aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEnji Cooper <ngie@FreeBSD.org>2023-03-01 04:21:31 +0000
committerEnji Cooper <ngie@FreeBSD.org>2023-03-06 20:41:29 +0000
commite4520c8bd1d300a7a338d0ed4af171a2d0e583ef (patch)
tree26fed32699a59a50cfbc90a2eb4dac39b498d9ae
parent3c320f4e5ee3d575d48eee7edddbafa059bce3c9 (diff)
openssl: Vendor import of OpenSSL-3.0.8vendor/openssl/3.0.8
Summary: Release notes can be found at https://www.openssl.org/news/openssl-3.0-notes.html . Obtained from: https://www.openssl.org/source/openssl-3.0.8.tar.gz Differential Revision: https://reviews.freebsd.org/D38835 Test Plan: ``` $ git status On branch vendor/openssl-3.0 nothing to commit, working tree clean $ (cd ..; fetch http://www.openssl.org/source/openssl-${OSSLVER}.tar.gz http://www.openssl.org/source/openssl-${OSSLVER}.tar.gz.asc) openssl-3.0.8.tar.gz 14 MB 4507 kBps 04s openssl-3.0.8.tar.gz.asc 833 B 10 MBps 00s $ set | egrep '(XLIST|OSSLVER)=' OSSLVER=3.0.8 XLIST=FREEBSD-Xlist $ gpg --list-keys /home/ngie/.gnupg/pubring.kbx ----------------------------- pub rsa4096 2014-10-04 [SC] 7953AC1FBC3DC8B3B292393ED5E9E43F7DF9EE8C uid [ unknown] Richard Levitte <richard@levitte.org> uid [ unknown] Richard Levitte <levitte@lp.se> uid [ unknown] Richard Levitte <levitte@openssl.org> sub rsa4096 2014-10-04 [E] $ gpg --verify openssl-${OSSLVER}.tar.gz.asc openssl-${OSSLVER}.tar.gz gpg: Signature made Tue Feb 7 05:43:55 2023 PST gpg: using RSA key 7953AC1FBC3DC8B3B292393ED5E9E43F7DF9EE8C gpg: Good signature from "Richard Levitte <richard@levitte.org>" [unknown] gpg: aka "Richard Levitte <levitte@lp.se>" [unknown] gpg: aka "Richard Levitte <levitte@openssl.org>" [unknown] gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: 7953 AC1F BC3D C8B3 B292 393E D5E9 E43F 7DF9 EE8C $ (cd vendor.checkout/; git status; find . -type f -or -type l | cut -c 3- | sort > ../old) On branch vendor/openssl-3.0 nothing to commit, working tree clean $ tar -x -X $XLIST -f ../openssl-${OSSLVER}.tar.gz -C .. $ rsync --exclude FREEBSD.* --delete -avzz ../openssl-${OSSLVER}/* . $ cat .git gitdir: /home/ngie/git/freebsd-src/.git/worktrees/vendor.checkout $ diff -arq ../openssl-3.0.8 . Only in .: .git Only in .: FREEBSD-Xlist Only in .: FREEBSD-upgrade $ git status FREEBSD* On branch vendor/openssl-3.0 nothing to commit, working tree clean $ ``` Reviewers: emaste, jkim Subscribers: imp, andrew, dab Differential Revision: https://reviews.freebsd.org/D38835
-rw-r--r--ACKNOWLEDGEMENTS2
-rw-r--r--ACKNOWLEDGEMENTS.md6
-rw-r--r--AUTHORS42
-rw-r--r--AUTHORS.md51
-rw-r--r--CHANGES13899
-rw-r--r--CHANGES.md19753
-rw-r--r--CONTRIBUTING72
-rw-r--r--CONTRIBUTING.md94
-rwxr-xr-xConfigure2205
-rw-r--r--FAQ2
-rw-r--r--FAQ.md6
-rw-r--r--HACKING.md33
-rw-r--r--INSTALL1289
-rw-r--r--INSTALL.md1817
-rw-r--r--LICENSE125
-rw-r--r--LICENSE.txt177
-rw-r--r--NEWS1045
-rw-r--r--NEWS.md1586
-rw-r--r--NOTES-ANDROID.md90
-rw-r--r--NOTES-DJGPP.md46
-rw-r--r--NOTES-NONSTOP.md245
-rw-r--r--NOTES-PERL.md127
-rw-r--r--NOTES-UNIX.md115
-rw-r--r--NOTES-VALGRIND.md72
-rw-r--r--NOTES-VMS.md115
-rw-r--r--NOTES-WINDOWS.md265
-rw-r--r--NOTES.PERL119
-rw-r--r--NOTES.UNIX117
-rw-r--r--README93
-rw-r--r--README-ENGINES.md316
-rw-r--r--README-FIPS.md86
-rw-r--r--README-PROVIDERS.md145
-rw-r--r--README.ENGINE287
-rw-r--r--README.FIPS1
-rw-r--r--README.md224
-rw-r--r--SUPPORT.md93
-rw-r--r--VERSION.dat7
-rw-r--r--apps/CA.pl.in134
-rw-r--r--apps/app_rand.c93
-rw-r--r--apps/apps.c2796
-rw-r--r--apps/apps.h635
-rw-r--r--apps/asn1pars.c355
-rw-r--r--apps/asn1parse.c362
-rw-r--r--apps/bf_prefix.c177
-rw-r--r--apps/build.info147
-rw-r--r--[-rwxr-xr-x]apps/ca.c502
-rw-r--r--apps/ciphers.c66
-rw-r--r--apps/cmp.c3023
-rw-r--r--apps/cms.c685
-rw-r--r--apps/crl.c134
-rw-r--r--apps/crl2p7.c219
-rw-r--r--apps/crl2pkcs7.c233
-rw-r--r--apps/dgst.c302
-rw-r--r--apps/dh1024.pem10
-rw-r--r--apps/dh2048.pem14
-rw-r--r--apps/dh4096.pem19
-rw-r--r--apps/dhparam.c432
-rw-r--r--apps/dsa.c219
-rw-r--r--apps/dsaparam.c211
-rw-r--r--apps/ec.c266
-rw-r--r--apps/ecparam.c476
-rw-r--r--apps/enc.c228
-rw-r--r--apps/engine.c27
-rw-r--r--apps/errstr.c23
-rw-r--r--apps/fipsinstall.c590
-rw-r--r--apps/gendsa.c103
-rw-r--r--apps/genpkey.c206
-rw-r--r--apps/genrsa.c173
-rw-r--r--apps/include/__DECC_INCLUDE_EPILOGUE.H22
-rw-r--r--apps/include/__DECC_INCLUDE_PROLOGUE.H26
-rw-r--r--apps/include/app_libctx.h20
-rw-r--r--apps/include/app_params.h14
-rw-r--r--apps/include/apps.h348
-rw-r--r--apps/include/apps_ui.h29
-rw-r--r--apps/include/cmp_mock_srv.h35
-rw-r--r--apps/include/ec_common.h23
-rw-r--r--apps/include/engine_loader.h21
-rw-r--r--apps/include/fmt.h45
-rw-r--r--apps/include/function.h44
-rw-r--r--apps/include/http_server.h125
-rw-r--r--apps/include/names.h17
-rw-r--r--apps/include/opt.h400
-rw-r--r--apps/include/platform.h32
-rw-r--r--apps/include/s_apps.h108
-rw-r--r--apps/include/vms_term_sock.h31
-rw-r--r--apps/info.c104
-rw-r--r--apps/insta.ca.crtbin0 -> 916 bytes
-rw-r--r--apps/kdf.c211
-rw-r--r--apps/lib/app_libctx.c48
-rw-r--r--apps/lib/app_params.c132
-rw-r--r--apps/lib/app_provider.c92
-rw-r--r--apps/lib/app_rand.c124
-rw-r--r--apps/lib/app_x509.c137
-rw-r--r--apps/lib/apps.c3389
-rw-r--r--apps/lib/apps_ui.c223
-rw-r--r--apps/lib/build.info23
-rw-r--r--apps/lib/cmp_mock_srv.c450
-rw-r--r--apps/lib/columns.c27
-rw-r--r--apps/lib/engine.c193
-rw-r--r--apps/lib/engine_loader.c203
-rw-r--r--apps/lib/fmt.c15
-rw-r--r--apps/lib/http_server.c533
-rw-r--r--apps/lib/names.c45
-rw-r--r--apps/lib/opt.c1198
-rw-r--r--apps/lib/s_cb.c1569
-rw-r--r--apps/lib/s_socket.c455
-rw-r--r--apps/lib/tlssrp_depr.c231
-rw-r--r--apps/lib/vms_decc_argv.c72
-rw-r--r--apps/lib/vms_term_sock.c591
-rw-r--r--apps/lib/win32_init.c307
-rw-r--r--apps/list.c1706
-rw-r--r--apps/mac.c237
-rw-r--r--apps/nseq.c30
-rw-r--r--apps/ocsp.c915
-rw-r--r--apps/openssl.c766
-rw-r--r--apps/openssl.cnf154
-rw-r--r--apps/opt.c898
-rw-r--r--apps/passwd.c80
-rw-r--r--apps/pkcs12.c493
-rw-r--r--apps/pkcs7.c46
-rw-r--r--apps/pkcs8.c82
-rw-r--r--apps/pkey.c195
-rw-r--r--apps/pkeyparam.c62
-rw-r--r--apps/pkeyutl.c439
-rw-r--r--apps/prime.c43
-rw-r--r--apps/progs.pl285
-rw-r--r--apps/rand.c42
-rw-r--r--apps/rehash.c61
-rw-r--r--apps/req.c1003
-rw-r--r--apps/rsa.c322
-rw-r--r--apps/rsautl.c126
-rw-r--r--apps/s_apps.h77
-rw-r--r--apps/s_cb.c1548
-rw-r--r--apps/s_client.c812
-rw-r--r--apps/s_server.c923
-rw-r--r--apps/s_socket.c405
-rw-r--r--apps/s_time.c142
-rw-r--r--apps/sess_id.c19
-rw-r--r--apps/smime.c186
-rw-r--r--apps/speed.c3476
-rw-r--r--apps/spkac.c59
-rw-r--r--apps/srp.c55
-rw-r--r--apps/storeutl.c113
-rw-r--r--apps/testdsa.h51
-rw-r--r--apps/testrsa.h2
-rw-r--r--apps/timeouts.h2
-rw-r--r--apps/ts.c195
-rw-r--r--apps/tsget.in56
-rw-r--r--apps/verify.c179
-rw-r--r--apps/version.c137
-rw-r--r--apps/x509.c1179
-rw-r--r--appveyor.yml54
-rw-r--r--build.info155
-rwxr-xr-xconfig944
-rw-r--r--configdata.pm.in487
-rw-r--r--crypto/LPdir_unix.c7
-rw-r--r--crypto/README-sparse_array.md156
-rw-r--r--crypto/aes/aes_cbc.c11
-rw-r--r--crypto/aes/aes_cfb.c10
-rw-r--r--crypto/aes/aes_core.c304
-rw-r--r--crypto/aes/aes_ecb.c10
-rw-r--r--crypto/aes/aes_ige.c21
-rw-r--r--crypto/aes/aes_local.h6
-rw-r--r--crypto/aes/aes_misc.c12
-rw-r--r--crypto/aes/aes_ofb.c10
-rw-r--r--crypto/aes/aes_wrap.c10
-rw-r--r--crypto/aes/aes_x86core.c2
-rwxr-xr-xcrypto/aes/asm/aes-586.pl2998
-rw-r--r--crypto/aes/asm/aes-armv4.pl17
-rw-r--r--crypto/aes/asm/aes-c64xplus.pl5
-rw-r--r--crypto/aes/asm/aes-ia64.S4
-rw-r--r--crypto/aes/asm/aes-mips.pl150
-rw-r--r--crypto/aes/asm/aes-parisc.pl11
-rw-r--r--crypto/aes/asm/aes-ppc.pl10
-rw-r--r--crypto/aes/asm/aes-s390x.pl10
-rwxr-xr-xcrypto/aes/asm/aes-sparcv9.pl14
-rwxr-xr-xcrypto/aes/asm/aes-x86_64.pl2927
-rw-r--r--crypto/aes/asm/aesfx-sparcv9.pl12
-rw-r--r--crypto/aes/asm/aesni-mb-x86_64.pl96
-rw-r--r--crypto/aes/asm/aesni-sha1-x86_64.pl12
-rw-r--r--crypto/aes/asm/aesni-sha256-x86_64.pl12
-rw-r--r--crypto/aes/asm/aesni-x86.pl6
-rw-r--r--crypto/aes/asm/aesni-x86_64.pl23
-rwxr-xr-xcrypto/aes/asm/aesp8-ppc.pl10
-rw-r--r--crypto/aes/asm/aest4-sparcv9.pl12
-rwxr-xr-xcrypto/aes/asm/aesv8-armx.pl2683
-rw-r--r--crypto/aes/asm/bsaes-armv7.pl55
-rw-r--r--crypto/aes/asm/bsaes-x86_64.pl3243
-rwxr-xr-xcrypto/aes/asm/vpaes-armv8.pl288
-rw-r--r--crypto/aes/asm/vpaes-ppc.pl10
-rw-r--r--crypto/aes/asm/vpaes-x86.pl6
-rw-r--r--crypto/aes/asm/vpaes-x86_64.pl17
-rw-r--r--crypto/aes/build.info152
-rw-r--r--crypto/aria/aria.c34
-rwxr-xr-xcrypto/arm64cpuid.pl18
-rw-r--r--crypto/arm_arch.h49
-rw-r--r--crypto/armcap.c51
-rw-r--r--crypto/armv4cpuid.pl14
-rw-r--r--crypto/asn1/a_bitstr.c14
-rw-r--r--crypto/asn1/a_d2i_fp.c73
-rw-r--r--crypto/asn1/a_digest.c53
-rw-r--r--crypto/asn1/a_dup.c47
-rw-r--r--crypto/asn1/a_gentm.c16
-rw-r--r--crypto/asn1/a_i2d_fp.c38
-rw-r--r--crypto/asn1/a_int.c71
-rw-r--r--crypto/asn1/a_mbstr.c49
-rw-r--r--crypto/asn1/a_object.c51
-rw-r--r--crypto/asn1/a_octet.c2
-rw-r--r--crypto/asn1/a_print.c2
-rw-r--r--crypto/asn1/a_sign.c156
-rw-r--r--crypto/asn1/a_strex.c10
-rw-r--r--crypto/asn1/a_strnid.c13
-rw-r--r--crypto/asn1/a_time.c85
-rw-r--r--crypto/asn1/a_type.c6
-rw-r--r--crypto/asn1/a_utctm.c19
-rw-r--r--crypto/asn1/a_utf8.c77
-rw-r--r--crypto/asn1/a_verify.c160
-rw-r--r--crypto/asn1/ameth_lib.c86
-rw-r--r--crypto/asn1/asn1_err.c154
-rw-r--r--crypto/asn1/asn1_gen.c75
-rw-r--r--crypto/asn1/asn1_item_list.c7
-rw-r--r--crypto/asn1/asn1_item_list.h13
-rw-r--r--crypto/asn1/asn1_lib.c125
-rw-r--r--crypto/asn1/asn1_local.h77
-rw-r--r--crypto/asn1/asn1_par.c380
-rw-r--r--crypto/asn1/asn1_parse.c387
-rw-r--r--crypto/asn1/asn_mime.c187
-rw-r--r--crypto/asn1/asn_moid.c10
-rw-r--r--crypto/asn1/asn_mstbl.c18
-rw-r--r--crypto/asn1/asn_pack.c12
-rw-r--r--crypto/asn1/bio_asn1.c12
-rw-r--r--crypto/asn1/bio_ndef.c22
-rw-r--r--crypto/asn1/build.info17
-rw-r--r--crypto/asn1/charmap.h4
-rw-r--r--crypto/asn1/charmap.pl7
-rw-r--r--crypto/asn1/d2i_param.c65
-rw-r--r--crypto/asn1/d2i_pr.c203
-rw-r--r--crypto/asn1/d2i_pu.c49
-rw-r--r--crypto/asn1/evp_asn1.c122
-rw-r--r--crypto/asn1/f_int.c13
-rw-r--r--crypto/asn1/f_string.c13
-rw-r--r--crypto/asn1/i2d_evp.c149
-rw-r--r--crypto/asn1/i2d_pr.c33
-rw-r--r--crypto/asn1/i2d_pu.c38
-rw-r--r--crypto/asn1/n_pkey.c48
-rw-r--r--crypto/asn1/nsseq.c2
-rw-r--r--crypto/asn1/p5_pbe.c43
-rw-r--r--crypto/asn1/p5_pbev2.c71
-rw-r--r--crypto/asn1/p5_scrypt.c74
-rw-r--r--crypto/asn1/p8_pkey.c15
-rw-r--r--crypto/asn1/standard_methods.h50
-rw-r--r--crypto/asn1/t_bitst.c2
-rw-r--r--crypto/asn1/t_pkey.c2
-rw-r--r--crypto/asn1/t_spki.c4
-rw-r--r--crypto/asn1/tasn_dec.c341
-rw-r--r--crypto/asn1/tasn_enc.c165
-rw-r--r--crypto/asn1/tasn_fre.c54
-rw-r--r--crypto/asn1/tasn_new.c97
-rw-r--r--crypto/asn1/tasn_prn.c58
-rw-r--r--crypto/asn1/tasn_scn.c6
-rw-r--r--crypto/asn1/tasn_typ.c6
-rw-r--r--crypto/asn1/tasn_utl.c123
-rw-r--r--crypto/asn1/tbl_standard.h7
-rw-r--r--crypto/asn1/x_algor.c80
-rw-r--r--crypto/asn1/x_bignum.c12
-rw-r--r--crypto/asn1/x_info.c6
-rw-r--r--crypto/asn1/x_int64.c48
-rw-r--r--crypto/asn1/x_long.c25
-rw-r--r--crypto/asn1/x_pkey.c6
-rw-r--r--crypto/asn1/x_sig.c2
-rw-r--r--crypto/asn1/x_spki.c2
-rw-r--r--crypto/asn1/x_val.c2
-rw-r--r--crypto/asn1_dsa.c252
-rw-r--r--crypto/async/arch/async_null.c2
-rw-r--r--crypto/async/arch/async_null.h2
-rw-r--r--crypto/async/arch/async_posix.c6
-rw-r--r--crypto/async/arch/async_posix.h37
-rw-r--r--crypto/async/arch/async_win.h14
-rw-r--r--crypto/async/async.c78
-rw-r--r--crypto/async/async_err.c24
-rw-r--r--crypto/async/async_local.h8
-rw-r--r--crypto/async/async_wait.c41
-rw-r--r--crypto/bf/asm/bf-586.pl5
-rw-r--r--crypto/bf/bf_cfb64.c10
-rw-r--r--crypto/bf/bf_ecb.c10
-rw-r--r--crypto/bf/bf_enc.c10
-rw-r--r--crypto/bf/bf_local.h2
-rw-r--r--crypto/bf/bf_ofb64.c10
-rw-r--r--crypto/bf/bf_pi.h2
-rw-r--r--crypto/bf/bf_skey.c10
-rw-r--r--crypto/bf/build.info28
-rw-r--r--crypto/bio/b_addr.c928
-rw-r--r--crypto/bio/b_dump.c148
-rw-r--r--crypto/bio/b_print.c954
-rw-r--r--crypto/bio/b_sock.c369
-rw-r--r--crypto/bio/b_sock2.c318
-rw-r--r--crypto/bio/bf_buff.c31
-rw-r--r--crypto/bio/bf_lbuf.c27
-rw-r--r--crypto/bio/bf_nbio.c17
-rw-r--r--crypto/bio/bf_null.c15
-rw-r--r--crypto/bio/bf_prefix.c207
-rw-r--r--crypto/bio/bf_readbuff.c288
-rw-r--r--crypto/bio/bio_addr.c939
-rw-r--r--crypto/bio/bio_cb.c74
-rw-r--r--crypto/bio/bio_dump.c153
-rw-r--r--crypto/bio/bio_err.c75
-rw-r--r--crypto/bio/bio_lib.c370
-rw-r--r--crypto/bio/bio_local.h13
-rw-r--r--crypto/bio/bio_meth.c8
-rw-r--r--crypto/bio/bio_print.c960
-rw-r--r--crypto/bio/bio_sock.c415
-rw-r--r--crypto/bio/bio_sock2.c340
-rw-r--r--crypto/bio/bss_acpt.c49
-rw-r--r--crypto/bio/bss_bio.c28
-rw-r--r--crypto/bio/bss_conn.c120
-rw-r--r--crypto/bio/bss_core.c194
-rw-r--r--crypto/bio/bss_dgram.c155
-rw-r--r--crypto/bio/bss_fd.c12
-rw-r--r--crypto/bio/bss_file.c90
-rw-r--r--crypto/bio/bss_log.c9
-rw-r--r--crypto/bio/bss_mem.c45
-rw-r--r--crypto/bio/bss_null.c6
-rw-r--r--crypto/bio/bss_sock.c65
-rw-r--r--crypto/bio/build.info20
-rw-r--r--crypto/bio/ossl_core_bio.c124
-rw-r--r--crypto/blake2/blake2_impl.h129
-rw-r--r--crypto/blake2/blake2_local.h90
-rw-r--r--crypto/blake2/blake2b.c269
-rw-r--r--crypto/blake2/blake2s.c263
-rw-r--r--crypto/blake2/build.info3
-rw-r--r--crypto/blake2/m_blake2b.c59
-rw-r--r--crypto/blake2/m_blake2s.c59
-rw-r--r--crypto/bn/README.pod2
-rw-r--r--crypto/bn/asm/armv4-gf2m.pl27
-rw-r--r--crypto/bn/asm/armv4-mont.pl31
-rwxr-xr-xcrypto/bn/asm/armv8-mont.pl410
-rw-r--r--crypto/bn/asm/bn-586.pl5
-rw-r--r--crypto/bn/asm/bn-c64xplus.asm5
-rw-r--r--crypto/bn/asm/c64xplus-gf2m.pl5
-rw-r--r--crypto/bn/asm/co-586.pl5
-rw-r--r--crypto/bn/asm/ia64-mont.pl5
-rw-r--r--crypto/bn/asm/ia64.S7
-rw-r--r--crypto/bn/asm/mips-mont.pl13
-rw-r--r--crypto/bn/asm/mips.pl14
-rw-r--r--crypto/bn/asm/parisc-mont.pl10
-rw-r--r--crypto/bn/asm/ppc-mont.pl10
-rw-r--r--crypto/bn/asm/ppc.pl10
-rwxr-xr-xcrypto/bn/asm/ppc64-mont-fixed.pl0
-rw-r--r--crypto/bn/asm/ppc64-mont.pl10
-rwxr-xr-xcrypto/bn/asm/rsaz-avx2.pl12
-rw-r--r--crypto/bn/asm/rsaz-avx512.pl754
-rwxr-xr-xcrypto/bn/asm/rsaz-x86_64.pl12
-rw-r--r--crypto/bn/asm/s390x-gf2m.pl10
-rw-r--r--crypto/bn/asm/s390x-mont.pl10
-rw-r--r--crypto/bn/asm/s390x.S2
-rwxr-xr-xcrypto/bn/asm/sparct4-mont.pl12
-rw-r--r--crypto/bn/asm/sparcv8.S2
-rw-r--r--crypto/bn/asm/sparcv8plus.S4
-rw-r--r--crypto/bn/asm/sparcv9-gf2m.pl12
-rw-r--r--crypto/bn/asm/sparcv9-mont.pl12
-rwxr-xr-xcrypto/bn/asm/sparcv9a-mont.pl15
-rw-r--r--crypto/bn/asm/via-mont.pl5
-rw-r--r--crypto/bn/asm/vis3-mont.pl12
-rw-r--r--crypto/bn/asm/x86-gf2m.pl5
-rwxr-xr-xcrypto/bn/asm/x86-mont.pl5
-rw-r--r--crypto/bn/asm/x86_64-gcc.c5
-rw-r--r--crypto/bn/asm/x86_64-gf2m.pl12
-rwxr-xr-xcrypto/bn/asm/x86_64-mont.pl12
-rwxr-xr-xcrypto/bn/asm/x86_64-mont5.pl12
-rw-r--r--crypto/bn/bn_add.c6
-rw-r--r--crypto/bn/bn_asm.c2
-rw-r--r--crypto/bn/bn_blind.c16
-rw-r--r--crypto/bn/bn_const.c424
-rw-r--r--crypto/bn/bn_conv.c291
-rw-r--r--crypto/bn/bn_ctx.c133
-rw-r--r--crypto/bn/bn_depr.c21
-rw-r--r--crypto/bn/bn_dh.c1402
-rw-r--r--crypto/bn/bn_div.c10
-rw-r--r--crypto/bn/bn_err.c78
-rw-r--r--crypto/bn/bn_exp.c108
-rw-r--r--crypto/bn/bn_exp2.c4
-rw-r--r--crypto/bn/bn_gcd.c8
-rw-r--r--crypto/bn/bn_gf2m.c89
-rw-r--r--crypto/bn/bn_intern.c22
-rw-r--r--crypto/bn/bn_kron.c2
-rw-r--r--crypto/bn/bn_lib.c38
-rw-r--r--crypto/bn/bn_local.h36
-rw-r--r--crypto/bn/bn_mod.c16
-rw-r--r--crypto/bn/bn_mont.c15
-rw-r--r--crypto/bn/bn_mpi.c6
-rw-r--r--crypto/bn/bn_mul.c2
-rw-r--r--crypto/bn/bn_nist.c62
-rw-r--r--crypto/bn/bn_ppc.c38
-rw-r--r--crypto/bn/bn_prime.c445
-rw-r--r--crypto/bn/bn_prime.h4
-rw-r--r--crypto/bn/bn_prime.pl7
-rw-r--r--crypto/bn/bn_print.c281
-rw-r--r--crypto/bn/bn_rand.c121
-rw-r--r--crypto/bn/bn_recp.c8
-rw-r--r--crypto/bn/bn_rsa_fips186_4.c367
-rw-r--r--crypto/bn/bn_shift.c8
-rw-r--r--crypto/bn/bn_sparc.c77
-rw-r--r--crypto/bn/bn_sqr.c2
-rw-r--r--crypto/bn/bn_sqrt.c21
-rw-r--r--crypto/bn/bn_srp.c24
-rw-r--r--crypto/bn/bn_word.c2
-rw-r--r--crypto/bn/bn_x931p.c22
-rw-r--r--crypto/bn/build.info196
-rw-r--r--crypto/bn/rsa_sup_mul.c66
-rw-r--r--crypto/bn/rsaz_exp.c2
-rw-r--r--crypto/bn/rsaz_exp.h21
-rw-r--r--crypto/bn/rsaz_exp_x2.c575
-rw-r--r--crypto/bsearch.c44
-rw-r--r--crypto/buffer/buf_err.c18
-rw-r--r--crypto/buffer/buffer.c14
-rw-r--r--crypto/buffer/build.info1
-rw-r--r--crypto/build.info145
-rw-r--r--crypto/c64xpluscpuid.pl2
-rw-r--r--crypto/camellia/asm/cmll-x86.pl5
-rw-r--r--crypto/camellia/asm/cmll-x86_64.pl13
-rw-r--r--crypto/camellia/asm/cmllt4-sparcv9.pl12
-rw-r--r--crypto/camellia/build.info32
-rw-r--r--crypto/camellia/camellia.c16
-rw-r--r--crypto/camellia/cmll_cbc.c10
-rw-r--r--crypto/camellia/cmll_cfb.c10
-rw-r--r--crypto/camellia/cmll_ctr.c10
-rw-r--r--crypto/camellia/cmll_ecb.c10
-rw-r--r--crypto/camellia/cmll_local.h2
-rw-r--r--crypto/camellia/cmll_misc.c10
-rw-r--r--crypto/camellia/cmll_ofb.c10
-rw-r--r--crypto/cast/asm/cast-586.pl5
-rw-r--r--crypto/cast/build.info29
-rw-r--r--crypto/cast/c_cfb64.c10
-rw-r--r--crypto/cast/c_ecb.c10
-rw-r--r--crypto/cast/c_enc.c10
-rw-r--r--crypto/cast/c_ofb64.c10
-rw-r--r--crypto/cast/c_skey.c10
-rw-r--r--crypto/cast/cast_local.h2
-rw-r--r--crypto/cast/cast_s.h2
-rwxr-xr-xcrypto/chacha/asm/chacha-armv4.pl25
-rwxr-xr-xcrypto/chacha/asm/chacha-armv8.pl590
-rwxr-xr-xcrypto/chacha/asm/chacha-c64xplus.pl5
-rw-r--r--crypto/chacha/asm/chacha-ia64.pl291
-rwxr-xr-xcrypto/chacha/asm/chacha-ppc.pl10
-rwxr-xr-xcrypto/chacha/asm/chacha-s390x.pl1258
-rwxr-xr-xcrypto/chacha/asm/chacha-x86.pl5
-rwxr-xr-xcrypto/chacha/asm/chacha-x86_64.pl12
-rw-r--r--crypto/chacha/build.info50
-rw-r--r--crypto/chacha/chacha_enc.c12
-rw-r--r--crypto/chacha/chacha_ppc.c35
-rw-r--r--crypto/cmac/build.info6
-rw-r--r--crypto/cmac/cm_ameth.c51
-rw-r--r--crypto/cmac/cm_pmeth.c161
-rw-r--r--crypto/cmac/cmac.c44
-rw-r--r--crypto/cmp/build.info4
-rw-r--r--crypto/cmp/cmp_asn.c459
-rw-r--r--crypto/cmp/cmp_client.c890
-rw-r--r--crypto/cmp/cmp_ctx.c1157
-rw-r--r--crypto/cmp/cmp_err.c178
-rw-r--r--crypto/cmp/cmp_hdr.c369
-rw-r--r--crypto/cmp/cmp_http.c106
-rw-r--r--crypto/cmp/cmp_local.h930
-rw-r--r--crypto/cmp/cmp_msg.c1170
-rw-r--r--crypto/cmp/cmp_protect.c332
-rw-r--r--crypto/cmp/cmp_server.c644
-rw-r--r--crypto/cmp/cmp_status.c314
-rw-r--r--crypto/cmp/cmp_util.c286
-rw-r--r--crypto/cmp/cmp_vfy.c856
-rw-r--r--crypto/cms/build.info2
-rw-r--r--crypto/cms/cms_asn1.c16
-rw-r--r--crypto/cms/cms_att.c11
-rw-r--r--crypto/cms/cms_cd.c23
-rw-r--r--crypto/cms/cms_dd.c33
-rw-r--r--crypto/cms/cms_dh.c343
-rw-r--r--crypto/cms/cms_ec.c413
-rw-r--r--crypto/cms/cms_enc.c138
-rw-r--r--crypto/cms/cms_env.c742
-rw-r--r--crypto/cms/cms_err.c181
-rw-r--r--crypto/cms/cms_ess.c188
-rw-r--r--crypto/cms/cms_io.c55
-rw-r--r--crypto/cms/cms_kari.c213
-rw-r--r--crypto/cms/cms_lib.c301
-rw-r--r--crypto/cms/cms_local.h173
-rw-r--r--crypto/cms/cms_pwri.c117
-rw-r--r--crypto/cms/cms_rsa.c264
-rw-r--r--crypto/cms/cms_sd.c381
-rw-r--r--crypto/cms/cms_smime.c396
-rw-r--r--crypto/comp/c_zlib.c131
-rw-r--r--crypto/comp/comp_err.c31
-rw-r--r--crypto/comp/comp_lib.c6
-rw-r--r--crypto/comp/comp_local.h2
-rw-r--r--crypto/conf/conf_api.c80
-rw-r--r--crypto/conf/conf_def.c222
-rw-r--r--crypto/conf/conf_def.h12
-rw-r--r--crypto/conf/conf_err.c45
-rw-r--r--crypto/conf/conf_lib.c94
-rw-r--r--crypto/conf/conf_local.h8
-rw-r--r--crypto/conf/conf_mall.c13
-rw-r--r--crypto/conf/conf_mod.c280
-rw-r--r--crypto/conf/conf_sap.c25
-rw-r--r--crypto/conf/conf_ssl.c31
-rw-r--r--crypto/conf/keysets.pl13
-rw-r--r--crypto/context.c510
-rw-r--r--crypto/core_algorithm.c199
-rw-r--r--crypto/core_fetch.c171
-rw-r--r--crypto/core_namemap.c531
-rw-r--r--crypto/cpt_err.c89
-rw-r--r--crypto/cpuid.c214
-rw-r--r--crypto/crmf/build.info2
-rw-r--r--crypto/crmf/crmf_asn.c235
-rw-r--r--crypto/crmf/crmf_err.c74
-rw-r--r--crypto/crmf/crmf_lib.c715
-rw-r--r--crypto/crmf/crmf_local.h385
-rw-r--r--crypto/crmf/crmf_pbm.c233
-rw-r--r--crypto/cryptlib.c213
-rw-r--r--crypto/ct/ct_b64.c38
-rw-r--r--crypto/ct/ct_err.c61
-rw-r--r--crypto/ct/ct_local.h19
-rw-r--r--crypto/ct/ct_log.c96
-rw-r--r--crypto/ct/ct_oct.c48
-rw-r--r--crypto/ct/ct_policy.c25
-rw-r--r--crypto/ct/ct_prn.c4
-rw-r--r--crypto/ct/ct_sct.c26
-rw-r--r--crypto/ct/ct_sct_ctx.c43
-rw-r--r--crypto/ct/ct_vfy.c17
-rw-r--r--crypto/ct/ct_x509v3.c6
-rw-r--r--crypto/ctype.c51
-rw-r--r--crypto/cversion.c44
-rw-r--r--crypto/der_writer.c199
-rw-r--r--crypto/des/asm/crypt586.pl5
-rw-r--r--crypto/des/asm/des-586.pl5
-rw-r--r--crypto/des/asm/des_enc.m46
-rw-r--r--crypto/des/asm/desboth.pl2
-rw-r--r--crypto/des/asm/dest4-sparcv9.pl12
-rw-r--r--crypto/des/build.info56
-rw-r--r--crypto/des/cbc_cksm.c10
-rw-r--r--crypto/des/cbc_enc.c10
-rw-r--r--crypto/des/cfb64ede.c10
-rw-r--r--crypto/des/cfb64enc.c10
-rw-r--r--crypto/des/cfb_enc.c10
-rw-r--r--crypto/des/des_enc.c10
-rw-r--r--crypto/des/des_local.h2
-rw-r--r--crypto/des/ecb3_enc.c10
-rw-r--r--crypto/des/ecb_enc.c10
-rw-r--r--crypto/des/fcrypt.c14
-rw-r--r--crypto/des/fcrypt_b.c10
-rw-r--r--crypto/des/ncbc_enc.c2
-rw-r--r--crypto/des/ofb64ede.c10
-rw-r--r--crypto/des/ofb64enc.c10
-rw-r--r--crypto/des/ofb_enc.c10
-rw-r--r--crypto/des/pcbc_enc.c10
-rw-r--r--crypto/des/qud_cksm.c11
-rw-r--r--crypto/des/rand_key.c10
-rw-r--r--crypto/des/set_key.c64
-rw-r--r--crypto/des/spr.h2
-rw-r--r--crypto/des/str2key.c10
-rw-r--r--crypto/des/xcbc_enc.c10
-rw-r--r--crypto/dh/build.info16
-rw-r--r--crypto/dh/dh1024.pem5
-rw-r--r--crypto/dh/dh192.pem3
-rw-r--r--crypto/dh/dh2048.pem16
-rw-r--r--crypto/dh/dh4096.pem14
-rw-r--r--crypto/dh/dh512.pem4
-rw-r--r--crypto/dh/dh_ameth.c715
-rw-r--r--crypto/dh/dh_asn1.c95
-rw-r--r--crypto/dh/dh_backend.c250
-rw-r--r--crypto/dh/dh_check.c233
-rw-r--r--crypto/dh/dh_depr.c22
-rw-r--r--crypto/dh/dh_err.c58
-rw-r--r--crypto/dh/dh_gen.c136
-rw-r--r--crypto/dh/dh_group_params.c99
-rw-r--r--crypto/dh/dh_kdf.c181
-rw-r--r--crypto/dh/dh_key.c398
-rw-r--r--crypto/dh/dh_lib.c151
-rw-r--r--crypto/dh/dh_local.h27
-rw-r--r--crypto/dh/dh_meth.c16
-rw-r--r--crypto/dh/dh_pmeth.c225
-rw-r--r--crypto/dh/dh_prn.c12
-rw-r--r--crypto/dh/dh_rfc5114.c18
-rw-r--r--crypto/dh/dh_rfc7919.c74
-rw-r--r--crypto/dllmain.c2
-rw-r--r--crypto/dsa/build.info13
-rw-r--r--crypto/dsa/dsa_ameth.c342
-rw-r--r--crypto/dsa/dsa_asn1.c127
-rw-r--r--crypto/dsa/dsa_backend.c192
-rw-r--r--crypto/dsa/dsa_check.c95
-rw-r--r--crypto/dsa/dsa_depr.c31
-rw-r--r--crypto/dsa/dsa_err.c54
-rw-r--r--crypto/dsa/dsa_gen.c629
-rw-r--r--crypto/dsa/dsa_key.c150
-rw-r--r--crypto/dsa/dsa_lib.c356
-rw-r--r--crypto/dsa/dsa_local.h27
-rw-r--r--crypto/dsa/dsa_meth.c20
-rw-r--r--crypto/dsa/dsa_ossl.c134
-rw-r--r--crypto/dsa/dsa_pmeth.c94
-rw-r--r--crypto/dsa/dsa_prn.c12
-rw-r--r--crypto/dsa/dsa_sign.c193
-rw-r--r--crypto/dsa/dsa_vrf.c10
-rw-r--r--crypto/dso/dso_dl.c46
-rw-r--r--crypto/dso/dso_dlfcn.c38
-rw-r--r--crypto/dso/dso_err.c52
-rw-r--r--crypto/dso/dso_lib.c84
-rw-r--r--crypto/dso/dso_local.h2
-rw-r--r--crypto/dso/dso_openssl.c4
-rw-r--r--crypto/ebcdic.c2
-rwxr-xr-xcrypto/ec/asm/ecp_nistp521-ppc64.pl435
-rwxr-xr-xcrypto/ec/asm/ecp_nistz256-armv4.pl18
-rw-r--r--crypto/ec/asm/ecp_nistz256-armv8.pl19
-rwxr-xr-xcrypto/ec/asm/ecp_nistz256-ppc64.pl13
-rwxr-xr-xcrypto/ec/asm/ecp_nistz256-sparcv9.pl12
-rwxr-xr-xcrypto/ec/asm/ecp_nistz256-x86.pl5
-rwxr-xr-xcrypto/ec/asm/ecp_nistz256-x86_64.pl14
-rwxr-xr-xcrypto/ec/asm/x25519-ppc64.pl11
-rwxr-xr-xcrypto/ec/asm/x25519-x86_64.pl12
-rw-r--r--crypto/ec/build.info129
-rw-r--r--crypto/ec/curve25519.c129
-rw-r--r--crypto/ec/curve448/arch_32/arch_intrinsics.h2
-rw-r--r--crypto/ec/curve448/arch_32/f_impl.c95
-rw-r--r--crypto/ec/curve448/arch_32/f_impl.h2
-rw-r--r--crypto/ec/curve448/arch_32/f_impl32.c105
-rw-r--r--crypto/ec/curve448/arch_64/arch_intrinsics.h27
-rw-r--r--crypto/ec/curve448/arch_64/f_impl.h58
-rw-r--r--crypto/ec/curve448/arch_64/f_impl64.c210
-rw-r--r--crypto/ec/curve448/curve448.c95
-rw-r--r--crypto/ec/curve448/curve448_local.h36
-rw-r--r--crypto/ec/curve448/curve448_tables.c8
-rw-r--r--crypto/ec/curve448/curve448utils.h10
-rw-r--r--crypto/ec/curve448/ed448.h92
-rw-r--r--crypto/ec/curve448/eddsa.c268
-rw-r--r--crypto/ec/curve448/f_generic.c6
-rw-r--r--crypto/ec/curve448/field.h13
-rw-r--r--crypto/ec/curve448/point_448.h71
-rw-r--r--crypto/ec/curve448/scalar.c51
-rw-r--r--crypto/ec/curve448/word.h15
-rw-r--r--crypto/ec/ec2_oct.c103
-rw-r--r--crypto/ec/ec2_smpl.c262
-rw-r--r--crypto/ec/ec_ameth.c775
-rw-r--r--crypto/ec/ec_asn1.c428
-rw-r--r--crypto/ec/ec_backend.c842
-rw-r--r--crypto/ec/ec_check.c62
-rw-r--r--crypto/ec/ec_curve.c300
-rw-r--r--crypto/ec/ec_cvt.c19
-rw-r--r--crypto/ec/ec_deprecated.c78
-rw-r--r--crypto/ec/ec_err.c316
-rw-r--r--crypto/ec/ec_key.c541
-rw-r--r--crypto/ec/ec_kmeth.c57
-rw-r--r--crypto/ec/ec_lib.c776
-rw-r--r--crypto/ec/ec_local.h562
-rw-r--r--crypto/ec/ec_mult.c144
-rw-r--r--crypto/ec/ec_oct.c54
-rw-r--r--crypto/ec/ec_pmeth.c115
-rw-r--r--crypto/ec/ec_print.c102
-rw-r--r--crypto/ec/ecdh_kdf.c92
-rw-r--r--crypto/ec/ecdh_ossl.c58
-rw-r--r--crypto/ec/ecdsa_ossl.c157
-rw-r--r--crypto/ec/ecdsa_sign.c16
-rw-r--r--crypto/ec/ecdsa_vrf.c12
-rw-r--r--crypto/ec/eck_prn.c59
-rw-r--r--crypto/ec/ecp_mont.c161
-rw-r--r--crypto/ec/ecp_nist.c120
-rw-r--r--crypto/ec/ecp_nistp224.c264
-rw-r--r--crypto/ec/ecp_nistp256.c290
-rw-r--r--crypto/ec/ecp_nistp521.c319
-rw-r--r--crypto/ec/ecp_nistputil.c33
-rw-r--r--crypto/ec/ecp_nistz256.c132
-rw-r--r--crypto/ec/ecp_nistz256_table.c2
-rw-r--r--crypto/ec/ecp_oct.c92
-rw-r--r--crypto/ec/ecp_ppc.c34
-rw-r--r--crypto/ec/ecp_s390x_nistp.c400
-rw-r--r--crypto/ec/ecp_smpl.c281
-rw-r--r--crypto/ec/ecx_backend.c260
-rw-r--r--crypto/ec/ecx_backend.h20
-rw-r--r--crypto/ec/ecx_key.c98
-rw-r--r--crypto/ec/ecx_meth.c951
-rw-r--r--crypto/ec/ecx_s390x.c217
-rw-r--r--crypto/encode_decode/build.info5
-rw-r--r--crypto/encode_decode/decoder_err.c36
-rw-r--r--crypto/encode_decode/decoder_lib.c999
-rw-r--r--crypto/encode_decode/decoder_meth.c701
-rw-r--r--crypto/encode_decode/decoder_pkey.c462
-rw-r--r--crypto/encode_decode/encoder_err.c36
-rw-r--r--crypto/encode_decode/encoder_lib.c674
-rw-r--r--crypto/encode_decode/encoder_local.h164
-rw-r--r--crypto/encode_decode/encoder_meth.c700
-rw-r--r--crypto/encode_decode/encoder_pkey.c379
-rw-r--r--crypto/engine/README211
-rw-r--r--crypto/engine/README.md210
-rw-r--r--crypto/engine/build.info3
-rw-r--r--crypto/engine/eng_all.c8
-rw-r--r--crypto/engine/eng_cnf.c47
-rw-r--r--crypto/engine/eng_ctrl.c55
-rw-r--r--crypto/engine/eng_devcrypto.c849
-rw-r--r--crypto/engine/eng_dyn.c76
-rw-r--r--crypto/engine/eng_err.c86
-rw-r--r--crypto/engine/eng_fat.c16
-rw-r--r--crypto/engine/eng_init.c30
-rw-r--r--crypto/engine/eng_lib.c16
-rw-r--r--crypto/engine/eng_list.c86
-rw-r--r--crypto/engine/eng_local.h53
-rw-r--r--crypto/engine/eng_openssl.c56
-rw-r--r--crypto/engine/eng_pkey.c66
-rw-r--r--crypto/engine/eng_rdrand.c22
-rw-r--r--crypto/engine/eng_table.c85
-rw-r--r--crypto/engine/tb_asnmth.c24
-rw-r--r--crypto/engine/tb_cipher.c12
-rw-r--r--crypto/engine/tb_dh.c10
-rw-r--r--crypto/engine/tb_digest.c12
-rw-r--r--crypto/engine/tb_dsa.c10
-rw-r--r--crypto/engine/tb_eckey.c10
-rw-r--r--crypto/engine/tb_pkmeth.c13
-rw-r--r--crypto/engine/tb_rand.c10
-rw-r--r--crypto/engine/tb_rsa.c10
-rw-r--r--crypto/err/README44
-rw-r--r--crypto/err/README.md55
-rw-r--r--crypto/err/build.info2
-rw-r--r--crypto/err/err.c577
-rw-r--r--crypto/err/err_all.c144
-rw-r--r--crypto/err/err_all_legacy.c106
-rw-r--r--crypto/err/err_blocks.c117
-rw-r--r--crypto/err/err_local.h94
-rw-r--r--crypto/err/err_prn.c165
-rw-r--r--crypto/err/openssl.txt2250
-rw-r--r--crypto/ess/build.info3
-rw-r--r--crypto/ess/ess_asn1.c58
-rw-r--r--crypto/ess/ess_err.c48
-rw-r--r--crypto/ess/ess_lib.c315
-rw-r--r--crypto/evp/asymcipher.c552
-rw-r--r--crypto/evp/bio_b64.c17
-rw-r--r--crypto/evp/bio_enc.c50
-rw-r--r--crypto/evp/bio_md.c23
-rw-r--r--crypto/evp/bio_ok.c55
-rw-r--r--crypto/evp/build.info72
-rw-r--r--crypto/evp/c_allc.c5
-rw-r--r--crypto/evp/c_alld.c2
-rw-r--r--crypto/evp/cmeth_lib.c64
-rw-r--r--crypto/evp/ctrl_params_translate.c2808
-rw-r--r--crypto/evp/dh_ctrl.c346
-rw-r--r--crypto/evp/dh_support.c63
-rw-r--r--crypto/evp/digest.c899
-rw-r--r--crypto/evp/dsa_ctrl.c132
-rw-r--r--crypto/evp/e_aes.c1312
-rw-r--r--crypto/evp/e_aes_cbc_hmac_sha1.c49
-rw-r--r--crypto/evp/e_aes_cbc_hmac_sha256.c49
-rw-r--r--crypto/evp/e_aria.c152
-rw-r--r--crypto/evp/e_bf.c17
-rw-r--r--crypto/evp/e_camellia.c171
-rw-r--r--crypto/evp/e_cast.c17
-rw-r--r--crypto/evp/e_chacha20_poly1305.c29
-rw-r--r--crypto/evp/e_des.c64
-rw-r--r--crypto/evp/e_des3.c107
-rw-r--r--crypto/evp/e_idea.c16
-rw-r--r--crypto/evp/e_null.c5
-rw-r--r--crypto/evp/e_old.c57
-rw-r--r--crypto/evp/e_rc2.c27
-rw-r--r--crypto/evp/e_rc4.c18
-rw-r--r--crypto/evp/e_rc4_hmac_md5.c25
-rw-r--r--crypto/evp/e_rc5.c22
-rw-r--r--crypto/evp/e_seed.c28
-rw-r--r--crypto/evp/e_sm4.c34
-rw-r--r--crypto/evp/e_xcbc_d.c20
-rw-r--r--crypto/evp/ec_ctrl.c300
-rw-r--r--crypto/evp/ec_support.c188
-rw-r--r--crypto/evp/encode.c8
-rw-r--r--crypto/evp/evp_cnf.c38
-rw-r--r--crypto/evp/evp_enc.c1230
-rw-r--r--crypto/evp/evp_err.c235
-rw-r--r--crypto/evp/evp_fetch.c690
-rw-r--r--crypto/evp/evp_key.c14
-rw-r--r--crypto/evp/evp_lib.c883
-rw-r--r--crypto/evp/evp_local.h316
-rw-r--r--crypto/evp/evp_pbe.c154
-rw-r--r--crypto/evp/evp_pkey.c147
-rw-r--r--crypto/evp/evp_rand.c682
-rw-r--r--crypto/evp/evp_utils.c81
-rw-r--r--crypto/evp/exchange.c597
-rw-r--r--crypto/evp/kdf_lib.c184
-rw-r--r--crypto/evp/kdf_meth.c232
-rw-r--r--crypto/evp/kem.c482
-rw-r--r--crypto/evp/keymgmt_lib.c589
-rw-r--r--crypto/evp/keymgmt_meth.c496
-rw-r--r--crypto/evp/legacy_blake2.c48
-rw-r--r--crypto/evp/legacy_md2.c34
-rw-r--r--crypto/evp/legacy_md4.c34
-rw-r--r--crypto/evp/legacy_md5.c34
-rw-r--r--crypto/evp/legacy_md5_sha1.c41
-rw-r--r--crypto/evp/legacy_mdc2.c35
-rw-r--r--crypto/evp/legacy_meth.h40
-rw-r--r--crypto/evp/legacy_ripemd.c35
-rw-r--r--crypto/evp/legacy_sha.c228
-rw-r--r--crypto/evp/legacy_wp.c35
-rw-r--r--crypto/evp/m_md2.c56
-rw-r--r--crypto/evp/m_md4.c55
-rw-r--r--crypto/evp/m_md5.c55
-rw-r--r--crypto/evp/m_md5_sha1.c142
-rw-r--r--crypto/evp/m_mdc2.c55
-rw-r--r--crypto/evp/m_null.c5
-rw-r--r--crypto/evp/m_ripemd.c55
-rw-r--r--crypto/evp/m_sha1.c297
-rw-r--r--crypto/evp/m_sha3.c409
-rw-r--r--crypto/evp/m_sigver.c523
-rw-r--r--crypto/evp/m_wp.c54
-rw-r--r--crypto/evp/mac_lib.c303
-rw-r--r--crypto/evp/mac_meth.c246
-rw-r--r--crypto/evp/names.c88
-rw-r--r--crypto/evp/p5_crpt.c93
-rw-r--r--crypto/evp/p5_crpt2.c285
-rw-r--r--crypto/evp/p_dec.c24
-rw-r--r--crypto/evp/p_enc.c25
-rw-r--r--crypto/evp/p_legacy.c91
-rw-r--r--crypto/evp/p_lib.c2450
-rw-r--r--crypto/evp/p_open.c53
-rw-r--r--crypto/evp/p_seal.c44
-rw-r--r--crypto/evp/p_sign.c24
-rw-r--r--crypto/evp/p_verify.c22
-rw-r--r--crypto/evp/pbe_scrypt.c273
-rw-r--r--crypto/evp/pmeth_check.c193
-rw-r--r--crypto/evp/pmeth_fn.c297
-rw-r--r--crypto/evp/pmeth_gn.c444
-rw-r--r--crypto/evp/pmeth_lib.c1570
-rw-r--r--crypto/evp/signature.c748
-rw-r--r--crypto/ex_data.c293
-rw-r--r--crypto/ffc/build.info8
-rw-r--r--crypto/ffc/ffc_backend.c129
-rw-r--r--crypto/ffc/ffc_dh.c173
-rw-r--r--crypto/ffc/ffc_key_generate.c60
-rw-r--r--crypto/ffc/ffc_key_validate.c130
-rw-r--r--crypto/ffc/ffc_params.c322
-rw-r--r--crypto/ffc/ffc_params_generate.c1057
-rw-r--r--crypto/ffc/ffc_params_validate.c187
-rw-r--r--crypto/getenv.c76
-rw-r--r--crypto/hmac/build.info7
-rw-r--r--crypto/hmac/hm_ameth.c128
-rw-r--r--crypto/hmac/hm_pmeth.c212
-rw-r--r--crypto/hmac/hmac.c78
-rw-r--r--crypto/hmac/hmac_local.h2
-rw-r--r--crypto/http/build.info2
-rw-r--r--crypto/http/http_client.c1422
-rw-r--r--crypto/http/http_err.c82
-rw-r--r--crypto/http/http_lib.c286
-rw-r--r--crypto/ia64cpuid.S2
-rw-r--r--crypto/idea/build.info11
-rw-r--r--crypto/idea/i_cbc.c11
-rw-r--r--crypto/idea/i_cfb64.c16
-rw-r--r--crypto/idea/i_ecb.c11
-rw-r--r--crypto/idea/i_ofb64.c16
-rw-r--r--crypto/idea/i_skey.c11
-rw-r--r--crypto/idea/idea_local.h2
-rw-r--r--crypto/info.c207
-rw-r--r--crypto/init.c562
-rw-r--r--crypto/initthread.c467
-rw-r--r--crypto/kdf/build.info3
-rw-r--r--crypto/kdf/hkdf.c352
-rw-r--r--crypto/kdf/kdf_err.c56
-rw-r--r--crypto/kdf/scrypt.c266
-rw-r--r--crypto/kdf/tls1_prf.c278
-rw-r--r--crypto/lhash/build.info2
-rw-r--r--crypto/lhash/lh_stats.c30
-rw-r--r--crypto/lhash/lhash.c46
-rw-r--r--crypto/lhash/lhash_local.h17
-rw-r--r--crypto/md2/build.info10
-rw-r--r--crypto/md2/md2_dgst.c10
-rw-r--r--crypto/md2/md2_one.c10
-rw-r--r--crypto/md4/build.info10
-rw-r--r--crypto/md4/md4_dgst.c10
-rw-r--r--crypto/md4/md4_local.h2
-rw-r--r--crypto/md4/md4_one.c10
-rw-r--r--crypto/md5/asm/md5-586.pl10
-rw-r--r--crypto/md5/asm/md5-sparcv9.pl23
-rwxr-xr-xcrypto/md5/asm/md5-x86_64.pl28
-rw-r--r--crypto/md5/build.info41
-rw-r--r--crypto/md5/md5_dgst.c10
-rw-r--r--crypto/md5/md5_local.h10
-rw-r--r--crypto/md5/md5_one.c10
-rw-r--r--crypto/md5/md5_sha1.c108
-rw-r--r--crypto/mdc2/build.info10
-rw-r--r--crypto/mdc2/mdc2_one.c10
-rw-r--r--crypto/mdc2/mdc2dgst.c10
-rw-r--r--crypto/mem.c208
-rw-r--r--crypto/mem_clr.c2
-rw-r--r--crypto/mem_dbg.c670
-rw-r--r--crypto/mem_sec.c199
-rw-r--r--crypto/mips_arch.h4
-rwxr-xr-xcrypto/modes/asm/aes-gcm-armv8_64.pl5722
-rw-r--r--crypto/modes/asm/aesni-gcm-x86_64.pl12
-rw-r--r--crypto/modes/asm/ghash-armv4.pl17
-rw-r--r--crypto/modes/asm/ghash-c64xplus.pl5
-rwxr-xr-xcrypto/modes/asm/ghash-ia64.pl2
-rw-r--r--crypto/modes/asm/ghash-parisc.pl11
-rw-r--r--crypto/modes/asm/ghash-s390x.pl10
-rw-r--r--crypto/modes/asm/ghash-sparcv9.pl12
-rw-r--r--crypto/modes/asm/ghash-x86.pl5
-rw-r--r--crypto/modes/asm/ghash-x86_64.pl18
-rwxr-xr-xcrypto/modes/asm/ghashp8-ppc.pl11
-rw-r--r--crypto/modes/asm/ghashv8-armx.pl38
-rw-r--r--crypto/modes/build.info96
-rw-r--r--crypto/modes/cbc128.c6
-rw-r--r--crypto/modes/ccm128.c6
-rw-r--r--crypto/modes/cfb128.c13
-rw-r--r--crypto/modes/ctr128.c22
-rw-r--r--crypto/modes/cts128.c6
-rw-r--r--crypto/modes/gcm128.c136
-rw-r--r--crypto/modes/modes_local.h201
-rw-r--r--crypto/modes/ocb128.c10
-rw-r--r--crypto/modes/ofb128.c13
-rw-r--r--crypto/modes/siv128.c393
-rw-r--r--crypto/modes/wrap128.c2
-rw-r--r--crypto/modes/xts128.c18
-rw-r--r--crypto/o_dir.c2
-rw-r--r--crypto/o_fips.c24
-rw-r--r--crypto/o_fopen.c6
-rw-r--r--crypto/o_init.c2
-rw-r--r--crypto/o_str.c219
-rw-r--r--crypto/o_time.c2
-rw-r--r--crypto/objects/README44
-rw-r--r--crypto/objects/README.md43
-rw-r--r--crypto/objects/o_names.c59
-rw-r--r--crypto/objects/obj_compat.h54
-rw-r--r--crypto/objects/obj_dat.c160
-rw-r--r--crypto/objects/obj_dat.h345
-rw-r--r--crypto/objects/obj_dat.pl6
-rw-r--r--crypto/objects/obj_err.c26
-rw-r--r--crypto/objects/obj_lib.c8
-rw-r--r--crypto/objects/obj_local.h2
-rw-r--r--crypto/objects/obj_mac.num77
-rw-r--r--crypto/objects/obj_xref.c6
-rw-r--r--crypto/objects/obj_xref.h8
-rw-r--r--crypto/objects/obj_xref.txt4
-rw-r--r--crypto/objects/objects.pl15
-rw-r--r--crypto/objects/objects.txt101
-rw-r--r--crypto/objects/objxref.pl7
-rw-r--r--crypto/ocsp/build.info2
-rw-r--r--crypto/ocsp/ocsp_asn.c2
-rw-r--r--crypto/ocsp/ocsp_cl.c118
-rw-r--r--crypto/ocsp/ocsp_err.c56
-rw-r--r--crypto/ocsp/ocsp_ext.c10
-rw-r--r--crypto/ocsp/ocsp_ht.c502
-rw-r--r--crypto/ocsp/ocsp_http.c68
-rw-r--r--crypto/ocsp/ocsp_lib.c123
-rw-r--r--crypto/ocsp/ocsp_local.h52
-rw-r--r--crypto/ocsp/ocsp_prn.c4
-rw-r--r--crypto/ocsp/ocsp_srv.c101
-rw-r--r--crypto/ocsp/ocsp_vfy.c395
-rw-r--r--crypto/ocsp/v3_ocsp.c42
-rw-r--r--crypto/packet.c512
-rw-r--r--crypto/param_build.c389
-rw-r--r--crypto/param_build_set.c121
-rw-r--r--crypto/params.c1299
-rw-r--r--crypto/params_dup.c235
-rw-r--r--crypto/params_from_text.c230
-rw-r--r--crypto/pariscid.pl11
-rw-r--r--crypto/passphrase.c353
-rw-r--r--crypto/pem/pem_all.c94
-rw-r--r--crypto/pem/pem_err.c74
-rw-r--r--crypto/pem/pem_info.c182
-rw-r--r--crypto/pem/pem_lib.c150
-rw-r--r--crypto/pem/pem_local.h167
-rw-r--r--crypto/pem/pem_oth.c6
-rw-r--r--crypto/pem/pem_pk8.c221
-rw-r--r--crypto/pem/pem_pkey.c447
-rw-r--r--crypto/pem/pem_sign.c11
-rw-r--r--crypto/pem/pem_x509.c2
-rw-r--r--crypto/pem/pem_xaux.c2
-rw-r--r--crypto/pem/pvkfmt.c659
-rw-r--r--crypto/perlasm/README124
-rw-r--r--crypto/perlasm/README.md130
-rwxr-xr-xcrypto/perlasm/arm-xlate.pl21
-rw-r--r--crypto/perlasm/cbc.pl11
-rwxr-xr-xcrypto/perlasm/ppc-xlate.pl103
-rw-r--r--crypto/perlasm/s390x.pm3175
-rw-r--r--crypto/perlasm/sparcv9_modes.pl2
-rw-r--r--crypto/perlasm/x86_64-support.pl51
-rwxr-xr-xcrypto/perlasm/x86_64-xlate.pl56
-rw-r--r--crypto/perlasm/x86asm.pl6
-rw-r--r--crypto/perlasm/x86gas.pl25
-rw-r--r--crypto/perlasm/x86masm.pl2
-rw-r--r--crypto/perlasm/x86nasm.pl2
-rw-r--r--crypto/pkcs12/p12_add.c110
-rw-r--r--crypto/pkcs12/p12_asn.c2
-rw-r--r--crypto/pkcs12/p12_attr.c32
-rw-r--r--crypto/pkcs12/p12_crpt.c61
-rw-r--r--crypto/pkcs12/p12_crt.c131
-rw-r--r--crypto/pkcs12/p12_decr.c167
-rw-r--r--crypto/pkcs12/p12_init.c26
-rw-r--r--crypto/pkcs12/p12_key.c223
-rw-r--r--crypto/pkcs12/p12_kiss.c85
-rw-r--r--crypto/pkcs12/p12_local.h2
-rw-r--r--crypto/pkcs12/p12_mutl.c120
-rw-r--r--crypto/pkcs12/p12_npas.c22
-rw-r--r--crypto/pkcs12/p12_p8d.c21
-rw-r--r--crypto/pkcs12/p12_p8e.c76
-rw-r--r--crypto/pkcs12/p12_sbag.c122
-rw-r--r--crypto/pkcs12/p12_utl.c21
-rw-r--r--crypto/pkcs12/pk12err.c68
-rw-r--r--crypto/pkcs7/bio_pk7.c2
-rw-r--r--crypto/pkcs7/pk7_asn1.c61
-rw-r--r--crypto/pkcs7/pk7_attr.c13
-rw-r--r--crypto/pkcs7/pk7_doit.c378
-rw-r--r--crypto/pkcs7/pk7_lib.c285
-rw-r--r--crypto/pkcs7/pk7_local.h16
-rw-r--r--crypto/pkcs7/pk7_mime.c34
-rw-r--r--crypto/pkcs7/pk7_smime.c156
-rw-r--r--crypto/pkcs7/pkcs7err.c68
-rwxr-xr-xcrypto/poly1305/asm/poly1305-armv4.pl53
-rwxr-xr-xcrypto/poly1305/asm/poly1305-armv8.pl43
-rwxr-xr-xcrypto/poly1305/asm/poly1305-c64xplus.pl5
-rw-r--r--crypto/poly1305/asm/poly1305-ia64.S365
-rwxr-xr-xcrypto/poly1305/asm/poly1305-mips.pl10
-rwxr-xr-xcrypto/poly1305/asm/poly1305-ppc.pl1562
-rwxr-xr-xcrypto/poly1305/asm/poly1305-ppcfp.pl10
-rwxr-xr-xcrypto/poly1305/asm/poly1305-s390x.pl1123
-rwxr-xr-xcrypto/poly1305/asm/poly1305-sparcv9.pl18
-rwxr-xr-xcrypto/poly1305/asm/poly1305-x86.pl5
-rwxr-xr-xcrypto/poly1305/asm/poly1305-x86_64.pl14
-rw-r--r--crypto/poly1305/build.info66
-rw-r--r--crypto/poly1305/poly1305.c10
-rw-r--r--crypto/poly1305/poly1305_ameth.c122
-rw-r--r--crypto/poly1305/poly1305_base2_44.c6
-rw-r--r--crypto/poly1305/poly1305_ieee754.c2
-rw-r--r--crypto/poly1305/poly1305_local.h27
-rw-r--r--crypto/poly1305/poly1305_pmeth.c194
-rw-r--r--crypto/poly1305/poly1305_ppc.c47
-rw-r--r--crypto/ppc_arch.h28
-rw-r--r--crypto/ppccap.c128
-rwxr-xr-xcrypto/ppccpuid.pl10
-rw-r--r--crypto/property/README.md94
-rw-r--r--crypto/property/build.info4
-rw-r--r--crypto/property/defn_cache.c143
-rw-r--r--crypto/property/property.c769
-rw-r--r--crypto/property/property_err.c46
-rw-r--r--crypto/property/property_local.h55
-rw-r--r--crypto/property/property_parse.c706
-rw-r--r--crypto/property/property_query.c82
-rw-r--r--crypto/property/property_string.c246
-rw-r--r--crypto/provider.c149
-rw-r--r--crypto/provider_child.c328
-rw-r--r--crypto/provider_conf.c316
-rw-r--r--crypto/provider_core.c2171
-rw-r--r--crypto/provider_local.h33
-rw-r--r--crypto/provider_predefined.c32
-rw-r--r--crypto/punycode.c332
-rw-r--r--crypto/rand/build.info16
-rw-r--r--crypto/rand/drbg_ctr.c489
-rw-r--r--crypto/rand/drbg_lib.c1148
-rw-r--r--crypto/rand/prov_seed.c76
-rw-r--r--crypto/rand/rand_deprecated.c35
-rw-r--r--crypto/rand/rand_egd.c135
-rw-r--r--crypto/rand/rand_err.c66
-rw-r--r--crypto/rand/rand_lib.c1347
-rw-r--r--crypto/rand/rand_local.h295
-rw-r--r--crypto/rand/rand_meth.c65
-rw-r--r--crypto/rand/rand_pool.c412
-rw-r--r--crypto/rand/rand_unix.c880
-rw-r--r--crypto/rand/randfile.c33
-rw-r--r--crypto/rc2/build.info12
-rw-r--r--crypto/rc2/rc2_cbc.c10
-rw-r--r--crypto/rc2/rc2_ecb.c10
-rw-r--r--crypto/rc2/rc2_local.h2
-rw-r--r--crypto/rc2/rc2_skey.c14
-rw-r--r--crypto/rc2/rc2cfb64.c10
-rw-r--r--crypto/rc2/rc2ofb64.c10
-rw-r--r--crypto/rc4/asm/rc4-586.pl5
-rw-r--r--crypto/rc4/asm/rc4-c64xplus.pl5
-rw-r--r--crypto/rc4/asm/rc4-md5-x86_64.pl16
-rw-r--r--crypto/rc4/asm/rc4-parisc.pl11
-rw-r--r--crypto/rc4/asm/rc4-s390x.pl10
-rwxr-xr-xcrypto/rc4/asm/rc4-x86_64.pl15
-rw-r--r--crypto/rc4/build.info44
-rw-r--r--crypto/rc4/rc4_enc.c10
-rw-r--r--crypto/rc4/rc4_local.h2
-rw-r--r--crypto/rc4/rc4_skey.c10
-rw-r--r--crypto/rc5/asm/rc5-586.pl5
-rw-r--r--crypto/rc5/build.info29
-rw-r--r--crypto/rc5/rc5_ecb.c10
-rw-r--r--crypto/rc5/rc5_enc.c10
-rw-r--r--crypto/rc5/rc5_local.h2
-rw-r--r--crypto/rc5/rc5_skey.c19
-rw-r--r--crypto/rc5/rc5cfb64.c10
-rw-r--r--crypto/rc5/rc5ofb64.c10
-rw-r--r--crypto/ripemd/asm/rmd-586.pl5
-rw-r--r--crypto/ripemd/build.info32
-rw-r--r--crypto/ripemd/rmd_dgst.c10
-rw-r--r--crypto/ripemd/rmd_local.h2
-rw-r--r--crypto/ripemd/rmd_one.c10
-rw-r--r--crypto/ripemd/rmdconst.h2
-rw-r--r--crypto/rsa/build.info26
-rw-r--r--crypto/rsa/rsa_acvp_test_params.c167
-rw-r--r--crypto/rsa/rsa_ameth.c753
-rw-r--r--crypto/rsa/rsa_asn1.c21
-rw-r--r--crypto/rsa/rsa_backend.c595
-rw-r--r--crypto/rsa/rsa_chk.c98
-rw-r--r--crypto/rsa/rsa_crpt.c20
-rw-r--r--crypto/rsa/rsa_depr.c25
-rw-r--r--crypto/rsa/rsa_err.c116
-rw-r--r--crypto/rsa/rsa_gen.c170
-rw-r--r--crypto/rsa/rsa_lib.c833
-rw-r--r--crypto/rsa/rsa_local.h122
-rw-r--r--crypto/rsa/rsa_meth.c16
-rw-r--r--crypto/rsa/rsa_mp.c22
-rw-r--r--crypto/rsa/rsa_mp_names.c76
-rw-r--r--crypto/rsa/rsa_none.c16
-rw-r--r--crypto/rsa/rsa_oaep.c114
-rw-r--r--crypto/rsa/rsa_ossl.c171
-rw-r--r--crypto/rsa/rsa_pk1.c193
-rw-r--r--crypto/rsa/rsa_pmeth.c201
-rw-r--r--crypto/rsa/rsa_prn.c10
-rw-r--r--crypto/rsa/rsa_pss.c183
-rw-r--r--crypto/rsa/rsa_saos.c22
-rw-r--r--crypto/rsa/rsa_schemes.c86
-rw-r--r--crypto/rsa/rsa_sign.c365
-rw-r--r--crypto/rsa/rsa_sp800_56b_check.c437
-rw-r--r--crypto/rsa/rsa_sp800_56b_gen.c440
-rw-r--r--crypto/rsa/rsa_ssl.c176
-rw-r--r--crypto/rsa/rsa_x931.c20
-rw-r--r--crypto/rsa/rsa_x931g.c12
-rw-r--r--crypto/s390x_arch.h131
-rw-r--r--crypto/s390xcap.c733
-rwxr-xr-xcrypto/s390xcpuid.pl168
-rw-r--r--crypto/seed/build.info10
-rw-r--r--crypto/seed/seed.c10
-rw-r--r--crypto/seed/seed_cbc.c10
-rw-r--r--crypto/seed/seed_cfb.c10
-rw-r--r--crypto/seed/seed_ecb.c10
-rw-r--r--crypto/seed/seed_local.h6
-rw-r--r--crypto/seed/seed_ofb.c10
-rw-r--r--crypto/self_test_core.c172
-rwxr-xr-xcrypto/sha/asm/keccak1600-armv4.pl48
-rwxr-xr-xcrypto/sha/asm/keccak1600-armv8.pl158
-rwxr-xr-xcrypto/sha/asm/keccak1600-avx2.pl5
-rwxr-xr-xcrypto/sha/asm/keccak1600-avx512.pl5
-rwxr-xr-xcrypto/sha/asm/keccak1600-avx512vl.pl5
-rwxr-xr-xcrypto/sha/asm/keccak1600-c64x.pl5
-rwxr-xr-xcrypto/sha/asm/keccak1600-mmx.pl5
-rwxr-xr-xcrypto/sha/asm/keccak1600-ppc64.pl50
-rwxr-xr-xcrypto/sha/asm/keccak1600-s390x.pl10
-rwxr-xr-xcrypto/sha/asm/keccak1600-x86_64.pl12
-rwxr-xr-xcrypto/sha/asm/keccak1600p8-ppc.pl10
-rw-r--r--crypto/sha/asm/sha1-586.pl5
-rw-r--r--crypto/sha/asm/sha1-armv4-large.pl34
-rw-r--r--crypto/sha/asm/sha1-armv8.pl42
-rw-r--r--crypto/sha/asm/sha1-c64xplus.pl5
-rw-r--r--crypto/sha/asm/sha1-ia64.pl5
-rw-r--r--crypto/sha/asm/sha1-mb-x86_64.pl54
-rw-r--r--crypto/sha/asm/sha1-mips.pl13
-rw-r--r--crypto/sha/asm/sha1-parisc.pl11
-rwxr-xr-xcrypto/sha/asm/sha1-ppc.pl10
-rw-r--r--crypto/sha/asm/sha1-s390x.pl10
-rw-r--r--crypto/sha/asm/sha1-sparcv9.pl12
-rw-r--r--crypto/sha/asm/sha1-sparcv9a.pl5
-rw-r--r--crypto/sha/asm/sha1-thumb.pl5
-rwxr-xr-xcrypto/sha/asm/sha1-x86_64.pl12
-rw-r--r--crypto/sha/asm/sha256-586.pl5
-rw-r--r--crypto/sha/asm/sha256-armv4.pl32
-rw-r--r--crypto/sha/asm/sha256-c64xplus.pl5
-rw-r--r--crypto/sha/asm/sha256-mb-x86_64.pl54
-rw-r--r--crypto/sha/asm/sha512-586.pl5
-rw-r--r--crypto/sha/asm/sha512-armv4.pl34
-rw-r--r--crypto/sha/asm/sha512-armv8.pl37
-rw-r--r--crypto/sha/asm/sha512-c64xplus.pl5
-rwxr-xr-xcrypto/sha/asm/sha512-ia64.pl11
-rw-r--r--crypto/sha/asm/sha512-mips.pl12
-rwxr-xr-xcrypto/sha/asm/sha512-parisc.pl11
-rwxr-xr-xcrypto/sha/asm/sha512-ppc.pl11
-rw-r--r--crypto/sha/asm/sha512-s390x.pl8
-rw-r--r--crypto/sha/asm/sha512-sparcv9.pl15
-rwxr-xr-xcrypto/sha/asm/sha512-x86_64.pl14
-rwxr-xr-xcrypto/sha/asm/sha512p8-ppc.pl11
-rw-r--r--crypto/sha/build.info219
-rw-r--r--crypto/sha/keccak1600.c15
-rw-r--r--crypto/sha/sha1_one.c59
-rw-r--r--crypto/sha/sha1dgst.c71
-rw-r--r--crypto/sha/sha256.c48
-rw-r--r--crypto/sha/sha3.c109
-rw-r--r--crypto/sha/sha512.c47
-rw-r--r--crypto/sha/sha_local.h16
-rw-r--r--crypto/sha/sha_ppc.c33
-rw-r--r--crypto/siphash/build.info4
-rw-r--r--crypto/siphash/siphash.c15
-rw-r--r--crypto/siphash/siphash_ameth.c123
-rw-r--r--crypto/siphash/siphash_local.h23
-rw-r--r--crypto/siphash/siphash_pmeth.c205
-rw-r--r--crypto/sm2/build.info2
-rw-r--r--crypto/sm2/sm2_crypt.c120
-rw-r--r--crypto/sm2/sm2_err.c47
-rw-r--r--crypto/sm2/sm2_key.c51
-rw-r--r--crypto/sm2/sm2_pmeth.c329
-rw-r--r--crypto/sm2/sm2_sign.c165
-rw-r--r--crypto/sm3/build.info5
-rw-r--r--crypto/sm3/legacy_sm3.c31
-rw-r--r--crypto/sm3/m_sm3.c52
-rw-r--r--crypto/sm3/sm3.c9
-rw-r--r--crypto/sm3/sm3_local.h17
-rw-r--r--crypto/sm4/sm4.c10
-rw-r--r--crypto/sparc_arch.h118
-rw-r--r--crypto/sparccpuid.S2
-rw-r--r--crypto/sparcv9cap.c69
-rw-r--r--crypto/sparse_array.c216
-rw-r--r--crypto/srp/srp_lib.c103
-rw-r--r--crypto/srp/srp_vfy.c106
-rw-r--r--crypto/stack/build.info1
-rw-r--r--crypto/stack/stack.c155
-rw-r--r--crypto/store/build.info7
-rw-r--r--crypto/store/loader_file.c1477
-rw-r--r--crypto/store/store_err.c93
-rw-r--r--crypto/store/store_init.c21
-rw-r--r--crypto/store/store_lib.c734
-rw-r--r--crypto/store/store_local.h106
-rw-r--r--crypto/store/store_meth.c538
-rw-r--r--crypto/store/store_register.c116
-rw-r--r--crypto/store/store_result.c648
-rw-r--r--crypto/store/store_strings.c5
-rw-r--r--crypto/threads_lib.c25
-rw-r--r--crypto/threads_none.c24
-rw-r--r--crypto/threads_pthread.c122
-rw-r--r--crypto/trace.c531
-rw-r--r--crypto/ts/ts_asn1.c104
-rw-r--r--crypto/ts/ts_conf.c47
-rw-r--r--crypto/ts/ts_err.c119
-rw-r--r--crypto/ts/ts_lib.c2
-rw-r--r--crypto/ts/ts_local.h67
-rw-r--r--crypto/ts/ts_req_print.c2
-rw-r--r--crypto/ts/ts_req_utils.c12
-rw-r--r--crypto/ts/ts_rsp_print.c4
-rw-r--r--crypto/ts/ts_rsp_sign.c415
-rw-r--r--crypto/ts/ts_rsp_utils.c26
-rw-r--r--crypto/ts/ts_rsp_verify.c276
-rw-r--r--crypto/ts/ts_verify_ctx.c6
-rw-r--r--crypto/txt_db/txt_db.c4
-rw-r--r--crypto/ui/ui_err.c41
-rw-r--r--crypto/ui/ui_lib.c134
-rw-r--r--crypto/ui/ui_local.h2
-rw-r--r--crypto/ui/ui_null.c2
-rw-r--r--crypto/ui/ui_openssl.c64
-rw-r--r--crypto/ui/ui_util.c18
-rw-r--r--crypto/uid.c6
-rw-r--r--crypto/vms_rms.h2
-rw-r--r--crypto/whrlpool/asm/wp-mmx.pl7
-rw-r--r--crypto/whrlpool/asm/wp-x86_64.pl14
-rw-r--r--crypto/whrlpool/build.info35
-rw-r--r--crypto/whrlpool/wp_block.c14
-rw-r--r--crypto/whrlpool/wp_dgst.c10
-rw-r--r--crypto/whrlpool/wp_local.h2
-rw-r--r--crypto/x509/build.info17
-rw-r--r--crypto/x509/by_dir.c104
-rw-r--r--crypto/x509/by_file.c110
-rw-r--r--crypto/x509/by_store.c249
-rw-r--r--crypto/x509/ext_dat.h27
-rw-r--r--crypto/x509/pcy_cache.c225
-rw-r--r--crypto/x509/pcy_data.c82
-rw-r--r--crypto/x509/pcy_lib.c108
-rw-r--r--crypto/x509/pcy_local.h165
-rw-r--r--crypto/x509/pcy_map.c79
-rw-r--r--crypto/x509/pcy_node.c147
-rw-r--r--crypto/x509/pcy_tree.c697
-rw-r--r--crypto/x509/standard_exts.h80
-rw-r--r--crypto/x509/t_crl.c8
-rw-r--r--crypto/x509/t_req.c22
-rw-r--r--crypto/x509/t_x509.c198
-rw-r--r--crypto/x509/v3_addr.c1357
-rw-r--r--crypto/x509/v3_admis.c355
-rw-r--r--crypto/x509/v3_admis.h38
-rw-r--r--crypto/x509/v3_akeya.c23
-rw-r--r--crypto/x509/v3_akid.c218
-rw-r--r--crypto/x509/v3_asid.c896
-rw-r--r--crypto/x509/v3_bcons.c85
-rw-r--r--crypto/x509/v3_bitst.c91
-rw-r--r--crypto/x509/v3_conf.c584
-rw-r--r--crypto/x509/v3_cpols.c500
-rw-r--r--crypto/x509/v3_crld.c508
-rw-r--r--crypto/x509/v3_enum.c53
-rw-r--r--crypto/x509/v3_extku.c102
-rw-r--r--crypto/x509/v3_genn.c241
-rw-r--r--crypto/x509/v3_ia5.c64
-rw-r--r--crypto/x509/v3_info.c156
-rw-r--r--crypto/x509/v3_int.c43
-rw-r--r--crypto/x509/v3_ist.c149
-rw-r--r--crypto/x509/v3_lib.c304
-rw-r--r--crypto/x509/v3_ncons.c834
-rw-r--r--crypto/x509/v3_pci.c321
-rw-r--r--crypto/x509/v3_pcia.c64
-rw-r--r--crypto/x509/v3_pcons.c91
-rw-r--r--crypto/x509/v3_pku.c52
-rw-r--r--crypto/x509/v3_pmaps.c110
-rw-r--r--crypto/x509/v3_prn.c216
-rw-r--r--crypto/x509/v3_purp.c1066
-rw-r--r--crypto/x509/v3_san.c691
-rw-r--r--crypto/x509/v3_skid.c111
-rw-r--r--crypto/x509/v3_sxnet.c242
-rw-r--r--crypto/x509/v3_tlsf.c140
-rw-r--r--crypto/x509/v3_utf8.c68
-rw-r--r--crypto/x509/v3_utl.c1358
-rw-r--r--crypto/x509/v3err.c147
-rw-r--r--crypto/x509/x509_att.c50
-rw-r--r--crypto/x509/x509_cmp.c238
-rw-r--r--crypto/x509/x509_d2.c96
-rw-r--r--crypto/x509/x509_def.c2
-rw-r--r--crypto/x509/x509_err.c118
-rw-r--r--crypto/x509/x509_ext.c2
-rw-r--r--crypto/x509/x509_local.h34
-rw-r--r--crypto/x509/x509_lu.c287
-rw-r--r--crypto/x509/x509_meth.c8
-rw-r--r--crypto/x509/x509_obj.c36
-rw-r--r--crypto/x509/x509_r2x.c8
-rw-r--r--crypto/x509/x509_req.c71
-rw-r--r--crypto/x509/x509_set.c99
-rw-r--r--crypto/x509/x509_trs.c300
-rw-r--r--crypto/x509/x509_trust.c300
-rw-r--r--crypto/x509/x509_txt.c66
-rw-r--r--crypto/x509/x509_v3.c18
-rw-r--r--crypto/x509/x509_vfy.c1631
-rw-r--r--crypto/x509/x509_vpm.c154
-rw-r--r--crypto/x509/x509cset.c12
-rw-r--r--crypto/x509/x509name.c37
-rw-r--r--crypto/x509/x509rset.c6
-rw-r--r--crypto/x509/x509spki.c13
-rw-r--r--crypto/x509/x509type.c6
-rw-r--r--crypto/x509/x_all.c430
-rw-r--r--crypto/x509/x_attrib.c4
-rw-r--r--crypto/x509/x_crl.c73
-rw-r--r--crypto/x509/x_exten.c2
-rw-r--r--crypto/x509/x_name.c62
-rw-r--r--crypto/x509/x_pubkey.c930
-rw-r--r--crypto/x509/x_req.c111
-rw-r--r--crypto/x509/x_x509.c93
-rw-r--r--crypto/x509/x_x509a.c15
-rw-r--r--crypto/x509v3/build.info8
-rw-r--r--crypto/x509v3/ext_dat.h25
-rw-r--r--crypto/x509v3/pcy_cache.c224
-rw-r--r--crypto/x509v3/pcy_data.c82
-rw-r--r--crypto/x509v3/pcy_lib.c108
-rw-r--r--crypto/x509v3/pcy_local.h167
-rw-r--r--crypto/x509v3/pcy_map.c81
-rw-r--r--crypto/x509v3/pcy_node.c147
-rw-r--r--crypto/x509v3/pcy_tree.c703
-rw-r--r--crypto/x509v3/standard_exts.h78
-rw-r--r--crypto/x509v3/v3_addr.c1332
-rw-r--r--crypto/x509v3/v3_admis.c356
-rw-r--r--crypto/x509v3/v3_admis.h38
-rw-r--r--crypto/x509v3/v3_akey.c188
-rw-r--r--crypto/x509v3/v3_akeya.c23
-rw-r--r--crypto/x509v3/v3_alt.c613
-rw-r--r--crypto/x509v3/v3_asid.c907
-rw-r--r--crypto/x509v3/v3_bcons.c84
-rw-r--r--crypto/x509v3/v3_bitst.c93
-rw-r--r--crypto/x509v3/v3_conf.c511
-rw-r--r--crypto/x509v3/v3_cpols.c494
-rw-r--r--crypto/x509v3/v3_crld.c506
-rw-r--r--crypto/x509v3/v3_enum.c53
-rw-r--r--crypto/x509v3/v3_extku.c103
-rw-r--r--crypto/x509v3/v3_genn.c241
-rw-r--r--crypto/x509v3/v3_ia5.c65
-rw-r--r--crypto/x509v3/v3_info.c162
-rw-r--r--crypto/x509v3/v3_int.c43
-rw-r--r--crypto/x509v3/v3_lib.c305
-rw-r--r--crypto/x509v3/v3_ncons.c705
-rw-r--r--crypto/x509v3/v3_pci.c326
-rw-r--r--crypto/x509v3/v3_pcia.c64
-rw-r--r--crypto/x509v3/v3_pcons.c91
-rw-r--r--crypto/x509v3/v3_pku.c52
-rw-r--r--crypto/x509v3/v3_pmaps.c112
-rw-r--r--crypto/x509v3/v3_prn.c210
-rw-r--r--crypto/x509v3/v3_purp.c993
-rw-r--r--crypto/x509v3/v3_skey.c106
-rw-r--r--crypto/x509v3/v3_sxnet.c240
-rw-r--r--crypto/x509v3/v3_tlsf.c137
-rw-r--r--crypto/x509v3/v3_utl.c1289
-rw-r--r--crypto/x509v3/v3err.c261
-rw-r--r--crypto/x86_64cpuid.pl25
-rw-r--r--crypto/x86cpuid.pl6
-rw-r--r--doc/HOWTO/certificates.txt2
-rw-r--r--doc/HOWTO/keys.txt4
-rw-r--r--doc/README27
-rw-r--r--doc/README.md30
-rw-r--r--doc/build.info4860
-rw-r--r--doc/build.info.in80
-rw-r--r--doc/fingerprints.txt25
-rw-r--r--doc/images/openssl.svg41
-rw-r--r--doc/internal/man3/OPENSSL_SA.pod131
-rw-r--r--doc/internal/man3/OPTIONS.pod343
-rw-r--r--doc/internal/man3/OSSL_DEPRECATED.pod54
-rw-r--r--doc/internal/man3/OSSL_METHOD_STORE.pod144
-rw-r--r--doc/internal/man3/cms_add1_signing_cert.pod46
-rw-r--r--doc/internal/man3/evp_generic_fetch.pod285
-rw-r--r--doc/internal/man3/evp_keymgmt_newdata.pod88
-rw-r--r--doc/internal/man3/evp_keymgmt_util_export_to_provider.pod106
-rw-r--r--doc/internal/man3/evp_md_get_number.pod112
-rw-r--r--doc/internal/man3/evp_pkey_export_to_provider.pod80
-rw-r--r--doc/internal/man3/evp_pkey_get1_ED25519.pod43
-rw-r--r--doc/internal/man3/ossl_DER_w_begin_sequence.pod48
-rw-r--r--doc/internal/man3/ossl_DER_w_bn.pod66
-rw-r--r--doc/internal/man3/ossl_DER_w_precompiled.pod48
-rw-r--r--doc/internal/man3/ossl_algorithm_do_all.pod63
-rw-r--r--doc/internal/man3/ossl_cmp_X509_STORE_add1_certs.pod44
-rw-r--r--doc/internal/man3/ossl_cmp_asn1_octet_string_set1.pod45
-rw-r--r--doc/internal/man3/ossl_cmp_certreq_new.pod177
-rw-r--r--doc/internal/man3/ossl_cmp_ctx_set1_caPubs.pod76
-rw-r--r--doc/internal/man3/ossl_cmp_hdr_init.pod151
-rw-r--r--doc/internal/man3/ossl_cmp_mock_srv_new.pod87
-rw-r--r--doc/internal/man3/ossl_cmp_msg_check_update.pod95
-rw-r--r--doc/internal/man3/ossl_cmp_msg_create.pod134
-rw-r--r--doc/internal/man3/ossl_cmp_msg_protect.pod62
-rw-r--r--doc/internal/man3/ossl_cmp_pkisi_get_status.pod99
-rw-r--r--doc/internal/man3/ossl_cmp_print_log.pod108
-rw-r--r--doc/internal/man3/ossl_ends_with_dirsep.pod45
-rw-r--r--doc/internal/man3/ossl_global_properties_no_mirrored.pod56
-rw-r--r--doc/internal/man3/ossl_init_thread_deregister.pod66
-rw-r--r--doc/internal/man3/ossl_lib_ctx_get_data.pod154
-rw-r--r--doc/internal/man3/ossl_method_construct.pod158
-rw-r--r--doc/internal/man3/ossl_namemap_new.pod129
-rw-r--r--doc/internal/man3/ossl_provider_add_conf_module.pod41
-rw-r--r--doc/internal/man3/ossl_provider_new.pod400
-rw-r--r--doc/internal/man3/ossl_punycode_decode.pod60
-rw-r--r--doc/internal/man3/ossl_rand_get_entropy.pod66
-rw-r--r--doc/internal/man3/ossl_random_add_conf_module.pod42
-rw-r--r--doc/internal/man3/ossl_rsa_get0_all_params.pod75
-rw-r--r--doc/internal/man3/x509v3_cache_extensions.pod41
-rw-r--r--doc/internal/man7/DERlib.pod149
-rw-r--r--doc/internal/man7/EVP_PKEY.pod212
-rw-r--r--doc/internal/man7/VERSION.pod149
-rw-r--r--doc/internal/man7/build.info.pod644
-rw-r--r--doc/internal/man7/deprecation.pod140
-rw-r--r--doc/life-cycles/Makefile26
-rw-r--r--doc/life-cycles/README.md20
-rw-r--r--doc/life-cycles/cipher.dot72
-rw-r--r--doc/life-cycles/digest.dot33
-rw-r--r--doc/life-cycles/kdf.dot16
-rw-r--r--doc/life-cycles/lifecycles.odsbin0 -> 17042 bytes
-rw-r--r--doc/life-cycles/mac.dot28
-rw-r--r--doc/life-cycles/pkey.dot49
-rw-r--r--doc/life-cycles/rand.dot17
-rw-r--r--doc/man1/CA.pl.pod159
-rw-r--r--doc/man1/asn1parse.pod215
-rw-r--r--doc/man1/build.info57
-rw-r--r--doc/man1/ca.pod769
-rw-r--r--doc/man1/ciphers.pod776
-rw-r--r--doc/man1/cms.pod748
-rw-r--r--doc/man1/crl.pod143
-rw-r--r--doc/man1/crl2pkcs7.pod106
-rw-r--r--doc/man1/dgst.pod251
-rw-r--r--doc/man1/dhparam.pod166
-rw-r--r--doc/man1/dsa.pod182
-rw-r--r--doc/man1/dsaparam.pod131
-rw-r--r--doc/man1/ec.pod203
-rw-r--r--doc/man1/ecparam.pod192
-rw-r--r--doc/man1/enc.pod438
-rw-r--r--doc/man1/engine.pod119
-rw-r--r--doc/man1/errstr.pod46
-rw-r--r--doc/man1/gendsa.pod101
-rw-r--r--doc/man1/genpkey.pod335
-rw-r--r--doc/man1/genrsa.pod128
-rw-r--r--doc/man1/list.pod94
-rw-r--r--doc/man1/nseq.pod85
-rw-r--r--doc/man1/ocsp.pod500
-rw-r--r--doc/man1/openssl-asn1parse.pod.in220
-rw-r--r--doc/man1/openssl-ca.pod.in849
-rw-r--r--doc/man1/openssl-ciphers.pod.in804
-rw-r--r--doc/man1/openssl-cmds.pod.in162
-rw-r--r--doc/man1/openssl-cmp.pod.in1244
-rw-r--r--doc/man1/openssl-cms.pod.in912
-rw-r--r--doc/man1/openssl-crl.pod.in172
-rw-r--r--doc/man1/openssl-crl2pkcs7.pod.in108
-rw-r--r--doc/man1/openssl-dgst.pod.in288
-rw-r--r--doc/man1/openssl-dhparam.pod.in136
-rw-r--r--doc/man1/openssl-dsa.pod.in195
-rw-r--r--doc/man1/openssl-dsaparam.pod.in120
-rw-r--r--doc/man1/openssl-ec.pod.in208
-rw-r--r--doc/man1/openssl-ecparam.pod.in186
-rw-r--r--doc/man1/openssl-enc.pod.in458
-rw-r--r--doc/man1/openssl-engine.pod.in132
-rw-r--r--doc/man1/openssl-errstr.pod.in54
-rw-r--r--doc/man1/openssl-fipsinstall.pod.in251
-rw-r--r--doc/man1/openssl-format-options.pod145
-rw-r--r--doc/man1/openssl-gendsa.pod.in108
-rw-r--r--doc/man1/openssl-genpkey.pod.in504
-rw-r--r--doc/man1/openssl-genrsa.pod.in134
-rw-r--r--doc/man1/openssl-info.pod.in91
-rw-r--r--doc/man1/openssl-kdf.pod.in205
-rw-r--r--doc/man1/openssl-list.pod.in247
-rw-r--r--doc/man1/openssl-mac.pod.in175
-rw-r--r--doc/man1/openssl-namedisplay-options.pod179
-rw-r--r--doc/man1/openssl-nseq.pod.in76
-rw-r--r--doc/man1/openssl-ocsp.pod.in517
-rw-r--r--doc/man1/openssl-passphrase-options.pod75
-rw-r--r--doc/man1/openssl-passwd.pod.in122
-rw-r--r--doc/man1/openssl-pkcs12.pod.in470
-rw-r--r--doc/man1/openssl-pkcs7.pod.in110
-rw-r--r--doc/man1/openssl-pkcs8.pod.in288
-rw-r--r--doc/man1/openssl-pkey.pod.in238
-rw-r--r--doc/man1/openssl-pkeyparam.pod.in98
-rw-r--r--doc/man1/openssl-pkeyutl.pod.in430
-rw-r--r--doc/man1/openssl-prime.pod.in70
-rw-r--r--doc/man1/openssl-rand.pod.in78
-rw-r--r--doc/man1/openssl-rehash.pod.in157
-rw-r--r--doc/man1/openssl-req.pod.in775
-rw-r--r--doc/man1/openssl-rsa.pod.in216
-rw-r--r--doc/man1/openssl-rsautl.pod.in242
-rw-r--r--doc/man1/openssl-s_client.pod.in920
-rw-r--r--doc/man1/openssl-s_server.pod.in940
-rw-r--r--doc/man1/openssl-s_time.pod.in198
-rw-r--r--doc/man1/openssl-sess_id.pod.in162
-rw-r--r--doc/man1/openssl-smime.pod.in492
-rw-r--r--doc/man1/openssl-speed.pod.in146
-rw-r--r--doc/man1/openssl-spkac.pod.in169
-rw-r--r--doc/man1/openssl-srp.pod.in118
-rw-r--r--doc/man1/openssl-storeutl.pod.in147
-rw-r--r--doc/man1/openssl-ts.pod.in662
-rw-r--r--doc/man1/openssl-verification-options.pod696
-rw-r--r--doc/man1/openssl-verify.pod.in150
-rw-r--r--doc/man1/openssl-version.pod.in96
-rw-r--r--doc/man1/openssl-x509.pod.in794
-rw-r--r--doc/man1/openssl.pod489
-rw-r--r--doc/man1/passwd.pod130
-rw-r--r--doc/man1/pkcs12.pod389
-rw-r--r--doc/man1/pkcs7.pod120
-rw-r--r--doc/man1/pkcs8.pod319
-rw-r--r--doc/man1/pkey.pod168
-rw-r--r--doc/man1/pkeyparam.pod88
-rw-r--r--doc/man1/pkeyutl.pod347
-rw-r--r--doc/man1/prime.pod68
-rw-r--r--doc/man1/rand.pod95
-rw-r--r--doc/man1/rehash.pod146
-rw-r--r--doc/man1/req.pod705
-rw-r--r--doc/man1/rsa.pod205
-rw-r--r--doc/man1/rsautl.pod220
-rw-r--r--doc/man1/s_client.pod838
-rw-r--r--doc/man1/s_server.pod855
-rw-r--r--doc/man1/s_time.pod212
-rw-r--r--doc/man1/sess_id.pod166
-rw-r--r--doc/man1/smime.pod524
-rw-r--r--doc/man1/speed.pod104
-rw-r--r--doc/man1/spkac.pod155
-rw-r--r--doc/man1/srp.pod73
-rw-r--r--doc/man1/storeutl.pod133
-rw-r--r--doc/man1/ts.pod675
-rw-r--r--doc/man1/tsget.pod124
-rw-r--r--doc/man1/verify.pod786
-rw-r--r--doc/man1/version.pod81
-rw-r--r--doc/man1/x509.pod946
-rw-r--r--doc/man3/ADMISSIONS.pod4
-rw-r--r--doc/man3/ASN1_EXTERN_FUNCS.pod181
-rw-r--r--doc/man3/ASN1_INTEGER_get_int64.pod38
-rw-r--r--doc/man3/ASN1_INTEGER_new.pod44
-rw-r--r--doc/man3/ASN1_ITEM_lookup.pod10
-rw-r--r--doc/man3/ASN1_OBJECT_new.pod16
-rw-r--r--doc/man3/ASN1_STRING_TABLE_add.pod16
-rw-r--r--doc/man3/ASN1_STRING_length.pod40
-rw-r--r--doc/man3/ASN1_STRING_new.pod16
-rw-r--r--doc/man3/ASN1_STRING_print_ex.pod16
-rw-r--r--doc/man3/ASN1_TIME_set.pod182
-rw-r--r--doc/man3/ASN1_TYPE_get.pod57
-rw-r--r--doc/man3/ASN1_aux_cb.pod284
-rw-r--r--doc/man3/ASN1_generate_nconf.pod51
-rw-r--r--doc/man3/ASN1_item_d2i_bio.pod88
-rw-r--r--doc/man3/ASN1_item_new.pod45
-rw-r--r--doc/man3/ASN1_item_sign.pod226
-rw-r--r--doc/man3/ASYNC_WAIT_CTX_new.pod180
-rw-r--r--doc/man3/ASYNC_start_job.pod130
-rw-r--r--doc/man3/BF_encrypt.pod16
-rw-r--r--doc/man3/BIO_ADDR.pod6
-rw-r--r--doc/man3/BIO_ADDRINFO.pod9
-rw-r--r--doc/man3/BIO_connect.pod2
-rw-r--r--doc/man3/BIO_ctrl.pod41
-rw-r--r--doc/man3/BIO_f_base64.pod4
-rw-r--r--doc/man3/BIO_f_buffer.pod11
-rw-r--r--doc/man3/BIO_f_cipher.pod20
-rw-r--r--doc/man3/BIO_f_md.pod10
-rw-r--r--doc/man3/BIO_f_null.pod2
-rw-r--r--doc/man3/BIO_f_prefix.pod70
-rw-r--r--doc/man3/BIO_f_readbuffer.pod61
-rw-r--r--doc/man3/BIO_f_ssl.pod34
-rw-r--r--doc/man3/BIO_find_type.pod6
-rw-r--r--doc/man3/BIO_get_data.pod6
-rw-r--r--doc/man3/BIO_get_ex_new_index.pod89
-rw-r--r--doc/man3/BIO_meth_new.pod29
-rw-r--r--doc/man3/BIO_new.pod28
-rw-r--r--doc/man3/BIO_new_CMS.pod2
-rw-r--r--doc/man3/BIO_parse_hostserv.pod7
-rw-r--r--doc/man3/BIO_printf.pod27
-rw-r--r--doc/man3/BIO_push.pod4
-rw-r--r--doc/man3/BIO_read.pod76
-rw-r--r--doc/man3/BIO_s_accept.pod22
-rw-r--r--doc/man3/BIO_s_bio.pod2
-rw-r--r--doc/man3/BIO_s_connect.pod62
-rw-r--r--doc/man3/BIO_s_core.pod72
-rw-r--r--doc/man3/BIO_s_datagram.pod234
-rw-r--r--doc/man3/BIO_s_fd.pod12
-rw-r--r--doc/man3/BIO_s_file.pod25
-rw-r--r--doc/man3/BIO_s_mem.pod12
-rw-r--r--doc/man3/BIO_s_null.pod2
-rw-r--r--doc/man3/BIO_s_socket.pod2
-rw-r--r--doc/man3/BIO_set_callback.pod38
-rw-r--r--doc/man3/BIO_should_retry.pod4
-rw-r--r--doc/man3/BIO_socket_wait.pod69
-rw-r--r--doc/man3/BN_BLINDING_new.pod8
-rw-r--r--doc/man3/BN_CTX_new.pod22
-rw-r--r--doc/man3/BN_CTX_start.pod4
-rw-r--r--doc/man3/BN_add.pod2
-rw-r--r--doc/man3/BN_add_word.pod2
-rw-r--r--doc/man3/BN_bn2bin.pod22
-rw-r--r--doc/man3/BN_cmp.pod2
-rw-r--r--doc/man3/BN_copy.pod2
-rw-r--r--doc/man3/BN_generate_prime.pod139
-rw-r--r--doc/man3/BN_mod_exp_mont.pod65
-rw-r--r--doc/man3/BN_mod_inverse.pod2
-rw-r--r--doc/man3/BN_mod_mul_montgomery.pod2
-rw-r--r--doc/man3/BN_mod_mul_reciprocal.pod8
-rw-r--r--doc/man3/BN_new.pod4
-rw-r--r--doc/man3/BN_num_bytes.pod2
-rw-r--r--doc/man3/BN_rand.pod78
-rw-r--r--doc/man3/BN_security_bits.pod2
-rw-r--r--doc/man3/BN_set_bit.pod2
-rw-r--r--doc/man3/BN_swap.pod2
-rw-r--r--doc/man3/BN_zero.pod2
-rw-r--r--doc/man3/BUF_MEM_new.pod2
-rw-r--r--doc/man3/CMS_EncryptedData_decrypt.pod49
-rw-r--r--doc/man3/CMS_EncryptedData_encrypt.pod69
-rw-r--r--doc/man3/CMS_EnvelopedData_create.pod80
-rw-r--r--doc/man3/CMS_add0_cert.pod2
-rw-r--r--doc/man3/CMS_add1_recipient_cert.pod20
-rw-r--r--doc/man3/CMS_add1_signer.pod2
-rw-r--r--doc/man3/CMS_compress.pod6
-rw-r--r--doc/man3/CMS_data_create.pod54
-rw-r--r--doc/man3/CMS_decrypt.pod27
-rw-r--r--doc/man3/CMS_digest_create.pod58
-rw-r--r--doc/man3/CMS_encrypt.pod36
-rw-r--r--doc/man3/CMS_final.pod4
-rw-r--r--doc/man3/CMS_get0_RecipientInfos.pod22
-rw-r--r--doc/man3/CMS_get0_SignerInfos.pod2
-rw-r--r--doc/man3/CMS_get0_type.pod7
-rw-r--r--doc/man3/CMS_get1_ReceiptRequest.pod46
-rw-r--r--doc/man3/CMS_sign.pod35
-rw-r--r--doc/man3/CMS_sign_receipt.pod2
-rw-r--r--doc/man3/CMS_uncompress.pod2
-rw-r--r--doc/man3/CMS_verify.pod10
-rw-r--r--doc/man3/CMS_verify_receipt.pod2
-rw-r--r--doc/man3/CONF_modules_free.pod16
-rw-r--r--doc/man3/CONF_modules_load_file.pod62
-rw-r--r--doc/man3/CRYPTO_THREAD_run_once.pod82
-rw-r--r--doc/man3/CRYPTO_get_ex_new_index.pod49
-rw-r--r--doc/man3/CRYPTO_memcmp.pod2
-rw-r--r--doc/man3/CTLOG_STORE_get0_log_by_id.pod2
-rw-r--r--doc/man3/CTLOG_STORE_new.pod29
-rw-r--r--doc/man3/CTLOG_new.pod40
-rw-r--r--doc/man3/CT_POLICY_EVAL_CTX_new.pod26
-rw-r--r--doc/man3/DEFINE_STACK_OF.pod279
-rw-r--r--doc/man3/DES_random_key.pod26
-rw-r--r--doc/man3/DH_generate_key.pod13
-rw-r--r--doc/man3/DH_generate_parameters.pod29
-rw-r--r--doc/man3/DH_get0_pqg.pod65
-rw-r--r--doc/man3/DH_get_1024_160.pod59
-rw-r--r--doc/man3/DH_meth_new.pod13
-rw-r--r--doc/man3/DH_new.pod17
-rw-r--r--doc/man3/DH_new_by_nid.pod31
-rw-r--r--doc/man3/DH_set_method.pod15
-rw-r--r--doc/man3/DH_size.pod32
-rw-r--r--doc/man3/DSA_SIG_new.pod6
-rw-r--r--doc/man3/DSA_do_sign.pod16
-rw-r--r--doc/man3/DSA_dup_DH.pod16
-rw-r--r--doc/man3/DSA_generate_key.pod16
-rw-r--r--doc/man3/DSA_generate_parameters.pod20
-rw-r--r--doc/man3/DSA_get0_pqg.pod15
-rw-r--r--doc/man3/DSA_meth_new.pod17
-rw-r--r--doc/man3/DSA_new.pod16
-rw-r--r--doc/man3/DSA_set_method.pod19
-rw-r--r--doc/man3/DSA_sign.pod18
-rw-r--r--doc/man3/DSA_size.pod44
-rw-r--r--doc/man3/DTLS_get_data_mtu.pod2
-rw-r--r--doc/man3/DTLS_set_timer_cb.pod2
-rw-r--r--doc/man3/DTLSv1_listen.pod21
-rw-r--r--doc/man3/ECDSA_SIG_new.pod205
-rw-r--r--doc/man3/ECDSA_sign.pod186
-rw-r--r--doc/man3/ECPKParameters_print.pod15
-rw-r--r--doc/man3/EC_GFp_simple_method.pod26
-rw-r--r--doc/man3/EC_GROUP_copy.pod75
-rw-r--r--doc/man3/EC_GROUP_new.pod155
-rw-r--r--doc/man3/EC_KEY_get_enc_flags.pod2
-rw-r--r--doc/man3/EC_KEY_new.pod103
-rw-r--r--doc/man3/EC_POINT_add.pod32
-rw-r--r--doc/man3/EC_POINT_new.pod76
-rw-r--r--doc/man3/ENGINE_add.pod37
-rw-r--r--doc/man3/ERR_GET_LIB.pod38
-rw-r--r--doc/man3/ERR_clear_error.pod2
-rw-r--r--doc/man3/ERR_error_string.pod27
-rw-r--r--doc/man3/ERR_get_error.pod109
-rw-r--r--doc/man3/ERR_load_crypto_strings.pod12
-rw-r--r--doc/man3/ERR_load_strings.pod4
-rw-r--r--doc/man3/ERR_new.pod78
-rw-r--r--doc/man3/ERR_print_errors.pod6
-rw-r--r--doc/man3/ERR_put_error.pod160
-rw-r--r--doc/man3/ERR_remove_state.pod16
-rw-r--r--doc/man3/ERR_set_mark.pod15
-rw-r--r--doc/man3/EVP_ASYM_CIPHER_free.pod112
-rw-r--r--doc/man3/EVP_BytesToKey.pod2
-rw-r--r--doc/man3/EVP_CIPHER_CTX_get_cipher_data.pod2
-rw-r--r--doc/man3/EVP_CIPHER_CTX_get_original_iv.pod74
-rw-r--r--doc/man3/EVP_CIPHER_meth_new.pod34
-rw-r--r--doc/man3/EVP_DigestInit.pod539
-rw-r--r--doc/man3/EVP_DigestSignInit.pod131
-rw-r--r--doc/man3/EVP_DigestVerifyInit.pod126
-rw-r--r--doc/man3/EVP_EncodeInit.pod2
-rw-r--r--doc/man3/EVP_EncryptInit.pod1446
-rw-r--r--doc/man3/EVP_KDF.pod305
-rw-r--r--doc/man3/EVP_KEM_free.pod105
-rw-r--r--doc/man3/EVP_KEYEXCH_free.pod111
-rw-r--r--doc/man3/EVP_KEYMGMT.pod150
-rw-r--r--doc/man3/EVP_MAC.pod491
-rw-r--r--doc/man3/EVP_MD_meth_new.pod32
-rw-r--r--doc/man3/EVP_OpenInit.pod2
-rw-r--r--doc/man3/EVP_PBE_CipherInit.pod111
-rw-r--r--doc/man3/EVP_PKEY2PKCS8.pod47
-rw-r--r--doc/man3/EVP_PKEY_ASN1_METHOD.pod36
-rw-r--r--doc/man3/EVP_PKEY_CTX_ctrl.pod603
-rw-r--r--doc/man3/EVP_PKEY_CTX_get0_libctx.pod54
-rw-r--r--doc/man3/EVP_PKEY_CTX_get0_pkey.pod56
-rw-r--r--doc/man3/EVP_PKEY_CTX_new.pod98
-rw-r--r--doc/man3/EVP_PKEY_CTX_set1_pbe_pass.pod13
-rw-r--r--doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod21
-rw-r--r--doc/man3/EVP_PKEY_CTX_set_params.pod94
-rw-r--r--doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod29
-rw-r--r--doc/man3/EVP_PKEY_CTX_set_scrypt_N.pod18
-rw-r--r--doc/man3/EVP_PKEY_CTX_set_tls1_prf_md.pod11
-rw-r--r--doc/man3/EVP_PKEY_asn1_get_count.pod4
-rw-r--r--doc/man3/EVP_PKEY_check.pod96
-rw-r--r--doc/man3/EVP_PKEY_cmp.pod73
-rw-r--r--doc/man3/EVP_PKEY_copy_parameters.pod120
-rw-r--r--doc/man3/EVP_PKEY_decapsulate.pod99
-rw-r--r--doc/man3/EVP_PKEY_decrypt.pod40
-rw-r--r--doc/man3/EVP_PKEY_derive.pod61
-rw-r--r--doc/man3/EVP_PKEY_digestsign_supports_digest.pod44
-rw-r--r--doc/man3/EVP_PKEY_encapsulate.pod102
-rw-r--r--doc/man3/EVP_PKEY_encrypt.pod22
-rw-r--r--doc/man3/EVP_PKEY_fromdata.pod280
-rw-r--r--doc/man3/EVP_PKEY_get_default_digest_nid.pod42
-rw-r--r--doc/man3/EVP_PKEY_get_field_type.pod55
-rw-r--r--doc/man3/EVP_PKEY_get_group_name.pod46
-rw-r--r--doc/man3/EVP_PKEY_get_size.pod91
-rw-r--r--doc/man3/EVP_PKEY_gettable_params.pod136
-rw-r--r--doc/man3/EVP_PKEY_is_a.pod113
-rw-r--r--doc/man3/EVP_PKEY_keygen.pod116
-rw-r--r--doc/man3/EVP_PKEY_meth_get_count.pod15
-rw-r--r--doc/man3/EVP_PKEY_meth_new.pod28
-rw-r--r--doc/man3/EVP_PKEY_new.pod158
-rw-r--r--doc/man3/EVP_PKEY_print_private.pod34
-rw-r--r--doc/man3/EVP_PKEY_set1_RSA.pod189
-rw-r--r--doc/man3/EVP_PKEY_set1_encoded_public_key.pod142
-rw-r--r--doc/man3/EVP_PKEY_set_type.pod68
-rw-r--r--doc/man3/EVP_PKEY_settable_params.pod83
-rw-r--r--doc/man3/EVP_PKEY_sign.pod35
-rw-r--r--doc/man3/EVP_PKEY_size.pod80
-rw-r--r--doc/man3/EVP_PKEY_todata.pod64
-rw-r--r--doc/man3/EVP_PKEY_verify.pod29
-rw-r--r--doc/man3/EVP_PKEY_verify_recover.pod38
-rw-r--r--doc/man3/EVP_RAND.pod404
-rw-r--r--doc/man3/EVP_SIGNATURE.pod116
-rw-r--r--doc/man3/EVP_SealInit.pod8
-rw-r--r--doc/man3/EVP_SignInit.pod49
-rw-r--r--doc/man3/EVP_VerifyInit.pod42
-rw-r--r--doc/man3/EVP_aes.pod194
-rw-r--r--doc/man3/EVP_aes_128_gcm.pod194
-rw-r--r--doc/man3/EVP_aria.pod117
-rw-r--r--doc/man3/EVP_aria_128_gcm.pod117
-rw-r--r--doc/man3/EVP_bf_cbc.pod15
-rw-r--r--doc/man3/EVP_blake2b512.pod6
-rw-r--r--doc/man3/EVP_camellia.pod100
-rw-r--r--doc/man3/EVP_camellia_128_ecb.pod100
-rw-r--r--doc/man3/EVP_cast5_cbc.pod15
-rw-r--r--doc/man3/EVP_chacha20.pod8
-rw-r--r--doc/man3/EVP_des.pod106
-rw-r--r--doc/man3/EVP_des_cbc.pod110
-rw-r--r--doc/man3/EVP_desx_cbc.pod10
-rw-r--r--doc/man3/EVP_idea_cbc.pod15
-rw-r--r--doc/man3/EVP_md2.pod9
-rw-r--r--doc/man3/EVP_md4.pod10
-rw-r--r--doc/man3/EVP_md5.pod6
-rw-r--r--doc/man3/EVP_mdc2.pod10
-rw-r--r--doc/man3/EVP_rc2_cbc.pod18
-rw-r--r--doc/man3/EVP_rc4.pod11
-rw-r--r--doc/man3/EVP_rc5_32_12_16_cbc.pod15
-rw-r--r--doc/man3/EVP_ripemd160.pod8
-rw-r--r--doc/man3/EVP_seed_cbc.pod15
-rw-r--r--doc/man3/EVP_set_default_properties.pod71
-rw-r--r--doc/man3/EVP_sha1.pod6
-rw-r--r--doc/man3/EVP_sha224.pod6
-rw-r--r--doc/man3/EVP_sha3_224.pod6
-rw-r--r--doc/man3/EVP_sm3.pod6
-rw-r--r--doc/man3/EVP_sm4_cbc.pod2
-rw-r--r--doc/man3/EVP_whirlpool.pod10
-rw-r--r--doc/man3/HMAC.pod70
-rw-r--r--doc/man3/MD5.pod30
-rw-r--r--doc/man3/MDC2_Init.pod16
-rw-r--r--doc/man3/NCONF_new_ex.pod84
-rw-r--r--doc/man3/OBJ_nid2obj.pod34
-rw-r--r--doc/man3/OCSP_REQUEST_new.pod6
-rw-r--r--doc/man3/OCSP_cert_to_id.pod4
-rw-r--r--doc/man3/OCSP_request_add1_nonce.pod2
-rw-r--r--doc/man3/OCSP_resp_find_status.pod171
-rw-r--r--doc/man3/OCSP_response_status.pod76
-rw-r--r--doc/man3/OCSP_sendreq_new.pod170
-rw-r--r--doc/man3/OPENSSL_Applink.pod2
-rw-r--r--doc/man3/OPENSSL_FILE.pod56
-rw-r--r--doc/man3/OPENSSL_LH_COMPFUNC.pod131
-rw-r--r--doc/man3/OPENSSL_LH_stats.pod11
-rw-r--r--doc/man3/OPENSSL_VERSION_NUMBER.pod113
-rw-r--r--doc/man3/OPENSSL_config.pod10
-rw-r--r--doc/man3/OPENSSL_fork_prepare.pod11
-rw-r--r--doc/man3/OPENSSL_gmtime.pod62
-rw-r--r--doc/man3/OPENSSL_hexchar2int.pod81
-rw-r--r--doc/man3/OPENSSL_ia32cap.pod50
-rw-r--r--doc/man3/OPENSSL_init_crypto.pod67
-rw-r--r--doc/man3/OPENSSL_init_ssl.pod2
-rw-r--r--doc/man3/OPENSSL_instrument_bus.pod8
-rw-r--r--doc/man3/OPENSSL_load_builtin_modules.pod8
-rw-r--r--doc/man3/OPENSSL_malloc.pod191
-rw-r--r--doc/man3/OPENSSL_s390xcap.pod199
-rw-r--r--doc/man3/OPENSSL_secure_malloc.pod15
-rw-r--r--doc/man3/OPENSSL_strcasecmp.pod47
-rw-r--r--doc/man3/OSSL_ALGORITHM.pod151
-rw-r--r--doc/man3/OSSL_CALLBACK.pod77
-rw-r--r--doc/man3/OSSL_CMP_CTX_new.pod802
-rw-r--r--doc/man3/OSSL_CMP_HDR_get0_transactionID.pod47
-rw-r--r--doc/man3/OSSL_CMP_ITAV_set0.pod111
-rw-r--r--doc/man3/OSSL_CMP_MSG_get0_header.pod147
-rw-r--r--doc/man3/OSSL_CMP_MSG_http_perform.pod60
-rw-r--r--doc/man3/OSSL_CMP_SRV_CTX_new.pod168
-rw-r--r--doc/man3/OSSL_CMP_STATUSINFO_new.pod66
-rw-r--r--doc/man3/OSSL_CMP_exec_certreq.pod173
-rw-r--r--doc/man3/OSSL_CMP_log_open.pod124
-rw-r--r--doc/man3/OSSL_CMP_validate_msg.pod84
-rw-r--r--doc/man3/OSSL_CORE_MAKE_FUNC.pod43
-rw-r--r--doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod98
-rw-r--r--doc/man3/OSSL_CRMF_MSG_set0_validity.pod120
-rw-r--r--doc/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod131
-rw-r--r--doc/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod68
-rw-r--r--doc/man3/OSSL_CRMF_pbmp_new.pod92
-rw-r--r--doc/man3/OSSL_DECODER.pod190
-rw-r--r--doc/man3/OSSL_DECODER_CTX.pod259
-rw-r--r--doc/man3/OSSL_DECODER_CTX_new_for_pkey.pod145
-rw-r--r--doc/man3/OSSL_DECODER_from_bio.pod120
-rw-r--r--doc/man3/OSSL_DISPATCH.pod81
-rw-r--r--doc/man3/OSSL_ENCODER.pod144
-rw-r--r--doc/man3/OSSL_ENCODER_CTX.pod221
-rw-r--r--doc/man3/OSSL_ENCODER_CTX_new_for_pkey.pod146
-rw-r--r--doc/man3/OSSL_ENCODER_to_bio.pod133
-rw-r--r--doc/man3/OSSL_ESS_check_signing_certs.pod88
-rw-r--r--doc/man3/OSSL_HTTP_REQ_CTX.pod266
-rw-r--r--doc/man3/OSSL_HTTP_parse_url.pod107
-rw-r--r--doc/man3/OSSL_HTTP_transfer.pod284
-rw-r--r--doc/man3/OSSL_ITEM.pod56
-rw-r--r--doc/man3/OSSL_LIB_CTX.pod136
-rw-r--r--doc/man3/OSSL_PARAM.pod366
-rw-r--r--doc/man3/OSSL_PARAM_BLD.pod203
-rw-r--r--doc/man3/OSSL_PARAM_allocate_from_text.pod207
-rw-r--r--doc/man3/OSSL_PARAM_dup.pod59
-rw-r--r--doc/man3/OSSL_PARAM_int.pod413
-rw-r--r--doc/man3/OSSL_PROVIDER.pod223
-rw-r--r--doc/man3/OSSL_SELF_TEST_new.pod175
-rw-r--r--doc/man3/OSSL_SELF_TEST_set_callback.pod52
-rw-r--r--doc/man3/OSSL_STORE_INFO.pod107
-rw-r--r--doc/man3/OSSL_STORE_LOADER.pod266
-rw-r--r--doc/man3/OSSL_STORE_SEARCH.pod16
-rw-r--r--doc/man3/OSSL_STORE_attach.pod47
-rw-r--r--doc/man3/OSSL_STORE_expect.pod16
-rw-r--r--doc/man3/OSSL_STORE_open.pod72
-rw-r--r--doc/man3/OSSL_trace_enabled.pod292
-rw-r--r--doc/man3/OSSL_trace_get_category_num.pod44
-rw-r--r--doc/man3/OSSL_trace_set_channel.pod332
-rw-r--r--doc/man3/OpenSSL_add_all_algorithms.pod12
-rw-r--r--doc/man3/OpenSSL_version.pod250
-rw-r--r--doc/man3/PEM_X509_INFO_read_bio_ex.pod83
-rw-r--r--doc/man3/PEM_bytes_read_bio.pod2
-rw-r--r--doc/man3/PEM_read.pod8
-rw-r--r--doc/man3/PEM_read_CMS.pod79
-rw-r--r--doc/man3/PEM_read_bio_PrivateKey.pod265
-rw-r--r--doc/man3/PEM_read_bio_ex.pod2
-rw-r--r--doc/man3/PEM_write_bio_CMS_stream.pod2
-rw-r--r--doc/man3/PEM_write_bio_PKCS7_stream.pod2
-rw-r--r--doc/man3/PKCS12_PBE_keyivgen.pod108
-rw-r--r--doc/man3/PKCS12_SAFEBAG_create_cert.pod100
-rw-r--r--doc/man3/PKCS12_SAFEBAG_get0_attrs.pod50
-rw-r--r--doc/man3/PKCS12_SAFEBAG_get1_cert.pod74
-rw-r--r--doc/man3/PKCS12_add1_attr_by_NID.pod52
-rw-r--r--doc/man3/PKCS12_add_CSPName_asc.pod36
-rw-r--r--doc/man3/PKCS12_add_cert.pod81
-rw-r--r--doc/man3/PKCS12_add_friendlyname_asc.pod52
-rw-r--r--doc/man3/PKCS12_add_localkeyid.pod38
-rw-r--r--doc/man3/PKCS12_add_safe.pod87
-rw-r--r--doc/man3/PKCS12_create.pod60
-rw-r--r--doc/man3/PKCS12_decrypt_skey.pod55
-rw-r--r--doc/man3/PKCS12_gen_mac.pod72
-rw-r--r--doc/man3/PKCS12_get_friendlyname.pod39
-rw-r--r--doc/man3/PKCS12_init.pod48
-rw-r--r--doc/man3/PKCS12_item_decrypt_d2i.pod73
-rw-r--r--doc/man3/PKCS12_key_gen_utf8_ex.pod138
-rw-r--r--doc/man3/PKCS12_newpass.pod26
-rw-r--r--doc/man3/PKCS12_pack_p7encdata.pod59
-rw-r--r--doc/man3/PKCS12_parse.pod16
-rw-r--r--doc/man3/PKCS5_PBE_keyivgen.pod177
-rw-r--r--doc/man3/PKCS5_PBKDF2_HMAC.pod9
-rw-r--r--doc/man3/PKCS7_decrypt.pod2
-rw-r--r--doc/man3/PKCS7_encrypt.pod31
-rw-r--r--doc/man3/PKCS7_get_octet_string.pod40
-rw-r--r--doc/man3/PKCS7_sign.pod25
-rw-r--r--doc/man3/PKCS7_sign_add_signer.pod2
-rw-r--r--doc/man3/PKCS7_type_is_other.pod42
-rw-r--r--doc/man3/PKCS7_verify.pod4
-rw-r--r--doc/man3/PKCS8_encrypt.pod78
-rw-r--r--doc/man3/PKCS8_pkey_add1_attr.pod54
-rw-r--r--doc/man3/RAND_DRBG_generate.pod88
-rw-r--r--doc/man3/RAND_DRBG_get0_master.pod79
-rw-r--r--doc/man3/RAND_DRBG_new.pod127
-rw-r--r--doc/man3/RAND_DRBG_reseed.pod116
-rw-r--r--doc/man3/RAND_DRBG_set_callbacks.pod146
-rw-r--r--doc/man3/RAND_DRBG_set_ex_data.pod68
-rw-r--r--doc/man3/RAND_add.pod19
-rw-r--r--doc/man3/RAND_bytes.pod37
-rw-r--r--doc/man3/RAND_cleanup.pod12
-rw-r--r--doc/man3/RAND_egd.pod2
-rw-r--r--doc/man3/RAND_get0_primary.pod82
-rw-r--r--doc/man3/RAND_load_file.pod2
-rw-r--r--doc/man3/RAND_set_DRBG_type.pod64
-rw-r--r--doc/man3/RAND_set_rand_method.pod22
-rw-r--r--doc/man3/RC4_set_key.pod16
-rw-r--r--doc/man3/RIPEMD160_Init.pod16
-rw-r--r--doc/man3/RSA_blinding_on.pod14
-rw-r--r--doc/man3/RSA_check_key.pod18
-rw-r--r--doc/man3/RSA_generate_key.pod65
-rw-r--r--doc/man3/RSA_get0_key.pod17
-rw-r--r--doc/man3/RSA_meth_new.pod16
-rw-r--r--doc/man3/RSA_new.pod13
-rw-r--r--doc/man3/RSA_padding_add_PKCS1_type_1.pod26
-rw-r--r--doc/man3/RSA_print.pod47
-rw-r--r--doc/man3/RSA_private_encrypt.pod20
-rw-r--r--doc/man3/RSA_public_encrypt.pod22
-rw-r--r--doc/man3/RSA_set_method.pod21
-rw-r--r--doc/man3/RSA_sign.pod20
-rw-r--r--doc/man3/RSA_sign_ASN1_OCTET_STRING.pod15
-rw-r--r--doc/man3/RSA_size.pod32
-rw-r--r--doc/man3/SCT_new.pod7
-rw-r--r--doc/man3/SCT_print.pod8
-rw-r--r--doc/man3/SCT_validate.pod2
-rw-r--r--doc/man3/SHA256_Init.pod40
-rw-r--r--doc/man3/SMIME_read_ASN1.pod86
-rw-r--r--doc/man3/SMIME_read_CMS.pod33
-rw-r--r--doc/man3/SMIME_read_PKCS7.pod20
-rw-r--r--doc/man3/SMIME_write_ASN1.pod82
-rw-r--r--doc/man3/SMIME_write_CMS.pod2
-rw-r--r--doc/man3/SMIME_write_PKCS7.pod2
-rw-r--r--doc/man3/SRP_Calc_B.pod100
-rw-r--r--doc/man3/SRP_VBASE_new.pod108
-rw-r--r--doc/man3/SRP_create_verifier.pod139
-rw-r--r--doc/man3/SRP_user_pwd_new.pod77
-rw-r--r--doc/man3/SSL_CIPHER_get_name.pod10
-rw-r--r--doc/man3/SSL_COMP_add_compression_method.pod12
-rw-r--r--doc/man3/SSL_CONF_CTX_new.pod3
-rw-r--r--doc/man3/SSL_CONF_CTX_set1_prefix.pod3
-rw-r--r--doc/man3/SSL_CONF_CTX_set_flags.pod3
-rw-r--r--doc/man3/SSL_CONF_CTX_set_ssl_ctx.pod3
-rw-r--r--doc/man3/SSL_CONF_cmd.pod361
-rw-r--r--doc/man3/SSL_CONF_cmd_argv.pod3
-rw-r--r--doc/man3/SSL_CTX_add1_chain_cert.pod12
-rw-r--r--doc/man3/SSL_CTX_add_extra_chain_cert.pod22
-rw-r--r--doc/man3/SSL_CTX_add_session.pod2
-rw-r--r--doc/man3/SSL_CTX_config.pod7
-rw-r--r--doc/man3/SSL_CTX_ctrl.pod2
-rw-r--r--doc/man3/SSL_CTX_dane_enable.pod11
-rw-r--r--doc/man3/SSL_CTX_flush_sessions.pod2
-rw-r--r--doc/man3/SSL_CTX_free.pod2
-rw-r--r--doc/man3/SSL_CTX_get0_param.pod35
-rw-r--r--doc/man3/SSL_CTX_get_verify_mode.pod2
-rw-r--r--doc/man3/SSL_CTX_has_client_custom_ext.pod2
-rw-r--r--doc/man3/SSL_CTX_load_verify_locations.pod70
-rw-r--r--doc/man3/SSL_CTX_new.pod77
-rw-r--r--doc/man3/SSL_CTX_sess_number.pod2
-rw-r--r--doc/man3/SSL_CTX_sess_set_cache_size.pod2
-rw-r--r--doc/man3/SSL_CTX_sess_set_get_cb.pod2
-rw-r--r--doc/man3/SSL_CTX_sessions.pod6
-rw-r--r--doc/man3/SSL_CTX_set0_CA_list.pod4
-rw-r--r--doc/man3/SSL_CTX_set1_curves.pod53
-rw-r--r--doc/man3/SSL_CTX_set1_sigalgs.pod4
-rw-r--r--doc/man3/SSL_CTX_set1_verify_cert_store.pod6
-rw-r--r--doc/man3/SSL_CTX_set_alpn_select_cb.pod4
-rw-r--r--doc/man3/SSL_CTX_set_cert_cb.pod20
-rw-r--r--doc/man3/SSL_CTX_set_cert_store.pod2
-rw-r--r--doc/man3/SSL_CTX_set_cert_verify_callback.pod62
-rw-r--r--doc/man3/SSL_CTX_set_cipher_list.pod39
-rw-r--r--doc/man3/SSL_CTX_set_client_cert_cb.pod21
-rw-r--r--doc/man3/SSL_CTX_set_client_hello_cb.pod10
-rw-r--r--doc/man3/SSL_CTX_set_ct_validation_callback.pod6
-rw-r--r--doc/man3/SSL_CTX_set_ctlog_list_file.pod6
-rw-r--r--doc/man3/SSL_CTX_set_default_passwd_cb.pod2
-rw-r--r--doc/man3/SSL_CTX_set_ex_data.pod52
-rw-r--r--doc/man3/SSL_CTX_set_generate_session_id.pod6
-rw-r--r--doc/man3/SSL_CTX_set_info_callback.pod4
-rw-r--r--doc/man3/SSL_CTX_set_keylog_callback.pod6
-rw-r--r--doc/man3/SSL_CTX_set_max_cert_list.pod2
-rw-r--r--doc/man3/SSL_CTX_set_min_proto_version.pod3
-rw-r--r--doc/man3/SSL_CTX_set_mode.pod16
-rw-r--r--doc/man3/SSL_CTX_set_msg_callback.pod2
-rw-r--r--doc/man3/SSL_CTX_set_num_tickets.pod42
-rw-r--r--doc/man3/SSL_CTX_set_options.pod292
-rw-r--r--doc/man3/SSL_CTX_set_psk_client_callback.pod13
-rw-r--r--doc/man3/SSL_CTX_set_quiet_shutdown.pod2
-rw-r--r--doc/man3/SSL_CTX_set_read_ahead.pod2
-rw-r--r--doc/man3/SSL_CTX_set_record_padding_callback.pod14
-rw-r--r--doc/man3/SSL_CTX_set_security_level.pod21
-rw-r--r--doc/man3/SSL_CTX_set_session_cache_mode.pod9
-rw-r--r--doc/man3/SSL_CTX_set_session_id_context.pod2
-rw-r--r--doc/man3/SSL_CTX_set_session_ticket_cb.pod6
-rw-r--r--doc/man3/SSL_CTX_set_split_send_fragment.pod7
-rw-r--r--doc/man3/SSL_CTX_set_srp_password.pod224
-rw-r--r--doc/man3/SSL_CTX_set_ssl_version.pod33
-rw-r--r--doc/man3/SSL_CTX_set_stateless_cookie_generate_cb.pod3
-rw-r--r--doc/man3/SSL_CTX_set_timeout.pod2
-rw-r--r--doc/man3/SSL_CTX_set_tlsext_servername_callback.pod2
-rw-r--r--doc/man3/SSL_CTX_set_tlsext_status_cb.pod6
-rw-r--r--doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod80
-rw-r--r--doc/man3/SSL_CTX_set_tlsext_use_srtp.pod3
-rw-r--r--doc/man3/SSL_CTX_set_tmp_dh_callback.pod161
-rw-r--r--doc/man3/SSL_CTX_set_tmp_ecdh.pod50
-rw-r--r--doc/man3/SSL_CTX_set_verify.pod21
-rw-r--r--doc/man3/SSL_CTX_use_certificate.pod29
-rw-r--r--doc/man3/SSL_CTX_use_psk_identity_hint.pod5
-rw-r--r--doc/man3/SSL_CTX_use_serverinfo.pod8
-rw-r--r--doc/man3/SSL_SESSION_free.pod4
-rw-r--r--doc/man3/SSL_SESSION_get0_cipher.pod2
-rw-r--r--doc/man3/SSL_SESSION_get0_hostname.pod2
-rw-r--r--doc/man3/SSL_SESSION_get0_id_context.pod6
-rw-r--r--doc/man3/SSL_SESSION_get0_peer.pod2
-rw-r--r--doc/man3/SSL_SESSION_get_compress_id.pod2
-rw-r--r--doc/man3/SSL_SESSION_get_ex_data.pod47
-rw-r--r--doc/man3/SSL_SESSION_get_protocol_version.pod2
-rw-r--r--doc/man3/SSL_SESSION_get_time.pod2
-rw-r--r--doc/man3/SSL_SESSION_has_ticket.pod2
-rw-r--r--doc/man3/SSL_SESSION_is_resumable.pod2
-rw-r--r--doc/man3/SSL_SESSION_print.pod2
-rw-r--r--doc/man3/SSL_SESSION_set1_id.pod6
-rw-r--r--doc/man3/SSL_accept.pod2
-rw-r--r--doc/man3/SSL_alert_type_string.pod2
-rw-r--r--doc/man3/SSL_alloc_buffers.pod5
-rw-r--r--doc/man3/SSL_check_chain.pod2
-rw-r--r--doc/man3/SSL_clear.pod2
-rw-r--r--doc/man3/SSL_connect.pod2
-rw-r--r--doc/man3/SSL_do_handshake.pod2
-rw-r--r--doc/man3/SSL_export_keying_material.pod6
-rw-r--r--doc/man3/SSL_extension_supported.pod47
-rw-r--r--doc/man3/SSL_free.pod2
-rw-r--r--doc/man3/SSL_get0_peer_scts.pod2
-rw-r--r--doc/man3/SSL_get_SSL_CTX.pod2
-rw-r--r--doc/man3/SSL_get_all_async_fds.pod43
-rw-r--r--doc/man3/SSL_get_certificate.pod73
-rw-r--r--doc/man3/SSL_get_ciphers.pod2
-rw-r--r--doc/man3/SSL_get_client_random.pod2
-rw-r--r--doc/man3/SSL_get_current_cipher.pod2
-rw-r--r--doc/man3/SSL_get_default_timeout.pod2
-rw-r--r--doc/man3/SSL_get_error.pod32
-rw-r--r--doc/man3/SSL_get_extms_support.pod2
-rw-r--r--doc/man3/SSL_get_fd.pod2
-rw-r--r--doc/man3/SSL_get_peer_cert_chain.pod2
-rw-r--r--doc/man3/SSL_get_peer_certificate.pod29
-rw-r--r--doc/man3/SSL_get_peer_signature_nid.pod2
-rw-r--r--doc/man3/SSL_get_peer_tmp_key.pod2
-rw-r--r--doc/man3/SSL_get_psk_identity.pod6
-rw-r--r--doc/man3/SSL_get_rbio.pod2
-rw-r--r--doc/man3/SSL_get_session.pod2
-rw-r--r--doc/man3/SSL_get_shared_sigalgs.pod2
-rw-r--r--doc/man3/SSL_get_verify_result.pod6
-rw-r--r--doc/man3/SSL_get_version.pod2
-rw-r--r--doc/man3/SSL_group_to_name.pod43
-rw-r--r--doc/man3/SSL_in_init.pod2
-rw-r--r--doc/man3/SSL_key_update.pod13
-rw-r--r--doc/man3/SSL_library_init.pod4
-rw-r--r--doc/man3/SSL_load_client_CA_file.pod36
-rw-r--r--doc/man3/SSL_new.pod6
-rw-r--r--doc/man3/SSL_pending.pod2
-rw-r--r--doc/man3/SSL_read.pod2
-rw-r--r--doc/man3/SSL_read_early_data.pod4
-rw-r--r--doc/man3/SSL_rstate_string.pod2
-rw-r--r--doc/man3/SSL_session_reused.pod4
-rw-r--r--doc/man3/SSL_set1_host.pod7
-rw-r--r--doc/man3/SSL_set_async_callback.pod131
-rw-r--r--doc/man3/SSL_set_bio.pod10
-rw-r--r--doc/man3/SSL_set_connect_state.pod2
-rw-r--r--doc/man3/SSL_set_fd.pod2
-rw-r--r--doc/man3/SSL_set_retry_verify.pod70
-rw-r--r--doc/man3/SSL_set_session.pod7
-rw-r--r--doc/man3/SSL_set_shutdown.pod6
-rw-r--r--doc/man3/SSL_set_verify_result.pod6
-rw-r--r--doc/man3/SSL_shutdown.pod82
-rw-r--r--doc/man3/SSL_state_string.pod10
-rw-r--r--doc/man3/SSL_want.pod40
-rw-r--r--doc/man3/SSL_write.pod36
-rw-r--r--doc/man3/TS_RESP_CTX_new.pod49
-rw-r--r--doc/man3/TS_VERIFY_CTX_set_certs.pod61
-rw-r--r--doc/man3/UI_STRING.pod2
-rw-r--r--doc/man3/UI_UTIL_read_pw.pod4
-rw-r--r--doc/man3/UI_create_method.pod2
-rw-r--r--doc/man3/UI_new.pod18
-rw-r--r--doc/man3/X509V3_get_d2i.pod107
-rw-r--r--doc/man3/X509V3_set_ctx.pod67
-rw-r--r--doc/man3/X509_ALGOR_dup.pod2
-rw-r--r--doc/man3/X509_CRL_get0_by_serial.pod54
-rw-r--r--doc/man3/X509_EXTENSION_set_object.pod2
-rw-r--r--doc/man3/X509_LOOKUP.pod162
-rw-r--r--doc/man3/X509_LOOKUP_hash_dir.pod55
-rw-r--r--doc/man3/X509_LOOKUP_meth_new.pod8
-rw-r--r--doc/man3/X509_NAME_ENTRY_get_object.pod2
-rw-r--r--doc/man3/X509_NAME_add_entry_by_txt.pod18
-rw-r--r--doc/man3/X509_NAME_get0_der.pod8
-rw-r--r--doc/man3/X509_NAME_get_index_by_NID.pod22
-rw-r--r--doc/man3/X509_NAME_print_ex.pod79
-rw-r--r--doc/man3/X509_PUBKEY_new.pod100
-rw-r--r--doc/man3/X509_SIG_get0.pod6
-rw-r--r--doc/man3/X509_STORE_CTX_get_error.pod333
-rw-r--r--doc/man3/X509_STORE_CTX_new.pod146
-rw-r--r--doc/man3/X509_STORE_CTX_set_verify_cb.pod18
-rw-r--r--doc/man3/X509_STORE_add_cert.pod87
-rw-r--r--doc/man3/X509_STORE_get0_param.pod22
-rw-r--r--doc/man3/X509_STORE_new.pod9
-rw-r--r--doc/man3/X509_STORE_set_verify_cb_func.pod87
-rw-r--r--doc/man3/X509_VERIFY_PARAM_set_flags.pod79
-rw-r--r--doc/man3/X509_add_cert.pod76
-rw-r--r--doc/man3/X509_check_ca.pod9
-rw-r--r--doc/man3/X509_check_host.pod22
-rw-r--r--doc/man3/X509_check_issued.pod16
-rw-r--r--doc/man3/X509_check_private_key.pod2
-rw-r--r--doc/man3/X509_check_purpose.pod10
-rw-r--r--doc/man3/X509_cmp.pod24
-rw-r--r--doc/man3/X509_cmp_time.pod63
-rw-r--r--doc/man3/X509_digest.pod42
-rw-r--r--doc/man3/X509_dup.pod115
-rw-r--r--doc/man3/X509_get0_distinguishing_id.pod73
-rw-r--r--doc/man3/X509_get0_notBefore.pod2
-rw-r--r--doc/man3/X509_get0_signature.pod8
-rw-r--r--doc/man3/X509_get0_uids.pod2
-rw-r--r--doc/man3/X509_get_extension_flags.pod4
-rw-r--r--doc/man3/X509_get_pubkey.pod6
-rw-r--r--doc/man3/X509_get_serialNumber.pod2
-rw-r--r--doc/man3/X509_get_subject_name.pod72
-rw-r--r--doc/man3/X509_get_version.pod14
-rw-r--r--doc/man3/X509_load_http.pod68
-rw-r--r--doc/man3/X509_new.pod35
-rw-r--r--doc/man3/X509_sign.pod57
-rw-r--r--doc/man3/X509_verify.pod83
-rw-r--r--doc/man3/X509_verify_cert.pod89
-rw-r--r--doc/man3/X509v3_get_ext_by_NID.pod78
-rw-r--r--doc/man3/b2i_PVK_bio_ex.pod69
-rw-r--r--doc/man3/d2i_DHparams.pod42
-rw-r--r--doc/man3/d2i_PKCS8PrivateKey_bio.pod10
-rw-r--r--doc/man3/d2i_PrivateKey.pod102
-rw-r--r--doc/man3/d2i_RSAPrivateKey.pod319
-rw-r--r--doc/man3/d2i_SSL_SESSION.pod2
-rw-r--r--doc/man3/d2i_X509.pod207
-rw-r--r--doc/man3/i2d_CMS_bio_stream.pod2
-rw-r--r--doc/man3/i2d_PKCS7_bio_stream.pod2
-rw-r--r--doc/man3/i2d_re_X509_tbs.pod8
-rw-r--r--doc/man3/o2i_SCT_LIST.pod6
-rw-r--r--doc/man3/s2i_ASN1_IA5STRING.pod99
-rw-r--r--doc/man5/config.pod742
-rw-r--r--doc/man5/fips_config.pod123
-rw-r--r--doc/man5/x509v3_config.pod594
-rw-r--r--doc/man7/EVP_ASYM_CIPHER-RSA.pod90
-rw-r--r--doc/man7/EVP_ASYM_CIPHER-SM2.pod41
-rw-r--r--doc/man7/EVP_CIPHER-AES.pod77
-rw-r--r--doc/man7/EVP_CIPHER-ARIA.pod55
-rw-r--r--doc/man7/EVP_CIPHER-BLOWFISH.pod46
-rw-r--r--doc/man7/EVP_CIPHER-CAMELLIA.pod51
-rw-r--r--doc/man7/EVP_CIPHER-CAST.pod45
-rw-r--r--doc/man7/EVP_CIPHER-CHACHA.pod41
-rw-r--r--doc/man7/EVP_CIPHER-DES.pod78
-rw-r--r--doc/man7/EVP_CIPHER-IDEA.pod45
-rw-r--r--doc/man7/EVP_CIPHER-RC2.pod49
-rw-r--r--doc/man7/EVP_CIPHER-RC4.pod43
-rw-r--r--doc/man7/EVP_CIPHER-RC5.pod47
-rw-r--r--doc/man7/EVP_CIPHER-SEED.pod45
-rw-r--r--doc/man7/EVP_CIPHER-SM4.pod47
-rw-r--r--doc/man7/EVP_KDF-HKDF.pod156
-rw-r--r--doc/man7/EVP_KDF-KB.pod172
-rw-r--r--doc/man7/EVP_KDF-KRB5KDF.pod115
-rw-r--r--doc/man7/EVP_KDF-PBKDF1.pod82
-rw-r--r--doc/man7/EVP_KDF-PBKDF2.pod104
-rw-r--r--doc/man7/EVP_KDF-PKCS12KDF.pod86
-rw-r--r--doc/man7/EVP_KDF-SCRYPT.pod150
-rw-r--r--doc/man7/EVP_KDF-SS.pod188
-rw-r--r--doc/man7/EVP_KDF-SSHKDF.pod161
-rw-r--r--doc/man7/EVP_KDF-TLS13_KDF.pod132
-rw-r--r--doc/man7/EVP_KDF-TLS1_PRF.pod114
-rw-r--r--doc/man7/EVP_KDF-X942-ASN1.pod151
-rw-r--r--doc/man7/EVP_KDF-X942-CONCAT.pod35
-rw-r--r--doc/man7/EVP_KDF-X963.pod108
-rw-r--r--doc/man7/EVP_KEM-RSA.pod70
-rw-r--r--doc/man7/EVP_KEYEXCH-DH.pod132
-rw-r--r--doc/man7/EVP_KEYEXCH-ECDH.pod117
-rw-r--r--doc/man7/EVP_KEYEXCH-X25519.pod50
-rw-r--r--doc/man7/EVP_MAC-BLAKE2.pod90
-rw-r--r--doc/man7/EVP_MAC-CMAC.pod86
-rw-r--r--doc/man7/EVP_MAC-GMAC.pod83
-rw-r--r--doc/man7/EVP_MAC-HMAC.pod100
-rw-r--r--doc/man7/EVP_MAC-KMAC.pod152
-rw-r--r--doc/man7/EVP_MAC-Poly1305.pod73
-rw-r--r--doc/man7/EVP_MAC-Siphash.pod68
-rw-r--r--doc/man7/EVP_MD-BLAKE2.pod46
-rw-r--r--doc/man7/EVP_MD-MD2.pod34
-rw-r--r--doc/man7/EVP_MD-MD4.pod34
-rw-r--r--doc/man7/EVP_MD-MD5-SHA1.pod56
-rw-r--r--doc/man7/EVP_MD-MD5.pod34
-rw-r--r--doc/man7/EVP_MD-MDC2.pod50
-rw-r--r--doc/man7/EVP_MD-RIPEMD160.pod39
-rw-r--r--doc/man7/EVP_MD-SHA1.pod55
-rw-r--r--doc/man7/EVP_MD-SHA2.pod77
-rw-r--r--doc/man7/EVP_MD-SHA3.pod46
-rw-r--r--doc/man7/EVP_MD-SHAKE.pod83
-rw-r--r--doc/man7/EVP_MD-SM3.pod34
-rw-r--r--doc/man7/EVP_MD-WHIRLPOOL.pod34
-rw-r--r--doc/man7/EVP_MD-common.pod62
-rw-r--r--doc/man7/EVP_PKEY-DH.pod337
-rw-r--r--doc/man7/EVP_PKEY-DSA.pod123
-rw-r--r--doc/man7/EVP_PKEY-EC.pod282
-rw-r--r--doc/man7/EVP_PKEY-FFC.pod232
-rw-r--r--doc/man7/EVP_PKEY-HMAC.pod95
-rw-r--r--doc/man7/EVP_PKEY-RSA.pod274
-rw-r--r--doc/man7/EVP_PKEY-SM2.pod94
-rw-r--r--doc/man7/EVP_PKEY-X25519.pod106
-rw-r--r--doc/man7/EVP_RAND-CTR-DRBG.pod107
-rw-r--r--doc/man7/EVP_RAND-HASH-DRBG.pod100
-rw-r--r--doc/man7/EVP_RAND-HMAC-DRBG.pod103
-rw-r--r--doc/man7/EVP_RAND-SEED-SRC.pod87
-rw-r--r--doc/man7/EVP_RAND-TEST-RAND.pod116
-rw-r--r--doc/man7/EVP_RAND.pod306
-rw-r--r--doc/man7/EVP_SIGNATURE-DSA.pod58
-rw-r--r--doc/man7/EVP_SIGNATURE-ECDSA.pod57
-rw-r--r--doc/man7/EVP_SIGNATURE-ED25519.pod102
-rw-r--r--doc/man7/EVP_SIGNATURE-HMAC.pod49
-rw-r--r--doc/man7/EVP_SIGNATURE-RSA.pod112
-rw-r--r--doc/man7/Ed25519.pod87
-rw-r--r--doc/man7/OSSL_PROVIDER-FIPS.pod419
-rw-r--r--doc/man7/OSSL_PROVIDER-base.pod100
-rw-r--r--doc/man7/OSSL_PROVIDER-default.pod261
-rw-r--r--doc/man7/OSSL_PROVIDER-legacy.pod131
-rw-r--r--doc/man7/OSSL_PROVIDER-null.pod39
-rw-r--r--doc/man7/RAND.pod43
-rw-r--r--doc/man7/RAND_DRBG.pod301
-rw-r--r--doc/man7/RSA-PSS.pod2
-rw-r--r--doc/man7/SM2.pod79
-rw-r--r--doc/man7/X25519.pod2
-rw-r--r--doc/man7/bio.pod17
-rw-r--r--doc/man7/crypto.pod508
-rw-r--r--doc/man7/ct.pod2
-rw-r--r--doc/man7/des_modes.pod2
-rw-r--r--doc/man7/evp.pod14
-rw-r--r--doc/man7/fips_module.pod477
-rw-r--r--doc/man7/img/cipher.pngbin0 -> 81349 bytes
-rw-r--r--doc/man7/img/digest.pngbin0 -> 56894 bytes
-rw-r--r--doc/man7/img/kdf.pngbin0 -> 22285 bytes
-rw-r--r--doc/man7/img/mac.pngbin0 -> 42741 bytes
-rw-r--r--doc/man7/img/pkey.pngbin0 -> 148963 bytes
-rw-r--r--doc/man7/img/rand.pngbin0 -> 30526 bytes
-rw-r--r--doc/man7/life_cycle-cipher.pod370
-rw-r--r--doc/man7/life_cycle-digest.pod221
-rw-r--r--doc/man7/life_cycle-kdf.pod165
-rw-r--r--doc/man7/life_cycle-mac.pod218
-rw-r--r--doc/man7/life_cycle-pkey.pod713
-rw-r--r--doc/man7/life_cycle-rand.pod193
-rw-r--r--doc/man7/migration_guide.pod2432
-rw-r--r--doc/man7/openssl-core.h.pod54
-rw-r--r--doc/man7/openssl-core_dispatch.h.pod56
-rw-r--r--doc/man7/openssl-core_names.h.pod49
-rw-r--r--doc/man7/openssl-env.pod101
-rw-r--r--doc/man7/openssl-glossary.pod231
-rw-r--r--doc/man7/openssl-threads.pod105
-rw-r--r--doc/man7/openssl_user_macros.pod.in102
-rw-r--r--doc/man7/ossl_store-file.pod6
-rw-r--r--doc/man7/ossl_store.pod4
-rw-r--r--doc/man7/passphrase-encoding.pod8
-rw-r--r--doc/man7/property.pod177
-rw-r--r--doc/man7/provider-asym_cipher.pod269
-rw-r--r--doc/man7/provider-base.pod819
-rw-r--r--doc/man7/provider-cipher.pod247
-rw-r--r--doc/man7/provider-decoder.pod312
-rw-r--r--doc/man7/provider-digest.pod286
-rw-r--r--doc/man7/provider-encoder.pod331
-rw-r--r--doc/man7/provider-kdf.pod359
-rw-r--r--doc/man7/provider-kem.pod212
-rw-r--r--doc/man7/provider-keyexch.pod238
-rw-r--r--doc/man7/provider-keymgmt.pod422
-rw-r--r--doc/man7/provider-mac.pod236
-rw-r--r--doc/man7/provider-object.pod194
-rw-r--r--doc/man7/provider-rand.pod302
-rw-r--r--doc/man7/provider-signature.pod439
-rw-r--r--doc/man7/provider-storemgmt.pod198
-rw-r--r--doc/man7/provider.pod264
-rw-r--r--doc/man7/proxy-certificates.pod42
-rw-r--r--doc/man7/scrypt.pod115
-rw-r--r--doc/man7/ssl.pod751
-rw-r--r--doc/man7/x509.pod4
-rw-r--r--doc/perlvars.pm224
-rw-r--r--e_os.h227
-rw-r--r--engines/asm/e_padlock-x86.pl5
-rw-r--r--engines/asm/e_padlock-x86_64.pl12
-rw-r--r--engines/build.info81
-rw-r--r--engines/e_afalg.c100
-rw-r--r--engines/e_afalg.h2
-rw-r--r--engines/e_afalg.txt13
-rw-r--r--engines/e_afalg_err.c22
-rw-r--r--engines/e_afalg_err.h23
-rw-r--r--engines/e_capi.c37
-rw-r--r--engines/e_capi.txt26
-rw-r--r--engines/e_capi_err.c35
-rw-r--r--engines/e_capi_err.h37
-rw-r--r--engines/e_dasync.c437
-rw-r--r--engines/e_dasync.txt17
-rw-r--r--engines/e_dasync_err.c27
-rw-r--r--engines/e_dasync_err.h28
-rw-r--r--engines/e_devcrypto.c1382
-rw-r--r--engines/e_loader_attic.c1773
-rw-r--r--engines/e_loader_attic.txt21
-rw-r--r--engines/e_loader_attic_err.c73
-rw-r--r--engines/e_loader_attic_err.h37
-rw-r--r--engines/e_ossltest.c356
-rw-r--r--engines/e_ossltest.txt8
-rw-r--r--engines/e_ossltest_err.c17
-rw-r--r--engines/e_ossltest_err.h19
-rw-r--r--engines/e_padlock.c157
-rw-r--r--include/crypto/__DECC_INCLUDE_EPILOGUE.H2
-rw-r--r--include/crypto/__DECC_INCLUDE_PROLOGUE.H2
-rw-r--r--include/crypto/aes_platform.h450
-rw-r--r--include/crypto/aria.h17
-rw-r--r--include/crypto/asn1.h82
-rw-r--r--include/crypto/asn1_dsa.h24
-rw-r--r--include/crypto/asn1err.h27
-rw-r--r--include/crypto/async.h12
-rw-r--r--include/crypto/asyncerr.h27
-rw-r--r--include/crypto/bioerr.h27
-rw-r--r--include/crypto/bn.h30
-rw-r--r--include/crypto/bn_conf.h.in5
-rw-r--r--include/crypto/bn_dh.h41
-rw-r--r--include/crypto/bn_srp.h24
-rw-r--r--include/crypto/bnerr.h27
-rw-r--r--include/crypto/buffererr.h27
-rw-r--r--include/crypto/chacha.h11
-rw-r--r--include/crypto/cmll_platform.h51
-rw-r--r--include/crypto/cmperr.h30
-rw-r--r--include/crypto/cmserr.h30
-rw-r--r--include/crypto/comperr.h30
-rw-r--r--include/crypto/conferr.h27
-rw-r--r--include/crypto/crmferr.h30
-rw-r--r--include/crypto/cryptlib.h36
-rw-r--r--include/crypto/cryptoerr.h27
-rw-r--r--include/crypto/cterr.h30
-rw-r--r--include/crypto/ctype.h18
-rw-r--r--include/crypto/decoder.h44
-rw-r--r--include/crypto/decodererr.h27
-rw-r--r--include/crypto/des_platform.h35
-rw-r--r--include/crypto/dh.h62
-rw-r--r--include/crypto/dherr.h30
-rw-r--r--include/crypto/dsa.h49
-rw-r--r--include/crypto/dsaerr.h30
-rw-r--r--include/crypto/dso_conf.h.in8
-rw-r--r--include/crypto/ec.h65
-rw-r--r--include/crypto/ecerr.h30
-rw-r--r--include/crypto/ecx.h150
-rw-r--r--include/crypto/encoder.h22
-rw-r--r--include/crypto/encodererr.h27
-rw-r--r--include/crypto/engine.h2
-rw-r--r--include/crypto/engineerr.h30
-rw-r--r--include/crypto/err.h9
-rw-r--r--include/crypto/ess.h76
-rw-r--r--include/crypto/esserr.h27
-rw-r--r--include/crypto/evp.h666
-rw-r--r--include/crypto/evperr.h27
-rw-r--r--include/crypto/httperr.h27
-rw-r--r--include/crypto/lhash.h9
-rw-r--r--include/crypto/md32_common.h2
-rw-r--r--include/crypto/modes.h223
-rw-r--r--include/crypto/objects.h6
-rw-r--r--include/crypto/objectserr.h27
-rw-r--r--include/crypto/ocsperr.h30
-rw-r--r--include/crypto/pem.h51
-rw-r--r--include/crypto/pemerr.h27
-rw-r--r--include/crypto/pkcs12err.h27
-rw-r--r--include/crypto/pkcs7.h19
-rw-r--r--include/crypto/pkcs7err.h27
-rw-r--r--include/crypto/poly1305.h29
-rw-r--r--include/crypto/ppc_arch.h28
-rw-r--r--include/crypto/punycode.h24
-rw-r--r--include/crypto/rand.h163
-rw-r--r--include/crypto/rand_pool.h109
-rw-r--r--include/crypto/randerr.h27
-rw-r--r--include/crypto/rsa.h130
-rw-r--r--include/crypto/rsaerr.h27
-rw-r--r--include/crypto/security_bits.h16
-rw-r--r--include/crypto/sha.h9
-rw-r--r--include/crypto/siphash.h39
-rw-r--r--include/crypto/siv.h33
-rw-r--r--include/crypto/sm2.h71
-rw-r--r--include/crypto/sm2err.h44
-rw-r--r--include/crypto/sm3.h39
-rw-r--r--include/crypto/sm4.h11
-rw-r--r--include/crypto/sparc_arch.h122
-rw-r--r--include/crypto/sparse_array.h92
-rw-r--r--include/crypto/store.h17
-rw-r--r--include/crypto/storeerr.h27
-rw-r--r--include/crypto/tserr.h30
-rw-r--r--include/crypto/types.h32
-rw-r--r--include/crypto/uierr.h27
-rw-r--r--include/crypto/x509.h103
-rw-r--r--include/crypto/x509err.h27
-rw-r--r--include/crypto/x509v3err.h27
-rw-r--r--include/internal/__DECC_INCLUDE_EPILOGUE.H2
-rw-r--r--include/internal/__DECC_INCLUDE_PROLOGUE.H2
-rw-r--r--include/internal/asn1.h16
-rw-r--r--include/internal/bio.h64
-rw-r--r--include/internal/comp.h6
-rw-r--r--include/internal/conf.h15
-rw-r--r--include/internal/constant_time.h38
-rw-r--r--include/internal/core.h71
-rw-r--r--include/internal/cryptlib.h180
-rw-r--r--include/internal/dane.h7
-rw-r--r--include/internal/deprecated.h30
-rw-r--r--include/internal/der.h88
-rw-r--r--include/internal/dso.h7
-rw-r--r--include/internal/dsoerr.h88
-rw-r--r--include/internal/endian.h51
-rw-r--r--include/internal/err.h5
-rw-r--r--include/internal/ffc.h216
-rw-r--r--include/internal/ktls.h404
-rw-r--r--include/internal/namemap.h43
-rw-r--r--include/internal/nelem.h5
-rw-r--r--include/internal/numbers.h27
-rw-r--r--include/internal/o_dir.h5
-rw-r--r--include/internal/o_str.h17
-rw-r--r--include/internal/packet.h937
-rw-r--r--include/internal/param_build_set.h46
-rw-r--r--include/internal/passphrase.h122
-rw-r--r--include/internal/property.h99
-rw-r--r--include/internal/propertyerr.h43
-rw-r--r--include/internal/provider.h120
-rw-r--r--include/internal/refcount.h126
-rw-r--r--include/internal/sha3.h54
-rw-r--r--include/internal/sizes.h22
-rw-r--r--include/internal/sm3.h39
-rw-r--r--include/internal/sockets.h28
-rw-r--r--include/internal/sslconf.h5
-rw-r--r--include/internal/symhacks.h27
-rw-r--r--include/internal/thread_once.h36
-rw-r--r--include/internal/tlsgroups.h50
-rw-r--r--include/internal/tsan_assist.h12
-rw-r--r--include/internal/unicode.h31
-rw-r--r--include/openssl/__DECC_INCLUDE_EPILOGUE.H2
-rw-r--r--include/openssl/__DECC_INCLUDE_PROLOGUE.H2
-rw-r--r--include/openssl/aes.h73
-rw-r--r--include/openssl/asn1.h886
-rw-r--r--include/openssl/asn1.h.in961
-rw-r--r--include/openssl/asn1_mac.h2
-rw-r--r--include/openssl/asn1err.h134
-rw-r--r--include/openssl/asn1t.h945
-rw-r--r--include/openssl/asn1t.h.in923
-rw-r--r--include/openssl/async.h26
-rw-r--r--include/openssl/asyncerr.h29
-rw-r--r--include/openssl/bio.h801
-rw-r--r--include/openssl/bio.h.in864
-rw-r--r--include/openssl/bioerr.h83
-rw-r--r--include/openssl/blowfish.h67
-rw-r--r--include/openssl/bn.h144
-rw-r--r--include/openssl/bnerr.h74
-rw-r--r--include/openssl/buffer.h34
-rw-r--r--include/openssl/buffererr.h25
-rw-r--r--include/openssl/camellia.h102
-rw-r--r--include/openssl/cast.h36
-rw-r--r--include/openssl/cmac.h55
-rw-r--r--include/openssl/cmp.h.in477
-rw-r--r--include/openssl/cmp_util.h56
-rw-r--r--include/openssl/cmperr.h114
-rw-r--r--include/openssl/cms.h339
-rw-r--r--include/openssl/cms.h.in395
-rw-r--r--include/openssl/cmserr.h118
-rw-r--r--include/openssl/comp.h18
-rw-r--r--include/openssl/comperr.h29
-rw-r--r--include/openssl/conf.h168
-rw-r--r--include/openssl/conf.h.in174
-rw-r--r--include/openssl/conf_api.h12
-rw-r--r--include/openssl/conferr.h49
-rw-r--r--include/openssl/configuration.h.in69
-rw-r--r--include/openssl/conftypes.h44
-rw-r--r--include/openssl/core.h233
-rw-r--r--include/openssl/core_dispatch.h943
-rw-r--r--include/openssl/core_names.h556
-rw-r--r--include/openssl/core_object.h41
-rw-r--r--include/openssl/crmf.h.in180
-rw-r--r--include/openssl/crmferr.h50
-rw-r--r--include/openssl/crypto.h445
-rw-r--r--include/openssl/crypto.h.in535
-rw-r--r--include/openssl/cryptoerr.h65
-rw-r--r--include/openssl/cryptoerr_legacy.h1466
-rw-r--r--include/openssl/ct.h474
-rw-r--r--include/openssl/ct.h.in525
-rw-r--r--include/openssl/cterr.h51
-rw-r--r--include/openssl/decoder.h133
-rw-r--r--include/openssl/decodererr.h28
-rw-r--r--include/openssl/des.h147
-rw-r--r--include/openssl/dh.h546
-rw-r--r--include/openssl/dherr.h53
-rw-r--r--include/openssl/dsa.h347
-rw-r--r--include/openssl/dsaerr.h49
-rw-r--r--include/openssl/dtls1.h40
-rw-r--r--include/openssl/e_os2.h80
-rw-r--r--include/openssl/ebcdic.h12
-rw-r--r--include/openssl/ec.h935
-rw-r--r--include/openssl/ecdh.h2
-rw-r--r--include/openssl/ecdsa.h2
-rw-r--r--include/openssl/ecerr.h211
-rw-r--r--include/openssl/encoder.h124
-rw-r--r--include/openssl/encodererr.h28
-rw-r--r--include/openssl/engine.h497
-rw-r--r--include/openssl/engineerr.h64
-rw-r--r--include/openssl/err.h274
-rw-r--r--include/openssl/err.h.in493
-rw-r--r--include/openssl/ess.h.in81
-rw-r--r--include/openssl/esserr.h32
-rw-r--r--include/openssl/evp.h1394
-rw-r--r--include/openssl/evperr.h168
-rw-r--r--include/openssl/fips_names.h60
-rw-r--r--include/openssl/fipskey.h.in35
-rw-r--r--include/openssl/hmac.h69
-rw-r--r--include/openssl/http.h109
-rw-r--r--include/openssl/httperr.h55
-rw-r--r--include/openssl/idea.h96
-rw-r--r--include/openssl/kdf.h147
-rw-r--r--include/openssl/kdferr.h53
-rw-r--r--include/openssl/lhash.h241
-rw-r--r--include/openssl/lhash.h.in263
-rw-r--r--include/openssl/macros.h304
-rw-r--r--include/openssl/md2.h50
-rw-r--r--include/openssl/md4.h54
-rw-r--r--include/openssl/md5.h52
-rw-r--r--include/openssl/mdc2.h53
-rw-r--r--include/openssl/modes.h17
-rw-r--r--include/openssl/obj_mac.h351
-rw-r--r--include/openssl/objects.h22
-rw-r--r--include/openssl/objectserr.h32
-rw-r--r--include/openssl/ocsp.h352
-rw-r--r--include/openssl/ocsp.h.in387
-rw-r--r--include/openssl/ocsperr.h45
-rw-r--r--include/openssl/opensslconf.h17
-rw-r--r--include/openssl/opensslconf.h.in160
-rw-r--r--include/openssl/opensslv.h101
-rw-r--r--include/openssl/opensslv.h.in113
-rw-r--r--include/openssl/ossl_typ.h195
-rw-r--r--include/openssl/param_build.h63
-rw-r--r--include/openssl/params.h160
-rw-r--r--include/openssl/pem.h496
-rw-r--r--include/openssl/pem2.h12
-rw-r--r--include/openssl/pemerr.h67
-rw-r--r--include/openssl/pkcs12.h223
-rw-r--r--include/openssl/pkcs12.h.in327
-rw-r--r--include/openssl/pkcs12err.h54
-rw-r--r--include/openssl/pkcs7.h319
-rw-r--r--include/openssl/pkcs7.h.in356
-rw-r--r--include/openssl/pkcs7err.h56
-rw-r--r--include/openssl/prov_ssl.h34
-rw-r--r--include/openssl/proverr.h148
-rw-r--r--include/openssl/provider.h60
-rw-r--r--include/openssl/rand.h80
-rw-r--r--include/openssl/rand_drbg.h130
-rw-r--r--include/openssl/randerr.h52
-rw-r--r--include/openssl/rc2.h71
-rw-r--r--include/openssl/rc4.h39
-rw-r--r--include/openssl/rc5.h80
-rw-r--r--include/openssl/ripemd.h60
-rw-r--r--include/openssl/rsa.h597
-rw-r--r--include/openssl/rsaerr.h96
-rw-r--r--include/openssl/safestack.h207
-rw-r--r--include/openssl/safestack.h.in227
-rw-r--r--include/openssl/seed.h77
-rw-r--r--include/openssl/self_test.h92
-rw-r--r--include/openssl/sha.h109
-rw-r--r--include/openssl/srp.h135
-rw-r--r--include/openssl/srp.h.in214
-rw-r--r--include/openssl/srtp.h12
-rw-r--r--include/openssl/ssl.h2448
-rw-r--r--include/openssl/ssl.h.in2527
-rw-r--r--include/openssl/ssl2.h12
-rw-r--r--include/openssl/ssl3.h19
-rw-r--r--include/openssl/sslerr.h460
-rw-r--r--include/openssl/sslerr_legacy.h468
-rw-r--r--include/openssl/stack.h17
-rw-r--r--include/openssl/store.h183
-rw-r--r--include/openssl/storeerr.h64
-rw-r--r--include/openssl/symhacks.h18
-rw-r--r--include/openssl/tls1.h74
-rw-r--r--include/openssl/trace.h310
-rw-r--r--include/openssl/ts.h150
-rw-r--r--include/openssl/tserr.h81
-rw-r--r--include/openssl/txt_db.h12
-rw-r--r--include/openssl/types.h236
-rw-r--r--include/openssl/ui.h368
-rw-r--r--include/openssl/ui.h.in384
-rw-r--r--include/openssl/uierr.h43
-rw-r--r--include/openssl/whrlpool.h56
-rw-r--r--include/openssl/x509.h1050
-rw-r--r--include/openssl/x509.h.in1082
-rw-r--r--include/openssl/x509_vfy.h632
-rw-r--r--include/openssl/x509_vfy.h.in797
-rw-r--r--include/openssl/x509err.h85
-rw-r--r--include/openssl/x509v3.h938
-rw-r--r--include/openssl/x509v3.h.in1017
-rw-r--r--include/openssl/x509v3err.h93
-rw-r--r--providers/baseprov.c178
-rw-r--r--providers/build.info177
-rw-r--r--providers/common/bio_prov.c244
-rw-r--r--providers/common/build.info10
-rw-r--r--providers/common/capabilities.c225
-rw-r--r--providers/common/der/DIGESTS.asn143
-rw-r--r--providers/common/der/DSA.asn136
-rw-r--r--providers/common/der/EC.asn190
-rw-r--r--providers/common/der/ECX.asn117
-rw-r--r--providers/common/der/NIST.asn115
-rw-r--r--providers/common/der/RSA.asn189
-rw-r--r--providers/common/der/SM2.asn118
-rw-r--r--providers/common/der/build.info119
-rw-r--r--providers/common/der/der_digests_gen.c.in20
-rw-r--r--providers/common/der/der_dsa_gen.c.in25
-rw-r--r--providers/common/der/der_dsa_key.c27
-rw-r--r--providers/common/der/der_dsa_sig.c50
-rw-r--r--providers/common/der/der_ec_gen.c.in19
-rw-r--r--providers/common/der/der_ec_key.c21
-rw-r--r--providers/common/der/der_ec_sig.c51
-rw-r--r--providers/common/der/der_ecx_gen.c.in19
-rw-r--r--providers/common/der/der_ecx_key.c48
-rw-r--r--providers/common/der/der_rsa_gen.c.in20
-rw-r--r--providers/common/der/der_rsa_key.c400
-rw-r--r--providers/common/der/der_rsa_sig.c73
-rw-r--r--providers/common/der/der_sm2_gen.c.in19
-rw-r--r--providers/common/der/der_sm2_key.c23
-rw-r--r--providers/common/der/der_sm2_sig.c39
-rw-r--r--providers/common/der/der_wrap_gen.c.in19
-rw-r--r--providers/common/der/oids_to_c.pm113
-rw-r--r--providers/common/der/wrap.asn126
-rw-r--r--providers/common/digest_to_nid.c57
-rw-r--r--providers/common/include/prov/__DECC_INCLUDE_EPILOGUE.H22
-rw-r--r--providers/common/include/prov/__DECC_INCLUDE_PROLOGUE.H26
-rw-r--r--providers/common/include/prov/bio.h32
-rw-r--r--providers/common/include/prov/der_digests.h.in20
-rw-r--r--providers/common/include/prov/der_dsa.h.in25
-rw-r--r--providers/common/include/prov/der_ec.h.in26
-rw-r--r--providers/common/include/prov/der_ecx.h.in25
-rw-r--r--providers/common/include/prov/der_rsa.h.in33
-rw-r--r--providers/common/include/prov/der_sm2.h.in26
-rw-r--r--providers/common/include/prov/der_wrap.h.in19
-rw-r--r--providers/common/include/prov/proverr.h27
-rw-r--r--providers/common/include/prov/provider_ctx.h40
-rw-r--r--providers/common/include/prov/provider_util.h138
-rw-r--r--providers/common/include/prov/providercommon.h24
-rw-r--r--providers/common/include/prov/securitycheck.h30
-rw-r--r--providers/common/provider_ctx.c61
-rw-r--r--providers/common/provider_err.c229
-rw-r--r--providers/common/provider_seeding.c77
-rw-r--r--providers/common/provider_util.c353
-rw-r--r--providers/common/securitycheck.c248
-rw-r--r--providers/common/securitycheck_default.c43
-rw-r--r--providers/common/securitycheck_fips.c41
-rw-r--r--providers/decoders.inc94
-rw-r--r--providers/defltprov.c596
-rw-r--r--providers/encoders.inc271
-rw-r--r--providers/fips-sources.checksums583
-rw-r--r--providers/fips.checksum1
-rw-r--r--providers/fips.module.sources583
-rw-r--r--providers/fips/build.info6
-rw-r--r--providers/fips/fips_entry.c19
-rw-r--r--providers/fips/fipsprov.c915
-rw-r--r--providers/fips/self_test.c412
-rw-r--r--providers/fips/self_test.h41
-rw-r--r--providers/fips/self_test_data.inc1634
-rw-r--r--providers/fips/self_test_kats.c725
-rw-r--r--providers/implementations/asymciphers/build.info11
-rw-r--r--providers/implementations/asymciphers/rsa_enc.c588
-rw-r--r--providers/implementations/asymciphers/sm2_enc.c233
-rw-r--r--providers/implementations/build.info2
-rw-r--r--providers/implementations/ciphers/build.info142
-rw-r--r--providers/implementations/ciphers/cipher_aes.c95
-rw-r--r--providers/implementations/ciphers/cipher_aes.h62
-rw-r--r--providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c418
-rw-r--r--providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.h65
-rw-r--r--providers/implementations/ciphers/cipher_aes_cbc_hmac_sha1_hw.c795
-rw-r--r--providers/implementations/ciphers/cipher_aes_cbc_hmac_sha256_hw.c846
-rw-r--r--providers/implementations/ciphers/cipher_aes_ccm.c49
-rw-r--r--providers/implementations/ciphers/cipher_aes_ccm.h48
-rw-r--r--providers/implementations/ciphers/cipher_aes_ccm_hw.c69
-rw-r--r--providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc38
-rw-r--r--providers/implementations/ciphers/cipher_aes_ccm_hw_s390x.inc268
-rw-r--r--providers/implementations/ciphers/cipher_aes_ccm_hw_t4.inc36
-rw-r--r--providers/implementations/ciphers/cipher_aes_cts.inc94
-rw-r--r--providers/implementations/ciphers/cipher_aes_gcm.c50
-rw-r--r--providers/implementations/ciphers/cipher_aes_gcm.h45
-rw-r--r--providers/implementations/ciphers/cipher_aes_gcm_hw.c150
-rw-r--r--providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc38
-rw-r--r--providers/implementations/ciphers/cipher_aes_gcm_hw_armv8.inc83
-rw-r--r--providers/implementations/ciphers/cipher_aes_gcm_hw_s390x.inc312
-rw-r--r--providers/implementations/ciphers/cipher_aes_gcm_hw_t4.inc52
-rw-r--r--providers/implementations/ciphers/cipher_aes_hw.c157
-rw-r--r--providers/implementations/ciphers/cipher_aes_hw_aesni.inc84
-rw-r--r--providers/implementations/ciphers/cipher_aes_hw_s390x.inc206
-rw-r--r--providers/implementations/ciphers/cipher_aes_hw_t4.inc96
-rw-r--r--providers/implementations/ciphers/cipher_aes_ocb.c559
-rw-r--r--providers/implementations/ciphers/cipher_aes_ocb.h39
-rw-r--r--providers/implementations/ciphers/cipher_aes_ocb_hw.c122
-rw-r--r--providers/implementations/ciphers/cipher_aes_siv.c303
-rw-r--r--providers/implementations/ciphers/cipher_aes_siv.h36
-rw-r--r--providers/implementations/ciphers/cipher_aes_siv_hw.c136
-rw-r--r--providers/implementations/ciphers/cipher_aes_wrp.c311
-rw-r--r--providers/implementations/ciphers/cipher_aes_xts.c294
-rw-r--r--providers/implementations/ciphers/cipher_aes_xts.h35
-rw-r--r--providers/implementations/ciphers/cipher_aes_xts_fips.c23
-rw-r--r--providers/implementations/ciphers/cipher_aes_xts_hw.c177
-rw-r--r--providers/implementations/ciphers/cipher_aria.c86
-rw-r--r--providers/implementations/ciphers/cipher_aria.h30
-rw-r--r--providers/implementations/ciphers/cipher_aria_ccm.c44
-rw-r--r--providers/implementations/ciphers/cipher_aria_ccm.h22
-rw-r--r--providers/implementations/ciphers/cipher_aria_ccm_hw.c40
-rw-r--r--providers/implementations/ciphers/cipher_aria_gcm.c44
-rw-r--r--providers/implementations/ciphers/cipher_aria_gcm.h22
-rw-r--r--providers/implementations/ciphers/cipher_aria_gcm_hw.c37
-rw-r--r--providers/implementations/ciphers/cipher_aria_hw.c52
-rw-r--r--providers/implementations/ciphers/cipher_blowfish.c60
-rw-r--r--providers/implementations/ciphers/cipher_blowfish.h24
-rw-r--r--providers/implementations/ciphers/cipher_blowfish_hw.c42
-rw-r--r--providers/implementations/ciphers/cipher_camellia.c94
-rw-r--r--providers/implementations/ciphers/cipher_camellia.h30
-rw-r--r--providers/implementations/ciphers/cipher_camellia_cts.inc94
-rw-r--r--providers/implementations/ciphers/cipher_camellia_hw.c74
-rw-r--r--providers/implementations/ciphers/cipher_camellia_hw_t4.inc84
-rw-r--r--providers/implementations/ciphers/cipher_cast.h24
-rw-r--r--providers/implementations/ciphers/cipher_cast5.c61
-rw-r--r--providers/implementations/ciphers/cipher_cast5_hw.c42
-rw-r--r--providers/implementations/ciphers/cipher_chacha20.c205
-rw-r--r--providers/implementations/ciphers/cipher_chacha20.h34
-rw-r--r--providers/implementations/ciphers/cipher_chacha20_hw.c122
-rw-r--r--providers/implementations/ciphers/cipher_chacha20_poly1305.c332
-rw-r--r--providers/implementations/ciphers/cipher_chacha20_poly1305.h43
-rw-r--r--providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c413
-rw-r--r--providers/implementations/ciphers/cipher_cts.c378
-rw-r--r--providers/implementations/ciphers/cipher_cts.h52
-rw-r--r--providers/implementations/ciphers/cipher_des.c202
-rw-r--r--providers/implementations/ciphers/cipher_des.h33
-rw-r--r--providers/implementations/ciphers/cipher_des_hw.c196
-rw-r--r--providers/implementations/ciphers/cipher_desx.c21
-rw-r--r--providers/implementations/ciphers/cipher_desx_hw.c80
-rw-r--r--providers/implementations/ciphers/cipher_idea.c59
-rw-r--r--providers/implementations/ciphers/cipher_idea.h24
-rw-r--r--providers/implementations/ciphers/cipher_idea_hw.c63
-rw-r--r--providers/implementations/ciphers/cipher_null.c197
-rw-r--r--providers/implementations/ciphers/cipher_rc2.c283
-rw-r--r--providers/implementations/ciphers/cipher_rc2.h28
-rw-r--r--providers/implementations/ciphers/cipher_rc2_hw.c43
-rw-r--r--providers/implementations/ciphers/cipher_rc4.c121
-rw-r--r--providers/implementations/ciphers/cipher_rc4.h21
-rw-r--r--providers/implementations/ciphers/cipher_rc4_hmac_md5.c234
-rw-r--r--providers/implementations/ciphers/cipher_rc4_hmac_md5.h33
-rw-r--r--providers/implementations/ciphers/cipher_rc4_hmac_md5_hw.c233
-rw-r--r--providers/implementations/ciphers/cipher_rc4_hw.c44
-rw-r--r--providers/implementations/ciphers/cipher_rc5.c188
-rw-r--r--providers/implementations/ciphers/cipher_rc5.h25
-rw-r--r--providers/implementations/ciphers/cipher_rc5_hw.c41
-rw-r--r--providers/implementations/ciphers/cipher_seed.c58
-rw-r--r--providers/implementations/ciphers/cipher_seed.h24
-rw-r--r--providers/implementations/ciphers/cipher_seed_hw.c42
-rw-r--r--providers/implementations/ciphers/cipher_sm4.c54
-rw-r--r--providers/implementations/ciphers/cipher_sm4.h25
-rw-r--r--providers/implementations/ciphers/cipher_sm4_hw.c46
-rw-r--r--providers/implementations/ciphers/cipher_tdes.c25
-rw-r--r--providers/implementations/ciphers/cipher_tdes.h103
-rw-r--r--providers/implementations/ciphers/cipher_tdes_common.c149
-rw-r--r--providers/implementations/ciphers/cipher_tdes_default.c35
-rw-r--r--providers/implementations/ciphers/cipher_tdes_default.h25
-rw-r--r--providers/implementations/ciphers/cipher_tdes_default_hw.c147
-rw-r--r--providers/implementations/ciphers/cipher_tdes_hw.c98
-rw-r--r--providers/implementations/ciphers/cipher_tdes_wrap.c210
-rw-r--r--providers/implementations/ciphers/cipher_tdes_wrap_hw.c20
-rw-r--r--providers/implementations/ciphers/ciphercommon.c680
-rw-r--r--providers/implementations/ciphers/ciphercommon_block.c190
-rw-r--r--providers/implementations/ciphers/ciphercommon_ccm.c453
-rw-r--r--providers/implementations/ciphers/ciphercommon_ccm_hw.c69
-rw-r--r--providers/implementations/ciphers/ciphercommon_gcm.c568
-rw-r--r--providers/implementations/ciphers/ciphercommon_gcm_hw.c69
-rw-r--r--providers/implementations/ciphers/ciphercommon_hw.c194
-rw-r--r--providers/implementations/ciphers/ciphercommon_local.h16
-rw-r--r--providers/implementations/digests/blake2_impl.h118
-rw-r--r--providers/implementations/digests/blake2_prov.c41
-rw-r--r--providers/implementations/digests/blake2b_prov.c331
-rw-r--r--providers/implementations/digests/blake2s_prov.c322
-rw-r--r--providers/implementations/digests/build.info62
-rw-r--r--providers/implementations/digests/digestcommon.c54
-rw-r--r--providers/implementations/digests/md2_prov.c24
-rw-r--r--providers/implementations/digests/md4_prov.c24
-rw-r--r--providers/implementations/digests/md5_prov.c24
-rw-r--r--providers/implementations/digests/md5_sha1_prov.c61
-rw-r--r--providers/implementations/digests/mdc2_prov.c61
-rw-r--r--providers/implementations/digests/null_prov.c52
-rw-r--r--providers/implementations/digests/ripemd_prov.c24
-rw-r--r--providers/implementations/digests/sha2_prov.c95
-rw-r--r--providers/implementations/digests/sha3_prov.c332
-rw-r--r--providers/implementations/digests/sm3_prov.c18
-rw-r--r--providers/implementations/digests/wp_prov.c24
-rw-r--r--providers/implementations/encode_decode/build.info20
-rw-r--r--providers/implementations/encode_decode/decode_der2key.c793
-rw-r--r--providers/implementations/encode_decode/decode_epki2pki.c158
-rw-r--r--providers/implementations/encode_decode/decode_msblob2key.c273
-rw-r--r--providers/implementations/encode_decode/decode_pem2der.c219
-rw-r--r--providers/implementations/encode_decode/decode_pvk2key.c239
-rw-r--r--providers/implementations/encode_decode/decode_spki2typespki.c124
-rw-r--r--providers/implementations/encode_decode/encode_key2any.c1465
-rw-r--r--providers/implementations/encode_decode/encode_key2blob.c179
-rw-r--r--providers/implementations/encode_decode/encode_key2ms.c234
-rw-r--r--providers/implementations/encode_decode/encode_key2text.c889
-rw-r--r--providers/implementations/encode_decode/endecoder_common.c104
-rw-r--r--providers/implementations/encode_decode/endecoder_local.h28
-rw-r--r--providers/implementations/exchange/build.info29
-rw-r--r--providers/implementations/exchange/dh_exch.c512
-rw-r--r--providers/implementations/exchange/ecdh_exch.c580
-rw-r--r--providers/implementations/exchange/ecx_exch.c243
-rw-r--r--providers/implementations/exchange/kdf_exch.c215
-rw-r--r--providers/implementations/include/prov/__DECC_INCLUDE_EPILOGUE.H22
-rw-r--r--providers/implementations/include/prov/__DECC_INCLUDE_PROLOGUE.H26
-rw-r--r--providers/implementations/include/prov/blake2.h120
-rw-r--r--providers/implementations/include/prov/ciphercommon.h361
-rw-r--r--providers/implementations/include/prov/ciphercommon_aead.h47
-rw-r--r--providers/implementations/include/prov/ciphercommon_ccm.h100
-rw-r--r--providers/implementations/include/prov/ciphercommon_gcm.h129
-rw-r--r--providers/implementations/include/prov/digestcommon.h126
-rw-r--r--providers/implementations/include/prov/implementations.h517
-rw-r--r--providers/implementations/include/prov/kdfexchange.h24
-rw-r--r--providers/implementations/include/prov/macsignature.h30
-rw-r--r--providers/implementations/include/prov/md5_sha1.h36
-rw-r--r--providers/implementations/include/prov/names.h327
-rw-r--r--providers/implementations/include/prov/seeding.h41
-rw-r--r--providers/implementations/kdfs/build.info38
-rw-r--r--providers/implementations/kdfs/hkdf.c783
-rw-r--r--providers/implementations/kdfs/kbkdf.c395
-rw-r--r--providers/implementations/kdfs/krb5kdf.c467
-rw-r--r--providers/implementations/kdfs/pbkdf1.c244
-rw-r--r--providers/implementations/kdfs/pbkdf2.c363
-rw-r--r--providers/implementations/kdfs/pbkdf2.h14
-rw-r--r--providers/implementations/kdfs/pbkdf2_fips.c20
-rw-r--r--providers/implementations/kdfs/pkcs12kdf.c300
-rw-r--r--providers/implementations/kdfs/scrypt.c517
-rw-r--r--providers/implementations/kdfs/sshkdf.c302
-rw-r--r--providers/implementations/kdfs/sskdf.c559
-rw-r--r--providers/implementations/kdfs/tls1_prf.c411
-rw-r--r--providers/implementations/kdfs/x942kdf.c594
-rw-r--r--providers/implementations/kem/build.info6
-rw-r--r--providers/implementations/kem/rsa_kem.c364
-rw-r--r--providers/implementations/keymgmt/build.info41
-rw-r--r--providers/implementations/keymgmt/dh_kmgmt.c881
-rw-r--r--providers/implementations/keymgmt/dsa_kmgmt.c677
-rw-r--r--providers/implementations/keymgmt/ec_kmgmt.c1467
-rw-r--r--providers/implementations/keymgmt/ec_kmgmt_imexport.inc109
-rw-r--r--providers/implementations/keymgmt/ecx_kmgmt.c1056
-rw-r--r--providers/implementations/keymgmt/kdf_legacy_kmgmt.c104
-rw-r--r--providers/implementations/keymgmt/mac_legacy_kmgmt.c575
-rw-r--r--providers/implementations/keymgmt/rsa_kmgmt.c744
-rw-r--r--providers/implementations/macs/blake2_mac_impl.c254
-rw-r--r--providers/implementations/macs/blake2b_mac.c33
-rw-r--r--providers/implementations/macs/blake2s_mac.c32
-rw-r--r--providers/implementations/macs/build.info30
-rw-r--r--providers/implementations/macs/cmac_prov.c223
-rw-r--r--providers/implementations/macs/gmac_prov.c259
-rw-r--r--providers/implementations/macs/hmac_prov.c357
-rw-r--r--providers/implementations/macs/kmac_prov.c627
-rw-r--r--providers/implementations/macs/poly1305_prov.c187
-rw-r--r--providers/implementations/macs/siphash_prov.c237
-rw-r--r--providers/implementations/rands/build.info6
-rw-r--r--providers/implementations/rands/crngt.c198
-rw-r--r--providers/implementations/rands/drbg.c934
-rw-r--r--providers/implementations/rands/drbg_ctr.c755
-rw-r--r--providers/implementations/rands/drbg_hash.c529
-rw-r--r--providers/implementations/rands/drbg_hmac.c432
-rw-r--r--providers/implementations/rands/drbg_local.h259
-rw-r--r--providers/implementations/rands/seed_src.c253
-rw-r--r--providers/implementations/rands/seeding/build.info10
-rw-r--r--providers/implementations/rands/seeding/rand_cpu_x86.c107
-rw-r--r--providers/implementations/rands/seeding/rand_tsc.c48
-rw-r--r--providers/implementations/rands/seeding/rand_unix.c882
-rw-r--r--providers/implementations/rands/seeding/rand_vms.c615
-rw-r--r--providers/implementations/rands/seeding/rand_vxworks.c167
-rw-r--r--providers/implementations/rands/seeding/rand_win.c183
-rw-r--r--providers/implementations/rands/test_rng.c296
-rw-r--r--providers/implementations/signature/build.info30
-rw-r--r--providers/implementations/signature/dsa_sig.c601
-rw-r--r--providers/implementations/signature/ecdsa_sig.c619
-rw-r--r--providers/implementations/signature/eddsa_sig.c468
-rw-r--r--providers/implementations/signature/mac_legacy_sig.c267
-rw-r--r--providers/implementations/signature/rsa_sig.c1474
-rw-r--r--providers/implementations/signature/sm2_sig.c564
-rw-r--r--providers/implementations/storemgmt/build.info6
-rw-r--r--providers/implementations/storemgmt/file_store.c790
-rw-r--r--providers/implementations/storemgmt/file_store_any2obj.c261
-rw-r--r--providers/implementations/storemgmt/file_store_local.h11
-rw-r--r--providers/legacyprov.c201
-rw-r--r--providers/nullprov.c80
-rw-r--r--providers/prov_running.c22
-rw-r--r--providers/stores.inc14
-rw-r--r--ssl/bio_ssl.c4
-rw-r--r--ssl/build.info37
-rw-r--r--ssl/d1_lib.c63
-rw-r--r--ssl/d1_msg.c21
-rw-r--r--ssl/d1_srtp.c16
-rw-r--r--ssl/ktls.c247
-rw-r--r--ssl/methods.c5
-rw-r--r--ssl/packet.c424
-rw-r--r--ssl/packet_local.h909
-rw-r--r--ssl/pqueue.c8
-rw-r--r--ssl/record/README74
-rw-r--r--ssl/record/README.md73
-rw-r--r--ssl/record/dtls1_bitmap.c2
-rw-r--r--ssl/record/rec_layer_d1.c125
-rw-r--r--ssl/record/rec_layer_s3.c374
-rw-r--r--ssl/record/record.h21
-rw-r--r--ssl/record/record_local.h29
-rw-r--r--ssl/record/ssl3_buffer.c39
-rw-r--r--ssl/record/ssl3_record.c1266
-rw-r--r--ssl/record/ssl3_record_tls13.c79
-rw-r--r--ssl/record/tls_pad.c325
-rw-r--r--ssl/s3_cbc.c144
-rw-r--r--ssl/s3_enc.c259
-rw-r--r--ssl/s3_lib.c775
-rw-r--r--ssl/s3_msg.c32
-rw-r--r--ssl/ssl_asn1.c41
-rw-r--r--ssl/ssl_cert.c211
-rw-r--r--ssl/ssl_cert_table.h2
-rw-r--r--ssl/ssl_ciph.c572
-rw-r--r--ssl/ssl_conf.c223
-rw-r--r--ssl/ssl_err.c741
-rw-r--r--ssl/ssl_err_legacy.c21
-rw-r--r--ssl/ssl_init.c99
-rw-r--r--ssl/ssl_lib.c1118
-rw-r--r--ssl/ssl_local.h714
-rw-r--r--ssl/ssl_mcnf.c29
-rw-r--r--ssl/ssl_rsa.c534
-rw-r--r--ssl/ssl_rsa_legacy.c180
-rw-r--r--ssl/ssl_sess.c350
-rw-r--r--ssl/ssl_stat.c12
-rw-r--r--ssl/ssl_txt.c7
-rw-r--r--ssl/ssl_utst.c2
-rw-r--r--ssl/sslerr.h27
-rw-r--r--ssl/statem/README63
-rw-r--r--ssl/statem/README.md63
-rw-r--r--ssl/statem/extensions.c265
-rw-r--r--ssl/statem/extensions_clnt.c616
-rw-r--r--ssl/statem/extensions_cust.c17
-rw-r--r--ssl/statem/extensions_srvr.c646
-rw-r--r--ssl/statem/statem.c149
-rw-r--r--ssl/statem/statem.h20
-rw-r--r--ssl/statem/statem_clnt.c1212
-rw-r--r--ssl/statem/statem_dtls.c223
-rw-r--r--ssl/statem/statem_lib.c537
-rw-r--r--ssl/statem/statem_local.h32
-rw-r--r--ssl/statem/statem_srvr.c1268
-rw-r--r--ssl/t1_enc.c561
-rw-r--r--ssl/t1_lib.c1503
-rw-r--r--ssl/t1_trce.c45
-rw-r--r--ssl/tls13_enc.c459
-rw-r--r--ssl/tls_depr.c207
-rw-r--r--ssl/tls_srp.c148
2961 files changed, 377030 insertions, 141460 deletions
diff --git a/ACKNOWLEDGEMENTS b/ACKNOWLEDGEMENTS
deleted file mode 100644
index d21dccbb79cf..000000000000
--- a/ACKNOWLEDGEMENTS
+++ /dev/null
@@ -1,2 +0,0 @@
-Please https://www.openssl.org/community/thanks.html for the current
-acknowledgements.
diff --git a/ACKNOWLEDGEMENTS.md b/ACKNOWLEDGEMENTS.md
new file mode 100644
index 000000000000..a4dab0c4fff4
--- /dev/null
+++ b/ACKNOWLEDGEMENTS.md
@@ -0,0 +1,6 @@
+Acknowlegements
+===============
+
+Please see our [Thanks!][] page for the current acknowledgements.
+
+[Thanks!]: https://www.openssl.org/community/thanks.html
diff --git a/AUTHORS b/AUTHORS
deleted file mode 100644
index dac46f8b7e08..000000000000
--- a/AUTHORS
+++ /dev/null
@@ -1,42 +0,0 @@
-# This is the list of OpenSSL authors for copyright purposes.
-#
-# This does not necessarily list everyone who has contributed code, since in
-# some cases, their employer may be the copyright holder. To see the full list
-# of contributors, see the revision history in source control.
-OpenSSL Software Services, Inc.
-OpenSSL Software Foundation, Inc.
-
-# Individuals
-Andy Polyakov
-Ben Laurie
-Ben Kaduk
-Bernd Edlinger
-Bodo Möller
-David Benjamin
-David von Oheimb
-Dmitry Belyavskiy (Дмитрий Белявский)
-Emilia Käsper
-Eric Young
-Geoff Thorpe
-Holger Reif
-Kurt Roeckx
-Lutz Jänicke
-Mark J. Cox
-Matt Caswell
-Matthias St. Pierre
-Nicola Tuveri
-Nils Larsch
-Patrick Steuer
-Paul Dale
-Paul C. Sutton
-Paul Yang
-Ralf S. Engelschall
-Rich Salz
-Richard Levitte
-Shane Lontis
-Stephen Henson
-Steve Marquess
-Tim Hudson
-Tomáš Mráz
-Ulf Möller
-Viktor Dukhovni
diff --git a/AUTHORS.md b/AUTHORS.md
new file mode 100644
index 000000000000..dc6b534b82a5
--- /dev/null
+++ b/AUTHORS.md
@@ -0,0 +1,51 @@
+Authors
+=======
+
+This is the list of OpenSSL authors for copyright purposes.
+It does not necessarily list everyone who has contributed code,
+since in some cases, their employer may be the copyright holder.
+To see the full list of contributors, see the revision history in
+source control.
+
+Groups
+------
+
+ * OpenSSL Software Services, Inc.
+ * OpenSSL Software Foundation, Inc.
+
+Individuals
+-----------
+
+ * Andy Polyakov
+ * Ben Laurie
+ * Ben Kaduk
+ * Bernd Edlinger
+ * Bodo Möller
+ * David Benjamin
+ * David von Oheimb
+ * Dmitry Belyavskiy (Дмитрий Белявский)
+ * Emilia Käsper
+ * Eric Young
+ * Geoff Thorpe
+ * Holger Reif
+ * Kurt Roeckx
+ * Lutz Jänicke
+ * Mark J. Cox
+ * Matt Caswell
+ * Matthias St. Pierre
+ * Nicola Tuveri
+ * Nils Larsch
+ * Patrick Steuer
+ * Paul Dale
+ * Paul C. Sutton
+ * Paul Yang
+ * Ralf S. Engelschall
+ * Rich Salz
+ * Richard Levitte
+ * Shane Lontis
+ * Stephen Henson
+ * Steve Marquess
+ * Tim Hudson
+ * Tomáš Mráz
+ * Ulf Möller
+ * Viktor Dukhovni
diff --git a/CHANGES b/CHANGES
deleted file mode 100644
index 1e2d651b7514..000000000000
--- a/CHANGES
+++ /dev/null
@@ -1,13899 +0,0 @@
-
- OpenSSL CHANGES
- _______________
-
- This is a high-level summary of the most important changes.
- For a full list of changes, see the git commit log; for example,
- https://github.com/openssl/openssl/commits/ and pick the appropriate
- release branch.
-
- Changes between 1.1.1s and 1.1.1t [7 Feb 2023]
-
- *) Fixed X.400 address type confusion in X.509 GeneralName.
-
- There is a type confusion vulnerability relating to X.400 address processing
- inside an X.509 GeneralName. X.400 addresses were parsed as an ASN1_STRING
- but subsequently interpreted by GENERAL_NAME_cmp as an ASN1_TYPE. This
- vulnerability may allow an attacker who can provide a certificate chain and
- CRL (neither of which need have a valid signature) to pass arbitrary
- pointers to a memcmp call, creating a possible read primitive, subject to
- some constraints. Refer to the advisory for more information. Thanks to
- David Benjamin for discovering this issue. (CVE-2023-0286)
-
- This issue has been fixed by changing the public header file definition of
- GENERAL_NAME so that x400Address reflects the implementation. It was not
- possible for any existing application to successfully use the existing
- definition; however, if any application references the x400Address field
- (e.g. in dead code), note that the type of this field has changed. There is
- no ABI change.
- [Hugo Landau]
-
- *) Fixed Use-after-free following BIO_new_NDEF.
-
- The public API function BIO_new_NDEF is a helper function used for
- streaming ASN.1 data via a BIO. It is primarily used internally to OpenSSL
- to support the SMIME, CMS and PKCS7 streaming capabilities, but may also
- be called directly by end user applications.
-
- The function receives a BIO from the caller, prepends a new BIO_f_asn1
- filter BIO onto the front of it to form a BIO chain, and then returns
- the new head of the BIO chain to the caller. Under certain conditions,
- for example if a CMS recipient public key is invalid, the new filter BIO
- is freed and the function returns a NULL result indicating a failure.
- However, in this case, the BIO chain is not properly cleaned up and the
- BIO passed by the caller still retains internal pointers to the previously
- freed filter BIO. If the caller then goes on to call BIO_pop() on the BIO
- then a use-after-free will occur. This will most likely result in a crash.
- (CVE-2023-0215)
- [Viktor Dukhovni, Matt Caswell]
-
- *) Fixed Double free after calling PEM_read_bio_ex.
-
- The function PEM_read_bio_ex() reads a PEM file from a BIO and parses and
- decodes the "name" (e.g. "CERTIFICATE"), any header data and the payload
- data. If the function succeeds then the "name_out", "header" and "data"
- arguments are populated with pointers to buffers containing the relevant
- decoded data. The caller is responsible for freeing those buffers. It is
- possible to construct a PEM file that results in 0 bytes of payload data.
- In this case PEM_read_bio_ex() will return a failure code but will populate
- the header argument with a pointer to a buffer that has already been freed.
- If the caller also frees this buffer then a double free will occur. This
- will most likely lead to a crash.
-
- The functions PEM_read_bio() and PEM_read() are simple wrappers around
- PEM_read_bio_ex() and therefore these functions are also directly affected.
-
- These functions are also called indirectly by a number of other OpenSSL
- functions including PEM_X509_INFO_read_bio_ex() and
- SSL_CTX_use_serverinfo_file() which are also vulnerable. Some OpenSSL
- internal uses of these functions are not vulnerable because the caller does
- not free the header argument if PEM_read_bio_ex() returns a failure code.
- (CVE-2022-4450)
- [Kurt Roeckx, Matt Caswell]
-
- *) Fixed Timing Oracle in RSA Decryption.
-
- A timing based side channel exists in the OpenSSL RSA Decryption
- implementation which could be sufficient to recover a plaintext across
- a network in a Bleichenbacher style attack. To achieve a successful
- decryption an attacker would have to be able to send a very large number
- of trial messages for decryption. The vulnerability affects all RSA padding
- modes: PKCS#1 v1.5, RSA-OEAP and RSASVE.
- (CVE-2022-4304)
- [Dmitry Belyavsky, Hubert Kario]
-
- Changes between 1.1.1r and 1.1.1s [1 Nov 2022]
-
- *) Fixed a regression introduced in 1.1.1r version not refreshing the
- certificate data to be signed before signing the certificate.
- [Gibeom Gwon]
-
- Changes between 1.1.1q and 1.1.1r [11 Oct 2022]
-
- *) Fixed the linux-mips64 Configure target which was missing the
- SIXTY_FOUR_BIT bn_ops flag. This was causing heap corruption on that
- platform.
- [Adam Joseph]
-
- *) Fixed a strict aliasing problem in bn_nist. Clang-14 optimisation was
- causing incorrect results in some cases as a result.
- [Paul Dale]
-
- *) Fixed SSL_pending() and SSL_has_pending() with DTLS which were failing to
- report correct results in some cases
- [Matt Caswell]
-
- *) Fixed a regression introduced in 1.1.1o for re-signing certificates with
- different key sizes
- [Todd Short]
-
- *) Added the loongarch64 target
- [Shi Pujin]
-
- *) Fixed a DRBG seed propagation thread safety issue
- [Bernd Edlinger]
-
- *) Fixed a memory leak in tls13_generate_secret
- [Bernd Edlinger]
-
- *) Fixed reported performance degradation on aarch64. Restored the
- implementation prior to commit 2621751 ("aes/asm/aesv8-armx.pl: avoid
- 32-bit lane assignment in CTR mode") for 64bit targets only, since it is
- reportedly 2-17% slower and the silicon errata only affects 32bit targets.
- The new algorithm is still used for 32 bit targets.
- [Bernd Edlinger]
-
- *) Added a missing header for memcmp that caused compilation failure on some
- platforms
- [Gregor Jasny]
-
- Changes between 1.1.1p and 1.1.1q [5 Jul 2022]
-
- *) AES OCB mode for 32-bit x86 platforms using the AES-NI assembly optimised
- implementation would not encrypt the entirety of the data under some
- circumstances. This could reveal sixteen bytes of data that was
- preexisting in the memory that wasn't written. In the special case of
- "in place" encryption, sixteen bytes of the plaintext would be revealed.
-
- Since OpenSSL does not support OCB based cipher suites for TLS and DTLS,
- they are both unaffected.
- (CVE-2022-2097)
- [Alex Chernyakhovsky, David Benjamin, Alejandro Sedeño]
-
- Changes between 1.1.1o and 1.1.1p [21 Jun 2022]
-
- *) In addition to the c_rehash shell command injection identified in
- CVE-2022-1292, further bugs where the c_rehash script does not
- properly sanitise shell metacharacters to prevent command injection have been
- fixed.
-
- When the CVE-2022-1292 was fixed it was not discovered that there
- are other places in the script where the file names of certificates
- being hashed were possibly passed to a command executed through the shell.
-
- This script is distributed by some operating systems in a manner where
- it is automatically executed. On such operating systems, an attacker
- could execute arbitrary commands with the privileges of the script.
-
- Use of the c_rehash script is considered obsolete and should be replaced
- by the OpenSSL rehash command line tool.
- (CVE-2022-2068)
- [Daniel Fiala, Tomáš Mráz]
-
- *) When OpenSSL TLS client is connecting without any supported elliptic
- curves and TLS-1.3 protocol is disabled the connection will no longer fail
- if a ciphersuite that does not use a key exchange based on elliptic
- curves can be negotiated.
- [Tomáš Mráz]
-
- Changes between 1.1.1n and 1.1.1o [3 May 2022]
-
- *) Fixed a bug in the c_rehash script which was not properly sanitising shell
- metacharacters to prevent command injection. This script is distributed
- by some operating systems in a manner where it is automatically executed.
- On such operating systems, an attacker could execute arbitrary commands
- with the privileges of the script.
-
- Use of the c_rehash script is considered obsolete and should be replaced
- by the OpenSSL rehash command line tool.
- (CVE-2022-1292)
- [Tomáš Mráz]
-
- Changes between 1.1.1m and 1.1.1n [15 Mar 2022]
-
- *) Fixed a bug in the BN_mod_sqrt() function that can cause it to loop forever
- for non-prime moduli.
-
- Internally this function is used when parsing certificates that contain
- elliptic curve public keys in compressed form or explicit elliptic curve
- parameters with a base point encoded in compressed form.
-
- It is possible to trigger the infinite loop by crafting a certificate that
- has invalid explicit curve parameters.
-
- Since certificate parsing happens prior to verification of the certificate
- signature, any process that parses an externally supplied certificate may
- thus be subject to a denial of service attack. The infinite loop can also
- be reached when parsing crafted private keys as they can contain explicit
- elliptic curve parameters.
-
- Thus vulnerable situations include:
-
- - TLS clients consuming server certificates
- - TLS servers consuming client certificates
- - Hosting providers taking certificates or private keys from customers
- - Certificate authorities parsing certification requests from subscribers
- - Anything else which parses ASN.1 elliptic curve parameters
-
- Also any other applications that use the BN_mod_sqrt() where the attacker
- can control the parameter values are vulnerable to this DoS issue.
- (CVE-2022-0778)
- [Tomáš Mráz]
-
- *) Add ciphersuites based on DHE_PSK (RFC 4279) and ECDHE_PSK (RFC 5489)
- to the list of ciphersuites providing Perfect Forward Secrecy as
- required by SECLEVEL >= 3.
-
- [Dmitry Belyavskiy, Nicola Tuveri]
-
- Changes between 1.1.1l and 1.1.1m [14 Dec 2021]
-
- *) Avoid loading of a dynamic engine twice.
-
- [Bernd Edlinger]
-
- *) Fixed building on Debian with kfreebsd kernels
-
- [Mattias Ellert]
-
- *) Prioritise DANE TLSA issuer certs over peer certs
-
- [Viktor Dukhovni]
-
- *) Fixed random API for MacOS prior to 10.12
-
- These MacOS versions don't support the CommonCrypto APIs
-
- [Lenny Primak]
-
- Changes between 1.1.1k and 1.1.1l [24 Aug 2021]
-
- *) Fixed an SM2 Decryption Buffer Overflow.
-
- In order to decrypt SM2 encrypted data an application is expected to call the
- API function EVP_PKEY_decrypt(). Typically an application will call this
- function twice. The first time, on entry, the "out" parameter can be NULL and,
- on exit, the "outlen" parameter is populated with the buffer size required to
- hold the decrypted plaintext. The application can then allocate a sufficiently
- sized buffer and call EVP_PKEY_decrypt() again, but this time passing a non-NULL
- value for the "out" parameter.
-
- A bug in the implementation of the SM2 decryption code means that the
- calculation of the buffer size required to hold the plaintext returned by the
- first call to EVP_PKEY_decrypt() can be smaller than the actual size required by
- the second call. This can lead to a buffer overflow when EVP_PKEY_decrypt() is
- called by the application a second time with a buffer that is too small.
-
- A malicious attacker who is able present SM2 content for decryption to an
- application could cause attacker chosen data to overflow the buffer by up to a
- maximum of 62 bytes altering the contents of other data held after the
- buffer, possibly changing application behaviour or causing the application to
- crash. The location of the buffer is application dependent but is typically
- heap allocated.
- (CVE-2021-3711)
- [Matt Caswell]
-
- *) Fixed various read buffer overruns processing ASN.1 strings
-
- ASN.1 strings are represented internally within OpenSSL as an ASN1_STRING
- structure which contains a buffer holding the string data and a field holding
- the buffer length. This contrasts with normal C strings which are repesented as
- a buffer for the string data which is terminated with a NUL (0) byte.
-
- Although not a strict requirement, ASN.1 strings that are parsed using OpenSSL's
- own "d2i" functions (and other similar parsing functions) as well as any string
- whose value has been set with the ASN1_STRING_set() function will additionally
- NUL terminate the byte array in the ASN1_STRING structure.
-
- However, it is possible for applications to directly construct valid ASN1_STRING
- structures which do not NUL terminate the byte array by directly setting the
- "data" and "length" fields in the ASN1_STRING array. This can also happen by
- using the ASN1_STRING_set0() function.
-
- Numerous OpenSSL functions that print ASN.1 data have been found to assume that
- the ASN1_STRING byte array will be NUL terminated, even though this is not
- guaranteed for strings that have been directly constructed. Where an application
- requests an ASN.1 structure to be printed, and where that ASN.1 structure
- contains ASN1_STRINGs that have been directly constructed by the application
- without NUL terminating the "data" field, then a read buffer overrun can occur.
-
- The same thing can also occur during name constraints processing of certificates
- (for example if a certificate has been directly constructed by the application
- instead of loading it via the OpenSSL parsing functions, and the certificate
- contains non NUL terminated ASN1_STRING structures). It can also occur in the
- X509_get1_email(), X509_REQ_get1_email() and X509_get1_ocsp() functions.
-
- If a malicious actor can cause an application to directly construct an
- ASN1_STRING and then process it through one of the affected OpenSSL functions
- then this issue could be hit. This might result in a crash (causing a Denial of
- Service attack). It could also result in the disclosure of private memory
- contents (such as private keys, or sensitive plaintext).
- (CVE-2021-3712)
- [Matt Caswell]
-
- Changes between 1.1.1j and 1.1.1k [25 Mar 2021]
-
- *) Fixed a problem with verifying a certificate chain when using the
- X509_V_FLAG_X509_STRICT flag. This flag enables additional security checks
- of the certificates present in a certificate chain. It is not set by
- default.
-
- Starting from OpenSSL version 1.1.1h a check to disallow certificates in
- the chain that have explicitly encoded elliptic curve parameters was added
- as an additional strict check.
-
- An error in the implementation of this check meant that the result of a
- previous check to confirm that certificates in the chain are valid CA
- certificates was overwritten. This effectively bypasses the check
- that non-CA certificates must not be able to issue other certificates.
-
- If a "purpose" has been configured then there is a subsequent opportunity
- for checks that the certificate is a valid CA. All of the named "purpose"
- values implemented in libcrypto perform this check. Therefore, where
- a purpose is set the certificate chain will still be rejected even when the
- strict flag has been used. A purpose is set by default in libssl client and
- server certificate verification routines, but it can be overridden or
- removed by an application.
-
- In order to be affected, an application must explicitly set the
- X509_V_FLAG_X509_STRICT verification flag and either not set a purpose
- for the certificate verification or, in the case of TLS client or server
- applications, override the default purpose.
- (CVE-2021-3450)
- [Tomáš Mráz]
-
- *) Fixed an issue where an OpenSSL TLS server may crash if sent a maliciously
- crafted renegotiation ClientHello message from a client. If a TLSv1.2
- renegotiation ClientHello omits the signature_algorithms extension (where
- it was present in the initial ClientHello), but includes a
- signature_algorithms_cert extension then a NULL pointer dereference will
- result, leading to a crash and a denial of service attack.
-
- A server is only vulnerable if it has TLSv1.2 and renegotiation enabled
- (which is the default configuration). OpenSSL TLS clients are not impacted
- by this issue.
- (CVE-2021-3449)
- [Peter Kästle and Samuel Sapalski]
-
- Changes between 1.1.1i and 1.1.1j [16 Feb 2021]
-
- *) Fixed the X509_issuer_and_serial_hash() function. It attempts to
- create a unique hash value based on the issuer and serial number data
- contained within an X509 certificate. However it was failing to correctly
- handle any errors that may occur while parsing the issuer field (which might
- occur if the issuer field is maliciously constructed). This may subsequently
- result in a NULL pointer deref and a crash leading to a potential denial of
- service attack.
- (CVE-2021-23841)
- [Matt Caswell]
-
- *) Fixed the RSA_padding_check_SSLv23() function and the RSA_SSLV23_PADDING
- padding mode to correctly check for rollback attacks. This is considered a
- bug in OpenSSL 1.1.1 because it does not support SSLv2. In 1.0.2 this is
- CVE-2021-23839.
- [Matt Caswell]
-
- *) Fixed the EVP_CipherUpdate, EVP_EncryptUpdate and EVP_DecryptUpdate
- functions. Previously they could overflow the output length argument in some
- cases where the input length is close to the maximum permissable length for
- an integer on the platform. In such cases the return value from the function
- call would be 1 (indicating success), but the output length value would be
- negative. This could cause applications to behave incorrectly or crash.
- (CVE-2021-23840)
- [Matt Caswell]
-
- *) Fixed SRP_Calc_client_key so that it runs in constant time. The previous
- implementation called BN_mod_exp without setting BN_FLG_CONSTTIME. This
- could be exploited in a side channel attack to recover the password. Since
- the attack is local host only this is outside of the current OpenSSL
- threat model and therefore no CVE is assigned.
-
- Thanks to Mohammed Sabt and Daniel De Almeida Braga for reporting this
- issue.
- [Matt Caswell]
-
- Changes between 1.1.1h and 1.1.1i [8 Dec 2020]
-
- *) Fixed NULL pointer deref in the GENERAL_NAME_cmp function
- This function could crash if both GENERAL_NAMEs contain an EDIPARTYNAME.
- If an attacker can control both items being compared then this could lead
- to a possible denial of service attack. OpenSSL itself uses the
- GENERAL_NAME_cmp function for two purposes:
- 1) Comparing CRL distribution point names between an available CRL and a
- CRL distribution point embedded in an X509 certificate
- 2) When verifying that a timestamp response token signer matches the
- timestamp authority name (exposed via the API functions
- TS_RESP_verify_response and TS_RESP_verify_token)
- (CVE-2020-1971)
- [Matt Caswell]
-
- *) Add support for Apple Silicon M1 Macs with the darwin64-arm64-cc target.
- [Stuart Carnie]
-
- *) The security callback, which can be customised by application code, supports
- the security operation SSL_SECOP_TMP_DH. This is defined to take an EVP_PKEY
- in the "other" parameter. In most places this is what is passed. All these
- places occur server side. However there was one client side call of this
- security operation and it passed a DH object instead. This is incorrect
- according to the definition of SSL_SECOP_TMP_DH, and is inconsistent with all
- of the other locations. Therefore this client side call has been changed to
- pass an EVP_PKEY instead.
- [Matt Caswell]
-
- *) In 1.1.1h, an expired trusted (root) certificate was not anymore rejected
- when validating a certificate path. This check is restored in 1.1.1i.
- [David von Oheimb]
-
- Changes between 1.1.1g and 1.1.1h [22 Sep 2020]
-
- *) Certificates with explicit curve parameters are now disallowed in
- verification chains if the X509_V_FLAG_X509_STRICT flag is used.
- [Tomas Mraz]
-
- *) The 'MinProtocol' and 'MaxProtocol' configuration commands now silently
- ignore TLS protocol version bounds when configuring DTLS-based contexts, and
- conversely, silently ignore DTLS protocol version bounds when configuring
- TLS-based contexts. The commands can be repeated to set bounds of both
- types. The same applies with the corresponding "min_protocol" and
- "max_protocol" command-line switches, in case some application uses both TLS
- and DTLS.
-
- SSL_CTX instances that are created for a fixed protocol version (e.g.
- TLSv1_server_method()) also silently ignore version bounds. Previously
- attempts to apply bounds to these protocol versions would result in an
- error. Now only the "version-flexible" SSL_CTX instances are subject to
- limits in configuration files in command-line options.
- [Viktor Dukhovni]
-
- *) Handshake now fails if Extended Master Secret extension is dropped
- on renegotiation.
- [Tomas Mraz]
-
- *) Accidentally, an expired trusted (root) certificate is not anymore rejected
- when validating a certificate path.
- [David von Oheimb]
-
- *) The Oracle Developer Studio compiler will start reporting deprecated APIs
-
- Changes between 1.1.1f and 1.1.1g [21 Apr 2020]
-
- *) Fixed segmentation fault in SSL_check_chain()
- Server or client applications that call the SSL_check_chain() function
- during or after a TLS 1.3 handshake may crash due to a NULL pointer
- dereference as a result of incorrect handling of the
- "signature_algorithms_cert" TLS extension. The crash occurs if an invalid
- or unrecognised signature algorithm is received from the peer. This could
- be exploited by a malicious peer in a Denial of Service attack.
- (CVE-2020-1967)
- [Benjamin Kaduk]
-
- *) Added AES consttime code for no-asm configurations
- an optional constant time support for AES was added
- when building openssl for no-asm.
- Enable with: ./config no-asm -DOPENSSL_AES_CONST_TIME
- Disable with: ./config no-asm -DOPENSSL_NO_AES_CONST_TIME
- At this time this feature is by default disabled.
- It will be enabled by default in 3.0.
- [Bernd Edlinger]
-
- Changes between 1.1.1e and 1.1.1f [31 Mar 2020]
-
- *) Revert the change of EOF detection while reading in libssl to avoid
- regressions in applications depending on the current way of reporting
- the EOF. As the existing method is not fully accurate the change to
- reporting the EOF via SSL_ERROR_SSL is kept on the current development
- branch and will be present in the 3.0 release.
- [Tomas Mraz]
-
- *) Revised BN_generate_prime_ex to not avoid factors 3..17863 in p-1
- when primes for RSA keys are computed.
- Since we previously always generated primes == 2 (mod 3) for RSA keys,
- the 2-prime and 3-prime RSA modules were easy to distinguish, since
- N = p*q = 1 (mod 3), but N = p*q*r = 2 (mod 3). Therefore fingerprinting
- 2-prime vs. 3-prime RSA keys was possible by computing N mod 3.
- This avoids possible fingerprinting of newly generated RSA modules.
- [Bernd Edlinger]
-
- Changes between 1.1.1d and 1.1.1e [17 Mar 2020]
- *) Properly detect EOF while reading in libssl. Previously if we hit an EOF
- while reading in libssl then we would report an error back to the
- application (SSL_ERROR_SYSCALL) but errno would be 0. We now add
- an error to the stack (which means we instead return SSL_ERROR_SSL) and
- therefore give a hint as to what went wrong.
- [Matt Caswell]
-
- *) Check that ed25519 and ed448 are allowed by the security level. Previously
- signature algorithms not using an MD were not being checked that they were
- allowed by the security level.
- [Kurt Roeckx]
-
- *) Fixed SSL_get_servername() behaviour. The behaviour of SSL_get_servername()
- was not quite right. The behaviour was not consistent between resumption
- and normal handshakes, and also not quite consistent with historical
- behaviour. The behaviour in various scenarios has been clarified and
- it has been updated to make it match historical behaviour as closely as
- possible.
- [Matt Caswell]
-
- *) [VMS only] The header files that the VMS compilers include automatically,
- __DECC_INCLUDE_PROLOGUE.H and __DECC_INCLUDE_EPILOGUE.H, use pragmas that
- the C++ compiler doesn't understand. This is a shortcoming in the
- compiler, but can be worked around with __cplusplus guards.
-
- C++ applications that use OpenSSL libraries must be compiled using the
- qualifier '/NAMES=(AS_IS,SHORTENED)' to be able to use all the OpenSSL
- functions. Otherwise, only functions with symbols of less than 31
- characters can be used, as the linker will not be able to successfully
- resolve symbols with longer names.
- [Richard Levitte]
-
- *) Corrected the documentation of the return values from the EVP_DigestSign*
- set of functions. The documentation mentioned negative values for some
- errors, but this was never the case, so the mention of negative values
- was removed.
-
- Code that followed the documentation and thereby check with something
- like 'EVP_DigestSignInit(...) <= 0' will continue to work undisturbed.
- [Richard Levitte]
-
- *) Fixed an an overflow bug in the x64_64 Montgomery squaring procedure
- used in exponentiation with 512-bit moduli. No EC algorithms are
- affected. Analysis suggests that attacks against 2-prime RSA1024,
- 3-prime RSA1536, and DSA1024 as a result of this defect would be very
- difficult to perform and are not believed likely. Attacks against DH512
- are considered just feasible. However, for an attack the target would
- have to re-use the DH512 private key, which is not recommended anyway.
- Also applications directly using the low level API BN_mod_exp may be
- affected if they use BN_FLG_CONSTTIME.
- (CVE-2019-1551)
- [Andy Polyakov]
-
- *) Added a new method to gather entropy on VMS, based on SYS$GET_ENTROPY.
- The presence of this system service is determined at run-time.
- [Richard Levitte]
-
- *) Added newline escaping functionality to a filename when using openssl dgst.
- This output format is to replicate the output format found in the '*sum'
- checksum programs. This aims to preserve backward compatibility.
- [Matt Eaton, Richard Levitte, and Paul Dale]
-
- *) Print all values for a PKCS#12 attribute with 'openssl pkcs12', not just
- the first value.
- [Jon Spillett]
-
- Changes between 1.1.1c and 1.1.1d [10 Sep 2019]
-
- *) Fixed a fork protection issue. OpenSSL 1.1.1 introduced a rewritten random
- number generator (RNG). This was intended to include protection in the
- event of a fork() system call in order to ensure that the parent and child
- processes did not share the same RNG state. However this protection was not
- being used in the default case.
-
- A partial mitigation for this issue is that the output from a high
- precision timer is mixed into the RNG state so the likelihood of a parent
- and child process sharing state is significantly reduced.
-
- If an application already calls OPENSSL_init_crypto() explicitly using
- OPENSSL_INIT_ATFORK then this problem does not occur at all.
- (CVE-2019-1549)
- [Matthias St. Pierre]
-
- *) For built-in EC curves, ensure an EC_GROUP built from the curve name is
- used even when parsing explicit parameters, when loading a serialized key
- or calling `EC_GROUP_new_from_ecpkparameters()`/
- `EC_GROUP_new_from_ecparameters()`.
- This prevents bypass of security hardening and performance gains,
- especially for curves with specialized EC_METHODs.
- By default, if a key encoded with explicit parameters is loaded and later
- serialized, the output is still encoded with explicit parameters, even if
- internally a "named" EC_GROUP is used for computation.
- [Nicola Tuveri]
-
- *) Compute ECC cofactors if not provided during EC_GROUP construction. Before
- this change, EC_GROUP_set_generator would accept order and/or cofactor as
- NULL. After this change, only the cofactor parameter can be NULL. It also
- does some minimal sanity checks on the passed order.
- (CVE-2019-1547)
- [Billy Bob Brumley]
-
- *) Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey.
- An attack is simple, if the first CMS_recipientInfo is valid but the
- second CMS_recipientInfo is chosen ciphertext. If the second
- recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct
- encryption key will be replaced by garbage, and the message cannot be
- decoded, but if the RSA decryption fails, the correct encryption key is
- used and the recipient will not notice the attack.
- As a work around for this potential attack the length of the decrypted
- key must be equal to the cipher default key length, in case the
- certifiate is not given and all recipientInfo are tried out.
- The old behaviour can be re-enabled in the CMS code by setting the
- CMS_DEBUG_DECRYPT flag.
- (CVE-2019-1563)
- [Bernd Edlinger]
-
- *) Early start up entropy quality from the DEVRANDOM seed source has been
- improved for older Linux systems. The RAND subsystem will wait for
- /dev/random to be producing output before seeding from /dev/urandom.
- The seeded state is stored for future library initialisations using
- a system global shared memory segment. The shared memory identifier
- can be configured by defining OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID to
- the desired value. The default identifier is 114.
- [Paul Dale]
-
- *) Correct the extended master secret constant on EBCDIC systems. Without this
- fix TLS connections between an EBCDIC system and a non-EBCDIC system that
- negotiate EMS will fail. Unfortunately this also means that TLS connections
- between EBCDIC systems with this fix, and EBCDIC systems without this
- fix will fail if they negotiate EMS.
- [Matt Caswell]
-
- *) Use Windows installation paths in the mingw builds
-
- Mingw isn't a POSIX environment per se, which means that Windows
- paths should be used for installation.
- (CVE-2019-1552)
- [Richard Levitte]
-
- *) Changed DH_check to accept parameters with order q and 2q subgroups.
- With order 2q subgroups the bit 0 of the private key is not secret
- but DH_generate_key works around that by clearing bit 0 of the
- private key for those. This avoids leaking bit 0 of the private key.
- [Bernd Edlinger]
-
- *) Significantly reduce secure memory usage by the randomness pools.
- [Paul Dale]
-
- *) Revert the DEVRANDOM_WAIT feature for Linux systems
-
- The DEVRANDOM_WAIT feature added a select() call to wait for the
- /dev/random device to become readable before reading from the
- /dev/urandom device.
-
- It turned out that this change had negative side effects on
- performance which were not acceptable. After some discussion it
- was decided to revert this feature and leave it up to the OS
- resp. the platform maintainer to ensure a proper initialization
- during early boot time.
- [Matthias St. Pierre]
-
- Changes between 1.1.1b and 1.1.1c [28 May 2019]
-
- *) Add build tests for C++. These are generated files that only do one
- thing, to include one public OpenSSL head file each. This tests that
- the public header files can be usefully included in a C++ application.
-
- This test isn't enabled by default. It can be enabled with the option
- 'enable-buildtest-c++'.
- [Richard Levitte]
-
- *) Enable SHA3 pre-hashing for ECDSA and DSA.
- [Patrick Steuer]
-
- *) Change the default RSA, DSA and DH size to 2048 bit instead of 1024.
- This changes the size when using the genpkey app when no size is given. It
- fixes an omission in earlier changes that changed all RSA, DSA and DH
- generation apps to use 2048 bits by default.
- [Kurt Roeckx]
-
- *) Reorganize the manual pages to consistently have RETURN VALUES,
- EXAMPLES, SEE ALSO and HISTORY come in that order, and adjust
- util/fix-doc-nits accordingly.
- [Paul Yang, Joshua Lock]
-
- *) Add the missing accessor EVP_PKEY_get0_engine()
- [Matt Caswell]
-
- *) Have apps like 's_client' and 's_server' output the signature scheme
- along with other cipher suite parameters when debugging.
- [Lorinczy Zsigmond]
-
- *) Make OPENSSL_config() error agnostic again.
- [Richard Levitte]
-
- *) Do the error handling in RSA decryption constant time.
- [Bernd Edlinger]
-
- *) Prevent over long nonces in ChaCha20-Poly1305.
-
- ChaCha20-Poly1305 is an AEAD cipher, and requires a unique nonce input
- for every encryption operation. RFC 7539 specifies that the nonce value
- (IV) should be 96 bits (12 bytes). OpenSSL allows a variable nonce length
- and front pads the nonce with 0 bytes if it is less than 12
- bytes. However it also incorrectly allows a nonce to be set of up to 16
- bytes. In this case only the last 12 bytes are significant and any
- additional leading bytes are ignored.
-
- It is a requirement of using this cipher that nonce values are
- unique. Messages encrypted using a reused nonce value are susceptible to
- serious confidentiality and integrity attacks. If an application changes
- the default nonce length to be longer than 12 bytes and then makes a
- change to the leading bytes of the nonce expecting the new value to be a
- new unique nonce then such an application could inadvertently encrypt
- messages with a reused nonce.
-
- Additionally the ignored bytes in a long nonce are not covered by the
- integrity guarantee of this cipher. Any application that relies on the
- integrity of these ignored leading bytes of a long nonce may be further
- affected. Any OpenSSL internal use of this cipher, including in SSL/TLS,
- is safe because no such use sets such a long nonce value. However user
- applications that use this cipher directly and set a non-default nonce
- length to be longer than 12 bytes may be vulnerable.
-
- This issue was reported to OpenSSL on 16th of March 2019 by Joran Dirk
- Greef of Ronomon.
- (CVE-2019-1543)
- [Matt Caswell]
-
- *) Add DEVRANDOM_WAIT feature for Linux systems
-
- On older Linux systems where the getrandom() system call is not available,
- OpenSSL normally uses the /dev/urandom device for seeding its CSPRNG.
- Contrary to getrandom(), the /dev/urandom device will not block during
- early boot when the kernel CSPRNG has not been seeded yet.
-
- To mitigate this known weakness, use select() to wait for /dev/random to
- become readable before reading from /dev/urandom.
-
- *) Ensure that SM2 only uses SM3 as digest algorithm
- [Paul Yang]
-
- Changes between 1.1.1a and 1.1.1b [26 Feb 2019]
-
- *) Added SCA hardening for modular field inversion in EC_GROUP through
- a new dedicated field_inv() pointer in EC_METHOD.
- This also addresses a leakage affecting conversions from projective
- to affine coordinates.
- [Billy Bob Brumley, Nicola Tuveri]
-
- *) Change the info callback signals for the start and end of a post-handshake
- message exchange in TLSv1.3. In 1.1.1/1.1.1a we used SSL_CB_HANDSHAKE_START
- and SSL_CB_HANDSHAKE_DONE. Experience has shown that many applications get
- confused by this and assume that a TLSv1.2 renegotiation has started. This
- can break KeyUpdate handling. Instead we no longer signal the start and end
- of a post handshake message exchange (although the messages themselves are
- still signalled). This could break some applications that were expecting
- the old signals. However without this KeyUpdate is not usable for many
- applications.
- [Matt Caswell]
-
- *) Fix a bug in the computation of the endpoint-pair shared secret used
- by DTLS over SCTP. This breaks interoperability with older versions
- of OpenSSL like OpenSSL 1.1.0 and OpenSSL 1.0.2. There is a runtime
- switch SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG (off by default) enabling
- interoperability with such broken implementations. However, enabling
- this switch breaks interoperability with correct implementations.
-
- *) Fix a use after free bug in d2i_X509_PUBKEY when overwriting a
- re-used X509_PUBKEY object if the second PUBKEY is malformed.
- [Bernd Edlinger]
-
- *) Move strictness check from EVP_PKEY_asn1_new() to EVP_PKEY_asn1_add0().
- [Richard Levitte]
-
- *) Remove the 'dist' target and add a tarball building script. The
- 'dist' target has fallen out of use, and it shouldn't be
- necessary to configure just to create a source distribution.
- [Richard Levitte]
-
- Changes between 1.1.1 and 1.1.1a [20 Nov 2018]
-
- *) Timing vulnerability in DSA signature generation
-
- The OpenSSL DSA signature algorithm has been shown to be vulnerable to a
- timing side channel attack. An attacker could use variations in the signing
- algorithm to recover the private key.
-
- This issue was reported to OpenSSL on 16th October 2018 by Samuel Weiser.
- (CVE-2018-0734)
- [Paul Dale]
-
- *) Timing vulnerability in ECDSA signature generation
-
- The OpenSSL ECDSA signature algorithm has been shown to be vulnerable to a
- timing side channel attack. An attacker could use variations in the signing
- algorithm to recover the private key.
-
- This issue was reported to OpenSSL on 25th October 2018 by Samuel Weiser.
- (CVE-2018-0735)
- [Paul Dale]
-
- *) Added EVP_PKEY_ECDH_KDF_X9_63 and ecdh_KDF_X9_63() as replacements for
- the EVP_PKEY_ECDH_KDF_X9_62 KDF type and ECDH_KDF_X9_62(). The old names
- are retained for backwards compatibility.
- [Antoine Salon]
-
- *) Fixed the issue that RAND_add()/RAND_seed() silently discards random input
- if its length exceeds 4096 bytes. The limit has been raised to a buffer size
- of two gigabytes and the error handling improved.
-
- This issue was reported to OpenSSL by Dr. Falko Strenzke. It has been
- categorized as a normal bug, not a security issue, because the DRBG reseeds
- automatically and is fully functional even without additional randomness
- provided by the application.
-
- Changes between 1.1.0i and 1.1.1 [11 Sep 2018]
-
- *) Add a new ClientHello callback. Provides a callback interface that gives
- the application the ability to adjust the nascent SSL object at the
- earliest stage of ClientHello processing, immediately after extensions have
- been collected but before they have been processed. In particular, this
- callback can adjust the supported TLS versions in response to the contents
- of the ClientHello
- [Benjamin Kaduk]
-
- *) Add SM2 base algorithm support.
- [Jack Lloyd]
-
- *) s390x assembly pack: add (improved) hardware-support for the following
- cryptographic primitives: sha3, shake, aes-gcm, aes-ccm, aes-ctr, aes-ofb,
- aes-cfb/cfb8, aes-ecb.
- [Patrick Steuer]
-
- *) Make EVP_PKEY_asn1_new() a bit stricter about its input. A NULL pem_str
- parameter is no longer accepted, as it leads to a corrupt table. NULL
- pem_str is reserved for alias entries only.
- [Richard Levitte]
-
- *) Use the new ec_scalar_mul_ladder scaffold to implement a specialized ladder
- step for prime curves. The new implementation is based on formulae from
- differential addition-and-doubling in homogeneous projective coordinates
- from Izu-Takagi "A fast parallel elliptic curve multiplication resistant
- against side channel attacks" and Brier-Joye "Weierstrass Elliptic Curves
- and Side-Channel Attacks" Eq. (8) for y-coordinate recovery, modified
- to work in projective coordinates.
- [Billy Bob Brumley, Nicola Tuveri]
-
- *) Change generating and checking of primes so that the error rate of not
- being prime depends on the intended use based on the size of the input.
- For larger primes this will result in more rounds of Miller-Rabin.
- The maximal error rate for primes with more than 1080 bits is lowered
- to 2^-128.
- [Kurt Roeckx, Annie Yousar]
-
- *) Increase the number of Miller-Rabin rounds for DSA key generating to 64.
- [Kurt Roeckx]
-
- *) The 'tsget' script is renamed to 'tsget.pl', to avoid confusion when
- moving between systems, and to avoid confusion when a Windows build is
- done with mingw vs with MSVC. For POSIX installs, there's still a
- symlink or copy named 'tsget' to avoid that confusion as well.
- [Richard Levitte]
-
- *) Revert blinding in ECDSA sign and instead make problematic addition
- length-invariant. Switch even to fixed-length Montgomery multiplication.
- [Andy Polyakov]
-
- *) Use the new ec_scalar_mul_ladder scaffold to implement a specialized ladder
- step for binary curves. The new implementation is based on formulae from
- differential addition-and-doubling in mixed Lopez-Dahab projective
- coordinates, modified to independently blind the operands.
- [Billy Bob Brumley, Sohaib ul Hassan, Nicola Tuveri]
-
- *) Add a scaffold to optionally enhance the Montgomery ladder implementation
- for `ec_scalar_mul_ladder` (formerly `ec_mul_consttime`) allowing
- EC_METHODs to implement their own specialized "ladder step", to take
- advantage of more favorable coordinate systems or more efficient
- differential addition-and-doubling algorithms.
- [Billy Bob Brumley, Sohaib ul Hassan, Nicola Tuveri]
-
- *) Modified the random device based seed sources to keep the relevant
- file descriptors open rather than reopening them on each access.
- This allows such sources to operate in a chroot() jail without
- the associated device nodes being available. This behaviour can be
- controlled using RAND_keep_random_devices_open().
- [Paul Dale]
-
- *) Numerous side-channel attack mitigations have been applied. This may have
- performance impacts for some algorithms for the benefit of improved
- security. Specific changes are noted in this change log by their respective
- authors.
- [Matt Caswell]
-
- *) AIX shared library support overhaul. Switch to AIX "natural" way of
- handling shared libraries, which means collecting shared objects of
- different versions and bitnesses in one common archive. This allows to
- mitigate conflict between 1.0 and 1.1 side-by-side installations. It
- doesn't affect the way 3rd party applications are linked, only how
- multi-version installation is managed.
- [Andy Polyakov]
-
- *) Make ec_group_do_inverse_ord() more robust and available to other
- EC cryptosystems, so that irrespective of BN_FLG_CONSTTIME, SCA
- mitigations are applied to the fallback BN_mod_inverse().
- When using this function rather than BN_mod_inverse() directly, new
- EC cryptosystem implementations are then safer-by-default.
- [Billy Bob Brumley]
-
- *) Add coordinate blinding for EC_POINT and implement projective
- coordinate blinding for generic prime curves as a countermeasure to
- chosen point SCA attacks.
- [Sohaib ul Hassan, Nicola Tuveri, Billy Bob Brumley]
-
- *) Add blinding to ECDSA and DSA signatures to protect against side channel
- attacks discovered by Keegan Ryan (NCC Group).
- [Matt Caswell]
-
- *) Enforce checking in the pkeyutl command line app to ensure that the input
- length does not exceed the maximum supported digest length when performing
- a sign, verify or verifyrecover operation.
- [Matt Caswell]
-
- *) SSL_MODE_AUTO_RETRY is enabled by default. Applications that use blocking
- I/O in combination with something like select() or poll() will hang. This
- can be turned off again using SSL_CTX_clear_mode().
- Many applications do not properly handle non-application data records, and
- TLS 1.3 sends more of such records. Setting SSL_MODE_AUTO_RETRY works
- around the problems in those applications, but can also break some.
- It's recommended to read the manpages about SSL_read(), SSL_write(),
- SSL_get_error(), SSL_shutdown(), SSL_CTX_set_mode() and
- SSL_CTX_set_read_ahead() again.
- [Kurt Roeckx]
-
- *) When unlocking a pass phrase protected PEM file or PKCS#8 container, we
- now allow empty (zero character) pass phrases.
- [Richard Levitte]
-
- *) Apply blinding to binary field modular inversion and remove patent
- pending (OPENSSL_SUN_GF2M_DIV) BN_GF2m_mod_div implementation.
- [Billy Bob Brumley]
-
- *) Deprecate ec2_mult.c and unify scalar multiplication code paths for
- binary and prime elliptic curves.
- [Billy Bob Brumley]
-
- *) Remove ECDSA nonce padding: EC_POINT_mul is now responsible for
- constant time fixed point multiplication.
- [Billy Bob Brumley]
-
- *) Revise elliptic curve scalar multiplication with timing attack
- defenses: ec_wNAF_mul redirects to a constant time implementation
- when computing fixed point and variable point multiplication (which
- in OpenSSL are mostly used with secret scalars in keygen, sign,
- ECDH derive operations).
- [Billy Bob Brumley, Nicola Tuveri, Cesar Pereida García,
- Sohaib ul Hassan]
-
- *) Updated CONTRIBUTING
- [Rich Salz]
-
- *) Updated DRBG / RAND to request nonce and additional low entropy
- randomness from the system.
- [Matthias St. Pierre]
-
- *) Updated 'openssl rehash' to use OpenSSL consistent default.
- [Richard Levitte]
-
- *) Moved the load of the ssl_conf module to libcrypto, which helps
- loading engines that libssl uses before libssl is initialised.
- [Matt Caswell]
-
- *) Added EVP_PKEY_sign() and EVP_PKEY_verify() for EdDSA
- [Matt Caswell]
-
- *) Fixed X509_NAME_ENTRY_set to get multi-valued RDNs right in all cases.
- [Ingo Schwarze, Rich Salz]
-
- *) Added output of accepting IP address and port for 'openssl s_server'
- [Richard Levitte]
-
- *) Added a new API for TLSv1.3 ciphersuites:
- SSL_CTX_set_ciphersuites()
- SSL_set_ciphersuites()
- [Matt Caswell]
-
- *) Memory allocation failures consistently add an error to the error
- stack.
- [Rich Salz]
-
- *) Don't use OPENSSL_ENGINES and OPENSSL_CONF environment values
- in libcrypto when run as setuid/setgid.
- [Bernd Edlinger]
-
- *) Load any config file by default when libssl is used.
- [Matt Caswell]
-
- *) Added new public header file <openssl/rand_drbg.h> and documentation
- for the RAND_DRBG API. See manual page RAND_DRBG(7) for an overview.
- [Matthias St. Pierre]
-
- *) QNX support removed (cannot find contributors to get their approval
- for the license change).
- [Rich Salz]
-
- *) TLSv1.3 replay protection for early data has been implemented. See the
- SSL_read_early_data() man page for further details.
- [Matt Caswell]
-
- *) Separated TLSv1.3 ciphersuite configuration out from TLSv1.2 ciphersuite
- configuration. TLSv1.3 ciphersuites are not compatible with TLSv1.2 and
- below. Similarly TLSv1.2 ciphersuites are not compatible with TLSv1.3.
- In order to avoid issues where legacy TLSv1.2 ciphersuite configuration
- would otherwise inadvertently disable all TLSv1.3 ciphersuites the
- configuration has been separated out. See the ciphers man page or the
- SSL_CTX_set_ciphersuites() man page for more information.
- [Matt Caswell]
-
- *) On POSIX (BSD, Linux, ...) systems the ocsp(1) command running
- in responder mode now supports the new "-multi" option, which
- spawns the specified number of child processes to handle OCSP
- requests. The "-timeout" option now also limits the OCSP
- responder's patience to wait to receive the full client request
- on a newly accepted connection. Child processes are respawned
- as needed, and the CA index file is automatically reloaded
- when changed. This makes it possible to run the "ocsp" responder
- as a long-running service, making the OpenSSL CA somewhat more
- feature-complete. In this mode, most diagnostic messages logged
- after entering the event loop are logged via syslog(3) rather than
- written to stderr.
- [Viktor Dukhovni]
-
- *) Added support for X448 and Ed448. Heavily based on original work by
- Mike Hamburg.
- [Matt Caswell]
-
- *) Extend OSSL_STORE with capabilities to search and to narrow the set of
- objects loaded. This adds the functions OSSL_STORE_expect() and
- OSSL_STORE_find() as well as needed tools to construct searches and
- get the search data out of them.
- [Richard Levitte]
-
- *) Support for TLSv1.3 added. Note that users upgrading from an earlier
- version of OpenSSL should review their configuration settings to ensure
- that they are still appropriate for TLSv1.3. For further information see:
- https://wiki.openssl.org/index.php/TLS1.3
- [Matt Caswell]
-
- *) Grand redesign of the OpenSSL random generator
-
- The default RAND method now utilizes an AES-CTR DRBG according to
- NIST standard SP 800-90Ar1. The new random generator is essentially
- a port of the default random generator from the OpenSSL FIPS 2.0
- object module. It is a hybrid deterministic random bit generator
- using an AES-CTR bit stream and which seeds and reseeds itself
- automatically using trusted system entropy sources.
-
- Some of its new features are:
- o Support for multiple DRBG instances with seed chaining.
- o The default RAND method makes use of a DRBG.
- o There is a public and private DRBG instance.
- o The DRBG instances are fork-safe.
- o Keep all global DRBG instances on the secure heap if it is enabled.
- o The public and private DRBG instance are per thread for lock free
- operation
- [Paul Dale, Benjamin Kaduk, Kurt Roeckx, Rich Salz, Matthias St. Pierre]
-
- *) Changed Configure so it only says what it does and doesn't dump
- so much data. Instead, ./configdata.pm should be used as a script
- to display all sorts of configuration data.
- [Richard Levitte]
-
- *) Added processing of "make variables" to Configure.
- [Richard Levitte]
-
- *) Added SHA512/224 and SHA512/256 algorithm support.
- [Paul Dale]
-
- *) The last traces of Netware support, first removed in 1.1.0, have
- now been removed.
- [Rich Salz]
-
- *) Get rid of Makefile.shared, and in the process, make the processing
- of certain files (rc.obj, or the .def/.map/.opt files produced from
- the ordinal files) more visible and hopefully easier to trace and
- debug (or make silent).
- [Richard Levitte]
-
- *) Make it possible to have environment variable assignments as
- arguments to config / Configure.
- [Richard Levitte]
-
- *) Add multi-prime RSA (RFC 8017) support.
- [Paul Yang]
-
- *) Add SM3 implemented according to GB/T 32905-2016
- [ Jack Lloyd <jack.lloyd@ribose.com>,
- Ronald Tse <ronald.tse@ribose.com>,
- Erick Borsboom <erick.borsboom@ribose.com> ]
-
- *) Add 'Maximum Fragment Length' TLS extension negotiation and support
- as documented in RFC6066.
- Based on a patch from Tomasz Moń
- [Filipe Raimundo da Silva]
-
- *) Add SM4 implemented according to GB/T 32907-2016.
- [ Jack Lloyd <jack.lloyd@ribose.com>,
- Ronald Tse <ronald.tse@ribose.com>,
- Erick Borsboom <erick.borsboom@ribose.com> ]
-
- *) Reimplement -newreq-nodes and ERR_error_string_n; the
- original author does not agree with the license change.
- [Rich Salz]
-
- *) Add ARIA AEAD TLS support.
- [Jon Spillett]
-
- *) Some macro definitions to support VS6 have been removed. Visual
- Studio 6 has not worked since 1.1.0
- [Rich Salz]
-
- *) Add ERR_clear_last_mark(), to allow callers to clear the last mark
- without clearing the errors.
- [Richard Levitte]
-
- *) Add "atfork" functions. If building on a system that without
- pthreads, see doc/man3/OPENSSL_fork_prepare.pod for application
- requirements. The RAND facility now uses/requires this.
- [Rich Salz]
-
- *) Add SHA3.
- [Andy Polyakov]
-
- *) The UI API becomes a permanent and integral part of libcrypto, i.e.
- not possible to disable entirely. However, it's still possible to
- disable the console reading UI method, UI_OpenSSL() (use UI_null()
- as a fallback).
-
- To disable, configure with 'no-ui-console'. 'no-ui' is still
- possible to use as an alias. Check at compile time with the
- macro OPENSSL_NO_UI_CONSOLE. The macro OPENSSL_NO_UI is still
- possible to check and is an alias for OPENSSL_NO_UI_CONSOLE.
- [Richard Levitte]
-
- *) Add a STORE module, which implements a uniform and URI based reader of
- stores that can contain keys, certificates, CRLs and numerous other
- objects. The main API is loosely based on a few stdio functions,
- and includes OSSL_STORE_open, OSSL_STORE_load, OSSL_STORE_eof,
- OSSL_STORE_error and OSSL_STORE_close.
- The implementation uses backends called "loaders" to implement arbitrary
- URI schemes. There is one built in "loader" for the 'file' scheme.
- [Richard Levitte]
-
- *) Add devcrypto engine. This has been implemented against cryptodev-linux,
- then adjusted to work on FreeBSD 8.4 as well.
- Enable by configuring with 'enable-devcryptoeng'. This is done by default
- on BSD implementations, as cryptodev.h is assumed to exist on all of them.
- [Richard Levitte]
-
- *) Module names can prefixed with OSSL_ or OPENSSL_. This affects
- util/mkerr.pl, which is adapted to allow those prefixes, leading to
- error code calls like this:
-
- OSSL_FOOerr(OSSL_FOO_F_SOMETHING, OSSL_FOO_R_WHATEVER);
-
- With this change, we claim the namespaces OSSL and OPENSSL in a manner
- that can be encoded in C. For the foreseeable future, this will only
- affect new modules.
- [Richard Levitte and Tim Hudson]
-
- *) Removed BSD cryptodev engine.
- [Rich Salz]
-
- *) Add a build target 'build_all_generated', to build all generated files
- and only that. This can be used to prepare everything that requires
- things like perl for a system that lacks perl and then move everything
- to that system and do the rest of the build there.
- [Richard Levitte]
-
- *) In the UI interface, make it possible to duplicate the user data. This
- can be used by engines that need to retain the data for a longer time
- than just the call where this user data is passed.
- [Richard Levitte]
-
- *) Ignore the '-named_curve auto' value for compatibility of applications
- with OpenSSL 1.0.2.
- [Tomas Mraz <tmraz@fedoraproject.org>]
-
- *) Fragmented SSL/TLS alerts are no longer accepted. An alert message is 2
- bytes long. In theory it is permissible in SSLv3 - TLSv1.2 to fragment such
- alerts across multiple records (some of which could be empty). In practice
- it make no sense to send an empty alert record, or to fragment one. TLSv1.3
- prohibits this altogether and other libraries (BoringSSL, NSS) do not
- support this at all. Supporting it adds significant complexity to the
- record layer, and its removal is unlikely to cause interoperability
- issues.
- [Matt Caswell]
-
- *) Add the ASN.1 types INT32, UINT32, INT64, UINT64 and variants prefixed
- with Z. These are meant to replace LONG and ZLONG and to be size safe.
- The use of LONG and ZLONG is discouraged and scheduled for deprecation
- in OpenSSL 1.2.0.
- [Richard Levitte]
-
- *) Add the 'z' and 'j' modifiers to BIO_printf() et al formatting string,
- 'z' is to be used for [s]size_t, and 'j' - with [u]int64_t.
- [Richard Levitte, Andy Polyakov]
-
- *) Add EC_KEY_get0_engine(), which does for EC_KEY what RSA_get0_engine()
- does for RSA, etc.
- [Richard Levitte]
-
- *) Have 'config' recognise 64-bit mingw and choose 'mingw64' as the target
- platform rather than 'mingw'.
- [Richard Levitte]
-
- *) The functions X509_STORE_add_cert and X509_STORE_add_crl return
- success if they are asked to add an object which already exists
- in the store. This change cascades to other functions which load
- certificates and CRLs.
- [Paul Dale]
-
- *) x86_64 assembly pack: annotate code with DWARF CFI directives to
- facilitate stack unwinding even from assembly subroutines.
- [Andy Polyakov]
-
- *) Remove VAX C specific definitions of OPENSSL_EXPORT, OPENSSL_EXTERN.
- Also remove OPENSSL_GLOBAL entirely, as it became a no-op.
- [Richard Levitte]
-
- *) Remove the VMS-specific reimplementation of gmtime from crypto/o_times.c.
- VMS C's RTL has a fully up to date gmtime() and gmtime_r() since V7.1,
- which is the minimum version we support.
- [Richard Levitte]
-
- *) Certificate time validation (X509_cmp_time) enforces stricter
- compliance with RFC 5280. Fractional seconds and timezone offsets
- are no longer allowed.
- [Emilia Käsper]
-
- *) Add support for ARIA
- [Paul Dale]
-
- *) s_client will now send the Server Name Indication (SNI) extension by
- default unless the new "-noservername" option is used. The server name is
- based on the host provided to the "-connect" option unless overridden by
- using "-servername".
- [Matt Caswell]
-
- *) Add support for SipHash
- [Todd Short]
-
- *) OpenSSL now fails if it receives an unrecognised record type in TLS1.0
- or TLS1.1. Previously this only happened in SSLv3 and TLS1.2. This is to
- prevent issues where no progress is being made and the peer continually
- sends unrecognised record types, using up resources processing them.
- [Matt Caswell]
-
- *) 'openssl passwd' can now produce SHA256 and SHA512 based output,
- using the algorithm defined in
- https://www.akkadia.org/drepper/SHA-crypt.txt
- [Richard Levitte]
-
- *) Heartbeat support has been removed; the ABI is changed for now.
- [Richard Levitte, Rich Salz]
-
- *) Support for SSL_OP_NO_ENCRYPT_THEN_MAC in SSL_CONF_cmd.
- [Emilia Käsper]
-
- *) The RSA "null" method, which was partially supported to avoid patent
- issues, has been replaced to always returns NULL.
- [Rich Salz]
-
-
- Changes between 1.1.0h and 1.1.0i [xx XXX xxxx]
-
- *) Client DoS due to large DH parameter
-
- During key agreement in a TLS handshake using a DH(E) based ciphersuite a
- malicious server can send a very large prime value to the client. This will
- cause the client to spend an unreasonably long period of time generating a
- key for this prime resulting in a hang until the client has finished. This
- could be exploited in a Denial Of Service attack.
-
- This issue was reported to OpenSSL on 5th June 2018 by Guido Vranken
- (CVE-2018-0732)
- [Guido Vranken]
-
- *) Cache timing vulnerability in RSA Key Generation
-
- The OpenSSL RSA Key generation algorithm has been shown to be vulnerable to
- a cache timing side channel attack. An attacker with sufficient access to
- mount cache timing attacks during the RSA key generation process could
- recover the private key.
-
- This issue was reported to OpenSSL on 4th April 2018 by Alejandro Cabrera
- Aldaya, Billy Brumley, Cesar Pereida Garcia and Luis Manuel Alvarez Tapia.
- (CVE-2018-0737)
- [Billy Brumley]
-
- *) Make EVP_PKEY_asn1_new() a bit stricter about its input. A NULL pem_str
- parameter is no longer accepted, as it leads to a corrupt table. NULL
- pem_str is reserved for alias entries only.
- [Richard Levitte]
-
- *) Revert blinding in ECDSA sign and instead make problematic addition
- length-invariant. Switch even to fixed-length Montgomery multiplication.
- [Andy Polyakov]
-
- *) Change generating and checking of primes so that the error rate of not
- being prime depends on the intended use based on the size of the input.
- For larger primes this will result in more rounds of Miller-Rabin.
- The maximal error rate for primes with more than 1080 bits is lowered
- to 2^-128.
- [Kurt Roeckx, Annie Yousar]
-
- *) Increase the number of Miller-Rabin rounds for DSA key generating to 64.
- [Kurt Roeckx]
-
- *) Add blinding to ECDSA and DSA signatures to protect against side channel
- attacks discovered by Keegan Ryan (NCC Group).
- [Matt Caswell]
-
- *) When unlocking a pass phrase protected PEM file or PKCS#8 container, we
- now allow empty (zero character) pass phrases.
- [Richard Levitte]
-
- *) Certificate time validation (X509_cmp_time) enforces stricter
- compliance with RFC 5280. Fractional seconds and timezone offsets
- are no longer allowed.
- [Emilia Käsper]
-
- *) Fixed a text canonicalisation bug in CMS
-
- Where a CMS detached signature is used with text content the text goes
- through a canonicalisation process first prior to signing or verifying a
- signature. This process strips trailing space at the end of lines, converts
- line terminators to CRLF and removes additional trailing line terminators
- at the end of a file. A bug in the canonicalisation process meant that
- some characters, such as form-feed, were incorrectly treated as whitespace
- and removed. This is contrary to the specification (RFC5485). This fix
- could mean that detached text data signed with an earlier version of
- OpenSSL 1.1.0 may fail to verify using the fixed version, or text data
- signed with a fixed OpenSSL may fail to verify with an earlier version of
- OpenSSL 1.1.0. A workaround is to only verify the canonicalised text data
- and use the "-binary" flag (for the "cms" command line application) or set
- the SMIME_BINARY/PKCS7_BINARY/CMS_BINARY flags (if using CMS_verify()).
- [Matt Caswell]
-
- Changes between 1.1.0g and 1.1.0h [27 Mar 2018]
-
- *) Constructed ASN.1 types with a recursive definition could exceed the stack
-
- Constructed ASN.1 types with a recursive definition (such as can be found
- in PKCS7) could eventually exceed the stack given malicious input with
- excessive recursion. This could result in a Denial Of Service attack. There
- are no such structures used within SSL/TLS that come from untrusted sources
- so this is considered safe.
-
- This issue was reported to OpenSSL on 4th January 2018 by the OSS-fuzz
- project.
- (CVE-2018-0739)
- [Matt Caswell]
-
- *) Incorrect CRYPTO_memcmp on HP-UX PA-RISC
-
- Because of an implementation bug the PA-RISC CRYPTO_memcmp function is
- effectively reduced to only comparing the least significant bit of each
- byte. This allows an attacker to forge messages that would be considered as
- authenticated in an amount of tries lower than that guaranteed by the
- security claims of the scheme. The module can only be compiled by the
- HP-UX assembler, so that only HP-UX PA-RISC targets are affected.
-
- This issue was reported to OpenSSL on 2nd March 2018 by Peter Waltenberg
- (IBM).
- (CVE-2018-0733)
- [Andy Polyakov]
-
- *) Add a build target 'build_all_generated', to build all generated files
- and only that. This can be used to prepare everything that requires
- things like perl for a system that lacks perl and then move everything
- to that system and do the rest of the build there.
- [Richard Levitte]
-
- *) Backport SSL_OP_NO_RENGOTIATION
-
- OpenSSL 1.0.2 and below had the ability to disable renegotiation using the
- (undocumented) SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS flag. Due to the opacity
- changes this is no longer possible in 1.1.0. Therefore the new
- SSL_OP_NO_RENEGOTIATION option from 1.1.1-dev has been backported to
- 1.1.0 to provide equivalent functionality.
-
- Note that if an application built against 1.1.0h headers (or above) is run
- using an older version of 1.1.0 (prior to 1.1.0h) then the option will be
- accepted but nothing will happen, i.e. renegotiation will not be prevented.
- [Matt Caswell]
-
- *) Removed the OS390-Unix config target. It relied on a script that doesn't
- exist.
- [Rich Salz]
-
- *) rsaz_1024_mul_avx2 overflow bug on x86_64
-
- There is an overflow bug in the AVX2 Montgomery multiplication procedure
- used in exponentiation with 1024-bit moduli. No EC algorithms are affected.
- Analysis suggests that attacks against RSA and DSA as a result of this
- defect would be very difficult to perform and are not believed likely.
- Attacks against DH1024 are considered just feasible, because most of the
- work necessary to deduce information about a private key may be performed
- offline. The amount of resources required for such an attack would be
- significant. However, for an attack on TLS to be meaningful, the server
- would have to share the DH1024 private key among multiple clients, which is
- no longer an option since CVE-2016-0701.
-
- This only affects processors that support the AVX2 but not ADX extensions
- like Intel Haswell (4th generation).
-
- This issue was reported to OpenSSL by David Benjamin (Google). The issue
- was originally found via the OSS-Fuzz project.
- (CVE-2017-3738)
- [Andy Polyakov]
-
- Changes between 1.1.0f and 1.1.0g [2 Nov 2017]
-
- *) bn_sqrx8x_internal carry bug on x86_64
-
- There is a carry propagating bug in the x86_64 Montgomery squaring
- procedure. No EC algorithms are affected. Analysis suggests that attacks
- against RSA and DSA as a result of this defect would be very difficult to
- perform and are not believed likely. Attacks against DH are considered just
- feasible (although very difficult) because most of the work necessary to
- deduce information about a private key may be performed offline. The amount
- of resources required for such an attack would be very significant and
- likely only accessible to a limited number of attackers. An attacker would
- additionally need online access to an unpatched system using the target
- private key in a scenario with persistent DH parameters and a private
- key that is shared between multiple clients.
-
- This only affects processors that support the BMI1, BMI2 and ADX extensions
- like Intel Broadwell (5th generation) and later or AMD Ryzen.
-
- This issue was reported to OpenSSL by the OSS-Fuzz project.
- (CVE-2017-3736)
- [Andy Polyakov]
-
- *) Malformed X.509 IPAddressFamily could cause OOB read
-
- If an X.509 certificate has a malformed IPAddressFamily extension,
- OpenSSL could do a one-byte buffer overread. The most likely result
- would be an erroneous display of the certificate in text format.
-
- This issue was reported to OpenSSL by the OSS-Fuzz project.
- (CVE-2017-3735)
- [Rich Salz]
-
- Changes between 1.1.0e and 1.1.0f [25 May 2017]
-
- *) Have 'config' recognise 64-bit mingw and choose 'mingw64' as the target
- platform rather than 'mingw'.
- [Richard Levitte]
-
- *) Remove the VMS-specific reimplementation of gmtime from crypto/o_times.c.
- VMS C's RTL has a fully up to date gmtime() and gmtime_r() since V7.1,
- which is the minimum version we support.
- [Richard Levitte]
-
- Changes between 1.1.0d and 1.1.0e [16 Feb 2017]
-
- *) Encrypt-Then-Mac renegotiation crash
-
- During a renegotiation handshake if the Encrypt-Then-Mac extension is
- negotiated where it was not in the original handshake (or vice-versa) then
- this can cause OpenSSL to crash (dependant on ciphersuite). Both clients
- and servers are affected.
-
- This issue was reported to OpenSSL by Joe Orton (Red Hat).
- (CVE-2017-3733)
- [Matt Caswell]
-
- Changes between 1.1.0c and 1.1.0d [26 Jan 2017]
-
- *) Truncated packet could crash via OOB read
-
- If one side of an SSL/TLS path is running on a 32-bit host and a specific
- cipher is being used, then a truncated packet can cause that host to
- perform an out-of-bounds read, usually resulting in a crash.
-
- This issue was reported to OpenSSL by Robert Święcki of Google.
- (CVE-2017-3731)
- [Andy Polyakov]
-
- *) Bad (EC)DHE parameters cause a client crash
-
- If a malicious server supplies bad parameters for a DHE or ECDHE key
- exchange then this can result in the client attempting to dereference a
- NULL pointer leading to a client crash. This could be exploited in a Denial
- of Service attack.
-
- This issue was reported to OpenSSL by Guido Vranken.
- (CVE-2017-3730)
- [Matt Caswell]
-
- *) BN_mod_exp may produce incorrect results on x86_64
-
- There is a carry propagating bug in the x86_64 Montgomery squaring
- procedure. No EC algorithms are affected. Analysis suggests that attacks
- against RSA and DSA as a result of this defect would be very difficult to
- perform and are not believed likely. Attacks against DH are considered just
- feasible (although very difficult) because most of the work necessary to
- deduce information about a private key may be performed offline. The amount
- of resources required for such an attack would be very significant and
- likely only accessible to a limited number of attackers. An attacker would
- additionally need online access to an unpatched system using the target
- private key in a scenario with persistent DH parameters and a private
- key that is shared between multiple clients. For example this can occur by
- default in OpenSSL DHE based SSL/TLS ciphersuites. Note: This issue is very
- similar to CVE-2015-3193 but must be treated as a separate problem.
-
- This issue was reported to OpenSSL by the OSS-Fuzz project.
- (CVE-2017-3732)
- [Andy Polyakov]
-
- Changes between 1.1.0b and 1.1.0c [10 Nov 2016]
-
- *) ChaCha20/Poly1305 heap-buffer-overflow
-
- TLS connections using *-CHACHA20-POLY1305 ciphersuites are susceptible to
- a DoS attack by corrupting larger payloads. This can result in an OpenSSL
- crash. This issue is not considered to be exploitable beyond a DoS.
-
- This issue was reported to OpenSSL by Robert Święcki (Google Security Team)
- (CVE-2016-7054)
- [Richard Levitte]
-
- *) CMS Null dereference
-
- Applications parsing invalid CMS structures can crash with a NULL pointer
- dereference. This is caused by a bug in the handling of the ASN.1 CHOICE
- type in OpenSSL 1.1.0 which can result in a NULL value being passed to the
- structure callback if an attempt is made to free certain invalid encodings.
- Only CHOICE structures using a callback which do not handle NULL value are
- affected.
-
- This issue was reported to OpenSSL by Tyler Nighswander of ForAllSecure.
- (CVE-2016-7053)
- [Stephen Henson]
-
- *) Montgomery multiplication may produce incorrect results
-
- There is a carry propagating bug in the Broadwell-specific Montgomery
- multiplication procedure that handles input lengths divisible by, but
- longer than 256 bits. Analysis suggests that attacks against RSA, DSA
- and DH private keys are impossible. This is because the subroutine in
- question is not used in operations with the private key itself and an input
- of the attacker's direct choice. Otherwise the bug can manifest itself as
- transient authentication and key negotiation failures or reproducible
- erroneous outcome of public-key operations with specially crafted input.
- Among EC algorithms only Brainpool P-512 curves are affected and one
- presumably can attack ECDH key negotiation. Impact was not analyzed in
- detail, because pre-requisites for attack are considered unlikely. Namely
- multiple clients have to choose the curve in question and the server has to
- share the private key among them, neither of which is default behaviour.
- Even then only clients that chose the curve will be affected.
-
- This issue was publicly reported as transient failures and was not
- initially recognized as a security issue. Thanks to Richard Morgan for
- providing reproducible case.
- (CVE-2016-7055)
- [Andy Polyakov]
-
- *) Removed automatic addition of RPATH in shared libraries and executables,
- as this was a remainder from OpenSSL 1.0.x and isn't needed any more.
- [Richard Levitte]
-
- Changes between 1.1.0a and 1.1.0b [26 Sep 2016]
-
- *) Fix Use After Free for large message sizes
-
- The patch applied to address CVE-2016-6307 resulted in an issue where if a
- message larger than approx 16k is received then the underlying buffer to
- store the incoming message is reallocated and moved. Unfortunately a
- dangling pointer to the old location is left which results in an attempt to
- write to the previously freed location. This is likely to result in a
- crash, however it could potentially lead to execution of arbitrary code.
-
- This issue only affects OpenSSL 1.1.0a.
-
- This issue was reported to OpenSSL by Robert Święcki.
- (CVE-2016-6309)
- [Matt Caswell]
-
- Changes between 1.1.0 and 1.1.0a [22 Sep 2016]
-
- *) OCSP Status Request extension unbounded memory growth
-
- A malicious client can send an excessively large OCSP Status Request
- extension. If that client continually requests renegotiation, sending a
- large OCSP Status Request extension each time, then there will be unbounded
- memory growth on the server. This will eventually lead to a Denial Of
- Service attack through memory exhaustion. Servers with a default
- configuration are vulnerable even if they do not support OCSP. Builds using
- the "no-ocsp" build time option are not affected.
-
- This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
- (CVE-2016-6304)
- [Matt Caswell]
-
- *) SSL_peek() hang on empty record
-
- OpenSSL 1.1.0 SSL/TLS will hang during a call to SSL_peek() if the peer
- sends an empty record. This could be exploited by a malicious peer in a
- Denial Of Service attack.
-
- This issue was reported to OpenSSL by Alex Gaynor.
- (CVE-2016-6305)
- [Matt Caswell]
-
- *) Excessive allocation of memory in tls_get_message_header() and
- dtls1_preprocess_fragment()
-
- A (D)TLS message includes 3 bytes for its length in the header for the
- message. This would allow for messages up to 16Mb in length. Messages of
- this length are excessive and OpenSSL includes a check to ensure that a
- peer is sending reasonably sized messages in order to avoid too much memory
- being consumed to service a connection. A flaw in the logic of version
- 1.1.0 means that memory for the message is allocated too early, prior to
- the excessive message length check. Due to way memory is allocated in
- OpenSSL this could mean an attacker could force up to 21Mb to be allocated
- to service a connection. This could lead to a Denial of Service through
- memory exhaustion. However, the excessive message length check still takes
- place, and this would cause the connection to immediately fail. Assuming
- that the application calls SSL_free() on the failed connection in a timely
- manner then the 21Mb of allocated memory will then be immediately freed
- again. Therefore the excessive memory allocation will be transitory in
- nature. This then means that there is only a security impact if:
-
- 1) The application does not call SSL_free() in a timely manner in the event
- that the connection fails
- or
- 2) The application is working in a constrained environment where there is
- very little free memory
- or
- 3) The attacker initiates multiple connection attempts such that there are
- multiple connections in a state where memory has been allocated for the
- connection; SSL_free() has not yet been called; and there is insufficient
- memory to service the multiple requests.
-
- Except in the instance of (1) above any Denial Of Service is likely to be
- transitory because as soon as the connection fails the memory is
- subsequently freed again in the SSL_free() call. However there is an
- increased risk during this period of application crashes due to the lack of
- memory - which would then mean a more serious Denial of Service.
-
- This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
- (CVE-2016-6307 and CVE-2016-6308)
- [Matt Caswell]
-
- *) solaris-x86-cc, i.e. 32-bit configuration with vendor compiler,
- had to be removed. Primary reason is that vendor assembler can't
- assemble our modules with -KPIC flag. As result it, assembly
- support, was not even available as option. But its lack means
- lack of side-channel resistant code, which is incompatible with
- security by todays standards. Fortunately gcc is readily available
- prepackaged option, which we firmly point at...
- [Andy Polyakov]
-
- Changes between 1.0.2h and 1.1.0 [25 Aug 2016]
-
- *) Windows command-line tool supports UTF-8 opt-in option for arguments
- and console input. Setting OPENSSL_WIN32_UTF8 environment variable
- (to any value) allows Windows user to access PKCS#12 file generated
- with Windows CryptoAPI and protected with non-ASCII password, as well
- as files generated under UTF-8 locale on Linux also protected with
- non-ASCII password.
- [Andy Polyakov]
-
- *) To mitigate the SWEET32 attack (CVE-2016-2183), 3DES cipher suites
- have been disabled by default and removed from DEFAULT, just like RC4.
- See the RC4 item below to re-enable both.
- [Rich Salz]
-
- *) The method for finding the storage location for the Windows RAND seed file
- has changed. First we check %RANDFILE%. If that is not set then we check
- the directories %HOME%, %USERPROFILE% and %SYSTEMROOT% in that order. If
- all else fails we fall back to C:\.
- [Matt Caswell]
-
- *) The EVP_EncryptUpdate() function has had its return type changed from void
- to int. A return of 0 indicates and error while a return of 1 indicates
- success.
- [Matt Caswell]
-
- *) The flags RSA_FLAG_NO_CONSTTIME, DSA_FLAG_NO_EXP_CONSTTIME and
- DH_FLAG_NO_EXP_CONSTTIME which previously provided the ability to switch
- off the constant time implementation for RSA, DSA and DH have been made
- no-ops and deprecated.
- [Matt Caswell]
-
- *) Windows RAND implementation was simplified to only get entropy by
- calling CryptGenRandom(). Various other RAND-related tickets
- were also closed.
- [Joseph Wylie Yandle, Rich Salz]
-
- *) The stack and lhash API's were renamed to start with OPENSSL_SK_
- and OPENSSL_LH_, respectively. The old names are available
- with API compatibility. They new names are now completely documented.
- [Rich Salz]
-
- *) Unify TYPE_up_ref(obj) methods signature.
- SSL_CTX_up_ref(), SSL_up_ref(), X509_up_ref(), EVP_PKEY_up_ref(),
- X509_CRL_up_ref(), X509_OBJECT_up_ref_count() methods are now returning an
- int (instead of void) like all others TYPE_up_ref() methods.
- So now these methods also check the return value of CRYPTO_atomic_add(),
- and the validity of object reference counter.
- [fdasilvayy@gmail.com]
-
- *) With Windows Visual Studio builds, the .pdb files are installed
- alongside the installed libraries and executables. For a static
- library installation, ossl_static.pdb is the associate compiler
- generated .pdb file to be used when linking programs.
- [Richard Levitte]
-
- *) Remove openssl.spec. Packaging files belong with the packagers.
- [Richard Levitte]
-
- *) Automatic Darwin/OSX configuration has had a refresh, it will now
- recognise x86_64 architectures automatically. You can still decide
- to build for a different bitness with the environment variable
- KERNEL_BITS (can be 32 or 64), for example:
-
- KERNEL_BITS=32 ./config
-
- [Richard Levitte]
-
- *) Change default algorithms in pkcs8 utility to use PKCS#5 v2.0,
- 256 bit AES and HMAC with SHA256.
- [Steve Henson]
-
- *) Remove support for MIPS o32 ABI on IRIX (and IRIX only).
- [Andy Polyakov]
-
- *) Triple-DES ciphers have been moved from HIGH to MEDIUM.
- [Rich Salz]
-
- *) To enable users to have their own config files and build file templates,
- Configure looks in the directory indicated by the environment variable
- OPENSSL_LOCAL_CONFIG_DIR as well as the in-source Configurations/
- directory. On VMS, OPENSSL_LOCAL_CONFIG_DIR is expected to be a logical
- name and is used as is.
- [Richard Levitte]
-
- *) The following datatypes were made opaque: X509_OBJECT, X509_STORE_CTX,
- X509_STORE, X509_LOOKUP, and X509_LOOKUP_METHOD. The unused type
- X509_CERT_FILE_CTX was removed.
- [Rich Salz]
-
- *) "shared" builds are now the default. To create only static libraries use
- the "no-shared" Configure option.
- [Matt Caswell]
-
- *) Remove the no-aes, no-hmac, no-rsa, no-sha and no-md5 Configure options.
- All of these option have not worked for some while and are fundamental
- algorithms.
- [Matt Caswell]
-
- *) Make various cleanup routines no-ops and mark them as deprecated. Most
- global cleanup functions are no longer required because they are handled
- via auto-deinit (see OPENSSL_init_crypto and OPENSSL_init_ssl man pages).
- Explicitly de-initing can cause problems (e.g. where a library that uses
- OpenSSL de-inits, but an application is still using it). The affected
- functions are CONF_modules_free(), ENGINE_cleanup(), OBJ_cleanup(),
- EVP_cleanup(), BIO_sock_cleanup(), CRYPTO_cleanup_all_ex_data(),
- RAND_cleanup(), SSL_COMP_free_compression_methods(), ERR_free_strings() and
- COMP_zlib_cleanup().
- [Matt Caswell]
-
- *) --strict-warnings no longer enables runtime debugging options
- such as REF_DEBUG. Instead, debug options are automatically
- enabled with '--debug' builds.
- [Andy Polyakov, Emilia Käsper]
-
- *) Made DH and DH_METHOD opaque. The structures for managing DH objects
- have been moved out of the public header files. New functions for managing
- these have been added.
- [Matt Caswell]
-
- *) Made RSA and RSA_METHOD opaque. The structures for managing RSA
- objects have been moved out of the public header files. New
- functions for managing these have been added.
- [Richard Levitte]
-
- *) Made DSA and DSA_METHOD opaque. The structures for managing DSA objects
- have been moved out of the public header files. New functions for managing
- these have been added.
- [Matt Caswell]
-
- *) Made BIO and BIO_METHOD opaque. The structures for managing BIOs have been
- moved out of the public header files. New functions for managing these
- have been added.
- [Matt Caswell]
-
- *) Removed no-rijndael as a config option. Rijndael is an old name for AES.
- [Matt Caswell]
-
- *) Removed the mk1mf build scripts.
- [Richard Levitte]
-
- *) Headers are now wrapped, if necessary, with OPENSSL_NO_xxx, so
- it is always safe to #include a header now.
- [Rich Salz]
-
- *) Removed the aged BC-32 config and all its supporting scripts
- [Richard Levitte]
-
- *) Removed support for Ultrix, Netware, and OS/2.
- [Rich Salz]
-
- *) Add support for HKDF.
- [Alessandro Ghedini]
-
- *) Add support for blake2b and blake2s
- [Bill Cox]
-
- *) Added support for "pipelining". Ciphers that have the
- EVP_CIPH_FLAG_PIPELINE flag set have a capability to process multiple
- encryptions/decryptions simultaneously. There are currently no built-in
- ciphers with this property but the expectation is that engines will be able
- to offer it to significantly improve throughput. Support has been extended
- into libssl so that multiple records for a single connection can be
- processed in one go (for >=TLS 1.1).
- [Matt Caswell]
-
- *) Added the AFALG engine. This is an async capable engine which is able to
- offload work to the Linux kernel. In this initial version it only supports
- AES128-CBC. The kernel must be version 4.1.0 or greater.
- [Catriona Lucey]
-
- *) OpenSSL now uses a new threading API. It is no longer necessary to
- set locking callbacks to use OpenSSL in a multi-threaded environment. There
- are two supported threading models: pthreads and windows threads. It is
- also possible to configure OpenSSL at compile time for "no-threads". The
- old threading API should no longer be used. The functions have been
- replaced with "no-op" compatibility macros.
- [Alessandro Ghedini, Matt Caswell]
-
- *) Modify behavior of ALPN to invoke callback after SNI/servername
- callback, such that updates to the SSL_CTX affect ALPN.
- [Todd Short]
-
- *) Add SSL_CIPHER queries for authentication and key-exchange.
- [Todd Short]
-
- *) Changes to the DEFAULT cipherlist:
- - Prefer (EC)DHE handshakes over plain RSA.
- - Prefer AEAD ciphers over legacy ciphers.
- - Prefer ECDSA over RSA when both certificates are available.
- - Prefer TLSv1.2 ciphers/PRF.
- - Remove DSS, SEED, IDEA, CAMELLIA, and AES-CCM from the
- default cipherlist.
- [Emilia Käsper]
-
- *) Change the ECC default curve list to be this, in order: x25519,
- secp256r1, secp521r1, secp384r1.
- [Rich Salz]
-
- *) RC4 based libssl ciphersuites are now classed as "weak" ciphers and are
- disabled by default. They can be re-enabled using the
- enable-weak-ssl-ciphers option to Configure.
- [Matt Caswell]
-
- *) If the server has ALPN configured, but supports no protocols that the
- client advertises, send a fatal "no_application_protocol" alert.
- This behaviour is SHALL in RFC 7301, though it isn't universally
- implemented by other servers.
- [Emilia Käsper]
-
- *) Add X25519 support.
- Add ASN.1 and EVP_PKEY methods for X25519. This includes support
- for public and private key encoding using the format documented in
- draft-ietf-curdle-pkix-02. The corresponding EVP_PKEY method supports
- key generation and key derivation.
-
- TLS support complies with draft-ietf-tls-rfc4492bis-08 and uses
- X25519(29).
- [Steve Henson]
-
- *) Deprecate SRP_VBASE_get_by_user.
- SRP_VBASE_get_by_user had inconsistent memory management behaviour.
- In order to fix an unavoidable memory leak (CVE-2016-0798),
- SRP_VBASE_get_by_user was changed to ignore the "fake user" SRP
- seed, even if the seed is configured.
-
- Users should use SRP_VBASE_get1_by_user instead. Note that in
- SRP_VBASE_get1_by_user, caller must free the returned value. Note
- also that even though configuring the SRP seed attempts to hide
- invalid usernames by continuing the handshake with fake
- credentials, this behaviour is not constant time and no strong
- guarantees are made that the handshake is indistinguishable from
- that of a valid user.
- [Emilia Käsper]
-
- *) Configuration change; it's now possible to build dynamic engines
- without having to build shared libraries and vice versa. This
- only applies to the engines in engines/, those in crypto/engine/
- will always be built into libcrypto (i.e. "static").
-
- Building dynamic engines is enabled by default; to disable, use
- the configuration option "disable-dynamic-engine".
-
- The only requirements for building dynamic engines are the
- presence of the DSO module and building with position independent
- code, so they will also automatically be disabled if configuring
- with "disable-dso" or "disable-pic".
-
- The macros OPENSSL_NO_STATIC_ENGINE and OPENSSL_NO_DYNAMIC_ENGINE
- are also taken away from openssl/opensslconf.h, as they are
- irrelevant.
- [Richard Levitte]
-
- *) Configuration change; if there is a known flag to compile
- position independent code, it will always be applied on the
- libcrypto and libssl object files, and never on the application
- object files. This means other libraries that use routines from
- libcrypto / libssl can be made into shared libraries regardless
- of how OpenSSL was configured.
-
- If this isn't desirable, the configuration options "disable-pic"
- or "no-pic" can be used to disable the use of PIC. This will
- also disable building shared libraries and dynamic engines.
- [Richard Levitte]
-
- *) Removed JPAKE code. It was experimental and has no wide use.
- [Rich Salz]
-
- *) The INSTALL_PREFIX Makefile variable has been renamed to
- DESTDIR. That makes for less confusion on what this variable
- is for. Also, the configuration option --install_prefix is
- removed.
- [Richard Levitte]
-
- *) Heartbeat for TLS has been removed and is disabled by default
- for DTLS; configure with enable-heartbeats. Code that uses the
- old #define's might need to be updated.
- [Emilia Käsper, Rich Salz]
-
- *) Rename REF_CHECK to REF_DEBUG.
- [Rich Salz]
-
- *) New "unified" build system
-
- The "unified" build system is aimed to be a common system for all
- platforms we support. With it comes new support for VMS.
-
- This system builds supports building in a different directory tree
- than the source tree. It produces one Makefile (for unix family
- or lookalikes), or one descrip.mms (for VMS).
-
- The source of information to make the Makefile / descrip.mms is
- small files called 'build.info', holding the necessary
- information for each directory with source to compile, and a
- template in Configurations, like unix-Makefile.tmpl or
- descrip.mms.tmpl.
-
- With this change, the library names were also renamed on Windows
- and on VMS. They now have names that are closer to the standard
- on Unix, and include the major version number, and in certain
- cases, the architecture they are built for. See "Notes on shared
- libraries" in INSTALL.
-
- We rely heavily on the perl module Text::Template.
- [Richard Levitte]
-
- *) Added support for auto-initialisation and de-initialisation of the library.
- OpenSSL no longer requires explicit init or deinit routines to be called,
- except in certain circumstances. See the OPENSSL_init_crypto() and
- OPENSSL_init_ssl() man pages for further information.
- [Matt Caswell]
-
- *) The arguments to the DTLSv1_listen function have changed. Specifically the
- "peer" argument is now expected to be a BIO_ADDR object.
-
- *) Rewrite of BIO networking library. The BIO library lacked consistent
- support of IPv6, and adding it required some more extensive
- modifications. This introduces the BIO_ADDR and BIO_ADDRINFO types,
- which hold all types of addresses and chains of address information.
- It also introduces a new API, with functions like BIO_socket,
- BIO_connect, BIO_listen, BIO_lookup and a rewrite of BIO_accept.
- The source/sink BIOs BIO_s_connect, BIO_s_accept and BIO_s_datagram
- have been adapted accordingly.
- [Richard Levitte]
-
- *) RSA_padding_check_PKCS1_type_1 now accepts inputs with and without
- the leading 0-byte.
- [Emilia Käsper]
-
- *) CRIME protection: disable compression by default, even if OpenSSL is
- compiled with zlib enabled. Applications can still enable compression
- by calling SSL_CTX_clear_options(ctx, SSL_OP_NO_COMPRESSION), or by
- using the SSL_CONF library to configure compression.
- [Emilia Käsper]
-
- *) The signature of the session callback configured with
- SSL_CTX_sess_set_get_cb was changed. The read-only input buffer
- was explicitly marked as 'const unsigned char*' instead of
- 'unsigned char*'.
- [Emilia Käsper]
-
- *) Always DPURIFY. Remove the use of uninitialized memory in the
- RNG, and other conditional uses of DPURIFY. This makes -DPURIFY a no-op.
- [Emilia Käsper]
-
- *) Removed many obsolete configuration items, including
- DES_PTR, DES_RISC1, DES_RISC2, DES_INT
- MD2_CHAR, MD2_INT, MD2_LONG
- BF_PTR, BF_PTR2
- IDEA_SHORT, IDEA_LONG
- RC2_SHORT, RC2_LONG, RC4_LONG, RC4_CHUNK, RC4_INDEX
- [Rich Salz, with advice from Andy Polyakov]
-
- *) Many BN internals have been moved to an internal header file.
- [Rich Salz with help from Andy Polyakov]
-
- *) Configuration and writing out the results from it has changed.
- Files such as Makefile include/openssl/opensslconf.h and are now
- produced through general templates, such as Makefile.in and
- crypto/opensslconf.h.in and some help from the perl module
- Text::Template.
-
- Also, the center of configuration information is no longer
- Makefile. Instead, Configure produces a perl module in
- configdata.pm which holds most of the config data (in the hash
- table %config), the target data that comes from the target
- configuration in one of the Configurations/*.conf files (in
- %target).
- [Richard Levitte]
-
- *) To clarify their intended purposes, the Configure options
- --prefix and --openssldir change their semantics, and become more
- straightforward and less interdependent.
-
- --prefix shall be used exclusively to give the location INSTALLTOP
- where programs, scripts, libraries, include files and manuals are
- going to be installed. The default is now /usr/local.
-
- --openssldir shall be used exclusively to give the default
- location OPENSSLDIR where certificates, private keys, CRLs are
- managed. This is also where the default openssl.cnf gets
- installed.
- If the directory given with this option is a relative path, the
- values of both the --prefix value and the --openssldir value will
- be combined to become OPENSSLDIR.
- The default for --openssldir is INSTALLTOP/ssl.
-
- Anyone who uses --openssldir to specify where OpenSSL is to be
- installed MUST change to use --prefix instead.
- [Richard Levitte]
-
- *) The GOST engine was out of date and therefore it has been removed. An up
- to date GOST engine is now being maintained in an external repository.
- See: https://wiki.openssl.org/index.php/Binaries. Libssl still retains
- support for GOST ciphersuites (these are only activated if a GOST engine
- is present).
- [Matt Caswell]
-
- *) EGD is no longer supported by default; use enable-egd when
- configuring.
- [Ben Kaduk and Rich Salz]
-
- *) The distribution now has Makefile.in files, which are used to
- create Makefile's when Configure is run. *Configure must be run
- before trying to build now.*
- [Rich Salz]
-
- *) The return value for SSL_CIPHER_description() for error conditions
- has changed.
- [Rich Salz]
-
- *) Support for RFC6698/RFC7671 DANE TLSA peer authentication.
-
- Obtaining and performing DNSSEC validation of TLSA records is
- the application's responsibility. The application provides
- the TLSA records of its choice to OpenSSL, and these are then
- used to authenticate the peer.
-
- The TLSA records need not even come from DNS. They can, for
- example, be used to implement local end-entity certificate or
- trust-anchor "pinning", where the "pin" data takes the form
- of TLSA records, which can augment or replace verification
- based on the usual WebPKI public certification authorities.
- [Viktor Dukhovni]
-
- *) Revert default OPENSSL_NO_DEPRECATED setting. Instead OpenSSL
- continues to support deprecated interfaces in default builds.
- However, applications are strongly advised to compile their
- source files with -DOPENSSL_API_COMPAT=0x10100000L, which hides
- the declarations of all interfaces deprecated in 0.9.8, 1.0.0
- or the 1.1.0 releases.
-
- In environments in which all applications have been ported to
- not use any deprecated interfaces OpenSSL's Configure script
- should be used with the --api=1.1.0 option to entirely remove
- support for the deprecated features from the library and
- unconditionally disable them in the installed headers.
- Essentially the same effect can be achieved with the "no-deprecated"
- argument to Configure, except that this will always restrict
- the build to just the latest API, rather than a fixed API
- version.
-
- As applications are ported to future revisions of the API,
- they should update their compile-time OPENSSL_API_COMPAT define
- accordingly, but in most cases should be able to continue to
- compile with later releases.
-
- The OPENSSL_API_COMPAT versions for 1.0.0, and 0.9.8 are
- 0x10000000L and 0x00908000L, respectively. However those
- versions did not support the OPENSSL_API_COMPAT feature, and
- so applications are not typically tested for explicit support
- of just the undeprecated features of either release.
- [Viktor Dukhovni]
-
- *) Add support for setting the minimum and maximum supported protocol.
- It can bet set via the SSL_set_min_proto_version() and
- SSL_set_max_proto_version(), or via the SSL_CONF's MinProtocol and
- MaxProtocol. It's recommended to use the new APIs to disable
- protocols instead of disabling individual protocols using
- SSL_set_options() or SSL_CONF's Protocol. This change also
- removes support for disabling TLS 1.2 in the OpenSSL TLS
- client at compile time by defining OPENSSL_NO_TLS1_2_CLIENT.
- [Kurt Roeckx]
-
- *) Support for ChaCha20 and Poly1305 added to libcrypto and libssl.
- [Andy Polyakov]
-
- *) New EC_KEY_METHOD, this replaces the older ECDSA_METHOD and ECDH_METHOD
- and integrates ECDSA and ECDH functionality into EC. Implementations can
- now redirect key generation and no longer need to convert to or from
- ECDSA_SIG format.
-
- Note: the ecdsa.h and ecdh.h headers are now no longer needed and just
- include the ec.h header file instead.
- [Steve Henson]
-
- *) Remove support for all 40 and 56 bit ciphers. This includes all the export
- ciphers who are no longer supported and drops support the ephemeral RSA key
- exchange. The LOW ciphers currently doesn't have any ciphers in it.
- [Kurt Roeckx]
-
- *) Made EVP_MD_CTX, EVP_MD, EVP_CIPHER_CTX, EVP_CIPHER and HMAC_CTX
- opaque. For HMAC_CTX, the following constructors and destructors
- were added:
-
- HMAC_CTX *HMAC_CTX_new(void);
- void HMAC_CTX_free(HMAC_CTX *ctx);
-
- For EVP_MD and EVP_CIPHER, complete APIs to create, fill and
- destroy such methods has been added. See EVP_MD_meth_new(3) and
- EVP_CIPHER_meth_new(3) for documentation.
-
- Additional changes:
- 1) EVP_MD_CTX_cleanup(), EVP_CIPHER_CTX_cleanup() and
- HMAC_CTX_cleanup() were removed. HMAC_CTX_reset() and
- EVP_MD_CTX_reset() should be called instead to reinitialise
- an already created structure.
- 2) For consistency with the majority of our object creators and
- destructors, EVP_MD_CTX_(create|destroy) were renamed to
- EVP_MD_CTX_(new|free). The old names are retained as macros
- for deprecated builds.
- [Richard Levitte]
-
- *) Added ASYNC support. Libcrypto now includes the async sub-library to enable
- cryptographic operations to be performed asynchronously as long as an
- asynchronous capable engine is used. See the ASYNC_start_job() man page for
- further details. Libssl has also had this capability integrated with the
- introduction of the new mode SSL_MODE_ASYNC and associated error
- SSL_ERROR_WANT_ASYNC. See the SSL_CTX_set_mode() and SSL_get_error() man
- pages. This work was developed in partnership with Intel Corp.
- [Matt Caswell]
-
- *) SSL_{CTX_}set_ecdh_auto() has been removed and ECDH is support is
- always enabled now. If you want to disable the support you should
- exclude it using the list of supported ciphers. This also means that the
- "-no_ecdhe" option has been removed from s_server.
- [Kurt Roeckx]
-
- *) SSL_{CTX}_set_tmp_ecdh() which can set 1 EC curve now internally calls
- SSL_{CTX_}set1_curves() which can set a list.
- [Kurt Roeckx]
-
- *) Remove support for SSL_{CTX_}set_tmp_ecdh_callback(). You should set the
- curve you want to support using SSL_{CTX_}set1_curves().
- [Kurt Roeckx]
-
- *) State machine rewrite. The state machine code has been significantly
- refactored in order to remove much duplication of code and solve issues
- with the old code (see ssl/statem/README for further details). This change
- does have some associated API changes. Notably the SSL_state() function
- has been removed and replaced by SSL_get_state which now returns an
- "OSSL_HANDSHAKE_STATE" instead of an int. SSL_set_state() has been removed
- altogether. The previous handshake states defined in ssl.h and ssl3.h have
- also been removed.
- [Matt Caswell]
-
- *) All instances of the string "ssleay" in the public API were replaced
- with OpenSSL (case-matching; e.g., OPENSSL_VERSION for #define's)
- Some error codes related to internal RSA_eay API's were renamed.
- [Rich Salz]
-
- *) The demo files in crypto/threads were moved to demo/threads.
- [Rich Salz]
-
- *) Removed obsolete engines: 4758cca, aep, atalla, cswift, nuron, gmp,
- sureware and ubsec.
- [Matt Caswell, Rich Salz]
-
- *) New ASN.1 embed macro.
-
- New ASN.1 macro ASN1_EMBED. This is the same as ASN1_SIMPLE except the
- structure is not allocated: it is part of the parent. That is instead of
-
- FOO *x;
-
- it must be:
-
- FOO x;
-
- This reduces memory fragmentation and make it impossible to accidentally
- set a mandatory field to NULL.
-
- This currently only works for some fields specifically a SEQUENCE, CHOICE,
- or ASN1_STRING type which is part of a parent SEQUENCE. Since it is
- equivalent to ASN1_SIMPLE it cannot be tagged, OPTIONAL, SET OF or
- SEQUENCE OF.
- [Steve Henson]
-
- *) Remove EVP_CHECK_DES_KEY, a compile-time option that never compiled.
- [Emilia Käsper]
-
- *) Removed DES and RC4 ciphersuites from DEFAULT. Also removed RC2 although
- in 1.0.2 EXPORT was already removed and the only RC2 ciphersuite is also
- an EXPORT one. COMPLEMENTOFDEFAULT has been updated accordingly to add
- DES and RC4 ciphersuites.
- [Matt Caswell]
-
- *) Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs.
- This changes the decoding behaviour for some invalid messages,
- though the change is mostly in the more lenient direction, and
- legacy behaviour is preserved as much as possible.
- [Emilia Käsper]
-
- *) Fix no-stdio build.
- [ David Woodhouse <David.Woodhouse@intel.com> and also
- Ivan Nestlerode <ivan.nestlerode@sonos.com> ]
-
- *) New testing framework
- The testing framework has been largely rewritten and is now using
- perl and the perl modules Test::Harness and an extended variant of
- Test::More called OpenSSL::Test to do its work. All test scripts in
- test/ have been rewritten into test recipes, and all direct calls to
- executables in test/Makefile have become individual recipes using the
- simplified testing OpenSSL::Test::Simple.
-
- For documentation on our testing modules, do:
-
- perldoc test/testlib/OpenSSL/Test/Simple.pm
- perldoc test/testlib/OpenSSL/Test.pm
-
- [Richard Levitte]
-
- *) Revamped memory debug; only -DCRYPTO_MDEBUG and -DCRYPTO_MDEBUG_ABORT
- are used; the latter aborts on memory leaks (usually checked on exit).
- Some undocumented "set malloc, etc., hooks" functions were removed
- and others were changed. All are now documented.
- [Rich Salz]
-
- *) In DSA_generate_parameters_ex, if the provided seed is too short,
- return an error
- [Rich Salz and Ismo Puustinen <ismo.puustinen@intel.com>]
-
- *) Rewrite PSK to support ECDHE_PSK, DHE_PSK and RSA_PSK. Add ciphersuites
- from RFC4279, RFC4785, RFC5487, RFC5489.
-
- Thanks to Christian J. Dietrich and Giuseppe D'Angelo for the
- original RSA_PSK patch.
- [Steve Henson]
-
- *) Dropped support for the SSL3_FLAGS_DELAY_CLIENT_FINISHED flag. This SSLeay
- era flag was never set throughout the codebase (only read). Also removed
- SSL3_FLAGS_POP_BUFFER which was only used if
- SSL3_FLAGS_DELAY_CLIENT_FINISHED was also set.
- [Matt Caswell]
-
- *) Changed the default name options in the "ca", "crl", "req" and "x509"
- to be "oneline" instead of "compat".
- [Richard Levitte]
-
- *) Remove SSL_OP_TLS_BLOCK_PADDING_BUG. This is SSLeay legacy, we're
- not aware of clients that still exhibit this bug, and the workaround
- hasn't been working properly for a while.
- [Emilia Käsper]
-
- *) The return type of BIO_number_read() and BIO_number_written() as well as
- the corresponding num_read and num_write members in the BIO structure has
- changed from unsigned long to uint64_t. On platforms where an unsigned
- long is 32 bits (e.g. Windows) these counters could overflow if >4Gb is
- transferred.
- [Matt Caswell]
-
- *) Given the pervasive nature of TLS extensions it is inadvisable to run
- OpenSSL without support for them. It also means that maintaining
- the OPENSSL_NO_TLSEXT option within the code is very invasive (and probably
- not well tested). Therefore the OPENSSL_NO_TLSEXT option has been removed.
- [Matt Caswell]
-
- *) Removed support for the two export grade static DH ciphersuites
- EXP-DH-RSA-DES-CBC-SHA and EXP-DH-DSS-DES-CBC-SHA. These two ciphersuites
- were newly added (along with a number of other static DH ciphersuites) to
- 1.0.2. However the two export ones have *never* worked since they were
- introduced. It seems strange in any case to be adding new export
- ciphersuites, and given "logjam" it also does not seem correct to fix them.
- [Matt Caswell]
-
- *) Version negotiation has been rewritten. In particular SSLv23_method(),
- SSLv23_client_method() and SSLv23_server_method() have been deprecated,
- and turned into macros which simply call the new preferred function names
- TLS_method(), TLS_client_method() and TLS_server_method(). All new code
- should use the new names instead. Also as part of this change the ssl23.h
- header file has been removed.
- [Matt Caswell]
-
- *) Support for Kerberos ciphersuites in TLS (RFC2712) has been removed. This
- code and the associated standard is no longer considered fit-for-purpose.
- [Matt Caswell]
-
- *) RT2547 was closed. When generating a private key, try to make the
- output file readable only by the owner. This behavior change might
- be noticeable when interacting with other software.
-
- *) Documented all exdata functions. Added CRYPTO_free_ex_index.
- Added a test.
- [Rich Salz]
-
- *) Added HTTP GET support to the ocsp command.
- [Rich Salz]
-
- *) Changed default digest for the dgst and enc commands from MD5 to
- sha256
- [Rich Salz]
-
- *) RAND_pseudo_bytes has been deprecated. Users should use RAND_bytes instead.
- [Matt Caswell]
-
- *) Added support for TLS extended master secret from
- draft-ietf-tls-session-hash-03.txt. Thanks for Alfredo Pironti for an
- initial patch which was a great help during development.
- [Steve Henson]
-
- *) All libssl internal structures have been removed from the public header
- files, and the OPENSSL_NO_SSL_INTERN option has been removed (since it is
- now redundant). Users should not attempt to access internal structures
- directly. Instead they should use the provided API functions.
- [Matt Caswell]
-
- *) config has been changed so that by default OPENSSL_NO_DEPRECATED is used.
- Access to deprecated functions can be re-enabled by running config with
- "enable-deprecated". In addition applications wishing to use deprecated
- functions must define OPENSSL_USE_DEPRECATED. Note that this new behaviour
- will, by default, disable some transitive includes that previously existed
- in the header files (e.g. ec.h will no longer, by default, include bn.h)
- [Matt Caswell]
-
- *) Added support for OCB mode. OpenSSL has been granted a patent license
- compatible with the OpenSSL license for use of OCB. Details are available
- at https://www.openssl.org/source/OCB-patent-grant-OpenSSL.pdf. Support
- for OCB can be removed by calling config with no-ocb.
- [Matt Caswell]
-
- *) SSLv2 support has been removed. It still supports receiving a SSLv2
- compatible client hello.
- [Kurt Roeckx]
-
- *) Increased the minimal RSA keysize from 256 to 512 bits [Rich Salz],
- done while fixing the error code for the key-too-small case.
- [Annie Yousar <a.yousar@informatik.hu-berlin.de>]
-
- *) CA.sh has been removed; use CA.pl instead.
- [Rich Salz]
-
- *) Removed old DES API.
- [Rich Salz]
-
- *) Remove various unsupported platforms:
- Sony NEWS4
- BEOS and BEOS_R5
- NeXT
- SUNOS
- MPE/iX
- Sinix/ReliantUNIX RM400
- DGUX
- NCR
- Tandem
- Cray
- 16-bit platforms such as WIN16
- [Rich Salz]
-
- *) Clean up OPENSSL_NO_xxx #define's
- Use setbuf() and remove OPENSSL_NO_SETVBUF_IONBF
- Rename OPENSSL_SYSNAME_xxx to OPENSSL_SYS_xxx
- OPENSSL_NO_EC{DH,DSA} merged into OPENSSL_NO_EC
- OPENSSL_NO_RIPEMD160, OPENSSL_NO_RIPEMD merged into OPENSSL_NO_RMD160
- OPENSSL_NO_FP_API merged into OPENSSL_NO_STDIO
- Remove OPENSSL_NO_BIO OPENSSL_NO_BUFFER OPENSSL_NO_CHAIN_VERIFY
- OPENSSL_NO_EVP OPENSSL_NO_FIPS_ERR OPENSSL_NO_HASH_COMP
- OPENSSL_NO_LHASH OPENSSL_NO_OBJECT OPENSSL_NO_SPEED OPENSSL_NO_STACK
- OPENSSL_NO_X509 OPENSSL_NO_X509_VERIFY
- Remove MS_STATIC; it's a relic from platforms <32 bits.
- [Rich Salz]
-
- *) Cleaned up dead code
- Remove all but one '#ifdef undef' which is to be looked at.
- [Rich Salz]
-
- *) Clean up calling of xxx_free routines.
- Just like free(), fix most of the xxx_free routines to accept
- NULL. Remove the non-null checks from callers. Save much code.
- [Rich Salz]
-
- *) Add secure heap for storage of private keys (when possible).
- Add BIO_s_secmem(), CBIGNUM, etc.
- Contributed by Akamai Technologies under our Corporate CLA.
- [Rich Salz]
-
- *) Experimental support for a new, fast, unbiased prime candidate generator,
- bn_probable_prime_dh_coprime(). Not currently used by any prime generator.
- [Felix Laurie von Massenbach <felix@erbridge.co.uk>]
-
- *) New output format NSS in the sess_id command line tool. This allows
- exporting the session id and the master key in NSS keylog format.
- [Martin Kaiser <martin@kaiser.cx>]
-
- *) Harmonize version and its documentation. -f flag is used to display
- compilation flags.
- [mancha <mancha1@zoho.com>]
-
- *) Fix eckey_priv_encode so it immediately returns an error upon a failure
- in i2d_ECPrivateKey. Thanks to Ted Unangst for feedback on this issue.
- [mancha <mancha1@zoho.com>]
-
- *) Fix some double frees. These are not thought to be exploitable.
- [mancha <mancha1@zoho.com>]
-
- *) A missing bounds check in the handling of the TLS heartbeat extension
- can be used to reveal up to 64k of memory to a connected client or
- server.
-
- Thanks for Neel Mehta of Google Security for discovering this bug and to
- Adam Langley <agl@chromium.org> and Bodo Moeller <bmoeller@acm.org> for
- preparing the fix (CVE-2014-0160)
- [Adam Langley, Bodo Moeller]
-
- *) Fix for the attack described in the paper "Recovering OpenSSL
- ECDSA Nonces Using the FLUSH+RELOAD Cache Side-channel Attack"
- by Yuval Yarom and Naomi Benger. Details can be obtained from:
- http://eprint.iacr.org/2014/140
-
- Thanks to Yuval Yarom and Naomi Benger for discovering this
- flaw and to Yuval Yarom for supplying a fix (CVE-2014-0076)
- [Yuval Yarom and Naomi Benger]
-
- *) Use algorithm specific chains in SSL_CTX_use_certificate_chain_file():
- this fixes a limitation in previous versions of OpenSSL.
- [Steve Henson]
-
- *) Experimental encrypt-then-mac support.
-
- Experimental support for encrypt then mac from
- draft-gutmann-tls-encrypt-then-mac-02.txt
-
- To enable it set the appropriate extension number (0x42 for the test
- server) using e.g. -DTLSEXT_TYPE_encrypt_then_mac=0x42
-
- For non-compliant peers (i.e. just about everything) this should have no
- effect.
-
- WARNING: EXPERIMENTAL, SUBJECT TO CHANGE.
-
- [Steve Henson]
-
- *) Add EVP support for key wrapping algorithms, to avoid problems with
- existing code the flag EVP_CIPHER_CTX_WRAP_ALLOW has to be set in
- the EVP_CIPHER_CTX or an error is returned. Add AES and DES3 wrap
- algorithms and include tests cases.
- [Steve Henson]
-
- *) Extend CMS code to support RSA-PSS signatures and RSA-OAEP for
- enveloped data.
- [Steve Henson]
-
- *) Extended RSA OAEP support via EVP_PKEY API. Options to specify digest,
- MGF1 digest and OAEP label.
- [Steve Henson]
-
- *) Make openssl verify return errors.
- [Chris Palmer <palmer@google.com> and Ben Laurie]
-
- *) New function ASN1_TIME_diff to calculate the difference between two
- ASN1_TIME structures or one structure and the current time.
- [Steve Henson]
-
- *) Update fips_test_suite to support multiple command line options. New
- test to induce all self test errors in sequence and check expected
- failures.
- [Steve Henson]
-
- *) Add FIPS_{rsa,dsa,ecdsa}_{sign,verify} functions which digest and
- sign or verify all in one operation.
- [Steve Henson]
-
- *) Add fips_algvs: a multicall fips utility incorporating all the algorithm
- test programs and fips_test_suite. Includes functionality to parse
- the minimal script output of fipsalgest.pl directly.
- [Steve Henson]
-
- *) Add authorisation parameter to FIPS_module_mode_set().
- [Steve Henson]
-
- *) Add FIPS selftest for ECDH algorithm using P-224 and B-233 curves.
- [Steve Henson]
-
- *) Use separate DRBG fields for internal and external flags. New function
- FIPS_drbg_health_check() to perform on demand health checking. Add
- generation tests to fips_test_suite with reduced health check interval to
- demonstrate periodic health checking. Add "nodh" option to
- fips_test_suite to skip very slow DH test.
- [Steve Henson]
-
- *) New function FIPS_get_cipherbynid() to lookup FIPS supported ciphers
- based on NID.
- [Steve Henson]
-
- *) More extensive health check for DRBG checking many more failure modes.
- New function FIPS_selftest_drbg_all() to handle every possible DRBG
- combination: call this in fips_test_suite.
- [Steve Henson]
-
- *) Add support for canonical generation of DSA parameter 'g'. See
- FIPS 186-3 A.2.3.
-
- *) Add support for HMAC DRBG from SP800-90. Update DRBG algorithm test and
- POST to handle HMAC cases.
- [Steve Henson]
-
- *) Add functions FIPS_module_version() and FIPS_module_version_text()
- to return numerical and string versions of the FIPS module number.
- [Steve Henson]
-
- *) Rename FIPS_mode_set and FIPS_mode to FIPS_module_mode_set and
- FIPS_module_mode. FIPS_mode and FIPS_mode_set will be implemented
- outside the validated module in the FIPS capable OpenSSL.
- [Steve Henson]
-
- *) Minor change to DRBG entropy callback semantics. In some cases
- there is no multiple of the block length between min_len and
- max_len. Allow the callback to return more than max_len bytes
- of entropy but discard any extra: it is the callback's responsibility
- to ensure that the extra data discarded does not impact the
- requested amount of entropy.
- [Steve Henson]
-
- *) Add PRNG security strength checks to RSA, DSA and ECDSA using
- information in FIPS186-3, SP800-57 and SP800-131A.
- [Steve Henson]
-
- *) CCM support via EVP. Interface is very similar to GCM case except we
- must supply all data in one chunk (i.e. no update, final) and the
- message length must be supplied if AAD is used. Add algorithm test
- support.
- [Steve Henson]
-
- *) Initial version of POST overhaul. Add POST callback to allow the status
- of POST to be monitored and/or failures induced. Modify fips_test_suite
- to use callback. Always run all selftests even if one fails.
- [Steve Henson]
-
- *) XTS support including algorithm test driver in the fips_gcmtest program.
- Note: this does increase the maximum key length from 32 to 64 bytes but
- there should be no binary compatibility issues as existing applications
- will never use XTS mode.
- [Steve Henson]
-
- *) Extensive reorganisation of FIPS PRNG behaviour. Remove all dependencies
- to OpenSSL RAND code and replace with a tiny FIPS RAND API which also
- performs algorithm blocking for unapproved PRNG types. Also do not
- set PRNG type in FIPS_mode_set(): leave this to the application.
- Add default OpenSSL DRBG handling: sets up FIPS PRNG and seeds with
- the standard OpenSSL PRNG: set additional data to a date time vector.
- [Steve Henson]
-
- *) Rename old X9.31 PRNG functions of the form FIPS_rand* to FIPS_x931*.
- This shouldn't present any incompatibility problems because applications
- shouldn't be using these directly and any that are will need to rethink
- anyway as the X9.31 PRNG is now deprecated by FIPS 140-2
- [Steve Henson]
-
- *) Extensive self tests and health checking required by SP800-90 DRBG.
- Remove strength parameter from FIPS_drbg_instantiate and always
- instantiate at maximum supported strength.
- [Steve Henson]
-
- *) Add ECDH code to fips module and fips_ecdhvs for primitives only testing.
- [Steve Henson]
-
- *) New algorithm test program fips_dhvs to handle DH primitives only testing.
- [Steve Henson]
-
- *) New function DH_compute_key_padded() to compute a DH key and pad with
- leading zeroes if needed: this complies with SP800-56A et al.
- [Steve Henson]
-
- *) Initial implementation of SP800-90 DRBGs for Hash and CTR. Not used by
- anything, incomplete, subject to change and largely untested at present.
- [Steve Henson]
-
- *) Modify fipscanisteronly build option to only build the necessary object
- files by filtering FIPS_EX_OBJ through a perl script in crypto/Makefile.
- [Steve Henson]
-
- *) Add experimental option FIPSSYMS to give all symbols in
- fipscanister.o and FIPS or fips prefix. This will avoid
- conflicts with future versions of OpenSSL. Add perl script
- util/fipsas.pl to preprocess assembly language source files
- and rename any affected symbols.
- [Steve Henson]
-
- *) Add selftest checks and algorithm block of non-fips algorithms in
- FIPS mode. Remove DES2 from selftests.
- [Steve Henson]
-
- *) Add ECDSA code to fips module. Add tiny fips_ecdsa_check to just
- return internal method without any ENGINE dependencies. Add new
- tiny fips sign and verify functions.
- [Steve Henson]
-
- *) New build option no-ec2m to disable characteristic 2 code.
- [Steve Henson]
-
- *) New build option "fipscanisteronly". This only builds fipscanister.o
- and (currently) associated fips utilities. Uses the file Makefile.fips
- instead of Makefile.org as the prototype.
- [Steve Henson]
-
- *) Add some FIPS mode restrictions to GCM. Add internal IV generator.
- Update fips_gcmtest to use IV generator.
- [Steve Henson]
-
- *) Initial, experimental EVP support for AES-GCM. AAD can be input by
- setting output buffer to NULL. The *Final function must be
- called although it will not retrieve any additional data. The tag
- can be set or retrieved with a ctrl. The IV length is by default 12
- bytes (96 bits) but can be set to an alternative value. If the IV
- length exceeds the maximum IV length (currently 16 bytes) it cannot be
- set before the key.
- [Steve Henson]
-
- *) New flag in ciphers: EVP_CIPH_FLAG_CUSTOM_CIPHER. This means the
- underlying do_cipher function handles all cipher semantics itself
- including padding and finalisation. This is useful if (for example)
- an ENGINE cipher handles block padding itself. The behaviour of
- do_cipher is subtly changed if this flag is set: the return value
- is the number of characters written to the output buffer (zero is
- no longer an error code) or a negative error code. Also if the
- input buffer is NULL and length 0 finalisation should be performed.
- [Steve Henson]
-
- *) If a candidate issuer certificate is already part of the constructed
- path ignore it: new debug notification X509_V_ERR_PATH_LOOP for this case.
- [Steve Henson]
-
- *) Improve forward-security support: add functions
-
- void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx, int (*cb)(SSL *ssl, int is_forward_secure))
- void SSL_set_not_resumable_session_callback(SSL *ssl, int (*cb)(SSL *ssl, int is_forward_secure))
-
- for use by SSL/TLS servers; the callback function will be called whenever a
- new session is created, and gets to decide whether the session may be
- cached to make it resumable (return 0) or not (return 1). (As by the
- SSL/TLS protocol specifications, the session_id sent by the server will be
- empty to indicate that the session is not resumable; also, the server will
- not generate RFC 4507 (RFC 5077) session tickets.)
-
- A simple reasonable callback implementation is to return is_forward_secure.
- This parameter will be set to 1 or 0 depending on the ciphersuite selected
- by the SSL/TLS server library, indicating whether it can provide forward
- security.
- [Emilia Käsper <emilia.kasper@esat.kuleuven.be> (Google)]
-
- *) New -verify_name option in command line utilities to set verification
- parameters by name.
- [Steve Henson]
-
- *) Initial CMAC implementation. WARNING: EXPERIMENTAL, API MAY CHANGE.
- Add CMAC pkey methods.
- [Steve Henson]
-
- *) Experimental renegotiation in s_server -www mode. If the client
- browses /reneg connection is renegotiated. If /renegcert it is
- renegotiated requesting a certificate.
- [Steve Henson]
-
- *) Add an "external" session cache for debugging purposes to s_server. This
- should help trace issues which normally are only apparent in deployed
- multi-process servers.
- [Steve Henson]
-
- *) Extensive audit of libcrypto with DEBUG_UNUSED. Fix many cases where
- return value is ignored. NB. The functions RAND_add(), RAND_seed(),
- BIO_set_cipher() and some obscure PEM functions were changed so they
- can now return an error. The RAND changes required a change to the
- RAND_METHOD structure.
- [Steve Henson]
-
- *) New macro __owur for "OpenSSL Warn Unused Result". This makes use of
- a gcc attribute to warn if the result of a function is ignored. This
- is enable if DEBUG_UNUSED is set. Add to several functions in evp.h
- whose return value is often ignored.
- [Steve Henson]
-
- *) New -noct, -requestct, -requirect and -ctlogfile options for s_client.
- These allow SCTs (signed certificate timestamps) to be requested and
- validated when establishing a connection.
- [Rob Percival <robpercival@google.com>]
-
- Changes between 1.0.2g and 1.0.2h [3 May 2016]
-
- *) Prevent padding oracle in AES-NI CBC MAC check
-
- A MITM attacker can use a padding oracle attack to decrypt traffic
- when the connection uses an AES CBC cipher and the server support
- AES-NI.
-
- This issue was introduced as part of the fix for Lucky 13 padding
- attack (CVE-2013-0169). The padding check was rewritten to be in
- constant time by making sure that always the same bytes are read and
- compared against either the MAC or padding bytes. But it no longer
- checked that there was enough data to have both the MAC and padding
- bytes.
-
- This issue was reported by Juraj Somorovsky using TLS-Attacker.
- (CVE-2016-2107)
- [Kurt Roeckx]
-
- *) Fix EVP_EncodeUpdate overflow
-
- An overflow can occur in the EVP_EncodeUpdate() function which is used for
- Base64 encoding of binary data. If an attacker is able to supply very large
- amounts of input data then a length check can overflow resulting in a heap
- corruption.
-
- Internally to OpenSSL the EVP_EncodeUpdate() function is primarily used by
- the PEM_write_bio* family of functions. These are mainly used within the
- OpenSSL command line applications, so any application which processes data
- from an untrusted source and outputs it as a PEM file should be considered
- vulnerable to this issue. User applications that call these APIs directly
- with large amounts of untrusted data may also be vulnerable.
-
- This issue was reported by Guido Vranken.
- (CVE-2016-2105)
- [Matt Caswell]
-
- *) Fix EVP_EncryptUpdate overflow
-
- An overflow can occur in the EVP_EncryptUpdate() function. If an attacker
- is able to supply very large amounts of input data after a previous call to
- EVP_EncryptUpdate() with a partial block then a length check can overflow
- resulting in a heap corruption. Following an analysis of all OpenSSL
- internal usage of the EVP_EncryptUpdate() function all usage is one of two
- forms. The first form is where the EVP_EncryptUpdate() call is known to be
- the first called function after an EVP_EncryptInit(), and therefore that
- specific call must be safe. The second form is where the length passed to
- EVP_EncryptUpdate() can be seen from the code to be some small value and
- therefore there is no possibility of an overflow. Since all instances are
- one of these two forms, it is believed that there can be no overflows in
- internal code due to this problem. It should be noted that
- EVP_DecryptUpdate() can call EVP_EncryptUpdate() in certain code paths.
- Also EVP_CipherUpdate() is a synonym for EVP_EncryptUpdate(). All instances
- of these calls have also been analysed too and it is believed there are no
- instances in internal usage where an overflow could occur.
-
- This issue was reported by Guido Vranken.
- (CVE-2016-2106)
- [Matt Caswell]
-
- *) Prevent ASN.1 BIO excessive memory allocation
-
- When ASN.1 data is read from a BIO using functions such as d2i_CMS_bio()
- a short invalid encoding can cause allocation of large amounts of memory
- potentially consuming excessive resources or exhausting memory.
-
- Any application parsing untrusted data through d2i BIO functions is
- affected. The memory based functions such as d2i_X509() are *not* affected.
- Since the memory based functions are used by the TLS library, TLS
- applications are not affected.
-
- This issue was reported by Brian Carpenter.
- (CVE-2016-2109)
- [Stephen Henson]
-
- *) EBCDIC overread
-
- ASN1 Strings that are over 1024 bytes can cause an overread in applications
- using the X509_NAME_oneline() function on EBCDIC systems. This could result
- in arbitrary stack data being returned in the buffer.
-
- This issue was reported by Guido Vranken.
- (CVE-2016-2176)
- [Matt Caswell]
-
- *) Modify behavior of ALPN to invoke callback after SNI/servername
- callback, such that updates to the SSL_CTX affect ALPN.
- [Todd Short]
-
- *) Remove LOW from the DEFAULT cipher list. This removes singles DES from the
- default.
- [Kurt Roeckx]
-
- *) Only remove the SSLv2 methods with the no-ssl2-method option. When the
- methods are enabled and ssl2 is disabled the methods return NULL.
- [Kurt Roeckx]
-
- Changes between 1.0.2f and 1.0.2g [1 Mar 2016]
-
- * Disable weak ciphers in SSLv3 and up in default builds of OpenSSL.
- Builds that are not configured with "enable-weak-ssl-ciphers" will not
- provide any "EXPORT" or "LOW" strength ciphers.
- [Viktor Dukhovni]
-
- * Disable SSLv2 default build, default negotiation and weak ciphers. SSLv2
- is by default disabled at build-time. Builds that are not configured with
- "enable-ssl2" will not support SSLv2. Even if "enable-ssl2" is used,
- users who want to negotiate SSLv2 via the version-flexible SSLv23_method()
- will need to explicitly call either of:
-
- SSL_CTX_clear_options(ctx, SSL_OP_NO_SSLv2);
- or
- SSL_clear_options(ssl, SSL_OP_NO_SSLv2);
-
- as appropriate. Even if either of those is used, or the application
- explicitly uses the version-specific SSLv2_method() or its client and
- server variants, SSLv2 ciphers vulnerable to exhaustive search key
- recovery have been removed. Specifically, the SSLv2 40-bit EXPORT
- ciphers, and SSLv2 56-bit DES are no longer available.
- (CVE-2016-0800)
- [Viktor Dukhovni]
-
- *) Fix a double-free in DSA code
-
- A double free bug was discovered when OpenSSL parses malformed DSA private
- keys and could lead to a DoS attack or memory corruption for applications
- that receive DSA private keys from untrusted sources. This scenario is
- considered rare.
-
- This issue was reported to OpenSSL by Adam Langley(Google/BoringSSL) using
- libFuzzer.
- (CVE-2016-0705)
- [Stephen Henson]
-
- *) Disable SRP fake user seed to address a server memory leak.
-
- Add a new method SRP_VBASE_get1_by_user that handles the seed properly.
-
- SRP_VBASE_get_by_user had inconsistent memory management behaviour.
- In order to fix an unavoidable memory leak, SRP_VBASE_get_by_user
- was changed to ignore the "fake user" SRP seed, even if the seed
- is configured.
-
- Users should use SRP_VBASE_get1_by_user instead. Note that in
- SRP_VBASE_get1_by_user, caller must free the returned value. Note
- also that even though configuring the SRP seed attempts to hide
- invalid usernames by continuing the handshake with fake
- credentials, this behaviour is not constant time and no strong
- guarantees are made that the handshake is indistinguishable from
- that of a valid user.
- (CVE-2016-0798)
- [Emilia Käsper]
-
- *) Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption
-
- In the BN_hex2bn function the number of hex digits is calculated using an
- int value |i|. Later |bn_expand| is called with a value of |i * 4|. For
- large values of |i| this can result in |bn_expand| not allocating any
- memory because |i * 4| is negative. This can leave the internal BIGNUM data
- field as NULL leading to a subsequent NULL ptr deref. For very large values
- of |i|, the calculation |i * 4| could be a positive value smaller than |i|.
- In this case memory is allocated to the internal BIGNUM data field, but it
- is insufficiently sized leading to heap corruption. A similar issue exists
- in BN_dec2bn. This could have security consequences if BN_hex2bn/BN_dec2bn
- is ever called by user applications with very large untrusted hex/dec data.
- This is anticipated to be a rare occurrence.
-
- All OpenSSL internal usage of these functions use data that is not expected
- to be untrusted, e.g. config file data or application command line
- arguments. If user developed applications generate config file data based
- on untrusted data then it is possible that this could also lead to security
- consequences. This is also anticipated to be rare.
-
- This issue was reported to OpenSSL by Guido Vranken.
- (CVE-2016-0797)
- [Matt Caswell]
-
- *) Fix memory issues in BIO_*printf functions
-
- The internal |fmtstr| function used in processing a "%s" format string in
- the BIO_*printf functions could overflow while calculating the length of a
- string and cause an OOB read when printing very long strings.
-
- Additionally the internal |doapr_outch| function can attempt to write to an
- OOB memory location (at an offset from the NULL pointer) in the event of a
- memory allocation failure. In 1.0.2 and below this could be caused where
- the size of a buffer to be allocated is greater than INT_MAX. E.g. this
- could be in processing a very long "%s" format string. Memory leaks can
- also occur.
-
- The first issue may mask the second issue dependent on compiler behaviour.
- These problems could enable attacks where large amounts of untrusted data
- is passed to the BIO_*printf functions. If applications use these functions
- in this way then they could be vulnerable. OpenSSL itself uses these
- functions when printing out human-readable dumps of ASN.1 data. Therefore
- applications that print this data could be vulnerable if the data is from
- untrusted sources. OpenSSL command line applications could also be
- vulnerable where they print out ASN.1 data, or if untrusted data is passed
- as command line arguments.
-
- Libssl is not considered directly vulnerable. Additionally certificates etc
- received via remote connections via libssl are also unlikely to be able to
- trigger these issues because of message size limits enforced within libssl.
-
- This issue was reported to OpenSSL Guido Vranken.
- (CVE-2016-0799)
- [Matt Caswell]
-
- *) Side channel attack on modular exponentiation
-
- A side-channel attack was found which makes use of cache-bank conflicts on
- the Intel Sandy-Bridge microarchitecture which could lead to the recovery
- of RSA keys. The ability to exploit this issue is limited as it relies on
- an attacker who has control of code in a thread running on the same
- hyper-threaded core as the victim thread which is performing decryptions.
-
- This issue was reported to OpenSSL by Yuval Yarom, The University of
- Adelaide and NICTA, Daniel Genkin, Technion and Tel Aviv University, and
- Nadia Heninger, University of Pennsylvania with more information at
- http://cachebleed.info.
- (CVE-2016-0702)
- [Andy Polyakov]
-
- *) Change the req app to generate a 2048-bit RSA/DSA key by default,
- if no keysize is specified with default_bits. This fixes an
- omission in an earlier change that changed all RSA/DSA key generation
- apps to use 2048 bits by default.
- [Emilia Käsper]
-
- Changes between 1.0.2e and 1.0.2f [28 Jan 2016]
- *) DH small subgroups
-
- Historically OpenSSL only ever generated DH parameters based on "safe"
- primes. More recently (in version 1.0.2) support was provided for
- generating X9.42 style parameter files such as those required for RFC 5114
- support. The primes used in such files may not be "safe". Where an
- application is using DH configured with parameters based on primes that are
- not "safe" then an attacker could use this fact to find a peer's private
- DH exponent. This attack requires that the attacker complete multiple
- handshakes in which the peer uses the same private DH exponent. For example
- this could be used to discover a TLS server's private DH exponent if it's
- reusing the private DH exponent or it's using a static DH ciphersuite.
-
- OpenSSL provides the option SSL_OP_SINGLE_DH_USE for ephemeral DH (DHE) in
- TLS. It is not on by default. If the option is not set then the server
- reuses the same private DH exponent for the life of the server process and
- would be vulnerable to this attack. It is believed that many popular
- applications do set this option and would therefore not be at risk.
-
- The fix for this issue adds an additional check where a "q" parameter is
- available (as is the case in X9.42 based parameters). This detects the
- only known attack, and is the only possible defense for static DH
- ciphersuites. This could have some performance impact.
-
- Additionally the SSL_OP_SINGLE_DH_USE option has been switched on by
- default and cannot be disabled. This could have some performance impact.
-
- This issue was reported to OpenSSL by Antonio Sanso (Adobe).
- (CVE-2016-0701)
- [Matt Caswell]
-
- *) SSLv2 doesn't block disabled ciphers
-
- A malicious client can negotiate SSLv2 ciphers that have been disabled on
- the server and complete SSLv2 handshakes even if all SSLv2 ciphers have
- been disabled, provided that the SSLv2 protocol was not also disabled via
- SSL_OP_NO_SSLv2.
-
- This issue was reported to OpenSSL on 26th December 2015 by Nimrod Aviram
- and Sebastian Schinzel.
- (CVE-2015-3197)
- [Viktor Dukhovni]
-
- Changes between 1.0.2d and 1.0.2e [3 Dec 2015]
-
- *) BN_mod_exp may produce incorrect results on x86_64
-
- There is a carry propagating bug in the x86_64 Montgomery squaring
- procedure. No EC algorithms are affected. Analysis suggests that attacks
- against RSA and DSA as a result of this defect would be very difficult to
- perform and are not believed likely. Attacks against DH are considered just
- feasible (although very difficult) because most of the work necessary to
- deduce information about a private key may be performed offline. The amount
- of resources required for such an attack would be very significant and
- likely only accessible to a limited number of attackers. An attacker would
- additionally need online access to an unpatched system using the target
- private key in a scenario with persistent DH parameters and a private
- key that is shared between multiple clients. For example this can occur by
- default in OpenSSL DHE based SSL/TLS ciphersuites.
-
- This issue was reported to OpenSSL by Hanno Böck.
- (CVE-2015-3193)
- [Andy Polyakov]
-
- *) Certificate verify crash with missing PSS parameter
-
- The signature verification routines will crash with a NULL pointer
- dereference if presented with an ASN.1 signature using the RSA PSS
- algorithm and absent mask generation function parameter. Since these
- routines are used to verify certificate signature algorithms this can be
- used to crash any certificate verification operation and exploited in a
- DoS attack. Any application which performs certificate verification is
- vulnerable including OpenSSL clients and servers which enable client
- authentication.
-
- This issue was reported to OpenSSL by Loïc Jonas Etienne (Qnective AG).
- (CVE-2015-3194)
- [Stephen Henson]
-
- *) X509_ATTRIBUTE memory leak
-
- When presented with a malformed X509_ATTRIBUTE structure OpenSSL will leak
- memory. This structure is used by the PKCS#7 and CMS routines so any
- application which reads PKCS#7 or CMS data from untrusted sources is
- affected. SSL/TLS is not affected.
-
- This issue was reported to OpenSSL by Adam Langley (Google/BoringSSL) using
- libFuzzer.
- (CVE-2015-3195)
- [Stephen Henson]
-
- *) Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs.
- This changes the decoding behaviour for some invalid messages,
- though the change is mostly in the more lenient direction, and
- legacy behaviour is preserved as much as possible.
- [Emilia Käsper]
-
- *) In DSA_generate_parameters_ex, if the provided seed is too short,
- return an error
- [Rich Salz and Ismo Puustinen <ismo.puustinen@intel.com>]
-
- Changes between 1.0.2c and 1.0.2d [9 Jul 2015]
-
- *) Alternate chains certificate forgery
-
- During certificate verification, OpenSSL will attempt to find an
- alternative certificate chain if the first attempt to build such a chain
- fails. An error in the implementation of this logic can mean that an
- attacker could cause certain checks on untrusted certificates to be
- bypassed, such as the CA flag, enabling them to use a valid leaf
- certificate to act as a CA and "issue" an invalid certificate.
-
- This issue was reported to OpenSSL by Adam Langley/David Benjamin
- (Google/BoringSSL).
- [Matt Caswell]
-
- Changes between 1.0.2b and 1.0.2c [12 Jun 2015]
-
- *) Fix HMAC ABI incompatibility. The previous version introduced an ABI
- incompatibility in the handling of HMAC. The previous ABI has now been
- restored.
- [Matt Caswell]
-
- Changes between 1.0.2a and 1.0.2b [11 Jun 2015]
-
- *) Malformed ECParameters causes infinite loop
-
- When processing an ECParameters structure OpenSSL enters an infinite loop
- if the curve specified is over a specially malformed binary polynomial
- field.
-
- This can be used to perform denial of service against any
- system which processes public keys, certificate requests or
- certificates. This includes TLS clients and TLS servers with
- client authentication enabled.
-
- This issue was reported to OpenSSL by Joseph Barr-Pixton.
- (CVE-2015-1788)
- [Andy Polyakov]
-
- *) Exploitable out-of-bounds read in X509_cmp_time
-
- X509_cmp_time does not properly check the length of the ASN1_TIME
- string and can read a few bytes out of bounds. In addition,
- X509_cmp_time accepts an arbitrary number of fractional seconds in the
- time string.
-
- An attacker can use this to craft malformed certificates and CRLs of
- various sizes and potentially cause a segmentation fault, resulting in
- a DoS on applications that verify certificates or CRLs. TLS clients
- that verify CRLs are affected. TLS clients and servers with client
- authentication enabled may be affected if they use custom verification
- callbacks.
-
- This issue was reported to OpenSSL by Robert Swiecki (Google), and
- independently by Hanno Böck.
- (CVE-2015-1789)
- [Emilia Käsper]
-
- *) PKCS7 crash with missing EnvelopedContent
-
- The PKCS#7 parsing code does not handle missing inner EncryptedContent
- correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs
- with missing content and trigger a NULL pointer dereference on parsing.
-
- Applications that decrypt PKCS#7 data or otherwise parse PKCS#7
- structures from untrusted sources are affected. OpenSSL clients and
- servers are not affected.
-
- This issue was reported to OpenSSL by Michal Zalewski (Google).
- (CVE-2015-1790)
- [Emilia Käsper]
-
- *) CMS verify infinite loop with unknown hash function
-
- When verifying a signedData message the CMS code can enter an infinite loop
- if presented with an unknown hash function OID. This can be used to perform
- denial of service against any system which verifies signedData messages using
- the CMS code.
- This issue was reported to OpenSSL by Johannes Bauer.
- (CVE-2015-1792)
- [Stephen Henson]
-
- *) Race condition handling NewSessionTicket
-
- If a NewSessionTicket is received by a multi-threaded client when attempting to
- reuse a previous ticket then a race condition can occur potentially leading to
- a double free of the ticket data.
- (CVE-2015-1791)
- [Matt Caswell]
-
- *) Only support 256-bit or stronger elliptic curves with the
- 'ecdh_auto' setting (server) or by default (client). Of supported
- curves, prefer P-256 (both).
- [Emilia Kasper]
-
- Changes between 1.0.2 and 1.0.2a [19 Mar 2015]
-
- *) ClientHello sigalgs DoS fix
-
- If a client connects to an OpenSSL 1.0.2 server and renegotiates with an
- invalid signature algorithms extension a NULL pointer dereference will
- occur. This can be exploited in a DoS attack against the server.
-
- This issue was was reported to OpenSSL by David Ramos of Stanford
- University.
- (CVE-2015-0291)
- [Stephen Henson and Matt Caswell]
-
- *) Multiblock corrupted pointer fix
-
- OpenSSL 1.0.2 introduced the "multiblock" performance improvement. This
- feature only applies on 64 bit x86 architecture platforms that support AES
- NI instructions. A defect in the implementation of "multiblock" can cause
- OpenSSL's internal write buffer to become incorrectly set to NULL when
- using non-blocking IO. Typically, when the user application is using a
- socket BIO for writing, this will only result in a failed connection.
- However if some other BIO is used then it is likely that a segmentation
- fault will be triggered, thus enabling a potential DoS attack.
-
- This issue was reported to OpenSSL by Daniel Danner and Rainer Mueller.
- (CVE-2015-0290)
- [Matt Caswell]
-
- *) Segmentation fault in DTLSv1_listen fix
-
- The DTLSv1_listen function is intended to be stateless and processes the
- initial ClientHello from many peers. It is common for user code to loop
- over the call to DTLSv1_listen until a valid ClientHello is received with
- an associated cookie. A defect in the implementation of DTLSv1_listen means
- that state is preserved in the SSL object from one invocation to the next
- that can lead to a segmentation fault. Errors processing the initial
- ClientHello can trigger this scenario. An example of such an error could be
- that a DTLS1.0 only client is attempting to connect to a DTLS1.2 only
- server.
-
- This issue was reported to OpenSSL by Per Allansson.
- (CVE-2015-0207)
- [Matt Caswell]
-
- *) Segmentation fault in ASN1_TYPE_cmp fix
-
- The function ASN1_TYPE_cmp will crash with an invalid read if an attempt is
- made to compare ASN.1 boolean types. Since ASN1_TYPE_cmp is used to check
- certificate signature algorithm consistency this can be used to crash any
- certificate verification operation and exploited in a DoS attack. Any
- application which performs certificate verification is vulnerable including
- OpenSSL clients and servers which enable client authentication.
- (CVE-2015-0286)
- [Stephen Henson]
-
- *) Segmentation fault for invalid PSS parameters fix
-
- The signature verification routines will crash with a NULL pointer
- dereference if presented with an ASN.1 signature using the RSA PSS
- algorithm and invalid parameters. Since these routines are used to verify
- certificate signature algorithms this can be used to crash any
- certificate verification operation and exploited in a DoS attack. Any
- application which performs certificate verification is vulnerable including
- OpenSSL clients and servers which enable client authentication.
-
- This issue was was reported to OpenSSL by Brian Carpenter.
- (CVE-2015-0208)
- [Stephen Henson]
-
- *) ASN.1 structure reuse memory corruption fix
-
- Reusing a structure in ASN.1 parsing may allow an attacker to cause
- memory corruption via an invalid write. Such reuse is and has been
- strongly discouraged and is believed to be rare.
-
- Applications that parse structures containing CHOICE or ANY DEFINED BY
- components may be affected. Certificate parsing (d2i_X509 and related
- functions) are however not affected. OpenSSL clients and servers are
- not affected.
- (CVE-2015-0287)
- [Stephen Henson]
-
- *) PKCS7 NULL pointer dereferences fix
-
- The PKCS#7 parsing code does not handle missing outer ContentInfo
- correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs with
- missing content and trigger a NULL pointer dereference on parsing.
-
- Applications that verify PKCS#7 signatures, decrypt PKCS#7 data or
- otherwise parse PKCS#7 structures from untrusted sources are
- affected. OpenSSL clients and servers are not affected.
-
- This issue was reported to OpenSSL by Michal Zalewski (Google).
- (CVE-2015-0289)
- [Emilia Käsper]
-
- *) DoS via reachable assert in SSLv2 servers fix
-
- A malicious client can trigger an OPENSSL_assert (i.e., an abort) in
- servers that both support SSLv2 and enable export cipher suites by sending
- a specially crafted SSLv2 CLIENT-MASTER-KEY message.
-
- This issue was discovered by Sean Burford (Google) and Emilia Käsper
- (OpenSSL development team).
- (CVE-2015-0293)
- [Emilia Käsper]
-
- *) Empty CKE with client auth and DHE fix
-
- If client auth is used then a server can seg fault in the event of a DHE
- ciphersuite being selected and a zero length ClientKeyExchange message
- being sent by the client. This could be exploited in a DoS attack.
- (CVE-2015-1787)
- [Matt Caswell]
-
- *) Handshake with unseeded PRNG fix
-
- Under certain conditions an OpenSSL 1.0.2 client can complete a handshake
- with an unseeded PRNG. The conditions are:
- - The client is on a platform where the PRNG has not been seeded
- automatically, and the user has not seeded manually
- - A protocol specific client method version has been used (i.e. not
- SSL_client_methodv23)
- - A ciphersuite is used that does not require additional random data from
- the PRNG beyond the initial ClientHello client random (e.g. PSK-RC4-SHA).
-
- If the handshake succeeds then the client random that has been used will
- have been generated from a PRNG with insufficient entropy and therefore the
- output may be predictable.
-
- For example using the following command with an unseeded openssl will
- succeed on an unpatched platform:
-
- openssl s_client -psk 1a2b3c4d -tls1_2 -cipher PSK-RC4-SHA
- (CVE-2015-0285)
- [Matt Caswell]
-
- *) Use After Free following d2i_ECPrivatekey error fix
-
- A malformed EC private key file consumed via the d2i_ECPrivateKey function
- could cause a use after free condition. This, in turn, could cause a double
- free in several private key parsing functions (such as d2i_PrivateKey
- or EVP_PKCS82PKEY) and could lead to a DoS attack or memory corruption
- for applications that receive EC private keys from untrusted
- sources. This scenario is considered rare.
-
- This issue was discovered by the BoringSSL project and fixed in their
- commit 517073cd4b.
- (CVE-2015-0209)
- [Matt Caswell]
-
- *) X509_to_X509_REQ NULL pointer deref fix
-
- The function X509_to_X509_REQ will crash with a NULL pointer dereference if
- the certificate key is invalid. This function is rarely used in practice.
-
- This issue was discovered by Brian Carpenter.
- (CVE-2015-0288)
- [Stephen Henson]
-
- *) Removed the export ciphers from the DEFAULT ciphers
- [Kurt Roeckx]
-
- Changes between 1.0.1l and 1.0.2 [22 Jan 2015]
-
- *) Facilitate "universal" ARM builds targeting range of ARM ISAs, e.g.
- ARMv5 through ARMv8, as opposite to "locking" it to single one.
- So far those who have to target multiple platforms would compromise
- and argue that binary targeting say ARMv5 would still execute on
- ARMv8. "Universal" build resolves this compromise by providing
- near-optimal performance even on newer platforms.
- [Andy Polyakov]
-
- *) Accelerated NIST P-256 elliptic curve implementation for x86_64
- (other platforms pending).
- [Shay Gueron & Vlad Krasnov (Intel Corp), Andy Polyakov]
-
- *) Add support for the SignedCertificateTimestampList certificate and
- OCSP response extensions from RFC6962.
- [Rob Stradling]
-
- *) Fix ec_GFp_simple_points_make_affine (thus, EC_POINTs_mul etc.)
- for corner cases. (Certain input points at infinity could lead to
- bogus results, with non-infinity inputs mapped to infinity too.)
- [Bodo Moeller]
-
- *) Initial support for PowerISA 2.0.7, first implemented in POWER8.
- This covers AES, SHA256/512 and GHASH. "Initial" means that most
- common cases are optimized and there still is room for further
- improvements. Vector Permutation AES for Altivec is also added.
- [Andy Polyakov]
-
- *) Add support for little-endian ppc64 Linux target.
- [Marcelo Cerri (IBM)]
-
- *) Initial support for AMRv8 ISA crypto extensions. This covers AES,
- SHA1, SHA256 and GHASH. "Initial" means that most common cases
- are optimized and there still is room for further improvements.
- Both 32- and 64-bit modes are supported.
- [Andy Polyakov, Ard Biesheuvel (Linaro)]
-
- *) Improved ARMv7 NEON support.
- [Andy Polyakov]
-
- *) Support for SPARC Architecture 2011 crypto extensions, first
- implemented in SPARC T4. This covers AES, DES, Camellia, SHA1,
- SHA256/512, MD5, GHASH and modular exponentiation.
- [Andy Polyakov, David Miller]
-
- *) Accelerated modular exponentiation for Intel processors, a.k.a.
- RSAZ.
- [Shay Gueron & Vlad Krasnov (Intel Corp)]
-
- *) Support for new and upcoming Intel processors, including AVX2,
- BMI and SHA ISA extensions. This includes additional "stitched"
- implementations, AESNI-SHA256 and GCM, and multi-buffer support
- for TLS encrypt.
-
- This work was sponsored by Intel Corp.
- [Andy Polyakov]
-
- *) Support for DTLS 1.2. This adds two sets of DTLS methods: DTLS_*_method()
- supports both DTLS 1.2 and 1.0 and should use whatever version the peer
- supports and DTLSv1_2_*_method() which supports DTLS 1.2 only.
- [Steve Henson]
-
- *) Use algorithm specific chains in SSL_CTX_use_certificate_chain_file():
- this fixes a limitation in previous versions of OpenSSL.
- [Steve Henson]
-
- *) Extended RSA OAEP support via EVP_PKEY API. Options to specify digest,
- MGF1 digest and OAEP label.
- [Steve Henson]
-
- *) Add EVP support for key wrapping algorithms, to avoid problems with
- existing code the flag EVP_CIPHER_CTX_WRAP_ALLOW has to be set in
- the EVP_CIPHER_CTX or an error is returned. Add AES and DES3 wrap
- algorithms and include tests cases.
- [Steve Henson]
-
- *) Add functions to allocate and set the fields of an ECDSA_METHOD
- structure.
- [Douglas E. Engert, Steve Henson]
-
- *) New functions OPENSSL_gmtime_diff and ASN1_TIME_diff to find the
- difference in days and seconds between two tm or ASN1_TIME structures.
- [Steve Henson]
-
- *) Add -rev test option to s_server to just reverse order of characters
- received by client and send back to server. Also prints an abbreviated
- summary of the connection parameters.
- [Steve Henson]
-
- *) New option -brief for s_client and s_server to print out a brief summary
- of connection parameters.
- [Steve Henson]
-
- *) Add callbacks for arbitrary TLS extensions.
- [Trevor Perrin <trevp@trevp.net> and Ben Laurie]
-
- *) New option -crl_download in several openssl utilities to download CRLs
- from CRLDP extension in certificates.
- [Steve Henson]
-
- *) New options -CRL and -CRLform for s_client and s_server for CRLs.
- [Steve Henson]
-
- *) New function X509_CRL_diff to generate a delta CRL from the difference
- of two full CRLs. Add support to "crl" utility.
- [Steve Henson]
-
- *) New functions to set lookup_crls function and to retrieve
- X509_STORE from X509_STORE_CTX.
- [Steve Henson]
-
- *) Print out deprecated issuer and subject unique ID fields in
- certificates.
- [Steve Henson]
-
- *) Extend OCSP I/O functions so they can be used for simple general purpose
- HTTP as well as OCSP. New wrapper function which can be used to download
- CRLs using the OCSP API.
- [Steve Henson]
-
- *) Delegate command line handling in s_client/s_server to SSL_CONF APIs.
- [Steve Henson]
-
- *) SSL_CONF* functions. These provide a common framework for application
- configuration using configuration files or command lines.
- [Steve Henson]
-
- *) SSL/TLS tracing code. This parses out SSL/TLS records using the
- message callback and prints the results. Needs compile time option
- "enable-ssl-trace". New options to s_client and s_server to enable
- tracing.
- [Steve Henson]
-
- *) New ctrl and macro to retrieve supported points extensions.
- Print out extension in s_server and s_client.
- [Steve Henson]
-
- *) New functions to retrieve certificate signature and signature
- OID NID.
- [Steve Henson]
-
- *) Add functions to retrieve and manipulate the raw cipherlist sent by a
- client to OpenSSL.
- [Steve Henson]
-
- *) New Suite B modes for TLS code. These use and enforce the requirements
- of RFC6460: restrict ciphersuites, only permit Suite B algorithms and
- only use Suite B curves. The Suite B modes can be set by using the
- strings "SUITEB128", "SUITEB192" or "SUITEB128ONLY" for the cipherstring.
- [Steve Henson]
-
- *) New chain verification flags for Suite B levels of security. Check
- algorithms are acceptable when flags are set in X509_verify_cert.
- [Steve Henson]
-
- *) Make tls1_check_chain return a set of flags indicating checks passed
- by a certificate chain. Add additional tests to handle client
- certificates: checks for matching certificate type and issuer name
- comparison.
- [Steve Henson]
-
- *) If an attempt is made to use a signature algorithm not in the peer
- preference list abort the handshake. If client has no suitable
- signature algorithms in response to a certificate request do not
- use the certificate.
- [Steve Henson]
-
- *) If server EC tmp key is not in client preference list abort handshake.
- [Steve Henson]
-
- *) Add support for certificate stores in CERT structure. This makes it
- possible to have different stores per SSL structure or one store in
- the parent SSL_CTX. Include distinct stores for certificate chain
- verification and chain building. New ctrl SSL_CTRL_BUILD_CERT_CHAIN
- to build and store a certificate chain in CERT structure: returning
- an error if the chain cannot be built: this will allow applications
- to test if a chain is correctly configured.
-
- Note: if the CERT based stores are not set then the parent SSL_CTX
- store is used to retain compatibility with existing behaviour.
-
- [Steve Henson]
-
- *) New function ssl_set_client_disabled to set a ciphersuite disabled
- mask based on the current session, check mask when sending client
- hello and checking the requested ciphersuite.
- [Steve Henson]
-
- *) New ctrls to retrieve and set certificate types in a certificate
- request message. Print out received values in s_client. If certificate
- types is not set with custom values set sensible values based on
- supported signature algorithms.
- [Steve Henson]
-
- *) Support for distinct client and server supported signature algorithms.
- [Steve Henson]
-
- *) Add certificate callback. If set this is called whenever a certificate
- is required by client or server. An application can decide which
- certificate chain to present based on arbitrary criteria: for example
- supported signature algorithms. Add very simple example to s_server.
- This fixes many of the problems and restrictions of the existing client
- certificate callback: for example you can now clear an existing
- certificate and specify the whole chain.
- [Steve Henson]
-
- *) Add new "valid_flags" field to CERT_PKEY structure which determines what
- the certificate can be used for (if anything). Set valid_flags field
- in new tls1_check_chain function. Simplify ssl_set_cert_masks which used
- to have similar checks in it.
-
- Add new "cert_flags" field to CERT structure and include a "strict mode".
- This enforces some TLS certificate requirements (such as only permitting
- certificate signature algorithms contained in the supported algorithms
- extension) which some implementations ignore: this option should be used
- with caution as it could cause interoperability issues.
- [Steve Henson]
-
- *) Update and tidy signature algorithm extension processing. Work out
- shared signature algorithms based on preferences and peer algorithms
- and print them out in s_client and s_server. Abort handshake if no
- shared signature algorithms.
- [Steve Henson]
-
- *) Add new functions to allow customised supported signature algorithms
- for SSL and SSL_CTX structures. Add options to s_client and s_server
- to support them.
- [Steve Henson]
-
- *) New function SSL_certs_clear() to delete all references to certificates
- from an SSL structure. Before this once a certificate had been added
- it couldn't be removed.
- [Steve Henson]
-
- *) Integrate hostname, email address and IP address checking with certificate
- verification. New verify options supporting checking in openssl utility.
- [Steve Henson]
-
- *) Fixes and wildcard matching support to hostname and email checking
- functions. Add manual page.
- [Florian Weimer (Red Hat Product Security Team)]
-
- *) New functions to check a hostname email or IP address against a
- certificate. Add options x509 utility to print results of checks against
- a certificate.
- [Steve Henson]
-
- *) Fix OCSP checking.
- [Rob Stradling <rob.stradling@comodo.com> and Ben Laurie]
-
- *) Initial experimental support for explicitly trusted non-root CAs.
- OpenSSL still tries to build a complete chain to a root but if an
- intermediate CA has a trust setting included that is used. The first
- setting is used: whether to trust (e.g., -addtrust option to the x509
- utility) or reject.
- [Steve Henson]
-
- *) Add -trusted_first option which attempts to find certificates in the
- trusted store even if an untrusted chain is also supplied.
- [Steve Henson]
-
- *) MIPS assembly pack updates: support for MIPS32r2 and SmartMIPS ASE,
- platform support for Linux and Android.
- [Andy Polyakov]
-
- *) Support for linux-x32, ILP32 environment in x86_64 framework.
- [Andy Polyakov]
-
- *) Experimental multi-implementation support for FIPS capable OpenSSL.
- When in FIPS mode the approved implementations are used as normal,
- when not in FIPS mode the internal unapproved versions are used instead.
- This means that the FIPS capable OpenSSL isn't forced to use the
- (often lower performance) FIPS implementations outside FIPS mode.
- [Steve Henson]
-
- *) Transparently support X9.42 DH parameters when calling
- PEM_read_bio_DHparameters. This means existing applications can handle
- the new parameter format automatically.
- [Steve Henson]
-
- *) Initial experimental support for X9.42 DH parameter format: mainly
- to support use of 'q' parameter for RFC5114 parameters.
- [Steve Henson]
-
- *) Add DH parameters from RFC5114 including test data to dhtest.
- [Steve Henson]
-
- *) Support for automatic EC temporary key parameter selection. If enabled
- the most preferred EC parameters are automatically used instead of
- hardcoded fixed parameters. Now a server just has to call:
- SSL_CTX_set_ecdh_auto(ctx, 1) and the server will automatically
- support ECDH and use the most appropriate parameters.
- [Steve Henson]
-
- *) Enhance and tidy EC curve and point format TLS extension code. Use
- static structures instead of allocation if default values are used.
- New ctrls to set curves we wish to support and to retrieve shared curves.
- Print out shared curves in s_server. New options to s_server and s_client
- to set list of supported curves.
- [Steve Henson]
-
- *) New ctrls to retrieve supported signature algorithms and
- supported curve values as an array of NIDs. Extend openssl utility
- to print out received values.
- [Steve Henson]
-
- *) Add new APIs EC_curve_nist2nid and EC_curve_nid2nist which convert
- between NIDs and the more common NIST names such as "P-256". Enhance
- ecparam utility and ECC method to recognise the NIST names for curves.
- [Steve Henson]
-
- *) Enhance SSL/TLS certificate chain handling to support different
- chains for each certificate instead of one chain in the parent SSL_CTX.
- [Steve Henson]
-
- *) Support for fixed DH ciphersuite client authentication: where both
- server and client use DH certificates with common parameters.
- [Steve Henson]
-
- *) Support for fixed DH ciphersuites: those requiring DH server
- certificates.
- [Steve Henson]
-
- *) New function i2d_re_X509_tbs for re-encoding the TBS portion of
- the certificate.
- Note: Related 1.0.2-beta specific macros X509_get_cert_info,
- X509_CINF_set_modified, X509_CINF_get_issuer, X509_CINF_get_extensions and
- X509_CINF_get_signature were reverted post internal team review.
-
- Changes between 1.0.1k and 1.0.1l [15 Jan 2015]
-
- *) Build fixes for the Windows and OpenVMS platforms
- [Matt Caswell and Richard Levitte]
-
- Changes between 1.0.1j and 1.0.1k [8 Jan 2015]
-
- *) Fix DTLS segmentation fault in dtls1_get_record. A carefully crafted DTLS
- message can cause a segmentation fault in OpenSSL due to a NULL pointer
- dereference. This could lead to a Denial Of Service attack. Thanks to
- Markus Stenberg of Cisco Systems, Inc. for reporting this issue.
- (CVE-2014-3571)
- [Steve Henson]
-
- *) Fix DTLS memory leak in dtls1_buffer_record. A memory leak can occur in the
- dtls1_buffer_record function under certain conditions. In particular this
- could occur if an attacker sent repeated DTLS records with the same
- sequence number but for the next epoch. The memory leak could be exploited
- by an attacker in a Denial of Service attack through memory exhaustion.
- Thanks to Chris Mueller for reporting this issue.
- (CVE-2015-0206)
- [Matt Caswell]
-
- *) Fix issue where no-ssl3 configuration sets method to NULL. When openssl is
- built with the no-ssl3 option and a SSL v3 ClientHello is received the ssl
- method would be set to NULL which could later result in a NULL pointer
- dereference. Thanks to Frank Schmirler for reporting this issue.
- (CVE-2014-3569)
- [Kurt Roeckx]
-
- *) Abort handshake if server key exchange message is omitted for ephemeral
- ECDH ciphersuites.
-
- Thanks to Karthikeyan Bhargavan of the PROSECCO team at INRIA for
- reporting this issue.
- (CVE-2014-3572)
- [Steve Henson]
-
- *) Remove non-export ephemeral RSA code on client and server. This code
- violated the TLS standard by allowing the use of temporary RSA keys in
- non-export ciphersuites and could be used by a server to effectively
- downgrade the RSA key length used to a value smaller than the server
- certificate. Thanks for Karthikeyan Bhargavan of the PROSECCO team at
- INRIA or reporting this issue.
- (CVE-2015-0204)
- [Steve Henson]
-
- *) Fixed issue where DH client certificates are accepted without verification.
- An OpenSSL server will accept a DH certificate for client authentication
- without the certificate verify message. This effectively allows a client to
- authenticate without the use of a private key. This only affects servers
- which trust a client certificate authority which issues certificates
- containing DH keys: these are extremely rare and hardly ever encountered.
- Thanks for Karthikeyan Bhargavan of the PROSECCO team at INRIA or reporting
- this issue.
- (CVE-2015-0205)
- [Steve Henson]
-
- *) Ensure that the session ID context of an SSL is updated when its
- SSL_CTX is updated via SSL_set_SSL_CTX.
-
- The session ID context is typically set from the parent SSL_CTX,
- and can vary with the CTX.
- [Adam Langley]
-
- *) Fix various certificate fingerprint issues.
-
- By using non-DER or invalid encodings outside the signed portion of a
- certificate the fingerprint can be changed without breaking the signature.
- Although no details of the signed portion of the certificate can be changed
- this can cause problems with some applications: e.g. those using the
- certificate fingerprint for blacklists.
-
- 1. Reject signatures with non zero unused bits.
-
- If the BIT STRING containing the signature has non zero unused bits reject
- the signature. All current signature algorithms require zero unused bits.
-
- 2. Check certificate algorithm consistency.
-
- Check the AlgorithmIdentifier inside TBS matches the one in the
- certificate signature. NB: this will result in signature failure
- errors for some broken certificates.
-
- Thanks to Konrad Kraszewski from Google for reporting this issue.
-
- 3. Check DSA/ECDSA signatures use DER.
-
- Re-encode DSA/ECDSA signatures and compare with the original received
- signature. Return an error if there is a mismatch.
-
- This will reject various cases including garbage after signature
- (thanks to Antti Karjalainen and Tuomo Untinen from the Codenomicon CROSS
- program for discovering this case) and use of BER or invalid ASN.1 INTEGERs
- (negative or with leading zeroes).
-
- Further analysis was conducted and fixes were developed by Stephen Henson
- of the OpenSSL core team.
-
- (CVE-2014-8275)
- [Steve Henson]
-
- *) Correct Bignum squaring. Bignum squaring (BN_sqr) may produce incorrect
- results on some platforms, including x86_64. This bug occurs at random
- with a very low probability, and is not known to be exploitable in any
- way, though its exact impact is difficult to determine. Thanks to Pieter
- Wuille (Blockstream) who reported this issue and also suggested an initial
- fix. Further analysis was conducted by the OpenSSL development team and
- Adam Langley of Google. The final fix was developed by Andy Polyakov of
- the OpenSSL core team.
- (CVE-2014-3570)
- [Andy Polyakov]
-
- *) Do not resume sessions on the server if the negotiated protocol
- version does not match the session's version. Resuming with a different
- version, while not strictly forbidden by the RFC, is of questionable
- sanity and breaks all known clients.
- [David Benjamin, Emilia Käsper]
-
- *) Tighten handling of the ChangeCipherSpec (CCS) message: reject
- early CCS messages during renegotiation. (Note that because
- renegotiation is encrypted, this early CCS was not exploitable.)
- [Emilia Käsper]
-
- *) Tighten client-side session ticket handling during renegotiation:
- ensure that the client only accepts a session ticket if the server sends
- the extension anew in the ServerHello. Previously, a TLS client would
- reuse the old extension state and thus accept a session ticket if one was
- announced in the initial ServerHello.
-
- Similarly, ensure that the client requires a session ticket if one
- was advertised in the ServerHello. Previously, a TLS client would
- ignore a missing NewSessionTicket message.
- [Emilia Käsper]
-
- Changes between 1.0.1i and 1.0.1j [15 Oct 2014]
-
- *) SRTP Memory Leak.
-
- A flaw in the DTLS SRTP extension parsing code allows an attacker, who
- sends a carefully crafted handshake message, to cause OpenSSL to fail
- to free up to 64k of memory causing a memory leak. This could be
- exploited in a Denial Of Service attack. This issue affects OpenSSL
- 1.0.1 server implementations for both SSL/TLS and DTLS regardless of
- whether SRTP is used or configured. Implementations of OpenSSL that
- have been compiled with OPENSSL_NO_SRTP defined are not affected.
-
- The fix was developed by the OpenSSL team.
- (CVE-2014-3513)
- [OpenSSL team]
-
- *) Session Ticket Memory Leak.
-
- When an OpenSSL SSL/TLS/DTLS server receives a session ticket the
- integrity of that ticket is first verified. In the event of a session
- ticket integrity check failing, OpenSSL will fail to free memory
- causing a memory leak. By sending a large number of invalid session
- tickets an attacker could exploit this issue in a Denial Of Service
- attack.
- (CVE-2014-3567)
- [Steve Henson]
-
- *) Build option no-ssl3 is incomplete.
-
- When OpenSSL is configured with "no-ssl3" as a build option, servers
- could accept and complete a SSL 3.0 handshake, and clients could be
- configured to send them.
- (CVE-2014-3568)
- [Akamai and the OpenSSL team]
-
- *) Add support for TLS_FALLBACK_SCSV.
- Client applications doing fallback retries should call
- SSL_set_mode(s, SSL_MODE_SEND_FALLBACK_SCSV).
- (CVE-2014-3566)
- [Adam Langley, Bodo Moeller]
-
- *) Add additional DigestInfo checks.
-
- Re-encode DigestInto in DER and check against the original when
- verifying RSA signature: this will reject any improperly encoded
- DigestInfo structures.
-
- Note: this is a precautionary measure and no attacks are currently known.
-
- [Steve Henson]
-
- Changes between 1.0.1h and 1.0.1i [6 Aug 2014]
-
- *) Fix SRP buffer overrun vulnerability. Invalid parameters passed to the
- SRP code can be overrun an internal buffer. Add sanity check that
- g, A, B < N to SRP code.
-
- Thanks to Sean Devlin and Watson Ladd of Cryptography Services, NCC
- Group for discovering this issue.
- (CVE-2014-3512)
- [Steve Henson]
-
- *) A flaw in the OpenSSL SSL/TLS server code causes the server to negotiate
- TLS 1.0 instead of higher protocol versions when the ClientHello message
- is badly fragmented. This allows a man-in-the-middle attacker to force a
- downgrade to TLS 1.0 even if both the server and the client support a
- higher protocol version, by modifying the client's TLS records.
-
- Thanks to David Benjamin and Adam Langley (Google) for discovering and
- researching this issue.
- (CVE-2014-3511)
- [David Benjamin]
-
- *) OpenSSL DTLS clients enabling anonymous (EC)DH ciphersuites are subject
- to a denial of service attack. A malicious server can crash the client
- with a null pointer dereference (read) by specifying an anonymous (EC)DH
- ciphersuite and sending carefully crafted handshake messages.
-
- Thanks to Felix Gröbert (Google) for discovering and researching this
- issue.
- (CVE-2014-3510)
- [Emilia Käsper]
-
- *) By sending carefully crafted DTLS packets an attacker could cause openssl
- to leak memory. This can be exploited through a Denial of Service attack.
- Thanks to Adam Langley for discovering and researching this issue.
- (CVE-2014-3507)
- [Adam Langley]
-
- *) An attacker can force openssl to consume large amounts of memory whilst
- processing DTLS handshake messages. This can be exploited through a
- Denial of Service attack.
- Thanks to Adam Langley for discovering and researching this issue.
- (CVE-2014-3506)
- [Adam Langley]
-
- *) An attacker can force an error condition which causes openssl to crash
- whilst processing DTLS packets due to memory being freed twice. This
- can be exploited through a Denial of Service attack.
- Thanks to Adam Langley and Wan-Teh Chang for discovering and researching
- this issue.
- (CVE-2014-3505)
- [Adam Langley]
-
- *) If a multithreaded client connects to a malicious server using a resumed
- session and the server sends an ec point format extension it could write
- up to 255 bytes to freed memory.
-
- Thanks to Gabor Tyukasz (LogMeIn Inc) for discovering and researching this
- issue.
- (CVE-2014-3509)
- [Gabor Tyukasz]
-
- *) A malicious server can crash an OpenSSL client with a null pointer
- dereference (read) by specifying an SRP ciphersuite even though it was not
- properly negotiated with the client. This can be exploited through a
- Denial of Service attack.
-
- Thanks to Joonas Kuorilehto and Riku Hietamäki (Codenomicon) for
- discovering and researching this issue.
- (CVE-2014-5139)
- [Steve Henson]
-
- *) A flaw in OBJ_obj2txt may cause pretty printing functions such as
- X509_name_oneline, X509_name_print_ex et al. to leak some information
- from the stack. Applications may be affected if they echo pretty printing
- output to the attacker.
-
- Thanks to Ivan Fratric (Google) for discovering this issue.
- (CVE-2014-3508)
- [Emilia Käsper, and Steve Henson]
-
- *) Fix ec_GFp_simple_points_make_affine (thus, EC_POINTs_mul etc.)
- for corner cases. (Certain input points at infinity could lead to
- bogus results, with non-infinity inputs mapped to infinity too.)
- [Bodo Moeller]
-
- Changes between 1.0.1g and 1.0.1h [5 Jun 2014]
-
- *) Fix for SSL/TLS MITM flaw. An attacker using a carefully crafted
- handshake can force the use of weak keying material in OpenSSL
- SSL/TLS clients and servers.
-
- Thanks to KIKUCHI Masashi (Lepidum Co. Ltd.) for discovering and
- researching this issue. (CVE-2014-0224)
- [KIKUCHI Masashi, Steve Henson]
-
- *) Fix DTLS recursion flaw. By sending an invalid DTLS handshake to an
- OpenSSL DTLS client the code can be made to recurse eventually crashing
- in a DoS attack.
-
- Thanks to Imre Rad (Search-Lab Ltd.) for discovering this issue.
- (CVE-2014-0221)
- [Imre Rad, Steve Henson]
-
- *) Fix DTLS invalid fragment vulnerability. A buffer overrun attack can
- be triggered by sending invalid DTLS fragments to an OpenSSL DTLS
- client or server. This is potentially exploitable to run arbitrary
- code on a vulnerable client or server.
-
- Thanks to Jüri Aedla for reporting this issue. (CVE-2014-0195)
- [Jüri Aedla, Steve Henson]
-
- *) Fix bug in TLS code where clients enable anonymous ECDH ciphersuites
- are subject to a denial of service attack.
-
- Thanks to Felix Gröbert and Ivan Fratric at Google for discovering
- this issue. (CVE-2014-3470)
- [Felix Gröbert, Ivan Fratric, Steve Henson]
-
- *) Harmonize version and its documentation. -f flag is used to display
- compilation flags.
- [mancha <mancha1@zoho.com>]
-
- *) Fix eckey_priv_encode so it immediately returns an error upon a failure
- in i2d_ECPrivateKey.
- [mancha <mancha1@zoho.com>]
-
- *) Fix some double frees. These are not thought to be exploitable.
- [mancha <mancha1@zoho.com>]
-
- Changes between 1.0.1f and 1.0.1g [7 Apr 2014]
-
- *) A missing bounds check in the handling of the TLS heartbeat extension
- can be used to reveal up to 64k of memory to a connected client or
- server.
-
- Thanks for Neel Mehta of Google Security for discovering this bug and to
- Adam Langley <agl@chromium.org> and Bodo Moeller <bmoeller@acm.org> for
- preparing the fix (CVE-2014-0160)
- [Adam Langley, Bodo Moeller]
-
- *) Fix for the attack described in the paper "Recovering OpenSSL
- ECDSA Nonces Using the FLUSH+RELOAD Cache Side-channel Attack"
- by Yuval Yarom and Naomi Benger. Details can be obtained from:
- http://eprint.iacr.org/2014/140
-
- Thanks to Yuval Yarom and Naomi Benger for discovering this
- flaw and to Yuval Yarom for supplying a fix (CVE-2014-0076)
- [Yuval Yarom and Naomi Benger]
-
- *) TLS pad extension: draft-agl-tls-padding-03
-
- Workaround for the "TLS hang bug" (see FAQ and PR#2771): if the
- TLS client Hello record length value would otherwise be > 255 and
- less that 512 pad with a dummy extension containing zeroes so it
- is at least 512 bytes long.
-
- [Adam Langley, Steve Henson]
-
- Changes between 1.0.1e and 1.0.1f [6 Jan 2014]
-
- *) Fix for TLS record tampering bug. A carefully crafted invalid
- handshake could crash OpenSSL with a NULL pointer exception.
- Thanks to Anton Johansson for reporting this issues.
- (CVE-2013-4353)
-
- *) Keep original DTLS digest and encryption contexts in retransmission
- structures so we can use the previous session parameters if they need
- to be resent. (CVE-2013-6450)
- [Steve Henson]
-
- *) Add option SSL_OP_SAFARI_ECDHE_ECDSA_BUG (part of SSL_OP_ALL) which
- avoids preferring ECDHE-ECDSA ciphers when the client appears to be
- Safari on OS X. Safari on OS X 10.8..10.8.3 advertises support for
- several ECDHE-ECDSA ciphers, but fails to negotiate them. The bug
- is fixed in OS X 10.8.4, but Apple have ruled out both hot fixing
- 10.8..10.8.3 and forcing users to upgrade to 10.8.4 or newer.
- [Rob Stradling, Adam Langley]
-
- Changes between 1.0.1d and 1.0.1e [11 Feb 2013]
-
- *) Correct fix for CVE-2013-0169. The original didn't work on AES-NI
- supporting platforms or when small records were transferred.
- [Andy Polyakov, Steve Henson]
-
- Changes between 1.0.1c and 1.0.1d [5 Feb 2013]
-
- *) Make the decoding of SSLv3, TLS and DTLS CBC records constant time.
-
- This addresses the flaw in CBC record processing discovered by
- Nadhem Alfardan and Kenny Paterson. Details of this attack can be found
- at: http://www.isg.rhul.ac.uk/tls/
-
- Thanks go to Nadhem Alfardan and Kenny Paterson of the Information
- Security Group at Royal Holloway, University of London
- (www.isg.rhul.ac.uk) for discovering this flaw and Adam Langley and
- Emilia Käsper for the initial patch.
- (CVE-2013-0169)
- [Emilia Käsper, Adam Langley, Ben Laurie, Andy Polyakov, Steve Henson]
-
- *) Fix flaw in AESNI handling of TLS 1.2 and 1.1 records for CBC mode
- ciphersuites which can be exploited in a denial of service attack.
- Thanks go to and to Adam Langley <agl@chromium.org> for discovering
- and detecting this bug and to Wolfgang Ettlinger
- <wolfgang.ettlinger@gmail.com> for independently discovering this issue.
- (CVE-2012-2686)
- [Adam Langley]
-
- *) Return an error when checking OCSP signatures when key is NULL.
- This fixes a DoS attack. (CVE-2013-0166)
- [Steve Henson]
-
- *) Make openssl verify return errors.
- [Chris Palmer <palmer@google.com> and Ben Laurie]
-
- *) Call OCSP Stapling callback after ciphersuite has been chosen, so
- the right response is stapled. Also change SSL_get_certificate()
- so it returns the certificate actually sent.
- See http://rt.openssl.org/Ticket/Display.html?id=2836.
- [Rob Stradling <rob.stradling@comodo.com>]
-
- *) Fix possible deadlock when decoding public keys.
- [Steve Henson]
-
- *) Don't use TLS 1.0 record version number in initial client hello
- if renegotiating.
- [Steve Henson]
-
- Changes between 1.0.1b and 1.0.1c [10 May 2012]
-
- *) Sanity check record length before skipping explicit IV in TLS
- 1.2, 1.1 and DTLS to fix DoS attack.
-
- Thanks to Codenomicon for discovering this issue using Fuzz-o-Matic
- fuzzing as a service testing platform.
- (CVE-2012-2333)
- [Steve Henson]
-
- *) Initialise tkeylen properly when encrypting CMS messages.
- Thanks to Solar Designer of Openwall for reporting this issue.
- [Steve Henson]
-
- *) In FIPS mode don't try to use composite ciphers as they are not
- approved.
- [Steve Henson]
-
- Changes between 1.0.1a and 1.0.1b [26 Apr 2012]
-
- *) OpenSSL 1.0.0 sets SSL_OP_ALL to 0x80000FFFL and OpenSSL 1.0.1 and
- 1.0.1a set SSL_OP_NO_TLSv1_1 to 0x00000400L which would unfortunately
- mean any application compiled against OpenSSL 1.0.0 headers setting
- SSL_OP_ALL would also set SSL_OP_NO_TLSv1_1, unintentionally disabling
- TLS 1.1 also. Fix this by changing the value of SSL_OP_NO_TLSv1_1 to
- 0x10000000L Any application which was previously compiled against
- OpenSSL 1.0.1 or 1.0.1a headers and which cares about SSL_OP_NO_TLSv1_1
- will need to be recompiled as a result. Letting be results in
- inability to disable specifically TLS 1.1 and in client context,
- in unlike event, limit maximum offered version to TLS 1.0 [see below].
- [Steve Henson]
-
- *) In order to ensure interoperability SSL_OP_NO_protocolX does not
- disable just protocol X, but all protocols above X *if* there are
- protocols *below* X still enabled. In more practical terms it means
- that if application wants to disable TLS1.0 in favor of TLS1.1 and
- above, it's not sufficient to pass SSL_OP_NO_TLSv1, one has to pass
- SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2. This applies to
- client side.
- [Andy Polyakov]
-
- Changes between 1.0.1 and 1.0.1a [19 Apr 2012]
-
- *) Check for potentially exploitable overflows in asn1_d2i_read_bio
- BUF_mem_grow and BUF_mem_grow_clean. Refuse attempts to shrink buffer
- in CRYPTO_realloc_clean.
-
- Thanks to Tavis Ormandy, Google Security Team, for discovering this
- issue and to Adam Langley <agl@chromium.org> for fixing it.
- (CVE-2012-2110)
- [Adam Langley (Google), Tavis Ormandy, Google Security Team]
-
- *) Don't allow TLS 1.2 SHA-256 ciphersuites in TLS 1.0, 1.1 connections.
- [Adam Langley]
-
- *) Workarounds for some broken servers that "hang" if a client hello
- record length exceeds 255 bytes.
-
- 1. Do not use record version number > TLS 1.0 in initial client
- hello: some (but not all) hanging servers will now work.
- 2. If we set OPENSSL_MAX_TLS1_2_CIPHER_LENGTH this will truncate
- the number of ciphers sent in the client hello. This should be
- set to an even number, such as 50, for example by passing:
- -DOPENSSL_MAX_TLS1_2_CIPHER_LENGTH=50 to config or Configure.
- Most broken servers should now work.
- 3. If all else fails setting OPENSSL_NO_TLS1_2_CLIENT will disable
- TLS 1.2 client support entirely.
- [Steve Henson]
-
- *) Fix SEGV in Vector Permutation AES module observed in OpenSSH.
- [Andy Polyakov]
-
- Changes between 1.0.0h and 1.0.1 [14 Mar 2012]
-
- *) Add compatibility with old MDC2 signatures which use an ASN1 OCTET
- STRING form instead of a DigestInfo.
- [Steve Henson]
-
- *) The format used for MDC2 RSA signatures is inconsistent between EVP
- and the RSA_sign/RSA_verify functions. This was made more apparent when
- OpenSSL used RSA_sign/RSA_verify for some RSA signatures in particular
- those which went through EVP_PKEY_METHOD in 1.0.0 and later. Detect
- the correct format in RSA_verify so both forms transparently work.
- [Steve Henson]
-
- *) Some servers which support TLS 1.0 can choke if we initially indicate
- support for TLS 1.2 and later renegotiate using TLS 1.0 in the RSA
- encrypted premaster secret. As a workaround use the maximum permitted
- client version in client hello, this should keep such servers happy
- and still work with previous versions of OpenSSL.
- [Steve Henson]
-
- *) Add support for TLS/DTLS heartbeats.
- [Robin Seggelmann <seggelmann@fh-muenster.de>]
-
- *) Add support for SCTP.
- [Robin Seggelmann <seggelmann@fh-muenster.de>]
-
- *) Improved PRNG seeding for VOS.
- [Paul Green <Paul.Green@stratus.com>]
-
- *) Extensive assembler packs updates, most notably:
-
- - x86[_64]: AES-NI, PCLMULQDQ, RDRAND support;
- - x86[_64]: SSSE3 support (SHA1, vector-permutation AES);
- - x86_64: bit-sliced AES implementation;
- - ARM: NEON support, contemporary platforms optimizations;
- - s390x: z196 support;
- - *: GHASH and GF(2^m) multiplication implementations;
-
- [Andy Polyakov]
-
- *) Make TLS-SRP code conformant with RFC 5054 API cleanup
- (removal of unnecessary code)
- [Peter Sylvester <peter.sylvester@edelweb.fr>]
-
- *) Add TLS key material exporter from RFC 5705.
- [Eric Rescorla]
-
- *) Add DTLS-SRTP negotiation from RFC 5764.
- [Eric Rescorla]
-
- *) Add Next Protocol Negotiation,
- http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-00. Can be
- disabled with a no-npn flag to config or Configure. Code donated
- by Google.
- [Adam Langley <agl@google.com> and Ben Laurie]
-
- *) Add optional 64-bit optimized implementations of elliptic curves NIST-P224,
- NIST-P256, NIST-P521, with constant-time single point multiplication on
- typical inputs. Compiler support for the nonstandard type __uint128_t is
- required to use this (present in gcc 4.4 and later, for 64-bit builds).
- Code made available under Apache License version 2.0.
-
- Specify "enable-ec_nistp_64_gcc_128" on the Configure (or config) command
- line to include this in your build of OpenSSL, and run "make depend" (or
- "make update"). This enables the following EC_METHODs:
-
- EC_GFp_nistp224_method()
- EC_GFp_nistp256_method()
- EC_GFp_nistp521_method()
-
- EC_GROUP_new_by_curve_name() will automatically use these (while
- EC_GROUP_new_curve_GFp() currently prefers the more flexible
- implementations).
- [Emilia Käsper, Adam Langley, Bodo Moeller (Google)]
-
- *) Use type ossl_ssize_t instead of ssize_t which isn't available on
- all platforms. Move ssize_t definition from e_os.h to the public
- header file e_os2.h as it now appears in public header file cms.h
- [Steve Henson]
-
- *) New -sigopt option to the ca, req and x509 utilities. Additional
- signature parameters can be passed using this option and in
- particular PSS.
- [Steve Henson]
-
- *) Add RSA PSS signing function. This will generate and set the
- appropriate AlgorithmIdentifiers for PSS based on those in the
- corresponding EVP_MD_CTX structure. No application support yet.
- [Steve Henson]
-
- *) Support for companion algorithm specific ASN1 signing routines.
- New function ASN1_item_sign_ctx() signs a pre-initialised
- EVP_MD_CTX structure and sets AlgorithmIdentifiers based on
- the appropriate parameters.
- [Steve Henson]
-
- *) Add new algorithm specific ASN1 verification initialisation function
- to EVP_PKEY_ASN1_METHOD: this is not in EVP_PKEY_METHOD since the ASN1
- handling will be the same no matter what EVP_PKEY_METHOD is used.
- Add a PSS handler to support verification of PSS signatures: checked
- against a number of sample certificates.
- [Steve Henson]
-
- *) Add signature printing for PSS. Add PSS OIDs.
- [Steve Henson, Martin Kaiser <lists@kaiser.cx>]
-
- *) Add algorithm specific signature printing. An individual ASN1 method
- can now print out signatures instead of the standard hex dump.
-
- More complex signatures (e.g. PSS) can print out more meaningful
- information. Include DSA version that prints out the signature
- parameters r, s.
- [Steve Henson]
-
- *) Password based recipient info support for CMS library: implementing
- RFC3211.
- [Steve Henson]
-
- *) Split password based encryption into PBES2 and PBKDF2 functions. This
- neatly separates the code into cipher and PBE sections and is required
- for some algorithms that split PBES2 into separate pieces (such as
- password based CMS).
- [Steve Henson]
-
- *) Session-handling fixes:
- - Fix handling of connections that are resuming with a session ID,
- but also support Session Tickets.
- - Fix a bug that suppressed issuing of a new ticket if the client
- presented a ticket with an expired session.
- - Try to set the ticket lifetime hint to something reasonable.
- - Make tickets shorter by excluding irrelevant information.
- - On the client side, don't ignore renewed tickets.
- [Adam Langley, Bodo Moeller (Google)]
-
- *) Fix PSK session representation.
- [Bodo Moeller]
-
- *) Add RC4-MD5 and AESNI-SHA1 "stitched" implementations.
-
- This work was sponsored by Intel.
- [Andy Polyakov]
-
- *) Add GCM support to TLS library. Some custom code is needed to split
- the IV between the fixed (from PRF) and explicit (from TLS record)
- portions. This adds all GCM ciphersuites supported by RFC5288 and
- RFC5289. Generalise some AES* cipherstrings to include GCM and
- add a special AESGCM string for GCM only.
- [Steve Henson]
-
- *) Expand range of ctrls for AES GCM. Permit setting invocation
- field on decrypt and retrieval of invocation field only on encrypt.
- [Steve Henson]
-
- *) Add HMAC ECC ciphersuites from RFC5289. Include SHA384 PRF support.
- As required by RFC5289 these ciphersuites cannot be used if for
- versions of TLS earlier than 1.2.
- [Steve Henson]
-
- *) For FIPS capable OpenSSL interpret a NULL default public key method
- as unset and return the appropriate default but do *not* set the default.
- This means we can return the appropriate method in applications that
- switch between FIPS and non-FIPS modes.
- [Steve Henson]
-
- *) Redirect HMAC and CMAC operations to FIPS module in FIPS mode. If an
- ENGINE is used then we cannot handle that in the FIPS module so we
- keep original code iff non-FIPS operations are allowed.
- [Steve Henson]
-
- *) Add -attime option to openssl utilities.
- [Peter Eckersley <pde@eff.org>, Ben Laurie and Steve Henson]
-
- *) Redirect DSA and DH operations to FIPS module in FIPS mode.
- [Steve Henson]
-
- *) Redirect ECDSA and ECDH operations to FIPS module in FIPS mode. Also use
- FIPS EC methods unconditionally for now.
- [Steve Henson]
-
- *) New build option no-ec2m to disable characteristic 2 code.
- [Steve Henson]
-
- *) Backport libcrypto audit of return value checking from 1.1.0-dev; not
- all cases can be covered as some introduce binary incompatibilities.
- [Steve Henson]
-
- *) Redirect RSA operations to FIPS module including keygen,
- encrypt, decrypt, sign and verify. Block use of non FIPS RSA methods.
- [Steve Henson]
-
- *) Add similar low level API blocking to ciphers.
- [Steve Henson]
-
- *) Low level digest APIs are not approved in FIPS mode: any attempt
- to use these will cause a fatal error. Applications that *really* want
- to use them can use the private_* version instead.
- [Steve Henson]
-
- *) Redirect cipher operations to FIPS module for FIPS builds.
- [Steve Henson]
-
- *) Redirect digest operations to FIPS module for FIPS builds.
- [Steve Henson]
-
- *) Update build system to add "fips" flag which will link in fipscanister.o
- for static and shared library builds embedding a signature if needed.
- [Steve Henson]
-
- *) Output TLS supported curves in preference order instead of numerical
- order. This is currently hardcoded for the highest order curves first.
- This should be configurable so applications can judge speed vs strength.
- [Steve Henson]
-
- *) Add TLS v1.2 server support for client authentication.
- [Steve Henson]
-
- *) Add support for FIPS mode in ssl library: disable SSLv3, non-FIPS ciphers
- and enable MD5.
- [Steve Henson]
-
- *) Functions FIPS_mode_set() and FIPS_mode() which call the underlying
- FIPS modules versions.
- [Steve Henson]
-
- *) Add TLS v1.2 client side support for client authentication. Keep cache
- of handshake records longer as we don't know the hash algorithm to use
- until after the certificate request message is received.
- [Steve Henson]
-
- *) Initial TLS v1.2 client support. Add a default signature algorithms
- extension including all the algorithms we support. Parse new signature
- format in client key exchange. Relax some ECC signing restrictions for
- TLS v1.2 as indicated in RFC5246.
- [Steve Henson]
-
- *) Add server support for TLS v1.2 signature algorithms extension. Switch
- to new signature format when needed using client digest preference.
- All server ciphersuites should now work correctly in TLS v1.2. No client
- support yet and no support for client certificates.
- [Steve Henson]
-
- *) Initial TLS v1.2 support. Add new SHA256 digest to ssl code, switch
- to SHA256 for PRF when using TLS v1.2 and later. Add new SHA256 based
- ciphersuites. At present only RSA key exchange ciphersuites work with
- TLS v1.2. Add new option for TLS v1.2 replacing the old and obsolete
- SSL_OP_PKCS1_CHECK flags with SSL_OP_NO_TLSv1_2. New TLSv1.2 methods
- and version checking.
- [Steve Henson]
-
- *) New option OPENSSL_NO_SSL_INTERN. If an application can be compiled
- with this defined it will not be affected by any changes to ssl internal
- structures. Add several utility functions to allow openssl application
- to work with OPENSSL_NO_SSL_INTERN defined.
- [Steve Henson]
-
- *) A long standing patch to add support for SRP from EdelWeb (Peter
- Sylvester and Christophe Renou) was integrated.
- [Christophe Renou <christophe.renou@edelweb.fr>, Peter Sylvester
- <peter.sylvester@edelweb.fr>, Tom Wu <tjw@cs.stanford.edu>, and
- Ben Laurie]
-
- *) Add functions to copy EVP_PKEY_METHOD and retrieve flags and id.
- [Steve Henson]
-
- *) Permit abbreviated handshakes when renegotiating using the function
- SSL_renegotiate_abbreviated().
- [Robin Seggelmann <seggelmann@fh-muenster.de>]
-
- *) Add call to ENGINE_register_all_complete() to
- ENGINE_load_builtin_engines(), so some implementations get used
- automatically instead of needing explicit application support.
- [Steve Henson]
-
- *) Add support for TLS key exporter as described in RFC5705.
- [Robin Seggelmann <seggelmann@fh-muenster.de>, Steve Henson]
-
- *) Initial TLSv1.1 support. Since TLSv1.1 is very similar to TLS v1.0 only
- a few changes are required:
-
- Add SSL_OP_NO_TLSv1_1 flag.
- Add TLSv1_1 methods.
- Update version checking logic to handle version 1.1.
- Add explicit IV handling (ported from DTLS code).
- Add command line options to s_client/s_server.
- [Steve Henson]
-
- Changes between 1.0.0g and 1.0.0h [12 Mar 2012]
-
- *) Fix MMA (Bleichenbacher's attack on PKCS #1 v1.5 RSA padding) weakness
- in CMS and PKCS7 code. When RSA decryption fails use a random key for
- content decryption and always return the same error. Note: this attack
- needs on average 2^20 messages so it only affects automated senders. The
- old behaviour can be re-enabled in the CMS code by setting the
- CMS_DEBUG_DECRYPT flag: this is useful for debugging and testing where
- an MMA defence is not necessary.
- Thanks to Ivan Nestlerode <inestlerode@us.ibm.com> for discovering
- this issue. (CVE-2012-0884)
- [Steve Henson]
-
- *) Fix CVE-2011-4619: make sure we really are receiving a
- client hello before rejecting multiple SGC restarts. Thanks to
- Ivan Nestlerode <inestlerode@us.ibm.com> for discovering this bug.
- [Steve Henson]
-
- Changes between 1.0.0f and 1.0.0g [18 Jan 2012]
-
- *) Fix for DTLS DoS issue introduced by fix for CVE-2011-4109.
- Thanks to Antonio Martin, Enterprise Secure Access Research and
- Development, Cisco Systems, Inc. for discovering this bug and
- preparing a fix. (CVE-2012-0050)
- [Antonio Martin]
-
- Changes between 1.0.0e and 1.0.0f [4 Jan 2012]
-
- *) Nadhem Alfardan and Kenny Paterson have discovered an extension
- of the Vaudenay padding oracle attack on CBC mode encryption
- which enables an efficient plaintext recovery attack against
- the OpenSSL implementation of DTLS. Their attack exploits timing
- differences arising during decryption processing. A research
- paper describing this attack can be found at:
- http://www.isg.rhul.ac.uk/~kp/dtls.pdf
- Thanks go to Nadhem Alfardan and Kenny Paterson of the Information
- Security Group at Royal Holloway, University of London
- (www.isg.rhul.ac.uk) for discovering this flaw and to Robin Seggelmann
- <seggelmann@fh-muenster.de> and Michael Tuexen <tuexen@fh-muenster.de>
- for preparing the fix. (CVE-2011-4108)
- [Robin Seggelmann, Michael Tuexen]
-
- *) Clear bytes used for block padding of SSL 3.0 records.
- (CVE-2011-4576)
- [Adam Langley (Google)]
-
- *) Only allow one SGC handshake restart for SSL/TLS. Thanks to George
- Kadianakis <desnacked@gmail.com> for discovering this issue and
- Adam Langley for preparing the fix. (CVE-2011-4619)
- [Adam Langley (Google)]
-
- *) Check parameters are not NULL in GOST ENGINE. (CVE-2012-0027)
- [Andrey Kulikov <amdeich@gmail.com>]
-
- *) Prevent malformed RFC3779 data triggering an assertion failure.
- Thanks to Andrew Chi, BBN Technologies, for discovering the flaw
- and Rob Austein <sra@hactrn.net> for fixing it. (CVE-2011-4577)
- [Rob Austein <sra@hactrn.net>]
-
- *) Improved PRNG seeding for VOS.
- [Paul Green <Paul.Green@stratus.com>]
-
- *) Fix ssl_ciph.c set-up race.
- [Adam Langley (Google)]
-
- *) Fix spurious failures in ecdsatest.c.
- [Emilia Käsper (Google)]
-
- *) Fix the BIO_f_buffer() implementation (which was mixing different
- interpretations of the '..._len' fields).
- [Adam Langley (Google)]
-
- *) Fix handling of BN_BLINDING: now BN_BLINDING_invert_ex (rather than
- BN_BLINDING_invert_ex) calls BN_BLINDING_update, ensuring that concurrent
- threads won't reuse the same blinding coefficients.
-
- This also avoids the need to obtain the CRYPTO_LOCK_RSA_BLINDING
- lock to call BN_BLINDING_invert_ex, and avoids one use of
- BN_BLINDING_update for each BN_BLINDING structure (previously,
- the last update always remained unused).
- [Emilia Käsper (Google)]
-
- *) In ssl3_clear, preserve s3->init_extra along with s3->rbuf.
- [Bob Buckholz (Google)]
-
- Changes between 1.0.0d and 1.0.0e [6 Sep 2011]
-
- *) Fix bug where CRLs with nextUpdate in the past are sometimes accepted
- by initialising X509_STORE_CTX properly. (CVE-2011-3207)
- [Kaspar Brand <ossl@velox.ch>]
-
- *) Fix SSL memory handling for (EC)DH ciphersuites, in particular
- for multi-threaded use of ECDH. (CVE-2011-3210)
- [Adam Langley (Google)]
-
- *) Fix x509_name_ex_d2i memory leak on bad inputs.
- [Bodo Moeller]
-
- *) Remove hard coded ecdsaWithSHA1 signature tests in ssl code and check
- signature public key algorithm by using OID xref utilities instead.
- Before this you could only use some ECC ciphersuites with SHA1 only.
- [Steve Henson]
-
- *) Add protection against ECDSA timing attacks as mentioned in the paper
- by Billy Bob Brumley and Nicola Tuveri, see:
-
- http://eprint.iacr.org/2011/232.pdf
-
- [Billy Bob Brumley and Nicola Tuveri]
-
- Changes between 1.0.0c and 1.0.0d [8 Feb 2011]
-
- *) Fix parsing of OCSP stapling ClientHello extension. CVE-2011-0014
- [Neel Mehta, Adam Langley, Bodo Moeller (Google)]
-
- *) Fix bug in string printing code: if *any* escaping is enabled we must
- escape the escape character (backslash) or the resulting string is
- ambiguous.
- [Steve Henson]
-
- Changes between 1.0.0b and 1.0.0c [2 Dec 2010]
-
- *) Disable code workaround for ancient and obsolete Netscape browsers
- and servers: an attacker can use it in a ciphersuite downgrade attack.
- Thanks to Martin Rex for discovering this bug. CVE-2010-4180
- [Steve Henson]
-
- *) Fixed J-PAKE implementation error, originally discovered by
- Sebastien Martini, further info and confirmation from Stefan
- Arentz and Feng Hao. Note that this fix is a security fix. CVE-2010-4252
- [Ben Laurie]
-
- Changes between 1.0.0a and 1.0.0b [16 Nov 2010]
-
- *) Fix extension code to avoid race conditions which can result in a buffer
- overrun vulnerability: resumed sessions must not be modified as they can
- be shared by multiple threads. CVE-2010-3864
- [Steve Henson]
-
- *) Fix WIN32 build system to correctly link an ENGINE directory into
- a DLL.
- [Steve Henson]
-
- Changes between 1.0.0 and 1.0.0a [01 Jun 2010]
-
- *) Check return value of int_rsa_verify in pkey_rsa_verifyrecover
- (CVE-2010-1633)
- [Steve Henson, Peter-Michael Hager <hager@dortmund.net>]
-
- Changes between 0.9.8n and 1.0.0 [29 Mar 2010]
-
- *) Add "missing" function EVP_CIPHER_CTX_copy(). This copies a cipher
- context. The operation can be customised via the ctrl mechanism in
- case ENGINEs want to include additional functionality.
- [Steve Henson]
-
- *) Tolerate yet another broken PKCS#8 key format: private key value negative.
- [Steve Henson]
-
- *) Add new -subject_hash_old and -issuer_hash_old options to x509 utility to
- output hashes compatible with older versions of OpenSSL.
- [Willy Weisz <weisz@vcpc.univie.ac.at>]
-
- *) Fix compression algorithm handling: if resuming a session use the
- compression algorithm of the resumed session instead of determining
- it from client hello again. Don't allow server to change algorithm.
- [Steve Henson]
-
- *) Add load_crls() function to apps tidying load_certs() too. Add option
- to verify utility to allow additional CRLs to be included.
- [Steve Henson]
-
- *) Update OCSP request code to permit adding custom headers to the request:
- some responders need this.
- [Steve Henson]
-
- *) The function EVP_PKEY_sign() returns <=0 on error: check return code
- correctly.
- [Julia Lawall <julia@diku.dk>]
-
- *) Update verify callback code in apps/s_cb.c and apps/verify.c, it
- needlessly dereferenced structures, used obsolete functions and
- didn't handle all updated verify codes correctly.
- [Steve Henson]
-
- *) Disable MD2 in the default configuration.
- [Steve Henson]
-
- *) In BIO_pop() and BIO_push() use the ctrl argument (which was NULL) to
- indicate the initial BIO being pushed or popped. This makes it possible
- to determine whether the BIO is the one explicitly called or as a result
- of the ctrl being passed down the chain. Fix BIO_pop() and SSL BIOs so
- it handles reference counts correctly and doesn't zero out the I/O bio
- when it is not being explicitly popped. WARNING: applications which
- included workarounds for the old buggy behaviour will need to be modified
- or they could free up already freed BIOs.
- [Steve Henson]
-
- *) Extend the uni2asc/asc2uni => OPENSSL_uni2asc/OPENSSL_asc2uni
- renaming to all platforms (within the 0.9.8 branch, this was
- done conditionally on Netware platforms to avoid a name clash).
- [Guenter <lists@gknw.net>]
-
- *) Add ECDHE and PSK support to DTLS.
- [Michael Tuexen <tuexen@fh-muenster.de>]
-
- *) Add CHECKED_STACK_OF macro to safestack.h, otherwise safestack can't
- be used on C++.
- [Steve Henson]
-
- *) Add "missing" function EVP_MD_flags() (without this the only way to
- retrieve a digest flags is by accessing the structure directly. Update
- EVP_MD_do_all*() and EVP_CIPHER_do_all*() to include the name a digest
- or cipher is registered as in the "from" argument. Print out all
- registered digests in the dgst usage message instead of manually
- attempting to work them out.
- [Steve Henson]
-
- *) If no SSLv2 ciphers are used don't use an SSLv2 compatible client hello:
- this allows the use of compression and extensions. Change default cipher
- string to remove SSLv2 ciphersuites. This effectively avoids ancient SSLv2
- by default unless an application cipher string requests it.
- [Steve Henson]
-
- *) Alter match criteria in PKCS12_parse(). It used to try to use local
- key ids to find matching certificates and keys but some PKCS#12 files
- don't follow the (somewhat unwritten) rules and this strategy fails.
- Now just gather all certificates together and the first private key
- then look for the first certificate that matches the key.
- [Steve Henson]
-
- *) Support use of registered digest and cipher names for dgst and cipher
- commands instead of having to add each one as a special case. So now
- you can do:
-
- openssl sha256 foo
-
- as well as:
-
- openssl dgst -sha256 foo
-
- and this works for ENGINE based algorithms too.
-
- [Steve Henson]
-
- *) Update Gost ENGINE to support parameter files.
- [Victor B. Wagner <vitus@cryptocom.ru>]
-
- *) Support GeneralizedTime in ca utility.
- [Oliver Martin <oliver@volatilevoid.net>, Steve Henson]
-
- *) Enhance the hash format used for certificate directory links. The new
- form uses the canonical encoding (meaning equivalent names will work
- even if they aren't identical) and uses SHA1 instead of MD5. This form
- is incompatible with the older format and as a result c_rehash should
- be used to rebuild symbolic links.
- [Steve Henson]
-
- *) Make PKCS#8 the default write format for private keys, replacing the
- traditional format. This form is standardised, more secure and doesn't
- include an implicit MD5 dependency.
- [Steve Henson]
-
- *) Add a $gcc_devteam_warn option to Configure. The idea is that any code
- committed to OpenSSL should pass this lot as a minimum.
- [Steve Henson]
-
- *) Add session ticket override functionality for use by EAP-FAST.
- [Jouni Malinen <j@w1.fi>]
-
- *) Modify HMAC functions to return a value. Since these can be implemented
- in an ENGINE errors can occur.
- [Steve Henson]
-
- *) Type-checked OBJ_bsearch_ex.
- [Ben Laurie]
-
- *) Type-checked OBJ_bsearch. Also some constification necessitated
- by type-checking. Still to come: TXT_DB, bsearch(?),
- OBJ_bsearch_ex, qsort, CRYPTO_EX_DATA, ASN1_VALUE, ASN1_STRING,
- CONF_VALUE.
- [Ben Laurie]
-
- *) New function OPENSSL_gmtime_adj() to add a specific number of days and
- seconds to a tm structure directly, instead of going through OS
- specific date routines. This avoids any issues with OS routines such
- as the year 2038 bug. New *_adj() functions for ASN1 time structures
- and X509_time_adj_ex() to cover the extended range. The existing
- X509_time_adj() is still usable and will no longer have any date issues.
- [Steve Henson]
-
- *) Delta CRL support. New use deltas option which will attempt to locate
- and search any appropriate delta CRLs available.
-
- This work was sponsored by Google.
- [Steve Henson]
-
- *) Support for CRLs partitioned by reason code. Reorganise CRL processing
- code and add additional score elements. Validate alternate CRL paths
- as part of the CRL checking and indicate a new error "CRL path validation
- error" in this case. Applications wanting additional details can use
- the verify callback and check the new "parent" field. If this is not
- NULL CRL path validation is taking place. Existing applications won't
- see this because it requires extended CRL support which is off by
- default.
-
- This work was sponsored by Google.
- [Steve Henson]
-
- *) Support for freshest CRL extension.
-
- This work was sponsored by Google.
- [Steve Henson]
-
- *) Initial indirect CRL support. Currently only supported in the CRLs
- passed directly and not via lookup. Process certificate issuer
- CRL entry extension and lookup CRL entries by bother issuer name
- and serial number. Check and process CRL issuer entry in IDP extension.
-
- This work was sponsored by Google.
- [Steve Henson]
-
- *) Add support for distinct certificate and CRL paths. The CRL issuer
- certificate is validated separately in this case. Only enabled if
- an extended CRL support flag is set: this flag will enable additional
- CRL functionality in future.
-
- This work was sponsored by Google.
- [Steve Henson]
-
- *) Add support for policy mappings extension.
-
- This work was sponsored by Google.
- [Steve Henson]
-
- *) Fixes to pathlength constraint, self issued certificate handling,
- policy processing to align with RFC3280 and PKITS tests.
-
- This work was sponsored by Google.
- [Steve Henson]
-
- *) Support for name constraints certificate extension. DN, email, DNS
- and URI types are currently supported.
-
- This work was sponsored by Google.
- [Steve Henson]
-
- *) To cater for systems that provide a pointer-based thread ID rather
- than numeric, deprecate the current numeric thread ID mechanism and
- replace it with a structure and associated callback type. This
- mechanism allows a numeric "hash" to be extracted from a thread ID in
- either case, and on platforms where pointers are larger than 'long',
- mixing is done to help ensure the numeric 'hash' is usable even if it
- can't be guaranteed unique. The default mechanism is to use "&errno"
- as a pointer-based thread ID to distinguish between threads.
-
- Applications that want to provide their own thread IDs should now use
- CRYPTO_THREADID_set_callback() to register a callback that will call
- either CRYPTO_THREADID_set_numeric() or CRYPTO_THREADID_set_pointer().
-
- Note that ERR_remove_state() is now deprecated, because it is tied
- to the assumption that thread IDs are numeric. ERR_remove_state(0)
- to free the current thread's error state should be replaced by
- ERR_remove_thread_state(NULL).
-
- (This new approach replaces the functions CRYPTO_set_idptr_callback(),
- CRYPTO_get_idptr_callback(), and CRYPTO_thread_idptr() that existed in
- OpenSSL 0.9.9-dev between June 2006 and August 2008. Also, if an
- application was previously providing a numeric thread callback that
- was inappropriate for distinguishing threads, then uniqueness might
- have been obtained with &errno that happened immediately in the
- intermediate development versions of OpenSSL; this is no longer the
- case, the numeric thread callback will now override the automatic use
- of &errno.)
- [Geoff Thorpe, with help from Bodo Moeller]
-
- *) Initial support for different CRL issuing certificates. This covers a
- simple case where the self issued certificates in the chain exist and
- the real CRL issuer is higher in the existing chain.
-
- This work was sponsored by Google.
- [Steve Henson]
-
- *) Removed effectively defunct crypto/store from the build.
- [Ben Laurie]
-
- *) Revamp of STACK to provide stronger type-checking. Still to come:
- TXT_DB, bsearch(?), OBJ_bsearch, qsort, CRYPTO_EX_DATA, ASN1_VALUE,
- ASN1_STRING, CONF_VALUE.
- [Ben Laurie]
-
- *) Add a new SSL_MODE_RELEASE_BUFFERS mode flag to release unused buffer
- RAM on SSL connections. This option can save about 34k per idle SSL.
- [Nick Mathewson]
-
- *) Revamp of LHASH to provide stronger type-checking. Still to come:
- STACK, TXT_DB, bsearch, qsort.
- [Ben Laurie]
-
- *) Initial support for Cryptographic Message Syntax (aka CMS) based
- on RFC3850, RFC3851 and RFC3852. New cms directory and cms utility,
- support for data, signedData, compressedData, digestedData and
- encryptedData, envelopedData types included. Scripts to check against
- RFC4134 examples draft and interop and consistency checks of many
- content types and variants.
- [Steve Henson]
-
- *) Add options to enc utility to support use of zlib compression BIO.
- [Steve Henson]
-
- *) Extend mk1mf to support importing of options and assembly language
- files from Configure script, currently only included in VC-WIN32.
- The assembly language rules can now optionally generate the source
- files from the associated perl scripts.
- [Steve Henson]
-
- *) Implement remaining functionality needed to support GOST ciphersuites.
- Interop testing has been performed using CryptoPro implementations.
- [Victor B. Wagner <vitus@cryptocom.ru>]
-
- *) s390x assembler pack.
- [Andy Polyakov]
-
- *) ARMv4 assembler pack. ARMv4 refers to v4 and later ISA, not CPU
- "family."
- [Andy Polyakov]
-
- *) Implement Opaque PRF Input TLS extension as specified in
- draft-rescorla-tls-opaque-prf-input-00.txt. Since this is not an
- official specification yet and no extension type assignment by
- IANA exists, this extension (for now) will have to be explicitly
- enabled when building OpenSSL by providing the extension number
- to use. For example, specify an option
-
- -DTLSEXT_TYPE_opaque_prf_input=0x9527
-
- to the "config" or "Configure" script to enable the extension,
- assuming extension number 0x9527 (which is a completely arbitrary
- and unofficial assignment based on the MD5 hash of the Internet
- Draft). Note that by doing so, you potentially lose
- interoperability with other TLS implementations since these might
- be using the same extension number for other purposes.
-
- SSL_set_tlsext_opaque_prf_input(ssl, src, len) is used to set the
- opaque PRF input value to use in the handshake. This will create
- an internal copy of the length-'len' string at 'src', and will
- return non-zero for success.
-
- To get more control and flexibility, provide a callback function
- by using
-
- SSL_CTX_set_tlsext_opaque_prf_input_callback(ctx, cb)
- SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(ctx, arg)
-
- where
-
- int (*cb)(SSL *, void *peerinput, size_t len, void *arg);
- void *arg;
-
- Callback function 'cb' will be called in handshakes, and is
- expected to use SSL_set_tlsext_opaque_prf_input() as appropriate.
- Argument 'arg' is for application purposes (the value as given to
- SSL_CTX_set_tlsext_opaque_prf_input_callback_arg() will directly
- be provided to the callback function). The callback function
- has to return non-zero to report success: usually 1 to use opaque
- PRF input just if possible, or 2 to enforce use of the opaque PRF
- input. In the latter case, the library will abort the handshake
- if opaque PRF input is not successfully negotiated.
-
- Arguments 'peerinput' and 'len' given to the callback function
- will always be NULL and 0 in the case of a client. A server will
- see the client's opaque PRF input through these variables if
- available (NULL and 0 otherwise). Note that if the server
- provides an opaque PRF input, the length must be the same as the
- length of the client's opaque PRF input.
-
- Note that the callback function will only be called when creating
- a new session (session resumption can resume whatever was
- previously negotiated), and will not be called in SSL 2.0
- handshakes; thus, SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) or
- SSL_set_options(ssl, SSL_OP_NO_SSLv2) is especially recommended
- for applications that need to enforce opaque PRF input.
-
- [Bodo Moeller]
-
- *) Update ssl code to support digests other than SHA1+MD5 for handshake
- MAC.
-
- [Victor B. Wagner <vitus@cryptocom.ru>]
-
- *) Add RFC4507 support to OpenSSL. This includes the corrections in
- RFC4507bis. The encrypted ticket format is an encrypted encoded
- SSL_SESSION structure, that way new session features are automatically
- supported.
-
- If a client application caches session in an SSL_SESSION structure
- support is transparent because tickets are now stored in the encoded
- SSL_SESSION.
-
- The SSL_CTX structure automatically generates keys for ticket
- protection in servers so again support should be possible
- with no application modification.
-
- If a client or server wishes to disable RFC4507 support then the option
- SSL_OP_NO_TICKET can be set.
-
- Add a TLS extension debugging callback to allow the contents of any client
- or server extensions to be examined.
-
- This work was sponsored by Google.
- [Steve Henson]
-
- *) Final changes to avoid use of pointer pointer casts in OpenSSL.
- OpenSSL should now compile cleanly on gcc 4.2
- [Peter Hartley <pdh@utter.chaos.org.uk>, Steve Henson]
-
- *) Update SSL library to use new EVP_PKEY MAC API. Include generic MAC
- support including streaming MAC support: this is required for GOST
- ciphersuite support.
- [Victor B. Wagner <vitus@cryptocom.ru>, Steve Henson]
-
- *) Add option -stream to use PKCS#7 streaming in smime utility. New
- function i2d_PKCS7_bio_stream() and PEM_write_PKCS7_bio_stream()
- to output in BER and PEM format.
- [Steve Henson]
-
- *) Experimental support for use of HMAC via EVP_PKEY interface. This
- allows HMAC to be handled via the EVP_DigestSign*() interface. The
- EVP_PKEY "key" in this case is the HMAC key, potentially allowing
- ENGINE support for HMAC keys which are unextractable. New -mac and
- -macopt options to dgst utility.
- [Steve Henson]
-
- *) New option -sigopt to dgst utility. Update dgst to use
- EVP_Digest{Sign,Verify}*. These two changes make it possible to use
- alternative signing parameters such as X9.31 or PSS in the dgst
- utility.
- [Steve Henson]
-
- *) Change ssl_cipher_apply_rule(), the internal function that does
- the work each time a ciphersuite string requests enabling
- ("foo+bar"), moving ("+foo+bar"), disabling ("-foo+bar", or
- removing ("!foo+bar") a class of ciphersuites: Now it maintains
- the order of disabled ciphersuites such that those ciphersuites
- that most recently went from enabled to disabled not only stay
- in order with respect to each other, but also have higher priority
- than other disabled ciphersuites the next time ciphersuites are
- enabled again.
-
- This means that you can now say, e.g., "PSK:-PSK:HIGH" to enable
- the same ciphersuites as with "HIGH" alone, but in a specific
- order where the PSK ciphersuites come first (since they are the
- most recently disabled ciphersuites when "HIGH" is parsed).
-
- Also, change ssl_create_cipher_list() (using this new
- functionality) such that between otherwise identical
- ciphersuites, ephemeral ECDH is preferred over ephemeral DH in
- the default order.
- [Bodo Moeller]
-
- *) Change ssl_create_cipher_list() so that it automatically
- arranges the ciphersuites in reasonable order before starting
- to process the rule string. Thus, the definition for "DEFAULT"
- (SSL_DEFAULT_CIPHER_LIST) now is just "ALL:!aNULL:!eNULL", but
- remains equivalent to "AES:ALL:!aNULL:!eNULL:+aECDH:+kRSA:+RC4:@STRENGTH".
- This makes it much easier to arrive at a reasonable default order
- in applications for which anonymous ciphers are OK (meaning
- that you can't actually use DEFAULT).
- [Bodo Moeller; suggested by Victor Duchovni]
-
- *) Split the SSL/TLS algorithm mask (as used for ciphersuite string
- processing) into multiple integers instead of setting
- "SSL_MKEY_MASK" bits, "SSL_AUTH_MASK" bits, "SSL_ENC_MASK",
- "SSL_MAC_MASK", and "SSL_SSL_MASK" bits all in a single integer.
- (These masks as well as the individual bit definitions are hidden
- away into the non-exported interface ssl/ssl_locl.h, so this
- change to the definition of the SSL_CIPHER structure shouldn't
- affect applications.) This give us more bits for each of these
- categories, so there is no longer a need to coagulate AES128 and
- AES256 into a single algorithm bit, and to coagulate Camellia128
- and Camellia256 into a single algorithm bit, which has led to all
- kinds of kludges.
-
- Thus, among other things, the kludge introduced in 0.9.7m and
- 0.9.8e for masking out AES256 independently of AES128 or masking
- out Camellia256 independently of AES256 is not needed here in 0.9.9.
-
- With the change, we also introduce new ciphersuite aliases that
- so far were missing: "AES128", "AES256", "CAMELLIA128", and
- "CAMELLIA256".
- [Bodo Moeller]
-
- *) Add support for dsa-with-SHA224 and dsa-with-SHA256.
- Use the leftmost N bytes of the signature input if the input is
- larger than the prime q (with N being the size in bytes of q).
- [Nils Larsch]
-
- *) Very *very* experimental PKCS#7 streaming encoder support. Nothing uses
- it yet and it is largely untested.
- [Steve Henson]
-
- *) Add support for the ecdsa-with-SHA224/256/384/512 signature types.
- [Nils Larsch]
-
- *) Initial incomplete changes to avoid need for function casts in OpenSSL
- some compilers (gcc 4.2 and later) reject their use. Safestack is
- reimplemented. Update ASN1 to avoid use of legacy functions.
- [Steve Henson]
-
- *) Win32/64 targets are linked with Winsock2.
- [Andy Polyakov]
-
- *) Add an X509_CRL_METHOD structure to allow CRL processing to be redirected
- to external functions. This can be used to increase CRL handling
- efficiency especially when CRLs are very large by (for example) storing
- the CRL revoked certificates in a database.
- [Steve Henson]
-
- *) Overhaul of by_dir code. Add support for dynamic loading of CRLs so
- new CRLs added to a directory can be used. New command line option
- -verify_return_error to s_client and s_server. This causes real errors
- to be returned by the verify callback instead of carrying on no matter
- what. This reflects the way a "real world" verify callback would behave.
- [Steve Henson]
-
- *) GOST engine, supporting several GOST algorithms and public key formats.
- Kindly donated by Cryptocom.
- [Cryptocom]
-
- *) Partial support for Issuing Distribution Point CRL extension. CRLs
- partitioned by DP are handled but no indirect CRL or reason partitioning
- (yet). Complete overhaul of CRL handling: now the most suitable CRL is
- selected via a scoring technique which handles IDP and AKID in CRLs.
- [Steve Henson]
-
- *) New X509_STORE_CTX callbacks lookup_crls() and lookup_certs() which
- will ultimately be used for all verify operations: this will remove the
- X509_STORE dependency on certificate verification and allow alternative
- lookup methods. X509_STORE based implementations of these two callbacks.
- [Steve Henson]
-
- *) Allow multiple CRLs to exist in an X509_STORE with matching issuer names.
- Modify get_crl() to find a valid (unexpired) CRL if possible.
- [Steve Henson]
-
- *) New function X509_CRL_match() to check if two CRLs are identical. Normally
- this would be called X509_CRL_cmp() but that name is already used by
- a function that just compares CRL issuer names. Cache several CRL
- extensions in X509_CRL structure and cache CRLDP in X509.
- [Steve Henson]
-
- *) Store a "canonical" representation of X509_NAME structure (ASN1 Name)
- this maps equivalent X509_NAME structures into a consistent structure.
- Name comparison can then be performed rapidly using memcmp().
- [Steve Henson]
-
- *) Non-blocking OCSP request processing. Add -timeout option to ocsp
- utility.
- [Steve Henson]
-
- *) Allow digests to supply their own micalg string for S/MIME type using
- the ctrl EVP_MD_CTRL_MICALG.
- [Steve Henson]
-
- *) During PKCS7 signing pass the PKCS7 SignerInfo structure to the
- EVP_PKEY_METHOD before and after signing via the EVP_PKEY_CTRL_PKCS7_SIGN
- ctrl. It can then customise the structure before and/or after signing
- if necessary.
- [Steve Henson]
-
- *) New function OBJ_add_sigid() to allow application defined signature OIDs
- to be added to OpenSSLs internal tables. New function OBJ_sigid_free()
- to free up any added signature OIDs.
- [Steve Henson]
-
- *) New functions EVP_CIPHER_do_all(), EVP_CIPHER_do_all_sorted(),
- EVP_MD_do_all() and EVP_MD_do_all_sorted() to enumerate internal
- digest and cipher tables. New options added to openssl utility:
- list-message-digest-algorithms and list-cipher-algorithms.
- [Steve Henson]
-
- *) Change the array representation of binary polynomials: the list
- of degrees of non-zero coefficients is now terminated with -1.
- Previously it was terminated with 0, which was also part of the
- value; thus, the array representation was not applicable to
- polynomials where t^0 has coefficient zero. This change makes
- the array representation useful in a more general context.
- [Douglas Stebila]
-
- *) Various modifications and fixes to SSL/TLS cipher string
- handling. For ECC, the code now distinguishes between fixed ECDH
- with RSA certificates on the one hand and with ECDSA certificates
- on the other hand, since these are separate ciphersuites. The
- unused code for Fortezza ciphersuites has been removed.
-
- For consistency with EDH, ephemeral ECDH is now called "EECDH"
- (not "ECDHE"). For consistency with the code for DH
- certificates, use of ECDH certificates is now considered ECDH
- authentication, not RSA or ECDSA authentication (the latter is
- merely the CA's signing algorithm and not actively used in the
- protocol).
-
- The temporary ciphersuite alias "ECCdraft" is no longer
- available, and ECC ciphersuites are no longer excluded from "ALL"
- and "DEFAULT". The following aliases now exist for RFC 4492
- ciphersuites, most of these by analogy with the DH case:
-
- kECDHr - ECDH cert, signed with RSA
- kECDHe - ECDH cert, signed with ECDSA
- kECDH - ECDH cert (signed with either RSA or ECDSA)
- kEECDH - ephemeral ECDH
- ECDH - ECDH cert or ephemeral ECDH
-
- aECDH - ECDH cert
- aECDSA - ECDSA cert
- ECDSA - ECDSA cert
-
- AECDH - anonymous ECDH
- EECDH - non-anonymous ephemeral ECDH (equivalent to "kEECDH:-AECDH")
-
- [Bodo Moeller]
-
- *) Add additional S/MIME capabilities for AES and GOST ciphers if supported.
- Use correct micalg parameters depending on digest(s) in signed message.
- [Steve Henson]
-
- *) Add engine support for EVP_PKEY_ASN1_METHOD. Add functions to process
- an ENGINE asn1 method. Support ENGINE lookups in the ASN1 code.
- [Steve Henson]
-
- *) Initial engine support for EVP_PKEY_METHOD. New functions to permit
- an engine to register a method. Add ENGINE lookups for methods and
- functional reference processing.
- [Steve Henson]
-
- *) New functions EVP_Digest{Sign,Verify)*. These are enhanced versions of
- EVP_{Sign,Verify}* which allow an application to customise the signature
- process.
- [Steve Henson]
-
- *) New -resign option to smime utility. This adds one or more signers
- to an existing PKCS#7 signedData structure. Also -md option to use an
- alternative message digest algorithm for signing.
- [Steve Henson]
-
- *) Tidy up PKCS#7 routines and add new functions to make it easier to
- create PKCS7 structures containing multiple signers. Update smime
- application to support multiple signers.
- [Steve Henson]
-
- *) New -macalg option to pkcs12 utility to allow setting of an alternative
- digest MAC.
- [Steve Henson]
-
- *) Initial support for PKCS#5 v2.0 PRFs other than default SHA1 HMAC.
- Reorganize PBE internals to lookup from a static table using NIDs,
- add support for HMAC PBE OID translation. Add a EVP_CIPHER ctrl:
- EVP_CTRL_PBE_PRF_NID this allows a cipher to specify an alternative
- PRF which will be automatically used with PBES2.
- [Steve Henson]
-
- *) Replace the algorithm specific calls to generate keys in "req" with the
- new API.
- [Steve Henson]
-
- *) Update PKCS#7 enveloped data routines to use new API. This is now
- supported by any public key method supporting the encrypt operation. A
- ctrl is added to allow the public key algorithm to examine or modify
- the PKCS#7 RecipientInfo structure if it needs to: for RSA this is
- a no op.
- [Steve Henson]
-
- *) Add a ctrl to asn1 method to allow a public key algorithm to express
- a default digest type to use. In most cases this will be SHA1 but some
- algorithms (such as GOST) need to specify an alternative digest. The
- return value indicates how strong the preference is 1 means optional and
- 2 is mandatory (that is it is the only supported type). Modify
- ASN1_item_sign() to accept a NULL digest argument to indicate it should
- use the default md. Update openssl utilities to use the default digest
- type for signing if it is not explicitly indicated.
- [Steve Henson]
-
- *) Use OID cross reference table in ASN1_sign() and ASN1_verify(). New
- EVP_MD flag EVP_MD_FLAG_PKEY_METHOD_SIGNATURE. This uses the relevant
- signing method from the key type. This effectively removes the link
- between digests and public key types.
- [Steve Henson]
-
- *) Add an OID cross reference table and utility functions. Its purpose is to
- translate between signature OIDs such as SHA1WithrsaEncryption and SHA1,
- rsaEncryption. This will allow some of the algorithm specific hackery
- needed to use the correct OID to be removed.
- [Steve Henson]
-
- *) Remove algorithm specific dependencies when setting PKCS7_SIGNER_INFO
- structures for PKCS7_sign(). They are now set up by the relevant public
- key ASN1 method.
- [Steve Henson]
-
- *) Add provisional EC pkey method with support for ECDSA and ECDH.
- [Steve Henson]
-
- *) Add support for key derivation (agreement) in the API, DH method and
- pkeyutl.
- [Steve Henson]
-
- *) Add DSA pkey method and DH pkey methods, extend DH ASN1 method to support
- public and private key formats. As a side effect these add additional
- command line functionality not previously available: DSA signatures can be
- generated and verified using pkeyutl and DH key support and generation in
- pkey, genpkey.
- [Steve Henson]
-
- *) BeOS support.
- [Oliver Tappe <zooey@hirschkaefer.de>]
-
- *) New make target "install_html_docs" installs HTML renditions of the
- manual pages.
- [Oliver Tappe <zooey@hirschkaefer.de>]
-
- *) New utility "genpkey" this is analogous to "genrsa" etc except it can
- generate keys for any algorithm. Extend and update EVP_PKEY_METHOD to
- support key and parameter generation and add initial key generation
- functionality for RSA.
- [Steve Henson]
-
- *) Add functions for main EVP_PKEY_method operations. The undocumented
- functions EVP_PKEY_{encrypt,decrypt} have been renamed to
- EVP_PKEY_{encrypt,decrypt}_old.
- [Steve Henson]
-
- *) Initial definitions for EVP_PKEY_METHOD. This will be a high level public
- key API, doesn't do much yet.
- [Steve Henson]
-
- *) New function EVP_PKEY_asn1_get0_info() to retrieve information about
- public key algorithms. New option to openssl utility:
- "list-public-key-algorithms" to print out info.
- [Steve Henson]
-
- *) Implement the Supported Elliptic Curves Extension for
- ECC ciphersuites from draft-ietf-tls-ecc-12.txt.
- [Douglas Stebila]
-
- *) Don't free up OIDs in OBJ_cleanup() if they are in use by EVP_MD or
- EVP_CIPHER structures to avoid later problems in EVP_cleanup().
- [Steve Henson]
-
- *) New utilities pkey and pkeyparam. These are similar to algorithm specific
- utilities such as rsa, dsa, dsaparam etc except they process any key
- type.
- [Steve Henson]
-
- *) Transfer public key printing routines to EVP_PKEY_ASN1_METHOD. New
- functions EVP_PKEY_print_public(), EVP_PKEY_print_private(),
- EVP_PKEY_print_param() to print public key data from an EVP_PKEY
- structure.
- [Steve Henson]
-
- *) Initial support for pluggable public key ASN1.
- De-spaghettify the public key ASN1 handling. Move public and private
- key ASN1 handling to a new EVP_PKEY_ASN1_METHOD structure. Relocate
- algorithm specific handling to a single module within the relevant
- algorithm directory. Add functions to allow (near) opaque processing
- of public and private key structures.
- [Steve Henson]
-
- *) Implement the Supported Point Formats Extension for
- ECC ciphersuites from draft-ietf-tls-ecc-12.txt.
- [Douglas Stebila]
-
- *) Add initial support for RFC 4279 PSK TLS ciphersuites. Add members
- for the psk identity [hint] and the psk callback functions to the
- SSL_SESSION, SSL and SSL_CTX structure.
-
- New ciphersuites:
- PSK-RC4-SHA, PSK-3DES-EDE-CBC-SHA, PSK-AES128-CBC-SHA,
- PSK-AES256-CBC-SHA
-
- New functions:
- SSL_CTX_use_psk_identity_hint
- SSL_get_psk_identity_hint
- SSL_get_psk_identity
- SSL_use_psk_identity_hint
-
- [Mika Kousa and Pasi Eronen of Nokia Corporation]
-
- *) Add RFC 3161 compliant time stamp request creation, response generation
- and response verification functionality.
- [Zoltán Glózik <zglozik@opentsa.org>, The OpenTSA Project]
-
- *) Add initial support for TLS extensions, specifically for the server_name
- extension so far. The SSL_SESSION, SSL_CTX, and SSL data structures now
- have new members for a host name. The SSL data structure has an
- additional member SSL_CTX *initial_ctx so that new sessions can be
- stored in that context to allow for session resumption, even after the
- SSL has been switched to a new SSL_CTX in reaction to a client's
- server_name extension.
-
- New functions (subject to change):
-
- SSL_get_servername()
- SSL_get_servername_type()
- SSL_set_SSL_CTX()
-
- New CTRL codes and macros (subject to change):
-
- SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
- - SSL_CTX_set_tlsext_servername_callback()
- SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG
- - SSL_CTX_set_tlsext_servername_arg()
- SSL_CTRL_SET_TLSEXT_HOSTNAME - SSL_set_tlsext_host_name()
-
- openssl s_client has a new '-servername ...' option.
-
- openssl s_server has new options '-servername_host ...', '-cert2 ...',
- '-key2 ...', '-servername_fatal' (subject to change). This allows
- testing the HostName extension for a specific single host name ('-cert'
- and '-key' remain fallbacks for handshakes without HostName
- negotiation). If the unrecognized_name alert has to be sent, this by
- default is a warning; it becomes fatal with the '-servername_fatal'
- option.
-
- [Peter Sylvester, Remy Allais, Christophe Renou]
-
- *) Whirlpool hash implementation is added.
- [Andy Polyakov]
-
- *) BIGNUM code on 64-bit SPARCv9 targets is switched from bn(64,64) to
- bn(64,32). Because of instruction set limitations it doesn't have
- any negative impact on performance. This was done mostly in order
- to make it possible to share assembler modules, such as bn_mul_mont
- implementations, between 32- and 64-bit builds without hassle.
- [Andy Polyakov]
-
- *) Move code previously exiled into file crypto/ec/ec2_smpt.c
- to ec2_smpl.c, and no longer require the OPENSSL_EC_BIN_PT_COMP
- macro.
- [Bodo Moeller]
-
- *) New candidate for BIGNUM assembler implementation, bn_mul_mont,
- dedicated Montgomery multiplication procedure, is introduced.
- BN_MONT_CTX is modified to allow bn_mul_mont to reach for higher
- "64-bit" performance on certain 32-bit targets.
- [Andy Polyakov]
-
- *) New option SSL_OP_NO_COMP to disable use of compression selectively
- in SSL structures. New SSL ctrl to set maximum send fragment size.
- Save memory by setting the I/O buffer sizes dynamically instead of
- using the maximum available value.
- [Steve Henson]
-
- *) New option -V for 'openssl ciphers'. This prints the ciphersuite code
- in addition to the text details.
- [Bodo Moeller]
-
- *) Very, very preliminary EXPERIMENTAL support for printing of general
- ASN1 structures. This currently produces rather ugly output and doesn't
- handle several customised structures at all.
- [Steve Henson]
-
- *) Integrated support for PVK file format and some related formats such
- as MS PUBLICKEYBLOB and PRIVATEKEYBLOB. Command line switches to support
- these in the 'rsa' and 'dsa' utilities.
- [Steve Henson]
-
- *) Support for PKCS#1 RSAPublicKey format on rsa utility command line.
- [Steve Henson]
-
- *) Remove the ancient ASN1_METHOD code. This was only ever used in one
- place for the (very old) "NETSCAPE" format certificates which are now
- handled using new ASN1 code equivalents.
- [Steve Henson]
-
- *) Let the TLSv1_method() etc. functions return a 'const' SSL_METHOD
- pointer and make the SSL_METHOD parameter in SSL_CTX_new,
- SSL_CTX_set_ssl_version and SSL_set_ssl_method 'const'.
- [Nils Larsch]
-
- *) Modify CRL distribution points extension code to print out previously
- unsupported fields. Enhance extension setting code to allow setting of
- all fields.
- [Steve Henson]
-
- *) Add print and set support for Issuing Distribution Point CRL extension.
- [Steve Henson]
-
- *) Change 'Configure' script to enable Camellia by default.
- [NTT]
-
- Changes between 0.9.8m and 0.9.8n [24 Mar 2010]
-
- *) When rejecting SSL/TLS records due to an incorrect version number, never
- update s->server with a new major version number. As of
- - OpenSSL 0.9.8m if 'short' is a 16-bit type,
- - OpenSSL 0.9.8f if 'short' is longer than 16 bits,
- the previous behavior could result in a read attempt at NULL when
- receiving specific incorrect SSL/TLS records once record payload
- protection is active. (CVE-2010-0740)
- [Bodo Moeller, Adam Langley <agl@chromium.org>]
-
- *) Fix for CVE-2010-0433 where some kerberos enabled versions of OpenSSL
- could be crashed if the relevant tables were not present (e.g. chrooted).
- [Tomas Hoger <thoger@redhat.com>]
-
- Changes between 0.9.8l and 0.9.8m [25 Feb 2010]
-
- *) Always check bn_wexpand() return values for failure. (CVE-2009-3245)
- [Martin Olsson, Neel Mehta]
-
- *) Fix X509_STORE locking: Every 'objs' access requires a lock (to
- accommodate for stack sorting, always a write lock!).
- [Bodo Moeller]
-
- *) On some versions of WIN32 Heap32Next is very slow. This can cause
- excessive delays in the RAND_poll(): over a minute. As a workaround
- include a time check in the inner Heap32Next loop too.
- [Steve Henson]
-
- *) The code that handled flushing of data in SSL/TLS originally used the
- BIO_CTRL_INFO ctrl to see if any data was pending first. This caused
- the problem outlined in PR#1949. The fix suggested there however can
- trigger problems with buggy BIO_CTRL_WPENDING (e.g. some versions
- of Apache). So instead simplify the code to flush unconditionally.
- This should be fine since flushing with no data to flush is a no op.
- [Steve Henson]
-
- *) Handle TLS versions 2.0 and later properly and correctly use the
- highest version of TLS/SSL supported. Although TLS >= 2.0 is some way
- off ancient servers have a habit of sticking around for a while...
- [Steve Henson]
-
- *) Modify compression code so it frees up structures without using the
- ex_data callbacks. This works around a problem where some applications
- call CRYPTO_cleanup_all_ex_data() before application exit (e.g. when
- restarting) then use compression (e.g. SSL with compression) later.
- This results in significant per-connection memory leaks and
- has caused some security issues including CVE-2008-1678 and
- CVE-2009-4355.
- [Steve Henson]
-
- *) Constify crypto/cast (i.e., <openssl/cast.h>): a CAST_KEY doesn't
- change when encrypting or decrypting.
- [Bodo Moeller]
-
- *) Add option SSL_OP_LEGACY_SERVER_CONNECT which will allow clients to
- connect and renegotiate with servers which do not support RI.
- Until RI is more widely deployed this option is enabled by default.
- [Steve Henson]
-
- *) Add "missing" ssl ctrls to clear options and mode.
- [Steve Henson]
-
- *) If client attempts to renegotiate and doesn't support RI respond with
- a no_renegotiation alert as required by RFC5746. Some renegotiating
- TLS clients will continue a connection gracefully when they receive
- the alert. Unfortunately OpenSSL mishandled this alert and would hang
- waiting for a server hello which it will never receive. Now we treat a
- received no_renegotiation alert as a fatal error. This is because
- applications requesting a renegotiation might well expect it to succeed
- and would have no code in place to handle the server denying it so the
- only safe thing to do is to terminate the connection.
- [Steve Henson]
-
- *) Add ctrl macro SSL_get_secure_renegotiation_support() which returns 1 if
- peer supports secure renegotiation and 0 otherwise. Print out peer
- renegotiation support in s_client/s_server.
- [Steve Henson]
-
- *) Replace the highly broken and deprecated SPKAC certification method with
- the updated NID creation version. This should correctly handle UTF8.
- [Steve Henson]
-
- *) Implement RFC5746. Re-enable renegotiation but require the extension
- as needed. Unfortunately, SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
- turns out to be a bad idea. It has been replaced by
- SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION which can be set with
- SSL_CTX_set_options(). This is really not recommended unless you
- know what you are doing.
- [Eric Rescorla <ekr@networkresonance.com>, Ben Laurie, Steve Henson]
-
- *) Fixes to stateless session resumption handling. Use initial_ctx when
- issuing and attempting to decrypt tickets in case it has changed during
- servername handling. Use a non-zero length session ID when attempting
- stateless session resumption: this makes it possible to determine if
- a resumption has occurred immediately after receiving server hello
- (several places in OpenSSL subtly assume this) instead of later in
- the handshake.
- [Steve Henson]
-
- *) The functions ENGINE_ctrl(), OPENSSL_isservice(),
- CMS_get1_RecipientRequest() and RAND_bytes() can return <=0 on error
- fixes for a few places where the return code is not checked
- correctly.
- [Julia Lawall <julia@diku.dk>]
-
- *) Add --strict-warnings option to Configure script to include devteam
- warnings in other configurations.
- [Steve Henson]
-
- *) Add support for --libdir option and LIBDIR variable in makefiles. This
- makes it possible to install openssl libraries in locations which
- have names other than "lib", for example "/usr/lib64" which some
- systems need.
- [Steve Henson, based on patch from Jeremy Utley]
-
- *) Don't allow the use of leading 0x80 in OIDs. This is a violation of
- X690 8.9.12 and can produce some misleading textual output of OIDs.
- [Steve Henson, reported by Dan Kaminsky]
-
- *) Delete MD2 from algorithm tables. This follows the recommendation in
- several standards that it is not used in new applications due to
- several cryptographic weaknesses. For binary compatibility reasons
- the MD2 API is still compiled in by default.
- [Steve Henson]
-
- *) Add compression id to {d2i,i2d}_SSL_SESSION so it is correctly saved
- and restored.
- [Steve Henson]
-
- *) Rename uni2asc and asc2uni functions to OPENSSL_uni2asc and
- OPENSSL_asc2uni conditionally on Netware platforms to avoid a name
- clash.
- [Guenter <lists@gknw.net>]
-
- *) Fix the server certificate chain building code to use X509_verify_cert(),
- it used to have an ad-hoc builder which was unable to cope with anything
- other than a simple chain.
- [David Woodhouse <dwmw2@infradead.org>, Steve Henson]
-
- *) Don't check self signed certificate signatures in X509_verify_cert()
- by default (a flag can override this): it just wastes time without
- adding any security. As a useful side effect self signed root CAs
- with non-FIPS digests are now usable in FIPS mode.
- [Steve Henson]
-
- *) In dtls1_process_out_of_seq_message() the check if the current message
- is already buffered was missing. For every new message was memory
- allocated, allowing an attacker to perform an denial of service attack
- with sending out of seq handshake messages until there is no memory
- left. Additionally every future message was buffered, even if the
- sequence number made no sense and would be part of another handshake.
- So only messages with sequence numbers less than 10 in advance will be
- buffered. (CVE-2009-1378)
- [Robin Seggelmann, discovered by Daniel Mentz]
-
- *) Records are buffered if they arrive with a future epoch to be
- processed after finishing the corresponding handshake. There is
- currently no limitation to this buffer allowing an attacker to perform
- a DOS attack with sending records with future epochs until there is no
- memory left. This patch adds the pqueue_size() function to determine
- the size of a buffer and limits the record buffer to 100 entries.
- (CVE-2009-1377)
- [Robin Seggelmann, discovered by Daniel Mentz]
-
- *) Keep a copy of frag->msg_header.frag_len so it can be used after the
- parent structure is freed. (CVE-2009-1379)
- [Daniel Mentz]
-
- *) Handle non-blocking I/O properly in SSL_shutdown() call.
- [Darryl Miles <darryl-mailinglists@netbauds.net>]
-
- *) Add 2.5.4.* OIDs
- [Ilya O. <vrghost@gmail.com>]
-
- Changes between 0.9.8k and 0.9.8l [5 Nov 2009]
-
- *) Disable renegotiation completely - this fixes a severe security
- problem (CVE-2009-3555) at the cost of breaking all
- renegotiation. Renegotiation can be re-enabled by setting
- SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION in s3->flags at
- run-time. This is really not recommended unless you know what
- you're doing.
- [Ben Laurie]
-
- Changes between 0.9.8j and 0.9.8k [25 Mar 2009]
-
- *) Don't set val to NULL when freeing up structures, it is freed up by
- underlying code. If sizeof(void *) > sizeof(long) this can result in
- zeroing past the valid field. (CVE-2009-0789)
- [Paolo Ganci <Paolo.Ganci@AdNovum.CH>]
-
- *) Fix bug where return value of CMS_SignerInfo_verify_content() was not
- checked correctly. This would allow some invalid signed attributes to
- appear to verify correctly. (CVE-2009-0591)
- [Ivan Nestlerode <inestlerode@us.ibm.com>]
-
- *) Reject UniversalString and BMPString types with invalid lengths. This
- prevents a crash in ASN1_STRING_print_ex() which assumes the strings have
- a legal length. (CVE-2009-0590)
- [Steve Henson]
-
- *) Set S/MIME signing as the default purpose rather than setting it
- unconditionally. This allows applications to override it at the store
- level.
- [Steve Henson]
-
- *) Permit restricted recursion of ASN1 strings. This is needed in practice
- to handle some structures.
- [Steve Henson]
-
- *) Improve efficiency of mem_gets: don't search whole buffer each time
- for a '\n'
- [Jeremy Shapiro <jnshapir@us.ibm.com>]
-
- *) New -hex option for openssl rand.
- [Matthieu Herrb]
-
- *) Print out UTF8String and NumericString when parsing ASN1.
- [Steve Henson]
-
- *) Support NumericString type for name components.
- [Steve Henson]
-
- *) Allow CC in the environment to override the automatically chosen
- compiler. Note that nothing is done to ensure flags work with the
- chosen compiler.
- [Ben Laurie]
-
- Changes between 0.9.8i and 0.9.8j [07 Jan 2009]
-
- *) Properly check EVP_VerifyFinal() and similar return values
- (CVE-2008-5077).
- [Ben Laurie, Bodo Moeller, Google Security Team]
-
- *) Enable TLS extensions by default.
- [Ben Laurie]
-
- *) Allow the CHIL engine to be loaded, whether the application is
- multithreaded or not. (This does not release the developer from the
- obligation to set up the dynamic locking callbacks.)
- [Sander Temme <sander@temme.net>]
-
- *) Use correct exit code if there is an error in dgst command.
- [Steve Henson; problem pointed out by Roland Dirlewanger]
-
- *) Tweak Configure so that you need to say "experimental-jpake" to enable
- JPAKE, and need to use -DOPENSSL_EXPERIMENTAL_JPAKE in applications.
- [Bodo Moeller]
-
- *) Add experimental JPAKE support, including demo authentication in
- s_client and s_server.
- [Ben Laurie]
-
- *) Set the comparison function in v3_addr_canonize().
- [Rob Austein <sra@hactrn.net>]
-
- *) Add support for XMPP STARTTLS in s_client.
- [Philip Paeps <philip@freebsd.org>]
-
- *) Change the server-side SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG behavior
- to ensure that even with this option, only ciphersuites in the
- server's preference list will be accepted. (Note that the option
- applies only when resuming a session, so the earlier behavior was
- just about the algorithm choice for symmetric cryptography.)
- [Bodo Moeller]
-
- Changes between 0.9.8h and 0.9.8i [15 Sep 2008]
-
- *) Fix NULL pointer dereference if a DTLS server received
- ChangeCipherSpec as first record (CVE-2009-1386).
- [PR #1679]
-
- *) Fix a state transition in s3_srvr.c and d1_srvr.c
- (was using SSL3_ST_CW_CLNT_HELLO_B, should be ..._ST_SW_SRVR_...).
- [Nagendra Modadugu]
-
- *) The fix in 0.9.8c that supposedly got rid of unsafe
- double-checked locking was incomplete for RSA blinding,
- addressing just one layer of what turns out to have been
- doubly unsafe triple-checked locking.
-
- So now fix this for real by retiring the MONT_HELPER macro
- in crypto/rsa/rsa_eay.c.
-
- [Bodo Moeller; problem pointed out by Marius Schilder]
-
- *) Various precautionary measures:
-
- - Avoid size_t integer overflow in HASH_UPDATE (md32_common.h).
-
- - Avoid a buffer overflow in d2i_SSL_SESSION() (ssl_asn1.c).
- (NB: This would require knowledge of the secret session ticket key
- to exploit, in which case you'd be SOL either way.)
-
- - Change bn_nist.c so that it will properly handle input BIGNUMs
- outside the expected range.
-
- - Enforce the 'num' check in BN_div() (bn_div.c) for non-BN_DEBUG
- builds.
-
- [Neel Mehta, Bodo Moeller]
-
- *) Allow engines to be "soft loaded" - i.e. optionally don't die if
- the load fails. Useful for distros.
- [Ben Laurie and the FreeBSD team]
-
- *) Add support for Local Machine Keyset attribute in PKCS#12 files.
- [Steve Henson]
-
- *) Fix BN_GF2m_mod_arr() top-bit cleanup code.
- [Huang Ying]
-
- *) Expand ENGINE to support engine supplied SSL client certificate functions.
-
- This work was sponsored by Logica.
- [Steve Henson]
-
- *) Add CryptoAPI ENGINE to support use of RSA and DSA keys held in Windows
- keystores. Support for SSL/TLS client authentication too.
- Not compiled unless enable-capieng specified to Configure.
-
- This work was sponsored by Logica.
- [Steve Henson]
-
- *) Fix bug in X509_ATTRIBUTE creation: don't set attribute using
- ASN1_TYPE_set1 if MBSTRING flag set. This bug would crash certain
- attribute creation routines such as certificate requests and PKCS#12
- files.
- [Steve Henson]
-
- Changes between 0.9.8g and 0.9.8h [28 May 2008]
-
- *) Fix flaw if 'Server Key exchange message' is omitted from a TLS
- handshake which could lead to a client crash as found using the
- Codenomicon TLS test suite (CVE-2008-1672)
- [Steve Henson, Mark Cox]
-
- *) Fix double free in TLS server name extensions which could lead to
- a remote crash found by Codenomicon TLS test suite (CVE-2008-0891)
- [Joe Orton]
-
- *) Clear error queue in SSL_CTX_use_certificate_chain_file()
-
- Clear the error queue to ensure that error entries left from
- older function calls do not interfere with the correct operation.
- [Lutz Jaenicke, Erik de Castro Lopo]
-
- *) Remove root CA certificates of commercial CAs:
-
- The OpenSSL project does not recommend any specific CA and does not
- have any policy with respect to including or excluding any CA.
- Therefore it does not make any sense to ship an arbitrary selection
- of root CA certificates with the OpenSSL software.
- [Lutz Jaenicke]
-
- *) RSA OAEP patches to fix two separate invalid memory reads.
- The first one involves inputs when 'lzero' is greater than
- 'SHA_DIGEST_LENGTH' (it would read about SHA_DIGEST_LENGTH bytes
- before the beginning of from). The second one involves inputs where
- the 'db' section contains nothing but zeroes (there is a one-byte
- invalid read after the end of 'db').
- [Ivan Nestlerode <inestlerode@us.ibm.com>]
-
- *) Partial backport from 0.9.9-dev:
-
- Introduce bn_mul_mont (dedicated Montgomery multiplication
- procedure) as a candidate for BIGNUM assembler implementation.
- While 0.9.9-dev uses assembler for various architectures, only
- x86_64 is available by default here in the 0.9.8 branch, and
- 32-bit x86 is available through a compile-time setting.
-
- To try the 32-bit x86 assembler implementation, use Configure
- option "enable-montasm" (which exists only for this backport).
-
- As "enable-montasm" for 32-bit x86 disclaims code stability
- anyway, in this constellation we activate additional code
- backported from 0.9.9-dev for further performance improvements,
- namely BN_from_montgomery_word. (To enable this otherwise,
- e.g. x86_64, try "-DMONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD".)
-
- [Andy Polyakov (backport partially by Bodo Moeller)]
-
- *) Add TLS session ticket callback. This allows an application to set
- TLS ticket cipher and HMAC keys rather than relying on hardcoded fixed
- values. This is useful for key rollover for example where several key
- sets may exist with different names.
- [Steve Henson]
-
- *) Reverse ENGINE-internal logic for caching default ENGINE handles.
- This was broken until now in 0.9.8 releases, such that the only way
- a registered ENGINE could be used (assuming it initialises
- successfully on the host) was to explicitly set it as the default
- for the relevant algorithms. This is in contradiction with 0.9.7
- behaviour and the documentation. With this fix, when an ENGINE is
- registered into a given algorithm's table of implementations, the
- 'uptodate' flag is reset so that auto-discovery will be used next
- time a new context for that algorithm attempts to select an
- implementation.
- [Ian Lister (tweaked by Geoff Thorpe)]
-
- *) Backport of CMS code to OpenSSL 0.9.8. This differs from the 0.9.9
- implementation in the following ways:
-
- Lack of EVP_PKEY_ASN1_METHOD means algorithm parameters have to be
- hard coded.
-
- Lack of BER streaming support means one pass streaming processing is
- only supported if data is detached: setting the streaming flag is
- ignored for embedded content.
-
- CMS support is disabled by default and must be explicitly enabled
- with the enable-cms configuration option.
- [Steve Henson]
-
- *) Update the GMP engine glue to do direct copies between BIGNUM and
- mpz_t when openssl and GMP use the same limb size. Otherwise the
- existing "conversion via a text string export" trick is still used.
- [Paul Sheer <paulsheer@gmail.com>]
-
- *) Zlib compression BIO. This is a filter BIO which compressed and
- uncompresses any data passed through it.
- [Steve Henson]
-
- *) Add AES_wrap_key() and AES_unwrap_key() functions to implement
- RFC3394 compatible AES key wrapping.
- [Steve Henson]
-
- *) Add utility functions to handle ASN1 structures. ASN1_STRING_set0():
- sets string data without copying. X509_ALGOR_set0() and
- X509_ALGOR_get0(): set and retrieve X509_ALGOR (AlgorithmIdentifier)
- data. Attribute function X509at_get0_data_by_OBJ(): retrieves data
- from an X509_ATTRIBUTE structure optionally checking it occurs only
- once. ASN1_TYPE_set1(): set and ASN1_TYPE structure copying supplied
- data.
- [Steve Henson]
-
- *) Fix BN flag handling in RSA_eay_mod_exp() and BN_MONT_CTX_set()
- to get the expected BN_FLG_CONSTTIME behavior.
- [Bodo Moeller (Google)]
-
- *) Netware support:
-
- - fixed wrong usage of ioctlsocket() when build for LIBC BSD sockets
- - fixed do_tests.pl to run the test suite with CLIB builds too (CLIB_OPT)
- - added some more tests to do_tests.pl
- - fixed RunningProcess usage so that it works with newer LIBC NDKs too
- - removed usage of BN_LLONG for CLIB builds to avoid runtime dependency
- - added new Configure targets netware-clib-bsdsock, netware-clib-gcc,
- netware-clib-bsdsock-gcc, netware-libc-bsdsock-gcc
- - various changes to netware.pl to enable gcc-cross builds on Win32
- platform
- - changed crypto/bio/b_sock.c to work with macro functions (CLIB BSD)
- - various changes to fix missing prototype warnings
- - fixed x86nasm.pl to create correct asm files for NASM COFF output
- - added AES, WHIRLPOOL and CPUID assembler code to build files
- - added missing AES assembler make rules to mk1mf.pl
- - fixed order of includes in apps/ocsp.c so that e_os.h settings apply
- [Guenter Knauf <eflash@gmx.net>]
-
- *) Implement certificate status request TLS extension defined in RFC3546.
- A client can set the appropriate parameters and receive the encoded
- OCSP response via a callback. A server can query the supplied parameters
- and set the encoded OCSP response in the callback. Add simplified examples
- to s_client and s_server.
- [Steve Henson]
-
- Changes between 0.9.8f and 0.9.8g [19 Oct 2007]
-
- *) Fix various bugs:
- + Binary incompatibility of ssl_ctx_st structure
- + DTLS interoperation with non-compliant servers
- + Don't call get_session_cb() without proposed session
- + Fix ia64 assembler code
- [Andy Polyakov, Steve Henson]
-
- Changes between 0.9.8e and 0.9.8f [11 Oct 2007]
-
- *) DTLS Handshake overhaul. There were longstanding issues with
- OpenSSL DTLS implementation, which were making it impossible for
- RFC 4347 compliant client to communicate with OpenSSL server.
- Unfortunately just fixing these incompatibilities would "cut off"
- pre-0.9.8f clients. To allow for hassle free upgrade post-0.9.8e
- server keeps tolerating non RFC compliant syntax. The opposite is
- not true, 0.9.8f client can not communicate with earlier server.
- This update even addresses CVE-2007-4995.
- [Andy Polyakov]
-
- *) Changes to avoid need for function casts in OpenSSL: some compilers
- (gcc 4.2 and later) reject their use.
- [Kurt Roeckx <kurt@roeckx.be>, Peter Hartley <pdh@utter.chaos.org.uk>,
- Steve Henson]
-
- *) Add RFC4507 support to OpenSSL. This includes the corrections in
- RFC4507bis. The encrypted ticket format is an encrypted encoded
- SSL_SESSION structure, that way new session features are automatically
- supported.
-
- If a client application caches session in an SSL_SESSION structure
- support is transparent because tickets are now stored in the encoded
- SSL_SESSION.
-
- The SSL_CTX structure automatically generates keys for ticket
- protection in servers so again support should be possible
- with no application modification.
-
- If a client or server wishes to disable RFC4507 support then the option
- SSL_OP_NO_TICKET can be set.
-
- Add a TLS extension debugging callback to allow the contents of any client
- or server extensions to be examined.
-
- This work was sponsored by Google.
- [Steve Henson]
-
- *) Add initial support for TLS extensions, specifically for the server_name
- extension so far. The SSL_SESSION, SSL_CTX, and SSL data structures now
- have new members for a host name. The SSL data structure has an
- additional member SSL_CTX *initial_ctx so that new sessions can be
- stored in that context to allow for session resumption, even after the
- SSL has been switched to a new SSL_CTX in reaction to a client's
- server_name extension.
-
- New functions (subject to change):
-
- SSL_get_servername()
- SSL_get_servername_type()
- SSL_set_SSL_CTX()
-
- New CTRL codes and macros (subject to change):
-
- SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
- - SSL_CTX_set_tlsext_servername_callback()
- SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG
- - SSL_CTX_set_tlsext_servername_arg()
- SSL_CTRL_SET_TLSEXT_HOSTNAME - SSL_set_tlsext_host_name()
-
- openssl s_client has a new '-servername ...' option.
-
- openssl s_server has new options '-servername_host ...', '-cert2 ...',
- '-key2 ...', '-servername_fatal' (subject to change). This allows
- testing the HostName extension for a specific single host name ('-cert'
- and '-key' remain fallbacks for handshakes without HostName
- negotiation). If the unrecognized_name alert has to be sent, this by
- default is a warning; it becomes fatal with the '-servername_fatal'
- option.
-
- [Peter Sylvester, Remy Allais, Christophe Renou, Steve Henson]
-
- *) Add AES and SSE2 assembly language support to VC++ build.
- [Steve Henson]
-
- *) Mitigate attack on final subtraction in Montgomery reduction.
- [Andy Polyakov]
-
- *) Fix crypto/ec/ec_mult.c to work properly with scalars of value 0
- (which previously caused an internal error).
- [Bodo Moeller]
-
- *) Squeeze another 10% out of IGE mode when in != out.
- [Ben Laurie]
-
- *) AES IGE mode speedup.
- [Dean Gaudet (Google)]
-
- *) Add the Korean symmetric 128-bit cipher SEED (see
- http://www.kisa.or.kr/kisa/seed/jsp/seed_eng.jsp) and
- add SEED ciphersuites from RFC 4162:
-
- TLS_RSA_WITH_SEED_CBC_SHA = "SEED-SHA"
- TLS_DHE_DSS_WITH_SEED_CBC_SHA = "DHE-DSS-SEED-SHA"
- TLS_DHE_RSA_WITH_SEED_CBC_SHA = "DHE-RSA-SEED-SHA"
- TLS_DH_anon_WITH_SEED_CBC_SHA = "ADH-SEED-SHA"
-
- To minimize changes between patchlevels in the OpenSSL 0.9.8
- series, SEED remains excluded from compilation unless OpenSSL
- is configured with 'enable-seed'.
- [KISA, Bodo Moeller]
-
- *) Mitigate branch prediction attacks, which can be practical if a
- single processor is shared, allowing a spy process to extract
- information. For detailed background information, see
- http://eprint.iacr.org/2007/039 (O. Aciicmez, S. Gueron,
- J.-P. Seifert, "New Branch Prediction Vulnerabilities in OpenSSL
- and Necessary Software Countermeasures"). The core of the change
- are new versions BN_div_no_branch() and
- BN_mod_inverse_no_branch() of BN_div() and BN_mod_inverse(),
- respectively, which are slower, but avoid the security-relevant
- conditional branches. These are automatically called by BN_div()
- and BN_mod_inverse() if the flag BN_FLG_CONSTTIME is set for one
- of the input BIGNUMs. Also, BN_is_bit_set() has been changed to
- remove a conditional branch.
-
- BN_FLG_CONSTTIME is the new name for the previous
- BN_FLG_EXP_CONSTTIME flag, since it now affects more than just
- modular exponentiation. (Since OpenSSL 0.9.7h, setting this flag
- in the exponent causes BN_mod_exp_mont() to use the alternative
- implementation in BN_mod_exp_mont_consttime().) The old name
- remains as a deprecated alias.
-
- Similarly, RSA_FLAG_NO_EXP_CONSTTIME is replaced by a more general
- RSA_FLAG_NO_CONSTTIME flag since the RSA implementation now uses
- constant-time implementations for more than just exponentiation.
- Here too the old name is kept as a deprecated alias.
-
- BN_BLINDING_new() will now use BN_dup() for the modulus so that
- the BN_BLINDING structure gets an independent copy of the
- modulus. This means that the previous "BIGNUM *m" argument to
- BN_BLINDING_new() and to BN_BLINDING_create_param() now
- essentially becomes "const BIGNUM *m", although we can't actually
- change this in the header file before 0.9.9. It allows
- RSA_setup_blinding() to use BN_with_flags() on the modulus to
- enable BN_FLG_CONSTTIME.
-
- [Matthew D Wood (Intel Corp)]
-
- *) In the SSL/TLS server implementation, be strict about session ID
- context matching (which matters if an application uses a single
- external cache for different purposes). Previously,
- out-of-context reuse was forbidden only if SSL_VERIFY_PEER was
- set. This did ensure strict client verification, but meant that,
- with applications using a single external cache for quite
- different requirements, clients could circumvent ciphersuite
- restrictions for a given session ID context by starting a session
- in a different context.
- [Bodo Moeller]
-
- *) Include "!eNULL" in SSL_DEFAULT_CIPHER_LIST to make sure that
- a ciphersuite string such as "DEFAULT:RSA" cannot enable
- authentication-only ciphersuites.
- [Bodo Moeller]
-
- *) Update the SSL_get_shared_ciphers() fix CVE-2006-3738 which was
- not complete and could lead to a possible single byte overflow
- (CVE-2007-5135) [Ben Laurie]
-
- Changes between 0.9.8d and 0.9.8e [23 Feb 2007]
-
- *) Since AES128 and AES256 (and similarly Camellia128 and
- Camellia256) share a single mask bit in the logic of
- ssl/ssl_ciph.c, the code for masking out disabled ciphers needs a
- kludge to work properly if AES128 is available and AES256 isn't
- (or if Camellia128 is available and Camellia256 isn't).
- [Victor Duchovni]
-
- *) Fix the BIT STRING encoding generated by crypto/ec/ec_asn1.c
- (within i2d_ECPrivateKey, i2d_ECPKParameters, i2d_ECParameters):
- When a point or a seed is encoded in a BIT STRING, we need to
- prevent the removal of trailing zero bits to get the proper DER
- encoding. (By default, crypto/asn1/a_bitstr.c assumes the case
- of a NamedBitList, for which trailing 0 bits need to be removed.)
- [Bodo Moeller]
-
- *) Have SSL/TLS server implementation tolerate "mismatched" record
- protocol version while receiving ClientHello even if the
- ClientHello is fragmented. (The server can't insist on the
- particular protocol version it has chosen before the ServerHello
- message has informed the client about his choice.)
- [Bodo Moeller]
-
- *) Add RFC 3779 support.
- [Rob Austein for ARIN, Ben Laurie]
-
- *) Load error codes if they are not already present instead of using a
- static variable. This allows them to be cleanly unloaded and reloaded.
- Improve header file function name parsing.
- [Steve Henson]
-
- *) extend SMTP and IMAP protocol emulation in s_client to use EHLO
- or CAPABILITY handshake as required by RFCs.
- [Goetz Babin-Ebell]
-
- Changes between 0.9.8c and 0.9.8d [28 Sep 2006]
-
- *) Introduce limits to prevent malicious keys being able to
- cause a denial of service. (CVE-2006-2940)
- [Steve Henson, Bodo Moeller]
-
- *) Fix ASN.1 parsing of certain invalid structures that can result
- in a denial of service. (CVE-2006-2937) [Steve Henson]
-
- *) Fix buffer overflow in SSL_get_shared_ciphers() function.
- (CVE-2006-3738) [Tavis Ormandy and Will Drewry, Google Security Team]
-
- *) Fix SSL client code which could crash if connecting to a
- malicious SSLv2 server. (CVE-2006-4343)
- [Tavis Ormandy and Will Drewry, Google Security Team]
-
- *) Since 0.9.8b, ciphersuite strings naming explicit ciphersuites
- match only those. Before that, "AES256-SHA" would be interpreted
- as a pattern and match "AES128-SHA" too (since AES128-SHA got
- the same strength classification in 0.9.7h) as we currently only
- have a single AES bit in the ciphersuite description bitmap.
- That change, however, also applied to ciphersuite strings such as
- "RC4-MD5" that intentionally matched multiple ciphersuites --
- namely, SSL 2.0 ciphersuites in addition to the more common ones
- from SSL 3.0/TLS 1.0.
-
- So we change the selection algorithm again: Naming an explicit
- ciphersuite selects this one ciphersuite, and any other similar
- ciphersuite (same bitmap) from *other* protocol versions.
- Thus, "RC4-MD5" again will properly select both the SSL 2.0
- ciphersuite and the SSL 3.0/TLS 1.0 ciphersuite.
-
- Since SSL 2.0 does not have any ciphersuites for which the
- 128/256 bit distinction would be relevant, this works for now.
- The proper fix will be to use different bits for AES128 and
- AES256, which would have avoided the problems from the beginning;
- however, bits are scarce, so we can only do this in a new release
- (not just a patchlevel) when we can change the SSL_CIPHER
- definition to split the single 'unsigned long mask' bitmap into
- multiple values to extend the available space.
-
- [Bodo Moeller]
-
- Changes between 0.9.8b and 0.9.8c [05 Sep 2006]
-
- *) Avoid PKCS #1 v1.5 signature attack discovered by Daniel Bleichenbacher
- (CVE-2006-4339) [Ben Laurie and Google Security Team]
-
- *) Add AES IGE and biIGE modes.
- [Ben Laurie]
-
- *) Change the Unix randomness entropy gathering to use poll() when
- possible instead of select(), since the latter has some
- undesirable limitations.
- [Darryl Miles via Richard Levitte and Bodo Moeller]
-
- *) Disable "ECCdraft" ciphersuites more thoroughly. Now special
- treatment in ssl/ssl_ciph.s makes sure that these ciphersuites
- cannot be implicitly activated as part of, e.g., the "AES" alias.
- However, please upgrade to OpenSSL 0.9.9[-dev] for
- non-experimental use of the ECC ciphersuites to get TLS extension
- support, which is required for curve and point format negotiation
- to avoid potential handshake problems.
- [Bodo Moeller]
-
- *) Disable rogue ciphersuites:
-
- - SSLv2 0x08 0x00 0x80 ("RC4-64-MD5")
- - SSLv3/TLSv1 0x00 0x61 ("EXP1024-RC2-CBC-MD5")
- - SSLv3/TLSv1 0x00 0x60 ("EXP1024-RC4-MD5")
-
- The latter two were purportedly from
- draft-ietf-tls-56-bit-ciphersuites-0[01].txt, but do not really
- appear there.
-
- Also deactivate the remaining ciphersuites from
- draft-ietf-tls-56-bit-ciphersuites-01.txt. These are just as
- unofficial, and the ID has long expired.
- [Bodo Moeller]
-
- *) Fix RSA blinding Heisenbug (problems sometimes occurred on
- dual-core machines) and other potential thread-safety issues.
- [Bodo Moeller]
-
- *) Add the symmetric cipher Camellia (128-bit, 192-bit, 256-bit key
- versions), which is now available for royalty-free use
- (see http://info.isl.ntt.co.jp/crypt/eng/info/chiteki.html).
- Also, add Camellia TLS ciphersuites from RFC 4132.
-
- To minimize changes between patchlevels in the OpenSSL 0.9.8
- series, Camellia remains excluded from compilation unless OpenSSL
- is configured with 'enable-camellia'.
- [NTT]
-
- *) Disable the padding bug check when compression is in use. The padding
- bug check assumes the first packet is of even length, this is not
- necessarily true if compression is enabled and can result in false
- positives causing handshake failure. The actual bug test is ancient
- code so it is hoped that implementations will either have fixed it by
- now or any which still have the bug do not support compression.
- [Steve Henson]
-
- Changes between 0.9.8a and 0.9.8b [04 May 2006]
-
- *) When applying a cipher rule check to see if string match is an explicit
- cipher suite and only match that one cipher suite if it is.
- [Steve Henson]
-
- *) Link in manifests for VC++ if needed.
- [Austin Ziegler <halostatue@gmail.com>]
-
- *) Update support for ECC-based TLS ciphersuites according to
- draft-ietf-tls-ecc-12.txt with proposed changes (but without
- TLS extensions, which are supported starting with the 0.9.9
- branch, not in the OpenSSL 0.9.8 branch).
- [Douglas Stebila]
-
- *) New functions EVP_CIPHER_CTX_new() and EVP_CIPHER_CTX_free() to support
- opaque EVP_CIPHER_CTX handling.
- [Steve Henson]
-
- *) Fixes and enhancements to zlib compression code. We now only use
- "zlib1.dll" and use the default __cdecl calling convention on Win32
- to conform with the standards mentioned here:
- http://www.zlib.net/DLL_FAQ.txt
- Static zlib linking now works on Windows and the new --with-zlib-include
- --with-zlib-lib options to Configure can be used to supply the location
- of the headers and library. Gracefully handle case where zlib library
- can't be loaded.
- [Steve Henson]
-
- *) Several fixes and enhancements to the OID generation code. The old code
- sometimes allowed invalid OIDs (1.X for X >= 40 for example), couldn't
- handle numbers larger than ULONG_MAX, truncated printing and had a
- non standard OBJ_obj2txt() behaviour.
- [Steve Henson]
-
- *) Add support for building of engines under engine/ as shared libraries
- under VC++ build system.
- [Steve Henson]
-
- *) Corrected the numerous bugs in the Win32 path splitter in DSO.
- Hopefully, we will not see any false combination of paths any more.
- [Richard Levitte]
-
- Changes between 0.9.8 and 0.9.8a [11 Oct 2005]
-
- *) Remove the functionality of SSL_OP_MSIE_SSLV2_RSA_PADDING
- (part of SSL_OP_ALL). This option used to disable the
- countermeasure against man-in-the-middle protocol-version
- rollback in the SSL 2.0 server implementation, which is a bad
- idea. (CVE-2005-2969)
-
- [Bodo Moeller; problem pointed out by Yutaka Oiwa (Research Center
- for Information Security, National Institute of Advanced Industrial
- Science and Technology [AIST], Japan)]
-
- *) Add two function to clear and return the verify parameter flags.
- [Steve Henson]
-
- *) Keep cipherlists sorted in the source instead of sorting them at
- runtime, thus removing the need for a lock.
- [Nils Larsch]
-
- *) Avoid some small subgroup attacks in Diffie-Hellman.
- [Nick Mathewson and Ben Laurie]
-
- *) Add functions for well-known primes.
- [Nick Mathewson]
-
- *) Extended Windows CE support.
- [Satoshi Nakamura and Andy Polyakov]
-
- *) Initialize SSL_METHOD structures at compile time instead of during
- runtime, thus removing the need for a lock.
- [Steve Henson]
-
- *) Make PKCS7_decrypt() work even if no certificate is supplied by
- attempting to decrypt each encrypted key in turn. Add support to
- smime utility.
- [Steve Henson]
-
- Changes between 0.9.7h and 0.9.8 [05 Jul 2005]
-
- [NB: OpenSSL 0.9.7i and later 0.9.7 patch levels were released after
- OpenSSL 0.9.8.]
-
- *) Add libcrypto.pc and libssl.pc for those who feel they need them.
- [Richard Levitte]
-
- *) Change CA.sh and CA.pl so they don't bundle the CSR and the private
- key into the same file any more.
- [Richard Levitte]
-
- *) Add initial support for Win64, both IA64 and AMD64/x64 flavors.
- [Andy Polyakov]
-
- *) Add -utf8 command line and config file option to 'ca'.
- [Stefan <stf@udoma.org]
-
- *) Removed the macro des_crypt(), as it seems to conflict with some
- libraries. Use DES_crypt().
- [Richard Levitte]
-
- *) Correct naming of the 'chil' and '4758cca' ENGINEs. This
- involves renaming the source and generated shared-libs for
- both. The engines will accept the corrected or legacy ids
- ('ncipher' and '4758_cca' respectively) when binding. NB,
- this only applies when building 'shared'.
- [Corinna Vinschen <vinschen@redhat.com> and Geoff Thorpe]
-
- *) Add attribute functions to EVP_PKEY structure. Modify
- PKCS12_create() to recognize a CSP name attribute and
- use it. Make -CSP option work again in pkcs12 utility.
- [Steve Henson]
-
- *) Add new functionality to the bn blinding code:
- - automatic re-creation of the BN_BLINDING parameters after
- a fixed number of uses (currently 32)
- - add new function for parameter creation
- - introduce flags to control the update behaviour of the
- BN_BLINDING parameters
- - hide BN_BLINDING structure
- Add a second BN_BLINDING slot to the RSA structure to improve
- performance when a single RSA object is shared among several
- threads.
- [Nils Larsch]
-
- *) Add support for DTLS.
- [Nagendra Modadugu <nagendra@cs.stanford.edu> and Ben Laurie]
-
- *) Add support for DER encoded private keys (SSL_FILETYPE_ASN1)
- to SSL_CTX_use_PrivateKey_file() and SSL_use_PrivateKey_file()
- [Walter Goulet]
-
- *) Remove buggy and incomplete DH cert support from
- ssl/ssl_rsa.c and ssl/s3_both.c
- [Nils Larsch]
-
- *) Use SHA-1 instead of MD5 as the default digest algorithm for
- the apps/openssl applications.
- [Nils Larsch]
-
- *) Compile clean with "-Wall -Wmissing-prototypes
- -Wstrict-prototypes -Wmissing-declarations -Werror". Currently
- DEBUG_SAFESTACK must also be set.
- [Ben Laurie]
-
- *) Change ./Configure so that certain algorithms can be disabled by default.
- The new counterpiece to "no-xxx" is "enable-xxx".
-
- The patented RC5 and MDC2 algorithms will now be disabled unless
- "enable-rc5" and "enable-mdc2", respectively, are specified.
-
- (IDEA remains enabled despite being patented. This is because IDEA
- is frequently required for interoperability, and there is no license
- fee for non-commercial use. As before, "no-idea" can be used to
- avoid this algorithm.)
-
- [Bodo Moeller]
-
- *) Add processing of proxy certificates (see RFC 3820). This work was
- sponsored by KTH (The Royal Institute of Technology in Stockholm) and
- EGEE (Enabling Grids for E-science in Europe).
- [Richard Levitte]
-
- *) RC4 performance overhaul on modern architectures/implementations, such
- as Intel P4, IA-64 and AMD64.
- [Andy Polyakov]
-
- *) New utility extract-section.pl. This can be used specify an alternative
- section number in a pod file instead of having to treat each file as
- a separate case in Makefile. This can be done by adding two lines to the
- pod file:
-
- =for comment openssl_section:XXX
-
- The blank line is mandatory.
-
- [Steve Henson]
-
- *) New arguments -certform, -keyform and -pass for s_client and s_server
- to allow alternative format key and certificate files and passphrase
- sources.
- [Steve Henson]
-
- *) New structure X509_VERIFY_PARAM which combines current verify parameters,
- update associated structures and add various utility functions.
-
- Add new policy related verify parameters, include policy checking in
- standard verify code. Enhance 'smime' application with extra parameters
- to support policy checking and print out.
- [Steve Henson]
-
- *) Add a new engine to support VIA PadLock ACE extensions in the VIA C3
- Nehemiah processors. These extensions support AES encryption in hardware
- as well as RNG (though RNG support is currently disabled).
- [Michal Ludvig <michal@logix.cz>, with help from Andy Polyakov]
-
- *) Deprecate BN_[get|set]_params() functions (they were ignored internally).
- [Geoff Thorpe]
-
- *) New FIPS 180-2 algorithms, SHA-224/-256/-384/-512 are implemented.
- [Andy Polyakov and a number of other people]
-
- *) Improved PowerPC platform support. Most notably BIGNUM assembler
- implementation contributed by IBM.
- [Suresh Chari, Peter Waltenberg, Andy Polyakov]
-
- *) The new 'RSA_generate_key_ex' function now takes a BIGNUM for the public
- exponent rather than 'unsigned long'. There is a corresponding change to
- the new 'rsa_keygen' element of the RSA_METHOD structure.
- [Jelte Jansen, Geoff Thorpe]
-
- *) Functionality for creating the initial serial number file is now
- moved from CA.pl to the 'ca' utility with a new option -create_serial.
-
- (Before OpenSSL 0.9.7e, CA.pl used to initialize the serial
- number file to 1, which is bound to cause problems. To avoid
- the problems while respecting compatibility between different 0.9.7
- patchlevels, 0.9.7e employed 'openssl x509 -next_serial' in
- CA.pl for serial number initialization. With the new release 0.9.8,
- we can fix the problem directly in the 'ca' utility.)
- [Steve Henson]
-
- *) Reduced header interdependencies by declaring more opaque objects in
- ossl_typ.h. As a consequence, including some headers (eg. engine.h) will
- give fewer recursive includes, which could break lazy source code - so
- this change is covered by the OPENSSL_NO_DEPRECATED symbol. As always,
- developers should define this symbol when building and using openssl to
- ensure they track the recommended behaviour, interfaces, [etc], but
- backwards-compatible behaviour prevails when this isn't defined.
- [Geoff Thorpe]
-
- *) New function X509_POLICY_NODE_print() which prints out policy nodes.
- [Steve Henson]
-
- *) Add new EVP function EVP_CIPHER_CTX_rand_key and associated functionality.
- This will generate a random key of the appropriate length based on the
- cipher context. The EVP_CIPHER can provide its own random key generation
- routine to support keys of a specific form. This is used in the des and
- 3des routines to generate a key of the correct parity. Update S/MIME
- code to use new functions and hence generate correct parity DES keys.
- Add EVP_CHECK_DES_KEY #define to return an error if the key is not
- valid (weak or incorrect parity).
- [Steve Henson]
-
- *) Add a local set of CRLs that can be used by X509_verify_cert() as well
- as looking them up. This is useful when the verified structure may contain
- CRLs, for example PKCS#7 signedData. Modify PKCS7_verify() to use any CRLs
- present unless the new PKCS7_NO_CRL flag is asserted.
- [Steve Henson]
-
- *) Extend ASN1 oid configuration module. It now additionally accepts the
- syntax:
-
- shortName = some long name, 1.2.3.4
- [Steve Henson]
-
- *) Reimplemented the BN_CTX implementation. There is now no more static
- limitation on the number of variables it can handle nor the depth of the
- "stack" handling for BN_CTX_start()/BN_CTX_end() pairs. The stack
- information can now expand as required, and rather than having a single
- static array of bignums, BN_CTX now uses a linked-list of such arrays
- allowing it to expand on demand whilst maintaining the usefulness of
- BN_CTX's "bundling".
- [Geoff Thorpe]
-
- *) Add a missing BN_CTX parameter to the 'rsa_mod_exp' callback in RSA_METHOD
- to allow all RSA operations to function using a single BN_CTX.
- [Geoff Thorpe]
-
- *) Preliminary support for certificate policy evaluation and checking. This
- is initially intended to pass the tests outlined in "Conformance Testing
- of Relying Party Client Certificate Path Processing Logic" v1.07.
- [Steve Henson]
-
- *) bn_dup_expand() has been deprecated, it was introduced in 0.9.7 and
- remained unused and not that useful. A variety of other little bignum
- tweaks and fixes have also been made continuing on from the audit (see
- below).
- [Geoff Thorpe]
-
- *) Constify all or almost all d2i, c2i, s2i and r2i functions, along with
- associated ASN1, EVP and SSL functions and old ASN1 macros.
- [Richard Levitte]
-
- *) BN_zero() only needs to set 'top' and 'neg' to zero for correct results,
- and this should never fail. So the return value from the use of
- BN_set_word() (which can fail due to needless expansion) is now deprecated;
- if OPENSSL_NO_DEPRECATED is defined, BN_zero() is a void macro.
- [Geoff Thorpe]
-
- *) BN_CTX_get() should return zero-valued bignums, providing the same
- initialised value as BN_new().
- [Geoff Thorpe, suggested by Ulf Möller]
-
- *) Support for inhibitAnyPolicy certificate extension.
- [Steve Henson]
-
- *) An audit of the BIGNUM code is underway, for which debugging code is
- enabled when BN_DEBUG is defined. This makes stricter enforcements on what
- is considered valid when processing BIGNUMs, and causes execution to
- assert() when a problem is discovered. If BN_DEBUG_RAND is defined,
- further steps are taken to deliberately pollute unused data in BIGNUM
- structures to try and expose faulty code further on. For now, openssl will
- (in its default mode of operation) continue to tolerate the inconsistent
- forms that it has tolerated in the past, but authors and packagers should
- consider trying openssl and their own applications when compiled with
- these debugging symbols defined. It will help highlight potential bugs in
- their own code, and will improve the test coverage for OpenSSL itself. At
- some point, these tighter rules will become openssl's default to improve
- maintainability, though the assert()s and other overheads will remain only
- in debugging configurations. See bn.h for more details.
- [Geoff Thorpe, Nils Larsch, Ulf Möller]
-
- *) BN_CTX_init() has been deprecated, as BN_CTX is an opaque structure
- that can only be obtained through BN_CTX_new() (which implicitly
- initialises it). The presence of this function only made it possible
- to overwrite an existing structure (and cause memory leaks).
- [Geoff Thorpe]
-
- *) Because of the callback-based approach for implementing LHASH as a
- template type, lh_insert() adds opaque objects to hash-tables and
- lh_doall() or lh_doall_arg() are typically used with a destructor callback
- to clean up those corresponding objects before destroying the hash table
- (and losing the object pointers). So some over-zealous constifications in
- LHASH have been relaxed so that lh_insert() does not take (nor store) the
- objects as "const" and the lh_doall[_arg] callback wrappers are not
- prototyped to have "const" restrictions on the object pointers they are
- given (and so aren't required to cast them away any more).
- [Geoff Thorpe]
-
- *) The tmdiff.h API was so ugly and minimal that our own timing utility
- (speed) prefers to use its own implementation. The two implementations
- haven't been consolidated as yet (volunteers?) but the tmdiff API has had
- its object type properly exposed (MS_TM) instead of casting to/from "char
- *". This may still change yet if someone realises MS_TM and "ms_time_***"
- aren't necessarily the greatest nomenclatures - but this is what was used
- internally to the implementation so I've used that for now.
- [Geoff Thorpe]
-
- *) Ensure that deprecated functions do not get compiled when
- OPENSSL_NO_DEPRECATED is defined. Some "openssl" subcommands and a few of
- the self-tests were still using deprecated key-generation functions so
- these have been updated also.
- [Geoff Thorpe]
-
- *) Reorganise PKCS#7 code to separate the digest location functionality
- into PKCS7_find_digest(), digest addition into PKCS7_bio_add_digest().
- New function PKCS7_set_digest() to set the digest type for PKCS#7
- digestedData type. Add additional code to correctly generate the
- digestedData type and add support for this type in PKCS7 initialization
- functions.
- [Steve Henson]
-
- *) New function PKCS7_set0_type_other() this initializes a PKCS7
- structure of type "other".
- [Steve Henson]
-
- *) Fix prime generation loop in crypto/bn/bn_prime.pl by making
- sure the loop does correctly stop and breaking ("division by zero")
- modulus operations are not performed. The (pre-generated) prime
- table crypto/bn/bn_prime.h was already correct, but it could not be
- re-generated on some platforms because of the "division by zero"
- situation in the script.
- [Ralf S. Engelschall]
-
- *) Update support for ECC-based TLS ciphersuites according to
- draft-ietf-tls-ecc-03.txt: the KDF1 key derivation function with
- SHA-1 now is only used for "small" curves (where the
- representation of a field element takes up to 24 bytes); for
- larger curves, the field element resulting from ECDH is directly
- used as premaster secret.
- [Douglas Stebila (Sun Microsystems Laboratories)]
-
- *) Add code for kP+lQ timings to crypto/ec/ectest.c, and add SEC2
- curve secp160r1 to the tests.
- [Douglas Stebila (Sun Microsystems Laboratories)]
-
- *) Add the possibility to load symbols globally with DSO.
- [Götz Babin-Ebell <babin-ebell@trustcenter.de> via Richard Levitte]
-
- *) Add the functions ERR_set_mark() and ERR_pop_to_mark() for better
- control of the error stack.
- [Richard Levitte]
-
- *) Add support for STORE in ENGINE.
- [Richard Levitte]
-
- *) Add the STORE type. The intention is to provide a common interface
- to certificate and key stores, be they simple file-based stores, or
- HSM-type store, or LDAP stores, or...
- NOTE: The code is currently UNTESTED and isn't really used anywhere.
- [Richard Levitte]
-
- *) Add a generic structure called OPENSSL_ITEM. This can be used to
- pass a list of arguments to any function as well as provide a way
- for a function to pass data back to the caller.
- [Richard Levitte]
-
- *) Add the functions BUF_strndup() and BUF_memdup(). BUF_strndup()
- works like BUF_strdup() but can be used to duplicate a portion of
- a string. The copy gets NUL-terminated. BUF_memdup() duplicates
- a memory area.
- [Richard Levitte]
-
- *) Add the function sk_find_ex() which works like sk_find(), but will
- return an index to an element even if an exact match couldn't be
- found. The index is guaranteed to point at the element where the
- searched-for key would be inserted to preserve sorting order.
- [Richard Levitte]
-
- *) Add the function OBJ_bsearch_ex() which works like OBJ_bsearch() but
- takes an extra flags argument for optional functionality. Currently,
- the following flags are defined:
-
- OBJ_BSEARCH_VALUE_ON_NOMATCH
- This one gets OBJ_bsearch_ex() to return a pointer to the first
- element where the comparing function returns a negative or zero
- number.
-
- OBJ_BSEARCH_FIRST_VALUE_ON_MATCH
- This one gets OBJ_bsearch_ex() to return a pointer to the first
- element where the comparing function returns zero. This is useful
- if there are more than one element where the comparing function
- returns zero.
- [Richard Levitte]
-
- *) Make it possible to create self-signed certificates with 'openssl ca'
- in such a way that the self-signed certificate becomes part of the
- CA database and uses the same mechanisms for serial number generation
- as all other certificate signing. The new flag '-selfsign' enables
- this functionality. Adapt CA.sh and CA.pl.in.
- [Richard Levitte]
-
- *) Add functionality to check the public key of a certificate request
- against a given private. This is useful to check that a certificate
- request can be signed by that key (self-signing).
- [Richard Levitte]
-
- *) Make it possible to have multiple active certificates with the same
- subject in the CA index file. This is done only if the keyword
- 'unique_subject' is set to 'no' in the main CA section (default
- if 'CA_default') of the configuration file. The value is saved
- with the database itself in a separate index attribute file,
- named like the index file with '.attr' appended to the name.
- [Richard Levitte]
-
- *) Generate multi-valued AVAs using '+' notation in config files for
- req and dirName.
- [Steve Henson]
-
- *) Support for nameConstraints certificate extension.
- [Steve Henson]
-
- *) Support for policyConstraints certificate extension.
- [Steve Henson]
-
- *) Support for policyMappings certificate extension.
- [Steve Henson]
-
- *) Make sure the default DSA_METHOD implementation only uses its
- dsa_mod_exp() and/or bn_mod_exp() handlers if they are non-NULL,
- and change its own handlers to be NULL so as to remove unnecessary
- indirection. This lets alternative implementations fallback to the
- default implementation more easily.
- [Geoff Thorpe]
-
- *) Support for directoryName in GeneralName related extensions
- in config files.
- [Steve Henson]
-
- *) Make it possible to link applications using Makefile.shared.
- Make that possible even when linking against static libraries!
- [Richard Levitte]
-
- *) Support for single pass processing for S/MIME signing. This now
- means that S/MIME signing can be done from a pipe, in addition
- cleartext signing (multipart/signed type) is effectively streaming
- and the signed data does not need to be all held in memory.
-
- This is done with a new flag PKCS7_STREAM. When this flag is set
- PKCS7_sign() only initializes the PKCS7 structure and the actual signing
- is done after the data is output (and digests calculated) in
- SMIME_write_PKCS7().
- [Steve Henson]
-
- *) Add full support for -rpath/-R, both in shared libraries and
- applications, at least on the platforms where it's known how
- to do it.
- [Richard Levitte]
-
- *) In crypto/ec/ec_mult.c, implement fast point multiplication with
- precomputation, based on wNAF splitting: EC_GROUP_precompute_mult()
- will now compute a table of multiples of the generator that
- makes subsequent invocations of EC_POINTs_mul() or EC_POINT_mul()
- faster (notably in the case of a single point multiplication,
- scalar * generator).
- [Nils Larsch, Bodo Moeller]
-
- *) IPv6 support for certificate extensions. The various extensions
- which use the IP:a.b.c.d can now take IPv6 addresses using the
- formats of RFC1884 2.2 . IPv6 addresses are now also displayed
- correctly.
- [Steve Henson]
-
- *) Added an ENGINE that implements RSA by performing private key
- exponentiations with the GMP library. The conversions to and from
- GMP's mpz_t format aren't optimised nor are any montgomery forms
- cached, and on x86 it appears OpenSSL's own performance has caught up.
- However there are likely to be other architectures where GMP could
- provide a boost. This ENGINE is not built in by default, but it can be
- specified at Configure time and should be accompanied by the necessary
- linker additions, eg;
- ./config -DOPENSSL_USE_GMP -lgmp
- [Geoff Thorpe]
-
- *) "openssl engine" will not display ENGINE/DSO load failure errors when
- testing availability of engines with "-t" - the old behaviour is
- produced by increasing the feature's verbosity with "-tt".
- [Geoff Thorpe]
-
- *) ECDSA routines: under certain error conditions uninitialized BN objects
- could be freed. Solution: make sure initialization is performed early
- enough. (Reported and fix supplied by Nils Larsch <nla@trustcenter.de>
- via PR#459)
- [Lutz Jaenicke]
-
- *) Key-generation can now be implemented in RSA_METHOD, DSA_METHOD
- and DH_METHOD (eg. by ENGINE implementations) to override the normal
- software implementations. For DSA and DH, parameter generation can
- also be overridden by providing the appropriate method callbacks.
- [Geoff Thorpe]
-
- *) Change the "progress" mechanism used in key-generation and
- primality testing to functions that take a new BN_GENCB pointer in
- place of callback/argument pairs. The new API functions have "_ex"
- postfixes and the older functions are reimplemented as wrappers for
- the new ones. The OPENSSL_NO_DEPRECATED symbol can be used to hide
- declarations of the old functions to help (graceful) attempts to
- migrate to the new functions. Also, the new key-generation API
- functions operate on a caller-supplied key-structure and return
- success/failure rather than returning a key or NULL - this is to
- help make "keygen" another member function of RSA_METHOD etc.
-
- Example for using the new callback interface:
-
- int (*my_callback)(int a, int b, BN_GENCB *cb) = ...;
- void *my_arg = ...;
- BN_GENCB my_cb;
-
- BN_GENCB_set(&my_cb, my_callback, my_arg);
-
- return BN_is_prime_ex(some_bignum, BN_prime_checks, NULL, &cb);
- /* For the meaning of a, b in calls to my_callback(), see the
- * documentation of the function that calls the callback.
- * cb will point to my_cb; my_arg can be retrieved as cb->arg.
- * my_callback should return 1 if it wants BN_is_prime_ex()
- * to continue, or 0 to stop.
- */
-
- [Geoff Thorpe]
-
- *) Change the ZLIB compression method to be stateful, and make it
- available to TLS with the number defined in
- draft-ietf-tls-compression-04.txt.
- [Richard Levitte]
-
- *) Add the ASN.1 structures and functions for CertificatePair, which
- is defined as follows (according to X.509_4thEditionDraftV6.pdf):
-
- CertificatePair ::= SEQUENCE {
- forward [0] Certificate OPTIONAL,
- reverse [1] Certificate OPTIONAL,
- -- at least one of the pair shall be present -- }
-
- Also implement the PEM functions to read and write certificate
- pairs, and defined the PEM tag as "CERTIFICATE PAIR".
-
- This needed to be defined, mostly for the sake of the LDAP
- attribute crossCertificatePair, but may prove useful elsewhere as
- well.
- [Richard Levitte]
-
- *) Make it possible to inhibit symlinking of shared libraries in
- Makefile.shared, for Cygwin's sake.
- [Richard Levitte]
-
- *) Extend the BIGNUM API by creating a function
- void BN_set_negative(BIGNUM *a, int neg);
- and a macro that behave like
- int BN_is_negative(const BIGNUM *a);
-
- to avoid the need to access 'a->neg' directly in applications.
- [Nils Larsch]
-
- *) Implement fast modular reduction for pseudo-Mersenne primes
- used in NIST curves (crypto/bn/bn_nist.c, crypto/ec/ecp_nist.c).
- EC_GROUP_new_curve_GFp() will now automatically use this
- if applicable.
- [Nils Larsch <nla@trustcenter.de>]
-
- *) Add new lock type (CRYPTO_LOCK_BN).
- [Bodo Moeller]
-
- *) Change the ENGINE framework to automatically load engines
- dynamically from specific directories unless they could be
- found to already be built in or loaded. Move all the
- current engines except for the cryptodev one to a new
- directory engines/.
- The engines in engines/ are built as shared libraries if
- the "shared" options was given to ./Configure or ./config.
- Otherwise, they are inserted in libcrypto.a.
- /usr/local/ssl/engines is the default directory for dynamic
- engines, but that can be overridden at configure time through
- the usual use of --prefix and/or --openssldir, and at run
- time with the environment variable OPENSSL_ENGINES.
- [Geoff Thorpe and Richard Levitte]
-
- *) Add Makefile.shared, a helper makefile to build shared
- libraries. Adapt Makefile.org.
- [Richard Levitte]
-
- *) Add version info to Win32 DLLs.
- [Peter 'Luna' Runestig" <peter@runestig.com>]
-
- *) Add new 'medium level' PKCS#12 API. Certificates and keys
- can be added using this API to created arbitrary PKCS#12
- files while avoiding the low level API.
-
- New options to PKCS12_create(), key or cert can be NULL and
- will then be omitted from the output file. The encryption
- algorithm NIDs can be set to -1 for no encryption, the mac
- iteration count can be set to 0 to omit the mac.
-
- Enhance pkcs12 utility by making the -nokeys and -nocerts
- options work when creating a PKCS#12 file. New option -nomac
- to omit the mac, NONE can be set for an encryption algorithm.
- New code is modified to use the enhanced PKCS12_create()
- instead of the low level API.
- [Steve Henson]
-
- *) Extend ASN1 encoder to support indefinite length constructed
- encoding. This can output sequences tags and octet strings in
- this form. Modify pk7_asn1.c to support indefinite length
- encoding. This is experimental and needs additional code to
- be useful, such as an ASN1 bio and some enhanced streaming
- PKCS#7 code.
-
- Extend template encode functionality so that tagging is passed
- down to the template encoder.
- [Steve Henson]
-
- *) Let 'openssl req' fail if an argument to '-newkey' is not
- recognized instead of using RSA as a default.
- [Bodo Moeller]
-
- *) Add support for ECC-based ciphersuites from draft-ietf-tls-ecc-01.txt.
- As these are not official, they are not included in "ALL";
- the "ECCdraft" ciphersuite group alias can be used to select them.
- [Vipul Gupta and Sumit Gupta (Sun Microsystems Laboratories)]
-
- *) Add ECDH engine support.
- [Nils Gura and Douglas Stebila (Sun Microsystems Laboratories)]
-
- *) Add ECDH in new directory crypto/ecdh/.
- [Douglas Stebila (Sun Microsystems Laboratories)]
-
- *) Let BN_rand_range() abort with an error after 100 iterations
- without success (which indicates a broken PRNG).
- [Bodo Moeller]
-
- *) Change BN_mod_sqrt() so that it verifies that the input value
- is really the square of the return value. (Previously,
- BN_mod_sqrt would show GIGO behaviour.)
- [Bodo Moeller]
-
- *) Add named elliptic curves over binary fields from X9.62, SECG,
- and WAP/WTLS; add OIDs that were still missing.
-
- [Sheueling Chang Shantz and Douglas Stebila
- (Sun Microsystems Laboratories)]
-
- *) Extend the EC library for elliptic curves over binary fields
- (new files ec2_smpl.c, ec2_smpt.c, ec2_mult.c in crypto/ec/).
- New EC_METHOD:
-
- EC_GF2m_simple_method
-
- New API functions:
-
- EC_GROUP_new_curve_GF2m
- EC_GROUP_set_curve_GF2m
- EC_GROUP_get_curve_GF2m
- EC_POINT_set_affine_coordinates_GF2m
- EC_POINT_get_affine_coordinates_GF2m
- EC_POINT_set_compressed_coordinates_GF2m
-
- Point compression for binary fields is disabled by default for
- patent reasons (compile with OPENSSL_EC_BIN_PT_COMP defined to
- enable it).
-
- As binary polynomials are represented as BIGNUMs, various members
- of the EC_GROUP and EC_POINT data structures can be shared
- between the implementations for prime fields and binary fields;
- the above ..._GF2m functions (except for EX_GROUP_new_curve_GF2m)
- are essentially identical to their ..._GFp counterparts.
- (For simplicity, the '..._GFp' prefix has been dropped from
- various internal method names.)
-
- An internal 'field_div' method (similar to 'field_mul' and
- 'field_sqr') has been added; this is used only for binary fields.
-
- [Sheueling Chang Shantz and Douglas Stebila
- (Sun Microsystems Laboratories)]
-
- *) Optionally dispatch EC_POINT_mul(), EC_POINT_precompute_mult()
- through methods ('mul', 'precompute_mult').
-
- The generic implementations (now internally called 'ec_wNAF_mul'
- and 'ec_wNAF_precomputed_mult') remain the default if these
- methods are undefined.
-
- [Sheueling Chang Shantz and Douglas Stebila
- (Sun Microsystems Laboratories)]
-
- *) New function EC_GROUP_get_degree, which is defined through
- EC_METHOD. For curves over prime fields, this returns the bit
- length of the modulus.
-
- [Sheueling Chang Shantz and Douglas Stebila
- (Sun Microsystems Laboratories)]
-
- *) New functions EC_GROUP_dup, EC_POINT_dup.
- (These simply call ..._new and ..._copy).
-
- [Sheueling Chang Shantz and Douglas Stebila
- (Sun Microsystems Laboratories)]
-
- *) Add binary polynomial arithmetic software in crypto/bn/bn_gf2m.c.
- Polynomials are represented as BIGNUMs (where the sign bit is not
- used) in the following functions [macros]:
-
- BN_GF2m_add
- BN_GF2m_sub [= BN_GF2m_add]
- BN_GF2m_mod [wrapper for BN_GF2m_mod_arr]
- BN_GF2m_mod_mul [wrapper for BN_GF2m_mod_mul_arr]
- BN_GF2m_mod_sqr [wrapper for BN_GF2m_mod_sqr_arr]
- BN_GF2m_mod_inv
- BN_GF2m_mod_exp [wrapper for BN_GF2m_mod_exp_arr]
- BN_GF2m_mod_sqrt [wrapper for BN_GF2m_mod_sqrt_arr]
- BN_GF2m_mod_solve_quad [wrapper for BN_GF2m_mod_solve_quad_arr]
- BN_GF2m_cmp [= BN_ucmp]
-
- (Note that only the 'mod' functions are actually for fields GF(2^m).
- BN_GF2m_add() is misnomer, but this is for the sake of consistency.)
-
- For some functions, an the irreducible polynomial defining a
- field can be given as an 'unsigned int[]' with strictly
- decreasing elements giving the indices of those bits that are set;
- i.e., p[] represents the polynomial
- f(t) = t^p[0] + t^p[1] + ... + t^p[k]
- where
- p[0] > p[1] > ... > p[k] = 0.
- This applies to the following functions:
-
- BN_GF2m_mod_arr
- BN_GF2m_mod_mul_arr
- BN_GF2m_mod_sqr_arr
- BN_GF2m_mod_inv_arr [wrapper for BN_GF2m_mod_inv]
- BN_GF2m_mod_div_arr [wrapper for BN_GF2m_mod_div]
- BN_GF2m_mod_exp_arr
- BN_GF2m_mod_sqrt_arr
- BN_GF2m_mod_solve_quad_arr
- BN_GF2m_poly2arr
- BN_GF2m_arr2poly
-
- Conversion can be performed by the following functions:
-
- BN_GF2m_poly2arr
- BN_GF2m_arr2poly
-
- bntest.c has additional tests for binary polynomial arithmetic.
-
- Two implementations for BN_GF2m_mod_div() are available.
- The default algorithm simply uses BN_GF2m_mod_inv() and
- BN_GF2m_mod_mul(). The alternative algorithm is compiled in only
- if OPENSSL_SUN_GF2M_DIV is defined (patent pending; read the
- copyright notice in crypto/bn/bn_gf2m.c before enabling it).
-
- [Sheueling Chang Shantz and Douglas Stebila
- (Sun Microsystems Laboratories)]
-
- *) Add new error code 'ERR_R_DISABLED' that can be used when some
- functionality is disabled at compile-time.
- [Douglas Stebila <douglas.stebila@sun.com>]
-
- *) Change default behaviour of 'openssl asn1parse' so that more
- information is visible when viewing, e.g., a certificate:
-
- Modify asn1_parse2 (crypto/asn1/asn1_par.c) so that in non-'dump'
- mode the content of non-printable OCTET STRINGs is output in a
- style similar to INTEGERs, but with '[HEX DUMP]' prepended to
- avoid the appearance of a printable string.
- [Nils Larsch <nla@trustcenter.de>]
-
- *) Add 'asn1_flag' and 'asn1_form' member to EC_GROUP with access
- functions
- EC_GROUP_set_asn1_flag()
- EC_GROUP_get_asn1_flag()
- EC_GROUP_set_point_conversion_form()
- EC_GROUP_get_point_conversion_form()
- These control ASN1 encoding details:
- - Curves (i.e., groups) are encoded explicitly unless asn1_flag
- has been set to OPENSSL_EC_NAMED_CURVE.
- - Points are encoded in uncompressed form by default; options for
- asn1_for are as for point2oct, namely
- POINT_CONVERSION_COMPRESSED
- POINT_CONVERSION_UNCOMPRESSED
- POINT_CONVERSION_HYBRID
-
- Also add 'seed' and 'seed_len' members to EC_GROUP with access
- functions
- EC_GROUP_set_seed()
- EC_GROUP_get0_seed()
- EC_GROUP_get_seed_len()
- This is used only for ASN1 purposes (so far).
- [Nils Larsch <nla@trustcenter.de>]
-
- *) Add 'field_type' member to EC_METHOD, which holds the NID
- of the appropriate field type OID. The new function
- EC_METHOD_get_field_type() returns this value.
- [Nils Larsch <nla@trustcenter.de>]
-
- *) Add functions
- EC_POINT_point2bn()
- EC_POINT_bn2point()
- EC_POINT_point2hex()
- EC_POINT_hex2point()
- providing useful interfaces to EC_POINT_point2oct() and
- EC_POINT_oct2point().
- [Nils Larsch <nla@trustcenter.de>]
-
- *) Change internals of the EC library so that the functions
- EC_GROUP_set_generator()
- EC_GROUP_get_generator()
- EC_GROUP_get_order()
- EC_GROUP_get_cofactor()
- are implemented directly in crypto/ec/ec_lib.c and not dispatched
- to methods, which would lead to unnecessary code duplication when
- adding different types of curves.
- [Nils Larsch <nla@trustcenter.de> with input by Bodo Moeller]
-
- *) Implement compute_wNAF (crypto/ec/ec_mult.c) without BIGNUM
- arithmetic, and such that modified wNAFs are generated
- (which avoid length expansion in many cases).
- [Bodo Moeller]
-
- *) Add a function EC_GROUP_check_discriminant() (defined via
- EC_METHOD) that verifies that the curve discriminant is non-zero.
-
- Add a function EC_GROUP_check() that makes some sanity tests
- on a EC_GROUP, its generator and order. This includes
- EC_GROUP_check_discriminant().
- [Nils Larsch <nla@trustcenter.de>]
-
- *) Add ECDSA in new directory crypto/ecdsa/.
-
- Add applications 'openssl ecparam' and 'openssl ecdsa'
- (these are based on 'openssl dsaparam' and 'openssl dsa').
-
- ECDSA support is also included in various other files across the
- library. Most notably,
- - 'openssl req' now has a '-newkey ecdsa:file' option;
- - EVP_PKCS82PKEY (crypto/evp/evp_pkey.c) now can handle ECDSA;
- - X509_PUBKEY_get (crypto/asn1/x_pubkey.c) and
- d2i_PublicKey (crypto/asn1/d2i_pu.c) have been modified to make
- them suitable for ECDSA where domain parameters must be
- extracted before the specific public key;
- - ECDSA engine support has been added.
- [Nils Larsch <nla@trustcenter.de>]
-
- *) Include some named elliptic curves, and add OIDs from X9.62,
- SECG, and WAP/WTLS. Each curve can be obtained from the new
- function
- EC_GROUP_new_by_curve_name(),
- and the list of available named curves can be obtained with
- EC_get_builtin_curves().
- Also add a 'curve_name' member to EC_GROUP objects, which can be
- accessed via
- EC_GROUP_set_curve_name()
- EC_GROUP_get_curve_name()
- [Nils Larsch <larsch@trustcenter.de, Bodo Moeller]
-
- *) Remove a few calls to bn_wexpand() in BN_sqr() (the one in there
- was actually never needed) and in BN_mul(). The removal in BN_mul()
- required a small change in bn_mul_part_recursive() and the addition
- of the functions bn_cmp_part_words(), bn_sub_part_words() and
- bn_add_part_words(), which do the same thing as bn_cmp_words(),
- bn_sub_words() and bn_add_words() except they take arrays with
- differing sizes.
- [Richard Levitte]
-
- Changes between 0.9.7l and 0.9.7m [23 Feb 2007]
-
- *) Cleanse PEM buffers before freeing them since they may contain
- sensitive data.
- [Benjamin Bennett <ben@psc.edu>]
-
- *) Include "!eNULL" in SSL_DEFAULT_CIPHER_LIST to make sure that
- a ciphersuite string such as "DEFAULT:RSA" cannot enable
- authentication-only ciphersuites.
- [Bodo Moeller]
-
- *) Since AES128 and AES256 share a single mask bit in the logic of
- ssl/ssl_ciph.c, the code for masking out disabled ciphers needs a
- kludge to work properly if AES128 is available and AES256 isn't.
- [Victor Duchovni]
-
- *) Expand security boundary to match 1.1.1 module.
- [Steve Henson]
-
- *) Remove redundant features: hash file source, editing of test vectors
- modify fipsld to use external fips_premain.c signature.
- [Steve Henson]
-
- *) New perl script mkfipsscr.pl to create shell scripts or batch files to
- run algorithm test programs.
- [Steve Henson]
-
- *) Make algorithm test programs more tolerant of whitespace.
- [Steve Henson]
-
- *) Have SSL/TLS server implementation tolerate "mismatched" record
- protocol version while receiving ClientHello even if the
- ClientHello is fragmented. (The server can't insist on the
- particular protocol version it has chosen before the ServerHello
- message has informed the client about his choice.)
- [Bodo Moeller]
-
- *) Load error codes if they are not already present instead of using a
- static variable. This allows them to be cleanly unloaded and reloaded.
- [Steve Henson]
-
- Changes between 0.9.7k and 0.9.7l [28 Sep 2006]
-
- *) Introduce limits to prevent malicious keys being able to
- cause a denial of service. (CVE-2006-2940)
- [Steve Henson, Bodo Moeller]
-
- *) Fix ASN.1 parsing of certain invalid structures that can result
- in a denial of service. (CVE-2006-2937) [Steve Henson]
-
- *) Fix buffer overflow in SSL_get_shared_ciphers() function.
- (CVE-2006-3738) [Tavis Ormandy and Will Drewry, Google Security Team]
-
- *) Fix SSL client code which could crash if connecting to a
- malicious SSLv2 server. (CVE-2006-4343)
- [Tavis Ormandy and Will Drewry, Google Security Team]
-
- *) Change ciphersuite string processing so that an explicit
- ciphersuite selects this one ciphersuite (so that "AES256-SHA"
- will no longer include "AES128-SHA"), and any other similar
- ciphersuite (same bitmap) from *other* protocol versions (so that
- "RC4-MD5" will still include both the SSL 2.0 ciphersuite and the
- SSL 3.0/TLS 1.0 ciphersuite). This is a backport combining
- changes from 0.9.8b and 0.9.8d.
- [Bodo Moeller]
-
- Changes between 0.9.7j and 0.9.7k [05 Sep 2006]
-
- *) Avoid PKCS #1 v1.5 signature attack discovered by Daniel Bleichenbacher
- (CVE-2006-4339) [Ben Laurie and Google Security Team]
-
- *) Change the Unix randomness entropy gathering to use poll() when
- possible instead of select(), since the latter has some
- undesirable limitations.
- [Darryl Miles via Richard Levitte and Bodo Moeller]
-
- *) Disable rogue ciphersuites:
-
- - SSLv2 0x08 0x00 0x80 ("RC4-64-MD5")
- - SSLv3/TLSv1 0x00 0x61 ("EXP1024-RC2-CBC-MD5")
- - SSLv3/TLSv1 0x00 0x60 ("EXP1024-RC4-MD5")
-
- The latter two were purportedly from
- draft-ietf-tls-56-bit-ciphersuites-0[01].txt, but do not really
- appear there.
-
- Also deactivate the remaining ciphersuites from
- draft-ietf-tls-56-bit-ciphersuites-01.txt. These are just as
- unofficial, and the ID has long expired.
- [Bodo Moeller]
-
- *) Fix RSA blinding Heisenbug (problems sometimes occurred on
- dual-core machines) and other potential thread-safety issues.
- [Bodo Moeller]
-
- Changes between 0.9.7i and 0.9.7j [04 May 2006]
-
- *) Adapt fipsld and the build system to link against the validated FIPS
- module in FIPS mode.
- [Steve Henson]
-
- *) Fixes for VC++ 2005 build under Windows.
- [Steve Henson]
-
- *) Add new Windows build target VC-32-GMAKE for VC++. This uses GNU make
- from a Windows bash shell such as MSYS. It is autodetected from the
- "config" script when run from a VC++ environment. Modify standard VC++
- build to use fipscanister.o from the GNU make build.
- [Steve Henson]
-
- Changes between 0.9.7h and 0.9.7i [14 Oct 2005]
-
- *) Wrapped the definition of EVP_MAX_MD_SIZE in a #ifdef OPENSSL_FIPS.
- The value now differs depending on if you build for FIPS or not.
- BEWARE! A program linked with a shared FIPSed libcrypto can't be
- safely run with a non-FIPSed libcrypto, as it may crash because of
- the difference induced by this change.
- [Andy Polyakov]
-
- Changes between 0.9.7g and 0.9.7h [11 Oct 2005]
-
- *) Remove the functionality of SSL_OP_MSIE_SSLV2_RSA_PADDING
- (part of SSL_OP_ALL). This option used to disable the
- countermeasure against man-in-the-middle protocol-version
- rollback in the SSL 2.0 server implementation, which is a bad
- idea. (CVE-2005-2969)
-
- [Bodo Moeller; problem pointed out by Yutaka Oiwa (Research Center
- for Information Security, National Institute of Advanced Industrial
- Science and Technology [AIST], Japan)]
-
- *) Minimal support for X9.31 signatures and PSS padding modes. This is
- mainly for FIPS compliance and not fully integrated at this stage.
- [Steve Henson]
-
- *) For DSA signing, unless DSA_FLAG_NO_EXP_CONSTTIME is set, perform
- the exponentiation using a fixed-length exponent. (Otherwise,
- the information leaked through timing could expose the secret key
- after many signatures; cf. Bleichenbacher's attack on DSA with
- biased k.)
- [Bodo Moeller]
-
- *) Make a new fixed-window mod_exp implementation the default for
- RSA, DSA, and DH private-key operations so that the sequence of
- squares and multiplies and the memory access pattern are
- independent of the particular secret key. This will mitigate
- cache-timing and potential related attacks.
-
- BN_mod_exp_mont_consttime() is the new exponentiation implementation,
- and this is automatically used by BN_mod_exp_mont() if the new flag
- BN_FLG_EXP_CONSTTIME is set for the exponent. RSA, DSA, and DH
- will use this BN flag for private exponents unless the flag
- RSA_FLAG_NO_EXP_CONSTTIME, DSA_FLAG_NO_EXP_CONSTTIME, or
- DH_FLAG_NO_EXP_CONSTTIME, respectively, is set.
-
- [Matthew D Wood (Intel Corp), with some changes by Bodo Moeller]
-
- *) Change the client implementation for SSLv23_method() and
- SSLv23_client_method() so that is uses the SSL 3.0/TLS 1.0
- Client Hello message format if the SSL_OP_NO_SSLv2 option is set.
- (Previously, the SSL 2.0 backwards compatible Client Hello
- message format would be used even with SSL_OP_NO_SSLv2.)
- [Bodo Moeller]
-
- *) Add support for smime-type MIME parameter in S/MIME messages which some
- clients need.
- [Steve Henson]
-
- *) New function BN_MONT_CTX_set_locked() to set montgomery parameters in
- a threadsafe manner. Modify rsa code to use new function and add calls
- to dsa and dh code (which had race conditions before).
- [Steve Henson]
-
- *) Include the fixed error library code in the C error file definitions
- instead of fixing them up at runtime. This keeps the error code
- structures constant.
- [Steve Henson]
-
- Changes between 0.9.7f and 0.9.7g [11 Apr 2005]
-
- [NB: OpenSSL 0.9.7h and later 0.9.7 patch levels were released after
- OpenSSL 0.9.8.]
-
- *) Fixes for newer kerberos headers. NB: the casts are needed because
- the 'length' field is signed on one version and unsigned on another
- with no (?) obvious way to tell the difference, without these VC++
- complains. Also the "definition" of FAR (blank) is no longer included
- nor is the error ENOMEM. KRB5_PRIVATE has to be set to 1 to pick up
- some needed definitions.
- [Steve Henson]
-
- *) Undo Cygwin change.
- [Ulf Möller]
-
- *) Added support for proxy certificates according to RFC 3820.
- Because they may be a security thread to unaware applications,
- they must be explicitly allowed in run-time. See
- docs/HOWTO/proxy_certificates.txt for further information.
- [Richard Levitte]
-
- Changes between 0.9.7e and 0.9.7f [22 Mar 2005]
-
- *) Use (SSL_RANDOM_VALUE - 4) bytes of pseudo random data when generating
- server and client random values. Previously
- (SSL_RANDOM_VALUE - sizeof(time_t)) would be used which would result in
- less random data when sizeof(time_t) > 4 (some 64 bit platforms).
-
- This change has negligible security impact because:
-
- 1. Server and client random values still have 24 bytes of pseudo random
- data.
-
- 2. Server and client random values are sent in the clear in the initial
- handshake.
-
- 3. The master secret is derived using the premaster secret (48 bytes in
- size for static RSA ciphersuites) as well as client server and random
- values.
-
- The OpenSSL team would like to thank the UK NISCC for bringing this issue
- to our attention.
-
- [Stephen Henson, reported by UK NISCC]
-
- *) Use Windows randomness collection on Cygwin.
- [Ulf Möller]
-
- *) Fix hang in EGD/PRNGD query when communication socket is closed
- prematurely by EGD/PRNGD.
- [Darren Tucker <dtucker@zip.com.au> via Lutz Jänicke, resolves #1014]
-
- *) Prompt for pass phrases when appropriate for PKCS12 input format.
- [Steve Henson]
-
- *) Back-port of selected performance improvements from development
- branch, as well as improved support for PowerPC platforms.
- [Andy Polyakov]
-
- *) Add lots of checks for memory allocation failure, error codes to indicate
- failure and freeing up memory if a failure occurs.
- [Nauticus Networks SSL Team <openssl@nauticusnet.com>, Steve Henson]
-
- *) Add new -passin argument to dgst.
- [Steve Henson]
-
- *) Perform some character comparisons of different types in X509_NAME_cmp:
- this is needed for some certificates that re-encode DNs into UTF8Strings
- (in violation of RFC3280) and can't or won't issue name rollover
- certificates.
- [Steve Henson]
-
- *) Make an explicit check during certificate validation to see that
- the CA setting in each certificate on the chain is correct. As a
- side effect always do the following basic checks on extensions,
- not just when there's an associated purpose to the check:
-
- - if there is an unhandled critical extension (unless the user
- has chosen to ignore this fault)
- - if the path length has been exceeded (if one is set at all)
- - that certain extensions fit the associated purpose (if one has
- been given)
- [Richard Levitte]
-
- Changes between 0.9.7d and 0.9.7e [25 Oct 2004]
-
- *) Avoid a race condition when CRLs are checked in a multi threaded
- environment. This would happen due to the reordering of the revoked
- entries during signature checking and serial number lookup. Now the
- encoding is cached and the serial number sort performed under a lock.
- Add new STACK function sk_is_sorted().
- [Steve Henson]
-
- *) Add Delta CRL to the extension code.
- [Steve Henson]
-
- *) Various fixes to s3_pkt.c so alerts are sent properly.
- [David Holmes <d.holmes@f5.com>]
-
- *) Reduce the chances of duplicate issuer name and serial numbers (in
- violation of RFC3280) using the OpenSSL certificate creation utilities.
- This is done by creating a random 64 bit value for the initial serial
- number when a serial number file is created or when a self signed
- certificate is created using 'openssl req -x509'. The initial serial
- number file is created using 'openssl x509 -next_serial' in CA.pl
- rather than being initialized to 1.
- [Steve Henson]
-
- Changes between 0.9.7c and 0.9.7d [17 Mar 2004]
-
- *) Fix null-pointer assignment in do_change_cipher_spec() revealed
- by using the Codenomicon TLS Test Tool (CVE-2004-0079)
- [Joe Orton, Steve Henson]
-
- *) Fix flaw in SSL/TLS handshaking when using Kerberos ciphersuites
- (CVE-2004-0112)
- [Joe Orton, Steve Henson]
-
- *) Make it possible to have multiple active certificates with the same
- subject in the CA index file. This is done only if the keyword
- 'unique_subject' is set to 'no' in the main CA section (default
- if 'CA_default') of the configuration file. The value is saved
- with the database itself in a separate index attribute file,
- named like the index file with '.attr' appended to the name.
- [Richard Levitte]
-
- *) X509 verify fixes. Disable broken certificate workarounds when
- X509_V_FLAGS_X509_STRICT is set. Check CRL issuer has cRLSign set if
- keyUsage extension present. Don't accept CRLs with unhandled critical
- extensions: since verify currently doesn't process CRL extensions this
- rejects a CRL with *any* critical extensions. Add new verify error codes
- for these cases.
- [Steve Henson]
-
- *) When creating an OCSP nonce use an OCTET STRING inside the extnValue.
- A clarification of RFC2560 will require the use of OCTET STRINGs and
- some implementations cannot handle the current raw format. Since OpenSSL
- copies and compares OCSP nonces as opaque blobs without any attempt at
- parsing them this should not create any compatibility issues.
- [Steve Henson]
-
- *) New md flag EVP_MD_CTX_FLAG_REUSE this allows md_data to be reused when
- calling EVP_MD_CTX_copy_ex() to avoid calling OPENSSL_malloc(). Without
- this HMAC (and other) operations are several times slower than OpenSSL
- < 0.9.7.
- [Steve Henson]
-
- *) Print out GeneralizedTime and UTCTime in ASN1_STRING_print_ex().
- [Peter Sylvester <Peter.Sylvester@EdelWeb.fr>]
-
- *) Use the correct content when signing type "other".
- [Steve Henson]
-
- Changes between 0.9.7b and 0.9.7c [30 Sep 2003]
-
- *) Fix various bugs revealed by running the NISCC test suite:
-
- Stop out of bounds reads in the ASN1 code when presented with
- invalid tags (CVE-2003-0543 and CVE-2003-0544).
-
- Free up ASN1_TYPE correctly if ANY type is invalid (CVE-2003-0545).
-
- If verify callback ignores invalid public key errors don't try to check
- certificate signature with the NULL public key.
-
- [Steve Henson]
-
- *) New -ignore_err option in ocsp application to stop the server
- exiting on the first error in a request.
- [Steve Henson]
-
- *) In ssl3_accept() (ssl/s3_srvr.c) only accept a client certificate
- if the server requested one: as stated in TLS 1.0 and SSL 3.0
- specifications.
- [Steve Henson]
-
- *) In ssl3_get_client_hello() (ssl/s3_srvr.c), tolerate additional
- extra data after the compression methods not only for TLS 1.0
- but also for SSL 3.0 (as required by the specification).
- [Bodo Moeller; problem pointed out by Matthias Loepfe]
-
- *) Change X509_certificate_type() to mark the key as exported/exportable
- when it's 512 *bits* long, not 512 bytes.
- [Richard Levitte]
-
- *) Change AES_cbc_encrypt() so it outputs exact multiple of
- blocks during encryption.
- [Richard Levitte]
-
- *) Various fixes to base64 BIO and non blocking I/O. On write
- flushes were not handled properly if the BIO retried. On read
- data was not being buffered properly and had various logic bugs.
- This also affects blocking I/O when the data being decoded is a
- certain size.
- [Steve Henson]
-
- *) Various S/MIME bugfixes and compatibility changes:
- output correct application/pkcs7 MIME type if
- PKCS7_NOOLDMIMETYPE is set. Tolerate some broken signatures.
- Output CR+LF for EOL if PKCS7_CRLFEOL is set (this makes opening
- of files as .eml work). Correctly handle very long lines in MIME
- parser.
- [Steve Henson]
-
- Changes between 0.9.7a and 0.9.7b [10 Apr 2003]
-
- *) Countermeasure against the Klima-Pokorny-Rosa extension of
- Bleichbacher's attack on PKCS #1 v1.5 padding: treat
- a protocol version number mismatch like a decryption error
- in ssl3_get_client_key_exchange (ssl/s3_srvr.c).
- [Bodo Moeller]
-
- *) Turn on RSA blinding by default in the default implementation
- to avoid a timing attack. Applications that don't want it can call
- RSA_blinding_off() or use the new flag RSA_FLAG_NO_BLINDING.
- They would be ill-advised to do so in most cases.
- [Ben Laurie, Steve Henson, Geoff Thorpe, Bodo Moeller]
-
- *) Change RSA blinding code so that it works when the PRNG is not
- seeded (in this case, the secret RSA exponent is abused as
- an unpredictable seed -- if it is not unpredictable, there
- is no point in blinding anyway). Make RSA blinding thread-safe
- by remembering the creator's thread ID in rsa->blinding and
- having all other threads use local one-time blinding factors
- (this requires more computation than sharing rsa->blinding, but
- avoids excessive locking; and if an RSA object is not shared
- between threads, blinding will still be very fast).
- [Bodo Moeller]
-
- *) Fixed a typo bug that would cause ENGINE_set_default() to set an
- ENGINE as defaults for all supported algorithms irrespective of
- the 'flags' parameter. 'flags' is now honoured, so applications
- should make sure they are passing it correctly.
- [Geoff Thorpe]
-
- *) Target "mingw" now allows native Windows code to be generated in
- the Cygwin environment as well as with the MinGW compiler.
- [Ulf Moeller]
-
- Changes between 0.9.7 and 0.9.7a [19 Feb 2003]
-
- *) In ssl3_get_record (ssl/s3_pkt.c), minimize information leaked
- via timing by performing a MAC computation even if incorrect
- block cipher padding has been found. This is a countermeasure
- against active attacks where the attacker has to distinguish
- between bad padding and a MAC verification error. (CVE-2003-0078)
-
- [Bodo Moeller; problem pointed out by Brice Canvel (EPFL),
- Alain Hiltgen (UBS), Serge Vaudenay (EPFL), and
- Martin Vuagnoux (EPFL, Ilion)]
-
- *) Make the no-err option work as intended. The intention with no-err
- is not to have the whole error stack handling routines removed from
- libcrypto, it's only intended to remove all the function name and
- reason texts, thereby removing some of the footprint that may not
- be interesting if those errors aren't displayed anyway.
-
- NOTE: it's still possible for any application or module to have its
- own set of error texts inserted. The routines are there, just not
- used by default when no-err is given.
- [Richard Levitte]
-
- *) Add support for FreeBSD on IA64.
- [dirk.meyer@dinoex.sub.org via Richard Levitte, resolves #454]
-
- *) Adjust DES_cbc_cksum() so it returns the same value as the MIT
- Kerberos function mit_des_cbc_cksum(). Before this change,
- the value returned by DES_cbc_cksum() was like the one from
- mit_des_cbc_cksum(), except the bytes were swapped.
- [Kevin Greaney <Kevin.Greaney@hp.com> and Richard Levitte]
-
- *) Allow an application to disable the automatic SSL chain building.
- Before this a rather primitive chain build was always performed in
- ssl3_output_cert_chain(): an application had no way to send the
- correct chain if the automatic operation produced an incorrect result.
-
- Now the chain builder is disabled if either:
-
- 1. Extra certificates are added via SSL_CTX_add_extra_chain_cert().
-
- 2. The mode flag SSL_MODE_NO_AUTO_CHAIN is set.
-
- The reasoning behind this is that an application would not want the
- auto chain building to take place if extra chain certificates are
- present and it might also want a means of sending no additional
- certificates (for example the chain has two certificates and the
- root is omitted).
- [Steve Henson]
-
- *) Add the possibility to build without the ENGINE framework.
- [Steven Reddie <smr@essemer.com.au> via Richard Levitte]
-
- *) Under Win32 gmtime() can return NULL: check return value in
- OPENSSL_gmtime(). Add error code for case where gmtime() fails.
- [Steve Henson]
-
- *) DSA routines: under certain error conditions uninitialized BN objects
- could be freed. Solution: make sure initialization is performed early
- enough. (Reported and fix supplied by Ivan D Nestlerode <nestler@MIT.EDU>,
- Nils Larsch <nla@trustcenter.de> via PR#459)
- [Lutz Jaenicke]
-
- *) Another fix for SSLv2 session ID handling: the session ID was incorrectly
- checked on reconnect on the client side, therefore session resumption
- could still fail with a "ssl session id is different" error. This
- behaviour is masked when SSL_OP_ALL is used due to
- SSL_OP_MICROSOFT_SESS_ID_BUG being set.
- Behaviour observed by Crispin Flowerday <crispin@flowerday.cx> as
- followup to PR #377.
- [Lutz Jaenicke]
-
- *) IA-32 assembler support enhancements: unified ELF targets, support
- for SCO/Caldera platforms, fix for Cygwin shared build.
- [Andy Polyakov]
-
- *) Add support for FreeBSD on sparc64. As a consequence, support for
- FreeBSD on non-x86 processors is separate from x86 processors on
- the config script, much like the NetBSD support.
- [Richard Levitte & Kris Kennaway <kris@obsecurity.org>]
-
- Changes between 0.9.6h and 0.9.7 [31 Dec 2002]
-
- [NB: OpenSSL 0.9.6i and later 0.9.6 patch levels were released after
- OpenSSL 0.9.7.]
-
- *) Fix session ID handling in SSLv2 client code: the SERVER FINISHED
- code (06) was taken as the first octet of the session ID and the last
- octet was ignored consequently. As a result SSLv2 client side session
- caching could not have worked due to the session ID mismatch between
- client and server.
- Behaviour observed by Crispin Flowerday <crispin@flowerday.cx> as
- PR #377.
- [Lutz Jaenicke]
-
- *) Change the declaration of needed Kerberos libraries to use EX_LIBS
- instead of the special (and badly supported) LIBKRB5. LIBKRB5 is
- removed entirely.
- [Richard Levitte]
-
- *) The hw_ncipher.c engine requires dynamic locks. Unfortunately, it
- seems that in spite of existing for more than a year, many application
- author have done nothing to provide the necessary callbacks, which
- means that this particular engine will not work properly anywhere.
- This is a very unfortunate situation which forces us, in the name
- of usability, to give the hw_ncipher.c a static lock, which is part
- of libcrypto.
- NOTE: This is for the 0.9.7 series ONLY. This hack will never
- appear in 0.9.8 or later. We EXPECT application authors to have
- dealt properly with this when 0.9.8 is released (unless we actually
- make such changes in the libcrypto locking code that changes will
- have to be made anyway).
- [Richard Levitte]
-
- *) In asn1_d2i_read_bio() repeatedly call BIO_read() until all content
- octets have been read, EOF or an error occurs. Without this change
- some truncated ASN1 structures will not produce an error.
- [Steve Henson]
-
- *) Disable Heimdal support, since it hasn't been fully implemented.
- Still give the possibility to force the use of Heimdal, but with
- warnings and a request that patches get sent to openssl-dev.
- [Richard Levitte]
-
- *) Add the VC-CE target, introduce the WINCE sysname, and add
- INSTALL.WCE and appropriate conditionals to make it build.
- [Steven Reddie <smr@essemer.com.au> via Richard Levitte]
-
- *) Change the DLL names for Cygwin to cygcrypto-x.y.z.dll and
- cygssl-x.y.z.dll, where x, y and z are the major, minor and
- edit numbers of the version.
- [Corinna Vinschen <vinschen@redhat.com> and Richard Levitte]
-
- *) Introduce safe string copy and catenation functions
- (BUF_strlcpy() and BUF_strlcat()).
- [Ben Laurie (CHATS) and Richard Levitte]
-
- *) Avoid using fixed-size buffers for one-line DNs.
- [Ben Laurie (CHATS)]
-
- *) Add BUF_MEM_grow_clean() to avoid information leakage when
- resizing buffers containing secrets, and use where appropriate.
- [Ben Laurie (CHATS)]
-
- *) Avoid using fixed size buffers for configuration file location.
- [Ben Laurie (CHATS)]
-
- *) Avoid filename truncation for various CA files.
- [Ben Laurie (CHATS)]
-
- *) Use sizeof in preference to magic numbers.
- [Ben Laurie (CHATS)]
-
- *) Avoid filename truncation in cert requests.
- [Ben Laurie (CHATS)]
-
- *) Add assertions to check for (supposedly impossible) buffer
- overflows.
- [Ben Laurie (CHATS)]
-
- *) Don't cache truncated DNS entries in the local cache (this could
- potentially lead to a spoofing attack).
- [Ben Laurie (CHATS)]
-
- *) Fix various buffers to be large enough for hex/decimal
- representations in a platform independent manner.
- [Ben Laurie (CHATS)]
-
- *) Add CRYPTO_realloc_clean() to avoid information leakage when
- resizing buffers containing secrets, and use where appropriate.
- [Ben Laurie (CHATS)]
-
- *) Add BIO_indent() to avoid much slightly worrying code to do
- indents.
- [Ben Laurie (CHATS)]
-
- *) Convert sprintf()/BIO_puts() to BIO_printf().
- [Ben Laurie (CHATS)]
-
- *) buffer_gets() could terminate with the buffer only half
- full. Fixed.
- [Ben Laurie (CHATS)]
-
- *) Add assertions to prevent user-supplied crypto functions from
- overflowing internal buffers by having large block sizes, etc.
- [Ben Laurie (CHATS)]
-
- *) New OPENSSL_assert() macro (similar to assert(), but enabled
- unconditionally).
- [Ben Laurie (CHATS)]
-
- *) Eliminate unused copy of key in RC4.
- [Ben Laurie (CHATS)]
-
- *) Eliminate unused and incorrectly sized buffers for IV in pem.h.
- [Ben Laurie (CHATS)]
-
- *) Fix off-by-one error in EGD path.
- [Ben Laurie (CHATS)]
-
- *) If RANDFILE path is too long, ignore instead of truncating.
- [Ben Laurie (CHATS)]
-
- *) Eliminate unused and incorrectly sized X.509 structure
- CBCParameter.
- [Ben Laurie (CHATS)]
-
- *) Eliminate unused and dangerous function knumber().
- [Ben Laurie (CHATS)]
-
- *) Eliminate unused and dangerous structure, KSSL_ERR.
- [Ben Laurie (CHATS)]
-
- *) Protect against overlong session ID context length in an encoded
- session object. Since these are local, this does not appear to be
- exploitable.
- [Ben Laurie (CHATS)]
-
- *) Change from security patch (see 0.9.6e below) that did not affect
- the 0.9.6 release series:
-
- Remote buffer overflow in SSL3 protocol - an attacker could
- supply an oversized master key in Kerberos-enabled versions.
- (CVE-2002-0657)
- [Ben Laurie (CHATS)]
-
- *) Change the SSL kerb5 codes to match RFC 2712.
- [Richard Levitte]
-
- *) Make -nameopt work fully for req and add -reqopt switch.
- [Michael Bell <michael.bell@rz.hu-berlin.de>, Steve Henson]
-
- *) The "block size" for block ciphers in CFB and OFB mode should be 1.
- [Steve Henson, reported by Yngve Nysaeter Pettersen <yngve@opera.com>]
-
- *) Make sure tests can be performed even if the corresponding algorithms
- have been removed entirely. This was also the last step to make
- OpenSSL compilable with DJGPP under all reasonable conditions.
- [Richard Levitte, Doug Kaufman <dkaufman@rahul.net>]
-
- *) Add cipher selection rules COMPLEMENTOFALL and COMPLEMENTOFDEFAULT
- to allow version independent disabling of normally unselected ciphers,
- which may be activated as a side-effect of selecting a single cipher.
-
- (E.g., cipher list string "RSA" enables ciphersuites that are left
- out of "ALL" because they do not provide symmetric encryption.
- "RSA:!COMPLEMEMENTOFALL" avoids these unsafe ciphersuites.)
- [Lutz Jaenicke, Bodo Moeller]
-
- *) Add appropriate support for separate platform-dependent build
- directories. The recommended way to make a platform-dependent
- build directory is the following (tested on Linux), maybe with
- some local tweaks:
-
- # Place yourself outside of the OpenSSL source tree. In
- # this example, the environment variable OPENSSL_SOURCE
- # is assumed to contain the absolute OpenSSL source directory.
- mkdir -p objtree/"`uname -s`-`uname -r`-`uname -m`"
- cd objtree/"`uname -s`-`uname -r`-`uname -m`"
- (cd $OPENSSL_SOURCE; find . -type f) | while read F; do
- mkdir -p `dirname $F`
- ln -s $OPENSSL_SOURCE/$F $F
- done
-
- To be absolutely sure not to disturb the source tree, a "make clean"
- is a good thing. If it isn't successful, don't worry about it,
- it probably means the source directory is very clean.
- [Richard Levitte]
-
- *) Make sure any ENGINE control commands make local copies of string
- pointers passed to them whenever necessary. Otherwise it is possible
- the caller may have overwritten (or deallocated) the original string
- data when a later ENGINE operation tries to use the stored values.
- [Götz Babin-Ebell <babinebell@trustcenter.de>]
-
- *) Improve diagnostics in file reading and command-line digests.
- [Ben Laurie aided and abetted by Solar Designer <solar@openwall.com>]
-
- *) Add AES modes CFB and OFB to the object database. Correct an
- error in AES-CFB decryption.
- [Richard Levitte]
-
- *) Remove most calls to EVP_CIPHER_CTX_cleanup() in evp_enc.c, this
- allows existing EVP_CIPHER_CTX structures to be reused after
- calling EVP_*Final(). This behaviour is used by encryption
- BIOs and some applications. This has the side effect that
- applications must explicitly clean up cipher contexts with
- EVP_CIPHER_CTX_cleanup() or they will leak memory.
- [Steve Henson]
-
- *) Check the values of dna and dnb in bn_mul_recursive before calling
- bn_mul_comba (a non zero value means the a or b arrays do not contain
- n2 elements) and fallback to bn_mul_normal if either is not zero.
- [Steve Henson]
-
- *) Fix escaping of non-ASCII characters when using the -subj option
- of the "openssl req" command line tool. (Robert Joop <joop@fokus.gmd.de>)
- [Lutz Jaenicke]
-
- *) Make object definitions compliant to LDAP (RFC2256): SN is the short
- form for "surname", serialNumber has no short form.
- Use "mail" as the short name for "rfc822Mailbox" according to RFC2798;
- therefore remove "mail" short name for "internet 7".
- The OID for unique identifiers in X509 certificates is
- x500UniqueIdentifier, not uniqueIdentifier.
- Some more OID additions. (Michael Bell <michael.bell@rz.hu-berlin.de>)
- [Lutz Jaenicke]
-
- *) Add an "init" command to the ENGINE config module and auto initialize
- ENGINEs. Without any "init" command the ENGINE will be initialized
- after all ctrl commands have been executed on it. If init=1 the
- ENGINE is initialized at that point (ctrls before that point are run
- on the uninitialized ENGINE and after on the initialized one). If
- init=0 then the ENGINE will not be initialized at all.
- [Steve Henson]
-
- *) Fix the 'app_verify_callback' interface so that the user-defined
- argument is actually passed to the callback: In the
- SSL_CTX_set_cert_verify_callback() prototype, the callback
- declaration has been changed from
- int (*cb)()
- into
- int (*cb)(X509_STORE_CTX *,void *);
- in ssl_verify_cert_chain (ssl/ssl_cert.c), the call
- i=s->ctx->app_verify_callback(&ctx)
- has been changed into
- i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg).
-
- To update applications using SSL_CTX_set_cert_verify_callback(),
- a dummy argument can be added to their callback functions.
- [D. K. Smetters <smetters@parc.xerox.com>]
-
- *) Added the '4758cca' ENGINE to support IBM 4758 cards.
- [Maurice Gittens <maurice@gittens.nl>, touchups by Geoff Thorpe]
-
- *) Add and OPENSSL_LOAD_CONF define which will cause
- OpenSSL_add_all_algorithms() to load the openssl.cnf config file.
- This allows older applications to transparently support certain
- OpenSSL features: such as crypto acceleration and dynamic ENGINE loading.
- Two new functions OPENSSL_add_all_algorithms_noconf() which will never
- load the config file and OPENSSL_add_all_algorithms_conf() which will
- always load it have also been added.
- [Steve Henson]
-
- *) Add the OFB, CFB and CTR (all with 128 bit feedback) to AES.
- Adjust NIDs and EVP layer.
- [Stephen Sprunk <stephen@sprunk.org> and Richard Levitte]
-
- *) Config modules support in openssl utility.
-
- Most commands now load modules from the config file,
- though in a few (such as version) this isn't done
- because it couldn't be used for anything.
-
- In the case of ca and req the config file used is
- the same as the utility itself: that is the -config
- command line option can be used to specify an
- alternative file.
- [Steve Henson]
-
- *) Move default behaviour from OPENSSL_config(). If appname is NULL
- use "openssl_conf" if filename is NULL use default openssl config file.
- [Steve Henson]
-
- *) Add an argument to OPENSSL_config() to allow the use of an alternative
- config section name. Add a new flag to tolerate a missing config file
- and move code to CONF_modules_load_file().
- [Steve Henson]
-
- *) Support for crypto accelerator cards from Accelerated Encryption
- Processing, www.aep.ie. (Use engine 'aep')
- The support was copied from 0.9.6c [engine] and adapted/corrected
- to work with the new engine framework.
- [AEP Inc. and Richard Levitte]
-
- *) Support for SureWare crypto accelerator cards from Baltimore
- Technologies. (Use engine 'sureware')
- The support was copied from 0.9.6c [engine] and adapted
- to work with the new engine framework.
- [Richard Levitte]
-
- *) Have the CHIL engine fork-safe (as defined by nCipher) and actually
- make the newer ENGINE framework commands for the CHIL engine work.
- [Toomas Kiisk <vix@cyber.ee> and Richard Levitte]
-
- *) Make it possible to produce shared libraries on ReliantUNIX.
- [Robert Dahlem <Robert.Dahlem@ffm2.siemens.de> via Richard Levitte]
-
- *) Add the configuration target debug-linux-ppro.
- Make 'openssl rsa' use the general key loading routines
- implemented in apps.c, and make those routines able to
- handle the key format FORMAT_NETSCAPE and the variant
- FORMAT_IISSGC.
- [Toomas Kiisk <vix@cyber.ee> via Richard Levitte]
-
- *) Fix a crashbug and a logic bug in hwcrhk_load_pubkey().
- [Toomas Kiisk <vix@cyber.ee> via Richard Levitte]
-
- *) Add -keyform to rsautl, and document -engine.
- [Richard Levitte, inspired by Toomas Kiisk <vix@cyber.ee>]
-
- *) Change BIO_new_file (crypto/bio/bss_file.c) to use new
- BIO_R_NO_SUCH_FILE error code rather than the generic
- ERR_R_SYS_LIB error code if fopen() fails with ENOENT.
- [Ben Laurie]
-
- *) Add new functions
- ERR_peek_last_error
- ERR_peek_last_error_line
- ERR_peek_last_error_line_data.
- These are similar to
- ERR_peek_error
- ERR_peek_error_line
- ERR_peek_error_line_data,
- but report on the latest error recorded rather than the first one
- still in the error queue.
- [Ben Laurie, Bodo Moeller]
-
- *) default_algorithms option in ENGINE config module. This allows things
- like:
- default_algorithms = ALL
- default_algorithms = RSA, DSA, RAND, CIPHERS, DIGESTS
- [Steve Henson]
-
- *) Preliminary ENGINE config module.
- [Steve Henson]
-
- *) New experimental application configuration code.
- [Steve Henson]
-
- *) Change the AES code to follow the same name structure as all other
- symmetric ciphers, and behave the same way. Move everything to
- the directory crypto/aes, thereby obsoleting crypto/rijndael.
- [Stephen Sprunk <stephen@sprunk.org> and Richard Levitte]
-
- *) SECURITY: remove unsafe setjmp/signal interaction from ui_openssl.c.
- [Ben Laurie and Theo de Raadt]
-
- *) Add option to output public keys in req command.
- [Massimiliano Pala madwolf@openca.org]
-
- *) Use wNAFs in EC_POINTs_mul() for improved efficiency
- (up to about 10% better than before for P-192 and P-224).
- [Bodo Moeller]
-
- *) New functions/macros
-
- SSL_CTX_set_msg_callback(ctx, cb)
- SSL_CTX_set_msg_callback_arg(ctx, arg)
- SSL_set_msg_callback(ssl, cb)
- SSL_set_msg_callback_arg(ssl, arg)
-
- to request calling a callback function
-
- void cb(int write_p, int version, int content_type,
- const void *buf, size_t len, SSL *ssl, void *arg)
-
- whenever a protocol message has been completely received
- (write_p == 0) or sent (write_p == 1). Here 'version' is the
- protocol version according to which the SSL library interprets
- the current protocol message (SSL2_VERSION, SSL3_VERSION, or
- TLS1_VERSION). 'content_type' is 0 in the case of SSL 2.0, or
- the content type as defined in the SSL 3.0/TLS 1.0 protocol
- specification (change_cipher_spec(20), alert(21), handshake(22)).
- 'buf' and 'len' point to the actual message, 'ssl' to the
- SSL object, and 'arg' is the application-defined value set by
- SSL[_CTX]_set_msg_callback_arg().
-
- 'openssl s_client' and 'openssl s_server' have new '-msg' options
- to enable a callback that displays all protocol messages.
- [Bodo Moeller]
-
- *) Change the shared library support so shared libraries are built as
- soon as the corresponding static library is finished, and thereby get
- openssl and the test programs linked against the shared library.
- This still only happens when the keyword "shard" has been given to
- the configuration scripts.
-
- NOTE: shared library support is still an experimental thing, and
- backward binary compatibility is still not guaranteed.
- ["Maciej W. Rozycki" <macro@ds2.pg.gda.pl> and Richard Levitte]
-
- *) Add support for Subject Information Access extension.
- [Peter Sylvester <Peter.Sylvester@EdelWeb.fr>]
-
- *) Make BUF_MEM_grow() behaviour more consistent: Initialise to zero
- additional bytes when new memory had to be allocated, not just
- when reusing an existing buffer.
- [Bodo Moeller]
-
- *) New command line and configuration option 'utf8' for the req command.
- This allows field values to be specified as UTF8 strings.
- [Steve Henson]
-
- *) Add -multi and -mr options to "openssl speed" - giving multiple parallel
- runs for the former and machine-readable output for the latter.
- [Ben Laurie]
-
- *) Add '-noemailDN' option to 'openssl ca'. This prevents inclusion
- of the e-mail address in the DN (i.e., it will go into a certificate
- extension only). The new configuration file option 'email_in_dn = no'
- has the same effect.
- [Massimiliano Pala madwolf@openca.org]
-
- *) Change all functions with names starting with des_ to be starting
- with DES_ instead. Add wrappers that are compatible with libdes,
- but are named _ossl_old_des_*. Finally, add macros that map the
- des_* symbols to the corresponding _ossl_old_des_* if libdes
- compatibility is desired. If OpenSSL 0.9.6c compatibility is
- desired, the des_* symbols will be mapped to DES_*, with one
- exception.
-
- Since we provide two compatibility mappings, the user needs to
- define the macro OPENSSL_DES_LIBDES_COMPATIBILITY if libdes
- compatibility is desired. The default (i.e., when that macro
- isn't defined) is OpenSSL 0.9.6c compatibility.
-
- There are also macros that enable and disable the support of old
- des functions altogether. Those are OPENSSL_ENABLE_OLD_DES_SUPPORT
- and OPENSSL_DISABLE_OLD_DES_SUPPORT. If none or both of those
- are defined, the default will apply: to support the old des routines.
-
- In either case, one must include openssl/des.h to get the correct
- definitions. Do not try to just include openssl/des_old.h, that
- won't work.
-
- NOTE: This is a major break of an old API into a new one. Software
- authors are encouraged to switch to the DES_ style functions. Some
- time in the future, des_old.h and the libdes compatibility functions
- will be disable (i.e. OPENSSL_DISABLE_OLD_DES_SUPPORT will be the
- default), and then completely removed.
- [Richard Levitte]
-
- *) Test for certificates which contain unsupported critical extensions.
- If such a certificate is found during a verify operation it is
- rejected by default: this behaviour can be overridden by either
- handling the new error X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION or
- by setting the verify flag X509_V_FLAG_IGNORE_CRITICAL. A new function
- X509_supported_extension() has also been added which returns 1 if a
- particular extension is supported.
- [Steve Henson]
-
- *) Modify the behaviour of EVP cipher functions in similar way to digests
- to retain compatibility with existing code.
- [Steve Henson]
-
- *) Modify the behaviour of EVP_DigestInit() and EVP_DigestFinal() to retain
- compatibility with existing code. In particular the 'ctx' parameter does
- not have to be to be initialized before the call to EVP_DigestInit() and
- it is tidied up after a call to EVP_DigestFinal(). New function
- EVP_DigestFinal_ex() which does not tidy up the ctx. Similarly function
- EVP_MD_CTX_copy() changed to not require the destination to be
- initialized valid and new function EVP_MD_CTX_copy_ex() added which
- requires the destination to be valid.
-
- Modify all the OpenSSL digest calls to use EVP_DigestInit_ex(),
- EVP_DigestFinal_ex() and EVP_MD_CTX_copy_ex().
- [Steve Henson]
-
- *) Change ssl3_get_message (ssl/s3_both.c) and the functions using it
- so that complete 'Handshake' protocol structures are kept in memory
- instead of overwriting 'msg_type' and 'length' with 'body' data.
- [Bodo Moeller]
-
- *) Add an implementation of SSL_add_dir_cert_subjects_to_stack for Win32.
- [Massimo Santin via Richard Levitte]
-
- *) Major restructuring to the underlying ENGINE code. This includes
- reduction of linker bloat, separation of pure "ENGINE" manipulation
- (initialisation, etc) from functionality dealing with implementations
- of specific crypto interfaces. This change also introduces integrated
- support for symmetric ciphers and digest implementations - so ENGINEs
- can now accelerate these by providing EVP_CIPHER and EVP_MD
- implementations of their own. This is detailed in crypto/engine/README
- as it couldn't be adequately described here. However, there are a few
- API changes worth noting - some RSA, DSA, DH, and RAND functions that
- were changed in the original introduction of ENGINE code have now
- reverted back - the hooking from this code to ENGINE is now a good
- deal more passive and at run-time, operations deal directly with
- RSA_METHODs, DSA_METHODs (etc) as they did before, rather than
- dereferencing through an ENGINE pointer any more. Also, the ENGINE
- functions dealing with BN_MOD_EXP[_CRT] handlers have been removed -
- they were not being used by the framework as there is no concept of a
- BIGNUM_METHOD and they could not be generalised to the new
- 'ENGINE_TABLE' mechanism that underlies the new code. Similarly,
- ENGINE_cpy() has been removed as it cannot be consistently defined in
- the new code.
- [Geoff Thorpe]
-
- *) Change ASN1_GENERALIZEDTIME_check() to allow fractional seconds.
- [Steve Henson]
-
- *) Change mkdef.pl to sort symbols that get the same entry number,
- and make sure the automatically generated functions ERR_load_*
- become part of libeay.num as well.
- [Richard Levitte]
-
- *) New function SSL_renegotiate_pending(). This returns true once
- renegotiation has been requested (either SSL_renegotiate() call
- or HelloRequest/ClientHello received from the peer) and becomes
- false once a handshake has been completed.
- (For servers, SSL_renegotiate() followed by SSL_do_handshake()
- sends a HelloRequest, but does not ensure that a handshake takes
- place. SSL_renegotiate_pending() is useful for checking if the
- client has followed the request.)
- [Bodo Moeller]
-
- *) New SSL option SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION.
- By default, clients may request session resumption even during
- renegotiation (if session ID contexts permit); with this option,
- session resumption is possible only in the first handshake.
-
- SSL_OP_ALL is now 0x00000FFFL instead of 0x000FFFFFL. This makes
- more bits available for options that should not be part of
- SSL_OP_ALL (such as SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION).
- [Bodo Moeller]
-
- *) Add some demos for certificate and certificate request creation.
- [Steve Henson]
-
- *) Make maximum certificate chain size accepted from the peer application
- settable (SSL*_get/set_max_cert_list()), as proposed by
- "Douglas E. Engert" <deengert@anl.gov>.
- [Lutz Jaenicke]
-
- *) Add support for shared libraries for Unixware-7
- (Boyd Lynn Gerber <gerberb@zenez.com>).
- [Lutz Jaenicke]
-
- *) Add a "destroy" handler to ENGINEs that allows structural cleanup to
- be done prior to destruction. Use this to unload error strings from
- ENGINEs that load their own error strings. NB: This adds two new API
- functions to "get" and "set" this destroy handler in an ENGINE.
- [Geoff Thorpe]
-
- *) Alter all existing ENGINE implementations (except "openssl" and
- "openbsd") to dynamically instantiate their own error strings. This
- makes them more flexible to be built both as statically-linked ENGINEs
- and self-contained shared-libraries loadable via the "dynamic" ENGINE.
- Also, add stub code to each that makes building them as self-contained
- shared-libraries easier (see README.ENGINE).
- [Geoff Thorpe]
-
- *) Add a "dynamic" ENGINE that provides a mechanism for binding ENGINE
- implementations into applications that are completely implemented in
- self-contained shared-libraries. The "dynamic" ENGINE exposes control
- commands that can be used to configure what shared-library to load and
- to control aspects of the way it is handled. Also, made an update to
- the README.ENGINE file that brings its information up-to-date and
- provides some information and instructions on the "dynamic" ENGINE
- (ie. how to use it, how to build "dynamic"-loadable ENGINEs, etc).
- [Geoff Thorpe]
-
- *) Make it possible to unload ranges of ERR strings with a new
- "ERR_unload_strings" function.
- [Geoff Thorpe]
-
- *) Add a copy() function to EVP_MD.
- [Ben Laurie]
-
- *) Make EVP_MD routines take a context pointer instead of just the
- md_data void pointer.
- [Ben Laurie]
-
- *) Add flags to EVP_MD and EVP_MD_CTX. EVP_MD_FLAG_ONESHOT indicates
- that the digest can only process a single chunk of data
- (typically because it is provided by a piece of
- hardware). EVP_MD_CTX_FLAG_ONESHOT indicates that the application
- is only going to provide a single chunk of data, and hence the
- framework needn't accumulate the data for oneshot drivers.
- [Ben Laurie]
-
- *) As with "ERR", make it possible to replace the underlying "ex_data"
- functions. This change also alters the storage and management of global
- ex_data state - it's now all inside ex_data.c and all "class" code (eg.
- RSA, BIO, SSL_CTX, etc) no longer stores its own STACKS and per-class
- index counters. The API functions that use this state have been changed
- to take a "class_index" rather than pointers to the class's local STACK
- and counter, and there is now an API function to dynamically create new
- classes. This centralisation allows us to (a) plug a lot of the
- thread-safety problems that existed, and (b) makes it possible to clean
- up all allocated state using "CRYPTO_cleanup_all_ex_data()". W.r.t. (b)
- such data would previously have always leaked in application code and
- workarounds were in place to make the memory debugging turn a blind eye
- to it. Application code that doesn't use this new function will still
- leak as before, but their memory debugging output will announce it now
- rather than letting it slide.
-
- Besides the addition of CRYPTO_cleanup_all_ex_data(), another API change
- induced by the "ex_data" overhaul is that X509_STORE_CTX_init() now
- has a return value to indicate success or failure.
- [Geoff Thorpe]
-
- *) Make it possible to replace the underlying "ERR" functions such that the
- global state (2 LHASH tables and 2 locks) is only used by the "default"
- implementation. This change also adds two functions to "get" and "set"
- the implementation prior to it being automatically set the first time
- any other ERR function takes place. Ie. an application can call "get",
- pass the return value to a module it has just loaded, and that module
- can call its own "set" function using that value. This means the
- module's "ERR" operations will use (and modify) the error state in the
- application and not in its own statically linked copy of OpenSSL code.
- [Geoff Thorpe]
-
- *) Give DH, DSA, and RSA types their own "**_up_ref()" function to increment
- reference counts. This performs normal REF_PRINT/REF_CHECK macros on
- the operation, and provides a more encapsulated way for external code
- (crypto/evp/ and ssl/) to do this. Also changed the evp and ssl code
- to use these functions rather than manually incrementing the counts.
-
- Also rename "DSO_up()" function to more descriptive "DSO_up_ref()".
- [Geoff Thorpe]
-
- *) Add EVP test program.
- [Ben Laurie]
-
- *) Add symmetric cipher support to ENGINE. Expect the API to change!
- [Ben Laurie]
-
- *) New CRL functions: X509_CRL_set_version(), X509_CRL_set_issuer_name()
- X509_CRL_set_lastUpdate(), X509_CRL_set_nextUpdate(), X509_CRL_sort(),
- X509_REVOKED_set_serialNumber(), and X509_REVOKED_set_revocationDate().
- These allow a CRL to be built without having to access X509_CRL fields
- directly. Modify 'ca' application to use new functions.
- [Steve Henson]
-
- *) Move SSL_OP_TLS_ROLLBACK_BUG out of the SSL_OP_ALL list of recommended
- bug workarounds. Rollback attack detection is a security feature.
- The problem will only arise on OpenSSL servers when TLSv1 is not
- available (sslv3_server_method() or SSL_OP_NO_TLSv1).
- Software authors not wanting to support TLSv1 will have special reasons
- for their choice and can explicitly enable this option.
- [Bodo Moeller, Lutz Jaenicke]
-
- *) Rationalise EVP so it can be extended: don't include a union of
- cipher/digest structures, add init/cleanup functions for EVP_MD_CTX
- (similar to those existing for EVP_CIPHER_CTX).
- Usage example:
-
- EVP_MD_CTX md;
-
- EVP_MD_CTX_init(&md); /* new function call */
- EVP_DigestInit(&md, EVP_sha1());
- EVP_DigestUpdate(&md, in, len);
- EVP_DigestFinal(&md, out, NULL);
- EVP_MD_CTX_cleanup(&md); /* new function call */
-
- [Ben Laurie]
-
- *) Make DES key schedule conform to the usual scheme, as well as
- correcting its structure. This means that calls to DES functions
- now have to pass a pointer to a des_key_schedule instead of a
- plain des_key_schedule (which was actually always a pointer
- anyway): E.g.,
-
- des_key_schedule ks;
-
- des_set_key_checked(..., &ks);
- des_ncbc_encrypt(..., &ks, ...);
-
- (Note that a later change renames 'des_...' into 'DES_...'.)
- [Ben Laurie]
-
- *) Initial reduction of linker bloat: the use of some functions, such as
- PEM causes large amounts of unused functions to be linked in due to
- poor organisation. For example pem_all.c contains every PEM function
- which has a knock on effect of linking in large amounts of (unused)
- ASN1 code. Grouping together similar functions and splitting unrelated
- functions prevents this.
- [Steve Henson]
-
- *) Cleanup of EVP macros.
- [Ben Laurie]
-
- *) Change historical references to {NID,SN,LN}_des_ede and ede3 to add the
- correct _ecb suffix.
- [Ben Laurie]
-
- *) Add initial OCSP responder support to ocsp application. The
- revocation information is handled using the text based index
- use by the ca application. The responder can either handle
- requests generated internally, supplied in files (for example
- via a CGI script) or using an internal minimal server.
- [Steve Henson]
-
- *) Add configuration choices to get zlib compression for TLS.
- [Richard Levitte]
-
- *) Changes to Kerberos SSL for RFC 2712 compliance:
- 1. Implemented real KerberosWrapper, instead of just using
- KRB5 AP_REQ message. [Thanks to Simon Wilkinson <sxw@sxw.org.uk>]
- 2. Implemented optional authenticator field of KerberosWrapper.
-
- Added openssl-style ASN.1 macros for Kerberos ticket, ap_req,
- and authenticator structs; see crypto/krb5/.
-
- Generalized Kerberos calls to support multiple Kerberos libraries.
- [Vern Staats <staatsvr@asc.hpc.mil>,
- Jeffrey Altman <jaltman@columbia.edu>
- via Richard Levitte]
-
- *) Cause 'openssl speed' to use fully hard-coded DSA keys as it
- already does with RSA. testdsa.h now has 'priv_key/pub_key'
- values for each of the key sizes rather than having just
- parameters (and 'speed' generating keys each time).
- [Geoff Thorpe]
-
- *) Speed up EVP routines.
- Before:
-encrypt
-type 8 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes
-des-cbc 4408.85k 5560.51k 5778.46k 5862.20k 5825.16k
-des-cbc 4389.55k 5571.17k 5792.23k 5846.91k 5832.11k
-des-cbc 4394.32k 5575.92k 5807.44k 5848.37k 5841.30k
-decrypt
-des-cbc 3482.66k 5069.49k 5496.39k 5614.16k 5639.28k
-des-cbc 3480.74k 5068.76k 5510.34k 5609.87k 5635.52k
-des-cbc 3483.72k 5067.62k 5504.60k 5708.01k 5724.80k
- After:
-encrypt
-des-cbc 4660.16k 5650.19k 5807.19k 5827.13k 5783.32k
-decrypt
-des-cbc 3624.96k 5258.21k 5530.91k 5624.30k 5628.26k
- [Ben Laurie]
-
- *) Added the OS2-EMX target.
- ["Brian Havard" <brianh@kheldar.apana.org.au> and Richard Levitte]
-
- *) Rewrite apps to use NCONF routines instead of the old CONF. New functions
- to support NCONF routines in extension code. New function CONF_set_nconf()
- to allow functions which take an NCONF to also handle the old LHASH
- structure: this means that the old CONF compatible routines can be
- retained (in particular wrt extensions) without having to duplicate the
- code. New function X509V3_add_ext_nconf_sk to add extensions to a stack.
- [Steve Henson]
-
- *) Enhance the general user interface with mechanisms for inner control
- and with possibilities to have yes/no kind of prompts.
- [Richard Levitte]
-
- *) Change all calls to low level digest routines in the library and
- applications to use EVP. Add missing calls to HMAC_cleanup() and
- don't assume HMAC_CTX can be copied using memcpy().
- [Verdon Walker <VWalker@novell.com>, Steve Henson]
-
- *) Add the possibility to control engines through control names but with
- arbitrary arguments instead of just a string.
- Change the key loaders to take a UI_METHOD instead of a callback
- function pointer. NOTE: this breaks binary compatibility with earlier
- versions of OpenSSL [engine].
- Adapt the nCipher code for these new conditions and add a card insertion
- callback.
- [Richard Levitte]
-
- *) Enhance the general user interface with mechanisms to better support
- dialog box interfaces, application-defined prompts, the possibility
- to use defaults (for example default passwords from somewhere else)
- and interrupts/cancellations.
- [Richard Levitte]
-
- *) Tidy up PKCS#12 attribute handling. Add support for the CSP name
- attribute in PKCS#12 files, add new -CSP option to pkcs12 utility.
- [Steve Henson]
-
- *) Fix a memory leak in 'sk_dup()' in the case reallocation fails. (Also
- tidy up some unnecessarily weird code in 'sk_new()').
- [Geoff, reported by Diego Tartara <dtartara@novamens.com>]
-
- *) Change the key loading routines for ENGINEs to use the same kind
- callback (pem_password_cb) as all other routines that need this
- kind of callback.
- [Richard Levitte]
-
- *) Increase ENTROPY_NEEDED to 32 bytes, as Rijndael can operate with
- 256 bit (=32 byte) keys. Of course seeding with more entropy bytes
- than this minimum value is recommended.
- [Lutz Jaenicke]
-
- *) New random seeder for OpenVMS, using the system process statistics
- that are easily reachable.
- [Richard Levitte]
-
- *) Windows apparently can't transparently handle global
- variables defined in DLLs. Initialisations such as:
-
- const ASN1_ITEM *it = &ASN1_INTEGER_it;
-
- won't compile. This is used by the any applications that need to
- declare their own ASN1 modules. This was fixed by adding the option
- EXPORT_VAR_AS_FN to all Win32 platforms, although this isn't strictly
- needed for static libraries under Win32.
- [Steve Henson]
-
- *) New functions X509_PURPOSE_set() and X509_TRUST_set() to handle
- setting of purpose and trust fields. New X509_STORE trust and
- purpose functions and tidy up setting in other SSL functions.
- [Steve Henson]
-
- *) Add copies of X509_STORE_CTX fields and callbacks to X509_STORE
- structure. These are inherited by X509_STORE_CTX when it is
- initialised. This allows various defaults to be set in the
- X509_STORE structure (such as flags for CRL checking and custom
- purpose or trust settings) for functions which only use X509_STORE_CTX
- internally such as S/MIME.
-
- Modify X509_STORE_CTX_purpose_inherit() so it only sets purposes and
- trust settings if they are not set in X509_STORE. This allows X509_STORE
- purposes and trust (in S/MIME for example) to override any set by default.
-
- Add command line options for CRL checking to smime, s_client and s_server
- applications.
- [Steve Henson]
-
- *) Initial CRL based revocation checking. If the CRL checking flag(s)
- are set then the CRL is looked up in the X509_STORE structure and
- its validity and signature checked, then if the certificate is found
- in the CRL the verify fails with a revoked error.
-
- Various new CRL related callbacks added to X509_STORE_CTX structure.
-
- Command line options added to 'verify' application to support this.
-
- This needs some additional work, such as being able to handle multiple
- CRLs with different times, extension based lookup (rather than just
- by subject name) and ultimately more complete V2 CRL extension
- handling.
- [Steve Henson]
-
- *) Add a general user interface API (crypto/ui/). This is designed
- to replace things like des_read_password and friends (backward
- compatibility functions using this new API are provided).
- The purpose is to remove prompting functions from the DES code
- section as well as provide for prompting through dialog boxes in
- a window system and the like.
- [Richard Levitte]
-
- *) Add "ex_data" support to ENGINE so implementations can add state at a
- per-structure level rather than having to store it globally.
- [Geoff]
-
- *) Make it possible for ENGINE structures to be copied when retrieved by
- ENGINE_by_id() if the ENGINE specifies a new flag: ENGINE_FLAGS_BY_ID_COPY.
- This causes the "original" ENGINE structure to act like a template,
- analogous to the RSA vs. RSA_METHOD type of separation. Because of this
- operational state can be localised to each ENGINE structure, despite the
- fact they all share the same "methods". New ENGINE structures returned in
- this case have no functional references and the return value is the single
- structural reference. This matches the single structural reference returned
- by ENGINE_by_id() normally, when it is incremented on the pre-existing
- ENGINE structure.
- [Geoff]
-
- *) Fix ASN1 decoder when decoding type ANY and V_ASN1_OTHER: since this
- needs to match any other type at all we need to manually clear the
- tag cache.
- [Steve Henson]
-
- *) Changes to the "openssl engine" utility to include;
- - verbosity levels ('-v', '-vv', and '-vvv') that provide information
- about an ENGINE's available control commands.
- - executing control commands from command line arguments using the
- '-pre' and '-post' switches. '-post' is only used if '-t' is
- specified and the ENGINE is successfully initialised. The syntax for
- the individual commands are colon-separated, for example;
- openssl engine chil -pre FORK_CHECK:0 -pre SO_PATH:/lib/test.so
- [Geoff]
-
- *) New dynamic control command support for ENGINEs. ENGINEs can now
- declare their own commands (numbers), names (strings), descriptions,
- and input types for run-time discovery by calling applications. A
- subset of these commands are implicitly classed as "executable"
- depending on their input type, and only these can be invoked through
- the new string-based API function ENGINE_ctrl_cmd_string(). (Eg. this
- can be based on user input, config files, etc). The distinction is
- that "executable" commands cannot return anything other than a boolean
- result and can only support numeric or string input, whereas some
- discoverable commands may only be for direct use through
- ENGINE_ctrl(), eg. supporting the exchange of binary data, function
- pointers, or other custom uses. The "executable" commands are to
- support parameterisations of ENGINE behaviour that can be
- unambiguously defined by ENGINEs and used consistently across any
- OpenSSL-based application. Commands have been added to all the
- existing hardware-supporting ENGINEs, noticeably "SO_PATH" to allow
- control over shared-library paths without source code alterations.
- [Geoff]
-
- *) Changed all ENGINE implementations to dynamically allocate their
- ENGINEs rather than declaring them statically. Apart from this being
- necessary with the removal of the ENGINE_FLAGS_MALLOCED distinction,
- this also allows the implementations to compile without using the
- internal engine_int.h header.
- [Geoff]
-
- *) Minor adjustment to "rand" code. RAND_get_rand_method() now returns a
- 'const' value. Any code that should be able to modify a RAND_METHOD
- should already have non-const pointers to it (ie. they should only
- modify their own ones).
- [Geoff]
-
- *) Made a variety of little tweaks to the ENGINE code.
- - "atalla" and "ubsec" string definitions were moved from header files
- to C code. "nuron" string definitions were placed in variables
- rather than hard-coded - allowing parameterisation of these values
- later on via ctrl() commands.
- - Removed unused "#if 0"'d code.
- - Fixed engine list iteration code so it uses ENGINE_free() to release
- structural references.
- - Constified the RAND_METHOD element of ENGINE structures.
- - Constified various get/set functions as appropriate and added
- missing functions (including a catch-all ENGINE_cpy that duplicates
- all ENGINE values onto a new ENGINE except reference counts/state).
- - Removed NULL parameter checks in get/set functions. Setting a method
- or function to NULL is a way of cancelling out a previously set
- value. Passing a NULL ENGINE parameter is just plain stupid anyway
- and doesn't justify the extra error symbols and code.
- - Deprecate the ENGINE_FLAGS_MALLOCED define and move the area for
- flags from engine_int.h to engine.h.
- - Changed prototypes for ENGINE handler functions (init(), finish(),
- ctrl(), key-load functions, etc) to take an (ENGINE*) parameter.
- [Geoff]
-
- *) Implement binary inversion algorithm for BN_mod_inverse in addition
- to the algorithm using long division. The binary algorithm can be
- used only if the modulus is odd. On 32-bit systems, it is faster
- only for relatively small moduli (roughly 20-30% for 128-bit moduli,
- roughly 5-15% for 256-bit moduli), so we use it only for moduli
- up to 450 bits. In 64-bit environments, the binary algorithm
- appears to be advantageous for much longer moduli; here we use it
- for moduli up to 2048 bits.
- [Bodo Moeller]
-
- *) Rewrite CHOICE field setting in ASN1_item_ex_d2i(). The old code
- could not support the combine flag in choice fields.
- [Steve Henson]
-
- *) Add a 'copy_extensions' option to the 'ca' utility. This copies
- extensions from a certificate request to the certificate.
- [Steve Henson]
-
- *) Allow multiple 'certopt' and 'nameopt' options to be separated
- by commas. Add 'namopt' and 'certopt' options to the 'ca' config
- file: this allows the display of the certificate about to be
- signed to be customised, to allow certain fields to be included
- or excluded and extension details. The old system didn't display
- multicharacter strings properly, omitted fields not in the policy
- and couldn't display additional details such as extensions.
- [Steve Henson]
-
- *) Function EC_POINTs_mul for multiple scalar multiplication
- of an arbitrary number of elliptic curve points
- \sum scalars[i]*points[i],
- optionally including the generator defined for the EC_GROUP:
- scalar*generator + \sum scalars[i]*points[i].
-
- EC_POINT_mul is a simple wrapper function for the typical case
- that the point list has just one item (besides the optional
- generator).
- [Bodo Moeller]
-
- *) First EC_METHODs for curves over GF(p):
-
- EC_GFp_simple_method() uses the basic BN_mod_mul and BN_mod_sqr
- operations and provides various method functions that can also
- operate with faster implementations of modular arithmetic.
-
- EC_GFp_mont_method() reuses most functions that are part of
- EC_GFp_simple_method, but uses Montgomery arithmetic.
-
- [Bodo Moeller; point addition and point doubling
- implementation directly derived from source code provided by
- Lenka Fibikova <fibikova@exp-math.uni-essen.de>]
-
- *) Framework for elliptic curves (crypto/ec/ec.h, crypto/ec/ec_lcl.h,
- crypto/ec/ec_lib.c):
-
- Curves are EC_GROUP objects (with an optional group generator)
- based on EC_METHODs that are built into the library.
-
- Points are EC_POINT objects based on EC_GROUP objects.
-
- Most of the framework would be able to handle curves over arbitrary
- finite fields, but as there are no obvious types for fields other
- than GF(p), some functions are limited to that for now.
- [Bodo Moeller]
-
- *) Add the -HTTP option to s_server. It is similar to -WWW, but requires
- that the file contains a complete HTTP response.
- [Richard Levitte]
-
- *) Add the ec directory to mkdef.pl and mkfiles.pl. In mkdef.pl
- change the def and num file printf format specifier from "%-40sXXX"
- to "%-39s XXX". The latter will always guarantee a space after the
- field while the former will cause them to run together if the field
- is 40 of more characters long.
- [Steve Henson]
-
- *) Constify the cipher and digest 'method' functions and structures
- and modify related functions to take constant EVP_MD and EVP_CIPHER
- pointers.
- [Steve Henson]
-
- *) Hide BN_CTX structure details in bn_lcl.h instead of publishing them
- in <openssl/bn.h>. Also further increase BN_CTX_NUM to 32.
- [Bodo Moeller]
-
- *) Modify EVP_Digest*() routines so they now return values. Although the
- internal software routines can never fail additional hardware versions
- might.
- [Steve Henson]
-
- *) Clean up crypto/err/err.h and change some error codes to avoid conflicts:
-
- Previously ERR_R_FATAL was too small and coincided with ERR_LIB_PKCS7
- (= ERR_R_PKCS7_LIB); it is now 64 instead of 32.
-
- ASN1 error codes
- ERR_R_NESTED_ASN1_ERROR
- ...
- ERR_R_MISSING_ASN1_EOS
- were 4 .. 9, conflicting with
- ERR_LIB_RSA (= ERR_R_RSA_LIB)
- ...
- ERR_LIB_PEM (= ERR_R_PEM_LIB).
- They are now 58 .. 63 (i.e., just below ERR_R_FATAL).
-
- Add new error code 'ERR_R_INTERNAL_ERROR'.
- [Bodo Moeller]
-
- *) Don't overuse locks in crypto/err/err.c: For data retrieval, CRYPTO_r_lock
- suffices.
- [Bodo Moeller]
-
- *) New option '-subj arg' for 'openssl req' and 'openssl ca'. This
- sets the subject name for a new request or supersedes the
- subject name in a given request. Formats that can be parsed are
- 'CN=Some Name, OU=myOU, C=IT'
- and
- 'CN=Some Name/OU=myOU/C=IT'.
-
- Add options '-batch' and '-verbose' to 'openssl req'.
- [Massimiliano Pala <madwolf@hackmasters.net>]
-
- *) Introduce the possibility to access global variables through
- functions on platform were that's the best way to handle exporting
- global variables in shared libraries. To enable this functionality,
- one must configure with "EXPORT_VAR_AS_FN" or defined the C macro
- "OPENSSL_EXPORT_VAR_AS_FUNCTION" in crypto/opensslconf.h (the latter
- is normally done by Configure or something similar).
-
- To implement a global variable, use the macro OPENSSL_IMPLEMENT_GLOBAL
- in the source file (foo.c) like this:
-
- OPENSSL_IMPLEMENT_GLOBAL(int,foo)=1;
- OPENSSL_IMPLEMENT_GLOBAL(double,bar);
-
- To declare a global variable, use the macros OPENSSL_DECLARE_GLOBAL
- and OPENSSL_GLOBAL_REF in the header file (foo.h) like this:
-
- OPENSSL_DECLARE_GLOBAL(int,foo);
- #define foo OPENSSL_GLOBAL_REF(foo)
- OPENSSL_DECLARE_GLOBAL(double,bar);
- #define bar OPENSSL_GLOBAL_REF(bar)
-
- The #defines are very important, and therefore so is including the
- header file everywhere where the defined globals are used.
-
- The macro OPENSSL_EXPORT_VAR_AS_FUNCTION also affects the definition
- of ASN.1 items, but that structure is a bit different.
-
- The largest change is in util/mkdef.pl which has been enhanced with
- better and easier to understand logic to choose which symbols should
- go into the Windows .def files as well as a number of fixes and code
- cleanup (among others, algorithm keywords are now sorted
- lexicographically to avoid constant rewrites).
- [Richard Levitte]
-
- *) In BN_div() keep a copy of the sign of 'num' before writing the
- result to 'rm' because if rm==num the value will be overwritten
- and produce the wrong result if 'num' is negative: this caused
- problems with BN_mod() and BN_nnmod().
- [Steve Henson]
-
- *) Function OCSP_request_verify(). This checks the signature on an
- OCSP request and verifies the signer certificate. The signer
- certificate is just checked for a generic purpose and OCSP request
- trust settings.
- [Steve Henson]
-
- *) Add OCSP_check_validity() function to check the validity of OCSP
- responses. OCSP responses are prepared in real time and may only
- be a few seconds old. Simply checking that the current time lies
- between thisUpdate and nextUpdate max reject otherwise valid responses
- caused by either OCSP responder or client clock inaccuracy. Instead
- we allow thisUpdate and nextUpdate to fall within a certain period of
- the current time. The age of the response can also optionally be
- checked. Two new options -validity_period and -status_age added to
- ocsp utility.
- [Steve Henson]
-
- *) If signature or public key algorithm is unrecognized print out its
- OID rather that just UNKNOWN.
- [Steve Henson]
-
- *) Change OCSP_cert_to_id() to tolerate a NULL subject certificate and
- OCSP_cert_id_new() a NULL serialNumber. This allows a partial certificate
- ID to be generated from the issuer certificate alone which can then be
- passed to OCSP_id_issuer_cmp().
- [Steve Henson]
-
- *) New compilation option ASN1_ITEM_FUNCTIONS. This causes the new
- ASN1 modules to export functions returning ASN1_ITEM pointers
- instead of the ASN1_ITEM structures themselves. This adds several
- new macros which allow the underlying ASN1 function/structure to
- be accessed transparently. As a result code should not use ASN1_ITEM
- references directly (such as &X509_it) but instead use the relevant
- macros (such as ASN1_ITEM_rptr(X509)). This option is to allow
- use of the new ASN1 code on platforms where exporting structures
- is problematical (for example in shared libraries) but exporting
- functions returning pointers to structures is not.
- [Steve Henson]
-
- *) Add support for overriding the generation of SSL/TLS session IDs.
- These callbacks can be registered either in an SSL_CTX or per SSL.
- The purpose of this is to allow applications to control, if they wish,
- the arbitrary values chosen for use as session IDs, particularly as it
- can be useful for session caching in multiple-server environments. A
- command-line switch for testing this (and any client code that wishes
- to use such a feature) has been added to "s_server".
- [Geoff Thorpe, Lutz Jaenicke]
-
- *) Modify mkdef.pl to recognise and parse preprocessor conditionals
- of the form '#if defined(...) || defined(...) || ...' and
- '#if !defined(...) && !defined(...) && ...'. This also avoids
- the growing number of special cases it was previously handling.
- [Richard Levitte]
-
- *) Make all configuration macros available for application by making
- sure they are available in opensslconf.h, by giving them names starting
- with "OPENSSL_" to avoid conflicts with other packages and by making
- sure e_os2.h will cover all platform-specific cases together with
- opensslconf.h.
- Additionally, it is now possible to define configuration/platform-
- specific names (called "system identities"). In the C code, these
- are prefixed with "OPENSSL_SYSNAME_". e_os2.h will create another
- macro with the name beginning with "OPENSSL_SYS_", which is determined
- from "OPENSSL_SYSNAME_*" or compiler-specific macros depending on
- what is available.
- [Richard Levitte]
-
- *) New option -set_serial to 'req' and 'x509' this allows the serial
- number to use to be specified on the command line. Previously self
- signed certificates were hard coded with serial number 0 and the
- CA options of 'x509' had to use a serial number in a file which was
- auto incremented.
- [Steve Henson]
-
- *) New options to 'ca' utility to support V2 CRL entry extensions.
- Currently CRL reason, invalidity date and hold instruction are
- supported. Add new CRL extensions to V3 code and some new objects.
- [Steve Henson]
-
- *) New function EVP_CIPHER_CTX_set_padding() this is used to
- disable standard block padding (aka PKCS#5 padding) in the EVP
- API, which was previously mandatory. This means that the data is
- not padded in any way and so the total length much be a multiple
- of the block size, otherwise an error occurs.
- [Steve Henson]
-
- *) Initial (incomplete) OCSP SSL support.
- [Steve Henson]
-
- *) New function OCSP_parse_url(). This splits up a URL into its host,
- port and path components: primarily to parse OCSP URLs. New -url
- option to ocsp utility.
- [Steve Henson]
-
- *) New nonce behavior. The return value of OCSP_check_nonce() now
- reflects the various checks performed. Applications can decide
- whether to tolerate certain situations such as an absent nonce
- in a response when one was present in a request: the ocsp application
- just prints out a warning. New function OCSP_add1_basic_nonce()
- this is to allow responders to include a nonce in a response even if
- the request is nonce-less.
- [Steve Henson]
-
- *) Disable stdin buffering in load_cert (apps/apps.c) so that no certs are
- skipped when using openssl x509 multiple times on a single input file,
- e.g. "(openssl x509 -out cert1; openssl x509 -out cert2) <certs".
- [Bodo Moeller]
-
- *) Make ASN1_UTCTIME_set_string() and ASN1_GENERALIZEDTIME_set_string()
- set string type: to handle setting ASN1_TIME structures. Fix ca
- utility to correctly initialize revocation date of CRLs.
- [Steve Henson]
-
- *) New option SSL_OP_CIPHER_SERVER_PREFERENCE allows the server to override
- the clients preferred ciphersuites and rather use its own preferences.
- Should help to work around M$ SGC (Server Gated Cryptography) bug in
- Internet Explorer by ensuring unchanged hash method during stepup.
- (Also replaces the broken/deactivated SSL_OP_NON_EXPORT_FIRST option.)
- [Lutz Jaenicke]
-
- *) Make mkdef.pl recognise all DECLARE_ASN1 macros, change rijndael
- to aes and add a new 'exist' option to print out symbols that don't
- appear to exist.
- [Steve Henson]
-
- *) Additional options to ocsp utility to allow flags to be set and
- additional certificates supplied.
- [Steve Henson]
-
- *) Add the option -VAfile to 'openssl ocsp', so the user can give the
- OCSP client a number of certificate to only verify the response
- signature against.
- [Richard Levitte]
-
- *) Update Rijndael code to version 3.0 and change EVP AES ciphers to
- handle the new API. Currently only ECB, CBC modes supported. Add new
- AES OIDs.
-
- Add TLS AES ciphersuites as described in RFC3268, "Advanced
- Encryption Standard (AES) Ciphersuites for Transport Layer
- Security (TLS)". (In beta versions of OpenSSL 0.9.7, these were
- not enabled by default and were not part of the "ALL" ciphersuite
- alias because they were not yet official; they could be
- explicitly requested by specifying the "AESdraft" ciphersuite
- group alias. In the final release of OpenSSL 0.9.7, the group
- alias is called "AES" and is part of "ALL".)
- [Ben Laurie, Steve Henson, Bodo Moeller]
-
- *) New function OCSP_copy_nonce() to copy nonce value (if present) from
- request to response.
- [Steve Henson]
-
- *) Functions for OCSP responders. OCSP_request_onereq_count(),
- OCSP_request_onereq_get0(), OCSP_onereq_get0_id() and OCSP_id_get0_info()
- extract information from a certificate request. OCSP_response_create()
- creates a response and optionally adds a basic response structure.
- OCSP_basic_add1_status() adds a complete single response to a basic
- response and returns the OCSP_SINGLERESP structure just added (to allow
- extensions to be included for example). OCSP_basic_add1_cert() adds a
- certificate to a basic response and OCSP_basic_sign() signs a basic
- response with various flags. New helper functions ASN1_TIME_check()
- (checks validity of ASN1_TIME structure) and ASN1_TIME_to_generalizedtime()
- (converts ASN1_TIME to GeneralizedTime).
- [Steve Henson]
-
- *) Various new functions. EVP_Digest() combines EVP_Digest{Init,Update,Final}()
- in a single operation. X509_get0_pubkey_bitstr() extracts the public_key
- structure from a certificate. X509_pubkey_digest() digests the public_key
- contents: this is used in various key identifiers.
- [Steve Henson]
-
- *) Make sk_sort() tolerate a NULL argument.
- [Steve Henson reported by Massimiliano Pala <madwolf@comune.modena.it>]
-
- *) New OCSP verify flag OCSP_TRUSTOTHER. When set the "other" certificates
- passed by the function are trusted implicitly. If any of them signed the
- response then it is assumed to be valid and is not verified.
- [Steve Henson]
-
- *) In PKCS7_set_type() initialise content_type in PKCS7_ENC_CONTENT
- to data. This was previously part of the PKCS7 ASN1 code. This
- was causing problems with OpenSSL created PKCS#12 and PKCS#7 structures.
- [Steve Henson, reported by Kenneth R. Robinette
- <support@securenetterm.com>]
-
- *) Add CRYPTO_push_info() and CRYPTO_pop_info() calls to new ASN1
- routines: without these tracing memory leaks is very painful.
- Fix leaks in PKCS12 and PKCS7 routines.
- [Steve Henson]
-
- *) Make X509_time_adj() cope with the new behaviour of ASN1_TIME_new().
- Previously it initialised the 'type' argument to V_ASN1_UTCTIME which
- effectively meant GeneralizedTime would never be used. Now it
- is initialised to -1 but X509_time_adj() now has to check the value
- and use ASN1_TIME_set() if the value is not V_ASN1_UTCTIME or
- V_ASN1_GENERALIZEDTIME, without this it always uses GeneralizedTime.
- [Steve Henson, reported by Kenneth R. Robinette
- <support@securenetterm.com>]
-
- *) Fixes to BN_to_ASN1_INTEGER when bn is zero. This would previously
- result in a zero length in the ASN1_INTEGER structure which was
- not consistent with the structure when d2i_ASN1_INTEGER() was used
- and would cause ASN1_INTEGER_cmp() to fail. Enhance s2i_ASN1_INTEGER()
- to cope with hex and negative integers. Fix bug in i2a_ASN1_INTEGER()
- where it did not print out a minus for negative ASN1_INTEGER.
- [Steve Henson]
-
- *) Add summary printout to ocsp utility. The various functions which
- convert status values to strings have been renamed to:
- OCSP_response_status_str(), OCSP_cert_status_str() and
- OCSP_crl_reason_str() and are no longer static. New options
- to verify nonce values and to disable verification. OCSP response
- printout format cleaned up.
- [Steve Henson]
-
- *) Add additional OCSP certificate checks. These are those specified
- in RFC2560. This consists of two separate checks: the CA of the
- certificate being checked must either be the OCSP signer certificate
- or the issuer of the OCSP signer certificate. In the latter case the
- OCSP signer certificate must contain the OCSP signing extended key
- usage. This check is performed by attempting to match the OCSP
- signer or the OCSP signer CA to the issuerNameHash and issuerKeyHash
- in the OCSP_CERTID structures of the response.
- [Steve Henson]
-
- *) Initial OCSP certificate verification added to OCSP_basic_verify()
- and related routines. This uses the standard OpenSSL certificate
- verify routines to perform initial checks (just CA validity) and
- to obtain the certificate chain. Then additional checks will be
- performed on the chain. Currently the root CA is checked to see
- if it is explicitly trusted for OCSP signing. This is used to set
- a root CA as a global signing root: that is any certificate that
- chains to that CA is an acceptable OCSP signing certificate.
- [Steve Henson]
-
- *) New '-extfile ...' option to 'openssl ca' for reading X.509v3
- extensions from a separate configuration file.
- As when reading extensions from the main configuration file,
- the '-extensions ...' option may be used for specifying the
- section to use.
- [Massimiliano Pala <madwolf@comune.modena.it>]
-
- *) New OCSP utility. Allows OCSP requests to be generated or
- read. The request can be sent to a responder and the output
- parsed, outputted or printed in text form. Not complete yet:
- still needs to check the OCSP response validity.
- [Steve Henson]
-
- *) New subcommands for 'openssl ca':
- 'openssl ca -status <serial>' prints the status of the cert with
- the given serial number (according to the index file).
- 'openssl ca -updatedb' updates the expiry status of certificates
- in the index file.
- [Massimiliano Pala <madwolf@comune.modena.it>]
-
- *) New '-newreq-nodes' command option to CA.pl. This is like
- '-newreq', but calls 'openssl req' with the '-nodes' option
- so that the resulting key is not encrypted.
- [Damien Miller <djm@mindrot.org>]
-
- *) New configuration for the GNU Hurd.
- [Jonathan Bartlett <johnnyb@wolfram.com> via Richard Levitte]
-
- *) Initial code to implement OCSP basic response verify. This
- is currently incomplete. Currently just finds the signer's
- certificate and verifies the signature on the response.
- [Steve Henson]
-
- *) New SSLeay_version code SSLEAY_DIR to determine the compiled-in
- value of OPENSSLDIR. This is available via the new '-d' option
- to 'openssl version', and is also included in 'openssl version -a'.
- [Bodo Moeller]
-
- *) Allowing defining memory allocation callbacks that will be given
- file name and line number information in additional arguments
- (a const char* and an int). The basic functionality remains, as
- well as the original possibility to just replace malloc(),
- realloc() and free() by functions that do not know about these
- additional arguments. To register and find out the current
- settings for extended allocation functions, the following
- functions are provided:
-
- CRYPTO_set_mem_ex_functions
- CRYPTO_set_locked_mem_ex_functions
- CRYPTO_get_mem_ex_functions
- CRYPTO_get_locked_mem_ex_functions
-
- These work the same way as CRYPTO_set_mem_functions and friends.
- CRYPTO_get_[locked_]mem_functions now writes 0 where such an
- extended allocation function is enabled.
- Similarly, CRYPTO_get_[locked_]mem_ex_functions writes 0 where
- a conventional allocation function is enabled.
- [Richard Levitte, Bodo Moeller]
-
- *) Finish off removing the remaining LHASH function pointer casts.
- There should no longer be any prototype-casting required when using
- the LHASH abstraction, and any casts that remain are "bugs". See
- the callback types and macros at the head of lhash.h for details
- (and "OBJ_cleanup" in crypto/objects/obj_dat.c as an example).
- [Geoff Thorpe]
-
- *) Add automatic query of EGD sockets in RAND_poll() for the unix variant.
- If /dev/[u]random devices are not available or do not return enough
- entropy, EGD style sockets (served by EGD or PRNGD) will automatically
- be queried.
- The locations /var/run/egd-pool, /dev/egd-pool, /etc/egd-pool, and
- /etc/entropy will be queried once each in this sequence, querying stops
- when enough entropy was collected without querying more sockets.
- [Lutz Jaenicke]
-
- *) Change the Unix RAND_poll() variant to be able to poll several
- random devices, as specified by DEVRANDOM, until a sufficient amount
- of data has been collected. We spend at most 10 ms on each file
- (select timeout) and read in non-blocking mode. DEVRANDOM now
- defaults to the list "/dev/urandom", "/dev/random", "/dev/srandom"
- (previously it was just the string "/dev/urandom"), so on typical
- platforms the 10 ms delay will never occur.
- Also separate out the Unix variant to its own file, rand_unix.c.
- For VMS, there's a currently-empty rand_vms.c.
- [Richard Levitte]
-
- *) Move OCSP client related routines to ocsp_cl.c. These
- provide utility functions which an application needing
- to issue a request to an OCSP responder and analyse the
- response will typically need: as opposed to those which an
- OCSP responder itself would need which will be added later.
-
- OCSP_request_sign() signs an OCSP request with an API similar
- to PKCS7_sign(). OCSP_response_status() returns status of OCSP
- response. OCSP_response_get1_basic() extracts basic response
- from response. OCSP_resp_find_status(): finds and extracts status
- information from an OCSP_CERTID structure (which will be created
- when the request structure is built). These are built from lower
- level functions which work on OCSP_SINGLERESP structures but
- won't normally be used unless the application wishes to examine
- extensions in the OCSP response for example.
-
- Replace nonce routines with a pair of functions.
- OCSP_request_add1_nonce() adds a nonce value and optionally
- generates a random value. OCSP_check_nonce() checks the
- validity of the nonce in an OCSP response.
- [Steve Henson]
-
- *) Change function OCSP_request_add() to OCSP_request_add0_id().
- This doesn't copy the supplied OCSP_CERTID and avoids the
- need to free up the newly created id. Change return type
- to OCSP_ONEREQ to return the internal OCSP_ONEREQ structure.
- This can then be used to add extensions to the request.
- Deleted OCSP_request_new(), since most of its functionality
- is now in OCSP_REQUEST_new() (and the case insensitive name
- clash) apart from the ability to set the request name which
- will be added elsewhere.
- [Steve Henson]
-
- *) Update OCSP API. Remove obsolete extensions argument from
- various functions. Extensions are now handled using the new
- OCSP extension code. New simple OCSP HTTP function which
- can be used to send requests and parse the response.
- [Steve Henson]
-
- *) Fix the PKCS#7 (S/MIME) code to work with new ASN1. Two new
- ASN1_ITEM structures help with sign and verify. PKCS7_ATTR_SIGN
- uses the special reorder version of SET OF to sort the attributes
- and reorder them to match the encoded order. This resolves a long
- standing problem: a verify on a PKCS7 structure just after signing
- it used to fail because the attribute order did not match the
- encoded order. PKCS7_ATTR_VERIFY does not reorder the attributes:
- it uses the received order. This is necessary to tolerate some broken
- software that does not order SET OF. This is handled by encoding
- as a SEQUENCE OF but using implicit tagging (with UNIVERSAL class)
- to produce the required SET OF.
- [Steve Henson]
-
- *) Have mk1mf.pl generate the macros OPENSSL_BUILD_SHLIBCRYPTO and
- OPENSSL_BUILD_SHLIBSSL and use them appropriately in the header
- files to get correct declarations of the ASN.1 item variables.
- [Richard Levitte]
-
- *) Rewrite of PKCS#12 code to use new ASN1 functionality. Replace many
- PKCS#12 macros with real functions. Fix two unrelated ASN1 bugs:
- asn1_check_tlen() would sometimes attempt to use 'ctx' when it was
- NULL and ASN1_TYPE was not dereferenced properly in asn1_ex_c2i().
- New ASN1 macro: DECLARE_ASN1_ITEM() which just declares the relevant
- ASN1_ITEM and no wrapper functions.
- [Steve Henson]
-
- *) New functions or ASN1_item_d2i_fp() and ASN1_item_d2i_bio(). These
- replace the old function pointer based I/O routines. Change most of
- the *_d2i_bio() and *_d2i_fp() functions to use these.
- [Steve Henson]
-
- *) Enhance mkdef.pl to be more accepting about spacing in C preprocessor
- lines, recognize more "algorithms" that can be deselected, and make
- it complain about algorithm deselection that isn't recognised.
- [Richard Levitte]
-
- *) New ASN1 functions to handle dup, sign, verify, digest, pack and
- unpack operations in terms of ASN1_ITEM. Modify existing wrappers
- to use new functions. Add NO_ASN1_OLD which can be set to remove
- some old style ASN1 functions: this can be used to determine if old
- code will still work when these eventually go away.
- [Steve Henson]
-
- *) New extension functions for OCSP structures, these follow the
- same conventions as certificates and CRLs.
- [Steve Henson]
-
- *) New function X509V3_add1_i2d(). This automatically encodes and
- adds an extension. Its behaviour can be customised with various
- flags to append, replace or delete. Various wrappers added for
- certificates and CRLs.
- [Steve Henson]
-
- *) Fix to avoid calling the underlying ASN1 print routine when
- an extension cannot be parsed. Correct a typo in the
- OCSP_SERVICELOC extension. Tidy up print OCSP format.
- [Steve Henson]
-
- *) Make mkdef.pl parse some of the ASN1 macros and add appropriate
- entries for variables.
- [Steve Henson]
-
- *) Add functionality to apps/openssl.c for detecting locking
- problems: As the program is single-threaded, all we have
- to do is register a locking callback using an array for
- storing which locks are currently held by the program.
- [Bodo Moeller]
-
- *) Use a lock around the call to CRYPTO_get_ex_new_index() in
- SSL_get_ex_data_X509_STORE_idx(), which is used in
- ssl_verify_cert_chain() and thus can be called at any time
- during TLS/SSL handshakes so that thread-safety is essential.
- Unfortunately, the ex_data design is not at all suited
- for multi-threaded use, so it probably should be abolished.
- [Bodo Moeller]
-
- *) Added Broadcom "ubsec" ENGINE to OpenSSL.
- [Broadcom, tweaked and integrated by Geoff Thorpe]
-
- *) Move common extension printing code to new function
- X509V3_print_extensions(). Reorganise OCSP print routines and
- implement some needed OCSP ASN1 functions. Add OCSP extensions.
- [Steve Henson]
-
- *) New function X509_signature_print() to remove duplication in some
- print routines.
- [Steve Henson]
-
- *) Add a special meaning when SET OF and SEQUENCE OF flags are both
- set (this was treated exactly the same as SET OF previously). This
- is used to reorder the STACK representing the structure to match the
- encoding. This will be used to get round a problem where a PKCS7
- structure which was signed could not be verified because the STACK
- order did not reflect the encoded order.
- [Steve Henson]
-
- *) Reimplement the OCSP ASN1 module using the new code.
- [Steve Henson]
-
- *) Update the X509V3 code to permit the use of an ASN1_ITEM structure
- for its ASN1 operations. The old style function pointers still exist
- for now but they will eventually go away.
- [Steve Henson]
-
- *) Merge in replacement ASN1 code from the ASN1 branch. This almost
- completely replaces the old ASN1 functionality with a table driven
- encoder and decoder which interprets an ASN1_ITEM structure describing
- the ASN1 module. Compatibility with the existing ASN1 API (i2d,d2i) is
- largely maintained. Almost all of the old asn1_mac.h macro based ASN1
- has also been converted to the new form.
- [Steve Henson]
-
- *) Change BN_mod_exp_recp so that negative moduli are tolerated
- (the sign is ignored). Similarly, ignore the sign in BN_MONT_CTX_set
- so that BN_mod_exp_mont and BN_mod_exp_mont_word work
- for negative moduli.
- [Bodo Moeller]
-
- *) Fix BN_uadd and BN_usub: Always return non-negative results instead
- of not touching the result's sign bit.
- [Bodo Moeller]
-
- *) BN_div bugfix: If the result is 0, the sign (res->neg) must not be
- set.
- [Bodo Moeller]
-
- *) Changed the LHASH code to use prototypes for callbacks, and created
- macros to declare and implement thin (optionally static) functions
- that provide type-safety and avoid function pointer casting for the
- type-specific callbacks.
- [Geoff Thorpe]
-
- *) Added Kerberos Cipher Suites to be used with TLS, as written in
- RFC 2712.
- [Veers Staats <staatsvr@asc.hpc.mil>,
- Jeffrey Altman <jaltman@columbia.edu>, via Richard Levitte]
-
- *) Reformat the FAQ so the different questions and answers can be divided
- in sections depending on the subject.
- [Richard Levitte]
-
- *) Have the zlib compression code load ZLIB.DLL dynamically under
- Windows.
- [Richard Levitte]
-
- *) New function BN_mod_sqrt for computing square roots modulo a prime
- (using the probabilistic Tonelli-Shanks algorithm unless
- p == 3 (mod 4) or p == 5 (mod 8), which are cases that can
- be handled deterministically).
- [Lenka Fibikova <fibikova@exp-math.uni-essen.de>, Bodo Moeller]
-
- *) Make BN_mod_inverse faster by explicitly handling small quotients
- in the Euclid loop. (Speed gain about 20% for small moduli [256 or
- 512 bits], about 30% for larger ones [1024 or 2048 bits].)
- [Bodo Moeller]
-
- *) New function BN_kronecker.
- [Bodo Moeller]
-
- *) Fix BN_gcd so that it works on negative inputs; the result is
- positive unless both parameters are zero.
- Previously something reasonably close to an infinite loop was
- possible because numbers could be growing instead of shrinking
- in the implementation of Euclid's algorithm.
- [Bodo Moeller]
-
- *) Fix BN_is_word() and BN_is_one() macros to take into account the
- sign of the number in question.
-
- Fix BN_is_word(a,w) to work correctly for w == 0.
-
- The old BN_is_word(a,w) macro is now called BN_abs_is_word(a,w)
- because its test if the absolute value of 'a' equals 'w'.
- Note that BN_abs_is_word does *not* handle w == 0 reliably;
- it exists mostly for use in the implementations of BN_is_zero(),
- BN_is_one(), and BN_is_word().
- [Bodo Moeller]
-
- *) New function BN_swap.
- [Bodo Moeller]
-
- *) Use BN_nnmod instead of BN_mod in crypto/bn/bn_exp.c so that
- the exponentiation functions are more likely to produce reasonable
- results on negative inputs.
- [Bodo Moeller]
-
- *) Change BN_mod_mul so that the result is always non-negative.
- Previously, it could be negative if one of the factors was negative;
- I don't think anyone really wanted that behaviour.
- [Bodo Moeller]
-
- *) Move BN_mod_... functions into new file crypto/bn/bn_mod.c
- (except for exponentiation, which stays in crypto/bn/bn_exp.c,
- and BN_mod_mul_reciprocal, which stays in crypto/bn/bn_recp.c)
- and add new functions:
-
- BN_nnmod
- BN_mod_sqr
- BN_mod_add
- BN_mod_add_quick
- BN_mod_sub
- BN_mod_sub_quick
- BN_mod_lshift1
- BN_mod_lshift1_quick
- BN_mod_lshift
- BN_mod_lshift_quick
-
- These functions always generate non-negative results.
-
- BN_nnmod otherwise is like BN_mod (if BN_mod computes a remainder r
- such that |m| < r < 0, BN_nnmod will output rem + |m| instead).
-
- BN_mod_XXX_quick(r, a, [b,] m) generates the same result as
- BN_mod_XXX(r, a, [b,] m, ctx), but requires that a [and b]
- be reduced modulo m.
- [Lenka Fibikova <fibikova@exp-math.uni-essen.de>, Bodo Moeller]
-
-#if 0
- The following entry accidentally appeared in the CHANGES file
- distributed with OpenSSL 0.9.7. The modifications described in
- it do *not* apply to OpenSSL 0.9.7.
-
- *) Remove a few calls to bn_wexpand() in BN_sqr() (the one in there
- was actually never needed) and in BN_mul(). The removal in BN_mul()
- required a small change in bn_mul_part_recursive() and the addition
- of the functions bn_cmp_part_words(), bn_sub_part_words() and
- bn_add_part_words(), which do the same thing as bn_cmp_words(),
- bn_sub_words() and bn_add_words() except they take arrays with
- differing sizes.
- [Richard Levitte]
-#endif
-
- *) In 'openssl passwd', verify passwords read from the terminal
- unless the '-salt' option is used (which usually means that
- verification would just waste user's time since the resulting
- hash is going to be compared with some given password hash)
- or the new '-noverify' option is used.
-
- This is an incompatible change, but it does not affect
- non-interactive use of 'openssl passwd' (passwords on the command
- line, '-stdin' option, '-in ...' option) and thus should not
- cause any problems.
- [Bodo Moeller]
-
- *) Remove all references to RSAref, since there's no more need for it.
- [Richard Levitte]
-
- *) Make DSO load along a path given through an environment variable
- (SHLIB_PATH) with shl_load().
- [Richard Levitte]
-
- *) Constify the ENGINE code as a result of BIGNUM constification.
- Also constify the RSA code and most things related to it. In a
- few places, most notable in the depth of the ASN.1 code, ugly
- casts back to non-const were required (to be solved at a later
- time)
- [Richard Levitte]
-
- *) Make it so the openssl application has all engines loaded by default.
- [Richard Levitte]
-
- *) Constify the BIGNUM routines a little more.
- [Richard Levitte]
-
- *) Add the following functions:
-
- ENGINE_load_cswift()
- ENGINE_load_chil()
- ENGINE_load_atalla()
- ENGINE_load_nuron()
- ENGINE_load_builtin_engines()
-
- That way, an application can itself choose if external engines that
- are built-in in OpenSSL shall ever be used or not. The benefit is
- that applications won't have to be linked with libdl or other dso
- libraries unless it's really needed.
-
- Changed 'openssl engine' to load all engines on demand.
- Changed the engine header files to avoid the duplication of some
- declarations (they differed!).
- [Richard Levitte]
-
- *) 'openssl engine' can now list capabilities.
- [Richard Levitte]
-
- *) Better error reporting in 'openssl engine'.
- [Richard Levitte]
-
- *) Never call load_dh_param(NULL) in s_server.
- [Bodo Moeller]
-
- *) Add engine application. It can currently list engines by name and
- identity, and test if they are actually available.
- [Richard Levitte]
-
- *) Improve RPM specification file by forcing symbolic linking and making
- sure the installed documentation is also owned by root.root.
- [Damien Miller <djm@mindrot.org>]
-
- *) Give the OpenSSL applications more possibilities to make use of
- keys (public as well as private) handled by engines.
- [Richard Levitte]
-
- *) Add OCSP code that comes from CertCo.
- [Richard Levitte]
-
- *) Add VMS support for the Rijndael code.
- [Richard Levitte]
-
- *) Added untested support for Nuron crypto accelerator.
- [Ben Laurie]
-
- *) Add support for external cryptographic devices. This code was
- previously distributed separately as the "engine" branch.
- [Geoff Thorpe, Richard Levitte]
-
- *) Rework the filename-translation in the DSO code. It is now possible to
- have far greater control over how a "name" is turned into a filename
- depending on the operating environment and any oddities about the
- different shared library filenames on each system.
- [Geoff Thorpe]
-
- *) Support threads on FreeBSD-elf in Configure.
- [Richard Levitte]
-
- *) Fix for SHA1 assembly problem with MASM: it produces
- warnings about corrupt line number information when assembling
- with debugging information. This is caused by the overlapping
- of two sections.
- [Bernd Matthes <mainbug@celocom.de>, Steve Henson]
-
- *) NCONF changes.
- NCONF_get_number() has no error checking at all. As a replacement,
- NCONF_get_number_e() is defined (_e for "error checking") and is
- promoted strongly. The old NCONF_get_number is kept around for
- binary backward compatibility.
- Make it possible for methods to load from something other than a BIO,
- by providing a function pointer that is given a name instead of a BIO.
- For example, this could be used to load configuration data from an
- LDAP server.
- [Richard Levitte]
-
- *) Fix for non blocking accept BIOs. Added new I/O special reason
- BIO_RR_ACCEPT to cover this case. Previously use of accept BIOs
- with non blocking I/O was not possible because no retry code was
- implemented. Also added new SSL code SSL_WANT_ACCEPT to cover
- this case.
- [Steve Henson]
-
- *) Added the beginnings of Rijndael support.
- [Ben Laurie]
-
- *) Fix for bug in DirectoryString mask setting. Add support for
- X509_NAME_print_ex() in 'req' and X509_print_ex() function
- to allow certificate printing to more controllable, additional
- 'certopt' option to 'x509' to allow new printing options to be
- set.
- [Steve Henson]
-
- *) Clean old EAY MD5 hack from e_os.h.
- [Richard Levitte]
-
- Changes between 0.9.6l and 0.9.6m [17 Mar 2004]
-
- *) Fix null-pointer assignment in do_change_cipher_spec() revealed
- by using the Codenomicon TLS Test Tool (CVE-2004-0079)
- [Joe Orton, Steve Henson]
-
- Changes between 0.9.6k and 0.9.6l [04 Nov 2003]
-
- *) Fix additional bug revealed by the NISCC test suite:
-
- Stop bug triggering large recursion when presented with
- certain ASN.1 tags (CVE-2003-0851)
- [Steve Henson]
-
- Changes between 0.9.6j and 0.9.6k [30 Sep 2003]
-
- *) Fix various bugs revealed by running the NISCC test suite:
-
- Stop out of bounds reads in the ASN1 code when presented with
- invalid tags (CVE-2003-0543 and CVE-2003-0544).
-
- If verify callback ignores invalid public key errors don't try to check
- certificate signature with the NULL public key.
-
- [Steve Henson]
-
- *) In ssl3_accept() (ssl/s3_srvr.c) only accept a client certificate
- if the server requested one: as stated in TLS 1.0 and SSL 3.0
- specifications.
- [Steve Henson]
-
- *) In ssl3_get_client_hello() (ssl/s3_srvr.c), tolerate additional
- extra data after the compression methods not only for TLS 1.0
- but also for SSL 3.0 (as required by the specification).
- [Bodo Moeller; problem pointed out by Matthias Loepfe]
-
- *) Change X509_certificate_type() to mark the key as exported/exportable
- when it's 512 *bits* long, not 512 bytes.
- [Richard Levitte]
-
- Changes between 0.9.6i and 0.9.6j [10 Apr 2003]
-
- *) Countermeasure against the Klima-Pokorny-Rosa extension of
- Bleichbacher's attack on PKCS #1 v1.5 padding: treat
- a protocol version number mismatch like a decryption error
- in ssl3_get_client_key_exchange (ssl/s3_srvr.c).
- [Bodo Moeller]
-
- *) Turn on RSA blinding by default in the default implementation
- to avoid a timing attack. Applications that don't want it can call
- RSA_blinding_off() or use the new flag RSA_FLAG_NO_BLINDING.
- They would be ill-advised to do so in most cases.
- [Ben Laurie, Steve Henson, Geoff Thorpe, Bodo Moeller]
-
- *) Change RSA blinding code so that it works when the PRNG is not
- seeded (in this case, the secret RSA exponent is abused as
- an unpredictable seed -- if it is not unpredictable, there
- is no point in blinding anyway). Make RSA blinding thread-safe
- by remembering the creator's thread ID in rsa->blinding and
- having all other threads use local one-time blinding factors
- (this requires more computation than sharing rsa->blinding, but
- avoids excessive locking; and if an RSA object is not shared
- between threads, blinding will still be very fast).
- [Bodo Moeller]
-
- Changes between 0.9.6h and 0.9.6i [19 Feb 2003]
-
- *) In ssl3_get_record (ssl/s3_pkt.c), minimize information leaked
- via timing by performing a MAC computation even if incorrect
- block cipher padding has been found. This is a countermeasure
- against active attacks where the attacker has to distinguish
- between bad padding and a MAC verification error. (CVE-2003-0078)
-
- [Bodo Moeller; problem pointed out by Brice Canvel (EPFL),
- Alain Hiltgen (UBS), Serge Vaudenay (EPFL), and
- Martin Vuagnoux (EPFL, Ilion)]
-
- Changes between 0.9.6g and 0.9.6h [5 Dec 2002]
-
- *) New function OPENSSL_cleanse(), which is used to cleanse a section of
- memory from its contents. This is done with a counter that will
- place alternating values in each byte. This can be used to solve
- two issues: 1) the removal of calls to memset() by highly optimizing
- compilers, and 2) cleansing with other values than 0, since those can
- be read through on certain media, for example a swap space on disk.
- [Geoff Thorpe]
-
- *) Bugfix: client side session caching did not work with external caching,
- because the session->cipher setting was not restored when reloading
- from the external cache. This problem was masked, when
- SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG (part of SSL_OP_ALL) was set.
- (Found by Steve Haslam <steve@araqnid.ddts.net>.)
- [Lutz Jaenicke]
-
- *) Fix client_certificate (ssl/s2_clnt.c): The permissible total
- length of the REQUEST-CERTIFICATE message is 18 .. 34, not 17 .. 33.
- [Zeev Lieber <zeev-l@yahoo.com>]
-
- *) Undo an undocumented change introduced in 0.9.6e which caused
- repeated calls to OpenSSL_add_all_ciphers() and
- OpenSSL_add_all_digests() to be ignored, even after calling
- EVP_cleanup().
- [Richard Levitte]
-
- *) Change the default configuration reader to deal with last line not
- being properly terminated.
- [Richard Levitte]
-
- *) Change X509_NAME_cmp() so it applies the special rules on handling
- DN values that are of type PrintableString, as well as RDNs of type
- emailAddress where the value has the type ia5String.
- [stefank@valicert.com via Richard Levitte]
-
- *) Add a SSL_SESS_CACHE_NO_INTERNAL_STORE flag to take over half
- the job SSL_SESS_CACHE_NO_INTERNAL_LOOKUP was inconsistently
- doing, define a new flag (SSL_SESS_CACHE_NO_INTERNAL) to be
- the bitwise-OR of the two for use by the majority of applications
- wanting this behaviour, and update the docs. The documented
- behaviour and actual behaviour were inconsistent and had been
- changing anyway, so this is more a bug-fix than a behavioural
- change.
- [Geoff Thorpe, diagnosed by Nadav Har'El]
-
- *) Don't impose a 16-byte length minimum on session IDs in ssl/s3_clnt.c
- (the SSL 3.0 and TLS 1.0 specifications allow any length up to 32 bytes).
- [Bodo Moeller]
-
- *) Fix initialization code race conditions in
- SSLv23_method(), SSLv23_client_method(), SSLv23_server_method(),
- SSLv2_method(), SSLv2_client_method(), SSLv2_server_method(),
- SSLv3_method(), SSLv3_client_method(), SSLv3_server_method(),
- TLSv1_method(), TLSv1_client_method(), TLSv1_server_method(),
- ssl2_get_cipher_by_char(),
- ssl3_get_cipher_by_char().
- [Patrick McCormick <patrick@tellme.com>, Bodo Moeller]
-
- *) Reorder cleanup sequence in SSL_CTX_free(): only remove the ex_data after
- the cached sessions are flushed, as the remove_cb() might use ex_data
- contents. Bug found by Sam Varshavchik <mrsam@courier-mta.com>
- (see [openssl.org #212]).
- [Geoff Thorpe, Lutz Jaenicke]
-
- *) Fix typo in OBJ_txt2obj which incorrectly passed the content
- length, instead of the encoding length to d2i_ASN1_OBJECT.
- [Steve Henson]
-
- Changes between 0.9.6f and 0.9.6g [9 Aug 2002]
-
- *) [In 0.9.6g-engine release:]
- Fix crypto/engine/vendor_defns/cswift.h for WIN32 (use '_stdcall').
- [Lynn Gazis <lgazis@rainbow.com>]
-
- Changes between 0.9.6e and 0.9.6f [8 Aug 2002]
-
- *) Fix ASN1 checks. Check for overflow by comparing with LONG_MAX
- and get fix the header length calculation.
- [Florian Weimer <Weimer@CERT.Uni-Stuttgart.DE>,
- Alon Kantor <alonk@checkpoint.com> (and others),
- Steve Henson]
-
- *) Use proper error handling instead of 'assertions' in buffer
- overflow checks added in 0.9.6e. This prevents DoS (the
- assertions could call abort()).
- [Arne Ansper <arne@ats.cyber.ee>, Bodo Moeller]
-
- Changes between 0.9.6d and 0.9.6e [30 Jul 2002]
-
- *) Add various sanity checks to asn1_get_length() to reject
- the ASN1 length bytes if they exceed sizeof(long), will appear
- negative or the content length exceeds the length of the
- supplied buffer.
- [Steve Henson, Adi Stav <stav@mercury.co.il>, James Yonan <jim@ntlp.com>]
-
- *) Fix cipher selection routines: ciphers without encryption had no flags
- for the cipher strength set and where therefore not handled correctly
- by the selection routines (PR #130).
- [Lutz Jaenicke]
-
- *) Fix EVP_dsa_sha macro.
- [Nils Larsch]
-
- *) New option
- SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
- for disabling the SSL 3.0/TLS 1.0 CBC vulnerability countermeasure
- that was added in OpenSSL 0.9.6d.
-
- As the countermeasure turned out to be incompatible with some
- broken SSL implementations, the new option is part of SSL_OP_ALL.
- SSL_OP_ALL is usually employed when compatibility with weird SSL
- implementations is desired (e.g. '-bugs' option to 's_client' and
- 's_server'), so the new option is automatically set in many
- applications.
- [Bodo Moeller]
-
- *) Changes in security patch:
-
- Changes marked "(CHATS)" were sponsored by the Defense Advanced
- Research Projects Agency (DARPA) and Air Force Research Laboratory,
- Air Force Materiel Command, USAF, under agreement number
- F30602-01-2-0537.
-
- *) Add various sanity checks to asn1_get_length() to reject
- the ASN1 length bytes if they exceed sizeof(long), will appear
- negative or the content length exceeds the length of the
- supplied buffer. (CVE-2002-0659)
- [Steve Henson, Adi Stav <stav@mercury.co.il>, James Yonan <jim@ntlp.com>]
-
- *) Assertions for various potential buffer overflows, not known to
- happen in practice.
- [Ben Laurie (CHATS)]
-
- *) Various temporary buffers to hold ASCII versions of integers were
- too small for 64 bit platforms. (CVE-2002-0655)
- [Matthew Byng-Maddick <mbm@aldigital.co.uk> and Ben Laurie (CHATS)>
-
- *) Remote buffer overflow in SSL3 protocol - an attacker could
- supply an oversized session ID to a client. (CVE-2002-0656)
- [Ben Laurie (CHATS)]
-
- *) Remote buffer overflow in SSL2 protocol - an attacker could
- supply an oversized client master key. (CVE-2002-0656)
- [Ben Laurie (CHATS)]
-
- Changes between 0.9.6c and 0.9.6d [9 May 2002]
-
- *) Fix crypto/asn1/a_sign.c so that 'parameters' is omitted (not
- encoded as NULL) with id-dsa-with-sha1.
- [Nils Larsch <nla@trustcenter.de>; problem pointed out by Bodo Moeller]
-
- *) Check various X509_...() return values in apps/req.c.
- [Nils Larsch <nla@trustcenter.de>]
-
- *) Fix BASE64 decode (EVP_DecodeUpdate) for data with CR/LF ended lines:
- an end-of-file condition would erroneously be flagged, when the CRLF
- was just at the end of a processed block. The bug was discovered when
- processing data through a buffering memory BIO handing the data to a
- BASE64-decoding BIO. Bug fund and patch submitted by Pavel Tsekov
- <ptsekov@syntrex.com> and Nedelcho Stanev.
- [Lutz Jaenicke]
-
- *) Implement a countermeasure against a vulnerability recently found
- in CBC ciphersuites in SSL 3.0/TLS 1.0: Send an empty fragment
- before application data chunks to avoid the use of known IVs
- with data potentially chosen by the attacker.
- [Bodo Moeller]
-
- *) Fix length checks in ssl3_get_client_hello().
- [Bodo Moeller]
-
- *) TLS/SSL library bugfix: use s->s3->in_read_app_data differently
- to prevent ssl3_read_internal() from incorrectly assuming that
- ssl3_read_bytes() found application data while handshake
- processing was enabled when in fact s->s3->in_read_app_data was
- merely automatically cleared during the initial handshake.
- [Bodo Moeller; problem pointed out by Arne Ansper <arne@ats.cyber.ee>]
-
- *) Fix object definitions for Private and Enterprise: they were not
- recognized in their shortname (=lowercase) representation. Extend
- obj_dat.pl to issue an error when using undefined keywords instead
- of silently ignoring the problem (Svenning Sorensen
- <sss@sss.dnsalias.net>).
- [Lutz Jaenicke]
-
- *) Fix DH_generate_parameters() so that it works for 'non-standard'
- generators, i.e. generators other than 2 and 5. (Previously, the
- code did not properly initialise the 'add' and 'rem' values to
- BN_generate_prime().)
-
- In the new general case, we do not insist that 'generator' is
- actually a primitive root: This requirement is rather pointless;
- a generator of the order-q subgroup is just as good, if not
- better.
- [Bodo Moeller]
-
- *) Map new X509 verification errors to alerts. Discovered and submitted by
- Tom Wu <tom@arcot.com>.
- [Lutz Jaenicke]
-
- *) Fix ssl3_pending() (ssl/s3_lib.c) to prevent SSL_pending() from
- returning non-zero before the data has been completely received
- when using non-blocking I/O.
- [Bodo Moeller; problem pointed out by John Hughes]
-
- *) Some of the ciphers missed the strength entry (SSL_LOW etc).
- [Ben Laurie, Lutz Jaenicke]
-
- *) Fix bug in SSL_clear(): bad sessions were not removed (found by
- Yoram Zahavi <YoramZ@gilian.com>).
- [Lutz Jaenicke]
-
- *) Add information about CygWin 1.3 and on, and preserve proper
- configuration for the versions before that.
- [Corinna Vinschen <vinschen@redhat.com> and Richard Levitte]
-
- *) Make removal from session cache (SSL_CTX_remove_session()) more robust:
- check whether we deal with a copy of a session and do not delete from
- the cache in this case. Problem reported by "Izhar Shoshani Levi"
- <izhar@checkpoint.com>.
- [Lutz Jaenicke]
-
- *) Do not store session data into the internal session cache, if it
- is never intended to be looked up (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP
- flag is set). Proposed by Aslam <aslam@funk.com>.
- [Lutz Jaenicke]
-
- *) Have ASN1_BIT_STRING_set_bit() really clear a bit when the requested
- value is 0.
- [Richard Levitte]
-
- *) [In 0.9.6d-engine release:]
- Fix a crashbug and a logic bug in hwcrhk_load_pubkey().
- [Toomas Kiisk <vix@cyber.ee> via Richard Levitte]
-
- *) Add the configuration target linux-s390x.
- [Neale Ferguson <Neale.Ferguson@SoftwareAG-USA.com> via Richard Levitte]
-
- *) The earlier bugfix for the SSL3_ST_SW_HELLO_REQ_C case of
- ssl3_accept (ssl/s3_srvr.c) incorrectly used a local flag
- variable as an indication that a ClientHello message has been
- received. As the flag value will be lost between multiple
- invocations of ssl3_accept when using non-blocking I/O, the
- function may not be aware that a handshake has actually taken
- place, thus preventing a new session from being added to the
- session cache.
-
- To avoid this problem, we now set s->new_session to 2 instead of
- using a local variable.
- [Lutz Jaenicke, Bodo Moeller]
-
- *) Bugfix: Return -1 from ssl3_get_server_done (ssl3/s3_clnt.c)
- if the SSL_R_LENGTH_MISMATCH error is detected.
- [Geoff Thorpe, Bodo Moeller]
-
- *) New 'shared_ldflag' column in Configure platform table.
- [Richard Levitte]
-
- *) Fix EVP_CIPHER_mode macro.
- ["Dan S. Camper" <dan@bti.net>]
-
- *) Fix ssl3_read_bytes (ssl/s3_pkt.c): To ignore messages of unknown
- type, we must throw them away by setting rr->length to 0.
- [D P Chang <dpc@qualys.com>]
-
- Changes between 0.9.6b and 0.9.6c [21 dec 2001]
-
- *) Fix BN_rand_range bug pointed out by Dominikus Scherkl
- <Dominikus.Scherkl@biodata.com>. (The previous implementation
- worked incorrectly for those cases where range = 10..._2 and
- 3*range is two bits longer than range.)
- [Bodo Moeller]
-
- *) Only add signing time to PKCS7 structures if it is not already
- present.
- [Steve Henson]
-
- *) Fix crypto/objects/objects.h: "ld-ce" should be "id-ce",
- OBJ_ld_ce should be OBJ_id_ce.
- Also some ip-pda OIDs in crypto/objects/objects.txt were
- incorrect (cf. RFC 3039).
- [Matt Cooper, Frederic Giudicelli, Bodo Moeller]
-
- *) Release CRYPTO_LOCK_DYNLOCK when CRYPTO_destroy_dynlockid()
- returns early because it has nothing to do.
- [Andy Schneider <andy.schneider@bjss.co.uk>]
-
- *) [In 0.9.6c-engine release:]
- Fix mutex callback return values in crypto/engine/hw_ncipher.c.
- [Andy Schneider <andy.schneider@bjss.co.uk>]
-
- *) [In 0.9.6c-engine release:]
- Add support for Cryptographic Appliance's keyserver technology.
- (Use engine 'keyclient')
- [Cryptographic Appliances and Geoff Thorpe]
-
- *) Add a configuration entry for OS/390 Unix. The C compiler 'c89'
- is called via tools/c89.sh because arguments have to be
- rearranged (all '-L' options must appear before the first object
- modules).
- [Richard Shapiro <rshapiro@abinitio.com>]
-
- *) [In 0.9.6c-engine release:]
- Add support for Broadcom crypto accelerator cards, backported
- from 0.9.7.
- [Broadcom, Nalin Dahyabhai <nalin@redhat.com>, Mark Cox]
-
- *) [In 0.9.6c-engine release:]
- Add support for SureWare crypto accelerator cards from
- Baltimore Technologies. (Use engine 'sureware')
- [Baltimore Technologies and Mark Cox]
-
- *) [In 0.9.6c-engine release:]
- Add support for crypto accelerator cards from Accelerated
- Encryption Processing, www.aep.ie. (Use engine 'aep')
- [AEP Inc. and Mark Cox]
-
- *) Add a configuration entry for gcc on UnixWare.
- [Gary Benson <gbenson@redhat.com>]
-
- *) Change ssl/s2_clnt.c and ssl/s2_srvr.c so that received handshake
- messages are stored in a single piece (fixed-length part and
- variable-length part combined) and fix various bugs found on the way.
- [Bodo Moeller]
-
- *) Disable caching in BIO_gethostbyname(), directly use gethostbyname()
- instead. BIO_gethostbyname() does not know what timeouts are
- appropriate, so entries would stay in cache even when they have
- become invalid.
- [Bodo Moeller; problem pointed out by Rich Salz <rsalz@zolera.com>
-
- *) Change ssl23_get_client_hello (ssl/s23_srvr.c) behaviour when
- faced with a pathologically small ClientHello fragment that does
- not contain client_version: Instead of aborting with an error,
- simply choose the highest available protocol version (i.e.,
- TLS 1.0 unless it is disabled). In practice, ClientHello
- messages are never sent like this, but this change gives us
- strictly correct behaviour at least for TLS.
- [Bodo Moeller]
-
- *) Fix SSL handshake functions and SSL_clear() such that SSL_clear()
- never resets s->method to s->ctx->method when called from within
- one of the SSL handshake functions.
- [Bodo Moeller; problem pointed out by Niko Baric]
-
- *) In ssl3_get_client_hello (ssl/s3_srvr.c), generate a fatal alert
- (sent using the client's version number) if client_version is
- smaller than the protocol version in use. Also change
- ssl23_get_client_hello (ssl/s23_srvr.c) to select TLS 1.0 if
- the client demanded SSL 3.0 but only TLS 1.0 is enabled; then
- the client will at least see that alert.
- [Bodo Moeller]
-
- *) Fix ssl3_get_message (ssl/s3_both.c) to handle message fragmentation
- correctly.
- [Bodo Moeller]
-
- *) Avoid infinite loop in ssl3_get_message (ssl/s3_both.c) if a
- client receives HelloRequest while in a handshake.
- [Bodo Moeller; bug noticed by Andy Schneider <andy.schneider@bjss.co.uk>]
-
- *) Bugfix in ssl3_accept (ssl/s3_srvr.c): Case SSL3_ST_SW_HELLO_REQ_C
- should end in 'break', not 'goto end' which circumvents various
- cleanups done in state SSL_ST_OK. But session related stuff
- must be disabled for SSL_ST_OK in the case that we just sent a
- HelloRequest.
-
- Also avoid some overhead by not calling ssl_init_wbio_buffer()
- before just sending a HelloRequest.
- [Bodo Moeller, Eric Rescorla <ekr@rtfm.com>]
-
- *) Fix ssl/s3_enc.c, ssl/t1_enc.c and ssl/s3_pkt.c so that we don't
- reveal whether illegal block cipher padding was found or a MAC
- verification error occurred. (Neither SSLerr() codes nor alerts
- are directly visible to potential attackers, but the information
- may leak via logfiles.)
-
- Similar changes are not required for the SSL 2.0 implementation
- because the number of padding bytes is sent in clear for SSL 2.0,
- and the extra bytes are just ignored. However ssl/s2_pkt.c
- failed to verify that the purported number of padding bytes is in
- the legal range.
- [Bodo Moeller]
-
- *) Add OpenUNIX-8 support including shared libraries
- (Boyd Lynn Gerber <gerberb@zenez.com>).
- [Lutz Jaenicke]
-
- *) Improve RSA_padding_check_PKCS1_OAEP() check again to avoid
- 'wristwatch attack' using huge encoding parameters (cf.
- James H. Manger's CRYPTO 2001 paper). Note that the
- RSA_PKCS1_OAEP_PADDING case of RSA_private_decrypt() does not use
- encoding parameters and hence was not vulnerable.
- [Bodo Moeller]
-
- *) BN_sqr() bug fix.
- [Ulf Möller, reported by Jim Ellis <jim.ellis@cavium.com>]
-
- *) Rabin-Miller test analyses assume uniformly distributed witnesses,
- so use BN_pseudo_rand_range() instead of using BN_pseudo_rand()
- followed by modular reduction.
- [Bodo Moeller; pointed out by Adam Young <AYoung1@NCSUS.JNJ.COM>]
-
- *) Add BN_pseudo_rand_range() with obvious functionality: BN_rand_range()
- equivalent based on BN_pseudo_rand() instead of BN_rand().
- [Bodo Moeller]
-
- *) s3_srvr.c: allow sending of large client certificate lists (> 16 kB).
- This function was broken, as the check for a new client hello message
- to handle SGC did not allow these large messages.
- (Tracked down by "Douglas E. Engert" <deengert@anl.gov>.)
- [Lutz Jaenicke]
-
- *) Add alert descriptions for TLSv1 to SSL_alert_desc_string[_long]().
- [Lutz Jaenicke]
-
- *) Fix buggy behaviour of BIO_get_num_renegotiates() and BIO_ctrl()
- for BIO_C_GET_WRITE_BUF_SIZE ("Stephen Hinton" <shinton@netopia.com>).
- [Lutz Jaenicke]
-
- *) Rework the configuration and shared library support for Tru64 Unix.
- The configuration part makes use of modern compiler features and
- still retains old compiler behavior for those that run older versions
- of the OS. The shared library support part includes a variant that
- uses the RPATH feature, and is available through the special
- configuration target "alpha-cc-rpath", which will never be selected
- automatically.
- [Tim Mooney <mooney@dogbert.cc.ndsu.NoDak.edu> via Richard Levitte]
-
- *) In ssl3_get_key_exchange (ssl/s3_clnt.c), call ssl3_get_message()
- with the same message size as in ssl3_get_certificate_request().
- Otherwise, if no ServerKeyExchange message occurs, CertificateRequest
- messages might inadvertently be reject as too long.
- [Petr Lampa <lampa@fee.vutbr.cz>]
-
- *) Enhanced support for IA-64 Unix platforms (well, Linux and HP-UX).
- [Andy Polyakov]
-
- *) Modified SSL library such that the verify_callback that has been set
- specifically for an SSL object with SSL_set_verify() is actually being
- used. Before the change, a verify_callback set with this function was
- ignored and the verify_callback() set in the SSL_CTX at the time of
- the call was used. New function X509_STORE_CTX_set_verify_cb() introduced
- to allow the necessary settings.
- [Lutz Jaenicke]
-
- *) Initialize static variable in crypto/dsa/dsa_lib.c and crypto/dh/dh_lib.c
- explicitly to NULL, as at least on Solaris 8 this seems not always to be
- done automatically (in contradiction to the requirements of the C
- standard). This made problems when used from OpenSSH.
- [Lutz Jaenicke]
-
- *) In OpenSSL 0.9.6a and 0.9.6b, crypto/dh/dh_key.c ignored
- dh->length and always used
-
- BN_rand_range(priv_key, dh->p).
-
- BN_rand_range() is not necessary for Diffie-Hellman, and this
- specific range makes Diffie-Hellman unnecessarily inefficient if
- dh->length (recommended exponent length) is much smaller than the
- length of dh->p. We could use BN_rand_range() if the order of
- the subgroup was stored in the DH structure, but we only have
- dh->length.
-
- So switch back to
-
- BN_rand(priv_key, l, ...)
-
- where 'l' is dh->length if this is defined, or BN_num_bits(dh->p)-1
- otherwise.
- [Bodo Moeller]
-
- *) In
-
- RSA_eay_public_encrypt
- RSA_eay_private_decrypt
- RSA_eay_private_encrypt (signing)
- RSA_eay_public_decrypt (signature verification)
-
- (default implementations for RSA_public_encrypt,
- RSA_private_decrypt, RSA_private_encrypt, RSA_public_decrypt),
- always reject numbers >= n.
- [Bodo Moeller]
-
- *) In crypto/rand/md_rand.c, use a new short-time lock CRYPTO_LOCK_RAND2
- to synchronize access to 'locking_thread'. This is necessary on
- systems where access to 'locking_thread' (an 'unsigned long'
- variable) is not atomic.
- [Bodo Moeller]
-
- *) In crypto/rand/md_rand.c, set 'locking_thread' to current thread's ID
- *before* setting the 'crypto_lock_rand' flag. The previous code had
- a race condition if 0 is a valid thread ID.
- [Travis Vitek <vitek@roguewave.com>]
-
- *) Add support for shared libraries under Irix.
- [Albert Chin-A-Young <china@thewrittenword.com>]
-
- *) Add configuration option to build on Linux on both big-endian and
- little-endian MIPS.
- [Ralf Baechle <ralf@uni-koblenz.de>]
-
- *) Add the possibility to create shared libraries on HP-UX.
- [Richard Levitte]
-
- Changes between 0.9.6a and 0.9.6b [9 Jul 2001]
-
- *) Change ssleay_rand_bytes (crypto/rand/md_rand.c)
- to avoid a SSLeay/OpenSSL PRNG weakness pointed out by
- Markku-Juhani O. Saarinen <markku-juhani.saarinen@nokia.com>:
- PRNG state recovery was possible based on the output of
- one PRNG request appropriately sized to gain knowledge on
- 'md' followed by enough consecutive 1-byte PRNG requests
- to traverse all of 'state'.
-
- 1. When updating 'md_local' (the current thread's copy of 'md')
- during PRNG output generation, hash all of the previous
- 'md_local' value, not just the half used for PRNG output.
-
- 2. Make the number of bytes from 'state' included into the hash
- independent from the number of PRNG bytes requested.
-
- The first measure alone would be sufficient to avoid
- Markku-Juhani's attack. (Actually it had never occurred
- to me that the half of 'md_local' used for chaining was the
- half from which PRNG output bytes were taken -- I had always
- assumed that the secret half would be used.) The second
- measure makes sure that additional data from 'state' is never
- mixed into 'md_local' in small portions; this heuristically
- further strengthens the PRNG.
- [Bodo Moeller]
-
- *) Fix crypto/bn/asm/mips3.s.
- [Andy Polyakov]
-
- *) When only the key is given to "enc", the IV is undefined. Print out
- an error message in this case.
- [Lutz Jaenicke]
-
- *) Handle special case when X509_NAME is empty in X509 printing routines.
- [Steve Henson]
-
- *) In dsa_do_verify (crypto/dsa/dsa_ossl.c), verify that r and s are
- positive and less than q.
- [Bodo Moeller]
-
- *) Don't change *pointer in CRYPTO_add_lock() is add_lock_callback is
- used: it isn't thread safe and the add_lock_callback should handle
- that itself.
- [Paul Rose <Paul.Rose@bridge.com>]
-
- *) Verify that incoming data obeys the block size in
- ssl3_enc (ssl/s3_enc.c) and tls1_enc (ssl/t1_enc.c).
- [Bodo Moeller]
-
- *) Fix OAEP check.
- [Ulf Möller, Bodo Möller]
-
- *) The countermeasure against Bleichbacher's attack on PKCS #1 v1.5
- RSA encryption was accidentally removed in s3_srvr.c in OpenSSL 0.9.5
- when fixing the server behaviour for backwards-compatible 'client
- hello' messages. (Note that the attack is impractical against
- SSL 3.0 and TLS 1.0 anyway because length and version checking
- means that the probability of guessing a valid ciphertext is
- around 2^-40; see section 5 in Bleichenbacher's CRYPTO '98
- paper.)
-
- Before 0.9.5, the countermeasure (hide the error by generating a
- random 'decryption result') did not work properly because
- ERR_clear_error() was missing, meaning that SSL_get_error() would
- detect the supposedly ignored error.
-
- Both problems are now fixed.
- [Bodo Moeller]
-
- *) In crypto/bio/bf_buff.c, increase DEFAULT_BUFFER_SIZE to 4096
- (previously it was 1024).
- [Bodo Moeller]
-
- *) Fix for compatibility mode trust settings: ignore trust settings
- unless some valid trust or reject settings are present.
- [Steve Henson]
-
- *) Fix for blowfish EVP: its a variable length cipher.
- [Steve Henson]
-
- *) Fix various bugs related to DSA S/MIME verification. Handle missing
- parameters in DSA public key structures and return an error in the
- DSA routines if parameters are absent.
- [Steve Henson]
-
- *) In versions up to 0.9.6, RAND_file_name() resorted to file ".rnd"
- in the current directory if neither $RANDFILE nor $HOME was set.
- RAND_file_name() in 0.9.6a returned NULL in this case. This has
- caused some confusion to Windows users who haven't defined $HOME.
- Thus RAND_file_name() is changed again: e_os.h can define a
- DEFAULT_HOME, which will be used if $HOME is not set.
- For Windows, we use "C:"; on other platforms, we still require
- environment variables.
-
- *) Move 'if (!initialized) RAND_poll()' into regions protected by
- CRYPTO_LOCK_RAND. This is not strictly necessary, but avoids
- having multiple threads call RAND_poll() concurrently.
- [Bodo Moeller]
-
- *) In crypto/rand/md_rand.c, replace 'add_do_not_lock' flag by a
- combination of a flag and a thread ID variable.
- Otherwise while one thread is in ssleay_rand_bytes (which sets the
- flag), *other* threads can enter ssleay_add_bytes without obeying
- the CRYPTO_LOCK_RAND lock (and may even illegally release the lock
- that they do not hold after the first thread unsets add_do_not_lock).
- [Bodo Moeller]
-
- *) Change bctest again: '-x' expressions are not available in all
- versions of 'test'.
- [Bodo Moeller]
-
- Changes between 0.9.6 and 0.9.6a [5 Apr 2001]
-
- *) Fix a couple of memory leaks in PKCS7_dataDecode()
- [Steve Henson, reported by Heyun Zheng <hzheng@atdsprint.com>]
-
- *) Change Configure and Makefiles to provide EXE_EXT, which will contain
- the default extension for executables, if any. Also, make the perl
- scripts that use symlink() to test if it really exists and use "cp"
- if it doesn't. All this made OpenSSL compilable and installable in
- CygWin.
- [Richard Levitte]
-
- *) Fix for asn1_GetSequence() for indefinite length constructed data.
- If SEQUENCE is length is indefinite just set c->slen to the total
- amount of data available.
- [Steve Henson, reported by shige@FreeBSD.org]
- [This change does not apply to 0.9.7.]
-
- *) Change bctest to avoid here-documents inside command substitution
- (workaround for FreeBSD /bin/sh bug).
- For compatibility with Ultrix, avoid shell functions (introduced
- in the bctest version that searches along $PATH).
- [Bodo Moeller]
-
- *) Rename 'des_encrypt' to 'des_encrypt1'. This avoids the clashes
- with des_encrypt() defined on some operating systems, like Solaris
- and UnixWare.
- [Richard Levitte]
-
- *) Check the result of RSA-CRT (see D. Boneh, R. DeMillo, R. Lipton:
- On the Importance of Eliminating Errors in Cryptographic
- Computations, J. Cryptology 14 (2001) 2, 101-119,
- http://theory.stanford.edu/~dabo/papers/faults.ps.gz).
- [Ulf Moeller]
-
- *) MIPS assembler BIGNUM division bug fix.
- [Andy Polyakov]
-
- *) Disabled incorrect Alpha assembler code.
- [Richard Levitte]
-
- *) Fix PKCS#7 decode routines so they correctly update the length
- after reading an EOC for the EXPLICIT tag.
- [Steve Henson]
- [This change does not apply to 0.9.7.]
-
- *) Fix bug in PKCS#12 key generation routines. This was triggered
- if a 3DES key was generated with a 0 initial byte. Include
- PKCS12_BROKEN_KEYGEN compilation option to retain the old
- (but broken) behaviour.
- [Steve Henson]
-
- *) Enhance bctest to search for a working bc along $PATH and print
- it when found.
- [Tim Rice <tim@multitalents.net> via Richard Levitte]
-
- *) Fix memory leaks in err.c: free err_data string if necessary;
- don't write to the wrong index in ERR_set_error_data.
- [Bodo Moeller]
-
- *) Implement ssl23_peek (analogous to ssl23_read), which previously
- did not exist.
- [Bodo Moeller]
-
- *) Replace rdtsc with _emit statements for VC++ version 5.
- [Jeremy Cooper <jeremy@baymoo.org>]
-
- *) Make it possible to reuse SSLv2 sessions.
- [Richard Levitte]
-
- *) In copy_email() check for >= 0 as a return value for
- X509_NAME_get_index_by_NID() since 0 is a valid index.
- [Steve Henson reported by Massimiliano Pala <madwolf@opensca.org>]
-
- *) Avoid coredump with unsupported or invalid public keys by checking if
- X509_get_pubkey() fails in PKCS7_verify(). Fix memory leak when
- PKCS7_verify() fails with non detached data.
- [Steve Henson]
-
- *) Don't use getenv in library functions when run as setuid/setgid.
- New function OPENSSL_issetugid().
- [Ulf Moeller]
-
- *) Avoid false positives in memory leak detection code (crypto/mem_dbg.c)
- due to incorrect handling of multi-threading:
-
- 1. Fix timing glitch in the MemCheck_off() portion of CRYPTO_mem_ctrl().
-
- 2. Fix logical glitch in is_MemCheck_on() aka CRYPTO_is_mem_check_on().
-
- 3. Count how many times MemCheck_off() has been called so that
- nested use can be treated correctly. This also avoids
- inband-signalling in the previous code (which relied on the
- assumption that thread ID 0 is impossible).
- [Bodo Moeller]
-
- *) Add "-rand" option also to s_client and s_server.
- [Lutz Jaenicke]
-
- *) Fix CPU detection on Irix 6.x.
- [Kurt Hockenbury <khockenb@stevens-tech.edu> and
- "Bruce W. Forsberg" <bruce.forsberg@baesystems.com>]
-
- *) Fix X509_NAME bug which produced incorrect encoding if X509_NAME
- was empty.
- [Steve Henson]
- [This change does not apply to 0.9.7.]
-
- *) Use the cached encoding of an X509_NAME structure rather than
- copying it. This is apparently the reason for the libsafe "errors"
- but the code is actually correct.
- [Steve Henson]
-
- *) Add new function BN_rand_range(), and fix DSA_sign_setup() to prevent
- Bleichenbacher's DSA attack.
- Extend BN_[pseudo_]rand: As before, top=1 forces the highest two bits
- to be set and top=0 forces the highest bit to be set; top=-1 is new
- and leaves the highest bit random.
- [Ulf Moeller, Bodo Moeller]
-
- *) In the NCONF_...-based implementations for CONF_... queries
- (crypto/conf/conf_lib.c), if the input LHASH is NULL, avoid using
- a temporary CONF structure with the data component set to NULL
- (which gives segmentation faults in lh_retrieve).
- Instead, use NULL for the CONF pointer in CONF_get_string and
- CONF_get_number (which may use environment variables) and directly
- return NULL from CONF_get_section.
- [Bodo Moeller]
-
- *) Fix potential buffer overrun for EBCDIC.
- [Ulf Moeller]
-
- *) Tolerate nonRepudiation as being valid for S/MIME signing and certSign
- keyUsage if basicConstraints absent for a CA.
- [Steve Henson]
-
- *) Make SMIME_write_PKCS7() write mail header values with a format that
- is more generally accepted (no spaces before the semicolon), since
- some programs can't parse those values properly otherwise. Also make
- sure BIO's that break lines after each write do not create invalid
- headers.
- [Richard Levitte]
-
- *) Make the CRL encoding routines work with empty SEQUENCE OF. The
- macros previously used would not encode an empty SEQUENCE OF
- and break the signature.
- [Steve Henson]
- [This change does not apply to 0.9.7.]
-
- *) Zero the premaster secret after deriving the master secret in
- DH ciphersuites.
- [Steve Henson]
-
- *) Add some EVP_add_digest_alias registrations (as found in
- OpenSSL_add_all_digests()) to SSL_library_init()
- aka OpenSSL_add_ssl_algorithms(). This provides improved
- compatibility with peers using X.509 certificates
- with unconventional AlgorithmIdentifier OIDs.
- [Bodo Moeller]
-
- *) Fix for Irix with NO_ASM.
- ["Bruce W. Forsberg" <bruce.forsberg@baesystems.com>]
-
- *) ./config script fixes.
- [Ulf Moeller, Richard Levitte]
-
- *) Fix 'openssl passwd -1'.
- [Bodo Moeller]
-
- *) Change PKCS12_key_gen_asc() so it can cope with non null
- terminated strings whose length is passed in the passlen
- parameter, for example from PEM callbacks. This was done
- by adding an extra length parameter to asc2uni().
- [Steve Henson, reported by <oddissey@samsung.co.kr>]
-
- *) Fix C code generated by 'openssl dsaparam -C': If a BN_bin2bn
- call failed, free the DSA structure.
- [Bodo Moeller]
-
- *) Fix to uni2asc() to cope with zero length Unicode strings.
- These are present in some PKCS#12 files.
- [Steve Henson]
-
- *) Increase s2->wbuf allocation by one byte in ssl2_new (ssl/s2_lib.c).
- Otherwise do_ssl_write (ssl/s2_pkt.c) will write beyond buffer limits
- when writing a 32767 byte record.
- [Bodo Moeller; problem reported by Eric Day <eday@concentric.net>]
-
- *) In RSA_eay_public_{en,ed}crypt and RSA_eay_mod_exp (rsa_eay.c),
- obtain lock CRYPTO_LOCK_RSA before setting rsa->_method_mod_{n,p,q}.
-
- (RSA objects have a reference count access to which is protected
- by CRYPTO_LOCK_RSA [see rsa_lib.c, s3_srvr.c, ssl_cert.c, ssl_rsa.c],
- so they are meant to be shared between threads.)
- [Bodo Moeller, Geoff Thorpe; original patch submitted by
- "Reddie, Steven" <Steven.Reddie@ca.com>]
-
- *) Fix a deadlock in CRYPTO_mem_leaks().
- [Bodo Moeller]
-
- *) Use better test patterns in bntest.
- [Ulf Möller]
-
- *) rand_win.c fix for Borland C.
- [Ulf Möller]
-
- *) BN_rshift bugfix for n == 0.
- [Bodo Moeller]
-
- *) Add a 'bctest' script that checks for some known 'bc' bugs
- so that 'make test' does not abort just because 'bc' is broken.
- [Bodo Moeller]
-
- *) Store verify_result within SSL_SESSION also for client side to
- avoid potential security hole. (Re-used sessions on the client side
- always resulted in verify_result==X509_V_OK, not using the original
- result of the server certificate verification.)
- [Lutz Jaenicke]
-
- *) Fix ssl3_pending: If the record in s->s3->rrec is not of type
- SSL3_RT_APPLICATION_DATA, return 0.
- Similarly, change ssl2_pending to return 0 if SSL_in_init(s) is true.
- [Bodo Moeller]
-
- *) Fix SSL_peek:
- Both ssl2_peek and ssl3_peek, which were totally broken in earlier
- releases, have been re-implemented by renaming the previous
- implementations of ssl2_read and ssl3_read to ssl2_read_internal
- and ssl3_read_internal, respectively, and adding 'peek' parameters
- to them. The new ssl[23]_{read,peek} functions are calls to
- ssl[23]_read_internal with the 'peek' flag set appropriately.
- A 'peek' parameter has also been added to ssl3_read_bytes, which
- does the actual work for ssl3_read_internal.
- [Bodo Moeller]
-
- *) Initialise "ex_data" member of RSA/DSA/DH structures prior to calling
- the method-specific "init()" handler. Also clean up ex_data after
- calling the method-specific "finish()" handler. Previously, this was
- happening the other way round.
- [Geoff Thorpe]
-
- *) Increase BN_CTX_NUM (the number of BIGNUMs in a BN_CTX) to 16.
- The previous value, 12, was not always sufficient for BN_mod_exp().
- [Bodo Moeller]
-
- *) Make sure that shared libraries get the internal name engine with
- the full version number and not just 0. This should mark the
- shared libraries as not backward compatible. Of course, this should
- be changed again when we can guarantee backward binary compatibility.
- [Richard Levitte]
-
- *) Fix typo in get_cert_by_subject() in by_dir.c
- [Jean-Marc Desperrier <jean-marc.desperrier@certplus.com>]
-
- *) Rework the system to generate shared libraries:
-
- - Make note of the expected extension for the shared libraries and
- if there is a need for symbolic links from for example libcrypto.so.0
- to libcrypto.so.0.9.7. There is extended info in Configure for
- that.
-
- - Make as few rebuilds of the shared libraries as possible.
-
- - Still avoid linking the OpenSSL programs with the shared libraries.
-
- - When installing, install the shared libraries separately from the
- static ones.
- [Richard Levitte]
-
- *) Fix SSL_CTX_set_read_ahead macro to actually use its argument.
-
- Copy SSL_CTX's read_ahead flag to SSL object directly in SSL_new
- and not in SSL_clear because the latter is also used by the
- accept/connect functions; previously, the settings made by
- SSL_set_read_ahead would be lost during the handshake.
- [Bodo Moeller; problems reported by Anders Gertz <gertz@epact.se>]
-
- *) Correct util/mkdef.pl to be selective about disabled algorithms.
- Previously, it would create entries for disabled algorithms no
- matter what.
- [Richard Levitte]
-
- *) Added several new manual pages for SSL_* function.
- [Lutz Jaenicke]
-
- Changes between 0.9.5a and 0.9.6 [24 Sep 2000]
-
- *) In ssl23_get_client_hello, generate an error message when faced
- with an initial SSL 3.0/TLS record that is too small to contain the
- first two bytes of the ClientHello message, i.e. client_version.
- (Note that this is a pathologic case that probably has never happened
- in real life.) The previous approach was to use the version number
- from the record header as a substitute; but our protocol choice
- should not depend on that one because it is not authenticated
- by the Finished messages.
- [Bodo Moeller]
-
- *) More robust randomness gathering functions for Windows.
- [Jeffrey Altman <jaltman@columbia.edu>]
-
- *) For compatibility reasons if the flag X509_V_FLAG_ISSUER_CHECK is
- not set then we don't setup the error code for issuer check errors
- to avoid possibly overwriting other errors which the callback does
- handle. If an application does set the flag then we assume it knows
- what it is doing and can handle the new informational codes
- appropriately.
- [Steve Henson]
-
- *) Fix for a nasty bug in ASN1_TYPE handling. ASN1_TYPE is used for
- a general "ANY" type, as such it should be able to decode anything
- including tagged types. However it didn't check the class so it would
- wrongly interpret tagged types in the same way as their universal
- counterpart and unknown types were just rejected. Changed so that the
- tagged and unknown types are handled in the same way as a SEQUENCE:
- that is the encoding is stored intact. There is also a new type
- "V_ASN1_OTHER" which is used when the class is not universal, in this
- case we have no idea what the actual type is so we just lump them all
- together.
- [Steve Henson]
-
- *) On VMS, stdout may very well lead to a file that is written to
- in a record-oriented fashion. That means that every write() will
- write a separate record, which will be read separately by the
- programs trying to read from it. This can be very confusing.
-
- The solution is to put a BIO filter in the way that will buffer
- text until a linefeed is reached, and then write everything a
- line at a time, so every record written will be an actual line,
- not chunks of lines and not (usually doesn't happen, but I've
- seen it once) several lines in one record. BIO_f_linebuffer() is
- the answer.
-
- Currently, it's a VMS-only method, because that's where it has
- been tested well enough.
- [Richard Levitte]
-
- *) Remove 'optimized' squaring variant in BN_mod_mul_montgomery,
- it can return incorrect results.
- (Note: The buggy variant was not enabled in OpenSSL 0.9.5a,
- but it was in 0.9.6-beta[12].)
- [Bodo Moeller]
-
- *) Disable the check for content being present when verifying detached
- signatures in pk7_smime.c. Some versions of Netscape (wrongly)
- include zero length content when signing messages.
- [Steve Henson]
-
- *) New BIO_shutdown_wr macro, which invokes the BIO_C_SHUTDOWN_WR
- BIO_ctrl (for BIO pairs).
- [Bodo Möller]
-
- *) Add DSO method for VMS.
- [Richard Levitte]
-
- *) Bug fix: Montgomery multiplication could produce results with the
- wrong sign.
- [Ulf Möller]
-
- *) Add RPM specification openssl.spec and modify it to build three
- packages. The default package contains applications, application
- documentation and run-time libraries. The devel package contains
- include files, static libraries and function documentation. The
- doc package contains the contents of the doc directory. The original
- openssl.spec was provided by Damien Miller <djm@mindrot.org>.
- [Richard Levitte]
-
- *) Add a large number of documentation files for many SSL routines.
- [Lutz Jaenicke <Lutz.Jaenicke@aet.TU-Cottbus.DE>]
-
- *) Add a configuration entry for Sony News 4.
- [NAKAJI Hiroyuki <nakaji@tutrp.tut.ac.jp>]
-
- *) Don't set the two most significant bits to one when generating a
- random number < q in the DSA library.
- [Ulf Möller]
-
- *) New SSL API mode 'SSL_MODE_AUTO_RETRY'. This disables the default
- behaviour that SSL_read may result in SSL_ERROR_WANT_READ (even if
- the underlying transport is blocking) if a handshake took place.
- (The default behaviour is needed by applications such as s_client
- and s_server that use select() to determine when to use SSL_read;
- but for applications that know in advance when to expect data, it
- just makes things more complicated.)
- [Bodo Moeller]
-
- *) Add RAND_egd_bytes(), which gives control over the number of bytes read
- from EGD.
- [Ben Laurie]
-
- *) Add a few more EBCDIC conditionals that make `req' and `x509'
- work better on such systems.
- [Martin Kraemer <Martin.Kraemer@MchP.Siemens.De>]
-
- *) Add two demo programs for PKCS12_parse() and PKCS12_create().
- Update PKCS12_parse() so it copies the friendlyName and the
- keyid to the certificates aux info.
- [Steve Henson]
-
- *) Fix bug in PKCS7_verify() which caused an infinite loop
- if there was more than one signature.
- [Sven Uszpelkat <su@celocom.de>]
-
- *) Major change in util/mkdef.pl to include extra information
- about each symbol, as well as presenting variables as well
- as functions. This change means that there's n more need
- to rebuild the .num files when some algorithms are excluded.
- [Richard Levitte]
-
- *) Allow the verify time to be set by an application,
- rather than always using the current time.
- [Steve Henson]
-
- *) Phase 2 verify code reorganisation. The certificate
- verify code now looks up an issuer certificate by a
- number of criteria: subject name, authority key id
- and key usage. It also verifies self signed certificates
- by the same criteria. The main comparison function is
- X509_check_issued() which performs these checks.
-
- Lot of changes were necessary in order to support this
- without completely rewriting the lookup code.
-
- Authority and subject key identifier are now cached.
-
- The LHASH 'certs' is X509_STORE has now been replaced
- by a STACK_OF(X509_OBJECT). This is mainly because an
- LHASH can't store or retrieve multiple objects with
- the same hash value.
-
- As a result various functions (which were all internal
- use only) have changed to handle the new X509_STORE
- structure. This will break anything that messed round
- with X509_STORE internally.
-
- The functions X509_STORE_add_cert() now checks for an
- exact match, rather than just subject name.
-
- The X509_STORE API doesn't directly support the retrieval
- of multiple certificates matching a given criteria, however
- this can be worked round by performing a lookup first
- (which will fill the cache with candidate certificates)
- and then examining the cache for matches. This is probably
- the best we can do without throwing out X509_LOOKUP
- entirely (maybe later...).
-
- The X509_VERIFY_CTX structure has been enhanced considerably.
-
- All certificate lookup operations now go via a get_issuer()
- callback. Although this currently uses an X509_STORE it
- can be replaced by custom lookups. This is a simple way
- to bypass the X509_STORE hackery necessary to make this
- work and makes it possible to use more efficient techniques
- in future. A very simple version which uses a simple
- STACK for its trusted certificate store is also provided
- using X509_STORE_CTX_trusted_stack().
-
- The verify_cb() and verify() callbacks now have equivalents
- in the X509_STORE_CTX structure.
-
- X509_STORE_CTX also has a 'flags' field which can be used
- to customise the verify behaviour.
- [Steve Henson]
-
- *) Add new PKCS#7 signing option PKCS7_NOSMIMECAP which
- excludes S/MIME capabilities.
- [Steve Henson]
-
- *) When a certificate request is read in keep a copy of the
- original encoding of the signed data and use it when outputting
- again. Signatures then use the original encoding rather than
- a decoded, encoded version which may cause problems if the
- request is improperly encoded.
- [Steve Henson]
-
- *) For consistency with other BIO_puts implementations, call
- buffer_write(b, ...) directly in buffer_puts instead of calling
- BIO_write(b, ...).
-
- In BIO_puts, increment b->num_write as in BIO_write.
- [Peter.Sylvester@EdelWeb.fr]
-
- *) Fix BN_mul_word for the case where the word is 0. (We have to use
- BN_zero, we may not return a BIGNUM with an array consisting of
- words set to zero.)
- [Bodo Moeller]
-
- *) Avoid calling abort() from within the library when problems are
- detected, except if preprocessor symbols have been defined
- (such as REF_CHECK, BN_DEBUG etc.).
- [Bodo Moeller]
-
- *) New openssl application 'rsautl'. This utility can be
- used for low level RSA operations. DER public key
- BIO/fp routines also added.
- [Steve Henson]
-
- *) New Configure entry and patches for compiling on QNX 4.
- [Andreas Schneider <andreas@ds3.etech.fh-hamburg.de>]
-
- *) A demo state-machine implementation was sponsored by
- Nuron (http://www.nuron.com/) and is now available in
- demos/state_machine.
- [Ben Laurie]
-
- *) New options added to the 'dgst' utility for signature
- generation and verification.
- [Steve Henson]
-
- *) Unrecognized PKCS#7 content types are now handled via a
- catch all ASN1_TYPE structure. This allows unsupported
- types to be stored as a "blob" and an application can
- encode and decode it manually.
- [Steve Henson]
-
- *) Fix various signed/unsigned issues to make a_strex.c
- compile under VC++.
- [Oscar Jacobsson <oscar.jacobsson@celocom.com>]
-
- *) ASN1 fixes. i2d_ASN1_OBJECT was not returning the correct
- length if passed a buffer. ASN1_INTEGER_to_BN failed
- if passed a NULL BN and its argument was negative.
- [Steve Henson, pointed out by Sven Heiberg <sven@tartu.cyber.ee>]
-
- *) Modification to PKCS#7 encoding routines to output definite
- length encoding. Since currently the whole structures are in
- memory there's not real point in using indefinite length
- constructed encoding. However if OpenSSL is compiled with
- the flag PKCS7_INDEFINITE_ENCODING the old form is used.
- [Steve Henson]
-
- *) Added BIO_vprintf() and BIO_vsnprintf().
- [Richard Levitte]
-
- *) Added more prefixes to parse for in the strings written
- through a logging bio, to cover all the levels that are available
- through syslog. The prefixes are now:
-
- PANIC, EMERG, EMR => LOG_EMERG
- ALERT, ALR => LOG_ALERT
- CRIT, CRI => LOG_CRIT
- ERROR, ERR => LOG_ERR
- WARNING, WARN, WAR => LOG_WARNING
- NOTICE, NOTE, NOT => LOG_NOTICE
- INFO, INF => LOG_INFO
- DEBUG, DBG => LOG_DEBUG
-
- and as before, if none of those prefixes are present at the
- beginning of the string, LOG_ERR is chosen.
-
- On Win32, the LOG_* levels are mapped according to this:
-
- LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR => EVENTLOG_ERROR_TYPE
- LOG_WARNING => EVENTLOG_WARNING_TYPE
- LOG_NOTICE, LOG_INFO, LOG_DEBUG => EVENTLOG_INFORMATION_TYPE
-
- [Richard Levitte]
-
- *) Made it possible to reconfigure with just the configuration
- argument "reconf" or "reconfigure". The command line arguments
- are stored in Makefile.ssl in the variable CONFIGURE_ARGS,
- and are retrieved from there when reconfiguring.
- [Richard Levitte]
-
- *) MD4 implemented.
- [Assar Westerlund <assar@sics.se>, Richard Levitte]
-
- *) Add the arguments -CAfile and -CApath to the pkcs12 utility.
- [Richard Levitte]
-
- *) The obj_dat.pl script was messing up the sorting of object
- names. The reason was that it compared the quoted version
- of strings as a result "OCSP" > "OCSP Signing" because
- " > SPACE. Changed script to store unquoted versions of
- names and add quotes on output. It was also omitting some
- names from the lookup table if they were given a default
- value (that is if SN is missing it is given the same
- value as LN and vice versa), these are now added on the
- grounds that if an object has a name we should be able to
- look it up. Finally added warning output when duplicate
- short or long names are found.
- [Steve Henson]
-
- *) Changes needed for Tandem NSK.
- [Scott Uroff <scott@xypro.com>]
-
- *) Fix SSL 2.0 rollback checking: Due to an off-by-one error in
- RSA_padding_check_SSLv23(), special padding was never detected
- and thus the SSL 3.0/TLS 1.0 countermeasure against protocol
- version rollback attacks was not effective.
-
- In s23_clnt.c, don't use special rollback-attack detection padding
- (RSA_SSLV23_PADDING) if SSL 2.0 is the only protocol enabled in the
- client; similarly, in s23_srvr.c, don't do the rollback check if
- SSL 2.0 is the only protocol enabled in the server.
- [Bodo Moeller]
-
- *) Make it possible to get hexdumps of unprintable data with 'openssl
- asn1parse'. By implication, the functions ASN1_parse_dump() and
- BIO_dump_indent() are added.
- [Richard Levitte]
-
- *) New functions ASN1_STRING_print_ex() and X509_NAME_print_ex()
- these print out strings and name structures based on various
- flags including RFC2253 support and proper handling of
- multibyte characters. Added options to the 'x509' utility
- to allow the various flags to be set.
- [Steve Henson]
-
- *) Various fixes to use ASN1_TIME instead of ASN1_UTCTIME.
- Also change the functions X509_cmp_current_time() and
- X509_gmtime_adj() work with an ASN1_TIME structure,
- this will enable certificates using GeneralizedTime in validity
- dates to be checked.
- [Steve Henson]
-
- *) Make the NEG_PUBKEY_BUG code (which tolerates invalid
- negative public key encodings) on by default,
- NO_NEG_PUBKEY_BUG can be set to disable it.
- [Steve Henson]
-
- *) New function c2i_ASN1_OBJECT() which acts on ASN1_OBJECT
- content octets. An i2c_ASN1_OBJECT is unnecessary because
- the encoding can be trivially obtained from the structure.
- [Steve Henson]
-
- *) crypto/err.c locking bugfix: Use write locks (CRYPTO_w_[un]lock),
- not read locks (CRYPTO_r_[un]lock).
- [Bodo Moeller]
-
- *) A first attempt at creating official support for shared
- libraries through configuration. I've kept it so the
- default is static libraries only, and the OpenSSL programs
- are always statically linked for now, but there are
- preparations for dynamic linking in place.
- This has been tested on Linux and Tru64.
- [Richard Levitte]
-
- *) Randomness polling function for Win9x, as described in:
- Peter Gutmann, Software Generation of Practically Strong
- Random Numbers.
- [Ulf Möller]
-
- *) Fix so PRNG is seeded in req if using an already existing
- DSA key.
- [Steve Henson]
-
- *) New options to smime application. -inform and -outform
- allow alternative formats for the S/MIME message including
- PEM and DER. The -content option allows the content to be
- specified separately. This should allow things like Netscape
- form signing output easier to verify.
- [Steve Henson]
-
- *) Fix the ASN1 encoding of tags using the 'long form'.
- [Steve Henson]
-
- *) New ASN1 functions, i2c_* and c2i_* for INTEGER and BIT
- STRING types. These convert content octets to and from the
- underlying type. The actual tag and length octets are
- already assumed to have been read in and checked. These
- are needed because all other string types have virtually
- identical handling apart from the tag. By having versions
- of the ASN1 functions that just operate on content octets
- IMPLICIT tagging can be handled properly. It also allows
- the ASN1_ENUMERATED code to be cut down because ASN1_ENUMERATED
- and ASN1_INTEGER are identical apart from the tag.
- [Steve Henson]
-
- *) Change the handling of OID objects as follows:
-
- - New object identifiers are inserted in objects.txt, following
- the syntax given in objects.README.
- - objects.pl is used to process obj_mac.num and create a new
- obj_mac.h.
- - obj_dat.pl is used to create a new obj_dat.h, using the data in
- obj_mac.h.
-
- This is currently kind of a hack, and the perl code in objects.pl
- isn't very elegant, but it works as I intended. The simplest way
- to check that it worked correctly is to look in obj_dat.h and
- check the array nid_objs and make sure the objects haven't moved
- around (this is important!). Additions are OK, as well as
- consistent name changes.
- [Richard Levitte]
-
- *) Add BSD-style MD5-based passwords to 'openssl passwd' (option '-1').
- [Bodo Moeller]
-
- *) Addition of the command line parameter '-rand file' to 'openssl req'.
- The given file adds to whatever has already been seeded into the
- random pool through the RANDFILE configuration file option or
- environment variable, or the default random state file.
- [Richard Levitte]
-
- *) mkstack.pl now sorts each macro group into lexical order.
- Previously the output order depended on the order the files
- appeared in the directory, resulting in needless rewriting
- of safestack.h .
- [Steve Henson]
-
- *) Patches to make OpenSSL compile under Win32 again. Mostly
- work arounds for the VC++ problem that it treats func() as
- func(void). Also stripped out the parts of mkdef.pl that
- added extra typesafe functions: these no longer exist.
- [Steve Henson]
-
- *) Reorganisation of the stack code. The macros are now all
- collected in safestack.h . Each macro is defined in terms of
- a "stack macro" of the form SKM_<name>(type, a, b). The
- DEBUG_SAFESTACK is now handled in terms of function casts,
- this has the advantage of retaining type safety without the
- use of additional functions. If DEBUG_SAFESTACK is not defined
- then the non typesafe macros are used instead. Also modified the
- mkstack.pl script to handle the new form. Needs testing to see
- if which (if any) compilers it chokes and maybe make DEBUG_SAFESTACK
- the default if no major problems. Similar behaviour for ASN1_SET_OF
- and PKCS12_STACK_OF.
- [Steve Henson]
-
- *) When some versions of IIS use the 'NET' form of private key the
- key derivation algorithm is different. Normally MD5(password) is
- used as a 128 bit RC4 key. In the modified case
- MD5(MD5(password) + "SGCKEYSALT") is used instead. Added some
- new functions i2d_RSA_NET(), d2i_RSA_NET() etc which are the same
- as the old Netscape_RSA functions except they have an additional
- 'sgckey' parameter which uses the modified algorithm. Also added
- an -sgckey command line option to the rsa utility. Thanks to
- Adrian Peck <bertie@ncipher.com> for posting details of the modified
- algorithm to openssl-dev.
- [Steve Henson]
-
- *) The evp_local.h macros were using 'c.##kname' which resulted in
- invalid expansion on some systems (SCO 5.0.5 for example).
- Corrected to 'c.kname'.
- [Phillip Porch <root@theporch.com>]
-
- *) New X509_get1_email() and X509_REQ_get1_email() functions that return
- a STACK of email addresses from a certificate or request, these look
- in the subject name and the subject alternative name extensions and
- omit any duplicate addresses.
- [Steve Henson]
-
- *) Re-implement BN_mod_exp2_mont using independent (and larger) windows.
- This makes DSA verification about 2 % faster.
- [Bodo Moeller]
-
- *) Increase maximum window size in BN_mod_exp_... to 6 bits instead of 5
- (meaning that now 2^5 values will be precomputed, which is only 4 KB
- plus overhead for 1024 bit moduli).
- This makes exponentiations about 0.5 % faster for 1024 bit
- exponents (as measured by "openssl speed rsa2048").
- [Bodo Moeller]
-
- *) Rename memory handling macros to avoid conflicts with other
- software:
- Malloc => OPENSSL_malloc
- Malloc_locked => OPENSSL_malloc_locked
- Realloc => OPENSSL_realloc
- Free => OPENSSL_free
- [Richard Levitte]
-
- *) New function BN_mod_exp_mont_word for small bases (roughly 15%
- faster than BN_mod_exp_mont, i.e. 7% for a full DH exchange).
- [Bodo Moeller]
-
- *) CygWin32 support.
- [John Jarvie <jjarvie@newsguy.com>]
-
- *) The type-safe stack code has been rejigged. It is now only compiled
- in when OpenSSL is configured with the DEBUG_SAFESTACK option and
- by default all type-specific stack functions are "#define"d back to
- standard stack functions. This results in more streamlined output
- but retains the type-safety checking possibilities of the original
- approach.
- [Geoff Thorpe]
-
- *) The STACK code has been cleaned up, and certain type declarations
- that didn't make a lot of sense have been brought in line. This has
- also involved a cleanup of sorts in safestack.h to more correctly
- map type-safe stack functions onto their plain stack counterparts.
- This work has also resulted in a variety of "const"ifications of
- lots of the code, especially "_cmp" operations which should normally
- be prototyped with "const" parameters anyway.
- [Geoff Thorpe]
-
- *) When generating bytes for the first time in md_rand.c, 'stir the pool'
- by seeding with STATE_SIZE dummy bytes (with zero entropy count).
- (The PRNG state consists of two parts, the large pool 'state' and 'md',
- where all of 'md' is used each time the PRNG is used, but 'state'
- is used only indexed by a cyclic counter. As entropy may not be
- well distributed from the beginning, 'md' is important as a
- chaining variable. However, the output function chains only half
- of 'md', i.e. 80 bits. ssleay_rand_add, on the other hand, chains
- all of 'md', and seeding with STATE_SIZE dummy bytes will result
- in all of 'state' being rewritten, with the new values depending
- on virtually all of 'md'. This overcomes the 80 bit limitation.)
- [Bodo Moeller]
-
- *) In ssl/s2_clnt.c and ssl/s3_clnt.c, call ERR_clear_error() when
- the handshake is continued after ssl_verify_cert_chain();
- otherwise, if SSL_VERIFY_NONE is set, remaining error codes
- can lead to 'unexplainable' connection aborts later.
- [Bodo Moeller; problem tracked down by Lutz Jaenicke]
-
- *) Major EVP API cipher revision.
- Add hooks for extra EVP features. This allows various cipher
- parameters to be set in the EVP interface. Support added for variable
- key length ciphers via the EVP_CIPHER_CTX_set_key_length() function and
- setting of RC2 and RC5 parameters.
-
- Modify EVP_OpenInit() and EVP_SealInit() to cope with variable key length
- ciphers.
-
- Remove lots of duplicated code from the EVP library. For example *every*
- cipher init() function handles the 'iv' in the same way according to the
- cipher mode. They also all do nothing if the 'key' parameter is NULL and
- for CFB and OFB modes they zero ctx->num.
-
- New functionality allows removal of S/MIME code RC2 hack.
-
- Most of the routines have the same form and so can be declared in terms
- of macros.
-
- By shifting this to the top level EVP_CipherInit() it can be removed from
- all individual ciphers. If the cipher wants to handle IVs or keys
- differently it can set the EVP_CIPH_CUSTOM_IV or EVP_CIPH_ALWAYS_CALL_INIT
- flags.
-
- Change lots of functions like EVP_EncryptUpdate() to now return a
- value: although software versions of the algorithms cannot fail
- any installed hardware versions can.
- [Steve Henson]
-
- *) Implement SSL_OP_TLS_ROLLBACK_BUG: In ssl3_get_client_key_exchange, if
- this option is set, tolerate broken clients that send the negotiated
- protocol version number instead of the requested protocol version
- number.
- [Bodo Moeller]
-
- *) Call dh_tmp_cb (set by ..._TMP_DH_CB) with correct 'is_export' flag;
- i.e. non-zero for export ciphersuites, zero otherwise.
- Previous versions had this flag inverted, inconsistent with
- rsa_tmp_cb (..._TMP_RSA_CB).
- [Bodo Moeller; problem reported by Amit Chopra]
-
- *) Add missing DSA library text string. Work around for some IIS
- key files with invalid SEQUENCE encoding.
- [Steve Henson]
-
- *) Add a document (doc/standards.txt) that list all kinds of standards
- and so on that are implemented in OpenSSL.
- [Richard Levitte]
-
- *) Enhance c_rehash script. Old version would mishandle certificates
- with the same subject name hash and wouldn't handle CRLs at all.
- Added -fingerprint option to crl utility, to support new c_rehash
- features.
- [Steve Henson]
-
- *) Eliminate non-ANSI declarations in crypto.h and stack.h.
- [Ulf Möller]
-
- *) Fix for SSL server purpose checking. Server checking was
- rejecting certificates which had extended key usage present
- but no ssl client purpose.
- [Steve Henson, reported by Rene Grosser <grosser@hisolutions.com>]
-
- *) Make PKCS#12 code work with no password. The PKCS#12 spec
- is a little unclear about how a blank password is handled.
- Since the password in encoded as a BMPString with terminating
- double NULL a zero length password would end up as just the
- double NULL. However no password at all is different and is
- handled differently in the PKCS#12 key generation code. NS
- treats a blank password as zero length. MSIE treats it as no
- password on export: but it will try both on import. We now do
- the same: PKCS12_parse() tries zero length and no password if
- the password is set to "" or NULL (NULL is now a valid password:
- it wasn't before) as does the pkcs12 application.
- [Steve Henson]
-
- *) Bugfixes in apps/x509.c: Avoid a memory leak; and don't use
- perror when PEM_read_bio_X509_REQ fails, the error message must
- be obtained from the error queue.
- [Bodo Moeller]
-
- *) Avoid 'thread_hash' memory leak in crypto/err/err.c by freeing
- it in ERR_remove_state if appropriate, and change ERR_get_state
- accordingly to avoid race conditions (this is necessary because
- thread_hash is no longer constant once set).
- [Bodo Moeller]
-
- *) Bugfix for linux-elf makefile.one.
- [Ulf Möller]
-
- *) RSA_get_default_method() will now cause a default
- RSA_METHOD to be chosen if one doesn't exist already.
- Previously this was only set during a call to RSA_new()
- or RSA_new_method(NULL) meaning it was possible for
- RSA_get_default_method() to return NULL.
- [Geoff Thorpe]
-
- *) Added native name translation to the existing DSO code
- that will convert (if the flag to do so is set) filenames
- that are sufficiently small and have no path information
- into a canonical native form. Eg. "blah" converted to
- "libblah.so" or "blah.dll" etc.
- [Geoff Thorpe]
-
- *) New function ERR_error_string_n(e, buf, len) which is like
- ERR_error_string(e, buf), but writes at most 'len' bytes
- including the 0 terminator. For ERR_error_string_n, 'buf'
- may not be NULL.
- [Damien Miller <djm@mindrot.org>, Bodo Moeller]
-
- *) CONF library reworked to become more general. A new CONF
- configuration file reader "class" is implemented as well as a
- new functions (NCONF_*, for "New CONF") to handle it. The now
- old CONF_* functions are still there, but are reimplemented to
- work in terms of the new functions. Also, a set of functions
- to handle the internal storage of the configuration data is
- provided to make it easier to write new configuration file
- reader "classes" (I can definitely see something reading a
- configuration file in XML format, for example), called _CONF_*,
- or "the configuration storage API"...
-
- The new configuration file reading functions are:
-
- NCONF_new, NCONF_free, NCONF_load, NCONF_load_fp, NCONF_load_bio,
- NCONF_get_section, NCONF_get_string, NCONF_get_numbre
-
- NCONF_default, NCONF_WIN32
-
- NCONF_dump_fp, NCONF_dump_bio
-
- NCONF_default and NCONF_WIN32 are method (or "class") choosers,
- NCONF_new creates a new CONF object. This works in the same way
- as other interfaces in OpenSSL, like the BIO interface.
- NCONF_dump_* dump the internal storage of the configuration file,
- which is useful for debugging. All other functions take the same
- arguments as the old CONF_* functions with the exception of the
- first that must be a `CONF *' instead of a `LHASH *'.
-
- To make it easier to use the new classes with the old CONF_* functions,
- the function CONF_set_default_method is provided.
- [Richard Levitte]
-
- *) Add '-tls1' option to 'openssl ciphers', which was already
- mentioned in the documentation but had not been implemented.
- (This option is not yet really useful because even the additional
- experimental TLS 1.0 ciphers are currently treated as SSL 3.0 ciphers.)
- [Bodo Moeller]
-
- *) Initial DSO code added into libcrypto for letting OpenSSL (and
- OpenSSL-based applications) load shared libraries and bind to
- them in a portable way.
- [Geoff Thorpe, with contributions from Richard Levitte]
-
- Changes between 0.9.5 and 0.9.5a [1 Apr 2000]
-
- *) Make sure _lrotl and _lrotr are only used with MSVC.
-
- *) Use lock CRYPTO_LOCK_RAND correctly in ssleay_rand_status
- (the default implementation of RAND_status).
-
- *) Rename openssl x509 option '-crlext', which was added in 0.9.5,
- to '-clrext' (= clear extensions), as intended and documented.
- [Bodo Moeller; inconsistency pointed out by Michael Attili
- <attili@amaxo.com>]
-
- *) Fix for HMAC. It wasn't zeroing the rest of the block if the key length
- was larger than the MD block size.
- [Steve Henson, pointed out by Yost William <YostW@tce.com>]
-
- *) Modernise PKCS12_parse() so it uses STACK_OF(X509) for its ca argument
- fix a leak when the ca argument was passed as NULL. Stop X509_PUBKEY_set()
- using the passed key: if the passed key was a private key the result
- of X509_print(), for example, would be to print out all the private key
- components.
- [Steve Henson]
-
- *) des_quad_cksum() byte order bug fix.
- [Ulf Möller, using the problem description in krb4-0.9.7, where
- the solution is attributed to Derrick J Brashear <shadow@DEMENTIA.ORG>]
-
- *) Fix so V_ASN1_APP_CHOOSE works again: however its use is strongly
- discouraged.
- [Steve Henson, pointed out by Brian Korver <briank@cs.stanford.edu>]
-
- *) For easily testing in shell scripts whether some command
- 'openssl XXX' exists, the new pseudo-command 'openssl no-XXX'
- returns with exit code 0 iff no command of the given name is available.
- 'no-XXX' is printed in this case, 'XXX' otherwise. In both cases,
- the output goes to stdout and nothing is printed to stderr.
- Additional arguments are always ignored.
-
- Since for each cipher there is a command of the same name,
- the 'no-cipher' compilation switches can be tested this way.
-
- ('openssl no-XXX' is not able to detect pseudo-commands such
- as 'quit', 'list-XXX-commands', or 'no-XXX' itself.)
- [Bodo Moeller]
-
- *) Update test suite so that 'make test' succeeds in 'no-rsa' configuration.
- [Bodo Moeller]
-
- *) For SSL_[CTX_]set_tmp_dh, don't create a DH key if SSL_OP_SINGLE_DH_USE
- is set; it will be thrown away anyway because each handshake creates
- its own key.
- ssl_cert_dup, which is used by SSL_new, now copies DH keys in addition
- to parameters -- in previous versions (since OpenSSL 0.9.3) the
- 'default key' from SSL_CTX_set_tmp_dh would always be lost, meaning
- you effectively got SSL_OP_SINGLE_DH_USE when using this macro.
- [Bodo Moeller]
-
- *) New s_client option -ign_eof: EOF at stdin is ignored, and
- 'Q' and 'R' lose their special meanings (quit/renegotiate).
- This is part of what -quiet does; unlike -quiet, -ign_eof
- does not suppress any output.
- [Richard Levitte]
-
- *) Add compatibility options to the purpose and trust code. The
- purpose X509_PURPOSE_ANY is "any purpose" which automatically
- accepts a certificate or CA, this was the previous behaviour,
- with all the associated security issues.
-
- X509_TRUST_COMPAT is the old trust behaviour: only and
- automatically trust self signed roots in certificate store. A
- new trust setting X509_TRUST_DEFAULT is used to specify that
- a purpose has no associated trust setting and it should instead
- use the value in the default purpose.
- [Steve Henson]
-
- *) Fix the PKCS#8 DSA private key code so it decodes keys again
- and fix a memory leak.
- [Steve Henson]
-
- *) In util/mkerr.pl (which implements 'make errors'), preserve
- reason strings from the previous version of the .c file, as
- the default to have only downcase letters (and digits) in
- automatically generated reasons codes is not always appropriate.
- [Bodo Moeller]
-
- *) In ERR_load_ERR_strings(), build an ERR_LIB_SYS error reason table
- using strerror. Previously, ERR_reason_error_string() returned
- library names as reason strings for SYSerr; but SYSerr is a special
- case where small numbers are errno values, not library numbers.
- [Bodo Moeller]
-
- *) Add '-dsaparam' option to 'openssl dhparam' application. This
- converts DSA parameters into DH parameters. (When creating parameters,
- DSA_generate_parameters is used.)
- [Bodo Moeller]
-
- *) Include 'length' (recommended exponent length) in C code generated
- by 'openssl dhparam -C'.
- [Bodo Moeller]
-
- *) The second argument to set_label in perlasm was already being used
- so couldn't be used as a "file scope" flag. Moved to third argument
- which was free.
- [Steve Henson]
-
- *) In PEM_ASN1_write_bio and some other functions, use RAND_pseudo_bytes
- instead of RAND_bytes for encryption IVs and salts.
- [Bodo Moeller]
-
- *) Include RAND_status() into RAND_METHOD instead of implementing
- it only for md_rand.c Otherwise replacing the PRNG by calling
- RAND_set_rand_method would be impossible.
- [Bodo Moeller]
-
- *) Don't let DSA_generate_key() enter an infinite loop if the random
- number generation fails.
- [Bodo Moeller]
-
- *) New 'rand' application for creating pseudo-random output.
- [Bodo Moeller]
-
- *) Added configuration support for Linux/IA64
- [Rolf Haberrecker <rolf@suse.de>]
-
- *) Assembler module support for Mingw32.
- [Ulf Möller]
-
- *) Shared library support for HPUX (in shlib/).
- [Lutz Jaenicke <Lutz.Jaenicke@aet.TU-Cottbus.DE> and Anonymous]
-
- *) Shared library support for Solaris gcc.
- [Lutz Behnke <behnke@trustcenter.de>]
-
- Changes between 0.9.4 and 0.9.5 [28 Feb 2000]
-
- *) PKCS7_encrypt() was adding text MIME headers twice because they
- were added manually and by SMIME_crlf_copy().
- [Steve Henson]
-
- *) In bntest.c don't call BN_rand with zero bits argument.
- [Steve Henson, pointed out by Andrew W. Gray <agray@iconsinc.com>]
-
- *) BN_mul bugfix: In bn_mul_part_recursion() only the a>a[n] && b>b[n]
- case was implemented. This caused BN_div_recp() to fail occasionally.
- [Ulf Möller]
-
- *) Add an optional second argument to the set_label() in the perl
- assembly language builder. If this argument exists and is set
- to 1 it signals that the assembler should use a symbol whose
- scope is the entire file, not just the current function. This
- is needed with MASM which uses the format label:: for this scope.
- [Steve Henson, pointed out by Peter Runestig <peter@runestig.com>]
-
- *) Change the ASN1 types so they are typedefs by default. Before
- almost all types were #define'd to ASN1_STRING which was causing
- STACK_OF() problems: you couldn't declare STACK_OF(ASN1_UTF8STRING)
- for example.
- [Steve Henson]
-
- *) Change names of new functions to the new get1/get0 naming
- convention: After 'get1', the caller owns a reference count
- and has to call ..._free; 'get0' returns a pointer to some
- data structure without incrementing reference counters.
- (Some of the existing 'get' functions increment a reference
- counter, some don't.)
- Similarly, 'set1' and 'add1' functions increase reference
- counters or duplicate objects.
- [Steve Henson]
-
- *) Allow for the possibility of temp RSA key generation failure:
- the code used to assume it always worked and crashed on failure.
- [Steve Henson]
-
- *) Fix potential buffer overrun problem in BIO_printf().
- [Ulf Möller, using public domain code by Patrick Powell; problem
- pointed out by David Sacerdote <das33@cornell.edu>]
-
- *) Support EGD <http://www.lothar.com/tech/crypto/>. New functions
- RAND_egd() and RAND_status(). In the command line application,
- the EGD socket can be specified like a seed file using RANDFILE
- or -rand.
- [Ulf Möller]
-
- *) Allow the string CERTIFICATE to be tolerated in PKCS#7 structures.
- Some CAs (e.g. Verisign) distribute certificates in this form.
- [Steve Henson]
-
- *) Remove the SSL_ALLOW_ADH compile option and set the default cipher
- list to exclude them. This means that no special compilation option
- is needed to use anonymous DH: it just needs to be included in the
- cipher list.
- [Steve Henson]
-
- *) Change the EVP_MD_CTX_type macro so its meaning consistent with
- EVP_MD_type. The old functionality is available in a new macro called
- EVP_MD_md(). Change code that uses it and update docs.
- [Steve Henson]
-
- *) ..._ctrl functions now have corresponding ..._callback_ctrl functions
- where the 'void *' argument is replaced by a function pointer argument.
- Previously 'void *' was abused to point to functions, which works on
- many platforms, but is not correct. As these functions are usually
- called by macros defined in OpenSSL header files, most source code
- should work without changes.
- [Richard Levitte]
-
- *) <openssl/opensslconf.h> (which is created by Configure) now contains
- sections with information on -D... compiler switches used for
- compiling the library so that applications can see them. To enable
- one of these sections, a pre-processor symbol OPENSSL_..._DEFINES
- must be defined. E.g.,
- #define OPENSSL_ALGORITHM_DEFINES
- #include <openssl/opensslconf.h>
- defines all pertinent NO_<algo> symbols, such as NO_IDEA, NO_RSA, etc.
- [Richard Levitte, Ulf and Bodo Möller]
-
- *) Bugfix: Tolerate fragmentation and interleaving in the SSL 3/TLS
- record layer.
- [Bodo Moeller]
-
- *) Change the 'other' type in certificate aux info to a STACK_OF
- X509_ALGOR. Although not an AlgorithmIdentifier as such it has
- the required ASN1 format: arbitrary types determined by an OID.
- [Steve Henson]
-
- *) Add some PEM_write_X509_REQ_NEW() functions and a command line
- argument to 'req'. This is not because the function is newer or
- better than others it just uses the work 'NEW' in the certificate
- request header lines. Some software needs this.
- [Steve Henson]
-
- *) Reorganise password command line arguments: now passwords can be
- obtained from various sources. Delete the PEM_cb function and make
- it the default behaviour: i.e. if the callback is NULL and the
- usrdata argument is not NULL interpret it as a null terminated pass
- phrase. If usrdata and the callback are NULL then the pass phrase
- is prompted for as usual.
- [Steve Henson]
-
- *) Add support for the Compaq Atalla crypto accelerator. If it is installed,
- the support is automatically enabled. The resulting binaries will
- autodetect the card and use it if present.
- [Ben Laurie and Compaq Inc.]
-
- *) Work around for Netscape hang bug. This sends certificate request
- and server done in one record. Since this is perfectly legal in the
- SSL/TLS protocol it isn't a "bug" option and is on by default. See
- the bugs/SSLv3 entry for more info.
- [Steve Henson]
-
- *) HP-UX tune-up: new unified configs, HP C compiler bug workaround.
- [Andy Polyakov]
-
- *) Add -rand argument to smime and pkcs12 applications and read/write
- of seed file.
- [Steve Henson]
-
- *) New 'passwd' tool for crypt(3) and apr1 password hashes.
- [Bodo Moeller]
-
- *) Add command line password options to the remaining applications.
- [Steve Henson]
-
- *) Bug fix for BN_div_recp() for numerators with an even number of
- bits.
- [Ulf Möller]
-
- *) More tests in bntest.c, and changed test_bn output.
- [Ulf Möller]
-
- *) ./config recognizes MacOS X now.
- [Andy Polyakov]
-
- *) Bug fix for BN_div() when the first words of num and divisor are
- equal (it gave wrong results if (rem=(n1-q*d0)&BN_MASK2) < d0).
- [Ulf Möller]
-
- *) Add support for various broken PKCS#8 formats, and command line
- options to produce them.
- [Steve Henson]
-
- *) New functions BN_CTX_start(), BN_CTX_get() and BT_CTX_end() to
- get temporary BIGNUMs from a BN_CTX.
- [Ulf Möller]
-
- *) Correct return values in BN_mod_exp_mont() and BN_mod_exp2_mont()
- for p == 0.
- [Ulf Möller]
-
- *) Change the SSLeay_add_all_*() functions to OpenSSL_add_all_*() and
- include a #define from the old name to the new. The original intent
- was that statically linked binaries could for example just call
- SSLeay_add_all_ciphers() to just add ciphers to the table and not
- link with digests. This never worked because SSLeay_add_all_digests()
- and SSLeay_add_all_ciphers() were in the same source file so calling
- one would link with the other. They are now in separate source files.
- [Steve Henson]
-
- *) Add a new -notext option to 'ca' and a -pubkey option to 'spkac'.
- [Steve Henson]
-
- *) Use a less unusual form of the Miller-Rabin primality test (it used
- a binary algorithm for exponentiation integrated into the Miller-Rabin
- loop, our standard modexp algorithms are faster).
- [Bodo Moeller]
-
- *) Support for the EBCDIC character set completed.
- [Martin Kraemer <Martin.Kraemer@Mch.SNI.De>]
-
- *) Source code cleanups: use const where appropriate, eliminate casts,
- use void * instead of char * in lhash.
- [Ulf Möller]
-
- *) Bugfix: ssl3_send_server_key_exchange was not restartable
- (the state was not changed to SSL3_ST_SW_KEY_EXCH_B, and because of
- this the server could overwrite ephemeral keys that the client
- has already seen).
- [Bodo Moeller]
-
- *) Turn DSA_is_prime into a macro that calls BN_is_prime,
- using 50 iterations of the Rabin-Miller test.
-
- DSA_generate_parameters now uses BN_is_prime_fasttest (with 50
- iterations of the Rabin-Miller test as required by the appendix
- to FIPS PUB 186[-1]) instead of DSA_is_prime.
- As BN_is_prime_fasttest includes trial division, DSA parameter
- generation becomes much faster.
-
- This implies a change for the callback functions in DSA_is_prime
- and DSA_generate_parameters: The callback function is called once
- for each positive witness in the Rabin-Miller test, not just
- occasionally in the inner loop; and the parameters to the
- callback function now provide an iteration count for the outer
- loop rather than for the current invocation of the inner loop.
- DSA_generate_parameters additionally can call the callback
- function with an 'iteration count' of -1, meaning that a
- candidate has passed the trial division test (when q is generated
- from an application-provided seed, trial division is skipped).
- [Bodo Moeller]
-
- *) New function BN_is_prime_fasttest that optionally does trial
- division before starting the Rabin-Miller test and has
- an additional BN_CTX * argument (whereas BN_is_prime always
- has to allocate at least one BN_CTX).
- 'callback(1, -1, cb_arg)' is called when a number has passed the
- trial division stage.
- [Bodo Moeller]
-
- *) Fix for bug in CRL encoding. The validity dates weren't being handled
- as ASN1_TIME.
- [Steve Henson]
-
- *) New -pkcs12 option to CA.pl script to write out a PKCS#12 file.
- [Steve Henson]
-
- *) New function BN_pseudo_rand().
- [Ulf Möller]
-
- *) Clean up BN_mod_mul_montgomery(): replace the broken (and unreadable)
- bignum version of BN_from_montgomery() with the working code from
- SSLeay 0.9.0 (the word based version is faster anyway), and clean up
- the comments.
- [Ulf Möller]
-
- *) Avoid a race condition in s2_clnt.c (function get_server_hello) that
- made it impossible to use the same SSL_SESSION data structure in
- SSL2 clients in multiple threads.
- [Bodo Moeller]
-
- *) The return value of RAND_load_file() no longer counts bytes obtained
- by stat(). RAND_load_file(..., -1) is new and uses the complete file
- to seed the PRNG (previously an explicit byte count was required).
- [Ulf Möller, Bodo Möller]
-
- *) Clean up CRYPTO_EX_DATA functions, some of these didn't have prototypes
- used (char *) instead of (void *) and had casts all over the place.
- [Steve Henson]
-
- *) Make BN_generate_prime() return NULL on error if ret!=NULL.
- [Ulf Möller]
-
- *) Retain source code compatibility for BN_prime_checks macro:
- BN_is_prime(..., BN_prime_checks, ...) now uses
- BN_prime_checks_for_size to determine the appropriate number of
- Rabin-Miller iterations.
- [Ulf Möller]
-
- *) Diffie-Hellman uses "safe" primes: DH_check() return code renamed to
- DH_CHECK_P_NOT_SAFE_PRIME.
- (Check if this is true? OpenPGP calls them "strong".)
- [Ulf Möller]
-
- *) Merge the functionality of "dh" and "gendh" programs into a new program
- "dhparam". The old programs are retained for now but will handle DH keys
- (instead of parameters) in future.
- [Steve Henson]
-
- *) Make the ciphers, s_server and s_client programs check the return values
- when a new cipher list is set.
- [Steve Henson]
-
- *) Enhance the SSL/TLS cipher mechanism to correctly handle the TLS 56bit
- ciphers. Before when the 56bit ciphers were enabled the sorting was
- wrong.
-
- The syntax for the cipher sorting has been extended to support sorting by
- cipher-strength (using the strength_bits hard coded in the tables).
- The new command is "@STRENGTH" (see also doc/apps/ciphers.pod).
-
- Fix a bug in the cipher-command parser: when supplying a cipher command
- string with an "undefined" symbol (neither command nor alphanumeric
- [A-Za-z0-9], ssl_set_cipher_list used to hang in an endless loop. Now
- an error is flagged.
-
- Due to the strength-sorting extension, the code of the
- ssl_create_cipher_list() function was completely rearranged. I hope that
- the readability was also increased :-)
- [Lutz Jaenicke <Lutz.Jaenicke@aet.TU-Cottbus.DE>]
-
- *) Minor change to 'x509' utility. The -CAcreateserial option now uses 1
- for the first serial number and places 2 in the serial number file. This
- avoids problems when the root CA is created with serial number zero and
- the first user certificate has the same issuer name and serial number
- as the root CA.
- [Steve Henson]
-
- *) Fixes to X509_ATTRIBUTE utilities, change the 'req' program so it uses
- the new code. Add documentation for this stuff.
- [Steve Henson]
-
- *) Changes to X509_ATTRIBUTE utilities. These have been renamed from
- X509_*() to X509at_*() on the grounds that they don't handle X509
- structures and behave in an analogous way to the X509v3 functions:
- they shouldn't be called directly but wrapper functions should be used
- instead.
-
- So we also now have some wrapper functions that call the X509at functions
- when passed certificate requests. (TO DO: similar things can be done with
- PKCS#7 signed and unsigned attributes, PKCS#12 attributes and a few other
- things. Some of these need some d2i or i2d and print functionality
- because they handle more complex structures.)
- [Steve Henson]
-
- *) Add missing #ifndefs that caused missing symbols when building libssl
- as a shared library without RSA. Use #ifndef NO_SSL2 instead of
- NO_RSA in ssl/s2*.c.
- [Kris Kennaway <kris@hub.freebsd.org>, modified by Ulf Möller]
-
- *) Precautions against using the PRNG uninitialized: RAND_bytes() now
- has a return value which indicates the quality of the random data
- (1 = ok, 0 = not seeded). Also an error is recorded on the thread's
- error queue. New function RAND_pseudo_bytes() generates output that is
- guaranteed to be unique but not unpredictable. RAND_add is like
- RAND_seed, but takes an extra argument for an entropy estimate
- (RAND_seed always assumes full entropy).
- [Ulf Möller]
-
- *) Do more iterations of Rabin-Miller probable prime test (specifically,
- 3 for 1024-bit primes, 6 for 512-bit primes, 12 for 256-bit primes
- instead of only 2 for all lengths; see BN_prime_checks_for_size definition
- in crypto/bn/bn_prime.c for the complete table). This guarantees a
- false-positive rate of at most 2^-80 for random input.
- [Bodo Moeller]
-
- *) Rewrite ssl3_read_n (ssl/s3_pkt.c) avoiding a couple of bugs.
- [Bodo Moeller]
-
- *) New function X509_CTX_rget_chain() (renamed to X509_CTX_get1_chain
- in the 0.9.5 release), this returns the chain
- from an X509_CTX structure with a dup of the stack and all
- the X509 reference counts upped: so the stack will exist
- after X509_CTX_cleanup() has been called. Modify pkcs12.c
- to use this.
-
- Also make SSL_SESSION_print() print out the verify return
- code.
- [Steve Henson]
-
- *) Add manpage for the pkcs12 command. Also change the default
- behaviour so MAC iteration counts are used unless the new
- -nomaciter option is used. This improves file security and
- only older versions of MSIE (4.0 for example) need it.
- [Steve Henson]
-
- *) Honor the no-xxx Configure options when creating .DEF files.
- [Ulf Möller]
-
- *) Add PKCS#10 attributes to field table: challengePassword,
- unstructuredName and unstructuredAddress. These are taken from
- draft PKCS#9 v2.0 but are compatible with v1.2 provided no
- international characters are used.
-
- More changes to X509_ATTRIBUTE code: allow the setting of types
- based on strings. Remove the 'loc' parameter when adding
- attributes because these will be a SET OF encoding which is sorted
- in ASN1 order.
- [Steve Henson]
-
- *) Initial changes to the 'req' utility to allow request generation
- automation. This will allow an application to just generate a template
- file containing all the field values and have req construct the
- request.
-
- Initial support for X509_ATTRIBUTE handling. Stacks of these are
- used all over the place including certificate requests and PKCS#7
- structures. They are currently handled manually where necessary with
- some primitive wrappers for PKCS#7. The new functions behave in a
- manner analogous to the X509 extension functions: they allow
- attributes to be looked up by NID and added.
-
- Later something similar to the X509V3 code would be desirable to
- automatically handle the encoding, decoding and printing of the
- more complex types. The string types like challengePassword can
- be handled by the string table functions.
-
- Also modified the multi byte string table handling. Now there is
- a 'global mask' which masks out certain types. The table itself
- can use the flag STABLE_NO_MASK to ignore the mask setting: this
- is useful when for example there is only one permissible type
- (as in countryName) and using the mask might result in no valid
- types at all.
- [Steve Henson]
-
- *) Clean up 'Finished' handling, and add functions SSL_get_finished and
- SSL_get_peer_finished to allow applications to obtain the latest
- Finished messages sent to the peer or expected from the peer,
- respectively. (SSL_get_peer_finished is usually the Finished message
- actually received from the peer, otherwise the protocol will be aborted.)
-
- As the Finished message are message digests of the complete handshake
- (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can
- be used for external authentication procedures when the authentication
- provided by SSL/TLS is not desired or is not enough.
- [Bodo Moeller]
-
- *) Enhanced support for Alpha Linux is added. Now ./config checks if
- the host supports BWX extension and if Compaq C is present on the
- $PATH. Just exploiting of the BWX extension results in 20-30%
- performance kick for some algorithms, e.g. DES and RC4 to mention
- a couple. Compaq C in turn generates ~20% faster code for MD5 and
- SHA1.
- [Andy Polyakov]
-
- *) Add support for MS "fast SGC". This is arguably a violation of the
- SSL3/TLS protocol. Netscape SGC does two handshakes: the first with
- weak crypto and after checking the certificate is SGC a second one
- with strong crypto. MS SGC stops the first handshake after receiving
- the server certificate message and sends a second client hello. Since
- a server will typically do all the time consuming operations before
- expecting any further messages from the client (server key exchange
- is the most expensive) there is little difference between the two.
-
- To get OpenSSL to support MS SGC we have to permit a second client
- hello message after we have sent server done. In addition we have to
- reset the MAC if we do get this second client hello.
- [Steve Henson]
-
- *) Add a function 'd2i_AutoPrivateKey()' this will automatically decide
- if a DER encoded private key is RSA or DSA traditional format. Changed
- d2i_PrivateKey_bio() to use it. This is only needed for the "traditional"
- format DER encoded private key. Newer code should use PKCS#8 format which
- has the key type encoded in the ASN1 structure. Added DER private key
- support to pkcs8 application.
- [Steve Henson]
-
- *) SSL 3/TLS 1 servers now don't request certificates when an anonymous
- ciphersuites has been selected (as required by the SSL 3/TLS 1
- specifications). Exception: When SSL_VERIFY_FAIL_IF_NO_PEER_CERT
- is set, we interpret this as a request to violate the specification
- (the worst that can happen is a handshake failure, and 'correct'
- behaviour would result in a handshake failure anyway).
- [Bodo Moeller]
-
- *) In SSL_CTX_add_session, take into account that there might be multiple
- SSL_SESSION structures with the same session ID (e.g. when two threads
- concurrently obtain them from an external cache).
- The internal cache can handle only one SSL_SESSION with a given ID,
- so if there's a conflict, we now throw out the old one to achieve
- consistency.
- [Bodo Moeller]
-
- *) Add OIDs for idea and blowfish in CBC mode. This will allow both
- to be used in PKCS#5 v2.0 and S/MIME. Also add checking to
- some routines that use cipher OIDs: some ciphers do not have OIDs
- defined and so they cannot be used for S/MIME and PKCS#5 v2.0 for
- example.
- [Steve Henson]
-
- *) Simplify the trust setting structure and code. Now we just have
- two sequences of OIDs for trusted and rejected settings. These will
- typically have values the same as the extended key usage extension
- and any application specific purposes.
-
- The trust checking code now has a default behaviour: it will just
- check for an object with the same NID as the passed id. Functions can
- be provided to override either the default behaviour or the behaviour
- for a given id. SSL client, server and email already have functions
- in place for compatibility: they check the NID and also return "trusted"
- if the certificate is self signed.
- [Steve Henson]
-
- *) Add d2i,i2d bio/fp functions for PrivateKey: these convert the
- traditional format into an EVP_PKEY structure.
- [Steve Henson]
-
- *) Add a password callback function PEM_cb() which either prompts for
- a password if usr_data is NULL or otherwise assumes it is a null
- terminated password. Allow passwords to be passed on command line
- environment or config files in a few more utilities.
- [Steve Henson]
-
- *) Add a bunch of DER and PEM functions to handle PKCS#8 format private
- keys. Add some short names for PKCS#8 PBE algorithms and allow them
- to be specified on the command line for the pkcs8 and pkcs12 utilities.
- Update documentation.
- [Steve Henson]
-
- *) Support for ASN1 "NULL" type. This could be handled before by using
- ASN1_TYPE but there wasn't any function that would try to read a NULL
- and produce an error if it couldn't. For compatibility we also have
- ASN1_NULL_new() and ASN1_NULL_free() functions but these are faked and
- don't allocate anything because they don't need to.
- [Steve Henson]
-
- *) Initial support for MacOS is now provided. Examine INSTALL.MacOS
- for details.
- [Andy Polyakov, Roy Woods <roy@centicsystems.ca>]
-
- *) Rebuild of the memory allocation routines used by OpenSSL code and
- possibly others as well. The purpose is to make an interface that
- provide hooks so anyone can build a separate set of allocation and
- deallocation routines to be used by OpenSSL, for example memory
- pool implementations, or something else, which was previously hard
- since Malloc(), Realloc() and Free() were defined as macros having
- the values malloc, realloc and free, respectively (except for Win32
- compilations). The same is provided for memory debugging code.
- OpenSSL already comes with functionality to find memory leaks, but
- this gives people a chance to debug other memory problems.
-
- With these changes, a new set of functions and macros have appeared:
-
- CRYPTO_set_mem_debug_functions() [F]
- CRYPTO_get_mem_debug_functions() [F]
- CRYPTO_dbg_set_options() [F]
- CRYPTO_dbg_get_options() [F]
- CRYPTO_malloc_debug_init() [M]
-
- The memory debug functions are NULL by default, unless the library
- is compiled with CRYPTO_MDEBUG or friends is defined. If someone
- wants to debug memory anyway, CRYPTO_malloc_debug_init() (which
- gives the standard debugging functions that come with OpenSSL) or
- CRYPTO_set_mem_debug_functions() (tells OpenSSL to use functions
- provided by the library user) must be used. When the standard
- debugging functions are used, CRYPTO_dbg_set_options can be used to
- request additional information:
- CRYPTO_dbg_set_options(V_CYRPTO_MDEBUG_xxx) corresponds to setting
- the CRYPTO_MDEBUG_xxx macro when compiling the library.
-
- Also, things like CRYPTO_set_mem_functions will always give the
- expected result (the new set of functions is used for allocation
- and deallocation) at all times, regardless of platform and compiler
- options.
-
- To finish it up, some functions that were never use in any other
- way than through macros have a new API and new semantic:
-
- CRYPTO_dbg_malloc()
- CRYPTO_dbg_realloc()
- CRYPTO_dbg_free()
-
- All macros of value have retained their old syntax.
- [Richard Levitte and Bodo Moeller]
-
- *) Some S/MIME fixes. The OID for SMIMECapabilities was wrong, the
- ordering of SMIMECapabilities wasn't in "strength order" and there
- was a missing NULL in the AlgorithmIdentifier for the SHA1 signature
- algorithm.
- [Steve Henson]
-
- *) Some ASN1 types with illegal zero length encoding (INTEGER,
- ENUMERATED and OBJECT IDENTIFIER) choked the ASN1 routines.
- [Frans Heymans <fheymans@isaserver.be>, modified by Steve Henson]
-
- *) Merge in my S/MIME library for OpenSSL. This provides a simple
- S/MIME API on top of the PKCS#7 code, a MIME parser (with enough
- functionality to handle multipart/signed properly) and a utility
- called 'smime' to call all this stuff. This is based on code I
- originally wrote for Celo who have kindly allowed it to be
- included in OpenSSL.
- [Steve Henson]
-
- *) Add variants des_set_key_checked and des_set_key_unchecked of
- des_set_key (aka des_key_sched). Global variable des_check_key
- decides which of these is called by des_set_key; this way
- des_check_key behaves as it always did, but applications and
- the library itself, which was buggy for des_check_key == 1,
- have a cleaner way to pick the version they need.
- [Bodo Moeller]
-
- *) New function PKCS12_newpass() which changes the password of a
- PKCS12 structure.
- [Steve Henson]
-
- *) Modify X509_TRUST and X509_PURPOSE so it also uses a static and
- dynamic mix. In both cases the ids can be used as an index into the
- table. Also modified the X509_TRUST_add() and X509_PURPOSE_add()
- functions so they accept a list of the field values and the
- application doesn't need to directly manipulate the X509_TRUST
- structure.
- [Steve Henson]
-
- *) Modify the ASN1_STRING_TABLE stuff so it also uses bsearch and doesn't
- need initialising.
- [Steve Henson]
-
- *) Modify the way the V3 extension code looks up extensions. This now
- works in a similar way to the object code: we have some "standard"
- extensions in a static table which is searched with OBJ_bsearch()
- and the application can add dynamic ones if needed. The file
- crypto/x509v3/ext_dat.h now has the info: this file needs to be
- updated whenever a new extension is added to the core code and kept
- in ext_nid order. There is a simple program 'tabtest.c' which checks
- this. New extensions are not added too often so this file can readily
- be maintained manually.
-
- There are two big advantages in doing things this way. The extensions
- can be looked up immediately and no longer need to be "added" using
- X509V3_add_standard_extensions(): this function now does nothing.
- [Side note: I get *lots* of email saying the extension code doesn't
- work because people forget to call this function]
- Also no dynamic allocation is done unless new extensions are added:
- so if we don't add custom extensions there is no need to call
- X509V3_EXT_cleanup().
- [Steve Henson]
-
- *) Modify enc utility's salting as follows: make salting the default. Add a
- magic header, so unsalted files fail gracefully instead of just decrypting
- to garbage. This is because not salting is a big security hole, so people
- should be discouraged from doing it.
- [Ben Laurie]
-
- *) Fixes and enhancements to the 'x509' utility. It allowed a message
- digest to be passed on the command line but it only used this
- parameter when signing a certificate. Modified so all relevant
- operations are affected by the digest parameter including the
- -fingerprint and -x509toreq options. Also -x509toreq choked if a
- DSA key was used because it didn't fix the digest.
- [Steve Henson]
-
- *) Initial certificate chain verify code. Currently tests the untrusted
- certificates for consistency with the verify purpose (which is set
- when the X509_STORE_CTX structure is set up) and checks the pathlength.
-
- There is a NO_CHAIN_VERIFY compilation option to keep the old behaviour:
- this is because it will reject chains with invalid extensions whereas
- every previous version of OpenSSL and SSLeay made no checks at all.
-
- Trust code: checks the root CA for the relevant trust settings. Trust
- settings have an initial value consistent with the verify purpose: e.g.
- if the verify purpose is for SSL client use it expects the CA to be
- trusted for SSL client use. However the default value can be changed to
- permit custom trust settings: one example of this would be to only trust
- certificates from a specific "secure" set of CAs.
-
- Also added X509_STORE_CTX_new() and X509_STORE_CTX_free() functions
- which should be used for version portability: especially since the
- verify structure is likely to change more often now.
-
- SSL integration. Add purpose and trust to SSL_CTX and SSL and functions
- to set them. If not set then assume SSL clients will verify SSL servers
- and vice versa.
-
- Two new options to the verify program: -untrusted allows a set of
- untrusted certificates to be passed in and -purpose which sets the
- intended purpose of the certificate. If a purpose is set then the
- new chain verify code is used to check extension consistency.
- [Steve Henson]
-
- *) Support for the authority information access extension.
- [Steve Henson]
-
- *) Modify RSA and DSA PEM read routines to transparently handle
- PKCS#8 format private keys. New *_PUBKEY_* functions that handle
- public keys in a format compatible with certificate
- SubjectPublicKeyInfo structures. Unfortunately there were already
- functions called *_PublicKey_* which used various odd formats so
- these are retained for compatibility: however the DSA variants were
- never in a public release so they have been deleted. Changed dsa/rsa
- utilities to handle the new format: note no releases ever handled public
- keys so we should be OK.
-
- The primary motivation for this change is to avoid the same fiasco
- that dogs private keys: there are several incompatible private key
- formats some of which are standard and some OpenSSL specific and
- require various evil hacks to allow partial transparent handling and
- even then it doesn't work with DER formats. Given the option anything
- other than PKCS#8 should be dumped: but the other formats have to
- stay in the name of compatibility.
-
- With public keys and the benefit of hindsight one standard format
- is used which works with EVP_PKEY, RSA or DSA structures: though
- it clearly returns an error if you try to read the wrong kind of key.
-
- Added a -pubkey option to the 'x509' utility to output the public key.
- Also rename the EVP_PKEY_get_*() to EVP_PKEY_rget_*()
- (renamed to EVP_PKEY_get1_*() in the OpenSSL 0.9.5 release) and add
- EVP_PKEY_rset_*() functions (renamed to EVP_PKEY_set1_*())
- that do the same as the EVP_PKEY_assign_*() except they up the
- reference count of the added key (they don't "swallow" the
- supplied key).
- [Steve Henson]
-
- *) Fixes to crypto/x509/by_file.c the code to read in certificates and
- CRLs would fail if the file contained no certificates or no CRLs:
- added a new function to read in both types and return the number
- read: this means that if none are read it will be an error. The
- DER versions of the certificate and CRL reader would always fail
- because it isn't possible to mix certificates and CRLs in DER format
- without choking one or the other routine. Changed this to just read
- a certificate: this is the best we can do. Also modified the code
- in apps/verify.c to take notice of return codes: it was previously
- attempting to read in certificates from NULL pointers and ignoring
- any errors: this is one reason why the cert and CRL reader seemed
- to work. It doesn't check return codes from the default certificate
- routines: these may well fail if the certificates aren't installed.
- [Steve Henson]
-
- *) Code to support otherName option in GeneralName.
- [Steve Henson]
-
- *) First update to verify code. Change the verify utility
- so it warns if it is passed a self signed certificate:
- for consistency with the normal behaviour. X509_verify
- has been modified to it will now verify a self signed
- certificate if *exactly* the same certificate appears
- in the store: it was previously impossible to trust a
- single self signed certificate. This means that:
- openssl verify ss.pem
- now gives a warning about a self signed certificate but
- openssl verify -CAfile ss.pem ss.pem
- is OK.
- [Steve Henson]
-
- *) For servers, store verify_result in SSL_SESSION data structure
- (and add it to external session representation).
- This is needed when client certificate verifications fails,
- but an application-provided verification callback (set by
- SSL_CTX_set_cert_verify_callback) allows accepting the session
- anyway (i.e. leaves x509_store_ctx->error != X509_V_OK
- but returns 1): When the session is reused, we have to set
- ssl->verify_result to the appropriate error code to avoid
- security holes.
- [Bodo Moeller, problem pointed out by Lutz Jaenicke]
-
- *) Fix a bug in the new PKCS#7 code: it didn't consider the
- case in PKCS7_dataInit() where the signed PKCS7 structure
- didn't contain any existing data because it was being created.
- [Po-Cheng Chen <pocheng@nst.com.tw>, slightly modified by Steve Henson]
-
- *) Add a salt to the key derivation routines in enc.c. This
- forms the first 8 bytes of the encrypted file. Also add a
- -S option to allow a salt to be input on the command line.
- [Steve Henson]
-
- *) New function X509_cmp(). Oddly enough there wasn't a function
- to compare two certificates. We do this by working out the SHA1
- hash and comparing that. X509_cmp() will be needed by the trust
- code.
- [Steve Henson]
-
- *) SSL_get1_session() is like SSL_get_session(), but increments
- the reference count in the SSL_SESSION returned.
- [Geoff Thorpe <geoff@eu.c2.net>]
-
- *) Fix for 'req': it was adding a null to request attributes.
- Also change the X509_LOOKUP and X509_INFO code to handle
- certificate auxiliary information.
- [Steve Henson]
-
- *) Add support for 40 and 64 bit RC2 and RC4 algorithms: document
- the 'enc' command.
- [Steve Henson]
-
- *) Add the possibility to add extra information to the memory leak
- detecting output, to form tracebacks, showing from where each
- allocation was originated: CRYPTO_push_info("constant string") adds
- the string plus current file name and line number to a per-thread
- stack, CRYPTO_pop_info() does the obvious, CRYPTO_remove_all_info()
- is like calling CYRPTO_pop_info() until the stack is empty.
- Also updated memory leak detection code to be multi-thread-safe.
- [Richard Levitte]
-
- *) Add options -text and -noout to pkcs7 utility and delete the
- encryption options which never did anything. Update docs.
- [Steve Henson]
-
- *) Add options to some of the utilities to allow the pass phrase
- to be included on either the command line (not recommended on
- OSes like Unix) or read from the environment. Update the
- manpages and fix a few bugs.
- [Steve Henson]
-
- *) Add a few manpages for some of the openssl commands.
- [Steve Henson]
-
- *) Fix the -revoke option in ca. It was freeing up memory twice,
- leaking and not finding already revoked certificates.
- [Steve Henson]
-
- *) Extensive changes to support certificate auxiliary information.
- This involves the use of X509_CERT_AUX structure and X509_AUX
- functions. An X509_AUX function such as PEM_read_X509_AUX()
- can still read in a certificate file in the usual way but it
- will also read in any additional "auxiliary information". By
- doing things this way a fair degree of compatibility can be
- retained: existing certificates can have this information added
- using the new 'x509' options.
-
- Current auxiliary information includes an "alias" and some trust
- settings. The trust settings will ultimately be used in enhanced
- certificate chain verification routines: currently a certificate
- can only be trusted if it is self signed and then it is trusted
- for all purposes.
- [Steve Henson]
-
- *) Fix assembler for Alpha (tested only on DEC OSF not Linux or *BSD).
- The problem was that one of the replacement routines had not been working
- since SSLeay releases. For now the offending routine has been replaced
- with non-optimised assembler. Even so, this now gives around 95%
- performance improvement for 1024 bit RSA signs.
- [Mark Cox]
-
- *) Hack to fix PKCS#7 decryption when used with some unorthodox RC2
- handling. Most clients have the effective key size in bits equal to
- the key length in bits: so a 40 bit RC2 key uses a 40 bit (5 byte) key.
- A few however don't do this and instead use the size of the decrypted key
- to determine the RC2 key length and the AlgorithmIdentifier to determine
- the effective key length. In this case the effective key length can still
- be 40 bits but the key length can be 168 bits for example. This is fixed
- by manually forcing an RC2 key into the EVP_PKEY structure because the
- EVP code can't currently handle unusual RC2 key sizes: it always assumes
- the key length and effective key length are equal.
- [Steve Henson]
-
- *) Add a bunch of functions that should simplify the creation of
- X509_NAME structures. Now you should be able to do:
- X509_NAME_add_entry_by_txt(nm, "CN", MBSTRING_ASC, "Steve", -1, -1, 0);
- and have it automatically work out the correct field type and fill in
- the structures. The more adventurous can try:
- X509_NAME_add_entry_by_txt(nm, field, MBSTRING_UTF8, str, -1, -1, 0);
- and it will (hopefully) work out the correct multibyte encoding.
- [Steve Henson]
-
- *) Change the 'req' utility to use the new field handling and multibyte
- copy routines. Before the DN field creation was handled in an ad hoc
- way in req, ca, and x509 which was rather broken and didn't support
- BMPStrings or UTF8Strings. Since some software doesn't implement
- BMPStrings or UTF8Strings yet, they can be enabled using the config file
- using the dirstring_type option. See the new comment in the default
- openssl.cnf for more info.
- [Steve Henson]
-
- *) Make crypto/rand/md_rand.c more robust:
- - Assure unique random numbers after fork().
- - Make sure that concurrent threads access the global counter and
- md serializably so that we never lose entropy in them
- or use exactly the same state in multiple threads.
- Access to the large state is not always serializable because
- the additional locking could be a performance killer, and
- md should be large enough anyway.
- [Bodo Moeller]
-
- *) New file apps/app_rand.c with commonly needed functionality
- for handling the random seed file.
-
- Use the random seed file in some applications that previously did not:
- ca,
- dsaparam -genkey (which also ignored its '-rand' option),
- s_client,
- s_server,
- x509 (when signing).
- Except on systems with /dev/urandom, it is crucial to have a random
- seed file at least for key creation, DSA signing, and for DH exchanges;
- for RSA signatures we could do without one.
-
- gendh and gendsa (unlike genrsa) used to read only the first byte
- of each file listed in the '-rand' option. The function as previously
- found in genrsa is now in app_rand.c and is used by all programs
- that support '-rand'.
- [Bodo Moeller]
-
- *) In RAND_write_file, use mode 0600 for creating files;
- don't just chmod when it may be too late.
- [Bodo Moeller]
-
- *) Report an error from X509_STORE_load_locations
- when X509_LOOKUP_load_file or X509_LOOKUP_add_dir failed.
- [Bill Perry]
-
- *) New function ASN1_mbstring_copy() this copies a string in either
- ASCII, Unicode, Universal (4 bytes per character) or UTF8 format
- into an ASN1_STRING type. A mask of permissible types is passed
- and it chooses the "minimal" type to use or an error if not type
- is suitable.
- [Steve Henson]
-
- *) Add function equivalents to the various macros in asn1.h. The old
- macros are retained with an M_ prefix. Code inside the library can
- use the M_ macros. External code (including the openssl utility)
- should *NOT* in order to be "shared library friendly".
- [Steve Henson]
-
- *) Add various functions that can check a certificate's extensions
- to see if it usable for various purposes such as SSL client,
- server or S/MIME and CAs of these types. This is currently
- VERY EXPERIMENTAL but will ultimately be used for certificate chain
- verification. Also added a -purpose flag to x509 utility to
- print out all the purposes.
- [Steve Henson]
-
- *) Add a CRYPTO_EX_DATA to X509 certificate structure and associated
- functions.
- [Steve Henson]
-
- *) New X509V3_{X509,CRL,REVOKED}_get_d2i() functions. These will search
- for, obtain and decode and extension and obtain its critical flag.
- This allows all the necessary extension code to be handled in a
- single function call.
- [Steve Henson]
-
- *) RC4 tune-up featuring 30-40% performance improvement on most RISC
- platforms. See crypto/rc4/rc4_enc.c for further details.
- [Andy Polyakov]
-
- *) New -noout option to asn1parse. This causes no output to be produced
- its main use is when combined with -strparse and -out to extract data
- from a file (which may not be in ASN.1 format).
- [Steve Henson]
-
- *) Fix for pkcs12 program. It was hashing an invalid certificate pointer
- when producing the local key id.
- [Richard Levitte <levitte@stacken.kth.se>]
-
- *) New option -dhparam in s_server. This allows a DH parameter file to be
- stated explicitly. If it is not stated then it tries the first server
- certificate file. The previous behaviour hard coded the filename
- "server.pem".
- [Steve Henson]
-
- *) Add -pubin and -pubout options to the rsa and dsa commands. These allow
- a public key to be input or output. For example:
- openssl rsa -in key.pem -pubout -out pubkey.pem
- Also added necessary DSA public key functions to handle this.
- [Steve Henson]
-
- *) Fix so PKCS7_dataVerify() doesn't crash if no certificates are contained
- in the message. This was handled by allowing
- X509_find_by_issuer_and_serial() to tolerate a NULL passed to it.
- [Steve Henson, reported by Sampo Kellomaki <sampo@mail.neuronio.pt>]
-
- *) Fix for bug in d2i_ASN1_bytes(): other ASN1 functions add an extra null
- to the end of the strings whereas this didn't. This would cause problems
- if strings read with d2i_ASN1_bytes() were later modified.
- [Steve Henson, reported by Arne Ansper <arne@ats.cyber.ee>]
-
- *) Fix for base64 decode bug. When a base64 bio reads only one line of
- data and it contains EOF it will end up returning an error. This is
- caused by input 46 bytes long. The cause is due to the way base64
- BIOs find the start of base64 encoded data. They do this by trying a
- trial decode on each line until they find one that works. When they
- do a flag is set and it starts again knowing it can pass all the
- data directly through the decoder. Unfortunately it doesn't reset
- the context it uses. This means that if EOF is reached an attempt
- is made to pass two EOFs through the context and this causes the
- resulting error. This can also cause other problems as well. As is
- usual with these problems it takes *ages* to find and the fix is
- trivial: move one line.
- [Steve Henson, reported by ian@uns.ns.ac.yu (Ivan Nejgebauer) ]
-
- *) Ugly workaround to get s_client and s_server working under Windows. The
- old code wouldn't work because it needed to select() on sockets and the
- tty (for keypresses and to see if data could be written). Win32 only
- supports select() on sockets so we select() with a 1s timeout on the
- sockets and then see if any characters are waiting to be read, if none
- are present then we retry, we also assume we can always write data to
- the tty. This isn't nice because the code then blocks until we've
- received a complete line of data and it is effectively polling the
- keyboard at 1s intervals: however it's quite a bit better than not
- working at all :-) A dedicated Windows application might handle this
- with an event loop for example.
- [Steve Henson]
-
- *) Enhance RSA_METHOD structure. Now there are two extra methods, rsa_sign
- and rsa_verify. When the RSA_FLAGS_SIGN_VER option is set these functions
- will be called when RSA_sign() and RSA_verify() are used. This is useful
- if rsa_pub_dec() and rsa_priv_enc() equivalents are not available.
- For this to work properly RSA_public_decrypt() and RSA_private_encrypt()
- should *not* be used: RSA_sign() and RSA_verify() must be used instead.
- This necessitated the support of an extra signature type NID_md5_sha1
- for SSL signatures and modifications to the SSL library to use it instead
- of calling RSA_public_decrypt() and RSA_private_encrypt().
- [Steve Henson]
-
- *) Add new -verify -CAfile and -CApath options to the crl program, these
- will lookup a CRL issuers certificate and verify the signature in a
- similar way to the verify program. Tidy up the crl program so it
- no longer accesses structures directly. Make the ASN1 CRL parsing a bit
- less strict. It will now permit CRL extensions even if it is not
- a V2 CRL: this will allow it to tolerate some broken CRLs.
- [Steve Henson]
-
- *) Initialize all non-automatic variables each time one of the openssl
- sub-programs is started (this is necessary as they may be started
- multiple times from the "OpenSSL>" prompt).
- [Lennart Bang, Bodo Moeller]
-
- *) Preliminary compilation option RSA_NULL which disables RSA crypto without
- removing all other RSA functionality (this is what NO_RSA does). This
- is so (for example) those in the US can disable those operations covered
- by the RSA patent while allowing storage and parsing of RSA keys and RSA
- key generation.
- [Steve Henson]
-
- *) Non-copying interface to BIO pairs.
- (still largely untested)
- [Bodo Moeller]
-
- *) New function ANS1_tag2str() to convert an ASN1 tag to a descriptive
- ASCII string. This was handled independently in various places before.
- [Steve Henson]
-
- *) New functions UTF8_getc() and UTF8_putc() that parse and generate
- UTF8 strings a character at a time.
- [Steve Henson]
-
- *) Use client_version from client hello to select the protocol
- (s23_srvr.c) and for RSA client key exchange verification
- (s3_srvr.c), as required by the SSL 3.0/TLS 1.0 specifications.
- [Bodo Moeller]
-
- *) Add various utility functions to handle SPKACs, these were previously
- handled by poking round in the structure internals. Added new function
- NETSCAPE_SPKI_print() to print out SPKAC and a new utility 'spkac' to
- print, verify and generate SPKACs. Based on an original idea from
- Massimiliano Pala <madwolf@comune.modena.it> but extensively modified.
- [Steve Henson]
-
- *) RIPEMD160 is operational on all platforms and is back in 'make test'.
- [Andy Polyakov]
-
- *) Allow the config file extension section to be overwritten on the
- command line. Based on an original idea from Massimiliano Pala
- <madwolf@comune.modena.it>. The new option is called -extensions
- and can be applied to ca, req and x509. Also -reqexts to override
- the request extensions in req and -crlexts to override the crl extensions
- in ca.
- [Steve Henson]
-
- *) Add new feature to the SPKAC handling in ca. Now you can include
- the same field multiple times by preceding it by "XXXX." for example:
- 1.OU="Unit name 1"
- 2.OU="Unit name 2"
- this is the same syntax as used in the req config file.
- [Steve Henson]
-
- *) Allow certificate extensions to be added to certificate requests. These
- are specified in a 'req_extensions' option of the req section of the
- config file. They can be printed out with the -text option to req but
- are otherwise ignored at present.
- [Steve Henson]
-
- *) Fix a horrible bug in enc_read() in crypto/evp/bio_enc.c: if the first
- data read consists of only the final block it would not decrypted because
- EVP_CipherUpdate() would correctly report zero bytes had been decrypted.
- A misplaced 'break' also meant the decrypted final block might not be
- copied until the next read.
- [Steve Henson]
-
- *) Initial support for DH_METHOD. Again based on RSA_METHOD. Also added
- a few extra parameters to the DH structure: these will be useful if
- for example we want the value of 'q' or implement X9.42 DH.
- [Steve Henson]
-
- *) Initial support for DSA_METHOD. This is based on the RSA_METHOD and
- provides hooks that allow the default DSA functions or functions on a
- "per key" basis to be replaced. This allows hardware acceleration and
- hardware key storage to be handled without major modification to the
- library. Also added low level modexp hooks and CRYPTO_EX structure and
- associated functions.
- [Steve Henson]
-
- *) Add a new flag to memory BIOs, BIO_FLAG_MEM_RDONLY. This marks the BIO
- as "read only": it can't be written to and the buffer it points to will
- not be freed. Reading from a read only BIO is much more efficient than
- a normal memory BIO. This was added because there are several times when
- an area of memory needs to be read from a BIO. The previous method was
- to create a memory BIO and write the data to it, this results in two
- copies of the data and an O(n^2) reading algorithm. There is a new
- function BIO_new_mem_buf() which creates a read only memory BIO from
- an area of memory. Also modified the PKCS#7 routines to use read only
- memory BIOs.
- [Steve Henson]
-
- *) Bugfix: ssl23_get_client_hello did not work properly when called in
- state SSL23_ST_SR_CLNT_HELLO_B, i.e. when the first 7 bytes of
- a SSLv2-compatible client hello for SSLv3 or TLSv1 could be read,
- but a retry condition occurred while trying to read the rest.
- [Bodo Moeller]
-
- *) The PKCS7_ENC_CONTENT_new() function was setting the content type as
- NID_pkcs7_encrypted by default: this was wrong since this should almost
- always be NID_pkcs7_data. Also modified the PKCS7_set_type() to handle
- the encrypted data type: this is a more sensible place to put it and it
- allows the PKCS#12 code to be tidied up that duplicated this
- functionality.
- [Steve Henson]
-
- *) Changed obj_dat.pl script so it takes its input and output files on
- the command line. This should avoid shell escape redirection problems
- under Win32.
- [Steve Henson]
-
- *) Initial support for certificate extension requests, these are included
- in things like Xenroll certificate requests. Included functions to allow
- extensions to be obtained and added.
- [Steve Henson]
-
- *) -crlf option to s_client and s_server for sending newlines as
- CRLF (as required by many protocols).
- [Bodo Moeller]
-
- Changes between 0.9.3a and 0.9.4 [09 Aug 1999]
-
- *) Install libRSAglue.a when OpenSSL is built with RSAref.
- [Ralf S. Engelschall]
-
- *) A few more ``#ifndef NO_FP_API / #endif'' pairs for consistency.
- [Andrija Antonijevic <TheAntony2@bigfoot.com>]
-
- *) Fix -startdate and -enddate (which was missing) arguments to 'ca'
- program.
- [Steve Henson]
-
- *) New function DSA_dup_DH, which duplicates DSA parameters/keys as
- DH parameters/keys (q is lost during that conversion, but the resulting
- DH parameters contain its length).
-
- For 1024-bit p, DSA_generate_parameters followed by DSA_dup_DH is
- much faster than DH_generate_parameters (which creates parameters
- where p = 2*q + 1), and also the smaller q makes DH computations
- much more efficient (160-bit exponentiation instead of 1024-bit
- exponentiation); so this provides a convenient way to support DHE
- ciphersuites in SSL/TLS servers (see ssl/ssltest.c). It is of
- utter importance to use
- SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE);
- or
- SSL_set_options(s_ctx, SSL_OP_SINGLE_DH_USE);
- when such DH parameters are used, because otherwise small subgroup
- attacks may become possible!
- [Bodo Moeller]
-
- *) Avoid memory leak in i2d_DHparams.
- [Bodo Moeller]
-
- *) Allow the -k option to be used more than once in the enc program:
- this allows the same encrypted message to be read by multiple recipients.
- [Steve Henson]
-
- *) New function OBJ_obj2txt(buf, buf_len, a, no_name), this converts
- an ASN1_OBJECT to a text string. If the "no_name" parameter is set then
- it will always use the numerical form of the OID, even if it has a short
- or long name.
- [Steve Henson]
-
- *) Added an extra RSA flag: RSA_FLAG_EXT_PKEY. Previously the rsa_mod_exp
- method only got called if p,q,dmp1,dmq1,iqmp components were present,
- otherwise bn_mod_exp was called. In the case of hardware keys for example
- no private key components need be present and it might store extra data
- in the RSA structure, which cannot be accessed from bn_mod_exp.
- By setting RSA_FLAG_EXT_PKEY rsa_mod_exp will always be called for
- private key operations.
- [Steve Henson]
-
- *) Added support for SPARC Linux.
- [Andy Polyakov]
-
- *) pem_password_cb function type incompatibly changed from
- typedef int pem_password_cb(char *buf, int size, int rwflag);
- to
- ....(char *buf, int size, int rwflag, void *userdata);
- so that applications can pass data to their callbacks:
- The PEM[_ASN1]_{read,write}... functions and macros now take an
- additional void * argument, which is just handed through whenever
- the password callback is called.
- [Damien Miller <dmiller@ilogic.com.au>; tiny changes by Bodo Moeller]
-
- New function SSL_CTX_set_default_passwd_cb_userdata.
-
- Compatibility note: As many C implementations push function arguments
- onto the stack in reverse order, the new library version is likely to
- interoperate with programs that have been compiled with the old
- pem_password_cb definition (PEM_whatever takes some data that
- happens to be on the stack as its last argument, and the callback
- just ignores this garbage); but there is no guarantee whatsoever that
- this will work.
-
- *) The -DPLATFORM="\"$(PLATFORM)\"" definition and the similar -DCFLAGS=...
- (both in crypto/Makefile.ssl for use by crypto/cversion.c) caused
- problems not only on Windows, but also on some Unix platforms.
- To avoid problematic command lines, these definitions are now in an
- auto-generated file crypto/buildinf.h (created by crypto/Makefile.ssl
- for standard "make" builds, by util/mk1mf.pl for "mk1mf" builds).
- [Bodo Moeller]
-
- *) MIPS III/IV assembler module is reimplemented.
- [Andy Polyakov]
-
- *) More DES library cleanups: remove references to srand/rand and
- delete an unused file.
- [Ulf Möller]
-
- *) Add support for the free Netwide assembler (NASM) under Win32,
- since not many people have MASM (ml) and it can be hard to obtain.
- This is currently experimental but it seems to work OK and pass all
- the tests. Check out INSTALL.W32 for info.
- [Steve Henson]
-
- *) Fix memory leaks in s3_clnt.c: All non-anonymous SSL3/TLS1 connections
- without temporary keys kept an extra copy of the server key,
- and connections with temporary keys did not free everything in case
- of an error.
- [Bodo Moeller]
-
- *) New function RSA_check_key and new openssl rsa option -check
- for verifying the consistency of RSA keys.
- [Ulf Moeller, Bodo Moeller]
-
- *) Various changes to make Win32 compile work:
- 1. Casts to avoid "loss of data" warnings in p5_crpt2.c
- 2. Change unsigned int to int in b_dump.c to avoid "signed/unsigned
- comparison" warnings.
- 3. Add sk_<TYPE>_sort to DEF file generator and do make update.
- [Steve Henson]
-
- *) Add a debugging option to PKCS#5 v2 key generation function: when
- you #define DEBUG_PKCS5V2 passwords, salts, iteration counts and
- derived keys are printed to stderr.
- [Steve Henson]
-
- *) Copy the flags in ASN1_STRING_dup().
- [Roman E. Pavlov <pre@mo.msk.ru>]
-
- *) The x509 application mishandled signing requests containing DSA
- keys when the signing key was also DSA and the parameters didn't match.
-
- It was supposed to omit the parameters when they matched the signing key:
- the verifying software was then supposed to automatically use the CA's
- parameters if they were absent from the end user certificate.
-
- Omitting parameters is no longer recommended. The test was also
- the wrong way round! This was probably due to unusual behaviour in
- EVP_cmp_parameters() which returns 1 if the parameters match.
- This meant that parameters were omitted when they *didn't* match and
- the certificate was useless. Certificates signed with 'ca' didn't have
- this bug.
- [Steve Henson, reported by Doug Erickson <Doug.Erickson@Part.NET>]
-
- *) Memory leak checking (-DCRYPTO_MDEBUG) had some problems.
- The interface is as follows:
- Applications can use
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON) aka MemCheck_start(),
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF) aka MemCheck_stop();
- "off" is now the default.
- The library internally uses
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE) aka MemCheck_off(),
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE) aka MemCheck_on()
- to disable memory-checking temporarily.
-
- Some inconsistent states that previously were possible (and were
- even the default) are now avoided.
-
- -DCRYPTO_MDEBUG_TIME is new and additionally stores the current time
- with each memory chunk allocated; this is occasionally more helpful
- than just having a counter.
-
- -DCRYPTO_MDEBUG_THREAD is also new and adds the thread ID.
-
- -DCRYPTO_MDEBUG_ALL enables all of the above, plus any future
- extensions.
- [Bodo Moeller]
-
- *) Introduce "mode" for SSL structures (with defaults in SSL_CTX),
- which largely parallels "options", but is for changing API behaviour,
- whereas "options" are about protocol behaviour.
- Initial "mode" flags are:
-
- SSL_MODE_ENABLE_PARTIAL_WRITE Allow SSL_write to report success when
- a single record has been written.
- SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER Don't insist that SSL_write
- retries use the same buffer location.
- (But all of the contents must be
- copied!)
- [Bodo Moeller]
-
- *) Bugfix: SSL_set_options ignored its parameter, only SSL_CTX_set_options
- worked.
-
- *) Fix problems with no-hmac etc.
- [Ulf Möller, pointed out by Brian Wellington <bwelling@tislabs.com>]
-
- *) New functions RSA_get_default_method(), RSA_set_method() and
- RSA_get_method(). These allows replacement of RSA_METHODs without having
- to mess around with the internals of an RSA structure.
- [Steve Henson]
-
- *) Fix memory leaks in DSA_do_sign and DSA_is_prime.
- Also really enable memory leak checks in openssl.c and in some
- test programs.
- [Chad C. Mulligan, Bodo Moeller]
-
- *) Fix a bug in d2i_ASN1_INTEGER() and i2d_ASN1_INTEGER() which can mess
- up the length of negative integers. This has now been simplified to just
- store the length when it is first determined and use it later, rather
- than trying to keep track of where data is copied and updating it to
- point to the end.
- [Steve Henson, reported by Brien Wheeler
- <bwheeler@authentica-security.com>]
-
- *) Add a new function PKCS7_signatureVerify. This allows the verification
- of a PKCS#7 signature but with the signing certificate passed to the
- function itself. This contrasts with PKCS7_dataVerify which assumes the
- certificate is present in the PKCS#7 structure. This isn't always the
- case: certificates can be omitted from a PKCS#7 structure and be
- distributed by "out of band" means (such as a certificate database).
- [Steve Henson]
-
- *) Complete the PEM_* macros with DECLARE_PEM versions to replace the
- function prototypes in pem.h, also change util/mkdef.pl to add the
- necessary function names.
- [Steve Henson]
-
- *) mk1mf.pl (used by Windows builds) did not properly read the
- options set by Configure in the top level Makefile, and Configure
- was not even able to write more than one option correctly.
- Fixed, now "no-idea no-rc5 -DCRYPTO_MDEBUG" etc. works as intended.
- [Bodo Moeller]
-
- *) New functions CONF_load_bio() and CONF_load_fp() to allow a config
- file to be loaded from a BIO or FILE pointer. The BIO version will
- for example allow memory BIOs to contain config info.
- [Steve Henson]
-
- *) New function "CRYPTO_num_locks" that returns CRYPTO_NUM_LOCKS.
- Whoever hopes to achieve shared-library compatibility across versions
- must use this, not the compile-time macro.
- (Exercise 0.9.4: Which is the minimum library version required by
- such programs?)
- Note: All this applies only to multi-threaded programs, others don't
- need locks.
- [Bodo Moeller]
-
- *) Add missing case to s3_clnt.c state machine -- one of the new SSL tests
- through a BIO pair triggered the default case, i.e.
- SSLerr(...,SSL_R_UNKNOWN_STATE).
- [Bodo Moeller]
-
- *) New "BIO pair" concept (crypto/bio/bss_bio.c) so that applications
- can use the SSL library even if none of the specific BIOs is
- appropriate.
- [Bodo Moeller]
-
- *) Fix a bug in i2d_DSAPublicKey() which meant it returned the wrong value
- for the encoded length.
- [Jeon KyoungHo <khjeon@sds.samsung.co.kr>]
-
- *) Add initial documentation of the X509V3 functions.
- [Steve Henson]
-
- *) Add a new pair of functions PEM_write_PKCS8PrivateKey() and
- PEM_write_bio_PKCS8PrivateKey() that are equivalent to
- PEM_write_PrivateKey() and PEM_write_bio_PrivateKey() but use the more
- secure PKCS#8 private key format with a high iteration count.
- [Steve Henson]
-
- *) Fix determination of Perl interpreter: A perl or perl5
- _directory_ in $PATH was also accepted as the interpreter.
- [Ralf S. Engelschall]
-
- *) Fix demos/sign/sign.c: well there wasn't anything strictly speaking
- wrong with it but it was very old and did things like calling
- PEM_ASN1_read() directly and used MD5 for the hash not to mention some
- unusual formatting.
- [Steve Henson]
-
- *) Fix demos/selfsign.c: it used obsolete and deleted functions, changed
- to use the new extension code.
- [Steve Henson]
-
- *) Implement the PEM_read/PEM_write functions in crypto/pem/pem_all.c
- with macros. This should make it easier to change their form, add extra
- arguments etc. Fix a few PEM prototypes which didn't have cipher as a
- constant.
- [Steve Henson]
-
- *) Add to configuration table a new entry that can specify an alternative
- name for unistd.h (for pre-POSIX systems); we need this for NeXTstep,
- according to Mark Crispin <MRC@Panda.COM>.
- [Bodo Moeller]
-
-#if 0
- *) DES CBC did not update the IV. Weird.
- [Ben Laurie]
-#else
- des_cbc_encrypt does not update the IV, but des_ncbc_encrypt does.
- Changing the behaviour of the former might break existing programs --
- where IV updating is needed, des_ncbc_encrypt can be used.
-#endif
-
- *) When bntest is run from "make test" it drives bc to check its
- calculations, as well as internally checking them. If an internal check
- fails, it needs to cause bc to give a non-zero result or make test carries
- on without noticing the failure. Fixed.
- [Ben Laurie]
-
- *) DES library cleanups.
- [Ulf Möller]
-
- *) Add support for PKCS#5 v2.0 PBE algorithms. This will permit PKCS#8 to be
- used with any cipher unlike PKCS#5 v1.5 which can at most handle 64 bit
- ciphers. NOTE: although the key derivation function has been verified
- against some published test vectors it has not been extensively tested
- yet. Added a -v2 "cipher" option to pkcs8 application to allow the use
- of v2.0.
- [Steve Henson]
-
- *) Instead of "mkdir -p", which is not fully portable, use new
- Perl script "util/mkdir-p.pl".
- [Bodo Moeller]
-
- *) Rewrite the way password based encryption (PBE) is handled. It used to
- assume that the ASN1 AlgorithmIdentifier parameter was a PBEParameter
- structure. This was true for the PKCS#5 v1.5 and PKCS#12 PBE algorithms
- but doesn't apply to PKCS#5 v2.0 where it can be something else. Now
- the 'parameter' field of the AlgorithmIdentifier is passed to the
- underlying key generation function so it must do its own ASN1 parsing.
- This has also changed the EVP_PBE_CipherInit() function which now has a
- 'parameter' argument instead of literal salt and iteration count values
- and the function EVP_PBE_ALGOR_CipherInit() has been deleted.
- [Steve Henson]
-
- *) Support for PKCS#5 v1.5 compatible password based encryption algorithms
- and PKCS#8 functionality. New 'pkcs8' application linked to openssl.
- Needed to change the PEM_STRING_EVP_PKEY value which was just "PRIVATE
- KEY" because this clashed with PKCS#8 unencrypted string. Since this
- value was just used as a "magic string" and not used directly its
- value doesn't matter.
- [Steve Henson]
-
- *) Introduce some semblance of const correctness to BN. Shame C doesn't
- support mutable.
- [Ben Laurie]
-
- *) "linux-sparc64" configuration (ultrapenguin).
- [Ray Miller <ray.miller@oucs.ox.ac.uk>]
- "linux-sparc" configuration.
- [Christian Forster <fo@hawo.stw.uni-erlangen.de>]
-
- *) config now generates no-xxx options for missing ciphers.
- [Ulf Möller]
-
- *) Support the EBCDIC character set (work in progress).
- File ebcdic.c not yet included because it has a different license.
- [Martin Kraemer <Martin.Kraemer@MchP.Siemens.De>]
-
- *) Support BS2000/OSD-POSIX.
- [Martin Kraemer <Martin.Kraemer@MchP.Siemens.De>]
-
- *) Make callbacks for key generation use void * instead of char *.
- [Ben Laurie]
-
- *) Make S/MIME samples compile (not yet tested).
- [Ben Laurie]
-
- *) Additional typesafe stacks.
- [Ben Laurie]
-
- *) New configuration variants "bsdi-elf-gcc" (BSD/OS 4.x).
- [Bodo Moeller]
-
-
- Changes between 0.9.3 and 0.9.3a [29 May 1999]
-
- *) New configuration variant "sco5-gcc".
-
- *) Updated some demos.
- [Sean O Riordain, Wade Scholine]
-
- *) Add missing BIO_free at exit of pkcs12 application.
- [Wu Zhigang]
-
- *) Fix memory leak in conf.c.
- [Steve Henson]
-
- *) Updates for Win32 to assembler version of MD5.
- [Steve Henson]
-
- *) Set #! path to perl in apps/der_chop to where we found it
- instead of using a fixed path.
- [Bodo Moeller]
-
- *) SHA library changes for irix64-mips4-cc.
- [Andy Polyakov]
-
- *) Improvements for VMS support.
- [Richard Levitte]
-
-
- Changes between 0.9.2b and 0.9.3 [24 May 1999]
-
- *) Bignum library bug fix. IRIX 6 passes "make test" now!
- This also avoids the problems with SC4.2 and unpatched SC5.
- [Andy Polyakov <appro@fy.chalmers.se>]
-
- *) New functions sk_num, sk_value and sk_set to replace the previous macros.
- These are required because of the typesafe stack would otherwise break
- existing code. If old code used a structure member which used to be STACK
- and is now STACK_OF (for example cert in a PKCS7_SIGNED structure) with
- sk_num or sk_value it would produce an error because the num, data members
- are not present in STACK_OF. Now it just produces a warning. sk_set
- replaces the old method of assigning a value to sk_value
- (e.g. sk_value(x, i) = y) which the library used in a few cases. Any code
- that does this will no longer work (and should use sk_set instead) but
- this could be regarded as a "questionable" behaviour anyway.
- [Steve Henson]
-
- *) Fix most of the other PKCS#7 bugs. The "experimental" code can now
- correctly handle encrypted S/MIME data.
- [Steve Henson]
-
- *) Change type of various DES function arguments from des_cblock
- (which means, in function argument declarations, pointer to char)
- to des_cblock * (meaning pointer to array with 8 char elements),
- which allows the compiler to do more typechecking; it was like
- that back in SSLeay, but with lots of ugly casts.
-
- Introduce new type const_des_cblock.
- [Bodo Moeller]
-
- *) Reorganise the PKCS#7 library and get rid of some of the more obvious
- problems: find RecipientInfo structure that matches recipient certificate
- and initialise the ASN1 structures properly based on passed cipher.
- [Steve Henson]
-
- *) Belatedly make the BN tests actually check the results.
- [Ben Laurie]
-
- *) Fix the encoding and decoding of negative ASN1 INTEGERS and conversion
- to and from BNs: it was completely broken. New compilation option
- NEG_PUBKEY_BUG to allow for some broken certificates that encode public
- key elements as negative integers.
- [Steve Henson]
-
- *) Reorganize and speed up MD5.
- [Andy Polyakov <appro@fy.chalmers.se>]
-
- *) VMS support.
- [Richard Levitte <richard@levitte.org>]
-
- *) New option -out to asn1parse to allow the parsed structure to be
- output to a file. This is most useful when combined with the -strparse
- option to examine the output of things like OCTET STRINGS.
- [Steve Henson]
-
- *) Make SSL library a little more fool-proof by not requiring any longer
- that SSL_set_{accept,connect}_state be called before
- SSL_{accept,connect} may be used (SSL_set_..._state is omitted
- in many applications because usually everything *appeared* to work as
- intended anyway -- now it really works as intended).
- [Bodo Moeller]
-
- *) Move openssl.cnf out of lib/.
- [Ulf Möller]
-
- *) Fix various things to let OpenSSL even pass ``egcc -pipe -O2 -Wall
- -Wshadow -Wpointer-arith -Wcast-align -Wmissing-prototypes
- -Wmissing-declarations -Wnested-externs -Winline'' with EGCS 1.1.2+
- [Ralf S. Engelschall]
-
- *) Various fixes to the EVP and PKCS#7 code. It may now be able to
- handle PKCS#7 enveloped data properly.
- [Sebastian Akerman <sak@parallelconsulting.com>, modified by Steve]
-
- *) Create a duplicate of the SSL_CTX's CERT in SSL_new instead of
- copying pointers. The cert_st handling is changed by this in
- various ways (and thus what used to be known as ctx->default_cert
- is now called ctx->cert, since we don't resort to s->ctx->[default_]cert
- any longer when s->cert does not give us what we need).
- ssl_cert_instantiate becomes obsolete by this change.
- As soon as we've got the new code right (possibly it already is?),
- we have solved a couple of bugs of the earlier code where s->cert
- was used as if it could not have been shared with other SSL structures.
-
- Note that using the SSL API in certain dirty ways now will result
- in different behaviour than observed with earlier library versions:
- Changing settings for an SSL_CTX *ctx after having done s = SSL_new(ctx)
- does not influence s as it used to.
-
- In order to clean up things more thoroughly, inside SSL_SESSION
- we don't use CERT any longer, but a new structure SESS_CERT
- that holds per-session data (if available); currently, this is
- the peer's certificate chain and, for clients, the server's certificate
- and temporary key. CERT holds only those values that can have
- meaningful defaults in an SSL_CTX.
- [Bodo Moeller]
-
- *) New function X509V3_EXT_i2d() to create an X509_EXTENSION structure
- from the internal representation. Various PKCS#7 fixes: remove some
- evil casts and set the enc_dig_alg field properly based on the signing
- key type.
- [Steve Henson]
-
- *) Allow PKCS#12 password to be set from the command line or the
- environment. Let 'ca' get its config file name from the environment
- variables "OPENSSL_CONF" or "SSLEAY_CONF" (for consistency with 'req'
- and 'x509').
- [Steve Henson]
-
- *) Allow certificate policies extension to use an IA5STRING for the
- organization field. This is contrary to the PKIX definition but
- VeriSign uses it and IE5 only recognises this form. Document 'x509'
- extension option.
- [Steve Henson]
-
- *) Add PEDANTIC compiler flag to allow compilation with gcc -pedantic,
- without disallowing inline assembler and the like for non-pedantic builds.
- [Ben Laurie]
-
- *) Support Borland C++ builder.
- [Janez Jere <jj@void.si>, modified by Ulf Möller]
-
- *) Support Mingw32.
- [Ulf Möller]
-
- *) SHA-1 cleanups and performance enhancements.
- [Andy Polyakov <appro@fy.chalmers.se>]
-
- *) Sparc v8plus assembler for the bignum library.
- [Andy Polyakov <appro@fy.chalmers.se>]
-
- *) Accept any -xxx and +xxx compiler options in Configure.
- [Ulf Möller]
-
- *) Update HPUX configuration.
- [Anonymous]
-
- *) Add missing sk_<type>_unshift() function to safestack.h
- [Ralf S. Engelschall]
-
- *) New function SSL_CTX_use_certificate_chain_file that sets the
- "extra_cert"s in addition to the certificate. (This makes sense
- only for "PEM" format files, as chains as a whole are not
- DER-encoded.)
- [Bodo Moeller]
-
- *) Support verify_depth from the SSL API.
- x509_vfy.c had what can be considered an off-by-one-error:
- Its depth (which was not part of the external interface)
- was actually counting the number of certificates in a chain;
- now it really counts the depth.
- [Bodo Moeller]
-
- *) Bugfix in crypto/x509/x509_cmp.c: The SSLerr macro was used
- instead of X509err, which often resulted in confusing error
- messages since the error codes are not globally unique
- (e.g. an alleged error in ssl3_accept when a certificate
- didn't match the private key).
-
- *) New function SSL_CTX_set_session_id_context that allows to set a default
- value (so that you don't need SSL_set_session_id_context for each
- connection using the SSL_CTX).
- [Bodo Moeller]
-
- *) OAEP decoding bug fix.
- [Ulf Möller]
-
- *) Support INSTALL_PREFIX for package builders, as proposed by
- David Harris.
- [Bodo Moeller]
-
- *) New Configure options "threads" and "no-threads". For systems
- where the proper compiler options are known (currently Solaris
- and Linux), "threads" is the default.
- [Bodo Moeller]
-
- *) New script util/mklink.pl as a faster substitute for util/mklink.sh.
- [Bodo Moeller]
-
- *) Install various scripts to $(OPENSSLDIR)/misc, not to
- $(INSTALLTOP)/bin -- they shouldn't clutter directories
- such as /usr/local/bin.
- [Bodo Moeller]
-
- *) "make linux-shared" to build shared libraries.
- [Niels Poppe <niels@netbox.org>]
-
- *) New Configure option no-<cipher> (rsa, idea, rc5, ...).
- [Ulf Möller]
-
- *) Add the PKCS#12 API documentation to openssl.txt. Preliminary support for
- extension adding in x509 utility.
- [Steve Henson]
-
- *) Remove NOPROTO sections and error code comments.
- [Ulf Möller]
-
- *) Partial rewrite of the DEF file generator to now parse the ANSI
- prototypes.
- [Steve Henson]
-
- *) New Configure options --prefix=DIR and --openssldir=DIR.
- [Ulf Möller]
-
- *) Complete rewrite of the error code script(s). It is all now handled
- by one script at the top level which handles error code gathering,
- header rewriting and C source file generation. It should be much better
- than the old method: it now uses a modified version of Ulf's parser to
- read the ANSI prototypes in all header files (thus the old K&R definitions
- aren't needed for error creation any more) and do a better job of
- translating function codes into names. The old 'ASN1 error code embedded
- in a comment' is no longer necessary and it doesn't use .err files which
- have now been deleted. Also the error code call doesn't have to appear all
- on one line (which resulted in some large lines...).
- [Steve Henson]
-
- *) Change #include filenames from <foo.h> to <openssl/foo.h>.
- [Bodo Moeller]
-
- *) Change behaviour of ssl2_read when facing length-0 packets: Don't return
- 0 (which usually indicates a closed connection), but continue reading.
- [Bodo Moeller]
-
- *) Fix some race conditions.
- [Bodo Moeller]
-
- *) Add support for CRL distribution points extension. Add Certificate
- Policies and CRL distribution points documentation.
- [Steve Henson]
-
- *) Move the autogenerated header file parts to crypto/opensslconf.h.
- [Ulf Möller]
-
- *) Fix new 56-bit DES export ciphersuites: they were using 7 bytes instead of
- 8 of keying material. Merlin has also confirmed interop with this fix
- between OpenSSL and Baltimore C/SSL 2.0 and J/SSL 2.0.
- [Merlin Hughes <merlin@baltimore.ie>]
-
- *) Fix lots of warnings.
- [Richard Levitte <levitte@stacken.kth.se>]
-
- *) In add_cert_dir() in crypto/x509/by_dir.c, break out of the loop if
- the directory spec didn't end with a LIST_SEPARATOR_CHAR.
- [Richard Levitte <levitte@stacken.kth.se>]
-
- *) Fix problems with sizeof(long) == 8.
- [Andy Polyakov <appro@fy.chalmers.se>]
-
- *) Change functions to ANSI C.
- [Ulf Möller]
-
- *) Fix typos in error codes.
- [Martin Kraemer <Martin.Kraemer@MchP.Siemens.De>, Ulf Möller]
-
- *) Remove defunct assembler files from Configure.
- [Ulf Möller]
-
- *) SPARC v8 assembler BIGNUM implementation.
- [Andy Polyakov <appro@fy.chalmers.se>]
-
- *) Support for Certificate Policies extension: both print and set.
- Various additions to support the r2i method this uses.
- [Steve Henson]
-
- *) A lot of constification, and fix a bug in X509_NAME_oneline() that could
- return a const string when you are expecting an allocated buffer.
- [Ben Laurie]
-
- *) Add support for ASN1 types UTF8String and VISIBLESTRING, also the CHOICE
- types DirectoryString and DisplayText.
- [Steve Henson]
-
- *) Add code to allow r2i extensions to access the configuration database,
- add an LHASH database driver and add several ctx helper functions.
- [Steve Henson]
-
- *) Fix an evil bug in bn_expand2() which caused various BN functions to
- fail when they extended the size of a BIGNUM.
- [Steve Henson]
-
- *) Various utility functions to handle SXNet extension. Modify mkdef.pl to
- support typesafe stack.
- [Steve Henson]
-
- *) Fix typo in SSL_[gs]et_options().
- [Nils Frostberg <nils@medcom.se>]
-
- *) Delete various functions and files that belonged to the (now obsolete)
- old X509V3 handling code.
- [Steve Henson]
-
- *) New Configure option "rsaref".
- [Ulf Möller]
-
- *) Don't auto-generate pem.h.
- [Bodo Moeller]
-
- *) Introduce type-safe ASN.1 SETs.
- [Ben Laurie]
-
- *) Convert various additional casted stacks to type-safe STACK_OF() variants.
- [Ben Laurie, Ralf S. Engelschall, Steve Henson]
-
- *) Introduce type-safe STACKs. This will almost certainly break lots of code
- that links with OpenSSL (well at least cause lots of warnings), but fear
- not: the conversion is trivial, and it eliminates loads of evil casts. A
- few STACKed things have been converted already. Feel free to convert more.
- In the fullness of time, I'll do away with the STACK type altogether.
- [Ben Laurie]
-
- *) Add `openssl ca -revoke <certfile>' facility which revokes a certificate
- specified in <certfile> by updating the entry in the index.txt file.
- This way one no longer has to edit the index.txt file manually for
- revoking a certificate. The -revoke option does the gory details now.
- [Massimiliano Pala <madwolf@openca.org>, Ralf S. Engelschall]
-
- *) Fix `openssl crl -noout -text' combination where `-noout' killed the
- `-text' option at all and this way the `-noout -text' combination was
- inconsistent in `openssl crl' with the friends in `openssl x509|rsa|dsa'.
- [Ralf S. Engelschall]
-
- *) Make sure a corresponding plain text error message exists for the
- X509_V_ERR_CERT_REVOKED/23 error number which can occur when a
- verify callback function determined that a certificate was revoked.
- [Ralf S. Engelschall]
-
- *) Bugfix: In test/testenc, don't test "openssl <cipher>" for
- ciphers that were excluded, e.g. by -DNO_IDEA. Also, test
- all available ciphers including rc5, which was forgotten until now.
- In order to let the testing shell script know which algorithms
- are available, a new (up to now undocumented) command
- "openssl list-cipher-commands" is used.
- [Bodo Moeller]
-
- *) Bugfix: s_client occasionally would sleep in select() when
- it should have checked SSL_pending() first.
- [Bodo Moeller]
-
- *) New functions DSA_do_sign and DSA_do_verify to provide access to
- the raw DSA values prior to ASN.1 encoding.
- [Ulf Möller]
-
- *) Tweaks to Configure
- [Niels Poppe <niels@netbox.org>]
-
- *) Add support for PKCS#5 v2.0 ASN1 PBES2 structures. No other support,
- yet...
- [Steve Henson]
-
- *) New variables $(RANLIB) and $(PERL) in the Makefiles.
- [Ulf Möller]
-
- *) New config option to avoid instructions that are illegal on the 80386.
- The default code is faster, but requires at least a 486.
- [Ulf Möller]
-
- *) Got rid of old SSL2_CLIENT_VERSION (inconsistently used) and
- SSL2_SERVER_VERSION (not used at all) macros, which are now the
- same as SSL2_VERSION anyway.
- [Bodo Moeller]
-
- *) New "-showcerts" option for s_client.
- [Bodo Moeller]
-
- *) Still more PKCS#12 integration. Add pkcs12 application to openssl
- application. Various cleanups and fixes.
- [Steve Henson]
-
- *) More PKCS#12 integration. Add new pkcs12 directory with Makefile.ssl and
- modify error routines to work internally. Add error codes and PBE init
- to library startup routines.
- [Steve Henson]
-
- *) Further PKCS#12 integration. Added password based encryption, PKCS#8 and
- packing functions to asn1 and evp. Changed function names and error
- codes along the way.
- [Steve Henson]
-
- *) PKCS12 integration: and so it begins... First of several patches to
- slowly integrate PKCS#12 functionality into OpenSSL. Add PKCS#12
- objects to objects.h
- [Steve Henson]
-
- *) Add a new 'indent' option to some X509V3 extension code. Initial ASN1
- and display support for Thawte strong extranet extension.
- [Steve Henson]
-
- *) Add LinuxPPC support.
- [Jeff Dubrule <igor@pobox.org>]
-
- *) Get rid of redundant BN file bn_mulw.c, and rename bn_div64 to
- bn_div_words in alpha.s.
- [Hannes Reinecke <H.Reinecke@hw.ac.uk> and Ben Laurie]
-
- *) Make sure the RSA OAEP test is skipped under -DRSAref because
- OAEP isn't supported when OpenSSL is built with RSAref.
- [Ulf Moeller <ulf@fitug.de>]
-
- *) Move definitions of IS_SET/IS_SEQUENCE inside crypto/asn1/asn1.h
- so they no longer are missing under -DNOPROTO.
- [Soren S. Jorvang <soren@t.dk>]
-
-
- Changes between 0.9.1c and 0.9.2b [22 Mar 1999]
-
- *) Make SSL_get_peer_cert_chain() work in servers. Unfortunately, it still
- doesn't work when the session is reused. Coming soon!
- [Ben Laurie]
-
- *) Fix a security hole, that allows sessions to be reused in the wrong
- context thus bypassing client cert protection! All software that uses
- client certs and session caches in multiple contexts NEEDS PATCHING to
- allow session reuse! A fuller solution is in the works.
- [Ben Laurie, problem pointed out by Holger Reif, Bodo Moeller (and ???)]
-
- *) Some more source tree cleanups (removed obsolete files
- crypto/bf/asm/bf586.pl, test/test.txt and crypto/sha/asm/f.s; changed
- permission on "config" script to be executable) and a fix for the INSTALL
- document.
- [Ulf Moeller <ulf@fitug.de>]
-
- *) Remove some legacy and erroneous uses of malloc, free instead of
- Malloc, Free.
- [Lennart Bang <lob@netstream.se>, with minor changes by Steve]
-
- *) Make rsa_oaep_test return non-zero on error.
- [Ulf Moeller <ulf@fitug.de>]
-
- *) Add support for native Solaris shared libraries. Configure
- solaris-sparc-sc4-pic, make, then run shlib/solaris-sc4.sh. It'd be nice
- if someone would make that last step automatic.
- [Matthias Loepfe <Matthias.Loepfe@AdNovum.CH>]
-
- *) ctx_size was not built with the right compiler during "make links". Fixed.
- [Ben Laurie]
-
- *) Change the meaning of 'ALL' in the cipher list. It now means "everything
- except NULL ciphers". This means the default cipher list will no longer
- enable NULL ciphers. They need to be specifically enabled e.g. with
- the string "DEFAULT:eNULL".
- [Steve Henson]
-
- *) Fix to RSA private encryption routines: if p < q then it would
- occasionally produce an invalid result. This will only happen with
- externally generated keys because OpenSSL (and SSLeay) ensure p > q.
- [Steve Henson]
-
- *) Be less restrictive and allow also `perl util/perlpath.pl
- /path/to/bin/perl' in addition to `perl util/perlpath.pl /path/to/bin',
- because this way one can also use an interpreter named `perl5' (which is
- usually the name of Perl 5.xxx on platforms where an Perl 4.x is still
- installed as `perl').
- [Matthias Loepfe <Matthias.Loepfe@adnovum.ch>]
-
- *) Let util/clean-depend.pl work also with older Perl 5.00x versions.
- [Matthias Loepfe <Matthias.Loepfe@adnovum.ch>]
-
- *) Fix Makefile.org so CC,CFLAG etc are passed to 'make links' add
- advapi32.lib to Win32 build and change the pem test comparison
- to fc.exe (thanks to Ulrich Kroener <kroneru@yahoo.com> for the
- suggestion). Fix misplaced ASNI prototypes and declarations in evp.h
- and crypto/des/ede_cbcm_enc.c.
- [Steve Henson]
-
- *) DES quad checksum was broken on big-endian architectures. Fixed.
- [Ben Laurie]
-
- *) Comment out two functions in bio.h that aren't implemented. Fix up the
- Win32 test batch file so it (might) work again. The Win32 test batch file
- is horrible: I feel ill....
- [Steve Henson]
-
- *) Move various #ifdefs around so NO_SYSLOG, NO_DIRENT etc are now selected
- in e_os.h. Audit of header files to check ANSI and non ANSI
- sections: 10 functions were absent from non ANSI section and not exported
- from Windows DLLs. Fixed up libeay.num for new functions.
- [Steve Henson]
-
- *) Make `openssl version' output lines consistent.
- [Ralf S. Engelschall]
-
- *) Fix Win32 symbol export lists for BIO functions: Added
- BIO_get_ex_new_index, BIO_get_ex_num, BIO_get_ex_data and BIO_set_ex_data
- to ms/libeay{16,32}.def.
- [Ralf S. Engelschall]
-
- *) Second round of fixing the OpenSSL perl/ stuff. It now at least compiled
- fine under Unix and passes some trivial tests I've now added. But the
- whole stuff is horribly incomplete, so a README.1ST with a disclaimer was
- added to make sure no one expects that this stuff really works in the
- OpenSSL 0.9.2 release. Additionally I've started to clean the XS sources
- up and fixed a few little bugs and inconsistencies in OpenSSL.{pm,xs} and
- openssl_bio.xs.
- [Ralf S. Engelschall]
-
- *) Fix the generation of two part addresses in perl.
- [Kenji Miyake <kenji@miyake.org>, integrated by Ben Laurie]
-
- *) Add config entry for Linux on MIPS.
- [John Tobey <jtobey@channel1.com>]
-
- *) Make links whenever Configure is run, unless we are on Windoze.
- [Ben Laurie]
-
- *) Permit extensions to be added to CRLs using crl_section in openssl.cnf.
- Currently only issuerAltName and AuthorityKeyIdentifier make any sense
- in CRLs.
- [Steve Henson]
-
- *) Add a useful kludge to allow package maintainers to specify compiler and
- other platforms details on the command line without having to patch the
- Configure script every time: One now can use ``perl Configure
- <id>:<details>'', i.e. platform ids are allowed to have details appended
- to them (separated by colons). This is treated as there would be a static
- pre-configured entry in Configure's %table under key <id> with value
- <details> and ``perl Configure <id>'' is called. So, when you want to
- perform a quick test-compile under FreeBSD 3.1 with pgcc and without
- assembler stuff you can use ``perl Configure "FreeBSD-elf:pgcc:-O6:::"''
- now, which overrides the FreeBSD-elf entry on-the-fly.
- [Ralf S. Engelschall]
-
- *) Disable new TLS1 ciphersuites by default: they aren't official yet.
- [Ben Laurie]
-
- *) Allow DSO flags like -fpic, -fPIC, -KPIC etc. to be specified
- on the `perl Configure ...' command line. This way one can compile
- OpenSSL libraries with Position Independent Code (PIC) which is needed
- for linking it into DSOs.
- [Ralf S. Engelschall]
-
- *) Remarkably, export ciphers were totally broken and no-one had noticed!
- Fixed.
- [Ben Laurie]
-
- *) Cleaned up the LICENSE document: The official contact for any license
- questions now is the OpenSSL core team under openssl-core@openssl.org.
- And add a paragraph about the dual-license situation to make sure people
- recognize that _BOTH_ the OpenSSL license _AND_ the SSLeay license apply
- to the OpenSSL toolkit.
- [Ralf S. Engelschall]
-
- *) General source tree makefile cleanups: Made `making xxx in yyy...'
- display consistent in the source tree and replaced `/bin/rm' by `rm'.
- Additionally cleaned up the `make links' target: Remove unnecessary
- semicolons, subsequent redundant removes, inline point.sh into mklink.sh
- to speed processing and no longer clutter the display with confusing
- stuff. Instead only the actually done links are displayed.
- [Ralf S. Engelschall]
-
- *) Permit null encryption ciphersuites, used for authentication only. It used
- to be necessary to set the preprocessor define SSL_ALLOW_ENULL to do this.
- It is now necessary to set SSL_FORBID_ENULL to prevent the use of null
- encryption.
- [Ben Laurie]
-
- *) Add a bunch of fixes to the PKCS#7 stuff. It used to sometimes reorder
- signed attributes when verifying signatures (this would break them),
- the detached data encoding was wrong and public keys obtained using
- X509_get_pubkey() weren't freed.
- [Steve Henson]
-
- *) Add text documentation for the BUFFER functions. Also added a work around
- to a Win95 console bug. This was triggered by the password read stuff: the
- last character typed gets carried over to the next fread(). If you were
- generating a new cert request using 'req' for example then the last
- character of the passphrase would be CR which would then enter the first
- field as blank.
- [Steve Henson]
-
- *) Added the new `Includes OpenSSL Cryptography Software' button as
- doc/openssl_button.{gif,html} which is similar in style to the old SSLeay
- button and can be used by applications based on OpenSSL to show the
- relationship to the OpenSSL project.
- [Ralf S. Engelschall]
-
- *) Remove confusing variables in function signatures in files
- ssl/ssl_lib.c and ssl/ssl.h.
- [Lennart Bong <lob@kulthea.stacken.kth.se>]
-
- *) Don't install bss_file.c under PREFIX/include/
- [Lennart Bong <lob@kulthea.stacken.kth.se>]
-
- *) Get the Win32 compile working again. Modify mkdef.pl so it can handle
- functions that return function pointers and has support for NT specific
- stuff. Fix mk1mf.pl and VC-32.pl to support NT differences also. Various
- #ifdef WIN32 and WINNTs sprinkled about the place and some changes from
- unsigned to signed types: this was killing the Win32 compile.
- [Steve Henson]
-
- *) Add new certificate file to stack functions,
- SSL_add_dir_cert_subjects_to_stack() and
- SSL_add_file_cert_subjects_to_stack(). These largely supplant
- SSL_load_client_CA_file(), and can be used to add multiple certs easily
- to a stack (usually this is then handed to SSL_CTX_set_client_CA_list()).
- This means that Apache-SSL and similar packages don't have to mess around
- to add as many CAs as they want to the preferred list.
- [Ben Laurie]
-
- *) Experiment with doxygen documentation. Currently only partially applied to
- ssl/ssl_lib.c.
- See http://www.stack.nl/~dimitri/doxygen/index.html, and run doxygen with
- openssl.doxy as the configuration file.
- [Ben Laurie]
-
- *) Get rid of remaining C++-style comments which strict C compilers hate.
- [Ralf S. Engelschall, pointed out by Carlos Amengual]
-
- *) Changed BN_RECURSION in bn_mont.c to BN_RECURSION_MONT so it is not
- compiled in by default: it has problems with large keys.
- [Steve Henson]
-
- *) Add a bunch of SSL_xxx() functions for configuring the temporary RSA and
- DH private keys and/or callback functions which directly correspond to
- their SSL_CTX_xxx() counterparts but work on a per-connection basis. This
- is needed for applications which have to configure certificates on a
- per-connection basis (e.g. Apache+mod_ssl) instead of a per-context basis
- (e.g. s_server).
- For the RSA certificate situation is makes no difference, but
- for the DSA certificate situation this fixes the "no shared cipher"
- problem where the OpenSSL cipher selection procedure failed because the
- temporary keys were not overtaken from the context and the API provided
- no way to reconfigure them.
- The new functions now let applications reconfigure the stuff and they
- are in detail: SSL_need_tmp_RSA, SSL_set_tmp_rsa, SSL_set_tmp_dh,
- SSL_set_tmp_rsa_callback and SSL_set_tmp_dh_callback. Additionally a new
- non-public-API function ssl_cert_instantiate() is used as a helper
- function and also to reduce code redundancy inside ssl_rsa.c.
- [Ralf S. Engelschall]
-
- *) Move s_server -dcert and -dkey options out of the undocumented feature
- area because they are useful for the DSA situation and should be
- recognized by the users.
- [Ralf S. Engelschall]
-
- *) Fix the cipher decision scheme for export ciphers: the export bits are
- *not* within SSL_MKEY_MASK or SSL_AUTH_MASK, they are within
- SSL_EXP_MASK. So, the original variable has to be used instead of the
- already masked variable.
- [Richard Levitte <levitte@stacken.kth.se>]
-
- *) Fix 'port' variable from `int' to `unsigned int' in crypto/bio/b_sock.c
- [Richard Levitte <levitte@stacken.kth.se>]
-
- *) Change type of another md_len variable in pk7_doit.c:PKCS7_dataFinal()
- from `int' to `unsigned int' because it's a length and initialized by
- EVP_DigestFinal() which expects an `unsigned int *'.
- [Richard Levitte <levitte@stacken.kth.se>]
-
- *) Don't hard-code path to Perl interpreter on shebang line of Configure
- script. Instead use the usual Shell->Perl transition trick.
- [Ralf S. Engelschall]
-
- *) Make `openssl x509 -noout -modulus' functional also for DSA certificates
- (in addition to RSA certificates) to match the behaviour of `openssl dsa
- -noout -modulus' as it's already the case for `openssl rsa -noout
- -modulus'. For RSA the -modulus is the real "modulus" while for DSA
- currently the public key is printed (a decision which was already done by
- `openssl dsa -modulus' in the past) which serves a similar purpose.
- Additionally the NO_RSA no longer completely removes the whole -modulus
- option; it now only avoids using the RSA stuff. Same applies to NO_DSA
- now, too.
- [Ralf S. Engelschall]
-
- *) Add Arne Ansper's reliable BIO - this is an encrypted, block-digested
- BIO. See the source (crypto/evp/bio_ok.c) for more info.
- [Arne Ansper <arne@ats.cyber.ee>]
-
- *) Dump the old yucky req code that tried (and failed) to allow raw OIDs
- to be added. Now both 'req' and 'ca' can use new objects defined in the
- config file.
- [Steve Henson]
-
- *) Add cool BIO that does syslog (or event log on NT).
- [Arne Ansper <arne@ats.cyber.ee>, integrated by Ben Laurie]
-
- *) Add support for new TLS ciphersuites, TLS_RSA_EXPORT56_WITH_RC4_56_MD5,
- TLS_RSA_EXPORT56_WITH_RC2_CBC_56_MD5 and
- TLS_RSA_EXPORT56_WITH_DES_CBC_SHA, as specified in "56-bit Export Cipher
- Suites For TLS", draft-ietf-tls-56-bit-ciphersuites-00.txt.
- [Ben Laurie]
-
- *) Add preliminary config info for new extension code.
- [Steve Henson]
-
- *) Make RSA_NO_PADDING really use no padding.
- [Ulf Moeller <ulf@fitug.de>]
-
- *) Generate errors when private/public key check is done.
- [Ben Laurie]
-
- *) Overhaul for 'crl' utility. New function X509_CRL_print. Partial support
- for some CRL extensions and new objects added.
- [Steve Henson]
-
- *) Really fix the ASN1 IMPLICIT bug this time... Partial support for private
- key usage extension and fuller support for authority key id.
- [Steve Henson]
-
- *) Add OAEP encryption for the OpenSSL crypto library. OAEP is the improved
- padding method for RSA, which is recommended for new applications in PKCS
- #1 v2.0 (RFC 2437, October 1998).
- OAEP (Optimal Asymmetric Encryption Padding) has better theoretical
- foundations than the ad-hoc padding used in PKCS #1 v1.5. It is secure
- against Bleichbacher's attack on RSA.
- [Ulf Moeller <ulf@fitug.de>, reformatted, corrected and integrated by
- Ben Laurie]
-
- *) Updates to the new SSL compression code
- [Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)]
-
- *) Fix so that the version number in the master secret, when passed
- via RSA, checks that if TLS was proposed, but we roll back to SSLv3
- (because the server will not accept higher), that the version number
- is 0x03,0x01, not 0x03,0x00
- [Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)]
-
- *) Run extensive memory leak checks on SSL apps. Fixed *lots* of memory
- leaks in ssl/ relating to new X509_get_pubkey() behaviour. Also fixes
- in apps/ and an unrelated leak in crypto/dsa/dsa_vrf.c
- [Steve Henson]
-
- *) Support for RAW extensions where an arbitrary extension can be
- created by including its DER encoding. See apps/openssl.cnf for
- an example.
- [Steve Henson]
-
- *) Make sure latest Perl versions don't interpret some generated C array
- code as Perl array code in the crypto/err/err_genc.pl script.
- [Lars Weber <3weber@informatik.uni-hamburg.de>]
-
- *) Modify ms/do_ms.bat to not generate assembly language makefiles since
- not many people have the assembler. Various Win32 compilation fixes and
- update to the INSTALL.W32 file with (hopefully) more accurate Win32
- build instructions.
- [Steve Henson]
-
- *) Modify configure script 'Configure' to automatically create crypto/date.h
- file under Win32 and also build pem.h from pem.org. New script
- util/mkfiles.pl to create the MINFO file on environments that can't do a
- 'make files': perl util/mkfiles.pl >MINFO should work.
- [Steve Henson]
-
- *) Major rework of DES function declarations, in the pursuit of correctness
- and purity. As a result, many evil casts evaporated, and some weirdness,
- too. You may find this causes warnings in your code. Zapping your evil
- casts will probably fix them. Mostly.
- [Ben Laurie]
-
- *) Fix for a typo in asn1.h. Bug fix to object creation script
- obj_dat.pl. It considered a zero in an object definition to mean
- "end of object": none of the objects in objects.h have any zeros
- so it wasn't spotted.
- [Steve Henson, reported by Erwann ABALEA <eabalea@certplus.com>]
-
- *) Add support for Triple DES Cipher Block Chaining with Output Feedback
- Masking (CBCM). In the absence of test vectors, the best I have been able
- to do is check that the decrypt undoes the encrypt, so far. Send me test
- vectors if you have them.
- [Ben Laurie]
-
- *) Correct calculation of key length for export ciphers (too much space was
- allocated for null ciphers). This has not been tested!
- [Ben Laurie]
-
- *) Modifications to the mkdef.pl for Win32 DEF file creation. The usage
- message is now correct (it understands "crypto" and "ssl" on its
- command line). There is also now an "update" option. This will update
- the util/ssleay.num and util/libeay.num files with any new functions.
- If you do a:
- perl util/mkdef.pl crypto ssl update
- it will update them.
- [Steve Henson]
-
- *) Overhauled the Perl interface (perl/*):
- - ported BN stuff to OpenSSL's different BN library
- - made the perl/ source tree CVS-aware
- - renamed the package from SSLeay to OpenSSL (the files still contain
- their history because I've copied them in the repository)
- - removed obsolete files (the test scripts will be replaced
- by better Test::Harness variants in the future)
- [Ralf S. Engelschall]
-
- *) First cut for a very conservative source tree cleanup:
- 1. merge various obsolete readme texts into doc/ssleay.txt
- where we collect the old documents and readme texts.
- 2. remove the first part of files where I'm already sure that we no
- longer need them because of three reasons: either they are just temporary
- files which were left by Eric or they are preserved original files where
- I've verified that the diff is also available in the CVS via "cvs diff
- -rSSLeay_0_8_1b" or they were renamed (as it was definitely the case for
- the crypto/md/ stuff).
- [Ralf S. Engelschall]
-
- *) More extension code. Incomplete support for subject and issuer alt
- name, issuer and authority key id. Change the i2v function parameters
- and add an extra 'crl' parameter in the X509V3_CTX structure: guess
- what that's for :-) Fix to ASN1 macro which messed up
- IMPLICIT tag and add f_enum.c which adds a2i, i2a for ENUMERATED.
- [Steve Henson]
-
- *) Preliminary support for ENUMERATED type. This is largely copied from the
- INTEGER code.
- [Steve Henson]
-
- *) Add new function, EVP_MD_CTX_copy() to replace frequent use of memcpy.
- [Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)]
-
- *) Make sure `make rehash' target really finds the `openssl' program.
- [Ralf S. Engelschall, Matthias Loepfe <Matthias.Loepfe@adnovum.ch>]
-
- *) Squeeze another 7% of speed out of MD5 assembler, at least on a P2. I'd
- like to hear about it if this slows down other processors.
- [Ben Laurie]
-
- *) Add CygWin32 platform information to Configure script.
- [Alan Batie <batie@aahz.jf.intel.com>]
-
- *) Fixed ms/32all.bat script: `no_asm' -> `no-asm'
- [Rainer W. Gerling <gerling@mpg-gv.mpg.de>]
-
- *) New program nseq to manipulate netscape certificate sequences
- [Steve Henson]
-
- *) Modify crl2pkcs7 so it supports multiple -certfile arguments. Fix a
- few typos.
- [Steve Henson]
-
- *) Fixes to BN code. Previously the default was to define BN_RECURSION
- but the BN code had some problems that would cause failures when
- doing certificate verification and some other functions.
- [Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)]
-
- *) Add ASN1 and PEM code to support netscape certificate sequences.
- [Steve Henson]
-
- *) Add ASN1 and PEM code to support netscape certificate sequences.
- [Steve Henson]
-
- *) Add several PKIX and private extended key usage OIDs.
- [Steve Henson]
-
- *) Modify the 'ca' program to handle the new extension code. Modify
- openssl.cnf for new extension format, add comments.
- [Steve Henson]
-
- *) More X509 V3 changes. Fix typo in v3_bitstr.c. Add support to 'req'
- and add a sample to openssl.cnf so req -x509 now adds appropriate
- CA extensions.
- [Steve Henson]
-
- *) Continued X509 V3 changes. Add to other makefiles, integrate with the
- error code, add initial support to X509_print() and x509 application.
- [Steve Henson]
-
- *) Takes a deep breath and start adding X509 V3 extension support code. Add
- files in crypto/x509v3. Move original stuff to crypto/x509v3/old. All this
- stuff is currently isolated and isn't even compiled yet.
- [Steve Henson]
-
- *) Continuing patches for GeneralizedTime. Fix up certificate and CRL
- ASN1 to use ASN1_TIME and modify print routines to use ASN1_TIME_print.
- Removed the versions check from X509 routines when loading extensions:
- this allows certain broken certificates that don't set the version
- properly to be processed.
- [Steve Henson]
-
- *) Deal with irritating shit to do with dependencies, in YAAHW (Yet Another
- Ad Hoc Way) - Makefile.ssls now all contain local dependencies, which
- can still be regenerated with "make depend".
- [Ben Laurie]
-
- *) Spelling mistake in C version of CAST-128.
- [Ben Laurie, reported by Jeremy Hylton <jeremy@cnri.reston.va.us>]
-
- *) Changes to the error generation code. The perl script err-code.pl
- now reads in the old error codes and retains the old numbers, only
- adding new ones if necessary. It also only changes the .err files if new
- codes are added. The makefiles have been modified to only insert errors
- when needed (to avoid needlessly modifying header files). This is done
- by only inserting errors if the .err file is newer than the auto generated
- C file. To rebuild all the error codes from scratch (the old behaviour)
- either modify crypto/Makefile.ssl to pass the -regen flag to err_code.pl
- or delete all the .err files.
- [Steve Henson]
-
- *) CAST-128 was incorrectly implemented for short keys. The C version has
- been fixed, but is untested. The assembler versions are also fixed, but
- new assembler HAS NOT BEEN GENERATED FOR WIN32 - the Makefile needs fixing
- to regenerate it if needed.
- [Ben Laurie, reported (with fix for C version) by Jun-ichiro itojun
- Hagino <itojun@kame.net>]
-
- *) File was opened incorrectly in randfile.c.
- [Ulf Möller <ulf@fitug.de>]
-
- *) Beginning of support for GeneralizedTime. d2i, i2d, check and print
- functions. Also ASN1_TIME suite which is a CHOICE of UTCTime or
- GeneralizedTime. ASN1_TIME is the proper type used in certificates et
- al: it's just almost always a UTCTime. Note this patch adds new error
- codes so do a "make errors" if there are problems.
- [Steve Henson]
-
- *) Correct Linux 1 recognition in config.
- [Ulf Möller <ulf@fitug.de>]
-
- *) Remove pointless MD5 hash when using DSA keys in ca.
- [Anonymous <nobody@replay.com>]
-
- *) Generate an error if given an empty string as a cert directory. Also
- generate an error if handed NULL (previously returned 0 to indicate an
- error, but didn't set one).
- [Ben Laurie, reported by Anonymous <nobody@replay.com>]
-
- *) Add prototypes to SSL methods. Make SSL_write's buffer const, at last.
- [Ben Laurie]
-
- *) Fix the dummy function BN_ref_mod_exp() in rsaref.c to have the correct
- parameters. This was causing a warning which killed off the Win32 compile.
- [Steve Henson]
-
- *) Remove C++ style comments from crypto/bn/bn_local.h.
- [Neil Costigan <neil.costigan@celocom.com>]
-
- *) The function OBJ_txt2nid was broken. It was supposed to return a nid
- based on a text string, looking up short and long names and finally
- "dot" format. The "dot" format stuff didn't work. Added new function
- OBJ_txt2obj to do the same but return an ASN1_OBJECT and rewrote
- OBJ_txt2nid to use it. OBJ_txt2obj can also return objects even if the
- OID is not part of the table.
- [Steve Henson]
-
- *) Add prototypes to X509 lookup/verify methods, fixing a bug in
- X509_LOOKUP_by_alias().
- [Ben Laurie]
-
- *) Sort openssl functions by name.
- [Ben Laurie]
-
- *) Get the gendsa program working (hopefully) and add it to app list. Remove
- encryption from sample DSA keys (in case anyone is interested the password
- was "1234").
- [Steve Henson]
-
- *) Make _all_ *_free functions accept a NULL pointer.
- [Frans Heymans <fheymans@isaserver.be>]
-
- *) If a DH key is generated in s3_srvr.c, don't blow it by trying to use
- NULL pointers.
- [Anonymous <nobody@replay.com>]
-
- *) s_server should send the CAfile as acceptable CAs, not its own cert.
- [Bodo Moeller <3moeller@informatik.uni-hamburg.de>]
-
- *) Don't blow it for numeric -newkey arguments to apps/req.
- [Bodo Moeller <3moeller@informatik.uni-hamburg.de>]
-
- *) Temp key "for export" tests were wrong in s3_srvr.c.
- [Anonymous <nobody@replay.com>]
-
- *) Add prototype for temp key callback functions
- SSL_CTX_set_tmp_{rsa,dh}_callback().
- [Ben Laurie]
-
- *) Make DH_free() tolerate being passed a NULL pointer (like RSA_free() and
- DSA_free()). Make X509_PUBKEY_set() check for errors in d2i_PublicKey().
- [Steve Henson]
-
- *) X509_name_add_entry() freed the wrong thing after an error.
- [Arne Ansper <arne@ats.cyber.ee>]
-
- *) rsa_eay.c would attempt to free a NULL context.
- [Arne Ansper <arne@ats.cyber.ee>]
-
- *) BIO_s_socket() had a broken should_retry() on Windoze.
- [Arne Ansper <arne@ats.cyber.ee>]
-
- *) BIO_f_buffer() didn't pass on BIO_CTRL_FLUSH.
- [Arne Ansper <arne@ats.cyber.ee>]
-
- *) Make sure the already existing X509_STORE->depth variable is initialized
- in X509_STORE_new(), but document the fact that this variable is still
- unused in the certificate verification process.
- [Ralf S. Engelschall]
-
- *) Fix the various library and apps files to free up pkeys obtained from
- X509_PUBKEY_get() et al. Also allow x509.c to handle netscape extensions.
- [Steve Henson]
-
- *) Fix reference counting in X509_PUBKEY_get(). This makes
- demos/maurice/example2.c work, amongst others, probably.
- [Steve Henson and Ben Laurie]
-
- *) First cut of a cleanup for apps/. First the `ssleay' program is now named
- `openssl' and second, the shortcut symlinks for the `openssl <command>'
- are no longer created. This way we have a single and consistent command
- line interface `openssl <command>', similar to `cvs <command>'.
- [Ralf S. Engelschall, Paul Sutton and Ben Laurie]
-
- *) ca.c: move test for DSA keys inside #ifndef NO_DSA. Make pubkey
- BIT STRING wrapper always have zero unused bits.
- [Steve Henson]
-
- *) Add CA.pl, perl version of CA.sh, add extended key usage OID.
- [Steve Henson]
-
- *) Make the top-level INSTALL documentation easier to understand.
- [Paul Sutton]
-
- *) Makefiles updated to exit if an error occurs in a sub-directory
- make (including if user presses ^C) [Paul Sutton]
-
- *) Make Montgomery context stuff explicit in RSA data structure.
- [Ben Laurie]
-
- *) Fix build order of pem and err to allow for generated pem.h.
- [Ben Laurie]
-
- *) Fix renumbering bug in X509_NAME_delete_entry().
- [Ben Laurie]
-
- *) Enhanced the err-ins.pl script so it makes the error library number
- global and can add a library name. This is needed for external ASN1 and
- other error libraries.
- [Steve Henson]
-
- *) Fixed sk_insert which never worked properly.
- [Steve Henson]
-
- *) Fix ASN1 macros so they can handle indefinite length constructed
- EXPLICIT tags. Some non standard certificates use these: they can now
- be read in.
- [Steve Henson]
-
- *) Merged the various old/obsolete SSLeay documentation files (doc/xxx.doc)
- into a single doc/ssleay.txt bundle. This way the information is still
- preserved but no longer messes up this directory. Now it's new room for
- the new set of documentation files.
- [Ralf S. Engelschall]
-
- *) SETs were incorrectly DER encoded. This was a major pain, because they
- shared code with SEQUENCEs, which aren't coded the same. This means that
- almost everything to do with SETs or SEQUENCEs has either changed name or
- number of arguments.
- [Ben Laurie, based on a partial fix by GP Jayan <gp@nsj.co.jp>]
-
- *) Fix test data to work with the above.
- [Ben Laurie]
-
- *) Fix the RSA header declarations that hid a bug I fixed in 0.9.0b but
- was already fixed by Eric for 0.9.1 it seems.
- [Ben Laurie - pointed out by Ulf Möller <ulf@fitug.de>]
-
- *) Autodetect FreeBSD3.
- [Ben Laurie]
-
- *) Fix various bugs in Configure. This affects the following platforms:
- nextstep
- ncr-scde
- unixware-2.0
- unixware-2.0-pentium
- sco5-cc.
- [Ben Laurie]
-
- *) Eliminate generated files from CVS. Reorder tests to regenerate files
- before they are needed.
- [Ben Laurie]
-
- *) Generate Makefile.ssl from Makefile.org (to keep CVS happy).
- [Ben Laurie]
-
-
- Changes between 0.9.1b and 0.9.1c [23-Dec-1998]
-
- *) Added OPENSSL_VERSION_NUMBER to crypto/crypto.h and
- changed SSLeay to OpenSSL in version strings.
- [Ralf S. Engelschall]
-
- *) Some fixups to the top-level documents.
- [Paul Sutton]
-
- *) Fixed the nasty bug where rsaref.h was not found under compile-time
- because the symlink to include/ was missing.
- [Ralf S. Engelschall]
-
- *) Incorporated the popular no-RSA/DSA-only patches
- which allow to compile a RSA-free SSLeay.
- [Andrew Cooke / Interrader Ldt., Ralf S. Engelschall]
-
- *) Fixed nasty rehash problem under `make -f Makefile.ssl links'
- when "ssleay" is still not found.
- [Ralf S. Engelschall]
-
- *) Added more platforms to Configure: Cray T3E, HPUX 11,
- [Ralf S. Engelschall, Beckmann <beckman@acl.lanl.gov>]
-
- *) Updated the README file.
- [Ralf S. Engelschall]
-
- *) Added various .cvsignore files in the CVS repository subdirs
- to make a "cvs update" really silent.
- [Ralf S. Engelschall]
-
- *) Recompiled the error-definition header files and added
- missing symbols to the Win32 linker tables.
- [Ralf S. Engelschall]
-
- *) Cleaned up the top-level documents;
- o new files: CHANGES and LICENSE
- o merged VERSION, HISTORY* and README* files a CHANGES.SSLeay
- o merged COPYRIGHT into LICENSE
- o removed obsolete TODO file
- o renamed MICROSOFT to INSTALL.W32
- [Ralf S. Engelschall]
-
- *) Removed dummy files from the 0.9.1b source tree:
- crypto/asn1/x crypto/bio/cd crypto/bio/fg crypto/bio/grep crypto/bio/vi
- crypto/bn/asm/......add.c crypto/bn/asm/a.out crypto/dsa/f crypto/md5/f
- crypto/pem/gmon.out crypto/perlasm/f crypto/pkcs7/build crypto/rsa/f
- crypto/sha/asm/f crypto/threads/f ms/zzz ssl/f ssl/f.mak test/f
- util/f.mak util/pl/f util/pl/f.mak crypto/bf/bf_locl.old apps/f
- [Ralf S. Engelschall]
-
- *) Added various platform portability fixes.
- [Mark J. Cox]
-
- *) The Genesis of the OpenSSL rpject:
- We start with the latest (unreleased) SSLeay version 0.9.1b which Eric A.
- Young and Tim J. Hudson created while they were working for C2Net until
- summer 1998.
- [The OpenSSL Project]
-
-
- Changes between 0.9.0b and 0.9.1b [not released]
-
- *) Updated a few CA certificates under certs/
- [Eric A. Young]
-
- *) Changed some BIGNUM api stuff.
- [Eric A. Young]
-
- *) Various platform ports: OpenBSD, Ultrix, IRIX 64bit, NetBSD,
- DGUX x86, Linux Alpha, etc.
- [Eric A. Young]
-
- *) New COMP library [crypto/comp/] for SSL Record Layer Compression:
- RLE (dummy implemented) and ZLIB (really implemented when ZLIB is
- available).
- [Eric A. Young]
-
- *) Add -strparse option to asn1pars program which parses nested
- binary structures
- [Dr Stephen Henson <shenson@bigfoot.com>]
-
- *) Added "oid_file" to ssleay.cnf for "ca" and "req" programs.
- [Eric A. Young]
-
- *) DSA fix for "ca" program.
- [Eric A. Young]
-
- *) Added "-genkey" option to "dsaparam" program.
- [Eric A. Young]
-
- *) Added RIPE MD160 (rmd160) message digest.
- [Eric A. Young]
-
- *) Added -a (all) option to "ssleay version" command.
- [Eric A. Young]
-
- *) Added PLATFORM define which is the id given to Configure.
- [Eric A. Young]
-
- *) Added MemCheck_XXXX functions to crypto/mem.c for memory checking.
- [Eric A. Young]
-
- *) Extended the ASN.1 parser routines.
- [Eric A. Young]
-
- *) Extended BIO routines to support REUSEADDR, seek, tell, etc.
- [Eric A. Young]
-
- *) Added a BN_CTX to the BN library.
- [Eric A. Young]
-
- *) Fixed the weak key values in DES library
- [Eric A. Young]
-
- *) Changed API in EVP library for cipher aliases.
- [Eric A. Young]
-
- *) Added support for RC2/64bit cipher.
- [Eric A. Young]
-
- *) Converted the lhash library to the crypto/mem.c functions.
- [Eric A. Young]
-
- *) Added more recognized ASN.1 object ids.
- [Eric A. Young]
-
- *) Added more RSA padding checks for SSL/TLS.
- [Eric A. Young]
-
- *) Added BIO proxy/filter functionality.
- [Eric A. Young]
-
- *) Added extra_certs to SSL_CTX which can be used
- send extra CA certificates to the client in the CA cert chain sending
- process. It can be configured with SSL_CTX_add_extra_chain_cert().
- [Eric A. Young]
-
- *) Now Fortezza is denied in the authentication phase because
- this is key exchange mechanism is not supported by SSLeay at all.
- [Eric A. Young]
-
- *) Additional PKCS1 checks.
- [Eric A. Young]
-
- *) Support the string "TLSv1" for all TLS v1 ciphers.
- [Eric A. Young]
-
- *) Added function SSL_get_ex_data_X509_STORE_CTX_idx() which gives the
- ex_data index of the SSL context in the X509_STORE_CTX ex_data.
- [Eric A. Young]
-
- *) Fixed a few memory leaks.
- [Eric A. Young]
-
- *) Fixed various code and comment typos.
- [Eric A. Young]
-
- *) A minor bug in ssl/s3_clnt.c where there would always be 4 0
- bytes sent in the client random.
- [Edward Bishop <ebishop@spyglass.com>]
diff --git a/CHANGES.md b/CHANGES.md
new file mode 100644
index 000000000000..7cdd9d974536
--- /dev/null
+++ b/CHANGES.md
@@ -0,0 +1,19753 @@
+OpenSSL CHANGES
+===============
+
+This is a high-level summary of the most important changes.
+For a full list of changes, see the [git commit log][log] and
+pick the appropriate release branch.
+
+ [log]: https://github.com/openssl/openssl/commits/
+
+OpenSSL Releases
+----------------
+
+ - [OpenSSL 3.0](#openssl-30)
+ - [OpenSSL 1.1.1](#openssl-111)
+ - [OpenSSL 1.1.0](#openssl-110)
+ - [OpenSSL 1.0.2](#openssl-102)
+ - [OpenSSL 1.0.1](#openssl-101)
+ - [OpenSSL 1.0.0](#openssl-100)
+ - [OpenSSL 0.9.x](#openssl-09x)
+
+OpenSSL 3.0
+-----------
+
+For OpenSSL 3.0 a [Migration guide][] has been added, so the CHANGES entries
+listed here are only a brief description.
+The migration guide contains more detailed information related to new features,
+breaking changes, and mappings for the large list of deprecated functions.
+
+[Migration guide]: https://github.com/openssl/openssl/tree/master/doc/man7/migration_guide.pod
+
+### Changes between 3.0.7 and 3.0.8 [7 Feb 2023]
+
+ * Fixed NULL dereference during PKCS7 data verification.
+
+ A NULL pointer can be dereferenced when signatures are being
+ verified on PKCS7 signed or signedAndEnveloped data. In case the hash
+ algorithm used for the signature is known to the OpenSSL library but
+ the implementation of the hash algorithm is not available the digest
+ initialization will fail. There is a missing check for the return
+ value from the initialization function which later leads to invalid
+ usage of the digest API most likely leading to a crash.
+ ([CVE-2023-0401])
+
+ PKCS7 data is processed by the SMIME library calls and also by the
+ time stamp (TS) library calls. The TLS implementation in OpenSSL does
+ not call these functions however third party applications would be
+ affected if they call these functions to verify signatures on untrusted
+ data.
+
+ *Tomáš Mráz*
+
+ * Fixed X.400 address type confusion in X.509 GeneralName.
+
+ There is a type confusion vulnerability relating to X.400 address processing
+ inside an X.509 GeneralName. X.400 addresses were parsed as an ASN1_STRING
+ but the public structure definition for GENERAL_NAME incorrectly specified
+ the type of the x400Address field as ASN1_TYPE. This field is subsequently
+ interpreted by the OpenSSL function GENERAL_NAME_cmp as an ASN1_TYPE rather
+ than an ASN1_STRING.
+
+ When CRL checking is enabled (i.e. the application sets the
+ X509_V_FLAG_CRL_CHECK flag), this vulnerability may allow an attacker to
+ pass arbitrary pointers to a memcmp call, enabling them to read memory
+ contents or enact a denial of service.
+ ([CVE-2023-0286])
+
+ *Hugo Landau*
+
+ * Fixed NULL dereference validating DSA public key.
+
+ An invalid pointer dereference on read can be triggered when an
+ application tries to check a malformed DSA public key by the
+ EVP_PKEY_public_check() function. This will most likely lead
+ to an application crash. This function can be called on public
+ keys supplied from untrusted sources which could allow an attacker
+ to cause a denial of service attack.
+
+ The TLS implementation in OpenSSL does not call this function
+ but applications might call the function if there are additional
+ security requirements imposed by standards such as FIPS 140-3.
+ ([CVE-2023-0217])
+
+ *Shane Lontis, Tomáš Mráz*
+
+ * Fixed Invalid pointer dereference in d2i_PKCS7 functions.
+
+ An invalid pointer dereference on read can be triggered when an
+ application tries to load malformed PKCS7 data with the
+ d2i_PKCS7(), d2i_PKCS7_bio() or d2i_PKCS7_fp() functions.
+
+ The result of the dereference is an application crash which could
+ lead to a denial of service attack. The TLS implementation in OpenSSL
+ does not call this function however third party applications might
+ call these functions on untrusted data.
+ ([CVE-2023-0216])
+
+ *Tomáš Mráz*
+
+ * Fixed Use-after-free following BIO_new_NDEF.
+
+ The public API function BIO_new_NDEF is a helper function used for
+ streaming ASN.1 data via a BIO. It is primarily used internally to OpenSSL
+ to support the SMIME, CMS and PKCS7 streaming capabilities, but may also
+ be called directly by end user applications.
+
+ The function receives a BIO from the caller, prepends a new BIO_f_asn1
+ filter BIO onto the front of it to form a BIO chain, and then returns
+ the new head of the BIO chain to the caller. Under certain conditions,
+ for example if a CMS recipient public key is invalid, the new filter BIO
+ is freed and the function returns a NULL result indicating a failure.
+ However, in this case, the BIO chain is not properly cleaned up and the
+ BIO passed by the caller still retains internal pointers to the previously
+ freed filter BIO. If the caller then goes on to call BIO_pop() on the BIO
+ then a use-after-free will occur. This will most likely result in a crash.
+ ([CVE-2023-0215])
+
+ *Viktor Dukhovni, Matt Caswell*
+
+ * Fixed Double free after calling PEM_read_bio_ex.
+
+ The function PEM_read_bio_ex() reads a PEM file from a BIO and parses and
+ decodes the "name" (e.g. "CERTIFICATE"), any header data and the payload
+ data. If the function succeeds then the "name_out", "header" and "data"
+ arguments are populated with pointers to buffers containing the relevant
+ decoded data. The caller is responsible for freeing those buffers. It is
+ possible to construct a PEM file that results in 0 bytes of payload data.
+ In this case PEM_read_bio_ex() will return a failure code but will populate
+ the header argument with a pointer to a buffer that has already been freed.
+ If the caller also frees this buffer then a double free will occur. This
+ will most likely lead to a crash.
+
+ The functions PEM_read_bio() and PEM_read() are simple wrappers around
+ PEM_read_bio_ex() and therefore these functions are also directly affected.
+
+ These functions are also called indirectly by a number of other OpenSSL
+ functions including PEM_X509_INFO_read_bio_ex() and
+ SSL_CTX_use_serverinfo_file() which are also vulnerable. Some OpenSSL
+ internal uses of these functions are not vulnerable because the caller does
+ not free the header argument if PEM_read_bio_ex() returns a failure code.
+ ([CVE-2022-4450])
+
+ *Kurt Roeckx, Matt Caswell*
+
+ * Fixed Timing Oracle in RSA Decryption.
+
+ A timing based side channel exists in the OpenSSL RSA Decryption
+ implementation which could be sufficient to recover a plaintext across
+ a network in a Bleichenbacher style attack. To achieve a successful
+ decryption an attacker would have to be able to send a very large number
+ of trial messages for decryption. The vulnerability affects all RSA padding
+ modes: PKCS#1 v1.5, RSA-OEAP and RSASVE.
+ ([CVE-2022-4304])
+
+ *Dmitry Belyavsky, Hubert Kario*
+
+ * Fixed X.509 Name Constraints Read Buffer Overflow.
+
+ A read buffer overrun can be triggered in X.509 certificate verification,
+ specifically in name constraint checking. The read buffer overrun might
+ result in a crash which could lead to a denial of service attack.
+ In a TLS client, this can be triggered by connecting to a malicious
+ server. In a TLS server, this can be triggered if the server requests
+ client authentication and a malicious client connects.
+ ([CVE-2022-4203])
+
+ *Viktor Dukhovni*
+
+ * Fixed X.509 Policy Constraints Double Locking security issue.
+
+ If an X.509 certificate contains a malformed policy constraint and
+ policy processing is enabled, then a write lock will be taken twice
+ recursively. On some operating systems (most widely: Windows) this
+ results in a denial of service when the affected process hangs. Policy
+ processing being enabled on a publicly facing server is not considered
+ to be a common setup.
+ ([CVE-2022-3996])
+
+ *Paul Dale*
+
+ * Our provider implementations of `OSSL_FUNC_KEYMGMT_EXPORT` and
+ `OSSL_FUNC_KEYMGMT_GET_PARAMS` for EC and SM2 keys now honor
+ `OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT` as set (and
+ default to `POINT_CONVERSION_UNCOMPRESSED`) when exporting
+ `OSSL_PKEY_PARAM_PUB_KEY`, instead of unconditionally using
+ `POINT_CONVERSION_COMPRESSED` as in previous 3.x releases.
+ For symmetry, our implementation of `EVP_PKEY_ASN1_METHOD->export_to`
+ for legacy EC and SM2 keys is also changed similarly to honor the
+ equivalent conversion format flag as specified in the underlying
+ `EC_KEY` object being exported to a provider, when this function is
+ called through `EVP_PKEY_export()`.
+
+ *Nicola Tuveri*
+
+### Changes between 3.0.6 and 3.0.7 [1 Nov 2022]
+
+ * Fixed two buffer overflows in punycode decoding functions.
+
+ A buffer overrun can be triggered in X.509 certificate verification,
+ specifically in name constraint checking. Note that this occurs after
+ certificate chain signature verification and requires either a CA to
+ have signed the malicious certificate or for the application to continue
+ certificate verification despite failure to construct a path to a trusted
+ issuer.
+
+ In a TLS client, this can be triggered by connecting to a malicious
+ server. In a TLS server, this can be triggered if the server requests
+ client authentication and a malicious client connects.
+
+ An attacker can craft a malicious email address to overflow
+ an arbitrary number of bytes containing the `.` character (decimal 46)
+ on the stack. This buffer overflow could result in a crash (causing a
+ denial of service).
+ ([CVE-2022-3786])
+
+ An attacker can craft a malicious email address to overflow four
+ attacker-controlled bytes on the stack. This buffer overflow could
+ result in a crash (causing a denial of service) or potentially remote code
+ execution depending on stack layout for any given platform/compiler.
+ ([CVE-2022-3602])
+
+ *Paul Dale*
+
+ * Removed all references to invalid OSSL_PKEY_PARAM_RSA names for CRT
+ parameters in OpenSSL code.
+ Applications should not use the names OSSL_PKEY_PARAM_RSA_FACTOR,
+ OSSL_PKEY_PARAM_RSA_EXPONENT and OSSL_PKEY_PARAM_RSA_COEFFICIENT.
+ Use the numbered names such as OSSL_PKEY_PARAM_RSA_FACTOR1 instead.
+ Using these invalid names may cause algorithms to use slower methods
+ that ignore the CRT parameters.
+
+ *Shane Lontis*
+
+ * Fixed a regression introduced in 3.0.6 version raising errors on some stack
+ operations.
+
+ *Tomáš Mráz*
+
+ * Fixed a regression introduced in 3.0.6 version not refreshing the certificate
+ data to be signed before signing the certificate.
+
+ *Gibeom Gwon*
+
+ * Added RIPEMD160 to the default provider.
+
+ *Paul Dale*
+
+ * Ensured that the key share group sent or accepted for the key exchange
+ is allowed for the protocol version.
+
+ *Matt Caswell*
+
+### Changes between 3.0.5 and 3.0.6 [11 Oct 2022]
+
+ * OpenSSL supports creating a custom cipher via the legacy
+ EVP_CIPHER_meth_new() function and associated function calls. This function
+ was deprecated in OpenSSL 3.0 and application authors are instead encouraged
+ to use the new provider mechanism in order to implement custom ciphers.
+
+ OpenSSL versions 3.0.0 to 3.0.5 incorrectly handle legacy custom ciphers
+ passed to the EVP_EncryptInit_ex2(), EVP_DecryptInit_ex2() and
+ EVP_CipherInit_ex2() functions (as well as other similarly named encryption
+ and decryption initialisation functions). Instead of using the custom cipher
+ directly it incorrectly tries to fetch an equivalent cipher from the
+ available providers. An equivalent cipher is found based on the NID passed to
+ EVP_CIPHER_meth_new(). This NID is supposed to represent the unique NID for a
+ given cipher. However it is possible for an application to incorrectly pass
+ NID_undef as this value in the call to EVP_CIPHER_meth_new(). When NID_undef
+ is used in this way the OpenSSL encryption/decryption initialisation function
+ will match the NULL cipher as being equivalent and will fetch this from the
+ available providers. This will succeed if the default provider has been
+ loaded (or if a third party provider has been loaded that offers this
+ cipher). Using the NULL cipher means that the plaintext is emitted as the
+ ciphertext.
+
+ Applications are only affected by this issue if they call
+ EVP_CIPHER_meth_new() using NID_undef and subsequently use it in a call to an
+ encryption/decryption initialisation function. Applications that only use
+ SSL/TLS are not impacted by this issue.
+ ([CVE-2022-3358])
+
+ *Matt Caswell*
+
+ * Fix LLVM vs Apple LLVM version numbering confusion that caused build failures
+ on MacOS 10.11
+
+ *Richard Levitte*
+
+ * Fixed the linux-mips64 Configure target which was missing the
+ SIXTY_FOUR_BIT bn_ops flag. This was causing heap corruption on that
+ platform.
+
+ *Adam Joseph*
+
+ * Fix handling of a ticket key callback that returns 0 in TLSv1.3 to not send a
+ ticket
+
+ *Matt Caswell*
+
+ * Correctly handle a retransmitted ClientHello in DTLS
+
+ *Matt Caswell*
+
+ * Fixed detection of ktls support in cross-compile environment on Linux
+
+ *Tomas Mraz*
+
+ * Fixed some regressions and test failures when running the 3.0.0 FIPS provider
+ against 3.0.x
+
+ *Paul Dale*
+
+ * Fixed SSL_pending() and SSL_has_pending() with DTLS which were failing to
+ report correct results in some cases
+
+ *Matt Caswell*
+
+ * Fix UWP builds by defining VirtualLock
+
+ *Charles Milette*
+
+ * For known safe primes use the minimum key length according to RFC 7919.
+ Longer private key sizes unnecessarily raise the cycles needed to compute the
+ shared secret without any increase of the real security. This fixes a
+ regression from 1.1.1 where these shorter keys were generated for the known
+ safe primes.
+
+ *Tomas Mraz*
+
+ * Added the loongarch64 target
+
+ *Shi Pujin*
+
+ * Fixed EC ASM flag passing. Flags for ASM implementations of EC curves were
+ only passed to the FIPS provider and not to the default or legacy provider.
+
+ *Juergen Christ*
+
+ * Fixed reported performance degradation on aarch64. Restored the
+ implementation prior to commit 2621751 ("aes/asm/aesv8-armx.pl: avoid
+ 32-bit lane assignment in CTR mode") for 64bit targets only, since it is
+ reportedly 2-17% slower and the silicon errata only affects 32bit targets.
+ The new algorithm is still used for 32 bit targets.
+
+ *Bernd Edlinger*
+
+ * Added a missing header for memcmp that caused compilation failure on some
+ platforms
+
+ *Gregor Jasny*
+
+### Changes between 3.0.4 and 3.0.5 [5 Jul 2022]
+
+ * The OpenSSL 3.0.4 release introduced a serious bug in the RSA
+ implementation for X86_64 CPUs supporting the AVX512IFMA instructions.
+ This issue makes the RSA implementation with 2048 bit private keys
+ incorrect on such machines and memory corruption will happen during
+ the computation. As a consequence of the memory corruption an attacker
+ may be able to trigger a remote code execution on the machine performing
+ the computation.
+
+ SSL/TLS servers or other servers using 2048 bit RSA private keys running
+ on machines supporting AVX512IFMA instructions of the X86_64 architecture
+ are affected by this issue.
+ ([CVE-2022-2274])
+
+ *Xi Ruoyao*
+
+ * AES OCB mode for 32-bit x86 platforms using the AES-NI assembly optimised
+ implementation would not encrypt the entirety of the data under some
+ circumstances. This could reveal sixteen bytes of data that was
+ preexisting in the memory that wasn't written. In the special case of
+ "in place" encryption, sixteen bytes of the plaintext would be revealed.
+
+ Since OpenSSL does not support OCB based cipher suites for TLS and DTLS,
+ they are both unaffected.
+ ([CVE-2022-2097])
+
+ *Alex Chernyakhovsky, David Benjamin, Alejandro Sedeño*
+
+### Changes between 3.0.3 and 3.0.4 [21 Jun 2022]
+
+ * In addition to the c_rehash shell command injection identified in
+ CVE-2022-1292, further bugs where the c_rehash script does not
+ properly sanitise shell metacharacters to prevent command injection have been
+ fixed.
+
+ When the CVE-2022-1292 was fixed it was not discovered that there
+ are other places in the script where the file names of certificates
+ being hashed were possibly passed to a command executed through the shell.
+
+ This script is distributed by some operating systems in a manner where
+ it is automatically executed. On such operating systems, an attacker
+ could execute arbitrary commands with the privileges of the script.
+
+ Use of the c_rehash script is considered obsolete and should be replaced
+ by the OpenSSL rehash command line tool.
+ (CVE-2022-2068)
+
+ *Daniel Fiala, Tomáš Mráz*
+
+ * Case insensitive string comparison no longer uses locales. It has instead
+ been directly implemented.
+
+ *Paul Dale*
+
+### Changes between 3.0.2 and 3.0.3 [3 May 2022]
+
+ * Case insensitive string comparison is reimplemented via new locale-agnostic
+ comparison functions OPENSSL_str[n]casecmp always using the POSIX locale for
+ comparison. The previous implementation had problems when the Turkish locale
+ was used.
+
+ *Dmitry Belyavskiy*
+
+ * Fixed a bug in the c_rehash script which was not properly sanitising shell
+ metacharacters to prevent command injection. This script is distributed by
+ some operating systems in a manner where it is automatically executed. On
+ such operating systems, an attacker could execute arbitrary commands with the
+ privileges of the script.
+
+ Use of the c_rehash script is considered obsolete and should be replaced
+ by the OpenSSL rehash command line tool.
+ (CVE-2022-1292)
+
+ *Tomáš Mráz*
+
+ * Fixed a bug in the function `OCSP_basic_verify` that verifies the signer
+ certificate on an OCSP response. The bug caused the function in the case
+ where the (non-default) flag OCSP_NOCHECKS is used to return a postivie
+ response (meaning a successful verification) even in the case where the
+ response signing certificate fails to verify.
+
+ It is anticipated that most users of `OCSP_basic_verify` will not use the
+ OCSP_NOCHECKS flag. In this case the `OCSP_basic_verify` function will return
+ a negative value (indicating a fatal error) in the case of a certificate
+ verification failure. The normal expected return value in this case would be
+ 0.
+
+ This issue also impacts the command line OpenSSL "ocsp" application. When
+ verifying an ocsp response with the "-no_cert_checks" option the command line
+ application will report that the verification is successful even though it
+ has in fact failed. In this case the incorrect successful response will also
+ be accompanied by error messages showing the failure and contradicting the
+ apparently successful result.
+ ([CVE-2022-1343])
+
+ *Matt Caswell*
+
+ * Fixed a bug where the RC4-MD5 ciphersuite incorrectly used the
+ AAD data as the MAC key. This made the MAC key trivially predictable.
+
+ An attacker could exploit this issue by performing a man-in-the-middle attack
+ to modify data being sent from one endpoint to an OpenSSL 3.0 recipient such
+ that the modified data would still pass the MAC integrity check.
+
+ Note that data sent from an OpenSSL 3.0 endpoint to a non-OpenSSL 3.0
+ endpoint will always be rejected by the recipient and the connection will
+ fail at that point. Many application protocols require data to be sent from
+ the client to the server first. Therefore, in such a case, only an OpenSSL
+ 3.0 server would be impacted when talking to a non-OpenSSL 3.0 client.
+
+ If both endpoints are OpenSSL 3.0 then the attacker could modify data being
+ sent in both directions. In this case both clients and servers could be
+ affected, regardless of the application protocol.
+
+ Note that in the absence of an attacker this bug means that an OpenSSL 3.0
+ endpoint communicating with a non-OpenSSL 3.0 endpoint will fail to complete
+ the handshake when using this ciphersuite.
+
+ The confidentiality of data is not impacted by this issue, i.e. an attacker
+ cannot decrypt data that has been encrypted using this ciphersuite - they can
+ only modify it.
+
+ In order for this attack to work both endpoints must legitimately negotiate
+ the RC4-MD5 ciphersuite. This ciphersuite is not compiled by default in
+ OpenSSL 3.0, and is not available within the default provider or the default
+ ciphersuite list. This ciphersuite will never be used if TLSv1.3 has been
+ negotiated. In order for an OpenSSL 3.0 endpoint to use this ciphersuite the
+ following must have occurred:
+
+ 1) OpenSSL must have been compiled with the (non-default) compile time option
+ enable-weak-ssl-ciphers
+
+ 2) OpenSSL must have had the legacy provider explicitly loaded (either
+ through application code or via configuration)
+
+ 3) The ciphersuite must have been explicitly added to the ciphersuite list
+
+ 4) The libssl security level must have been set to 0 (default is 1)
+
+ 5) A version of SSL/TLS below TLSv1.3 must have been negotiated
+
+ 6) Both endpoints must negotiate the RC4-MD5 ciphersuite in preference to any
+ others that both endpoints have in common
+ (CVE-2022-1434)
+
+ *Matt Caswell*
+
+ * Fix a bug in the OPENSSL_LH_flush() function that breaks reuse of the memory
+ occuppied by the removed hash table entries.
+
+ This function is used when decoding certificates or keys. If a long lived
+ process periodically decodes certificates or keys its memory usage will
+ expand without bounds and the process might be terminated by the operating
+ system causing a denial of service. Also traversing the empty hash table
+ entries will take increasingly more time.
+
+ Typically such long lived processes might be TLS clients or TLS servers
+ configured to accept client certificate authentication.
+ (CVE-2022-1473)
+
+ *Hugo Landau, Aliaksei Levin*
+
+ * The functions `OPENSSL_LH_stats` and `OPENSSL_LH_stats_bio` now only report
+ the `num_items`, `num_nodes` and `num_alloc_nodes` statistics. All other
+ statistics are no longer supported. For compatibility, these statistics are
+ still listed in the output but are now always reported as zero.
+
+ *Hugo Landau*
+
+### Changes between 3.0.1 and 3.0.2 [15 Mar 2022]
+
+ * Fixed a bug in the BN_mod_sqrt() function that can cause it to loop forever
+ for non-prime moduli.
+
+ Internally this function is used when parsing certificates that contain
+ elliptic curve public keys in compressed form or explicit elliptic curve
+ parameters with a base point encoded in compressed form.
+
+ It is possible to trigger the infinite loop by crafting a certificate that
+ has invalid explicit curve parameters.
+
+ Since certificate parsing happens prior to verification of the certificate
+ signature, any process that parses an externally supplied certificate may thus
+ be subject to a denial of service attack. The infinite loop can also be
+ reached when parsing crafted private keys as they can contain explicit
+ elliptic curve parameters.
+
+ Thus vulnerable situations include:
+
+ - TLS clients consuming server certificates
+ - TLS servers consuming client certificates
+ - Hosting providers taking certificates or private keys from customers
+ - Certificate authorities parsing certification requests from subscribers
+ - Anything else which parses ASN.1 elliptic curve parameters
+
+ Also any other applications that use the BN_mod_sqrt() where the attacker
+ can control the parameter values are vulnerable to this DoS issue.
+ ([CVE-2022-0778])
+
+ *Tomáš Mráz*
+
+ * Add ciphersuites based on DHE_PSK (RFC 4279) and ECDHE_PSK (RFC 5489)
+ to the list of ciphersuites providing Perfect Forward Secrecy as
+ required by SECLEVEL >= 3.
+
+ *Dmitry Belyavskiy, Nicola Tuveri*
+
+ * Made the AES constant time code for no-asm configurations
+ optional due to the resulting 95% performance degradation.
+ The AES constant time code can be enabled, for no assembly
+ builds, with: ./config no-asm -DOPENSSL_AES_CONST_TIME
+
+ *Paul Dale*
+
+ * Fixed PEM_write_bio_PKCS8PrivateKey() to make it possible to use empty
+ passphrase strings.
+
+ *Darshan Sen*
+
+ * The negative return value handling of the certificate verification callback
+ was reverted. The replacement is to set the verification retry state with
+ the SSL_set_retry_verify() function.
+
+ *Tomáš Mráz*
+
+### Changes between 3.0.0 and 3.0.1 [14 Dec 2021]
+
+ * Fixed invalid handling of X509_verify_cert() internal errors in libssl
+ Internally libssl in OpenSSL calls X509_verify_cert() on the client side to
+ verify a certificate supplied by a server. That function may return a
+ negative return value to indicate an internal error (for example out of
+ memory). Such a negative return value is mishandled by OpenSSL and will cause
+ an IO function (such as SSL_connect() or SSL_do_handshake()) to not indicate
+ success and a subsequent call to SSL_get_error() to return the value
+ SSL_ERROR_WANT_RETRY_VERIFY. This return value is only supposed to be
+ returned by OpenSSL if the application has previously called
+ SSL_CTX_set_cert_verify_callback(). Since most applications do not do this
+ the SSL_ERROR_WANT_RETRY_VERIFY return value from SSL_get_error() will be
+ totally unexpected and applications may not behave correctly as a result. The
+ exact behaviour will depend on the application but it could result in
+ crashes, infinite loops or other similar incorrect responses.
+
+ This issue is made more serious in combination with a separate bug in OpenSSL
+ 3.0 that will cause X509_verify_cert() to indicate an internal error when
+ processing a certificate chain. This will occur where a certificate does not
+ include the Subject Alternative Name extension but where a Certificate
+ Authority has enforced name constraints. This issue can occur even with valid
+ chains.
+ ([CVE-2021-4044])
+
+ *Matt Caswell*
+
+ * Corrected a few file name and file reference bugs in the build,
+ installation and setup scripts, which lead to installation verification
+ failures. Slightly enhanced the installation verification script.
+
+ *Richard Levitte*
+
+ * Fixed EVP_PKEY_eq() to make it possible to use it with strictly private
+ keys.
+
+ *Richard Levitte*
+
+ * Fixed PVK encoder to properly query for the passphrase.
+
+ *Tomáš Mráz*
+
+ * Multiple fixes in the OSSL_HTTP API functions.
+
+ *David von Oheimb*
+
+ * Allow sign extension in OSSL_PARAM_allocate_from_text() for the
+ OSSL_PARAM_INTEGER data type and return error on negative numbers
+ used with the OSSL_PARAM_UNSIGNED_INTEGER data type. Make
+ OSSL_PARAM_BLD_push_BN{,_pad}() return an error on negative numbers.
+
+ *Richard Levitte*
+
+ * Allow copying uninitialized digest contexts with EVP_MD_CTX_copy_ex.
+
+ *Tomáš Mráz*
+
+ * Fixed detection of ARMv7 and ARM64 CPU features on FreeBSD.
+
+ *Allan Jude*
+
+ * Multiple threading fixes.
+
+ *Matt Caswell*
+
+ * Added NULL digest implementation to keep compatibility with 1.1.1 version.
+
+ *Tomáš Mráz*
+
+ * Allow fetching an operation from the provider that owns an unexportable key
+ as a fallback if that is still allowed by the property query.
+
+ *Richard Levitte*
+
+### Changes between 1.1.1 and 3.0.0 [7 sep 2021]
+
+ * TLS_MAX_VERSION, DTLS_MAX_VERSION and DTLS_MIN_VERSION constants are now
+ deprecated.
+
+ *Matt Caswell*
+
+ * The `OPENSSL_s390xcap` environment variable can be used to set bits in the
+ S390X capability vector to zero. This simplifies testing of different code
+ paths on S390X architecture.
+
+ *Patrick Steuer*
+
+ * Encrypting more than 2^64 TLS records with AES-GCM is disallowed
+ as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness Requirements from
+ SP 800-38D". The communication will fail at this point.
+
+ *Paul Dale*
+
+ * The EC_GROUP_clear_free() function is deprecated as there is nothing
+ confidential in EC_GROUP data.
+
+ *Nicola Tuveri*
+
+ * The byte order mark (BOM) character is ignored if encountered at the
+ beginning of a PEM-formatted file.
+
+ *Dmitry Belyavskiy*
+
+ * Added CMS support for the Russian GOST algorithms.
+
+ *Dmitry Belyavskiy*
+
+ * Due to move of the implementation of cryptographic operations
+ to the providers, validation of various operation parameters can
+ be postponed until the actual operation is executed where previously
+ it happened immediately when an operation parameter was set.
+
+ For example when setting an unsupported curve with
+ EVP_PKEY_CTX_set_ec_paramgen_curve_nid() this function call will not
+ fail but later keygen operations with the EVP_PKEY_CTX will fail.
+
+ *OpenSSL team members and many third party contributors*
+
+ * The EVP_get_cipherbyname() function will return NULL for algorithms such as
+ "AES-128-SIV", "AES-128-CBC-CTS" and "CAMELLIA-128-CBC-CTS" which were
+ previously only accessible via low level interfaces. Use EVP_CIPHER_fetch()
+ instead to retrieve these algorithms from a provider.
+
+ *Shane Lontis*
+
+ * On build targets where the multilib postfix is set in the build
+ configuration the libdir directory was changing based on whether
+ the lib directory with the multilib postfix exists on the system
+ or not. This unpredictable behavior was removed and eventual
+ multilib postfix is now always added to the default libdir. Use
+ `--libdir=lib` to override the libdir if adding the postfix is
+ undesirable.
+
+ *Jan Lána*
+
+ * The triple DES key wrap functionality now conforms to RFC 3217 but is
+ no longer interoperable with OpenSSL 1.1.1.
+
+ *Paul Dale*
+
+ * The ERR_GET_FUNC() function was removed. With the loss of meaningful
+ function codes, this function can only cause problems for calling
+ applications.
+
+ *Paul Dale*
+
+ * Add a configurable flag to output date formats as ISO 8601. Does not
+ change the default date format.
+
+ *William Edmisten*
+
+ * Version of MSVC earlier than 1300 could get link warnings, which could
+ be suppressed if the undocumented -DI_CAN_LIVE_WITH_LNK4049 was set.
+ Support for this flag has been removed.
+
+ *Rich Salz*
+
+ * Rework and make DEBUG macros consistent. Remove unused -DCONF_DEBUG,
+ -DBN_CTX_DEBUG, and REF_PRINT. Add a new tracing category and use it for
+ printing reference counts. Rename -DDEBUG_UNUSED to -DUNUSED_RESULT_DEBUG
+ Fix BN_DEBUG_RAND so it compiles and, when set, force DEBUG_RAND to be set
+ also. Rename engine_debug_ref to be ENGINE_REF_PRINT also for consistency.
+
+ *Rich Salz*
+
+ * The signatures of the functions to get and set options on SSL and
+ SSL_CTX objects changed from "unsigned long" to "uint64_t" type.
+ Some source code changes may be required.
+
+ *Rich Salz*
+
+ * The public definitions of conf_method_st and conf_st have been
+ deprecated. They will be made opaque in a future release.
+
+ *Rich Salz and Tomáš Mráz*
+
+ * Client-initiated renegotiation is disabled by default. To allow it, use
+ the -client_renegotiation option, the SSL_OP_ALLOW_CLIENT_RENEGOTIATION
+ flag, or the "ClientRenegotiation" config parameter as appropriate.
+
+ *Rich Salz*
+
+ * Add "abspath" and "includedir" pragma's to config files, to prevent,
+ or modify relative pathname inclusion.
+
+ *Rich Salz*
+
+ * OpenSSL includes a cryptographic module that is intended to be FIPS 140-2
+ validated. Please consult the README-FIPS and
+ README-PROVIDERS files, as well as the migration guide.
+
+ *OpenSSL team members and many third party contributors*
+
+ * For the key types DH and DHX the allowed settable parameters are now different.
+
+ *Shane Lontis*
+
+ * The openssl commands that read keys, certificates, and CRLs now
+ automatically detect the PEM or DER format of the input files.
+
+ *David von Oheimb, Richard Levitte, and Tomáš Mráz*
+
+ * Added enhanced PKCS#12 APIs which accept a library context.
+
+ *Jon Spillett*
+
+ * The default manual page suffix ($MANSUFFIX) has been changed to "ossl"
+
+ *Matt Caswell*
+
+ * Added support for Kernel TLS (KTLS).
+
+ *Boris Pismenny, John Baldwin and Andrew Gallatin*
+
+ * Support for RFC 5746 secure renegotiation is now required by default for
+ SSL or TLS connections to succeed.
+
+ *Benjamin Kaduk*
+
+ * The signature of the `copy` functional parameter of the
+ EVP_PKEY_meth_set_copy() function has changed so its `src` argument is
+ now `const EVP_PKEY_CTX *` instead of `EVP_PKEY_CTX *`. Similarly
+ the signature of the `pub_decode` functional parameter of the
+ EVP_PKEY_asn1_set_public() function has changed so its `pub` argument is
+ now `const X509_PUBKEY *` instead of `X509_PUBKEY *`.
+
+ *David von Oheimb*
+
+ * The error return values from some control calls (ctrl) have changed.
+
+ *Paul Dale*
+
+ * A public key check is now performed during EVP_PKEY_derive_set_peer().
+
+ *Shane Lontis*
+
+ * Many functions in the EVP_ namespace that are getters of values from
+ implementations or contexts were renamed to include get or get0 in their
+ names. Old names are provided as macro aliases for compatibility and
+ are not deprecated.
+
+ *Tomáš Mráz*
+
+ * The EVP_PKEY_CTRL_PKCS7_ENCRYPT, EVP_PKEY_CTRL_PKCS7_DECRYPT,
+ EVP_PKEY_CTRL_PKCS7_SIGN, EVP_PKEY_CTRL_CMS_ENCRYPT,
+ EVP_PKEY_CTRL_CMS_DECRYPT, and EVP_PKEY_CTRL_CMS_SIGN control operations
+ are deprecated.
+
+ *Tomáš Mráz*
+
+ * The EVP_PKEY_public_check() and EVP_PKEY_param_check() functions now work for
+ more key types.
+
+ * The output from the command line applications may have minor
+ changes.
+
+ *Paul Dale*
+
+ * The output from numerous "printing" may have minor changes.
+
+ *David von Oheimb*
+
+ * Windows thread synchronization uses read/write primitives (SRWLock) when
+ supported by the OS, otherwise CriticalSection continues to be used.
+
+ *Vincent Drake*
+
+ * Add filter BIO BIO_f_readbuffer() that allows BIO_tell() and BIO_seek() to
+ work on read only BIO source/sinks that do not support these functions.
+ This allows piping or redirection of a file BIO using stdin to be buffered
+ into memory. This is used internally in OSSL_DECODER_from_bio().
+
+ *Shane Lontis*
+
+ * OSSL_STORE_INFO_get_type() may now return an additional value. In 1.1.1
+ this function would return one of the values OSSL_STORE_INFO_NAME,
+ OSSL_STORE_INFO_PKEY, OSSL_STORE_INFO_PARAMS, OSSL_STORE_INFO_CERT or
+ OSSL_STORE_INFO_CRL. Decoded public keys would previously have been reported
+ as type OSSL_STORE_INFO_PKEY in 1.1.1. In 3.0 decoded public keys are now
+ reported as having the new type OSSL_STORE_INFO_PUBKEY. Applications
+ using this function should be amended to handle the changed return value.
+
+ *Richard Levitte*
+
+ * Improved adherence to Enhanced Security Services (ESS, RFC 2634 and RFC 5035)
+ for the TSP and CMS Advanced Electronic Signatures (CAdES) implementations.
+ As required by RFC 5035 check both ESSCertID and ESSCertIDv2 if both present.
+ Correct the semantics of checking the validation chain in case ESSCertID{,v2}
+ contains more than one certificate identifier: This means that all
+ certificates referenced there MUST be part of the validation chain.
+
+ *David von Oheimb*
+
+ * The implementation of older EVP ciphers related to CAST, IDEA, SEED, RC2, RC4,
+ RC5, DESX and DES have been moved to the legacy provider.
+
+ *Matt Caswell*
+
+ * The implementation of the EVP digests MD2, MD4, MDC2, WHIRLPOOL and
+ RIPEMD-160 have been moved to the legacy provider.
+
+ *Matt Caswell*
+
+ * The deprecated function EVP_PKEY_get0() now returns NULL being called for a
+ provided key.
+
+ *Dmitry Belyavskiy*
+
+ * The deprecated functions EVP_PKEY_get0_RSA(),
+ EVP_PKEY_get0_DSA(), EVP_PKEY_get0_EC_KEY(), EVP_PKEY_get0_DH(),
+ EVP_PKEY_get0_hmac(), EVP_PKEY_get0_poly1305() and EVP_PKEY_get0_siphash() as
+ well as the similarly named "get1" functions behave differently in
+ OpenSSL 3.0.
+
+ *Matt Caswell*
+
+ * A number of functions handling low-level keys or engines were deprecated
+ including EVP_PKEY_set1_engine(), EVP_PKEY_get0_engine(), EVP_PKEY_assign(),
+ EVP_PKEY_get0(), EVP_PKEY_get0_hmac(), EVP_PKEY_get0_poly1305() and
+ EVP_PKEY_get0_siphash().
+
+ *Matt Caswell*
+
+ * PKCS#5 PBKDF1 key derivation has been moved from PKCS5_PBE_keyivgen() into
+ the legacy crypto provider as an EVP_KDF. Applications requiring this KDF
+ will need to load the legacy crypto provider. This includes these PBE
+ algorithms which use this KDF:
+ - NID_pbeWithMD2AndDES_CBC
+ - NID_pbeWithMD5AndDES_CBC
+ - NID_pbeWithSHA1AndRC2_CBC
+ - NID_pbeWithMD2AndRC2_CBC
+ - NID_pbeWithMD5AndRC2_CBC
+ - NID_pbeWithSHA1AndDES_CBC
+
+ *Jon Spillett*
+
+ * Deprecated obsolete BIO_set_callback(), BIO_get_callback(), and
+ BIO_debug_callback() functions.
+
+ *Tomáš Mráz*
+
+ * Deprecated obsolete EVP_PKEY_CTX_get0_dh_kdf_ukm() and
+ EVP_PKEY_CTX_get0_ecdh_kdf_ukm() functions.
+
+ *Tomáš Mráz*
+
+ * The RAND_METHOD APIs have been deprecated.
+
+ *Paul Dale*
+
+ * The SRP APIs have been deprecated.
+
+ *Matt Caswell*
+
+ * Add a compile time option to prevent the caching of provider fetched
+ algorithms. This is enabled by including the no-cached-fetch option
+ at configuration time.
+
+ *Paul Dale*
+
+ * pkcs12 now uses defaults of PBKDF2, AES and SHA-256, with a MAC iteration
+ count of PKCS12_DEFAULT_ITER.
+
+ *Tomáš Mráz and Sahana Prasad*
+
+ * The openssl speed command does not use low-level API calls anymore.
+
+ *Tomáš Mráz*
+
+ * Parallel dual-prime 1024-bit modular exponentiation for AVX512_IFMA
+ capable processors.
+
+ *Ilya Albrekht, Sergey Kirillov, Andrey Matyukov (Intel Corp)*
+
+ * Combining the Configure options no-ec and no-dh no longer disables TLSv1.3.
+
+ *Matt Caswell*
+
+ * Implemented support for fully "pluggable" TLSv1.3 groups. This means that
+ providers may supply their own group implementations (using either the "key
+ exchange" or the "key encapsulation" methods) which will automatically be
+ detected and used by libssl.
+
+ *Matt Caswell, Nicola Tuveri*
+
+ * The undocumented function X509_certificate_type() has been deprecated;
+
+ *Rich Salz*
+
+ * Deprecated the obsolete BN_pseudo_rand() and BN_pseudo_rand_range().
+
+ *Tomáš Mráz*
+
+ * Removed RSA padding mode for SSLv23 (which was only used for
+ SSLv2). This includes the functions RSA_padding_check_SSLv23() and
+ RSA_padding_add_SSLv23() and the `-ssl` option in the deprecated
+ `rsautl` command.
+
+ *Rich Salz*
+
+ * Deprecated the obsolete X9.31 RSA key generation related functions.
+
+ * While a callback function set via `SSL_CTX_set_cert_verify_callback()`
+ is not allowed to return a value > 1, this is no more taken as failure.
+
+ *Viktor Dukhovni and David von Oheimb*
+
+ * Deprecated the obsolete X9.31 RSA key generation related functions
+ BN_X931_generate_Xpq(), BN_X931_derive_prime_ex(), and
+ BN_X931_generate_prime_ex().
+
+ *Tomáš Mráz*
+
+ * The default key generation method for the regular 2-prime RSA keys was
+ changed to the FIPS 186-4 B.3.6 method.
+
+ *Shane Lontis*
+
+ * Deprecated the BN_is_prime_ex() and BN_is_prime_fasttest_ex() functions.
+
+ *Kurt Roeckx*
+
+ * Deprecated EVP_MD_CTX_set_update_fn() and EVP_MD_CTX_update_fn().
+
+ *Rich Salz*
+
+ * Deprecated the type OCSP_REQ_CTX and the functions OCSP_REQ_CTX_*() and
+ replaced with OSSL_HTTP_REQ_CTX and the functions OSSL_HTTP_REQ_CTX_*().
+
+ *Rich Salz, Richard Levitte, and David von Oheimb*
+
+ * Deprecated `X509_http_nbio()` and `X509_CRL_http_nbio()`.
+
+ *David von Oheimb*
+
+ * Deprecated `OCSP_parse_url()`.
+
+ *David von Oheimb*
+
+ * Validation of SM2 keys has been separated from the validation of regular EC
+ keys.
+
+ *Nicola Tuveri*
+
+ * Behavior of the `pkey` app is changed, when using the `-check` or `-pubcheck`
+ switches: a validation failure triggers an early exit, returning a failure
+ exit status to the parent process.
+
+ *Nicola Tuveri*
+
+ * Changed behavior of SSL_CTX_set_ciphersuites() and SSL_set_ciphersuites()
+ to ignore unknown ciphers.
+
+ *Otto Hollmann*
+
+ * The `-cipher-commands` and `-digest-commands` options
+ of the command line utility `list` have been deprecated.
+ Instead use the `-cipher-algorithms` and `-digest-algorithms` options.
+
+ *Dmitry Belyavskiy*
+
+ * Added convenience functions for generating asymmetric key pairs:
+ The 'quick' one-shot (yet somewhat limited) function L<EVP_PKEY_Q_keygen(3)>
+ and macros for the most common cases: <EVP_RSA_gen(3)> and L<EVP_EC_gen(3)>.
+
+ *David von Oheimb*
+
+ * All of the low level EC_KEY functions have been deprecated.
+
+ *Shane Lontis, Paul Dale, Richard Levitte, and Tomáš Mráz*
+
+ * Deprecated all the libcrypto and libssl error string loading
+ functions.
+
+ *Richard Levitte*
+
+ * The functions SSL_CTX_set_tmp_dh_callback and SSL_set_tmp_dh_callback, as
+ well as the macros SSL_CTX_set_tmp_dh() and SSL_set_tmp_dh() have been
+ deprecated.
+
+ *Matt Caswell*
+
+ * The `-crypt` option to the `passwd` command line tool has been removed.
+
+ *Paul Dale*
+
+ * The -C option to the `x509`, `dhparam`, `dsaparam`, and `ecparam` commands
+ were removed.
+
+ *Rich Salz*
+
+ * Add support for AES Key Wrap inverse ciphers to the EVP layer.
+
+ *Shane Lontis*
+
+ * Deprecated EVP_PKEY_set1_tls_encodedpoint() and
+ EVP_PKEY_get1_tls_encodedpoint().
+
+ *Matt Caswell*
+
+ * The security callback, which can be customised by application code, supports
+ the security operation SSL_SECOP_TMP_DH. One location of the "other" parameter
+ was incorrectly passing a DH object. It now passed an EVP_PKEY in all cases.
+
+ *Matt Caswell*
+
+ * Add PKCS7_get_octet_string() and PKCS7_type_is_other() to the public
+ interface. Their functionality remains unchanged.
+
+ *Jordan Montgomery*
+
+ * Added new option for 'openssl list', '-providers', which will display the
+ list of loaded providers, their names, version and status. It optionally
+ displays their gettable parameters.
+
+ *Paul Dale*
+
+ * Removed EVP_PKEY_set_alias_type().
+
+ *Richard Levitte*
+
+ * Deprecated `EVP_PKEY_CTX_set_rsa_keygen_pubexp()` and introduced
+ `EVP_PKEY_CTX_set1_rsa_keygen_pubexp()`, which is now preferred.
+
+ *Jeremy Walch*
+
+ * Changed all "STACK" functions to be macros instead of inline functions. Macro
+ parameters are still checked for type safety at compile time via helper
+ inline functions.
+
+ *Matt Caswell*
+
+ * Remove the RAND_DRBG API
+
+ *Paul Dale and Matthias St. Pierre*
+
+ * Allow `SSL_set1_host()` and `SSL_add1_host()` to take IP literal addresses
+ as well as actual hostnames.
+
+ *David Woodhouse*
+
+ * The 'MinProtocol' and 'MaxProtocol' configuration commands now silently
+ ignore TLS protocol version bounds when configuring DTLS-based contexts, and
+ conversely, silently ignore DTLS protocol version bounds when configuring
+ TLS-based contexts. The commands can be repeated to set bounds of both
+ types. The same applies with the corresponding "min_protocol" and
+ "max_protocol" command-line switches, in case some application uses both TLS
+ and DTLS.
+
+ SSL_CTX instances that are created for a fixed protocol version (e.g.
+ `TLSv1_server_method()`) also silently ignore version bounds. Previously
+ attempts to apply bounds to these protocol versions would result in an
+ error. Now only the "version-flexible" SSL_CTX instances are subject to
+ limits in configuration files in command-line options.
+
+ *Viktor Dukhovni*
+
+ * Deprecated the `ENGINE` API. Engines should be replaced with providers
+ going forward.
+
+ *Paul Dale*
+
+ * Reworked the recorded ERR codes to make better space for system errors.
+ To distinguish them, the macro `ERR_SYSTEM_ERROR()` indicates if the
+ given code is a system error (true) or an OpenSSL error (false).
+
+ *Richard Levitte*
+
+ * Reworked the test perl framework to better allow parallel testing.
+
+ *Nicola Tuveri and David von Oheimb*
+
+ * Added ciphertext stealing algorithms AES-128-CBC-CTS, AES-192-CBC-CTS and
+ AES-256-CBC-CTS to the providers. CS1, CS2 and CS3 variants are supported.
+
+ *Shane Lontis*
+
+ * 'Configure' has been changed to figure out the configuration target if
+ none is given on the command line. Consequently, the 'config' script is
+ now only a mere wrapper. All documentation is changed to only mention
+ 'Configure'.
+
+ *Rich Salz and Richard Levitte*
+
+ * Added a library context `OSSL_LIB_CTX` that applications as well as
+ other libraries can use to form a separate context within which
+ libcrypto operations are performed.
+
+ *Richard Levitte*
+
+ * Added various `_ex` functions to the OpenSSL API that support using
+ a non-default `OSSL_LIB_CTX`.
+
+ *OpenSSL team*
+
+ * Handshake now fails if Extended Master Secret extension is dropped
+ on renegotiation.
+
+ *Tomáš Mráz*
+
+ * Dropped interactive mode from the `openssl` program.
+
+ *Richard Levitte*
+
+ * Deprecated `EVP_PKEY_cmp()` and `EVP_PKEY_cmp_parameters()`.
+
+ *David von Oheimb and Shane Lontis*
+
+ * Deprecated `EC_METHOD_get_field_type()`.
+
+ *Billy Bob Brumley*
+
+ * Deprecated EC_GFp_simple_method(), EC_GFp_mont_method(),
+ EC_GF2m_simple_method(), EC_GFp_nist_method(), EC_GFp_nistp224_method()
+ EC_GFp_nistp256_method(), and EC_GFp_nistp521_method().
+
+ *Billy Bob Brumley*
+
+ * Deprecated EC_GROUP_new(), EC_GROUP_method_of(), and EC_POINT_method_of().
+
+ *Billy Bob Brumley*
+
+ * Add CAdES-BES signature verification support, mostly derived
+ from ESSCertIDv2 TS (RFC 5816) contribution by Marek Klein.
+
+ *Filipe Raimundo da Silva*
+
+ * Add CAdES-BES signature scheme and attributes support (RFC 5126) to CMS API.
+
+ *Antonio Iacono*
+
+ * Added the AuthEnvelopedData content type structure (RFC 5083) with AES-GCM
+ parameter (RFC 5084) for the Cryptographic Message Syntax (CMS).
+
+ *Jakub Zelenka*
+
+ * Deprecated EC_POINT_make_affine() and EC_POINTs_make_affine().
+
+ *Billy Bob Brumley*
+
+ * Deprecated EC_GROUP_precompute_mult(), EC_GROUP_have_precompute_mult(), and
+ EC_KEY_precompute_mult().
+
+ *Billy Bob Brumley*
+
+ * Deprecated EC_POINTs_mul().
+
+ *Billy Bob Brumley*
+
+ * Removed FIPS_mode() and FIPS_mode_set().
+
+ *Shane Lontis*
+
+ * The SSL option SSL_OP_IGNORE_UNEXPECTED_EOF is introduced.
+
+ *Dmitry Belyavskiy*
+
+ * Deprecated EC_POINT_set_Jprojective_coordinates_GFp() and
+ EC_POINT_get_Jprojective_coordinates_GFp().
+
+ *Billy Bob Brumley*
+
+ * Added OSSL_PARAM_BLD to the public interface. This allows OSSL_PARAM
+ arrays to be more easily constructed via a series of utility functions.
+ Create a parameter builder using OSSL_PARAM_BLD_new(), add parameters using
+ the various push functions and finally convert to a passable OSSL_PARAM
+ array using OSSL_PARAM_BLD_to_param().
+
+ *Paul Dale*
+
+ * The security strength of SHA1 and MD5 based signatures in TLS has been
+ reduced.
+
+ *Kurt Roeckx*
+
+ * Added EVP_PKEY_set_type_by_keymgmt(), to initialise an EVP_PKEY to
+ contain a provider side internal key.
+
+ *Richard Levitte*
+
+ * ASN1_verify(), ASN1_digest() and ASN1_sign() have been deprecated.
+
+ *Richard Levitte*
+
+ * Project text documents not yet having a proper file name extension
+ (`HACKING`, `LICENSE`, `NOTES*`, `README*`, `VERSION`) have been renamed to
+ `*.md` as far as reasonable, else `*.txt`, for better use with file managers.
+
+ *David von Oheimb*
+
+ * The main project documents (README, NEWS, CHANGES, INSTALL, SUPPORT)
+ have been converted to Markdown with the goal to produce documents
+ which not only look pretty when viewed online in the browser, but
+ remain well readable inside a plain text editor.
+
+ To achieve this goal, a 'minimalistic' Markdown style has been applied
+ which avoids formatting elements that interfere too much with the
+ reading flow in the text file. For example, it
+
+ * avoids [ATX headings][] and uses [setext headings][] instead
+ (which works for `<h1>` and `<h2>` headings only).
+ * avoids [inline links][] and uses [reference links][] instead.
+ * avoids [fenced code blocks][] and uses [indented code blocks][] instead.
+
+ [ATX headings]: https://github.github.com/gfm/#atx-headings
+ [setext headings]: https://github.github.com/gfm/#setext-headings
+ [inline links]: https://github.github.com/gfm/#inline-link
+ [reference links]: https://github.github.com/gfm/#reference-link
+ [fenced code blocks]: https://github.github.com/gfm/#fenced-code-blocks
+ [indented code blocks]: https://github.github.com/gfm/#indented-code-blocks
+
+ *Matthias St. Pierre*
+
+ * The test suite is changed to preserve results of each test recipe.
+ A new directory test-runs/ with subdirectories named like the
+ test recipes are created in the build tree for this purpose.
+
+ *Richard Levitte*
+
+ * Added an implementation of CMP and CRMF (RFC 4210, RFC 4211 RFC 6712).
+ This adds `crypto/cmp/`, `crpyto/crmf/`, `apps/cmp.c`, and `test/cmp_*`.
+ See L<openssl-cmp(1)> and L<OSSL_CMP_exec_IR_ses(3)> as starting points.
+
+ *David von Oheimb, Martin Peylo*
+
+ * Generalized the HTTP client code from `crypto/ocsp/` into `crpyto/http/`.
+ It supports arbitrary request and response content types, GET redirection,
+ TLS, connections via HTTP(S) proxies, connections and exchange via
+ user-defined BIOs (allowing implicit connections), persistent connections,
+ and timeout checks. See L<OSSL_HTTP_transfer(3)> etc. for details.
+ The legacy OCSP-focused (and only partly documented) API
+ is retained for backward compatibility, while most of it is deprecated.
+
+ *David von Oheimb*
+
+ * Added `util/check-format.pl`, a tool for checking adherence to the
+ OpenSSL coding style <https://www.openssl.org/policies/codingstyle.html>.
+ The checks performed are incomplete and yield some false positives.
+ Still the tool should be useful for detecting most typical glitches.
+
+ *David von Oheimb*
+
+ * `BIO_do_connect()` and `BIO_do_handshake()` have been extended:
+ If domain name resolution yields multiple IP addresses all of them are tried
+ after `connect()` failures.
+
+ *David von Oheimb*
+
+ * All of the low level RSA functions have been deprecated.
+
+ *Paul Dale*
+
+ * X509 certificates signed using SHA1 are no longer allowed at security
+ level 1 and above.
+
+ *Kurt Roeckx*
+
+ * The command line utilities dhparam, dsa, gendsa and dsaparam have been
+ modified to use PKEY APIs. These commands are now in maintenance mode
+ and no new features will be added to them.
+
+ *Paul Dale*
+
+ * The command line utility rsautl has been deprecated.
+
+ *Paul Dale*
+
+ * The command line utilities genrsa and rsa have been modified to use PKEY
+ APIs. They now write PKCS#8 keys by default. These commands are now in
+ maintenance mode and no new features will be added to them.
+
+ *Paul Dale*
+
+ * All of the low level DH functions have been deprecated.
+
+ *Paul Dale and Matt Caswell*
+
+ * All of the low level DSA functions have been deprecated.
+
+ *Paul Dale*
+
+ * Reworked the treatment of EC EVP_PKEYs with the SM2 curve to
+ automatically become EVP_PKEY_SM2 rather than EVP_PKEY_EC.
+
+ *Richard Levitte*
+
+ * Deprecated low level ECDH and ECDSA functions.
+
+ *Paul Dale*
+
+ * Deprecated EVP_PKEY_decrypt_old() and EVP_PKEY_encrypt_old().
+
+ *Richard Levitte*
+
+ * Enhanced the documentation of EVP_PKEY_get_size(), EVP_PKEY_get_bits()
+ and EVP_PKEY_get_security_bits(). Especially EVP_PKEY_get_size() needed
+ a new formulation to include all the things it can be used for,
+ as well as words of caution.
+
+ *Richard Levitte*
+
+ * The SSL_CTX_set_tlsext_ticket_key_cb(3) function has been deprecated.
+
+ *Paul Dale*
+
+ * All of the low level HMAC functions have been deprecated.
+
+ *Paul Dale and David von Oheimb*
+
+ * Over two thousand fixes were made to the documentation, including:
+ - Common options (such as -rand/-writerand, TLS version control, etc)
+ were refactored and point to newly-enhanced descriptions in openssl.pod.
+ - Added style conformance for all options (with help from Richard Levitte),
+ documented all reported missing options, added a CI build to check
+ that all options are documented and that no unimplemented options
+ are documented.
+ - Documented some internals, such as all use of environment variables.
+ - Addressed all internal broken L<> references.
+
+ *Rich Salz*
+
+ * All of the low level CMAC functions have been deprecated.
+
+ *Paul Dale*
+
+ * The low-level MD2, MD4, MD5, MDC2, RIPEMD160 and Whirlpool digest
+ functions have been deprecated.
+
+ *Paul Dale and David von Oheimb*
+
+ * Corrected the documentation of the return values from the `EVP_DigestSign*`
+ set of functions. The documentation mentioned negative values for some
+ errors, but this was never the case, so the mention of negative values
+ was removed.
+
+ Code that followed the documentation and thereby check with something
+ like `EVP_DigestSignInit(...) <= 0` will continue to work undisturbed.
+
+ *Richard Levitte*
+
+ * All of the low level cipher functions have been deprecated.
+
+ *Matt Caswell and Paul Dale*
+
+ * Removed include/openssl/opensslconf.h.in and replaced it with
+ include/openssl/configuration.h.in, which differs in not including
+ <openssl/macros.h>. A short header include/openssl/opensslconf.h
+ was added to include both.
+
+ This allows internal hacks where one might need to modify the set
+ of configured macros, for example this if deprecated symbols are
+ still supposed to be available internally:
+
+ #include <openssl/configuration.h>
+
+ #undef OPENSSL_NO_DEPRECATED
+ #define OPENSSL_SUPPRESS_DEPRECATED
+
+ #include <openssl/macros.h>
+
+ This should not be used by applications that use the exported
+ symbols, as that will lead to linking errors.
+
+ *Richard Levitte*
+
+ * Fixed an overflow bug in the x64_64 Montgomery squaring procedure
+ used in exponentiation with 512-bit moduli. No EC algorithms are
+ affected. Analysis suggests that attacks against 2-prime RSA1024,
+ 3-prime RSA1536, and DSA1024 as a result of this defect would be very
+ difficult to perform and are not believed likely. Attacks against DH512
+ are considered just feasible. However, for an attack the target would
+ have to re-use the DH512 private key, which is not recommended anyway.
+ Also applications directly using the low-level API BN_mod_exp may be
+ affected if they use BN_FLG_CONSTTIME.
+ ([CVE-2019-1551])
+
+ *Andy Polyakov*
+
+ * Most memory-debug features have been deprecated, and the functionality
+ replaced with no-ops.
+
+ *Rich Salz*
+
+ * Added documentation for the STACK API.
+
+ *Rich Salz*
+
+ * Introduced a new method type and API, OSSL_ENCODER, to represent
+ generic encoders. These do the same sort of job that PEM writers
+ and d2i functions do, but with support for methods supplied by
+ providers, and the possibility for providers to support other
+ formats as well.
+
+ *Richard Levitte*
+
+ * Introduced a new method type and API, OSSL_DECODER, to represent
+ generic decoders. These do the same sort of job that PEM readers
+ and i2d functions do, but with support for methods supplied by
+ providers, and the possibility for providers to support other
+ formats as well.
+
+ *Richard Levitte*
+
+ * Added a .pragma directive to the syntax of configuration files, to
+ allow varying behavior in a supported and predictable manner.
+ Currently added pragma:
+
+ .pragma dollarid:on
+
+ This allows dollar signs to be a keyword character unless it's
+ followed by a opening brace or parenthesis. This is useful for
+ platforms where dollar signs are commonly used in names, such as
+ volume names and system directory names on VMS.
+
+ *Richard Levitte*
+
+ * Added functionality to create an EVP_PKEY from user data.
+
+ *Richard Levitte*
+
+ * Change the interpretation of the '--api' configuration option to
+ mean that this is a desired API compatibility level with no
+ further meaning. The previous interpretation, that this would
+ also mean to remove all deprecated symbols up to and including
+ the given version, no requires that 'no-deprecated' is also used
+ in the configuration.
+
+ When building applications, the desired API compatibility level
+ can be set with the OPENSSL_API_COMPAT macro like before. For
+ API compatibility version below 3.0, the old style numerical
+ value is valid as before, such as -DOPENSSL_API_COMPAT=0x10100000L.
+ For version 3.0 and on, the value is expected to be the decimal
+ value calculated from the major and minor version like this:
+
+ MAJOR * 10000 + MINOR * 100
+
+ Examples:
+
+ -DOPENSSL_API_COMPAT=30000 For 3.0
+ -DOPENSSL_API_COMPAT=30200 For 3.2
+
+ To hide declarations that are deprecated up to and including the
+ given API compatibility level, -DOPENSSL_NO_DEPRECATED must be
+ given when building the application as well.
+
+ *Richard Levitte*
+
+ * Added the X509_LOOKUP_METHOD called X509_LOOKUP_store, to allow
+ access to certificate and CRL stores via URIs and OSSL_STORE
+ loaders.
+
+ This adds the following functions:
+
+ - X509_LOOKUP_store()
+ - X509_STORE_load_file()
+ - X509_STORE_load_path()
+ - X509_STORE_load_store()
+ - SSL_add_store_cert_subjects_to_stack()
+ - SSL_CTX_set_default_verify_store()
+ - SSL_CTX_load_verify_file()
+ - SSL_CTX_load_verify_dir()
+ - SSL_CTX_load_verify_store()
+
+ *Richard Levitte*
+
+ * Added a new method to gather entropy on VMS, based on SYS$GET_ENTROPY.
+ The presence of this system service is determined at run-time.
+
+ *Richard Levitte*
+
+ * Added functionality to create an EVP_PKEY context based on data
+ for methods from providers. This takes an algorithm name and a
+ property query string and simply stores them, with the intent
+ that any operation that uses this context will use those strings
+ to fetch the needed methods implicitly, thereby making the port
+ of application written for pre-3.0 OpenSSL easier.
+
+ *Richard Levitte*
+
+ * The undocumented function NCONF_WIN32() has been deprecated; for
+ conversion details see the HISTORY section of doc/man5/config.pod
+
+ *Rich Salz*
+
+ * Introduced the new functions EVP_DigestSignInit_ex() and
+ EVP_DigestVerifyInit_ex(). The macros EVP_DigestSignUpdate() and
+ EVP_DigestVerifyUpdate() have been converted to functions. See the man
+ pages for further details.
+
+ *Matt Caswell*
+
+ * Over two thousand fixes were made to the documentation, including:
+ adding missing command flags, better style conformance, documentation
+ of internals, etc.
+
+ *Rich Salz, Richard Levitte*
+
+ * s390x assembly pack: add hardware-support for P-256, P-384, P-521,
+ X25519, X448, Ed25519 and Ed448.
+
+ *Patrick Steuer*
+
+ * Print all values for a PKCS#12 attribute with 'openssl pkcs12', not just
+ the first value.
+
+ *Jon Spillett*
+
+ * Deprecated the public definition of `ERR_STATE` as well as the function
+ `ERR_get_state()`. This is done in preparation of making `ERR_STATE` an
+ opaque type.
+
+ *Richard Levitte*
+
+ * Added ERR functionality to give callers access to the stored function
+ names that have replaced the older function code based functions.
+
+ New functions are ERR_peek_error_func(), ERR_peek_last_error_func(),
+ ERR_peek_error_data(), ERR_peek_last_error_data(), ERR_get_error_all(),
+ ERR_peek_error_all() and ERR_peek_last_error_all().
+
+ Deprecate ERR functions ERR_get_error_line(), ERR_get_error_line_data(),
+ ERR_peek_error_line_data(), ERR_peek_last_error_line_data() and
+ ERR_func_error_string().
+
+ *Richard Levitte*
+
+ * Extended testing to be verbose for failing tests only. The make variables
+ VERBOSE_FAILURE or VF can be used to enable this:
+
+ $ make VF=1 test # Unix
+ $ mms /macro=(VF=1) test ! OpenVMS
+ $ nmake VF=1 test # Windows
+
+ *Richard Levitte*
+
+ * Added the `-copy_extensions` option to the `x509` command for use with
+ `-req` and `-x509toreq`. When given with the `copy` or `copyall` argument,
+ all extensions in the request are copied to the certificate or vice versa.
+
+ *David von Oheimb*, *Kirill Stefanenkov <kirill_stefanenkov@rambler.ru>*
+
+ * Added the `-copy_extensions` option to the `req` command for use with
+ `-x509`. When given with the `copy` or `copyall` argument,
+ all extensions in the certification request are copied to the certificate.
+
+ *David von Oheimb*
+
+ * The `x509`, `req`, and `ca` commands now make sure that X.509v3 certificates
+ they generate are by default RFC 5280 compliant in the following sense:
+ There is a subjectKeyIdentifier extension with a hash value of the public key
+ and for not self-signed certs there is an authorityKeyIdentifier extension
+ with a keyIdentifier field or issuer information identifying the signing key.
+ This is done unless some configuration overrides the new default behavior,
+ such as `subjectKeyIdentifier = none` and `authorityKeyIdentifier = none`.
+
+ *David von Oheimb*
+
+ * Added several checks to `X509_verify_cert()` according to requirements in
+ RFC 5280 in case `X509_V_FLAG_X509_STRICT` is set
+ (which may be done by using the CLI option `-x509_strict`):
+ * The basicConstraints of CA certificates must be marked critical.
+ * CA certificates must explicitly include the keyUsage extension.
+ * If a pathlenConstraint is given the key usage keyCertSign must be allowed.
+ * The issuer name of any certificate must not be empty.
+ * The subject name of CA certs, certs with keyUsage crlSign,
+ and certs without subjectAlternativeName must not be empty.
+ * If a subjectAlternativeName extension is given it must not be empty.
+ * The signatureAlgorithm field and the cert signature must be consistent.
+ * Any given authorityKeyIdentifier and any given subjectKeyIdentifier
+ must not be marked critical.
+ * The authorityKeyIdentifier must be given for X.509v3 certs
+ unless they are self-signed.
+ * The subjectKeyIdentifier must be given for all X.509v3 CA certs.
+
+ *David von Oheimb*
+
+ * Certificate verification using `X509_verify_cert()` meanwhile rejects EC keys
+ with explicit curve parameters (specifiedCurve) as required by RFC 5480.
+
+ *Tomáš Mráz*
+
+ * For built-in EC curves, ensure an EC_GROUP built from the curve name is
+ used even when parsing explicit parameters, when loading a encoded key
+ or calling `EC_GROUP_new_from_ecpkparameters()`/
+ `EC_GROUP_new_from_ecparameters()`.
+ This prevents bypass of security hardening and performance gains,
+ especially for curves with specialized EC_METHODs.
+ By default, if a key encoded with explicit parameters is loaded and later
+ encoded, the output is still encoded with explicit parameters, even if
+ internally a "named" EC_GROUP is used for computation.
+
+ *Nicola Tuveri*
+
+ * Compute ECC cofactors if not provided during EC_GROUP construction. Before
+ this change, EC_GROUP_set_generator would accept order and/or cofactor as
+ NULL. After this change, only the cofactor parameter can be NULL. It also
+ does some minimal sanity checks on the passed order.
+ ([CVE-2019-1547])
+
+ *Billy Bob Brumley*
+
+ * Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey.
+ An attack is simple, if the first CMS_recipientInfo is valid but the
+ second CMS_recipientInfo is chosen ciphertext. If the second
+ recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct
+ encryption key will be replaced by garbage, and the message cannot be
+ decoded, but if the RSA decryption fails, the correct encryption key is
+ used and the recipient will not notice the attack.
+ As a work around for this potential attack the length of the decrypted
+ key must be equal to the cipher default key length, in case the
+ certifiate is not given and all recipientInfo are tried out.
+ The old behaviour can be re-enabled in the CMS code by setting the
+ CMS_DEBUG_DECRYPT flag.
+
+ *Bernd Edlinger*
+
+ * Early start up entropy quality from the DEVRANDOM seed source has been
+ improved for older Linux systems. The RAND subsystem will wait for
+ /dev/random to be producing output before seeding from /dev/urandom.
+ The seeded state is stored for future library initialisations using
+ a system global shared memory segment. The shared memory identifier
+ can be configured by defining OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID to
+ the desired value. The default identifier is 114.
+
+ *Paul Dale*
+
+ * Revised BN_generate_prime_ex to not avoid factors 2..17863 in p-1
+ when primes for RSA keys are computed.
+ Since we previously always generated primes == 2 (mod 3) for RSA keys,
+ the 2-prime and 3-prime RSA modules were easy to distinguish, since
+ `N = p*q = 1 (mod 3)`, but `N = p*q*r = 2 (mod 3)`. Therefore fingerprinting
+ 2-prime vs. 3-prime RSA keys was possible by computing N mod 3.
+ This avoids possible fingerprinting of newly generated RSA modules.
+
+ *Bernd Edlinger*
+
+ * Correct the extended master secret constant on EBCDIC systems. Without this
+ fix TLS connections between an EBCDIC system and a non-EBCDIC system that
+ negotiate EMS will fail. Unfortunately this also means that TLS connections
+ between EBCDIC systems with this fix, and EBCDIC systems without this
+ fix will fail if they negotiate EMS.
+
+ *Matt Caswell*
+
+ * Changed the library initialisation so that the config file is now loaded
+ by default. This was already the case for libssl. It now occurs for both
+ libcrypto and libssl. Use the OPENSSL_INIT_NO_LOAD_CONFIG option to
+ `OPENSSL_init_crypto()` to suppress automatic loading of a config file.
+
+ *Matt Caswell*
+
+ * Introduced new error raising macros, `ERR_raise()` and `ERR_raise_data()`,
+ where the former acts as a replacement for `ERR_put_error()`, and the
+ latter replaces the combination `ERR_put_error()` + `ERR_add_error_data()`.
+ `ERR_raise_data()` adds more flexibility by taking a format string and
+ an arbitrary number of arguments following it, to be processed with
+ `BIO_snprintf()`.
+
+ *Richard Levitte*
+
+ * Introduced a new function, `OSSL_PROVIDER_available()`, which can be used
+ to check if a named provider is loaded and available. When called, it
+ will also activate all fallback providers if such are still present.
+
+ *Richard Levitte*
+
+ * Enforce a minimum DH modulus size of 512 bits.
+
+ *Bernd Edlinger*
+
+ * Changed DH parameters to generate the order q subgroup instead of 2q.
+ Previously generated DH parameters are still accepted by DH_check
+ but DH_generate_key works around that by clearing bit 0 of the
+ private key for those. This avoids leaking bit 0 of the private key.
+
+ *Bernd Edlinger*
+
+ * Significantly reduce secure memory usage by the randomness pools.
+
+ *Paul Dale*
+
+ * `{CRYPTO,OPENSSL}_mem_debug_{push,pop}` are now no-ops and have been
+ deprecated.
+
+ *Rich Salz*
+
+ * A new type, EVP_KEYEXCH, has been introduced to represent key exchange
+ algorithms. An implementation of a key exchange algorithm can be obtained
+ by using the function EVP_KEYEXCH_fetch(). An EVP_KEYEXCH algorithm can be
+ used in a call to EVP_PKEY_derive_init_ex() which works in a similar way to
+ the older EVP_PKEY_derive_init() function. See the man pages for the new
+ functions for further details.
+
+ *Matt Caswell*
+
+ * The EVP_PKEY_CTX_set_dh_pad() macro has now been converted to a function.
+
+ *Matt Caswell*
+
+ * Removed the function names from error messages and deprecated the
+ xxx_F_xxx define's.
+
+ *Richard Levitte*
+
+ * Removed NextStep support and the macro OPENSSL_UNISTD
+
+ *Rich Salz*
+
+ * Removed DES_check_key. Also removed OPENSSL_IMPLEMENT_GLOBAL,
+ OPENSSL_GLOBAL_REF, OPENSSL_DECLARE_GLOBAL.
+ Also removed "export var as function" capability; we do not export
+ variables, only functions.
+
+ *Rich Salz*
+
+ * RC5_32_set_key has been changed to return an int type, with 0 indicating
+ an error and 1 indicating success. In previous versions of OpenSSL this
+ was a void type. If a key was set longer than the maximum possible this
+ would crash.
+
+ *Matt Caswell*
+
+ * Support SM2 signing and verification schemes with X509 certificate.
+
+ *Paul Yang*
+
+ * Use SHA256 as the default digest for TS query in the `ts` app.
+
+ *Tomáš Mráz*
+
+ * Change PBKDF2 to conform to SP800-132 instead of the older PKCS5 RFC2898.
+
+ *Shane Lontis*
+
+ * Default cipher lists/suites are now available via a function, the
+ #defines are deprecated.
+
+ *Todd Short*
+
+ * Add target VC-WIN32-UWP, VC-WIN64A-UWP, VC-WIN32-ARM-UWP and
+ VC-WIN64-ARM-UWP in Windows OneCore target for making building libraries
+ for Windows Store apps easier. Also, the "no-uplink" option has been added.
+
+ *Kenji Mouri*
+
+ * Join the directories crypto/x509 and crypto/x509v3
+
+ *Richard Levitte*
+
+ * Added command 'openssl kdf' that uses the EVP_KDF API.
+
+ *Shane Lontis*
+
+ * Added command 'openssl mac' that uses the EVP_MAC API.
+
+ *Shane Lontis*
+
+ * Added OPENSSL_info() to get diverse built-in OpenSSL data, such
+ as default directories. Also added the command 'openssl info'
+ for scripting purposes.
+
+ *Richard Levitte*
+
+ * The functions AES_ige_encrypt() and AES_bi_ige_encrypt() have been
+ deprecated.
+
+ *Matt Caswell*
+
+ * Add prediction resistance to the DRBG reseeding process.
+
+ *Paul Dale*
+
+ * Limit the number of blocks in a data unit for AES-XTS to 2^20 as
+ mandated by IEEE Std 1619-2018.
+
+ *Paul Dale*
+
+ * Added newline escaping functionality to a filename when using openssl dgst.
+ This output format is to replicate the output format found in the `*sum`
+ checksum programs. This aims to preserve backward compatibility.
+
+ *Matt Eaton, Richard Levitte, and Paul Dale*
+
+ * Removed the heartbeat message in DTLS feature, as it has very
+ little usage and doesn't seem to fulfill a valuable purpose.
+ The configuration option is now deprecated.
+
+ *Richard Levitte*
+
+ * Changed the output of 'openssl {digestname} < file' to display the
+ digest name in its output.
+
+ *Richard Levitte*
+
+ * Added a new generic trace API which provides support for enabling
+ instrumentation through trace output.
+
+ *Richard Levitte & Matthias St. Pierre*
+
+ * Added build tests for C++. These are generated files that only do one
+ thing, to include one public OpenSSL head file each. This tests that
+ the public header files can be usefully included in a C++ application.
+
+ This test isn't enabled by default. It can be enabled with the option
+ 'enable-buildtest-c++'.
+
+ *Richard Levitte*
+
+ * Added KB KDF (EVP_KDF_KB) to EVP_KDF.
+
+ *Robbie Harwood*
+
+ * Added SSH KDF (EVP_KDF_SSHKDF) and KRB5 KDF (EVP_KDF_KRB5KDF) to EVP_KDF.
+
+ *Simo Sorce*
+
+ * Added Single Step KDF (EVP_KDF_SS), X963 KDF, and X942 KDF to EVP_KDF.
+
+ *Shane Lontis*
+
+ * Added KMAC to EVP_MAC.
+
+ *Shane Lontis*
+
+ * Added property based algorithm implementation selection framework to
+ the core.
+
+ *Paul Dale*
+
+ * Added SCA hardening for modular field inversion in EC_GROUP through
+ a new dedicated field_inv() pointer in EC_METHOD.
+ This also addresses a leakage affecting conversions from projective
+ to affine coordinates.
+
+ *Billy Bob Brumley, Nicola Tuveri*
+
+ * Added EVP_KDF, an EVP layer KDF API, to simplify adding KDF and PRF
+ implementations. This includes an EVP_PKEY to EVP_KDF bridge for
+ those algorithms that were already supported through the EVP_PKEY API
+ (scrypt, TLS1 PRF and HKDF). The low-level KDF functions for PBKDF2
+ and scrypt are now wrappers that call EVP_KDF.
+
+ *David Makepeace*
+
+ * Build devcrypto engine as a dynamic engine.
+
+ *Eneas U de Queiroz*
+
+ * Add keyed BLAKE2 to EVP_MAC.
+
+ *Antoine Salon*
+
+ * Fix a bug in the computation of the endpoint-pair shared secret used
+ by DTLS over SCTP. This breaks interoperability with older versions
+ of OpenSSL like OpenSSL 1.1.0 and OpenSSL 1.0.2. There is a runtime
+ switch SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG (off by default) enabling
+ interoperability with such broken implementations. However, enabling
+ this switch breaks interoperability with correct implementations.
+
+ * Fix a use after free bug in d2i_X509_PUBKEY when overwriting a
+ re-used X509_PUBKEY object if the second PUBKEY is malformed.
+
+ *Bernd Edlinger*
+
+ * Move strictness check from EVP_PKEY_asn1_new() to EVP_PKEY_asn1_add0().
+
+ *Richard Levitte*
+
+ * Changed the license to the Apache License v2.0.
+
+ *Richard Levitte*
+
+ * Switch to a new version scheme using three numbers MAJOR.MINOR.PATCH.
+
+ - Major releases (indicated by incrementing the MAJOR release number)
+ may introduce incompatible API/ABI changes.
+ - Minor releases (indicated by incrementing the MINOR release number)
+ may introduce new features but retain API/ABI compatibility.
+ - Patch releases (indicated by incrementing the PATCH number)
+ are intended for bug fixes and other improvements of existing
+ features only (like improving performance or adding documentation)
+ and retain API/ABI compatibility.
+
+ *Richard Levitte*
+
+ * Add support for RFC5297 SIV mode (siv128), including AES-SIV.
+
+ *Todd Short*
+
+ * Remove the 'dist' target and add a tarball building script. The
+ 'dist' target has fallen out of use, and it shouldn't be
+ necessary to configure just to create a source distribution.
+
+ *Richard Levitte*
+
+ * Recreate the OS390-Unix config target. It no longer relies on a
+ special script like it did for OpenSSL pre-1.1.0.
+
+ *Richard Levitte*
+
+ * Instead of having the source directories listed in Configure, add
+ a 'build.info' keyword SUBDIRS to indicate what sub-directories to
+ look into.
+
+ *Richard Levitte*
+
+ * Add GMAC to EVP_MAC.
+
+ *Paul Dale*
+
+ * Ported the HMAC, CMAC and SipHash EVP_PKEY_METHODs to EVP_MAC.
+
+ *Richard Levitte*
+
+ * Added EVP_MAC, an EVP layer MAC API, to simplify adding MAC
+ implementations. This includes a generic EVP_PKEY to EVP_MAC bridge,
+ to facilitate the continued use of MACs through raw private keys in
+ functionality such as `EVP_DigestSign*` and `EVP_DigestVerify*`.
+
+ *Richard Levitte*
+
+ * Deprecate ECDH_KDF_X9_62().
+
+ *Antoine Salon*
+
+ * Added EVP_PKEY_ECDH_KDF_X9_63 and ecdh_KDF_X9_63() as replacements for
+ the EVP_PKEY_ECDH_KDF_X9_62 KDF type and ECDH_KDF_X9_62(). The old names
+ are retained for backwards compatibility.
+
+ *Antoine Salon*
+
+ * AES-XTS mode now enforces that its two keys are different to mitigate
+ the attacked described in "Efficient Instantiations of Tweakable
+ Blockciphers and Refinements to Modes OCB and PMAC" by Phillip Rogaway.
+ Details of this attack can be obtained from:
+ <http://web.cs.ucdavis.edu/%7Erogaway/papers/offsets.pdf>
+
+ *Paul Dale*
+
+ * Rename the object files, i.e. give them other names than in previous
+ versions. Their names now include the name of the final product, as
+ well as its type mnemonic (bin, lib, shlib).
+
+ *Richard Levitte*
+
+ * Added new option for 'openssl list', '-objects', which will display the
+ list of built in objects, i.e. OIDs with names.
+
+ *Richard Levitte*
+
+ * Added the options `-crl_lastupdate` and `-crl_nextupdate` to `openssl ca`,
+ allowing the `lastUpdate` and `nextUpdate` fields in the generated CRL to
+ be set explicitly.
+
+ *Chris Novakovic*
+
+ * Added support for Linux Kernel TLS data-path. The Linux Kernel data-path
+ improves application performance by removing data copies and providing
+ applications with zero-copy system calls such as sendfile and splice.
+
+ *Boris Pismenny*
+
+ * The SSL option SSL_OP_CLEANSE_PLAINTEXT is introduced.
+
+ *Martin Elshuber*
+
+ * `PKCS12_parse` now maintains the order of the parsed certificates
+ when outputting them via `*ca` (rather than reversing it).
+
+ *David von Oheimb*
+
+ * Deprecated pthread fork support methods.
+
+ *Randall S. Becker*
+
+ * Added support for FFDHE key exchange in TLS 1.3.
+
+ *Raja Ashok*
+
+ * Added a new concept for OpenSSL plugability: providers. This
+ functionality is designed to replace the ENGINE API and ENGINE
+ implementations, and to be much more dynamic, allowing provider
+ authors to introduce new algorithms among other things, as long as
+ there's an API that supports the algorithm type.
+
+ With this concept comes a new core API for interaction between
+ libcrypto and provider implementations. Public libcrypto functions
+ that want to use providers do so through this core API.
+
+ The main documentation for this core API is found in
+ doc/man7/provider.pod, doc/man7/provider-base.pod, and they in turn
+ refer to other manuals describing the API specific for supported
+ algorithm types (also called operations).
+
+ *The OpenSSL team*
+
+OpenSSL 1.1.1
+-------------
+
+### Changes between 1.1.1l and 1.1.1m [xx XXX xxxx]
+
+ * Avoid loading of a dynamic engine twice.
+
+ *Bernd Edlinger*
+
+ * Prioritise DANE TLSA issuer certs over peer certs
+
+ *Viktor Dukhovni*
+
+ * Fixed random API for MacOS prior to 10.12
+
+ These MacOS versions don't support the CommonCrypto APIs
+
+ *Lenny Primak*
+
+### Changes between 1.1.1k and 1.1.1l [24 Aug 2021]
+
+ * Fixed an SM2 Decryption Buffer Overflow.
+
+ In order to decrypt SM2 encrypted data an application is expected to
+ call the API function EVP_PKEY_decrypt(). Typically an application will
+ call this function twice. The first time, on entry, the "out" parameter
+ can be NULL and, on exit, the "outlen" parameter is populated with the
+ buffer size required to hold the decrypted plaintext. The application
+ can then allocate a sufficiently sized buffer and call EVP_PKEY_decrypt()
+ again, but this time passing a non-NULL value for the "out" parameter.
+
+ A bug in the implementation of the SM2 decryption code means that the
+ calculation of the buffer size required to hold the plaintext returned
+ by the first call to EVP_PKEY_decrypt() can be smaller than the actual
+ size required by the second call. This can lead to a buffer overflow
+ when EVP_PKEY_decrypt() is called by the application a second time with
+ a buffer that is too small.
+
+ A malicious attacker who is able present SM2 content for decryption to
+ an application could cause attacker chosen data to overflow the buffer
+ by up to a maximum of 62 bytes altering the contents of other data held
+ after the buffer, possibly changing application behaviour or causing
+ the application to crash. The location of the buffer is application
+ dependent but is typically heap allocated.
+ ([CVE-2021-3711])
+
+ *Matt Caswell*
+
+ * Fixed various read buffer overruns processing ASN.1 strings
+
+ ASN.1 strings are represented internally within OpenSSL as an ASN1_STRING
+ structure which contains a buffer holding the string data and a field
+ holding the buffer length. This contrasts with normal C strings which
+ are repesented as a buffer for the string data which is terminated
+ with a NUL (0) byte.
+
+ Although not a strict requirement, ASN.1 strings that are parsed using
+ OpenSSL's own "d2i" functions (and other similar parsing functions) as
+ well as any string whose value has been set with the ASN1_STRING_set()
+ function will additionally NUL terminate the byte array in the
+ ASN1_STRING structure.
+
+ However, it is possible for applications to directly construct valid
+ ASN1_STRING structures which do not NUL terminate the byte array by
+ directly setting the "data" and "length" fields in the ASN1_STRING
+ array. This can also happen by using the ASN1_STRING_set0() function.
+
+ Numerous OpenSSL functions that print ASN.1 data have been found to
+ assume that the ASN1_STRING byte array will be NUL terminated, even
+ though this is not guaranteed for strings that have been directly
+ constructed. Where an application requests an ASN.1 structure to be
+ printed, and where that ASN.1 structure contains ASN1_STRINGs that have
+ been directly constructed by the application without NUL terminating
+ the "data" field, then a read buffer overrun can occur.
+
+ The same thing can also occur during name constraints processing
+ of certificates (for example if a certificate has been directly
+ constructed by the application instead of loading it via the OpenSSL
+ parsing functions, and the certificate contains non NUL terminated
+ ASN1_STRING structures). It can also occur in the X509_get1_email(),
+ X509_REQ_get1_email() and X509_get1_ocsp() functions.
+
+ If a malicious actor can cause an application to directly construct an
+ ASN1_STRING and then process it through one of the affected OpenSSL
+ functions then this issue could be hit. This might result in a crash
+ (causing a Denial of Service attack). It could also result in the
+ disclosure of private memory contents (such as private keys, or
+ sensitive plaintext).
+ ([CVE-2021-3712])
+
+ *Matt Caswell*
+
+### Changes between 1.1.1j and 1.1.1k [25 Mar 2021]
+
+ * Fixed a problem with verifying a certificate chain when using the
+ X509_V_FLAG_X509_STRICT flag. This flag enables additional security checks of
+ the certificates present in a certificate chain. It is not set by default.
+
+ Starting from OpenSSL version 1.1.1h a check to disallow certificates in
+ the chain that have explicitly encoded elliptic curve parameters was added
+ as an additional strict check.
+
+ An error in the implementation of this check meant that the result of a
+ previous check to confirm that certificates in the chain are valid CA
+ certificates was overwritten. This effectively bypasses the check
+ that non-CA certificates must not be able to issue other certificates.
+
+ If a "purpose" has been configured then there is a subsequent opportunity
+ for checks that the certificate is a valid CA. All of the named "purpose"
+ values implemented in libcrypto perform this check. Therefore, where
+ a purpose is set the certificate chain will still be rejected even when the
+ strict flag has been used. A purpose is set by default in libssl client and
+ server certificate verification routines, but it can be overridden or
+ removed by an application.
+
+ In order to be affected, an application must explicitly set the
+ X509_V_FLAG_X509_STRICT verification flag and either not set a purpose
+ for the certificate verification or, in the case of TLS client or server
+ applications, override the default purpose.
+ ([CVE-2021-3450])
+
+ *Tomáš Mráz*
+
+ * Fixed an issue where an OpenSSL TLS server may crash if sent a maliciously
+ crafted renegotiation ClientHello message from a client. If a TLSv1.2
+ renegotiation ClientHello omits the signature_algorithms extension (where it
+ was present in the initial ClientHello), but includes a
+ signature_algorithms_cert extension then a NULL pointer dereference will
+ result, leading to a crash and a denial of service attack.
+
+ A server is only vulnerable if it has TLSv1.2 and renegotiation enabled
+ (which is the default configuration). OpenSSL TLS clients are not impacted by
+ this issue.
+ ([CVE-2021-3449])
+
+ *Peter Kästle and Samuel Sapalski*
+
+### Changes between 1.1.1i and 1.1.1j [16 Feb 2021]
+
+ * Fixed the X509_issuer_and_serial_hash() function. It attempts to
+ create a unique hash value based on the issuer and serial number data
+ contained within an X509 certificate. However it was failing to correctly
+ handle any errors that may occur while parsing the issuer field (which might
+ occur if the issuer field is maliciously constructed). This may subsequently
+ result in a NULL pointer deref and a crash leading to a potential denial of
+ service attack.
+ ([CVE-2021-23841])
+
+ *Matt Caswell*
+
+ * Fixed the RSA_padding_check_SSLv23() function and the RSA_SSLV23_PADDING
+ padding mode to correctly check for rollback attacks. This is considered a
+ bug in OpenSSL 1.1.1 because it does not support SSLv2. In 1.0.2 this is
+ CVE-2021-23839.
+
+ *Matt Caswell*
+
+ Fixed the EVP_CipherUpdate, EVP_EncryptUpdate and EVP_DecryptUpdate
+ functions. Previously they could overflow the output length argument in some
+ cases where the input length is close to the maximum permissable length for
+ an integer on the platform. In such cases the return value from the function
+ call would be 1 (indicating success), but the output length value would be
+ negative. This could cause applications to behave incorrectly or crash.
+ ([CVE-2021-23840])
+
+ *Matt Caswell*
+
+ * Fixed SRP_Calc_client_key so that it runs in constant time. The previous
+ implementation called BN_mod_exp without setting BN_FLG_CONSTTIME. This
+ could be exploited in a side channel attack to recover the password. Since
+ the attack is local host only this is outside of the current OpenSSL
+ threat model and therefore no CVE is assigned.
+
+ Thanks to Mohammed Sabt and Daniel De Almeida Braga for reporting this
+ issue.
+
+ *Matt Caswell*
+
+### Changes between 1.1.1h and 1.1.1i [8 Dec 2020]
+
+ * Fixed NULL pointer deref in the GENERAL_NAME_cmp function
+ This function could crash if both GENERAL_NAMEs contain an EDIPARTYNAME.
+ If an attacker can control both items being compared then this could lead
+ to a possible denial of service attack. OpenSSL itself uses the
+ GENERAL_NAME_cmp function for two purposes:
+ 1) Comparing CRL distribution point names between an available CRL and a
+ CRL distribution point embedded in an X509 certificate
+ 2) When verifying that a timestamp response token signer matches the
+ timestamp authority name (exposed via the API functions
+ TS_RESP_verify_response and TS_RESP_verify_token)
+ ([CVE-2020-1971])
+
+ *Matt Caswell*
+
+### Changes between 1.1.1g and 1.1.1h [22 Sep 2020]
+
+ * Certificates with explicit curve parameters are now disallowed in
+ verification chains if the X509_V_FLAG_X509_STRICT flag is used.
+
+ *Tomáš Mráz*
+
+ * The 'MinProtocol' and 'MaxProtocol' configuration commands now silently
+ ignore TLS protocol version bounds when configuring DTLS-based contexts, and
+ conversely, silently ignore DTLS protocol version bounds when configuring
+ TLS-based contexts. The commands can be repeated to set bounds of both
+ types. The same applies with the corresponding "min_protocol" and
+ "max_protocol" command-line switches, in case some application uses both TLS
+ and DTLS.
+
+ SSL_CTX instances that are created for a fixed protocol version (e.g.
+ TLSv1_server_method()) also silently ignore version bounds. Previously
+ attempts to apply bounds to these protocol versions would result in an
+ error. Now only the "version-flexible" SSL_CTX instances are subject to
+ limits in configuration files in command-line options.
+
+ *Viktor Dukhovni*
+
+ * Handshake now fails if Extended Master Secret extension is dropped
+ on renegotiation.
+
+ *Tomáš Mráz*
+
+ * The Oracle Developer Studio compiler will start reporting deprecated APIs
+
+### Changes between 1.1.1f and 1.1.1g [21 Apr 2020]
+
+ * Fixed segmentation fault in SSL_check_chain()
+ Server or client applications that call the SSL_check_chain() function
+ during or after a TLS 1.3 handshake may crash due to a NULL pointer
+ dereference as a result of incorrect handling of the
+ "signature_algorithms_cert" TLS extension. The crash occurs if an invalid
+ or unrecognised signature algorithm is received from the peer. This could
+ be exploited by a malicious peer in a Denial of Service attack.
+ ([CVE-2020-1967])
+
+ *Benjamin Kaduk*
+
+ * Added AES consttime code for no-asm configurations
+ an optional constant time support for AES was added
+ when building openssl for no-asm.
+ Enable with: ./config no-asm -DOPENSSL_AES_CONST_TIME
+ Disable with: ./config no-asm -DOPENSSL_NO_AES_CONST_TIME
+ At this time this feature is by default disabled.
+ It will be enabled by default in 3.0.
+
+ *Bernd Edlinger*
+
+### Changes between 1.1.1e and 1.1.1f [31 Mar 2020]
+
+ * Revert the change of EOF detection while reading in libssl to avoid
+ regressions in applications depending on the current way of reporting
+ the EOF. As the existing method is not fully accurate the change to
+ reporting the EOF via SSL_ERROR_SSL is kept on the current development
+ branch and will be present in the 3.0 release.
+
+ *Tomáš Mráz*
+
+ * Revised BN_generate_prime_ex to not avoid factors 3..17863 in p-1
+ when primes for RSA keys are computed.
+ Since we previously always generated primes == 2 (mod 3) for RSA keys,
+ the 2-prime and 3-prime RSA modules were easy to distinguish, since
+ N = p*q = 1 (mod 3), but N = p*q*r = 2 (mod 3). Therefore fingerprinting
+ 2-prime vs. 3-prime RSA keys was possible by computing N mod 3.
+ This avoids possible fingerprinting of newly generated RSA modules.
+
+ *Bernd Edlinger*
+
+### Changes between 1.1.1d and 1.1.1e [17 Mar 2020]
+
+ * Properly detect EOF while reading in libssl. Previously if we hit an EOF
+ while reading in libssl then we would report an error back to the
+ application (SSL_ERROR_SYSCALL) but errno would be 0. We now add
+ an error to the stack (which means we instead return SSL_ERROR_SSL) and
+ therefore give a hint as to what went wrong.
+
+ *Matt Caswell*
+
+ * Check that ed25519 and ed448 are allowed by the security level. Previously
+ signature algorithms not using an MD were not being checked that they were
+ allowed by the security level.
+
+ *Kurt Roeckx*
+
+ * Fixed SSL_get_servername() behaviour. The behaviour of SSL_get_servername()
+ was not quite right. The behaviour was not consistent between resumption
+ and normal handshakes, and also not quite consistent with historical
+ behaviour. The behaviour in various scenarios has been clarified and
+ it has been updated to make it match historical behaviour as closely as
+ possible.
+
+ *Matt Caswell*
+
+ * *[VMS only]* The header files that the VMS compilers include automatically,
+ `__DECC_INCLUDE_PROLOGUE.H` and `__DECC_INCLUDE_EPILOGUE.H`, use pragmas
+ that the C++ compiler doesn't understand. This is a shortcoming in the
+ compiler, but can be worked around with `__cplusplus` guards.
+
+ C++ applications that use OpenSSL libraries must be compiled using the
+ qualifier `/NAMES=(AS_IS,SHORTENED)` to be able to use all the OpenSSL
+ functions. Otherwise, only functions with symbols of less than 31
+ characters can be used, as the linker will not be able to successfully
+ resolve symbols with longer names.
+
+ *Richard Levitte*
+
+ * Added a new method to gather entropy on VMS, based on SYS$GET_ENTROPY.
+ The presence of this system service is determined at run-time.
+
+ *Richard Levitte*
+
+ * Print all values for a PKCS#12 attribute with 'openssl pkcs12', not just
+ the first value.
+
+ *Jon Spillett*
+
+### Changes between 1.1.1c and 1.1.1d [10 Sep 2019]
+
+ * Fixed a fork protection issue. OpenSSL 1.1.1 introduced a rewritten random
+ number generator (RNG). This was intended to include protection in the
+ event of a fork() system call in order to ensure that the parent and child
+ processes did not share the same RNG state. However this protection was not
+ being used in the default case.
+
+ A partial mitigation for this issue is that the output from a high
+ precision timer is mixed into the RNG state so the likelihood of a parent
+ and child process sharing state is significantly reduced.
+
+ If an application already calls OPENSSL_init_crypto() explicitly using
+ OPENSSL_INIT_ATFORK then this problem does not occur at all.
+ ([CVE-2019-1549])
+
+ *Matthias St. Pierre*
+
+ * For built-in EC curves, ensure an EC_GROUP built from the curve name is
+ used even when parsing explicit parameters, when loading a encoded key
+ or calling `EC_GROUP_new_from_ecpkparameters()`/
+ `EC_GROUP_new_from_ecparameters()`.
+ This prevents bypass of security hardening and performance gains,
+ especially for curves with specialized EC_METHODs.
+ By default, if a key encoded with explicit parameters is loaded and later
+ encoded, the output is still encoded with explicit parameters, even if
+ internally a "named" EC_GROUP is used for computation.
+
+ *Nicola Tuveri*
+
+ * Compute ECC cofactors if not provided during EC_GROUP construction. Before
+ this change, EC_GROUP_set_generator would accept order and/or cofactor as
+ NULL. After this change, only the cofactor parameter can be NULL. It also
+ does some minimal sanity checks on the passed order.
+ ([CVE-2019-1547])
+
+ *Billy Bob Brumley*
+
+ * Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey.
+ An attack is simple, if the first CMS_recipientInfo is valid but the
+ second CMS_recipientInfo is chosen ciphertext. If the second
+ recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct
+ encryption key will be replaced by garbage, and the message cannot be
+ decoded, but if the RSA decryption fails, the correct encryption key is
+ used and the recipient will not notice the attack.
+ As a work around for this potential attack the length of the decrypted
+ key must be equal to the cipher default key length, in case the
+ certifiate is not given and all recipientInfo are tried out.
+ The old behaviour can be re-enabled in the CMS code by setting the
+ CMS_DEBUG_DECRYPT flag.
+ ([CVE-2019-1563])
+
+ *Bernd Edlinger*
+
+ * Early start up entropy quality from the DEVRANDOM seed source has been
+ improved for older Linux systems. The RAND subsystem will wait for
+ /dev/random to be producing output before seeding from /dev/urandom.
+ The seeded state is stored for future library initialisations using
+ a system global shared memory segment. The shared memory identifier
+ can be configured by defining OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID to
+ the desired value. The default identifier is 114.
+
+ *Paul Dale*
+
+ * Correct the extended master secret constant on EBCDIC systems. Without this
+ fix TLS connections between an EBCDIC system and a non-EBCDIC system that
+ negotiate EMS will fail. Unfortunately this also means that TLS connections
+ between EBCDIC systems with this fix, and EBCDIC systems without this
+ fix will fail if they negotiate EMS.
+
+ *Matt Caswell*
+
+ * Use Windows installation paths in the mingw builds
+
+ Mingw isn't a POSIX environment per se, which means that Windows
+ paths should be used for installation.
+ ([CVE-2019-1552])
+
+ *Richard Levitte*
+
+ * Changed DH_check to accept parameters with order q and 2q subgroups.
+ With order 2q subgroups the bit 0 of the private key is not secret
+ but DH_generate_key works around that by clearing bit 0 of the
+ private key for those. This avoids leaking bit 0 of the private key.
+
+ *Bernd Edlinger*
+
+ * Significantly reduce secure memory usage by the randomness pools.
+
+ *Paul Dale*
+
+ * Revert the DEVRANDOM_WAIT feature for Linux systems
+
+ The DEVRANDOM_WAIT feature added a select() call to wait for the
+ /dev/random device to become readable before reading from the
+ /dev/urandom device.
+
+ It turned out that this change had negative side effects on
+ performance which were not acceptable. After some discussion it
+ was decided to revert this feature and leave it up to the OS
+ resp. the platform maintainer to ensure a proper initialization
+ during early boot time.
+
+ *Matthias St. Pierre*
+
+### Changes between 1.1.1b and 1.1.1c [28 May 2019]
+
+ * Add build tests for C++. These are generated files that only do one
+ thing, to include one public OpenSSL head file each. This tests that
+ the public header files can be usefully included in a C++ application.
+
+ This test isn't enabled by default. It can be enabled with the option
+ 'enable-buildtest-c++'.
+
+ *Richard Levitte*
+
+ * Enable SHA3 pre-hashing for ECDSA and DSA.
+
+ *Patrick Steuer*
+
+ * Change the default RSA, DSA and DH size to 2048 bit instead of 1024.
+ This changes the size when using the `genpkey` command when no size is given.
+ It fixes an omission in earlier changes that changed all RSA, DSA and DH
+ generation commands to use 2048 bits by default.
+
+ *Kurt Roeckx*
+
+ * Reorganize the manual pages to consistently have RETURN VALUES,
+ EXAMPLES, SEE ALSO and HISTORY come in that order, and adjust
+ util/fix-doc-nits accordingly.
+
+ *Paul Yang, Joshua Lock*
+
+ * Add the missing accessor EVP_PKEY_get0_engine()
+
+ *Matt Caswell*
+
+ * Have commands like `s_client` and `s_server` output the signature scheme
+ along with other cipher suite parameters when debugging.
+
+ *Lorinczy Zsigmond*
+
+ * Make OPENSSL_config() error agnostic again.
+
+ *Richard Levitte*
+
+ * Do the error handling in RSA decryption constant time.
+
+ *Bernd Edlinger*
+
+ * Prevent over long nonces in ChaCha20-Poly1305.
+
+ ChaCha20-Poly1305 is an AEAD cipher, and requires a unique nonce input
+ for every encryption operation. RFC 7539 specifies that the nonce value
+ (IV) should be 96 bits (12 bytes). OpenSSL allows a variable nonce length
+ and front pads the nonce with 0 bytes if it is less than 12
+ bytes. However it also incorrectly allows a nonce to be set of up to 16
+ bytes. In this case only the last 12 bytes are significant and any
+ additional leading bytes are ignored.
+
+ It is a requirement of using this cipher that nonce values are
+ unique. Messages encrypted using a reused nonce value are susceptible to
+ serious confidentiality and integrity attacks. If an application changes
+ the default nonce length to be longer than 12 bytes and then makes a
+ change to the leading bytes of the nonce expecting the new value to be a
+ new unique nonce then such an application could inadvertently encrypt
+ messages with a reused nonce.
+
+ Additionally the ignored bytes in a long nonce are not covered by the
+ integrity guarantee of this cipher. Any application that relies on the
+ integrity of these ignored leading bytes of a long nonce may be further
+ affected. Any OpenSSL internal use of this cipher, including in SSL/TLS,
+ is safe because no such use sets such a long nonce value. However user
+ applications that use this cipher directly and set a non-default nonce
+ length to be longer than 12 bytes may be vulnerable.
+
+ This issue was reported to OpenSSL on 16th of March 2019 by Joran Dirk
+ Greef of Ronomon.
+ ([CVE-2019-1543])
+
+ *Matt Caswell*
+
+ * Add DEVRANDOM_WAIT feature for Linux systems
+
+ On older Linux systems where the getrandom() system call is not available,
+ OpenSSL normally uses the /dev/urandom device for seeding its CSPRNG.
+ Contrary to getrandom(), the /dev/urandom device will not block during
+ early boot when the kernel CSPRNG has not been seeded yet.
+
+ To mitigate this known weakness, use select() to wait for /dev/random to
+ become readable before reading from /dev/urandom.
+
+ * Ensure that SM2 only uses SM3 as digest algorithm
+
+ *Paul Yang*
+
+### Changes between 1.1.1a and 1.1.1b [26 Feb 2019]
+
+ * Change the info callback signals for the start and end of a post-handshake
+ message exchange in TLSv1.3. In 1.1.1/1.1.1a we used SSL_CB_HANDSHAKE_START
+ and SSL_CB_HANDSHAKE_DONE. Experience has shown that many applications get
+ confused by this and assume that a TLSv1.2 renegotiation has started. This
+ can break KeyUpdate handling. Instead we no longer signal the start and end
+ of a post handshake message exchange (although the messages themselves are
+ still signalled). This could break some applications that were expecting
+ the old signals. However without this KeyUpdate is not usable for many
+ applications.
+
+ *Matt Caswell*
+
+### Changes between 1.1.1 and 1.1.1a [20 Nov 2018]
+
+ * Timing vulnerability in DSA signature generation
+
+ The OpenSSL DSA signature algorithm has been shown to be vulnerable to a
+ timing side channel attack. An attacker could use variations in the signing
+ algorithm to recover the private key.
+
+ This issue was reported to OpenSSL on 16th October 2018 by Samuel Weiser.
+ ([CVE-2018-0734])
+
+ *Paul Dale*
+
+ * Timing vulnerability in ECDSA signature generation
+
+ The OpenSSL ECDSA signature algorithm has been shown to be vulnerable to a
+ timing side channel attack. An attacker could use variations in the signing
+ algorithm to recover the private key.
+
+ This issue was reported to OpenSSL on 25th October 2018 by Samuel Weiser.
+ ([CVE-2018-0735])
+
+ *Paul Dale*
+
+ * Fixed the issue that RAND_add()/RAND_seed() silently discards random input
+ if its length exceeds 4096 bytes. The limit has been raised to a buffer size
+ of two gigabytes and the error handling improved.
+
+ This issue was reported to OpenSSL by Dr. Falko Strenzke. It has been
+ categorized as a normal bug, not a security issue, because the DRBG reseeds
+ automatically and is fully functional even without additional randomness
+ provided by the application.
+
+### Changes between 1.1.0i and 1.1.1 [11 Sep 2018]
+
+ * Add a new ClientHello callback. Provides a callback interface that gives
+ the application the ability to adjust the nascent SSL object at the
+ earliest stage of ClientHello processing, immediately after extensions have
+ been collected but before they have been processed. In particular, this
+ callback can adjust the supported TLS versions in response to the contents
+ of the ClientHello
+
+ *Benjamin Kaduk*
+
+ * Add SM2 base algorithm support.
+
+ *Jack Lloyd*
+
+ * s390x assembly pack: add (improved) hardware-support for the following
+ cryptographic primitives: sha3, shake, aes-gcm, aes-ccm, aes-ctr, aes-ofb,
+ aes-cfb/cfb8, aes-ecb.
+
+ *Patrick Steuer*
+
+ * Make EVP_PKEY_asn1_new() a bit stricter about its input. A NULL pem_str
+ parameter is no longer accepted, as it leads to a corrupt table. NULL
+ pem_str is reserved for alias entries only.
+
+ *Richard Levitte*
+
+ * Use the new ec_scalar_mul_ladder scaffold to implement a specialized ladder
+ step for prime curves. The new implementation is based on formulae from
+ differential addition-and-doubling in homogeneous projective coordinates
+ from Izu-Takagi "A fast parallel elliptic curve multiplication resistant
+ against side channel attacks" and Brier-Joye "Weierstrass Elliptic Curves
+ and Side-Channel Attacks" Eq. (8) for y-coordinate recovery, modified
+ to work in projective coordinates.
+
+ *Billy Bob Brumley, Nicola Tuveri*
+
+ * Change generating and checking of primes so that the error rate of not
+ being prime depends on the intended use based on the size of the input.
+ For larger primes this will result in more rounds of Miller-Rabin.
+ The maximal error rate for primes with more than 1080 bits is lowered
+ to 2^-128.
+
+ *Kurt Roeckx, Annie Yousar*
+
+ * Increase the number of Miller-Rabin rounds for DSA key generating to 64.
+
+ *Kurt Roeckx*
+
+ * The 'tsget' script is renamed to 'tsget.pl', to avoid confusion when
+ moving between systems, and to avoid confusion when a Windows build is
+ done with mingw vs with MSVC. For POSIX installs, there's still a
+ symlink or copy named 'tsget' to avoid that confusion as well.
+
+ *Richard Levitte*
+
+ * Revert blinding in ECDSA sign and instead make problematic addition
+ length-invariant. Switch even to fixed-length Montgomery multiplication.
+
+ *Andy Polyakov*
+
+ * Use the new ec_scalar_mul_ladder scaffold to implement a specialized ladder
+ step for binary curves. The new implementation is based on formulae from
+ differential addition-and-doubling in mixed Lopez-Dahab projective
+ coordinates, modified to independently blind the operands.
+
+ *Billy Bob Brumley, Sohaib ul Hassan, Nicola Tuveri*
+
+ * Add a scaffold to optionally enhance the Montgomery ladder implementation
+ for `ec_scalar_mul_ladder` (formerly `ec_mul_consttime`) allowing
+ EC_METHODs to implement their own specialized "ladder step", to take
+ advantage of more favorable coordinate systems or more efficient
+ differential addition-and-doubling algorithms.
+
+ *Billy Bob Brumley, Sohaib ul Hassan, Nicola Tuveri*
+
+ * Modified the random device based seed sources to keep the relevant
+ file descriptors open rather than reopening them on each access.
+ This allows such sources to operate in a chroot() jail without
+ the associated device nodes being available. This behaviour can be
+ controlled using RAND_keep_random_devices_open().
+
+ *Paul Dale*
+
+ * Numerous side-channel attack mitigations have been applied. This may have
+ performance impacts for some algorithms for the benefit of improved
+ security. Specific changes are noted in this change log by their respective
+ authors.
+
+ *Matt Caswell*
+
+ * AIX shared library support overhaul. Switch to AIX "natural" way of
+ handling shared libraries, which means collecting shared objects of
+ different versions and bitnesses in one common archive. This allows to
+ mitigate conflict between 1.0 and 1.1 side-by-side installations. It
+ doesn't affect the way 3rd party applications are linked, only how
+ multi-version installation is managed.
+
+ *Andy Polyakov*
+
+ * Make ec_group_do_inverse_ord() more robust and available to other
+ EC cryptosystems, so that irrespective of BN_FLG_CONSTTIME, SCA
+ mitigations are applied to the fallback BN_mod_inverse().
+ When using this function rather than BN_mod_inverse() directly, new
+ EC cryptosystem implementations are then safer-by-default.
+
+ *Billy Bob Brumley*
+
+ * Add coordinate blinding for EC_POINT and implement projective
+ coordinate blinding for generic prime curves as a countermeasure to
+ chosen point SCA attacks.
+
+ *Sohaib ul Hassan, Nicola Tuveri, Billy Bob Brumley*
+
+ * Add blinding to ECDSA and DSA signatures to protect against side channel
+ attacks discovered by Keegan Ryan (NCC Group).
+
+ *Matt Caswell*
+
+ * Enforce checking in the `pkeyutl` command to ensure that the input
+ length does not exceed the maximum supported digest length when performing
+ a sign, verify or verifyrecover operation.
+
+ *Matt Caswell*
+
+ * SSL_MODE_AUTO_RETRY is enabled by default. Applications that use blocking
+ I/O in combination with something like select() or poll() will hang. This
+ can be turned off again using SSL_CTX_clear_mode().
+ Many applications do not properly handle non-application data records, and
+ TLS 1.3 sends more of such records. Setting SSL_MODE_AUTO_RETRY works
+ around the problems in those applications, but can also break some.
+ It's recommended to read the manpages about SSL_read(), SSL_write(),
+ SSL_get_error(), SSL_shutdown(), SSL_CTX_set_mode() and
+ SSL_CTX_set_read_ahead() again.
+
+ *Kurt Roeckx*
+
+ * When unlocking a pass phrase protected PEM file or PKCS#8 container, we
+ now allow empty (zero character) pass phrases.
+
+ *Richard Levitte*
+
+ * Apply blinding to binary field modular inversion and remove patent
+ pending (OPENSSL_SUN_GF2M_DIV) BN_GF2m_mod_div implementation.
+
+ *Billy Bob Brumley*
+
+ * Deprecate ec2_mult.c and unify scalar multiplication code paths for
+ binary and prime elliptic curves.
+
+ *Billy Bob Brumley*
+
+ * Remove ECDSA nonce padding: EC_POINT_mul is now responsible for
+ constant time fixed point multiplication.
+
+ *Billy Bob Brumley*
+
+ * Revise elliptic curve scalar multiplication with timing attack
+ defenses: ec_wNAF_mul redirects to a constant time implementation
+ when computing fixed point and variable point multiplication (which
+ in OpenSSL are mostly used with secret scalars in keygen, sign,
+ ECDH derive operations).
+ *Billy Bob Brumley, Nicola Tuveri, Cesar Pereida García,
+ Sohaib ul Hassan*
+
+ * Updated CONTRIBUTING
+
+ *Rich Salz*
+
+ * Updated DRBG / RAND to request nonce and additional low entropy
+ randomness from the system.
+
+ *Matthias St. Pierre*
+
+ * Updated 'openssl rehash' to use OpenSSL consistent default.
+
+ *Richard Levitte*
+
+ * Moved the load of the ssl_conf module to libcrypto, which helps
+ loading engines that libssl uses before libssl is initialised.
+
+ *Matt Caswell*
+
+ * Added EVP_PKEY_sign() and EVP_PKEY_verify() for EdDSA
+
+ *Matt Caswell*
+
+ * Fixed X509_NAME_ENTRY_set to get multi-valued RDNs right in all cases.
+
+ *Ingo Schwarze, Rich Salz*
+
+ * Added output of accepting IP address and port for 'openssl s_server'
+
+ *Richard Levitte*
+
+ * Added a new API for TLSv1.3 ciphersuites:
+ SSL_CTX_set_ciphersuites()
+ SSL_set_ciphersuites()
+
+ *Matt Caswell*
+
+ * Memory allocation failures consistently add an error to the error
+ stack.
+
+ *Rich Salz*
+
+ * Don't use OPENSSL_ENGINES and OPENSSL_CONF environment values
+ in libcrypto when run as setuid/setgid.
+
+ *Bernd Edlinger*
+
+ * Load any config file by default when libssl is used.
+
+ *Matt Caswell*
+
+ * Added new public header file <openssl/rand_drbg.h> and documentation
+ for the RAND_DRBG API. See manual page RAND_DRBG(7) for an overview.
+
+ *Matthias St. Pierre*
+
+ * QNX support removed (cannot find contributors to get their approval
+ for the license change).
+
+ *Rich Salz*
+
+ * TLSv1.3 replay protection for early data has been implemented. See the
+ SSL_read_early_data() man page for further details.
+
+ *Matt Caswell*
+
+ * Separated TLSv1.3 ciphersuite configuration out from TLSv1.2 ciphersuite
+ configuration. TLSv1.3 ciphersuites are not compatible with TLSv1.2 and
+ below. Similarly TLSv1.2 ciphersuites are not compatible with TLSv1.3.
+ In order to avoid issues where legacy TLSv1.2 ciphersuite configuration
+ would otherwise inadvertently disable all TLSv1.3 ciphersuites the
+ configuration has been separated out. See the ciphers man page or the
+ SSL_CTX_set_ciphersuites() man page for more information.
+
+ *Matt Caswell*
+
+ * On POSIX (BSD, Linux, ...) systems the ocsp(1) command running
+ in responder mode now supports the new "-multi" option, which
+ spawns the specified number of child processes to handle OCSP
+ requests. The "-timeout" option now also limits the OCSP
+ responder's patience to wait to receive the full client request
+ on a newly accepted connection. Child processes are respawned
+ as needed, and the CA index file is automatically reloaded
+ when changed. This makes it possible to run the "ocsp" responder
+ as a long-running service, making the OpenSSL CA somewhat more
+ feature-complete. In this mode, most diagnostic messages logged
+ after entering the event loop are logged via syslog(3) rather than
+ written to stderr.
+
+ *Viktor Dukhovni*
+
+ * Added support for X448 and Ed448. Heavily based on original work by
+ Mike Hamburg.
+
+ *Matt Caswell*
+
+ * Extend OSSL_STORE with capabilities to search and to narrow the set of
+ objects loaded. This adds the functions OSSL_STORE_expect() and
+ OSSL_STORE_find() as well as needed tools to construct searches and
+ get the search data out of them.
+
+ *Richard Levitte*
+
+ * Support for TLSv1.3 added. Note that users upgrading from an earlier
+ version of OpenSSL should review their configuration settings to ensure
+ that they are still appropriate for TLSv1.3. For further information see:
+ <https://wiki.openssl.org/index.php/TLS1.3>
+
+ *Matt Caswell*
+
+ * Grand redesign of the OpenSSL random generator
+
+ The default RAND method now utilizes an AES-CTR DRBG according to
+ NIST standard SP 800-90Ar1. The new random generator is essentially
+ a port of the default random generator from the OpenSSL FIPS 2.0
+ object module. It is a hybrid deterministic random bit generator
+ using an AES-CTR bit stream and which seeds and reseeds itself
+ automatically using trusted system entropy sources.
+
+ Some of its new features are:
+ - Support for multiple DRBG instances with seed chaining.
+ - The default RAND method makes use of a DRBG.
+ - There is a public and private DRBG instance.
+ - The DRBG instances are fork-safe.
+ - Keep all global DRBG instances on the secure heap if it is enabled.
+ - The public and private DRBG instance are per thread for lock free
+ operation
+
+ *Paul Dale, Benjamin Kaduk, Kurt Roeckx, Rich Salz, Matthias St. Pierre*
+
+ * Changed Configure so it only says what it does and doesn't dump
+ so much data. Instead, ./configdata.pm should be used as a script
+ to display all sorts of configuration data.
+
+ *Richard Levitte*
+
+ * Added processing of "make variables" to Configure.
+
+ *Richard Levitte*
+
+ * Added SHA512/224 and SHA512/256 algorithm support.
+
+ *Paul Dale*
+
+ * The last traces of Netware support, first removed in 1.1.0, have
+ now been removed.
+
+ *Rich Salz*
+
+ * Get rid of Makefile.shared, and in the process, make the processing
+ of certain files (rc.obj, or the .def/.map/.opt files produced from
+ the ordinal files) more visible and hopefully easier to trace and
+ debug (or make silent).
+
+ *Richard Levitte*
+
+ * Make it possible to have environment variable assignments as
+ arguments to config / Configure.
+
+ *Richard Levitte*
+
+ * Add multi-prime RSA (RFC 8017) support.
+
+ *Paul Yang*
+
+ * Add SM3 implemented according to GB/T 32905-2016
+ *Jack Lloyd <jack.lloyd@ribose.com>,*
+ *Ronald Tse <ronald.tse@ribose.com>,*
+ *Erick Borsboom <erick.borsboom@ribose.com>*
+
+ * Add 'Maximum Fragment Length' TLS extension negotiation and support
+ as documented in RFC6066.
+ Based on a patch from Tomasz Moń
+
+ *Filipe Raimundo da Silva*
+
+ * Add SM4 implemented according to GB/T 32907-2016.
+ *Jack Lloyd <jack.lloyd@ribose.com>,*
+ *Ronald Tse <ronald.tse@ribose.com>,*
+ *Erick Borsboom <erick.borsboom@ribose.com>*
+
+ * Reimplement -newreq-nodes and ERR_error_string_n; the
+ original author does not agree with the license change.
+
+ *Rich Salz*
+
+ * Add ARIA AEAD TLS support.
+
+ *Jon Spillett*
+
+ * Some macro definitions to support VS6 have been removed. Visual
+ Studio 6 has not worked since 1.1.0
+
+ *Rich Salz*
+
+ * Add ERR_clear_last_mark(), to allow callers to clear the last mark
+ without clearing the errors.
+
+ *Richard Levitte*
+
+ * Add "atfork" functions. If building on a system that without
+ pthreads, see doc/man3/OPENSSL_fork_prepare.pod for application
+ requirements. The RAND facility now uses/requires this.
+
+ *Rich Salz*
+
+ * Add SHA3.
+
+ *Andy Polyakov*
+
+ * The UI API becomes a permanent and integral part of libcrypto, i.e.
+ not possible to disable entirely. However, it's still possible to
+ disable the console reading UI method, UI_OpenSSL() (use UI_null()
+ as a fallback).
+
+ To disable, configure with 'no-ui-console'. 'no-ui' is still
+ possible to use as an alias. Check at compile time with the
+ macro OPENSSL_NO_UI_CONSOLE. The macro OPENSSL_NO_UI is still
+ possible to check and is an alias for OPENSSL_NO_UI_CONSOLE.
+
+ *Richard Levitte*
+
+ * Add a STORE module, which implements a uniform and URI based reader of
+ stores that can contain keys, certificates, CRLs and numerous other
+ objects. The main API is loosely based on a few stdio functions,
+ and includes OSSL_STORE_open, OSSL_STORE_load, OSSL_STORE_eof,
+ OSSL_STORE_error and OSSL_STORE_close.
+ The implementation uses backends called "loaders" to implement arbitrary
+ URI schemes. There is one built in "loader" for the 'file' scheme.
+
+ *Richard Levitte*
+
+ * Add devcrypto engine. This has been implemented against cryptodev-linux,
+ then adjusted to work on FreeBSD 8.4 as well.
+ Enable by configuring with 'enable-devcryptoeng'. This is done by default
+ on BSD implementations, as cryptodev.h is assumed to exist on all of them.
+
+ *Richard Levitte*
+
+ * Module names can prefixed with OSSL_ or OPENSSL_. This affects
+ util/mkerr.pl, which is adapted to allow those prefixes, leading to
+ error code calls like this:
+
+ OSSL_FOOerr(OSSL_FOO_F_SOMETHING, OSSL_FOO_R_WHATEVER);
+
+ With this change, we claim the namespaces OSSL and OPENSSL in a manner
+ that can be encoded in C. For the foreseeable future, this will only
+ affect new modules.
+
+ *Richard Levitte and Tim Hudson*
+
+ * Removed BSD cryptodev engine.
+
+ *Rich Salz*
+
+ * Add a build target 'build_all_generated', to build all generated files
+ and only that. This can be used to prepare everything that requires
+ things like perl for a system that lacks perl and then move everything
+ to that system and do the rest of the build there.
+
+ *Richard Levitte*
+
+ * In the UI interface, make it possible to duplicate the user data. This
+ can be used by engines that need to retain the data for a longer time
+ than just the call where this user data is passed.
+
+ *Richard Levitte*
+
+ * Ignore the '-named_curve auto' value for compatibility of applications
+ with OpenSSL 1.0.2.
+
+ *Tomáš Mráz <tmraz@fedoraproject.org>*
+
+ * Fragmented SSL/TLS alerts are no longer accepted. An alert message is 2
+ bytes long. In theory it is permissible in SSLv3 - TLSv1.2 to fragment such
+ alerts across multiple records (some of which could be empty). In practice
+ it make no sense to send an empty alert record, or to fragment one. TLSv1.3
+ prohibits this altogether and other libraries (BoringSSL, NSS) do not
+ support this at all. Supporting it adds significant complexity to the
+ record layer, and its removal is unlikely to cause interoperability
+ issues.
+
+ *Matt Caswell*
+
+ * Add the ASN.1 types INT32, UINT32, INT64, UINT64 and variants prefixed
+ with Z. These are meant to replace LONG and ZLONG and to be size safe.
+ The use of LONG and ZLONG is discouraged and scheduled for deprecation
+ in OpenSSL 1.2.0.
+
+ *Richard Levitte*
+
+ * Add the 'z' and 'j' modifiers to BIO_printf() et al formatting string,
+ 'z' is to be used for [s]size_t, and 'j' - with [u]int64_t.
+
+ *Richard Levitte, Andy Polyakov*
+
+ * Add EC_KEY_get0_engine(), which does for EC_KEY what RSA_get0_engine()
+ does for RSA, etc.
+
+ *Richard Levitte*
+
+ * Have 'config' recognise 64-bit mingw and choose 'mingw64' as the target
+ platform rather than 'mingw'.
+
+ *Richard Levitte*
+
+ * The functions X509_STORE_add_cert and X509_STORE_add_crl return
+ success if they are asked to add an object which already exists
+ in the store. This change cascades to other functions which load
+ certificates and CRLs.
+
+ *Paul Dale*
+
+ * x86_64 assembly pack: annotate code with DWARF CFI directives to
+ facilitate stack unwinding even from assembly subroutines.
+
+ *Andy Polyakov*
+
+ * Remove VAX C specific definitions of OPENSSL_EXPORT, OPENSSL_EXTERN.
+ Also remove OPENSSL_GLOBAL entirely, as it became a no-op.
+
+ *Richard Levitte*
+
+ * Remove the VMS-specific reimplementation of gmtime from crypto/o_times.c.
+ VMS C's RTL has a fully up to date gmtime() and gmtime_r() since V7.1,
+ which is the minimum version we support.
+
+ *Richard Levitte*
+
+ * Certificate time validation (X509_cmp_time) enforces stricter
+ compliance with RFC 5280. Fractional seconds and timezone offsets
+ are no longer allowed.
+
+ *Emilia Käsper*
+
+ * Add support for ARIA
+
+ *Paul Dale*
+
+ * s_client will now send the Server Name Indication (SNI) extension by
+ default unless the new "-noservername" option is used. The server name is
+ based on the host provided to the "-connect" option unless overridden by
+ using "-servername".
+
+ *Matt Caswell*
+
+ * Add support for SipHash
+
+ *Todd Short*
+
+ * OpenSSL now fails if it receives an unrecognised record type in TLS1.0
+ or TLS1.1. Previously this only happened in SSLv3 and TLS1.2. This is to
+ prevent issues where no progress is being made and the peer continually
+ sends unrecognised record types, using up resources processing them.
+
+ *Matt Caswell*
+
+ * 'openssl passwd' can now produce SHA256 and SHA512 based output,
+ using the algorithm defined in
+ <https://www.akkadia.org/drepper/SHA-crypt.txt>
+
+ *Richard Levitte*
+
+ * Heartbeat support has been removed; the ABI is changed for now.
+
+ *Richard Levitte, Rich Salz*
+
+ * Support for SSL_OP_NO_ENCRYPT_THEN_MAC in SSL_CONF_cmd.
+
+ *Emilia Käsper*
+
+ * The RSA "null" method, which was partially supported to avoid patent
+ issues, has been replaced to always returns NULL.
+
+ *Rich Salz*
+
+OpenSSL 1.1.0
+-------------
+
+### Changes between 1.1.0k and 1.1.0l [10 Sep 2019]
+
+ * For built-in EC curves, ensure an EC_GROUP built from the curve name is
+ used even when parsing explicit parameters, when loading a encoded key
+ or calling `EC_GROUP_new_from_ecpkparameters()`/
+ `EC_GROUP_new_from_ecparameters()`.
+ This prevents bypass of security hardening and performance gains,
+ especially for curves with specialized EC_METHODs.
+ By default, if a key encoded with explicit parameters is loaded and later
+ encoded, the output is still encoded with explicit parameters, even if
+ internally a "named" EC_GROUP is used for computation.
+
+ *Nicola Tuveri*
+
+ * Compute ECC cofactors if not provided during EC_GROUP construction. Before
+ this change, EC_GROUP_set_generator would accept order and/or cofactor as
+ NULL. After this change, only the cofactor parameter can be NULL. It also
+ does some minimal sanity checks on the passed order.
+ ([CVE-2019-1547])
+
+ *Billy Bob Brumley*
+
+ * Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey.
+ An attack is simple, if the first CMS_recipientInfo is valid but the
+ second CMS_recipientInfo is chosen ciphertext. If the second
+ recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct
+ encryption key will be replaced by garbage, and the message cannot be
+ decoded, but if the RSA decryption fails, the correct encryption key is
+ used and the recipient will not notice the attack.
+ As a work around for this potential attack the length of the decrypted
+ key must be equal to the cipher default key length, in case the
+ certifiate is not given and all recipientInfo are tried out.
+ The old behaviour can be re-enabled in the CMS code by setting the
+ CMS_DEBUG_DECRYPT flag.
+ ([CVE-2019-1563])
+
+ *Bernd Edlinger*
+
+ * Use Windows installation paths in the mingw builds
+
+ Mingw isn't a POSIX environment per se, which means that Windows
+ paths should be used for installation.
+ ([CVE-2019-1552])
+
+ *Richard Levitte*
+
+### Changes between 1.1.0j and 1.1.0k [28 May 2019]
+
+ * Change the default RSA, DSA and DH size to 2048 bit instead of 1024.
+ This changes the size when using the `genpkey` command when no size is given.
+ It fixes an omission in earlier changes that changed all RSA, DSA and DH
+ generation commands to use 2048 bits by default.
+
+ *Kurt Roeckx*
+
+ * Prevent over long nonces in ChaCha20-Poly1305.
+
+ ChaCha20-Poly1305 is an AEAD cipher, and requires a unique nonce input
+ for every encryption operation. RFC 7539 specifies that the nonce value
+ (IV) should be 96 bits (12 bytes). OpenSSL allows a variable nonce length
+ and front pads the nonce with 0 bytes if it is less than 12
+ bytes. However it also incorrectly allows a nonce to be set of up to 16
+ bytes. In this case only the last 12 bytes are significant and any
+ additional leading bytes are ignored.
+
+ It is a requirement of using this cipher that nonce values are
+ unique. Messages encrypted using a reused nonce value are susceptible to
+ serious confidentiality and integrity attacks. If an application changes
+ the default nonce length to be longer than 12 bytes and then makes a
+ change to the leading bytes of the nonce expecting the new value to be a
+ new unique nonce then such an application could inadvertently encrypt
+ messages with a reused nonce.
+
+ Additionally the ignored bytes in a long nonce are not covered by the
+ integrity guarantee of this cipher. Any application that relies on the
+ integrity of these ignored leading bytes of a long nonce may be further
+ affected. Any OpenSSL internal use of this cipher, including in SSL/TLS,
+ is safe because no such use sets such a long nonce value. However user
+ applications that use this cipher directly and set a non-default nonce
+ length to be longer than 12 bytes may be vulnerable.
+
+ This issue was reported to OpenSSL on 16th of March 2019 by Joran Dirk
+ Greef of Ronomon.
+ ([CVE-2019-1543])
+
+ *Matt Caswell*
+
+ * Added SCA hardening for modular field inversion in EC_GROUP through
+ a new dedicated field_inv() pointer in EC_METHOD.
+ This also addresses a leakage affecting conversions from projective
+ to affine coordinates.
+
+ *Billy Bob Brumley, Nicola Tuveri*
+
+ * Fix a use after free bug in d2i_X509_PUBKEY when overwriting a
+ re-used X509_PUBKEY object if the second PUBKEY is malformed.
+
+ *Bernd Edlinger*
+
+ * Move strictness check from EVP_PKEY_asn1_new() to EVP_PKEY_asn1_add0().
+
+ *Richard Levitte*
+
+ * Remove the 'dist' target and add a tarball building script. The
+ 'dist' target has fallen out of use, and it shouldn't be
+ necessary to configure just to create a source distribution.
+
+ *Richard Levitte*
+
+### Changes between 1.1.0i and 1.1.0j [20 Nov 2018]
+
+ * Timing vulnerability in DSA signature generation
+
+ The OpenSSL DSA signature algorithm has been shown to be vulnerable to a
+ timing side channel attack. An attacker could use variations in the signing
+ algorithm to recover the private key.
+
+ This issue was reported to OpenSSL on 16th October 2018 by Samuel Weiser.
+ ([CVE-2018-0734])
+
+ *Paul Dale*
+
+ * Timing vulnerability in ECDSA signature generation
+
+ The OpenSSL ECDSA signature algorithm has been shown to be vulnerable to a
+ timing side channel attack. An attacker could use variations in the signing
+ algorithm to recover the private key.
+
+ This issue was reported to OpenSSL on 25th October 2018 by Samuel Weiser.
+ ([CVE-2018-0735])
+
+ *Paul Dale*
+
+ * Add coordinate blinding for EC_POINT and implement projective
+ coordinate blinding for generic prime curves as a countermeasure to
+ chosen point SCA attacks.
+
+ *Sohaib ul Hassan, Nicola Tuveri, Billy Bob Brumley*
+
+### Changes between 1.1.0h and 1.1.0i [14 Aug 2018]
+
+ * Client DoS due to large DH parameter
+
+ During key agreement in a TLS handshake using a DH(E) based ciphersuite a
+ malicious server can send a very large prime value to the client. This will
+ cause the client to spend an unreasonably long period of time generating a
+ key for this prime resulting in a hang until the client has finished. This
+ could be exploited in a Denial Of Service attack.
+
+ This issue was reported to OpenSSL on 5th June 2018 by Guido Vranken
+ ([CVE-2018-0732])
+
+ *Guido Vranken*
+
+ * Cache timing vulnerability in RSA Key Generation
+
+ The OpenSSL RSA Key generation algorithm has been shown to be vulnerable to
+ a cache timing side channel attack. An attacker with sufficient access to
+ mount cache timing attacks during the RSA key generation process could
+ recover the private key.
+
+ This issue was reported to OpenSSL on 4th April 2018 by Alejandro Cabrera
+ Aldaya, Billy Brumley, Cesar Pereida Garcia and Luis Manuel Alvarez Tapia.
+ ([CVE-2018-0737])
+
+ *Billy Brumley*
+
+ * Make EVP_PKEY_asn1_new() a bit stricter about its input. A NULL pem_str
+ parameter is no longer accepted, as it leads to a corrupt table. NULL
+ pem_str is reserved for alias entries only.
+
+ *Richard Levitte*
+
+ * Revert blinding in ECDSA sign and instead make problematic addition
+ length-invariant. Switch even to fixed-length Montgomery multiplication.
+
+ *Andy Polyakov*
+
+ * Change generating and checking of primes so that the error rate of not
+ being prime depends on the intended use based on the size of the input.
+ For larger primes this will result in more rounds of Miller-Rabin.
+ The maximal error rate for primes with more than 1080 bits is lowered
+ to 2^-128.
+
+ *Kurt Roeckx, Annie Yousar*
+
+ * Increase the number of Miller-Rabin rounds for DSA key generating to 64.
+
+ *Kurt Roeckx*
+
+ * Add blinding to ECDSA and DSA signatures to protect against side channel
+ attacks discovered by Keegan Ryan (NCC Group).
+
+ *Matt Caswell*
+
+ * When unlocking a pass phrase protected PEM file or PKCS#8 container, we
+ now allow empty (zero character) pass phrases.
+
+ *Richard Levitte*
+
+ * Certificate time validation (X509_cmp_time) enforces stricter
+ compliance with RFC 5280. Fractional seconds and timezone offsets
+ are no longer allowed.
+
+ *Emilia Käsper*
+
+ * Fixed a text canonicalisation bug in CMS
+
+ Where a CMS detached signature is used with text content the text goes
+ through a canonicalisation process first prior to signing or verifying a
+ signature. This process strips trailing space at the end of lines, converts
+ line terminators to CRLF and removes additional trailing line terminators
+ at the end of a file. A bug in the canonicalisation process meant that
+ some characters, such as form-feed, were incorrectly treated as whitespace
+ and removed. This is contrary to the specification (RFC5485). This fix
+ could mean that detached text data signed with an earlier version of
+ OpenSSL 1.1.0 may fail to verify using the fixed version, or text data
+ signed with a fixed OpenSSL may fail to verify with an earlier version of
+ OpenSSL 1.1.0. A workaround is to only verify the canonicalised text data
+ and use the "-binary" flag (for the "cms" command line application) or set
+ the SMIME_BINARY/PKCS7_BINARY/CMS_BINARY flags (if using CMS_verify()).
+
+ *Matt Caswell*
+
+### Changes between 1.1.0g and 1.1.0h [27 Mar 2018]
+
+ * Constructed ASN.1 types with a recursive definition could exceed the stack
+
+ Constructed ASN.1 types with a recursive definition (such as can be found
+ in PKCS7) could eventually exceed the stack given malicious input with
+ excessive recursion. This could result in a Denial Of Service attack. There
+ are no such structures used within SSL/TLS that come from untrusted sources
+ so this is considered safe.
+
+ This issue was reported to OpenSSL on 4th January 2018 by the OSS-fuzz
+ project.
+ ([CVE-2018-0739])
+
+ *Matt Caswell*
+
+ * Incorrect CRYPTO_memcmp on HP-UX PA-RISC
+
+ Because of an implementation bug the PA-RISC CRYPTO_memcmp function is
+ effectively reduced to only comparing the least significant bit of each
+ byte. This allows an attacker to forge messages that would be considered as
+ authenticated in an amount of tries lower than that guaranteed by the
+ security claims of the scheme. The module can only be compiled by the
+ HP-UX assembler, so that only HP-UX PA-RISC targets are affected.
+
+ This issue was reported to OpenSSL on 2nd March 2018 by Peter Waltenberg
+ (IBM).
+ ([CVE-2018-0733])
+
+ *Andy Polyakov*
+
+ * Add a build target 'build_all_generated', to build all generated files
+ and only that. This can be used to prepare everything that requires
+ things like perl for a system that lacks perl and then move everything
+ to that system and do the rest of the build there.
+
+ *Richard Levitte*
+
+ * Backport SSL_OP_NO_RENGOTIATION
+
+ OpenSSL 1.0.2 and below had the ability to disable renegotiation using the
+ (undocumented) SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS flag. Due to the opacity
+ changes this is no longer possible in 1.1.0. Therefore the new
+ SSL_OP_NO_RENEGOTIATION option from 1.1.1-dev has been backported to
+ 1.1.0 to provide equivalent functionality.
+
+ Note that if an application built against 1.1.0h headers (or above) is run
+ using an older version of 1.1.0 (prior to 1.1.0h) then the option will be
+ accepted but nothing will happen, i.e. renegotiation will not be prevented.
+
+ *Matt Caswell*
+
+ * Removed the OS390-Unix config target. It relied on a script that doesn't
+ exist.
+
+ *Rich Salz*
+
+ * rsaz_1024_mul_avx2 overflow bug on x86_64
+
+ There is an overflow bug in the AVX2 Montgomery multiplication procedure
+ used in exponentiation with 1024-bit moduli. No EC algorithms are affected.
+ Analysis suggests that attacks against RSA and DSA as a result of this
+ defect would be very difficult to perform and are not believed likely.
+ Attacks against DH1024 are considered just feasible, because most of the
+ work necessary to deduce information about a private key may be performed
+ offline. The amount of resources required for such an attack would be
+ significant. However, for an attack on TLS to be meaningful, the server
+ would have to share the DH1024 private key among multiple clients, which is
+ no longer an option since CVE-2016-0701.
+
+ This only affects processors that support the AVX2 but not ADX extensions
+ like Intel Haswell (4th generation).
+
+ This issue was reported to OpenSSL by David Benjamin (Google). The issue
+ was originally found via the OSS-Fuzz project.
+ ([CVE-2017-3738])
+
+ *Andy Polyakov*
+
+### Changes between 1.1.0f and 1.1.0g [2 Nov 2017]
+
+ * bn_sqrx8x_internal carry bug on x86_64
+
+ There is a carry propagating bug in the x86_64 Montgomery squaring
+ procedure. No EC algorithms are affected. Analysis suggests that attacks
+ against RSA and DSA as a result of this defect would be very difficult to
+ perform and are not believed likely. Attacks against DH are considered just
+ feasible (although very difficult) because most of the work necessary to
+ deduce information about a private key may be performed offline. The amount
+ of resources required for such an attack would be very significant and
+ likely only accessible to a limited number of attackers. An attacker would
+ additionally need online access to an unpatched system using the target
+ private key in a scenario with persistent DH parameters and a private
+ key that is shared between multiple clients.
+
+ This only affects processors that support the BMI1, BMI2 and ADX extensions
+ like Intel Broadwell (5th generation) and later or AMD Ryzen.
+
+ This issue was reported to OpenSSL by the OSS-Fuzz project.
+ ([CVE-2017-3736])
+
+ *Andy Polyakov*
+
+ * Malformed X.509 IPAddressFamily could cause OOB read
+
+ If an X.509 certificate has a malformed IPAddressFamily extension,
+ OpenSSL could do a one-byte buffer overread. The most likely result
+ would be an erroneous display of the certificate in text format.
+
+ This issue was reported to OpenSSL by the OSS-Fuzz project.
+ ([CVE-2017-3735])
+
+ *Rich Salz*
+
+### Changes between 1.1.0e and 1.1.0f [25 May 2017]
+
+ * Have 'config' recognise 64-bit mingw and choose 'mingw64' as the target
+ platform rather than 'mingw'.
+
+ *Richard Levitte*
+
+ * Remove the VMS-specific reimplementation of gmtime from crypto/o_times.c.
+ VMS C's RTL has a fully up to date gmtime() and gmtime_r() since V7.1,
+ which is the minimum version we support.
+
+ *Richard Levitte*
+
+### Changes between 1.1.0d and 1.1.0e [16 Feb 2017]
+
+ * Encrypt-Then-Mac renegotiation crash
+
+ During a renegotiation handshake if the Encrypt-Then-Mac extension is
+ negotiated where it was not in the original handshake (or vice-versa) then
+ this can cause OpenSSL to crash (dependant on ciphersuite). Both clients
+ and servers are affected.
+
+ This issue was reported to OpenSSL by Joe Orton (Red Hat).
+ ([CVE-2017-3733])
+
+ *Matt Caswell*
+
+### Changes between 1.1.0c and 1.1.0d [26 Jan 2017]
+
+ * Truncated packet could crash via OOB read
+
+ If one side of an SSL/TLS path is running on a 32-bit host and a specific
+ cipher is being used, then a truncated packet can cause that host to
+ perform an out-of-bounds read, usually resulting in a crash.
+
+ This issue was reported to OpenSSL by Robert Święcki of Google.
+ ([CVE-2017-3731])
+
+ *Andy Polyakov*
+
+ * Bad (EC)DHE parameters cause a client crash
+
+ If a malicious server supplies bad parameters for a DHE or ECDHE key
+ exchange then this can result in the client attempting to dereference a
+ NULL pointer leading to a client crash. This could be exploited in a Denial
+ of Service attack.
+
+ This issue was reported to OpenSSL by Guido Vranken.
+ ([CVE-2017-3730])
+
+ *Matt Caswell*
+
+ * BN_mod_exp may produce incorrect results on x86_64
+
+ There is a carry propagating bug in the x86_64 Montgomery squaring
+ procedure. No EC algorithms are affected. Analysis suggests that attacks
+ against RSA and DSA as a result of this defect would be very difficult to
+ perform and are not believed likely. Attacks against DH are considered just
+ feasible (although very difficult) because most of the work necessary to
+ deduce information about a private key may be performed offline. The amount
+ of resources required for such an attack would be very significant and
+ likely only accessible to a limited number of attackers. An attacker would
+ additionally need online access to an unpatched system using the target
+ private key in a scenario with persistent DH parameters and a private
+ key that is shared between multiple clients. For example this can occur by
+ default in OpenSSL DHE based SSL/TLS ciphersuites. Note: This issue is very
+ similar to CVE-2015-3193 but must be treated as a separate problem.
+
+ This issue was reported to OpenSSL by the OSS-Fuzz project.
+ ([CVE-2017-3732])
+
+ *Andy Polyakov*
+
+### Changes between 1.1.0b and 1.1.0c [10 Nov 2016]
+
+ * ChaCha20/Poly1305 heap-buffer-overflow
+
+ TLS connections using `*-CHACHA20-POLY1305` ciphersuites are susceptible to
+ a DoS attack by corrupting larger payloads. This can result in an OpenSSL
+ crash. This issue is not considered to be exploitable beyond a DoS.
+
+ This issue was reported to OpenSSL by Robert Święcki (Google Security Team)
+ ([CVE-2016-7054])
+
+ *Richard Levitte*
+
+ * CMS Null dereference
+
+ Applications parsing invalid CMS structures can crash with a NULL pointer
+ dereference. This is caused by a bug in the handling of the ASN.1 CHOICE
+ type in OpenSSL 1.1.0 which can result in a NULL value being passed to the
+ structure callback if an attempt is made to free certain invalid encodings.
+ Only CHOICE structures using a callback which do not handle NULL value are
+ affected.
+
+ This issue was reported to OpenSSL by Tyler Nighswander of ForAllSecure.
+ ([CVE-2016-7053])
+
+ *Stephen Henson*
+
+ * Montgomery multiplication may produce incorrect results
+
+ There is a carry propagating bug in the Broadwell-specific Montgomery
+ multiplication procedure that handles input lengths divisible by, but
+ longer than 256 bits. Analysis suggests that attacks against RSA, DSA
+ and DH private keys are impossible. This is because the subroutine in
+ question is not used in operations with the private key itself and an input
+ of the attacker's direct choice. Otherwise the bug can manifest itself as
+ transient authentication and key negotiation failures or reproducible
+ erroneous outcome of public-key operations with specially crafted input.
+ Among EC algorithms only Brainpool P-512 curves are affected and one
+ presumably can attack ECDH key negotiation. Impact was not analyzed in
+ detail, because pre-requisites for attack are considered unlikely. Namely
+ multiple clients have to choose the curve in question and the server has to
+ share the private key among them, neither of which is default behaviour.
+ Even then only clients that chose the curve will be affected.
+
+ This issue was publicly reported as transient failures and was not
+ initially recognized as a security issue. Thanks to Richard Morgan for
+ providing reproducible case.
+ ([CVE-2016-7055])
+
+ *Andy Polyakov*
+
+ * Removed automatic addition of RPATH in shared libraries and executables,
+ as this was a remainder from OpenSSL 1.0.x and isn't needed any more.
+
+ *Richard Levitte*
+
+### Changes between 1.1.0a and 1.1.0b [26 Sep 2016]
+
+ * Fix Use After Free for large message sizes
+
+ The patch applied to address CVE-2016-6307 resulted in an issue where if a
+ message larger than approx 16k is received then the underlying buffer to
+ store the incoming message is reallocated and moved. Unfortunately a
+ dangling pointer to the old location is left which results in an attempt to
+ write to the previously freed location. This is likely to result in a
+ crash, however it could potentially lead to execution of arbitrary code.
+
+ This issue only affects OpenSSL 1.1.0a.
+
+ This issue was reported to OpenSSL by Robert Święcki.
+ ([CVE-2016-6309])
+
+ *Matt Caswell*
+
+### Changes between 1.1.0 and 1.1.0a [22 Sep 2016]
+
+ * OCSP Status Request extension unbounded memory growth
+
+ A malicious client can send an excessively large OCSP Status Request
+ extension. If that client continually requests renegotiation, sending a
+ large OCSP Status Request extension each time, then there will be unbounded
+ memory growth on the server. This will eventually lead to a Denial Of
+ Service attack through memory exhaustion. Servers with a default
+ configuration are vulnerable even if they do not support OCSP. Builds using
+ the "no-ocsp" build time option are not affected.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ ([CVE-2016-6304])
+
+ *Matt Caswell*
+
+ * SSL_peek() hang on empty record
+
+ OpenSSL 1.1.0 SSL/TLS will hang during a call to SSL_peek() if the peer
+ sends an empty record. This could be exploited by a malicious peer in a
+ Denial Of Service attack.
+
+ This issue was reported to OpenSSL by Alex Gaynor.
+ ([CVE-2016-6305])
+
+ *Matt Caswell*
+
+ * Excessive allocation of memory in tls_get_message_header() and
+ dtls1_preprocess_fragment()
+
+ A (D)TLS message includes 3 bytes for its length in the header for the
+ message. This would allow for messages up to 16Mb in length. Messages of
+ this length are excessive and OpenSSL includes a check to ensure that a
+ peer is sending reasonably sized messages in order to avoid too much memory
+ being consumed to service a connection. A flaw in the logic of version
+ 1.1.0 means that memory for the message is allocated too early, prior to
+ the excessive message length check. Due to way memory is allocated in
+ OpenSSL this could mean an attacker could force up to 21Mb to be allocated
+ to service a connection. This could lead to a Denial of Service through
+ memory exhaustion. However, the excessive message length check still takes
+ place, and this would cause the connection to immediately fail. Assuming
+ that the application calls SSL_free() on the failed connection in a timely
+ manner then the 21Mb of allocated memory will then be immediately freed
+ again. Therefore the excessive memory allocation will be transitory in
+ nature. This then means that there is only a security impact if:
+
+ 1) The application does not call SSL_free() in a timely manner in the event
+ that the connection fails
+ or
+ 2) The application is working in a constrained environment where there is
+ very little free memory
+ or
+ 3) The attacker initiates multiple connection attempts such that there are
+ multiple connections in a state where memory has been allocated for the
+ connection; SSL_free() has not yet been called; and there is insufficient
+ memory to service the multiple requests.
+
+ Except in the instance of (1) above any Denial Of Service is likely to be
+ transitory because as soon as the connection fails the memory is
+ subsequently freed again in the SSL_free() call. However there is an
+ increased risk during this period of application crashes due to the lack of
+ memory - which would then mean a more serious Denial of Service.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ (CVE-2016-6307 and CVE-2016-6308)
+
+ *Matt Caswell*
+
+ * solaris-x86-cc, i.e. 32-bit configuration with vendor compiler,
+ had to be removed. Primary reason is that vendor assembler can't
+ assemble our modules with -KPIC flag. As result it, assembly
+ support, was not even available as option. But its lack means
+ lack of side-channel resistant code, which is incompatible with
+ security by todays standards. Fortunately gcc is readily available
+ prepackaged option, which we firmly point at...
+
+ *Andy Polyakov*
+
+### Changes between 1.0.2h and 1.1.0 [25 Aug 2016]
+
+ * Windows command-line tool supports UTF-8 opt-in option for arguments
+ and console input. Setting OPENSSL_WIN32_UTF8 environment variable
+ (to any value) allows Windows user to access PKCS#12 file generated
+ with Windows CryptoAPI and protected with non-ASCII password, as well
+ as files generated under UTF-8 locale on Linux also protected with
+ non-ASCII password.
+
+ *Andy Polyakov*
+
+ * To mitigate the SWEET32 attack ([CVE-2016-2183]), 3DES cipher suites
+ have been disabled by default and removed from DEFAULT, just like RC4.
+ See the RC4 item below to re-enable both.
+
+ *Rich Salz*
+
+ * The method for finding the storage location for the Windows RAND seed file
+ has changed. First we check %RANDFILE%. If that is not set then we check
+ the directories %HOME%, %USERPROFILE% and %SYSTEMROOT% in that order. If
+ all else fails we fall back to C:\.
+
+ *Matt Caswell*
+
+ * The EVP_EncryptUpdate() function has had its return type changed from void
+ to int. A return of 0 indicates and error while a return of 1 indicates
+ success.
+
+ *Matt Caswell*
+
+ * The flags RSA_FLAG_NO_CONSTTIME, DSA_FLAG_NO_EXP_CONSTTIME and
+ DH_FLAG_NO_EXP_CONSTTIME which previously provided the ability to switch
+ off the constant time implementation for RSA, DSA and DH have been made
+ no-ops and deprecated.
+
+ *Matt Caswell*
+
+ * Windows RAND implementation was simplified to only get entropy by
+ calling CryptGenRandom(). Various other RAND-related tickets
+ were also closed.
+
+ *Joseph Wylie Yandle, Rich Salz*
+
+ * The stack and lhash API's were renamed to start with `OPENSSL_SK_`
+ and `OPENSSL_LH_`, respectively. The old names are available
+ with API compatibility. They new names are now completely documented.
+
+ *Rich Salz*
+
+ * Unify TYPE_up_ref(obj) methods signature.
+ SSL_CTX_up_ref(), SSL_up_ref(), X509_up_ref(), EVP_PKEY_up_ref(),
+ X509_CRL_up_ref(), X509_OBJECT_up_ref_count() methods are now returning an
+ int (instead of void) like all others TYPE_up_ref() methods.
+ So now these methods also check the return value of CRYPTO_atomic_add(),
+ and the validity of object reference counter.
+
+ *fdasilvayy@gmail.com*
+
+ * With Windows Visual Studio builds, the .pdb files are installed
+ alongside the installed libraries and executables. For a static
+ library installation, ossl_static.pdb is the associate compiler
+ generated .pdb file to be used when linking programs.
+
+ *Richard Levitte*
+
+ * Remove openssl.spec. Packaging files belong with the packagers.
+
+ *Richard Levitte*
+
+ * Automatic Darwin/OSX configuration has had a refresh, it will now
+ recognise x86_64 architectures automatically. You can still decide
+ to build for a different bitness with the environment variable
+ KERNEL_BITS (can be 32 or 64), for example:
+
+ KERNEL_BITS=32 ./config
+
+ *Richard Levitte*
+
+ * Change default algorithms in pkcs8 utility to use PKCS#5 v2.0,
+ 256 bit AES and HMAC with SHA256.
+
+ *Steve Henson*
+
+ * Remove support for MIPS o32 ABI on IRIX (and IRIX only).
+
+ *Andy Polyakov*
+
+ * Triple-DES ciphers have been moved from HIGH to MEDIUM.
+
+ *Rich Salz*
+
+ * To enable users to have their own config files and build file templates,
+ Configure looks in the directory indicated by the environment variable
+ OPENSSL_LOCAL_CONFIG_DIR as well as the in-source Configurations/
+ directory. On VMS, OPENSSL_LOCAL_CONFIG_DIR is expected to be a logical
+ name and is used as is.
+
+ *Richard Levitte*
+
+ * The following datatypes were made opaque: X509_OBJECT, X509_STORE_CTX,
+ X509_STORE, X509_LOOKUP, and X509_LOOKUP_METHOD. The unused type
+ X509_CERT_FILE_CTX was removed.
+
+ *Rich Salz*
+
+ * "shared" builds are now the default. To create only static libraries use
+ the "no-shared" Configure option.
+
+ *Matt Caswell*
+
+ * Remove the no-aes, no-hmac, no-rsa, no-sha and no-md5 Configure options.
+ All of these option have not worked for some while and are fundamental
+ algorithms.
+
+ *Matt Caswell*
+
+ * Make various cleanup routines no-ops and mark them as deprecated. Most
+ global cleanup functions are no longer required because they are handled
+ via auto-deinit (see OPENSSL_init_crypto and OPENSSL_init_ssl man pages).
+ Explicitly de-initing can cause problems (e.g. where a library that uses
+ OpenSSL de-inits, but an application is still using it). The affected
+ functions are CONF_modules_free(), ENGINE_cleanup(), OBJ_cleanup(),
+ EVP_cleanup(), BIO_sock_cleanup(), CRYPTO_cleanup_all_ex_data(),
+ RAND_cleanup(), SSL_COMP_free_compression_methods(), ERR_free_strings() and
+ COMP_zlib_cleanup().
+
+ *Matt Caswell*
+
+ * --strict-warnings no longer enables runtime debugging options
+ such as REF_DEBUG. Instead, debug options are automatically
+ enabled with '--debug' builds.
+
+ *Andy Polyakov, Emilia Käsper*
+
+ * Made DH and DH_METHOD opaque. The structures for managing DH objects
+ have been moved out of the public header files. New functions for managing
+ these have been added.
+
+ *Matt Caswell*
+
+ * Made RSA and RSA_METHOD opaque. The structures for managing RSA
+ objects have been moved out of the public header files. New
+ functions for managing these have been added.
+
+ *Richard Levitte*
+
+ * Made DSA and DSA_METHOD opaque. The structures for managing DSA objects
+ have been moved out of the public header files. New functions for managing
+ these have been added.
+
+ *Matt Caswell*
+
+ * Made BIO and BIO_METHOD opaque. The structures for managing BIOs have been
+ moved out of the public header files. New functions for managing these
+ have been added.
+
+ *Matt Caswell*
+
+ * Removed no-rijndael as a config option. Rijndael is an old name for AES.
+
+ *Matt Caswell*
+
+ * Removed the mk1mf build scripts.
+
+ *Richard Levitte*
+
+ * Headers are now wrapped, if necessary, with OPENSSL_NO_xxx, so
+ it is always safe to #include a header now.
+
+ *Rich Salz*
+
+ * Removed the aged BC-32 config and all its supporting scripts
+
+ *Richard Levitte*
+
+ * Removed support for Ultrix, Netware, and OS/2.
+
+ *Rich Salz*
+
+ * Add support for HKDF.
+
+ *Alessandro Ghedini*
+
+ * Add support for blake2b and blake2s
+
+ *Bill Cox*
+
+ * Added support for "pipelining". Ciphers that have the
+ EVP_CIPH_FLAG_PIPELINE flag set have a capability to process multiple
+ encryptions/decryptions simultaneously. There are currently no built-in
+ ciphers with this property but the expectation is that engines will be able
+ to offer it to significantly improve throughput. Support has been extended
+ into libssl so that multiple records for a single connection can be
+ processed in one go (for >=TLS 1.1).
+
+ *Matt Caswell*
+
+ * Added the AFALG engine. This is an async capable engine which is able to
+ offload work to the Linux kernel. In this initial version it only supports
+ AES128-CBC. The kernel must be version 4.1.0 or greater.
+
+ *Catriona Lucey*
+
+ * OpenSSL now uses a new threading API. It is no longer necessary to
+ set locking callbacks to use OpenSSL in a multi-threaded environment. There
+ are two supported threading models: pthreads and windows threads. It is
+ also possible to configure OpenSSL at compile time for "no-threads". The
+ old threading API should no longer be used. The functions have been
+ replaced with "no-op" compatibility macros.
+
+ *Alessandro Ghedini, Matt Caswell*
+
+ * Modify behavior of ALPN to invoke callback after SNI/servername
+ callback, such that updates to the SSL_CTX affect ALPN.
+
+ *Todd Short*
+
+ * Add SSL_CIPHER queries for authentication and key-exchange.
+
+ *Todd Short*
+
+ * Changes to the DEFAULT cipherlist:
+ - Prefer (EC)DHE handshakes over plain RSA.
+ - Prefer AEAD ciphers over legacy ciphers.
+ - Prefer ECDSA over RSA when both certificates are available.
+ - Prefer TLSv1.2 ciphers/PRF.
+ - Remove DSS, SEED, IDEA, CAMELLIA, and AES-CCM from the
+ default cipherlist.
+
+ *Emilia Käsper*
+
+ * Change the ECC default curve list to be this, in order: x25519,
+ secp256r1, secp521r1, secp384r1.
+
+ *Rich Salz*
+
+ * RC4 based libssl ciphersuites are now classed as "weak" ciphers and are
+ disabled by default. They can be re-enabled using the
+ enable-weak-ssl-ciphers option to Configure.
+
+ *Matt Caswell*
+
+ * If the server has ALPN configured, but supports no protocols that the
+ client advertises, send a fatal "no_application_protocol" alert.
+ This behaviour is SHALL in RFC 7301, though it isn't universally
+ implemented by other servers.
+
+ *Emilia Käsper*
+
+ * Add X25519 support.
+ Add ASN.1 and EVP_PKEY methods for X25519. This includes support
+ for public and private key encoding using the format documented in
+ draft-ietf-curdle-pkix-02. The corresponding EVP_PKEY method supports
+ key generation and key derivation.
+
+ TLS support complies with draft-ietf-tls-rfc4492bis-08 and uses
+ X25519(29).
+
+ *Steve Henson*
+
+ * Deprecate SRP_VBASE_get_by_user.
+ SRP_VBASE_get_by_user had inconsistent memory management behaviour.
+ In order to fix an unavoidable memory leak ([CVE-2016-0798]),
+ SRP_VBASE_get_by_user was changed to ignore the "fake user" SRP
+ seed, even if the seed is configured.
+
+ Users should use SRP_VBASE_get1_by_user instead. Note that in
+ SRP_VBASE_get1_by_user, caller must free the returned value. Note
+ also that even though configuring the SRP seed attempts to hide
+ invalid usernames by continuing the handshake with fake
+ credentials, this behaviour is not constant time and no strong
+ guarantees are made that the handshake is indistinguishable from
+ that of a valid user.
+
+ *Emilia Käsper*
+
+ * Configuration change; it's now possible to build dynamic engines
+ without having to build shared libraries and vice versa. This
+ only applies to the engines in `engines/`, those in `crypto/engine/`
+ will always be built into libcrypto (i.e. "static").
+
+ Building dynamic engines is enabled by default; to disable, use
+ the configuration option "disable-dynamic-engine".
+
+ The only requirements for building dynamic engines are the
+ presence of the DSO module and building with position independent
+ code, so they will also automatically be disabled if configuring
+ with "disable-dso" or "disable-pic".
+
+ The macros OPENSSL_NO_STATIC_ENGINE and OPENSSL_NO_DYNAMIC_ENGINE
+ are also taken away from openssl/opensslconf.h, as they are
+ irrelevant.
+
+ *Richard Levitte*
+
+ * Configuration change; if there is a known flag to compile
+ position independent code, it will always be applied on the
+ libcrypto and libssl object files, and never on the application
+ object files. This means other libraries that use routines from
+ libcrypto / libssl can be made into shared libraries regardless
+ of how OpenSSL was configured.
+
+ If this isn't desirable, the configuration options "disable-pic"
+ or "no-pic" can be used to disable the use of PIC. This will
+ also disable building shared libraries and dynamic engines.
+
+ *Richard Levitte*
+
+ * Removed JPAKE code. It was experimental and has no wide use.
+
+ *Rich Salz*
+
+ * The INSTALL_PREFIX Makefile variable has been renamed to
+ DESTDIR. That makes for less confusion on what this variable
+ is for. Also, the configuration option --install_prefix is
+ removed.
+
+ *Richard Levitte*
+
+ * Heartbeat for TLS has been removed and is disabled by default
+ for DTLS; configure with enable-heartbeats. Code that uses the
+ old #define's might need to be updated.
+
+ *Emilia Käsper, Rich Salz*
+
+ * Rename REF_CHECK to REF_DEBUG.
+
+ *Rich Salz*
+
+ * New "unified" build system
+
+ The "unified" build system is aimed to be a common system for all
+ platforms we support. With it comes new support for VMS.
+
+ This system builds supports building in a different directory tree
+ than the source tree. It produces one Makefile (for unix family
+ or lookalikes), or one descrip.mms (for VMS).
+
+ The source of information to make the Makefile / descrip.mms is
+ small files called 'build.info', holding the necessary
+ information for each directory with source to compile, and a
+ template in Configurations, like unix-Makefile.tmpl or
+ descrip.mms.tmpl.
+
+ With this change, the library names were also renamed on Windows
+ and on VMS. They now have names that are closer to the standard
+ on Unix, and include the major version number, and in certain
+ cases, the architecture they are built for. See "Notes on shared
+ libraries" in INSTALL.
+
+ We rely heavily on the perl module Text::Template.
+
+ *Richard Levitte*
+
+ * Added support for auto-initialisation and de-initialisation of the library.
+ OpenSSL no longer requires explicit init or deinit routines to be called,
+ except in certain circumstances. See the OPENSSL_init_crypto() and
+ OPENSSL_init_ssl() man pages for further information.
+
+ *Matt Caswell*
+
+ * The arguments to the DTLSv1_listen function have changed. Specifically the
+ "peer" argument is now expected to be a BIO_ADDR object.
+
+ * Rewrite of BIO networking library. The BIO library lacked consistent
+ support of IPv6, and adding it required some more extensive
+ modifications. This introduces the BIO_ADDR and BIO_ADDRINFO types,
+ which hold all types of addresses and chains of address information.
+ It also introduces a new API, with functions like BIO_socket,
+ BIO_connect, BIO_listen, BIO_lookup and a rewrite of BIO_accept.
+ The source/sink BIOs BIO_s_connect, BIO_s_accept and BIO_s_datagram
+ have been adapted accordingly.
+
+ *Richard Levitte*
+
+ * RSA_padding_check_PKCS1_type_1 now accepts inputs with and without
+ the leading 0-byte.
+
+ *Emilia Käsper*
+
+ * CRIME protection: disable compression by default, even if OpenSSL is
+ compiled with zlib enabled. Applications can still enable compression
+ by calling SSL_CTX_clear_options(ctx, SSL_OP_NO_COMPRESSION), or by
+ using the SSL_CONF library to configure compression.
+
+ *Emilia Käsper*
+
+ * The signature of the session callback configured with
+ SSL_CTX_sess_set_get_cb was changed. The read-only input buffer
+ was explicitly marked as `const unsigned char*` instead of
+ `unsigned char*`.
+
+ *Emilia Käsper*
+
+ * Always DPURIFY. Remove the use of uninitialized memory in the
+ RNG, and other conditional uses of DPURIFY. This makes -DPURIFY a no-op.
+
+ *Emilia Käsper*
+
+ * Removed many obsolete configuration items, including
+ DES_PTR, DES_RISC1, DES_RISC2, DES_INT
+ MD2_CHAR, MD2_INT, MD2_LONG
+ BF_PTR, BF_PTR2
+ IDEA_SHORT, IDEA_LONG
+ RC2_SHORT, RC2_LONG, RC4_LONG, RC4_CHUNK, RC4_INDEX
+
+ *Rich Salz, with advice from Andy Polyakov*
+
+ * Many BN internals have been moved to an internal header file.
+
+ *Rich Salz with help from Andy Polyakov*
+
+ * Configuration and writing out the results from it has changed.
+ Files such as Makefile include/openssl/opensslconf.h and are now
+ produced through general templates, such as Makefile.in and
+ crypto/opensslconf.h.in and some help from the perl module
+ Text::Template.
+
+ Also, the center of configuration information is no longer
+ Makefile. Instead, Configure produces a perl module in
+ configdata.pm which holds most of the config data (in the hash
+ table %config), the target data that comes from the target
+ configuration in one of the `Configurations/*.conf` files (in
+ %target).
+
+ *Richard Levitte*
+
+ * To clarify their intended purposes, the Configure options
+ --prefix and --openssldir change their semantics, and become more
+ straightforward and less interdependent.
+
+ --prefix shall be used exclusively to give the location INSTALLTOP
+ where programs, scripts, libraries, include files and manuals are
+ going to be installed. The default is now /usr/local.
+
+ --openssldir shall be used exclusively to give the default
+ location OPENSSLDIR where certificates, private keys, CRLs are
+ managed. This is also where the default openssl.cnf gets
+ installed.
+ If the directory given with this option is a relative path, the
+ values of both the --prefix value and the --openssldir value will
+ be combined to become OPENSSLDIR.
+ The default for --openssldir is INSTALLTOP/ssl.
+
+ Anyone who uses --openssldir to specify where OpenSSL is to be
+ installed MUST change to use --prefix instead.
+
+ *Richard Levitte*
+
+ * The GOST engine was out of date and therefore it has been removed. An up
+ to date GOST engine is now being maintained in an external repository.
+ See: <https://wiki.openssl.org/index.php/Binaries>. Libssl still retains
+ support for GOST ciphersuites (these are only activated if a GOST engine
+ is present).
+
+ *Matt Caswell*
+
+ * EGD is no longer supported by default; use enable-egd when
+ configuring.
+
+ *Ben Kaduk and Rich Salz*
+
+ * The distribution now has Makefile.in files, which are used to
+ create Makefile's when Configure is run. *Configure must be run
+ before trying to build now.*
+
+ *Rich Salz*
+
+ * The return value for SSL_CIPHER_description() for error conditions
+ has changed.
+
+ *Rich Salz*
+
+ * Support for RFC6698/RFC7671 DANE TLSA peer authentication.
+
+ Obtaining and performing DNSSEC validation of TLSA records is
+ the application's responsibility. The application provides
+ the TLSA records of its choice to OpenSSL, and these are then
+ used to authenticate the peer.
+
+ The TLSA records need not even come from DNS. They can, for
+ example, be used to implement local end-entity certificate or
+ trust-anchor "pinning", where the "pin" data takes the form
+ of TLSA records, which can augment or replace verification
+ based on the usual WebPKI public certification authorities.
+
+ *Viktor Dukhovni*
+
+ * Revert default OPENSSL_NO_DEPRECATED setting. Instead OpenSSL
+ continues to support deprecated interfaces in default builds.
+ However, applications are strongly advised to compile their
+ source files with -DOPENSSL_API_COMPAT=0x10100000L, which hides
+ the declarations of all interfaces deprecated in 0.9.8, 1.0.0
+ or the 1.1.0 releases.
+
+ In environments in which all applications have been ported to
+ not use any deprecated interfaces OpenSSL's Configure script
+ should be used with the --api=1.1.0 option to entirely remove
+ support for the deprecated features from the library and
+ unconditionally disable them in the installed headers.
+ Essentially the same effect can be achieved with the "no-deprecated"
+ argument to Configure, except that this will always restrict
+ the build to just the latest API, rather than a fixed API
+ version.
+
+ As applications are ported to future revisions of the API,
+ they should update their compile-time OPENSSL_API_COMPAT define
+ accordingly, but in most cases should be able to continue to
+ compile with later releases.
+
+ The OPENSSL_API_COMPAT versions for 1.0.0, and 0.9.8 are
+ 0x10000000L and 0x00908000L, respectively. However those
+ versions did not support the OPENSSL_API_COMPAT feature, and
+ so applications are not typically tested for explicit support
+ of just the undeprecated features of either release.
+
+ *Viktor Dukhovni*
+
+ * Add support for setting the minimum and maximum supported protocol.
+ It can bet set via the SSL_set_min_proto_version() and
+ SSL_set_max_proto_version(), or via the SSL_CONF's MinProtocol and
+ MaxProtocol. It's recommended to use the new APIs to disable
+ protocols instead of disabling individual protocols using
+ SSL_set_options() or SSL_CONF's Protocol. This change also
+ removes support for disabling TLS 1.2 in the OpenSSL TLS
+ client at compile time by defining OPENSSL_NO_TLS1_2_CLIENT.
+
+ *Kurt Roeckx*
+
+ * Support for ChaCha20 and Poly1305 added to libcrypto and libssl.
+
+ *Andy Polyakov*
+
+ * New EC_KEY_METHOD, this replaces the older ECDSA_METHOD and ECDH_METHOD
+ and integrates ECDSA and ECDH functionality into EC. Implementations can
+ now redirect key generation and no longer need to convert to or from
+ ECDSA_SIG format.
+
+ Note: the ecdsa.h and ecdh.h headers are now no longer needed and just
+ include the ec.h header file instead.
+
+ *Steve Henson*
+
+ * Remove support for all 40 and 56 bit ciphers. This includes all the export
+ ciphers who are no longer supported and drops support the ephemeral RSA key
+ exchange. The LOW ciphers currently doesn't have any ciphers in it.
+
+ *Kurt Roeckx*
+
+ * Made EVP_MD_CTX, EVP_MD, EVP_CIPHER_CTX, EVP_CIPHER and HMAC_CTX
+ opaque. For HMAC_CTX, the following constructors and destructors
+ were added:
+
+ HMAC_CTX *HMAC_CTX_new(void);
+ void HMAC_CTX_free(HMAC_CTX *ctx);
+
+ For EVP_MD and EVP_CIPHER, complete APIs to create, fill and
+ destroy such methods has been added. See EVP_MD_meth_new(3) and
+ EVP_CIPHER_meth_new(3) for documentation.
+
+ Additional changes:
+ 1) `EVP_MD_CTX_cleanup()`, `EVP_CIPHER_CTX_cleanup()` and
+ `HMAC_CTX_cleanup()` were removed. `HMAC_CTX_reset()` and
+ `EVP_MD_CTX_reset()` should be called instead to reinitialise
+ an already created structure.
+ 2) For consistency with the majority of our object creators and
+ destructors, `EVP_MD_CTX_(create|destroy)` were renamed to
+ `EVP_MD_CTX_(new|free)`. The old names are retained as macros
+ for deprecated builds.
+
+ *Richard Levitte*
+
+ * Added ASYNC support. Libcrypto now includes the async sub-library to enable
+ cryptographic operations to be performed asynchronously as long as an
+ asynchronous capable engine is used. See the ASYNC_start_job() man page for
+ further details. Libssl has also had this capability integrated with the
+ introduction of the new mode SSL_MODE_ASYNC and associated error
+ SSL_ERROR_WANT_ASYNC. See the SSL_CTX_set_mode() and SSL_get_error() man
+ pages. This work was developed in partnership with Intel Corp.
+
+ *Matt Caswell*
+
+ * SSL_{CTX_}set_ecdh_auto() has been removed and ECDH is support is
+ always enabled now. If you want to disable the support you should
+ exclude it using the list of supported ciphers. This also means that the
+ "-no_ecdhe" option has been removed from s_server.
+
+ *Kurt Roeckx*
+
+ * SSL_{CTX}_set_tmp_ecdh() which can set 1 EC curve now internally calls
+ SSL_{CTX_}set1_curves() which can set a list.
+
+ *Kurt Roeckx*
+
+ * Remove support for SSL_{CTX_}set_tmp_ecdh_callback(). You should set the
+ curve you want to support using SSL_{CTX_}set1_curves().
+
+ *Kurt Roeckx*
+
+ * State machine rewrite. The state machine code has been significantly
+ refactored in order to remove much duplication of code and solve issues
+ with the old code (see [ssl/statem/README.md](ssl/statem/README.md) for
+ further details). This change does have some associated API changes.
+ Notably the SSL_state() function has been removed and replaced by
+ SSL_get_state which now returns an "OSSL_HANDSHAKE_STATE" instead of an int.
+ SSL_set_state() has been removed altogether. The previous handshake states
+ defined in ssl.h and ssl3.h have also been removed.
+
+ *Matt Caswell*
+
+ * All instances of the string "ssleay" in the public API were replaced
+ with OpenSSL (case-matching; e.g., OPENSSL_VERSION for #define's)
+ Some error codes related to internal RSA_eay API's were renamed.
+
+ *Rich Salz*
+
+ * The demo files in crypto/threads were moved to demo/threads.
+
+ *Rich Salz*
+
+ * Removed obsolete engines: 4758cca, aep, atalla, cswift, nuron, gmp,
+ sureware and ubsec.
+
+ *Matt Caswell, Rich Salz*
+
+ * New ASN.1 embed macro.
+
+ New ASN.1 macro ASN1_EMBED. This is the same as ASN1_SIMPLE except the
+ structure is not allocated: it is part of the parent. That is instead of
+
+ FOO *x;
+
+ it must be:
+
+ FOO x;
+
+ This reduces memory fragmentation and make it impossible to accidentally
+ set a mandatory field to NULL.
+
+ This currently only works for some fields specifically a SEQUENCE, CHOICE,
+ or ASN1_STRING type which is part of a parent SEQUENCE. Since it is
+ equivalent to ASN1_SIMPLE it cannot be tagged, OPTIONAL, SET OF or
+ SEQUENCE OF.
+
+ *Steve Henson*
+
+ * Remove EVP_CHECK_DES_KEY, a compile-time option that never compiled.
+
+ *Emilia Käsper*
+
+ * Removed DES and RC4 ciphersuites from DEFAULT. Also removed RC2 although
+ in 1.0.2 EXPORT was already removed and the only RC2 ciphersuite is also
+ an EXPORT one. COMPLEMENTOFDEFAULT has been updated accordingly to add
+ DES and RC4 ciphersuites.
+
+ *Matt Caswell*
+
+ * Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs.
+ This changes the decoding behaviour for some invalid messages,
+ though the change is mostly in the more lenient direction, and
+ legacy behaviour is preserved as much as possible.
+
+ *Emilia Käsper*
+
+ * Fix no-stdio build.
+ *David Woodhouse <David.Woodhouse@intel.com> and also*
+ *Ivan Nestlerode <ivan.nestlerode@sonos.com>*
+
+ * New testing framework
+ The testing framework has been largely rewritten and is now using
+ perl and the perl modules Test::Harness and an extended variant of
+ Test::More called OpenSSL::Test to do its work. All test scripts in
+ test/ have been rewritten into test recipes, and all direct calls to
+ executables in test/Makefile have become individual recipes using the
+ simplified testing OpenSSL::Test::Simple.
+
+ For documentation on our testing modules, do:
+
+ perldoc test/testlib/OpenSSL/Test/Simple.pm
+ perldoc test/testlib/OpenSSL/Test.pm
+
+ *Richard Levitte*
+
+ * Revamped memory debug; only -DCRYPTO_MDEBUG and -DCRYPTO_MDEBUG_ABORT
+ are used; the latter aborts on memory leaks (usually checked on exit).
+ Some undocumented "set malloc, etc., hooks" functions were removed
+ and others were changed. All are now documented.
+
+ *Rich Salz*
+
+ * In DSA_generate_parameters_ex, if the provided seed is too short,
+ return an error
+
+ *Rich Salz and Ismo Puustinen <ismo.puustinen@intel.com>*
+
+ * Rewrite PSK to support ECDHE_PSK, DHE_PSK and RSA_PSK. Add ciphersuites
+ from RFC4279, RFC4785, RFC5487, RFC5489.
+
+ Thanks to Christian J. Dietrich and Giuseppe D'Angelo for the
+ original RSA_PSK patch.
+
+ *Steve Henson*
+
+ * Dropped support for the SSL3_FLAGS_DELAY_CLIENT_FINISHED flag. This SSLeay
+ era flag was never set throughout the codebase (only read). Also removed
+ SSL3_FLAGS_POP_BUFFER which was only used if
+ SSL3_FLAGS_DELAY_CLIENT_FINISHED was also set.
+
+ *Matt Caswell*
+
+ * Changed the default name options in the "ca", "crl", "req" and "x509"
+ to be "oneline" instead of "compat".
+
+ *Richard Levitte*
+
+ * Remove SSL_OP_TLS_BLOCK_PADDING_BUG. This is SSLeay legacy, we're
+ not aware of clients that still exhibit this bug, and the workaround
+ hasn't been working properly for a while.
+
+ *Emilia Käsper*
+
+ * The return type of BIO_number_read() and BIO_number_written() as well as
+ the corresponding num_read and num_write members in the BIO structure has
+ changed from unsigned long to uint64_t. On platforms where an unsigned
+ long is 32 bits (e.g. Windows) these counters could overflow if >4Gb is
+ transferred.
+
+ *Matt Caswell*
+
+ * Given the pervasive nature of TLS extensions it is inadvisable to run
+ OpenSSL without support for them. It also means that maintaining
+ the OPENSSL_NO_TLSEXT option within the code is very invasive (and probably
+ not well tested). Therefore the OPENSSL_NO_TLSEXT option has been removed.
+
+ *Matt Caswell*
+
+ * Removed support for the two export grade static DH ciphersuites
+ EXP-DH-RSA-DES-CBC-SHA and EXP-DH-DSS-DES-CBC-SHA. These two ciphersuites
+ were newly added (along with a number of other static DH ciphersuites) to
+ 1.0.2. However the two export ones have *never* worked since they were
+ introduced. It seems strange in any case to be adding new export
+ ciphersuites, and given "logjam" it also does not seem correct to fix them.
+
+ *Matt Caswell*
+
+ * Version negotiation has been rewritten. In particular SSLv23_method(),
+ SSLv23_client_method() and SSLv23_server_method() have been deprecated,
+ and turned into macros which simply call the new preferred function names
+ TLS_method(), TLS_client_method() and TLS_server_method(). All new code
+ should use the new names instead. Also as part of this change the ssl23.h
+ header file has been removed.
+
+ *Matt Caswell*
+
+ * Support for Kerberos ciphersuites in TLS (RFC2712) has been removed. This
+ code and the associated standard is no longer considered fit-for-purpose.
+
+ *Matt Caswell*
+
+ * RT2547 was closed. When generating a private key, try to make the
+ output file readable only by the owner. This behavior change might
+ be noticeable when interacting with other software.
+
+ * Documented all exdata functions. Added CRYPTO_free_ex_index.
+ Added a test.
+
+ *Rich Salz*
+
+ * Added HTTP GET support to the ocsp command.
+
+ *Rich Salz*
+
+ * Changed default digest for the dgst and enc commands from MD5 to
+ sha256
+
+ *Rich Salz*
+
+ * RAND_pseudo_bytes has been deprecated. Users should use RAND_bytes instead.
+
+ *Matt Caswell*
+
+ * Added support for TLS extended master secret from
+ draft-ietf-tls-session-hash-03.txt. Thanks for Alfredo Pironti for an
+ initial patch which was a great help during development.
+
+ *Steve Henson*
+
+ * All libssl internal structures have been removed from the public header
+ files, and the OPENSSL_NO_SSL_INTERN option has been removed (since it is
+ now redundant). Users should not attempt to access internal structures
+ directly. Instead they should use the provided API functions.
+
+ *Matt Caswell*
+
+ * config has been changed so that by default OPENSSL_NO_DEPRECATED is used.
+ Access to deprecated functions can be re-enabled by running config with
+ "enable-deprecated". In addition applications wishing to use deprecated
+ functions must define OPENSSL_USE_DEPRECATED. Note that this new behaviour
+ will, by default, disable some transitive includes that previously existed
+ in the header files (e.g. ec.h will no longer, by default, include bn.h)
+
+ *Matt Caswell*
+
+ * Added support for OCB mode. OpenSSL has been granted a patent license
+ compatible with the OpenSSL license for use of OCB. Details are available
+ at <https://www.openssl.org/source/OCB-patent-grant-OpenSSL.pdf>. Support
+ for OCB can be removed by calling config with no-ocb.
+
+ *Matt Caswell*
+
+ * SSLv2 support has been removed. It still supports receiving a SSLv2
+ compatible client hello.
+
+ *Kurt Roeckx*
+
+ * Increased the minimal RSA keysize from 256 to 512 bits [Rich Salz],
+ done while fixing the error code for the key-too-small case.
+
+ *Annie Yousar <a.yousar@informatik.hu-berlin.de>*
+
+ * CA.sh has been removed; use CA.pl instead.
+
+ *Rich Salz*
+
+ * Removed old DES API.
+
+ *Rich Salz*
+
+ * Remove various unsupported platforms:
+ Sony NEWS4
+ BEOS and BEOS_R5
+ NeXT
+ SUNOS
+ MPE/iX
+ Sinix/ReliantUNIX RM400
+ DGUX
+ NCR
+ Tandem
+ Cray
+ 16-bit platforms such as WIN16
+
+ *Rich Salz*
+
+ * Clean up OPENSSL_NO_xxx #define's
+ - Use setbuf() and remove OPENSSL_NO_SETVBUF_IONBF
+ - Rename OPENSSL_SYSNAME_xxx to OPENSSL_SYS_xxx
+ - OPENSSL_NO_EC{DH,DSA} merged into OPENSSL_NO_EC
+ - OPENSSL_NO_RIPEMD160, OPENSSL_NO_RIPEMD merged into OPENSSL_NO_RMD160
+ - OPENSSL_NO_FP_API merged into OPENSSL_NO_STDIO
+ - Remove OPENSSL_NO_BIO OPENSSL_NO_BUFFER OPENSSL_NO_CHAIN_VERIFY
+ OPENSSL_NO_EVP OPENSSL_NO_FIPS_ERR OPENSSL_NO_HASH_COMP
+ OPENSSL_NO_LHASH OPENSSL_NO_OBJECT OPENSSL_NO_SPEED OPENSSL_NO_STACK
+ OPENSSL_NO_X509 OPENSSL_NO_X509_VERIFY
+ - Remove MS_STATIC; it's a relic from platforms <32 bits.
+
+ *Rich Salz*
+
+ * Cleaned up dead code
+ Remove all but one '#ifdef undef' which is to be looked at.
+
+ *Rich Salz*
+
+ * Clean up calling of xxx_free routines.
+ Just like free(), fix most of the xxx_free routines to accept
+ NULL. Remove the non-null checks from callers. Save much code.
+
+ *Rich Salz*
+
+ * Add secure heap for storage of private keys (when possible).
+ Add BIO_s_secmem(), CBIGNUM, etc.
+ Contributed by Akamai Technologies under our Corporate CLA.
+
+ *Rich Salz*
+
+ * Experimental support for a new, fast, unbiased prime candidate generator,
+ bn_probable_prime_dh_coprime(). Not currently used by any prime generator.
+
+ *Felix Laurie von Massenbach <felix@erbridge.co.uk>*
+
+ * New output format NSS in the sess_id command line tool. This allows
+ exporting the session id and the master key in NSS keylog format.
+
+ *Martin Kaiser <martin@kaiser.cx>*
+
+ * Harmonize version and its documentation. -f flag is used to display
+ compilation flags.
+
+ *mancha <mancha1@zoho.com>*
+
+ * Fix eckey_priv_encode so it immediately returns an error upon a failure
+ in i2d_ECPrivateKey. Thanks to Ted Unangst for feedback on this issue.
+
+ *mancha <mancha1@zoho.com>*
+
+ * Fix some double frees. These are not thought to be exploitable.
+
+ *mancha <mancha1@zoho.com>*
+
+ * A missing bounds check in the handling of the TLS heartbeat extension
+ can be used to reveal up to 64k of memory to a connected client or
+ server.
+
+ Thanks for Neel Mehta of Google Security for discovering this bug and to
+ Adam Langley <agl@chromium.org> and Bodo Moeller <bmoeller@acm.org> for
+ preparing the fix ([CVE-2014-0160])
+
+ *Adam Langley, Bodo Moeller*
+
+ * Fix for the attack described in the paper "Recovering OpenSSL
+ ECDSA Nonces Using the FLUSH+RELOAD Cache Side-channel Attack"
+ by Yuval Yarom and Naomi Benger. Details can be obtained from:
+ <http://eprint.iacr.org/2014/140>
+
+ Thanks to Yuval Yarom and Naomi Benger for discovering this
+ flaw and to Yuval Yarom for supplying a fix ([CVE-2014-0076])
+
+ *Yuval Yarom and Naomi Benger*
+
+ * Use algorithm specific chains in SSL_CTX_use_certificate_chain_file():
+ this fixes a limitation in previous versions of OpenSSL.
+
+ *Steve Henson*
+
+ * Experimental encrypt-then-mac support.
+
+ Experimental support for encrypt then mac from
+ draft-gutmann-tls-encrypt-then-mac-02.txt
+
+ To enable it set the appropriate extension number (0x42 for the test
+ server) using e.g. -DTLSEXT_TYPE_encrypt_then_mac=0x42
+
+ For non-compliant peers (i.e. just about everything) this should have no
+ effect.
+
+ WARNING: EXPERIMENTAL, SUBJECT TO CHANGE.
+
+ *Steve Henson*
+
+ * Add EVP support for key wrapping algorithms, to avoid problems with
+ existing code the flag EVP_CIPHER_CTX_WRAP_ALLOW has to be set in
+ the EVP_CIPHER_CTX or an error is returned. Add AES and DES3 wrap
+ algorithms and include tests cases.
+
+ *Steve Henson*
+
+ * Extend CMS code to support RSA-PSS signatures and RSA-OAEP for
+ enveloped data.
+
+ *Steve Henson*
+
+ * Extended RSA OAEP support via EVP_PKEY API. Options to specify digest,
+ MGF1 digest and OAEP label.
+
+ *Steve Henson*
+
+ * Make openssl verify return errors.
+
+ *Chris Palmer <palmer@google.com> and Ben Laurie*
+
+ * New function ASN1_TIME_diff to calculate the difference between two
+ ASN1_TIME structures or one structure and the current time.
+
+ *Steve Henson*
+
+ * Update fips_test_suite to support multiple command line options. New
+ test to induce all self test errors in sequence and check expected
+ failures.
+
+ *Steve Henson*
+
+ * Add FIPS_{rsa,dsa,ecdsa}_{sign,verify} functions which digest and
+ sign or verify all in one operation.
+
+ *Steve Henson*
+
+ * Add fips_algvs: a multicall fips utility incorporating all the algorithm
+ test programs and fips_test_suite. Includes functionality to parse
+ the minimal script output of fipsalgest.pl directly.
+
+ *Steve Henson*
+
+ * Add authorisation parameter to FIPS_module_mode_set().
+
+ *Steve Henson*
+
+ * Add FIPS selftest for ECDH algorithm using P-224 and B-233 curves.
+
+ *Steve Henson*
+
+ * Use separate DRBG fields for internal and external flags. New function
+ FIPS_drbg_health_check() to perform on demand health checking. Add
+ generation tests to fips_test_suite with reduced health check interval to
+ demonstrate periodic health checking. Add "nodh" option to
+ fips_test_suite to skip very slow DH test.
+
+ *Steve Henson*
+
+ * New function FIPS_get_cipherbynid() to lookup FIPS supported ciphers
+ based on NID.
+
+ *Steve Henson*
+
+ * More extensive health check for DRBG checking many more failure modes.
+ New function FIPS_selftest_drbg_all() to handle every possible DRBG
+ combination: call this in fips_test_suite.
+
+ *Steve Henson*
+
+ * Add support for canonical generation of DSA parameter 'g'. See
+ FIPS 186-3 A.2.3.
+
+ * Add support for HMAC DRBG from SP800-90. Update DRBG algorithm test and
+ POST to handle HMAC cases.
+
+ *Steve Henson*
+
+ * Add functions FIPS_module_version() and FIPS_module_version_text()
+ to return numerical and string versions of the FIPS module number.
+
+ *Steve Henson*
+
+ * Rename FIPS_mode_set and FIPS_mode to FIPS_module_mode_set and
+ FIPS_module_mode. FIPS_mode and FIPS_mode_set will be implemented
+ outside the validated module in the FIPS capable OpenSSL.
+
+ *Steve Henson*
+
+ * Minor change to DRBG entropy callback semantics. In some cases
+ there is no multiple of the block length between min_len and
+ max_len. Allow the callback to return more than max_len bytes
+ of entropy but discard any extra: it is the callback's responsibility
+ to ensure that the extra data discarded does not impact the
+ requested amount of entropy.
+
+ *Steve Henson*
+
+ * Add PRNG security strength checks to RSA, DSA and ECDSA using
+ information in FIPS186-3, SP800-57 and SP800-131A.
+
+ *Steve Henson*
+
+ * CCM support via EVP. Interface is very similar to GCM case except we
+ must supply all data in one chunk (i.e. no update, final) and the
+ message length must be supplied if AAD is used. Add algorithm test
+ support.
+
+ *Steve Henson*
+
+ * Initial version of POST overhaul. Add POST callback to allow the status
+ of POST to be monitored and/or failures induced. Modify fips_test_suite
+ to use callback. Always run all selftests even if one fails.
+
+ *Steve Henson*
+
+ * XTS support including algorithm test driver in the fips_gcmtest program.
+ Note: this does increase the maximum key length from 32 to 64 bytes but
+ there should be no binary compatibility issues as existing applications
+ will never use XTS mode.
+
+ *Steve Henson*
+
+ * Extensive reorganisation of FIPS PRNG behaviour. Remove all dependencies
+ to OpenSSL RAND code and replace with a tiny FIPS RAND API which also
+ performs algorithm blocking for unapproved PRNG types. Also do not
+ set PRNG type in FIPS_mode_set(): leave this to the application.
+ Add default OpenSSL DRBG handling: sets up FIPS PRNG and seeds with
+ the standard OpenSSL PRNG: set additional data to a date time vector.
+
+ *Steve Henson*
+
+ * Rename old X9.31 PRNG functions of the form `FIPS_rand*` to `FIPS_x931*`.
+ This shouldn't present any incompatibility problems because applications
+ shouldn't be using these directly and any that are will need to rethink
+ anyway as the X9.31 PRNG is now deprecated by FIPS 140-2
+
+ *Steve Henson*
+
+ * Extensive self tests and health checking required by SP800-90 DRBG.
+ Remove strength parameter from FIPS_drbg_instantiate and always
+ instantiate at maximum supported strength.
+
+ *Steve Henson*
+
+ * Add ECDH code to fips module and fips_ecdhvs for primitives only testing.
+
+ *Steve Henson*
+
+ * New algorithm test program fips_dhvs to handle DH primitives only testing.
+
+ *Steve Henson*
+
+ * New function DH_compute_key_padded() to compute a DH key and pad with
+ leading zeroes if needed: this complies with SP800-56A et al.
+
+ *Steve Henson*
+
+ * Initial implementation of SP800-90 DRBGs for Hash and CTR. Not used by
+ anything, incomplete, subject to change and largely untested at present.
+
+ *Steve Henson*
+
+ * Modify fipscanisteronly build option to only build the necessary object
+ files by filtering FIPS_EX_OBJ through a perl script in crypto/Makefile.
+
+ *Steve Henson*
+
+ * Add experimental option FIPSSYMS to give all symbols in
+ fipscanister.o and FIPS or fips prefix. This will avoid
+ conflicts with future versions of OpenSSL. Add perl script
+ util/fipsas.pl to preprocess assembly language source files
+ and rename any affected symbols.
+
+ *Steve Henson*
+
+ * Add selftest checks and algorithm block of non-fips algorithms in
+ FIPS mode. Remove DES2 from selftests.
+
+ *Steve Henson*
+
+ * Add ECDSA code to fips module. Add tiny fips_ecdsa_check to just
+ return internal method without any ENGINE dependencies. Add new
+ tiny fips sign and verify functions.
+
+ *Steve Henson*
+
+ * New build option no-ec2m to disable characteristic 2 code.
+
+ *Steve Henson*
+
+ * New build option "fipscanisteronly". This only builds fipscanister.o
+ and (currently) associated fips utilities. Uses the file Makefile.fips
+ instead of Makefile.org as the prototype.
+
+ *Steve Henson*
+
+ * Add some FIPS mode restrictions to GCM. Add internal IV generator.
+ Update fips_gcmtest to use IV generator.
+
+ *Steve Henson*
+
+ * Initial, experimental EVP support for AES-GCM. AAD can be input by
+ setting output buffer to NULL. The `*Final` function must be
+ called although it will not retrieve any additional data. The tag
+ can be set or retrieved with a ctrl. The IV length is by default 12
+ bytes (96 bits) but can be set to an alternative value. If the IV
+ length exceeds the maximum IV length (currently 16 bytes) it cannot be
+ set before the key.
+
+ *Steve Henson*
+
+ * New flag in ciphers: EVP_CIPH_FLAG_CUSTOM_CIPHER. This means the
+ underlying do_cipher function handles all cipher semantics itself
+ including padding and finalisation. This is useful if (for example)
+ an ENGINE cipher handles block padding itself. The behaviour of
+ do_cipher is subtly changed if this flag is set: the return value
+ is the number of characters written to the output buffer (zero is
+ no longer an error code) or a negative error code. Also if the
+ input buffer is NULL and length 0 finalisation should be performed.
+
+ *Steve Henson*
+
+ * If a candidate issuer certificate is already part of the constructed
+ path ignore it: new debug notification X509_V_ERR_PATH_LOOP for this case.
+
+ *Steve Henson*
+
+ * Improve forward-security support: add functions
+
+ void SSL_CTX_set_not_resumable_session_callback(
+ SSL_CTX *ctx, int (*cb)(SSL *ssl, int is_forward_secure))
+ void SSL_set_not_resumable_session_callback(
+ SSL *ssl, int (*cb)(SSL *ssl, int is_forward_secure))
+
+ for use by SSL/TLS servers; the callback function will be called whenever a
+ new session is created, and gets to decide whether the session may be
+ cached to make it resumable (return 0) or not (return 1). (As by the
+ SSL/TLS protocol specifications, the session_id sent by the server will be
+ empty to indicate that the session is not resumable; also, the server will
+ not generate RFC 4507 (RFC 5077) session tickets.)
+
+ A simple reasonable callback implementation is to return is_forward_secure.
+ This parameter will be set to 1 or 0 depending on the ciphersuite selected
+ by the SSL/TLS server library, indicating whether it can provide forward
+ security.
+
+ *Emilia Käsper <emilia.kasper@esat.kuleuven.be> (Google)*
+
+ * New -verify_name option in command line utilities to set verification
+ parameters by name.
+
+ *Steve Henson*
+
+ * Initial CMAC implementation. WARNING: EXPERIMENTAL, API MAY CHANGE.
+ Add CMAC pkey methods.
+
+ *Steve Henson*
+
+ * Experimental renegotiation in s_server -www mode. If the client
+ browses /reneg connection is renegotiated. If /renegcert it is
+ renegotiated requesting a certificate.
+
+ *Steve Henson*
+
+ * Add an "external" session cache for debugging purposes to s_server. This
+ should help trace issues which normally are only apparent in deployed
+ multi-process servers.
+
+ *Steve Henson*
+
+ * Extensive audit of libcrypto with DEBUG_UNUSED. Fix many cases where
+ return value is ignored. NB. The functions RAND_add(), RAND_seed(),
+ BIO_set_cipher() and some obscure PEM functions were changed so they
+ can now return an error. The RAND changes required a change to the
+ RAND_METHOD structure.
+
+ *Steve Henson*
+
+ * New macro `__owur` for "OpenSSL Warn Unused Result". This makes use of
+ a gcc attribute to warn if the result of a function is ignored. This
+ is enable if DEBUG_UNUSED is set. Add to several functions in evp.h
+ whose return value is often ignored.
+
+ *Steve Henson*
+
+ * New -noct, -requestct, -requirect and -ctlogfile options for s_client.
+ These allow SCTs (signed certificate timestamps) to be requested and
+ validated when establishing a connection.
+
+ *Rob Percival <robpercival@google.com>*
+
+OpenSSL 1.0.2
+-------------
+
+### Changes between 1.0.2s and 1.0.2t [10 Sep 2019]
+
+ * For built-in EC curves, ensure an EC_GROUP built from the curve name is
+ used even when parsing explicit parameters, when loading a encoded key
+ or calling `EC_GROUP_new_from_ecpkparameters()`/
+ `EC_GROUP_new_from_ecparameters()`.
+ This prevents bypass of security hardening and performance gains,
+ especially for curves with specialized EC_METHODs.
+ By default, if a key encoded with explicit parameters is loaded and later
+ encoded, the output is still encoded with explicit parameters, even if
+ internally a "named" EC_GROUP is used for computation.
+
+ *Nicola Tuveri*
+
+ * Compute ECC cofactors if not provided during EC_GROUP construction. Before
+ this change, EC_GROUP_set_generator would accept order and/or cofactor as
+ NULL. After this change, only the cofactor parameter can be NULL. It also
+ does some minimal sanity checks on the passed order.
+ ([CVE-2019-1547])
+
+ *Billy Bob Brumley*
+
+ * Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey.
+ An attack is simple, if the first CMS_recipientInfo is valid but the
+ second CMS_recipientInfo is chosen ciphertext. If the second
+ recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct
+ encryption key will be replaced by garbage, and the message cannot be
+ decoded, but if the RSA decryption fails, the correct encryption key is
+ used and the recipient will not notice the attack.
+ As a work around for this potential attack the length of the decrypted
+ key must be equal to the cipher default key length, in case the
+ certifiate is not given and all recipientInfo are tried out.
+ The old behaviour can be re-enabled in the CMS code by setting the
+ CMS_DEBUG_DECRYPT flag.
+ ([CVE-2019-1563])
+
+ *Bernd Edlinger*
+
+ * Document issue with installation paths in diverse Windows builds
+
+ '/usr/local/ssl' is an unsafe prefix for location to install OpenSSL
+ binaries and run-time config file.
+ ([CVE-2019-1552])
+
+ *Richard Levitte*
+
+### Changes between 1.0.2r and 1.0.2s [28 May 2019]
+
+ * Change the default RSA, DSA and DH size to 2048 bit instead of 1024.
+ This changes the size when using the `genpkey` command when no size is given.
+ It fixes an omission in earlier changes that changed all RSA, DSA and DH
+ generation commands to use 2048 bits by default.
+
+ *Kurt Roeckx*
+
+ * Add FIPS support for Android Arm 64-bit
+
+ Support for Android Arm 64-bit was added to the OpenSSL FIPS Object
+ Module in Version 2.0.10. For some reason, the corresponding target
+ 'android64-aarch64' was missing OpenSSL 1.0.2, whence it could not be
+ built with FIPS support on Android Arm 64-bit. This omission has been
+ fixed.
+
+ *Matthias St. Pierre*
+
+### Changes between 1.0.2q and 1.0.2r [26 Feb 2019]
+
+ * 0-byte record padding oracle
+
+ If an application encounters a fatal protocol error and then calls
+ SSL_shutdown() twice (once to send a close_notify, and once to receive one)
+ then OpenSSL can respond differently to the calling application if a 0 byte
+ record is received with invalid padding compared to if a 0 byte record is
+ received with an invalid MAC. If the application then behaves differently
+ based on that in a way that is detectable to the remote peer, then this
+ amounts to a padding oracle that could be used to decrypt data.
+
+ In order for this to be exploitable "non-stitched" ciphersuites must be in
+ use. Stitched ciphersuites are optimised implementations of certain
+ commonly used ciphersuites. Also the application must call SSL_shutdown()
+ twice even if a protocol error has occurred (applications should not do
+ this but some do anyway).
+
+ This issue was discovered by Juraj Somorovsky, Robert Merget and Nimrod
+ Aviram, with additional investigation by Steven Collison and Andrew
+ Hourselt. It was reported to OpenSSL on 10th December 2018.
+ ([CVE-2019-1559])
+
+ *Matt Caswell*
+
+ * Move strictness check from EVP_PKEY_asn1_new() to EVP_PKEY_asn1_add0().
+
+ *Richard Levitte*
+
+### Changes between 1.0.2p and 1.0.2q [20 Nov 2018]
+
+ * Microarchitecture timing vulnerability in ECC scalar multiplication
+
+ OpenSSL ECC scalar multiplication, used in e.g. ECDSA and ECDH, has been
+ shown to be vulnerable to a microarchitecture timing side channel attack.
+ An attacker with sufficient access to mount local timing attacks during
+ ECDSA signature generation could recover the private key.
+
+ This issue was reported to OpenSSL on 26th October 2018 by Alejandro
+ Cabrera Aldaya, Billy Brumley, Sohaib ul Hassan, Cesar Pereida Garcia and
+ Nicola Tuveri.
+ ([CVE-2018-5407])
+
+ *Billy Brumley*
+
+ * Timing vulnerability in DSA signature generation
+
+ The OpenSSL DSA signature algorithm has been shown to be vulnerable to a
+ timing side channel attack. An attacker could use variations in the signing
+ algorithm to recover the private key.
+
+ This issue was reported to OpenSSL on 16th October 2018 by Samuel Weiser.
+ ([CVE-2018-0734])
+
+ *Paul Dale*
+
+ * Resolve a compatibility issue in EC_GROUP handling with the FIPS Object
+ Module, accidentally introduced while backporting security fixes from the
+ development branch and hindering the use of ECC in FIPS mode.
+
+ *Nicola Tuveri*
+
+### Changes between 1.0.2o and 1.0.2p [14 Aug 2018]
+
+ * Client DoS due to large DH parameter
+
+ During key agreement in a TLS handshake using a DH(E) based ciphersuite a
+ malicious server can send a very large prime value to the client. This will
+ cause the client to spend an unreasonably long period of time generating a
+ key for this prime resulting in a hang until the client has finished. This
+ could be exploited in a Denial Of Service attack.
+
+ This issue was reported to OpenSSL on 5th June 2018 by Guido Vranken
+ ([CVE-2018-0732])
+
+ *Guido Vranken*
+
+ * Cache timing vulnerability in RSA Key Generation
+
+ The OpenSSL RSA Key generation algorithm has been shown to be vulnerable to
+ a cache timing side channel attack. An attacker with sufficient access to
+ mount cache timing attacks during the RSA key generation process could
+ recover the private key.
+
+ This issue was reported to OpenSSL on 4th April 2018 by Alejandro Cabrera
+ Aldaya, Billy Brumley, Cesar Pereida Garcia and Luis Manuel Alvarez Tapia.
+ ([CVE-2018-0737])
+
+ *Billy Brumley*
+
+ * Make EVP_PKEY_asn1_new() a bit stricter about its input. A NULL pem_str
+ parameter is no longer accepted, as it leads to a corrupt table. NULL
+ pem_str is reserved for alias entries only.
+
+ *Richard Levitte*
+
+ * Revert blinding in ECDSA sign and instead make problematic addition
+ length-invariant. Switch even to fixed-length Montgomery multiplication.
+
+ *Andy Polyakov*
+
+ * Change generating and checking of primes so that the error rate of not
+ being prime depends on the intended use based on the size of the input.
+ For larger primes this will result in more rounds of Miller-Rabin.
+ The maximal error rate for primes with more than 1080 bits is lowered
+ to 2^-128.
+
+ *Kurt Roeckx, Annie Yousar*
+
+ * Increase the number of Miller-Rabin rounds for DSA key generating to 64.
+
+ *Kurt Roeckx*
+
+ * Add blinding to ECDSA and DSA signatures to protect against side channel
+ attacks discovered by Keegan Ryan (NCC Group).
+
+ *Matt Caswell*
+
+ * When unlocking a pass phrase protected PEM file or PKCS#8 container, we
+ now allow empty (zero character) pass phrases.
+
+ *Richard Levitte*
+
+ * Certificate time validation (X509_cmp_time) enforces stricter
+ compliance with RFC 5280. Fractional seconds and timezone offsets
+ are no longer allowed.
+
+ *Emilia Käsper*
+
+### Changes between 1.0.2n and 1.0.2o [27 Mar 2018]
+
+ * Constructed ASN.1 types with a recursive definition could exceed the stack
+
+ Constructed ASN.1 types with a recursive definition (such as can be found
+ in PKCS7) could eventually exceed the stack given malicious input with
+ excessive recursion. This could result in a Denial Of Service attack. There
+ are no such structures used within SSL/TLS that come from untrusted sources
+ so this is considered safe.
+
+ This issue was reported to OpenSSL on 4th January 2018 by the OSS-fuzz
+ project.
+ ([CVE-2018-0739])
+
+ *Matt Caswell*
+
+### Changes between 1.0.2m and 1.0.2n [7 Dec 2017]
+
+ * Read/write after SSL object in error state
+
+ OpenSSL 1.0.2 (starting from version 1.0.2b) introduced an "error state"
+ mechanism. The intent was that if a fatal error occurred during a handshake
+ then OpenSSL would move into the error state and would immediately fail if
+ you attempted to continue the handshake. This works as designed for the
+ explicit handshake functions (SSL_do_handshake(), SSL_accept() and
+ SSL_connect()), however due to a bug it does not work correctly if
+ SSL_read() or SSL_write() is called directly. In that scenario, if the
+ handshake fails then a fatal error will be returned in the initial function
+ call. If SSL_read()/SSL_write() is subsequently called by the application
+ for the same SSL object then it will succeed and the data is passed without
+ being decrypted/encrypted directly from the SSL/TLS record layer.
+
+ In order to exploit this issue an application bug would have to be present
+ that resulted in a call to SSL_read()/SSL_write() being issued after having
+ already received a fatal error.
+
+ This issue was reported to OpenSSL by David Benjamin (Google).
+ ([CVE-2017-3737])
+
+ *Matt Caswell*
+
+ * rsaz_1024_mul_avx2 overflow bug on x86_64
+
+ There is an overflow bug in the AVX2 Montgomery multiplication procedure
+ used in exponentiation with 1024-bit moduli. No EC algorithms are affected.
+ Analysis suggests that attacks against RSA and DSA as a result of this
+ defect would be very difficult to perform and are not believed likely.
+ Attacks against DH1024 are considered just feasible, because most of the
+ work necessary to deduce information about a private key may be performed
+ offline. The amount of resources required for such an attack would be
+ significant. However, for an attack on TLS to be meaningful, the server
+ would have to share the DH1024 private key among multiple clients, which is
+ no longer an option since CVE-2016-0701.
+
+ This only affects processors that support the AVX2 but not ADX extensions
+ like Intel Haswell (4th generation).
+
+ This issue was reported to OpenSSL by David Benjamin (Google). The issue
+ was originally found via the OSS-Fuzz project.
+ ([CVE-2017-3738])
+
+ *Andy Polyakov*
+
+### Changes between 1.0.2l and 1.0.2m [2 Nov 2017]
+
+ * bn_sqrx8x_internal carry bug on x86_64
+
+ There is a carry propagating bug in the x86_64 Montgomery squaring
+ procedure. No EC algorithms are affected. Analysis suggests that attacks
+ against RSA and DSA as a result of this defect would be very difficult to
+ perform and are not believed likely. Attacks against DH are considered just
+ feasible (although very difficult) because most of the work necessary to
+ deduce information about a private key may be performed offline. The amount
+ of resources required for such an attack would be very significant and
+ likely only accessible to a limited number of attackers. An attacker would
+ additionally need online access to an unpatched system using the target
+ private key in a scenario with persistent DH parameters and a private
+ key that is shared between multiple clients.
+
+ This only affects processors that support the BMI1, BMI2 and ADX extensions
+ like Intel Broadwell (5th generation) and later or AMD Ryzen.
+
+ This issue was reported to OpenSSL by the OSS-Fuzz project.
+ ([CVE-2017-3736])
+
+ *Andy Polyakov*
+
+ * Malformed X.509 IPAddressFamily could cause OOB read
+
+ If an X.509 certificate has a malformed IPAddressFamily extension,
+ OpenSSL could do a one-byte buffer overread. The most likely result
+ would be an erroneous display of the certificate in text format.
+
+ This issue was reported to OpenSSL by the OSS-Fuzz project.
+
+ *Rich Salz*
+
+### Changes between 1.0.2k and 1.0.2l [25 May 2017]
+
+ * Have 'config' recognise 64-bit mingw and choose 'mingw64' as the target
+ platform rather than 'mingw'.
+
+ *Richard Levitte*
+
+### Changes between 1.0.2j and 1.0.2k [26 Jan 2017]
+
+ * Truncated packet could crash via OOB read
+
+ If one side of an SSL/TLS path is running on a 32-bit host and a specific
+ cipher is being used, then a truncated packet can cause that host to
+ perform an out-of-bounds read, usually resulting in a crash.
+
+ This issue was reported to OpenSSL by Robert Święcki of Google.
+ ([CVE-2017-3731])
+
+ *Andy Polyakov*
+
+ * BN_mod_exp may produce incorrect results on x86_64
+
+ There is a carry propagating bug in the x86_64 Montgomery squaring
+ procedure. No EC algorithms are affected. Analysis suggests that attacks
+ against RSA and DSA as a result of this defect would be very difficult to
+ perform and are not believed likely. Attacks against DH are considered just
+ feasible (although very difficult) because most of the work necessary to
+ deduce information about a private key may be performed offline. The amount
+ of resources required for such an attack would be very significant and
+ likely only accessible to a limited number of attackers. An attacker would
+ additionally need online access to an unpatched system using the target
+ private key in a scenario with persistent DH parameters and a private
+ key that is shared between multiple clients. For example this can occur by
+ default in OpenSSL DHE based SSL/TLS ciphersuites. Note: This issue is very
+ similar to CVE-2015-3193 but must be treated as a separate problem.
+
+ This issue was reported to OpenSSL by the OSS-Fuzz project.
+ ([CVE-2017-3732])
+
+ *Andy Polyakov*
+
+ * Montgomery multiplication may produce incorrect results
+
+ There is a carry propagating bug in the Broadwell-specific Montgomery
+ multiplication procedure that handles input lengths divisible by, but
+ longer than 256 bits. Analysis suggests that attacks against RSA, DSA
+ and DH private keys are impossible. This is because the subroutine in
+ question is not used in operations with the private key itself and an input
+ of the attacker's direct choice. Otherwise the bug can manifest itself as
+ transient authentication and key negotiation failures or reproducible
+ erroneous outcome of public-key operations with specially crafted input.
+ Among EC algorithms only Brainpool P-512 curves are affected and one
+ presumably can attack ECDH key negotiation. Impact was not analyzed in
+ detail, because pre-requisites for attack are considered unlikely. Namely
+ multiple clients have to choose the curve in question and the server has to
+ share the private key among them, neither of which is default behaviour.
+ Even then only clients that chose the curve will be affected.
+
+ This issue was publicly reported as transient failures and was not
+ initially recognized as a security issue. Thanks to Richard Morgan for
+ providing reproducible case.
+ ([CVE-2016-7055])
+
+ *Andy Polyakov*
+
+ * OpenSSL now fails if it receives an unrecognised record type in TLS1.0
+ or TLS1.1. Previously this only happened in SSLv3 and TLS1.2. This is to
+ prevent issues where no progress is being made and the peer continually
+ sends unrecognised record types, using up resources processing them.
+
+ *Matt Caswell*
+
+### Changes between 1.0.2i and 1.0.2j [26 Sep 2016]
+
+ * Missing CRL sanity check
+
+ A bug fix which included a CRL sanity check was added to OpenSSL 1.1.0
+ but was omitted from OpenSSL 1.0.2i. As a result any attempt to use
+ CRLs in OpenSSL 1.0.2i will crash with a null pointer exception.
+
+ This issue only affects the OpenSSL 1.0.2i
+ ([CVE-2016-7052])
+
+ *Matt Caswell*
+
+### Changes between 1.0.2h and 1.0.2i [22 Sep 2016]
+
+ * OCSP Status Request extension unbounded memory growth
+
+ A malicious client can send an excessively large OCSP Status Request
+ extension. If that client continually requests renegotiation, sending a
+ large OCSP Status Request extension each time, then there will be unbounded
+ memory growth on the server. This will eventually lead to a Denial Of
+ Service attack through memory exhaustion. Servers with a default
+ configuration are vulnerable even if they do not support OCSP. Builds using
+ the "no-ocsp" build time option are not affected.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ ([CVE-2016-6304])
+
+ *Matt Caswell*
+
+ * In order to mitigate the SWEET32 attack, the DES ciphers were moved from
+ HIGH to MEDIUM.
+
+ This issue was reported to OpenSSL Karthikeyan Bhargavan and Gaetan
+ Leurent (INRIA)
+ ([CVE-2016-2183])
+
+ *Rich Salz*
+
+ * OOB write in MDC2_Update()
+
+ An overflow can occur in MDC2_Update() either if called directly or
+ through the EVP_DigestUpdate() function using MDC2. If an attacker
+ is able to supply very large amounts of input data after a previous
+ call to EVP_EncryptUpdate() with a partial block then a length check
+ can overflow resulting in a heap corruption.
+
+ The amount of data needed is comparable to SIZE_MAX which is impractical
+ on most platforms.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ ([CVE-2016-6303])
+
+ *Stephen Henson*
+
+ * Malformed SHA512 ticket DoS
+
+ If a server uses SHA512 for TLS session ticket HMAC it is vulnerable to a
+ DoS attack where a malformed ticket will result in an OOB read which will
+ ultimately crash.
+
+ The use of SHA512 in TLS session tickets is comparatively rare as it requires
+ a custom server callback and ticket lookup mechanism.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ ([CVE-2016-6302])
+
+ *Stephen Henson*
+
+ * OOB write in BN_bn2dec()
+
+ The function BN_bn2dec() does not check the return value of BN_div_word().
+ This can cause an OOB write if an application uses this function with an
+ overly large BIGNUM. This could be a problem if an overly large certificate
+ or CRL is printed out from an untrusted source. TLS is not affected because
+ record limits will reject an oversized certificate before it is parsed.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ ([CVE-2016-2182])
+
+ *Stephen Henson*
+
+ * OOB read in TS_OBJ_print_bio()
+
+ The function TS_OBJ_print_bio() misuses OBJ_obj2txt(): the return value is
+ the total length the OID text representation would use and not the amount
+ of data written. This will result in OOB reads when large OIDs are
+ presented.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ ([CVE-2016-2180])
+
+ *Stephen Henson*
+
+ * Pointer arithmetic undefined behaviour
+
+ Avoid some undefined pointer arithmetic
+
+ A common idiom in the codebase is to check limits in the following manner:
+ "p + len > limit"
+
+ Where "p" points to some malloc'd data of SIZE bytes and
+ limit == p + SIZE
+
+ "len" here could be from some externally supplied data (e.g. from a TLS
+ message).
+
+ The rules of C pointer arithmetic are such that "p + len" is only well
+ defined where len <= SIZE. Therefore the above idiom is actually
+ undefined behaviour.
+
+ For example this could cause problems if some malloc implementation
+ provides an address for "p" such that "p + len" actually overflows for
+ values of len that are too big and therefore p + len < limit.
+
+ This issue was reported to OpenSSL by Guido Vranken
+ ([CVE-2016-2177])
+
+ *Matt Caswell*
+
+ * Constant time flag not preserved in DSA signing
+
+ Operations in the DSA signing algorithm should run in constant time in
+ order to avoid side channel attacks. A flaw in the OpenSSL DSA
+ implementation means that a non-constant time codepath is followed for
+ certain operations. This has been demonstrated through a cache-timing
+ attack to be sufficient for an attacker to recover the private DSA key.
+
+ This issue was reported by César Pereida (Aalto University), Billy Brumley
+ (Tampere University of Technology), and Yuval Yarom (The University of
+ Adelaide and NICTA).
+ ([CVE-2016-2178])
+
+ *César Pereida*
+
+ * DTLS buffered message DoS
+
+ In a DTLS connection where handshake messages are delivered out-of-order
+ those messages that OpenSSL is not yet ready to process will be buffered
+ for later use. Under certain circumstances, a flaw in the logic means that
+ those messages do not get removed from the buffer even though the handshake
+ has been completed. An attacker could force up to approx. 15 messages to
+ remain in the buffer when they are no longer required. These messages will
+ be cleared when the DTLS connection is closed. The default maximum size for
+ a message is 100k. Therefore the attacker could force an additional 1500k
+ to be consumed per connection. By opening many simulataneous connections an
+ attacker could cause a DoS attack through memory exhaustion.
+
+ This issue was reported to OpenSSL by Quan Luo.
+ ([CVE-2016-2179])
+
+ *Matt Caswell*
+
+ * DTLS replay protection DoS
+
+ A flaw in the DTLS replay attack protection mechanism means that records
+ that arrive for future epochs update the replay protection "window" before
+ the MAC for the record has been validated. This could be exploited by an
+ attacker by sending a record for the next epoch (which does not have to
+ decrypt or have a valid MAC), with a very large sequence number. This means
+ that all subsequent legitimate packets are dropped causing a denial of
+ service for a specific DTLS connection.
+
+ This issue was reported to OpenSSL by the OCAP audit team.
+ ([CVE-2016-2181])
+
+ *Matt Caswell*
+
+ * Certificate message OOB reads
+
+ In OpenSSL 1.0.2 and earlier some missing message length checks can result
+ in OOB reads of up to 2 bytes beyond an allocated buffer. There is a
+ theoretical DoS risk but this has not been observed in practice on common
+ platforms.
+
+ The messages affected are client certificate, client certificate request
+ and server certificate. As a result the attack can only be performed
+ against a client or a server which enables client authentication.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ ([CVE-2016-6306])
+
+ *Stephen Henson*
+
+### Changes between 1.0.2g and 1.0.2h [3 May 2016]
+
+ * Prevent padding oracle in AES-NI CBC MAC check
+
+ A MITM attacker can use a padding oracle attack to decrypt traffic
+ when the connection uses an AES CBC cipher and the server support
+ AES-NI.
+
+ This issue was introduced as part of the fix for Lucky 13 padding
+ attack ([CVE-2013-0169]). The padding check was rewritten to be in
+ constant time by making sure that always the same bytes are read and
+ compared against either the MAC or padding bytes. But it no longer
+ checked that there was enough data to have both the MAC and padding
+ bytes.
+
+ This issue was reported by Juraj Somorovsky using TLS-Attacker.
+
+ *Kurt Roeckx*
+
+ * Fix EVP_EncodeUpdate overflow
+
+ An overflow can occur in the EVP_EncodeUpdate() function which is used for
+ Base64 encoding of binary data. If an attacker is able to supply very large
+ amounts of input data then a length check can overflow resulting in a heap
+ corruption.
+
+ Internally to OpenSSL the EVP_EncodeUpdate() function is primarily used by
+ the `PEM_write_bio*` family of functions. These are mainly used within the
+ OpenSSL command line applications, so any application which processes data
+ from an untrusted source and outputs it as a PEM file should be considered
+ vulnerable to this issue. User applications that call these APIs directly
+ with large amounts of untrusted data may also be vulnerable.
+
+ This issue was reported by Guido Vranken.
+ ([CVE-2016-2105])
+
+ *Matt Caswell*
+
+ * Fix EVP_EncryptUpdate overflow
+
+ An overflow can occur in the EVP_EncryptUpdate() function. If an attacker
+ is able to supply very large amounts of input data after a previous call to
+ EVP_EncryptUpdate() with a partial block then a length check can overflow
+ resulting in a heap corruption. Following an analysis of all OpenSSL
+ internal usage of the EVP_EncryptUpdate() function all usage is one of two
+ forms. The first form is where the EVP_EncryptUpdate() call is known to be
+ the first called function after an EVP_EncryptInit(), and therefore that
+ specific call must be safe. The second form is where the length passed to
+ EVP_EncryptUpdate() can be seen from the code to be some small value and
+ therefore there is no possibility of an overflow. Since all instances are
+ one of these two forms, it is believed that there can be no overflows in
+ internal code due to this problem. It should be noted that
+ EVP_DecryptUpdate() can call EVP_EncryptUpdate() in certain code paths.
+ Also EVP_CipherUpdate() is a synonym for EVP_EncryptUpdate(). All instances
+ of these calls have also been analysed too and it is believed there are no
+ instances in internal usage where an overflow could occur.
+
+ This issue was reported by Guido Vranken.
+ ([CVE-2016-2106])
+
+ *Matt Caswell*
+
+ * Prevent ASN.1 BIO excessive memory allocation
+
+ When ASN.1 data is read from a BIO using functions such as d2i_CMS_bio()
+ a short invalid encoding can cause allocation of large amounts of memory
+ potentially consuming excessive resources or exhausting memory.
+
+ Any application parsing untrusted data through d2i BIO functions is
+ affected. The memory based functions such as d2i_X509() are *not* affected.
+ Since the memory based functions are used by the TLS library, TLS
+ applications are not affected.
+
+ This issue was reported by Brian Carpenter.
+ ([CVE-2016-2109])
+
+ *Stephen Henson*
+
+ * EBCDIC overread
+
+ ASN1 Strings that are over 1024 bytes can cause an overread in applications
+ using the X509_NAME_oneline() function on EBCDIC systems. This could result
+ in arbitrary stack data being returned in the buffer.
+
+ This issue was reported by Guido Vranken.
+ ([CVE-2016-2176])
+
+ *Matt Caswell*
+
+ * Modify behavior of ALPN to invoke callback after SNI/servername
+ callback, such that updates to the SSL_CTX affect ALPN.
+
+ *Todd Short*
+
+ * Remove LOW from the DEFAULT cipher list. This removes singles DES from the
+ default.
+
+ *Kurt Roeckx*
+
+ * Only remove the SSLv2 methods with the no-ssl2-method option. When the
+ methods are enabled and ssl2 is disabled the methods return NULL.
+
+ *Kurt Roeckx*
+
+### Changes between 1.0.2f and 1.0.2g [1 Mar 2016]
+
+* Disable weak ciphers in SSLv3 and up in default builds of OpenSSL.
+ Builds that are not configured with "enable-weak-ssl-ciphers" will not
+ provide any "EXPORT" or "LOW" strength ciphers.
+
+ *Viktor Dukhovni*
+
+* Disable SSLv2 default build, default negotiation and weak ciphers. SSLv2
+ is by default disabled at build-time. Builds that are not configured with
+ "enable-ssl2" will not support SSLv2. Even if "enable-ssl2" is used,
+ users who want to negotiate SSLv2 via the version-flexible SSLv23_method()
+ will need to explicitly call either of:
+
+ SSL_CTX_clear_options(ctx, SSL_OP_NO_SSLv2);
+ or
+ SSL_clear_options(ssl, SSL_OP_NO_SSLv2);
+
+ as appropriate. Even if either of those is used, or the application
+ explicitly uses the version-specific SSLv2_method() or its client and
+ server variants, SSLv2 ciphers vulnerable to exhaustive search key
+ recovery have been removed. Specifically, the SSLv2 40-bit EXPORT
+ ciphers, and SSLv2 56-bit DES are no longer available.
+ ([CVE-2016-0800])
+
+ *Viktor Dukhovni*
+
+ * Fix a double-free in DSA code
+
+ A double free bug was discovered when OpenSSL parses malformed DSA private
+ keys and could lead to a DoS attack or memory corruption for applications
+ that receive DSA private keys from untrusted sources. This scenario is
+ considered rare.
+
+ This issue was reported to OpenSSL by Adam Langley(Google/BoringSSL) using
+ libFuzzer.
+ ([CVE-2016-0705])
+
+ *Stephen Henson*
+
+ * Disable SRP fake user seed to address a server memory leak.
+
+ Add a new method SRP_VBASE_get1_by_user that handles the seed properly.
+
+ SRP_VBASE_get_by_user had inconsistent memory management behaviour.
+ In order to fix an unavoidable memory leak, SRP_VBASE_get_by_user
+ was changed to ignore the "fake user" SRP seed, even if the seed
+ is configured.
+
+ Users should use SRP_VBASE_get1_by_user instead. Note that in
+ SRP_VBASE_get1_by_user, caller must free the returned value. Note
+ also that even though configuring the SRP seed attempts to hide
+ invalid usernames by continuing the handshake with fake
+ credentials, this behaviour is not constant time and no strong
+ guarantees are made that the handshake is indistinguishable from
+ that of a valid user.
+ ([CVE-2016-0798])
+
+ *Emilia Käsper*
+
+ * Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption
+
+ In the BN_hex2bn function the number of hex digits is calculated using an
+ int value `i`. Later `bn_expand` is called with a value of `i * 4`. For
+ large values of `i` this can result in `bn_expand` not allocating any
+ memory because `i * 4` is negative. This can leave the internal BIGNUM data
+ field as NULL leading to a subsequent NULL ptr deref. For very large values
+ of `i`, the calculation `i * 4` could be a positive value smaller than `i`.
+ In this case memory is allocated to the internal BIGNUM data field, but it
+ is insufficiently sized leading to heap corruption. A similar issue exists
+ in BN_dec2bn. This could have security consequences if BN_hex2bn/BN_dec2bn
+ is ever called by user applications with very large untrusted hex/dec data.
+ This is anticipated to be a rare occurrence.
+
+ All OpenSSL internal usage of these functions use data that is not expected
+ to be untrusted, e.g. config file data or application command line
+ arguments. If user developed applications generate config file data based
+ on untrusted data then it is possible that this could also lead to security
+ consequences. This is also anticipated to be rare.
+
+ This issue was reported to OpenSSL by Guido Vranken.
+ ([CVE-2016-0797])
+
+ *Matt Caswell*
+
+ * Fix memory issues in `BIO_*printf` functions
+
+ The internal `fmtstr` function used in processing a "%s" format string in
+ the `BIO_*printf` functions could overflow while calculating the length of a
+ string and cause an OOB read when printing very long strings.
+
+ Additionally the internal `doapr_outch` function can attempt to write to an
+ OOB memory location (at an offset from the NULL pointer) in the event of a
+ memory allocation failure. In 1.0.2 and below this could be caused where
+ the size of a buffer to be allocated is greater than INT_MAX. E.g. this
+ could be in processing a very long "%s" format string. Memory leaks can
+ also occur.
+
+ The first issue may mask the second issue dependent on compiler behaviour.
+ These problems could enable attacks where large amounts of untrusted data
+ is passed to the `BIO_*printf` functions. If applications use these functions
+ in this way then they could be vulnerable. OpenSSL itself uses these
+ functions when printing out human-readable dumps of ASN.1 data. Therefore
+ applications that print this data could be vulnerable if the data is from
+ untrusted sources. OpenSSL command line applications could also be
+ vulnerable where they print out ASN.1 data, or if untrusted data is passed
+ as command line arguments.
+
+ Libssl is not considered directly vulnerable. Additionally certificates etc
+ received via remote connections via libssl are also unlikely to be able to
+ trigger these issues because of message size limits enforced within libssl.
+
+ This issue was reported to OpenSSL Guido Vranken.
+ ([CVE-2016-0799])
+
+ *Matt Caswell*
+
+ * Side channel attack on modular exponentiation
+
+ A side-channel attack was found which makes use of cache-bank conflicts on
+ the Intel Sandy-Bridge microarchitecture which could lead to the recovery
+ of RSA keys. The ability to exploit this issue is limited as it relies on
+ an attacker who has control of code in a thread running on the same
+ hyper-threaded core as the victim thread which is performing decryptions.
+
+ This issue was reported to OpenSSL by Yuval Yarom, The University of
+ Adelaide and NICTA, Daniel Genkin, Technion and Tel Aviv University, and
+ Nadia Heninger, University of Pennsylvania with more information at
+ <http://cachebleed.info>.
+ ([CVE-2016-0702])
+
+ *Andy Polyakov*
+
+ * Change the `req` command to generate a 2048-bit RSA/DSA key by default,
+ if no keysize is specified with default_bits. This fixes an
+ omission in an earlier change that changed all RSA/DSA key generation
+ commands to use 2048 bits by default.
+
+ *Emilia Käsper*
+
+### Changes between 1.0.2e and 1.0.2f [28 Jan 2016]
+
+ * DH small subgroups
+
+ Historically OpenSSL only ever generated DH parameters based on "safe"
+ primes. More recently (in version 1.0.2) support was provided for
+ generating X9.42 style parameter files such as those required for RFC 5114
+ support. The primes used in such files may not be "safe". Where an
+ application is using DH configured with parameters based on primes that are
+ not "safe" then an attacker could use this fact to find a peer's private
+ DH exponent. This attack requires that the attacker complete multiple
+ handshakes in which the peer uses the same private DH exponent. For example
+ this could be used to discover a TLS server's private DH exponent if it's
+ reusing the private DH exponent or it's using a static DH ciphersuite.
+
+ OpenSSL provides the option SSL_OP_SINGLE_DH_USE for ephemeral DH (DHE) in
+ TLS. It is not on by default. If the option is not set then the server
+ reuses the same private DH exponent for the life of the server process and
+ would be vulnerable to this attack. It is believed that many popular
+ applications do set this option and would therefore not be at risk.
+
+ The fix for this issue adds an additional check where a "q" parameter is
+ available (as is the case in X9.42 based parameters). This detects the
+ only known attack, and is the only possible defense for static DH
+ ciphersuites. This could have some performance impact.
+
+ Additionally the SSL_OP_SINGLE_DH_USE option has been switched on by
+ default and cannot be disabled. This could have some performance impact.
+
+ This issue was reported to OpenSSL by Antonio Sanso (Adobe).
+ ([CVE-2016-0701])
+
+ *Matt Caswell*
+
+ * SSLv2 doesn't block disabled ciphers
+
+ A malicious client can negotiate SSLv2 ciphers that have been disabled on
+ the server and complete SSLv2 handshakes even if all SSLv2 ciphers have
+ been disabled, provided that the SSLv2 protocol was not also disabled via
+ SSL_OP_NO_SSLv2.
+
+ This issue was reported to OpenSSL on 26th December 2015 by Nimrod Aviram
+ and Sebastian Schinzel.
+ ([CVE-2015-3197])
+
+ *Viktor Dukhovni*
+
+### Changes between 1.0.2d and 1.0.2e [3 Dec 2015]
+
+ * BN_mod_exp may produce incorrect results on x86_64
+
+ There is a carry propagating bug in the x86_64 Montgomery squaring
+ procedure. No EC algorithms are affected. Analysis suggests that attacks
+ against RSA and DSA as a result of this defect would be very difficult to
+ perform and are not believed likely. Attacks against DH are considered just
+ feasible (although very difficult) because most of the work necessary to
+ deduce information about a private key may be performed offline. The amount
+ of resources required for such an attack would be very significant and
+ likely only accessible to a limited number of attackers. An attacker would
+ additionally need online access to an unpatched system using the target
+ private key in a scenario with persistent DH parameters and a private
+ key that is shared between multiple clients. For example this can occur by
+ default in OpenSSL DHE based SSL/TLS ciphersuites.
+
+ This issue was reported to OpenSSL by Hanno Böck.
+ ([CVE-2015-3193])
+
+ *Andy Polyakov*
+
+ * Certificate verify crash with missing PSS parameter
+
+ The signature verification routines will crash with a NULL pointer
+ dereference if presented with an ASN.1 signature using the RSA PSS
+ algorithm and absent mask generation function parameter. Since these
+ routines are used to verify certificate signature algorithms this can be
+ used to crash any certificate verification operation and exploited in a
+ DoS attack. Any application which performs certificate verification is
+ vulnerable including OpenSSL clients and servers which enable client
+ authentication.
+
+ This issue was reported to OpenSSL by Loïc Jonas Etienne (Qnective AG).
+ ([CVE-2015-3194])
+
+ *Stephen Henson*
+
+ * X509_ATTRIBUTE memory leak
+
+ When presented with a malformed X509_ATTRIBUTE structure OpenSSL will leak
+ memory. This structure is used by the PKCS#7 and CMS routines so any
+ application which reads PKCS#7 or CMS data from untrusted sources is
+ affected. SSL/TLS is not affected.
+
+ This issue was reported to OpenSSL by Adam Langley (Google/BoringSSL) using
+ libFuzzer.
+ ([CVE-2015-3195])
+
+ *Stephen Henson*
+
+ * Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs.
+ This changes the decoding behaviour for some invalid messages,
+ though the change is mostly in the more lenient direction, and
+ legacy behaviour is preserved as much as possible.
+
+ *Emilia Käsper*
+
+ * In DSA_generate_parameters_ex, if the provided seed is too short,
+ return an error
+
+ *Rich Salz and Ismo Puustinen <ismo.puustinen@intel.com>*
+
+### Changes between 1.0.2c and 1.0.2d [9 Jul 2015]
+
+ * Alternate chains certificate forgery
+
+ During certificate verification, OpenSSL will attempt to find an
+ alternative certificate chain if the first attempt to build such a chain
+ fails. An error in the implementation of this logic can mean that an
+ attacker could cause certain checks on untrusted certificates to be
+ bypassed, such as the CA flag, enabling them to use a valid leaf
+ certificate to act as a CA and "issue" an invalid certificate.
+
+ This issue was reported to OpenSSL by Adam Langley/David Benjamin
+ (Google/BoringSSL).
+
+ *Matt Caswell*
+
+### Changes between 1.0.2b and 1.0.2c [12 Jun 2015]
+
+ * Fix HMAC ABI incompatibility. The previous version introduced an ABI
+ incompatibility in the handling of HMAC. The previous ABI has now been
+ restored.
+
+ *Matt Caswell*
+
+### Changes between 1.0.2a and 1.0.2b [11 Jun 2015]
+
+ * Malformed ECParameters causes infinite loop
+
+ When processing an ECParameters structure OpenSSL enters an infinite loop
+ if the curve specified is over a specially malformed binary polynomial
+ field.
+
+ This can be used to perform denial of service against any
+ system which processes public keys, certificate requests or
+ certificates. This includes TLS clients and TLS servers with
+ client authentication enabled.
+
+ This issue was reported to OpenSSL by Joseph Barr-Pixton.
+ ([CVE-2015-1788])
+
+ *Andy Polyakov*
+
+ * Exploitable out-of-bounds read in X509_cmp_time
+
+ X509_cmp_time does not properly check the length of the ASN1_TIME
+ string and can read a few bytes out of bounds. In addition,
+ X509_cmp_time accepts an arbitrary number of fractional seconds in the
+ time string.
+
+ An attacker can use this to craft malformed certificates and CRLs of
+ various sizes and potentially cause a segmentation fault, resulting in
+ a DoS on applications that verify certificates or CRLs. TLS clients
+ that verify CRLs are affected. TLS clients and servers with client
+ authentication enabled may be affected if they use custom verification
+ callbacks.
+
+ This issue was reported to OpenSSL by Robert Swiecki (Google), and
+ independently by Hanno Böck.
+ ([CVE-2015-1789])
+
+ *Emilia Käsper*
+
+ * PKCS7 crash with missing EnvelopedContent
+
+ The PKCS#7 parsing code does not handle missing inner EncryptedContent
+ correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs
+ with missing content and trigger a NULL pointer dereference on parsing.
+
+ Applications that decrypt PKCS#7 data or otherwise parse PKCS#7
+ structures from untrusted sources are affected. OpenSSL clients and
+ servers are not affected.
+
+ This issue was reported to OpenSSL by Michal Zalewski (Google).
+ ([CVE-2015-1790])
+
+ *Emilia Käsper*
+
+ * CMS verify infinite loop with unknown hash function
+
+ When verifying a signedData message the CMS code can enter an infinite loop
+ if presented with an unknown hash function OID. This can be used to perform
+ denial of service against any system which verifies signedData messages using
+ the CMS code.
+ This issue was reported to OpenSSL by Johannes Bauer.
+ ([CVE-2015-1792])
+
+ *Stephen Henson*
+
+ * Race condition handling NewSessionTicket
+
+ If a NewSessionTicket is received by a multi-threaded client when attempting to
+ reuse a previous ticket then a race condition can occur potentially leading to
+ a double free of the ticket data.
+ ([CVE-2015-1791])
+
+ *Matt Caswell*
+
+ * Only support 256-bit or stronger elliptic curves with the
+ 'ecdh_auto' setting (server) or by default (client). Of supported
+ curves, prefer P-256 (both).
+
+ *Emilia Kasper*
+
+### Changes between 1.0.2 and 1.0.2a [19 Mar 2015]
+
+ * ClientHello sigalgs DoS fix
+
+ If a client connects to an OpenSSL 1.0.2 server and renegotiates with an
+ invalid signature algorithms extension a NULL pointer dereference will
+ occur. This can be exploited in a DoS attack against the server.
+
+ This issue was was reported to OpenSSL by David Ramos of Stanford
+ University.
+ ([CVE-2015-0291])
+
+ *Stephen Henson and Matt Caswell*
+
+ * Multiblock corrupted pointer fix
+
+ OpenSSL 1.0.2 introduced the "multiblock" performance improvement. This
+ feature only applies on 64 bit x86 architecture platforms that support AES
+ NI instructions. A defect in the implementation of "multiblock" can cause
+ OpenSSL's internal write buffer to become incorrectly set to NULL when
+ using non-blocking IO. Typically, when the user application is using a
+ socket BIO for writing, this will only result in a failed connection.
+ However if some other BIO is used then it is likely that a segmentation
+ fault will be triggered, thus enabling a potential DoS attack.
+
+ This issue was reported to OpenSSL by Daniel Danner and Rainer Mueller.
+ ([CVE-2015-0290])
+
+ *Matt Caswell*
+
+ * Segmentation fault in DTLSv1_listen fix
+
+ The DTLSv1_listen function is intended to be stateless and processes the
+ initial ClientHello from many peers. It is common for user code to loop
+ over the call to DTLSv1_listen until a valid ClientHello is received with
+ an associated cookie. A defect in the implementation of DTLSv1_listen means
+ that state is preserved in the SSL object from one invocation to the next
+ that can lead to a segmentation fault. Errors processing the initial
+ ClientHello can trigger this scenario. An example of such an error could be
+ that a DTLS1.0 only client is attempting to connect to a DTLS1.2 only
+ server.
+
+ This issue was reported to OpenSSL by Per Allansson.
+ ([CVE-2015-0207])
+
+ *Matt Caswell*
+
+ * Segmentation fault in ASN1_TYPE_cmp fix
+
+ The function ASN1_TYPE_cmp will crash with an invalid read if an attempt is
+ made to compare ASN.1 boolean types. Since ASN1_TYPE_cmp is used to check
+ certificate signature algorithm consistency this can be used to crash any
+ certificate verification operation and exploited in a DoS attack. Any
+ application which performs certificate verification is vulnerable including
+ OpenSSL clients and servers which enable client authentication.
+ ([CVE-2015-0286])
+
+ *Stephen Henson*
+
+ * Segmentation fault for invalid PSS parameters fix
+
+ The signature verification routines will crash with a NULL pointer
+ dereference if presented with an ASN.1 signature using the RSA PSS
+ algorithm and invalid parameters. Since these routines are used to verify
+ certificate signature algorithms this can be used to crash any
+ certificate verification operation and exploited in a DoS attack. Any
+ application which performs certificate verification is vulnerable including
+ OpenSSL clients and servers which enable client authentication.
+
+ This issue was was reported to OpenSSL by Brian Carpenter.
+ ([CVE-2015-0208])
+
+ *Stephen Henson*
+
+ * ASN.1 structure reuse memory corruption fix
+
+ Reusing a structure in ASN.1 parsing may allow an attacker to cause
+ memory corruption via an invalid write. Such reuse is and has been
+ strongly discouraged and is believed to be rare.
+
+ Applications that parse structures containing CHOICE or ANY DEFINED BY
+ components may be affected. Certificate parsing (d2i_X509 and related
+ functions) are however not affected. OpenSSL clients and servers are
+ not affected.
+ ([CVE-2015-0287])
+
+ *Stephen Henson*
+
+ * PKCS7 NULL pointer dereferences fix
+
+ The PKCS#7 parsing code does not handle missing outer ContentInfo
+ correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs with
+ missing content and trigger a NULL pointer dereference on parsing.
+
+ Applications that verify PKCS#7 signatures, decrypt PKCS#7 data or
+ otherwise parse PKCS#7 structures from untrusted sources are
+ affected. OpenSSL clients and servers are not affected.
+
+ This issue was reported to OpenSSL by Michal Zalewski (Google).
+ ([CVE-2015-0289])
+
+ *Emilia Käsper*
+
+ * DoS via reachable assert in SSLv2 servers fix
+
+ A malicious client can trigger an OPENSSL_assert (i.e., an abort) in
+ servers that both support SSLv2 and enable export cipher suites by sending
+ a specially crafted SSLv2 CLIENT-MASTER-KEY message.
+
+ This issue was discovered by Sean Burford (Google) and Emilia Käsper
+ (OpenSSL development team).
+ ([CVE-2015-0293])
+
+ *Emilia Käsper*
+
+ * Empty CKE with client auth and DHE fix
+
+ If client auth is used then a server can seg fault in the event of a DHE
+ ciphersuite being selected and a zero length ClientKeyExchange message
+ being sent by the client. This could be exploited in a DoS attack.
+ ([CVE-2015-1787])
+
+ *Matt Caswell*
+
+ * Handshake with unseeded PRNG fix
+
+ Under certain conditions an OpenSSL 1.0.2 client can complete a handshake
+ with an unseeded PRNG. The conditions are:
+ - The client is on a platform where the PRNG has not been seeded
+ automatically, and the user has not seeded manually
+ - A protocol specific client method version has been used (i.e. not
+ SSL_client_methodv23)
+ - A ciphersuite is used that does not require additional random data from
+ the PRNG beyond the initial ClientHello client random (e.g. PSK-RC4-SHA).
+
+ If the handshake succeeds then the client random that has been used will
+ have been generated from a PRNG with insufficient entropy and therefore the
+ output may be predictable.
+
+ For example using the following command with an unseeded openssl will
+ succeed on an unpatched platform:
+
+ openssl s_client -psk 1a2b3c4d -tls1_2 -cipher PSK-RC4-SHA
+ ([CVE-2015-0285])
+
+ *Matt Caswell*
+
+ * Use After Free following d2i_ECPrivatekey error fix
+
+ A malformed EC private key file consumed via the d2i_ECPrivateKey function
+ could cause a use after free condition. This, in turn, could cause a double
+ free in several private key parsing functions (such as d2i_PrivateKey
+ or EVP_PKCS82PKEY) and could lead to a DoS attack or memory corruption
+ for applications that receive EC private keys from untrusted
+ sources. This scenario is considered rare.
+
+ This issue was discovered by the BoringSSL project and fixed in their
+ commit 517073cd4b.
+ ([CVE-2015-0209])
+
+ *Matt Caswell*
+
+ * X509_to_X509_REQ NULL pointer deref fix
+
+ The function X509_to_X509_REQ will crash with a NULL pointer dereference if
+ the certificate key is invalid. This function is rarely used in practice.
+
+ This issue was discovered by Brian Carpenter.
+ ([CVE-2015-0288])
+
+ *Stephen Henson*
+
+ * Removed the export ciphers from the DEFAULT ciphers
+
+ *Kurt Roeckx*
+
+### Changes between 1.0.1l and 1.0.2 [22 Jan 2015]
+
+ * Facilitate "universal" ARM builds targeting range of ARM ISAs, e.g.
+ ARMv5 through ARMv8, as opposite to "locking" it to single one.
+ So far those who have to target multiple platforms would compromise
+ and argue that binary targeting say ARMv5 would still execute on
+ ARMv8. "Universal" build resolves this compromise by providing
+ near-optimal performance even on newer platforms.
+
+ *Andy Polyakov*
+
+ * Accelerated NIST P-256 elliptic curve implementation for x86_64
+ (other platforms pending).
+
+ *Shay Gueron & Vlad Krasnov (Intel Corp), Andy Polyakov*
+
+ * Add support for the SignedCertificateTimestampList certificate and
+ OCSP response extensions from RFC6962.
+
+ *Rob Stradling*
+
+ * Fix ec_GFp_simple_points_make_affine (thus, EC_POINTs_mul etc.)
+ for corner cases. (Certain input points at infinity could lead to
+ bogus results, with non-infinity inputs mapped to infinity too.)
+
+ *Bodo Moeller*
+
+ * Initial support for PowerISA 2.0.7, first implemented in POWER8.
+ This covers AES, SHA256/512 and GHASH. "Initial" means that most
+ common cases are optimized and there still is room for further
+ improvements. Vector Permutation AES for Altivec is also added.
+
+ *Andy Polyakov*
+
+ * Add support for little-endian ppc64 Linux target.
+
+ *Marcelo Cerri (IBM)*
+
+ * Initial support for AMRv8 ISA crypto extensions. This covers AES,
+ SHA1, SHA256 and GHASH. "Initial" means that most common cases
+ are optimized and there still is room for further improvements.
+ Both 32- and 64-bit modes are supported.
+
+ *Andy Polyakov, Ard Biesheuvel (Linaro)*
+
+ * Improved ARMv7 NEON support.
+
+ *Andy Polyakov*
+
+ * Support for SPARC Architecture 2011 crypto extensions, first
+ implemented in SPARC T4. This covers AES, DES, Camellia, SHA1,
+ SHA256/512, MD5, GHASH and modular exponentiation.
+
+ *Andy Polyakov, David Miller*
+
+ * Accelerated modular exponentiation for Intel processors, a.k.a.
+ RSAZ.
+
+ *Shay Gueron & Vlad Krasnov (Intel Corp)*
+
+ * Support for new and upcoming Intel processors, including AVX2,
+ BMI and SHA ISA extensions. This includes additional "stitched"
+ implementations, AESNI-SHA256 and GCM, and multi-buffer support
+ for TLS encrypt.
+
+ This work was sponsored by Intel Corp.
+
+ *Andy Polyakov*
+
+ * Support for DTLS 1.2. This adds two sets of DTLS methods: DTLS_*_method()
+ supports both DTLS 1.2 and 1.0 and should use whatever version the peer
+ supports and DTLSv1_2_*_method() which supports DTLS 1.2 only.
+
+ *Steve Henson*
+
+ * Use algorithm specific chains in SSL_CTX_use_certificate_chain_file():
+ this fixes a limitation in previous versions of OpenSSL.
+
+ *Steve Henson*
+
+ * Extended RSA OAEP support via EVP_PKEY API. Options to specify digest,
+ MGF1 digest and OAEP label.
+
+ *Steve Henson*
+
+ * Add EVP support for key wrapping algorithms, to avoid problems with
+ existing code the flag EVP_CIPHER_CTX_WRAP_ALLOW has to be set in
+ the EVP_CIPHER_CTX or an error is returned. Add AES and DES3 wrap
+ algorithms and include tests cases.
+
+ *Steve Henson*
+
+ * Add functions to allocate and set the fields of an ECDSA_METHOD
+ structure.
+
+ *Douglas E. Engert, Steve Henson*
+
+ * New functions OPENSSL_gmtime_diff and ASN1_TIME_diff to find the
+ difference in days and seconds between two tm or ASN1_TIME structures.
+
+ *Steve Henson*
+
+ * Add -rev test option to s_server to just reverse order of characters
+ received by client and send back to server. Also prints an abbreviated
+ summary of the connection parameters.
+
+ *Steve Henson*
+
+ * New option -brief for s_client and s_server to print out a brief summary
+ of connection parameters.
+
+ *Steve Henson*
+
+ * Add callbacks for arbitrary TLS extensions.
+
+ *Trevor Perrin <trevp@trevp.net> and Ben Laurie*
+
+ * New option -crl_download in several openssl utilities to download CRLs
+ from CRLDP extension in certificates.
+
+ *Steve Henson*
+
+ * New options -CRL and -CRLform for s_client and s_server for CRLs.
+
+ *Steve Henson*
+
+ * New function X509_CRL_diff to generate a delta CRL from the difference
+ of two full CRLs. Add support to "crl" utility.
+
+ *Steve Henson*
+
+ * New functions to set lookup_crls function and to retrieve
+ X509_STORE from X509_STORE_CTX.
+
+ *Steve Henson*
+
+ * Print out deprecated issuer and subject unique ID fields in
+ certificates.
+
+ *Steve Henson*
+
+ * Extend OCSP I/O functions so they can be used for simple general purpose
+ HTTP as well as OCSP. New wrapper function which can be used to download
+ CRLs using the OCSP API.
+
+ *Steve Henson*
+
+ * Delegate command line handling in s_client/s_server to SSL_CONF APIs.
+
+ *Steve Henson*
+
+ * `SSL_CONF*` functions. These provide a common framework for application
+ configuration using configuration files or command lines.
+
+ *Steve Henson*
+
+ * SSL/TLS tracing code. This parses out SSL/TLS records using the
+ message callback and prints the results. Needs compile time option
+ "enable-ssl-trace". New options to s_client and s_server to enable
+ tracing.
+
+ *Steve Henson*
+
+ * New ctrl and macro to retrieve supported points extensions.
+ Print out extension in s_server and s_client.
+
+ *Steve Henson*
+
+ * New functions to retrieve certificate signature and signature
+ OID NID.
+
+ *Steve Henson*
+
+ * Add functions to retrieve and manipulate the raw cipherlist sent by a
+ client to OpenSSL.
+
+ *Steve Henson*
+
+ * New Suite B modes for TLS code. These use and enforce the requirements
+ of RFC6460: restrict ciphersuites, only permit Suite B algorithms and
+ only use Suite B curves. The Suite B modes can be set by using the
+ strings "SUITEB128", "SUITEB192" or "SUITEB128ONLY" for the cipherstring.
+
+ *Steve Henson*
+
+ * New chain verification flags for Suite B levels of security. Check
+ algorithms are acceptable when flags are set in X509_verify_cert.
+
+ *Steve Henson*
+
+ * Make tls1_check_chain return a set of flags indicating checks passed
+ by a certificate chain. Add additional tests to handle client
+ certificates: checks for matching certificate type and issuer name
+ comparison.
+
+ *Steve Henson*
+
+ * If an attempt is made to use a signature algorithm not in the peer
+ preference list abort the handshake. If client has no suitable
+ signature algorithms in response to a certificate request do not
+ use the certificate.
+
+ *Steve Henson*
+
+ * If server EC tmp key is not in client preference list abort handshake.
+
+ *Steve Henson*
+
+ * Add support for certificate stores in CERT structure. This makes it
+ possible to have different stores per SSL structure or one store in
+ the parent SSL_CTX. Include distinct stores for certificate chain
+ verification and chain building. New ctrl SSL_CTRL_BUILD_CERT_CHAIN
+ to build and store a certificate chain in CERT structure: returning
+ an error if the chain cannot be built: this will allow applications
+ to test if a chain is correctly configured.
+
+ Note: if the CERT based stores are not set then the parent SSL_CTX
+ store is used to retain compatibility with existing behaviour.
+
+ *Steve Henson*
+
+ * New function ssl_set_client_disabled to set a ciphersuite disabled
+ mask based on the current session, check mask when sending client
+ hello and checking the requested ciphersuite.
+
+ *Steve Henson*
+
+ * New ctrls to retrieve and set certificate types in a certificate
+ request message. Print out received values in s_client. If certificate
+ types is not set with custom values set sensible values based on
+ supported signature algorithms.
+
+ *Steve Henson*
+
+ * Support for distinct client and server supported signature algorithms.
+
+ *Steve Henson*
+
+ * Add certificate callback. If set this is called whenever a certificate
+ is required by client or server. An application can decide which
+ certificate chain to present based on arbitrary criteria: for example
+ supported signature algorithms. Add very simple example to s_server.
+ This fixes many of the problems and restrictions of the existing client
+ certificate callback: for example you can now clear an existing
+ certificate and specify the whole chain.
+
+ *Steve Henson*
+
+ * Add new "valid_flags" field to CERT_PKEY structure which determines what
+ the certificate can be used for (if anything). Set valid_flags field
+ in new tls1_check_chain function. Simplify ssl_set_cert_masks which used
+ to have similar checks in it.
+
+ Add new "cert_flags" field to CERT structure and include a "strict mode".
+ This enforces some TLS certificate requirements (such as only permitting
+ certificate signature algorithms contained in the supported algorithms
+ extension) which some implementations ignore: this option should be used
+ with caution as it could cause interoperability issues.
+
+ *Steve Henson*
+
+ * Update and tidy signature algorithm extension processing. Work out
+ shared signature algorithms based on preferences and peer algorithms
+ and print them out in s_client and s_server. Abort handshake if no
+ shared signature algorithms.
+
+ *Steve Henson*
+
+ * Add new functions to allow customised supported signature algorithms
+ for SSL and SSL_CTX structures. Add options to s_client and s_server
+ to support them.
+
+ *Steve Henson*
+
+ * New function SSL_certs_clear() to delete all references to certificates
+ from an SSL structure. Before this once a certificate had been added
+ it couldn't be removed.
+
+ *Steve Henson*
+
+ * Integrate hostname, email address and IP address checking with certificate
+ verification. New verify options supporting checking in openssl utility.
+
+ *Steve Henson*
+
+ * Fixes and wildcard matching support to hostname and email checking
+ functions. Add manual page.
+
+ *Florian Weimer (Red Hat Product Security Team)*
+
+ * New functions to check a hostname email or IP address against a
+ certificate. Add options x509 utility to print results of checks against
+ a certificate.
+
+ *Steve Henson*
+
+ * Fix OCSP checking.
+
+ *Rob Stradling <rob.stradling@comodo.com> and Ben Laurie*
+
+ * Initial experimental support for explicitly trusted non-root CAs.
+ OpenSSL still tries to build a complete chain to a root but if an
+ intermediate CA has a trust setting included that is used. The first
+ setting is used: whether to trust (e.g., -addtrust option to the x509
+ utility) or reject.
+
+ *Steve Henson*
+
+ * Add -trusted_first option which attempts to find certificates in the
+ trusted store even if an untrusted chain is also supplied.
+
+ *Steve Henson*
+
+ * MIPS assembly pack updates: support for MIPS32r2 and SmartMIPS ASE,
+ platform support for Linux and Android.
+
+ *Andy Polyakov*
+
+ * Support for linux-x32, ILP32 environment in x86_64 framework.
+
+ *Andy Polyakov*
+
+ * Experimental multi-implementation support for FIPS capable OpenSSL.
+ When in FIPS mode the approved implementations are used as normal,
+ when not in FIPS mode the internal unapproved versions are used instead.
+ This means that the FIPS capable OpenSSL isn't forced to use the
+ (often lower performance) FIPS implementations outside FIPS mode.
+
+ *Steve Henson*
+
+ * Transparently support X9.42 DH parameters when calling
+ PEM_read_bio_DHparameters. This means existing applications can handle
+ the new parameter format automatically.
+
+ *Steve Henson*
+
+ * Initial experimental support for X9.42 DH parameter format: mainly
+ to support use of 'q' parameter for RFC5114 parameters.
+
+ *Steve Henson*
+
+ * Add DH parameters from RFC5114 including test data to dhtest.
+
+ *Steve Henson*
+
+ * Support for automatic EC temporary key parameter selection. If enabled
+ the most preferred EC parameters are automatically used instead of
+ hardcoded fixed parameters. Now a server just has to call:
+ SSL_CTX_set_ecdh_auto(ctx, 1) and the server will automatically
+ support ECDH and use the most appropriate parameters.
+
+ *Steve Henson*
+
+ * Enhance and tidy EC curve and point format TLS extension code. Use
+ static structures instead of allocation if default values are used.
+ New ctrls to set curves we wish to support and to retrieve shared curves.
+ Print out shared curves in s_server. New options to s_server and s_client
+ to set list of supported curves.
+
+ *Steve Henson*
+
+ * New ctrls to retrieve supported signature algorithms and
+ supported curve values as an array of NIDs. Extend openssl utility
+ to print out received values.
+
+ *Steve Henson*
+
+ * Add new APIs EC_curve_nist2nid and EC_curve_nid2nist which convert
+ between NIDs and the more common NIST names such as "P-256". Enhance
+ ecparam utility and ECC method to recognise the NIST names for curves.
+
+ *Steve Henson*
+
+ * Enhance SSL/TLS certificate chain handling to support different
+ chains for each certificate instead of one chain in the parent SSL_CTX.
+
+ *Steve Henson*
+
+ * Support for fixed DH ciphersuite client authentication: where both
+ server and client use DH certificates with common parameters.
+
+ *Steve Henson*
+
+ * Support for fixed DH ciphersuites: those requiring DH server
+ certificates.
+
+ *Steve Henson*
+
+ * New function i2d_re_X509_tbs for re-encoding the TBS portion of
+ the certificate.
+ Note: Related 1.0.2-beta specific macros X509_get_cert_info,
+ X509_CINF_set_modified, X509_CINF_get_issuer, X509_CINF_get_extensions and
+ X509_CINF_get_signature were reverted post internal team review.
+
+OpenSSL 1.0.1
+-------------
+
+### Changes between 1.0.1t and 1.0.1u [22 Sep 2016]
+
+ * OCSP Status Request extension unbounded memory growth
+
+ A malicious client can send an excessively large OCSP Status Request
+ extension. If that client continually requests renegotiation, sending a
+ large OCSP Status Request extension each time, then there will be unbounded
+ memory growth on the server. This will eventually lead to a Denial Of
+ Service attack through memory exhaustion. Servers with a default
+ configuration are vulnerable even if they do not support OCSP. Builds using
+ the "no-ocsp" build time option are not affected.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ ([CVE-2016-6304])
+
+ *Matt Caswell*
+
+ * In order to mitigate the SWEET32 attack, the DES ciphers were moved from
+ HIGH to MEDIUM.
+
+ This issue was reported to OpenSSL Karthikeyan Bhargavan and Gaetan
+ Leurent (INRIA)
+ ([CVE-2016-2183])
+
+ *Rich Salz*
+
+ * OOB write in MDC2_Update()
+
+ An overflow can occur in MDC2_Update() either if called directly or
+ through the EVP_DigestUpdate() function using MDC2. If an attacker
+ is able to supply very large amounts of input data after a previous
+ call to EVP_EncryptUpdate() with a partial block then a length check
+ can overflow resulting in a heap corruption.
+
+ The amount of data needed is comparable to SIZE_MAX which is impractical
+ on most platforms.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ ([CVE-2016-6303])
+
+ *Stephen Henson*
+
+ * Malformed SHA512 ticket DoS
+
+ If a server uses SHA512 for TLS session ticket HMAC it is vulnerable to a
+ DoS attack where a malformed ticket will result in an OOB read which will
+ ultimately crash.
+
+ The use of SHA512 in TLS session tickets is comparatively rare as it requires
+ a custom server callback and ticket lookup mechanism.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ ([CVE-2016-6302])
+
+ *Stephen Henson*
+
+ * OOB write in BN_bn2dec()
+
+ The function BN_bn2dec() does not check the return value of BN_div_word().
+ This can cause an OOB write if an application uses this function with an
+ overly large BIGNUM. This could be a problem if an overly large certificate
+ or CRL is printed out from an untrusted source. TLS is not affected because
+ record limits will reject an oversized certificate before it is parsed.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ ([CVE-2016-2182])
+
+ *Stephen Henson*
+
+ * OOB read in TS_OBJ_print_bio()
+
+ The function TS_OBJ_print_bio() misuses OBJ_obj2txt(): the return value is
+ the total length the OID text representation would use and not the amount
+ of data written. This will result in OOB reads when large OIDs are
+ presented.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ ([CVE-2016-2180])
+
+ *Stephen Henson*
+
+ * Pointer arithmetic undefined behaviour
+
+ Avoid some undefined pointer arithmetic
+
+ A common idiom in the codebase is to check limits in the following manner:
+ "p + len > limit"
+
+ Where "p" points to some malloc'd data of SIZE bytes and
+ limit == p + SIZE
+
+ "len" here could be from some externally supplied data (e.g. from a TLS
+ message).
+
+ The rules of C pointer arithmetic are such that "p + len" is only well
+ defined where len <= SIZE. Therefore the above idiom is actually
+ undefined behaviour.
+
+ For example this could cause problems if some malloc implementation
+ provides an address for "p" such that "p + len" actually overflows for
+ values of len that are too big and therefore p + len < limit.
+
+ This issue was reported to OpenSSL by Guido Vranken
+ ([CVE-2016-2177])
+
+ *Matt Caswell*
+
+ * Constant time flag not preserved in DSA signing
+
+ Operations in the DSA signing algorithm should run in constant time in
+ order to avoid side channel attacks. A flaw in the OpenSSL DSA
+ implementation means that a non-constant time codepath is followed for
+ certain operations. This has been demonstrated through a cache-timing
+ attack to be sufficient for an attacker to recover the private DSA key.
+
+ This issue was reported by César Pereida (Aalto University), Billy Brumley
+ (Tampere University of Technology), and Yuval Yarom (The University of
+ Adelaide and NICTA).
+ ([CVE-2016-2178])
+
+ *César Pereida*
+
+ * DTLS buffered message DoS
+
+ In a DTLS connection where handshake messages are delivered out-of-order
+ those messages that OpenSSL is not yet ready to process will be buffered
+ for later use. Under certain circumstances, a flaw in the logic means that
+ those messages do not get removed from the buffer even though the handshake
+ has been completed. An attacker could force up to approx. 15 messages to
+ remain in the buffer when they are no longer required. These messages will
+ be cleared when the DTLS connection is closed. The default maximum size for
+ a message is 100k. Therefore the attacker could force an additional 1500k
+ to be consumed per connection. By opening many simulataneous connections an
+ attacker could cause a DoS attack through memory exhaustion.
+
+ This issue was reported to OpenSSL by Quan Luo.
+ ([CVE-2016-2179])
+
+ *Matt Caswell*
+
+ * DTLS replay protection DoS
+
+ A flaw in the DTLS replay attack protection mechanism means that records
+ that arrive for future epochs update the replay protection "window" before
+ the MAC for the record has been validated. This could be exploited by an
+ attacker by sending a record for the next epoch (which does not have to
+ decrypt or have a valid MAC), with a very large sequence number. This means
+ that all subsequent legitimate packets are dropped causing a denial of
+ service for a specific DTLS connection.
+
+ This issue was reported to OpenSSL by the OCAP audit team.
+ ([CVE-2016-2181])
+
+ *Matt Caswell*
+
+ * Certificate message OOB reads
+
+ In OpenSSL 1.0.2 and earlier some missing message length checks can result
+ in OOB reads of up to 2 bytes beyond an allocated buffer. There is a
+ theoretical DoS risk but this has not been observed in practice on common
+ platforms.
+
+ The messages affected are client certificate, client certificate request
+ and server certificate. As a result the attack can only be performed
+ against a client or a server which enables client authentication.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ ([CVE-2016-6306])
+
+ *Stephen Henson*
+
+### Changes between 1.0.1s and 1.0.1t [3 May 2016]
+
+ * Prevent padding oracle in AES-NI CBC MAC check
+
+ A MITM attacker can use a padding oracle attack to decrypt traffic
+ when the connection uses an AES CBC cipher and the server support
+ AES-NI.
+
+ This issue was introduced as part of the fix for Lucky 13 padding
+ attack ([CVE-2013-0169]). The padding check was rewritten to be in
+ constant time by making sure that always the same bytes are read and
+ compared against either the MAC or padding bytes. But it no longer
+ checked that there was enough data to have both the MAC and padding
+ bytes.
+
+ This issue was reported by Juraj Somorovsky using TLS-Attacker.
+ ([CVE-2016-2107])
+
+ *Kurt Roeckx*
+
+ * Fix EVP_EncodeUpdate overflow
+
+ An overflow can occur in the EVP_EncodeUpdate() function which is used for
+ Base64 encoding of binary data. If an attacker is able to supply very large
+ amounts of input data then a length check can overflow resulting in a heap
+ corruption.
+
+ Internally to OpenSSL the EVP_EncodeUpdate() function is primarly used by
+ the `PEM_write_bio*` family of functions. These are mainly used within the
+ OpenSSL command line applications, so any application which processes data
+ from an untrusted source and outputs it as a PEM file should be considered
+ vulnerable to this issue. User applications that call these APIs directly
+ with large amounts of untrusted data may also be vulnerable.
+
+ This issue was reported by Guido Vranken.
+ ([CVE-2016-2105])
+
+ *Matt Caswell*
+
+ * Fix EVP_EncryptUpdate overflow
+
+ An overflow can occur in the EVP_EncryptUpdate() function. If an attacker
+ is able to supply very large amounts of input data after a previous call to
+ EVP_EncryptUpdate() with a partial block then a length check can overflow
+ resulting in a heap corruption. Following an analysis of all OpenSSL
+ internal usage of the EVP_EncryptUpdate() function all usage is one of two
+ forms. The first form is where the EVP_EncryptUpdate() call is known to be
+ the first called function after an EVP_EncryptInit(), and therefore that
+ specific call must be safe. The second form is where the length passed to
+ EVP_EncryptUpdate() can be seen from the code to be some small value and
+ therefore there is no possibility of an overflow. Since all instances are
+ one of these two forms, it is believed that there can be no overflows in
+ internal code due to this problem. It should be noted that
+ EVP_DecryptUpdate() can call EVP_EncryptUpdate() in certain code paths.
+ Also EVP_CipherUpdate() is a synonym for EVP_EncryptUpdate(). All instances
+ of these calls have also been analysed too and it is believed there are no
+ instances in internal usage where an overflow could occur.
+
+ This issue was reported by Guido Vranken.
+ ([CVE-2016-2106])
+
+ *Matt Caswell*
+
+ * Prevent ASN.1 BIO excessive memory allocation
+
+ When ASN.1 data is read from a BIO using functions such as d2i_CMS_bio()
+ a short invalid encoding can casuse allocation of large amounts of memory
+ potentially consuming excessive resources or exhausting memory.
+
+ Any application parsing untrusted data through d2i BIO functions is
+ affected. The memory based functions such as d2i_X509() are *not* affected.
+ Since the memory based functions are used by the TLS library, TLS
+ applications are not affected.
+
+ This issue was reported by Brian Carpenter.
+ ([CVE-2016-2109])
+
+ *Stephen Henson*
+
+ * EBCDIC overread
+
+ ASN1 Strings that are over 1024 bytes can cause an overread in applications
+ using the X509_NAME_oneline() function on EBCDIC systems. This could result
+ in arbitrary stack data being returned in the buffer.
+
+ This issue was reported by Guido Vranken.
+ ([CVE-2016-2176])
+
+ *Matt Caswell*
+
+ * Modify behavior of ALPN to invoke callback after SNI/servername
+ callback, such that updates to the SSL_CTX affect ALPN.
+
+ *Todd Short*
+
+ * Remove LOW from the DEFAULT cipher list. This removes singles DES from the
+ default.
+
+ *Kurt Roeckx*
+
+ * Only remove the SSLv2 methods with the no-ssl2-method option. When the
+ methods are enabled and ssl2 is disabled the methods return NULL.
+
+ *Kurt Roeckx*
+
+### Changes between 1.0.1r and 1.0.1s [1 Mar 2016]
+
+* Disable weak ciphers in SSLv3 and up in default builds of OpenSSL.
+ Builds that are not configured with "enable-weak-ssl-ciphers" will not
+ provide any "EXPORT" or "LOW" strength ciphers.
+
+ *Viktor Dukhovni*
+
+* Disable SSLv2 default build, default negotiation and weak ciphers. SSLv2
+ is by default disabled at build-time. Builds that are not configured with
+ "enable-ssl2" will not support SSLv2. Even if "enable-ssl2" is used,
+ users who want to negotiate SSLv2 via the version-flexible SSLv23_method()
+ will need to explicitly call either of:
+
+ SSL_CTX_clear_options(ctx, SSL_OP_NO_SSLv2);
+ or
+ SSL_clear_options(ssl, SSL_OP_NO_SSLv2);
+
+ as appropriate. Even if either of those is used, or the application
+ explicitly uses the version-specific SSLv2_method() or its client and
+ server variants, SSLv2 ciphers vulnerable to exhaustive search key
+ recovery have been removed. Specifically, the SSLv2 40-bit EXPORT
+ ciphers, and SSLv2 56-bit DES are no longer available.
+ ([CVE-2016-0800])
+
+ *Viktor Dukhovni*
+
+ * Fix a double-free in DSA code
+
+ A double free bug was discovered when OpenSSL parses malformed DSA private
+ keys and could lead to a DoS attack or memory corruption for applications
+ that receive DSA private keys from untrusted sources. This scenario is
+ considered rare.
+
+ This issue was reported to OpenSSL by Adam Langley(Google/BoringSSL) using
+ libFuzzer.
+ ([CVE-2016-0705])
+
+ *Stephen Henson*
+
+ * Disable SRP fake user seed to address a server memory leak.
+
+ Add a new method SRP_VBASE_get1_by_user that handles the seed properly.
+
+ SRP_VBASE_get_by_user had inconsistent memory management behaviour.
+ In order to fix an unavoidable memory leak, SRP_VBASE_get_by_user
+ was changed to ignore the "fake user" SRP seed, even if the seed
+ is configured.
+
+ Users should use SRP_VBASE_get1_by_user instead. Note that in
+ SRP_VBASE_get1_by_user, caller must free the returned value. Note
+ also that even though configuring the SRP seed attempts to hide
+ invalid usernames by continuing the handshake with fake
+ credentials, this behaviour is not constant time and no strong
+ guarantees are made that the handshake is indistinguishable from
+ that of a valid user.
+ ([CVE-2016-0798])
+
+ *Emilia Käsper*
+
+ * Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption
+
+ In the BN_hex2bn function the number of hex digits is calculated using an
+ int value `i`. Later `bn_expand` is called with a value of `i * 4`. For
+ large values of `i` this can result in `bn_expand` not allocating any
+ memory because `i * 4` is negative. This can leave the internal BIGNUM data
+ field as NULL leading to a subsequent NULL ptr deref. For very large values
+ of `i`, the calculation `i * 4` could be a positive value smaller than `i`.
+ In this case memory is allocated to the internal BIGNUM data field, but it
+ is insufficiently sized leading to heap corruption. A similar issue exists
+ in BN_dec2bn. This could have security consequences if BN_hex2bn/BN_dec2bn
+ is ever called by user applications with very large untrusted hex/dec data.
+ This is anticipated to be a rare occurrence.
+
+ All OpenSSL internal usage of these functions use data that is not expected
+ to be untrusted, e.g. config file data or application command line
+ arguments. If user developed applications generate config file data based
+ on untrusted data then it is possible that this could also lead to security
+ consequences. This is also anticipated to be rare.
+
+ This issue was reported to OpenSSL by Guido Vranken.
+ ([CVE-2016-0797])
+
+ *Matt Caswell*
+
+ * Fix memory issues in `BIO_*printf` functions
+
+ The internal `fmtstr` function used in processing a "%s" format string in
+ the `BIO_*printf` functions could overflow while calculating the length of a
+ string and cause an OOB read when printing very long strings.
+
+ Additionally the internal `doapr_outch` function can attempt to write to an
+ OOB memory location (at an offset from the NULL pointer) in the event of a
+ memory allocation failure. In 1.0.2 and below this could be caused where
+ the size of a buffer to be allocated is greater than INT_MAX. E.g. this
+ could be in processing a very long "%s" format string. Memory leaks can
+ also occur.
+
+ The first issue may mask the second issue dependent on compiler behaviour.
+ These problems could enable attacks where large amounts of untrusted data
+ is passed to the `BIO_*printf` functions. If applications use these functions
+ in this way then they could be vulnerable. OpenSSL itself uses these
+ functions when printing out human-readable dumps of ASN.1 data. Therefore
+ applications that print this data could be vulnerable if the data is from
+ untrusted sources. OpenSSL command line applications could also be
+ vulnerable where they print out ASN.1 data, or if untrusted data is passed
+ as command line arguments.
+
+ Libssl is not considered directly vulnerable. Additionally certificates etc
+ received via remote connections via libssl are also unlikely to be able to
+ trigger these issues because of message size limits enforced within libssl.
+
+ This issue was reported to OpenSSL Guido Vranken.
+ ([CVE-2016-0799])
+
+ *Matt Caswell*
+
+ * Side channel attack on modular exponentiation
+
+ A side-channel attack was found which makes use of cache-bank conflicts on
+ the Intel Sandy-Bridge microarchitecture which could lead to the recovery
+ of RSA keys. The ability to exploit this issue is limited as it relies on
+ an attacker who has control of code in a thread running on the same
+ hyper-threaded core as the victim thread which is performing decryptions.
+
+ This issue was reported to OpenSSL by Yuval Yarom, The University of
+ Adelaide and NICTA, Daniel Genkin, Technion and Tel Aviv University, and
+ Nadia Heninger, University of Pennsylvania with more information at
+ <http://cachebleed.info>.
+ ([CVE-2016-0702])
+
+ *Andy Polyakov*
+
+ * Change the req command to generate a 2048-bit RSA/DSA key by default,
+ if no keysize is specified with default_bits. This fixes an
+ omission in an earlier change that changed all RSA/DSA key generation
+ commands to use 2048 bits by default.
+
+ *Emilia Käsper*
+
+### Changes between 1.0.1q and 1.0.1r [28 Jan 2016]
+
+ * Protection for DH small subgroup attacks
+
+ As a precautionary measure the SSL_OP_SINGLE_DH_USE option has been
+ switched on by default and cannot be disabled. This could have some
+ performance impact.
+
+ *Matt Caswell*
+
+ * SSLv2 doesn't block disabled ciphers
+
+ A malicious client can negotiate SSLv2 ciphers that have been disabled on
+ the server and complete SSLv2 handshakes even if all SSLv2 ciphers have
+ been disabled, provided that the SSLv2 protocol was not also disabled via
+ SSL_OP_NO_SSLv2.
+
+ This issue was reported to OpenSSL on 26th December 2015 by Nimrod Aviram
+ and Sebastian Schinzel.
+ ([CVE-2015-3197])
+
+ *Viktor Dukhovni*
+
+ * Reject DH handshakes with parameters shorter than 1024 bits.
+
+ *Kurt Roeckx*
+
+### Changes between 1.0.1p and 1.0.1q [3 Dec 2015]
+
+ * Certificate verify crash with missing PSS parameter
+
+ The signature verification routines will crash with a NULL pointer
+ dereference if presented with an ASN.1 signature using the RSA PSS
+ algorithm and absent mask generation function parameter. Since these
+ routines are used to verify certificate signature algorithms this can be
+ used to crash any certificate verification operation and exploited in a
+ DoS attack. Any application which performs certificate verification is
+ vulnerable including OpenSSL clients and servers which enable client
+ authentication.
+
+ This issue was reported to OpenSSL by Loïc Jonas Etienne (Qnective AG).
+ ([CVE-2015-3194])
+
+ *Stephen Henson*
+
+ * X509_ATTRIBUTE memory leak
+
+ When presented with a malformed X509_ATTRIBUTE structure OpenSSL will leak
+ memory. This structure is used by the PKCS#7 and CMS routines so any
+ application which reads PKCS#7 or CMS data from untrusted sources is
+ affected. SSL/TLS is not affected.
+
+ This issue was reported to OpenSSL by Adam Langley (Google/BoringSSL) using
+ libFuzzer.
+ ([CVE-2015-3195])
+
+ *Stephen Henson*
+
+ * Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs.
+ This changes the decoding behaviour for some invalid messages,
+ though the change is mostly in the more lenient direction, and
+ legacy behaviour is preserved as much as possible.
+
+ *Emilia Käsper*
+
+ * In DSA_generate_parameters_ex, if the provided seed is too short,
+ use a random seed, as already documented.
+
+ *Rich Salz and Ismo Puustinen <ismo.puustinen@intel.com>*
+
+### Changes between 1.0.1o and 1.0.1p [9 Jul 2015]
+
+ * Alternate chains certificate forgery
+
+ During certificate verfification, OpenSSL will attempt to find an
+ alternative certificate chain if the first attempt to build such a chain
+ fails. An error in the implementation of this logic can mean that an
+ attacker could cause certain checks on untrusted certificates to be
+ bypassed, such as the CA flag, enabling them to use a valid leaf
+ certificate to act as a CA and "issue" an invalid certificate.
+
+ This issue was reported to OpenSSL by Adam Langley/David Benjamin
+ (Google/BoringSSL).
+ ([CVE-2015-1793])
+
+ *Matt Caswell*
+
+ * Race condition handling PSK identify hint
+
+ If PSK identity hints are received by a multi-threaded client then
+ the values are wrongly updated in the parent SSL_CTX structure. This can
+ result in a race condition potentially leading to a double free of the
+ identify hint data.
+ ([CVE-2015-3196])
+
+ *Stephen Henson*
+
+### Changes between 1.0.1n and 1.0.1o [12 Jun 2015]
+
+ * Fix HMAC ABI incompatibility. The previous version introduced an ABI
+ incompatibility in the handling of HMAC. The previous ABI has now been
+ restored.
+
+### Changes between 1.0.1m and 1.0.1n [11 Jun 2015]
+
+ * Malformed ECParameters causes infinite loop
+
+ When processing an ECParameters structure OpenSSL enters an infinite loop
+ if the curve specified is over a specially malformed binary polynomial
+ field.
+
+ This can be used to perform denial of service against any
+ system which processes public keys, certificate requests or
+ certificates. This includes TLS clients and TLS servers with
+ client authentication enabled.
+
+ This issue was reported to OpenSSL by Joseph Barr-Pixton.
+ ([CVE-2015-1788])
+
+ *Andy Polyakov*
+
+ * Exploitable out-of-bounds read in X509_cmp_time
+
+ X509_cmp_time does not properly check the length of the ASN1_TIME
+ string and can read a few bytes out of bounds. In addition,
+ X509_cmp_time accepts an arbitrary number of fractional seconds in the
+ time string.
+
+ An attacker can use this to craft malformed certificates and CRLs of
+ various sizes and potentially cause a segmentation fault, resulting in
+ a DoS on applications that verify certificates or CRLs. TLS clients
+ that verify CRLs are affected. TLS clients and servers with client
+ authentication enabled may be affected if they use custom verification
+ callbacks.
+
+ This issue was reported to OpenSSL by Robert Swiecki (Google), and
+ independently by Hanno Böck.
+ ([CVE-2015-1789])
+
+ *Emilia Käsper*
+
+ * PKCS7 crash with missing EnvelopedContent
+
+ The PKCS#7 parsing code does not handle missing inner EncryptedContent
+ correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs
+ with missing content and trigger a NULL pointer dereference on parsing.
+
+ Applications that decrypt PKCS#7 data or otherwise parse PKCS#7
+ structures from untrusted sources are affected. OpenSSL clients and
+ servers are not affected.
+
+ This issue was reported to OpenSSL by Michal Zalewski (Google).
+ ([CVE-2015-1790])
+
+ *Emilia Käsper*
+
+ * CMS verify infinite loop with unknown hash function
+
+ When verifying a signedData message the CMS code can enter an infinite loop
+ if presented with an unknown hash function OID. This can be used to perform
+ denial of service against any system which verifies signedData messages using
+ the CMS code.
+ This issue was reported to OpenSSL by Johannes Bauer.
+ ([CVE-2015-1792])
+
+ *Stephen Henson*
+
+ * Race condition handling NewSessionTicket
+
+ If a NewSessionTicket is received by a multi-threaded client when attempting to
+ reuse a previous ticket then a race condition can occur potentially leading to
+ a double free of the ticket data.
+ ([CVE-2015-1791])
+
+ *Matt Caswell*
+
+ * Reject DH handshakes with parameters shorter than 768 bits.
+
+ *Kurt Roeckx and Emilia Kasper*
+
+ * dhparam: generate 2048-bit parameters by default.
+
+ *Kurt Roeckx and Emilia Kasper*
+
+### Changes between 1.0.1l and 1.0.1m [19 Mar 2015]
+
+ * Segmentation fault in ASN1_TYPE_cmp fix
+
+ The function ASN1_TYPE_cmp will crash with an invalid read if an attempt is
+ made to compare ASN.1 boolean types. Since ASN1_TYPE_cmp is used to check
+ certificate signature algorithm consistency this can be used to crash any
+ certificate verification operation and exploited in a DoS attack. Any
+ application which performs certificate verification is vulnerable including
+ OpenSSL clients and servers which enable client authentication.
+ ([CVE-2015-0286])
+
+ *Stephen Henson*
+
+ * ASN.1 structure reuse memory corruption fix
+
+ Reusing a structure in ASN.1 parsing may allow an attacker to cause
+ memory corruption via an invalid write. Such reuse is and has been
+ strongly discouraged and is believed to be rare.
+
+ Applications that parse structures containing CHOICE or ANY DEFINED BY
+ components may be affected. Certificate parsing (d2i_X509 and related
+ functions) are however not affected. OpenSSL clients and servers are
+ not affected.
+ ([CVE-2015-0287])
+
+ *Stephen Henson*
+
+ * PKCS7 NULL pointer dereferences fix
+
+ The PKCS#7 parsing code does not handle missing outer ContentInfo
+ correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs with
+ missing content and trigger a NULL pointer dereference on parsing.
+
+ Applications that verify PKCS#7 signatures, decrypt PKCS#7 data or
+ otherwise parse PKCS#7 structures from untrusted sources are
+ affected. OpenSSL clients and servers are not affected.
+
+ This issue was reported to OpenSSL by Michal Zalewski (Google).
+ ([CVE-2015-0289])
+
+ *Emilia Käsper*
+
+ * DoS via reachable assert in SSLv2 servers fix
+
+ A malicious client can trigger an OPENSSL_assert (i.e., an abort) in
+ servers that both support SSLv2 and enable export cipher suites by sending
+ a specially crafted SSLv2 CLIENT-MASTER-KEY message.
+
+ This issue was discovered by Sean Burford (Google) and Emilia Käsper
+ (OpenSSL development team).
+ ([CVE-2015-0293])
+
+ *Emilia Käsper*
+
+ * Use After Free following d2i_ECPrivatekey error fix
+
+ A malformed EC private key file consumed via the d2i_ECPrivateKey function
+ could cause a use after free condition. This, in turn, could cause a double
+ free in several private key parsing functions (such as d2i_PrivateKey
+ or EVP_PKCS82PKEY) and could lead to a DoS attack or memory corruption
+ for applications that receive EC private keys from untrusted
+ sources. This scenario is considered rare.
+
+ This issue was discovered by the BoringSSL project and fixed in their
+ commit 517073cd4b.
+ ([CVE-2015-0209])
+
+ *Matt Caswell*
+
+ * X509_to_X509_REQ NULL pointer deref fix
+
+ The function X509_to_X509_REQ will crash with a NULL pointer dereference if
+ the certificate key is invalid. This function is rarely used in practice.
+
+ This issue was discovered by Brian Carpenter.
+ ([CVE-2015-0288])
+
+ *Stephen Henson*
+
+ * Removed the export ciphers from the DEFAULT ciphers
+
+ *Kurt Roeckx*
+
+### Changes between 1.0.1k and 1.0.1l [15 Jan 2015]
+
+ * Build fixes for the Windows and OpenVMS platforms
+
+ *Matt Caswell and Richard Levitte*
+
+### Changes between 1.0.1j and 1.0.1k [8 Jan 2015]
+
+ * Fix DTLS segmentation fault in dtls1_get_record. A carefully crafted DTLS
+ message can cause a segmentation fault in OpenSSL due to a NULL pointer
+ dereference. This could lead to a Denial Of Service attack. Thanks to
+ Markus Stenberg of Cisco Systems, Inc. for reporting this issue.
+ ([CVE-2014-3571])
+
+ *Steve Henson*
+
+ * Fix DTLS memory leak in dtls1_buffer_record. A memory leak can occur in the
+ dtls1_buffer_record function under certain conditions. In particular this
+ could occur if an attacker sent repeated DTLS records with the same
+ sequence number but for the next epoch. The memory leak could be exploited
+ by an attacker in a Denial of Service attack through memory exhaustion.
+ Thanks to Chris Mueller for reporting this issue.
+ ([CVE-2015-0206])
+
+ *Matt Caswell*
+
+ * Fix issue where no-ssl3 configuration sets method to NULL. When openssl is
+ built with the no-ssl3 option and a SSL v3 ClientHello is received the ssl
+ method would be set to NULL which could later result in a NULL pointer
+ dereference. Thanks to Frank Schmirler for reporting this issue.
+ ([CVE-2014-3569])
+
+ *Kurt Roeckx*
+
+ * Abort handshake if server key exchange message is omitted for ephemeral
+ ECDH ciphersuites.
+
+ Thanks to Karthikeyan Bhargavan of the PROSECCO team at INRIA for
+ reporting this issue.
+ ([CVE-2014-3572])
+
+ *Steve Henson*
+
+ * Remove non-export ephemeral RSA code on client and server. This code
+ violated the TLS standard by allowing the use of temporary RSA keys in
+ non-export ciphersuites and could be used by a server to effectively
+ downgrade the RSA key length used to a value smaller than the server
+ certificate. Thanks for Karthikeyan Bhargavan of the PROSECCO team at
+ INRIA or reporting this issue.
+ ([CVE-2015-0204])
+
+ *Steve Henson*
+
+ * Fixed issue where DH client certificates are accepted without verification.
+ An OpenSSL server will accept a DH certificate for client authentication
+ without the certificate verify message. This effectively allows a client to
+ authenticate without the use of a private key. This only affects servers
+ which trust a client certificate authority which issues certificates
+ containing DH keys: these are extremely rare and hardly ever encountered.
+ Thanks for Karthikeyan Bhargavan of the PROSECCO team at INRIA or reporting
+ this issue.
+ ([CVE-2015-0205])
+
+ *Steve Henson*
+
+ * Ensure that the session ID context of an SSL is updated when its
+ SSL_CTX is updated via SSL_set_SSL_CTX.
+
+ The session ID context is typically set from the parent SSL_CTX,
+ and can vary with the CTX.
+
+ *Adam Langley*
+
+ * Fix various certificate fingerprint issues.
+
+ By using non-DER or invalid encodings outside the signed portion of a
+ certificate the fingerprint can be changed without breaking the signature.
+ Although no details of the signed portion of the certificate can be changed
+ this can cause problems with some applications: e.g. those using the
+ certificate fingerprint for blacklists.
+
+ 1. Reject signatures with non zero unused bits.
+
+ If the BIT STRING containing the signature has non zero unused bits reject
+ the signature. All current signature algorithms require zero unused bits.
+
+ 2. Check certificate algorithm consistency.
+
+ Check the AlgorithmIdentifier inside TBS matches the one in the
+ certificate signature. NB: this will result in signature failure
+ errors for some broken certificates.
+
+ Thanks to Konrad Kraszewski from Google for reporting this issue.
+
+ 3. Check DSA/ECDSA signatures use DER.
+
+ Re-encode DSA/ECDSA signatures and compare with the original received
+ signature. Return an error if there is a mismatch.
+
+ This will reject various cases including garbage after signature
+ (thanks to Antti Karjalainen and Tuomo Untinen from the Codenomicon CROSS
+ program for discovering this case) and use of BER or invalid ASN.1 INTEGERs
+ (negative or with leading zeroes).
+
+ Further analysis was conducted and fixes were developed by Stephen Henson
+ of the OpenSSL core team.
+
+ ([CVE-2014-8275])
+
+ *Steve Henson*
+
+ * Correct Bignum squaring. Bignum squaring (BN_sqr) may produce incorrect
+ results on some platforms, including x86_64. This bug occurs at random
+ with a very low probability, and is not known to be exploitable in any
+ way, though its exact impact is difficult to determine. Thanks to Pieter
+ Wuille (Blockstream) who reported this issue and also suggested an initial
+ fix. Further analysis was conducted by the OpenSSL development team and
+ Adam Langley of Google. The final fix was developed by Andy Polyakov of
+ the OpenSSL core team.
+ ([CVE-2014-3570])
+
+ *Andy Polyakov*
+
+ * Do not resume sessions on the server if the negotiated protocol
+ version does not match the session's version. Resuming with a different
+ version, while not strictly forbidden by the RFC, is of questionable
+ sanity and breaks all known clients.
+
+ *David Benjamin, Emilia Käsper*
+
+ * Tighten handling of the ChangeCipherSpec (CCS) message: reject
+ early CCS messages during renegotiation. (Note that because
+ renegotiation is encrypted, this early CCS was not exploitable.)
+
+ *Emilia Käsper*
+
+ * Tighten client-side session ticket handling during renegotiation:
+ ensure that the client only accepts a session ticket if the server sends
+ the extension anew in the ServerHello. Previously, a TLS client would
+ reuse the old extension state and thus accept a session ticket if one was
+ announced in the initial ServerHello.
+
+ Similarly, ensure that the client requires a session ticket if one
+ was advertised in the ServerHello. Previously, a TLS client would
+ ignore a missing NewSessionTicket message.
+
+ *Emilia Käsper*
+
+### Changes between 1.0.1i and 1.0.1j [15 Oct 2014]
+
+ * SRTP Memory Leak.
+
+ A flaw in the DTLS SRTP extension parsing code allows an attacker, who
+ sends a carefully crafted handshake message, to cause OpenSSL to fail
+ to free up to 64k of memory causing a memory leak. This could be
+ exploited in a Denial Of Service attack. This issue affects OpenSSL
+ 1.0.1 server implementations for both SSL/TLS and DTLS regardless of
+ whether SRTP is used or configured. Implementations of OpenSSL that
+ have been compiled with OPENSSL_NO_SRTP defined are not affected.
+
+ The fix was developed by the OpenSSL team.
+ ([CVE-2014-3513])
+
+ *OpenSSL team*
+
+ * Session Ticket Memory Leak.
+
+ When an OpenSSL SSL/TLS/DTLS server receives a session ticket the
+ integrity of that ticket is first verified. In the event of a session
+ ticket integrity check failing, OpenSSL will fail to free memory
+ causing a memory leak. By sending a large number of invalid session
+ tickets an attacker could exploit this issue in a Denial Of Service
+ attack.
+ ([CVE-2014-3567])
+
+ *Steve Henson*
+
+ * Build option no-ssl3 is incomplete.
+
+ When OpenSSL is configured with "no-ssl3" as a build option, servers
+ could accept and complete a SSL 3.0 handshake, and clients could be
+ configured to send them.
+ ([CVE-2014-3568])
+
+ *Akamai and the OpenSSL team*
+
+ * Add support for TLS_FALLBACK_SCSV.
+ Client applications doing fallback retries should call
+ SSL_set_mode(s, SSL_MODE_SEND_FALLBACK_SCSV).
+ ([CVE-2014-3566])
+
+ *Adam Langley, Bodo Moeller*
+
+ * Add additional DigestInfo checks.
+
+ Re-encode DigestInto in DER and check against the original when
+ verifying RSA signature: this will reject any improperly encoded
+ DigestInfo structures.
+
+ Note: this is a precautionary measure and no attacks are currently known.
+
+ *Steve Henson*
+
+### Changes between 1.0.1h and 1.0.1i [6 Aug 2014]
+
+ * Fix SRP buffer overrun vulnerability. Invalid parameters passed to the
+ SRP code can be overrun an internal buffer. Add sanity check that
+ g, A, B < N to SRP code.
+
+ Thanks to Sean Devlin and Watson Ladd of Cryptography Services, NCC
+ Group for discovering this issue.
+ ([CVE-2014-3512])
+
+ *Steve Henson*
+
+ * A flaw in the OpenSSL SSL/TLS server code causes the server to negotiate
+ TLS 1.0 instead of higher protocol versions when the ClientHello message
+ is badly fragmented. This allows a man-in-the-middle attacker to force a
+ downgrade to TLS 1.0 even if both the server and the client support a
+ higher protocol version, by modifying the client's TLS records.
+
+ Thanks to David Benjamin and Adam Langley (Google) for discovering and
+ researching this issue.
+ ([CVE-2014-3511])
+
+ *David Benjamin*
+
+ * OpenSSL DTLS clients enabling anonymous (EC)DH ciphersuites are subject
+ to a denial of service attack. A malicious server can crash the client
+ with a null pointer dereference (read) by specifying an anonymous (EC)DH
+ ciphersuite and sending carefully crafted handshake messages.
+
+ Thanks to Felix Gröbert (Google) for discovering and researching this
+ issue.
+ ([CVE-2014-3510])
+
+ *Emilia Käsper*
+
+ * By sending carefully crafted DTLS packets an attacker could cause openssl
+ to leak memory. This can be exploited through a Denial of Service attack.
+ Thanks to Adam Langley for discovering and researching this issue.
+ ([CVE-2014-3507])
+
+ *Adam Langley*
+
+ * An attacker can force openssl to consume large amounts of memory whilst
+ processing DTLS handshake messages. This can be exploited through a
+ Denial of Service attack.
+ Thanks to Adam Langley for discovering and researching this issue.
+ ([CVE-2014-3506])
+
+ *Adam Langley*
+
+ * An attacker can force an error condition which causes openssl to crash
+ whilst processing DTLS packets due to memory being freed twice. This
+ can be exploited through a Denial of Service attack.
+ Thanks to Adam Langley and Wan-Teh Chang for discovering and researching
+ this issue.
+ ([CVE-2014-3505])
+
+ *Adam Langley*
+
+ * If a multithreaded client connects to a malicious server using a resumed
+ session and the server sends an ec point format extension it could write
+ up to 255 bytes to freed memory.
+
+ Thanks to Gabor Tyukasz (LogMeIn Inc) for discovering and researching this
+ issue.
+ ([CVE-2014-3509])
+
+ *Gabor Tyukasz*
+
+ * A malicious server can crash an OpenSSL client with a null pointer
+ dereference (read) by specifying an SRP ciphersuite even though it was not
+ properly negotiated with the client. This can be exploited through a
+ Denial of Service attack.
+
+ Thanks to Joonas Kuorilehto and Riku Hietamäki (Codenomicon) for
+ discovering and researching this issue.
+ ([CVE-2014-5139])
+
+ *Steve Henson*
+
+ * A flaw in OBJ_obj2txt may cause pretty printing functions such as
+ X509_name_oneline, X509_name_print_ex et al. to leak some information
+ from the stack. Applications may be affected if they echo pretty printing
+ output to the attacker.
+
+ Thanks to Ivan Fratric (Google) for discovering this issue.
+ ([CVE-2014-3508])
+
+ *Emilia Käsper, and Steve Henson*
+
+ * Fix ec_GFp_simple_points_make_affine (thus, EC_POINTs_mul etc.)
+ for corner cases. (Certain input points at infinity could lead to
+ bogus results, with non-infinity inputs mapped to infinity too.)
+
+ *Bodo Moeller*
+
+### Changes between 1.0.1g and 1.0.1h [5 Jun 2014]
+
+ * Fix for SSL/TLS MITM flaw. An attacker using a carefully crafted
+ handshake can force the use of weak keying material in OpenSSL
+ SSL/TLS clients and servers.
+
+ Thanks to KIKUCHI Masashi (Lepidum Co. Ltd.) for discovering and
+ researching this issue. ([CVE-2014-0224])
+
+ *KIKUCHI Masashi, Steve Henson*
+
+ * Fix DTLS recursion flaw. By sending an invalid DTLS handshake to an
+ OpenSSL DTLS client the code can be made to recurse eventually crashing
+ in a DoS attack.
+
+ Thanks to Imre Rad (Search-Lab Ltd.) for discovering this issue.
+ ([CVE-2014-0221])
+
+ *Imre Rad, Steve Henson*
+
+ * Fix DTLS invalid fragment vulnerability. A buffer overrun attack can
+ be triggered by sending invalid DTLS fragments to an OpenSSL DTLS
+ client or server. This is potentially exploitable to run arbitrary
+ code on a vulnerable client or server.
+
+ Thanks to Jüri Aedla for reporting this issue. ([CVE-2014-0195])
+
+ *Jüri Aedla, Steve Henson*
+
+ * Fix bug in TLS code where clients enable anonymous ECDH ciphersuites
+ are subject to a denial of service attack.
+
+ Thanks to Felix Gröbert and Ivan Fratric at Google for discovering
+ this issue. ([CVE-2014-3470])
+
+ *Felix Gröbert, Ivan Fratric, Steve Henson*
+
+ * Harmonize version and its documentation. -f flag is used to display
+ compilation flags.
+
+ *mancha <mancha1@zoho.com>*
+
+ * Fix eckey_priv_encode so it immediately returns an error upon a failure
+ in i2d_ECPrivateKey.
+
+ *mancha <mancha1@zoho.com>*
+
+ * Fix some double frees. These are not thought to be exploitable.
+
+ *mancha <mancha1@zoho.com>*
+
+### Changes between 1.0.1f and 1.0.1g [7 Apr 2014]
+
+ * A missing bounds check in the handling of the TLS heartbeat extension
+ can be used to reveal up to 64k of memory to a connected client or
+ server.
+
+ Thanks for Neel Mehta of Google Security for discovering this bug and to
+ Adam Langley <agl@chromium.org> and Bodo Moeller <bmoeller@acm.org> for
+ preparing the fix ([CVE-2014-0160])
+
+ *Adam Langley, Bodo Moeller*
+
+ * Fix for the attack described in the paper "Recovering OpenSSL
+ ECDSA Nonces Using the FLUSH+RELOAD Cache Side-channel Attack"
+ by Yuval Yarom and Naomi Benger. Details can be obtained from:
+ <http://eprint.iacr.org/2014/140>
+
+ Thanks to Yuval Yarom and Naomi Benger for discovering this
+ flaw and to Yuval Yarom for supplying a fix ([CVE-2014-0076])
+
+ *Yuval Yarom and Naomi Benger*
+
+ * TLS pad extension: draft-agl-tls-padding-03
+
+ Workaround for the "TLS hang bug" (see FAQ and PR#2771): if the
+ TLS client Hello record length value would otherwise be > 255 and
+ less that 512 pad with a dummy extension containing zeroes so it
+ is at least 512 bytes long.
+
+ *Adam Langley, Steve Henson*
+
+### Changes between 1.0.1e and 1.0.1f [6 Jan 2014]
+
+ * Fix for TLS record tampering bug. A carefully crafted invalid
+ handshake could crash OpenSSL with a NULL pointer exception.
+ Thanks to Anton Johansson for reporting this issues.
+ ([CVE-2013-4353])
+
+ * Keep original DTLS digest and encryption contexts in retransmission
+ structures so we can use the previous session parameters if they need
+ to be resent. ([CVE-2013-6450])
+
+ *Steve Henson*
+
+ * Add option SSL_OP_SAFARI_ECDHE_ECDSA_BUG (part of SSL_OP_ALL) which
+ avoids preferring ECDHE-ECDSA ciphers when the client appears to be
+ Safari on OS X. Safari on OS X 10.8..10.8.3 advertises support for
+ several ECDHE-ECDSA ciphers, but fails to negotiate them. The bug
+ is fixed in OS X 10.8.4, but Apple have ruled out both hot fixing
+ 10.8..10.8.3 and forcing users to upgrade to 10.8.4 or newer.
+
+ *Rob Stradling, Adam Langley*
+
+### Changes between 1.0.1d and 1.0.1e [11 Feb 2013]
+
+ * Correct fix for CVE-2013-0169. The original didn't work on AES-NI
+ supporting platforms or when small records were transferred.
+
+ *Andy Polyakov, Steve Henson*
+
+### Changes between 1.0.1c and 1.0.1d [5 Feb 2013]
+
+ * Make the decoding of SSLv3, TLS and DTLS CBC records constant time.
+
+ This addresses the flaw in CBC record processing discovered by
+ Nadhem Alfardan and Kenny Paterson. Details of this attack can be found
+ at: <http://www.isg.rhul.ac.uk/tls/>
+
+ Thanks go to Nadhem Alfardan and Kenny Paterson of the Information
+ Security Group at Royal Holloway, University of London
+ (www.isg.rhul.ac.uk) for discovering this flaw and Adam Langley and
+ Emilia Käsper for the initial patch.
+ ([CVE-2013-0169])
+
+ *Emilia Käsper, Adam Langley, Ben Laurie, Andy Polyakov, Steve Henson*
+
+ * Fix flaw in AESNI handling of TLS 1.2 and 1.1 records for CBC mode
+ ciphersuites which can be exploited in a denial of service attack.
+ Thanks go to and to Adam Langley <agl@chromium.org> for discovering
+ and detecting this bug and to Wolfgang Ettlinger
+ <wolfgang.ettlinger@gmail.com> for independently discovering this issue.
+ ([CVE-2012-2686])
+
+ *Adam Langley*
+
+ * Return an error when checking OCSP signatures when key is NULL.
+ This fixes a DoS attack. ([CVE-2013-0166])
+
+ *Steve Henson*
+
+ * Make openssl verify return errors.
+
+ *Chris Palmer <palmer@google.com> and Ben Laurie*
+
+ * Call OCSP Stapling callback after ciphersuite has been chosen, so
+ the right response is stapled. Also change SSL_get_certificate()
+ so it returns the certificate actually sent.
+ See <http://rt.openssl.org/Ticket/Display.html?id=2836>.
+
+ *Rob Stradling <rob.stradling@comodo.com>*
+
+ * Fix possible deadlock when decoding public keys.
+
+ *Steve Henson*
+
+ * Don't use TLS 1.0 record version number in initial client hello
+ if renegotiating.
+
+ *Steve Henson*
+
+### Changes between 1.0.1b and 1.0.1c [10 May 2012]
+
+ * Sanity check record length before skipping explicit IV in TLS
+ 1.2, 1.1 and DTLS to fix DoS attack.
+
+ Thanks to Codenomicon for discovering this issue using Fuzz-o-Matic
+ fuzzing as a service testing platform.
+ ([CVE-2012-2333])
+
+ *Steve Henson*
+
+ * Initialise tkeylen properly when encrypting CMS messages.
+ Thanks to Solar Designer of Openwall for reporting this issue.
+
+ *Steve Henson*
+
+ * In FIPS mode don't try to use composite ciphers as they are not
+ approved.
+
+ *Steve Henson*
+
+### Changes between 1.0.1a and 1.0.1b [26 Apr 2012]
+
+ * OpenSSL 1.0.0 sets SSL_OP_ALL to 0x80000FFFL and OpenSSL 1.0.1 and
+ 1.0.1a set SSL_OP_NO_TLSv1_1 to 0x00000400L which would unfortunately
+ mean any application compiled against OpenSSL 1.0.0 headers setting
+ SSL_OP_ALL would also set SSL_OP_NO_TLSv1_1, unintentionally disabling
+ TLS 1.1 also. Fix this by changing the value of SSL_OP_NO_TLSv1_1 to
+ 0x10000000L Any application which was previously compiled against
+ OpenSSL 1.0.1 or 1.0.1a headers and which cares about SSL_OP_NO_TLSv1_1
+ will need to be recompiled as a result. Letting be results in
+ inability to disable specifically TLS 1.1 and in client context,
+ in unlike event, limit maximum offered version to TLS 1.0 [see below].
+
+ *Steve Henson*
+
+ * In order to ensure interoperability SSL_OP_NO_protocolX does not
+ disable just protocol X, but all protocols above X *if* there are
+ protocols *below* X still enabled. In more practical terms it means
+ that if application wants to disable TLS1.0 in favor of TLS1.1 and
+ above, it's not sufficient to pass `SSL_OP_NO_TLSv1`, one has to pass
+ `SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2`. This applies to
+ client side.
+
+ *Andy Polyakov*
+
+### Changes between 1.0.1 and 1.0.1a [19 Apr 2012]
+
+ * Check for potentially exploitable overflows in asn1_d2i_read_bio
+ BUF_mem_grow and BUF_mem_grow_clean. Refuse attempts to shrink buffer
+ in CRYPTO_realloc_clean.
+
+ Thanks to Tavis Ormandy, Google Security Team, for discovering this
+ issue and to Adam Langley <agl@chromium.org> for fixing it.
+ ([CVE-2012-2110])
+
+ *Adam Langley (Google), Tavis Ormandy, Google Security Team*
+
+ * Don't allow TLS 1.2 SHA-256 ciphersuites in TLS 1.0, 1.1 connections.
+
+ *Adam Langley*
+
+ * Workarounds for some broken servers that "hang" if a client hello
+ record length exceeds 255 bytes.
+
+ 1. Do not use record version number > TLS 1.0 in initial client
+ hello: some (but not all) hanging servers will now work.
+ 2. If we set OPENSSL_MAX_TLS1_2_CIPHER_LENGTH this will truncate
+ the number of ciphers sent in the client hello. This should be
+ set to an even number, such as 50, for example by passing:
+ -DOPENSSL_MAX_TLS1_2_CIPHER_LENGTH=50 to config or Configure.
+ Most broken servers should now work.
+ 3. If all else fails setting OPENSSL_NO_TLS1_2_CLIENT will disable
+ TLS 1.2 client support entirely.
+
+ *Steve Henson*
+
+ * Fix SEGV in Vector Permutation AES module observed in OpenSSH.
+
+ *Andy Polyakov*
+
+### Changes between 1.0.0h and 1.0.1 [14 Mar 2012]
+
+ * Add compatibility with old MDC2 signatures which use an ASN1 OCTET
+ STRING form instead of a DigestInfo.
+
+ *Steve Henson*
+
+ * The format used for MDC2 RSA signatures is inconsistent between EVP
+ and the RSA_sign/RSA_verify functions. This was made more apparent when
+ OpenSSL used RSA_sign/RSA_verify for some RSA signatures in particular
+ those which went through EVP_PKEY_METHOD in 1.0.0 and later. Detect
+ the correct format in RSA_verify so both forms transparently work.
+
+ *Steve Henson*
+
+ * Some servers which support TLS 1.0 can choke if we initially indicate
+ support for TLS 1.2 and later renegotiate using TLS 1.0 in the RSA
+ encrypted premaster secret. As a workaround use the maximum permitted
+ client version in client hello, this should keep such servers happy
+ and still work with previous versions of OpenSSL.
+
+ *Steve Henson*
+
+ * Add support for TLS/DTLS heartbeats.
+
+ *Robin Seggelmann <seggelmann@fh-muenster.de>*
+
+ * Add support for SCTP.
+
+ *Robin Seggelmann <seggelmann@fh-muenster.de>*
+
+ * Improved PRNG seeding for VOS.
+
+ *Paul Green <Paul.Green@stratus.com>*
+
+ * Extensive assembler packs updates, most notably:
+
+ - x86[_64]: AES-NI, PCLMULQDQ, RDRAND support;
+ - x86[_64]: SSSE3 support (SHA1, vector-permutation AES);
+ - x86_64: bit-sliced AES implementation;
+ - ARM: NEON support, contemporary platforms optimizations;
+ - s390x: z196 support;
+ - `*`: GHASH and GF(2^m) multiplication implementations;
+
+ *Andy Polyakov*
+
+ * Make TLS-SRP code conformant with RFC 5054 API cleanup
+ (removal of unnecessary code)
+
+ *Peter Sylvester <peter.sylvester@edelweb.fr>*
+
+ * Add TLS key material exporter from RFC 5705.
+
+ *Eric Rescorla*
+
+ * Add DTLS-SRTP negotiation from RFC 5764.
+
+ *Eric Rescorla*
+
+ * Add Next Protocol Negotiation,
+ <http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-00>. Can be
+ disabled with a no-npn flag to config or Configure. Code donated
+ by Google.
+
+ *Adam Langley <agl@google.com> and Ben Laurie*
+
+ * Add optional 64-bit optimized implementations of elliptic curves NIST-P224,
+ NIST-P256, NIST-P521, with constant-time single point multiplication on
+ typical inputs. Compiler support for the nonstandard type `__uint128_t` is
+ required to use this (present in gcc 4.4 and later, for 64-bit builds).
+ Code made available under Apache License version 2.0.
+
+ Specify "enable-ec_nistp_64_gcc_128" on the Configure (or config) command
+ line to include this in your build of OpenSSL, and run "make depend" (or
+ "make update"). This enables the following EC_METHODs:
+
+ EC_GFp_nistp224_method()
+ EC_GFp_nistp256_method()
+ EC_GFp_nistp521_method()
+
+ EC_GROUP_new_by_curve_name() will automatically use these (while
+ EC_GROUP_new_curve_GFp() currently prefers the more flexible
+ implementations).
+
+ *Emilia Käsper, Adam Langley, Bodo Moeller (Google)*
+
+ * Use type ossl_ssize_t instead of ssize_t which isn't available on
+ all platforms. Move ssize_t definition from e_os.h to the public
+ header file e_os2.h as it now appears in public header file cms.h
+
+ *Steve Henson*
+
+ * New -sigopt option to the ca, req and x509 utilities. Additional
+ signature parameters can be passed using this option and in
+ particular PSS.
+
+ *Steve Henson*
+
+ * Add RSA PSS signing function. This will generate and set the
+ appropriate AlgorithmIdentifiers for PSS based on those in the
+ corresponding EVP_MD_CTX structure. No application support yet.
+
+ *Steve Henson*
+
+ * Support for companion algorithm specific ASN1 signing routines.
+ New function ASN1_item_sign_ctx() signs a pre-initialised
+ EVP_MD_CTX structure and sets AlgorithmIdentifiers based on
+ the appropriate parameters.
+
+ *Steve Henson*
+
+ * Add new algorithm specific ASN1 verification initialisation function
+ to EVP_PKEY_ASN1_METHOD: this is not in EVP_PKEY_METHOD since the ASN1
+ handling will be the same no matter what EVP_PKEY_METHOD is used.
+ Add a PSS handler to support verification of PSS signatures: checked
+ against a number of sample certificates.
+
+ *Steve Henson*
+
+ * Add signature printing for PSS. Add PSS OIDs.
+
+ *Steve Henson, Martin Kaiser <lists@kaiser.cx>*
+
+ * Add algorithm specific signature printing. An individual ASN1 method
+ can now print out signatures instead of the standard hex dump.
+
+ More complex signatures (e.g. PSS) can print out more meaningful
+ information. Include DSA version that prints out the signature
+ parameters r, s.
+
+ *Steve Henson*
+
+ * Password based recipient info support for CMS library: implementing
+ RFC3211.
+
+ *Steve Henson*
+
+ * Split password based encryption into PBES2 and PBKDF2 functions. This
+ neatly separates the code into cipher and PBE sections and is required
+ for some algorithms that split PBES2 into separate pieces (such as
+ password based CMS).
+
+ *Steve Henson*
+
+ * Session-handling fixes:
+ - Fix handling of connections that are resuming with a session ID,
+ but also support Session Tickets.
+ - Fix a bug that suppressed issuing of a new ticket if the client
+ presented a ticket with an expired session.
+ - Try to set the ticket lifetime hint to something reasonable.
+ - Make tickets shorter by excluding irrelevant information.
+ - On the client side, don't ignore renewed tickets.
+
+ *Adam Langley, Bodo Moeller (Google)*
+
+ * Fix PSK session representation.
+
+ *Bodo Moeller*
+
+ * Add RC4-MD5 and AESNI-SHA1 "stitched" implementations.
+
+ This work was sponsored by Intel.
+
+ *Andy Polyakov*
+
+ * Add GCM support to TLS library. Some custom code is needed to split
+ the IV between the fixed (from PRF) and explicit (from TLS record)
+ portions. This adds all GCM ciphersuites supported by RFC5288 and
+ RFC5289. Generalise some `AES*` cipherstrings to include GCM and
+ add a special AESGCM string for GCM only.
+
+ *Steve Henson*
+
+ * Expand range of ctrls for AES GCM. Permit setting invocation
+ field on decrypt and retrieval of invocation field only on encrypt.
+
+ *Steve Henson*
+
+ * Add HMAC ECC ciphersuites from RFC5289. Include SHA384 PRF support.
+ As required by RFC5289 these ciphersuites cannot be used if for
+ versions of TLS earlier than 1.2.
+
+ *Steve Henson*
+
+ * For FIPS capable OpenSSL interpret a NULL default public key method
+ as unset and return the appropriate default but do *not* set the default.
+ This means we can return the appropriate method in applications that
+ switch between FIPS and non-FIPS modes.
+
+ *Steve Henson*
+
+ * Redirect HMAC and CMAC operations to FIPS module in FIPS mode. If an
+ ENGINE is used then we cannot handle that in the FIPS module so we
+ keep original code iff non-FIPS operations are allowed.
+
+ *Steve Henson*
+
+ * Add -attime option to openssl utilities.
+
+ *Peter Eckersley <pde@eff.org>, Ben Laurie and Steve Henson*
+
+ * Redirect DSA and DH operations to FIPS module in FIPS mode.
+
+ *Steve Henson*
+
+ * Redirect ECDSA and ECDH operations to FIPS module in FIPS mode. Also use
+ FIPS EC methods unconditionally for now.
+
+ *Steve Henson*
+
+ * New build option no-ec2m to disable characteristic 2 code.
+
+ *Steve Henson*
+
+ * Backport libcrypto audit of return value checking from 1.1.0-dev; not
+ all cases can be covered as some introduce binary incompatibilities.
+
+ *Steve Henson*
+
+ * Redirect RSA operations to FIPS module including keygen,
+ encrypt, decrypt, sign and verify. Block use of non FIPS RSA methods.
+
+ *Steve Henson*
+
+ * Add similar low-level API blocking to ciphers.
+
+ *Steve Henson*
+
+ * low-level digest APIs are not approved in FIPS mode: any attempt
+ to use these will cause a fatal error. Applications that *really* want
+ to use them can use the `private_*` version instead.
+
+ *Steve Henson*
+
+ * Redirect cipher operations to FIPS module for FIPS builds.
+
+ *Steve Henson*
+
+ * Redirect digest operations to FIPS module for FIPS builds.
+
+ *Steve Henson*
+
+ * Update build system to add "fips" flag which will link in fipscanister.o
+ for static and shared library builds embedding a signature if needed.
+
+ *Steve Henson*
+
+ * Output TLS supported curves in preference order instead of numerical
+ order. This is currently hardcoded for the highest order curves first.
+ This should be configurable so applications can judge speed vs strength.
+
+ *Steve Henson*
+
+ * Add TLS v1.2 server support for client authentication.
+
+ *Steve Henson*
+
+ * Add support for FIPS mode in ssl library: disable SSLv3, non-FIPS ciphers
+ and enable MD5.
+
+ *Steve Henson*
+
+ * Functions FIPS_mode_set() and FIPS_mode() which call the underlying
+ FIPS modules versions.
+
+ *Steve Henson*
+
+ * Add TLS v1.2 client side support for client authentication. Keep cache
+ of handshake records longer as we don't know the hash algorithm to use
+ until after the certificate request message is received.
+
+ *Steve Henson*
+
+ * Initial TLS v1.2 client support. Add a default signature algorithms
+ extension including all the algorithms we support. Parse new signature
+ format in client key exchange. Relax some ECC signing restrictions for
+ TLS v1.2 as indicated in RFC5246.
+
+ *Steve Henson*
+
+ * Add server support for TLS v1.2 signature algorithms extension. Switch
+ to new signature format when needed using client digest preference.
+ All server ciphersuites should now work correctly in TLS v1.2. No client
+ support yet and no support for client certificates.
+
+ *Steve Henson*
+
+ * Initial TLS v1.2 support. Add new SHA256 digest to ssl code, switch
+ to SHA256 for PRF when using TLS v1.2 and later. Add new SHA256 based
+ ciphersuites. At present only RSA key exchange ciphersuites work with
+ TLS v1.2. Add new option for TLS v1.2 replacing the old and obsolete
+ SSL_OP_PKCS1_CHECK flags with SSL_OP_NO_TLSv1_2. New TLSv1.2 methods
+ and version checking.
+
+ *Steve Henson*
+
+ * New option OPENSSL_NO_SSL_INTERN. If an application can be compiled
+ with this defined it will not be affected by any changes to ssl internal
+ structures. Add several utility functions to allow openssl application
+ to work with OPENSSL_NO_SSL_INTERN defined.
+
+ *Steve Henson*
+
+ * A long standing patch to add support for SRP from EdelWeb (Peter
+ Sylvester and Christophe Renou) was integrated.
+ *Christophe Renou <christophe.renou@edelweb.fr>, Peter Sylvester
+ <peter.sylvester@edelweb.fr>, Tom Wu <tjw@cs.stanford.edu>, and
+ Ben Laurie*
+
+ * Add functions to copy EVP_PKEY_METHOD and retrieve flags and id.
+
+ *Steve Henson*
+
+ * Permit abbreviated handshakes when renegotiating using the function
+ SSL_renegotiate_abbreviated().
+
+ *Robin Seggelmann <seggelmann@fh-muenster.de>*
+
+ * Add call to ENGINE_register_all_complete() to
+ ENGINE_load_builtin_engines(), so some implementations get used
+ automatically instead of needing explicit application support.
+
+ *Steve Henson*
+
+ * Add support for TLS key exporter as described in RFC5705.
+
+ *Robin Seggelmann <seggelmann@fh-muenster.de>, Steve Henson*
+
+ * Initial TLSv1.1 support. Since TLSv1.1 is very similar to TLS v1.0 only
+ a few changes are required:
+
+ Add SSL_OP_NO_TLSv1_1 flag.
+ Add TLSv1_1 methods.
+ Update version checking logic to handle version 1.1.
+ Add explicit IV handling (ported from DTLS code).
+ Add command line options to s_client/s_server.
+
+ *Steve Henson*
+
+OpenSSL 1.0.0
+-------------
+
+### Changes between 1.0.0s and 1.0.0t [3 Dec 2015]
+
+ * X509_ATTRIBUTE memory leak
+
+ When presented with a malformed X509_ATTRIBUTE structure OpenSSL will leak
+ memory. This structure is used by the PKCS#7 and CMS routines so any
+ application which reads PKCS#7 or CMS data from untrusted sources is
+ affected. SSL/TLS is not affected.
+
+ This issue was reported to OpenSSL by Adam Langley (Google/BoringSSL) using
+ libFuzzer.
+ ([CVE-2015-3195])
+
+ *Stephen Henson*
+
+ * Race condition handling PSK identify hint
+
+ If PSK identity hints are received by a multi-threaded client then
+ the values are wrongly updated in the parent SSL_CTX structure. This can
+ result in a race condition potentially leading to a double free of the
+ identify hint data.
+ ([CVE-2015-3196])
+
+ *Stephen Henson*
+
+### Changes between 1.0.0r and 1.0.0s [11 Jun 2015]
+
+ * Malformed ECParameters causes infinite loop
+
+ When processing an ECParameters structure OpenSSL enters an infinite loop
+ if the curve specified is over a specially malformed binary polynomial
+ field.
+
+ This can be used to perform denial of service against any
+ system which processes public keys, certificate requests or
+ certificates. This includes TLS clients and TLS servers with
+ client authentication enabled.
+
+ This issue was reported to OpenSSL by Joseph Barr-Pixton.
+ ([CVE-2015-1788])
+
+ *Andy Polyakov*
+
+ * Exploitable out-of-bounds read in X509_cmp_time
+
+ X509_cmp_time does not properly check the length of the ASN1_TIME
+ string and can read a few bytes out of bounds. In addition,
+ X509_cmp_time accepts an arbitrary number of fractional seconds in the
+ time string.
+
+ An attacker can use this to craft malformed certificates and CRLs of
+ various sizes and potentially cause a segmentation fault, resulting in
+ a DoS on applications that verify certificates or CRLs. TLS clients
+ that verify CRLs are affected. TLS clients and servers with client
+ authentication enabled may be affected if they use custom verification
+ callbacks.
+
+ This issue was reported to OpenSSL by Robert Swiecki (Google), and
+ independently by Hanno Böck.
+ ([CVE-2015-1789])
+
+ *Emilia Käsper*
+
+ * PKCS7 crash with missing EnvelopedContent
+
+ The PKCS#7 parsing code does not handle missing inner EncryptedContent
+ correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs
+ with missing content and trigger a NULL pointer dereference on parsing.
+
+ Applications that decrypt PKCS#7 data or otherwise parse PKCS#7
+ structures from untrusted sources are affected. OpenSSL clients and
+ servers are not affected.
+
+ This issue was reported to OpenSSL by Michal Zalewski (Google).
+ ([CVE-2015-1790])
+
+ *Emilia Käsper*
+
+ * CMS verify infinite loop with unknown hash function
+
+ When verifying a signedData message the CMS code can enter an infinite loop
+ if presented with an unknown hash function OID. This can be used to perform
+ denial of service against any system which verifies signedData messages using
+ the CMS code.
+ This issue was reported to OpenSSL by Johannes Bauer.
+ ([CVE-2015-1792])
+
+ *Stephen Henson*
+
+ * Race condition handling NewSessionTicket
+
+ If a NewSessionTicket is received by a multi-threaded client when attempting to
+ reuse a previous ticket then a race condition can occur potentially leading to
+ a double free of the ticket data.
+ ([CVE-2015-1791])
+
+ *Matt Caswell*
+
+### Changes between 1.0.0q and 1.0.0r [19 Mar 2015]
+
+ * Segmentation fault in ASN1_TYPE_cmp fix
+
+ The function ASN1_TYPE_cmp will crash with an invalid read if an attempt is
+ made to compare ASN.1 boolean types. Since ASN1_TYPE_cmp is used to check
+ certificate signature algorithm consistency this can be used to crash any
+ certificate verification operation and exploited in a DoS attack. Any
+ application which performs certificate verification is vulnerable including
+ OpenSSL clients and servers which enable client authentication.
+ ([CVE-2015-0286])
+
+ *Stephen Henson*
+
+ * ASN.1 structure reuse memory corruption fix
+
+ Reusing a structure in ASN.1 parsing may allow an attacker to cause
+ memory corruption via an invalid write. Such reuse is and has been
+ strongly discouraged and is believed to be rare.
+
+ Applications that parse structures containing CHOICE or ANY DEFINED BY
+ components may be affected. Certificate parsing (d2i_X509 and related
+ functions) are however not affected. OpenSSL clients and servers are
+ not affected.
+ ([CVE-2015-0287])
+
+ *Stephen Henson*
+
+ * PKCS7 NULL pointer dereferences fix
+
+ The PKCS#7 parsing code does not handle missing outer ContentInfo
+ correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs with
+ missing content and trigger a NULL pointer dereference on parsing.
+
+ Applications that verify PKCS#7 signatures, decrypt PKCS#7 data or
+ otherwise parse PKCS#7 structures from untrusted sources are
+ affected. OpenSSL clients and servers are not affected.
+
+ This issue was reported to OpenSSL by Michal Zalewski (Google).
+ ([CVE-2015-0289])
+
+ *Emilia Käsper*
+
+ * DoS via reachable assert in SSLv2 servers fix
+
+ A malicious client can trigger an OPENSSL_assert (i.e., an abort) in
+ servers that both support SSLv2 and enable export cipher suites by sending
+ a specially crafted SSLv2 CLIENT-MASTER-KEY message.
+
+ This issue was discovered by Sean Burford (Google) and Emilia Käsper
+ (OpenSSL development team).
+ ([CVE-2015-0293])
+
+ *Emilia Käsper*
+
+ * Use After Free following d2i_ECPrivatekey error fix
+
+ A malformed EC private key file consumed via the d2i_ECPrivateKey function
+ could cause a use after free condition. This, in turn, could cause a double
+ free in several private key parsing functions (such as d2i_PrivateKey
+ or EVP_PKCS82PKEY) and could lead to a DoS attack or memory corruption
+ for applications that receive EC private keys from untrusted
+ sources. This scenario is considered rare.
+
+ This issue was discovered by the BoringSSL project and fixed in their
+ commit 517073cd4b.
+ ([CVE-2015-0209])
+
+ *Matt Caswell*
+
+ * X509_to_X509_REQ NULL pointer deref fix
+
+ The function X509_to_X509_REQ will crash with a NULL pointer dereference if
+ the certificate key is invalid. This function is rarely used in practice.
+
+ This issue was discovered by Brian Carpenter.
+ ([CVE-2015-0288])
+
+ *Stephen Henson*
+
+ * Removed the export ciphers from the DEFAULT ciphers
+
+ *Kurt Roeckx*
+
+### Changes between 1.0.0p and 1.0.0q [15 Jan 2015]
+
+ * Build fixes for the Windows and OpenVMS platforms
+
+ *Matt Caswell and Richard Levitte*
+
+### Changes between 1.0.0o and 1.0.0p [8 Jan 2015]
+
+ * Fix DTLS segmentation fault in dtls1_get_record. A carefully crafted DTLS
+ message can cause a segmentation fault in OpenSSL due to a NULL pointer
+ dereference. This could lead to a Denial Of Service attack. Thanks to
+ Markus Stenberg of Cisco Systems, Inc. for reporting this issue.
+ ([CVE-2014-3571])
+
+ *Steve Henson*
+
+ * Fix DTLS memory leak in dtls1_buffer_record. A memory leak can occur in the
+ dtls1_buffer_record function under certain conditions. In particular this
+ could occur if an attacker sent repeated DTLS records with the same
+ sequence number but for the next epoch. The memory leak could be exploited
+ by an attacker in a Denial of Service attack through memory exhaustion.
+ Thanks to Chris Mueller for reporting this issue.
+ ([CVE-2015-0206])
+
+ *Matt Caswell*
+
+ * Fix issue where no-ssl3 configuration sets method to NULL. When openssl is
+ built with the no-ssl3 option and a SSL v3 ClientHello is received the ssl
+ method would be set to NULL which could later result in a NULL pointer
+ dereference. Thanks to Frank Schmirler for reporting this issue.
+ ([CVE-2014-3569])
+
+ *Kurt Roeckx*
+
+ * Abort handshake if server key exchange message is omitted for ephemeral
+ ECDH ciphersuites.
+
+ Thanks to Karthikeyan Bhargavan of the PROSECCO team at INRIA for
+ reporting this issue.
+ ([CVE-2014-3572])
+
+ *Steve Henson*
+
+ * Remove non-export ephemeral RSA code on client and server. This code
+ violated the TLS standard by allowing the use of temporary RSA keys in
+ non-export ciphersuites and could be used by a server to effectively
+ downgrade the RSA key length used to a value smaller than the server
+ certificate. Thanks for Karthikeyan Bhargavan of the PROSECCO team at
+ INRIA or reporting this issue.
+ ([CVE-2015-0204])
+
+ *Steve Henson*
+
+ * Fixed issue where DH client certificates are accepted without verification.
+ An OpenSSL server will accept a DH certificate for client authentication
+ without the certificate verify message. This effectively allows a client to
+ authenticate without the use of a private key. This only affects servers
+ which trust a client certificate authority which issues certificates
+ containing DH keys: these are extremely rare and hardly ever encountered.
+ Thanks for Karthikeyan Bhargavan of the PROSECCO team at INRIA or reporting
+ this issue.
+ ([CVE-2015-0205])
+
+ *Steve Henson*
+
+ * Correct Bignum squaring. Bignum squaring (BN_sqr) may produce incorrect
+ results on some platforms, including x86_64. This bug occurs at random
+ with a very low probability, and is not known to be exploitable in any
+ way, though its exact impact is difficult to determine. Thanks to Pieter
+ Wuille (Blockstream) who reported this issue and also suggested an initial
+ fix. Further analysis was conducted by the OpenSSL development team and
+ Adam Langley of Google. The final fix was developed by Andy Polyakov of
+ the OpenSSL core team.
+ ([CVE-2014-3570])
+
+ *Andy Polyakov*
+
+ * Fix various certificate fingerprint issues.
+
+ By using non-DER or invalid encodings outside the signed portion of a
+ certificate the fingerprint can be changed without breaking the signature.
+ Although no details of the signed portion of the certificate can be changed
+ this can cause problems with some applications: e.g. those using the
+ certificate fingerprint for blacklists.
+
+ 1. Reject signatures with non zero unused bits.
+
+ If the BIT STRING containing the signature has non zero unused bits reject
+ the signature. All current signature algorithms require zero unused bits.
+
+ 2. Check certificate algorithm consistency.
+
+ Check the AlgorithmIdentifier inside TBS matches the one in the
+ certificate signature. NB: this will result in signature failure
+ errors for some broken certificates.
+
+ Thanks to Konrad Kraszewski from Google for reporting this issue.
+
+ 3. Check DSA/ECDSA signatures use DER.
+
+ Reencode DSA/ECDSA signatures and compare with the original received
+ signature. Return an error if there is a mismatch.
+
+ This will reject various cases including garbage after signature
+ (thanks to Antti Karjalainen and Tuomo Untinen from the Codenomicon CROSS
+ program for discovering this case) and use of BER or invalid ASN.1 INTEGERs
+ (negative or with leading zeroes).
+
+ Further analysis was conducted and fixes were developed by Stephen Henson
+ of the OpenSSL core team.
+
+ ([CVE-2014-8275])
+
+ *Steve Henson*
+
+### Changes between 1.0.0n and 1.0.0o [15 Oct 2014]
+
+ * Session Ticket Memory Leak.
+
+ When an OpenSSL SSL/TLS/DTLS server receives a session ticket the
+ integrity of that ticket is first verified. In the event of a session
+ ticket integrity check failing, OpenSSL will fail to free memory
+ causing a memory leak. By sending a large number of invalid session
+ tickets an attacker could exploit this issue in a Denial Of Service
+ attack.
+ ([CVE-2014-3567])
+
+ *Steve Henson*
+
+ * Build option no-ssl3 is incomplete.
+
+ When OpenSSL is configured with "no-ssl3" as a build option, servers
+ could accept and complete a SSL 3.0 handshake, and clients could be
+ configured to send them.
+ ([CVE-2014-3568])
+
+ *Akamai and the OpenSSL team*
+
+ * Add support for TLS_FALLBACK_SCSV.
+ Client applications doing fallback retries should call
+ SSL_set_mode(s, SSL_MODE_SEND_FALLBACK_SCSV).
+ ([CVE-2014-3566])
+
+ *Adam Langley, Bodo Moeller*
+
+ * Add additional DigestInfo checks.
+
+ Reencode DigestInto in DER and check against the original when
+ verifying RSA signature: this will reject any improperly encoded
+ DigestInfo structures.
+
+ Note: this is a precautionary measure and no attacks are currently known.
+
+ *Steve Henson*
+
+### Changes between 1.0.0m and 1.0.0n [6 Aug 2014]
+
+ * OpenSSL DTLS clients enabling anonymous (EC)DH ciphersuites are subject
+ to a denial of service attack. A malicious server can crash the client
+ with a null pointer dereference (read) by specifying an anonymous (EC)DH
+ ciphersuite and sending carefully crafted handshake messages.
+
+ Thanks to Felix Gröbert (Google) for discovering and researching this
+ issue.
+ ([CVE-2014-3510])
+
+ *Emilia Käsper*
+
+ * By sending carefully crafted DTLS packets an attacker could cause openssl
+ to leak memory. This can be exploited through a Denial of Service attack.
+ Thanks to Adam Langley for discovering and researching this issue.
+ ([CVE-2014-3507])
+
+ *Adam Langley*
+
+ * An attacker can force openssl to consume large amounts of memory whilst
+ processing DTLS handshake messages. This can be exploited through a
+ Denial of Service attack.
+ Thanks to Adam Langley for discovering and researching this issue.
+ ([CVE-2014-3506])
+
+ *Adam Langley*
+
+ * An attacker can force an error condition which causes openssl to crash
+ whilst processing DTLS packets due to memory being freed twice. This
+ can be exploited through a Denial of Service attack.
+ Thanks to Adam Langley and Wan-Teh Chang for discovering and researching
+ this issue.
+ ([CVE-2014-3505])
+
+ *Adam Langley*
+
+ * If a multithreaded client connects to a malicious server using a resumed
+ session and the server sends an ec point format extension it could write
+ up to 255 bytes to freed memory.
+
+ Thanks to Gabor Tyukasz (LogMeIn Inc) for discovering and researching this
+ issue.
+ ([CVE-2014-3509])
+
+ *Gabor Tyukasz*
+
+ * A flaw in OBJ_obj2txt may cause pretty printing functions such as
+ X509_name_oneline, X509_name_print_ex et al. to leak some information
+ from the stack. Applications may be affected if they echo pretty printing
+ output to the attacker.
+
+ Thanks to Ivan Fratric (Google) for discovering this issue.
+ ([CVE-2014-3508])
+
+ *Emilia Käsper, and Steve Henson*
+
+ * Fix ec_GFp_simple_points_make_affine (thus, EC_POINTs_mul etc.)
+ for corner cases. (Certain input points at infinity could lead to
+ bogus results, with non-infinity inputs mapped to infinity too.)
+
+ *Bodo Moeller*
+
+### Changes between 1.0.0l and 1.0.0m [5 Jun 2014]
+
+ * Fix for SSL/TLS MITM flaw. An attacker using a carefully crafted
+ handshake can force the use of weak keying material in OpenSSL
+ SSL/TLS clients and servers.
+
+ Thanks to KIKUCHI Masashi (Lepidum Co. Ltd.) for discovering and
+ researching this issue. ([CVE-2014-0224])
+
+ *KIKUCHI Masashi, Steve Henson*
+
+ * Fix DTLS recursion flaw. By sending an invalid DTLS handshake to an
+ OpenSSL DTLS client the code can be made to recurse eventually crashing
+ in a DoS attack.
+
+ Thanks to Imre Rad (Search-Lab Ltd.) for discovering this issue.
+ ([CVE-2014-0221])
+
+ *Imre Rad, Steve Henson*
+
+ * Fix DTLS invalid fragment vulnerability. A buffer overrun attack can
+ be triggered by sending invalid DTLS fragments to an OpenSSL DTLS
+ client or server. This is potentially exploitable to run arbitrary
+ code on a vulnerable client or server.
+
+ Thanks to Jüri Aedla for reporting this issue. ([CVE-2014-0195])
+
+ *Jüri Aedla, Steve Henson*
+
+ * Fix bug in TLS code where clients enable anonymous ECDH ciphersuites
+ are subject to a denial of service attack.
+
+ Thanks to Felix Gröbert and Ivan Fratric at Google for discovering
+ this issue. ([CVE-2014-3470])
+
+ *Felix Gröbert, Ivan Fratric, Steve Henson*
+
+ * Harmonize version and its documentation. -f flag is used to display
+ compilation flags.
+
+ *mancha <mancha1@zoho.com>*
+
+ * Fix eckey_priv_encode so it immediately returns an error upon a failure
+ in i2d_ECPrivateKey.
+
+ *mancha <mancha1@zoho.com>*
+
+ * Fix some double frees. These are not thought to be exploitable.
+
+ *mancha <mancha1@zoho.com>*
+
+ * Fix for the attack described in the paper "Recovering OpenSSL
+ ECDSA Nonces Using the FLUSH+RELOAD Cache Side-channel Attack"
+ by Yuval Yarom and Naomi Benger. Details can be obtained from:
+ <http://eprint.iacr.org/2014/140>
+
+ Thanks to Yuval Yarom and Naomi Benger for discovering this
+ flaw and to Yuval Yarom for supplying a fix ([CVE-2014-0076])
+
+ *Yuval Yarom and Naomi Benger*
+
+### Changes between 1.0.0k and 1.0.0l [6 Jan 2014]
+
+ * Keep original DTLS digest and encryption contexts in retransmission
+ structures so we can use the previous session parameters if they need
+ to be resent. ([CVE-2013-6450])
+
+ *Steve Henson*
+
+ * Add option SSL_OP_SAFARI_ECDHE_ECDSA_BUG (part of SSL_OP_ALL) which
+ avoids preferring ECDHE-ECDSA ciphers when the client appears to be
+ Safari on OS X. Safari on OS X 10.8..10.8.3 advertises support for
+ several ECDHE-ECDSA ciphers, but fails to negotiate them. The bug
+ is fixed in OS X 10.8.4, but Apple have ruled out both hot fixing
+ 10.8..10.8.3 and forcing users to upgrade to 10.8.4 or newer.
+
+ *Rob Stradling, Adam Langley*
+
+### Changes between 1.0.0j and 1.0.0k [5 Feb 2013]
+
+ * Make the decoding of SSLv3, TLS and DTLS CBC records constant time.
+
+ This addresses the flaw in CBC record processing discovered by
+ Nadhem Alfardan and Kenny Paterson. Details of this attack can be found
+ at: <http://www.isg.rhul.ac.uk/tls/>
+
+ Thanks go to Nadhem Alfardan and Kenny Paterson of the Information
+ Security Group at Royal Holloway, University of London
+ (www.isg.rhul.ac.uk) for discovering this flaw and Adam Langley and
+ Emilia Käsper for the initial patch.
+ ([CVE-2013-0169])
+
+ *Emilia Käsper, Adam Langley, Ben Laurie, Andy Polyakov, Steve Henson*
+
+ * Return an error when checking OCSP signatures when key is NULL.
+ This fixes a DoS attack. ([CVE-2013-0166])
+
+ *Steve Henson*
+
+ * Call OCSP Stapling callback after ciphersuite has been chosen, so
+ the right response is stapled. Also change SSL_get_certificate()
+ so it returns the certificate actually sent.
+ See <http://rt.openssl.org/Ticket/Display.html?id=2836>.
+ (This is a backport)
+
+ *Rob Stradling <rob.stradling@comodo.com>*
+
+ * Fix possible deadlock when decoding public keys.
+
+ *Steve Henson*
+
+### Changes between 1.0.0i and 1.0.0j [10 May 2012]
+
+[NB: OpenSSL 1.0.0i and later 1.0.0 patch levels were released after
+OpenSSL 1.0.1.]
+
+ * Sanity check record length before skipping explicit IV in DTLS
+ to fix DoS attack.
+
+ Thanks to Codenomicon for discovering this issue using Fuzz-o-Matic
+ fuzzing as a service testing platform.
+ ([CVE-2012-2333])
+
+ *Steve Henson*
+
+ * Initialise tkeylen properly when encrypting CMS messages.
+ Thanks to Solar Designer of Openwall for reporting this issue.
+
+ *Steve Henson*
+
+### Changes between 1.0.0h and 1.0.0i [19 Apr 2012]
+
+ * Check for potentially exploitable overflows in asn1_d2i_read_bio
+ BUF_mem_grow and BUF_mem_grow_clean. Refuse attempts to shrink buffer
+ in CRYPTO_realloc_clean.
+
+ Thanks to Tavis Ormandy, Google Security Team, for discovering this
+ issue and to Adam Langley <agl@chromium.org> for fixing it.
+ ([CVE-2012-2110])
+
+ *Adam Langley (Google), Tavis Ormandy, Google Security Team*
+
+### Changes between 1.0.0g and 1.0.0h [12 Mar 2012]
+
+ * Fix MMA (Bleichenbacher's attack on PKCS #1 v1.5 RSA padding) weakness
+ in CMS and PKCS7 code. When RSA decryption fails use a random key for
+ content decryption and always return the same error. Note: this attack
+ needs on average 2^20 messages so it only affects automated senders. The
+ old behaviour can be re-enabled in the CMS code by setting the
+ CMS_DEBUG_DECRYPT flag: this is useful for debugging and testing where
+ an MMA defence is not necessary.
+ Thanks to Ivan Nestlerode <inestlerode@us.ibm.com> for discovering
+ this issue. ([CVE-2012-0884])
+
+ *Steve Henson*
+
+ * Fix CVE-2011-4619: make sure we really are receiving a
+ client hello before rejecting multiple SGC restarts. Thanks to
+ Ivan Nestlerode <inestlerode@us.ibm.com> for discovering this bug.
+
+ *Steve Henson*
+
+### Changes between 1.0.0f and 1.0.0g [18 Jan 2012]
+
+ * Fix for DTLS DoS issue introduced by fix for CVE-2011-4109.
+ Thanks to Antonio Martin, Enterprise Secure Access Research and
+ Development, Cisco Systems, Inc. for discovering this bug and
+ preparing a fix. ([CVE-2012-0050])
+
+ *Antonio Martin*
+
+### Changes between 1.0.0e and 1.0.0f [4 Jan 2012]
+
+ * Nadhem Alfardan and Kenny Paterson have discovered an extension
+ of the Vaudenay padding oracle attack on CBC mode encryption
+ which enables an efficient plaintext recovery attack against
+ the OpenSSL implementation of DTLS. Their attack exploits timing
+ differences arising during decryption processing. A research
+ paper describing this attack can be found at:
+ <http://www.isg.rhul.ac.uk/~kp/dtls.pdf>
+ Thanks go to Nadhem Alfardan and Kenny Paterson of the Information
+ Security Group at Royal Holloway, University of London
+ (www.isg.rhul.ac.uk) for discovering this flaw and to Robin Seggelmann
+ <seggelmann@fh-muenster.de> and Michael Tuexen <tuexen@fh-muenster.de>
+ for preparing the fix. ([CVE-2011-4108])
+
+ *Robin Seggelmann, Michael Tuexen*
+
+ * Clear bytes used for block padding of SSL 3.0 records.
+ ([CVE-2011-4576])
+
+ *Adam Langley (Google)*
+
+ * Only allow one SGC handshake restart for SSL/TLS. Thanks to George
+ Kadianakis <desnacked@gmail.com> for discovering this issue and
+ Adam Langley for preparing the fix. ([CVE-2011-4619])
+
+ *Adam Langley (Google)*
+
+ * Check parameters are not NULL in GOST ENGINE. ([CVE-2012-0027])
+
+ *Andrey Kulikov <amdeich@gmail.com>*
+
+ * Prevent malformed RFC3779 data triggering an assertion failure.
+ Thanks to Andrew Chi, BBN Technologies, for discovering the flaw
+ and Rob Austein <sra@hactrn.net> for fixing it. ([CVE-2011-4577])
+
+ *Rob Austein <sra@hactrn.net>*
+
+ * Improved PRNG seeding for VOS.
+
+ *Paul Green <Paul.Green@stratus.com>*
+
+ * Fix ssl_ciph.c set-up race.
+
+ *Adam Langley (Google)*
+
+ * Fix spurious failures in ecdsatest.c.
+
+ *Emilia Käsper (Google)*
+
+ * Fix the BIO_f_buffer() implementation (which was mixing different
+ interpretations of the `..._len` fields).
+
+ *Adam Langley (Google)*
+
+ * Fix handling of BN_BLINDING: now BN_BLINDING_invert_ex (rather than
+ BN_BLINDING_invert_ex) calls BN_BLINDING_update, ensuring that concurrent
+ threads won't reuse the same blinding coefficients.
+
+ This also avoids the need to obtain the CRYPTO_LOCK_RSA_BLINDING
+ lock to call BN_BLINDING_invert_ex, and avoids one use of
+ BN_BLINDING_update for each BN_BLINDING structure (previously,
+ the last update always remained unused).
+
+ *Emilia Käsper (Google)*
+
+ * In ssl3_clear, preserve s3->init_extra along with s3->rbuf.
+
+ *Bob Buckholz (Google)*
+
+### Changes between 1.0.0d and 1.0.0e [6 Sep 2011]
+
+ * Fix bug where CRLs with nextUpdate in the past are sometimes accepted
+ by initialising X509_STORE_CTX properly. ([CVE-2011-3207])
+
+ *Kaspar Brand <ossl@velox.ch>*
+
+ * Fix SSL memory handling for (EC)DH ciphersuites, in particular
+ for multi-threaded use of ECDH. ([CVE-2011-3210])
+
+ *Adam Langley (Google)*
+
+ * Fix x509_name_ex_d2i memory leak on bad inputs.
+
+ *Bodo Moeller*
+
+ * Remove hard coded ecdsaWithSHA1 signature tests in ssl code and check
+ signature public key algorithm by using OID xref utilities instead.
+ Before this you could only use some ECC ciphersuites with SHA1 only.
+
+ *Steve Henson*
+
+ * Add protection against ECDSA timing attacks as mentioned in the paper
+ by Billy Bob Brumley and Nicola Tuveri, see:
+ <http://eprint.iacr.org/2011/232.pdf>
+
+ *Billy Bob Brumley and Nicola Tuveri*
+
+### Changes between 1.0.0c and 1.0.0d [8 Feb 2011]
+
+ * Fix parsing of OCSP stapling ClientHello extension. CVE-2011-0014
+
+ *Neel Mehta, Adam Langley, Bodo Moeller (Google)*
+
+ * Fix bug in string printing code: if *any* escaping is enabled we must
+ escape the escape character (backslash) or the resulting string is
+ ambiguous.
+
+ *Steve Henson*
+
+### Changes between 1.0.0b and 1.0.0c [2 Dec 2010]
+
+ * Disable code workaround for ancient and obsolete Netscape browsers
+ and servers: an attacker can use it in a ciphersuite downgrade attack.
+ Thanks to Martin Rex for discovering this bug. CVE-2010-4180
+
+ *Steve Henson*
+
+ * Fixed J-PAKE implementation error, originally discovered by
+ Sebastien Martini, further info and confirmation from Stefan
+ Arentz and Feng Hao. Note that this fix is a security fix. CVE-2010-4252
+
+ *Ben Laurie*
+
+### Changes between 1.0.0a and 1.0.0b [16 Nov 2010]
+
+ * Fix extension code to avoid race conditions which can result in a buffer
+ overrun vulnerability: resumed sessions must not be modified as they can
+ be shared by multiple threads. CVE-2010-3864
+
+ *Steve Henson*
+
+ * Fix WIN32 build system to correctly link an ENGINE directory into
+ a DLL.
+
+ *Steve Henson*
+
+### Changes between 1.0.0 and 1.0.0a [01 Jun 2010]
+
+ * Check return value of int_rsa_verify in pkey_rsa_verifyrecover
+ ([CVE-2010-1633])
+
+ *Steve Henson, Peter-Michael Hager <hager@dortmund.net>*
+
+### Changes between 0.9.8n and 1.0.0 [29 Mar 2010]
+
+ * Add "missing" function EVP_CIPHER_CTX_copy(). This copies a cipher
+ context. The operation can be customised via the ctrl mechanism in
+ case ENGINEs want to include additional functionality.
+
+ *Steve Henson*
+
+ * Tolerate yet another broken PKCS#8 key format: private key value negative.
+
+ *Steve Henson*
+
+ * Add new -subject_hash_old and -issuer_hash_old options to x509 utility to
+ output hashes compatible with older versions of OpenSSL.
+
+ *Willy Weisz <weisz@vcpc.univie.ac.at>*
+
+ * Fix compression algorithm handling: if resuming a session use the
+ compression algorithm of the resumed session instead of determining
+ it from client hello again. Don't allow server to change algorithm.
+
+ *Steve Henson*
+
+ * Add load_crls() function to commands tidying load_certs() too. Add option
+ to verify utility to allow additional CRLs to be included.
+
+ *Steve Henson*
+
+ * Update OCSP request code to permit adding custom headers to the request:
+ some responders need this.
+
+ *Steve Henson*
+
+ * The function EVP_PKEY_sign() returns <=0 on error: check return code
+ correctly.
+
+ *Julia Lawall <julia@diku.dk>*
+
+ * Update verify callback code in `apps/s_cb.c` and `apps/verify.c`, it
+ needlessly dereferenced structures, used obsolete functions and
+ didn't handle all updated verify codes correctly.
+
+ *Steve Henson*
+
+ * Disable MD2 in the default configuration.
+
+ *Steve Henson*
+
+ * In BIO_pop() and BIO_push() use the ctrl argument (which was NULL) to
+ indicate the initial BIO being pushed or popped. This makes it possible
+ to determine whether the BIO is the one explicitly called or as a result
+ of the ctrl being passed down the chain. Fix BIO_pop() and SSL BIOs so
+ it handles reference counts correctly and doesn't zero out the I/O bio
+ when it is not being explicitly popped. WARNING: applications which
+ included workarounds for the old buggy behaviour will need to be modified
+ or they could free up already freed BIOs.
+
+ *Steve Henson*
+
+ * Extend the uni2asc/asc2uni => OPENSSL_uni2asc/OPENSSL_asc2uni
+ renaming to all platforms (within the 0.9.8 branch, this was
+ done conditionally on Netware platforms to avoid a name clash).
+
+ *Guenter <lists@gknw.net>*
+
+ * Add ECDHE and PSK support to DTLS.
+
+ *Michael Tuexen <tuexen@fh-muenster.de>*
+
+ * Add CHECKED_STACK_OF macro to safestack.h, otherwise safestack can't
+ be used on C++.
+
+ *Steve Henson*
+
+ * Add "missing" function EVP_MD_flags() (without this the only way to
+ retrieve a digest flags is by accessing the structure directly. Update
+ `EVP_MD_do_all*()` and `EVP_CIPHER_do_all*()` to include the name a digest
+ or cipher is registered as in the "from" argument. Print out all
+ registered digests in the dgst usage message instead of manually
+ attempting to work them out.
+
+ *Steve Henson*
+
+ * If no SSLv2 ciphers are used don't use an SSLv2 compatible client hello:
+ this allows the use of compression and extensions. Change default cipher
+ string to remove SSLv2 ciphersuites. This effectively avoids ancient SSLv2
+ by default unless an application cipher string requests it.
+
+ *Steve Henson*
+
+ * Alter match criteria in PKCS12_parse(). It used to try to use local
+ key ids to find matching certificates and keys but some PKCS#12 files
+ don't follow the (somewhat unwritten) rules and this strategy fails.
+ Now just gather all certificates together and the first private key
+ then look for the first certificate that matches the key.
+
+ *Steve Henson*
+
+ * Support use of registered digest and cipher names for dgst and cipher
+ commands instead of having to add each one as a special case. So now
+ you can do:
+
+ openssl sha256 foo
+
+ as well as:
+
+ openssl dgst -sha256 foo
+
+ and this works for ENGINE based algorithms too.
+
+ *Steve Henson*
+
+ * Update Gost ENGINE to support parameter files.
+
+ *Victor B. Wagner <vitus@cryptocom.ru>*
+
+ * Support GeneralizedTime in ca utility.
+
+ *Oliver Martin <oliver@volatilevoid.net>, Steve Henson*
+
+ * Enhance the hash format used for certificate directory links. The new
+ form uses the canonical encoding (meaning equivalent names will work
+ even if they aren't identical) and uses SHA1 instead of MD5. This form
+ is incompatible with the older format and as a result c_rehash should
+ be used to rebuild symbolic links.
+
+ *Steve Henson*
+
+ * Make PKCS#8 the default write format for private keys, replacing the
+ traditional format. This form is standardised, more secure and doesn't
+ include an implicit MD5 dependency.
+
+ *Steve Henson*
+
+ * Add a $gcc_devteam_warn option to Configure. The idea is that any code
+ committed to OpenSSL should pass this lot as a minimum.
+
+ *Steve Henson*
+
+ * Add session ticket override functionality for use by EAP-FAST.
+
+ *Jouni Malinen <j@w1.fi>*
+
+ * Modify HMAC functions to return a value. Since these can be implemented
+ in an ENGINE errors can occur.
+
+ *Steve Henson*
+
+ * Type-checked OBJ_bsearch_ex.
+
+ *Ben Laurie*
+
+ * Type-checked OBJ_bsearch. Also some constification necessitated
+ by type-checking. Still to come: TXT_DB, bsearch(?),
+ OBJ_bsearch_ex, qsort, CRYPTO_EX_DATA, ASN1_VALUE, ASN1_STRING,
+ CONF_VALUE.
+
+ *Ben Laurie*
+
+ * New function OPENSSL_gmtime_adj() to add a specific number of days and
+ seconds to a tm structure directly, instead of going through OS
+ specific date routines. This avoids any issues with OS routines such
+ as the year 2038 bug. New `*_adj()` functions for ASN1 time structures
+ and X509_time_adj_ex() to cover the extended range. The existing
+ X509_time_adj() is still usable and will no longer have any date issues.
+
+ *Steve Henson*
+
+ * Delta CRL support. New use deltas option which will attempt to locate
+ and search any appropriate delta CRLs available.
+
+ This work was sponsored by Google.
+
+ *Steve Henson*
+
+ * Support for CRLs partitioned by reason code. Reorganise CRL processing
+ code and add additional score elements. Validate alternate CRL paths
+ as part of the CRL checking and indicate a new error "CRL path validation
+ error" in this case. Applications wanting additional details can use
+ the verify callback and check the new "parent" field. If this is not
+ NULL CRL path validation is taking place. Existing applications won't
+ see this because it requires extended CRL support which is off by
+ default.
+
+ This work was sponsored by Google.
+
+ *Steve Henson*
+
+ * Support for freshest CRL extension.
+
+ This work was sponsored by Google.
+
+ *Steve Henson*
+
+ * Initial indirect CRL support. Currently only supported in the CRLs
+ passed directly and not via lookup. Process certificate issuer
+ CRL entry extension and lookup CRL entries by bother issuer name
+ and serial number. Check and process CRL issuer entry in IDP extension.
+
+ This work was sponsored by Google.
+
+ *Steve Henson*
+
+ * Add support for distinct certificate and CRL paths. The CRL issuer
+ certificate is validated separately in this case. Only enabled if
+ an extended CRL support flag is set: this flag will enable additional
+ CRL functionality in future.
+
+ This work was sponsored by Google.
+
+ *Steve Henson*
+
+ * Add support for policy mappings extension.
+
+ This work was sponsored by Google.
+
+ *Steve Henson*
+
+ * Fixes to pathlength constraint, self issued certificate handling,
+ policy processing to align with RFC3280 and PKITS tests.
+
+ This work was sponsored by Google.
+
+ *Steve Henson*
+
+ * Support for name constraints certificate extension. DN, email, DNS
+ and URI types are currently supported.
+
+ This work was sponsored by Google.
+
+ *Steve Henson*
+
+ * To cater for systems that provide a pointer-based thread ID rather
+ than numeric, deprecate the current numeric thread ID mechanism and
+ replace it with a structure and associated callback type. This
+ mechanism allows a numeric "hash" to be extracted from a thread ID in
+ either case, and on platforms where pointers are larger than 'long',
+ mixing is done to help ensure the numeric 'hash' is usable even if it
+ can't be guaranteed unique. The default mechanism is to use "&errno"
+ as a pointer-based thread ID to distinguish between threads.
+
+ Applications that want to provide their own thread IDs should now use
+ CRYPTO_THREADID_set_callback() to register a callback that will call
+ either CRYPTO_THREADID_set_numeric() or CRYPTO_THREADID_set_pointer().
+
+ Note that ERR_remove_state() is now deprecated, because it is tied
+ to the assumption that thread IDs are numeric. ERR_remove_state(0)
+ to free the current thread's error state should be replaced by
+ ERR_remove_thread_state(NULL).
+
+ (This new approach replaces the functions CRYPTO_set_idptr_callback(),
+ CRYPTO_get_idptr_callback(), and CRYPTO_thread_idptr() that existed in
+ OpenSSL 0.9.9-dev between June 2006 and August 2008. Also, if an
+ application was previously providing a numeric thread callback that
+ was inappropriate for distinguishing threads, then uniqueness might
+ have been obtained with &errno that happened immediately in the
+ intermediate development versions of OpenSSL; this is no longer the
+ case, the numeric thread callback will now override the automatic use
+ of &errno.)
+
+ *Geoff Thorpe, with help from Bodo Moeller*
+
+ * Initial support for different CRL issuing certificates. This covers a
+ simple case where the self issued certificates in the chain exist and
+ the real CRL issuer is higher in the existing chain.
+
+ This work was sponsored by Google.
+
+ *Steve Henson*
+
+ * Removed effectively defunct crypto/store from the build.
+
+ *Ben Laurie*
+
+ * Revamp of STACK to provide stronger type-checking. Still to come:
+ TXT_DB, bsearch(?), OBJ_bsearch, qsort, CRYPTO_EX_DATA, ASN1_VALUE,
+ ASN1_STRING, CONF_VALUE.
+
+ *Ben Laurie*
+
+ * Add a new SSL_MODE_RELEASE_BUFFERS mode flag to release unused buffer
+ RAM on SSL connections. This option can save about 34k per idle SSL.
+
+ *Nick Mathewson*
+
+ * Revamp of LHASH to provide stronger type-checking. Still to come:
+ STACK, TXT_DB, bsearch, qsort.
+
+ *Ben Laurie*
+
+ * Initial support for Cryptographic Message Syntax (aka CMS) based
+ on RFC3850, RFC3851 and RFC3852. New cms directory and cms utility,
+ support for data, signedData, compressedData, digestedData and
+ encryptedData, envelopedData types included. Scripts to check against
+ RFC4134 examples draft and interop and consistency checks of many
+ content types and variants.
+
+ *Steve Henson*
+
+ * Add options to enc utility to support use of zlib compression BIO.
+
+ *Steve Henson*
+
+ * Extend mk1mf to support importing of options and assembly language
+ files from Configure script, currently only included in VC-WIN32.
+ The assembly language rules can now optionally generate the source
+ files from the associated perl scripts.
+
+ *Steve Henson*
+
+ * Implement remaining functionality needed to support GOST ciphersuites.
+ Interop testing has been performed using CryptoPro implementations.
+
+ *Victor B. Wagner <vitus@cryptocom.ru>*
+
+ * s390x assembler pack.
+
+ *Andy Polyakov*
+
+ * ARMv4 assembler pack. ARMv4 refers to v4 and later ISA, not CPU
+ "family."
+
+ *Andy Polyakov*
+
+ * Implement Opaque PRF Input TLS extension as specified in
+ draft-rescorla-tls-opaque-prf-input-00.txt. Since this is not an
+ official specification yet and no extension type assignment by
+ IANA exists, this extension (for now) will have to be explicitly
+ enabled when building OpenSSL by providing the extension number
+ to use. For example, specify an option
+
+ -DTLSEXT_TYPE_opaque_prf_input=0x9527
+
+ to the "config" or "Configure" script to enable the extension,
+ assuming extension number 0x9527 (which is a completely arbitrary
+ and unofficial assignment based on the MD5 hash of the Internet
+ Draft). Note that by doing so, you potentially lose
+ interoperability with other TLS implementations since these might
+ be using the same extension number for other purposes.
+
+ SSL_set_tlsext_opaque_prf_input(ssl, src, len) is used to set the
+ opaque PRF input value to use in the handshake. This will create
+ an internal copy of the length-'len' string at 'src', and will
+ return non-zero for success.
+
+ To get more control and flexibility, provide a callback function
+ by using
+
+ SSL_CTX_set_tlsext_opaque_prf_input_callback(ctx, cb)
+ SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(ctx, arg)
+
+ where
+
+ int (*cb)(SSL *, void *peerinput, size_t len, void *arg);
+ void *arg;
+
+ Callback function 'cb' will be called in handshakes, and is
+ expected to use SSL_set_tlsext_opaque_prf_input() as appropriate.
+ Argument 'arg' is for application purposes (the value as given to
+ SSL_CTX_set_tlsext_opaque_prf_input_callback_arg() will directly
+ be provided to the callback function). The callback function
+ has to return non-zero to report success: usually 1 to use opaque
+ PRF input just if possible, or 2 to enforce use of the opaque PRF
+ input. In the latter case, the library will abort the handshake
+ if opaque PRF input is not successfully negotiated.
+
+ Arguments 'peerinput' and 'len' given to the callback function
+ will always be NULL and 0 in the case of a client. A server will
+ see the client's opaque PRF input through these variables if
+ available (NULL and 0 otherwise). Note that if the server
+ provides an opaque PRF input, the length must be the same as the
+ length of the client's opaque PRF input.
+
+ Note that the callback function will only be called when creating
+ a new session (session resumption can resume whatever was
+ previously negotiated), and will not be called in SSL 2.0
+ handshakes; thus, SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) or
+ SSL_set_options(ssl, SSL_OP_NO_SSLv2) is especially recommended
+ for applications that need to enforce opaque PRF input.
+
+ *Bodo Moeller*
+
+ * Update ssl code to support digests other than SHA1+MD5 for handshake
+ MAC.
+
+ *Victor B. Wagner <vitus@cryptocom.ru>*
+
+ * Add RFC4507 support to OpenSSL. This includes the corrections in
+ RFC4507bis. The encrypted ticket format is an encrypted encoded
+ SSL_SESSION structure, that way new session features are automatically
+ supported.
+
+ If a client application caches session in an SSL_SESSION structure
+ support is transparent because tickets are now stored in the encoded
+ SSL_SESSION.
+
+ The SSL_CTX structure automatically generates keys for ticket
+ protection in servers so again support should be possible
+ with no application modification.
+
+ If a client or server wishes to disable RFC4507 support then the option
+ SSL_OP_NO_TICKET can be set.
+
+ Add a TLS extension debugging callback to allow the contents of any client
+ or server extensions to be examined.
+
+ This work was sponsored by Google.
+
+ *Steve Henson*
+
+ * Final changes to avoid use of pointer pointer casts in OpenSSL.
+ OpenSSL should now compile cleanly on gcc 4.2
+
+ *Peter Hartley <pdh@utter.chaos.org.uk>, Steve Henson*
+
+ * Update SSL library to use new EVP_PKEY MAC API. Include generic MAC
+ support including streaming MAC support: this is required for GOST
+ ciphersuite support.
+
+ *Victor B. Wagner <vitus@cryptocom.ru>, Steve Henson*
+
+ * Add option -stream to use PKCS#7 streaming in smime utility. New
+ function i2d_PKCS7_bio_stream() and PEM_write_PKCS7_bio_stream()
+ to output in BER and PEM format.
+
+ *Steve Henson*
+
+ * Experimental support for use of HMAC via EVP_PKEY interface. This
+ allows HMAC to be handled via the `EVP_DigestSign*()` interface. The
+ EVP_PKEY "key" in this case is the HMAC key, potentially allowing
+ ENGINE support for HMAC keys which are unextractable. New -mac and
+ -macopt options to dgst utility.
+
+ *Steve Henson*
+
+ * New option -sigopt to dgst utility. Update dgst to use
+ `EVP_Digest{Sign,Verify}*`. These two changes make it possible to use
+ alternative signing parameters such as X9.31 or PSS in the dgst
+ utility.
+
+ *Steve Henson*
+
+ * Change ssl_cipher_apply_rule(), the internal function that does
+ the work each time a ciphersuite string requests enabling
+ ("foo+bar"), moving ("+foo+bar"), disabling ("-foo+bar", or
+ removing ("!foo+bar") a class of ciphersuites: Now it maintains
+ the order of disabled ciphersuites such that those ciphersuites
+ that most recently went from enabled to disabled not only stay
+ in order with respect to each other, but also have higher priority
+ than other disabled ciphersuites the next time ciphersuites are
+ enabled again.
+
+ This means that you can now say, e.g., "PSK:-PSK:HIGH" to enable
+ the same ciphersuites as with "HIGH" alone, but in a specific
+ order where the PSK ciphersuites come first (since they are the
+ most recently disabled ciphersuites when "HIGH" is parsed).
+
+ Also, change ssl_create_cipher_list() (using this new
+ functionality) such that between otherwise identical
+ ciphersuites, ephemeral ECDH is preferred over ephemeral DH in
+ the default order.
+
+ *Bodo Moeller*
+
+ * Change ssl_create_cipher_list() so that it automatically
+ arranges the ciphersuites in reasonable order before starting
+ to process the rule string. Thus, the definition for "DEFAULT"
+ (SSL_DEFAULT_CIPHER_LIST) now is just "ALL:!aNULL:!eNULL", but
+ remains equivalent to `"AES:ALL:!aNULL:!eNULL:+aECDH:+kRSA:+RC4:@STRENGTH"`.
+ This makes it much easier to arrive at a reasonable default order
+ in applications for which anonymous ciphers are OK (meaning
+ that you can't actually use DEFAULT).
+
+ *Bodo Moeller; suggested by Victor Duchovni*
+
+ * Split the SSL/TLS algorithm mask (as used for ciphersuite string
+ processing) into multiple integers instead of setting
+ "SSL_MKEY_MASK" bits, "SSL_AUTH_MASK" bits, "SSL_ENC_MASK",
+ "SSL_MAC_MASK", and "SSL_SSL_MASK" bits all in a single integer.
+ (These masks as well as the individual bit definitions are hidden
+ away into the non-exported interface ssl/ssl_locl.h, so this
+ change to the definition of the SSL_CIPHER structure shouldn't
+ affect applications.) This give us more bits for each of these
+ categories, so there is no longer a need to coagulate AES128 and
+ AES256 into a single algorithm bit, and to coagulate Camellia128
+ and Camellia256 into a single algorithm bit, which has led to all
+ kinds of kludges.
+
+ Thus, among other things, the kludge introduced in 0.9.7m and
+ 0.9.8e for masking out AES256 independently of AES128 or masking
+ out Camellia256 independently of AES256 is not needed here in 0.9.9.
+
+ With the change, we also introduce new ciphersuite aliases that
+ so far were missing: "AES128", "AES256", "CAMELLIA128", and
+ "CAMELLIA256".
+
+ *Bodo Moeller*
+
+ * Add support for dsa-with-SHA224 and dsa-with-SHA256.
+ Use the leftmost N bytes of the signature input if the input is
+ larger than the prime q (with N being the size in bytes of q).
+
+ *Nils Larsch*
+
+ * Very *very* experimental PKCS#7 streaming encoder support. Nothing uses
+ it yet and it is largely untested.
+
+ *Steve Henson*
+
+ * Add support for the ecdsa-with-SHA224/256/384/512 signature types.
+
+ *Nils Larsch*
+
+ * Initial incomplete changes to avoid need for function casts in OpenSSL
+ some compilers (gcc 4.2 and later) reject their use. Safestack is
+ reimplemented. Update ASN1 to avoid use of legacy functions.
+
+ *Steve Henson*
+
+ * Win32/64 targets are linked with Winsock2.
+
+ *Andy Polyakov*
+
+ * Add an X509_CRL_METHOD structure to allow CRL processing to be redirected
+ to external functions. This can be used to increase CRL handling
+ efficiency especially when CRLs are very large by (for example) storing
+ the CRL revoked certificates in a database.
+
+ *Steve Henson*
+
+ * Overhaul of by_dir code. Add support for dynamic loading of CRLs so
+ new CRLs added to a directory can be used. New command line option
+ -verify_return_error to s_client and s_server. This causes real errors
+ to be returned by the verify callback instead of carrying on no matter
+ what. This reflects the way a "real world" verify callback would behave.
+
+ *Steve Henson*
+
+ * GOST engine, supporting several GOST algorithms and public key formats.
+ Kindly donated by Cryptocom.
+
+ *Cryptocom*
+
+ * Partial support for Issuing Distribution Point CRL extension. CRLs
+ partitioned by DP are handled but no indirect CRL or reason partitioning
+ (yet). Complete overhaul of CRL handling: now the most suitable CRL is
+ selected via a scoring technique which handles IDP and AKID in CRLs.
+
+ *Steve Henson*
+
+ * New X509_STORE_CTX callbacks lookup_crls() and lookup_certs() which
+ will ultimately be used for all verify operations: this will remove the
+ X509_STORE dependency on certificate verification and allow alternative
+ lookup methods. X509_STORE based implementations of these two callbacks.
+
+ *Steve Henson*
+
+ * Allow multiple CRLs to exist in an X509_STORE with matching issuer names.
+ Modify get_crl() to find a valid (unexpired) CRL if possible.
+
+ *Steve Henson*
+
+ * New function X509_CRL_match() to check if two CRLs are identical. Normally
+ this would be called X509_CRL_cmp() but that name is already used by
+ a function that just compares CRL issuer names. Cache several CRL
+ extensions in X509_CRL structure and cache CRLDP in X509.
+
+ *Steve Henson*
+
+ * Store a "canonical" representation of X509_NAME structure (ASN1 Name)
+ this maps equivalent X509_NAME structures into a consistent structure.
+ Name comparison can then be performed rapidly using memcmp().
+
+ *Steve Henson*
+
+ * Non-blocking OCSP request processing. Add -timeout option to ocsp
+ utility.
+
+ *Steve Henson*
+
+ * Allow digests to supply their own micalg string for S/MIME type using
+ the ctrl EVP_MD_CTRL_MICALG.
+
+ *Steve Henson*
+
+ * During PKCS7 signing pass the PKCS7 SignerInfo structure to the
+ EVP_PKEY_METHOD before and after signing via the EVP_PKEY_CTRL_PKCS7_SIGN
+ ctrl. It can then customise the structure before and/or after signing
+ if necessary.
+
+ *Steve Henson*
+
+ * New function OBJ_add_sigid() to allow application defined signature OIDs
+ to be added to OpenSSLs internal tables. New function OBJ_sigid_free()
+ to free up any added signature OIDs.
+
+ *Steve Henson*
+
+ * New functions EVP_CIPHER_do_all(), EVP_CIPHER_do_all_sorted(),
+ EVP_MD_do_all() and EVP_MD_do_all_sorted() to enumerate internal
+ digest and cipher tables. New options added to openssl utility:
+ list-message-digest-algorithms and list-cipher-algorithms.
+
+ *Steve Henson*
+
+ * Change the array representation of binary polynomials: the list
+ of degrees of non-zero coefficients is now terminated with -1.
+ Previously it was terminated with 0, which was also part of the
+ value; thus, the array representation was not applicable to
+ polynomials where t^0 has coefficient zero. This change makes
+ the array representation useful in a more general context.
+
+ *Douglas Stebila*
+
+ * Various modifications and fixes to SSL/TLS cipher string
+ handling. For ECC, the code now distinguishes between fixed ECDH
+ with RSA certificates on the one hand and with ECDSA certificates
+ on the other hand, since these are separate ciphersuites. The
+ unused code for Fortezza ciphersuites has been removed.
+
+ For consistency with EDH, ephemeral ECDH is now called "EECDH"
+ (not "ECDHE"). For consistency with the code for DH
+ certificates, use of ECDH certificates is now considered ECDH
+ authentication, not RSA or ECDSA authentication (the latter is
+ merely the CA's signing algorithm and not actively used in the
+ protocol).
+
+ The temporary ciphersuite alias "ECCdraft" is no longer
+ available, and ECC ciphersuites are no longer excluded from "ALL"
+ and "DEFAULT". The following aliases now exist for RFC 4492
+ ciphersuites, most of these by analogy with the DH case:
+
+ kECDHr - ECDH cert, signed with RSA
+ kECDHe - ECDH cert, signed with ECDSA
+ kECDH - ECDH cert (signed with either RSA or ECDSA)
+ kEECDH - ephemeral ECDH
+ ECDH - ECDH cert or ephemeral ECDH
+
+ aECDH - ECDH cert
+ aECDSA - ECDSA cert
+ ECDSA - ECDSA cert
+
+ AECDH - anonymous ECDH
+ EECDH - non-anonymous ephemeral ECDH (equivalent to "kEECDH:-AECDH")
+
+ *Bodo Moeller*
+
+ * Add additional S/MIME capabilities for AES and GOST ciphers if supported.
+ Use correct micalg parameters depending on digest(s) in signed message.
+
+ *Steve Henson*
+
+ * Add engine support for EVP_PKEY_ASN1_METHOD. Add functions to process
+ an ENGINE asn1 method. Support ENGINE lookups in the ASN1 code.
+
+ *Steve Henson*
+
+ * Initial engine support for EVP_PKEY_METHOD. New functions to permit
+ an engine to register a method. Add ENGINE lookups for methods and
+ functional reference processing.
+
+ *Steve Henson*
+
+ * New functions `EVP_Digest{Sign,Verify)*`. These are enhanced versions of
+ `EVP_{Sign,Verify}*` which allow an application to customise the signature
+ process.
+
+ *Steve Henson*
+
+ * New -resign option to smime utility. This adds one or more signers
+ to an existing PKCS#7 signedData structure. Also -md option to use an
+ alternative message digest algorithm for signing.
+
+ *Steve Henson*
+
+ * Tidy up PKCS#7 routines and add new functions to make it easier to
+ create PKCS7 structures containing multiple signers. Update smime
+ application to support multiple signers.
+
+ *Steve Henson*
+
+ * New -macalg option to pkcs12 utility to allow setting of an alternative
+ digest MAC.
+
+ *Steve Henson*
+
+ * Initial support for PKCS#5 v2.0 PRFs other than default SHA1 HMAC.
+ Reorganize PBE internals to lookup from a static table using NIDs,
+ add support for HMAC PBE OID translation. Add a EVP_CIPHER ctrl:
+ EVP_CTRL_PBE_PRF_NID this allows a cipher to specify an alternative
+ PRF which will be automatically used with PBES2.
+
+ *Steve Henson*
+
+ * Replace the algorithm specific calls to generate keys in "req" with the
+ new API.
+
+ *Steve Henson*
+
+ * Update PKCS#7 enveloped data routines to use new API. This is now
+ supported by any public key method supporting the encrypt operation. A
+ ctrl is added to allow the public key algorithm to examine or modify
+ the PKCS#7 RecipientInfo structure if it needs to: for RSA this is
+ a no op.
+
+ *Steve Henson*
+
+ * Add a ctrl to asn1 method to allow a public key algorithm to express
+ a default digest type to use. In most cases this will be SHA1 but some
+ algorithms (such as GOST) need to specify an alternative digest. The
+ return value indicates how strong the preference is 1 means optional and
+ 2 is mandatory (that is it is the only supported type). Modify
+ ASN1_item_sign() to accept a NULL digest argument to indicate it should
+ use the default md. Update openssl utilities to use the default digest
+ type for signing if it is not explicitly indicated.
+
+ *Steve Henson*
+
+ * Use OID cross reference table in ASN1_sign() and ASN1_verify(). New
+ EVP_MD flag EVP_MD_FLAG_PKEY_METHOD_SIGNATURE. This uses the relevant
+ signing method from the key type. This effectively removes the link
+ between digests and public key types.
+
+ *Steve Henson*
+
+ * Add an OID cross reference table and utility functions. Its purpose is to
+ translate between signature OIDs such as SHA1WithrsaEncryption and SHA1,
+ rsaEncryption. This will allow some of the algorithm specific hackery
+ needed to use the correct OID to be removed.
+
+ *Steve Henson*
+
+ * Remove algorithm specific dependencies when setting PKCS7_SIGNER_INFO
+ structures for PKCS7_sign(). They are now set up by the relevant public
+ key ASN1 method.
+
+ *Steve Henson*
+
+ * Add provisional EC pkey method with support for ECDSA and ECDH.
+
+ *Steve Henson*
+
+ * Add support for key derivation (agreement) in the API, DH method and
+ pkeyutl.
+
+ *Steve Henson*
+
+ * Add DSA pkey method and DH pkey methods, extend DH ASN1 method to support
+ public and private key formats. As a side effect these add additional
+ command line functionality not previously available: DSA signatures can be
+ generated and verified using pkeyutl and DH key support and generation in
+ pkey, genpkey.
+
+ *Steve Henson*
+
+ * BeOS support.
+
+ *Oliver Tappe <zooey@hirschkaefer.de>*
+
+ * New make target "install_html_docs" installs HTML renditions of the
+ manual pages.
+
+ *Oliver Tappe <zooey@hirschkaefer.de>*
+
+ * New utility "genpkey" this is analogous to "genrsa" etc except it can
+ generate keys for any algorithm. Extend and update EVP_PKEY_METHOD to
+ support key and parameter generation and add initial key generation
+ functionality for RSA.
+
+ *Steve Henson*
+
+ * Add functions for main EVP_PKEY_method operations. The undocumented
+ functions `EVP_PKEY_{encrypt,decrypt}` have been renamed to
+ `EVP_PKEY_{encrypt,decrypt}_old`.
+
+ *Steve Henson*
+
+ * Initial definitions for EVP_PKEY_METHOD. This will be a high level public
+ key API, doesn't do much yet.
+
+ *Steve Henson*
+
+ * New function EVP_PKEY_asn1_get0_info() to retrieve information about
+ public key algorithms. New option to openssl utility:
+ "list-public-key-algorithms" to print out info.
+
+ *Steve Henson*
+
+ * Implement the Supported Elliptic Curves Extension for
+ ECC ciphersuites from draft-ietf-tls-ecc-12.txt.
+
+ *Douglas Stebila*
+
+ * Don't free up OIDs in OBJ_cleanup() if they are in use by EVP_MD or
+ EVP_CIPHER structures to avoid later problems in EVP_cleanup().
+
+ *Steve Henson*
+
+ * New utilities pkey and pkeyparam. These are similar to algorithm specific
+ utilities such as rsa, dsa, dsaparam etc except they process any key
+ type.
+
+ *Steve Henson*
+
+ * Transfer public key printing routines to EVP_PKEY_ASN1_METHOD. New
+ functions EVP_PKEY_print_public(), EVP_PKEY_print_private(),
+ EVP_PKEY_print_param() to print public key data from an EVP_PKEY
+ structure.
+
+ *Steve Henson*
+
+ * Initial support for pluggable public key ASN1.
+ De-spaghettify the public key ASN1 handling. Move public and private
+ key ASN1 handling to a new EVP_PKEY_ASN1_METHOD structure. Relocate
+ algorithm specific handling to a single module within the relevant
+ algorithm directory. Add functions to allow (near) opaque processing
+ of public and private key structures.
+
+ *Steve Henson*
+
+ * Implement the Supported Point Formats Extension for
+ ECC ciphersuites from draft-ietf-tls-ecc-12.txt.
+
+ *Douglas Stebila*
+
+ * Add initial support for RFC 4279 PSK TLS ciphersuites. Add members
+ for the psk identity [hint] and the psk callback functions to the
+ SSL_SESSION, SSL and SSL_CTX structure.
+
+ New ciphersuites:
+ PSK-RC4-SHA, PSK-3DES-EDE-CBC-SHA, PSK-AES128-CBC-SHA,
+ PSK-AES256-CBC-SHA
+
+ New functions:
+ SSL_CTX_use_psk_identity_hint
+ SSL_get_psk_identity_hint
+ SSL_get_psk_identity
+ SSL_use_psk_identity_hint
+
+ *Mika Kousa and Pasi Eronen of Nokia Corporation*
+
+ * Add RFC 3161 compliant time stamp request creation, response generation
+ and response verification functionality.
+
+ *Zoltán Glózik <zglozik@opentsa.org>, The OpenTSA Project*
+
+ * Add initial support for TLS extensions, specifically for the server_name
+ extension so far. The SSL_SESSION, SSL_CTX, and SSL data structures now
+ have new members for a host name. The SSL data structure has an
+ additional member `SSL_CTX *initial_ctx` so that new sessions can be
+ stored in that context to allow for session resumption, even after the
+ SSL has been switched to a new SSL_CTX in reaction to a client's
+ server_name extension.
+
+ New functions (subject to change):
+
+ SSL_get_servername()
+ SSL_get_servername_type()
+ SSL_set_SSL_CTX()
+
+ New CTRL codes and macros (subject to change):
+
+ SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
+ - SSL_CTX_set_tlsext_servername_callback()
+ SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG
+ - SSL_CTX_set_tlsext_servername_arg()
+ SSL_CTRL_SET_TLSEXT_HOSTNAME - SSL_set_tlsext_host_name()
+
+ openssl s_client has a new '-servername ...' option.
+
+ openssl s_server has new options '-servername_host ...', '-cert2 ...',
+ '-key2 ...', '-servername_fatal' (subject to change). This allows
+ testing the HostName extension for a specific single host name ('-cert'
+ and '-key' remain fallbacks for handshakes without HostName
+ negotiation). If the unrecognized_name alert has to be sent, this by
+ default is a warning; it becomes fatal with the '-servername_fatal'
+ option.
+
+ *Peter Sylvester, Remy Allais, Christophe Renou*
+
+ * Whirlpool hash implementation is added.
+
+ *Andy Polyakov*
+
+ * BIGNUM code on 64-bit SPARCv9 targets is switched from bn(64,64) to
+ bn(64,32). Because of instruction set limitations it doesn't have
+ any negative impact on performance. This was done mostly in order
+ to make it possible to share assembler modules, such as bn_mul_mont
+ implementations, between 32- and 64-bit builds without hassle.
+
+ *Andy Polyakov*
+
+ * Move code previously exiled into file crypto/ec/ec2_smpt.c
+ to ec2_smpl.c, and no longer require the OPENSSL_EC_BIN_PT_COMP
+ macro.
+
+ *Bodo Moeller*
+
+ * New candidate for BIGNUM assembler implementation, bn_mul_mont,
+ dedicated Montgomery multiplication procedure, is introduced.
+ BN_MONT_CTX is modified to allow bn_mul_mont to reach for higher
+ "64-bit" performance on certain 32-bit targets.
+
+ *Andy Polyakov*
+
+ * New option SSL_OP_NO_COMP to disable use of compression selectively
+ in SSL structures. New SSL ctrl to set maximum send fragment size.
+ Save memory by setting the I/O buffer sizes dynamically instead of
+ using the maximum available value.
+
+ *Steve Henson*
+
+ * New option -V for 'openssl ciphers'. This prints the ciphersuite code
+ in addition to the text details.
+
+ *Bodo Moeller*
+
+ * Very, very preliminary EXPERIMENTAL support for printing of general
+ ASN1 structures. This currently produces rather ugly output and doesn't
+ handle several customised structures at all.
+
+ *Steve Henson*
+
+ * Integrated support for PVK file format and some related formats such
+ as MS PUBLICKEYBLOB and PRIVATEKEYBLOB. Command line switches to support
+ these in the 'rsa' and 'dsa' utilities.
+
+ *Steve Henson*
+
+ * Support for PKCS#1 RSAPublicKey format on rsa utility command line.
+
+ *Steve Henson*
+
+ * Remove the ancient ASN1_METHOD code. This was only ever used in one
+ place for the (very old) "NETSCAPE" format certificates which are now
+ handled using new ASN1 code equivalents.
+
+ *Steve Henson*
+
+ * Let the TLSv1_method() etc. functions return a 'const' SSL_METHOD
+ pointer and make the SSL_METHOD parameter in SSL_CTX_new,
+ SSL_CTX_set_ssl_version and SSL_set_ssl_method 'const'.
+
+ *Nils Larsch*
+
+ * Modify CRL distribution points extension code to print out previously
+ unsupported fields. Enhance extension setting code to allow setting of
+ all fields.
+
+ *Steve Henson*
+
+ * Add print and set support for Issuing Distribution Point CRL extension.
+
+ *Steve Henson*
+
+ * Change 'Configure' script to enable Camellia by default.
+
+ *NTT*
+
+OpenSSL 0.9.x
+-------------
+
+### Changes between 0.9.8m and 0.9.8n [24 Mar 2010]
+
+ * When rejecting SSL/TLS records due to an incorrect version number, never
+ update s->server with a new major version number. As of
+ - OpenSSL 0.9.8m if 'short' is a 16-bit type,
+ - OpenSSL 0.9.8f if 'short' is longer than 16 bits,
+ the previous behavior could result in a read attempt at NULL when
+ receiving specific incorrect SSL/TLS records once record payload
+ protection is active. ([CVE-2010-0740])
+
+ *Bodo Moeller, Adam Langley <agl@chromium.org>*
+
+ * Fix for CVE-2010-0433 where some kerberos enabled versions of OpenSSL
+ could be crashed if the relevant tables were not present (e.g. chrooted).
+
+ *Tomas Hoger <thoger@redhat.com>*
+
+### Changes between 0.9.8l and 0.9.8m [25 Feb 2010]
+
+ * Always check bn_wexpand() return values for failure. ([CVE-2009-3245])
+
+ *Martin Olsson, Neel Mehta*
+
+ * Fix X509_STORE locking: Every 'objs' access requires a lock (to
+ accommodate for stack sorting, always a write lock!).
+
+ *Bodo Moeller*
+
+ * On some versions of WIN32 Heap32Next is very slow. This can cause
+ excessive delays in the RAND_poll(): over a minute. As a workaround
+ include a time check in the inner Heap32Next loop too.
+
+ *Steve Henson*
+
+ * The code that handled flushing of data in SSL/TLS originally used the
+ BIO_CTRL_INFO ctrl to see if any data was pending first. This caused
+ the problem outlined in PR#1949. The fix suggested there however can
+ trigger problems with buggy BIO_CTRL_WPENDING (e.g. some versions
+ of Apache). So instead simplify the code to flush unconditionally.
+ This should be fine since flushing with no data to flush is a no op.
+
+ *Steve Henson*
+
+ * Handle TLS versions 2.0 and later properly and correctly use the
+ highest version of TLS/SSL supported. Although TLS >= 2.0 is some way
+ off ancient servers have a habit of sticking around for a while...
+
+ *Steve Henson*
+
+ * Modify compression code so it frees up structures without using the
+ ex_data callbacks. This works around a problem where some applications
+ call CRYPTO_cleanup_all_ex_data() before application exit (e.g. when
+ restarting) then use compression (e.g. SSL with compression) later.
+ This results in significant per-connection memory leaks and
+ has caused some security issues including CVE-2008-1678 and
+ CVE-2009-4355.
+
+ *Steve Henson*
+
+ * Constify crypto/cast (i.e., <openssl/cast.h>): a CAST_KEY doesn't
+ change when encrypting or decrypting.
+
+ *Bodo Moeller*
+
+ * Add option SSL_OP_LEGACY_SERVER_CONNECT which will allow clients to
+ connect and renegotiate with servers which do not support RI.
+ Until RI is more widely deployed this option is enabled by default.
+
+ *Steve Henson*
+
+ * Add "missing" ssl ctrls to clear options and mode.
+
+ *Steve Henson*
+
+ * If client attempts to renegotiate and doesn't support RI respond with
+ a no_renegotiation alert as required by RFC5746. Some renegotiating
+ TLS clients will continue a connection gracefully when they receive
+ the alert. Unfortunately OpenSSL mishandled this alert and would hang
+ waiting for a server hello which it will never receive. Now we treat a
+ received no_renegotiation alert as a fatal error. This is because
+ applications requesting a renegotiation might well expect it to succeed
+ and would have no code in place to handle the server denying it so the
+ only safe thing to do is to terminate the connection.
+
+ *Steve Henson*
+
+ * Add ctrl macro SSL_get_secure_renegotiation_support() which returns 1 if
+ peer supports secure renegotiation and 0 otherwise. Print out peer
+ renegotiation support in s_client/s_server.
+
+ *Steve Henson*
+
+ * Replace the highly broken and deprecated SPKAC certification method with
+ the updated NID creation version. This should correctly handle UTF8.
+
+ *Steve Henson*
+
+ * Implement RFC5746. Re-enable renegotiation but require the extension
+ as needed. Unfortunately, SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
+ turns out to be a bad idea. It has been replaced by
+ SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION which can be set with
+ SSL_CTX_set_options(). This is really not recommended unless you
+ know what you are doing.
+
+ *Eric Rescorla <ekr@networkresonance.com>, Ben Laurie, Steve Henson*
+
+ * Fixes to stateless session resumption handling. Use initial_ctx when
+ issuing and attempting to decrypt tickets in case it has changed during
+ servername handling. Use a non-zero length session ID when attempting
+ stateless session resumption: this makes it possible to determine if
+ a resumption has occurred immediately after receiving server hello
+ (several places in OpenSSL subtly assume this) instead of later in
+ the handshake.
+
+ *Steve Henson*
+
+ * The functions ENGINE_ctrl(), OPENSSL_isservice(),
+ CMS_get1_RecipientRequest() and RAND_bytes() can return <=0 on error
+ fixes for a few places where the return code is not checked
+ correctly.
+
+ *Julia Lawall <julia@diku.dk>*
+
+ * Add --strict-warnings option to Configure script to include devteam
+ warnings in other configurations.
+
+ *Steve Henson*
+
+ * Add support for --libdir option and LIBDIR variable in makefiles. This
+ makes it possible to install openssl libraries in locations which
+ have names other than "lib", for example "/usr/lib64" which some
+ systems need.
+
+ *Steve Henson, based on patch from Jeremy Utley*
+
+ * Don't allow the use of leading 0x80 in OIDs. This is a violation of
+ X690 8.9.12 and can produce some misleading textual output of OIDs.
+
+ *Steve Henson, reported by Dan Kaminsky*
+
+ * Delete MD2 from algorithm tables. This follows the recommendation in
+ several standards that it is not used in new applications due to
+ several cryptographic weaknesses. For binary compatibility reasons
+ the MD2 API is still compiled in by default.
+
+ *Steve Henson*
+
+ * Add compression id to {d2i,i2d}_SSL_SESSION so it is correctly saved
+ and restored.
+
+ *Steve Henson*
+
+ * Rename uni2asc and asc2uni functions to OPENSSL_uni2asc and
+ OPENSSL_asc2uni conditionally on Netware platforms to avoid a name
+ clash.
+
+ *Guenter <lists@gknw.net>*
+
+ * Fix the server certificate chain building code to use X509_verify_cert(),
+ it used to have an ad-hoc builder which was unable to cope with anything
+ other than a simple chain.
+
+ *David Woodhouse <dwmw2@infradead.org>, Steve Henson*
+
+ * Don't check self signed certificate signatures in X509_verify_cert()
+ by default (a flag can override this): it just wastes time without
+ adding any security. As a useful side effect self signed root CAs
+ with non-FIPS digests are now usable in FIPS mode.
+
+ *Steve Henson*
+
+ * In dtls1_process_out_of_seq_message() the check if the current message
+ is already buffered was missing. For every new message was memory
+ allocated, allowing an attacker to perform an denial of service attack
+ with sending out of seq handshake messages until there is no memory
+ left. Additionally every future message was buffered, even if the
+ sequence number made no sense and would be part of another handshake.
+ So only messages with sequence numbers less than 10 in advance will be
+ buffered. ([CVE-2009-1378])
+
+ *Robin Seggelmann, discovered by Daniel Mentz*
+
+ * Records are buffered if they arrive with a future epoch to be
+ processed after finishing the corresponding handshake. There is
+ currently no limitation to this buffer allowing an attacker to perform
+ a DOS attack with sending records with future epochs until there is no
+ memory left. This patch adds the pqueue_size() function to determine
+ the size of a buffer and limits the record buffer to 100 entries.
+ ([CVE-2009-1377])
+
+ *Robin Seggelmann, discovered by Daniel Mentz*
+
+ * Keep a copy of frag->msg_header.frag_len so it can be used after the
+ parent structure is freed. ([CVE-2009-1379])
+
+ *Daniel Mentz*
+
+ * Handle non-blocking I/O properly in SSL_shutdown() call.
+
+ *Darryl Miles <darryl-mailinglists@netbauds.net>*
+
+ * Add `2.5.4.*` OIDs
+
+ *Ilya O. <vrghost@gmail.com>*
+
+### Changes between 0.9.8k and 0.9.8l [5 Nov 2009]
+
+ * Disable renegotiation completely - this fixes a severe security
+ problem ([CVE-2009-3555]) at the cost of breaking all
+ renegotiation. Renegotiation can be re-enabled by setting
+ SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION in s3->flags at
+ run-time. This is really not recommended unless you know what
+ you're doing.
+
+ *Ben Laurie*
+
+### Changes between 0.9.8j and 0.9.8k [25 Mar 2009]
+
+ * Don't set val to NULL when freeing up structures, it is freed up by
+ underlying code. If `sizeof(void *) > sizeof(long)` this can result in
+ zeroing past the valid field. ([CVE-2009-0789])
+
+ *Paolo Ganci <Paolo.Ganci@AdNovum.CH>*
+
+ * Fix bug where return value of CMS_SignerInfo_verify_content() was not
+ checked correctly. This would allow some invalid signed attributes to
+ appear to verify correctly. ([CVE-2009-0591])
+
+ *Ivan Nestlerode <inestlerode@us.ibm.com>*
+
+ * Reject UniversalString and BMPString types with invalid lengths. This
+ prevents a crash in ASN1_STRING_print_ex() which assumes the strings have
+ a legal length. ([CVE-2009-0590])
+
+ *Steve Henson*
+
+ * Set S/MIME signing as the default purpose rather than setting it
+ unconditionally. This allows applications to override it at the store
+ level.
+
+ *Steve Henson*
+
+ * Permit restricted recursion of ASN1 strings. This is needed in practice
+ to handle some structures.
+
+ *Steve Henson*
+
+ * Improve efficiency of mem_gets: don't search whole buffer each time
+ for a '\n'
+
+ *Jeremy Shapiro <jnshapir@us.ibm.com>*
+
+ * New -hex option for openssl rand.
+
+ *Matthieu Herrb*
+
+ * Print out UTF8String and NumericString when parsing ASN1.
+
+ *Steve Henson*
+
+ * Support NumericString type for name components.
+
+ *Steve Henson*
+
+ * Allow CC in the environment to override the automatically chosen
+ compiler. Note that nothing is done to ensure flags work with the
+ chosen compiler.
+
+ *Ben Laurie*
+
+### Changes between 0.9.8i and 0.9.8j [07 Jan 2009]
+
+ * Properly check EVP_VerifyFinal() and similar return values
+ ([CVE-2008-5077]).
+
+ *Ben Laurie, Bodo Moeller, Google Security Team*
+
+ * Enable TLS extensions by default.
+
+ *Ben Laurie*
+
+ * Allow the CHIL engine to be loaded, whether the application is
+ multithreaded or not. (This does not release the developer from the
+ obligation to set up the dynamic locking callbacks.)
+
+ *Sander Temme <sander@temme.net>*
+
+ * Use correct exit code if there is an error in dgst command.
+
+ *Steve Henson; problem pointed out by Roland Dirlewanger*
+
+ * Tweak Configure so that you need to say "experimental-jpake" to enable
+ JPAKE, and need to use -DOPENSSL_EXPERIMENTAL_JPAKE in applications.
+
+ *Bodo Moeller*
+
+ * Add experimental JPAKE support, including demo authentication in
+ s_client and s_server.
+
+ *Ben Laurie*
+
+ * Set the comparison function in v3_addr_canonize().
+
+ *Rob Austein <sra@hactrn.net>*
+
+ * Add support for XMPP STARTTLS in s_client.
+
+ *Philip Paeps <philip@freebsd.org>*
+
+ * Change the server-side SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG behavior
+ to ensure that even with this option, only ciphersuites in the
+ server's preference list will be accepted. (Note that the option
+ applies only when resuming a session, so the earlier behavior was
+ just about the algorithm choice for symmetric cryptography.)
+
+ *Bodo Moeller*
+
+### Changes between 0.9.8h and 0.9.8i [15 Sep 2008]
+
+ * Fix NULL pointer dereference if a DTLS server received
+ ChangeCipherSpec as first record ([CVE-2009-1386]).
+
+ *PR #1679*
+
+ * Fix a state transition in s3_srvr.c and d1_srvr.c
+ (was using SSL3_ST_CW_CLNT_HELLO_B, should be `..._ST_SW_SRVR_...`).
+
+ *Nagendra Modadugu*
+
+ * The fix in 0.9.8c that supposedly got rid of unsafe
+ double-checked locking was incomplete for RSA blinding,
+ addressing just one layer of what turns out to have been
+ doubly unsafe triple-checked locking.
+
+ So now fix this for real by retiring the MONT_HELPER macro
+ in crypto/rsa/rsa_eay.c.
+
+ *Bodo Moeller; problem pointed out by Marius Schilder*
+
+ * Various precautionary measures:
+
+ - Avoid size_t integer overflow in HASH_UPDATE (md32_common.h).
+
+ - Avoid a buffer overflow in d2i_SSL_SESSION() (ssl_asn1.c).
+ (NB: This would require knowledge of the secret session ticket key
+ to exploit, in which case you'd be SOL either way.)
+
+ - Change bn_nist.c so that it will properly handle input BIGNUMs
+ outside the expected range.
+
+ - Enforce the 'num' check in BN_div() (bn_div.c) for non-BN_DEBUG
+ builds.
+
+ *Neel Mehta, Bodo Moeller*
+
+ * Allow engines to be "soft loaded" - i.e. optionally don't die if
+ the load fails. Useful for distros.
+
+ *Ben Laurie and the FreeBSD team*
+
+ * Add support for Local Machine Keyset attribute in PKCS#12 files.
+
+ *Steve Henson*
+
+ * Fix BN_GF2m_mod_arr() top-bit cleanup code.
+
+ *Huang Ying*
+
+ * Expand ENGINE to support engine supplied SSL client certificate functions.
+
+ This work was sponsored by Logica.
+
+ *Steve Henson*
+
+ * Add CryptoAPI ENGINE to support use of RSA and DSA keys held in Windows
+ keystores. Support for SSL/TLS client authentication too.
+ Not compiled unless enable-capieng specified to Configure.
+
+ This work was sponsored by Logica.
+
+ *Steve Henson*
+
+ * Fix bug in X509_ATTRIBUTE creation: don't set attribute using
+ ASN1_TYPE_set1 if MBSTRING flag set. This bug would crash certain
+ attribute creation routines such as certificate requests and PKCS#12
+ files.
+
+ *Steve Henson*
+
+### Changes between 0.9.8g and 0.9.8h [28 May 2008]
+
+ * Fix flaw if 'Server Key exchange message' is omitted from a TLS
+ handshake which could lead to a client crash as found using the
+ Codenomicon TLS test suite ([CVE-2008-1672])
+
+ *Steve Henson, Mark Cox*
+
+ * Fix double free in TLS server name extensions which could lead to
+ a remote crash found by Codenomicon TLS test suite ([CVE-2008-0891])
+
+ *Joe Orton*
+
+ * Clear error queue in SSL_CTX_use_certificate_chain_file()
+
+ Clear the error queue to ensure that error entries left from
+ older function calls do not interfere with the correct operation.
+
+ *Lutz Jaenicke, Erik de Castro Lopo*
+
+ * Remove root CA certificates of commercial CAs:
+
+ The OpenSSL project does not recommend any specific CA and does not
+ have any policy with respect to including or excluding any CA.
+ Therefore it does not make any sense to ship an arbitrary selection
+ of root CA certificates with the OpenSSL software.
+
+ *Lutz Jaenicke*
+
+ * RSA OAEP patches to fix two separate invalid memory reads.
+ The first one involves inputs when 'lzero' is greater than
+ 'SHA_DIGEST_LENGTH' (it would read about SHA_DIGEST_LENGTH bytes
+ before the beginning of from). The second one involves inputs where
+ the 'db' section contains nothing but zeroes (there is a one-byte
+ invalid read after the end of 'db').
+
+ *Ivan Nestlerode <inestlerode@us.ibm.com>*
+
+ * Partial backport from 0.9.9-dev:
+
+ Introduce bn_mul_mont (dedicated Montgomery multiplication
+ procedure) as a candidate for BIGNUM assembler implementation.
+ While 0.9.9-dev uses assembler for various architectures, only
+ x86_64 is available by default here in the 0.9.8 branch, and
+ 32-bit x86 is available through a compile-time setting.
+
+ To try the 32-bit x86 assembler implementation, use Configure
+ option "enable-montasm" (which exists only for this backport).
+
+ As "enable-montasm" for 32-bit x86 disclaims code stability
+ anyway, in this constellation we activate additional code
+ backported from 0.9.9-dev for further performance improvements,
+ namely BN_from_montgomery_word. (To enable this otherwise,
+ e.g. x86_64, try `-DMONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD`.)
+
+ *Andy Polyakov (backport partially by Bodo Moeller)*
+
+ * Add TLS session ticket callback. This allows an application to set
+ TLS ticket cipher and HMAC keys rather than relying on hardcoded fixed
+ values. This is useful for key rollover for example where several key
+ sets may exist with different names.
+
+ *Steve Henson*
+
+ * Reverse ENGINE-internal logic for caching default ENGINE handles.
+ This was broken until now in 0.9.8 releases, such that the only way
+ a registered ENGINE could be used (assuming it initialises
+ successfully on the host) was to explicitly set it as the default
+ for the relevant algorithms. This is in contradiction with 0.9.7
+ behaviour and the documentation. With this fix, when an ENGINE is
+ registered into a given algorithm's table of implementations, the
+ 'uptodate' flag is reset so that auto-discovery will be used next
+ time a new context for that algorithm attempts to select an
+ implementation.
+
+ *Ian Lister (tweaked by Geoff Thorpe)*
+
+ * Backport of CMS code to OpenSSL 0.9.8. This differs from the 0.9.9
+ implementation in the following ways:
+
+ Lack of EVP_PKEY_ASN1_METHOD means algorithm parameters have to be
+ hard coded.
+
+ Lack of BER streaming support means one pass streaming processing is
+ only supported if data is detached: setting the streaming flag is
+ ignored for embedded content.
+
+ CMS support is disabled by default and must be explicitly enabled
+ with the enable-cms configuration option.
+
+ *Steve Henson*
+
+ * Update the GMP engine glue to do direct copies between BIGNUM and
+ mpz_t when openssl and GMP use the same limb size. Otherwise the
+ existing "conversion via a text string export" trick is still used.
+
+ *Paul Sheer <paulsheer@gmail.com>*
+
+ * Zlib compression BIO. This is a filter BIO which compressed and
+ uncompresses any data passed through it.
+
+ *Steve Henson*
+
+ * Add AES_wrap_key() and AES_unwrap_key() functions to implement
+ RFC3394 compatible AES key wrapping.
+
+ *Steve Henson*
+
+ * Add utility functions to handle ASN1 structures. ASN1_STRING_set0():
+ sets string data without copying. X509_ALGOR_set0() and
+ X509_ALGOR_get0(): set and retrieve X509_ALGOR (AlgorithmIdentifier)
+ data. Attribute function X509at_get0_data_by_OBJ(): retrieves data
+ from an X509_ATTRIBUTE structure optionally checking it occurs only
+ once. ASN1_TYPE_set1(): set and ASN1_TYPE structure copying supplied
+ data.
+
+ *Steve Henson*
+
+ * Fix BN flag handling in RSA_eay_mod_exp() and BN_MONT_CTX_set()
+ to get the expected BN_FLG_CONSTTIME behavior.
+
+ *Bodo Moeller (Google)*
+
+ * Netware support:
+
+ - fixed wrong usage of ioctlsocket() when build for LIBC BSD sockets
+ - fixed do_tests.pl to run the test suite with CLIB builds too (CLIB_OPT)
+ - added some more tests to do_tests.pl
+ - fixed RunningProcess usage so that it works with newer LIBC NDKs too
+ - removed usage of BN_LLONG for CLIB builds to avoid runtime dependency
+ - added new Configure targets netware-clib-bsdsock, netware-clib-gcc,
+ netware-clib-bsdsock-gcc, netware-libc-bsdsock-gcc
+ - various changes to netware.pl to enable gcc-cross builds on Win32
+ platform
+ - changed crypto/bio/b_sock.c to work with macro functions (CLIB BSD)
+ - various changes to fix missing prototype warnings
+ - fixed x86nasm.pl to create correct asm files for NASM COFF output
+ - added AES, WHIRLPOOL and CPUID assembler code to build files
+ - added missing AES assembler make rules to mk1mf.pl
+ - fixed order of includes in `apps/ocsp.c` so that `e_os.h` settings apply
+
+ *Guenter Knauf <eflash@gmx.net>*
+
+ * Implement certificate status request TLS extension defined in RFC3546.
+ A client can set the appropriate parameters and receive the encoded
+ OCSP response via a callback. A server can query the supplied parameters
+ and set the encoded OCSP response in the callback. Add simplified examples
+ to s_client and s_server.
+
+ *Steve Henson*
+
+### Changes between 0.9.8f and 0.9.8g [19 Oct 2007]
+
+ * Fix various bugs:
+ + Binary incompatibility of ssl_ctx_st structure
+ + DTLS interoperation with non-compliant servers
+ + Don't call get_session_cb() without proposed session
+ + Fix ia64 assembler code
+
+ *Andy Polyakov, Steve Henson*
+
+### Changes between 0.9.8e and 0.9.8f [11 Oct 2007]
+
+ * DTLS Handshake overhaul. There were longstanding issues with
+ OpenSSL DTLS implementation, which were making it impossible for
+ RFC 4347 compliant client to communicate with OpenSSL server.
+ Unfortunately just fixing these incompatibilities would "cut off"
+ pre-0.9.8f clients. To allow for hassle free upgrade post-0.9.8e
+ server keeps tolerating non RFC compliant syntax. The opposite is
+ not true, 0.9.8f client can not communicate with earlier server.
+ This update even addresses CVE-2007-4995.
+
+ *Andy Polyakov*
+
+ * Changes to avoid need for function casts in OpenSSL: some compilers
+ (gcc 4.2 and later) reject their use.
+ *Kurt Roeckx <kurt@roeckx.be>, Peter Hartley <pdh@utter.chaos.org.uk>,
+ Steve Henson*
+
+ * Add RFC4507 support to OpenSSL. This includes the corrections in
+ RFC4507bis. The encrypted ticket format is an encrypted encoded
+ SSL_SESSION structure, that way new session features are automatically
+ supported.
+
+ If a client application caches session in an SSL_SESSION structure
+ support is transparent because tickets are now stored in the encoded
+ SSL_SESSION.
+
+ The SSL_CTX structure automatically generates keys for ticket
+ protection in servers so again support should be possible
+ with no application modification.
+
+ If a client or server wishes to disable RFC4507 support then the option
+ SSL_OP_NO_TICKET can be set.
+
+ Add a TLS extension debugging callback to allow the contents of any client
+ or server extensions to be examined.
+
+ This work was sponsored by Google.
+
+ *Steve Henson*
+
+ * Add initial support for TLS extensions, specifically for the server_name
+ extension so far. The SSL_SESSION, SSL_CTX, and SSL data structures now
+ have new members for a host name. The SSL data structure has an
+ additional member `SSL_CTX *initial_ctx` so that new sessions can be
+ stored in that context to allow for session resumption, even after the
+ SSL has been switched to a new SSL_CTX in reaction to a client's
+ server_name extension.
+
+ New functions (subject to change):
+
+ SSL_get_servername()
+ SSL_get_servername_type()
+ SSL_set_SSL_CTX()
+
+ New CTRL codes and macros (subject to change):
+
+ SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
+ - SSL_CTX_set_tlsext_servername_callback()
+ SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG
+ - SSL_CTX_set_tlsext_servername_arg()
+ SSL_CTRL_SET_TLSEXT_HOSTNAME - SSL_set_tlsext_host_name()
+
+ openssl s_client has a new '-servername ...' option.
+
+ openssl s_server has new options '-servername_host ...', '-cert2 ...',
+ '-key2 ...', '-servername_fatal' (subject to change). This allows
+ testing the HostName extension for a specific single host name ('-cert'
+ and '-key' remain fallbacks for handshakes without HostName
+ negotiation). If the unrecognized_name alert has to be sent, this by
+ default is a warning; it becomes fatal with the '-servername_fatal'
+ option.
+
+ *Peter Sylvester, Remy Allais, Christophe Renou, Steve Henson*
+
+ * Add AES and SSE2 assembly language support to VC++ build.
+
+ *Steve Henson*
+
+ * Mitigate attack on final subtraction in Montgomery reduction.
+
+ *Andy Polyakov*
+
+ * Fix crypto/ec/ec_mult.c to work properly with scalars of value 0
+ (which previously caused an internal error).
+
+ *Bodo Moeller*
+
+ * Squeeze another 10% out of IGE mode when in != out.
+
+ *Ben Laurie*
+
+ * AES IGE mode speedup.
+
+ *Dean Gaudet (Google)*
+
+ * Add the Korean symmetric 128-bit cipher SEED (see
+ <http://www.kisa.or.kr/kisa/seed/jsp/seed_eng.jsp>) and
+ add SEED ciphersuites from RFC 4162:
+
+ TLS_RSA_WITH_SEED_CBC_SHA = "SEED-SHA"
+ TLS_DHE_DSS_WITH_SEED_CBC_SHA = "DHE-DSS-SEED-SHA"
+ TLS_DHE_RSA_WITH_SEED_CBC_SHA = "DHE-RSA-SEED-SHA"
+ TLS_DH_anon_WITH_SEED_CBC_SHA = "ADH-SEED-SHA"
+
+ To minimize changes between patchlevels in the OpenSSL 0.9.8
+ series, SEED remains excluded from compilation unless OpenSSL
+ is configured with 'enable-seed'.
+
+ *KISA, Bodo Moeller*
+
+ * Mitigate branch prediction attacks, which can be practical if a
+ single processor is shared, allowing a spy process to extract
+ information. For detailed background information, see
+ <http://eprint.iacr.org/2007/039> (O. Aciicmez, S. Gueron,
+ J.-P. Seifert, "New Branch Prediction Vulnerabilities in OpenSSL
+ and Necessary Software Countermeasures"). The core of the change
+ are new versions BN_div_no_branch() and
+ BN_mod_inverse_no_branch() of BN_div() and BN_mod_inverse(),
+ respectively, which are slower, but avoid the security-relevant
+ conditional branches. These are automatically called by BN_div()
+ and BN_mod_inverse() if the flag BN_FLG_CONSTTIME is set for one
+ of the input BIGNUMs. Also, BN_is_bit_set() has been changed to
+ remove a conditional branch.
+
+ BN_FLG_CONSTTIME is the new name for the previous
+ BN_FLG_EXP_CONSTTIME flag, since it now affects more than just
+ modular exponentiation. (Since OpenSSL 0.9.7h, setting this flag
+ in the exponent causes BN_mod_exp_mont() to use the alternative
+ implementation in BN_mod_exp_mont_consttime().) The old name
+ remains as a deprecated alias.
+
+ Similarly, RSA_FLAG_NO_EXP_CONSTTIME is replaced by a more general
+ RSA_FLAG_NO_CONSTTIME flag since the RSA implementation now uses
+ constant-time implementations for more than just exponentiation.
+ Here too the old name is kept as a deprecated alias.
+
+ BN_BLINDING_new() will now use BN_dup() for the modulus so that
+ the BN_BLINDING structure gets an independent copy of the
+ modulus. This means that the previous `BIGNUM *m` argument to
+ BN_BLINDING_new() and to BN_BLINDING_create_param() now
+ essentially becomes `const BIGNUM *m`, although we can't actually
+ change this in the header file before 0.9.9. It allows
+ RSA_setup_blinding() to use BN_with_flags() on the modulus to
+ enable BN_FLG_CONSTTIME.
+
+ *Matthew D Wood (Intel Corp)*
+
+ * In the SSL/TLS server implementation, be strict about session ID
+ context matching (which matters if an application uses a single
+ external cache for different purposes). Previously,
+ out-of-context reuse was forbidden only if SSL_VERIFY_PEER was
+ set. This did ensure strict client verification, but meant that,
+ with applications using a single external cache for quite
+ different requirements, clients could circumvent ciphersuite
+ restrictions for a given session ID context by starting a session
+ in a different context.
+
+ *Bodo Moeller*
+
+ * Include "!eNULL" in SSL_DEFAULT_CIPHER_LIST to make sure that
+ a ciphersuite string such as "DEFAULT:RSA" cannot enable
+ authentication-only ciphersuites.
+
+ *Bodo Moeller*
+
+ * Update the SSL_get_shared_ciphers() fix CVE-2006-3738 which was
+ not complete and could lead to a possible single byte overflow
+ ([CVE-2007-5135]) [Ben Laurie]
+
+### Changes between 0.9.8d and 0.9.8e [23 Feb 2007]
+
+ * Since AES128 and AES256 (and similarly Camellia128 and
+ Camellia256) share a single mask bit in the logic of
+ ssl/ssl_ciph.c, the code for masking out disabled ciphers needs a
+ kludge to work properly if AES128 is available and AES256 isn't
+ (or if Camellia128 is available and Camellia256 isn't).
+
+ *Victor Duchovni*
+
+ * Fix the BIT STRING encoding generated by crypto/ec/ec_asn1.c
+ (within i2d_ECPrivateKey, i2d_ECPKParameters, i2d_ECParameters):
+ When a point or a seed is encoded in a BIT STRING, we need to
+ prevent the removal of trailing zero bits to get the proper DER
+ encoding. (By default, crypto/asn1/a_bitstr.c assumes the case
+ of a NamedBitList, for which trailing 0 bits need to be removed.)
+
+ *Bodo Moeller*
+
+ * Have SSL/TLS server implementation tolerate "mismatched" record
+ protocol version while receiving ClientHello even if the
+ ClientHello is fragmented. (The server can't insist on the
+ particular protocol version it has chosen before the ServerHello
+ message has informed the client about his choice.)
+
+ *Bodo Moeller*
+
+ * Add RFC 3779 support.
+
+ *Rob Austein for ARIN, Ben Laurie*
+
+ * Load error codes if they are not already present instead of using a
+ static variable. This allows them to be cleanly unloaded and reloaded.
+ Improve header file function name parsing.
+
+ *Steve Henson*
+
+ * extend SMTP and IMAP protocol emulation in s_client to use EHLO
+ or CAPABILITY handshake as required by RFCs.
+
+ *Goetz Babin-Ebell*
+
+### Changes between 0.9.8c and 0.9.8d [28 Sep 2006]
+
+ * Introduce limits to prevent malicious keys being able to
+ cause a denial of service. ([CVE-2006-2940])
+
+ *Steve Henson, Bodo Moeller*
+
+ * Fix ASN.1 parsing of certain invalid structures that can result
+ in a denial of service. ([CVE-2006-2937]) [Steve Henson]
+
+ * Fix buffer overflow in SSL_get_shared_ciphers() function.
+ ([CVE-2006-3738]) [Tavis Ormandy and Will Drewry, Google Security Team]
+
+ * Fix SSL client code which could crash if connecting to a
+ malicious SSLv2 server. ([CVE-2006-4343])
+
+ *Tavis Ormandy and Will Drewry, Google Security Team*
+
+ * Since 0.9.8b, ciphersuite strings naming explicit ciphersuites
+ match only those. Before that, "AES256-SHA" would be interpreted
+ as a pattern and match "AES128-SHA" too (since AES128-SHA got
+ the same strength classification in 0.9.7h) as we currently only
+ have a single AES bit in the ciphersuite description bitmap.
+ That change, however, also applied to ciphersuite strings such as
+ "RC4-MD5" that intentionally matched multiple ciphersuites --
+ namely, SSL 2.0 ciphersuites in addition to the more common ones
+ from SSL 3.0/TLS 1.0.
+
+ So we change the selection algorithm again: Naming an explicit
+ ciphersuite selects this one ciphersuite, and any other similar
+ ciphersuite (same bitmap) from *other* protocol versions.
+ Thus, "RC4-MD5" again will properly select both the SSL 2.0
+ ciphersuite and the SSL 3.0/TLS 1.0 ciphersuite.
+
+ Since SSL 2.0 does not have any ciphersuites for which the
+ 128/256 bit distinction would be relevant, this works for now.
+ The proper fix will be to use different bits for AES128 and
+ AES256, which would have avoided the problems from the beginning;
+ however, bits are scarce, so we can only do this in a new release
+ (not just a patchlevel) when we can change the SSL_CIPHER
+ definition to split the single 'unsigned long mask' bitmap into
+ multiple values to extend the available space.
+
+ *Bodo Moeller*
+
+### Changes between 0.9.8b and 0.9.8c [05 Sep 2006]
+
+ * Avoid PKCS #1 v1.5 signature attack discovered by Daniel Bleichenbacher
+ ([CVE-2006-4339]) [Ben Laurie and Google Security Team]
+
+ * Add AES IGE and biIGE modes.
+
+ *Ben Laurie*
+
+ * Change the Unix randomness entropy gathering to use poll() when
+ possible instead of select(), since the latter has some
+ undesirable limitations.
+
+ *Darryl Miles via Richard Levitte and Bodo Moeller*
+
+ * Disable "ECCdraft" ciphersuites more thoroughly. Now special
+ treatment in ssl/ssl_ciph.s makes sure that these ciphersuites
+ cannot be implicitly activated as part of, e.g., the "AES" alias.
+ However, please upgrade to OpenSSL 0.9.9[-dev] for
+ non-experimental use of the ECC ciphersuites to get TLS extension
+ support, which is required for curve and point format negotiation
+ to avoid potential handshake problems.
+
+ *Bodo Moeller*
+
+ * Disable rogue ciphersuites:
+
+ - SSLv2 0x08 0x00 0x80 ("RC4-64-MD5")
+ - SSLv3/TLSv1 0x00 0x61 ("EXP1024-RC2-CBC-MD5")
+ - SSLv3/TLSv1 0x00 0x60 ("EXP1024-RC4-MD5")
+
+ The latter two were purportedly from
+ draft-ietf-tls-56-bit-ciphersuites-0[01].txt, but do not really
+ appear there.
+
+ Also deactivate the remaining ciphersuites from
+ draft-ietf-tls-56-bit-ciphersuites-01.txt. These are just as
+ unofficial, and the ID has long expired.
+
+ *Bodo Moeller*
+
+ * Fix RSA blinding Heisenbug (problems sometimes occurred on
+ dual-core machines) and other potential thread-safety issues.
+
+ *Bodo Moeller*
+
+ * Add the symmetric cipher Camellia (128-bit, 192-bit, 256-bit key
+ versions), which is now available for royalty-free use
+ (see <http://info.isl.ntt.co.jp/crypt/eng/info/chiteki.html>).
+ Also, add Camellia TLS ciphersuites from RFC 4132.
+
+ To minimize changes between patchlevels in the OpenSSL 0.9.8
+ series, Camellia remains excluded from compilation unless OpenSSL
+ is configured with 'enable-camellia'.
+
+ *NTT*
+
+ * Disable the padding bug check when compression is in use. The padding
+ bug check assumes the first packet is of even length, this is not
+ necessarily true if compression is enabled and can result in false
+ positives causing handshake failure. The actual bug test is ancient
+ code so it is hoped that implementations will either have fixed it by
+ now or any which still have the bug do not support compression.
+
+ *Steve Henson*
+
+### Changes between 0.9.8a and 0.9.8b [04 May 2006]
+
+ * When applying a cipher rule check to see if string match is an explicit
+ cipher suite and only match that one cipher suite if it is.
+
+ *Steve Henson*
+
+ * Link in manifests for VC++ if needed.
+
+ *Austin Ziegler <halostatue@gmail.com>*
+
+ * Update support for ECC-based TLS ciphersuites according to
+ draft-ietf-tls-ecc-12.txt with proposed changes (but without
+ TLS extensions, which are supported starting with the 0.9.9
+ branch, not in the OpenSSL 0.9.8 branch).
+
+ *Douglas Stebila*
+
+ * New functions EVP_CIPHER_CTX_new() and EVP_CIPHER_CTX_free() to support
+ opaque EVP_CIPHER_CTX handling.
+
+ *Steve Henson*
+
+ * Fixes and enhancements to zlib compression code. We now only use
+ "zlib1.dll" and use the default `__cdecl` calling convention on Win32
+ to conform with the standards mentioned here:
+ <http://www.zlib.net/DLL_FAQ.txt>
+ Static zlib linking now works on Windows and the new --with-zlib-include
+ --with-zlib-lib options to Configure can be used to supply the location
+ of the headers and library. Gracefully handle case where zlib library
+ can't be loaded.
+
+ *Steve Henson*
+
+ * Several fixes and enhancements to the OID generation code. The old code
+ sometimes allowed invalid OIDs (1.X for X >= 40 for example), couldn't
+ handle numbers larger than ULONG_MAX, truncated printing and had a
+ non standard OBJ_obj2txt() behaviour.
+
+ *Steve Henson*
+
+ * Add support for building of engines under engine/ as shared libraries
+ under VC++ build system.
+
+ *Steve Henson*
+
+ * Corrected the numerous bugs in the Win32 path splitter in DSO.
+ Hopefully, we will not see any false combination of paths any more.
+
+ *Richard Levitte*
+
+### Changes between 0.9.8 and 0.9.8a [11 Oct 2005]
+
+ * Remove the functionality of SSL_OP_MSIE_SSLV2_RSA_PADDING
+ (part of SSL_OP_ALL). This option used to disable the
+ countermeasure against man-in-the-middle protocol-version
+ rollback in the SSL 2.0 server implementation, which is a bad
+ idea. ([CVE-2005-2969])
+
+ *Bodo Moeller; problem pointed out by Yutaka Oiwa (Research Center
+ for Information Security, National Institute of Advanced Industrial
+ Science and Technology [AIST], Japan)*
+
+ * Add two function to clear and return the verify parameter flags.
+
+ *Steve Henson*
+
+ * Keep cipherlists sorted in the source instead of sorting them at
+ runtime, thus removing the need for a lock.
+
+ *Nils Larsch*
+
+ * Avoid some small subgroup attacks in Diffie-Hellman.
+
+ *Nick Mathewson and Ben Laurie*
+
+ * Add functions for well-known primes.
+
+ *Nick Mathewson*
+
+ * Extended Windows CE support.
+
+ *Satoshi Nakamura and Andy Polyakov*
+
+ * Initialize SSL_METHOD structures at compile time instead of during
+ runtime, thus removing the need for a lock.
+
+ *Steve Henson*
+
+ * Make PKCS7_decrypt() work even if no certificate is supplied by
+ attempting to decrypt each encrypted key in turn. Add support to
+ smime utility.
+
+ *Steve Henson*
+
+### Changes between 0.9.7h and 0.9.8 [05 Jul 2005]
+
+[NB: OpenSSL 0.9.7i and later 0.9.7 patch levels were released after
+OpenSSL 0.9.8.]
+
+ * Add libcrypto.pc and libssl.pc for those who feel they need them.
+
+ *Richard Levitte*
+
+ * Change CA.sh and CA.pl so they don't bundle the CSR and the private
+ key into the same file any more.
+
+ *Richard Levitte*
+
+ * Add initial support for Win64, both IA64 and AMD64/x64 flavors.
+
+ *Andy Polyakov*
+
+ * Add -utf8 command line and config file option to 'ca'.
+
+ *Stefan <stf@udoma.org*
+
+ * Removed the macro des_crypt(), as it seems to conflict with some
+ libraries. Use DES_crypt().
+
+ *Richard Levitte*
+
+ * Correct naming of the 'chil' and '4758cca' ENGINEs. This
+ involves renaming the source and generated shared-libs for
+ both. The engines will accept the corrected or legacy ids
+ ('ncipher' and '4758_cca' respectively) when binding. NB,
+ this only applies when building 'shared'.
+
+ *Corinna Vinschen <vinschen@redhat.com> and Geoff Thorpe*
+
+ * Add attribute functions to EVP_PKEY structure. Modify
+ PKCS12_create() to recognize a CSP name attribute and
+ use it. Make -CSP option work again in pkcs12 utility.
+
+ *Steve Henson*
+
+ * Add new functionality to the bn blinding code:
+ - automatic re-creation of the BN_BLINDING parameters after
+ a fixed number of uses (currently 32)
+ - add new function for parameter creation
+ - introduce flags to control the update behaviour of the
+ BN_BLINDING parameters
+ - hide BN_BLINDING structure
+ Add a second BN_BLINDING slot to the RSA structure to improve
+ performance when a single RSA object is shared among several
+ threads.
+
+ *Nils Larsch*
+
+ * Add support for DTLS.
+
+ *Nagendra Modadugu <nagendra@cs.stanford.edu> and Ben Laurie*
+
+ * Add support for DER encoded private keys (SSL_FILETYPE_ASN1)
+ to SSL_CTX_use_PrivateKey_file() and SSL_use_PrivateKey_file()
+
+ *Walter Goulet*
+
+ * Remove buggy and incomplete DH cert support from
+ ssl/ssl_rsa.c and ssl/s3_both.c
+
+ *Nils Larsch*
+
+ * Use SHA-1 instead of MD5 as the default digest algorithm for
+ the `apps/openssl` commands.
+
+ *Nils Larsch*
+
+ * Compile clean with "-Wall -Wmissing-prototypes
+ -Wstrict-prototypes -Wmissing-declarations -Werror". Currently
+ DEBUG_SAFESTACK must also be set.
+
+ *Ben Laurie*
+
+ * Change ./Configure so that certain algorithms can be disabled by default.
+ The new counterpiece to "no-xxx" is "enable-xxx".
+
+ The patented RC5 and MDC2 algorithms will now be disabled unless
+ "enable-rc5" and "enable-mdc2", respectively, are specified.
+
+ (IDEA remains enabled despite being patented. This is because IDEA
+ is frequently required for interoperability, and there is no license
+ fee for non-commercial use. As before, "no-idea" can be used to
+ avoid this algorithm.)
+
+ *Bodo Moeller*
+
+ * Add processing of proxy certificates (see RFC 3820). This work was
+ sponsored by KTH (The Royal Institute of Technology in Stockholm) and
+ EGEE (Enabling Grids for E-science in Europe).
+
+ *Richard Levitte*
+
+ * RC4 performance overhaul on modern architectures/implementations, such
+ as Intel P4, IA-64 and AMD64.
+
+ *Andy Polyakov*
+
+ * New utility extract-section.pl. This can be used specify an alternative
+ section number in a pod file instead of having to treat each file as
+ a separate case in Makefile. This can be done by adding two lines to the
+ pod file:
+
+ =for comment openssl_section:XXX
+
+ The blank line is mandatory.
+
+ *Steve Henson*
+
+ * New arguments -certform, -keyform and -pass for s_client and s_server
+ to allow alternative format key and certificate files and passphrase
+ sources.
+
+ *Steve Henson*
+
+ * New structure X509_VERIFY_PARAM which combines current verify parameters,
+ update associated structures and add various utility functions.
+
+ Add new policy related verify parameters, include policy checking in
+ standard verify code. Enhance 'smime' application with extra parameters
+ to support policy checking and print out.
+
+ *Steve Henson*
+
+ * Add a new engine to support VIA PadLock ACE extensions in the VIA C3
+ Nehemiah processors. These extensions support AES encryption in hardware
+ as well as RNG (though RNG support is currently disabled).
+
+ *Michal Ludvig <michal@logix.cz>, with help from Andy Polyakov*
+
+ * Deprecate `BN_[get|set]_params()` functions (they were ignored internally).
+
+ *Geoff Thorpe*
+
+ * New FIPS 180-2 algorithms, SHA-224/-256/-384/-512 are implemented.
+
+ *Andy Polyakov and a number of other people*
+
+ * Improved PowerPC platform support. Most notably BIGNUM assembler
+ implementation contributed by IBM.
+
+ *Suresh Chari, Peter Waltenberg, Andy Polyakov*
+
+ * The new 'RSA_generate_key_ex' function now takes a BIGNUM for the public
+ exponent rather than 'unsigned long'. There is a corresponding change to
+ the new 'rsa_keygen' element of the RSA_METHOD structure.
+
+ *Jelte Jansen, Geoff Thorpe*
+
+ * Functionality for creating the initial serial number file is now
+ moved from CA.pl to the 'ca' utility with a new option -create_serial.
+
+ (Before OpenSSL 0.9.7e, CA.pl used to initialize the serial
+ number file to 1, which is bound to cause problems. To avoid
+ the problems while respecting compatibility between different 0.9.7
+ patchlevels, 0.9.7e employed 'openssl x509 -next_serial' in
+ CA.pl for serial number initialization. With the new release 0.9.8,
+ we can fix the problem directly in the 'ca' utility.)
+
+ *Steve Henson*
+
+ * Reduced header interdependencies by declaring more opaque objects in
+ ossl_typ.h. As a consequence, including some headers (eg. engine.h) will
+ give fewer recursive includes, which could break lazy source code - so
+ this change is covered by the OPENSSL_NO_DEPRECATED symbol. As always,
+ developers should define this symbol when building and using openssl to
+ ensure they track the recommended behaviour, interfaces, [etc], but
+ backwards-compatible behaviour prevails when this isn't defined.
+
+ *Geoff Thorpe*
+
+ * New function X509_POLICY_NODE_print() which prints out policy nodes.
+
+ *Steve Henson*
+
+ * Add new EVP function EVP_CIPHER_CTX_rand_key and associated functionality.
+ This will generate a random key of the appropriate length based on the
+ cipher context. The EVP_CIPHER can provide its own random key generation
+ routine to support keys of a specific form. This is used in the des and
+ 3des routines to generate a key of the correct parity. Update S/MIME
+ code to use new functions and hence generate correct parity DES keys.
+ Add EVP_CHECK_DES_KEY #define to return an error if the key is not
+ valid (weak or incorrect parity).
+
+ *Steve Henson*
+
+ * Add a local set of CRLs that can be used by X509_verify_cert() as well
+ as looking them up. This is useful when the verified structure may contain
+ CRLs, for example PKCS#7 signedData. Modify PKCS7_verify() to use any CRLs
+ present unless the new PKCS7_NO_CRL flag is asserted.
+
+ *Steve Henson*
+
+ * Extend ASN1 oid configuration module. It now additionally accepts the
+ syntax:
+
+ shortName = some long name, 1.2.3.4
+
+ *Steve Henson*
+
+ * Reimplemented the BN_CTX implementation. There is now no more static
+ limitation on the number of variables it can handle nor the depth of the
+ "stack" handling for BN_CTX_start()/BN_CTX_end() pairs. The stack
+ information can now expand as required, and rather than having a single
+ static array of bignums, BN_CTX now uses a linked-list of such arrays
+ allowing it to expand on demand whilst maintaining the usefulness of
+ BN_CTX's "bundling".
+
+ *Geoff Thorpe*
+
+ * Add a missing BN_CTX parameter to the 'rsa_mod_exp' callback in RSA_METHOD
+ to allow all RSA operations to function using a single BN_CTX.
+
+ *Geoff Thorpe*
+
+ * Preliminary support for certificate policy evaluation and checking. This
+ is initially intended to pass the tests outlined in "Conformance Testing
+ of Relying Party Client Certificate Path Processing Logic" v1.07.
+
+ *Steve Henson*
+
+ * bn_dup_expand() has been deprecated, it was introduced in 0.9.7 and
+ remained unused and not that useful. A variety of other little bignum
+ tweaks and fixes have also been made continuing on from the audit (see
+ below).
+
+ *Geoff Thorpe*
+
+ * Constify all or almost all d2i, c2i, s2i and r2i functions, along with
+ associated ASN1, EVP and SSL functions and old ASN1 macros.
+
+ *Richard Levitte*
+
+ * BN_zero() only needs to set 'top' and 'neg' to zero for correct results,
+ and this should never fail. So the return value from the use of
+ BN_set_word() (which can fail due to needless expansion) is now deprecated;
+ if OPENSSL_NO_DEPRECATED is defined, BN_zero() is a void macro.
+
+ *Geoff Thorpe*
+
+ * BN_CTX_get() should return zero-valued bignums, providing the same
+ initialised value as BN_new().
+
+ *Geoff Thorpe, suggested by Ulf Möller*
+
+ * Support for inhibitAnyPolicy certificate extension.
+
+ *Steve Henson*
+
+ * An audit of the BIGNUM code is underway, for which debugging code is
+ enabled when BN_DEBUG is defined. This makes stricter enforcements on what
+ is considered valid when processing BIGNUMs, and causes execution to
+ assert() when a problem is discovered. If BN_DEBUG_RAND is defined,
+ further steps are taken to deliberately pollute unused data in BIGNUM
+ structures to try and expose faulty code further on. For now, openssl will
+ (in its default mode of operation) continue to tolerate the inconsistent
+ forms that it has tolerated in the past, but authors and packagers should
+ consider trying openssl and their own applications when compiled with
+ these debugging symbols defined. It will help highlight potential bugs in
+ their own code, and will improve the test coverage for OpenSSL itself. At
+ some point, these tighter rules will become openssl's default to improve
+ maintainability, though the assert()s and other overheads will remain only
+ in debugging configurations. See bn.h for more details.
+
+ *Geoff Thorpe, Nils Larsch, Ulf Möller*
+
+ * BN_CTX_init() has been deprecated, as BN_CTX is an opaque structure
+ that can only be obtained through BN_CTX_new() (which implicitly
+ initialises it). The presence of this function only made it possible
+ to overwrite an existing structure (and cause memory leaks).
+
+ *Geoff Thorpe*
+
+ * Because of the callback-based approach for implementing LHASH as a
+ template type, lh_insert() adds opaque objects to hash-tables and
+ lh_doall() or lh_doall_arg() are typically used with a destructor callback
+ to clean up those corresponding objects before destroying the hash table
+ (and losing the object pointers). So some over-zealous constifications in
+ LHASH have been relaxed so that lh_insert() does not take (nor store) the
+ objects as "const" and the `lh_doall[_arg]` callback wrappers are not
+ prototyped to have "const" restrictions on the object pointers they are
+ given (and so aren't required to cast them away any more).
+
+ *Geoff Thorpe*
+
+ * The tmdiff.h API was so ugly and minimal that our own timing utility
+ (speed) prefers to use its own implementation. The two implementations
+ haven't been consolidated as yet (volunteers?) but the tmdiff API has had
+ its object type properly exposed (MS_TM) instead of casting to/from
+ `char *`. This may still change yet if someone realises MS_TM and
+ `ms_time_***`
+ aren't necessarily the greatest nomenclatures - but this is what was used
+ internally to the implementation so I've used that for now.
+
+ *Geoff Thorpe*
+
+ * Ensure that deprecated functions do not get compiled when
+ OPENSSL_NO_DEPRECATED is defined. Some "openssl" subcommands and a few of
+ the self-tests were still using deprecated key-generation functions so
+ these have been updated also.
+
+ *Geoff Thorpe*
+
+ * Reorganise PKCS#7 code to separate the digest location functionality
+ into PKCS7_find_digest(), digest addition into PKCS7_bio_add_digest().
+ New function PKCS7_set_digest() to set the digest type for PKCS#7
+ digestedData type. Add additional code to correctly generate the
+ digestedData type and add support for this type in PKCS7 initialization
+ functions.
+
+ *Steve Henson*
+
+ * New function PKCS7_set0_type_other() this initializes a PKCS7
+ structure of type "other".
+
+ *Steve Henson*
+
+ * Fix prime generation loop in crypto/bn/bn_prime.pl by making
+ sure the loop does correctly stop and breaking ("division by zero")
+ modulus operations are not performed. The (pre-generated) prime
+ table crypto/bn/bn_prime.h was already correct, but it could not be
+ re-generated on some platforms because of the "division by zero"
+ situation in the script.
+
+ *Ralf S. Engelschall*
+
+ * Update support for ECC-based TLS ciphersuites according to
+ draft-ietf-tls-ecc-03.txt: the KDF1 key derivation function with
+ SHA-1 now is only used for "small" curves (where the
+ representation of a field element takes up to 24 bytes); for
+ larger curves, the field element resulting from ECDH is directly
+ used as premaster secret.
+
+ *Douglas Stebila (Sun Microsystems Laboratories)*
+
+ * Add code for kP+lQ timings to crypto/ec/ectest.c, and add SEC2
+ curve secp160r1 to the tests.
+
+ *Douglas Stebila (Sun Microsystems Laboratories)*
+
+ * Add the possibility to load symbols globally with DSO.
+
+ *Götz Babin-Ebell <babin-ebell@trustcenter.de> via Richard Levitte*
+
+ * Add the functions ERR_set_mark() and ERR_pop_to_mark() for better
+ control of the error stack.
+
+ *Richard Levitte*
+
+ * Add support for STORE in ENGINE.
+
+ *Richard Levitte*
+
+ * Add the STORE type. The intention is to provide a common interface
+ to certificate and key stores, be they simple file-based stores, or
+ HSM-type store, or LDAP stores, or...
+ NOTE: The code is currently UNTESTED and isn't really used anywhere.
+
+ *Richard Levitte*
+
+ * Add a generic structure called OPENSSL_ITEM. This can be used to
+ pass a list of arguments to any function as well as provide a way
+ for a function to pass data back to the caller.
+
+ *Richard Levitte*
+
+ * Add the functions BUF_strndup() and BUF_memdup(). BUF_strndup()
+ works like BUF_strdup() but can be used to duplicate a portion of
+ a string. The copy gets NUL-terminated. BUF_memdup() duplicates
+ a memory area.
+
+ *Richard Levitte*
+
+ * Add the function sk_find_ex() which works like sk_find(), but will
+ return an index to an element even if an exact match couldn't be
+ found. The index is guaranteed to point at the element where the
+ searched-for key would be inserted to preserve sorting order.
+
+ *Richard Levitte*
+
+ * Add the function OBJ_bsearch_ex() which works like OBJ_bsearch() but
+ takes an extra flags argument for optional functionality. Currently,
+ the following flags are defined:
+
+ OBJ_BSEARCH_VALUE_ON_NOMATCH
+ This one gets OBJ_bsearch_ex() to return a pointer to the first
+ element where the comparing function returns a negative or zero
+ number.
+
+ OBJ_BSEARCH_FIRST_VALUE_ON_MATCH
+ This one gets OBJ_bsearch_ex() to return a pointer to the first
+ element where the comparing function returns zero. This is useful
+ if there are more than one element where the comparing function
+ returns zero.
+
+ *Richard Levitte*
+
+ * Make it possible to create self-signed certificates with 'openssl ca'
+ in such a way that the self-signed certificate becomes part of the
+ CA database and uses the same mechanisms for serial number generation
+ as all other certificate signing. The new flag '-selfsign' enables
+ this functionality. Adapt CA.sh and CA.pl.in.
+
+ *Richard Levitte*
+
+ * Add functionality to check the public key of a certificate request
+ against a given private. This is useful to check that a certificate
+ request can be signed by that key (self-signing).
+
+ *Richard Levitte*
+
+ * Make it possible to have multiple active certificates with the same
+ subject in the CA index file. This is done only if the keyword
+ 'unique_subject' is set to 'no' in the main CA section (default
+ if 'CA_default') of the configuration file. The value is saved
+ with the database itself in a separate index attribute file,
+ named like the index file with '.attr' appended to the name.
+
+ *Richard Levitte*
+
+ * Generate multi-valued AVAs using '+' notation in config files for
+ req and dirName.
+
+ *Steve Henson*
+
+ * Support for nameConstraints certificate extension.
+
+ *Steve Henson*
+
+ * Support for policyConstraints certificate extension.
+
+ *Steve Henson*
+
+ * Support for policyMappings certificate extension.
+
+ *Steve Henson*
+
+ * Make sure the default DSA_METHOD implementation only uses its
+ dsa_mod_exp() and/or bn_mod_exp() handlers if they are non-NULL,
+ and change its own handlers to be NULL so as to remove unnecessary
+ indirection. This lets alternative implementations fallback to the
+ default implementation more easily.
+
+ *Geoff Thorpe*
+
+ * Support for directoryName in GeneralName related extensions
+ in config files.
+
+ *Steve Henson*
+
+ * Make it possible to link applications using Makefile.shared.
+ Make that possible even when linking against static libraries!
+
+ *Richard Levitte*
+
+ * Support for single pass processing for S/MIME signing. This now
+ means that S/MIME signing can be done from a pipe, in addition
+ cleartext signing (multipart/signed type) is effectively streaming
+ and the signed data does not need to be all held in memory.
+
+ This is done with a new flag PKCS7_STREAM. When this flag is set
+ PKCS7_sign() only initializes the PKCS7 structure and the actual signing
+ is done after the data is output (and digests calculated) in
+ SMIME_write_PKCS7().
+
+ *Steve Henson*
+
+ * Add full support for -rpath/-R, both in shared libraries and
+ applications, at least on the platforms where it's known how
+ to do it.
+
+ *Richard Levitte*
+
+ * In crypto/ec/ec_mult.c, implement fast point multiplication with
+ precomputation, based on wNAF splitting: EC_GROUP_precompute_mult()
+ will now compute a table of multiples of the generator that
+ makes subsequent invocations of EC_POINTs_mul() or EC_POINT_mul()
+ faster (notably in the case of a single point multiplication,
+ scalar * generator).
+
+ *Nils Larsch, Bodo Moeller*
+
+ * IPv6 support for certificate extensions. The various extensions
+ which use the IP:a.b.c.d can now take IPv6 addresses using the
+ formats of RFC1884 2.2 . IPv6 addresses are now also displayed
+ correctly.
+
+ *Steve Henson*
+
+ * Added an ENGINE that implements RSA by performing private key
+ exponentiations with the GMP library. The conversions to and from
+ GMP's mpz_t format aren't optimised nor are any montgomery forms
+ cached, and on x86 it appears OpenSSL's own performance has caught up.
+ However there are likely to be other architectures where GMP could
+ provide a boost. This ENGINE is not built in by default, but it can be
+ specified at Configure time and should be accompanied by the necessary
+ linker additions, eg;
+ ./config -DOPENSSL_USE_GMP -lgmp
+
+ *Geoff Thorpe*
+
+ * "openssl engine" will not display ENGINE/DSO load failure errors when
+ testing availability of engines with "-t" - the old behaviour is
+ produced by increasing the feature's verbosity with "-tt".
+
+ *Geoff Thorpe*
+
+ * ECDSA routines: under certain error conditions uninitialized BN objects
+ could be freed. Solution: make sure initialization is performed early
+ enough. (Reported and fix supplied by Nils Larsch <nla@trustcenter.de>
+ via PR#459)
+
+ *Lutz Jaenicke*
+
+ * Key-generation can now be implemented in RSA_METHOD, DSA_METHOD
+ and DH_METHOD (eg. by ENGINE implementations) to override the normal
+ software implementations. For DSA and DH, parameter generation can
+ also be overridden by providing the appropriate method callbacks.
+
+ *Geoff Thorpe*
+
+ * Change the "progress" mechanism used in key-generation and
+ primality testing to functions that take a new BN_GENCB pointer in
+ place of callback/argument pairs. The new API functions have `_ex`
+ postfixes and the older functions are reimplemented as wrappers for
+ the new ones. The OPENSSL_NO_DEPRECATED symbol can be used to hide
+ declarations of the old functions to help (graceful) attempts to
+ migrate to the new functions. Also, the new key-generation API
+ functions operate on a caller-supplied key-structure and return
+ success/failure rather than returning a key or NULL - this is to
+ help make "keygen" another member function of RSA_METHOD etc.
+
+ Example for using the new callback interface:
+
+ int (*my_callback)(int a, int b, BN_GENCB *cb) = ...;
+ void *my_arg = ...;
+ BN_GENCB my_cb;
+
+ BN_GENCB_set(&my_cb, my_callback, my_arg);
+
+ return BN_is_prime_ex(some_bignum, BN_prime_checks, NULL, &cb);
+ /* For the meaning of a, b in calls to my_callback(), see the
+ * documentation of the function that calls the callback.
+ * cb will point to my_cb; my_arg can be retrieved as cb->arg.
+ * my_callback should return 1 if it wants BN_is_prime_ex()
+ * to continue, or 0 to stop.
+ */
+
+ *Geoff Thorpe*
+
+ * Change the ZLIB compression method to be stateful, and make it
+ available to TLS with the number defined in
+ draft-ietf-tls-compression-04.txt.
+
+ *Richard Levitte*
+
+ * Add the ASN.1 structures and functions for CertificatePair, which
+ is defined as follows (according to X.509_4thEditionDraftV6.pdf):
+
+ CertificatePair ::= SEQUENCE {
+ forward [0] Certificate OPTIONAL,
+ reverse [1] Certificate OPTIONAL,
+ -- at least one of the pair shall be present -- }
+
+ Also implement the PEM functions to read and write certificate
+ pairs, and defined the PEM tag as "CERTIFICATE PAIR".
+
+ This needed to be defined, mostly for the sake of the LDAP
+ attribute crossCertificatePair, but may prove useful elsewhere as
+ well.
+
+ *Richard Levitte*
+
+ * Make it possible to inhibit symlinking of shared libraries in
+ Makefile.shared, for Cygwin's sake.
+
+ *Richard Levitte*
+
+ * Extend the BIGNUM API by creating a function
+ void BN_set_negative(BIGNUM *a, int neg);
+ and a macro that behave like
+ int BN_is_negative(const BIGNUM *a);
+
+ to avoid the need to access 'a->neg' directly in applications.
+
+ *Nils Larsch*
+
+ * Implement fast modular reduction for pseudo-Mersenne primes
+ used in NIST curves (crypto/bn/bn_nist.c, crypto/ec/ecp_nist.c).
+ EC_GROUP_new_curve_GFp() will now automatically use this
+ if applicable.
+
+ *Nils Larsch <nla@trustcenter.de>*
+
+ * Add new lock type (CRYPTO_LOCK_BN).
+
+ *Bodo Moeller*
+
+ * Change the ENGINE framework to automatically load engines
+ dynamically from specific directories unless they could be
+ found to already be built in or loaded. Move all the
+ current engines except for the cryptodev one to a new
+ directory engines/.
+ The engines in engines/ are built as shared libraries if
+ the "shared" options was given to ./Configure or ./config.
+ Otherwise, they are inserted in libcrypto.a.
+ /usr/local/ssl/engines is the default directory for dynamic
+ engines, but that can be overridden at configure time through
+ the usual use of --prefix and/or --openssldir, and at run
+ time with the environment variable OPENSSL_ENGINES.
+
+ *Geoff Thorpe and Richard Levitte*
+
+ * Add Makefile.shared, a helper makefile to build shared
+ libraries. Adapt Makefile.org.
+
+ *Richard Levitte*
+
+ * Add version info to Win32 DLLs.
+
+ *Peter 'Luna' Runestig" <peter@runestig.com>*
+
+ * Add new 'medium level' PKCS#12 API. Certificates and keys
+ can be added using this API to created arbitrary PKCS#12
+ files while avoiding the low-level API.
+
+ New options to PKCS12_create(), key or cert can be NULL and
+ will then be omitted from the output file. The encryption
+ algorithm NIDs can be set to -1 for no encryption, the mac
+ iteration count can be set to 0 to omit the mac.
+
+ Enhance pkcs12 utility by making the -nokeys and -nocerts
+ options work when creating a PKCS#12 file. New option -nomac
+ to omit the mac, NONE can be set for an encryption algorithm.
+ New code is modified to use the enhanced PKCS12_create()
+ instead of the low-level API.
+
+ *Steve Henson*
+
+ * Extend ASN1 encoder to support indefinite length constructed
+ encoding. This can output sequences tags and octet strings in
+ this form. Modify pk7_asn1.c to support indefinite length
+ encoding. This is experimental and needs additional code to
+ be useful, such as an ASN1 bio and some enhanced streaming
+ PKCS#7 code.
+
+ Extend template encode functionality so that tagging is passed
+ down to the template encoder.
+
+ *Steve Henson*
+
+ * Let 'openssl req' fail if an argument to '-newkey' is not
+ recognized instead of using RSA as a default.
+
+ *Bodo Moeller*
+
+ * Add support for ECC-based ciphersuites from draft-ietf-tls-ecc-01.txt.
+ As these are not official, they are not included in "ALL";
+ the "ECCdraft" ciphersuite group alias can be used to select them.
+
+ *Vipul Gupta and Sumit Gupta (Sun Microsystems Laboratories)*
+
+ * Add ECDH engine support.
+
+ *Nils Gura and Douglas Stebila (Sun Microsystems Laboratories)*
+
+ * Add ECDH in new directory crypto/ecdh/.
+
+ *Douglas Stebila (Sun Microsystems Laboratories)*
+
+ * Let BN_rand_range() abort with an error after 100 iterations
+ without success (which indicates a broken PRNG).
+
+ *Bodo Moeller*
+
+ * Change BN_mod_sqrt() so that it verifies that the input value
+ is really the square of the return value. (Previously,
+ BN_mod_sqrt would show GIGO behaviour.)
+
+ *Bodo Moeller*
+
+ * Add named elliptic curves over binary fields from X9.62, SECG,
+ and WAP/WTLS; add OIDs that were still missing.
+
+ *Sheueling Chang Shantz and Douglas Stebila (Sun Microsystems Laboratories)*
+
+ * Extend the EC library for elliptic curves over binary fields
+ (new files ec2_smpl.c, ec2_smpt.c, ec2_mult.c in crypto/ec/).
+ New EC_METHOD:
+
+ EC_GF2m_simple_method
+
+ New API functions:
+
+ EC_GROUP_new_curve_GF2m
+ EC_GROUP_set_curve_GF2m
+ EC_GROUP_get_curve_GF2m
+ EC_POINT_set_affine_coordinates_GF2m
+ EC_POINT_get_affine_coordinates_GF2m
+ EC_POINT_set_compressed_coordinates_GF2m
+
+ Point compression for binary fields is disabled by default for
+ patent reasons (compile with OPENSSL_EC_BIN_PT_COMP defined to
+ enable it).
+
+ As binary polynomials are represented as BIGNUMs, various members
+ of the EC_GROUP and EC_POINT data structures can be shared
+ between the implementations for prime fields and binary fields;
+ the above `..._GF2m functions` (except for EX_GROUP_new_curve_GF2m)
+ are essentially identical to their `..._GFp` counterparts.
+ (For simplicity, the `..._GFp` prefix has been dropped from
+ various internal method names.)
+
+ An internal 'field_div' method (similar to 'field_mul' and
+ 'field_sqr') has been added; this is used only for binary fields.
+
+ *Sheueling Chang Shantz and Douglas Stebila (Sun Microsystems Laboratories)*
+
+ * Optionally dispatch EC_POINT_mul(), EC_POINT_precompute_mult()
+ through methods ('mul', 'precompute_mult').
+
+ The generic implementations (now internally called 'ec_wNAF_mul'
+ and 'ec_wNAF_precomputed_mult') remain the default if these
+ methods are undefined.
+
+ *Sheueling Chang Shantz and Douglas Stebila (Sun Microsystems Laboratories)*
+
+ * New function EC_GROUP_get_degree, which is defined through
+ EC_METHOD. For curves over prime fields, this returns the bit
+ length of the modulus.
+
+ *Sheueling Chang Shantz and Douglas Stebila (Sun Microsystems Laboratories)*
+
+ * New functions EC_GROUP_dup, EC_POINT_dup.
+ (These simply call ..._new and ..._copy).
+
+ *Sheueling Chang Shantz and Douglas Stebila (Sun Microsystems Laboratories)*
+
+ * Add binary polynomial arithmetic software in crypto/bn/bn_gf2m.c.
+ Polynomials are represented as BIGNUMs (where the sign bit is not
+ used) in the following functions [macros]:
+
+ BN_GF2m_add
+ BN_GF2m_sub [= BN_GF2m_add]
+ BN_GF2m_mod [wrapper for BN_GF2m_mod_arr]
+ BN_GF2m_mod_mul [wrapper for BN_GF2m_mod_mul_arr]
+ BN_GF2m_mod_sqr [wrapper for BN_GF2m_mod_sqr_arr]
+ BN_GF2m_mod_inv
+ BN_GF2m_mod_exp [wrapper for BN_GF2m_mod_exp_arr]
+ BN_GF2m_mod_sqrt [wrapper for BN_GF2m_mod_sqrt_arr]
+ BN_GF2m_mod_solve_quad [wrapper for BN_GF2m_mod_solve_quad_arr]
+ BN_GF2m_cmp [= BN_ucmp]
+
+ (Note that only the 'mod' functions are actually for fields GF(2^m).
+ BN_GF2m_add() is misnomer, but this is for the sake of consistency.)
+
+ For some functions, an the irreducible polynomial defining a
+ field can be given as an 'unsigned int[]' with strictly
+ decreasing elements giving the indices of those bits that are set;
+ i.e., p[] represents the polynomial
+ f(t) = t^p[0] + t^p[1] + ... + t^p[k]
+ where
+ p[0] > p[1] > ... > p[k] = 0.
+ This applies to the following functions:
+
+ BN_GF2m_mod_arr
+ BN_GF2m_mod_mul_arr
+ BN_GF2m_mod_sqr_arr
+ BN_GF2m_mod_inv_arr [wrapper for BN_GF2m_mod_inv]
+ BN_GF2m_mod_div_arr [wrapper for BN_GF2m_mod_div]
+ BN_GF2m_mod_exp_arr
+ BN_GF2m_mod_sqrt_arr
+ BN_GF2m_mod_solve_quad_arr
+ BN_GF2m_poly2arr
+ BN_GF2m_arr2poly
+
+ Conversion can be performed by the following functions:
+
+ BN_GF2m_poly2arr
+ BN_GF2m_arr2poly
+
+ bntest.c has additional tests for binary polynomial arithmetic.
+
+ Two implementations for BN_GF2m_mod_div() are available.
+ The default algorithm simply uses BN_GF2m_mod_inv() and
+ BN_GF2m_mod_mul(). The alternative algorithm is compiled in only
+ if OPENSSL_SUN_GF2M_DIV is defined (patent pending; read the
+ copyright notice in crypto/bn/bn_gf2m.c before enabling it).
+
+ *Sheueling Chang Shantz and Douglas Stebila (Sun Microsystems Laboratories)*
+
+ * Add new error code 'ERR_R_DISABLED' that can be used when some
+ functionality is disabled at compile-time.
+
+ *Douglas Stebila <douglas.stebila@sun.com>*
+
+ * Change default behaviour of 'openssl asn1parse' so that more
+ information is visible when viewing, e.g., a certificate:
+
+ Modify asn1_parse2 (crypto/asn1/asn1_par.c) so that in non-'dump'
+ mode the content of non-printable OCTET STRINGs is output in a
+ style similar to INTEGERs, but with '[HEX DUMP]' prepended to
+ avoid the appearance of a printable string.
+
+ *Nils Larsch <nla@trustcenter.de>*
+
+ * Add 'asn1_flag' and 'asn1_form' member to EC_GROUP with access
+ functions
+ EC_GROUP_set_asn1_flag()
+ EC_GROUP_get_asn1_flag()
+ EC_GROUP_set_point_conversion_form()
+ EC_GROUP_get_point_conversion_form()
+ These control ASN1 encoding details:
+ - Curves (i.e., groups) are encoded explicitly unless asn1_flag
+ has been set to OPENSSL_EC_NAMED_CURVE.
+ - Points are encoded in uncompressed form by default; options for
+ asn1_for are as for point2oct, namely
+ POINT_CONVERSION_COMPRESSED
+ POINT_CONVERSION_UNCOMPRESSED
+ POINT_CONVERSION_HYBRID
+
+ Also add 'seed' and 'seed_len' members to EC_GROUP with access
+ functions
+ EC_GROUP_set_seed()
+ EC_GROUP_get0_seed()
+ EC_GROUP_get_seed_len()
+ This is used only for ASN1 purposes (so far).
+
+ *Nils Larsch <nla@trustcenter.de>*
+
+ * Add 'field_type' member to EC_METHOD, which holds the NID
+ of the appropriate field type OID. The new function
+ EC_METHOD_get_field_type() returns this value.
+
+ *Nils Larsch <nla@trustcenter.de>*
+
+ * Add functions
+ EC_POINT_point2bn()
+ EC_POINT_bn2point()
+ EC_POINT_point2hex()
+ EC_POINT_hex2point()
+ providing useful interfaces to EC_POINT_point2oct() and
+ EC_POINT_oct2point().
+
+ *Nils Larsch <nla@trustcenter.de>*
+
+ * Change internals of the EC library so that the functions
+ EC_GROUP_set_generator()
+ EC_GROUP_get_generator()
+ EC_GROUP_get_order()
+ EC_GROUP_get_cofactor()
+ are implemented directly in crypto/ec/ec_lib.c and not dispatched
+ to methods, which would lead to unnecessary code duplication when
+ adding different types of curves.
+
+ *Nils Larsch <nla@trustcenter.de> with input by Bodo Moeller*
+
+ * Implement compute_wNAF (crypto/ec/ec_mult.c) without BIGNUM
+ arithmetic, and such that modified wNAFs are generated
+ (which avoid length expansion in many cases).
+
+ *Bodo Moeller*
+
+ * Add a function EC_GROUP_check_discriminant() (defined via
+ EC_METHOD) that verifies that the curve discriminant is non-zero.
+
+ Add a function EC_GROUP_check() that makes some sanity tests
+ on a EC_GROUP, its generator and order. This includes
+ EC_GROUP_check_discriminant().
+
+ *Nils Larsch <nla@trustcenter.de>*
+
+ * Add ECDSA in new directory crypto/ecdsa/.
+
+ Add applications 'openssl ecparam' and 'openssl ecdsa'
+ (these are based on 'openssl dsaparam' and 'openssl dsa').
+
+ ECDSA support is also included in various other files across the
+ library. Most notably,
+ - 'openssl req' now has a '-newkey ecdsa:file' option;
+ - EVP_PKCS82PKEY (crypto/evp/evp_pkey.c) now can handle ECDSA;
+ - X509_PUBKEY_get (crypto/asn1/x_pubkey.c) and
+ d2i_PublicKey (crypto/asn1/d2i_pu.c) have been modified to make
+ them suitable for ECDSA where domain parameters must be
+ extracted before the specific public key;
+ - ECDSA engine support has been added.
+
+ *Nils Larsch <nla@trustcenter.de>*
+
+ * Include some named elliptic curves, and add OIDs from X9.62,
+ SECG, and WAP/WTLS. Each curve can be obtained from the new
+ function
+ EC_GROUP_new_by_curve_name(),
+ and the list of available named curves can be obtained with
+ EC_get_builtin_curves().
+ Also add a 'curve_name' member to EC_GROUP objects, which can be
+ accessed via
+ EC_GROUP_set_curve_name()
+ EC_GROUP_get_curve_name()
+
+ *Nils Larsch <larsch@trustcenter.de, Bodo Moeller*
+
+ * Remove a few calls to bn_wexpand() in BN_sqr() (the one in there
+ was actually never needed) and in BN_mul(). The removal in BN_mul()
+ required a small change in bn_mul_part_recursive() and the addition
+ of the functions bn_cmp_part_words(), bn_sub_part_words() and
+ bn_add_part_words(), which do the same thing as bn_cmp_words(),
+ bn_sub_words() and bn_add_words() except they take arrays with
+ differing sizes.
+
+ *Richard Levitte*
+
+### Changes between 0.9.7l and 0.9.7m [23 Feb 2007]
+
+ * Cleanse PEM buffers before freeing them since they may contain
+ sensitive data.
+
+ *Benjamin Bennett <ben@psc.edu>*
+
+ * Include "!eNULL" in SSL_DEFAULT_CIPHER_LIST to make sure that
+ a ciphersuite string such as "DEFAULT:RSA" cannot enable
+ authentication-only ciphersuites.
+
+ *Bodo Moeller*
+
+ * Since AES128 and AES256 share a single mask bit in the logic of
+ ssl/ssl_ciph.c, the code for masking out disabled ciphers needs a
+ kludge to work properly if AES128 is available and AES256 isn't.
+
+ *Victor Duchovni*
+
+ * Expand security boundary to match 1.1.1 module.
+
+ *Steve Henson*
+
+ * Remove redundant features: hash file source, editing of test vectors
+ modify fipsld to use external fips_premain.c signature.
+
+ *Steve Henson*
+
+ * New perl script mkfipsscr.pl to create shell scripts or batch files to
+ run algorithm test programs.
+
+ *Steve Henson*
+
+ * Make algorithm test programs more tolerant of whitespace.
+
+ *Steve Henson*
+
+ * Have SSL/TLS server implementation tolerate "mismatched" record
+ protocol version while receiving ClientHello even if the
+ ClientHello is fragmented. (The server can't insist on the
+ particular protocol version it has chosen before the ServerHello
+ message has informed the client about his choice.)
+
+ *Bodo Moeller*
+
+ * Load error codes if they are not already present instead of using a
+ static variable. This allows them to be cleanly unloaded and reloaded.
+
+ *Steve Henson*
+
+### Changes between 0.9.7k and 0.9.7l [28 Sep 2006]
+
+ * Introduce limits to prevent malicious keys being able to
+ cause a denial of service. ([CVE-2006-2940])
+
+ *Steve Henson, Bodo Moeller*
+
+ * Fix ASN.1 parsing of certain invalid structures that can result
+ in a denial of service. ([CVE-2006-2937]) [Steve Henson]
+
+ * Fix buffer overflow in SSL_get_shared_ciphers() function.
+ ([CVE-2006-3738]) [Tavis Ormandy and Will Drewry, Google Security Team]
+
+ * Fix SSL client code which could crash if connecting to a
+ malicious SSLv2 server. ([CVE-2006-4343])
+
+ *Tavis Ormandy and Will Drewry, Google Security Team*
+
+ * Change ciphersuite string processing so that an explicit
+ ciphersuite selects this one ciphersuite (so that "AES256-SHA"
+ will no longer include "AES128-SHA"), and any other similar
+ ciphersuite (same bitmap) from *other* protocol versions (so that
+ "RC4-MD5" will still include both the SSL 2.0 ciphersuite and the
+ SSL 3.0/TLS 1.0 ciphersuite). This is a backport combining
+ changes from 0.9.8b and 0.9.8d.
+
+ *Bodo Moeller*
+
+### Changes between 0.9.7j and 0.9.7k [05 Sep 2006]
+
+ * Avoid PKCS #1 v1.5 signature attack discovered by Daniel Bleichenbacher
+ ([CVE-2006-4339]) [Ben Laurie and Google Security Team]
+
+ * Change the Unix randomness entropy gathering to use poll() when
+ possible instead of select(), since the latter has some
+ undesirable limitations.
+
+ *Darryl Miles via Richard Levitte and Bodo Moeller*
+
+ * Disable rogue ciphersuites:
+
+ - SSLv2 0x08 0x00 0x80 ("RC4-64-MD5")
+ - SSLv3/TLSv1 0x00 0x61 ("EXP1024-RC2-CBC-MD5")
+ - SSLv3/TLSv1 0x00 0x60 ("EXP1024-RC4-MD5")
+
+ The latter two were purportedly from
+ draft-ietf-tls-56-bit-ciphersuites-0[01].txt, but do not really
+ appear there.
+
+ Also deactivate the remaining ciphersuites from
+ draft-ietf-tls-56-bit-ciphersuites-01.txt. These are just as
+ unofficial, and the ID has long expired.
+
+ *Bodo Moeller*
+
+ * Fix RSA blinding Heisenbug (problems sometimes occurred on
+ dual-core machines) and other potential thread-safety issues.
+
+ *Bodo Moeller*
+
+### Changes between 0.9.7i and 0.9.7j [04 May 2006]
+
+ * Adapt fipsld and the build system to link against the validated FIPS
+ module in FIPS mode.
+
+ *Steve Henson*
+
+ * Fixes for VC++ 2005 build under Windows.
+
+ *Steve Henson*
+
+ * Add new Windows build target VC-32-GMAKE for VC++. This uses GNU make
+ from a Windows bash shell such as MSYS. It is autodetected from the
+ "config" script when run from a VC++ environment. Modify standard VC++
+ build to use fipscanister.o from the GNU make build.
+
+ *Steve Henson*
+
+### Changes between 0.9.7h and 0.9.7i [14 Oct 2005]
+
+ * Wrapped the definition of EVP_MAX_MD_SIZE in a #ifdef OPENSSL_FIPS.
+ The value now differs depending on if you build for FIPS or not.
+ BEWARE! A program linked with a shared FIPSed libcrypto can't be
+ safely run with a non-FIPSed libcrypto, as it may crash because of
+ the difference induced by this change.
+
+ *Andy Polyakov*
+
+### Changes between 0.9.7g and 0.9.7h [11 Oct 2005]
+
+ * Remove the functionality of SSL_OP_MSIE_SSLV2_RSA_PADDING
+ (part of SSL_OP_ALL). This option used to disable the
+ countermeasure against man-in-the-middle protocol-version
+ rollback in the SSL 2.0 server implementation, which is a bad
+ idea. ([CVE-2005-2969])
+
+ *Bodo Moeller; problem pointed out by Yutaka Oiwa (Research Center
+ for Information Security, National Institute of Advanced Industrial
+ Science and Technology [AIST, Japan)]*
+
+ * Minimal support for X9.31 signatures and PSS padding modes. This is
+ mainly for FIPS compliance and not fully integrated at this stage.
+
+ *Steve Henson*
+
+ * For DSA signing, unless DSA_FLAG_NO_EXP_CONSTTIME is set, perform
+ the exponentiation using a fixed-length exponent. (Otherwise,
+ the information leaked through timing could expose the secret key
+ after many signatures; cf. Bleichenbacher's attack on DSA with
+ biased k.)
+
+ *Bodo Moeller*
+
+ * Make a new fixed-window mod_exp implementation the default for
+ RSA, DSA, and DH private-key operations so that the sequence of
+ squares and multiplies and the memory access pattern are
+ independent of the particular secret key. This will mitigate
+ cache-timing and potential related attacks.
+
+ BN_mod_exp_mont_consttime() is the new exponentiation implementation,
+ and this is automatically used by BN_mod_exp_mont() if the new flag
+ BN_FLG_EXP_CONSTTIME is set for the exponent. RSA, DSA, and DH
+ will use this BN flag for private exponents unless the flag
+ RSA_FLAG_NO_EXP_CONSTTIME, DSA_FLAG_NO_EXP_CONSTTIME, or
+ DH_FLAG_NO_EXP_CONSTTIME, respectively, is set.
+
+ *Matthew D Wood (Intel Corp), with some changes by Bodo Moeller*
+
+ * Change the client implementation for SSLv23_method() and
+ SSLv23_client_method() so that is uses the SSL 3.0/TLS 1.0
+ Client Hello message format if the SSL_OP_NO_SSLv2 option is set.
+ (Previously, the SSL 2.0 backwards compatible Client Hello
+ message format would be used even with SSL_OP_NO_SSLv2.)
+
+ *Bodo Moeller*
+
+ * Add support for smime-type MIME parameter in S/MIME messages which some
+ clients need.
+
+ *Steve Henson*
+
+ * New function BN_MONT_CTX_set_locked() to set montgomery parameters in
+ a threadsafe manner. Modify rsa code to use new function and add calls
+ to dsa and dh code (which had race conditions before).
+
+ *Steve Henson*
+
+ * Include the fixed error library code in the C error file definitions
+ instead of fixing them up at runtime. This keeps the error code
+ structures constant.
+
+ *Steve Henson*
+
+### Changes between 0.9.7f and 0.9.7g [11 Apr 2005]
+
+[NB: OpenSSL 0.9.7h and later 0.9.7 patch levels were released after
+OpenSSL 0.9.8.]
+
+ * Fixes for newer kerberos headers. NB: the casts are needed because
+ the 'length' field is signed on one version and unsigned on another
+ with no (?) obvious way to tell the difference, without these VC++
+ complains. Also the "definition" of FAR (blank) is no longer included
+ nor is the error ENOMEM. KRB5_PRIVATE has to be set to 1 to pick up
+ some needed definitions.
+
+ *Steve Henson*
+
+ * Undo Cygwin change.
+
+ *Ulf Möller*
+
+ * Added support for proxy certificates according to RFC 3820.
+ Because they may be a security thread to unaware applications,
+ they must be explicitly allowed in run-time. See
+ docs/HOWTO/proxy_certificates.txt for further information.
+
+ *Richard Levitte*
+
+### Changes between 0.9.7e and 0.9.7f [22 Mar 2005]
+
+ * Use (SSL_RANDOM_VALUE - 4) bytes of pseudo random data when generating
+ server and client random values. Previously
+ (SSL_RANDOM_VALUE - sizeof(time_t)) would be used which would result in
+ less random data when sizeof(time_t) > 4 (some 64 bit platforms).
+
+ This change has negligible security impact because:
+
+ 1. Server and client random values still have 24 bytes of pseudo random
+ data.
+
+ 2. Server and client random values are sent in the clear in the initial
+ handshake.
+
+ 3. The master secret is derived using the premaster secret (48 bytes in
+ size for static RSA ciphersuites) as well as client server and random
+ values.
+
+ The OpenSSL team would like to thank the UK NISCC for bringing this issue
+ to our attention.
+
+ *Stephen Henson, reported by UK NISCC*
+
+ * Use Windows randomness collection on Cygwin.
+
+ *Ulf Möller*
+
+ * Fix hang in EGD/PRNGD query when communication socket is closed
+ prematurely by EGD/PRNGD.
+
+ *Darren Tucker <dtucker@zip.com.au> via Lutz Jänicke, resolves #1014*
+
+ * Prompt for pass phrases when appropriate for PKCS12 input format.
+
+ *Steve Henson*
+
+ * Back-port of selected performance improvements from development
+ branch, as well as improved support for PowerPC platforms.
+
+ *Andy Polyakov*
+
+ * Add lots of checks for memory allocation failure, error codes to indicate
+ failure and freeing up memory if a failure occurs.
+
+ *Nauticus Networks SSL Team <openssl@nauticusnet.com>, Steve Henson*
+
+ * Add new -passin argument to dgst.
+
+ *Steve Henson*
+
+ * Perform some character comparisons of different types in X509_NAME_cmp:
+ this is needed for some certificates that re-encode DNs into UTF8Strings
+ (in violation of RFC3280) and can't or won't issue name rollover
+ certificates.
+
+ *Steve Henson*
+
+ * Make an explicit check during certificate validation to see that
+ the CA setting in each certificate on the chain is correct. As a
+ side effect always do the following basic checks on extensions,
+ not just when there's an associated purpose to the check:
+
+ - if there is an unhandled critical extension (unless the user
+ has chosen to ignore this fault)
+ - if the path length has been exceeded (if one is set at all)
+ - that certain extensions fit the associated purpose (if one has
+ been given)
+
+ *Richard Levitte*
+
+### Changes between 0.9.7d and 0.9.7e [25 Oct 2004]
+
+ * Avoid a race condition when CRLs are checked in a multi threaded
+ environment. This would happen due to the reordering of the revoked
+ entries during signature checking and serial number lookup. Now the
+ encoding is cached and the serial number sort performed under a lock.
+ Add new STACK function sk_is_sorted().
+
+ *Steve Henson*
+
+ * Add Delta CRL to the extension code.
+
+ *Steve Henson*
+
+ * Various fixes to s3_pkt.c so alerts are sent properly.
+
+ *David Holmes <d.holmes@f5.com>*
+
+ * Reduce the chances of duplicate issuer name and serial numbers (in
+ violation of RFC3280) using the OpenSSL certificate creation utilities.
+ This is done by creating a random 64 bit value for the initial serial
+ number when a serial number file is created or when a self signed
+ certificate is created using 'openssl req -x509'. The initial serial
+ number file is created using 'openssl x509 -next_serial' in CA.pl
+ rather than being initialized to 1.
+
+ *Steve Henson*
+
+### Changes between 0.9.7c and 0.9.7d [17 Mar 2004]
+
+ * Fix null-pointer assignment in do_change_cipher_spec() revealed
+ by using the Codenomicon TLS Test Tool ([CVE-2004-0079])
+
+ *Joe Orton, Steve Henson*
+
+ * Fix flaw in SSL/TLS handshaking when using Kerberos ciphersuites
+ ([CVE-2004-0112])
+
+ *Joe Orton, Steve Henson*
+
+ * Make it possible to have multiple active certificates with the same
+ subject in the CA index file. This is done only if the keyword
+ 'unique_subject' is set to 'no' in the main CA section (default
+ if 'CA_default') of the configuration file. The value is saved
+ with the database itself in a separate index attribute file,
+ named like the index file with '.attr' appended to the name.
+
+ *Richard Levitte*
+
+ * X509 verify fixes. Disable broken certificate workarounds when
+ X509_V_FLAGS_X509_STRICT is set. Check CRL issuer has cRLSign set if
+ keyUsage extension present. Don't accept CRLs with unhandled critical
+ extensions: since verify currently doesn't process CRL extensions this
+ rejects a CRL with *any* critical extensions. Add new verify error codes
+ for these cases.
+
+ *Steve Henson*
+
+ * When creating an OCSP nonce use an OCTET STRING inside the extnValue.
+ A clarification of RFC2560 will require the use of OCTET STRINGs and
+ some implementations cannot handle the current raw format. Since OpenSSL
+ copies and compares OCSP nonces as opaque blobs without any attempt at
+ parsing them this should not create any compatibility issues.
+
+ *Steve Henson*
+
+ * New md flag EVP_MD_CTX_FLAG_REUSE this allows md_data to be reused when
+ calling EVP_MD_CTX_copy_ex() to avoid calling OPENSSL_malloc(). Without
+ this HMAC (and other) operations are several times slower than OpenSSL
+ < 0.9.7.
+
+ *Steve Henson*
+
+ * Print out GeneralizedTime and UTCTime in ASN1_STRING_print_ex().
+
+ *Peter Sylvester <Peter.Sylvester@EdelWeb.fr>*
+
+ * Use the correct content when signing type "other".
+
+ *Steve Henson*
+
+### Changes between 0.9.7b and 0.9.7c [30 Sep 2003]
+
+ * Fix various bugs revealed by running the NISCC test suite:
+
+ Stop out of bounds reads in the ASN1 code when presented with
+ invalid tags (CVE-2003-0543 and CVE-2003-0544).
+
+ Free up ASN1_TYPE correctly if ANY type is invalid ([CVE-2003-0545]).
+
+ If verify callback ignores invalid public key errors don't try to check
+ certificate signature with the NULL public key.
+
+ *Steve Henson*
+
+ * New -ignore_err option in ocsp application to stop the server
+ exiting on the first error in a request.
+
+ *Steve Henson*
+
+ * In ssl3_accept() (ssl/s3_srvr.c) only accept a client certificate
+ if the server requested one: as stated in TLS 1.0 and SSL 3.0
+ specifications.
+
+ *Steve Henson*
+
+ * In ssl3_get_client_hello() (ssl/s3_srvr.c), tolerate additional
+ extra data after the compression methods not only for TLS 1.0
+ but also for SSL 3.0 (as required by the specification).
+
+ *Bodo Moeller; problem pointed out by Matthias Loepfe*
+
+ * Change X509_certificate_type() to mark the key as exported/exportable
+ when it's 512 *bits* long, not 512 bytes.
+
+ *Richard Levitte*
+
+ * Change AES_cbc_encrypt() so it outputs exact multiple of
+ blocks during encryption.
+
+ *Richard Levitte*
+
+ * Various fixes to base64 BIO and non blocking I/O. On write
+ flushes were not handled properly if the BIO retried. On read
+ data was not being buffered properly and had various logic bugs.
+ This also affects blocking I/O when the data being decoded is a
+ certain size.
+
+ *Steve Henson*
+
+ * Various S/MIME bugfixes and compatibility changes:
+ output correct application/pkcs7 MIME type if
+ PKCS7_NOOLDMIMETYPE is set. Tolerate some broken signatures.
+ Output CR+LF for EOL if PKCS7_CRLFEOL is set (this makes opening
+ of files as .eml work). Correctly handle very long lines in MIME
+ parser.
+
+ *Steve Henson*
+
+### Changes between 0.9.7a and 0.9.7b [10 Apr 2003]
+
+ * Countermeasure against the Klima-Pokorny-Rosa extension of
+ Bleichbacher's attack on PKCS #1 v1.5 padding: treat
+ a protocol version number mismatch like a decryption error
+ in ssl3_get_client_key_exchange (ssl/s3_srvr.c).
+
+ *Bodo Moeller*
+
+ * Turn on RSA blinding by default in the default implementation
+ to avoid a timing attack. Applications that don't want it can call
+ RSA_blinding_off() or use the new flag RSA_FLAG_NO_BLINDING.
+ They would be ill-advised to do so in most cases.
+
+ *Ben Laurie, Steve Henson, Geoff Thorpe, Bodo Moeller*
+
+ * Change RSA blinding code so that it works when the PRNG is not
+ seeded (in this case, the secret RSA exponent is abused as
+ an unpredictable seed -- if it is not unpredictable, there
+ is no point in blinding anyway). Make RSA blinding thread-safe
+ by remembering the creator's thread ID in rsa->blinding and
+ having all other threads use local one-time blinding factors
+ (this requires more computation than sharing rsa->blinding, but
+ avoids excessive locking; and if an RSA object is not shared
+ between threads, blinding will still be very fast).
+
+ *Bodo Moeller*
+
+ * Fixed a typo bug that would cause ENGINE_set_default() to set an
+ ENGINE as defaults for all supported algorithms irrespective of
+ the 'flags' parameter. 'flags' is now honoured, so applications
+ should make sure they are passing it correctly.
+
+ *Geoff Thorpe*
+
+ * Target "mingw" now allows native Windows code to be generated in
+ the Cygwin environment as well as with the MinGW compiler.
+
+ *Ulf Moeller*
+
+### Changes between 0.9.7 and 0.9.7a [19 Feb 2003]
+
+ * In ssl3_get_record (ssl/s3_pkt.c), minimize information leaked
+ via timing by performing a MAC computation even if incorrect
+ block cipher padding has been found. This is a countermeasure
+ against active attacks where the attacker has to distinguish
+ between bad padding and a MAC verification error. ([CVE-2003-0078])
+
+ *Bodo Moeller; problem pointed out by Brice Canvel (EPFL),
+ Alain Hiltgen (UBS), Serge Vaudenay (EPFL), and
+ Martin Vuagnoux (EPFL, Ilion)*
+
+ * Make the no-err option work as intended. The intention with no-err
+ is not to have the whole error stack handling routines removed from
+ libcrypto, it's only intended to remove all the function name and
+ reason texts, thereby removing some of the footprint that may not
+ be interesting if those errors aren't displayed anyway.
+
+ NOTE: it's still possible for any application or module to have its
+ own set of error texts inserted. The routines are there, just not
+ used by default when no-err is given.
+
+ *Richard Levitte*
+
+ * Add support for FreeBSD on IA64.
+
+ *dirk.meyer@dinoex.sub.org via Richard Levitte, resolves #454*
+
+ * Adjust DES_cbc_cksum() so it returns the same value as the MIT
+ Kerberos function mit_des_cbc_cksum(). Before this change,
+ the value returned by DES_cbc_cksum() was like the one from
+ mit_des_cbc_cksum(), except the bytes were swapped.
+
+ *Kevin Greaney <Kevin.Greaney@hp.com> and Richard Levitte*
+
+ * Allow an application to disable the automatic SSL chain building.
+ Before this a rather primitive chain build was always performed in
+ ssl3_output_cert_chain(): an application had no way to send the
+ correct chain if the automatic operation produced an incorrect result.
+
+ Now the chain builder is disabled if either:
+
+ 1. Extra certificates are added via SSL_CTX_add_extra_chain_cert().
+
+ 2. The mode flag SSL_MODE_NO_AUTO_CHAIN is set.
+
+ The reasoning behind this is that an application would not want the
+ auto chain building to take place if extra chain certificates are
+ present and it might also want a means of sending no additional
+ certificates (for example the chain has two certificates and the
+ root is omitted).
+
+ *Steve Henson*
+
+ * Add the possibility to build without the ENGINE framework.
+
+ *Steven Reddie <smr@essemer.com.au> via Richard Levitte*
+
+ * Under Win32 gmtime() can return NULL: check return value in
+ OPENSSL_gmtime(). Add error code for case where gmtime() fails.
+
+ *Steve Henson*
+
+ * DSA routines: under certain error conditions uninitialized BN objects
+ could be freed. Solution: make sure initialization is performed early
+ enough. (Reported and fix supplied by Ivan D Nestlerode <nestler@MIT.EDU>,
+ Nils Larsch <nla@trustcenter.de> via PR#459)
+
+ *Lutz Jaenicke*
+
+ * Another fix for SSLv2 session ID handling: the session ID was incorrectly
+ checked on reconnect on the client side, therefore session resumption
+ could still fail with a "ssl session id is different" error. This
+ behaviour is masked when SSL_OP_ALL is used due to
+ SSL_OP_MICROSOFT_SESS_ID_BUG being set.
+ Behaviour observed by Crispin Flowerday <crispin@flowerday.cx> as
+ followup to PR #377.
+
+ *Lutz Jaenicke*
+
+ * IA-32 assembler support enhancements: unified ELF targets, support
+ for SCO/Caldera platforms, fix for Cygwin shared build.
+
+ *Andy Polyakov*
+
+ * Add support for FreeBSD on sparc64. As a consequence, support for
+ FreeBSD on non-x86 processors is separate from x86 processors on
+ the config script, much like the NetBSD support.
+
+ *Richard Levitte & Kris Kennaway <kris@obsecurity.org>*
+
+### Changes between 0.9.6h and 0.9.7 [31 Dec 2002]
+
+[NB: OpenSSL 0.9.6i and later 0.9.6 patch levels were released after
+OpenSSL 0.9.7.]
+
+ * Fix session ID handling in SSLv2 client code: the SERVER FINISHED
+ code (06) was taken as the first octet of the session ID and the last
+ octet was ignored consequently. As a result SSLv2 client side session
+ caching could not have worked due to the session ID mismatch between
+ client and server.
+ Behaviour observed by Crispin Flowerday <crispin@flowerday.cx> as
+ PR #377.
+
+ *Lutz Jaenicke*
+
+ * Change the declaration of needed Kerberos libraries to use EX_LIBS
+ instead of the special (and badly supported) LIBKRB5. LIBKRB5 is
+ removed entirely.
+
+ *Richard Levitte*
+
+ * The hw_ncipher.c engine requires dynamic locks. Unfortunately, it
+ seems that in spite of existing for more than a year, many application
+ author have done nothing to provide the necessary callbacks, which
+ means that this particular engine will not work properly anywhere.
+ This is a very unfortunate situation which forces us, in the name
+ of usability, to give the hw_ncipher.c a static lock, which is part
+ of libcrypto.
+ NOTE: This is for the 0.9.7 series ONLY. This hack will never
+ appear in 0.9.8 or later. We EXPECT application authors to have
+ dealt properly with this when 0.9.8 is released (unless we actually
+ make such changes in the libcrypto locking code that changes will
+ have to be made anyway).
+
+ *Richard Levitte*
+
+ * In asn1_d2i_read_bio() repeatedly call BIO_read() until all content
+ octets have been read, EOF or an error occurs. Without this change
+ some truncated ASN1 structures will not produce an error.
+
+ *Steve Henson*
+
+ * Disable Heimdal support, since it hasn't been fully implemented.
+ Still give the possibility to force the use of Heimdal, but with
+ warnings and a request that patches get sent to openssl-dev.
+
+ *Richard Levitte*
+
+ * Add the VC-CE target, introduce the WINCE sysname, and add
+ INSTALL.WCE and appropriate conditionals to make it build.
+
+ *Steven Reddie <smr@essemer.com.au> via Richard Levitte*
+
+ * Change the DLL names for Cygwin to cygcrypto-x.y.z.dll and
+ cygssl-x.y.z.dll, where x, y and z are the major, minor and
+ edit numbers of the version.
+
+ *Corinna Vinschen <vinschen@redhat.com> and Richard Levitte*
+
+ * Introduce safe string copy and catenation functions
+ (BUF_strlcpy() and BUF_strlcat()).
+
+ *Ben Laurie (CHATS) and Richard Levitte*
+
+ * Avoid using fixed-size buffers for one-line DNs.
+
+ *Ben Laurie (CHATS)*
+
+ * Add BUF_MEM_grow_clean() to avoid information leakage when
+ resizing buffers containing secrets, and use where appropriate.
+
+ *Ben Laurie (CHATS)*
+
+ * Avoid using fixed size buffers for configuration file location.
+
+ *Ben Laurie (CHATS)*
+
+ * Avoid filename truncation for various CA files.
+
+ *Ben Laurie (CHATS)*
+
+ * Use sizeof in preference to magic numbers.
+
+ *Ben Laurie (CHATS)*
+
+ * Avoid filename truncation in cert requests.
+
+ *Ben Laurie (CHATS)*
+
+ * Add assertions to check for (supposedly impossible) buffer
+ overflows.
+
+ *Ben Laurie (CHATS)*
+
+ * Don't cache truncated DNS entries in the local cache (this could
+ potentially lead to a spoofing attack).
+
+ *Ben Laurie (CHATS)*
+
+ * Fix various buffers to be large enough for hex/decimal
+ representations in a platform independent manner.
+
+ *Ben Laurie (CHATS)*
+
+ * Add CRYPTO_realloc_clean() to avoid information leakage when
+ resizing buffers containing secrets, and use where appropriate.
+
+ *Ben Laurie (CHATS)*
+
+ * Add BIO_indent() to avoid much slightly worrying code to do
+ indents.
+
+ *Ben Laurie (CHATS)*
+
+ * Convert sprintf()/BIO_puts() to BIO_printf().
+
+ *Ben Laurie (CHATS)*
+
+ * buffer_gets() could terminate with the buffer only half
+ full. Fixed.
+
+ *Ben Laurie (CHATS)*
+
+ * Add assertions to prevent user-supplied crypto functions from
+ overflowing internal buffers by having large block sizes, etc.
+
+ *Ben Laurie (CHATS)*
+
+ * New OPENSSL_assert() macro (similar to assert(), but enabled
+ unconditionally).
+
+ *Ben Laurie (CHATS)*
+
+ * Eliminate unused copy of key in RC4.
+
+ *Ben Laurie (CHATS)*
+
+ * Eliminate unused and incorrectly sized buffers for IV in pem.h.
+
+ *Ben Laurie (CHATS)*
+
+ * Fix off-by-one error in EGD path.
+
+ *Ben Laurie (CHATS)*
+
+ * If RANDFILE path is too long, ignore instead of truncating.
+
+ *Ben Laurie (CHATS)*
+
+ * Eliminate unused and incorrectly sized X.509 structure
+ CBCParameter.
+
+ *Ben Laurie (CHATS)*
+
+ * Eliminate unused and dangerous function knumber().
+
+ *Ben Laurie (CHATS)*
+
+ * Eliminate unused and dangerous structure, KSSL_ERR.
+
+ *Ben Laurie (CHATS)*
+
+ * Protect against overlong session ID context length in an encoded
+ session object. Since these are local, this does not appear to be
+ exploitable.
+
+ *Ben Laurie (CHATS)*
+
+ * Change from security patch (see 0.9.6e below) that did not affect
+ the 0.9.6 release series:
+
+ Remote buffer overflow in SSL3 protocol - an attacker could
+ supply an oversized master key in Kerberos-enabled versions.
+ ([CVE-2002-0657])
+
+ *Ben Laurie (CHATS)*
+
+ * Change the SSL kerb5 codes to match RFC 2712.
+
+ *Richard Levitte*
+
+ * Make -nameopt work fully for req and add -reqopt switch.
+
+ *Michael Bell <michael.bell@rz.hu-berlin.de>, Steve Henson*
+
+ * The "block size" for block ciphers in CFB and OFB mode should be 1.
+
+ *Steve Henson, reported by Yngve Nysaeter Pettersen <yngve@opera.com>*
+
+ * Make sure tests can be performed even if the corresponding algorithms
+ have been removed entirely. This was also the last step to make
+ OpenSSL compilable with DJGPP under all reasonable conditions.
+
+ *Richard Levitte, Doug Kaufman <dkaufman@rahul.net>*
+
+ * Add cipher selection rules COMPLEMENTOFALL and COMPLEMENTOFDEFAULT
+ to allow version independent disabling of normally unselected ciphers,
+ which may be activated as a side-effect of selecting a single cipher.
+
+ (E.g., cipher list string "RSA" enables ciphersuites that are left
+ out of "ALL" because they do not provide symmetric encryption.
+ "RSA:!COMPLEMEMENTOFALL" avoids these unsafe ciphersuites.)
+
+ *Lutz Jaenicke, Bodo Moeller*
+
+ * Add appropriate support for separate platform-dependent build
+ directories. The recommended way to make a platform-dependent
+ build directory is the following (tested on Linux), maybe with
+ some local tweaks:
+
+ # Place yourself outside of the OpenSSL source tree. In
+ # this example, the environment variable OPENSSL_SOURCE
+ # is assumed to contain the absolute OpenSSL source directory.
+ mkdir -p objtree/"`uname -s`-`uname -r`-`uname -m`"
+ cd objtree/"`uname -s`-`uname -r`-`uname -m`"
+ (cd $OPENSSL_SOURCE; find . -type f) | while read F; do
+ mkdir -p `dirname $F`
+ ln -s $OPENSSL_SOURCE/$F $F
+ done
+
+ To be absolutely sure not to disturb the source tree, a "make clean"
+ is a good thing. If it isn't successful, don't worry about it,
+ it probably means the source directory is very clean.
+
+ *Richard Levitte*
+
+ * Make sure any ENGINE control commands make local copies of string
+ pointers passed to them whenever necessary. Otherwise it is possible
+ the caller may have overwritten (or deallocated) the original string
+ data when a later ENGINE operation tries to use the stored values.
+
+ *Götz Babin-Ebell <babinebell@trustcenter.de>*
+
+ * Improve diagnostics in file reading and command-line digests.
+
+ *Ben Laurie aided and abetted by Solar Designer <solar@openwall.com>*
+
+ * Add AES modes CFB and OFB to the object database. Correct an
+ error in AES-CFB decryption.
+
+ *Richard Levitte*
+
+ * Remove most calls to EVP_CIPHER_CTX_cleanup() in evp_enc.c, this
+ allows existing EVP_CIPHER_CTX structures to be reused after
+ calling `EVP_*Final()`. This behaviour is used by encryption
+ BIOs and some applications. This has the side effect that
+ applications must explicitly clean up cipher contexts with
+ EVP_CIPHER_CTX_cleanup() or they will leak memory.
+
+ *Steve Henson*
+
+ * Check the values of dna and dnb in bn_mul_recursive before calling
+ bn_mul_comba (a non zero value means the a or b arrays do not contain
+ n2 elements) and fallback to bn_mul_normal if either is not zero.
+
+ *Steve Henson*
+
+ * Fix escaping of non-ASCII characters when using the -subj option
+ of the "openssl req" command line tool. (Robert Joop <joop@fokus.gmd.de>)
+
+ *Lutz Jaenicke*
+
+ * Make object definitions compliant to LDAP (RFC2256): SN is the short
+ form for "surname", serialNumber has no short form.
+ Use "mail" as the short name for "rfc822Mailbox" according to RFC2798;
+ therefore remove "mail" short name for "internet 7".
+ The OID for unique identifiers in X509 certificates is
+ x500UniqueIdentifier, not uniqueIdentifier.
+ Some more OID additions. (Michael Bell <michael.bell@rz.hu-berlin.de>)
+
+ *Lutz Jaenicke*
+
+ * Add an "init" command to the ENGINE config module and auto initialize
+ ENGINEs. Without any "init" command the ENGINE will be initialized
+ after all ctrl commands have been executed on it. If init=1 the
+ ENGINE is initialized at that point (ctrls before that point are run
+ on the uninitialized ENGINE and after on the initialized one). If
+ init=0 then the ENGINE will not be initialized at all.
+
+ *Steve Henson*
+
+ * Fix the 'app_verify_callback' interface so that the user-defined
+ argument is actually passed to the callback: In the
+ SSL_CTX_set_cert_verify_callback() prototype, the callback
+ declaration has been changed from
+ int (*cb)()
+ into
+ int (*cb)(X509_STORE_CTX *,void *);
+ in ssl_verify_cert_chain (ssl/ssl_cert.c), the call
+ i=s->ctx->app_verify_callback(&ctx)
+ has been changed into
+ i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg).
+
+ To update applications using SSL_CTX_set_cert_verify_callback(),
+ a dummy argument can be added to their callback functions.
+
+ *D. K. Smetters <smetters@parc.xerox.com>*
+
+ * Added the '4758cca' ENGINE to support IBM 4758 cards.
+
+ *Maurice Gittens <maurice@gittens.nl>, touchups by Geoff Thorpe*
+
+ * Add and OPENSSL_LOAD_CONF define which will cause
+ OpenSSL_add_all_algorithms() to load the openssl.cnf config file.
+ This allows older applications to transparently support certain
+ OpenSSL features: such as crypto acceleration and dynamic ENGINE loading.
+ Two new functions OPENSSL_add_all_algorithms_noconf() which will never
+ load the config file and OPENSSL_add_all_algorithms_conf() which will
+ always load it have also been added.
+
+ *Steve Henson*
+
+ * Add the OFB, CFB and CTR (all with 128 bit feedback) to AES.
+ Adjust NIDs and EVP layer.
+
+ *Stephen Sprunk <stephen@sprunk.org> and Richard Levitte*
+
+ * Config modules support in openssl utility.
+
+ Most commands now load modules from the config file,
+ though in a few (such as version) this isn't done
+ because it couldn't be used for anything.
+
+ In the case of ca and req the config file used is
+ the same as the utility itself: that is the -config
+ command line option can be used to specify an
+ alternative file.
+
+ *Steve Henson*
+
+ * Move default behaviour from OPENSSL_config(). If appname is NULL
+ use "openssl_conf" if filename is NULL use default openssl config file.
+
+ *Steve Henson*
+
+ * Add an argument to OPENSSL_config() to allow the use of an alternative
+ config section name. Add a new flag to tolerate a missing config file
+ and move code to CONF_modules_load_file().
+
+ *Steve Henson*
+
+ * Support for crypto accelerator cards from Accelerated Encryption
+ Processing, www.aep.ie. (Use engine 'aep')
+ The support was copied from 0.9.6c [engine] and adapted/corrected
+ to work with the new engine framework.
+
+ *AEP Inc. and Richard Levitte*
+
+ * Support for SureWare crypto accelerator cards from Baltimore
+ Technologies. (Use engine 'sureware')
+ The support was copied from 0.9.6c [engine] and adapted
+ to work with the new engine framework.
+
+ *Richard Levitte*
+
+ * Have the CHIL engine fork-safe (as defined by nCipher) and actually
+ make the newer ENGINE framework commands for the CHIL engine work.
+
+ *Toomas Kiisk <vix@cyber.ee> and Richard Levitte*
+
+ * Make it possible to produce shared libraries on ReliantUNIX.
+
+ *Robert Dahlem <Robert.Dahlem@ffm2.siemens.de> via Richard Levitte*
+
+ * Add the configuration target debug-linux-ppro.
+ Make 'openssl rsa' use the general key loading routines
+ implemented in `apps.c`, and make those routines able to
+ handle the key format FORMAT_NETSCAPE and the variant
+ FORMAT_IISSGC.
+
+ *Toomas Kiisk <vix@cyber.ee> via Richard Levitte*
+
+ * Fix a crashbug and a logic bug in hwcrhk_load_pubkey().
+
+ *Toomas Kiisk <vix@cyber.ee> via Richard Levitte*
+
+ * Add -keyform to rsautl, and document -engine.
+
+ *Richard Levitte, inspired by Toomas Kiisk <vix@cyber.ee>*
+
+ * Change BIO_new_file (crypto/bio/bss_file.c) to use new
+ BIO_R_NO_SUCH_FILE error code rather than the generic
+ ERR_R_SYS_LIB error code if fopen() fails with ENOENT.
+
+ *Ben Laurie*
+
+ * Add new functions
+ ERR_peek_last_error
+ ERR_peek_last_error_line
+ ERR_peek_last_error_line_data.
+ These are similar to
+ ERR_peek_error
+ ERR_peek_error_line
+ ERR_peek_error_line_data,
+ but report on the latest error recorded rather than the first one
+ still in the error queue.
+
+ *Ben Laurie, Bodo Moeller*
+
+ * default_algorithms option in ENGINE config module. This allows things
+ like:
+ default_algorithms = ALL
+ default_algorithms = RSA, DSA, RAND, CIPHERS, DIGESTS
+
+ *Steve Henson*
+
+ * Preliminary ENGINE config module.
+
+ *Steve Henson*
+
+ * New experimental application configuration code.
+
+ *Steve Henson*
+
+ * Change the AES code to follow the same name structure as all other
+ symmetric ciphers, and behave the same way. Move everything to
+ the directory crypto/aes, thereby obsoleting crypto/rijndael.
+
+ *Stephen Sprunk <stephen@sprunk.org> and Richard Levitte*
+
+ * SECURITY: remove unsafe setjmp/signal interaction from ui_openssl.c.
+
+ *Ben Laurie and Theo de Raadt*
+
+ * Add option to output public keys in req command.
+
+ *Massimiliano Pala madwolf@openca.org*
+
+ * Use wNAFs in EC_POINTs_mul() for improved efficiency
+ (up to about 10% better than before for P-192 and P-224).
+
+ *Bodo Moeller*
+
+ * New functions/macros
+
+ SSL_CTX_set_msg_callback(ctx, cb)
+ SSL_CTX_set_msg_callback_arg(ctx, arg)
+ SSL_set_msg_callback(ssl, cb)
+ SSL_set_msg_callback_arg(ssl, arg)
+
+ to request calling a callback function
+
+ void cb(int write_p, int version, int content_type,
+ const void *buf, size_t len, SSL *ssl, void *arg)
+
+ whenever a protocol message has been completely received
+ (write_p == 0) or sent (write_p == 1). Here 'version' is the
+ protocol version according to which the SSL library interprets
+ the current protocol message (SSL2_VERSION, SSL3_VERSION, or
+ TLS1_VERSION). 'content_type' is 0 in the case of SSL 2.0, or
+ the content type as defined in the SSL 3.0/TLS 1.0 protocol
+ specification (change_cipher_spec(20), alert(21), handshake(22)).
+ 'buf' and 'len' point to the actual message, 'ssl' to the
+ SSL object, and 'arg' is the application-defined value set by
+ SSL[_CTX]_set_msg_callback_arg().
+
+ 'openssl s_client' and 'openssl s_server' have new '-msg' options
+ to enable a callback that displays all protocol messages.
+
+ *Bodo Moeller*
+
+ * Change the shared library support so shared libraries are built as
+ soon as the corresponding static library is finished, and thereby get
+ openssl and the test programs linked against the shared library.
+ This still only happens when the keyword "shard" has been given to
+ the configuration scripts.
+
+ NOTE: shared library support is still an experimental thing, and
+ backward binary compatibility is still not guaranteed.
+
+ *"Maciej W. Rozycki" <macro@ds2.pg.gda.pl> and Richard Levitte*
+
+ * Add support for Subject Information Access extension.
+
+ *Peter Sylvester <Peter.Sylvester@EdelWeb.fr>*
+
+ * Make BUF_MEM_grow() behaviour more consistent: Initialise to zero
+ additional bytes when new memory had to be allocated, not just
+ when reusing an existing buffer.
+
+ *Bodo Moeller*
+
+ * New command line and configuration option 'utf8' for the req command.
+ This allows field values to be specified as UTF8 strings.
+
+ *Steve Henson*
+
+ * Add -multi and -mr options to "openssl speed" - giving multiple parallel
+ runs for the former and machine-readable output for the latter.
+
+ *Ben Laurie*
+
+ * Add '-noemailDN' option to 'openssl ca'. This prevents inclusion
+ of the e-mail address in the DN (i.e., it will go into a certificate
+ extension only). The new configuration file option 'email_in_dn = no'
+ has the same effect.
+
+ *Massimiliano Pala madwolf@openca.org*
+
+ * Change all functions with names starting with `des_` to be starting
+ with `DES_` instead. Add wrappers that are compatible with libdes,
+ but are named `_ossl_old_des_*`. Finally, add macros that map the
+ `des_*` symbols to the corresponding `_ossl_old_des_*` if libdes
+ compatibility is desired. If OpenSSL 0.9.6c compatibility is
+ desired, the `des_*` symbols will be mapped to `DES_*`, with one
+ exception.
+
+ Since we provide two compatibility mappings, the user needs to
+ define the macro OPENSSL_DES_LIBDES_COMPATIBILITY if libdes
+ compatibility is desired. The default (i.e., when that macro
+ isn't defined) is OpenSSL 0.9.6c compatibility.
+
+ There are also macros that enable and disable the support of old
+ des functions altogether. Those are OPENSSL_ENABLE_OLD_DES_SUPPORT
+ and OPENSSL_DISABLE_OLD_DES_SUPPORT. If none or both of those
+ are defined, the default will apply: to support the old des routines.
+
+ In either case, one must include openssl/des.h to get the correct
+ definitions. Do not try to just include openssl/des_old.h, that
+ won't work.
+
+ NOTE: This is a major break of an old API into a new one. Software
+ authors are encouraged to switch to the `DES_` style functions. Some
+ time in the future, des_old.h and the libdes compatibility functions
+ will be disable (i.e. OPENSSL_DISABLE_OLD_DES_SUPPORT will be the
+ default), and then completely removed.
+
+ *Richard Levitte*
+
+ * Test for certificates which contain unsupported critical extensions.
+ If such a certificate is found during a verify operation it is
+ rejected by default: this behaviour can be overridden by either
+ handling the new error X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION or
+ by setting the verify flag X509_V_FLAG_IGNORE_CRITICAL. A new function
+ X509_supported_extension() has also been added which returns 1 if a
+ particular extension is supported.
+
+ *Steve Henson*
+
+ * Modify the behaviour of EVP cipher functions in similar way to digests
+ to retain compatibility with existing code.
+
+ *Steve Henson*
+
+ * Modify the behaviour of EVP_DigestInit() and EVP_DigestFinal() to retain
+ compatibility with existing code. In particular the 'ctx' parameter does
+ not have to be to be initialized before the call to EVP_DigestInit() and
+ it is tidied up after a call to EVP_DigestFinal(). New function
+ EVP_DigestFinal_ex() which does not tidy up the ctx. Similarly function
+ EVP_MD_CTX_copy() changed to not require the destination to be
+ initialized valid and new function EVP_MD_CTX_copy_ex() added which
+ requires the destination to be valid.
+
+ Modify all the OpenSSL digest calls to use EVP_DigestInit_ex(),
+ EVP_DigestFinal_ex() and EVP_MD_CTX_copy_ex().
+
+ *Steve Henson*
+
+ * Change ssl3_get_message (ssl/s3_both.c) and the functions using it
+ so that complete 'Handshake' protocol structures are kept in memory
+ instead of overwriting 'msg_type' and 'length' with 'body' data.
+
+ *Bodo Moeller*
+
+ * Add an implementation of SSL_add_dir_cert_subjects_to_stack for Win32.
+
+ *Massimo Santin via Richard Levitte*
+
+ * Major restructuring to the underlying ENGINE code. This includes
+ reduction of linker bloat, separation of pure "ENGINE" manipulation
+ (initialisation, etc) from functionality dealing with implementations
+ of specific crypto interfaces. This change also introduces integrated
+ support for symmetric ciphers and digest implementations - so ENGINEs
+ can now accelerate these by providing EVP_CIPHER and EVP_MD
+ implementations of their own. This is detailed in
+ [crypto/engine/README.md](crypto/engine/README.md)
+ as it couldn't be adequately described here. However, there are a few
+ API changes worth noting - some RSA, DSA, DH, and RAND functions that
+ were changed in the original introduction of ENGINE code have now
+ reverted back - the hooking from this code to ENGINE is now a good
+ deal more passive and at run-time, operations deal directly with
+ RSA_METHODs, DSA_METHODs (etc) as they did before, rather than
+ dereferencing through an ENGINE pointer any more. Also, the ENGINE
+ functions dealing with `BN_MOD_EXP[_CRT]` handlers have been removed -
+ they were not being used by the framework as there is no concept of a
+ BIGNUM_METHOD and they could not be generalised to the new
+ 'ENGINE_TABLE' mechanism that underlies the new code. Similarly,
+ ENGINE_cpy() has been removed as it cannot be consistently defined in
+ the new code.
+
+ *Geoff Thorpe*
+
+ * Change ASN1_GENERALIZEDTIME_check() to allow fractional seconds.
+
+ *Steve Henson*
+
+ * Change mkdef.pl to sort symbols that get the same entry number,
+ and make sure the automatically generated functions `ERR_load_*`
+ become part of libeay.num as well.
+
+ *Richard Levitte*
+
+ * New function SSL_renegotiate_pending(). This returns true once
+ renegotiation has been requested (either SSL_renegotiate() call
+ or HelloRequest/ClientHello received from the peer) and becomes
+ false once a handshake has been completed.
+ (For servers, SSL_renegotiate() followed by SSL_do_handshake()
+ sends a HelloRequest, but does not ensure that a handshake takes
+ place. SSL_renegotiate_pending() is useful for checking if the
+ client has followed the request.)
+
+ *Bodo Moeller*
+
+ * New SSL option SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION.
+ By default, clients may request session resumption even during
+ renegotiation (if session ID contexts permit); with this option,
+ session resumption is possible only in the first handshake.
+
+ SSL_OP_ALL is now 0x00000FFFL instead of 0x000FFFFFL. This makes
+ more bits available for options that should not be part of
+ SSL_OP_ALL (such as SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION).
+
+ *Bodo Moeller*
+
+ * Add some demos for certificate and certificate request creation.
+
+ *Steve Henson*
+
+ * Make maximum certificate chain size accepted from the peer application
+ settable (`SSL*_get/set_max_cert_list()`), as proposed by
+ "Douglas E. Engert" <deengert@anl.gov>.
+
+ *Lutz Jaenicke*
+
+ * Add support for shared libraries for Unixware-7
+ (Boyd Lynn Gerber <gerberb@zenez.com>).
+
+ *Lutz Jaenicke*
+
+ * Add a "destroy" handler to ENGINEs that allows structural cleanup to
+ be done prior to destruction. Use this to unload error strings from
+ ENGINEs that load their own error strings. NB: This adds two new API
+ functions to "get" and "set" this destroy handler in an ENGINE.
+
+ *Geoff Thorpe*
+
+ * Alter all existing ENGINE implementations (except "openssl" and
+ "openbsd") to dynamically instantiate their own error strings. This
+ makes them more flexible to be built both as statically-linked ENGINEs
+ and self-contained shared-libraries loadable via the "dynamic" ENGINE.
+ Also, add stub code to each that makes building them as self-contained
+ shared-libraries easier (see [README-Engine.md](README-Engine.md)).
+
+ *Geoff Thorpe*
+
+ * Add a "dynamic" ENGINE that provides a mechanism for binding ENGINE
+ implementations into applications that are completely implemented in
+ self-contained shared-libraries. The "dynamic" ENGINE exposes control
+ commands that can be used to configure what shared-library to load and
+ to control aspects of the way it is handled. Also, made an update to
+ the [README-Engine.md](README-Engine.md) file
+ that brings its information up-to-date and
+ provides some information and instructions on the "dynamic" ENGINE
+ (ie. how to use it, how to build "dynamic"-loadable ENGINEs, etc).
+
+ *Geoff Thorpe*
+
+ * Make it possible to unload ranges of ERR strings with a new
+ "ERR_unload_strings" function.
+
+ *Geoff Thorpe*
+
+ * Add a copy() function to EVP_MD.
+
+ *Ben Laurie*
+
+ * Make EVP_MD routines take a context pointer instead of just the
+ md_data void pointer.
+
+ *Ben Laurie*
+
+ * Add flags to EVP_MD and EVP_MD_CTX. EVP_MD_FLAG_ONESHOT indicates
+ that the digest can only process a single chunk of data
+ (typically because it is provided by a piece of
+ hardware). EVP_MD_CTX_FLAG_ONESHOT indicates that the application
+ is only going to provide a single chunk of data, and hence the
+ framework needn't accumulate the data for oneshot drivers.
+
+ *Ben Laurie*
+
+ * As with "ERR", make it possible to replace the underlying "ex_data"
+ functions. This change also alters the storage and management of global
+ ex_data state - it's now all inside ex_data.c and all "class" code (eg.
+ RSA, BIO, SSL_CTX, etc) no longer stores its own STACKS and per-class
+ index counters. The API functions that use this state have been changed
+ to take a "class_index" rather than pointers to the class's local STACK
+ and counter, and there is now an API function to dynamically create new
+ classes. This centralisation allows us to (a) plug a lot of the
+ thread-safety problems that existed, and (b) makes it possible to clean
+ up all allocated state using "CRYPTO_cleanup_all_ex_data()". W.r.t. (b)
+ such data would previously have always leaked in application code and
+ workarounds were in place to make the memory debugging turn a blind eye
+ to it. Application code that doesn't use this new function will still
+ leak as before, but their memory debugging output will announce it now
+ rather than letting it slide.
+
+ Besides the addition of CRYPTO_cleanup_all_ex_data(), another API change
+ induced by the "ex_data" overhaul is that X509_STORE_CTX_init() now
+ has a return value to indicate success or failure.
+
+ *Geoff Thorpe*
+
+ * Make it possible to replace the underlying "ERR" functions such that the
+ global state (2 LHASH tables and 2 locks) is only used by the "default"
+ implementation. This change also adds two functions to "get" and "set"
+ the implementation prior to it being automatically set the first time
+ any other ERR function takes place. Ie. an application can call "get",
+ pass the return value to a module it has just loaded, and that module
+ can call its own "set" function using that value. This means the
+ module's "ERR" operations will use (and modify) the error state in the
+ application and not in its own statically linked copy of OpenSSL code.
+
+ *Geoff Thorpe*
+
+ * Give DH, DSA, and RSA types their own `*_up_ref()` function to increment
+ reference counts. This performs normal REF_PRINT/REF_CHECK macros on
+ the operation, and provides a more encapsulated way for external code
+ (crypto/evp/ and ssl/) to do this. Also changed the evp and ssl code
+ to use these functions rather than manually incrementing the counts.
+
+ Also rename "DSO_up()" function to more descriptive "DSO_up_ref()".
+
+ *Geoff Thorpe*
+
+ * Add EVP test program.
+
+ *Ben Laurie*
+
+ * Add symmetric cipher support to ENGINE. Expect the API to change!
+
+ *Ben Laurie*
+
+ * New CRL functions: X509_CRL_set_version(), X509_CRL_set_issuer_name()
+ X509_CRL_set_lastUpdate(), X509_CRL_set_nextUpdate(), X509_CRL_sort(),
+ X509_REVOKED_set_serialNumber(), and X509_REVOKED_set_revocationDate().
+ These allow a CRL to be built without having to access X509_CRL fields
+ directly. Modify 'ca' application to use new functions.
+
+ *Steve Henson*
+
+ * Move SSL_OP_TLS_ROLLBACK_BUG out of the SSL_OP_ALL list of recommended
+ bug workarounds. Rollback attack detection is a security feature.
+ The problem will only arise on OpenSSL servers when TLSv1 is not
+ available (sslv3_server_method() or SSL_OP_NO_TLSv1).
+ Software authors not wanting to support TLSv1 will have special reasons
+ for their choice and can explicitly enable this option.
+
+ *Bodo Moeller, Lutz Jaenicke*
+
+ * Rationalise EVP so it can be extended: don't include a union of
+ cipher/digest structures, add init/cleanup functions for EVP_MD_CTX
+ (similar to those existing for EVP_CIPHER_CTX).
+ Usage example:
+
+ EVP_MD_CTX md;
+
+ EVP_MD_CTX_init(&md); /* new function call */
+ EVP_DigestInit(&md, EVP_sha1());
+ EVP_DigestUpdate(&md, in, len);
+ EVP_DigestFinal(&md, out, NULL);
+ EVP_MD_CTX_cleanup(&md); /* new function call */
+
+ *Ben Laurie*
+
+ * Make DES key schedule conform to the usual scheme, as well as
+ correcting its structure. This means that calls to DES functions
+ now have to pass a pointer to a des_key_schedule instead of a
+ plain des_key_schedule (which was actually always a pointer
+ anyway): E.g.,
+
+ des_key_schedule ks;
+
+ des_set_key_checked(..., &ks);
+ des_ncbc_encrypt(..., &ks, ...);
+
+ (Note that a later change renames 'des_...' into 'DES_...'.)
+
+ *Ben Laurie*
+
+ * Initial reduction of linker bloat: the use of some functions, such as
+ PEM causes large amounts of unused functions to be linked in due to
+ poor organisation. For example pem_all.c contains every PEM function
+ which has a knock on effect of linking in large amounts of (unused)
+ ASN1 code. Grouping together similar functions and splitting unrelated
+ functions prevents this.
+
+ *Steve Henson*
+
+ * Cleanup of EVP macros.
+
+ *Ben Laurie*
+
+ * Change historical references to `{NID,SN,LN}_des_ede` and ede3 to add the
+ correct `_ecb suffix`.
+
+ *Ben Laurie*
+
+ * Add initial OCSP responder support to ocsp application. The
+ revocation information is handled using the text based index
+ use by the ca application. The responder can either handle
+ requests generated internally, supplied in files (for example
+ via a CGI script) or using an internal minimal server.
+
+ *Steve Henson*
+
+ * Add configuration choices to get zlib compression for TLS.
+
+ *Richard Levitte*
+
+ * Changes to Kerberos SSL for RFC 2712 compliance:
+ 1. Implemented real KerberosWrapper, instead of just using
+ KRB5 AP_REQ message. [Thanks to Simon Wilkinson <sxw@sxw.org.uk>]
+ 2. Implemented optional authenticator field of KerberosWrapper.
+
+ Added openssl-style ASN.1 macros for Kerberos ticket, ap_req,
+ and authenticator structs; see crypto/krb5/.
+
+ Generalized Kerberos calls to support multiple Kerberos libraries.
+ *Vern Staats <staatsvr@asc.hpc.mil>, Jeffrey Altman <jaltman@columbia.edu>
+ via Richard Levitte*
+
+ * Cause 'openssl speed' to use fully hard-coded DSA keys as it
+ already does with RSA. testdsa.h now has 'priv_key/pub_key'
+ values for each of the key sizes rather than having just
+ parameters (and 'speed' generating keys each time).
+
+ *Geoff Thorpe*
+
+ * Speed up EVP routines.
+ Before:
+crypt
+pe 8 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes
+s-cbc 4408.85k 5560.51k 5778.46k 5862.20k 5825.16k
+s-cbc 4389.55k 5571.17k 5792.23k 5846.91k 5832.11k
+s-cbc 4394.32k 5575.92k 5807.44k 5848.37k 5841.30k
+crypt
+s-cbc 3482.66k 5069.49k 5496.39k 5614.16k 5639.28k
+s-cbc 3480.74k 5068.76k 5510.34k 5609.87k 5635.52k
+s-cbc 3483.72k 5067.62k 5504.60k 5708.01k 5724.80k
+ After:
+crypt
+s-cbc 4660.16k 5650.19k 5807.19k 5827.13k 5783.32k
+crypt
+s-cbc 3624.96k 5258.21k 5530.91k 5624.30k 5628.26k
+
+ *Ben Laurie*
+
+ * Added the OS2-EMX target.
+
+ *"Brian Havard" <brianh@kheldar.apana.org.au> and Richard Levitte*
+
+ * Rewrite commands to use `NCONF` routines instead of the old `CONF`.
+ New functions to support `NCONF` routines in extension code.
+ New function `CONF_set_nconf()`
+ to allow functions which take an `NCONF` to also handle the old `LHASH`
+ structure: this means that the old `CONF` compatible routines can be
+ retained (in particular w.rt. extensions) without having to duplicate the
+ code. New function `X509V3_add_ext_nconf_sk()` to add extensions to a stack.
+
+ *Steve Henson*
+
+ * Enhance the general user interface with mechanisms for inner control
+ and with possibilities to have yes/no kind of prompts.
+
+ *Richard Levitte*
+
+ * Change all calls to low-level digest routines in the library and
+ applications to use EVP. Add missing calls to HMAC_cleanup() and
+ don't assume HMAC_CTX can be copied using memcpy().
+
+ *Verdon Walker <VWalker@novell.com>, Steve Henson*
+
+ * Add the possibility to control engines through control names but with
+ arbitrary arguments instead of just a string.
+ Change the key loaders to take a UI_METHOD instead of a callback
+ function pointer. NOTE: this breaks binary compatibility with earlier
+ versions of OpenSSL [engine].
+ Adapt the nCipher code for these new conditions and add a card insertion
+ callback.
+
+ *Richard Levitte*
+
+ * Enhance the general user interface with mechanisms to better support
+ dialog box interfaces, application-defined prompts, the possibility
+ to use defaults (for example default passwords from somewhere else)
+ and interrupts/cancellations.
+
+ *Richard Levitte*
+
+ * Tidy up PKCS#12 attribute handling. Add support for the CSP name
+ attribute in PKCS#12 files, add new -CSP option to pkcs12 utility.
+
+ *Steve Henson*
+
+ * Fix a memory leak in 'sk_dup()' in the case reallocation fails. (Also
+ tidy up some unnecessarily weird code in 'sk_new()').
+
+ *Geoff, reported by Diego Tartara <dtartara@novamens.com>*
+
+ * Change the key loading routines for ENGINEs to use the same kind
+ callback (pem_password_cb) as all other routines that need this
+ kind of callback.
+
+ *Richard Levitte*
+
+ * Increase ENTROPY_NEEDED to 32 bytes, as Rijndael can operate with
+ 256 bit (=32 byte) keys. Of course seeding with more entropy bytes
+ than this minimum value is recommended.
+
+ *Lutz Jaenicke*
+
+ * New random seeder for OpenVMS, using the system process statistics
+ that are easily reachable.
+
+ *Richard Levitte*
+
+ * Windows apparently can't transparently handle global
+ variables defined in DLLs. Initialisations such as:
+
+ const ASN1_ITEM *it = &ASN1_INTEGER_it;
+
+ won't compile. This is used by the any applications that need to
+ declare their own ASN1 modules. This was fixed by adding the option
+ EXPORT_VAR_AS_FN to all Win32 platforms, although this isn't strictly
+ needed for static libraries under Win32.
+
+ *Steve Henson*
+
+ * New functions X509_PURPOSE_set() and X509_TRUST_set() to handle
+ setting of purpose and trust fields. New X509_STORE trust and
+ purpose functions and tidy up setting in other SSL functions.
+
+ *Steve Henson*
+
+ * Add copies of X509_STORE_CTX fields and callbacks to X509_STORE
+ structure. These are inherited by X509_STORE_CTX when it is
+ initialised. This allows various defaults to be set in the
+ X509_STORE structure (such as flags for CRL checking and custom
+ purpose or trust settings) for functions which only use X509_STORE_CTX
+ internally such as S/MIME.
+
+ Modify X509_STORE_CTX_purpose_inherit() so it only sets purposes and
+ trust settings if they are not set in X509_STORE. This allows X509_STORE
+ purposes and trust (in S/MIME for example) to override any set by default.
+
+ Add command line options for CRL checking to smime, s_client and s_server
+ applications.
+
+ *Steve Henson*
+
+ * Initial CRL based revocation checking. If the CRL checking flag(s)
+ are set then the CRL is looked up in the X509_STORE structure and
+ its validity and signature checked, then if the certificate is found
+ in the CRL the verify fails with a revoked error.
+
+ Various new CRL related callbacks added to X509_STORE_CTX structure.
+
+ Command line options added to 'verify' application to support this.
+
+ This needs some additional work, such as being able to handle multiple
+ CRLs with different times, extension based lookup (rather than just
+ by subject name) and ultimately more complete V2 CRL extension
+ handling.
+
+ *Steve Henson*
+
+ * Add a general user interface API (crypto/ui/). This is designed
+ to replace things like des_read_password and friends (backward
+ compatibility functions using this new API are provided).
+ The purpose is to remove prompting functions from the DES code
+ section as well as provide for prompting through dialog boxes in
+ a window system and the like.
+
+ *Richard Levitte*
+
+ * Add "ex_data" support to ENGINE so implementations can add state at a
+ per-structure level rather than having to store it globally.
+
+ *Geoff*
+
+ * Make it possible for ENGINE structures to be copied when retrieved by
+ ENGINE_by_id() if the ENGINE specifies a new flag: ENGINE_FLAGS_BY_ID_COPY.
+ This causes the "original" ENGINE structure to act like a template,
+ analogous to the RSA vs. RSA_METHOD type of separation. Because of this
+ operational state can be localised to each ENGINE structure, despite the
+ fact they all share the same "methods". New ENGINE structures returned in
+ this case have no functional references and the return value is the single
+ structural reference. This matches the single structural reference returned
+ by ENGINE_by_id() normally, when it is incremented on the pre-existing
+ ENGINE structure.
+
+ *Geoff*
+
+ * Fix ASN1 decoder when decoding type ANY and V_ASN1_OTHER: since this
+ needs to match any other type at all we need to manually clear the
+ tag cache.
+
+ *Steve Henson*
+
+ * Changes to the "openssl engine" utility to include;
+ - verbosity levels ('-v', '-vv', and '-vvv') that provide information
+ about an ENGINE's available control commands.
+ - executing control commands from command line arguments using the
+ '-pre' and '-post' switches. '-post' is only used if '-t' is
+ specified and the ENGINE is successfully initialised. The syntax for
+ the individual commands are colon-separated, for example;
+ openssl engine chil -pre FORK_CHECK:0 -pre SO_PATH:/lib/test.so
+
+ *Geoff*
+
+ * New dynamic control command support for ENGINEs. ENGINEs can now
+ declare their own commands (numbers), names (strings), descriptions,
+ and input types for run-time discovery by calling applications. A
+ subset of these commands are implicitly classed as "executable"
+ depending on their input type, and only these can be invoked through
+ the new string-based API function ENGINE_ctrl_cmd_string(). (Eg. this
+ can be based on user input, config files, etc). The distinction is
+ that "executable" commands cannot return anything other than a boolean
+ result and can only support numeric or string input, whereas some
+ discoverable commands may only be for direct use through
+ ENGINE_ctrl(), eg. supporting the exchange of binary data, function
+ pointers, or other custom uses. The "executable" commands are to
+ support parameterisations of ENGINE behaviour that can be
+ unambiguously defined by ENGINEs and used consistently across any
+ OpenSSL-based application. Commands have been added to all the
+ existing hardware-supporting ENGINEs, noticeably "SO_PATH" to allow
+ control over shared-library paths without source code alterations.
+
+ *Geoff*
+
+ * Changed all ENGINE implementations to dynamically allocate their
+ ENGINEs rather than declaring them statically. Apart from this being
+ necessary with the removal of the ENGINE_FLAGS_MALLOCED distinction,
+ this also allows the implementations to compile without using the
+ internal engine_int.h header.
+
+ *Geoff*
+
+ * Minor adjustment to "rand" code. RAND_get_rand_method() now returns a
+ 'const' value. Any code that should be able to modify a RAND_METHOD
+ should already have non-const pointers to it (ie. they should only
+ modify their own ones).
+
+ *Geoff*
+
+ * Made a variety of little tweaks to the ENGINE code.
+ - "atalla" and "ubsec" string definitions were moved from header files
+ to C code. "nuron" string definitions were placed in variables
+ rather than hard-coded - allowing parameterisation of these values
+ later on via ctrl() commands.
+ - Removed unused "#if 0"'d code.
+ - Fixed engine list iteration code so it uses ENGINE_free() to release
+ structural references.
+ - Constified the RAND_METHOD element of ENGINE structures.
+ - Constified various get/set functions as appropriate and added
+ missing functions (including a catch-all ENGINE_cpy that duplicates
+ all ENGINE values onto a new ENGINE except reference counts/state).
+ - Removed NULL parameter checks in get/set functions. Setting a method
+ or function to NULL is a way of cancelling out a previously set
+ value. Passing a NULL ENGINE parameter is just plain stupid anyway
+ and doesn't justify the extra error symbols and code.
+ - Deprecate the ENGINE_FLAGS_MALLOCED define and move the area for
+ flags from engine_int.h to engine.h.
+ - Changed prototypes for ENGINE handler functions (init(), finish(),
+ ctrl(), key-load functions, etc) to take an (ENGINE*) parameter.
+
+ *Geoff*
+
+ * Implement binary inversion algorithm for BN_mod_inverse in addition
+ to the algorithm using long division. The binary algorithm can be
+ used only if the modulus is odd. On 32-bit systems, it is faster
+ only for relatively small moduli (roughly 20-30% for 128-bit moduli,
+ roughly 5-15% for 256-bit moduli), so we use it only for moduli
+ up to 450 bits. In 64-bit environments, the binary algorithm
+ appears to be advantageous for much longer moduli; here we use it
+ for moduli up to 2048 bits.
+
+ *Bodo Moeller*
+
+ * Rewrite CHOICE field setting in ASN1_item_ex_d2i(). The old code
+ could not support the combine flag in choice fields.
+
+ *Steve Henson*
+
+ * Add a 'copy_extensions' option to the 'ca' utility. This copies
+ extensions from a certificate request to the certificate.
+
+ *Steve Henson*
+
+ * Allow multiple 'certopt' and 'nameopt' options to be separated
+ by commas. Add 'namopt' and 'certopt' options to the 'ca' config
+ file: this allows the display of the certificate about to be
+ signed to be customised, to allow certain fields to be included
+ or excluded and extension details. The old system didn't display
+ multicharacter strings properly, omitted fields not in the policy
+ and couldn't display additional details such as extensions.
+
+ *Steve Henson*
+
+ * Function EC_POINTs_mul for multiple scalar multiplication
+ of an arbitrary number of elliptic curve points
+ \sum scalars[i]*points[i],
+ optionally including the generator defined for the EC_GROUP:
+ scalar*generator + \sum scalars[i]*points[i].
+
+ EC_POINT_mul is a simple wrapper function for the typical case
+ that the point list has just one item (besides the optional
+ generator).
+
+ *Bodo Moeller*
+
+ * First EC_METHODs for curves over GF(p):
+
+ EC_GFp_simple_method() uses the basic BN_mod_mul and BN_mod_sqr
+ operations and provides various method functions that can also
+ operate with faster implementations of modular arithmetic.
+
+ EC_GFp_mont_method() reuses most functions that are part of
+ EC_GFp_simple_method, but uses Montgomery arithmetic.
+
+ *Bodo Moeller; point addition and point doubling
+ implementation directly derived from source code provided by
+ Lenka Fibikova <fibikova@exp-math.uni-essen.de>*
+
+ * Framework for elliptic curves (crypto/ec/ec.h, crypto/ec/ec_lcl.h,
+ crypto/ec/ec_lib.c):
+
+ Curves are EC_GROUP objects (with an optional group generator)
+ based on EC_METHODs that are built into the library.
+
+ Points are EC_POINT objects based on EC_GROUP objects.
+
+ Most of the framework would be able to handle curves over arbitrary
+ finite fields, but as there are no obvious types for fields other
+ than GF(p), some functions are limited to that for now.
+
+ *Bodo Moeller*
+
+ * Add the -HTTP option to s_server. It is similar to -WWW, but requires
+ that the file contains a complete HTTP response.
+
+ *Richard Levitte*
+
+ * Add the ec directory to mkdef.pl and mkfiles.pl. In mkdef.pl
+ change the def and num file printf format specifier from "%-40sXXX"
+ to "%-39s XXX". The latter will always guarantee a space after the
+ field while the former will cause them to run together if the field
+ is 40 of more characters long.
+
+ *Steve Henson*
+
+ * Constify the cipher and digest 'method' functions and structures
+ and modify related functions to take constant EVP_MD and EVP_CIPHER
+ pointers.
+
+ *Steve Henson*
+
+ * Hide BN_CTX structure details in bn_lcl.h instead of publishing them
+ in <openssl/bn.h>. Also further increase BN_CTX_NUM to 32.
+
+ *Bodo Moeller*
+
+ * Modify `EVP_Digest*()` routines so they now return values. Although the
+ internal software routines can never fail additional hardware versions
+ might.
+
+ *Steve Henson*
+
+ * Clean up crypto/err/err.h and change some error codes to avoid conflicts:
+
+ Previously ERR_R_FATAL was too small and coincided with ERR_LIB_PKCS7
+ (= ERR_R_PKCS7_LIB); it is now 64 instead of 32.
+
+ ASN1 error codes
+ ERR_R_NESTED_ASN1_ERROR
+ ...
+ ERR_R_MISSING_ASN1_EOS
+ were 4 .. 9, conflicting with
+ ERR_LIB_RSA (= ERR_R_RSA_LIB)
+ ...
+ ERR_LIB_PEM (= ERR_R_PEM_LIB).
+ They are now 58 .. 63 (i.e., just below ERR_R_FATAL).
+
+ Add new error code 'ERR_R_INTERNAL_ERROR'.
+
+ *Bodo Moeller*
+
+ * Don't overuse locks in crypto/err/err.c: For data retrieval, CRYPTO_r_lock
+ suffices.
+
+ *Bodo Moeller*
+
+ * New option '-subj arg' for 'openssl req' and 'openssl ca'. This
+ sets the subject name for a new request or supersedes the
+ subject name in a given request. Formats that can be parsed are
+ 'CN=Some Name, OU=myOU, C=IT'
+ and
+ 'CN=Some Name/OU=myOU/C=IT'.
+
+ Add options '-batch' and '-verbose' to 'openssl req'.
+
+ *Massimiliano Pala <madwolf@hackmasters.net>*
+
+ * Introduce the possibility to access global variables through
+ functions on platform were that's the best way to handle exporting
+ global variables in shared libraries. To enable this functionality,
+ one must configure with "EXPORT_VAR_AS_FN" or defined the C macro
+ "OPENSSL_EXPORT_VAR_AS_FUNCTION" in crypto/opensslconf.h (the latter
+ is normally done by Configure or something similar).
+
+ To implement a global variable, use the macro OPENSSL_IMPLEMENT_GLOBAL
+ in the source file (foo.c) like this:
+
+ OPENSSL_IMPLEMENT_GLOBAL(int,foo)=1;
+ OPENSSL_IMPLEMENT_GLOBAL(double,bar);
+
+ To declare a global variable, use the macros OPENSSL_DECLARE_GLOBAL
+ and OPENSSL_GLOBAL_REF in the header file (foo.h) like this:
+
+ OPENSSL_DECLARE_GLOBAL(int,foo);
+ #define foo OPENSSL_GLOBAL_REF(foo)
+ OPENSSL_DECLARE_GLOBAL(double,bar);
+ #define bar OPENSSL_GLOBAL_REF(bar)
+
+ The #defines are very important, and therefore so is including the
+ header file everywhere where the defined globals are used.
+
+ The macro OPENSSL_EXPORT_VAR_AS_FUNCTION also affects the definition
+ of ASN.1 items, but that structure is a bit different.
+
+ The largest change is in util/mkdef.pl which has been enhanced with
+ better and easier to understand logic to choose which symbols should
+ go into the Windows .def files as well as a number of fixes and code
+ cleanup (among others, algorithm keywords are now sorted
+ lexicographically to avoid constant rewrites).
+
+ *Richard Levitte*
+
+ * In BN_div() keep a copy of the sign of 'num' before writing the
+ result to 'rm' because if rm==num the value will be overwritten
+ and produce the wrong result if 'num' is negative: this caused
+ problems with BN_mod() and BN_nnmod().
+
+ *Steve Henson*
+
+ * Function OCSP_request_verify(). This checks the signature on an
+ OCSP request and verifies the signer certificate. The signer
+ certificate is just checked for a generic purpose and OCSP request
+ trust settings.
+
+ *Steve Henson*
+
+ * Add OCSP_check_validity() function to check the validity of OCSP
+ responses. OCSP responses are prepared in real time and may only
+ be a few seconds old. Simply checking that the current time lies
+ between thisUpdate and nextUpdate max reject otherwise valid responses
+ caused by either OCSP responder or client clock inaccuracy. Instead
+ we allow thisUpdate and nextUpdate to fall within a certain period of
+ the current time. The age of the response can also optionally be
+ checked. Two new options -validity_period and -status_age added to
+ ocsp utility.
+
+ *Steve Henson*
+
+ * If signature or public key algorithm is unrecognized print out its
+ OID rather that just UNKNOWN.
+
+ *Steve Henson*
+
+ * Change OCSP_cert_to_id() to tolerate a NULL subject certificate and
+ OCSP_cert_id_new() a NULL serialNumber. This allows a partial certificate
+ ID to be generated from the issuer certificate alone which can then be
+ passed to OCSP_id_issuer_cmp().
+
+ *Steve Henson*
+
+ * New compilation option ASN1_ITEM_FUNCTIONS. This causes the new
+ ASN1 modules to export functions returning ASN1_ITEM pointers
+ instead of the ASN1_ITEM structures themselves. This adds several
+ new macros which allow the underlying ASN1 function/structure to
+ be accessed transparently. As a result code should not use ASN1_ITEM
+ references directly (such as &X509_it) but instead use the relevant
+ macros (such as ASN1_ITEM_rptr(X509)). This option is to allow
+ use of the new ASN1 code on platforms where exporting structures
+ is problematical (for example in shared libraries) but exporting
+ functions returning pointers to structures is not.
+
+ *Steve Henson*
+
+ * Add support for overriding the generation of SSL/TLS session IDs.
+ These callbacks can be registered either in an SSL_CTX or per SSL.
+ The purpose of this is to allow applications to control, if they wish,
+ the arbitrary values chosen for use as session IDs, particularly as it
+ can be useful for session caching in multiple-server environments. A
+ command-line switch for testing this (and any client code that wishes
+ to use such a feature) has been added to "s_server".
+
+ *Geoff Thorpe, Lutz Jaenicke*
+
+ * Modify mkdef.pl to recognise and parse preprocessor conditionals
+ of the form `#if defined(...) || defined(...) || ...` and
+ `#if !defined(...) && !defined(...) && ...`. This also avoids
+ the growing number of special cases it was previously handling.
+
+ *Richard Levitte*
+
+ * Make all configuration macros available for application by making
+ sure they are available in opensslconf.h, by giving them names starting
+ with `OPENSSL_` to avoid conflicts with other packages and by making
+ sure e_os2.h will cover all platform-specific cases together with
+ opensslconf.h.
+ Additionally, it is now possible to define configuration/platform-
+ specific names (called "system identities"). In the C code, these
+ are prefixed with `OPENSSL_SYSNAME_`. e_os2.h will create another
+ macro with the name beginning with `OPENSSL_SYS_`, which is determined
+ from `OPENSSL_SYSNAME_*` or compiler-specific macros depending on
+ what is available.
+
+ *Richard Levitte*
+
+ * New option -set_serial to 'req' and 'x509' this allows the serial
+ number to use to be specified on the command line. Previously self
+ signed certificates were hard coded with serial number 0 and the
+ CA options of 'x509' had to use a serial number in a file which was
+ auto incremented.
+
+ *Steve Henson*
+
+ * New options to 'ca' utility to support V2 CRL entry extensions.
+ Currently CRL reason, invalidity date and hold instruction are
+ supported. Add new CRL extensions to V3 code and some new objects.
+
+ *Steve Henson*
+
+ * New function EVP_CIPHER_CTX_set_padding() this is used to
+ disable standard block padding (aka PKCS#5 padding) in the EVP
+ API, which was previously mandatory. This means that the data is
+ not padded in any way and so the total length much be a multiple
+ of the block size, otherwise an error occurs.
+
+ *Steve Henson*
+
+ * Initial (incomplete) OCSP SSL support.
+
+ *Steve Henson*
+
+ * New function OCSP_parse_url(). This splits up a URL into its host,
+ port and path components: primarily to parse OCSP URLs. New -url
+ option to ocsp utility.
+
+ *Steve Henson*
+
+ * New nonce behavior. The return value of OCSP_check_nonce() now
+ reflects the various checks performed. Applications can decide
+ whether to tolerate certain situations such as an absent nonce
+ in a response when one was present in a request: the ocsp application
+ just prints out a warning. New function OCSP_add1_basic_nonce()
+ this is to allow responders to include a nonce in a response even if
+ the request is nonce-less.
+
+ *Steve Henson*
+
+ * Disable stdin buffering in `load_cert()` (`apps/apps.c`) so that no certs are
+ skipped when using openssl x509 multiple times on a single input file,
+ e.g. `(openssl x509 -out cert1; openssl x509 -out cert2) <certs`.
+
+ *Bodo Moeller*
+
+ * Make ASN1_UTCTIME_set_string() and ASN1_GENERALIZEDTIME_set_string()
+ set string type: to handle setting ASN1_TIME structures. Fix ca
+ utility to correctly initialize revocation date of CRLs.
+
+ *Steve Henson*
+
+ * New option SSL_OP_CIPHER_SERVER_PREFERENCE allows the server to override
+ the clients preferred ciphersuites and rather use its own preferences.
+ Should help to work around M$ SGC (Server Gated Cryptography) bug in
+ Internet Explorer by ensuring unchanged hash method during stepup.
+ (Also replaces the broken/deactivated SSL_OP_NON_EXPORT_FIRST option.)
+
+ *Lutz Jaenicke*
+
+ * Make mkdef.pl recognise all DECLARE_ASN1 macros, change rijndael
+ to aes and add a new 'exist' option to print out symbols that don't
+ appear to exist.
+
+ *Steve Henson*
+
+ * Additional options to ocsp utility to allow flags to be set and
+ additional certificates supplied.
+
+ *Steve Henson*
+
+ * Add the option -VAfile to 'openssl ocsp', so the user can give the
+ OCSP client a number of certificate to only verify the response
+ signature against.
+
+ *Richard Levitte*
+
+ * Update Rijndael code to version 3.0 and change EVP AES ciphers to
+ handle the new API. Currently only ECB, CBC modes supported. Add new
+ AES OIDs.
+
+ Add TLS AES ciphersuites as described in RFC3268, "Advanced
+ Encryption Standard (AES) Ciphersuites for Transport Layer
+ Security (TLS)". (In beta versions of OpenSSL 0.9.7, these were
+ not enabled by default and were not part of the "ALL" ciphersuite
+ alias because they were not yet official; they could be
+ explicitly requested by specifying the "AESdraft" ciphersuite
+ group alias. In the final release of OpenSSL 0.9.7, the group
+ alias is called "AES" and is part of "ALL".)
+
+ *Ben Laurie, Steve Henson, Bodo Moeller*
+
+ * New function OCSP_copy_nonce() to copy nonce value (if present) from
+ request to response.
+
+ *Steve Henson*
+
+ * Functions for OCSP responders. OCSP_request_onereq_count(),
+ OCSP_request_onereq_get0(), OCSP_onereq_get0_id() and OCSP_id_get0_info()
+ extract information from a certificate request. OCSP_response_create()
+ creates a response and optionally adds a basic response structure.
+ OCSP_basic_add1_status() adds a complete single response to a basic
+ response and returns the OCSP_SINGLERESP structure just added (to allow
+ extensions to be included for example). OCSP_basic_add1_cert() adds a
+ certificate to a basic response and OCSP_basic_sign() signs a basic
+ response with various flags. New helper functions ASN1_TIME_check()
+ (checks validity of ASN1_TIME structure) and ASN1_TIME_to_generalizedtime()
+ (converts ASN1_TIME to GeneralizedTime).
+
+ *Steve Henson*
+
+ * Various new functions. EVP_Digest() combines EVP_Digest{Init,Update,Final}()
+ in a single operation. X509_get0_pubkey_bitstr() extracts the public_key
+ structure from a certificate. X509_pubkey_digest() digests the public_key
+ contents: this is used in various key identifiers.
+
+ *Steve Henson*
+
+ * Make sk_sort() tolerate a NULL argument.
+
+ *Steve Henson reported by Massimiliano Pala <madwolf@comune.modena.it>*
+
+ * New OCSP verify flag OCSP_TRUSTOTHER. When set the "other" certificates
+ passed by the function are trusted implicitly. If any of them signed the
+ response then it is assumed to be valid and is not verified.
+
+ *Steve Henson*
+
+ * In PKCS7_set_type() initialise content_type in PKCS7_ENC_CONTENT
+ to data. This was previously part of the PKCS7 ASN1 code. This
+ was causing problems with OpenSSL created PKCS#12 and PKCS#7 structures.
+ *Steve Henson, reported by Kenneth R. Robinette
+ <support@securenetterm.com>*
+
+ * Add CRYPTO_push_info() and CRYPTO_pop_info() calls to new ASN1
+ routines: without these tracing memory leaks is very painful.
+ Fix leaks in PKCS12 and PKCS7 routines.
+
+ *Steve Henson*
+
+ * Make X509_time_adj() cope with the new behaviour of ASN1_TIME_new().
+ Previously it initialised the 'type' argument to V_ASN1_UTCTIME which
+ effectively meant GeneralizedTime would never be used. Now it
+ is initialised to -1 but X509_time_adj() now has to check the value
+ and use ASN1_TIME_set() if the value is not V_ASN1_UTCTIME or
+ V_ASN1_GENERALIZEDTIME, without this it always uses GeneralizedTime.
+ *Steve Henson, reported by Kenneth R. Robinette
+ <support@securenetterm.com>*
+
+ * Fixes to BN_to_ASN1_INTEGER when bn is zero. This would previously
+ result in a zero length in the ASN1_INTEGER structure which was
+ not consistent with the structure when d2i_ASN1_INTEGER() was used
+ and would cause ASN1_INTEGER_cmp() to fail. Enhance s2i_ASN1_INTEGER()
+ to cope with hex and negative integers. Fix bug in i2a_ASN1_INTEGER()
+ where it did not print out a minus for negative ASN1_INTEGER.
+
+ *Steve Henson*
+
+ * Add summary printout to ocsp utility. The various functions which
+ convert status values to strings have been renamed to:
+ OCSP_response_status_str(), OCSP_cert_status_str() and
+ OCSP_crl_reason_str() and are no longer static. New options
+ to verify nonce values and to disable verification. OCSP response
+ printout format cleaned up.
+
+ *Steve Henson*
+
+ * Add additional OCSP certificate checks. These are those specified
+ in RFC2560. This consists of two separate checks: the CA of the
+ certificate being checked must either be the OCSP signer certificate
+ or the issuer of the OCSP signer certificate. In the latter case the
+ OCSP signer certificate must contain the OCSP signing extended key
+ usage. This check is performed by attempting to match the OCSP
+ signer or the OCSP signer CA to the issuerNameHash and issuerKeyHash
+ in the OCSP_CERTID structures of the response.
+
+ *Steve Henson*
+
+ * Initial OCSP certificate verification added to OCSP_basic_verify()
+ and related routines. This uses the standard OpenSSL certificate
+ verify routines to perform initial checks (just CA validity) and
+ to obtain the certificate chain. Then additional checks will be
+ performed on the chain. Currently the root CA is checked to see
+ if it is explicitly trusted for OCSP signing. This is used to set
+ a root CA as a global signing root: that is any certificate that
+ chains to that CA is an acceptable OCSP signing certificate.
+
+ *Steve Henson*
+
+ * New '-extfile ...' option to 'openssl ca' for reading X.509v3
+ extensions from a separate configuration file.
+ As when reading extensions from the main configuration file,
+ the '-extensions ...' option may be used for specifying the
+ section to use.
+
+ *Massimiliano Pala <madwolf@comune.modena.it>*
+
+ * New OCSP utility. Allows OCSP requests to be generated or
+ read. The request can be sent to a responder and the output
+ parsed, outputted or printed in text form. Not complete yet:
+ still needs to check the OCSP response validity.
+
+ *Steve Henson*
+
+ * New subcommands for 'openssl ca':
+ `openssl ca -status <serial>` prints the status of the cert with
+ the given serial number (according to the index file).
+ `openssl ca -updatedb` updates the expiry status of certificates
+ in the index file.
+
+ *Massimiliano Pala <madwolf@comune.modena.it>*
+
+ * New '-newreq-nodes' command option to CA.pl. This is like
+ '-newreq', but calls 'openssl req' with the '-nodes' option
+ so that the resulting key is not encrypted.
+
+ *Damien Miller <djm@mindrot.org>*
+
+ * New configuration for the GNU Hurd.
+
+ *Jonathan Bartlett <johnnyb@wolfram.com> via Richard Levitte*
+
+ * Initial code to implement OCSP basic response verify. This
+ is currently incomplete. Currently just finds the signer's
+ certificate and verifies the signature on the response.
+
+ *Steve Henson*
+
+ * New SSLeay_version code SSLEAY_DIR to determine the compiled-in
+ value of OPENSSLDIR. This is available via the new '-d' option
+ to 'openssl version', and is also included in 'openssl version -a'.
+
+ *Bodo Moeller*
+
+ * Allowing defining memory allocation callbacks that will be given
+ file name and line number information in additional arguments
+ (a `const char*` and an int). The basic functionality remains, as
+ well as the original possibility to just replace malloc(),
+ realloc() and free() by functions that do not know about these
+ additional arguments. To register and find out the current
+ settings for extended allocation functions, the following
+ functions are provided:
+
+ CRYPTO_set_mem_ex_functions
+ CRYPTO_set_locked_mem_ex_functions
+ CRYPTO_get_mem_ex_functions
+ CRYPTO_get_locked_mem_ex_functions
+
+ These work the same way as CRYPTO_set_mem_functions and friends.
+ `CRYPTO_get_[locked_]mem_functions` now writes 0 where such an
+ extended allocation function is enabled.
+ Similarly, `CRYPTO_get_[locked_]mem_ex_functions` writes 0 where
+ a conventional allocation function is enabled.
+
+ *Richard Levitte, Bodo Moeller*
+
+ * Finish off removing the remaining LHASH function pointer casts.
+ There should no longer be any prototype-casting required when using
+ the LHASH abstraction, and any casts that remain are "bugs". See
+ the callback types and macros at the head of lhash.h for details
+ (and "OBJ_cleanup" in crypto/objects/obj_dat.c as an example).
+
+ *Geoff Thorpe*
+
+ * Add automatic query of EGD sockets in RAND_poll() for the unix variant.
+ If /dev/[u]random devices are not available or do not return enough
+ entropy, EGD style sockets (served by EGD or PRNGD) will automatically
+ be queried.
+ The locations /var/run/egd-pool, /dev/egd-pool, /etc/egd-pool, and
+ /etc/entropy will be queried once each in this sequence, querying stops
+ when enough entropy was collected without querying more sockets.
+
+ *Lutz Jaenicke*
+
+ * Change the Unix RAND_poll() variant to be able to poll several
+ random devices, as specified by DEVRANDOM, until a sufficient amount
+ of data has been collected. We spend at most 10 ms on each file
+ (select timeout) and read in non-blocking mode. DEVRANDOM now
+ defaults to the list "/dev/urandom", "/dev/random", "/dev/srandom"
+ (previously it was just the string "/dev/urandom"), so on typical
+ platforms the 10 ms delay will never occur.
+ Also separate out the Unix variant to its own file, rand_unix.c.
+ For VMS, there's a currently-empty rand_vms.c.
+
+ *Richard Levitte*
+
+ * Move OCSP client related routines to ocsp_cl.c. These
+ provide utility functions which an application needing
+ to issue a request to an OCSP responder and analyse the
+ response will typically need: as opposed to those which an
+ OCSP responder itself would need which will be added later.
+
+ OCSP_request_sign() signs an OCSP request with an API similar
+ to PKCS7_sign(). OCSP_response_status() returns status of OCSP
+ response. OCSP_response_get1_basic() extracts basic response
+ from response. OCSP_resp_find_status(): finds and extracts status
+ information from an OCSP_CERTID structure (which will be created
+ when the request structure is built). These are built from lower
+ level functions which work on OCSP_SINGLERESP structures but
+ won't normally be used unless the application wishes to examine
+ extensions in the OCSP response for example.
+
+ Replace nonce routines with a pair of functions.
+ OCSP_request_add1_nonce() adds a nonce value and optionally
+ generates a random value. OCSP_check_nonce() checks the
+ validity of the nonce in an OCSP response.
+
+ *Steve Henson*
+
+ * Change function OCSP_request_add() to OCSP_request_add0_id().
+ This doesn't copy the supplied OCSP_CERTID and avoids the
+ need to free up the newly created id. Change return type
+ to OCSP_ONEREQ to return the internal OCSP_ONEREQ structure.
+ This can then be used to add extensions to the request.
+ Deleted OCSP_request_new(), since most of its functionality
+ is now in OCSP_REQUEST_new() (and the case insensitive name
+ clash) apart from the ability to set the request name which
+ will be added elsewhere.
+
+ *Steve Henson*
+
+ * Update OCSP API. Remove obsolete extensions argument from
+ various functions. Extensions are now handled using the new
+ OCSP extension code. New simple OCSP HTTP function which
+ can be used to send requests and parse the response.
+
+ *Steve Henson*
+
+ * Fix the PKCS#7 (S/MIME) code to work with new ASN1. Two new
+ ASN1_ITEM structures help with sign and verify. PKCS7_ATTR_SIGN
+ uses the special reorder version of SET OF to sort the attributes
+ and reorder them to match the encoded order. This resolves a long
+ standing problem: a verify on a PKCS7 structure just after signing
+ it used to fail because the attribute order did not match the
+ encoded order. PKCS7_ATTR_VERIFY does not reorder the attributes:
+ it uses the received order. This is necessary to tolerate some broken
+ software that does not order SET OF. This is handled by encoding
+ as a SEQUENCE OF but using implicit tagging (with UNIVERSAL class)
+ to produce the required SET OF.
+
+ *Steve Henson*
+
+ * Have mk1mf.pl generate the macros OPENSSL_BUILD_SHLIBCRYPTO and
+ OPENSSL_BUILD_SHLIBSSL and use them appropriately in the header
+ files to get correct declarations of the ASN.1 item variables.
+
+ *Richard Levitte*
+
+ * Rewrite of PKCS#12 code to use new ASN1 functionality. Replace many
+ PKCS#12 macros with real functions. Fix two unrelated ASN1 bugs:
+ asn1_check_tlen() would sometimes attempt to use 'ctx' when it was
+ NULL and ASN1_TYPE was not dereferenced properly in asn1_ex_c2i().
+ New ASN1 macro: DECLARE_ASN1_ITEM() which just declares the relevant
+ ASN1_ITEM and no wrapper functions.
+
+ *Steve Henson*
+
+ * New functions or ASN1_item_d2i_fp() and ASN1_item_d2i_bio(). These
+ replace the old function pointer based I/O routines. Change most of
+ the `*_d2i_bio()` and `*_d2i_fp()` functions to use these.
+
+ *Steve Henson*
+
+ * Enhance mkdef.pl to be more accepting about spacing in C preprocessor
+ lines, recognize more "algorithms" that can be deselected, and make
+ it complain about algorithm deselection that isn't recognised.
+
+ *Richard Levitte*
+
+ * New ASN1 functions to handle dup, sign, verify, digest, pack and
+ unpack operations in terms of ASN1_ITEM. Modify existing wrappers
+ to use new functions. Add NO_ASN1_OLD which can be set to remove
+ some old style ASN1 functions: this can be used to determine if old
+ code will still work when these eventually go away.
+
+ *Steve Henson*
+
+ * New extension functions for OCSP structures, these follow the
+ same conventions as certificates and CRLs.
+
+ *Steve Henson*
+
+ * New function X509V3_add1_i2d(). This automatically encodes and
+ adds an extension. Its behaviour can be customised with various
+ flags to append, replace or delete. Various wrappers added for
+ certificates and CRLs.
+
+ *Steve Henson*
+
+ * Fix to avoid calling the underlying ASN1 print routine when
+ an extension cannot be parsed. Correct a typo in the
+ OCSP_SERVICELOC extension. Tidy up print OCSP format.
+
+ *Steve Henson*
+
+ * Make mkdef.pl parse some of the ASN1 macros and add appropriate
+ entries for variables.
+
+ *Steve Henson*
+
+ * Add functionality to `apps/openssl.c` for detecting locking
+ problems: As the program is single-threaded, all we have
+ to do is register a locking callback using an array for
+ storing which locks are currently held by the program.
+
+ *Bodo Moeller*
+
+ * Use a lock around the call to CRYPTO_get_ex_new_index() in
+ SSL_get_ex_data_X509_STORE_idx(), which is used in
+ ssl_verify_cert_chain() and thus can be called at any time
+ during TLS/SSL handshakes so that thread-safety is essential.
+ Unfortunately, the ex_data design is not at all suited
+ for multi-threaded use, so it probably should be abolished.
+
+ *Bodo Moeller*
+
+ * Added Broadcom "ubsec" ENGINE to OpenSSL.
+
+ *Broadcom, tweaked and integrated by Geoff Thorpe*
+
+ * Move common extension printing code to new function
+ X509V3_print_extensions(). Reorganise OCSP print routines and
+ implement some needed OCSP ASN1 functions. Add OCSP extensions.
+
+ *Steve Henson*
+
+ * New function X509_signature_print() to remove duplication in some
+ print routines.
+
+ *Steve Henson*
+
+ * Add a special meaning when SET OF and SEQUENCE OF flags are both
+ set (this was treated exactly the same as SET OF previously). This
+ is used to reorder the STACK representing the structure to match the
+ encoding. This will be used to get round a problem where a PKCS7
+ structure which was signed could not be verified because the STACK
+ order did not reflect the encoded order.
+
+ *Steve Henson*
+
+ * Reimplement the OCSP ASN1 module using the new code.
+
+ *Steve Henson*
+
+ * Update the X509V3 code to permit the use of an ASN1_ITEM structure
+ for its ASN1 operations. The old style function pointers still exist
+ for now but they will eventually go away.
+
+ *Steve Henson*
+
+ * Merge in replacement ASN1 code from the ASN1 branch. This almost
+ completely replaces the old ASN1 functionality with a table driven
+ encoder and decoder which interprets an ASN1_ITEM structure describing
+ the ASN1 module. Compatibility with the existing ASN1 API (i2d,d2i) is
+ largely maintained. Almost all of the old asn1_mac.h macro based ASN1
+ has also been converted to the new form.
+
+ *Steve Henson*
+
+ * Change BN_mod_exp_recp so that negative moduli are tolerated
+ (the sign is ignored). Similarly, ignore the sign in BN_MONT_CTX_set
+ so that BN_mod_exp_mont and BN_mod_exp_mont_word work
+ for negative moduli.
+
+ *Bodo Moeller*
+
+ * Fix BN_uadd and BN_usub: Always return non-negative results instead
+ of not touching the result's sign bit.
+
+ *Bodo Moeller*
+
+ * BN_div bugfix: If the result is 0, the sign (res->neg) must not be
+ set.
+
+ *Bodo Moeller*
+
+ * Changed the LHASH code to use prototypes for callbacks, and created
+ macros to declare and implement thin (optionally static) functions
+ that provide type-safety and avoid function pointer casting for the
+ type-specific callbacks.
+
+ *Geoff Thorpe*
+
+ * Added Kerberos Cipher Suites to be used with TLS, as written in
+ RFC 2712.
+ *Veers Staats <staatsvr@asc.hpc.mil>,
+ Jeffrey Altman <jaltman@columbia.edu>, via Richard Levitte*
+
+ * Reformat the FAQ so the different questions and answers can be divided
+ in sections depending on the subject.
+
+ *Richard Levitte*
+
+ * Have the zlib compression code load ZLIB.DLL dynamically under
+ Windows.
+
+ *Richard Levitte*
+
+ * New function BN_mod_sqrt for computing square roots modulo a prime
+ (using the probabilistic Tonelli-Shanks algorithm unless
+ p == 3 (mod 4) or p == 5 (mod 8), which are cases that can
+ be handled deterministically).
+
+ *Lenka Fibikova <fibikova@exp-math.uni-essen.de>, Bodo Moeller*
+
+ * Make BN_mod_inverse faster by explicitly handling small quotients
+ in the Euclid loop. (Speed gain about 20% for small moduli [256 or
+ 512 bits], about 30% for larger ones [1024 or 2048 bits].)
+
+ *Bodo Moeller*
+
+ * New function BN_kronecker.
+
+ *Bodo Moeller*
+
+ * Fix BN_gcd so that it works on negative inputs; the result is
+ positive unless both parameters are zero.
+ Previously something reasonably close to an infinite loop was
+ possible because numbers could be growing instead of shrinking
+ in the implementation of Euclid's algorithm.
+
+ *Bodo Moeller*
+
+ * Fix BN_is_word() and BN_is_one() macros to take into account the
+ sign of the number in question.
+
+ Fix BN_is_word(a,w) to work correctly for w == 0.
+
+ The old BN_is_word(a,w) macro is now called BN_abs_is_word(a,w)
+ because its test if the absolute value of 'a' equals 'w'.
+ Note that BN_abs_is_word does *not* handle w == 0 reliably;
+ it exists mostly for use in the implementations of BN_is_zero(),
+ BN_is_one(), and BN_is_word().
+
+ *Bodo Moeller*
+
+ * New function BN_swap.
+
+ *Bodo Moeller*
+
+ * Use BN_nnmod instead of BN_mod in crypto/bn/bn_exp.c so that
+ the exponentiation functions are more likely to produce reasonable
+ results on negative inputs.
+
+ *Bodo Moeller*
+
+ * Change BN_mod_mul so that the result is always non-negative.
+ Previously, it could be negative if one of the factors was negative;
+ I don't think anyone really wanted that behaviour.
+
+ *Bodo Moeller*
+
+ * Move `BN_mod_...` functions into new file `crypto/bn/bn_mod.c`
+ (except for exponentiation, which stays in `crypto/bn/bn_exp.c`,
+ and `BN_mod_mul_reciprocal`, which stays in `crypto/bn/bn_recp.c`)
+ and add new functions:
+
+ BN_nnmod
+ BN_mod_sqr
+ BN_mod_add
+ BN_mod_add_quick
+ BN_mod_sub
+ BN_mod_sub_quick
+ BN_mod_lshift1
+ BN_mod_lshift1_quick
+ BN_mod_lshift
+ BN_mod_lshift_quick
+
+ These functions always generate non-negative results.
+
+ `BN_nnmod` otherwise is `like BN_mod` (if `BN_mod` computes a remainder `r`
+ such that `|m| < r < 0`, `BN_nnmod` will output `rem + |m|` instead).
+
+ `BN_mod_XXX_quick(r, a, [b,] m)` generates the same result as
+ `BN_mod_XXX(r, a, [b,] m, ctx)`, but requires that `a` [and `b`]
+ be reduced modulo `m`.
+
+ *Lenka Fibikova <fibikova@exp-math.uni-essen.de>, Bodo Moeller*
+
+<!--
+ The following entry accidentally appeared in the CHANGES file
+ distributed with OpenSSL 0.9.7. The modifications described in
+ it do *not* apply to OpenSSL 0.9.7.
+
+ * Remove a few calls to bn_wexpand() in BN_sqr() (the one in there
+ was actually never needed) and in BN_mul(). The removal in BN_mul()
+ required a small change in bn_mul_part_recursive() and the addition
+ of the functions bn_cmp_part_words(), bn_sub_part_words() and
+ bn_add_part_words(), which do the same thing as bn_cmp_words(),
+ bn_sub_words() and bn_add_words() except they take arrays with
+ differing sizes.
+
+ *Richard Levitte*
+-->
+
+ * In 'openssl passwd', verify passwords read from the terminal
+ unless the '-salt' option is used (which usually means that
+ verification would just waste user's time since the resulting
+ hash is going to be compared with some given password hash)
+ or the new '-noverify' option is used.
+
+ This is an incompatible change, but it does not affect
+ non-interactive use of 'openssl passwd' (passwords on the command
+ line, '-stdin' option, '-in ...' option) and thus should not
+ cause any problems.
+
+ *Bodo Moeller*
+
+ * Remove all references to RSAref, since there's no more need for it.
+
+ *Richard Levitte*
+
+ * Make DSO load along a path given through an environment variable
+ (SHLIB_PATH) with shl_load().
+
+ *Richard Levitte*
+
+ * Constify the ENGINE code as a result of BIGNUM constification.
+ Also constify the RSA code and most things related to it. In a
+ few places, most notable in the depth of the ASN.1 code, ugly
+ casts back to non-const were required (to be solved at a later
+ time)
+
+ *Richard Levitte*
+
+ * Make it so the openssl application has all engines loaded by default.
+
+ *Richard Levitte*
+
+ * Constify the BIGNUM routines a little more.
+
+ *Richard Levitte*
+
+ * Add the following functions:
+
+ ENGINE_load_cswift()
+ ENGINE_load_chil()
+ ENGINE_load_atalla()
+ ENGINE_load_nuron()
+ ENGINE_load_builtin_engines()
+
+ That way, an application can itself choose if external engines that
+ are built-in in OpenSSL shall ever be used or not. The benefit is
+ that applications won't have to be linked with libdl or other dso
+ libraries unless it's really needed.
+
+ Changed 'openssl engine' to load all engines on demand.
+ Changed the engine header files to avoid the duplication of some
+ declarations (they differed!).
+
+ *Richard Levitte*
+
+ * 'openssl engine' can now list capabilities.
+
+ *Richard Levitte*
+
+ * Better error reporting in 'openssl engine'.
+
+ *Richard Levitte*
+
+ * Never call load_dh_param(NULL) in s_server.
+
+ *Bodo Moeller*
+
+ * Add engine application. It can currently list engines by name and
+ identity, and test if they are actually available.
+
+ *Richard Levitte*
+
+ * Improve RPM specification file by forcing symbolic linking and making
+ sure the installed documentation is also owned by root.root.
+
+ *Damien Miller <djm@mindrot.org>*
+
+ * Give the OpenSSL applications more possibilities to make use of
+ keys (public as well as private) handled by engines.
+
+ *Richard Levitte*
+
+ * Add OCSP code that comes from CertCo.
+
+ *Richard Levitte*
+
+ * Add VMS support for the Rijndael code.
+
+ *Richard Levitte*
+
+ * Added untested support for Nuron crypto accelerator.
+
+ *Ben Laurie*
+
+ * Add support for external cryptographic devices. This code was
+ previously distributed separately as the "engine" branch.
+
+ *Geoff Thorpe, Richard Levitte*
+
+ * Rework the filename-translation in the DSO code. It is now possible to
+ have far greater control over how a "name" is turned into a filename
+ depending on the operating environment and any oddities about the
+ different shared library filenames on each system.
+
+ *Geoff Thorpe*
+
+ * Support threads on FreeBSD-elf in Configure.
+
+ *Richard Levitte*
+
+ * Fix for SHA1 assembly problem with MASM: it produces
+ warnings about corrupt line number information when assembling
+ with debugging information. This is caused by the overlapping
+ of two sections.
+
+ *Bernd Matthes <mainbug@celocom.de>, Steve Henson*
+
+ * NCONF changes.
+ NCONF_get_number() has no error checking at all. As a replacement,
+ NCONF_get_number_e() is defined (`_e` for "error checking") and is
+ promoted strongly. The old NCONF_get_number is kept around for
+ binary backward compatibility.
+ Make it possible for methods to load from something other than a BIO,
+ by providing a function pointer that is given a name instead of a BIO.
+ For example, this could be used to load configuration data from an
+ LDAP server.
+
+ *Richard Levitte*
+
+ * Fix for non blocking accept BIOs. Added new I/O special reason
+ BIO_RR_ACCEPT to cover this case. Previously use of accept BIOs
+ with non blocking I/O was not possible because no retry code was
+ implemented. Also added new SSL code SSL_WANT_ACCEPT to cover
+ this case.
+
+ *Steve Henson*
+
+ * Added the beginnings of Rijndael support.
+
+ *Ben Laurie*
+
+ * Fix for bug in DirectoryString mask setting. Add support for
+ X509_NAME_print_ex() in 'req' and X509_print_ex() function
+ to allow certificate printing to more controllable, additional
+ 'certopt' option to 'x509' to allow new printing options to be
+ set.
+
+ *Steve Henson*
+
+ * Clean old EAY MD5 hack from e_os.h.
+
+ *Richard Levitte*
+
+### Changes between 0.9.6l and 0.9.6m [17 Mar 2004]
+
+ * Fix null-pointer assignment in do_change_cipher_spec() revealed
+ by using the Codenomicon TLS Test Tool ([CVE-2004-0079])
+
+ *Joe Orton, Steve Henson*
+
+### Changes between 0.9.6k and 0.9.6l [04 Nov 2003]
+
+ * Fix additional bug revealed by the NISCC test suite:
+
+ Stop bug triggering large recursion when presented with
+ certain ASN.1 tags ([CVE-2003-0851])
+
+ *Steve Henson*
+
+### Changes between 0.9.6j and 0.9.6k [30 Sep 2003]
+
+ * Fix various bugs revealed by running the NISCC test suite:
+
+ Stop out of bounds reads in the ASN1 code when presented with
+ invalid tags (CVE-2003-0543 and CVE-2003-0544).
+
+ If verify callback ignores invalid public key errors don't try to check
+ certificate signature with the NULL public key.
+
+ *Steve Henson*
+
+ * In ssl3_accept() (ssl/s3_srvr.c) only accept a client certificate
+ if the server requested one: as stated in TLS 1.0 and SSL 3.0
+ specifications.
+
+ *Steve Henson*
+
+ * In ssl3_get_client_hello() (ssl/s3_srvr.c), tolerate additional
+ extra data after the compression methods not only for TLS 1.0
+ but also for SSL 3.0 (as required by the specification).
+
+ *Bodo Moeller; problem pointed out by Matthias Loepfe*
+
+ * Change X509_certificate_type() to mark the key as exported/exportable
+ when it's 512 *bits* long, not 512 bytes.
+
+ *Richard Levitte*
+
+### Changes between 0.9.6i and 0.9.6j [10 Apr 2003]
+
+ * Countermeasure against the Klima-Pokorny-Rosa extension of
+ Bleichbacher's attack on PKCS #1 v1.5 padding: treat
+ a protocol version number mismatch like a decryption error
+ in ssl3_get_client_key_exchange (ssl/s3_srvr.c).
+
+ *Bodo Moeller*
+
+ * Turn on RSA blinding by default in the default implementation
+ to avoid a timing attack. Applications that don't want it can call
+ RSA_blinding_off() or use the new flag RSA_FLAG_NO_BLINDING.
+ They would be ill-advised to do so in most cases.
+
+ *Ben Laurie, Steve Henson, Geoff Thorpe, Bodo Moeller*
+
+ * Change RSA blinding code so that it works when the PRNG is not
+ seeded (in this case, the secret RSA exponent is abused as
+ an unpredictable seed -- if it is not unpredictable, there
+ is no point in blinding anyway). Make RSA blinding thread-safe
+ by remembering the creator's thread ID in rsa->blinding and
+ having all other threads use local one-time blinding factors
+ (this requires more computation than sharing rsa->blinding, but
+ avoids excessive locking; and if an RSA object is not shared
+ between threads, blinding will still be very fast).
+
+ *Bodo Moeller*
+
+### Changes between 0.9.6h and 0.9.6i [19 Feb 2003]
+
+ * In ssl3_get_record (ssl/s3_pkt.c), minimize information leaked
+ via timing by performing a MAC computation even if incorrect
+ block cipher padding has been found. This is a countermeasure
+ against active attacks where the attacker has to distinguish
+ between bad padding and a MAC verification error. ([CVE-2003-0078])
+
+ *Bodo Moeller; problem pointed out by Brice Canvel (EPFL),
+ Alain Hiltgen (UBS), Serge Vaudenay (EPFL), and
+ Martin Vuagnoux (EPFL, Ilion)*
+
+### Changes between 0.9.6g and 0.9.6h [5 Dec 2002]
+
+ * New function OPENSSL_cleanse(), which is used to cleanse a section of
+ memory from its contents. This is done with a counter that will
+ place alternating values in each byte. This can be used to solve
+ two issues: 1) the removal of calls to memset() by highly optimizing
+ compilers, and 2) cleansing with other values than 0, since those can
+ be read through on certain media, for example a swap space on disk.
+
+ *Geoff Thorpe*
+
+ * Bugfix: client side session caching did not work with external caching,
+ because the session->cipher setting was not restored when reloading
+ from the external cache. This problem was masked, when
+ SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG (part of SSL_OP_ALL) was set.
+ (Found by Steve Haslam <steve@araqnid.ddts.net>.)
+
+ *Lutz Jaenicke*
+
+ * Fix client_certificate (ssl/s2_clnt.c): The permissible total
+ length of the REQUEST-CERTIFICATE message is 18 .. 34, not 17 .. 33.
+
+ *Zeev Lieber <zeev-l@yahoo.com>*
+
+ * Undo an undocumented change introduced in 0.9.6e which caused
+ repeated calls to OpenSSL_add_all_ciphers() and
+ OpenSSL_add_all_digests() to be ignored, even after calling
+ EVP_cleanup().
+
+ *Richard Levitte*
+
+ * Change the default configuration reader to deal with last line not
+ being properly terminated.
+
+ *Richard Levitte*
+
+ * Change X509_NAME_cmp() so it applies the special rules on handling
+ DN values that are of type PrintableString, as well as RDNs of type
+ emailAddress where the value has the type ia5String.
+
+ *stefank@valicert.com via Richard Levitte*
+
+ * Add a SSL_SESS_CACHE_NO_INTERNAL_STORE flag to take over half
+ the job SSL_SESS_CACHE_NO_INTERNAL_LOOKUP was inconsistently
+ doing, define a new flag (SSL_SESS_CACHE_NO_INTERNAL) to be
+ the bitwise-OR of the two for use by the majority of applications
+ wanting this behaviour, and update the docs. The documented
+ behaviour and actual behaviour were inconsistent and had been
+ changing anyway, so this is more a bug-fix than a behavioural
+ change.
+
+ *Geoff Thorpe, diagnosed by Nadav Har'El*
+
+ * Don't impose a 16-byte length minimum on session IDs in ssl/s3_clnt.c
+ (the SSL 3.0 and TLS 1.0 specifications allow any length up to 32 bytes).
+
+ *Bodo Moeller*
+
+ * Fix initialization code race conditions in
+ SSLv23_method(), SSLv23_client_method(), SSLv23_server_method(),
+ SSLv2_method(), SSLv2_client_method(), SSLv2_server_method(),
+ SSLv3_method(), SSLv3_client_method(), SSLv3_server_method(),
+ TLSv1_method(), TLSv1_client_method(), TLSv1_server_method(),
+ ssl2_get_cipher_by_char(),
+ ssl3_get_cipher_by_char().
+
+ *Patrick McCormick <patrick@tellme.com>, Bodo Moeller*
+
+ * Reorder cleanup sequence in SSL_CTX_free(): only remove the ex_data after
+ the cached sessions are flushed, as the remove_cb() might use ex_data
+ contents. Bug found by Sam Varshavchik <mrsam@courier-mta.com>
+ (see [openssl.org #212]).
+
+ *Geoff Thorpe, Lutz Jaenicke*
+
+ * Fix typo in OBJ_txt2obj which incorrectly passed the content
+ length, instead of the encoding length to d2i_ASN1_OBJECT.
+
+ *Steve Henson*
+
+### Changes between 0.9.6f and 0.9.6g [9 Aug 2002]
+
+ * [In 0.9.6g-engine release:]
+ Fix crypto/engine/vendor_defns/cswift.h for WIN32 (use `_stdcall`).
+
+ *Lynn Gazis <lgazis@rainbow.com>*
+
+### Changes between 0.9.6e and 0.9.6f [8 Aug 2002]
+
+ * Fix ASN1 checks. Check for overflow by comparing with LONG_MAX
+ and get fix the header length calculation.
+ *Florian Weimer <Weimer@CERT.Uni-Stuttgart.DE>,
+ Alon Kantor <alonk@checkpoint.com> (and others), Steve Henson*
+
+ * Use proper error handling instead of 'assertions' in buffer
+ overflow checks added in 0.9.6e. This prevents DoS (the
+ assertions could call abort()).
+
+ *Arne Ansper <arne@ats.cyber.ee>, Bodo Moeller*
+
+### Changes between 0.9.6d and 0.9.6e [30 Jul 2002]
+
+ * Add various sanity checks to asn1_get_length() to reject
+ the ASN1 length bytes if they exceed sizeof(long), will appear
+ negative or the content length exceeds the length of the
+ supplied buffer.
+
+ *Steve Henson, Adi Stav <stav@mercury.co.il>, James Yonan <jim@ntlp.com>*
+
+ * Fix cipher selection routines: ciphers without encryption had no flags
+ for the cipher strength set and where therefore not handled correctly
+ by the selection routines (PR #130).
+
+ *Lutz Jaenicke*
+
+ * Fix EVP_dsa_sha macro.
+
+ *Nils Larsch*
+
+ * New option
+ SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
+ for disabling the SSL 3.0/TLS 1.0 CBC vulnerability countermeasure
+ that was added in OpenSSL 0.9.6d.
+
+ As the countermeasure turned out to be incompatible with some
+ broken SSL implementations, the new option is part of SSL_OP_ALL.
+ SSL_OP_ALL is usually employed when compatibility with weird SSL
+ implementations is desired (e.g. '-bugs' option to 's_client' and
+ 's_server'), so the new option is automatically set in many
+ applications.
+
+ *Bodo Moeller*
+
+ * Changes in security patch:
+
+ Changes marked "(CHATS)" were sponsored by the Defense Advanced
+ Research Projects Agency (DARPA) and Air Force Research Laboratory,
+ Air Force Materiel Command, USAF, under agreement number
+ F30602-01-2-0537.
+
+ * Add various sanity checks to asn1_get_length() to reject
+ the ASN1 length bytes if they exceed sizeof(long), will appear
+ negative or the content length exceeds the length of the
+ supplied buffer. ([CVE-2002-0659])
+
+ *Steve Henson, Adi Stav <stav@mercury.co.il>, James Yonan <jim@ntlp.com>*
+
+ * Assertions for various potential buffer overflows, not known to
+ happen in practice.
+
+ *Ben Laurie (CHATS)*
+
+ * Various temporary buffers to hold ASCII versions of integers were
+ too small for 64 bit platforms. ([CVE-2002-0655])
+ *Matthew Byng-Maddick <mbm@aldigital.co.uk> and Ben Laurie (CHATS)>*
+
+ * Remote buffer overflow in SSL3 protocol - an attacker could
+ supply an oversized session ID to a client. ([CVE-2002-0656])
+
+ *Ben Laurie (CHATS)*
+
+ * Remote buffer overflow in SSL2 protocol - an attacker could
+ supply an oversized client master key. ([CVE-2002-0656])
+
+ *Ben Laurie (CHATS)*
+
+### Changes between 0.9.6c and 0.9.6d [9 May 2002]
+
+ * Fix crypto/asn1/a_sign.c so that 'parameters' is omitted (not
+ encoded as NULL) with id-dsa-with-sha1.
+
+ *Nils Larsch <nla@trustcenter.de>; problem pointed out by Bodo Moeller*
+
+ * Check various `X509_...()` return values in `apps/req.c`.
+
+ *Nils Larsch <nla@trustcenter.de>*
+
+ * Fix BASE64 decode (EVP_DecodeUpdate) for data with CR/LF ended lines:
+ an end-of-file condition would erroneously be flagged, when the CRLF
+ was just at the end of a processed block. The bug was discovered when
+ processing data through a buffering memory BIO handing the data to a
+ BASE64-decoding BIO. Bug fund and patch submitted by Pavel Tsekov
+ <ptsekov@syntrex.com> and Nedelcho Stanev.
+
+ *Lutz Jaenicke*
+
+ * Implement a countermeasure against a vulnerability recently found
+ in CBC ciphersuites in SSL 3.0/TLS 1.0: Send an empty fragment
+ before application data chunks to avoid the use of known IVs
+ with data potentially chosen by the attacker.
+
+ *Bodo Moeller*
+
+ * Fix length checks in ssl3_get_client_hello().
+
+ *Bodo Moeller*
+
+ * TLS/SSL library bugfix: use s->s3->in_read_app_data differently
+ to prevent ssl3_read_internal() from incorrectly assuming that
+ ssl3_read_bytes() found application data while handshake
+ processing was enabled when in fact s->s3->in_read_app_data was
+ merely automatically cleared during the initial handshake.
+
+ *Bodo Moeller; problem pointed out by Arne Ansper <arne@ats.cyber.ee>*
+
+ * Fix object definitions for Private and Enterprise: they were not
+ recognized in their shortname (=lowercase) representation. Extend
+ obj_dat.pl to issue an error when using undefined keywords instead
+ of silently ignoring the problem (Svenning Sorensen
+ <sss@sss.dnsalias.net>).
+
+ *Lutz Jaenicke*
+
+ * Fix DH_generate_parameters() so that it works for 'non-standard'
+ generators, i.e. generators other than 2 and 5. (Previously, the
+ code did not properly initialise the 'add' and 'rem' values to
+ BN_generate_prime().)
+
+ In the new general case, we do not insist that 'generator' is
+ actually a primitive root: This requirement is rather pointless;
+ a generator of the order-q subgroup is just as good, if not
+ better.
+
+ *Bodo Moeller*
+
+ * Map new X509 verification errors to alerts. Discovered and submitted by
+ Tom Wu <tom@arcot.com>.
+
+ *Lutz Jaenicke*
+
+ * Fix ssl3_pending() (ssl/s3_lib.c) to prevent SSL_pending() from
+ returning non-zero before the data has been completely received
+ when using non-blocking I/O.
+
+ *Bodo Moeller; problem pointed out by John Hughes*
+
+ * Some of the ciphers missed the strength entry (SSL_LOW etc).
+
+ *Ben Laurie, Lutz Jaenicke*
+
+ * Fix bug in SSL_clear(): bad sessions were not removed (found by
+ Yoram Zahavi <YoramZ@gilian.com>).
+
+ *Lutz Jaenicke*
+
+ * Add information about CygWin 1.3 and on, and preserve proper
+ configuration for the versions before that.
+
+ *Corinna Vinschen <vinschen@redhat.com> and Richard Levitte*
+
+ * Make removal from session cache (SSL_CTX_remove_session()) more robust:
+ check whether we deal with a copy of a session and do not delete from
+ the cache in this case. Problem reported by "Izhar Shoshani Levi"
+ <izhar@checkpoint.com>.
+
+ *Lutz Jaenicke*
+
+ * Do not store session data into the internal session cache, if it
+ is never intended to be looked up (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP
+ flag is set). Proposed by Aslam <aslam@funk.com>.
+
+ *Lutz Jaenicke*
+
+ * Have ASN1_BIT_STRING_set_bit() really clear a bit when the requested
+ value is 0.
+
+ *Richard Levitte*
+
+ * [In 0.9.6d-engine release:]
+ Fix a crashbug and a logic bug in hwcrhk_load_pubkey().
+
+ *Toomas Kiisk <vix@cyber.ee> via Richard Levitte*
+
+ * Add the configuration target linux-s390x.
+
+ *Neale Ferguson <Neale.Ferguson@SoftwareAG-USA.com> via Richard Levitte*
+
+ * The earlier bugfix for the SSL3_ST_SW_HELLO_REQ_C case of
+ ssl3_accept (ssl/s3_srvr.c) incorrectly used a local flag
+ variable as an indication that a ClientHello message has been
+ received. As the flag value will be lost between multiple
+ invocations of ssl3_accept when using non-blocking I/O, the
+ function may not be aware that a handshake has actually taken
+ place, thus preventing a new session from being added to the
+ session cache.
+
+ To avoid this problem, we now set s->new_session to 2 instead of
+ using a local variable.
+
+ *Lutz Jaenicke, Bodo Moeller*
+
+ * Bugfix: Return -1 from ssl3_get_server_done (ssl3/s3_clnt.c)
+ if the SSL_R_LENGTH_MISMATCH error is detected.
+
+ *Geoff Thorpe, Bodo Moeller*
+
+ * New 'shared_ldflag' column in Configure platform table.
+
+ *Richard Levitte*
+
+ * Fix EVP_CIPHER_mode macro.
+
+ *"Dan S. Camper" <dan@bti.net>*
+
+ * Fix ssl3_read_bytes (ssl/s3_pkt.c): To ignore messages of unknown
+ type, we must throw them away by setting rr->length to 0.
+
+ *D P Chang <dpc@qualys.com>*
+
+### Changes between 0.9.6b and 0.9.6c [21 dec 2001]
+
+ * Fix BN_rand_range bug pointed out by Dominikus Scherkl
+ <Dominikus.Scherkl@biodata.com>. (The previous implementation
+ worked incorrectly for those cases where range = `10..._2` and
+ `3*range` is two bits longer than range.)
+
+ *Bodo Moeller*
+
+ * Only add signing time to PKCS7 structures if it is not already
+ present.
+
+ *Steve Henson*
+
+ * Fix crypto/objects/objects.h: "ld-ce" should be "id-ce",
+ OBJ_ld_ce should be OBJ_id_ce.
+ Also some ip-pda OIDs in crypto/objects/objects.txt were
+ incorrect (cf. RFC 3039).
+
+ *Matt Cooper, Frederic Giudicelli, Bodo Moeller*
+
+ * Release CRYPTO_LOCK_DYNLOCK when CRYPTO_destroy_dynlockid()
+ returns early because it has nothing to do.
+
+ *Andy Schneider <andy.schneider@bjss.co.uk>*
+
+ * [In 0.9.6c-engine release:]
+ Fix mutex callback return values in crypto/engine/hw_ncipher.c.
+
+ *Andy Schneider <andy.schneider@bjss.co.uk>*
+
+ * [In 0.9.6c-engine release:]
+ Add support for Cryptographic Appliance's keyserver technology.
+ (Use engine 'keyclient')
+
+ *Cryptographic Appliances and Geoff Thorpe*
+
+ * Add a configuration entry for OS/390 Unix. The C compiler 'c89'
+ is called via tools/c89.sh because arguments have to be
+ rearranged (all '-L' options must appear before the first object
+ modules).
+
+ *Richard Shapiro <rshapiro@abinitio.com>*
+
+ * [In 0.9.6c-engine release:]
+ Add support for Broadcom crypto accelerator cards, backported
+ from 0.9.7.
+
+ *Broadcom, Nalin Dahyabhai <nalin@redhat.com>, Mark Cox*
+
+ * [In 0.9.6c-engine release:]
+ Add support for SureWare crypto accelerator cards from
+ Baltimore Technologies. (Use engine 'sureware')
+
+ *Baltimore Technologies and Mark Cox*
+
+ * [In 0.9.6c-engine release:]
+ Add support for crypto accelerator cards from Accelerated
+ Encryption Processing, www.aep.ie. (Use engine 'aep')
+
+ *AEP Inc. and Mark Cox*
+
+ * Add a configuration entry for gcc on UnixWare.
+
+ *Gary Benson <gbenson@redhat.com>*
+
+ * Change ssl/s2_clnt.c and ssl/s2_srvr.c so that received handshake
+ messages are stored in a single piece (fixed-length part and
+ variable-length part combined) and fix various bugs found on the way.
+
+ *Bodo Moeller*
+
+ * Disable caching in BIO_gethostbyname(), directly use gethostbyname()
+ instead. BIO_gethostbyname() does not know what timeouts are
+ appropriate, so entries would stay in cache even when they have
+ become invalid.
+ *Bodo Moeller; problem pointed out by Rich Salz <rsalz@zolera.com>*
+
+ * Change ssl23_get_client_hello (ssl/s23_srvr.c) behaviour when
+ faced with a pathologically small ClientHello fragment that does
+ not contain client_version: Instead of aborting with an error,
+ simply choose the highest available protocol version (i.e.,
+ TLS 1.0 unless it is disabled). In practice, ClientHello
+ messages are never sent like this, but this change gives us
+ strictly correct behaviour at least for TLS.
+
+ *Bodo Moeller*
+
+ * Fix SSL handshake functions and SSL_clear() such that SSL_clear()
+ never resets s->method to s->ctx->method when called from within
+ one of the SSL handshake functions.
+
+ *Bodo Moeller; problem pointed out by Niko Baric*
+
+ * In ssl3_get_client_hello (ssl/s3_srvr.c), generate a fatal alert
+ (sent using the client's version number) if client_version is
+ smaller than the protocol version in use. Also change
+ ssl23_get_client_hello (ssl/s23_srvr.c) to select TLS 1.0 if
+ the client demanded SSL 3.0 but only TLS 1.0 is enabled; then
+ the client will at least see that alert.
+
+ *Bodo Moeller*
+
+ * Fix ssl3_get_message (ssl/s3_both.c) to handle message fragmentation
+ correctly.
+
+ *Bodo Moeller*
+
+ * Avoid infinite loop in ssl3_get_message (ssl/s3_both.c) if a
+ client receives HelloRequest while in a handshake.
+
+ *Bodo Moeller; bug noticed by Andy Schneider <andy.schneider@bjss.co.uk>*
+
+ * Bugfix in ssl3_accept (ssl/s3_srvr.c): Case SSL3_ST_SW_HELLO_REQ_C
+ should end in 'break', not 'goto end' which circumvents various
+ cleanups done in state SSL_ST_OK. But session related stuff
+ must be disabled for SSL_ST_OK in the case that we just sent a
+ HelloRequest.
+
+ Also avoid some overhead by not calling ssl_init_wbio_buffer()
+ before just sending a HelloRequest.
+
+ *Bodo Moeller, Eric Rescorla <ekr@rtfm.com>*
+
+ * Fix ssl/s3_enc.c, ssl/t1_enc.c and ssl/s3_pkt.c so that we don't
+ reveal whether illegal block cipher padding was found or a MAC
+ verification error occurred. (Neither SSLerr() codes nor alerts
+ are directly visible to potential attackers, but the information
+ may leak via logfiles.)
+
+ Similar changes are not required for the SSL 2.0 implementation
+ because the number of padding bytes is sent in clear for SSL 2.0,
+ and the extra bytes are just ignored. However ssl/s2_pkt.c
+ failed to verify that the purported number of padding bytes is in
+ the legal range.
+
+ *Bodo Moeller*
+
+ * Add OpenUNIX-8 support including shared libraries
+ (Boyd Lynn Gerber <gerberb@zenez.com>).
+
+ *Lutz Jaenicke*
+
+ * Improve RSA_padding_check_PKCS1_OAEP() check again to avoid
+ 'wristwatch attack' using huge encoding parameters (cf.
+ James H. Manger's CRYPTO 2001 paper). Note that the
+ RSA_PKCS1_OAEP_PADDING case of RSA_private_decrypt() does not use
+ encoding parameters and hence was not vulnerable.
+
+ *Bodo Moeller*
+
+ * BN_sqr() bug fix.
+
+ *Ulf Möller, reported by Jim Ellis <jim.ellis@cavium.com>*
+
+ * Rabin-Miller test analyses assume uniformly distributed witnesses,
+ so use BN_pseudo_rand_range() instead of using BN_pseudo_rand()
+ followed by modular reduction.
+
+ *Bodo Moeller; pointed out by Adam Young <AYoung1@NCSUS.JNJ.COM>*
+
+ * Add BN_pseudo_rand_range() with obvious functionality: BN_rand_range()
+ equivalent based on BN_pseudo_rand() instead of BN_rand().
+
+ *Bodo Moeller*
+
+ * s3_srvr.c: allow sending of large client certificate lists (> 16 kB).
+ This function was broken, as the check for a new client hello message
+ to handle SGC did not allow these large messages.
+ (Tracked down by "Douglas E. Engert" <deengert@anl.gov>.)
+
+ *Lutz Jaenicke*
+
+ * Add alert descriptions for TLSv1 to `SSL_alert_desc_string[_long]()`.
+
+ *Lutz Jaenicke*
+
+ * Fix buggy behaviour of BIO_get_num_renegotiates() and BIO_ctrl()
+ for BIO_C_GET_WRITE_BUF_SIZE ("Stephen Hinton" <shinton@netopia.com>).
+
+ *Lutz Jaenicke*
+
+ * Rework the configuration and shared library support for Tru64 Unix.
+ The configuration part makes use of modern compiler features and
+ still retains old compiler behavior for those that run older versions
+ of the OS. The shared library support part includes a variant that
+ uses the RPATH feature, and is available through the special
+ configuration target "alpha-cc-rpath", which will never be selected
+ automatically.
+
+ *Tim Mooney <mooney@dogbert.cc.ndsu.NoDak.edu> via Richard Levitte*
+
+ * In ssl3_get_key_exchange (ssl/s3_clnt.c), call ssl3_get_message()
+ with the same message size as in ssl3_get_certificate_request().
+ Otherwise, if no ServerKeyExchange message occurs, CertificateRequest
+ messages might inadvertently be reject as too long.
+
+ *Petr Lampa <lampa@fee.vutbr.cz>*
+
+ * Enhanced support for IA-64 Unix platforms (well, Linux and HP-UX).
+
+ *Andy Polyakov*
+
+ * Modified SSL library such that the verify_callback that has been set
+ specifically for an SSL object with SSL_set_verify() is actually being
+ used. Before the change, a verify_callback set with this function was
+ ignored and the verify_callback() set in the SSL_CTX at the time of
+ the call was used. New function X509_STORE_CTX_set_verify_cb() introduced
+ to allow the necessary settings.
+
+ *Lutz Jaenicke*
+
+ * Initialize static variable in crypto/dsa/dsa_lib.c and crypto/dh/dh_lib.c
+ explicitly to NULL, as at least on Solaris 8 this seems not always to be
+ done automatically (in contradiction to the requirements of the C
+ standard). This made problems when used from OpenSSH.
+
+ *Lutz Jaenicke*
+
+ * In OpenSSL 0.9.6a and 0.9.6b, crypto/dh/dh_key.c ignored
+ dh->length and always used
+
+ BN_rand_range(priv_key, dh->p).
+
+ BN_rand_range() is not necessary for Diffie-Hellman, and this
+ specific range makes Diffie-Hellman unnecessarily inefficient if
+ dh->length (recommended exponent length) is much smaller than the
+ length of dh->p. We could use BN_rand_range() if the order of
+ the subgroup was stored in the DH structure, but we only have
+ dh->length.
+
+ So switch back to
+
+ BN_rand(priv_key, l, ...)
+
+ where 'l' is dh->length if this is defined, or BN_num_bits(dh->p)-1
+ otherwise.
+
+ *Bodo Moeller*
+
+ * In
+
+ RSA_eay_public_encrypt
+ RSA_eay_private_decrypt
+ RSA_eay_private_encrypt (signing)
+ RSA_eay_public_decrypt (signature verification)
+
+ (default implementations for RSA_public_encrypt,
+ RSA_private_decrypt, RSA_private_encrypt, RSA_public_decrypt),
+ always reject numbers >= n.
+
+ *Bodo Moeller*
+
+ * In crypto/rand/md_rand.c, use a new short-time lock CRYPTO_LOCK_RAND2
+ to synchronize access to 'locking_thread'. This is necessary on
+ systems where access to 'locking_thread' (an 'unsigned long'
+ variable) is not atomic.
+
+ *Bodo Moeller*
+
+ * In crypto/rand/md_rand.c, set 'locking_thread' to current thread's ID
+ *before* setting the 'crypto_lock_rand' flag. The previous code had
+ a race condition if 0 is a valid thread ID.
+
+ *Travis Vitek <vitek@roguewave.com>*
+
+ * Add support for shared libraries under Irix.
+
+ *Albert Chin-A-Young <china@thewrittenword.com>*
+
+ * Add configuration option to build on Linux on both big-endian and
+ little-endian MIPS.
+
+ *Ralf Baechle <ralf@uni-koblenz.de>*
+
+ * Add the possibility to create shared libraries on HP-UX.
+
+ *Richard Levitte*
+
+### Changes between 0.9.6a and 0.9.6b [9 Jul 2001]
+
+ * Change ssleay_rand_bytes (crypto/rand/md_rand.c)
+ to avoid a SSLeay/OpenSSL PRNG weakness pointed out by
+ Markku-Juhani O. Saarinen <markku-juhani.saarinen@nokia.com>:
+ PRNG state recovery was possible based on the output of
+ one PRNG request appropriately sized to gain knowledge on
+ 'md' followed by enough consecutive 1-byte PRNG requests
+ to traverse all of 'state'.
+
+ 1. When updating 'md_local' (the current thread's copy of 'md')
+ during PRNG output generation, hash all of the previous
+ 'md_local' value, not just the half used for PRNG output.
+
+ 2. Make the number of bytes from 'state' included into the hash
+ independent from the number of PRNG bytes requested.
+
+ The first measure alone would be sufficient to avoid
+ Markku-Juhani's attack. (Actually it had never occurred
+ to me that the half of 'md_local' used for chaining was the
+ half from which PRNG output bytes were taken -- I had always
+ assumed that the secret half would be used.) The second
+ measure makes sure that additional data from 'state' is never
+ mixed into 'md_local' in small portions; this heuristically
+ further strengthens the PRNG.
+
+ *Bodo Moeller*
+
+ * Fix crypto/bn/asm/mips3.s.
+
+ *Andy Polyakov*
+
+ * When only the key is given to "enc", the IV is undefined. Print out
+ an error message in this case.
+
+ *Lutz Jaenicke*
+
+ * Handle special case when X509_NAME is empty in X509 printing routines.
+
+ *Steve Henson*
+
+ * In dsa_do_verify (crypto/dsa/dsa_ossl.c), verify that r and s are
+ positive and less than q.
+
+ *Bodo Moeller*
+
+ * Don't change `*pointer` in CRYPTO_add_lock() is add_lock_callback is
+ used: it isn't thread safe and the add_lock_callback should handle
+ that itself.
+
+ *Paul Rose <Paul.Rose@bridge.com>*
+
+ * Verify that incoming data obeys the block size in
+ ssl3_enc (ssl/s3_enc.c) and tls1_enc (ssl/t1_enc.c).
+
+ *Bodo Moeller*
+
+ * Fix OAEP check.
+
+ *Ulf Möller, Bodo Möller*
+
+ * The countermeasure against Bleichbacher's attack on PKCS #1 v1.5
+ RSA encryption was accidentally removed in s3_srvr.c in OpenSSL 0.9.5
+ when fixing the server behaviour for backwards-compatible 'client
+ hello' messages. (Note that the attack is impractical against
+ SSL 3.0 and TLS 1.0 anyway because length and version checking
+ means that the probability of guessing a valid ciphertext is
+ around 2^-40; see section 5 in Bleichenbacher's CRYPTO '98
+ paper.)
+
+ Before 0.9.5, the countermeasure (hide the error by generating a
+ random 'decryption result') did not work properly because
+ ERR_clear_error() was missing, meaning that SSL_get_error() would
+ detect the supposedly ignored error.
+
+ Both problems are now fixed.
+
+ *Bodo Moeller*
+
+ * In crypto/bio/bf_buff.c, increase DEFAULT_BUFFER_SIZE to 4096
+ (previously it was 1024).
+
+ *Bodo Moeller*
+
+ * Fix for compatibility mode trust settings: ignore trust settings
+ unless some valid trust or reject settings are present.
+
+ *Steve Henson*
+
+ * Fix for blowfish EVP: its a variable length cipher.
+
+ *Steve Henson*
+
+ * Fix various bugs related to DSA S/MIME verification. Handle missing
+ parameters in DSA public key structures and return an error in the
+ DSA routines if parameters are absent.
+
+ *Steve Henson*
+
+ * In versions up to 0.9.6, RAND_file_name() resorted to file ".rnd"
+ in the current directory if neither $RANDFILE nor $HOME was set.
+ RAND_file_name() in 0.9.6a returned NULL in this case. This has
+ caused some confusion to Windows users who haven't defined $HOME.
+ Thus RAND_file_name() is changed again: e_os.h can define a
+ DEFAULT_HOME, which will be used if $HOME is not set.
+ For Windows, we use "C:"; on other platforms, we still require
+ environment variables.
+
+ * Move 'if (!initialized) RAND_poll()' into regions protected by
+ CRYPTO_LOCK_RAND. This is not strictly necessary, but avoids
+ having multiple threads call RAND_poll() concurrently.
+
+ *Bodo Moeller*
+
+ * In crypto/rand/md_rand.c, replace 'add_do_not_lock' flag by a
+ combination of a flag and a thread ID variable.
+ Otherwise while one thread is in ssleay_rand_bytes (which sets the
+ flag), *other* threads can enter ssleay_add_bytes without obeying
+ the CRYPTO_LOCK_RAND lock (and may even illegally release the lock
+ that they do not hold after the first thread unsets add_do_not_lock).
+
+ *Bodo Moeller*
+
+ * Change bctest again: '-x' expressions are not available in all
+ versions of 'test'.
+
+ *Bodo Moeller*
+
+### Changes between 0.9.6 and 0.9.6a [5 Apr 2001]
+
+ * Fix a couple of memory leaks in PKCS7_dataDecode()
+
+ *Steve Henson, reported by Heyun Zheng <hzheng@atdsprint.com>*
+
+ * Change Configure and Makefiles to provide EXE_EXT, which will contain
+ the default extension for executables, if any. Also, make the perl
+ scripts that use symlink() to test if it really exists and use "cp"
+ if it doesn't. All this made OpenSSL compilable and installable in
+ CygWin.
+
+ *Richard Levitte*
+
+ * Fix for asn1_GetSequence() for indefinite length constructed data.
+ If SEQUENCE is length is indefinite just set c->slen to the total
+ amount of data available.
+
+ *Steve Henson, reported by shige@FreeBSD.org*
+
+ *This change does not apply to 0.9.7.*
+
+ * Change bctest to avoid here-documents inside command substitution
+ (workaround for FreeBSD /bin/sh bug).
+ For compatibility with Ultrix, avoid shell functions (introduced
+ in the bctest version that searches along $PATH).
+
+ *Bodo Moeller*
+
+ * Rename 'des_encrypt' to 'des_encrypt1'. This avoids the clashes
+ with des_encrypt() defined on some operating systems, like Solaris
+ and UnixWare.
+
+ *Richard Levitte*
+
+ * Check the result of RSA-CRT (see D. Boneh, R. DeMillo, R. Lipton:
+ On the Importance of Eliminating Errors in Cryptographic
+ Computations, J. Cryptology 14 (2001) 2, 101-119,
+ <http://theory.stanford.edu/~dabo/papers/faults.ps.gz>).
+
+ *Ulf Moeller*
+
+ * MIPS assembler BIGNUM division bug fix.
+
+ *Andy Polyakov*
+
+ * Disabled incorrect Alpha assembler code.
+
+ *Richard Levitte*
+
+ * Fix PKCS#7 decode routines so they correctly update the length
+ after reading an EOC for the EXPLICIT tag.
+
+ *Steve Henson*
+
+ *This change does not apply to 0.9.7.*
+
+ * Fix bug in PKCS#12 key generation routines. This was triggered
+ if a 3DES key was generated with a 0 initial byte. Include
+ PKCS12_BROKEN_KEYGEN compilation option to retain the old
+ (but broken) behaviour.
+
+ *Steve Henson*
+
+ * Enhance bctest to search for a working bc along $PATH and print
+ it when found.
+
+ *Tim Rice <tim@multitalents.net> via Richard Levitte*
+
+ * Fix memory leaks in err.c: free err_data string if necessary;
+ don't write to the wrong index in ERR_set_error_data.
+
+ *Bodo Moeller*
+
+ * Implement ssl23_peek (analogous to ssl23_read), which previously
+ did not exist.
+
+ *Bodo Moeller*
+
+ * Replace rdtsc with `_emit` statements for VC++ version 5.
+
+ *Jeremy Cooper <jeremy@baymoo.org>*
+
+ * Make it possible to reuse SSLv2 sessions.
+
+ *Richard Levitte*
+
+ * In copy_email() check for >= 0 as a return value for
+ X509_NAME_get_index_by_NID() since 0 is a valid index.
+
+ *Steve Henson reported by Massimiliano Pala <madwolf@opensca.org>*
+
+ * Avoid coredump with unsupported or invalid public keys by checking if
+ X509_get_pubkey() fails in PKCS7_verify(). Fix memory leak when
+ PKCS7_verify() fails with non detached data.
+
+ *Steve Henson*
+
+ * Don't use getenv in library functions when run as setuid/setgid.
+ New function OPENSSL_issetugid().
+
+ *Ulf Moeller*
+
+ * Avoid false positives in memory leak detection code (crypto/mem_dbg.c)
+ due to incorrect handling of multi-threading:
+
+ 1. Fix timing glitch in the MemCheck_off() portion of CRYPTO_mem_ctrl().
+
+ 2. Fix logical glitch in is_MemCheck_on() aka CRYPTO_is_mem_check_on().
+
+ 3. Count how many times MemCheck_off() has been called so that
+ nested use can be treated correctly. This also avoids
+ inband-signalling in the previous code (which relied on the
+ assumption that thread ID 0 is impossible).
+
+ *Bodo Moeller*
+
+ * Add "-rand" option also to s_client and s_server.
+
+ *Lutz Jaenicke*
+
+ * Fix CPU detection on Irix 6.x.
+ *Kurt Hockenbury <khockenb@stevens-tech.edu> and
+ "Bruce W. Forsberg" <bruce.forsberg@baesystems.com>*
+
+ * Fix X509_NAME bug which produced incorrect encoding if X509_NAME
+ was empty.
+
+ *Steve Henson*
+
+ *This change does not apply to 0.9.7.*
+
+ * Use the cached encoding of an X509_NAME structure rather than
+ copying it. This is apparently the reason for the libsafe "errors"
+ but the code is actually correct.
+
+ *Steve Henson*
+
+ * Add new function BN_rand_range(), and fix DSA_sign_setup() to prevent
+ Bleichenbacher's DSA attack.
+ Extend BN_[pseudo_]rand: As before, top=1 forces the highest two bits
+ to be set and top=0 forces the highest bit to be set; top=-1 is new
+ and leaves the highest bit random.
+
+ *Ulf Moeller, Bodo Moeller*
+
+ * In the `NCONF_...`-based implementations for `CONF_...` queries
+ (crypto/conf/conf_lib.c), if the input LHASH is NULL, avoid using
+ a temporary CONF structure with the data component set to NULL
+ (which gives segmentation faults in lh_retrieve).
+ Instead, use NULL for the CONF pointer in CONF_get_string and
+ CONF_get_number (which may use environment variables) and directly
+ return NULL from CONF_get_section.
+
+ *Bodo Moeller*
+
+ * Fix potential buffer overrun for EBCDIC.
+
+ *Ulf Moeller*
+
+ * Tolerate nonRepudiation as being valid for S/MIME signing and certSign
+ keyUsage if basicConstraints absent for a CA.
+
+ *Steve Henson*
+
+ * Make SMIME_write_PKCS7() write mail header values with a format that
+ is more generally accepted (no spaces before the semicolon), since
+ some programs can't parse those values properly otherwise. Also make
+ sure BIO's that break lines after each write do not create invalid
+ headers.
+
+ *Richard Levitte*
+
+ * Make the CRL encoding routines work with empty SEQUENCE OF. The
+ macros previously used would not encode an empty SEQUENCE OF
+ and break the signature.
+
+ *Steve Henson*
+
+ *This change does not apply to 0.9.7.*
+
+ * Zero the premaster secret after deriving the master secret in
+ DH ciphersuites.
+
+ *Steve Henson*
+
+ * Add some EVP_add_digest_alias registrations (as found in
+ OpenSSL_add_all_digests()) to SSL_library_init()
+ aka OpenSSL_add_ssl_algorithms(). This provides improved
+ compatibility with peers using X.509 certificates
+ with unconventional AlgorithmIdentifier OIDs.
+
+ *Bodo Moeller*
+
+ * Fix for Irix with NO_ASM.
+
+ *"Bruce W. Forsberg" <bruce.forsberg@baesystems.com>*
+
+ * ./config script fixes.
+
+ *Ulf Moeller, Richard Levitte*
+
+ * Fix 'openssl passwd -1'.
+
+ *Bodo Moeller*
+
+ * Change PKCS12_key_gen_asc() so it can cope with non null
+ terminated strings whose length is passed in the passlen
+ parameter, for example from PEM callbacks. This was done
+ by adding an extra length parameter to asc2uni().
+
+ *Steve Henson, reported by <oddissey@samsung.co.kr>*
+
+ * Fix C code generated by 'openssl dsaparam -C': If a BN_bin2bn
+ call failed, free the DSA structure.
+
+ *Bodo Moeller*
+
+ * Fix to uni2asc() to cope with zero length Unicode strings.
+ These are present in some PKCS#12 files.
+
+ *Steve Henson*
+
+ * Increase s2->wbuf allocation by one byte in ssl2_new (ssl/s2_lib.c).
+ Otherwise do_ssl_write (ssl/s2_pkt.c) will write beyond buffer limits
+ when writing a 32767 byte record.
+
+ *Bodo Moeller; problem reported by Eric Day <eday@concentric.net>*
+
+ * In `RSA_eay_public_{en,ed}crypt` and RSA_eay_mod_exp (rsa_eay.c),
+ obtain lock CRYPTO_LOCK_RSA before setting `rsa->_method_mod_{n,p,q}`.
+
+ (RSA objects have a reference count access to which is protected
+ by CRYPTO_LOCK_RSA [see rsa_lib.c, s3_srvr.c, ssl_cert.c, ssl_rsa.c],
+ so they are meant to be shared between threads.)
+ *Bodo Moeller, Geoff Thorpe; original patch submitted by
+ "Reddie, Steven" <Steven.Reddie@ca.com>*
+
+ * Fix a deadlock in CRYPTO_mem_leaks().
+
+ *Bodo Moeller*
+
+ * Use better test patterns in bntest.
+
+ *Ulf Möller*
+
+ * rand_win.c fix for Borland C.
+
+ *Ulf Möller*
+
+ * BN_rshift bugfix for n == 0.
+
+ *Bodo Moeller*
+
+ * Add a 'bctest' script that checks for some known 'bc' bugs
+ so that 'make test' does not abort just because 'bc' is broken.
+
+ *Bodo Moeller*
+
+ * Store verify_result within SSL_SESSION also for client side to
+ avoid potential security hole. (Re-used sessions on the client side
+ always resulted in verify_result==X509_V_OK, not using the original
+ result of the server certificate verification.)
+
+ *Lutz Jaenicke*
+
+ * Fix ssl3_pending: If the record in s->s3->rrec is not of type
+ SSL3_RT_APPLICATION_DATA, return 0.
+ Similarly, change ssl2_pending to return 0 if SSL_in_init(s) is true.
+
+ *Bodo Moeller*
+
+ * Fix SSL_peek:
+ Both ssl2_peek and ssl3_peek, which were totally broken in earlier
+ releases, have been re-implemented by renaming the previous
+ implementations of ssl2_read and ssl3_read to ssl2_read_internal
+ and ssl3_read_internal, respectively, and adding 'peek' parameters
+ to them. The new ssl[23]_{read,peek} functions are calls to
+ ssl[23]_read_internal with the 'peek' flag set appropriately.
+ A 'peek' parameter has also been added to ssl3_read_bytes, which
+ does the actual work for ssl3_read_internal.
+
+ *Bodo Moeller*
+
+ * Initialise "ex_data" member of RSA/DSA/DH structures prior to calling
+ the method-specific "init()" handler. Also clean up ex_data after
+ calling the method-specific "finish()" handler. Previously, this was
+ happening the other way round.
+
+ *Geoff Thorpe*
+
+ * Increase BN_CTX_NUM (the number of BIGNUMs in a BN_CTX) to 16.
+ The previous value, 12, was not always sufficient for BN_mod_exp().
+
+ *Bodo Moeller*
+
+ * Make sure that shared libraries get the internal name engine with
+ the full version number and not just 0. This should mark the
+ shared libraries as not backward compatible. Of course, this should
+ be changed again when we can guarantee backward binary compatibility.
+
+ *Richard Levitte*
+
+ * Fix typo in get_cert_by_subject() in by_dir.c
+
+ *Jean-Marc Desperrier <jean-marc.desperrier@certplus.com>*
+
+ * Rework the system to generate shared libraries:
+
+ - Make note of the expected extension for the shared libraries and
+ if there is a need for symbolic links from for example libcrypto.so.0
+ to libcrypto.so.0.9.7. There is extended info in Configure for
+ that.
+
+ - Make as few rebuilds of the shared libraries as possible.
+
+ - Still avoid linking the OpenSSL programs with the shared libraries.
+
+ - When installing, install the shared libraries separately from the
+ static ones.
+
+ *Richard Levitte*
+
+ * Fix SSL_CTX_set_read_ahead macro to actually use its argument.
+
+ Copy SSL_CTX's read_ahead flag to SSL object directly in SSL_new
+ and not in SSL_clear because the latter is also used by the
+ accept/connect functions; previously, the settings made by
+ SSL_set_read_ahead would be lost during the handshake.
+
+ *Bodo Moeller; problems reported by Anders Gertz <gertz@epact.se>*
+
+ * Correct util/mkdef.pl to be selective about disabled algorithms.
+ Previously, it would create entries for disabled algorithms no
+ matter what.
+
+ *Richard Levitte*
+
+ * Added several new manual pages for SSL_* function.
+
+ *Lutz Jaenicke*
+
+### Changes between 0.9.5a and 0.9.6 [24 Sep 2000]
+
+ * In ssl23_get_client_hello, generate an error message when faced
+ with an initial SSL 3.0/TLS record that is too small to contain the
+ first two bytes of the ClientHello message, i.e. client_version.
+ (Note that this is a pathologic case that probably has never happened
+ in real life.) The previous approach was to use the version number
+ from the record header as a substitute; but our protocol choice
+ should not depend on that one because it is not authenticated
+ by the Finished messages.
+
+ *Bodo Moeller*
+
+ * More robust randomness gathering functions for Windows.
+
+ *Jeffrey Altman <jaltman@columbia.edu>*
+
+ * For compatibility reasons if the flag X509_V_FLAG_ISSUER_CHECK is
+ not set then we don't setup the error code for issuer check errors
+ to avoid possibly overwriting other errors which the callback does
+ handle. If an application does set the flag then we assume it knows
+ what it is doing and can handle the new informational codes
+ appropriately.
+
+ *Steve Henson*
+
+ * Fix for a nasty bug in ASN1_TYPE handling. ASN1_TYPE is used for
+ a general "ANY" type, as such it should be able to decode anything
+ including tagged types. However it didn't check the class so it would
+ wrongly interpret tagged types in the same way as their universal
+ counterpart and unknown types were just rejected. Changed so that the
+ tagged and unknown types are handled in the same way as a SEQUENCE:
+ that is the encoding is stored intact. There is also a new type
+ "V_ASN1_OTHER" which is used when the class is not universal, in this
+ case we have no idea what the actual type is so we just lump them all
+ together.
+
+ *Steve Henson*
+
+ * On VMS, stdout may very well lead to a file that is written to
+ in a record-oriented fashion. That means that every write() will
+ write a separate record, which will be read separately by the
+ programs trying to read from it. This can be very confusing.
+
+ The solution is to put a BIO filter in the way that will buffer
+ text until a linefeed is reached, and then write everything a
+ line at a time, so every record written will be an actual line,
+ not chunks of lines and not (usually doesn't happen, but I've
+ seen it once) several lines in one record. BIO_f_linebuffer() is
+ the answer.
+
+ Currently, it's a VMS-only method, because that's where it has
+ been tested well enough.
+
+ *Richard Levitte*
+
+ * Remove 'optimized' squaring variant in BN_mod_mul_montgomery,
+ it can return incorrect results.
+ (Note: The buggy variant was not enabled in OpenSSL 0.9.5a,
+ but it was in 0.9.6-beta[12].)
+
+ *Bodo Moeller*
+
+ * Disable the check for content being present when verifying detached
+ signatures in pk7_smime.c. Some versions of Netscape (wrongly)
+ include zero length content when signing messages.
+
+ *Steve Henson*
+
+ * New BIO_shutdown_wr macro, which invokes the BIO_C_SHUTDOWN_WR
+ BIO_ctrl (for BIO pairs).
+
+ *Bodo Möller*
+
+ * Add DSO method for VMS.
+
+ *Richard Levitte*
+
+ * Bug fix: Montgomery multiplication could produce results with the
+ wrong sign.
+
+ *Ulf Möller*
+
+ * Add RPM specification openssl.spec and modify it to build three
+ packages. The default package contains applications, application
+ documentation and run-time libraries. The devel package contains
+ include files, static libraries and function documentation. The
+ doc package contains the contents of the doc directory. The original
+ openssl.spec was provided by Damien Miller <djm@mindrot.org>.
+
+ *Richard Levitte*
+
+ * Add a large number of documentation files for many SSL routines.
+
+ *Lutz Jaenicke <Lutz.Jaenicke@aet.TU-Cottbus.DE>*
+
+ * Add a configuration entry for Sony News 4.
+
+ *NAKAJI Hiroyuki <nakaji@tutrp.tut.ac.jp>*
+
+ * Don't set the two most significant bits to one when generating a
+ random number < q in the DSA library.
+
+ *Ulf Möller*
+
+ * New SSL API mode 'SSL_MODE_AUTO_RETRY'. This disables the default
+ behaviour that SSL_read may result in SSL_ERROR_WANT_READ (even if
+ the underlying transport is blocking) if a handshake took place.
+ (The default behaviour is needed by applications such as s_client
+ and s_server that use select() to determine when to use SSL_read;
+ but for applications that know in advance when to expect data, it
+ just makes things more complicated.)
+
+ *Bodo Moeller*
+
+ * Add RAND_egd_bytes(), which gives control over the number of bytes read
+ from EGD.
+
+ *Ben Laurie*
+
+ * Add a few more EBCDIC conditionals that make `req` and `x509`
+ work better on such systems.
+
+ *Martin Kraemer <Martin.Kraemer@MchP.Siemens.De>*
+
+ * Add two demo programs for PKCS12_parse() and PKCS12_create().
+ Update PKCS12_parse() so it copies the friendlyName and the
+ keyid to the certificates aux info.
+
+ *Steve Henson*
+
+ * Fix bug in PKCS7_verify() which caused an infinite loop
+ if there was more than one signature.
+
+ *Sven Uszpelkat <su@celocom.de>*
+
+ * Major change in util/mkdef.pl to include extra information
+ about each symbol, as well as presenting variables as well
+ as functions. This change means that there's n more need
+ to rebuild the .num files when some algorithms are excluded.
+
+ *Richard Levitte*
+
+ * Allow the verify time to be set by an application,
+ rather than always using the current time.
+
+ *Steve Henson*
+
+ * Phase 2 verify code reorganisation. The certificate
+ verify code now looks up an issuer certificate by a
+ number of criteria: subject name, authority key id
+ and key usage. It also verifies self signed certificates
+ by the same criteria. The main comparison function is
+ X509_check_issued() which performs these checks.
+
+ Lot of changes were necessary in order to support this
+ without completely rewriting the lookup code.
+
+ Authority and subject key identifier are now cached.
+
+ The LHASH 'certs' is X509_STORE has now been replaced
+ by a STACK_OF(X509_OBJECT). This is mainly because an
+ LHASH can't store or retrieve multiple objects with
+ the same hash value.
+
+ As a result various functions (which were all internal
+ use only) have changed to handle the new X509_STORE
+ structure. This will break anything that messed round
+ with X509_STORE internally.
+
+ The functions X509_STORE_add_cert() now checks for an
+ exact match, rather than just subject name.
+
+ The X509_STORE API doesn't directly support the retrieval
+ of multiple certificates matching a given criteria, however
+ this can be worked round by performing a lookup first
+ (which will fill the cache with candidate certificates)
+ and then examining the cache for matches. This is probably
+ the best we can do without throwing out X509_LOOKUP
+ entirely (maybe later...).
+
+ The X509_VERIFY_CTX structure has been enhanced considerably.
+
+ All certificate lookup operations now go via a get_issuer()
+ callback. Although this currently uses an X509_STORE it
+ can be replaced by custom lookups. This is a simple way
+ to bypass the X509_STORE hackery necessary to make this
+ work and makes it possible to use more efficient techniques
+ in future. A very simple version which uses a simple
+ STACK for its trusted certificate store is also provided
+ using X509_STORE_CTX_trusted_stack().
+
+ The verify_cb() and verify() callbacks now have equivalents
+ in the X509_STORE_CTX structure.
+
+ X509_STORE_CTX also has a 'flags' field which can be used
+ to customise the verify behaviour.
+
+ *Steve Henson*
+
+ * Add new PKCS#7 signing option PKCS7_NOSMIMECAP which
+ excludes S/MIME capabilities.
+
+ *Steve Henson*
+
+ * When a certificate request is read in keep a copy of the
+ original encoding of the signed data and use it when outputting
+ again. Signatures then use the original encoding rather than
+ a decoded, encoded version which may cause problems if the
+ request is improperly encoded.
+
+ *Steve Henson*
+
+ * For consistency with other BIO_puts implementations, call
+ buffer_write(b, ...) directly in buffer_puts instead of calling
+ BIO_write(b, ...).
+
+ In BIO_puts, increment b->num_write as in BIO_write.
+
+ *Peter.Sylvester@EdelWeb.fr*
+
+ * Fix BN_mul_word for the case where the word is 0. (We have to use
+ BN_zero, we may not return a BIGNUM with an array consisting of
+ words set to zero.)
+
+ *Bodo Moeller*
+
+ * Avoid calling abort() from within the library when problems are
+ detected, except if preprocessor symbols have been defined
+ (such as REF_CHECK, BN_DEBUG etc.).
+
+ *Bodo Moeller*
+
+ * New openssl application 'rsautl'. This utility can be
+ used for low-level RSA operations. DER public key
+ BIO/fp routines also added.
+
+ *Steve Henson*
+
+ * New Configure entry and patches for compiling on QNX 4.
+
+ *Andreas Schneider <andreas@ds3.etech.fh-hamburg.de>*
+
+ * A demo state-machine implementation was sponsored by
+ Nuron (<http://www.nuron.com/>) and is now available in
+ demos/state_machine.
+
+ *Ben Laurie*
+
+ * New options added to the 'dgst' utility for signature
+ generation and verification.
+
+ *Steve Henson*
+
+ * Unrecognized PKCS#7 content types are now handled via a
+ catch all ASN1_TYPE structure. This allows unsupported
+ types to be stored as a "blob" and an application can
+ encode and decode it manually.
+
+ *Steve Henson*
+
+ * Fix various signed/unsigned issues to make a_strex.c
+ compile under VC++.
+
+ *Oscar Jacobsson <oscar.jacobsson@celocom.com>*
+
+ * ASN1 fixes. i2d_ASN1_OBJECT was not returning the correct
+ length if passed a buffer. ASN1_INTEGER_to_BN failed
+ if passed a NULL BN and its argument was negative.
+
+ *Steve Henson, pointed out by Sven Heiberg <sven@tartu.cyber.ee>*
+
+ * Modification to PKCS#7 encoding routines to output definite
+ length encoding. Since currently the whole structures are in
+ memory there's not real point in using indefinite length
+ constructed encoding. However if OpenSSL is compiled with
+ the flag PKCS7_INDEFINITE_ENCODING the old form is used.
+
+ *Steve Henson*
+
+ * Added BIO_vprintf() and BIO_vsnprintf().
+
+ *Richard Levitte*
+
+ * Added more prefixes to parse for in the strings written
+ through a logging bio, to cover all the levels that are available
+ through syslog. The prefixes are now:
+
+ PANIC, EMERG, EMR => LOG_EMERG
+ ALERT, ALR => LOG_ALERT
+ CRIT, CRI => LOG_CRIT
+ ERROR, ERR => LOG_ERR
+ WARNING, WARN, WAR => LOG_WARNING
+ NOTICE, NOTE, NOT => LOG_NOTICE
+ INFO, INF => LOG_INFO
+ DEBUG, DBG => LOG_DEBUG
+
+ and as before, if none of those prefixes are present at the
+ beginning of the string, LOG_ERR is chosen.
+
+ On Win32, the `LOG_*` levels are mapped according to this:
+
+ LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR => EVENTLOG_ERROR_TYPE
+ LOG_WARNING => EVENTLOG_WARNING_TYPE
+ LOG_NOTICE, LOG_INFO, LOG_DEBUG => EVENTLOG_INFORMATION_TYPE
+
+ *Richard Levitte*
+
+ * Made it possible to reconfigure with just the configuration
+ argument "reconf" or "reconfigure". The command line arguments
+ are stored in Makefile.ssl in the variable CONFIGURE_ARGS,
+ and are retrieved from there when reconfiguring.
+
+ *Richard Levitte*
+
+ * MD4 implemented.
+
+ *Assar Westerlund <assar@sics.se>, Richard Levitte*
+
+ * Add the arguments -CAfile and -CApath to the pkcs12 utility.
+
+ *Richard Levitte*
+
+ * The obj_dat.pl script was messing up the sorting of object
+ names. The reason was that it compared the quoted version
+ of strings as a result "OCSP" > "OCSP Signing" because
+ " > SPACE. Changed script to store unquoted versions of
+ names and add quotes on output. It was also omitting some
+ names from the lookup table if they were given a default
+ value (that is if SN is missing it is given the same
+ value as LN and vice versa), these are now added on the
+ grounds that if an object has a name we should be able to
+ look it up. Finally added warning output when duplicate
+ short or long names are found.
+
+ *Steve Henson*
+
+ * Changes needed for Tandem NSK.
+
+ *Scott Uroff <scott@xypro.com>*
+
+ * Fix SSL 2.0 rollback checking: Due to an off-by-one error in
+ RSA_padding_check_SSLv23(), special padding was never detected
+ and thus the SSL 3.0/TLS 1.0 countermeasure against protocol
+ version rollback attacks was not effective.
+
+ In s23_clnt.c, don't use special rollback-attack detection padding
+ (RSA_SSLV23_PADDING) if SSL 2.0 is the only protocol enabled in the
+ client; similarly, in s23_srvr.c, don't do the rollback check if
+ SSL 2.0 is the only protocol enabled in the server.
+
+ *Bodo Moeller*
+
+ * Make it possible to get hexdumps of unprintable data with 'openssl
+ asn1parse'. By implication, the functions ASN1_parse_dump() and
+ BIO_dump_indent() are added.
+
+ *Richard Levitte*
+
+ * New functions ASN1_STRING_print_ex() and X509_NAME_print_ex()
+ these print out strings and name structures based on various
+ flags including RFC2253 support and proper handling of
+ multibyte characters. Added options to the 'x509' utility
+ to allow the various flags to be set.
+
+ *Steve Henson*
+
+ * Various fixes to use ASN1_TIME instead of ASN1_UTCTIME.
+ Also change the functions X509_cmp_current_time() and
+ X509_gmtime_adj() work with an ASN1_TIME structure,
+ this will enable certificates using GeneralizedTime in validity
+ dates to be checked.
+
+ *Steve Henson*
+
+ * Make the NEG_PUBKEY_BUG code (which tolerates invalid
+ negative public key encodings) on by default,
+ NO_NEG_PUBKEY_BUG can be set to disable it.
+
+ *Steve Henson*
+
+ * New function c2i_ASN1_OBJECT() which acts on ASN1_OBJECT
+ content octets. An i2c_ASN1_OBJECT is unnecessary because
+ the encoding can be trivially obtained from the structure.
+
+ *Steve Henson*
+
+ * crypto/err.c locking bugfix: Use write locks (`CRYPTO_w_[un]lock`),
+ not read locks (`CRYPTO_r_[un]lock`).
+
+ *Bodo Moeller*
+
+ * A first attempt at creating official support for shared
+ libraries through configuration. I've kept it so the
+ default is static libraries only, and the OpenSSL programs
+ are always statically linked for now, but there are
+ preparations for dynamic linking in place.
+ This has been tested on Linux and Tru64.
+
+ *Richard Levitte*
+
+ * Randomness polling function for Win9x, as described in:
+ Peter Gutmann, Software Generation of Practically Strong
+ Random Numbers.
+
+ *Ulf Möller*
+
+ * Fix so PRNG is seeded in req if using an already existing
+ DSA key.
+
+ *Steve Henson*
+
+ * New options to smime application. -inform and -outform
+ allow alternative formats for the S/MIME message including
+ PEM and DER. The -content option allows the content to be
+ specified separately. This should allow things like Netscape
+ form signing output easier to verify.
+
+ *Steve Henson*
+
+ * Fix the ASN1 encoding of tags using the 'long form'.
+
+ *Steve Henson*
+
+ * New ASN1 functions, `i2c_*` and `c2i_*` for INTEGER and BIT
+ STRING types. These convert content octets to and from the
+ underlying type. The actual tag and length octets are
+ already assumed to have been read in and checked. These
+ are needed because all other string types have virtually
+ identical handling apart from the tag. By having versions
+ of the ASN1 functions that just operate on content octets
+ IMPLICIT tagging can be handled properly. It also allows
+ the ASN1_ENUMERATED code to be cut down because ASN1_ENUMERATED
+ and ASN1_INTEGER are identical apart from the tag.
+
+ *Steve Henson*
+
+ * Change the handling of OID objects as follows:
+
+ - New object identifiers are inserted in objects.txt, following
+ the syntax given in [crypto/objects/README.md](crypto/objects/README.md).
+ - objects.pl is used to process obj_mac.num and create a new
+ obj_mac.h.
+ - obj_dat.pl is used to create a new obj_dat.h, using the data in
+ obj_mac.h.
+
+ This is currently kind of a hack, and the perl code in objects.pl
+ isn't very elegant, but it works as I intended. The simplest way
+ to check that it worked correctly is to look in obj_dat.h and
+ check the array nid_objs and make sure the objects haven't moved
+ around (this is important!). Additions are OK, as well as
+ consistent name changes.
+
+ *Richard Levitte*
+
+ * Add BSD-style MD5-based passwords to 'openssl passwd' (option '-1').
+
+ *Bodo Moeller*
+
+ * Addition of the command line parameter '-rand file' to 'openssl req'.
+ The given file adds to whatever has already been seeded into the
+ random pool through the RANDFILE configuration file option or
+ environment variable, or the default random state file.
+
+ *Richard Levitte*
+
+ * mkstack.pl now sorts each macro group into lexical order.
+ Previously the output order depended on the order the files
+ appeared in the directory, resulting in needless rewriting
+ of safestack.h .
+
+ *Steve Henson*
+
+ * Patches to make OpenSSL compile under Win32 again. Mostly
+ work arounds for the VC++ problem that it treats func() as
+ func(void). Also stripped out the parts of mkdef.pl that
+ added extra typesafe functions: these no longer exist.
+
+ *Steve Henson*
+
+ * Reorganisation of the stack code. The macros are now all
+ collected in safestack.h . Each macro is defined in terms of
+ a "stack macro" of the form `SKM_<name>(type, a, b)`. The
+ DEBUG_SAFESTACK is now handled in terms of function casts,
+ this has the advantage of retaining type safety without the
+ use of additional functions. If DEBUG_SAFESTACK is not defined
+ then the non typesafe macros are used instead. Also modified the
+ mkstack.pl script to handle the new form. Needs testing to see
+ if which (if any) compilers it chokes and maybe make DEBUG_SAFESTACK
+ the default if no major problems. Similar behaviour for ASN1_SET_OF
+ and PKCS12_STACK_OF.
+
+ *Steve Henson*
+
+ * When some versions of IIS use the 'NET' form of private key the
+ key derivation algorithm is different. Normally MD5(password) is
+ used as a 128 bit RC4 key. In the modified case
+ MD5(MD5(password) + "SGCKEYSALT") is used instead. Added some
+ new functions i2d_RSA_NET(), d2i_RSA_NET() etc which are the same
+ as the old Netscape_RSA functions except they have an additional
+ 'sgckey' parameter which uses the modified algorithm. Also added
+ an -sgckey command line option to the rsa utility. Thanks to
+ Adrian Peck <bertie@ncipher.com> for posting details of the modified
+ algorithm to openssl-dev.
+
+ *Steve Henson*
+
+ * The evp_local.h macros were using 'c.##kname' which resulted in
+ invalid expansion on some systems (SCO 5.0.5 for example).
+ Corrected to 'c.kname'.
+
+ *Phillip Porch <root@theporch.com>*
+
+ * New X509_get1_email() and X509_REQ_get1_email() functions that return
+ a STACK of email addresses from a certificate or request, these look
+ in the subject name and the subject alternative name extensions and
+ omit any duplicate addresses.
+
+ *Steve Henson*
+
+ * Re-implement BN_mod_exp2_mont using independent (and larger) windows.
+ This makes DSA verification about 2 % faster.
+
+ *Bodo Moeller*
+
+ * Increase maximum window size in `BN_mod_exp_...` to 6 bits instead of 5
+ (meaning that now 2^5 values will be precomputed, which is only 4 KB
+ plus overhead for 1024 bit moduli).
+ This makes exponentiations about 0.5 % faster for 1024 bit
+ exponents (as measured by "openssl speed rsa2048").
+
+ *Bodo Moeller*
+
+ * Rename memory handling macros to avoid conflicts with other
+ software:
+ Malloc => OPENSSL_malloc
+ Malloc_locked => OPENSSL_malloc_locked
+ Realloc => OPENSSL_realloc
+ Free => OPENSSL_free
+
+ *Richard Levitte*
+
+ * New function BN_mod_exp_mont_word for small bases (roughly 15%
+ faster than BN_mod_exp_mont, i.e. 7% for a full DH exchange).
+
+ *Bodo Moeller*
+
+ * CygWin32 support.
+
+ *John Jarvie <jjarvie@newsguy.com>*
+
+ * The type-safe stack code has been rejigged. It is now only compiled
+ in when OpenSSL is configured with the DEBUG_SAFESTACK option and
+ by default all type-specific stack functions are "#define"d back to
+ standard stack functions. This results in more streamlined output
+ but retains the type-safety checking possibilities of the original
+ approach.
+
+ *Geoff Thorpe*
+
+ * The STACK code has been cleaned up, and certain type declarations
+ that didn't make a lot of sense have been brought in line. This has
+ also involved a cleanup of sorts in safestack.h to more correctly
+ map type-safe stack functions onto their plain stack counterparts.
+ This work has also resulted in a variety of "const"ifications of
+ lots of the code, especially `_cmp` operations which should normally
+ be prototyped with "const" parameters anyway.
+
+ *Geoff Thorpe*
+
+ * When generating bytes for the first time in md_rand.c, 'stir the pool'
+ by seeding with STATE_SIZE dummy bytes (with zero entropy count).
+ (The PRNG state consists of two parts, the large pool 'state' and 'md',
+ where all of 'md' is used each time the PRNG is used, but 'state'
+ is used only indexed by a cyclic counter. As entropy may not be
+ well distributed from the beginning, 'md' is important as a
+ chaining variable. However, the output function chains only half
+ of 'md', i.e. 80 bits. ssleay_rand_add, on the other hand, chains
+ all of 'md', and seeding with STATE_SIZE dummy bytes will result
+ in all of 'state' being rewritten, with the new values depending
+ on virtually all of 'md'. This overcomes the 80 bit limitation.)
+
+ *Bodo Moeller*
+
+ * In ssl/s2_clnt.c and ssl/s3_clnt.c, call ERR_clear_error() when
+ the handshake is continued after ssl_verify_cert_chain();
+ otherwise, if SSL_VERIFY_NONE is set, remaining error codes
+ can lead to 'unexplainable' connection aborts later.
+
+ *Bodo Moeller; problem tracked down by Lutz Jaenicke*
+
+ * Major EVP API cipher revision.
+ Add hooks for extra EVP features. This allows various cipher
+ parameters to be set in the EVP interface. Support added for variable
+ key length ciphers via the EVP_CIPHER_CTX_set_key_length() function and
+ setting of RC2 and RC5 parameters.
+
+ Modify EVP_OpenInit() and EVP_SealInit() to cope with variable key length
+ ciphers.
+
+ Remove lots of duplicated code from the EVP library. For example *every*
+ cipher init() function handles the 'iv' in the same way according to the
+ cipher mode. They also all do nothing if the 'key' parameter is NULL and
+ for CFB and OFB modes they zero ctx->num.
+
+ New functionality allows removal of S/MIME code RC2 hack.
+
+ Most of the routines have the same form and so can be declared in terms
+ of macros.
+
+ By shifting this to the top level EVP_CipherInit() it can be removed from
+ all individual ciphers. If the cipher wants to handle IVs or keys
+ differently it can set the EVP_CIPH_CUSTOM_IV or EVP_CIPH_ALWAYS_CALL_INIT
+ flags.
+
+ Change lots of functions like EVP_EncryptUpdate() to now return a
+ value: although software versions of the algorithms cannot fail
+ any installed hardware versions can.
+
+ *Steve Henson*
+
+ * Implement SSL_OP_TLS_ROLLBACK_BUG: In ssl3_get_client_key_exchange, if
+ this option is set, tolerate broken clients that send the negotiated
+ protocol version number instead of the requested protocol version
+ number.
+
+ *Bodo Moeller*
+
+ * Call dh_tmp_cb (set by `..._TMP_DH_CB`) with correct 'is_export' flag;
+ i.e. non-zero for export ciphersuites, zero otherwise.
+ Previous versions had this flag inverted, inconsistent with
+ rsa_tmp_cb (..._TMP_RSA_CB).
+
+ *Bodo Moeller; problem reported by Amit Chopra*
+
+ * Add missing DSA library text string. Work around for some IIS
+ key files with invalid SEQUENCE encoding.
+
+ *Steve Henson*
+
+ * Add a document (doc/standards.txt) that list all kinds of standards
+ and so on that are implemented in OpenSSL.
+
+ *Richard Levitte*
+
+ * Enhance c_rehash script. Old version would mishandle certificates
+ with the same subject name hash and wouldn't handle CRLs at all.
+ Added -fingerprint option to crl utility, to support new c_rehash
+ features.
+
+ *Steve Henson*
+
+ * Eliminate non-ANSI declarations in crypto.h and stack.h.
+
+ *Ulf Möller*
+
+ * Fix for SSL server purpose checking. Server checking was
+ rejecting certificates which had extended key usage present
+ but no ssl client purpose.
+
+ *Steve Henson, reported by Rene Grosser <grosser@hisolutions.com>*
+
+ * Make PKCS#12 code work with no password. The PKCS#12 spec
+ is a little unclear about how a blank password is handled.
+ Since the password in encoded as a BMPString with terminating
+ double NULL a zero length password would end up as just the
+ double NULL. However no password at all is different and is
+ handled differently in the PKCS#12 key generation code. NS
+ treats a blank password as zero length. MSIE treats it as no
+ password on export: but it will try both on import. We now do
+ the same: PKCS12_parse() tries zero length and no password if
+ the password is set to "" or NULL (NULL is now a valid password:
+ it wasn't before) as does the pkcs12 application.
+
+ *Steve Henson*
+
+ * Bugfixes in `apps/x509.c`: Avoid a memory leak; and don't use
+ perror when PEM_read_bio_X509_REQ fails, the error message must
+ be obtained from the error queue.
+
+ *Bodo Moeller*
+
+ * Avoid 'thread_hash' memory leak in crypto/err/err.c by freeing
+ it in ERR_remove_state if appropriate, and change ERR_get_state
+ accordingly to avoid race conditions (this is necessary because
+ thread_hash is no longer constant once set).
+
+ *Bodo Moeller*
+
+ * Bugfix for linux-elf makefile.one.
+
+ *Ulf Möller*
+
+ * RSA_get_default_method() will now cause a default
+ RSA_METHOD to be chosen if one doesn't exist already.
+ Previously this was only set during a call to RSA_new()
+ or RSA_new_method(NULL) meaning it was possible for
+ RSA_get_default_method() to return NULL.
+
+ *Geoff Thorpe*
+
+ * Added native name translation to the existing DSO code
+ that will convert (if the flag to do so is set) filenames
+ that are sufficiently small and have no path information
+ into a canonical native form. Eg. "blah" converted to
+ "libblah.so" or "blah.dll" etc.
+
+ *Geoff Thorpe*
+
+ * New function ERR_error_string_n(e, buf, len) which is like
+ ERR_error_string(e, buf), but writes at most 'len' bytes
+ including the 0 terminator. For ERR_error_string_n, 'buf'
+ may not be NULL.
+
+ *Damien Miller <djm@mindrot.org>, Bodo Moeller*
+
+ * CONF library reworked to become more general. A new CONF
+ configuration file reader "class" is implemented as well as a
+ new functions (`NCONF_*`, for "New CONF") to handle it. The now
+ old `CONF_*` functions are still there, but are reimplemented to
+ work in terms of the new functions. Also, a set of functions
+ to handle the internal storage of the configuration data is
+ provided to make it easier to write new configuration file
+ reader "classes" (I can definitely see something reading a
+ configuration file in XML format, for example), called `_CONF_*`,
+ or "the configuration storage API"...
+
+ The new configuration file reading functions are:
+
+ NCONF_new, NCONF_free, NCONF_load, NCONF_load_fp, NCONF_load_bio,
+ NCONF_get_section, NCONF_get_string, NCONF_get_numbre
+
+ NCONF_default, NCONF_WIN32
+
+ NCONF_dump_fp, NCONF_dump_bio
+
+ NCONF_default and NCONF_WIN32 are method (or "class") choosers,
+ NCONF_new creates a new CONF object. This works in the same way
+ as other interfaces in OpenSSL, like the BIO interface.
+ `NCONF_dump_*` dump the internal storage of the configuration file,
+ which is useful for debugging. All other functions take the same
+ arguments as the old `CONF_*` functions with the exception of the
+ first that must be a `CONF *` instead of a `LHASH *`.
+
+ To make it easier to use the new classes with the old `CONF_*` functions,
+ the function CONF_set_default_method is provided.
+
+ *Richard Levitte*
+
+ * Add '-tls1' option to 'openssl ciphers', which was already
+ mentioned in the documentation but had not been implemented.
+ (This option is not yet really useful because even the additional
+ experimental TLS 1.0 ciphers are currently treated as SSL 3.0 ciphers.)
+
+ *Bodo Moeller*
+
+ * Initial DSO code added into libcrypto for letting OpenSSL (and
+ OpenSSL-based applications) load shared libraries and bind to
+ them in a portable way.
+
+ *Geoff Thorpe, with contributions from Richard Levitte*
+
+### Changes between 0.9.5 and 0.9.5a [1 Apr 2000]
+
+ * Make sure _lrotl and _lrotr are only used with MSVC.
+
+ * Use lock CRYPTO_LOCK_RAND correctly in ssleay_rand_status
+ (the default implementation of RAND_status).
+
+ * Rename openssl x509 option '-crlext', which was added in 0.9.5,
+ to '-clrext' (= clear extensions), as intended and documented.
+ *Bodo Moeller; inconsistency pointed out by Michael Attili
+ <attili@amaxo.com>*
+
+ * Fix for HMAC. It wasn't zeroing the rest of the block if the key length
+ was larger than the MD block size.
+
+ *Steve Henson, pointed out by Yost William <YostW@tce.com>*
+
+ * Modernise PKCS12_parse() so it uses STACK_OF(X509) for its ca argument
+ fix a leak when the ca argument was passed as NULL. Stop X509_PUBKEY_set()
+ using the passed key: if the passed key was a private key the result
+ of X509_print(), for example, would be to print out all the private key
+ components.
+
+ *Steve Henson*
+
+ * des_quad_cksum() byte order bug fix.
+ *Ulf Möller, using the problem description in krb4-0.9.7, where
+ the solution is attributed to Derrick J Brashear <shadow@DEMENTIA.ORG>*
+
+ * Fix so V_ASN1_APP_CHOOSE works again: however its use is strongly
+ discouraged.
+
+ *Steve Henson, pointed out by Brian Korver <briank@cs.stanford.edu>*
+
+ * For easily testing in shell scripts whether some command
+ 'openssl XXX' exists, the new pseudo-command 'openssl no-XXX'
+ returns with exit code 0 iff no command of the given name is available.
+ 'no-XXX' is printed in this case, 'XXX' otherwise. In both cases,
+ the output goes to stdout and nothing is printed to stderr.
+ Additional arguments are always ignored.
+
+ Since for each cipher there is a command of the same name,
+ the 'no-cipher' compilation switches can be tested this way.
+
+ ('openssl no-XXX' is not able to detect pseudo-commands such
+ as 'quit', 'list-XXX-commands', or 'no-XXX' itself.)
+
+ *Bodo Moeller*
+
+ * Update test suite so that 'make test' succeeds in 'no-rsa' configuration.
+
+ *Bodo Moeller*
+
+ * For SSL_[CTX_]set_tmp_dh, don't create a DH key if SSL_OP_SINGLE_DH_USE
+ is set; it will be thrown away anyway because each handshake creates
+ its own key.
+ ssl_cert_dup, which is used by SSL_new, now copies DH keys in addition
+ to parameters -- in previous versions (since OpenSSL 0.9.3) the
+ 'default key' from SSL_CTX_set_tmp_dh would always be lost, meaning
+ you effectively got SSL_OP_SINGLE_DH_USE when using this macro.
+
+ *Bodo Moeller*
+
+ * New s_client option -ign_eof: EOF at stdin is ignored, and
+ 'Q' and 'R' lose their special meanings (quit/renegotiate).
+ This is part of what -quiet does; unlike -quiet, -ign_eof
+ does not suppress any output.
+
+ *Richard Levitte*
+
+ * Add compatibility options to the purpose and trust code. The
+ purpose X509_PURPOSE_ANY is "any purpose" which automatically
+ accepts a certificate or CA, this was the previous behaviour,
+ with all the associated security issues.
+
+ X509_TRUST_COMPAT is the old trust behaviour: only and
+ automatically trust self signed roots in certificate store. A
+ new trust setting X509_TRUST_DEFAULT is used to specify that
+ a purpose has no associated trust setting and it should instead
+ use the value in the default purpose.
+
+ *Steve Henson*
+
+ * Fix the PKCS#8 DSA private key code so it decodes keys again
+ and fix a memory leak.
+
+ *Steve Henson*
+
+ * In util/mkerr.pl (which implements 'make errors'), preserve
+ reason strings from the previous version of the .c file, as
+ the default to have only downcase letters (and digits) in
+ automatically generated reasons codes is not always appropriate.
+
+ *Bodo Moeller*
+
+ * In ERR_load_ERR_strings(), build an ERR_LIB_SYS error reason table
+ using strerror. Previously, ERR_reason_error_string() returned
+ library names as reason strings for SYSerr; but SYSerr is a special
+ case where small numbers are errno values, not library numbers.
+
+ *Bodo Moeller*
+
+ * Add '-dsaparam' option to 'openssl dhparam' application. This
+ converts DSA parameters into DH parameters. (When creating parameters,
+ DSA_generate_parameters is used.)
+
+ *Bodo Moeller*
+
+ * Include 'length' (recommended exponent length) in C code generated
+ by 'openssl dhparam -C'.
+
+ *Bodo Moeller*
+
+ * The second argument to set_label in perlasm was already being used
+ so couldn't be used as a "file scope" flag. Moved to third argument
+ which was free.
+
+ *Steve Henson*
+
+ * In PEM_ASN1_write_bio and some other functions, use RAND_pseudo_bytes
+ instead of RAND_bytes for encryption IVs and salts.
+
+ *Bodo Moeller*
+
+ * Include RAND_status() into RAND_METHOD instead of implementing
+ it only for md_rand.c Otherwise replacing the PRNG by calling
+ RAND_set_rand_method would be impossible.
+
+ *Bodo Moeller*
+
+ * Don't let DSA_generate_key() enter an infinite loop if the random
+ number generation fails.
+
+ *Bodo Moeller*
+
+ * New 'rand' application for creating pseudo-random output.
+
+ *Bodo Moeller*
+
+ * Added configuration support for Linux/IA64
+
+ *Rolf Haberrecker <rolf@suse.de>*
+
+ * Assembler module support for Mingw32.
+
+ *Ulf Möller*
+
+ * Shared library support for HPUX (in shlib/).
+
+ *Lutz Jaenicke <Lutz.Jaenicke@aet.TU-Cottbus.DE> and Anonymous*
+
+ * Shared library support for Solaris gcc.
+
+ *Lutz Behnke <behnke@trustcenter.de>*
+
+### Changes between 0.9.4 and 0.9.5 [28 Feb 2000]
+
+ * PKCS7_encrypt() was adding text MIME headers twice because they
+ were added manually and by SMIME_crlf_copy().
+
+ *Steve Henson*
+
+ * In bntest.c don't call BN_rand with zero bits argument.
+
+ *Steve Henson, pointed out by Andrew W. Gray <agray@iconsinc.com>*
+
+ * BN_mul bugfix: In bn_mul_part_recursion() only the a>a[n] && b>b[n]
+ case was implemented. This caused BN_div_recp() to fail occasionally.
+
+ *Ulf Möller*
+
+ * Add an optional second argument to the set_label() in the perl
+ assembly language builder. If this argument exists and is set
+ to 1 it signals that the assembler should use a symbol whose
+ scope is the entire file, not just the current function. This
+ is needed with MASM which uses the format label:: for this scope.
+
+ *Steve Henson, pointed out by Peter Runestig <peter@runestig.com>*
+
+ * Change the ASN1 types so they are typedefs by default. Before
+ almost all types were #define'd to ASN1_STRING which was causing
+ STACK_OF() problems: you couldn't declare STACK_OF(ASN1_UTF8STRING)
+ for example.
+
+ *Steve Henson*
+
+ * Change names of new functions to the new get1/get0 naming
+ convention: After 'get1', the caller owns a reference count
+ and has to call `..._free`; 'get0' returns a pointer to some
+ data structure without incrementing reference counters.
+ (Some of the existing 'get' functions increment a reference
+ counter, some don't.)
+ Similarly, 'set1' and 'add1' functions increase reference
+ counters or duplicate objects.
+
+ *Steve Henson*
+
+ * Allow for the possibility of temp RSA key generation failure:
+ the code used to assume it always worked and crashed on failure.
+
+ *Steve Henson*
+
+ * Fix potential buffer overrun problem in BIO_printf().
+ *Ulf Möller, using public domain code by Patrick Powell; problem
+ pointed out by David Sacerdote <das33@cornell.edu>*
+
+ * Support EGD <http://www.lothar.com/tech/crypto/>. New functions
+ RAND_egd() and RAND_status(). In the command line application,
+ the EGD socket can be specified like a seed file using RANDFILE
+ or -rand.
+
+ *Ulf Möller*
+
+ * Allow the string CERTIFICATE to be tolerated in PKCS#7 structures.
+ Some CAs (e.g. Verisign) distribute certificates in this form.
+
+ *Steve Henson*
+
+ * Remove the SSL_ALLOW_ADH compile option and set the default cipher
+ list to exclude them. This means that no special compilation option
+ is needed to use anonymous DH: it just needs to be included in the
+ cipher list.
+
+ *Steve Henson*
+
+ * Change the EVP_MD_CTX_type macro so its meaning consistent with
+ EVP_MD_type. The old functionality is available in a new macro called
+ EVP_MD_md(). Change code that uses it and update docs.
+
+ *Steve Henson*
+
+ * `..._ctrl` functions now have corresponding `..._callback_ctrl` functions
+ where the `void *` argument is replaced by a function pointer argument.
+ Previously `void *` was abused to point to functions, which works on
+ many platforms, but is not correct. As these functions are usually
+ called by macros defined in OpenSSL header files, most source code
+ should work without changes.
+
+ *Richard Levitte*
+
+ * `<openssl/opensslconf.h>` (which is created by Configure) now contains
+ sections with information on -D... compiler switches used for
+ compiling the library so that applications can see them. To enable
+ one of these sections, a pre-processor symbol `OPENSSL_..._DEFINES`
+ must be defined. E.g.,
+ #define OPENSSL_ALGORITHM_DEFINES
+ #include <openssl/opensslconf.h>
+ defines all pertinent `NO_<algo>` symbols, such as NO_IDEA, NO_RSA, etc.
+
+ *Richard Levitte, Ulf and Bodo Möller*
+
+ * Bugfix: Tolerate fragmentation and interleaving in the SSL 3/TLS
+ record layer.
+
+ *Bodo Moeller*
+
+ * Change the 'other' type in certificate aux info to a STACK_OF
+ X509_ALGOR. Although not an AlgorithmIdentifier as such it has
+ the required ASN1 format: arbitrary types determined by an OID.
+
+ *Steve Henson*
+
+ * Add some PEM_write_X509_REQ_NEW() functions and a command line
+ argument to 'req'. This is not because the function is newer or
+ better than others it just uses the work 'NEW' in the certificate
+ request header lines. Some software needs this.
+
+ *Steve Henson*
+
+ * Reorganise password command line arguments: now passwords can be
+ obtained from various sources. Delete the PEM_cb function and make
+ it the default behaviour: i.e. if the callback is NULL and the
+ usrdata argument is not NULL interpret it as a null terminated pass
+ phrase. If usrdata and the callback are NULL then the pass phrase
+ is prompted for as usual.
+
+ *Steve Henson*
+
+ * Add support for the Compaq Atalla crypto accelerator. If it is installed,
+ the support is automatically enabled. The resulting binaries will
+ autodetect the card and use it if present.
+
+ *Ben Laurie and Compaq Inc.*
+
+ * Work around for Netscape hang bug. This sends certificate request
+ and server done in one record. Since this is perfectly legal in the
+ SSL/TLS protocol it isn't a "bug" option and is on by default. See
+ the bugs/SSLv3 entry for more info.
+
+ *Steve Henson*
+
+ * HP-UX tune-up: new unified configs, HP C compiler bug workaround.
+
+ *Andy Polyakov*
+
+ * Add -rand argument to smime and pkcs12 applications and read/write
+ of seed file.
+
+ *Steve Henson*
+
+ * New 'passwd' tool for crypt(3) and apr1 password hashes.
+
+ *Bodo Moeller*
+
+ * Add command line password options to the remaining applications.
+
+ *Steve Henson*
+
+ * Bug fix for BN_div_recp() for numerators with an even number of
+ bits.
+
+ *Ulf Möller*
+
+ * More tests in bntest.c, and changed test_bn output.
+
+ *Ulf Möller*
+
+ * ./config recognizes MacOS X now.
+
+ *Andy Polyakov*
+
+ * Bug fix for BN_div() when the first words of num and divisor are
+ equal (it gave wrong results if `(rem=(n1-q*d0)&BN_MASK2) < d0)`.
+
+ *Ulf Möller*
+
+ * Add support for various broken PKCS#8 formats, and command line
+ options to produce them.
+
+ *Steve Henson*
+
+ * New functions BN_CTX_start(), BN_CTX_get() and BT_CTX_end() to
+ get temporary BIGNUMs from a BN_CTX.
+
+ *Ulf Möller*
+
+ * Correct return values in BN_mod_exp_mont() and BN_mod_exp2_mont()
+ for p == 0.
+
+ *Ulf Möller*
+
+ * Change the `SSLeay_add_all_*()` functions to `OpenSSL_add_all_*()` and
+ include a #define from the old name to the new. The original intent
+ was that statically linked binaries could for example just call
+ SSLeay_add_all_ciphers() to just add ciphers to the table and not
+ link with digests. This never worked because SSLeay_add_all_digests()
+ and SSLeay_add_all_ciphers() were in the same source file so calling
+ one would link with the other. They are now in separate source files.
+
+ *Steve Henson*
+
+ * Add a new -notext option to 'ca' and a -pubkey option to 'spkac'.
+
+ *Steve Henson*
+
+ * Use a less unusual form of the Miller-Rabin primality test (it used
+ a binary algorithm for exponentiation integrated into the Miller-Rabin
+ loop, our standard modexp algorithms are faster).
+
+ *Bodo Moeller*
+
+ * Support for the EBCDIC character set completed.
+
+ *Martin Kraemer <Martin.Kraemer@Mch.SNI.De>*
+
+ * Source code cleanups: use const where appropriate, eliminate casts,
+ use `void *` instead of `char *` in lhash.
+
+ *Ulf Möller*
+
+ * Bugfix: ssl3_send_server_key_exchange was not restartable
+ (the state was not changed to SSL3_ST_SW_KEY_EXCH_B, and because of
+ this the server could overwrite ephemeral keys that the client
+ has already seen).
+
+ *Bodo Moeller*
+
+ * Turn DSA_is_prime into a macro that calls BN_is_prime,
+ using 50 iterations of the Rabin-Miller test.
+
+ DSA_generate_parameters now uses BN_is_prime_fasttest (with 50
+ iterations of the Rabin-Miller test as required by the appendix
+ to FIPS PUB 186[-1]) instead of DSA_is_prime.
+ As BN_is_prime_fasttest includes trial division, DSA parameter
+ generation becomes much faster.
+
+ This implies a change for the callback functions in DSA_is_prime
+ and DSA_generate_parameters: The callback function is called once
+ for each positive witness in the Rabin-Miller test, not just
+ occasionally in the inner loop; and the parameters to the
+ callback function now provide an iteration count for the outer
+ loop rather than for the current invocation of the inner loop.
+ DSA_generate_parameters additionally can call the callback
+ function with an 'iteration count' of -1, meaning that a
+ candidate has passed the trial division test (when q is generated
+ from an application-provided seed, trial division is skipped).
+
+ *Bodo Moeller*
+
+ * New function BN_is_prime_fasttest that optionally does trial
+ division before starting the Rabin-Miller test and has
+ an additional BN_CTX * argument (whereas BN_is_prime always
+ has to allocate at least one BN_CTX).
+ 'callback(1, -1, cb_arg)' is called when a number has passed the
+ trial division stage.
+
+ *Bodo Moeller*
+
+ * Fix for bug in CRL encoding. The validity dates weren't being handled
+ as ASN1_TIME.
+
+ *Steve Henson*
+
+ * New -pkcs12 option to CA.pl script to write out a PKCS#12 file.
+
+ *Steve Henson*
+
+ * New function BN_pseudo_rand().
+
+ *Ulf Möller*
+
+ * Clean up BN_mod_mul_montgomery(): replace the broken (and unreadable)
+ bignum version of BN_from_montgomery() with the working code from
+ SSLeay 0.9.0 (the word based version is faster anyway), and clean up
+ the comments.
+
+ *Ulf Möller*
+
+ * Avoid a race condition in s2_clnt.c (function get_server_hello) that
+ made it impossible to use the same SSL_SESSION data structure in
+ SSL2 clients in multiple threads.
+
+ *Bodo Moeller*
+
+ * The return value of RAND_load_file() no longer counts bytes obtained
+ by stat(). RAND_load_file(..., -1) is new and uses the complete file
+ to seed the PRNG (previously an explicit byte count was required).
+
+ *Ulf Möller, Bodo Möller*
+
+ * Clean up CRYPTO_EX_DATA functions, some of these didn't have prototypes
+ used `char *` instead of `void *` and had casts all over the place.
+
+ *Steve Henson*
+
+ * Make BN_generate_prime() return NULL on error if ret!=NULL.
+
+ *Ulf Möller*
+
+ * Retain source code compatibility for BN_prime_checks macro:
+ BN_is_prime(..., BN_prime_checks, ...) now uses
+ BN_prime_checks_for_size to determine the appropriate number of
+ Rabin-Miller iterations.
+
+ *Ulf Möller*
+
+ * Diffie-Hellman uses "safe" primes: DH_check() return code renamed to
+ DH_CHECK_P_NOT_SAFE_PRIME.
+ (Check if this is true? OpenPGP calls them "strong".)
+
+ *Ulf Möller*
+
+ * Merge the functionality of "dh" and "gendh" programs into a new program
+ "dhparam". The old programs are retained for now but will handle DH keys
+ (instead of parameters) in future.
+
+ *Steve Henson*
+
+ * Make the ciphers, s_server and s_client programs check the return values
+ when a new cipher list is set.
+
+ *Steve Henson*
+
+ * Enhance the SSL/TLS cipher mechanism to correctly handle the TLS 56bit
+ ciphers. Before when the 56bit ciphers were enabled the sorting was
+ wrong.
+
+ The syntax for the cipher sorting has been extended to support sorting by
+ cipher-strength (using the strength_bits hard coded in the tables).
+ The new command is `@STRENGTH` (see also `doc/apps/ciphers.pod`).
+
+ Fix a bug in the cipher-command parser: when supplying a cipher command
+ string with an "undefined" symbol (neither command nor alphanumeric
+ *A-Za-z0-9*, ssl_set_cipher_list used to hang in an endless loop. Now
+ an error is flagged.
+
+ Due to the strength-sorting extension, the code of the
+ ssl_create_cipher_list() function was completely rearranged. I hope that
+ the readability was also increased :-)
+
+ *Lutz Jaenicke <Lutz.Jaenicke@aet.TU-Cottbus.DE>*
+
+ * Minor change to 'x509' utility. The -CAcreateserial option now uses 1
+ for the first serial number and places 2 in the serial number file. This
+ avoids problems when the root CA is created with serial number zero and
+ the first user certificate has the same issuer name and serial number
+ as the root CA.
+
+ *Steve Henson*
+
+ * Fixes to X509_ATTRIBUTE utilities, change the 'req' program so it uses
+ the new code. Add documentation for this stuff.
+
+ *Steve Henson*
+
+ * Changes to X509_ATTRIBUTE utilities. These have been renamed from
+ `X509_*()` to `X509at_*()` on the grounds that they don't handle X509
+ structures and behave in an analogous way to the X509v3 functions:
+ they shouldn't be called directly but wrapper functions should be used
+ instead.
+
+ So we also now have some wrapper functions that call the X509at functions
+ when passed certificate requests. (TO DO: similar things can be done with
+ PKCS#7 signed and unsigned attributes, PKCS#12 attributes and a few other
+ things. Some of these need some d2i or i2d and print functionality
+ because they handle more complex structures.)
+
+ *Steve Henson*
+
+ * Add missing #ifndefs that caused missing symbols when building libssl
+ as a shared library without RSA. Use #ifndef NO_SSL2 instead of
+ NO_RSA in `ssl/s2*.c`.
+
+ *Kris Kennaway <kris@hub.freebsd.org>, modified by Ulf Möller*
+
+ * Precautions against using the PRNG uninitialized: RAND_bytes() now
+ has a return value which indicates the quality of the random data
+ (1 = ok, 0 = not seeded). Also an error is recorded on the thread's
+ error queue. New function RAND_pseudo_bytes() generates output that is
+ guaranteed to be unique but not unpredictable. RAND_add is like
+ RAND_seed, but takes an extra argument for an entropy estimate
+ (RAND_seed always assumes full entropy).
+
+ *Ulf Möller*
+
+ * Do more iterations of Rabin-Miller probable prime test (specifically,
+ 3 for 1024-bit primes, 6 for 512-bit primes, 12 for 256-bit primes
+ instead of only 2 for all lengths; see BN_prime_checks_for_size definition
+ in crypto/bn/bn_prime.c for the complete table). This guarantees a
+ false-positive rate of at most 2^-80 for random input.
+
+ *Bodo Moeller*
+
+ * Rewrite ssl3_read_n (ssl/s3_pkt.c) avoiding a couple of bugs.
+
+ *Bodo Moeller*
+
+ * New function X509_CTX_rget_chain() (renamed to X509_CTX_get1_chain
+ in the 0.9.5 release), this returns the chain
+ from an X509_CTX structure with a dup of the stack and all
+ the X509 reference counts upped: so the stack will exist
+ after X509_CTX_cleanup() has been called. Modify pkcs12.c
+ to use this.
+
+ Also make SSL_SESSION_print() print out the verify return
+ code.
+
+ *Steve Henson*
+
+ * Add manpage for the pkcs12 command. Also change the default
+ behaviour so MAC iteration counts are used unless the new
+ -nomaciter option is used. This improves file security and
+ only older versions of MSIE (4.0 for example) need it.
+
+ *Steve Henson*
+
+ * Honor the no-xxx Configure options when creating .DEF files.
+
+ *Ulf Möller*
+
+ * Add PKCS#10 attributes to field table: challengePassword,
+ unstructuredName and unstructuredAddress. These are taken from
+ draft PKCS#9 v2.0 but are compatible with v1.2 provided no
+ international characters are used.
+
+ More changes to X509_ATTRIBUTE code: allow the setting of types
+ based on strings. Remove the 'loc' parameter when adding
+ attributes because these will be a SET OF encoding which is sorted
+ in ASN1 order.
+
+ *Steve Henson*
+
+ * Initial changes to the 'req' utility to allow request generation
+ automation. This will allow an application to just generate a template
+ file containing all the field values and have req construct the
+ request.
+
+ Initial support for X509_ATTRIBUTE handling. Stacks of these are
+ used all over the place including certificate requests and PKCS#7
+ structures. They are currently handled manually where necessary with
+ some primitive wrappers for PKCS#7. The new functions behave in a
+ manner analogous to the X509 extension functions: they allow
+ attributes to be looked up by NID and added.
+
+ Later something similar to the X509V3 code would be desirable to
+ automatically handle the encoding, decoding and printing of the
+ more complex types. The string types like challengePassword can
+ be handled by the string table functions.
+
+ Also modified the multi byte string table handling. Now there is
+ a 'global mask' which masks out certain types. The table itself
+ can use the flag STABLE_NO_MASK to ignore the mask setting: this
+ is useful when for example there is only one permissible type
+ (as in countryName) and using the mask might result in no valid
+ types at all.
+
+ *Steve Henson*
+
+ * Clean up 'Finished' handling, and add functions SSL_get_finished and
+ SSL_get_peer_finished to allow applications to obtain the latest
+ Finished messages sent to the peer or expected from the peer,
+ respectively. (SSL_get_peer_finished is usually the Finished message
+ actually received from the peer, otherwise the protocol will be aborted.)
+
+ As the Finished message are message digests of the complete handshake
+ (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can
+ be used for external authentication procedures when the authentication
+ provided by SSL/TLS is not desired or is not enough.
+
+ *Bodo Moeller*
+
+ * Enhanced support for Alpha Linux is added. Now ./config checks if
+ the host supports BWX extension and if Compaq C is present on the
+ $PATH. Just exploiting of the BWX extension results in 20-30%
+ performance kick for some algorithms, e.g. DES and RC4 to mention
+ a couple. Compaq C in turn generates ~20% faster code for MD5 and
+ SHA1.
+
+ *Andy Polyakov*
+
+ * Add support for MS "fast SGC". This is arguably a violation of the
+ SSL3/TLS protocol. Netscape SGC does two handshakes: the first with
+ weak crypto and after checking the certificate is SGC a second one
+ with strong crypto. MS SGC stops the first handshake after receiving
+ the server certificate message and sends a second client hello. Since
+ a server will typically do all the time consuming operations before
+ expecting any further messages from the client (server key exchange
+ is the most expensive) there is little difference between the two.
+
+ To get OpenSSL to support MS SGC we have to permit a second client
+ hello message after we have sent server done. In addition we have to
+ reset the MAC if we do get this second client hello.
+
+ *Steve Henson*
+
+ * Add a function 'd2i_AutoPrivateKey()' this will automatically decide
+ if a DER encoded private key is RSA or DSA traditional format. Changed
+ d2i_PrivateKey_bio() to use it. This is only needed for the "traditional"
+ format DER encoded private key. Newer code should use PKCS#8 format which
+ has the key type encoded in the ASN1 structure. Added DER private key
+ support to pkcs8 application.
+
+ *Steve Henson*
+
+ * SSL 3/TLS 1 servers now don't request certificates when an anonymous
+ ciphersuites has been selected (as required by the SSL 3/TLS 1
+ specifications). Exception: When SSL_VERIFY_FAIL_IF_NO_PEER_CERT
+ is set, we interpret this as a request to violate the specification
+ (the worst that can happen is a handshake failure, and 'correct'
+ behaviour would result in a handshake failure anyway).
+
+ *Bodo Moeller*
+
+ * In SSL_CTX_add_session, take into account that there might be multiple
+ SSL_SESSION structures with the same session ID (e.g. when two threads
+ concurrently obtain them from an external cache).
+ The internal cache can handle only one SSL_SESSION with a given ID,
+ so if there's a conflict, we now throw out the old one to achieve
+ consistency.
+
+ *Bodo Moeller*
+
+ * Add OIDs for idea and blowfish in CBC mode. This will allow both
+ to be used in PKCS#5 v2.0 and S/MIME. Also add checking to
+ some routines that use cipher OIDs: some ciphers do not have OIDs
+ defined and so they cannot be used for S/MIME and PKCS#5 v2.0 for
+ example.
+
+ *Steve Henson*
+
+ * Simplify the trust setting structure and code. Now we just have
+ two sequences of OIDs for trusted and rejected settings. These will
+ typically have values the same as the extended key usage extension
+ and any application specific purposes.
+
+ The trust checking code now has a default behaviour: it will just
+ check for an object with the same NID as the passed id. Functions can
+ be provided to override either the default behaviour or the behaviour
+ for a given id. SSL client, server and email already have functions
+ in place for compatibility: they check the NID and also return "trusted"
+ if the certificate is self signed.
+
+ *Steve Henson*
+
+ * Add d2i,i2d bio/fp functions for PrivateKey: these convert the
+ traditional format into an EVP_PKEY structure.
+
+ *Steve Henson*
+
+ * Add a password callback function PEM_cb() which either prompts for
+ a password if usr_data is NULL or otherwise assumes it is a null
+ terminated password. Allow passwords to be passed on command line
+ environment or config files in a few more utilities.
+
+ *Steve Henson*
+
+ * Add a bunch of DER and PEM functions to handle PKCS#8 format private
+ keys. Add some short names for PKCS#8 PBE algorithms and allow them
+ to be specified on the command line for the pkcs8 and pkcs12 utilities.
+ Update documentation.
+
+ *Steve Henson*
+
+ * Support for ASN1 "NULL" type. This could be handled before by using
+ ASN1_TYPE but there wasn't any function that would try to read a NULL
+ and produce an error if it couldn't. For compatibility we also have
+ ASN1_NULL_new() and ASN1_NULL_free() functions but these are faked and
+ don't allocate anything because they don't need to.
+
+ *Steve Henson*
+
+ * Initial support for MacOS is now provided. Examine INSTALL.MacOS
+ for details.
+
+ *Andy Polyakov, Roy Woods <roy@centicsystems.ca>*
+
+ * Rebuild of the memory allocation routines used by OpenSSL code and
+ possibly others as well. The purpose is to make an interface that
+ provide hooks so anyone can build a separate set of allocation and
+ deallocation routines to be used by OpenSSL, for example memory
+ pool implementations, or something else, which was previously hard
+ since Malloc(), Realloc() and Free() were defined as macros having
+ the values malloc, realloc and free, respectively (except for Win32
+ compilations). The same is provided for memory debugging code.
+ OpenSSL already comes with functionality to find memory leaks, but
+ this gives people a chance to debug other memory problems.
+
+ With these changes, a new set of functions and macros have appeared:
+
+ CRYPTO_set_mem_debug_functions() [F]
+ CRYPTO_get_mem_debug_functions() [F]
+ CRYPTO_dbg_set_options() [F]
+ CRYPTO_dbg_get_options() [F]
+ CRYPTO_malloc_debug_init() [M]
+
+ The memory debug functions are NULL by default, unless the library
+ is compiled with CRYPTO_MDEBUG or friends is defined. If someone
+ wants to debug memory anyway, CRYPTO_malloc_debug_init() (which
+ gives the standard debugging functions that come with OpenSSL) or
+ CRYPTO_set_mem_debug_functions() (tells OpenSSL to use functions
+ provided by the library user) must be used. When the standard
+ debugging functions are used, CRYPTO_dbg_set_options can be used to
+ request additional information:
+ CRYPTO_dbg_set_options(V_CYRPTO_MDEBUG_xxx) corresponds to setting
+ the CRYPTO_MDEBUG_xxx macro when compiling the library.
+
+ Also, things like CRYPTO_set_mem_functions will always give the
+ expected result (the new set of functions is used for allocation
+ and deallocation) at all times, regardless of platform and compiler
+ options.
+
+ To finish it up, some functions that were never use in any other
+ way than through macros have a new API and new semantic:
+
+ CRYPTO_dbg_malloc()
+ CRYPTO_dbg_realloc()
+ CRYPTO_dbg_free()
+
+ All macros of value have retained their old syntax.
+
+ *Richard Levitte and Bodo Moeller*
+
+ * Some S/MIME fixes. The OID for SMIMECapabilities was wrong, the
+ ordering of SMIMECapabilities wasn't in "strength order" and there
+ was a missing NULL in the AlgorithmIdentifier for the SHA1 signature
+ algorithm.
+
+ *Steve Henson*
+
+ * Some ASN1 types with illegal zero length encoding (INTEGER,
+ ENUMERATED and OBJECT IDENTIFIER) choked the ASN1 routines.
+
+ *Frans Heymans <fheymans@isaserver.be>, modified by Steve Henson*
+
+ * Merge in my S/MIME library for OpenSSL. This provides a simple
+ S/MIME API on top of the PKCS#7 code, a MIME parser (with enough
+ functionality to handle multipart/signed properly) and a utility
+ called 'smime' to call all this stuff. This is based on code I
+ originally wrote for Celo who have kindly allowed it to be
+ included in OpenSSL.
+
+ *Steve Henson*
+
+ * Add variants des_set_key_checked and des_set_key_unchecked of
+ des_set_key (aka des_key_sched). Global variable des_check_key
+ decides which of these is called by des_set_key; this way
+ des_check_key behaves as it always did, but applications and
+ the library itself, which was buggy for des_check_key == 1,
+ have a cleaner way to pick the version they need.
+
+ *Bodo Moeller*
+
+ * New function PKCS12_newpass() which changes the password of a
+ PKCS12 structure.
+
+ *Steve Henson*
+
+ * Modify X509_TRUST and X509_PURPOSE so it also uses a static and
+ dynamic mix. In both cases the ids can be used as an index into the
+ table. Also modified the X509_TRUST_add() and X509_PURPOSE_add()
+ functions so they accept a list of the field values and the
+ application doesn't need to directly manipulate the X509_TRUST
+ structure.
+
+ *Steve Henson*
+
+ * Modify the ASN1_STRING_TABLE stuff so it also uses bsearch and doesn't
+ need initialising.
+
+ *Steve Henson*
+
+ * Modify the way the V3 extension code looks up extensions. This now
+ works in a similar way to the object code: we have some "standard"
+ extensions in a static table which is searched with OBJ_bsearch()
+ and the application can add dynamic ones if needed. The file
+ crypto/x509v3/ext_dat.h now has the info: this file needs to be
+ updated whenever a new extension is added to the core code and kept
+ in ext_nid order. There is a simple program 'tabtest.c' which checks
+ this. New extensions are not added too often so this file can readily
+ be maintained manually.
+
+ There are two big advantages in doing things this way. The extensions
+ can be looked up immediately and no longer need to be "added" using
+ X509V3_add_standard_extensions(): this function now does nothing.
+ Side note: I get *lots* of email saying the extension code doesn't
+ work because people forget to call this function.
+ Also no dynamic allocation is done unless new extensions are added:
+ so if we don't add custom extensions there is no need to call
+ X509V3_EXT_cleanup().
+
+ *Steve Henson*
+
+ * Modify enc utility's salting as follows: make salting the default. Add a
+ magic header, so unsalted files fail gracefully instead of just decrypting
+ to garbage. This is because not salting is a big security hole, so people
+ should be discouraged from doing it.
+
+ *Ben Laurie*
+
+ * Fixes and enhancements to the 'x509' utility. It allowed a message
+ digest to be passed on the command line but it only used this
+ parameter when signing a certificate. Modified so all relevant
+ operations are affected by the digest parameter including the
+ -fingerprint and -x509toreq options. Also -x509toreq choked if a
+ DSA key was used because it didn't fix the digest.
+
+ *Steve Henson*
+
+ * Initial certificate chain verify code. Currently tests the untrusted
+ certificates for consistency with the verify purpose (which is set
+ when the X509_STORE_CTX structure is set up) and checks the pathlength.
+
+ There is a NO_CHAIN_VERIFY compilation option to keep the old behaviour:
+ this is because it will reject chains with invalid extensions whereas
+ every previous version of OpenSSL and SSLeay made no checks at all.
+
+ Trust code: checks the root CA for the relevant trust settings. Trust
+ settings have an initial value consistent with the verify purpose: e.g.
+ if the verify purpose is for SSL client use it expects the CA to be
+ trusted for SSL client use. However the default value can be changed to
+ permit custom trust settings: one example of this would be to only trust
+ certificates from a specific "secure" set of CAs.
+
+ Also added X509_STORE_CTX_new() and X509_STORE_CTX_free() functions
+ which should be used for version portability: especially since the
+ verify structure is likely to change more often now.
+
+ SSL integration. Add purpose and trust to SSL_CTX and SSL and functions
+ to set them. If not set then assume SSL clients will verify SSL servers
+ and vice versa.
+
+ Two new options to the verify program: -untrusted allows a set of
+ untrusted certificates to be passed in and -purpose which sets the
+ intended purpose of the certificate. If a purpose is set then the
+ new chain verify code is used to check extension consistency.
+
+ *Steve Henson*
+
+ * Support for the authority information access extension.
+
+ *Steve Henson*
+
+ * Modify RSA and DSA PEM read routines to transparently handle
+ PKCS#8 format private keys. New *_PUBKEY_* functions that handle
+ public keys in a format compatible with certificate
+ SubjectPublicKeyInfo structures. Unfortunately there were already
+ functions called *_PublicKey_* which used various odd formats so
+ these are retained for compatibility: however the DSA variants were
+ never in a public release so they have been deleted. Changed dsa/rsa
+ utilities to handle the new format: note no releases ever handled public
+ keys so we should be OK.
+
+ The primary motivation for this change is to avoid the same fiasco
+ that dogs private keys: there are several incompatible private key
+ formats some of which are standard and some OpenSSL specific and
+ require various evil hacks to allow partial transparent handling and
+ even then it doesn't work with DER formats. Given the option anything
+ other than PKCS#8 should be dumped: but the other formats have to
+ stay in the name of compatibility.
+
+ With public keys and the benefit of hindsight one standard format
+ is used which works with EVP_PKEY, RSA or DSA structures: though
+ it clearly returns an error if you try to read the wrong kind of key.
+
+ Added a -pubkey option to the 'x509' utility to output the public key.
+ Also rename the `EVP_PKEY_get_*()` to `EVP_PKEY_rget_*()`
+ (renamed to `EVP_PKEY_get1_*()` in the OpenSSL 0.9.5 release) and add
+ `EVP_PKEY_rset_*()` functions (renamed to `EVP_PKEY_set1_*()`)
+ that do the same as the `EVP_PKEY_assign_*()` except they up the
+ reference count of the added key (they don't "swallow" the
+ supplied key).
+
+ *Steve Henson*
+
+ * Fixes to crypto/x509/by_file.c the code to read in certificates and
+ CRLs would fail if the file contained no certificates or no CRLs:
+ added a new function to read in both types and return the number
+ read: this means that if none are read it will be an error. The
+ DER versions of the certificate and CRL reader would always fail
+ because it isn't possible to mix certificates and CRLs in DER format
+ without choking one or the other routine. Changed this to just read
+ a certificate: this is the best we can do. Also modified the code
+ in `apps/verify.c` to take notice of return codes: it was previously
+ attempting to read in certificates from NULL pointers and ignoring
+ any errors: this is one reason why the cert and CRL reader seemed
+ to work. It doesn't check return codes from the default certificate
+ routines: these may well fail if the certificates aren't installed.
+
+ *Steve Henson*
+
+ * Code to support otherName option in GeneralName.
+
+ *Steve Henson*
+
+ * First update to verify code. Change the verify utility
+ so it warns if it is passed a self signed certificate:
+ for consistency with the normal behaviour. X509_verify
+ has been modified to it will now verify a self signed
+ certificate if *exactly* the same certificate appears
+ in the store: it was previously impossible to trust a
+ single self signed certificate. This means that:
+ openssl verify ss.pem
+ now gives a warning about a self signed certificate but
+ openssl verify -CAfile ss.pem ss.pem
+ is OK.
+
+ *Steve Henson*
+
+ * For servers, store verify_result in SSL_SESSION data structure
+ (and add it to external session representation).
+ This is needed when client certificate verifications fails,
+ but an application-provided verification callback (set by
+ SSL_CTX_set_cert_verify_callback) allows accepting the session
+ anyway (i.e. leaves x509_store_ctx->error != X509_V_OK
+ but returns 1): When the session is reused, we have to set
+ ssl->verify_result to the appropriate error code to avoid
+ security holes.
+
+ *Bodo Moeller, problem pointed out by Lutz Jaenicke*
+
+ * Fix a bug in the new PKCS#7 code: it didn't consider the
+ case in PKCS7_dataInit() where the signed PKCS7 structure
+ didn't contain any existing data because it was being created.
+
+ *Po-Cheng Chen <pocheng@nst.com.tw>, slightly modified by Steve Henson*
+
+ * Add a salt to the key derivation routines in enc.c. This
+ forms the first 8 bytes of the encrypted file. Also add a
+ -S option to allow a salt to be input on the command line.
+
+ *Steve Henson*
+
+ * New function X509_cmp(). Oddly enough there wasn't a function
+ to compare two certificates. We do this by working out the SHA1
+ hash and comparing that. X509_cmp() will be needed by the trust
+ code.
+
+ *Steve Henson*
+
+ * SSL_get1_session() is like SSL_get_session(), but increments
+ the reference count in the SSL_SESSION returned.
+
+ *Geoff Thorpe <geoff@eu.c2.net>*
+
+ * Fix for 'req': it was adding a null to request attributes.
+ Also change the X509_LOOKUP and X509_INFO code to handle
+ certificate auxiliary information.
+
+ *Steve Henson*
+
+ * Add support for 40 and 64 bit RC2 and RC4 algorithms: document
+ the 'enc' command.
+
+ *Steve Henson*
+
+ * Add the possibility to add extra information to the memory leak
+ detecting output, to form tracebacks, showing from where each
+ allocation was originated: CRYPTO_push_info("constant string") adds
+ the string plus current file name and line number to a per-thread
+ stack, CRYPTO_pop_info() does the obvious, CRYPTO_remove_all_info()
+ is like calling CYRPTO_pop_info() until the stack is empty.
+ Also updated memory leak detection code to be multi-thread-safe.
+
+ *Richard Levitte*
+
+ * Add options -text and -noout to pkcs7 utility and delete the
+ encryption options which never did anything. Update docs.
+
+ *Steve Henson*
+
+ * Add options to some of the utilities to allow the pass phrase
+ to be included on either the command line (not recommended on
+ OSes like Unix) or read from the environment. Update the
+ manpages and fix a few bugs.
+
+ *Steve Henson*
+
+ * Add a few manpages for some of the openssl commands.
+
+ *Steve Henson*
+
+ * Fix the -revoke option in ca. It was freeing up memory twice,
+ leaking and not finding already revoked certificates.
+
+ *Steve Henson*
+
+ * Extensive changes to support certificate auxiliary information.
+ This involves the use of X509_CERT_AUX structure and X509_AUX
+ functions. An X509_AUX function such as PEM_read_X509_AUX()
+ can still read in a certificate file in the usual way but it
+ will also read in any additional "auxiliary information". By
+ doing things this way a fair degree of compatibility can be
+ retained: existing certificates can have this information added
+ using the new 'x509' options.
+
+ Current auxiliary information includes an "alias" and some trust
+ settings. The trust settings will ultimately be used in enhanced
+ certificate chain verification routines: currently a certificate
+ can only be trusted if it is self signed and then it is trusted
+ for all purposes.
+
+ *Steve Henson*
+
+ * Fix assembler for Alpha (tested only on DEC OSF not Linux or `*BSD`).
+ The problem was that one of the replacement routines had not been working
+ since SSLeay releases. For now the offending routine has been replaced
+ with non-optimised assembler. Even so, this now gives around 95%
+ performance improvement for 1024 bit RSA signs.
+
+ *Mark Cox*
+
+ * Hack to fix PKCS#7 decryption when used with some unorthodox RC2
+ handling. Most clients have the effective key size in bits equal to
+ the key length in bits: so a 40 bit RC2 key uses a 40 bit (5 byte) key.
+ A few however don't do this and instead use the size of the decrypted key
+ to determine the RC2 key length and the AlgorithmIdentifier to determine
+ the effective key length. In this case the effective key length can still
+ be 40 bits but the key length can be 168 bits for example. This is fixed
+ by manually forcing an RC2 key into the EVP_PKEY structure because the
+ EVP code can't currently handle unusual RC2 key sizes: it always assumes
+ the key length and effective key length are equal.
+
+ *Steve Henson*
+
+ * Add a bunch of functions that should simplify the creation of
+ X509_NAME structures. Now you should be able to do:
+ X509_NAME_add_entry_by_txt(nm, "CN", MBSTRING_ASC, "Steve", -1, -1, 0);
+ and have it automatically work out the correct field type and fill in
+ the structures. The more adventurous can try:
+ X509_NAME_add_entry_by_txt(nm, field, MBSTRING_UTF8, str, -1, -1, 0);
+ and it will (hopefully) work out the correct multibyte encoding.
+
+ *Steve Henson*
+
+ * Change the 'req' utility to use the new field handling and multibyte
+ copy routines. Before the DN field creation was handled in an ad hoc
+ way in req, ca, and x509 which was rather broken and didn't support
+ BMPStrings or UTF8Strings. Since some software doesn't implement
+ BMPStrings or UTF8Strings yet, they can be enabled using the config file
+ using the dirstring_type option. See the new comment in the default
+ openssl.cnf for more info.
+
+ *Steve Henson*
+
+ * Make crypto/rand/md_rand.c more robust:
+ - Assure unique random numbers after fork().
+ - Make sure that concurrent threads access the global counter and
+ md serializably so that we never lose entropy in them
+ or use exactly the same state in multiple threads.
+ Access to the large state is not always serializable because
+ the additional locking could be a performance killer, and
+ md should be large enough anyway.
+
+ *Bodo Moeller*
+
+ * New file `apps/app_rand.c` with commonly needed functionality
+ for handling the random seed file.
+
+ Use the random seed file in some applications that previously did not:
+ ca,
+ dsaparam -genkey (which also ignored its '-rand' option),
+ s_client,
+ s_server,
+ x509 (when signing).
+ Except on systems with /dev/urandom, it is crucial to have a random
+ seed file at least for key creation, DSA signing, and for DH exchanges;
+ for RSA signatures we could do without one.
+
+ gendh and gendsa (unlike genrsa) used to read only the first byte
+ of each file listed in the '-rand' option. The function as previously
+ found in genrsa is now in app_rand.c and is used by all programs
+ that support '-rand'.
+
+ *Bodo Moeller*
+
+ * In RAND_write_file, use mode 0600 for creating files;
+ don't just chmod when it may be too late.
+
+ *Bodo Moeller*
+
+ * Report an error from X509_STORE_load_locations
+ when X509_LOOKUP_load_file or X509_LOOKUP_add_dir failed.
+
+ *Bill Perry*
+
+ * New function ASN1_mbstring_copy() this copies a string in either
+ ASCII, Unicode, Universal (4 bytes per character) or UTF8 format
+ into an ASN1_STRING type. A mask of permissible types is passed
+ and it chooses the "minimal" type to use or an error if not type
+ is suitable.
+
+ *Steve Henson*
+
+ * Add function equivalents to the various macros in asn1.h. The old
+ macros are retained with an `M_` prefix. Code inside the library can
+ use the `M_` macros. External code (including the openssl utility)
+ should *NOT* in order to be "shared library friendly".
+
+ *Steve Henson*
+
+ * Add various functions that can check a certificate's extensions
+ to see if it usable for various purposes such as SSL client,
+ server or S/MIME and CAs of these types. This is currently
+ VERY EXPERIMENTAL but will ultimately be used for certificate chain
+ verification. Also added a -purpose flag to x509 utility to
+ print out all the purposes.
+
+ *Steve Henson*
+
+ * Add a CRYPTO_EX_DATA to X509 certificate structure and associated
+ functions.
+
+ *Steve Henson*
+
+ * New `X509V3_{X509,CRL,REVOKED}_get_d2i()` functions. These will search
+ for, obtain and decode and extension and obtain its critical flag.
+ This allows all the necessary extension code to be handled in a
+ single function call.
+
+ *Steve Henson*
+
+ * RC4 tune-up featuring 30-40% performance improvement on most RISC
+ platforms. See crypto/rc4/rc4_enc.c for further details.
+
+ *Andy Polyakov*
+
+ * New -noout option to asn1parse. This causes no output to be produced
+ its main use is when combined with -strparse and -out to extract data
+ from a file (which may not be in ASN.1 format).
+
+ *Steve Henson*
+
+ * Fix for pkcs12 program. It was hashing an invalid certificate pointer
+ when producing the local key id.
+
+ *Richard Levitte <levitte@stacken.kth.se>*
+
+ * New option -dhparam in s_server. This allows a DH parameter file to be
+ stated explicitly. If it is not stated then it tries the first server
+ certificate file. The previous behaviour hard coded the filename
+ "server.pem".
+
+ *Steve Henson*
+
+ * Add -pubin and -pubout options to the rsa and dsa commands. These allow
+ a public key to be input or output. For example:
+ openssl rsa -in key.pem -pubout -out pubkey.pem
+ Also added necessary DSA public key functions to handle this.
+
+ *Steve Henson*
+
+ * Fix so PKCS7_dataVerify() doesn't crash if no certificates are contained
+ in the message. This was handled by allowing
+ X509_find_by_issuer_and_serial() to tolerate a NULL passed to it.
+
+ *Steve Henson, reported by Sampo Kellomaki <sampo@mail.neuronio.pt>*
+
+ * Fix for bug in d2i_ASN1_bytes(): other ASN1 functions add an extra null
+ to the end of the strings whereas this didn't. This would cause problems
+ if strings read with d2i_ASN1_bytes() were later modified.
+
+ *Steve Henson, reported by Arne Ansper <arne@ats.cyber.ee>*
+
+ * Fix for base64 decode bug. When a base64 bio reads only one line of
+ data and it contains EOF it will end up returning an error. This is
+ caused by input 46 bytes long. The cause is due to the way base64
+ BIOs find the start of base64 encoded data. They do this by trying a
+ trial decode on each line until they find one that works. When they
+ do a flag is set and it starts again knowing it can pass all the
+ data directly through the decoder. Unfortunately it doesn't reset
+ the context it uses. This means that if EOF is reached an attempt
+ is made to pass two EOFs through the context and this causes the
+ resulting error. This can also cause other problems as well. As is
+ usual with these problems it takes *ages* to find and the fix is
+ trivial: move one line.
+
+ *Steve Henson, reported by ian@uns.ns.ac.yu (Ivan Nejgebauer)*
+
+ * Ugly workaround to get s_client and s_server working under Windows. The
+ old code wouldn't work because it needed to select() on sockets and the
+ tty (for keypresses and to see if data could be written). Win32 only
+ supports select() on sockets so we select() with a 1s timeout on the
+ sockets and then see if any characters are waiting to be read, if none
+ are present then we retry, we also assume we can always write data to
+ the tty. This isn't nice because the code then blocks until we've
+ received a complete line of data and it is effectively polling the
+ keyboard at 1s intervals: however it's quite a bit better than not
+ working at all :-) A dedicated Windows application might handle this
+ with an event loop for example.
+
+ *Steve Henson*
+
+ * Enhance RSA_METHOD structure. Now there are two extra methods, rsa_sign
+ and rsa_verify. When the RSA_FLAGS_SIGN_VER option is set these functions
+ will be called when RSA_sign() and RSA_verify() are used. This is useful
+ if rsa_pub_dec() and rsa_priv_enc() equivalents are not available.
+ For this to work properly RSA_public_decrypt() and RSA_private_encrypt()
+ should *not* be used: RSA_sign() and RSA_verify() must be used instead.
+ This necessitated the support of an extra signature type NID_md5_sha1
+ for SSL signatures and modifications to the SSL library to use it instead
+ of calling RSA_public_decrypt() and RSA_private_encrypt().
+
+ *Steve Henson*
+
+ * Add new -verify -CAfile and -CApath options to the crl program, these
+ will lookup a CRL issuers certificate and verify the signature in a
+ similar way to the verify program. Tidy up the crl program so it
+ no longer accesses structures directly. Make the ASN1 CRL parsing a bit
+ less strict. It will now permit CRL extensions even if it is not
+ a V2 CRL: this will allow it to tolerate some broken CRLs.
+
+ *Steve Henson*
+
+ * Initialize all non-automatic variables each time one of the openssl
+ sub-programs is started (this is necessary as they may be started
+ multiple times from the "OpenSSL>" prompt).
+
+ *Lennart Bang, Bodo Moeller*
+
+ * Preliminary compilation option RSA_NULL which disables RSA crypto without
+ removing all other RSA functionality (this is what NO_RSA does). This
+ is so (for example) those in the US can disable those operations covered
+ by the RSA patent while allowing storage and parsing of RSA keys and RSA
+ key generation.
+
+ *Steve Henson*
+
+ * Non-copying interface to BIO pairs.
+ (still largely untested)
+
+ *Bodo Moeller*
+
+ * New function ASN1_tag2str() to convert an ASN1 tag to a descriptive
+ ASCII string. This was handled independently in various places before.
+
+ *Steve Henson*
+
+ * New functions UTF8_getc() and UTF8_putc() that parse and generate
+ UTF8 strings a character at a time.
+
+ *Steve Henson*
+
+ * Use client_version from client hello to select the protocol
+ (s23_srvr.c) and for RSA client key exchange verification
+ (s3_srvr.c), as required by the SSL 3.0/TLS 1.0 specifications.
+
+ *Bodo Moeller*
+
+ * Add various utility functions to handle SPKACs, these were previously
+ handled by poking round in the structure internals. Added new function
+ NETSCAPE_SPKI_print() to print out SPKAC and a new utility 'spkac' to
+ print, verify and generate SPKACs. Based on an original idea from
+ Massimiliano Pala <madwolf@comune.modena.it> but extensively modified.
+
+ *Steve Henson*
+
+ * RIPEMD160 is operational on all platforms and is back in 'make test'.
+
+ *Andy Polyakov*
+
+ * Allow the config file extension section to be overwritten on the
+ command line. Based on an original idea from Massimiliano Pala
+ <madwolf@comune.modena.it>. The new option is called -extensions
+ and can be applied to ca, req and x509. Also -reqexts to override
+ the request extensions in req and -crlexts to override the crl extensions
+ in ca.
+
+ *Steve Henson*
+
+ * Add new feature to the SPKAC handling in ca. Now you can include
+ the same field multiple times by preceding it by "XXXX." for example:
+ 1.OU="Unit name 1"
+ 2.OU="Unit name 2"
+ this is the same syntax as used in the req config file.
+
+ *Steve Henson*
+
+ * Allow certificate extensions to be added to certificate requests. These
+ are specified in a 'req_extensions' option of the req section of the
+ config file. They can be printed out with the -text option to req but
+ are otherwise ignored at present.
+
+ *Steve Henson*
+
+ * Fix a horrible bug in enc_read() in crypto/evp/bio_enc.c: if the first
+ data read consists of only the final block it would not decrypted because
+ EVP_CipherUpdate() would correctly report zero bytes had been decrypted.
+ A misplaced 'break' also meant the decrypted final block might not be
+ copied until the next read.
+
+ *Steve Henson*
+
+ * Initial support for DH_METHOD. Again based on RSA_METHOD. Also added
+ a few extra parameters to the DH structure: these will be useful if
+ for example we want the value of 'q' or implement X9.42 DH.
+
+ *Steve Henson*
+
+ * Initial support for DSA_METHOD. This is based on the RSA_METHOD and
+ provides hooks that allow the default DSA functions or functions on a
+ "per key" basis to be replaced. This allows hardware acceleration and
+ hardware key storage to be handled without major modification to the
+ library. Also added low-level modexp hooks and CRYPTO_EX structure and
+ associated functions.
+
+ *Steve Henson*
+
+ * Add a new flag to memory BIOs, BIO_FLAG_MEM_RDONLY. This marks the BIO
+ as "read only": it can't be written to and the buffer it points to will
+ not be freed. Reading from a read only BIO is much more efficient than
+ a normal memory BIO. This was added because there are several times when
+ an area of memory needs to be read from a BIO. The previous method was
+ to create a memory BIO and write the data to it, this results in two
+ copies of the data and an O(n^2) reading algorithm. There is a new
+ function BIO_new_mem_buf() which creates a read only memory BIO from
+ an area of memory. Also modified the PKCS#7 routines to use read only
+ memory BIOs.
+
+ *Steve Henson*
+
+ * Bugfix: ssl23_get_client_hello did not work properly when called in
+ state SSL23_ST_SR_CLNT_HELLO_B, i.e. when the first 7 bytes of
+ a SSLv2-compatible client hello for SSLv3 or TLSv1 could be read,
+ but a retry condition occurred while trying to read the rest.
+
+ *Bodo Moeller*
+
+ * The PKCS7_ENC_CONTENT_new() function was setting the content type as
+ NID_pkcs7_encrypted by default: this was wrong since this should almost
+ always be NID_pkcs7_data. Also modified the PKCS7_set_type() to handle
+ the encrypted data type: this is a more sensible place to put it and it
+ allows the PKCS#12 code to be tidied up that duplicated this
+ functionality.
+
+ *Steve Henson*
+
+ * Changed obj_dat.pl script so it takes its input and output files on
+ the command line. This should avoid shell escape redirection problems
+ under Win32.
+
+ *Steve Henson*
+
+ * Initial support for certificate extension requests, these are included
+ in things like Xenroll certificate requests. Included functions to allow
+ extensions to be obtained and added.
+
+ *Steve Henson*
+
+ * -crlf option to s_client and s_server for sending newlines as
+ CRLF (as required by many protocols).
+
+ *Bodo Moeller*
+
+### Changes between 0.9.3a and 0.9.4 [09 Aug 1999]
+
+ * Install libRSAglue.a when OpenSSL is built with RSAref.
+
+ *Ralf S. Engelschall*
+
+ * A few more `#ifndef NO_FP_API / #endif` pairs for consistency.
+
+ *Andrija Antonijevic <TheAntony2@bigfoot.com>*
+
+ * Fix -startdate and -enddate (which was missing) arguments to 'ca'
+ program.
+
+ *Steve Henson*
+
+ * New function DSA_dup_DH, which duplicates DSA parameters/keys as
+ DH parameters/keys (q is lost during that conversion, but the resulting
+ DH parameters contain its length).
+
+ For 1024-bit p, DSA_generate_parameters followed by DSA_dup_DH is
+ much faster than DH_generate_parameters (which creates parameters
+ where `p = 2*q + 1`), and also the smaller q makes DH computations
+ much more efficient (160-bit exponentiation instead of 1024-bit
+ exponentiation); so this provides a convenient way to support DHE
+ ciphersuites in SSL/TLS servers (see ssl/ssltest.c). It is of
+ utter importance to use
+ SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE);
+ or
+ SSL_set_options(s_ctx, SSL_OP_SINGLE_DH_USE);
+ when such DH parameters are used, because otherwise small subgroup
+ attacks may become possible!
+
+ *Bodo Moeller*
+
+ * Avoid memory leak in i2d_DHparams.
+
+ *Bodo Moeller*
+
+ * Allow the -k option to be used more than once in the enc program:
+ this allows the same encrypted message to be read by multiple recipients.
+
+ *Steve Henson*
+
+ * New function OBJ_obj2txt(buf, buf_len, a, no_name), this converts
+ an ASN1_OBJECT to a text string. If the "no_name" parameter is set then
+ it will always use the numerical form of the OID, even if it has a short
+ or long name.
+
+ *Steve Henson*
+
+ * Added an extra RSA flag: RSA_FLAG_EXT_PKEY. Previously the rsa_mod_exp
+ method only got called if p,q,dmp1,dmq1,iqmp components were present,
+ otherwise bn_mod_exp was called. In the case of hardware keys for example
+ no private key components need be present and it might store extra data
+ in the RSA structure, which cannot be accessed from bn_mod_exp.
+ By setting RSA_FLAG_EXT_PKEY rsa_mod_exp will always be called for
+ private key operations.
+
+ *Steve Henson*
+
+ * Added support for SPARC Linux.
+
+ *Andy Polyakov*
+
+ * pem_password_cb function type incompatibly changed from
+ typedef int pem_password_cb(char *buf, int size, int rwflag);
+ to
+ ....(char *buf, int size, int rwflag, void *userdata);
+ so that applications can pass data to their callbacks:
+ The `PEM[_ASN1]_{read,write}...` functions and macros now take an
+ additional void * argument, which is just handed through whenever
+ the password callback is called.
+
+ *Damien Miller <dmiller@ilogic.com.au>; tiny changes by Bodo Moeller*
+
+ New function SSL_CTX_set_default_passwd_cb_userdata.
+
+ Compatibility note: As many C implementations push function arguments
+ onto the stack in reverse order, the new library version is likely to
+ interoperate with programs that have been compiled with the old
+ pem_password_cb definition (PEM_whatever takes some data that
+ happens to be on the stack as its last argument, and the callback
+ just ignores this garbage); but there is no guarantee whatsoever that
+ this will work.
+
+ * The -DPLATFORM="\"$(PLATFORM)\"" definition and the similar -DCFLAGS=...
+ (both in crypto/Makefile.ssl for use by crypto/cversion.c) caused
+ problems not only on Windows, but also on some Unix platforms.
+ To avoid problematic command lines, these definitions are now in an
+ auto-generated file crypto/buildinf.h (created by crypto/Makefile.ssl
+ for standard "make" builds, by util/mk1mf.pl for "mk1mf" builds).
+
+ *Bodo Moeller*
+
+ * MIPS III/IV assembler module is reimplemented.
+
+ *Andy Polyakov*
+
+ * More DES library cleanups: remove references to srand/rand and
+ delete an unused file.
+
+ *Ulf Möller*
+
+ * Add support for the free Netwide assembler (NASM) under Win32,
+ since not many people have MASM (ml) and it can be hard to obtain.
+ This is currently experimental but it seems to work OK and pass all
+ the tests. Check out INSTALL.W32 for info.
+
+ *Steve Henson*
+
+ * Fix memory leaks in s3_clnt.c: All non-anonymous SSL3/TLS1 connections
+ without temporary keys kept an extra copy of the server key,
+ and connections with temporary keys did not free everything in case
+ of an error.
+
+ *Bodo Moeller*
+
+ * New function RSA_check_key and new openssl rsa option -check
+ for verifying the consistency of RSA keys.
+
+ *Ulf Moeller, Bodo Moeller*
+
+ * Various changes to make Win32 compile work:
+ 1. Casts to avoid "loss of data" warnings in p5_crpt2.c
+ 2. Change unsigned int to int in b_dump.c to avoid "signed/unsigned
+ comparison" warnings.
+ 3. Add `sk_<TYPE>_sort` to DEF file generator and do make update.
+
+ *Steve Henson*
+
+ * Add a debugging option to PKCS#5 v2 key generation function: when
+ you #define DEBUG_PKCS5V2 passwords, salts, iteration counts and
+ derived keys are printed to stderr.
+
+ *Steve Henson*
+
+ * Copy the flags in ASN1_STRING_dup().
+
+ *Roman E. Pavlov <pre@mo.msk.ru>*
+
+ * The x509 application mishandled signing requests containing DSA
+ keys when the signing key was also DSA and the parameters didn't match.
+
+ It was supposed to omit the parameters when they matched the signing key:
+ the verifying software was then supposed to automatically use the CA's
+ parameters if they were absent from the end user certificate.
+
+ Omitting parameters is no longer recommended. The test was also
+ the wrong way round! This was probably due to unusual behaviour in
+ EVP_cmp_parameters() which returns 1 if the parameters match.
+ This meant that parameters were omitted when they *didn't* match and
+ the certificate was useless. Certificates signed with 'ca' didn't have
+ this bug.
+
+ *Steve Henson, reported by Doug Erickson <Doug.Erickson@Part.NET>*
+
+ * Memory leak checking (-DCRYPTO_MDEBUG) had some problems.
+ The interface is as follows:
+ Applications can use
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON) aka MemCheck_start(),
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF) aka MemCheck_stop();
+ "off" is now the default.
+ The library internally uses
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE) aka MemCheck_off(),
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE) aka MemCheck_on()
+ to disable memory-checking temporarily.
+
+ Some inconsistent states that previously were possible (and were
+ even the default) are now avoided.
+
+ -DCRYPTO_MDEBUG_TIME is new and additionally stores the current time
+ with each memory chunk allocated; this is occasionally more helpful
+ than just having a counter.
+
+ -DCRYPTO_MDEBUG_THREAD is also new and adds the thread ID.
+
+ -DCRYPTO_MDEBUG_ALL enables all of the above, plus any future
+ extensions.
+
+ *Bodo Moeller*
+
+ * Introduce "mode" for SSL structures (with defaults in SSL_CTX),
+ which largely parallels "options", but is for changing API behaviour,
+ whereas "options" are about protocol behaviour.
+ Initial "mode" flags are:
+
+ SSL_MODE_ENABLE_PARTIAL_WRITE Allow SSL_write to report success when
+ a single record has been written.
+ SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER Don't insist that SSL_write
+ retries use the same buffer location.
+ (But all of the contents must be
+ copied!)
+
+ *Bodo Moeller*
+
+ * Bugfix: SSL_set_options ignored its parameter, only SSL_CTX_set_options
+ worked.
+
+ * Fix problems with no-hmac etc.
+
+ *Ulf Möller, pointed out by Brian Wellington <bwelling@tislabs.com>*
+
+ * New functions RSA_get_default_method(), RSA_set_method() and
+ RSA_get_method(). These allows replacement of RSA_METHODs without having
+ to mess around with the internals of an RSA structure.
+
+ *Steve Henson*
+
+ * Fix memory leaks in DSA_do_sign and DSA_is_prime.
+ Also really enable memory leak checks in openssl.c and in some
+ test programs.
+
+ *Chad C. Mulligan, Bodo Moeller*
+
+ * Fix a bug in d2i_ASN1_INTEGER() and i2d_ASN1_INTEGER() which can mess
+ up the length of negative integers. This has now been simplified to just
+ store the length when it is first determined and use it later, rather
+ than trying to keep track of where data is copied and updating it to
+ point to the end.
+ *Steve Henson, reported by Brien Wheeler <bwheeler@authentica-security.com>*
+
+ * Add a new function PKCS7_signatureVerify. This allows the verification
+ of a PKCS#7 signature but with the signing certificate passed to the
+ function itself. This contrasts with PKCS7_dataVerify which assumes the
+ certificate is present in the PKCS#7 structure. This isn't always the
+ case: certificates can be omitted from a PKCS#7 structure and be
+ distributed by "out of band" means (such as a certificate database).
+
+ *Steve Henson*
+
+ * Complete the `PEM_*` macros with DECLARE_PEM versions to replace the
+ function prototypes in pem.h, also change util/mkdef.pl to add the
+ necessary function names.
+
+ *Steve Henson*
+
+ * mk1mf.pl (used by Windows builds) did not properly read the
+ options set by Configure in the top level Makefile, and Configure
+ was not even able to write more than one option correctly.
+ Fixed, now "no-idea no-rc5 -DCRYPTO_MDEBUG" etc. works as intended.
+
+ *Bodo Moeller*
+
+ * New functions CONF_load_bio() and CONF_load_fp() to allow a config
+ file to be loaded from a BIO or FILE pointer. The BIO version will
+ for example allow memory BIOs to contain config info.
+
+ *Steve Henson*
+
+ * New function "CRYPTO_num_locks" that returns CRYPTO_NUM_LOCKS.
+ Whoever hopes to achieve shared-library compatibility across versions
+ must use this, not the compile-time macro.
+ (Exercise 0.9.4: Which is the minimum library version required by
+ such programs?)
+ Note: All this applies only to multi-threaded programs, others don't
+ need locks.
+
+ *Bodo Moeller*
+
+ * Add missing case to s3_clnt.c state machine -- one of the new SSL tests
+ through a BIO pair triggered the default case, i.e.
+ SSLerr(...,SSL_R_UNKNOWN_STATE).
+
+ *Bodo Moeller*
+
+ * New "BIO pair" concept (crypto/bio/bss_bio.c) so that applications
+ can use the SSL library even if none of the specific BIOs is
+ appropriate.
+
+ *Bodo Moeller*
+
+ * Fix a bug in i2d_DSAPublicKey() which meant it returned the wrong value
+ for the encoded length.
+
+ *Jeon KyoungHo <khjeon@sds.samsung.co.kr>*
+
+ * Add initial documentation of the X509V3 functions.
+
+ *Steve Henson*
+
+ * Add a new pair of functions PEM_write_PKCS8PrivateKey() and
+ PEM_write_bio_PKCS8PrivateKey() that are equivalent to
+ PEM_write_PrivateKey() and PEM_write_bio_PrivateKey() but use the more
+ secure PKCS#8 private key format with a high iteration count.
+
+ *Steve Henson*
+
+ * Fix determination of Perl interpreter: A perl or perl5
+ *directory* in $PATH was also accepted as the interpreter.
+
+ *Ralf S. Engelschall*
+
+ * Fix demos/sign/sign.c: well there wasn't anything strictly speaking
+ wrong with it but it was very old and did things like calling
+ PEM_ASN1_read() directly and used MD5 for the hash not to mention some
+ unusual formatting.
+
+ *Steve Henson*
+
+ * Fix demos/selfsign.c: it used obsolete and deleted functions, changed
+ to use the new extension code.
+
+ *Steve Henson*
+
+ * Implement the PEM_read/PEM_write functions in crypto/pem/pem_all.c
+ with macros. This should make it easier to change their form, add extra
+ arguments etc. Fix a few PEM prototypes which didn't have cipher as a
+ constant.
+
+ *Steve Henson*
+
+ * Add to configuration table a new entry that can specify an alternative
+ name for unistd.h (for pre-POSIX systems); we need this for NeXTstep,
+ according to Mark Crispin <MRC@Panda.COM>.
+
+ *Bodo Moeller*
+
+ * DES CBC did not update the IV. Weird.
+
+ *Ben Laurie*
+lse
+ des_cbc_encrypt does not update the IV, but des_ncbc_encrypt does.
+ Changing the behaviour of the former might break existing programs --
+ where IV updating is needed, des_ncbc_encrypt can be used.
+ndif
+
+ * When bntest is run from "make test" it drives bc to check its
+ calculations, as well as internally checking them. If an internal check
+ fails, it needs to cause bc to give a non-zero result or make test carries
+ on without noticing the failure. Fixed.
+
+ *Ben Laurie*
+
+ * DES library cleanups.
+
+ *Ulf Möller*
+
+ * Add support for PKCS#5 v2.0 PBE algorithms. This will permit PKCS#8 to be
+ used with any cipher unlike PKCS#5 v1.5 which can at most handle 64 bit
+ ciphers. NOTE: although the key derivation function has been verified
+ against some published test vectors it has not been extensively tested
+ yet. Added a -v2 "cipher" option to pkcs8 application to allow the use
+ of v2.0.
+
+ *Steve Henson*
+
+ * Instead of "mkdir -p", which is not fully portable, use new
+ Perl script "util/mkdir-p.pl".
+
+ *Bodo Moeller*
+
+ * Rewrite the way password based encryption (PBE) is handled. It used to
+ assume that the ASN1 AlgorithmIdentifier parameter was a PBEParameter
+ structure. This was true for the PKCS#5 v1.5 and PKCS#12 PBE algorithms
+ but doesn't apply to PKCS#5 v2.0 where it can be something else. Now
+ the 'parameter' field of the AlgorithmIdentifier is passed to the
+ underlying key generation function so it must do its own ASN1 parsing.
+ This has also changed the EVP_PBE_CipherInit() function which now has a
+ 'parameter' argument instead of literal salt and iteration count values
+ and the function EVP_PBE_ALGOR_CipherInit() has been deleted.
+
+ *Steve Henson*
+
+ * Support for PKCS#5 v1.5 compatible password based encryption algorithms
+ and PKCS#8 functionality. New 'pkcs8' application linked to openssl.
+ Needed to change the PEM_STRING_EVP_PKEY value which was just "PRIVATE
+ KEY" because this clashed with PKCS#8 unencrypted string. Since this
+ value was just used as a "magic string" and not used directly its
+ value doesn't matter.
+
+ *Steve Henson*
+
+ * Introduce some semblance of const correctness to BN. Shame C doesn't
+ support mutable.
+
+ *Ben Laurie*
+
+ * "linux-sparc64" configuration (ultrapenguin).
+
+ *Ray Miller <ray.miller@oucs.ox.ac.uk>*
+ "linux-sparc" configuration.
+
+ *Christian Forster <fo@hawo.stw.uni-erlangen.de>*
+
+ * config now generates no-xxx options for missing ciphers.
+
+ *Ulf Möller*
+
+ * Support the EBCDIC character set (work in progress).
+ File ebcdic.c not yet included because it has a different license.
+
+ *Martin Kraemer <Martin.Kraemer@MchP.Siemens.De>*
+
+ * Support BS2000/OSD-POSIX.
+
+ *Martin Kraemer <Martin.Kraemer@MchP.Siemens.De>*
+
+ * Make callbacks for key generation use `void *` instead of `char *`.
+
+ *Ben Laurie*
+
+ * Make S/MIME samples compile (not yet tested).
+
+ *Ben Laurie*
+
+ * Additional typesafe stacks.
+
+ *Ben Laurie*
+
+ * New configuration variants "bsdi-elf-gcc" (BSD/OS 4.x).
+
+ *Bodo Moeller*
+
+### Changes between 0.9.3 and 0.9.3a [29 May 1999]
+
+ * New configuration variant "sco5-gcc".
+
+ * Updated some demos.
+
+ *Sean O Riordain, Wade Scholine*
+
+ * Add missing BIO_free at exit of pkcs12 application.
+
+ *Wu Zhigang*
+
+ * Fix memory leak in conf.c.
+
+ *Steve Henson*
+
+ * Updates for Win32 to assembler version of MD5.
+
+ *Steve Henson*
+
+ * Set #! path to perl in `apps/der_chop` to where we found it
+ instead of using a fixed path.
+
+ *Bodo Moeller*
+
+ * SHA library changes for irix64-mips4-cc.
+
+ *Andy Polyakov*
+
+ * Improvements for VMS support.
+
+ *Richard Levitte*
+
+### Changes between 0.9.2b and 0.9.3 [24 May 1999]
+
+ * Bignum library bug fix. IRIX 6 passes "make test" now!
+ This also avoids the problems with SC4.2 and unpatched SC5.
+
+ *Andy Polyakov <appro@fy.chalmers.se>*
+
+ * New functions sk_num, sk_value and sk_set to replace the previous macros.
+ These are required because of the typesafe stack would otherwise break
+ existing code. If old code used a structure member which used to be STACK
+ and is now STACK_OF (for example cert in a PKCS7_SIGNED structure) with
+ sk_num or sk_value it would produce an error because the num, data members
+ are not present in STACK_OF. Now it just produces a warning. sk_set
+ replaces the old method of assigning a value to sk_value
+ (e.g. sk_value(x, i) = y) which the library used in a few cases. Any code
+ that does this will no longer work (and should use sk_set instead) but
+ this could be regarded as a "questionable" behaviour anyway.
+
+ *Steve Henson*
+
+ * Fix most of the other PKCS#7 bugs. The "experimental" code can now
+ correctly handle encrypted S/MIME data.
+
+ *Steve Henson*
+
+ * Change type of various DES function arguments from des_cblock
+ (which means, in function argument declarations, pointer to char)
+ to des_cblock * (meaning pointer to array with 8 char elements),
+ which allows the compiler to do more typechecking; it was like
+ that back in SSLeay, but with lots of ugly casts.
+
+ Introduce new type const_des_cblock.
+
+ *Bodo Moeller*
+
+ * Reorganise the PKCS#7 library and get rid of some of the more obvious
+ problems: find RecipientInfo structure that matches recipient certificate
+ and initialise the ASN1 structures properly based on passed cipher.
+
+ *Steve Henson*
+
+ * Belatedly make the BN tests actually check the results.
+
+ *Ben Laurie*
+
+ * Fix the encoding and decoding of negative ASN1 INTEGERS and conversion
+ to and from BNs: it was completely broken. New compilation option
+ NEG_PUBKEY_BUG to allow for some broken certificates that encode public
+ key elements as negative integers.
+
+ *Steve Henson*
+
+ * Reorganize and speed up MD5.
+
+ *Andy Polyakov <appro@fy.chalmers.se>*
+
+ * VMS support.
+
+ *Richard Levitte <richard@levitte.org>*
+
+ * New option -out to asn1parse to allow the parsed structure to be
+ output to a file. This is most useful when combined with the -strparse
+ option to examine the output of things like OCTET STRINGS.
+
+ *Steve Henson*
+
+ * Make SSL library a little more fool-proof by not requiring any longer
+ that `SSL_set_{accept,connect}_state` be called before
+ `SSL_{accept,connect}` may be used (`SSL_set_..._state` is omitted
+ in many applications because usually everything *appeared* to work as
+ intended anyway -- now it really works as intended).
+
+ *Bodo Moeller*
+
+ * Move openssl.cnf out of lib/.
+
+ *Ulf Möller*
+
+ * Fix various things to let OpenSSL even pass "egcc -pipe -O2 -Wall
+ -Wshadow -Wpointer-arith -Wcast-align -Wmissing-prototypes
+ -Wmissing-declarations -Wnested-externs -Winline" with EGCS 1.1.2+
+
+ *Ralf S. Engelschall*
+
+ * Various fixes to the EVP and PKCS#7 code. It may now be able to
+ handle PKCS#7 enveloped data properly.
+
+ *Sebastian Akerman <sak@parallelconsulting.com>, modified by Steve*
+
+ * Create a duplicate of the SSL_CTX's CERT in SSL_new instead of
+ copying pointers. The cert_st handling is changed by this in
+ various ways (and thus what used to be known as ctx->default_cert
+ is now called ctx->cert, since we don't resort to `s->ctx->[default_]cert`
+ any longer when s->cert does not give us what we need).
+ ssl_cert_instantiate becomes obsolete by this change.
+ As soon as we've got the new code right (possibly it already is?),
+ we have solved a couple of bugs of the earlier code where s->cert
+ was used as if it could not have been shared with other SSL structures.
+
+ Note that using the SSL API in certain dirty ways now will result
+ in different behaviour than observed with earlier library versions:
+ Changing settings for an `SSL_CTX *ctx` after having done s = SSL_new(ctx)
+ does not influence s as it used to.
+
+ In order to clean up things more thoroughly, inside SSL_SESSION
+ we don't use CERT any longer, but a new structure SESS_CERT
+ that holds per-session data (if available); currently, this is
+ the peer's certificate chain and, for clients, the server's certificate
+ and temporary key. CERT holds only those values that can have
+ meaningful defaults in an SSL_CTX.
+
+ *Bodo Moeller*
+
+ * New function X509V3_EXT_i2d() to create an X509_EXTENSION structure
+ from the internal representation. Various PKCS#7 fixes: remove some
+ evil casts and set the enc_dig_alg field properly based on the signing
+ key type.
+
+ *Steve Henson*
+
+ * Allow PKCS#12 password to be set from the command line or the
+ environment. Let 'ca' get its config file name from the environment
+ variables "OPENSSL_CONF" or "SSLEAY_CONF" (for consistency with 'req'
+ and 'x509').
+
+ *Steve Henson*
+
+ * Allow certificate policies extension to use an IA5STRING for the
+ organization field. This is contrary to the PKIX definition but
+ VeriSign uses it and IE5 only recognises this form. Document 'x509'
+ extension option.
+
+ *Steve Henson*
+
+ * Add PEDANTIC compiler flag to allow compilation with gcc -pedantic,
+ without disallowing inline assembler and the like for non-pedantic builds.
+
+ *Ben Laurie*
+
+ * Support Borland C++ builder.
+
+ *Janez Jere <jj@void.si>, modified by Ulf Möller*
+
+ * Support Mingw32.
+
+ *Ulf Möller*
+
+ * SHA-1 cleanups and performance enhancements.
+
+ *Andy Polyakov <appro@fy.chalmers.se>*
+
+ * Sparc v8plus assembler for the bignum library.
+
+ *Andy Polyakov <appro@fy.chalmers.se>*
+
+ * Accept any -xxx and +xxx compiler options in Configure.
+
+ *Ulf Möller*
+
+ * Update HPUX configuration.
+
+ *Anonymous*
+
+ * Add missing `sk_<type>_unshift()` function to safestack.h
+
+ *Ralf S. Engelschall*
+
+ * New function SSL_CTX_use_certificate_chain_file that sets the
+ "extra_cert"s in addition to the certificate. (This makes sense
+ only for "PEM" format files, as chains as a whole are not
+ DER-encoded.)
+
+ *Bodo Moeller*
+
+ * Support verify_depth from the SSL API.
+ x509_vfy.c had what can be considered an off-by-one-error:
+ Its depth (which was not part of the external interface)
+ was actually counting the number of certificates in a chain;
+ now it really counts the depth.
+
+ *Bodo Moeller*
+
+ * Bugfix in crypto/x509/x509_cmp.c: The SSLerr macro was used
+ instead of X509err, which often resulted in confusing error
+ messages since the error codes are not globally unique
+ (e.g. an alleged error in ssl3_accept when a certificate
+ didn't match the private key).
+
+ * New function SSL_CTX_set_session_id_context that allows to set a default
+ value (so that you don't need SSL_set_session_id_context for each
+ connection using the SSL_CTX).
+
+ *Bodo Moeller*
+
+ * OAEP decoding bug fix.
+
+ *Ulf Möller*
+
+ * Support INSTALL_PREFIX for package builders, as proposed by
+ David Harris.
+
+ *Bodo Moeller*
+
+ * New Configure options "threads" and "no-threads". For systems
+ where the proper compiler options are known (currently Solaris
+ and Linux), "threads" is the default.
+
+ *Bodo Moeller*
+
+ * New script util/mklink.pl as a faster substitute for util/mklink.sh.
+
+ *Bodo Moeller*
+
+ * Install various scripts to $(OPENSSLDIR)/misc, not to
+ $(INSTALLTOP)/bin -- they shouldn't clutter directories
+ such as /usr/local/bin.
+
+ *Bodo Moeller*
+
+ * "make linux-shared" to build shared libraries.
+
+ *Niels Poppe <niels@netbox.org>*
+
+ * New Configure option `no-<cipher>` (rsa, idea, rc5, ...).
+
+ *Ulf Möller*
+
+ * Add the PKCS#12 API documentation to openssl.txt. Preliminary support for
+ extension adding in x509 utility.
+
+ *Steve Henson*
+
+ * Remove NOPROTO sections and error code comments.
+
+ *Ulf Möller*
+
+ * Partial rewrite of the DEF file generator to now parse the ANSI
+ prototypes.
+
+ *Steve Henson*
+
+ * New Configure options --prefix=DIR and --openssldir=DIR.
+
+ *Ulf Möller*
+
+ * Complete rewrite of the error code script(s). It is all now handled
+ by one script at the top level which handles error code gathering,
+ header rewriting and C source file generation. It should be much better
+ than the old method: it now uses a modified version of Ulf's parser to
+ read the ANSI prototypes in all header files (thus the old K&R definitions
+ aren't needed for error creation any more) and do a better job of
+ translating function codes into names. The old 'ASN1 error code embedded
+ in a comment' is no longer necessary and it doesn't use .err files which
+ have now been deleted. Also the error code call doesn't have to appear all
+ on one line (which resulted in some large lines...).
+
+ *Steve Henson*
+
+ * Change #include filenames from `<foo.h>` to `<openssl/foo.h>`.
+
+ *Bodo Moeller*
+
+ * Change behaviour of ssl2_read when facing length-0 packets: Don't return
+ 0 (which usually indicates a closed connection), but continue reading.
+
+ *Bodo Moeller*
+
+ * Fix some race conditions.
+
+ *Bodo Moeller*
+
+ * Add support for CRL distribution points extension. Add Certificate
+ Policies and CRL distribution points documentation.
+
+ *Steve Henson*
+
+ * Move the autogenerated header file parts to crypto/opensslconf.h.
+
+ *Ulf Möller*
+
+ * Fix new 56-bit DES export ciphersuites: they were using 7 bytes instead of
+ 8 of keying material. Merlin has also confirmed interop with this fix
+ between OpenSSL and Baltimore C/SSL 2.0 and J/SSL 2.0.
+
+ *Merlin Hughes <merlin@baltimore.ie>*
+
+ * Fix lots of warnings.
+
+ *Richard Levitte <levitte@stacken.kth.se>*
+
+ * In add_cert_dir() in crypto/x509/by_dir.c, break out of the loop if
+ the directory spec didn't end with a LIST_SEPARATOR_CHAR.
+
+ *Richard Levitte <levitte@stacken.kth.se>*
+
+ * Fix problems with sizeof(long) == 8.
+
+ *Andy Polyakov <appro@fy.chalmers.se>*
+
+ * Change functions to ANSI C.
+
+ *Ulf Möller*
+
+ * Fix typos in error codes.
+
+ *Martin Kraemer <Martin.Kraemer@MchP.Siemens.De>, Ulf Möller*
+
+ * Remove defunct assembler files from Configure.
+
+ *Ulf Möller*
+
+ * SPARC v8 assembler BIGNUM implementation.
+
+ *Andy Polyakov <appro@fy.chalmers.se>*
+
+ * Support for Certificate Policies extension: both print and set.
+ Various additions to support the r2i method this uses.
+
+ *Steve Henson*
+
+ * A lot of constification, and fix a bug in X509_NAME_oneline() that could
+ return a const string when you are expecting an allocated buffer.
+
+ *Ben Laurie*
+
+ * Add support for ASN1 types UTF8String and VISIBLESTRING, also the CHOICE
+ types DirectoryString and DisplayText.
+
+ *Steve Henson*
+
+ * Add code to allow r2i extensions to access the configuration database,
+ add an LHASH database driver and add several ctx helper functions.
+
+ *Steve Henson*
+
+ * Fix an evil bug in bn_expand2() which caused various BN functions to
+ fail when they extended the size of a BIGNUM.
+
+ *Steve Henson*
+
+ * Various utility functions to handle SXNet extension. Modify mkdef.pl to
+ support typesafe stack.
+
+ *Steve Henson*
+
+ * Fix typo in SSL_[gs]et_options().
+
+ *Nils Frostberg <nils@medcom.se>*
+
+ * Delete various functions and files that belonged to the (now obsolete)
+ old X509V3 handling code.
+
+ *Steve Henson*
+
+ * New Configure option "rsaref".
+
+ *Ulf Möller*
+
+ * Don't auto-generate pem.h.
+
+ *Bodo Moeller*
+
+ * Introduce type-safe ASN.1 SETs.
+
+ *Ben Laurie*
+
+ * Convert various additional casted stacks to type-safe STACK_OF() variants.
+
+ *Ben Laurie, Ralf S. Engelschall, Steve Henson*
+
+ * Introduce type-safe STACKs. This will almost certainly break lots of code
+ that links with OpenSSL (well at least cause lots of warnings), but fear
+ not: the conversion is trivial, and it eliminates loads of evil casts. A
+ few STACKed things have been converted already. Feel free to convert more.
+ In the fullness of time, I'll do away with the STACK type altogether.
+
+ *Ben Laurie*
+
+ * Add `openssl ca -revoke <certfile>` facility which revokes a certificate
+ specified in `<certfile>` by updating the entry in the index.txt file.
+ This way one no longer has to edit the index.txt file manually for
+ revoking a certificate. The -revoke option does the gory details now.
+
+ *Massimiliano Pala <madwolf@openca.org>, Ralf S. Engelschall*
+
+ * Fix `openssl crl -noout -text` combination where `-noout` killed the
+ `-text` option at all and this way the `-noout -text` combination was
+ inconsistent in `openssl crl` with the friends in `openssl x509|rsa|dsa`.
+
+ *Ralf S. Engelschall*
+
+ * Make sure a corresponding plain text error message exists for the
+ X509_V_ERR_CERT_REVOKED/23 error number which can occur when a
+ verify callback function determined that a certificate was revoked.
+
+ *Ralf S. Engelschall*
+
+ * Bugfix: In test/testenc, don't test `openssl <cipher>` for
+ ciphers that were excluded, e.g. by -DNO_IDEA. Also, test
+ all available ciphers including rc5, which was forgotten until now.
+ In order to let the testing shell script know which algorithms
+ are available, a new (up to now undocumented) command
+ `openssl list-cipher-commands` is used.
+
+ *Bodo Moeller*
+
+ * Bugfix: s_client occasionally would sleep in select() when
+ it should have checked SSL_pending() first.
+
+ *Bodo Moeller*
+
+ * New functions DSA_do_sign and DSA_do_verify to provide access to
+ the raw DSA values prior to ASN.1 encoding.
+
+ *Ulf Möller*
+
+ * Tweaks to Configure
+
+ *Niels Poppe <niels@netbox.org>*
+
+ * Add support for PKCS#5 v2.0 ASN1 PBES2 structures. No other support,
+ yet...
+
+ *Steve Henson*
+
+ * New variables $(RANLIB) and $(PERL) in the Makefiles.
+
+ *Ulf Möller*
+
+ * New config option to avoid instructions that are illegal on the 80386.
+ The default code is faster, but requires at least a 486.
+
+ *Ulf Möller*
+
+ * Got rid of old SSL2_CLIENT_VERSION (inconsistently used) and
+ SSL2_SERVER_VERSION (not used at all) macros, which are now the
+ same as SSL2_VERSION anyway.
+
+ *Bodo Moeller*
+
+ * New "-showcerts" option for s_client.
+
+ *Bodo Moeller*
+
+ * Still more PKCS#12 integration. Add pkcs12 application to openssl
+ application. Various cleanups and fixes.
+
+ *Steve Henson*
+
+ * More PKCS#12 integration. Add new pkcs12 directory with Makefile.ssl and
+ modify error routines to work internally. Add error codes and PBE init
+ to library startup routines.
+
+ *Steve Henson*
+
+ * Further PKCS#12 integration. Added password based encryption, PKCS#8 and
+ packing functions to asn1 and evp. Changed function names and error
+ codes along the way.
+
+ *Steve Henson*
+
+ * PKCS12 integration: and so it begins... First of several patches to
+ slowly integrate PKCS#12 functionality into OpenSSL. Add PKCS#12
+ objects to objects.h
+
+ *Steve Henson*
+
+ * Add a new 'indent' option to some X509V3 extension code. Initial ASN1
+ and display support for Thawte strong extranet extension.
+
+ *Steve Henson*
+
+ * Add LinuxPPC support.
+
+ *Jeff Dubrule <igor@pobox.org>*
+
+ * Get rid of redundant BN file bn_mulw.c, and rename bn_div64 to
+ bn_div_words in alpha.s.
+
+ *Hannes Reinecke <H.Reinecke@hw.ac.uk> and Ben Laurie*
+
+ * Make sure the RSA OAEP test is skipped under -DRSAref because
+ OAEP isn't supported when OpenSSL is built with RSAref.
+
+ *Ulf Moeller <ulf@fitug.de>*
+
+ * Move definitions of IS_SET/IS_SEQUENCE inside crypto/asn1/asn1.h
+ so they no longer are missing under -DNOPROTO.
+
+ *Soren S. Jorvang <soren@t.dk>*
+
+### Changes between 0.9.1c and 0.9.2b [22 Mar 1999]
+
+ * Make SSL_get_peer_cert_chain() work in servers. Unfortunately, it still
+ doesn't work when the session is reused. Coming soon!
+
+ *Ben Laurie*
+
+ * Fix a security hole, that allows sessions to be reused in the wrong
+ context thus bypassing client cert protection! All software that uses
+ client certs and session caches in multiple contexts NEEDS PATCHING to
+ allow session reuse! A fuller solution is in the works.
+
+ *Ben Laurie, problem pointed out by Holger Reif, Bodo Moeller (and ???)*
+
+ * Some more source tree cleanups (removed obsolete files
+ crypto/bf/asm/bf586.pl, test/test.txt and crypto/sha/asm/f.s; changed
+ permission on "config" script to be executable) and a fix for the INSTALL
+ document.
+
+ *Ulf Moeller <ulf@fitug.de>*
+
+ * Remove some legacy and erroneous uses of malloc, free instead of
+ Malloc, Free.
+
+ *Lennart Bang <lob@netstream.se>, with minor changes by Steve*
+
+ * Make rsa_oaep_test return non-zero on error.
+
+ *Ulf Moeller <ulf@fitug.de>*
+
+ * Add support for native Solaris shared libraries. Configure
+ solaris-sparc-sc4-pic, make, then run shlib/solaris-sc4.sh. It'd be nice
+ if someone would make that last step automatic.
+
+ *Matthias Loepfe <Matthias.Loepfe@AdNovum.CH>*
+
+ * ctx_size was not built with the right compiler during "make links". Fixed.
+
+ *Ben Laurie*
+
+ * Change the meaning of 'ALL' in the cipher list. It now means "everything
+ except NULL ciphers". This means the default cipher list will no longer
+ enable NULL ciphers. They need to be specifically enabled e.g. with
+ the string "DEFAULT:eNULL".
+
+ *Steve Henson*
+
+ * Fix to RSA private encryption routines: if p < q then it would
+ occasionally produce an invalid result. This will only happen with
+ externally generated keys because OpenSSL (and SSLeay) ensure p > q.
+
+ *Steve Henson*
+
+ * Be less restrictive and allow also `perl util/perlpath.pl
+ /path/to/bin/perl` in addition to `perl util/perlpath.pl /path/to/bin`,
+ because this way one can also use an interpreter named `perl5` (which is
+ usually the name of Perl 5.xxx on platforms where an Perl 4.x is still
+ installed as `perl`).
+
+ *Matthias Loepfe <Matthias.Loepfe@adnovum.ch>*
+
+ * Let util/clean-depend.pl work also with older Perl 5.00x versions.
+
+ *Matthias Loepfe <Matthias.Loepfe@adnovum.ch>*
+
+ * Fix Makefile.org so CC,CFLAG etc are passed to 'make links' add
+ advapi32.lib to Win32 build and change the pem test comparison
+ to fc.exe (thanks to Ulrich Kroener <kroneru@yahoo.com> for the
+ suggestion). Fix misplaced ASNI prototypes and declarations in evp.h
+ and crypto/des/ede_cbcm_enc.c.
+
+ *Steve Henson*
+
+ * DES quad checksum was broken on big-endian architectures. Fixed.
+
+ *Ben Laurie*
+
+ * Comment out two functions in bio.h that aren't implemented. Fix up the
+ Win32 test batch file so it (might) work again. The Win32 test batch file
+ is horrible: I feel ill....
+
+ *Steve Henson*
+
+ * Move various #ifdefs around so NO_SYSLOG, NO_DIRENT etc are now selected
+ in e_os.h. Audit of header files to check ANSI and non ANSI
+ sections: 10 functions were absent from non ANSI section and not exported
+ from Windows DLLs. Fixed up libeay.num for new functions.
+
+ *Steve Henson*
+
+ * Make `openssl version` output lines consistent.
+
+ *Ralf S. Engelschall*
+
+ * Fix Win32 symbol export lists for BIO functions: Added
+ BIO_get_ex_new_index, BIO_get_ex_num, BIO_get_ex_data and BIO_set_ex_data
+ to ms/libeay{16,32}.def.
+
+ *Ralf S. Engelschall*
+
+ * Second round of fixing the OpenSSL perl/ stuff. It now at least compiled
+ fine under Unix and passes some trivial tests I've now added. But the
+ whole stuff is horribly incomplete, so a README.1ST with a disclaimer was
+ added to make sure no one expects that this stuff really works in the
+ OpenSSL 0.9.2 release. Additionally I've started to clean the XS sources
+ up and fixed a few little bugs and inconsistencies in OpenSSL.{pm,xs} and
+ openssl_bio.xs.
+
+ *Ralf S. Engelschall*
+
+ * Fix the generation of two part addresses in perl.
+
+ *Kenji Miyake <kenji@miyake.org>, integrated by Ben Laurie*
+
+ * Add config entry for Linux on MIPS.
+
+ *John Tobey <jtobey@channel1.com>*
+
+ * Make links whenever Configure is run, unless we are on Windoze.
+
+ *Ben Laurie*
+
+ * Permit extensions to be added to CRLs using crl_section in openssl.cnf.
+ Currently only issuerAltName and AuthorityKeyIdentifier make any sense
+ in CRLs.
+
+ *Steve Henson*
+
+ * Add a useful kludge to allow package maintainers to specify compiler and
+ other platforms details on the command line without having to patch the
+ Configure script every time: One now can use
+ `perl Configure <id>:<details>`,
+ i.e. platform ids are allowed to have details appended
+ to them (separated by colons). This is treated as there would be a static
+ pre-configured entry in Configure's %table under key `<id>` with value
+ `<details>` and `perl Configure <id>` is called. So, when you want to
+ perform a quick test-compile under FreeBSD 3.1 with pgcc and without
+ assembler stuff you can use `perl Configure "FreeBSD-elf:pgcc:-O6:::"`
+ now, which overrides the FreeBSD-elf entry on-the-fly.
+
+ *Ralf S. Engelschall*
+
+ * Disable new TLS1 ciphersuites by default: they aren't official yet.
+
+ *Ben Laurie*
+
+ * Allow DSO flags like -fpic, -fPIC, -KPIC etc. to be specified
+ on the `perl Configure ...` command line. This way one can compile
+ OpenSSL libraries with Position Independent Code (PIC) which is needed
+ for linking it into DSOs.
+
+ *Ralf S. Engelschall*
+
+ * Remarkably, export ciphers were totally broken and no-one had noticed!
+ Fixed.
+
+ *Ben Laurie*
+
+ * Cleaned up the LICENSE document: The official contact for any license
+ questions now is the OpenSSL core team under openssl-core@openssl.org.
+ And add a paragraph about the dual-license situation to make sure people
+ recognize that _BOTH_ the OpenSSL license _AND_ the SSLeay license apply
+ to the OpenSSL toolkit.
+
+ *Ralf S. Engelschall*
+
+ * General source tree makefile cleanups: Made `making xxx in yyy...`
+ display consistent in the source tree and replaced `/bin/rm` by `rm`.
+ Additionally cleaned up the `make links` target: Remove unnecessary
+ semicolons, subsequent redundant removes, inline point.sh into mklink.sh
+ to speed processing and no longer clutter the display with confusing
+ stuff. Instead only the actually done links are displayed.
+
+ *Ralf S. Engelschall*
+
+ * Permit null encryption ciphersuites, used for authentication only. It used
+ to be necessary to set the preprocessor define SSL_ALLOW_ENULL to do this.
+ It is now necessary to set SSL_FORBID_ENULL to prevent the use of null
+ encryption.
+
+ *Ben Laurie*
+
+ * Add a bunch of fixes to the PKCS#7 stuff. It used to sometimes reorder
+ signed attributes when verifying signatures (this would break them),
+ the detached data encoding was wrong and public keys obtained using
+ X509_get_pubkey() weren't freed.
+
+ *Steve Henson*
+
+ * Add text documentation for the BUFFER functions. Also added a work around
+ to a Win95 console bug. This was triggered by the password read stuff: the
+ last character typed gets carried over to the next fread(). If you were
+ generating a new cert request using 'req' for example then the last
+ character of the passphrase would be CR which would then enter the first
+ field as blank.
+
+ *Steve Henson*
+
+ * Added the new 'Includes OpenSSL Cryptography Software' button as
+ doc/openssl_button.{gif,html} which is similar in style to the old SSLeay
+ button and can be used by applications based on OpenSSL to show the
+ relationship to the OpenSSL project.
+
+ *Ralf S. Engelschall*
+
+ * Remove confusing variables in function signatures in files
+ ssl/ssl_lib.c and ssl/ssl.h.
+
+ *Lennart Bong <lob@kulthea.stacken.kth.se>*
+
+ * Don't install bss_file.c under PREFIX/include/
+
+ *Lennart Bong <lob@kulthea.stacken.kth.se>*
+
+ * Get the Win32 compile working again. Modify mkdef.pl so it can handle
+ functions that return function pointers and has support for NT specific
+ stuff. Fix mk1mf.pl and VC-32.pl to support NT differences also. Various
+ #ifdef WIN32 and WINNTs sprinkled about the place and some changes from
+ unsigned to signed types: this was killing the Win32 compile.
+
+ *Steve Henson*
+
+ * Add new certificate file to stack functions,
+ SSL_add_dir_cert_subjects_to_stack() and
+ SSL_add_file_cert_subjects_to_stack(). These largely supplant
+ SSL_load_client_CA_file(), and can be used to add multiple certs easily
+ to a stack (usually this is then handed to SSL_CTX_set_client_CA_list()).
+ This means that Apache-SSL and similar packages don't have to mess around
+ to add as many CAs as they want to the preferred list.
+
+ *Ben Laurie*
+
+ * Experiment with doxygen documentation. Currently only partially applied to
+ ssl/ssl_lib.c.
+ See <http://www.stack.nl/~dimitri/doxygen/index.html>, and run doxygen with
+ openssl.doxy as the configuration file.
+
+ *Ben Laurie*
+
+ * Get rid of remaining C++-style comments which strict C compilers hate.
+
+ *Ralf S. Engelschall, pointed out by Carlos Amengual*
+
+ * Changed BN_RECURSION in bn_mont.c to BN_RECURSION_MONT so it is not
+ compiled in by default: it has problems with large keys.
+
+ *Steve Henson*
+
+ * Add a bunch of SSL_xxx() functions for configuring the temporary RSA and
+ DH private keys and/or callback functions which directly correspond to
+ their SSL_CTX_xxx() counterparts but work on a per-connection basis. This
+ is needed for applications which have to configure certificates on a
+ per-connection basis (e.g. Apache+mod_ssl) instead of a per-context basis
+ (e.g. s_server).
+ For the RSA certificate situation is makes no difference, but
+ for the DSA certificate situation this fixes the "no shared cipher"
+ problem where the OpenSSL cipher selection procedure failed because the
+ temporary keys were not overtaken from the context and the API provided
+ no way to reconfigure them.
+ The new functions now let applications reconfigure the stuff and they
+ are in detail: SSL_need_tmp_RSA, SSL_set_tmp_rsa, SSL_set_tmp_dh,
+ SSL_set_tmp_rsa_callback and SSL_set_tmp_dh_callback. Additionally a new
+ non-public-API function ssl_cert_instantiate() is used as a helper
+ function and also to reduce code redundancy inside ssl_rsa.c.
+
+ *Ralf S. Engelschall*
+
+ * Move s_server -dcert and -dkey options out of the undocumented feature
+ area because they are useful for the DSA situation and should be
+ recognized by the users.
+
+ *Ralf S. Engelschall*
+
+ * Fix the cipher decision scheme for export ciphers: the export bits are
+ *not* within SSL_MKEY_MASK or SSL_AUTH_MASK, they are within
+ SSL_EXP_MASK. So, the original variable has to be used instead of the
+ already masked variable.
+
+ *Richard Levitte <levitte@stacken.kth.se>*
+
+ * Fix `port` variable from `int` to `unsigned int` in crypto/bio/b_sock.c
+
+ *Richard Levitte <levitte@stacken.kth.se>*
+
+ * Change type of another md_len variable in pk7_doit.c:PKCS7_dataFinal()
+ from `int` to `unsigned int` because it is a length and initialized by
+ EVP_DigestFinal() which expects an `unsigned int *`.
+
+ *Richard Levitte <levitte@stacken.kth.se>*
+
+ * Don't hard-code path to Perl interpreter on shebang line of Configure
+ script. Instead use the usual Shell->Perl transition trick.
+
+ *Ralf S. Engelschall*
+
+ * Make `openssl x509 -noout -modulus`' functional also for DSA certificates
+ (in addition to RSA certificates) to match the behaviour of `openssl dsa
+ -noout -modulus` as it's already the case for `openssl rsa -noout
+ -modulus`. For RSA the -modulus is the real "modulus" while for DSA
+ currently the public key is printed (a decision which was already done by
+ `openssl dsa -modulus` in the past) which serves a similar purpose.
+ Additionally the NO_RSA no longer completely removes the whole -modulus
+ option; it now only avoids using the RSA stuff. Same applies to NO_DSA
+ now, too.
+
+ *Ralf S. Engelschall*
+
+ * Add Arne Ansper's reliable BIO - this is an encrypted, block-digested
+ BIO. See the source (crypto/evp/bio_ok.c) for more info.
+
+ *Arne Ansper <arne@ats.cyber.ee>*
+
+ * Dump the old yucky req code that tried (and failed) to allow raw OIDs
+ to be added. Now both 'req' and 'ca' can use new objects defined in the
+ config file.
+
+ *Steve Henson*
+
+ * Add cool BIO that does syslog (or event log on NT).
+
+ *Arne Ansper <arne@ats.cyber.ee>, integrated by Ben Laurie*
+
+ * Add support for new TLS ciphersuites, TLS_RSA_EXPORT56_WITH_RC4_56_MD5,
+ TLS_RSA_EXPORT56_WITH_RC2_CBC_56_MD5 and
+ TLS_RSA_EXPORT56_WITH_DES_CBC_SHA, as specified in "56-bit Export Cipher
+ Suites For TLS", draft-ietf-tls-56-bit-ciphersuites-00.txt.
+
+ *Ben Laurie*
+
+ * Add preliminary config info for new extension code.
+
+ *Steve Henson*
+
+ * Make RSA_NO_PADDING really use no padding.
+
+ *Ulf Moeller <ulf@fitug.de>*
+
+ * Generate errors when private/public key check is done.
+
+ *Ben Laurie*
+
+ * Overhaul for 'crl' utility. New function X509_CRL_print. Partial support
+ for some CRL extensions and new objects added.
+
+ *Steve Henson*
+
+ * Really fix the ASN1 IMPLICIT bug this time... Partial support for private
+ key usage extension and fuller support for authority key id.
+
+ *Steve Henson*
+
+ * Add OAEP encryption for the OpenSSL crypto library. OAEP is the improved
+ padding method for RSA, which is recommended for new applications in PKCS
+ #1 v2.0 (RFC 2437, October 1998).
+ OAEP (Optimal Asymmetric Encryption Padding) has better theoretical
+ foundations than the ad-hoc padding used in PKCS #1 v1.5. It is secure
+ against Bleichbacher's attack on RSA.
+ *Ulf Moeller <ulf@fitug.de>, reformatted, corrected and integrated by
+ Ben Laurie*
+
+ * Updates to the new SSL compression code
+
+ *Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)*
+
+ * Fix so that the version number in the master secret, when passed
+ via RSA, checks that if TLS was proposed, but we roll back to SSLv3
+ (because the server will not accept higher), that the version number
+ is 0x03,0x01, not 0x03,0x00
+
+ *Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)*
+
+ * Run extensive memory leak checks on SSL commands. Fixed *lots* of memory
+ leaks in `ssl/` relating to new `X509_get_pubkey()` behaviour. Also fixes
+ in `apps/` and an unrelated leak in `crypto/dsa/dsa_vrf.c`.
+
+ *Steve Henson*
+
+ * Support for RAW extensions where an arbitrary extension can be
+ created by including its DER encoding. See `apps/openssl.cnf` for
+ an example.
+
+ *Steve Henson*
+
+ * Make sure latest Perl versions don't interpret some generated C array
+ code as Perl array code in the crypto/err/err_genc.pl script.
+
+ *Lars Weber <3weber@informatik.uni-hamburg.de>*
+
+ * Modify ms/do_ms.bat to not generate assembly language makefiles since
+ not many people have the assembler. Various Win32 compilation fixes and
+ update to the INSTALL.W32 file with (hopefully) more accurate Win32
+ build instructions.
+
+ *Steve Henson*
+
+ * Modify configure script 'Configure' to automatically create crypto/date.h
+ file under Win32 and also build pem.h from pem.org. New script
+ util/mkfiles.pl to create the MINFO file on environments that can't do a
+ 'make files': perl util/mkfiles.pl >MINFO should work.
+
+ *Steve Henson*
+
+ * Major rework of DES function declarations, in the pursuit of correctness
+ and purity. As a result, many evil casts evaporated, and some weirdness,
+ too. You may find this causes warnings in your code. Zapping your evil
+ casts will probably fix them. Mostly.
+
+ *Ben Laurie*
+
+ * Fix for a typo in asn1.h. Bug fix to object creation script
+ obj_dat.pl. It considered a zero in an object definition to mean
+ "end of object": none of the objects in objects.h have any zeros
+ so it wasn't spotted.
+
+ *Steve Henson, reported by Erwann ABALEA <eabalea@certplus.com>*
+
+ * Add support for Triple DES Cipher Block Chaining with Output Feedback
+ Masking (CBCM). In the absence of test vectors, the best I have been able
+ to do is check that the decrypt undoes the encrypt, so far. Send me test
+ vectors if you have them.
+
+ *Ben Laurie*
+
+ * Correct calculation of key length for export ciphers (too much space was
+ allocated for null ciphers). This has not been tested!
+
+ *Ben Laurie*
+
+ * Modifications to the mkdef.pl for Win32 DEF file creation. The usage
+ message is now correct (it understands "crypto" and "ssl" on its
+ command line). There is also now an "update" option. This will update
+ the util/ssleay.num and util/libeay.num files with any new functions.
+ If you do a:
+ perl util/mkdef.pl crypto ssl update
+ it will update them.
+
+ *Steve Henson*
+
+ * Overhauled the Perl interface:
+ - ported BN stuff to OpenSSL's different BN library
+ - made the perl/ source tree CVS-aware
+ - renamed the package from SSLeay to OpenSSL (the files still contain
+ their history because I've copied them in the repository)
+ - removed obsolete files (the test scripts will be replaced
+ by better Test::Harness variants in the future)
+
+ *Ralf S. Engelschall*
+
+ * First cut for a very conservative source tree cleanup:
+ 1. merge various obsolete readme texts into doc/ssleay.txt
+ where we collect the old documents and readme texts.
+ 2. remove the first part of files where I'm already sure that we no
+ longer need them because of three reasons: either they are just temporary
+ files which were left by Eric or they are preserved original files where
+ I've verified that the diff is also available in the CVS via "cvs diff
+ -rSSLeay_0_8_1b" or they were renamed (as it was definitely the case for
+ the crypto/md/ stuff).
+
+ *Ralf S. Engelschall*
+
+ * More extension code. Incomplete support for subject and issuer alt
+ name, issuer and authority key id. Change the i2v function parameters
+ and add an extra 'crl' parameter in the X509V3_CTX structure: guess
+ what that's for :-) Fix to ASN1 macro which messed up
+ IMPLICIT tag and add f_enum.c which adds a2i, i2a for ENUMERATED.
+
+ *Steve Henson*
+
+ * Preliminary support for ENUMERATED type. This is largely copied from the
+ INTEGER code.
+
+ *Steve Henson*
+
+ * Add new function, EVP_MD_CTX_copy() to replace frequent use of memcpy.
+
+ *Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)*
+
+ * Make sure `make rehash` target really finds the `openssl` program.
+
+ *Ralf S. Engelschall, Matthias Loepfe <Matthias.Loepfe@adnovum.ch>*
+
+ * Squeeze another 7% of speed out of MD5 assembler, at least on a P2. I'd
+ like to hear about it if this slows down other processors.
+
+ *Ben Laurie*
+
+ * Add CygWin32 platform information to Configure script.
+
+ *Alan Batie <batie@aahz.jf.intel.com>*
+
+ * Fixed ms/32all.bat script: `no_asm` -> `no-asm`
+
+ *Rainer W. Gerling <gerling@mpg-gv.mpg.de>*
+
+ * New program nseq to manipulate netscape certificate sequences
+
+ *Steve Henson*
+
+ * Modify crl2pkcs7 so it supports multiple -certfile arguments. Fix a
+ few typos.
+
+ *Steve Henson*
+
+ * Fixes to BN code. Previously the default was to define BN_RECURSION
+ but the BN code had some problems that would cause failures when
+ doing certificate verification and some other functions.
+
+ *Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)*
+
+ * Add ASN1 and PEM code to support netscape certificate sequences.
+
+ *Steve Henson*
+
+ * Add ASN1 and PEM code to support netscape certificate sequences.
+
+ *Steve Henson*
+
+ * Add several PKIX and private extended key usage OIDs.
+
+ *Steve Henson*
+
+ * Modify the 'ca' program to handle the new extension code. Modify
+ openssl.cnf for new extension format, add comments.
+
+ *Steve Henson*
+
+ * More X509 V3 changes. Fix typo in v3_bitstr.c. Add support to 'req'
+ and add a sample to openssl.cnf so req -x509 now adds appropriate
+ CA extensions.
+
+ *Steve Henson*
+
+ * Continued X509 V3 changes. Add to other makefiles, integrate with the
+ error code, add initial support to X509_print() and x509 application.
+
+ *Steve Henson*
+
+ * Takes a deep breath and start adding X509 V3 extension support code. Add
+ files in crypto/x509v3. Move original stuff to crypto/x509v3/old. All this
+ stuff is currently isolated and isn't even compiled yet.
+
+ *Steve Henson*
+
+ * Continuing patches for GeneralizedTime. Fix up certificate and CRL
+ ASN1 to use ASN1_TIME and modify print routines to use ASN1_TIME_print.
+ Removed the versions check from X509 routines when loading extensions:
+ this allows certain broken certificates that don't set the version
+ properly to be processed.
+
+ *Steve Henson*
+
+ * Deal with irritating shit to do with dependencies, in YAAHW (Yet Another
+ Ad Hoc Way) - Makefile.ssls now all contain local dependencies, which
+ can still be regenerated with "make depend".
+
+ *Ben Laurie*
+
+ * Spelling mistake in C version of CAST-128.
+
+ *Ben Laurie, reported by Jeremy Hylton <jeremy@cnri.reston.va.us>*
+
+ * Changes to the error generation code. The perl script err-code.pl
+ now reads in the old error codes and retains the old numbers, only
+ adding new ones if necessary. It also only changes the .err files if new
+ codes are added. The makefiles have been modified to only insert errors
+ when needed (to avoid needlessly modifying header files). This is done
+ by only inserting errors if the .err file is newer than the auto generated
+ C file. To rebuild all the error codes from scratch (the old behaviour)
+ either modify crypto/Makefile.ssl to pass the -regen flag to err_code.pl
+ or delete all the .err files.
+
+ *Steve Henson*
+
+ * CAST-128 was incorrectly implemented for short keys. The C version has
+ been fixed, but is untested. The assembler versions are also fixed, but
+ new assembler HAS NOT BEEN GENERATED FOR WIN32 - the Makefile needs fixing
+ to regenerate it if needed.
+ *Ben Laurie, reported (with fix for C version) by Jun-ichiro itojun
+ Hagino <itojun@kame.net>*
+
+ * File was opened incorrectly in randfile.c.
+
+ *Ulf Möller <ulf@fitug.de>*
+
+ * Beginning of support for GeneralizedTime. d2i, i2d, check and print
+ functions. Also ASN1_TIME suite which is a CHOICE of UTCTime or
+ GeneralizedTime. ASN1_TIME is the proper type used in certificates et
+ al: it's just almost always a UTCTime. Note this patch adds new error
+ codes so do a "make errors" if there are problems.
+
+ *Steve Henson*
+
+ * Correct Linux 1 recognition in config.
+
+ *Ulf Möller <ulf@fitug.de>*
+
+ * Remove pointless MD5 hash when using DSA keys in ca.
+
+ *Anonymous <nobody@replay.com>*
+
+ * Generate an error if given an empty string as a cert directory. Also
+ generate an error if handed NULL (previously returned 0 to indicate an
+ error, but didn't set one).
+
+ *Ben Laurie, reported by Anonymous <nobody@replay.com>*
+
+ * Add prototypes to SSL methods. Make SSL_write's buffer const, at last.
+
+ *Ben Laurie*
+
+ * Fix the dummy function BN_ref_mod_exp() in rsaref.c to have the correct
+ parameters. This was causing a warning which killed off the Win32 compile.
+
+ *Steve Henson*
+
+ * Remove C++ style comments from crypto/bn/bn_local.h.
+
+ *Neil Costigan <neil.costigan@celocom.com>*
+
+ * The function OBJ_txt2nid was broken. It was supposed to return a nid
+ based on a text string, looking up short and long names and finally
+ "dot" format. The "dot" format stuff didn't work. Added new function
+ OBJ_txt2obj to do the same but return an ASN1_OBJECT and rewrote
+ OBJ_txt2nid to use it. OBJ_txt2obj can also return objects even if the
+ OID is not part of the table.
+
+ *Steve Henson*
+
+ * Add prototypes to X509 lookup/verify methods, fixing a bug in
+ X509_LOOKUP_by_alias().
+
+ *Ben Laurie*
+
+ * Sort openssl functions by name.
+
+ *Ben Laurie*
+
+ * Get the `gendsa` command working and add it to the `list` command. Remove
+ encryption from sample DSA keys (in case anyone is interested the password
+ was "1234").
+
+ *Steve Henson*
+
+ * Make *all* `*_free` functions accept a NULL pointer.
+
+ *Frans Heymans <fheymans@isaserver.be>*
+
+ * If a DH key is generated in s3_srvr.c, don't blow it by trying to use
+ NULL pointers.
+
+ *Anonymous <nobody@replay.com>*
+
+ * s_server should send the CAfile as acceptable CAs, not its own cert.
+
+ *Bodo Moeller <3moeller@informatik.uni-hamburg.de>*
+
+ * Don't blow it for numeric `-newkey` arguments to `apps/req`.
+
+ *Bodo Moeller <3moeller@informatik.uni-hamburg.de>*
+
+ * Temp key "for export" tests were wrong in s3_srvr.c.
+
+ *Anonymous <nobody@replay.com>*
+
+ * Add prototype for temp key callback functions
+ SSL_CTX_set_tmp_{rsa,dh}_callback().
+
+ *Ben Laurie*
+
+ * Make DH_free() tolerate being passed a NULL pointer (like RSA_free() and
+ DSA_free()). Make X509_PUBKEY_set() check for errors in d2i_PublicKey().
+
+ *Steve Henson*
+
+ * X509_name_add_entry() freed the wrong thing after an error.
+
+ *Arne Ansper <arne@ats.cyber.ee>*
+
+ * rsa_eay.c would attempt to free a NULL context.
+
+ *Arne Ansper <arne@ats.cyber.ee>*
+
+ * BIO_s_socket() had a broken should_retry() on Windoze.
+
+ *Arne Ansper <arne@ats.cyber.ee>*
+
+ * BIO_f_buffer() didn't pass on BIO_CTRL_FLUSH.
+
+ *Arne Ansper <arne@ats.cyber.ee>*
+
+ * Make sure the already existing X509_STORE->depth variable is initialized
+ in X509_STORE_new(), but document the fact that this variable is still
+ unused in the certificate verification process.
+
+ *Ralf S. Engelschall*
+
+ * Fix the various library and `apps/` files to free up pkeys obtained from
+ X509_PUBKEY_get() et al. Also allow x509.c to handle netscape extensions.
+
+ *Steve Henson*
+
+ * Fix reference counting in X509_PUBKEY_get(). This makes
+ demos/maurice/example2.c work, amongst others, probably.
+
+ *Steve Henson and Ben Laurie*
+
+ * First cut of a cleanup for `apps/`. First the `ssleay` program is now named
+ `openssl` and second, the shortcut symlinks for the `openssl <command>`
+ are no longer created. This way we have a single and consistent command
+ line interface `openssl <command>`, similar to `cvs <command>`.
+
+ *Ralf S. Engelschall, Paul Sutton and Ben Laurie*
+
+ * ca.c: move test for DSA keys inside #ifndef NO_DSA. Make pubkey
+ BIT STRING wrapper always have zero unused bits.
+
+ *Steve Henson*
+
+ * Add CA.pl, perl version of CA.sh, add extended key usage OID.
+
+ *Steve Henson*
+
+ * Make the top-level INSTALL documentation easier to understand.
+
+ *Paul Sutton*
+
+ * Makefiles updated to exit if an error occurs in a sub-directory
+ make (including if user presses ^C) [Paul Sutton]
+
+ * Make Montgomery context stuff explicit in RSA data structure.
+
+ *Ben Laurie*
+
+ * Fix build order of pem and err to allow for generated pem.h.
+
+ *Ben Laurie*
+
+ * Fix renumbering bug in X509_NAME_delete_entry().
+
+ *Ben Laurie*
+
+ * Enhanced the err-ins.pl script so it makes the error library number
+ global and can add a library name. This is needed for external ASN1 and
+ other error libraries.
+
+ *Steve Henson*
+
+ * Fixed sk_insert which never worked properly.
+
+ *Steve Henson*
+
+ * Fix ASN1 macros so they can handle indefinite length constructed
+ EXPLICIT tags. Some non standard certificates use these: they can now
+ be read in.
+
+ *Steve Henson*
+
+ * Merged the various old/obsolete SSLeay documentation files (doc/xxx.doc)
+ into a single doc/ssleay.txt bundle. This way the information is still
+ preserved but no longer messes up this directory. Now it's new room for
+ the new set of documentation files.
+
+ *Ralf S. Engelschall*
+
+ * SETs were incorrectly DER encoded. This was a major pain, because they
+ shared code with SEQUENCEs, which aren't coded the same. This means that
+ almost everything to do with SETs or SEQUENCEs has either changed name or
+ number of arguments.
+
+ *Ben Laurie, based on a partial fix by GP Jayan <gp@nsj.co.jp>*
+
+ * Fix test data to work with the above.
+
+ *Ben Laurie*
+
+ * Fix the RSA header declarations that hid a bug I fixed in 0.9.0b but
+ was already fixed by Eric for 0.9.1 it seems.
+
+ *Ben Laurie - pointed out by Ulf Möller <ulf@fitug.de>*
+
+ * Autodetect FreeBSD3.
+
+ *Ben Laurie*
+
+ * Fix various bugs in Configure. This affects the following platforms:
+ nextstep
+ ncr-scde
+ unixware-2.0
+ unixware-2.0-pentium
+ sco5-cc.
+
+ *Ben Laurie*
+
+ * Eliminate generated files from CVS. Reorder tests to regenerate files
+ before they are needed.
+
+ *Ben Laurie*
+
+ * Generate Makefile.ssl from Makefile.org (to keep CVS happy).
+
+ *Ben Laurie*
+
+### Changes between 0.9.1b and 0.9.1c [23-Dec-1998]
+
+ * Added OPENSSL_VERSION_NUMBER to crypto/crypto.h and
+ changed SSLeay to OpenSSL in version strings.
+
+ *Ralf S. Engelschall*
+
+ * Some fixups to the top-level documents.
+
+ *Paul Sutton*
+
+ * Fixed the nasty bug where rsaref.h was not found under compile-time
+ because the symlink to include/ was missing.
+
+ *Ralf S. Engelschall*
+
+ * Incorporated the popular no-RSA/DSA-only patches
+ which allow to compile an RSA-free SSLeay.
+
+ *Andrew Cooke / Interrader Ldt., Ralf S. Engelschall*
+
+ * Fixed nasty rehash problem under `make -f Makefile.ssl links`
+ when "ssleay" is still not found.
+
+ *Ralf S. Engelschall*
+
+ * Added more platforms to Configure: Cray T3E, HPUX 11,
+
+ *Ralf S. Engelschall, Beckmann <beckman@acl.lanl.gov>*
+
+ * Updated the README file.
+
+ *Ralf S. Engelschall*
+
+ * Added various .cvsignore files in the CVS repository subdirs
+ to make a "cvs update" really silent.
+
+ *Ralf S. Engelschall*
+
+ * Recompiled the error-definition header files and added
+ missing symbols to the Win32 linker tables.
+
+ *Ralf S. Engelschall*
+
+ * Cleaned up the top-level documents;
+ o new files: CHANGES and LICENSE
+ o merged VERSION, HISTORY* and README* files a CHANGES.SSLeay
+ o merged COPYRIGHT into LICENSE
+ o removed obsolete TODO file
+ o renamed MICROSOFT to INSTALL.W32
+
+ *Ralf S. Engelschall*
+
+ * Removed dummy files from the 0.9.1b source tree:
+ crypto/asn1/x crypto/bio/cd crypto/bio/fg crypto/bio/grep crypto/bio/vi
+ crypto/bn/asm/......add.c crypto/bn/asm/a.out crypto/dsa/f crypto/md5/f
+ crypto/pem/gmon.out crypto/perlasm/f crypto/pkcs7/build crypto/rsa/f
+ crypto/sha/asm/f crypto/threads/f ms/zzz ssl/f ssl/f.mak test/f
+ util/f.mak util/pl/f util/pl/f.mak crypto/bf/bf_locl.old apps/f
+
+ *Ralf S. Engelschall*
+
+ * Added various platform portability fixes.
+
+ *Mark J. Cox*
+
+ * The Genesis of the OpenSSL rpject:
+ We start with the latest (unreleased) SSLeay version 0.9.1b which Eric A.
+ Young and Tim J. Hudson created while they were working for C2Net until
+ summer 1998.
+
+ *The OpenSSL Project*
+
+### Changes between 0.9.0b and 0.9.1b [not released]
+
+ * Updated a few CA certificates under certs/
+
+ *Eric A. Young*
+
+ * Changed some BIGNUM api stuff.
+
+ *Eric A. Young*
+
+ * Various platform ports: OpenBSD, Ultrix, IRIX 64bit, NetBSD,
+ DGUX x86, Linux Alpha, etc.
+
+ *Eric A. Young*
+
+ * New COMP library [crypto/comp/] for SSL Record Layer Compression:
+ RLE (dummy implemented) and ZLIB (really implemented when ZLIB is
+ available).
+
+ *Eric A. Young*
+
+ * Add -strparse option to asn1pars program which parses nested
+ binary structures
+
+ *Dr Stephen Henson <shenson@bigfoot.com>*
+
+ * Added "oid_file" to ssleay.cnf for "ca" and "req" programs.
+
+ *Eric A. Young*
+
+ * DSA fix for "ca" program.
+
+ *Eric A. Young*
+
+ * Added "-genkey" option to "dsaparam" program.
+
+ *Eric A. Young*
+
+ * Added RIPE MD160 (rmd160) message digest.
+
+ *Eric A. Young*
+
+ * Added -a (all) option to "ssleay version" command.
+
+ *Eric A. Young*
+
+ * Added PLATFORM define which is the id given to Configure.
+
+ *Eric A. Young*
+
+ * Added MemCheck_XXXX functions to crypto/mem.c for memory checking.
+
+ *Eric A. Young*
+
+ * Extended the ASN.1 parser routines.
+
+ *Eric A. Young*
+
+ * Extended BIO routines to support REUSEADDR, seek, tell, etc.
+
+ *Eric A. Young*
+
+ * Added a BN_CTX to the BN library.
+
+ *Eric A. Young*
+
+ * Fixed the weak key values in DES library
+
+ *Eric A. Young*
+
+ * Changed API in EVP library for cipher aliases.
+
+ *Eric A. Young*
+
+ * Added support for RC2/64bit cipher.
+
+ *Eric A. Young*
+
+ * Converted the lhash library to the crypto/mem.c functions.
+
+ *Eric A. Young*
+
+ * Added more recognized ASN.1 object ids.
+
+ *Eric A. Young*
+
+ * Added more RSA padding checks for SSL/TLS.
+
+ *Eric A. Young*
+
+ * Added BIO proxy/filter functionality.
+
+ *Eric A. Young*
+
+ * Added extra_certs to SSL_CTX which can be used
+ send extra CA certificates to the client in the CA cert chain sending
+ process. It can be configured with SSL_CTX_add_extra_chain_cert().
+
+ *Eric A. Young*
+
+ * Now Fortezza is denied in the authentication phase because
+ this is key exchange mechanism is not supported by SSLeay at all.
+
+ *Eric A. Young*
+
+ * Additional PKCS1 checks.
+
+ *Eric A. Young*
+
+ * Support the string "TLSv1" for all TLS v1 ciphers.
+
+ *Eric A. Young*
+
+ * Added function SSL_get_ex_data_X509_STORE_CTX_idx() which gives the
+ ex_data index of the SSL context in the X509_STORE_CTX ex_data.
+
+ *Eric A. Young*
+
+ * Fixed a few memory leaks.
+
+ *Eric A. Young*
+
+ * Fixed various code and comment typos.
+
+ *Eric A. Young*
+
+ * A minor bug in ssl/s3_clnt.c where there would always be 4 0
+ bytes sent in the client random.
+
+ *Edward Bishop <ebishop@spyglass.com>*
+
+<!-- Links -->
+
+[CVE-2023-0401]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0401
+[CVE-2023-0286]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0286
+[CVE-2023-0217]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0217
+[CVE-2023-0216]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0216
+[CVE-2023-0215]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0215
+[CVE-2022-4450]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4450
+[CVE-2022-4304]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4304
+[CVE-2022-4203]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4203
+[CVE-2022-3996]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-3996
+[CVE-2022-2274]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-2274
+[CVE-2022-2097]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-2274
+[CVE-2020-1971]: https://www.openssl.org/news/vulnerabilities.html#CVE-2020-1971
+[CVE-2020-1967]: https://www.openssl.org/news/vulnerabilities.html#CVE-2020-1967
+[CVE-2019-1563]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1563
+[CVE-2019-1559]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1559
+[CVE-2019-1552]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1552
+[CVE-2019-1551]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1551
+[CVE-2019-1549]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1549
+[CVE-2019-1547]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1547
+[CVE-2019-1543]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1543
+[CVE-2018-5407]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-5407
+[CVE-2018-0739]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0739
+[CVE-2018-0737]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0737
+[CVE-2018-0735]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0735
+[CVE-2018-0734]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0734
+[CVE-2018-0733]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0733
+[CVE-2018-0732]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0732
+[CVE-2017-3738]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3738
+[CVE-2017-3737]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3737
+[CVE-2017-3736]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3736
+[CVE-2017-3735]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3735
+[CVE-2017-3733]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3733
+[CVE-2017-3732]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3732
+[CVE-2017-3731]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3731
+[CVE-2017-3730]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3730
+[CVE-2016-7055]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7055
+[CVE-2016-7054]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7054
+[CVE-2016-7053]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7053
+[CVE-2016-7052]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7052
+[CVE-2016-6309]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6309
+[CVE-2016-6308]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6308
+[CVE-2016-6307]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6307
+[CVE-2016-6306]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6306
+[CVE-2016-6305]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6305
+[CVE-2016-6304]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6304
+[CVE-2016-6303]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6303
+[CVE-2016-6302]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6302
+[CVE-2016-2183]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2183
+[CVE-2016-2182]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2182
+[CVE-2016-2181]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2181
+[CVE-2016-2180]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2180
+[CVE-2016-2179]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2179
+[CVE-2016-2178]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2178
+[CVE-2016-2177]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2177
+[CVE-2016-2176]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2176
+[CVE-2016-2109]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2109
+[CVE-2016-2107]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2107
+[CVE-2016-2106]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2106
+[CVE-2016-2105]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2105
+[CVE-2016-0800]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0800
+[CVE-2016-0799]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0799
+[CVE-2016-0798]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0798
+[CVE-2016-0797]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0797
+[CVE-2016-0705]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0705
+[CVE-2016-0702]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0702
+[CVE-2016-0701]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0701
+[CVE-2015-3197]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3197
+[CVE-2015-3196]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3196
+[CVE-2015-3195]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3195
+[CVE-2015-3194]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3194
+[CVE-2015-3193]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3193
+[CVE-2015-1793]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1793
+[CVE-2015-1792]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1792
+[CVE-2015-1791]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1791
+[CVE-2015-1790]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1790
+[CVE-2015-1789]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1789
+[CVE-2015-1788]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1788
+[CVE-2015-1787]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1787
+[CVE-2015-0293]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0293
+[CVE-2015-0291]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0291
+[CVE-2015-0290]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0290
+[CVE-2015-0289]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0289
+[CVE-2015-0288]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0288
+[CVE-2015-0287]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0287
+[CVE-2015-0286]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0286
+[CVE-2015-0285]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0285
+[CVE-2015-0209]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0209
+[CVE-2015-0208]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0208
+[CVE-2015-0207]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0207
+[CVE-2015-0206]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0206
+[CVE-2015-0205]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0205
+[CVE-2015-0204]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0204
+[CVE-2014-8275]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-8275
+[CVE-2014-5139]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-5139
+[CVE-2014-3572]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3572
+[CVE-2014-3571]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3571
+[CVE-2014-3570]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3570
+[CVE-2014-3569]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3569
+[CVE-2014-3568]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3568
+[CVE-2014-3567]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3567
+[CVE-2014-3566]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3566
+[CVE-2014-3513]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3513
+[CVE-2014-3512]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3512
+[CVE-2014-3511]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3511
+[CVE-2014-3510]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3510
+[CVE-2014-3509]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3509
+[CVE-2014-3508]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3508
+[CVE-2014-3507]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3507
+[CVE-2014-3506]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3506
+[CVE-2014-3505]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3505
+[CVE-2014-3470]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3470
+[CVE-2014-0224]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0224
+[CVE-2014-0221]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0221
+[CVE-2014-0195]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0195
+[CVE-2014-0160]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0160
+[CVE-2014-0076]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0076
+[CVE-2013-6450]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-6450
+[CVE-2013-4353]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-4353
+[CVE-2013-0169]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-0169
+[CVE-2013-0166]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-0166
+[CVE-2012-2686]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2686
+[CVE-2012-2333]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2333
+[CVE-2012-2110]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2110
+[CVE-2012-0884]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0884
+[CVE-2012-0050]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0050
+[CVE-2012-0027]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0027
+[CVE-2011-4619]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4619
+[CVE-2011-4577]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4577
+[CVE-2011-4576]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4576
+[CVE-2011-4109]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4109
+[CVE-2011-4108]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4108
+[CVE-2011-3210]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-3210
+[CVE-2011-3207]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-3207
+[CVE-2011-0014]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-0014
+[CVE-2010-4252]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-4252
+[CVE-2010-4180]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-4180
+[CVE-2010-3864]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-3864
+[CVE-2010-1633]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-1633
+[CVE-2010-0740]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-0740
+[CVE-2010-0433]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-0433
+[CVE-2009-4355]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-4355
+[CVE-2009-3555]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-3555
+[CVE-2009-3245]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-3245
+[CVE-2009-1386]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-1386
+[CVE-2009-1379]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-1379
+[CVE-2009-1378]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-1378
+[CVE-2009-1377]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-1377
+[CVE-2009-0789]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0789
+[CVE-2009-0591]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0591
+[CVE-2009-0590]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0590
+[CVE-2008-5077]: https://www.openssl.org/news/vulnerabilities.html#CVE-2008-5077
+[CVE-2008-1678]: https://www.openssl.org/news/vulnerabilities.html#CVE-2008-1678
+[CVE-2008-1672]: https://www.openssl.org/news/vulnerabilities.html#CVE-2008-1672
+[CVE-2008-0891]: https://www.openssl.org/news/vulnerabilities.html#CVE-2008-0891
+[CVE-2007-5135]: https://www.openssl.org/news/vulnerabilities.html#CVE-2007-5135
+[CVE-2007-4995]: https://www.openssl.org/news/vulnerabilities.html#CVE-2007-4995
+[CVE-2006-4343]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-4343
+[CVE-2006-4339]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-4339
+[CVE-2006-3738]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-3738
+[CVE-2006-2940]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-2940
+[CVE-2006-2937]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-2937
+[CVE-2005-2969]: https://www.openssl.org/news/vulnerabilities.html#CVE-2005-2969
+[CVE-2004-0112]: https://www.openssl.org/news/vulnerabilities.html#CVE-2004-0112
+[CVE-2004-0079]: https://www.openssl.org/news/vulnerabilities.html#CVE-2004-0079
+[CVE-2003-0851]: https://www.openssl.org/news/vulnerabilities.html#CVE-2003-0851
+[CVE-2003-0545]: https://www.openssl.org/news/vulnerabilities.html#CVE-2003-0545
+[CVE-2003-0544]: https://www.openssl.org/news/vulnerabilities.html#CVE-2003-0544
+[CVE-2003-0543]: https://www.openssl.org/news/vulnerabilities.html#CVE-2003-0543
+[CVE-2003-0078]: https://www.openssl.org/news/vulnerabilities.html#CVE-2003-0078
+[CVE-2002-0659]: https://www.openssl.org/news/vulnerabilities.html#CVE-2002-0659
+[CVE-2002-0657]: https://www.openssl.org/news/vulnerabilities.html#CVE-2002-0657
+[CVE-2002-0656]: https://www.openssl.org/news/vulnerabilities.html#CVE-2002-0656
+[CVE-2002-0655]: https://www.openssl.org/news/vulnerabilities.html#CVE-2002-0655
diff --git a/CONTRIBUTING b/CONTRIBUTING
deleted file mode 100644
index 83c0dde12819..000000000000
--- a/CONTRIBUTING
+++ /dev/null
@@ -1,72 +0,0 @@
-HOW TO CONTRIBUTE TO OpenSSL
-----------------------------
-
-(Please visit https://www.openssl.org/community/getting-started.html for
-other ideas about how to contribute.)
-
-Development is done on GitHub, https://github.com/openssl/openssl.
-
-To request new features or report bugs, please open an issue on GitHub
-
-To submit a patch, please open a pull request on GitHub. If you are thinking
-of making a large contribution, open an issue for it before starting work,
-to get comments from the community. Someone may be already working on
-the same thing or there may be reasons why that feature isn't implemented.
-
-To make it easier to review and accept your pull request, please follow these
-guidelines:
-
- 1. Anything other than a trivial contribution requires a Contributor
- License Agreement (CLA), giving us permission to use your code. See
- https://www.openssl.org/policies/cla.html for details. If your
- contribution is too small to require a CLA, put "CLA: trivial" on a
- line by itself in your commit message body.
-
- 2. All source files should start with the following text (with
- appropriate comment characters at the start of each line and the
- year(s) updated):
-
- Copyright 20xx-20yy The OpenSSL Project Authors. All Rights Reserved.
-
- Licensed under the OpenSSL license (the "License"). You may not use
- this file except in compliance with the License. You can obtain a copy
- in the file LICENSE in the source distribution or at
- https://www.openssl.org/source/license.html
-
- 3. Patches should be as current as possible; expect to have to rebase
- often. We do not accept merge commits, you will have to remove them
- (usually by rebasing) before it will be acceptable.
-
- 4. Patches should follow our coding style (see
- https://www.openssl.org/policies/codingstyle.html) and compile
- without warnings. Where gcc or clang is available you should use the
- --strict-warnings Configure option. OpenSSL compiles on many varied
- platforms: try to ensure you only use portable features. Clean builds via
- GitHub Actions and AppVeyor are required, and they are started automatically
- whenever a PR is created or updated.
-
- 5. When at all possible, patches should include tests. These can
- either be added to an existing test, or completely new. Please see
- test/README for information on the test framework.
-
- 6. New features or changed functionality must include
- documentation. Please look at the "pod" files in doc/man[1357] for
- examples of our style. Run "make doc-nits" to make sure that your
- documentation changes are clean.
-
- 7. For user visible changes (API changes, behaviour changes, ...),
- consider adding a note in CHANGES. This could be a summarising
- description of the change, and could explain the grander details.
- Have a look through existing entries for inspiration.
- Please note that this is NOT simply a copy of git-log one-liners.
- Also note that security fixes get an entry in CHANGES.
- This file helps users get more in depth information of what comes
- with a specific release without having to sift through the higher
- noise ratio in git-log.
-
- 8. For larger or more important user visible changes, as well as
- security fixes, please add a line in NEWS. On exception, it might be
- worth adding a multi-line entry (such as the entry that announces all
- the types that became opaque with OpenSSL 1.1.0).
- This file helps users get a very quick summary of what comes with a
- specific release, to see if an upgrade is worth the effort.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000000..efb4be871695
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,94 @@
+HOW TO CONTRIBUTE TO OpenSSL
+============================
+
+Please visit our [Getting Started] page for other ideas about how to contribute.
+
+ [Getting Started]: <https://www.openssl.org/community/getting-started.html>
+
+Development is done on GitHub in the [openssl/openssl] repository.
+
+ [openssl/openssl]: <https://github.com/openssl/openssl>
+
+To request new features or report bugs, please open an issue on GitHub
+
+To submit a patch, please open a pull request on GitHub. If you are thinking
+of making a large contribution, open an issue for it before starting work,
+to get comments from the community. Someone may be already working on
+the same thing or there may be reasons why that feature isn't implemented.
+
+To make it easier to review and accept your pull request, please follow these
+guidelines:
+
+ 1. Anything other than a trivial contribution requires a [Contributor
+ License Agreement] (CLA), giving us permission to use your code.
+ If your contribution is too small to require a CLA (e.g. fixing a spelling
+ mistake), place the text "`CLA: trivial`" on a line by itself separated by
+ an empty line from the rest of the commit message. It is not sufficient to
+ only place the text in the GitHub pull request description.
+
+ [Contributor License Agreement]: <https://www.openssl.org/policies/cla.html>
+
+ To amend a missing "`CLA: trivial`" line after submission, do the following:
+
+ ```
+ git commit --amend
+ [add the line, save and quit the editor]
+ git push -f
+ ```
+
+ 2. All source files should start with the following text (with
+ appropriate comment characters at the start of each line and the
+ year(s) updated):
+
+ ```
+ Copyright 20xx-20yy The OpenSSL Project Authors. All Rights Reserved.
+
+ Licensed under the Apache License 2.0 (the "License"). You may not use
+ this file except in compliance with the License. You can obtain a copy
+ in the file LICENSE in the source distribution or at
+ https://www.openssl.org/source/license.html
+ ```
+
+ 3. Patches should be as current as possible; expect to have to rebase
+ often. We do not accept merge commits, you will have to remove them
+ (usually by rebasing) before it will be acceptable.
+
+ 4. Patches should follow our [coding style] and compile without warnings.
+ Where `gcc` or `clang` is available you should use the
+ `--strict-warnings` `Configure` option. OpenSSL compiles on many varied
+ platforms: try to ensure you only use portable features. Clean builds via
+ GitHub Actions and AppVeyor are required, and they are started automatically
+ whenever a PR is created or updated.
+
+ [coding style]: https://www.openssl.org/policies/technical/coding-style.html
+
+ 5. When at all possible, patches should include tests. These can
+ either be added to an existing test, or completely new. Please see
+ [test/README.md](test/README.md) for information on the test framework.
+
+ 6. New features or changed functionality must include
+ documentation. Please look at the "pod" files in doc/man[1357] for
+ examples of our style. Run "make doc-nits" to make sure that your
+ documentation changes are clean.
+
+ 7. For user visible changes (API changes, behaviour changes, ...),
+ consider adding a note in [CHANGES.md](CHANGES.md).
+ This could be a summarising description of the change, and could
+ explain the grander details.
+ Have a look through existing entries for inspiration.
+ Please note that this is NOT simply a copy of git-log one-liners.
+ Also note that security fixes get an entry in [CHANGES.md](CHANGES.md).
+ This file helps users get more in depth information of what comes
+ with a specific release without having to sift through the higher
+ noise ratio in git-log.
+
+ 8. For larger or more important user visible changes, as well as
+ security fixes, please add a line in [NEWS.md](NEWS.md).
+ On exception, it might be worth adding a multi-line entry (such as
+ the entry that announces all the types that became opaque with
+ OpenSSL 1.1.0).
+ This file helps users get a very quick summary of what comes with a
+ specific release, to see if an upgrade is worth the effort.
+
+ 9. Guidelines how to integrate error output of new crypto library modules
+ can be found in [crypto/err/README.md](crypto/err/README.md).
diff --git a/Configure b/Configure
index 6cb1a84f4b7f..5ac4b5222e4f 100755
--- a/Configure
+++ b/Configure
@@ -2,7 +2,7 @@
# -*- mode: perl; -*-
# Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -15,17 +15,38 @@ use Config;
use FindBin;
use lib "$FindBin::Bin/util/perl";
use File::Basename;
-use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs/;
+use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs splitdir/;
use File::Path qw/mkpath/;
+use OpenSSL::fallback "$FindBin::Bin/external/perl/MODULES.txt";
use OpenSSL::Glob;
+use OpenSSL::Template;
+use OpenSSL::config;
-# see INSTALL for instructions.
+# see INSTALL.md for instructions.
my $orig_death_handler = $SIG{__DIE__};
$SIG{__DIE__} = \&death_handler;
my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-egd] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--config=FILE] os/compiler[:flags]\n";
+my $banner = <<"EOF";
+
+**********************************************************************
+*** ***
+*** OpenSSL has been successfully configured ***
+*** ***
+*** If you encounter a problem while building, please open an ***
+*** issue on GitHub <https://github.com/openssl/openssl/issues> ***
+*** and include the output from the following command: ***
+*** ***
+*** perl configdata.pm --dump ***
+*** ***
+*** (If you are new to OpenSSL, you might want to consult the ***
+*** 'Troubleshooting' section in the INSTALL.md file first) ***
+*** ***
+**********************************************************************
+EOF
+
# Options:
#
# --config add the given configuration file, which will be read after
@@ -40,11 +61,17 @@ my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lx
# given with --prefix.
# This becomes the value of OPENSSLDIR in Makefile and in C.
# (Default: PREFIX/ssl)
+# --banner=".." Output specified text instead of default completion banner
+#
+# -w Don't wait after showing a Configure warning
#
# --cross-compile-prefix Add specified prefix to binutils components.
#
-# --api One of 0.9.8, 1.0.0 or 1.1.0. Do not compile support for
-# interfaces deprecated as of the specified OpenSSL version.
+# --api One of 0.9.8, 1.0.0, 1.0.1, 1.0.2, 1.1.0, 1.1.1, or 3.0
+# Define the public APIs as they were for that version
+# including patch releases. If 'no-deprecated' is also
+# given, do not compile support for interfaces deprecated
+# up to and including the specified OpenSSL version.
#
# no-hw-xxx do not compile support for specific crypto hardware.
# Generic OpenSSL-style methods relating to this support
@@ -63,12 +90,13 @@ my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lx
# zlib-dynamic Like "zlib", but the zlib library is expected to be a shared
# library and will be loaded in run-time by the OpenSSL library.
# sctp include SCTP support
+# no-uplink Don't build support for UPLINK interface.
# enable-weak-ssl-ciphers
# Enable weak ciphers that are disabled by default.
# 386 generate 80386 code in assembly modules
# no-sse2 disables IA-32 SSE2 code in assembly modules, the above
# mentioned '386' option implies this one
-# no-<cipher> build without specified algorithm (rsa, idea, rc5, ...)
+# no-<cipher> build without specified algorithm (dsa, idea, rc5, ...)
# -<xxx> +<xxx> All options which are unknown to the 'Configure' script are
# /<xxx> passed through to the compiler. Unix-style options beginning
# with a '-' or '+' are recognized, as well as Windows-style
@@ -110,7 +138,6 @@ my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lx
# get past these. Note that we only use these with C compilers, not with
# C++ compilers.
-# DEBUG_UNUSED enables __owur (warn unused result) checks.
# -DPEDANTIC complements -pedantic and is meant to mask code that
# is not strictly standard-compliant and/or implementation-specific,
# e.g. inline assembly, disregards to alignment requirements, such
@@ -124,9 +151,9 @@ my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lx
# but 'long long' type.
my @gcc_devteam_warn = qw(
- -DDEBUG_UNUSED
- -DPEDANTIC -pedantic -Wno-long-long
+ -DPEDANTIC -pedantic -Wno-long-long -DUNUSEDRESULT_DEBUG
-Wall
+ -Wmissing-declarations
-Wextra
-Wno-unused-parameter
-Wno-missing-field-initializers
@@ -164,10 +191,6 @@ my @cl_devteam_warn = qw(
/WX
);
-# This adds backtrace information to the memory leak info. Is only used
-# when crypto-mdebug-backtrace is enabled.
-my $memleak_devteam_backtrace = "-rdynamic";
-
my $strict_warnings = 0;
# As for $BSDthreads. Idea is to maintain "collective" set of flags,
@@ -182,13 +205,31 @@ our $BSDthreads="-pthread -D_THREAD_SAFE -D_REENTRANT";
#
# API compatibility name to version number mapping.
#
-my $maxapi = "1.1.0"; # API for "no-deprecated" builds
my $apitable = {
- "1.1.0" => "0x10100000L",
- "1.0.0" => "0x10000000L",
- "0.9.8" => "0x00908000L",
+ # This table expresses when API additions or changes can occur.
+ # The numbering used changes from 3.0 and on because we updated
+ # (solidified) our version numbering scheme at that point.
+
+ # From 3.0 and on, we internalise the given version number in decimal
+ # as MAJOR * 10000 + MINOR * 100 + 0
+ "3.0.0" => 30000,
+ "3.0" => 30000,
+
+ # Note that before 3.0, we didn't have the same version number scheme.
+ # Still, the numbering we use here covers what we need.
+ "1.1.1" => 10101,
+ "1.1.0" => 10100,
+ "1.0.2" => 10002,
+ "1.0.1" => 10001,
+ "1.0.0" => 10000,
+ "0.9.8" => 908,
};
+# For OpenSSL::config::get_platform
+my %guess_opts = ();
+
+my $dryrun = 0;
+
our %table = ();
our %config = ();
our %withargs = ();
@@ -233,6 +274,9 @@ my $local_config_envname = 'OPENSSL_LOCAL_CONFIG_DIR';
$config{sourcedir} = abs2rel($srcdir, $blddir);
$config{builddir} = abs2rel($blddir, $blddir);
+# echo -n 'holy hand grenade of antioch' | openssl sha256
+$config{FIPSKEY} =
+ 'f4556650ac31d35461610bac4ed81b1a181b2d8a43ea2854cbae22ca74560813';
# Collect reconfiguration information if needed
my @argvcopy=@ARGV;
@@ -260,29 +304,58 @@ if (grep /^reconf(igure)?$/, @argvcopy) {
$config{perlargv} = [ @argvcopy ];
+# Historical: if known directories in crypto/ have been removed, it means
+# that those sub-systems are disabled.
+# (the other option would be to removed them from the SUBDIRS statement in
+# crypto/build.info)
+# We reverse the input list for cosmetic purely reasons, to compensate that
+# 'unshift' adds at the front of the list (i.e. in reverse input order).
+foreach ( reverse sort( 'aes', 'aria', 'bf', 'camellia', 'cast', 'des', 'dh',
+ 'dsa', 'ec', 'hmac', 'idea', 'md2', 'md5', 'mdc2',
+ 'rc2', 'rc4', 'rc5', 'ripemd', 'seed', 'sha',
+ 'sm2', 'sm3', 'sm4') ) {
+ unshift @argvcopy, "no-$_" if ! -d catdir($srcdir, 'crypto', $_);
+}
+
# Collect version numbers
-$config{version} = "unknown";
-$config{version_num} = "unknown";
-$config{shlib_version_number} = "unknown";
-$config{shlib_version_history} = "unknown";
+my %version = ();
collect_information(
- collect_from_file(catfile($srcdir,'include/openssl/opensslv.h')),
- qr/OPENSSL.VERSION.TEXT.*OpenSSL (\S+) / => sub { $config{version} = $1; },
- qr/OPENSSL.VERSION.NUMBER.*(0x\S+)/ => sub { $config{version_num}=$1 },
- qr/SHLIB_VERSION_NUMBER *"([^"]+)"/ => sub { $config{shlib_version_number}=$1 },
- qr/SHLIB_VERSION_HISTORY *"([^"]*)"/ => sub { $config{shlib_version_history}=$1 }
+ collect_from_file(catfile($srcdir,'VERSION.dat')),
+ qr/\s*(\w+)\s*=\s*(.*?)\s*$/ =>
+ sub {
+ # Only define it if there is a value at all
+ if ($2 ne '') {
+ my $k = $1;
+ my $v = $2;
+ # Some values are quoted. Trim the quotes
+ $v = $1 if $v =~ /^"(.*)"$/;
+ $version{uc $k} = $v;
+ }
+ },
+ "OTHERWISE" =>
+ sub { die "Something wrong with this line:\n$_\nin $srcdir/VERSION.dat" },
);
-if ($config{shlib_version_history} ne "") { $config{shlib_version_history} .= ":"; }
-($config{major}, $config{minor})
- = ($config{version} =~ /^([0-9]+)\.([0-9\.]+)/);
-($config{shlib_major}, $config{shlib_minor})
- = ($config{shlib_version_number} =~ /^([0-9]+)\.([0-9\.]+)/);
-die "erroneous version information in opensslv.h: ",
- "$config{major}, $config{minor}, $config{shlib_major}, $config{shlib_minor}\n"
- if ($config{major} eq "" || $config{minor} eq ""
- || $config{shlib_major} eq "" || $config{shlib_minor} eq "");
+$config{major} = $version{MAJOR} // 'unknown';
+$config{minor} = $version{MINOR} // 'unknown';
+$config{patch} = $version{PATCH} // 'unknown';
+$config{prerelease} =
+ defined $version{PRE_RELEASE_TAG} ? "-$version{PRE_RELEASE_TAG}" : '';
+$config{build_metadata} =
+ defined $version{BUILD_METADATA} ? "+$version{BUILD_METADATA}" : '';
+$config{shlib_version} = $version{SHLIB_VERSION} // 'unknown';
+$config{release_date} = $version{RELEASE_DATE} // 'xx XXX xxxx';
+
+$config{version} = "$config{major}.$config{minor}.$config{patch}";
+$config{full_version} = "$config{version}$config{prerelease}$config{build_metadata}";
+
+die "erroneous version information in VERSION.dat: ",
+ "$config{version}, $config{shlib_version}\n"
+ unless (defined $version{MAJOR}
+ && defined $version{MINOR}
+ && defined $version{PATCH}
+ && defined $version{SHLIB_VERSION});
# Collect target configurations
@@ -317,21 +390,6 @@ $config{libdir}="";
my $auto_threads=1; # enable threads automatically? true by default
my $default_ranlib;
-# Top level directories to build
-$config{dirs} = [ "crypto", "ssl", "engines", "apps", "test", "util", "tools", "fuzz" ];
-# crypto/ subdirectories to build
-$config{sdirs} = [
- "objects",
- "md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash", "sm3",
- "des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "sm4", "chacha", "modes",
- "bn", "ec", "rsa", "dsa", "dh", "sm2", "dso", "engine",
- "buffer", "bio", "stack", "lhash", "rand", "err",
- "evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",
- "cms", "ts", "srp", "cmac", "ct", "async", "kdf", "store"
- ];
-# test/ subdirectories to build
-$config{tdirs} = [ "ossl_shim" ];
-
# Known TLS and DTLS protocols
my @tls = qw(ssl3 tls1 tls1_1 tls1_2 tls1_3);
my @dtls = qw(dtls1 dtls1_2);
@@ -341,6 +399,7 @@ my @dtls = qw(dtls1 dtls1_2);
# For developers: keep it sorted alphabetically
my @disablables = (
+ "acvp-tests",
"afalgeng",
"aria",
"asan",
@@ -351,16 +410,18 @@ my @disablables = (
"autoload-config",
"bf",
"blake2",
- "buildtest-c\\+\\+",
+ "buildtest-c++",
+ "bulk",
+ "cached-fetch",
"camellia",
"capieng",
"cast",
"chacha",
"cmac",
+ "cmp",
"cms",
"comp",
"crypto-mdebug",
- "crypto-mdebug-backtrace",
"ct",
"deprecated",
"des",
@@ -373,31 +434,36 @@ my @disablables = (
"dynamic-engine",
"ec",
"ec2m",
+ "ec_nistp_64_gcc_128",
"ecdh",
"ecdsa",
- "ec_nistp_64_gcc_128",
"egd",
"engine",
"err",
"external-tests",
"filenames",
- "fuzz-libfuzzer",
+ "fips",
+ "fips-securitychecks",
"fuzz-afl",
+ "fuzz-libfuzzer",
"gost",
- "heartbeats",
- "hw(-.+)?",
"idea",
+ "ktls",
+ "legacy",
+ "loadereng",
"makedepend",
"md2",
"md4",
"mdc2",
+ "module",
"msan",
"multiblock",
"nextprotoneg",
- "pinshared",
"ocb",
"ocsp",
+ "padlockeng",
"pic",
+ "pinshared",
"poly1305",
"posix-io",
"psk",
@@ -409,9 +475,11 @@ my @disablables = (
"rmd160",
"scrypt",
"sctp",
+ "secure-memory",
"seed",
"shared",
"siphash",
+ "siv",
"sm2",
"sm3",
"sm4",
@@ -426,12 +494,14 @@ my @disablables = (
"tests",
"threads",
"tls",
+ "trace",
"ts",
"ubsan",
"ui-console",
"unit-test",
- "whirlpool",
+ "uplink",
"weak-ssl-ciphers",
+ "whirlpool",
"zlib",
"zlib-dynamic",
);
@@ -441,16 +511,29 @@ foreach my $proto ((@tls, @dtls))
push(@disablables, "$proto-method") unless $proto eq "tls1_3";
}
+# Internal disablables, for aliasing purposes. They serve no special
+# purpose here, but allow scripts to get to know them through configdata.pm,
+# where these are merged with @disablables.
+# The actual aliasing mechanism is done via %disable_cascades
+my @disablables_int = qw(
+ crmf
+ );
+
my %deprecated_disablables = (
"ssl2" => undef,
"buf-freelists" => undef,
+ "crypto-mdebug-backtrace" => undef,
+ "hw" => "hw", # causes cascade, but no macro
+ "hw-padlock" => "padlockeng",
"ripemd" => "rmd160",
"ui" => "ui-console",
+ "heartbeats" => undef,
);
# All of the following are disabled by default:
our %disabled = ( # "what" => "comment"
+ "fips" => "default",
"asan" => "default",
"buildtest-c++" => "default",
"crypto-mdebug" => "default",
@@ -459,16 +542,16 @@ our %disabled = ( # "what" => "comment"
"ec_nistp_64_gcc_128" => "default",
"egd" => "default",
"external-tests" => "default",
- "fuzz-libfuzzer" => "default",
"fuzz-afl" => "default",
- "heartbeats" => "default",
+ "fuzz-libfuzzer" => "default",
+ "ktls" => "default",
"md2" => "default",
"msan" => "default",
"rc5" => "default",
"sctp" => "default",
- "ssl-trace" => "default",
"ssl3" => "default",
"ssl3-method" => "default",
+ "trace" => "default",
"ubsan" => "default",
"unit-test" => "default",
"weak-ssl-ciphers" => "default",
@@ -479,14 +562,29 @@ our %disabled = ( # "what" => "comment"
# Note: => pair form used for aesthetics, not to truly make a hash table
my @disable_cascades = (
# "what" => [ "cascade", ... ]
+ "bulk" => [ "shared", "dso",
+ "aria", "async", "autoload-config",
+ "blake2", "bf", "camellia", "cast", "chacha",
+ "cmac", "cms", "cmp", "comp", "ct",
+ "des", "dgram", "dh", "dsa",
+ "ec", "engine",
+ "filenames",
+ "idea", "ktls",
+ "md4", "multiblock", "nextprotoneg",
+ "ocsp", "ocb", "poly1305", "psk",
+ "rc2", "rc4", "rmd160",
+ "seed", "siphash", "siv",
+ "sm3", "sm4", "srp",
+ "srtp", "ssl3-method", "ssl-trace",
+ "ts", "ui-console", "whirlpool",
+ "fips-securitychecks" ],
sub { $config{processor} eq "386" }
=> [ "sse2" ],
"ssl" => [ "ssl3" ],
"ssl3-method" => [ "ssl3" ],
"zlib" => [ "zlib-dynamic" ],
"des" => [ "mdc2" ],
- "ec" => [ "ecdsa", "ecdh" ],
-
+ "ec" => [ "ec2m", "ecdsa", "ecdh", "sm2", "gost" ],
"dgram" => [ "dtls", "sctp" ],
"sock" => [ "dgram" ],
"dtls" => [ @dtls ],
@@ -499,24 +597,51 @@ my @disable_cascades = (
"crypto-mdebug" => [ "crypto-mdebug-backtrace" ],
- # Without position independent code, there can be no shared libraries or DSOs
- "pic" => [ "shared" ],
- "shared" => [ "dynamic-engine" ],
- "dso" => [ "dynamic-engine" ],
- "engine" => [ "afalgeng", "devcryptoeng" ],
+ # If no modules, then no dynamic engines either
+ "module" => [ "dynamic-engine" ],
+
+ # Without shared libraries, dynamic engines aren't possible.
+ # This is due to them having to link with libcrypto and register features
+ # using the ENGINE functionality, and since that relies on global tables,
+ # those *have* to be exacty the same as the ones accessed from the app,
+ # which cannot be guaranteed if shared libraries aren't present.
+ # (note that even with shared libraries, both the app and dynamic engines
+ # must be linked with the same library)
+ "shared" => [ "dynamic-engine", "uplink" ],
+ "dso" => [ "dynamic-engine", "module" ],
+ # Other modules don't necessarily have to link with libcrypto, so shared
+ # libraries do not have to be a condition to produce those.
+
+ # Without position independent code, there can be no shared libraries
+ # or modules.
+ "pic" => [ "shared", "module" ],
+
+ "module" => [ "fips", "dso" ],
+
+ "engine" => [ "dynamic-engine", grep(/eng$/, @disablables) ],
+ "dynamic-engine" => [ "loadereng" ],
+ "hw" => [ "padlockeng" ],
# no-autoalginit is only useful when building non-shared
- "autoalginit" => [ "shared", "apps" ],
+ "autoalginit" => [ "shared", "apps", "fips" ],
"stdio" => [ "apps", "capieng", "egd" ],
"apps" => [ "tests" ],
"tests" => [ "external-tests" ],
"comp" => [ "zlib" ],
- "ec" => [ "tls1_3", "sm2" ],
"sm3" => [ "sm2" ],
sub { !$disabled{"unit-test"} } => [ "heartbeats" ],
sub { !$disabled{"msan"} } => [ "asm" ],
+
+ "cmac" => [ "siv" ],
+ "legacy" => [ "md2" ],
+
+ "cmp" => [ "crmf" ],
+
+ "fips" => [ "fips-securitychecks", "acvp-tests" ],
+
+ "deprecated-3.0" => [ "engine", "srp" ]
);
# Avoid protocol support holes. Also disable all versions below N, if version
@@ -541,8 +666,6 @@ while ((my $first, my $second) = (shift @list, shift @list)) {
# To remove something from %disabled, use "enable-foo".
# For symmetry, "disable-foo" is a synonym for "no-foo".
-&usage if ($#ARGV < 0);
-
# For the "make variables" CPPINCLUDES and CPPDEFINES, we support lists with
# platform specific list separators. Users from those platforms should
# recognise those separators from how you set up the PATH to find executables.
@@ -627,10 +750,8 @@ $config{lflags} = [ env('__CNF_LDFLAGS') || () ];
$config{ex_libs} = [ env('__CNF_LDLIBS') || () ];
$config{openssl_api_defines}=[];
-$config{openssl_algorithm_defines}=[];
-$config{openssl_thread_defines}=[];
$config{openssl_sys_defines}=[];
-$config{openssl_other_defines}=[];
+$config{openssl_feature_defines}=[];
$config{options}="";
$config{build_type} = "release";
my $target="";
@@ -679,12 +800,14 @@ while (@argvcopy)
s /^threads$/enable-threads/;
s /^zlib$/enable-zlib/;
s /^zlib-dynamic$/enable-zlib-dynamic/;
+ s /^fips$/enable-fips/;
if (/^(no|disable|enable)-(.+)$/)
{
my $word = $2;
- if (!exists $deprecated_disablables{$word}
- && !grep { $word =~ /^${_}$/ } @disablables)
+ if ($word !~ m|hw(?:-.+)| # special treatment for hw regexp opt
+ && !exists $deprecated_disablables{$word}
+ && !grep { $word eq $_ } @disablables)
{
$unsupported_options{$_} = 1;
next;
@@ -732,15 +855,16 @@ while (@argvcopy)
}
elsif (exists $deprecated_disablables{$1})
{
- if ($deprecated_disablables{$1} ne "")
+ $deprecated_options{$_} = 1;
+ if (defined $deprecated_disablables{$1})
{
- $deprecated_options{$_} = 1;
- if (defined $deprecated_disablables{$1})
- {
- $disabled{$deprecated_disablables{$1}} = "option";
- }
+ $disabled{$deprecated_disablables{$1}} = "option";
}
}
+ elsif ($1 =~ m|hw(?:-.+)|) # deprecate hw options in regexp form
+ {
+ $deprecated_options{$_} = 1;
+ }
else
{
$disabled{$1} = "option";
@@ -768,6 +892,22 @@ while (@argvcopy)
# No longer an automatic choice
$auto_threads = 0 if ($1 eq "threads");
}
+ elsif (/^-d$/) # From older 'config'
+ {
+ $config{build_type} = "debug";
+ }
+ elsif (/^-v$/) # From older 'config'
+ {
+ $guess_opts{verbose} = 1;
+ }
+ elsif (/^-w$/)
+ {
+ $guess_opts{nowait} = 1;
+ }
+ elsif (/^-t$/) # From older 'config'
+ {
+ $dryrun = 1;
+ }
elsif (/^--strict-warnings$/)
{
# Pretend that our strict flags is a C flag, and replace it
@@ -785,20 +925,12 @@ while (@argvcopy)
}
elsif (/^386$/)
{ $config{processor}=386; }
- elsif (/^fips$/)
- {
- die "FIPS mode not supported\n";
- }
elsif (/^rsaref$/)
{
# No RSAref support any more since it's not needed.
# The check for the option is there so scripts aren't
# broken
}
- elsif (/^nofipscanistercheck$/)
- {
- die "FIPS mode not supported\n";
- }
elsif (m|^[-+/]|)
{
if (/^--prefix=(.*)$/)
@@ -809,7 +941,10 @@ while (@argvcopy)
}
elsif (/^--api=(.*)$/)
{
- $config{api}=$1;
+ my $api = $1;
+ die "Unknown API compatibility level $api"
+ unless defined $apitable->{$api};
+ $config{api}=$apitable->{$api};
}
elsif (/^--libdir=(.*)$/)
{
@@ -844,6 +979,20 @@ while (@argvcopy)
push @seed_sources, $x;
}
}
+ elsif (/^--fips-key=(.*)$/)
+ {
+ $user{FIPSKEY}=lc($1);
+ die "Non-hex character in FIPS key\n"
+ if $user{FIPSKEY} =~ /[^a-f0-9]/;
+ die "FIPS key must have even number of characters\n"
+ if length $1 & 1;
+ die "FIPS key too long (64 bytes max)\n"
+ if length $1 > 64;
+ }
+ elsif (/^--banner=(.*)$/)
+ {
+ $banner = $1 . "\n";
+ }
elsif (/^--cross-compile-prefix=(.*)$/)
{
$user{CROSS_COMPILE}=$1;
@@ -926,10 +1075,6 @@ while (@argvcopy)
}
}
-if (defined($config{api}) && !exists $apitable->{$config{api}}) {
- die "***** Unsupported api compatibility level: $config{api}\n",
-}
-
if (keys %deprecated_options)
{
warn "***** Deprecated options: ",
@@ -1002,6 +1147,23 @@ if (grep { /-rpath\b/ } ($user{LDFLAGS} ? @{$user{LDFLAGS}} : ())
"***** any of asan, msan or ubsan\n";
}
+# If no target was given, try guessing.
+unless ($target) {
+ my %system_config = OpenSSL::config::get_platform(%guess_opts, %user);
+
+ # The $system_config{disable} is used to populate %disabled with
+ # entries that aren't already there.
+ foreach ( @{$system_config{disable} // []} ) {
+ $disabled{$_} = 'system' unless defined $disabled{$_};
+ }
+ delete $system_config{disable};
+
+ # Override config entries with stuff from the guesser.
+ # It's assumed that this really is nothing new.
+ %config = ( %config, %system_config );
+ $target = $system_config{target};
+}
+
sub disable {
my $disable_type = shift;
@@ -1052,8 +1214,8 @@ if ($target eq "HASH") {
exit 0;
}
-print "Configuring OpenSSL version $config{version} ($config{version_num}) ";
-print "for $target\n";
+print "Configuring OpenSSL version $config{full_version} ";
+print "for target $target\n";
if (scalar(@seed_sources) == 0) {
print "Using os-specific seed configuration\n";
@@ -1074,12 +1236,13 @@ will not work unless the random generator is seeded manually by the
application.
Please read the 'Note on random number generation' section in the
-INSTALL instructions and the RAND_DRBG(7) manual page for more details.
+INSTALL.md instructions and the RAND_DRBG(7) manual page for more
+details.
============================== WARNING ===============================
_____
}
-push @{$config{openssl_other_defines}},
+push @{$config{openssl_feature_defines}},
map { (my $x = $_) =~ tr|[\-a-z]|[_A-Z]|; "OPENSSL_RAND_SEED_$x" }
@seed_sources;
@@ -1099,7 +1262,26 @@ if ($d) {
}
}
-&usage if !$table{$target} || $table{$target}->{template};
+if ($target) {
+ # It's possible that we have different config targets for specific
+ # toolchains, so we try to detect them, and go for the plain config
+ # target if not.
+ my $found;
+ foreach ( ( "$target-$user{CC}", "$target", undef ) ) {
+ $found=$_ if $table{$_} && !$table{$_}->{template};
+ last if $found;
+ }
+ $target = $found;
+} else {
+ # If we don't have a config target now, we try the C compiler as we
+ # fallback
+ my $cc = $user{CC} // 'cc';
+ $target = $cc if $table{$cc} && !$table{$cc}->{template};
+}
+
+&usage unless $target;
+
+exit 0 if $dryrun; # From older 'config'
$config{target} = $target;
my %target = resolve_config($target);
@@ -1135,22 +1317,19 @@ foreach my $feature (@{$target{enable}}) {
delete $disabled{$feature};
}
}
+
+# If uplink_arch isn't defined, disable uplink
+$disabled{uplink} = 'no uplink_arch' unless (defined $target{uplink_arch});
+# If asm_arch isn't defined, disable asm
+$disabled{asm} = 'no asm_arch' unless (defined $target{asm_arch});
+
disable(); # Run a cascade now
$target{CXXFLAGS}//=$target{CFLAGS} if $target{CXX};
$target{cxxflags}//=$target{cflags} if $target{CXX};
-$target{exe_extension}="";
-$target{exe_extension}=".exe" if ($config{target} eq "DJGPP"
- || $config{target} =~ /^(?:Cygwin|mingw)/);
+$target{exe_extension}=".exe" if ($config{target} eq "DJGPP");
$target{exe_extension}=".pm" if ($config{target} =~ /vos/);
-($target{shared_extension_simple}=$target{shared_extension})
- =~ s|\.\$\(SHLIB_VERSION_NUMBER\)||
- unless defined($target{shared_extension_simple});
-$target{dso_extension}//=$target{shared_extension_simple};
-($target{shared_import_extension}=$target{shared_extension_simple}.".a")
- if ($config{target} =~ /^(?:Cygwin|mingw)/);
-
# Fill %config with values from %user, and in case those are undefined or
# empty, use values from %target (acting as a default).
foreach (keys %user) {
@@ -1201,7 +1380,7 @@ foreach (keys %useradd) {
# At this point, we can forget everything about %user and %useradd,
# because it's now all been merged into the corresponding $config entry
-if (grep { $_ eq '-static' } @{$config{LDFLAGS}}) {
+if (grep { $_ =~ /(?:^|\s)-static(?:\s|$)/ } @{$config{LDFLAGS}}) {
disable('static', 'pic', 'threads');
}
@@ -1277,19 +1456,35 @@ unless ($disabled{threads}) {
}
}
+# Find out if clang's sanitizers have been enabled with -fsanitize
+# flags and ensure that the corresponding %disabled elements area
+# removed to reflect that the sanitizers are indeed enabled.
+my %detected_sanitizers = ();
+foreach (grep /^-fsanitize=/, @{$config{CFLAGS} || []}) {
+ (my $checks = $_) =~ s/^-fsanitize=//;
+ foreach (split /,/, $checks) {
+ my $d = { address => 'asan',
+ undefined => 'ubsan',
+ memory => 'msan' } -> {$_};
+ next unless defined $d;
+
+ $detected_sanitizers{$d} = 1;
+ if (defined $disabled{$d}) {
+ die "***** Conflict between disabling $d and enabling $_ sanitizer"
+ if $disabled{$d} ne "default";
+ delete $disabled{$d};
+ }
+ }
+}
+
# If threads still aren't disabled, add a C macro to ensure the source
# code knows about it. Any other flag is taken care of by the configs.
unless($disabled{threads}) {
- push @{$config{openssl_thread_defines}}, "OPENSSL_THREADS";
-}
-
-# With "deprecated" disable all deprecated features.
-if (defined($disabled{"deprecated"})) {
- $config{api} = $maxapi;
+ push @{$config{openssl_feature_defines}}, "OPENSSL_THREADS";
}
my $no_shared_warn=0;
-if ($target{shared_target} eq "")
+if (($target{shared_target} // '') eq "")
{
$no_shared_warn = 1
if (!$disabled{shared} || !$disabled{"dynamic-engine"});
@@ -1302,21 +1497,16 @@ if ($disabled{"dynamic-engine"}) {
$config{dynamic_engines} = 1;
}
-unless ($disabled{asan}) {
+unless ($disabled{asan} || defined $detected_sanitizers{asan}) {
push @{$config{cflags}}, "-fsanitize=address";
- push @{$config{cxxflags}}, "-fsanitize=address" if $config{CXX};
}
-unless ($disabled{ubsan}) {
- # -DPEDANTIC or -fnosanitize=alignment may also be required on some
- # platforms.
- push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all";
- push @{$config{cxxflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all" if $config{CXX};
+unless ($disabled{ubsan} || defined $detected_sanitizers{ubsan}) {
+ push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all", "-DPEDANTIC";
}
-unless ($disabled{msan}) {
+unless ($disabled{msan} || defined $detected_sanitizers{msan}) {
push @{$config{cflags}}, "-fsanitize=memory";
- push @{$config{cxxflags}}, "-fsanitize=memory" if $config{CXX};
}
unless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"}
@@ -1350,98 +1540,46 @@ if ($target{sys_id} ne "")
push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}";
}
-unless ($disabled{asm}) {
- $target{cpuid_asm_src}=$table{DEFAULTS}->{cpuid_asm_src} if ($config{processor} eq "386");
- push @{$config{lib_defines}}, "OPENSSL_CPUID_OBJ" if ($target{cpuid_asm_src} ne "mem_clr.c");
-
- $target{bn_asm_src} =~ s/\w+-gf2m.c// if (defined($disabled{ec2m}));
-
- # bn-586 is the only one implementing bn_*_part_words
- push @{$config{lib_defines}}, "OPENSSL_BN_ASM_PART_WORDS" if ($target{bn_asm_src} =~ /bn-586/);
- push @{$config{lib_defines}}, "OPENSSL_IA32_SSE2" if (!$disabled{sse2} && $target{bn_asm_src} =~ /86/);
-
- push @{$config{lib_defines}}, "OPENSSL_BN_ASM_MONT" if ($target{bn_asm_src} =~ /-mont/);
- push @{$config{lib_defines}}, "OPENSSL_BN_ASM_MONT5" if ($target{bn_asm_src} =~ /-mont5/);
- push @{$config{lib_defines}}, "OPENSSL_BN_ASM_GF2m" if ($target{bn_asm_src} =~ /-gf2m/);
- push @{$config{lib_defines}}, "BN_DIV3W" if ($target{bn_asm_src} =~ /-div3w/);
-
- if ($target{sha1_asm_src}) {
- push @{$config{lib_defines}}, "SHA1_ASM" if ($target{sha1_asm_src} =~ /sx86/ || $target{sha1_asm_src} =~ /sha1/);
- push @{$config{lib_defines}}, "SHA256_ASM" if ($target{sha1_asm_src} =~ /sha256/);
- push @{$config{lib_defines}}, "SHA512_ASM" if ($target{sha1_asm_src} =~ /sha512/);
- }
- if ($target{keccak1600_asm_src} ne $table{DEFAULTS}->{keccak1600_asm_src}) {
- push @{$config{lib_defines}}, "KECCAK1600_ASM";
- }
- if ($target{rc4_asm_src} ne $table{DEFAULTS}->{rc4_asm_src}) {
- push @{$config{lib_defines}}, "RC4_ASM";
- }
- if ($target{md5_asm_src}) {
- push @{$config{lib_defines}}, "MD5_ASM";
- }
- $target{cast_asm_src}=$table{DEFAULTS}->{cast_asm_src} unless $disabled{pic}; # CAST assembler is not PIC
- if ($target{rmd160_asm_src}) {
- push @{$config{lib_defines}}, "RMD160_ASM";
- }
- if ($target{aes_asm_src}) {
- push @{$config{lib_defines}}, "AES_ASM" if ($target{aes_asm_src} =~ m/\baes-/);;
- push @{$config{lib_defines}}, "AESNI_ASM" if ($target{aes_asm_src} =~ m/\baesni-/);;
- # aes-ctr.fake is not a real file, only indication that assembler
- # module implements AES_ctr32_encrypt...
- push @{$config{lib_defines}}, "AES_CTR_ASM" if ($target{aes_asm_src} =~ s/\s*aes-ctr\.fake//);
- # aes-xts.fake indicates presence of AES_xts_[en|de]crypt...
- push @{$config{lib_defines}}, "AES_XTS_ASM" if ($target{aes_asm_src} =~ s/\s*aes-xts\.fake//);
- $target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($disabled{sse2});
- push @{$config{lib_defines}}, "VPAES_ASM" if ($target{aes_asm_src} =~ m/vpaes/);
- push @{$config{lib_defines}}, "BSAES_ASM" if ($target{aes_asm_src} =~ m/bsaes/);
- }
- if ($target{wp_asm_src} =~ /mmx/) {
- if ($config{processor} eq "386") {
- $target{wp_asm_src}=$table{DEFAULTS}->{wp_asm_src};
- } elsif (!$disabled{"whirlpool"}) {
- push @{$config{lib_defines}}, "WHIRLPOOL_ASM";
- }
- }
- if ($target{modes_asm_src} =~ /ghash-/) {
- push @{$config{lib_defines}}, "GHASH_ASM";
- }
- if ($target{ec_asm_src} =~ /ecp_nistz256/) {
- push @{$config{lib_defines}}, "ECP_NISTZ256_ASM";
- }
- if ($target{ec_asm_src} =~ /x25519/) {
- push @{$config{lib_defines}}, "X25519_ASM";
- }
- if ($target{padlock_asm_src} ne $table{DEFAULTS}->{padlock_asm_src}) {
- push @{$config{dso_defines}}, "PADLOCK_ASM";
- }
- if ($target{poly1305_asm_src} ne "") {
- push @{$config{lib_defines}}, "POLY1305_ASM";
- }
-}
-
my %predefined_C = compiler_predefined($config{CROSS_COMPILE}.$config{CC});
my %predefined_CXX = $config{CXX}
? compiler_predefined($config{CROSS_COMPILE}.$config{CXX})
: ();
+unless ($disabled{asm}) {
+ # big endian systems can use ELFv2 ABI
+ if ($target eq "linux-ppc64") {
+ $target{perlasm_scheme} = "linux64v2" if ($predefined_C{_CALL_ELF} == 2);
+ }
+}
+
# Check for makedepend capabilities.
if (!$disabled{makedepend}) {
- if ($config{target} =~ /^(VC|vms)-/) {
- # For VC- and vms- targets, there's nothing more to do here. The
- # functionality is hard coded in the corresponding build files for
- # cl (Windows) and CC/DECC (VMS).
+ # If the attribute makedep_scheme is defined, then we assume that the
+ # config target and its associated build file are programmed to deal
+ # with it.
+ # If makedep_scheme is undefined, we go looking for GCC compatible
+ # dependency making, and if that's not available, we try to fall back
+ # on 'makedepend'.
+ if ($target{makedep_scheme}) {
+ $config{makedep_scheme} = $target{makedep_scheme};
+ # If the makedepcmd attribute is defined, copy it. If not, the
+ # build files will have to fend for themselves.
+ $config{makedepcmd} = $target{makedepcmd} if $target{makedepcmd};
} elsif (($predefined_C{__GNUC__} // -1) >= 3
&& !($predefined_C{__APPLE_CC__} && !$predefined_C{__clang__})) {
# We know that GNU C version 3 and up as well as all clang
# versions support dependency generation, but Xcode did not
# handle $cc -M before clang support (but claims __GNUC__ = 3)
- $config{makedepprog} = "\$(CROSS_COMPILE)$config{CC}";
+ $config{makedep_scheme} = 'gcc';
} else {
- # In all other cases, we look for 'makedepend', and disable the
- # capability if not found.
- $config{makedepprog} = which('makedepend');
- disable('unavailable', 'makedepend') unless $config{makedepprog};
+ # In all other cases, we look for 'makedepend', and set the
+ # makedep_scheme value if we found it.
+ $config{makedepcmd} = which('makedepend');
+ $config{makedep_scheme} = 'makedepend' if $config{makedepcmd};
}
+
+ # If no depend scheme is set, we disable makedepend
+ disable('unavailable', 'makedepend') unless $config{makedep_scheme};
}
if (!$disabled{asm} && !$predefined_C{__MACH__} && $^O ne 'VMS') {
@@ -1469,7 +1607,6 @@ if (!$disabled{asm} && !$predefined_C{__MACH__} && $^O ne 'VMS') {
# Deal with bn_ops ###################################################
$config{bn_ll} =0;
-$config{export_var_as_fn} =0;
my $def_int="unsigned int";
$config{rc4_int} =$def_int;
($config{b64l},$config{b64},$config{b32})=(0,0,1);
@@ -1477,7 +1614,6 @@ $config{rc4_int} =$def_int;
my $count = 0;
foreach (sort split(/\s+/,$target{bn_ops})) {
$count++ if /SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT/;
- $config{export_var_as_fn}=1 if $_ eq 'EXPORT_VAR_AS_FN';
$config{bn_ll}=1 if $_ eq 'BN_LLONG';
$config{rc4_int}="unsigned char" if $_ eq 'RC4_CHAR';
($config{b64l},$config{b64},$config{b32})
@@ -1490,6 +1626,14 @@ foreach (sort split(/\s+/,$target{bn_ops})) {
die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set in bn_ops\n"
if $count > 1;
+$config{api} = $config{major} * 10000 + $config{minor} * 100
+ unless $config{api};
+foreach (keys %$apitable) {
+ $disabled{"deprecated-$_"} = "deprecation"
+ if $disabled{deprecated} && $config{api} >= $apitable->{$_};
+}
+
+disable(); # Run a cascade now
# Hack cflags for better warnings (dev option) #######################
@@ -1500,11 +1644,9 @@ $config{cflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x }
$config{cxxflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x }
@{$config{cxxflags}} ] if $config{CXX};
-if (defined($config{api})) {
- $config{openssl_api_defines} = [ "OPENSSL_MIN_API=".$apitable->{$config{api}} ];
- my $apiflag = sprintf("OPENSSL_API_COMPAT=%s", $apitable->{$config{api}});
- push @{$config{defines}}, $apiflag;
-}
+$config{openssl_api_defines} = [
+ "OPENSSL_CONFIGURED_API=".$config{api},
+];
my @strict_warnings_collection=();
if ($strict_warnings)
@@ -1533,19 +1675,6 @@ $config{CFLAGS} = [ map { $_ eq '--ossl-strict-warnings'
: ( $_ ) }
@{$config{CFLAGS}} ];
-unless ($disabled{"crypto-mdebug-backtrace"})
- {
- foreach my $wopt (split /\s+/, $memleak_devteam_backtrace)
- {
- push @{$config{cflags}}, $wopt
- unless grep { $_ eq $wopt } @{$config{cflags}};
- }
- if ($target =~ /^BSD-/)
- {
- push @{$config{ex_libs}}, "-lexecinfo";
- }
- }
-
unless ($disabled{afalgeng}) {
$config{afalgeng}="";
if (grep { $_ eq 'afalgeng' } @{$target{enable}}) {
@@ -1583,6 +1712,26 @@ unless ($disabled{devcryptoeng}) {
}
}
+unless ($disabled{ktls}) {
+ $config{ktls}="";
+ my $cc = $config{CROSS_COMPILE}.$config{CC};
+ if ($target =~ m/^linux/) {
+ system("printf '#include <sys/types.h>\n#include <linux/tls.h>' | $cc -E - >/dev/null 2>&1");
+ if ($? != 0) {
+ disable('too-old-kernel', 'ktls');
+ }
+ } elsif ($target =~ m/^BSD/) {
+ system("printf '#include <sys/types.h>\n#include <sys/ktls.h>' | $cc -E - >/dev/null 2>&1");
+ if ($? != 0) {
+ disable('too-old-freebsd', 'ktls');
+ }
+ } else {
+ disable('not-linux-or-freebsd', 'ktls');
+ }
+}
+
+push @{$config{openssl_other_defines}}, "OPENSSL_NO_KTLS" if ($disabled{ktls});
+
# Get the extra flags used when building shared libraries and modules. We
# do this late because some of them depend on %disabled.
@@ -1626,47 +1775,53 @@ $target{module_ldflags} = $target{shared_ldflag} unless defined $target{module_l
# ALL MODIFICATIONS TO %disabled, %config and %target MUST BE DONE FROM HERE ON
+######################################################################
+# Build up information for skipping certain directories depending on disabled
+# features, as well as setting up macros for disabled features.
+
+# This is a tentative database of directories to skip. Some entries may not
+# correspond to anything real, but that's ok, they will simply be ignored.
+# The actual processing of these entries is done in the build.info lookup
+# loop further down.
+#
+# The key is a Unix formatted path in the source tree, the value is an index
+# into %disabled_info, so any existing path gets added to a corresponding
+# 'skipped' entry in there with the list of skipped directories.
+my %skipdir = ();
my %disabled_info = (); # For configdata.pm
foreach my $what (sort keys %disabled) {
+ # There are deprecated disablables that translate to themselves.
+ # They cause disabling cascades, but should otherwise not regiter.
+ next if $deprecated_disablables{$what};
+ # The generated $disabled{"deprecated-x.y"} entries are special
+ # and treated properly elsewhere
+ next if $what =~ m|^deprecated-|;
+
$config{options} .= " no-$what";
- if (!grep { $what eq $_ } ( 'buildtest-c++', 'threads', 'shared', 'pic',
- 'dynamic-engine', 'makedepend',
- 'zlib-dynamic', 'zlib', 'sse2' )) {
+ if (!grep { $what eq $_ } ( 'buildtest-c++', 'fips', 'threads', 'shared',
+ 'module', 'pic', 'dynamic-engine', 'makedepend',
+ 'zlib-dynamic', 'zlib', 'sse2', 'legacy' )) {
(my $WHAT = uc $what) =~ s|-|_|g;
-
- # Fix up C macro end names
- $WHAT = "RMD160" if $what eq "ripemd";
+ my $skipdir = $what;
# fix-up crypto/directory name(s)
- $what = "ripemd" if $what eq "rmd160";
- $what = "whrlpool" if $what eq "whirlpool";
+ $skipdir = "ripemd" if $what eq "rmd160";
+ $skipdir = "whrlpool" if $what eq "whirlpool";
my $macro = $disabled_info{$what}->{macro} = "OPENSSL_NO_$WHAT";
+ push @{$config{openssl_feature_defines}}, $macro;
- if ((grep { $what eq $_ } @{$config{sdirs}})
- && $what ne 'async' && $what ne 'err' && $what ne 'dso') {
- @{$config{sdirs}} = grep { $what ne $_} @{$config{sdirs}};
- $disabled_info{$what}->{skipped} = [ catdir('crypto', $what) ];
-
- if ($what ne 'engine') {
- push @{$config{openssl_algorithm_defines}}, $macro;
- } else {
- @{$config{dirs}} = grep !/^engines$/, @{$config{dirs}};
- push @{$disabled_info{engine}->{skipped}}, catdir('engines');
- push @{$config{openssl_other_defines}}, $macro;
- }
- } else {
- push @{$config{openssl_other_defines}}, $macro;
- }
-
+ $skipdir{engines} = $what if $what eq 'engine';
+ $skipdir{"crypto/$skipdir"} = $what
+ unless $what eq 'async' || $what eq 'err' || $what eq 'dso';
}
}
if ($disabled{"dynamic-engine"}) {
- push @{$config{openssl_other_defines}}, "OPENSSL_NO_DYNAMIC_ENGINE";
+ push @{$config{openssl_feature_defines}}, "OPENSSL_NO_DYNAMIC_ENGINE";
} else {
- push @{$config{openssl_other_defines}}, "OPENSSL_NO_STATIC_ENGINE";
+ push @{$config{openssl_feature_defines}}, "OPENSSL_NO_STATIC_ENGINE";
}
# If we use the unified build, collect information from build.info files
@@ -1674,7 +1829,7 @@ my %unified_info = ();
my $buildinfo_debug = defined($ENV{CONFIGURE_DEBUG_BUILDINFO});
if ($builder eq "unified") {
- use with_fallback qw(Text::Template);
+ use Text::Template 1.46;
sub cleandir {
my $base = shift;
@@ -1748,64 +1903,174 @@ if ($builder eq "unified") {
$config{build_file_templates}
= [ cleanfile($srcdir, catfile("Configurations", "common0.tmpl"),
$blddir),
- $build_file_template,
- cleanfile($srcdir, catfile("Configurations", "common.tmpl"),
- $blddir) ];
+ $build_file_template ];
- my @build_infos = ( [ ".", "build.info" ] );
- foreach (@{$config{dirs}}) {
- push @build_infos, [ $_, "build.info" ]
- if (-f catfile($srcdir, $_, "build.info"));
- }
- foreach (@{$config{sdirs}}) {
- push @build_infos, [ catdir("crypto", $_), "build.info" ]
- if (-f catfile($srcdir, "crypto", $_, "build.info"));
- }
- foreach (@{$config{engdirs}}) {
- push @build_infos, [ catdir("engines", $_), "build.info" ]
- if (-f catfile($srcdir, "engines", $_, "build.info"));
- }
- foreach (@{$config{tdirs}}) {
- push @build_infos, [ catdir("test", $_), "build.info" ]
- if (-f catfile($srcdir, "test", $_, "build.info"));
- }
+ my @build_dirs = ( [ ] ); # current directory
$config{build_infos} = [ ];
+ # We want to detect configdata.pm in the source tree, so we
+ # don't use it if the build tree is different.
+ my $src_configdata = cleanfile($srcdir, "configdata.pm", $blddir);
+
+ # Any source file that we recognise is placed in this hash table, with
+ # the list of its intended destinations as value. When everything has
+ # been collected, there's a routine that checks that these source files
+ # exist, or if they are generated, that the generator exists.
+ my %check_exist = ();
+ my %check_generate = ();
+
my %ordinals = ();
- foreach (@build_infos) {
- my $sourced = catdir($srcdir, $_->[0]);
- my $buildd = catdir($blddir, $_->[0]);
+ while (@build_dirs) {
+ my @curd = @{shift @build_dirs};
+ my $sourced = catdir($srcdir, @curd);
+ my $buildd = catdir($blddir, @curd);
+
+ my $unixdir = join('/', @curd);
+ if (exists $skipdir{$unixdir}) {
+ my $what = $skipdir{$unixdir};
+ push @{$disabled_info{$what}->{skipped}}, catdir(@curd);
+ next;
+ }
mkpath($buildd);
- my $f = $_->[1];
+ my $f = 'build.info';
# The basic things we're trying to build
my @programs = ();
- my @programs_install = ();
my @libraries = ();
- my @libraries_install = ();
- my @engines = ();
- my @engines_install = ();
+ my @modules = ();
my @scripts = ();
- my @scripts_install = ();
- my @extra = ();
- my @overrides = ();
- my @intermediates = ();
- my @rawlines = ();
my %sources = ();
my %shared_sources = ();
my %includes = ();
+ my %defines = ();
my %depends = ();
- my %renames = ();
- my %sharednames = ();
my %generate = ();
+ my %imagedocs = ();
+ my %htmldocs = ();
+ my %mandocs = ();
+
+ # Support for $variablename in build.info files.
+ # Embedded perl code is the ultimate master, still. If its output
+ # contains a dollar sign, it had better be escaped, or it will be
+ # taken for a variable name prefix.
+ my %variables = ();
+ # Variable name syntax
+ my $variable_name_re = qr/(?P<VARIABLE>[[:alpha:]][[:alnum:]_]*)/;
+ # Value modifier syntaxes
+ my $variable_subst_re = qr/\/(?P<RE>(?:\\\/|.)*?)\/(?P<SUBST>.*?)/;
+ # Variable reference
+ my $variable_simple_re = qr/(?<!\\)\$${variable_name_re}/;
+ my $variable_w_mod_re =
+ qr/(?<!\\)\$\{${variable_name_re}(?P<MOD>(?:\\\/|.)*?)\}/;
+ # Tie it all together
+ my $variable_re = qr/${variable_simple_re}|${variable_w_mod_re}/;
+
+ my $expand_variables = sub {
+ my $value = '';
+ my $value_rest = shift;
+
+ if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) {
+ print STDERR
+ "DEBUG[\$expand_variables] Parsed '$value_rest' ...\n"
+ }
+
+ while ($value_rest =~ /${variable_re}/) {
+ # We must save important regexp values, because the next
+ # regexp clears them
+ my $mod = $+{MOD};
+ my $variable_value = $variables{$+{VARIABLE}};
+
+ $value_rest = $';
+ $value .= $`;
+
+ # Process modifier expressions, if present
+ if (defined $mod) {
+ if ($mod =~ /^${variable_subst_re}$/) {
+ my $re = $+{RE};
+ my $subst = $+{SUBST};
- # We want to detect configdata.pm in the source tree, so we
- # don't use it if the build tree is different.
- my $src_configdata = cleanfile($srcdir, "configdata.pm", $blddir);
+ $variable_value =~ s/\Q$re\E/$subst/g;
+
+ if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) {
+ print STDERR
+ "DEBUG[\$expand_variables] ... and substituted ",
+ "'$re' with '$subst'\n";
+ }
+ }
+ }
+
+ $value .= $variable_value;
+ }
+ if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) {
+ print STDERR
+ "DEBUG[\$expand_variables] ... into: '$value$value_rest'\n";
+ }
+ return $value . $value_rest;
+ };
+
+ # Support for attributes in build.info files
+ my %attributes = ();
+ my $handle_attributes = sub {
+ my $attr_str = shift;
+ my $ref = shift;
+ my @goals = @_;
+
+ return unless defined $attr_str;
+
+ my @a = tokenize($attr_str, qr|\s*,\s*|);
+ foreach my $a (@a) {
+ my $ac = 1;
+ my $ak = $a;
+ my $av = 1;
+ if ($a =~ m|^(!)?(.*?)\s* = \s*(.*?)$|x) {
+ $ac = ! $1;
+ $ak = $2;
+ $av = $3;
+ }
+ foreach my $g (@goals) {
+ if ($ac) {
+ $$ref->{$g}->{$ak} = $av;
+ } else {
+ delete $$ref->{$g}->{$ak};
+ }
+ }
+ }
+ };
+
+ # Support for pushing values on multiple indexes of a given hash
+ # array.
+ my $push_to = sub {
+ my $valueref = shift;
+ my $index_str = shift; # May be undef or empty
+ my $attrref = shift; # May be undef
+ my $attr_str = shift;
+ my @values = @_;
+
+ if (defined $index_str) {
+ my @indexes = ( '' );
+ if ($index_str !~ m|^\s*$|) {
+ @indexes = tokenize($index_str);
+ }
+ foreach (@indexes) {
+ push @{$valueref->{$_}}, @values;
+ if (defined $attrref) {
+ $handle_attributes->($attr_str, \$$attrref->{$_},
+ @values);
+ }
+ }
+ } else {
+ push @$valueref, @values;
+ $handle_attributes->($attr_str, $attrref, @values)
+ if defined $attrref;
+ }
+ };
+ if ($buildinfo_debug) {
+ print STDERR "DEBUG: Reading ",catfile($sourced, $f),"\n";
+ }
push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f);
my $template =
Text::Template->new(TYPE => 'FILE',
@@ -1831,117 +2096,118 @@ if ($builder eq "unified") {
# 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF)
# 2 positive ELSE (following ELSIF should fail)
my @skip = ();
+
+ # A few useful generic regexps
+ my $index_re = qr/\[\s*(?P<INDEX>(?:\\.|.)*?)\s*\]/;
+ my $cond_re = qr/\[\s*(?P<COND>(?:\\.|.)*?)\s*\]/;
+ my $attribs_re = qr/(?:\{\s*(?P<ATTRIBS>(?:\\.|.)*?)\s*\})?/;
+ my $value_re = qr/(?P<VALUE>.*?)/;
collect_information(
collect_from_array([ @text ],
qr/\\$/ => sub { my $l1 = shift; my $l2 = shift;
$l1 =~ s/\\$//; $l1.$l2 }),
# Info we're looking for
- qr/^\s*IF\[((?:\\.|[^\\\]])*)\]\s*$/
+ qr/^\s* IF ${cond_re} \s*$/x
=> sub {
if (! @skip || $skip[$#skip] > 0) {
- push @skip, !! $1;
+ push @skip, !! $expand_variables->($+{COND});
} else {
push @skip, -1;
}
},
- qr/^\s*ELSIF\[((?:\\.|[^\\\]])*)\]\s*$/
+ qr/^\s* ELSIF ${cond_re} \s*$/x
=> sub { die "ELSIF out of scope" if ! @skip;
die "ELSIF following ELSE" if abs($skip[$#skip]) == 2;
$skip[$#skip] = -1 if $skip[$#skip] != 0;
- $skip[$#skip] = !! $1
+ $skip[$#skip] = !! $expand_variables->($+{COND})
if $skip[$#skip] == 0; },
- qr/^\s*ELSE\s*$/
+ qr/^\s* ELSE \s*$/x
=> sub { die "ELSE out of scope" if ! @skip;
$skip[$#skip] = -2 if $skip[$#skip] != 0;
$skip[$#skip] = 2 if $skip[$#skip] == 0; },
- qr/^\s*ENDIF\s*$/
+ qr/^\s* ENDIF \s*$/x
=> sub { die "ENDIF out of scope" if ! @skip;
pop @skip; },
- qr/^\s*PROGRAMS(_NO_INST)?\s*=\s*(.*)\s*$/
- => sub {
- if (!@skip || $skip[$#skip] > 0) {
- my $install = $1;
- my @x = tokenize($2);
- push @programs, @x;
- push @programs_install, @x unless $install;
- }
- },
- qr/^\s*LIBS(_NO_INST)?\s*=\s*(.*)\s*$/
+ qr/^\s* ${variable_re} \s* = \s* ${value_re} \s* $/x
=> sub {
if (!@skip || $skip[$#skip] > 0) {
- my $install = $1;
- my @x = tokenize($2);
- push @libraries, @x;
- push @libraries_install, @x unless $install;
+ $variables{$+{VARIABLE}} = $expand_variables->($+{VALUE});
}
},
- qr/^\s*ENGINES(_NO_INST)?\s*=\s*(.*)\s*$/
+ qr/^\s* SUBDIRS \s* = \s* ${value_re} \s* $/x
=> sub {
if (!@skip || $skip[$#skip] > 0) {
- my $install = $1;
- my @x = tokenize($2);
- push @engines, @x;
- push @engines_install, @x unless $install;
- }
- },
- qr/^\s*SCRIPTS(_NO_INST)?\s*=\s*(.*)\s*$/
- => sub {
- if (!@skip || $skip[$#skip] > 0) {
- my $install = $1;
- my @x = tokenize($2);
- push @scripts, @x;
- push @scripts_install, @x unless $install;
- }
- },
- qr/^\s*EXTRA\s*=\s*(.*)\s*$/
- => sub { push @extra, tokenize($1)
- if !@skip || $skip[$#skip] > 0 },
- qr/^\s*OVERRIDES\s*=\s*(.*)\s*$/
- => sub { push @overrides, tokenize($1)
- if !@skip || $skip[$#skip] > 0 },
-
- qr/^\s*ORDINALS\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/,
- => sub { push @{$ordinals{$1}}, tokenize($2)
- if !@skip || $skip[$#skip] > 0 },
- qr/^\s*SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
- => sub { push @{$sources{$1}}, tokenize($2)
- if !@skip || $skip[$#skip] > 0 },
- qr/^\s*SHARED_SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
- => sub { push @{$shared_sources{$1}}, tokenize($2)
- if !@skip || $skip[$#skip] > 0 },
- qr/^\s*INCLUDE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
- => sub { push @{$includes{$1}}, tokenize($2)
- if !@skip || $skip[$#skip] > 0 },
- qr/^\s*DEPEND\[((?:\\.|[^\\\]])*)\]\s*=\s*(.*)\s*$/
- => sub { push @{$depends{$1}}, tokenize($2)
- if !@skip || $skip[$#skip] > 0 },
- qr/^\s*GENERATE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
- => sub { push @{$generate{$1}}, $2
- if !@skip || $skip[$#skip] > 0 },
- qr/^\s*RENAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
- => sub { push @{$renames{$1}}, tokenize($2)
- if !@skip || $skip[$#skip] > 0 },
- qr/^\s*SHARED_NAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
- => sub { push @{$sharednames{$1}}, tokenize($2)
- if !@skip || $skip[$#skip] > 0 },
- qr/^\s*BEGINRAW\[((?:\\.|[^\\\]])+)\]\s*$/
- => sub {
- my $lineiterator = shift;
- my $target_kind = $1;
- while (defined $lineiterator->()) {
- s|\R$||;
- if (/^\s*ENDRAW\[((?:\\.|[^\\\]])+)\]\s*$/) {
- die "ENDRAW doesn't match BEGINRAW"
- if $1 ne $target_kind;
- last;
+ foreach (tokenize($expand_variables->($+{VALUE}))) {
+ push @build_dirs, [ @curd, splitdir($_, 1) ];
}
- next if @skip && $skip[$#skip] <= 0;
- push @rawlines, $_
- if ($target_kind eq $config{build_file}
- || $target_kind eq $config{build_file}."(".$builder_platform.")");
}
},
- qr/^\s*(?:#.*)?$/ => sub { },
+ qr/^\s* PROGRAMS ${attribs_re} \s* = \s* ${value_re} \s* $/x
+ => sub { $push_to->(\@programs, undef,
+ \$attributes{programs}, $+{ATTRIBS},
+ tokenize($expand_variables->($+{VALUE})))
+ if !@skip || $skip[$#skip] > 0; },
+ qr/^\s* LIBS ${attribs_re} \s* = \s* ${value_re} \s* $/x
+ => sub { $push_to->(\@libraries, undef,
+ \$attributes{libraries}, $+{ATTRIBS},
+ tokenize($expand_variables->($+{VALUE})))
+ if !@skip || $skip[$#skip] > 0; },
+ qr/^\s* MODULES ${attribs_re} \s* = \s* ${value_re} \s* $/x
+ => sub { $push_to->(\@modules, undef,
+ \$attributes{modules}, $+{ATTRIBS},
+ tokenize($expand_variables->($+{VALUE})))
+ if !@skip || $skip[$#skip] > 0; },
+ qr/^\s* SCRIPTS ${attribs_re} \s* = \s* ${value_re} \s* $/x
+ => sub { $push_to->(\@scripts, undef,
+ \$attributes{scripts}, $+{ATTRIBS},
+ tokenize($expand_variables->($+{VALUE})))
+ if !@skip || $skip[$#skip] > 0; },
+ qr/^\s* IMAGEDOCS ${index_re} \s* = \s* ${value_re} \s* $/x
+ => sub { $push_to->(\%imagedocs, $expand_variables->($+{INDEX}),
+ undef, undef,
+ tokenize($expand_variables->($+{VALUE})))
+ if !@skip || $skip[$#skip] > 0; },
+ qr/^\s* HTMLDOCS ${index_re} \s* = \s* ${value_re} \s* $/x
+ => sub { $push_to->(\%htmldocs, $expand_variables->($+{INDEX}),
+ undef, undef,
+ tokenize($expand_variables->($+{VALUE})))
+ if !@skip || $skip[$#skip] > 0; },
+ qr/^\s* MANDOCS ${index_re} \s* = \s* ${value_re} \s* $/x
+ => sub { $push_to->(\%mandocs, $expand_variables->($+{INDEX}),
+ undef, undef,
+ tokenize($expand_variables->($+{VALUE})))
+ if !@skip || $skip[$#skip] > 0; },
+ qr/^\s* SOURCE ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x
+ => sub { $push_to->(\%sources, $expand_variables->($+{INDEX}),
+ \$attributes{sources}, $+{ATTRIBS},
+ tokenize($expand_variables->($+{VALUE})))
+ if !@skip || $skip[$#skip] > 0; },
+ qr/^\s* SHARED_SOURCE ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x
+ => sub { $push_to->(\%shared_sources, $expand_variables->($+{INDEX}),
+ \$attributes{sources}, $+{ATTRIBS},
+ tokenize($expand_variables->($+{VALUE})))
+ if !@skip || $skip[$#skip] > 0; },
+ qr/^\s* INCLUDE ${index_re} \s* = \s* ${value_re} \s* $/x
+ => sub { $push_to->(\%includes, $expand_variables->($+{INDEX}),
+ undef, undef,
+ tokenize($expand_variables->($+{VALUE})))
+ if !@skip || $skip[$#skip] > 0; },
+ qr/^\s* DEFINE ${index_re} \s* = \s* ${value_re} \s* $/x
+ => sub { $push_to->(\%defines, $expand_variables->($+{INDEX}),
+ undef, undef,
+ tokenize($expand_variables->($+{VALUE})))
+ if !@skip || $skip[$#skip] > 0; },
+ qr/^\s* DEPEND ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x
+ => sub { $push_to->(\%depends, $expand_variables->($+{INDEX}),
+ \$attributes{depends}, $+{ATTRIBS},
+ tokenize($expand_variables->($+{VALUE})))
+ if !@skip || $skip[$#skip] > 0; },
+ qr/^\s* GENERATE ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x
+ => sub { $push_to->(\%generate, $expand_variables->($+{INDEX}),
+ \$attributes{generate}, $+{ATTRIBS},
+ $expand_variables->($+{VALUE}))
+ if !@skip || $skip[$#skip] > 0; },
+ qr/^\s* (?:\#.*)? $/x => sub { },
"OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" },
"BEFORE" => sub {
if ($buildinfo_debug) {
@@ -1957,269 +2223,200 @@ if ($builder eq "unified") {
);
die "runaway IF?" if (@skip);
- foreach (keys %renames) {
- die "$_ renamed to more than one thing: "
- ,join(" ", @{$renames{$_}}),"\n"
- if scalar @{$renames{$_}} > 1;
- my $dest = cleanfile($buildd, $_, $blddir);
- my $to = cleanfile($buildd, $renames{$_}->[0], $blddir);
- die "$dest renamed to more than one thing: "
- ,$unified_info{rename}->{$dest}, $to
- unless !defined($unified_info{rename}->{$dest})
- or $unified_info{rename}->{$dest} eq $to;
- $unified_info{rename}->{$dest} = $to;
- }
-
- foreach (@programs) {
- my $program = cleanfile($buildd, $_, $blddir);
- if ($unified_info{rename}->{$program}) {
- $program = $unified_info{rename}->{$program};
- }
- $unified_info{programs}->{$program} = 1;
- }
-
- foreach (@programs_install) {
- my $program = cleanfile($buildd, $_, $blddir);
- if ($unified_info{rename}->{$program}) {
- $program = $unified_info{rename}->{$program};
- }
- $unified_info{install}->{programs}->{$program} = 1;
- }
-
- foreach (@libraries) {
- my $library = cleanfile($buildd, $_, $blddir);
- if ($unified_info{rename}->{$library}) {
- $library = $unified_info{rename}->{$library};
- }
- $unified_info{libraries}->{$library} = 1;
- }
-
- foreach (@libraries_install) {
- my $library = cleanfile($buildd, $_, $blddir);
- if ($unified_info{rename}->{$library}) {
- $library = $unified_info{rename}->{$library};
- }
- $unified_info{install}->{libraries}->{$library} = 1;
- }
-
- die <<"EOF" if scalar @engines and !$config{dynamic_engines};
+ if (grep { defined $attributes{modules}->{$_}->{engine} } keys %attributes
+ and !$config{dynamic_engines}) {
+ die <<"EOF"
ENGINES can only be used if configured with 'dynamic-engine'.
This is usually a fault in a build.info file.
EOF
- foreach (@engines) {
- my $library = cleanfile($buildd, $_, $blddir);
- if ($unified_info{rename}->{$library}) {
- $library = $unified_info{rename}->{$library};
- }
- $unified_info{engines}->{$library} = 1;
}
- foreach (@engines_install) {
- my $library = cleanfile($buildd, $_, $blddir);
- if ($unified_info{rename}->{$library}) {
- $library = $unified_info{rename}->{$library};
- }
- $unified_info{install}->{engines}->{$library} = 1;
- }
-
- foreach (@scripts) {
- my $script = cleanfile($buildd, $_, $blddir);
- if ($unified_info{rename}->{$script}) {
- $script = $unified_info{rename}->{$script};
- }
- $unified_info{scripts}->{$script} = 1;
- }
-
- foreach (@scripts_install) {
- my $script = cleanfile($buildd, $_, $blddir);
- if ($unified_info{rename}->{$script}) {
- $script = $unified_info{rename}->{$script};
- }
- $unified_info{install}->{scripts}->{$script} = 1;
- }
-
- foreach (@extra) {
- my $extra = cleanfile($buildd, $_, $blddir);
- $unified_info{extra}->{$extra} = 1;
- }
-
- foreach (@overrides) {
- my $override = cleanfile($buildd, $_, $blddir);
- $unified_info{overrides}->{$override} = 1;
- }
-
- push @{$unified_info{rawlines}}, @rawlines;
-
- unless ($disabled{shared}) {
- # Check sharednames.
- foreach (keys %sharednames) {
- my $dest = cleanfile($buildd, $_, $blddir);
- if ($unified_info{rename}->{$dest}) {
- $dest = $unified_info{rename}->{$dest};
- }
- die "shared_name for $dest with multiple values: "
- ,join(" ", @{$sharednames{$_}}),"\n"
- if scalar @{$sharednames{$_}} > 1;
- my $to = cleanfile($buildd, $sharednames{$_}->[0], $blddir);
- die "shared_name found for a library $dest that isn't defined\n"
- unless $unified_info{libraries}->{$dest};
- die "shared_name for $dest with multiple values: "
- ,$unified_info{sharednames}->{$dest}, ", ", $to
- unless !defined($unified_info{sharednames}->{$dest})
- or $unified_info{sharednames}->{$dest} eq $to;
- $unified_info{sharednames}->{$dest} = $to;
- }
-
- # Additionally, we set up sharednames for libraries that don't
- # have any, as themselves. Only for libraries that aren't
- # explicitly static.
- foreach (grep !/\.a$/, keys %{$unified_info{libraries}}) {
- if (!defined $unified_info{sharednames}->{$_}) {
- $unified_info{sharednames}->{$_} = $_
+ {
+ my %infos = ( programs => [ @programs ],
+ libraries => [ @libraries ],
+ modules => [ @modules ],
+ scripts => [ @scripts ] );
+ foreach my $k (keys %infos) {
+ foreach (@{$infos{$k}}) {
+ my $item = cleanfile($buildd, $_, $blddir);
+ $unified_info{$k}->{$item} = 1;
+
+ # Fix up associated attributes
+ $unified_info{attributes}->{$k}->{$item} =
+ $attributes{$k}->{$_}
+ if defined $attributes{$k}->{$_};
}
}
+ }
- # Check that we haven't defined any library as both shared and
- # explicitly static. That is forbidden.
- my @doubles = ();
- foreach (grep /\.a$/, keys %{$unified_info{libraries}}) {
- (my $l = $_) =~ s/\.a$//;
- push @doubles, $l if defined $unified_info{sharednames}->{$l};
- }
- die "these libraries are both explicitly static and shared:\n ",
- join(" ", @doubles), "\n"
- if @doubles;
+ # Check that we haven't defined any library as both shared and
+ # explicitly static. That is forbidden.
+ my @doubles = ();
+ foreach (grep /\.a$/, keys %{$unified_info{libraries}}) {
+ (my $l = $_) =~ s/\.a$//;
+ push @doubles, $l if defined $unified_info{libraries}->{$l};
}
+ die "these libraries are both explicitly static and shared:\n ",
+ join(" ", @doubles), "\n"
+ if @doubles;
foreach (keys %sources) {
my $dest = $_;
my $ddest = cleanfile($buildd, $_, $blddir);
- if ($unified_info{rename}->{$ddest}) {
- $ddest = $unified_info{rename}->{$ddest};
- }
foreach (@{$sources{$dest}}) {
my $s = cleanfile($sourced, $_, $blddir);
- # If it isn't in the source tree, we assume it's generated
- # in the build tree
- if ($s eq $src_configdata || ! -f $s || $generate{$_}) {
+ # If it's generated or we simply don't find it in the source
+ # tree, we assume it's in the build tree.
+ if ($s eq $src_configdata || $generate{$_} || ! -f $s) {
$s = cleanfile($buildd, $_, $blddir);
}
+ my $o = $_;
# We recognise C++, C and asm files
if ($s =~ /\.(cc|cpp|c|s|S)$/) {
- my $o = $_;
+ push @{$check_exist{$s}}, $ddest;
$o =~ s/\.[csS]$/.o/; # C and assembler
$o =~ s/\.(cc|cpp)$/_cc.o/; # C++
$o = cleanfile($buildd, $o, $blddir);
- $unified_info{sources}->{$ddest}->{$o} = 1;
- $unified_info{sources}->{$o}->{$s} = 1;
+ $unified_info{sources}->{$ddest}->{$o} = -1;
+ $unified_info{sources}->{$o}->{$s} = -1;
} elsif ($s =~ /\.rc$/) {
# We also recognise resource files
- my $o = $_;
+ push @{$check_exist{$s}}, $ddest;
$o =~ s/\.rc$/.res/; # Resource configuration
- my $o = cleanfile($buildd, $o, $blddir);
- $unified_info{sources}->{$ddest}->{$o} = 1;
- $unified_info{sources}->{$o}->{$s} = 1;
+ $o = cleanfile($buildd, $o, $blddir);
+ $unified_info{sources}->{$ddest}->{$o} = -1;
+ $unified_info{sources}->{$o}->{$s} = -1;
} else {
+ push @{$check_exist{$s}}, $ddest;
$unified_info{sources}->{$ddest}->{$s} = 1;
}
+ # Fix up associated attributes
+ if ($o ne $_) {
+ $unified_info{attributes}->{sources}->{$ddest}->{$o} =
+ $unified_info{attributes}->{sources}->{$o}->{$s} =
+ $attributes{sources}->{$dest}->{$_}
+ if defined $attributes{sources}->{$dest}->{$_};
+ } else {
+ $unified_info{attributes}->{sources}->{$ddest}->{$s} =
+ $attributes{sources}->{$dest}->{$_}
+ if defined $attributes{sources}->{$dest}->{$_};
+ }
}
}
foreach (keys %shared_sources) {
my $dest = $_;
my $ddest = cleanfile($buildd, $_, $blddir);
- if ($unified_info{rename}->{$ddest}) {
- $ddest = $unified_info{rename}->{$ddest};
- }
foreach (@{$shared_sources{$dest}}) {
my $s = cleanfile($sourced, $_, $blddir);
- # If it isn't in the source tree, we assume it's generated
- # in the build tree
- if ($s eq $src_configdata || ! -f $s || $generate{$_}) {
+ # If it's generated or we simply don't find it in the source
+ # tree, we assume it's in the build tree.
+ if ($s eq $src_configdata || $generate{$_} || ! -f $s) {
$s = cleanfile($buildd, $_, $blddir);
}
+ my $o = $_;
if ($s =~ /\.(cc|cpp|c|s|S)$/) {
# We recognise C++, C and asm files
- my $o = $_;
+ push @{$check_exist{$s}}, $ddest;
$o =~ s/\.[csS]$/.o/; # C and assembler
$o =~ s/\.(cc|cpp)$/_cc.o/; # C++
$o = cleanfile($buildd, $o, $blddir);
- $unified_info{shared_sources}->{$ddest}->{$o} = 1;
- $unified_info{sources}->{$o}->{$s} = 1;
+ $unified_info{shared_sources}->{$ddest}->{$o} = -1;
+ $unified_info{sources}->{$o}->{$s} = -1;
} elsif ($s =~ /\.rc$/) {
# We also recognise resource files
- my $o = $_;
+ push @{$check_exist{$s}}, $ddest;
$o =~ s/\.rc$/.res/; # Resource configuration
- my $o = cleanfile($buildd, $o, $blddir);
- $unified_info{shared_sources}->{$ddest}->{$o} = 1;
- $unified_info{sources}->{$o}->{$s} = 1;
- } elsif ($s =~ /\.(def|map|opt)$/) {
- # We also recognise .def / .map / .opt files
+ $o = cleanfile($buildd, $o, $blddir);
+ $unified_info{shared_sources}->{$ddest}->{$o} = -1;
+ $unified_info{sources}->{$o}->{$s} = -1;
+ } elsif ($s =~ /\.ld$/) {
+ # We also recognise linker scripts (or corresponding)
# We know they are generated files
- my $def = cleanfile($buildd, $s, $blddir);
- $unified_info{shared_sources}->{$ddest}->{$def} = 1;
+ push @{$check_exist{$s}}, $ddest;
+ $o = cleanfile($buildd, $_, $blddir);
+ $unified_info{shared_sources}->{$ddest}->{$o} = 1;
} else {
die "unrecognised source file type for shared library: $s\n";
}
+ # Fix up associated attributes
+ if ($o ne $_) {
+ $unified_info{attributes}->{shared_sources}->{$ddest}->{$o} =
+ $unified_info{attributes}->{sources}->{$o}->{$s} =
+ $attributes{sources}->{$dest}->{$_}
+ if defined $attributes{sources}->{$dest}->{$_};
+ } else {
+ $unified_info{attributes}->{shared_sources}->{$ddest}->{$o} =
+ $attributes{sources}->{$dest}->{$_}
+ if defined $attributes{sources}->{$dest}->{$_};
+ }
}
}
foreach (keys %generate) {
my $dest = $_;
my $ddest = cleanfile($buildd, $_, $blddir);
- if ($unified_info{rename}->{$ddest}) {
- $ddest = $unified_info{rename}->{$ddest};
- }
die "more than one generator for $dest: "
- ,join(" ", @{$generate{$_}}),"\n"
- if scalar @{$generate{$_}} > 1;
+ ,join(" ", @{$generate{$_}}),"\n"
+ if scalar @{$generate{$_}} > 1;
my @generator = split /\s+/, $generate{$dest}->[0];
- $generator[0] = cleanfile($sourced, $generator[0], $blddir),
+ my $gen = $generator[0];
+ $generator[0] = cleanfile($sourced, $gen, $blddir);
+
+ # If the generator is itself generated, it's in the build tree
+ if ($generate{$gen} || ! -f $generator[0]) {
+ $generator[0] = cleanfile($buildd, $gen, $blddir);
+ }
+ $check_generate{$ddest}->{$generator[0]}++;
+
$unified_info{generate}->{$ddest} = [ @generator ];
+ # Fix up associated attributes
+ $unified_info{attributes}->{generate}->{$ddest} =
+ $attributes{generate}->{$dest}->{$gen}
+ if defined $attributes{generate}->{$dest}->{$gen};
}
foreach (keys %depends) {
my $dest = $_;
- my $ddest = $dest eq "" ? "" : cleanfile($sourced, $_, $blddir);
+ my $ddest = $dest;
+
+ if ($dest =~ /^\|(.*)\|$/) {
+ # Collect the raw target
+ $unified_info{targets}->{$1} = 1;
+ $ddest = $1;
+ } elsif ($dest eq '') {
+ $ddest = '';
+ } else {
+ $ddest = cleanfile($sourced, $_, $blddir);
- # If the destination doesn't exist in source, it can only be
- # a generated file in the build tree.
- if ($ddest ne "" && ($ddest eq $src_configdata || ! -f $ddest)) {
- $ddest = cleanfile($buildd, $_, $blddir);
- if ($unified_info{rename}->{$ddest}) {
- $ddest = $unified_info{rename}->{$ddest};
+ # If the destination doesn't exist in source, it can only be
+ # a generated file in the build tree.
+ if ($ddest eq $src_configdata || ! -f $ddest) {
+ $ddest = cleanfile($buildd, $_, $blddir);
}
}
foreach (@{$depends{$dest}}) {
my $d = cleanfile($sourced, $_, $blddir);
+ my $d2 = cleanfile($buildd, $_, $blddir);
# If we know it's generated, or assume it is because we can't
# find it in the source tree, we set file we depend on to be
- # in the build tree rather than the source tree, and assume
- # and that there are lines to build it in a BEGINRAW..ENDRAW
- # section or in the Makefile template.
+ # in the build tree rather than the source tree.
if ($d eq $src_configdata
- || ! -f $d
- || (grep { $d eq $_ }
- map { cleanfile($srcdir, $_, $blddir) }
- grep { /\.h$/ } keys %{$unified_info{generate}})) {
- $d = cleanfile($buildd, $_, $blddir);
- }
- # Take note if the file to depend on is being renamed
- # Take extra care with files ending with .a, they should
- # be treated without that extension, and the extension
- # should be added back after treatment.
- $d =~ /(\.a)?$/;
- my $e = $1 // "";
- $d = $`;
- if ($unified_info{rename}->{$d}) {
- $d = $unified_info{rename}->{$d};
+ || (grep { $d2 eq $_ }
+ keys %{$unified_info{generate}})
+ || ! -f $d) {
+ $d = $d2;
}
- $d .= $e;
$unified_info{depends}->{$ddest}->{$d} = 1;
+
+ # Fix up associated attributes
+ $unified_info{attributes}->{depends}->{$ddest}->{$d} =
+ $attributes{depends}->{$dest}->{$_}
+ if defined $attributes{depends}->{$dest}->{$_};
}
}
@@ -2231,9 +2428,6 @@ EOF
# a generated file in the build tree.
if ($ddest eq $src_configdata || ! -f $ddest) {
$ddest = cleanfile($buildd, $_, $blddir);
- if ($unified_info{rename}->{$ddest}) {
- $ddest = $unified_info{rename}->{$ddest};
- }
}
foreach (@{$includes{$dest}}) {
my $is = cleandir($sourced, $_, $blddir);
@@ -2244,6 +2438,54 @@ EOF
unless grep { $_ eq $ib } @{$unified_info{includes}->{$ddest}->{build}};
}
}
+
+ foreach my $dest (keys %defines) {
+ my $ddest;
+
+ if ($dest ne "") {
+ $ddest = cleanfile($sourced, $dest, $blddir);
+
+ # If the destination doesn't exist in source, it can only
+ # be a generated file in the build tree.
+ if (! -f $ddest) {
+ $ddest = cleanfile($buildd, $dest, $blddir);
+ }
+ }
+ foreach my $v (@{$defines{$dest}}) {
+ $v =~ m|^([^=]*)(=.*)?$|;
+ die "0 length macro name not permitted\n" if $1 eq "";
+ if ($dest ne "") {
+ die "$1 defined more than once\n"
+ if defined $unified_info{defines}->{$ddest}->{$1};
+ $unified_info{defines}->{$ddest}->{$1} = $2;
+ } else {
+ die "$1 defined more than once\n"
+ if grep { $v eq $_ } @{$config{defines}};
+ push @{$config{defines}}, $v;
+ }
+ }
+ }
+
+ foreach my $section (keys %imagedocs) {
+ foreach (@{$imagedocs{$section}}) {
+ my $imagedocs = cleanfile($buildd, $_, $blddir);
+ $unified_info{imagedocs}->{$section}->{$imagedocs} = 1;
+ }
+ }
+
+ foreach my $section (keys %htmldocs) {
+ foreach (@{$htmldocs{$section}}) {
+ my $htmldocs = cleanfile($buildd, $_, $blddir);
+ $unified_info{htmldocs}->{$section}->{$htmldocs} = 1;
+ }
+ }
+
+ foreach my $section (keys %mandocs) {
+ foreach (@{$mandocs{$section}}) {
+ my $mandocs = cleanfile($buildd, $_, $blddir);
+ $unified_info{mandocs}->{$section}->{$mandocs} = 1;
+ }
+ }
}
my $ordinals_text = join(', ', sort keys %ordinals);
@@ -2254,18 +2496,90 @@ They are ignored and should be replaced with a combination of GENERATE,
DEPEND and SHARED_SOURCE.
EOF
- # Massage the result
+ # Check that each generated file is only generated once
+ my $ambiguous_generation = 0;
+ foreach (sort keys %check_generate) {
+ my @generators = sort keys %{$check_generate{$_}};
+ my $generators_txt = join(', ', @generators);
+ if (scalar @generators > 1) {
+ warn "$_ is GENERATEd by more than one generator ($generators_txt)\n";
+ $ambiguous_generation++;
+ }
+ if ($check_generate{$_}->{$generators[0]} > 1) {
+ warn "INFO: $_ has more than one GENERATE declaration (same generator)\n"
+ }
+ }
+ die "There are ambiguous source file generations\n"
+ if $ambiguous_generation > 0;
+
+ # All given source files should exist, or if generated, their
+ # generator should exist. This loop ensures this is true.
+ my $missing = 0;
+ foreach my $orig (sort keys %check_exist) {
+ foreach my $dest (@{$check_exist{$orig}}) {
+ if ($orig ne $src_configdata) {
+ if ($orig =~ /\.a$/) {
+ # Static library names may be used as sources, so we
+ # need to detect those and give them special treatment.
+ unless (grep { $_ eq $orig }
+ keys %{$unified_info{libraries}}) {
+ warn "$orig is given as source for $dest, but no such library is built\n";
+ $missing++;
+ }
+ } else {
+ # A source may be generated, and its generator may be
+ # generated as well. We therefore loop to dig out the
+ # first generator.
+ my $gen = $orig;
+
+ while (my @next = keys %{$check_generate{$gen}}) {
+ $gen = $next[0];
+ }
+
+ if (! -f $gen) {
+ if ($gen ne $orig) {
+ $missing++;
+ warn "$orig is given as source for $dest, but its generator (leading to $gen) is missing\n";
+ } else {
+ $missing++;
+ warn "$orig is given as source for $dest, but is missing\n";
+ }
+ }
+ }
+ }
+ }
+ }
+ die "There are files missing\n" if $missing > 0;
+
+ # Go through the sources of all libraries and check that the same basename
+ # doesn't appear more than once. Some static library archivers depend on
+ # them being unique.
+ {
+ my $err = 0;
+ foreach my $prod (keys %{$unified_info{libraries}}) {
+ my @prod_sources =
+ map { keys %{$unified_info{sources}->{$_}} }
+ keys %{$unified_info{sources}->{$prod}};
+ my %srccnt = ();
+
+ # Count how many times a given each source basename
+ # appears for each product.
+ foreach my $src (@prod_sources) {
+ $srccnt{basename $src}++;
+ }
- # If the user configured no-shared, we allow no shared sources
- if ($disabled{shared}) {
- foreach (keys %{$unified_info{shared_sources}}) {
- foreach (keys %{$unified_info{shared_sources}->{$_}}) {
- delete $unified_info{sources}->{$_};
+ foreach my $src (keys %srccnt) {
+ if ((my $cnt = $srccnt{$src}) > 1) {
+ print STDERR "$src appears $cnt times for the product $prod\n";
+ $err++
+ }
}
}
- $unified_info{shared_sources} = {};
+ die if $err > 0;
}
+ # Massage the result
+
# If we depend on a header file or a perl module, add an inclusion of
# its directory to allow smoothe inclusion
foreach my $dest (keys %{$unified_info{depends}}) {
@@ -2281,38 +2595,144 @@ EOF
}
}
- # Trickle down includes placed on libraries, engines and programs to
- # their sources (i.e. object files)
- foreach my $dest (keys %{$unified_info{engines}},
- keys %{$unified_info{libraries}},
- keys %{$unified_info{programs}}) {
- foreach my $k (("source", "build")) {
- next unless defined($unified_info{includes}->{$dest}->{$k});
- my @incs = reverse @{$unified_info{includes}->{$dest}->{$k}};
- foreach my $obj (grep /\.o$/,
- (keys %{$unified_info{sources}->{$dest} // {}},
- keys %{$unified_info{shared_sources}->{$dest} // {}})) {
- foreach my $inc (@incs) {
- unshift @{$unified_info{includes}->{$obj}->{$k}}, $inc
- unless grep { $_ eq $inc } @{$unified_info{includes}->{$obj}->{$k}};
+ # Go through all intermediary files and change their names to something that
+ # reflects what they will be built for. Note that for some source files,
+ # this leads to duplicate object files because they are used multiple times.
+ # the goal is to rename all object files according to this scheme:
+ # {productname}-{midfix}-{origobjname}.[o|res]
+ # the {midfix} is a keyword indicating the type of product, which is mostly
+ # valuable for libraries since they come in two forms.
+ #
+ # This also reorganises the {sources} and {shared_sources} so that the
+ # former only contains ALL object files that are supposed to end up in
+ # static libraries and programs, while the latter contains ALL object files
+ # that are supposed to end up in shared libraries and DSOs.
+ # The main reason for having two different source structures is to allow
+ # the same name to be used for the static and the shared variants of a
+ # library.
+ {
+ # Take copies so we don't get interference from added stuff
+ my %unified_copy = ();
+ foreach (('sources', 'shared_sources')) {
+ $unified_copy{$_} = { %{$unified_info{$_}} }
+ if defined($unified_info{$_});
+ delete $unified_info{$_};
+ }
+ foreach my $prodtype (('programs', 'libraries', 'modules', 'scripts')) {
+ # $intent serves multi purposes:
+ # - give a prefix for the new object files names
+ # - in the case of libraries, rearrange the object files so static
+ # libraries use the 'sources' structure exclusively, while shared
+ # libraries use the 'shared_sources' structure exclusively.
+ my $intent = {
+ programs => { bin => { src => [ 'sources' ],
+ dst => 'sources' } },
+ libraries => { lib => { src => [ 'sources' ],
+ dst => 'sources' },
+ shlib => { prodselect =>
+ sub { grep !/\.a$/, @_ },
+ src => [ 'sources',
+ 'shared_sources' ],
+ dst => 'shared_sources' } },
+ modules => { dso => { src => [ 'sources' ],
+ dst => 'sources' } },
+ scripts => { script => { src => [ 'sources' ],
+ dst => 'sources' } }
+ } -> {$prodtype};
+ foreach my $kind (keys %$intent) {
+ next if ($intent->{$kind}->{dst} eq 'shared_sources'
+ && $disabled{shared});
+
+ my @src = @{$intent->{$kind}->{src}};
+ my $dst = $intent->{$kind}->{dst};
+ my $prodselect = $intent->{$kind}->{prodselect} // sub { @_ };
+ foreach my $prod ($prodselect->(keys %{$unified_info{$prodtype}})) {
+ # %prod_sources has all applicable objects as keys, and
+ # their corresponding sources as values
+ my %prod_sources =
+ map { $_ => [ keys %{$unified_copy{sources}->{$_}} ] }
+ map { keys %{$unified_copy{$_}->{$prod}} }
+ @src;
+ foreach (keys %prod_sources) {
+ # Only affect object files and resource files,
+ # the others simply get a new value
+ # (+1 instead of -1)
+ if ($_ =~ /\.(o|res)$/) {
+ (my $prodname = $prod) =~ s|\.a$||;
+ my $newobj =
+ catfile(dirname($_),
+ basename($prodname)
+ . '-' . $kind
+ . '-' . basename($_));
+ $unified_info{$dst}->{$prod}->{$newobj} = 1;
+ foreach my $src (@{$prod_sources{$_}}) {
+ $unified_info{sources}->{$newobj}->{$src} = 1;
+ # Adjust source attributes
+ my $attrs = $unified_info{attributes}->{sources};
+ if (defined $attrs->{$prod}
+ && defined $attrs->{$prod}->{$_}) {
+ $attrs->{$prod}->{$newobj} =
+ $attrs->{$prod}->{$_};
+ delete $attrs->{$prod}->{$_};
+ }
+ foreach my $objsrc (keys %{$attrs->{$_} // {}}) {
+ $attrs->{$newobj}->{$objsrc} =
+ $attrs->{$_}->{$objsrc};
+ delete $attrs->{$_}->{$objsrc};
+ }
+ }
+ # Adjust dependencies
+ foreach my $deps (keys %{$unified_info{depends}->{$_}}) {
+ $unified_info{depends}->{$_}->{$deps} = -1;
+ $unified_info{depends}->{$newobj}->{$deps} = 1;
+ }
+ # Adjust includes
+ foreach my $k (('source', 'build')) {
+ next unless
+ defined($unified_info{includes}->{$_}->{$k});
+ my @incs = @{$unified_info{includes}->{$_}->{$k}};
+ $unified_info{includes}->{$newobj}->{$k} = [ @incs ];
+ }
+ } else {
+ $unified_info{$dst}->{$prod}->{$_} = 1;
+ }
+ }
}
}
}
- delete $unified_info{includes}->{$dest};
}
+ # At this point, we have a number of sources with the value -1. They
+ # aren't part of the local build and are probably meant for a different
+ # platform, and can therefore be cleaned away. That happens when making
+ # %unified_info more efficient below.
+
### Make unified_info a bit more efficient
# One level structures
- foreach (("programs", "libraries", "engines", "scripts", "extra", "overrides")) {
+ foreach (("programs", "libraries", "modules", "scripts", "targets")) {
$unified_info{$_} = [ sort keys %{$unified_info{$_}} ];
}
# Two level structures
- foreach my $l1 (("install", "sources", "shared_sources", "ldadd", "depends")) {
+ foreach my $l1 (("sources", "shared_sources", "ldadd", "depends",
+ "imagedocs", "htmldocs", "mandocs")) {
foreach my $l2 (sort keys %{$unified_info{$l1}}) {
- $unified_info{$l1}->{$l2} =
- [ sort keys %{$unified_info{$l1}->{$l2}} ];
+ my @items =
+ sort
+ grep { $unified_info{$l1}->{$l2}->{$_} > 0 }
+ keys %{$unified_info{$l1}->{$l2}};
+ if (@items) {
+ $unified_info{$l1}->{$l2} = [ @items ];
+ } else {
+ delete $unified_info{$l1}->{$l2};
+ }
}
}
+ # Defines
+ foreach my $dest (sort keys %{$unified_info{defines}}) {
+ $unified_info{defines}->{$dest}
+ = [ map { $_.$unified_info{defines}->{$dest}->{$_} }
+ sort keys %{$unified_info{defines}->{$dest}} ];
+ }
# Includes
foreach my $dest (sort keys %{$unified_info{includes}}) {
if (defined($unified_info{includes}->{$dest}->{build})) {
@@ -2325,9 +2745,11 @@ EOF
push @{$unified_info{includes}->{$dest}}, $inc
unless grep { $_ eq $inc } @{$unified_info{includes}->{$dest}};
}
- } else {
+ } elsif (defined($unified_info{includes}->{$dest}->{source})) {
$unified_info{includes}->{$dest} =
[ @{$unified_info{includes}->{$dest}->{source}} ];
+ } else {
+ delete $unified_info{includes}->{$dest};
}
}
@@ -2336,10 +2758,16 @@ EOF
# they end up in where applicable. Then, add build rules for those
# directories
my %loopinfo = ( "lib" => [ @{$unified_info{libraries}} ],
- "dso" => [ @{$unified_info{engines}} ],
+ "dso" => [ @{$unified_info{modules}} ],
"bin" => [ @{$unified_info{programs}} ],
- "script" => [ @{$unified_info{scripts}} ] );
- foreach my $type (keys %loopinfo) {
+ "script" => [ @{$unified_info{scripts}} ],
+ "docs" => [ (map { @{$unified_info{imagedocs}->{$_} // []} }
+ keys %{$unified_info{imagedocs} // {}}),
+ (map { @{$unified_info{htmldocs}->{$_} // []} }
+ keys %{$unified_info{htmldocs} // {}}),
+ (map { @{$unified_info{mandocs}->{$_} // []} }
+ keys %{$unified_info{mandocs} // {}}) ] );
+ foreach my $type (sort keys %loopinfo) {
foreach my $product (@{$loopinfo{$type}}) {
my %dirs = ();
my $pd = dirname($product);
@@ -2360,7 +2788,7 @@ EOF
push @{$unified_info{dirinfo}->{$d}->{deps}}, $_
if $d ne $pd;
}
- foreach (keys %dirs) {
+ foreach (sort keys %dirs) {
push @{$unified_info{dirinfo}->{$_}->{products}->{$type}},
$product;
}
@@ -2380,446 +2808,51 @@ foreach (grep /_(asm|aux)_src$/, keys %target) {
# Write down our configuration where it fits #########################
-print "Creating configdata.pm\n";
-open(OUT,">configdata.pm") || die "unable to create configdata.pm: $!\n";
-print OUT <<"EOF";
-#! $config{HASHBANGPERL}
-
-package configdata;
-
-use strict;
-use warnings;
-
-use Exporter;
-#use vars qw(\@ISA \@EXPORT);
-our \@ISA = qw(Exporter);
-our \@EXPORT = qw(\%config \%target \%disabled \%withargs \%unified_info \@disablables);
-
-EOF
-print OUT "our %config = (\n";
-foreach (sort keys %config) {
- if (ref($config{$_}) eq "ARRAY") {
- print OUT " ", $_, " => [ ", join(", ",
- map { quotify("perl", $_) }
- @{$config{$_}}), " ],\n";
- } elsif (ref($config{$_}) eq "HASH") {
- print OUT " ", $_, " => {";
- if (scalar keys %{$config{$_}} > 0) {
- print OUT "\n";
- foreach my $key (sort keys %{$config{$_}}) {
- print OUT " ",
- join(" => ",
- quotify("perl", $key),
- defined $config{$_}->{$key}
- ? quotify("perl", $config{$_}->{$key})
- : "undef");
- print OUT ",\n";
- }
- print OUT " ";
- }
- print OUT "},\n";
- } else {
- print OUT " ", $_, " => ", quotify("perl", $config{$_}), ",\n"
- }
-}
-print OUT <<"EOF";
-);
-
-EOF
-print OUT "our %target = (\n";
-foreach (sort keys %target) {
- if (ref($target{$_}) eq "ARRAY") {
- print OUT " ", $_, " => [ ", join(", ",
- map { quotify("perl", $_) }
- @{$target{$_}}), " ],\n";
- } else {
- print OUT " ", $_, " => ", quotify("perl", $target{$_}), ",\n"
- }
-}
-print OUT <<"EOF";
-);
-
-EOF
-print OUT "our \%available_protocols = (\n";
-print OUT " tls => [ ", join(", ", map { quotify("perl", $_) } @tls), " ],\n";
-print OUT " dtls => [ ", join(", ", map { quotify("perl", $_) } @dtls), " ],\n";
-print OUT <<"EOF";
-);
-
-EOF
-print OUT "our \@disablables = (\n";
-foreach (@disablables) {
- print OUT " ", quotify("perl", $_), ",\n";
-}
-print OUT <<"EOF";
-);
-
-EOF
-print OUT "our \%disabled = (\n";
-foreach (sort keys %disabled) {
- print OUT " ", quotify("perl", $_), " => ", quotify("perl", $disabled{$_}), ",\n";
-}
-print OUT <<"EOF";
-);
-
-EOF
-print OUT "our %withargs = (\n";
-foreach (sort keys %withargs) {
- if (ref($withargs{$_}) eq "ARRAY") {
- print OUT " ", $_, " => [ ", join(", ",
- map { quotify("perl", $_) }
- @{$withargs{$_}}), " ],\n";
- } else {
- print OUT " ", $_, " => ", quotify("perl", $withargs{$_}), ",\n"
- }
-}
-print OUT <<"EOF";
-);
-
-EOF
-if ($builder eq "unified") {
- my $recurse;
- $recurse = sub {
- my $indent = shift;
- foreach (@_) {
- if (ref $_ eq "ARRAY") {
- print OUT " "x$indent, "[\n";
- foreach (@$_) {
- $recurse->($indent + 4, $_);
- }
- print OUT " "x$indent, "],\n";
- } elsif (ref $_ eq "HASH") {
- my %h = %$_;
- print OUT " "x$indent, "{\n";
- foreach (sort keys %h) {
- if (ref $h{$_} eq "") {
- print OUT " "x($indent + 4), quotify("perl", $_), " => ", quotify("perl", $h{$_}), ",\n";
- } else {
- print OUT " "x($indent + 4), quotify("perl", $_), " =>\n";
- $recurse->($indent + 8, $h{$_});
- }
- }
- print OUT " "x$indent, "},\n";
- } else {
- print OUT " "x$indent, quotify("perl", $_), ",\n";
- }
- }
- };
- print OUT "our %unified_info = (\n";
- foreach (sort keys %unified_info) {
- if (ref $unified_info{$_} eq "") {
- print OUT " "x4, quotify("perl", $_), " => ", quotify("perl", $unified_info{$_}), ",\n";
- } else {
- print OUT " "x4, quotify("perl", $_), " =>\n";
- $recurse->(8, $unified_info{$_});
- }
- }
- print OUT <<"EOF";
+my %template_vars = (
+ config => \%config,
+ target => \%target,
+ disablables => \@disablables,
+ disablables_int => \@disablables_int,
+ disabled => \%disabled,
+ withargs => \%withargs,
+ unified_info => \%unified_info,
+ tls => \@tls,
+ dtls => \@dtls,
+ makevars => [ sort keys %user ],
+ disabled_info => \%disabled_info,
+ user_crossable => \@user_crossable,
);
-
-EOF
-}
-print OUT
- "# The following data is only used when this files is use as a script\n";
-print OUT "my \@makevars = (\n";
-foreach (sort keys %user) {
- print OUT " '",$_,"',\n";
-}
-print OUT ");\n";
-print OUT "my \%disabled_info = (\n";
-foreach my $what (sort keys %disabled_info) {
- print OUT " '$what' => {\n";
- foreach my $info (sort keys %{$disabled_info{$what}}) {
- if (ref $disabled_info{$what}->{$info} eq 'ARRAY') {
- print OUT " $info => [ ",
- join(', ', map { "'$_'" } @{$disabled_info{$what}->{$info}}),
- " ],\n";
- } else {
- print OUT " $info => '", $disabled_info{$what}->{$info},
- "',\n";
- }
- }
- print OUT " },\n";
-}
-print OUT ");\n";
-print OUT 'my @user_crossable = qw( ', join (' ', @user_crossable), " );\n";
-print OUT << 'EOF';
-# If run directly, we can give some answers, and even reconfigure
-unless (caller) {
- use Getopt::Long;
- use File::Spec::Functions;
- use File::Basename;
- use Pod::Usage;
-
- my $here = dirname($0);
-
- my $dump = undef;
- my $cmdline = undef;
- my $options = undef;
- my $target = undef;
- my $envvars = undef;
- my $makevars = undef;
- my $buildparams = undef;
- my $reconf = undef;
- my $verbose = undef;
- my $help = undef;
- my $man = undef;
- GetOptions('dump|d' => \$dump,
- 'command-line|c' => \$cmdline,
- 'options|o' => \$options,
- 'target|t' => \$target,
- 'environment|e' => \$envvars,
- 'make-variables|m' => \$makevars,
- 'build-parameters|b' => \$buildparams,
- 'reconfigure|reconf|r' => \$reconf,
- 'verbose|v' => \$verbose,
- 'help' => \$help,
- 'man' => \$man)
- or die "Errors in command line arguments\n";
-
- unless ($dump || $cmdline || $options || $target || $envvars || $makevars
- || $buildparams || $reconf || $verbose || $help || $man) {
- print STDERR <<"_____";
-You must give at least one option.
-For more information, do '$0 --help'
-_____
- exit(2);
- }
-
- if ($help) {
- pod2usage(-exitval => 0,
- -verbose => 1);
- }
- if ($man) {
- pod2usage(-exitval => 0,
- -verbose => 2);
- }
- if ($dump || $cmdline) {
- print "\nCommand line (with current working directory = $here):\n\n";
- print ' ',join(' ',
- $config{PERL},
- catfile($config{sourcedir}, 'Configure'),
- @{$config{perlargv}}), "\n";
- print "\nPerl information:\n\n";
- print ' ',$config{perl_cmd},"\n";
- print ' ',$config{perl_version},' for ',$config{perl_archname},"\n";
- }
- if ($dump || $options) {
- my $longest = 0;
- my $longest2 = 0;
- foreach my $what (@disablables) {
- $longest = length($what) if $longest < length($what);
- $longest2 = length($disabled{$what})
- if $disabled{$what} && $longest2 < length($disabled{$what});
- }
- print "\nEnabled features:\n\n";
- foreach my $what (@disablables) {
- print " $what\n"
- unless grep { $_ =~ /^${what}$/ } keys %disabled;
- }
- print "\nDisabled features:\n\n";
- foreach my $what (@disablables) {
- my @what2 = grep { $_ =~ /^${what}$/ } keys %disabled;
- my $what3 = $what2[0];
- if ($what3) {
- print " $what3", ' ' x ($longest - length($what3) + 1),
- "[$disabled{$what3}]", ' ' x ($longest2 - length($disabled{$what3}) + 1);
- print $disabled_info{$what3}->{macro}
- if $disabled_info{$what3}->{macro};
- print ' (skip ',
- join(', ', @{$disabled_info{$what3}->{skipped}}),
- ')'
- if $disabled_info{$what3}->{skipped};
- print "\n";
- }
- }
- }
- if ($dump || $target) {
- print "\nConfig target attributes:\n\n";
- foreach (sort keys %target) {
- next if $_ =~ m|^_| || $_ eq 'template';
- my $quotify = sub {
- map { (my $x = $_) =~ s|([\\\$\@"])|\\$1|g; "\"$x\""} @_;
- };
- print ' ', $_, ' => ';
- if (ref($target{$_}) eq "ARRAY") {
- print '[ ', join(', ', $quotify->(@{$target{$_}})), " ],\n";
- } else {
- print $quotify->($target{$_}), ",\n"
- }
- }
- }
- if ($dump || $envvars) {
- print "\nRecorded environment:\n\n";
- foreach (sort keys %{$config{perlenv}}) {
- print ' ',$_,' = ',($config{perlenv}->{$_} || ''),"\n";
- }
- }
- if ($dump || $makevars) {
- print "\nMakevars:\n\n";
- foreach my $var (@makevars) {
- my $prefix = '';
- $prefix = $config{CROSS_COMPILE}
- if grep { $var eq $_ } @user_crossable;
- $prefix //= '';
- print ' ',$var,' ' x (16 - length $var),'= ',
- (ref $config{$var} eq 'ARRAY'
- ? join(' ', @{$config{$var}})
- : $prefix.$config{$var}),
- "\n"
- if defined $config{$var};
- }
-
- my @buildfile = ($config{builddir}, $config{build_file});
- unshift @buildfile, $here
- unless file_name_is_absolute($config{builddir});
- my $buildfile = canonpath(catdir(@buildfile));
- print <<"_____";
-
-NOTE: These variables only represent the configuration view. The build file
-template may have processed these variables further, please have a look at the
-build file for more exact data:
- $buildfile
-_____
- }
- if ($dump || $buildparams) {
- my @buildfile = ($config{builddir}, $config{build_file});
- unshift @buildfile, $here
- unless file_name_is_absolute($config{builddir});
- print "\nbuild file:\n\n";
- print " ", canonpath(catfile(@buildfile)),"\n";
-
- print "\nbuild file templates:\n\n";
- foreach (@{$config{build_file_templates}}) {
- my @tmpl = ($_);
- unshift @tmpl, $here
- unless file_name_is_absolute($config{sourcedir});
- print ' ',canonpath(catfile(@tmpl)),"\n";
- }
- }
- if ($reconf) {
- if ($verbose) {
- print 'Reconfiguring with: ', join(' ',@{$config{perlargv}}), "\n";
- foreach (sort keys %{$config{perlenv}}) {
- print ' ',$_,' = ',($config{perlenv}->{$_} || ""),"\n";
- }
- }
-
- chdir $here;
- exec $^X,catfile($config{sourcedir}, 'Configure'),'reconf';
- }
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-configdata.pm - configuration data for OpenSSL builds
-
-=head1 SYNOPSIS
-
-Interactive:
-
- perl configdata.pm [options]
-
-As data bank module:
-
- use configdata;
-
-=head1 DESCRIPTION
-
-This module can be used in two modes, interactively and as a module containing
-all the data recorded by OpenSSL's Configure script.
-
-When used interactively, simply run it as any perl script, with at least one
-option, and you will get the information you ask for. See L</OPTIONS> below.
-
-When loaded as a module, you get a few databanks with useful information to
-perform build related tasks. The databanks are:
-
- %config Configured things.
- %target The OpenSSL config target with all inheritances
- resolved.
- %disabled The features that are disabled.
- @disablables The list of features that can be disabled.
- %withargs All data given through --with-THING options.
- %unified_info All information that was computed from the build.info
- files.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<--help>
-
-Print a brief help message and exit.
-
-=item B<--man>
-
-Print the manual page and exit.
-
-=item B<--dump> | B<-d>
-
-Print all relevant configuration data. This is equivalent to B<--command-line>
-B<--options> B<--target> B<--environment> B<--make-variables>
-B<--build-parameters>.
-
-=item B<--command-line> | B<-c>
-
-Print the current configuration command line.
-
-=item B<--options> | B<-o>
-
-Print the features, both enabled and disabled, and display defined macro and
-skipped directories where applicable.
-
-=item B<--target> | B<-t>
-
-Print the config attributes for this config target.
-
-=item B<--environment> | B<-e>
-
-Print the environment variables and their values at the time of configuration.
-
-=item B<--make-variables> | B<-m>
-
-Print the main make variables generated in the current configuration
-
-=item B<--build-parameters> | B<-b>
-
-Print the build parameters, i.e. build file and build file templates.
-
-=item B<--reconfigure> | B<--reconf> | B<-r>
-
-Redo the configuration.
-
-=item B<--verbose> | B<-v>
-
-Verbose output.
-
-=back
-
-=cut
-
-EOF
-close(OUT);
+my $configdata_outname = 'configdata.pm';
+open CONFIGDATA, ">$configdata_outname.new"
+ or die "Trying to create $configdata_outname.new: $!";
+my $configdata_tmplname = cleanfile($srcdir, "configdata.pm.in", $blddir);
+my $configdata_tmpl =
+ OpenSSL::Template->new(TYPE => 'FILE', SOURCE => $configdata_tmplname);
+$configdata_tmpl->fill_in(
+ FILENAME => $configdata_tmplname,
+ OUTPUT => \*CONFIGDATA,
+ HASH => { %template_vars,
+ autowarntext => [
+ 'WARNING: do not edit!',
+ "Generated by Configure from $configdata_tmplname",
+ ] }
+) or die $Text::Template::ERROR;
+close CONFIGDATA;
+
+rename "$configdata_outname.new", $configdata_outname;
if ($builder_platform eq 'unix') {
my $mode = (0755 & ~umask);
chmod $mode, 'configdata.pm'
or warn sprintf("WARNING: Couldn't change mode for 'configdata.pm' to 0%03o: %s\n",$mode,$!);
}
+print "Created $configdata_outname\n";
-my %builders = (
- unified => sub {
- print 'Creating ',$config{build_file},"\n";
- run_dofile(catfile($blddir, $config{build_file}),
- @{$config{build_file_templates}});
- },
- );
-
-$builders{$builder}->($builder_platform, @builder_opts);
+print "Running $configdata_outname\n";
+my $perlcmd = (quotify("maybeshell", $config{PERL}))[0];
+my $cmd = "$perlcmd $configdata_outname";
+#print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
+system($cmd);
+exit 1 if $? != 0;
$SIG{__DIE__} = $orig_death_handler;
@@ -2827,7 +2860,7 @@ print <<"EOF" if ($disabled{threads} eq "unavailable");
The library could not be configured for supporting multi-threaded
applications as the compiler options required on this system are not known.
-See file INSTALL for details if you need multi-threading.
+See file INSTALL.md for details if you need multi-threading.
EOF
print <<"EOF" if ($no_shared_warn);
@@ -2839,23 +2872,7 @@ or position independent code, please let us know (but please first make sure
you have tried with a current version of OpenSSL).
EOF
-print <<"EOF";
-
-**********************************************************************
-*** ***
-*** OpenSSL has been successfully configured ***
-*** ***
-*** If you encounter a problem while building, please open an ***
-*** issue on GitHub <https://github.com/openssl/openssl/issues> ***
-*** and include the output from the following command: ***
-*** ***
-*** perl configdata.pm --dump ***
-*** ***
-*** (If you are new to OpenSSL, you might want to consult the ***
-*** 'Troubleshooting' section in the INSTALL file first) ***
-*** ***
-**********************************************************************
-EOF
+print $banner;
exit(0);
@@ -2872,8 +2889,8 @@ sub death_handler {
my @message = ( <<"_____", @_ );
Failure! $build_file wasn't produced.
-Please read INSTALL and associated NOTES files. You may also have to look over
-your available compiler tool chain or change your configuration.
+Please read INSTALL.md and associated NOTES-* files. You may also have to
+look over your available compiler tool chain or change your configuration.
_____
@@ -2889,18 +2906,6 @@ _____
# Thus, whenever there's mention of a returned value, it's about that
# intended value.
-# Helper function to implement conditional inheritance depending on the
-# value of $disabled{asm}. Used in inherit_from values as follows:
-#
-# inherit_from => [ "template", asm("asm_tmpl") ]
-#
-sub asm {
- my @x = @_;
- sub {
- $disabled{asm} ? () : @x;
- }
-}
-
# Helper function to implement conditional value variants, with a default
# plus additional values based on the value of $config{build_type}.
# Arguments are given in hash table form:
@@ -3218,28 +3223,9 @@ sub usage
}
print STDERR $i . " ";
}
- print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n";
exit(1);
}
-sub run_dofile
-{
- my $out = shift;
- my @templates = @_;
-
- unlink $out || warn "Can't remove $out, $!"
- if -f $out;
- foreach (@templates) {
- die "Can't open $_, $!" unless -f $_;
- }
- my $perlcmd = (quotify("maybeshell", $config{PERL}))[0];
- my $cmd = "$perlcmd \"-I.\" \"-Mconfigdata\" \"$dofile\" -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\"";
- #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
- system($cmd);
- exit 1 if $? != 0;
- rename("$out.new", $out) || die "Can't rename $out.new, $!";
-}
-
sub compiler_predefined {
state %predefined;
my $cc = shift;
@@ -3321,31 +3307,13 @@ sub print_table_entry
"includes",
"cc",
"cflags",
- "unistd",
"ld",
"lflags",
"loutflag",
"ex_libs",
"bn_ops",
- "apps_aux_src",
- "cpuid_asm_src",
- "uplink_aux_src",
- "bn_asm_src",
- "ec_asm_src",
- "des_asm_src",
- "aes_asm_src",
- "bf_asm_src",
- "md5_asm_src",
- "cast_asm_src",
- "sha1_asm_src",
- "rc4_asm_src",
- "rmd160_asm_src",
- "rc5_asm_src",
- "wp_asm_src",
- "cmll_asm_src",
- "modes_asm_src",
- "padlock_asm_src",
- "chacha_asm_src",
+ "enable",
+ "disable",
"poly1035_asm_src",
"thread_scheme",
"perlasm_scheme",
@@ -3577,32 +3545,43 @@ sub collect_information {
}
# tokenize($line)
+# tokenize($line,$separator)
# $line is a line of text to split up into tokens
-# returns a list of tokens
+# $separator [optional] is a regular expression that separates the tokens,
+# the default being spaces. Do not use quotes of any kind as separators,
+# that will give undefined results.
+# Returns a list of tokens.
#
-# Tokens are divided by spaces. If the tokens include spaces, they
-# have to be quoted with single or double quotes. Double quotes
-# inside a double quoted token must be escaped. Escaping is done
+# Tokens are divided by separator (spaces by default). If the tokens include
+# the separators, they have to be quoted with single or double quotes.
+# Double quotes inside a double quoted token must be escaped. Escaping is done
# with backslash.
# Basically, the same quoting rules apply for " and ' as in any
# Unix shell.
sub tokenize {
my $line = my $debug_line = shift;
+ my $separator = shift // qr|\s+|;
my @result = ();
- while ($line =~ s|^\s+||, $line ne "") {
+ if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) {
+ print STDERR "DEBUG[tokenize]: \$separator = $separator\n";
+ }
+
+ while ($line =~ s|^${separator}||, $line ne "") {
my $token = "";
- while ($line ne "" && $line !~ m|^\s|) {
- if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) {
- $token .= $1;
- $line = $';
- } elsif ($line =~ m/^'([^']*)'/) {
- $token .= $1;
- $line = $';
- } elsif ($line =~ m/^(\S+)/) {
- $token .= $1;
- $line = $';
- }
+ again:
+ $line =~ m/^(.*?)(${separator}|"|'|$)/;
+ $token .= $1;
+ $line = $2.$';
+
+ if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) {
+ $token .= $1;
+ $line = $';
+ goto again;
+ } elsif ($line =~ m/^'([^']*)'/) {
+ $token .= $1;
+ $line = $';
+ goto again;
}
push @result, $token;
}
diff --git a/FAQ b/FAQ
deleted file mode 100644
index 22c5cf7dc2f3..000000000000
--- a/FAQ
+++ /dev/null
@@ -1,2 +0,0 @@
-The FAQ is now maintained on the web:
- https://www.openssl.org/docs/faq.html
diff --git a/FAQ.md b/FAQ.md
new file mode 100644
index 000000000000..30f5010ce3a4
--- /dev/null
+++ b/FAQ.md
@@ -0,0 +1,6 @@
+Frequently Asked Questions (FAQ)
+================================
+
+The [Frequently Asked Questions][FAQ] are now maintained on the OpenSSL homepage.
+
+ [FAQ]: https://www.openssl.org/docs/faq.html
diff --git a/HACKING.md b/HACKING.md
new file mode 100644
index 000000000000..6375450c2413
--- /dev/null
+++ b/HACKING.md
@@ -0,0 +1,33 @@
+MODIFYING OPENSSL SOURCE
+========================
+
+This document describes the way to add custom modifications to OpenSSL sources.
+
+ If you are adding new public functions to the custom library build, you need to
+ either add a prototype in one of the existing OpenSSL header files;
+ or provide a new header file and edit
+ [Configurations/unix-Makefile.tmpl](Configurations/unix-Makefile.tmpl)
+ to pick up that file.
+
+ After that perform the following steps:
+
+ ./Configure -Werror --strict-warnings [your-options]
+ make update
+ make
+ make test
+
+ `make update` ensures that your functions declarations are added to
+ `util/libcrypto.num` or `util/libssl.num`.
+ If you plan to submit the changes you made to OpenSSL
+ (see [CONTRIBUTING.md](CONTRIBUTING.md)), it's worth running:
+
+ make doc-nits
+
+ after running `make update` to ensure that documentation has correct format.
+
+ `make update` also generates files related to OIDs (in the `crypto/objects/`
+ folder) and errors.
+ If a merge error occurs in one of these generated files then the
+ generated files need to be removed and regenerated using `make update`.
+ To aid in this process the generated files can be committed separately
+ so they can be removed easily.
diff --git a/INSTALL b/INSTALL
deleted file mode 100644
index f3ac727183f0..000000000000
--- a/INSTALL
+++ /dev/null
@@ -1,1289 +0,0 @@
- OPENSSL INSTALLATION
- --------------------
-
- This document describes installation on all supported operating
- systems (the Unix/Linux family (which includes Mac OS/X), OpenVMS,
- and Windows).
-
- To install OpenSSL, you will need:
-
- * A make implementation
- * Perl 5 with core modules (please read NOTES.PERL)
- * The perl module Text::Template (please read NOTES.PERL)
- * an ANSI C compiler
- * a development environment in the form of development libraries and C
- header files
- * a supported operating system
-
- For additional platform specific requirements, solutions to specific
- issues and other details, please read one of these:
-
- * NOTES.UNIX (any supported Unix like system)
- * NOTES.VMS (OpenVMS)
- * NOTES.WIN (any supported Windows)
- * NOTES.DJGPP (DOS platform with DJGPP)
- * NOTES.ANDROID (obviously Android [NDK])
-
- Notational conventions in this document
- ---------------------------------------
-
- Throughout this document, we use the following conventions in command
- examples:
-
- $ command Any line starting with a dollar sign
- ($) is a command line.
-
- { word1 | word2 | word3 } This denotes a mandatory choice, to be
- replaced with one of the given words.
- A simple example would be this:
-
- $ echo { FOO | BAR | COOKIE }
-
- which is to be understood as one of
- these:
-
- $ echo FOO
- - or -
- $ echo BAR
- - or -
- $ echo COOKIE
-
- [ word1 | word2 | word3 ] Similar to { word1 | word2 | word3 }
- except it's optional to give any of
- those. In addition to the examples
- above, this would also be valid:
-
- $ echo
-
- {{ target }} This denotes a mandatory word or
- sequence of words of some sort. A
- simple example would be this:
-
- $ type {{ filename }}
-
- which is to be understood to use the
- command 'type' on some file name
- determined by the user.
-
- [[ options ]] Similar to {{ target }}, but is
- optional.
-
- Note that the notation assumes spaces around {, }, [, ], {{, }} and
- [[, ]]. This is to differentiate from OpenVMS directory
- specifications, which also use [ and ], but without spaces.
-
- Quick Start
- -----------
-
- If you want to just get on with it, do:
-
- on Unix (again, this includes Mac OS/X):
-
- $ ./config
- $ make
- $ make test
- $ make install
-
- on OpenVMS:
-
- $ @config
- $ mms
- $ mms test
- $ mms install
-
- on Windows (only pick one of the targets for configuration):
-
- $ perl Configure { VC-WIN32 | VC-WIN64A | VC-WIN64I | VC-CE }
- $ nmake
- $ nmake test
- $ nmake install
-
- Note that in order to perform the install step above you need to have
- appropriate permissions to write to the installation directory.
-
- If any of these steps fails, see section Installation in Detail below.
-
- This will build and install OpenSSL in the default location, which is:
-
- Unix: normal installation directories under /usr/local
- OpenVMS: SYS$COMMON:[OPENSSL]
- Windows: C:\Program Files\OpenSSL or C:\Program Files (x86)\OpenSSL
-
- The installation directory should be appropriately protected to ensure
- unprivileged users cannot make changes to OpenSSL binaries or files, or install
- engines. If you already have a pre-installed version of OpenSSL as part of
- your Operating System it is recommended that you do not overwrite the system
- version and instead install to somewhere else.
-
- If you want to install it anywhere else, run config like this (the options
- --prefix and --openssldir are explained further down, and the values shown
- here are mere examples):
-
- On Unix:
-
- $ ./config --prefix=/opt/openssl --openssldir=/usr/local/ssl
-
- On OpenVMS:
-
- $ @config --prefix=PROGRAM:[INSTALLS] --openssldir=SYS$MANAGER:[OPENSSL]
-
- (Note: if you do add options to the configuration command, please make sure
- you've read more than just this Quick Start, such as relevant NOTES.* files,
- the options outline below, as configuration options may change the outcome
- in otherwise unexpected ways)
-
-
- Configuration Options
- ---------------------
-
- There are several options to ./config (or ./Configure) to customize
- the build (note that for Windows, the defaults for --prefix and
- --openssldir depend in what configuration is used and what Windows
- implementation OpenSSL is built on. More notes on this in NOTES.WIN):
-
- --api=x.y.z
- Don't build with support for deprecated APIs below the
- specified version number. For example "--api=1.1.0" will
- remove support for all APIS that were deprecated in OpenSSL
- version 1.1.0 or below. This is a rather specialized option
- for developers. If you just intend to remove all deprecated
- APIs entirely (up to the current version), it is easier
- to add the 'no-deprecated' option instead (see below).
-
- --cross-compile-prefix=PREFIX
- The PREFIX to include in front of commands for your
- toolchain. It's likely to have to end with dash, e.g.
- a-b-c- would invoke GNU compiler as a-b-c-gcc, etc.
- Unfortunately cross-compiling is too case-specific to
- put together one-size-fits-all instructions. You might
- have to pass more flags or set up environment variables
- to actually make it work. Android and iOS cases are
- discussed in corresponding Configurations/15-*.conf
- files. But there are cases when this option alone is
- sufficient. For example to build the mingw64 target on
- Linux "--cross-compile-prefix=x86_64-w64-mingw32-"
- works. Naturally provided that mingw packages are
- installed. Today Debian and Ubuntu users have option to
- install a number of prepackaged cross-compilers along
- with corresponding run-time and development packages for
- "alien" hardware. To give another example
- "--cross-compile-prefix=mipsel-linux-gnu-" suffices
- in such case. Needless to mention that you have to
- invoke ./Configure, not ./config, and pass your target
- name explicitly. Also, note that --openssldir refers
- to target's file system, not one you are building on.
-
- --debug
- Build OpenSSL with debugging symbols and zero optimization
- level.
-
- --libdir=DIR
- The name of the directory under the top of the installation
- directory tree (see the --prefix option) where libraries will
- be installed. By default this is "lib". Note that on Windows
- only ".lib" files will be stored in this location. dll files
- will always be installed to the "bin" directory.
-
- --openssldir=DIR
- Directory for OpenSSL configuration files, and also the
- default certificate and key store. Defaults are:
-
- Unix: /usr/local/ssl
- Windows: C:\Program Files\Common Files\SSL
- or C:\Program Files (x86)\Common Files\SSL
- OpenVMS: SYS$COMMON:[OPENSSL-COMMON]
-
- --prefix=DIR
- The top of the installation directory tree. Defaults are:
-
- Unix: /usr/local
- Windows: C:\Program Files\OpenSSL
- or C:\Program Files (x86)\OpenSSL
- OpenVMS: SYS$COMMON:[OPENSSL]
-
- --release
- Build OpenSSL without debugging symbols. This is the default.
-
- --strict-warnings
- This is a developer flag that switches on various compiler
- options recommended for OpenSSL development. It only works
- when using gcc or clang as the compiler. If you are
- developing a patch for OpenSSL then it is recommended that
- you use this option where possible.
-
- --with-zlib-include=DIR
- The directory for the location of the zlib include file. This
- option is only necessary if enable-zlib (see below) is used
- and the include file is not already on the system include
- path.
-
- --with-zlib-lib=LIB
- On Unix: this is the directory containing the zlib library.
- If not provided the system library path will be used.
- On Windows: this is the filename of the zlib library (with or
- without a path). This flag must be provided if the
- zlib-dynamic option is not also used. If zlib-dynamic is used
- then this flag is optional and a default value ("ZLIB1") is
- used if not provided.
- On VMS: this is the filename of the zlib library (with or
- without a path). This flag is optional and if not provided
- then "GNV$LIBZSHR", "GNV$LIBZSHR32" or "GNV$LIBZSHR64" is
- used by default depending on the pointer size chosen.
-
-
- --with-rand-seed=seed1[,seed2,...]
- A comma separated list of seeding methods which will be tried
- by OpenSSL in order to obtain random input (a.k.a "entropy")
- for seeding its cryptographically secure random number
- generator (CSPRNG). The current seeding methods are:
-
- os: Use a trusted operating system entropy source.
- This is the default method if such an entropy
- source exists.
- getrandom: Use the L<getrandom(2)> or equivalent system
- call.
- devrandom: Use the first device from the DEVRANDOM list
- which can be opened to read random bytes. The
- DEVRANDOM preprocessor constant expands to
- "/dev/urandom","/dev/random","/dev/srandom" on
- most unix-ish operating systems.
- egd: Check for an entropy generating daemon.
- rdcpu: Use the RDSEED or RDRAND command if provided by
- the CPU.
- librandom: Use librandom (not implemented yet).
- none: Disable automatic seeding. This is the default
- on some operating systems where no suitable
- entropy source exists, or no support for it is
- implemented yet.
-
- For more information, see the section 'Note on random number
- generation' at the end of this document.
-
- no-afalgeng
- Don't build the AFALG engine. This option will be forced if
- on a platform that does not support AFALG.
-
- enable-asan
- Build with the Address sanitiser. This is a developer option
- only. It may not work on all platforms and should never be
- used in production environments. It will only work when used
- with gcc or clang and should be used in conjunction with the
- no-shared option.
-
- no-asm
- Do not use assembler code. This should be viewed as
- debugging/trouble-shooting option rather than production.
- On some platforms a small amount of assembler code may
- still be used even with this option.
-
- no-async
- Do not build support for async operations.
-
- no-autoalginit
- Don't automatically load all supported ciphers and digests.
- Typically OpenSSL will make available all of its supported
- ciphers and digests. For a statically linked application this
- may be undesirable if small executable size is an objective.
- This only affects libcrypto. Ciphers and digests will have to
- be loaded manually using EVP_add_cipher() and
- EVP_add_digest() if this option is used. This option will
- force a non-shared build.
-
- no-autoerrinit
- Don't automatically load all libcrypto/libssl error strings.
- Typically OpenSSL will automatically load human readable
- error strings. For a statically linked application this may
- be undesirable if small executable size is an objective.
-
- no-autoload-config
- Don't automatically load the default openssl.cnf file.
- Typically OpenSSL will automatically load a system config
- file which configures default ssl options.
-
- enable-buildtest-c++
- While testing, generate C++ buildtest files that
- simply check that the public OpenSSL header files
- are usable standalone with C++.
-
- Enabling this option demands extra care. For any
- compiler flag given directly as configuration
- option, you must ensure that it's valid for both
- the C and the C++ compiler. If not, the C++ build
- test will most likely break. As an alternative,
- you can use the language specific variables, CFLAGS
- and CXXFLAGS.
-
- no-capieng
- Don't build the CAPI engine. This option will be forced if
- on a platform that does not support CAPI.
-
- no-cms
- Don't build support for CMS features
-
- no-comp
- Don't build support for SSL/TLS compression. If this option
- is left enabled (the default), then compression will only
- work if the zlib or zlib-dynamic options are also chosen.
-
- enable-crypto-mdebug
- Build support for debugging memory allocated via
- OPENSSL_malloc() or OPENSSL_zalloc().
-
- enable-crypto-mdebug-backtrace
- As for crypto-mdebug, but additionally provide backtrace
- information for allocated memory.
- TO BE USED WITH CARE: this uses GNU C functionality, and
- is therefore not usable for non-GNU config targets. If
- your build complains about the use of '-rdynamic' or the
- lack of header file execinfo.h, this option is not for you.
- ALSO NOTE that even though execinfo.h is available on your
- system (through Gnulib), the functions might just be stubs
- that do nothing.
-
- no-ct
- Don't build support for Certificate Transparency.
-
- no-deprecated
- Don't build with support for any deprecated APIs. This is the
- same as using "--api" and supplying the latest version
- number.
-
- no-dgram
- Don't build support for datagram based BIOs. Selecting this
- option will also force the disabling of DTLS.
-
- no-dso
- Don't build support for loading Dynamic Shared Objects.
-
- enable-devcryptoeng
- Build the /dev/crypto engine. It is automatically selected
- on BSD implementations, in which case it can be disabled with
- no-devcryptoeng.
-
- no-dynamic-engine
- Don't build the dynamically loaded engines. This only has an
- effect in a "shared" build
-
- no-ec
- Don't build support for Elliptic Curves.
-
- no-ec2m
- Don't build support for binary Elliptic Curves
-
- enable-ec_nistp_64_gcc_128
- Enable support for optimised implementations of some commonly
- used NIST elliptic curves.
- This is only supported on platforms:
- - with little-endian storage of non-byte types
- - that tolerate misaligned memory references
- - where the compiler:
- - supports the non-standard type __uint128_t
- - defines the built-in macro __SIZEOF_INT128__
-
- enable-egd
- Build support for gathering entropy from EGD (Entropy
- Gathering Daemon).
-
- no-engine
- Don't build support for loading engines.
-
- no-err
- Don't compile in any error strings.
-
- enable-external-tests
- Enable building of integration with external test suites.
- This is a developer option and may not work on all platforms.
- The only supported external test suite at the current time is
- the BoringSSL test suite. See the file test/README.external
- for further details.
-
- no-filenames
- Don't compile in filename and line number information (e.g.
- for errors and memory allocation).
-
- enable-fuzz-libfuzzer, enable-fuzz-afl
- Build with support for fuzzing using either libfuzzer or AFL.
- These are developer options only. They may not work on all
- platforms and should never be used in production environments.
- See the file fuzz/README.md for further details.
-
- no-gost
- Don't build support for GOST based ciphersuites. Note that
- if this feature is enabled then GOST ciphersuites are only
- available if the GOST algorithms are also available through
- loading an externally supplied engine.
-
- no-hw-padlock
- Don't build the padlock engine.
-
- no-makedepend
- Don't generate dependencies.
-
- no-multiblock
- Don't build support for writing multiple records in one
- go in libssl (Note: this is a different capability to the
- pipelining functionality).
-
- no-nextprotoneg
- Don't build support for the NPN TLS extension.
-
- no-ocsp
- Don't build support for OCSP.
-
- no-pic
- Don't build with support for Position Independent Code.
-
- no-pinshared By default OpenSSL will attempt to stay in memory until the
- process exits. This is so that libcrypto and libssl can be
- properly cleaned up automatically via an "atexit()" handler.
- The handler is registered by libcrypto and cleans up both
- libraries. On some platforms the atexit() handler will run on
- unload of libcrypto (if it has been dynamically loaded)
- rather than at process exit. This option can be used to stop
- OpenSSL from attempting to stay in memory until the process
- exits. This could lead to crashes if either libcrypto or
- libssl have already been unloaded at the point
- that the atexit handler is invoked, e.g. on a platform which
- calls atexit() on unload of the library, and libssl is
- unloaded before libcrypto then a crash is likely to happen.
- Applications can suppress running of the atexit() handler at
- run time by using the OPENSSL_INIT_NO_ATEXIT option to
- OPENSSL_init_crypto(). See the man page for it for further
- details.
-
- no-posix-io
- Don't use POSIX IO capabilities.
-
- no-psk
- Don't build support for Pre-Shared Key based ciphersuites.
-
- no-rdrand
- Don't use hardware RDRAND capabilities.
-
- no-rfc3779
- Don't build support for RFC3779 ("X.509 Extensions for IP
- Addresses and AS Identifiers")
-
- sctp
- Build support for SCTP
-
- no-shared
- Do not create shared libraries, only static ones. See "Note
- on shared libraries" below.
-
- no-sock
- Don't build support for socket BIOs
-
- no-srp
- Don't build support for SRP or SRP based ciphersuites.
-
- no-srtp
- Don't build SRTP support
-
- no-sse2
- Exclude SSE2 code paths from 32-bit x86 assembly modules.
- Normally SSE2 extension is detected at run-time, but the
- decision whether or not the machine code will be executed
- is taken solely on CPU capability vector. This means that
- if you happen to run OS kernel which does not support SSE2
- extension on Intel P4 processor, then your application
- might be exposed to "illegal instruction" exception.
- There might be a way to enable support in kernel, e.g.
- FreeBSD kernel can be compiled with CPU_ENABLE_SSE, and
- there is a way to disengage SSE2 code paths upon application
- start-up, but if you aim for wider "audience" running
- such kernel, consider no-sse2. Both the 386 and
- no-asm options imply no-sse2.
-
- enable-ssl-trace
- Build with the SSL Trace capabilities (adds the "-trace"
- option to s_client and s_server).
-
- no-static-engine
- Don't build the statically linked engines. This only
- has an impact when not built "shared".
-
- no-stdio
- Don't use anything from the C header file "stdio.h" that
- makes use of the "FILE" type. Only libcrypto and libssl can
- be built in this way. Using this option will suppress
- building the command line applications. Additionally since
- the OpenSSL tests also use the command line applications the
- tests will also be skipped.
-
- no-tests
- Don't build test programs or run any test.
-
- no-threads
- Don't try to build with support for multi-threaded
- applications.
-
- threads
- Build with support for multi-threaded applications. Most
- platforms will enable this by default. However if on a
- platform where this is not the case then this will usually
- require additional system-dependent options! See "Note on
- multi-threading" below.
-
- no-ts
- Don't build Time Stamping Authority support.
-
- enable-ubsan
- Build with the Undefined Behaviour sanitiser. This is a
- developer option only. It may not work on all platforms and
- should never be used in production environments. It will only
- work when used with gcc or clang and should be used in
- conjunction with the "-DPEDANTIC" option (or the
- --strict-warnings option).
-
- no-ui-console
- Don't build with the "UI" console method (i.e. the "UI"
- method that enables text based console prompts).
-
- enable-unit-test
- Enable additional unit test APIs. This should not typically
- be used in production deployments.
-
- enable-weak-ssl-ciphers
- Build support for SSL/TLS ciphers that are considered "weak"
- (e.g. RC4 based ciphersuites).
-
- zlib
- Build with support for zlib compression/decompression.
-
- zlib-dynamic
- Like "zlib", but has OpenSSL load the zlib library
- dynamically when needed. This is only supported on systems
- where loading of shared libraries is supported.
-
- 386
- In 32-bit x86 builds, when generating assembly modules,
- use the 80386 instruction set only (the default x86 code
- is more efficient, but requires at least a 486). Note:
- This doesn't affect code generated by compiler, you're
- likely to complement configuration command line with
- suitable compiler-specific option.
-
- no-<prot>
- Don't build support for negotiating the specified SSL/TLS
- protocol (one of ssl, ssl3, tls, tls1, tls1_1, tls1_2,
- tls1_3, dtls, dtls1 or dtls1_2). If "no-tls" is selected then
- all of tls1, tls1_1, tls1_2 and tls1_3 are disabled.
- Similarly "no-dtls" will disable dtls1 and dtls1_2. The
- "no-ssl" option is synonymous with "no-ssl3". Note this only
- affects version negotiation. OpenSSL will still provide the
- methods for applications to explicitly select the individual
- protocol versions.
-
- no-<prot>-method
- As for no-<prot> but in addition do not build the methods for
- applications to explicitly select individual protocol
- versions. Note that there is no "no-tls1_3-method" option
- because there is no application method for TLSv1.3. Using
- individual protocol methods directly is deprecated.
- Applications should use TLS_method() instead.
-
- enable-<alg>
- Build with support for the specified algorithm, where <alg>
- is one of: md2 or rc5.
-
- no-<alg>
- Build without support for the specified algorithm, where
- <alg> is one of: aria, bf, blake2, camellia, cast, chacha,
- cmac, des, dh, dsa, ecdh, ecdsa, idea, md4, mdc2, ocb,
- poly1305, rc2, rc4, rmd160, scrypt, seed, siphash, sm2, sm3,
- sm4 or whirlpool. The "ripemd" algorithm is deprecated and
- if used is synonymous with rmd160.
-
- -Dxxx, -Ixxx, -Wp, -lxxx, -Lxxx, -Wl, -rpath, -R, -framework, -static
- These system specific options will be recognised and
- passed through to the compiler to allow you to define
- preprocessor symbols, specify additional libraries, library
- directories or other compiler options. It might be worth
- noting that some compilers generate code specifically for
- processor the compiler currently executes on. This is not
- necessarily what you might have in mind, since it might be
- unsuitable for execution on other, typically older,
- processor. Consult your compiler documentation.
-
- Take note of the VAR=value documentation below and how
- these flags interact with those variables.
-
- -xxx, +xxx, /xxx
- Additional options that are not otherwise recognised are
- passed through as they are to the compiler as well.
- Unix-style options beginning with a '-' or '+' and
- Windows-style options beginning with a '/' are recognized.
- Again, consult your compiler documentation.
-
- If the option contains arguments separated by spaces,
- then the URL-style notation %20 can be used for the space
- character in order to avoid having to quote the option.
- For example, -opt%20arg gets expanded to -opt arg.
- In fact, any ASCII character can be encoded as %xx using its
- hexadecimal encoding.
-
- Take note of the VAR=value documentation below and how
- these flags interact with those variables.
-
- VAR=value
- Assignment of environment variable for Configure. These
- work just like normal environment variable assignments,
- but are supported on all platforms and are confined to
- the configuration scripts only. These assignments override
- the corresponding value in the inherited environment, if
- there is one.
-
- The following variables are used as "make variables" and
- can be used as an alternative to giving preprocessor,
- compiler and linker options directly as configuration.
- The following variables are supported:
-
- AR The static library archiver.
- ARFLAGS Flags for the static library archiver.
- AS The assembler compiler.
- ASFLAGS Flags for the assembler compiler.
- CC The C compiler.
- CFLAGS Flags for the C compiler.
- CXX The C++ compiler.
- CXXFLAGS Flags for the C++ compiler.
- CPP The C/C++ preprocessor.
- CPPFLAGS Flags for the C/C++ preprocessor.
- CPPDEFINES List of CPP macro definitions, separated
- by a platform specific character (':' or
- space for Unix, ';' for Windows, ',' for
- VMS). This can be used instead of using
- -D (or what corresponds to that on your
- compiler) in CPPFLAGS.
- CPPINCLUDES List of CPP inclusion directories, separated
- the same way as for CPPDEFINES. This can
- be used instead of -I (or what corresponds
- to that on your compiler) in CPPFLAGS.
- HASHBANGPERL Perl invocation to be inserted after '#!'
- in public perl scripts (only relevant on
- Unix).
- LD The program linker (not used on Unix, $(CC)
- is used there).
- LDFLAGS Flags for the shared library, DSO and
- program linker.
- LDLIBS Extra libraries to use when linking.
- Takes the form of a space separated list
- of library specifications on Unix and
- Windows, and as a comma separated list of
- libraries on VMS.
- RANLIB The library archive indexer.
- RC The Windows resource compiler.
- RCFLAGS Flags for the Windows resource compiler.
- RM The command to remove files and directories.
-
- These cannot be mixed with compiling / linking flags given
- on the command line. In other words, something like this
- isn't permitted.
-
- ./config -DFOO CPPFLAGS=-DBAR -DCOOKIE
-
- Backward compatibility note:
-
- To be compatible with older configuration scripts, the
- environment variables are ignored if compiling / linking
- flags are given on the command line, except for these:
-
- AR, CC, CXX, CROSS_COMPILE, HASHBANGPERL, PERL, RANLIB, RC
- and WINDRES
-
- For example, the following command will not see -DBAR:
-
- CPPFLAGS=-DBAR ./config -DCOOKIE
-
- However, the following will see both set variables:
-
- CC=gcc CROSS_COMPILE=x86_64-w64-mingw32- \
- ./config -DCOOKIE
-
- If CC is set, it is advisable to also set CXX to ensure
- both C and C++ compilers are in the same "family". This
- becomes relevant with 'enable-external-tests' and
- 'enable-buildtest-c++'.
-
- reconf
- reconfigure
- Reconfigure from earlier data. This fetches the previous
- command line options and environment from data saved in
- "configdata.pm", and runs the configuration process again,
- using these options and environment.
- Note: NO other option is permitted together with "reconf".
- This means that you also MUST use "./Configure" (or
- what corresponds to that on non-Unix platforms) directly
- to invoke this option.
- Note: The original configuration saves away values for ALL
- environment variables that were used, and if they weren't
- defined, they are still saved away with information that
- they weren't originally defined. This information takes
- precedence over environment variables that are defined
- when reconfiguring.
-
- Displaying configuration data
- -----------------------------
-
- The configuration script itself will say very little, and finishes by
- creating "configdata.pm". This perl module can be loaded by other scripts
- to find all the configuration data, and it can also be used as a script to
- display all sorts of configuration data in a human readable form.
-
- For more information, please do:
-
- $ ./configdata.pm --help # Unix
-
- or
-
- $ perl configdata.pm --help # Windows and VMS
-
- Installation in Detail
- ----------------------
-
- 1a. Configure OpenSSL for your operation system automatically:
-
- NOTE: This is not available on Windows.
-
- $ ./config [[ options ]] # Unix
-
- or
-
- $ @config [[ options ]] ! OpenVMS
-
- For the remainder of this text, the Unix form will be used in all
- examples, please use the appropriate form for your platform.
-
- This guesses at your operating system (and compiler, if necessary) and
- configures OpenSSL based on this guess. Run ./config -t to see
- if it guessed correctly. If you want to use a different compiler, you
- are cross-compiling for another platform, or the ./config guess was
- wrong for other reasons, go to step 1b. Otherwise go to step 2.
-
- On some systems, you can include debugging information as follows:
-
- $ ./config -d [[ options ]]
-
- 1b. Configure OpenSSL for your operating system manually
-
- OpenSSL knows about a range of different operating system, hardware and
- compiler combinations. To see the ones it knows about, run
-
- $ ./Configure # Unix
-
- or
-
- $ perl Configure # All other platforms
-
- For the remainder of this text, the Unix form will be used in all
- examples, please use the appropriate form for your platform.
-
- Pick a suitable name from the list that matches your system. For most
- operating systems there is a choice between using "cc" or "gcc". When
- you have identified your system (and if necessary compiler) use this name
- as the argument to Configure. For example, a "linux-elf" user would
- run:
-
- $ ./Configure linux-elf [[ options ]]
-
- If your system isn't listed, you will have to create a configuration
- file named Configurations/{{ something }}.conf and add the correct
- configuration for your system. See the available configs as examples
- and read Configurations/README and Configurations/README.design for
- more information.
-
- The generic configurations "cc" or "gcc" should usually work on 32 bit
- Unix-like systems.
-
- Configure creates a build file ("Makefile" on Unix, "makefile" on Windows
- and "descrip.mms" on OpenVMS) from a suitable template in Configurations,
- and defines various macros in include/openssl/opensslconf.h (generated from
- include/openssl/opensslconf.h.in).
-
- 1c. Configure OpenSSL for building outside of the source tree.
-
- OpenSSL can be configured to build in a build directory separate from
- the directory with the source code. It's done by placing yourself in
- some other directory and invoking the configuration commands from
- there.
-
- Unix example:
-
- $ mkdir /var/tmp/openssl-build
- $ cd /var/tmp/openssl-build
- $ /PATH/TO/OPENSSL/SOURCE/config [[ options ]]
-
- or
-
- $ /PATH/TO/OPENSSL/SOURCE/Configure {{ target }} [[ options ]]
-
- OpenVMS example:
-
- $ set default sys$login:
- $ create/dir [.tmp.openssl-build]
- $ set default [.tmp.openssl-build]
- $ @[PATH.TO.OPENSSL.SOURCE]config [[ options ]]
-
- or
-
- $ @[PATH.TO.OPENSSL.SOURCE]Configure {{ target }} [[ options ]]
-
- Windows example:
-
- $ C:
- $ mkdir \temp-openssl
- $ cd \temp-openssl
- $ perl d:\PATH\TO\OPENSSL\SOURCE\Configure {{ target }} [[ options ]]
-
- Paths can be relative just as well as absolute. Configure will
- do its best to translate them to relative paths whenever possible.
-
- 2. Build OpenSSL by running:
-
- $ make # Unix
- $ mms ! (or mmk) OpenVMS
- $ nmake # Windows
-
- This will build the OpenSSL libraries (libcrypto.a and libssl.a on
- Unix, corresponding on other platforms) and the OpenSSL binary
- ("openssl"). The libraries will be built in the top-level directory,
- and the binary will be in the "apps" subdirectory.
-
- Troubleshooting:
-
- If the build fails, look at the output. There may be reasons
- for the failure that aren't problems in OpenSSL itself (like
- missing standard headers).
-
- If the build succeeded previously, but fails after a source or
- configuration change, it might be helpful to clean the build tree
- before attempting another build. Use this command:
-
- $ make clean # Unix
- $ mms clean ! (or mmk) OpenVMS
- $ nmake clean # Windows
-
- Assembler error messages can sometimes be sidestepped by using the
- "no-asm" configuration option.
-
- Compiling parts of OpenSSL with gcc and others with the system
- compiler will result in unresolved symbols on some systems.
-
- If you are still having problems you can get help by sending an email
- to the openssl-users email list (see
- https://www.openssl.org/community/mailinglists.html for details). If
- it is a bug with OpenSSL itself, please open an issue on GitHub, at
- https://github.com/openssl/openssl/issues. Please review the existing
- ones first; maybe the bug was already reported or has already been
- fixed.
-
- 3. After a successful build, the libraries should be tested. Run:
-
- $ make test # Unix
- $ mms test ! OpenVMS
- $ nmake test # Windows
-
- NOTE: you MUST run the tests from an unprivileged account (or
- disable your privileges temporarily if your platform allows it).
-
- If some tests fail, look at the output. There may be reasons for
- the failure that isn't a problem in OpenSSL itself (like a
- malfunction with Perl). You may want increased verbosity, that
- can be accomplished like this:
-
- $ make VERBOSE=1 test # Unix
-
- $ mms /macro=(VERBOSE=1) test ! OpenVMS
-
- $ nmake VERBOSE=1 test # Windows
-
- If you want to run just one or a few specific tests, you can use
- the make variable TESTS to specify them, like this:
-
- $ make TESTS='test_rsa test_dsa' test # Unix
- $ mms/macro="TESTS=test_rsa test_dsa" test ! OpenVMS
- $ nmake TESTS='test_rsa test_dsa' test # Windows
-
- And of course, you can combine (Unix example shown):
-
- $ make VERBOSE=1 TESTS='test_rsa test_dsa' test
-
- You can find the list of available tests like this:
-
- $ make list-tests # Unix
- $ mms list-tests ! OpenVMS
- $ nmake list-tests # Windows
-
- Have a look at the manual for the perl module Test::Harness to
- see what other HARNESS_* variables there are.
-
- If you find a problem with OpenSSL itself, try removing any
- compiler optimization flags from the CFLAGS line in Makefile and
- run "make clean; make" or corresponding.
-
- To report a bug please open an issue on GitHub, at
- https://github.com/openssl/openssl/issues.
-
- For more details on how the make variables TESTS can be used,
- see section TESTS in Detail below.
-
- 4. If everything tests ok, install OpenSSL with
-
- $ make install # Unix
- $ mms install ! OpenVMS
- $ nmake install # Windows
-
- Note that in order to perform the install step above you need to have
- appropriate permissions to write to the installation directory.
-
- The above commands will install all the software components in this
- directory tree under PREFIX (the directory given with --prefix or its
- default):
-
- Unix:
-
- bin/ Contains the openssl binary and a few other
- utility scripts.
- include/openssl
- Contains the header files needed if you want
- to build your own programs that use libcrypto
- or libssl.
- lib Contains the OpenSSL library files.
- lib/engines Contains the OpenSSL dynamically loadable engines.
-
- share/man/man1 Contains the OpenSSL command line man-pages.
- share/man/man3 Contains the OpenSSL library calls man-pages.
- share/man/man5 Contains the OpenSSL configuration format man-pages.
- share/man/man7 Contains the OpenSSL other misc man-pages.
-
- share/doc/openssl/html/man1
- share/doc/openssl/html/man3
- share/doc/openssl/html/man5
- share/doc/openssl/html/man7
- Contains the HTML rendition of the man-pages.
-
- OpenVMS ('arch' is replaced with the architecture name, "ALPHA"
- or "IA64", 'sover' is replaced with the shared library version
- (0101 for 1.1.x), and 'pz' is replaced with the pointer size
- OpenSSL was built with):
-
- [.EXE.'arch'] Contains the openssl binary.
- [.EXE] Contains a few utility scripts.
- [.include.openssl]
- Contains the header files needed if you want
- to build your own programs that use libcrypto
- or libssl.
- [.LIB.'arch'] Contains the OpenSSL library files.
- [.ENGINES'sover''pz'.'arch']
- Contains the OpenSSL dynamically loadable engines.
- [.SYS$STARTUP] Contains startup, login and shutdown scripts.
- These define appropriate logical names and
- command symbols.
- [.SYSTEST] Contains the installation verification procedure.
- [.HTML] Contains the HTML rendition of the manual pages.
-
-
- Additionally, install will add the following directories under
- OPENSSLDIR (the directory given with --openssldir or its default)
- for you convenience:
-
- certs Initially empty, this is the default location
- for certificate files.
- private Initially empty, this is the default location
- for private key files.
- misc Various scripts.
-
- The installation directory should be appropriately protected to ensure
- unprivileged users cannot make changes to OpenSSL binaries or files, or
- install engines. If you already have a pre-installed version of OpenSSL as
- part of your Operating System it is recommended that you do not overwrite
- the system version and instead install to somewhere else.
-
- Package builders who want to configure the library for standard
- locations, but have the package installed somewhere else so that
- it can easily be packaged, can use
-
- $ make DESTDIR=/tmp/package-root install # Unix
- $ mms/macro="DESTDIR=TMP:[PACKAGE-ROOT]" install ! OpenVMS
-
- The specified destination directory will be prepended to all
- installation target paths.
-
- Compatibility issues with previous OpenSSL versions:
-
- * COMPILING existing applications
-
- Starting with version 1.1.0, OpenSSL hides a number of structures
- that were previously open. This includes all internal libssl
- structures and a number of EVP types. Accessor functions have
- been added to allow controlled access to the structures' data.
-
- This means that some software needs to be rewritten to adapt to
- the new ways of doing things. This often amounts to allocating
- an instance of a structure explicitly where you could previously
- allocate them on the stack as automatic variables, and using the
- provided accessor functions where you would previously access a
- structure's field directly.
-
- Some APIs have changed as well. However, older APIs have been
- preserved when possible.
-
- Environment Variables
- ---------------------
-
- A number of environment variables can be used to provide additional control
- over the build process. Typically these should be defined prior to running
- config or Configure. Not all environment variables are relevant to all
- platforms.
-
- AR
- The name of the ar executable to use.
-
- BUILDFILE
- Use a different build file name than the platform default
- ("Makefile" on Unix-like platforms, "makefile" on native Windows,
- "descrip.mms" on OpenVMS). This requires that there is a
- corresponding build file template. See Configurations/README
- for further information.
-
- CC
- The compiler to use. Configure will attempt to pick a default
- compiler for your platform but this choice can be overridden
- using this variable. Set it to the compiler executable you wish
- to use, e.g. "gcc" or "clang".
-
- CROSS_COMPILE
- This environment variable has the same meaning as for the
- "--cross-compile-prefix" Configure flag described above. If both
- are set then the Configure flag takes precedence.
-
- NM
- The name of the nm executable to use.
-
- OPENSSL_LOCAL_CONFIG_DIR
- OpenSSL comes with a database of information about how it
- should be built on different platforms as well as build file
- templates for those platforms. The database is comprised of
- ".conf" files in the Configurations directory. The build
- file templates reside there as well as ".tmpl" files. See the
- file Configurations/README for further information about the
- format of ".conf" files as well as information on the ".tmpl"
- files.
- In addition to the standard ".conf" and ".tmpl" files, it is
- possible to create your own ".conf" and ".tmpl" files and store
- them locally, outside the OpenSSL source tree. This environment
- variable can be set to the directory where these files are held
- and will be considered by Configure before it looks in the
- standard directories.
-
- PERL
- The name of the Perl executable to use when building OpenSSL.
- This variable is used in config script only. Configure on the
- other hand imposes the interpreter by which it itself was
- executed on the whole build procedure.
-
- HASHBANGPERL
- The command string for the Perl executable to insert in the
- #! line of perl scripts that will be publicly installed.
- Default: /usr/bin/env perl
- Note: the value of this variable is added to the same scripts
- on all platforms, but it's only relevant on Unix-like platforms.
-
- RC
- The name of the rc executable to use. The default will be as
- defined for the target platform in the ".conf" file. If not
- defined then "windres" will be used. The WINDRES environment
- variable is synonymous to this. If both are defined then RC
- takes precedence.
-
- RANLIB
- The name of the ranlib executable to use.
-
- WINDRES
- See RC.
-
- Makefile targets
- ----------------
-
- The Configure script generates a Makefile in a format relevant to the specific
- platform. The Makefiles provide a number of targets that can be used. Not all
- targets may be available on all platforms. Only the most common targets are
- described here. Examine the Makefiles themselves for the full list.
-
- all
- The default target to build all the software components.
-
- clean
- Remove all build artefacts and return the directory to a "clean"
- state.
-
- depend
- Rebuild the dependencies in the Makefiles. This is a legacy
- option that no longer needs to be used since OpenSSL 1.1.0.
-
- install
- Install all OpenSSL components.
-
- install_sw
- Only install the OpenSSL software components.
-
- install_docs
- Only install the OpenSSL documentation components.
-
- install_man_docs
- Only install the OpenSSL man pages (Unix only).
-
- install_html_docs
- Only install the OpenSSL html documentation.
-
- list-tests
- Prints a list of all the self test names.
-
- test
- Build and run the OpenSSL self tests.
-
- uninstall
- Uninstall all OpenSSL components.
-
- reconfigure
- reconf
- Re-run the configuration process, as exactly as the last time
- as possible.
-
- update
- This is a developer option. If you are developing a patch for
- OpenSSL you may need to use this if you want to update
- automatically generated files; add new error codes or add new
- (or change the visibility of) public API functions. (Unix only).
-
- TESTS in Detail
- ---------------
-
- The make variable TESTS supports a versatile set of space separated tokens
- with which you can specify a set of tests to be performed. With a "current
- set of tests" in mind, initially being empty, here are the possible tokens:
-
- alltests The current set of tests becomes the whole set of available
- tests (as listed when you do 'make list-tests' or similar).
- xxx Adds the test 'xxx' to the current set of tests.
- -xxx Removes 'xxx' from the current set of tests. If this is the
- first token in the list, the current set of tests is first
- assigned the whole set of available tests, effectively making
- this token equivalent to TESTS="alltests -xxx".
- nn Adds the test group 'nn' (which is a number) to the current
- set of tests.
- -nn Removes the test group 'nn' from the current set of tests.
- If this is the first token in the list, the current set of
- tests is first assigned the whole set of available tests,
- effectively making this token equivalent to
- TESTS="alltests -xxx".
-
- Also, all tokens except for "alltests" may have wildcards, such as *.
- (on Unix and Windows, BSD style wildcards are supported, while on VMS,
- it's VMS style wildcards)
-
- Example: All tests except for the fuzz tests:
-
- $ make TESTS=-test_fuzz test
-
- or (if you want to be explicit)
-
- $ make TESTS='alltests -test_fuzz' test
-
- Example: All tests that have a name starting with "test_ssl" but not those
- starting with "test_ssl_":
-
- $ make TESTS='test_ssl* -test_ssl_*' test
-
- Example: Only test group 10:
-
- $ make TESTS='10'
-
- Example: All tests except the slow group (group 99):
-
- $ make TESTS='-99'
-
- Example: All tests in test groups 80 to 99 except for tests in group 90:
-
- $ make TESTS='[89]? -90'
-
- Note on multi-threading
- -----------------------
-
- For some systems, the OpenSSL Configure script knows what compiler options
- are needed to generate a library that is suitable for multi-threaded
- applications. On these systems, support for multi-threading is enabled
- by default; use the "no-threads" option to disable (this should never be
- necessary).
-
- On other systems, to enable support for multi-threading, you will have
- to specify at least two options: "threads", and a system-dependent option.
- (The latter is "-D_REENTRANT" on various systems.) The default in this
- case, obviously, is not to include support for multi-threading (but
- you can still use "no-threads" to suppress an annoying warning message
- from the Configure script.)
-
- OpenSSL provides built-in support for two threading models: pthreads (found on
- most UNIX/Linux systems), and Windows threads. No other threading models are
- supported. If your platform does not provide pthreads or Windows threads then
- you should Configure with the "no-threads" option.
-
- Notes on shared libraries
- -------------------------
-
- For most systems the OpenSSL Configure script knows what is needed to
- build shared libraries for libcrypto and libssl. On these systems
- the shared libraries will be created by default. This can be suppressed and
- only static libraries created by using the "no-shared" option. On systems
- where OpenSSL does not know how to build shared libraries the "no-shared"
- option will be forced and only static libraries will be created.
-
- Shared libraries are named a little differently on different platforms.
- One way or another, they all have the major OpenSSL version number as
- part of the file name, i.e. for OpenSSL 1.1.x, 1.1 is somehow part of
- the name.
-
- On most POSIX platforms, shared libraries are named libcrypto.so.1.1
- and libssl.so.1.1.
-
- on Cygwin, shared libraries are named cygcrypto-1.1.dll and cygssl-1.1.dll
- with import libraries libcrypto.dll.a and libssl.dll.a.
-
- On Windows build with MSVC or using MingW, shared libraries are named
- libcrypto-1_1.dll and libssl-1_1.dll for 32-bit Windows, libcrypto-1_1-x64.dll
- and libssl-1_1-x64.dll for 64-bit x86_64 Windows, and libcrypto-1_1-ia64.dll
- and libssl-1_1-ia64.dll for IA64 Windows. With MSVC, the import libraries
- are named libcrypto.lib and libssl.lib, while with MingW, they are named
- libcrypto.dll.a and libssl.dll.a.
-
- On VMS, shareable images (VMS speak for shared libraries) are named
- ossl$libcrypto0101_shr.exe and ossl$libssl0101_shr.exe. However, when
- OpenSSL is specifically built for 32-bit pointers, the shareable images
- are named ossl$libcrypto0101_shr32.exe and ossl$libssl0101_shr32.exe
- instead, and when built for 64-bit pointers, they are named
- ossl$libcrypto0101_shr64.exe and ossl$libssl0101_shr64.exe.
-
- Note on random number generation
- --------------------------------
-
- Availability of cryptographically secure random numbers is required for
- secret key generation. OpenSSL provides several options to seed the
- internal CSPRNG. If not properly seeded, the internal CSPRNG will refuse
- to deliver random bytes and a "PRNG not seeded error" will occur.
-
- The seeding method can be configured using the --with-rand-seed option,
- which can be used to specify a comma separated list of seed methods.
- However in most cases OpenSSL will choose a suitable default method,
- so it is not necessary to explicitly provide this option. Note also
- that not all methods are available on all platforms.
-
- I) On operating systems which provide a suitable randomness source (in
- form of a system call or system device), OpenSSL will use the optimal
- available method to seed the CSPRNG from the operating system's
- randomness sources. This corresponds to the option --with-rand-seed=os.
-
- II) On systems without such a suitable randomness source, automatic seeding
- and reseeding is disabled (--with-rand-seed=none) and it may be necessary
- to install additional support software to obtain a random seed and reseed
- the CSPRNG manually. Please check out the manual pages for RAND_add(),
- RAND_bytes(), RAND_egd(), and the FAQ for more information.
diff --git a/INSTALL.md b/INSTALL.md
new file mode 100644
index 000000000000..84e8a7d542a5
--- /dev/null
+++ b/INSTALL.md
@@ -0,0 +1,1817 @@
+Build and Install
+=================
+
+This document describes installation on all supported operating
+systems (the Unix/Linux family, including macOS), OpenVMS,
+and Windows).
+
+Table of Contents
+=================
+
+ - [Prerequisites](#prerequisites)
+ - [Notational Conventions](#notational-conventions)
+ - [Quick Installation Guide](#quick-installation-guide)
+ - [Building OpenSSL](#building-openssl)
+ - [Installing OpenSSL](#installing-openssl)
+ - [Configuration Options](#configuration-options)
+ - [API Level](#api-level)
+ - [Cross Compile Prefix](#cross-compile-prefix)
+ - [Build Type](#build-type)
+ - [Directories](#directories)
+ - [Compiler Warnings](#compiler-warnings)
+ - [ZLib Flags](#zlib-flags)
+ - [Seeding the Random Generator](#seeding-the-random-generator)
+ - [Setting the FIPS HMAC key](#setting-the-FIPS-HMAC-key)
+ - [Enable and Disable Features](#enable-and-disable-features)
+ - [Displaying configuration data](#displaying-configuration-data)
+ - [Installation Steps in Detail](#installation-steps-in-detail)
+ - [Configure](#configure-openssl)
+ - [Build](#build-openssl)
+ - [Test](#test-openssl)
+ - [Install](#install-openssl)
+ - [Advanced Build Options](#advanced-build-options)
+ - [Environment Variables](#environment-variables)
+ - [Makefile Targets](#makefile-targets)
+ - [Running Selected Tests](#running-selected-tests)
+ - [Troubleshooting](#troubleshooting)
+ - [Configuration Problems](#configuration-problems)
+ - [Build Failures](#build-failures)
+ - [Test Failures](#test-failures)
+ - [Notes](#notes)
+ - [Notes on multi-threading](#notes-on-multi-threading)
+ - [Notes on shared libraries](#notes-on-shared-libraries)
+ - [Notes on random number generation](#notes-on-random-number-generation)
+ - [Notes on assembler modules compilation](#notes-on-assembler-modules-compilation)
+
+Prerequisites
+=============
+
+To install OpenSSL, you will need:
+
+ * A "make" implementation
+ * Perl 5 with core modules (please read [NOTES-PERL.md](NOTES-PERL.md))
+ * The Perl module `Text::Template` (please read [NOTES-PERL.md](NOTES-PERL.md))
+ * an ANSI C compiler
+ * a development environment in the form of development libraries and C
+ header files
+ * a supported operating system
+
+For additional platform specific requirements, solutions to specific
+issues and other details, please read one of these:
+
+ * [Notes for UNIX-like platforms](NOTES-UNIX.md)
+ * [Notes for Android platforms](NOTES-ANDROID.md)
+ * [Notes for Windows platforms](NOTES-WINDOWS.md)
+ * [Notes for the DOS platform with DJGPP](NOTES-DJGPP.md)
+ * [Notes for the OpenVMS platform](NOTES-VMS.md)
+ * [Notes on Perl](NOTES-PERL.md)
+ * [Notes on Valgrind](NOTES-VALGRIND.md)
+
+Notational conventions
+======================
+
+Throughout this document, we use the following conventions.
+
+Commands
+--------
+
+Any line starting with a dollar sign is a command line.
+
+ $ command
+
+The dollar sign indicates the shell prompt and is not to be entered as
+part of the command.
+
+Choices
+-------
+
+Several words in curly braces separated by pipe characters indicate a
+**mandatory choice**, to be replaced with one of the given words.
+For example, the line
+
+ $ echo { WORD1 | WORD2 | WORD3 }
+
+represents one of the following three commands
+
+ $ echo WORD1
+ - or -
+ $ echo WORD2
+ - or -
+ $ echo WORD3
+
+One or several words in square brackets separated by pipe characters
+denote an **optional choice**. It is similar to the mandatory choice,
+but it can also be omitted entirely.
+
+So the line
+
+ $ echo [ WORD1 | WORD2 | WORD3 ]
+
+represents one of the four commands
+
+ $ echo WORD1
+ - or -
+ $ echo WORD2
+ - or -
+ $ echo WORD3
+ - or -
+ $ echo
+
+Arguments
+---------
+
+**Mandatory arguments** are enclosed in double curly braces.
+A simple example would be
+
+ $ type {{ filename }}
+
+which is to be understood to use the command `type` on some file name
+determined by the user.
+
+**Optional Arguments** are enclosed in double square brackets.
+
+ [[ options ]]
+
+Note that the notation assumes spaces around `{`, `}`, `[`, `]`, `{{`, `}}` and
+`[[`, `]]`. This is to differentiate from OpenVMS directory
+specifications, which also use [ and ], but without spaces.
+
+Quick Installation Guide
+========================
+
+If you just want to get OpenSSL installed without bothering too much
+about the details, here is the short version of how to build and install
+OpenSSL. If any of the following steps fails, please consult the
+[Installation in Detail](#installation-steps-in-detail) section below.
+
+Building OpenSSL
+----------------
+
+Use the following commands to configure, build and test OpenSSL.
+The testing is optional, but recommended if you intend to install
+OpenSSL for production use.
+
+### Unix / Linux / macOS
+
+ $ ./Configure
+ $ make
+ $ make test
+
+### OpenVMS
+
+Use the following commands to build OpenSSL:
+
+ $ perl Configure
+ $ mms
+ $ mms test
+
+### Windows
+
+If you are using Visual Studio, open a Developer Command Prompt and
+issue the following commands to build OpenSSL.
+
+ $ perl Configure
+ $ nmake
+ $ nmake test
+
+As mentioned in the [Choices](#choices) section, you need to pick one
+of the four Configure targets in the first command.
+
+Most likely you will be using the `VC-WIN64A` target for 64bit Windows
+binaries (AMD64) or `VC-WIN32` for 32bit Windows binaries (X86).
+The other two options are `VC-WIN64I` (Intel IA64, Itanium) and
+`VC-CE` (Windows CE) are rather uncommon nowadays.
+
+Installing OpenSSL
+------------------
+
+The following commands will install OpenSSL to a default system location.
+
+**Danger Zone:** even if you are impatient, please read the following two
+paragraphs carefully before you install OpenSSL.
+
+For security reasons the default system location is by default not writable
+for unprivileged users. So for the final installation step administrative
+privileges are required. The default system location and the procedure to
+obtain administrative privileges depends on the operating system.
+It is recommended to compile and test OpenSSL with normal user privileges
+and use administrative privileges only for the final installation step.
+
+On some platforms OpenSSL is preinstalled as part of the Operating System.
+In this case it is highly recommended not to overwrite the system versions,
+because other applications or libraries might depend on it.
+To avoid breaking other applications, install your copy of OpenSSL to a
+[different location](#installing-to-a-different-location) which is not in
+the global search path for system libraries.
+
+Finally, if you plan on using the FIPS module, you need to read the
+[Post-installation Notes](#post-installation-notes) further down.
+
+### Unix / Linux / macOS
+
+Depending on your distribution, you need to run the following command as
+root user or prepend `sudo` to the command:
+
+ $ make install
+
+By default, OpenSSL will be installed to
+
+ /usr/local
+
+More precisely, the files will be installed into the subdirectories
+
+ /usr/local/bin
+ /usr/local/lib
+ /usr/local/include
+ ...
+
+depending on the file type, as it is custom on Unix-like operating systems.
+
+### OpenVMS
+
+Use the following command to install OpenSSL.
+
+ $ mms install
+
+By default, OpenSSL will be installed to
+
+ SYS$COMMON:[OPENSSL]
+
+### Windows
+
+If you are using Visual Studio, open the Developer Command Prompt _elevated_
+and issue the following command.
+
+ $ nmake install
+
+The easiest way to elevate the Command Prompt is to press and hold down both
+the `<CTRL>` and `<SHIFT>` keys while clicking the menu item in the task menu.
+
+The default installation location is
+
+ C:\Program Files\OpenSSL
+
+for native binaries, or
+
+ C:\Program Files (x86)\OpenSSL
+
+for 32bit binaries on 64bit Windows (WOW64).
+
+#### Installing to a different location
+
+To install OpenSSL to a different location (for example into your home
+directory for testing purposes) run `Configure` as shown in the following
+examples.
+
+The options `--prefix` and `--openssldir` are explained in further detail in
+[Directories](#directories) below, and the values used here are mere examples.
+
+On Unix:
+
+ $ ./Configure --prefix=/opt/openssl --openssldir=/usr/local/ssl
+
+On OpenVMS:
+
+ $ perl Configure --prefix=PROGRAM:[INSTALLS] --openssldir=SYS$MANAGER:[OPENSSL]
+
+Note: if you do add options to the configuration command, please make sure
+you've read more than just this Quick Start, such as relevant `NOTES-*` files,
+the options outline below, as configuration options may change the outcome
+in otherwise unexpected ways.
+
+Configuration Options
+=====================
+
+There are several options to `./Configure` to customize the build (note that
+for Windows, the defaults for `--prefix` and `--openssldir` depend on what
+configuration is used and what Windows implementation OpenSSL is built on.
+For more information, see the [Notes for Windows platforms](NOTES-WINDOWS.md).
+
+API Level
+---------
+
+ --api=x.y[.z]
+
+Build the OpenSSL libraries to support the API for the specified version.
+If [no-deprecated](#no-deprecated) is also given, don't build with support
+for deprecated APIs in or below the specified version number. For example,
+adding
+
+ --api=1.1.0 no-deprecated
+
+will remove support for all APIs that were deprecated in OpenSSL version
+1.1.0 or below. This is a rather specialized option for developers.
+If you just intend to remove all deprecated APIs up to the current version
+entirely, just specify [no-deprecated](#no-deprecated).
+If `--api` isn't given, it defaults to the current (minor) OpenSSL version.
+
+Cross Compile Prefix
+--------------------
+
+ --cross-compile-prefix=<PREFIX>
+
+The `<PREFIX>` to include in front of commands for your toolchain.
+
+It is likely to have to end with dash, e.g. `a-b-c-` would invoke GNU compiler
+as `a-b-c-gcc`, etc. Unfortunately cross-compiling is too case-specific to put
+together one-size-fits-all instructions. You might have to pass more flags or
+set up environment variables to actually make it work. Android and iOS cases
+are discussed in corresponding `Configurations/15-*.conf` files. But there are
+cases when this option alone is sufficient. For example to build the mingw64
+target on Linux `--cross-compile-prefix=x86_64-w64-mingw32-` works. Naturally
+provided that mingw packages are installed. Today Debian and Ubuntu users
+have option to install a number of prepackaged cross-compilers along with
+corresponding run-time and development packages for "alien" hardware. To give
+another example `--cross-compile-prefix=mipsel-linux-gnu-` suffices in such
+case.
+
+For cross compilation, you must [configure manually](#manual-configuration).
+Also, note that `--openssldir` refers to target's file system, not one you are
+building on.
+
+Build Type
+----------
+
+ --debug
+
+Build OpenSSL with debugging symbols and zero optimization level.
+
+ --release
+
+Build OpenSSL without debugging symbols. This is the default.
+
+Directories
+-----------
+
+### libdir
+
+ --libdir=DIR
+
+The name of the directory under the top of the installation directory tree
+(see the `--prefix` option) where libraries will be installed. By default
+this is `lib`. Note that on Windows only static libraries (`*.lib`) will
+be stored in this location. Shared libraries (`*.dll`) will always be
+installed to the `bin` directory.
+
+Some build targets have a multilib postfix set in the build configuration.
+For these targets the default libdir is `lib<multilib-postfix>`. Please use
+`--libdir=lib` to override the libdir if adding the postfix is undesirable.
+
+### openssldir
+
+ --openssldir=DIR
+
+Directory for OpenSSL configuration files, and also the default certificate
+and key store. Defaults are:
+
+ Unix: /usr/local/ssl
+ Windows: C:\Program Files\Common Files\SSL
+ OpenVMS: SYS$COMMON:[OPENSSL-COMMON]
+
+For 32bit Windows applications on Windows 64bit (WOW64), always replace
+`C:\Program Files` by `C:\Program Files (x86)`.
+
+### prefix
+
+ --prefix=DIR
+
+The top of the installation directory tree. Defaults are:
+
+ Unix: /usr/local
+ Windows: C:\Program Files\OpenSSL
+ OpenVMS: SYS$COMMON:[OPENSSL]
+
+Compiler Warnings
+-----------------
+
+ --strict-warnings
+
+This is a developer flag that switches on various compiler options recommended
+for OpenSSL development. It only works when using gcc or clang as the compiler.
+If you are developing a patch for OpenSSL then it is recommended that you use
+this option where possible.
+
+ZLib Flags
+----------
+
+### with-zlib-include
+
+ --with-zlib-include=DIR
+
+The directory for the location of the zlib include file. This option is only
+necessary if [zlib](#zlib) is used and the include file is not
+already on the system include path.
+
+### with-zlib-lib
+
+ --with-zlib-lib=LIB
+
+**On Unix**: this is the directory containing the zlib library.
+If not provided the system library path will be used.
+
+**On Windows:** this is the filename of the zlib library (with or
+without a path). This flag must be provided if the
+[zlib-dynamic](#zlib-dynamic) option is not also used. If `zlib-dynamic` is used
+then this flag is optional and defaults to `ZLIB1` if not provided.
+
+**On VMS:** this is the filename of the zlib library (with or without a path).
+This flag is optional and if not provided then `GNV$LIBZSHR`, `GNV$LIBZSHR32`
+or `GNV$LIBZSHR64` is used by default depending on the pointer size chosen.
+
+Seeding the Random Generator
+----------------------------
+
+ --with-rand-seed=seed1[,seed2,...]
+
+A comma separated list of seeding methods which will be tried by OpenSSL
+in order to obtain random input (a.k.a "entropy") for seeding its
+cryptographically secure random number generator (CSPRNG).
+The current seeding methods are:
+
+### os
+
+Use a trusted operating system entropy source.
+This is the default method if such an entropy source exists.
+
+### getrandom
+
+Use the [getrandom(2)][man-getrandom] or equivalent system call.
+
+[man-getrandom]: http://man7.org/linux/man-pages/man2/getrandom.2.html
+
+### devrandom
+
+Use the first device from the `DEVRANDOM` list which can be opened to read
+random bytes. The `DEVRANDOM` preprocessor constant expands to
+
+ "/dev/urandom","/dev/random","/dev/srandom"
+
+on most unix-ish operating systems.
+
+### egd
+
+Check for an entropy generating daemon.
+This source is ignored by the FIPS provider.
+
+### rdcpu
+
+Use the `RDSEED` or `RDRAND` command if provided by the CPU.
+
+### librandom
+
+Use librandom (not implemented yet).
+This source is ignored by the FIPS provider.
+
+### none
+
+Disable automatic seeding. This is the default on some operating systems where
+no suitable entropy source exists, or no support for it is implemented yet.
+This option is ignored by the FIPS provider.
+
+For more information, see the section [Notes on random number generation][rng]
+at the end of this document.
+
+[rng]: #notes-on-random-number-generation
+
+Setting the FIPS HMAC key
+-------------------------
+
+ --fips-key=value
+
+As part of its self-test validation, the FIPS module must verify itself
+by performing a SHA-256 HMAC computation on itself. The default key is
+the SHA256 value of "the holy handgrenade of antioch" and is sufficient
+for meeting the FIPS requirements.
+
+To change the key to a different value, use this flag. The value should
+be a hex string no more than 64 characters.
+
+Enable and Disable Features
+---------------------------
+
+Feature options always come in pairs, an option to enable feature
+`xxxx`, and an option to disable it:
+
+ [ enable-xxxx | no-xxxx ]
+
+Whether a feature is enabled or disabled by default, depends on the feature.
+In the following list, always the non-default variant is documented: if
+feature `xxxx` is disabled by default then `enable-xxxx` is documented and
+if feature `xxxx` is enabled by default then `no-xxxx` is documented.
+
+### no-afalgeng
+
+Don't build the AFALG engine.
+
+This option will be forced on a platform that does not support AFALG.
+
+### enable-ktls
+
+Build with Kernel TLS support.
+
+This option will enable the use of the Kernel TLS data-path, which can improve
+performance and allow for the use of sendfile and splice system calls on
+TLS sockets. The Kernel may use TLS accelerators if any are available on the
+system. This option will be forced off on systems that do not support the
+Kernel TLS data-path.
+
+### enable-asan
+
+Build with the Address sanitiser.
+
+This is a developer option only. It may not work on all platforms and should
+never be used in production environments. It will only work when used with
+gcc or clang and should be used in conjunction with the [no-shared](#no-shared)
+option.
+
+### enable-acvp-tests
+
+Build support for Automated Cryptographic Validation Protocol (ACVP)
+tests.
+
+This is required for FIPS validation purposes. Certain ACVP tests require
+access to algorithm internals that are not normally accessible.
+Additional information related to ACVP can be found at
+<https://github.com/usnistgov/ACVP>.
+
+### no-asm
+
+Do not use assembler code.
+
+This should be viewed as debugging/troubleshooting option rather than for
+production use. On some platforms a small amount of assembler code may still
+be used even with this option.
+
+### no-async
+
+Do not build support for async operations.
+
+### no-autoalginit
+
+Don't automatically load all supported ciphers and digests.
+
+Typically OpenSSL will make available all of its supported ciphers and digests.
+For a statically linked application this may be undesirable if small executable
+size is an objective. This only affects libcrypto. Ciphers and digests will
+have to be loaded manually using `EVP_add_cipher()` and `EVP_add_digest()`
+if this option is used. This option will force a non-shared build.
+
+### no-autoerrinit
+
+Don't automatically load all libcrypto/libssl error strings.
+
+Typically OpenSSL will automatically load human readable error strings. For a
+statically linked application this may be undesirable if small executable size
+is an objective.
+
+### no-autoload-config
+
+Don't automatically load the default `openssl.cnf` file.
+
+Typically OpenSSL will automatically load a system config file which configures
+default SSL options.
+
+### enable-buildtest-c++
+
+While testing, generate C++ buildtest files that simply check that the public
+OpenSSL header files are usable standalone with C++.
+
+Enabling this option demands extra care. For any compiler flag given directly
+as configuration option, you must ensure that it's valid for both the C and
+the C++ compiler. If not, the C++ build test will most likely break. As an
+alternative, you can use the language specific variables, `CFLAGS` and `CXXFLAGS`.
+
+### --banner=text
+
+Use the specified text instead of the default banner at the end of
+configuration.
+
+### --w
+
+On platforms where the choice of 32-bit or 64-bit architecture
+is not explicitly specified, `Configure` will print a warning
+message and wait for a few seconds to let you interrupt the
+configuration. Using this flag skips the wait.
+
+### no-bulk
+
+Build only some minimal set of features.
+This is a developer option used internally for CI build tests of the project.
+
+### no-cached-fetch
+
+Never cache algorithms when they are fetched from a provider. Normally, a
+provider indicates if the algorithms it supplies can be cached or not. Using
+this option will reduce run-time memory usage but it also introduces a
+significant performance penalty. This option is primarily designed to help
+with detecting incorrect reference counting.
+
+### no-capieng
+
+Don't build the CAPI engine.
+
+This option will be forced if on a platform that does not support CAPI.
+
+### no-cmp
+
+Don't build support for Certificate Management Protocol (CMP)
+and Certificate Request Message Format (CRMF).
+
+### no-cms
+
+Don't build support for Cryptographic Message Syntax (CMS).
+
+### no-comp
+
+Don't build support for SSL/TLS compression.
+
+If this option is enabled (the default), then compression will only work if
+the zlib or `zlib-dynamic` options are also chosen.
+
+### enable-crypto-mdebug
+
+This now only enables the `failed-malloc` feature.
+
+### enable-crypto-mdebug-backtrace
+
+This is a no-op; the project uses the compiler's address/leak sanitizer instead.
+
+### no-ct
+
+Don't build support for Certificate Transparency (CT).
+
+### no-deprecated
+
+Don't build with support for deprecated APIs up until and including the version
+given with `--api` (or the current version, if `--api` wasn't specified).
+
+### no-dgram
+
+Don't build support for datagram based BIOs.
+
+Selecting this option will also force the disabling of DTLS.
+
+### no-dso
+
+Don't build support for loading Dynamic Shared Objects (DSO)
+
+### enable-devcryptoeng
+
+Build the `/dev/crypto` engine.
+
+This option is automatically selected on the BSD platform, in which case it can
+be disabled with `no-devcryptoeng`.
+
+### no-dynamic-engine
+
+Don't build the dynamically loaded engines.
+
+This only has an effect in a shared build.
+
+### no-ec
+
+Don't build support for Elliptic Curves.
+
+### no-ec2m
+
+Don't build support for binary Elliptic Curves
+
+### enable-ec_nistp_64_gcc_128
+
+Enable support for optimised implementations of some commonly used NIST
+elliptic curves.
+
+This option is only supported on platforms:
+
+ - with little-endian storage of non-byte types
+ - that tolerate misaligned memory references
+ - where the compiler:
+ - supports the non-standard type `__uint128_t`
+ - defines the built-in macro `__SIZEOF_INT128__`
+
+### enable-egd
+
+Build support for gathering entropy from the Entropy Gathering Daemon (EGD).
+
+### no-engine
+
+Don't build support for loading engines.
+
+### no-err
+
+Don't compile in any error strings.
+
+### enable-external-tests
+
+Enable building of integration with external test suites.
+
+This is a developer option and may not work on all platforms. The following
+external test suites are currently supported:
+
+ - GOST engine test suite
+ - Python PYCA/Cryptography test suite
+ - krb5 test suite
+
+See the file [test/README-external.md](test/README-external.md)
+for further details.
+
+### no-filenames
+
+Don't compile in filename and line number information (e.g. for errors and
+memory allocation).
+
+### enable-fips
+
+Build (and install) the FIPS provider
+
+### no-fips-securitychecks
+
+Don't perform FIPS module run-time checks related to enforcement of security
+parameters such as minimum security strength of keys.
+
+### enable-fuzz-libfuzzer, enable-fuzz-afl
+
+Build with support for fuzzing using either libfuzzer or AFL.
+
+These are developer options only. They may not work on all platforms and
+should never be used in production environments.
+
+See the file [fuzz/README.md](fuzz/README.md) for further details.
+
+### no-gost
+
+Don't build support for GOST based ciphersuites.
+
+Note that if this feature is enabled then GOST ciphersuites are only available
+if the GOST algorithms are also available through loading an externally supplied
+engine.
+
+### no-legacy
+
+Don't build the legacy provider.
+
+Disabling this also disables the legacy algorithms: MD2 (already disabled by default).
+
+### no-makedepend
+
+Don't generate dependencies.
+
+### no-module
+
+Don't build any dynamically loadable engines.
+
+This also implies `no-dynamic-engine`.
+
+### no-multiblock
+
+Don't build support for writing multiple records in one go in libssl
+
+Note: this is a different capability to the pipelining functionality.
+
+### no-nextprotoneg
+
+Don't build support for the Next Protocol Negotiation (NPN) TLS extension.
+
+### no-ocsp
+
+Don't build support for Online Certificate Status Protocol (OCSP).
+
+### no-padlockeng
+
+Don't build the padlock engine.
+
+### no-hw-padlock
+
+As synonym for `no-padlockeng`. Deprecated and should not be used.
+
+### no-pic
+
+Don't build with support for Position Independent Code.
+
+### no-pinshared
+
+Don't pin the shared libraries.
+
+By default OpenSSL will attempt to stay in memory until the process exits.
+This is so that libcrypto and libssl can be properly cleaned up automatically
+via an `atexit()` handler. The handler is registered by libcrypto and cleans
+up both libraries. On some platforms the `atexit()` handler will run on unload of
+libcrypto (if it has been dynamically loaded) rather than at process exit. This
+option can be used to stop OpenSSL from attempting to stay in memory until the
+process exits. This could lead to crashes if either libcrypto or libssl have
+already been unloaded at the point that the atexit handler is invoked, e.g. on a
+platform which calls `atexit()` on unload of the library, and libssl is unloaded
+before libcrypto then a crash is likely to happen. Applications can suppress
+running of the `atexit()` handler at run time by using the
+`OPENSSL_INIT_NO_ATEXIT` option to `OPENSSL_init_crypto()`.
+See the man page for it for further details.
+
+### no-posix-io
+
+Don't use POSIX IO capabilities.
+
+### no-psk
+
+Don't build support for Pre-Shared Key based ciphersuites.
+
+### no-rdrand
+
+Don't use hardware RDRAND capabilities.
+
+### no-rfc3779
+
+Don't build support for RFC3779, "X.509 Extensions for IP Addresses and
+AS Identifiers".
+
+### sctp
+
+Build support for Stream Control Transmission Protocol (SCTP).
+
+### no-shared
+
+Do not create shared libraries, only static ones.
+
+See [Notes on shared libraries](#notes-on-shared-libraries) below.
+
+### no-sock
+
+Don't build support for socket BIOs.
+
+### no-srp
+
+Don't build support for Secure Remote Password (SRP) protocol or
+SRP based ciphersuites.
+
+### no-srtp
+
+Don't build Secure Real-Time Transport Protocol (SRTP) support.
+
+### no-sse2
+
+Exclude SSE2 code paths from 32-bit x86 assembly modules.
+
+Normally SSE2 extension is detected at run-time, but the decision whether or not
+the machine code will be executed is taken solely on CPU capability vector. This
+means that if you happen to run OS kernel which does not support SSE2 extension
+on Intel P4 processor, then your application might be exposed to "illegal
+instruction" exception. There might be a way to enable support in kernel, e.g.
+FreeBSD kernel can be compiled with `CPU_ENABLE_SSE`, and there is a way to
+disengage SSE2 code paths upon application start-up, but if you aim for wider
+"audience" running such kernel, consider `no-sse2`. Both the `386` and `no-asm`
+options imply `no-sse2`.
+
+### no-ssl-trace
+
+Don't build with SSL Trace capabilities.
+
+This removes the `-trace` option from `s_client` and `s_server`, and omits the
+`SSL_trace()` function from libssl.
+
+Disabling `ssl-trace` may provide a small reduction in libssl binary size.
+
+### no-static-engine
+
+Don't build the statically linked engines.
+
+This only has an impact when not built "shared".
+
+### no-stdio
+
+Don't use anything from the C header file `stdio.h` that makes use of the `FILE`
+type. Only libcrypto and libssl can be built in this way. Using this option will
+suppress building the command line applications. Additionally, since the OpenSSL
+tests also use the command line applications, the tests will also be skipped.
+
+### no-tests
+
+Don't build test programs or run any tests.
+
+### no-threads
+
+Don't build with support for multi-threaded applications.
+
+### threads
+
+Build with support for multi-threaded applications. Most platforms will enable
+this by default. However, if on a platform where this is not the case then this
+will usually require additional system-dependent options!
+
+See [Notes on multi-threading](#notes-on-multi-threading) below.
+
+### enable-trace
+
+Build with support for the integrated tracing api.
+
+See manual pages OSSL_trace_set_channel(3) and OSSL_trace_enabled(3) for details.
+
+### no-ts
+
+Don't build Time Stamping (TS) Authority support.
+
+### enable-ubsan
+
+Build with the Undefined Behaviour sanitiser (UBSAN).
+
+This is a developer option only. It may not work on all platforms and should
+never be used in production environments. It will only work when used with
+gcc or clang and should be used in conjunction with the `-DPEDANTIC` option
+(or the `--strict-warnings` option).
+
+### no-ui-console
+
+Don't build with the User Interface (UI) console method
+
+The User Interface console method enables text based console prompts.
+
+### enable-unit-test
+
+Enable additional unit test APIs.
+
+This should not typically be used in production deployments.
+
+### no-uplink
+
+Don't build support for UPLINK interface.
+
+### enable-weak-ssl-ciphers
+
+Build support for SSL/TLS ciphers that are considered "weak"
+
+Enabling this includes for example the RC4 based ciphersuites.
+
+### zlib
+
+Build with support for zlib compression/decompression.
+
+### zlib-dynamic
+
+Like the zlib option, but has OpenSSL load the zlib library dynamically
+when needed.
+
+This is only supported on systems where loading of shared libraries is supported.
+
+### 386
+
+In 32-bit x86 builds, use the 80386 instruction set only in assembly modules
+
+The default x86 code is more efficient, but requires at least an 486 processor.
+Note: This doesn't affect compiler generated code, so this option needs to be
+accompanied by a corresponding compiler-specific option.
+
+### no-{protocol}
+
+ no-{ssl|ssl3|tls|tls1|tls1_1|tls1_2|tls1_3|dtls|dtls1|dtls1_2}
+
+Don't build support for negotiating the specified SSL/TLS protocol.
+
+If `no-tls` is selected then all of `tls1`, `tls1_1`, `tls1_2` and `tls1_3`
+are disabled.
+Similarly `no-dtls` will disable `dtls1` and `dtls1_2`. The `no-ssl` option is
+synonymous with `no-ssl3`. Note this only affects version negotiation.
+OpenSSL will still provide the methods for applications to explicitly select
+the individual protocol versions.
+
+### no-{protocol}-method
+
+ no-{ssl3|tls1|tls1_1|tls1_2|dtls1|dtls1_2}-method
+
+Analogous to `no-{protocol}` but in addition do not build the methods for
+applications to explicitly select individual protocol versions. Note that there
+is no `no-tls1_3-method` option because there is no application method for
+TLSv1.3.
+
+Using individual protocol methods directly is deprecated. Applications should
+use `TLS_method()` instead.
+
+### enable-{algorithm}
+
+ enable-{md2|rc5}
+
+Build with support for the specified algorithm.
+
+### no-{algorithm}
+
+ no-{aria|bf|blake2|camellia|cast|chacha|cmac|
+ des|dh|dsa|ecdh|ecdsa|idea|md4|mdc2|ocb|
+ poly1305|rc2|rc4|rmd160|scrypt|seed|
+ siphash|siv|sm2|sm3|sm4|whirlpool}
+
+Build without support for the specified algorithm.
+
+The `ripemd` algorithm is deprecated and if used is synonymous with `rmd160`.
+
+### Compiler-specific options
+
+ -Dxxx, -Ixxx, -Wp, -lxxx, -Lxxx, -Wl, -rpath, -R, -framework, -static
+
+These system specific options will be recognised and passed through to the
+compiler to allow you to define preprocessor symbols, specify additional
+libraries, library directories or other compiler options. It might be worth
+noting that some compilers generate code specifically for processor the
+compiler currently executes on. This is not necessarily what you might have
+in mind, since it might be unsuitable for execution on other, typically older,
+processor. Consult your compiler documentation.
+
+Take note of the [Environment Variables](#environment-variables) documentation
+below and how these flags interact with those variables.
+
+ -xxx, +xxx, /xxx
+
+Additional options that are not otherwise recognised are passed through as
+they are to the compiler as well. Unix-style options beginning with a
+`-` or `+` and Windows-style options beginning with a `/` are recognized.
+Again, consult your compiler documentation.
+
+If the option contains arguments separated by spaces, then the URL-style
+notation `%20` can be used for the space character in order to avoid having
+to quote the option. For example, `-opt%20arg` gets expanded to `-opt arg`.
+In fact, any ASCII character can be encoded as %xx using its hexadecimal
+encoding.
+
+Take note of the [Environment Variables](#environment-variables) documentation
+below and how these flags interact with those variables.
+
+### Environment Variables
+
+ VAR=value
+
+Assign the given value to the environment variable `VAR` for `Configure`.
+
+These work just like normal environment variable assignments, but are supported
+on all platforms and are confined to the configuration scripts only.
+These assignments override the corresponding value in the inherited environment,
+if there is one.
+
+The following variables are used as "`make` variables" and can be used as an
+alternative to giving preprocessor, compiler and linker options directly as
+configuration. The following variables are supported:
+
+ AR The static library archiver.
+ ARFLAGS Flags for the static library archiver.
+ AS The assembler compiler.
+ ASFLAGS Flags for the assembler compiler.
+ CC The C compiler.
+ CFLAGS Flags for the C compiler.
+ CXX The C++ compiler.
+ CXXFLAGS Flags for the C++ compiler.
+ CPP The C/C++ preprocessor.
+ CPPFLAGS Flags for the C/C++ preprocessor.
+ CPPDEFINES List of CPP macro definitions, separated
+ by a platform specific character (':' or
+ space for Unix, ';' for Windows, ',' for
+ VMS). This can be used instead of using
+ -D (or what corresponds to that on your
+ compiler) in CPPFLAGS.
+ CPPINCLUDES List of CPP inclusion directories, separated
+ the same way as for CPPDEFINES. This can
+ be used instead of -I (or what corresponds
+ to that on your compiler) in CPPFLAGS.
+ HASHBANGPERL Perl invocation to be inserted after '#!'
+ in public perl scripts (only relevant on
+ Unix).
+ LD The program linker (not used on Unix, $(CC)
+ is used there).
+ LDFLAGS Flags for the shared library, DSO and
+ program linker.
+ LDLIBS Extra libraries to use when linking.
+ Takes the form of a space separated list
+ of library specifications on Unix and
+ Windows, and as a comma separated list of
+ libraries on VMS.
+ RANLIB The library archive indexer.
+ RC The Windows resource compiler.
+ RCFLAGS Flags for the Windows resource compiler.
+ RM The command to remove files and directories.
+
+These cannot be mixed with compiling/linking flags given on the command line.
+In other words, something like this isn't permitted.
+
+ $ ./Configure -DFOO CPPFLAGS=-DBAR -DCOOKIE
+
+Backward compatibility note:
+
+To be compatible with older configuration scripts, the environment variables
+are ignored if compiling/linking flags are given on the command line, except
+for the following:
+
+ AR, CC, CXX, CROSS_COMPILE, HASHBANGPERL, PERL, RANLIB, RC, and WINDRES
+
+For example, the following command will not see `-DBAR`:
+
+ $ CPPFLAGS=-DBAR ./Configure -DCOOKIE
+
+However, the following will see both set variables:
+
+ $ CC=gcc CROSS_COMPILE=x86_64-w64-mingw32- ./Configure -DCOOKIE
+
+If `CC` is set, it is advisable to also set `CXX` to ensure both the C and C++
+compiler are in the same "family". This becomes relevant with
+`enable-external-tests` and `enable-buildtest-c++`.
+
+### Reconfigure
+
+ reconf
+ reconfigure
+
+Reconfigure from earlier data.
+
+This fetches the previous command line options and environment from data
+saved in `configdata.pm` and runs the configuration process again, using
+these options and environment. Note: NO other option is permitted together
+with `reconf`. Note: The original configuration saves away values for ALL
+environment variables that were used, and if they weren't defined, they are
+still saved away with information that they weren't originally defined.
+This information takes precedence over environment variables that are
+defined when reconfiguring.
+
+Displaying configuration data
+-----------------------------
+
+The configuration script itself will say very little, and finishes by
+creating `configdata.pm`. This perl module can be loaded by other scripts
+to find all the configuration data, and it can also be used as a script to
+display all sorts of configuration data in a human readable form.
+
+For more information, please do:
+
+ $ ./configdata.pm --help # Unix
+
+or
+
+ $ perl configdata.pm --help # Windows and VMS
+
+Installation Steps in Detail
+============================
+
+Configure OpenSSL
+-----------------
+
+### Automatic Configuration
+
+In previous version, the `config` script determined the platform type and
+compiler and then called `Configure`. Starting with this release, they are
+the same.
+
+#### Unix / Linux / macOS
+
+ $ ./Configure [[ options ]]
+
+#### OpenVMS
+
+ $ perl Configure [[ options ]]
+
+#### Windows
+
+ $ perl Configure [[ options ]]
+
+### Manual Configuration
+
+OpenSSL knows about a range of different operating system, hardware and
+compiler combinations. To see the ones it knows about, run
+
+ $ ./Configure LIST # Unix
+
+or
+
+ $ perl Configure LIST # All other platforms
+
+For the remainder of this text, the Unix form will be used in all examples.
+Please use the appropriate form for your platform.
+
+Pick a suitable name from the list that matches your system. For most
+operating systems there is a choice between using cc or gcc.
+When you have identified your system (and if necessary compiler) use this
+name as the argument to `Configure`. For example, a `linux-elf` user would
+run:
+
+ $ ./Configure linux-elf [[ options ]]
+
+### Creating your own Configuration
+
+If your system isn't listed, you will have to create a configuration
+file named `Configurations/{{ something }}.conf` and add the correct
+configuration for your system. See the available configs as examples
+and read [Configurations/README.md](Configurations/README.md) and
+[Configurations/README-design.md](Configurations/README-design.md)
+for more information.
+
+The generic configurations `cc` or `gcc` should usually work on 32 bit
+Unix-like systems.
+
+`Configure` creates a build file (`Makefile` on Unix, `makefile` on Windows
+and `descrip.mms` on OpenVMS) from a suitable template in `Configurations/`,
+and defines various macros in `include/openssl/configuration.h` (generated
+from `include/openssl/configuration.h.in`.
+
+If none of the generated build files suit your purpose, it's possible to
+write your own build file template and give its name through the environment
+variable `BUILDFILE`. For example, Ninja build files could be supported by
+writing `Configurations/build.ninja.tmpl` and then configure with `BUILDFILE`
+set like this (Unix syntax shown, you'll have to adapt for other platforms):
+
+ $ BUILDFILE=build.ninja perl Configure [options...]
+
+### Out of Tree Builds
+
+OpenSSL can be configured to build in a build directory separate from the
+source code directory. It's done by placing yourself in some other
+directory and invoking the configuration commands from there.
+
+#### Unix example
+
+ $ mkdir /var/tmp/openssl-build
+ $ cd /var/tmp/openssl-build
+ $ /PATH/TO/OPENSSL/SOURCE/Configure [[ options ]]
+
+#### OpenVMS example
+
+ $ set default sys$login:
+ $ create/dir [.tmp.openssl-build]
+ $ set default [.tmp.openssl-build]
+ $ perl D:[PATH.TO.OPENSSL.SOURCE]Configure [[ options ]]
+
+#### Windows example
+
+ $ C:
+ $ mkdir \temp-openssl
+ $ cd \temp-openssl
+ $ perl d:\PATH\TO\OPENSSL\SOURCE\Configure [[ options ]]
+
+Paths can be relative just as well as absolute. `Configure` will do its best
+to translate them to relative paths whenever possible.
+
+Build OpenSSL
+-------------
+
+Build OpenSSL by running:
+
+ $ make # Unix
+ $ mms ! (or mmk) OpenVMS
+ $ nmake # Windows
+
+This will build the OpenSSL libraries (`libcrypto.a` and `libssl.a` on
+Unix, corresponding on other platforms) and the OpenSSL binary
+(`openssl`). The libraries will be built in the top-level directory,
+and the binary will be in the `apps/` subdirectory.
+
+If the build fails, take a look at the [Build Failures](#build-failures)
+subsection of the [Troubleshooting](#troubleshooting) section.
+
+Test OpenSSL
+------------
+
+After a successful build, and before installing, the libraries should
+be tested. Run:
+
+ $ make test # Unix
+ $ mms test ! OpenVMS
+ $ nmake test # Windows
+
+**Warning:** you MUST run the tests from an unprivileged account (or disable
+your privileges temporarily if your platform allows it).
+
+See [test/README.md](test/README.md) for further details how run tests.
+
+See [test/README-dev.md](test/README-dev.md) for guidelines on adding tests.
+
+Install OpenSSL
+---------------
+
+If everything tests ok, install OpenSSL with
+
+ $ make install # Unix
+ $ mms install ! OpenVMS
+ $ nmake install # Windows
+
+Note that in order to perform the install step above you need to have
+appropriate permissions to write to the installation directory.
+
+The above commands will install all the software components in this
+directory tree under `<PREFIX>` (the directory given with `--prefix` or
+its default):
+
+### Unix / Linux / macOS
+
+ bin/ Contains the openssl binary and a few other
+ utility scripts.
+ include/openssl
+ Contains the header files needed if you want
+ to build your own programs that use libcrypto
+ or libssl.
+ lib Contains the OpenSSL library files.
+ lib/engines Contains the OpenSSL dynamically loadable engines.
+
+ share/man/man1 Contains the OpenSSL command line man-pages.
+ share/man/man3 Contains the OpenSSL library calls man-pages.
+ share/man/man5 Contains the OpenSSL configuration format man-pages.
+ share/man/man7 Contains the OpenSSL other misc man-pages.
+
+ share/doc/openssl/html/man1
+ share/doc/openssl/html/man3
+ share/doc/openssl/html/man5
+ share/doc/openssl/html/man7
+ Contains the HTML rendition of the man-pages.
+
+### OpenVMS
+
+'arch' is replaced with the architecture name, `ALPHA` or `IA64`,
+'sover' is replaced with the shared library version (`0101` for 1.1), and
+'pz' is replaced with the pointer size OpenSSL was built with:
+
+ [.EXE.'arch'] Contains the openssl binary.
+ [.EXE] Contains a few utility scripts.
+ [.include.openssl]
+ Contains the header files needed if you want
+ to build your own programs that use libcrypto
+ or libssl.
+ [.LIB.'arch'] Contains the OpenSSL library files.
+ [.ENGINES'sover''pz'.'arch']
+ Contains the OpenSSL dynamically loadable engines.
+ [.SYS$STARTUP] Contains startup, login and shutdown scripts.
+ These define appropriate logical names and
+ command symbols.
+ [.SYSTEST] Contains the installation verification procedure.
+ [.HTML] Contains the HTML rendition of the manual pages.
+
+### Additional Directories
+
+Additionally, install will add the following directories under
+OPENSSLDIR (the directory given with `--openssldir` or its default)
+for you convenience:
+
+ certs Initially empty, this is the default location
+ for certificate files.
+ private Initially empty, this is the default location
+ for private key files.
+ misc Various scripts.
+
+The installation directory should be appropriately protected to ensure
+unprivileged users cannot make changes to OpenSSL binaries or files, or
+install engines. If you already have a pre-installed version of OpenSSL as
+part of your Operating System it is recommended that you do not overwrite
+the system version and instead install to somewhere else.
+
+Package builders who want to configure the library for standard locations,
+but have the package installed somewhere else so that it can easily be
+packaged, can use
+
+ $ make DESTDIR=/tmp/package-root install # Unix
+ $ mms/macro="DESTDIR=TMP:[PACKAGE-ROOT]" install ! OpenVMS
+
+The specified destination directory will be prepended to all installation
+target paths.
+
+Compatibility issues with previous OpenSSL versions
+---------------------------------------------------
+
+### COMPILING existing applications
+
+Starting with version 1.1.0, OpenSSL hides a number of structures that were
+previously open. This includes all internal libssl structures and a number
+of EVP types. Accessor functions have been added to allow controlled access
+to the structures' data.
+
+This means that some software needs to be rewritten to adapt to the new ways
+of doing things. This often amounts to allocating an instance of a structure
+explicitly where you could previously allocate them on the stack as automatic
+variables, and using the provided accessor functions where you would previously
+access a structure's field directly.
+
+Some APIs have changed as well. However, older APIs have been preserved when
+possible.
+
+Post-installation Notes
+-----------------------
+
+With the default OpenSSL installation comes a FIPS provider module, which
+needs some post-installation attention, without which it will not be usable.
+This involves using the following command:
+
+ $ openssl fipsinstall
+
+See the openssl-fipsinstall(1) manual for details and examples.
+
+Advanced Build Options
+======================
+
+Environment Variables
+---------------------
+
+A number of environment variables can be used to provide additional control
+over the build process. Typically these should be defined prior to running
+`Configure`. Not all environment variables are relevant to all platforms.
+
+ AR
+ The name of the ar executable to use.
+
+ BUILDFILE
+ Use a different build file name than the platform default
+ ("Makefile" on Unix-like platforms, "makefile" on native Windows,
+ "descrip.mms" on OpenVMS). This requires that there is a
+ corresponding build file template.
+ See [Configurations/README.md](Configurations/README.md)
+ for further information.
+
+ CC
+ The compiler to use. Configure will attempt to pick a default
+ compiler for your platform but this choice can be overridden
+ using this variable. Set it to the compiler executable you wish
+ to use, e.g. gcc or clang.
+
+ CROSS_COMPILE
+ This environment variable has the same meaning as for the
+ "--cross-compile-prefix" Configure flag described above. If both
+ are set then the Configure flag takes precedence.
+
+ HASHBANGPERL
+ The command string for the Perl executable to insert in the
+ #! line of perl scripts that will be publicly installed.
+ Default: /usr/bin/env perl
+ Note: the value of this variable is added to the same scripts
+ on all platforms, but it's only relevant on Unix-like platforms.
+
+ KERNEL_BITS
+ This can be the value `32` or `64` to specify the architecture
+ when it is not "obvious" to the configuration. It should generally
+ not be necessary to specify this environment variable.
+
+ NM
+ The name of the nm executable to use.
+
+ OPENSSL_LOCAL_CONFIG_DIR
+ OpenSSL comes with a database of information about how it
+ should be built on different platforms as well as build file
+ templates for those platforms. The database is comprised of
+ ".conf" files in the Configurations directory. The build
+ file templates reside there as well as ".tmpl" files. See the
+ file [Configurations/README.md](Configurations/README.md)
+ for further information about the format of ".conf" files
+ as well as information on the ".tmpl" files.
+ In addition to the standard ".conf" and ".tmpl" files, it is
+ possible to create your own ".conf" and ".tmpl" files and
+ store them locally, outside the OpenSSL source tree.
+ This environment variable can be set to the directory where
+ these files are held and will be considered by Configure
+ before it looks in the standard directories.
+
+ PERL
+ The name of the Perl executable to use when building OpenSSL.
+ Only needed if builing should use a different Perl executable
+ than what is used to run the Configure script.
+
+ RANLIB
+ The name of the ranlib executable to use.
+
+ RC
+ The name of the rc executable to use. The default will be as
+ defined for the target platform in the ".conf" file. If not
+ defined then "windres" will be used. The WINDRES environment
+ variable is synonymous to this. If both are defined then RC
+ takes precedence.
+
+ WINDRES
+ See RC.
+
+Makefile Targets
+----------------
+
+The `Configure` script generates a Makefile in a format relevant to the specific
+platform. The Makefiles provide a number of targets that can be used. Not all
+targets may be available on all platforms. Only the most common targets are
+described here. Examine the Makefiles themselves for the full list.
+
+ all
+ The target to build all the software components and
+ documentation.
+
+ build_sw
+ Build all the software components.
+ THIS IS THE DEFAULT TARGET.
+
+ build_docs
+ Build all documentation components.
+
+ clean
+ Remove all build artefacts and return the directory to a "clean"
+ state.
+
+ depend
+ Rebuild the dependencies in the Makefiles. This is a legacy
+ option that no longer needs to be used since OpenSSL 1.1.0.
+
+ install
+ Install all OpenSSL components.
+
+ install_sw
+ Only install the OpenSSL software components.
+
+ install_docs
+ Only install the OpenSSL documentation components.
+
+ install_man_docs
+ Only install the OpenSSL man pages (Unix only).
+
+ install_html_docs
+ Only install the OpenSSL HTML documentation.
+
+ install_fips
+ Install the FIPS provider module configuration file.
+
+ list-tests
+ Prints a list of all the self test names.
+
+ test
+ Build and run the OpenSSL self tests.
+
+ uninstall
+ Uninstall all OpenSSL components.
+
+ reconfigure
+ reconf
+ Re-run the configuration process, as exactly as the last time
+ as possible.
+
+ update
+ This is a developer option. If you are developing a patch for
+ OpenSSL you may need to use this if you want to update
+ automatically generated files; add new error codes or add new
+ (or change the visibility of) public API functions. (Unix only).
+
+Running Selected Tests
+----------------------
+
+You can specify a set of tests to be performed
+using the `make` variable `TESTS`.
+
+See the section [Running Selected Tests of
+test/README.md](test/README.md#running-selected-tests).
+
+Troubleshooting
+===============
+
+Configuration Problems
+----------------------
+
+### Selecting the correct target
+
+The `./Configure` script tries hard to guess your operating system, but in some
+cases it does not succeed. You will see a message like the following:
+
+ $ ./Configure
+ Operating system: x86-whatever-minix
+ This system (minix) is not supported. See file INSTALL.md for details.
+
+Even if the automatic target selection by the `./Configure` script fails,
+chances are that you still might find a suitable target in the `Configurations`
+directory, which you can supply to the `./Configure` command,
+possibly after some adjustment.
+
+The `Configurations/` directory contains a lot of examples of such targets.
+The main configuration file is [10-main.conf], which contains all targets that
+are officially supported by the OpenSSL team. Other configuration files contain
+targets contributed by other OpenSSL users. The list of targets can be found in
+a Perl list `my %targets = ( ... )`.
+
+ my %targets = (
+ ...
+ "target-name" => {
+ inherit_from => [ "base-target" ],
+ CC => "...",
+ cflags => add("..."),
+ asm_arch => '...',
+ perlasm_scheme => "...",
+ },
+ ...
+ )
+
+If you call `./Configure` without arguments, it will give you a list of all
+known targets. Using `grep`, you can lookup the target definition in the
+`Configurations/` directory. For example the `android-x86_64` can be found in
+[Configurations/15-android.conf](Configurations/15-android.conf).
+
+The directory contains two README files, which explain the general syntax and
+design of the configuration files.
+
+ - [Configurations/README.md](Configurations/README.md)
+ - [Configurations/README-design.md](Configurations/README-design.md)
+
+If you need further help, try to search the [openssl-users] mailing list
+or the [GitHub Issues] for existing solutions. If you don't find anything,
+you can [raise an issue] to ask a question yourself.
+
+More about our support resources can be found in the [SUPPORT] file.
+
+### Configuration Errors
+
+If the `./Configure` or `./Configure` command fails with an error message,
+read the error message carefully and try to figure out whether you made
+a mistake (e.g., by providing a wrong option), or whether the script is
+working incorrectly. If you think you encountered a bug, please
+[raise an issue] on GitHub to file a bug report.
+
+Along with a short description of the bug, please provide the complete
+configure command line and the relevant output including the error message.
+
+Note: To make the output readable, pleace add a 'code fence' (three backquotes
+` ``` ` on a separate line) before and after your output:
+
+ ```
+ ./Configure [your arguments...]
+
+ [output...]
+
+ ```
+
+Build Failures
+--------------
+
+If the build fails, look carefully at the output. Try to locate and understand
+the error message. It might be that the compiler is already telling you
+exactly what you need to do to fix your problem.
+
+There may be reasons for the failure that aren't problems in OpenSSL itself,
+for example if the compiler reports missing standard or third party headers.
+
+If the build succeeded previously, but fails after a source or configuration
+change, it might be helpful to clean the build tree before attempting another
+build. Use this command:
+
+ $ make clean # Unix
+ $ mms clean ! (or mmk) OpenVMS
+ $ nmake clean # Windows
+
+Assembler error messages can sometimes be sidestepped by using the `no-asm`
+configuration option. See also [notes](#notes-on-assembler-modules-compilation).
+
+Compiling parts of OpenSSL with gcc and others with the system compiler will
+result in unresolved symbols on some systems.
+
+If you are still having problems, try to search the [openssl-users] mailing
+list or the [GitHub Issues] for existing solutions. If you think you
+encountered an OpenSSL bug, please [raise an issue] to file a bug report.
+Please take the time to review the existing issues first; maybe the bug was
+already reported or has already been fixed.
+
+Test Failures
+-------------
+
+If some tests fail, look at the output. There may be reasons for the failure
+that isn't a problem in OpenSSL itself (like an OS malfunction or a Perl issue).
+
+You may want increased verbosity, that can be accomplished as described in
+section [Test Failures of test/README.md](test/README.md#test-failures).
+
+You may also want to selectively specify which test(s) to perform. This can be
+done using the `make` variable `TESTS` as described in section [Running
+Selected Tests of test/README.md](test/README.md#running-selected-tests).
+
+If you find a problem with OpenSSL itself, try removing any
+compiler optimization flags from the `CFLAGS` line in the Makefile and
+run `make clean; make` or corresponding.
+
+To report a bug please open an issue on GitHub, at
+<https://github.com/openssl/openssl/issues>.
+
+Notes
+=====
+
+Notes on multi-threading
+------------------------
+
+For some systems, the OpenSSL `Configure` script knows what compiler options
+are needed to generate a library that is suitable for multi-threaded
+applications. On these systems, support for multi-threading is enabled
+by default; use the `no-threads` option to disable (this should never be
+necessary).
+
+On other systems, to enable support for multi-threading, you will have
+to specify at least two options: `threads`, and a system-dependent option.
+(The latter is `-D_REENTRANT` on various systems.) The default in this
+case, obviously, is not to include support for multi-threading (but
+you can still use `no-threads` to suppress an annoying warning message
+from the `Configure` script.)
+
+OpenSSL provides built-in support for two threading models: pthreads (found on
+most UNIX/Linux systems), and Windows threads. No other threading models are
+supported. If your platform does not provide pthreads or Windows threads then
+you should use `Configure` with the `no-threads` option.
+
+For pthreads, all locks are non-recursive. In addition, in a debug build,
+the mutex attribute `PTHREAD_MUTEX_ERRORCHECK` is used. If this is not
+available on your platform, you might have to add
+`-DOPENSSL_NO_MUTEX_ERRORCHECK` to your `Configure` invocation.
+(On Linux `PTHREAD_MUTEX_ERRORCHECK` is an enum value, so a built-in
+ifdef test cannot be used.)
+
+Notes on shared libraries
+-------------------------
+
+For most systems the OpenSSL `Configure` script knows what is needed to
+build shared libraries for libcrypto and libssl. On these systems
+the shared libraries will be created by default. This can be suppressed and
+only static libraries created by using the `no-shared` option. On systems
+where OpenSSL does not know how to build shared libraries the `no-shared`
+option will be forced and only static libraries will be created.
+
+Shared libraries are named a little differently on different platforms.
+One way or another, they all have the major OpenSSL version number as
+part of the file name, i.e. for OpenSSL 1.1.x, `1.1` is somehow part of
+the name.
+
+On most POSIX platforms, shared libraries are named `libcrypto.so.1.1`
+and `libssl.so.1.1`.
+
+on Cygwin, shared libraries are named `cygcrypto-1.1.dll` and `cygssl-1.1.dll`
+with import libraries `libcrypto.dll.a` and `libssl.dll.a`.
+
+On Windows build with MSVC or using MingW, shared libraries are named
+`libcrypto-1_1.dll` and `libssl-1_1.dll` for 32-bit Windows,
+`libcrypto-1_1-x64.dll` and `libssl-1_1-x64.dll` for 64-bit x86_64 Windows,
+and `libcrypto-1_1-ia64.dll` and `libssl-1_1-ia64.dll` for IA64 Windows.
+With MSVC, the import libraries are named `libcrypto.lib` and `libssl.lib`,
+while with MingW, they are named `libcrypto.dll.a` and `libssl.dll.a`.
+
+On VMS, shareable images (VMS speak for shared libraries) are named
+`ossl$libcrypto0101_shr.exe` and `ossl$libssl0101_shr.exe`. However, when
+OpenSSL is specifically built for 32-bit pointers, the shareable images
+are named `ossl$libcrypto0101_shr32.exe` and `ossl$libssl0101_shr32.exe`
+instead, and when built for 64-bit pointers, they are named
+`ossl$libcrypto0101_shr64.exe` and `ossl$libssl0101_shr64.exe`.
+
+Notes on random number generation
+---------------------------------
+
+Availability of cryptographically secure random numbers is required for
+secret key generation. OpenSSL provides several options to seed the
+internal CSPRNG. If not properly seeded, the internal CSPRNG will refuse
+to deliver random bytes and a "PRNG not seeded error" will occur.
+
+The seeding method can be configured using the `--with-rand-seed` option,
+which can be used to specify a comma separated list of seed methods.
+However, in most cases OpenSSL will choose a suitable default method,
+so it is not necessary to explicitly provide this option. Note also
+that not all methods are available on all platforms. The FIPS provider will
+silently ignore seed sources that were not validated.
+
+I) On operating systems which provide a suitable randomness source (in
+form of a system call or system device), OpenSSL will use the optimal
+available method to seed the CSPRNG from the operating system's
+randomness sources. This corresponds to the option `--with-rand-seed=os`.
+
+II) On systems without such a suitable randomness source, automatic seeding
+and reseeding is disabled (`--with-rand-seed=none`) and it may be necessary
+to install additional support software to obtain a random seed and reseed
+the CSPRNG manually. Please check out the manual pages for `RAND_add()`,
+`RAND_bytes()`, `RAND_egd()`, and the FAQ for more information.
+
+Notes on assembler modules compilation
+--------------------------------------
+
+Compilation of some code paths in assembler modules might depend on whether the
+current assembler version supports certain ISA extensions or not. Code paths
+that use the AES-NI, PCLMULQDQ, SSSE3, and SHA extensions are always assembled.
+Apart from that, the minimum requirements for the assembler versions are shown
+in the table below:
+
+| ISA extension | GNU as | nasm | llvm |
+|---------------|--------|--------|---------|
+| AVX | 2.19 | 2.09 | 3.0 |
+| AVX2 | 2.22 | 2.10 | 3.1 |
+| ADCX/ADOX | 2.23 | 2.10 | 3.3 |
+| AVX512 | 2.25 | 2.11.8 | 3.6 (*) |
+| AVX512IFMA | 2.26 | 2.11.8 | 6.0 (*) |
+| VAES | 2.30 | 2.13.3 | 6.0 (*) |
+
+---
+
+(*) Even though AVX512 support was implemented in llvm 3.6, prior to version 7.0
+an explicit -march flag was apparently required to compile assembly modules. But
+then the compiler generates processor-specific code, which in turn contradicts
+the idea of performing dispatch at run-time, which is facilitated by the special
+variable `OPENSSL_ia32cap`. For versions older than 7.0, it is possible to work
+around the problem by forcing the build procedure to use the following script:
+
+ #!/bin/sh
+ exec clang -no-integrated-as "$@"
+
+instead of the real clang. In which case it doesn't matter what clang version
+is used, as it is the version of the GNU assembler that will be checked.
+
+---
+
+<!-- Links -->
+
+[openssl-users]:
+ <https://mta.openssl.org/mailman/listinfo/openssl-users>
+
+[SUPPORT]:
+ ./SUPPORT.md
+
+[GitHub Issues]:
+ <https://github.com/openssl/openssl/issues>
+
+[raise an issue]:
+ <https://github.com/openssl/openssl/issues/new/choose>
+
+[10-main.conf]:
+ Configurations/10-main.conf
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 9601ab43575f..000000000000
--- a/LICENSE
+++ /dev/null
@@ -1,125 +0,0 @@
-
- LICENSE ISSUES
- ==============
-
- The OpenSSL toolkit stays under a double license, i.e. both the conditions of
- the OpenSSL License and the original SSLeay license apply to the toolkit.
- See below for the actual license texts.
-
- OpenSSL License
- ---------------
-
-/* ====================================================================
- * Copyright (c) 1998-2019 The OpenSSL Project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission. For written permission, please contact
- * openssl-core@openssl.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- * nor may "OpenSSL" appear in their names without prior written
- * permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com). This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
- *
- */
-
- Original SSLeay License
- -----------------------
-
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to. The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code. The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * "This product includes cryptographic software written by
- * Eric Young (eay@cryptsoft.com)"
- * The word 'cryptographic' can be left out if the rouines from the library
- * being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- * the apps directory (application code) you must include an acknowledgement:
- * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed. i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 000000000000..49cc83d2ee29
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,177 @@
+
+ Apache License
+ Version 2.0, January 2004
+ https://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
diff --git a/NEWS b/NEWS
deleted file mode 100644
index 2724fc4d85ba..000000000000
--- a/NEWS
+++ /dev/null
@@ -1,1045 +0,0 @@
-
- NEWS
- ====
-
- This file gives a brief overview of the major changes between each OpenSSL
- release. For more details please read the CHANGES file.
-
- Major changes between OpenSSL 1.1.1s and OpenSSL 1.1.1t [7 Feb 2023]
-
- o Fixed X.400 address type confusion in X.509 GeneralName (CVE-2023-0286)
- o Fixed Use-after-free following BIO_new_NDEF (CVE-2023-0215)
- o Fixed Double free after calling PEM_read_bio_ex (CVE-2022-4450)
- o Fixed Timing Oracle in RSA Decryption (CVE-2022-4304)
-
- Major changes between OpenSSL 1.1.1r and OpenSSL 1.1.1s [1 Nov 2022]
-
- o Fixed a regression introduced in OpenSSL 1.1.1r not refreshing the
- certificate data to be signed before signing the certificate.
-
- Major changes between OpenSSL 1.1.1q and OpenSSL 1.1.1r [11 Oct 2022]
-
- o Added a missing header for memcmp that caused compilation failure on
- some platforms
-
- Major changes between OpenSSL 1.1.1p and OpenSSL 1.1.1q [5 Jul 2022]
-
- o Fixed AES OCB failure to encrypt some bytes on 32-bit x86 platforms
- (CVE-2022-2097)
-
- Major changes between OpenSSL 1.1.1o and OpenSSL 1.1.1p [21 Jun 2022]
-
- o Fixed additional bugs in the c_rehash script which was not properly
- sanitising shell metacharacters to prevent command injection
- (CVE-2022-2068)
-
- Major changes between OpenSSL 1.1.1n and OpenSSL 1.1.1o [3 May 2022]
-
- o Fixed a bug in the c_rehash script which was not properly sanitising
- shell metacharacters to prevent command injection (CVE-2022-1292)
-
- Major changes between OpenSSL 1.1.1m and OpenSSL 1.1.1n [15 Mar 2022]
-
- o Fixed a bug in the BN_mod_sqrt() function that can cause it to loop
- forever for non-prime moduli (CVE-2022-0778)
-
- Major changes between OpenSSL 1.1.1l and OpenSSL 1.1.1m [14 Dec 2021]
-
- o None
-
- Major changes between OpenSSL 1.1.1k and OpenSSL 1.1.1l [24 Aug 2021]
-
- o Fixed an SM2 Decryption Buffer Overflow (CVE-2021-3711)
- o Fixed various read buffer overruns processing ASN.1 strings (CVE-2021-3712)
-
- Major changes between OpenSSL 1.1.1j and OpenSSL 1.1.1k [25 Mar 2021]
-
- o Fixed a problem with verifying a certificate chain when using the
- X509_V_FLAG_X509_STRICT flag (CVE-2021-3450)
- o Fixed an issue where an OpenSSL TLS server may crash if sent a
- maliciously crafted renegotiation ClientHello message from a client
- (CVE-2021-3449)
-
- Major changes between OpenSSL 1.1.1i and OpenSSL 1.1.1j [16 Feb 2021]
-
- o Fixed a NULL pointer deref in the X509_issuer_and_serial_hash()
- function (CVE-2021-23841)
- o Fixed the RSA_padding_check_SSLv23() function and the RSA_SSLV23_PADDING
- padding mode to correctly check for rollback attacks
- o Fixed an overflow in the EVP_CipherUpdate, EVP_EncryptUpdate and
- EVP_DecryptUpdate functions (CVE-2021-23840)
- o Fixed SRP_Calc_client_key so that it runs in constant time
-
- Major changes between OpenSSL 1.1.1h and OpenSSL 1.1.1i [8 Dec 2020]
-
- o Fixed NULL pointer deref in GENERAL_NAME_cmp (CVE-2020-1971)
-
- Major changes between OpenSSL 1.1.1g and OpenSSL 1.1.1h [22 Sep 2020]
-
- o Disallow explicit curve parameters in verifications chains when
- X509_V_FLAG_X509_STRICT is used
- o Enable 'MinProtocol' and 'MaxProtocol' to configure both TLS and DTLS
- contexts
- o Oracle Developer Studio will start reporting deprecation warnings
-
- Major changes between OpenSSL 1.1.1f and OpenSSL 1.1.1g [21 Apr 2020]
-
- o Fixed segmentation fault in SSL_check_chain() (CVE-2020-1967)
-
- Major changes between OpenSSL 1.1.1e and OpenSSL 1.1.1f [31 Mar 2020]
-
- o Revert the unexpected EOF reporting via SSL_ERROR_SSL
-
- Major changes between OpenSSL 1.1.1d and OpenSSL 1.1.1e [17 Mar 2020]
-
- o Fixed an overflow bug in the x64_64 Montgomery squaring procedure
- used in exponentiation with 512-bit moduli (CVE-2019-1551)
- o Properly detect unexpected EOF while reading in libssl and report
- it via SSL_ERROR_SSL
-
- Major changes between OpenSSL 1.1.1c and OpenSSL 1.1.1d [10 Sep 2019]
-
- o Fixed a fork protection issue (CVE-2019-1549)
- o Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey
- (CVE-2019-1563)
- o For built-in EC curves, ensure an EC_GROUP built from the curve name is
- used even when parsing explicit parameters
- o Compute ECC cofactors if not provided during EC_GROUP construction
- (CVE-2019-1547)
- o Early start up entropy quality from the DEVRANDOM seed source has been
- improved for older Linux systems
- o Correct the extended master secret constant on EBCDIC systems
- o Use Windows installation paths in the mingw builds (CVE-2019-1552)
- o Changed DH_check to accept parameters with order q and 2q subgroups
- o Significantly reduce secure memory usage by the randomness pools
- o Revert the DEVRANDOM_WAIT feature for Linux systems
-
- Major changes between OpenSSL 1.1.1b and OpenSSL 1.1.1c [28 May 2019]
-
- o Prevent over long nonces in ChaCha20-Poly1305 (CVE-2019-1543)
-
- Major changes between OpenSSL 1.1.1a and OpenSSL 1.1.1b [26 Feb 2019]
-
- o Change the info callback signals for the start and end of a post-handshake
- message exchange in TLSv1.3.
- o Fix a bug in DTLS over SCTP. This breaks interoperability with older versions
- of OpenSSL like OpenSSL 1.1.0 and OpenSSL 1.0.2.
-
- Major changes between OpenSSL 1.1.1 and OpenSSL 1.1.1a [20 Nov 2018]
-
- o Timing vulnerability in DSA signature generation (CVE-2018-0734)
- o Timing vulnerability in ECDSA signature generation (CVE-2018-0735)
-
- Major changes between OpenSSL 1.1.0i and OpenSSL 1.1.1 [11 Sep 2018]
-
- o Support for TLSv1.3 added (see https://wiki.openssl.org/index.php/TLS1.3
- for further important information). The TLSv1.3 implementation includes:
- o Fully compliant implementation of RFC8446 (TLSv1.3) on by default
- o Early data (0-RTT)
- o Post-handshake authentication and key update
- o Middlebox Compatibility Mode
- o TLSv1.3 PSKs
- o Support for all five RFC8446 ciphersuites
- o RSA-PSS signature algorithms (backported to TLSv1.2)
- o Configurable session ticket support
- o Stateless server support
- o Rewrite of the packet construction code for "safer" packet handling
- o Rewrite of the extension handling code
- o Complete rewrite of the OpenSSL random number generator to introduce the
- following capabilities
- o The default RAND method now utilizes an AES-CTR DRBG according to
- NIST standard SP 800-90Ar1.
- o Support for multiple DRBG instances with seed chaining.
- o There is a public and private DRBG instance.
- o The DRBG instances are fork-safe.
- o Keep all global DRBG instances on the secure heap if it is enabled.
- o The public and private DRBG instance are per thread for lock free
- operation
- o Support for various new cryptographic algorithms including:
- o SHA3
- o SHA512/224 and SHA512/256
- o EdDSA (both Ed25519 and Ed448) including X509 and TLS support
- o X448 (adding to the existing X25519 support in 1.1.0)
- o Multi-prime RSA
- o SM2
- o SM3
- o SM4
- o SipHash
- o ARIA (including TLS support)
- o Significant Side-Channel attack security improvements
- o Add a new ClientHello callback to provide the ability to adjust the SSL
- object at an early stage.
- o Add 'Maximum Fragment Length' TLS extension negotiation and support
- o A new STORE module, which implements a uniform and URI based reader of
- stores that can contain keys, certificates, CRLs and numerous other
- objects.
- o Move the display of configuration data to configdata.pm.
- o Allow GNU style "make variables" to be used with Configure.
- o Claim the namespaces OSSL and OPENSSL, represented as symbol prefixes
- o Rewrite of devcrypto engine
-
- Major changes between OpenSSL 1.1.0h and OpenSSL 1.1.0i [under development]
-
- o Client DoS due to large DH parameter (CVE-2018-0732)
- o Cache timing vulnerability in RSA Key Generation (CVE-2018-0737)
-
- Major changes between OpenSSL 1.1.0g and OpenSSL 1.1.0h [under development]
-
- o Constructed ASN.1 types with a recursive definition could exceed the
- stack (CVE-2018-0739)
- o Incorrect CRYPTO_memcmp on HP-UX PA-RISC (CVE-2018-0733)
- o rsaz_1024_mul_avx2 overflow bug on x86_64 (CVE-2017-3738)
-
- Major changes between OpenSSL 1.1.0f and OpenSSL 1.1.0g [2 Nov 2017]
-
- o bn_sqrx8x_internal carry bug on x86_64 (CVE-2017-3736)
- o Malformed X.509 IPAddressFamily could cause OOB read (CVE-2017-3735)
-
- Major changes between OpenSSL 1.1.0e and OpenSSL 1.1.0f [25 May 2017]
-
- o config now recognises 64-bit mingw and chooses mingw64 instead of mingw
-
- Major changes between OpenSSL 1.1.0d and OpenSSL 1.1.0e [16 Feb 2017]
-
- o Encrypt-Then-Mac renegotiation crash (CVE-2017-3733)
-
- Major changes between OpenSSL 1.1.0c and OpenSSL 1.1.0d [26 Jan 2017]
-
- o Truncated packet could crash via OOB read (CVE-2017-3731)
- o Bad (EC)DHE parameters cause a client crash (CVE-2017-3730)
- o BN_mod_exp may produce incorrect results on x86_64 (CVE-2017-3732)
-
- Major changes between OpenSSL 1.1.0b and OpenSSL 1.1.0c [10 Nov 2016]
-
- o ChaCha20/Poly1305 heap-buffer-overflow (CVE-2016-7054)
- o CMS Null dereference (CVE-2016-7053)
- o Montgomery multiplication may produce incorrect results (CVE-2016-7055)
-
- Major changes between OpenSSL 1.1.0a and OpenSSL 1.1.0b [26 Sep 2016]
-
- o Fix Use After Free for large message sizes (CVE-2016-6309)
-
- Major changes between OpenSSL 1.1.0 and OpenSSL 1.1.0a [22 Sep 2016]
-
- o OCSP Status Request extension unbounded memory growth (CVE-2016-6304)
- o SSL_peek() hang on empty record (CVE-2016-6305)
- o Excessive allocation of memory in tls_get_message_header()
- (CVE-2016-6307)
- o Excessive allocation of memory in dtls1_preprocess_fragment()
- (CVE-2016-6308)
-
- Major changes between OpenSSL 1.0.2h and OpenSSL 1.1.0 [25 Aug 2016]
-
- o Copyright text was shrunk to a boilerplate that points to the license
- o "shared" builds are now the default when possible
- o Added support for "pipelining"
- o Added the AFALG engine
- o New threading API implemented
- o Support for ChaCha20 and Poly1305 added to libcrypto and libssl
- o Support for extended master secret
- o CCM ciphersuites
- o Reworked test suite, now based on perl, Test::Harness and Test::More
- o *Most* libcrypto and libssl public structures were made opaque,
- including:
- BIGNUM and associated types, EC_KEY and EC_KEY_METHOD,
- DH and DH_METHOD, DSA and DSA_METHOD, RSA and RSA_METHOD,
- BIO and BIO_METHOD, EVP_MD_CTX, EVP_MD, EVP_CIPHER_CTX,
- EVP_CIPHER, EVP_PKEY and associated types, HMAC_CTX,
- X509, X509_CRL, X509_OBJECT, X509_STORE_CTX, X509_STORE,
- X509_LOOKUP, X509_LOOKUP_METHOD
- o libssl internal structures made opaque
- o SSLv2 support removed
- o Kerberos ciphersuite support removed
- o RC4 removed from DEFAULT ciphersuites in libssl
- o 40 and 56 bit cipher support removed from libssl
- o All public header files moved to include/openssl, no more symlinking
- o SSL/TLS state machine, version negotiation and record layer rewritten
- o EC revision: now operations use new EC_KEY_METHOD.
- o Support for OCB mode added to libcrypto
- o Support for asynchronous crypto operations added to libcrypto and libssl
- o Deprecated interfaces can now be disabled at build time either
- relative to the latest release via the "no-deprecated" Configure
- argument, or via the "--api=1.1.0|1.0.0|0.9.8" option.
- o Application software can be compiled with -DOPENSSL_API_COMPAT=version
- to ensure that features deprecated in that version are not exposed.
- o Support for RFC6698/RFC7671 DANE TLSA peer authentication
- o Change of Configure to use --prefix as the main installation
- directory location rather than --openssldir. The latter becomes
- the directory for certs, private key and openssl.cnf exclusively.
- o Reworked BIO networking library, with full support for IPv6.
- o New "unified" build system
- o New security levels
- o Support for scrypt algorithm
- o Support for X25519
- o Extended SSL_CONF support using configuration files
- o KDF algorithm support. Implement TLS PRF as a KDF.
- o Support for Certificate Transparency
- o HKDF support.
-
- Major changes between OpenSSL 1.0.2g and OpenSSL 1.0.2h [3 May 2016]
-
- o Prevent padding oracle in AES-NI CBC MAC check (CVE-2016-2107)
- o Fix EVP_EncodeUpdate overflow (CVE-2016-2105)
- o Fix EVP_EncryptUpdate overflow (CVE-2016-2106)
- o Prevent ASN.1 BIO excessive memory allocation (CVE-2016-2109)
- o EBCDIC overread (CVE-2016-2176)
- o Modify behavior of ALPN to invoke callback after SNI/servername
- callback, such that updates to the SSL_CTX affect ALPN.
- o Remove LOW from the DEFAULT cipher list. This removes singles DES from
- the default.
- o Only remove the SSLv2 methods with the no-ssl2-method option.
-
- Major changes between OpenSSL 1.0.2f and OpenSSL 1.0.2g [1 Mar 2016]
-
- o Disable weak ciphers in SSLv3 and up in default builds of OpenSSL.
- o Disable SSLv2 default build, default negotiation and weak ciphers
- (CVE-2016-0800)
- o Fix a double-free in DSA code (CVE-2016-0705)
- o Disable SRP fake user seed to address a server memory leak
- (CVE-2016-0798)
- o Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption
- (CVE-2016-0797)
- o Fix memory issues in BIO_*printf functions (CVE-2016-0799)
- o Fix side channel attack on modular exponentiation (CVE-2016-0702)
-
- Major changes between OpenSSL 1.0.2e and OpenSSL 1.0.2f [28 Jan 2016]
-
- o DH small subgroups (CVE-2016-0701)
- o SSLv2 doesn't block disabled ciphers (CVE-2015-3197)
-
- Major changes between OpenSSL 1.0.2d and OpenSSL 1.0.2e [3 Dec 2015]
-
- o BN_mod_exp may produce incorrect results on x86_64 (CVE-2015-3193)
- o Certificate verify crash with missing PSS parameter (CVE-2015-3194)
- o X509_ATTRIBUTE memory leak (CVE-2015-3195)
- o Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs
- o In DSA_generate_parameters_ex, if the provided seed is too short,
- return an error
-
- Major changes between OpenSSL 1.0.2c and OpenSSL 1.0.2d [9 Jul 2015]
-
- o Alternate chains certificate forgery (CVE-2015-1793)
- o Race condition handling PSK identify hint (CVE-2015-3196)
-
- Major changes between OpenSSL 1.0.2b and OpenSSL 1.0.2c [12 Jun 2015]
-
- o Fix HMAC ABI incompatibility
-
- Major changes between OpenSSL 1.0.2a and OpenSSL 1.0.2b [11 Jun 2015]
-
- o Malformed ECParameters causes infinite loop (CVE-2015-1788)
- o Exploitable out-of-bounds read in X509_cmp_time (CVE-2015-1789)
- o PKCS7 crash with missing EnvelopedContent (CVE-2015-1790)
- o CMS verify infinite loop with unknown hash function (CVE-2015-1792)
- o Race condition handling NewSessionTicket (CVE-2015-1791)
-
- Major changes between OpenSSL 1.0.2 and OpenSSL 1.0.2a [19 Mar 2015]
-
- o OpenSSL 1.0.2 ClientHello sigalgs DoS fix (CVE-2015-0291)
- o Multiblock corrupted pointer fix (CVE-2015-0290)
- o Segmentation fault in DTLSv1_listen fix (CVE-2015-0207)
- o Segmentation fault in ASN1_TYPE_cmp fix (CVE-2015-0286)
- o Segmentation fault for invalid PSS parameters fix (CVE-2015-0208)
- o ASN.1 structure reuse memory corruption fix (CVE-2015-0287)
- o PKCS7 NULL pointer dereferences fix (CVE-2015-0289)
- o DoS via reachable assert in SSLv2 servers fix (CVE-2015-0293)
- o Empty CKE with client auth and DHE fix (CVE-2015-1787)
- o Handshake with unseeded PRNG fix (CVE-2015-0285)
- o Use After Free following d2i_ECPrivatekey error fix (CVE-2015-0209)
- o X509_to_X509_REQ NULL pointer deref fix (CVE-2015-0288)
- o Removed the export ciphers from the DEFAULT ciphers
-
- Major changes between OpenSSL 1.0.1l and OpenSSL 1.0.2 [22 Jan 2015]:
-
- o Suite B support for TLS 1.2 and DTLS 1.2
- o Support for DTLS 1.2
- o TLS automatic EC curve selection.
- o API to set TLS supported signature algorithms and curves
- o SSL_CONF configuration API.
- o TLS Brainpool support.
- o ALPN support.
- o CMS support for RSA-PSS, RSA-OAEP, ECDH and X9.42 DH.
-
- Major changes between OpenSSL 1.0.1k and OpenSSL 1.0.1l [15 Jan 2015]
-
- o Build fixes for the Windows and OpenVMS platforms
-
- Major changes between OpenSSL 1.0.1j and OpenSSL 1.0.1k [8 Jan 2015]
-
- o Fix for CVE-2014-3571
- o Fix for CVE-2015-0206
- o Fix for CVE-2014-3569
- o Fix for CVE-2014-3572
- o Fix for CVE-2015-0204
- o Fix for CVE-2015-0205
- o Fix for CVE-2014-8275
- o Fix for CVE-2014-3570
-
- Major changes between OpenSSL 1.0.1i and OpenSSL 1.0.1j [15 Oct 2014]
-
- o Fix for CVE-2014-3513
- o Fix for CVE-2014-3567
- o Mitigation for CVE-2014-3566 (SSL protocol vulnerability)
- o Fix for CVE-2014-3568
-
- Major changes between OpenSSL 1.0.1h and OpenSSL 1.0.1i [6 Aug 2014]
-
- o Fix for CVE-2014-3512
- o Fix for CVE-2014-3511
- o Fix for CVE-2014-3510
- o Fix for CVE-2014-3507
- o Fix for CVE-2014-3506
- o Fix for CVE-2014-3505
- o Fix for CVE-2014-3509
- o Fix for CVE-2014-5139
- o Fix for CVE-2014-3508
-
- Major changes between OpenSSL 1.0.1g and OpenSSL 1.0.1h [5 Jun 2014]
-
- o Fix for CVE-2014-0224
- o Fix for CVE-2014-0221
- o Fix for CVE-2014-0198
- o Fix for CVE-2014-0195
- o Fix for CVE-2014-3470
- o Fix for CVE-2010-5298
-
- Major changes between OpenSSL 1.0.1f and OpenSSL 1.0.1g [7 Apr 2014]
-
- o Fix for CVE-2014-0160
- o Add TLS padding extension workaround for broken servers.
- o Fix for CVE-2014-0076
-
- Major changes between OpenSSL 1.0.1e and OpenSSL 1.0.1f [6 Jan 2014]
-
- o Don't include gmt_unix_time in TLS server and client random values
- o Fix for TLS record tampering bug CVE-2013-4353
- o Fix for TLS version checking bug CVE-2013-6449
- o Fix for DTLS retransmission bug CVE-2013-6450
-
- Major changes between OpenSSL 1.0.1d and OpenSSL 1.0.1e [11 Feb 2013]:
-
- o Corrected fix for CVE-2013-0169
-
- Major changes between OpenSSL 1.0.1c and OpenSSL 1.0.1d [4 Feb 2013]:
-
- o Fix renegotiation in TLS 1.1, 1.2 by using the correct TLS version.
- o Include the fips configuration module.
- o Fix OCSP bad key DoS attack CVE-2013-0166
- o Fix for SSL/TLS/DTLS CBC plaintext recovery attack CVE-2013-0169
- o Fix for TLS AESNI record handling flaw CVE-2012-2686
-
- Major changes between OpenSSL 1.0.1b and OpenSSL 1.0.1c [10 May 2012]:
-
- o Fix TLS/DTLS record length checking bug CVE-2012-2333
- o Don't attempt to use non-FIPS composite ciphers in FIPS mode.
-
- Major changes between OpenSSL 1.0.1a and OpenSSL 1.0.1b [26 Apr 2012]:
-
- o Fix compilation error on non-x86 platforms.
- o Make FIPS capable OpenSSL ciphers work in non-FIPS mode.
- o Fix SSL_OP_NO_TLSv1_1 clash with SSL_OP_ALL in OpenSSL 1.0.0
-
- Major changes between OpenSSL 1.0.1 and OpenSSL 1.0.1a [19 Apr 2012]:
-
- o Fix for ASN1 overflow bug CVE-2012-2110
- o Workarounds for some servers that hang on long client hellos.
- o Fix SEGV in AES code.
-
- Major changes between OpenSSL 1.0.0h and OpenSSL 1.0.1 [14 Mar 2012]:
-
- o TLS/DTLS heartbeat support.
- o SCTP support.
- o RFC 5705 TLS key material exporter.
- o RFC 5764 DTLS-SRTP negotiation.
- o Next Protocol Negotiation.
- o PSS signatures in certificates, requests and CRLs.
- o Support for password based recipient info for CMS.
- o Support TLS v1.2 and TLS v1.1.
- o Preliminary FIPS capability for unvalidated 2.0 FIPS module.
- o SRP support.
-
- Major changes between OpenSSL 1.0.0g and OpenSSL 1.0.0h [12 Mar 2012]:
-
- o Fix for CMS/PKCS#7 MMA CVE-2012-0884
- o Corrected fix for CVE-2011-4619
- o Various DTLS fixes.
-
- Major changes between OpenSSL 1.0.0f and OpenSSL 1.0.0g [18 Jan 2012]:
-
- o Fix for DTLS DoS issue CVE-2012-0050
-
- Major changes between OpenSSL 1.0.0e and OpenSSL 1.0.0f [4 Jan 2012]:
-
- o Fix for DTLS plaintext recovery attack CVE-2011-4108
- o Clear block padding bytes of SSL 3.0 records CVE-2011-4576
- o Only allow one SGC handshake restart for SSL/TLS CVE-2011-4619
- o Check parameters are not NULL in GOST ENGINE CVE-2012-0027
- o Check for malformed RFC3779 data CVE-2011-4577
-
- Major changes between OpenSSL 1.0.0d and OpenSSL 1.0.0e [6 Sep 2011]:
-
- o Fix for CRL vulnerability issue CVE-2011-3207
- o Fix for ECDH crashes CVE-2011-3210
- o Protection against EC timing attacks.
- o Support ECDH ciphersuites for certificates using SHA2 algorithms.
- o Various DTLS fixes.
-
- Major changes between OpenSSL 1.0.0c and OpenSSL 1.0.0d [8 Feb 2011]:
-
- o Fix for security issue CVE-2011-0014
-
- Major changes between OpenSSL 1.0.0b and OpenSSL 1.0.0c [2 Dec 2010]:
-
- o Fix for security issue CVE-2010-4180
- o Fix for CVE-2010-4252
- o Fix mishandling of absent EC point format extension.
- o Fix various platform compilation issues.
- o Corrected fix for security issue CVE-2010-3864.
-
- Major changes between OpenSSL 1.0.0a and OpenSSL 1.0.0b [16 Nov 2010]:
-
- o Fix for security issue CVE-2010-3864.
- o Fix for CVE-2010-2939
- o Fix WIN32 build system for GOST ENGINE.
-
- Major changes between OpenSSL 1.0.0 and OpenSSL 1.0.0a [1 Jun 2010]:
-
- o Fix for security issue CVE-2010-1633.
- o GOST MAC and CFB fixes.
-
- Major changes between OpenSSL 0.9.8n and OpenSSL 1.0.0 [29 Mar 2010]:
-
- o RFC3280 path validation: sufficient to process PKITS tests.
- o Integrated support for PVK files and keyblobs.
- o Change default private key format to PKCS#8.
- o CMS support: able to process all examples in RFC4134
- o Streaming ASN1 encode support for PKCS#7 and CMS.
- o Multiple signer and signer add support for PKCS#7 and CMS.
- o ASN1 printing support.
- o Whirlpool hash algorithm added.
- o RFC3161 time stamp support.
- o New generalised public key API supporting ENGINE based algorithms.
- o New generalised public key API utilities.
- o New ENGINE supporting GOST algorithms.
- o SSL/TLS GOST ciphersuite support.
- o PKCS#7 and CMS GOST support.
- o RFC4279 PSK ciphersuite support.
- o Supported points format extension for ECC ciphersuites.
- o ecdsa-with-SHA224/256/384/512 signature types.
- o dsa-with-SHA224 and dsa-with-SHA256 signature types.
- o Opaque PRF Input TLS extension support.
- o Updated time routines to avoid OS limitations.
-
- Major changes between OpenSSL 0.9.8m and OpenSSL 0.9.8n [24 Mar 2010]:
-
- o CFB cipher definition fixes.
- o Fix security issues CVE-2010-0740 and CVE-2010-0433.
-
- Major changes between OpenSSL 0.9.8l and OpenSSL 0.9.8m [25 Feb 2010]:
-
- o Cipher definition fixes.
- o Workaround for slow RAND_poll() on some WIN32 versions.
- o Remove MD2 from algorithm tables.
- o SPKAC handling fixes.
- o Support for RFC5746 TLS renegotiation extension.
- o Compression memory leak fixed.
- o Compression session resumption fixed.
- o Ticket and SNI coexistence fixes.
- o Many fixes to DTLS handling.
-
- Major changes between OpenSSL 0.9.8k and OpenSSL 0.9.8l [5 Nov 2009]:
-
- o Temporary work around for CVE-2009-3555: disable renegotiation.
-
- Major changes between OpenSSL 0.9.8j and OpenSSL 0.9.8k [25 Mar 2009]:
-
- o Fix various build issues.
- o Fix security issues (CVE-2009-0590, CVE-2009-0591, CVE-2009-0789)
-
- Major changes between OpenSSL 0.9.8i and OpenSSL 0.9.8j [7 Jan 2009]:
-
- o Fix security issue (CVE-2008-5077)
- o Merge FIPS 140-2 branch code.
-
- Major changes between OpenSSL 0.9.8g and OpenSSL 0.9.8h [28 May 2008]:
-
- o CryptoAPI ENGINE support.
- o Various precautionary measures.
- o Fix for bugs affecting certificate request creation.
- o Support for local machine keyset attribute in PKCS#12 files.
-
- Major changes between OpenSSL 0.9.8f and OpenSSL 0.9.8g [19 Oct 2007]:
-
- o Backport of CMS functionality to 0.9.8.
- o Fixes for bugs introduced with 0.9.8f.
-
- Major changes between OpenSSL 0.9.8e and OpenSSL 0.9.8f [11 Oct 2007]:
-
- o Add gcc 4.2 support.
- o Add support for AES and SSE2 assembly language optimization
- for VC++ build.
- o Support for RFC4507bis and server name extensions if explicitly
- selected at compile time.
- o DTLS improvements.
- o RFC4507bis support.
- o TLS Extensions support.
-
- Major changes between OpenSSL 0.9.8d and OpenSSL 0.9.8e [23 Feb 2007]:
-
- o Various ciphersuite selection fixes.
- o RFC3779 support.
-
- Major changes between OpenSSL 0.9.8c and OpenSSL 0.9.8d [28 Sep 2006]:
-
- o Introduce limits to prevent malicious key DoS (CVE-2006-2940)
- o Fix security issues (CVE-2006-2937, CVE-2006-3737, CVE-2006-4343)
- o Changes to ciphersuite selection algorithm
-
- Major changes between OpenSSL 0.9.8b and OpenSSL 0.9.8c [5 Sep 2006]:
-
- o Fix Daniel Bleichenbacher forged signature attack, CVE-2006-4339
- o New cipher Camellia
-
- Major changes between OpenSSL 0.9.8a and OpenSSL 0.9.8b [4 May 2006]:
-
- o Cipher string fixes.
- o Fixes for VC++ 2005.
- o Updated ECC cipher suite support.
- o New functions EVP_CIPHER_CTX_new() and EVP_CIPHER_CTX_free().
- o Zlib compression usage fixes.
- o Built in dynamic engine compilation support on Win32.
- o Fixes auto dynamic engine loading in Win32.
-
- Major changes between OpenSSL 0.9.8 and OpenSSL 0.9.8a [11 Oct 2005]:
-
- o Fix potential SSL 2.0 rollback, CVE-2005-2969
- o Extended Windows CE support
-
- Major changes between OpenSSL 0.9.7g and OpenSSL 0.9.8 [5 Jul 2005]:
-
- o Major work on the BIGNUM library for higher efficiency and to
- make operations more streamlined and less contradictory. This
- is the result of a major audit of the BIGNUM library.
- o Addition of BIGNUM functions for fields GF(2^m) and NIST
- curves, to support the Elliptic Crypto functions.
- o Major work on Elliptic Crypto; ECDH and ECDSA added, including
- the use through EVP, X509 and ENGINE.
- o New ASN.1 mini-compiler that's usable through the OpenSSL
- configuration file.
- o Added support for ASN.1 indefinite length constructed encoding.
- o New PKCS#12 'medium level' API to manipulate PKCS#12 files.
- o Complete rework of shared library construction and linking
- programs with shared or static libraries, through a separate
- Makefile.shared.
- o Rework of the passing of parameters from one Makefile to another.
- o Changed ENGINE framework to load dynamic engine modules
- automatically from specifically given directories.
- o New structure and ASN.1 functions for CertificatePair.
- o Changed the ZLIB compression method to be stateful.
- o Changed the key-generation and primality testing "progress"
- mechanism to take a structure that contains the ticker
- function and an argument.
- o New engine module: GMP (performs private key exponentiation).
- o New engine module: VIA PadLOck ACE extension in VIA C3
- Nehemiah processors.
- o Added support for IPv6 addresses in certificate extensions.
- See RFC 1884, section 2.2.
- o Added support for certificate policy mappings, policy
- constraints and name constraints.
- o Added support for multi-valued AVAs in the OpenSSL
- configuration file.
- o Added support for multiple certificates with the same subject
- in the 'openssl ca' index file.
- o Make it possible to create self-signed certificates using
- 'openssl ca -selfsign'.
- o Make it possible to generate a serial number file with
- 'openssl ca -create_serial'.
- o New binary search functions with extended functionality.
- o New BUF functions.
- o New STORE structure and library to provide an interface to all
- sorts of data repositories. Supports storage of public and
- private keys, certificates, CRLs, numbers and arbitrary blobs.
- This library is unfortunately unfinished and unused within
- OpenSSL.
- o New control functions for the error stack.
- o Changed the PKCS#7 library to support one-pass S/MIME
- processing.
- o Added the possibility to compile without old deprecated
- functionality with the OPENSSL_NO_DEPRECATED macro or the
- 'no-deprecated' argument to the config and Configure scripts.
- o Constification of all ASN.1 conversion functions, and other
- affected functions.
- o Improved platform support for PowerPC.
- o New FIPS 180-2 algorithms (SHA-224, -256, -384 and -512).
- o New X509_VERIFY_PARAM structure to support parameterisation
- of X.509 path validation.
- o Major overhaul of RC4 performance on Intel P4, IA-64 and
- AMD64.
- o Changed the Configure script to have some algorithms disabled
- by default. Those can be explicitly enabled with the new
- argument form 'enable-xxx'.
- o Change the default digest in 'openssl' commands from MD5 to
- SHA-1.
- o Added support for DTLS.
- o New BIGNUM blinding.
- o Added support for the RSA-PSS encryption scheme
- o Added support for the RSA X.931 padding.
- o Added support for BSD sockets on NetWare.
- o Added support for files larger than 2GB.
- o Added initial support for Win64.
- o Added alternate pkg-config files.
-
- Major changes between OpenSSL 0.9.7l and OpenSSL 0.9.7m [23 Feb 2007]:
-
- o FIPS 1.1.1 module linking.
- o Various ciphersuite selection fixes.
-
- Major changes between OpenSSL 0.9.7k and OpenSSL 0.9.7l [28 Sep 2006]:
-
- o Introduce limits to prevent malicious key DoS (CVE-2006-2940)
- o Fix security issues (CVE-2006-2937, CVE-2006-3737, CVE-2006-4343)
-
- Major changes between OpenSSL 0.9.7j and OpenSSL 0.9.7k [5 Sep 2006]:
-
- o Fix Daniel Bleichenbacher forged signature attack, CVE-2006-4339
-
- Major changes between OpenSSL 0.9.7i and OpenSSL 0.9.7j [4 May 2006]:
-
- o Visual C++ 2005 fixes.
- o Update Windows build system for FIPS.
-
- Major changes between OpenSSL 0.9.7h and OpenSSL 0.9.7i [14 Oct 2005]:
-
- o Give EVP_MAX_MD_SIZE its old value, except for a FIPS build.
-
- Major changes between OpenSSL 0.9.7g and OpenSSL 0.9.7h [11 Oct 2005]:
-
- o Fix SSL 2.0 Rollback, CVE-2005-2969
- o Allow use of fixed-length exponent on DSA signing
- o Default fixed-window RSA, DSA, DH private-key operations
-
- Major changes between OpenSSL 0.9.7f and OpenSSL 0.9.7g [11 Apr 2005]:
-
- o More compilation issues fixed.
- o Adaptation to more modern Kerberos API.
- o Enhanced or corrected configuration for Solaris64, Mingw and Cygwin.
- o Enhanced x86_64 assembler BIGNUM module.
- o More constification.
- o Added processing of proxy certificates (RFC 3820).
-
- Major changes between OpenSSL 0.9.7e and OpenSSL 0.9.7f [22 Mar 2005]:
-
- o Several compilation issues fixed.
- o Many memory allocation failure checks added.
- o Improved comparison of X509 Name type.
- o Mandatory basic checks on certificates.
- o Performance improvements.
-
- Major changes between OpenSSL 0.9.7d and OpenSSL 0.9.7e [25 Oct 2004]:
-
- o Fix race condition in CRL checking code.
- o Fixes to PKCS#7 (S/MIME) code.
-
- Major changes between OpenSSL 0.9.7c and OpenSSL 0.9.7d [17 Mar 2004]:
-
- o Security: Fix Kerberos ciphersuite SSL/TLS handshaking bug
- o Security: Fix null-pointer assignment in do_change_cipher_spec()
- o Allow multiple active certificates with same subject in CA index
- o Multiple X509 verification fixes
- o Speed up HMAC and other operations
-
- Major changes between OpenSSL 0.9.7b and OpenSSL 0.9.7c [30 Sep 2003]:
-
- o Security: fix various ASN1 parsing bugs.
- o New -ignore_err option to OCSP utility.
- o Various interop and bug fixes in S/MIME code.
- o SSL/TLS protocol fix for unrequested client certificates.
-
- Major changes between OpenSSL 0.9.7a and OpenSSL 0.9.7b [10 Apr 2003]:
-
- o Security: counter the Klima-Pokorny-Rosa extension of
- Bleichbacher's attack
- o Security: make RSA blinding default.
- o Configuration: Irix fixes, AIX fixes, better mingw support.
- o Support for new platforms: linux-ia64-ecc.
- o Build: shared library support fixes.
- o ASN.1: treat domainComponent correctly.
- o Documentation: fixes and additions.
-
- Major changes between OpenSSL 0.9.7 and OpenSSL 0.9.7a [19 Feb 2003]:
-
- o Security: Important security related bugfixes.
- o Enhanced compatibility with MIT Kerberos.
- o Can be built without the ENGINE framework.
- o IA32 assembler enhancements.
- o Support for new platforms: FreeBSD/IA64 and FreeBSD/Sparc64.
- o Configuration: the no-err option now works properly.
- o SSL/TLS: now handles manual certificate chain building.
- o SSL/TLS: certain session ID malfunctions corrected.
-
- Major changes between OpenSSL 0.9.6 and OpenSSL 0.9.7 [30 Dec 2002]:
-
- o New library section OCSP.
- o Complete rewrite of ASN1 code.
- o CRL checking in verify code and openssl utility.
- o Extension copying in 'ca' utility.
- o Flexible display options in 'ca' utility.
- o Provisional support for international characters with UTF8.
- o Support for external crypto devices ('engine') is no longer
- a separate distribution.
- o New elliptic curve library section.
- o New AES (Rijndael) library section.
- o Support for new platforms: Windows CE, Tandem OSS, A/UX, AIX 64-bit,
- Linux x86_64, Linux 64-bit on Sparc v9
- o Extended support for some platforms: VxWorks
- o Enhanced support for shared libraries.
- o Now only builds PIC code when shared library support is requested.
- o Support for pkg-config.
- o Lots of new manuals.
- o Makes symbolic links to or copies of manuals to cover all described
- functions.
- o Change DES API to clean up the namespace (some applications link also
- against libdes providing similar functions having the same name).
- Provide macros for backward compatibility (will be removed in the
- future).
- o Unify handling of cryptographic algorithms (software and engine)
- to be available via EVP routines for asymmetric and symmetric ciphers.
- o NCONF: new configuration handling routines.
- o Change API to use more 'const' modifiers to improve error checking
- and help optimizers.
- o Finally remove references to RSAref.
- o Reworked parts of the BIGNUM code.
- o Support for new engines: Broadcom ubsec, Accelerated Encryption
- Processing, IBM 4758.
- o A few new engines added in the demos area.
- o Extended and corrected OID (object identifier) table.
- o PRNG: query at more locations for a random device, automatic query for
- EGD style random sources at several locations.
- o SSL/TLS: allow optional cipher choice according to server's preference.
- o SSL/TLS: allow server to explicitly set new session ids.
- o SSL/TLS: support Kerberos cipher suites (RFC2712).
- Only supports MIT Kerberos for now.
- o SSL/TLS: allow more precise control of renegotiations and sessions.
- o SSL/TLS: add callback to retrieve SSL/TLS messages.
- o SSL/TLS: support AES cipher suites (RFC3268).
-
- Major changes between OpenSSL 0.9.6j and OpenSSL 0.9.6k [30 Sep 2003]:
-
- o Security: fix various ASN1 parsing bugs.
- o SSL/TLS protocol fix for unrequested client certificates.
-
- Major changes between OpenSSL 0.9.6i and OpenSSL 0.9.6j [10 Apr 2003]:
-
- o Security: counter the Klima-Pokorny-Rosa extension of
- Bleichbacher's attack
- o Security: make RSA blinding default.
- o Build: shared library support fixes.
-
- Major changes between OpenSSL 0.9.6h and OpenSSL 0.9.6i [19 Feb 2003]:
-
- o Important security related bugfixes.
-
- Major changes between OpenSSL 0.9.6g and OpenSSL 0.9.6h [5 Dec 2002]:
-
- o New configuration targets for Tandem OSS and A/UX.
- o New OIDs for Microsoft attributes.
- o Better handling of SSL session caching.
- o Better comparison of distinguished names.
- o Better handling of shared libraries in a mixed GNU/non-GNU environment.
- o Support assembler code with Borland C.
- o Fixes for length problems.
- o Fixes for uninitialised variables.
- o Fixes for memory leaks, some unusual crashes and some race conditions.
- o Fixes for smaller building problems.
- o Updates of manuals, FAQ and other instructive documents.
-
- Major changes between OpenSSL 0.9.6f and OpenSSL 0.9.6g [9 Aug 2002]:
-
- o Important building fixes on Unix.
-
- Major changes between OpenSSL 0.9.6e and OpenSSL 0.9.6f [8 Aug 2002]:
-
- o Various important bugfixes.
-
- Major changes between OpenSSL 0.9.6d and OpenSSL 0.9.6e [30 Jul 2002]:
-
- o Important security related bugfixes.
- o Various SSL/TLS library bugfixes.
-
- Major changes between OpenSSL 0.9.6c and OpenSSL 0.9.6d [9 May 2002]:
-
- o Various SSL/TLS library bugfixes.
- o Fix DH parameter generation for 'non-standard' generators.
-
- Major changes between OpenSSL 0.9.6b and OpenSSL 0.9.6c [21 Dec 2001]:
-
- o Various SSL/TLS library bugfixes.
- o BIGNUM library fixes.
- o RSA OAEP and random number generation fixes.
- o Object identifiers corrected and added.
- o Add assembler BN routines for IA64.
- o Add support for OS/390 Unix, UnixWare with gcc, OpenUNIX 8,
- MIPS Linux; shared library support for Irix, HP-UX.
- o Add crypto accelerator support for AEP, Baltimore SureWare,
- Broadcom and Cryptographic Appliance's keyserver
- [in 0.9.6c-engine release].
-
- Major changes between OpenSSL 0.9.6a and OpenSSL 0.9.6b [9 Jul 2001]:
-
- o Security fix: PRNG improvements.
- o Security fix: RSA OAEP check.
- o Security fix: Reinsert and fix countermeasure to Bleichbacher's
- attack.
- o MIPS bug fix in BIGNUM.
- o Bug fix in "openssl enc".
- o Bug fix in X.509 printing routine.
- o Bug fix in DSA verification routine and DSA S/MIME verification.
- o Bug fix to make PRNG thread-safe.
- o Bug fix in RAND_file_name().
- o Bug fix in compatibility mode trust settings.
- o Bug fix in blowfish EVP.
- o Increase default size for BIO buffering filter.
- o Compatibility fixes in some scripts.
-
- Major changes between OpenSSL 0.9.6 and OpenSSL 0.9.6a [5 Apr 2001]:
-
- o Security fix: change behavior of OpenSSL to avoid using
- environment variables when running as root.
- o Security fix: check the result of RSA-CRT to reduce the
- possibility of deducing the private key from an incorrectly
- calculated signature.
- o Security fix: prevent Bleichenbacher's DSA attack.
- o Security fix: Zero the premaster secret after deriving the
- master secret in DH ciphersuites.
- o Reimplement SSL_peek(), which had various problems.
- o Compatibility fix: the function des_encrypt() renamed to
- des_encrypt1() to avoid clashes with some Unixen libc.
- o Bug fixes for Win32, HP/UX and Irix.
- o Bug fixes in BIGNUM, SSL, PKCS#7, PKCS#12, X.509, CONF and
- memory checking routines.
- o Bug fixes for RSA operations in threaded environments.
- o Bug fixes in misc. openssl applications.
- o Remove a few potential memory leaks.
- o Add tighter checks of BIGNUM routines.
- o Shared library support has been reworked for generality.
- o More documentation.
- o New function BN_rand_range().
- o Add "-rand" option to openssl s_client and s_server.
-
- Major changes between OpenSSL 0.9.5a and OpenSSL 0.9.6 [10 Oct 2000]:
-
- o Some documentation for BIO and SSL libraries.
- o Enhanced chain verification using key identifiers.
- o New sign and verify options to 'dgst' application.
- o Support for DER and PEM encoded messages in 'smime' application.
- o New 'rsautl' application, low level RSA utility.
- o MD4 now included.
- o Bugfix for SSL rollback padding check.
- o Support for external crypto devices [1].
- o Enhanced EVP interface.
-
- [1] The support for external crypto devices is currently a separate
- distribution. See the file README.ENGINE.
-
- Major changes between OpenSSL 0.9.5 and OpenSSL 0.9.5a [1 Apr 2000]:
-
- o Bug fixes for Win32, SuSE Linux, NeXTSTEP and FreeBSD 2.2.8
- o Shared library support for HPUX and Solaris-gcc
- o Support of Linux/IA64
- o Assembler support for Mingw32
- o New 'rand' application
- o New way to check for existence of algorithms from scripts
-
- Major changes between OpenSSL 0.9.4 and OpenSSL 0.9.5 [25 May 2000]:
-
- o S/MIME support in new 'smime' command
- o Documentation for the OpenSSL command line application
- o Automation of 'req' application
- o Fixes to make s_client, s_server work under Windows
- o Support for multiple fieldnames in SPKACs
- o New SPKAC command line utility and associated library functions
- o Options to allow passwords to be obtained from various sources
- o New public key PEM format and options to handle it
- o Many other fixes and enhancements to command line utilities
- o Usable certificate chain verification
- o Certificate purpose checking
- o Certificate trust settings
- o Support of authority information access extension
- o Extensions in certificate requests
- o Simplified X509 name and attribute routines
- o Initial (incomplete) support for international character sets
- o New DH_METHOD, DSA_METHOD and enhanced RSA_METHOD
- o Read only memory BIOs and simplified creation function
- o TLS/SSL protocol bugfixes: Accept TLS 'client hello' in SSL 3.0
- record; allow fragmentation and interleaving of handshake and other
- data
- o TLS/SSL code now "tolerates" MS SGC
- o Work around for Netscape client certificate hang bug
- o RSA_NULL option that removes RSA patent code but keeps other
- RSA functionality
- o Memory leak detection now allows applications to add extra information
- via a per-thread stack
- o PRNG robustness improved
- o EGD support
- o BIGNUM library bug fixes
- o Faster DSA parameter generation
- o Enhanced support for Alpha Linux
- o Experimental MacOS support
-
- Major changes between OpenSSL 0.9.3 and OpenSSL 0.9.4 [9 Aug 1999]:
-
- o Transparent support for PKCS#8 format private keys: these are used
- by several software packages and are more secure than the standard
- form
- o PKCS#5 v2.0 implementation
- o Password callbacks have a new void * argument for application data
- o Avoid various memory leaks
- o New pipe-like BIO that allows using the SSL library when actual I/O
- must be handled by the application (BIO pair)
-
- Major changes between OpenSSL 0.9.2b and OpenSSL 0.9.3 [24 May 1999]:
- o Lots of enhancements and cleanups to the Configuration mechanism
- o RSA OEAP related fixes
- o Added `openssl ca -revoke' option for revoking a certificate
- o Source cleanups: const correctness, type-safe stacks and ASN.1 SETs
- o Source tree cleanups: removed lots of obsolete files
- o Thawte SXNet, certificate policies and CRL distribution points
- extension support
- o Preliminary (experimental) S/MIME support
- o Support for ASN.1 UTF8String and VisibleString
- o Full integration of PKCS#12 code
- o Sparc assembler bignum implementation, optimized hash functions
- o Option to disable selected ciphers
-
- Major changes between OpenSSL 0.9.1c and OpenSSL 0.9.2b [22 Mar 1999]:
- o Fixed a security hole related to session resumption
- o Fixed RSA encryption routines for the p < q case
- o "ALL" in cipher lists now means "everything except NULL ciphers"
- o Support for Triple-DES CBCM cipher
- o Support of Optimal Asymmetric Encryption Padding (OAEP) for RSA
- o First support for new TLSv1 ciphers
- o Added a few new BIOs (syslog BIO, reliable BIO)
- o Extended support for DSA certificate/keys.
- o Extended support for Certificate Signing Requests (CSR)
- o Initial support for X.509v3 extensions
- o Extended support for compression inside the SSL record layer
- o Overhauled Win32 builds
- o Cleanups and fixes to the Big Number (BN) library
- o Support for ASN.1 GeneralizedTime
- o Splitted ASN.1 SETs from SEQUENCEs
- o ASN1 and PEM support for Netscape Certificate Sequences
- o Overhauled Perl interface
- o Lots of source tree cleanups.
- o Lots of memory leak fixes.
- o Lots of bug fixes.
-
- Major changes between SSLeay 0.9.0b and OpenSSL 0.9.1c [23 Dec 1998]:
- o Integration of the popular NO_RSA/NO_DSA patches
- o Initial support for compression inside the SSL record layer
- o Added BIO proxy and filtering functionality
- o Extended Big Number (BN) library
- o Added RIPE MD160 message digest
- o Added support for RC2/64bit cipher
- o Extended ASN.1 parser routines
- o Adjustments of the source tree for CVS
- o Support for various new platforms
diff --git a/NEWS.md b/NEWS.md
new file mode 100644
index 000000000000..36dbfa72f6d5
--- /dev/null
+++ b/NEWS.md
@@ -0,0 +1,1586 @@
+NEWS
+====
+
+This file gives a brief overview of the major changes between each OpenSSL
+release. For more details please read the CHANGES file.
+
+OpenSSL Releases
+----------------
+
+ - [OpenSSL 3.0](#openssl-30)
+ - [OpenSSL 1.1.1](#openssl-111)
+ - [OpenSSL 1.1.0](#openssl-110)
+ - [OpenSSL 1.0.2](#openssl-102)
+ - [OpenSSL 1.0.1](#openssl-101)
+ - [OpenSSL 1.0.0](#openssl-100)
+ - [OpenSSL 0.9.x](#openssl-09x)
+
+OpenSSL 3.0
+-----------
+
+### Major changes between OpenSSL 3.0.7 and OpenSSL 3.0.8 [7 Feb 2023]
+
+ * Fixed NULL dereference during PKCS7 data verification ([CVE-2023-0401])
+ * Fixed X.400 address type confusion in X.509 GeneralName ([CVE-2023-0286])
+ * Fixed NULL dereference validating DSA public key ([CVE-2023-0217])
+ * Fixed Invalid pointer dereference in d2i_PKCS7 functions ([CVE-2023-0216])
+ * Fixed Use-after-free following BIO_new_NDEF ([CVE-2023-0215])
+ * Fixed Double free after calling PEM_read_bio_ex ([CVE-2022-4450])
+ * Fixed Timing Oracle in RSA Decryption ([CVE-2022-4304])
+ * Fixed X.509 Name Constraints Read Buffer Overflow ([CVE-2022-4203])
+ * Fixed X.509 Policy Constraints Double Locking ([CVE-2022-3996])
+
+### Major changes between OpenSSL 3.0.6 and OpenSSL 3.0.7 [1 Nov 2022]
+
+ * Added RIPEMD160 to the default provider.
+ * Fixed regressions introduced in 3.0.6 version.
+ * Fixed two buffer overflows in punycode decoding functions.
+ ([CVE-2022-3786]) and ([CVE-2022-3602])
+
+### Major changes between OpenSSL 3.0.5 and OpenSSL 3.0.6 [11 Oct 2022]
+
+ * Fix for custom ciphers to prevent accidental use of NULL encryption
+ ([CVE-2022-3358])
+
+### Major changes between OpenSSL 3.0.4 and OpenSSL 3.0.5 [5 Jul 2022]
+
+ * Fixed heap memory corruption with RSA private key operation
+ ([CVE-2022-2274])
+ * Fixed AES OCB failure to encrypt some bytes on 32-bit x86 platforms
+ ([CVE-2022-2097])
+
+### Major changes between OpenSSL 3.0.3 and OpenSSL 3.0.4 [21 Jun 2022]
+
+ * Fixed additional bugs in the c_rehash script which was not properly
+ sanitising shell metacharacters to prevent command injection
+ ([CVE-2022-2068])
+
+### Major changes between OpenSSL 3.0.2 and OpenSSL 3.0.3 [3 May 2022]
+
+ * Fixed a bug in the c_rehash script which was not properly sanitising shell
+ metacharacters to prevent command injection ([CVE-2022-1292])
+ * Fixed a bug in the function `OCSP_basic_verify` that verifies the signer
+ certificate on an OCSP response ([CVE-2022-1343])
+ * Fixed a bug where the RC4-MD5 ciphersuite incorrectly used the
+ AAD data as the MAC key ([CVE-2022-1434])
+ * Fix a bug in the OPENSSL_LH_flush() function that breaks reuse of the memory
+ occuppied by the removed hash table entries ([CVE-2022-1473])
+
+### Major changes between OpenSSL 3.0.1 and OpenSSL 3.0.2 [15 Mar 2022]
+
+ * Fixed a bug in the BN_mod_sqrt() function that can cause it to loop forever
+ for non-prime moduli ([CVE-2022-0778])
+
+### Major changes between OpenSSL 3.0.0 and OpenSSL 3.0.1 [14 Dec 2021]
+
+ * Fixed invalid handling of X509_verify_cert() internal errors in libssl
+ ([CVE-2021-4044])
+ * Allow fetching an operation from the provider that owns an unexportable key
+ as a fallback if that is still allowed by the property query.
+
+### Major changes between OpenSSL 1.1.1 and OpenSSL 3.0.0 [7 sep 2021]
+
+ * Enhanced 'openssl list' with many new options.
+ * Added migration guide to man7.
+ * Implemented support for fully "pluggable" TLSv1.3 groups.
+ * Added suport for Kernel TLS (KTLS).
+ * Changed the license to the Apache License v2.0.
+ * Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2,
+ RC4, RC5, and DES to the legacy provider.
+ * Moved the EVP digests MD2, MD4, MDC2, WHIRLPOOL and RIPEMD-160 to the legacy
+ provider.
+ * Added convenience functions for generating asymmetric key pairs.
+ * Deprecated the `OCSP_REQ_CTX` type and functions.
+ * Deprecated the `EC_KEY` and `EC_KEY_METHOD` types and functions.
+ * Deprecated the `RSA` and `RSA_METHOD` types and functions.
+ * Deprecated the `DSA` and `DSA_METHOD` types and functions.
+ * Deprecated the `DH` and `DH_METHOD` types and functions.
+ * Deprecated the `ERR_load_` functions.
+ * Remove the `RAND_DRBG` API.
+ * Deprecated the `ENGINE` API.
+ * Added `OSSL_LIB_CTX`, a libcrypto library context.
+ * Added various `_ex` functions to the OpenSSL API that support using
+ a non-default `OSSL_LIB_CTX`.
+ * Interactive mode is removed from the 'openssl' program.
+ * The X25519, X448, Ed25519, Ed448, SHAKE128 and SHAKE256 algorithms are
+ included in the FIPS provider.
+ * X509 certificates signed using SHA1 are no longer allowed at security
+ level 1 or higher. The default security level for TLS is 1, so
+ certificates signed using SHA1 are by default no longer trusted to
+ authenticate servers or clients.
+ * enable-crypto-mdebug and enable-crypto-mdebug-backtrace were mostly
+ disabled; the project uses address sanitize/leak-detect instead.
+ * Added a Certificate Management Protocol (CMP, RFC 4210) implementation
+ also covering CRMF (RFC 4211) and HTTP transfer (RFC 6712).
+ It is part of the crypto lib and adds a 'cmp' app with a demo configuration.
+ All widely used CMP features are supported for both clients and servers.
+ * Added a proper HTTP client supporting GET with optional redirection, POST,
+ arbitrary request and response content types, TLS, persistent connections,
+ connections via HTTP(s) proxies, connections and exchange via user-defined
+ BIOs (allowing implicit connections), and timeout checks.
+ * Added util/check-format.pl for checking adherence to the coding guidelines.
+ * Added OSSL_ENCODER, a generic encoder API.
+ * Added OSSL_DECODER, a generic decoder API.
+ * Added OSSL_PARAM_BLD, an easier to use API to OSSL_PARAM.
+ * Added error raising macros, ERR_raise() and ERR_raise_data().
+ * Deprecated ERR_put_error(), ERR_get_error_line(), ERR_get_error_line_data(),
+ ERR_peek_error_line_data(), ERR_peek_last_error_line_data() and
+ ERR_func_error_string().
+ * Added OSSL_PROVIDER_available(), to check provider availibility.
+ * Added 'openssl mac' that uses the EVP_MAC API.
+ * Added 'openssl kdf' that uses the EVP_KDF API.
+ * Add OPENSSL_info() and 'openssl info' to get built-in data.
+ * Add support for enabling instrumentation through trace and debug
+ output.
+ * Changed our version number scheme and set the next major release to
+ 3.0.0
+ * Added EVP_MAC, an EVP layer MAC API, and a generic EVP_PKEY to EVP_MAC
+ bridge. Supported MACs are: BLAKE2, CMAC, GMAC, HMAC, KMAC, POLY1305
+ and SIPHASH.
+ * Removed the heartbeat message in DTLS feature.
+ * Added EVP_KDF, an EVP layer KDF and PRF API, and a generic EVP_PKEY to
+ EVP_KDF bridge. Supported KDFs are: HKDF, KBKDF, KRB5 KDF, PBKDF2,
+ PKCS12 KDF, SCRYPT, SSH KDF, SSKDF, TLS1 PRF, X9.42 KDF and X9.63 KDF.
+ * All of the low-level MD2, MD4, MD5, MDC2, RIPEMD160, SHA1, SHA224,
+ SHA256, SHA384, SHA512 and Whirlpool digest functions have been
+ deprecated.
+ * All of the low-level AES, Blowfish, Camellia, CAST, DES, IDEA, RC2,
+ RC4, RC5 and SEED cipher functions have been deprecated.
+ * All of the low-level DH, DSA, ECDH, ECDSA and RSA public key functions
+ have been deprecated.
+ * SSL 3, TLS 1.0, TLS 1.1, and DTLS 1.0 only work at security level 0,
+ except when RSA key exchange without SHA1 is used.
+ * Added providers, a new pluggability concept that will replace the
+ ENGINE API and ENGINE implementations.
+
+OpenSSL 1.1.1
+-------------
+
+### Major changes between OpenSSL 1.1.1k and OpenSSL 1.1.1l [24 Aug 2021]
+
+ * Fixed an SM2 Decryption Buffer Overflow ([CVE-2021-3711])
+ * Fixed various read buffer overruns processing ASN.1 strings ([CVE-2021-3712])
+
+### Major changes between OpenSSL 1.1.1j and OpenSSL 1.1.1k [25 Mar 2021]
+
+ * Fixed a problem with verifying a certificate chain when using the
+ X509_V_FLAG_X509_STRICT flag ([CVE-2021-3450])
+ * Fixed an issue where an OpenSSL TLS server may crash if sent a maliciously
+ crafted renegotiation ClientHello message from a client ([CVE-2021-3449])
+
+### Major changes between OpenSSL 1.1.1i and OpenSSL 1.1.1j [16 Feb 2021]
+
+ * Fixed a NULL pointer deref in the X509_issuer_and_serial_hash()
+ function ([CVE-2021-23841])
+ * Fixed the RSA_padding_check_SSLv23() function and the RSA_SSLV23_PADDING
+ padding mode to correctly check for rollback attacks
+ * Fixed an overflow in the EVP_CipherUpdate, EVP_EncryptUpdate and
+ EVP_DecryptUpdate functions ([CVE-2021-23840])
+ * Fixed SRP_Calc_client_key so that it runs in constant time
+
+### Major changes between OpenSSL 1.1.1h and OpenSSL 1.1.1i [8 Dec 2020]
+
+ * Fixed NULL pointer deref in GENERAL_NAME_cmp ([CVE-2020-1971])
+
+### Major changes between OpenSSL 1.1.1g and OpenSSL 1.1.1h [22 Sep 2020]
+
+ * Disallow explicit curve parameters in verifications chains when
+ X509_V_FLAG_X509_STRICT is used
+ * Enable 'MinProtocol' and 'MaxProtocol' to configure both TLS and DTLS
+ contexts
+ * Oracle Developer Studio will start reporting deprecation warnings
+
+### Major changes between OpenSSL 1.1.1f and OpenSSL 1.1.1g [21 Apr 2020]
+
+ * Fixed segmentation fault in SSL_check_chain() ([CVE-2020-1967])
+
+### Major changes between OpenSSL 1.1.1e and OpenSSL 1.1.1f [31 Mar 2020]
+
+ * Revert the unexpected EOF reporting via SSL_ERROR_SSL
+
+### Major changes between OpenSSL 1.1.1d and OpenSSL 1.1.1e [17 Mar 2020]
+
+ * Fixed an overflow bug in the x64_64 Montgomery squaring procedure
+ used in exponentiation with 512-bit moduli ([CVE-2019-1551])
+
+### Major changes between OpenSSL 1.1.1c and OpenSSL 1.1.1d [10 Sep 2019]
+
+ * Fixed a fork protection issue ([CVE-2019-1549])
+ * Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey
+ ([CVE-2019-1563])
+ * For built-in EC curves, ensure an EC_GROUP built from the curve name is
+ used even when parsing explicit parameters
+ * Compute ECC cofactors if not provided during EC_GROUP construction
+ ([CVE-2019-1547])
+ * Early start up entropy quality from the DEVRANDOM seed source has been
+ improved for older Linux systems
+ * Correct the extended master secret constant on EBCDIC systems
+ * Use Windows installation paths in the mingw builds ([CVE-2019-1552])
+ * Changed DH_check to accept parameters with order q and 2q subgroups
+ * Significantly reduce secure memory usage by the randomness pools
+ * Revert the DEVRANDOM_WAIT feature for Linux systems
+
+### Major changes between OpenSSL 1.1.1b and OpenSSL 1.1.1c [28 May 2019]
+
+ * Prevent over long nonces in ChaCha20-Poly1305 ([CVE-2019-1543])
+
+### Major changes between OpenSSL 1.1.1a and OpenSSL 1.1.1b [26 Feb 2019]
+
+ * Change the info callback signals for the start and end of a post-handshake
+ message exchange in TLSv1.3.
+ * Fix a bug in DTLS over SCTP. This breaks interoperability with older
+ versions of OpenSSL like OpenSSL 1.1.0 and OpenSSL 1.0.2.
+
+### Major changes between OpenSSL 1.1.1 and OpenSSL 1.1.1a [20 Nov 2018]
+
+ * Timing vulnerability in DSA signature generation ([CVE-2018-0734])
+ * Timing vulnerability in ECDSA signature generation ([CVE-2018-0735])
+
+### Major changes between OpenSSL 1.1.0i and OpenSSL 1.1.1 [11 Sep 2018]
+
+ * Support for TLSv1.3 added. The TLSv1.3 implementation includes:
+ * Fully compliant implementation of RFC8446 (TLSv1.3) on by default
+ * Early data (0-RTT)
+ * Post-handshake authentication and key update
+ * Middlebox Compatibility Mode
+ * TLSv1.3 PSKs
+ * Support for all five RFC8446 ciphersuites
+ * RSA-PSS signature algorithms (backported to TLSv1.2)
+ * Configurable session ticket support
+ * Stateless server support
+ * Rewrite of the packet construction code for "safer" packet handling
+ * Rewrite of the extension handling code
+ For further important information, see the [TLS1.3 page](
+ https://wiki.openssl.org/index.php/TLS1.3) in the OpenSSL Wiki.
+
+ * Complete rewrite of the OpenSSL random number generator to introduce the
+ following capabilities
+ * The default RAND method now utilizes an AES-CTR DRBG according to
+ NIST standard SP 800-90Ar1.
+ * Support for multiple DRBG instances with seed chaining.
+ * There is a public and private DRBG instance.
+ * The DRBG instances are fork-safe.
+ * Keep all global DRBG instances on the secure heap if it is enabled.
+ * The public and private DRBG instance are per thread for lock free
+ operation
+ * Support for various new cryptographic algorithms including:
+ * SHA3
+ * SHA512/224 and SHA512/256
+ * EdDSA (both Ed25519 and Ed448) including X509 and TLS support
+ * X448 (adding to the existing X25519 support in 1.1.0)
+ * Multi-prime RSA
+ * SM2
+ * SM3
+ * SM4
+ * SipHash
+ * ARIA (including TLS support)
+ * Significant Side-Channel attack security improvements
+ * Add a new ClientHello callback to provide the ability to adjust the SSL
+ object at an early stage.
+ * Add 'Maximum Fragment Length' TLS extension negotiation and support
+ * A new STORE module, which implements a uniform and URI based reader of
+ stores that can contain keys, certificates, CRLs and numerous other
+ objects.
+ * Move the display of configuration data to configdata.pm.
+ * Allow GNU style "make variables" to be used with Configure.
+ * Claim the namespaces OSSL and OPENSSL, represented as symbol prefixes
+ * Rewrite of devcrypto engine
+
+OpenSSL 1.1.0
+-------------
+
+### Major changes between OpenSSL 1.1.0k and OpenSSL 1.1.0l [10 Sep 2019]
+
+ * Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey
+ ([CVE-2019-1563])
+ * For built-in EC curves, ensure an EC_GROUP built from the curve name is
+ used even when parsing explicit parameters
+ * Compute ECC cofactors if not provided during EC_GROUP construction
+ ([CVE-2019-1547])
+ * Use Windows installation paths in the mingw builds ([CVE-2019-1552])
+
+### Major changes between OpenSSL 1.1.0j and OpenSSL 1.1.0k [28 May 2019]
+
+ * Prevent over long nonces in ChaCha20-Poly1305 ([CVE-2019-1543])
+
+### Major changes between OpenSSL 1.1.0i and OpenSSL 1.1.0j [20 Nov 2018]
+
+ * Timing vulnerability in DSA signature generation ([CVE-2018-0734])
+ * Timing vulnerability in ECDSA signature generation ([CVE-2018-0735])
+
+### Major changes between OpenSSL 1.1.0h and OpenSSL 1.1.0i [14 Aug 2018]
+
+ * Client DoS due to large DH parameter ([CVE-2018-0732])
+ * Cache timing vulnerability in RSA Key Generation ([CVE-2018-0737])
+
+### Major changes between OpenSSL 1.1.0g and OpenSSL 1.1.0h [27 Mar 2018]
+
+ * Constructed ASN.1 types with a recursive definition could exceed the
+ stack ([CVE-2018-0739])
+ * Incorrect CRYPTO_memcmp on HP-UX PA-RISC ([CVE-2018-0733])
+ * rsaz_1024_mul_avx2 overflow bug on x86_64 ([CVE-2017-3738])
+
+### Major changes between OpenSSL 1.1.0f and OpenSSL 1.1.0g [2 Nov 2017]
+
+ * bn_sqrx8x_internal carry bug on x86_64 ([CVE-2017-3736])
+ * Malformed X.509 IPAddressFamily could cause OOB read ([CVE-2017-3735])
+
+### Major changes between OpenSSL 1.1.0e and OpenSSL 1.1.0f [25 May 2017]
+
+ * config now recognises 64-bit mingw and chooses mingw64 instead of mingw
+
+### Major changes between OpenSSL 1.1.0d and OpenSSL 1.1.0e [16 Feb 2017]
+
+ * Encrypt-Then-Mac renegotiation crash ([CVE-2017-3733])
+
+### Major changes between OpenSSL 1.1.0c and OpenSSL 1.1.0d [26 Jan 2017]
+
+ * Truncated packet could crash via OOB read ([CVE-2017-3731])
+ * Bad (EC)DHE parameters cause a client crash ([CVE-2017-3730])
+ * BN_mod_exp may produce incorrect results on x86_64 ([CVE-2017-3732])
+
+### Major changes between OpenSSL 1.1.0b and OpenSSL 1.1.0c [10 Nov 2016]
+
+ * ChaCha20/Poly1305 heap-buffer-overflow ([CVE-2016-7054])
+ * CMS Null dereference ([CVE-2016-7053])
+ * Montgomery multiplication may produce incorrect results ([CVE-2016-7055])
+
+### Major changes between OpenSSL 1.1.0a and OpenSSL 1.1.0b [26 Sep 2016]
+
+ * Fix Use After Free for large message sizes ([CVE-2016-6309])
+
+### Major changes between OpenSSL 1.1.0 and OpenSSL 1.1.0a [22 Sep 2016]
+
+ * OCSP Status Request extension unbounded memory growth ([CVE-2016-6304])
+ * SSL_peek() hang on empty record ([CVE-2016-6305])
+ * Excessive allocation of memory in tls_get_message_header()
+ ([CVE-2016-6307])
+ * Excessive allocation of memory in dtls1_preprocess_fragment()
+ ([CVE-2016-6308])
+
+### Major changes between OpenSSL 1.0.2h and OpenSSL 1.1.0 [25 Aug 2016]
+
+ * Copyright text was shrunk to a boilerplate that points to the license
+ * "shared" builds are now the default when possible
+ * Added support for "pipelining"
+ * Added the AFALG engine
+ * New threading API implemented
+ * Support for ChaCha20 and Poly1305 added to libcrypto and libssl
+ * Support for extended master secret
+ * CCM ciphersuites
+ * Reworked test suite, now based on perl, Test::Harness and Test::More
+ * *Most* libcrypto and libssl public structures were made opaque,
+ including:
+ BIGNUM and associated types, EC_KEY and EC_KEY_METHOD,
+ DH and DH_METHOD, DSA and DSA_METHOD, RSA and RSA_METHOD,
+ BIO and BIO_METHOD, EVP_MD_CTX, EVP_MD, EVP_CIPHER_CTX,
+ EVP_CIPHER, EVP_PKEY and associated types, HMAC_CTX,
+ X509, X509_CRL, X509_OBJECT, X509_STORE_CTX, X509_STORE,
+ X509_LOOKUP, X509_LOOKUP_METHOD
+ * libssl internal structures made opaque
+ * SSLv2 support removed
+ * Kerberos ciphersuite support removed
+ * RC4 removed from DEFAULT ciphersuites in libssl
+ * 40 and 56 bit cipher support removed from libssl
+ * All public header files moved to include/openssl, no more symlinking
+ * SSL/TLS state machine, version negotiation and record layer rewritten
+ * EC revision: now operations use new EC_KEY_METHOD.
+ * Support for OCB mode added to libcrypto
+ * Support for asynchronous crypto operations added to libcrypto and libssl
+ * Deprecated interfaces can now be disabled at build time either
+ relative to the latest release via the "no-deprecated" Configure
+ argument, or via the "--api=1.1.0|1.0.0|0.9.8" option.
+ * Application software can be compiled with -DOPENSSL_API_COMPAT=version
+ to ensure that features deprecated in that version are not exposed.
+ * Support for RFC6698/RFC7671 DANE TLSA peer authentication
+ * Change of Configure to use --prefix as the main installation
+ directory location rather than --openssldir. The latter becomes
+ the directory for certs, private key and openssl.cnf exclusively.
+ * Reworked BIO networking library, with full support for IPv6.
+ * New "unified" build system
+ * New security levels
+ * Support for scrypt algorithm
+ * Support for X25519
+ * Extended SSL_CONF support using configuration files
+ * KDF algorithm support. Implement TLS PRF as a KDF.
+ * Support for Certificate Transparency
+ * HKDF support.
+
+OpenSSL 1.0.2
+-------------
+
+### Major changes between OpenSSL 1.0.2s and OpenSSL 1.0.2t [10 Sep 2019]
+
+ * Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey
+ ([CVE-2019-1563])
+ * For built-in EC curves, ensure an EC_GROUP built from the curve name is
+ used even when parsing explicit parameters
+ * Compute ECC cofactors if not provided during EC_GROUP construction
+ ([CVE-2019-1547])
+ * Document issue with installation paths in diverse Windows builds
+ ([CVE-2019-1552])
+
+### Major changes between OpenSSL 1.0.2r and OpenSSL 1.0.2s [28 May 2019]
+
+ * None
+
+### Major changes between OpenSSL 1.0.2q and OpenSSL 1.0.2r [26 Feb 2019]
+
+ * 0-byte record padding oracle ([CVE-2019-1559])
+
+### Major changes between OpenSSL 1.0.2p and OpenSSL 1.0.2q [20 Nov 2018]
+
+ * Microarchitecture timing vulnerability in ECC scalar multiplication ([CVE-2018-5407])
+ * Timing vulnerability in DSA signature generation ([CVE-2018-0734])
+
+### Major changes between OpenSSL 1.0.2o and OpenSSL 1.0.2p [14 Aug 2018]
+
+ * Client DoS due to large DH parameter ([CVE-2018-0732])
+ * Cache timing vulnerability in RSA Key Generation ([CVE-2018-0737])
+
+### Major changes between OpenSSL 1.0.2n and OpenSSL 1.0.2o [27 Mar 2018]
+
+ * Constructed ASN.1 types with a recursive definition could exceed the
+ stack ([CVE-2018-0739])
+
+### Major changes between OpenSSL 1.0.2m and OpenSSL 1.0.2n [7 Dec 2017]
+
+ * Read/write after SSL object in error state ([CVE-2017-3737])
+ * rsaz_1024_mul_avx2 overflow bug on x86_64 ([CVE-2017-3738])
+
+### Major changes between OpenSSL 1.0.2l and OpenSSL 1.0.2m [2 Nov 2017]
+
+ * bn_sqrx8x_internal carry bug on x86_64 ([CVE-2017-3736])
+ * Malformed X.509 IPAddressFamily could cause OOB read ([CVE-2017-3735])
+
+### Major changes between OpenSSL 1.0.2k and OpenSSL 1.0.2l [25 May 2017]
+
+ * config now recognises 64-bit mingw and chooses mingw64 instead of mingw
+
+### Major changes between OpenSSL 1.0.2j and OpenSSL 1.0.2k [26 Jan 2017]
+
+ * Truncated packet could crash via OOB read ([CVE-2017-3731])
+ * BN_mod_exp may produce incorrect results on x86_64 ([CVE-2017-3732])
+ * Montgomery multiplication may produce incorrect results ([CVE-2016-7055])
+
+### Major changes between OpenSSL 1.0.2i and OpenSSL 1.0.2j [26 Sep 2016]
+
+ * Missing CRL sanity check ([CVE-2016-7052])
+
+### Major changes between OpenSSL 1.0.2h and OpenSSL 1.0.2i [22 Sep 2016]
+
+ * OCSP Status Request extension unbounded memory growth ([CVE-2016-6304])
+ * SWEET32 Mitigation ([CVE-2016-2183])
+ * OOB write in MDC2_Update() ([CVE-2016-6303])
+ * Malformed SHA512 ticket DoS ([CVE-2016-6302])
+ * OOB write in BN_bn2dec() ([CVE-2016-2182])
+ * OOB read in TS_OBJ_print_bio() ([CVE-2016-2180])
+ * Pointer arithmetic undefined behaviour ([CVE-2016-2177])
+ * Constant time flag not preserved in DSA signing ([CVE-2016-2178])
+ * DTLS buffered message DoS ([CVE-2016-2179])
+ * DTLS replay protection DoS ([CVE-2016-2181])
+ * Certificate message OOB reads ([CVE-2016-6306])
+
+### Major changes between OpenSSL 1.0.2g and OpenSSL 1.0.2h [3 May 2016]
+
+ * Prevent padding oracle in AES-NI CBC MAC check ([CVE-2016-2107])
+ * Fix EVP_EncodeUpdate overflow ([CVE-2016-2105])
+ * Fix EVP_EncryptUpdate overflow ([CVE-2016-2106])
+ * Prevent ASN.1 BIO excessive memory allocation ([CVE-2016-2109])
+ * EBCDIC overread ([CVE-2016-2176])
+ * Modify behavior of ALPN to invoke callback after SNI/servername
+ callback, such that updates to the SSL_CTX affect ALPN.
+ * Remove LOW from the DEFAULT cipher list. This removes singles DES from
+ the default.
+ * Only remove the SSLv2 methods with the no-ssl2-method option.
+
+### Major changes between OpenSSL 1.0.2f and OpenSSL 1.0.2g [1 Mar 2016]
+
+ * Disable weak ciphers in SSLv3 and up in default builds of OpenSSL.
+ * Disable SSLv2 default build, default negotiation and weak ciphers
+ ([CVE-2016-0800])
+ * Fix a double-free in DSA code ([CVE-2016-0705])
+ * Disable SRP fake user seed to address a server memory leak
+ ([CVE-2016-0798])
+ * Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption
+ ([CVE-2016-0797])
+ * Fix memory issues in BIO_*printf functions ([CVE-2016-0799])
+ * Fix side channel attack on modular exponentiation ([CVE-2016-0702])
+
+### Major changes between OpenSSL 1.0.2e and OpenSSL 1.0.2f [28 Jan 2016]
+
+ * DH small subgroups ([CVE-2016-0701])
+ * SSLv2 doesn't block disabled ciphers ([CVE-2015-3197])
+
+### Major changes between OpenSSL 1.0.2d and OpenSSL 1.0.2e [3 Dec 2015]
+
+ * BN_mod_exp may produce incorrect results on x86_64 ([CVE-2015-3193])
+ * Certificate verify crash with missing PSS parameter ([CVE-2015-3194])
+ * X509_ATTRIBUTE memory leak ([CVE-2015-3195])
+ * Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs
+ * In DSA_generate_parameters_ex, if the provided seed is too short,
+ return an error
+
+### Major changes between OpenSSL 1.0.2c and OpenSSL 1.0.2d [9 Jul 2015]
+
+ * Alternate chains certificate forgery ([CVE-2015-1793])
+ * Race condition handling PSK identify hint ([CVE-2015-3196])
+
+### Major changes between OpenSSL 1.0.2b and OpenSSL 1.0.2c [12 Jun 2015]
+
+ * Fix HMAC ABI incompatibility
+
+### Major changes between OpenSSL 1.0.2a and OpenSSL 1.0.2b [11 Jun 2015]
+
+ * Malformed ECParameters causes infinite loop ([CVE-2015-1788])
+ * Exploitable out-of-bounds read in X509_cmp_time ([CVE-2015-1789])
+ * PKCS7 crash with missing EnvelopedContent ([CVE-2015-1790])
+ * CMS verify infinite loop with unknown hash function ([CVE-2015-1792])
+ * Race condition handling NewSessionTicket ([CVE-2015-1791])
+
+### Major changes between OpenSSL 1.0.2 and OpenSSL 1.0.2a [19 Mar 2015]
+
+ * OpenSSL 1.0.2 ClientHello sigalgs DoS fix ([CVE-2015-0291])
+ * Multiblock corrupted pointer fix ([CVE-2015-0290])
+ * Segmentation fault in DTLSv1_listen fix ([CVE-2015-0207])
+ * Segmentation fault in ASN1_TYPE_cmp fix ([CVE-2015-0286])
+ * Segmentation fault for invalid PSS parameters fix ([CVE-2015-0208])
+ * ASN.1 structure reuse memory corruption fix ([CVE-2015-0287])
+ * PKCS7 NULL pointer dereferences fix ([CVE-2015-0289])
+ * DoS via reachable assert in SSLv2 servers fix ([CVE-2015-0293])
+ * Empty CKE with client auth and DHE fix ([CVE-2015-1787])
+ * Handshake with unseeded PRNG fix ([CVE-2015-0285])
+ * Use After Free following d2i_ECPrivatekey error fix ([CVE-2015-0209])
+ * X509_to_X509_REQ NULL pointer deref fix ([CVE-2015-0288])
+ * Removed the export ciphers from the DEFAULT ciphers
+
+### Major changes between OpenSSL 1.0.1l and OpenSSL 1.0.2 [22 Jan 2015]
+
+ * Suite B support for TLS 1.2 and DTLS 1.2
+ * Support for DTLS 1.2
+ * TLS automatic EC curve selection.
+ * API to set TLS supported signature algorithms and curves
+ * SSL_CONF configuration API.
+ * TLS Brainpool support.
+ * ALPN support.
+ * CMS support for RSA-PSS, RSA-OAEP, ECDH and X9.42 DH.
+
+OpenSSL 1.0.1
+-------------
+
+### Major changes between OpenSSL 1.0.1t and OpenSSL 1.0.1u [22 Sep 2016]
+
+ * OCSP Status Request extension unbounded memory growth ([CVE-2016-6304])
+ * SWEET32 Mitigation ([CVE-2016-2183])
+ * OOB write in MDC2_Update() ([CVE-2016-6303])
+ * Malformed SHA512 ticket DoS ([CVE-2016-6302])
+ * OOB write in BN_bn2dec() ([CVE-2016-2182])
+ * OOB read in TS_OBJ_print_bio() ([CVE-2016-2180])
+ * Pointer arithmetic undefined behaviour ([CVE-2016-2177])
+ * Constant time flag not preserved in DSA signing ([CVE-2016-2178])
+ * DTLS buffered message DoS ([CVE-2016-2179])
+ * DTLS replay protection DoS ([CVE-2016-2181])
+ * Certificate message OOB reads ([CVE-2016-6306])
+
+### Major changes between OpenSSL 1.0.1s and OpenSSL 1.0.1t [3 May 2016]
+
+ * Prevent padding oracle in AES-NI CBC MAC check ([CVE-2016-2107])
+ * Fix EVP_EncodeUpdate overflow ([CVE-2016-2105])
+ * Fix EVP_EncryptUpdate overflow ([CVE-2016-2106])
+ * Prevent ASN.1 BIO excessive memory allocation ([CVE-2016-2109])
+ * EBCDIC overread ([CVE-2016-2176])
+ * Modify behavior of ALPN to invoke callback after SNI/servername
+ callback, such that updates to the SSL_CTX affect ALPN.
+ * Remove LOW from the DEFAULT cipher list. This removes singles DES from
+ the default.
+ * Only remove the SSLv2 methods with the no-ssl2-method option.
+
+### Major changes between OpenSSL 1.0.1r and OpenSSL 1.0.1s [1 Mar 2016]
+
+ * Disable weak ciphers in SSLv3 and up in default builds of OpenSSL.
+ * Disable SSLv2 default build, default negotiation and weak ciphers
+ ([CVE-2016-0800])
+ * Fix a double-free in DSA code ([CVE-2016-0705])
+ * Disable SRP fake user seed to address a server memory leak
+ ([CVE-2016-0798])
+ * Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption
+ ([CVE-2016-0797])
+ * Fix memory issues in BIO_*printf functions ([CVE-2016-0799])
+ * Fix side channel attack on modular exponentiation ([CVE-2016-0702])
+
+### Major changes between OpenSSL 1.0.1q and OpenSSL 1.0.1r [28 Jan 2016]
+
+ * Protection for DH small subgroup attacks
+ * SSLv2 doesn't block disabled ciphers ([CVE-2015-3197])
+
+### Major changes between OpenSSL 1.0.1p and OpenSSL 1.0.1q [3 Dec 2015]
+
+ * Certificate verify crash with missing PSS parameter ([CVE-2015-3194])
+ * X509_ATTRIBUTE memory leak ([CVE-2015-3195])
+ * Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs
+ * In DSA_generate_parameters_ex, if the provided seed is too short,
+ return an error
+
+### Major changes between OpenSSL 1.0.1o and OpenSSL 1.0.1p [9 Jul 2015]
+
+ * Alternate chains certificate forgery ([CVE-2015-1793])
+ * Race condition handling PSK identify hint ([CVE-2015-3196])
+
+### Major changes between OpenSSL 1.0.1n and OpenSSL 1.0.1o [12 Jun 2015]
+
+ * Fix HMAC ABI incompatibility
+
+### Major changes between OpenSSL 1.0.1m and OpenSSL 1.0.1n [11 Jun 2015]
+
+ * Malformed ECParameters causes infinite loop ([CVE-2015-1788])
+ * Exploitable out-of-bounds read in X509_cmp_time ([CVE-2015-1789])
+ * PKCS7 crash with missing EnvelopedContent ([CVE-2015-1790])
+ * CMS verify infinite loop with unknown hash function ([CVE-2015-1792])
+ * Race condition handling NewSessionTicket ([CVE-2015-1791])
+
+### Major changes between OpenSSL 1.0.1l and OpenSSL 1.0.1m [19 Mar 2015]
+
+ * Segmentation fault in ASN1_TYPE_cmp fix ([CVE-2015-0286])
+ * ASN.1 structure reuse memory corruption fix ([CVE-2015-0287])
+ * PKCS7 NULL pointer dereferences fix ([CVE-2015-0289])
+ * DoS via reachable assert in SSLv2 servers fix ([CVE-2015-0293])
+ * Use After Free following d2i_ECPrivatekey error fix ([CVE-2015-0209])
+ * X509_to_X509_REQ NULL pointer deref fix ([CVE-2015-0288])
+ * Removed the export ciphers from the DEFAULT ciphers
+
+### Major changes between OpenSSL 1.0.1k and OpenSSL 1.0.1l [15 Jan 2015]
+
+ * Build fixes for the Windows and OpenVMS platforms
+
+### Major changes between OpenSSL 1.0.1j and OpenSSL 1.0.1k [8 Jan 2015]
+
+ * Fix for [CVE-2014-3571]
+ * Fix for [CVE-2015-0206]
+ * Fix for [CVE-2014-3569]
+ * Fix for [CVE-2014-3572]
+ * Fix for [CVE-2015-0204]
+ * Fix for [CVE-2015-0205]
+ * Fix for [CVE-2014-8275]
+ * Fix for [CVE-2014-3570]
+
+### Major changes between OpenSSL 1.0.1i and OpenSSL 1.0.1j [15 Oct 2014]
+
+ * Fix for [CVE-2014-3513]
+ * Fix for [CVE-2014-3567]
+ * Mitigation for [CVE-2014-3566] (SSL protocol vulnerability)
+ * Fix for [CVE-2014-3568]
+
+### Major changes between OpenSSL 1.0.1h and OpenSSL 1.0.1i [6 Aug 2014]
+
+ * Fix for [CVE-2014-3512]
+ * Fix for [CVE-2014-3511]
+ * Fix for [CVE-2014-3510]
+ * Fix for [CVE-2014-3507]
+ * Fix for [CVE-2014-3506]
+ * Fix for [CVE-2014-3505]
+ * Fix for [CVE-2014-3509]
+ * Fix for [CVE-2014-5139]
+ * Fix for [CVE-2014-3508]
+
+### Major changes between OpenSSL 1.0.1g and OpenSSL 1.0.1h [5 Jun 2014]
+
+ * Fix for [CVE-2014-0224]
+ * Fix for [CVE-2014-0221]
+ * Fix for [CVE-2014-0198]
+ * Fix for [CVE-2014-0195]
+ * Fix for [CVE-2014-3470]
+ * Fix for [CVE-2010-5298]
+
+### Major changes between OpenSSL 1.0.1f and OpenSSL 1.0.1g [7 Apr 2014]
+
+ * Fix for [CVE-2014-0160]
+ * Add TLS padding extension workaround for broken servers.
+ * Fix for [CVE-2014-0076]
+
+### Major changes between OpenSSL 1.0.1e and OpenSSL 1.0.1f [6 Jan 2014]
+
+ * Don't include gmt_unix_time in TLS server and client random values
+ * Fix for TLS record tampering bug ([CVE-2013-4353])
+ * Fix for TLS version checking bug ([CVE-2013-6449])
+ * Fix for DTLS retransmission bug ([CVE-2013-6450])
+
+### Major changes between OpenSSL 1.0.1d and OpenSSL 1.0.1e [11 Feb 2013]
+
+ * Corrected fix for ([CVE-2013-0169])
+
+### Major changes between OpenSSL 1.0.1c and OpenSSL 1.0.1d [4 Feb 2013]
+
+ * Fix renegotiation in TLS 1.1, 1.2 by using the correct TLS version.
+ * Include the fips configuration module.
+ * Fix OCSP bad key DoS attack ([CVE-2013-0166])
+ * Fix for SSL/TLS/DTLS CBC plaintext recovery attack ([CVE-2013-0169])
+ * Fix for TLS AESNI record handling flaw ([CVE-2012-2686])
+
+### Major changes between OpenSSL 1.0.1b and OpenSSL 1.0.1c [10 May 2012]
+
+ * Fix TLS/DTLS record length checking bug ([CVE-2012-2333])
+ * Don't attempt to use non-FIPS composite ciphers in FIPS mode.
+
+### Major changes between OpenSSL 1.0.1a and OpenSSL 1.0.1b [26 Apr 2012]
+
+ * Fix compilation error on non-x86 platforms.
+ * Make FIPS capable OpenSSL ciphers work in non-FIPS mode.
+ * Fix SSL_OP_NO_TLSv1_1 clash with SSL_OP_ALL in OpenSSL 1.0.0
+
+### Major changes between OpenSSL 1.0.1 and OpenSSL 1.0.1a [19 Apr 2012]
+
+ * Fix for ASN1 overflow bug ([CVE-2012-2110])
+ * Workarounds for some servers that hang on long client hellos.
+ * Fix SEGV in AES code.
+
+### Major changes between OpenSSL 1.0.0h and OpenSSL 1.0.1 [14 Mar 2012]
+
+ * TLS/DTLS heartbeat support.
+ * SCTP support.
+ * RFC 5705 TLS key material exporter.
+ * RFC 5764 DTLS-SRTP negotiation.
+ * Next Protocol Negotiation.
+ * PSS signatures in certificates, requests and CRLs.
+ * Support for password based recipient info for CMS.
+ * Support TLS v1.2 and TLS v1.1.
+ * Preliminary FIPS capability for unvalidated 2.0 FIPS module.
+ * SRP support.
+
+OpenSSL 1.0.0
+-------------
+
+### Major changes between OpenSSL 1.0.0s and OpenSSL 1.0.0t [3 Dec 2015]
+
+ * X509_ATTRIBUTE memory leak (([CVE-2015-3195]))
+ * Race condition handling PSK identify hint ([CVE-2015-3196])
+
+### Major changes between OpenSSL 1.0.0r and OpenSSL 1.0.0s [11 Jun 2015]
+
+ * Malformed ECParameters causes infinite loop ([CVE-2015-1788])
+ * Exploitable out-of-bounds read in X509_cmp_time ([CVE-2015-1789])
+ * PKCS7 crash with missing EnvelopedContent ([CVE-2015-1790])
+ * CMS verify infinite loop with unknown hash function ([CVE-2015-1792])
+ * Race condition handling NewSessionTicket ([CVE-2015-1791])
+
+### Major changes between OpenSSL 1.0.0q and OpenSSL 1.0.0r [19 Mar 2015]
+
+ * Segmentation fault in ASN1_TYPE_cmp fix ([CVE-2015-0286])
+ * ASN.1 structure reuse memory corruption fix ([CVE-2015-0287])
+ * PKCS7 NULL pointer dereferences fix ([CVE-2015-0289])
+ * DoS via reachable assert in SSLv2 servers fix ([CVE-2015-0293])
+ * Use After Free following d2i_ECPrivatekey error fix ([CVE-2015-0209])
+ * X509_to_X509_REQ NULL pointer deref fix ([CVE-2015-0288])
+ * Removed the export ciphers from the DEFAULT ciphers
+
+### Major changes between OpenSSL 1.0.0p and OpenSSL 1.0.0q [15 Jan 2015]
+
+ * Build fixes for the Windows and OpenVMS platforms
+
+### Major changes between OpenSSL 1.0.0o and OpenSSL 1.0.0p [8 Jan 2015]
+
+ * Fix for [CVE-2014-3571]
+ * Fix for [CVE-2015-0206]
+ * Fix for [CVE-2014-3569]
+ * Fix for [CVE-2014-3572]
+ * Fix for [CVE-2015-0204]
+ * Fix for [CVE-2015-0205]
+ * Fix for [CVE-2014-8275]
+ * Fix for [CVE-2014-3570]
+
+### Major changes between OpenSSL 1.0.0n and OpenSSL 1.0.0o [15 Oct 2014]
+
+ * Fix for [CVE-2014-3513]
+ * Fix for [CVE-2014-3567]
+ * Mitigation for [CVE-2014-3566] (SSL protocol vulnerability)
+ * Fix for [CVE-2014-3568]
+
+### Major changes between OpenSSL 1.0.0m and OpenSSL 1.0.0n [6 Aug 2014]
+
+ * Fix for [CVE-2014-3510]
+ * Fix for [CVE-2014-3507]
+ * Fix for [CVE-2014-3506]
+ * Fix for [CVE-2014-3505]
+ * Fix for [CVE-2014-3509]
+ * Fix for [CVE-2014-3508]
+
+ Known issues in OpenSSL 1.0.0m:
+
+ * EAP-FAST and other applications using tls_session_secret_cb
+ won't resume sessions. Fixed in 1.0.0n-dev
+ * Compilation failure of s3_pkt.c on some platforms due to missing
+ `<limits.h>` include. Fixed in 1.0.0n-dev
+
+### Major changes between OpenSSL 1.0.0l and OpenSSL 1.0.0m [5 Jun 2014]
+
+ * Fix for [CVE-2014-0224]
+ * Fix for [CVE-2014-0221]
+ * Fix for [CVE-2014-0198]
+ * Fix for [CVE-2014-0195]
+ * Fix for [CVE-2014-3470]
+ * Fix for [CVE-2014-0076]
+ * Fix for [CVE-2010-5298]
+
+### Major changes between OpenSSL 1.0.0k and OpenSSL 1.0.0l [6 Jan 2014]
+
+ * Fix for DTLS retransmission bug ([CVE-2013-6450])
+
+### Major changes between OpenSSL 1.0.0j and OpenSSL 1.0.0k [5 Feb 2013]
+
+ * Fix for SSL/TLS/DTLS CBC plaintext recovery attack ([CVE-2013-0169])
+ * Fix OCSP bad key DoS attack ([CVE-2013-0166])
+
+### Major changes between OpenSSL 1.0.0i and OpenSSL 1.0.0j [10 May 2012]
+
+ * Fix DTLS record length checking bug ([CVE-2012-2333])
+
+### Major changes between OpenSSL 1.0.0h and OpenSSL 1.0.0i [19 Apr 2012]
+
+ * Fix for ASN1 overflow bug ([CVE-2012-2110])
+
+### Major changes between OpenSSL 1.0.0g and OpenSSL 1.0.0h [12 Mar 2012]
+
+ * Fix for CMS/PKCS#7 MMA ([CVE-2012-0884])
+ * Corrected fix for ([CVE-2011-4619])
+ * Various DTLS fixes.
+
+### Major changes between OpenSSL 1.0.0f and OpenSSL 1.0.0g [18 Jan 2012]
+
+ * Fix for DTLS DoS issue ([CVE-2012-0050])
+
+### Major changes between OpenSSL 1.0.0e and OpenSSL 1.0.0f [4 Jan 2012]
+
+ * Fix for DTLS plaintext recovery attack ([CVE-2011-4108])
+ * Clear block padding bytes of SSL 3.0 records ([CVE-2011-4576])
+ * Only allow one SGC handshake restart for SSL/TLS ([CVE-2011-4619])
+ * Check parameters are not NULL in GOST ENGINE ([CVE-2012-0027])
+ * Check for malformed RFC3779 data ([CVE-2011-4577])
+
+### Major changes between OpenSSL 1.0.0d and OpenSSL 1.0.0e [6 Sep 2011]
+
+ * Fix for CRL vulnerability issue ([CVE-2011-3207])
+ * Fix for ECDH crashes ([CVE-2011-3210])
+ * Protection against EC timing attacks.
+ * Support ECDH ciphersuites for certificates using SHA2 algorithms.
+ * Various DTLS fixes.
+
+### Major changes between OpenSSL 1.0.0c and OpenSSL 1.0.0d [8 Feb 2011]
+
+ * Fix for security issue ([CVE-2011-0014])
+
+### Major changes between OpenSSL 1.0.0b and OpenSSL 1.0.0c [2 Dec 2010]
+
+ * Fix for security issue ([CVE-2010-4180])
+ * Fix for ([CVE-2010-4252])
+ * Fix mishandling of absent EC point format extension.
+ * Fix various platform compilation issues.
+ * Corrected fix for security issue ([CVE-2010-3864]).
+
+### Major changes between OpenSSL 1.0.0a and OpenSSL 1.0.0b [16 Nov 2010]
+
+ * Fix for security issue ([CVE-2010-3864]).
+ * Fix for ([CVE-2010-2939])
+ * Fix WIN32 build system for GOST ENGINE.
+
+### Major changes between OpenSSL 1.0.0 and OpenSSL 1.0.0a [1 Jun 2010]
+
+ * Fix for security issue ([CVE-2010-1633]).
+ * GOST MAC and CFB fixes.
+
+### Major changes between OpenSSL 0.9.8n and OpenSSL 1.0.0 [29 Mar 2010]
+
+ * RFC3280 path validation: sufficient to process PKITS tests.
+ * Integrated support for PVK files and keyblobs.
+ * Change default private key format to PKCS#8.
+ * CMS support: able to process all examples in RFC4134
+ * Streaming ASN1 encode support for PKCS#7 and CMS.
+ * Multiple signer and signer add support for PKCS#7 and CMS.
+ * ASN1 printing support.
+ * Whirlpool hash algorithm added.
+ * RFC3161 time stamp support.
+ * New generalised public key API supporting ENGINE based algorithms.
+ * New generalised public key API utilities.
+ * New ENGINE supporting GOST algorithms.
+ * SSL/TLS GOST ciphersuite support.
+ * PKCS#7 and CMS GOST support.
+ * RFC4279 PSK ciphersuite support.
+ * Supported points format extension for ECC ciphersuites.
+ * ecdsa-with-SHA224/256/384/512 signature types.
+ * dsa-with-SHA224 and dsa-with-SHA256 signature types.
+ * Opaque PRF Input TLS extension support.
+ * Updated time routines to avoid OS limitations.
+
+OpenSSL 0.9.x
+-------------
+
+### Major changes between OpenSSL 0.9.8m and OpenSSL 0.9.8n [24 Mar 2010]
+
+ * CFB cipher definition fixes.
+ * Fix security issues [CVE-2010-0740] and [CVE-2010-0433].
+
+### Major changes between OpenSSL 0.9.8l and OpenSSL 0.9.8m [25 Feb 2010]
+
+ * Cipher definition fixes.
+ * Workaround for slow RAND_poll() on some WIN32 versions.
+ * Remove MD2 from algorithm tables.
+ * SPKAC handling fixes.
+ * Support for RFC5746 TLS renegotiation extension.
+ * Compression memory leak fixed.
+ * Compression session resumption fixed.
+ * Ticket and SNI coexistence fixes.
+ * Many fixes to DTLS handling.
+
+### Major changes between OpenSSL 0.9.8k and OpenSSL 0.9.8l [5 Nov 2009]
+
+ * Temporary work around for [CVE-2009-3555]: disable renegotiation.
+
+### Major changes between OpenSSL 0.9.8j and OpenSSL 0.9.8k [25 Mar 2009]
+
+ * Fix various build issues.
+ * Fix security issues [CVE-2009-0590], [CVE-2009-0591], [CVE-2009-0789]
+
+### Major changes between OpenSSL 0.9.8i and OpenSSL 0.9.8j [7 Jan 2009]
+
+ * Fix security issue ([CVE-2008-5077])
+ * Merge FIPS 140-2 branch code.
+
+### Major changes between OpenSSL 0.9.8g and OpenSSL 0.9.8h [28 May 2008]
+
+ * CryptoAPI ENGINE support.
+ * Various precautionary measures.
+ * Fix for bugs affecting certificate request creation.
+ * Support for local machine keyset attribute in PKCS#12 files.
+
+### Major changes between OpenSSL 0.9.8f and OpenSSL 0.9.8g [19 Oct 2007]
+
+ * Backport of CMS functionality to 0.9.8.
+ * Fixes for bugs introduced with 0.9.8f.
+
+### Major changes between OpenSSL 0.9.8e and OpenSSL 0.9.8f [11 Oct 2007]
+
+ * Add gcc 4.2 support.
+ * Add support for AES and SSE2 assembly language optimization
+ for VC++ build.
+ * Support for RFC4507bis and server name extensions if explicitly
+ selected at compile time.
+ * DTLS improvements.
+ * RFC4507bis support.
+ * TLS Extensions support.
+
+### Major changes between OpenSSL 0.9.8d and OpenSSL 0.9.8e [23 Feb 2007]
+
+ * Various ciphersuite selection fixes.
+ * RFC3779 support.
+
+### Major changes between OpenSSL 0.9.8c and OpenSSL 0.9.8d [28 Sep 2006]
+
+ * Introduce limits to prevent malicious key DoS ([CVE-2006-2940])
+ * Fix security issues [CVE-2006-2937], [CVE-2006-3737], [CVE-2006-4343]
+ * Changes to ciphersuite selection algorithm
+
+### Major changes between OpenSSL 0.9.8b and OpenSSL 0.9.8c [5 Sep 2006]
+
+ * Fix Daniel Bleichenbacher forged signature attack, [CVE-2006-4339]
+ * New cipher Camellia
+
+### Major changes between OpenSSL 0.9.8a and OpenSSL 0.9.8b [4 May 2006]
+
+ * Cipher string fixes.
+ * Fixes for VC++ 2005.
+ * Updated ECC cipher suite support.
+ * New functions EVP_CIPHER_CTX_new() and EVP_CIPHER_CTX_free().
+ * Zlib compression usage fixes.
+ * Built in dynamic engine compilation support on Win32.
+ * Fixes auto dynamic engine loading in Win32.
+
+### Major changes between OpenSSL 0.9.8 and OpenSSL 0.9.8a [11 Oct 2005]
+
+ * Fix potential SSL 2.0 rollback ([CVE-2005-2969])
+ * Extended Windows CE support
+
+### Major changes between OpenSSL 0.9.7g and OpenSSL 0.9.8 [5 Jul 2005]
+
+ * Major work on the BIGNUM library for higher efficiency and to
+ make operations more streamlined and less contradictory. This
+ is the result of a major audit of the BIGNUM library.
+ * Addition of BIGNUM functions for fields GF(2^m) and NIST
+ curves, to support the Elliptic Crypto functions.
+ * Major work on Elliptic Crypto; ECDH and ECDSA added, including
+ the use through EVP, X509 and ENGINE.
+ * New ASN.1 mini-compiler that's usable through the OpenSSL
+ configuration file.
+ * Added support for ASN.1 indefinite length constructed encoding.
+ * New PKCS#12 'medium level' API to manipulate PKCS#12 files.
+ * Complete rework of shared library construction and linking
+ programs with shared or static libraries, through a separate
+ Makefile.shared.
+ * Rework of the passing of parameters from one Makefile to another.
+ * Changed ENGINE framework to load dynamic engine modules
+ automatically from specifically given directories.
+ * New structure and ASN.1 functions for CertificatePair.
+ * Changed the ZLIB compression method to be stateful.
+ * Changed the key-generation and primality testing "progress"
+ mechanism to take a structure that contains the ticker
+ function and an argument.
+ * New engine module: GMP (performs private key exponentiation).
+ * New engine module: VIA PadLOck ACE extension in VIA C3
+ Nehemiah processors.
+ * Added support for IPv6 addresses in certificate extensions.
+ See RFC 1884, section 2.2.
+ * Added support for certificate policy mappings, policy
+ constraints and name constraints.
+ * Added support for multi-valued AVAs in the OpenSSL
+ configuration file.
+ * Added support for multiple certificates with the same subject
+ in the 'openssl ca' index file.
+ * Make it possible to create self-signed certificates using
+ 'openssl ca -selfsign'.
+ * Make it possible to generate a serial number file with
+ 'openssl ca -create_serial'.
+ * New binary search functions with extended functionality.
+ * New BUF functions.
+ * New STORE structure and library to provide an interface to all
+ sorts of data repositories. Supports storage of public and
+ private keys, certificates, CRLs, numbers and arbitrary blobs.
+ This library is unfortunately unfinished and unused within
+ OpenSSL.
+ * New control functions for the error stack.
+ * Changed the PKCS#7 library to support one-pass S/MIME
+ processing.
+ * Added the possibility to compile without old deprecated
+ functionality with the OPENSSL_NO_DEPRECATED macro or the
+ 'no-deprecated' argument to the config and Configure scripts.
+ * Constification of all ASN.1 conversion functions, and other
+ affected functions.
+ * Improved platform support for PowerPC.
+ * New FIPS 180-2 algorithms (SHA-224, -256, -384 and -512).
+ * New X509_VERIFY_PARAM structure to support parameterisation
+ of X.509 path validation.
+ * Major overhaul of RC4 performance on Intel P4, IA-64 and
+ AMD64.
+ * Changed the Configure script to have some algorithms disabled
+ by default. Those can be explicitly enabled with the new
+ argument form 'enable-xxx'.
+ * Change the default digest in 'openssl' commands from MD5 to
+ SHA-1.
+ * Added support for DTLS.
+ * New BIGNUM blinding.
+ * Added support for the RSA-PSS encryption scheme
+ * Added support for the RSA X.931 padding.
+ * Added support for BSD sockets on NetWare.
+ * Added support for files larger than 2GB.
+ * Added initial support for Win64.
+ * Added alternate pkg-config files.
+
+### Major changes between OpenSSL 0.9.7l and OpenSSL 0.9.7m [23 Feb 2007]
+
+ * FIPS 1.1.1 module linking.
+ * Various ciphersuite selection fixes.
+
+### Major changes between OpenSSL 0.9.7k and OpenSSL 0.9.7l [28 Sep 2006]
+
+ * Introduce limits to prevent malicious key DoS ([CVE-2006-2940])
+ * Fix security issues [CVE-2006-2937], [CVE-2006-3737], [CVE-2006-4343]
+
+### Major changes between OpenSSL 0.9.7j and OpenSSL 0.9.7k [5 Sep 2006]
+
+ * Fix Daniel Bleichenbacher forged signature attack, [CVE-2006-4339]
+
+### Major changes between OpenSSL 0.9.7i and OpenSSL 0.9.7j [4 May 2006]
+
+ * Visual C++ 2005 fixes.
+ * Update Windows build system for FIPS.
+
+### Major changes between OpenSSL 0.9.7h and OpenSSL 0.9.7i [14 Oct 2005]
+
+ * Give EVP_MAX_MD_SIZE its old value, except for a FIPS build.
+
+### Major changes between OpenSSL 0.9.7g and OpenSSL 0.9.7h [11 Oct 2005]
+
+ * Fix SSL 2.0 Rollback ([CVE-2005-2969])
+ * Allow use of fixed-length exponent on DSA signing
+ * Default fixed-window RSA, DSA, DH private-key operations
+
+### Major changes between OpenSSL 0.9.7f and OpenSSL 0.9.7g [11 Apr 2005]
+
+ * More compilation issues fixed.
+ * Adaptation to more modern Kerberos API.
+ * Enhanced or corrected configuration for Solaris64, Mingw and Cygwin.
+ * Enhanced x86_64 assembler BIGNUM module.
+ * More constification.
+ * Added processing of proxy certificates (RFC 3820).
+
+### Major changes between OpenSSL 0.9.7e and OpenSSL 0.9.7f [22 Mar 2005]
+
+ * Several compilation issues fixed.
+ * Many memory allocation failure checks added.
+ * Improved comparison of X509 Name type.
+ * Mandatory basic checks on certificates.
+ * Performance improvements.
+
+### Major changes between OpenSSL 0.9.7d and OpenSSL 0.9.7e [25 Oct 2004]
+
+ * Fix race condition in CRL checking code.
+ * Fixes to PKCS#7 (S/MIME) code.
+
+### Major changes between OpenSSL 0.9.7c and OpenSSL 0.9.7d [17 Mar 2004]
+
+ * Security: Fix Kerberos ciphersuite SSL/TLS handshaking bug
+ * Security: Fix null-pointer assignment in do_change_cipher_spec()
+ * Allow multiple active certificates with same subject in CA index
+ * Multiple X509 verification fixes
+ * Speed up HMAC and other operations
+
+### Major changes between OpenSSL 0.9.7b and OpenSSL 0.9.7c [30 Sep 2003]
+
+ * Security: fix various ASN1 parsing bugs.
+ * New -ignore_err option to OCSP utility.
+ * Various interop and bug fixes in S/MIME code.
+ * SSL/TLS protocol fix for unrequested client certificates.
+
+### Major changes between OpenSSL 0.9.7a and OpenSSL 0.9.7b [10 Apr 2003]
+
+ * Security: counter the Klima-Pokorny-Rosa extension of
+ Bleichbacher's attack
+ * Security: make RSA blinding default.
+ * Configuration: Irix fixes, AIX fixes, better mingw support.
+ * Support for new platforms: linux-ia64-ecc.
+ * Build: shared library support fixes.
+ * ASN.1: treat domainComponent correctly.
+ * Documentation: fixes and additions.
+
+### Major changes between OpenSSL 0.9.7 and OpenSSL 0.9.7a [19 Feb 2003]
+
+ * Security: Important security related bugfixes.
+ * Enhanced compatibility with MIT Kerberos.
+ * Can be built without the ENGINE framework.
+ * IA32 assembler enhancements.
+ * Support for new platforms: FreeBSD/IA64 and FreeBSD/Sparc64.
+ * Configuration: the no-err option now works properly.
+ * SSL/TLS: now handles manual certificate chain building.
+ * SSL/TLS: certain session ID malfunctions corrected.
+
+### Major changes between OpenSSL 0.9.6 and OpenSSL 0.9.7 [30 Dec 2002]
+
+ * New library section OCSP.
+ * Complete rewrite of ASN1 code.
+ * CRL checking in verify code and openssl utility.
+ * Extension copying in 'ca' utility.
+ * Flexible display options in 'ca' utility.
+ * Provisional support for international characters with UTF8.
+ * Support for external crypto devices ('engine') is no longer
+ a separate distribution.
+ * New elliptic curve library section.
+ * New AES (Rijndael) library section.
+ * Support for new platforms: Windows CE, Tandem OSS, A/UX, AIX 64-bit,
+ Linux x86_64, Linux 64-bit on Sparc v9
+ * Extended support for some platforms: VxWorks
+ * Enhanced support for shared libraries.
+ * Now only builds PIC code when shared library support is requested.
+ * Support for pkg-config.
+ * Lots of new manuals.
+ * Makes symbolic links to or copies of manuals to cover all described
+ functions.
+ * Change DES API to clean up the namespace (some applications link also
+ against libdes providing similar functions having the same name).
+ Provide macros for backward compatibility (will be removed in the
+ future).
+ * Unify handling of cryptographic algorithms (software and engine)
+ to be available via EVP routines for asymmetric and symmetric ciphers.
+ * NCONF: new configuration handling routines.
+ * Change API to use more 'const' modifiers to improve error checking
+ and help optimizers.
+ * Finally remove references to RSAref.
+ * Reworked parts of the BIGNUM code.
+ * Support for new engines: Broadcom ubsec, Accelerated Encryption
+ Processing, IBM 4758.
+ * A few new engines added in the demos area.
+ * Extended and corrected OID (object identifier) table.
+ * PRNG: query at more locations for a random device, automatic query for
+ EGD style random sources at several locations.
+ * SSL/TLS: allow optional cipher choice according to server's preference.
+ * SSL/TLS: allow server to explicitly set new session ids.
+ * SSL/TLS: support Kerberos cipher suites (RFC2712).
+ Only supports MIT Kerberos for now.
+ * SSL/TLS: allow more precise control of renegotiations and sessions.
+ * SSL/TLS: add callback to retrieve SSL/TLS messages.
+ * SSL/TLS: support AES cipher suites (RFC3268).
+
+### Major changes between OpenSSL 0.9.6j and OpenSSL 0.9.6k [30 Sep 2003]
+
+ * Security: fix various ASN1 parsing bugs.
+ * SSL/TLS protocol fix for unrequested client certificates.
+
+### Major changes between OpenSSL 0.9.6i and OpenSSL 0.9.6j [10 Apr 2003]
+
+ * Security: counter the Klima-Pokorny-Rosa extension of
+ Bleichbacher's attack
+ * Security: make RSA blinding default.
+ * Build: shared library support fixes.
+
+### Major changes between OpenSSL 0.9.6h and OpenSSL 0.9.6i [19 Feb 2003]
+
+ * Important security related bugfixes.
+
+### Major changes between OpenSSL 0.9.6g and OpenSSL 0.9.6h [5 Dec 2002]
+
+ * New configuration targets for Tandem OSS and A/UX.
+ * New OIDs for Microsoft attributes.
+ * Better handling of SSL session caching.
+ * Better comparison of distinguished names.
+ * Better handling of shared libraries in a mixed GNU/non-GNU environment.
+ * Support assembler code with Borland C.
+ * Fixes for length problems.
+ * Fixes for uninitialised variables.
+ * Fixes for memory leaks, some unusual crashes and some race conditions.
+ * Fixes for smaller building problems.
+ * Updates of manuals, FAQ and other instructive documents.
+
+### Major changes between OpenSSL 0.9.6f and OpenSSL 0.9.6g [9 Aug 2002]
+
+ * Important building fixes on Unix.
+
+### Major changes between OpenSSL 0.9.6e and OpenSSL 0.9.6f [8 Aug 2002]
+
+ * Various important bugfixes.
+
+### Major changes between OpenSSL 0.9.6d and OpenSSL 0.9.6e [30 Jul 2002]
+
+ * Important security related bugfixes.
+ * Various SSL/TLS library bugfixes.
+
+### Major changes between OpenSSL 0.9.6c and OpenSSL 0.9.6d [9 May 2002]
+
+ * Various SSL/TLS library bugfixes.
+ * Fix DH parameter generation for 'non-standard' generators.
+
+### Major changes between OpenSSL 0.9.6b and OpenSSL 0.9.6c [21 Dec 2001]
+
+ * Various SSL/TLS library bugfixes.
+ * BIGNUM library fixes.
+ * RSA OAEP and random number generation fixes.
+ * Object identifiers corrected and added.
+ * Add assembler BN routines for IA64.
+ * Add support for OS/390 Unix, UnixWare with gcc, OpenUNIX 8,
+ MIPS Linux; shared library support for Irix, HP-UX.
+ * Add crypto accelerator support for AEP, Baltimore SureWare,
+ Broadcom and Cryptographic Appliance's keyserver
+ [in 0.9.6c-engine release].
+
+### Major changes between OpenSSL 0.9.6a and OpenSSL 0.9.6b [9 Jul 2001]
+
+ * Security fix: PRNG improvements.
+ * Security fix: RSA OAEP check.
+ * Security fix: Reinsert and fix countermeasure to Bleichbacher's
+ attack.
+ * MIPS bug fix in BIGNUM.
+ * Bug fix in "openssl enc".
+ * Bug fix in X.509 printing routine.
+ * Bug fix in DSA verification routine and DSA S/MIME verification.
+ * Bug fix to make PRNG thread-safe.
+ * Bug fix in RAND_file_name().
+ * Bug fix in compatibility mode trust settings.
+ * Bug fix in blowfish EVP.
+ * Increase default size for BIO buffering filter.
+ * Compatibility fixes in some scripts.
+
+### Major changes between OpenSSL 0.9.6 and OpenSSL 0.9.6a [5 Apr 2001]
+
+ * Security fix: change behavior of OpenSSL to avoid using
+ environment variables when running as root.
+ * Security fix: check the result of RSA-CRT to reduce the
+ possibility of deducing the private key from an incorrectly
+ calculated signature.
+ * Security fix: prevent Bleichenbacher's DSA attack.
+ * Security fix: Zero the premaster secret after deriving the
+ master secret in DH ciphersuites.
+ * Reimplement SSL_peek(), which had various problems.
+ * Compatibility fix: the function des_encrypt() renamed to
+ des_encrypt1() to avoid clashes with some Unixen libc.
+ * Bug fixes for Win32, HP/UX and Irix.
+ * Bug fixes in BIGNUM, SSL, PKCS#7, PKCS#12, X.509, CONF and
+ memory checking routines.
+ * Bug fixes for RSA operations in threaded environments.
+ * Bug fixes in misc. openssl applications.
+ * Remove a few potential memory leaks.
+ * Add tighter checks of BIGNUM routines.
+ * Shared library support has been reworked for generality.
+ * More documentation.
+ * New function BN_rand_range().
+ * Add "-rand" option to openssl s_client and s_server.
+
+### Major changes between OpenSSL 0.9.5a and OpenSSL 0.9.6 [10 Oct 2000]
+
+ * Some documentation for BIO and SSL libraries.
+ * Enhanced chain verification using key identifiers.
+ * New sign and verify options to 'dgst' application.
+ * Support for DER and PEM encoded messages in 'smime' application.
+ * New 'rsautl' application, low-level RSA utility.
+ * MD4 now included.
+ * Bugfix for SSL rollback padding check.
+ * Support for external crypto devices [1].
+ * Enhanced EVP interface.
+
+ [1] The support for external crypto devices is currently a separate
+ distribution. See the file README-Engine.md.
+
+### Major changes between OpenSSL 0.9.5 and OpenSSL 0.9.5a [1 Apr 2000]
+
+ * Bug fixes for Win32, SuSE Linux, NeXTSTEP and FreeBSD 2.2.8
+ * Shared library support for HPUX and Solaris-gcc
+ * Support of Linux/IA64
+ * Assembler support for Mingw32
+ * New 'rand' application
+ * New way to check for existence of algorithms from scripts
+
+### Major changes between OpenSSL 0.9.4 and OpenSSL 0.9.5 [25 May 2000]
+
+ * S/MIME support in new 'smime' command
+ * Documentation for the OpenSSL command line application
+ * Automation of 'req' application
+ * Fixes to make s_client, s_server work under Windows
+ * Support for multiple fieldnames in SPKACs
+ * New SPKAC command line utility and associated library functions
+ * Options to allow passwords to be obtained from various sources
+ * New public key PEM format and options to handle it
+ * Many other fixes and enhancements to command line utilities
+ * Usable certificate chain verification
+ * Certificate purpose checking
+ * Certificate trust settings
+ * Support of authority information access extension
+ * Extensions in certificate requests
+ * Simplified X509 name and attribute routines
+ * Initial (incomplete) support for international character sets
+ * New DH_METHOD, DSA_METHOD and enhanced RSA_METHOD
+ * Read only memory BIOs and simplified creation function
+ * TLS/SSL protocol bugfixes: Accept TLS 'client hello' in SSL 3.0
+ record; allow fragmentation and interleaving of handshake and other
+ data
+ * TLS/SSL code now "tolerates" MS SGC
+ * Work around for Netscape client certificate hang bug
+ * RSA_NULL option that removes RSA patent code but keeps other
+ RSA functionality
+ * Memory leak detection now allows applications to add extra information
+ via a per-thread stack
+ * PRNG robustness improved
+ * EGD support
+ * BIGNUM library bug fixes
+ * Faster DSA parameter generation
+ * Enhanced support for Alpha Linux
+ * Experimental macOS support
+
+### Major changes between OpenSSL 0.9.3 and OpenSSL 0.9.4 [9 Aug 1999]
+
+ * Transparent support for PKCS#8 format private keys: these are used
+ by several software packages and are more secure than the standard
+ form
+ * PKCS#5 v2.0 implementation
+ * Password callbacks have a new void * argument for application data
+ * Avoid various memory leaks
+ * New pipe-like BIO that allows using the SSL library when actual I/O
+ must be handled by the application (BIO pair)
+
+### Major changes between OpenSSL 0.9.2b and OpenSSL 0.9.3 [24 May 1999]
+
+ * Lots of enhancements and cleanups to the Configuration mechanism
+ * RSA OEAP related fixes
+ * Added "openssl ca -revoke" option for revoking a certificate
+ * Source cleanups: const correctness, type-safe stacks and ASN.1 SETs
+ * Source tree cleanups: removed lots of obsolete files
+ * Thawte SXNet, certificate policies and CRL distribution points
+ extension support
+ * Preliminary (experimental) S/MIME support
+ * Support for ASN.1 UTF8String and VisibleString
+ * Full integration of PKCS#12 code
+ * Sparc assembler bignum implementation, optimized hash functions
+ * Option to disable selected ciphers
+
+### Major changes between OpenSSL 0.9.1c and OpenSSL 0.9.2b [22 Mar 1999]
+
+ * Fixed a security hole related to session resumption
+ * Fixed RSA encryption routines for the p < q case
+ * "ALL" in cipher lists now means "everything except NULL ciphers"
+ * Support for Triple-DES CBCM cipher
+ * Support of Optimal Asymmetric Encryption Padding (OAEP) for RSA
+ * First support for new TLSv1 ciphers
+ * Added a few new BIOs (syslog BIO, reliable BIO)
+ * Extended support for DSA certificate/keys.
+ * Extended support for Certificate Signing Requests (CSR)
+ * Initial support for X.509v3 extensions
+ * Extended support for compression inside the SSL record layer
+ * Overhauled Win32 builds
+ * Cleanups and fixes to the Big Number (BN) library
+ * Support for ASN.1 GeneralizedTime
+ * Splitted ASN.1 SETs from SEQUENCEs
+ * ASN1 and PEM support for Netscape Certificate Sequences
+ * Overhauled Perl interface
+ * Lots of source tree cleanups.
+ * Lots of memory leak fixes.
+ * Lots of bug fixes.
+
+### Major changes between SSLeay 0.9.0b and OpenSSL 0.9.1c [23 Dec 1998]
+
+ * Integration of the popular NO_RSA/NO_DSA patches
+ * Initial support for compression inside the SSL record layer
+ * Added BIO proxy and filtering functionality
+ * Extended Big Number (BN) library
+ * Added RIPE MD160 message digest
+ * Added support for RC2/64bit cipher
+ * Extended ASN.1 parser routines
+ * Adjustments of the source tree for CVS
+ * Support for various new platforms
+
+<!-- Links -->
+[CVE-2023-0401]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0401
+[CVE-2023-0286]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0286
+[CVE-2023-0217]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0217
+[CVE-2023-0216]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0216
+[CVE-2023-0215]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0215
+[CVE-2022-4450]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4450
+[CVE-2022-4304]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4304
+[CVE-2022-4203]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4203
+[CVE-2022-3996]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-3996
+[CVE-2022-2274]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-2274
+[CVE-2022-2097]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-2274
+[CVE-2020-1971]: https://www.openssl.org/news/vulnerabilities.html#CVE-2020-1971
+[CVE-2020-1967]: https://www.openssl.org/news/vulnerabilities.html#CVE-2020-1967
+[CVE-2019-1563]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1563
+[CVE-2019-1559]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1559
+[CVE-2019-1552]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1552
+[CVE-2019-1551]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1551
+[CVE-2019-1549]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1549
+[CVE-2019-1547]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1547
+[CVE-2019-1543]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1543
+[CVE-2018-5407]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-5407
+[CVE-2018-0739]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0739
+[CVE-2018-0737]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0737
+[CVE-2018-0735]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0735
+[CVE-2018-0734]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0734
+[CVE-2018-0733]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0733
+[CVE-2018-0732]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0732
+[CVE-2017-3738]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3738
+[CVE-2017-3737]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3737
+[CVE-2017-3736]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3736
+[CVE-2017-3735]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3735
+[CVE-2017-3733]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3733
+[CVE-2017-3732]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3732
+[CVE-2017-3731]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3731
+[CVE-2017-3730]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3730
+[CVE-2016-7055]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7055
+[CVE-2016-7054]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7054
+[CVE-2016-7053]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7053
+[CVE-2016-7052]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7052
+[CVE-2016-6309]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6309
+[CVE-2016-6308]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6308
+[CVE-2016-6307]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6307
+[CVE-2016-6306]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6306
+[CVE-2016-6305]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6305
+[CVE-2016-6304]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6304
+[CVE-2016-6303]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6303
+[CVE-2016-6302]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6302
+[CVE-2016-2183]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2183
+[CVE-2016-2182]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2182
+[CVE-2016-2181]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2181
+[CVE-2016-2180]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2180
+[CVE-2016-2179]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2179
+[CVE-2016-2178]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2178
+[CVE-2016-2177]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2177
+[CVE-2016-2176]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2176
+[CVE-2016-2109]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2109
+[CVE-2016-2107]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2107
+[CVE-2016-2106]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2106
+[CVE-2016-2105]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2105
+[CVE-2016-0800]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0800
+[CVE-2016-0799]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0799
+[CVE-2016-0798]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0798
+[CVE-2016-0797]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0797
+[CVE-2016-0705]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0705
+[CVE-2016-0702]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0702
+[CVE-2016-0701]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0701
+[CVE-2015-3197]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3197
+[CVE-2015-3196]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3196
+[CVE-2015-3195]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3195
+[CVE-2015-3194]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3194
+[CVE-2015-3193]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3193
+[CVE-2015-1793]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1793
+[CVE-2015-1792]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1792
+[CVE-2015-1791]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1791
+[CVE-2015-1790]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1790
+[CVE-2015-1789]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1789
+[CVE-2015-1788]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1788
+[CVE-2015-1787]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1787
+[CVE-2015-0293]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0293
+[CVE-2015-0291]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0291
+[CVE-2015-0290]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0290
+[CVE-2015-0289]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0289
+[CVE-2015-0288]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0288
+[CVE-2015-0287]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0287
+[CVE-2015-0286]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0286
+[CVE-2015-0285]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0285
+[CVE-2015-0209]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0209
+[CVE-2015-0208]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0208
+[CVE-2015-0207]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0207
+[CVE-2015-0206]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0206
+[CVE-2015-0205]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0205
+[CVE-2015-0204]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0204
+[CVE-2014-8275]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-8275
+[CVE-2014-5139]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-5139
+[CVE-2014-3572]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3572
+[CVE-2014-3571]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3571
+[CVE-2014-3570]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3570
+[CVE-2014-3569]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3569
+[CVE-2014-3568]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3568
+[CVE-2014-3567]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3567
+[CVE-2014-3566]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3566
+[CVE-2014-3513]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3513
+[CVE-2014-3512]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3512
+[CVE-2014-3511]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3511
+[CVE-2014-3510]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3510
+[CVE-2014-3509]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3509
+[CVE-2014-3508]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3508
+[CVE-2014-3507]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3507
+[CVE-2014-3506]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3506
+[CVE-2014-3505]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3505
+[CVE-2014-3470]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3470
+[CVE-2014-0224]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0224
+[CVE-2014-0221]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0221
+[CVE-2014-0198]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0198
+[CVE-2014-0195]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0195
+[CVE-2014-0160]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0160
+[CVE-2014-0076]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0076
+[CVE-2013-6450]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-6450
+[CVE-2013-6449]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-6449
+[CVE-2013-4353]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-4353
+[CVE-2013-0169]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-0169
+[CVE-2013-0166]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-0166
+[CVE-2012-2686]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2686
+[CVE-2012-2333]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2333
+[CVE-2012-2110]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2110
+[CVE-2012-0884]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0884
+[CVE-2012-0050]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0050
+[CVE-2012-0027]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0027
+[CVE-2011-4619]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4619
+[CVE-2011-4577]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4577
+[CVE-2011-4576]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4576
+[CVE-2011-4108]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4108
+[CVE-2011-3210]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-3210
+[CVE-2011-3207]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-3207
+[CVE-2011-0014]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-0014
+[CVE-2010-5298]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-5298
+[CVE-2010-4252]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-4252
+[CVE-2010-4180]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-4180
+[CVE-2010-3864]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-3864
+[CVE-2010-2939]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-2939
+[CVE-2010-1633]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-1633
+[CVE-2010-0740]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-0740
+[CVE-2010-0433]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-0433
+[CVE-2009-3555]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-3555
+[CVE-2009-0789]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0789
+[CVE-2009-0591]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0591
+[CVE-2009-0590]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0590
+[CVE-2008-5077]: https://www.openssl.org/news/vulnerabilities.html#CVE-2008-5077
+[CVE-2006-4343]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-4343
+[CVE-2006-4339]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-4339
+[CVE-2006-3737]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-3737
+[CVE-2006-2940]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-2940
+[CVE-2006-2937]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-2937
+[CVE-2005-2969]: https://www.openssl.org/news/vulnerabilities.html#CVE-2005-2969
diff --git a/NOTES-ANDROID.md b/NOTES-ANDROID.md
new file mode 100644
index 000000000000..eebf03a4c496
--- /dev/null
+++ b/NOTES-ANDROID.md
@@ -0,0 +1,90 @@
+Notes for Android platforms
+===========================
+
+ Requirement details
+ -------------------
+
+ Beside basic tools like perl and make you'll need to download the Android
+ NDK. It's available for Linux, macOS and Windows, but only Linux
+ version was actually tested. There is no reason to believe that macOS
+ wouldn't work. And as for Windows, it's unclear which "shell" would be
+ suitable, MSYS2 might have best chances. NDK version should play lesser
+ role, the goal is to support a range of most recent versions.
+
+ Configuration
+ -------------
+
+ Android is a cross-compiled target and you can't rely on `./Configure`
+ to find out the configuration target for you. You have to name your
+ target explicitly; there are `android-arm`, `android-arm64`, `android-mips`,
+ `android-mip64`, `android-x86` and `android-x86_64` (`*MIPS` targets are no
+ longer supported with NDK R20+).
+
+ Do not pass --cross-compile-prefix (as you might be tempted), as it
+ will be "calculated" automatically based on chosen platform. However,
+ you still need to know the prefix to extend your PATH, in order to
+ invoke `$(CROSS_COMPILE)clang` [`*gcc` on NDK 19 and lower] and company.
+ (`./Configure` will fail and give you a hint if you get it wrong.)
+
+ Apart from `PATH` adjustment you need to set `ANDROID_NDK_ROOT` environment
+ to point at the `NDK` directory. If you're using a side-by-side NDK the path
+ will look something like `/some/where/android-sdk/ndk/<ver>`, and for a
+ standalone NDK the path will be something like `/some/where/android-ndk-<ver>`.
+ Both variables are significant at both configuration and compilation times.
+ The NDK customarily supports multiple Android API levels, e.g. `android-14`,
+ `android-21`, etc. By default latest API level is chosen. If you need to target
+ an older platform pass the argument `-D__ANDROID_API__=N` to `Configure`,
+ with `N` being the numerical value of the target platform version. For example,
+ to compile for Android 10 arm64 with a side-by-side NDK r20.0.5594570
+
+ export ANDROID_NDK_ROOT=/home/whoever/Android/android-sdk/ndk/20.0.5594570
+ PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$PATH
+ ./Configure android-arm64 -D__ANDROID_API__=29
+ make
+
+ Older versions of the NDK have GCC under their common prebuilt tools
+ directory, so the bin path will be slightly different. EG: to compile
+ for ICS on ARM with NDK 10d:
+
+ export ANDROID_NDK_ROOT=/some/where/android-ndk-10d
+ PATH=$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin:$PATH
+ ./Configure android-arm -D__ANDROID_API__=14
+ make
+
+ Caveat lector! Earlier OpenSSL versions relied on additional `CROSS_SYSROOT`
+ variable set to `$ANDROID_NDK_ROOT/platforms/android-<api>/arch-<arch>` to
+ appoint headers-n-libraries' location. It's still recognized in order
+ to facilitate migration from older projects. However, since API level
+ appears in `CROSS_SYSROOT` value, passing `-D__ANDROID_API__=N` can be in
+ conflict, and mixing the two is therefore not supported. Migration to
+ `CROSS_SYSROOT`-less setup is recommended.
+
+ One can engage clang by adjusting PATH to cover same NDK's clang. Just
+ keep in mind that if you miss it, Configure will try to use gcc...
+ Also, PATH would need even further adjustment to cover unprefixed, yet
+ target-specific, ar and ranlib. It's possible that you don't need to
+ bother, if binutils-multiarch is installed on your Linux system.
+
+ Another option is to create so called "standalone toolchain" tailored
+ for single specific platform including Android API level, and assign its
+ location to `ANDROID_NDK_ROOT`. In such case you have to pass matching
+ target name to Configure and shouldn't use `-D__ANDROID_API__=N`. `PATH`
+ adjustment becomes simpler, `$ANDROID_NDK_ROOT/bin:$PATH` suffices.
+
+ Running tests (on Linux)
+ ------------------------
+
+ This is not actually supported. Notes are meant rather as inspiration.
+
+ Even though build output targets alien system, it's possible to execute
+ test suite on Linux system by employing qemu-user. The trick is static
+ linking. Pass -static to Configure, then edit generated Makefile and
+ remove occurrences of -ldl and -pie flags. You would also need to pick
+ API version that comes with usable static libraries, 42/2=21 used to
+ work. Once built, you should be able to
+
+ env EXE_SHELL=qemu-<arch> make test
+
+ If you need to pass additional flag to qemu, quotes are your friend, e.g.
+
+ env EXE_SHELL="qemu-mips64el -cpu MIPS64R6-generic" make test
diff --git a/NOTES-DJGPP.md b/NOTES-DJGPP.md
new file mode 100644
index 000000000000..0b23c48370b3
--- /dev/null
+++ b/NOTES-DJGPP.md
@@ -0,0 +1,46 @@
+Notes for the DOS platform with DJGPP
+=====================================
+
+ OpenSSL has been ported to DJGPP, a Unix look-alike 32-bit run-time
+ environment for 16-bit DOS, but only with long filename support.
+ If you wish to compile on native DOS with 8+3 filenames, you will
+ have to tweak the installation yourself, including renaming files
+ with illegal or duplicate names.
+
+ You should have a full DJGPP environment installed, including the
+ latest versions of DJGPP, GCC, BINUTILS, BASH, etc. This package
+ requires that PERL and the PERL module `Text::Template` also be
+ installed (see [NOTES-PERL.md](NOTES-PERL.md)).
+
+ All of these can be obtained from the usual DJGPP mirror sites or
+ directly at <http://www.delorie.com/pub/djgpp>. For help on which
+ files to download, see the DJGPP "ZIP PICKER" page at
+ <http://www.delorie.com/djgpp/zip-picker.html>. You also need to have
+ the WATT-32 networking package installed before you try to compile
+ OpenSSL. This can be obtained from <http://www.watt-32.net/>.
+ The Makefile assumes that the WATT-32 code is in the directory
+ specified by the environment variable WATT_ROOT. If you have watt-32
+ in directory `watt32` under your main DJGPP directory, specify
+ `WATT_ROOT="/dev/env/DJDIR/watt32"`.
+
+ To compile OpenSSL, start your BASH shell, then configure for DJGPP by
+ running `./Configure` with appropriate arguments:
+
+ ./Configure no-threads --prefix=/dev/env/DJDIR DJGPP
+
+ And finally fire up `make`. You may run out of DPMI selectors when
+ running in a DOS box under Windows. If so, just close the BASH
+ shell, go back to Windows, and restart BASH. Then run `make` again.
+
+ RUN-TIME CAVEAT LECTOR
+ --------------
+
+ Quoting FAQ:
+
+ "Cryptographic software needs a source of unpredictable data to work
+ correctly. Many open source operating systems provide a "randomness
+ device" (`/dev/urandom` or `/dev/random`) that serves this purpose."
+
+ As of version 0.9.7f DJGPP port checks upon `/dev/urandom$` for a 3rd
+ party "randomness" DOS driver. One such driver, `NOISE.SYS`, can be
+ obtained from <http://www.rahul.net/dkaufman/index.html>.
diff --git a/NOTES-NONSTOP.md b/NOTES-NONSTOP.md
new file mode 100644
index 000000000000..627843babf32
--- /dev/null
+++ b/NOTES-NONSTOP.md
@@ -0,0 +1,245 @@
+NOTES FOR THE HPE NONSTOP PLATFORM
+==============================
+
+Requirement details
+-------------------
+
+In addition to the requirements and instructions listed
+in [INSTALL.md](INSTALL.md), the following are required as well:
+
+ * The TNS/X platform supports hardware randomization.
+ Specify the `--with-rand-seed=rdcpu` option to the `./Configure` script.
+ This is recommended but not required. `egd` is supported at 3.0 but cannot
+ be used if FIPS is selected.
+ * The TNS/E platform does not support hardware randomization, so
+ specify the `--with-rand-seed=egd` option to the `./Configure` script.
+
+About c99 compiler
+------------------
+
+The c99 compiler is required for building OpenSSL from source. While c11
+may work, it has not been broadly tested. c99 is the only compiler
+prerequisite needed to build OpenSSL 3.0 on this platform. You should also
+have the FLOSS package installed on your system. The ITUGLIB FLOSS package
+is the only FLOSS variant that has been broadly tested.
+
+Threading Models
+----------------
+
+OpenSSL can be built using unthreaded, POSIX User Threads (PUT), or Standard
+POSIX Threads (SPT). Select the following build configuration for each on
+the TNS/X (L-Series) platform:
+
+ * `nonstop-nsx` or default will select an unthreaded build.
+ * `nonstop-nsx_put` selects the PUT build.
+ * `nonstop-nsx_64_put` selects the 64 bit file length PUT build.
+ * `nonstop-nsx_spt_floss` selects the SPT build with FLOSS. FLOSS is
+ required for SPT builds because of a known hang when using SPT on its own.
+
+### TNS/E Considerations
+
+The TNS/E platform is build using the same set of builds specifying `nse`
+instead of `nsx` in the set above.
+
+You cannot build for TNS/E for FIPS, so you must specify the `no-fips`
+option to `./Configure`.
+
+About Prefix and OpenSSLDir
+---------------------------
+
+Because there are many potential builds that must co-exist on any given
+NonStop node, managing the location of your build distribution is crucial.
+Keep each destination separate and distinct. Mixing any mode described in
+this document can cause application instability. The recommended approach
+is to specify the OpenSSL version and threading model in your configuration
+options, and keeping your memory and float options consistent, for example:
+
+ * For 1.1 `--prefix=/usr/local-ssl1.1 --openssldir=/usr/local-ssl1.1/ssl`
+ * For 1.1 PUT `--prefix=/usr/local-ssl1.1_put --openssldir=/usr/local-ssl1.1_put/ssl`
+
+As of 3.0, the NonStop configurations use the multilib attribute to distinguish
+between different models:
+
+ * For 3.0 `--prefix=/usr/local-ssl3.0 --openssldir=/usr/local-ssl3.0/ssl`
+
+The PUT model is placed in `${prefix}/lib-put` for 32-bit models and
+`${prefix}/lib64-put` for 64-bit models.
+
+Use the `_RLD_LIB_PATH` environment variable in OSS to select the appropriate
+directory containing `libcrypto.so` and `libssl.so`. In GUARDIAN, use the
+`=_RLD_LIB_PATH` search define to locate the GUARDIAN subvolume where OpenSSL
+is installed.
+
+Float Considerations
+--------------------
+
+OpenSSL is built using IEEE Float mode by default. If you need a different
+IEEE mode, create a new configuration specifying `tfloat-x86-64` (for Tandem
+Float) or `nfloat-x86-64` (for Neutral Float).
+
+Memory Models
+-------------
+
+The current OpenSSL default memory model uses the default platform address
+model. If you need a different address model, you must specify the appropriate
+c99 options for compile (`CFLAGS`) and linkers (`LDFLAGS`).
+
+Cross Compiling on Windows
+--------------------------
+
+To configure and compile OpenSSL, you will need to set up a Cygwin environment.
+The Cygwin tools should include bash, make, and any other normal tools required
+for building programs.
+
+Your `PATH` must include the bin directory for the c99 cross-compiler, as in:
+
+ export PATH=/cygdrive/c/Program\ Files\ \(x86\)/HPE\ NonStop/L16.05/usr/bin:$PATH
+
+This should be set before Configure is run. For the c99 cross-compiler to work
+correctly, you also need the `COMP_ROOT` set, as in:
+
+ export COMP_ROOT="C:\Program Files (x86)\HPE NonStop\L16.05"
+
+`COMP_ROOT` needs to be in Windows form.
+
+`Configure` must specify the `no-makedepend` option otherwise errors will
+result when running the build because the c99 cross-compiler does not support
+the `gcc -MT` option. An example of a `Configure` command to be run from the
+OpenSSL directory is:
+
+ ./Configure nonstop-nsx_64 no-makedepend --with-rand-seed=rdcpu
+
+Do not forget to include any OpenSSL cross-compiling prefix and certificate
+options when creating your libraries.
+
+The OpenSSL test suite will not run on your workstation. In order to verify the
+build, you will need to perform the build and test steps in OSS in your NonStop
+server. You can also build under gcc and run the test suite for Windows but that
+is not equivalent.
+
+**Note:** In the event that you are attempting a FIPS-compliant cross-compile,
+be aware that signatures may not match between builds done under OSS and under
+cross-compiles as the compilers do not necessarily generate identical objects.
+Anything and everything to do with FIPS is outside the scope of this document.
+Refer to the FIPS security policy for more information.
+
+The following build configurations have been successfully attempted at one
+point or another. If you are successful in your cross-compile efforts, please
+update this list:
+
+- nonstop-nsx_64
+- nonstop-nsx_64_put
+
+**Note:** Cross-compile builds for TNS/E have not been attempted, but should
+follow the same considerations as for TNS/X above. SPT builds generally require
+FLOSS, which is not available for workstation builds. As a result, SPT builds
+of OpenSSL cannot be cross-compiled.
+
+Also see the NSDEE discussion below for more historical information.
+
+Cross Compiling with NSDEE
+--------------------------
+
+**Note:** None of these builds have been tested by the platform maintainer and
+are supplied for historical value. Please submit a Pull Request to OpenSSL
+should these need to be adjusted.
+
+If you are attempting to build OpenSSL with NSDEE, you will need to specify
+the following variables. The following set of compiler defines are required:
+
+ # COMP_ROOT must be a full path for the build system (e.g. windows)
+ COMP_ROOT=$(cygpath -w /path/to/comp_root)
+ # CC must be executable by your shell
+ CC=/path/to/c99
+
+### Optional Build Variables
+
+ DBGFLAG="--debug"
+ CIPHENABLES="enable-ssl3 enable-ssl3-method enable-weak-ssl-ciphers enable-rc4"
+
+### Internal Known TNS/X to TNS/E Cross Compile Variables
+
+The following definition is required if you are building on TNS/X for TNS/E
+and have access to a TNS/E machine on your EXPAND network - with an example
+node named `\CS3`:
+
+ SYSTEMLIBS="-L/E/cs3/usr/local/lib"
+
+Version Procedure (VPROC) Considerations
+----------------------------------------
+
+If you require a VPROC entry for platform version identification, use the
+following variables:
+
+### For Itanium
+
+ OPENSSL_VPROC_PREFIX=T0085H06
+
+### For x86
+
+ OPENSSL_VPROC_PREFIX=T0085L01
+
+### Common Definition
+
+ export OPENSSL_VPROC=${OPENSSL_VPROC_PREFIX}_$(
+ . VERSION.dat
+ if [ -n "$PRE_RELEASE_TAG" ]; then
+ PRE_RELEASE_TAG="-$PRE_RELEASE_TAG"
+ fi
+ if [ -n "$BUILD_METADATA" ]; then
+ BUILD_METADATA="+$BUILD_METADATA"
+ fi
+ echo "$MAJOR.$MINOR.$PATCH$PRE_RELEASE_TAG$BUILD_METADATA" |\
+ sed -e 's/[-.+]/_/g'
+ )
+
+Example Configure Targets
+-------------------------
+
+For OSS targets, the main DLL names will be `libssl.so` and `libcrypto.so`.
+For GUARDIAN targets, DLL names will be `ssl` and `crypto`. The following
+assumes that your PWD is set according to your installation standards.
+
+ ./Configure nonstop-nsx --prefix=${PWD} \
+ --openssldir=${PWD}/ssl no-threads \
+ --with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
+ ./Configure nonstop-nsx_g --prefix=${PWD} \
+ --openssldir=${PWD}/ssl no-threads \
+ --with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
+ ./Configure nonstop-nsx_put --prefix=${PWD} \
+ --openssldir=${PWD}/ssl threads "-D_REENTRANT" \
+ --with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
+ ./Configure nonstop-nsx_spt_floss --prefix=${PWD} \
+ --openssldir=${PWD}/ssl threads "-D_REENTRANT" \
+ --with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
+ ./Configure nonstop-nsx_64 --prefix=${PWD} \
+ --openssldir=${PWD}/ssl no-threads \
+ --with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
+ ./Configure nonstop-nsx_64_put --prefix=${PWD} \
+ --openssldir=${PWD}/ssl threads "-D_REENTRANT" \
+ --with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
+ ./Configure nonstop-nsx_g_tandem --prefix=${PWD} \
+ --openssldir=${PWD}/ssl no-threads \
+ --with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
+
+ ./Configure nonstop-nse --prefix=${PWD} \
+ --openssldir=${PWD}/ssl no-threads \
+ --with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
+ ./Configure nonstop-nse_g --prefix=${PWD} \
+ --openssldir=${PWD}/ssl no-threads \
+ --with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
+ ./Configure nonstop-nse_put --prefix=${PWD} \
+ --openssldir=${PWD}/ssl threads "-D_REENTRANT" \
+ --with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
+ ./Configure nonstop-nse_spt_floss --prefix=${PWD} \
+ --openssldir=${PWD}/ssl threads "-D_REENTRANT" \
+ --with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
+ ./Configure nonstop-nse_64 --prefix=${PWD} \
+ --openssldir=${PWD}/ssl no-threads \
+ --with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
+ ./Configure nonstop-nse_64_put --prefix=${PWD} \
+ --openssldir=${PWD}/ssl threads "-D_REENTRANT"
+ --with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
+ ./Configure nonstop-nse_g_tandem --prefix=${PWD} \
+ --openssldir=${PWD}/ssl no-threads \
+ --with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS}
diff --git a/NOTES-PERL.md b/NOTES-PERL.md
new file mode 100644
index 000000000000..b7fc83fc7d75
--- /dev/null
+++ b/NOTES-PERL.md
@@ -0,0 +1,127 @@
+Notes on Perl
+=============
+
+ - [General Notes](#general-notes)
+ - [Perl on Windows](#perl-on-windows)
+ - [Perl on VMS](#perl-on-vms)
+ - [Perl on NonStop](#perl-on-nonstop)
+ - [Required Perl modules](#required-perl-modules)
+ - [Notes on installing a Perl module](#notes-on-installing-a-perl-module])
+
+General Notes
+-------------
+
+For our scripts, we rely quite a bit on Perl, and increasingly on
+some core Perl modules. These Perl modules are part of the Perl
+source, so if you build Perl on your own, you should be set.
+
+However, if you install Perl as binary packages, the outcome might
+differ, and you may have to check that you do get the core modules
+installed properly. We do not claim to know them all, but experience
+has told us the following:
+
+ - on Linux distributions based on Debian, the package `perl` will
+ install the core Perl modules as well, so you will be fine.
+ - on Linux distributions based on RPMs, you will need to install
+ `perl-core` rather than just `perl`.
+
+You MUST have at least Perl version 5.10.0 installed. This minimum
+requirement is due to our use of regexp backslash sequence \R among
+other features that didn't exist in core Perl before that version.
+
+Perl on Windows
+---------------
+
+There are a number of build targets that can be viewed as "Windows".
+Indeed, there are `VC-*` configs targeting VisualStudio C, as well as
+MinGW and Cygwin. The key recommendation is to use a Perl installation
+that matches the build environment. For example, if you will build
+on Cygwin be sure to use the Cygwin package manager to install Perl.
+For MSYS builds use the MSYS provided Perl.
+For VC-* builds we recommend Strawberry Perl, from <http://strawberryperl.com>.
+An alternative is ActiveState Perl, from <http://www.activestate.com/ActivePerl>
+for which you may need to explicitly select the Perl module Win32/Console.pm
+available via <https://platform.activestate.com/ActiveState>.
+
+Perl on VMS
+-----------
+
+You will need to install Perl separately. One way to do so is to
+download the source from <http://perl.org/>, unpacking it, reading
+`README-VMS.md` and follow the instructions. Another way is to download a
+`.PCSI` file from <http://www.vmsperl.com/> and install it using the
+POLYCENTER install tool.
+
+Perl on NonStop
+---------------
+
+Perl is installed on HPE NonStop platforms as part of the Scripting Languages
+package T1203PAX file. The package is shipped as part of a NonStop RVU
+(Release Version Updates) package. Individual SPRs (Software Product Release)
+representing fixes can be obtained from the Scout website at
+<https://h22204.www2.hpe.com/NEP>. Follow the appropriate set of installation
+instructions for your operating system release as described in the
+Script Language User Guide available from the NonStop Technical Library.
+
+Required Perl modules
+---------------------
+
+We do our best to limit ourselves to core Perl modules to keep the
+requirements down. There are just a few exceptions.
+
+ * Text::Template this is required *for building*
+
+ To avoid unnecessary initial hurdles, we include a copy of this module
+ in the source. It will work as a fallback if the module isn't already
+ installed.
+
+ * `Test::More` this is required *for testing*
+
+ We require the minimum version to be 0.96, which appeared in Perl 5.13.4,
+ because that version was the first to have all the features we're using.
+ This module is required for testing only! If you don't plan on running
+ the tests, you don't need to bother with this one.
+
+Notes on installing a Perl module
+---------------------------------
+
+There are a number of ways to install a perl module. In all
+descriptions below, `Text::Template` will serve as an example.
+
+1. for Linux users, the easiest is to install with the use of your
+ favorite package manager. Usually, all you need to do is search
+ for the module name and to install the package that comes up.
+
+ On Debian based Linux distributions, it would go like this:
+
+ $ apt-cache search Text::Template
+ ...
+ libtext-template-perl - perl module to process text templates
+ $ sudo apt-get install libtext-template-perl
+
+ Perl modules in Debian based distributions use package names like
+ the name of the module in question, with "lib" prepended and
+ "-perl" appended.
+
+2. Install using CPAN. This is very easy, but usually requires root
+ access:
+
+ $ cpan -i Text::Template
+
+ Note that this runs all the tests that the module to be installed
+ comes with. This is usually a smooth operation, but there are
+ platforms where a failure is indicated even though the actual tests
+ were successful. Should that happen, you can force an
+ installation regardless (that should be safe since you've already
+ seen the tests succeed!):
+
+ $ cpan -f -i Text::Template
+
+ Note: on VMS, you must quote any argument that contains upper case
+ characters, so the lines above would be:
+
+ $ cpan -i "Text::Template"
+
+ and:
+
+ $ cpan -f -i "Text::Template"
diff --git a/NOTES-UNIX.md b/NOTES-UNIX.md
new file mode 100644
index 000000000000..293793b60559
--- /dev/null
+++ b/NOTES-UNIX.md
@@ -0,0 +1,115 @@
+Notes for UNIX-like platforms
+=============================
+
+ For Unix/POSIX runtime systems on Windows,
+ please see the [Notes for Windows platforms](NOTES-WINDOWS.md).
+
+ OpenSSL uses the compiler to link programs and shared libraries
+ ---------------------------------------------------------------
+
+ OpenSSL's generated Makefile uses the C compiler command line to
+ link programs, shared libraries and dynamically loadable shared
+ objects. Because of this, any linking option that's given to the
+ configuration scripts MUST be in a form that the compiler can accept.
+ This varies between systems, where some have compilers that accept
+ linker flags directly, while others take them in `-Wl,` form. You need
+ to read your compiler documentation to figure out what is acceptable,
+ and `ld(1)` to figure out what linker options are available.
+
+ Shared libraries and installation in non-default locations
+ ----------------------------------------------------------
+
+ Every Unix system has its own set of default locations for shared
+ libraries, such as `/lib`, `/usr/lib` or possibly `/usr/local/lib`. If
+ libraries are installed in non-default locations, dynamically linked
+ binaries will not find them and therefore fail to run, unless they get
+ a bit of help from a defined runtime shared library search path.
+
+ For OpenSSL's application (the `openssl` command), our configuration
+ scripts do NOT generally set the runtime shared library search path for
+ you. It's therefore advisable to set it explicitly when configuring,
+ unless the libraries are to be installed in directories that you know
+ to be in the default list.
+
+ Runtime shared library search paths are specified with different
+ linking options depending on operating system and versions thereof, and
+ are talked about differently in their respective documentation;
+ variations of RPATH are the most usual (note: ELF systems have two such
+ tags, more on that below).
+
+ Possible options to set the runtime shared library search path include
+ the following:
+
+ -Wl,-rpath,/whatever/path # Linux, *BSD, etc.
+ -R /whatever/path # Solaris
+ -Wl,-R,/whatever/path # AIX (-bsvr4 is passed internally)
+ -Wl,+b,/whatever/path # HP-UX
+ -rpath /whatever/path # Tru64, IRIX
+
+ OpenSSL's configuration scripts recognise all these options and pass
+ them to the Makefile that they build. (In fact, all arguments starting
+ with `-Wl,` are recognised as linker options.)
+ Please note that 'l' in '-Wl' is lowercase L and not 1.
+
+ Please do not use verbatim directories in your runtime shared library
+ search path! Some OpenSSL config targets add an extra directory level
+ for multilib installations. To help with that, the produced Makefile
+ includes the variable LIBRPATH, which is a convenience variable to be
+ used with the runtime shared library search path options, as shown in
+ this example:
+
+ $ ./Configure --prefix=/usr/local/ssl --openssldir=/usr/local/ssl \
+ '-Wl,-rpath,$(LIBRPATH)'
+
+ On modern ELF based systems, there are two runtime search paths tags to
+ consider, `DT_RPATH` and `DT_RUNPATH`. Shared objects are searched for in
+ this order:
+
+ 1. Using directories specified in DT_RPATH, unless DT_RUNPATH is also set.
+ 2. Using the environment variable LD_LIBRARY_PATH
+ 3. Using directories specified in DT_RUNPATH.
+ 4. Using system shared object caches and default directories.
+
+ This means that the values in the environment variable `LD_LIBRARY_PATH`
+ won't matter if the library is found in the paths given by `DT_RPATH`
+ (and `DT_RUNPATH` isn't set).
+
+ Exactly which of `DT_RPATH` or `DT_RUNPATH` is set by default appears to
+ depend on the system. For example, according to documentation,
+ `DT_RPATH` appears to be deprecated on Solaris in favor of `DT_RUNPATH`,
+ while on Debian GNU/Linux, either can be set, and `DT_RPATH` is the
+ default at the time of writing.
+
+ How to choose which runtime search path tag is to be set depends on
+ your system, please refer to ld(1) for the exact information on your
+ system. As an example, the way to ensure the `DT_RUNPATH` is set on
+ Debian GNU/Linux systems rather than DT_RPATH is to tell the linker to
+ set new dtags, like this:
+
+ $ ./Configure --prefix=/usr/local/ssl --openssldir=/usr/local/ssl \
+ '-Wl,--enable-new-dtags,-rpath,$(LIBRPATH)'
+
+ It might be worth noting that some/most ELF systems implement support
+ for runtime search path relative to the directory containing current
+ executable, by interpreting `$ORIGIN` along with some other internal
+ variables. Consult your system documentation.
+
+ Linking your application
+ ------------------------
+
+ Third-party applications dynamically linked with OpenSSL (or any other)
+ shared library face exactly the same problem with non-default locations.
+ The OpenSSL config options mentioned above might or might not have bearing
+ on linking of the target application. "Might" means that under some
+ circumstances it would be sufficient to link with OpenSSL shared library
+ "naturally", i.e. with `-L/whatever/path -lssl -lcrypto`. But there are
+ also cases when you'd have to explicitly specify runtime search path
+ when linking your application. Consult your system documentation and use
+ above section as inspiration...
+
+ Shared OpenSSL builds also install static libraries. Linking with the
+ latter is likely to require special care, because linkers usually look
+ for shared libraries first and tend to remain "blind" to static OpenSSL
+ libraries. Referring to system documentation would suffice, if not for
+ a corner case. On AIX static libraries (in shared build) are named
+ differently, add `_a` suffix to link with them, e.g. `-lcrypto_a`.
diff --git a/NOTES-VALGRIND.md b/NOTES-VALGRIND.md
new file mode 100644
index 000000000000..2700324efa36
--- /dev/null
+++ b/NOTES-VALGRIND.md
@@ -0,0 +1,72 @@
+Notes on Valgrind
+=================
+
+Valgrind is a test harness that includes many tools such as memcheck,
+which is commonly used to check for memory leaks, etc. The default tool
+run by Valgrind is memcheck. There are other tools available, but this
+will focus on memcheck.
+
+Valgrind runs programs in a virtual machine, this means OpenSSL unit
+tests run under Valgrind will take longer than normal.
+
+Requirements
+------------
+
+1. Platform supported by Valgrind
+ See <http://valgrind.org/info/platforms.html>
+2. Valgrind installed on the platform
+ See <http://valgrind.org/downloads/current.html>
+3. OpenSSL compiled
+ See [INSTALL.md](INSTALL.md)
+
+Running Tests
+-------------
+
+Test behavior can be modified by adjusting environment variables.
+
+`EXE_SHELL`
+
+This variable is used to specify the shell used to execute OpenSSL test
+programs. The default wrapper (`util/wrap.pl`) initializes the environment
+to allow programs to find shared libraries. The variable can be modified
+to specify a different executable environment.
+
+ EXE_SHELL=\
+ "`/bin/pwd`/util/wrap.pl valgrind --error-exitcode=1 --leak-check=full -q"
+
+This will start up Valgrind with the default checker (`memcheck`).
+The `--error-exitcode=1` option specifies that Valgrind should exit with an
+error code of 1 when memory leaks occur.
+The `--leak-check=full` option specifies extensive memory checking.
+The `-q` option prints only error messages.
+Additional Valgrind options may be added to the `EXE_SHELL` variable.
+
+`OPENSSL_ia32cap`
+
+This variable controls the processor-specific code on Intel processors.
+By default, OpenSSL will attempt to figure out the capabilities of a
+processor, and use it to its fullest capability. This variable can be
+used to control what capabilities OpenSSL uses.
+
+As of valgrind-3.15.0 on Linux/x86_64, instructions up to AVX2 are
+supported. Setting the following disables instructions beyond AVX2:
+
+`OPENSSL_ia32cap=":0"`
+
+This variable may need to be set to something different based on the
+processor and Valgrind version you are running tests on. More information
+may be found in [doc/man3/OPENSSL_ia32cap.pod](doc/man3/OPENSSL_ia32cap.pod).
+
+Additional variables (such as `VERBOSE` and `TESTS`) are described in the
+file [test/README.md](test/README.md).
+
+Example command line:
+
+ $ make test EXE_SHELL="`/bin/pwd`/util/wrap.pl valgrind --error-exitcode=1 \
+ --leak-check=full -q" OPENSSL_ia32cap=":0"
+
+If an error occurs, you can then run the specific test via the `TESTS` variable
+with the `VERBOSE` or `VF` or `VFP` options to gather additional information.
+
+ $ make test VERBOSE=1 TESTS=test_test EXE_SHELL="`/bin/pwd`/util/wrap.pl \
+ valgrind --error-exitcode=1 --leak-check=full -q" OPENSSL_ia32cap=":0"
diff --git a/NOTES-VMS.md b/NOTES-VMS.md
new file mode 100644
index 000000000000..e27f3d682a2a
--- /dev/null
+++ b/NOTES-VMS.md
@@ -0,0 +1,115 @@
+Notes for the OpenVMS platform
+==============================
+
+ - [Requirement details](#requirement-details)
+ - [About ANSI C compiler](#about-ansi-c-compiler)
+ - [About ODS-5 directory names and Perl](#about-ods-5-directory-names-and-perl)
+ - [About MMS and DCL](#about-mms-and-dcl)
+ - [About debugging](#about-debugging)
+ - [Checking the distribution](#checking-the-distribution)
+
+Requirement details
+-------------------
+
+In addition to the requirements and instructions listed
+in [INSTALL.md](INSTALL.md), this are required as well:
+
+ * At least ODS-5 disk organization for source and build.
+ Installation can be done on any existing disk organization.
+
+About ANSI C compiler
+---------------------
+
+An ANSI C compiled is needed among other things. This means that
+VAX C is not and will not be supported.
+
+We have only tested with DEC C (aka HP VMS C / VSI C) and require
+version 7.1 or later. Compiling with a different ANSI C compiler may
+require some work.
+
+Please avoid using C RTL feature logical names `DECC$*` when building
+and testing OpenSSL. Most of all, they can be disruptive when
+running the tests, as they affect the Perl interpreter.
+
+About ODS-5 directory names and Perl
+------------------------------------
+
+It seems that the perl function canonpath() in the `File::Spec` module
+doesn't treat file specifications where the last directory name
+contains periods very well. Unfortunately, some versions of VMS tar
+will keep the periods in the OpenSSL source directory instead of
+converting them to underscore, thereby leaving your source in
+something like `[.openssl-1^.1^.0]`. This will lead to issues when
+configuring and building OpenSSL.
+
+We have no replacement for Perl's canonpath(), so the best workaround
+for now is to rename the OpenSSL source directory, as follows (please
+adjust for the actual source directory name you have):
+
+ $ rename openssl-1^.1^.0.DIR openssl-1_1_0.DIR
+
+About MMS and DCL
+-----------------
+
+MMS has certain limitations when it comes to line length, and DCL has
+certain limitations when it comes to total command length. We do
+what we can to mitigate, but there is the possibility that it's not
+enough. Should you run into issues, a very simple solution is to set
+yourself up a few logical names for the directory trees you're going
+to use.
+
+About debugging
+---------------
+
+If you build for debugging, the default on VMS is that image
+activation starts the debugger automatically, giving you a debug
+prompt. Unfortunately, this disrupts all other uses, such as running
+test programs in the test framework.
+
+Generally speaking, if you build for debugging, only use the programs
+directly for debugging. Do not try to use them from a script, such
+as running the test suite.
+
+### The following is not available on Alpha
+
+As a compromise, we're turning off the flag that makes the debugger
+start automatically. If there is a program that you need to debug,
+you need to turn that flag back on first, for example:
+
+ $ set image /flag=call_debug [.test]evp_test.exe
+
+Then just run it and you will find yourself in a debugging session.
+When done, we recommend that you turn that flag back off:
+
+ $ set image /flag=nocall_debug [.test]evp_test.exe
+
+Checking the distribution
+-------------------------
+
+There have been reports of places where the distribution didn't quite
+get through, for example if you've copied the tree from a NFS-mounted
+Unix mount point.
+
+The easiest way to check if everything got through as it should is to
+check that this file exists:
+
+ [.include.openssl]configuration^.h.in
+
+The best way to get a correct distribution is to download the gzipped
+tar file from ftp://ftp.openssl.org/source/, use `GZIP -d` to uncompress
+it and `VMSTAR` to unpack the resulting tar file.
+
+Gzip and VMSTAR are available here:
+
+ <http://antinode.info/dec/index.html#Software>
+
+Should you need it, you can find UnZip for VMS here:
+
+ <http://www.info-zip.org/UnZip.html>
+
+ How the value of 'arch' is determined
+ -------------------------------------
+
+ 'arch' is mentioned in INSTALL. It's value is determined like this:
+
+ arch = f$edit( f$getsyi( "arch_name"), "upcase")
diff --git a/NOTES-WINDOWS.md b/NOTES-WINDOWS.md
new file mode 100644
index 000000000000..b1d6c4fe13bb
--- /dev/null
+++ b/NOTES-WINDOWS.md
@@ -0,0 +1,265 @@
+Notes for Windows platforms
+===========================
+
+ - [Native builds using Visual C++](#native-builds-using-visual-c++)
+ - [Native builds using Embarcadero C++Builder](
+ #native-builds-using-embarcadero-c++-builder)
+ - [Native builds using MinGW](#native-builds-using-mingw)
+ - [Linking native applications](#linking-native-applications)
+ - [Hosted builds using Cygwin](#hosted-builds-using-cygwin)
+
+There are various options to build and run OpenSSL on the Windows platforms.
+
+"Native" OpenSSL uses the Windows APIs directly at run time.
+To build a native OpenSSL you can either use:
+
+ Microsoft Visual C++ (MSVC) C compiler on the command line
+or
+ Embarcadero C++Builder
+or
+ MinGW cross compiler
+ run on the GNU-like development environment MSYS2
+ or run on Linux or Cygwin
+
+"Hosted" OpenSSL relies on an external POSIX compatibility layer
+for building (using GNU/Unix shell, compiler, and tools) and at run time.
+For this option you can use Cygwin.
+
+Native builds using Visual C++
+==============================
+
+The native builds using Visual C++ have a `VC-*` prefix.
+
+Requirement details
+-------------------
+
+In addition to the requirements and instructions listed in `INSTALL.md`,
+these are required as well:
+
+### Perl
+
+We recommend Strawberry Perl, available from <http://strawberryperl.com/>
+Please read NOTES.PERL for more information, including the use of CPAN.
+An alternative is ActiveState Perl, <https://www.activestate.com/ActivePerl>
+for which you may need to explicitly build the Perl module Win32/Console.pm
+via <https://platform.activestate.com/ActiveState> and then download it.
+
+### Microsoft Visual C compiler.
+
+Since these are proprietary and ever-changing we cannot test them all.
+Older versions may not work. Use a recent version wherever possible.
+
+### Netwide Assembler (NASM)
+
+NASM is the only supported assembler. It is available from <https://www.nasm.us>.
+
+Quick start
+-----------
+
+ 1. Install Perl
+
+ 2. Install NASM
+
+ 3. Make sure both Perl and NASM are on your %PATH%
+
+ 4. Use Visual Studio Developer Command Prompt with administrative privileges,
+ choosing one of its variants depending on the intended architecture.
+ Or run `cmd` and execute `vcvarsall.bat` with one of the options `x86`,
+ `x86_amd64`, `x86_arm`, `x86_arm64`, `amd64`, `amd64_x86`, `amd64_arm`,
+ or `amd64_arm64`.
+ This sets up the environment variables needed for `nmake.exe`, `cl.exe`,
+ etc.
+ See also
+ <https://docs.microsoft.com/cpp/build/building-on-the-command-line>
+
+ 5. From the root of the OpenSSL source directory enter
+ - `perl Configure VC-WIN32` if you want 32-bit OpenSSL or
+ - `perl Configure VC-WIN64A` if you want 64-bit OpenSSL or
+ - `perl Configure VC-WIN64-ARM` if you want Windows on Arm (win-arm64)
+ OpenSSL or
+ - `perl Configure` to let Configure figure out the platform
+
+ 6. `nmake`
+
+ 7. `nmake test`
+
+ 8. `nmake install`
+
+For the full installation instructions, or if anything goes wrong at any stage,
+check the INSTALL.md file.
+
+Installation directories
+------------------------
+
+The default installation directories are derived from environment
+variables.
+
+For VC-WIN32, the following defaults are use:
+
+ PREFIX: %ProgramFiles(x86)%\OpenSSL
+ OPENSSLDIR: %CommonProgramFiles(x86)%\SSL
+
+For VC-WIN64, the following defaults are use:
+
+ PREFIX: %ProgramW6432%\OpenSSL
+ OPENSSLDIR: %CommonProgramW6432%\SSL
+
+Should those environment variables not exist (on a pure Win32
+installation for examples), these fallbacks are used:
+
+ PREFIX: %ProgramFiles%\OpenSSL
+ OPENSSLDIR: %CommonProgramFiles%\SSL
+
+ALSO NOTE that those directories are usually write protected, even if
+your account is in the Administrators group. To work around that,
+start the command prompt by right-clicking on it and choosing "Run as
+Administrator" before running `nmake install`. The other solution
+is, of course, to choose a different set of directories by using
+`--prefix` and `--openssldir` when configuring.
+
+Special notes for Universal Windows Platform builds, aka `VC-*-UWP`
+-------------------------------------------------------------------
+
+ - UWP targets only support building the static and dynamic libraries.
+
+ - You should define the platform type to `uwp` and the target arch via
+ `vcvarsall.bat` before you compile. For example, if you want to build
+ `arm64` builds, you should run `vcvarsall.bat x86_arm64 uwp`.
+
+Native builds using Embarcadero C++Builder
+=========================================
+
+This toolchain (a descendant of Turbo/Borland C++) is an alternative to MSVC.
+OpenSSL currently includes an experimental 32-bit configuration targeting the
+Clang-based compiler (`bcc32c.exe`) in v10.3.3 Community Edition.
+<https://www.embarcadero.com/products/cbuilder/starter>
+
+ 1. Install Perl.
+
+ 2. Open the RAD Studio Command Prompt.
+
+ 3. Go to the root of the OpenSSL source directory and run:
+ `perl Configure BC-32 --prefix=%CD%`
+
+ 4. `make -N`
+
+ 5. `make -N test`
+
+ 6. Build your program against this OpenSSL:
+ * Set your include search path to the "include" subdirectory of OpenSSL.
+ * Set your library search path to the OpenSSL source directory.
+
+Note that this is very experimental. Support for 64-bit and other Configure
+options is still pending.
+
+Native builds using MinGW
+=========================
+
+MinGW offers an alternative way to build native OpenSSL, by cross compilation.
+
+ * Usually the build is done on Windows in a GNU-like environment called MSYS2.
+
+ MSYS2 provides GNU tools, a Unix-like command prompt,
+ and a UNIX compatibility layer for applications.
+ However, in this context it is only used for building OpenSSL.
+ The resulting OpenSSL does not rely on MSYS2 to run and is fully native.
+
+ Requirement details
+
+ - MSYS2 shell, from <https://www.msys2.org/>
+
+ - Perl, at least version 5.10.0, which usually comes pre-installed with MSYS2
+
+ - make, installed using `pacman -S make` into the MSYS2 environment
+
+ - MinGW[64] compiler: `mingw-w64-i686-gcc` and/or `mingw-w64-x86_64-gcc`.
+ These compilers must be on your MSYS2 $PATH.
+ A common error is to not have these on your $PATH.
+ The MSYS2 version of gcc will not work correctly here.
+
+ In the MSYS2 shell do the configuration depending on the target architecture:
+
+ ./Configure mingw ...
+
+ or
+
+ ./Configure mingw64 ...
+
+ or
+
+ ./Configure ...
+
+ for the default architecture.
+
+ Apart from that, follow the Unix / Linux instructions in `INSTALL.md`.
+
+ * It is also possible to build mingw[64] on Linux or Cygwin.
+
+ In this case configure with the corresponding `--cross-compile-prefix=`
+ option. For example
+
+ ./Configure mingw --cross-compile-prefix=i686-w64-mingw32- ...
+
+ or
+
+ ./Configure mingw64 --cross-compile-prefix=x86_64-w64-mingw32- ...
+
+ This requires that you've installed the necessary add-on packages for
+ mingw[64] cross compilation.
+
+Linking native applications
+===========================
+
+This section applies to all native builds.
+
+If you link with static OpenSSL libraries then you're expected to
+additionally link your application with `WS2_32.LIB`, `GDI32.LIB`,
+`ADVAPI32.LIB`, `CRYPT32.LIB` and `USER32.LIB`. Those developing
+non-interactive service applications might feel concerned about
+linking with `GDI32.LIB` and `USER32.LIB`, as they are justly associated
+with interactive desktop, which is not available to service
+processes. The toolkit is designed to detect in which context it's
+currently executed, GUI, console app or service, and act accordingly,
+namely whether or not to actually make GUI calls. Additionally those
+who wish to `/DELAYLOAD:GDI32.DLL` and `/DELAYLOAD:USER32.DLL` and
+actually keep them off service process should consider implementing
+and exporting from .exe image in question own `_OPENSSL_isservice` not
+relying on `USER32.DLL`. E.g., on Windows Vista and later you could:
+
+ __declspec(dllexport) __cdecl BOOL _OPENSSL_isservice(void)
+ {
+ DWORD sess;
+
+ if (ProcessIdToSessionId(GetCurrentProcessId(), &sess))
+ return sess == 0;
+ return FALSE;
+ }
+
+If you link with OpenSSL .DLLs, then you're expected to include into
+your application code a small "shim" snippet, which provides
+the glue between the OpenSSL BIO layer and your compiler run-time.
+See also the OPENSSL_Applink manual page.
+
+Hosted builds using Cygwin
+==========================
+
+Cygwin implements a POSIX/Unix runtime system (`cygwin1.dll`) on top of the
+Windows subsystem and provides a Bash shell and GNU tools environment.
+Consequently, a build of OpenSSL with Cygwin is virtually identical to the
+Unix procedure.
+
+To build OpenSSL using Cygwin, you need to:
+
+ * Install Cygwin, see <https://cygwin.com/>
+
+ * Install Cygwin Perl, at least version 5.10.0
+ and ensure it is in the $PATH
+
+ * Run the Cygwin Bash shell
+
+Apart from that, follow the Unix / Linux instructions in INSTALL.md.
+
+NOTE: `make test` and normal file operations may fail in directories
+mounted as text (i.e. `mount -t c:\somewhere /home`) due to Cygwin
+stripping of carriage returns. To avoid this ensure that a binary
+mount is used, e.g. `mount -b c:\somewhere /home`.
diff --git a/NOTES.PERL b/NOTES.PERL
deleted file mode 100644
index 201b14386729..000000000000
--- a/NOTES.PERL
+++ /dev/null
@@ -1,119 +0,0 @@
- TOC
- ===
-
- - Notes on Perl
- - Notes on Perl on Windows
- - Notes on Perl modules we use
- - Notes on installing a perl module
-
- Notes on Perl
- -------------
-
- For our scripts, we rely quite a bit on Perl, and increasingly on
- some core Perl modules. These Perl modules are part of the Perl
- source, so if you build Perl on your own, you should be set.
-
- However, if you install Perl as binary packages, the outcome might
- differ, and you may have to check that you do get the core modules
- installed properly. We do not claim to know them all, but experience
- has told us the following:
-
- - on Linux distributions based on Debian, the package 'perl' will
- install the core Perl modules as well, so you will be fine.
- - on Linux distributions based on RPMs, you will need to install
- 'perl-core' rather than just 'perl'.
-
- You MUST have at least Perl version 5.10.0 installed. This minimum
- requirement is due to our use of regexp backslash sequence \R among
- other features that didn't exist in core Perl before that version.
-
- Notes on Perl on Windows
- ------------------------
-
- There are a number of build targets that can be viewed as "Windows".
- Indeed, there are VC-* configs targeting VisualStudio C, as well as
- MinGW and Cygwin. The key recommendation is to use "matching" Perl,
- one that matches build environment. For example, if you will build
- on Cygwin be sure to use the Cygwin package manager to install Perl.
- For MSYS builds use the MSYS provided Perl. For VC-* builds we
- recommend ActiveState Perl, available from
- http://www.activestate.com/ActivePerl.
-
- Notes on Perl on VMS
- --------------------
-
- You will need to install Perl separately. One way to do so is to
- download the source from http://perl.org/, unpacking it, reading
- README.vms and follow the instructions. Another way is to download a
- .PCSI file from http://www.vmsperl.com/ and install it using the
- POLYCENTER install tool.
-
- Notes on Perl modules we use
- ----------------------------
-
- We make increasing use of Perl modules, and do our best to limit
- ourselves to core Perl modules to keep the requirements down. There
- are just a few exceptions:
-
- Test::More We require the minimum version to be 0.96, which
- appeared in Perl 5.13.4, because that version was
- the first to have all the features we're using.
- This module is required for testing only! If you
- don't plan on running the tests, you don't need to
- bother with this one.
-
- Text::Template This module is not part of the core Perl modules.
- As a matter of fact, the core Perl modules do not
- include any templating module to date.
- This module is absolutely needed, configuration
- depends on it.
-
- To avoid unnecessary initial hurdles, we have bundled a copy of the
- following modules in our source. They will work as fallbacks if
- these modules aren't already installed on the system.
-
- Text::Template
-
- Notes on installing a perl module
- ---------------------------------
-
- There are a number of ways to install a perl module. In all
- descriptions below, Text::Template will serve as an example.
-
- 1. for Linux users, the easiest is to install with the use of your
- favorite package manager. Usually, all you need to do is search
- for the module name and to install the package that comes up.
-
- On Debian based Linux distributions, it would go like this:
-
- $ apt-cache search Text::Template
- ...
- libtext-template-perl - perl module to process text templates
- $ sudo apt-get install libtext-template-perl
-
- Perl modules in Debian based distributions use package names like
- the name of the module in question, with "lib" prepended and
- "-perl" appended.
-
- 2. Install using CPAN. This is very easy, but usually requires root
- access:
-
- $ cpan -i Text::Template
-
- Note that this runs all the tests that the module to be installed
- comes with. This is usually a smooth operation, but there are
- platforms where a failure is indicated even though the actual tests
- were successful. Should that happen, you can force an
- installation regardless (that should be safe since you've already
- seen the tests succeed!):
-
- $ cpan -f -i Text::Template
-
- Note: on VMS, you must quote any argument that contains uppercase
- characters, so the lines above would be:
-
- $ cpan -i "Text::Template"
-
- and:
-
- $ cpan -f -i "Text::Template"
diff --git a/NOTES.UNIX b/NOTES.UNIX
deleted file mode 100644
index 6c291cbab6fd..000000000000
--- a/NOTES.UNIX
+++ /dev/null
@@ -1,117 +0,0 @@
-
- NOTES FOR UNIX LIKE PLATFORMS
- =============================
-
- For Unix/POSIX runtime systems on Windows, please see NOTES.WIN.
-
-
- OpenSSL uses the compiler to link programs and shared libraries
- ---------------------------------------------------------------
-
- OpenSSL's generated Makefile uses the C compiler command line to
- link programs, shared libraries and dynamically loadable shared
- objects. Because of this, any linking option that's given to the
- configuration scripts MUST be in a form that the compiler can accept.
- This varies between systems, where some have compilers that accept
- linker flags directly, while others take them in '-Wl,' form. You need
- to read your compiler documentation to figure out what is acceptable,
- and ld(1) to figure out what linker options are available.
-
-
- Shared libraries and installation in non-default locations
- ----------------------------------------------------------
-
- Every Unix system has its own set of default locations for shared
- libraries, such as /lib, /usr/lib or possibly /usr/local/lib. If
- libraries are installed in non-default locations, dynamically linked
- binaries will not find them and therefore fail to run, unless they get
- a bit of help from a defined runtime shared library search path.
-
- For OpenSSL's application (the 'openssl' command), our configuration
- scripts do NOT generally set the runtime shared library search path for
- you. It's therefore advisable to set it explicitly when configuring,
- unless the libraries are to be installed in directories that you know
- to be in the default list.
-
- Runtime shared library search paths are specified with different
- linking options depending on operating system and versions thereof, and
- are talked about differently in their respective documentation;
- variations of RPATH are the most usual (note: ELF systems have two such
- tags, more on that below).
-
- Possible options to set the runtime shared library search path include
- the following:
-
- -Wl,-rpath,/whatever/path # Linux, *BSD, etc.
- -R /whatever/path # Solaris
- -Wl,-R,/whatever/path # AIX (-bsvr4 is passed internally)
- -Wl,+b,/whatever/path # HP-UX
- -rpath /whatever/path # Tru64, IRIX
-
- OpenSSL's configuration scripts recognise all these options and pass
- them to the Makefile that they build. (In fact, all arguments starting
- with '-Wl,' are recognised as linker options.)
-
- Please do not use verbatim directories in your runtime shared library
- search path! Some OpenSSL config targets add an extra directory level
- for multilib installations. To help with that, the produced Makefile
- includes the variable LIBRPATH, which is a convenience variable to be
- used with the runtime shared library search path options, as shown in
- this example:
-
- $ ./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl \
- '-Wl,-rpath,$(LIBRPATH)'
-
- On modern ELF based systems, there are two runtime search paths tags to
- consider, DT_RPATH and DT_RUNPATH. Shared objects are searched for in
- this order:
-
- 1. Using directories specified in DT_RPATH, unless DT_RUNPATH is
- also set.
- 2. Using the environment variable LD_LIBRARY_PATH
- 3. Using directories specified in DT_RUNPATH.
- 4. Using system shared object caches and default directories.
-
- This means that the values in the environment variable LD_LIBRARY_PATH
- won't matter if the library is found in the paths given by DT_RPATH
- (and DT_RUNPATH isn't set).
-
- Exactly which of DT_RPATH or DT_RUNPATH is set by default appears to
- depend on the system. For example, according to documentation,
- DT_RPATH appears to be deprecated on Solaris in favor of DT_RUNPATH,
- while on Debian GNU/Linux, either can be set, and DT_RPATH is the
- default at the time of writing.
-
- How to choose which runtime search path tag is to be set depends on
- your system, please refer to ld(1) for the exact information on your
- system. As an example, the way to ensure the DT_RUNPATH is set on
- Debian GNU/Linux systems rather than DT_RPATH is to tell the linker to
- set new dtags, like this:
-
- $ ./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl \
- '-Wl,--enable-new-dtags,-rpath,$(LIBRPATH)'
-
- It might be worth noting that some/most ELF systems implement support
- for runtime search path relative to the directory containing current
- executable, by interpreting $ORIGIN along with some other internal
- variables. Consult your system documentation.
-
- Linking your application
- ------------------------
-
- Third-party applications dynamically linked with OpenSSL (or any other)
- shared library face exactly the same problem with non-default locations.
- The OpenSSL config options mentioned above might or might not have bearing
- on linking of the target application. "Might" means that under some
- circumstances it would be sufficient to link with OpenSSL shared library
- "naturally", i.e. with -L/whatever/path -lssl -lcrypto. But there are
- also cases when you'd have to explicitly specify runtime search path
- when linking your application. Consult your system documentation and use
- above section as inspiration...
-
- Shared OpenSSL builds also install static libraries. Linking with the
- latter is likely to require special care, because linkers usually look
- for shared libraries first and tend to remain "blind" to static OpenSSL
- libraries. Referring to system documentation would suffice, if not for
- a corner case. On AIX static libraries (in shared build) are named
- differently, add _a suffix to link with them, e.g. -lcrypto_a.
diff --git a/README b/README
deleted file mode 100644
index b2f806be3a44..000000000000
--- a/README
+++ /dev/null
@@ -1,93 +0,0 @@
-
- OpenSSL 1.1.1t 7 Feb 2023
-
- Copyright (c) 1998-2022 The OpenSSL Project
- Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson
- All rights reserved.
-
- DESCRIPTION
- -----------
-
- The OpenSSL Project is a collaborative effort to develop a robust,
- commercial-grade, fully featured, and Open Source toolkit implementing the
- Transport Layer Security (TLS) protocols (including SSLv3) as well as a
- full-strength general purpose cryptographic library.
-
- OpenSSL is descended from the SSLeay library developed by Eric A. Young
- and Tim J. Hudson. The OpenSSL toolkit is licensed under a dual-license (the
- OpenSSL license plus the SSLeay license), which means that you are free to
- get and use it for commercial and non-commercial purposes as long as you
- fulfill the conditions of both licenses.
-
- OVERVIEW
- --------
-
- The OpenSSL toolkit includes:
-
- libssl (with platform specific naming):
- Provides the client and server-side implementations for SSLv3 and TLS.
-
- libcrypto (with platform specific naming):
- Provides general cryptographic and X.509 support needed by SSL/TLS but
- not logically part of it.
-
- openssl:
- A command line tool that can be used for:
- Creation of key parameters
- Creation of X.509 certificates, CSRs and CRLs
- Calculation of message digests
- Encryption and decryption
- SSL/TLS client and server tests
- Handling of S/MIME signed or encrypted mail
- And more...
-
- INSTALLATION
- ------------
-
- See the appropriate file:
- INSTALL Linux, Unix, Windows, OpenVMS, ...
- NOTES.* INSTALL addendums for different platforms
-
- SUPPORT
- -------
-
- See the OpenSSL website www.openssl.org for details on how to obtain
- commercial technical support. Free community support is available through the
- openssl-users email list (see
- https://www.openssl.org/community/mailinglists.html for further details).
-
- If you have any problems with OpenSSL then please take the following steps
- first:
-
- - Download the latest version from the repository
- to see if the problem has already been addressed
- - Configure with no-asm
- - Remove compiler optimization flags
-
- If you wish to report a bug then please include the following information
- and create an issue on GitHub:
-
- - OpenSSL version: output of 'openssl version -a'
- - Configuration data: output of 'perl configdata.pm --dump'
- - OS Name, Version, Hardware platform
- - Compiler Details (name, version)
- - Application Details (name, version)
- - Problem Description (steps that will reproduce the problem, if known)
- - Stack Traceback (if the application dumps core)
-
- Just because something doesn't work the way you expect does not mean it
- is necessarily a bug in OpenSSL. Use the openssl-users email list for this type
- of query.
-
- HOW TO CONTRIBUTE TO OpenSSL
- ----------------------------
-
- See CONTRIBUTING
-
- LEGALITIES
- ----------
-
- A number of nations restrict the use or export of cryptography. If you
- are potentially subject to such restrictions you should seek competent
- professional legal advice before attempting to develop or distribute
- cryptographic code.
diff --git a/README-ENGINES.md b/README-ENGINES.md
new file mode 100644
index 000000000000..9874276f1320
--- /dev/null
+++ b/README-ENGINES.md
@@ -0,0 +1,316 @@
+Engines
+=======
+
+Deprecation Note
+----------------
+
+The ENGINE API was introduced in OpenSSL version 0.9.6 as a low level
+interface for adding alternative implementations of cryptographic
+primitives, most notably for integrating hardware crypto devices.
+
+The ENGINE interface has its limitations and it has been superseeded
+by the [PROVIDER API](README-PROVIDERS.md), it is deprecated in OpenSSL
+version 3.0. The following documentation is retained as an aid for
+users who need to maintain or support existing ENGINE implementations.
+Support for new hardware devices or new algorithms should be added
+via providers, and existing engines should be converted to providers
+as soon as possible.
+
+Built-in ENGINE implementations
+-------------------------------
+
+There are currently built-in ENGINE implementations for the following
+crypto devices:
+
+ * Microsoft CryptoAPI
+ * VIA Padlock
+ * nCipher CHIL
+
+In addition, dynamic binding to external ENGINE implementations is now
+provided by a special ENGINE called "dynamic". See the "DYNAMIC ENGINE"
+section below for details.
+
+At this stage, a number of things are still needed and are being worked on:
+
+ 1. Integration of EVP support.
+ 2. Configuration support.
+ 3. Documentation!
+
+Integration of EVP support
+--------------------------
+
+With respect to EVP, this relates to support for ciphers and digests in
+the ENGINE model so that alternative implementations of existing
+algorithms/modes (or previously unimplemented ones) can be provided by
+ENGINE implementations.
+
+Configuration support
+---------------------
+
+Configuration support currently exists in the ENGINE API itself, in the
+form of "control commands". These allow an application to expose to the
+user/admin the set of commands and parameter types a given ENGINE
+implementation supports, and for an application to directly feed string
+based input to those ENGINEs, in the form of name-value pairs. This is an
+extensible way for ENGINEs to define their own "configuration" mechanisms
+that are specific to a given ENGINE (eg. for a particular hardware
+device) but that should be consistent across *all* OpenSSL-based
+applications when they use that ENGINE. Work is in progress (or at least
+in planning) for supporting these control commands from the CONF (or
+NCONF) code so that applications using OpenSSL's existing configuration
+file format can have ENGINE settings specified in much the same way.
+Presently however, applications must use the ENGINE API itself to provide
+such functionality. To see first hand the types of commands available
+with the various compiled-in ENGINEs (see further down for dynamic
+ENGINEs), use the "engine" openssl utility with full verbosity, i.e.:
+
+ openssl engine -vvvv
+
+Documentation
+-------------
+
+Documentation? Volunteers welcome! The source code is reasonably well
+self-documenting, but some summaries and usage instructions are needed -
+moreover, they are needed in the same POD format the existing OpenSSL
+documentation is provided in. Any complete or incomplete contributions
+would help make this happen.
+
+STABILITY & BUG-REPORTS
+=======================
+
+What already exists is fairly stable as far as it has been tested, but
+the test base has been a bit small most of the time. For the most part,
+the vendors of the devices these ENGINEs support have contributed to the
+development and/or testing of the implementations, and *usually* (with no
+guarantees) have experience in using the ENGINE support to drive their
+devices from common OpenSSL-based applications. Bugs and/or inexplicable
+behaviour in using a specific ENGINE implementation should be sent to the
+author of that implementation (if it is mentioned in the corresponding C
+file), and in the case of implementations for commercial hardware
+devices, also through whatever vendor support channels are available. If
+none of this is possible, or the problem seems to be something about the
+ENGINE API itself (ie. not necessarily specific to a particular ENGINE
+implementation) then you should mail complete details to the relevant
+OpenSSL mailing list. For a definition of "complete details", refer to
+the OpenSSL "README" file. As for which list to send it to:
+
+ * openssl-users: if you are *using* the ENGINE abstraction, either in an
+ pre-compiled application or in your own application code.
+
+ * openssl-dev: if you are discussing problems with OpenSSL source code.
+
+USAGE
+=====
+
+The default "openssl" ENGINE is always chosen when performing crypto
+operations unless you specify otherwise. You must actively tell the
+openssl utility commands to use anything else through a new command line
+switch called "-engine". Also, if you want to use the ENGINE support in
+your own code to do something similar, you must likewise explicitly
+select the ENGINE implementation you want.
+
+Depending on the type of hardware, system, and configuration, "settings"
+may need to be applied to an ENGINE for it to function as expected/hoped.
+The recommended way of doing this is for the application to support
+ENGINE "control commands" so that each ENGINE implementation can provide
+whatever configuration primitives it might require and the application
+can allow the user/admin (and thus the hardware vendor's support desk
+also) to provide any such input directly to the ENGINE implementation.
+This way, applications do not need to know anything specific to any
+device, they only need to provide the means to carry such user/admin
+input through to the ENGINE in question. Ie. this connects *you* (and
+your helpdesk) to the specific ENGINE implementation (and device), and
+allows application authors to not get buried in hassle supporting
+arbitrary devices they know (and care) nothing about.
+
+A new "openssl" utility, "openssl engine", has been added in that allows
+for testing and examination of ENGINE implementations. Basic usage
+instructions are available by specifying the "-?" command line switch.
+
+DYNAMIC ENGINES
+===============
+
+The new "dynamic" ENGINE provides a low-overhead way to support ENGINE
+implementations that aren't pre-compiled and linked into OpenSSL-based
+applications. This could be because existing compiled-in implementations
+have known problems and you wish to use a newer version with an existing
+application. It could equally be because the application (or OpenSSL
+library) you are using simply doesn't have support for the ENGINE you
+wish to use, and the ENGINE provider (eg. hardware vendor) is providing
+you with a self-contained implementation in the form of a shared-library.
+The other use-case for "dynamic" is with applications that wish to
+maintain the smallest foot-print possible and so do not link in various
+ENGINE implementations from OpenSSL, but instead leaves you to provide
+them, if you want them, in the form of "dynamic"-loadable
+shared-libraries. It should be possible for hardware vendors to provide
+their own shared-libraries to support arbitrary hardware to work with
+applications based on OpenSSL 0.9.7 or later. If you're using an
+application based on 0.9.7 (or later) and the support you desire is only
+announced for versions later than the one you need, ask the vendor to
+backport their ENGINE to the version you need.
+
+How does "dynamic" work?
+------------------------
+
+The dynamic ENGINE has a special flag in its implementation such that
+every time application code asks for the 'dynamic' ENGINE, it in fact
+gets its own copy of it. As such, multi-threaded code (or code that
+multiplexes multiple uses of 'dynamic' in a single application in any
+way at all) does not get confused by 'dynamic' being used to do many
+independent things. Other ENGINEs typically don't do this so there is
+only ever 1 ENGINE structure of its type (and reference counts are used
+to keep order). The dynamic ENGINE itself provides absolutely no
+cryptographic functionality, and any attempt to "initialise" the ENGINE
+automatically fails. All it does provide are a few "control commands"
+that can be used to control how it will load an external ENGINE
+implementation from a shared-library. To see these control commands,
+use the command-line;
+
+ openssl engine -vvvv dynamic
+
+The "SO_PATH" control command should be used to identify the
+shared-library that contains the ENGINE implementation, and "NO_VCHECK"
+might possibly be useful if there is a minor version conflict and you
+(or a vendor helpdesk) is convinced you can safely ignore it.
+"ID" is probably only needed if a shared-library implements
+multiple ENGINEs, but if you know the engine id you expect to be using,
+it doesn't hurt to specify it (and this provides a sanity check if
+nothing else). "LIST_ADD" is only required if you actually wish the
+loaded ENGINE to be discoverable by application code later on using the
+ENGINE's "id". For most applications, this isn't necessary - but some
+application authors may have nifty reasons for using it. The "LOAD"
+command is the only one that takes no parameters and is the command
+that uses the settings from any previous commands to actually *load*
+the shared-library ENGINE implementation. If this command succeeds, the
+(copy of the) 'dynamic' ENGINE will magically morph into the ENGINE
+that has been loaded from the shared-library. As such, any control
+commands supported by the loaded ENGINE could then be executed as per
+normal. Eg. if ENGINE "foo" is implemented in the shared-library
+"libfoo.so" and it supports some special control command "CMD_FOO", the
+following code would load and use it (NB: obviously this code has no
+error checking);
+
+ ENGINE *e = ENGINE_by_id("dynamic");
+ ENGINE_ctrl_cmd_string(e, "SO_PATH", "/lib/libfoo.so", 0);
+ ENGINE_ctrl_cmd_string(e, "ID", "foo", 0);
+ ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0);
+ ENGINE_ctrl_cmd_string(e, "CMD_FOO", "some input data", 0);
+
+For testing, the "openssl engine" utility can be useful for this sort
+of thing. For example the above code excerpt would achieve much the
+same result as;
+
+ openssl engine dynamic \
+ -pre SO_PATH:/lib/libfoo.so \
+ -pre ID:foo \
+ -pre LOAD \
+ -pre "CMD_FOO:some input data"
+
+Or to simply see the list of commands supported by the "foo" ENGINE;
+
+ openssl engine -vvvv dynamic \
+ -pre SO_PATH:/lib/libfoo.so \
+ -pre ID:foo \
+ -pre LOAD
+
+Applications that support the ENGINE API and more specifically, the
+"control commands" mechanism, will provide some way for you to pass
+such commands through to ENGINEs. As such, you would select "dynamic"
+as the ENGINE to use, and the parameters/commands you pass would
+control the *actual* ENGINE used. Each command is actually a name-value
+pair and the value can sometimes be omitted (eg. the "LOAD" command).
+Whilst the syntax demonstrated in "openssl engine" uses a colon to
+separate the command name from the value, applications may provide
+their own syntax for making that separation (eg. a win32 registry
+key-value pair may be used by some applications). The reason for the
+"-pre" syntax in the "openssl engine" utility is that some commands
+might be issued to an ENGINE *after* it has been initialised for use.
+Eg. if an ENGINE implementation requires a smart-card to be inserted
+during initialisation (or a PIN to be typed, or whatever), there may be
+a control command you can issue afterwards to "forget" the smart-card
+so that additional initialisation is no longer possible. In
+applications such as web-servers, where potentially volatile code may
+run on the same host system, this may provide some arguable security
+value. In such a case, the command would be passed to the ENGINE after
+it has been initialised for use, and so the "-post" switch would be
+used instead. Applications may provide a different syntax for
+supporting this distinction, and some may simply not provide it at all
+("-pre" is almost always what you're after, in reality).
+
+How do I build a "dynamic" ENGINE?
+----------------------------------
+
+This question is trickier - currently OpenSSL bundles various ENGINE
+implementations that are statically built in, and any application that
+calls the "ENGINE_load_builtin_engines()" function will automatically
+have all such ENGINEs available (and occupying memory). Applications
+that don't call that function have no ENGINEs available like that and
+would have to use "dynamic" to load any such ENGINE - but on the other
+hand such applications would only have the memory footprint of any
+ENGINEs explicitly loaded using user/admin provided control commands.
+The main advantage of not statically linking ENGINEs and only using
+"dynamic" for hardware support is that any installation using no
+"external" ENGINE suffers no unnecessary memory footprint from unused
+ENGINEs. Likewise, installations that do require an ENGINE incur the
+overheads from only *that* ENGINE once it has been loaded.
+
+Sounds good? Maybe, but currently building an ENGINE implementation as
+a shared-library that can be loaded by "dynamic" isn't automated in
+OpenSSL's build process. It can be done manually quite easily however.
+Such a shared-library can either be built with any OpenSSL code it
+needs statically linked in, or it can link dynamically against OpenSSL
+if OpenSSL itself is built as a shared library. The instructions are
+the same in each case, but in the former (statically linked any
+dependencies on OpenSSL) you must ensure OpenSSL is built with
+position-independent code ("PIC"). The default OpenSSL compilation may
+already specify the relevant flags to do this, but you should consult
+with your compiler documentation if you are in any doubt.
+
+This example will show building the "atalla" ENGINE in the
+crypto/engine/ directory as a shared-library for use via the "dynamic"
+ENGINE.
+
+ 1. "cd" to the crypto/engine/ directory of a pre-compiled OpenSSL
+ source tree.
+
+ 2. Recompile at least one source file so you can see all the compiler
+ flags (and syntax) being used to build normally. Eg;
+
+ touch hw_atalla.c ; make
+
+ will rebuild "hw_atalla.o" using all such flags.
+
+ 3. Manually enter the same compilation line to compile the
+ "hw_atalla.c" file but with the following two changes;
+ * add "-DENGINE_DYNAMIC_SUPPORT" to the command line switches,
+ * change the output file from "hw_atalla.o" to something new,
+ eg. "tmp_atalla.o"
+
+ 4. Link "tmp_atalla.o" into a shared-library using the top-level
+ OpenSSL libraries to resolve any dependencies. The syntax for doing
+ this depends heavily on your system/compiler and is a nightmare
+ known well to anyone who has worked with shared-library portability
+ before. 'gcc' on Linux, for example, would use the following syntax;
+
+ gcc -shared -o dyn_atalla.so tmp_atalla.o -L../.. -lcrypto
+
+ 5. Test your shared library using "openssl engine" as explained in the
+ previous section. Eg. from the top-level directory, you might try
+
+ apps/openssl engine -vvvv dynamic \
+ -pre SO_PATH:./crypto/engine/dyn_atalla.so -pre LOAD
+
+If the shared-library loads successfully, you will see both "-pre"
+commands marked as "SUCCESS" and the list of control commands
+displayed (because of "-vvvv") will be the control commands for the
+*atalla* ENGINE (ie. *not* the 'dynamic' ENGINE). You can also add
+the "-t" switch to the utility if you want it to try and initialise
+the atalla ENGINE for use to test any possible hardware/driver issues.
+
+PROBLEMS
+========
+
+It seems like the ENGINE part doesn't work too well with CryptoSwift on Win32.
+A quick test done right before the release showed that trying "openssl speed
+-engine cswift" generated errors. If the DSO gets enabled, an attempt is made
+to write at memory address 0x00000002.
diff --git a/README-FIPS.md b/README-FIPS.md
new file mode 100644
index 000000000000..ba88ff2c4e98
--- /dev/null
+++ b/README-FIPS.md
@@ -0,0 +1,86 @@
+OpenSSL FIPS support
+====================
+
+This release of OpenSSL includes a cryptographic module that can be
+FIPS 140-2 validated. The module is implemented as an OpenSSL provider.
+A provider is essentially a dynamically loadable module which implements
+cryptographic algorithms, see the [README-PROVIDERS](README-PROVIDERS.md) file
+for further details.
+
+A cryptographic module is only FIPS validated after it has gone through the complex
+FIPS 140 validation process. As this process takes a very long time, it is not
+possible to validate every minor release of OpenSSL.
+If you need a FIPS validated module then you must ONLY generate a FIPS provider
+using OpenSSL versions that have valid FIPS certificates. A FIPS certificate
+contains a link to a Security Policy, and you MUST follow the instructions
+in the Security Policy in order to be FIPS compliant.
+See <https://www.openssl.org/source/> for information related to OpenSSL
+FIPS certificates and Security Policies.
+
+Newer OpenSSL Releases that include security or bug fixes can be used to build
+all other components (such as the core API's, TLS and the default, base and
+legacy providers) without any restrictions, but the FIPS provider must be built
+as specified in the Security Policy (normally with a different version of the
+source code).
+
+The OpenSSL FIPS provider is a shared library called `fips.so` (on Unix), or
+resp. `fips.dll` (on Windows). The FIPS provider does not get built and
+installed automatically. To enable it, you need to configure OpenSSL using
+the `enable-fips` option.
+
+Installing the FIPS module
+==========================
+
+The following is only a guide.
+Please read the Security Policy for up to date installation instructions.
+
+If the FIPS provider is enabled, it gets installed automatically during the
+normal installation process. Simply follow the normal procedure (configure,
+make, make test, make install) as described in the [INSTALL](INSTALL.md) file.
+
+For example, on Unix the final command
+
+ $ make install
+
+effectively executes the following install targets
+
+ $ make install_sw
+ $ make install_ssldirs
+ $ make install_docs
+ $ make install_fips # for `enable-fips` only
+
+The `install_fips` make target can also be invoked explicitly to install
+the FIPS provider independently, without installing the rest of OpenSSL.
+
+The Installation of the FIPS provider consists of two steps. In the first step,
+the shared library is copied to its installed location, which by default is
+
+ /usr/local/lib/ossl-modules/fips.so on Unix, and
+ C:\Program Files\OpenSSL\lib\ossl-modules\fips.dll on Windows.
+
+In the second step, the `openssl fipsinstall` command is executed, which completes
+the installation by doing the following two things:
+
+- Runs the FIPS module self tests
+- Generates the so-called FIPS module configuration file containing information
+ about the module such as the self test status, and the module checksum.
+
+The FIPS module must have the self tests run, and the FIPS module config file
+output generated on every machine that it is to be used on. You must not copy
+the FIPS module config file output data from one machine to another.
+
+On Unix the `openssl fipsinstall` command will be invoked as follows by default:
+
+ $ openssl fipsinstall -out /usr/local/ssl/fipsmodule.cnf -module /usr/local/lib/ossl-modules/fips.so
+
+If you configured OpenSSL to be installed to a different location, the paths will
+vary accordingly. In the rare case that you need to install the fipsmodule.cnf
+to non-standard location, you can execute the `openssl fipsinstall` command manually.
+
+Using the FIPS Module in applications
+=====================================
+
+Documentation about using the FIPS module is available on the [fips_module(7)]
+manual page.
+
+ [fips_module(7)]: https://www.openssl.org/docs/man3.0/man7/fips_module.html
diff --git a/README-PROVIDERS.md b/README-PROVIDERS.md
new file mode 100644
index 000000000000..25e49c8618f7
--- /dev/null
+++ b/README-PROVIDERS.md
@@ -0,0 +1,145 @@
+Providers
+=========
+
+ - [Standard Providers](#standard-providers)
+ - [The Default Provider](#the-default-provider)
+ - [The Legacy Provider](#the-legacy-provider)
+ - [The FIPS Provider](#the-fips-provider)
+ - [The Base Provider](#the-base-provider)
+ - [The Null Provider](#the-null-provider)
+ - [Loading Providers](#loading-providers)
+
+Standard Providers
+==================
+
+Providers are containers for algorithm implementations. Whenever a cryptographic
+algorithm is used via the high level APIs a provider is selected. It is that
+provider implementation that actually does the required work. There are five
+providers distributed with OpenSSL. In the future we expect third parties to
+distribute their own providers which can be added to OpenSSL dynamically.
+Documentation about writing providers is available on the [provider(7)]
+manual page.
+
+ [provider(7)]: https://www.openssl.org/docs/man3.0/man7/provider.html
+
+The Default Provider
+--------------------
+
+The default provider collects together all of the standard built-in OpenSSL
+algorithm implementations. If an application doesn't specify anything else
+explicitly (e.g. in the application or via config), then this is the provider
+that will be used. It is loaded automatically the first time that we try to
+get an algorithm from a provider if no other provider has been loaded yet.
+If another provider has already been loaded then it won't be loaded
+automatically. Therefore if you want to use it in conjunction with other
+providers then you must load it explicitly.
+
+This is a "built-in" provider which means that it is compiled and linked
+into the libcrypto library and does not exist as a separate standalone module.
+
+The Legacy Provider
+-------------------
+
+The legacy provider is a collection of legacy algorithms that are either no
+longer in common use or considered insecure and strongly discouraged from use.
+However, some applications may need to use these algorithms for backwards
+compatibility reasons. This provider is **not** loaded by default.
+This may mean that some applications upgrading from earlier versions of OpenSSL
+may find that some algorithms are no longer available unless they load the
+legacy provider explicitly.
+
+Algorithms in the legacy provider include MD2, MD4, MDC2, RMD160, CAST5,
+BF (Blowfish), IDEA, SEED, RC2, RC4, RC5 and DES (but not 3DES).
+
+The FIPS Provider
+-----------------
+
+The FIPS provider contains a sub-set of the algorithm implementations available
+from the default provider, consisting of algorithms conforming to FIPS standards.
+It is intended that this provider will be FIPS140-2 validated.
+
+In some cases there may be minor behavioural differences between algorithm
+implementations in this provider compared to the equivalent algorithm in the
+default provider. This is typically in order to conform to FIPS standards.
+
+The Base Provider
+-----------------
+
+The base provider contains a small sub-set of non-cryptographic algorithms
+available in the default provider. For example, it contains algorithms to
+serialize and deserialize keys to files. If you do not load the default
+provider then you should always load this one instead (in particular, if
+you are using the FIPS provider).
+
+The Null Provider
+-----------------
+
+The null provider is "built-in" to libcrypto and contains no algorithm
+implementations. In order to guarantee that the default provider is not
+automatically loaded, the null provider can be loaded instead.
+
+This can be useful if you are using non-default library contexts and want
+to ensure that the default library context is never used unintentionally.
+
+Loading Providers
+=================
+
+Providers to be loaded can be specified in the OpenSSL config file.
+See the [config(5)] manual page for information about how to configure
+providers via the config file, and how to automatically activate them.
+
+ [config(5)]: https://www.openssl.org/docs/man3.0/man5/config.html
+
+The following is a minimal config file example to load and activate both
+the legacy and the default provider in the default library context.
+
+ openssl_conf = openssl_init
+
+ [openssl_init]
+ providers = provider_sect
+
+ [provider_sect]
+ default = default_sect
+ legacy = legacy_sect
+
+ [default_sect]
+ activate = 1
+
+ [legacy_sect]
+ activate = 1
+
+It is also possible to load providers programmatically. For example you can
+load the legacy provider into the default library context as shown below.
+Note that once you have explicitly loaded a provider into the library context
+the default provider will no longer be automatically loaded. Therefore you will
+often also want to explicitly load the default provider, as is done here:
+
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ #include <openssl/provider.h>
+
+ int main(void)
+ {
+ OSSL_PROVIDER *legacy;
+ OSSL_PROVIDER *deflt;
+
+ /* Load Multiple providers into the default (NULL) library context */
+ legacy = OSSL_PROVIDER_load(NULL, "legacy");
+ if (legacy == NULL) {
+ printf("Failed to load Legacy provider\n");
+ exit(EXIT_FAILURE);
+ }
+ deflt = OSSL_PROVIDER_load(NULL, "default");
+ if (deflt == NULL) {
+ printf("Failed to load Default provider\n");
+ OSSL_PROVIDER_unload(legacy);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Rest of application */
+
+ OSSL_PROVIDER_unload(legacy);
+ OSSL_PROVIDER_unload(deflt);
+ exit(EXIT_SUCCESS);
+ }
diff --git a/README.ENGINE b/README.ENGINE
deleted file mode 100644
index 230dc82a87ba..000000000000
--- a/README.ENGINE
+++ /dev/null
@@ -1,287 +0,0 @@
- ENGINE
- ======
-
- With OpenSSL 0.9.6, a new component was added to support alternative
- cryptography implementations, most commonly for interfacing with external
- crypto devices (eg. accelerator cards). This component is called ENGINE,
- and its presence in OpenSSL 0.9.6 (and subsequent bug-fix releases)
- caused a little confusion as 0.9.6** releases were rolled in two
- versions, a "standard" and an "engine" version. In development for 0.9.7,
- the ENGINE code has been merged into the main branch and will be present
- in the standard releases from 0.9.7 forwards.
-
- There are currently built-in ENGINE implementations for the following
- crypto devices:
-
- o Microsoft CryptoAPI
- o VIA Padlock
- o nCipher CHIL
-
- In addition, dynamic binding to external ENGINE implementations is now
- provided by a special ENGINE called "dynamic". See the "DYNAMIC ENGINE"
- section below for details.
-
- At this stage, a number of things are still needed and are being worked on:
-
- 1 Integration of EVP support.
- 2 Configuration support.
- 3 Documentation!
-
-1 With respect to EVP, this relates to support for ciphers and digests in
- the ENGINE model so that alternative implementations of existing
- algorithms/modes (or previously unimplemented ones) can be provided by
- ENGINE implementations.
-
-2 Configuration support currently exists in the ENGINE API itself, in the
- form of "control commands". These allow an application to expose to the
- user/admin the set of commands and parameter types a given ENGINE
- implementation supports, and for an application to directly feed string
- based input to those ENGINEs, in the form of name-value pairs. This is an
- extensible way for ENGINEs to define their own "configuration" mechanisms
- that are specific to a given ENGINE (eg. for a particular hardware
- device) but that should be consistent across *all* OpenSSL-based
- applications when they use that ENGINE. Work is in progress (or at least
- in planning) for supporting these control commands from the CONF (or
- NCONF) code so that applications using OpenSSL's existing configuration
- file format can have ENGINE settings specified in much the same way.
- Presently however, applications must use the ENGINE API itself to provide
- such functionality. To see first hand the types of commands available
- with the various compiled-in ENGINEs (see further down for dynamic
- ENGINEs), use the "engine" openssl utility with full verbosity, ie;
- openssl engine -vvvv
-
-3 Documentation? Volunteers welcome! The source code is reasonably well
- self-documenting, but some summaries and usage instructions are needed -
- moreover, they are needed in the same POD format the existing OpenSSL
- documentation is provided in. Any complete or incomplete contributions
- would help make this happen.
-
- STABILITY & BUG-REPORTS
- =======================
-
- What already exists is fairly stable as far as it has been tested, but
- the test base has been a bit small most of the time. For the most part,
- the vendors of the devices these ENGINEs support have contributed to the
- development and/or testing of the implementations, and *usually* (with no
- guarantees) have experience in using the ENGINE support to drive their
- devices from common OpenSSL-based applications. Bugs and/or inexplicable
- behaviour in using a specific ENGINE implementation should be sent to the
- author of that implementation (if it is mentioned in the corresponding C
- file), and in the case of implementations for commercial hardware
- devices, also through whatever vendor support channels are available. If
- none of this is possible, or the problem seems to be something about the
- ENGINE API itself (ie. not necessarily specific to a particular ENGINE
- implementation) then you should mail complete details to the relevant
- OpenSSL mailing list. For a definition of "complete details", refer to
- the OpenSSL "README" file. As for which list to send it to;
-
- openssl-users: if you are *using* the ENGINE abstraction, either in an
- pre-compiled application or in your own application code.
-
- openssl-dev: if you are discussing problems with OpenSSL source code.
-
- USAGE
- =====
-
- The default "openssl" ENGINE is always chosen when performing crypto
- operations unless you specify otherwise. You must actively tell the
- openssl utility commands to use anything else through a new command line
- switch called "-engine". Also, if you want to use the ENGINE support in
- your own code to do something similar, you must likewise explicitly
- select the ENGINE implementation you want.
-
- Depending on the type of hardware, system, and configuration, "settings"
- may need to be applied to an ENGINE for it to function as expected/hoped.
- The recommended way of doing this is for the application to support
- ENGINE "control commands" so that each ENGINE implementation can provide
- whatever configuration primitives it might require and the application
- can allow the user/admin (and thus the hardware vendor's support desk
- also) to provide any such input directly to the ENGINE implementation.
- This way, applications do not need to know anything specific to any
- device, they only need to provide the means to carry such user/admin
- input through to the ENGINE in question. Ie. this connects *you* (and
- your helpdesk) to the specific ENGINE implementation (and device), and
- allows application authors to not get buried in hassle supporting
- arbitrary devices they know (and care) nothing about.
-
- A new "openssl" utility, "openssl engine", has been added in that allows
- for testing and examination of ENGINE implementations. Basic usage
- instructions are available by specifying the "-?" command line switch.
-
- DYNAMIC ENGINES
- ===============
-
- The new "dynamic" ENGINE provides a low-overhead way to support ENGINE
- implementations that aren't pre-compiled and linked into OpenSSL-based
- applications. This could be because existing compiled-in implementations
- have known problems and you wish to use a newer version with an existing
- application. It could equally be because the application (or OpenSSL
- library) you are using simply doesn't have support for the ENGINE you
- wish to use, and the ENGINE provider (eg. hardware vendor) is providing
- you with a self-contained implementation in the form of a shared-library.
- The other use-case for "dynamic" is with applications that wish to
- maintain the smallest foot-print possible and so do not link in various
- ENGINE implementations from OpenSSL, but instead leaves you to provide
- them, if you want them, in the form of "dynamic"-loadable
- shared-libraries. It should be possible for hardware vendors to provide
- their own shared-libraries to support arbitrary hardware to work with
- applications based on OpenSSL 0.9.7 or later. If you're using an
- application based on 0.9.7 (or later) and the support you desire is only
- announced for versions later than the one you need, ask the vendor to
- backport their ENGINE to the version you need.
-
- How does "dynamic" work?
- ------------------------
- The dynamic ENGINE has a special flag in its implementation such that
- every time application code asks for the 'dynamic' ENGINE, it in fact
- gets its own copy of it. As such, multi-threaded code (or code that
- multiplexes multiple uses of 'dynamic' in a single application in any
- way at all) does not get confused by 'dynamic' being used to do many
- independent things. Other ENGINEs typically don't do this so there is
- only ever 1 ENGINE structure of its type (and reference counts are used
- to keep order). The dynamic ENGINE itself provides absolutely no
- cryptographic functionality, and any attempt to "initialise" the ENGINE
- automatically fails. All it does provide are a few "control commands"
- that can be used to control how it will load an external ENGINE
- implementation from a shared-library. To see these control commands,
- use the command-line;
-
- openssl engine -vvvv dynamic
-
- The "SO_PATH" control command should be used to identify the
- shared-library that contains the ENGINE implementation, and "NO_VCHECK"
- might possibly be useful if there is a minor version conflict and you
- (or a vendor helpdesk) is convinced you can safely ignore it.
- "ID" is probably only needed if a shared-library implements
- multiple ENGINEs, but if you know the engine id you expect to be using,
- it doesn't hurt to specify it (and this provides a sanity check if
- nothing else). "LIST_ADD" is only required if you actually wish the
- loaded ENGINE to be discoverable by application code later on using the
- ENGINE's "id". For most applications, this isn't necessary - but some
- application authors may have nifty reasons for using it. The "LOAD"
- command is the only one that takes no parameters and is the command
- that uses the settings from any previous commands to actually *load*
- the shared-library ENGINE implementation. If this command succeeds, the
- (copy of the) 'dynamic' ENGINE will magically morph into the ENGINE
- that has been loaded from the shared-library. As such, any control
- commands supported by the loaded ENGINE could then be executed as per
- normal. Eg. if ENGINE "foo" is implemented in the shared-library
- "libfoo.so" and it supports some special control command "CMD_FOO", the
- following code would load and use it (NB: obviously this code has no
- error checking);
-
- ENGINE *e = ENGINE_by_id("dynamic");
- ENGINE_ctrl_cmd_string(e, "SO_PATH", "/lib/libfoo.so", 0);
- ENGINE_ctrl_cmd_string(e, "ID", "foo", 0);
- ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0);
- ENGINE_ctrl_cmd_string(e, "CMD_FOO", "some input data", 0);
-
- For testing, the "openssl engine" utility can be useful for this sort
- of thing. For example the above code excerpt would achieve much the
- same result as;
-
- openssl engine dynamic \
- -pre SO_PATH:/lib/libfoo.so \
- -pre ID:foo \
- -pre LOAD \
- -pre "CMD_FOO:some input data"
-
- Or to simply see the list of commands supported by the "foo" ENGINE;
-
- openssl engine -vvvv dynamic \
- -pre SO_PATH:/lib/libfoo.so \
- -pre ID:foo \
- -pre LOAD
-
- Applications that support the ENGINE API and more specifically, the
- "control commands" mechanism, will provide some way for you to pass
- such commands through to ENGINEs. As such, you would select "dynamic"
- as the ENGINE to use, and the parameters/commands you pass would
- control the *actual* ENGINE used. Each command is actually a name-value
- pair and the value can sometimes be omitted (eg. the "LOAD" command).
- Whilst the syntax demonstrated in "openssl engine" uses a colon to
- separate the command name from the value, applications may provide
- their own syntax for making that separation (eg. a win32 registry
- key-value pair may be used by some applications). The reason for the
- "-pre" syntax in the "openssl engine" utility is that some commands
- might be issued to an ENGINE *after* it has been initialised for use.
- Eg. if an ENGINE implementation requires a smart-card to be inserted
- during initialisation (or a PIN to be typed, or whatever), there may be
- a control command you can issue afterwards to "forget" the smart-card
- so that additional initialisation is no longer possible. In
- applications such as web-servers, where potentially volatile code may
- run on the same host system, this may provide some arguable security
- value. In such a case, the command would be passed to the ENGINE after
- it has been initialised for use, and so the "-post" switch would be
- used instead. Applications may provide a different syntax for
- supporting this distinction, and some may simply not provide it at all
- ("-pre" is almost always what you're after, in reality).
-
- How do I build a "dynamic" ENGINE?
- ----------------------------------
- This question is trickier - currently OpenSSL bundles various ENGINE
- implementations that are statically built in, and any application that
- calls the "ENGINE_load_builtin_engines()" function will automatically
- have all such ENGINEs available (and occupying memory). Applications
- that don't call that function have no ENGINEs available like that and
- would have to use "dynamic" to load any such ENGINE - but on the other
- hand such applications would only have the memory footprint of any
- ENGINEs explicitly loaded using user/admin provided control commands.
- The main advantage of not statically linking ENGINEs and only using
- "dynamic" for hardware support is that any installation using no
- "external" ENGINE suffers no unnecessary memory footprint from unused
- ENGINEs. Likewise, installations that do require an ENGINE incur the
- overheads from only *that* ENGINE once it has been loaded.
-
- Sounds good? Maybe, but currently building an ENGINE implementation as
- a shared-library that can be loaded by "dynamic" isn't automated in
- OpenSSL's build process. It can be done manually quite easily however.
- Such a shared-library can either be built with any OpenSSL code it
- needs statically linked in, or it can link dynamically against OpenSSL
- if OpenSSL itself is built as a shared library. The instructions are
- the same in each case, but in the former (statically linked any
- dependencies on OpenSSL) you must ensure OpenSSL is built with
- position-independent code ("PIC"). The default OpenSSL compilation may
- already specify the relevant flags to do this, but you should consult
- with your compiler documentation if you are in any doubt.
-
- This example will show building the "atalla" ENGINE in the
- crypto/engine/ directory as a shared-library for use via the "dynamic"
- ENGINE.
- 1) "cd" to the crypto/engine/ directory of a pre-compiled OpenSSL
- source tree.
- 2) Recompile at least one source file so you can see all the compiler
- flags (and syntax) being used to build normally. Eg;
- touch hw_atalla.c ; make
- will rebuild "hw_atalla.o" using all such flags.
- 3) Manually enter the same compilation line to compile the
- "hw_atalla.c" file but with the following two changes;
- (a) add "-DENGINE_DYNAMIC_SUPPORT" to the command line switches,
- (b) change the output file from "hw_atalla.o" to something new,
- eg. "tmp_atalla.o"
- 4) Link "tmp_atalla.o" into a shared-library using the top-level
- OpenSSL libraries to resolve any dependencies. The syntax for doing
- this depends heavily on your system/compiler and is a nightmare
- known well to anyone who has worked with shared-library portability
- before. 'gcc' on Linux, for example, would use the following syntax;
- gcc -shared -o dyn_atalla.so tmp_atalla.o -L../.. -lcrypto
- 5) Test your shared library using "openssl engine" as explained in the
- previous section. Eg. from the top-level directory, you might try;
- apps/openssl engine -vvvv dynamic \
- -pre SO_PATH:./crypto/engine/dyn_atalla.so -pre LOAD
- If the shared-library loads successfully, you will see both "-pre"
- commands marked as "SUCCESS" and the list of control commands
- displayed (because of "-vvvv") will be the control commands for the
- *atalla* ENGINE (ie. *not* the 'dynamic' ENGINE). You can also add
- the "-t" switch to the utility if you want it to try and initialise
- the atalla ENGINE for use to test any possible hardware/driver
- issues.
-
- PROBLEMS
- ========
-
- It seems like the ENGINE part doesn't work too well with CryptoSwift on Win32.
- A quick test done right before the release showed that trying "openssl speed
- -engine cswift" generated errors. If the DSO gets enabled, an attempt is made
- to write at memory address 0x00000002.
-
diff --git a/README.FIPS b/README.FIPS
deleted file mode 100644
index 859348664ef6..000000000000
--- a/README.FIPS
+++ /dev/null
@@ -1 +0,0 @@
-This release does not support a FIPS 140-2 validated module.
diff --git a/README.md b/README.md
new file mode 100644
index 000000000000..f2f4fd39ad05
--- /dev/null
+++ b/README.md
@@ -0,0 +1,224 @@
+Welcome to the OpenSSL Project
+==============================
+
+[![openssl logo]][www.openssl.org]
+
+[![github actions ci badge]][github actions ci]
+[![appveyor badge]][appveyor jobs]
+
+OpenSSL is a robust, commercial-grade, full-featured Open Source Toolkit
+for the Transport Layer Security (TLS) protocol formerly known as the
+Secure Sockets Layer (SSL) protocol. The protocol implementation is based
+on a full-strength general purpose cryptographic library, which can also
+be used stand-alone.
+
+OpenSSL is descended from the SSLeay library developed by Eric A. Young
+and Tim J. Hudson.
+
+The official Home Page of the OpenSSL Project is [www.openssl.org].
+
+Table of Contents
+=================
+
+ - [Overview](#overview)
+ - [Download](#download)
+ - [Build and Install](#build-and-install)
+ - [Documentation](#documentation)
+ - [License](#license)
+ - [Support](#support)
+ - [Contributing](#contributing)
+ - [Legalities](#legalities)
+
+Overview
+========
+
+The OpenSSL toolkit includes:
+
+- **libssl**
+ an implementation of all TLS protocol versions up to TLSv1.3 ([RFC 8446]).
+
+- **libcrypto**
+ a full-strength general purpose cryptographic library. It constitutes the
+ basis of the TLS implementation, but can also be used independently.
+
+- **openssl**
+ the OpenSSL command line tool, a swiss army knife for cryptographic tasks,
+ testing and analyzing. It can be used for
+ - creation of key parameters
+ - creation of X.509 certificates, CSRs and CRLs
+ - calculation of message digests
+ - encryption and decryption
+ - SSL/TLS client and server tests
+ - handling of S/MIME signed or encrypted mail
+ - and more...
+
+Download
+========
+
+For Production Use
+------------------
+
+Source code tarballs of the official releases can be downloaded from
+[www.openssl.org/source](https://www.openssl.org/source).
+The OpenSSL project does not distribute the toolkit in binary form.
+
+However, for a large variety of operating systems precompiled versions
+of the OpenSSL toolkit are available. In particular on Linux and other
+Unix operating systems it is normally recommended to link against the
+precompiled shared libraries provided by the distributor or vendor.
+
+For Testing and Development
+---------------------------
+
+Although testing and development could in theory also be done using
+the source tarballs, having a local copy of the git repository with
+the entire project history gives you much more insight into the
+code base.
+
+The official OpenSSL Git Repository is located at [git.openssl.org].
+There is a GitHub mirror of the repository at [github.com/openssl/openssl],
+which is updated automatically from the former on every commit.
+
+A local copy of the Git Repository can be obtained by cloning it from
+the original OpenSSL repository using
+
+ git clone git://git.openssl.org/openssl.git
+
+or from the GitHub mirror using
+
+ git clone https://github.com/openssl/openssl.git
+
+If you intend to contribute to OpenSSL, either to fix bugs or contribute
+new features, you need to fork the OpenSSL repository openssl/openssl on
+GitHub and clone your public fork instead.
+
+ git clone https://github.com/yourname/openssl.git
+
+This is necessary, because all development of OpenSSL nowadays is done via
+GitHub pull requests. For more details, see [Contributing](#contributing).
+
+Build and Install
+=================
+
+After obtaining the Source, have a look at the [INSTALL](INSTALL.md) file for
+detailed instructions about building and installing OpenSSL. For some
+platforms, the installation instructions are amended by a platform specific
+document.
+
+ * [Notes for UNIX-like platforms](NOTES-UNIX.md)
+ * [Notes for Android platforms](NOTES-ANDROID.md)
+ * [Notes for Windows platforms](NOTES-WINDOWS.md)
+ * [Notes for the DOS platform with DJGPP](NOTES-DJGPP.md)
+ * [Notes for the OpenVMS platform](NOTES-VMS.md)
+ * [Notes on Perl](NOTES-PERL.md)
+ * [Notes on Valgrind](NOTES-VALGRIND.md)
+
+Specific notes on upgrading to OpenSSL 3.0 from previous versions can be found
+in the [migration_guide(7ossl)] manual page.
+
+Documentation
+=============
+
+Manual Pages
+------------
+
+The manual pages for the master branch and all current stable releases are
+available online.
+
+- [OpenSSL master](https://www.openssl.org/docs/manmaster)
+- [OpenSSL 3.0](https://www.openssl.org/docs/man3.0)
+- [OpenSSL 1.1.1](https://www.openssl.org/docs/man1.1.1)
+
+Wiki
+----
+
+There is a Wiki at [wiki.openssl.org] which is currently not very active.
+It contains a lot of useful information, not all of which is up to date.
+
+License
+=======
+
+OpenSSL is licensed under the Apache License 2.0, which means that
+you are free to get and use it for commercial and non-commercial
+purposes as long as you fulfill its conditions.
+
+See the [LICENSE.txt](LICENSE.txt) file for more details.
+
+Support
+=======
+
+There are various ways to get in touch. The correct channel depends on
+your requirement. see the [SUPPORT](SUPPORT.md) file for more details.
+
+Contributing
+============
+
+If you are interested and willing to contribute to the OpenSSL project,
+please take a look at the [CONTRIBUTING](CONTRIBUTING.md) file.
+
+Legalities
+==========
+
+A number of nations restrict the use or export of cryptography. If you are
+potentially subject to such restrictions you should seek legal advice before
+attempting to develop or distribute cryptographic code.
+
+Copyright
+=========
+
+Copyright (c) 1998-2022 The OpenSSL Project
+
+Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson
+
+All rights reserved.
+
+<!-- Links -->
+
+[www.openssl.org]:
+ <https://www.openssl.org>
+ "OpenSSL Homepage"
+
+[git.openssl.org]:
+ <https://git.openssl.org>
+ "OpenSSL Git Repository"
+
+[git.openssl.org]:
+ <https://git.openssl.org>
+ "OpenSSL Git Repository"
+
+[github.com/openssl/openssl]:
+ <https://github.com/openssl/openssl>
+ "OpenSSL GitHub Mirror"
+
+[wiki.openssl.org]:
+ <https://wiki.openssl.org>
+ "OpenSSL Wiki"
+
+[migration_guide(7ossl)]:
+ <https://www.openssl.org/docs/man3.0/man7/migration_guide.html>
+ "OpenSSL Migration Guide"
+
+[RFC 8446]:
+ <https://tools.ietf.org/html/rfc8446>
+
+<!-- Logos and Badges -->
+
+[openssl logo]:
+ doc/images/openssl.svg
+ "OpenSSL Logo"
+
+[github actions ci badge]:
+ <https://github.com/openssl/openssl/workflows/GitHub%20CI/badge.svg>
+ "GitHub Actions CI Status"
+
+[github actions ci]:
+ <https://github.com/openssl/openssl/actions?query=workflow%3A%22GitHub+CI%22>
+ "GitHub Actions CI"
+
+[appveyor badge]:
+ <https://ci.appveyor.com/api/projects/status/8e10o7xfrg73v98f/branch/master?svg=true>
+ "AppVeyor Build Status"
+
+[appveyor jobs]:
+ <https://ci.appveyor.com/project/openssl/openssl/branch/master>
+ "AppVeyor Jobs"
diff --git a/SUPPORT.md b/SUPPORT.md
new file mode 100644
index 000000000000..c0b6babe89ad
--- /dev/null
+++ b/SUPPORT.md
@@ -0,0 +1,93 @@
+OpenSSL User Support resources
+==============================
+
+See the <https://www.openssl.org/support/contracts.html> for details on how to
+obtain commercial technical support.
+
+If you have general questions about using OpenSSL
+-------------------------------------------------
+
+In this case the [openssl-users] mailing list is the right place for you.
+The list is not only watched by the OpenSSL team members, but also by many
+other OpenSSL users. Here you will most likely get the answer to your questions.
+An overview over the [mailing lists](#mailing-lists) can be found below.
+
+If you think you found a Bug
+----------------------------
+
+*NOTE: this section assumes that you want to report it or figure it out and
+fix it. What's written here is not to be taken as a recipe for how to get a
+working production installation*
+
+If you have any problems with OpenSSL then please take the following steps
+first:
+
+- Search the mailing lists and/or the GitHub issues to find out whether
+ the problem has already been reported.
+- Download the latest version from the repository to see if the problem
+ has already been addressed.
+- Configure without assembler support (`no-asm`) and check whether the
+ problem persists.
+- Remove compiler optimization flags.
+
+Please keep in mind: Just because something doesn't work the way you expect
+does not mean it is necessarily a bug in OpenSSL. If you are not sure,
+consider searching the mail archives and posting a question to the
+[openssl-users] mailing list first.
+
+### Open an Issue
+
+If you wish to report a bug, please open an [issue][github-issues] on GitHub
+and include the following information:
+
+- OpenSSL version: output of `openssl version -a`
+- Configuration data: output of `perl configdata.pm --dump`
+- OS Name, Version, Hardware platform
+- Compiler Details (name, version)
+- Application Details (name, version)
+- Problem Description (steps that will reproduce the problem, if known)
+- Stack Traceback (if the application dumps core)
+
+Not only errors in the software, also errors in the documentation, in
+particular the manual pages, can be reported as issues.
+
+### Submit a Pull Request
+
+The fastest way to get a bug fixed is to fix it yourself ;-). If you are
+experienced in programming and know how to fix the bug, you can open a
+pull request. The details are covered in the [Contributing][contributing] section.
+
+Don't hesitate to open a pull request, even if it's only a small change
+like a grammatical or typographical error in the documentation.
+
+Mailing Lists
+=============
+
+The OpenSSL maintains a number of [mailing lists] for various purposes.
+The most important lists are:
+
+- [openssl-users] for general questions about using the OpenSSL software
+ and discussions between OpenSSL users.
+
+- [openssl-announce] for official announcements to the OpenSSL community.
+
+- [openssl-project] for discussion about the development roadmap
+ and governance.
+
+Only subscribers can post to [openssl-users] or [openssl-project]. The
+archives are made public, however. For more information, see the [mailing
+lists] page.
+
+There was an [openssl-dev] list that has been discontinued since development
+is now taking place in the form of GitHub pull requests. Although not active
+anymore, the searchable archive may still contain useful information.
+
+<!-- Links -->
+
+[mailing lists]: https://www.openssl.org/community/mailinglists.html
+[openssl-users]: https://mta.openssl.org/mailman/listinfo/openssl-users
+[openssl-announce]: https://mta.openssl.org/mailman/listinfo/openssl-announce
+[openssl-project]: https://mta.openssl.org/mailman/listinfo/openssl-project
+[openssl-dev]: https://mta.openssl.org/mailman/listinfo/openssl-dev
+[github-issues]: https://github.com/openssl/openssl/issues/new/choose
+[contributing]: https://github.com/openssl/openssl/blob/master/CONTRIBUTING.md
diff --git a/VERSION.dat b/VERSION.dat
new file mode 100644
index 000000000000..375a0de7e128
--- /dev/null
+++ b/VERSION.dat
@@ -0,0 +1,7 @@
+MAJOR=3
+MINOR=0
+PATCH=8
+PRE_RELEASE_TAG=
+BUILD_METADATA=
+RELEASE_DATE="7 Feb 2023"
+SHLIB_VERSION=3
diff --git a/apps/CA.pl.in b/apps/CA.pl.in
index db3cc383189e..f029470005d9 100644
--- a/apps/CA.pl.in
+++ b/apps/CA.pl.in
@@ -1,7 +1,7 @@
#!{- $config{HASHBANGPERL} -}
-# Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -14,57 +14,63 @@
use strict;
use warnings;
-my $openssl = "openssl";
-if(defined $ENV{'OPENSSL'}) {
- $openssl = $ENV{'OPENSSL'};
-} else {
- $ENV{'OPENSSL'} = $openssl;
-}
-
my $verbose = 1;
+my @OPENSSL_CMDS = ("req", "ca", "pkcs12", "x509", "verify");
-my $OPENSSL_CONFIG = $ENV{"OPENSSL_CONFIG"} || "";
-my $DAYS = "-days 365";
-my $CADAYS = "-days 1095"; # 3 years
+my $openssl = $ENV{'OPENSSL'} // "openssl";
+$ENV{'OPENSSL'} = $openssl;
+my $OPENSSL_CONFIG = $ENV{"OPENSSL_CONFIG"} // "";
+
+# Command invocations.
my $REQ = "$openssl req $OPENSSL_CONFIG";
my $CA = "$openssl ca $OPENSSL_CONFIG";
my $VERIFY = "$openssl verify";
my $X509 = "$openssl x509";
my $PKCS12 = "$openssl pkcs12";
-# default openssl.cnf file has setup as per the following
+# Default values for various configuration settings.
my $CATOP = "./demoCA";
my $CAKEY = "cakey.pem";
my $CAREQ = "careq.pem";
my $CACERT = "cacert.pem";
my $CACRL = "crl.pem";
-my $DIRMODE = 0777;
-
+my $DAYS = "-days 365";
+my $CADAYS = "-days 1095"; # 3 years
my $NEWKEY = "newkey.pem";
my $NEWREQ = "newreq.pem";
my $NEWCERT = "newcert.pem";
my $NEWP12 = "newcert.p12";
-my $RET = 0;
+
+# Commandline parsing
+my %EXTRA;
my $WHAT = shift @ARGV || "";
-my @OPENSSL_CMDS = ("req", "ca", "pkcs12", "x509", "verify");
-my %EXTRA = extra_args(\@ARGV, "-extra-");
-my $FILE;
-
-sub extra_args {
- my ($args_ref, $arg_prefix) = @_;
- my %eargs = map {
- if ($_ < $#$args_ref) {
- my ($arg, $value) = splice(@$args_ref, $_, 2);
- $arg =~ s/$arg_prefix//;
- ($arg, $value);
- } else {
- ();
- }
- } reverse grep($$args_ref[$_] =~ /$arg_prefix/, 0..$#$args_ref);
- my %empty = map { ($_, "") } @OPENSSL_CMDS;
- return (%empty, %eargs);
+@ARGV = parse_extra(@ARGV);
+my $RET = 0;
+
+# Split out "-extra-CMD value", and return new |@ARGV|. Fill in
+# |EXTRA{CMD}| with list of values.
+sub parse_extra
+{
+ foreach ( @OPENSSL_CMDS ) {
+ $EXTRA{$_} = '';
+ }
+
+ my @result;
+ while ( scalar(@_) > 0 ) {
+ my $arg = shift;
+ if ( $arg !~ m/-extra-([a-z0-9]+)/ ) {
+ push @result, $arg;
+ next;
+ }
+ $arg =~ s/-extra-//;
+ die("Unknown \"-${arg}-extra\" option, exiting")
+ unless scalar grep { $arg eq $_ } @OPENSSL_CMDS;
+ $EXTRA{$arg} .= " " . shift;
+ }
+ return @result;
}
+
# See if reason for a CRL entry is valid; exit if not.
sub crl_reason_ok
{
@@ -113,19 +119,25 @@ sub run
if ( $WHAT =~ /^(-\?|-h|-help)$/ ) {
- print STDERR "usage: CA.pl -newcert | -newreq | -newreq-nodes | -xsign | -sign | -signCA | -signcert | -crl | -newca [-extra-cmd extra-params]\n";
- print STDERR " CA.pl -pkcs12 [-extra-pkcs12 extra-params] [certname]\n";
- print STDERR " CA.pl -verify [-extra-verify extra-params] certfile ...\n";
- print STDERR " CA.pl -revoke [-extra-ca extra-params] certfile [reason]\n";
+ print STDERR <<EOF;
+Usage:
+ CA.pl -newcert | -newreq | -newreq-nodes | -xsign | -sign | -signCA | -signcert | -crl | -newca [-extra-cmd parameter]
+ CA.pl -pkcs12 [certname]
+ CA.pl -verify certfile ...
+ CA.pl -revoke certfile [reason]
+EOF
exit 0;
}
+
if ($WHAT eq '-newcert' ) {
# create a certificate
- $RET = run("$REQ -new -x509 -keyout $NEWKEY -out $NEWCERT $DAYS $EXTRA{req}");
+ $RET = run("$REQ -new -x509 -keyout $NEWKEY -out $NEWCERT $DAYS"
+ . " $EXTRA{req}");
print "Cert is in $NEWCERT, private key is in $NEWKEY\n" if $RET == 0;
} elsif ($WHAT eq '-precert' ) {
# create a pre-certificate
- $RET = run("$REQ -x509 -precert -keyout $NEWKEY -out $NEWCERT $DAYS");
+ $RET = run("$REQ -x509 -precert -keyout $NEWKEY -out $NEWCERT $DAYS"
+ . " $EXTRA{req}");
print "Pre-cert is in $NEWCERT, private key is in $NEWKEY\n" if $RET == 0;
} elsif ($WHAT =~ /^\-newreq(\-nodes)?$/ ) {
# create a certificate request
@@ -133,11 +145,20 @@ if ($WHAT eq '-newcert' ) {
print "Request is in $NEWREQ, private key is in $NEWKEY\n" if $RET == 0;
} elsif ($WHAT eq '-newca' ) {
# create the directory hierarchy
- mkdir ${CATOP}, $DIRMODE;
- mkdir "${CATOP}/certs", $DIRMODE;
- mkdir "${CATOP}/crl", $DIRMODE ;
- mkdir "${CATOP}/newcerts", $DIRMODE;
- mkdir "${CATOP}/private", $DIRMODE;
+ my @dirs = ( "${CATOP}", "${CATOP}/certs", "${CATOP}/crl",
+ "${CATOP}/newcerts", "${CATOP}/private" );
+ die "${CATOP}/index.txt exists.\nRemove old sub-tree to proceed,"
+ if -f "${CATOP}/index.txt";
+ die "${CATOP}/serial exists.\nRemove old sub-tree to proceed,"
+ if -f "${CATOP}/serial";
+ foreach my $d ( @dirs ) {
+ if ( -d $d ) {
+ warn "Directory $d exists" if -d $d;
+ } else {
+ mkdir $d or die "Can't mkdir $d, $!";
+ }
+ }
+
open OUT, ">${CATOP}/index.txt";
close OUT;
open OUT, ">${CATOP}/crlnumber";
@@ -145,6 +166,7 @@ if ($WHAT eq '-newcert' ) {
close OUT;
# ask user for existing CA certificate
print "CA certificate filename (or enter to create)\n";
+ my $FILE;
$FILE = "" unless defined($FILE = <STDIN>);
$FILE =~ s{\R$}{};
if ($FILE ne "") {
@@ -152,43 +174,43 @@ if ($WHAT eq '-newcert' ) {
copy_pemfile($FILE,"${CATOP}/$CACERT", "CERTIFICATE");
} else {
print "Making CA certificate ...\n";
- $RET = run("$REQ -new -keyout"
- . " ${CATOP}/private/$CAKEY"
+ $RET = run("$REQ -new -keyout ${CATOP}/private/$CAKEY"
. " -out ${CATOP}/$CAREQ $EXTRA{req}");
$RET = run("$CA -create_serial"
. " -out ${CATOP}/$CACERT $CADAYS -batch"
. " -keyfile ${CATOP}/private/$CAKEY -selfsign"
- . " -extensions v3_ca $EXTRA{ca}"
- . " -infiles ${CATOP}/$CAREQ") if $RET == 0;
+ . " -extensions v3_ca"
+ . " -infiles ${CATOP}/$CAREQ $EXTRA{ca}") if $RET == 0;
print "CA certificate is in ${CATOP}/$CACERT\n" if $RET == 0;
}
} elsif ($WHAT eq '-pkcs12' ) {
my $cname = $ARGV[0];
$cname = "My Certificate" unless defined $cname;
$RET = run("$PKCS12 -in $NEWCERT -inkey $NEWKEY"
- . " -certfile ${CATOP}/$CACERT"
- . " -out $NEWP12"
+ . " -certfile ${CATOP}/$CACERT -out $NEWP12"
. " -export -name \"$cname\" $EXTRA{pkcs12}");
print "PKCS #12 file is in $NEWP12\n" if $RET == 0;
} elsif ($WHAT eq '-xsign' ) {
- $RET = run("$CA -policy policy_anything $EXTRA{ca} -infiles $NEWREQ");
+ $RET = run("$CA -policy policy_anything -infiles $NEWREQ $EXTRA{ca}");
} elsif ($WHAT eq '-sign' ) {
- $RET = run("$CA -policy policy_anything -out $NEWCERT $EXTRA{ca} -infiles $NEWREQ");
+ $RET = run("$CA -policy policy_anything -out $NEWCERT"
+ . " -infiles $NEWREQ $EXTRA{ca}");
print "Signed certificate is in $NEWCERT\n" if $RET == 0;
} elsif ($WHAT eq '-signCA' ) {
$RET = run("$CA -policy policy_anything -out $NEWCERT"
- . " -extensions v3_ca $EXTRA{ca} -infiles $NEWREQ");
+ . " -extensions v3_ca -infiles $NEWREQ $EXTRA{ca}");
print "Signed CA certificate is in $NEWCERT\n" if $RET == 0;
} elsif ($WHAT eq '-signcert' ) {
$RET = run("$X509 -x509toreq -in $NEWREQ -signkey $NEWREQ"
. " -out tmp.pem $EXTRA{x509}");
$RET = run("$CA -policy policy_anything -out $NEWCERT"
- . "$EXTRA{ca} -infiles tmp.pem") if $RET == 0;
+ . "-infiles tmp.pem $EXTRA{ca}") if $RET == 0;
print "Signed certificate is in $NEWCERT\n" if $RET == 0;
} elsif ($WHAT eq '-verify' ) {
my @files = @ARGV ? @ARGV : ( $NEWCERT );
- my $file;
- foreach $file (@files) {
+ foreach my $file (@files) {
+ # -CAfile quoted for VMS, since the C RTL downcases all unquoted
+ # arguments to C programs
my $status = run("$VERIFY \"-CAfile\" ${CATOP}/$CACERT $file $EXTRA{verify}");
$RET = $status if $status != 0;
}
diff --git a/apps/app_rand.c b/apps/app_rand.c
deleted file mode 100644
index 2b0bbde03423..000000000000
--- a/apps/app_rand.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "apps.h"
-#include <openssl/bio.h>
-#include <openssl/err.h>
-#include <openssl/rand.h>
-#include <openssl/conf.h>
-
-static char *save_rand_file;
-
-void app_RAND_load_conf(CONF *c, const char *section)
-{
- const char *randfile = NCONF_get_string(c, section, "RANDFILE");
-
- if (randfile == NULL) {
- ERR_clear_error();
- return;
- }
- if (RAND_load_file(randfile, -1) < 0) {
- BIO_printf(bio_err, "Can't load %s into RNG\n", randfile);
- ERR_print_errors(bio_err);
- }
- if (save_rand_file == NULL)
- save_rand_file = OPENSSL_strdup(randfile);
-}
-
-static int loadfiles(char *name)
-{
- char *p;
- int last, ret = 1;
-
- for ( ; ; ) {
- last = 0;
- for (p = name; *p != '\0' && *p != LIST_SEPARATOR_CHAR; p++)
- continue;
- if (*p == '\0')
- last = 1;
- *p = '\0';
- if (RAND_load_file(name, -1) < 0) {
- BIO_printf(bio_err, "Can't load %s into RNG\n", name);
- ERR_print_errors(bio_err);
- ret = 0;
- }
- if (last)
- break;
- name = p + 1;
- if (*name == '\0')
- break;
- }
- return ret;
-}
-
-void app_RAND_write(void)
-{
- if (save_rand_file == NULL)
- return;
- if (RAND_write_file(save_rand_file) == -1) {
- BIO_printf(bio_err, "Cannot write random bytes:\n");
- ERR_print_errors(bio_err);
- }
- OPENSSL_free(save_rand_file);
- save_rand_file = NULL;
-}
-
-
-/*
- * See comments in opt_verify for explanation of this.
- */
-enum r_range { OPT_R_ENUM };
-
-int opt_rand(int opt)
-{
- switch ((enum r_range)opt) {
- case OPT_R__FIRST:
- case OPT_R__LAST:
- break;
- case OPT_R_RAND:
- return loadfiles(opt_arg());
- break;
- case OPT_R_WRITERAND:
- OPENSSL_free(save_rand_file);
- save_rand_file = OPENSSL_strdup(opt_arg());
- break;
- }
- return 1;
-}
diff --git a/apps/apps.c b/apps/apps.c
deleted file mode 100644
index f2447fb0bef8..000000000000
--- a/apps/apps.c
+++ /dev/null
@@ -1,2796 +0,0 @@
-/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
-/*
- * On VMS, you need to define this to get the declaration of fileno(). The
- * value 2 is to make sure no function defined in POSIX-2 is left undefined.
- */
-# define _POSIX_C_SOURCE 2
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#ifndef OPENSSL_NO_POSIX_IO
-# include <sys/stat.h>
-# include <fcntl.h>
-#endif
-#include <ctype.h>
-#include <errno.h>
-#include <openssl/err.h>
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-#include <openssl/pem.h>
-#include <openssl/pkcs12.h>
-#include <openssl/ui.h>
-#include <openssl/safestack.h>
-#ifndef OPENSSL_NO_ENGINE
-# include <openssl/engine.h>
-#endif
-#ifndef OPENSSL_NO_RSA
-# include <openssl/rsa.h>
-#endif
-#include <openssl/bn.h>
-#include <openssl/ssl.h>
-#include "apps.h"
-
-#ifdef _WIN32
-static int WIN32_rename(const char *from, const char *to);
-# define rename(from,to) WIN32_rename((from),(to))
-#endif
-
-#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
-# include <conio.h>
-#endif
-
-#if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32)
-# define _kbhit kbhit
-#endif
-
-typedef struct {
- const char *name;
- unsigned long flag;
- unsigned long mask;
-} NAME_EX_TBL;
-
-static UI_METHOD *ui_method = NULL;
-static const UI_METHOD *ui_fallback_method = NULL;
-
-static int set_table_opts(unsigned long *flags, const char *arg,
- const NAME_EX_TBL * in_tbl);
-static int set_multi_opts(unsigned long *flags, const char *arg,
- const NAME_EX_TBL * in_tbl);
-
-int app_init(long mesgwin);
-
-int chopup_args(ARGS *arg, char *buf)
-{
- int quoted;
- char c = '\0', *p = NULL;
-
- arg->argc = 0;
- if (arg->size == 0) {
- arg->size = 20;
- arg->argv = app_malloc(sizeof(*arg->argv) * arg->size, "argv space");
- }
-
- for (p = buf;;) {
- /* Skip whitespace. */
- while (*p && isspace(_UC(*p)))
- p++;
- if (!*p)
- break;
-
- /* The start of something good :-) */
- if (arg->argc >= arg->size) {
- char **tmp;
- arg->size += 20;
- tmp = OPENSSL_realloc(arg->argv, sizeof(*arg->argv) * arg->size);
- if (tmp == NULL)
- return 0;
- arg->argv = tmp;
- }
- quoted = *p == '\'' || *p == '"';
- if (quoted)
- c = *p++;
- arg->argv[arg->argc++] = p;
-
- /* now look for the end of this */
- if (quoted) {
- while (*p && *p != c)
- p++;
- *p++ = '\0';
- } else {
- while (*p && !isspace(_UC(*p)))
- p++;
- if (*p)
- *p++ = '\0';
- }
- }
- arg->argv[arg->argc] = NULL;
- return 1;
-}
-
-#ifndef APP_INIT
-int app_init(long mesgwin)
-{
- return 1;
-}
-#endif
-
-int ctx_set_verify_locations(SSL_CTX *ctx, const char *CAfile,
- const char *CApath, int noCAfile, int noCApath)
-{
- if (CAfile == NULL && CApath == NULL) {
- if (!noCAfile && SSL_CTX_set_default_verify_file(ctx) <= 0)
- return 0;
- if (!noCApath && SSL_CTX_set_default_verify_dir(ctx) <= 0)
- return 0;
-
- return 1;
- }
- return SSL_CTX_load_verify_locations(ctx, CAfile, CApath);
-}
-
-#ifndef OPENSSL_NO_CT
-
-int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path)
-{
- if (path == NULL)
- return SSL_CTX_set_default_ctlog_list_file(ctx);
-
- return SSL_CTX_set_ctlog_list_file(ctx, path);
-}
-
-#endif
-
-static unsigned long nmflag = 0;
-static char nmflag_set = 0;
-
-int set_nameopt(const char *arg)
-{
- int ret = set_name_ex(&nmflag, arg);
-
- if (ret)
- nmflag_set = 1;
-
- return ret;
-}
-
-unsigned long get_nameopt(void)
-{
- return (nmflag_set) ? nmflag : XN_FLAG_ONELINE;
-}
-
-int dump_cert_text(BIO *out, X509 *x)
-{
- print_name(out, "subject=", X509_get_subject_name(x), get_nameopt());
- BIO_puts(out, "\n");
- print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt());
- BIO_puts(out, "\n");
-
- return 0;
-}
-
-static int ui_open(UI *ui)
-{
- int (*opener)(UI *ui) = UI_method_get_opener(ui_fallback_method);
-
- if (opener)
- return opener(ui);
- return 1;
-}
-
-static int ui_read(UI *ui, UI_STRING *uis)
-{
- int (*reader)(UI *ui, UI_STRING *uis) = NULL;
-
- if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
- && UI_get0_user_data(ui)) {
- switch (UI_get_string_type(uis)) {
- case UIT_PROMPT:
- case UIT_VERIFY:
- {
- const char *password =
- ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
- if (password && password[0] != '\0') {
- UI_set_result(ui, uis, password);
- return 1;
- }
- }
- break;
- case UIT_NONE:
- case UIT_BOOLEAN:
- case UIT_INFO:
- case UIT_ERROR:
- break;
- }
- }
-
- reader = UI_method_get_reader(ui_fallback_method);
- if (reader)
- return reader(ui, uis);
- return 1;
-}
-
-static int ui_write(UI *ui, UI_STRING *uis)
-{
- int (*writer)(UI *ui, UI_STRING *uis) = NULL;
-
- if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
- && UI_get0_user_data(ui)) {
- switch (UI_get_string_type(uis)) {
- case UIT_PROMPT:
- case UIT_VERIFY:
- {
- const char *password =
- ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
- if (password && password[0] != '\0')
- return 1;
- }
- break;
- case UIT_NONE:
- case UIT_BOOLEAN:
- case UIT_INFO:
- case UIT_ERROR:
- break;
- }
- }
-
- writer = UI_method_get_writer(ui_fallback_method);
- if (writer)
- return writer(ui, uis);
- return 1;
-}
-
-static int ui_close(UI *ui)
-{
- int (*closer)(UI *ui) = UI_method_get_closer(ui_fallback_method);
-
- if (closer)
- return closer(ui);
- return 1;
-}
-
-int setup_ui_method(void)
-{
- ui_fallback_method = UI_null();
-#ifndef OPENSSL_NO_UI_CONSOLE
- ui_fallback_method = UI_OpenSSL();
-#endif
- ui_method = UI_create_method("OpenSSL application user interface");
- UI_method_set_opener(ui_method, ui_open);
- UI_method_set_reader(ui_method, ui_read);
- UI_method_set_writer(ui_method, ui_write);
- UI_method_set_closer(ui_method, ui_close);
- return 0;
-}
-
-void destroy_ui_method(void)
-{
- if (ui_method) {
- UI_destroy_method(ui_method);
- ui_method = NULL;
- }
-}
-
-const UI_METHOD *get_ui_method(void)
-{
- return ui_method;
-}
-
-int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_tmp)
-{
- int res = 0;
- UI *ui = NULL;
- PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp;
-
- ui = UI_new_method(ui_method);
- if (ui) {
- int ok = 0;
- char *buff = NULL;
- int ui_flags = 0;
- const char *prompt_info = NULL;
- char *prompt;
- int pw_min_len = PW_MIN_LENGTH;
-
- if (cb_data != NULL && cb_data->prompt_info != NULL)
- prompt_info = cb_data->prompt_info;
- if (cb_data != NULL && cb_data->password != NULL
- && *(const char*)cb_data->password != '\0')
- pw_min_len = 1;
- else if (!verify)
- pw_min_len = 0;
- prompt = UI_construct_prompt(ui, "pass phrase", prompt_info);
- if (!prompt) {
- BIO_printf(bio_err, "Out of memory\n");
- UI_free(ui);
- return 0;
- }
-
- ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
- UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
-
- /* We know that there is no previous user data to return to us */
- (void)UI_add_user_data(ui, cb_data);
-
- ok = UI_add_input_string(ui, prompt, ui_flags, buf,
- pw_min_len, bufsiz - 1);
-
- if (ok >= 0 && verify) {
- buff = app_malloc(bufsiz, "password buffer");
- ok = UI_add_verify_string(ui, prompt, ui_flags, buff,
- pw_min_len, bufsiz - 1, buf);
- }
- if (ok >= 0)
- do {
- ok = UI_process(ui);
- } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
-
- OPENSSL_clear_free(buff, (unsigned int)bufsiz);
-
- if (ok >= 0)
- res = strlen(buf);
- if (ok == -1) {
- BIO_printf(bio_err, "User interface error\n");
- ERR_print_errors(bio_err);
- OPENSSL_cleanse(buf, (unsigned int)bufsiz);
- res = 0;
- }
- if (ok == -2) {
- BIO_printf(bio_err, "aborted!\n");
- OPENSSL_cleanse(buf, (unsigned int)bufsiz);
- res = 0;
- }
- UI_free(ui);
- OPENSSL_free(prompt);
- }
- return res;
-}
-
-static char *app_get_pass(const char *arg, int keepbio);
-
-int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2)
-{
- int same;
- if (arg2 == NULL || arg1 == NULL || strcmp(arg1, arg2))
- same = 0;
- else
- same = 1;
- if (arg1 != NULL) {
- *pass1 = app_get_pass(arg1, same);
- if (*pass1 == NULL)
- return 0;
- } else if (pass1 != NULL) {
- *pass1 = NULL;
- }
- if (arg2 != NULL) {
- *pass2 = app_get_pass(arg2, same ? 2 : 0);
- if (*pass2 == NULL)
- return 0;
- } else if (pass2 != NULL) {
- *pass2 = NULL;
- }
- return 1;
-}
-
-static char *app_get_pass(const char *arg, int keepbio)
-{
- char *tmp, tpass[APP_PASS_LEN];
- static BIO *pwdbio = NULL;
- int i;
-
- if (strncmp(arg, "pass:", 5) == 0)
- return OPENSSL_strdup(arg + 5);
- if (strncmp(arg, "env:", 4) == 0) {
- tmp = getenv(arg + 4);
- if (tmp == NULL) {
- BIO_printf(bio_err, "Can't read environment variable %s\n", arg + 4);
- return NULL;
- }
- return OPENSSL_strdup(tmp);
- }
- if (!keepbio || pwdbio == NULL) {
- if (strncmp(arg, "file:", 5) == 0) {
- pwdbio = BIO_new_file(arg + 5, "r");
- if (pwdbio == NULL) {
- BIO_printf(bio_err, "Can't open file %s\n", arg + 5);
- return NULL;
- }
-#if !defined(_WIN32)
- /*
- * Under _WIN32, which covers even Win64 and CE, file
- * descriptors referenced by BIO_s_fd are not inherited
- * by child process and therefore below is not an option.
- * It could have been an option if bss_fd.c was operating
- * on real Windows descriptors, such as those obtained
- * with CreateFile.
- */
- } else if (strncmp(arg, "fd:", 3) == 0) {
- BIO *btmp;
- i = atoi(arg + 3);
- if (i >= 0)
- pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
- if ((i < 0) || !pwdbio) {
- BIO_printf(bio_err, "Can't access file descriptor %s\n", arg + 3);
- return NULL;
- }
- /*
- * Can't do BIO_gets on an fd BIO so add a buffering BIO
- */
- btmp = BIO_new(BIO_f_buffer());
- pwdbio = BIO_push(btmp, pwdbio);
-#endif
- } else if (strcmp(arg, "stdin") == 0) {
- pwdbio = dup_bio_in(FORMAT_TEXT);
- if (!pwdbio) {
- BIO_printf(bio_err, "Can't open BIO for stdin\n");
- return NULL;
- }
- } else {
- BIO_printf(bio_err, "Invalid password argument \"%s\"\n", arg);
- return NULL;
- }
- }
- i = BIO_gets(pwdbio, tpass, APP_PASS_LEN);
- if (keepbio != 1) {
- BIO_free_all(pwdbio);
- pwdbio = NULL;
- }
- if (i <= 0) {
- BIO_printf(bio_err, "Error reading password from BIO\n");
- return NULL;
- }
- tmp = strchr(tpass, '\n');
- if (tmp != NULL)
- *tmp = 0;
- return OPENSSL_strdup(tpass);
-}
-
-CONF *app_load_config_bio(BIO *in, const char *filename)
-{
- long errorline = -1;
- CONF *conf;
- int i;
-
- conf = NCONF_new(NULL);
- i = NCONF_load_bio(conf, in, &errorline);
- if (i > 0)
- return conf;
-
- if (errorline <= 0) {
- BIO_printf(bio_err, "%s: Can't load ", opt_getprog());
- } else {
- BIO_printf(bio_err, "%s: Error on line %ld of ", opt_getprog(),
- errorline);
- }
- if (filename != NULL)
- BIO_printf(bio_err, "config file \"%s\"\n", filename);
- else
- BIO_printf(bio_err, "config input");
-
- NCONF_free(conf);
- return NULL;
-}
-
-CONF *app_load_config(const char *filename)
-{
- BIO *in;
- CONF *conf;
-
- in = bio_open_default(filename, 'r', FORMAT_TEXT);
- if (in == NULL)
- return NULL;
-
- conf = app_load_config_bio(in, filename);
- BIO_free(in);
- return conf;
-}
-
-CONF *app_load_config_quiet(const char *filename)
-{
- BIO *in;
- CONF *conf;
-
- in = bio_open_default_quiet(filename, 'r', FORMAT_TEXT);
- if (in == NULL)
- return NULL;
-
- conf = app_load_config_bio(in, filename);
- BIO_free(in);
- return conf;
-}
-
-int app_load_modules(const CONF *config)
-{
- CONF *to_free = NULL;
-
- if (config == NULL)
- config = to_free = app_load_config_quiet(default_config_file);
- if (config == NULL)
- return 1;
-
- if (CONF_modules_load(config, NULL, 0) <= 0) {
- BIO_printf(bio_err, "Error configuring OpenSSL modules\n");
- ERR_print_errors(bio_err);
- NCONF_free(to_free);
- return 0;
- }
- NCONF_free(to_free);
- return 1;
-}
-
-int add_oid_section(CONF *conf)
-{
- char *p;
- STACK_OF(CONF_VALUE) *sktmp;
- CONF_VALUE *cnf;
- int i;
-
- if ((p = NCONF_get_string(conf, NULL, "oid_section")) == NULL) {
- ERR_clear_error();
- return 1;
- }
- if ((sktmp = NCONF_get_section(conf, p)) == NULL) {
- BIO_printf(bio_err, "problem loading oid section %s\n", p);
- return 0;
- }
- for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
- cnf = sk_CONF_VALUE_value(sktmp, i);
- if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
- BIO_printf(bio_err, "problem creating object %s=%s\n",
- cnf->name, cnf->value);
- return 0;
- }
- }
- return 1;
-}
-
-static int load_pkcs12(BIO *in, const char *desc,
- pem_password_cb *pem_cb, void *cb_data,
- EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
-{
- const char *pass;
- char tpass[PEM_BUFSIZE];
- int len, ret = 0;
- PKCS12 *p12;
- p12 = d2i_PKCS12_bio(in, NULL);
- if (p12 == NULL) {
- BIO_printf(bio_err, "Error loading PKCS12 file for %s\n", desc);
- goto die;
- }
- /* See if an empty password will do */
- if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0)) {
- pass = "";
- } else {
- if (!pem_cb)
- pem_cb = (pem_password_cb *)password_callback;
- len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data);
- if (len < 0) {
- BIO_printf(bio_err, "Passphrase callback error for %s\n", desc);
- goto die;
- }
- if (len < PEM_BUFSIZE)
- tpass[len] = 0;
- if (!PKCS12_verify_mac(p12, tpass, len)) {
- BIO_printf(bio_err,
- "Mac verify error (wrong password?) in PKCS12 file for %s\n",
- desc);
- goto die;
- }
- pass = tpass;
- }
- ret = PKCS12_parse(p12, pass, pkey, cert, ca);
- die:
- PKCS12_free(p12);
- return ret;
-}
-
-#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK)
-static int load_cert_crl_http(const char *url, X509 **pcert, X509_CRL **pcrl)
-{
- char *host = NULL, *port = NULL, *path = NULL;
- BIO *bio = NULL;
- OCSP_REQ_CTX *rctx = NULL;
- int use_ssl, rv = 0;
- if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl))
- goto err;
- if (use_ssl) {
- BIO_puts(bio_err, "https not supported\n");
- goto err;
- }
- bio = BIO_new_connect(host);
- if (!bio || !BIO_set_conn_port(bio, port))
- goto err;
- rctx = OCSP_REQ_CTX_new(bio, 1024);
- if (rctx == NULL)
- goto err;
- if (!OCSP_REQ_CTX_http(rctx, "GET", path))
- goto err;
- if (!OCSP_REQ_CTX_add1_header(rctx, "Host", host))
- goto err;
- if (pcert) {
- do {
- rv = X509_http_nbio(rctx, pcert);
- } while (rv == -1);
- } else {
- do {
- rv = X509_CRL_http_nbio(rctx, pcrl);
- } while (rv == -1);
- }
-
- err:
- OPENSSL_free(host);
- OPENSSL_free(path);
- OPENSSL_free(port);
- BIO_free_all(bio);
- OCSP_REQ_CTX_free(rctx);
- if (rv != 1) {
- BIO_printf(bio_err, "Error loading %s from %s\n",
- pcert ? "certificate" : "CRL", url);
- ERR_print_errors(bio_err);
- }
- return rv;
-}
-#endif
-
-X509 *load_cert(const char *file, int format, const char *cert_descrip)
-{
- X509 *x = NULL;
- BIO *cert;
-
- if (format == FORMAT_HTTP) {
-#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK)
- load_cert_crl_http(file, &x, NULL);
-#endif
- return x;
- }
-
- if (file == NULL) {
- unbuffer(stdin);
- cert = dup_bio_in(format);
- } else {
- cert = bio_open_default(file, 'r', format);
- }
- if (cert == NULL)
- goto end;
-
- if (format == FORMAT_ASN1) {
- x = d2i_X509_bio(cert, NULL);
- } else if (format == FORMAT_PEM) {
- x = PEM_read_bio_X509_AUX(cert, NULL,
- (pem_password_cb *)password_callback, NULL);
- } else if (format == FORMAT_PKCS12) {
- if (!load_pkcs12(cert, cert_descrip, NULL, NULL, NULL, &x, NULL))
- goto end;
- } else {
- BIO_printf(bio_err, "bad input format specified for %s\n", cert_descrip);
- goto end;
- }
- end:
- if (x == NULL) {
- BIO_printf(bio_err, "unable to load certificate\n");
- ERR_print_errors(bio_err);
- }
- BIO_free(cert);
- return x;
-}
-
-X509_CRL *load_crl(const char *infile, int format)
-{
- X509_CRL *x = NULL;
- BIO *in = NULL;
-
- if (format == FORMAT_HTTP) {
-#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK)
- load_cert_crl_http(infile, NULL, &x);
-#endif
- return x;
- }
-
- in = bio_open_default(infile, 'r', format);
- if (in == NULL)
- goto end;
- if (format == FORMAT_ASN1) {
- x = d2i_X509_CRL_bio(in, NULL);
- } else if (format == FORMAT_PEM) {
- x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
- } else {
- BIO_printf(bio_err, "bad input format specified for input crl\n");
- goto end;
- }
- if (x == NULL) {
- BIO_printf(bio_err, "unable to load CRL\n");
- ERR_print_errors(bio_err);
- goto end;
- }
-
- end:
- BIO_free(in);
- return x;
-}
-
-EVP_PKEY *load_key(const char *file, int format, int maybe_stdin,
- const char *pass, ENGINE *e, const char *key_descrip)
-{
- BIO *key = NULL;
- EVP_PKEY *pkey = NULL;
- PW_CB_DATA cb_data;
-
- cb_data.password = pass;
- cb_data.prompt_info = file;
-
- if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) {
- BIO_printf(bio_err, "no keyfile specified\n");
- goto end;
- }
- if (format == FORMAT_ENGINE) {
- if (e == NULL) {
- BIO_printf(bio_err, "no engine specified\n");
- } else {
-#ifndef OPENSSL_NO_ENGINE
- if (ENGINE_init(e)) {
- pkey = ENGINE_load_private_key(e, file, ui_method, &cb_data);
- ENGINE_finish(e);
- }
- if (pkey == NULL) {
- BIO_printf(bio_err, "cannot load %s from engine\n", key_descrip);
- ERR_print_errors(bio_err);
- }
-#else
- BIO_printf(bio_err, "engines not supported\n");
-#endif
- }
- goto end;
- }
- if (file == NULL && maybe_stdin) {
- unbuffer(stdin);
- key = dup_bio_in(format);
- } else {
- key = bio_open_default(file, 'r', format);
- }
- if (key == NULL)
- goto end;
- if (format == FORMAT_ASN1) {
- pkey = d2i_PrivateKey_bio(key, NULL);
- } else if (format == FORMAT_PEM) {
- pkey = PEM_read_bio_PrivateKey(key, NULL,
- (pem_password_cb *)password_callback,
- &cb_data);
- } else if (format == FORMAT_PKCS12) {
- if (!load_pkcs12(key, key_descrip,
- (pem_password_cb *)password_callback, &cb_data,
- &pkey, NULL, NULL))
- goto end;
-#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4)
- } else if (format == FORMAT_MSBLOB) {
- pkey = b2i_PrivateKey_bio(key);
- } else if (format == FORMAT_PVK) {
- pkey = b2i_PVK_bio(key, (pem_password_cb *)password_callback,
- &cb_data);
-#endif
- } else {
- BIO_printf(bio_err, "bad input format specified for key file\n");
- goto end;
- }
- end:
- BIO_free(key);
- if (pkey == NULL) {
- BIO_printf(bio_err, "unable to load %s\n", key_descrip);
- ERR_print_errors(bio_err);
- }
- return pkey;
-}
-
-EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin,
- const char *pass, ENGINE *e, const char *key_descrip)
-{
- BIO *key = NULL;
- EVP_PKEY *pkey = NULL;
- PW_CB_DATA cb_data;
-
- cb_data.password = pass;
- cb_data.prompt_info = file;
-
- if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) {
- BIO_printf(bio_err, "no keyfile specified\n");
- goto end;
- }
- if (format == FORMAT_ENGINE) {
- if (e == NULL) {
- BIO_printf(bio_err, "no engine specified\n");
- } else {
-#ifndef OPENSSL_NO_ENGINE
- pkey = ENGINE_load_public_key(e, file, ui_method, &cb_data);
- if (pkey == NULL) {
- BIO_printf(bio_err, "cannot load %s from engine\n", key_descrip);
- ERR_print_errors(bio_err);
- }
-#else
- BIO_printf(bio_err, "engines not supported\n");
-#endif
- }
- goto end;
- }
- if (file == NULL && maybe_stdin) {
- unbuffer(stdin);
- key = dup_bio_in(format);
- } else {
- key = bio_open_default(file, 'r', format);
- }
- if (key == NULL)
- goto end;
- if (format == FORMAT_ASN1) {
- pkey = d2i_PUBKEY_bio(key, NULL);
- } else if (format == FORMAT_ASN1RSA) {
-#ifndef OPENSSL_NO_RSA
- RSA *rsa;
- rsa = d2i_RSAPublicKey_bio(key, NULL);
- if (rsa) {
- pkey = EVP_PKEY_new();
- if (pkey != NULL)
- EVP_PKEY_set1_RSA(pkey, rsa);
- RSA_free(rsa);
- } else
-#else
- BIO_printf(bio_err, "RSA keys not supported\n");
-#endif
- pkey = NULL;
- } else if (format == FORMAT_PEMRSA) {
-#ifndef OPENSSL_NO_RSA
- RSA *rsa;
- rsa = PEM_read_bio_RSAPublicKey(key, NULL,
- (pem_password_cb *)password_callback,
- &cb_data);
- if (rsa != NULL) {
- pkey = EVP_PKEY_new();
- if (pkey != NULL)
- EVP_PKEY_set1_RSA(pkey, rsa);
- RSA_free(rsa);
- } else
-#else
- BIO_printf(bio_err, "RSA keys not supported\n");
-#endif
- pkey = NULL;
- } else if (format == FORMAT_PEM) {
- pkey = PEM_read_bio_PUBKEY(key, NULL,
- (pem_password_cb *)password_callback,
- &cb_data);
-#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
- } else if (format == FORMAT_MSBLOB) {
- pkey = b2i_PublicKey_bio(key);
-#endif
- }
- end:
- BIO_free(key);
- if (pkey == NULL)
- BIO_printf(bio_err, "unable to load %s\n", key_descrip);
- return pkey;
-}
-
-static int load_certs_crls(const char *file, int format,
- const char *pass, const char *desc,
- STACK_OF(X509) **pcerts,
- STACK_OF(X509_CRL) **pcrls)
-{
- int i;
- BIO *bio;
- STACK_OF(X509_INFO) *xis = NULL;
- X509_INFO *xi;
- PW_CB_DATA cb_data;
- int rv = 0;
-
- cb_data.password = pass;
- cb_data.prompt_info = file;
-
- if (format != FORMAT_PEM) {
- BIO_printf(bio_err, "bad input format specified for %s\n", desc);
- return 0;
- }
-
- bio = bio_open_default(file, 'r', FORMAT_PEM);
- if (bio == NULL)
- return 0;
-
- xis = PEM_X509_INFO_read_bio(bio, NULL,
- (pem_password_cb *)password_callback,
- &cb_data);
-
- BIO_free(bio);
-
- if (pcerts != NULL && *pcerts == NULL) {
- *pcerts = sk_X509_new_null();
- if (*pcerts == NULL)
- goto end;
- }
-
- if (pcrls != NULL && *pcrls == NULL) {
- *pcrls = sk_X509_CRL_new_null();
- if (*pcrls == NULL)
- goto end;
- }
-
- for (i = 0; i < sk_X509_INFO_num(xis); i++) {
- xi = sk_X509_INFO_value(xis, i);
- if (xi->x509 != NULL && pcerts != NULL) {
- if (!sk_X509_push(*pcerts, xi->x509))
- goto end;
- xi->x509 = NULL;
- }
- if (xi->crl != NULL && pcrls != NULL) {
- if (!sk_X509_CRL_push(*pcrls, xi->crl))
- goto end;
- xi->crl = NULL;
- }
- }
-
- if (pcerts != NULL && sk_X509_num(*pcerts) > 0)
- rv = 1;
-
- if (pcrls != NULL && sk_X509_CRL_num(*pcrls) > 0)
- rv = 1;
-
- end:
-
- sk_X509_INFO_pop_free(xis, X509_INFO_free);
-
- if (rv == 0) {
- if (pcerts != NULL) {
- sk_X509_pop_free(*pcerts, X509_free);
- *pcerts = NULL;
- }
- if (pcrls != NULL) {
- sk_X509_CRL_pop_free(*pcrls, X509_CRL_free);
- *pcrls = NULL;
- }
- BIO_printf(bio_err, "unable to load %s\n",
- pcerts ? "certificates" : "CRLs");
- ERR_print_errors(bio_err);
- }
- return rv;
-}
-
-void* app_malloc(int sz, const char *what)
-{
- void *vp = OPENSSL_malloc(sz);
-
- if (vp == NULL) {
- BIO_printf(bio_err, "%s: Could not allocate %d bytes for %s\n",
- opt_getprog(), sz, what);
- ERR_print_errors(bio_err);
- exit(1);
- }
- return vp;
-}
-
-/*
- * Initialize or extend, if *certs != NULL, a certificate stack.
- */
-int load_certs(const char *file, STACK_OF(X509) **certs, int format,
- const char *pass, const char *desc)
-{
- return load_certs_crls(file, format, pass, desc, certs, NULL);
-}
-
-/*
- * Initialize or extend, if *crls != NULL, a certificate stack.
- */
-int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format,
- const char *pass, const char *desc)
-{
- return load_certs_crls(file, format, pass, desc, NULL, crls);
-}
-
-#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16)
-/* Return error for unknown extensions */
-#define X509V3_EXT_DEFAULT 0
-/* Print error for unknown extensions */
-#define X509V3_EXT_ERROR_UNKNOWN (1L << 16)
-/* ASN1 parse unknown extensions */
-#define X509V3_EXT_PARSE_UNKNOWN (2L << 16)
-/* BIO_dump unknown extensions */
-#define X509V3_EXT_DUMP_UNKNOWN (3L << 16)
-
-#define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \
- X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION)
-
-int set_cert_ex(unsigned long *flags, const char *arg)
-{
- static const NAME_EX_TBL cert_tbl[] = {
- {"compatible", X509_FLAG_COMPAT, 0xffffffffl},
- {"ca_default", X509_FLAG_CA, 0xffffffffl},
- {"no_header", X509_FLAG_NO_HEADER, 0},
- {"no_version", X509_FLAG_NO_VERSION, 0},
- {"no_serial", X509_FLAG_NO_SERIAL, 0},
- {"no_signame", X509_FLAG_NO_SIGNAME, 0},
- {"no_validity", X509_FLAG_NO_VALIDITY, 0},
- {"no_subject", X509_FLAG_NO_SUBJECT, 0},
- {"no_issuer", X509_FLAG_NO_ISSUER, 0},
- {"no_pubkey", X509_FLAG_NO_PUBKEY, 0},
- {"no_extensions", X509_FLAG_NO_EXTENSIONS, 0},
- {"no_sigdump", X509_FLAG_NO_SIGDUMP, 0},
- {"no_aux", X509_FLAG_NO_AUX, 0},
- {"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0},
- {"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK},
- {"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
- {"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
- {"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
- {NULL, 0, 0}
- };
- return set_multi_opts(flags, arg, cert_tbl);
-}
-
-int set_name_ex(unsigned long *flags, const char *arg)
-{
- static const NAME_EX_TBL ex_tbl[] = {
- {"esc_2253", ASN1_STRFLGS_ESC_2253, 0},
- {"esc_2254", ASN1_STRFLGS_ESC_2254, 0},
- {"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0},
- {"esc_msb", ASN1_STRFLGS_ESC_MSB, 0},
- {"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0},
- {"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0},
- {"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0},
- {"show_type", ASN1_STRFLGS_SHOW_TYPE, 0},
- {"dump_all", ASN1_STRFLGS_DUMP_ALL, 0},
- {"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0},
- {"dump_der", ASN1_STRFLGS_DUMP_DER, 0},
- {"compat", XN_FLAG_COMPAT, 0xffffffffL},
- {"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK},
- {"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK},
- {"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK},
- {"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK},
- {"dn_rev", XN_FLAG_DN_REV, 0},
- {"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK},
- {"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK},
- {"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK},
- {"align", XN_FLAG_FN_ALIGN, 0},
- {"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK},
- {"space_eq", XN_FLAG_SPC_EQ, 0},
- {"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0},
- {"RFC2253", XN_FLAG_RFC2253, 0xffffffffL},
- {"oneline", XN_FLAG_ONELINE, 0xffffffffL},
- {"multiline", XN_FLAG_MULTILINE, 0xffffffffL},
- {"ca_default", XN_FLAG_MULTILINE, 0xffffffffL},
- {NULL, 0, 0}
- };
- if (set_multi_opts(flags, arg, ex_tbl) == 0)
- return 0;
- if (*flags != XN_FLAG_COMPAT
- && (*flags & XN_FLAG_SEP_MASK) == 0)
- *flags |= XN_FLAG_SEP_CPLUS_SPC;
- return 1;
-}
-
-int set_ext_copy(int *copy_type, const char *arg)
-{
- if (strcasecmp(arg, "none") == 0)
- *copy_type = EXT_COPY_NONE;
- else if (strcasecmp(arg, "copy") == 0)
- *copy_type = EXT_COPY_ADD;
- else if (strcasecmp(arg, "copyall") == 0)
- *copy_type = EXT_COPY_ALL;
- else
- return 0;
- return 1;
-}
-
-int copy_extensions(X509 *x, X509_REQ *req, int copy_type)
-{
- STACK_OF(X509_EXTENSION) *exts = NULL;
- X509_EXTENSION *ext, *tmpext;
- ASN1_OBJECT *obj;
- int i, idx, ret = 0;
- if (!x || !req || (copy_type == EXT_COPY_NONE))
- return 1;
- exts = X509_REQ_get_extensions(req);
-
- for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
- ext = sk_X509_EXTENSION_value(exts, i);
- obj = X509_EXTENSION_get_object(ext);
- idx = X509_get_ext_by_OBJ(x, obj, -1);
- /* Does extension exist? */
- if (idx != -1) {
- /* If normal copy don't override existing extension */
- if (copy_type == EXT_COPY_ADD)
- continue;
- /* Delete all extensions of same type */
- do {
- tmpext = X509_get_ext(x, idx);
- X509_delete_ext(x, idx);
- X509_EXTENSION_free(tmpext);
- idx = X509_get_ext_by_OBJ(x, obj, -1);
- } while (idx != -1);
- }
- if (!X509_add_ext(x, ext, -1))
- goto end;
- }
-
- ret = 1;
-
- end:
-
- sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
-
- return ret;
-}
-
-static int set_multi_opts(unsigned long *flags, const char *arg,
- const NAME_EX_TBL * in_tbl)
-{
- STACK_OF(CONF_VALUE) *vals;
- CONF_VALUE *val;
- int i, ret = 1;
- if (!arg)
- return 0;
- vals = X509V3_parse_list(arg);
- for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
- val = sk_CONF_VALUE_value(vals, i);
- if (!set_table_opts(flags, val->name, in_tbl))
- ret = 0;
- }
- sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
- return ret;
-}
-
-static int set_table_opts(unsigned long *flags, const char *arg,
- const NAME_EX_TBL * in_tbl)
-{
- char c;
- const NAME_EX_TBL *ptbl;
- c = arg[0];
-
- if (c == '-') {
- c = 0;
- arg++;
- } else if (c == '+') {
- c = 1;
- arg++;
- } else {
- c = 1;
- }
-
- for (ptbl = in_tbl; ptbl->name; ptbl++) {
- if (strcasecmp(arg, ptbl->name) == 0) {
- *flags &= ~ptbl->mask;
- if (c)
- *flags |= ptbl->flag;
- else
- *flags &= ~ptbl->flag;
- return 1;
- }
- }
- return 0;
-}
-
-void print_name(BIO *out, const char *title, X509_NAME *nm,
- unsigned long lflags)
-{
- char *buf;
- char mline = 0;
- int indent = 0;
-
- if (title)
- BIO_puts(out, title);
- if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
- mline = 1;
- indent = 4;
- }
- if (lflags == XN_FLAG_COMPAT) {
- buf = X509_NAME_oneline(nm, 0, 0);
- BIO_puts(out, buf);
- BIO_puts(out, "\n");
- OPENSSL_free(buf);
- } else {
- if (mline)
- BIO_puts(out, "\n");
- X509_NAME_print_ex(out, nm, indent, lflags);
- BIO_puts(out, "\n");
- }
-}
-
-void print_bignum_var(BIO *out, const BIGNUM *in, const char *var,
- int len, unsigned char *buffer)
-{
- BIO_printf(out, " static unsigned char %s_%d[] = {", var, len);
- if (BN_is_zero(in)) {
- BIO_printf(out, "\n 0x00");
- } else {
- int i, l;
-
- l = BN_bn2bin(in, buffer);
- for (i = 0; i < l; i++) {
- BIO_printf(out, (i % 10) == 0 ? "\n " : " ");
- if (i < l - 1)
- BIO_printf(out, "0x%02X,", buffer[i]);
- else
- BIO_printf(out, "0x%02X", buffer[i]);
- }
- }
- BIO_printf(out, "\n };\n");
-}
-
-void print_array(BIO *out, const char* title, int len, const unsigned char* d)
-{
- int i;
-
- BIO_printf(out, "unsigned char %s[%d] = {", title, len);
- for (i = 0; i < len; i++) {
- if ((i % 10) == 0)
- BIO_printf(out, "\n ");
- if (i < len - 1)
- BIO_printf(out, "0x%02X, ", d[i]);
- else
- BIO_printf(out, "0x%02X", d[i]);
- }
- BIO_printf(out, "\n};\n");
-}
-
-X509_STORE *setup_verify(const char *CAfile, const char *CApath, int noCAfile, int noCApath)
-{
- X509_STORE *store = X509_STORE_new();
- X509_LOOKUP *lookup;
-
- if (store == NULL)
- goto end;
-
- if (CAfile != NULL || !noCAfile) {
- lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
- if (lookup == NULL)
- goto end;
- if (CAfile) {
- if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) {
- BIO_printf(bio_err, "Error loading file %s\n", CAfile);
- goto end;
- }
- } else {
- X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
- }
- }
-
- if (CApath != NULL || !noCApath) {
- lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
- if (lookup == NULL)
- goto end;
- if (CApath) {
- if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) {
- BIO_printf(bio_err, "Error loading directory %s\n", CApath);
- goto end;
- }
- } else {
- X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
- }
- }
-
- ERR_clear_error();
- return store;
- end:
- X509_STORE_free(store);
- return NULL;
-}
-
-#ifndef OPENSSL_NO_ENGINE
-/* Try to load an engine in a shareable library */
-static ENGINE *try_load_engine(const char *engine)
-{
- ENGINE *e = ENGINE_by_id("dynamic");
- if (e) {
- if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0)
- || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
- ENGINE_free(e);
- e = NULL;
- }
- }
- return e;
-}
-#endif
-
-ENGINE *setup_engine(const char *engine, int debug)
-{
- ENGINE *e = NULL;
-
-#ifndef OPENSSL_NO_ENGINE
- if (engine != NULL) {
- if (strcmp(engine, "auto") == 0) {
- BIO_printf(bio_err, "enabling auto ENGINE support\n");
- ENGINE_register_all_complete();
- return NULL;
- }
- if ((e = ENGINE_by_id(engine)) == NULL
- && (e = try_load_engine(engine)) == NULL) {
- BIO_printf(bio_err, "invalid engine \"%s\"\n", engine);
- ERR_print_errors(bio_err);
- return NULL;
- }
- if (debug) {
- ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, bio_err, 0);
- }
- ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, ui_method, 0, 1);
- if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
- BIO_printf(bio_err, "can't use that engine\n");
- ERR_print_errors(bio_err);
- ENGINE_free(e);
- return NULL;
- }
-
- BIO_printf(bio_err, "engine \"%s\" set.\n", ENGINE_get_id(e));
- }
-#endif
- return e;
-}
-
-void release_engine(ENGINE *e)
-{
-#ifndef OPENSSL_NO_ENGINE
- if (e != NULL)
- /* Free our "structural" reference. */
- ENGINE_free(e);
-#endif
-}
-
-static unsigned long index_serial_hash(const OPENSSL_CSTRING *a)
-{
- const char *n;
-
- n = a[DB_serial];
- while (*n == '0')
- n++;
- return OPENSSL_LH_strhash(n);
-}
-
-static int index_serial_cmp(const OPENSSL_CSTRING *a,
- const OPENSSL_CSTRING *b)
-{
- const char *aa, *bb;
-
- for (aa = a[DB_serial]; *aa == '0'; aa++) ;
- for (bb = b[DB_serial]; *bb == '0'; bb++) ;
- return strcmp(aa, bb);
-}
-
-static int index_name_qual(char **a)
-{
- return (a[0][0] == 'V');
-}
-
-static unsigned long index_name_hash(const OPENSSL_CSTRING *a)
-{
- return OPENSSL_LH_strhash(a[DB_name]);
-}
-
-int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b)
-{
- return strcmp(a[DB_name], b[DB_name]);
-}
-
-static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING)
-static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING)
-static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING)
-static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING)
-#undef BSIZE
-#define BSIZE 256
-BIGNUM *load_serial(const char *serialfile, int *exists, int create,
- ASN1_INTEGER **retai)
-{
- BIO *in = NULL;
- BIGNUM *ret = NULL;
- char buf[1024];
- ASN1_INTEGER *ai = NULL;
-
- ai = ASN1_INTEGER_new();
- if (ai == NULL)
- goto err;
-
- in = BIO_new_file(serialfile, "r");
- if (exists != NULL)
- *exists = in != NULL;
- if (in == NULL) {
- if (!create) {
- perror(serialfile);
- goto err;
- }
- ERR_clear_error();
- ret = BN_new();
- if (ret == NULL) {
- BIO_printf(bio_err, "Out of memory\n");
- } else if (!rand_serial(ret, ai)) {
- BIO_printf(bio_err, "Error creating random number to store in %s\n",
- serialfile);
- BN_free(ret);
- ret = NULL;
- }
- } else {
- if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) {
- BIO_printf(bio_err, "unable to load number from %s\n",
- serialfile);
- goto err;
- }
- ret = ASN1_INTEGER_to_BN(ai, NULL);
- if (ret == NULL) {
- BIO_printf(bio_err,
- "error converting number from bin to BIGNUM\n");
- goto err;
- }
- }
-
- if (ret && retai) {
- *retai = ai;
- ai = NULL;
- }
- err:
- if (ret == NULL)
- ERR_print_errors(bio_err);
- BIO_free(in);
- ASN1_INTEGER_free(ai);
- return ret;
-}
-
-int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial,
- ASN1_INTEGER **retai)
-{
- char buf[1][BSIZE];
- BIO *out = NULL;
- int ret = 0;
- ASN1_INTEGER *ai = NULL;
- int j;
-
- if (suffix == NULL)
- j = strlen(serialfile);
- else
- j = strlen(serialfile) + strlen(suffix) + 1;
- if (j >= BSIZE) {
- BIO_printf(bio_err, "file name too long\n");
- goto err;
- }
-
- if (suffix == NULL)
- OPENSSL_strlcpy(buf[0], serialfile, BSIZE);
- else {
-#ifndef OPENSSL_SYS_VMS
- j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, suffix);
-#else
- j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, suffix);
-#endif
- }
- out = BIO_new_file(buf[0], "w");
- if (out == NULL) {
- ERR_print_errors(bio_err);
- goto err;
- }
-
- if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) {
- BIO_printf(bio_err, "error converting serial to ASN.1 format\n");
- goto err;
- }
- i2a_ASN1_INTEGER(out, ai);
- BIO_puts(out, "\n");
- ret = 1;
- if (retai) {
- *retai = ai;
- ai = NULL;
- }
- err:
- BIO_free_all(out);
- ASN1_INTEGER_free(ai);
- return ret;
-}
-
-int rotate_serial(const char *serialfile, const char *new_suffix,
- const char *old_suffix)
-{
- char buf[2][BSIZE];
- int i, j;
-
- i = strlen(serialfile) + strlen(old_suffix);
- j = strlen(serialfile) + strlen(new_suffix);
- if (i > j)
- j = i;
- if (j + 1 >= BSIZE) {
- BIO_printf(bio_err, "file name too long\n");
- goto err;
- }
-#ifndef OPENSSL_SYS_VMS
- j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, new_suffix);
- j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", serialfile, old_suffix);
-#else
- j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, new_suffix);
- j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", serialfile, old_suffix);
-#endif
- if (rename(serialfile, buf[1]) < 0 && errno != ENOENT
-#ifdef ENOTDIR
- && errno != ENOTDIR
-#endif
- ) {
- BIO_printf(bio_err,
- "unable to rename %s to %s\n", serialfile, buf[1]);
- perror("reason");
- goto err;
- }
- if (rename(buf[0], serialfile) < 0) {
- BIO_printf(bio_err,
- "unable to rename %s to %s\n", buf[0], serialfile);
- perror("reason");
- rename(buf[1], serialfile);
- goto err;
- }
- return 1;
- err:
- return 0;
-}
-
-int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
-{
- BIGNUM *btmp;
- int ret = 0;
-
- btmp = b == NULL ? BN_new() : b;
- if (btmp == NULL)
- return 0;
-
- if (!BN_rand(btmp, SERIAL_RAND_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
- goto error;
- if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
- goto error;
-
- ret = 1;
-
- error:
-
- if (btmp != b)
- BN_free(btmp);
-
- return ret;
-}
-
-CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr)
-{
- CA_DB *retdb = NULL;
- TXT_DB *tmpdb = NULL;
- BIO *in;
- CONF *dbattr_conf = NULL;
- char buf[BSIZE];
-#ifndef OPENSSL_NO_POSIX_IO
- FILE *dbfp;
- struct stat dbst;
-#endif
-
- in = BIO_new_file(dbfile, "r");
- if (in == NULL) {
- ERR_print_errors(bio_err);
- goto err;
- }
-
-#ifndef OPENSSL_NO_POSIX_IO
- BIO_get_fp(in, &dbfp);
- if (fstat(fileno(dbfp), &dbst) == -1) {
- SYSerr(SYS_F_FSTAT, errno);
- ERR_add_error_data(3, "fstat('", dbfile, "')");
- ERR_print_errors(bio_err);
- goto err;
- }
-#endif
-
- if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL)
- goto err;
-
-#ifndef OPENSSL_SYS_VMS
- BIO_snprintf(buf, sizeof(buf), "%s.attr", dbfile);
-#else
- BIO_snprintf(buf, sizeof(buf), "%s-attr", dbfile);
-#endif
- dbattr_conf = app_load_config_quiet(buf);
-
- retdb = app_malloc(sizeof(*retdb), "new DB");
- retdb->db = tmpdb;
- tmpdb = NULL;
- if (db_attr)
- retdb->attributes = *db_attr;
- else {
- retdb->attributes.unique_subject = 1;
- }
-
- if (dbattr_conf) {
- char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject");
- if (p) {
- retdb->attributes.unique_subject = parse_yesno(p, 1);
- }
- }
-
- retdb->dbfname = OPENSSL_strdup(dbfile);
-#ifndef OPENSSL_NO_POSIX_IO
- retdb->dbst = dbst;
-#endif
-
- err:
- NCONF_free(dbattr_conf);
- TXT_DB_free(tmpdb);
- BIO_free_all(in);
- return retdb;
-}
-
-/*
- * Returns > 0 on success, <= 0 on error
- */
-int index_index(CA_DB *db)
-{
- if (!TXT_DB_create_index(db->db, DB_serial, NULL,
- LHASH_HASH_FN(index_serial),
- LHASH_COMP_FN(index_serial))) {
- BIO_printf(bio_err,
- "error creating serial number index:(%ld,%ld,%ld)\n",
- db->db->error, db->db->arg1, db->db->arg2);
- return 0;
- }
-
- if (db->attributes.unique_subject
- && !TXT_DB_create_index(db->db, DB_name, index_name_qual,
- LHASH_HASH_FN(index_name),
- LHASH_COMP_FN(index_name))) {
- BIO_printf(bio_err, "error creating name index:(%ld,%ld,%ld)\n",
- db->db->error, db->db->arg1, db->db->arg2);
- return 0;
- }
- return 1;
-}
-
-int save_index(const char *dbfile, const char *suffix, CA_DB *db)
-{
- char buf[3][BSIZE];
- BIO *out;
- int j;
-
- j = strlen(dbfile) + strlen(suffix);
- if (j + 6 >= BSIZE) {
- BIO_printf(bio_err, "file name too long\n");
- goto err;
- }
-#ifndef OPENSSL_SYS_VMS
- j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr", dbfile);
- j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.attr.%s", dbfile, suffix);
- j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, suffix);
-#else
- j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr", dbfile);
- j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-attr-%s", dbfile, suffix);
- j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, suffix);
-#endif
- out = BIO_new_file(buf[0], "w");
- if (out == NULL) {
- perror(dbfile);
- BIO_printf(bio_err, "unable to open '%s'\n", dbfile);
- goto err;
- }
- j = TXT_DB_write(out, db->db);
- BIO_free(out);
- if (j <= 0)
- goto err;
-
- out = BIO_new_file(buf[1], "w");
- if (out == NULL) {
- perror(buf[2]);
- BIO_printf(bio_err, "unable to open '%s'\n", buf[2]);
- goto err;
- }
- BIO_printf(out, "unique_subject = %s\n",
- db->attributes.unique_subject ? "yes" : "no");
- BIO_free(out);
-
- return 1;
- err:
- return 0;
-}
-
-int rotate_index(const char *dbfile, const char *new_suffix,
- const char *old_suffix)
-{
- char buf[5][BSIZE];
- int i, j;
-
- i = strlen(dbfile) + strlen(old_suffix);
- j = strlen(dbfile) + strlen(new_suffix);
- if (i > j)
- j = i;
- if (j + 6 >= BSIZE) {
- BIO_printf(bio_err, "file name too long\n");
- goto err;
- }
-#ifndef OPENSSL_SYS_VMS
- j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s.attr", dbfile);
- j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s.attr.%s", dbfile, old_suffix);
- j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr.%s", dbfile, new_suffix);
- j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", dbfile, old_suffix);
- j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, new_suffix);
-#else
- j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s-attr", dbfile);
- j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s-attr-%s", dbfile, old_suffix);
- j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr-%s", dbfile, new_suffix);
- j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", dbfile, old_suffix);
- j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, new_suffix);
-#endif
- if (rename(dbfile, buf[1]) < 0 && errno != ENOENT
-#ifdef ENOTDIR
- && errno != ENOTDIR
-#endif
- ) {
- BIO_printf(bio_err, "unable to rename %s to %s\n", dbfile, buf[1]);
- perror("reason");
- goto err;
- }
- if (rename(buf[0], dbfile) < 0) {
- BIO_printf(bio_err, "unable to rename %s to %s\n", buf[0], dbfile);
- perror("reason");
- rename(buf[1], dbfile);
- goto err;
- }
- if (rename(buf[4], buf[3]) < 0 && errno != ENOENT
-#ifdef ENOTDIR
- && errno != ENOTDIR
-#endif
- ) {
- BIO_printf(bio_err, "unable to rename %s to %s\n", buf[4], buf[3]);
- perror("reason");
- rename(dbfile, buf[0]);
- rename(buf[1], dbfile);
- goto err;
- }
- if (rename(buf[2], buf[4]) < 0) {
- BIO_printf(bio_err, "unable to rename %s to %s\n", buf[2], buf[4]);
- perror("reason");
- rename(buf[3], buf[4]);
- rename(dbfile, buf[0]);
- rename(buf[1], dbfile);
- goto err;
- }
- return 1;
- err:
- return 0;
-}
-
-void free_index(CA_DB *db)
-{
- if (db) {
- TXT_DB_free(db->db);
- OPENSSL_free(db->dbfname);
- OPENSSL_free(db);
- }
-}
-
-int parse_yesno(const char *str, int def)
-{
- if (str) {
- switch (*str) {
- case 'f': /* false */
- case 'F': /* FALSE */
- case 'n': /* no */
- case 'N': /* NO */
- case '0': /* 0 */
- return 0;
- case 't': /* true */
- case 'T': /* TRUE */
- case 'y': /* yes */
- case 'Y': /* YES */
- case '1': /* 1 */
- return 1;
- }
- }
- return def;
-}
-
-/*
- * name is expected to be in the format /type0=value0/type1=value1/type2=...
- * where characters may be escaped by \
- */
-X509_NAME *parse_name(const char *cp, long chtype, int canmulti)
-{
- int nextismulti = 0;
- char *work;
- X509_NAME *n;
-
- if (*cp++ != '/') {
- BIO_printf(bio_err,
- "name is expected to be in the format "
- "/type0=value0/type1=value1/type2=... where characters may "
- "be escaped by \\. This name is not in that format: '%s'\n",
- --cp);
- return NULL;
- }
-
- n = X509_NAME_new();
- if (n == NULL)
- return NULL;
- work = OPENSSL_strdup(cp);
- if (work == NULL)
- goto err;
-
- while (*cp) {
- char *bp = work;
- char *typestr = bp;
- unsigned char *valstr;
- int nid;
- int ismulti = nextismulti;
- nextismulti = 0;
-
- /* Collect the type */
- while (*cp && *cp != '=')
- *bp++ = *cp++;
- if (*cp == '\0') {
- BIO_printf(bio_err,
- "%s: Hit end of string before finding the equals.\n",
- opt_getprog());
- goto err;
- }
- *bp++ = '\0';
- ++cp;
-
- /* Collect the value. */
- valstr = (unsigned char *)bp;
- for (; *cp && *cp != '/'; *bp++ = *cp++) {
- if (canmulti && *cp == '+') {
- nextismulti = 1;
- break;
- }
- if (*cp == '\\' && *++cp == '\0') {
- BIO_printf(bio_err,
- "%s: escape character at end of string\n",
- opt_getprog());
- goto err;
- }
- }
- *bp++ = '\0';
-
- /* If not at EOS (must be + or /), move forward. */
- if (*cp)
- ++cp;
-
- /* Parse */
- nid = OBJ_txt2nid(typestr);
- if (nid == NID_undef) {
- BIO_printf(bio_err, "%s: Skipping unknown attribute \"%s\"\n",
- opt_getprog(), typestr);
- continue;
- }
- if (*valstr == '\0') {
- BIO_printf(bio_err,
- "%s: No value provided for Subject Attribute %s, skipped\n",
- opt_getprog(), typestr);
- continue;
- }
- if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
- valstr, strlen((char *)valstr),
- -1, ismulti ? -1 : 0))
- goto err;
- }
-
- OPENSSL_free(work);
- return n;
-
- err:
- X509_NAME_free(n);
- OPENSSL_free(work);
- return NULL;
-}
-
-/*
- * Read whole contents of a BIO into an allocated memory buffer and return
- * it.
- */
-
-int bio_to_mem(unsigned char **out, int maxlen, BIO *in)
-{
- BIO *mem;
- int len, ret;
- unsigned char tbuf[1024];
-
- mem = BIO_new(BIO_s_mem());
- if (mem == NULL)
- return -1;
- for (;;) {
- if ((maxlen != -1) && maxlen < 1024)
- len = maxlen;
- else
- len = 1024;
- len = BIO_read(in, tbuf, len);
- if (len < 0) {
- BIO_free(mem);
- return -1;
- }
- if (len == 0)
- break;
- if (BIO_write(mem, tbuf, len) != len) {
- BIO_free(mem);
- return -1;
- }
- maxlen -= len;
-
- if (maxlen == 0)
- break;
- }
- ret = BIO_get_mem_data(mem, (char **)out);
- BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY);
- BIO_free(mem);
- return ret;
-}
-
-int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value)
-{
- int rv;
- char *stmp, *vtmp = NULL;
- stmp = OPENSSL_strdup(value);
- if (!stmp)
- return -1;
- vtmp = strchr(stmp, ':');
- if (vtmp) {
- *vtmp = 0;
- vtmp++;
- }
- rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp);
- OPENSSL_free(stmp);
- return rv;
-}
-
-static void nodes_print(const char *name, STACK_OF(X509_POLICY_NODE) *nodes)
-{
- X509_POLICY_NODE *node;
- int i;
-
- BIO_printf(bio_err, "%s Policies:", name);
- if (nodes) {
- BIO_puts(bio_err, "\n");
- for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) {
- node = sk_X509_POLICY_NODE_value(nodes, i);
- X509_POLICY_NODE_print(bio_err, node, 2);
- }
- } else {
- BIO_puts(bio_err, " <empty>\n");
- }
-}
-
-void policies_print(X509_STORE_CTX *ctx)
-{
- X509_POLICY_TREE *tree;
- int explicit_policy;
- tree = X509_STORE_CTX_get0_policy_tree(ctx);
- explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx);
-
- BIO_printf(bio_err, "Require explicit Policy: %s\n",
- explicit_policy ? "True" : "False");
-
- nodes_print("Authority", X509_policy_tree_get0_policies(tree));
- nodes_print("User", X509_policy_tree_get0_user_policies(tree));
-}
-
-/*-
- * next_protos_parse parses a comma separated list of strings into a string
- * in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
- * outlen: (output) set to the length of the resulting buffer on success.
- * err: (maybe NULL) on failure, an error message line is written to this BIO.
- * in: a NUL terminated string like "abc,def,ghi"
- *
- * returns: a malloc'd buffer or NULL on failure.
- */
-unsigned char *next_protos_parse(size_t *outlen, const char *in)
-{
- size_t len;
- unsigned char *out;
- size_t i, start = 0;
- size_t skipped = 0;
-
- len = strlen(in);
- if (len == 0 || len >= 65535)
- return NULL;
-
- out = app_malloc(len + 1, "NPN buffer");
- for (i = 0; i <= len; ++i) {
- if (i == len || in[i] == ',') {
- /*
- * Zero-length ALPN elements are invalid on the wire, we could be
- * strict and reject the entire string, but just ignoring extra
- * commas seems harmless and more friendly.
- *
- * Every comma we skip in this way puts the input buffer another
- * byte ahead of the output buffer, so all stores into the output
- * buffer need to be decremented by the number commas skipped.
- */
- if (i == start) {
- ++start;
- ++skipped;
- continue;
- }
- if (i - start > 255) {
- OPENSSL_free(out);
- return NULL;
- }
- out[start-skipped] = (unsigned char)(i - start);
- start = i + 1;
- } else {
- out[i + 1 - skipped] = in[i];
- }
- }
-
- if (len <= skipped) {
- OPENSSL_free(out);
- return NULL;
- }
-
- *outlen = len + 1 - skipped;
- return out;
-}
-
-void print_cert_checks(BIO *bio, X509 *x,
- const char *checkhost,
- const char *checkemail, const char *checkip)
-{
- if (x == NULL)
- return;
- if (checkhost) {
- BIO_printf(bio, "Hostname %s does%s match certificate\n",
- checkhost,
- X509_check_host(x, checkhost, 0, 0, NULL) == 1
- ? "" : " NOT");
- }
-
- if (checkemail) {
- BIO_printf(bio, "Email %s does%s match certificate\n",
- checkemail, X509_check_email(x, checkemail, 0, 0)
- ? "" : " NOT");
- }
-
- if (checkip) {
- BIO_printf(bio, "IP %s does%s match certificate\n",
- checkip, X509_check_ip_asc(x, checkip, 0) ? "" : " NOT");
- }
-}
-
-/* Get first http URL from a DIST_POINT structure */
-
-static const char *get_dp_url(DIST_POINT *dp)
-{
- GENERAL_NAMES *gens;
- GENERAL_NAME *gen;
- int i, gtype;
- ASN1_STRING *uri;
- if (!dp->distpoint || dp->distpoint->type != 0)
- return NULL;
- gens = dp->distpoint->name.fullname;
- for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
- gen = sk_GENERAL_NAME_value(gens, i);
- uri = GENERAL_NAME_get0_value(gen, &gtype);
- if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6) {
- const char *uptr = (const char *)ASN1_STRING_get0_data(uri);
- if (strncmp(uptr, "http://", 7) == 0)
- return uptr;
- }
- }
- return NULL;
-}
-
-/*
- * Look through a CRLDP structure and attempt to find an http URL to
- * downloads a CRL from.
- */
-
-static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp)
-{
- int i;
- const char *urlptr = NULL;
- for (i = 0; i < sk_DIST_POINT_num(crldp); i++) {
- DIST_POINT *dp = sk_DIST_POINT_value(crldp, i);
- urlptr = get_dp_url(dp);
- if (urlptr)
- return load_crl(urlptr, FORMAT_HTTP);
- }
- return NULL;
-}
-
-/*
- * Example of downloading CRLs from CRLDP: not usable for real world as it
- * always downloads, doesn't support non-blocking I/O and doesn't cache
- * anything.
- */
-
-static STACK_OF(X509_CRL) *crls_http_cb(X509_STORE_CTX *ctx, X509_NAME *nm)
-{
- X509 *x;
- STACK_OF(X509_CRL) *crls = NULL;
- X509_CRL *crl;
- STACK_OF(DIST_POINT) *crldp;
-
- crls = sk_X509_CRL_new_null();
- if (!crls)
- return NULL;
- x = X509_STORE_CTX_get_current_cert(ctx);
- crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
- crl = load_crl_crldp(crldp);
- sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
- if (!crl) {
- sk_X509_CRL_free(crls);
- return NULL;
- }
- sk_X509_CRL_push(crls, crl);
- /* Try to download delta CRL */
- crldp = X509_get_ext_d2i(x, NID_freshest_crl, NULL, NULL);
- crl = load_crl_crldp(crldp);
- sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
- if (crl)
- sk_X509_CRL_push(crls, crl);
- return crls;
-}
-
-void store_setup_crl_download(X509_STORE *st)
-{
- X509_STORE_set_lookup_crls_cb(st, crls_http_cb);
-}
-
-/*
- * Platform-specific sections
- */
-#if defined(_WIN32)
-# ifdef fileno
-# undef fileno
-# define fileno(a) (int)_fileno(a)
-# endif
-
-# include <windows.h>
-# include <tchar.h>
-
-static int WIN32_rename(const char *from, const char *to)
-{
- TCHAR *tfrom = NULL, *tto;
- DWORD err;
- int ret = 0;
-
- if (sizeof(TCHAR) == 1) {
- tfrom = (TCHAR *)from;
- tto = (TCHAR *)to;
- } else { /* UNICODE path */
-
- size_t i, flen = strlen(from) + 1, tlen = strlen(to) + 1;
- tfrom = malloc(sizeof(*tfrom) * (flen + tlen));
- if (tfrom == NULL)
- goto err;
- tto = tfrom + flen;
-# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
- if (!MultiByteToWideChar(CP_ACP, 0, from, flen, (WCHAR *)tfrom, flen))
-# endif
- for (i = 0; i < flen; i++)
- tfrom[i] = (TCHAR)from[i];
-# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
- if (!MultiByteToWideChar(CP_ACP, 0, to, tlen, (WCHAR *)tto, tlen))
-# endif
- for (i = 0; i < tlen; i++)
- tto[i] = (TCHAR)to[i];
- }
-
- if (MoveFile(tfrom, tto))
- goto ok;
- err = GetLastError();
- if (err == ERROR_ALREADY_EXISTS || err == ERROR_FILE_EXISTS) {
- if (DeleteFile(tto) && MoveFile(tfrom, tto))
- goto ok;
- err = GetLastError();
- }
- if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
- errno = ENOENT;
- else if (err == ERROR_ACCESS_DENIED)
- errno = EACCES;
- else
- errno = EINVAL; /* we could map more codes... */
- err:
- ret = -1;
- ok:
- if (tfrom != NULL && tfrom != (TCHAR *)from)
- free(tfrom);
- return ret;
-}
-#endif
-
-/* app_tminterval section */
-#if defined(_WIN32)
-double app_tminterval(int stop, int usertime)
-{
- FILETIME now;
- double ret = 0;
- static ULARGE_INTEGER tmstart;
- static int warning = 1;
-# ifdef _WIN32_WINNT
- static HANDLE proc = NULL;
-
- if (proc == NULL) {
- if (check_winnt())
- proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE,
- GetCurrentProcessId());
- if (proc == NULL)
- proc = (HANDLE) - 1;
- }
-
- if (usertime && proc != (HANDLE) - 1) {
- FILETIME junk;
- GetProcessTimes(proc, &junk, &junk, &junk, &now);
- } else
-# endif
- {
- SYSTEMTIME systime;
-
- if (usertime && warning) {
- BIO_printf(bio_err, "To get meaningful results, run "
- "this program on idle system.\n");
- warning = 0;
- }
- GetSystemTime(&systime);
- SystemTimeToFileTime(&systime, &now);
- }
-
- if (stop == TM_START) {
- tmstart.u.LowPart = now.dwLowDateTime;
- tmstart.u.HighPart = now.dwHighDateTime;
- } else {
- ULARGE_INTEGER tmstop;
-
- tmstop.u.LowPart = now.dwLowDateTime;
- tmstop.u.HighPart = now.dwHighDateTime;
-
- ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart) * 1e-7;
- }
-
- return ret;
-}
-#elif defined(OPENSSL_SYS_VXWORKS)
-# include <time.h>
-
-double app_tminterval(int stop, int usertime)
-{
- double ret = 0;
-# ifdef CLOCK_REALTIME
- static struct timespec tmstart;
- struct timespec now;
-# else
- static unsigned long tmstart;
- unsigned long now;
-# endif
- static int warning = 1;
-
- if (usertime && warning) {
- BIO_printf(bio_err, "To get meaningful results, run "
- "this program on idle system.\n");
- warning = 0;
- }
-# ifdef CLOCK_REALTIME
- clock_gettime(CLOCK_REALTIME, &now);
- if (stop == TM_START)
- tmstart = now;
- else
- ret = ((now.tv_sec + now.tv_nsec * 1e-9)
- - (tmstart.tv_sec + tmstart.tv_nsec * 1e-9));
-# else
- now = tickGet();
- if (stop == TM_START)
- tmstart = now;
- else
- ret = (now - tmstart) / (double)sysClkRateGet();
-# endif
- return ret;
-}
-
-#elif defined(OPENSSL_SYSTEM_VMS)
-# include <time.h>
-# include <times.h>
-
-double app_tminterval(int stop, int usertime)
-{
- static clock_t tmstart;
- double ret = 0;
- clock_t now;
-# ifdef __TMS
- struct tms rus;
-
- now = times(&rus);
- if (usertime)
- now = rus.tms_utime;
-# else
- if (usertime)
- now = clock(); /* sum of user and kernel times */
- else {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- now = (clock_t)((unsigned long long)tv.tv_sec * CLK_TCK +
- (unsigned long long)tv.tv_usec * (1000000 / CLK_TCK)
- );
- }
-# endif
- if (stop == TM_START)
- tmstart = now;
- else
- ret = (now - tmstart) / (double)(CLK_TCK);
-
- return ret;
-}
-
-#elif defined(_SC_CLK_TCK) /* by means of unistd.h */
-# include <sys/times.h>
-
-double app_tminterval(int stop, int usertime)
-{
- double ret = 0;
- struct tms rus;
- clock_t now = times(&rus);
- static clock_t tmstart;
-
- if (usertime)
- now = rus.tms_utime;
-
- if (stop == TM_START) {
- tmstart = now;
- } else {
- long int tck = sysconf(_SC_CLK_TCK);
- ret = (now - tmstart) / (double)tck;
- }
-
- return ret;
-}
-
-#else
-# include <sys/time.h>
-# include <sys/resource.h>
-
-double app_tminterval(int stop, int usertime)
-{
- double ret = 0;
- struct rusage rus;
- struct timeval now;
- static struct timeval tmstart;
-
- if (usertime)
- getrusage(RUSAGE_SELF, &rus), now = rus.ru_utime;
- else
- gettimeofday(&now, NULL);
-
- if (stop == TM_START)
- tmstart = now;
- else
- ret = ((now.tv_sec + now.tv_usec * 1e-6)
- - (tmstart.tv_sec + tmstart.tv_usec * 1e-6));
-
- return ret;
-}
-#endif
-
-int app_access(const char* name, int flag)
-{
-#ifdef _WIN32
- return _access(name, flag);
-#else
- return access(name, flag);
-#endif
-}
-
-/* app_isdir section */
-#ifdef _WIN32
-int app_isdir(const char *name)
-{
- DWORD attr;
-# if defined(UNICODE) || defined(_UNICODE)
- size_t i, len_0 = strlen(name) + 1;
- WCHAR tempname[MAX_PATH];
-
- if (len_0 > MAX_PATH)
- return -1;
-
-# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
- if (!MultiByteToWideChar(CP_ACP, 0, name, len_0, tempname, MAX_PATH))
-# endif
- for (i = 0; i < len_0; i++)
- tempname[i] = (WCHAR)name[i];
-
- attr = GetFileAttributes(tempname);
-# else
- attr = GetFileAttributes(name);
-# endif
- if (attr == INVALID_FILE_ATTRIBUTES)
- return -1;
- return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0);
-}
-#else
-# include <sys/stat.h>
-# ifndef S_ISDIR
-# if defined(_S_IFMT) && defined(_S_IFDIR)
-# define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR)
-# else
-# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
-# endif
-# endif
-
-int app_isdir(const char *name)
-{
-# if defined(S_ISDIR)
- struct stat st;
-
- if (stat(name, &st) == 0)
- return S_ISDIR(st.st_mode);
- else
- return -1;
-# else
- return -1;
-# endif
-}
-#endif
-
-/* raw_read|write section */
-#if defined(__VMS)
-# include "vms_term_sock.h"
-static int stdin_sock = -1;
-
-static void close_stdin_sock(void)
-{
- TerminalSocket (TERM_SOCK_DELETE, &stdin_sock);
-}
-
-int fileno_stdin(void)
-{
- if (stdin_sock == -1) {
- TerminalSocket(TERM_SOCK_CREATE, &stdin_sock);
- atexit(close_stdin_sock);
- }
-
- return stdin_sock;
-}
-#else
-int fileno_stdin(void)
-{
- return fileno(stdin);
-}
-#endif
-
-int fileno_stdout(void)
-{
- return fileno(stdout);
-}
-
-#if defined(_WIN32) && defined(STD_INPUT_HANDLE)
-int raw_read_stdin(void *buf, int siz)
-{
- DWORD n;
- if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, siz, &n, NULL))
- return n;
- else
- return -1;
-}
-#elif defined(__VMS)
-# include <sys/socket.h>
-
-int raw_read_stdin(void *buf, int siz)
-{
- return recv(fileno_stdin(), buf, siz, 0);
-}
-#else
-int raw_read_stdin(void *buf, int siz)
-{
- return read(fileno_stdin(), buf, siz);
-}
-#endif
-
-#if defined(_WIN32) && defined(STD_OUTPUT_HANDLE)
-int raw_write_stdout(const void *buf, int siz)
-{
- DWORD n;
- if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, siz, &n, NULL))
- return n;
- else
- return -1;
-}
-#else
-int raw_write_stdout(const void *buf, int siz)
-{
- return write(fileno_stdout(), buf, siz);
-}
-#endif
-
-/*
- * Centralized handling if input and output files with format specification
- * The format is meant to show what the input and output is supposed to be,
- * and is therefore a show of intent more than anything else. However, it
- * does impact behavior on some platform, such as differentiating between
- * text and binary input/output on non-Unix platforms
- */
-static int istext(int format)
-{
- return (format & B_FORMAT_TEXT) == B_FORMAT_TEXT;
-}
-
-BIO *dup_bio_in(int format)
-{
- return BIO_new_fp(stdin,
- BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0));
-}
-
-static BIO_METHOD *prefix_method = NULL;
-
-BIO *dup_bio_out(int format)
-{
- BIO *b = BIO_new_fp(stdout,
- BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0));
- void *prefix = NULL;
-
-#ifdef OPENSSL_SYS_VMS
- if (istext(format))
- b = BIO_push(BIO_new(BIO_f_linebuffer()), b);
-#endif
-
- if (istext(format) && (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) {
- if (prefix_method == NULL)
- prefix_method = apps_bf_prefix();
- b = BIO_push(BIO_new(prefix_method), b);
- BIO_ctrl(b, PREFIX_CTRL_SET_PREFIX, 0, prefix);
- }
-
- return b;
-}
-
-BIO *dup_bio_err(int format)
-{
- BIO *b = BIO_new_fp(stderr,
- BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0));
-#ifdef OPENSSL_SYS_VMS
- if (istext(format))
- b = BIO_push(BIO_new(BIO_f_linebuffer()), b);
-#endif
- return b;
-}
-
-void destroy_prefix_method(void)
-{
- BIO_meth_free(prefix_method);
- prefix_method = NULL;
-}
-
-void unbuffer(FILE *fp)
-{
-/*
- * On VMS, setbuf() will only take 32-bit pointers, and a compilation
- * with /POINTER_SIZE=64 will give off a MAYLOSEDATA2 warning here.
- * However, we trust that the C RTL will never give us a FILE pointer
- * above the first 4 GB of memory, so we simply turn off the warning
- * temporarily.
- */
-#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
-# pragma environment save
-# pragma message disable maylosedata2
-#endif
- setbuf(fp, NULL);
-#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
-# pragma environment restore
-#endif
-}
-
-static const char *modestr(char mode, int format)
-{
- OPENSSL_assert(mode == 'a' || mode == 'r' || mode == 'w');
-
- switch (mode) {
- case 'a':
- return istext(format) ? "a" : "ab";
- case 'r':
- return istext(format) ? "r" : "rb";
- case 'w':
- return istext(format) ? "w" : "wb";
- }
- /* The assert above should make sure we never reach this point */
- return NULL;
-}
-
-static const char *modeverb(char mode)
-{
- switch (mode) {
- case 'a':
- return "appending";
- case 'r':
- return "reading";
- case 'w':
- return "writing";
- }
- return "(doing something)";
-}
-
-/*
- * Open a file for writing, owner-read-only.
- */
-BIO *bio_open_owner(const char *filename, int format, int private)
-{
- FILE *fp = NULL;
- BIO *b = NULL;
- int fd = -1, bflags, mode, textmode;
-
- if (!private || filename == NULL || strcmp(filename, "-") == 0)
- return bio_open_default(filename, 'w', format);
-
- mode = O_WRONLY;
-#ifdef O_CREAT
- mode |= O_CREAT;
-#endif
-#ifdef O_TRUNC
- mode |= O_TRUNC;
-#endif
- textmode = istext(format);
- if (!textmode) {
-#ifdef O_BINARY
- mode |= O_BINARY;
-#elif defined(_O_BINARY)
- mode |= _O_BINARY;
-#endif
- }
-
-#ifdef OPENSSL_SYS_VMS
- /* VMS doesn't have O_BINARY, it just doesn't make sense. But,
- * it still needs to know that we're going binary, or fdopen()
- * will fail with "invalid argument"... so we tell VMS what the
- * context is.
- */
- if (!textmode)
- fd = open(filename, mode, 0600, "ctx=bin");
- else
-#endif
- fd = open(filename, mode, 0600);
- if (fd < 0)
- goto err;
- fp = fdopen(fd, modestr('w', format));
- if (fp == NULL)
- goto err;
- bflags = BIO_CLOSE;
- if (textmode)
- bflags |= BIO_FP_TEXT;
- b = BIO_new_fp(fp, bflags);
- if (b)
- return b;
-
- err:
- BIO_printf(bio_err, "%s: Can't open \"%s\" for writing, %s\n",
- opt_getprog(), filename, strerror(errno));
- ERR_print_errors(bio_err);
- /* If we have fp, then fdopen took over fd, so don't close both. */
- if (fp)
- fclose(fp);
- else if (fd >= 0)
- close(fd);
- return NULL;
-}
-
-static BIO *bio_open_default_(const char *filename, char mode, int format,
- int quiet)
-{
- BIO *ret;
-
- if (filename == NULL || strcmp(filename, "-") == 0) {
- ret = mode == 'r' ? dup_bio_in(format) : dup_bio_out(format);
- if (quiet) {
- ERR_clear_error();
- return ret;
- }
- if (ret != NULL)
- return ret;
- BIO_printf(bio_err,
- "Can't open %s, %s\n",
- mode == 'r' ? "stdin" : "stdout", strerror(errno));
- } else {
- ret = BIO_new_file(filename, modestr(mode, format));
- if (quiet) {
- ERR_clear_error();
- return ret;
- }
- if (ret != NULL)
- return ret;
- BIO_printf(bio_err,
- "Can't open %s for %s, %s\n",
- filename, modeverb(mode), strerror(errno));
- }
- ERR_print_errors(bio_err);
- return NULL;
-}
-
-BIO *bio_open_default(const char *filename, char mode, int format)
-{
- return bio_open_default_(filename, mode, format, 0);
-}
-
-BIO *bio_open_default_quiet(const char *filename, char mode, int format)
-{
- return bio_open_default_(filename, mode, format, 1);
-}
-
-void wait_for_async(SSL *s)
-{
- /* On Windows select only works for sockets, so we simply don't wait */
-#ifndef OPENSSL_SYS_WINDOWS
- int width = 0;
- fd_set asyncfds;
- OSSL_ASYNC_FD *fds;
- size_t numfds;
- size_t i;
-
- if (!SSL_get_all_async_fds(s, NULL, &numfds))
- return;
- if (numfds == 0)
- return;
- fds = app_malloc(sizeof(OSSL_ASYNC_FD) * numfds, "allocate async fds");
- if (!SSL_get_all_async_fds(s, fds, &numfds)) {
- OPENSSL_free(fds);
- return;
- }
-
- FD_ZERO(&asyncfds);
- for (i = 0; i < numfds; i++) {
- if (width <= (int)fds[i])
- width = (int)fds[i] + 1;
- openssl_fdset((int)fds[i], &asyncfds);
- }
- select(width, (void *)&asyncfds, NULL, NULL, NULL);
- OPENSSL_free(fds);
-#endif
-}
-
-/* if OPENSSL_SYS_WINDOWS is defined then so is OPENSSL_SYS_MSDOS */
-#if defined(OPENSSL_SYS_MSDOS)
-int has_stdin_waiting(void)
-{
-# if defined(OPENSSL_SYS_WINDOWS)
- HANDLE inhand = GetStdHandle(STD_INPUT_HANDLE);
- DWORD events = 0;
- INPUT_RECORD inputrec;
- DWORD insize = 1;
- BOOL peeked;
-
- if (inhand == INVALID_HANDLE_VALUE) {
- return 0;
- }
-
- peeked = PeekConsoleInput(inhand, &inputrec, insize, &events);
- if (!peeked) {
- /* Probably redirected input? _kbhit() does not work in this case */
- if (!feof(stdin)) {
- return 1;
- }
- return 0;
- }
-# endif
- return _kbhit();
-}
-#endif
-
-/* Corrupt a signature by modifying final byte */
-void corrupt_signature(const ASN1_STRING *signature)
-{
- unsigned char *s = signature->data;
- s[signature->length - 1] ^= 0x1;
-}
-
-int set_cert_times(X509 *x, const char *startdate, const char *enddate,
- int days)
-{
- if (startdate == NULL || strcmp(startdate, "today") == 0) {
- if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL)
- return 0;
- } else {
- if (!ASN1_TIME_set_string_X509(X509_getm_notBefore(x), startdate))
- return 0;
- }
- if (enddate == NULL) {
- if (X509_time_adj_ex(X509_getm_notAfter(x), days, 0, NULL)
- == NULL)
- return 0;
- } else if (!ASN1_TIME_set_string_X509(X509_getm_notAfter(x), enddate)) {
- return 0;
- }
- return 1;
-}
-
-void make_uppercase(char *string)
-{
- int i;
-
- for (i = 0; string[i] != '\0'; i++)
- string[i] = toupper((unsigned char)string[i]);
-}
diff --git a/apps/apps.h b/apps/apps.h
deleted file mode 100644
index 3e8f50fda87b..000000000000
--- a/apps/apps.h
+++ /dev/null
@@ -1,635 +0,0 @@
-/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef OSSL_APPS_H
-# define OSSL_APPS_H
-
-# include "e_os.h" /* struct timeval for DTLS */
-# include "internal/nelem.h"
-# include <assert.h>
-
-# include <sys/types.h>
-# ifndef OPENSSL_NO_POSIX_IO
-# include <sys/stat.h>
-# include <fcntl.h>
-# endif
-
-# include <openssl/e_os2.h>
-# include <openssl/ossl_typ.h>
-# include <openssl/bio.h>
-# include <openssl/x509.h>
-# include <openssl/conf.h>
-# include <openssl/txt_db.h>
-# include <openssl/engine.h>
-# include <openssl/ocsp.h>
-# include <signal.h>
-
-# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WINCE)
-# define openssl_fdset(a,b) FD_SET((unsigned int)a, b)
-# else
-# define openssl_fdset(a,b) FD_SET(a, b)
-# endif
-
-/*
- * quick macro when you need to pass an unsigned char instead of a char.
- * this is true for some implementations of the is*() functions, for
- * example.
- */
-#define _UC(c) ((unsigned char)(c))
-
-void app_RAND_load_conf(CONF *c, const char *section);
-void app_RAND_write(void);
-
-extern char *default_config_file;
-extern BIO *bio_in;
-extern BIO *bio_out;
-extern BIO *bio_err;
-extern const unsigned char tls13_aes128gcmsha256_id[];
-extern const unsigned char tls13_aes256gcmsha384_id[];
-extern BIO_ADDR *ourpeer;
-
-BIO_METHOD *apps_bf_prefix(void);
-/*
- * The control used to set the prefix with BIO_ctrl()
- * We make it high enough so the chance of ever clashing with the BIO library
- * remains unlikely for the foreseeable future and beyond.
- */
-#define PREFIX_CTRL_SET_PREFIX (1 << 15)
-/*
- * apps_bf_prefix() returns a dynamically created BIO_METHOD, which we
- * need to destroy at some point. When created internally, it's stored
- * in an internal pointer which can be freed with the following function
- */
-void destroy_prefix_method(void);
-
-BIO *dup_bio_in(int format);
-BIO *dup_bio_out(int format);
-BIO *dup_bio_err(int format);
-BIO *bio_open_owner(const char *filename, int format, int private);
-BIO *bio_open_default(const char *filename, char mode, int format);
-BIO *bio_open_default_quiet(const char *filename, char mode, int format);
-CONF *app_load_config_bio(BIO *in, const char *filename);
-CONF *app_load_config(const char *filename);
-CONF *app_load_config_quiet(const char *filename);
-int app_load_modules(const CONF *config);
-void unbuffer(FILE *fp);
-void wait_for_async(SSL *s);
-# if defined(OPENSSL_SYS_MSDOS)
-int has_stdin_waiting(void);
-# endif
-
-void corrupt_signature(const ASN1_STRING *signature);
-int set_cert_times(X509 *x, const char *startdate, const char *enddate,
- int days);
-
-/*
- * Common verification options.
- */
-# define OPT_V_ENUM \
- OPT_V__FIRST=2000, \
- OPT_V_POLICY, OPT_V_PURPOSE, OPT_V_VERIFY_NAME, OPT_V_VERIFY_DEPTH, \
- OPT_V_ATTIME, OPT_V_VERIFY_HOSTNAME, OPT_V_VERIFY_EMAIL, \
- OPT_V_VERIFY_IP, OPT_V_IGNORE_CRITICAL, OPT_V_ISSUER_CHECKS, \
- OPT_V_CRL_CHECK, OPT_V_CRL_CHECK_ALL, OPT_V_POLICY_CHECK, \
- OPT_V_EXPLICIT_POLICY, OPT_V_INHIBIT_ANY, OPT_V_INHIBIT_MAP, \
- OPT_V_X509_STRICT, OPT_V_EXTENDED_CRL, OPT_V_USE_DELTAS, \
- OPT_V_POLICY_PRINT, OPT_V_CHECK_SS_SIG, OPT_V_TRUSTED_FIRST, \
- OPT_V_SUITEB_128_ONLY, OPT_V_SUITEB_128, OPT_V_SUITEB_192, \
- OPT_V_PARTIAL_CHAIN, OPT_V_NO_ALT_CHAINS, OPT_V_NO_CHECK_TIME, \
- OPT_V_VERIFY_AUTH_LEVEL, OPT_V_ALLOW_PROXY_CERTS, \
- OPT_V__LAST
-
-# define OPT_V_OPTIONS \
- { "policy", OPT_V_POLICY, 's', "adds policy to the acceptable policy set"}, \
- { "purpose", OPT_V_PURPOSE, 's', \
- "certificate chain purpose"}, \
- { "verify_name", OPT_V_VERIFY_NAME, 's', "verification policy name"}, \
- { "verify_depth", OPT_V_VERIFY_DEPTH, 'n', \
- "chain depth limit" }, \
- { "auth_level", OPT_V_VERIFY_AUTH_LEVEL, 'n', \
- "chain authentication security level" }, \
- { "attime", OPT_V_ATTIME, 'M', "verification epoch time" }, \
- { "verify_hostname", OPT_V_VERIFY_HOSTNAME, 's', \
- "expected peer hostname" }, \
- { "verify_email", OPT_V_VERIFY_EMAIL, 's', \
- "expected peer email" }, \
- { "verify_ip", OPT_V_VERIFY_IP, 's', \
- "expected peer IP address" }, \
- { "ignore_critical", OPT_V_IGNORE_CRITICAL, '-', \
- "permit unhandled critical extensions"}, \
- { "issuer_checks", OPT_V_ISSUER_CHECKS, '-', "(deprecated)"}, \
- { "crl_check", OPT_V_CRL_CHECK, '-', "check leaf certificate revocation" }, \
- { "crl_check_all", OPT_V_CRL_CHECK_ALL, '-', "check full chain revocation" }, \
- { "policy_check", OPT_V_POLICY_CHECK, '-', "perform rfc5280 policy checks"}, \
- { "explicit_policy", OPT_V_EXPLICIT_POLICY, '-', \
- "set policy variable require-explicit-policy"}, \
- { "inhibit_any", OPT_V_INHIBIT_ANY, '-', \
- "set policy variable inhibit-any-policy"}, \
- { "inhibit_map", OPT_V_INHIBIT_MAP, '-', \
- "set policy variable inhibit-policy-mapping"}, \
- { "x509_strict", OPT_V_X509_STRICT, '-', \
- "disable certificate compatibility work-arounds"}, \
- { "extended_crl", OPT_V_EXTENDED_CRL, '-', \
- "enable extended CRL features"}, \
- { "use_deltas", OPT_V_USE_DELTAS, '-', \
- "use delta CRLs"}, \
- { "policy_print", OPT_V_POLICY_PRINT, '-', \
- "print policy processing diagnostics"}, \
- { "check_ss_sig", OPT_V_CHECK_SS_SIG, '-', \
- "check root CA self-signatures"}, \
- { "trusted_first", OPT_V_TRUSTED_FIRST, '-', \
- "search trust store first (default)" }, \
- { "suiteB_128_only", OPT_V_SUITEB_128_ONLY, '-', "Suite B 128-bit-only mode"}, \
- { "suiteB_128", OPT_V_SUITEB_128, '-', \
- "Suite B 128-bit mode allowing 192-bit algorithms"}, \
- { "suiteB_192", OPT_V_SUITEB_192, '-', "Suite B 192-bit-only mode" }, \
- { "partial_chain", OPT_V_PARTIAL_CHAIN, '-', \
- "accept chains anchored by intermediate trust-store CAs"}, \
- { "no_alt_chains", OPT_V_NO_ALT_CHAINS, '-', "(deprecated)" }, \
- { "no_check_time", OPT_V_NO_CHECK_TIME, '-', "ignore certificate validity time" }, \
- { "allow_proxy_certs", OPT_V_ALLOW_PROXY_CERTS, '-', "allow the use of proxy certificates" }
-
-# define OPT_V_CASES \
- OPT_V__FIRST: case OPT_V__LAST: break; \
- case OPT_V_POLICY: \
- case OPT_V_PURPOSE: \
- case OPT_V_VERIFY_NAME: \
- case OPT_V_VERIFY_DEPTH: \
- case OPT_V_VERIFY_AUTH_LEVEL: \
- case OPT_V_ATTIME: \
- case OPT_V_VERIFY_HOSTNAME: \
- case OPT_V_VERIFY_EMAIL: \
- case OPT_V_VERIFY_IP: \
- case OPT_V_IGNORE_CRITICAL: \
- case OPT_V_ISSUER_CHECKS: \
- case OPT_V_CRL_CHECK: \
- case OPT_V_CRL_CHECK_ALL: \
- case OPT_V_POLICY_CHECK: \
- case OPT_V_EXPLICIT_POLICY: \
- case OPT_V_INHIBIT_ANY: \
- case OPT_V_INHIBIT_MAP: \
- case OPT_V_X509_STRICT: \
- case OPT_V_EXTENDED_CRL: \
- case OPT_V_USE_DELTAS: \
- case OPT_V_POLICY_PRINT: \
- case OPT_V_CHECK_SS_SIG: \
- case OPT_V_TRUSTED_FIRST: \
- case OPT_V_SUITEB_128_ONLY: \
- case OPT_V_SUITEB_128: \
- case OPT_V_SUITEB_192: \
- case OPT_V_PARTIAL_CHAIN: \
- case OPT_V_NO_ALT_CHAINS: \
- case OPT_V_NO_CHECK_TIME: \
- case OPT_V_ALLOW_PROXY_CERTS
-
-/*
- * Common "extended validation" options.
- */
-# define OPT_X_ENUM \
- OPT_X__FIRST=1000, \
- OPT_X_KEY, OPT_X_CERT, OPT_X_CHAIN, OPT_X_CHAIN_BUILD, \
- OPT_X_CERTFORM, OPT_X_KEYFORM, \
- OPT_X__LAST
-
-# define OPT_X_OPTIONS \
- { "xkey", OPT_X_KEY, '<', "key for Extended certificates"}, \
- { "xcert", OPT_X_CERT, '<', "cert for Extended certificates"}, \
- { "xchain", OPT_X_CHAIN, '<', "chain for Extended certificates"}, \
- { "xchain_build", OPT_X_CHAIN_BUILD, '-', \
- "build certificate chain for the extended certificates"}, \
- { "xcertform", OPT_X_CERTFORM, 'F', \
- "format of Extended certificate (PEM or DER) PEM default " }, \
- { "xkeyform", OPT_X_KEYFORM, 'F', \
- "format of Extended certificate's key (PEM or DER) PEM default"}
-
-# define OPT_X_CASES \
- OPT_X__FIRST: case OPT_X__LAST: break; \
- case OPT_X_KEY: \
- case OPT_X_CERT: \
- case OPT_X_CHAIN: \
- case OPT_X_CHAIN_BUILD: \
- case OPT_X_CERTFORM: \
- case OPT_X_KEYFORM
-
-/*
- * Common SSL options.
- * Any changes here must be coordinated with ../ssl/ssl_conf.c
- */
-# define OPT_S_ENUM \
- OPT_S__FIRST=3000, \
- OPT_S_NOSSL3, OPT_S_NOTLS1, OPT_S_NOTLS1_1, OPT_S_NOTLS1_2, \
- OPT_S_NOTLS1_3, OPT_S_BUGS, OPT_S_NO_COMP, OPT_S_NOTICKET, \
- OPT_S_SERVERPREF, OPT_S_LEGACYRENEG, OPT_S_LEGACYCONN, \
- OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, OPT_S_ALLOW_NO_DHE_KEX, \
- OPT_S_PRIORITIZE_CHACHA, \
- OPT_S_STRICT, OPT_S_SIGALGS, OPT_S_CLIENTSIGALGS, OPT_S_GROUPS, \
- OPT_S_CURVES, OPT_S_NAMEDCURVE, OPT_S_CIPHER, OPT_S_CIPHERSUITES, \
- OPT_S_RECORD_PADDING, OPT_S_DEBUGBROKE, OPT_S_COMP, \
- OPT_S_MINPROTO, OPT_S_MAXPROTO, \
- OPT_S_NO_RENEGOTIATION, OPT_S_NO_MIDDLEBOX, OPT_S__LAST
-
-# define OPT_S_OPTIONS \
- {"no_ssl3", OPT_S_NOSSL3, '-',"Just disable SSLv3" }, \
- {"no_tls1", OPT_S_NOTLS1, '-', "Just disable TLSv1"}, \
- {"no_tls1_1", OPT_S_NOTLS1_1, '-', "Just disable TLSv1.1" }, \
- {"no_tls1_2", OPT_S_NOTLS1_2, '-', "Just disable TLSv1.2"}, \
- {"no_tls1_3", OPT_S_NOTLS1_3, '-', "Just disable TLSv1.3"}, \
- {"bugs", OPT_S_BUGS, '-', "Turn on SSL bug compatibility"}, \
- {"no_comp", OPT_S_NO_COMP, '-', "Disable SSL/TLS compression (default)" }, \
- {"comp", OPT_S_COMP, '-', "Use SSL/TLS-level compression" }, \
- {"no_ticket", OPT_S_NOTICKET, '-', \
- "Disable use of TLS session tickets"}, \
- {"serverpref", OPT_S_SERVERPREF, '-', "Use server's cipher preferences"}, \
- {"legacy_renegotiation", OPT_S_LEGACYRENEG, '-', \
- "Enable use of legacy renegotiation (dangerous)"}, \
- {"no_renegotiation", OPT_S_NO_RENEGOTIATION, '-', \
- "Disable all renegotiation."}, \
- {"legacy_server_connect", OPT_S_LEGACYCONN, '-', \
- "Allow initial connection to servers that don't support RI"}, \
- {"no_resumption_on_reneg", OPT_S_ONRESUMP, '-', \
- "Disallow session resumption on renegotiation"}, \
- {"no_legacy_server_connect", OPT_S_NOLEGACYCONN, '-', \
- "Disallow initial connection to servers that don't support RI"}, \
- {"allow_no_dhe_kex", OPT_S_ALLOW_NO_DHE_KEX, '-', \
- "In TLSv1.3 allow non-(ec)dhe based key exchange on resumption"}, \
- {"prioritize_chacha", OPT_S_PRIORITIZE_CHACHA, '-', \
- "Prioritize ChaCha ciphers when preferred by clients"}, \
- {"strict", OPT_S_STRICT, '-', \
- "Enforce strict certificate checks as per TLS standard"}, \
- {"sigalgs", OPT_S_SIGALGS, 's', \
- "Signature algorithms to support (colon-separated list)" }, \
- {"client_sigalgs", OPT_S_CLIENTSIGALGS, 's', \
- "Signature algorithms to support for client certificate" \
- " authentication (colon-separated list)" }, \
- {"groups", OPT_S_GROUPS, 's', \
- "Groups to advertise (colon-separated list)" }, \
- {"curves", OPT_S_CURVES, 's', \
- "Groups to advertise (colon-separated list)" }, \
- {"named_curve", OPT_S_NAMEDCURVE, 's', \
- "Elliptic curve used for ECDHE (server-side only)" }, \
- {"cipher", OPT_S_CIPHER, 's', "Specify TLSv1.2 and below cipher list to be used"}, \
- {"ciphersuites", OPT_S_CIPHERSUITES, 's', "Specify TLSv1.3 ciphersuites to be used"}, \
- {"min_protocol", OPT_S_MINPROTO, 's', "Specify the minimum protocol version to be used"}, \
- {"max_protocol", OPT_S_MAXPROTO, 's', "Specify the maximum protocol version to be used"}, \
- {"record_padding", OPT_S_RECORD_PADDING, 's', \
- "Block size to pad TLS 1.3 records to."}, \
- {"debug_broken_protocol", OPT_S_DEBUGBROKE, '-', \
- "Perform all sorts of protocol violations for testing purposes"}, \
- {"no_middlebox", OPT_S_NO_MIDDLEBOX, '-', \
- "Disable TLSv1.3 middlebox compat mode" }
-
-# define OPT_S_CASES \
- OPT_S__FIRST: case OPT_S__LAST: break; \
- case OPT_S_NOSSL3: \
- case OPT_S_NOTLS1: \
- case OPT_S_NOTLS1_1: \
- case OPT_S_NOTLS1_2: \
- case OPT_S_NOTLS1_3: \
- case OPT_S_BUGS: \
- case OPT_S_NO_COMP: \
- case OPT_S_COMP: \
- case OPT_S_NOTICKET: \
- case OPT_S_SERVERPREF: \
- case OPT_S_LEGACYRENEG: \
- case OPT_S_LEGACYCONN: \
- case OPT_S_ONRESUMP: \
- case OPT_S_NOLEGACYCONN: \
- case OPT_S_ALLOW_NO_DHE_KEX: \
- case OPT_S_PRIORITIZE_CHACHA: \
- case OPT_S_STRICT: \
- case OPT_S_SIGALGS: \
- case OPT_S_CLIENTSIGALGS: \
- case OPT_S_GROUPS: \
- case OPT_S_CURVES: \
- case OPT_S_NAMEDCURVE: \
- case OPT_S_CIPHER: \
- case OPT_S_CIPHERSUITES: \
- case OPT_S_RECORD_PADDING: \
- case OPT_S_NO_RENEGOTIATION: \
- case OPT_S_MINPROTO: \
- case OPT_S_MAXPROTO: \
- case OPT_S_DEBUGBROKE: \
- case OPT_S_NO_MIDDLEBOX
-
-#define IS_NO_PROT_FLAG(o) \
- (o == OPT_S_NOSSL3 || o == OPT_S_NOTLS1 || o == OPT_S_NOTLS1_1 \
- || o == OPT_S_NOTLS1_2 || o == OPT_S_NOTLS1_3)
-
-/*
- * Random state options.
- */
-# define OPT_R_ENUM \
- OPT_R__FIRST=1500, OPT_R_RAND, OPT_R_WRITERAND, OPT_R__LAST
-
-# define OPT_R_OPTIONS \
- {"rand", OPT_R_RAND, 's', "Load the file(s) into the random number generator"}, \
- {"writerand", OPT_R_WRITERAND, '>', "Write random data to the specified file"}
-
-# define OPT_R_CASES \
- OPT_R__FIRST: case OPT_R__LAST: break; \
- case OPT_R_RAND: case OPT_R_WRITERAND
-
-/*
- * Option parsing.
- */
-extern const char OPT_HELP_STR[];
-extern const char OPT_MORE_STR[];
-typedef struct options_st {
- const char *name;
- int retval;
- /*
- * value type: - no value (also the value zero), n number, p positive
- * number, u unsigned, l long, s string, < input file, > output file,
- * f any format, F der/pem format, E der/pem/engine format identifier.
- * l, n and u include zero; p does not.
- */
- int valtype;
- const char *helpstr;
-} OPTIONS;
-
-/*
- * A string/int pairing; widely use for option value lookup, hence the
- * name OPT_PAIR. But that name is misleading in s_cb.c, so we also use
- * the "generic" name STRINT_PAIR.
- */
-typedef struct string_int_pair_st {
- const char *name;
- int retval;
-} OPT_PAIR, STRINT_PAIR;
-
-/* Flags to pass into opt_format; see FORMAT_xxx, below. */
-# define OPT_FMT_PEMDER (1L << 1)
-# define OPT_FMT_PKCS12 (1L << 2)
-# define OPT_FMT_SMIME (1L << 3)
-# define OPT_FMT_ENGINE (1L << 4)
-# define OPT_FMT_MSBLOB (1L << 5)
-/* (1L << 6) was OPT_FMT_NETSCAPE, but wasn't used */
-# define OPT_FMT_NSS (1L << 7)
-# define OPT_FMT_TEXT (1L << 8)
-# define OPT_FMT_HTTP (1L << 9)
-# define OPT_FMT_PVK (1L << 10)
-# define OPT_FMT_PDE (OPT_FMT_PEMDER | OPT_FMT_ENGINE)
-# define OPT_FMT_PDS (OPT_FMT_PEMDER | OPT_FMT_SMIME)
-# define OPT_FMT_ANY ( \
- OPT_FMT_PEMDER | OPT_FMT_PKCS12 | OPT_FMT_SMIME | \
- OPT_FMT_ENGINE | OPT_FMT_MSBLOB | OPT_FMT_NSS | \
- OPT_FMT_TEXT | OPT_FMT_HTTP | OPT_FMT_PVK)
-
-char *opt_progname(const char *argv0);
-char *opt_getprog(void);
-char *opt_init(int ac, char **av, const OPTIONS * o);
-int opt_next(void);
-int opt_format(const char *s, unsigned long flags, int *result);
-int opt_int(const char *arg, int *result);
-int opt_ulong(const char *arg, unsigned long *result);
-int opt_long(const char *arg, long *result);
-#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
- defined(INTMAX_MAX) && defined(UINTMAX_MAX)
-int opt_imax(const char *arg, intmax_t *result);
-int opt_umax(const char *arg, uintmax_t *result);
-#else
-# define opt_imax opt_long
-# define opt_umax opt_ulong
-# define intmax_t long
-# define uintmax_t unsigned long
-#endif
-int opt_pair(const char *arg, const OPT_PAIR * pairs, int *result);
-int opt_cipher(const char *name, const EVP_CIPHER **cipherp);
-int opt_md(const char *name, const EVP_MD **mdp);
-char *opt_arg(void);
-char *opt_flag(void);
-char *opt_unknown(void);
-char **opt_rest(void);
-int opt_num_rest(void);
-int opt_verify(int i, X509_VERIFY_PARAM *vpm);
-int opt_rand(int i);
-void opt_help(const OPTIONS * list);
-int opt_format_error(const char *s, unsigned long flags);
-
-typedef struct args_st {
- int size;
- int argc;
- char **argv;
-} ARGS;
-
-/*
- * VMS C only for now, implemented in vms_decc_init.c
- * If other C compilers forget to terminate argv with NULL, this function
- * can be re-used.
- */
-char **copy_argv(int *argc, char *argv[]);
-/*
- * Win32-specific argv initialization that splits OS-supplied UNICODE
- * command line string to array of UTF8-encoded strings.
- */
-void win32_utf8argv(int *argc, char **argv[]);
-
-
-# define PW_MIN_LENGTH 4
-typedef struct pw_cb_data {
- const void *password;
- const char *prompt_info;
-} PW_CB_DATA;
-
-int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data);
-
-int setup_ui_method(void);
-void destroy_ui_method(void);
-const UI_METHOD *get_ui_method(void);
-
-int chopup_args(ARGS *arg, char *buf);
-int dump_cert_text(BIO *out, X509 *x);
-void print_name(BIO *out, const char *title, X509_NAME *nm,
- unsigned long lflags);
-void print_bignum_var(BIO *, const BIGNUM *, const char*,
- int, unsigned char *);
-void print_array(BIO *, const char *, int, const unsigned char *);
-int set_nameopt(const char *arg);
-unsigned long get_nameopt(void);
-int set_cert_ex(unsigned long *flags, const char *arg);
-int set_name_ex(unsigned long *flags, const char *arg);
-int set_ext_copy(int *copy_type, const char *arg);
-int copy_extensions(X509 *x, X509_REQ *req, int copy_type);
-int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2);
-int add_oid_section(CONF *conf);
-X509 *load_cert(const char *file, int format, const char *cert_descrip);
-X509_CRL *load_crl(const char *infile, int format);
-EVP_PKEY *load_key(const char *file, int format, int maybe_stdin,
- const char *pass, ENGINE *e, const char *key_descrip);
-EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin,
- const char *pass, ENGINE *e, const char *key_descrip);
-int load_certs(const char *file, STACK_OF(X509) **certs, int format,
- const char *pass, const char *cert_descrip);
-int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format,
- const char *pass, const char *cert_descrip);
-X509_STORE *setup_verify(const char *CAfile, const char *CApath,
- int noCAfile, int noCApath);
-__owur int ctx_set_verify_locations(SSL_CTX *ctx, const char *CAfile,
- const char *CApath, int noCAfile,
- int noCApath);
-
-#ifndef OPENSSL_NO_CT
-
-/*
- * Sets the file to load the Certificate Transparency log list from.
- * If path is NULL, loads from the default file path.
- * Returns 1 on success, 0 otherwise.
- */
-__owur int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path);
-
-#endif
-
-ENGINE *setup_engine(const char *engine, int debug);
-void release_engine(ENGINE *e);
-
-# ifndef OPENSSL_NO_OCSP
-OCSP_RESPONSE *process_responder(OCSP_REQUEST *req,
- const char *host, const char *path,
- const char *port, int use_ssl,
- STACK_OF(CONF_VALUE) *headers,
- int req_timeout);
-# endif
-
-/* Functions defined in ca.c and also used in ocsp.c */
-int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold,
- ASN1_GENERALIZEDTIME **pinvtm, const char *str);
-
-# define DB_type 0
-# define DB_exp_date 1
-# define DB_rev_date 2
-# define DB_serial 3 /* index - unique */
-# define DB_file 4
-# define DB_name 5 /* index - unique when active and not
- * disabled */
-# define DB_NUMBER 6
-
-# define DB_TYPE_REV 'R' /* Revoked */
-# define DB_TYPE_EXP 'E' /* Expired */
-# define DB_TYPE_VAL 'V' /* Valid ; inserted with: ca ... -valid */
-# define DB_TYPE_SUSP 'S' /* Suspended */
-
-typedef struct db_attr_st {
- int unique_subject;
-} DB_ATTR;
-typedef struct ca_db_st {
- DB_ATTR attributes;
- TXT_DB *db;
- char *dbfname;
-# ifndef OPENSSL_NO_POSIX_IO
- struct stat dbst;
-# endif
-} CA_DB;
-
-void* app_malloc(int sz, const char *what);
-
-/* load_serial, save_serial, and rotate_serial are also used for CRL numbers */
-BIGNUM *load_serial(const char *serialfile, int *exists, int create,
- ASN1_INTEGER **retai);
-int save_serial(const char *serialfile, const char *suffix,
- const BIGNUM *serial, ASN1_INTEGER **retai);
-int rotate_serial(const char *serialfile, const char *new_suffix,
- const char *old_suffix);
-int rand_serial(BIGNUM *b, ASN1_INTEGER *ai);
-CA_DB *load_index(const char *dbfile, DB_ATTR *dbattr);
-int index_index(CA_DB *db);
-int save_index(const char *dbfile, const char *suffix, CA_DB *db);
-int rotate_index(const char *dbfile, const char *new_suffix,
- const char *old_suffix);
-void free_index(CA_DB *db);
-# define index_name_cmp_noconst(a, b) \
- index_name_cmp((const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, a), \
- (const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, b))
-int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b);
-int parse_yesno(const char *str, int def);
-
-X509_NAME *parse_name(const char *str, long chtype, int multirdn);
-void policies_print(X509_STORE_CTX *ctx);
-int bio_to_mem(unsigned char **out, int maxlen, BIO *in);
-int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value);
-int init_gen_str(EVP_PKEY_CTX **pctx,
- const char *algname, ENGINE *e, int do_param);
-int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md,
- STACK_OF(OPENSSL_STRING) *sigopts);
-int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md,
- STACK_OF(OPENSSL_STRING) *sigopts);
-int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md,
- STACK_OF(OPENSSL_STRING) *sigopts);
-
-extern char *psk_key;
-
-
-unsigned char *next_protos_parse(size_t *outlen, const char *in);
-
-void print_cert_checks(BIO *bio, X509 *x,
- const char *checkhost,
- const char *checkemail, const char *checkip);
-
-void store_setup_crl_download(X509_STORE *st);
-
-/* See OPT_FMT_xxx, above. */
-/* On some platforms, it's important to distinguish between text and binary
- * files. On some, there might even be specific file formats for different
- * contents. The FORMAT_xxx macros are meant to express an intent with the
- * file being read or created.
- */
-# define B_FORMAT_TEXT 0x8000
-# define FORMAT_UNDEF 0
-# define FORMAT_TEXT (1 | B_FORMAT_TEXT) /* Generic text */
-# define FORMAT_BINARY 2 /* Generic binary */
-# define FORMAT_BASE64 (3 | B_FORMAT_TEXT) /* Base64 */
-# define FORMAT_ASN1 4 /* ASN.1/DER */
-# define FORMAT_PEM (5 | B_FORMAT_TEXT)
-# define FORMAT_PKCS12 6
-# define FORMAT_SMIME (7 | B_FORMAT_TEXT)
-# define FORMAT_ENGINE 8 /* Not really a file format */
-# define FORMAT_PEMRSA (9 | B_FORMAT_TEXT) /* PEM RSAPubicKey format */
-# define FORMAT_ASN1RSA 10 /* DER RSAPubicKey format */
-# define FORMAT_MSBLOB 11 /* MS Key blob format */
-# define FORMAT_PVK 12 /* MS PVK file format */
-# define FORMAT_HTTP 13 /* Download using HTTP */
-# define FORMAT_NSS 14 /* NSS keylog format */
-
-# define EXT_COPY_NONE 0
-# define EXT_COPY_ADD 1
-# define EXT_COPY_ALL 2
-
-# define NETSCAPE_CERT_HDR "certificate"
-
-# define APP_PASS_LEN 1024
-
-/*
- * IETF RFC 5280 says serial number must be <= 20 bytes. Use 159 bits
- * so that the first bit will never be one, so that the DER encoding
- * rules won't force a leading octet.
- */
-# define SERIAL_RAND_BITS 159
-
-int app_isdir(const char *);
-int app_access(const char *, int flag);
-int fileno_stdin(void);
-int fileno_stdout(void);
-int raw_read_stdin(void *, int);
-int raw_write_stdout(const void *, int);
-
-# define TM_START 0
-# define TM_STOP 1
-double app_tminterval(int stop, int usertime);
-
-void make_uppercase(char *string);
-
-typedef struct verify_options_st {
- int depth;
- int quiet;
- int error;
- int return_error;
-} VERIFY_CB_ARGS;
-
-extern VERIFY_CB_ARGS verify_args;
-
-#endif
diff --git a/apps/asn1pars.c b/apps/asn1pars.c
deleted file mode 100644
index 6c44df7de490..000000000000
--- a/apps/asn1pars.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "apps.h"
-#include "progs.h"
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-#include <openssl/pem.h>
-#include <openssl/asn1t.h>
-
-typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_INFORM, OPT_IN, OPT_OUT, OPT_INDENT, OPT_NOOUT,
- OPT_OID, OPT_OFFSET, OPT_LENGTH, OPT_DUMP, OPT_DLIMIT,
- OPT_STRPARSE, OPT_GENSTR, OPT_GENCONF, OPT_STRICTPEM,
- OPT_ITEM
-} OPTION_CHOICE;
-
-const OPTIONS asn1parse_options[] = {
- {"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'F', "input format - one of DER PEM"},
- {"in", OPT_IN, '<', "input file"},
- {"out", OPT_OUT, '>', "output file (output format is always DER)"},
- {"i", OPT_INDENT, 0, "indents the output"},
- {"noout", OPT_NOOUT, 0, "do not produce any output"},
- {"offset", OPT_OFFSET, 'p', "offset into file"},
- {"length", OPT_LENGTH, 'p', "length of section in file"},
- {"oid", OPT_OID, '<', "file of extra oid definitions"},
- {"dump", OPT_DUMP, 0, "unknown data in hex form"},
- {"dlimit", OPT_DLIMIT, 'p',
- "dump the first arg bytes of unknown data in hex form"},
- {"strparse", OPT_STRPARSE, 'p',
- "offset; a series of these can be used to 'dig'"},
- {OPT_MORE_STR, 0, 0, "into multiple ASN1 blob wrappings"},
- {"genstr", OPT_GENSTR, 's', "string to generate ASN1 structure from"},
- {"genconf", OPT_GENCONF, 's', "file to generate ASN1 structure from"},
- {OPT_MORE_STR, 0, 0, "(-inform will be ignored)"},
- {"strictpem", OPT_STRICTPEM, 0,
- "do not attempt base64 decode outside PEM markers"},
- {"item", OPT_ITEM, 's', "item to parse and print"},
- {NULL}
-};
-
-static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf);
-
-int asn1parse_main(int argc, char **argv)
-{
- ASN1_TYPE *at = NULL;
- BIO *in = NULL, *b64 = NULL, *derout = NULL;
- BUF_MEM *buf = NULL;
- STACK_OF(OPENSSL_STRING) *osk = NULL;
- char *genstr = NULL, *genconf = NULL;
- char *infile = NULL, *oidfile = NULL, *derfile = NULL;
- unsigned char *str = NULL;
- char *name = NULL, *header = NULL, *prog;
- const unsigned char *ctmpbuf;
- int indent = 0, noout = 0, dump = 0, strictpem = 0, informat = FORMAT_PEM;
- int offset = 0, ret = 1, i, j;
- long num, tmplen;
- unsigned char *tmpbuf;
- unsigned int length = 0;
- OPTION_CHOICE o;
- const ASN1_ITEM *it = NULL;
-
- prog = opt_init(argc, argv, asn1parse_options);
-
- if ((osk = sk_OPENSSL_STRING_new_null()) == NULL) {
- BIO_printf(bio_err, "%s: Memory allocation failure\n", prog);
- goto end;
- }
-
- while ((o = opt_next()) != OPT_EOF) {
- switch (o) {
- case OPT_EOF:
- case OPT_ERR:
- opthelp:
- BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
- goto end;
- case OPT_HELP:
- opt_help(asn1parse_options);
- ret = 0;
- goto end;
- case OPT_INFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
- goto opthelp;
- break;
- case OPT_IN:
- infile = opt_arg();
- break;
- case OPT_OUT:
- derfile = opt_arg();
- break;
- case OPT_INDENT:
- indent = 1;
- break;
- case OPT_NOOUT:
- noout = 1;
- break;
- case OPT_OID:
- oidfile = opt_arg();
- break;
- case OPT_OFFSET:
- offset = strtol(opt_arg(), NULL, 0);
- break;
- case OPT_LENGTH:
- length = strtol(opt_arg(), NULL, 0);
- break;
- case OPT_DUMP:
- dump = -1;
- break;
- case OPT_DLIMIT:
- dump = strtol(opt_arg(), NULL, 0);
- break;
- case OPT_STRPARSE:
- sk_OPENSSL_STRING_push(osk, opt_arg());
- break;
- case OPT_GENSTR:
- genstr = opt_arg();
- break;
- case OPT_GENCONF:
- genconf = opt_arg();
- break;
- case OPT_STRICTPEM:
- strictpem = 1;
- informat = FORMAT_PEM;
- break;
- case OPT_ITEM:
- it = ASN1_ITEM_lookup(opt_arg());
- if (it == NULL) {
- size_t tmp;
-
- BIO_printf(bio_err, "Unknown item name %s\n", opt_arg());
- BIO_puts(bio_err, "Supported types:\n");
- for (tmp = 0;; tmp++) {
- it = ASN1_ITEM_get(tmp);
- if (it == NULL)
- break;
- BIO_printf(bio_err, " %s\n", it->sname);
- }
- goto end;
- }
- break;
- }
- }
- argc = opt_num_rest();
- if (argc != 0)
- goto opthelp;
-
- if (oidfile != NULL) {
- in = bio_open_default(oidfile, 'r', FORMAT_TEXT);
- if (in == NULL)
- goto end;
- OBJ_create_objects(in);
- BIO_free(in);
- }
-
- if ((in = bio_open_default(infile, 'r', informat)) == NULL)
- goto end;
-
- if (derfile && (derout = bio_open_default(derfile, 'w', FORMAT_ASN1)) == NULL)
- goto end;
-
- if ((buf = BUF_MEM_new()) == NULL)
- goto end;
- if (strictpem) {
- if (PEM_read_bio(in, &name, &header, &str, &num) != 1) {
- BIO_printf(bio_err, "Error reading PEM file\n");
- ERR_print_errors(bio_err);
- goto end;
- }
- buf->data = (char *)str;
- buf->length = buf->max = num;
- } else {
- if (!BUF_MEM_grow(buf, BUFSIZ * 8))
- goto end; /* Pre-allocate :-) */
-
- if (genstr || genconf) {
- num = do_generate(genstr, genconf, buf);
- if (num < 0) {
- ERR_print_errors(bio_err);
- goto end;
- }
- } else {
-
- if (informat == FORMAT_PEM) {
- BIO *tmp;
-
- if ((b64 = BIO_new(BIO_f_base64())) == NULL)
- goto end;
- BIO_push(b64, in);
- tmp = in;
- in = b64;
- b64 = tmp;
- }
-
- num = 0;
- for (;;) {
- if (!BUF_MEM_grow(buf, num + BUFSIZ))
- goto end;
- i = BIO_read(in, &(buf->data[num]), BUFSIZ);
- if (i <= 0)
- break;
- num += i;
- }
- }
- str = (unsigned char *)buf->data;
-
- }
-
- /* If any structs to parse go through in sequence */
-
- if (sk_OPENSSL_STRING_num(osk)) {
- tmpbuf = str;
- tmplen = num;
- for (i = 0; i < sk_OPENSSL_STRING_num(osk); i++) {
- ASN1_TYPE *atmp;
- int typ;
- j = strtol(sk_OPENSSL_STRING_value(osk, i), NULL, 0);
- if (j <= 0 || j >= tmplen) {
- BIO_printf(bio_err, "'%s' is out of range\n",
- sk_OPENSSL_STRING_value(osk, i));
- continue;
- }
- tmpbuf += j;
- tmplen -= j;
- atmp = at;
- ctmpbuf = tmpbuf;
- at = d2i_ASN1_TYPE(NULL, &ctmpbuf, tmplen);
- ASN1_TYPE_free(atmp);
- if (!at) {
- BIO_printf(bio_err, "Error parsing structure\n");
- ERR_print_errors(bio_err);
- goto end;
- }
- typ = ASN1_TYPE_get(at);
- if ((typ == V_ASN1_OBJECT)
- || (typ == V_ASN1_BOOLEAN)
- || (typ == V_ASN1_NULL)) {
- BIO_printf(bio_err, "Can't parse %s type\n", ASN1_tag2str(typ));
- ERR_print_errors(bio_err);
- goto end;
- }
- /* hmm... this is a little evil but it works */
- tmpbuf = at->value.asn1_string->data;
- tmplen = at->value.asn1_string->length;
- }
- str = tmpbuf;
- num = tmplen;
- }
-
- if (offset < 0 || offset >= num) {
- BIO_printf(bio_err, "Error: offset out of range\n");
- goto end;
- }
-
- num -= offset;
-
- if (length == 0 || length > (unsigned int)num)
- length = (unsigned int)num;
- if (derout != NULL) {
- if (BIO_write(derout, str + offset, length) != (int)length) {
- BIO_printf(bio_err, "Error writing output\n");
- ERR_print_errors(bio_err);
- goto end;
- }
- }
- if (!noout) {
- const unsigned char *p = str + offset;
-
- if (it != NULL) {
- ASN1_VALUE *value = ASN1_item_d2i(NULL, &p, length, it);
- if (value == NULL) {
- BIO_printf(bio_err, "Error parsing item %s\n", it->sname);
- ERR_print_errors(bio_err);
- goto end;
- }
- ASN1_item_print(bio_out, value, 0, it, NULL);
- ASN1_item_free(value, it);
- } else {
- if (!ASN1_parse_dump(bio_out, p, length, indent, dump)) {
- ERR_print_errors(bio_err);
- goto end;
- }
- }
- }
- ret = 0;
- end:
- BIO_free(derout);
- BIO_free(in);
- BIO_free(b64);
- if (ret != 0)
- ERR_print_errors(bio_err);
- BUF_MEM_free(buf);
- OPENSSL_free(name);
- OPENSSL_free(header);
- ASN1_TYPE_free(at);
- sk_OPENSSL_STRING_free(osk);
- return ret;
-}
-
-static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf)
-{
- CONF *cnf = NULL;
- int len;
- unsigned char *p;
- ASN1_TYPE *atyp = NULL;
-
- if (genconf != NULL) {
- if ((cnf = app_load_config(genconf)) == NULL)
- goto err;
- if (genstr == NULL)
- genstr = NCONF_get_string(cnf, "default", "asn1");
- if (genstr == NULL) {
- BIO_printf(bio_err, "Can't find 'asn1' in '%s'\n", genconf);
- goto err;
- }
- }
-
- atyp = ASN1_generate_nconf(genstr, cnf);
- NCONF_free(cnf);
- cnf = NULL;
-
- if (atyp == NULL)
- return -1;
-
- len = i2d_ASN1_TYPE(atyp, NULL);
-
- if (len <= 0)
- goto err;
-
- if (!BUF_MEM_grow(buf, len))
- goto err;
-
- p = (unsigned char *)buf->data;
-
- i2d_ASN1_TYPE(atyp, &p);
-
- ASN1_TYPE_free(atyp);
- return len;
-
- err:
- NCONF_free(cnf);
- ASN1_TYPE_free(atyp);
- return -1;
-}
diff --git a/apps/asn1parse.c b/apps/asn1parse.c
new file mode 100644
index 000000000000..f0bfd1d45fc4
--- /dev/null
+++ b/apps/asn1parse.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/asn1t.h>
+
+typedef enum OPTION_choice {
+ OPT_COMMON,
+ OPT_INFORM, OPT_IN, OPT_OUT, OPT_INDENT, OPT_NOOUT,
+ OPT_OID, OPT_OFFSET, OPT_LENGTH, OPT_DUMP, OPT_DLIMIT,
+ OPT_STRPARSE, OPT_GENSTR, OPT_GENCONF, OPT_STRICTPEM,
+ OPT_ITEM
+} OPTION_CHOICE;
+
+const OPTIONS asn1parse_options[] = {
+ OPT_SECTION("General"),
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"oid", OPT_OID, '<', "file of extra oid definitions"},
+
+ OPT_SECTION("I/O"),
+ {"inform", OPT_INFORM, 'F', "input format - one of DER PEM"},
+ {"in", OPT_IN, '<', "input file"},
+ {"out", OPT_OUT, '>', "output file (output format is always DER)"},
+ {"noout", OPT_NOOUT, 0, "do not produce any output"},
+ {"offset", OPT_OFFSET, 'p', "offset into file"},
+ {"length", OPT_LENGTH, 'p', "length of section in file"},
+ {"strparse", OPT_STRPARSE, 'p',
+ "offset; a series of these can be used to 'dig'"},
+ {"genstr", OPT_GENSTR, 's', "string to generate ASN1 structure from"},
+ {OPT_MORE_STR, 0, 0, "into multiple ASN1 blob wrappings"},
+ {"genconf", OPT_GENCONF, 's', "file to generate ASN1 structure from"},
+ {"strictpem", OPT_STRICTPEM, 0,
+ "do not attempt base64 decode outside PEM markers"},
+ {"item", OPT_ITEM, 's', "item to parse and print"},
+ {OPT_MORE_STR, 0, 0, "(-inform will be ignored)"},
+
+ OPT_SECTION("Formatting"),
+ {"i", OPT_INDENT, 0, "indents the output"},
+ {"dump", OPT_DUMP, 0, "unknown data in hex form"},
+ {"dlimit", OPT_DLIMIT, 'p',
+ "dump the first arg bytes of unknown data in hex form"},
+ {NULL}
+};
+
+static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf);
+
+int asn1parse_main(int argc, char **argv)
+{
+ ASN1_TYPE *at = NULL;
+ BIO *in = NULL, *b64 = NULL, *derout = NULL;
+ BUF_MEM *buf = NULL;
+ STACK_OF(OPENSSL_STRING) *osk = NULL;
+ char *genstr = NULL, *genconf = NULL;
+ char *infile = NULL, *oidfile = NULL, *derfile = NULL;
+ unsigned char *str = NULL;
+ char *name = NULL, *header = NULL, *prog;
+ const unsigned char *ctmpbuf;
+ int indent = 0, noout = 0, dump = 0, strictpem = 0, informat = FORMAT_PEM;
+ int offset = 0, ret = 1, i, j;
+ long num, tmplen;
+ unsigned char *tmpbuf;
+ unsigned int length = 0;
+ OPTION_CHOICE o;
+ const ASN1_ITEM *it = NULL;
+
+ prog = opt_init(argc, argv, asn1parse_options);
+
+ if ((osk = sk_OPENSSL_STRING_new_null()) == NULL) {
+ BIO_printf(bio_err, "%s: Memory allocation failure\n", prog);
+ goto end;
+ }
+
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(asn1parse_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ derfile = opt_arg();
+ break;
+ case OPT_INDENT:
+ indent = 1;
+ break;
+ case OPT_NOOUT:
+ noout = 1;
+ break;
+ case OPT_OID:
+ oidfile = opt_arg();
+ break;
+ case OPT_OFFSET:
+ offset = strtol(opt_arg(), NULL, 0);
+ break;
+ case OPT_LENGTH:
+ length = strtol(opt_arg(), NULL, 0);
+ break;
+ case OPT_DUMP:
+ dump = -1;
+ break;
+ case OPT_DLIMIT:
+ dump = strtol(opt_arg(), NULL, 0);
+ break;
+ case OPT_STRPARSE:
+ sk_OPENSSL_STRING_push(osk, opt_arg());
+ break;
+ case OPT_GENSTR:
+ genstr = opt_arg();
+ break;
+ case OPT_GENCONF:
+ genconf = opt_arg();
+ break;
+ case OPT_STRICTPEM:
+ strictpem = 1;
+ informat = FORMAT_PEM;
+ break;
+ case OPT_ITEM:
+ it = ASN1_ITEM_lookup(opt_arg());
+ if (it == NULL) {
+ size_t tmp;
+
+ BIO_printf(bio_err, "Unknown item name %s\n", opt_arg());
+ BIO_puts(bio_err, "Supported types:\n");
+ for (tmp = 0;; tmp++) {
+ it = ASN1_ITEM_get(tmp);
+ if (it == NULL)
+ break;
+ BIO_printf(bio_err, " %s\n", it->sname);
+ }
+ goto end;
+ }
+ break;
+ }
+ }
+
+ /* No extra args. */
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ if (oidfile != NULL) {
+ in = bio_open_default(oidfile, 'r', FORMAT_TEXT);
+ if (in == NULL)
+ goto end;
+ OBJ_create_objects(in);
+ BIO_free(in);
+ }
+
+ if ((in = bio_open_default(infile, 'r', informat)) == NULL)
+ goto end;
+
+ if (derfile && (derout = bio_open_default(derfile, 'w', FORMAT_ASN1)) == NULL)
+ goto end;
+
+ if ((buf = BUF_MEM_new()) == NULL)
+ goto end;
+ if (strictpem) {
+ if (PEM_read_bio(in, &name, &header, &str, &num) != 1) {
+ BIO_printf(bio_err, "Error reading PEM file\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ buf->data = (char *)str;
+ buf->length = buf->max = num;
+ } else {
+ if (!BUF_MEM_grow(buf, BUFSIZ * 8))
+ goto end; /* Pre-allocate :-) */
+
+ if (genstr || genconf) {
+ num = do_generate(genstr, genconf, buf);
+ if (num < 0) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ } else {
+
+ if (informat == FORMAT_PEM) {
+ BIO *tmp;
+
+ if ((b64 = BIO_new(BIO_f_base64())) == NULL)
+ goto end;
+ BIO_push(b64, in);
+ tmp = in;
+ in = b64;
+ b64 = tmp;
+ }
+
+ num = 0;
+ for (;;) {
+ if (!BUF_MEM_grow(buf, num + BUFSIZ))
+ goto end;
+ i = BIO_read(in, &(buf->data[num]), BUFSIZ);
+ if (i <= 0)
+ break;
+ num += i;
+ }
+ }
+ str = (unsigned char *)buf->data;
+
+ }
+
+ /* If any structs to parse go through in sequence */
+
+ if (sk_OPENSSL_STRING_num(osk)) {
+ tmpbuf = str;
+ tmplen = num;
+ for (i = 0; i < sk_OPENSSL_STRING_num(osk); i++) {
+ ASN1_TYPE *atmp;
+ int typ;
+ j = strtol(sk_OPENSSL_STRING_value(osk, i), NULL, 0);
+ if (j <= 0 || j >= tmplen) {
+ BIO_printf(bio_err, "'%s' is out of range\n",
+ sk_OPENSSL_STRING_value(osk, i));
+ continue;
+ }
+ tmpbuf += j;
+ tmplen -= j;
+ atmp = at;
+ ctmpbuf = tmpbuf;
+ at = d2i_ASN1_TYPE(NULL, &ctmpbuf, tmplen);
+ ASN1_TYPE_free(atmp);
+ if (!at) {
+ BIO_printf(bio_err, "Error parsing structure\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ typ = ASN1_TYPE_get(at);
+ if ((typ == V_ASN1_OBJECT)
+ || (typ == V_ASN1_BOOLEAN)
+ || (typ == V_ASN1_NULL)) {
+ BIO_printf(bio_err, "Can't parse %s type\n", ASN1_tag2str(typ));
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ /* hmm... this is a little evil but it works */
+ tmpbuf = at->value.asn1_string->data;
+ tmplen = at->value.asn1_string->length;
+ }
+ str = tmpbuf;
+ num = tmplen;
+ }
+
+ if (offset < 0 || offset >= num) {
+ BIO_printf(bio_err, "Error: offset out of range\n");
+ goto end;
+ }
+
+ num -= offset;
+
+ if (length == 0 || length > (unsigned int)num)
+ length = (unsigned int)num;
+ if (derout != NULL) {
+ if (BIO_write(derout, str + offset, length) != (int)length) {
+ BIO_printf(bio_err, "Error writing output\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ if (!noout) {
+ const unsigned char *p = str + offset;
+
+ if (it != NULL) {
+ ASN1_VALUE *value = ASN1_item_d2i(NULL, &p, length, it);
+ if (value == NULL) {
+ BIO_printf(bio_err, "Error parsing item %s\n", it->sname);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ ASN1_item_print(bio_out, value, 0, it, NULL);
+ ASN1_item_free(value, it);
+ } else {
+ if (!ASN1_parse_dump(bio_out, p, length, indent, dump)) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ }
+ ret = 0;
+ end:
+ BIO_free(derout);
+ BIO_free(in);
+ BIO_free(b64);
+ if (ret != 0)
+ ERR_print_errors(bio_err);
+ BUF_MEM_free(buf);
+ OPENSSL_free(name);
+ OPENSSL_free(header);
+ ASN1_TYPE_free(at);
+ sk_OPENSSL_STRING_free(osk);
+ return ret;
+}
+
+static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf)
+{
+ CONF *cnf = NULL;
+ int len;
+ unsigned char *p;
+ ASN1_TYPE *atyp = NULL;
+
+ if (genconf != NULL) {
+ if ((cnf = app_load_config(genconf)) == NULL)
+ goto err;
+ if (genstr == NULL)
+ genstr = NCONF_get_string(cnf, "default", "asn1");
+ if (genstr == NULL) {
+ BIO_printf(bio_err, "Can't find 'asn1' in '%s'\n", genconf);
+ goto err;
+ }
+ }
+
+ atyp = ASN1_generate_nconf(genstr, cnf);
+ NCONF_free(cnf);
+ cnf = NULL;
+
+ if (atyp == NULL)
+ return -1;
+
+ len = i2d_ASN1_TYPE(atyp, NULL);
+
+ if (len <= 0)
+ goto err;
+
+ if (!BUF_MEM_grow(buf, len))
+ goto err;
+
+ p = (unsigned char *)buf->data;
+
+ i2d_ASN1_TYPE(atyp, &p);
+
+ ASN1_TYPE_free(atyp);
+ return len;
+
+ err:
+ NCONF_free(cnf);
+ ASN1_TYPE_free(atyp);
+ return -1;
+}
diff --git a/apps/bf_prefix.c b/apps/bf_prefix.c
deleted file mode 100644
index bae3c91bf8b3..000000000000
--- a/apps/bf_prefix.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <openssl/bio.h>
-#include "apps.h"
-
-static int prefix_write(BIO *b, const char *out, size_t outl,
- size_t *numwritten);
-static int prefix_read(BIO *b, char *buf, size_t size, size_t *numread);
-static int prefix_puts(BIO *b, const char *str);
-static int prefix_gets(BIO *b, char *str, int size);
-static long prefix_ctrl(BIO *b, int cmd, long arg1, void *arg2);
-static int prefix_create(BIO *b);
-static int prefix_destroy(BIO *b);
-static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp);
-
-static BIO_METHOD *prefix_meth = NULL;
-
-BIO_METHOD *apps_bf_prefix(void)
-{
- if (prefix_meth == NULL) {
- if ((prefix_meth =
- BIO_meth_new(BIO_TYPE_FILTER, "Prefix filter")) == NULL
- || !BIO_meth_set_create(prefix_meth, prefix_create)
- || !BIO_meth_set_destroy(prefix_meth, prefix_destroy)
- || !BIO_meth_set_write_ex(prefix_meth, prefix_write)
- || !BIO_meth_set_read_ex(prefix_meth, prefix_read)
- || !BIO_meth_set_puts(prefix_meth, prefix_puts)
- || !BIO_meth_set_gets(prefix_meth, prefix_gets)
- || !BIO_meth_set_ctrl(prefix_meth, prefix_ctrl)
- || !BIO_meth_set_callback_ctrl(prefix_meth, prefix_callback_ctrl)) {
- BIO_meth_free(prefix_meth);
- prefix_meth = NULL;
- }
- }
- return prefix_meth;
-}
-
-typedef struct prefix_ctx_st {
- char *prefix;
- int linestart; /* flag to indicate we're at the line start */
-} PREFIX_CTX;
-
-static int prefix_create(BIO *b)
-{
- PREFIX_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
-
- if (ctx == NULL)
- return 0;
-
- ctx->prefix = NULL;
- ctx->linestart = 1;
- BIO_set_data(b, ctx);
- BIO_set_init(b, 1);
- return 1;
-}
-
-static int prefix_destroy(BIO *b)
-{
- PREFIX_CTX *ctx = BIO_get_data(b);
-
- OPENSSL_free(ctx->prefix);
- OPENSSL_free(ctx);
- return 1;
-}
-
-static int prefix_read(BIO *b, char *in, size_t size, size_t *numread)
-{
- return BIO_read_ex(BIO_next(b), in, size, numread);
-}
-
-static int prefix_write(BIO *b, const char *out, size_t outl,
- size_t *numwritten)
-{
- PREFIX_CTX *ctx = BIO_get_data(b);
-
- if (ctx == NULL)
- return 0;
-
- /* If no prefix is set or if it's empty, we've got nothing to do here */
- if (ctx->prefix == NULL || *ctx->prefix == '\0') {
- /* We do note if what comes next will be a new line, though */
- if (outl > 0)
- ctx->linestart = (out[outl-1] == '\n');
- return BIO_write_ex(BIO_next(b), out, outl, numwritten);
- }
-
- *numwritten = 0;
-
- while (outl > 0) {
- size_t i;
- char c;
-
- /* If we know that we're at the start of the line, output the prefix */
- if (ctx->linestart) {
- size_t dontcare;
-
- if (!BIO_write_ex(BIO_next(b), ctx->prefix, strlen(ctx->prefix),
- &dontcare))
- return 0;
- ctx->linestart = 0;
- }
-
- /* Now, go look for the next LF, or the end of the string */
- for (i = 0, c = '\0'; i < outl && (c = out[i]) != '\n'; i++)
- continue;
- if (c == '\n')
- i++;
-
- /* Output what we found so far */
- while (i > 0) {
- size_t num = 0;
-
- if (!BIO_write_ex(BIO_next(b), out, i, &num))
- return 0;
- out += num;
- outl -= num;
- *numwritten += num;
- i -= num;
- }
-
- /* If we found a LF, what follows is a new line, so take note */
- if (c == '\n')
- ctx->linestart = 1;
- }
-
- return 1;
-}
-
-static long prefix_ctrl(BIO *b, int cmd, long num, void *ptr)
-{
- long ret = 0;
-
- switch (cmd) {
- case PREFIX_CTRL_SET_PREFIX:
- {
- PREFIX_CTX *ctx = BIO_get_data(b);
-
- if (ctx == NULL)
- break;
-
- OPENSSL_free(ctx->prefix);
- ctx->prefix = OPENSSL_strdup((const char *)ptr);
- ret = ctx->prefix != NULL;
- }
- break;
- default:
- if (BIO_next(b) != NULL)
- ret = BIO_ctrl(BIO_next(b), cmd, num, ptr);
- break;
- }
- return ret;
-}
-
-static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
-{
- return BIO_callback_ctrl(BIO_next(b), cmd, fp);
-}
-
-static int prefix_gets(BIO *b, char *buf, int size)
-{
- return BIO_gets(BIO_next(b), buf, size);
-}
-
-static int prefix_puts(BIO *b, const char *str)
-{
- return BIO_write(b, str, strlen(str));
-}
diff --git a/apps/build.info b/apps/build.info
index 01537361820e..020d129f8cac 100644
--- a/apps/build.info
+++ b/apps/build.info
@@ -1,79 +1,90 @@
-{- our @apps_openssl_src =
- qw(openssl.c
- asn1pars.c ca.c ciphers.c cms.c crl.c crl2p7.c dgst.c
- enc.c errstr.c
- genpkey.c nseq.c passwd.c pkcs7.c pkcs8.c
- pkey.c pkeyparam.c pkeyutl.c prime.c rand.c req.c
- s_client.c s_server.c s_time.c sess_id.c smime.c speed.c spkac.c
- verify.c version.c x509.c rehash.c storeutl.c);
- our @apps_lib_src =
- ( qw(apps.c opt.c s_cb.c s_socket.c app_rand.c bf_prefix.c),
- split(/\s+/, $target{apps_aux_src}) );
- our @apps_init_src = split(/\s+/, $target{apps_init_src});
- "" -}
+SUBDIRS=lib
-IF[{- !$disabled{apps} -}]
- LIBS_NO_INST=libapps.a
- SOURCE[libapps.a]={- join(" ", @apps_lib_src) -}
- INCLUDE[libapps.a]=.. ../include
+# Program init source, that don't have direct linkage with the rest of the
+# source, and can therefore not be part of a library.
+IF[{- !$disabled{uplink} -}]
+ $INITSRC=../ms/applink.c
+ENDIF
+IF[{- $config{target} =~ /^vms-/ -}]
+ $INITSRC=vms_decc_init.c
+ENDIF
- PROGRAMS=openssl
- SOURCE[openssl]={- join(" ", @apps_init_src) -}
- SOURCE[openssl]={- join(" ", @apps_openssl_src) -}
- INCLUDE[openssl]=.. ../include
- DEPEND[openssl]=libapps.a ../libssl
- IF[{- !$disabled{'des'} -}]
- SOURCE[openssl]=pkcs12.c
- DEPEND[pkcs12.o]=progs.h
- ENDIF
- IF[{- !$disabled{'ec'} -}]
- SOURCE[openssl]=ec.c ecparam.c
- DEPEND[ec.o]=progs.h
- DEPEND[ecparam.o]=progs.h
- ENDIF
- IF[{- !$disabled{'ocsp'} -}]
- SOURCE[openssl]=ocsp.c
- DEPEND[ocsp.o]=progs.h
- ENDIF
- IF[{- !$disabled{'srp'} -}]
- SOURCE[openssl]=srp.c
- DEPEND[srp.o]=progs.h
- ENDIF
- IF[{- !$disabled{'ts'} -}]
- SOURCE[openssl]=ts.c
- DEPEND[ts.o]=progs.h
- ENDIF
- IF[{- !$disabled{'dh'} -}]
- SOURCE[openssl]=dhparam.c
- DEPEND[dhparam.o]=progs.h
- ENDIF
- IF[{- !$disabled{'dsa'} -}]
- SOURCE[openssl]=dsa.c dsaparam.c gendsa.c
- DEPEND[dsa.o]=progs.h
- DEPEND[dsaparam.o]=progs.h
- DEPEND[gendsa.o]=progs.h
- ENDIF
- IF[{- !$disabled{'engine'} -}]
- SOURCE[openssl]=engine.c
- DEPEND[engine.o]=progs.h
- ENDIF
+# Source for the 'openssl' program
+$OPENSSLSRC=\
+ openssl.c \
+ asn1parse.c ca.c ciphers.c crl.c crl2pkcs7.c dgst.c \
+ enc.c errstr.c \
+ genpkey.c kdf.c mac.c nseq.c passwd.c pkcs7.c \
+ pkcs8.c pkey.c pkeyparam.c pkeyutl.c prime.c rand.c req.c \
+ s_client.c s_server.c s_time.c sess_id.c smime.c speed.c \
+ spkac.c verify.c version.c x509.c rehash.c storeutl.c \
+ list.c info.c fipsinstall.c pkcs12.c
+IF[{- !$disabled{'ec'} -}]
+ $OPENSSLSRC=$OPENSSLSRC ec.c ecparam.c
+ENDIF
+IF[{- !$disabled{'ocsp'} -}]
+ $OPENSSLSRC=$OPENSSLSRC ocsp.c
+ENDIF
+IF[{- !$disabled{'srp'} -}]
+ $OPENSSLSRC=$OPENSSLSRC srp.c
+ENDIF
+IF[{- !$disabled{'ts'} -}]
+ $OPENSSLSRC=$OPENSSLSRC ts.c
+ENDIF
+IF[{- !$disabled{'dh'} -}]
+$OPENSSLSRC=$OPENSSLSRC dhparam.c
+ENDIF
+IF[{- !$disabled{'dsa'} -}]
+$OPENSSLSRC=$OPENSSLSRC dsa.c dsaparam.c gendsa.c
+ENDIF
+IF[{- !$disabled{'engine'} -}]
+$OPENSSLSRC=$OPENSSLSRC engine.c
+ENDIF
+IF[{- !$disabled{'rsa'} -}]
+$OPENSSLSRC=$OPENSSLSRC rsa.c genrsa.c
+ENDIF
+IF[{- !$disabled{'deprecated-3.0'} -}]
IF[{- !$disabled{'rsa'} -}]
- SOURCE[openssl]=rsa.c rsautl.c genrsa.c
- DEPEND[rsa.o]=progs.h
- DEPEND[rsautl.o]=progs.h
- DEPEND[genrsa.o]=progs.h
+ $OPENSSLSRC=$OPENSSLSRC rsautl.c
ENDIF
- IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-)/ -}]
+ENDIF
+IF[{- !$disabled{'cms'} -}]
+ $OPENSSLSRC=$OPENSSLSRC cms.c
+ENDIF
+IF[{- !$disabled{'cmp'} -}]
+ $OPENSSLSRC=$OPENSSLSRC cmp.c lib/cmp_mock_srv.c
+ENDIF
+
+IF[{- !$disabled{apps} -}]
+ PROGRAMS=openssl
+ SOURCE[openssl]=$INITSRC $OPENSSLSRC
+ INCLUDE[openssl]=.. ../include include
+ DEPEND[openssl]=libapps.a ../libssl
+
+ # The nocheck attribute is picked up by progs.pl as a signal not to look
+ # at that file; some systems may have locked it as the output file, and
+ # therefore don't allow it to be read at the same time, making progs.pl
+ # fail.
+ SOURCE[openssl]{nocheck}=progs.c
+ DEPEND[${OPENSSLSRC/.c/.o} progs.o]=progs.h
+ GENERATE[progs.c]=progs.pl "-C" $(APPS_OPENSSL)
+ GENERATE[progs.h]=progs.pl "-H" $(APPS_OPENSSL)
+ # progs.pl tries to read all 'openssl' sources, including progs.c, so we make
+ # sure things are generated in the correct order.
+ DEPEND[progs.h]=progs.c
+ # Because the files to look through may change (depends on $OPENSSLSRC),
+ # always depend on a changed configuration.
+ DEPEND[progs.c]=../configdata.pm
+
+ IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}]
GENERATE[openssl.rc]=../util/mkrc.pl openssl
SOURCE[openssl]=openssl.rc
ENDIF
- {- join("\n ", map { (my $x = $_) =~ s|\.c$|.o|; "DEPEND[$x]=progs.h" }
- @apps_openssl_src) -}
- GENERATE[progs.h]=progs.pl $(APPS_OPENSSL)
- DEPEND[progs.h]=../configdata.pm
-
- SCRIPTS=CA.pl tsget.pl
+ SCRIPTS{misc}=CA.pl
SOURCE[CA.pl]=CA.pl.in
+ # linkname tells build files that a symbolic link or copy of this script
+ # without extension must be installed as well. Unix or Unix lookalike only.
+ SCRIPTS{misc,linkname=tsget}=tsget.pl
SOURCE[tsget.pl]=tsget.in
ENDIF
diff --git a/apps/ca.c b/apps/ca.c
index ea375ca0b1d3..e14a5cff7802 100755..100644
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -26,7 +26,7 @@
#ifndef W_OK
# ifdef OPENSSL_SYS_VMS
# include <unistd.h>
-# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS)
+# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_TANDEM)
# include <sys/file.h>
# endif
#endif
@@ -88,40 +88,46 @@ typedef enum {
static char *lookup_conf(const CONF *conf, const char *group, const char *tag);
-static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
- const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+static int certify(X509 **xret, const char *infile, int informat,
+ EVP_PKEY *pkey, X509 *x509,
+ const char *dgst,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(OPENSSL_STRING) *vfyopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
BIGNUM *serial, const char *subj, unsigned long chtype,
int multirdn, int email_dn, const char *startdate,
const char *enddate,
long days, int batch, const char *ext_sect, CONF *conf,
int verbose, unsigned long certopt, unsigned long nameopt,
- int default_op, int ext_copy, int selfsign);
-static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
- const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+ int default_op, int ext_copy, int selfsign, unsigned long dateopt);
+static int certify_cert(X509 **xret, const char *infile, int certformat,
+ const char *passin, EVP_PKEY *pkey, X509 *x509,
+ const char *dgst,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(OPENSSL_STRING) *vfyopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
BIGNUM *serial, const char *subj, unsigned long chtype,
int multirdn, int email_dn, const char *startdate,
const char *enddate, long days, int batch, const char *ext_sect,
CONF *conf, int verbose, unsigned long certopt,
- unsigned long nameopt, int default_op, int ext_copy);
+ unsigned long nameopt, int default_op, int ext_copy, unsigned long dateopt);
static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey,
- X509 *x509, const EVP_MD *dgst,
+ X509 *x509, const char *dgst,
STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
BIGNUM *serial, const char *subj, unsigned long chtype,
int multirdn, int email_dn, const char *startdate,
const char *enddate, long days, const char *ext_sect, CONF *conf,
int verbose, unsigned long certopt,
- unsigned long nameopt, int default_op, int ext_copy);
+ unsigned long nameopt, int default_op, int ext_copy, unsigned long dateopt);
static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
- const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+ const char *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,
const char *subj, unsigned long chtype, int multirdn,
int email_dn, const char *startdate, const char *enddate, long days,
int batch, int verbose, X509_REQ *req, const char *ext_sect,
CONF *conf, unsigned long certopt, unsigned long nameopt,
- int default_op, int ext_copy, int selfsign);
+ int default_op, int ext_copy, int selfsign, unsigned long dateopt);
static int get_certificate_status(const char *ser_status, CA_DB *db);
static int do_updatedb(CA_DB *db);
static int check_time_format(const char *str);
@@ -132,77 +138,97 @@ static int make_revoked(X509_REVOKED *rev, const char *str);
static int old_entry_print(const ASN1_OBJECT *obj, const ASN1_STRING *str);
static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
-static CONF *extconf = NULL;
+static CONF *extfile_conf = NULL;
static int preserve = 0;
static int msie_hack = 0;
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_ENGINE, OPT_VERBOSE, OPT_CONFIG, OPT_NAME, OPT_SUBJ, OPT_UTF8,
OPT_CREATE_SERIAL, OPT_MULTIVALUE_RDN, OPT_STARTDATE, OPT_ENDDATE,
OPT_DAYS, OPT_MD, OPT_POLICY, OPT_KEYFILE, OPT_KEYFORM, OPT_PASSIN,
- OPT_KEY, OPT_CERT, OPT_SELFSIGN, OPT_IN, OPT_OUT, OPT_OUTDIR,
+ OPT_KEY, OPT_CERT, OPT_CERTFORM, OPT_SELFSIGN,
+ OPT_IN, OPT_INFORM, OPT_OUT, OPT_DATEOPT, OPT_OUTDIR, OPT_VFYOPT,
OPT_SIGOPT, OPT_NOTEXT, OPT_BATCH, OPT_PRESERVEDN, OPT_NOEMAILDN,
- OPT_GENCRL, OPT_MSIE_HACK, OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC,
+ OPT_GENCRL, OPT_MSIE_HACK, OPT_CRL_LASTUPDATE, OPT_CRL_NEXTUPDATE,
+ OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC,
OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID,
OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS,
OPT_RAND_SERIAL,
- OPT_R_ENUM,
+ OPT_R_ENUM, OPT_PROV_ENUM,
/* Do not change the order here; see related case statements below */
OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, OPT_CRL_CA_COMPROMISE
} OPTION_CHOICE;
const OPTIONS ca_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [certreq...]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"verbose", OPT_VERBOSE, '-', "Verbose output during processing"},
+ {"outdir", OPT_OUTDIR, '/', "Where to put output cert"},
+ {"in", OPT_IN, '<', "The input cert request(s)"},
+ {"inform", OPT_INFORM, 'F', "CSR input format (DER or PEM); default PEM"},
+ {"infiles", OPT_INFILES, '-', "The last argument, requests to process"},
+ {"out", OPT_OUT, '>', "Where to put the output file(s)"},
+ {"dateopt", OPT_DATEOPT, 's', "Datetime format used for printing. (rfc_822/iso_8601). Default is rfc_822."},
+ {"notext", OPT_NOTEXT, '-', "Do not print the generated certificate"},
+ {"batch", OPT_BATCH, '-', "Don't ask questions"},
+ {"msie_hack", OPT_MSIE_HACK, '-',
+ "msie modifications to handle all Universal Strings"},
+ {"ss_cert", OPT_SS_CERT, '<', "File contains a self signed cert to sign"},
+ {"spkac", OPT_SPKAC, '<',
+ "File contains DN and signed public key and challenge"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Configuration"),
{"config", OPT_CONFIG, 's', "A config file"},
{"name", OPT_NAME, 's', "The particular CA definition to use"},
+ {"section", OPT_NAME, 's', "An alias for -name"},
+ {"policy", OPT_POLICY, 's', "The CA 'policy' to support"},
+
+ OPT_SECTION("Certificate"),
{"subj", OPT_SUBJ, 's', "Use arg instead of request's subject"},
- {"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"},
+ {"utf8", OPT_UTF8, '-', "Input characters are UTF8; default ASCII"},
{"create_serial", OPT_CREATE_SERIAL, '-',
"If reading serial fails, create a new random serial"},
{"rand_serial", OPT_RAND_SERIAL, '-',
"Always create a random serial; do not store it"},
{"multivalue-rdn", OPT_MULTIVALUE_RDN, '-',
- "Enable support for multivalued RDNs"},
+ "Deprecated; multi-valued RDNs support is always on."},
{"startdate", OPT_STARTDATE, 's', "Cert notBefore, YYMMDDHHMMSSZ"},
{"enddate", OPT_ENDDATE, 's',
"YYMMDDHHMMSSZ cert notAfter (overrides -days)"},
{"days", OPT_DAYS, 'p', "Number of days to certify the cert for"},
- {"md", OPT_MD, 's', "md to use; one of md2, md5, sha or sha1"},
- {"policy", OPT_POLICY, 's', "The CA 'policy' to support"},
- {"keyfile", OPT_KEYFILE, 's', "Private key"},
- {"keyform", OPT_KEYFORM, 'f', "Private key file format (PEM or ENGINE)"},
- {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
- {"key", OPT_KEY, 's', "Key to decode the private key if it is encrypted"},
+ {"extensions", OPT_EXTENSIONS, 's',
+ "Extension section (override value in config file)"},
+ {"extfile", OPT_EXTFILE, '<',
+ "Configuration file with X509v3 extensions to add"},
+ {"preserveDN", OPT_PRESERVEDN, '-', "Don't re-order the DN"},
+ {"noemailDN", OPT_NOEMAILDN, '-', "Don't add the EMAIL field to the DN"},
+
+ OPT_SECTION("Signing"),
+ {"md", OPT_MD, 's', "Digest to use, such as sha256"},
+ {"keyfile", OPT_KEYFILE, 's', "The CA private key"},
+ {"keyform", OPT_KEYFORM, 'f',
+ "Private key file format (ENGINE, other values ignored)"},
+ {"passin", OPT_PASSIN, 's', "Key and cert input file pass phrase source"},
+ {"key", OPT_KEY, 's',
+ "Key to decrypt the private key or cert files if encrypted. Better use -passin"},
{"cert", OPT_CERT, '<', "The CA cert"},
+ {"certform", OPT_CERTFORM, 'F',
+ "Certificate input format (DER/PEM/P12); has no effect"},
{"selfsign", OPT_SELFSIGN, '-',
"Sign a cert with the key associated with it"},
- {"in", OPT_IN, '<', "The input PEM encoded cert request(s)"},
- {"out", OPT_OUT, '>', "Where to put the output file(s)"},
- {"outdir", OPT_OUTDIR, '/', "Where to put output cert"},
{"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
- {"notext", OPT_NOTEXT, '-', "Do not print the generated certificate"},
- {"batch", OPT_BATCH, '-', "Don't ask questions"},
- {"preserveDN", OPT_PRESERVEDN, '-', "Don't re-order the DN"},
- {"noemailDN", OPT_NOEMAILDN, '-', "Don't add the EMAIL field to the DN"},
+ {"vfyopt", OPT_VFYOPT, 's', "Verification parameter in n:v form"},
+
+ OPT_SECTION("Revocation"),
{"gencrl", OPT_GENCRL, '-', "Generate a new CRL"},
- {"msie_hack", OPT_MSIE_HACK, '-',
- "msie modifications to handle all those universal strings"},
- {"crldays", OPT_CRLDAYS, 'p', "Days until the next CRL is due"},
- {"crlhours", OPT_CRLHOURS, 'p', "Hours until the next CRL is due"},
- {"crlsec", OPT_CRLSEC, 'p', "Seconds until the next CRL is due"},
- {"infiles", OPT_INFILES, '-', "The last argument, requests to process"},
- {"ss_cert", OPT_SS_CERT, '<', "File contains a self signed cert to sign"},
- {"spkac", OPT_SPKAC, '<',
- "File contains DN and signed public key and challenge"},
- {"revoke", OPT_REVOKE, '<', "Revoke a cert (given in file)"},
{"valid", OPT_VALID, 's',
"Add a Valid(not-revoked) DB entry about a cert (given in file)"},
- {"extensions", OPT_EXTENSIONS, 's',
- "Extension section (override value in config file)"},
- {"extfile", OPT_EXTFILE, '<',
- "Configuration file with X509v3 extensions to add"},
{"status", OPT_STATUS, 's', "Shows cert status given the serial number"},
{"updatedb", OPT_UPDATEDB, '-', "Updates db for expired cert"},
{"crlexts", OPT_CRLEXTS, 's',
@@ -214,10 +240,20 @@ const OPTIONS ca_options[] = {
"sets compromise time to val and the revocation reason to keyCompromise"},
{"crl_CA_compromise", OPT_CRL_CA_COMPROMISE, 's',
"sets compromise time to val and the revocation reason to CACompromise"},
+ {"crl_lastupdate", OPT_CRL_LASTUPDATE, 's',
+ "Sets the CRL lastUpdate time to val (YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ)"},
+ {"crl_nextupdate", OPT_CRL_NEXTUPDATE, 's',
+ "Sets the CRL nextUpdate time to val (YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ)"},
+ {"crldays", OPT_CRLDAYS, 'p', "Days until the next CRL is due"},
+ {"crlhours", OPT_CRLHOURS, 'p', "Hours until the next CRL is due"},
+ {"crlsec", OPT_CRLSEC, 'p', "Seconds until the next CRL is due"},
+ {"revoke", OPT_REVOKE, '<', "Revoke a cert (given in file)"},
+
OPT_R_OPTIONS,
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"certreq", 0, 0, "Certificate requests to be signed (optional)"},
{NULL}
};
@@ -229,19 +265,21 @@ int ca_main(int argc, char **argv)
EVP_PKEY *pkey = NULL;
BIO *in = NULL, *out = NULL, *Sout = NULL;
ASN1_INTEGER *tmpser;
- ASN1_TIME *tmptm;
CA_DB *db = NULL;
DB_ATTR db_attr;
STACK_OF(CONF_VALUE) *attribs = NULL;
- STACK_OF(OPENSSL_STRING) *sigopts = NULL;
+ STACK_OF(OPENSSL_STRING) *sigopts = NULL, *vfyopts = NULL;
STACK_OF(X509) *cert_sk = NULL;
X509_CRL *crl = NULL;
- const EVP_MD *dgst = NULL;
char *configfile = default_config_file, *section = NULL;
- char *md = NULL, *policy = NULL, *keyfile = NULL;
- char *certfile = NULL, *crl_ext = NULL, *crlnumberfile = NULL, *key = NULL;
+ char def_dgst[80] = "";
+ char *dgst = NULL, *policy = NULL, *keyfile = NULL;
+ char *certfile = NULL, *crl_ext = NULL, *crlnumberfile = NULL;
+ int certformat = FORMAT_UNDEF, informat = FORMAT_UNDEF;
+ unsigned long dateopt = ASN1_DTFLGS_RFC822;
const char *infile = NULL, *spkac_file = NULL, *ss_cert_file = NULL;
const char *extensions = NULL, *extfile = NULL, *passinarg = NULL;
+ char *passin = NULL;
char *outdir = NULL, *outfile = NULL, *rev_arg = NULL, *ser_status = NULL;
const char *serialfile = NULL, *subj = NULL;
char *prog, *startdate = NULL, *enddate = NULL;
@@ -251,11 +289,12 @@ int ca_main(int argc, char **argv)
char *const *pp;
const char *p;
size_t outdirlen = 0;
- int create_ser = 0, free_key = 0, total = 0, total_done = 0;
+ int create_ser = 0, free_passin = 0, total = 0, total_done = 0;
int batch = 0, default_op = 1, doupdatedb = 0, ext_copy = EXT_COPY_NONE;
- int keyformat = FORMAT_PEM, multirdn = 0, notext = 0, output_der = 0;
+ int keyformat = FORMAT_UNDEF, multirdn = 1, notext = 0, output_der = 0;
int ret = 1, email_dn = 1, req = 0, verbose = 0, gencrl = 0, dorevoke = 0;
- int rand_ser = 0, i, j, selfsign = 0, def_nid, def_ret;
+ int rand_ser = 0, i, j, selfsign = 0, def_ret;
+ char *crl_lastupdate = NULL, *crl_nextupdate = NULL;
long crldays = 0, crlhours = 0, crlsec = 0, days = 0;
unsigned long chtype = MBSTRING_ASC, certopt = 0;
X509 *x509 = NULL, *x509p = NULL, *x = NULL;
@@ -279,9 +318,17 @@ opthelp:
req = 1;
infile = opt_arg();
break;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
+ goto opthelp;
+ break;
case OPT_OUT:
outfile = opt_arg();
break;
+ case OPT_DATEOPT:
+ if (!set_dateopt(&dateopt, opt_arg()))
+ goto opthelp;
+ break;
case OPT_VERBOSE:
verbose = 1;
break;
@@ -305,7 +352,7 @@ opthelp:
create_ser = 1;
break;
case OPT_MULTIVALUE_RDN:
- multirdn = 1;
+ /* obsolete */
break;
case OPT_STARTDATE:
startdate = opt_arg();
@@ -317,7 +364,7 @@ opthelp:
days = atoi(opt_arg());
break;
case OPT_MD:
- md = opt_arg();
+ dgst = opt_arg();
break;
case OPT_POLICY:
policy = opt_arg();
@@ -336,12 +383,20 @@ opthelp:
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_KEY:
- key = opt_arg();
+ passin = opt_arg();
break;
case OPT_CERT:
certfile = opt_arg();
break;
+ case OPT_CERTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &certformat))
+ goto opthelp;
+ break;
case OPT_SELFSIGN:
selfsign = 1;
break;
@@ -354,6 +409,12 @@ opthelp:
if (sigopts == NULL || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
goto end;
break;
+ case OPT_VFYOPT:
+ if (vfyopts == NULL)
+ vfyopts = sk_OPENSSL_STRING_new_null();
+ if (vfyopts == NULL || !sk_OPENSSL_STRING_push(vfyopts, opt_arg()))
+ goto end;
+ break;
case OPT_NOTEXT:
notext = 1;
break;
@@ -372,6 +433,12 @@ opthelp:
case OPT_MSIE_HACK:
msie_hack = 1;
break;
+ case OPT_CRL_LASTUPDATE:
+ crl_lastupdate = opt_arg();
+ break;
+ case OPT_CRL_NEXTUPDATE:
+ crl_nextupdate = opt_arg();
+ break;
case OPT_CRLDAYS:
crldays = atol(opt_arg());
break;
@@ -427,13 +494,13 @@ opthelp:
break;
}
}
+
end_of_options:
+ /* Remaining args are files to certify. */
argc = opt_num_rest();
argv = opt_rest();
- BIO_printf(bio_err, "Using configuration from %s\n", configfile);
-
- if ((conf = app_load_config(configfile)) == NULL)
+ if ((conf = app_load_config_verbose(configfile, 1)) == NULL)
goto end;
if (configfile != default_config_file && !app_load_modules(conf))
goto end;
@@ -456,12 +523,12 @@ end_of_options:
BIO_free(oid_bio);
}
}
- if (!add_oid_section(conf)) {
- ERR_print_errors(bio_err);
+ if (!add_oid_section(conf))
goto end;
- }
app_RAND_load_conf(conf, BASE_SECTION);
+ if (!app_RAND_load())
+ goto end;
f = NCONF_get_string(conf, section, STRING_MASK);
if (f == NULL)
@@ -495,8 +562,10 @@ end_of_options:
goto end;
db = load_index(dbfile, &db_attr);
- if (db == NULL)
+ if (db == NULL) {
+ BIO_printf(bio_err, "Problem with index file: %s (could not load/parse file)\n", dbfile);
goto end;
+ }
if (index_index(db) <= 0)
goto end;
@@ -513,16 +582,15 @@ end_of_options:
&& (keyfile = lookup_conf(conf, section, ENV_PRIVATE_KEY)) == NULL)
goto end;
- if (key == NULL) {
- free_key = 1;
- if (!app_passwd(passinarg, NULL, &key, NULL)) {
+ if (passin == NULL) {
+ free_passin = 1;
+ if (!app_passwd(passinarg, NULL, &passin, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
}
- pkey = load_key(keyfile, keyformat, 0, key, e, "CA private key");
- if (key != NULL)
- OPENSSL_cleanse(key, strlen(key));
+ pkey = load_key(keyfile, keyformat, 0, passin, e, "CA private key");
+ cleanse(passin);
if (pkey == NULL)
/* load_key() has already printed an appropriate message */
goto end;
@@ -534,7 +602,7 @@ end_of_options:
&& (certfile = lookup_conf(conf, section, ENV_CERTIFICATE)) == NULL)
goto end;
- x509 = load_cert(certfile, FORMAT_PEM, "CA certificate");
+ x509 = load_cert_pass(certfile, certformat, 1, passin, "CA certificate");
if (x509 == NULL)
goto end;
@@ -624,8 +692,10 @@ end_of_options:
goto end;
db = load_index(dbfile, &db_attr);
- if (db == NULL)
+ if (db == NULL) {
+ BIO_printf(bio_err, "Problem with index file: %s (could not load/parse file)\n", dbfile);
goto end;
+ }
/* Lets check some fields */
for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
@@ -703,7 +773,7 @@ end_of_options:
/*****************************************************************/
/* Read extensions config file */
if (extfile) {
- if ((extconf = app_load_config(extfile)) == NULL) {
+ if ((extfile_conf = app_load_config(extfile)) == NULL) {
ret = 1;
goto end;
}
@@ -714,7 +784,7 @@ end_of_options:
/* We can have sections in the ext file */
if (extensions == NULL) {
- extensions = NCONF_get_string(extconf, "default", "extensions");
+ extensions = NCONF_get_string(extfile_conf, "default", "extensions");
if (extensions == NULL)
extensions = "default";
}
@@ -728,28 +798,25 @@ end_of_options:
}
}
- def_ret = EVP_PKEY_get_default_digest_nid(pkey, &def_nid);
+ def_ret = EVP_PKEY_get_default_digest_name(pkey, def_dgst, sizeof(def_dgst));
/*
- * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is
+ * EVP_PKEY_get_default_digest_name() returns 2 if the digest is
* mandatory for this algorithm.
*/
- if (def_ret == 2 && def_nid == NID_undef) {
+ if (def_ret == 2 && strcmp(def_dgst, "UNDEF") == 0) {
/* The signing algorithm requires there to be no digest */
- dgst = EVP_md_null();
- } else if (md == NULL
- && (md = lookup_conf(conf, section, ENV_DEFAULT_MD)) == NULL) {
+ dgst = NULL;
+ } else if (dgst == NULL
+ && (dgst = lookup_conf(conf, section, ENV_DEFAULT_MD)) == NULL) {
goto end;
} else {
- if (strcmp(md, "default") == 0) {
+ if (strcmp(dgst, "default") == 0) {
if (def_ret <= 0) {
BIO_puts(bio_err, "no default digest\n");
goto end;
}
- md = (char *)OBJ_nid2sn(def_nid);
+ dgst = def_dgst;
}
-
- if (!opt_md(md, &dgst))
- goto end;
}
if (req) {
@@ -761,8 +828,7 @@ end_of_options:
email_dn = 0;
}
if (verbose)
- BIO_printf(bio_err, "message digest is %s\n",
- OBJ_nid2ln(EVP_MD_type(dgst)));
+ BIO_printf(bio_err, "message digest is %s\n", dgst);
if (policy == NULL
&& (policy = lookup_conf(conf, section, ENV_POLICY)) == NULL)
goto end;
@@ -778,7 +844,20 @@ end_of_options:
goto end;
}
- if (extconf == NULL) {
+ if (extfile_conf != NULL) {
+ /* Check syntax of extfile */
+ X509V3_CTX ctx;
+
+ X509V3_set_ctx_test(&ctx);
+ X509V3_set_nconf(&ctx, extfile_conf);
+ if (!X509V3_EXT_add_nconf(extfile_conf, &ctx, extensions, NULL)) {
+ BIO_printf(bio_err,
+ "Error checking certificate extensions from extfile section %s\n",
+ extensions);
+ ret = 1;
+ goto end;
+ }
+ } else {
/*
* no '-extfile' option, so we look for extensions in the main
* configuration file
@@ -789,13 +868,14 @@ end_of_options:
ERR_clear_error();
}
if (extensions != NULL) {
- /* Check syntax of file */
+ /* Check syntax of config file section */
X509V3_CTX ctx;
+
X509V3_set_ctx_test(&ctx);
X509V3_set_nconf(&ctx, conf);
if (!X509V3_EXT_add_nconf(conf, &ctx, extensions, NULL)) {
BIO_printf(bio_err,
- "Error Loading extension section %s\n",
+ "Error checking certificate extension config section %s\n",
extensions);
ret = 1;
goto end;
@@ -874,7 +954,7 @@ end_of_options:
attribs, db, serial, subj, chtype, multirdn,
email_dn, startdate, enddate, days, extensions,
conf, verbose, certopt, get_nameopt(), default_op,
- ext_copy);
+ ext_copy, dateopt);
if (j < 0)
goto end;
if (j > 0) {
@@ -890,12 +970,12 @@ end_of_options:
}
if (ss_cert_file != NULL) {
total++;
- j = certify_cert(&x, ss_cert_file, pkey, x509, dgst, sigopts,
- attribs,
+ j = certify_cert(&x, ss_cert_file, certformat, passin, pkey,
+ x509, dgst, sigopts, vfyopts, attribs,
db, serial, subj, chtype, multirdn, email_dn,
startdate, enddate, days, batch, extensions,
conf, verbose, certopt, get_nameopt(), default_op,
- ext_copy);
+ ext_copy, dateopt);
if (j < 0)
goto end;
if (j > 0) {
@@ -911,10 +991,11 @@ end_of_options:
}
if (infile != NULL) {
total++;
- j = certify(&x, infile, pkey, x509p, dgst, sigopts, attribs, db,
+ j = certify(&x, infile, informat, pkey, x509p, dgst,
+ sigopts, vfyopts, attribs, db,
serial, subj, chtype, multirdn, email_dn, startdate,
enddate, days, batch, extensions, conf, verbose,
- certopt, get_nameopt(), default_op, ext_copy, selfsign);
+ certopt, get_nameopt(), default_op, ext_copy, selfsign, dateopt);
if (j < 0)
goto end;
if (j > 0) {
@@ -930,10 +1011,12 @@ end_of_options:
}
for (i = 0; i < argc; i++) {
total++;
- j = certify(&x, argv[i], pkey, x509p, dgst, sigopts, attribs, db,
+ j = certify(&x, argv[i], informat, pkey, x509p, dgst,
+ sigopts, vfyopts,
+ attribs, db,
serial, subj, chtype, multirdn, email_dn, startdate,
enddate, days, batch, extensions, conf, verbose,
- certopt, get_nameopt(), default_op, ext_copy, selfsign);
+ certopt, get_nameopt(), default_op, ext_copy, selfsign, dateopt);
if (j < 0)
goto end;
if (j > 0) {
@@ -996,7 +1079,7 @@ end_of_options:
for (i = 0; i < sk_X509_num(cert_sk); i++) {
BIO *Cout = NULL;
X509 *xi = sk_X509_value(cert_sk, i);
- ASN1_INTEGER *serialNumber = X509_get_serialNumber(xi);
+ const ASN1_INTEGER *serialNumber = X509_get0_serialNumber(xi);
const unsigned char *psn = ASN1_STRING_get0_data(serialNumber);
const int snl = ASN1_STRING_length(serialNumber);
const int filen_len = 2 * (snl > 0 ? snl : 1) + sizeof(".pem");
@@ -1067,11 +1150,12 @@ end_of_options:
if (crl_ext != NULL) {
/* Check syntax of file */
X509V3_CTX ctx;
+
X509V3_set_ctx_test(&ctx);
X509V3_set_nconf(&ctx, conf);
if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL)) {
BIO_printf(bio_err,
- "Error Loading CRL extension section %s\n", crl_ext);
+ "Error checking CRL extension section %s\n", crl_ext);
ret = 1;
goto end;
}
@@ -1094,7 +1178,8 @@ end_of_options:
crlhours = 0;
ERR_clear_error();
}
- if ((crldays == 0) && (crlhours == 0) && (crlsec == 0)) {
+ if ((crl_nextupdate == NULL) &&
+ (crldays == 0) && (crlhours == 0) && (crlsec == 0)) {
BIO_printf(bio_err,
"cannot lookup how long until the next CRL is issued\n");
goto end;
@@ -1102,24 +1187,23 @@ end_of_options:
if (verbose)
BIO_printf(bio_err, "making CRL\n");
- if ((crl = X509_CRL_new()) == NULL)
+ if ((crl = X509_CRL_new_ex(app_get0_libctx(), app_get0_propq())) == NULL)
goto end;
if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509)))
goto end;
- tmptm = ASN1_TIME_new();
- if (tmptm == NULL
- || X509_gmtime_adj(tmptm, 0) == NULL
- || !X509_CRL_set1_lastUpdate(crl, tmptm)
- || X509_time_adj_ex(tmptm, crldays, crlhours * 60 * 60 + crlsec,
- NULL) == NULL) {
- BIO_puts(bio_err, "error setting CRL nextUpdate\n");
- ASN1_TIME_free(tmptm);
+ if (!set_crl_lastupdate(crl, crl_lastupdate)) {
+ BIO_puts(bio_err, "error setting CRL lastUpdate\n");
+ ret = 1;
goto end;
}
- X509_CRL_set1_nextUpdate(crl, tmptm);
- ASN1_TIME_free(tmptm);
+ if (!set_crl_nextupdate(crl, crl_nextupdate,
+ crldays, crlhours, crlsec)) {
+ BIO_puts(bio_err, "error setting CRL nextUpdate\n");
+ ret = 1;
+ goto end;
+ }
for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
@@ -1157,12 +1241,16 @@ end_of_options:
if (crl_ext != NULL || crlnumberfile != NULL) {
X509V3_CTX crlctx;
+
X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
X509V3_set_nconf(&crlctx, conf);
if (crl_ext != NULL)
- if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl))
+ if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl)) {
+ BIO_printf(bio_err,
+ "Error adding CRL extensions from section %s\n", crl_ext);
goto end;
+ }
if (crlnumberfile != NULL) {
tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL);
if (!tmpser)
@@ -1175,8 +1263,8 @@ end_of_options:
}
}
if (crl_ext != NULL || crl_v2) {
- if (!X509_CRL_set_version(crl, 1))
- goto end; /* version 2 CRL */
+ if (!X509_CRL_set_version(crl, X509_CRL_VERSION_2))
+ goto end;
}
/* we have a CRL number that need updating */
@@ -1210,7 +1298,9 @@ end_of_options:
goto end;
} else {
X509 *revcert;
- revcert = load_cert(infile, FORMAT_PEM, infile);
+
+ revcert = load_cert_pass(infile, informat, 1, passin,
+ "certificate to be revoked");
if (revcert == NULL)
goto end;
if (dorevoke == 2)
@@ -1239,17 +1329,19 @@ end_of_options:
BIO_free_all(in);
sk_X509_pop_free(cert_sk, X509_free);
- if (free_key)
- OPENSSL_free(key);
+ cleanse(passin);
+ if (free_passin)
+ OPENSSL_free(passin);
BN_free(serial);
BN_free(crlnumber);
free_index(db);
sk_OPENSSL_STRING_free(sigopts);
+ sk_OPENSSL_STRING_free(vfyopts);
EVP_PKEY_free(pkey);
X509_free(x509);
X509_CRL_free(crl);
NCONF_free(conf);
- NCONF_free(extconf);
+ NCONF_free(extfile_conf);
release_engine(e);
return ret;
}
@@ -1262,101 +1354,94 @@ static char *lookup_conf(const CONF *conf, const char *section, const char *tag)
return entry;
}
-static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
- const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+static int certify(X509 **xret, const char *infile, int informat,
+ EVP_PKEY *pkey, X509 *x509,
+ const char *dgst,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(OPENSSL_STRING) *vfyopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
BIGNUM *serial, const char *subj, unsigned long chtype,
int multirdn, int email_dn, const char *startdate,
const char *enddate,
long days, int batch, const char *ext_sect, CONF *lconf,
int verbose, unsigned long certopt, unsigned long nameopt,
- int default_op, int ext_copy, int selfsign)
+ int default_op, int ext_copy, int selfsign, unsigned long dateopt)
{
X509_REQ *req = NULL;
- BIO *in = NULL;
EVP_PKEY *pktmp = NULL;
int ok = -1, i;
- in = BIO_new_file(infile, "r");
- if (in == NULL) {
- ERR_print_errors(bio_err);
+ req = load_csr(infile, informat, "certificate request");
+ if (req == NULL)
goto end;
- }
- if ((req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL)) == NULL) {
- BIO_printf(bio_err, "Error reading certificate request in %s\n",
- infile);
+ if ((pktmp = X509_REQ_get0_pubkey(req)) == NULL) {
+ BIO_printf(bio_err, "Error unpacking public key\n");
goto end;
}
if (verbose)
X509_REQ_print_ex(bio_err, req, nameopt, X509_FLAG_COMPAT);
BIO_printf(bio_err, "Check that the request matches the signature\n");
+ ok = 0;
if (selfsign && !X509_REQ_check_private_key(req, pkey)) {
BIO_printf(bio_err,
"Certificate request and CA private key do not match\n");
- ok = 0;
- goto end;
- }
- if ((pktmp = X509_REQ_get0_pubkey(req)) == NULL) {
- BIO_printf(bio_err, "error unpacking public key\n");
goto end;
}
- i = X509_REQ_verify(req, pktmp);
- pktmp = NULL;
+ i = do_X509_REQ_verify(req, pktmp, vfyopts);
if (i < 0) {
- ok = 0;
- BIO_printf(bio_err, "Signature verification problems....\n");
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Signature verification problems...\n");
goto end;
}
if (i == 0) {
- ok = 0;
BIO_printf(bio_err,
"Signature did not match the certificate request\n");
- ERR_print_errors(bio_err);
goto end;
- } else {
- BIO_printf(bio_err, "Signature ok\n");
}
+ BIO_printf(bio_err, "Signature ok\n");
ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
chtype, multirdn, email_dn, startdate, enddate, days, batch,
verbose, req, ext_sect, lconf, certopt, nameopt, default_op,
- ext_copy, selfsign);
+ ext_copy, selfsign, dateopt);
end:
+ ERR_print_errors(bio_err);
X509_REQ_free(req);
- BIO_free(in);
return ok;
}
-static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
- const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+static int certify_cert(X509 **xret, const char *infile, int certformat,
+ const char *passin, EVP_PKEY *pkey, X509 *x509,
+ const char *dgst,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(OPENSSL_STRING) *vfyopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
BIGNUM *serial, const char *subj, unsigned long chtype,
int multirdn, int email_dn, const char *startdate,
const char *enddate, long days, int batch, const char *ext_sect,
CONF *lconf, int verbose, unsigned long certopt,
- unsigned long nameopt, int default_op, int ext_copy)
+ unsigned long nameopt, int default_op, int ext_copy, unsigned long dateopt)
{
- X509 *req = NULL;
+ X509 *template_cert = NULL;
X509_REQ *rreq = NULL;
EVP_PKEY *pktmp = NULL;
int ok = -1, i;
- if ((req = load_cert(infile, FORMAT_PEM, infile)) == NULL)
+ if ((template_cert = load_cert_pass(infile, certformat, 1, passin,
+ "template certificate")) == NULL)
goto end;
if (verbose)
- X509_print(bio_err, req);
+ X509_print(bio_err, template_cert);
BIO_printf(bio_err, "Check that the request matches the signature\n");
- if ((pktmp = X509_get0_pubkey(req)) == NULL) {
+ if ((pktmp = X509_get0_pubkey(template_cert)) == NULL) {
BIO_printf(bio_err, "error unpacking public key\n");
goto end;
}
- i = X509_verify(req, pktmp);
+ i = do_X509_verify(template_cert, pktmp, vfyopts);
if (i < 0) {
ok = 0;
BIO_printf(bio_err, "Signature verification problems....\n");
@@ -1370,30 +1455,31 @@ static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x
BIO_printf(bio_err, "Signature ok\n");
}
- if ((rreq = X509_to_X509_REQ(req, NULL, NULL)) == NULL)
+ if ((rreq = X509_to_X509_REQ(template_cert, NULL, NULL)) == NULL)
goto end;
ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
chtype, multirdn, email_dn, startdate, enddate, days, batch,
verbose, rreq, ext_sect, lconf, certopt, nameopt, default_op,
- ext_copy, 0);
+ ext_copy, 0, dateopt);
end:
X509_REQ_free(rreq);
- X509_free(req);
+ X509_free(template_cert);
return ok;
}
static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
- const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+ const char *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,
const char *subj, unsigned long chtype, int multirdn,
int email_dn, const char *startdate, const char *enddate, long days,
int batch, int verbose, X509_REQ *req, const char *ext_sect,
CONF *lconf, unsigned long certopt, unsigned long nameopt,
- int default_op, int ext_copy, int selfsign)
+ int default_op, int ext_copy, int selfsign, unsigned long dateopt)
{
- X509_NAME *name = NULL, *CAname = NULL, *subject = NULL;
+ const X509_NAME *name = NULL;
+ X509_NAME *CAname = NULL, *subject = NULL;
const ASN1_TIME *tm;
ASN1_STRING *str, *str2;
ASN1_OBJECT *obj;
@@ -1407,17 +1493,16 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
OPENSSL_STRING *irow = NULL;
OPENSSL_STRING *rrow = NULL;
char buf[25];
+ X509V3_CTX ext_ctx;
for (i = 0; i < DB_NUMBER; i++)
row[i] = NULL;
if (subj) {
- X509_NAME *n = parse_name(subj, chtype, multirdn);
+ X509_NAME *n = parse_name(subj, chtype, multirdn, "subject");
- if (!n) {
- ERR_print_errors(bio_err);
+ if (!n)
goto end;
- }
X509_REQ_set_subject_name(req, n);
X509_NAME_free(n);
}
@@ -1592,15 +1677,9 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
BIO_printf(bio_err,
"Everything appears to be ok, creating and signing the certificate\n");
- if ((ret = X509_new()) == NULL)
+ if ((ret = X509_new_ex(app_get0_libctx(), app_get0_propq())) == NULL)
goto end;
-#ifdef X509_V3
- /* Make it an X509 v3 certificate. */
- if (!X509_set_version(ret, 2))
- goto end;
-#endif
-
if (BN_to_ASN1_INTEGER(serial, X509_get_serialNumber(ret)) == NULL)
goto end;
if (selfsign) {
@@ -1630,32 +1709,24 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
if (!i)
goto end;
+ /* Initialize the context structure */
+ X509V3_set_ctx(&ext_ctx, selfsign ? ret : x509,
+ ret, req, NULL, X509V3_CTX_REPLACE);
+
/* Lets add the extensions, if there are any */
if (ext_sect) {
- X509V3_CTX ctx;
-
- /* Initialize the context structure */
- if (selfsign)
- X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0);
- else
- X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
-
- if (extconf != NULL) {
+ if (extfile_conf != NULL) {
if (verbose)
BIO_printf(bio_err, "Extra configuration file found\n");
- /* Use the extconf configuration db LHASH */
- X509V3_set_nconf(&ctx, extconf);
-
- /* Test the structure (needed?) */
- /* X509V3_set_ctx_test(&ctx); */
+ /* Use the extfile_conf configuration db LHASH */
+ X509V3_set_nconf(&ext_ctx, extfile_conf);
/* Adds exts contained in the configuration file */
- if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect, ret)) {
+ if (!X509V3_EXT_add_nconf(extfile_conf, &ext_ctx, ext_sect, ret)) {
BIO_printf(bio_err,
- "ERROR: adding extensions in section %s\n",
+ "Error adding certificate extensions from extfile section %s\n",
ext_sect);
- ERR_print_errors(bio_err);
goto end;
}
if (verbose)
@@ -1663,13 +1734,12 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
"Successfully added extensions from file.\n");
} else if (ext_sect) {
/* We found extensions to be set from config file */
- X509V3_set_nconf(&ctx, lconf);
+ X509V3_set_nconf(&ext_ctx, lconf);
- if (!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) {
+ if (!X509V3_EXT_add_nconf(lconf, &ext_ctx, ext_sect, ret)) {
BIO_printf(bio_err,
- "ERROR: adding extensions in section %s\n",
+ "Error adding certificate extensions from config section %s\n",
ext_sect);
- ERR_print_errors(bio_err);
goto end;
}
@@ -1683,19 +1753,9 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
if (!copy_extensions(ret, req, ext_copy)) {
BIO_printf(bio_err, "ERROR: adding extensions from request\n");
- ERR_print_errors(bio_err);
goto end;
}
- {
- const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(ret);
-
- if (exts != NULL && sk_X509_EXTENSION_num(exts) > 0)
- /* Make it an X509 v3 certificate. */
- if (!X509_set_version(ret, 2))
- goto end;
- }
-
if (verbose)
BIO_printf(bio_err,
"The subject name appears to be ok, checking data base for clashes\n");
@@ -1825,7 +1885,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
}
BIO_printf(bio_err, "Certificate is to be certified until ");
- ASN1_TIME_print(bio_err, X509_get0_notAfter(ret));
+ ASN1_TIME_print_ex(bio_err, X509_get0_notAfter(ret), dateopt);
if (days)
BIO_printf(bio_err, " (%ld days)", days);
BIO_printf(bio_err, "\n");
@@ -1853,7 +1913,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
!EVP_PKEY_missing_parameters(pkey))
EVP_PKEY_copy_parameters(pktmp, pkey);
- if (!do_X509_sign(ret, pkey, dgst, sigopts))
+ if (!do_X509_sign(ret, pkey, dgst, sigopts, &ext_ctx))
goto end;
/* We now just add it to the database as DB_TYPE_VAL('V') */
@@ -1911,14 +1971,14 @@ static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
}
static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey,
- X509 *x509, const EVP_MD *dgst,
+ X509 *x509, const char *dgst,
STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
BIGNUM *serial, const char *subj, unsigned long chtype,
int multirdn, int email_dn, const char *startdate,
const char *enddate, long days, const char *ext_sect,
CONF *lconf, int verbose, unsigned long certopt,
- unsigned long nameopt, int default_op, int ext_copy)
+ unsigned long nameopt, int default_op, int ext_copy, unsigned long dateopt)
{
STACK_OF(CONF_VALUE) *sk = NULL;
LHASH_OF(CONF_VALUE) *parms = NULL;
@@ -1941,7 +2001,6 @@ static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey,
parms = CONF_load(NULL, infile, &errline);
if (parms == NULL) {
BIO_printf(bio_err, "error on line %ld of %s\n", errline, infile);
- ERR_print_errors(bio_err);
goto end;
}
@@ -1959,10 +2018,8 @@ static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey,
* and we can use the same code as if you had a real X509 request.
*/
req = X509_REQ_new();
- if (req == NULL) {
- ERR_print_errors(bio_err);
+ if (req == NULL)
goto end;
- }
/*
* Build up the subject name set.
@@ -1993,7 +2050,6 @@ static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey,
if (spki == NULL) {
BIO_printf(bio_err,
"unable to load Netscape SPKAC structure\n");
- ERR_print_errors(bio_err);
goto end;
}
}
@@ -2035,7 +2091,7 @@ static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey,
ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
chtype, multirdn, email_dn, startdate, enddate, days, 1,
verbose, req, ext_sect, lconf, certopt, nameopt, default_op,
- ext_copy, 0);
+ ext_copy, 0, dateopt);
end:
X509_REQ_free(req);
CONF_free(parms);
@@ -2062,7 +2118,7 @@ static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type,
for (i = 0; i < DB_NUMBER; i++)
row[i] = NULL;
row[DB_name] = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0);
- bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509), NULL);
+ bn = ASN1_INTEGER_to_BN(X509_get0_serialNumber(x509), NULL);
if (!bn)
goto end;
if (BN_is_zero(bn))
@@ -2313,7 +2369,7 @@ static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg)
case REV_CRL_REASON:
for (i = 0; i < 8; i++) {
- if (strcasecmp(rev_arg, crl_reasons[i]) == 0) {
+ if (OPENSSL_strcasecmp(rev_arg, crl_reasons[i]) == 0) {
reason = crl_reasons[i];
break;
}
@@ -2413,18 +2469,18 @@ static int make_revoked(X509_REVOKED *rev, const char *str)
rtmp = ASN1_ENUMERATED_new();
if (rtmp == NULL || !ASN1_ENUMERATED_set(rtmp, reason_code))
goto end;
- if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
+ if (X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0) <= 0)
goto end;
}
if (rev && comp_time) {
- if (!X509_REVOKED_add1_ext_i2d
- (rev, NID_invalidity_date, comp_time, 0, 0))
+ if (X509_REVOKED_add1_ext_i2d
+ (rev, NID_invalidity_date, comp_time, 0, 0) <= 0)
goto end;
}
if (rev && hold) {
- if (!X509_REVOKED_add1_ext_i2d
- (rev, NID_hold_instruction_code, hold, 0, 0))
+ if (X509_REVOKED_add1_ext_i2d
+ (rev, NID_hold_instruction_code, hold, 0, 0) <= 0)
goto end;
}
@@ -2530,7 +2586,7 @@ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold,
}
if (reason_str) {
for (i = 0; i < NUM_REASONS; i++) {
- if (strcasecmp(reason_str, crl_reasons[i]) == 0) {
+ if (OPENSSL_strcasecmp(reason_str, crl_reasons[i]) == 0) {
reason_code = i;
break;
}
diff --git a/apps/ciphers.c b/apps/ciphers.c
index aade3fbf5671..42a0bb79f651 100644
--- a/apps/ciphers.c
+++ b/apps/ciphers.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -14,9 +14,10 @@
#include "progs.h"
#include <openssl/err.h>
#include <openssl/ssl.h>
+#include "s_apps.h"
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_STDNAME,
OPT_CONVERT,
OPT_SSL3,
@@ -27,39 +28,50 @@ typedef enum OPTION_choice {
OPT_PSK,
OPT_SRP,
OPT_CIPHERSUITES,
- OPT_V, OPT_UPPER_V, OPT_S
+ OPT_V, OPT_UPPER_V, OPT_S, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS ciphers_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cipher]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+
+ OPT_SECTION("Output"),
{"v", OPT_V, '-', "Verbose listing of the SSL/TLS ciphers"},
{"V", OPT_UPPER_V, '-', "Even more verbose"},
+ {"stdname", OPT_STDNAME, '-', "Show standard cipher names"},
+ {"convert", OPT_CONVERT, 's', "Convert standard name into OpenSSL name"},
+
+ OPT_SECTION("Cipher specification"),
{"s", OPT_S, '-', "Only supported ciphers"},
#ifndef OPENSSL_NO_SSL3
- {"ssl3", OPT_SSL3, '-', "SSL3 mode"},
+ {"ssl3", OPT_SSL3, '-', "Ciphers compatible with SSL3"},
#endif
#ifndef OPENSSL_NO_TLS1
- {"tls1", OPT_TLS1, '-', "TLS1 mode"},
+ {"tls1", OPT_TLS1, '-', "Ciphers compatible with TLS1"},
#endif
#ifndef OPENSSL_NO_TLS1_1
- {"tls1_1", OPT_TLS1_1, '-', "TLS1.1 mode"},
+ {"tls1_1", OPT_TLS1_1, '-', "Ciphers compatible with TLS1.1"},
#endif
#ifndef OPENSSL_NO_TLS1_2
- {"tls1_2", OPT_TLS1_2, '-', "TLS1.2 mode"},
+ {"tls1_2", OPT_TLS1_2, '-', "Ciphers compatible with TLS1.2"},
#endif
#ifndef OPENSSL_NO_TLS1_3
- {"tls1_3", OPT_TLS1_3, '-', "TLS1.3 mode"},
+ {"tls1_3", OPT_TLS1_3, '-', "Ciphers compatible with TLS1.3"},
#endif
- {"stdname", OPT_STDNAME, '-', "Show standard cipher names"},
#ifndef OPENSSL_NO_PSK
- {"psk", OPT_PSK, '-', "include ciphersuites requiring PSK"},
+ {"psk", OPT_PSK, '-', "Include ciphersuites requiring PSK"},
#endif
#ifndef OPENSSL_NO_SRP
- {"srp", OPT_SRP, '-', "include ciphersuites requiring SRP"},
+ {"srp", OPT_SRP, '-', "(deprecated) Include ciphersuites requiring SRP"},
#endif
- {"convert", OPT_CONVERT, 's', "Convert standard name into OpenSSL name"},
{"ciphersuites", OPT_CIPHERSUITES, 's',
"Configure the TLSv1.3 ciphersuites to use"},
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"cipher", 0, 0, "Cipher string to decode (optional)"},
{NULL}
};
@@ -72,12 +84,6 @@ static unsigned int dummy_psk(SSL *ssl, const char *hint, char *identity,
return 0;
}
#endif
-#ifndef OPENSSL_NO_SRP
-static char *dummy_srp(SSL *ssl, void *arg)
-{
- return "";
-}
-#endif
int ciphers_main(int argc, char **argv)
{
@@ -159,13 +165,18 @@ int ciphers_main(int argc, char **argv)
case OPT_CIPHERSUITES:
ciphersuites = opt_arg();
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* Optional arg is cipher name. */
argv = opt_rest();
argc = opt_num_rest();
-
if (argc == 1)
- ciphers = *argv;
+ ciphers = argv[0];
else if (argc != 0)
goto opthelp;
@@ -176,7 +187,7 @@ int ciphers_main(int argc, char **argv)
goto end;
}
- ctx = SSL_CTX_new(meth);
+ ctx = SSL_CTX_new_ex(app_get0_libctx(), app_get0_propq(), meth);
if (ctx == NULL)
goto err;
if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
@@ -190,7 +201,7 @@ int ciphers_main(int argc, char **argv)
#endif
#ifndef OPENSSL_NO_SRP
if (srp)
- SSL_CTX_set_srp_client_pwd_callback(ctx, dummy_srp);
+ set_up_dummy_srp(ctx);
#endif
if (ciphersuites != NULL && !SSL_CTX_set_ciphersuites(ctx, ciphersuites)) {
@@ -216,6 +227,10 @@ int ciphers_main(int argc, char **argv)
if (!verbose) {
for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
const SSL_CIPHER *c = sk_SSL_CIPHER_value(sk, i);
+
+ if (!ossl_assert(c != NULL))
+ continue;
+
p = SSL_CIPHER_get_name(c);
if (p == NULL)
break;
@@ -231,6 +246,9 @@ int ciphers_main(int argc, char **argv)
c = sk_SSL_CIPHER_value(sk, i);
+ if (!ossl_assert(c != NULL))
+ continue;
+
if (Verbose) {
unsigned long id = SSL_CIPHER_get_id(c);
int id0 = (int)(id >> 24);
@@ -248,7 +266,7 @@ int ciphers_main(int argc, char **argv)
const char *nm = SSL_CIPHER_standard_name(c);
if (nm == NULL)
nm = "UNKNOWN";
- BIO_printf(bio_out, "%s - ", nm);
+ BIO_printf(bio_out, "%-45s - ", nm);
}
BIO_puts(bio_out, SSL_CIPHER_description(c, buf, sizeof(buf)));
}
diff --git a/apps/cmp.c b/apps/cmp.c
new file mode 100644
index 000000000000..9b9e405bb248
--- /dev/null
+++ b/apps/cmp.c
@@ -0,0 +1,3023 @@
+/*
+ * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* This app is disabled when OPENSSL_NO_CMP is defined. */
+
+#include <string.h>
+#include <ctype.h>
+
+#include "apps.h"
+#include "http_server.h"
+#include "s_apps.h"
+#include "progs.h"
+
+#include "cmp_mock_srv.h"
+
+/* tweaks needed due to missing unistd.h on Windows */
+#if defined(_WIN32) && !defined(__BORLANDC__)
+# define access _access
+#endif
+#ifndef F_OK
+# define F_OK 0
+#endif
+
+#include <openssl/ui.h>
+#include <openssl/pkcs12.h>
+#include <openssl/ssl.h>
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <stdlib.h>
+#include <openssl/cmp.h>
+#include <openssl/cmp_util.h>
+#include <openssl/crmf.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/store.h>
+#include <openssl/objects.h>
+#include <openssl/x509.h>
+
+static char *prog;
+static char *opt_config = NULL;
+#define CMP_SECTION "cmp"
+#define SECTION_NAME_MAX 40 /* max length of section name */
+#define DEFAULT_SECTION "default"
+static char *opt_section = CMP_SECTION;
+static int opt_verbosity = OSSL_CMP_LOG_INFO;
+
+static int read_config(void);
+
+static CONF *conf = NULL; /* OpenSSL config file context structure */
+static OSSL_CMP_CTX *cmp_ctx = NULL; /* the client-side CMP context */
+
+/* the type of cmp command we want to send */
+typedef enum {
+ CMP_IR,
+ CMP_KUR,
+ CMP_CR,
+ CMP_P10CR,
+ CMP_RR,
+ CMP_GENM
+} cmp_cmd_t;
+
+/* message transfer */
+#ifndef OPENSSL_NO_SOCK
+static char *opt_server = NULL;
+static char *opt_proxy = NULL;
+static char *opt_no_proxy = NULL;
+#endif
+static char *opt_recipient = NULL;
+static char *opt_path = NULL;
+static int opt_keep_alive = 1;
+static int opt_msg_timeout = -1;
+static int opt_total_timeout = -1;
+
+/* server authentication */
+static char *opt_trusted = NULL;
+static char *opt_untrusted = NULL;
+static char *opt_srvcert = NULL;
+static char *opt_expect_sender = NULL;
+static int opt_ignore_keyusage = 0;
+static int opt_unprotected_errors = 0;
+static char *opt_extracertsout = NULL;
+static char *opt_cacertsout = NULL;
+
+/* client authentication */
+static char *opt_ref = NULL;
+static char *opt_secret = NULL;
+static char *opt_cert = NULL;
+static char *opt_own_trusted = NULL;
+static char *opt_key = NULL;
+static char *opt_keypass = NULL;
+static char *opt_digest = NULL;
+static char *opt_mac = NULL;
+static char *opt_extracerts = NULL;
+static int opt_unprotected_requests = 0;
+
+/* generic message */
+static char *opt_cmd_s = NULL;
+static int opt_cmd = -1;
+static char *opt_geninfo = NULL;
+static char *opt_infotype_s = NULL;
+static int opt_infotype = NID_undef;
+
+/* certificate enrollment */
+static char *opt_newkey = NULL;
+static char *opt_newkeypass = NULL;
+static char *opt_subject = NULL;
+static char *opt_issuer = NULL;
+static int opt_days = 0;
+static char *opt_reqexts = NULL;
+static char *opt_sans = NULL;
+static int opt_san_nodefault = 0;
+static char *opt_policies = NULL;
+static char *opt_policy_oids = NULL;
+static int opt_policy_oids_critical = 0;
+static int opt_popo = OSSL_CRMF_POPO_NONE - 1;
+static char *opt_csr = NULL;
+static char *opt_out_trusted = NULL;
+static int opt_implicit_confirm = 0;
+static int opt_disable_confirm = 0;
+static char *opt_certout = NULL;
+static char *opt_chainout = NULL;
+
+/* certificate enrollment and revocation */
+static char *opt_oldcert = NULL;
+static int opt_revreason = CRL_REASON_NONE;
+
+/* credentials format */
+static char *opt_certform_s = "PEM";
+static int opt_certform = FORMAT_PEM;
+static char *opt_keyform_s = NULL;
+static int opt_keyform = FORMAT_UNDEF;
+static char *opt_otherpass = NULL;
+static char *opt_engine = NULL;
+
+#ifndef OPENSSL_NO_SOCK
+/* TLS connection */
+static int opt_tls_used = 0;
+static char *opt_tls_cert = NULL;
+static char *opt_tls_key = NULL;
+static char *opt_tls_keypass = NULL;
+static char *opt_tls_extra = NULL;
+static char *opt_tls_trusted = NULL;
+static char *opt_tls_host = NULL;
+#endif
+
+/* client-side debugging */
+static int opt_batch = 0;
+static int opt_repeat = 1;
+static char *opt_reqin = NULL;
+static int opt_reqin_new_tid = 0;
+static char *opt_reqout = NULL;
+static char *opt_rspin = NULL;
+static char *opt_rspout = NULL;
+static int opt_use_mock_srv = 0;
+
+/* mock server */
+#ifndef OPENSSL_NO_SOCK
+static char *opt_port = NULL;
+static int opt_max_msgs = 0;
+#endif
+static char *opt_srv_ref = NULL;
+static char *opt_srv_secret = NULL;
+static char *opt_srv_cert = NULL;
+static char *opt_srv_key = NULL;
+static char *opt_srv_keypass = NULL;
+
+static char *opt_srv_trusted = NULL;
+static char *opt_srv_untrusted = NULL;
+static char *opt_rsp_cert = NULL;
+static char *opt_rsp_extracerts = NULL;
+static char *opt_rsp_capubs = NULL;
+static int opt_poll_count = 0;
+static int opt_check_after = 1;
+static int opt_grant_implicitconf = 0;
+
+static int opt_pkistatus = OSSL_CMP_PKISTATUS_accepted;
+static int opt_failure = INT_MIN;
+static int opt_failurebits = 0;
+static char *opt_statusstring = NULL;
+static int opt_send_error = 0;
+static int opt_send_unprotected = 0;
+static int opt_send_unprot_err = 0;
+static int opt_accept_unprotected = 0;
+static int opt_accept_unprot_err = 0;
+static int opt_accept_raverified = 0;
+
+static X509_VERIFY_PARAM *vpm = NULL;
+
+typedef enum OPTION_choice {
+ OPT_COMMON,
+ OPT_CONFIG, OPT_SECTION, OPT_VERBOSITY,
+
+ OPT_CMD, OPT_INFOTYPE, OPT_GENINFO,
+
+ OPT_NEWKEY, OPT_NEWKEYPASS, OPT_SUBJECT, OPT_ISSUER,
+ OPT_DAYS, OPT_REQEXTS,
+ OPT_SANS, OPT_SAN_NODEFAULT,
+ OPT_POLICIES, OPT_POLICY_OIDS, OPT_POLICY_OIDS_CRITICAL,
+ OPT_POPO, OPT_CSR,
+ OPT_OUT_TRUSTED, OPT_IMPLICIT_CONFIRM, OPT_DISABLE_CONFIRM,
+ OPT_CERTOUT, OPT_CHAINOUT,
+
+ OPT_OLDCERT, OPT_REVREASON,
+
+#ifndef OPENSSL_NO_SOCK
+ OPT_SERVER, OPT_PROXY, OPT_NO_PROXY,
+#endif
+ OPT_RECIPIENT, OPT_PATH,
+ OPT_KEEP_ALIVE, OPT_MSG_TIMEOUT, OPT_TOTAL_TIMEOUT,
+
+ OPT_TRUSTED, OPT_UNTRUSTED, OPT_SRVCERT,
+ OPT_EXPECT_SENDER,
+ OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS,
+ OPT_EXTRACERTSOUT, OPT_CACERTSOUT,
+
+ OPT_REF, OPT_SECRET, OPT_CERT, OPT_OWN_TRUSTED, OPT_KEY, OPT_KEYPASS,
+ OPT_DIGEST, OPT_MAC, OPT_EXTRACERTS,
+ OPT_UNPROTECTED_REQUESTS,
+
+ OPT_CERTFORM, OPT_KEYFORM,
+ OPT_OTHERPASS,
+#ifndef OPENSSL_NO_ENGINE
+ OPT_ENGINE,
+#endif
+ OPT_PROV_ENUM,
+ OPT_R_ENUM,
+
+#ifndef OPENSSL_NO_SOCK
+ OPT_TLS_USED, OPT_TLS_CERT, OPT_TLS_KEY,
+ OPT_TLS_KEYPASS,
+ OPT_TLS_EXTRA, OPT_TLS_TRUSTED, OPT_TLS_HOST,
+#endif
+
+ OPT_BATCH, OPT_REPEAT,
+ OPT_REQIN, OPT_REQIN_NEW_TID, OPT_REQOUT, OPT_RSPIN, OPT_RSPOUT,
+ OPT_USE_MOCK_SRV,
+
+#ifndef OPENSSL_NO_SOCK
+ OPT_PORT, OPT_MAX_MSGS,
+#endif
+ OPT_SRV_REF, OPT_SRV_SECRET,
+ OPT_SRV_CERT, OPT_SRV_KEY, OPT_SRV_KEYPASS,
+ OPT_SRV_TRUSTED, OPT_SRV_UNTRUSTED,
+ OPT_RSP_CERT, OPT_RSP_EXTRACERTS, OPT_RSP_CAPUBS,
+ OPT_POLL_COUNT, OPT_CHECK_AFTER,
+ OPT_GRANT_IMPLICITCONF,
+ OPT_PKISTATUS, OPT_FAILURE,
+ OPT_FAILUREBITS, OPT_STATUSSTRING,
+ OPT_SEND_ERROR, OPT_SEND_UNPROTECTED,
+ OPT_SEND_UNPROT_ERR, OPT_ACCEPT_UNPROTECTED,
+ OPT_ACCEPT_UNPROT_ERR, OPT_ACCEPT_RAVERIFIED,
+
+ OPT_V_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS cmp_options[] = {
+ /* entries must be in the same order as enumerated above!! */
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"config", OPT_CONFIG, 's',
+ "Configuration file to use. \"\" = none. Default from env variable OPENSSL_CONF"},
+ {"section", OPT_SECTION, 's',
+ "Section(s) in config file to get options from. \"\" = 'default'. Default 'cmp'"},
+ {"verbosity", OPT_VERBOSITY, 'N',
+ "Log level; 3=ERR, 4=WARN, 6=INFO, 7=DEBUG, 8=TRACE. Default 6 = INFO"},
+
+ OPT_SECTION("Generic message"),
+ {"cmd", OPT_CMD, 's', "CMP request to send: ir/cr/kur/p10cr/rr/genm"},
+ {"infotype", OPT_INFOTYPE, 's',
+ "InfoType name for requesting specific info in genm, e.g. 'signKeyPairTypes'"},
+ {"geninfo", OPT_GENINFO, 's',
+ "generalInfo integer values to place in request PKIHeader with given OID"},
+ {OPT_MORE_STR, 0, 0,
+ "specified in the form <OID>:int:<n>, e.g. \"1.2.3.4:int:56789\""},
+
+ OPT_SECTION("Certificate enrollment"),
+ {"newkey", OPT_NEWKEY, 's',
+ "Private or public key for the requested cert. Default: CSR key or client key"},
+ {"newkeypass", OPT_NEWKEYPASS, 's', "New private key pass phrase source"},
+ {"subject", OPT_SUBJECT, 's',
+ "Distinguished Name (DN) of subject to use in the requested cert template"},
+ {OPT_MORE_STR, 0, 0,
+ "For kur, default is subject of -csr arg or reference cert (see -oldcert)"},
+ {OPT_MORE_STR, 0, 0,
+ "this default is used for ir and cr only if no Subject Alt Names are set"},
+ {"issuer", OPT_ISSUER, 's',
+ "DN of the issuer to place in the requested certificate template"},
+ {OPT_MORE_STR, 0, 0,
+ "also used as recipient if neither -recipient nor -srvcert are given"},
+ {"days", OPT_DAYS, 'N',
+ "Requested validity time of the new certificate in number of days"},
+ {"reqexts", OPT_REQEXTS, 's',
+ "Name of config file section defining certificate request extensions."},
+ {OPT_MORE_STR, 0, 0,
+ "Augments or replaces any extensions contained CSR given with -csr"},
+ {"sans", OPT_SANS, 's',
+ "Subject Alt Names (IPADDR/DNS/URI) to add as (critical) cert req extension"},
+ {"san_nodefault", OPT_SAN_NODEFAULT, '-',
+ "Do not take default SANs from reference certificate (see -oldcert)"},
+ {"policies", OPT_POLICIES, 's',
+ "Name of config file section defining policies certificate request extension"},
+ {"policy_oids", OPT_POLICY_OIDS, 's',
+ "Policy OID(s) to add as policies certificate request extension"},
+ {"policy_oids_critical", OPT_POLICY_OIDS_CRITICAL, '-',
+ "Flag the policy OID(s) given with -policy_oids as critical"},
+ {"popo", OPT_POPO, 'n',
+ "Proof-of-Possession (POPO) method to use for ir/cr/kur where"},
+ {OPT_MORE_STR, 0, 0,
+ "-1 = NONE, 0 = RAVERIFIED, 1 = SIGNATURE (default), 2 = KEYENC"},
+ {"csr", OPT_CSR, 's',
+ "PKCS#10 CSR file in PEM or DER format to convert or to use in p10cr"},
+ {"out_trusted", OPT_OUT_TRUSTED, 's',
+ "Certificates to trust when verifying newly enrolled certificates"},
+ {"implicit_confirm", OPT_IMPLICIT_CONFIRM, '-',
+ "Request implicit confirmation of newly enrolled certificates"},
+ {"disable_confirm", OPT_DISABLE_CONFIRM, '-',
+ "Do not confirm newly enrolled certificate w/o requesting implicit"},
+ {OPT_MORE_STR, 0, 0,
+ "confirmation. WARNING: This leads to behavior violating RFC 4210"},
+ {"certout", OPT_CERTOUT, 's',
+ "File to save newly enrolled certificate"},
+ {"chainout", OPT_CHAINOUT, 's',
+ "File to save the chain of newly enrolled certificate"},
+
+ OPT_SECTION("Certificate enrollment and revocation"),
+
+ {"oldcert", OPT_OLDCERT, 's',
+ "Certificate to be updated (defaulting to -cert) or to be revoked in rr;"},
+ {OPT_MORE_STR, 0, 0,
+ "also used as reference (defaulting to -cert) for subject DN and SANs."},
+ {OPT_MORE_STR, 0, 0,
+ "Issuer is used as recipient unless -recipient, -srvcert, or -issuer given"},
+ {"revreason", OPT_REVREASON, 'n',
+ "Reason code to include in revocation request (rr); possible values:"},
+ {OPT_MORE_STR, 0, 0,
+ "0..6, 8..10 (see RFC5280, 5.3.1) or -1. Default -1 = none included"},
+
+ OPT_SECTION("Message transfer"),
+#ifdef OPENSSL_NO_SOCK
+ {OPT_MORE_STR, 0, 0,
+ "NOTE: -server, -proxy, and -no_proxy not supported due to no-sock build"},
+#else
+ {"server", OPT_SERVER, 's',
+ "[http[s]://]address[:port][/path] of CMP server. Default port 80 or 443."},
+ {OPT_MORE_STR, 0, 0,
+ "address may be a DNS name or an IP address; path can be overridden by -path"},
+ {"proxy", OPT_PROXY, 's',
+ "[http[s]://]address[:port][/path] of HTTP(S) proxy to use; path is ignored"},
+ {"no_proxy", OPT_NO_PROXY, 's',
+ "List of addresses of servers not to use HTTP(S) proxy for"},
+ {OPT_MORE_STR, 0, 0,
+ "Default from environment variable 'no_proxy', else 'NO_PROXY', else none"},
+#endif
+ {"recipient", OPT_RECIPIENT, 's',
+ "DN of CA. Default: subject of -srvcert, -issuer, issuer of -oldcert or -cert"},
+ {"path", OPT_PATH, 's',
+ "HTTP path (aka CMP alias) at the CMP server. Default from -server, else \"/\""},
+ {"keep_alive", OPT_KEEP_ALIVE, 'N',
+ "Persistent HTTP connections. 0: no, 1 (the default): request, 2: require"},
+ {"msg_timeout", OPT_MSG_TIMEOUT, 'N',
+ "Number of seconds allowed per CMP message round trip, or 0 for infinite"},
+ {"total_timeout", OPT_TOTAL_TIMEOUT, 'N',
+ "Overall time an enrollment incl. polling may take. Default 0 = infinite"},
+
+ OPT_SECTION("Server authentication"),
+ {"trusted", OPT_TRUSTED, 's',
+ "Certificates to trust as chain roots when verifying signed CMP responses"},
+ {OPT_MORE_STR, 0, 0, "unless -srvcert is given"},
+ {"untrusted", OPT_UNTRUSTED, 's',
+ "Intermediate CA certs for chain construction for CMP/TLS/enrolled certs"},
+ {"srvcert", OPT_SRVCERT, 's',
+ "Server cert to pin and trust directly when verifying signed CMP responses"},
+ {"expect_sender", OPT_EXPECT_SENDER, 's',
+ "DN of expected sender of responses. Defaults to subject of -srvcert, if any"},
+ {"ignore_keyusage", OPT_IGNORE_KEYUSAGE, '-',
+ "Ignore CMP signer cert key usage, else 'digitalSignature' must be allowed"},
+ {"unprotected_errors", OPT_UNPROTECTED_ERRORS, '-',
+ "Accept missing or invalid protection of regular error messages and negative"},
+ {OPT_MORE_STR, 0, 0,
+ "certificate responses (ip/cp/kup), revocation responses (rp), and PKIConf"},
+ {OPT_MORE_STR, 0, 0,
+ "WARNING: This setting leads to behavior allowing violation of RFC 4210"},
+ {"extracertsout", OPT_EXTRACERTSOUT, 's',
+ "File to save extra certificates received in the extraCerts field"},
+ {"cacertsout", OPT_CACERTSOUT, 's',
+ "File to save CA certificates received in the caPubs field of 'ip' messages"},
+
+ OPT_SECTION("Client authentication"),
+ {"ref", OPT_REF, 's',
+ "Reference value to use as senderKID in case no -cert is given"},
+ {"secret", OPT_SECRET, 's',
+ "Prefer PBM (over signatures) for protecting msgs with given password source"},
+ {"cert", OPT_CERT, 's',
+ "Client's CMP signer certificate; its public key must match the -key argument"},
+ {OPT_MORE_STR, 0, 0,
+ "This also used as default reference for subject DN and SANs."},
+ {OPT_MORE_STR, 0, 0,
+ "Any further certs included are appended to the untrusted certs"},
+ {"own_trusted", OPT_OWN_TRUSTED, 's',
+ "Optional certs to verify chain building for own CMP signer cert"},
+ {"key", OPT_KEY, 's', "CMP signer private key, not used when -secret given"},
+ {"keypass", OPT_KEYPASS, 's',
+ "Client private key (and cert and old cert) pass phrase source"},
+ {"digest", OPT_DIGEST, 's',
+ "Digest to use in message protection and POPO signatures. Default \"sha256\""},
+ {"mac", OPT_MAC, 's',
+ "MAC algorithm to use in PBM-based message protection. Default \"hmac-sha1\""},
+ {"extracerts", OPT_EXTRACERTS, 's',
+ "Certificates to append in extraCerts field of outgoing messages."},
+ {OPT_MORE_STR, 0, 0,
+ "This can be used as the default CMP signer cert chain to include"},
+ {"unprotected_requests", OPT_UNPROTECTED_REQUESTS, '-',
+ "Send messages without CMP-level protection"},
+
+ OPT_SECTION("Credentials format"),
+ {"certform", OPT_CERTFORM, 's',
+ "Format (PEM or DER) to use when saving a certificate to a file. Default PEM"},
+ {"keyform", OPT_KEYFORM, 's',
+ "Format of the key input (ENGINE, other values ignored)"},
+ {"otherpass", OPT_OTHERPASS, 's',
+ "Pass phrase source potentially needed for loading certificates of others"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's',
+ "Use crypto engine with given identifier, possibly a hardware device."},
+ {OPT_MORE_STR, 0, 0,
+ "Engines may also be defined in OpenSSL config file engine section."},
+#endif
+ OPT_PROV_OPTIONS,
+ OPT_R_OPTIONS,
+
+ OPT_SECTION("TLS connection"),
+#ifdef OPENSSL_NO_SOCK
+ {OPT_MORE_STR, 0, 0,
+ "NOTE: -tls_used and all other TLS options not supported due to no-sock build"},
+#else
+ {"tls_used", OPT_TLS_USED, '-',
+ "Enable using TLS (also when other TLS options are not set)"},
+ {"tls_cert", OPT_TLS_CERT, 's',
+ "Client's TLS certificate. May include chain to be provided to TLS server"},
+ {"tls_key", OPT_TLS_KEY, 's',
+ "Private key for the client's TLS certificate"},
+ {"tls_keypass", OPT_TLS_KEYPASS, 's',
+ "Pass phrase source for the client's private TLS key (and TLS cert)"},
+ {"tls_extra", OPT_TLS_EXTRA, 's',
+ "Extra certificates to provide to TLS server during TLS handshake"},
+ {"tls_trusted", OPT_TLS_TRUSTED, 's',
+ "Trusted certificates to use for verifying the TLS server certificate;"},
+ {OPT_MORE_STR, 0, 0, "this implies host name validation"},
+ {"tls_host", OPT_TLS_HOST, 's',
+ "Address to be checked (rather than -server) during TLS host name validation"},
+#endif
+
+ OPT_SECTION("Client-side debugging"),
+ {"batch", OPT_BATCH, '-',
+ "Do not interactively prompt for input when a password is required etc."},
+ {"repeat", OPT_REPEAT, 'p',
+ "Invoke the transaction the given positive number of times. Default 1"},
+ {"reqin", OPT_REQIN, 's', "Take sequence of CMP requests from file(s)"},
+ {"reqin_new_tid", OPT_REQIN_NEW_TID, '-',
+ "Use fresh transactionID for CMP requests read from -reqin"},
+ {"reqout", OPT_REQOUT, 's', "Save sequence of CMP requests to file(s)"},
+ {"rspin", OPT_RSPIN, 's',
+ "Process sequence of CMP responses provided in file(s), skipping server"},
+ {"rspout", OPT_RSPOUT, 's', "Save sequence of CMP responses to file(s)"},
+
+ {"use_mock_srv", OPT_USE_MOCK_SRV, '-',
+ "Use internal mock server at API level, bypassing socket-based HTTP"},
+
+ OPT_SECTION("Mock server"),
+#ifdef OPENSSL_NO_SOCK
+ {OPT_MORE_STR, 0, 0,
+ "NOTE: -port and -max_msgs not supported due to no-sock build"},
+#else
+ {"port", OPT_PORT, 's',
+ "Act as HTTP-based mock server listening on given port"},
+ {"max_msgs", OPT_MAX_MSGS, 'N',
+ "max number of messages handled by HTTP mock server. Default: 0 = unlimited"},
+#endif
+
+ {"srv_ref", OPT_SRV_REF, 's',
+ "Reference value to use as senderKID of server in case no -srv_cert is given"},
+ {"srv_secret", OPT_SRV_SECRET, 's',
+ "Password source for server authentication with a pre-shared key (secret)"},
+ {"srv_cert", OPT_SRV_CERT, 's', "Certificate of the server"},
+ {"srv_key", OPT_SRV_KEY, 's',
+ "Private key used by the server for signing messages"},
+ {"srv_keypass", OPT_SRV_KEYPASS, 's',
+ "Server private key (and cert) pass phrase source"},
+
+ {"srv_trusted", OPT_SRV_TRUSTED, 's',
+ "Trusted certificates for client authentication"},
+ {"srv_untrusted", OPT_SRV_UNTRUSTED, 's',
+ "Intermediate certs that may be useful for verifying CMP protection"},
+ {"rsp_cert", OPT_RSP_CERT, 's',
+ "Certificate to be returned as mock enrollment result"},
+ {"rsp_extracerts", OPT_RSP_EXTRACERTS, 's',
+ "Extra certificates to be included in mock certification responses"},
+ {"rsp_capubs", OPT_RSP_CAPUBS, 's',
+ "CA certificates to be included in mock ip response"},
+ {"poll_count", OPT_POLL_COUNT, 'N',
+ "Number of times the client must poll before receiving a certificate"},
+ {"check_after", OPT_CHECK_AFTER, 'N',
+ "The check_after value (time to wait) to include in poll response"},
+ {"grant_implicitconf", OPT_GRANT_IMPLICITCONF, '-',
+ "Grant implicit confirmation of newly enrolled certificate"},
+
+ {"pkistatus", OPT_PKISTATUS, 'N',
+ "PKIStatus to be included in server response. Possible values: 0..6"},
+ {"failure", OPT_FAILURE, 'N',
+ "A single failure info bit number to include in server response, 0..26"},
+ {"failurebits", OPT_FAILUREBITS, 'N',
+ "Number representing failure bits to include in server response, 0..2^27 - 1"},
+ {"statusstring", OPT_STATUSSTRING, 's',
+ "Status string to be included in server response"},
+ {"send_error", OPT_SEND_ERROR, '-',
+ "Force server to reply with error message"},
+ {"send_unprotected", OPT_SEND_UNPROTECTED, '-',
+ "Send response messages without CMP-level protection"},
+ {"send_unprot_err", OPT_SEND_UNPROT_ERR, '-',
+ "In case of negative responses, server shall send unprotected error messages,"},
+ {OPT_MORE_STR, 0, 0,
+ "certificate responses (ip/cp/kup), and revocation responses (rp)."},
+ {OPT_MORE_STR, 0, 0,
+ "WARNING: This setting leads to behavior violating RFC 4210"},
+ {"accept_unprotected", OPT_ACCEPT_UNPROTECTED, '-',
+ "Accept missing or invalid protection of requests"},
+ {"accept_unprot_err", OPT_ACCEPT_UNPROT_ERR, '-',
+ "Accept unprotected error messages from client"},
+ {"accept_raverified", OPT_ACCEPT_RAVERIFIED, '-',
+ "Accept RAVERIFIED as proof-of-possession (POPO)"},
+
+ OPT_V_OPTIONS,
+ {NULL}
+};
+
+typedef union {
+ char **txt;
+ int *num;
+ long *num_long;
+} varref;
+static varref cmp_vars[] = { /* must be in same order as enumerated above! */
+ {&opt_config}, {&opt_section}, {(char **)&opt_verbosity},
+
+ {&opt_cmd_s}, {&opt_infotype_s}, {&opt_geninfo},
+
+ {&opt_newkey}, {&opt_newkeypass}, {&opt_subject}, {&opt_issuer},
+ {(char **)&opt_days}, {&opt_reqexts},
+ {&opt_sans}, {(char **)&opt_san_nodefault},
+ {&opt_policies}, {&opt_policy_oids}, {(char **)&opt_policy_oids_critical},
+ {(char **)&opt_popo}, {&opt_csr},
+ {&opt_out_trusted},
+ {(char **)&opt_implicit_confirm}, {(char **)&opt_disable_confirm},
+ {&opt_certout}, {&opt_chainout},
+
+ {&opt_oldcert}, {(char **)&opt_revreason},
+
+#ifndef OPENSSL_NO_SOCK
+ {&opt_server}, {&opt_proxy}, {&opt_no_proxy},
+#endif
+ {&opt_recipient}, {&opt_path}, {(char **)&opt_keep_alive},
+ {(char **)&opt_msg_timeout}, {(char **)&opt_total_timeout},
+
+ {&opt_trusted}, {&opt_untrusted}, {&opt_srvcert},
+ {&opt_expect_sender},
+ {(char **)&opt_ignore_keyusage}, {(char **)&opt_unprotected_errors},
+ {&opt_extracertsout}, {&opt_cacertsout},
+
+ {&opt_ref}, {&opt_secret},
+ {&opt_cert}, {&opt_own_trusted}, {&opt_key}, {&opt_keypass},
+ {&opt_digest}, {&opt_mac}, {&opt_extracerts},
+ {(char **)&opt_unprotected_requests},
+
+ {&opt_certform_s}, {&opt_keyform_s},
+ {&opt_otherpass},
+#ifndef OPENSSL_NO_ENGINE
+ {&opt_engine},
+#endif
+
+#ifndef OPENSSL_NO_SOCK
+ {(char **)&opt_tls_used}, {&opt_tls_cert}, {&opt_tls_key},
+ {&opt_tls_keypass},
+ {&opt_tls_extra}, {&opt_tls_trusted}, {&opt_tls_host},
+#endif
+
+ {(char **)&opt_batch}, {(char **)&opt_repeat},
+ {&opt_reqin}, {(char **)&opt_reqin_new_tid},
+ {&opt_reqout}, {&opt_rspin}, {&opt_rspout},
+
+ {(char **)&opt_use_mock_srv},
+#ifndef OPENSSL_NO_SOCK
+ {&opt_port}, {(char **)&opt_max_msgs},
+#endif
+ {&opt_srv_ref}, {&opt_srv_secret},
+ {&opt_srv_cert}, {&opt_srv_key}, {&opt_srv_keypass},
+ {&opt_srv_trusted}, {&opt_srv_untrusted},
+ {&opt_rsp_cert}, {&opt_rsp_extracerts}, {&opt_rsp_capubs},
+ {(char **)&opt_poll_count}, {(char **)&opt_check_after},
+ {(char **)&opt_grant_implicitconf},
+ {(char **)&opt_pkistatus}, {(char **)&opt_failure},
+ {(char **)&opt_failurebits}, {&opt_statusstring},
+ {(char **)&opt_send_error}, {(char **)&opt_send_unprotected},
+ {(char **)&opt_send_unprot_err}, {(char **)&opt_accept_unprotected},
+ {(char **)&opt_accept_unprot_err}, {(char **)&opt_accept_raverified},
+
+ {NULL}
+};
+
+#define FUNC (strcmp(OPENSSL_FUNC, "(unknown function)") == 0 \
+ ? "CMP" : OPENSSL_FUNC)
+#define CMP_print(bio, level, prefix, msg, a1, a2, a3) \
+ ((void)(level > opt_verbosity ? 0 : \
+ (BIO_printf(bio, "%s:%s:%d:CMP %s: " msg "\n", \
+ FUNC, OPENSSL_FILE, OPENSSL_LINE, prefix, a1, a2, a3))))
+#define CMP_DEBUG(m, a1, a2, a3) \
+ CMP_print(bio_out, OSSL_CMP_LOG_DEBUG, "debug", m, a1, a2, a3)
+#define CMP_debug(msg) CMP_DEBUG(msg"%s%s%s", "", "", "")
+#define CMP_debug1(msg, a1) CMP_DEBUG(msg"%s%s", a1, "", "")
+#define CMP_debug2(msg, a1, a2) CMP_DEBUG(msg"%s", a1, a2, "")
+#define CMP_debug3(msg, a1, a2, a3) CMP_DEBUG(msg, a1, a2, a3)
+#define CMP_INFO(msg, a1, a2, a3) \
+ CMP_print(bio_out, OSSL_CMP_LOG_INFO, "info", msg, a1, a2, a3)
+#define CMP_info(msg) CMP_INFO(msg"%s%s%s", "", "", "")
+#define CMP_info1(msg, a1) CMP_INFO(msg"%s%s", a1, "", "")
+#define CMP_info2(msg, a1, a2) CMP_INFO(msg"%s", a1, a2, "")
+#define CMP_info3(msg, a1, a2, a3) CMP_INFO(msg, a1, a2, a3)
+#define CMP_WARN(m, a1, a2, a3) \
+ CMP_print(bio_out, OSSL_CMP_LOG_WARNING, "warning", m, a1, a2, a3)
+#define CMP_warn(msg) CMP_WARN(msg"%s%s%s", "", "", "")
+#define CMP_warn1(msg, a1) CMP_WARN(msg"%s%s", a1, "", "")
+#define CMP_warn2(msg, a1, a2) CMP_WARN(msg"%s", a1, a2, "")
+#define CMP_warn3(msg, a1, a2, a3) CMP_WARN(msg, a1, a2, a3)
+#define CMP_ERR(msg, a1, a2, a3) \
+ CMP_print(bio_err, OSSL_CMP_LOG_ERR, "error", msg, a1, a2, a3)
+#define CMP_err(msg) CMP_ERR(msg"%s%s%s", "", "", "")
+#define CMP_err1(msg, a1) CMP_ERR(msg"%s%s", a1, "", "")
+#define CMP_err2(msg, a1, a2) CMP_ERR(msg"%s", a1, a2, "")
+#define CMP_err3(msg, a1, a2, a3) CMP_ERR(msg, a1, a2, a3)
+
+static int print_to_bio_out(const char *func, const char *file, int line,
+ OSSL_CMP_severity level, const char *msg)
+{
+ return OSSL_CMP_print_to_bio(bio_out, func, file, line, level, msg);
+}
+
+static int print_to_bio_err(const char *func, const char *file, int line,
+ OSSL_CMP_severity level, const char *msg)
+{
+ return OSSL_CMP_print_to_bio(bio_err, func, file, line, level, msg);
+}
+
+static int set_verbosity(int level)
+{
+ if (level < OSSL_CMP_LOG_EMERG || level > OSSL_CMP_LOG_MAX) {
+ CMP_err1("Logging verbosity level %d out of range (0 .. 8)", level);
+ return 0;
+ }
+ opt_verbosity = level;
+ return 1;
+}
+
+static EVP_PKEY *load_key_pwd(const char *uri, int format,
+ const char *pass, ENGINE *eng, const char *desc)
+{
+ char *pass_string = get_passwd(pass, desc);
+ EVP_PKEY *pkey = load_key(uri, format, 0, pass_string, eng, desc);
+
+ clear_free(pass_string);
+ return pkey;
+}
+
+static X509 *load_cert_pwd(const char *uri, const char *pass, const char *desc)
+{
+ X509 *cert;
+ char *pass_string = get_passwd(pass, desc);
+
+ cert = load_cert_pass(uri, FORMAT_UNDEF, 0, pass_string, desc);
+ clear_free(pass_string);
+ return cert;
+}
+
+static X509_REQ *load_csr_autofmt(const char *infile, const char *desc)
+{
+ X509_REQ *csr;
+ BIO *bio_bak = bio_err;
+
+ bio_err = NULL; /* do not show errors on more than one try */
+ csr = load_csr(infile, FORMAT_PEM, desc);
+ bio_err = bio_bak;
+ if (csr == NULL) {
+ ERR_clear_error();
+ csr = load_csr(infile, FORMAT_ASN1, desc);
+ }
+ if (csr == NULL) {
+ ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "error: unable to load %s from file '%s'\n", desc,
+ infile);
+ } else {
+ EVP_PKEY *pkey = X509_REQ_get0_pubkey(csr);
+ int ret = do_X509_REQ_verify(csr, pkey, NULL /* vfyopts */);
+
+ if (pkey == NULL || ret < 0)
+ CMP_warn("error while verifying CSR self-signature");
+ else if (ret == 0)
+ CMP_warn("CSR self-signature does not match the contents");
+ }
+ return csr;
+}
+
+/* set expected host name/IP addr and clears the email addr in the given ts */
+static int truststore_set_host_etc(X509_STORE *ts, const char *host)
+{
+ X509_VERIFY_PARAM *ts_vpm = X509_STORE_get0_param(ts);
+
+ /* first clear any host names, IP, and email addresses */
+ if (!X509_VERIFY_PARAM_set1_host(ts_vpm, NULL, 0)
+ || !X509_VERIFY_PARAM_set1_ip(ts_vpm, NULL, 0)
+ || !X509_VERIFY_PARAM_set1_email(ts_vpm, NULL, 0))
+ return 0;
+ X509_VERIFY_PARAM_set_hostflags(ts_vpm,
+ X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT |
+ X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+ return (host != NULL && X509_VERIFY_PARAM_set1_ip_asc(ts_vpm, host))
+ || X509_VERIFY_PARAM_set1_host(ts_vpm, host, 0);
+}
+
+/* write OSSL_CMP_MSG DER-encoded to the specified file name item */
+static int write_PKIMESSAGE(const OSSL_CMP_MSG *msg, char **filenames)
+{
+ char *file;
+
+ if (msg == NULL || filenames == NULL) {
+ CMP_err("NULL arg to write_PKIMESSAGE");
+ return 0;
+ }
+ if (*filenames == NULL) {
+ CMP_err("not enough file names provided for writing PKIMessage");
+ return 0;
+ }
+
+ file = *filenames;
+ *filenames = next_item(file);
+ if (OSSL_CMP_MSG_write(file, msg) < 0) {
+ CMP_err1("cannot write PKIMessage to file '%s'", file);
+ return 0;
+ }
+ return 1;
+}
+
+/* read DER-encoded OSSL_CMP_MSG from the specified file name item */
+static OSSL_CMP_MSG *read_PKIMESSAGE(char **filenames)
+{
+ char *file;
+ OSSL_CMP_MSG *ret;
+
+ if (filenames == NULL) {
+ CMP_err("NULL arg to read_PKIMESSAGE");
+ return NULL;
+ }
+ if (*filenames == NULL) {
+ CMP_err("not enough file names provided for reading PKIMessage");
+ return NULL;
+ }
+
+ file = *filenames;
+ *filenames = next_item(file);
+
+ ret = OSSL_CMP_MSG_read(file, app_get0_libctx(), app_get0_propq());
+ if (ret == NULL)
+ CMP_err1("cannot read PKIMessage from file '%s'", file);
+ return ret;
+}
+
+/*-
+ * Sends the PKIMessage req and on success place the response in *res
+ * basically like OSSL_CMP_MSG_http_perform(), but in addition allows
+ * to dump the sequence of requests and responses to files and/or
+ * to take the sequence of requests and responses from files.
+ */
+static OSSL_CMP_MSG *read_write_req_resp(OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *req)
+{
+ OSSL_CMP_MSG *req_new = NULL;
+ OSSL_CMP_MSG *res = NULL;
+ OSSL_CMP_PKIHEADER *hdr;
+ const char *prev_opt_rspin = opt_rspin;
+
+ if (req != NULL && opt_reqout != NULL
+ && !write_PKIMESSAGE(req, &opt_reqout))
+ goto err;
+ if (opt_reqin != NULL && opt_rspin == NULL) {
+ if ((req_new = read_PKIMESSAGE(&opt_reqin)) == NULL)
+ goto err;
+ /*-
+ * The transaction ID in req_new read from opt_reqin may not be fresh.
+ * In this case the server may complain "Transaction id already in use."
+ * The following workaround unfortunately requires re-protection.
+ */
+ if (opt_reqin_new_tid
+ && !OSSL_CMP_MSG_update_transactionID(ctx, req_new))
+ goto err;
+ }
+
+ if (opt_rspin != NULL) {
+ res = read_PKIMESSAGE(&opt_rspin);
+ } else {
+ const OSSL_CMP_MSG *actual_req = opt_reqin != NULL ? req_new : req;
+
+ res = opt_use_mock_srv
+ ? OSSL_CMP_CTX_server_perform(ctx, actual_req)
+ : OSSL_CMP_MSG_http_perform(ctx, actual_req);
+ }
+ if (res == NULL)
+ goto err;
+
+ if (opt_reqin != NULL || prev_opt_rspin != NULL) {
+ /* need to satisfy nonce and transactionID checks */
+ ASN1_OCTET_STRING *nonce;
+ ASN1_OCTET_STRING *tid;
+
+ hdr = OSSL_CMP_MSG_get0_header(res);
+ nonce = OSSL_CMP_HDR_get0_recipNonce(hdr);
+ tid = OSSL_CMP_HDR_get0_transactionID(hdr);
+ if (!OSSL_CMP_CTX_set1_senderNonce(ctx, nonce)
+ || !OSSL_CMP_CTX_set1_transactionID(ctx, tid)) {
+ OSSL_CMP_MSG_free(res);
+ res = NULL;
+ goto err;
+ }
+ }
+
+ if (opt_rspout != NULL && !write_PKIMESSAGE(res, &opt_rspout)) {
+ OSSL_CMP_MSG_free(res);
+ res = NULL;
+ }
+
+ err:
+ OSSL_CMP_MSG_free(req_new);
+ return res;
+}
+
+static int set_name(const char *str,
+ int (*set_fn) (OSSL_CMP_CTX *ctx, const X509_NAME *name),
+ OSSL_CMP_CTX *ctx, const char *desc)
+{
+ if (str != NULL) {
+ X509_NAME *n = parse_name(str, MBSTRING_ASC, 1, desc);
+
+ if (n == NULL)
+ return 0;
+ if (!(*set_fn) (ctx, n)) {
+ X509_NAME_free(n);
+ CMP_err("out of memory");
+ return 0;
+ }
+ X509_NAME_free(n);
+ }
+ return 1;
+}
+
+static int set_gennames(OSSL_CMP_CTX *ctx, char *names, const char *desc)
+{
+ char *next;
+
+ for (; names != NULL; names = next) {
+ GENERAL_NAME *n;
+
+ next = next_item(names);
+ if (strcmp(names, "critical") == 0) {
+ (void)OSSL_CMP_CTX_set_option(ctx,
+ OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL,
+ 1);
+ continue;
+ }
+
+ /* try IP address first, then URI or domain name */
+ (void)ERR_set_mark();
+ n = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_IPADD, names, 0);
+ if (n == NULL)
+ n = a2i_GENERAL_NAME(NULL, NULL, NULL,
+ strchr(names, ':') != NULL ? GEN_URI : GEN_DNS,
+ names, 0);
+ (void)ERR_pop_to_mark();
+
+ if (n == NULL) {
+ CMP_err2("bad syntax of %s '%s'", desc, names);
+ return 0;
+ }
+ if (!OSSL_CMP_CTX_push1_subjectAltName(ctx, n)) {
+ GENERAL_NAME_free(n);
+ CMP_err("out of memory");
+ return 0;
+ }
+ GENERAL_NAME_free(n);
+ }
+ return 1;
+}
+
+static X509_STORE *load_trusted(char *input, int for_new_cert, const char *desc)
+{
+ X509_STORE *ts = load_certstore(input, opt_otherpass, desc, vpm);
+
+ if (ts == NULL)
+ return NULL;
+ X509_STORE_set_verify_cb(ts, X509_STORE_CTX_print_verify_cb);
+
+ /* copy vpm to store */
+ if (X509_STORE_set1_param(ts, vpm /* may be NULL */)
+ && (for_new_cert || truststore_set_host_etc(ts, NULL)))
+ return ts;
+ BIO_printf(bio_err, "error setting verification parameters for %s\n", desc);
+ OSSL_CMP_CTX_print_errors(cmp_ctx);
+ X509_STORE_free(ts);
+ return NULL;
+}
+
+typedef int (*add_X509_stack_fn_t)(void *ctx, const STACK_OF(X509) *certs);
+
+static int setup_certs(char *files, const char *desc, void *ctx,
+ add_X509_stack_fn_t set1_fn)
+{
+ STACK_OF(X509) *certs;
+ int ok;
+
+ if (files == NULL)
+ return 1;
+ if ((certs = load_certs_multifile(files, opt_otherpass, desc, vpm)) == NULL)
+ return 0;
+ ok = (*set1_fn)(ctx, certs);
+ sk_X509_pop_free(certs, X509_free);
+ return ok;
+}
+
+
+/*
+ * parse and transform some options, checking their syntax.
+ * Returns 1 on success, 0 on error
+ */
+static int transform_opts(void)
+{
+ if (opt_cmd_s != NULL) {
+ if (!strcmp(opt_cmd_s, "ir")) {
+ opt_cmd = CMP_IR;
+ } else if (!strcmp(opt_cmd_s, "kur")) {
+ opt_cmd = CMP_KUR;
+ } else if (!strcmp(opt_cmd_s, "cr")) {
+ opt_cmd = CMP_CR;
+ } else if (!strcmp(opt_cmd_s, "p10cr")) {
+ opt_cmd = CMP_P10CR;
+ } else if (!strcmp(opt_cmd_s, "rr")) {
+ opt_cmd = CMP_RR;
+ } else if (!strcmp(opt_cmd_s, "genm")) {
+ opt_cmd = CMP_GENM;
+ } else {
+ CMP_err1("unknown cmp command '%s'", opt_cmd_s);
+ return 0;
+ }
+ } else {
+ CMP_err("no cmp command to execute");
+ return 0;
+ }
+
+#ifndef OPENSSL_NO_ENGINE
+# define FORMAT_OPTIONS (OPT_FMT_PEMDER | OPT_FMT_PKCS12 | OPT_FMT_ENGINE)
+#else
+# define FORMAT_OPTIONS (OPT_FMT_PEMDER | OPT_FMT_PKCS12)
+#endif
+
+ if (opt_keyform_s != NULL
+ && !opt_format(opt_keyform_s, FORMAT_OPTIONS, &opt_keyform)) {
+ CMP_err("unknown option given for key loading format");
+ return 0;
+ }
+
+#undef FORMAT_OPTIONS
+
+ if (opt_certform_s != NULL
+ && !opt_format(opt_certform_s, OPT_FMT_PEMDER, &opt_certform)) {
+ CMP_err("unknown option given for certificate storing format");
+ return 0;
+ }
+
+ return 1;
+}
+
+static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
+{
+ OSSL_CMP_CTX *ctx; /* extra CMP (client) ctx partly used by server */
+ OSSL_CMP_SRV_CTX *srv_ctx = ossl_cmp_mock_srv_new(app_get0_libctx(),
+ app_get0_propq());
+
+ if (srv_ctx == NULL)
+ return NULL;
+ ctx = OSSL_CMP_SRV_CTX_get0_cmp_ctx(srv_ctx);
+
+ if (opt_srv_ref == NULL) {
+ if (opt_srv_cert == NULL) {
+ /* opt_srv_cert should determine the sender */
+ CMP_err("must give -srv_ref for mock server if no -srv_cert given");
+ goto err;
+ }
+ } else {
+ if (!OSSL_CMP_CTX_set1_referenceValue(ctx, (unsigned char *)opt_srv_ref,
+ strlen(opt_srv_ref)))
+ goto err;
+ }
+
+ if (opt_srv_secret != NULL) {
+ int res;
+ char *pass_str = get_passwd(opt_srv_secret, "PBMAC secret of mock server");
+
+ if (pass_str != NULL) {
+ cleanse(opt_srv_secret);
+ res = OSSL_CMP_CTX_set1_secretValue(ctx, (unsigned char *)pass_str,
+ strlen(pass_str));
+ clear_free(pass_str);
+ if (res == 0)
+ goto err;
+ }
+ } else if (opt_srv_cert == NULL) {
+ CMP_err("mock server credentials must be given if -use_mock_srv or -port is used");
+ goto err;
+ } else {
+ CMP_warn("mock server will not be able to handle PBM-protected requests since -srv_secret is not given");
+ }
+
+ if (opt_srv_secret == NULL
+ && ((opt_srv_cert == NULL) != (opt_srv_key == NULL))) {
+ CMP_err("must give both -srv_cert and -srv_key options or neither");
+ goto err;
+ }
+ if (opt_srv_cert != NULL) {
+ X509 *srv_cert = load_cert_pwd(opt_srv_cert, opt_srv_keypass,
+ "certificate of the mock server");
+
+ if (srv_cert == NULL || !OSSL_CMP_CTX_set1_cert(ctx, srv_cert)) {
+ X509_free(srv_cert);
+ goto err;
+ }
+ X509_free(srv_cert);
+ }
+ if (opt_srv_key != NULL) {
+ EVP_PKEY *pkey = load_key_pwd(opt_srv_key, opt_keyform,
+ opt_srv_keypass,
+ engine, "private key for mock server cert");
+
+ if (pkey == NULL || !OSSL_CMP_CTX_set1_pkey(ctx, pkey)) {
+ EVP_PKEY_free(pkey);
+ goto err;
+ }
+ EVP_PKEY_free(pkey);
+ }
+ cleanse(opt_srv_keypass);
+
+ if (opt_srv_trusted != NULL) {
+ X509_STORE *ts =
+ load_trusted(opt_srv_trusted, 0, "certs trusted by mock server");
+
+ if (ts == NULL || !OSSL_CMP_CTX_set0_trustedStore(ctx, ts)) {
+ X509_STORE_free(ts);
+ goto err;
+ }
+ } else {
+ CMP_warn("mock server will not be able to handle signature-protected requests since -srv_trusted is not given");
+ }
+ if (!setup_certs(opt_srv_untrusted,
+ "untrusted certificates for mock server", ctx,
+ (add_X509_stack_fn_t)OSSL_CMP_CTX_set1_untrusted))
+ goto err;
+
+ if (opt_rsp_cert == NULL) {
+ CMP_warn("no -rsp_cert given for mock server");
+ } else {
+ X509 *cert = load_cert_pwd(opt_rsp_cert, opt_keypass,
+ "cert to be returned by the mock server");
+
+ if (cert == NULL)
+ goto err;
+ /* from server perspective the server is the client */
+ if (!ossl_cmp_mock_srv_set1_certOut(srv_ctx, cert)) {
+ X509_free(cert);
+ goto err;
+ }
+ X509_free(cert);
+ }
+ if (!setup_certs(opt_rsp_extracerts,
+ "CMP extra certificates for mock server", srv_ctx,
+ (add_X509_stack_fn_t)ossl_cmp_mock_srv_set1_chainOut))
+ goto err;
+ if (!setup_certs(opt_rsp_capubs, "caPubs for mock server", srv_ctx,
+ (add_X509_stack_fn_t)ossl_cmp_mock_srv_set1_caPubsOut))
+ goto err;
+ (void)ossl_cmp_mock_srv_set_pollCount(srv_ctx, opt_poll_count);
+ (void)ossl_cmp_mock_srv_set_checkAfterTime(srv_ctx, opt_check_after);
+ if (opt_grant_implicitconf)
+ (void)OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(srv_ctx, 1);
+
+ if (opt_failure != INT_MIN) { /* option has been set explicity */
+ if (opt_failure < 0 || OSSL_CMP_PKIFAILUREINFO_MAX < opt_failure) {
+ CMP_err1("-failure out of range, should be >= 0 and <= %d",
+ OSSL_CMP_PKIFAILUREINFO_MAX);
+ goto err;
+ }
+ if (opt_failurebits != 0)
+ CMP_warn("-failurebits overrides -failure");
+ else
+ opt_failurebits = 1 << opt_failure;
+ }
+ if ((unsigned)opt_failurebits > OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN) {
+ CMP_err("-failurebits out of range");
+ goto err;
+ }
+ if (!ossl_cmp_mock_srv_set_statusInfo(srv_ctx, opt_pkistatus,
+ opt_failurebits, opt_statusstring))
+ goto err;
+
+ if (opt_send_error)
+ (void)ossl_cmp_mock_srv_set_send_error(srv_ctx, 1);
+
+ if (opt_send_unprotected)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_SEND, 1);
+ if (opt_send_unprot_err)
+ (void)OSSL_CMP_SRV_CTX_set_send_unprotected_errors(srv_ctx, 1);
+ if (opt_accept_unprotected)
+ (void)OSSL_CMP_SRV_CTX_set_accept_unprotected(srv_ctx, 1);
+ if (opt_accept_unprot_err)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS, 1);
+ if (opt_accept_raverified)
+ (void)OSSL_CMP_SRV_CTX_set_accept_raverified(srv_ctx, 1);
+
+ return srv_ctx;
+
+ err:
+ ossl_cmp_mock_srv_free(srv_ctx);
+ return NULL;
+}
+
+/*
+ * set up verification aspects of OSSL_CMP_CTX w.r.t. opts from config file/CLI.
+ * Returns pointer on success, NULL on error
+ */
+static int setup_verification_ctx(OSSL_CMP_CTX *ctx)
+{
+ if (!setup_certs(opt_untrusted, "untrusted certificates", ctx,
+ (add_X509_stack_fn_t)OSSL_CMP_CTX_set1_untrusted))
+ return 0;
+
+ if (opt_srvcert != NULL || opt_trusted != NULL) {
+ X509 *srvcert;
+ X509_STORE *ts;
+ int ok;
+
+ if (opt_srvcert != NULL) {
+ if (opt_trusted != NULL) {
+ CMP_warn("-trusted option is ignored since -srvcert option is present");
+ opt_trusted = NULL;
+ }
+ if (opt_recipient != NULL) {
+ CMP_warn("-recipient option is ignored since -srvcert option is present");
+ opt_recipient = NULL;
+ }
+ srvcert = load_cert_pwd(opt_srvcert, opt_otherpass,
+ "directly trusted CMP server certificate");
+ ok = srvcert != NULL && OSSL_CMP_CTX_set1_srvCert(ctx, srvcert);
+ X509_free(srvcert);
+ if (!ok)
+ return 0;
+ }
+ if (opt_trusted != NULL) {
+ /*
+ * the 0 arg below clears any expected host/ip/email address;
+ * opt_expect_sender is used instead
+ */
+ ts = load_trusted(opt_trusted, 0, "certs trusted by client");
+
+ if (ts == NULL || !OSSL_CMP_CTX_set0_trustedStore(ctx, ts)) {
+ X509_STORE_free(ts);
+ return 0;
+ }
+ }
+ }
+
+ if (opt_ignore_keyusage)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_IGNORE_KEYUSAGE, 1);
+
+ if (opt_unprotected_errors)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS, 1);
+
+ if (opt_out_trusted != NULL) { /* for use in OSSL_CMP_certConf_cb() */
+ X509_VERIFY_PARAM *out_vpm = NULL;
+ X509_STORE *out_trusted =
+ load_trusted(opt_out_trusted, 1,
+ "trusted certs for verifying newly enrolled cert");
+
+ if (out_trusted == NULL)
+ return 0;
+ /* ignore any -attime here, new certs are current anyway */
+ out_vpm = X509_STORE_get0_param(out_trusted);
+ X509_VERIFY_PARAM_clear_flags(out_vpm, X509_V_FLAG_USE_CHECK_TIME);
+
+ (void)OSSL_CMP_CTX_set_certConf_cb_arg(ctx, out_trusted);
+ }
+
+ if (opt_disable_confirm)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_DISABLE_CONFIRM, 1);
+
+ if (opt_implicit_confirm)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM, 1);
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_SOCK
+/*
+ * set up ssl_ctx for the OSSL_CMP_CTX based on options from config file/CLI.
+ * Returns pointer on success, NULL on error
+ */
+static SSL_CTX *setup_ssl_ctx(OSSL_CMP_CTX *ctx, const char *host,
+ ENGINE *engine)
+{
+ STACK_OF(X509) *untrusted = OSSL_CMP_CTX_get0_untrusted(ctx);
+ EVP_PKEY *pkey = NULL;
+ X509_STORE *trust_store = NULL;
+ SSL_CTX *ssl_ctx;
+ int i;
+
+ ssl_ctx = SSL_CTX_new(TLS_client_method());
+ if (ssl_ctx == NULL)
+ return NULL;
+
+ if (opt_tls_trusted != NULL) {
+ trust_store = load_trusted(opt_tls_trusted, 0, "trusted TLS certs");
+ if (trust_store == NULL)
+ goto err;
+ SSL_CTX_set_cert_store(ssl_ctx, trust_store);
+ }
+
+ if (opt_tls_cert != NULL && opt_tls_key != NULL) {
+ X509 *cert;
+ STACK_OF(X509) *certs = NULL;
+ int ok;
+
+ if (!load_cert_certs(opt_tls_cert, &cert, &certs, 0, opt_tls_keypass,
+ "TLS client certificate (optionally with chain)",
+ vpm))
+ /* need opt_tls_keypass if opt_tls_cert is encrypted PKCS#12 file */
+ goto err;
+
+ ok = SSL_CTX_use_certificate(ssl_ctx, cert) > 0;
+ X509_free(cert);
+
+ /*
+ * Any further certs and any untrusted certs are used for constructing
+ * the chain to be provided with the TLS client cert to the TLS server.
+ */
+ if (!ok || !SSL_CTX_set0_chain(ssl_ctx, certs)) {
+ CMP_err1("unable to use client TLS certificate file '%s'",
+ opt_tls_cert);
+ sk_X509_pop_free(certs, X509_free);
+ goto err;
+ }
+ for (i = 0; i < sk_X509_num(untrusted); i++) {
+ cert = sk_X509_value(untrusted, i);
+ if (!SSL_CTX_add1_chain_cert(ssl_ctx, cert)) {
+ CMP_err("could not add untrusted cert to TLS client cert chain");
+ goto err;
+ }
+ }
+
+ {
+ X509_VERIFY_PARAM *tls_vpm = NULL;
+ unsigned long bak_flags = 0; /* compiler warns without init */
+
+ if (trust_store != NULL) {
+ tls_vpm = X509_STORE_get0_param(trust_store);
+ bak_flags = X509_VERIFY_PARAM_get_flags(tls_vpm);
+ /* disable any cert status/revocation checking etc. */
+ X509_VERIFY_PARAM_clear_flags(tls_vpm,
+ ~(X509_V_FLAG_USE_CHECK_TIME
+ | X509_V_FLAG_NO_CHECK_TIME));
+ }
+ CMP_debug("trying to build cert chain for own TLS cert");
+ if (SSL_CTX_build_cert_chain(ssl_ctx,
+ SSL_BUILD_CHAIN_FLAG_UNTRUSTED |
+ SSL_BUILD_CHAIN_FLAG_NO_ROOT)) {
+ CMP_debug("success building cert chain for own TLS cert");
+ } else {
+ OSSL_CMP_CTX_print_errors(ctx);
+ CMP_warn("could not build cert chain for own TLS cert");
+ }
+ if (trust_store != NULL)
+ X509_VERIFY_PARAM_set_flags(tls_vpm, bak_flags);
+ }
+
+ /* If present we append to the list also the certs from opt_tls_extra */
+ if (opt_tls_extra != NULL) {
+ STACK_OF(X509) *tls_extra = load_certs_multifile(opt_tls_extra,
+ opt_otherpass,
+ "extra certificates for TLS",
+ vpm);
+ int res = 1;
+
+ if (tls_extra == NULL)
+ goto err;
+ for (i = 0; i < sk_X509_num(tls_extra); i++) {
+ cert = sk_X509_value(tls_extra, i);
+ if (res != 0)
+ res = SSL_CTX_add_extra_chain_cert(ssl_ctx, cert);
+ if (res == 0)
+ X509_free(cert);
+ }
+ sk_X509_free(tls_extra);
+ if (res == 0) {
+ BIO_printf(bio_err, "error: unable to add TLS extra certs\n");
+ goto err;
+ }
+ }
+
+ pkey = load_key_pwd(opt_tls_key, opt_keyform, opt_tls_keypass,
+ engine, "TLS client private key");
+ cleanse(opt_tls_keypass);
+ if (pkey == NULL)
+ goto err;
+ /*
+ * verify the key matches the cert,
+ * not using SSL_CTX_check_private_key(ssl_ctx)
+ * because it gives poor and sometimes misleading diagnostics
+ */
+ if (!X509_check_private_key(SSL_CTX_get0_certificate(ssl_ctx),
+ pkey)) {
+ CMP_err2("TLS private key '%s' does not match the TLS certificate '%s'\n",
+ opt_tls_key, opt_tls_cert);
+ EVP_PKEY_free(pkey);
+ pkey = NULL; /* otherwise, for some reason double free! */
+ goto err;
+ }
+ if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) <= 0) {
+ CMP_err1("unable to use TLS client private key '%s'", opt_tls_key);
+ EVP_PKEY_free(pkey);
+ pkey = NULL; /* otherwise, for some reason double free! */
+ goto err;
+ }
+ EVP_PKEY_free(pkey); /* we do not need the handle any more */
+ }
+ if (opt_tls_trusted != NULL) {
+ /* enable and parameterize server hostname/IP address check */
+ if (!truststore_set_host_etc(trust_store,
+ opt_tls_host != NULL ? opt_tls_host : host))
+ goto err;
+ SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
+ }
+ return ssl_ctx;
+ err:
+ SSL_CTX_free(ssl_ctx);
+ return NULL;
+}
+#endif /* OPENSSL_NO_SOCK */
+
+/*
+ * set up protection aspects of OSSL_CMP_CTX based on options from config
+ * file/CLI while parsing options and checking their consistency.
+ * Returns 1 on success, 0 on error
+ */
+static int setup_protection_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
+{
+ if (!opt_unprotected_requests && opt_secret == NULL && opt_key == NULL) {
+ CMP_err("must give -key or -secret unless -unprotected_requests is used");
+ return 0;
+ }
+
+ if (opt_ref == NULL && opt_cert == NULL && opt_subject == NULL) {
+ /* cert or subject should determine the sender */
+ CMP_err("must give -ref if no -cert and no -subject given");
+ return 0;
+ }
+ if (!opt_secret && ((opt_cert == NULL) != (opt_key == NULL))) {
+ CMP_err("must give both -cert and -key options or neither");
+ return 0;
+ }
+ if (opt_secret != NULL) {
+ char *pass_string = get_passwd(opt_secret, "PBMAC");
+ int res;
+
+ if (pass_string != NULL) {
+ cleanse(opt_secret);
+ res = OSSL_CMP_CTX_set1_secretValue(ctx,
+ (unsigned char *)pass_string,
+ strlen(pass_string));
+ clear_free(pass_string);
+ if (res == 0)
+ return 0;
+ }
+ if (opt_cert != NULL || opt_key != NULL)
+ CMP_warn("-cert and -key not used for protection since -secret is given");
+ }
+ if (opt_ref != NULL
+ && !OSSL_CMP_CTX_set1_referenceValue(ctx, (unsigned char *)opt_ref,
+ strlen(opt_ref)))
+ return 0;
+
+ if (opt_key != NULL) {
+ EVP_PKEY *pkey = load_key_pwd(opt_key, opt_keyform, opt_keypass, engine,
+ "private key for CMP client certificate");
+
+ if (pkey == NULL || !OSSL_CMP_CTX_set1_pkey(ctx, pkey)) {
+ EVP_PKEY_free(pkey);
+ return 0;
+ }
+ EVP_PKEY_free(pkey);
+ }
+ if (opt_secret == NULL && opt_srvcert == NULL && opt_trusted == NULL)
+ CMP_warn("will not authenticate server due to missing -secret, -trusted, or -srvcert");
+
+ if (opt_cert != NULL) {
+ X509 *cert;
+ STACK_OF(X509) *certs = NULL;
+ X509_STORE *own_trusted = NULL;
+ int ok;
+
+ if (!load_cert_certs(opt_cert, &cert, &certs, 0, opt_keypass,
+ "CMP client certificate (optionally with chain)",
+ vpm))
+ /* opt_keypass is needed if opt_cert is an encrypted PKCS#12 file */
+ return 0;
+ ok = OSSL_CMP_CTX_set1_cert(ctx, cert);
+ X509_free(cert);
+ if (!ok) {
+ CMP_err("out of memory");
+ } else {
+ if (opt_own_trusted != NULL) {
+ own_trusted = load_trusted(opt_own_trusted, 0,
+ "trusted certs for verifying own CMP signer cert");
+ ok = own_trusted != NULL;
+ }
+ ok = ok && OSSL_CMP_CTX_build_cert_chain(ctx, own_trusted, certs);
+ }
+ X509_STORE_free(own_trusted);
+ sk_X509_pop_free(certs, X509_free);
+ if (!ok)
+ return 0;
+ } else if (opt_own_trusted != NULL) {
+ CMP_warn("-own_trusted option is ignored without -cert");
+ }
+
+ if (!setup_certs(opt_extracerts, "extra certificates for CMP", ctx,
+ (add_X509_stack_fn_t)OSSL_CMP_CTX_set1_extraCertsOut))
+ return 0;
+ cleanse(opt_otherpass);
+
+ if (opt_unprotected_requests)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_SEND, 1);
+
+ if (opt_digest != NULL) {
+ int digest = OBJ_ln2nid(opt_digest);
+
+ if (digest == NID_undef) {
+ CMP_err1("digest algorithm name not recognized: '%s'", opt_digest);
+ return 0;
+ }
+ if (!OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_DIGEST_ALGNID, digest)
+ || !OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_OWF_ALGNID, digest)) {
+ CMP_err1("digest algorithm name not supported: '%s'", opt_digest);
+ return 0;
+ }
+ }
+
+ if (opt_mac != NULL) {
+ int mac = OBJ_ln2nid(opt_mac);
+ if (mac == NID_undef) {
+ CMP_err1("MAC algorithm name not recognized: '%s'", opt_mac);
+ return 0;
+ }
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_MAC_ALGNID, mac);
+ }
+ return 1;
+}
+
+/*
+ * set up IR/CR/KUR/CertConf/RR specific parts of the OSSL_CMP_CTX
+ * based on options from config file/CLI.
+ * Returns pointer on success, NULL on error
+ */
+static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
+{
+ X509_REQ *csr = NULL;
+ X509_EXTENSIONS *exts = NULL;
+ X509V3_CTX ext_ctx;
+
+ if (opt_subject == NULL
+ && opt_csr == NULL && opt_oldcert == NULL && opt_cert == NULL
+ && opt_cmd != CMP_RR && opt_cmd != CMP_GENM)
+ CMP_warn("no -subject given; no -csr or -oldcert or -cert available for fallback");
+
+ if (opt_cmd == CMP_IR || opt_cmd == CMP_CR || opt_cmd == CMP_KUR) {
+ if (opt_newkey == NULL && opt_key == NULL && opt_csr == NULL) {
+ CMP_err("missing -newkey (or -key) to be certified and no -csr given");
+ return 0;
+ }
+ if (opt_certout == NULL) {
+ CMP_err("-certout not given, nowhere to save newly enrolled certificate");
+ return 0;
+ }
+ if (!set_name(opt_subject, OSSL_CMP_CTX_set1_subjectName, ctx, "subject")
+ || !set_name(opt_issuer, OSSL_CMP_CTX_set1_issuer, ctx, "issuer"))
+ return 0;
+ } else {
+ const char *msg = "option is ignored for commands other than 'ir', 'cr', and 'kur'";
+
+ if (opt_subject != NULL) {
+ if (opt_ref == NULL && opt_cert == NULL) {
+ /* use subject as default sender unless oldcert subject is used */
+ if (!set_name(opt_subject, OSSL_CMP_CTX_set1_subjectName, ctx, "subject"))
+ return 0;
+ } else {
+ CMP_warn1("-subject %s since -ref or -cert is given", msg);
+ }
+ }
+ if (opt_issuer != NULL)
+ CMP_warn1("-issuer %s", msg);
+ if (opt_reqexts != NULL)
+ CMP_warn1("-reqexts %s", msg);
+ if (opt_san_nodefault)
+ CMP_warn1("-san_nodefault %s", msg);
+ if (opt_sans != NULL)
+ CMP_warn1("-sans %s", msg);
+ if (opt_policies != NULL)
+ CMP_warn1("-policies %s", msg);
+ if (opt_policy_oids != NULL)
+ CMP_warn1("-policy_oids %s", msg);
+ }
+ if (opt_cmd == CMP_KUR) {
+ char *ref_cert = opt_oldcert != NULL ? opt_oldcert : opt_cert;
+
+ if (ref_cert == NULL && opt_csr == NULL) {
+ CMP_err("missing -oldcert for certificate to be updated and no -csr given");
+ return 0;
+ }
+ if (opt_subject != NULL)
+ CMP_warn2("given -subject '%s' overrides the subject of '%s' for KUR",
+ opt_subject, ref_cert != NULL ? ref_cert : opt_csr);
+ }
+ if (opt_cmd == CMP_RR) {
+ if (opt_oldcert == NULL && opt_csr == NULL) {
+ CMP_err("missing -oldcert for certificate to be revoked and no -csr given");
+ return 0;
+ }
+ if (opt_oldcert != NULL && opt_csr != NULL)
+ CMP_warn("ignoring -csr since certificate to be revoked is given");
+ }
+ if (opt_cmd == CMP_P10CR && opt_csr == NULL) {
+ CMP_err("missing PKCS#10 CSR for p10cr");
+ return 0;
+ }
+
+ if (opt_recipient == NULL && opt_srvcert == NULL && opt_issuer == NULL
+ && opt_oldcert == NULL && opt_cert == NULL)
+ CMP_warn("missing -recipient, -srvcert, -issuer, -oldcert or -cert; recipient will be set to \"NULL-DN\"");
+
+ if (opt_cmd == CMP_P10CR || opt_cmd == CMP_RR) {
+ const char *msg = "option is ignored for 'p10cr' and 'rr' commands";
+
+ if (opt_newkeypass != NULL)
+ CMP_warn1("-newkeytype %s", msg);
+ if (opt_newkey != NULL)
+ CMP_warn1("-newkey %s", msg);
+ if (opt_days != 0)
+ CMP_warn1("-days %s", msg);
+ if (opt_popo != OSSL_CRMF_POPO_NONE - 1)
+ CMP_warn1("-popo %s", msg);
+ } else if (opt_newkey != NULL) {
+ const char *file = opt_newkey;
+ const int format = opt_keyform;
+ const char *pass = opt_newkeypass;
+ const char *desc = "new private key for cert to be enrolled";
+ EVP_PKEY *pkey;
+ int priv = 1;
+ BIO *bio_bak = bio_err;
+
+ bio_err = NULL; /* suppress diagnostics on first try loading key */
+ pkey = load_key_pwd(file, format, pass, engine, desc);
+ bio_err = bio_bak;
+ if (pkey == NULL) {
+ ERR_clear_error();
+ desc = opt_csr == NULL
+ ? "fallback public key for cert to be enrolled"
+ : "public key for checking cert resulting from p10cr";
+ pkey = load_pubkey(file, format, 0, pass, engine, desc);
+ priv = 0;
+ }
+ cleanse(opt_newkeypass);
+ if (pkey == NULL || !OSSL_CMP_CTX_set0_newPkey(ctx, priv, pkey)) {
+ EVP_PKEY_free(pkey);
+ return 0;
+ }
+ }
+
+ if (opt_days > 0
+ && !OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_VALIDITY_DAYS,
+ opt_days)) {
+ CMP_err("could not set requested cert validity period");
+ return 0;
+ }
+
+ if (opt_policies != NULL && opt_policy_oids != NULL) {
+ CMP_err("cannot have policies both via -policies and via -policy_oids");
+ return 0;
+ }
+
+ if (opt_csr != NULL) {
+ if (opt_cmd == CMP_GENM) {
+ CMP_warn("-csr option is ignored for command 'genm'");
+ } else {
+ if ((csr = load_csr_autofmt(opt_csr, "PKCS#10 CSR")) == NULL)
+ return 0;
+ if (!OSSL_CMP_CTX_set1_p10CSR(ctx, csr))
+ goto oom;
+ }
+ }
+ if (opt_reqexts != NULL || opt_policies != NULL) {
+ if ((exts = sk_X509_EXTENSION_new_null()) == NULL)
+ goto oom;
+ X509V3_set_ctx(&ext_ctx, NULL, NULL, csr, NULL, X509V3_CTX_REPLACE);
+ X509V3_set_nconf(&ext_ctx, conf);
+ if (opt_reqexts != NULL
+ && !X509V3_EXT_add_nconf_sk(conf, &ext_ctx, opt_reqexts, &exts)) {
+ CMP_err1("cannot load certificate request extension section '%s'",
+ opt_reqexts);
+ goto exts_err;
+ }
+ if (opt_policies != NULL
+ && !X509V3_EXT_add_nconf_sk(conf, &ext_ctx, opt_policies, &exts)) {
+ CMP_err1("cannot load policy cert request extension section '%s'",
+ opt_policies);
+ goto exts_err;
+ }
+ OSSL_CMP_CTX_set0_reqExtensions(ctx, exts);
+ }
+ X509_REQ_free(csr);
+ /* After here, must not goto oom/exts_err */
+
+ if (OSSL_CMP_CTX_reqExtensions_have_SAN(ctx) && opt_sans != NULL) {
+ CMP_err("cannot have Subject Alternative Names both via -reqexts and via -sans");
+ return 0;
+ }
+ if (!set_gennames(ctx, opt_sans, "Subject Alternative Name"))
+ return 0;
+
+ if (opt_san_nodefault) {
+ if (opt_sans != NULL)
+ CMP_warn("-opt_san_nodefault has no effect when -sans is used");
+ (void)OSSL_CMP_CTX_set_option(ctx,
+ OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT, 1);
+ }
+
+ if (opt_policy_oids_critical) {
+ if (opt_policy_oids == NULL)
+ CMP_warn("-opt_policy_oids_critical has no effect unless -policy_oids is given");
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_POLICIES_CRITICAL, 1);
+ }
+
+ while (opt_policy_oids != NULL) {
+ ASN1_OBJECT *policy;
+ POLICYINFO *pinfo;
+ char *next = next_item(opt_policy_oids);
+
+ if ((policy = OBJ_txt2obj(opt_policy_oids, 1)) == 0) {
+ CMP_err1("unknown policy OID '%s'", opt_policy_oids);
+ return 0;
+ }
+
+ if ((pinfo = POLICYINFO_new()) == NULL) {
+ ASN1_OBJECT_free(policy);
+ return 0;
+ }
+ pinfo->policyid = policy;
+
+ if (!OSSL_CMP_CTX_push0_policy(ctx, pinfo)) {
+ CMP_err1("cannot add policy with OID '%s'", opt_policy_oids);
+ POLICYINFO_free(pinfo);
+ return 0;
+ }
+ opt_policy_oids = next;
+ }
+
+ if (opt_popo >= OSSL_CRMF_POPO_NONE)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_POPO_METHOD, opt_popo);
+
+ if (opt_oldcert != NULL) {
+ if (opt_cmd == CMP_GENM) {
+ CMP_warn("-oldcert option is ignored for command 'genm'");
+ } else {
+ X509 *oldcert = load_cert_pwd(opt_oldcert, opt_keypass,
+ opt_cmd == CMP_KUR ?
+ "certificate to be updated" :
+ opt_cmd == CMP_RR ?
+ "certificate to be revoked" :
+ "reference certificate (oldcert)");
+ /* opt_keypass needed if opt_oldcert is an encrypted PKCS#12 file */
+
+ if (oldcert == NULL)
+ return 0;
+ if (!OSSL_CMP_CTX_set1_oldCert(ctx, oldcert)) {
+ X509_free(oldcert);
+ CMP_err("out of memory");
+ return 0;
+ }
+ X509_free(oldcert);
+ }
+ }
+ cleanse(opt_keypass);
+ if (opt_revreason > CRL_REASON_NONE)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_REVOCATION_REASON,
+ opt_revreason);
+
+ return 1;
+
+ oom:
+ CMP_err("out of memory");
+ exts_err:
+ sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+ X509_REQ_free(csr);
+ return 0;
+}
+
+static int handle_opt_geninfo(OSSL_CMP_CTX *ctx)
+{
+ long value;
+ ASN1_OBJECT *type;
+ ASN1_INTEGER *aint;
+ ASN1_TYPE *val;
+ OSSL_CMP_ITAV *itav;
+ char *endstr;
+ char *valptr = strchr(opt_geninfo, ':');
+
+ if (valptr == NULL) {
+ CMP_err("missing ':' in -geninfo option");
+ return 0;
+ }
+ valptr[0] = '\0';
+ valptr++;
+
+ if (OPENSSL_strncasecmp(valptr, "int:", 4) != 0) {
+ CMP_err("missing 'int:' in -geninfo option");
+ return 0;
+ }
+ valptr += 4;
+
+ value = strtol(valptr, &endstr, 10);
+ if (endstr == valptr || *endstr != '\0') {
+ CMP_err("cannot parse int in -geninfo option");
+ return 0;
+ }
+
+ type = OBJ_txt2obj(opt_geninfo, 1);
+ if (type == NULL) {
+ CMP_err("cannot parse OID in -geninfo option");
+ return 0;
+ }
+
+ if ((aint = ASN1_INTEGER_new()) == NULL)
+ goto oom;
+
+ val = ASN1_TYPE_new();
+ if (!ASN1_INTEGER_set(aint, value) || val == NULL) {
+ ASN1_INTEGER_free(aint);
+ goto oom;
+ }
+ ASN1_TYPE_set(val, V_ASN1_INTEGER, aint);
+ itav = OSSL_CMP_ITAV_create(type, val);
+ if (itav == NULL) {
+ ASN1_TYPE_free(val);
+ goto oom;
+ }
+
+ if (!OSSL_CMP_CTX_push0_geninfo_ITAV(ctx, itav)) {
+ OSSL_CMP_ITAV_free(itav);
+ return 0;
+ }
+ return 1;
+
+ oom:
+ ASN1_OBJECT_free(type);
+ CMP_err("out of memory");
+ return 0;
+}
+
+
+/*
+ * set up the client-side OSSL_CMP_CTX based on options from config file/CLI
+ * while parsing options and checking their consistency.
+ * Prints reason for error to bio_err.
+ * Returns 1 on success, 0 on error
+ */
+static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
+{
+ int ret = 0;
+ char *host = NULL, *port = NULL, *path = NULL, *used_path = opt_path;
+#ifndef OPENSSL_NO_SOCK
+ int portnum, ssl;
+ static char server_port[32] = { '\0' };
+ const char *proxy_host = NULL;
+#endif
+ char server_buf[200] = "mock server";
+ char proxy_buf[200] = "";
+
+ if (!opt_use_mock_srv && opt_rspin == NULL) { /* note: -port is not given */
+#ifndef OPENSSL_NO_SOCK
+ if (opt_server == NULL) {
+ CMP_err("missing -server or -use_mock_srv or -rspin option");
+ goto err;
+ }
+#else
+ CMP_err("missing -use_mock_srv or -rspin option; -server option is not supported due to no-sock build");
+ goto err;
+#endif
+ }
+#ifndef OPENSSL_NO_SOCK
+ if (opt_server == NULL) {
+ if (opt_proxy != NULL)
+ CMP_warn("ignoring -proxy option since -server is not given");
+ if (opt_no_proxy != NULL)
+ CMP_warn("ignoring -no_proxy option since -server is not given");
+ if (opt_tls_used) {
+ CMP_warn("ignoring -tls_used option since -server is not given");
+ opt_tls_used = 0;
+ }
+ goto set_path;
+ }
+ if (!OSSL_HTTP_parse_url(opt_server, &ssl, NULL /* user */, &host, &port,
+ &portnum, &path, NULL /* q */, NULL /* frag */)) {
+ CMP_err1("cannot parse -server URL: %s", opt_server);
+ goto err;
+ }
+ if (ssl && !opt_tls_used) {
+ CMP_err("missing -tls_used option since -server URL indicates https");
+ goto err;
+ }
+
+ BIO_snprintf(server_port, sizeof(server_port), "%s", port);
+ if (opt_path == NULL)
+ used_path = path;
+ if (!OSSL_CMP_CTX_set1_server(ctx, host)
+ || !OSSL_CMP_CTX_set_serverPort(ctx, portnum))
+ goto oom;
+ if (opt_proxy != NULL && !OSSL_CMP_CTX_set1_proxy(ctx, opt_proxy))
+ goto oom;
+ if (opt_no_proxy != NULL && !OSSL_CMP_CTX_set1_no_proxy(ctx, opt_no_proxy))
+ goto oom;
+ (void)BIO_snprintf(server_buf, sizeof(server_buf), "http%s://%s:%s/%s",
+ opt_tls_used ? "s" : "", host, port,
+ *used_path == '/' ? used_path + 1 : used_path);
+
+ proxy_host = OSSL_HTTP_adapt_proxy(opt_proxy, opt_no_proxy, host, ssl);
+ if (proxy_host != NULL)
+ (void)BIO_snprintf(proxy_buf, sizeof(proxy_buf), " via %s", proxy_host);
+
+ set_path:
+#endif
+
+ if (!OSSL_CMP_CTX_set1_serverPath(ctx, used_path))
+ goto oom;
+ if (!transform_opts())
+ goto err;
+
+ if (opt_infotype_s != NULL) {
+ char id_buf[100] = "id-it-";
+
+ strncat(id_buf, opt_infotype_s, sizeof(id_buf) - strlen(id_buf) - 1);
+ if ((opt_infotype = OBJ_sn2nid(id_buf)) == NID_undef) {
+ CMP_err("unknown OID name in -infotype option");
+ goto err;
+ }
+ }
+
+ if (!setup_verification_ctx(ctx))
+ goto err;
+
+ if (opt_keep_alive != 1)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_KEEP_ALIVE,
+ opt_keep_alive);
+ if (opt_total_timeout > 0 && opt_msg_timeout > 0
+ && opt_total_timeout < opt_msg_timeout) {
+ CMP_err2("-total_timeout argument = %d must not be < %d (-msg_timeout)",
+ opt_total_timeout, opt_msg_timeout);
+ goto err;
+ }
+ if (opt_msg_timeout >= 0) /* must do this before setup_ssl_ctx() */
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_MSG_TIMEOUT,
+ opt_msg_timeout);
+ if (opt_total_timeout >= 0)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_TOTAL_TIMEOUT,
+ opt_total_timeout);
+
+ if (opt_reqin != NULL && opt_rspin != NULL)
+ CMP_warn("-reqin is ignored since -rspin is present");
+ if (opt_reqin_new_tid && opt_reqin == NULL)
+ CMP_warn("-reqin_new_tid is ignored since -reqin is not present");
+ if (opt_reqin != NULL || opt_reqout != NULL
+ || opt_rspin != NULL || opt_rspout != NULL || opt_use_mock_srv)
+ (void)OSSL_CMP_CTX_set_transfer_cb(ctx, read_write_req_resp);
+
+#ifndef OPENSSL_NO_SOCK
+ if (opt_tls_used) {
+ APP_HTTP_TLS_INFO *info;
+
+ if (opt_tls_cert != NULL
+ || opt_tls_key != NULL || opt_tls_keypass != NULL) {
+ if (opt_tls_key == NULL) {
+ CMP_err("missing -tls_key option");
+ goto err;
+ } else if (opt_tls_cert == NULL) {
+ CMP_err("missing -tls_cert option");
+ goto err;
+ }
+ }
+
+ if ((info = OPENSSL_zalloc(sizeof(*info))) == NULL)
+ goto err;
+ (void)OSSL_CMP_CTX_set_http_cb_arg(ctx, info);
+ info->server = opt_server;
+ info->port = server_port;
+ /* workaround for callback design flaw, see #17088: */
+ info->use_proxy = proxy_host != NULL;
+ info->timeout = OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_MSG_TIMEOUT);
+ info->ssl_ctx = setup_ssl_ctx(ctx, host, engine);
+
+ if (info->ssl_ctx == NULL)
+ goto err;
+ (void)OSSL_CMP_CTX_set_http_cb(ctx, app_http_tls_cb);
+ }
+#endif
+
+ if (!setup_protection_ctx(ctx, engine))
+ goto err;
+
+ if (!setup_request_ctx(ctx, engine))
+ goto err;
+
+ if (!set_name(opt_recipient, OSSL_CMP_CTX_set1_recipient, ctx, "recipient")
+ || !set_name(opt_expect_sender, OSSL_CMP_CTX_set1_expected_sender,
+ ctx, "expected sender"))
+ goto err;
+
+ if (opt_geninfo != NULL && !handle_opt_geninfo(ctx))
+ goto err;
+
+ /* not printing earlier, to minimize confusion in case setup fails before */
+ if (opt_rspin != NULL)
+ CMP_info("will not contact any server since -rspin is given");
+ else
+ CMP_info2("will contact %s%s", server_buf, proxy_buf);
+
+ ret = 1;
+
+ err:
+ OPENSSL_free(host);
+ OPENSSL_free(port);
+ OPENSSL_free(path);
+ return ret;
+ oom:
+ CMP_err("out of memory");
+ goto err;
+}
+
+/*
+ * write out the given certificate to the output specified by bio.
+ * Depending on options use either PEM or DER format.
+ * Returns 1 on success, 0 on error
+ */
+static int write_cert(BIO *bio, X509 *cert)
+{
+ if ((opt_certform == FORMAT_PEM && PEM_write_bio_X509(bio, cert))
+ || (opt_certform == FORMAT_ASN1 && i2d_X509_bio(bio, cert)))
+ return 1;
+ if (opt_certform != FORMAT_PEM && opt_certform != FORMAT_ASN1)
+ BIO_printf(bio_err,
+ "error: unsupported type '%s' for writing certificates\n",
+ opt_certform_s);
+ return 0;
+}
+
+/*
+ * If destFile != NULL writes out a stack of certs to the given file.
+ * In any case frees the certs.
+ * Depending on options use either PEM or DER format,
+ * where DER does not make much sense for writing more than one cert!
+ * Returns number of written certificates on success, -1 on error.
+ */
+static int save_free_certs(OSSL_CMP_CTX *ctx,
+ STACK_OF(X509) *certs, char *destFile, char *desc)
+{
+ BIO *bio = NULL;
+ int i;
+ int n = sk_X509_num(certs);
+
+ if (destFile == NULL)
+ goto end;
+ CMP_info3("received %d %s certificate(s), saving to file '%s'",
+ n, desc, destFile);
+ if (n > 1 && opt_certform != FORMAT_PEM)
+ CMP_warn("saving more than one certificate in non-PEM format");
+
+ if (destFile == NULL || (bio = BIO_new(BIO_s_file())) == NULL
+ || !BIO_write_filename(bio, (char *)destFile)) {
+ CMP_err1("could not open file '%s' for writing", destFile);
+ n = -1;
+ goto end;
+ }
+
+ for (i = 0; i < n; i++) {
+ if (!write_cert(bio, sk_X509_value(certs, i))) {
+ CMP_err1("cannot write certificate to file '%s'", destFile);
+ n = -1;
+ goto end;
+ }
+ }
+
+ end:
+ BIO_free(bio);
+ sk_X509_pop_free(certs, X509_free);
+ return n;
+}
+
+static void print_itavs(STACK_OF(OSSL_CMP_ITAV) *itavs)
+{
+ OSSL_CMP_ITAV *itav = NULL;
+ char buf[128];
+ int i, r;
+ int n = sk_OSSL_CMP_ITAV_num(itavs); /* itavs == NULL leads to 0 */
+
+ if (n == 0) {
+ CMP_info("genp contains no ITAV");
+ return;
+ }
+
+ for (i = 0; i < n; i++) {
+ itav = sk_OSSL_CMP_ITAV_value(itavs, i);
+ r = OBJ_obj2txt(buf, 128, OSSL_CMP_ITAV_get0_type(itav), 0);
+ if (r < 0)
+ CMP_err("could not get ITAV details");
+ else if (r == 0)
+ CMP_info("genp contains empty ITAV");
+ else
+ CMP_info1("genp contains ITAV of type: %s", buf);
+ }
+}
+
+static char opt_item[SECTION_NAME_MAX + 1];
+/* get previous name from a comma or space-separated list of names */
+static const char *prev_item(const char *opt, const char *end)
+{
+ const char *beg;
+ size_t len;
+
+ if (end == opt)
+ return NULL;
+ beg = end;
+ while (beg > opt) {
+ --beg;
+ if (beg[0] == ',' || isspace(beg[0])) {
+ ++beg;
+ break;
+ }
+ }
+ len = end - beg;
+ if (len > SECTION_NAME_MAX) {
+ CMP_warn3("using only first %d characters of section name starting with \"%.*s\"",
+ SECTION_NAME_MAX, SECTION_NAME_MAX, beg);
+ len = SECTION_NAME_MAX;
+ }
+ memcpy(opt_item, beg, len);
+ opt_item[len] = '\0';
+ while (beg > opt) {
+ --beg;
+ if (beg[0] != ',' && !isspace(beg[0])) {
+ ++beg;
+ break;
+ }
+ }
+ return beg;
+}
+
+/* get str value for name from a comma-separated hierarchy of config sections */
+static char *conf_get_string(const CONF *src_conf, const char *groups,
+ const char *name)
+{
+ char *res = NULL;
+ const char *end = groups + strlen(groups);
+
+ while ((end = prev_item(groups, end)) != NULL) {
+ if ((res = NCONF_get_string(src_conf, opt_item, name)) != NULL)
+ return res;
+ }
+ return res;
+}
+
+/* get long val for name from a comma-separated hierarchy of config sections */
+static int conf_get_number_e(const CONF *conf_, const char *groups,
+ const char *name, long *result)
+{
+ char *str = conf_get_string(conf_, groups, name);
+ char *tailptr;
+ long res;
+
+ if (str == NULL || *str == '\0')
+ return 0;
+
+ res = strtol(str, &tailptr, 10);
+ if (res == LONG_MIN || res == LONG_MAX || *tailptr != '\0')
+ return 0;
+
+ *result = res;
+ return 1;
+}
+
+/*
+ * use the command line option table to read values from the CMP section
+ * of openssl.cnf. Defaults are taken from the config file, they can be
+ * overwritten on the command line.
+ */
+static int read_config(void)
+{
+ unsigned int i;
+ long num = 0;
+ char *txt = NULL;
+ const OPTIONS *opt;
+ int start_opt = OPT_VERBOSITY - OPT_HELP;
+ int start_idx = OPT_VERBOSITY - 2;
+ /*
+ * starting with offset OPT_VERBOSITY because OPT_CONFIG and OPT_SECTION
+ * would not make sense within the config file.
+ */
+ int n_options = OSSL_NELEM(cmp_options) - 1;
+
+ for (opt = &cmp_options[start_opt], i = start_idx;
+ opt->name != NULL; i++, opt++)
+ if (!strcmp(opt->name, OPT_SECTION_STR)
+ || !strcmp(opt->name, OPT_MORE_STR))
+ n_options--;
+ OPENSSL_assert(OSSL_NELEM(cmp_vars) == n_options
+ + OPT_PROV__FIRST + 1 - OPT_PROV__LAST
+ + OPT_R__FIRST + 1 - OPT_R__LAST
+ + OPT_V__FIRST + 1 - OPT_V__LAST);
+ for (opt = &cmp_options[start_opt], i = start_idx;
+ opt->name != NULL; i++, opt++) {
+ int provider_option = (OPT_PROV__FIRST <= opt->retval
+ && opt->retval < OPT_PROV__LAST);
+ int rand_state_option = (OPT_R__FIRST <= opt->retval
+ && opt->retval < OPT_R__LAST);
+ int verification_option = (OPT_V__FIRST <= opt->retval
+ && opt->retval < OPT_V__LAST);
+
+ if (strcmp(opt->name, OPT_SECTION_STR) == 0
+ || strcmp(opt->name, OPT_MORE_STR) == 0) {
+ i--;
+ continue;
+ }
+ if (provider_option || rand_state_option || verification_option)
+ i--;
+ switch (opt->valtype) {
+ case '-':
+ case 'p':
+ case 'n':
+ case 'N':
+ case 'l':
+ if (!conf_get_number_e(conf, opt_section, opt->name, &num)) {
+ ERR_clear_error();
+ continue; /* option not provided */
+ }
+ if (opt->valtype == 'p' && num <= 0) {
+ opt_printf_stderr("Non-positive number \"%ld\" for config option -%s\n",
+ num, opt->name);
+ return -1;
+ }
+ if (opt->valtype == 'N' && num < 0) {
+ opt_printf_stderr("Negative number \"%ld\" for config option -%s\n",
+ num, opt->name);
+ return -1;
+ }
+ break;
+ case 's':
+ case '>':
+ case 'M':
+ txt = conf_get_string(conf, opt_section, opt->name);
+ if (txt == NULL) {
+ ERR_clear_error();
+ continue; /* option not provided */
+ }
+ break;
+ default:
+ CMP_err2("internal: unsupported type '%c' for option '%s'",
+ opt->valtype, opt->name);
+ return 0;
+ break;
+ }
+ if (provider_option || verification_option) {
+ int conf_argc = 1;
+ char *conf_argv[3];
+ char arg1[82];
+
+ BIO_snprintf(arg1, 81, "-%s", (char *)opt->name);
+ conf_argv[0] = prog;
+ conf_argv[1] = arg1;
+ if (opt->valtype == '-') {
+ if (num != 0)
+ conf_argc = 2;
+ } else {
+ conf_argc = 3;
+ conf_argv[2] = conf_get_string(conf, opt_section, opt->name);
+ /* not NULL */
+ }
+ if (conf_argc > 1) {
+ (void)opt_init(conf_argc, conf_argv, cmp_options);
+
+ if (provider_option
+ ? !opt_provider(opt_next())
+ : !opt_verify(opt_next(), vpm)) {
+ CMP_err2("for option '%s' in config file section '%s'",
+ opt->name, opt_section);
+ return 0;
+ }
+ }
+ } else {
+ switch (opt->valtype) {
+ case '-':
+ case 'p':
+ case 'n':
+ case 'N':
+ if (num < INT_MIN || INT_MAX < num) {
+ BIO_printf(bio_err,
+ "integer value out of range for option '%s'\n",
+ opt->name);
+ return 0;
+ }
+ *cmp_vars[i].num = (int)num;
+ break;
+ case 'l':
+ *cmp_vars[i].num_long = num;
+ break;
+ default:
+ if (txt != NULL && txt[0] == '\0')
+ txt = NULL; /* reset option on empty string input */
+ *cmp_vars[i].txt = txt;
+ break;
+ }
+ }
+ }
+
+ return 1;
+}
+
+static char *opt_str(void)
+{
+ char *arg = opt_arg();
+
+ if (arg[0] == '\0') {
+ CMP_warn1("%s option argument is empty string, resetting option",
+ opt_flag());
+ arg = NULL;
+ } else if (arg[0] == '-') {
+ CMP_warn1("%s option argument starts with hyphen", opt_flag());
+ }
+ return arg;
+}
+
+/* returns 1 on success, 0 on error, -1 on -help (i.e., stop with success) */
+static int get_opts(int argc, char **argv)
+{
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, cmp_options);
+
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ return 0;
+ case OPT_HELP:
+ opt_help(cmp_options);
+ return -1;
+ case OPT_CONFIG: /* has already been handled */
+ case OPT_SECTION: /* has already been handled */
+ break;
+ case OPT_VERBOSITY:
+ if (!set_verbosity(opt_int_arg()))
+ goto opthelp;
+ break;
+#ifndef OPENSSL_NO_SOCK
+ case OPT_SERVER:
+ opt_server = opt_str();
+ break;
+ case OPT_PROXY:
+ opt_proxy = opt_str();
+ break;
+ case OPT_NO_PROXY:
+ opt_no_proxy = opt_str();
+ break;
+#endif
+ case OPT_RECIPIENT:
+ opt_recipient = opt_str();
+ break;
+ case OPT_PATH:
+ opt_path = opt_str();
+ break;
+ case OPT_KEEP_ALIVE:
+ opt_keep_alive = opt_int_arg();
+ if (opt_keep_alive > 2) {
+ CMP_err("-keep_alive argument must be 0, 1, or 2");
+ goto opthelp;
+ }
+ break;
+ case OPT_MSG_TIMEOUT:
+ opt_msg_timeout = opt_int_arg();
+ break;
+ case OPT_TOTAL_TIMEOUT:
+ opt_total_timeout = opt_int_arg();
+ break;
+#ifndef OPENSSL_NO_SOCK
+ case OPT_TLS_USED:
+ opt_tls_used = 1;
+ break;
+ case OPT_TLS_CERT:
+ opt_tls_cert = opt_str();
+ break;
+ case OPT_TLS_KEY:
+ opt_tls_key = opt_str();
+ break;
+ case OPT_TLS_KEYPASS:
+ opt_tls_keypass = opt_str();
+ break;
+ case OPT_TLS_EXTRA:
+ opt_tls_extra = opt_str();
+ break;
+ case OPT_TLS_TRUSTED:
+ opt_tls_trusted = opt_str();
+ break;
+ case OPT_TLS_HOST:
+ opt_tls_host = opt_str();
+ break;
+#endif
+
+ case OPT_REF:
+ opt_ref = opt_str();
+ break;
+ case OPT_SECRET:
+ opt_secret = opt_str();
+ break;
+ case OPT_CERT:
+ opt_cert = opt_str();
+ break;
+ case OPT_OWN_TRUSTED:
+ opt_own_trusted = opt_str();
+ break;
+ case OPT_KEY:
+ opt_key = opt_str();
+ break;
+ case OPT_KEYPASS:
+ opt_keypass = opt_str();
+ break;
+ case OPT_DIGEST:
+ opt_digest = opt_str();
+ break;
+ case OPT_MAC:
+ opt_mac = opt_str();
+ break;
+ case OPT_EXTRACERTS:
+ opt_extracerts = opt_str();
+ break;
+ case OPT_UNPROTECTED_REQUESTS:
+ opt_unprotected_requests = 1;
+ break;
+
+ case OPT_TRUSTED:
+ opt_trusted = opt_str();
+ break;
+ case OPT_UNTRUSTED:
+ opt_untrusted = opt_str();
+ break;
+ case OPT_SRVCERT:
+ opt_srvcert = opt_str();
+ break;
+ case OPT_EXPECT_SENDER:
+ opt_expect_sender = opt_str();
+ break;
+ case OPT_IGNORE_KEYUSAGE:
+ opt_ignore_keyusage = 1;
+ break;
+ case OPT_UNPROTECTED_ERRORS:
+ opt_unprotected_errors = 1;
+ break;
+ case OPT_EXTRACERTSOUT:
+ opt_extracertsout = opt_str();
+ break;
+ case OPT_CACERTSOUT:
+ opt_cacertsout = opt_str();
+ break;
+
+ case OPT_V_CASES:
+ if (!opt_verify(o, vpm))
+ goto opthelp;
+ break;
+ case OPT_CMD:
+ opt_cmd_s = opt_str();
+ break;
+ case OPT_INFOTYPE:
+ opt_infotype_s = opt_str();
+ break;
+ case OPT_GENINFO:
+ opt_geninfo = opt_str();
+ break;
+
+ case OPT_NEWKEY:
+ opt_newkey = opt_str();
+ break;
+ case OPT_NEWKEYPASS:
+ opt_newkeypass = opt_str();
+ break;
+ case OPT_SUBJECT:
+ opt_subject = opt_str();
+ break;
+ case OPT_ISSUER:
+ opt_issuer = opt_str();
+ break;
+ case OPT_DAYS:
+ opt_days = opt_int_arg();
+ break;
+ case OPT_REQEXTS:
+ opt_reqexts = opt_str();
+ break;
+ case OPT_SANS:
+ opt_sans = opt_str();
+ break;
+ case OPT_SAN_NODEFAULT:
+ opt_san_nodefault = 1;
+ break;
+ case OPT_POLICIES:
+ opt_policies = opt_str();
+ break;
+ case OPT_POLICY_OIDS:
+ opt_policy_oids = opt_str();
+ break;
+ case OPT_POLICY_OIDS_CRITICAL:
+ opt_policy_oids_critical = 1;
+ break;
+ case OPT_POPO:
+ opt_popo = opt_int_arg();
+ if (opt_popo < OSSL_CRMF_POPO_NONE
+ || opt_popo > OSSL_CRMF_POPO_KEYENC) {
+ CMP_err("invalid popo spec. Valid values are -1 .. 2");
+ goto opthelp;
+ }
+ break;
+ case OPT_CSR:
+ opt_csr = opt_arg();
+ break;
+ case OPT_OUT_TRUSTED:
+ opt_out_trusted = opt_str();
+ break;
+ case OPT_IMPLICIT_CONFIRM:
+ opt_implicit_confirm = 1;
+ break;
+ case OPT_DISABLE_CONFIRM:
+ opt_disable_confirm = 1;
+ break;
+ case OPT_CERTOUT:
+ opt_certout = opt_str();
+ break;
+ case OPT_CHAINOUT:
+ opt_chainout = opt_str();
+ break;
+ case OPT_OLDCERT:
+ opt_oldcert = opt_str();
+ break;
+ case OPT_REVREASON:
+ opt_revreason = opt_int_arg();
+ if (opt_revreason < CRL_REASON_NONE
+ || opt_revreason > CRL_REASON_AA_COMPROMISE
+ || opt_revreason == 7) {
+ CMP_err("invalid revreason. Valid values are -1 .. 6, 8 .. 10");
+ goto opthelp;
+ }
+ break;
+ case OPT_CERTFORM:
+ opt_certform_s = opt_str();
+ break;
+ case OPT_KEYFORM:
+ opt_keyform_s = opt_str();
+ break;
+ case OPT_OTHERPASS:
+ opt_otherpass = opt_str();
+ break;
+#ifndef OPENSSL_NO_ENGINE
+ case OPT_ENGINE:
+ opt_engine = opt_str();
+ break;
+#endif
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto opthelp;
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto opthelp;
+ break;
+
+ case OPT_BATCH:
+ opt_batch = 1;
+ break;
+ case OPT_REPEAT:
+ opt_repeat = opt_int_arg();
+ break;
+ case OPT_REQIN:
+ opt_reqin = opt_str();
+ break;
+ case OPT_REQIN_NEW_TID:
+ opt_reqin_new_tid = 1;
+ break;
+ case OPT_REQOUT:
+ opt_reqout = opt_str();
+ break;
+ case OPT_RSPIN:
+ opt_rspin = opt_str();
+ break;
+ case OPT_RSPOUT:
+ opt_rspout = opt_str();
+ break;
+ case OPT_USE_MOCK_SRV:
+ opt_use_mock_srv = 1;
+ break;
+
+#ifndef OPENSSL_NO_SOCK
+ case OPT_PORT:
+ opt_port = opt_str();
+ break;
+ case OPT_MAX_MSGS:
+ opt_max_msgs = opt_int_arg();
+ break;
+#endif
+ case OPT_SRV_REF:
+ opt_srv_ref = opt_str();
+ break;
+ case OPT_SRV_SECRET:
+ opt_srv_secret = opt_str();
+ break;
+ case OPT_SRV_CERT:
+ opt_srv_cert = opt_str();
+ break;
+ case OPT_SRV_KEY:
+ opt_srv_key = opt_str();
+ break;
+ case OPT_SRV_KEYPASS:
+ opt_srv_keypass = opt_str();
+ break;
+ case OPT_SRV_TRUSTED:
+ opt_srv_trusted = opt_str();
+ break;
+ case OPT_SRV_UNTRUSTED:
+ opt_srv_untrusted = opt_str();
+ break;
+ case OPT_RSP_CERT:
+ opt_rsp_cert = opt_str();
+ break;
+ case OPT_RSP_EXTRACERTS:
+ opt_rsp_extracerts = opt_str();
+ break;
+ case OPT_RSP_CAPUBS:
+ opt_rsp_capubs = opt_str();
+ break;
+ case OPT_POLL_COUNT:
+ opt_poll_count = opt_int_arg();
+ break;
+ case OPT_CHECK_AFTER:
+ opt_check_after = opt_int_arg();
+ break;
+ case OPT_GRANT_IMPLICITCONF:
+ opt_grant_implicitconf = 1;
+ break;
+ case OPT_PKISTATUS:
+ opt_pkistatus = opt_int_arg();
+ break;
+ case OPT_FAILURE:
+ opt_failure = opt_int_arg();
+ break;
+ case OPT_FAILUREBITS:
+ opt_failurebits = opt_int_arg();
+ break;
+ case OPT_STATUSSTRING:
+ opt_statusstring = opt_str();
+ break;
+ case OPT_SEND_ERROR:
+ opt_send_error = 1;
+ break;
+ case OPT_SEND_UNPROTECTED:
+ opt_send_unprotected = 1;
+ break;
+ case OPT_SEND_UNPROT_ERR:
+ opt_send_unprot_err = 1;
+ break;
+ case OPT_ACCEPT_UNPROTECTED:
+ opt_accept_unprotected = 1;
+ break;
+ case OPT_ACCEPT_UNPROT_ERR:
+ opt_accept_unprot_err = 1;
+ break;
+ case OPT_ACCEPT_RAVERIFIED:
+ opt_accept_raverified = 1;
+ break;
+ }
+ }
+
+ /* No extra args. */
+ argc = opt_num_rest();
+ argv = opt_rest();
+ if (argc != 0)
+ goto opthelp;
+ return 1;
+}
+
+#ifndef OPENSSL_NO_SOCK
+static int cmp_server(OSSL_CMP_CTX *srv_cmp_ctx) {
+ BIO *acbio;
+ BIO *cbio = NULL;
+ int keep_alive = 0;
+ int msgs = 0;
+ int retry = 1;
+ int ret = 1;
+
+ if ((acbio = http_server_init_bio(prog, opt_port)) == NULL)
+ return 0;
+ while (opt_max_msgs <= 0 || msgs < opt_max_msgs) {
+ char *path = NULL;
+ OSSL_CMP_MSG *req = NULL;
+ OSSL_CMP_MSG *resp = NULL;
+
+ ret = http_server_get_asn1_req(ASN1_ITEM_rptr(OSSL_CMP_MSG),
+ (ASN1_VALUE **)&req, &path,
+ &cbio, acbio, &keep_alive,
+ prog, opt_port, 0, 0);
+ if (ret == 0) { /* no request yet */
+ if (retry) {
+ ossl_sleep(1000);
+ retry = 0;
+ continue;
+ }
+ ret = 0;
+ goto next;
+ }
+ if (ret++ == -1) /* fatal error */
+ break;
+
+ ret = 0;
+ msgs++;
+ if (req != NULL) {
+ if (strcmp(path, "") != 0 && strcmp(path, "pkix/") != 0) {
+ (void)http_server_send_status(cbio, 404, "Not Found");
+ CMP_err1("expecting empty path or 'pkix/' but got '%s'",
+ path);
+ OPENSSL_free(path);
+ OSSL_CMP_MSG_free(req);
+ goto next;
+ }
+ OPENSSL_free(path);
+ resp = OSSL_CMP_CTX_server_perform(cmp_ctx, req);
+ OSSL_CMP_MSG_free(req);
+ if (resp == NULL) {
+ (void)http_server_send_status(cbio,
+ 500, "Internal Server Error");
+ break; /* treated as fatal error */
+ }
+ ret = http_server_send_asn1_resp(cbio, keep_alive,
+ "application/pkixcmp",
+ ASN1_ITEM_rptr(OSSL_CMP_MSG),
+ (const ASN1_VALUE *)resp);
+ OSSL_CMP_MSG_free(resp);
+ if (!ret)
+ break; /* treated as fatal error */
+ }
+ next:
+ if (!ret) { /* on transmission error, cancel CMP transaction */
+ (void)OSSL_CMP_CTX_set1_transactionID(srv_cmp_ctx, NULL);
+ (void)OSSL_CMP_CTX_set1_senderNonce(srv_cmp_ctx, NULL);
+ }
+ if (!ret || !keep_alive
+ || OSSL_CMP_CTX_get_status(srv_cmp_ctx) != OSSL_CMP_PKISTATUS_trans
+ /* transaction closed by OSSL_CMP_CTX_server_perform() */) {
+ BIO_free_all(cbio);
+ cbio = NULL;
+ }
+ }
+
+ BIO_free_all(cbio);
+ BIO_free_all(acbio);
+ return ret;
+}
+#endif
+
+static void print_status(void)
+{
+ /* print PKIStatusInfo */
+ int status = OSSL_CMP_CTX_get_status(cmp_ctx);
+ char *buf = app_malloc(OSSL_CMP_PKISI_BUFLEN, "PKIStatusInfo buf");
+ const char *string =
+ OSSL_CMP_CTX_snprint_PKIStatus(cmp_ctx, buf, OSSL_CMP_PKISI_BUFLEN);
+ const char *from = "", *server = "";
+
+#ifndef OPENSSL_NO_SOCK
+ if (opt_server != NULL) {
+ from = " from ";
+ server = opt_server;
+ }
+#endif
+ CMP_print(bio_err,
+ status == OSSL_CMP_PKISTATUS_accepted
+ ? OSSL_CMP_LOG_INFO :
+ status == OSSL_CMP_PKISTATUS_rejection
+ || status == OSSL_CMP_PKISTATUS_waiting
+ ? OSSL_CMP_LOG_ERR : OSSL_CMP_LOG_WARNING,
+ status == OSSL_CMP_PKISTATUS_accepted ? "info" :
+ status == OSSL_CMP_PKISTATUS_rejection ? "server error" :
+ status == OSSL_CMP_PKISTATUS_waiting ? "internal error"
+ : "warning", "received%s%s %s", from, server,
+ string != NULL ? string : "<unknown PKIStatus>");
+ OPENSSL_free(buf);
+}
+
+int cmp_main(int argc, char **argv)
+{
+ char *configfile = NULL;
+ int i;
+ X509 *newcert = NULL;
+ ENGINE *engine = NULL;
+ OSSL_CMP_CTX *srv_cmp_ctx = NULL;
+ int ret = 0; /* default: failure */
+
+ prog = opt_appname(argv[0]);
+ if (argc <= 1) {
+ opt_help(cmp_options);
+ goto err;
+ }
+
+ /*
+ * handle options -config, -section, and -verbosity upfront
+ * to take effect for other options
+ */
+ for (i = 1; i < argc - 1; i++) {
+ if (*argv[i] == '-') {
+ if (!strcmp(argv[i] + 1, cmp_options[OPT_CONFIG - OPT_HELP].name))
+ opt_config = argv[++i];
+ else if (!strcmp(argv[i] + 1,
+ cmp_options[OPT_SECTION - OPT_HELP].name))
+ opt_section = argv[++i];
+ else if (strcmp(argv[i] + 1,
+ cmp_options[OPT_VERBOSITY - OPT_HELP].name) == 0
+ && !set_verbosity(atoi(argv[++i])))
+ goto err;
+ }
+ }
+ if (opt_section[0] == '\0') /* empty string */
+ opt_section = DEFAULT_SECTION;
+
+ vpm = X509_VERIFY_PARAM_new();
+ if (vpm == NULL) {
+ CMP_err("out of memory");
+ goto err;
+ }
+
+ /* read default values for options from config file */
+ configfile = opt_config != NULL ? opt_config : default_config_file;
+ if (configfile != NULL && configfile[0] != '\0' /* non-empty string */
+ && (configfile != default_config_file || access(configfile, F_OK) != -1)) {
+ CMP_info2("using section(s) '%s' of OpenSSL configuration file '%s'",
+ opt_section, configfile);
+ conf = app_load_config(configfile);
+ if (conf == NULL) {
+ goto err;
+ } else {
+ if (strcmp(opt_section, CMP_SECTION) == 0) { /* default */
+ if (!NCONF_get_section(conf, opt_section))
+ CMP_info2("no [%s] section found in config file '%s';"
+ " will thus use just [default] and unnamed section if present",
+ opt_section, configfile);
+ } else {
+ const char *end = opt_section + strlen(opt_section);
+ while ((end = prev_item(opt_section, end)) != NULL) {
+ if (!NCONF_get_section(conf, opt_item)) {
+ CMP_err2("no [%s] section found in config file '%s'",
+ opt_item, configfile);
+ goto err;
+ }
+ }
+ }
+ ret = read_config();
+ if (!set_verbosity(opt_verbosity)) /* just for checking range */
+ ret = -1;
+ if (ret <= 0) {
+ if (ret == -1)
+ BIO_printf(bio_err, "Use -help for summary.\n");
+ goto err;
+ }
+ }
+ }
+ (void)BIO_flush(bio_err); /* prevent interference with opt_help() */
+
+ ret = get_opts(argc, argv);
+ if (ret <= 0)
+ goto err;
+ ret = 0;
+ if (!app_RAND_load())
+ goto err;
+
+ if (opt_batch)
+ set_base_ui_method(UI_null());
+
+ if (opt_engine != NULL) {
+ engine = setup_engine_methods(opt_engine, 0 /* not: ENGINE_METHOD_ALL */, 0);
+ if (engine == NULL) {
+ CMP_err1("cannot load engine %s", opt_engine);
+ goto err;
+ }
+ }
+
+ cmp_ctx = OSSL_CMP_CTX_new(app_get0_libctx(), app_get0_propq());
+ if (cmp_ctx == NULL)
+ goto err;
+ OSSL_CMP_CTX_set_log_verbosity(cmp_ctx, opt_verbosity);
+ if (!OSSL_CMP_CTX_set_log_cb(cmp_ctx, print_to_bio_out)) {
+ CMP_err1("cannot set up error reporting and logging for %s", prog);
+ goto err;
+ }
+
+#ifndef OPENSSL_NO_SOCK
+ if ((opt_tls_cert != NULL || opt_tls_key != NULL
+ || opt_tls_keypass != NULL || opt_tls_extra != NULL
+ || opt_tls_trusted != NULL || opt_tls_host != NULL)
+ && !opt_tls_used)
+ CMP_warn("Ingnoring TLS options(s) since -tls_used is not given");
+ if (opt_port != NULL) {
+ if (opt_tls_used) {
+ CMP_err("-tls_used option not supported with -port option");
+ goto err;
+ }
+ if (opt_use_mock_srv || opt_server != NULL || opt_rspin != NULL) {
+ CMP_err("cannot use -port with -use_mock_srv, -server, or -rspin options");
+ goto err;
+ }
+ }
+ if (opt_server != NULL && opt_use_mock_srv) {
+ CMP_err("cannot use both -server and -use_mock_srv options");
+ goto err;
+ }
+#endif
+ if (opt_rspin != NULL && opt_use_mock_srv) {
+ CMP_err("cannot use both -rspin and -use_mock_srv options");
+ goto err;
+ }
+
+ if (opt_use_mock_srv
+#ifndef OPENSSL_NO_SOCK
+ || opt_port != NULL
+#endif
+ ) {
+ OSSL_CMP_SRV_CTX *srv_ctx;
+
+ if ((srv_ctx = setup_srv_ctx(engine)) == NULL)
+ goto err;
+ srv_cmp_ctx = OSSL_CMP_SRV_CTX_get0_cmp_ctx(srv_ctx);
+ OSSL_CMP_CTX_set_transfer_cb_arg(cmp_ctx, srv_ctx);
+ if (!OSSL_CMP_CTX_set_log_cb(srv_cmp_ctx, print_to_bio_err)) {
+ CMP_err1("cannot set up error reporting and logging for %s", prog);
+ goto err;
+ }
+ OSSL_CMP_CTX_set_log_verbosity(srv_cmp_ctx, opt_verbosity);
+ }
+
+#ifndef OPENSSL_NO_SOCK
+ if (opt_tls_used && (opt_use_mock_srv || opt_rspin != NULL)) {
+ CMP_warn("ignoring -tls_used option since -use_mock_srv or -rspin is given");
+ opt_tls_used = 0;
+ }
+
+ if (opt_port != NULL) { /* act as very basic CMP HTTP server */
+ ret = cmp_server(srv_cmp_ctx);
+ goto err;
+ }
+
+ /* act as CMP client, possibly using internal mock server */
+
+ if (opt_server != NULL) {
+ if (opt_rspin != NULL) {
+ CMP_warn("ignoring -server option since -rspin is given");
+ opt_server = NULL;
+ }
+ }
+#endif
+
+ if (!setup_client_ctx(cmp_ctx, engine)) {
+ CMP_err("cannot set up CMP context");
+ goto err;
+ }
+ for (i = 0; i < opt_repeat; i++) {
+ /* everything is ready, now connect and perform the command! */
+ switch (opt_cmd) {
+ case CMP_IR:
+ newcert = OSSL_CMP_exec_IR_ses(cmp_ctx);
+ if (newcert != NULL)
+ ret = 1;
+ break;
+ case CMP_KUR:
+ newcert = OSSL_CMP_exec_KUR_ses(cmp_ctx);
+ if (newcert != NULL)
+ ret = 1;
+ break;
+ case CMP_CR:
+ newcert = OSSL_CMP_exec_CR_ses(cmp_ctx);
+ if (newcert != NULL)
+ ret = 1;
+ break;
+ case CMP_P10CR:
+ newcert = OSSL_CMP_exec_P10CR_ses(cmp_ctx);
+ if (newcert != NULL)
+ ret = 1;
+ break;
+ case CMP_RR:
+ ret = OSSL_CMP_exec_RR_ses(cmp_ctx);
+ break;
+ case CMP_GENM:
+ {
+ STACK_OF(OSSL_CMP_ITAV) *itavs;
+
+ if (opt_infotype != NID_undef) {
+ OSSL_CMP_ITAV *itav =
+ OSSL_CMP_ITAV_create(OBJ_nid2obj(opt_infotype), NULL);
+ if (itav == NULL)
+ goto err;
+ OSSL_CMP_CTX_push0_genm_ITAV(cmp_ctx, itav);
+ }
+
+ if ((itavs = OSSL_CMP_exec_GENM_ses(cmp_ctx)) != NULL) {
+ print_itavs(itavs);
+ sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free);
+ ret = 1;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ if (OSSL_CMP_CTX_get_status(cmp_ctx) < OSSL_CMP_PKISTATUS_accepted)
+ goto err; /* we got no response, maybe even did not send request */
+
+ print_status();
+ if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_extraCertsIn(cmp_ctx),
+ opt_extracertsout, "extra") < 0)
+ ret = 0;
+ if (!ret)
+ goto err;
+ ret = 0;
+ if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_caPubs(cmp_ctx),
+ opt_cacertsout, "CA") < 0)
+ goto err;
+ if (newcert != NULL) {
+ STACK_OF(X509) *certs = sk_X509_new_null();
+
+ if (!X509_add_cert(certs, newcert, X509_ADD_FLAG_UP_REF)) {
+ sk_X509_free(certs);
+ goto err;
+ }
+ if (save_free_certs(cmp_ctx, certs, opt_certout, "enrolled") < 0)
+ goto err;
+ }
+ if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_newChain(cmp_ctx),
+ opt_chainout, "chain") < 0)
+ goto err;
+
+ if (!OSSL_CMP_CTX_reinit(cmp_ctx))
+ goto err;
+ }
+ ret = 1;
+
+ err:
+ /* in case we ended up here on error without proper cleaning */
+ cleanse(opt_keypass);
+ cleanse(opt_newkeypass);
+ cleanse(opt_otherpass);
+#ifndef OPENSSL_NO_SOCK
+ cleanse(opt_tls_keypass);
+#endif
+ cleanse(opt_secret);
+ cleanse(opt_srv_keypass);
+ cleanse(opt_srv_secret);
+
+ if (ret != 1)
+ OSSL_CMP_CTX_print_errors(cmp_ctx);
+
+ if (cmp_ctx != NULL) {
+#ifndef OPENSSL_NO_SOCK
+ APP_HTTP_TLS_INFO *info = OSSL_CMP_CTX_get_http_cb_arg(cmp_ctx);
+
+#endif
+ ossl_cmp_mock_srv_free(OSSL_CMP_CTX_get_transfer_cb_arg(cmp_ctx));
+ X509_STORE_free(OSSL_CMP_CTX_get_certConf_cb_arg(cmp_ctx));
+ /* cannot free info already here, as it may be used indirectly by: */
+ OSSL_CMP_CTX_free(cmp_ctx);
+#ifndef OPENSSL_NO_SOCK
+ APP_HTTP_TLS_INFO_free(info);
+#endif
+ }
+ X509_VERIFY_PARAM_free(vpm);
+ release_engine(engine);
+
+ NCONF_free(conf); /* must not do as long as opt_... variables are used */
+ OSSL_CMP_log_close();
+
+ return ret == 0 ? EXIT_FAILURE : EXIT_SUCCESS; /* ret == -1 for -help */
+}
diff --git a/apps/cms.c b/apps/cms.c
index 71554037d0b7..76c789671937 100644
--- a/apps/cms.c
+++ b/apps/cms.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -14,43 +14,41 @@
#include "apps.h"
#include "progs.h"
-#ifndef OPENSSL_NO_CMS
-
-# include <openssl/crypto.h>
-# include <openssl/pem.h>
-# include <openssl/err.h>
-# include <openssl/x509_vfy.h>
-# include <openssl/x509v3.h>
-# include <openssl/cms.h>
+#include <openssl/crypto.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/x509_vfy.h>
+#include <openssl/x509v3.h>
+#include <openssl/cms.h>
static int save_certs(char *signerfile, STACK_OF(X509) *signers);
static int cms_cb(int ok, X509_STORE_CTX *ctx);
static void receipt_request_print(CMS_ContentInfo *cms);
-static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
- *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING)
- *rr_from);
+static CMS_ReceiptRequest
+*make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst,
+ STACK_OF(OPENSSL_STRING) *rr_from);
static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
STACK_OF(OPENSSL_STRING) *param);
-# define SMIME_OP 0x10
-# define SMIME_IP 0x20
-# define SMIME_SIGNERS 0x40
-# define SMIME_ENCRYPT (1 | SMIME_OP)
-# define SMIME_DECRYPT (2 | SMIME_IP)
-# define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS)
-# define SMIME_VERIFY (4 | SMIME_IP)
-# define SMIME_CMSOUT (5 | SMIME_IP | SMIME_OP)
-# define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
-# define SMIME_DATAOUT (7 | SMIME_IP)
-# define SMIME_DATA_CREATE (8 | SMIME_OP)
-# define SMIME_DIGEST_VERIFY (9 | SMIME_IP)
-# define SMIME_DIGEST_CREATE (10 | SMIME_OP)
-# define SMIME_UNCOMPRESS (11 | SMIME_IP)
-# define SMIME_COMPRESS (12 | SMIME_OP)
-# define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP)
-# define SMIME_ENCRYPTED_ENCRYPT (14 | SMIME_OP)
-# define SMIME_SIGN_RECEIPT (15 | SMIME_IP | SMIME_OP)
-# define SMIME_VERIFY_RECEIPT (16 | SMIME_IP)
+#define SMIME_OP 0x100
+#define SMIME_IP 0x200
+#define SMIME_SIGNERS 0x400
+#define SMIME_ENCRYPT (1 | SMIME_OP)
+#define SMIME_DECRYPT (2 | SMIME_IP)
+#define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS)
+#define SMIME_VERIFY (4 | SMIME_IP)
+#define SMIME_RESIGN (5 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
+#define SMIME_SIGN_RECEIPT (6 | SMIME_IP | SMIME_OP)
+#define SMIME_VERIFY_RECEIPT (7 | SMIME_IP)
+#define SMIME_DIGEST_CREATE (8 | SMIME_OP)
+#define SMIME_DIGEST_VERIFY (9 | SMIME_IP)
+#define SMIME_COMPRESS (10 | SMIME_OP)
+#define SMIME_UNCOMPRESS (11 | SMIME_IP)
+#define SMIME_ENCRYPTED_ENCRYPT (12 | SMIME_OP)
+#define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP)
+#define SMIME_DATA_CREATE (14 | SMIME_OP)
+#define SMIME_DATA_OUT (15 | SMIME_IP)
+#define SMIME_CMSOUT (16 | SMIME_IP | SMIME_OP)
static int verify_err = 0;
@@ -63,9 +61,9 @@ struct cms_key_param_st {
};
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENCRYPT,
- OPT_DECRYPT, OPT_SIGN, OPT_SIGN_RECEIPT, OPT_RESIGN,
+ OPT_DECRYPT, OPT_SIGN, OPT_CADES, OPT_SIGN_RECEIPT, OPT_RESIGN,
OPT_VERIFY, OPT_VERIFY_RETCODE, OPT_VERIFY_RECEIPT,
OPT_CMSOUT, OPT_DATA_OUT, OPT_DATA_CREATE, OPT_DIGEST_VERIFY,
OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS,
@@ -75,151 +73,246 @@ typedef enum OPTION_choice {
OPT_NOSIGS, OPT_NO_CONTENT_VERIFY, OPT_NO_ATTR_VERIFY, OPT_INDEF,
OPT_NOINDEF, OPT_CRLFEOL, OPT_NOOUT, OPT_RR_PRINT,
OPT_RR_ALL, OPT_RR_FIRST, OPT_RCTFORM, OPT_CERTFILE, OPT_CAFILE,
- OPT_CAPATH, OPT_NOCAPATH, OPT_NOCAFILE,OPT_CONTENT, OPT_PRINT,
+ OPT_CAPATH, OPT_CASTORE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE,
+ OPT_CONTENT, OPT_PRINT, OPT_NAMEOPT,
OPT_SECRETKEY, OPT_SECRETKEYID, OPT_PWRI_PASSWORD, OPT_ECONTENT_TYPE,
OPT_PASSIN, OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP,
OPT_CERTSOUT, OPT_MD, OPT_INKEY, OPT_KEYFORM, OPT_KEYOPT, OPT_RR_FROM,
OPT_RR_TO, OPT_AES128_WRAP, OPT_AES192_WRAP, OPT_AES256_WRAP,
- OPT_3DES_WRAP, OPT_ENGINE,
+ OPT_3DES_WRAP, OPT_WRAP, OPT_ENGINE,
OPT_R_ENUM,
+ OPT_PROV_ENUM, OPT_CONFIG,
OPT_V_ENUM,
- OPT_CIPHER
+ OPT_CIPHER,
+ OPT_ORIGINATOR
} OPTION_CHOICE;
const OPTIONS cms_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"},
- {OPT_HELP_STR, 1, '-',
- " cert.pem... recipient certs for encryption\n"},
- {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert...]\n"},
{"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"},
- {"outform", OPT_OUTFORM, 'c',
- "Output format SMIME (default), PEM or DER"},
+
+ OPT_SECTION("General"),
{"in", OPT_IN, '<', "Input file"},
{"out", OPT_OUT, '>', "Output file"},
+ OPT_CONFIG_OPTION,
+
+ OPT_SECTION("Operation"),
{"encrypt", OPT_ENCRYPT, '-', "Encrypt message"},
{"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"},
{"sign", OPT_SIGN, '-', "Sign message"},
- {"sign_receipt", OPT_SIGN_RECEIPT, '-', "Generate a signed receipt for the message"},
- {"resign", OPT_RESIGN, '-', "Resign a signed message"},
{"verify", OPT_VERIFY, '-', "Verify signed message"},
- {"verify_retcode", OPT_VERIFY_RETCODE, '-'},
- {"verify_receipt", OPT_VERIFY_RECEIPT, '<'},
+ {"resign", OPT_RESIGN, '-', "Resign a signed message"},
+ {"sign_receipt", OPT_SIGN_RECEIPT, '-',
+ "Generate a signed receipt for a message"},
+ {"verify_receipt", OPT_VERIFY_RECEIPT, '<',
+ "Verify receipts; exit if receipt signatures do not verify"},
+ {"digest_create", OPT_DIGEST_CREATE, '-',
+ "Create a CMS \"DigestedData\" object"},
+ {"digest_verify", OPT_DIGEST_VERIFY, '-',
+ "Verify a CMS \"DigestedData\" object and output it"},
+ {"compress", OPT_COMPRESS, '-', "Create a CMS \"CompressedData\" object"},
+ {"uncompress", OPT_UNCOMPRESS, '-',
+ "Uncompress a CMS \"CompressedData\" object"},
+ {"EncryptedData_encrypt", OPT_ED_ENCRYPT, '-',
+ "Create CMS \"EncryptedData\" object using symmetric key"},
+ {"EncryptedData_decrypt", OPT_ED_DECRYPT, '-',
+ "Decrypt CMS \"EncryptedData\" object using symmetric key"},
+ {"data_create", OPT_DATA_CREATE, '-', "Create a CMS \"Data\" object"},
+ {"data_out", OPT_DATA_OUT, '-', "Copy CMS \"Data\" object to output"},
{"cmsout", OPT_CMSOUT, '-', "Output CMS structure"},
- {"data_out", OPT_DATA_OUT, '-'},
- {"data_create", OPT_DATA_CREATE, '-'},
- {"digest_verify", OPT_DIGEST_VERIFY, '-'},
- {"digest_create", OPT_DIGEST_CREATE, '-'},
- {"compress", OPT_COMPRESS, '-'},
- {"uncompress", OPT_UNCOMPRESS, '-'},
- {"EncryptedData_decrypt", OPT_ED_DECRYPT, '-'},
- {"EncryptedData_encrypt", OPT_ED_ENCRYPT, '-'},
- {"debug_decrypt", OPT_DEBUG_DECRYPT, '-'},
- {"text", OPT_TEXT, '-', "Include or delete text MIME headers"},
- {"asciicrlf", OPT_ASCIICRLF, '-'},
- {"nointern", OPT_NOINTERN, '-',
- "Don't search certificates in message for signer"},
- {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"},
- {"nocerts", OPT_NOCERTS, '-',
- "Don't include signers certificate when signing"},
- {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"},
- {"nodetach", OPT_NODETACH, '-', "Use opaque signing"},
- {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"},
- {"binary", OPT_BINARY, '-', "Don't translate message to text"},
- {"keyid", OPT_KEYID, '-', "Use subject key identifier"},
- {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"},
- {"no_content_verify", OPT_NO_CONTENT_VERIFY, '-'},
- {"no_attr_verify", OPT_NO_ATTR_VERIFY, '-'},
+
+ OPT_SECTION("File format"),
+ {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"},
+ {"outform", OPT_OUTFORM, 'c',
+ "Output format SMIME (default), PEM or DER"},
+ {"rctform", OPT_RCTFORM, 'F', "Receipt file format"},
{"stream", OPT_INDEF, '-', "Enable CMS streaming"},
{"indef", OPT_INDEF, '-', "Same as -stream"},
{"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"},
- {"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of CR only" },
- {"noout", OPT_NOOUT, '-', "For the -cmsout operation do not output the parsed CMS structure"},
- {"receipt_request_print", OPT_RR_PRINT, '-', "Print CMS Receipt Request" },
- {"receipt_request_all", OPT_RR_ALL, '-'},
- {"receipt_request_first", OPT_RR_FIRST, '-'},
- {"rctform", OPT_RCTFORM, 'F', "Receipt file format"},
+ {"binary", OPT_BINARY, '-',
+ "Treat input as binary: do not translate to canonical form"},
+ {"crlfeol", OPT_CRLFEOL, '-',
+ "Use CRLF as EOL termination instead of CR only" },
+ {"asciicrlf", OPT_ASCIICRLF, '-',
+ "Perform CRLF canonicalisation when signing"},
+
+ OPT_SECTION("Keys and passwords"),
+ {"pwri_password", OPT_PWRI_PASSWORD, 's',
+ "Specific password for recipient"},
+ {"secretkey", OPT_SECRETKEY, 's',
+ "Use specified hex-encoded key to decrypt/encrypt recipients or content"},
+ {"secretkeyid", OPT_SECRETKEYID, 's',
+ "Identity of the -secretkey for CMS \"KEKRecipientInfo\" object"},
+ {"inkey", OPT_INKEY, 's',
+ "Input private key (if not signer or recipient)"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"keyopt", OPT_KEYOPT, 's', "Set public key parameters as n:v pairs"},
+ {"keyform", OPT_KEYFORM, 'f',
+ "Input private key format (ENGINE, other values ignored)"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
+#endif
+ OPT_PROV_OPTIONS,
+ OPT_R_OPTIONS,
+
+ OPT_SECTION("Encryption and decryption"),
+ {"originator", OPT_ORIGINATOR, 's', "Originator certificate file"},
+ {"recip", OPT_RECIP, '<', "Recipient cert file"},
+ {"cert...", OPT_PARAM, '.',
+ "Recipient certs (optional; used only when encrypting)"},
+ {"", OPT_CIPHER, '-',
+ "The encryption algorithm to use (any supported cipher)"},
+ {"wrap", OPT_WRAP, 's',
+ "Key wrap algorithm to use when encrypting with key agreement"},
+ {"aes128-wrap", OPT_AES128_WRAP, '-', "Use AES128 to wrap key"},
+ {"aes192-wrap", OPT_AES192_WRAP, '-', "Use AES192 to wrap key"},
+ {"aes256-wrap", OPT_AES256_WRAP, '-', "Use AES256 to wrap key"},
+ {"des3-wrap", OPT_3DES_WRAP, '-', "Use 3DES-EDE to wrap key"},
+ {"debug_decrypt", OPT_DEBUG_DECRYPT, '-',
+ "Disable MMA protection, return error if no recipient found (see doc)"},
+
+ OPT_SECTION("Signing"),
+ {"md", OPT_MD, 's', "Digest algorithm to use"},
+ {"signer", OPT_SIGNER, 's', "Signer certificate input file"},
{"certfile", OPT_CERTFILE, '<', "Other certificates file"},
+ {"cades", OPT_CADES, '-',
+ "Include signingCertificate attribute (CAdES-BES)"},
+ {"nodetach", OPT_NODETACH, '-', "Use opaque signing"},
+ {"nocerts", OPT_NOCERTS, '-',
+ "Don't include signer's certificate when signing"},
+ {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"},
+ {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"},
+ {"receipt_request_all", OPT_RR_ALL, '-',
+ "When signing, create a receipt request for all recipients"},
+ {"receipt_request_first", OPT_RR_FIRST, '-',
+ "When signing, create a receipt request for first recipient"},
+ {"receipt_request_from", OPT_RR_FROM, 's',
+ "Create signed receipt request with specified email address"},
+ {"receipt_request_to", OPT_RR_TO, 's',
+ "Create signed receipt targeted to specified address"},
+
+ OPT_SECTION("Verification"),
+ {"signer", OPT_DUP, 's', "Signer certificate(s) output file"},
+ {"content", OPT_CONTENT, '<',
+ "Supply or override content for detached signature"},
+ {"no_content_verify", OPT_NO_CONTENT_VERIFY, '-',
+ "Do not verify signed content signatures"},
+ {"no_attr_verify", OPT_NO_ATTR_VERIFY, '-',
+ "Do not verify signed attribute signatures"},
+ {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"},
+ {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"},
+ {"nointern", OPT_NOINTERN, '-',
+ "Don't search certificates in message for signer"},
+ {"cades", OPT_DUP, '-', "Check signingCertificate (CAdES-BES)"},
+ {"verify_retcode", OPT_VERIFY_RETCODE, '-',
+ "Exit non-zero on verification failure"},
{"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
- {"CApath", OPT_CAPATH, '/', "trusted certificates directory"},
+ {"CApath", OPT_CAPATH, '/', "Trusted certificates directory"},
+ {"CAstore", OPT_CASTORE, ':', "Trusted certificates store URI"},
{"no-CAfile", OPT_NOCAFILE, '-',
"Do not load the default certificates file"},
{"no-CApath", OPT_NOCAPATH, '-',
"Do not load certificates from the default certificates directory"},
- {"content", OPT_CONTENT, '<',
- "Supply or override content for detached signature"},
- {"print", OPT_PRINT, '-',
- "For the -cmsout operation print out all fields of the CMS structure"},
- {"secretkey", OPT_SECRETKEY, 's'},
- {"secretkeyid", OPT_SECRETKEYID, 's'},
- {"pwri_password", OPT_PWRI_PASSWORD, 's'},
- {"econtent_type", OPT_ECONTENT_TYPE, 's'},
- {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load certificates from the default certificates store"},
+
+ OPT_SECTION("Output"),
+ {"keyid", OPT_KEYID, '-', "Use subject key identifier"},
+ {"econtent_type", OPT_ECONTENT_TYPE, 's', "OID for external content"},
+ {"text", OPT_TEXT, '-', "Include or delete text MIME headers"},
+ {"certsout", OPT_CERTSOUT, '>', "Certificate output file"},
{"to", OPT_TO, 's', "To address"},
{"from", OPT_FROM, 's', "From address"},
{"subject", OPT_SUBJECT, 's', "Subject"},
- {"signer", OPT_SIGNER, 's', "Signer certificate file"},
- {"recip", OPT_RECIP, '<', "Recipient cert file for decryption"},
- {"certsout", OPT_CERTSOUT, '>', "Certificate output file"},
- {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"},
- {"inkey", OPT_INKEY, 's',
- "Input private key (if not signer or recipient)"},
- {"keyform", OPT_KEYFORM, 'f', "Input private key format (PEM or ENGINE)"},
- {"keyopt", OPT_KEYOPT, 's', "Set public key parameters as n:v pairs"},
- {"receipt_request_from", OPT_RR_FROM, 's'},
- {"receipt_request_to", OPT_RR_TO, 's'},
- {"", OPT_CIPHER, '-', "Any supported cipher"},
- OPT_R_OPTIONS,
+
+ OPT_SECTION("Printing"),
+ {"noout", OPT_NOOUT, '-',
+ "For the -cmsout operation do not output the parsed CMS structure"},
+ {"print", OPT_PRINT, '-',
+ "For the -cmsout operation print out all fields of the CMS structure"},
+ {"nameopt", OPT_NAMEOPT, 's',
+ "For the -print option specifies various strings printing options"},
+ {"receipt_request_print", OPT_RR_PRINT, '-', "Print CMS Receipt Request" },
+
OPT_V_OPTIONS,
- {"aes128-wrap", OPT_AES128_WRAP, '-', "Use AES128 to wrap key"},
- {"aes192-wrap", OPT_AES192_WRAP, '-', "Use AES192 to wrap key"},
- {"aes256-wrap", OPT_AES256_WRAP, '-', "Use AES256 to wrap key"},
-# ifndef OPENSSL_NO_DES
- {"des3-wrap", OPT_3DES_WRAP, '-', "Use 3DES-EDE to wrap key"},
-# endif
-# ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
-# endif
{NULL}
};
+static CMS_ContentInfo *load_content_info(int informat, BIO *in, int flags,
+ BIO **indata, const char *name)
+{
+ CMS_ContentInfo *ret, *ci;
+
+ ret = CMS_ContentInfo_new_ex(app_get0_libctx(), app_get0_propq());
+ if (ret == NULL) {
+ BIO_printf(bio_err, "Error allocating CMS_contentinfo\n");
+ return NULL;
+ }
+ switch (informat) {
+ case FORMAT_SMIME:
+ ci = SMIME_read_CMS_ex(in, flags, indata, &ret);
+ break;
+ case FORMAT_PEM:
+ ci = PEM_read_bio_CMS(in, &ret, NULL, NULL);
+ break;
+ case FORMAT_ASN1:
+ ci = d2i_CMS_bio(in, &ret);
+ break;
+ default:
+ BIO_printf(bio_err, "Bad input format for %s\n", name);
+ goto err;
+ }
+ if (ci == NULL) {
+ BIO_printf(bio_err, "Error reading %s Content Info\n", name);
+ goto err;
+ }
+ return ret;
+ err:
+ CMS_ContentInfo_free(ret);
+ return NULL;
+}
+
int cms_main(int argc, char **argv)
{
+ CONF *conf = NULL;
ASN1_OBJECT *econtent_type = NULL;
BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
CMS_ContentInfo *cms = NULL, *rcms = NULL;
CMS_ReceiptRequest *rr = NULL;
ENGINE *e = NULL;
EVP_PKEY *key = NULL;
- const EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL;
- const EVP_MD *sign_md = NULL;
+ EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL;
+ EVP_MD *sign_md = NULL;
STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL;
STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
- STACK_OF(X509) *encerts = NULL, *other = NULL;
- X509 *cert = NULL, *recip = NULL, *signer = NULL;
+ STACK_OF(X509) *encerts = sk_X509_new_null(), *other = NULL;
+ X509 *cert = NULL, *recip = NULL, *signer = NULL, *originator = NULL;
X509_STORE *store = NULL;
- X509_VERIFY_PARAM *vpm = NULL;
+ X509_VERIFY_PARAM *vpm = X509_VERIFY_PARAM_new();
char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
- const char *CAfile = NULL, *CApath = NULL;
- char *certsoutfile = NULL;
- int noCAfile = 0, noCApath = 0;
+ const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL;
+ char *certsoutfile = NULL, *digestname = NULL, *wrapname = NULL;
+ int noCAfile = 0, noCApath = 0, noCAstore = 0;
char *infile = NULL, *outfile = NULL, *rctfile = NULL;
- char *passinarg = NULL, *passin = NULL, *signerfile = NULL, *recipfile = NULL;
+ char *passinarg = NULL, *passin = NULL, *signerfile = NULL;
+ char *originatorfile = NULL, *recipfile = NULL, *ciphername = NULL;
char *to = NULL, *from = NULL, *subject = NULL, *prog;
cms_key_param *key_first = NULL, *key_param = NULL;
- int flags = CMS_DETACHED, noout = 0, print = 0, keyidx = -1, vpmtouched = 0;
+ int flags = CMS_DETACHED, binary_files = 0;
+ int noout = 0, print = 0, keyidx = -1, vpmtouched = 0;
int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
int operation = 0, ret = 1, rr_print = 0, rr_allorfirst = -1;
- int verify_retcode = 0, rctformat = FORMAT_SMIME, keyform = FORMAT_PEM;
+ int verify_retcode = 0, rctformat = FORMAT_SMIME, keyform = FORMAT_UNDEF;
size_t secret_keylen = 0, secret_keyidlen = 0;
unsigned char *pwri_pass = NULL, *pwri_tmp = NULL;
unsigned char *secret_key = NULL, *secret_keyid = NULL;
long ltmp;
const char *mime_eol = "\n";
OPTION_CHOICE o;
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
- if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
- return 1;
+ if (encerts == NULL || vpm == NULL)
+ goto end;
prog = opt_init(argc, argv, cms_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -244,6 +337,7 @@ int cms_main(int argc, char **argv)
case OPT_OUT:
outfile = opt_arg();
break;
+
case OPT_ENCRYPT:
operation = SMIME_ENCRYPT;
break;
@@ -253,49 +347,50 @@ int cms_main(int argc, char **argv)
case OPT_SIGN:
operation = SMIME_SIGN;
break;
- case OPT_SIGN_RECEIPT:
- operation = SMIME_SIGN_RECEIPT;
+ case OPT_VERIFY:
+ operation = SMIME_VERIFY;
break;
case OPT_RESIGN:
operation = SMIME_RESIGN;
break;
- case OPT_VERIFY:
- operation = SMIME_VERIFY;
- break;
- case OPT_VERIFY_RETCODE:
- verify_retcode = 1;
+ case OPT_SIGN_RECEIPT:
+ operation = SMIME_SIGN_RECEIPT;
break;
case OPT_VERIFY_RECEIPT:
operation = SMIME_VERIFY_RECEIPT;
rctfile = opt_arg();
break;
- case OPT_CMSOUT:
- operation = SMIME_CMSOUT;
- break;
- case OPT_DATA_OUT:
- operation = SMIME_DATAOUT;
+ case OPT_VERIFY_RETCODE:
+ verify_retcode = 1;
break;
- case OPT_DATA_CREATE:
- operation = SMIME_DATA_CREATE;
+ case OPT_DIGEST_CREATE:
+ operation = SMIME_DIGEST_CREATE;
break;
case OPT_DIGEST_VERIFY:
operation = SMIME_DIGEST_VERIFY;
break;
- case OPT_DIGEST_CREATE:
- operation = SMIME_DIGEST_CREATE;
- break;
case OPT_COMPRESS:
operation = SMIME_COMPRESS;
break;
case OPT_UNCOMPRESS:
operation = SMIME_UNCOMPRESS;
break;
+ case OPT_ED_ENCRYPT:
+ operation = SMIME_ENCRYPTED_ENCRYPT;
+ break;
case OPT_ED_DECRYPT:
operation = SMIME_ENCRYPTED_DECRYPT;
break;
- case OPT_ED_ENCRYPT:
- operation = SMIME_ENCRYPTED_ENCRYPT;
+ case OPT_DATA_CREATE:
+ operation = SMIME_DATA_CREATE;
+ break;
+ case OPT_DATA_OUT:
+ operation = SMIME_DATA_OUT;
break;
+ case OPT_CMSOUT:
+ operation = SMIME_CMSOUT;
+ break;
+
case OPT_DEBUG_DECRYPT:
flags |= CMS_DEBUG_DECRYPT;
break;
@@ -326,6 +421,9 @@ int cms_main(int argc, char **argv)
case OPT_BINARY:
flags |= CMS_BINARY;
break;
+ case OPT_CADES:
+ flags |= CMS_CADES;
+ break;
case OPT_KEYID:
flags |= CMS_USE_KEYID;
break;
@@ -361,14 +459,9 @@ int cms_main(int argc, char **argv)
rr_allorfirst = 1;
break;
case OPT_RCTFORM:
- if (rctformat == FORMAT_SMIME)
- rcms = SMIME_read_CMS(rctin, NULL);
- else if (rctformat == FORMAT_PEM)
- rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
- else if (rctformat == FORMAT_ASN1)
- if (!opt_format(opt_arg(),
- OPT_FMT_PEMDER | OPT_FMT_SMIME, &rctformat))
- goto opthelp;
+ if (!opt_format(opt_arg(),
+ OPT_FMT_PEMDER | OPT_FMT_SMIME, &rctformat))
+ goto opthelp;
break;
case OPT_CERTFILE:
certfile = opt_arg();
@@ -379,12 +472,18 @@ int cms_main(int argc, char **argv)
case OPT_CAPATH:
CApath = opt_arg();
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
case OPT_NOCAPATH:
noCApath = 1;
break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
case OPT_IN:
infile = opt_arg();
break;
@@ -406,6 +505,10 @@ int cms_main(int argc, char **argv)
case OPT_PRINT:
noout = print = 1;
break;
+ case OPT_NAMEOPT:
+ if (!set_nameopt(opt_arg()))
+ goto opthelp;
+ break;
case OPT_SECRETKEY:
if (secret_key != NULL) {
BIO_printf(bio_err, "Invalid key (supplied twice) %s\n",
@@ -466,8 +569,7 @@ int cms_main(int argc, char **argv)
certsoutfile = opt_arg();
break;
case OPT_MD:
- if (!opt_md(opt_arg(), &sign_md))
- goto end;
+ digestname = opt_arg();
break;
case OPT_SIGNER:
/* If previous -signer argument add signer to list */
@@ -486,6 +588,9 @@ int cms_main(int argc, char **argv)
}
signerfile = opt_arg();
break;
+ case OPT_ORIGINATOR:
+ originatorfile = opt_arg();
+ break;
case OPT_INKEY:
/* If previous -inkey argument add signer to list */
if (keyfile != NULL) {
@@ -511,9 +616,7 @@ int cms_main(int argc, char **argv)
break;
case OPT_RECIP:
if (operation == SMIME_ENCRYPT) {
- if (encerts == NULL && (encerts = sk_X509_new_null()) == NULL)
- goto end;
- cert = load_cert(opt_arg(), FORMAT_PEM,
+ cert = load_cert(opt_arg(), FORMAT_UNDEF,
"recipient certificate file");
if (cert == NULL)
goto end;
@@ -524,13 +627,12 @@ int cms_main(int argc, char **argv)
}
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &cipher))
- goto end;
+ ciphername = opt_unknown();
break;
case OPT_KEYOPT:
keyidx = -1;
if (operation == SMIME_ENCRYPT) {
- if (encerts != NULL)
+ if (sk_X509_num(encerts) > 0)
keyidx += sk_X509_num(encerts);
} else {
if (keyfile != NULL || signerfile != NULL)
@@ -568,22 +670,43 @@ int cms_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
- case OPT_3DES_WRAP:
-# ifndef OPENSSL_NO_DES
- wrap_cipher = EVP_des_ede3_wrap();
-# endif
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
break;
- case OPT_AES128_WRAP:
- wrap_cipher = EVP_aes_128_wrap();
+ case OPT_CONFIG:
+ conf = app_load_config_modules(opt_arg());
+ if (conf == NULL)
+ goto end;
break;
- case OPT_AES192_WRAP:
- wrap_cipher = EVP_aes_192_wrap();
+ case OPT_WRAP:
+ wrapname = opt_arg();
break;
+ case OPT_AES128_WRAP:
+ case OPT_AES192_WRAP:
case OPT_AES256_WRAP:
- wrap_cipher = EVP_aes_256_wrap();
+ case OPT_3DES_WRAP:
+ wrapname = opt_flag() + 1;
break;
}
}
+ if (!app_RAND_load())
+ goto end;
+
+ if (digestname != NULL) {
+ if (!opt_md(digestname, &sign_md))
+ goto end;
+ }
+ if (ciphername != NULL) {
+ if (!opt_cipher_any(ciphername, &cipher))
+ goto end;
+ }
+ if (wrapname != NULL) {
+ if (!opt_cipher_any(wrapname, &wrap_cipher))
+ goto end;
+ }
+
+ /* Remaining args are files to process. */
argc = opt_num_rest();
argv = opt_rest();
@@ -601,6 +724,20 @@ int cms_main(int argc, char **argv)
goto opthelp;
}
+ if ((flags & CMS_CADES) != 0) {
+ if ((flags & CMS_NOATTR) != 0) {
+ BIO_puts(bio_err, "Incompatible options: "
+ "CAdES requires signed attributes\n");
+ goto opthelp;
+ }
+ if (operation == SMIME_VERIFY
+ && (flags & (CMS_NO_SIGNER_CERT_VERIFY | CMS_NO_ATTR_VERIFY)) != 0) {
+ BIO_puts(bio_err, "Incompatible options: CAdES validation requires"
+ " certs and signed attributes validations\n");
+ goto opthelp;
+ }
+ }
+
if (operation & SMIME_SIGNERS) {
if (keyfile != NULL && signerfile == NULL) {
BIO_puts(bio_err, "Illegal -inkey without -signer\n");
@@ -633,7 +770,7 @@ int cms_main(int argc, char **argv)
}
} else if (operation == SMIME_ENCRYPT) {
if (*argv == NULL && secret_key == NULL
- && pwri_pass == NULL && encerts == NULL) {
+ && pwri_pass == NULL && sk_X509_num(encerts) <= 0) {
BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
goto opthelp;
}
@@ -649,25 +786,36 @@ int cms_main(int argc, char **argv)
ret = 2;
- if (!(operation & SMIME_SIGNERS))
+ if ((operation & SMIME_SIGNERS) == 0) {
+ if ((flags & CMS_DETACHED) == 0)
+ BIO_printf(bio_err,
+ "Warning: -nodetach option is ignored for non-signing operation\n");
+
flags &= ~CMS_DETACHED;
+ }
+ if ((operation & SMIME_IP) == 0 && contfile != NULL)
+ BIO_printf(bio_err,
+ "Warning: -contfile option is ignored for the given operation\n");
- if (!(operation & SMIME_OP))
- if (flags & CMS_BINARY)
+ if ((flags & CMS_BINARY) != 0) {
+ if (!(operation & SMIME_OP))
outformat = FORMAT_BINARY;
-
- if (!(operation & SMIME_IP))
- if (flags & CMS_BINARY)
+ if (!(operation & SMIME_IP))
informat = FORMAT_BINARY;
+ if ((operation & SMIME_SIGNERS) != 0 && (flags & CMS_DETACHED) != 0)
+ binary_files = 1;
+ if ((operation & SMIME_IP) != 0 && contfile == NULL)
+ binary_files = 1;
+ }
if (operation == SMIME_ENCRYPT) {
if (!cipher) {
-# ifndef OPENSSL_NO_DES
- cipher = EVP_des_ede3_cbc();
-# else
+#ifndef OPENSSL_NO_DES
+ cipher = (EVP_CIPHER *)EVP_des_ede3_cbc();
+#else
BIO_printf(bio_err, "No cipher selected\n");
goto end;
-# endif
+#endif
}
if (secret_key && !secret_keyid) {
@@ -675,44 +823,54 @@ int cms_main(int argc, char **argv)
goto end;
}
- if (*argv && encerts == NULL)
- if ((encerts = sk_X509_new_null()) == NULL)
- goto end;
- while (*argv) {
- if ((cert = load_cert(*argv, FORMAT_PEM,
- "recipient certificate file")) == NULL)
- goto end;
- sk_X509_push(encerts, cert);
- cert = NULL;
- argv++;
+ if (*argv != NULL) {
+ if (operation == SMIME_ENCRYPT) {
+ for (; *argv != NULL; argv++) {
+ cert = load_cert(*argv, FORMAT_UNDEF,
+ "recipient certificate file");
+ if (cert == NULL)
+ goto end;
+ sk_X509_push(encerts, cert);
+ cert = NULL;
+ }
+ } else {
+ BIO_printf(bio_err, "Warning: recipient certificate file parameters ignored for operation other than -encrypt\n");
+ }
}
}
if (certfile != NULL) {
- if (!load_certs(certfile, &other, FORMAT_PEM, NULL,
- "certificate file")) {
+ if (!load_certs(certfile, 0, &other, NULL, "certificate file")) {
ERR_print_errors(bio_err);
goto end;
}
}
if (recipfile != NULL && (operation == SMIME_DECRYPT)) {
- if ((recip = load_cert(recipfile, FORMAT_PEM,
+ if ((recip = load_cert(recipfile, FORMAT_UNDEF,
"recipient certificate file")) == NULL) {
ERR_print_errors(bio_err);
goto end;
}
}
+ if (originatorfile != NULL) {
+ if ((originator = load_cert(originatorfile, FORMAT_UNDEF,
+ "originator certificate file")) == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
if (operation == SMIME_SIGN_RECEIPT) {
- if ((signer = load_cert(signerfile, FORMAT_PEM,
+ if ((signer = load_cert(signerfile, FORMAT_UNDEF,
"receipt signer certificate file")) == NULL) {
ERR_print_errors(bio_err);
goto end;
}
}
- if (operation == SMIME_DECRYPT) {
+ if ((operation == SMIME_DECRYPT) || (operation == SMIME_ENCRYPT)) {
if (keyfile == NULL)
keyfile = recipfile;
} else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT)) {
@@ -723,31 +881,20 @@ int cms_main(int argc, char **argv)
}
if (keyfile != NULL) {
- key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
+ key = load_key(keyfile, keyform, 0, passin, e, "signing key");
if (key == NULL)
goto end;
}
- in = bio_open_default(infile, 'r', informat);
+ in = bio_open_default(infile, 'r',
+ binary_files ? FORMAT_BINARY : informat);
if (in == NULL)
goto end;
if (operation & SMIME_IP) {
- if (informat == FORMAT_SMIME) {
- cms = SMIME_read_CMS(in, &indata);
- } else if (informat == FORMAT_PEM) {
- cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
- } else if (informat == FORMAT_ASN1) {
- cms = d2i_CMS_bio(in, NULL);
- } else {
- BIO_printf(bio_err, "Bad input format for CMS file\n");
- goto end;
- }
-
- if (cms == NULL) {
- BIO_printf(bio_err, "Error reading S/MIME message\n");
+ cms = load_content_info(informat, in, flags, &indata, "SMIME");
+ if (cms == NULL)
goto end;
- }
if (contfile != NULL) {
BIO_free(indata);
if ((indata = BIO_new_file(contfile, "rb")) == NULL) {
@@ -770,34 +917,25 @@ int cms_main(int argc, char **argv)
if (rctfile != NULL) {
char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r";
+
if ((rctin = BIO_new_file(rctfile, rctmode)) == NULL) {
BIO_printf(bio_err, "Can't open receipt file %s\n", rctfile);
goto end;
}
- if (rctformat == FORMAT_SMIME) {
- rcms = SMIME_read_CMS(rctin, NULL);
- } else if (rctformat == FORMAT_PEM) {
- rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
- } else if (rctformat == FORMAT_ASN1) {
- rcms = d2i_CMS_bio(rctin, NULL);
- } else {
- BIO_printf(bio_err, "Bad input format for receipt\n");
- goto end;
- }
-
- if (rcms == NULL) {
- BIO_printf(bio_err, "Error reading receipt\n");
+ rcms = load_content_info(rctformat, rctin, 0, NULL, "receipt");
+ if (rcms == NULL)
goto end;
- }
}
- out = bio_open_default(outfile, 'w', outformat);
+ out = bio_open_default(outfile, 'w',
+ binary_files ? FORMAT_BINARY : outformat);
if (out == NULL)
goto end;
if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT)) {
- if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
+ if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore)) == NULL)
goto end;
X509_STORE_set_verify_cb(store, cms_cb);
if (vpmtouched)
@@ -807,39 +945,49 @@ int cms_main(int argc, char **argv)
ret = 3;
if (operation == SMIME_DATA_CREATE) {
- cms = CMS_data_create(in, flags);
+ cms = CMS_data_create_ex(in, flags, libctx, app_get0_propq());
} else if (operation == SMIME_DIGEST_CREATE) {
- cms = CMS_digest_create(in, sign_md, flags);
+ cms = CMS_digest_create_ex(in, sign_md, flags, libctx, app_get0_propq());
} else if (operation == SMIME_COMPRESS) {
cms = CMS_compress(in, -1, flags);
} else if (operation == SMIME_ENCRYPT) {
int i;
flags |= CMS_PARTIAL;
- cms = CMS_encrypt(NULL, in, cipher, flags);
+ cms = CMS_encrypt_ex(NULL, in, cipher, flags, libctx, app_get0_propq());
if (cms == NULL)
goto end;
for (i = 0; i < sk_X509_num(encerts); i++) {
CMS_RecipientInfo *ri;
cms_key_param *kparam;
- int tflags = flags;
+ int tflags = flags | CMS_KEY_PARAM;
+ /* This flag enforces allocating the EVP_PKEY_CTX for the recipient here */
+ EVP_PKEY_CTX *pctx;
X509 *x = sk_X509_value(encerts, i);
+ int res;
+
for (kparam = key_first; kparam; kparam = kparam->next) {
if (kparam->idx == i) {
- tflags |= CMS_KEY_PARAM;
break;
}
}
- ri = CMS_add1_recipient_cert(cms, x, tflags);
+ ri = CMS_add1_recipient(cms, x, key, originator, tflags);
if (ri == NULL)
goto end;
+
+ pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
if (kparam != NULL) {
- EVP_PKEY_CTX *pctx;
- pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
if (!cms_set_pkey_param(pctx, kparam->param))
goto end;
}
+
+ res = EVP_PKEY_CTX_ctrl(pctx, -1, -1,
+ EVP_PKEY_CTRL_CIPHER,
+ EVP_CIPHER_get_nid(cipher), NULL);
+ if (res <= 0 && res != -2)
+ goto end;
+
if (CMS_RecipientInfo_type(ri) == CMS_RECIPINFO_AGREE
- && wrap_cipher) {
+ && wrap_cipher != NULL) {
EVP_CIPHER_CTX *wctx;
wctx = CMS_RecipientInfo_kari_get0_ctx(ri);
EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL);
@@ -871,8 +1019,8 @@ int cms_main(int argc, char **argv)
goto end;
}
} else if (operation == SMIME_ENCRYPTED_ENCRYPT) {
- cms = CMS_EncryptedData_encrypt(in, cipher,
- secret_key, secret_keylen, flags);
+ cms = CMS_EncryptedData_encrypt_ex(in, cipher, secret_key,
+ secret_keylen, flags, libctx, app_get0_propq());
} else if (operation == SMIME_SIGN_RECEIPT) {
CMS_ContentInfo *srcms = NULL;
@@ -900,19 +1048,17 @@ int cms_main(int argc, char **argv)
flags |= CMS_STREAM;
}
flags |= CMS_PARTIAL;
- cms = CMS_sign(NULL, NULL, other, in, flags);
+ cms = CMS_sign_ex(NULL, NULL, other, in, flags, libctx, app_get0_propq());
if (cms == NULL)
goto end;
if (econtent_type != NULL)
CMS_set1_eContentType(cms, econtent_type);
- if (rr_to != NULL) {
- rr = make_receipt_request(rr_to, rr_allorfirst, rr_from);
- if (rr == NULL) {
- BIO_puts(bio_err,
- "Signed Receipt Request Creation Error\n");
- goto end;
- }
+ if (rr_to != NULL
+ && ((rr = make_receipt_request(rr_to, rr_allorfirst, rr_from))
+ == NULL)) {
+ BIO_puts(bio_err, "Signed Receipt Request Creation Error\n");
+ goto end;
}
} else {
flags |= CMS_REUSE_DIGEST;
@@ -924,16 +1070,17 @@ int cms_main(int argc, char **argv)
signerfile = sk_OPENSSL_STRING_value(sksigners, i);
keyfile = sk_OPENSSL_STRING_value(skkeys, i);
- signer = load_cert(signerfile, FORMAT_PEM, "signer certificate");
+ signer = load_cert(signerfile, FORMAT_UNDEF, "signer certificate");
if (signer == NULL) {
ret = 2;
goto end;
}
- key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
+ key = load_key(keyfile, keyform, 0, passin, e, "signing key");
if (key == NULL) {
ret = 2;
goto end;
}
+
for (kparam = key_first; kparam; kparam = kparam->next) {
if (kparam->idx == i) {
tflags |= CMS_KEY_PARAM;
@@ -983,7 +1130,7 @@ int cms_main(int argc, char **argv)
}
if (key != NULL) {
- if (!CMS_decrypt_set1_pkey(cms, key, recip)) {
+ if (!CMS_decrypt_set1_pkey_and_peer(cms, key, recip, originator)) {
BIO_puts(bio_err, "Error decrypting CMS using private key\n");
goto end;
}
@@ -1000,7 +1147,7 @@ int cms_main(int argc, char **argv)
BIO_printf(bio_err, "Error decrypting CMS structure\n");
goto end;
}
- } else if (operation == SMIME_DATAOUT) {
+ } else if (operation == SMIME_DATA_OUT) {
if (!CMS_data(cms, out, flags))
goto end;
} else if (operation == SMIME_UNCOMPRESS) {
@@ -1019,16 +1166,18 @@ int cms_main(int argc, char **argv)
goto end;
} else if (operation == SMIME_VERIFY) {
if (CMS_verify(cms, other, store, indata, out, flags) > 0) {
- BIO_printf(bio_err, "Verification successful\n");
+ BIO_printf(bio_err, "%s Verification successful\n",
+ (flags & CMS_CADES) != 0 ? "CAdES" : "CMS");
} else {
- BIO_printf(bio_err, "Verification failure\n");
+ BIO_printf(bio_err, "%s Verification failure\n",
+ (flags & CMS_CADES) != 0 ? "CAdES" : "CMS");
if (verify_retcode)
ret = verify_err + 32;
goto end;
}
if (signerfile != NULL) {
- STACK_OF(X509) *signers;
- signers = CMS_get0_signers(cms);
+ STACK_OF(X509) *signers = CMS_get0_signers(cms);
+
if (!save_certs(signerfile, signers)) {
BIO_printf(bio_err,
"Error writing signers to %s\n", signerfile);
@@ -1049,8 +1198,19 @@ int cms_main(int argc, char **argv)
}
} else {
if (noout) {
- if (print)
- CMS_ContentInfo_print_ctx(out, cms, 0, NULL);
+ if (print) {
+ ASN1_PCTX *pctx = NULL;
+ if (get_nameopt() != XN_FLAG_ONELINE) {
+ pctx = ASN1_PCTX_new();
+ if (pctx != NULL) { /* Print anyway if malloc failed */
+ ASN1_PCTX_set_flags(pctx, ASN1_PCTX_FLAGS_SHOW_ABSENT);
+ ASN1_PCTX_set_str_flags(pctx, get_nameopt());
+ ASN1_PCTX_set_nm_flags(pctx, get_nameopt());
+ }
+ }
+ CMS_ContentInfo_print_ctx(out, cms, 0, pctx);
+ ASN1_PCTX_free(pctx);
+ }
} else if (outformat == FORMAT_SMIME) {
if (to)
BIO_printf(out, "To: %s%s", to, mime_eol);
@@ -1103,6 +1263,9 @@ int cms_main(int argc, char **argv)
X509_free(recip);
X509_free(signer);
EVP_PKEY_free(key);
+ EVP_CIPHER_free(cipher);
+ EVP_CIPHER_free(wrap_cipher);
+ EVP_MD_free(sign_md);
CMS_ContentInfo_free(cms);
CMS_ContentInfo_free(rcms);
release_engine(e);
@@ -1111,6 +1274,7 @@ int cms_main(int argc, char **argv)
BIO_free(indata);
BIO_free_all(out);
OPENSSL_free(passin);
+ NCONF_free(conf);
return ret;
}
@@ -1247,12 +1411,12 @@ static STACK_OF(GENERAL_NAMES) *make_names_stack(STACK_OF(OPENSSL_STRING) *ns)
return NULL;
}
-static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
- *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING)
- *rr_from)
+static CMS_ReceiptRequest
+*make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst,
+ STACK_OF(OPENSSL_STRING) *rr_from)
{
STACK_OF(GENERAL_NAMES) *rct_to = NULL, *rct_from = NULL;
- CMS_ReceiptRequest *rr;
+
rct_to = make_names_stack(rr_to);
if (rct_to == NULL)
goto err;
@@ -1263,9 +1427,8 @@ static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
} else {
rct_from = NULL;
}
- rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from,
- rct_to);
- return rr;
+ return CMS_ReceiptRequest_create0_ex(NULL, -1, rr_allorfirst, rct_from,
+ rct_to, app_get0_libctx());
err:
sk_GENERAL_NAMES_pop_free(rct_to, GENERAL_NAMES_free);
return NULL;
@@ -1288,5 +1451,3 @@ static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
}
return 1;
}
-
-#endif
diff --git a/apps/crl.c b/apps/crl.c
index 031fada14c84..2158a107e551 100644
--- a/apps/crl.c
+++ b/apps/crl.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -19,22 +19,38 @@
#include <openssl/pem.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_INFORM, OPT_IN, OPT_OUTFORM, OPT_OUT, OPT_KEYFORM, OPT_KEY,
OPT_ISSUER, OPT_LASTUPDATE, OPT_NEXTUPDATE, OPT_FINGERPRINT,
- OPT_CRLNUMBER, OPT_BADSIG, OPT_GENDELTA, OPT_CAPATH, OPT_CAFILE,
- OPT_NOCAPATH, OPT_NOCAFILE, OPT_VERIFY, OPT_TEXT, OPT_HASH, OPT_HASH_OLD,
- OPT_NOOUT, OPT_NAMEOPT, OPT_MD
+ OPT_CRLNUMBER, OPT_BADSIG, OPT_GENDELTA, OPT_CAPATH, OPT_CAFILE, OPT_CASTORE,
+ OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, OPT_VERIFY, OPT_DATEOPT, OPT_TEXT, OPT_HASH,
+ OPT_HASH_OLD, OPT_NOOUT, OPT_NAMEOPT, OPT_MD, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS crl_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'F', "Input format; default PEM"},
+ {"verify", OPT_VERIFY, '-', "Verify CRL signature"},
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file - default stdin"},
- {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"},
- {"out", OPT_OUT, '>', "output file - default stdout"},
- {"keyform", OPT_KEYFORM, 'F', "Private key file format (PEM or ENGINE)"},
+ {"inform", OPT_INFORM, 'F', "CRL input format (DER or PEM); has no effect"},
{"key", OPT_KEY, '<', "CRL signing Private key to use"},
+ {"keyform", OPT_KEYFORM, 'F', "Private key file format (DER/PEM/P12); has no effect"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "output file - default stdout"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"},
+ {"dateopt", OPT_DATEOPT, 's', "Datetime format used for printing. (rfc_822/iso_8601). Default is rfc_822."},
+ {"text", OPT_TEXT, '-', "Print out a text format version"},
+ {"hash", OPT_HASH, '-', "Print hash value"},
+#ifndef OPENSSL_NO_MD5
+ {"hash_old", OPT_HASH_OLD, '-', "Print old-style (MD5) hash value"},
+#endif
+ {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
+ {"", OPT_MD, '-', "Any supported digest"},
+
+ OPT_SECTION("CRL"),
{"issuer", OPT_ISSUER, '-', "Print issuer DN"},
{"lastupdate", OPT_LASTUPDATE, '-', "Set lastUpdate field"},
{"nextupdate", OPT_NEXTUPDATE, '-', "Set nextUpdate field"},
@@ -43,20 +59,18 @@ const OPTIONS crl_options[] = {
{"crlnumber", OPT_CRLNUMBER, '-', "Print CRL number"},
{"badsig", OPT_BADSIG, '-', "Corrupt last byte of loaded CRL signature (for test)" },
{"gendelta", OPT_GENDELTA, '<', "Other CRL to compare/diff to the Input one"},
+
+ OPT_SECTION("Certificate"),
{"CApath", OPT_CAPATH, '/', "Verify CRL using certificates in dir"},
{"CAfile", OPT_CAFILE, '<', "Verify CRL using certificates in file name"},
+ {"CAstore", OPT_CASTORE, ':', "Verify CRL using certificates in store URI"},
{"no-CAfile", OPT_NOCAFILE, '-',
"Do not load the default certificates file"},
{"no-CApath", OPT_NOCAPATH, '-',
"Do not load certificates from the default certificates directory"},
- {"verify", OPT_VERIFY, '-', "Verify CRL signature"},
- {"text", OPT_TEXT, '-', "Print out a text format version"},
- {"hash", OPT_HASH, '-', "Print hash value"},
- {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
- {"", OPT_MD, '-', "Any supported digest"},
-#ifndef OPENSSL_NO_MD5
- {"hash_old", OPT_HASH_OLD, '-', "Print old-style (MD5) hash value"},
-#endif
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load certificates from the default certificates store"},
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -69,14 +83,16 @@ int crl_main(int argc, char **argv)
X509_LOOKUP *lookup = NULL;
X509_OBJECT *xobj = NULL;
EVP_PKEY *pkey;
- const EVP_MD *digest = EVP_sha1();
+ EVP_MD *digest = (EVP_MD *)EVP_sha1();
char *infile = NULL, *outfile = NULL, *crldiff = NULL, *keyfile = NULL;
- const char *CAfile = NULL, *CApath = NULL, *prog;
+ char *digestname = NULL;
+ const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL, *prog;
OPTION_CHOICE o;
int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout = 0;
- int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
+ int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyformat = FORMAT_UNDEF;
int ret = 1, num = 0, badsig = 0, fingerprint = 0, crlnumber = 0;
- int text = 0, do_ver = 0, noCAfile = 0, noCApath = 0;
+ int text = 0, do_ver = 0, noCAfile = 0, noCApath = 0, noCAstore = 0;
+ unsigned long dateopt = ASN1_DTFLGS_RFC822;
int i;
#ifndef OPENSSL_NO_MD5
int hash_old = 0;
@@ -109,7 +125,7 @@ int crl_main(int argc, char **argv)
outfile = opt_arg();
break;
case OPT_KEYFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat))
goto opthelp;
break;
case OPT_KEY:
@@ -126,12 +142,19 @@ int crl_main(int argc, char **argv)
CAfile = opt_arg();
do_ver = 1;
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ do_ver = 1;
+ break;
case OPT_NOCAPATH:
noCApath = 1;
break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
case OPT_HASH_OLD:
#ifndef OPENSSL_NO_MD5
hash_old = ++num;
@@ -140,6 +163,10 @@ int crl_main(int argc, char **argv)
case OPT_VERIFY:
do_ver = 1;
break;
+ case OPT_DATEOPT:
+ if (!set_dateopt(&dateopt, opt_arg()))
+ goto opthelp;
+ break;
case OPT_TEXT:
text = 1;
break;
@@ -156,7 +183,7 @@ int crl_main(int argc, char **argv)
nextupdate = ++num;
break;
case OPT_NOOUT:
- noout = ++num;
+ noout = 1;
break;
case OPT_FINGERPRINT:
fingerprint = ++num;
@@ -172,20 +199,31 @@ int crl_main(int argc, char **argv)
goto opthelp;
break;
case OPT_MD:
- if (!opt_md(opt_unknown(), &digest))
- goto opthelp;
+ digestname = opt_unknown();
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No remaining args. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
- x = load_crl(infile, informat);
+ if (digestname != NULL) {
+ if (!opt_md(digestname, &digest))
+ goto opthelp;
+ }
+ x = load_crl(infile, informat, 1, "CRL");
if (x == NULL)
goto end;
if (do_ver) {
- if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
+ if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore)) == NULL)
goto end;
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
if (lookup == NULL)
@@ -204,7 +242,7 @@ int crl_main(int argc, char **argv)
}
pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj));
X509_OBJECT_free(xobj);
- if (!pkey) {
+ if (pkey == NULL) {
BIO_printf(bio_err, "Error getting CRL issuer public key\n");
goto end;
}
@@ -218,17 +256,17 @@ int crl_main(int argc, char **argv)
BIO_printf(bio_err, "verify OK\n");
}
- if (crldiff) {
+ if (crldiff != NULL) {
X509_CRL *newcrl, *delta;
if (!keyfile) {
BIO_puts(bio_err, "Missing CRL signing key\n");
goto end;
}
- newcrl = load_crl(crldiff, informat);
+ newcrl = load_crl(crldiff, informat, 0, "other CRL");
if (!newcrl)
goto end;
pkey = load_key(keyfile, keyformat, 0, NULL, NULL, "CRL signing key");
- if (!pkey) {
+ if (pkey == NULL) {
X509_CRL_free(newcrl);
goto end;
}
@@ -254,39 +292,54 @@ int crl_main(int argc, char **argv)
if (num) {
for (i = 1; i <= num; i++) {
if (issuer == i) {
- print_name(bio_out, "issuer=", X509_CRL_get_issuer(x),
- get_nameopt());
+ print_name(bio_out, "issuer=", X509_CRL_get_issuer(x));
}
if (crlnumber == i) {
ASN1_INTEGER *crlnum;
+
crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL);
BIO_printf(bio_out, "crlNumber=");
if (crlnum) {
+ BIO_puts(bio_out, "0x");
i2a_ASN1_INTEGER(bio_out, crlnum);
ASN1_INTEGER_free(crlnum);
- } else
+ } else {
BIO_puts(bio_out, "<NONE>");
+ }
BIO_printf(bio_out, "\n");
}
if (hash == i) {
- BIO_printf(bio_out, "%08lx\n",
- X509_NAME_hash(X509_CRL_get_issuer(x)));
+ int ok;
+ unsigned long hash_value =
+ X509_NAME_hash_ex(X509_CRL_get_issuer(x), app_get0_libctx(),
+ app_get0_propq(), &ok);
+
+ if (num > 1)
+ BIO_printf(bio_out, "issuer name hash=");
+ if (ok) {
+ BIO_printf(bio_out, "%08lx\n", hash_value);
+ } else {
+ BIO_puts(bio_out, "<ERROR>");
+ goto end;
+ }
}
#ifndef OPENSSL_NO_MD5
if (hash_old == i) {
+ if (num > 1)
+ BIO_printf(bio_out, "issuer name old hash=");
BIO_printf(bio_out, "%08lx\n",
X509_NAME_hash_old(X509_CRL_get_issuer(x)));
}
#endif
if (lastupdate == i) {
BIO_printf(bio_out, "lastUpdate=");
- ASN1_TIME_print(bio_out, X509_CRL_get0_lastUpdate(x));
+ ASN1_TIME_print_ex(bio_out, X509_CRL_get0_lastUpdate(x), dateopt);
BIO_printf(bio_out, "\n");
}
if (nextupdate == i) {
BIO_printf(bio_out, "nextUpdate=");
if (X509_CRL_get0_nextUpdate(x))
- ASN1_TIME_print(bio_out, X509_CRL_get0_nextUpdate(x));
+ ASN1_TIME_print_ex(bio_out, X509_CRL_get0_nextUpdate(x), dateopt);
else
BIO_printf(bio_out, "NONE");
BIO_printf(bio_out, "\n");
@@ -301,7 +354,7 @@ int crl_main(int argc, char **argv)
goto end;
}
BIO_printf(bio_out, "%s Fingerprint=",
- OBJ_nid2sn(EVP_MD_type(digest)));
+ EVP_MD_get0_name(digest));
for (j = 0; j < (int)n; j++) {
BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n)
? '\n' : ':');
@@ -335,6 +388,7 @@ int crl_main(int argc, char **argv)
if (ret != 0)
ERR_print_errors(bio_err);
BIO_free_all(out);
+ EVP_MD_free(digest);
X509_CRL_free(x);
X509_STORE_CTX_free(ctx);
X509_STORE_free(store);
diff --git a/apps/crl2p7.c b/apps/crl2p7.c
deleted file mode 100644
index 3f619bf5278e..000000000000
--- a/apps/crl2p7.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include "apps.h"
-#include "progs.h"
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-#include <openssl/pkcs7.h>
-#include <openssl/pem.h>
-#include <openssl/objects.h>
-
-static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile);
-
-typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOCRL, OPT_CERTFILE
-} OPTION_CHOICE;
-
-const OPTIONS crl2pkcs7_options[] = {
- {"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
- {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
- {"in", OPT_IN, '<', "Input file"},
- {"out", OPT_OUT, '>', "Output file"},
- {"nocrl", OPT_NOCRL, '-', "No crl to load, just certs from '-certfile'"},
- {"certfile", OPT_CERTFILE, '<',
- "File of chain of certs to a trusted CA; can be repeated"},
- {NULL}
-};
-
-int crl2pkcs7_main(int argc, char **argv)
-{
- BIO *in = NULL, *out = NULL;
- PKCS7 *p7 = NULL;
- PKCS7_SIGNED *p7s = NULL;
- STACK_OF(OPENSSL_STRING) *certflst = NULL;
- STACK_OF(X509) *cert_stack = NULL;
- STACK_OF(X509_CRL) *crl_stack = NULL;
- X509_CRL *crl = NULL;
- char *infile = NULL, *outfile = NULL, *prog, *certfile;
- int i = 0, informat = FORMAT_PEM, outformat = FORMAT_PEM, ret = 1, nocrl =
- 0;
- OPTION_CHOICE o;
-
- prog = opt_init(argc, argv, crl2pkcs7_options);
- while ((o = opt_next()) != OPT_EOF) {
- switch (o) {
- case OPT_EOF:
- case OPT_ERR:
- opthelp:
- BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
- goto end;
- case OPT_HELP:
- opt_help(crl2pkcs7_options);
- ret = 0;
- goto end;
- case OPT_INFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
- goto opthelp;
- break;
- case OPT_OUTFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
- goto opthelp;
- break;
- case OPT_IN:
- infile = opt_arg();
- break;
- case OPT_OUT:
- outfile = opt_arg();
- break;
- case OPT_NOCRL:
- nocrl = 1;
- break;
- case OPT_CERTFILE:
- if ((certflst == NULL)
- && (certflst = sk_OPENSSL_STRING_new_null()) == NULL)
- goto end;
- if (!sk_OPENSSL_STRING_push(certflst, opt_arg()))
- goto end;
- break;
- }
- }
- argc = opt_num_rest();
- if (argc != 0)
- goto opthelp;
-
- if (!nocrl) {
- in = bio_open_default(infile, 'r', informat);
- if (in == NULL)
- goto end;
-
- if (informat == FORMAT_ASN1)
- crl = d2i_X509_CRL_bio(in, NULL);
- else if (informat == FORMAT_PEM)
- crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
- if (crl == NULL) {
- BIO_printf(bio_err, "unable to load CRL\n");
- ERR_print_errors(bio_err);
- goto end;
- }
- }
-
- if ((p7 = PKCS7_new()) == NULL)
- goto end;
- if ((p7s = PKCS7_SIGNED_new()) == NULL)
- goto end;
- p7->type = OBJ_nid2obj(NID_pkcs7_signed);
- p7->d.sign = p7s;
- p7s->contents->type = OBJ_nid2obj(NID_pkcs7_data);
-
- if (!ASN1_INTEGER_set(p7s->version, 1))
- goto end;
-
- if (crl != NULL) {
- if ((crl_stack = sk_X509_CRL_new_null()) == NULL)
- goto end;
- p7s->crl = crl_stack;
- sk_X509_CRL_push(crl_stack, crl);
- crl = NULL; /* now part of p7 for OPENSSL_freeing */
- }
-
- if (certflst != NULL) {
- if ((cert_stack = sk_X509_new_null()) == NULL)
- goto end;
- p7s->cert = cert_stack;
-
- for (i = 0; i < sk_OPENSSL_STRING_num(certflst); i++) {
- certfile = sk_OPENSSL_STRING_value(certflst, i);
- if (add_certs_from_file(cert_stack, certfile) < 0) {
- BIO_printf(bio_err, "error loading certificates\n");
- ERR_print_errors(bio_err);
- goto end;
- }
- }
- }
-
- out = bio_open_default(outfile, 'w', outformat);
- if (out == NULL)
- goto end;
-
- if (outformat == FORMAT_ASN1)
- i = i2d_PKCS7_bio(out, p7);
- else if (outformat == FORMAT_PEM)
- i = PEM_write_bio_PKCS7(out, p7);
- if (!i) {
- BIO_printf(bio_err, "unable to write pkcs7 object\n");
- ERR_print_errors(bio_err);
- goto end;
- }
- ret = 0;
- end:
- sk_OPENSSL_STRING_free(certflst);
- BIO_free(in);
- BIO_free_all(out);
- PKCS7_free(p7);
- X509_CRL_free(crl);
-
- return ret;
-}
-
-/*-
- *----------------------------------------------------------------------
- * int add_certs_from_file
- *
- * Read a list of certificates to be checked from a file.
- *
- * Results:
- * number of certs added if successful, -1 if not.
- *----------------------------------------------------------------------
- */
-static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile)
-{
- BIO *in = NULL;
- int count = 0;
- int ret = -1;
- STACK_OF(X509_INFO) *sk = NULL;
- X509_INFO *xi;
-
- in = BIO_new_file(certfile, "r");
- if (in == NULL) {
- BIO_printf(bio_err, "error opening the file, %s\n", certfile);
- goto end;
- }
-
- /* This loads from a file, a stack of x509/crl/pkey sets */
- sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
- if (sk == NULL) {
- BIO_printf(bio_err, "error reading the file, %s\n", certfile);
- goto end;
- }
-
- /* scan over it and pull out the CRL's */
- while (sk_X509_INFO_num(sk)) {
- xi = sk_X509_INFO_shift(sk);
- if (xi->x509 != NULL) {
- sk_X509_push(stack, xi->x509);
- xi->x509 = NULL;
- count++;
- }
- X509_INFO_free(xi);
- }
-
- ret = count;
- end:
- /* never need to OPENSSL_free x */
- BIO_free(in);
- sk_X509_INFO_free(sk);
- return ret;
-}
diff --git a/apps/crl2pkcs7.c b/apps/crl2pkcs7.c
new file mode 100644
index 000000000000..fe59e654270d
--- /dev/null
+++ b/apps/crl2pkcs7.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/pkcs7.h>
+#include <openssl/pem.h>
+#include <openssl/objects.h>
+
+static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile);
+
+typedef enum OPTION_choice {
+ OPT_COMMON,
+ OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOCRL, OPT_CERTFILE,
+ OPT_PROV_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS crl2pkcs7_options[] = {
+ OPT_SECTION("General"),
+ {"help", OPT_HELP, '-', "Display this summary"},
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, '<', "Input file"},
+ {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
+ {"nocrl", OPT_NOCRL, '-', "No crl to load, just certs from '-certfile'"},
+ {"certfile", OPT_CERTFILE, '<',
+ "File of chain of certs to a trusted CA; can be repeated"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
+
+ OPT_PROV_OPTIONS,
+ {NULL}
+};
+
+int crl2pkcs7_main(int argc, char **argv)
+{
+ BIO *in = NULL, *out = NULL;
+ PKCS7 *p7 = NULL;
+ PKCS7_SIGNED *p7s = NULL;
+ STACK_OF(OPENSSL_STRING) *certflst = NULL;
+ STACK_OF(X509) *cert_stack = NULL;
+ STACK_OF(X509_CRL) *crl_stack = NULL;
+ X509_CRL *crl = NULL;
+ char *infile = NULL, *outfile = NULL, *prog, *certfile;
+ int i = 0, informat = FORMAT_PEM, outformat = FORMAT_PEM, ret = 1, nocrl =
+ 0;
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, crl2pkcs7_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(crl2pkcs7_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
+ goto opthelp;
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_NOCRL:
+ nocrl = 1;
+ break;
+ case OPT_CERTFILE:
+ if ((certflst == NULL)
+ && (certflst = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ if (!sk_OPENSSL_STRING_push(certflst, opt_arg()))
+ goto end;
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
+ }
+ }
+
+ /* No remaining args. */
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ if (!nocrl) {
+ in = bio_open_default(infile, 'r', informat);
+ if (in == NULL)
+ goto end;
+
+ if (informat == FORMAT_ASN1)
+ crl = d2i_X509_CRL_bio(in, NULL);
+ else if (informat == FORMAT_PEM)
+ crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
+ if (crl == NULL) {
+ BIO_printf(bio_err, "unable to load CRL\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if ((p7 = PKCS7_new()) == NULL)
+ goto end;
+ if ((p7s = PKCS7_SIGNED_new()) == NULL)
+ goto end;
+ p7->type = OBJ_nid2obj(NID_pkcs7_signed);
+ p7->d.sign = p7s;
+ p7s->contents->type = OBJ_nid2obj(NID_pkcs7_data);
+
+ if (!ASN1_INTEGER_set(p7s->version, 1))
+ goto end;
+
+ if (crl != NULL) {
+ if ((crl_stack = sk_X509_CRL_new_null()) == NULL)
+ goto end;
+ p7s->crl = crl_stack;
+ sk_X509_CRL_push(crl_stack, crl);
+ crl = NULL; /* now part of p7 for OPENSSL_freeing */
+ }
+
+ if (certflst != NULL) {
+ if ((cert_stack = sk_X509_new_null()) == NULL)
+ goto end;
+ p7s->cert = cert_stack;
+
+ for (i = 0; i < sk_OPENSSL_STRING_num(certflst); i++) {
+ certfile = sk_OPENSSL_STRING_value(certflst, i);
+ if (add_certs_from_file(cert_stack, certfile) < 0) {
+ BIO_printf(bio_err, "error loading certificates\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ }
+
+ out = bio_open_default(outfile, 'w', outformat);
+ if (out == NULL)
+ goto end;
+
+ if (outformat == FORMAT_ASN1)
+ i = i2d_PKCS7_bio(out, p7);
+ else if (outformat == FORMAT_PEM)
+ i = PEM_write_bio_PKCS7(out, p7);
+ if (!i) {
+ BIO_printf(bio_err, "unable to write pkcs7 object\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ ret = 0;
+ end:
+ sk_OPENSSL_STRING_free(certflst);
+ BIO_free(in);
+ BIO_free_all(out);
+ PKCS7_free(p7);
+ X509_CRL_free(crl);
+
+ return ret;
+}
+
+/*-
+ *----------------------------------------------------------------------
+ * int add_certs_from_file
+ *
+ * Read a list of certificates to be checked from a file.
+ *
+ * Results:
+ * number of certs added if successful, -1 if not.
+ *----------------------------------------------------------------------
+ */
+static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile)
+{
+ BIO *in = NULL;
+ int count = 0;
+ int ret = -1;
+ STACK_OF(X509_INFO) *sk = NULL;
+ X509_INFO *xi;
+
+ in = BIO_new_file(certfile, "r");
+ if (in == NULL) {
+ BIO_printf(bio_err, "error opening the file, %s\n", certfile);
+ goto end;
+ }
+
+ /* This loads from a file, a stack of x509/crl/pkey sets */
+ sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
+ if (sk == NULL) {
+ BIO_printf(bio_err, "error reading the file, %s\n", certfile);
+ goto end;
+ }
+
+ /* scan over it and pull out the CRL's */
+ while (sk_X509_INFO_num(sk)) {
+ xi = sk_X509_INFO_shift(sk);
+ if (xi->x509 != NULL) {
+ sk_X509_push(stack, xi->x509);
+ xi->x509 = NULL;
+ count++;
+ }
+ X509_INFO_free(xi);
+ }
+
+ ret = count;
+ end:
+ /* never need to OPENSSL_free x */
+ BIO_free(in);
+ sk_X509_INFO_free(sk);
+ return ret;
+}
diff --git a/apps/dgst.c b/apps/dgst.c
index f9b184be4cc1..1042d940f49c 100644
--- a/apps/dgst.c
+++ b/apps/dgst.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -24,7 +24,7 @@
#undef BUFSIZE
#define BUFSIZE 1024*8
-int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
+int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen,
EVP_PKEY *key, unsigned char *sigin, int siglen,
const char *sig_name, const char *md_name,
const char *file);
@@ -36,49 +36,58 @@ struct doall_dgst_digests {
};
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_LIST,
+ OPT_COMMON,
+ OPT_LIST,
OPT_C, OPT_R, OPT_OUT, OPT_SIGN, OPT_PASSIN, OPT_VERIFY,
OPT_PRVERIFY, OPT_SIGNATURE, OPT_KEYFORM, OPT_ENGINE, OPT_ENGINE_IMPL,
OPT_HEX, OPT_BINARY, OPT_DEBUG, OPT_FIPS_FINGERPRINT,
- OPT_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT,
+ OPT_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT, OPT_XOFLEN,
OPT_DIGEST,
- OPT_R_ENUM
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS dgst_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] [file...]\n"},
- {OPT_HELP_STR, 1, '-',
- " file... files to digest (default is stdin)\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"list", OPT_LIST, '-', "List digests"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
+ {"engine_impl", OPT_ENGINE_IMPL, '-',
+ "Also use engine given by -engine for digest operations"},
+#endif
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+
+ OPT_SECTION("Output"),
{"c", OPT_C, '-', "Print the digest with separating colons"},
{"r", OPT_R, '-', "Print the digest in coreutils format"},
{"out", OPT_OUT, '>', "Output to filename rather than stdout"},
- {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
- {"sign", OPT_SIGN, 's', "Sign digest using private key"},
- {"verify", OPT_VERIFY, 's',
- "Verify a signature using public key"},
- {"prverify", OPT_PRVERIFY, 's',
- "Verify a signature using private key"},
- {"signature", OPT_SIGNATURE, '<', "File with signature to verify"},
- {"keyform", OPT_KEYFORM, 'f', "Key file format (PEM or ENGINE)"},
+ {"keyform", OPT_KEYFORM, 'f', "Key file format (ENGINE, other values ignored)"},
{"hex", OPT_HEX, '-', "Print as hex dump"},
{"binary", OPT_BINARY, '-', "Print in binary form"},
+ {"xoflen", OPT_XOFLEN, 'p', "Output length for XOF algorithms. To obtain the maximum security strength set this to 32 (or greater) for SHAKE128, and 64 (or greater) for SHAKE256"},
{"d", OPT_DEBUG, '-', "Print debug info"},
{"debug", OPT_DEBUG, '-', "Print debug info"},
- {"fips-fingerprint", OPT_FIPS_FINGERPRINT, '-',
- "Compute HMAC with the key used in OpenSSL-FIPS fingerprint"},
+
+ OPT_SECTION("Signing"),
+ {"sign", OPT_SIGN, 's', "Sign digest using private key"},
+ {"verify", OPT_VERIFY, 's', "Verify a signature using public key"},
+ {"prverify", OPT_PRVERIFY, 's', "Verify a signature using private key"},
+ {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
+ {"signature", OPT_SIGNATURE, '<', "File with signature to verify"},
{"hmac", OPT_HMAC, 's', "Create hashed MAC with key"},
{"mac", OPT_MAC, 's', "Create MAC (not necessarily HMAC)"},
- {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
{"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form or key"},
{"", OPT_DIGEST, '-', "Any supported digest"},
+ {"fips-fingerprint", OPT_FIPS_FINGERPRINT, '-',
+ "Compute HMAC with the key used in OpenSSL-FIPS fingerprint"},
+
OPT_R_OPTIONS,
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
- {"engine_impl", OPT_ENGINE_IMPL, '-',
- "Also use engine given by -engine for digest operations"},
-#endif
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"file", 0, 0, "Files to digest (optional; default is stdin)"},
{NULL}
};
@@ -89,21 +98,24 @@ int dgst_main(int argc, char **argv)
EVP_PKEY *sigkey = NULL;
STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL;
char *hmac_key = NULL;
- char *mac_name = NULL;
+ char *mac_name = NULL, *digestname = NULL;
char *passinarg = NULL, *passin = NULL;
- const EVP_MD *md = NULL, *m;
+ EVP_MD *md = NULL;
const char *outfile = NULL, *keyfile = NULL, *prog = NULL;
const char *sigfile = NULL;
+ const char *md_name = NULL;
OPTION_CHOICE o;
- int separator = 0, debug = 0, keyform = FORMAT_PEM, siglen = 0;
- int i, ret = 1, out_bin = -1, want_pub = 0, do_verify = 0;
+ int separator = 0, debug = 0, keyform = FORMAT_UNDEF, siglen = 0;
+ int i, ret = EXIT_FAILURE, out_bin = -1, want_pub = 0, do_verify = 0;
+ int xoflen = 0;
unsigned char *buf = NULL, *sigbuf = NULL;
int engine_impl = 0;
struct doall_dgst_digests dec;
- prog = opt_progname(argv[0]);
buf = app_malloc(BUFSIZE, "I/O buffer");
- md = EVP_get_digestbyname(prog);
+ md = (EVP_MD *)EVP_get_digestbyname(argv[0]);
+ if (md != NULL)
+ digestname = argv[0];
prog = opt_init(argc, argv, dgst_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -115,7 +127,7 @@ int dgst_main(int argc, char **argv)
goto end;
case OPT_HELP:
opt_help(dgst_options);
- ret = 0;
+ ret = EXIT_SUCCESS;
goto end;
case OPT_LIST:
BIO_printf(bio_out, "Supported digests:\n");
@@ -124,7 +136,7 @@ int dgst_main(int argc, char **argv)
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH,
show_digests, &dec);
BIO_printf(bio_out, "\n");
- ret = 0;
+ ret = EXIT_SUCCESS;
goto end;
case OPT_C:
separator = 1;
@@ -172,6 +184,9 @@ int dgst_main(int argc, char **argv)
case OPT_BINARY:
out_bin = 1;
break;
+ case OPT_XOFLEN:
+ xoflen = atoi(opt_arg());
+ break;
case OPT_DEBUG:
debug = 1;
break;
@@ -197,18 +212,29 @@ int dgst_main(int argc, char **argv)
goto opthelp;
break;
case OPT_DIGEST:
- if (!opt_md(opt_unknown(), &m))
- goto opthelp;
- md = m;
+ digestname = opt_unknown();
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
break;
}
}
+
+ /* Remaining args are files to digest. */
argc = opt_num_rest();
argv = opt_rest();
if (keyfile != NULL && argc > 1) {
BIO_printf(bio_err, "%s: Can only sign or verify one file.\n", prog);
goto end;
}
+ if (!app_RAND_load())
+ goto end;
+
+ if (digestname != NULL) {
+ if (!opt_md(digestname, &md))
+ goto opthelp;
+ }
if (do_verify && sigfile == NULL) {
BIO_printf(bio_err,
@@ -220,13 +246,11 @@ int dgst_main(int argc, char **argv)
in = BIO_new(BIO_s_file());
bmd = BIO_new(BIO_f_md());
- if ((in == NULL) || (bmd == NULL)) {
- ERR_print_errors(bio_err);
+ if (in == NULL || bmd == NULL)
goto end;
- }
if (debug) {
- BIO_set_callback(in, BIO_debug_callback);
+ BIO_set_callback_ex(in, BIO_debug_callback_ex);
/* needed for windows 3.1 */
BIO_set_callback_arg(in, (char *)bio_err);
}
@@ -248,7 +272,7 @@ int dgst_main(int argc, char **argv)
goto end;
if ((!(mac_name == NULL) + !(keyfile == NULL) + !(hmac_key == NULL)) > 1) {
- BIO_printf(bio_err, "MAC and Signing key cannot both be specified\n");
+ BIO_printf(bio_err, "MAC and signing key cannot both be specified\n");
goto end;
}
@@ -256,16 +280,16 @@ int dgst_main(int argc, char **argv)
int type;
if (want_pub)
- sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "key file");
+ sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "public key");
else
- sigkey = load_key(keyfile, keyform, 0, passin, e, "key file");
+ sigkey = load_key(keyfile, keyform, 0, passin, e, "private key");
if (sigkey == NULL) {
/*
* load_[pub]key() has already printed an appropriate message
*/
goto end;
}
- type = EVP_PKEY_id(sigkey);
+ type = EVP_PKEY_get_id(sigkey);
if (type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448) {
/*
* We implement PureEdDSA for these which doesn't have a separate
@@ -278,36 +302,34 @@ int dgst_main(int argc, char **argv)
if (mac_name != NULL) {
EVP_PKEY_CTX *mac_ctx = NULL;
- int r = 0;
- if (!init_gen_str(&mac_ctx, mac_name, impl, 0))
- goto mac_end;
+
+ if (!init_gen_str(&mac_ctx, mac_name, impl, 0, NULL, NULL))
+ goto end;
if (macopts != NULL) {
- char *macopt;
for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) {
- macopt = sk_OPENSSL_STRING_value(macopts, i);
+ char *macopt = sk_OPENSSL_STRING_value(macopts, i);
+
if (pkey_ctrl_string(mac_ctx, macopt) <= 0) {
- BIO_printf(bio_err,
- "MAC parameter error \"%s\"\n", macopt);
- ERR_print_errors(bio_err);
- goto mac_end;
+ EVP_PKEY_CTX_free(mac_ctx);
+ BIO_printf(bio_err, "MAC parameter error \"%s\"\n", macopt);
+ goto end;
}
}
}
- if (EVP_PKEY_keygen(mac_ctx, &sigkey) <= 0) {
- BIO_puts(bio_err, "Error generating key\n");
- ERR_print_errors(bio_err);
- goto mac_end;
- }
- r = 1;
- mac_end:
+
+ sigkey = app_keygen(mac_ctx, mac_name, 0, 0 /* not verbose */);
+ /* Verbose output would make external-tests gost-engine fail */
EVP_PKEY_CTX_free(mac_ctx);
- if (r == 0)
- goto end;
}
if (hmac_key != NULL) {
+ if (md == NULL) {
+ md = (EVP_MD *)EVP_sha256();
+ digestname = SN_sha256;
+ }
sigkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, impl,
- (unsigned char *)hmac_key, -1);
+ (unsigned char *)hmac_key,
+ strlen(hmac_key));
if (sigkey == NULL)
goto end;
}
@@ -315,28 +337,37 @@ int dgst_main(int argc, char **argv)
if (sigkey != NULL) {
EVP_MD_CTX *mctx = NULL;
EVP_PKEY_CTX *pctx = NULL;
- int r;
+ int res;
+
if (BIO_get_md_ctx(bmd, &mctx) <= 0) {
BIO_printf(bio_err, "Error getting context\n");
- ERR_print_errors(bio_err);
goto end;
}
if (do_verify)
- r = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey);
+ if (impl == NULL)
+ res = EVP_DigestVerifyInit_ex(mctx, &pctx, digestname,
+ app_get0_libctx(),
+ app_get0_propq(), sigkey, NULL);
+ else
+ res = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey);
else
- r = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey);
- if (!r) {
+ if (impl == NULL)
+ res = EVP_DigestSignInit_ex(mctx, &pctx, digestname,
+ app_get0_libctx(),
+ app_get0_propq(), sigkey, NULL);
+ else
+ res = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey);
+ if (res == 0) {
BIO_printf(bio_err, "Error setting context\n");
- ERR_print_errors(bio_err);
goto end;
}
if (sigopts != NULL) {
- char *sigopt;
for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
- sigopt = sk_OPENSSL_STRING_value(sigopts, i);
+ char *sigopt = sk_OPENSSL_STRING_value(sigopts, i);
+
if (pkey_ctrl_string(pctx, sigopt) <= 0) {
- BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt);
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Signature parameter error \"%s\"\n",
+ sigopt);
goto end;
}
}
@@ -347,32 +378,29 @@ int dgst_main(int argc, char **argv)
EVP_MD_CTX *mctx = NULL;
if (BIO_get_md_ctx(bmd, &mctx) <= 0) {
BIO_printf(bio_err, "Error getting context\n");
- ERR_print_errors(bio_err);
goto end;
}
if (md == NULL)
- md = EVP_sha256();
+ md = (EVP_MD *)EVP_sha256();
if (!EVP_DigestInit_ex(mctx, md, impl)) {
BIO_printf(bio_err, "Error setting digest\n");
- ERR_print_errors(bio_err);
goto end;
}
}
if (sigfile != NULL && sigkey != NULL) {
BIO *sigbio = BIO_new_file(sigfile, "rb");
+
if (sigbio == NULL) {
BIO_printf(bio_err, "Error opening signature file %s\n", sigfile);
- ERR_print_errors(bio_err);
goto end;
}
- siglen = EVP_PKEY_size(sigkey);
+ siglen = EVP_PKEY_get_size(sigkey);
sigbuf = app_malloc(siglen, "signature buffer");
siglen = BIO_read(sigbio, sigbuf, siglen);
BIO_free(sigbio);
if (siglen <= 0) {
BIO_printf(bio_err, "Error reading signature file %s\n", sigfile);
- ERR_print_errors(bio_err);
goto end;
}
}
@@ -380,48 +408,62 @@ int dgst_main(int argc, char **argv)
if (md == NULL) {
EVP_MD_CTX *tctx;
+
BIO_get_md_ctx(bmd, &tctx);
- md = EVP_MD_CTX_md(tctx);
+ md = EVP_MD_CTX_get1_md(tctx);
+ }
+ if (md != NULL)
+ md_name = EVP_MD_get0_name(md);
+
+ if (xoflen > 0) {
+ if (!(EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF)) {
+ BIO_printf(bio_err, "Length can only be specified for XOF\n");
+ goto end;
+ }
+ /*
+ * Signing using XOF is not supported by any algorithms currently since
+ * each algorithm only calls EVP_DigestFinal_ex() in their sign_final
+ * and verify_final methods.
+ */
+ if (sigkey != NULL) {
+ BIO_printf(bio_err, "Signing key cannot be specified for XOF\n");
+ goto end;
+ }
}
if (argc == 0) {
BIO_set_fp(in, stdin, BIO_NOCLOSE);
- ret = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf,
- siglen, NULL, NULL, "stdin");
+ ret = do_fp(out, buf, inp, separator, out_bin, xoflen, sigkey, sigbuf,
+ siglen, NULL, md_name, "stdin");
} else {
- const char *md_name = NULL, *sig_name = NULL;
- if (!out_bin) {
- if (sigkey != NULL) {
- const EVP_PKEY_ASN1_METHOD *ameth;
- ameth = EVP_PKEY_get0_asn1(sigkey);
- if (ameth)
- EVP_PKEY_asn1_get0_info(NULL, NULL,
- NULL, NULL, &sig_name, ameth);
- }
- if (md != NULL)
- md_name = EVP_MD_name(md);
+ const char *sig_name = NULL;
+
+ if (out_bin == 0) {
+ if (sigkey != NULL)
+ sig_name = EVP_PKEY_get0_type_name(sigkey);
}
- ret = 0;
+ ret = EXIT_SUCCESS;
for (i = 0; i < argc; i++) {
- int r;
if (BIO_read_filename(in, argv[i]) <= 0) {
perror(argv[i]);
- ret++;
+ ret = EXIT_FAILURE;
continue;
} else {
- r = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf,
- siglen, sig_name, md_name, argv[i]);
+ if (do_fp(out, buf, inp, separator, out_bin, xoflen,
+ sigkey, sigbuf, siglen, sig_name, md_name, argv[i]))
+ ret = EXIT_FAILURE;
}
- if (r)
- ret = r;
(void)BIO_reset(bmd);
}
}
end:
+ if (ret != EXIT_SUCCESS)
+ ERR_print_errors(bio_err);
OPENSSL_clear_free(buf, BUFSIZE);
BIO_free(in);
OPENSSL_free(passin);
BIO_free_all(out);
+ EVP_MD_free(md);
EVP_PKEY_free(sigkey);
sk_OPENSSL_STRING_free(sigopts);
sk_OPENSSL_STRING_free(macopts);
@@ -444,7 +486,7 @@ static void show_digests(const OBJ_NAME *name, void *arg)
return;
/* Filter out message digests that we cannot use */
- md = EVP_get_digestbyname(name->name);
+ md = EVP_MD_fetch(app_get0_libctx(), name->name, app_get0_propq());
if (md == NULL)
return;
@@ -496,20 +538,19 @@ static const char *newline_escape_filename(const char *file, int * backslash)
}
-int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
+int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen,
EVP_PKEY *key, unsigned char *sigin, int siglen,
const char *sig_name, const char *md_name,
const char *file)
{
size_t len = BUFSIZE;
- int i, backslash = 0, ret = 1;
- unsigned char *sigbuf = NULL;
+ int i, backslash = 0, ret = EXIT_FAILURE;
+ unsigned char *allocated_buf = NULL;
while (BIO_pending(bp) || !BIO_eof(bp)) {
i = BIO_read(bp, (char *)buf, BUFSIZE);
if (i < 0) {
- BIO_printf(bio_err, "Read Error in %s\n", file);
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Read error in %s\n", file);
goto end;
}
if (i == 0)
@@ -522,37 +563,52 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
if (i > 0) {
BIO_printf(out, "Verified OK\n");
} else if (i == 0) {
- BIO_printf(out, "Verification Failure\n");
+ BIO_printf(out, "Verification failure\n");
goto end;
} else {
- BIO_printf(bio_err, "Error Verifying Data\n");
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Error verifying data\n");
goto end;
}
- ret = 0;
+ ret = EXIT_SUCCESS;
goto end;
}
if (key != NULL) {
EVP_MD_CTX *ctx;
- int pkey_len;
+ size_t tmplen;
+
BIO_get_md_ctx(bp, &ctx);
- pkey_len = EVP_PKEY_size(key);
- if (pkey_len > BUFSIZE) {
- len = pkey_len;
- sigbuf = app_malloc(len, "Signature buffer");
- buf = sigbuf;
+ if (!EVP_DigestSignFinal(ctx, NULL, &tmplen)) {
+ BIO_printf(bio_err, "Error getting maximum length of signed data\n");
+ goto end;
+ }
+ if (tmplen > BUFSIZE) {
+ len = tmplen;
+ allocated_buf = app_malloc(len, "Signature buffer");
+ buf = allocated_buf;
}
if (!EVP_DigestSignFinal(ctx, buf, &len)) {
- BIO_printf(bio_err, "Error Signing Data\n");
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Error signing data\n");
+ goto end;
+ }
+ } else if (xoflen > 0) {
+ EVP_MD_CTX *ctx;
+
+ len = xoflen;
+ if (len > BUFSIZE) {
+ allocated_buf = app_malloc(len, "Digest buffer");
+ buf = allocated_buf;
+ }
+
+ BIO_get_md_ctx(bp, &ctx);
+
+ if (!EVP_DigestFinalXOF(ctx, buf, len)) {
+ BIO_printf(bio_err, "Error Digesting Data\n");
goto end;
}
} else {
len = BIO_gets(bp, (char *)buf, BUFSIZE);
- if ((int)len < 0) {
- ERR_print_errors(bio_err);
+ if ((int)len < 0)
goto end;
- }
}
if (binout) {
@@ -587,10 +643,10 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
BIO_printf(out, "\n");
}
- ret = 0;
+ ret = EXIT_SUCCESS;
end:
- if (sigbuf != NULL)
- OPENSSL_clear_free(sigbuf, len);
+ if (allocated_buf != NULL)
+ OPENSSL_clear_free(allocated_buf, len);
return ret;
}
diff --git a/apps/dh1024.pem b/apps/dh1024.pem
deleted file mode 100644
index 813e8a4a4822..000000000000
--- a/apps/dh1024.pem
+++ /dev/null
@@ -1,10 +0,0 @@
------BEGIN DH PARAMETERS-----
-MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR
-Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL
-/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC
------END DH PARAMETERS-----
-
-These are the 1024-bit DH parameters from "Internet Key Exchange
-Protocol Version 2 (IKEv2)": https://tools.ietf.org/html/rfc5996
-
-See https://tools.ietf.org/html/rfc2412 for how they were generated.
diff --git a/apps/dh2048.pem b/apps/dh2048.pem
deleted file mode 100644
index 288a20997e5a..000000000000
--- a/apps/dh2048.pem
+++ /dev/null
@@ -1,14 +0,0 @@
------BEGIN DH PARAMETERS-----
-MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb
-IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft
-awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT
-mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh
-fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq
-5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg==
------END DH PARAMETERS-----
-
-These are the 2048-bit DH parameters from "More Modular Exponential
-(MODP) Diffie-Hellman groups for Internet Key Exchange (IKE)":
-https://tools.ietf.org/html/rfc3526
-
-See https://tools.ietf.org/html/rfc2412 for how they were generated.
diff --git a/apps/dh4096.pem b/apps/dh4096.pem
deleted file mode 100644
index 08560e1284e2..000000000000
--- a/apps/dh4096.pem
+++ /dev/null
@@ -1,19 +0,0 @@
------BEGIN DH PARAMETERS-----
-MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb
-IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft
-awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT
-mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh
-fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq
-5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM
-fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq
-ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI
-ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O
-+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI
-HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQI=
------END DH PARAMETERS-----
-
-These are the 4096-bit DH parameters from "More Modular Exponential
-(MODP) Diffie-Hellman groups for Internet Key Exchange (IKE)":
-https://tools.ietf.org/html/rfc3526
-
-See https://tools.ietf.org/html/rfc2412 for how they were generated.
diff --git a/apps/dhparam.c b/apps/dhparam.c
index 98c73214b53e..43906cea5649 100644
--- a/apps/dhparam.c
+++ b/apps/dhparam.c
@@ -1,13 +1,14 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/opensslconf.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
@@ -17,61 +18,73 @@
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/bn.h>
+#include <openssl/dsa.h>
#include <openssl/dh.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
-
-#ifndef OPENSSL_NO_DSA
-# include <openssl/dsa.h>
-#endif
+#include <openssl/core_names.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/param_build.h>
+#include <openssl/encoder.h>
+#include <openssl/decoder.h>
#define DEFBITS 2048
-static int dh_cb(int p, int n, BN_GENCB *cb);
+static EVP_PKEY *dsa_to_dh(EVP_PKEY *dh);
+static int gendh_cb(EVP_PKEY_CTX *ctx);
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT,
OPT_ENGINE, OPT_CHECK, OPT_TEXT, OPT_NOOUT,
- OPT_DSAPARAM, OPT_C, OPT_2, OPT_5,
- OPT_R_ENUM
+ OPT_DSAPARAM, OPT_2, OPT_3, OPT_5,
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS dhparam_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [flags] [numbits]\n"},
- {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [numbits]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"in", OPT_IN, '<', "Input file"},
- {"inform", OPT_INFORM, 'F', "Input format, DER or PEM"},
- {"outform", OPT_OUTFORM, 'F', "Output format, DER or PEM"},
- {"out", OPT_OUT, '>', "Output file"},
{"check", OPT_CHECK, '-', "Check the DH parameters"},
- {"text", OPT_TEXT, '-', "Print a text form of the DH parameters"},
- {"noout", OPT_NOOUT, '-', "Don't output any DH parameters"},
- OPT_R_OPTIONS,
- {"C", OPT_C, '-', "Print C code"},
- {"2", OPT_2, '-', "Generate parameters using 2 as the generator value"},
- {"5", OPT_5, '-', "Generate parameters using 5 as the generator value"},
-#ifndef OPENSSL_NO_DSA
+#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_DEPRECATED_3_0)
{"dsaparam", OPT_DSAPARAM, '-',
"Read or generate DSA parameters, convert to DH"},
#endif
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
#endif
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, '<', "Input file"},
+ {"inform", OPT_INFORM, 'F', "Input format, DER or PEM"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'F', "Output format, DER or PEM"},
+ {"text", OPT_TEXT, '-', "Print a text form of the DH parameters"},
+ {"noout", OPT_NOOUT, '-', "Don't output any DH parameters"},
+ {"2", OPT_2, '-', "Generate parameters using 2 as the generator value"},
+ {"3", OPT_3, '-', "Generate parameters using 3 as the generator value"},
+ {"5", OPT_5, '-', "Generate parameters using 5 as the generator value"},
+
+ OPT_R_OPTIONS,
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"numbits", 0, 0, "Number of bits if generating parameters (optional)"},
{NULL}
};
int dhparam_main(int argc, char **argv)
{
BIO *in = NULL, *out = NULL;
- DH *dh = NULL;
+ EVP_PKEY *pkey = NULL, *tmppkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
char *infile = NULL, *outfile = NULL, *prog;
ENGINE *e = NULL;
-#ifndef OPENSSL_NO_DSA
int dsaparam = 0;
-#endif
- int i, text = 0, C = 0, ret = 1, num = 0, g = 0;
+ int text = 0, ret = 1, num = 0, g = 0;
int informat = FORMAT_PEM, outformat = FORMAT_PEM, check = 0, noout = 0;
OPTION_CHOICE o;
@@ -111,16 +124,14 @@ int dhparam_main(int argc, char **argv)
text = 1;
break;
case OPT_DSAPARAM:
-#ifndef OPENSSL_NO_DSA
dsaparam = 1;
-#endif
- break;
- case OPT_C:
- C = 1;
break;
case OPT_2:
g = 2;
break;
+ case OPT_3:
+ g = 3;
+ break;
case OPT_5:
g = 5;
break;
@@ -131,24 +142,33 @@ int dhparam_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* One optional argument, bitsize to generate. */
argc = opt_num_rest();
argv = opt_rest();
-
- if (argv[0] != NULL && (!opt_int(argv[0], &num) || num <= 0))
+ if (argc == 1) {
+ if (!opt_int(argv[0], &num) || num <= 0)
+ goto opthelp;
+ } else if (argc != 0) {
+ goto opthelp;
+ }
+ if (!app_RAND_load())
goto end;
if (g && !num)
num = DEFBITS;
-#ifndef OPENSSL_NO_DSA
if (dsaparam && g) {
BIO_printf(bio_err,
- "generator may not be chosen for DSA parameters\n");
+ "Error, generator may not be chosen for DSA parameters\n");
goto end;
}
-#endif
out = bio_open_default(outfile, 'w', outformat);
if (out == NULL)
@@ -159,216 +179,238 @@ int dhparam_main(int argc, char **argv)
g = 2;
if (num) {
+ const char *alg = dsaparam ? "DSA" : "DH";
+
+ if (infile != NULL) {
+ BIO_printf(bio_err, "Warning, input file %s ignored\n", infile);
+ }
- BN_GENCB *cb;
- cb = BN_GENCB_new();
- if (cb == NULL) {
- ERR_print_errors(bio_err);
+ ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), alg, app_get0_propq());
+ if (ctx == NULL) {
+ BIO_printf(bio_err,
+ "Error, %s param generation context allocation failed\n",
+ alg);
goto end;
}
+ EVP_PKEY_CTX_set_cb(ctx, gendh_cb);
+ EVP_PKEY_CTX_set_app_data(ctx, bio_err);
+ BIO_printf(bio_err,
+ "Generating %s parameters, %d bit long %sprime\n",
+ alg, num, dsaparam ? "" : "safe ");
- BN_GENCB_set(cb, dh_cb, bio_err);
+ if (EVP_PKEY_paramgen_init(ctx) <= 0) {
+ BIO_printf(bio_err,
+ "Error, unable to initialise %s parameters\n",
+ alg);
+ goto end;
+ }
-#ifndef OPENSSL_NO_DSA
if (dsaparam) {
- DSA *dsa = DSA_new();
-
- BIO_printf(bio_err,
- "Generating DSA parameters, %d bit long prime\n", num);
- if (dsa == NULL
- || !DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL,
- cb)) {
- DSA_free(dsa);
- BN_GENCB_free(cb);
- ERR_print_errors(bio_err);
+ if (EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, num) <= 0) {
+ BIO_printf(bio_err, "Error, unable to set DSA prime length\n");
goto end;
}
-
- dh = DSA_dup_DH(dsa);
- DSA_free(dsa);
- if (dh == NULL) {
- BN_GENCB_free(cb);
- ERR_print_errors(bio_err);
+ } else {
+ if (EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, num) <= 0) {
+ BIO_printf(bio_err, "Error, unable to set DH prime length\n");
goto end;
}
- } else
-#endif
- {
- dh = DH_new();
- BIO_printf(bio_err,
- "Generating DH parameters, %d bit long safe prime, generator %d\n",
- num, g);
- BIO_printf(bio_err, "This is going to take a long time\n");
- if (dh == NULL || !DH_generate_parameters_ex(dh, num, g, cb)) {
- BN_GENCB_free(cb);
- ERR_print_errors(bio_err);
+ if (EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, g) <= 0) {
+ BIO_printf(bio_err, "Error, unable to set generator\n");
goto end;
}
}
- BN_GENCB_free(cb);
+ tmppkey = app_paramgen(ctx, alg);
+ EVP_PKEY_CTX_free(ctx);
+ ctx = NULL;
+ if (dsaparam) {
+ pkey = dsa_to_dh(tmppkey);
+ if (pkey == NULL)
+ goto end;
+ EVP_PKEY_free(tmppkey);
+ } else {
+ pkey = tmppkey;
+ }
+ tmppkey = NULL;
} else {
+ OSSL_DECODER_CTX *decoderctx = NULL;
+ const char *keytype = "DH";
+ int done;
in = bio_open_default(infile, 'r', informat);
if (in == NULL)
goto end;
-#ifndef OPENSSL_NO_DSA
- if (dsaparam) {
- DSA *dsa;
-
- if (informat == FORMAT_ASN1)
- dsa = d2i_DSAparams_bio(in, NULL);
- else /* informat == FORMAT_PEM */
- dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL);
-
- if (dsa == NULL) {
- BIO_printf(bio_err, "unable to load DSA parameters\n");
- ERR_print_errors(bio_err);
- goto end;
- }
-
- dh = DSA_dup_DH(dsa);
- DSA_free(dsa);
- if (dh == NULL) {
- ERR_print_errors(bio_err);
- goto end;
- }
- } else
-#endif
- {
- if (informat == FORMAT_ASN1) {
+ do {
+ /*
+ * We assume we're done unless we explicitly want to retry and set
+ * this to 0 below.
+ */
+ done = 1;
+ /*
+ * We set NULL for the keytype to allow any key type. We don't know
+ * if we're going to get DH or DHX (or DSA in the event of dsaparam).
+ * We check that we got one of those key types afterwards.
+ */
+ decoderctx
+ = OSSL_DECODER_CTX_new_for_pkey(&tmppkey,
+ (informat == FORMAT_ASN1)
+ ? "DER" : "PEM",
+ NULL,
+ (informat == FORMAT_ASN1)
+ ? keytype : NULL,
+ OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ NULL, NULL);
+
+ if (decoderctx != NULL
+ && !OSSL_DECODER_from_bio(decoderctx, in)
+ && informat == FORMAT_ASN1
+ && strcmp(keytype, "DH") == 0) {
+ /*
+ * When reading DER we explicitly state the expected keytype
+ * because, unlike PEM, there is no header to declare what
+ * the contents of the DER file are. The decoders just try
+ * and guess. Unfortunately with DHX key types they may guess
+ * wrong and think we have a DSA keytype. Therefore we try
+ * both DH and DHX sequentially.
+ */
+ keytype = "DHX";
/*
- * We have no PEM header to determine what type of DH params it
- * is. We'll just try both.
+ * BIO_reset() returns 0 for success for file BIOs only!!!
+ * This won't work for stdin (and never has done)
*/
- dh = d2i_DHparams_bio(in, NULL);
- /* BIO_reset() returns 0 for success for file BIOs only!!! */
- if (dh == NULL && BIO_reset(in) == 0)
- dh = d2i_DHxparams_bio(in, NULL);
- } else {
- /* informat == FORMAT_PEM */
- dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
+ if (BIO_reset(in) == 0)
+ done = 0;
}
+ OSSL_DECODER_CTX_free(decoderctx);
+ } while (!done);
+ if (tmppkey == NULL) {
+ BIO_printf(bio_err, "Error, unable to load parameters\n");
+ goto end;
+ }
- if (dh == NULL) {
- BIO_printf(bio_err, "unable to load DH parameters\n");
- ERR_print_errors(bio_err);
+ if (dsaparam) {
+ if (!EVP_PKEY_is_a(tmppkey, "DSA")) {
+ BIO_printf(bio_err, "Error, unable to load DSA parameters\n");
goto end;
}
+ pkey = dsa_to_dh(tmppkey);
+ if (pkey == NULL)
+ goto end;
+ } else {
+ if (!EVP_PKEY_is_a(tmppkey, "DH")
+ && !EVP_PKEY_is_a(tmppkey, "DHX")) {
+ BIO_printf(bio_err, "Error, unable to load DH parameters\n");
+ goto end;
+ }
+ pkey = tmppkey;
+ tmppkey = NULL;
}
-
- /* dh != NULL */
}
- if (text) {
- DHparams_print(out, dh);
- }
+ if (text)
+ EVP_PKEY_print_params(out, pkey, 4, NULL);
if (check) {
- if (!DH_check(dh, &i)) {
- ERR_print_errors(bio_err);
+ ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), pkey, app_get0_propq());
+ if (ctx == NULL) {
+ BIO_printf(bio_err, "Error, failed to check DH parameters\n");
goto end;
}
- if (i & DH_CHECK_P_NOT_PRIME)
- BIO_printf(bio_err, "WARNING: p value is not prime\n");
- if (i & DH_CHECK_P_NOT_SAFE_PRIME)
- BIO_printf(bio_err, "WARNING: p value is not a safe prime\n");
- if (i & DH_CHECK_Q_NOT_PRIME)
- BIO_printf(bio_err, "WARNING: q value is not a prime\n");
- if (i & DH_CHECK_INVALID_Q_VALUE)
- BIO_printf(bio_err, "WARNING: q value is invalid\n");
- if (i & DH_CHECK_INVALID_J_VALUE)
- BIO_printf(bio_err, "WARNING: j value is invalid\n");
- if (i & DH_UNABLE_TO_CHECK_GENERATOR)
- BIO_printf(bio_err,
- "WARNING: unable to check the generator value\n");
- if (i & DH_NOT_SUITABLE_GENERATOR)
- BIO_printf(bio_err, "WARNING: the g value is not a generator\n");
- if (i == 0)
- BIO_printf(bio_err, "DH parameters appear to be ok.\n");
- if (num != 0 && i != 0) {
- /*
- * We have generated parameters but DH_check() indicates they are
- * invalid! This should never happen!
- */
- BIO_printf(bio_err, "ERROR: Invalid parameters generated\n");
+ if (EVP_PKEY_param_check(ctx) <= 0) {
+ BIO_printf(bio_err, "Error, invalid parameters generated\n");
goto end;
}
- }
- if (C) {
- unsigned char *data;
- int len, bits;
- const BIGNUM *pbn, *gbn;
-
- len = DH_size(dh);
- bits = DH_bits(dh);
- DH_get0_pqg(dh, &pbn, NULL, &gbn);
- data = app_malloc(len, "print a BN");
-
- BIO_printf(out, "static DH *get_dh%d(void)\n{\n", bits);
- print_bignum_var(out, pbn, "dhp", bits, data);
- print_bignum_var(out, gbn, "dhg", bits, data);
- BIO_printf(out, " DH *dh = DH_new();\n"
- " BIGNUM *p, *g;\n"
- "\n"
- " if (dh == NULL)\n"
- " return NULL;\n");
- BIO_printf(out, " p = BN_bin2bn(dhp_%d, sizeof(dhp_%d), NULL);\n",
- bits, bits);
- BIO_printf(out, " g = BN_bin2bn(dhg_%d, sizeof(dhg_%d), NULL);\n",
- bits, bits);
- BIO_printf(out, " if (p == NULL || g == NULL\n"
- " || !DH_set0_pqg(dh, p, NULL, g)) {\n"
- " DH_free(dh);\n"
- " BN_free(p);\n"
- " BN_free(g);\n"
- " return NULL;\n"
- " }\n");
- if (DH_get_length(dh) > 0)
- BIO_printf(out,
- " if (!DH_set_length(dh, %ld)) {\n"
- " DH_free(dh);\n"
- " return NULL;\n"
- " }\n", DH_get_length(dh));
- BIO_printf(out, " return dh;\n}\n");
- OPENSSL_free(data);
+ BIO_printf(bio_err, "DH parameters appear to be ok.\n");
}
if (!noout) {
- const BIGNUM *q;
- DH_get0_pqg(dh, NULL, &q, NULL);
- if (outformat == FORMAT_ASN1) {
- if (q != NULL)
- i = i2d_DHxparams_bio(out, dh);
- else
- i = i2d_DHparams_bio(out, dh);
- } else if (q != NULL) {
- i = PEM_write_bio_DHxparams(out, dh);
- } else {
- i = PEM_write_bio_DHparams(out, dh);
- }
- if (!i) {
- BIO_printf(bio_err, "unable to write DH parameters\n");
- ERR_print_errors(bio_err);
+ OSSL_ENCODER_CTX *ectx =
+ OSSL_ENCODER_CTX_new_for_pkey(pkey,
+ OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ outformat == FORMAT_ASN1
+ ? "DER" : "PEM",
+ NULL, NULL);
+
+ if (ectx == NULL || !OSSL_ENCODER_to_bio(ectx, out)) {
+ OSSL_ENCODER_CTX_free(ectx);
+ BIO_printf(bio_err, "Error, unable to write DH parameters\n");
goto end;
}
+ OSSL_ENCODER_CTX_free(ectx);
}
ret = 0;
end:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
BIO_free(in);
BIO_free_all(out);
- DH_free(dh);
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_free(tmppkey);
+ EVP_PKEY_CTX_free(ctx);
release_engine(e);
return ret;
}
-static int dh_cb(int p, int n, BN_GENCB *cb)
+/*
+ * Historically we had the low level call DSA_dup_DH() to do this.
+ * That is now deprecated with no replacement. Since we still need to do this
+ * for backwards compatibility reasons, we do it "manually".
+ */
+static EVP_PKEY *dsa_to_dh(EVP_PKEY *dh)
+{
+ OSSL_PARAM_BLD *tmpl = NULL;
+ OSSL_PARAM *params = NULL;
+ BIGNUM *bn_p = NULL, *bn_q = NULL, *bn_g = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ EVP_PKEY *pkey = NULL;
+
+ if (!EVP_PKEY_get_bn_param(dh, OSSL_PKEY_PARAM_FFC_P, &bn_p)
+ || !EVP_PKEY_get_bn_param(dh, OSSL_PKEY_PARAM_FFC_Q, &bn_q)
+ || !EVP_PKEY_get_bn_param(dh, OSSL_PKEY_PARAM_FFC_G, &bn_g)) {
+ BIO_printf(bio_err, "Error, failed to set DH parameters\n");
+ goto err;
+ }
+
+ if ((tmpl = OSSL_PARAM_BLD_new()) == NULL
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P,
+ bn_p)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q,
+ bn_q)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G,
+ bn_g)
+ || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
+ BIO_printf(bio_err, "Error, failed to set DH parameters\n");
+ goto err;
+ }
+
+ ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "DHX", app_get0_propq());
+ if (ctx == NULL
+ || EVP_PKEY_fromdata_init(ctx) <= 0
+ || EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEY_PARAMETERS, params) <= 0) {
+ BIO_printf(bio_err, "Error, failed to set DH parameters\n");
+ goto err;
+ }
+
+ err:
+ EVP_PKEY_CTX_free(ctx);
+ OSSL_PARAM_free(params);
+ OSSL_PARAM_BLD_free(tmpl);
+ BN_free(bn_p);
+ BN_free(bn_q);
+ BN_free(bn_g);
+ return pkey;
+}
+
+static int gendh_cb(EVP_PKEY_CTX *ctx)
{
+ int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
+ BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
static const char symbols[] = ".+*\n";
char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?';
- BIO_write(BN_GENCB_get_arg(cb), &c, 1);
- (void)BIO_flush(BN_GENCB_get_arg(cb));
+ BIO_write(b, &c, 1);
+ (void)BIO_flush(b);
return 1;
}
diff --git a/apps/dsa.c b/apps/dsa.c
index c7884df166b7..51c02843539f 100644
--- a/apps/dsa.c
+++ b/apps/dsa.c
@@ -1,13 +1,14 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/opensslconf.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -21,29 +22,29 @@
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/bn.h>
+#include <openssl/encoder.h>
+#include <openssl/core_names.h>
+#include <openssl/core_dispatch.h>
+
+#ifndef OPENSSL_NO_RC4
+# define DEFAULT_PVK_ENCR_STRENGTH 2
+#else
+# define DEFAULT_PVK_ENCR_STRENGTH 0
+#endif
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENGINE,
/* Do not change the order here; see case statements below */
OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG,
OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_PUBIN,
- OPT_PUBOUT, OPT_CIPHER, OPT_PASSIN, OPT_PASSOUT
+ OPT_PUBOUT, OPT_CIPHER, OPT_PASSIN, OPT_PASSOUT,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS dsa_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'f', "Input format, DER PEM PVK"},
- {"outform", OPT_OUTFORM, 'f', "Output format, DER PEM PVK"},
- {"in", OPT_IN, 's', "Input key"},
- {"out", OPT_OUT, '>', "Output file"},
- {"noout", OPT_NOOUT, '-', "Don't print key out"},
- {"text", OPT_TEXT, '-', "Print the key in text"},
- {"modulus", OPT_MODULUS, '-', "Print the DSA public value"},
- {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
- {"pubout", OPT_PUBOUT, '-', "Output public key, not private"},
- {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
- {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
{"", OPT_CIPHER, '-', "Any supported cipher"},
#ifndef OPENSSL_NO_RC4
{"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"},
@@ -53,24 +54,43 @@ const OPTIONS dsa_options[] = {
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
#endif
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, 's', "Input key"},
+ {"inform", OPT_INFORM, 'f', "Input format (DER/PEM/PVK); has no effect"},
+ {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'f', "Output format, DER PEM PVK"},
+ {"noout", OPT_NOOUT, '-', "Don't print key out"},
+ {"text", OPT_TEXT, '-', "Print the key in text"},
+ {"modulus", OPT_MODULUS, '-', "Print the DSA public value"},
+ {"pubout", OPT_PUBOUT, '-', "Output public key, not private"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+
+ OPT_PROV_OPTIONS,
{NULL}
};
int dsa_main(int argc, char **argv)
{
BIO *out = NULL;
- DSA *dsa = NULL;
ENGINE *e = NULL;
- const EVP_CIPHER *enc = NULL;
+ EVP_PKEY *pkey = NULL;
+ EVP_CIPHER *enc = NULL;
char *infile = NULL, *outfile = NULL, *prog;
char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL;
OPTION_CHOICE o;
- int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, noout = 0;
- int i, modulus = 0, pubin = 0, pubout = 0, ret = 1;
-#ifndef OPENSSL_NO_RC4
- int pvk_encr = 2;
-#endif
+ int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, text = 0, noout = 0;
+ int modulus = 0, pubin = 0, pubout = 0, ret = 1;
+ int pvk_encr = DEFAULT_PVK_ENCR_STRENGTH;
int private = 0;
+ const char *output_type = NULL, *ciphername = NULL;
+ const char *output_structure = NULL;
+ int selection = 0;
+ OSSL_ENCODER_CTX *ectx = NULL;
prog = opt_init(argc, argv, dsa_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -131,15 +151,24 @@ int dsa_main(int argc, char **argv)
pubout = 1;
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &enc))
+ ciphername = opt_unknown();
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
goto end;
break;
}
}
+
+ /* No extra args. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
+ if (ciphername != NULL) {
+ if (!opt_cipher(ciphername, &enc))
+ goto end;
+ }
private = pubin || pubout ? 0 : 1;
if (text && !pubin)
private = 1;
@@ -150,24 +179,20 @@ int dsa_main(int argc, char **argv)
}
BIO_printf(bio_err, "read DSA key\n");
- {
- EVP_PKEY *pkey;
-
- if (pubin)
- pkey = load_pubkey(infile, informat, 1, passin, e, "Public Key");
- else
- pkey = load_key(infile, informat, 1, passin, e, "Private Key");
+ if (pubin)
+ pkey = load_pubkey(infile, informat, 1, passin, e, "public key");
+ else
+ pkey = load_key(infile, informat, 1, passin, e, "private key");
- if (pkey != NULL) {
- dsa = EVP_PKEY_get1_DSA(pkey);
- EVP_PKEY_free(pkey);
- }
- }
- if (dsa == NULL) {
+ if (pkey == NULL) {
BIO_printf(bio_err, "unable to load Key\n");
ERR_print_errors(bio_err);
goto end;
}
+ if (!EVP_PKEY_is_a(pkey, "DSA")) {
+ BIO_printf(bio_err, "Not a DSA key\n");
+ goto end;
+ }
out = bio_open_owner(outfile, outformat, private);
if (out == NULL)
@@ -175,7 +200,8 @@ int dsa_main(int argc, char **argv)
if (text) {
assert(pubin || private);
- if (!DSA_print(out, dsa, 0)) {
+ if ((pubin && EVP_PKEY_print_public(out, pkey, 0, NULL) <= 0)
+ || (!pubin && EVP_PKEY_print_private(out, pkey, 0, NULL) <= 0)) {
perror(outfile);
ERR_print_errors(bio_err);
goto end;
@@ -183,11 +209,16 @@ int dsa_main(int argc, char **argv)
}
if (modulus) {
- const BIGNUM *pub_key = NULL;
- DSA_get0_key(dsa, &pub_key, NULL);
+ BIGNUM *pub_key = NULL;
+
+ if (!EVP_PKEY_get_bn_param(pkey, "pub", &pub_key)) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
BIO_printf(out, "Public Key=");
BN_print(out, pub_key);
BIO_printf(out, "\n");
+ BN_free(pub_key);
}
if (noout) {
@@ -196,63 +227,83 @@ int dsa_main(int argc, char **argv)
}
BIO_printf(bio_err, "writing DSA key\n");
if (outformat == FORMAT_ASN1) {
- if (pubin || pubout) {
- i = i2d_DSA_PUBKEY_bio(out, dsa);
- } else {
- assert(private);
- i = i2d_DSAPrivateKey_bio(out, dsa);
- }
+ output_type = "DER";
} else if (outformat == FORMAT_PEM) {
- if (pubin || pubout) {
- i = PEM_write_bio_DSA_PUBKEY(out, dsa);
- } else {
- assert(private);
- i = PEM_write_bio_DSAPrivateKey(out, dsa, enc,
- NULL, 0, NULL, passout);
- }
-#ifndef OPENSSL_NO_RSA
- } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) {
- EVP_PKEY *pk;
- pk = EVP_PKEY_new();
- if (pk == NULL)
- goto end;
-
- EVP_PKEY_set1_DSA(pk, dsa);
- if (outformat == FORMAT_PVK) {
- if (pubin) {
- BIO_printf(bio_err, "PVK form impossible with public key input\n");
- EVP_PKEY_free(pk);
- goto end;
- }
- assert(private);
-# ifdef OPENSSL_NO_RC4
- BIO_printf(bio_err, "PVK format not supported\n");
- EVP_PKEY_free(pk);
+ output_type = "PEM";
+ } else if (outformat == FORMAT_MSBLOB) {
+ output_type = "MSBLOB";
+ } else if (outformat == FORMAT_PVK) {
+ if (pubin) {
+ BIO_printf(bio_err, "PVK form impossible with public key input\n");
goto end;
-# else
- i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout);
-# endif
- } else if (pubin || pubout) {
- i = i2b_PublicKey_bio(out, pk);
- } else {
- assert(private);
- i = i2b_PrivateKey_bio(out, pk);
}
- EVP_PKEY_free(pk);
-#endif
+ output_type = "PVK";
} else {
BIO_printf(bio_err, "bad output format specified for outfile\n");
goto end;
}
- if (i <= 0) {
- BIO_printf(bio_err, "unable to write private key\n");
- ERR_print_errors(bio_err);
+
+ if (outformat == FORMAT_ASN1 || outformat == FORMAT_PEM) {
+ if (pubout || pubin)
+ output_structure = "SubjectPublicKeyInfo";
+ else
+ output_structure = "type-specific";
+ }
+
+ /* Select what you want in the output */
+ if (pubout || pubin) {
+ selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+ } else {
+ assert(private);
+ selection = (OSSL_KEYMGMT_SELECT_KEYPAIR
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
+ }
+
+ /* Perform the encoding */
+ ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, output_type,
+ output_structure, NULL);
+ if (OSSL_ENCODER_CTX_get_num_encoders(ectx) == 0) {
+ BIO_printf(bio_err, "%s format not supported\n", output_type);
+ goto end;
+ }
+
+ /* Passphrase setup */
+ if (enc != NULL)
+ OSSL_ENCODER_CTX_set_cipher(ectx, EVP_CIPHER_get0_name(enc), NULL);
+
+ /* Default passphrase prompter */
+ if (enc != NULL || outformat == FORMAT_PVK) {
+ OSSL_ENCODER_CTX_set_passphrase_ui(ectx, get_ui_method(), NULL);
+ if (passout != NULL)
+ /* When passout given, override the passphrase prompter */
+ OSSL_ENCODER_CTX_set_passphrase(ectx,
+ (const unsigned char *)passout,
+ strlen(passout));
+ }
+
+ /* PVK requires a bit more */
+ if (outformat == FORMAT_PVK) {
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] = OSSL_PARAM_construct_int("encrypt-level", &pvk_encr);
+ if (!OSSL_ENCODER_CTX_set_params(ectx, params)) {
+ BIO_printf(bio_err, "invalid PVK encryption level\n");
+ goto end;
+ }
+ }
+
+ if (!OSSL_ENCODER_to_bio(ectx, out)) {
+ BIO_printf(bio_err, "unable to write key\n");
goto end;
}
ret = 0;
end:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
+ OSSL_ENCODER_CTX_free(ectx);
BIO_free_all(out);
- DSA_free(dsa);
+ EVP_PKEY_free(pkey);
+ EVP_CIPHER_free(enc);
release_engine(e);
OPENSSL_free(passin);
OPENSSL_free(passout);
diff --git a/apps/dsaparam.c b/apps/dsaparam.c
index 75589ac6bc4e..b5555282be6e 100644
--- a/apps/dsaparam.c
+++ b/apps/dsaparam.c
@@ -1,15 +1,17 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/opensslconf.h>
+
#include <stdio.h>
#include <stdlib.h>
+#include "apps.h"
#include <time.h>
#include <string.h>
#include "apps.h"
@@ -21,39 +23,54 @@
#include <openssl/x509.h>
#include <openssl/pem.h>
-static int dsa_cb(int p, int n, BN_GENCB *cb);
+static int verbose = 0;
+
+static int gendsa_cb(EVP_PKEY_CTX *ctx);
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C,
- OPT_NOOUT, OPT_GENKEY, OPT_ENGINE, OPT_R_ENUM
+ OPT_COMMON,
+ OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT,
+ OPT_NOOUT, OPT_GENKEY, OPT_ENGINE, OPT_VERBOSE,
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS dsaparam_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [numbits]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file"},
- {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
+ {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
+
+ OPT_SECTION("Output"),
{"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
{"text", OPT_TEXT, '-', "Print as text"},
- {"C", OPT_C, '-', "Output C code"},
{"noout", OPT_NOOUT, '-', "No output"},
+ {"verbose", OPT_VERBOSE, '-', "Verbose output"},
{"genkey", OPT_GENKEY, '-', "Generate a DSA key"},
+
OPT_R_OPTIONS,
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
-#endif
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"numbits", 0, 0, "Number of bits if generating parameters (optional)"},
{NULL}
};
int dsaparam_main(int argc, char **argv)
{
ENGINE *e = NULL;
- DSA *dsa = NULL;
- BIO *in = NULL, *out = NULL;
- BN_GENCB *cb = NULL;
+ BIO *out = NULL;
+ EVP_PKEY *params = NULL, *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
int numbits = -1, num = 0, genkey = 0;
- int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0;
+ int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, noout = 0;
int ret = 1, i, text = 0, private = 0;
char *infile = NULL, *outfile = NULL, *prog;
OPTION_CHOICE o;
@@ -90,9 +107,6 @@ int dsaparam_main(int argc, char **argv)
case OPT_TEXT:
text = 1;
break;
- case OPT_C:
- C = 1;
- break;
case OPT_GENKEY:
genkey = 1;
break;
@@ -100,29 +114,45 @@ int dsaparam_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_NOOUT:
noout = 1;
break;
+ case OPT_VERBOSE:
+ verbose = 1;
+ break;
}
}
+
+ /* Optional arg is bitsize. */
argc = opt_num_rest();
argv = opt_rest();
-
if (argc == 1) {
if (!opt_int(argv[0], &num) || num < 0)
- goto end;
- /* generate a key */
- numbits = num;
+ goto opthelp;
+ } else if (argc != 0) {
+ goto opthelp;
}
+ if (!app_RAND_load())
+ goto end;
+
+ /* generate a key */
+ numbits = num;
private = genkey ? 1 : 0;
- in = bio_open_default(infile, 'r', informat);
- if (in == NULL)
- goto end;
out = bio_open_owner(outfile, outformat, private);
if (out == NULL)
goto end;
+ ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "DSA", app_get0_propq());
+ if (ctx == NULL) {
+ BIO_printf(bio_err,
+ "Error, DSA parameter generation context allocation failed\n");
+ goto end;
+ }
if (numbits > 0) {
if (numbits > OPENSSL_DSA_MAX_MODULUS_BITS)
BIO_printf(bio_err,
@@ -130,74 +160,34 @@ int dsaparam_main(int argc, char **argv)
" Your key size is %d! Larger key size may behave not as expected.\n",
OPENSSL_DSA_MAX_MODULUS_BITS, numbits);
- cb = BN_GENCB_new();
- if (cb == NULL) {
- BIO_printf(bio_err, "Error allocating BN_GENCB object\n");
- goto end;
+ EVP_PKEY_CTX_set_cb(ctx, gendsa_cb);
+ EVP_PKEY_CTX_set_app_data(ctx, bio_err);
+ if (verbose) {
+ BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n",
+ num);
+ BIO_printf(bio_err, "This could take some time\n");
}
- BN_GENCB_set(cb, dsa_cb, bio_err);
- dsa = DSA_new();
- if (dsa == NULL) {
- BIO_printf(bio_err, "Error allocating DSA object\n");
+ if (EVP_PKEY_paramgen_init(ctx) <= 0) {
+ BIO_printf(bio_err,
+ "Error, DSA key generation paramgen init failed\n");
goto end;
}
- BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n",
- num);
- BIO_printf(bio_err, "This could take some time\n");
- if (!DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL, cb)) {
- ERR_print_errors(bio_err);
- BIO_printf(bio_err, "Error, DSA key generation failed\n");
+ if (EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, num) <= 0) {
+ BIO_printf(bio_err,
+ "Error, DSA key generation setting bit length failed\n");
goto end;
}
- } else if (informat == FORMAT_ASN1) {
- dsa = d2i_DSAparams_bio(in, NULL);
+ params = app_paramgen(ctx, "DSA");
} else {
- dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL);
+ params = load_keyparams(infile, informat, 1, "DSA", "DSA parameters");
}
- if (dsa == NULL) {
- BIO_printf(bio_err, "unable to load DSA parameters\n");
- ERR_print_errors(bio_err);
+ if (params == NULL) {
+ /* Error message should already have been displayed */
goto end;
}
if (text) {
- DSAparams_print(out, dsa);
- }
-
- if (C) {
- const BIGNUM *p = NULL, *q = NULL, *g = NULL;
- unsigned char *data;
- int len, bits_p;
-
- DSA_get0_pqg(dsa, &p, &q, &g);
- len = BN_num_bytes(p);
- bits_p = BN_num_bits(p);
-
- data = app_malloc(len + 20, "BN space");
-
- BIO_printf(bio_out, "static DSA *get_dsa%d(void)\n{\n", bits_p);
- print_bignum_var(bio_out, p, "dsap", bits_p, data);
- print_bignum_var(bio_out, q, "dsaq", bits_p, data);
- print_bignum_var(bio_out, g, "dsag", bits_p, data);
- BIO_printf(bio_out, " DSA *dsa = DSA_new();\n"
- " BIGNUM *p, *q, *g;\n"
- "\n");
- BIO_printf(bio_out, " if (dsa == NULL)\n"
- " return NULL;\n");
- BIO_printf(bio_out, " if (!DSA_set0_pqg(dsa, p = BN_bin2bn(dsap_%d, sizeof(dsap_%d), NULL),\n",
- bits_p, bits_p);
- BIO_printf(bio_out, " q = BN_bin2bn(dsaq_%d, sizeof(dsaq_%d), NULL),\n",
- bits_p, bits_p);
- BIO_printf(bio_out, " g = BN_bin2bn(dsag_%d, sizeof(dsag_%d), NULL))) {\n",
- bits_p, bits_p);
- BIO_printf(bio_out, " DSA_free(dsa);\n"
- " BN_free(p);\n"
- " BN_free(q);\n"
- " BN_free(g);\n"
- " return NULL;\n"
- " }\n"
- " return dsa;\n}\n");
- OPENSSL_free(data);
+ EVP_PKEY_print_params(out, params, 0, NULL);
}
if (outformat == FORMAT_ASN1 && genkey)
@@ -205,49 +195,62 @@ int dsaparam_main(int argc, char **argv)
if (!noout) {
if (outformat == FORMAT_ASN1)
- i = i2d_DSAparams_bio(out, dsa);
+ i = i2d_KeyParams_bio(out, params);
else
- i = PEM_write_bio_DSAparams(out, dsa);
+ i = PEM_write_bio_Parameters(out, params);
if (!i) {
- BIO_printf(bio_err, "unable to write DSA parameters\n");
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Error, unable to write DSA parameters\n");
goto end;
}
}
if (genkey) {
- DSA *dsakey;
-
- if ((dsakey = DSAparams_dup(dsa)) == NULL)
+ EVP_PKEY_CTX_free(ctx);
+ ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), params,
+ app_get0_propq());
+ if (ctx == NULL) {
+ BIO_printf(bio_err,
+ "Error, DSA key generation context allocation failed\n");
goto end;
- if (!DSA_generate_key(dsakey)) {
- ERR_print_errors(bio_err);
- DSA_free(dsakey);
+ }
+ if (EVP_PKEY_keygen_init(ctx) <= 0) {
+ BIO_printf(bio_err,
+ "Error, unable to initialise for key generation\n");
goto end;
}
+ pkey = app_keygen(ctx, "DSA", numbits, verbose);
assert(private);
if (outformat == FORMAT_ASN1)
- i = i2d_DSAPrivateKey_bio(out, dsakey);
+ i = i2d_PrivateKey_bio(out, pkey);
else
- i = PEM_write_bio_DSAPrivateKey(out, dsakey, NULL, NULL, 0, NULL,
- NULL);
- DSA_free(dsakey);
+ i = PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, NULL);
}
ret = 0;
end:
- BN_GENCB_free(cb);
- BIO_free(in);
+ if (ret != 0)
+ ERR_print_errors(bio_err);
BIO_free_all(out);
- DSA_free(dsa);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_free(params);
release_engine(e);
return ret;
}
-static int dsa_cb(int p, int n, BN_GENCB *cb)
+static int gendsa_cb(EVP_PKEY_CTX *ctx)
{
static const char symbols[] = ".+*\n";
- char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?';
+ int p;
+ char c;
+ BIO *b;
+
+ if (!verbose)
+ return 1;
+
+ b = EVP_PKEY_CTX_get_app_data(ctx);
+ p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
+ c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?';
- BIO_write(BN_GENCB_get_arg(cb), &c, 1);
- (void)BIO_flush(BN_GENCB_get_arg(cb));
+ BIO_write(b, &c, 1);
+ (void)BIO_flush(b);
return 1;
}
diff --git a/apps/ec.c b/apps/ec.c
index 0c8ed750cc17..e2dd6f2b48f3 100644
--- a/apps/ec.c
+++ b/apps/ec.c
@@ -1,84 +1,84 @@
/*
- * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/opensslconf.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
-#include "apps.h"
-#include "progs.h"
-#include <openssl/bio.h>
-#include <openssl/err.h>
+#include <openssl/opensslconf.h>
#include <openssl/evp.h>
-#include <openssl/pem.h>
-
-static OPT_PAIR conv_forms[] = {
- {"compressed", POINT_CONVERSION_COMPRESSED},
- {"uncompressed", POINT_CONVERSION_UNCOMPRESSED},
- {"hybrid", POINT_CONVERSION_HYBRID},
- {NULL}
-};
+#include <openssl/encoder.h>
+#include <openssl/decoder.h>
+#include <openssl/core_names.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
-static OPT_PAIR param_enc[] = {
- {"named_curve", OPENSSL_EC_NAMED_CURVE},
- {"explicit", 0},
- {NULL}
-};
+#include "apps.h"
+#include "progs.h"
+#include "ec_common.h"
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT,
OPT_NOOUT, OPT_TEXT, OPT_PARAM_OUT, OPT_PUBIN, OPT_PUBOUT,
OPT_PASSIN, OPT_PASSOUT, OPT_PARAM_ENC, OPT_CONV_FORM, OPT_CIPHER,
- OPT_NO_PUBLIC, OPT_CHECK
+ OPT_NO_PUBLIC, OPT_CHECK, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS ec_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, 's', "Input file"},
- {"inform", OPT_INFORM, 'f', "Input format - DER or PEM"},
+ {"inform", OPT_INFORM, 'f', "Input format (DER/PEM/P12/ENGINE)"},
+ {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"check", OPT_CHECK, '-', "check key consistency"},
+ {"", OPT_CIPHER, '-', "Any supported cipher"},
+ {"param_enc", OPT_PARAM_ENC, 's',
+ "Specifies the way the ec parameters are encoded"},
+ {"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "},
+
+ OPT_SECTION("Output"),
{"out", OPT_OUT, '>', "Output file"},
{"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
{"noout", OPT_NOOUT, '-', "Don't print key out"},
{"text", OPT_TEXT, '-', "Print the key"},
{"param_out", OPT_PARAM_OUT, '-', "Print the elliptic curve parameters"},
- {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
{"pubout", OPT_PUBOUT, '-', "Output public key, not private"},
{"no_public", OPT_NO_PUBLIC, '-', "exclude public key from private key"},
- {"check", OPT_CHECK, '-', "check key consistency"},
- {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
- {"param_enc", OPT_PARAM_ENC, 's',
- "Specifies the way the ec parameters are encoded"},
- {"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "},
- {"", OPT_CIPHER, '-', "Any supported cipher"},
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
+
+ OPT_PROV_OPTIONS,
{NULL}
};
int ec_main(int argc, char **argv)
{
- BIO *in = NULL, *out = NULL;
+ OSSL_ENCODER_CTX *ectx = NULL;
+ OSSL_DECODER_CTX *dctx = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ EVP_PKEY *eckey = NULL;
+ BIO *out = NULL;
ENGINE *e = NULL;
- EC_KEY *eckey = NULL;
- const EC_GROUP *group;
- const EVP_CIPHER *enc = NULL;
- point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
- char *infile = NULL, *outfile = NULL, *prog;
+ EVP_CIPHER *enc = NULL;
+ char *infile = NULL, *outfile = NULL, *ciphername = NULL, *prog;
char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL;
OPTION_CHOICE o;
- int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_form = 0, new_asn1_flag = 0;
- int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, noout = 0;
- int pubin = 0, pubout = 0, param_out = 0, i, ret = 1, private = 0;
- int no_public = 0, check = 0;
+ int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, text = 0, noout = 0;
+ int pubin = 0, pubout = 0, param_out = 0, ret = 1, private = 0;
+ int check = 0;
+ char *asn1_encoding = NULL;
+ char *point_format = NULL;
+ int no_public = 0;
prog = opt_init(argc, argv, ec_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -131,20 +131,17 @@ int ec_main(int argc, char **argv)
e = setup_engine(opt_arg(), 0);
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &enc))
- goto opthelp;
+ ciphername = opt_unknown();
break;
case OPT_CONV_FORM:
- if (!opt_pair(opt_arg(), conv_forms, &i))
+ point_format = opt_arg();
+ if (!opt_string(point_format, point_format_options))
goto opthelp;
- new_form = 1;
- form = i;
break;
case OPT_PARAM_ENC:
- if (!opt_pair(opt_arg(), param_enc, &i))
+ asn1_encoding = opt_arg();
+ if (!opt_string(asn1_encoding, asn1_encoding_options))
goto opthelp;
- new_asn1_flag = 1;
- asn1_flag = i;
break;
case OPT_NO_PUBLIC:
no_public = 1;
@@ -152,12 +149,22 @@ int ec_main(int argc, char **argv)
case OPT_CHECK:
check = 1;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
+ if (ciphername != NULL) {
+ if (!opt_cipher(ciphername, &enc))
+ goto opthelp;
+ }
private = param_out || pubin || pubout ? 0 : 1;
if (text && !pubin)
private = 1;
@@ -167,37 +174,15 @@ int ec_main(int argc, char **argv)
goto end;
}
- if (informat != FORMAT_ENGINE) {
- in = bio_open_default(infile, 'r', informat);
- if (in == NULL)
- goto end;
- }
-
BIO_printf(bio_err, "read EC key\n");
- if (informat == FORMAT_ASN1) {
- if (pubin)
- eckey = d2i_EC_PUBKEY_bio(in, NULL);
- else
- eckey = d2i_ECPrivateKey_bio(in, NULL);
- } else if (informat == FORMAT_ENGINE) {
- EVP_PKEY *pkey;
- if (pubin)
- pkey = load_pubkey(infile, informat, 1, passin, e, "Public Key");
- else
- pkey = load_key(infile, informat, 1, passin, e, "Private Key");
- if (pkey != NULL) {
- eckey = EVP_PKEY_get1_EC_KEY(pkey);
- EVP_PKEY_free(pkey);
- }
- } else {
- if (pubin)
- eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, NULL);
- else
- eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL, passin);
- }
+
+ if (pubin)
+ eckey = load_pubkey(infile, informat, 1, passin, e, "public key");
+ else
+ eckey = load_key(infile, informat, 1, passin, e, "private key");
+
if (eckey == NULL) {
BIO_printf(bio_err, "unable to load Key\n");
- ERR_print_errors(bio_err);
goto end;
}
@@ -205,74 +190,105 @@ int ec_main(int argc, char **argv)
if (out == NULL)
goto end;
- group = EC_KEY_get0_group(eckey);
-
- if (new_form)
- EC_KEY_set_conv_form(eckey, form);
+ if (point_format
+ && !EVP_PKEY_set_utf8_string_param(
+ eckey, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
+ point_format)) {
+ BIO_printf(bio_err, "unable to set point conversion format\n");
+ goto end;
+ }
- if (new_asn1_flag)
- EC_KEY_set_asn1_flag(eckey, asn1_flag);
+ if (asn1_encoding != NULL
+ && !EVP_PKEY_set_utf8_string_param(
+ eckey, OSSL_PKEY_PARAM_EC_ENCODING, asn1_encoding)) {
+ BIO_printf(bio_err, "unable to set asn1 encoding format\n");
+ goto end;
+ }
- if (no_public)
- EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY);
+ if (no_public) {
+ if (!EVP_PKEY_set_int_param(eckey, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 0)) {
+ BIO_printf(bio_err, "unable to disable public key encoding\n");
+ goto end;
+ }
+ } else {
+ if (!EVP_PKEY_set_int_param(eckey, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 1)) {
+ BIO_printf(bio_err, "unable to enable public key encoding\n");
+ goto end;
+ }
+ }
if (text) {
assert(pubin || private);
- if (!EC_KEY_print(out, eckey, 0)) {
- perror(outfile);
- ERR_print_errors(bio_err);
+ if ((pubin && EVP_PKEY_print_public(out, eckey, 0, NULL) <= 0)
+ || (!pubin && EVP_PKEY_print_private(out, eckey, 0, NULL) <= 0)) {
+ BIO_printf(bio_err, "unable to print EC key\n");
goto end;
}
}
if (check) {
- if (EC_KEY_check_key(eckey) == 1) {
- BIO_printf(bio_err, "EC Key valid.\n");
- } else {
- BIO_printf(bio_err, "EC Key Invalid!\n");
- ERR_print_errors(bio_err);
+ pctx = EVP_PKEY_CTX_new_from_pkey(NULL, eckey, NULL);
+ if (pctx == NULL) {
+ BIO_printf(bio_err, "unable to check EC key\n");
+ goto end;
}
+ if (EVP_PKEY_check(pctx) <= 0)
+ BIO_printf(bio_err, "EC Key Invalid!\n");
+ else
+ BIO_printf(bio_err, "EC Key valid.\n");
+ ERR_print_errors(bio_err);
}
- if (noout) {
- ret = 0;
- goto end;
- }
+ if (!noout) {
+ int selection;
+ const char *output_type = outformat == FORMAT_ASN1 ? "DER" : "PEM";
+ const char *output_structure = "type-specific";
- BIO_printf(bio_err, "writing EC key\n");
- if (outformat == FORMAT_ASN1) {
+ BIO_printf(bio_err, "writing EC key\n");
if (param_out) {
- i = i2d_ECPKParameters_bio(out, group);
+ selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
} else if (pubin || pubout) {
- i = i2d_EC_PUBKEY_bio(out, eckey);
+ selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
+ | OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+ output_structure = "SubjectPublicKeyInfo";
} else {
+ selection = OSSL_KEYMGMT_SELECT_ALL;
assert(private);
- i = i2d_ECPrivateKey_bio(out, eckey);
}
- } else {
- if (param_out) {
- i = PEM_write_bio_ECPKParameters(out, group);
- } else if (pubin || pubout) {
- i = PEM_write_bio_EC_PUBKEY(out, eckey);
- } else {
- assert(private);
- i = PEM_write_bio_ECPrivateKey(out, eckey, enc,
- NULL, 0, NULL, passout);
+
+ ectx = OSSL_ENCODER_CTX_new_for_pkey(eckey, selection,
+ output_type, output_structure,
+ NULL);
+ if (enc != NULL) {
+ OSSL_ENCODER_CTX_set_cipher(ectx, EVP_CIPHER_get0_name(enc), NULL);
+ /* Default passphrase prompter */
+ OSSL_ENCODER_CTX_set_passphrase_ui(ectx, get_ui_method(), NULL);
+ if (passout != NULL)
+ /* When passout given, override the passphrase prompter */
+ OSSL_ENCODER_CTX_set_passphrase(ectx,
+ (const unsigned char *)passout,
+ strlen(passout));
+ }
+ if (!OSSL_ENCODER_to_bio(ectx, out)) {
+ BIO_printf(bio_err, "unable to write EC key\n");
+ goto end;
}
}
- if (!i) {
- BIO_printf(bio_err, "unable to write private key\n");
+ ret = 0;
+end:
+ if (ret != 0)
ERR_print_errors(bio_err);
- } else {
- ret = 0;
- }
- end:
- BIO_free(in);
BIO_free_all(out);
- EC_KEY_free(eckey);
+ EVP_PKEY_free(eckey);
+ EVP_CIPHER_free(enc);
+ OSSL_ENCODER_CTX_free(ectx);
+ OSSL_DECODER_CTX_free(dctx);
+ EVP_PKEY_CTX_free(pctx);
release_engine(e);
- OPENSSL_free(passin);
- OPENSSL_free(passout);
+ if (passin != NULL)
+ OPENSSL_clear_free(passin, strlen(passin));
+ if (passout != NULL)
+ OPENSSL_clear_free(passout, strlen(passout));
return ret;
}
diff --git a/apps/ecparam.c b/apps/ecparam.c
index 58fbeb95c9ce..9e9ad136837b 100644
--- a/apps/ecparam.c
+++ b/apps/ecparam.c
@@ -1,92 +1,115 @@
/*
- * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/opensslconf.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
#include <string.h>
+#include <openssl/opensslconf.h>
+#include <openssl/evp.h>
+#include <openssl/encoder.h>
+#include <openssl/decoder.h>
+#include <openssl/core_names.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
#include "apps.h"
#include "progs.h"
-#include <openssl/bio.h>
-#include <openssl/err.h>
-#include <openssl/bn.h>
-#include <openssl/ec.h>
-#include <openssl/x509.h>
-#include <openssl/pem.h>
+#include "ec_common.h"
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C,
+ OPT_COMMON,
+ OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT,
OPT_CHECK, OPT_LIST_CURVES, OPT_NO_SEED, OPT_NOOUT, OPT_NAME,
- OPT_CONV_FORM, OPT_PARAM_ENC, OPT_GENKEY, OPT_ENGINE,
- OPT_R_ENUM
+ OPT_CONV_FORM, OPT_PARAM_ENC, OPT_GENKEY, OPT_ENGINE, OPT_CHECK_NAMED,
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS ecparam_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"},
- {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"},
+ {"list_curves", OPT_LIST_CURVES, '-',
+ "Prints a list of all curve 'short names'"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ {"genkey", OPT_GENKEY, '-', "Generate ec key"},
{"in", OPT_IN, '<', "Input file - default stdin"},
+ {"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"},
{"out", OPT_OUT, '>', "Output file - default stdout"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"},
+
+ OPT_SECTION("Output"),
{"text", OPT_TEXT, '-', "Print the ec parameters in text form"},
- {"C", OPT_C, '-', "Print a 'C' function creating the parameters"},
+ {"noout", OPT_NOOUT, '-', "Do not print the ec parameter"},
+ {"param_enc", OPT_PARAM_ENC, 's',
+ "Specifies the way the ec parameters are encoded"},
+
+ OPT_SECTION("Parameter"),
{"check", OPT_CHECK, '-', "Validate the ec parameters"},
- {"list_curves", OPT_LIST_CURVES, '-',
- "Prints a list of all curve 'short names'"},
+ {"check_named", OPT_CHECK_NAMED, '-',
+ "Check that named EC curve parameters have not been modified"},
{"no_seed", OPT_NO_SEED, '-',
"If 'explicit' parameters are chosen do not use the seed"},
- {"noout", OPT_NOOUT, '-', "Do not print the ec parameter"},
{"name", OPT_NAME, 's',
"Use the ec parameters with specified 'short name'"},
{"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "},
- {"param_enc", OPT_PARAM_ENC, 's',
- "Specifies the way the ec parameters are encoded"},
- {"genkey", OPT_GENKEY, '-', "Generate ec key"},
+
OPT_R_OPTIONS,
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
+ OPT_PROV_OPTIONS,
{NULL}
};
-static OPT_PAIR forms[] = {
- {"compressed", POINT_CONVERSION_COMPRESSED},
- {"uncompressed", POINT_CONVERSION_UNCOMPRESSED},
- {"hybrid", POINT_CONVERSION_HYBRID},
- {NULL}
-};
+static int list_builtin_curves(BIO *out)
+{
+ int ret = 0;
+ EC_builtin_curve *curves = NULL;
+ size_t n, crv_len = EC_get_builtin_curves(NULL, 0);
-static OPT_PAIR encodings[] = {
- {"named_curve", OPENSSL_EC_NAMED_CURVE},
- {"explicit", 0},
- {NULL}
-};
+ curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves");
+ if (!EC_get_builtin_curves(curves, crv_len))
+ goto end;
+
+ for (n = 0; n < crv_len; n++) {
+ const char *comment = curves[n].comment;
+ const char *sname = OBJ_nid2sn(curves[n].nid);
+
+ if (comment == NULL)
+ comment = "CURVE DESCRIPTION NOT AVAILABLE";
+ if (sname == NULL)
+ sname = "";
+
+ BIO_printf(out, " %-10s: ", sname);
+ BIO_printf(out, "%s\n", comment);
+ }
+ ret = 1;
+end:
+ OPENSSL_free(curves);
+ return ret;
+}
int ecparam_main(int argc, char **argv)
{
+ EVP_PKEY_CTX *gctx_params = NULL, *gctx_key = NULL, *pctx = NULL;
+ EVP_PKEY *params_key = NULL, *key = NULL;
+ OSSL_ENCODER_CTX *ectx_key = NULL, *ectx_params = NULL;
+ OSSL_DECODER_CTX *dctx_params = NULL;
ENGINE *e = NULL;
- BIGNUM *ec_gen = NULL, *ec_order = NULL, *ec_cofactor = NULL;
- BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL;
- BIO *in = NULL, *out = NULL;
- EC_GROUP *group = NULL;
- point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
+ BIO *out = NULL;
char *curve_name = NULL;
+ char *asn1_encoding = NULL;
+ char *point_format = NULL;
char *infile = NULL, *outfile = NULL, *prog;
- unsigned char *buffer = NULL;
OPTION_CHOICE o;
- int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_asn1_flag = 0;
- int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0;
+ int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0;
int ret = 1, private = 0;
- int list_curves = 0, no_seed = 0, check = 0, new_form = 0;
- int text = 0, i, genkey = 0;
+ int no_seed = 0, check = 0, check_named = 0, text = 0, genkey = 0;
+ int list_curves = 0;
prog = opt_init(argc, argv, ecparam_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -117,12 +140,12 @@ int ecparam_main(int argc, char **argv)
case OPT_TEXT:
text = 1;
break;
- case OPT_C:
- C = 1;
- break;
case OPT_CHECK:
check = 1;
break;
+ case OPT_CHECK_NAMED:
+ check_named = 1;
+ break;
case OPT_LIST_CURVES:
list_curves = 1;
break;
@@ -136,15 +159,14 @@ int ecparam_main(int argc, char **argv)
curve_name = opt_arg();
break;
case OPT_CONV_FORM:
- if (!opt_pair(opt_arg(), forms, &new_form))
+ point_format = opt_arg();
+ if (!opt_string(point_format, point_format_options))
goto opthelp;
- form = new_form;
- new_form = 1;
break;
case OPT_PARAM_ENC:
- if (!opt_pair(opt_arg(), encodings, &asn1_flag))
+ asn1_encoding = opt_arg();
+ if (!opt_string(asn1_encoding, asn1_encoding_options))
goto opthelp;
- new_asn1_flag = 1;
break;
case OPT_GENKEY:
genkey = 1;
@@ -153,292 +175,178 @@ int ecparam_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
}
}
+
+ /* No extra args. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
+ if (!app_RAND_load())
+ goto end;
+
private = genkey ? 1 : 0;
- in = bio_open_default(infile, 'r', informat);
- if (in == NULL)
- goto end;
out = bio_open_owner(outfile, outformat, private);
if (out == NULL)
goto end;
if (list_curves) {
- EC_builtin_curve *curves = NULL;
- size_t crv_len = EC_get_builtin_curves(NULL, 0);
- size_t n;
-
- curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves");
- if (!EC_get_builtin_curves(curves, crv_len)) {
- OPENSSL_free(curves);
- goto end;
- }
-
- for (n = 0; n < crv_len; n++) {
- const char *comment;
- const char *sname;
- comment = curves[n].comment;
- sname = OBJ_nid2sn(curves[n].nid);
- if (comment == NULL)
- comment = "CURVE DESCRIPTION NOT AVAILABLE";
- if (sname == NULL)
- sname = "";
-
- BIO_printf(out, " %-10s: ", sname);
- BIO_printf(out, "%s\n", comment);
- }
-
- OPENSSL_free(curves);
- ret = 0;
+ if (list_builtin_curves(out))
+ ret = 0;
goto end;
}
if (curve_name != NULL) {
- int nid;
+ OSSL_PARAM params[4];
+ OSSL_PARAM *p = params;
- /*
- * workaround for the SECG curve names secp192r1 and secp256r1 (which
- * are the same as the curves prime192v1 and prime256v1 defined in
- * X9.62)
- */
if (strcmp(curve_name, "secp192r1") == 0) {
- BIO_printf(bio_err, "using curve name prime192v1 "
- "instead of secp192r1\n");
- nid = NID_X9_62_prime192v1;
+ BIO_printf(bio_err,
+ "using curve name prime192v1 instead of secp192r1\n");
+ curve_name = SN_X9_62_prime192v1;
} else if (strcmp(curve_name, "secp256r1") == 0) {
- BIO_printf(bio_err, "using curve name prime256v1 "
- "instead of secp256r1\n");
- nid = NID_X9_62_prime256v1;
- } else {
- nid = OBJ_sn2nid(curve_name);
+ BIO_printf(bio_err,
+ "using curve name prime256v1 instead of secp256r1\n");
+ curve_name = SN_X9_62_prime256v1;
}
-
- if (nid == 0)
- nid = EC_curve_nist2nid(curve_name);
-
- if (nid == 0) {
- BIO_printf(bio_err, "unknown curve name (%s)\n", curve_name);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
+ curve_name, 0);
+ if (asn1_encoding != NULL)
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING,
+ asn1_encoding, 0);
+ if (point_format != NULL)
+ *p++ = OSSL_PARAM_construct_utf8_string(
+ OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
+ point_format, 0);
+ *p = OSSL_PARAM_construct_end();
+
+ if (OPENSSL_strcasecmp(curve_name, "SM2") == 0)
+ gctx_params = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "sm2",
+ app_get0_propq());
+ else
+ gctx_params = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "ec",
+ app_get0_propq());
+ if (gctx_params == NULL
+ || EVP_PKEY_keygen_init(gctx_params) <= 0
+ || EVP_PKEY_CTX_set_params(gctx_params, params) <= 0
+ || EVP_PKEY_keygen(gctx_params, &params_key) <= 0) {
+ BIO_printf(bio_err, "unable to generate key\n");
+ goto end;
+ }
+ } else {
+ params_key = load_keyparams(infile, informat, 1, "EC", "EC parameters");
+ if (params_key == NULL || !EVP_PKEY_is_a(params_key, "EC"))
+ goto end;
+ if (point_format
+ && !EVP_PKEY_set_utf8_string_param(
+ params_key, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
+ point_format)) {
+ BIO_printf(bio_err, "unable to set point conversion format\n");
goto end;
}
- group = EC_GROUP_new_by_curve_name(nid);
- if (group == NULL) {
- BIO_printf(bio_err, "unable to create curve (%s)\n", curve_name);
+ if (asn1_encoding != NULL
+ && !EVP_PKEY_set_utf8_string_param(
+ params_key, OSSL_PKEY_PARAM_EC_ENCODING, asn1_encoding)) {
+ BIO_printf(bio_err, "unable to set asn1 encoding format\n");
goto end;
}
- EC_GROUP_set_asn1_flag(group, asn1_flag);
- EC_GROUP_set_point_conversion_form(group, form);
- } else if (informat == FORMAT_ASN1) {
- group = d2i_ECPKParameters_bio(in, NULL);
- } else {
- group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
}
- if (group == NULL) {
- BIO_printf(bio_err, "unable to load elliptic curve parameters\n");
- ERR_print_errors(bio_err);
- goto end;
- }
-
- if (new_form)
- EC_GROUP_set_point_conversion_form(group, form);
- if (new_asn1_flag)
- EC_GROUP_set_asn1_flag(group, asn1_flag);
-
- if (no_seed) {
- EC_GROUP_set_seed(group, NULL, 0);
+ if (no_seed
+ && !EVP_PKEY_set_octet_string_param(params_key, OSSL_PKEY_PARAM_EC_SEED,
+ NULL, 0)) {
+ BIO_printf(bio_err, "unable to clear seed\n");
+ goto end;
}
- if (text) {
- if (!ECPKParameters_print(out, group, 0))
- goto end;
+ if (text
+ && !EVP_PKEY_print_params(out, params_key, 0, NULL)) {
+ BIO_printf(bio_err, "unable to print params\n");
+ goto end;
}
- if (check) {
+ if (check || check_named) {
BIO_printf(bio_err, "checking elliptic curve parameters: ");
- if (!EC_GROUP_check(group, NULL)) {
- BIO_printf(bio_err, "failed\n");
- ERR_print_errors(bio_err);
- goto end;
- }
- BIO_printf(bio_err, "ok\n");
-
- }
-
- if (C) {
- size_t buf_len = 0, tmp_len = 0;
- const EC_POINT *point;
- int is_prime, len = 0;
- const EC_METHOD *meth = EC_GROUP_method_of(group);
- if ((ec_p = BN_new()) == NULL
- || (ec_a = BN_new()) == NULL
- || (ec_b = BN_new()) == NULL
- || (ec_gen = BN_new()) == NULL
- || (ec_order = BN_new()) == NULL
- || (ec_cofactor = BN_new()) == NULL) {
- perror("Can't allocate BN");
- goto end;
+ if (check_named
+ && !EVP_PKEY_set_utf8_string_param(params_key,
+ OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE,
+ OSSL_PKEY_EC_GROUP_CHECK_NAMED)) {
+ BIO_printf(bio_err, "unable to set check_type\n");
+ goto end;
}
-
- is_prime = (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field);
- if (!is_prime) {
- BIO_printf(bio_err, "Can only handle X9.62 prime fields\n");
+ pctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), params_key,
+ app_get0_propq());
+ if (pctx == NULL || EVP_PKEY_param_check(pctx) <= 0) {
+ BIO_printf(bio_err, "failed\n");
goto end;
}
-
- if (!EC_GROUP_get_curve(group, ec_p, ec_a, ec_b, NULL))
- goto end;
-
- if ((point = EC_GROUP_get0_generator(group)) == NULL)
- goto end;
- if (!EC_POINT_point2bn(group, point,
- EC_GROUP_get_point_conversion_form(group),
- ec_gen, NULL))
- goto end;
- if (!EC_GROUP_get_order(group, ec_order, NULL))
- goto end;
- if (!EC_GROUP_get_cofactor(group, ec_cofactor, NULL))
- goto end;
-
- if (!ec_p || !ec_a || !ec_b || !ec_gen || !ec_order || !ec_cofactor)
- goto end;
-
- len = BN_num_bits(ec_order);
-
- if ((tmp_len = (size_t)BN_num_bytes(ec_p)) > buf_len)
- buf_len = tmp_len;
- if ((tmp_len = (size_t)BN_num_bytes(ec_a)) > buf_len)
- buf_len = tmp_len;
- if ((tmp_len = (size_t)BN_num_bytes(ec_b)) > buf_len)
- buf_len = tmp_len;
- if ((tmp_len = (size_t)BN_num_bytes(ec_gen)) > buf_len)
- buf_len = tmp_len;
- if ((tmp_len = (size_t)BN_num_bytes(ec_order)) > buf_len)
- buf_len = tmp_len;
- if ((tmp_len = (size_t)BN_num_bytes(ec_cofactor)) > buf_len)
- buf_len = tmp_len;
-
- buffer = app_malloc(buf_len, "BN buffer");
-
- BIO_printf(out, "EC_GROUP *get_ec_group_%d(void)\n{\n", len);
- print_bignum_var(out, ec_p, "ec_p", len, buffer);
- print_bignum_var(out, ec_a, "ec_a", len, buffer);
- print_bignum_var(out, ec_b, "ec_b", len, buffer);
- print_bignum_var(out, ec_gen, "ec_gen", len, buffer);
- print_bignum_var(out, ec_order, "ec_order", len, buffer);
- print_bignum_var(out, ec_cofactor, "ec_cofactor", len, buffer);
- BIO_printf(out, " int ok = 0;\n"
- " EC_GROUP *group = NULL;\n"
- " EC_POINT *point = NULL;\n"
- " BIGNUM *tmp_1 = NULL;\n"
- " BIGNUM *tmp_2 = NULL;\n"
- " BIGNUM *tmp_3 = NULL;\n"
- "\n");
-
- BIO_printf(out, " if ((tmp_1 = BN_bin2bn(ec_p_%d, sizeof(ec_p_%d), NULL)) == NULL)\n"
- " goto err;\n", len, len);
- BIO_printf(out, " if ((tmp_2 = BN_bin2bn(ec_a_%d, sizeof(ec_a_%d), NULL)) == NULL)\n"
- " goto err;\n", len, len);
- BIO_printf(out, " if ((tmp_3 = BN_bin2bn(ec_b_%d, sizeof(ec_b_%d), NULL)) == NULL)\n"
- " goto err;\n", len, len);
- BIO_printf(out, " if ((group = EC_GROUP_new_curve_GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)\n"
- " goto err;\n"
- "\n");
- BIO_printf(out, " /* build generator */\n");
- BIO_printf(out, " if ((tmp_1 = BN_bin2bn(ec_gen_%d, sizeof(ec_gen_%d), tmp_1)) == NULL)\n"
- " goto err;\n", len, len);
- BIO_printf(out, " point = EC_POINT_bn2point(group, tmp_1, NULL, NULL);\n");
- BIO_printf(out, " if (point == NULL)\n"
- " goto err;\n");
- BIO_printf(out, " if ((tmp_2 = BN_bin2bn(ec_order_%d, sizeof(ec_order_%d), tmp_2)) == NULL)\n"
- " goto err;\n", len, len);
- BIO_printf(out, " if ((tmp_3 = BN_bin2bn(ec_cofactor_%d, sizeof(ec_cofactor_%d), tmp_3)) == NULL)\n"
- " goto err;\n", len, len);
- BIO_printf(out, " if (!EC_GROUP_set_generator(group, point, tmp_2, tmp_3))\n"
- " goto err;\n"
- "ok = 1;"
- "\n");
- BIO_printf(out, "err:\n"
- " BN_free(tmp_1);\n"
- " BN_free(tmp_2);\n"
- " BN_free(tmp_3);\n"
- " EC_POINT_free(point);\n"
- " if (!ok) {\n"
- " EC_GROUP_free(group);\n"
- " return NULL;\n"
- " }\n"
- " return (group);\n"
- "}\n");
+ BIO_printf(bio_err, "ok\n");
}
if (outformat == FORMAT_ASN1 && genkey)
noout = 1;
if (!noout) {
- if (outformat == FORMAT_ASN1)
- i = i2d_ECPKParameters_bio(out, group);
- else
- i = PEM_write_bio_ECPKParameters(out, group);
- if (!i) {
- BIO_printf(bio_err, "unable to write elliptic "
- "curve parameters\n");
- ERR_print_errors(bio_err);
+ ectx_params = OSSL_ENCODER_CTX_new_for_pkey(
+ params_key, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ outformat == FORMAT_ASN1 ? "DER" : "PEM", NULL, NULL);
+ if (!OSSL_ENCODER_to_bio(ectx_params, out)) {
+ BIO_printf(bio_err, "unable to write elliptic curve parameters\n");
goto end;
}
}
if (genkey) {
- EC_KEY *eckey = EC_KEY_new();
-
- if (eckey == NULL)
- goto end;
-
- if (EC_KEY_set_group(eckey, group) == 0) {
- BIO_printf(bio_err, "unable to set group when generating key\n");
- EC_KEY_free(eckey);
- ERR_print_errors(bio_err);
- goto end;
- }
-
- if (new_form)
- EC_KEY_set_conv_form(eckey, form);
-
- if (!EC_KEY_generate_key(eckey)) {
+ /*
+ * NOTE: EC keygen does not normally need to pass in the param_key
+ * for named curves. This can be achieved using:
+ * gctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
+ * EVP_PKEY_keygen_init(gctx);
+ * EVP_PKEY_CTX_set_group_name(gctx, curvename);
+ * EVP_PKEY_keygen(gctx, &key) <= 0)
+ */
+ gctx_key = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), params_key,
+ app_get0_propq());
+ if (EVP_PKEY_keygen_init(gctx_key) <= 0
+ || EVP_PKEY_keygen(gctx_key, &key) <= 0) {
BIO_printf(bio_err, "unable to generate key\n");
- EC_KEY_free(eckey);
- ERR_print_errors(bio_err);
goto end;
}
assert(private);
- if (outformat == FORMAT_ASN1)
- i = i2d_ECPrivateKey_bio(out, eckey);
- else
- i = PEM_write_bio_ECPrivateKey(out, eckey, NULL,
- NULL, 0, NULL, NULL);
- EC_KEY_free(eckey);
+ ectx_key = OSSL_ENCODER_CTX_new_for_pkey(
+ key, OSSL_KEYMGMT_SELECT_ALL,
+ outformat == FORMAT_ASN1 ? "DER" : "PEM", NULL, NULL);
+ if (!OSSL_ENCODER_to_bio(ectx_key, out)) {
+ BIO_printf(bio_err, "unable to write elliptic "
+ "curve parameters\n");
+ goto end;
+ }
}
ret = 0;
- end:
- BN_free(ec_p);
- BN_free(ec_a);
- BN_free(ec_b);
- BN_free(ec_gen);
- BN_free(ec_order);
- BN_free(ec_cofactor);
- OPENSSL_free(buffer);
- EC_GROUP_free(group);
+end:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
release_engine(e);
- BIO_free(in);
+ EVP_PKEY_free(params_key);
+ EVP_PKEY_free(key);
+ EVP_PKEY_CTX_free(pctx);
+ EVP_PKEY_CTX_free(gctx_params);
+ EVP_PKEY_CTX_free(gctx_key);
+ OSSL_DECODER_CTX_free(dctx_params);
+ OSSL_ENCODER_CTX_free(ectx_params);
+ OSSL_ENCODER_CTX_free(ectx_key);
BIO_free_all(out);
return ret;
}
diff --git a/apps/enc.c b/apps/enc.c
index 65710771a089..3dd609856304 100644
--- a/apps/enc.c
+++ b/apps/enc.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -39,38 +39,51 @@ struct doall_enc_ciphers {
};
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_LIST,
OPT_E, OPT_IN, OPT_OUT, OPT_PASS, OPT_ENGINE, OPT_D, OPT_P, OPT_V,
OPT_NOPAD, OPT_SALT, OPT_NOSALT, OPT_DEBUG, OPT_UPPER_P, OPT_UPPER_A,
OPT_A, OPT_Z, OPT_BUFSIZE, OPT_K, OPT_KFILE, OPT_UPPER_K, OPT_NONE,
OPT_UPPER_S, OPT_IV, OPT_MD, OPT_ITER, OPT_PBKDF2, OPT_CIPHER,
- OPT_R_ENUM
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS enc_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"list", OPT_LIST, '-', "List ciphers"},
+#ifndef OPENSSL_NO_DEPRECATED_3_0
{"ciphers", OPT_LIST, '-', "Alias for -list"},
- {"in", OPT_IN, '<', "Input file"},
- {"out", OPT_OUT, '>', "Output file"},
- {"pass", OPT_PASS, 's', "Passphrase source"},
+#endif
{"e", OPT_E, '-', "Encrypt"},
{"d", OPT_D, '-', "Decrypt"},
{"p", OPT_P, '-', "Print the iv/key"},
{"P", OPT_UPPER_P, '-', "Print the iv/key and exit"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, '<', "Input file"},
+ {"k", OPT_K, 's', "Passphrase"},
+ {"kfile", OPT_KFILE, '<', "Read passphrase from file"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"pass", OPT_PASS, 's', "Passphrase source"},
{"v", OPT_V, '-', "Verbose output"},
- {"nopad", OPT_NOPAD, '-', "Disable standard block padding"},
- {"salt", OPT_SALT, '-', "Use salt in the KDF (default)"},
- {"nosalt", OPT_NOSALT, '-', "Do not use salt in the KDF"},
- {"debug", OPT_DEBUG, '-', "Print debug info"},
{"a", OPT_A, '-', "Base64 encode/decode, depending on encryption flag"},
{"base64", OPT_A, '-', "Same as option -a"},
{"A", OPT_UPPER_A, '-',
"Used with -[base64|a] to specify base64 buffer as a single line"},
+
+ OPT_SECTION("Encryption"),
+ {"nopad", OPT_NOPAD, '-', "Disable standard block padding"},
+ {"salt", OPT_SALT, '-', "Use salt in the KDF (default)"},
+ {"nosalt", OPT_NOSALT, '-', "Do not use salt in the KDF"},
+ {"debug", OPT_DEBUG, '-', "Print debug info"},
+
{"bufsize", OPT_BUFSIZE, 's', "Buffer size"},
- {"k", OPT_K, 's', "Passphrase"},
- {"kfile", OPT_KFILE, '<', "Read passphrase from file"},
{"K", OPT_UPPER_K, 's', "Raw key, in hex"},
{"S", OPT_UPPER_S, 's', "Salt, in hex"},
{"iv", OPT_IV, 's', "IV in hex"},
@@ -78,14 +91,13 @@ const OPTIONS enc_options[] = {
{"iter", OPT_ITER, 'p', "Specify the iteration count and force use of PBKDF2"},
{"pbkdf2", OPT_PBKDF2, '-', "Use password-based key derivation function 2"},
{"none", OPT_NONE, '-', "Don't encrypt"},
- {"", OPT_CIPHER, '-', "Any supported cipher"},
- OPT_R_OPTIONS,
#ifdef ZLIB
{"z", OPT_Z, '-', "Compress or decompress encrypted data using zlib"},
#endif
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
+ {"", OPT_CIPHER, '-', "Any supported cipher"},
+
+ OPT_R_OPTIONS,
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -97,11 +109,13 @@ int enc_main(int argc, char **argv)
BIO *in = NULL, *out = NULL, *b64 = NULL, *benc = NULL, *rbio =
NULL, *wbio = NULL;
EVP_CIPHER_CTX *ctx = NULL;
- const EVP_CIPHER *cipher = NULL, *c;
- const EVP_MD *dgst = NULL;
+ EVP_CIPHER *cipher = NULL;
+ EVP_MD *dgst = NULL;
+ const char *digestname = NULL;
char *hkey = NULL, *hiv = NULL, *hsalt = NULL, *p;
char *infile = NULL, *outfile = NULL, *prog;
char *str = NULL, *passarg = NULL, *pass = NULL, *strbuf = NULL;
+ const char *ciphername = NULL;
char mbuf[sizeof(magic) - 1];
OPTION_CHOICE o;
int bsize = BSIZE, verbose = 0, debug = 0, olb64 = 0, nosalt = 0;
@@ -119,21 +133,15 @@ int enc_main(int argc, char **argv)
BIO *bzl = NULL;
#endif
- /* first check the program name */
- prog = opt_progname(argv[0]);
- if (strcmp(prog, "base64") == 0) {
+ /* first check the command name */
+ if (strcmp(argv[0], "base64") == 0)
base64 = 1;
#ifdef ZLIB
- } else if (strcmp(prog, "zlib") == 0) {
+ else if (strcmp(argv[0], "zlib") == 0)
do_zlib = 1;
#endif
- } else {
- cipher = EVP_get_cipherbyname(prog);
- if (cipher == NULL && strcmp(prog, "enc") != 0) {
- BIO_printf(bio_err, "%s is not a known cipher\n", prog);
- goto end;
- }
- }
+ else if (strcmp(argv[0], "enc") != 0)
+ ciphername = argv[0];
prog = opt_init(argc, argv, enc_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -252,17 +260,13 @@ int enc_main(int argc, char **argv)
hiv = opt_arg();
break;
case OPT_MD:
- if (!opt_md(opt_arg(), &dgst))
- goto opthelp;
+ digestname = opt_arg();
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &c))
- goto opthelp;
- cipher = c;
+ ciphername = opt_unknown();
break;
case OPT_ITER:
- if (!opt_int(opt_arg(), &iter))
- goto opthelp;
+ iter = opt_int_arg();
pbkdf2 = 1;
break;
case OPT_PBKDF2:
@@ -277,25 +281,31 @@ int enc_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
- if (opt_num_rest() != 0) {
- BIO_printf(bio_err, "Extra arguments given.\n");
- goto opthelp;
- }
- if (cipher && EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) {
- BIO_printf(bio_err, "%s: AEAD ciphers not supported\n", prog);
+ /* No extra arguments. */
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+ if (!app_RAND_load())
goto end;
- }
- if (cipher && (EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE)) {
- BIO_printf(bio_err, "%s XTS ciphers not supported\n", prog);
- goto end;
+ /* Get the cipher name, either from progname (if set) or flag. */
+ if (ciphername != NULL) {
+ if (!opt_cipher(ciphername, &cipher))
+ goto opthelp;
+ }
+ if (digestname != NULL) {
+ if (!opt_md(digestname, &dgst))
+ goto opthelp;
}
-
if (dgst == NULL)
- dgst = EVP_sha256();
+ dgst = (EVP_MD *)EVP_sha256();
if (iter == 0)
iter = 1;
@@ -342,7 +352,7 @@ int enc_main(int argc, char **argv)
char prompt[200];
BIO_snprintf(prompt, sizeof(prompt), "enter %s %s password:",
- OBJ_nid2ln(EVP_CIPHER_nid(cipher)),
+ EVP_CIPHER_get0_name(cipher),
(enc) ? "encryption" : "decryption");
strbuf[0] = '\0';
i = EVP_read_pw_string((char *)strbuf, SIZE, prompt, enc);
@@ -371,8 +381,8 @@ int enc_main(int argc, char **argv)
goto end;
if (debug) {
- BIO_set_callback(in, BIO_debug_callback);
- BIO_set_callback(out, BIO_debug_callback);
+ BIO_set_callback_ex(in, BIO_debug_callback_ex);
+ BIO_set_callback_ex(out, BIO_debug_callback_ex);
BIO_set_callback_arg(in, (char *)bio_err);
BIO_set_callback_arg(out, (char *)bio_err);
}
@@ -385,7 +395,7 @@ int enc_main(int argc, char **argv)
if ((bzl = BIO_new(BIO_f_zlib())) == NULL)
goto end;
if (debug) {
- BIO_set_callback(bzl, BIO_debug_callback);
+ BIO_set_callback_ex(bzl, BIO_debug_callback_ex);
BIO_set_callback_arg(bzl, (char *)bio_err);
}
if (enc)
@@ -399,7 +409,7 @@ int enc_main(int argc, char **argv)
if ((b64 = BIO_new(BIO_f_base64())) == NULL)
goto end;
if (debug) {
- BIO_set_callback(b64, BIO_debug_callback);
+ BIO_set_callback_ex(b64, BIO_debug_callback_ex);
BIO_set_callback_arg(b64, (char *)bio_err);
}
if (olb64)
@@ -411,14 +421,11 @@ int enc_main(int argc, char **argv)
}
if (cipher != NULL) {
- /*
- * Note that str is NULL if a key was passed on the command line, so
- * we get no salt in that case. Is this a bug?
- */
- if (str != NULL) {
+ if (str != NULL) { /* a passphrase is available */
/*
- * Salt handling: if encrypting generate a salt and write to
- * output BIO. If decrypting read salt from input BIO.
+ * Salt handling: if encrypting generate a salt if not supplied,
+ * and write to output BIO. If decrypting use salt from input BIO
+ * if not given with args
*/
unsigned char *sptr;
size_t str_len = strlen(str);
@@ -426,36 +433,47 @@ int enc_main(int argc, char **argv)
if (nosalt) {
sptr = NULL;
} else {
- if (enc) {
- if (hsalt) {
- if (!set_hex(hsalt, salt, sizeof(salt))) {
- BIO_printf(bio_err, "invalid hex salt value\n");
+ if (hsalt != NULL && !set_hex(hsalt, salt, sizeof(salt))) {
+ BIO_printf(bio_err, "invalid hex salt value\n");
+ goto end;
+ }
+ if (enc) { /* encryption */
+ if (hsalt == NULL) {
+ if (RAND_bytes(salt, sizeof(salt)) <= 0) {
+ BIO_printf(bio_err, "RAND_bytes failed\n");
+ goto end;
+ }
+ /*
+ * If -P option then don't bother writing.
+ * If salt is given, shouldn't either ?
+ */
+ if ((printkey != 2)
+ && (BIO_write(wbio, magic,
+ sizeof(magic) - 1) != sizeof(magic) - 1
+ || BIO_write(wbio,
+ (char *)salt,
+ sizeof(salt)) != sizeof(salt))) {
+ BIO_printf(bio_err, "error writing output file\n");
goto end;
}
- } else if (RAND_bytes(salt, sizeof(salt)) <= 0) {
- goto end;
}
- /*
- * If -P option then don't bother writing
- */
- if ((printkey != 2)
- && (BIO_write(wbio, magic,
- sizeof(magic) - 1) != sizeof(magic) - 1
- || BIO_write(wbio,
- (char *)salt,
- sizeof(salt)) != sizeof(salt))) {
- BIO_printf(bio_err, "error writing output file\n");
- goto end;
+ } else { /* decryption */
+ if (hsalt == NULL) {
+ if (BIO_read(rbio, mbuf, sizeof(mbuf)) != sizeof(mbuf)) {
+ BIO_printf(bio_err, "error reading input file\n");
+ goto end;
+ }
+ if (memcmp(mbuf, magic, sizeof(mbuf)) == 0) { /* file IS salted */
+ if (BIO_read(rbio, salt,
+ sizeof(salt)) != sizeof(salt)) {
+ BIO_printf(bio_err, "error reading input file\n");
+ goto end;
+ }
+ } else { /* file is NOT salted, NO salt available */
+ BIO_printf(bio_err, "bad magic number\n");
+ goto end;
+ }
}
- } else if (BIO_read(rbio, mbuf, sizeof(mbuf)) != sizeof(mbuf)
- || BIO_read(rbio,
- (unsigned char *)salt,
- sizeof(salt)) != sizeof(salt)) {
- BIO_printf(bio_err, "error reading input file\n");
- goto end;
- } else if (memcmp(mbuf, magic, sizeof(magic) - 1)) {
- BIO_printf(bio_err, "bad magic number\n");
- goto end;
}
sptr = salt;
}
@@ -466,8 +484,8 @@ int enc_main(int argc, char **argv)
* concatenated into a temporary buffer
*/
unsigned char tmpkeyiv[EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH];
- int iklen = EVP_CIPHER_key_length(cipher);
- int ivlen = EVP_CIPHER_iv_length(cipher);
+ int iklen = EVP_CIPHER_get_key_length(cipher);
+ int ivlen = EVP_CIPHER_get_iv_length(cipher);
/* not needed if HASH_UPDATE() is fixed : */
int islen = (sptr != NULL ? sizeof(salt) : 0);
if (!PKCS5_PBKDF2_HMAC(str, str_len, sptr, islen,
@@ -499,7 +517,7 @@ int enc_main(int argc, char **argv)
OPENSSL_cleanse(str, str_len);
}
if (hiv != NULL) {
- int siz = EVP_CIPHER_iv_length(cipher);
+ int siz = EVP_CIPHER_get_iv_length(cipher);
if (siz == 0) {
BIO_printf(bio_err, "warning: iv not used by this cipher\n");
} else if (!set_hex(hiv, iv, siz)) {
@@ -508,7 +526,7 @@ int enc_main(int argc, char **argv)
}
}
if ((hiv == NULL) && (str == NULL)
- && EVP_CIPHER_iv_length(cipher) != 0) {
+ && EVP_CIPHER_get_iv_length(cipher) != 0) {
/*
* No IV was explicitly set and no IV was generated.
* Hence the IV is undefined, making correct decryption impossible.
@@ -517,12 +535,12 @@ int enc_main(int argc, char **argv)
goto end;
}
if (hkey != NULL) {
- if (!set_hex(hkey, key, EVP_CIPHER_key_length(cipher))) {
+ if (!set_hex(hkey, key, EVP_CIPHER_get_key_length(cipher))) {
BIO_printf(bio_err, "invalid hex key value\n");
goto end;
}
/* wiping secret data as we no longer need it */
- OPENSSL_cleanse(hkey, strlen(hkey));
+ cleanse(hkey);
}
if ((benc = BIO_new(BIO_f_cipher())) == NULL)
@@ -535,9 +553,9 @@ int enc_main(int argc, char **argv)
BIO_get_cipher_ctx(benc, &ctx);
- if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)) {
+ if (!EVP_CipherInit_ex(ctx, cipher, e, NULL, NULL, enc)) {
BIO_printf(bio_err, "Error setting cipher %s\n",
- EVP_CIPHER_name(cipher));
+ EVP_CIPHER_get0_name(cipher));
ERR_print_errors(bio_err);
goto end;
}
@@ -547,13 +565,13 @@ int enc_main(int argc, char **argv)
if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc)) {
BIO_printf(bio_err, "Error setting cipher %s\n",
- EVP_CIPHER_name(cipher));
+ EVP_CIPHER_get0_name(cipher));
ERR_print_errors(bio_err);
goto end;
}
if (debug) {
- BIO_set_callback(benc, BIO_debug_callback);
+ BIO_set_callback_ex(benc, BIO_debug_callback_ex);
BIO_set_callback_arg(benc, (char *)bio_err);
}
@@ -564,15 +582,15 @@ int enc_main(int argc, char **argv)
printf("%02X", salt[i]);
printf("\n");
}
- if (EVP_CIPHER_key_length(cipher) > 0) {
+ if (EVP_CIPHER_get_key_length(cipher) > 0) {
printf("key=");
- for (i = 0; i < EVP_CIPHER_key_length(cipher); i++)
+ for (i = 0; i < EVP_CIPHER_get_key_length(cipher); i++)
printf("%02X", key[i]);
printf("\n");
}
- if (EVP_CIPHER_iv_length(cipher) > 0) {
+ if (EVP_CIPHER_get_iv_length(cipher) > 0) {
printf("iv =");
- for (i = 0; i < EVP_CIPHER_iv_length(cipher); i++)
+ for (i = 0; i < EVP_CIPHER_get_iv_length(cipher); i++)
printf("%02X", iv[i]);
printf("\n");
}
@@ -614,6 +632,8 @@ int enc_main(int argc, char **argv)
BIO_free_all(out);
BIO_free(benc);
BIO_free(b64);
+ EVP_MD_free(dgst);
+ EVP_CIPHER_free(cipher);
#ifdef ZLIB
BIO_free(bzl);
#endif
@@ -632,9 +652,9 @@ static void show_ciphers(const OBJ_NAME *name, void *arg)
/* Filter out ciphers that we cannot use */
cipher = EVP_get_cipherbyname(name->name);
- if (cipher == NULL ||
- (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0 ||
- EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE)
+ if (cipher == NULL
+ || (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0
+ || EVP_CIPHER_get_mode(cipher) == EVP_CIPH_XTS_MODE)
return;
BIO_printf(dec->bio, "-%-25s", name->name);
diff --git a/apps/engine.c b/apps/engine.c
index 746cace354b2..1b0f64309c6f 100644
--- a/apps/engine.c
+++ b/apps/engine.c
@@ -1,13 +1,17 @@
/*
- * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <openssl/opensslconf.h>
+
#include "apps.h"
#include "progs.h"
#include <stdio.h>
@@ -19,27 +23,32 @@
#include <openssl/store.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_C, OPT_T, OPT_TT, OPT_PRE, OPT_POST,
OPT_V = 100, OPT_VV, OPT_VVV, OPT_VVVV
} OPTION_CHOICE;
const OPTIONS engine_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] engine...\n"},
- {OPT_HELP_STR, 1, '-',
- " engine... Engines to load\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"t", OPT_T, '-', "Check that specified engine is available"},
+ {"pre", OPT_PRE, 's', "Run command against the ENGINE before loading it"},
+ {"post", OPT_POST, 's', "Run command against the ENGINE after loading it"},
+
+ OPT_SECTION("Output"),
{"v", OPT_V, '-', "List 'control commands' For each specified engine"},
{"vv", OPT_VV, '-', "Also display each command's description"},
{"vvv", OPT_VVV, '-', "Also add the input flags for each command"},
{"vvvv", OPT_VVVV, '-', "Also show internal input flags"},
{"c", OPT_C, '-', "List the capabilities of specified engine"},
- {"t", OPT_T, '-', "Check that specified engine is available"},
{"tt", OPT_TT, '-', "Display error trace for unavailable engines"},
- {"pre", OPT_PRE, 's', "Run command against the ENGINE before loading it"},
- {"post", OPT_POST, 's', "Run command against the ENGINE after loading it"},
{OPT_MORE_STR, OPT_EOF, 1,
"Commands are like \"SO_PATH:/lib/libdriver.so\""},
+
+ OPT_PARAMETERS(),
+ {"engine", 0, 0, "ID of engine(s) to load"},
{NULL}
};
@@ -351,7 +360,7 @@ int engine_main(int argc, char **argv)
}
}
- /* Allow any trailing parameters as engine names. */
+ /* Any remaining arguments are engine names. */
argc = opt_num_rest();
argv = opt_rest();
for ( ; *argv; argv++) {
diff --git a/apps/errstr.c b/apps/errstr.c
index 3ef01f076a8c..782705a78a33 100644
--- a/apps/errstr.c
+++ b/apps/errstr.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -22,8 +22,12 @@ typedef enum OPTION_choice {
const OPTIONS errstr_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] errnum...\n"},
- {OPT_HELP_STR, 1, '-', " errnum Error number\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+
+ OPT_PARAMETERS(),
+ {"errnum", 0, 0, "Error number(s) to decode"},
{NULL}
};
@@ -48,16 +52,19 @@ int errstr_main(int argc, char **argv)
}
}
+ /*
+ * We're not really an SSL application so this won't auto-init, but
+ * we're still interested in SSL error strings
+ */
+ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
+ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
+
+ /* All remaining arg are error code. */
ret = 0;
- for (argv = opt_rest(); *argv; argv++) {
+ for (argv = opt_rest(); *argv != NULL; argv++) {
if (sscanf(*argv, "%lx", &l) == 0) {
ret++;
} else {
- /* We're not really an SSL application so this won't auto-init, but
- * we're still interested in SSL error strings
- */
- OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
- | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
ERR_error_string_n(l, buf, sizeof(buf));
BIO_printf(bio_out, "%s\n", buf);
}
diff --git a/apps/fipsinstall.c b/apps/fipsinstall.c
new file mode 100644
index 000000000000..d0efdf7643bd
--- /dev/null
+++ b/apps/fipsinstall.c
@@ -0,0 +1,590 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/provider.h>
+#include <openssl/params.h>
+#include <openssl/fips_names.h>
+#include <openssl/core_names.h>
+#include <openssl/self_test.h>
+#include <openssl/fipskey.h>
+#include "apps.h"
+#include "progs.h"
+
+#define BUFSIZE 4096
+
+/* Configuration file values */
+#define VERSION_KEY "version"
+#define VERSION_VAL "1"
+#define INSTALL_STATUS_VAL "INSTALL_SELF_TEST_KATS_RUN"
+
+static OSSL_CALLBACK self_test_events;
+static char *self_test_corrupt_desc = NULL;
+static char *self_test_corrupt_type = NULL;
+static int self_test_log = 1;
+static int quiet = 0;
+
+typedef enum OPTION_choice {
+ OPT_COMMON,
+ OPT_IN, OPT_OUT, OPT_MODULE,
+ OPT_PROV_NAME, OPT_SECTION_NAME, OPT_MAC_NAME, OPT_MACOPT, OPT_VERIFY,
+ OPT_NO_LOG, OPT_CORRUPT_DESC, OPT_CORRUPT_TYPE, OPT_QUIET, OPT_CONFIG,
+ OPT_NO_CONDITIONAL_ERRORS,
+ OPT_NO_SECURITY_CHECKS,
+ OPT_SELF_TEST_ONLOAD
+} OPTION_CHOICE;
+
+const OPTIONS fipsinstall_options[] = {
+ OPT_SECTION("General"),
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"verify", OPT_VERIFY, '-',
+ "Verify a config file instead of generating one"},
+ {"module", OPT_MODULE, '<', "File name of the provider module"},
+ {"provider_name", OPT_PROV_NAME, 's', "FIPS provider name"},
+ {"section_name", OPT_SECTION_NAME, 's',
+ "FIPS Provider config section name (optional)"},
+ {"no_conditional_errors", OPT_NO_CONDITIONAL_ERRORS, '-',
+ "Disable the ability of the fips module to enter an error state if"
+ " any conditional self tests fail"},
+ {"no_security_checks", OPT_NO_SECURITY_CHECKS, '-',
+ "Disable the run-time FIPS security checks in the module"},
+ {"self_test_onload", OPT_SELF_TEST_ONLOAD, '-',
+ "Forces self tests to always run on module load"},
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, '<', "Input config file, used when verifying"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output config file, used when generating"},
+ {"mac_name", OPT_MAC_NAME, 's', "MAC name"},
+ {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form. "
+ "See 'PARAMETER NAMES' in the EVP_MAC_ docs"},
+ {"noout", OPT_NO_LOG, '-', "Disable logging of self test events"},
+ {"corrupt_desc", OPT_CORRUPT_DESC, 's', "Corrupt a self test by description"},
+ {"corrupt_type", OPT_CORRUPT_TYPE, 's', "Corrupt a self test by type"},
+ {"config", OPT_CONFIG, '<', "The parent config to verify"},
+ {"quiet", OPT_QUIET, '-', "No messages, just exit status"},
+ {NULL}
+};
+
+static int do_mac(EVP_MAC_CTX *ctx, unsigned char *tmp, BIO *in,
+ unsigned char *out, size_t *out_len)
+{
+ int ret = 0;
+ int i;
+ size_t outsz = *out_len;
+
+ if (!EVP_MAC_init(ctx, NULL, 0, NULL))
+ goto err;
+ if (EVP_MAC_CTX_get_mac_size(ctx) > outsz)
+ goto end;
+ while ((i = BIO_read(in, (char *)tmp, BUFSIZE)) != 0) {
+ if (i < 0 || !EVP_MAC_update(ctx, tmp, i))
+ goto err;
+ }
+end:
+ if (!EVP_MAC_final(ctx, out, out_len, outsz))
+ goto err;
+ ret = 1;
+err:
+ return ret;
+}
+
+static int load_fips_prov_and_run_self_test(const char *prov_name)
+{
+ int ret = 0;
+ OSSL_PROVIDER *prov = NULL;
+
+ prov = OSSL_PROVIDER_load(NULL, prov_name);
+ if (prov == NULL) {
+ BIO_printf(bio_err, "Failed to load FIPS module\n");
+ goto end;
+ }
+ ret = 1;
+end:
+ OSSL_PROVIDER_unload(prov);
+ return ret;
+}
+
+static int print_mac(BIO *bio, const char *label, const unsigned char *mac,
+ size_t len)
+{
+ int ret;
+ char *hexstr = NULL;
+
+ hexstr = OPENSSL_buf2hexstr(mac, (long)len);
+ if (hexstr == NULL)
+ return 0;
+ ret = BIO_printf(bio, "%s = %s\n", label, hexstr);
+ OPENSSL_free(hexstr);
+ return ret;
+}
+
+static int write_config_header(BIO *out, const char *prov_name,
+ const char *section)
+{
+ return BIO_printf(out, "openssl_conf = openssl_init\n\n")
+ && BIO_printf(out, "[openssl_init]\n")
+ && BIO_printf(out, "providers = provider_section\n\n")
+ && BIO_printf(out, "[provider_section]\n")
+ && BIO_printf(out, "%s = %s\n\n", prov_name, section);
+}
+
+/*
+ * Outputs a fips related config file that contains entries for the fips
+ * module checksum, installation indicator checksum and the options
+ * conditional_errors and security_checks.
+ *
+ * Returns 1 if the config file is written otherwise it returns 0 on error.
+ */
+static int write_config_fips_section(BIO *out, const char *section,
+ unsigned char *module_mac,
+ size_t module_mac_len,
+ int conditional_errors,
+ int security_checks,
+ unsigned char *install_mac,
+ size_t install_mac_len)
+{
+ int ret = 0;
+
+ if (BIO_printf(out, "[%s]\n", section) <= 0
+ || BIO_printf(out, "activate = 1\n") <= 0
+ || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_VERSION,
+ VERSION_VAL) <= 0
+ || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS,
+ conditional_errors ? "1" : "0") <= 0
+ || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS,
+ security_checks ? "1" : "0") <= 0
+ || !print_mac(out, OSSL_PROV_FIPS_PARAM_MODULE_MAC, module_mac,
+ module_mac_len))
+ goto end;
+
+ if (install_mac != NULL && install_mac_len > 0) {
+ if (!print_mac(out, OSSL_PROV_FIPS_PARAM_INSTALL_MAC, install_mac,
+ install_mac_len)
+ || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_STATUS,
+ INSTALL_STATUS_VAL) <= 0)
+ goto end;
+ }
+ ret = 1;
+end:
+ return ret;
+}
+
+static CONF *generate_config_and_load(const char *prov_name,
+ const char *section,
+ unsigned char *module_mac,
+ size_t module_mac_len,
+ int conditional_errors,
+ int security_checks)
+{
+ BIO *mem_bio = NULL;
+ CONF *conf = NULL;
+
+ mem_bio = BIO_new(BIO_s_mem());
+ if (mem_bio == NULL)
+ return 0;
+ if (!write_config_header(mem_bio, prov_name, section)
+ || !write_config_fips_section(mem_bio, section,
+ module_mac, module_mac_len,
+ conditional_errors,
+ security_checks,
+ NULL, 0))
+ goto end;
+
+ conf = app_load_config_bio(mem_bio, NULL);
+ if (conf == NULL)
+ goto end;
+
+ if (CONF_modules_load(conf, NULL, 0) <= 0)
+ goto end;
+ BIO_free(mem_bio);
+ return conf;
+end:
+ NCONF_free(conf);
+ BIO_free(mem_bio);
+ return NULL;
+}
+
+static void free_config_and_unload(CONF *conf)
+{
+ if (conf != NULL) {
+ NCONF_free(conf);
+ CONF_modules_unload(1);
+ }
+}
+
+static int verify_module_load(const char *parent_config_file)
+{
+ return OSSL_LIB_CTX_load_config(NULL, parent_config_file);
+}
+
+/*
+ * Returns 1 if the config file entries match the passed in module_mac and
+ * install_mac values, otherwise it returns 0.
+ */
+static int verify_config(const char *infile, const char *section,
+ unsigned char *module_mac, size_t module_mac_len,
+ unsigned char *install_mac, size_t install_mac_len)
+{
+ int ret = 0;
+ char *s = NULL;
+ unsigned char *buf1 = NULL, *buf2 = NULL;
+ long len;
+ CONF *conf = NULL;
+
+ /* read in the existing values and check they match the saved values */
+ conf = app_load_config(infile);
+ if (conf == NULL)
+ goto end;
+
+ s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_VERSION);
+ if (s == NULL || strcmp(s, VERSION_VAL) != 0) {
+ BIO_printf(bio_err, "version not found\n");
+ goto end;
+ }
+ s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_MODULE_MAC);
+ if (s == NULL) {
+ BIO_printf(bio_err, "Module integrity MAC not found\n");
+ goto end;
+ }
+ buf1 = OPENSSL_hexstr2buf(s, &len);
+ if (buf1 == NULL
+ || (size_t)len != module_mac_len
+ || memcmp(module_mac, buf1, module_mac_len) != 0) {
+ BIO_printf(bio_err, "Module integrity mismatch\n");
+ goto end;
+ }
+ if (install_mac != NULL && install_mac_len > 0) {
+ s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_STATUS);
+ if (s == NULL || strcmp(s, INSTALL_STATUS_VAL) != 0) {
+ BIO_printf(bio_err, "install status not found\n");
+ goto end;
+ }
+ s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_MAC);
+ if (s == NULL) {
+ BIO_printf(bio_err, "Install indicator MAC not found\n");
+ goto end;
+ }
+ buf2 = OPENSSL_hexstr2buf(s, &len);
+ if (buf2 == NULL
+ || (size_t)len != install_mac_len
+ || memcmp(install_mac, buf2, install_mac_len) != 0) {
+ BIO_printf(bio_err, "Install indicator status mismatch\n");
+ goto end;
+ }
+ }
+ ret = 1;
+end:
+ OPENSSL_free(buf1);
+ OPENSSL_free(buf2);
+ NCONF_free(conf);
+ return ret;
+}
+
+int fipsinstall_main(int argc, char **argv)
+{
+ int ret = 1, verify = 0, gotkey = 0, gotdigest = 0, self_test_onload = 0;
+ int enable_conditional_errors = 1, enable_security_checks = 1;
+ const char *section_name = "fips_sect";
+ const char *mac_name = "HMAC";
+ const char *prov_name = "fips";
+ BIO *module_bio = NULL, *mem_bio = NULL, *fout = NULL;
+ char *in_fname = NULL, *out_fname = NULL, *prog;
+ char *module_fname = NULL, *parent_config = NULL, *module_path = NULL;
+ const char *tail;
+ EVP_MAC_CTX *ctx = NULL, *ctx2 = NULL;
+ STACK_OF(OPENSSL_STRING) *opts = NULL;
+ OPTION_CHOICE o;
+ unsigned char *read_buffer = NULL;
+ unsigned char module_mac[EVP_MAX_MD_SIZE];
+ size_t module_mac_len = EVP_MAX_MD_SIZE;
+ unsigned char install_mac[EVP_MAX_MD_SIZE];
+ size_t install_mac_len = EVP_MAX_MD_SIZE;
+ EVP_MAC *mac = NULL;
+ CONF *conf = NULL;
+
+ if ((opts = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+
+ prog = opt_init(argc, argv, fipsinstall_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto cleanup;
+ case OPT_HELP:
+ opt_help(fipsinstall_options);
+ ret = 0;
+ goto end;
+ case OPT_IN:
+ in_fname = opt_arg();
+ break;
+ case OPT_OUT:
+ out_fname = opt_arg();
+ break;
+ case OPT_NO_CONDITIONAL_ERRORS:
+ enable_conditional_errors = 0;
+ break;
+ case OPT_NO_SECURITY_CHECKS:
+ enable_security_checks = 0;
+ break;
+ case OPT_QUIET:
+ quiet = 1;
+ /* FALLTHROUGH */
+ case OPT_NO_LOG:
+ self_test_log = 0;
+ break;
+ case OPT_CORRUPT_DESC:
+ self_test_corrupt_desc = opt_arg();
+ break;
+ case OPT_CORRUPT_TYPE:
+ self_test_corrupt_type = opt_arg();
+ break;
+ case OPT_PROV_NAME:
+ prov_name = opt_arg();
+ break;
+ case OPT_MODULE:
+ module_fname = opt_arg();
+ break;
+ case OPT_SECTION_NAME:
+ section_name = opt_arg();
+ break;
+ case OPT_MAC_NAME:
+ mac_name = opt_arg();
+ break;
+ case OPT_CONFIG:
+ parent_config = opt_arg();
+ break;
+ case OPT_MACOPT:
+ if (!sk_OPENSSL_STRING_push(opts, opt_arg()))
+ goto opthelp;
+ if (strncmp(opt_arg(), "hexkey:", 7) == 0)
+ gotkey = 1;
+ else if (strncmp(opt_arg(), "digest:", 7) == 0)
+ gotdigest = 1;
+ break;
+ case OPT_VERIFY:
+ verify = 1;
+ break;
+ case OPT_SELF_TEST_ONLOAD:
+ self_test_onload = 1;
+ break;
+ }
+ }
+
+ /* No extra arguments. */
+ argc = opt_num_rest();
+ if (argc != 0 || (verify && in_fname == NULL))
+ goto opthelp;
+
+ if (parent_config != NULL) {
+ /* Test that a parent config can load the module */
+ if (verify_module_load(parent_config)) {
+ ret = OSSL_PROVIDER_available(NULL, prov_name) ? 0 : 1;
+ if (!quiet)
+ BIO_printf(bio_err, "FIPS provider is %s\n",
+ ret == 0 ? "available" : " not available");
+ }
+ goto end;
+ }
+ if (module_fname == NULL)
+ goto opthelp;
+
+ tail = opt_path_end(module_fname);
+ if (tail != NULL) {
+ module_path = OPENSSL_strdup(module_fname);
+ if (module_path == NULL)
+ goto end;
+ module_path[tail - module_fname] = '\0';
+ if (!OSSL_PROVIDER_set_default_search_path(NULL, module_path))
+ goto end;
+ }
+
+ if (self_test_log
+ || self_test_corrupt_desc != NULL
+ || self_test_corrupt_type != NULL)
+ OSSL_SELF_TEST_set_callback(NULL, self_test_events, NULL);
+
+ /* Use the default FIPS HMAC digest and key if not specified. */
+ if (!gotdigest && !sk_OPENSSL_STRING_push(opts, "digest:SHA256"))
+ goto end;
+ if (!gotkey && !sk_OPENSSL_STRING_push(opts, "hexkey:" FIPS_KEY_STRING))
+ goto end;
+
+ module_bio = bio_open_default(module_fname, 'r', FORMAT_BINARY);
+ if (module_bio == NULL) {
+ BIO_printf(bio_err, "Failed to open module file\n");
+ goto end;
+ }
+
+ read_buffer = app_malloc(BUFSIZE, "I/O buffer");
+ if (read_buffer == NULL)
+ goto end;
+
+ mac = EVP_MAC_fetch(app_get0_libctx(), mac_name, app_get0_propq());
+ if (mac == NULL) {
+ BIO_printf(bio_err, "Unable to get MAC of type %s\n", mac_name);
+ goto end;
+ }
+
+ ctx = EVP_MAC_CTX_new(mac);
+ if (ctx == NULL) {
+ BIO_printf(bio_err, "Unable to create MAC CTX for module check\n");
+ goto end;
+ }
+
+ if (opts != NULL) {
+ int ok = 1;
+ OSSL_PARAM *params =
+ app_params_new_from_opts(opts, EVP_MAC_settable_ctx_params(mac));
+
+ if (params == NULL)
+ goto end;
+
+ if (!EVP_MAC_CTX_set_params(ctx, params)) {
+ BIO_printf(bio_err, "MAC parameter error\n");
+ ERR_print_errors(bio_err);
+ ok = 0;
+ }
+ app_params_free(params);
+ if (!ok)
+ goto end;
+ }
+
+ ctx2 = EVP_MAC_CTX_dup(ctx);
+ if (ctx2 == NULL) {
+ BIO_printf(bio_err, "Unable to create MAC CTX for install indicator\n");
+ goto end;
+ }
+
+ if (!do_mac(ctx, read_buffer, module_bio, module_mac, &module_mac_len))
+ goto end;
+
+ if (self_test_onload == 0) {
+ mem_bio = BIO_new_mem_buf((const void *)INSTALL_STATUS_VAL,
+ strlen(INSTALL_STATUS_VAL));
+ if (mem_bio == NULL) {
+ BIO_printf(bio_err, "Unable to create memory BIO\n");
+ goto end;
+ }
+ if (!do_mac(ctx2, read_buffer, mem_bio, install_mac, &install_mac_len))
+ goto end;
+ } else {
+ install_mac_len = 0;
+ }
+
+ if (verify) {
+ if (!verify_config(in_fname, section_name, module_mac, module_mac_len,
+ install_mac, install_mac_len))
+ goto end;
+ if (!quiet)
+ BIO_printf(bio_err, "VERIFY PASSED\n");
+ } else {
+
+ conf = generate_config_and_load(prov_name, section_name, module_mac,
+ module_mac_len,
+ enable_conditional_errors,
+ enable_security_checks);
+ if (conf == NULL)
+ goto end;
+ if (!load_fips_prov_and_run_self_test(prov_name))
+ goto end;
+
+ fout =
+ out_fname == NULL ? dup_bio_out(FORMAT_TEXT)
+ : bio_open_default(out_fname, 'w', FORMAT_TEXT);
+ if (fout == NULL) {
+ BIO_printf(bio_err, "Failed to open file\n");
+ goto end;
+ }
+ if (!write_config_fips_section(fout, section_name,
+ module_mac, module_mac_len,
+ enable_conditional_errors,
+ enable_security_checks,
+ install_mac, install_mac_len))
+ goto end;
+ if (!quiet)
+ BIO_printf(bio_err, "INSTALL PASSED\n");
+ }
+
+ ret = 0;
+end:
+ if (ret == 1) {
+ if (!quiet)
+ BIO_printf(bio_err, "%s FAILED\n", verify ? "VERIFY" : "INSTALL");
+ ERR_print_errors(bio_err);
+ }
+
+cleanup:
+ OPENSSL_free(module_path);
+ BIO_free(fout);
+ BIO_free(mem_bio);
+ BIO_free(module_bio);
+ sk_OPENSSL_STRING_free(opts);
+ EVP_MAC_free(mac);
+ EVP_MAC_CTX_free(ctx2);
+ EVP_MAC_CTX_free(ctx);
+ OPENSSL_free(read_buffer);
+ free_config_and_unload(conf);
+ return ret;
+}
+
+static int self_test_events(const OSSL_PARAM params[], void *arg)
+{
+ const OSSL_PARAM *p = NULL;
+ const char *phase = NULL, *type = NULL, *desc = NULL;
+ int ret = 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_PHASE);
+ if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
+ goto err;
+ phase = (const char *)p->data;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_DESC);
+ if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
+ goto err;
+ desc = (const char *)p->data;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_TYPE);
+ if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
+ goto err;
+ type = (const char *)p->data;
+
+ if (self_test_log) {
+ if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0)
+ BIO_printf(bio_err, "%s : (%s) : ", desc, type);
+ else if (strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0
+ || strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0)
+ BIO_printf(bio_err, "%s\n", phase);
+ }
+ /*
+ * The self test code will internally corrupt the KAT test result if an
+ * error is returned during the corrupt phase.
+ */
+ if (strcmp(phase, OSSL_SELF_TEST_PHASE_CORRUPT) == 0
+ && (self_test_corrupt_desc != NULL
+ || self_test_corrupt_type != NULL)) {
+ if (self_test_corrupt_desc != NULL
+ && strcmp(self_test_corrupt_desc, desc) != 0)
+ goto end;
+ if (self_test_corrupt_type != NULL
+ && strcmp(self_test_corrupt_type, type) != 0)
+ goto end;
+ BIO_printf(bio_err, "%s ", phase);
+ goto err;
+ }
+end:
+ ret = 1;
+err:
+ return ret;
+}
diff --git a/apps/gendsa.c b/apps/gendsa.c
index ec57c92a9492..27feb793fed2 100644
--- a/apps/gendsa.c
+++ b/apps/gendsa.c
@@ -1,13 +1,14 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/opensslconf.h>
+
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
@@ -22,22 +23,30 @@
#include <openssl/pem.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_OUT, OPT_PASSOUT, OPT_ENGINE, OPT_CIPHER,
- OPT_R_ENUM
+ OPT_COMMON,
+ OPT_OUT, OPT_PASSOUT, OPT_ENGINE, OPT_CIPHER, OPT_VERBOSE,
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS gendsa_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [args] dsaparam-file\n"},
- {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] dsaparam-file\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Output"),
{"out", OPT_OUT, '>', "Output the key to the specified file"},
{"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
OPT_R_OPTIONS,
+ OPT_PROV_OPTIONS,
{"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"},
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
+ {"verbose", OPT_VERBOSE, '-', "Verbose output"},
+
+ OPT_PARAMETERS(),
+ {"dsaparam-file", 0, 0, "File containing DSA parameters"},
{NULL}
};
@@ -45,13 +54,13 @@ int gendsa_main(int argc, char **argv)
{
ENGINE *e = NULL;
BIO *out = NULL, *in = NULL;
- DSA *dsa = NULL;
- const EVP_CIPHER *enc = NULL;
- char *dsaparams = NULL;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ EVP_CIPHER *enc = NULL;
+ char *dsaparams = NULL, *ciphername = NULL;
char *outfile = NULL, *passoutarg = NULL, *passout = NULL, *prog;
OPTION_CHOICE o;
- int ret = 1, private = 0;
- const BIGNUM *p = NULL;
+ int ret = 1, private = 0, verbose = 0, nbits;
prog = opt_init(argc, argv, gendsa_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -78,55 +87,71 @@ int gendsa_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
- case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &enc))
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
goto end;
break;
+ case OPT_CIPHER:
+ ciphername = opt_unknown();
+ break;
+ case OPT_VERBOSE:
+ verbose = 1;
+ break;
}
}
+
+ /* One argument, the params file. */
argc = opt_num_rest();
argv = opt_rest();
- private = 1;
-
if (argc != 1)
goto opthelp;
- dsaparams = *argv;
+ dsaparams = argv[0];
- if (!app_passwd(NULL, passoutarg, NULL, &passout)) {
- BIO_printf(bio_err, "Error getting password\n");
+ if (!app_RAND_load())
goto end;
- }
- in = bio_open_default(dsaparams, 'r', FORMAT_PEM);
- if (in == NULL)
- goto end2;
+ if (ciphername != NULL) {
+ if (!opt_cipher(ciphername, &enc))
+ goto end;
+ }
+ private = 1;
- if ((dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL)) == NULL) {
- BIO_printf(bio_err, "unable to load DSA parameter file\n");
+ if (!app_passwd(NULL, passoutarg, NULL, &passout)) {
+ BIO_printf(bio_err, "Error getting password\n");
goto end;
}
- BIO_free(in);
- in = NULL;
+
+ pkey = load_keyparams(dsaparams, FORMAT_UNDEF, 1, "DSA", "DSA parameters");
out = bio_open_owner(outfile, FORMAT_PEM, private);
if (out == NULL)
goto end2;
- DSA_get0_pqg(dsa, &p, NULL, NULL);
-
- if (BN_num_bits(p) > OPENSSL_DSA_MAX_MODULUS_BITS)
+ nbits = EVP_PKEY_get_bits(pkey);
+ if (nbits > OPENSSL_DSA_MAX_MODULUS_BITS)
BIO_printf(bio_err,
"Warning: It is not recommended to use more than %d bit for DSA keys.\n"
" Your key size is %d! Larger key size may behave not as expected.\n",
- OPENSSL_DSA_MAX_MODULUS_BITS, BN_num_bits(p));
+ OPENSSL_DSA_MAX_MODULUS_BITS, EVP_PKEY_get_bits(pkey));
- BIO_printf(bio_err, "Generating DSA key, %d bits\n", BN_num_bits(p));
- if (!DSA_generate_key(dsa))
+ ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), pkey, app_get0_propq());
+ if (ctx == NULL) {
+ BIO_printf(bio_err, "unable to create PKEY context\n");
goto end;
+ }
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ if (EVP_PKEY_keygen_init(ctx) <= 0) {
+ BIO_printf(bio_err, "unable to set up for key generation\n");
+ goto end;
+ }
+ pkey = app_keygen(ctx, "DSA", nbits, verbose);
assert(private);
- if (!PEM_write_bio_DSAPrivateKey(out, dsa, enc, NULL, 0, NULL, passout))
+ if (!PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, passout)) {
+ BIO_printf(bio_err, "unable to output generated key\n");
goto end;
+ }
ret = 0;
end:
if (ret != 0)
@@ -134,7 +159,9 @@ int gendsa_main(int argc, char **argv)
end2:
BIO_free(in);
BIO_free_all(out);
- DSA_free(dsa);
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_CIPHER_free(enc);
release_engine(e);
OPENSSL_free(passout);
return ret;
diff --git a/apps/genpkey.c b/apps/genpkey.c
index 3fe87e853c57..d00754eeaca0 100644
--- a/apps/genpkey.c
+++ b/apps/genpkey.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -14,34 +14,44 @@
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/evp.h>
-#ifndef OPENSSL_NO_ENGINE
-# include <openssl/engine.h>
-#endif
-static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e);
+static int quiet;
+
+static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e,
+ OSSL_LIB_CTX *libctx, const char *propq);
static int genpkey_cb(EVP_PKEY_CTX *ctx);
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_ENGINE, OPT_OUTFORM, OPT_OUT, OPT_PASS, OPT_PARAMFILE,
- OPT_ALGORITHM, OPT_PKEYOPT, OPT_GENPARAM, OPT_TEXT, OPT_CIPHER
+ OPT_ALGORITHM, OPT_PKEYOPT, OPT_GENPARAM, OPT_TEXT, OPT_CIPHER,
+ OPT_QUIET, OPT_CONFIG,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS genpkey_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"out", OPT_OUT, '>', "Output file"},
- {"outform", OPT_OUTFORM, 'F', "output format (DER or PEM)"},
- {"pass", OPT_PASS, 's', "Output file pass phrase source"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
{"paramfile", OPT_PARAMFILE, '<', "Parameters file"},
{"algorithm", OPT_ALGORITHM, 's', "The public key algorithm"},
+ {"quiet", OPT_QUIET, '-', "Do not output status while generating keys"},
{"pkeyopt", OPT_PKEYOPT, 's',
"Set the public key algorithm option as opt:value"},
+ OPT_CONFIG_OPTION,
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'F', "output format (DER or PEM)"},
+ {"pass", OPT_PASS, 's', "Output file pass phrase source"},
{"genparam", OPT_GENPARAM, '-', "Generate parameters, not key"},
{"text", OPT_TEXT, '-', "Print the in text"},
{"", OPT_CIPHER, '-', "Cipher to use to encrypt the key"},
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
+
+ OPT_PROV_OPTIONS,
+
/* This is deliberately last. */
{OPT_HELP_STR, 1, 1,
"Order of options may be important! See the documentation.\n"},
@@ -50,17 +60,24 @@ const OPTIONS genpkey_options[] = {
int genpkey_main(int argc, char **argv)
{
+ CONF *conf = NULL;
BIO *in = NULL, *out = NULL;
ENGINE *e = NULL;
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
- char *outfile = NULL, *passarg = NULL, *pass = NULL, *prog;
- const EVP_CIPHER *cipher = NULL;
+ char *outfile = NULL, *passarg = NULL, *pass = NULL, *prog, *p;
+ const char *ciphername = NULL, *paramfile = NULL, *algname = NULL;
+ EVP_CIPHER *cipher = NULL;
OPTION_CHOICE o;
int outformat = FORMAT_PEM, text = 0, ret = 1, rv, do_param = 0;
- int private = 0;
+ int private = 0, i;
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
+ STACK_OF(OPENSSL_STRING) *keyopt = NULL;
prog = opt_init(argc, argv, genpkey_options);
+ keyopt = sk_OPENSSL_STRING_new_null();
+ if (keyopt == NULL)
+ goto end;
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_EOF:
@@ -88,56 +105,70 @@ int genpkey_main(int argc, char **argv)
case OPT_PARAMFILE:
if (do_param == 1)
goto opthelp;
- if (!init_keygen_file(&ctx, opt_arg(), e))
- goto end;
+ paramfile = opt_arg();
break;
case OPT_ALGORITHM:
- if (!init_gen_str(&ctx, opt_arg(), e, do_param))
- goto end;
+ algname = opt_arg();
break;
case OPT_PKEYOPT:
- if (ctx == NULL) {
- BIO_printf(bio_err, "%s: No keytype specified.\n", prog);
- goto opthelp;
- }
- if (pkey_ctrl_string(ctx, opt_arg()) <= 0) {
- BIO_printf(bio_err,
- "%s: Error setting %s parameter:\n",
- prog, opt_arg());
- ERR_print_errors(bio_err);
+ if (!sk_OPENSSL_STRING_push(keyopt, opt_arg()))
goto end;
- }
+ break;
+ case OPT_QUIET:
+ quiet = 1;
break;
case OPT_GENPARAM:
- if (ctx != NULL)
- goto opthelp;
do_param = 1;
break;
case OPT_TEXT:
text = 1;
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &cipher)
- || do_param == 1)
- goto opthelp;
- if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE ||
- EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE ||
- EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE ||
- EVP_CIPHER_mode(cipher) == EVP_CIPH_OCB_MODE) {
- BIO_printf(bio_err, "%s: cipher mode not supported\n", prog);
+ ciphername = opt_unknown();
+ break;
+ case OPT_CONFIG:
+ conf = app_load_config_modules(opt_arg());
+ if (conf == NULL)
goto end;
- }
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
- private = do_param ? 0 : 1;
-
+ /* Fetch cipher, etc. */
+ if (paramfile != NULL) {
+ if (!init_keygen_file(&ctx, paramfile, e, libctx, app_get0_propq()))
+ goto end;
+ }
+ if (algname != NULL) {
+ if (!init_gen_str(&ctx, algname, e, do_param, libctx, app_get0_propq()))
+ goto end;
+ }
if (ctx == NULL)
goto opthelp;
+ for (i = 0; i < sk_OPENSSL_STRING_num(keyopt); i++) {
+ p = sk_OPENSSL_STRING_value(keyopt, i);
+ if (pkey_ctrl_string(ctx, p) <= 0) {
+ BIO_printf(bio_err, "%s: Error setting %s parameter:\n", prog, p);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ if (ciphername != NULL)
+ if (!opt_cipher(ciphername, &cipher) || do_param == 1)
+ goto opthelp;
+
+ private = do_param ? 0 : 1;
+
if (!app_passwd(passarg, NULL, &pass, NULL)) {
BIO_puts(bio_err, "Error getting password\n");
goto end;
@@ -150,19 +181,8 @@ int genpkey_main(int argc, char **argv)
EVP_PKEY_CTX_set_cb(ctx, genpkey_cb);
EVP_PKEY_CTX_set_app_data(ctx, bio_err);
- if (do_param) {
- if (EVP_PKEY_paramgen(ctx, &pkey) <= 0) {
- BIO_puts(bio_err, "Error generating parameters\n");
- ERR_print_errors(bio_err);
- goto end;
- }
- } else {
- if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
- BIO_puts(bio_err, "Error generating key\n");
- ERR_print_errors(bio_err);
- goto end;
- }
- }
+ pkey = do_param ? app_paramgen(ctx, algname)
+ : app_keygen(ctx, algname, 0, 0 /* not verbose */);
if (do_param) {
rv = PEM_write_bio_Parameters(out, pkey);
@@ -181,7 +201,6 @@ int genpkey_main(int argc, char **argv)
if (rv <= 0) {
BIO_puts(bio_err, "Error writing key\n");
- ERR_print_errors(bio_err);
ret = 1;
}
@@ -193,22 +212,27 @@ int genpkey_main(int argc, char **argv)
if (rv <= 0) {
BIO_puts(bio_err, "Error printing key\n");
- ERR_print_errors(bio_err);
ret = 1;
}
}
end:
+ sk_OPENSSL_STRING_free(keyopt);
+ if (ret != 0)
+ ERR_print_errors(bio_err);
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
+ EVP_CIPHER_free(cipher);
BIO_free_all(out);
BIO_free(in);
release_engine(e);
OPENSSL_free(pass);
+ NCONF_free(conf);
return ret;
}
-static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e)
+static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
BIO *pbio;
EVP_PKEY *pkey = NULL;
@@ -219,20 +243,23 @@ static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e)
}
pbio = BIO_new_file(file, "r");
- if (!pbio) {
+ if (pbio == NULL) {
BIO_printf(bio_err, "Can't open parameter file %s\n", file);
return 0;
}
- pkey = PEM_read_bio_Parameters(pbio, NULL);
+ pkey = PEM_read_bio_Parameters_ex(pbio, NULL, libctx, propq);
BIO_free(pbio);
- if (!pkey) {
+ if (pkey == NULL) {
BIO_printf(bio_err, "Error reading parameter file %s\n", file);
return 0;
}
- ctx = EVP_PKEY_CTX_new(pkey, e);
+ if (e != NULL)
+ ctx = EVP_PKEY_CTX_new(pkey, e);
+ else
+ ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
if (ctx == NULL)
goto err;
if (EVP_PKEY_keygen_init(ctx) <= 0)
@@ -251,11 +278,10 @@ static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e)
}
int init_gen_str(EVP_PKEY_CTX **pctx,
- const char *algname, ENGINE *e, int do_param)
+ const char *algname, ENGINE *e, int do_param,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
EVP_PKEY_CTX *ctx = NULL;
- const EVP_PKEY_ASN1_METHOD *ameth;
- ENGINE *tmpeng = NULL;
int pkey_id;
if (*pctx) {
@@ -263,27 +289,13 @@ int init_gen_str(EVP_PKEY_CTX **pctx,
return 0;
}
- ameth = EVP_PKEY_asn1_find_str(&tmpeng, algname, -1);
-
-#ifndef OPENSSL_NO_ENGINE
- if (!ameth && e)
- ameth = ENGINE_get_pkey_asn1_meth_str(e, algname, -1);
-#endif
-
- if (!ameth) {
- BIO_printf(bio_err, "Algorithm %s not found\n", algname);
- return 0;
- }
-
- ERR_clear_error();
+ pkey_id = get_legacy_pkey_id(libctx, algname, e);
+ if (pkey_id != NID_undef)
+ ctx = EVP_PKEY_CTX_new_id(pkey_id, e);
+ else
+ ctx = EVP_PKEY_CTX_new_from_name(libctx, algname, propq);
- EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
-#ifndef OPENSSL_NO_ENGINE
- ENGINE_finish(tmpeng);
-#endif
- ctx = EVP_PKEY_CTX_new_id(pkey_id, e);
-
- if (!ctx)
+ if (ctx == NULL)
goto err;
if (do_param) {
if (EVP_PKEY_paramgen_init(ctx) <= 0)
@@ -308,16 +320,22 @@ static int genpkey_cb(EVP_PKEY_CTX *ctx)
{
char c = '*';
BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
- int p;
- p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
- if (p == 0)
+
+ if (quiet)
+ return 1;
+
+ switch (EVP_PKEY_CTX_get_keygen_info(ctx, 0)) {
+ case 0:
c = '.';
- if (p == 1)
+ break;
+ case 1:
c = '+';
- if (p == 2)
- c = '*';
- if (p == 3)
+ break;
+ case 3:
c = '\n';
+ break;
+ }
+
BIO_write(b, &c, 1);
(void)BIO_flush(b);
return 1;
diff --git a/apps/genrsa.c b/apps/genrsa.c
index e34a2f7ab9e8..4436b7fa1745 100644
--- a/apps/genrsa.c
+++ b/apps/genrsa.c
@@ -1,13 +1,14 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/opensslconf.h>
+
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
@@ -26,52 +27,72 @@
#define DEFBITS 2048
#define DEFPRIMES 2
-static int genrsa_cb(int p, int n, BN_GENCB *cb);
+static int verbose = 0;
+
+static int genrsa_cb(EVP_PKEY_CTX *ctx);
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_3, OPT_F4, OPT_ENGINE,
- OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES,
- OPT_R_ENUM
+ OPT_COMMON,
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ OPT_3,
+#endif
+ OPT_F4, OPT_ENGINE,
+ OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES, OPT_VERBOSE,
+ OPT_R_ENUM, OPT_PROV_ENUM, OPT_TRADITIONAL
} OPTION_CHOICE;
const OPTIONS genrsa_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] numbits\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"3", OPT_3, '-', "Use 3 for the E value"},
- {"F4", OPT_F4, '-', "Use F4 (0x10001) for the E value"},
- {"f4", OPT_F4, '-', "Use F4 (0x10001) for the E value"},
- {"out", OPT_OUT, '>', "Output the key to specified file"},
- OPT_R_OPTIONS,
- {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
- {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"},
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
+
+ OPT_SECTION("Input"),
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ {"3", OPT_3, '-', "(deprecated) Use 3 for the E value"},
+#endif
+ {"F4", OPT_F4, '-', "Use the Fermat number F4 (0x10001) for the E value"},
+ {"f4", OPT_F4, '-', "Use the Fermat number F4 (0x10001) for the E value"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output the key to specified file"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
{"primes", OPT_PRIMES, 'p', "Specify number of primes"},
+ {"verbose", OPT_VERBOSE, '-', "Verbose output"},
+ {"traditional", OPT_TRADITIONAL, '-',
+ "Use traditional format for private keys"},
+ {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"},
+
+ OPT_R_OPTIONS,
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"numbits", 0, 0, "Size of key in bits"},
{NULL}
};
int genrsa_main(int argc, char **argv)
{
BN_GENCB *cb = BN_GENCB_new();
- PW_CB_DATA cb_data;
ENGINE *eng = NULL;
BIGNUM *bn = BN_new();
BIO *out = NULL;
- const BIGNUM *e;
- RSA *rsa = NULL;
- const EVP_CIPHER *enc = NULL;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ EVP_CIPHER *enc = NULL;
int ret = 1, num = DEFBITS, private = 0, primes = DEFPRIMES;
unsigned long f4 = RSA_F4;
char *outfile = NULL, *passoutarg = NULL, *passout = NULL;
- char *prog, *hexe, *dece;
+ char *prog, *hexe, *dece, *ciphername = NULL;
OPTION_CHOICE o;
+ int traditional = 0;
if (bn == NULL || cb == NULL)
goto end;
- BN_GENCB_set(cb, genrsa_cb, bio_err);
-
prog = opt_init(argc, argv, genrsa_options);
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
@@ -84,9 +105,11 @@ opthelp:
ret = 0;
opt_help(genrsa_options);
goto end;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
case OPT_3:
- f4 = 3;
+ f4 = RSA_3;
break;
+#endif
case OPT_F4:
f4 = RSA_F4;
break;
@@ -100,19 +123,29 @@ opthelp:
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_PASSOUT:
passoutarg = opt_arg();
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &enc))
- goto end;
+ ciphername = opt_unknown();
break;
case OPT_PRIMES:
- if (!opt_int(opt_arg(), &primes))
- goto end;
+ primes = opt_int_arg();
+ break;
+ case OPT_VERBOSE:
+ verbose = 1;
+ break;
+ case OPT_TRADITIONAL:
+ traditional = 1;
break;
}
}
+
+ /* One optional argument, the bitsize. */
argc = opt_num_rest();
argv = opt_rest();
@@ -129,7 +162,14 @@ opthelp:
goto opthelp;
}
+ if (!app_RAND_load())
+ goto end;
+
private = 1;
+ if (ciphername != NULL) {
+ if (!opt_cipher(ciphername, &enc))
+ goto end;
+ }
if (!app_passwd(NULL, passoutarg, NULL, &passout)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
@@ -139,37 +179,65 @@ opthelp:
if (out == NULL)
goto end;
- BIO_printf(bio_err, "Generating RSA private key, %d bit long modulus (%d primes)\n",
- num, primes);
- rsa = eng ? RSA_new_method(eng) : RSA_new();
- if (rsa == NULL)
+ if (!init_gen_str(&ctx, "RSA", eng, 0, app_get0_libctx(),
+ app_get0_propq()))
goto end;
- if (!BN_set_word(bn, f4)
- || !RSA_generate_multi_prime_key(rsa, num, primes, bn, cb))
- goto end;
+ EVP_PKEY_CTX_set_cb(ctx, genrsa_cb);
+ EVP_PKEY_CTX_set_app_data(ctx, bio_err);
- RSA_get0_key(rsa, NULL, &e, NULL);
- hexe = BN_bn2hex(e);
- dece = BN_bn2dec(e);
- if (hexe && dece) {
- BIO_printf(bio_err, "e is %s (0x%s)\n", dece, hexe);
+ if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, num) <= 0) {
+ BIO_printf(bio_err, "Error setting RSA length\n");
+ goto end;
+ }
+ if (!BN_set_word(bn, f4)) {
+ BIO_printf(bio_err, "Error allocating RSA public exponent\n");
+ goto end;
+ }
+ if (EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, bn) <= 0) {
+ BIO_printf(bio_err, "Error setting RSA public exponent\n");
+ goto end;
}
- OPENSSL_free(hexe);
- OPENSSL_free(dece);
- cb_data.password = passout;
- cb_data.prompt_info = outfile;
- assert(private);
- if (!PEM_write_bio_RSAPrivateKey(out, rsa, enc, NULL, 0,
- (pem_password_cb *)password_callback,
- &cb_data))
+ if (EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, primes) <= 0) {
+ BIO_printf(bio_err, "Error setting number of primes\n");
goto end;
+ }
+ pkey = app_keygen(ctx, "RSA", num, verbose);
+
+ if (verbose) {
+ BIGNUM *e = NULL;
+
+ /* Every RSA key has an 'e' */
+ EVP_PKEY_get_bn_param(pkey, "e", &e);
+ if (e == NULL) {
+ BIO_printf(bio_err, "Error cannot access RSA e\n");
+ goto end;
+ }
+ hexe = BN_bn2hex(e);
+ dece = BN_bn2dec(e);
+ if (hexe && dece) {
+ BIO_printf(bio_err, "e is %s (0x%s)\n", dece, hexe);
+ }
+ OPENSSL_free(hexe);
+ OPENSSL_free(dece);
+ BN_free(e);
+ }
+ if (traditional) {
+ if (!PEM_write_bio_PrivateKey_traditional(out, pkey, enc, NULL, 0,
+ NULL, passout))
+ goto end;
+ } else {
+ if (!PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, passout))
+ goto end;
+ }
ret = 0;
end:
BN_free(bn);
BN_GENCB_free(cb);
- RSA_free(rsa);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+ EVP_CIPHER_free(enc);
BIO_free_all(out);
release_engine(eng);
OPENSSL_free(passout);
@@ -178,9 +246,14 @@ opthelp:
return ret;
}
-static int genrsa_cb(int p, int n, BN_GENCB *cb)
+static int genrsa_cb(EVP_PKEY_CTX *ctx)
{
char c = '*';
+ BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
+ int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
+
+ if (!verbose)
+ return 1;
if (p == 0)
c = '.';
@@ -190,7 +263,7 @@ static int genrsa_cb(int p, int n, BN_GENCB *cb)
c = '*';
if (p == 3)
c = '\n';
- BIO_write(BN_GENCB_get_arg(cb), &c, 1);
- (void)BIO_flush(BN_GENCB_get_arg(cb));
+ BIO_write(b, &c, 1);
+ (void)BIO_flush(b);
return 1;
}
diff --git a/apps/include/__DECC_INCLUDE_EPILOGUE.H b/apps/include/__DECC_INCLUDE_EPILOGUE.H
new file mode 100644
index 000000000000..2ab493330675
--- /dev/null
+++ b/apps/include/__DECC_INCLUDE_EPILOGUE.H
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This file is only used by HP C/C++ on VMS, and is included automatically
+ * after each header file from this directory
+ */
+
+/*
+ * The C++ compiler doesn't understand these pragmas, even though it
+ * understands the corresponding command line qualifier.
+ */
+#ifndef __cplusplus
+/* restore state. Must correspond to the save in __decc_include_prologue.h */
+# pragma names restore
+#endif
diff --git a/apps/include/__DECC_INCLUDE_PROLOGUE.H b/apps/include/__DECC_INCLUDE_PROLOGUE.H
new file mode 100644
index 000000000000..8e95fa975488
--- /dev/null
+++ b/apps/include/__DECC_INCLUDE_PROLOGUE.H
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This file is only used by HP C/C++ on VMS, and is included automatically
+ * after each header file from this directory
+ */
+
+/*
+ * The C++ compiler doesn't understand these pragmas, even though it
+ * understands the corresponding command line qualifier.
+ */
+#ifndef __cplusplus
+/* save state */
+# pragma names save
+/* have the compiler shorten symbols larger than 31 chars to 23 chars
+ * followed by a 8 hex char CRC
+ */
+# pragma names as_is,shortened
+#endif
diff --git a/apps/include/app_libctx.h b/apps/include/app_libctx.h
new file mode 100644
index 000000000000..17c0afc713d2
--- /dev/null
+++ b/apps/include/app_libctx.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_APPS_LIBCTX_H
+# define OSSL_APPS_LIBCTX_H
+
+# include <openssl/types.h>
+
+OSSL_LIB_CTX *app_create_libctx(void);
+OSSL_LIB_CTX *app_get0_libctx(void);
+int app_set_propq(const char *arg);
+const char *app_get0_propq(void);
+
+#endif
diff --git a/apps/include/app_params.h b/apps/include/app_params.h
new file mode 100644
index 000000000000..79f8f58b3122
--- /dev/null
+++ b/apps/include/app_params.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core.h>
+
+int print_param_types(const char *thing, const OSSL_PARAM *pdefs, int indent);
+void print_param_value(const OSSL_PARAM *p, int indent);
+
diff --git a/apps/include/apps.h b/apps/include/apps.h
new file mode 100644
index 000000000000..baacd0025d68
--- /dev/null
+++ b/apps/include/apps.h
@@ -0,0 +1,348 @@
+/*
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_APPS_H
+# define OSSL_APPS_H
+
+# include "e_os.h" /* struct timeval for DTLS */
+# include "internal/nelem.h"
+# include "internal/sockets.h" /* for openssl_fdset() */
+# include "internal/cryptlib.h" /* ossl_assert() */
+# include <assert.h>
+
+# include <stdarg.h>
+# include <sys/types.h>
+# ifndef OPENSSL_NO_POSIX_IO
+# include <sys/stat.h>
+# include <fcntl.h>
+# endif
+
+# include <openssl/e_os2.h>
+# include <openssl/types.h>
+# include <openssl/bio.h>
+# include <openssl/x509.h>
+# include <openssl/conf.h>
+# include <openssl/txt_db.h>
+# include <openssl/engine.h>
+# include <openssl/ocsp.h>
+# include <openssl/http.h>
+# include <signal.h>
+# include "apps_ui.h"
+# include "opt.h"
+# include "fmt.h"
+# include "platform.h"
+# include "engine_loader.h"
+# include "app_libctx.h"
+
+/*
+ * quick macro when you need to pass an unsigned char instead of a char.
+ * this is true for some implementations of the is*() functions, for
+ * example.
+ */
+# define _UC(c) ((unsigned char)(c))
+
+void app_RAND_load_conf(CONF *c, const char *section);
+int app_RAND_write(void);
+int app_RAND_load(void);
+
+extern char *default_config_file; /* may be "" */
+extern BIO *bio_in;
+extern BIO *bio_out;
+extern BIO *bio_err;
+extern const unsigned char tls13_aes128gcmsha256_id[];
+extern const unsigned char tls13_aes256gcmsha384_id[];
+extern BIO_ADDR *ourpeer;
+
+BIO *dup_bio_in(int format);
+BIO *dup_bio_out(int format);
+BIO *dup_bio_err(int format);
+BIO *bio_open_owner(const char *filename, int format, int private);
+BIO *bio_open_default(const char *filename, char mode, int format);
+BIO *bio_open_default_quiet(const char *filename, char mode, int format);
+CONF *app_load_config_bio(BIO *in, const char *filename);
+#define app_load_config(filename) app_load_config_internal(filename, 0)
+#define app_load_config_quiet(filename) app_load_config_internal(filename, 1)
+CONF *app_load_config_internal(const char *filename, int quiet);
+CONF *app_load_config_verbose(const char *filename, int verbose);
+int app_load_modules(const CONF *config);
+CONF *app_load_config_modules(const char *configfile);
+void unbuffer(FILE *fp);
+void wait_for_async(SSL *s);
+# if defined(OPENSSL_SYS_MSDOS)
+int has_stdin_waiting(void);
+# endif
+
+void corrupt_signature(const ASN1_STRING *signature);
+int set_cert_times(X509 *x, const char *startdate, const char *enddate,
+ int days);
+int set_crl_lastupdate(X509_CRL *crl, const char *lastupdate);
+int set_crl_nextupdate(X509_CRL *crl, const char *nextupdate,
+ long days, long hours, long secs);
+
+typedef struct args_st {
+ int size;
+ int argc;
+ char **argv;
+} ARGS;
+
+/* We need both wrap and the "real" function because libcrypto uses both. */
+int wrap_password_callback(char *buf, int bufsiz, int verify, void *cb_data);
+
+int chopup_args(ARGS *arg, char *buf);
+void dump_cert_text(BIO *out, X509 *x);
+void print_name(BIO *out, const char *title, const X509_NAME *nm);
+void print_bignum_var(BIO *, const BIGNUM *, const char*,
+ int, unsigned char *);
+void print_array(BIO *, const char *, int, const unsigned char *);
+int set_nameopt(const char *arg);
+unsigned long get_nameopt(void);
+int set_dateopt(unsigned long *dateopt, const char *arg);
+int set_cert_ex(unsigned long *flags, const char *arg);
+int set_name_ex(unsigned long *flags, const char *arg);
+int set_ext_copy(int *copy_type, const char *arg);
+int copy_extensions(X509 *x, X509_REQ *req, int copy_type);
+char *get_passwd(const char *pass, const char *desc);
+int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2);
+int add_oid_section(CONF *conf);
+X509_REQ *load_csr(const char *file, int format, const char *desc);
+X509 *load_cert_pass(const char *uri, int format, int maybe_stdin,
+ const char *pass, const char *desc);
+#define load_cert(uri, format, desc) load_cert_pass(uri, format, 1, NULL, desc)
+X509_CRL *load_crl(const char *uri, int format, int maybe_stdin,
+ const char *desc);
+void cleanse(char *str);
+void clear_free(char *str);
+EVP_PKEY *load_key(const char *uri, int format, int maybe_stdin,
+ const char *pass, ENGINE *e, const char *desc);
+EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin,
+ const char *pass, ENGINE *e, const char *desc);
+EVP_PKEY *load_keyparams(const char *uri, int format, int maybe_stdin,
+ const char *keytype, const char *desc);
+EVP_PKEY *load_keyparams_suppress(const char *uri, int format, int maybe_stdin,
+ const char *keytype, const char *desc,
+ int suppress_decode_errors);
+char *next_item(char *opt); /* in list separated by comma and/or space */
+int load_cert_certs(const char *uri,
+ X509 **pcert, STACK_OF(X509) **pcerts,
+ int exclude_http, const char *pass, const char *desc,
+ X509_VERIFY_PARAM *vpm);
+STACK_OF(X509) *load_certs_multifile(char *files, const char *pass,
+ const char *desc, X509_VERIFY_PARAM *vpm);
+X509_STORE *load_certstore(char *input, const char *pass, const char *desc,
+ X509_VERIFY_PARAM *vpm);
+int load_certs(const char *uri, int maybe_stdin, STACK_OF(X509) **certs,
+ const char *pass, const char *desc);
+int load_crls(const char *uri, STACK_OF(X509_CRL) **crls,
+ const char *pass, const char *desc);
+int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
+ const char *pass, const char *desc,
+ EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
+ EVP_PKEY **pparams,
+ X509 **pcert, STACK_OF(X509) **pcerts,
+ X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls);
+int load_key_cert_crl(const char *uri, int format, int maybe_stdin,
+ const char *pass, const char *desc,
+ EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
+ X509 **pcert, X509_CRL **pcrl);
+X509_STORE *setup_verify(const char *CAfile, int noCAfile,
+ const char *CApath, int noCApath,
+ const char *CAstore, int noCAstore);
+__owur int ctx_set_verify_locations(SSL_CTX *ctx,
+ const char *CAfile, int noCAfile,
+ const char *CApath, int noCApath,
+ const char *CAstore, int noCAstore);
+
+# ifndef OPENSSL_NO_CT
+
+/*
+ * Sets the file to load the Certificate Transparency log list from.
+ * If path is NULL, loads from the default file path.
+ * Returns 1 on success, 0 otherwise.
+ */
+__owur int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path);
+
+# endif
+
+ENGINE *setup_engine_methods(const char *id, unsigned int methods, int debug);
+# define setup_engine(e, debug) setup_engine_methods(e, (unsigned int)-1, debug)
+void release_engine(ENGINE *e);
+int init_engine(ENGINE *e);
+int finish_engine(ENGINE *e);
+char *make_engine_uri(ENGINE *e, const char *key_id, const char *desc);
+
+int get_legacy_pkey_id(OSSL_LIB_CTX *libctx, const char *algname, ENGINE *e);
+const EVP_MD *get_digest_from_engine(const char *name);
+const EVP_CIPHER *get_cipher_from_engine(const char *name);
+
+# ifndef OPENSSL_NO_OCSP
+OCSP_RESPONSE *process_responder(OCSP_REQUEST *req, const char *host,
+ const char *port, const char *path,
+ const char *proxy, const char *no_proxy,
+ int use_ssl, STACK_OF(CONF_VALUE) *headers,
+ int req_timeout);
+# endif
+
+/* Functions defined in ca.c and also used in ocsp.c */
+int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold,
+ ASN1_GENERALIZEDTIME **pinvtm, const char *str);
+
+# define DB_type 0
+# define DB_exp_date 1
+# define DB_rev_date 2
+# define DB_serial 3 /* index - unique */
+# define DB_file 4
+# define DB_name 5 /* index - unique when active and not
+ * disabled */
+# define DB_NUMBER 6
+
+# define DB_TYPE_REV 'R' /* Revoked */
+# define DB_TYPE_EXP 'E' /* Expired */
+# define DB_TYPE_VAL 'V' /* Valid ; inserted with: ca ... -valid */
+# define DB_TYPE_SUSP 'S' /* Suspended */
+
+typedef struct db_attr_st {
+ int unique_subject;
+} DB_ATTR;
+typedef struct ca_db_st {
+ DB_ATTR attributes;
+ TXT_DB *db;
+ char *dbfname;
+# ifndef OPENSSL_NO_POSIX_IO
+ struct stat dbst;
+# endif
+} CA_DB;
+
+void app_bail_out(char *fmt, ...);
+void *app_malloc(size_t sz, const char *what);
+
+/* load_serial, save_serial, and rotate_serial are also used for CRL numbers */
+BIGNUM *load_serial(const char *serialfile, int *exists, int create,
+ ASN1_INTEGER **retai);
+int save_serial(const char *serialfile, const char *suffix,
+ const BIGNUM *serial, ASN1_INTEGER **retai);
+int rotate_serial(const char *serialfile, const char *new_suffix,
+ const char *old_suffix);
+int rand_serial(BIGNUM *b, ASN1_INTEGER *ai);
+
+CA_DB *load_index(const char *dbfile, DB_ATTR *dbattr);
+int index_index(CA_DB *db);
+int save_index(const char *dbfile, const char *suffix, CA_DB *db);
+int rotate_index(const char *dbfile, const char *new_suffix,
+ const char *old_suffix);
+void free_index(CA_DB *db);
+# define index_name_cmp_noconst(a, b) \
+ index_name_cmp((const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, a), \
+ (const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, b))
+int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b);
+int parse_yesno(const char *str, int def);
+
+X509_NAME *parse_name(const char *str, int chtype, int multirdn,
+ const char *desc);
+void policies_print(X509_STORE_CTX *ctx);
+int bio_to_mem(unsigned char **out, int maxlen, BIO *in);
+int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value);
+int x509_ctrl_string(X509 *x, const char *value);
+int x509_req_ctrl_string(X509_REQ *x, const char *value);
+int init_gen_str(EVP_PKEY_CTX **pctx,
+ const char *algname, ENGINE *e, int do_param,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int do_X509_sign(X509 *x, EVP_PKEY *pkey, const char *md,
+ STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx);
+int do_X509_verify(X509 *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts);
+int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const char *md,
+ STACK_OF(OPENSSL_STRING) *sigopts);
+int do_X509_REQ_verify(X509_REQ *x, EVP_PKEY *pkey,
+ STACK_OF(OPENSSL_STRING) *vfyopts);
+int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const char *md,
+ STACK_OF(OPENSSL_STRING) *sigopts);
+
+extern char *psk_key;
+
+
+unsigned char *next_protos_parse(size_t *outlen, const char *in);
+
+void print_cert_checks(BIO *bio, X509 *x,
+ const char *checkhost,
+ const char *checkemail, const char *checkip);
+
+void store_setup_crl_download(X509_STORE *st);
+
+typedef struct app_http_tls_info_st {
+ const char *server;
+ const char *port;
+ int use_proxy;
+ long timeout;
+ SSL_CTX *ssl_ctx;
+} APP_HTTP_TLS_INFO;
+BIO *app_http_tls_cb(BIO *hbio, /* APP_HTTP_TLS_INFO */ void *arg,
+ int connect, int detail);
+void APP_HTTP_TLS_INFO_free(APP_HTTP_TLS_INFO *info);
+# ifndef OPENSSL_NO_SOCK
+ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy,
+ const char *no_proxy, SSL_CTX *ssl_ctx,
+ const STACK_OF(CONF_VALUE) *headers,
+ long timeout, const char *expected_content_type,
+ const ASN1_ITEM *it);
+ASN1_VALUE *app_http_post_asn1(const char *host, const char *port,
+ const char *path, const char *proxy,
+ const char *no_proxy, SSL_CTX *ctx,
+ const STACK_OF(CONF_VALUE) *headers,
+ const char *content_type,
+ ASN1_VALUE *req, const ASN1_ITEM *req_it,
+ const char *expected_content_type,
+ long timeout, const ASN1_ITEM *rsp_it);
+# endif
+
+# define EXT_COPY_NONE 0
+# define EXT_COPY_ADD 1
+# define EXT_COPY_ALL 2
+
+# define NETSCAPE_CERT_HDR "certificate"
+
+# define APP_PASS_LEN 1024
+
+/*
+ * IETF RFC 5280 says serial number must be <= 20 bytes. Use 159 bits
+ * so that the first bit will never be one, so that the DER encoding
+ * rules won't force a leading octet.
+ */
+# define SERIAL_RAND_BITS 159
+
+int app_isdir(const char *);
+int app_access(const char *, int flag);
+int fileno_stdin(void);
+int fileno_stdout(void);
+int raw_read_stdin(void *, int);
+int raw_write_stdout(const void *, int);
+
+# define TM_START 0
+# define TM_STOP 1
+double app_tminterval(int stop, int usertime);
+
+void make_uppercase(char *string);
+
+typedef struct verify_options_st {
+ int depth;
+ int quiet;
+ int error;
+ int return_error;
+} VERIFY_CB_ARGS;
+
+extern VERIFY_CB_ARGS verify_args;
+
+OSSL_PARAM *app_params_new_from_opts(STACK_OF(OPENSSL_STRING) *opts,
+ const OSSL_PARAM *paramdefs);
+void app_params_free(OSSL_PARAM *params);
+int app_provider_load(OSSL_LIB_CTX *libctx, const char *provider_name);
+void app_providers_cleanup(void);
+
+EVP_PKEY *app_keygen(EVP_PKEY_CTX *ctx, const char *alg, int bits, int verbose);
+EVP_PKEY *app_paramgen(EVP_PKEY_CTX *ctx, const char *alg);
+
+#endif
diff --git a/apps/include/apps_ui.h b/apps/include/apps_ui.h
new file mode 100644
index 000000000000..6875b7c372d9
--- /dev/null
+++ b/apps/include/apps_ui.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_APPS_UI_H
+# define OSSL_APPS_UI_H
+
+
+# define PW_MIN_LENGTH 4
+typedef struct pw_cb_data {
+ const void *password;
+ const char *prompt_info;
+} PW_CB_DATA;
+
+int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data);
+
+int setup_ui_method(void);
+void destroy_ui_method(void);
+int set_base_ui_method(const UI_METHOD *ui_method);
+const UI_METHOD *get_ui_method(void);
+
+extern BIO *bio_err;
+
+#endif
diff --git a/apps/include/cmp_mock_srv.h b/apps/include/cmp_mock_srv.h
new file mode 100644
index 000000000000..6beba1473590
--- /dev/null
+++ b/apps/include/cmp_mock_srv.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Siemens AG 2018-2020
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_APPS_CMP_MOCK_SRV_H
+# define OSSL_APPS_CMP_MOCK_SRV_H
+
+# include <openssl/opensslconf.h>
+# ifndef OPENSSL_NO_CMP
+
+# include <openssl/cmp.h>
+
+OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx,
+ const char *propq);
+void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx);
+
+int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert);
+int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
+ STACK_OF(X509) *chain);
+int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx,
+ STACK_OF(X509) *caPubs);
+int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status,
+ int fail_info, const char *text);
+int ossl_cmp_mock_srv_set_send_error(OSSL_CMP_SRV_CTX *srv_ctx, int val);
+int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX *srv_ctx, int count);
+int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec);
+
+# endif /* !defined(OPENSSL_NO_CMP) */
+#endif /* !defined(OSSL_APPS_CMP_MOCK_SRV_H) */
diff --git a/apps/include/ec_common.h b/apps/include/ec_common.h
new file mode 100644
index 000000000000..f5711657a299
--- /dev/null
+++ b/apps/include/ec_common.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_NO_EC
+static const char *point_format_options[] = {
+ "uncompressed",
+ "compressed",
+ "hybrid",
+ NULL
+};
+
+static const char *asn1_encoding_options[] = {
+ "named_curve",
+ "explicit",
+ NULL
+};
+#endif
diff --git a/apps/include/engine_loader.h b/apps/include/engine_loader.h
new file mode 100644
index 000000000000..fa80fc96567c
--- /dev/null
+++ b/apps/include/engine_loader.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+#ifndef HEADER_ENGINE_LOADER_H
+# define HEADER_ENGINE_LOADER_H
+
+# include <openssl/store.h>
+
+/* this is a private URI scheme */
+# define ENGINE_SCHEME "org.openssl.engine"
+# define ENGINE_SCHEME_COLON (ENGINE_SCHEME ":")
+
+int setup_engine_loader(void);
+void destroy_engine_loader(void);
+
+#endif
diff --git a/apps/include/fmt.h b/apps/include/fmt.h
new file mode 100644
index 000000000000..98dfed7dc0a2
--- /dev/null
+++ b/apps/include/fmt.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Options are shared by apps (see apps.h) and the test system
+ * (see test/testutil.h').
+ * In order to remove the dependency between apps and options, the following
+ * shared fields have been moved into this file.
+ */
+
+#ifndef OSSL_APPS_FMT_H
+#define OSSL_APPS_FMT_H
+
+/*
+ * On some platforms, it's important to distinguish between text and binary
+ * files. On some, there might even be specific file formats for different
+ * contents. The FORMAT_xxx macros are meant to express an intent with the
+ * file being read or created.
+ */
+# define B_FORMAT_TEXT 0x8000
+# define FORMAT_UNDEF 0
+# define FORMAT_TEXT (1 | B_FORMAT_TEXT) /* Generic text */
+# define FORMAT_BINARY 2 /* Generic binary */
+# define FORMAT_BASE64 (3 | B_FORMAT_TEXT) /* Base64 */
+# define FORMAT_ASN1 4 /* ASN.1/DER */
+# define FORMAT_PEM (5 | B_FORMAT_TEXT)
+# define FORMAT_PKCS12 6
+# define FORMAT_SMIME (7 | B_FORMAT_TEXT)
+# define FORMAT_ENGINE 8 /* Not really a file format */
+# define FORMAT_PEMRSA (9 | B_FORMAT_TEXT) /* PEM RSAPublicKey format */
+# define FORMAT_ASN1RSA 10 /* DER RSAPublicKey format */
+# define FORMAT_MSBLOB 11 /* MS Key blob format */
+# define FORMAT_PVK 12 /* MS PVK file format */
+# define FORMAT_HTTP 13 /* Download using HTTP */
+# define FORMAT_NSS 14 /* NSS keylog format */
+
+int FMT_istext(int format);
+
+#endif /* OSSL_APPS_FMT_H_ */
diff --git a/apps/include/function.h b/apps/include/function.h
new file mode 100644
index 000000000000..14e8dd388670
--- /dev/null
+++ b/apps/include/function.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_APPS_FUNCTION_H
+# define OSSL_APPS_FUNCTION_H
+
+# include <openssl/lhash.h>
+# include "opt.h"
+
+#define DEPRECATED_NO_ALTERNATIVE "unknown"
+
+typedef enum FUNC_TYPE {
+ FT_none, FT_general, FT_md, FT_cipher, FT_pkey,
+ FT_md_alg, FT_cipher_alg
+} FUNC_TYPE;
+
+typedef struct function_st {
+ FUNC_TYPE type;
+ const char *name;
+ int (*func)(int argc, char *argv[]);
+ const OPTIONS *help;
+ const char *deprecated_alternative;
+ const char *deprecated_version;
+} FUNCTION;
+
+DEFINE_LHASH_OF(FUNCTION);
+
+/* Structure to hold the number of columns to be displayed and the
+ * field width used to display them.
+ */
+typedef struct {
+ int columns;
+ int width;
+} DISPLAY_COLUMNS;
+
+void calculate_columns(FUNCTION *functions, DISPLAY_COLUMNS *dc);
+
+#endif
diff --git a/apps/include/http_server.h b/apps/include/http_server.h
new file mode 100644
index 000000000000..8c339660a65e
--- /dev/null
+++ b/apps/include/http_server.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_HTTP_SERVER_H
+# define OSSL_HTTP_SERVER_H
+
+# include "apps.h"
+
+# ifndef HAVE_FORK
+# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS)
+# define HAVE_FORK 0
+# else
+# define HAVE_FORK 1
+# endif
+# endif
+
+# if HAVE_FORK
+# undef NO_FORK
+# else
+# define NO_FORK
+# endif
+
+# if !defined(NO_FORK) && !defined(OPENSSL_NO_SOCK) \
+ && !defined(OPENSSL_NO_POSIX_IO)
+# define HTTP_DAEMON
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <syslog.h>
+# include <signal.h>
+# define MAXERRLEN 1000 /* limit error text sent to syslog to 1000 bytes */
+# else
+# undef LOG_DEBUG
+# undef LOG_INFO
+# undef LOG_WARNING
+# undef LOG_ERR
+# define LOG_DEBUG 7
+# define LOG_INFO 6
+# define LOG_WARNING 4
+# define LOG_ERR 3
+# endif
+
+/*-
+ * Log a message to syslog if multi-threaded HTTP_DAEMON, else to bio_err
+ * prog: the name of the current app
+ * level: the severity of the message, e.g., LOG_ERR
+ * fmt: message with potential extra parameters like with printf()
+ * returns nothing
+ */
+void log_message(const char *prog, int level, const char *fmt, ...);
+
+# ifndef OPENSSL_NO_SOCK
+/*-
+ * Initialize an HTTP server by setting up its listening BIO
+ * prog: the name of the current app
+ * port: the port to listen on
+ * returns a BIO for accepting requests, NULL on error
+ */
+BIO *http_server_init_bio(const char *prog, const char *port);
+
+/*-
+ * Accept an ASN.1-formatted HTTP request
+ * it: the expected request ASN.1 type
+ * preq: pointer to variable where to place the parsed request
+ * ppath: pointer to variable where to place the request path, or NULL
+ * pcbio: pointer to variable where to place the BIO for sending the response to
+ * acbio: the listening bio (typically as returned by http_server_init_bio())
+ * found_keep_alive: for returning flag if client requests persistent connection
+ * prog: the name of the current app, for diagnostics only
+ * port: the local port listening to, for diagnostics only
+ * accept_get: whether to accept GET requests (in addition to POST requests)
+ * timeout: connection timeout (in seconds), or 0 for none/infinite
+ * returns 0 in case caller should retry, then *preq == *ppath == *pcbio == NULL
+ * returns -1 on fatal error; also then holds *preq == *ppath == *pcbio == NULL
+ * returns 1 otherwise. In this case it is guaranteed that *pcbio != NULL while
+ * *ppath == NULL and *preq == NULL if and only if the request is invalid,
+ * On return value 1 the caller is responsible for sending an HTTP response,
+ * using http_server_send_asn1_resp() or http_server_send_status().
+ * The caller must free any non-NULL *preq, *ppath, and *pcbio pointers.
+ */
+int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
+ char **ppath, BIO **pcbio, BIO *acbio,
+ int *found_keep_alive,
+ const char *prog, const char *port,
+ int accept_get, int timeout);
+
+/*-
+ * Send an ASN.1-formatted HTTP response
+ * cbio: destination BIO (typically as returned by http_server_get_asn1_req())
+ * note: cbio should not do an encoding that changes the output length
+ * keep_alive: grant persistent connnection
+ * content_type: string identifying the type of the response
+ * it: the response ASN.1 type
+ * resp: the response to send
+ * returns 1 on success, 0 on failure
+ */
+int http_server_send_asn1_resp(BIO *cbio, int keep_alive,
+ const char *content_type,
+ const ASN1_ITEM *it, const ASN1_VALUE *resp);
+
+/*-
+ * Send a trivial HTTP response, typically to report an error or OK
+ * cbio: destination BIO (typically as returned by http_server_get_asn1_req())
+ * status: the status code to send
+ * reason: the corresponding human-readable string
+ * returns 1 on success, 0 on failure
+ */
+int http_server_send_status(BIO *cbio, int status, const char *reason);
+
+# endif
+
+# ifdef HTTP_DAEMON
+extern int multi;
+extern int acfd;
+
+void socket_timeout(int signum);
+void spawn_loop(const char *prog);
+# endif
+
+#endif
diff --git a/apps/include/names.h b/apps/include/names.h
new file mode 100644
index 000000000000..f4d6f6a9a333
--- /dev/null
+++ b/apps/include/names.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/safestack.h>
+
+/* Standard comparing function for names */
+int name_cmp(const char * const *a, const char * const *b);
+/* collect_names is meant to be used with EVP_{type}_doall_names */
+void collect_names(const char *name, void *vdata);
+/* Sorts and prints a stack of names to |out| */
+void print_names(BIO *out, STACK_OF(OPENSSL_CSTRING) *names);
diff --git a/apps/include/opt.h b/apps/include/opt.h
new file mode 100644
index 000000000000..4f83a0ed53c9
--- /dev/null
+++ b/apps/include/opt.h
@@ -0,0 +1,400 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+#ifndef OSSL_APPS_OPT_H
+#define OSSL_APPS_OPT_H
+
+#include <sys/types.h>
+#include <openssl/e_os2.h>
+#include <openssl/types.h>
+#include <stdarg.h>
+
+#define OPT_COMMON OPT_ERR = -1, OPT_EOF = 0, OPT_HELP
+
+/*
+ * Common verification options.
+ */
+# define OPT_V_ENUM \
+ OPT_V__FIRST=2000, \
+ OPT_V_POLICY, OPT_V_PURPOSE, OPT_V_VERIFY_NAME, OPT_V_VERIFY_DEPTH, \
+ OPT_V_ATTIME, OPT_V_VERIFY_HOSTNAME, OPT_V_VERIFY_EMAIL, \
+ OPT_V_VERIFY_IP, OPT_V_IGNORE_CRITICAL, OPT_V_ISSUER_CHECKS, \
+ OPT_V_CRL_CHECK, OPT_V_CRL_CHECK_ALL, OPT_V_POLICY_CHECK, \
+ OPT_V_EXPLICIT_POLICY, OPT_V_INHIBIT_ANY, OPT_V_INHIBIT_MAP, \
+ OPT_V_X509_STRICT, OPT_V_EXTENDED_CRL, OPT_V_USE_DELTAS, \
+ OPT_V_POLICY_PRINT, OPT_V_CHECK_SS_SIG, OPT_V_TRUSTED_FIRST, \
+ OPT_V_SUITEB_128_ONLY, OPT_V_SUITEB_128, OPT_V_SUITEB_192, \
+ OPT_V_PARTIAL_CHAIN, OPT_V_NO_ALT_CHAINS, OPT_V_NO_CHECK_TIME, \
+ OPT_V_VERIFY_AUTH_LEVEL, OPT_V_ALLOW_PROXY_CERTS, \
+ OPT_V__LAST
+
+# define OPT_V_OPTIONS \
+ OPT_SECTION("Validation"), \
+ { "policy", OPT_V_POLICY, 's', "adds policy to the acceptable policy set"}, \
+ { "purpose", OPT_V_PURPOSE, 's', \
+ "certificate chain purpose"}, \
+ { "verify_name", OPT_V_VERIFY_NAME, 's', "verification policy name"}, \
+ { "verify_depth", OPT_V_VERIFY_DEPTH, 'n', \
+ "chain depth limit" }, \
+ { "auth_level", OPT_V_VERIFY_AUTH_LEVEL, 'n', \
+ "chain authentication security level" }, \
+ { "attime", OPT_V_ATTIME, 'M', "verification epoch time" }, \
+ { "verify_hostname", OPT_V_VERIFY_HOSTNAME, 's', \
+ "expected peer hostname" }, \
+ { "verify_email", OPT_V_VERIFY_EMAIL, 's', \
+ "expected peer email" }, \
+ { "verify_ip", OPT_V_VERIFY_IP, 's', \
+ "expected peer IP address" }, \
+ { "ignore_critical", OPT_V_IGNORE_CRITICAL, '-', \
+ "permit unhandled critical extensions"}, \
+ { "issuer_checks", OPT_V_ISSUER_CHECKS, '-', "(deprecated)"}, \
+ { "crl_check", OPT_V_CRL_CHECK, '-', "check leaf certificate revocation" }, \
+ { "crl_check_all", OPT_V_CRL_CHECK_ALL, '-', "check full chain revocation" }, \
+ { "policy_check", OPT_V_POLICY_CHECK, '-', "perform rfc5280 policy checks"}, \
+ { "explicit_policy", OPT_V_EXPLICIT_POLICY, '-', \
+ "set policy variable require-explicit-policy"}, \
+ { "inhibit_any", OPT_V_INHIBIT_ANY, '-', \
+ "set policy variable inhibit-any-policy"}, \
+ { "inhibit_map", OPT_V_INHIBIT_MAP, '-', \
+ "set policy variable inhibit-policy-mapping"}, \
+ { "x509_strict", OPT_V_X509_STRICT, '-', \
+ "disable certificate compatibility work-arounds"}, \
+ { "extended_crl", OPT_V_EXTENDED_CRL, '-', \
+ "enable extended CRL features"}, \
+ { "use_deltas", OPT_V_USE_DELTAS, '-', \
+ "use delta CRLs"}, \
+ { "policy_print", OPT_V_POLICY_PRINT, '-', \
+ "print policy processing diagnostics"}, \
+ { "check_ss_sig", OPT_V_CHECK_SS_SIG, '-', \
+ "check root CA self-signatures"}, \
+ { "trusted_first", OPT_V_TRUSTED_FIRST, '-', \
+ "search trust store first (default)" }, \
+ { "suiteB_128_only", OPT_V_SUITEB_128_ONLY, '-', "Suite B 128-bit-only mode"}, \
+ { "suiteB_128", OPT_V_SUITEB_128, '-', \
+ "Suite B 128-bit mode allowing 192-bit algorithms"}, \
+ { "suiteB_192", OPT_V_SUITEB_192, '-', "Suite B 192-bit-only mode" }, \
+ { "partial_chain", OPT_V_PARTIAL_CHAIN, '-', \
+ "accept chains anchored by intermediate trust-store CAs"}, \
+ { "no_alt_chains", OPT_V_NO_ALT_CHAINS, '-', "(deprecated)" }, \
+ { "no_check_time", OPT_V_NO_CHECK_TIME, '-', "ignore certificate validity time" }, \
+ { "allow_proxy_certs", OPT_V_ALLOW_PROXY_CERTS, '-', "allow the use of proxy certificates" }
+
+# define OPT_V_CASES \
+ OPT_V__FIRST: case OPT_V__LAST: break; \
+ case OPT_V_POLICY: \
+ case OPT_V_PURPOSE: \
+ case OPT_V_VERIFY_NAME: \
+ case OPT_V_VERIFY_DEPTH: \
+ case OPT_V_VERIFY_AUTH_LEVEL: \
+ case OPT_V_ATTIME: \
+ case OPT_V_VERIFY_HOSTNAME: \
+ case OPT_V_VERIFY_EMAIL: \
+ case OPT_V_VERIFY_IP: \
+ case OPT_V_IGNORE_CRITICAL: \
+ case OPT_V_ISSUER_CHECKS: \
+ case OPT_V_CRL_CHECK: \
+ case OPT_V_CRL_CHECK_ALL: \
+ case OPT_V_POLICY_CHECK: \
+ case OPT_V_EXPLICIT_POLICY: \
+ case OPT_V_INHIBIT_ANY: \
+ case OPT_V_INHIBIT_MAP: \
+ case OPT_V_X509_STRICT: \
+ case OPT_V_EXTENDED_CRL: \
+ case OPT_V_USE_DELTAS: \
+ case OPT_V_POLICY_PRINT: \
+ case OPT_V_CHECK_SS_SIG: \
+ case OPT_V_TRUSTED_FIRST: \
+ case OPT_V_SUITEB_128_ONLY: \
+ case OPT_V_SUITEB_128: \
+ case OPT_V_SUITEB_192: \
+ case OPT_V_PARTIAL_CHAIN: \
+ case OPT_V_NO_ALT_CHAINS: \
+ case OPT_V_NO_CHECK_TIME: \
+ case OPT_V_ALLOW_PROXY_CERTS
+
+/*
+ * Common "extended validation" options.
+ */
+# define OPT_X_ENUM \
+ OPT_X__FIRST=1000, \
+ OPT_X_KEY, OPT_X_CERT, OPT_X_CHAIN, OPT_X_CHAIN_BUILD, \
+ OPT_X_CERTFORM, OPT_X_KEYFORM, \
+ OPT_X__LAST
+
+# define OPT_X_OPTIONS \
+ OPT_SECTION("Extended certificate"), \
+ { "xkey", OPT_X_KEY, '<', "key for Extended certificates"}, \
+ { "xcert", OPT_X_CERT, '<', "cert for Extended certificates"}, \
+ { "xchain", OPT_X_CHAIN, '<', "chain for Extended certificates"}, \
+ { "xchain_build", OPT_X_CHAIN_BUILD, '-', \
+ "build certificate chain for the extended certificates"}, \
+ { "xcertform", OPT_X_CERTFORM, 'F', \
+ "format of Extended certificate (PEM/DER/P12); has no effect" }, \
+ { "xkeyform", OPT_X_KEYFORM, 'F', \
+ "format of Extended certificate's key (DER/PEM/P12); has no effect"}
+
+# define OPT_X_CASES \
+ OPT_X__FIRST: case OPT_X__LAST: break; \
+ case OPT_X_KEY: \
+ case OPT_X_CERT: \
+ case OPT_X_CHAIN: \
+ case OPT_X_CHAIN_BUILD: \
+ case OPT_X_CERTFORM: \
+ case OPT_X_KEYFORM
+
+/*
+ * Common SSL options.
+ * Any changes here must be coordinated with ../ssl/ssl_conf.c
+ */
+# define OPT_S_ENUM \
+ OPT_S__FIRST=3000, \
+ OPT_S_NOSSL3, OPT_S_NOTLS1, OPT_S_NOTLS1_1, OPT_S_NOTLS1_2, \
+ OPT_S_NOTLS1_3, OPT_S_BUGS, OPT_S_NO_COMP, OPT_S_NOTICKET, \
+ OPT_S_SERVERPREF, OPT_S_LEGACYRENEG, OPT_S_CLIENTRENEG, \
+ OPT_S_LEGACYCONN, \
+ OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, OPT_S_ALLOW_NO_DHE_KEX, \
+ OPT_S_PRIORITIZE_CHACHA, \
+ OPT_S_STRICT, OPT_S_SIGALGS, OPT_S_CLIENTSIGALGS, OPT_S_GROUPS, \
+ OPT_S_CURVES, OPT_S_NAMEDCURVE, OPT_S_CIPHER, OPT_S_CIPHERSUITES, \
+ OPT_S_RECORD_PADDING, OPT_S_DEBUGBROKE, OPT_S_COMP, \
+ OPT_S_MINPROTO, OPT_S_MAXPROTO, \
+ OPT_S_NO_RENEGOTIATION, OPT_S_NO_MIDDLEBOX, OPT_S_NO_ETM, OPT_S__LAST
+
+# define OPT_S_OPTIONS \
+ OPT_SECTION("TLS/SSL"), \
+ {"no_ssl3", OPT_S_NOSSL3, '-',"Just disable SSLv3" }, \
+ {"no_tls1", OPT_S_NOTLS1, '-', "Just disable TLSv1"}, \
+ {"no_tls1_1", OPT_S_NOTLS1_1, '-', "Just disable TLSv1.1" }, \
+ {"no_tls1_2", OPT_S_NOTLS1_2, '-', "Just disable TLSv1.2"}, \
+ {"no_tls1_3", OPT_S_NOTLS1_3, '-', "Just disable TLSv1.3"}, \
+ {"bugs", OPT_S_BUGS, '-', "Turn on SSL bug compatibility"}, \
+ {"no_comp", OPT_S_NO_COMP, '-', "Disable SSL/TLS compression (default)" }, \
+ {"comp", OPT_S_COMP, '-', "Use SSL/TLS-level compression" }, \
+ {"no_ticket", OPT_S_NOTICKET, '-', \
+ "Disable use of TLS session tickets"}, \
+ {"serverpref", OPT_S_SERVERPREF, '-', "Use server's cipher preferences"}, \
+ {"legacy_renegotiation", OPT_S_LEGACYRENEG, '-', \
+ "Enable use of legacy renegotiation (dangerous)"}, \
+ {"client_renegotiation", OPT_S_CLIENTRENEG, '-', \
+ "Allow client-initiated renegotiation" }, \
+ {"no_renegotiation", OPT_S_NO_RENEGOTIATION, '-', \
+ "Disable all renegotiation."}, \
+ {"legacy_server_connect", OPT_S_LEGACYCONN, '-', \
+ "Allow initial connection to servers that don't support RI"}, \
+ {"no_resumption_on_reneg", OPT_S_ONRESUMP, '-', \
+ "Disallow session resumption on renegotiation"}, \
+ {"no_legacy_server_connect", OPT_S_NOLEGACYCONN, '-', \
+ "Disallow initial connection to servers that don't support RI"}, \
+ {"allow_no_dhe_kex", OPT_S_ALLOW_NO_DHE_KEX, '-', \
+ "In TLSv1.3 allow non-(ec)dhe based key exchange on resumption"}, \
+ {"prioritize_chacha", OPT_S_PRIORITIZE_CHACHA, '-', \
+ "Prioritize ChaCha ciphers when preferred by clients"}, \
+ {"strict", OPT_S_STRICT, '-', \
+ "Enforce strict certificate checks as per TLS standard"}, \
+ {"sigalgs", OPT_S_SIGALGS, 's', \
+ "Signature algorithms to support (colon-separated list)" }, \
+ {"client_sigalgs", OPT_S_CLIENTSIGALGS, 's', \
+ "Signature algorithms to support for client certificate" \
+ " authentication (colon-separated list)" }, \
+ {"groups", OPT_S_GROUPS, 's', \
+ "Groups to advertise (colon-separated list)" }, \
+ {"curves", OPT_S_CURVES, 's', \
+ "Groups to advertise (colon-separated list)" }, \
+ {"named_curve", OPT_S_NAMEDCURVE, 's', \
+ "Elliptic curve used for ECDHE (server-side only)" }, \
+ {"cipher", OPT_S_CIPHER, 's', "Specify TLSv1.2 and below cipher list to be used"}, \
+ {"ciphersuites", OPT_S_CIPHERSUITES, 's', "Specify TLSv1.3 ciphersuites to be used"}, \
+ {"min_protocol", OPT_S_MINPROTO, 's', "Specify the minimum protocol version to be used"}, \
+ {"max_protocol", OPT_S_MAXPROTO, 's', "Specify the maximum protocol version to be used"}, \
+ {"record_padding", OPT_S_RECORD_PADDING, 's', \
+ "Block size to pad TLS 1.3 records to."}, \
+ {"debug_broken_protocol", OPT_S_DEBUGBROKE, '-', \
+ "Perform all sorts of protocol violations for testing purposes"}, \
+ {"no_middlebox", OPT_S_NO_MIDDLEBOX, '-', \
+ "Disable TLSv1.3 middlebox compat mode" }, \
+ {"no_etm", OPT_S_NO_ETM, '-', \
+ "Disable Encrypt-then-Mac extension"}
+
+# define OPT_S_CASES \
+ OPT_S__FIRST: case OPT_S__LAST: break; \
+ case OPT_S_NOSSL3: \
+ case OPT_S_NOTLS1: \
+ case OPT_S_NOTLS1_1: \
+ case OPT_S_NOTLS1_2: \
+ case OPT_S_NOTLS1_3: \
+ case OPT_S_BUGS: \
+ case OPT_S_NO_COMP: \
+ case OPT_S_COMP: \
+ case OPT_S_NOTICKET: \
+ case OPT_S_SERVERPREF: \
+ case OPT_S_LEGACYRENEG: \
+ case OPT_S_CLIENTRENEG: \
+ case OPT_S_LEGACYCONN: \
+ case OPT_S_ONRESUMP: \
+ case OPT_S_NOLEGACYCONN: \
+ case OPT_S_ALLOW_NO_DHE_KEX: \
+ case OPT_S_PRIORITIZE_CHACHA: \
+ case OPT_S_STRICT: \
+ case OPT_S_SIGALGS: \
+ case OPT_S_CLIENTSIGALGS: \
+ case OPT_S_GROUPS: \
+ case OPT_S_CURVES: \
+ case OPT_S_NAMEDCURVE: \
+ case OPT_S_CIPHER: \
+ case OPT_S_CIPHERSUITES: \
+ case OPT_S_RECORD_PADDING: \
+ case OPT_S_NO_RENEGOTIATION: \
+ case OPT_S_MINPROTO: \
+ case OPT_S_MAXPROTO: \
+ case OPT_S_DEBUGBROKE: \
+ case OPT_S_NO_MIDDLEBOX: \
+ case OPT_S_NO_ETM
+
+#define IS_NO_PROT_FLAG(o) \
+ (o == OPT_S_NOSSL3 || o == OPT_S_NOTLS1 || o == OPT_S_NOTLS1_1 \
+ || o == OPT_S_NOTLS1_2 || o == OPT_S_NOTLS1_3)
+
+/*
+ * Random state options.
+ */
+# define OPT_R_ENUM \
+ OPT_R__FIRST=1500, OPT_R_RAND, OPT_R_WRITERAND, OPT_R__LAST
+
+# define OPT_R_OPTIONS \
+ OPT_SECTION("Random state"), \
+ {"rand", OPT_R_RAND, 's', "Load the given file(s) into the random number generator"}, \
+ {"writerand", OPT_R_WRITERAND, '>', "Write random data to the specified file"}
+
+# define OPT_R_CASES \
+ OPT_R__FIRST: case OPT_R__LAST: break; \
+ case OPT_R_RAND: case OPT_R_WRITERAND
+
+/*
+ * Provider options.
+ */
+# define OPT_PROV_ENUM \
+ OPT_PROV__FIRST=1600, \
+ OPT_PROV_PROVIDER, OPT_PROV_PROVIDER_PATH, OPT_PROV_PROPQUERY, \
+ OPT_PROV__LAST
+
+# define OPT_CONFIG_OPTION \
+ { "config", OPT_CONFIG, '<', "Load a configuration file (this may load modules)" }
+
+# define OPT_PROV_OPTIONS \
+ OPT_SECTION("Provider"), \
+ { "provider-path", OPT_PROV_PROVIDER_PATH, 's', "Provider load path (must be before 'provider' argument if required)" }, \
+ { "provider", OPT_PROV_PROVIDER, 's', "Provider to load (can be specified multiple times)" }, \
+ { "propquery", OPT_PROV_PROPQUERY, 's', "Property query used when fetching algorithms" }
+
+# define OPT_PROV_CASES \
+ OPT_PROV__FIRST: case OPT_PROV__LAST: break; \
+ case OPT_PROV_PROVIDER: \
+ case OPT_PROV_PROVIDER_PATH: \
+ case OPT_PROV_PROPQUERY
+
+/*
+ * Option parsing.
+ */
+extern const char OPT_HELP_STR[];
+extern const char OPT_MORE_STR[];
+extern const char OPT_SECTION_STR[];
+extern const char OPT_PARAM_STR[];
+
+typedef struct options_st {
+ const char *name;
+ int retval;
+ /*
+ * value type: - no value (also the value zero), n number, p positive
+ * number, u unsigned, l long, s string, < input file, > output file,
+ * f any format, F der/pem format, E der/pem/engine format identifier.
+ * l, n and u include zero; p does not.
+ */
+ int valtype;
+ const char *helpstr;
+} OPTIONS;
+/* Special retval values: */
+#define OPT_PARAM 0 /* same as OPT_EOF usually defined in apps */
+#define OPT_DUP -2 /* marks duplicate occurrence of option in help output */
+
+/*
+ * A string/int pairing; widely use for option value lookup, hence the
+ * name OPT_PAIR. But that name is misleading in s_cb.c, so we also use
+ * the "generic" name STRINT_PAIR.
+ */
+typedef struct string_int_pair_st {
+ const char *name;
+ int retval;
+} OPT_PAIR, STRINT_PAIR;
+
+/* Flags to pass into opt_format; see FORMAT_xxx, below. */
+# define OPT_FMT_PEMDER (1L << 1)
+# define OPT_FMT_PKCS12 (1L << 2)
+# define OPT_FMT_SMIME (1L << 3)
+# define OPT_FMT_ENGINE (1L << 4)
+# define OPT_FMT_MSBLOB (1L << 5)
+/* (1L << 6) was OPT_FMT_NETSCAPE, but wasn't used */
+# define OPT_FMT_NSS (1L << 7)
+# define OPT_FMT_TEXT (1L << 8)
+# define OPT_FMT_HTTP (1L << 9)
+# define OPT_FMT_PVK (1L << 10)
+# define OPT_FMT_PDE (OPT_FMT_PEMDER | OPT_FMT_ENGINE)
+# define OPT_FMT_PDS (OPT_FMT_PEMDER | OPT_FMT_SMIME)
+# define OPT_FMT_ANY ( \
+ OPT_FMT_PEMDER | OPT_FMT_PKCS12 | OPT_FMT_SMIME | \
+ OPT_FMT_ENGINE | OPT_FMT_MSBLOB | OPT_FMT_NSS | \
+ OPT_FMT_TEXT | OPT_FMT_HTTP | OPT_FMT_PVK)
+
+/* Divide options into sections when displaying usage */
+#define OPT_SECTION(sec) { OPT_SECTION_STR, 1, '-', sec " options:\n" }
+#define OPT_PARAMETERS() { OPT_PARAM_STR, 1, '-', "Parameters:\n" }
+
+const char *opt_path_end(const char *filename);
+char *opt_init(int ac, char **av, const OPTIONS * o);
+char *opt_progname(const char *argv0);
+char *opt_appname(const char *argv0);
+char *opt_getprog(void);
+void opt_help(const OPTIONS * list);
+
+void opt_begin(void);
+int opt_next(void);
+char *opt_flag(void);
+char *opt_arg(void);
+char *opt_unknown(void);
+int opt_cipher(const char *name, EVP_CIPHER **cipherp);
+int opt_cipher_any(const char *name, EVP_CIPHER **cipherp);
+int opt_cipher_silent(const char *name, EVP_CIPHER **cipherp);
+int opt_md(const char *name, EVP_MD **mdp);
+int opt_md_silent(const char *name, EVP_MD **mdp);
+
+int opt_int(const char *arg, int *result);
+int opt_int_arg(void);
+int opt_long(const char *arg, long *result);
+int opt_ulong(const char *arg, unsigned long *result);
+int opt_intmax(const char *arg, ossl_intmax_t *result);
+int opt_uintmax(const char *arg, ossl_uintmax_t *result);
+
+int opt_isdir(const char *name);
+int opt_format(const char *s, unsigned long flags, int *result);
+void print_format_error(int format, unsigned long flags);
+int opt_printf_stderr(const char *fmt, ...);
+int opt_string(const char *name, const char **options);
+int opt_pair(const char *arg, const OPT_PAIR * pairs, int *result);
+
+int opt_verify(int i, X509_VERIFY_PARAM *vpm);
+int opt_rand(int i);
+int opt_provider(int i);
+int opt_provider_option_given(void);
+
+char **opt_rest(void);
+int opt_num_rest(void);
+
+/* Returns non-zero if legacy paths are still available */
+int opt_legacy_okay(void);
+
+
+#endif /* OSSL_APPS_OPT_H */
diff --git a/apps/include/platform.h b/apps/include/platform.h
new file mode 100644
index 000000000000..491559df3152
--- /dev/null
+++ b/apps/include/platform.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_APPS_PLATFORM_H
+# define OSSL_APPS_PLATFORM_H
+
+# include <openssl/e_os2.h>
+
+# if defined(OPENSSL_SYS_VMS) && defined(__DECC)
+/*
+ * VMS C only for now, implemented in vms_decc_init.c
+ * If other C compilers forget to terminate argv with NULL, this function
+ * can be re-used.
+ */
+char **copy_argv(int *argc, char *argv[]);
+# endif
+
+# ifdef _WIN32
+/*
+ * Win32-specific argv initialization that splits OS-supplied UNICODE
+ * command line string to array of UTF8-encoded strings.
+ */
+void win32_utf8argv(int *argc, char **argv[]);
+# endif
+
+#endif
diff --git a/apps/include/s_apps.h b/apps/include/s_apps.h
new file mode 100644
index 000000000000..d610df40be3f
--- /dev/null
+++ b/apps/include/s_apps.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+
+#include <openssl/ssl.h>
+#include <openssl/srp.h>
+
+#define PORT "4433"
+#define PROTOCOL "tcp"
+
+typedef int (*do_server_cb)(int s, int stype, int prot, unsigned char *context);
+int report_server_accept(BIO *out, int asock, int with_address, int with_pid);
+int do_server(int *accept_sock, const char *host, const char *port,
+ int family, int type, int protocol, do_server_cb cb,
+ unsigned char *context, int naccept, BIO *bio_s_out);
+
+int verify_callback(int ok, X509_STORE_CTX *ctx);
+
+int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file);
+int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
+ STACK_OF(X509) *chain, int build_chain);
+int ssl_print_sigalgs(BIO *out, SSL *s);
+int ssl_print_point_formats(BIO *out, SSL *s);
+int ssl_print_groups(BIO *out, SSL *s, int noshared);
+int ssl_print_tmp_key(BIO *out, SSL *s);
+int init_client(int *sock, const char *host, const char *port,
+ const char *bindhost, const char *bindport,
+ int family, int type, int protocol);
+int should_retry(int i);
+void do_ssl_shutdown(SSL *ssl);
+
+long bio_dump_callback(BIO *bio, int cmd, const char *argp, size_t len,
+ int argi, long argl, int ret, size_t *processed);
+
+void apps_ssl_info_callback(const SSL *s, int where, int ret);
+void msg_cb(int write_p, int version, int content_type, const void *buf,
+ size_t len, SSL *ssl, void *arg);
+void tlsext_cb(SSL *s, int client_server, int type, const unsigned char *data,
+ int len, void *arg);
+
+int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
+ unsigned int *cookie_len);
+int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
+ unsigned int cookie_len);
+
+#ifdef __VMS /* 31 char symbol name limit */
+# define generate_stateless_cookie_callback generate_stateless_cookie_cb
+# define verify_stateless_cookie_callback verify_stateless_cookie_cb
+#endif
+
+int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie,
+ size_t *cookie_len);
+int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie,
+ size_t cookie_len);
+
+typedef struct ssl_excert_st SSL_EXCERT;
+
+void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc);
+void ssl_excert_free(SSL_EXCERT *exc);
+int args_excert(int option, SSL_EXCERT **pexc);
+int load_excert(SSL_EXCERT **pexc);
+void print_verify_detail(SSL *s, BIO *bio);
+void print_ssl_summary(SSL *s);
+int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str, SSL_CTX *ctx);
+int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls,
+ int crl_download);
+int ssl_load_stores(SSL_CTX *ctx, const char *vfyCApath,
+ const char *vfyCAfile, const char *vfyCAstore,
+ const char *chCApath, const char *chCAfile,
+ const char *chCAstore, STACK_OF(X509_CRL) *crls,
+ int crl_download);
+void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose);
+int set_keylog_file(SSL_CTX *ctx, const char *keylog_file);
+void print_ca_names(BIO *bio, SSL *s);
+
+#ifndef OPENSSL_NO_SRP
+/* The client side SRP context that we pass to all SRP related callbacks */
+typedef struct srp_arg_st {
+ char *srppassin;
+ char *srplogin;
+ int msg; /* copy from c_msg */
+ int debug; /* copy from c_debug */
+ int amp; /* allow more groups */
+ int strength; /* minimal size for N */
+} SRP_ARG;
+
+int set_up_srp_arg(SSL_CTX *ctx, SRP_ARG *srp_arg, int srp_lateuser, int c_msg,
+ int c_debug);
+void set_up_dummy_srp(SSL_CTX *ctx);
+
+/* The server side SRP context that we pass to all SRP related callbacks */
+typedef struct srpsrvparm_st {
+ char *login;
+ SRP_VBASE *vb;
+ SRP_user_pwd *user;
+} srpsrvparm;
+
+int set_up_srp_verifier_file(SSL_CTX *ctx, srpsrvparm *srp_callback_parm,
+ char *srpuserseed, char *srp_verifier_file);
+void lookup_srp_user(srpsrvparm *srp_callback_parm, BIO *bio_s_out);
+#endif /* OPENSSL_NO_SRP */
diff --git a/apps/include/vms_term_sock.h b/apps/include/vms_term_sock.h
new file mode 100644
index 000000000000..eae37b1af931
--- /dev/null
+++ b/apps/include/vms_term_sock.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016 VMS Software, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_APPS_VMS_TERM_SOCK_H
+# define OSSL_APPS_VMS_TERM_SOCK_H
+
+/*
+** Terminal Socket Function Codes
+*/
+# define TERM_SOCK_CREATE 1
+# define TERM_SOCK_DELETE 2
+
+/*
+** Terminal Socket Status Codes
+*/
+# define TERM_SOCK_FAILURE 0
+# define TERM_SOCK_SUCCESS 1
+
+/*
+** Terminal Socket Prototype
+*/
+int TerminalSocket (int FunctionCode, int *ReturnSocket);
+
+#endif
diff --git a/apps/info.c b/apps/info.c
new file mode 100644
index 000000000000..c68603652f21
--- /dev/null
+++ b/apps/info.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include "apps.h"
+#include "progs.h"
+
+typedef enum OPTION_choice {
+ OPT_COMMON,
+ OPT_CONFIGDIR, OPT_ENGINESDIR, OPT_MODULESDIR, OPT_DSOEXT, OPT_DIRNAMESEP,
+ OPT_LISTSEP, OPT_SEEDS, OPT_CPUSETTINGS
+} OPTION_CHOICE;
+
+const OPTIONS info_options[] = {
+
+ OPT_SECTION("General"),
+ {"help", OPT_HELP, '-', "Display this summary"},
+
+ OPT_SECTION("Output"),
+ {"configdir", OPT_CONFIGDIR, '-', "Default configuration file directory"},
+ {"enginesdir", OPT_ENGINESDIR, '-', "Default engine module directory"},
+ {"modulesdir", OPT_MODULESDIR, '-',
+ "Default module directory (other than engine modules)"},
+ {"dsoext", OPT_DSOEXT, '-', "Configured extension for modules"},
+ {"dirnamesep", OPT_DIRNAMESEP, '-', "Directory-filename separator"},
+ {"listsep", OPT_LISTSEP, '-', "List separator character"},
+ {"seeds", OPT_SEEDS, '-', "Seed sources"},
+ {"cpusettings", OPT_CPUSETTINGS, '-', "CPU settings info"},
+ {NULL}
+};
+
+int info_main(int argc, char **argv)
+{
+ int ret = 1, dirty = 0, type = 0;
+ char *prog;
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, info_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ default:
+opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(info_options);
+ ret = 0;
+ goto end;
+ case OPT_CONFIGDIR:
+ type = OPENSSL_INFO_CONFIG_DIR;
+ dirty++;
+ break;
+ case OPT_ENGINESDIR:
+ type = OPENSSL_INFO_ENGINES_DIR;
+ dirty++;
+ break;
+ case OPT_MODULESDIR:
+ type = OPENSSL_INFO_MODULES_DIR;
+ dirty++;
+ break;
+ case OPT_DSOEXT:
+ type = OPENSSL_INFO_DSO_EXTENSION;
+ dirty++;
+ break;
+ case OPT_DIRNAMESEP:
+ type = OPENSSL_INFO_DIR_FILENAME_SEPARATOR;
+ dirty++;
+ break;
+ case OPT_LISTSEP:
+ type = OPENSSL_INFO_LIST_SEPARATOR;
+ dirty++;
+ break;
+ case OPT_SEEDS:
+ type = OPENSSL_INFO_SEED_SOURCE;
+ dirty++;
+ break;
+ case OPT_CPUSETTINGS:
+ type = OPENSSL_INFO_CPU_SETTINGS;
+ dirty++;
+ break;
+ }
+ }
+ if (opt_num_rest() != 0)
+ goto opthelp;
+ if (dirty > 1) {
+ BIO_printf(bio_err, "%s: Only one item allowed\n", prog);
+ goto opthelp;
+ }
+ if (dirty == 0) {
+ BIO_printf(bio_err, "%s: No items chosen\n", prog);
+ goto opthelp;
+ }
+
+ BIO_printf(bio_out, "%s\n", OPENSSL_info(type));
+ ret = 0;
+ end:
+ return ret;
+}
diff --git a/apps/insta.ca.crt b/apps/insta.ca.crt
new file mode 100644
index 000000000000..6aea6d4f9794
--- /dev/null
+++ b/apps/insta.ca.crt
Binary files differ
diff --git a/apps/kdf.c b/apps/kdf.c
new file mode 100644
index 000000000000..89ee1f69c766
--- /dev/null
+++ b/apps/kdf.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+
+#include "apps.h"
+#include "progs.h"
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/params.h>
+
+typedef enum OPTION_choice {
+ OPT_COMMON,
+ OPT_KDFOPT, OPT_BIN, OPT_KEYLEN, OPT_OUT,
+ OPT_CIPHER, OPT_DIGEST, OPT_MAC,
+ OPT_PROV_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS kdf_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] kdf_name\n"},
+
+ OPT_SECTION("General"),
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"kdfopt", OPT_KDFOPT, 's', "KDF algorithm control parameters in n:v form"},
+ {"cipher", OPT_CIPHER, 's', "Cipher"},
+ {"digest", OPT_DIGEST, 's', "Digest"},
+ {"mac", OPT_MAC, 's', "MAC"},
+ {OPT_MORE_STR, 1, '-', "See 'Supported Controls' in the EVP_KDF_ docs\n"},
+ {"keylen", OPT_KEYLEN, 's', "The size of the output derived key"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output to filename rather than stdout"},
+ {"binary", OPT_BIN, '-',
+ "Output in binary format (default is hexadecimal)"},
+
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"kdf_name", 0, 0, "Name of the KDF algorithm"},
+ {NULL}
+};
+
+static char *alloc_kdf_algorithm_name(STACK_OF(OPENSSL_STRING) **optp,
+ const char *name, const char *arg)
+{
+ size_t len = strlen(name) + strlen(arg) + 2;
+ char *res;
+
+ if (*optp == NULL)
+ *optp = sk_OPENSSL_STRING_new_null();
+ if (*optp == NULL)
+ return NULL;
+
+ res = app_malloc(len, "algorithm name");
+ BIO_snprintf(res, len, "%s:%s", name, arg);
+ if (sk_OPENSSL_STRING_push(*optp, res))
+ return res;
+ OPENSSL_free(res);
+ return NULL;
+}
+
+int kdf_main(int argc, char **argv)
+{
+ int ret = 1, out_bin = 0;
+ OPTION_CHOICE o;
+ STACK_OF(OPENSSL_STRING) *opts = NULL;
+ char *prog, *hexout = NULL;
+ const char *outfile = NULL;
+ unsigned char *dkm_bytes = NULL;
+ size_t dkm_len = 0;
+ BIO *out = NULL;
+ EVP_KDF *kdf = NULL;
+ EVP_KDF_CTX *ctx = NULL;
+ char *digest = NULL, *cipher = NULL, *mac = NULL;
+
+ prog = opt_init(argc, argv, kdf_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ default:
+opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto err;
+ case OPT_HELP:
+ opt_help(kdf_options);
+ ret = 0;
+ goto err;
+ case OPT_BIN:
+ out_bin = 1;
+ break;
+ case OPT_KEYLEN:
+ dkm_len = (size_t)atoi(opt_arg());
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_KDFOPT:
+ if (opts == NULL)
+ opts = sk_OPENSSL_STRING_new_null();
+ if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg()))
+ goto opthelp;
+ break;
+ case OPT_CIPHER:
+ OPENSSL_free(cipher);
+ cipher = alloc_kdf_algorithm_name(&opts, "cipher", opt_arg());
+ if (cipher == NULL)
+ goto opthelp;
+ break;
+ case OPT_DIGEST:
+ OPENSSL_free(digest);
+ digest = alloc_kdf_algorithm_name(&opts, "digest", opt_arg());
+ if (digest == NULL)
+ goto opthelp;
+ break;
+ case OPT_MAC:
+ OPENSSL_free(mac);
+ mac = alloc_kdf_algorithm_name(&opts, "mac", opt_arg());
+ if (mac == NULL)
+ goto opthelp;
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto err;
+ break;
+ }
+ }
+
+ /* One argument, the KDF name. */
+ argc = opt_num_rest();
+ argv = opt_rest();
+ if (argc != 1)
+ goto opthelp;
+
+ if ((kdf = EVP_KDF_fetch(app_get0_libctx(), argv[0],
+ app_get0_propq())) == NULL) {
+ BIO_printf(bio_err, "Invalid KDF name %s\n", argv[0]);
+ goto opthelp;
+ }
+
+ ctx = EVP_KDF_CTX_new(kdf);
+ if (ctx == NULL)
+ goto err;
+
+ if (opts != NULL) {
+ int ok = 1;
+ OSSL_PARAM *params =
+ app_params_new_from_opts(opts, EVP_KDF_settable_ctx_params(kdf));
+
+ if (params == NULL)
+ goto err;
+
+ if (!EVP_KDF_CTX_set_params(ctx, params)) {
+ BIO_printf(bio_err, "KDF parameter error\n");
+ ERR_print_errors(bio_err);
+ ok = 0;
+ }
+ app_params_free(params);
+ if (!ok)
+ goto err;
+ }
+
+ out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT);
+ if (out == NULL)
+ goto err;
+
+ if (dkm_len <= 0) {
+ BIO_printf(bio_err, "Invalid derived key length.\n");
+ goto err;
+ }
+ dkm_bytes = app_malloc(dkm_len, "out buffer");
+ if (dkm_bytes == NULL)
+ goto err;
+
+ if (!EVP_KDF_derive(ctx, dkm_bytes, dkm_len, NULL)) {
+ BIO_printf(bio_err, "EVP_KDF_derive failed\n");
+ goto err;
+ }
+
+ if (out_bin) {
+ BIO_write(out, dkm_bytes, dkm_len);
+ } else {
+ hexout = OPENSSL_buf2hexstr(dkm_bytes, dkm_len);
+ if (hexout == NULL) {
+ BIO_printf(bio_err, "Memory allocation failure\n");
+ goto err;
+ }
+ BIO_printf(out, "%s\n\n", hexout);
+ }
+
+ ret = 0;
+err:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
+ OPENSSL_clear_free(dkm_bytes, dkm_len);
+ sk_OPENSSL_STRING_free(opts);
+ EVP_KDF_free(kdf);
+ EVP_KDF_CTX_free(ctx);
+ BIO_free(out);
+ OPENSSL_free(hexout);
+ OPENSSL_free(cipher);
+ OPENSSL_free(digest);
+ OPENSSL_free(mac);
+ return ret;
+}
diff --git a/apps/lib/app_libctx.c b/apps/lib/app_libctx.c
new file mode 100644
index 000000000000..4b9ec40e8527
--- /dev/null
+++ b/apps/lib/app_libctx.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+#include "app_libctx.h"
+#include "apps.h"
+
+static OSSL_LIB_CTX *app_libctx = NULL;
+static const char *app_propq = NULL;
+
+int app_set_propq(const char *arg)
+{
+ app_propq = arg;
+ return 1;
+}
+
+const char *app_get0_propq(void)
+{
+ return app_propq;
+}
+
+OSSL_LIB_CTX *app_get0_libctx(void)
+{
+ return app_libctx;
+}
+
+OSSL_LIB_CTX *app_create_libctx(void)
+{
+ /*
+ * Load the NULL provider into the default library context and create a
+ * library context which will then be used for any OPT_PROV options.
+ */
+ if (app_libctx == NULL) {
+ if (!app_provider_load(NULL, "null")) {
+ opt_printf_stderr( "Failed to create null provider\n");
+ return NULL;
+ }
+ app_libctx = OSSL_LIB_CTX_new();
+ }
+ if (app_libctx == NULL)
+ opt_printf_stderr("Failed to create library context\n");
+ return app_libctx;
+}
+
diff --git a/apps/lib/app_params.c b/apps/lib/app_params.c
new file mode 100644
index 000000000000..95e1298ee926
--- /dev/null
+++ b/apps/lib/app_params.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "apps.h"
+#include "app_params.h"
+
+static int describe_param_type(char *buf, size_t bufsz, const OSSL_PARAM *param)
+{
+ const char *type_mod = "";
+ const char *type = NULL;
+ int show_type_number = 0;
+ int printed_len;
+
+ switch (param->data_type) {
+ case OSSL_PARAM_UNSIGNED_INTEGER:
+ type_mod = "unsigned ";
+ /* FALLTHRU */
+ case OSSL_PARAM_INTEGER:
+ type = "integer";
+ break;
+ case OSSL_PARAM_UTF8_PTR:
+ type_mod = "pointer to a ";
+ /* FALLTHRU */
+ case OSSL_PARAM_UTF8_STRING:
+ type = "UTF8 encoded string";
+ break;
+ case OSSL_PARAM_OCTET_PTR:
+ type_mod = "pointer to an ";
+ /* FALLTHRU */
+ case OSSL_PARAM_OCTET_STRING:
+ type = "octet string";
+ break;
+ default:
+ type = "unknown type";
+ show_type_number = 1;
+ break;
+ }
+
+ printed_len = BIO_snprintf(buf, bufsz, "%s: ", param->key);
+ if (printed_len > 0) {
+ buf += printed_len;
+ bufsz -= printed_len;
+ }
+ printed_len = BIO_snprintf(buf, bufsz, "%s%s", type_mod, type);
+ if (printed_len > 0) {
+ buf += printed_len;
+ bufsz -= printed_len;
+ }
+ if (show_type_number) {
+ printed_len = BIO_snprintf(buf, bufsz, " [%d]", param->data_type);
+ if (printed_len > 0) {
+ buf += printed_len;
+ bufsz -= printed_len;
+ }
+ }
+ if (param->data_size == 0)
+ printed_len = BIO_snprintf(buf, bufsz, " (arbitrary size)");
+ else
+ printed_len = BIO_snprintf(buf, bufsz, " (max %zu bytes large)",
+ param->data_size);
+ if (printed_len > 0) {
+ buf += printed_len;
+ bufsz -= printed_len;
+ }
+ *buf = '\0';
+ return 1;
+}
+
+int print_param_types(const char *thing, const OSSL_PARAM *pdefs, int indent)
+{
+ if (pdefs == NULL) {
+ return 1;
+ } else if (pdefs->key == NULL) {
+ /*
+ * An empty list? This shouldn't happen, but let's just make sure to
+ * say something if there's a badly written provider...
+ */
+ BIO_printf(bio_out, "%*sEmpty list of %s (!!!)\n", indent, "", thing);
+ } else {
+ BIO_printf(bio_out, "%*s%s:\n", indent, "", thing);
+ for (; pdefs->key != NULL; pdefs++) {
+ char buf[200]; /* This should be ample space */
+
+ describe_param_type(buf, sizeof(buf), pdefs);
+ BIO_printf(bio_out, "%*s %s\n", indent, "", buf);
+ }
+ }
+ return 1;
+}
+
+void print_param_value(const OSSL_PARAM *p, int indent)
+{
+ int64_t i;
+ uint64_t u;
+
+ printf("%*s%s: ", indent, "", p->key);
+ switch (p->data_type) {
+ case OSSL_PARAM_UNSIGNED_INTEGER:
+ if (OSSL_PARAM_get_uint64(p, &u))
+ BIO_printf(bio_out, "%llu\n", (unsigned long long int)u);
+ else
+ BIO_printf(bio_out, "error getting value\n");
+ break;
+ case OSSL_PARAM_INTEGER:
+ if (OSSL_PARAM_get_int64(p, &i))
+ BIO_printf(bio_out, "%lld\n", (long long int)i);
+ else
+ BIO_printf(bio_out, "error getting value\n");
+ break;
+ case OSSL_PARAM_UTF8_PTR:
+ BIO_printf(bio_out, "'%s'\n", *(char **)(p->data));
+ break;
+ case OSSL_PARAM_UTF8_STRING:
+ BIO_printf(bio_out, "'%s'\n", (char *)p->data);
+ break;
+ case OSSL_PARAM_OCTET_PTR:
+ case OSSL_PARAM_OCTET_STRING:
+ BIO_printf(bio_out, "<%zu bytes>\n", p->data_size);
+ break;
+ default:
+ BIO_printf(bio_out, "unknown type (%u) of %zu bytes\n",
+ p->data_type, p->data_size);
+ break;
+ }
+}
+
diff --git a/apps/lib/app_provider.c b/apps/lib/app_provider.c
new file mode 100644
index 000000000000..63f78ae07d80
--- /dev/null
+++ b/apps/lib/app_provider.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "apps.h"
+#include <string.h>
+#include <openssl/err.h>
+#include <openssl/provider.h>
+#include <openssl/safestack.h>
+
+/* Non-zero if any of the provider options have been seen */
+static int provider_option_given = 0;
+
+DEFINE_STACK_OF(OSSL_PROVIDER)
+
+/*
+ * See comments in opt_verify for explanation of this.
+ */
+enum prov_range { OPT_PROV_ENUM };
+
+static STACK_OF(OSSL_PROVIDER) *app_providers = NULL;
+
+static void provider_free(OSSL_PROVIDER *prov)
+{
+ OSSL_PROVIDER_unload(prov);
+}
+
+int app_provider_load(OSSL_LIB_CTX *libctx, const char *provider_name)
+{
+ OSSL_PROVIDER *prov;
+
+ prov = OSSL_PROVIDER_load(libctx, provider_name);
+ if (prov == NULL) {
+ opt_printf_stderr("%s: unable to load provider %s\n"
+ "Hint: use -provider-path option or OPENSSL_MODULES environment variable.\n",
+ opt_getprog(), provider_name);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ if (app_providers == NULL)
+ app_providers = sk_OSSL_PROVIDER_new_null();
+ if (app_providers == NULL
+ || !sk_OSSL_PROVIDER_push(app_providers, prov)) {
+ app_providers_cleanup();
+ return 0;
+ }
+ return 1;
+}
+
+void app_providers_cleanup(void)
+{
+ sk_OSSL_PROVIDER_pop_free(app_providers, provider_free);
+ app_providers = NULL;
+}
+
+static int opt_provider_path(const char *path)
+{
+ if (path != NULL && *path == '\0')
+ path = NULL;
+ return OSSL_PROVIDER_set_default_search_path(app_get0_libctx(), path);
+}
+
+int opt_provider(int opt)
+{
+ const int given = provider_option_given;
+
+ provider_option_given = 1;
+ switch ((enum prov_range)opt) {
+ case OPT_PROV__FIRST:
+ case OPT_PROV__LAST:
+ return 1;
+ case OPT_PROV_PROVIDER:
+ return app_provider_load(app_get0_libctx(), opt_arg());
+ case OPT_PROV_PROVIDER_PATH:
+ return opt_provider_path(opt_arg());
+ case OPT_PROV_PROPQUERY:
+ return app_set_propq(opt_arg());
+ }
+ /* Should never get here but if we do, undo what we did earlier */
+ provider_option_given = given;
+ return 0;
+}
+
+int opt_provider_option_given(void)
+{
+ return provider_option_given;
+}
diff --git a/apps/lib/app_rand.c b/apps/lib/app_rand.c
new file mode 100644
index 000000000000..713792ead40a
--- /dev/null
+++ b/apps/lib/app_rand.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "apps.h"
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/conf.h>
+
+static char *save_rand_file;
+static STACK_OF(OPENSSL_STRING) *randfiles;
+
+void app_RAND_load_conf(CONF *c, const char *section)
+{
+ const char *randfile = NCONF_get_string(c, section, "RANDFILE");
+
+ if (randfile == NULL) {
+ ERR_clear_error();
+ return;
+ }
+ if (RAND_load_file(randfile, -1) < 0) {
+ BIO_printf(bio_err, "Can't load %s into RNG\n", randfile);
+ ERR_print_errors(bio_err);
+ }
+ if (save_rand_file == NULL) {
+ save_rand_file = OPENSSL_strdup(randfile);
+ /* If some internal memory errors have occurred */
+ if (save_rand_file == NULL) {
+ BIO_printf(bio_err, "Can't duplicate %s\n", randfile);
+ ERR_print_errors(bio_err);
+ }
+ }
+}
+
+static int loadfiles(char *name)
+{
+ char *p;
+ int last, ret = 1;
+
+ for ( ; ; ) {
+ last = 0;
+ for (p = name; *p != '\0' && *p != LIST_SEPARATOR_CHAR; p++)
+ continue;
+ if (*p == '\0')
+ last = 1;
+ *p = '\0';
+ if (RAND_load_file(name, -1) < 0) {
+ BIO_printf(bio_err, "Can't load %s into RNG\n", name);
+ ERR_print_errors(bio_err);
+ ret = 0;
+ }
+ if (last)
+ break;
+ name = p + 1;
+ if (*name == '\0')
+ break;
+ }
+ return ret;
+}
+
+int app_RAND_load(void)
+{
+ char *p;
+ int i, ret = 1;
+
+ for (i = 0; i < sk_OPENSSL_STRING_num(randfiles); i++) {
+ p = sk_OPENSSL_STRING_value(randfiles, i);
+ if (!loadfiles(p))
+ ret = 0;
+ }
+ sk_OPENSSL_STRING_free(randfiles);
+ return ret;
+}
+
+int app_RAND_write(void)
+{
+ int ret = 1;
+
+ if (save_rand_file == NULL)
+ return 1;
+ if (RAND_write_file(save_rand_file) == -1) {
+ BIO_printf(bio_err, "Cannot write random bytes:\n");
+ ERR_print_errors(bio_err);
+ ret = 0;
+ }
+ OPENSSL_free(save_rand_file);
+ save_rand_file = NULL;
+ return ret;
+}
+
+
+/*
+ * See comments in opt_verify for explanation of this.
+ */
+enum r_range { OPT_R_ENUM };
+
+int opt_rand(int opt)
+{
+ switch ((enum r_range)opt) {
+ case OPT_R__FIRST:
+ case OPT_R__LAST:
+ break;
+ case OPT_R_RAND:
+ if (randfiles == NULL
+ && (randfiles = sk_OPENSSL_STRING_new_null()) == NULL)
+ return 0;
+ if (!sk_OPENSSL_STRING_push(randfiles, opt_arg()))
+ return 0;
+ break;
+ case OPT_R_WRITERAND:
+ OPENSSL_free(save_rand_file);
+ save_rand_file = OPENSSL_strdup(opt_arg());
+ if (save_rand_file == NULL)
+ return 0;
+ break;
+ }
+ return 1;
+}
diff --git a/apps/lib/app_x509.c b/apps/lib/app_x509.c
new file mode 100644
index 000000000000..f2c22948f201
--- /dev/null
+++ b/apps/lib/app_x509.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include "apps.h"
+
+/*
+ * X509_ctrl_str() is sorely lacking in libcrypto, but is still needed to
+ * allow the application to process verification options in a manner similar
+ * to signature or other options that pass through EVP_PKEY_CTX_ctrl_str(),
+ * for uniformity.
+ *
+ * As soon as more stuff is added, the code will need serious rework. For
+ * the moment, it only handles the FIPS 196 / SM2 distinguishing ID.
+ */
+#ifdef EVP_PKEY_CTRL_SET1_ID
+static ASN1_OCTET_STRING *mk_octet_string(void *value, size_t value_n)
+{
+ ASN1_OCTET_STRING *v = ASN1_OCTET_STRING_new();
+
+ if (v == NULL) {
+ BIO_printf(bio_err, "error: allocation failed\n");
+ } else if (!ASN1_OCTET_STRING_set(v, value, (int)value_n)) {
+ ASN1_OCTET_STRING_free(v);
+ v = NULL;
+ }
+ return v;
+}
+#endif
+
+static int x509_ctrl(void *object, int cmd, void *value, size_t value_n)
+{
+ switch (cmd) {
+#ifdef EVP_PKEY_CTRL_SET1_ID
+ case EVP_PKEY_CTRL_SET1_ID:
+ {
+ ASN1_OCTET_STRING *v = mk_octet_string(value, value_n);
+
+ if (v == NULL) {
+ BIO_printf(bio_err,
+ "error: setting distinguishing ID in certificate failed\n");
+ return 0;
+ }
+
+ X509_set0_distinguishing_id(object, v);
+ return 1;
+ }
+#endif
+ default:
+ break;
+ }
+ return -2; /* typical EVP_PKEY return for "unsupported" */
+}
+
+static int x509_req_ctrl(void *object, int cmd, void *value, size_t value_n)
+{
+ switch (cmd) {
+#ifdef EVP_PKEY_CTRL_SET1_ID
+ case EVP_PKEY_CTRL_SET1_ID:
+ {
+ ASN1_OCTET_STRING *v = mk_octet_string(value, value_n);
+
+ if (v == NULL) {
+ BIO_printf(bio_err,
+ "error: setting distinguishing ID in certificate signing request failed\n");
+ return 0;
+ }
+
+ X509_REQ_set0_distinguishing_id(object, v);
+ return 1;
+ }
+#endif
+ default:
+ break;
+ }
+ return -2; /* typical EVP_PKEY return for "unsupported" */
+}
+
+static int do_x509_ctrl_string(int (*ctrl)(void *object, int cmd,
+ void *value, size_t value_n),
+ void *object, const char *value)
+{
+ int rv = 0;
+ char *stmp, *vtmp = NULL;
+ size_t vtmp_len = 0;
+ int cmd = 0; /* Will get command values that make sense somehow */
+
+ stmp = OPENSSL_strdup(value);
+ if (stmp == NULL)
+ return -1;
+ vtmp = strchr(stmp, ':');
+ if (vtmp != NULL) {
+ *vtmp = 0;
+ vtmp++;
+ vtmp_len = strlen(vtmp);
+ }
+
+ if (strcmp(stmp, "distid") == 0) {
+#ifdef EVP_PKEY_CTRL_SET1_ID
+ cmd = EVP_PKEY_CTRL_SET1_ID; /* ... except we put it in X509 */
+#endif
+ } else if (strcmp(stmp, "hexdistid") == 0) {
+ if (vtmp != NULL) {
+ void *hexid;
+ long hexid_len = 0;
+
+ hexid = OPENSSL_hexstr2buf((const char *)vtmp, &hexid_len);
+ OPENSSL_free(stmp);
+ stmp = vtmp = hexid;
+ vtmp_len = (size_t)hexid_len;
+ }
+#ifdef EVP_PKEY_CTRL_SET1_ID
+ cmd = EVP_PKEY_CTRL_SET1_ID; /* ... except we put it in X509 */
+#endif
+ }
+
+ rv = ctrl(object, cmd, vtmp, vtmp_len);
+
+ OPENSSL_free(stmp);
+ return rv;
+}
+
+int x509_ctrl_string(X509 *x, const char *value)
+{
+ return do_x509_ctrl_string(x509_ctrl, x, value);
+}
+
+int x509_req_ctrl_string(X509_REQ *x, const char *value)
+{
+ return do_x509_ctrl_string(x509_req_ctrl, x, value);
+}
diff --git a/apps/lib/apps.c b/apps/lib/apps.c
new file mode 100644
index 000000000000..0d7a20b52afc
--- /dev/null
+++ b/apps/lib/apps.c
@@ -0,0 +1,3389 @@
+/*
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
+/*
+ * On VMS, you need to define this to get the declaration of fileno(). The
+ * value 2 is to make sure no function defined in POSIX-2 is left undefined.
+ */
+# define _POSIX_C_SOURCE 2
+#endif
+
+#ifndef OPENSSL_NO_ENGINE
+/* We need to use some deprecated APIs */
+# define OPENSSL_SUPPRESS_DEPRECATED
+# include <openssl/engine.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#ifndef OPENSSL_NO_POSIX_IO
+# include <sys/stat.h>
+# include <fcntl.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/http.h>
+#include <openssl/pem.h>
+#include <openssl/store.h>
+#include <openssl/pkcs12.h>
+#include <openssl/ui.h>
+#include <openssl/safestack.h>
+#include <openssl/rsa.h>
+#include <openssl/rand.h>
+#include <openssl/bn.h>
+#include <openssl/ssl.h>
+#include <openssl/store.h>
+#include <openssl/core_names.h>
+#include "s_apps.h"
+#include "apps.h"
+
+#ifdef _WIN32
+static int WIN32_rename(const char *from, const char *to);
+# define rename(from,to) WIN32_rename((from),(to))
+#endif
+
+#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
+# include <conio.h>
+#endif
+
+#if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) || defined(__BORLANDC__)
+# define _kbhit kbhit
+#endif
+
+static BIO *bio_open_default_(const char *filename, char mode, int format,
+ int quiet);
+
+#define PASS_SOURCE_SIZE_MAX 4
+
+DEFINE_STACK_OF(CONF)
+
+typedef struct {
+ const char *name;
+ unsigned long flag;
+ unsigned long mask;
+} NAME_EX_TBL;
+
+static int set_table_opts(unsigned long *flags, const char *arg,
+ const NAME_EX_TBL * in_tbl);
+static int set_multi_opts(unsigned long *flags, const char *arg,
+ const NAME_EX_TBL * in_tbl);
+static
+int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin,
+ const char *pass, const char *desc,
+ EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
+ EVP_PKEY **pparams,
+ X509 **pcert, STACK_OF(X509) **pcerts,
+ X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls,
+ int suppress_decode_errors);
+
+int app_init(long mesgwin);
+
+int chopup_args(ARGS *arg, char *buf)
+{
+ int quoted;
+ char c = '\0', *p = NULL;
+
+ arg->argc = 0;
+ if (arg->size == 0) {
+ arg->size = 20;
+ arg->argv = app_malloc(sizeof(*arg->argv) * arg->size, "argv space");
+ }
+
+ for (p = buf;;) {
+ /* Skip whitespace. */
+ while (*p && isspace(_UC(*p)))
+ p++;
+ if (*p == '\0')
+ break;
+
+ /* The start of something good :-) */
+ if (arg->argc >= arg->size) {
+ char **tmp;
+ arg->size += 20;
+ tmp = OPENSSL_realloc(arg->argv, sizeof(*arg->argv) * arg->size);
+ if (tmp == NULL)
+ return 0;
+ arg->argv = tmp;
+ }
+ quoted = *p == '\'' || *p == '"';
+ if (quoted)
+ c = *p++;
+ arg->argv[arg->argc++] = p;
+
+ /* now look for the end of this */
+ if (quoted) {
+ while (*p && *p != c)
+ p++;
+ *p++ = '\0';
+ } else {
+ while (*p && !isspace(_UC(*p)))
+ p++;
+ if (*p)
+ *p++ = '\0';
+ }
+ }
+ arg->argv[arg->argc] = NULL;
+ return 1;
+}
+
+#ifndef APP_INIT
+int app_init(long mesgwin)
+{
+ return 1;
+}
+#endif
+
+int ctx_set_verify_locations(SSL_CTX *ctx,
+ const char *CAfile, int noCAfile,
+ const char *CApath, int noCApath,
+ const char *CAstore, int noCAstore)
+{
+ if (CAfile == NULL && CApath == NULL && CAstore == NULL) {
+ if (!noCAfile && SSL_CTX_set_default_verify_file(ctx) <= 0)
+ return 0;
+ if (!noCApath && SSL_CTX_set_default_verify_dir(ctx) <= 0)
+ return 0;
+ if (!noCAstore && SSL_CTX_set_default_verify_store(ctx) <= 0)
+ return 0;
+
+ return 1;
+ }
+
+ if (CAfile != NULL && !SSL_CTX_load_verify_file(ctx, CAfile))
+ return 0;
+ if (CApath != NULL && !SSL_CTX_load_verify_dir(ctx, CApath))
+ return 0;
+ if (CAstore != NULL && !SSL_CTX_load_verify_store(ctx, CAstore))
+ return 0;
+ return 1;
+}
+
+#ifndef OPENSSL_NO_CT
+
+int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path)
+{
+ if (path == NULL)
+ return SSL_CTX_set_default_ctlog_list_file(ctx);
+
+ return SSL_CTX_set_ctlog_list_file(ctx, path);
+}
+
+#endif
+
+static unsigned long nmflag = 0;
+static char nmflag_set = 0;
+
+int set_nameopt(const char *arg)
+{
+ int ret = set_name_ex(&nmflag, arg);
+
+ if (ret)
+ nmflag_set = 1;
+
+ return ret;
+}
+
+unsigned long get_nameopt(void)
+{
+ return (nmflag_set) ? nmflag : XN_FLAG_ONELINE;
+}
+
+void dump_cert_text(BIO *out, X509 *x)
+{
+ print_name(out, "subject=", X509_get_subject_name(x));
+ print_name(out, "issuer=", X509_get_issuer_name(x));
+}
+
+int wrap_password_callback(char *buf, int bufsiz, int verify, void *userdata)
+{
+ return password_callback(buf, bufsiz, verify, (PW_CB_DATA *)userdata);
+}
+
+
+static char *app_get_pass(const char *arg, int keepbio);
+
+char *get_passwd(const char *pass, const char *desc)
+{
+ char *result = NULL;
+
+ if (desc == NULL)
+ desc = "<unknown>";
+ if (!app_passwd(pass, NULL, &result, NULL))
+ BIO_printf(bio_err, "Error getting password for %s\n", desc);
+ if (pass != NULL && result == NULL) {
+ BIO_printf(bio_err,
+ "Trying plain input string (better precede with 'pass:')\n");
+ result = OPENSSL_strdup(pass);
+ if (result == NULL)
+ BIO_printf(bio_err, "Out of memory getting password for %s\n", desc);
+ }
+ return result;
+}
+
+int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2)
+{
+ int same = arg1 != NULL && arg2 != NULL && strcmp(arg1, arg2) == 0;
+
+ if (arg1 != NULL) {
+ *pass1 = app_get_pass(arg1, same);
+ if (*pass1 == NULL)
+ return 0;
+ } else if (pass1 != NULL) {
+ *pass1 = NULL;
+ }
+ if (arg2 != NULL) {
+ *pass2 = app_get_pass(arg2, same ? 2 : 0);
+ if (*pass2 == NULL)
+ return 0;
+ } else if (pass2 != NULL) {
+ *pass2 = NULL;
+ }
+ return 1;
+}
+
+static char *app_get_pass(const char *arg, int keepbio)
+{
+ static BIO *pwdbio = NULL;
+ char *tmp, tpass[APP_PASS_LEN];
+ int i;
+
+ /* PASS_SOURCE_SIZE_MAX = max number of chars before ':' in below strings */
+ if (strncmp(arg, "pass:", 5) == 0)
+ return OPENSSL_strdup(arg + 5);
+ if (strncmp(arg, "env:", 4) == 0) {
+ tmp = getenv(arg + 4);
+ if (tmp == NULL) {
+ BIO_printf(bio_err, "No environment variable %s\n", arg + 4);
+ return NULL;
+ }
+ return OPENSSL_strdup(tmp);
+ }
+ if (!keepbio || pwdbio == NULL) {
+ if (strncmp(arg, "file:", 5) == 0) {
+ pwdbio = BIO_new_file(arg + 5, "r");
+ if (pwdbio == NULL) {
+ BIO_printf(bio_err, "Can't open file %s\n", arg + 5);
+ return NULL;
+ }
+#if !defined(_WIN32)
+ /*
+ * Under _WIN32, which covers even Win64 and CE, file
+ * descriptors referenced by BIO_s_fd are not inherited
+ * by child process and therefore below is not an option.
+ * It could have been an option if bss_fd.c was operating
+ * on real Windows descriptors, such as those obtained
+ * with CreateFile.
+ */
+ } else if (strncmp(arg, "fd:", 3) == 0) {
+ BIO *btmp;
+ i = atoi(arg + 3);
+ if (i >= 0)
+ pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
+ if ((i < 0) || pwdbio == NULL) {
+ BIO_printf(bio_err, "Can't access file descriptor %s\n", arg + 3);
+ return NULL;
+ }
+ /*
+ * Can't do BIO_gets on an fd BIO so add a buffering BIO
+ */
+ btmp = BIO_new(BIO_f_buffer());
+ if (btmp == NULL) {
+ BIO_free_all(pwdbio);
+ pwdbio = NULL;
+ BIO_printf(bio_err, "Out of memory\n");
+ return NULL;
+ }
+ pwdbio = BIO_push(btmp, pwdbio);
+#endif
+ } else if (strcmp(arg, "stdin") == 0) {
+ unbuffer(stdin);
+ pwdbio = dup_bio_in(FORMAT_TEXT);
+ if (pwdbio == NULL) {
+ BIO_printf(bio_err, "Can't open BIO for stdin\n");
+ return NULL;
+ }
+ } else {
+ /* argument syntax error; do not reveal too much about arg */
+ tmp = strchr(arg, ':');
+ if (tmp == NULL || tmp - arg > PASS_SOURCE_SIZE_MAX)
+ BIO_printf(bio_err,
+ "Invalid password argument, missing ':' within the first %d chars\n",
+ PASS_SOURCE_SIZE_MAX + 1);
+ else
+ BIO_printf(bio_err,
+ "Invalid password argument, starting with \"%.*s\"\n",
+ (int)(tmp - arg + 1), arg);
+ return NULL;
+ }
+ }
+ i = BIO_gets(pwdbio, tpass, APP_PASS_LEN);
+ if (keepbio != 1) {
+ BIO_free_all(pwdbio);
+ pwdbio = NULL;
+ }
+ if (i <= 0) {
+ BIO_printf(bio_err, "Error reading password from BIO\n");
+ return NULL;
+ }
+ tmp = strchr(tpass, '\n');
+ if (tmp != NULL)
+ *tmp = 0;
+ return OPENSSL_strdup(tpass);
+}
+
+CONF *app_load_config_bio(BIO *in, const char *filename)
+{
+ long errorline = -1;
+ CONF *conf;
+ int i;
+
+ conf = NCONF_new_ex(app_get0_libctx(), NULL);
+ i = NCONF_load_bio(conf, in, &errorline);
+ if (i > 0)
+ return conf;
+
+ if (errorline <= 0) {
+ BIO_printf(bio_err, "%s: Can't load ", opt_getprog());
+ } else {
+ BIO_printf(bio_err, "%s: Error on line %ld of ", opt_getprog(),
+ errorline);
+ }
+ if (filename != NULL)
+ BIO_printf(bio_err, "config file \"%s\"\n", filename);
+ else
+ BIO_printf(bio_err, "config input");
+
+ NCONF_free(conf);
+ return NULL;
+}
+
+CONF *app_load_config_verbose(const char *filename, int verbose)
+{
+ if (verbose) {
+ if (*filename == '\0')
+ BIO_printf(bio_err, "No configuration used\n");
+ else
+ BIO_printf(bio_err, "Using configuration from %s\n", filename);
+ }
+ return app_load_config_internal(filename, 0);
+}
+
+CONF *app_load_config_internal(const char *filename, int quiet)
+{
+ BIO *in;
+ CONF *conf;
+
+ if (filename == NULL || *filename != '\0') {
+ if ((in = bio_open_default_(filename, 'r', FORMAT_TEXT, quiet)) == NULL)
+ return NULL;
+ conf = app_load_config_bio(in, filename);
+ BIO_free(in);
+ } else {
+ /* Return empty config if filename is empty string. */
+ conf = NCONF_new_ex(app_get0_libctx(), NULL);
+ }
+ return conf;
+}
+
+int app_load_modules(const CONF *config)
+{
+ CONF *to_free = NULL;
+
+ if (config == NULL)
+ config = to_free = app_load_config_quiet(default_config_file);
+ if (config == NULL)
+ return 1;
+
+ if (CONF_modules_load(config, NULL, 0) <= 0) {
+ BIO_printf(bio_err, "Error configuring OpenSSL modules\n");
+ ERR_print_errors(bio_err);
+ NCONF_free(to_free);
+ return 0;
+ }
+ NCONF_free(to_free);
+ return 1;
+}
+
+int add_oid_section(CONF *conf)
+{
+ char *p;
+ STACK_OF(CONF_VALUE) *sktmp;
+ CONF_VALUE *cnf;
+ int i;
+
+ if ((p = NCONF_get_string(conf, NULL, "oid_section")) == NULL) {
+ ERR_clear_error();
+ return 1;
+ }
+ if ((sktmp = NCONF_get_section(conf, p)) == NULL) {
+ BIO_printf(bio_err, "problem loading oid section %s\n", p);
+ return 0;
+ }
+ for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
+ cnf = sk_CONF_VALUE_value(sktmp, i);
+ if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
+ BIO_printf(bio_err, "problem creating object %s=%s\n",
+ cnf->name, cnf->value);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+CONF *app_load_config_modules(const char *configfile)
+{
+ CONF *conf = NULL;
+
+ if (configfile != NULL) {
+ if ((conf = app_load_config_verbose(configfile, 1)) == NULL)
+ return NULL;
+ if (configfile != default_config_file && !app_load_modules(conf)) {
+ NCONF_free(conf);
+ conf = NULL;
+ }
+ }
+ return conf;
+}
+
+#define IS_HTTP(uri) ((uri) != NULL \
+ && strncmp(uri, OSSL_HTTP_PREFIX, strlen(OSSL_HTTP_PREFIX)) == 0)
+#define IS_HTTPS(uri) ((uri) != NULL \
+ && strncmp(uri, OSSL_HTTPS_PREFIX, strlen(OSSL_HTTPS_PREFIX)) == 0)
+
+X509 *load_cert_pass(const char *uri, int format, int maybe_stdin,
+ const char *pass, const char *desc)
+{
+ X509 *cert = NULL;
+
+ if (desc == NULL)
+ desc = "certificate";
+ if (IS_HTTPS(uri))
+ BIO_printf(bio_err, "Loading %s over HTTPS is unsupported\n", desc);
+ else if (IS_HTTP(uri))
+ cert = X509_load_http(uri, NULL, NULL, 0 /* timeout */);
+ else
+ (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc,
+ NULL, NULL, NULL, &cert, NULL, NULL, NULL);
+ if (cert == NULL) {
+ BIO_printf(bio_err, "Unable to load %s\n", desc);
+ ERR_print_errors(bio_err);
+ }
+ return cert;
+}
+
+X509_CRL *load_crl(const char *uri, int format, int maybe_stdin,
+ const char *desc)
+{
+ X509_CRL *crl = NULL;
+
+ if (desc == NULL)
+ desc = "CRL";
+ if (IS_HTTPS(uri))
+ BIO_printf(bio_err, "Loading %s over HTTPS is unsupported\n", desc);
+ else if (IS_HTTP(uri))
+ crl = X509_CRL_load_http(uri, NULL, NULL, 0 /* timeout */);
+ else
+ (void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc,
+ NULL, NULL, NULL, NULL, NULL, &crl, NULL);
+ if (crl == NULL) {
+ BIO_printf(bio_err, "Unable to load %s\n", desc);
+ ERR_print_errors(bio_err);
+ }
+ return crl;
+}
+
+X509_REQ *load_csr(const char *file, int format, const char *desc)
+{
+ X509_REQ *req = NULL;
+ BIO *in;
+
+ if (format == FORMAT_UNDEF)
+ format = FORMAT_PEM;
+ if (desc == NULL)
+ desc = "CSR";
+ in = bio_open_default(file, 'r', format);
+ if (in == NULL)
+ goto end;
+
+ if (format == FORMAT_ASN1)
+ req = d2i_X509_REQ_bio(in, NULL);
+ else if (format == FORMAT_PEM)
+ req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
+ else
+ print_format_error(format, OPT_FMT_PEMDER);
+
+ end:
+ if (req == NULL) {
+ BIO_printf(bio_err, "Unable to load %s\n", desc);
+ ERR_print_errors(bio_err);
+ }
+ BIO_free(in);
+ return req;
+}
+
+void cleanse(char *str)
+{
+ if (str != NULL)
+ OPENSSL_cleanse(str, strlen(str));
+}
+
+void clear_free(char *str)
+{
+ if (str != NULL)
+ OPENSSL_clear_free(str, strlen(str));
+}
+
+EVP_PKEY *load_key(const char *uri, int format, int may_stdin,
+ const char *pass, ENGINE *e, const char *desc)
+{
+ EVP_PKEY *pkey = NULL;
+ char *allocated_uri = NULL;
+
+ if (desc == NULL)
+ desc = "private key";
+
+ if (format == FORMAT_ENGINE) {
+ uri = allocated_uri = make_engine_uri(e, uri, desc);
+ }
+ (void)load_key_certs_crls(uri, format, may_stdin, pass, desc,
+ &pkey, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ OPENSSL_free(allocated_uri);
+ return pkey;
+}
+
+EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin,
+ const char *pass, ENGINE *e, const char *desc)
+{
+ EVP_PKEY *pkey = NULL;
+ char *allocated_uri = NULL;
+
+ if (desc == NULL)
+ desc = "public key";
+
+ if (format == FORMAT_ENGINE) {
+ uri = allocated_uri = make_engine_uri(e, uri, desc);
+ }
+ (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc,
+ NULL, &pkey, NULL, NULL, NULL, NULL, NULL);
+
+ OPENSSL_free(allocated_uri);
+ return pkey;
+}
+
+EVP_PKEY *load_keyparams_suppress(const char *uri, int format, int maybe_stdin,
+ const char *keytype, const char *desc,
+ int suppress_decode_errors)
+{
+ EVP_PKEY *params = NULL;
+
+ if (desc == NULL)
+ desc = "key parameters";
+
+ (void)load_key_certs_crls_suppress(uri, format, maybe_stdin, NULL, desc,
+ NULL, NULL, &params, NULL, NULL, NULL,
+ NULL, suppress_decode_errors);
+ if (params != NULL && keytype != NULL && !EVP_PKEY_is_a(params, keytype)) {
+ if (!suppress_decode_errors) {
+ BIO_printf(bio_err,
+ "Unable to load %s from %s (unexpected parameters type)\n",
+ desc, uri);
+ ERR_print_errors(bio_err);
+ }
+ EVP_PKEY_free(params);
+ params = NULL;
+ }
+ return params;
+}
+
+EVP_PKEY *load_keyparams(const char *uri, int format, int maybe_stdin,
+ const char *keytype, const char *desc)
+{
+ return load_keyparams_suppress(uri, format, maybe_stdin, keytype, desc, 0);
+}
+
+void app_bail_out(char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ BIO_vprintf(bio_err, fmt, args);
+ va_end(args);
+ ERR_print_errors(bio_err);
+ exit(EXIT_FAILURE);
+}
+
+void *app_malloc(size_t sz, const char *what)
+{
+ void *vp = OPENSSL_malloc(sz);
+
+ if (vp == NULL)
+ app_bail_out("%s: Could not allocate %zu bytes for %s\n",
+ opt_getprog(), sz, what);
+ return vp;
+}
+
+char *next_item(char *opt) /* in list separated by comma and/or space */
+{
+ /* advance to separator (comma or whitespace), if any */
+ while (*opt != ',' && !isspace(*opt) && *opt != '\0')
+ opt++;
+ if (*opt != '\0') {
+ /* terminate current item */
+ *opt++ = '\0';
+ /* skip over any whitespace after separator */
+ while (isspace(*opt))
+ opt++;
+ }
+ return *opt == '\0' ? NULL : opt; /* NULL indicates end of input */
+}
+
+static void warn_cert_msg(const char *uri, X509 *cert, const char *msg)
+{
+ char *subj = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
+
+ BIO_printf(bio_err, "Warning: certificate from '%s' with subject '%s' %s\n",
+ uri, subj, msg);
+ OPENSSL_free(subj);
+}
+
+static void warn_cert(const char *uri, X509 *cert, int warn_EE,
+ X509_VERIFY_PARAM *vpm)
+{
+ uint32_t ex_flags = X509_get_extension_flags(cert);
+ int res = X509_cmp_timeframe(vpm, X509_get0_notBefore(cert),
+ X509_get0_notAfter(cert));
+
+ if (res != 0)
+ warn_cert_msg(uri, cert, res > 0 ? "has expired" : "not yet valid");
+ if (warn_EE && (ex_flags & EXFLAG_V1) == 0 && (ex_flags & EXFLAG_CA) == 0)
+ warn_cert_msg(uri, cert, "is not a CA cert");
+}
+
+static void warn_certs(const char *uri, STACK_OF(X509) *certs, int warn_EE,
+ X509_VERIFY_PARAM *vpm)
+{
+ int i;
+
+ for (i = 0; i < sk_X509_num(certs); i++)
+ warn_cert(uri, sk_X509_value(certs, i), warn_EE, vpm);
+}
+
+int load_cert_certs(const char *uri,
+ X509 **pcert, STACK_OF(X509) **pcerts,
+ int exclude_http, const char *pass, const char *desc,
+ X509_VERIFY_PARAM *vpm)
+{
+ int ret = 0;
+ char *pass_string;
+
+ if (exclude_http && (OPENSSL_strncasecmp(uri, "http://", 7) == 0
+ || OPENSSL_strncasecmp(uri, "https://", 8) == 0)) {
+ BIO_printf(bio_err, "error: HTTP retrieval not allowed for %s\n", desc);
+ return ret;
+ }
+ pass_string = get_passwd(pass, desc);
+ ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass_string, desc,
+ NULL, NULL, NULL,
+ pcert, pcerts, NULL, NULL);
+ clear_free(pass_string);
+
+ if (ret) {
+ if (pcert != NULL)
+ warn_cert(uri, *pcert, 0, vpm);
+ if (pcerts != NULL)
+ warn_certs(uri, *pcerts, 1, vpm);
+ } else {
+ if (pcerts != NULL) {
+ sk_X509_pop_free(*pcerts, X509_free);
+ *pcerts = NULL;
+ }
+ }
+ return ret;
+}
+
+STACK_OF(X509) *load_certs_multifile(char *files, const char *pass,
+ const char *desc, X509_VERIFY_PARAM *vpm)
+{
+ STACK_OF(X509) *certs = NULL;
+ STACK_OF(X509) *result = sk_X509_new_null();
+
+ if (files == NULL)
+ goto err;
+ if (result == NULL)
+ goto oom;
+
+ while (files != NULL) {
+ char *next = next_item(files);
+
+ if (!load_cert_certs(files, NULL, &certs, 0, pass, desc, vpm))
+ goto err;
+ if (!X509_add_certs(result, certs,
+ X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
+ goto oom;
+ sk_X509_pop_free(certs, X509_free);
+ certs = NULL;
+ files = next;
+ }
+ return result;
+
+ oom:
+ BIO_printf(bio_err, "out of memory\n");
+ err:
+ sk_X509_pop_free(certs, X509_free);
+ sk_X509_pop_free(result, X509_free);
+ return NULL;
+}
+
+static X509_STORE *sk_X509_to_store(X509_STORE *store /* may be NULL */,
+ const STACK_OF(X509) *certs /* may NULL */)
+{
+ int i;
+
+ if (store == NULL)
+ store = X509_STORE_new();
+ if (store == NULL)
+ return NULL;
+ for (i = 0; i < sk_X509_num(certs); i++) {
+ if (!X509_STORE_add_cert(store, sk_X509_value(certs, i))) {
+ X509_STORE_free(store);
+ return NULL;
+ }
+ }
+ return store;
+}
+
+/*
+ * Create cert store structure with certificates read from given file(s).
+ * Returns pointer to created X509_STORE on success, NULL on error.
+ */
+X509_STORE *load_certstore(char *input, const char *pass, const char *desc,
+ X509_VERIFY_PARAM *vpm)
+{
+ X509_STORE *store = NULL;
+ STACK_OF(X509) *certs = NULL;
+
+ while (input != NULL) {
+ char *next = next_item(input);
+ int ok;
+
+ if (!load_cert_certs(input, NULL, &certs, 1, pass, desc, vpm)) {
+ X509_STORE_free(store);
+ return NULL;
+ }
+ ok = (store = sk_X509_to_store(store, certs)) != NULL;
+ sk_X509_pop_free(certs, X509_free);
+ certs = NULL;
+ if (!ok)
+ return NULL;
+ input = next;
+ }
+ return store;
+}
+
+/*
+ * Initialize or extend, if *certs != NULL, a certificate stack.
+ * The caller is responsible for freeing *certs if its value is left not NULL.
+ */
+int load_certs(const char *uri, int maybe_stdin, STACK_OF(X509) **certs,
+ const char *pass, const char *desc)
+{
+ int was_NULL = *certs == NULL;
+ int ret = load_key_certs_crls(uri, FORMAT_UNDEF, maybe_stdin,
+ pass, desc, NULL, NULL,
+ NULL, NULL, certs, NULL, NULL);
+
+ if (!ret && was_NULL) {
+ sk_X509_pop_free(*certs, X509_free);
+ *certs = NULL;
+ }
+ return ret;
+}
+
+/*
+ * Initialize or extend, if *crls != NULL, a certificate stack.
+ * The caller is responsible for freeing *crls if its value is left not NULL.
+ */
+int load_crls(const char *uri, STACK_OF(X509_CRL) **crls,
+ const char *pass, const char *desc)
+{
+ int was_NULL = *crls == NULL;
+ int ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass, desc,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, crls);
+
+ if (!ret && was_NULL) {
+ sk_X509_CRL_pop_free(*crls, X509_CRL_free);
+ *crls = NULL;
+ }
+ return ret;
+}
+
+static const char *format2string(int format)
+{
+ switch(format) {
+ case FORMAT_PEM:
+ return "PEM";
+ case FORMAT_ASN1:
+ return "DER";
+ }
+ return NULL;
+}
+
+/* Set type expectation, but clear it if objects of different types expected. */
+#define SET_EXPECT(expect, val) ((expect) = (expect) < 0 ? (val) : ((expect) == (val) ? (val) : 0))
+/*
+ * Load those types of credentials for which the result pointer is not NULL.
+ * Reads from stdio if uri is NULL and maybe_stdin is nonzero.
+ * For non-NULL ppkey, pcert, and pcrl the first suitable value found is loaded.
+ * If pcerts is non-NULL and *pcerts == NULL then a new cert list is allocated.
+ * If pcerts is non-NULL then all available certificates are appended to *pcerts
+ * except any certificate assigned to *pcert.
+ * If pcrls is non-NULL and *pcrls == NULL then a new list of CRLs is allocated.
+ * If pcrls is non-NULL then all available CRLs are appended to *pcerts
+ * except any CRL assigned to *pcrl.
+ * In any case (also on error) the caller is responsible for freeing all members
+ * of *pcerts and *pcrls (as far as they are not NULL).
+ */
+static
+int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin,
+ const char *pass, const char *desc,
+ EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
+ EVP_PKEY **pparams,
+ X509 **pcert, STACK_OF(X509) **pcerts,
+ X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls,
+ int suppress_decode_errors)
+{
+ PW_CB_DATA uidata;
+ OSSL_STORE_CTX *ctx = NULL;
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
+ const char *propq = app_get0_propq();
+ int ncerts = 0;
+ int ncrls = 0;
+ const char *failed =
+ ppkey != NULL ? "key" : ppubkey != NULL ? "public key" :
+ pparams != NULL ? "params" : pcert != NULL ? "cert" :
+ pcrl != NULL ? "CRL" : pcerts != NULL ? "certs" :
+ pcrls != NULL ? "CRLs" : NULL;
+ int cnt_expectations = 0;
+ int expect = -1;
+ const char *input_type;
+ OSSL_PARAM itp[2];
+ const OSSL_PARAM *params = NULL;
+
+ if (ppkey != NULL) {
+ *ppkey = NULL;
+ cnt_expectations++;
+ SET_EXPECT(expect, OSSL_STORE_INFO_PKEY);
+ }
+ if (ppubkey != NULL) {
+ *ppubkey = NULL;
+ cnt_expectations++;
+ SET_EXPECT(expect, OSSL_STORE_INFO_PUBKEY);
+ }
+ if (pparams != NULL) {
+ *pparams = NULL;
+ cnt_expectations++;
+ SET_EXPECT(expect, OSSL_STORE_INFO_PARAMS);
+ }
+ if (pcert != NULL) {
+ *pcert = NULL;
+ cnt_expectations++;
+ SET_EXPECT(expect, OSSL_STORE_INFO_CERT);
+ }
+ if (pcerts != NULL) {
+ if (*pcerts == NULL && (*pcerts = sk_X509_new_null()) == NULL) {
+ BIO_printf(bio_err, "Out of memory loading");
+ goto end;
+ }
+ cnt_expectations++;
+ SET_EXPECT(expect, OSSL_STORE_INFO_CERT);
+ }
+ if (pcrl != NULL) {
+ *pcrl = NULL;
+ cnt_expectations++;
+ SET_EXPECT(expect, OSSL_STORE_INFO_CRL);
+ }
+ if (pcrls != NULL) {
+ if (*pcrls == NULL && (*pcrls = sk_X509_CRL_new_null()) == NULL) {
+ BIO_printf(bio_err, "Out of memory loading");
+ goto end;
+ }
+ cnt_expectations++;
+ SET_EXPECT(expect, OSSL_STORE_INFO_CRL);
+ }
+ if (cnt_expectations == 0) {
+ BIO_printf(bio_err, "Internal error: nothing to load from %s\n",
+ uri != NULL ? uri : "<stdin>");
+ return 0;
+ }
+
+ uidata.password = pass;
+ uidata.prompt_info = uri;
+
+ if ((input_type = format2string(format)) != NULL) {
+ itp[0] = OSSL_PARAM_construct_utf8_string(OSSL_STORE_PARAM_INPUT_TYPE,
+ (char *)input_type, 0);
+ itp[1] = OSSL_PARAM_construct_end();
+ params = itp;
+ }
+
+ if (uri == NULL) {
+ BIO *bio;
+
+ if (!maybe_stdin) {
+ BIO_printf(bio_err, "No filename or uri specified for loading");
+ goto end;
+ }
+ uri = "<stdin>";
+ unbuffer(stdin);
+ bio = BIO_new_fp(stdin, 0);
+ if (bio != NULL) {
+ ctx = OSSL_STORE_attach(bio, "file", libctx, propq,
+ get_ui_method(), &uidata, params,
+ NULL, NULL);
+ BIO_free(bio);
+ }
+ } else {
+ ctx = OSSL_STORE_open_ex(uri, libctx, propq, get_ui_method(), &uidata,
+ params, NULL, NULL);
+ }
+ if (ctx == NULL) {
+ BIO_printf(bio_err, "Could not open file or uri for loading");
+ goto end;
+ }
+ if (expect > 0 && !OSSL_STORE_expect(ctx, expect))
+ goto end;
+
+ failed = NULL;
+ while (cnt_expectations > 0 && !OSSL_STORE_eof(ctx)) {
+ OSSL_STORE_INFO *info = OSSL_STORE_load(ctx);
+ int type, ok = 1;
+
+ /*
+ * This can happen (for example) if we attempt to load a file with
+ * multiple different types of things in it - but the thing we just
+ * tried to load wasn't one of the ones we wanted, e.g. if we're trying
+ * to load a certificate but the file has both the private key and the
+ * certificate in it. We just retry until eof.
+ */
+ if (info == NULL) {
+ continue;
+ }
+
+ type = OSSL_STORE_INFO_get_type(info);
+ switch (type) {
+ case OSSL_STORE_INFO_PKEY:
+ if (ppkey != NULL && *ppkey == NULL) {
+ ok = (*ppkey = OSSL_STORE_INFO_get1_PKEY(info)) != NULL;
+ cnt_expectations -= ok;
+ }
+ /*
+ * An EVP_PKEY with private parts also holds the public parts,
+ * so if the caller asked for a public key, and we got a private
+ * key, we can still pass it back.
+ */
+ if (ok && ppubkey != NULL && *ppubkey == NULL) {
+ ok = ((*ppubkey = OSSL_STORE_INFO_get1_PKEY(info)) != NULL);
+ cnt_expectations -= ok;
+ }
+ break;
+ case OSSL_STORE_INFO_PUBKEY:
+ if (ppubkey != NULL && *ppubkey == NULL) {
+ ok = ((*ppubkey = OSSL_STORE_INFO_get1_PUBKEY(info)) != NULL);
+ cnt_expectations -= ok;
+ }
+ break;
+ case OSSL_STORE_INFO_PARAMS:
+ if (pparams != NULL && *pparams == NULL) {
+ ok = ((*pparams = OSSL_STORE_INFO_get1_PARAMS(info)) != NULL);
+ cnt_expectations -= ok;
+ }
+ break;
+ case OSSL_STORE_INFO_CERT:
+ if (pcert != NULL && *pcert == NULL) {
+ ok = (*pcert = OSSL_STORE_INFO_get1_CERT(info)) != NULL;
+ cnt_expectations -= ok;
+ }
+ else if (pcerts != NULL)
+ ok = X509_add_cert(*pcerts,
+ OSSL_STORE_INFO_get1_CERT(info),
+ X509_ADD_FLAG_DEFAULT);
+ ncerts += ok;
+ break;
+ case OSSL_STORE_INFO_CRL:
+ if (pcrl != NULL && *pcrl == NULL) {
+ ok = (*pcrl = OSSL_STORE_INFO_get1_CRL(info)) != NULL;
+ cnt_expectations -= ok;
+ }
+ else if (pcrls != NULL)
+ ok = sk_X509_CRL_push(*pcrls, OSSL_STORE_INFO_get1_CRL(info));
+ ncrls += ok;
+ break;
+ default:
+ /* skip any other type */
+ break;
+ }
+ OSSL_STORE_INFO_free(info);
+ if (!ok) {
+ failed = info == NULL ? NULL : OSSL_STORE_INFO_type_string(type);
+ BIO_printf(bio_err, "Error reading");
+ break;
+ }
+ }
+
+ end:
+ OSSL_STORE_close(ctx);
+ if (failed == NULL) {
+ int any = 0;
+
+ if ((ppkey != NULL && *ppkey == NULL)
+ || (ppubkey != NULL && *ppubkey == NULL)) {
+ failed = "key";
+ } else if (pparams != NULL && *pparams == NULL) {
+ failed = "params";
+ } else if ((pcert != NULL || pcerts != NULL) && ncerts == 0) {
+ if (pcert == NULL)
+ any = 1;
+ failed = "cert";
+ } else if ((pcrl != NULL || pcrls != NULL) && ncrls == 0) {
+ if (pcrl == NULL)
+ any = 1;
+ failed = "CRL";
+ }
+ if (!suppress_decode_errors) {
+ if (failed != NULL)
+ BIO_printf(bio_err, "Could not read");
+ if (any)
+ BIO_printf(bio_err, " any");
+ }
+ }
+ if (!suppress_decode_errors && failed != NULL) {
+ if (desc != NULL && strstr(desc, failed) != NULL) {
+ BIO_printf(bio_err, " %s", desc);
+ } else {
+ BIO_printf(bio_err, " %s", failed);
+ if (desc != NULL)
+ BIO_printf(bio_err, " of %s", desc);
+ }
+ if (uri != NULL)
+ BIO_printf(bio_err, " from %s", uri);
+ BIO_printf(bio_err, "\n");
+ ERR_print_errors(bio_err);
+ }
+ if (suppress_decode_errors || failed == NULL)
+ /* clear any spurious errors */
+ ERR_clear_error();
+ return failed == NULL;
+}
+
+int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
+ const char *pass, const char *desc,
+ EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
+ EVP_PKEY **pparams,
+ X509 **pcert, STACK_OF(X509) **pcerts,
+ X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls)
+{
+ return load_key_certs_crls_suppress(uri, format, maybe_stdin, pass, desc,
+ ppkey, ppubkey, pparams, pcert, pcerts,
+ pcrl, pcrls, 0);
+}
+
+#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16)
+/* Return error for unknown extensions */
+#define X509V3_EXT_DEFAULT 0
+/* Print error for unknown extensions */
+#define X509V3_EXT_ERROR_UNKNOWN (1L << 16)
+/* ASN1 parse unknown extensions */
+#define X509V3_EXT_PARSE_UNKNOWN (2L << 16)
+/* BIO_dump unknown extensions */
+#define X509V3_EXT_DUMP_UNKNOWN (3L << 16)
+
+#define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \
+ X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION)
+
+int set_cert_ex(unsigned long *flags, const char *arg)
+{
+ static const NAME_EX_TBL cert_tbl[] = {
+ {"compatible", X509_FLAG_COMPAT, 0xffffffffl},
+ {"ca_default", X509_FLAG_CA, 0xffffffffl},
+ {"no_header", X509_FLAG_NO_HEADER, 0},
+ {"no_version", X509_FLAG_NO_VERSION, 0},
+ {"no_serial", X509_FLAG_NO_SERIAL, 0},
+ {"no_signame", X509_FLAG_NO_SIGNAME, 0},
+ {"no_validity", X509_FLAG_NO_VALIDITY, 0},
+ {"no_subject", X509_FLAG_NO_SUBJECT, 0},
+ {"no_issuer", X509_FLAG_NO_ISSUER, 0},
+ {"no_pubkey", X509_FLAG_NO_PUBKEY, 0},
+ {"no_extensions", X509_FLAG_NO_EXTENSIONS, 0},
+ {"no_sigdump", X509_FLAG_NO_SIGDUMP, 0},
+ {"no_aux", X509_FLAG_NO_AUX, 0},
+ {"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0},
+ {"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK},
+ {"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
+ {"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
+ {"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
+ {NULL, 0, 0}
+ };
+ return set_multi_opts(flags, arg, cert_tbl);
+}
+
+int set_name_ex(unsigned long *flags, const char *arg)
+{
+ static const NAME_EX_TBL ex_tbl[] = {
+ {"esc_2253", ASN1_STRFLGS_ESC_2253, 0},
+ {"esc_2254", ASN1_STRFLGS_ESC_2254, 0},
+ {"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0},
+ {"esc_msb", ASN1_STRFLGS_ESC_MSB, 0},
+ {"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0},
+ {"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0},
+ {"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0},
+ {"show_type", ASN1_STRFLGS_SHOW_TYPE, 0},
+ {"dump_all", ASN1_STRFLGS_DUMP_ALL, 0},
+ {"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0},
+ {"dump_der", ASN1_STRFLGS_DUMP_DER, 0},
+ {"compat", XN_FLAG_COMPAT, 0xffffffffL},
+ {"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK},
+ {"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK},
+ {"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK},
+ {"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK},
+ {"dn_rev", XN_FLAG_DN_REV, 0},
+ {"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK},
+ {"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK},
+ {"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK},
+ {"align", XN_FLAG_FN_ALIGN, 0},
+ {"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK},
+ {"space_eq", XN_FLAG_SPC_EQ, 0},
+ {"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0},
+ {"RFC2253", XN_FLAG_RFC2253, 0xffffffffL},
+ {"oneline", XN_FLAG_ONELINE, 0xffffffffL},
+ {"multiline", XN_FLAG_MULTILINE, 0xffffffffL},
+ {"ca_default", XN_FLAG_MULTILINE, 0xffffffffL},
+ {NULL, 0, 0}
+ };
+ if (set_multi_opts(flags, arg, ex_tbl) == 0)
+ return 0;
+ if (*flags != XN_FLAG_COMPAT
+ && (*flags & XN_FLAG_SEP_MASK) == 0)
+ *flags |= XN_FLAG_SEP_CPLUS_SPC;
+ return 1;
+}
+
+int set_dateopt(unsigned long *dateopt, const char *arg)
+{
+ if (OPENSSL_strcasecmp(arg, "rfc_822") == 0)
+ *dateopt = ASN1_DTFLGS_RFC822;
+ else if (OPENSSL_strcasecmp(arg, "iso_8601") == 0)
+ *dateopt = ASN1_DTFLGS_ISO8601;
+ else
+ return 0;
+ return 1;
+}
+
+int set_ext_copy(int *copy_type, const char *arg)
+{
+ if (OPENSSL_strcasecmp(arg, "none") == 0)
+ *copy_type = EXT_COPY_NONE;
+ else if (OPENSSL_strcasecmp(arg, "copy") == 0)
+ *copy_type = EXT_COPY_ADD;
+ else if (OPENSSL_strcasecmp(arg, "copyall") == 0)
+ *copy_type = EXT_COPY_ALL;
+ else
+ return 0;
+ return 1;
+}
+
+int copy_extensions(X509 *x, X509_REQ *req, int copy_type)
+{
+ STACK_OF(X509_EXTENSION) *exts;
+ int i, ret = 0;
+
+ if (x == NULL || req == NULL)
+ return 0;
+ if (copy_type == EXT_COPY_NONE)
+ return 1;
+ exts = X509_REQ_get_extensions(req);
+
+ for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
+ X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
+ ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext);
+ int idx = X509_get_ext_by_OBJ(x, obj, -1);
+
+ /* Does extension exist in target? */
+ if (idx != -1) {
+ /* If normal copy don't override existing extension */
+ if (copy_type == EXT_COPY_ADD)
+ continue;
+ /* Delete all extensions of same type */
+ do {
+ X509_EXTENSION_free(X509_delete_ext(x, idx));
+ idx = X509_get_ext_by_OBJ(x, obj, -1);
+ } while (idx != -1);
+ }
+ if (!X509_add_ext(x, ext, -1))
+ goto end;
+ }
+ ret = 1;
+
+ end:
+ sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+ return ret;
+}
+
+static int set_multi_opts(unsigned long *flags, const char *arg,
+ const NAME_EX_TBL * in_tbl)
+{
+ STACK_OF(CONF_VALUE) *vals;
+ CONF_VALUE *val;
+ int i, ret = 1;
+ if (!arg)
+ return 0;
+ vals = X509V3_parse_list(arg);
+ for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
+ val = sk_CONF_VALUE_value(vals, i);
+ if (!set_table_opts(flags, val->name, in_tbl))
+ ret = 0;
+ }
+ sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
+ return ret;
+}
+
+static int set_table_opts(unsigned long *flags, const char *arg,
+ const NAME_EX_TBL * in_tbl)
+{
+ char c;
+ const NAME_EX_TBL *ptbl;
+ c = arg[0];
+
+ if (c == '-') {
+ c = 0;
+ arg++;
+ } else if (c == '+') {
+ c = 1;
+ arg++;
+ } else {
+ c = 1;
+ }
+
+ for (ptbl = in_tbl; ptbl->name; ptbl++) {
+ if (OPENSSL_strcasecmp(arg, ptbl->name) == 0) {
+ *flags &= ~ptbl->mask;
+ if (c)
+ *flags |= ptbl->flag;
+ else
+ *flags &= ~ptbl->flag;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void print_name(BIO *out, const char *title, const X509_NAME *nm)
+{
+ char *buf;
+ char mline = 0;
+ int indent = 0;
+ unsigned long lflags = get_nameopt();
+
+ if (out == NULL)
+ return;
+ if (title != NULL)
+ BIO_puts(out, title);
+ if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
+ mline = 1;
+ indent = 4;
+ }
+ if (lflags == XN_FLAG_COMPAT) {
+ buf = X509_NAME_oneline(nm, 0, 0);
+ BIO_puts(out, buf);
+ BIO_puts(out, "\n");
+ OPENSSL_free(buf);
+ } else {
+ if (mline)
+ BIO_puts(out, "\n");
+ X509_NAME_print_ex(out, nm, indent, lflags);
+ BIO_puts(out, "\n");
+ }
+}
+
+void print_bignum_var(BIO *out, const BIGNUM *in, const char *var,
+ int len, unsigned char *buffer)
+{
+ BIO_printf(out, " static unsigned char %s_%d[] = {", var, len);
+ if (BN_is_zero(in)) {
+ BIO_printf(out, "\n 0x00");
+ } else {
+ int i, l;
+
+ l = BN_bn2bin(in, buffer);
+ for (i = 0; i < l; i++) {
+ BIO_printf(out, (i % 10) == 0 ? "\n " : " ");
+ if (i < l - 1)
+ BIO_printf(out, "0x%02X,", buffer[i]);
+ else
+ BIO_printf(out, "0x%02X", buffer[i]);
+ }
+ }
+ BIO_printf(out, "\n };\n");
+}
+
+void print_array(BIO *out, const char* title, int len, const unsigned char* d)
+{
+ int i;
+
+ BIO_printf(out, "unsigned char %s[%d] = {", title, len);
+ for (i = 0; i < len; i++) {
+ if ((i % 10) == 0)
+ BIO_printf(out, "\n ");
+ if (i < len - 1)
+ BIO_printf(out, "0x%02X, ", d[i]);
+ else
+ BIO_printf(out, "0x%02X", d[i]);
+ }
+ BIO_printf(out, "\n};\n");
+}
+
+X509_STORE *setup_verify(const char *CAfile, int noCAfile,
+ const char *CApath, int noCApath,
+ const char *CAstore, int noCAstore)
+{
+ X509_STORE *store = X509_STORE_new();
+ X509_LOOKUP *lookup;
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
+ const char *propq = app_get0_propq();
+
+ if (store == NULL)
+ goto end;
+
+ if (CAfile != NULL || !noCAfile) {
+ lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
+ if (lookup == NULL)
+ goto end;
+ if (CAfile != NULL) {
+ if (X509_LOOKUP_load_file_ex(lookup, CAfile, X509_FILETYPE_PEM,
+ libctx, propq) <= 0) {
+ BIO_printf(bio_err, "Error loading file %s\n", CAfile);
+ goto end;
+ }
+ } else {
+ X509_LOOKUP_load_file_ex(lookup, NULL, X509_FILETYPE_DEFAULT,
+ libctx, propq);
+ }
+ }
+
+ if (CApath != NULL || !noCApath) {
+ lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
+ if (lookup == NULL)
+ goto end;
+ if (CApath != NULL) {
+ if (X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM) <= 0) {
+ BIO_printf(bio_err, "Error loading directory %s\n", CApath);
+ goto end;
+ }
+ } else {
+ X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
+ }
+ }
+
+ if (CAstore != NULL || !noCAstore) {
+ lookup = X509_STORE_add_lookup(store, X509_LOOKUP_store());
+ if (lookup == NULL)
+ goto end;
+ if (!X509_LOOKUP_add_store_ex(lookup, CAstore, libctx, propq)) {
+ if (CAstore != NULL)
+ BIO_printf(bio_err, "Error loading store URI %s\n", CAstore);
+ goto end;
+ }
+ }
+
+ ERR_clear_error();
+ return store;
+ end:
+ ERR_print_errors(bio_err);
+ X509_STORE_free(store);
+ return NULL;
+}
+
+static unsigned long index_serial_hash(const OPENSSL_CSTRING *a)
+{
+ const char *n;
+
+ n = a[DB_serial];
+ while (*n == '0')
+ n++;
+ return OPENSSL_LH_strhash(n);
+}
+
+static int index_serial_cmp(const OPENSSL_CSTRING *a,
+ const OPENSSL_CSTRING *b)
+{
+ const char *aa, *bb;
+
+ for (aa = a[DB_serial]; *aa == '0'; aa++) ;
+ for (bb = b[DB_serial]; *bb == '0'; bb++) ;
+ return strcmp(aa, bb);
+}
+
+static int index_name_qual(char **a)
+{
+ return (a[0][0] == 'V');
+}
+
+static unsigned long index_name_hash(const OPENSSL_CSTRING *a)
+{
+ return OPENSSL_LH_strhash(a[DB_name]);
+}
+
+int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b)
+{
+ return strcmp(a[DB_name], b[DB_name]);
+}
+
+static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING)
+static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING)
+static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING)
+static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING)
+#undef BSIZE
+#define BSIZE 256
+BIGNUM *load_serial(const char *serialfile, int *exists, int create,
+ ASN1_INTEGER **retai)
+{
+ BIO *in = NULL;
+ BIGNUM *ret = NULL;
+ char buf[1024];
+ ASN1_INTEGER *ai = NULL;
+
+ ai = ASN1_INTEGER_new();
+ if (ai == NULL)
+ goto err;
+
+ in = BIO_new_file(serialfile, "r");
+ if (exists != NULL)
+ *exists = in != NULL;
+ if (in == NULL) {
+ if (!create) {
+ perror(serialfile);
+ goto err;
+ }
+ ERR_clear_error();
+ ret = BN_new();
+ if (ret == NULL) {
+ BIO_printf(bio_err, "Out of memory\n");
+ } else if (!rand_serial(ret, ai)) {
+ BIO_printf(bio_err, "Error creating random number to store in %s\n",
+ serialfile);
+ BN_free(ret);
+ ret = NULL;
+ }
+ } else {
+ if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) {
+ BIO_printf(bio_err, "Unable to load number from %s\n",
+ serialfile);
+ goto err;
+ }
+ ret = ASN1_INTEGER_to_BN(ai, NULL);
+ if (ret == NULL) {
+ BIO_printf(bio_err, "Error converting number from bin to BIGNUM\n");
+ goto err;
+ }
+ }
+
+ if (ret != NULL && retai != NULL) {
+ *retai = ai;
+ ai = NULL;
+ }
+ err:
+ if (ret == NULL)
+ ERR_print_errors(bio_err);
+ BIO_free(in);
+ ASN1_INTEGER_free(ai);
+ return ret;
+}
+
+int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial,
+ ASN1_INTEGER **retai)
+{
+ char buf[1][BSIZE];
+ BIO *out = NULL;
+ int ret = 0;
+ ASN1_INTEGER *ai = NULL;
+ int j;
+
+ if (suffix == NULL)
+ j = strlen(serialfile);
+ else
+ j = strlen(serialfile) + strlen(suffix) + 1;
+ if (j >= BSIZE) {
+ BIO_printf(bio_err, "File name too long\n");
+ goto err;
+ }
+
+ if (suffix == NULL)
+ OPENSSL_strlcpy(buf[0], serialfile, BSIZE);
+ else {
+#ifndef OPENSSL_SYS_VMS
+ j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, suffix);
+#else
+ j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, suffix);
+#endif
+ }
+ out = BIO_new_file(buf[0], "w");
+ if (out == NULL) {
+ goto err;
+ }
+
+ if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) {
+ BIO_printf(bio_err, "error converting serial to ASN.1 format\n");
+ goto err;
+ }
+ i2a_ASN1_INTEGER(out, ai);
+ BIO_puts(out, "\n");
+ ret = 1;
+ if (retai) {
+ *retai = ai;
+ ai = NULL;
+ }
+ err:
+ if (!ret)
+ ERR_print_errors(bio_err);
+ BIO_free_all(out);
+ ASN1_INTEGER_free(ai);
+ return ret;
+}
+
+int rotate_serial(const char *serialfile, const char *new_suffix,
+ const char *old_suffix)
+{
+ char buf[2][BSIZE];
+ int i, j;
+
+ i = strlen(serialfile) + strlen(old_suffix);
+ j = strlen(serialfile) + strlen(new_suffix);
+ if (i > j)
+ j = i;
+ if (j + 1 >= BSIZE) {
+ BIO_printf(bio_err, "File name too long\n");
+ goto err;
+ }
+#ifndef OPENSSL_SYS_VMS
+ j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, new_suffix);
+ j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", serialfile, old_suffix);
+#else
+ j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, new_suffix);
+ j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", serialfile, old_suffix);
+#endif
+ if (rename(serialfile, buf[1]) < 0 && errno != ENOENT
+#ifdef ENOTDIR
+ && errno != ENOTDIR
+#endif
+ ) {
+ BIO_printf(bio_err,
+ "Unable to rename %s to %s\n", serialfile, buf[1]);
+ perror("reason");
+ goto err;
+ }
+ if (rename(buf[0], serialfile) < 0) {
+ BIO_printf(bio_err,
+ "Unable to rename %s to %s\n", buf[0], serialfile);
+ perror("reason");
+ rename(buf[1], serialfile);
+ goto err;
+ }
+ return 1;
+ err:
+ ERR_print_errors(bio_err);
+ return 0;
+}
+
+int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
+{
+ BIGNUM *btmp;
+ int ret = 0;
+
+ btmp = b == NULL ? BN_new() : b;
+ if (btmp == NULL)
+ return 0;
+
+ if (!BN_rand(btmp, SERIAL_RAND_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
+ goto error;
+ if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
+ goto error;
+
+ ret = 1;
+
+ error:
+
+ if (btmp != b)
+ BN_free(btmp);
+
+ return ret;
+}
+
+CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr)
+{
+ CA_DB *retdb = NULL;
+ TXT_DB *tmpdb = NULL;
+ BIO *in;
+ CONF *dbattr_conf = NULL;
+ char buf[BSIZE];
+#ifndef OPENSSL_NO_POSIX_IO
+ FILE *dbfp;
+ struct stat dbst;
+#endif
+
+ in = BIO_new_file(dbfile, "r");
+ if (in == NULL)
+ goto err;
+
+#ifndef OPENSSL_NO_POSIX_IO
+ BIO_get_fp(in, &dbfp);
+ if (fstat(fileno(dbfp), &dbst) == -1) {
+ ERR_raise_data(ERR_LIB_SYS, errno,
+ "calling fstat(%s)", dbfile);
+ goto err;
+ }
+#endif
+
+ if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL)
+ goto err;
+
+#ifndef OPENSSL_SYS_VMS
+ BIO_snprintf(buf, sizeof(buf), "%s.attr", dbfile);
+#else
+ BIO_snprintf(buf, sizeof(buf), "%s-attr", dbfile);
+#endif
+ dbattr_conf = app_load_config_quiet(buf);
+
+ retdb = app_malloc(sizeof(*retdb), "new DB");
+ retdb->db = tmpdb;
+ tmpdb = NULL;
+ if (db_attr)
+ retdb->attributes = *db_attr;
+ else {
+ retdb->attributes.unique_subject = 1;
+ }
+
+ if (dbattr_conf) {
+ char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject");
+ if (p) {
+ retdb->attributes.unique_subject = parse_yesno(p, 1);
+ }
+ }
+
+ retdb->dbfname = OPENSSL_strdup(dbfile);
+#ifndef OPENSSL_NO_POSIX_IO
+ retdb->dbst = dbst;
+#endif
+
+ err:
+ ERR_print_errors(bio_err);
+ NCONF_free(dbattr_conf);
+ TXT_DB_free(tmpdb);
+ BIO_free_all(in);
+ return retdb;
+}
+
+/*
+ * Returns > 0 on success, <= 0 on error
+ */
+int index_index(CA_DB *db)
+{
+ if (!TXT_DB_create_index(db->db, DB_serial, NULL,
+ LHASH_HASH_FN(index_serial),
+ LHASH_COMP_FN(index_serial))) {
+ BIO_printf(bio_err,
+ "Error creating serial number index:(%ld,%ld,%ld)\n",
+ db->db->error, db->db->arg1, db->db->arg2);
+ goto err;
+ }
+
+ if (db->attributes.unique_subject
+ && !TXT_DB_create_index(db->db, DB_name, index_name_qual,
+ LHASH_HASH_FN(index_name),
+ LHASH_COMP_FN(index_name))) {
+ BIO_printf(bio_err, "Error creating name index:(%ld,%ld,%ld)\n",
+ db->db->error, db->db->arg1, db->db->arg2);
+ goto err;
+ }
+ return 1;
+ err:
+ ERR_print_errors(bio_err);
+ return 0;
+}
+
+int save_index(const char *dbfile, const char *suffix, CA_DB *db)
+{
+ char buf[3][BSIZE];
+ BIO *out;
+ int j;
+
+ j = strlen(dbfile) + strlen(suffix);
+ if (j + 6 >= BSIZE) {
+ BIO_printf(bio_err, "File name too long\n");
+ goto err;
+ }
+#ifndef OPENSSL_SYS_VMS
+ j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr", dbfile);
+ j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.attr.%s", dbfile, suffix);
+ j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, suffix);
+#else
+ j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr", dbfile);
+ j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-attr-%s", dbfile, suffix);
+ j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, suffix);
+#endif
+ out = BIO_new_file(buf[0], "w");
+ if (out == NULL) {
+ perror(dbfile);
+ BIO_printf(bio_err, "Unable to open '%s'\n", dbfile);
+ goto err;
+ }
+ j = TXT_DB_write(out, db->db);
+ BIO_free(out);
+ if (j <= 0)
+ goto err;
+
+ out = BIO_new_file(buf[1], "w");
+ if (out == NULL) {
+ perror(buf[2]);
+ BIO_printf(bio_err, "Unable to open '%s'\n", buf[2]);
+ goto err;
+ }
+ BIO_printf(out, "unique_subject = %s\n",
+ db->attributes.unique_subject ? "yes" : "no");
+ BIO_free(out);
+
+ return 1;
+ err:
+ ERR_print_errors(bio_err);
+ return 0;
+}
+
+int rotate_index(const char *dbfile, const char *new_suffix,
+ const char *old_suffix)
+{
+ char buf[5][BSIZE];
+ int i, j;
+
+ i = strlen(dbfile) + strlen(old_suffix);
+ j = strlen(dbfile) + strlen(new_suffix);
+ if (i > j)
+ j = i;
+ if (j + 6 >= BSIZE) {
+ BIO_printf(bio_err, "File name too long\n");
+ goto err;
+ }
+#ifndef OPENSSL_SYS_VMS
+ j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s.attr", dbfile);
+ j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s.attr.%s", dbfile, old_suffix);
+ j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr.%s", dbfile, new_suffix);
+ j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", dbfile, old_suffix);
+ j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, new_suffix);
+#else
+ j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s-attr", dbfile);
+ j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s-attr-%s", dbfile, old_suffix);
+ j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr-%s", dbfile, new_suffix);
+ j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", dbfile, old_suffix);
+ j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, new_suffix);
+#endif
+ if (rename(dbfile, buf[1]) < 0 && errno != ENOENT
+#ifdef ENOTDIR
+ && errno != ENOTDIR
+#endif
+ ) {
+ BIO_printf(bio_err, "Unable to rename %s to %s\n", dbfile, buf[1]);
+ perror("reason");
+ goto err;
+ }
+ if (rename(buf[0], dbfile) < 0) {
+ BIO_printf(bio_err, "Unable to rename %s to %s\n", buf[0], dbfile);
+ perror("reason");
+ rename(buf[1], dbfile);
+ goto err;
+ }
+ if (rename(buf[4], buf[3]) < 0 && errno != ENOENT
+#ifdef ENOTDIR
+ && errno != ENOTDIR
+#endif
+ ) {
+ BIO_printf(bio_err, "Unable to rename %s to %s\n", buf[4], buf[3]);
+ perror("reason");
+ rename(dbfile, buf[0]);
+ rename(buf[1], dbfile);
+ goto err;
+ }
+ if (rename(buf[2], buf[4]) < 0) {
+ BIO_printf(bio_err, "Unable to rename %s to %s\n", buf[2], buf[4]);
+ perror("reason");
+ rename(buf[3], buf[4]);
+ rename(dbfile, buf[0]);
+ rename(buf[1], dbfile);
+ goto err;
+ }
+ return 1;
+ err:
+ ERR_print_errors(bio_err);
+ return 0;
+}
+
+void free_index(CA_DB *db)
+{
+ if (db) {
+ TXT_DB_free(db->db);
+ OPENSSL_free(db->dbfname);
+ OPENSSL_free(db);
+ }
+}
+
+int parse_yesno(const char *str, int def)
+{
+ if (str) {
+ switch (*str) {
+ case 'f': /* false */
+ case 'F': /* FALSE */
+ case 'n': /* no */
+ case 'N': /* NO */
+ case '0': /* 0 */
+ return 0;
+ case 't': /* true */
+ case 'T': /* TRUE */
+ case 'y': /* yes */
+ case 'Y': /* YES */
+ case '1': /* 1 */
+ return 1;
+ }
+ }
+ return def;
+}
+
+/*
+ * name is expected to be in the format /type0=value0/type1=value1/type2=...
+ * where + can be used instead of / to form multi-valued RDNs if canmulti
+ * and characters may be escaped by \
+ */
+X509_NAME *parse_name(const char *cp, int chtype, int canmulti,
+ const char *desc)
+{
+ int nextismulti = 0;
+ char *work;
+ X509_NAME *n;
+
+ if (*cp++ != '/') {
+ BIO_printf(bio_err,
+ "%s: %s name is expected to be in the format "
+ "/type0=value0/type1=value1/type2=... where characters may "
+ "be escaped by \\. This name is not in that format: '%s'\n",
+ opt_getprog(), desc, --cp);
+ return NULL;
+ }
+
+ n = X509_NAME_new();
+ if (n == NULL) {
+ BIO_printf(bio_err, "%s: Out of memory\n", opt_getprog());
+ return NULL;
+ }
+ work = OPENSSL_strdup(cp);
+ if (work == NULL) {
+ BIO_printf(bio_err, "%s: Error copying %s name input\n",
+ opt_getprog(), desc);
+ goto err;
+ }
+
+ while (*cp != '\0') {
+ char *bp = work;
+ char *typestr = bp;
+ unsigned char *valstr;
+ int nid;
+ int ismulti = nextismulti;
+ nextismulti = 0;
+
+ /* Collect the type */
+ while (*cp != '\0' && *cp != '=')
+ *bp++ = *cp++;
+ *bp++ = '\0';
+ if (*cp == '\0') {
+ BIO_printf(bio_err,
+ "%s: Missing '=' after RDN type string '%s' in %s name string\n",
+ opt_getprog(), typestr, desc);
+ goto err;
+ }
+ ++cp;
+
+ /* Collect the value. */
+ valstr = (unsigned char *)bp;
+ for (; *cp != '\0' && *cp != '/'; *bp++ = *cp++) {
+ /* unescaped '+' symbol string signals further member of multiRDN */
+ if (canmulti && *cp == '+') {
+ nextismulti = 1;
+ break;
+ }
+ if (*cp == '\\' && *++cp == '\0') {
+ BIO_printf(bio_err,
+ "%s: Escape character at end of %s name string\n",
+ opt_getprog(), desc);
+ goto err;
+ }
+ }
+ *bp++ = '\0';
+
+ /* If not at EOS (must be + or /), move forward. */
+ if (*cp != '\0')
+ ++cp;
+
+ /* Parse */
+ nid = OBJ_txt2nid(typestr);
+ if (nid == NID_undef) {
+ BIO_printf(bio_err,
+ "%s: Skipping unknown %s name attribute \"%s\"\n",
+ opt_getprog(), desc, typestr);
+ if (ismulti)
+ BIO_printf(bio_err,
+ "Hint: a '+' in a value string needs be escaped using '\\' else a new member of a multi-valued RDN is expected\n");
+ continue;
+ }
+ if (*valstr == '\0') {
+ BIO_printf(bio_err,
+ "%s: No value provided for %s name attribute \"%s\", skipped\n",
+ opt_getprog(), desc, typestr);
+ continue;
+ }
+ if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
+ valstr, strlen((char *)valstr),
+ -1, ismulti ? -1 : 0)) {
+ ERR_print_errors(bio_err);
+ BIO_printf(bio_err,
+ "%s: Error adding %s name attribute \"/%s=%s\"\n",
+ opt_getprog(), desc, typestr ,valstr);
+ goto err;
+ }
+ }
+
+ OPENSSL_free(work);
+ return n;
+
+ err:
+ X509_NAME_free(n);
+ OPENSSL_free(work);
+ return NULL;
+}
+
+/*
+ * Read whole contents of a BIO into an allocated memory buffer and return
+ * it.
+ */
+
+int bio_to_mem(unsigned char **out, int maxlen, BIO *in)
+{
+ BIO *mem;
+ int len, ret;
+ unsigned char tbuf[1024];
+
+ mem = BIO_new(BIO_s_mem());
+ if (mem == NULL)
+ return -1;
+ for (;;) {
+ if ((maxlen != -1) && maxlen < 1024)
+ len = maxlen;
+ else
+ len = 1024;
+ len = BIO_read(in, tbuf, len);
+ if (len < 0) {
+ BIO_free(mem);
+ return -1;
+ }
+ if (len == 0)
+ break;
+ if (BIO_write(mem, tbuf, len) != len) {
+ BIO_free(mem);
+ return -1;
+ }
+ maxlen -= len;
+
+ if (maxlen == 0)
+ break;
+ }
+ ret = BIO_get_mem_data(mem, (char **)out);
+ BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY);
+ BIO_free(mem);
+ return ret;
+}
+
+int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value)
+{
+ int rv = 0;
+ char *stmp, *vtmp = NULL;
+
+ stmp = OPENSSL_strdup(value);
+ if (stmp == NULL)
+ return -1;
+ vtmp = strchr(stmp, ':');
+ if (vtmp == NULL)
+ goto err;
+
+ *vtmp = 0;
+ vtmp++;
+ rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp);
+
+ err:
+ OPENSSL_free(stmp);
+ return rv;
+}
+
+static void nodes_print(const char *name, STACK_OF(X509_POLICY_NODE) *nodes)
+{
+ X509_POLICY_NODE *node;
+ int i;
+
+ BIO_printf(bio_err, "%s Policies:", name);
+ if (nodes) {
+ BIO_puts(bio_err, "\n");
+ for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) {
+ node = sk_X509_POLICY_NODE_value(nodes, i);
+ X509_POLICY_NODE_print(bio_err, node, 2);
+ }
+ } else {
+ BIO_puts(bio_err, " <empty>\n");
+ }
+}
+
+void policies_print(X509_STORE_CTX *ctx)
+{
+ X509_POLICY_TREE *tree;
+ int explicit_policy;
+ tree = X509_STORE_CTX_get0_policy_tree(ctx);
+ explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx);
+
+ BIO_printf(bio_err, "Require explicit Policy: %s\n",
+ explicit_policy ? "True" : "False");
+
+ nodes_print("Authority", X509_policy_tree_get0_policies(tree));
+ nodes_print("User", X509_policy_tree_get0_user_policies(tree));
+}
+
+/*-
+ * next_protos_parse parses a comma separated list of strings into a string
+ * in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
+ * outlen: (output) set to the length of the resulting buffer on success.
+ * err: (maybe NULL) on failure, an error message line is written to this BIO.
+ * in: a NUL terminated string like "abc,def,ghi"
+ *
+ * returns: a malloc'd buffer or NULL on failure.
+ */
+unsigned char *next_protos_parse(size_t *outlen, const char *in)
+{
+ size_t len;
+ unsigned char *out;
+ size_t i, start = 0;
+ size_t skipped = 0;
+
+ len = strlen(in);
+ if (len == 0 || len >= 65535)
+ return NULL;
+
+ out = app_malloc(len + 1, "NPN buffer");
+ for (i = 0; i <= len; ++i) {
+ if (i == len || in[i] == ',') {
+ /*
+ * Zero-length ALPN elements are invalid on the wire, we could be
+ * strict and reject the entire string, but just ignoring extra
+ * commas seems harmless and more friendly.
+ *
+ * Every comma we skip in this way puts the input buffer another
+ * byte ahead of the output buffer, so all stores into the output
+ * buffer need to be decremented by the number commas skipped.
+ */
+ if (i == start) {
+ ++start;
+ ++skipped;
+ continue;
+ }
+ if (i - start > 255) {
+ OPENSSL_free(out);
+ return NULL;
+ }
+ out[start-skipped] = (unsigned char)(i - start);
+ start = i + 1;
+ } else {
+ out[i + 1 - skipped] = in[i];
+ }
+ }
+
+ if (len <= skipped) {
+ OPENSSL_free(out);
+ return NULL;
+ }
+
+ *outlen = len + 1 - skipped;
+ return out;
+}
+
+void print_cert_checks(BIO *bio, X509 *x,
+ const char *checkhost,
+ const char *checkemail, const char *checkip)
+{
+ if (x == NULL)
+ return;
+ if (checkhost) {
+ BIO_printf(bio, "Hostname %s does%s match certificate\n",
+ checkhost,
+ X509_check_host(x, checkhost, 0, 0, NULL) == 1
+ ? "" : " NOT");
+ }
+
+ if (checkemail) {
+ BIO_printf(bio, "Email %s does%s match certificate\n",
+ checkemail, X509_check_email(x, checkemail, 0, 0)
+ ? "" : " NOT");
+ }
+
+ if (checkip) {
+ BIO_printf(bio, "IP %s does%s match certificate\n",
+ checkip, X509_check_ip_asc(x, checkip, 0) ? "" : " NOT");
+ }
+}
+
+static int do_pkey_ctx_init(EVP_PKEY_CTX *pkctx, STACK_OF(OPENSSL_STRING) *opts)
+{
+ int i;
+
+ if (opts == NULL)
+ return 1;
+
+ for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) {
+ char *opt = sk_OPENSSL_STRING_value(opts, i);
+ if (pkey_ctrl_string(pkctx, opt) <= 0) {
+ BIO_printf(bio_err, "parameter error \"%s\"\n", opt);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int do_x509_init(X509 *x, STACK_OF(OPENSSL_STRING) *opts)
+{
+ int i;
+
+ if (opts == NULL)
+ return 1;
+
+ for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) {
+ char *opt = sk_OPENSSL_STRING_value(opts, i);
+ if (x509_ctrl_string(x, opt) <= 0) {
+ BIO_printf(bio_err, "parameter error \"%s\"\n", opt);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int do_x509_req_init(X509_REQ *x, STACK_OF(OPENSSL_STRING) *opts)
+{
+ int i;
+
+ if (opts == NULL)
+ return 1;
+
+ for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) {
+ char *opt = sk_OPENSSL_STRING_value(opts, i);
+ if (x509_req_ctrl_string(x, opt) <= 0) {
+ BIO_printf(bio_err, "parameter error \"%s\"\n", opt);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey,
+ const char *md, STACK_OF(OPENSSL_STRING) *sigopts)
+{
+ EVP_PKEY_CTX *pkctx = NULL;
+ char def_md[80];
+
+ if (ctx == NULL)
+ return 0;
+ /*
+ * EVP_PKEY_get_default_digest_name() returns 2 if the digest is mandatory
+ * for this algorithm.
+ */
+ if (EVP_PKEY_get_default_digest_name(pkey, def_md, sizeof(def_md)) == 2
+ && strcmp(def_md, "UNDEF") == 0) {
+ /* The signing algorithm requires there to be no digest */
+ md = NULL;
+ }
+
+ return EVP_DigestSignInit_ex(ctx, &pkctx, md, app_get0_libctx(),
+ app_get0_propq(), pkey, NULL)
+ && do_pkey_ctx_init(pkctx, sigopts);
+}
+
+static int adapt_keyid_ext(X509 *cert, X509V3_CTX *ext_ctx,
+ const char *name, const char *value, int add_default)
+{
+ const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert);
+ X509_EXTENSION *new_ext = X509V3_EXT_nconf(NULL, ext_ctx, name, value);
+ int idx, rv = 0;
+
+ if (new_ext == NULL)
+ return rv;
+
+ idx = X509v3_get_ext_by_OBJ(exts, X509_EXTENSION_get_object(new_ext), -1);
+ if (idx >= 0) {
+ X509_EXTENSION *found_ext = X509v3_get_ext(exts, idx);
+ ASN1_OCTET_STRING *data = X509_EXTENSION_get_data(found_ext);
+ int disabled = ASN1_STRING_length(data) <= 2; /* config said "none" */
+
+ if (disabled) {
+ X509_delete_ext(cert, idx);
+ X509_EXTENSION_free(found_ext);
+ } /* else keep existing key identifier, which might be outdated */
+ rv = 1;
+ } else {
+ rv = !add_default || X509_add_ext(cert, new_ext, -1);
+ }
+ X509_EXTENSION_free(new_ext);
+ return rv;
+}
+
+/* Ensure RFC 5280 compliance, adapt keyIDs as needed, and sign the cert info */
+int do_X509_sign(X509 *cert, EVP_PKEY *pkey, const char *md,
+ STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx)
+{
+ const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert);
+ EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+ int self_sign;
+ int rv = 0;
+
+ if (sk_X509_EXTENSION_num(exts /* may be NULL */) > 0) {
+ /* Prevent X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3 */
+ if (!X509_set_version(cert, X509_VERSION_3))
+ goto end;
+
+ /*
+ * Add default SKID before such that default AKID can make use of it
+ * in case the certificate is self-signed
+ */
+ /* Prevent X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER */
+ if (!adapt_keyid_ext(cert, ext_ctx, "subjectKeyIdentifier", "hash", 1))
+ goto end;
+ /* Prevent X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER */
+ ERR_set_mark();
+ self_sign = X509_check_private_key(cert, pkey);
+ ERR_pop_to_mark();
+ if (!adapt_keyid_ext(cert, ext_ctx, "authorityKeyIdentifier",
+ "keyid, issuer", !self_sign))
+ goto end;
+ }
+
+ if (mctx != NULL && do_sign_init(mctx, pkey, md, sigopts) > 0)
+ rv = (X509_sign_ctx(cert, mctx) > 0);
+ end:
+ EVP_MD_CTX_free(mctx);
+ return rv;
+}
+
+/* Sign the certificate request info */
+int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const char *md,
+ STACK_OF(OPENSSL_STRING) *sigopts)
+{
+ int rv = 0;
+ EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+
+ if (do_sign_init(mctx, pkey, md, sigopts) > 0)
+ rv = (X509_REQ_sign_ctx(x, mctx) > 0);
+ EVP_MD_CTX_free(mctx);
+ return rv;
+}
+
+/* Sign the CRL info */
+int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const char *md,
+ STACK_OF(OPENSSL_STRING) *sigopts)
+{
+ int rv = 0;
+ EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+
+ if (do_sign_init(mctx, pkey, md, sigopts) > 0)
+ rv = (X509_CRL_sign_ctx(x, mctx) > 0);
+ EVP_MD_CTX_free(mctx);
+ return rv;
+}
+
+/*
+ * do_X509_verify returns 1 if the signature is valid,
+ * 0 if the signature check fails, or -1 if error occurs.
+ */
+int do_X509_verify(X509 *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts)
+{
+ int rv = 0;
+
+ if (do_x509_init(x, vfyopts) > 0)
+ rv = X509_verify(x, pkey);
+ else
+ rv = -1;
+ return rv;
+}
+
+/*
+ * do_X509_REQ_verify returns 1 if the signature is valid,
+ * 0 if the signature check fails, or -1 if error occurs.
+ */
+int do_X509_REQ_verify(X509_REQ *x, EVP_PKEY *pkey,
+ STACK_OF(OPENSSL_STRING) *vfyopts)
+{
+ int rv = 0;
+
+ if (do_x509_req_init(x, vfyopts) > 0)
+ rv = X509_REQ_verify_ex(x, pkey,
+ app_get0_libctx(), app_get0_propq());
+ else
+ rv = -1;
+ return rv;
+}
+
+/* Get first http URL from a DIST_POINT structure */
+
+static const char *get_dp_url(DIST_POINT *dp)
+{
+ GENERAL_NAMES *gens;
+ GENERAL_NAME *gen;
+ int i, gtype;
+ ASN1_STRING *uri;
+ if (!dp->distpoint || dp->distpoint->type != 0)
+ return NULL;
+ gens = dp->distpoint->name.fullname;
+ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+ gen = sk_GENERAL_NAME_value(gens, i);
+ uri = GENERAL_NAME_get0_value(gen, &gtype);
+ if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6) {
+ const char *uptr = (const char *)ASN1_STRING_get0_data(uri);
+
+ if (IS_HTTP(uptr)) /* can/should not use HTTPS here */
+ return uptr;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Look through a CRLDP structure and attempt to find an http URL to
+ * downloads a CRL from.
+ */
+
+static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp)
+{
+ int i;
+ const char *urlptr = NULL;
+ for (i = 0; i < sk_DIST_POINT_num(crldp); i++) {
+ DIST_POINT *dp = sk_DIST_POINT_value(crldp, i);
+ urlptr = get_dp_url(dp);
+ if (urlptr != NULL)
+ return load_crl(urlptr, FORMAT_UNDEF, 0, "CRL via CDP");
+ }
+ return NULL;
+}
+
+/*
+ * Example of downloading CRLs from CRLDP:
+ * not usable for real world as it always downloads and doesn't cache anything.
+ */
+
+static STACK_OF(X509_CRL) *crls_http_cb(const X509_STORE_CTX *ctx,
+ const X509_NAME *nm)
+{
+ X509 *x;
+ STACK_OF(X509_CRL) *crls = NULL;
+ X509_CRL *crl;
+ STACK_OF(DIST_POINT) *crldp;
+
+ crls = sk_X509_CRL_new_null();
+ if (!crls)
+ return NULL;
+ x = X509_STORE_CTX_get_current_cert(ctx);
+ crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
+ crl = load_crl_crldp(crldp);
+ sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
+ if (!crl) {
+ sk_X509_CRL_free(crls);
+ return NULL;
+ }
+ sk_X509_CRL_push(crls, crl);
+ /* Try to download delta CRL */
+ crldp = X509_get_ext_d2i(x, NID_freshest_crl, NULL, NULL);
+ crl = load_crl_crldp(crldp);
+ sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
+ if (crl)
+ sk_X509_CRL_push(crls, crl);
+ return crls;
+}
+
+void store_setup_crl_download(X509_STORE *st)
+{
+ X509_STORE_set_lookup_crls_cb(st, crls_http_cb);
+}
+
+#ifndef OPENSSL_NO_SOCK
+static const char *tls_error_hint(void)
+{
+ unsigned long err = ERR_peek_error();
+
+ if (ERR_GET_LIB(err) != ERR_LIB_SSL)
+ err = ERR_peek_last_error();
+ if (ERR_GET_LIB(err) != ERR_LIB_SSL)
+ return NULL;
+
+ switch (ERR_GET_REASON(err)) {
+ case SSL_R_WRONG_VERSION_NUMBER:
+ return "The server does not support (a suitable version of) TLS";
+ case SSL_R_UNKNOWN_PROTOCOL:
+ return "The server does not support HTTPS";
+ case SSL_R_CERTIFICATE_VERIFY_FAILED:
+ return "Cannot authenticate server via its TLS certificate, likely due to mismatch with our trusted TLS certs or missing revocation status";
+ case SSL_AD_REASON_OFFSET + TLS1_AD_UNKNOWN_CA:
+ return "Server did not accept our TLS certificate, likely due to mismatch with server's trust anchor or missing revocation status";
+ case SSL_AD_REASON_OFFSET + SSL3_AD_HANDSHAKE_FAILURE:
+ return "TLS handshake failure. Possibly the server requires our TLS certificate but did not receive it";
+ default: /* no error or no hint available for error */
+ return NULL;
+ }
+}
+
+/* HTTP callback function that supports TLS connection also via HTTPS proxy */
+BIO *app_http_tls_cb(BIO *bio, void *arg, int connect, int detail)
+{
+ APP_HTTP_TLS_INFO *info = (APP_HTTP_TLS_INFO *)arg;
+ SSL_CTX *ssl_ctx = info->ssl_ctx;
+
+ if (ssl_ctx == NULL) /* not using TLS */
+ return bio;
+ if (connect) {
+ SSL *ssl;
+ BIO *sbio = NULL;
+
+ /* adapt after fixing callback design flaw, see #17088 */
+ if ((info->use_proxy
+ && !OSSL_HTTP_proxy_connect(bio, info->server, info->port,
+ NULL, NULL, /* no proxy credentials */
+ info->timeout, bio_err, opt_getprog()))
+ || (sbio = BIO_new(BIO_f_ssl())) == NULL) {
+ return NULL;
+ }
+ if (ssl_ctx == NULL || (ssl = SSL_new(ssl_ctx)) == NULL) {
+ BIO_free(sbio);
+ return NULL;
+ }
+
+ /* adapt after fixing callback design flaw, see #17088 */
+ SSL_set_tlsext_host_name(ssl, info->server); /* not critical to do */
+
+ SSL_set_connect_state(ssl);
+ BIO_set_ssl(sbio, ssl, BIO_CLOSE);
+
+ bio = BIO_push(sbio, bio);
+ }
+ if (!connect) {
+ const char *hint;
+ BIO *cbio;
+
+ if (!detail) { /* disconnecting after error */
+ hint = tls_error_hint();
+ if (hint != NULL)
+ ERR_add_error_data(2, " : ", hint);
+ }
+ if (ssl_ctx != NULL) {
+ (void)ERR_set_mark();
+ BIO_ssl_shutdown(bio);
+ cbio = BIO_pop(bio); /* connect+HTTP BIO */
+ BIO_free(bio); /* SSL BIO */
+ (void)ERR_pop_to_mark(); /* hide SSL_R_READ_BIO_NOT_SET etc. */
+ bio = cbio;
+ }
+ }
+ return bio;
+}
+
+void APP_HTTP_TLS_INFO_free(APP_HTTP_TLS_INFO *info)
+{
+ if (info != NULL) {
+ SSL_CTX_free(info->ssl_ctx);
+ OPENSSL_free(info);
+ }
+}
+
+ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy,
+ const char *no_proxy, SSL_CTX *ssl_ctx,
+ const STACK_OF(CONF_VALUE) *headers,
+ long timeout, const char *expected_content_type,
+ const ASN1_ITEM *it)
+{
+ APP_HTTP_TLS_INFO info;
+ char *server;
+ char *port;
+ int use_ssl;
+ BIO *mem;
+ ASN1_VALUE *resp = NULL;
+
+ if (url == NULL || it == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+
+ if (!OSSL_HTTP_parse_url(url, &use_ssl, NULL /* userinfo */, &server, &port,
+ NULL /* port_num, */, NULL, NULL, NULL))
+ return NULL;
+ if (use_ssl && ssl_ctx == NULL) {
+ ERR_raise_data(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER,
+ "missing SSL_CTX");
+ goto end;
+ }
+ if (!use_ssl && ssl_ctx != NULL) {
+ ERR_raise_data(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT,
+ "SSL_CTX given but use_ssl == 0");
+ goto end;
+ }
+
+ info.server = server;
+ info.port = port;
+ info.use_proxy = /* workaround for callback design flaw, see #17088 */
+ OSSL_HTTP_adapt_proxy(proxy, no_proxy, server, use_ssl) != NULL;
+ info.timeout = timeout;
+ info.ssl_ctx = ssl_ctx;
+ mem = OSSL_HTTP_get(url, proxy, no_proxy, NULL /* bio */, NULL /* rbio */,
+ app_http_tls_cb, &info, 0 /* buf_size */, headers,
+ expected_content_type, 1 /* expect_asn1 */,
+ OSSL_HTTP_DEFAULT_MAX_RESP_LEN, timeout);
+ resp = ASN1_item_d2i_bio(it, mem, NULL);
+ BIO_free(mem);
+
+ end:
+ OPENSSL_free(server);
+ OPENSSL_free(port);
+ return resp;
+
+}
+
+ASN1_VALUE *app_http_post_asn1(const char *host, const char *port,
+ const char *path, const char *proxy,
+ const char *no_proxy, SSL_CTX *ssl_ctx,
+ const STACK_OF(CONF_VALUE) *headers,
+ const char *content_type,
+ ASN1_VALUE *req, const ASN1_ITEM *req_it,
+ const char *expected_content_type,
+ long timeout, const ASN1_ITEM *rsp_it)
+{
+ int use_ssl = ssl_ctx != NULL;
+ APP_HTTP_TLS_INFO info;
+ BIO *rsp, *req_mem = ASN1_item_i2d_mem_bio(req_it, req);
+ ASN1_VALUE *res;
+
+ if (req_mem == NULL)
+ return NULL;
+
+ info.server = host;
+ info.port = port;
+ info.use_proxy = /* workaround for callback design flaw, see #17088 */
+ OSSL_HTTP_adapt_proxy(proxy, no_proxy, host, use_ssl) != NULL;
+ info.timeout = timeout;
+ info.ssl_ctx = ssl_ctx;
+ rsp = OSSL_HTTP_transfer(NULL, host, port, path, use_ssl,
+ proxy, no_proxy, NULL /* bio */, NULL /* rbio */,
+ app_http_tls_cb, &info,
+ 0 /* buf_size */, headers, content_type, req_mem,
+ expected_content_type, 1 /* expect_asn1 */,
+ OSSL_HTTP_DEFAULT_MAX_RESP_LEN, timeout,
+ 0 /* keep_alive */);
+ BIO_free(req_mem);
+ res = ASN1_item_d2i_bio(rsp_it, rsp, NULL);
+ BIO_free(rsp);
+ return res;
+}
+
+#endif
+
+/*
+ * Platform-specific sections
+ */
+#if defined(_WIN32)
+# ifdef fileno
+# undef fileno
+# define fileno(a) (int)_fileno(a)
+# endif
+
+# include <windows.h>
+# include <tchar.h>
+
+static int WIN32_rename(const char *from, const char *to)
+{
+ TCHAR *tfrom = NULL, *tto;
+ DWORD err;
+ int ret = 0;
+
+ if (sizeof(TCHAR) == 1) {
+ tfrom = (TCHAR *)from;
+ tto = (TCHAR *)to;
+ } else { /* UNICODE path */
+
+ size_t i, flen = strlen(from) + 1, tlen = strlen(to) + 1;
+ tfrom = malloc(sizeof(*tfrom) * (flen + tlen));
+ if (tfrom == NULL)
+ goto err;
+ tto = tfrom + flen;
+# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
+ if (!MultiByteToWideChar(CP_ACP, 0, from, flen, (WCHAR *)tfrom, flen))
+# endif
+ for (i = 0; i < flen; i++)
+ tfrom[i] = (TCHAR)from[i];
+# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
+ if (!MultiByteToWideChar(CP_ACP, 0, to, tlen, (WCHAR *)tto, tlen))
+# endif
+ for (i = 0; i < tlen; i++)
+ tto[i] = (TCHAR)to[i];
+ }
+
+ if (MoveFile(tfrom, tto))
+ goto ok;
+ err = GetLastError();
+ if (err == ERROR_ALREADY_EXISTS || err == ERROR_FILE_EXISTS) {
+ if (DeleteFile(tto) && MoveFile(tfrom, tto))
+ goto ok;
+ err = GetLastError();
+ }
+ if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
+ errno = ENOENT;
+ else if (err == ERROR_ACCESS_DENIED)
+ errno = EACCES;
+ else
+ errno = EINVAL; /* we could map more codes... */
+ err:
+ ret = -1;
+ ok:
+ if (tfrom != NULL && tfrom != (TCHAR *)from)
+ free(tfrom);
+ return ret;
+}
+#endif
+
+/* app_tminterval section */
+#if defined(_WIN32)
+double app_tminterval(int stop, int usertime)
+{
+ FILETIME now;
+ double ret = 0;
+ static ULARGE_INTEGER tmstart;
+ static int warning = 1;
+# ifdef _WIN32_WINNT
+ static HANDLE proc = NULL;
+
+ if (proc == NULL) {
+ if (check_winnt())
+ proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE,
+ GetCurrentProcessId());
+ if (proc == NULL)
+ proc = (HANDLE) - 1;
+ }
+
+ if (usertime && proc != (HANDLE) - 1) {
+ FILETIME junk;
+ GetProcessTimes(proc, &junk, &junk, &junk, &now);
+ } else
+# endif
+ {
+ SYSTEMTIME systime;
+
+ if (usertime && warning) {
+ BIO_printf(bio_err, "To get meaningful results, run "
+ "this program on idle system.\n");
+ warning = 0;
+ }
+ GetSystemTime(&systime);
+ SystemTimeToFileTime(&systime, &now);
+ }
+
+ if (stop == TM_START) {
+ tmstart.u.LowPart = now.dwLowDateTime;
+ tmstart.u.HighPart = now.dwHighDateTime;
+ } else {
+ ULARGE_INTEGER tmstop;
+
+ tmstop.u.LowPart = now.dwLowDateTime;
+ tmstop.u.HighPart = now.dwHighDateTime;
+
+ ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart) * 1e-7;
+ }
+
+ return ret;
+}
+#elif defined(OPENSSL_SYS_VXWORKS)
+# include <time.h>
+
+double app_tminterval(int stop, int usertime)
+{
+ double ret = 0;
+# ifdef CLOCK_REALTIME
+ static struct timespec tmstart;
+ struct timespec now;
+# else
+ static unsigned long tmstart;
+ unsigned long now;
+# endif
+ static int warning = 1;
+
+ if (usertime && warning) {
+ BIO_printf(bio_err, "To get meaningful results, run "
+ "this program on idle system.\n");
+ warning = 0;
+ }
+# ifdef CLOCK_REALTIME
+ clock_gettime(CLOCK_REALTIME, &now);
+ if (stop == TM_START)
+ tmstart = now;
+ else
+ ret = ((now.tv_sec + now.tv_nsec * 1e-9)
+ - (tmstart.tv_sec + tmstart.tv_nsec * 1e-9));
+# else
+ now = tickGet();
+ if (stop == TM_START)
+ tmstart = now;
+ else
+ ret = (now - tmstart) / (double)sysClkRateGet();
+# endif
+ return ret;
+}
+
+#elif defined(_SC_CLK_TCK) /* by means of unistd.h */
+# include <sys/times.h>
+
+double app_tminterval(int stop, int usertime)
+{
+ double ret = 0;
+ struct tms rus;
+ clock_t now = times(&rus);
+ static clock_t tmstart;
+
+ if (usertime)
+ now = rus.tms_utime;
+
+ if (stop == TM_START) {
+ tmstart = now;
+ } else {
+ long int tck = sysconf(_SC_CLK_TCK);
+ ret = (now - tmstart) / (double)tck;
+ }
+
+ return ret;
+}
+
+#else
+# include <sys/time.h>
+# include <sys/resource.h>
+
+double app_tminterval(int stop, int usertime)
+{
+ double ret = 0;
+ struct rusage rus;
+ struct timeval now;
+ static struct timeval tmstart;
+
+ if (usertime)
+ getrusage(RUSAGE_SELF, &rus), now = rus.ru_utime;
+ else
+ gettimeofday(&now, NULL);
+
+ if (stop == TM_START)
+ tmstart = now;
+ else
+ ret = ((now.tv_sec + now.tv_usec * 1e-6)
+ - (tmstart.tv_sec + tmstart.tv_usec * 1e-6));
+
+ return ret;
+}
+#endif
+
+int app_access(const char* name, int flag)
+{
+#ifdef _WIN32
+ return _access(name, flag);
+#else
+ return access(name, flag);
+#endif
+}
+
+int app_isdir(const char *name)
+{
+ return opt_isdir(name);
+}
+
+/* raw_read|write section */
+#if defined(__VMS)
+# include "vms_term_sock.h"
+static int stdin_sock = -1;
+
+static void close_stdin_sock(void)
+{
+ TerminalSocket (TERM_SOCK_DELETE, &stdin_sock);
+}
+
+int fileno_stdin(void)
+{
+ if (stdin_sock == -1) {
+ TerminalSocket(TERM_SOCK_CREATE, &stdin_sock);
+ atexit(close_stdin_sock);
+ }
+
+ return stdin_sock;
+}
+#else
+int fileno_stdin(void)
+{
+ return fileno(stdin);
+}
+#endif
+
+int fileno_stdout(void)
+{
+ return fileno(stdout);
+}
+
+#if defined(_WIN32) && defined(STD_INPUT_HANDLE)
+int raw_read_stdin(void *buf, int siz)
+{
+ DWORD n;
+ if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, siz, &n, NULL))
+ return n;
+ else
+ return -1;
+}
+#elif defined(__VMS)
+# include <sys/socket.h>
+
+int raw_read_stdin(void *buf, int siz)
+{
+ return recv(fileno_stdin(), buf, siz, 0);
+}
+#else
+# if defined(__TANDEM)
+# if defined(OPENSSL_TANDEM_FLOSS)
+# include <floss.h(floss_read)>
+# endif
+# endif
+int raw_read_stdin(void *buf, int siz)
+{
+ return read(fileno_stdin(), buf, siz);
+}
+#endif
+
+#if defined(_WIN32) && defined(STD_OUTPUT_HANDLE)
+int raw_write_stdout(const void *buf, int siz)
+{
+ DWORD n;
+ if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, siz, &n, NULL))
+ return n;
+ else
+ return -1;
+}
+#elif defined(OPENSSL_SYS_TANDEM) && defined(OPENSSL_THREADS) && defined(_SPT_MODEL_)
+# if defined(__TANDEM)
+# if defined(OPENSSL_TANDEM_FLOSS)
+# include <floss.h(floss_write)>
+# endif
+# endif
+int raw_write_stdout(const void *buf,int siz)
+{
+ return write(fileno(stdout),(void*)buf,siz);
+}
+#else
+# if defined(__TANDEM)
+# if defined(OPENSSL_TANDEM_FLOSS)
+# include <floss.h(floss_write)>
+# endif
+# endif
+int raw_write_stdout(const void *buf, int siz)
+{
+ return write(fileno_stdout(), buf, siz);
+}
+#endif
+
+/*
+ * Centralized handling of input and output files with format specification
+ * The format is meant to show what the input and output is supposed to be,
+ * and is therefore a show of intent more than anything else. However, it
+ * does impact behavior on some platforms, such as differentiating between
+ * text and binary input/output on non-Unix platforms
+ */
+BIO *dup_bio_in(int format)
+{
+ return BIO_new_fp(stdin,
+ BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0));
+}
+
+BIO *dup_bio_out(int format)
+{
+ BIO *b = BIO_new_fp(stdout,
+ BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0));
+ void *prefix = NULL;
+
+ if (b == NULL)
+ return NULL;
+
+#ifdef OPENSSL_SYS_VMS
+ if (FMT_istext(format))
+ b = BIO_push(BIO_new(BIO_f_linebuffer()), b);
+#endif
+
+ if (FMT_istext(format)
+ && (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) {
+ b = BIO_push(BIO_new(BIO_f_prefix()), b);
+ BIO_set_prefix(b, prefix);
+ }
+
+ return b;
+}
+
+BIO *dup_bio_err(int format)
+{
+ BIO *b = BIO_new_fp(stderr,
+ BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0));
+#ifdef OPENSSL_SYS_VMS
+ if (b != NULL && FMT_istext(format))
+ b = BIO_push(BIO_new(BIO_f_linebuffer()), b);
+#endif
+ return b;
+}
+
+void unbuffer(FILE *fp)
+{
+/*
+ * On VMS, setbuf() will only take 32-bit pointers, and a compilation
+ * with /POINTER_SIZE=64 will give off a MAYLOSEDATA2 warning here.
+ * However, we trust that the C RTL will never give us a FILE pointer
+ * above the first 4 GB of memory, so we simply turn off the warning
+ * temporarily.
+ */
+#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
+# pragma environment save
+# pragma message disable maylosedata2
+#endif
+ setbuf(fp, NULL);
+#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
+# pragma environment restore
+#endif
+}
+
+static const char *modestr(char mode, int format)
+{
+ OPENSSL_assert(mode == 'a' || mode == 'r' || mode == 'w');
+
+ switch (mode) {
+ case 'a':
+ return FMT_istext(format) ? "a" : "ab";
+ case 'r':
+ return FMT_istext(format) ? "r" : "rb";
+ case 'w':
+ return FMT_istext(format) ? "w" : "wb";
+ }
+ /* The assert above should make sure we never reach this point */
+ return NULL;
+}
+
+static const char *modeverb(char mode)
+{
+ switch (mode) {
+ case 'a':
+ return "appending";
+ case 'r':
+ return "reading";
+ case 'w':
+ return "writing";
+ }
+ return "(doing something)";
+}
+
+/*
+ * Open a file for writing, owner-read-only.
+ */
+BIO *bio_open_owner(const char *filename, int format, int private)
+{
+ FILE *fp = NULL;
+ BIO *b = NULL;
+ int textmode, bflags;
+#ifndef OPENSSL_NO_POSIX_IO
+ int fd = -1, mode;
+#endif
+
+ if (!private || filename == NULL || strcmp(filename, "-") == 0)
+ return bio_open_default(filename, 'w', format);
+
+ textmode = FMT_istext(format);
+#ifndef OPENSSL_NO_POSIX_IO
+ mode = O_WRONLY;
+# ifdef O_CREAT
+ mode |= O_CREAT;
+# endif
+# ifdef O_TRUNC
+ mode |= O_TRUNC;
+# endif
+ if (!textmode) {
+# ifdef O_BINARY
+ mode |= O_BINARY;
+# elif defined(_O_BINARY)
+ mode |= _O_BINARY;
+# endif
+ }
+
+# ifdef OPENSSL_SYS_VMS
+ /* VMS doesn't have O_BINARY, it just doesn't make sense. But,
+ * it still needs to know that we're going binary, or fdopen()
+ * will fail with "invalid argument"... so we tell VMS what the
+ * context is.
+ */
+ if (!textmode)
+ fd = open(filename, mode, 0600, "ctx=bin");
+ else
+# endif
+ fd = open(filename, mode, 0600);
+ if (fd < 0)
+ goto err;
+ fp = fdopen(fd, modestr('w', format));
+#else /* OPENSSL_NO_POSIX_IO */
+ /* Have stdio but not Posix IO, do the best we can */
+ fp = fopen(filename, modestr('w', format));
+#endif /* OPENSSL_NO_POSIX_IO */
+ if (fp == NULL)
+ goto err;
+ bflags = BIO_CLOSE;
+ if (textmode)
+ bflags |= BIO_FP_TEXT;
+ b = BIO_new_fp(fp, bflags);
+ if (b != NULL)
+ return b;
+
+ err:
+ BIO_printf(bio_err, "%s: Can't open \"%s\" for writing, %s\n",
+ opt_getprog(), filename, strerror(errno));
+ ERR_print_errors(bio_err);
+ /* If we have fp, then fdopen took over fd, so don't close both. */
+ if (fp != NULL)
+ fclose(fp);
+#ifndef OPENSSL_NO_POSIX_IO
+ else if (fd >= 0)
+ close(fd);
+#endif
+ return NULL;
+}
+
+static BIO *bio_open_default_(const char *filename, char mode, int format,
+ int quiet)
+{
+ BIO *ret;
+
+ if (filename == NULL || strcmp(filename, "-") == 0) {
+ ret = mode == 'r' ? dup_bio_in(format) : dup_bio_out(format);
+ if (quiet) {
+ ERR_clear_error();
+ return ret;
+ }
+ if (ret != NULL)
+ return ret;
+ BIO_printf(bio_err,
+ "Can't open %s, %s\n",
+ mode == 'r' ? "stdin" : "stdout", strerror(errno));
+ } else {
+ ret = BIO_new_file(filename, modestr(mode, format));
+ if (quiet) {
+ ERR_clear_error();
+ return ret;
+ }
+ if (ret != NULL)
+ return ret;
+ BIO_printf(bio_err,
+ "Can't open \"%s\" for %s, %s\n",
+ filename, modeverb(mode), strerror(errno));
+ }
+ ERR_print_errors(bio_err);
+ return NULL;
+}
+
+BIO *bio_open_default(const char *filename, char mode, int format)
+{
+ return bio_open_default_(filename, mode, format, 0);
+}
+
+BIO *bio_open_default_quiet(const char *filename, char mode, int format)
+{
+ return bio_open_default_(filename, mode, format, 1);
+}
+
+void wait_for_async(SSL *s)
+{
+ /* On Windows select only works for sockets, so we simply don't wait */
+#ifndef OPENSSL_SYS_WINDOWS
+ int width = 0;
+ fd_set asyncfds;
+ OSSL_ASYNC_FD *fds;
+ size_t numfds;
+ size_t i;
+
+ if (!SSL_get_all_async_fds(s, NULL, &numfds))
+ return;
+ if (numfds == 0)
+ return;
+ fds = app_malloc(sizeof(OSSL_ASYNC_FD) * numfds, "allocate async fds");
+ if (!SSL_get_all_async_fds(s, fds, &numfds)) {
+ OPENSSL_free(fds);
+ return;
+ }
+
+ FD_ZERO(&asyncfds);
+ for (i = 0; i < numfds; i++) {
+ if (width <= (int)fds[i])
+ width = (int)fds[i] + 1;
+ openssl_fdset((int)fds[i], &asyncfds);
+ }
+ select(width, (void *)&asyncfds, NULL, NULL, NULL);
+ OPENSSL_free(fds);
+#endif
+}
+
+/* if OPENSSL_SYS_WINDOWS is defined then so is OPENSSL_SYS_MSDOS */
+#if defined(OPENSSL_SYS_MSDOS)
+int has_stdin_waiting(void)
+{
+# if defined(OPENSSL_SYS_WINDOWS)
+ HANDLE inhand = GetStdHandle(STD_INPUT_HANDLE);
+ DWORD events = 0;
+ INPUT_RECORD inputrec;
+ DWORD insize = 1;
+ BOOL peeked;
+
+ if (inhand == INVALID_HANDLE_VALUE) {
+ return 0;
+ }
+
+ peeked = PeekConsoleInput(inhand, &inputrec, insize, &events);
+ if (!peeked) {
+ /* Probably redirected input? _kbhit() does not work in this case */
+ if (!feof(stdin)) {
+ return 1;
+ }
+ return 0;
+ }
+# endif
+ return _kbhit();
+}
+#endif
+
+/* Corrupt a signature by modifying final byte */
+void corrupt_signature(const ASN1_STRING *signature)
+{
+ unsigned char *s = signature->data;
+ s[signature->length - 1] ^= 0x1;
+}
+
+int set_cert_times(X509 *x, const char *startdate, const char *enddate,
+ int days)
+{
+ if (startdate == NULL || strcmp(startdate, "today") == 0) {
+ if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL)
+ return 0;
+ } else {
+ if (!ASN1_TIME_set_string_X509(X509_getm_notBefore(x), startdate))
+ return 0;
+ }
+ if (enddate == NULL) {
+ if (X509_time_adj_ex(X509_getm_notAfter(x), days, 0, NULL)
+ == NULL)
+ return 0;
+ } else if (!ASN1_TIME_set_string_X509(X509_getm_notAfter(x), enddate)) {
+ return 0;
+ }
+ return 1;
+}
+
+int set_crl_lastupdate(X509_CRL *crl, const char *lastupdate)
+{
+ int ret = 0;
+ ASN1_TIME *tm = ASN1_TIME_new();
+
+ if (tm == NULL)
+ goto end;
+
+ if (lastupdate == NULL) {
+ if (X509_gmtime_adj(tm, 0) == NULL)
+ goto end;
+ } else {
+ if (!ASN1_TIME_set_string_X509(tm, lastupdate))
+ goto end;
+ }
+
+ if (!X509_CRL_set1_lastUpdate(crl, tm))
+ goto end;
+
+ ret = 1;
+end:
+ ASN1_TIME_free(tm);
+ return ret;
+}
+
+int set_crl_nextupdate(X509_CRL *crl, const char *nextupdate,
+ long days, long hours, long secs)
+{
+ int ret = 0;
+ ASN1_TIME *tm = ASN1_TIME_new();
+
+ if (tm == NULL)
+ goto end;
+
+ if (nextupdate == NULL) {
+ if (X509_time_adj_ex(tm, days, hours * 60 * 60 + secs, NULL) == NULL)
+ goto end;
+ } else {
+ if (!ASN1_TIME_set_string_X509(tm, nextupdate))
+ goto end;
+ }
+
+ if (!X509_CRL_set1_nextUpdate(crl, tm))
+ goto end;
+
+ ret = 1;
+end:
+ ASN1_TIME_free(tm);
+ return ret;
+}
+
+void make_uppercase(char *string)
+{
+ int i;
+
+ for (i = 0; string[i] != '\0'; i++)
+ string[i] = toupper((unsigned char)string[i]);
+}
+
+/* This function is defined here due to visibility of bio_err */
+int opt_printf_stderr(const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = BIO_vprintf(bio_err, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+OSSL_PARAM *app_params_new_from_opts(STACK_OF(OPENSSL_STRING) *opts,
+ const OSSL_PARAM *paramdefs)
+{
+ OSSL_PARAM *params = NULL;
+ size_t sz = (size_t)sk_OPENSSL_STRING_num(opts);
+ size_t params_n;
+ char *opt = "", *stmp, *vtmp = NULL;
+ int found = 1;
+
+ if (opts == NULL)
+ return NULL;
+
+ params = OPENSSL_zalloc(sizeof(OSSL_PARAM) * (sz + 1));
+ if (params == NULL)
+ return NULL;
+
+ for (params_n = 0; params_n < sz; params_n++) {
+ opt = sk_OPENSSL_STRING_value(opts, (int)params_n);
+ if ((stmp = OPENSSL_strdup(opt)) == NULL
+ || (vtmp = strchr(stmp, ':')) == NULL)
+ goto err;
+ /* Replace ':' with 0 to terminate the string pointed to by stmp */
+ *vtmp = 0;
+ /* Skip over the separator so that vmtp points to the value */
+ vtmp++;
+ if (!OSSL_PARAM_allocate_from_text(&params[params_n], paramdefs,
+ stmp, vtmp, strlen(vtmp), &found))
+ goto err;
+ OPENSSL_free(stmp);
+ }
+ params[params_n] = OSSL_PARAM_construct_end();
+ return params;
+err:
+ OPENSSL_free(stmp);
+ BIO_printf(bio_err, "Parameter %s '%s'\n", found ? "error" : "unknown",
+ opt);
+ ERR_print_errors(bio_err);
+ app_params_free(params);
+ return NULL;
+}
+
+void app_params_free(OSSL_PARAM *params)
+{
+ int i;
+
+ if (params != NULL) {
+ for (i = 0; params[i].key != NULL; ++i)
+ OPENSSL_free(params[i].data);
+ OPENSSL_free(params);
+ }
+}
+
+EVP_PKEY *app_keygen(EVP_PKEY_CTX *ctx, const char *alg, int bits, int verbose)
+{
+ EVP_PKEY *res = NULL;
+
+ if (verbose && alg != NULL) {
+ BIO_printf(bio_err, "Generating %s key", alg);
+ if (bits > 0)
+ BIO_printf(bio_err, " with %d bits\n", bits);
+ else
+ BIO_printf(bio_err, "\n");
+ }
+ if (!RAND_status())
+ BIO_printf(bio_err, "Warning: generating random key material may take a long time\n"
+ "if the system has a poor entropy source\n");
+ if (EVP_PKEY_keygen(ctx, &res) <= 0)
+ app_bail_out("%s: Error generating %s key\n", opt_getprog(),
+ alg != NULL ? alg : "asymmetric");
+ return res;
+}
+
+EVP_PKEY *app_paramgen(EVP_PKEY_CTX *ctx, const char *alg)
+{
+ EVP_PKEY *res = NULL;
+
+ if (!RAND_status())
+ BIO_printf(bio_err, "Warning: generating random key parameters may take a long time\n"
+ "if the system has a poor entropy source\n");
+ if (EVP_PKEY_paramgen(ctx, &res) <= 0)
+ app_bail_out("%s: Generating %s key parameters failed\n",
+ opt_getprog(), alg != NULL ? alg : "asymmetric");
+ return res;
+}
+
+/*
+ * Return non-zero if the legacy path is still an option.
+ * This decision is based on the global command line operations and the
+ * behaviour thus far.
+ */
+int opt_legacy_okay(void)
+{
+ int provider_options = opt_provider_option_given();
+ int libctx = app_get0_libctx() != NULL || app_get0_propq() != NULL;
+ /*
+ * Having a provider option specified or a custom library context or
+ * property query, is a sure sign we're not using legacy.
+ */
+ if (provider_options || libctx)
+ return 0;
+ return 1;
+}
diff --git a/apps/lib/apps_ui.c b/apps/lib/apps_ui.c
new file mode 100644
index 000000000000..00e0ba5d9996
--- /dev/null
+++ b/apps/lib/apps_ui.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/err.h>
+#include <openssl/ui.h>
+#include "apps_ui.h"
+
+static UI_METHOD *ui_method = NULL;
+static const UI_METHOD *ui_base_method = NULL;
+
+static int ui_open(UI *ui)
+{
+ int (*opener)(UI *ui) = UI_method_get_opener(ui_base_method);
+
+ if (opener != NULL)
+ return opener(ui);
+ return 1;
+}
+
+static int ui_read(UI *ui, UI_STRING *uis)
+{
+ int (*reader)(UI *ui, UI_STRING *uis) = NULL;
+
+ if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
+ && UI_get0_user_data(ui)) {
+ switch (UI_get_string_type(uis)) {
+ case UIT_PROMPT:
+ case UIT_VERIFY:
+ {
+ const char *password =
+ ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
+
+ if (password != NULL) {
+ UI_set_result(ui, uis, password);
+ return 1;
+ }
+ }
+ break;
+ case UIT_NONE:
+ case UIT_BOOLEAN:
+ case UIT_INFO:
+ case UIT_ERROR:
+ break;
+ }
+ }
+
+ reader = UI_method_get_reader(ui_base_method);
+ if (reader != NULL)
+ return reader(ui, uis);
+ /* Default to the empty password if we've got nothing better */
+ UI_set_result(ui, uis, "");
+ return 1;
+}
+
+static int ui_write(UI *ui, UI_STRING *uis)
+{
+ int (*writer)(UI *ui, UI_STRING *uis) = NULL;
+
+ if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
+ && UI_get0_user_data(ui)) {
+ switch (UI_get_string_type(uis)) {
+ case UIT_PROMPT:
+ case UIT_VERIFY:
+ {
+ const char *password =
+ ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
+
+ if (password != NULL)
+ return 1;
+ }
+ break;
+ case UIT_NONE:
+ case UIT_BOOLEAN:
+ case UIT_INFO:
+ case UIT_ERROR:
+ break;
+ }
+ }
+
+ writer = UI_method_get_writer(ui_base_method);
+ if (writer != NULL)
+ return writer(ui, uis);
+ return 1;
+}
+
+static int ui_close(UI *ui)
+{
+ int (*closer)(UI *ui) = UI_method_get_closer(ui_base_method);
+
+ if (closer != NULL)
+ return closer(ui);
+ return 1;
+}
+
+/* object_name defaults to prompt_info from ui user data if present */
+static char *ui_prompt_construct(UI *ui, const char *phrase_desc,
+ const char *object_name)
+{
+ PW_CB_DATA *cb_data = (PW_CB_DATA *)UI_get0_user_data(ui);
+
+ if (phrase_desc == NULL)
+ phrase_desc = "pass phrase";
+ if (object_name == NULL && cb_data != NULL)
+ object_name = cb_data->prompt_info;
+ return UI_construct_prompt(NULL, phrase_desc, object_name);
+}
+
+int set_base_ui_method(const UI_METHOD *ui_meth)
+{
+ if (ui_meth == NULL)
+ ui_meth = UI_null();
+ ui_base_method = ui_meth;
+ return 1;
+}
+
+int setup_ui_method(void)
+{
+ ui_base_method = UI_null();
+#ifndef OPENSSL_NO_UI_CONSOLE
+ ui_base_method = UI_OpenSSL();
+#endif
+ ui_method = UI_create_method("OpenSSL application user interface");
+ return ui_method != NULL
+ && 0 == UI_method_set_opener(ui_method, ui_open)
+ && 0 == UI_method_set_reader(ui_method, ui_read)
+ && 0 == UI_method_set_writer(ui_method, ui_write)
+ && 0 == UI_method_set_closer(ui_method, ui_close)
+ && 0 == UI_method_set_prompt_constructor(ui_method,
+ ui_prompt_construct);
+}
+
+void destroy_ui_method(void)
+{
+ if (ui_method != NULL) {
+ UI_destroy_method(ui_method);
+ ui_method = NULL;
+ }
+}
+
+const UI_METHOD *get_ui_method(void)
+{
+ return ui_method;
+}
+
+static void *ui_malloc(int sz, const char *what)
+{
+ void *vp = OPENSSL_malloc(sz);
+
+ if (vp == NULL) {
+ BIO_printf(bio_err, "Could not allocate %d bytes for %s\n", sz, what);
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ return vp;
+}
+
+int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data)
+{
+ int res = 0;
+ UI *ui;
+ int ok = 0;
+ char *buff = NULL;
+ int ui_flags = 0;
+ const char *prompt_info = NULL;
+ char *prompt;
+
+ if ((ui = UI_new_method(ui_method)) == NULL)
+ return 0;
+
+ if (cb_data != NULL && cb_data->prompt_info != NULL)
+ prompt_info = cb_data->prompt_info;
+ prompt = UI_construct_prompt(ui, "pass phrase", prompt_info);
+ if (prompt == NULL) {
+ BIO_printf(bio_err, "Out of memory\n");
+ UI_free(ui);
+ return 0;
+ }
+
+ ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
+ UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
+
+ /* We know that there is no previous user data to return to us */
+ (void)UI_add_user_data(ui, cb_data);
+
+ ok = UI_add_input_string(ui, prompt, ui_flags, buf,
+ PW_MIN_LENGTH, bufsiz - 1);
+
+ if (ok >= 0 && verify) {
+ buff = ui_malloc(bufsiz, "password buffer");
+ ok = UI_add_verify_string(ui, prompt, ui_flags, buff,
+ PW_MIN_LENGTH, bufsiz - 1, buf);
+ }
+ if (ok >= 0)
+ do {
+ ok = UI_process(ui);
+ } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
+
+ OPENSSL_clear_free(buff, (unsigned int)bufsiz);
+
+ if (ok >= 0)
+ res = strlen(buf);
+ if (ok == -1) {
+ BIO_printf(bio_err, "User interface error\n");
+ ERR_print_errors(bio_err);
+ OPENSSL_cleanse(buf, (unsigned int)bufsiz);
+ res = 0;
+ }
+ if (ok == -2) {
+ BIO_printf(bio_err, "aborted!\n");
+ OPENSSL_cleanse(buf, (unsigned int)bufsiz);
+ res = 0;
+ }
+ UI_free(ui);
+ OPENSSL_free(prompt);
+ return res;
+}
diff --git a/apps/lib/build.info b/apps/lib/build.info
new file mode 100644
index 000000000000..923ef5d92b83
--- /dev/null
+++ b/apps/lib/build.info
@@ -0,0 +1,23 @@
+# Auxiliary program source
+IF[{- $config{target} =~ /^(?:VC-|mingw|BC-)/ -}]
+ # It's called 'init', but doesn't have much 'init' in it...
+ $AUXLIBAPPSSRC=win32_init.c
+ENDIF
+IF[{- $config{target} =~ /^vms-/ -}]
+ $AUXLIBAPPSSRC=vms_term_sock.c vms_decc_argv.c
+ENDIF
+
+# Source for libapps
+$LIBAPPSSRC=apps.c apps_ui.c opt.c fmt.c s_cb.c s_socket.c app_rand.c \
+ columns.c app_params.c names.c app_provider.c app_x509.c http_server.c \
+ engine.c engine_loader.c app_libctx.c
+
+IF[{- !$disabled{apps} -}]
+ LIBS{noinst}=../libapps.a
+ SOURCE[../libapps.a]=$LIBAPPSSRC $AUXLIBAPPSSRC
+ INCLUDE[../libapps.a]=../.. ../../include ../include
+ENDIF
+
+IF[{- !$disabled{srp} -}]
+ SOURCE[../libapps.a]=tlssrp_depr.c
+ENDIF
diff --git a/apps/lib/cmp_mock_srv.c b/apps/lib/cmp_mock_srv.c
new file mode 100644
index 000000000000..b37f3dd3d89c
--- /dev/null
+++ b/apps/lib/cmp_mock_srv.c
@@ -0,0 +1,450 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Siemens AG 2018-2020
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or atf
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "apps.h"
+#include "cmp_mock_srv.h"
+
+#include <openssl/cmp.h>
+#include <openssl/err.h>
+#include <openssl/cmperr.h>
+
+/* the context for the CMP mock server */
+typedef struct
+{
+ X509 *certOut; /* certificate to be returned in cp/ip/kup msg */
+ STACK_OF(X509) *chainOut; /* chain of certOut to add to extraCerts field */
+ STACK_OF(X509) *caPubsOut; /* certs to return in caPubs field of ip msg */
+ OSSL_CMP_PKISI *statusOut; /* status for ip/cp/kup/rp msg unless polling */
+ int sendError; /* send error response also on valid requests */
+ OSSL_CMP_MSG *certReq; /* ir/cr/p10cr/kur remembered while polling */
+ int certReqId; /* id of last ir/cr/kur, used for polling */
+ int pollCount; /* number of polls before actual cert response */
+ int curr_pollCount; /* number of polls so far for current request */
+ int checkAfterTime; /* time the client should wait between polling */
+} mock_srv_ctx;
+
+
+static void mock_srv_ctx_free(mock_srv_ctx *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ OSSL_CMP_PKISI_free(ctx->statusOut);
+ X509_free(ctx->certOut);
+ sk_X509_pop_free(ctx->chainOut, X509_free);
+ sk_X509_pop_free(ctx->caPubsOut, X509_free);
+ OSSL_CMP_MSG_free(ctx->certReq);
+ OPENSSL_free(ctx);
+}
+
+static mock_srv_ctx *mock_srv_ctx_new(void)
+{
+ mock_srv_ctx *ctx = OPENSSL_zalloc(sizeof(mock_srv_ctx));
+
+ if (ctx == NULL)
+ goto err;
+
+ if ((ctx->statusOut = OSSL_CMP_PKISI_new()) == NULL)
+ goto err;
+
+ ctx->certReqId = -1;
+
+ /* all other elements are initialized to 0 or NULL, respectively */
+ return ctx;
+ err:
+ mock_srv_ctx_free(ctx);
+ return NULL;
+}
+
+int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (cert == NULL || X509_up_ref(cert)) {
+ X509_free(ctx->certOut);
+ ctx->certOut = cert;
+ return 1;
+ }
+ return 0;
+}
+
+int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
+ STACK_OF(X509) *chain)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+ STACK_OF(X509) *chain_copy = NULL;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (chain != NULL && (chain_copy = X509_chain_up_ref(chain)) == NULL)
+ return 0;
+ sk_X509_pop_free(ctx->chainOut, X509_free);
+ ctx->chainOut = chain_copy;
+ return 1;
+}
+
+int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx,
+ STACK_OF(X509) *caPubs)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+ STACK_OF(X509) *caPubs_copy = NULL;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (caPubs != NULL && (caPubs_copy = X509_chain_up_ref(caPubs)) == NULL)
+ return 0;
+ sk_X509_pop_free(ctx->caPubsOut, X509_free);
+ ctx->caPubsOut = caPubs_copy;
+ return 1;
+}
+
+int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status,
+ int fail_info, const char *text)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+ OSSL_CMP_PKISI *si;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if ((si = OSSL_CMP_STATUSINFO_new(status, fail_info, text)) == NULL)
+ return 0;
+ OSSL_CMP_PKISI_free(ctx->statusOut);
+ ctx->statusOut = si;
+ return 1;
+}
+
+int ossl_cmp_mock_srv_set_send_error(OSSL_CMP_SRV_CTX *srv_ctx, int val)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ ctx->sendError = val != 0;
+ return 1;
+}
+
+int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX *srv_ctx, int count)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (count < 0) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
+ return 0;
+ }
+ ctx->pollCount = count;
+ return 1;
+}
+
+int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ ctx->checkAfterTime = sec;
+ return 1;
+}
+
+static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *cert_req,
+ int certReqId,
+ const OSSL_CRMF_MSG *crm,
+ const X509_REQ *p10cr,
+ X509 **certOut,
+ STACK_OF(X509) **chainOut,
+ STACK_OF(X509) **caPubs)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+ OSSL_CMP_PKISI *si = NULL;
+
+ if (ctx == NULL || cert_req == NULL
+ || certOut == NULL || chainOut == NULL || caPubs == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ if (ctx->sendError) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
+ return NULL;
+ }
+
+ *certOut = NULL;
+ *chainOut = NULL;
+ *caPubs = NULL;
+ ctx->certReqId = certReqId;
+
+ if (ctx->pollCount > 0 && ctx->curr_pollCount == 0) {
+ /* start polling */
+ if (ctx->certReq != NULL) {
+ /* already in polling mode */
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ return NULL;
+ }
+ if ((ctx->certReq = OSSL_CMP_MSG_dup(cert_req)) == NULL)
+ return NULL;
+ return OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting, 0, NULL);
+ }
+ if (ctx->curr_pollCount >= ctx->pollCount)
+ /* give final response after polling */
+ ctx->curr_pollCount = 0;
+
+ if (OSSL_CMP_MSG_get_bodytype(cert_req) == OSSL_CMP_KUR
+ && crm != NULL && ctx->certOut != NULL) {
+ const OSSL_CRMF_CERTID *cid = OSSL_CRMF_MSG_get0_regCtrl_oldCertID(crm);
+ const X509_NAME *issuer = X509_get_issuer_name(ctx->certOut);
+ const ASN1_INTEGER *serial = X509_get0_serialNumber(ctx->certOut);
+
+ if (cid == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_CERTID);
+ return NULL;
+ }
+ if (issuer != NULL
+ && X509_NAME_cmp(issuer, OSSL_CRMF_CERTID_get0_issuer(cid)) != 0) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_CERTID);
+ return NULL;
+ }
+ if (serial != NULL
+ && ASN1_INTEGER_cmp(serial,
+ OSSL_CRMF_CERTID_get0_serialNumber(cid)) != 0) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_CERTID);
+ return NULL;
+ }
+ }
+
+ if (ctx->certOut != NULL
+ && (*certOut = X509_dup(ctx->certOut)) == NULL)
+ goto err;
+ if (ctx->chainOut != NULL
+ && (*chainOut = X509_chain_up_ref(ctx->chainOut)) == NULL)
+ goto err;
+ if (ctx->caPubsOut != NULL
+ && (*caPubs = X509_chain_up_ref(ctx->caPubsOut)) == NULL)
+ goto err;
+ if (ctx->statusOut != NULL
+ && (si = OSSL_CMP_PKISI_dup(ctx->statusOut)) == NULL)
+ goto err;
+ return si;
+
+ err:
+ X509_free(*certOut);
+ *certOut = NULL;
+ sk_X509_pop_free(*chainOut, X509_free);
+ *chainOut = NULL;
+ sk_X509_pop_free(*caPubs, X509_free);
+ *caPubs = NULL;
+ return NULL;
+}
+
+static OSSL_CMP_PKISI *process_rr(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *rr,
+ const X509_NAME *issuer,
+ const ASN1_INTEGER *serial)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+ if (ctx == NULL || rr == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ if (ctx->sendError || ctx->certOut == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
+ return NULL;
+ }
+
+ /* Allow any RR derived from CSR, which may include subject and serial */
+ if (issuer == NULL || serial == NULL)
+ return OSSL_CMP_PKISI_dup(ctx->statusOut);
+
+ /* accept revocation only for the certificate we sent in ir/cr/kur */
+ if (X509_NAME_cmp(issuer, X509_get_issuer_name(ctx->certOut)) != 0
+ || ASN1_INTEGER_cmp(serial,
+ X509_get0_serialNumber(ctx->certOut)) != 0) {
+ ERR_raise_data(ERR_LIB_CMP, CMP_R_REQUEST_NOT_ACCEPTED,
+ "wrong certificate to revoke");
+ return NULL;
+ }
+ return OSSL_CMP_PKISI_dup(ctx->statusOut);
+}
+
+static int process_genm(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *genm,
+ const STACK_OF(OSSL_CMP_ITAV) *in,
+ STACK_OF(OSSL_CMP_ITAV) **out)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+ if (ctx == NULL || genm == NULL || in == NULL || out == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (sk_OSSL_CMP_ITAV_num(in) > 1 || ctx->sendError) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
+ return 0;
+ }
+
+ *out = sk_OSSL_CMP_ITAV_deep_copy(in, OSSL_CMP_ITAV_dup,
+ OSSL_CMP_ITAV_free);
+ return *out != NULL;
+}
+
+static void process_error(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *error,
+ const OSSL_CMP_PKISI *statusInfo,
+ const ASN1_INTEGER *errorCode,
+ const OSSL_CMP_PKIFREETEXT *errorDetails)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+ char buf[OSSL_CMP_PKISI_BUFLEN];
+ char *sibuf;
+ int i;
+
+ if (ctx == NULL || error == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return;
+ }
+
+ BIO_printf(bio_err, "mock server received error:\n");
+
+ if (statusInfo == NULL) {
+ BIO_printf(bio_err, "pkiStatusInfo absent\n");
+ } else {
+ sibuf = OSSL_CMP_snprint_PKIStatusInfo(statusInfo, buf, sizeof(buf));
+ BIO_printf(bio_err, "pkiStatusInfo: %s\n",
+ sibuf != NULL ? sibuf: "<invalid>");
+ }
+
+ if (errorCode == NULL)
+ BIO_printf(bio_err, "errorCode absent\n");
+ else
+ BIO_printf(bio_err, "errorCode: %ld\n", ASN1_INTEGER_get(errorCode));
+
+ if (sk_ASN1_UTF8STRING_num(errorDetails) <= 0) {
+ BIO_printf(bio_err, "errorDetails absent\n");
+ } else {
+ BIO_printf(bio_err, "errorDetails: ");
+ for (i = 0; i < sk_ASN1_UTF8STRING_num(errorDetails); i++) {
+ if (i > 0)
+ BIO_printf(bio_err, ", ");
+ BIO_printf(bio_err, "\"");
+ ASN1_STRING_print(bio_err,
+ sk_ASN1_UTF8STRING_value(errorDetails, i));
+ BIO_printf(bio_err, "\"");
+ }
+ BIO_printf(bio_err, "\n");
+ }
+}
+
+static int process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *certConf, int certReqId,
+ const ASN1_OCTET_STRING *certHash,
+ const OSSL_CMP_PKISI *si)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+ ASN1_OCTET_STRING *digest;
+
+ if (ctx == NULL || certConf == NULL || certHash == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (ctx->sendError || ctx->certOut == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
+ return 0;
+ }
+
+ if (certReqId != ctx->certReqId) {
+ /* in case of error, invalid reqId -1 */
+ ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
+ return 0;
+ }
+
+ if ((digest = X509_digest_sig(ctx->certOut, NULL, NULL)) == NULL)
+ return 0;
+ if (ASN1_OCTET_STRING_cmp(certHash, digest) != 0) {
+ ASN1_OCTET_STRING_free(digest);
+ ERR_raise(ERR_LIB_CMP, CMP_R_CERTHASH_UNMATCHED);
+ return 0;
+ }
+ ASN1_OCTET_STRING_free(digest);
+ return 1;
+}
+
+static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *pollReq, int certReqId,
+ OSSL_CMP_MSG **certReq, int64_t *check_after)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+ if (ctx == NULL || pollReq == NULL
+ || certReq == NULL || check_after == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (ctx->sendError) {
+ *certReq = NULL;
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
+ return 0;
+ }
+ if (ctx->certReq == NULL) {
+ /* not currently in polling mode */
+ *certReq = NULL;
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ return 0;
+ }
+
+ if (++ctx->curr_pollCount >= ctx->pollCount) {
+ /* end polling */
+ *certReq = ctx->certReq;
+ ctx->certReq = NULL;
+ *check_after = 0;
+ } else {
+ *certReq = NULL;
+ *check_after = ctx->checkAfterTime;
+ }
+ return 1;
+}
+
+OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, const char *propq)
+{
+ OSSL_CMP_SRV_CTX *srv_ctx = OSSL_CMP_SRV_CTX_new(libctx, propq);
+ mock_srv_ctx *ctx = mock_srv_ctx_new();
+
+ if (srv_ctx != NULL && ctx != NULL
+ && OSSL_CMP_SRV_CTX_init(srv_ctx, ctx, process_cert_request,
+ process_rr, process_genm, process_error,
+ process_certConf, process_pollReq))
+ return srv_ctx;
+
+ mock_srv_ctx_free(ctx);
+ OSSL_CMP_SRV_CTX_free(srv_ctx);
+ return NULL;
+}
+
+void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx)
+{
+ if (srv_ctx != NULL)
+ mock_srv_ctx_free(OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx));
+ OSSL_CMP_SRV_CTX_free(srv_ctx);
+}
diff --git a/apps/lib/columns.c b/apps/lib/columns.c
new file mode 100644
index 000000000000..aa58fe1781f5
--- /dev/null
+++ b/apps/lib/columns.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include "apps.h"
+#include "function.h"
+
+void calculate_columns(FUNCTION *functions, DISPLAY_COLUMNS *dc)
+{
+ FUNCTION *f;
+ int len, maxlen = 0;
+
+ for (f = functions; f->name != NULL; ++f)
+ if (f->type == FT_general || f->type == FT_md || f->type == FT_cipher)
+ if ((len = strlen(f->name)) > maxlen)
+ maxlen = len;
+
+ dc->width = maxlen + 2;
+ dc->columns = (80 - 1) / dc->width;
+}
+
diff --git a/apps/lib/engine.c b/apps/lib/engine.c
new file mode 100644
index 000000000000..209c4b6b03c2
--- /dev/null
+++ b/apps/lib/engine.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Here is a set of wrappers for the ENGINE API, which are no-ops when the
+ * ENGINE API is disabled / removed.
+ * We need to suppress deprecation warnings to make this work.
+ */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include <string.h> /* strcmp */
+
+#include <openssl/types.h> /* Ensure we have the ENGINE type, regardless */
+#include <openssl/err.h>
+#ifndef OPENSSL_NO_ENGINE
+# include <openssl/engine.h>
+#endif
+#include "apps.h"
+
+#ifndef OPENSSL_NO_ENGINE
+/* Try to load an engine in a shareable library */
+static ENGINE *try_load_engine(const char *engine)
+{
+ ENGINE *e = NULL;
+
+ if ((e = ENGINE_by_id("dynamic")) != NULL) {
+ if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0)
+ || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
+ ENGINE_free(e);
+ e = NULL;
+ }
+ }
+ return e;
+}
+#endif
+
+ENGINE *setup_engine_methods(const char *id, unsigned int methods, int debug)
+{
+ ENGINE *e = NULL;
+
+#ifndef OPENSSL_NO_ENGINE
+ if (id != NULL) {
+ if (strcmp(id, "auto") == 0) {
+ BIO_printf(bio_err, "Enabling auto ENGINE support\n");
+ ENGINE_register_all_complete();
+ return NULL;
+ }
+ if ((e = ENGINE_by_id(id)) == NULL
+ && (e = try_load_engine(id)) == NULL) {
+ BIO_printf(bio_err, "Invalid engine \"%s\"\n", id);
+ ERR_print_errors(bio_err);
+ return NULL;
+ }
+ if (debug)
+ (void)ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, bio_err, 0);
+ if (!ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0,
+ (void *)get_ui_method(), 0, 1)
+ || !ENGINE_set_default(e, methods)) {
+ BIO_printf(bio_err, "Cannot use engine \"%s\"\n", ENGINE_get_id(e));
+ ERR_print_errors(bio_err);
+ ENGINE_free(e);
+ return NULL;
+ }
+
+ BIO_printf(bio_err, "Engine \"%s\" set.\n", ENGINE_get_id(e));
+ }
+#endif
+ return e;
+}
+
+void release_engine(ENGINE *e)
+{
+#ifndef OPENSSL_NO_ENGINE
+ /* Free our "structural" reference. */
+ ENGINE_free(e);
+#endif
+}
+
+int init_engine(ENGINE *e)
+{
+ int rv = 1;
+
+#ifndef OPENSSL_NO_ENGINE
+ rv = ENGINE_init(e);
+#endif
+ return rv;
+}
+
+int finish_engine(ENGINE *e)
+{
+ int rv = 1;
+
+#ifndef OPENSSL_NO_ENGINE
+ rv = ENGINE_finish(e);
+#endif
+ return rv;
+}
+
+char *make_engine_uri(ENGINE *e, const char *key_id, const char *desc)
+{
+ char *new_uri = NULL;
+
+#ifndef OPENSSL_NO_ENGINE
+ if (e == NULL) {
+ BIO_printf(bio_err, "No engine specified for loading %s\n", desc);
+ } else if (key_id == NULL) {
+ BIO_printf(bio_err, "No engine key id specified for loading %s\n", desc);
+ } else {
+ const char *engineid = ENGINE_get_id(e);
+ size_t uri_sz =
+ sizeof(ENGINE_SCHEME_COLON) - 1
+ + strlen(engineid)
+ + 1 /* : */
+ + strlen(key_id)
+ + 1 /* \0 */
+ ;
+
+ new_uri = OPENSSL_malloc(uri_sz);
+ if (new_uri != NULL) {
+ OPENSSL_strlcpy(new_uri, ENGINE_SCHEME_COLON, uri_sz);
+ OPENSSL_strlcat(new_uri, engineid, uri_sz);
+ OPENSSL_strlcat(new_uri, ":", uri_sz);
+ OPENSSL_strlcat(new_uri, key_id, uri_sz);
+ }
+ }
+#else
+ BIO_printf(bio_err, "Engines not supported for loading %s\n", desc);
+#endif
+ return new_uri;
+}
+
+int get_legacy_pkey_id(OSSL_LIB_CTX *libctx, const char *algname, ENGINE *e)
+{
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ ENGINE *tmpeng = NULL;
+ int pkey_id = NID_undef;
+
+ ERR_set_mark();
+ ameth = EVP_PKEY_asn1_find_str(&tmpeng, algname, -1);
+
+#if !defined(OPENSSL_NO_ENGINE)
+ ENGINE_finish(tmpeng);
+
+ if (ameth == NULL && e != NULL)
+ ameth = ENGINE_get_pkey_asn1_meth_str(e, algname, -1);
+ else
+#endif
+ /* We're only interested if it comes from an ENGINE */
+ if (tmpeng == NULL)
+ ameth = NULL;
+
+ ERR_pop_to_mark();
+ if (ameth == NULL)
+ return NID_undef;
+
+ EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
+
+ return pkey_id;
+}
+
+const EVP_MD *get_digest_from_engine(const char *name)
+{
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE *eng;
+
+ eng = ENGINE_get_digest_engine(OBJ_sn2nid(name));
+ if (eng != NULL) {
+ ENGINE_finish(eng);
+ return EVP_get_digestbyname(name);
+ }
+#endif
+ return NULL;
+}
+
+const EVP_CIPHER *get_cipher_from_engine(const char *name)
+{
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE *eng;
+
+ eng = ENGINE_get_cipher_engine(OBJ_sn2nid(name));
+ if (eng != NULL) {
+ ENGINE_finish(eng);
+ return EVP_get_cipherbyname(name);
+ }
+#endif
+ return NULL;
+}
diff --git a/apps/lib/engine_loader.c b/apps/lib/engine_loader.c
new file mode 100644
index 000000000000..42775a89f361
--- /dev/null
+++ b/apps/lib/engine_loader.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Here is an STORE loader for ENGINE backed keys. It relies on deprecated
+ * functions, and therefore need to have deprecation warnings suppressed.
+ * This file is not compiled at all in a '--api=3 no-deprecated' configuration.
+ */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include "apps.h"
+
+#ifndef OPENSSL_NO_ENGINE
+
+# include <stdarg.h>
+# include <string.h>
+# include <openssl/engine.h>
+# include <openssl/store.h>
+
+/*
+ * Support for legacy private engine keys via the 'org.openssl.engine:' scheme
+ *
+ * org.openssl.engine:{engineid}:{keyid}
+ *
+ * Note: we ONLY support ENGINE_load_private_key() and ENGINE_load_public_key()
+ * Note 2: This scheme has a precedent in code in PKIX-SSH. for exactly
+ * this sort of purpose.
+ */
+
+/* Local definition of OSSL_STORE_LOADER_CTX */
+struct ossl_store_loader_ctx_st {
+ ENGINE *e; /* Structural reference */
+ char *keyid;
+ int expected;
+ int loaded; /* 0 = key not loaded yet, 1 = key loaded */
+};
+
+static OSSL_STORE_LOADER_CTX *OSSL_STORE_LOADER_CTX_new(ENGINE *e, char *keyid)
+{
+ OSSL_STORE_LOADER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx != NULL) {
+ ctx->e = e;
+ ctx->keyid = keyid;
+ }
+ return ctx;
+}
+
+static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx)
+{
+ if (ctx != NULL) {
+ ENGINE_free(ctx->e);
+ OPENSSL_free(ctx->keyid);
+ OPENSSL_free(ctx);
+ }
+}
+
+static OSSL_STORE_LOADER_CTX *engine_open(const OSSL_STORE_LOADER *loader,
+ const char *uri,
+ const UI_METHOD *ui_method,
+ void *ui_data)
+{
+ const char *p = uri, *q;
+ ENGINE *e = NULL;
+ char *keyid = NULL;
+ OSSL_STORE_LOADER_CTX *ctx = NULL;
+
+ if (OPENSSL_strncasecmp(p, ENGINE_SCHEME_COLON, sizeof(ENGINE_SCHEME_COLON) - 1)
+ != 0)
+ return NULL;
+ p += sizeof(ENGINE_SCHEME_COLON) - 1;
+
+ /* Look for engine ID */
+ q = strchr(p, ':');
+ if (q != NULL /* There is both an engine ID and a key ID */
+ && p[0] != ':' /* The engine ID is at least one character */
+ && q[1] != '\0') { /* The key ID is at least one character */
+ char engineid[256];
+ size_t engineid_l = q - p;
+
+ strncpy(engineid, p, engineid_l);
+ engineid[engineid_l] = '\0';
+ e = ENGINE_by_id(engineid);
+
+ keyid = OPENSSL_strdup(q + 1);
+ }
+
+ if (e != NULL && keyid != NULL)
+ ctx = OSSL_STORE_LOADER_CTX_new(e, keyid);
+
+ if (ctx == NULL) {
+ OPENSSL_free(keyid);
+ ENGINE_free(e);
+ }
+
+ return ctx;
+}
+
+static int engine_expect(OSSL_STORE_LOADER_CTX *ctx, int expected)
+{
+ if (expected == 0
+ || expected == OSSL_STORE_INFO_PUBKEY
+ || expected == OSSL_STORE_INFO_PKEY) {
+ ctx->expected = expected;
+ return 1;
+ }
+ return 0;
+}
+
+static OSSL_STORE_INFO *engine_load(OSSL_STORE_LOADER_CTX *ctx,
+ const UI_METHOD *ui_method, void *ui_data)
+{
+ EVP_PKEY *pkey = NULL, *pubkey = NULL;
+ OSSL_STORE_INFO *info = NULL;
+
+ if (ctx->loaded == 0) {
+ if (ENGINE_init(ctx->e)) {
+ if (ctx->expected == 0
+ || ctx->expected == OSSL_STORE_INFO_PKEY)
+ pkey =
+ ENGINE_load_private_key(ctx->e, ctx->keyid,
+ (UI_METHOD *)ui_method, ui_data);
+ if ((pkey == NULL && ctx->expected == 0)
+ || ctx->expected == OSSL_STORE_INFO_PUBKEY)
+ pubkey =
+ ENGINE_load_public_key(ctx->e, ctx->keyid,
+ (UI_METHOD *)ui_method, ui_data);
+ ENGINE_finish(ctx->e);
+ }
+ }
+
+ ctx->loaded = 1;
+
+ if (pubkey != NULL)
+ info = OSSL_STORE_INFO_new_PUBKEY(pubkey);
+ else if (pkey != NULL)
+ info = OSSL_STORE_INFO_new_PKEY(pkey);
+ if (info == NULL) {
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_free(pubkey);
+ }
+ return info;
+}
+
+static int engine_eof(OSSL_STORE_LOADER_CTX *ctx)
+{
+ return ctx->loaded != 0;
+}
+
+static int engine_error(OSSL_STORE_LOADER_CTX *ctx)
+{
+ return 0;
+}
+
+static int engine_close(OSSL_STORE_LOADER_CTX *ctx)
+{
+ OSSL_STORE_LOADER_CTX_free(ctx);
+ return 1;
+}
+
+int setup_engine_loader(void)
+{
+ OSSL_STORE_LOADER *loader = NULL;
+
+ if ((loader = OSSL_STORE_LOADER_new(NULL, ENGINE_SCHEME)) == NULL
+ || !OSSL_STORE_LOADER_set_open(loader, engine_open)
+ || !OSSL_STORE_LOADER_set_expect(loader, engine_expect)
+ || !OSSL_STORE_LOADER_set_load(loader, engine_load)
+ || !OSSL_STORE_LOADER_set_eof(loader, engine_eof)
+ || !OSSL_STORE_LOADER_set_error(loader, engine_error)
+ || !OSSL_STORE_LOADER_set_close(loader, engine_close)
+ || !OSSL_STORE_register_loader(loader)) {
+ OSSL_STORE_LOADER_free(loader);
+ loader = NULL;
+ }
+
+ return loader != NULL;
+}
+
+void destroy_engine_loader(void)
+{
+ OSSL_STORE_LOADER *loader = OSSL_STORE_unregister_loader(ENGINE_SCHEME);
+ OSSL_STORE_LOADER_free(loader);
+}
+
+#else /* !OPENSSL_NO_ENGINE */
+
+int setup_engine_loader(void)
+{
+ return 0;
+}
+
+void destroy_engine_loader(void)
+{
+}
+
+#endif
diff --git a/apps/lib/fmt.c b/apps/lib/fmt.c
new file mode 100644
index 000000000000..af0e63b85b14
--- /dev/null
+++ b/apps/lib/fmt.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "fmt.h"
+
+int FMT_istext(int format)
+{
+ return (format & B_FORMAT_TEXT) == B_FORMAT_TEXT;
+}
diff --git a/apps/lib/http_server.c b/apps/lib/http_server.c
new file mode 100644
index 000000000000..a7fe5e1a58b0
--- /dev/null
+++ b/apps/lib/http_server.c
@@ -0,0 +1,533 @@
+/*
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Very basic HTTP server */
+
+#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
+/*
+ * On VMS, you need to define this to get the declaration of fileno(). The
+ * value 2 is to make sure no function defined in POSIX-2 is left undefined.
+ */
+# define _POSIX_C_SOURCE 2
+#endif
+
+#include <string.h>
+#include <ctype.h>
+#include "http_server.h"
+#include "internal/sockets.h"
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include "s_apps.h"
+
+#if defined(__TANDEM)
+# if defined(OPENSSL_TANDEM_FLOSS)
+# include <floss.h(floss_fork)>
+# endif
+#endif
+
+static int verbosity = LOG_INFO;
+
+#define HTTP_PREFIX "HTTP/"
+#define HTTP_VERSION_PATT "1." /* allow 1.x */
+#define HTTP_PREFIX_VERSION HTTP_PREFIX""HTTP_VERSION_PATT
+#define HTTP_1_0 HTTP_PREFIX_VERSION"0" /* "HTTP/1.0" */
+
+#ifdef HTTP_DAEMON
+
+int multi = 0; /* run multiple responder processes */
+int acfd = (int) INVALID_SOCKET;
+
+static int print_syslog(const char *str, size_t len, void *levPtr)
+{
+ int level = *(int *)levPtr;
+ int ilen = len > MAXERRLEN ? MAXERRLEN : len;
+
+ syslog(level, "%.*s", ilen, str);
+
+ return ilen;
+}
+#endif
+
+void log_message(const char *prog, int level, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (verbosity < level)
+ return;
+
+ va_start(ap, fmt);
+#ifdef HTTP_DAEMON
+ if (multi) {
+ char buf[1024];
+
+ if (vsnprintf(buf, sizeof(buf), fmt, ap) > 0)
+ syslog(level, "%s", buf);
+ if (level <= LOG_ERR)
+ ERR_print_errors_cb(print_syslog, &level);
+ } else
+#endif
+ {
+ BIO_printf(bio_err, "%s: ", prog);
+ BIO_vprintf(bio_err, fmt, ap);
+ BIO_printf(bio_err, "\n");
+ (void)BIO_flush(bio_err);
+ }
+ va_end(ap);
+}
+
+#ifdef HTTP_DAEMON
+void socket_timeout(int signum)
+{
+ if (acfd != (int)INVALID_SOCKET)
+ (void)shutdown(acfd, SHUT_RD);
+}
+
+static void killall(int ret, pid_t *kidpids)
+{
+ int i;
+
+ for (i = 0; i < multi; ++i)
+ if (kidpids[i] != 0)
+ (void)kill(kidpids[i], SIGTERM);
+ OPENSSL_free(kidpids);
+ ossl_sleep(1000);
+ exit(ret);
+}
+
+static int termsig = 0;
+
+static void noteterm(int sig)
+{
+ termsig = sig;
+}
+
+/*
+ * Loop spawning up to `multi` child processes, only child processes return
+ * from this function. The parent process loops until receiving a termination
+ * signal, kills extant children and exits without returning.
+ */
+void spawn_loop(const char *prog)
+{
+ pid_t *kidpids = NULL;
+ int status;
+ int procs = 0;
+ int i;
+
+ openlog(prog, LOG_PID, LOG_DAEMON);
+
+ if (setpgid(0, 0)) {
+ syslog(LOG_ERR, "fatal: error detaching from parent process group: %s",
+ strerror(errno));
+ exit(1);
+ }
+ kidpids = app_malloc(multi * sizeof(*kidpids), "child PID array");
+ for (i = 0; i < multi; ++i)
+ kidpids[i] = 0;
+
+ signal(SIGINT, noteterm);
+ signal(SIGTERM, noteterm);
+
+ while (termsig == 0) {
+ pid_t fpid;
+
+ /*
+ * Wait for a child to replace when we're at the limit.
+ * Slow down if a child exited abnormally or waitpid() < 0
+ */
+ while (termsig == 0 && procs >= multi) {
+ if ((fpid = waitpid(-1, &status, 0)) > 0) {
+ for (i = 0; i < procs; ++i) {
+ if (kidpids[i] == fpid) {
+ kidpids[i] = 0;
+ --procs;
+ break;
+ }
+ }
+ if (i >= multi) {
+ syslog(LOG_ERR, "fatal: internal error: "
+ "no matching child slot for pid: %ld",
+ (long) fpid);
+ killall(1, kidpids);
+ }
+ if (status != 0) {
+ if (WIFEXITED(status))
+ syslog(LOG_WARNING, "child process: %ld, exit status: %d",
+ (long)fpid, WEXITSTATUS(status));
+ else if (WIFSIGNALED(status))
+ syslog(LOG_WARNING, "child process: %ld, term signal %d%s",
+ (long)fpid, WTERMSIG(status),
+# ifdef WCOREDUMP
+ WCOREDUMP(status) ? " (core dumped)" :
+# endif
+ "");
+ ossl_sleep(1000);
+ }
+ break;
+ } else if (errno != EINTR) {
+ syslog(LOG_ERR, "fatal: waitpid(): %s", strerror(errno));
+ killall(1, kidpids);
+ }
+ }
+ if (termsig)
+ break;
+
+ switch (fpid = fork()) {
+ case -1: /* error */
+ /* System critically low on memory, pause and try again later */
+ ossl_sleep(30000);
+ break;
+ case 0: /* child */
+ OPENSSL_free(kidpids);
+ signal(SIGINT, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
+ if (termsig)
+ _exit(0);
+ if (RAND_poll() <= 0) {
+ syslog(LOG_ERR, "fatal: RAND_poll() failed");
+ _exit(1);
+ }
+ return;
+ default: /* parent */
+ for (i = 0; i < multi; ++i) {
+ if (kidpids[i] == 0) {
+ kidpids[i] = fpid;
+ procs++;
+ break;
+ }
+ }
+ if (i >= multi) {
+ syslog(LOG_ERR, "fatal: internal error: no free child slots");
+ killall(1, kidpids);
+ }
+ break;
+ }
+ }
+
+ /* The loop above can only break on termsig */
+ syslog(LOG_INFO, "terminating on signal: %d", termsig);
+ killall(0, kidpids);
+}
+#endif
+
+#ifndef OPENSSL_NO_SOCK
+BIO *http_server_init_bio(const char *prog, const char *port)
+{
+ BIO *acbio = NULL, *bufbio;
+ int asock;
+
+ bufbio = BIO_new(BIO_f_buffer());
+ if (bufbio == NULL)
+ goto err;
+ acbio = BIO_new(BIO_s_accept());
+ if (acbio == NULL
+ || BIO_set_bind_mode(acbio, BIO_BIND_REUSEADDR) < 0
+ || BIO_set_accept_port(acbio, port) < 0) {
+ log_message(prog, LOG_ERR, "Error setting up accept BIO");
+ goto err;
+ }
+
+ BIO_set_accept_bios(acbio, bufbio);
+ bufbio = NULL;
+ if (BIO_do_accept(acbio) <= 0) {
+ log_message(prog, LOG_ERR, "Error starting accept");
+ goto err;
+ }
+
+ /* Report back what address and port are used */
+ BIO_get_fd(acbio, &asock);
+ if (!report_server_accept(bio_out, asock, 1, 1)) {
+ log_message(prog, LOG_ERR, "Error printing ACCEPT string");
+ goto err;
+ }
+
+ return acbio;
+
+ err:
+ BIO_free_all(acbio);
+ BIO_free(bufbio);
+ return NULL;
+}
+
+/*
+ * Decode %xx URL-decoding in-place. Ignores malformed sequences.
+ */
+static int urldecode(char *p)
+{
+ unsigned char *out = (unsigned char *)p;
+ unsigned char *save = out;
+
+ for (; *p; p++) {
+ if (*p != '%') {
+ *out++ = *p;
+ } else if (isxdigit(_UC(p[1])) && isxdigit(_UC(p[2]))) {
+ /* Don't check, can't fail because of ixdigit() call. */
+ *out++ = (OPENSSL_hexchar2int(p[1]) << 4)
+ | OPENSSL_hexchar2int(p[2]);
+ p += 2;
+ } else {
+ return -1;
+ }
+ }
+ *out = '\0';
+ return (int)(out - save);
+}
+
+/* if *pcbio != NULL, continue given connected session, else accept new */
+/* if found_keep_alive != NULL, return this way connection persistence state */
+int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
+ char **ppath, BIO **pcbio, BIO *acbio,
+ int *found_keep_alive,
+ const char *prog, const char *port,
+ int accept_get, int timeout)
+{
+ BIO *cbio = *pcbio, *getbio = NULL, *b64 = NULL;
+ int len;
+ char reqbuf[2048], inbuf[2048];
+ char *meth, *url, *end;
+ ASN1_VALUE *req;
+ int ret = 0;
+
+ *preq = NULL;
+ if (ppath != NULL)
+ *ppath = NULL;
+
+ if (cbio == NULL) {
+ log_message(prog, LOG_DEBUG,
+ "Awaiting new connection on port %s...", port);
+ if (BIO_do_accept(acbio) <= 0)
+ /* Connection loss before accept() is routine, ignore silently */
+ return ret;
+
+ *pcbio = cbio = BIO_pop(acbio);
+ } else {
+ log_message(prog, LOG_DEBUG, "Awaiting next request...");
+ }
+ if (cbio == NULL) {
+ /* Cannot call http_server_send_status(cbio, ...) */
+ ret = -1;
+ goto out;
+ }
+
+# ifdef HTTP_DAEMON
+ if (timeout > 0) {
+ (void)BIO_get_fd(cbio, &acfd);
+ alarm(timeout);
+ }
+# endif
+
+ /* Read the request line. */
+ len = BIO_gets(cbio, reqbuf, sizeof(reqbuf));
+ if (len == 0)
+ return ret;
+ ret = 1;
+ if (len < 0) {
+ log_message(prog, LOG_WARNING, "Request line read error");
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ goto out;
+ }
+ if ((end = strchr(reqbuf, '\r')) != NULL
+ || (end = strchr(reqbuf, '\n')) != NULL)
+ *end = '\0';
+ log_message(prog, LOG_INFO, "Received request, 1st line: %s", reqbuf);
+
+ meth = reqbuf;
+ url = meth + 3;
+ if ((accept_get && strncmp(meth, "GET ", 4) == 0)
+ || (url++, strncmp(meth, "POST ", 5) == 0)) {
+ static const char http_version_str[] = " "HTTP_PREFIX_VERSION;
+ static const size_t http_version_str_len = sizeof(http_version_str) - 1;
+
+ /* Expecting (GET|POST) {sp} /URL {sp} HTTP/1.x */
+ *(url++) = '\0';
+ while (*url == ' ')
+ url++;
+ if (*url != '/') {
+ log_message(prog, LOG_WARNING,
+ "Invalid %s -- URL does not begin with '/': %s",
+ meth, url);
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ goto out;
+ }
+ url++;
+
+ /* Splice off the HTTP version identifier. */
+ for (end = url; *end != '\0'; end++)
+ if (*end == ' ')
+ break;
+ if (strncmp(end, http_version_str, http_version_str_len) != 0) {
+ log_message(prog, LOG_WARNING,
+ "Invalid %s -- bad HTTP/version string: %s",
+ meth, end + 1);
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ goto out;
+ }
+ *end = '\0';
+ /* above HTTP 1.0, connection persistence is the default */
+ if (found_keep_alive != NULL)
+ *found_keep_alive = end[http_version_str_len] > '0';
+
+ /*-
+ * Skip "GET / HTTP..." requests often used by load-balancers.
+ * 'url' was incremented above to point to the first byte *after*
+ * the leading slash, so in case 'GET / ' it is now an empty string.
+ */
+ if (strlen(meth) == 3 && url[0] == '\0') {
+ (void)http_server_send_status(cbio, 200, "OK");
+ goto out;
+ }
+
+ len = urldecode(url);
+ if (len < 0) {
+ log_message(prog, LOG_WARNING,
+ "Invalid %s request -- bad URL encoding: %s",
+ meth, url);
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ goto out;
+ }
+ if (strlen(meth) == 3) { /* GET */
+ if ((getbio = BIO_new_mem_buf(url, len)) == NULL
+ || (b64 = BIO_new(BIO_f_base64())) == NULL) {
+ log_message(prog, LOG_ERR,
+ "Could not allocate base64 bio with size = %d",
+ len);
+ goto fatal;
+ }
+ BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+ getbio = BIO_push(b64, getbio);
+ }
+ } else {
+ log_message(prog, LOG_WARNING,
+ "HTTP request does not begin with %sPOST: %s",
+ accept_get ? "GET or " : "", reqbuf);
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ goto out;
+ }
+
+ /* chop any further/duplicate leading or trailing '/' */
+ while (*url == '/')
+ url++;
+ while (end >= url + 2 && end[-2] == '/' && end[-1] == '/')
+ end--;
+ *end = '\0';
+
+ /* Read and skip past the headers. */
+ for (;;) {
+ char *key, *value, *line_end = NULL;
+
+ len = BIO_gets(cbio, inbuf, sizeof(inbuf));
+ if (len <= 0) {
+ log_message(prog, LOG_WARNING, "Error reading HTTP header");
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ goto out;
+ }
+
+ if (inbuf[0] == '\r' || inbuf[0] == '\n')
+ break;
+
+ key = inbuf;
+ value = strchr(key, ':');
+ if (value == NULL) {
+ log_message(prog, LOG_WARNING,
+ "Error parsing HTTP header: missing ':'");
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ goto out;
+ }
+ *(value++) = '\0';
+ while (*value == ' ')
+ value++;
+ line_end = strchr(value, '\r');
+ if (line_end == NULL) {
+ line_end = strchr(value, '\n');
+ if (line_end == NULL) {
+ log_message(prog, LOG_WARNING,
+ "Error parsing HTTP header: missing end of line");
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ goto out;
+ }
+ }
+ *line_end = '\0';
+ /* https://tools.ietf.org/html/rfc7230#section-6.3 Persistence */
+ if (found_keep_alive != NULL
+ && OPENSSL_strcasecmp(key, "Connection") == 0) {
+ if (OPENSSL_strcasecmp(value, "keep-alive") == 0)
+ *found_keep_alive = 1;
+ else if (OPENSSL_strcasecmp(value, "close") == 0)
+ *found_keep_alive = 0;
+ }
+ }
+
+# ifdef HTTP_DAEMON
+ /* Clear alarm before we close the client socket */
+ alarm(0);
+ timeout = 0;
+# endif
+
+ /* Try to read and parse request */
+ req = ASN1_item_d2i_bio(it, getbio != NULL ? getbio : cbio, NULL);
+ if (req == NULL) {
+ log_message(prog, LOG_WARNING,
+ "Error parsing DER-encoded request content");
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ } else if (ppath != NULL && (*ppath = OPENSSL_strdup(url)) == NULL) {
+ log_message(prog, LOG_ERR,
+ "Out of memory allocating %zu bytes", strlen(url) + 1);
+ ASN1_item_free(req, it);
+ goto fatal;
+ }
+
+ *preq = req;
+
+ out:
+ BIO_free_all(getbio);
+# ifdef HTTP_DAEMON
+ if (timeout > 0)
+ alarm(0);
+ acfd = (int)INVALID_SOCKET;
+# endif
+ return ret;
+
+ fatal:
+ (void)http_server_send_status(cbio, 500, "Internal Server Error");
+ if (ppath != NULL) {
+ OPENSSL_free(*ppath);
+ *ppath = NULL;
+ }
+ BIO_free_all(cbio);
+ *pcbio = NULL;
+ ret = -1;
+ goto out;
+}
+
+/* assumes that cbio does not do an encoding that changes the output length */
+int http_server_send_asn1_resp(BIO *cbio, int keep_alive,
+ const char *content_type,
+ const ASN1_ITEM *it, const ASN1_VALUE *resp)
+{
+ int ret = BIO_printf(cbio, HTTP_1_0" 200 OK\r\n%s"
+ "Content-type: %s\r\n"
+ "Content-Length: %d\r\n\r\n",
+ keep_alive ? "Connection: keep-alive\r\n" : "",
+ content_type,
+ ASN1_item_i2d(resp, NULL, it)) > 0
+ && ASN1_item_i2d_bio(it, cbio, resp) > 0;
+
+ (void)BIO_flush(cbio);
+ return ret;
+}
+
+int http_server_send_status(BIO *cbio, int status, const char *reason)
+{
+ int ret = BIO_printf(cbio, HTTP_1_0" %d %s\r\n\r\n",
+ /* This implicitly cancels keep-alive */
+ status, reason) > 0;
+
+ (void)BIO_flush(cbio);
+ return ret;
+}
+#endif
diff --git a/apps/lib/names.c b/apps/lib/names.c
new file mode 100644
index 000000000000..4788ae84b915
--- /dev/null
+++ b/apps/lib/names.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/bio.h>
+#include <openssl/safestack.h>
+#include "names.h"
+#include "openssl/crypto.h"
+
+int name_cmp(const char * const *a, const char * const *b)
+{
+ return OPENSSL_strcasecmp(*a, *b);
+}
+
+void collect_names(const char *name, void *vdata)
+{
+ STACK_OF(OPENSSL_CSTRING) *names = vdata;
+
+ sk_OPENSSL_CSTRING_push(names, name);
+}
+
+void print_names(BIO *out, STACK_OF(OPENSSL_CSTRING) *names)
+{
+ int i = sk_OPENSSL_CSTRING_num(names);
+ int j;
+
+ sk_OPENSSL_CSTRING_sort(names);
+ if (i > 1)
+ BIO_printf(out, "{ ");
+ for (j = 0; j < i; j++) {
+ const char *name = sk_OPENSSL_CSTRING_value(names, j);
+
+ if (j > 0)
+ BIO_printf(out, ", ");
+ BIO_printf(out, "%s", name);
+ }
+ if (i > 1)
+ BIO_printf(out, " }");
+}
diff --git a/apps/lib/opt.c b/apps/lib/opt.c
new file mode 100644
index 000000000000..157367982d2f
--- /dev/null
+++ b/apps/lib/opt.c
@@ -0,0 +1,1198 @@
+/*
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This file is also used by the test suite. Do not #include "apps.h".
+ */
+#include "opt.h"
+#include "fmt.h"
+#include "app_libctx.h"
+#include "internal/nelem.h"
+#include "internal/numbers.h"
+#include <string.h>
+#if !defined(OPENSSL_SYS_MSDOS)
+# include <unistd.h>
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <limits.h>
+#include <openssl/err.h>
+#include <openssl/bio.h>
+#include <openssl/x509v3.h>
+
+#define MAX_OPT_HELP_WIDTH 30
+const char OPT_HELP_STR[] = "-H";
+const char OPT_MORE_STR[] = "-M";
+const char OPT_SECTION_STR[] = "-S";
+const char OPT_PARAM_STR[] = "-P";
+
+/* Our state */
+static char **argv;
+static int argc;
+static int opt_index;
+static char *arg;
+static char *flag;
+static char *dunno;
+static const OPTIONS *unknown;
+static const OPTIONS *opts;
+static char prog[40];
+
+/*
+ * Return the simple name of the program; removing various platform gunk.
+ */
+#if defined(OPENSSL_SYS_WIN32)
+
+const char *opt_path_end(const char *filename)
+{
+ const char *p;
+
+ /* find the last '/', '\' or ':' */
+ for (p = filename + strlen(filename); --p > filename; )
+ if (*p == '/' || *p == '\\' || *p == ':') {
+ p++;
+ break;
+ }
+ return p;
+}
+
+char *opt_progname(const char *argv0)
+{
+ size_t i, n;
+ const char *p;
+ char *q;
+
+ p = opt_path_end(argv0);
+
+ /* Strip off trailing nonsense. */
+ n = strlen(p);
+ if (n > 4 &&
+ (strcmp(&p[n - 4], ".exe") == 0 || strcmp(&p[n - 4], ".EXE") == 0))
+ n -= 4;
+
+ /* Copy over the name, in lowercase. */
+ if (n > sizeof(prog) - 1)
+ n = sizeof(prog) - 1;
+ for (q = prog, i = 0; i < n; i++, p++)
+ *q++ = tolower((unsigned char)*p);
+ *q = '\0';
+ return prog;
+}
+
+#elif defined(OPENSSL_SYS_VMS)
+
+const char *opt_path_end(const char *filename)
+{
+ const char *p;
+
+ /* Find last special character sys:[foo.bar]openssl */
+ for (p = filename + strlen(filename); --p > filename;)
+ if (*p == ':' || *p == ']' || *p == '>') {
+ p++;
+ break;
+ }
+ return p;
+}
+
+char *opt_progname(const char *argv0)
+{
+ const char *p, *q;
+
+ /* Find last special character sys:[foo.bar]openssl */
+ p = opt_path_end(argv0);
+ q = strrchr(p, '.');
+ if (prog != p)
+ strncpy(prog, p, sizeof(prog) - 1);
+ prog[sizeof(prog) - 1] = '\0';
+ if (q != NULL && q - p < sizeof(prog))
+ prog[q - p] = '\0';
+ return prog;
+}
+
+#else
+
+const char *opt_path_end(const char *filename)
+{
+ const char *p;
+
+ /* Could use strchr, but this is like the ones above. */
+ for (p = filename + strlen(filename); --p > filename;)
+ if (*p == '/') {
+ p++;
+ break;
+ }
+ return p;
+}
+
+char *opt_progname(const char *argv0)
+{
+ const char *p;
+
+ p = opt_path_end(argv0);
+ if (prog != p)
+ strncpy(prog, p, sizeof(prog) - 1);
+ prog[sizeof(prog) - 1] = '\0';
+ return prog;
+}
+#endif
+
+char *opt_appname(const char *argv0)
+{
+ size_t len = strlen(prog);
+
+ if (argv0 != NULL)
+ BIO_snprintf(prog + len, sizeof(prog) - len - 1, " %s", argv0);
+ return prog;
+}
+
+char *opt_getprog(void)
+{
+ return prog;
+}
+
+/* Set up the arg parsing. */
+char *opt_init(int ac, char **av, const OPTIONS *o)
+{
+ /* Store state. */
+ argc = ac;
+ argv = av;
+ opt_begin();
+ opts = o;
+ unknown = NULL;
+
+ /* Make sure prog name is set for usage output */
+ (void)opt_progname(argv[0]);
+
+ /* Check all options up until the PARAM marker (if present) */
+ for (; o->name != NULL && o->name != OPT_PARAM_STR; ++o) {
+#ifndef NDEBUG
+ const OPTIONS *next;
+ int duplicated, i;
+#endif
+
+ if (o->name == OPT_HELP_STR
+ || o->name == OPT_MORE_STR
+ || o->name == OPT_SECTION_STR)
+ continue;
+#ifndef NDEBUG
+ i = o->valtype;
+
+ /* Make sure options are legit. */
+ OPENSSL_assert(o->name[0] != '-');
+ if (o->valtype == '.')
+ OPENSSL_assert(o->retval == OPT_PARAM);
+ else
+ OPENSSL_assert(o->retval == OPT_DUP || o->retval > OPT_PARAM);
+ switch (i) {
+ case 0: case '-': case '.':
+ case '/': case '<': case '>': case 'E': case 'F':
+ case 'M': case 'U': case 'f': case 'l': case 'n': case 'p': case 's':
+ case 'u': case 'c': case ':': case 'N':
+ break;
+ default:
+ OPENSSL_assert(0);
+ }
+
+ /* Make sure there are no duplicates. */
+ for (next = o + 1; next->name; ++next) {
+ /*
+ * Some compilers inline strcmp and the assert string is too long.
+ */
+ duplicated = next->retval != OPT_DUP
+ && strcmp(o->name, next->name) == 0;
+ if (duplicated) {
+ opt_printf_stderr("%s: Internal error: duplicate option %s\n",
+ prog, o->name);
+ OPENSSL_assert(!duplicated);
+ }
+ }
+#endif
+ if (o->name[0] == '\0') {
+ OPENSSL_assert(unknown == NULL);
+ unknown = o;
+ OPENSSL_assert(unknown->valtype == 0 || unknown->valtype == '-');
+ }
+ }
+ return prog;
+}
+
+static OPT_PAIR formats[] = {
+ {"PEM/DER", OPT_FMT_PEMDER},
+ {"pkcs12", OPT_FMT_PKCS12},
+ {"smime", OPT_FMT_SMIME},
+ {"engine", OPT_FMT_ENGINE},
+ {"msblob", OPT_FMT_MSBLOB},
+ {"nss", OPT_FMT_NSS},
+ {"text", OPT_FMT_TEXT},
+ {"http", OPT_FMT_HTTP},
+ {"pvk", OPT_FMT_PVK},
+ {NULL}
+};
+
+/* Print an error message about a failed format parse. */
+static int opt_format_error(const char *s, unsigned long flags)
+{
+ OPT_PAIR *ap;
+
+ if (flags == OPT_FMT_PEMDER) {
+ opt_printf_stderr("%s: Bad format \"%s\"; must be pem or der\n",
+ prog, s);
+ } else {
+ opt_printf_stderr("%s: Bad format \"%s\"; must be one of:\n",
+ prog, s);
+ for (ap = formats; ap->name; ap++)
+ if (flags & ap->retval)
+ opt_printf_stderr(" %s\n", ap->name);
+ }
+ return 0;
+}
+
+/* Parse a format string, put it into *result; return 0 on failure, else 1. */
+int opt_format(const char *s, unsigned long flags, int *result)
+{
+ switch (*s) {
+ default:
+ opt_printf_stderr("%s: Bad format \"%s\"\n", prog, s);
+ return 0;
+ case 'D':
+ case 'd':
+ if ((flags & OPT_FMT_PEMDER) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_ASN1;
+ break;
+ case 'T':
+ case 't':
+ if ((flags & OPT_FMT_TEXT) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_TEXT;
+ break;
+ case 'N':
+ case 'n':
+ if ((flags & OPT_FMT_NSS) == 0)
+ return opt_format_error(s, flags);
+ if (strcmp(s, "NSS") != 0 && strcmp(s, "nss") != 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_NSS;
+ break;
+ case 'S':
+ case 's':
+ if ((flags & OPT_FMT_SMIME) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_SMIME;
+ break;
+ case 'M':
+ case 'm':
+ if ((flags & OPT_FMT_MSBLOB) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_MSBLOB;
+ break;
+ case 'E':
+ case 'e':
+ if ((flags & OPT_FMT_ENGINE) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_ENGINE;
+ break;
+ case 'H':
+ case 'h':
+ if ((flags & OPT_FMT_HTTP) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_HTTP;
+ break;
+ case '1':
+ if ((flags & OPT_FMT_PKCS12) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_PKCS12;
+ break;
+ case 'P':
+ case 'p':
+ if (s[1] == '\0' || strcmp(s, "PEM") == 0 || strcmp(s, "pem") == 0) {
+ if ((flags & OPT_FMT_PEMDER) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_PEM;
+ } else if (strcmp(s, "PVK") == 0 || strcmp(s, "pvk") == 0) {
+ if ((flags & OPT_FMT_PVK) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_PVK;
+ } else if (strcmp(s, "P12") == 0 || strcmp(s, "p12") == 0
+ || strcmp(s, "PKCS12") == 0 || strcmp(s, "pkcs12") == 0) {
+ if ((flags & OPT_FMT_PKCS12) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_PKCS12;
+ } else {
+ opt_printf_stderr("%s: Bad format \"%s\"\n", prog, s);
+ return 0;
+ }
+ break;
+ }
+ return 1;
+}
+
+/* Return string representing the given format. */
+static const char *format2str(int format)
+{
+ switch (format) {
+ default:
+ return "(undefined)";
+ case FORMAT_PEM:
+ return "PEM";
+ case FORMAT_ASN1:
+ return "DER";
+ case FORMAT_TEXT:
+ return "TEXT";
+ case FORMAT_NSS:
+ return "NSS";
+ case FORMAT_SMIME:
+ return "SMIME";
+ case FORMAT_MSBLOB:
+ return "MSBLOB";
+ case FORMAT_ENGINE:
+ return "ENGINE";
+ case FORMAT_HTTP:
+ return "HTTP";
+ case FORMAT_PKCS12:
+ return "P12";
+ case FORMAT_PVK:
+ return "PVK";
+ }
+}
+
+/* Print an error message about unsuitable/unsupported format requested. */
+void print_format_error(int format, unsigned long flags)
+{
+ (void)opt_format_error(format2str(format), flags);
+}
+
+/*
+ * Parse a cipher name, put it in *cipherp after freeing what was there, if
+ * cipherp is not NULL. Return 0 on failure, else 1.
+ */
+int opt_cipher_silent(const char *name, EVP_CIPHER **cipherp)
+{
+ EVP_CIPHER *c;
+
+ ERR_set_mark();
+ if ((c = EVP_CIPHER_fetch(app_get0_libctx(), name,
+ app_get0_propq())) != NULL
+ || (opt_legacy_okay()
+ && (c = (EVP_CIPHER *)EVP_get_cipherbyname(name)) != NULL)) {
+ ERR_pop_to_mark();
+ if (cipherp != NULL) {
+ EVP_CIPHER_free(*cipherp);
+ *cipherp = c;
+ } else {
+ EVP_CIPHER_free(c);
+ }
+ return 1;
+ }
+ ERR_clear_last_mark();
+ return 0;
+}
+
+int opt_cipher_any(const char *name, EVP_CIPHER **cipherp)
+{
+ int ret;
+
+ if ((ret = opt_cipher_silent(name, cipherp)) == 0)
+ opt_printf_stderr("%s: Unknown cipher: %s\n", prog, name);
+ return ret;
+}
+
+int opt_cipher(const char *name, EVP_CIPHER **cipherp)
+{
+ int mode, ret = 0;
+ unsigned long int flags;
+ EVP_CIPHER *c = NULL;
+
+ if (opt_cipher_any(name, &c)) {
+ mode = EVP_CIPHER_get_mode(c);
+ flags = EVP_CIPHER_get_flags(c);
+ if (mode == EVP_CIPH_XTS_MODE) {
+ opt_printf_stderr("%s XTS ciphers not supported\n", prog);
+ } else if ((flags & EVP_CIPH_FLAG_AEAD_CIPHER) != 0) {
+ opt_printf_stderr("%s: AEAD ciphers not supported\n", prog);
+ } else {
+ ret = 1;
+ if (cipherp != NULL)
+ *cipherp = c;
+ }
+ }
+ return ret;
+}
+
+/*
+ * Parse message digest name, put it in *EVP_MD; return 0 on failure, else 1.
+ */
+int opt_md_silent(const char *name, EVP_MD **mdp)
+{
+ EVP_MD *md;
+
+ ERR_set_mark();
+ if ((md = EVP_MD_fetch(app_get0_libctx(), name, app_get0_propq())) != NULL
+ || (opt_legacy_okay()
+ && (md = (EVP_MD *)EVP_get_digestbyname(name)) != NULL)) {
+ ERR_pop_to_mark();
+ if (mdp != NULL) {
+ EVP_MD_free(*mdp);
+ *mdp = md;
+ } else {
+ EVP_MD_free(md);
+ }
+ return 1;
+ }
+ ERR_clear_last_mark();
+ return 0;
+}
+
+int opt_md(const char *name, EVP_MD **mdp)
+{
+ int ret;
+
+ if ((ret = opt_md_silent(name, mdp)) == 0)
+ opt_printf_stderr("%s: Unknown option or message digest: %s\n", prog,
+ name != NULL ? name : "\"\"");
+ return ret;
+}
+
+/* Look through a list of name/value pairs. */
+int opt_pair(const char *name, const OPT_PAIR* pairs, int *result)
+{
+ const OPT_PAIR *pp;
+
+ for (pp = pairs; pp->name; pp++)
+ if (strcmp(pp->name, name) == 0) {
+ *result = pp->retval;
+ return 1;
+ }
+ opt_printf_stderr("%s: Value must be one of:\n", prog);
+ for (pp = pairs; pp->name; pp++)
+ opt_printf_stderr("\t%s\n", pp->name);
+ return 0;
+}
+
+/* Look through a list of valid names */
+int opt_string(const char *name, const char **options)
+{
+ const char **p;
+
+ for (p = options; *p != NULL; p++)
+ if (strcmp(*p, name) == 0)
+ return 1;
+ opt_printf_stderr("%s: Value must be one of:\n", prog);
+ for (p = options; *p != NULL; p++)
+ opt_printf_stderr("\t%s\n", *p);
+ return 0;
+}
+
+/* Parse an int, put it into *result; return 0 on failure, else 1. */
+int opt_int(const char *value, int *result)
+{
+ long l;
+
+ if (!opt_long(value, &l))
+ return 0;
+ *result = (int)l;
+ if (*result != l) {
+ opt_printf_stderr("%s: Value \"%s\" outside integer range\n",
+ prog, value);
+ return 0;
+ }
+ return 1;
+}
+
+/* Parse and return an integer, assuming range has been checked before. */
+int opt_int_arg(void)
+{
+ int result = -1;
+
+ (void)opt_int(arg, &result);
+ return result;
+}
+
+static void opt_number_error(const char *v)
+{
+ size_t i = 0;
+ struct strstr_pair_st {
+ char *prefix;
+ char *name;
+ } b[] = {
+ {"0x", "a hexadecimal"},
+ {"0X", "a hexadecimal"},
+ {"0", "an octal"}
+ };
+
+ for (i = 0; i < OSSL_NELEM(b); i++) {
+ if (strncmp(v, b[i].prefix, strlen(b[i].prefix)) == 0) {
+ opt_printf_stderr("%s: Can't parse \"%s\" as %s number\n",
+ prog, v, b[i].name);
+ return;
+ }
+ }
+ opt_printf_stderr("%s: Can't parse \"%s\" as a number\n", prog, v);
+ return;
+}
+
+/* Parse a long, put it into *result; return 0 on failure, else 1. */
+int opt_long(const char *value, long *result)
+{
+ int oerrno = errno;
+ long l;
+ char *endp;
+
+ errno = 0;
+ l = strtol(value, &endp, 0);
+ if (*endp
+ || endp == value
+ || ((l == LONG_MAX || l == LONG_MIN) && errno == ERANGE)
+ || (l == 0 && errno != 0)) {
+ opt_number_error(value);
+ errno = oerrno;
+ return 0;
+ }
+ *result = l;
+ errno = oerrno;
+ return 1;
+}
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
+ defined(INTMAX_MAX) && defined(UINTMAX_MAX) && \
+ !defined(OPENSSL_NO_INTTYPES_H)
+
+/* Parse an intmax_t, put it into *result; return 0 on failure, else 1. */
+int opt_intmax(const char *value, ossl_intmax_t *result)
+{
+ int oerrno = errno;
+ intmax_t m;
+ char *endp;
+
+ errno = 0;
+ m = strtoimax(value, &endp, 0);
+ if (*endp
+ || endp == value
+ || ((m == INTMAX_MAX || m == INTMAX_MIN)
+ && errno == ERANGE)
+ || (m == 0 && errno != 0)) {
+ opt_number_error(value);
+ errno = oerrno;
+ return 0;
+ }
+ /* Ensure that the value in |m| is never too big for |*result| */
+ if (sizeof(m) > sizeof(*result)
+ && (m < OSSL_INTMAX_MIN || m > OSSL_INTMAX_MAX)) {
+ opt_number_error(value);
+ return 0;
+ }
+ *result = (ossl_intmax_t)m;
+ errno = oerrno;
+ return 1;
+}
+
+/* Parse a uintmax_t, put it into *result; return 0 on failure, else 1. */
+int opt_uintmax(const char *value, ossl_uintmax_t *result)
+{
+ int oerrno = errno;
+ uintmax_t m;
+ char *endp;
+
+ errno = 0;
+ m = strtoumax(value, &endp, 0);
+ if (*endp
+ || endp == value
+ || (m == UINTMAX_MAX && errno == ERANGE)
+ || (m == 0 && errno != 0)) {
+ opt_number_error(value);
+ errno = oerrno;
+ return 0;
+ }
+ /* Ensure that the value in |m| is never too big for |*result| */
+ if (sizeof(m) > sizeof(*result)
+ && m > OSSL_UINTMAX_MAX) {
+ opt_number_error(value);
+ return 0;
+ }
+ *result = (ossl_intmax_t)m;
+ errno = oerrno;
+ return 1;
+}
+#else
+/* Fallback implementations based on long */
+int opt_intmax(const char *value, ossl_intmax_t *result)
+{
+ long m;
+ int ret;
+
+ if ((ret = opt_long(value, &m)))
+ *result = m;
+ return ret;
+}
+
+int opt_uintmax(const char *value, ossl_uintmax_t *result)
+{
+ unsigned long m;
+ int ret;
+
+ if ((ret = opt_ulong(value, &m)))
+ *result = m;
+ return ret;
+}
+#endif
+
+/*
+ * Parse an unsigned long, put it into *result; return 0 on failure, else 1.
+ */
+int opt_ulong(const char *value, unsigned long *result)
+{
+ int oerrno = errno;
+ char *endptr;
+ unsigned long l;
+
+ errno = 0;
+ l = strtoul(value, &endptr, 0);
+ if (*endptr
+ || endptr == value
+ || ((l == ULONG_MAX) && errno == ERANGE)
+ || (l == 0 && errno != 0)) {
+ opt_number_error(value);
+ errno = oerrno;
+ return 0;
+ }
+ *result = l;
+ errno = oerrno;
+ return 1;
+}
+
+/*
+ * We pass opt as an int but cast it to "enum range" so that all the
+ * items in the OPT_V_ENUM enumeration are caught; this makes -Wswitch
+ * in gcc do the right thing.
+ */
+enum range { OPT_V_ENUM };
+
+int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
+{
+ int i;
+ ossl_intmax_t t = 0;
+ ASN1_OBJECT *otmp;
+ X509_PURPOSE *xptmp;
+ const X509_VERIFY_PARAM *vtmp;
+
+ OPENSSL_assert(vpm != NULL);
+ OPENSSL_assert(opt > OPT_V__FIRST);
+ OPENSSL_assert(opt < OPT_V__LAST);
+
+ switch ((enum range)opt) {
+ case OPT_V__FIRST:
+ case OPT_V__LAST:
+ return 0;
+ case OPT_V_POLICY:
+ otmp = OBJ_txt2obj(opt_arg(), 0);
+ if (otmp == NULL) {
+ opt_printf_stderr("%s: Invalid Policy %s\n", prog, opt_arg());
+ return 0;
+ }
+ X509_VERIFY_PARAM_add0_policy(vpm, otmp);
+ break;
+ case OPT_V_PURPOSE:
+ /* purpose name -> purpose index */
+ i = X509_PURPOSE_get_by_sname(opt_arg());
+ if (i < 0) {
+ opt_printf_stderr("%s: Invalid purpose %s\n", prog, opt_arg());
+ return 0;
+ }
+
+ /* purpose index -> purpose object */
+ xptmp = X509_PURPOSE_get0(i);
+
+ /* purpose object -> purpose value */
+ i = X509_PURPOSE_get_id(xptmp);
+
+ if (!X509_VERIFY_PARAM_set_purpose(vpm, i)) {
+ opt_printf_stderr("%s: Internal error setting purpose %s\n",
+ prog, opt_arg());
+ return 0;
+ }
+ break;
+ case OPT_V_VERIFY_NAME:
+ vtmp = X509_VERIFY_PARAM_lookup(opt_arg());
+ if (vtmp == NULL) {
+ opt_printf_stderr("%s: Invalid verify name %s\n",
+ prog, opt_arg());
+ return 0;
+ }
+ X509_VERIFY_PARAM_set1(vpm, vtmp);
+ break;
+ case OPT_V_VERIFY_DEPTH:
+ i = atoi(opt_arg());
+ if (i >= 0)
+ X509_VERIFY_PARAM_set_depth(vpm, i);
+ break;
+ case OPT_V_VERIFY_AUTH_LEVEL:
+ i = atoi(opt_arg());
+ if (i >= 0)
+ X509_VERIFY_PARAM_set_auth_level(vpm, i);
+ break;
+ case OPT_V_ATTIME:
+ if (!opt_intmax(opt_arg(), &t))
+ return 0;
+ if (t != (time_t)t) {
+ opt_printf_stderr("%s: epoch time out of range %s\n",
+ prog, opt_arg());
+ return 0;
+ }
+ X509_VERIFY_PARAM_set_time(vpm, (time_t)t);
+ break;
+ case OPT_V_VERIFY_HOSTNAME:
+ if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0))
+ return 0;
+ break;
+ case OPT_V_VERIFY_EMAIL:
+ if (!X509_VERIFY_PARAM_set1_email(vpm, opt_arg(), 0))
+ return 0;
+ break;
+ case OPT_V_VERIFY_IP:
+ if (!X509_VERIFY_PARAM_set1_ip_asc(vpm, opt_arg()))
+ return 0;
+ break;
+ case OPT_V_IGNORE_CRITICAL:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_IGNORE_CRITICAL);
+ break;
+ case OPT_V_ISSUER_CHECKS:
+ /* NOP, deprecated */
+ break;
+ case OPT_V_CRL_CHECK:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CRL_CHECK);
+ break;
+ case OPT_V_CRL_CHECK_ALL:
+ X509_VERIFY_PARAM_set_flags(vpm,
+ X509_V_FLAG_CRL_CHECK |
+ X509_V_FLAG_CRL_CHECK_ALL);
+ break;
+ case OPT_V_POLICY_CHECK:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_POLICY_CHECK);
+ break;
+ case OPT_V_EXPLICIT_POLICY:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXPLICIT_POLICY);
+ break;
+ case OPT_V_INHIBIT_ANY:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_ANY);
+ break;
+ case OPT_V_INHIBIT_MAP:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_MAP);
+ break;
+ case OPT_V_X509_STRICT:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_X509_STRICT);
+ break;
+ case OPT_V_EXTENDED_CRL:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXTENDED_CRL_SUPPORT);
+ break;
+ case OPT_V_USE_DELTAS:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_USE_DELTAS);
+ break;
+ case OPT_V_POLICY_PRINT:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NOTIFY_POLICY);
+ break;
+ case OPT_V_CHECK_SS_SIG:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CHECK_SS_SIGNATURE);
+ break;
+ case OPT_V_TRUSTED_FIRST:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_TRUSTED_FIRST);
+ break;
+ case OPT_V_SUITEB_128_ONLY:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS_ONLY);
+ break;
+ case OPT_V_SUITEB_128:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS);
+ break;
+ case OPT_V_SUITEB_192:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_192_LOS);
+ break;
+ case OPT_V_PARTIAL_CHAIN:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN);
+ break;
+ case OPT_V_NO_ALT_CHAINS:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_ALT_CHAINS);
+ break;
+ case OPT_V_NO_CHECK_TIME:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME);
+ break;
+ case OPT_V_ALLOW_PROXY_CERTS:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_ALLOW_PROXY_CERTS);
+ break;
+ }
+ return 1;
+
+}
+
+void opt_begin(void)
+{
+ opt_index = 1;
+ arg = NULL;
+ flag = NULL;
+}
+
+/*
+ * Parse the next flag (and value if specified), return 0 if done, -1 on
+ * error, otherwise the flag's retval.
+ */
+int opt_next(void)
+{
+ char *p;
+ const OPTIONS *o;
+ int ival;
+ long lval;
+ unsigned long ulval;
+ ossl_intmax_t imval;
+ ossl_uintmax_t umval;
+
+ /* Look at current arg; at end of the list? */
+ arg = NULL;
+ p = argv[opt_index];
+ if (p == NULL)
+ return 0;
+
+ /* If word doesn't start with a -, we're done. */
+ if (*p != '-')
+ return 0;
+
+ /* Hit "--" ? We're done. */
+ opt_index++;
+ if (strcmp(p, "--") == 0)
+ return 0;
+
+ /* Allow -nnn and --nnn */
+ if (*++p == '-')
+ p++;
+ flag = p - 1;
+
+ /* If we have --flag=foo, snip it off */
+ if ((arg = strchr(p, '=')) != NULL)
+ *arg++ = '\0';
+ for (o = opts; o->name; ++o) {
+ /* If not this option, move on to the next one. */
+ if (!(strcmp(p, "h") == 0 && strcmp(o->name, "help") == 0)
+ && strcmp(p, o->name) != 0)
+ continue;
+
+ /* If it doesn't take a value, make sure none was given. */
+ if (o->valtype == 0 || o->valtype == '-') {
+ if (arg) {
+ opt_printf_stderr("%s: Option -%s does not take a value\n",
+ prog, p);
+ return -1;
+ }
+ return o->retval;
+ }
+
+ /* Want a value; get the next param if =foo not used. */
+ if (arg == NULL) {
+ if (argv[opt_index] == NULL) {
+ opt_printf_stderr("%s: Option -%s needs a value\n",
+ prog, o->name);
+ return -1;
+ }
+ arg = argv[opt_index++];
+ }
+
+ /* Syntax-check value. */
+ switch (o->valtype) {
+ default:
+ case 's':
+ case ':':
+ /* Just a string. */
+ break;
+ case '.':
+ /* Parameters */
+ break;
+ case '/':
+ if (opt_isdir(arg) > 0)
+ break;
+ opt_printf_stderr("%s: Not a directory: %s\n", prog, arg);
+ return -1;
+ case '<':
+ /* Input file. */
+ break;
+ case '>':
+ /* Output file. */
+ break;
+ case 'p':
+ case 'n':
+ case 'N':
+ if (!opt_int(arg, &ival))
+ return -1;
+ if (o->valtype == 'p' && ival <= 0) {
+ opt_printf_stderr("%s: Non-positive number \"%s\" for option -%s\n",
+ prog, arg, o->name);
+ return -1;
+ }
+ if (o->valtype == 'N' && ival < 0) {
+ opt_printf_stderr("%s: Negative number \"%s\" for option -%s\n",
+ prog, arg, o->name);
+ return -1;
+ }
+ break;
+ case 'M':
+ if (!opt_intmax(arg, &imval))
+ return -1;
+ break;
+ case 'U':
+ if (!opt_uintmax(arg, &umval))
+ return -1;
+ break;
+ case 'l':
+ if (!opt_long(arg, &lval))
+ return -1;
+ break;
+ case 'u':
+ if (!opt_ulong(arg, &ulval))
+ return -1;
+ break;
+ case 'c':
+ case 'E':
+ case 'F':
+ case 'f':
+ if (opt_format(arg,
+ o->valtype == 'c' ? OPT_FMT_PDS :
+ o->valtype == 'E' ? OPT_FMT_PDE :
+ o->valtype == 'F' ? OPT_FMT_PEMDER
+ : OPT_FMT_ANY, &ival))
+ break;
+ opt_printf_stderr("%s: Invalid format \"%s\" for option -%s\n",
+ prog, arg, o->name);
+ return -1;
+ }
+
+ /* Return the flag value. */
+ return o->retval;
+ }
+ if (unknown != NULL) {
+ dunno = p;
+ return unknown->retval;
+ }
+ opt_printf_stderr("%s: Unknown option: -%s\n", prog, p);
+ return -1;
+}
+
+/* Return the most recent flag parameter. */
+char *opt_arg(void)
+{
+ return arg;
+}
+
+/* Return the most recent flag (option name including the preceding '-'). */
+char *opt_flag(void)
+{
+ return flag;
+}
+
+/* Return the unknown option. */
+char *opt_unknown(void)
+{
+ return dunno;
+}
+
+/* Return the rest of the arguments after parsing flags. */
+char **opt_rest(void)
+{
+ return &argv[opt_index];
+}
+
+/* How many items in remaining args? */
+int opt_num_rest(void)
+{
+ int i = 0;
+ char **pp;
+
+ for (pp = opt_rest(); *pp; pp++, i++)
+ continue;
+ return i;
+}
+
+/* Return a string describing the parameter type. */
+static const char *valtype2param(const OPTIONS *o)
+{
+ switch (o->valtype) {
+ case 0:
+ case '-':
+ return "";
+ case ':':
+ return "uri";
+ case 's':
+ return "val";
+ case '/':
+ return "dir";
+ case '<':
+ return "infile";
+ case '>':
+ return "outfile";
+ case 'p':
+ return "+int";
+ case 'n':
+ return "int";
+ case 'l':
+ return "long";
+ case 'u':
+ return "ulong";
+ case 'E':
+ return "PEM|DER|ENGINE";
+ case 'F':
+ return "PEM|DER";
+ case 'f':
+ return "format";
+ case 'M':
+ return "intmax";
+ case 'N':
+ return "nonneg";
+ case 'U':
+ return "uintmax";
+ }
+ return "parm";
+}
+
+static void opt_print(const OPTIONS *o, int doingparams, int width)
+{
+ const char* help;
+ char start[80 + 1];
+ char *p;
+
+ help = o->helpstr ? o->helpstr : "(No additional info)";
+ if (o->name == OPT_HELP_STR) {
+ opt_printf_stderr(help, prog);
+ return;
+ }
+ if (o->name == OPT_SECTION_STR) {
+ opt_printf_stderr("\n");
+ opt_printf_stderr(help, prog);
+ return;
+ }
+ if (o->name == OPT_PARAM_STR) {
+ opt_printf_stderr("\nParameters:\n");
+ return;
+ }
+
+ /* Pad out prefix */
+ memset(start, ' ', sizeof(start) - 1);
+ start[sizeof(start) - 1] = '\0';
+
+ if (o->name == OPT_MORE_STR) {
+ /* Continuation of previous line; pad and print. */
+ start[width] = '\0';
+ opt_printf_stderr("%s %s\n", start, help);
+ return;
+ }
+
+ /* Build up the "-flag [param]" part. */
+ p = start;
+ *p++ = ' ';
+ if (!doingparams)
+ *p++ = '-';
+ if (o->name[0])
+ p += strlen(strcpy(p, o->name));
+ else
+ *p++ = '*';
+ if (o->valtype != '-') {
+ *p++ = ' ';
+ p += strlen(strcpy(p, valtype2param(o)));
+ }
+ *p = ' ';
+ if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) {
+ *p = '\0';
+ opt_printf_stderr("%s\n", start);
+ memset(start, ' ', sizeof(start));
+ }
+ start[width] = '\0';
+ opt_printf_stderr("%s %s\n", start, help);
+}
+
+void opt_help(const OPTIONS *list)
+{
+ const OPTIONS *o;
+ int i, sawparams = 0, width = 5;
+ int standard_prolog;
+ char start[80 + 1];
+
+ /* Starts with its own help message? */
+ standard_prolog = list[0].name != OPT_HELP_STR;
+
+ /* Find the widest help. */
+ for (o = list; o->name; o++) {
+ if (o->name == OPT_MORE_STR)
+ continue;
+ i = 2 + (int)strlen(o->name);
+ if (o->valtype != '-')
+ i += 1 + strlen(valtype2param(o));
+ if (i < MAX_OPT_HELP_WIDTH && i > width)
+ width = i;
+ OPENSSL_assert(i < (int)sizeof(start));
+ }
+
+ if (standard_prolog) {
+ opt_printf_stderr("Usage: %s [options]\n", prog);
+ if (list[0].name != OPT_SECTION_STR)
+ opt_printf_stderr("Valid options are:\n", prog);
+ }
+
+ /* Now let's print. */
+ for (o = list; o->name; o++) {
+ if (o->name == OPT_PARAM_STR)
+ sawparams = 1;
+ opt_print(o, sawparams, width);
+ }
+}
+
+/* opt_isdir section */
+#ifdef _WIN32
+# include <windows.h>
+int opt_isdir(const char *name)
+{
+ DWORD attr;
+# if defined(UNICODE) || defined(_UNICODE)
+ size_t i, len_0 = strlen(name) + 1;
+ WCHAR tempname[MAX_PATH];
+
+ if (len_0 > MAX_PATH)
+ return -1;
+
+# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
+ if (!MultiByteToWideChar(CP_ACP, 0, name, len_0, tempname, MAX_PATH))
+# endif
+ for (i = 0; i < len_0; i++)
+ tempname[i] = (WCHAR)name[i];
+
+ attr = GetFileAttributes(tempname);
+# else
+ attr = GetFileAttributes(name);
+# endif
+ if (attr == INVALID_FILE_ATTRIBUTES)
+ return -1;
+ return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0);
+}
+#else
+# include <sys/stat.h>
+# ifndef S_ISDIR
+# if defined(_S_IFMT) && defined(_S_IFDIR)
+# define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR)
+# else
+# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
+# endif
+# endif
+
+int opt_isdir(const char *name)
+{
+# if defined(S_ISDIR)
+ struct stat st;
+
+ if (stat(name, &st) == 0)
+ return S_ISDIR(st.st_mode);
+ else
+ return -1;
+# else
+ return -1;
+# endif
+}
+#endif
diff --git a/apps/lib/s_cb.c b/apps/lib/s_cb.c
new file mode 100644
index 000000000000..f2ddd94c3de4
--- /dev/null
+++ b/apps/lib/s_cb.c
@@ -0,0 +1,1569 @@
+/*
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* callback functions used by s_client, s_server, and s_time */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* for memcpy() and strcmp() */
+#include "apps.h"
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+#include <openssl/ssl.h>
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_DH
+# include <openssl/dh.h>
+#endif
+#include "s_apps.h"
+
+#define COOKIE_SECRET_LENGTH 16
+
+VERIFY_CB_ARGS verify_args = { -1, 0, X509_V_OK, 0 };
+
+#ifndef OPENSSL_NO_SOCK
+static unsigned char cookie_secret[COOKIE_SECRET_LENGTH];
+static int cookie_initialized = 0;
+#endif
+static BIO *bio_keylog = NULL;
+
+static const char *lookup(int val, const STRINT_PAIR* list, const char* def)
+{
+ for ( ; list->name; ++list)
+ if (list->retval == val)
+ return list->name;
+ return def;
+}
+
+int verify_callback(int ok, X509_STORE_CTX *ctx)
+{
+ X509 *err_cert;
+ int err, depth;
+
+ err_cert = X509_STORE_CTX_get_current_cert(ctx);
+ err = X509_STORE_CTX_get_error(ctx);
+ depth = X509_STORE_CTX_get_error_depth(ctx);
+
+ if (!verify_args.quiet || !ok) {
+ BIO_printf(bio_err, "depth=%d ", depth);
+ if (err_cert != NULL) {
+ X509_NAME_print_ex(bio_err,
+ X509_get_subject_name(err_cert),
+ 0, get_nameopt());
+ BIO_puts(bio_err, "\n");
+ } else {
+ BIO_puts(bio_err, "<no cert>\n");
+ }
+ }
+ if (!ok) {
+ BIO_printf(bio_err, "verify error:num=%d:%s\n", err,
+ X509_verify_cert_error_string(err));
+ if (verify_args.depth < 0 || verify_args.depth >= depth) {
+ if (!verify_args.return_error)
+ ok = 1;
+ verify_args.error = err;
+ } else {
+ ok = 0;
+ verify_args.error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+ }
+ }
+ switch (err) {
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+ if (err_cert != NULL) {
+ BIO_puts(bio_err, "issuer= ");
+ X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert),
+ 0, get_nameopt());
+ BIO_puts(bio_err, "\n");
+ }
+ break;
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+ if (err_cert != NULL) {
+ BIO_printf(bio_err, "notBefore=");
+ ASN1_TIME_print(bio_err, X509_get0_notBefore(err_cert));
+ BIO_printf(bio_err, "\n");
+ }
+ break;
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+ if (err_cert != NULL) {
+ BIO_printf(bio_err, "notAfter=");
+ ASN1_TIME_print(bio_err, X509_get0_notAfter(err_cert));
+ BIO_printf(bio_err, "\n");
+ }
+ break;
+ case X509_V_ERR_NO_EXPLICIT_POLICY:
+ if (!verify_args.quiet)
+ policies_print(ctx);
+ break;
+ }
+ if (err == X509_V_OK && ok == 2 && !verify_args.quiet)
+ policies_print(ctx);
+ if (ok && !verify_args.quiet)
+ BIO_printf(bio_err, "verify return:%d\n", ok);
+ return ok;
+}
+
+int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file)
+{
+ if (cert_file != NULL) {
+ if (SSL_CTX_use_certificate_file(ctx, cert_file,
+ SSL_FILETYPE_PEM) <= 0) {
+ BIO_printf(bio_err, "unable to get certificate from '%s'\n",
+ cert_file);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ if (key_file == NULL)
+ key_file = cert_file;
+ if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) {
+ BIO_printf(bio_err, "unable to get private key from '%s'\n",
+ key_file);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+
+ /*
+ * If we are using DSA, we can copy the parameters from the private
+ * key
+ */
+
+ /*
+ * Now we know that a key and cert have been set against the SSL
+ * context
+ */
+ if (!SSL_CTX_check_private_key(ctx)) {
+ BIO_printf(bio_err,
+ "Private key does not match the certificate public key\n");
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
+ STACK_OF(X509) *chain, int build_chain)
+{
+ int chflags = chain ? SSL_BUILD_CHAIN_FLAG_CHECK : 0;
+
+ if (cert == NULL)
+ return 1;
+ if (SSL_CTX_use_certificate(ctx, cert) <= 0) {
+ BIO_printf(bio_err, "error setting certificate\n");
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+
+ if (SSL_CTX_use_PrivateKey(ctx, key) <= 0) {
+ BIO_printf(bio_err, "error setting private key\n");
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+
+ /*
+ * Now we know that a key and cert have been set against the SSL context
+ */
+ if (!SSL_CTX_check_private_key(ctx)) {
+ BIO_printf(bio_err,
+ "Private key does not match the certificate public key\n");
+ return 0;
+ }
+ if (chain && !SSL_CTX_set1_chain(ctx, chain)) {
+ BIO_printf(bio_err, "error setting certificate chain\n");
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ if (build_chain && !SSL_CTX_build_cert_chain(ctx, chflags)) {
+ BIO_printf(bio_err, "error building certificate chain\n");
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ return 1;
+}
+
+static STRINT_PAIR cert_type_list[] = {
+ {"RSA sign", TLS_CT_RSA_SIGN},
+ {"DSA sign", TLS_CT_DSS_SIGN},
+ {"RSA fixed DH", TLS_CT_RSA_FIXED_DH},
+ {"DSS fixed DH", TLS_CT_DSS_FIXED_DH},
+ {"ECDSA sign", TLS_CT_ECDSA_SIGN},
+ {"RSA fixed ECDH", TLS_CT_RSA_FIXED_ECDH},
+ {"ECDSA fixed ECDH", TLS_CT_ECDSA_FIXED_ECDH},
+ {"GOST01 Sign", TLS_CT_GOST01_SIGN},
+ {"GOST12 Sign", TLS_CT_GOST12_IANA_SIGN},
+ {NULL}
+};
+
+static void ssl_print_client_cert_types(BIO *bio, SSL *s)
+{
+ const unsigned char *p;
+ int i;
+ int cert_type_num = SSL_get0_certificate_types(s, &p);
+
+ if (!cert_type_num)
+ return;
+ BIO_puts(bio, "Client Certificate Types: ");
+ for (i = 0; i < cert_type_num; i++) {
+ unsigned char cert_type = p[i];
+ const char *cname = lookup((int)cert_type, cert_type_list, NULL);
+
+ if (i)
+ BIO_puts(bio, ", ");
+ if (cname != NULL)
+ BIO_puts(bio, cname);
+ else
+ BIO_printf(bio, "UNKNOWN (%d),", cert_type);
+ }
+ BIO_puts(bio, "\n");
+}
+
+static const char *get_sigtype(int nid)
+{
+ switch (nid) {
+ case EVP_PKEY_RSA:
+ return "RSA";
+
+ case EVP_PKEY_RSA_PSS:
+ return "RSA-PSS";
+
+ case EVP_PKEY_DSA:
+ return "DSA";
+
+ case EVP_PKEY_EC:
+ return "ECDSA";
+
+ case NID_ED25519:
+ return "Ed25519";
+
+ case NID_ED448:
+ return "Ed448";
+
+ case NID_id_GostR3410_2001:
+ return "gost2001";
+
+ case NID_id_GostR3410_2012_256:
+ return "gost2012_256";
+
+ case NID_id_GostR3410_2012_512:
+ return "gost2012_512";
+
+ default:
+ return NULL;
+ }
+}
+
+static int do_print_sigalgs(BIO *out, SSL *s, int shared)
+{
+ int i, nsig, client;
+
+ client = SSL_is_server(s) ? 0 : 1;
+ if (shared)
+ nsig = SSL_get_shared_sigalgs(s, 0, NULL, NULL, NULL, NULL, NULL);
+ else
+ nsig = SSL_get_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL);
+ if (nsig == 0)
+ return 1;
+
+ if (shared)
+ BIO_puts(out, "Shared ");
+
+ if (client)
+ BIO_puts(out, "Requested ");
+ BIO_puts(out, "Signature Algorithms: ");
+ for (i = 0; i < nsig; i++) {
+ int hash_nid, sign_nid;
+ unsigned char rhash, rsign;
+ const char *sstr = NULL;
+ if (shared)
+ SSL_get_shared_sigalgs(s, i, &sign_nid, &hash_nid, NULL,
+ &rsign, &rhash);
+ else
+ SSL_get_sigalgs(s, i, &sign_nid, &hash_nid, NULL, &rsign, &rhash);
+ if (i)
+ BIO_puts(out, ":");
+ sstr = get_sigtype(sign_nid);
+ if (sstr)
+ BIO_printf(out, "%s", sstr);
+ else
+ BIO_printf(out, "0x%02X", (int)rsign);
+ if (hash_nid != NID_undef)
+ BIO_printf(out, "+%s", OBJ_nid2sn(hash_nid));
+ else if (sstr == NULL)
+ BIO_printf(out, "+0x%02X", (int)rhash);
+ }
+ BIO_puts(out, "\n");
+ return 1;
+}
+
+int ssl_print_sigalgs(BIO *out, SSL *s)
+{
+ int nid;
+
+ if (!SSL_is_server(s))
+ ssl_print_client_cert_types(out, s);
+ do_print_sigalgs(out, s, 0);
+ do_print_sigalgs(out, s, 1);
+ if (SSL_get_peer_signature_nid(s, &nid) && nid != NID_undef)
+ BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(nid));
+ if (SSL_get_peer_signature_type_nid(s, &nid))
+ BIO_printf(out, "Peer signature type: %s\n", get_sigtype(nid));
+ return 1;
+}
+
+#ifndef OPENSSL_NO_EC
+int ssl_print_point_formats(BIO *out, SSL *s)
+{
+ int i, nformats;
+ const char *pformats;
+
+ nformats = SSL_get0_ec_point_formats(s, &pformats);
+ if (nformats <= 0)
+ return 1;
+ BIO_puts(out, "Supported Elliptic Curve Point Formats: ");
+ for (i = 0; i < nformats; i++, pformats++) {
+ if (i)
+ BIO_puts(out, ":");
+ switch (*pformats) {
+ case TLSEXT_ECPOINTFORMAT_uncompressed:
+ BIO_puts(out, "uncompressed");
+ break;
+
+ case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime:
+ BIO_puts(out, "ansiX962_compressed_prime");
+ break;
+
+ case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2:
+ BIO_puts(out, "ansiX962_compressed_char2");
+ break;
+
+ default:
+ BIO_printf(out, "unknown(%d)", (int)*pformats);
+ break;
+
+ }
+ }
+ BIO_puts(out, "\n");
+ return 1;
+}
+
+int ssl_print_groups(BIO *out, SSL *s, int noshared)
+{
+ int i, ngroups, *groups, nid;
+
+ ngroups = SSL_get1_groups(s, NULL);
+ if (ngroups <= 0)
+ return 1;
+ groups = app_malloc(ngroups * sizeof(int), "groups to print");
+ SSL_get1_groups(s, groups);
+
+ BIO_puts(out, "Supported groups: ");
+ for (i = 0; i < ngroups; i++) {
+ if (i)
+ BIO_puts(out, ":");
+ nid = groups[i];
+ BIO_printf(out, "%s", SSL_group_to_name(s, nid));
+ }
+ OPENSSL_free(groups);
+ if (noshared) {
+ BIO_puts(out, "\n");
+ return 1;
+ }
+ BIO_puts(out, "\nShared groups: ");
+ ngroups = SSL_get_shared_group(s, -1);
+ for (i = 0; i < ngroups; i++) {
+ if (i)
+ BIO_puts(out, ":");
+ nid = SSL_get_shared_group(s, i);
+ BIO_printf(out, "%s", SSL_group_to_name(s, nid));
+ }
+ if (ngroups == 0)
+ BIO_puts(out, "NONE");
+ BIO_puts(out, "\n");
+ return 1;
+}
+#endif
+
+int ssl_print_tmp_key(BIO *out, SSL *s)
+{
+ EVP_PKEY *key;
+
+ if (!SSL_get_peer_tmp_key(s, &key))
+ return 1;
+ BIO_puts(out, "Server Temp Key: ");
+ switch (EVP_PKEY_get_id(key)) {
+ case EVP_PKEY_RSA:
+ BIO_printf(out, "RSA, %d bits\n", EVP_PKEY_get_bits(key));
+ break;
+
+ case EVP_PKEY_DH:
+ BIO_printf(out, "DH, %d bits\n", EVP_PKEY_get_bits(key));
+ break;
+#ifndef OPENSSL_NO_EC
+ case EVP_PKEY_EC:
+ {
+ char name[80];
+ size_t name_len;
+
+ if (!EVP_PKEY_get_utf8_string_param(key, OSSL_PKEY_PARAM_GROUP_NAME,
+ name, sizeof(name), &name_len))
+ strcpy(name, "?");
+ BIO_printf(out, "ECDH, %s, %d bits\n", name, EVP_PKEY_get_bits(key));
+ }
+ break;
+#endif
+ default:
+ BIO_printf(out, "%s, %d bits\n", OBJ_nid2sn(EVP_PKEY_get_id(key)),
+ EVP_PKEY_get_bits(key));
+ }
+ EVP_PKEY_free(key);
+ return 1;
+}
+
+long bio_dump_callback(BIO *bio, int cmd, const char *argp, size_t len,
+ int argi, long argl, int ret, size_t *processed)
+{
+ BIO *out;
+
+ out = (BIO *)BIO_get_callback_arg(bio);
+ if (out == NULL)
+ return ret;
+
+ if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) {
+ if (ret > 0 && processed != NULL) {
+ BIO_printf(out, "read from %p [%p] (%zu bytes => %zu (0x%zX))\n",
+ (void *)bio, (void *)argp, len, *processed, *processed);
+ BIO_dump(out, argp, (int)*processed);
+ } else {
+ BIO_printf(out, "read from %p [%p] (%zu bytes => %d)\n",
+ (void *)bio, (void *)argp, len, ret);
+ }
+ } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) {
+ if (ret > 0 && processed != NULL) {
+ BIO_printf(out, "write to %p [%p] (%zu bytes => %zu (0x%zX))\n",
+ (void *)bio, (void *)argp, len, *processed, *processed);
+ BIO_dump(out, argp, (int)*processed);
+ } else {
+ BIO_printf(out, "write to %p [%p] (%zu bytes => %d)\n",
+ (void *)bio, (void *)argp, len, ret);
+ }
+ }
+ return ret;
+}
+
+void apps_ssl_info_callback(const SSL *s, int where, int ret)
+{
+ const char *str;
+ int w;
+
+ w = where & ~SSL_ST_MASK;
+
+ if (w & SSL_ST_CONNECT)
+ str = "SSL_connect";
+ else if (w & SSL_ST_ACCEPT)
+ str = "SSL_accept";
+ else
+ str = "undefined";
+
+ if (where & SSL_CB_LOOP) {
+ BIO_printf(bio_err, "%s:%s\n", str, SSL_state_string_long(s));
+ } else if (where & SSL_CB_ALERT) {
+ str = (where & SSL_CB_READ) ? "read" : "write";
+ BIO_printf(bio_err, "SSL3 alert %s:%s:%s\n",
+ str,
+ SSL_alert_type_string_long(ret),
+ SSL_alert_desc_string_long(ret));
+ } else if (where & SSL_CB_EXIT) {
+ if (ret == 0)
+ BIO_printf(bio_err, "%s:failed in %s\n",
+ str, SSL_state_string_long(s));
+ else if (ret < 0)
+ BIO_printf(bio_err, "%s:error in %s\n",
+ str, SSL_state_string_long(s));
+ }
+}
+
+static STRINT_PAIR ssl_versions[] = {
+ {"SSL 3.0", SSL3_VERSION},
+ {"TLS 1.0", TLS1_VERSION},
+ {"TLS 1.1", TLS1_1_VERSION},
+ {"TLS 1.2", TLS1_2_VERSION},
+ {"TLS 1.3", TLS1_3_VERSION},
+ {"DTLS 1.0", DTLS1_VERSION},
+ {"DTLS 1.0 (bad)", DTLS1_BAD_VER},
+ {NULL}
+};
+
+static STRINT_PAIR alert_types[] = {
+ {" close_notify", 0},
+ {" end_of_early_data", 1},
+ {" unexpected_message", 10},
+ {" bad_record_mac", 20},
+ {" decryption_failed", 21},
+ {" record_overflow", 22},
+ {" decompression_failure", 30},
+ {" handshake_failure", 40},
+ {" bad_certificate", 42},
+ {" unsupported_certificate", 43},
+ {" certificate_revoked", 44},
+ {" certificate_expired", 45},
+ {" certificate_unknown", 46},
+ {" illegal_parameter", 47},
+ {" unknown_ca", 48},
+ {" access_denied", 49},
+ {" decode_error", 50},
+ {" decrypt_error", 51},
+ {" export_restriction", 60},
+ {" protocol_version", 70},
+ {" insufficient_security", 71},
+ {" internal_error", 80},
+ {" inappropriate_fallback", 86},
+ {" user_canceled", 90},
+ {" no_renegotiation", 100},
+ {" missing_extension", 109},
+ {" unsupported_extension", 110},
+ {" certificate_unobtainable", 111},
+ {" unrecognized_name", 112},
+ {" bad_certificate_status_response", 113},
+ {" bad_certificate_hash_value", 114},
+ {" unknown_psk_identity", 115},
+ {" certificate_required", 116},
+ {NULL}
+};
+
+static STRINT_PAIR handshakes[] = {
+ {", HelloRequest", SSL3_MT_HELLO_REQUEST},
+ {", ClientHello", SSL3_MT_CLIENT_HELLO},
+ {", ServerHello", SSL3_MT_SERVER_HELLO},
+ {", HelloVerifyRequest", DTLS1_MT_HELLO_VERIFY_REQUEST},
+ {", NewSessionTicket", SSL3_MT_NEWSESSION_TICKET},
+ {", EndOfEarlyData", SSL3_MT_END_OF_EARLY_DATA},
+ {", EncryptedExtensions", SSL3_MT_ENCRYPTED_EXTENSIONS},
+ {", Certificate", SSL3_MT_CERTIFICATE},
+ {", ServerKeyExchange", SSL3_MT_SERVER_KEY_EXCHANGE},
+ {", CertificateRequest", SSL3_MT_CERTIFICATE_REQUEST},
+ {", ServerHelloDone", SSL3_MT_SERVER_DONE},
+ {", CertificateVerify", SSL3_MT_CERTIFICATE_VERIFY},
+ {", ClientKeyExchange", SSL3_MT_CLIENT_KEY_EXCHANGE},
+ {", Finished", SSL3_MT_FINISHED},
+ {", CertificateUrl", SSL3_MT_CERTIFICATE_URL},
+ {", CertificateStatus", SSL3_MT_CERTIFICATE_STATUS},
+ {", SupplementalData", SSL3_MT_SUPPLEMENTAL_DATA},
+ {", KeyUpdate", SSL3_MT_KEY_UPDATE},
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ {", NextProto", SSL3_MT_NEXT_PROTO},
+#endif
+ {", MessageHash", SSL3_MT_MESSAGE_HASH},
+ {NULL}
+};
+
+void msg_cb(int write_p, int version, int content_type, const void *buf,
+ size_t len, SSL *ssl, void *arg)
+{
+ BIO *bio = arg;
+ const char *str_write_p = write_p ? ">>>" : "<<<";
+ char tmpbuf[128];
+ const char *str_version, *str_content_type = "", *str_details1 = "", *str_details2 = "";
+ const unsigned char* bp = buf;
+
+ if (version == SSL3_VERSION ||
+ version == TLS1_VERSION ||
+ version == TLS1_1_VERSION ||
+ version == TLS1_2_VERSION ||
+ version == TLS1_3_VERSION ||
+ version == DTLS1_VERSION || version == DTLS1_BAD_VER) {
+ str_version = lookup(version, ssl_versions, "???");
+ switch (content_type) {
+ case SSL3_RT_CHANGE_CIPHER_SPEC:
+ /* type 20 */
+ str_content_type = ", ChangeCipherSpec";
+ break;
+ case SSL3_RT_ALERT:
+ /* type 21 */
+ str_content_type = ", Alert";
+ str_details1 = ", ???";
+ if (len == 2) {
+ switch (bp[0]) {
+ case 1:
+ str_details1 = ", warning";
+ break;
+ case 2:
+ str_details1 = ", fatal";
+ break;
+ }
+ str_details2 = lookup((int)bp[1], alert_types, " ???");
+ }
+ break;
+ case SSL3_RT_HANDSHAKE:
+ /* type 22 */
+ str_content_type = ", Handshake";
+ str_details1 = "???";
+ if (len > 0)
+ str_details1 = lookup((int)bp[0], handshakes, "???");
+ break;
+ case SSL3_RT_APPLICATION_DATA:
+ /* type 23 */
+ str_content_type = ", ApplicationData";
+ break;
+ case SSL3_RT_HEADER:
+ /* type 256 */
+ str_content_type = ", RecordHeader";
+ break;
+ case SSL3_RT_INNER_CONTENT_TYPE:
+ /* type 257 */
+ str_content_type = ", InnerContent";
+ break;
+ default:
+ BIO_snprintf(tmpbuf, sizeof(tmpbuf)-1, ", Unknown (content_type=%d)", content_type);
+ str_content_type = tmpbuf;
+ }
+ } else {
+ BIO_snprintf(tmpbuf, sizeof(tmpbuf)-1, "Not TLS data or unknown version (version=%d, content_type=%d)", version, content_type);
+ str_version = tmpbuf;
+ }
+
+ BIO_printf(bio, "%s %s%s [length %04lx]%s%s\n", str_write_p, str_version,
+ str_content_type, (unsigned long)len, str_details1,
+ str_details2);
+
+ if (len > 0) {
+ size_t num, i;
+
+ BIO_printf(bio, " ");
+ num = len;
+ for (i = 0; i < num; i++) {
+ if (i % 16 == 0 && i > 0)
+ BIO_printf(bio, "\n ");
+ BIO_printf(bio, " %02x", ((const unsigned char *)buf)[i]);
+ }
+ if (i < len)
+ BIO_printf(bio, " ...");
+ BIO_printf(bio, "\n");
+ }
+ (void)BIO_flush(bio);
+}
+
+static STRINT_PAIR tlsext_types[] = {
+ {"server name", TLSEXT_TYPE_server_name},
+ {"max fragment length", TLSEXT_TYPE_max_fragment_length},
+ {"client certificate URL", TLSEXT_TYPE_client_certificate_url},
+ {"trusted CA keys", TLSEXT_TYPE_trusted_ca_keys},
+ {"truncated HMAC", TLSEXT_TYPE_truncated_hmac},
+ {"status request", TLSEXT_TYPE_status_request},
+ {"user mapping", TLSEXT_TYPE_user_mapping},
+ {"client authz", TLSEXT_TYPE_client_authz},
+ {"server authz", TLSEXT_TYPE_server_authz},
+ {"cert type", TLSEXT_TYPE_cert_type},
+ {"supported_groups", TLSEXT_TYPE_supported_groups},
+ {"EC point formats", TLSEXT_TYPE_ec_point_formats},
+ {"SRP", TLSEXT_TYPE_srp},
+ {"signature algorithms", TLSEXT_TYPE_signature_algorithms},
+ {"use SRTP", TLSEXT_TYPE_use_srtp},
+ {"session ticket", TLSEXT_TYPE_session_ticket},
+ {"renegotiation info", TLSEXT_TYPE_renegotiate},
+ {"signed certificate timestamps", TLSEXT_TYPE_signed_certificate_timestamp},
+ {"TLS padding", TLSEXT_TYPE_padding},
+#ifdef TLSEXT_TYPE_next_proto_neg
+ {"next protocol", TLSEXT_TYPE_next_proto_neg},
+#endif
+#ifdef TLSEXT_TYPE_encrypt_then_mac
+ {"encrypt-then-mac", TLSEXT_TYPE_encrypt_then_mac},
+#endif
+#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
+ {"application layer protocol negotiation",
+ TLSEXT_TYPE_application_layer_protocol_negotiation},
+#endif
+#ifdef TLSEXT_TYPE_extended_master_secret
+ {"extended master secret", TLSEXT_TYPE_extended_master_secret},
+#endif
+ {"key share", TLSEXT_TYPE_key_share},
+ {"supported versions", TLSEXT_TYPE_supported_versions},
+ {"psk", TLSEXT_TYPE_psk},
+ {"psk kex modes", TLSEXT_TYPE_psk_kex_modes},
+ {"certificate authorities", TLSEXT_TYPE_certificate_authorities},
+ {"post handshake auth", TLSEXT_TYPE_post_handshake_auth},
+ {NULL}
+};
+
+/* from rfc8446 4.2.3. + gost (https://tools.ietf.org/id/draft-smyshlyaev-tls12-gost-suites-04.html) */
+static STRINT_PAIR signature_tls13_scheme_list[] = {
+ {"rsa_pkcs1_sha1", 0x0201 /* TLSEXT_SIGALG_rsa_pkcs1_sha1 */},
+ {"ecdsa_sha1", 0x0203 /* TLSEXT_SIGALG_ecdsa_sha1 */},
+/* {"rsa_pkcs1_sha224", 0x0301 TLSEXT_SIGALG_rsa_pkcs1_sha224}, not in rfc8446 */
+/* {"ecdsa_sha224", 0x0303 TLSEXT_SIGALG_ecdsa_sha224} not in rfc8446 */
+ {"rsa_pkcs1_sha256", 0x0401 /* TLSEXT_SIGALG_rsa_pkcs1_sha256 */},
+ {"ecdsa_secp256r1_sha256", 0x0403 /* TLSEXT_SIGALG_ecdsa_secp256r1_sha256 */},
+ {"rsa_pkcs1_sha384", 0x0501 /* TLSEXT_SIGALG_rsa_pkcs1_sha384 */},
+ {"ecdsa_secp384r1_sha384", 0x0503 /* TLSEXT_SIGALG_ecdsa_secp384r1_sha384 */},
+ {"rsa_pkcs1_sha512", 0x0601 /* TLSEXT_SIGALG_rsa_pkcs1_sha512 */},
+ {"ecdsa_secp521r1_sha512", 0x0603 /* TLSEXT_SIGALG_ecdsa_secp521r1_sha512 */},
+ {"rsa_pss_rsae_sha256", 0x0804 /* TLSEXT_SIGALG_rsa_pss_rsae_sha256 */},
+ {"rsa_pss_rsae_sha384", 0x0805 /* TLSEXT_SIGALG_rsa_pss_rsae_sha384 */},
+ {"rsa_pss_rsae_sha512", 0x0806 /* TLSEXT_SIGALG_rsa_pss_rsae_sha512 */},
+ {"ed25519", 0x0807 /* TLSEXT_SIGALG_ed25519 */},
+ {"ed448", 0x0808 /* TLSEXT_SIGALG_ed448 */},
+ {"rsa_pss_pss_sha256", 0x0809 /* TLSEXT_SIGALG_rsa_pss_pss_sha256 */},
+ {"rsa_pss_pss_sha384", 0x080a /* TLSEXT_SIGALG_rsa_pss_pss_sha384 */},
+ {"rsa_pss_pss_sha512", 0x080b /* TLSEXT_SIGALG_rsa_pss_pss_sha512 */},
+ {"gostr34102001", 0xeded /* TLSEXT_SIGALG_gostr34102001_gostr3411 */},
+ {"gostr34102012_256", 0xeeee /* TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 */},
+ {"gostr34102012_512", 0xefef /* TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 */},
+ {NULL}
+};
+
+/* from rfc5246 7.4.1.4.1. */
+static STRINT_PAIR signature_tls12_alg_list[] = {
+ {"anonymous", TLSEXT_signature_anonymous /* 0 */},
+ {"RSA", TLSEXT_signature_rsa /* 1 */},
+ {"DSA", TLSEXT_signature_dsa /* 2 */},
+ {"ECDSA", TLSEXT_signature_ecdsa /* 3 */},
+ {NULL}
+};
+
+/* from rfc5246 7.4.1.4.1. */
+static STRINT_PAIR signature_tls12_hash_list[] = {
+ {"none", TLSEXT_hash_none /* 0 */},
+ {"MD5", TLSEXT_hash_md5 /* 1 */},
+ {"SHA1", TLSEXT_hash_sha1 /* 2 */},
+ {"SHA224", TLSEXT_hash_sha224 /* 3 */},
+ {"SHA256", TLSEXT_hash_sha256 /* 4 */},
+ {"SHA384", TLSEXT_hash_sha384 /* 5 */},
+ {"SHA512", TLSEXT_hash_sha512 /* 6 */},
+ {NULL}
+};
+
+void tlsext_cb(SSL *s, int client_server, int type,
+ const unsigned char *data, int len, void *arg)
+{
+ BIO *bio = arg;
+ const char *extname = lookup(type, tlsext_types, "unknown");
+
+ BIO_printf(bio, "TLS %s extension \"%s\" (id=%d), len=%d\n",
+ client_server ? "server" : "client", extname, type, len);
+ BIO_dump(bio, (const char *)data, len);
+ (void)BIO_flush(bio);
+}
+
+#ifndef OPENSSL_NO_SOCK
+int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie,
+ size_t *cookie_len)
+{
+ unsigned char *buffer = NULL;
+ size_t length = 0;
+ unsigned short port;
+ BIO_ADDR *lpeer = NULL, *peer = NULL;
+ int res = 0;
+
+ /* Initialize a random secret */
+ if (!cookie_initialized) {
+ if (RAND_bytes(cookie_secret, COOKIE_SECRET_LENGTH) <= 0) {
+ BIO_printf(bio_err, "error setting random cookie secret\n");
+ return 0;
+ }
+ cookie_initialized = 1;
+ }
+
+ if (SSL_is_dtls(ssl)) {
+ lpeer = peer = BIO_ADDR_new();
+ if (peer == NULL) {
+ BIO_printf(bio_err, "memory full\n");
+ return 0;
+ }
+
+ /* Read peer information */
+ (void)BIO_dgram_get_peer(SSL_get_rbio(ssl), peer);
+ } else {
+ peer = ourpeer;
+ }
+
+ /* Create buffer with peer's address and port */
+ if (!BIO_ADDR_rawaddress(peer, NULL, &length)) {
+ BIO_printf(bio_err, "Failed getting peer address\n");
+ BIO_ADDR_free(lpeer);
+ return 0;
+ }
+ OPENSSL_assert(length != 0);
+ port = BIO_ADDR_rawport(peer);
+ length += sizeof(port);
+ buffer = app_malloc(length, "cookie generate buffer");
+
+ memcpy(buffer, &port, sizeof(port));
+ BIO_ADDR_rawaddress(peer, buffer + sizeof(port), NULL);
+
+ if (EVP_Q_mac(NULL, "HMAC", NULL, "SHA1", NULL,
+ cookie_secret, COOKIE_SECRET_LENGTH, buffer, length,
+ cookie, DTLS1_COOKIE_LENGTH, cookie_len) == NULL) {
+ BIO_printf(bio_err,
+ "Error calculating HMAC-SHA1 of buffer with secret\n");
+ goto end;
+ }
+ res = 1;
+end:
+ OPENSSL_free(buffer);
+ BIO_ADDR_free(lpeer);
+
+ return res;
+}
+
+int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie,
+ size_t cookie_len)
+{
+ unsigned char result[EVP_MAX_MD_SIZE];
+ size_t resultlength;
+
+ /* Note: we check cookie_initialized because if it's not,
+ * it cannot be valid */
+ if (cookie_initialized
+ && generate_stateless_cookie_callback(ssl, result, &resultlength)
+ && cookie_len == resultlength
+ && memcmp(result, cookie, resultlength) == 0)
+ return 1;
+
+ return 0;
+}
+
+int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
+ unsigned int *cookie_len)
+{
+ size_t temp = 0;
+ int res = generate_stateless_cookie_callback(ssl, cookie, &temp);
+
+ if (res != 0)
+ *cookie_len = (unsigned int)temp;
+ return res;
+}
+
+int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
+ unsigned int cookie_len)
+{
+ return verify_stateless_cookie_callback(ssl, cookie, cookie_len);
+}
+
+#endif
+
+/*
+ * Example of extended certificate handling. Where the standard support of
+ * one certificate per algorithm is not sufficient an application can decide
+ * which certificate(s) to use at runtime based on whatever criteria it deems
+ * appropriate.
+ */
+
+/* Linked list of certificates, keys and chains */
+struct ssl_excert_st {
+ int certform;
+ const char *certfile;
+ int keyform;
+ const char *keyfile;
+ const char *chainfile;
+ X509 *cert;
+ EVP_PKEY *key;
+ STACK_OF(X509) *chain;
+ int build_chain;
+ struct ssl_excert_st *next, *prev;
+};
+
+static STRINT_PAIR chain_flags[] = {
+ {"Overall Validity", CERT_PKEY_VALID},
+ {"Sign with EE key", CERT_PKEY_SIGN},
+ {"EE signature", CERT_PKEY_EE_SIGNATURE},
+ {"CA signature", CERT_PKEY_CA_SIGNATURE},
+ {"EE key parameters", CERT_PKEY_EE_PARAM},
+ {"CA key parameters", CERT_PKEY_CA_PARAM},
+ {"Explicitly sign with EE key", CERT_PKEY_EXPLICIT_SIGN},
+ {"Issuer Name", CERT_PKEY_ISSUER_NAME},
+ {"Certificate Type", CERT_PKEY_CERT_TYPE},
+ {NULL}
+};
+
+static void print_chain_flags(SSL *s, int flags)
+{
+ STRINT_PAIR *pp;
+
+ for (pp = chain_flags; pp->name; ++pp)
+ BIO_printf(bio_err, "\t%s: %s\n",
+ pp->name,
+ (flags & pp->retval) ? "OK" : "NOT OK");
+ BIO_printf(bio_err, "\tSuite B: ");
+ if (SSL_set_cert_flags(s, 0) & SSL_CERT_FLAG_SUITEB_128_LOS)
+ BIO_puts(bio_err, flags & CERT_PKEY_SUITEB ? "OK\n" : "NOT OK\n");
+ else
+ BIO_printf(bio_err, "not tested\n");
+}
+
+/*
+ * Very basic selection callback: just use any certificate chain reported as
+ * valid. More sophisticated could prioritise according to local policy.
+ */
+static int set_cert_cb(SSL *ssl, void *arg)
+{
+ int i, rv;
+ SSL_EXCERT *exc = arg;
+#ifdef CERT_CB_TEST_RETRY
+ static int retry_cnt;
+
+ if (retry_cnt < 5) {
+ retry_cnt++;
+ BIO_printf(bio_err,
+ "Certificate callback retry test: count %d\n",
+ retry_cnt);
+ return -1;
+ }
+#endif
+ SSL_certs_clear(ssl);
+
+ if (exc == NULL)
+ return 1;
+
+ /*
+ * Go to end of list and traverse backwards since we prepend newer
+ * entries this retains the original order.
+ */
+ while (exc->next != NULL)
+ exc = exc->next;
+
+ i = 0;
+
+ while (exc != NULL) {
+ i++;
+ rv = SSL_check_chain(ssl, exc->cert, exc->key, exc->chain);
+ BIO_printf(bio_err, "Checking cert chain %d:\nSubject: ", i);
+ X509_NAME_print_ex(bio_err, X509_get_subject_name(exc->cert), 0,
+ get_nameopt());
+ BIO_puts(bio_err, "\n");
+ print_chain_flags(ssl, rv);
+ if (rv & CERT_PKEY_VALID) {
+ if (!SSL_use_certificate(ssl, exc->cert)
+ || !SSL_use_PrivateKey(ssl, exc->key)) {
+ return 0;
+ }
+ /*
+ * NB: we wouldn't normally do this as it is not efficient
+ * building chains on each connection better to cache the chain
+ * in advance.
+ */
+ if (exc->build_chain) {
+ if (!SSL_build_cert_chain(ssl, 0))
+ return 0;
+ } else if (exc->chain != NULL) {
+ if (!SSL_set1_chain(ssl, exc->chain))
+ return 0;
+ }
+ }
+ exc = exc->prev;
+ }
+ return 1;
+}
+
+void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc)
+{
+ SSL_CTX_set_cert_cb(ctx, set_cert_cb, exc);
+}
+
+static int ssl_excert_prepend(SSL_EXCERT **pexc)
+{
+ SSL_EXCERT *exc = app_malloc(sizeof(*exc), "prepend cert");
+
+ memset(exc, 0, sizeof(*exc));
+
+ exc->next = *pexc;
+ *pexc = exc;
+
+ if (exc->next) {
+ exc->certform = exc->next->certform;
+ exc->keyform = exc->next->keyform;
+ exc->next->prev = exc;
+ } else {
+ exc->certform = FORMAT_PEM;
+ exc->keyform = FORMAT_PEM;
+ }
+ return 1;
+
+}
+
+void ssl_excert_free(SSL_EXCERT *exc)
+{
+ SSL_EXCERT *curr;
+
+ if (exc == NULL)
+ return;
+ while (exc) {
+ X509_free(exc->cert);
+ EVP_PKEY_free(exc->key);
+ sk_X509_pop_free(exc->chain, X509_free);
+ curr = exc;
+ exc = exc->next;
+ OPENSSL_free(curr);
+ }
+}
+
+int load_excert(SSL_EXCERT **pexc)
+{
+ SSL_EXCERT *exc = *pexc;
+
+ if (exc == NULL)
+ return 1;
+ /* If nothing in list, free and set to NULL */
+ if (exc->certfile == NULL && exc->next == NULL) {
+ ssl_excert_free(exc);
+ *pexc = NULL;
+ return 1;
+ }
+ for (; exc; exc = exc->next) {
+ if (exc->certfile == NULL) {
+ BIO_printf(bio_err, "Missing filename\n");
+ return 0;
+ }
+ exc->cert = load_cert(exc->certfile, exc->certform,
+ "Server Certificate");
+ if (exc->cert == NULL)
+ return 0;
+ if (exc->keyfile != NULL) {
+ exc->key = load_key(exc->keyfile, exc->keyform,
+ 0, NULL, NULL, "server key");
+ } else {
+ exc->key = load_key(exc->certfile, exc->certform,
+ 0, NULL, NULL, "server key");
+ }
+ if (exc->key == NULL)
+ return 0;
+ if (exc->chainfile != NULL) {
+ if (!load_certs(exc->chainfile, 0, &exc->chain, NULL, "server chain"))
+ return 0;
+ }
+ }
+ return 1;
+}
+
+enum range { OPT_X_ENUM };
+
+int args_excert(int opt, SSL_EXCERT **pexc)
+{
+ SSL_EXCERT *exc = *pexc;
+
+ assert(opt > OPT_X__FIRST);
+ assert(opt < OPT_X__LAST);
+
+ if (exc == NULL) {
+ if (!ssl_excert_prepend(&exc)) {
+ BIO_printf(bio_err, " %s: Error initialising xcert\n",
+ opt_getprog());
+ goto err;
+ }
+ *pexc = exc;
+ }
+
+ switch ((enum range)opt) {
+ case OPT_X__FIRST:
+ case OPT_X__LAST:
+ return 0;
+ case OPT_X_CERT:
+ if (exc->certfile != NULL && !ssl_excert_prepend(&exc)) {
+ BIO_printf(bio_err, "%s: Error adding xcert\n", opt_getprog());
+ goto err;
+ }
+ *pexc = exc;
+ exc->certfile = opt_arg();
+ break;
+ case OPT_X_KEY:
+ if (exc->keyfile != NULL) {
+ BIO_printf(bio_err, "%s: Key already specified\n", opt_getprog());
+ goto err;
+ }
+ exc->keyfile = opt_arg();
+ break;
+ case OPT_X_CHAIN:
+ if (exc->chainfile != NULL) {
+ BIO_printf(bio_err, "%s: Chain already specified\n",
+ opt_getprog());
+ goto err;
+ }
+ exc->chainfile = opt_arg();
+ break;
+ case OPT_X_CHAIN_BUILD:
+ exc->build_chain = 1;
+ break;
+ case OPT_X_CERTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &exc->certform))
+ return 0;
+ break;
+ case OPT_X_KEYFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &exc->keyform))
+ return 0;
+ break;
+ }
+ return 1;
+
+ err:
+ ERR_print_errors(bio_err);
+ ssl_excert_free(exc);
+ *pexc = NULL;
+ return 0;
+}
+
+static void print_raw_cipherlist(SSL *s)
+{
+ const unsigned char *rlist;
+ static const unsigned char scsv_id[] = { 0, 0xFF };
+ size_t i, rlistlen, num;
+
+ if (!SSL_is_server(s))
+ return;
+ num = SSL_get0_raw_cipherlist(s, NULL);
+ OPENSSL_assert(num == 2);
+ rlistlen = SSL_get0_raw_cipherlist(s, &rlist);
+ BIO_puts(bio_err, "Client cipher list: ");
+ for (i = 0; i < rlistlen; i += num, rlist += num) {
+ const SSL_CIPHER *c = SSL_CIPHER_find(s, rlist);
+ if (i)
+ BIO_puts(bio_err, ":");
+ if (c != NULL) {
+ BIO_puts(bio_err, SSL_CIPHER_get_name(c));
+ } else if (memcmp(rlist, scsv_id, num) == 0) {
+ BIO_puts(bio_err, "SCSV");
+ } else {
+ size_t j;
+ BIO_puts(bio_err, "0x");
+ for (j = 0; j < num; j++)
+ BIO_printf(bio_err, "%02X", rlist[j]);
+ }
+ }
+ BIO_puts(bio_err, "\n");
+}
+
+/*
+ * Hex encoder for TLSA RRdata, not ':' delimited.
+ */
+static char *hexencode(const unsigned char *data, size_t len)
+{
+ static const char *hex = "0123456789abcdef";
+ char *out;
+ char *cp;
+ size_t outlen = 2 * len + 1;
+ int ilen = (int) outlen;
+
+ if (outlen < len || ilen < 0 || outlen != (size_t)ilen) {
+ BIO_printf(bio_err, "%s: %zu-byte buffer too large to hexencode\n",
+ opt_getprog(), len);
+ exit(1);
+ }
+ cp = out = app_malloc(ilen, "TLSA hex data buffer");
+
+ while (len-- > 0) {
+ *cp++ = hex[(*data >> 4) & 0x0f];
+ *cp++ = hex[*data++ & 0x0f];
+ }
+ *cp = '\0';
+ return out;
+}
+
+void print_verify_detail(SSL *s, BIO *bio)
+{
+ int mdpth;
+ EVP_PKEY *mspki;
+ long verify_err = SSL_get_verify_result(s);
+
+ if (verify_err == X509_V_OK) {
+ const char *peername = SSL_get0_peername(s);
+
+ BIO_printf(bio, "Verification: OK\n");
+ if (peername != NULL)
+ BIO_printf(bio, "Verified peername: %s\n", peername);
+ } else {
+ const char *reason = X509_verify_cert_error_string(verify_err);
+
+ BIO_printf(bio, "Verification error: %s\n", reason);
+ }
+
+ if ((mdpth = SSL_get0_dane_authority(s, NULL, &mspki)) >= 0) {
+ uint8_t usage, selector, mtype;
+ const unsigned char *data = NULL;
+ size_t dlen = 0;
+ char *hexdata;
+
+ mdpth = SSL_get0_dane_tlsa(s, &usage, &selector, &mtype, &data, &dlen);
+
+ /*
+ * The TLSA data field can be quite long when it is a certificate,
+ * public key or even a SHA2-512 digest. Because the initial octets of
+ * ASN.1 certificates and public keys contain mostly boilerplate OIDs
+ * and lengths, we show the last 12 bytes of the data instead, as these
+ * are more likely to distinguish distinct TLSA records.
+ */
+#define TLSA_TAIL_SIZE 12
+ if (dlen > TLSA_TAIL_SIZE)
+ hexdata = hexencode(data + dlen - TLSA_TAIL_SIZE, TLSA_TAIL_SIZE);
+ else
+ hexdata = hexencode(data, dlen);
+ BIO_printf(bio, "DANE TLSA %d %d %d %s%s %s at depth %d\n",
+ usage, selector, mtype,
+ (dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata,
+ (mspki != NULL) ? "signed the certificate" :
+ mdpth ? "matched TA certificate" : "matched EE certificate",
+ mdpth);
+ OPENSSL_free(hexdata);
+ }
+}
+
+void print_ssl_summary(SSL *s)
+{
+ const SSL_CIPHER *c;
+ X509 *peer;
+
+ BIO_printf(bio_err, "Protocol version: %s\n", SSL_get_version(s));
+ print_raw_cipherlist(s);
+ c = SSL_get_current_cipher(s);
+ BIO_printf(bio_err, "Ciphersuite: %s\n", SSL_CIPHER_get_name(c));
+ do_print_sigalgs(bio_err, s, 0);
+ peer = SSL_get0_peer_certificate(s);
+ if (peer != NULL) {
+ int nid;
+
+ BIO_puts(bio_err, "Peer certificate: ");
+ X509_NAME_print_ex(bio_err, X509_get_subject_name(peer),
+ 0, get_nameopt());
+ BIO_puts(bio_err, "\n");
+ if (SSL_get_peer_signature_nid(s, &nid))
+ BIO_printf(bio_err, "Hash used: %s\n", OBJ_nid2sn(nid));
+ if (SSL_get_peer_signature_type_nid(s, &nid))
+ BIO_printf(bio_err, "Signature type: %s\n", get_sigtype(nid));
+ print_verify_detail(s, bio_err);
+ } else {
+ BIO_puts(bio_err, "No peer certificate\n");
+ }
+#ifndef OPENSSL_NO_EC
+ ssl_print_point_formats(bio_err, s);
+ if (SSL_is_server(s))
+ ssl_print_groups(bio_err, s, 1);
+ else
+ ssl_print_tmp_key(bio_err, s);
+#else
+ if (!SSL_is_server(s))
+ ssl_print_tmp_key(bio_err, s);
+#endif
+}
+
+int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str,
+ SSL_CTX *ctx)
+{
+ int i;
+
+ SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
+ for (i = 0; i < sk_OPENSSL_STRING_num(str); i += 2) {
+ const char *flag = sk_OPENSSL_STRING_value(str, i);
+ const char *arg = sk_OPENSSL_STRING_value(str, i + 1);
+
+ if (SSL_CONF_cmd(cctx, flag, arg) <= 0) {
+ BIO_printf(bio_err, "Call to SSL_CONF_cmd(%s, %s) failed\n",
+ flag, arg == NULL ? "<NULL>" : arg);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ }
+ if (!SSL_CONF_CTX_finish(cctx)) {
+ BIO_puts(bio_err, "Error finishing context\n");
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ return 1;
+}
+
+static int add_crls_store(X509_STORE *st, STACK_OF(X509_CRL) *crls)
+{
+ X509_CRL *crl;
+ int i, ret = 1;
+
+ for (i = 0; i < sk_X509_CRL_num(crls); i++) {
+ crl = sk_X509_CRL_value(crls, i);
+ if (!X509_STORE_add_crl(st, crl))
+ ret = 0;
+ }
+ return ret;
+}
+
+int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, int crl_download)
+{
+ X509_STORE *st;
+
+ st = SSL_CTX_get_cert_store(ctx);
+ add_crls_store(st, crls);
+ if (crl_download)
+ store_setup_crl_download(st);
+ return 1;
+}
+
+int ssl_load_stores(SSL_CTX *ctx,
+ const char *vfyCApath, const char *vfyCAfile,
+ const char *vfyCAstore,
+ const char *chCApath, const char *chCAfile,
+ const char *chCAstore,
+ STACK_OF(X509_CRL) *crls, int crl_download)
+{
+ X509_STORE *vfy = NULL, *ch = NULL;
+ int rv = 0;
+
+ if (vfyCApath != NULL || vfyCAfile != NULL || vfyCAstore != NULL) {
+ vfy = X509_STORE_new();
+ if (vfy == NULL)
+ goto err;
+ if (vfyCAfile != NULL && !X509_STORE_load_file(vfy, vfyCAfile))
+ goto err;
+ if (vfyCApath != NULL && !X509_STORE_load_path(vfy, vfyCApath))
+ goto err;
+ if (vfyCAstore != NULL && !X509_STORE_load_store(vfy, vfyCAstore))
+ goto err;
+ add_crls_store(vfy, crls);
+ SSL_CTX_set1_verify_cert_store(ctx, vfy);
+ if (crl_download)
+ store_setup_crl_download(vfy);
+ }
+ if (chCApath != NULL || chCAfile != NULL || chCAstore != NULL) {
+ ch = X509_STORE_new();
+ if (ch == NULL)
+ goto err;
+ if (chCAfile != NULL && !X509_STORE_load_file(ch, chCAfile))
+ goto err;
+ if (chCApath != NULL && !X509_STORE_load_path(ch, chCApath))
+ goto err;
+ if (chCAstore != NULL && !X509_STORE_load_store(ch, chCAstore))
+ goto err;
+ SSL_CTX_set1_chain_cert_store(ctx, ch);
+ }
+ rv = 1;
+ err:
+ X509_STORE_free(vfy);
+ X509_STORE_free(ch);
+ return rv;
+}
+
+/* Verbose print out of security callback */
+
+typedef struct {
+ BIO *out;
+ int verbose;
+ int (*old_cb) (const SSL *s, const SSL_CTX *ctx, int op, int bits, int nid,
+ void *other, void *ex);
+} security_debug_ex;
+
+static STRINT_PAIR callback_types[] = {
+ {"Supported Ciphersuite", SSL_SECOP_CIPHER_SUPPORTED},
+ {"Shared Ciphersuite", SSL_SECOP_CIPHER_SHARED},
+ {"Check Ciphersuite", SSL_SECOP_CIPHER_CHECK},
+#ifndef OPENSSL_NO_DH
+ {"Temp DH key bits", SSL_SECOP_TMP_DH},
+#endif
+ {"Supported Curve", SSL_SECOP_CURVE_SUPPORTED},
+ {"Shared Curve", SSL_SECOP_CURVE_SHARED},
+ {"Check Curve", SSL_SECOP_CURVE_CHECK},
+ {"Supported Signature Algorithm", SSL_SECOP_SIGALG_SUPPORTED},
+ {"Shared Signature Algorithm", SSL_SECOP_SIGALG_SHARED},
+ {"Check Signature Algorithm", SSL_SECOP_SIGALG_CHECK},
+ {"Signature Algorithm mask", SSL_SECOP_SIGALG_MASK},
+ {"Certificate chain EE key", SSL_SECOP_EE_KEY},
+ {"Certificate chain CA key", SSL_SECOP_CA_KEY},
+ {"Peer Chain EE key", SSL_SECOP_PEER_EE_KEY},
+ {"Peer Chain CA key", SSL_SECOP_PEER_CA_KEY},
+ {"Certificate chain CA digest", SSL_SECOP_CA_MD},
+ {"Peer chain CA digest", SSL_SECOP_PEER_CA_MD},
+ {"SSL compression", SSL_SECOP_COMPRESSION},
+ {"Session ticket", SSL_SECOP_TICKET},
+ {NULL}
+};
+
+static int security_callback_debug(const SSL *s, const SSL_CTX *ctx,
+ int op, int bits, int nid,
+ void *other, void *ex)
+{
+ security_debug_ex *sdb = ex;
+ int rv, show_bits = 1, cert_md = 0;
+ const char *nm;
+ int show_nm;
+
+ rv = sdb->old_cb(s, ctx, op, bits, nid, other, ex);
+ if (rv == 1 && sdb->verbose < 2)
+ return 1;
+ BIO_puts(sdb->out, "Security callback: ");
+
+ nm = lookup(op, callback_types, NULL);
+ show_nm = nm != NULL;
+ switch (op) {
+ case SSL_SECOP_TICKET:
+ case SSL_SECOP_COMPRESSION:
+ show_bits = 0;
+ show_nm = 0;
+ break;
+ case SSL_SECOP_VERSION:
+ BIO_printf(sdb->out, "Version=%s", lookup(nid, ssl_versions, "???"));
+ show_bits = 0;
+ show_nm = 0;
+ break;
+ case SSL_SECOP_CA_MD:
+ case SSL_SECOP_PEER_CA_MD:
+ cert_md = 1;
+ break;
+ case SSL_SECOP_SIGALG_SUPPORTED:
+ case SSL_SECOP_SIGALG_SHARED:
+ case SSL_SECOP_SIGALG_CHECK:
+ case SSL_SECOP_SIGALG_MASK:
+ show_nm = 0;
+ break;
+ }
+ if (show_nm)
+ BIO_printf(sdb->out, "%s=", nm);
+
+ switch (op & SSL_SECOP_OTHER_TYPE) {
+
+ case SSL_SECOP_OTHER_CIPHER:
+ BIO_puts(sdb->out, SSL_CIPHER_get_name(other));
+ break;
+
+#ifndef OPENSSL_NO_EC
+ case SSL_SECOP_OTHER_CURVE:
+ {
+ const char *cname;
+ cname = EC_curve_nid2nist(nid);
+ if (cname == NULL)
+ cname = OBJ_nid2sn(nid);
+ BIO_puts(sdb->out, cname);
+ }
+ break;
+#endif
+ case SSL_SECOP_OTHER_CERT:
+ {
+ if (cert_md) {
+ int sig_nid = X509_get_signature_nid(other);
+
+ BIO_puts(sdb->out, OBJ_nid2sn(sig_nid));
+ } else {
+ EVP_PKEY *pkey = X509_get0_pubkey(other);
+
+ if (pkey == NULL) {
+ BIO_printf(sdb->out, "Public key missing");
+ } else {
+ const char *algname = "";
+
+ EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL,
+ &algname, EVP_PKEY_get0_asn1(pkey));
+ BIO_printf(sdb->out, "%s, bits=%d",
+ algname, EVP_PKEY_get_bits(pkey));
+ }
+ }
+ break;
+ }
+ case SSL_SECOP_OTHER_SIGALG:
+ {
+ const unsigned char *salg = other;
+ const char *sname = NULL;
+ int raw_sig_code = (salg[0] << 8) + salg[1]; /* always big endian (msb, lsb) */
+ /* raw_sig_code: signature_scheme from tls1.3, or signature_and_hash from tls1.2 */
+
+ if (nm != NULL)
+ BIO_printf(sdb->out, "%s", nm);
+ else
+ BIO_printf(sdb->out, "s_cb.c:security_callback_debug op=0x%x", op);
+
+ sname = lookup(raw_sig_code, signature_tls13_scheme_list, NULL);
+ if (sname != NULL) {
+ BIO_printf(sdb->out, " scheme=%s", sname);
+ } else {
+ int alg_code = salg[1];
+ int hash_code = salg[0];
+ const char *alg_str = lookup(alg_code, signature_tls12_alg_list, NULL);
+ const char *hash_str = lookup(hash_code, signature_tls12_hash_list, NULL);
+
+ if (alg_str != NULL && hash_str != NULL)
+ BIO_printf(sdb->out, " digest=%s, algorithm=%s", hash_str, alg_str);
+ else
+ BIO_printf(sdb->out, " scheme=unknown(0x%04x)", raw_sig_code);
+ }
+ }
+
+ }
+
+ if (show_bits)
+ BIO_printf(sdb->out, ", security bits=%d", bits);
+ BIO_printf(sdb->out, ": %s\n", rv ? "yes" : "no");
+ return rv;
+}
+
+void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose)
+{
+ static security_debug_ex sdb;
+
+ sdb.out = bio_err;
+ sdb.verbose = verbose;
+ sdb.old_cb = SSL_CTX_get_security_callback(ctx);
+ SSL_CTX_set_security_callback(ctx, security_callback_debug);
+ SSL_CTX_set0_security_ex_data(ctx, &sdb);
+}
+
+static void keylog_callback(const SSL *ssl, const char *line)
+{
+ if (bio_keylog == NULL) {
+ BIO_printf(bio_err, "Keylog callback is invoked without valid file!\n");
+ return;
+ }
+
+ /*
+ * There might be concurrent writers to the keylog file, so we must ensure
+ * that the given line is written at once.
+ */
+ BIO_printf(bio_keylog, "%s\n", line);
+ (void)BIO_flush(bio_keylog);
+}
+
+int set_keylog_file(SSL_CTX *ctx, const char *keylog_file)
+{
+ /* Close any open files */
+ BIO_free_all(bio_keylog);
+ bio_keylog = NULL;
+
+ if (ctx == NULL || keylog_file == NULL) {
+ /* Keylogging is disabled, OK. */
+ return 0;
+ }
+
+ /*
+ * Append rather than write in order to allow concurrent modification.
+ * Furthermore, this preserves existing keylog files which is useful when
+ * the tool is run multiple times.
+ */
+ bio_keylog = BIO_new_file(keylog_file, "a");
+ if (bio_keylog == NULL) {
+ BIO_printf(bio_err, "Error writing keylog file %s\n", keylog_file);
+ return 1;
+ }
+
+ /* Write a header for seekable, empty files (this excludes pipes). */
+ if (BIO_tell(bio_keylog) == 0) {
+ BIO_puts(bio_keylog,
+ "# SSL/TLS secrets log file, generated by OpenSSL\n");
+ (void)BIO_flush(bio_keylog);
+ }
+ SSL_CTX_set_keylog_callback(ctx, keylog_callback);
+ return 0;
+}
+
+void print_ca_names(BIO *bio, SSL *s)
+{
+ const char *cs = SSL_is_server(s) ? "server" : "client";
+ const STACK_OF(X509_NAME) *sk = SSL_get0_peer_CA_list(s);
+ int i;
+
+ if (sk == NULL || sk_X509_NAME_num(sk) == 0) {
+ if (!SSL_is_server(s))
+ BIO_printf(bio, "---\nNo %s certificate CA names sent\n", cs);
+ return;
+ }
+
+ BIO_printf(bio, "---\nAcceptable %s certificate CA names\n",cs);
+ for (i = 0; i < sk_X509_NAME_num(sk); i++) {
+ X509_NAME_print_ex(bio, sk_X509_NAME_value(sk, i), 0, get_nameopt());
+ BIO_write(bio, "\n", 1);
+ }
+}
diff --git a/apps/lib/s_socket.c b/apps/lib/s_socket.c
new file mode 100644
index 000000000000..059afe47b904
--- /dev/null
+++ b/apps/lib/s_socket.c
@@ -0,0 +1,455 @@
+/*
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* socket-related functions used by s_client and s_server */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <openssl/opensslconf.h>
+
+/*
+ * With IPv6, it looks like Digital has mixed up the proper order of
+ * recursive header file inclusion, resulting in the compiler complaining
+ * that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is
+ * needed to have fileno() declared correctly... So let's define u_int
+ */
+#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT)
+# define __U_INT
+typedef unsigned int u_int;
+#endif
+
+#ifdef _WIN32
+# include <process.h>
+
+/* MSVC renamed some POSIX functions to have an underscore prefix. */
+# ifdef _MSC_VER
+# define getpid _getpid
+# endif
+#endif
+
+#ifndef OPENSSL_NO_SOCK
+
+# include "apps.h"
+# include "s_apps.h"
+# include "internal/sockets.h"
+
+# if defined(__TANDEM)
+# if defined(OPENSSL_TANDEM_FLOSS)
+# include <floss.h(floss_read)>
+# endif
+# endif
+
+# include <openssl/bio.h>
+# include <openssl/err.h>
+
+/* Keep track of our peer's address for the cookie callback */
+BIO_ADDR *ourpeer = NULL;
+
+/*
+ * init_client - helper routine to set up socket communication
+ * @sock: pointer to storage of resulting socket.
+ * @host: the host name or path (for AF_UNIX) to connect to.
+ * @port: the port to connect to (ignored for AF_UNIX).
+ * @bindhost: source host or path (for AF_UNIX).
+ * @bindport: source port (ignored for AF_UNIX).
+ * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or
+ * AF_UNSPEC
+ * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM
+ * @protocol: socket protocol, e.g. IPPROTO_TCP or IPPROTO_UDP (or 0 for any)
+ *
+ * This will create a socket and use it to connect to a host:port, or if
+ * family == AF_UNIX, to the path found in host.
+ *
+ * If the host has more than one address, it will try them one by one until
+ * a successful connection is established. The resulting socket will be
+ * found in *sock on success, it will be given INVALID_SOCKET otherwise.
+ *
+ * Returns 1 on success, 0 on failure.
+ */
+int init_client(int *sock, const char *host, const char *port,
+ const char *bindhost, const char *bindport,
+ int family, int type, int protocol)
+{
+ BIO_ADDRINFO *res = NULL;
+ BIO_ADDRINFO *bindaddr = NULL;
+ const BIO_ADDRINFO *ai = NULL;
+ const BIO_ADDRINFO *bi = NULL;
+ int found = 0;
+ int ret;
+
+ if (BIO_sock_init() != 1)
+ return 0;
+
+ ret = BIO_lookup_ex(host, port, BIO_LOOKUP_CLIENT, family, type, protocol,
+ &res);
+ if (ret == 0) {
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+
+ if (bindhost != NULL || bindport != NULL) {
+ ret = BIO_lookup_ex(bindhost, bindport, BIO_LOOKUP_CLIENT,
+ family, type, protocol, &bindaddr);
+ if (ret == 0) {
+ ERR_print_errors (bio_err);
+ goto out;
+ }
+ }
+
+ ret = 0;
+ for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
+ /* Admittedly, these checks are quite paranoid, we should not get
+ * anything in the BIO_ADDRINFO chain that we haven't
+ * asked for. */
+ OPENSSL_assert((family == AF_UNSPEC
+ || family == BIO_ADDRINFO_family(ai))
+ && (type == 0 || type == BIO_ADDRINFO_socktype(ai))
+ && (protocol == 0
+ || protocol == BIO_ADDRINFO_protocol(ai)));
+
+ if (bindaddr != NULL) {
+ for (bi = bindaddr; bi != NULL; bi = BIO_ADDRINFO_next(bi)) {
+ if (BIO_ADDRINFO_family(bi) == BIO_ADDRINFO_family(ai))
+ break;
+ }
+ if (bi == NULL)
+ continue;
+ ++found;
+ }
+
+ *sock = BIO_socket(BIO_ADDRINFO_family(ai), BIO_ADDRINFO_socktype(ai),
+ BIO_ADDRINFO_protocol(ai), 0);
+ if (*sock == INVALID_SOCKET) {
+ /* Maybe the kernel doesn't support the socket family, even if
+ * BIO_lookup() added it in the returned result...
+ */
+ continue;
+ }
+
+ if (bi != NULL) {
+ if (!BIO_bind(*sock, BIO_ADDRINFO_address(bi),
+ BIO_SOCK_REUSEADDR)) {
+ BIO_closesocket(*sock);
+ *sock = INVALID_SOCKET;
+ break;
+ }
+ }
+
+#ifndef OPENSSL_NO_SCTP
+ if (protocol == IPPROTO_SCTP) {
+ /*
+ * For SCTP we have to set various options on the socket prior to
+ * connecting. This is done automatically by BIO_new_dgram_sctp().
+ * We don't actually need the created BIO though so we free it again
+ * immediately.
+ */
+ BIO *tmpbio = BIO_new_dgram_sctp(*sock, BIO_NOCLOSE);
+
+ if (tmpbio == NULL) {
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ BIO_free(tmpbio);
+ }
+#endif
+
+ if (!BIO_connect(*sock, BIO_ADDRINFO_address(ai),
+ BIO_ADDRINFO_protocol(ai) == IPPROTO_TCP ? BIO_SOCK_NODELAY : 0)) {
+ BIO_closesocket(*sock);
+ *sock = INVALID_SOCKET;
+ continue;
+ }
+
+ /* Success, don't try any more addresses */
+ break;
+ }
+
+ if (*sock == INVALID_SOCKET) {
+ if (bindaddr != NULL && !found) {
+ BIO_printf(bio_err, "Can't bind %saddress for %s%s%s\n",
+#ifdef AF_INET6
+ BIO_ADDRINFO_family(res) == AF_INET6 ? "IPv6 " :
+#endif
+ BIO_ADDRINFO_family(res) == AF_INET ? "IPv4 " :
+ BIO_ADDRINFO_family(res) == AF_UNIX ? "unix " : "",
+ bindhost != NULL ? bindhost : "",
+ bindport != NULL ? ":" : "",
+ bindport != NULL ? bindport : "");
+ ERR_clear_error();
+ ret = 0;
+ }
+ ERR_print_errors(bio_err);
+ } else {
+ /* Remove any stale errors from previous connection attempts */
+ ERR_clear_error();
+ ret = 1;
+ }
+out:
+ if (bindaddr != NULL) {
+ BIO_ADDRINFO_free (bindaddr);
+ }
+ BIO_ADDRINFO_free(res);
+ return ret;
+}
+
+int report_server_accept(BIO *out, int asock, int with_address, int with_pid)
+{
+ int success = 1;
+
+ if (BIO_printf(out, "ACCEPT") <= 0)
+ return 0;
+ if (with_address) {
+ union BIO_sock_info_u info;
+ char *hostname = NULL;
+ char *service = NULL;
+
+ if ((info.addr = BIO_ADDR_new()) != NULL
+ && BIO_sock_info(asock, BIO_SOCK_INFO_ADDRESS, &info)
+ && (hostname = BIO_ADDR_hostname_string(info.addr, 1)) != NULL
+ && (service = BIO_ADDR_service_string(info.addr, 1)) != NULL) {
+ success = BIO_printf(out,
+ strchr(hostname, ':') == NULL
+ ? /* IPv4 */ " %s:%s"
+ : /* IPv6 */ " [%s]:%s",
+ hostname, service) > 0;
+ } else {
+ (void)BIO_printf(out, "unknown:error\n");
+ success = 0;
+ }
+ OPENSSL_free(hostname);
+ OPENSSL_free(service);
+ BIO_ADDR_free(info.addr);
+ }
+ if (with_pid)
+ success = success && BIO_printf(out, " PID=%d", getpid()) > 0;
+ success = success && BIO_printf(out, "\n") > 0;
+ (void)BIO_flush(out);
+
+ return success;
+}
+
+/*
+ * do_server - helper routine to perform a server operation
+ * @accept_sock: pointer to storage of resulting socket.
+ * @host: the host name or path (for AF_UNIX) to connect to.
+ * @port: the port to connect to (ignored for AF_UNIX).
+ * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or
+ * AF_UNSPEC
+ * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM
+ * @cb: pointer to a function that receives the accepted socket and
+ * should perform the communication with the connecting client.
+ * @context: pointer to memory that's passed verbatim to the cb function.
+ * @naccept: number of times an incoming connect should be accepted. If -1,
+ * unlimited number.
+ *
+ * This will create a socket and use it to listen to a host:port, or if
+ * family == AF_UNIX, to the path found in host, then start accepting
+ * incoming connections and run cb on the resulting socket.
+ *
+ * 0 on failure, something other on success.
+ */
+int do_server(int *accept_sock, const char *host, const char *port,
+ int family, int type, int protocol, do_server_cb cb,
+ unsigned char *context, int naccept, BIO *bio_s_out)
+{
+ int asock = 0;
+ int sock;
+ int i;
+ BIO_ADDRINFO *res = NULL;
+ const BIO_ADDRINFO *next;
+ int sock_family, sock_type, sock_protocol, sock_port;
+ const BIO_ADDR *sock_address;
+ int sock_family_fallback = AF_UNSPEC;
+ const BIO_ADDR *sock_address_fallback = NULL;
+ int sock_options = BIO_SOCK_REUSEADDR;
+ int ret = 0;
+
+ if (BIO_sock_init() != 1)
+ return 0;
+
+ if (!BIO_lookup_ex(host, port, BIO_LOOKUP_SERVER, family, type, protocol,
+ &res)) {
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+
+ /* Admittedly, these checks are quite paranoid, we should not get
+ * anything in the BIO_ADDRINFO chain that we haven't asked for */
+ OPENSSL_assert((family == AF_UNSPEC || family == BIO_ADDRINFO_family(res))
+ && (type == 0 || type == BIO_ADDRINFO_socktype(res))
+ && (protocol == 0 || protocol == BIO_ADDRINFO_protocol(res)));
+
+ sock_family = BIO_ADDRINFO_family(res);
+ sock_type = BIO_ADDRINFO_socktype(res);
+ sock_protocol = BIO_ADDRINFO_protocol(res);
+ sock_address = BIO_ADDRINFO_address(res);
+ next = BIO_ADDRINFO_next(res);
+#ifdef AF_INET6
+ if (sock_family == AF_INET6)
+ sock_options |= BIO_SOCK_V6_ONLY;
+ if (next != NULL
+ && BIO_ADDRINFO_socktype(next) == sock_type
+ && BIO_ADDRINFO_protocol(next) == sock_protocol) {
+ if (sock_family == AF_INET
+ && BIO_ADDRINFO_family(next) == AF_INET6) {
+ /* In case AF_INET6 is returned but not supported by the
+ * kernel, retry with the first detected address family */
+ sock_family_fallback = sock_family;
+ sock_address_fallback = sock_address;
+ sock_family = AF_INET6;
+ sock_address = BIO_ADDRINFO_address(next);
+ } else if (sock_family == AF_INET6
+ && BIO_ADDRINFO_family(next) == AF_INET) {
+ sock_options &= ~BIO_SOCK_V6_ONLY;
+ }
+ }
+#endif
+
+ asock = BIO_socket(sock_family, sock_type, sock_protocol, 0);
+ if (asock == INVALID_SOCKET && sock_family_fallback != AF_UNSPEC) {
+ asock = BIO_socket(sock_family_fallback, sock_type, sock_protocol, 0);
+ sock_address = sock_address_fallback;
+ }
+ if (asock == INVALID_SOCKET
+ || !BIO_listen(asock, sock_address, sock_options)) {
+ BIO_ADDRINFO_free(res);
+ ERR_print_errors(bio_err);
+ if (asock != INVALID_SOCKET)
+ BIO_closesocket(asock);
+ goto end;
+ }
+
+#ifndef OPENSSL_NO_SCTP
+ if (protocol == IPPROTO_SCTP) {
+ /*
+ * For SCTP we have to set various options on the socket prior to
+ * accepting. This is done automatically by BIO_new_dgram_sctp().
+ * We don't actually need the created BIO though so we free it again
+ * immediately.
+ */
+ BIO *tmpbio = BIO_new_dgram_sctp(asock, BIO_NOCLOSE);
+
+ if (tmpbio == NULL) {
+ BIO_closesocket(asock);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ BIO_free(tmpbio);
+ }
+#endif
+
+ sock_port = BIO_ADDR_rawport(sock_address);
+
+ BIO_ADDRINFO_free(res);
+ res = NULL;
+
+ if (!report_server_accept(bio_s_out, asock, sock_port == 0, 0)) {
+ BIO_closesocket(asock);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (accept_sock != NULL)
+ *accept_sock = asock;
+ for (;;) {
+ char sink[64];
+ struct timeval timeout;
+ fd_set readfds;
+
+ if (type == SOCK_STREAM) {
+ BIO_ADDR_free(ourpeer);
+ ourpeer = BIO_ADDR_new();
+ if (ourpeer == NULL) {
+ BIO_closesocket(asock);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ do {
+ sock = BIO_accept_ex(asock, ourpeer, 0);
+ } while (sock < 0 && BIO_sock_should_retry(sock));
+ if (sock < 0) {
+ ERR_print_errors(bio_err);
+ BIO_closesocket(asock);
+ break;
+ }
+ BIO_set_tcp_ndelay(sock, 1);
+ i = (*cb)(sock, type, protocol, context);
+
+ /*
+ * If we ended with an alert being sent, but still with data in the
+ * network buffer to be read, then calling BIO_closesocket() will
+ * result in a TCP-RST being sent. On some platforms (notably
+ * Windows) then this will result in the peer immediately abandoning
+ * the connection including any buffered alert data before it has
+ * had a chance to be read. Shutting down the sending side first,
+ * and then closing the socket sends TCP-FIN first followed by
+ * TCP-RST. This seems to allow the peer to read the alert data.
+ */
+ shutdown(sock, 1); /* SHUT_WR */
+ /*
+ * We just said we have nothing else to say, but it doesn't mean
+ * that the other side has nothing. It's even recommended to
+ * consume incoming data. [In testing context this ensures that
+ * alerts are passed on...]
+ */
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 500000; /* some extreme round-trip */
+ do {
+ FD_ZERO(&readfds);
+ openssl_fdset(sock, &readfds);
+ } while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0
+ && readsocket(sock, sink, sizeof(sink)) > 0);
+
+ BIO_closesocket(sock);
+ } else {
+ i = (*cb)(asock, type, protocol, context);
+ }
+
+ if (naccept != -1)
+ naccept--;
+ if (i < 0 || naccept == 0) {
+ BIO_closesocket(asock);
+ ret = i;
+ break;
+ }
+ }
+ end:
+# ifdef AF_UNIX
+ if (family == AF_UNIX)
+ unlink(host);
+# endif
+ BIO_ADDR_free(ourpeer);
+ ourpeer = NULL;
+ return ret;
+}
+
+void do_ssl_shutdown(SSL *ssl)
+{
+ int ret;
+
+ do {
+ /* We only do unidirectional shutdown */
+ ret = SSL_shutdown(ssl);
+ if (ret < 0) {
+ switch (SSL_get_error(ssl, ret)) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_ASYNC:
+ case SSL_ERROR_WANT_ASYNC_JOB:
+ /* We just do busy waiting. Nothing clever */
+ continue;
+ }
+ ret = 0;
+ }
+ } while (ret < 0);
+}
+
+#endif /* OPENSSL_NO_SOCK */
diff --git a/apps/lib/tlssrp_depr.c b/apps/lib/tlssrp_depr.c
new file mode 100644
index 000000000000..91c19b096e9a
--- /dev/null
+++ b/apps/lib/tlssrp_depr.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This file is to enable backwards compatibility for the SRP features of
+ * s_client, s_server and ciphers. All of those features are deprecated and will
+ * eventually disappear. In the meantime, to continue to support them, we
+ * need to access deprecated SRP APIs.
+ */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include <openssl/bn.h>
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/srp.h>
+#include "apps_ui.h"
+#include "apps.h"
+#include "s_apps.h"
+
+static int srp_Verify_N_and_g(const BIGNUM *N, const BIGNUM *g)
+{
+ BN_CTX *bn_ctx = BN_CTX_new();
+ BIGNUM *p = BN_new();
+ BIGNUM *r = BN_new();
+ int ret =
+ g != NULL && N != NULL && bn_ctx != NULL && BN_is_odd(N) &&
+ BN_check_prime(N, bn_ctx, NULL) == 1 &&
+ p != NULL && BN_rshift1(p, N) &&
+ /* p = (N-1)/2 */
+ BN_check_prime(p, bn_ctx, NULL) == 1 &&
+ r != NULL &&
+ /* verify g^((N-1)/2) == -1 (mod N) */
+ BN_mod_exp(r, g, p, N, bn_ctx) &&
+ BN_add_word(r, 1) && BN_cmp(r, N) == 0;
+
+ BN_free(r);
+ BN_free(p);
+ BN_CTX_free(bn_ctx);
+ return ret;
+}
+
+/*-
+ * This callback is used here for two purposes:
+ * - extended debugging
+ * - making some primality tests for unknown groups
+ * The callback is only called for a non default group.
+ *
+ * An application does not need the call back at all if
+ * only the standard groups are used. In real life situations,
+ * client and server already share well known groups,
+ * thus there is no need to verify them.
+ * Furthermore, in case that a server actually proposes a group that
+ * is not one of those defined in RFC 5054, it is more appropriate
+ * to add the group to a static list and then compare since
+ * primality tests are rather cpu consuming.
+ */
+
+static int ssl_srp_verify_param_cb(SSL *s, void *arg)
+{
+ SRP_ARG *srp_arg = (SRP_ARG *)arg;
+ BIGNUM *N = NULL, *g = NULL;
+
+ if (((N = SSL_get_srp_N(s)) == NULL) || ((g = SSL_get_srp_g(s)) == NULL))
+ return 0;
+ if (srp_arg->debug || srp_arg->msg || srp_arg->amp == 1) {
+ BIO_printf(bio_err, "SRP parameters:\n");
+ BIO_printf(bio_err, "\tN=");
+ BN_print(bio_err, N);
+ BIO_printf(bio_err, "\n\tg=");
+ BN_print(bio_err, g);
+ BIO_printf(bio_err, "\n");
+ }
+
+ if (SRP_check_known_gN_param(g, N))
+ return 1;
+
+ if (srp_arg->amp == 1) {
+ if (srp_arg->debug)
+ BIO_printf(bio_err,
+ "SRP param N and g are not known params, going to check deeper.\n");
+
+ /*
+ * The srp_moregroups is a real debugging feature. Implementors
+ * should rather add the value to the known ones. The minimal size
+ * has already been tested.
+ */
+ if (BN_num_bits(g) <= BN_BITS && srp_Verify_N_and_g(N, g))
+ return 1;
+ }
+ BIO_printf(bio_err, "SRP param N and g rejected.\n");
+ return 0;
+}
+
+#define PWD_STRLEN 1024
+
+static char *ssl_give_srp_client_pwd_cb(SSL *s, void *arg)
+{
+ SRP_ARG *srp_arg = (SRP_ARG *)arg;
+ char *pass = app_malloc(PWD_STRLEN + 1, "SRP password buffer");
+ PW_CB_DATA cb_tmp;
+ int l;
+
+ cb_tmp.password = (char *)srp_arg->srppassin;
+ cb_tmp.prompt_info = "SRP user";
+ if ((l = password_callback(pass, PWD_STRLEN, 0, &cb_tmp)) < 0) {
+ BIO_printf(bio_err, "Can't read Password\n");
+ OPENSSL_free(pass);
+ return NULL;
+ }
+ *(pass + l) = '\0';
+
+ return pass;
+}
+
+int set_up_srp_arg(SSL_CTX *ctx, SRP_ARG *srp_arg, int srp_lateuser, int c_msg,
+ int c_debug)
+{
+ if (!srp_lateuser && !SSL_CTX_set_srp_username(ctx, srp_arg->srplogin)) {
+ BIO_printf(bio_err, "Unable to set SRP username\n");
+ return 0;
+ }
+ srp_arg->msg = c_msg;
+ srp_arg->debug = c_debug;
+ SSL_CTX_set_srp_cb_arg(ctx, &srp_arg);
+ SSL_CTX_set_srp_client_pwd_callback(ctx, ssl_give_srp_client_pwd_cb);
+ SSL_CTX_set_srp_strength(ctx, srp_arg->strength);
+ if (c_msg || c_debug || srp_arg->amp == 0)
+ SSL_CTX_set_srp_verify_param_callback(ctx, ssl_srp_verify_param_cb);
+
+ return 1;
+}
+
+static char *dummy_srp(SSL *ssl, void *arg)
+{
+ return "";
+}
+
+void set_up_dummy_srp(SSL_CTX *ctx)
+{
+ SSL_CTX_set_srp_client_pwd_callback(ctx, dummy_srp);
+}
+
+/*
+ * This callback pretends to require some asynchronous logic in order to
+ * obtain a verifier. When the callback is called for a new connection we
+ * return with a negative value. This will provoke the accept etc to return
+ * with an LOOKUP_X509. The main logic of the reinvokes the suspended call
+ * (which would normally occur after a worker has finished) and we set the
+ * user parameters.
+ */
+static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
+{
+ srpsrvparm *p = (srpsrvparm *) arg;
+ int ret = SSL3_AL_FATAL;
+
+ if (p->login == NULL && p->user == NULL) {
+ p->login = SSL_get_srp_username(s);
+ BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login);
+ return -1;
+ }
+
+ if (p->user == NULL) {
+ BIO_printf(bio_err, "User %s doesn't exist\n", p->login);
+ goto err;
+ }
+
+ if (SSL_set_srp_server_param
+ (s, p->user->N, p->user->g, p->user->s, p->user->v,
+ p->user->info) < 0) {
+ *ad = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+ BIO_printf(bio_err,
+ "SRP parameters set: username = \"%s\" info=\"%s\" \n",
+ p->login, p->user->info);
+ ret = SSL_ERROR_NONE;
+
+ err:
+ SRP_user_pwd_free(p->user);
+ p->user = NULL;
+ p->login = NULL;
+ return ret;
+}
+
+int set_up_srp_verifier_file(SSL_CTX *ctx, srpsrvparm *srp_callback_parm,
+ char *srpuserseed, char *srp_verifier_file)
+{
+ int ret;
+
+ srp_callback_parm->vb = SRP_VBASE_new(srpuserseed);
+ srp_callback_parm->user = NULL;
+ srp_callback_parm->login = NULL;
+
+ if (srp_callback_parm->vb == NULL) {
+ BIO_printf(bio_err, "Failed to initialize SRP verifier file \n");
+ return 0;
+ }
+ if ((ret =
+ SRP_VBASE_init(srp_callback_parm->vb,
+ srp_verifier_file)) != SRP_NO_ERROR) {
+ BIO_printf(bio_err,
+ "Cannot initialize SRP verifier file \"%s\":ret=%d\n",
+ srp_verifier_file, ret);
+ return 0;
+ }
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback);
+ SSL_CTX_set_srp_cb_arg(ctx, &srp_callback_parm);
+ SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb);
+
+ return 1;
+}
+
+void lookup_srp_user(srpsrvparm *srp_callback_parm, BIO *bio_s_out)
+{
+ SRP_user_pwd_free(srp_callback_parm->user);
+ srp_callback_parm->user = SRP_VBASE_get1_by_user(srp_callback_parm->vb,
+ srp_callback_parm->login);
+
+ if (srp_callback_parm->user != NULL)
+ BIO_printf(bio_s_out, "LOOKUP done %s\n",
+ srp_callback_parm->user->info);
+ else
+ BIO_printf(bio_s_out, "LOOKUP not successful\n");
+}
diff --git a/apps/lib/vms_decc_argv.c b/apps/lib/vms_decc_argv.c
new file mode 100644
index 000000000000..031e5afdeca0
--- /dev/null
+++ b/apps/lib/vms_decc_argv.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include <openssl/crypto.h>
+#include "platform.h" /* for copy_argv() */
+
+char **newargv = NULL;
+
+static void cleanup_argv(void)
+{
+ OPENSSL_free(newargv);
+ newargv = NULL;
+}
+
+char **copy_argv(int *argc, char *argv[])
+{
+ /*-
+ * The note below is for historical purpose. On VMS now we always
+ * copy argv "safely."
+ *
+ * 2011-03-22 SMS.
+ * If we have 32-bit pointers everywhere, then we're safe, and
+ * we bypass this mess, as on non-VMS systems.
+ * Problem 1: Compaq/HP C before V7.3 always used 32-bit
+ * pointers for argv[].
+ * Fix 1: For a 32-bit argv[], when we're using 64-bit pointers
+ * everywhere else, we always allocate and use a 64-bit
+ * duplicate of argv[].
+ * Problem 2: Compaq/HP C V7.3 (Alpha, IA64) before ECO1 failed
+ * to NULL-terminate a 64-bit argv[]. (As this was written, the
+ * compiler ECO was available only on IA64.)
+ * Fix 2: Unless advised not to (VMS_TRUST_ARGV), we test a
+ * 64-bit argv[argc] for NULL, and, if necessary, use a
+ * (properly) NULL-terminated (64-bit) duplicate of argv[].
+ * The same code is used in either case to duplicate argv[].
+ * Some of these decisions could be handled in preprocessing,
+ * but the code tends to get even uglier, and the penalty for
+ * deciding at compile- or run-time is tiny.
+ */
+
+ int i, count = *argc;
+ char **p = newargv;
+
+ cleanup_argv();
+
+ /*
+ * We purposefully use OPENSSL_malloc() rather than app_malloc() here,
+ * to avoid symbol name clashes in test programs that would otherwise
+ * get them when linking with all of libapps.a.
+ * See comment in test/build.info.
+ */
+ newargv = OPENSSL_malloc(sizeof(*newargv) * (count + 1));
+ if (newargv == NULL)
+ return NULL;
+
+ /* Register automatic cleanup on first use */
+ if (p == NULL)
+ OPENSSL_atexit(cleanup_argv);
+
+ for (i = 0; i < count; i++)
+ newargv[i] = argv[i];
+ newargv[i] = NULL;
+ *argc = i;
+ return newargv;
+}
diff --git a/apps/lib/vms_term_sock.c b/apps/lib/vms_term_sock.c
new file mode 100644
index 000000000000..97fb3943265c
--- /dev/null
+++ b/apps/lib/vms_term_sock.c
@@ -0,0 +1,591 @@
+/*
+ * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016 VMS Software, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifdef __VMS
+# define OPENSSL_SYS_VMS
+# pragma message disable DOLLARID
+
+
+# include <openssl/opensslconf.h>
+
+# if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
+/*
+ * On VMS, you need to define this to get the declaration of fileno(). The
+ * value 2 is to make sure no function defined in POSIX-2 is left undefined.
+ */
+# define _POSIX_C_SOURCE 2
+# endif
+
+# include <stdio.h>
+
+# undef _POSIX_C_SOURCE
+
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <inet.h>
+# include <unistd.h>
+# include <string.h>
+# include <errno.h>
+# include <starlet.h>
+# include <iodef.h>
+# ifdef __alpha
+# include <iosbdef.h>
+# else
+typedef struct _iosb { /* Copied from IOSBDEF.H for Alpha */
+# pragma __nomember_alignment
+ __union {
+ __struct {
+ unsigned short int iosb$w_status; /* Final I/O status */
+ __union {
+ __struct { /* 16-bit byte count variant */
+ unsigned short int iosb$w_bcnt; /* 16-bit byte count */
+ __union {
+ unsigned int iosb$l_dev_depend; /* 32-bit device dependent info */
+ unsigned int iosb$l_pid; /* 32-bit pid */
+ } iosb$r_l;
+ } iosb$r_bcnt_16;
+ __struct { /* 32-bit byte count variant */
+ unsigned int iosb$l_bcnt; /* 32-bit byte count (unaligned) */
+ unsigned short int iosb$w_dev_depend_high; /* 16-bit device dependent info */
+ } iosb$r_bcnt_32;
+ } iosb$r_devdepend;
+ } iosb$r_io_64;
+ __struct {
+ __union {
+ unsigned int iosb$l_getxxi_status; /* Final GETxxI status */
+ unsigned int iosb$l_reg_status; /* Final $Registry status */
+ } iosb$r_l_status;
+ unsigned int iosb$l_reserved; /* Reserved field */
+ } iosb$r_get_64;
+ } iosb$r_io_get;
+} IOSB;
+
+# if !defined(__VAXC)
+# define iosb$w_status iosb$r_io_get.iosb$r_io_64.iosb$w_status
+# define iosb$w_bcnt iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_16.iosb$w_bcnt
+# define iosb$r_l iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_16.iosb$r_l
+# define iosb$l_dev_depend iosb$r_l.iosb$l_dev_depend
+# define iosb$l_pid iosb$r_l.iosb$l_pid
+# define iosb$l_bcnt iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_32.iosb$l_bcnt
+# define iosb$w_dev_depend_high iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_32.iosb$w_dev_depend_high
+# define iosb$l_getxxi_status iosb$r_io_get.iosb$r_get_64.iosb$r_l_status.iosb$l_getxxi_status
+# define iosb$l_reg_status iosb$r_io_get.iosb$r_get_64.iosb$r_l_status.iosb$l_reg_status
+# endif /* #if !defined(__VAXC) */
+
+# endif /* End of IOSBDEF */
+
+# include <efndef.h>
+# include <stdlib.h>
+# include <ssdef.h>
+# include <time.h>
+# include <stdarg.h>
+# include <descrip.h>
+
+# include "vms_term_sock.h"
+
+# ifdef __alpha
+static struct _iosb TerminalDeviceIosb;
+# else
+IOSB TerminalDeviceIosb;
+# endif
+
+static char TerminalDeviceBuff[255 + 2];
+static int TerminalSocketPair[2] = {0, 0};
+static unsigned short TerminalDeviceChan = 0;
+
+static int CreateSocketPair (int, int, int, int *);
+static void SocketPairTimeoutAst (int);
+static int TerminalDeviceAst (int);
+static void LogMessage (char *, ...);
+
+/*
+** Socket Pair Timeout Value (must be 0-59 seconds)
+*/
+# define SOCKET_PAIR_TIMEOUT_VALUE 20
+
+/*
+** Socket Pair Timeout Block which is passed to timeout AST
+*/
+typedef struct _SocketPairTimeoutBlock {
+ unsigned short SockChan1;
+ unsigned short SockChan2;
+} SPTB;
+
+# ifdef TERM_SOCK_TEST
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*----------------------------------------------------------------------------*/
+int main (int argc, char *argv[], char *envp[])
+{
+ char TermBuff[80];
+ int TermSock,
+ status,
+ len;
+
+ LogMessage ("Enter 'q' or 'Q' to quit ...");
+ while (OPENSSL_strcasecmp (TermBuff, "Q")) {
+ /*
+ ** Create the terminal socket
+ */
+ status = TerminalSocket (TERM_SOCK_CREATE, &TermSock);
+ if (status != TERM_SOCK_SUCCESS)
+ exit (1);
+
+ /*
+ ** Process the terminal input
+ */
+ LogMessage ("Waiting on terminal I/O ...\n");
+ len = recv (TermSock, TermBuff, sizeof(TermBuff), 0) ;
+ TermBuff[len] = '\0';
+ LogMessage ("Received terminal I/O [%s]", TermBuff);
+
+ /*
+ ** Delete the terminal socket
+ */
+ status = TerminalSocket (TERM_SOCK_DELETE, &TermSock);
+ if (status != TERM_SOCK_SUCCESS)
+ exit (1);
+ }
+
+ return 1;
+
+}
+# endif
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*----------------------------------------------------------------------------*/
+int TerminalSocket (int FunctionCode, int *ReturnSocket)
+{
+ int status;
+ $DESCRIPTOR (TerminalDeviceDesc, "SYS$COMMAND");
+
+ /*
+ ** Process the requested function code
+ */
+ switch (FunctionCode) {
+ case TERM_SOCK_CREATE:
+ /*
+ ** Create a socket pair
+ */
+ status = CreateSocketPair (AF_INET, SOCK_STREAM, 0, TerminalSocketPair);
+ if (status == -1) {
+ LogMessage ("TerminalSocket: CreateSocketPair () - %08X", status);
+ if (TerminalSocketPair[0])
+ close (TerminalSocketPair[0]);
+ if (TerminalSocketPair[1])
+ close (TerminalSocketPair[1]);
+ return TERM_SOCK_FAILURE;
+ }
+
+ /*
+ ** Assign a channel to the terminal device
+ */
+ status = sys$assign (&TerminalDeviceDesc,
+ &TerminalDeviceChan,
+ 0, 0, 0);
+ if (! (status & 1)) {
+ LogMessage ("TerminalSocket: SYS$ASSIGN () - %08X", status);
+ close (TerminalSocketPair[0]);
+ close (TerminalSocketPair[1]);
+ return TERM_SOCK_FAILURE;
+ }
+
+ /*
+ ** Queue an async IO to the terminal device
+ */
+ status = sys$qio (EFN$C_ENF,
+ TerminalDeviceChan,
+ IO$_READVBLK,
+ &TerminalDeviceIosb,
+ TerminalDeviceAst,
+ 0,
+ TerminalDeviceBuff,
+ sizeof(TerminalDeviceBuff) - 2,
+ 0, 0, 0, 0);
+ if (! (status & 1)) {
+ LogMessage ("TerminalSocket: SYS$QIO () - %08X", status);
+ close (TerminalSocketPair[0]);
+ close (TerminalSocketPair[1]);
+ return TERM_SOCK_FAILURE;
+ }
+
+ /*
+ ** Return the input side of the socket pair
+ */
+ *ReturnSocket = TerminalSocketPair[1];
+ break;
+
+ case TERM_SOCK_DELETE:
+ /*
+ ** Cancel any pending IO on the terminal channel
+ */
+ status = sys$cancel (TerminalDeviceChan);
+ if (! (status & 1)) {
+ LogMessage ("TerminalSocket: SYS$CANCEL () - %08X", status);
+ close (TerminalSocketPair[0]);
+ close (TerminalSocketPair[1]);
+ return TERM_SOCK_FAILURE;
+ }
+
+ /*
+ ** Deassign the terminal channel
+ */
+ status = sys$dassgn (TerminalDeviceChan);
+ if (! (status & 1)) {
+ LogMessage ("TerminalSocket: SYS$DASSGN () - %08X", status);
+ close (TerminalSocketPair[0]);
+ close (TerminalSocketPair[1]);
+ return TERM_SOCK_FAILURE;
+ }
+
+ /*
+ ** Close the terminal socket pair
+ */
+ close (TerminalSocketPair[0]);
+ close (TerminalSocketPair[1]);
+
+ /*
+ ** Return the initialized socket
+ */
+ *ReturnSocket = 0;
+ break;
+
+ default:
+ /*
+ ** Invalid function code
+ */
+ LogMessage ("TerminalSocket: Invalid Function Code - %d", FunctionCode);
+ return TERM_SOCK_FAILURE;
+ break;
+ }
+
+ /*
+ ** Return success
+ */
+ return TERM_SOCK_SUCCESS;
+
+}
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*----------------------------------------------------------------------------*/
+static int CreateSocketPair (int SocketFamily,
+ int SocketType,
+ int SocketProtocol,
+ int *SocketPair)
+{
+ struct dsc$descriptor AscTimeDesc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
+ static const char* LocalHostAddr = {"127.0.0.1"};
+ unsigned short TcpAcceptChan = 0,
+ TcpDeviceChan = 0;
+ unsigned long BinTimeBuff[2];
+ struct sockaddr_in sin;
+ char AscTimeBuff[32];
+ short LocalHostPort;
+ int status;
+ unsigned int slen;
+
+# ifdef __alpha
+ struct _iosb iosb;
+# else
+ IOSB iosb;
+# endif
+
+ int SockDesc1 = 0,
+ SockDesc2 = 0;
+ SPTB sptb;
+ $DESCRIPTOR (TcpDeviceDesc, "TCPIP$DEVICE");
+
+ /*
+ ** Create a socket
+ */
+ SockDesc1 = socket (SocketFamily, SocketType, 0);
+ if (SockDesc1 < 0) {
+ LogMessage ("CreateSocketPair: socket () - %d", errno);
+ return -1;
+ }
+
+ /*
+ ** Initialize the socket information
+ */
+ slen = sizeof(sin);
+ memset ((char *) &sin, 0, slen);
+ sin.sin_family = SocketFamily;
+ sin.sin_addr.s_addr = inet_addr (LocalHostAddr);
+ sin.sin_port = 0;
+
+ /*
+ ** Bind the socket to the local IP
+ */
+ status = bind (SockDesc1, (struct sockaddr *) &sin, slen);
+ if (status < 0) {
+ LogMessage ("CreateSocketPair: bind () - %d", errno);
+ close (SockDesc1);
+ return -1;
+ }
+
+ /*
+ ** Get the socket name so we can save the port number
+ */
+ status = getsockname (SockDesc1, (struct sockaddr *) &sin, &slen);
+ if (status < 0) {
+ LogMessage ("CreateSocketPair: getsockname () - %d", errno);
+ close (SockDesc1);
+ return -1;
+ } else
+ LocalHostPort = sin.sin_port;
+
+ /*
+ ** Setup a listen for the socket
+ */
+ listen (SockDesc1, 5);
+
+ /*
+ ** Get the binary (64-bit) time of the specified timeout value
+ */
+ sprintf (AscTimeBuff, "0 0:0:%02d.00", SOCKET_PAIR_TIMEOUT_VALUE);
+ AscTimeDesc.dsc$w_length = strlen (AscTimeBuff);
+ AscTimeDesc.dsc$a_pointer = AscTimeBuff;
+ status = sys$bintim (&AscTimeDesc, BinTimeBuff);
+ if (! (status & 1)) {
+ LogMessage ("CreateSocketPair: SYS$BINTIM () - %08X", status);
+ close (SockDesc1);
+ return -1;
+ }
+
+ /*
+ ** Assign another channel to the TCP/IP device for the accept.
+ ** This is the channel that ends up being connected to.
+ */
+ status = sys$assign (&TcpDeviceDesc, &TcpDeviceChan, 0, 0, 0);
+ if (! (status & 1)) {
+ LogMessage ("CreateSocketPair: SYS$ASSIGN () - %08X", status);
+ close (SockDesc1);
+ return -1;
+ }
+
+ /*
+ ** Get the channel of the first socket for the accept
+ */
+ TcpAcceptChan = decc$get_sdc (SockDesc1);
+
+ /*
+ ** Perform the accept using $QIO so we can do this asynchronously
+ */
+ status = sys$qio (EFN$C_ENF,
+ TcpAcceptChan,
+ IO$_ACCESS | IO$M_ACCEPT,
+ &iosb,
+ 0, 0, 0, 0, 0,
+ &TcpDeviceChan,
+ 0, 0);
+ if (! (status & 1)) {
+ LogMessage ("CreateSocketPair: SYS$QIO () - %08X", status);
+ close (SockDesc1);
+ sys$dassgn (TcpDeviceChan);
+ return -1;
+ }
+
+ /*
+ ** Create the second socket to do the connect
+ */
+ SockDesc2 = socket (SocketFamily, SocketType, 0);
+ if (SockDesc2 < 0) {
+ LogMessage ("CreateSocketPair: socket () - %d", errno);
+ sys$cancel (TcpAcceptChan);
+ close (SockDesc1);
+ sys$dassgn (TcpDeviceChan);
+ return (-1) ;
+ }
+
+ /*
+ ** Setup the Socket Pair Timeout Block
+ */
+ sptb.SockChan1 = TcpAcceptChan;
+ sptb.SockChan2 = decc$get_sdc (SockDesc2);
+
+ /*
+ ** Before we block on the connect, set a timer that can cancel I/O on our
+ ** two sockets if it never connects.
+ */
+ status = sys$setimr (EFN$C_ENF,
+ BinTimeBuff,
+ SocketPairTimeoutAst,
+ &sptb,
+ 0);
+ if (! (status & 1)) {
+ LogMessage ("CreateSocketPair: SYS$SETIMR () - %08X", status);
+ sys$cancel (TcpAcceptChan);
+ close (SockDesc1);
+ close (SockDesc2);
+ sys$dassgn (TcpDeviceChan);
+ return -1;
+ }
+
+ /*
+ ** Now issue the connect
+ */
+ memset ((char *) &sin, 0, sizeof(sin)) ;
+ sin.sin_family = SocketFamily;
+ sin.sin_addr.s_addr = inet_addr (LocalHostAddr) ;
+ sin.sin_port = LocalHostPort ;
+
+ status = connect (SockDesc2, (struct sockaddr *) &sin, sizeof(sin));
+ if (status < 0 ) {
+ LogMessage ("CreateSocketPair: connect () - %d", errno);
+ sys$cantim (&sptb, 0);
+ sys$cancel (TcpAcceptChan);
+ close (SockDesc1);
+ close (SockDesc2);
+ sys$dassgn (TcpDeviceChan);
+ return -1;
+ }
+
+ /*
+ ** Wait for the asynch $QIO to finish. Note that if the I/O was aborted
+ ** (SS$_ABORT), then we probably canceled it from the AST routine - so log
+ ** a timeout.
+ */
+ status = sys$synch (EFN$C_ENF, &iosb);
+ if (! (iosb.iosb$w_status & 1)) {
+ if (iosb.iosb$w_status == SS$_ABORT)
+ LogMessage ("CreateSocketPair: SYS$QIO(iosb) timeout");
+ else {
+ LogMessage ("CreateSocketPair: SYS$QIO(iosb) - %d",
+ iosb.iosb$w_status);
+ sys$cantim (&sptb, 0);
+ }
+ close (SockDesc1);
+ close (SockDesc2);
+ sys$dassgn (TcpDeviceChan);
+ return -1;
+ }
+
+ /*
+ ** Here we're successfully connected, so cancel the timer, convert the
+ ** I/O channel to a socket fd, close the listener socket and return the
+ ** connected pair.
+ */
+ sys$cantim (&sptb, 0);
+
+ close (SockDesc1) ;
+ SocketPair[0] = SockDesc2 ;
+ SocketPair[1] = socket_fd (TcpDeviceChan);
+
+ return (0) ;
+
+}
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*----------------------------------------------------------------------------*/
+static void SocketPairTimeoutAst (int astparm)
+{
+ SPTB *sptb = (SPTB *) astparm;
+
+ sys$cancel (sptb->SockChan2); /* Cancel the connect() */
+ sys$cancel (sptb->SockChan1); /* Cancel the accept() */
+
+ return;
+
+}
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*----------------------------------------------------------------------------*/
+static int TerminalDeviceAst (int astparm)
+{
+ int status;
+
+ /*
+ ** Terminate the terminal buffer
+ */
+ TerminalDeviceBuff[TerminalDeviceIosb.iosb$w_bcnt] = '\0';
+ strcat (TerminalDeviceBuff, "\n");
+
+ /*
+ ** Send the data read from the terminal device through the socket pair
+ */
+ send (TerminalSocketPair[0], TerminalDeviceBuff,
+ TerminalDeviceIosb.iosb$w_bcnt + 1, 0);
+
+ /*
+ ** Queue another async IO to the terminal device
+ */
+ status = sys$qio (EFN$C_ENF,
+ TerminalDeviceChan,
+ IO$_READVBLK,
+ &TerminalDeviceIosb,
+ TerminalDeviceAst,
+ 0,
+ TerminalDeviceBuff,
+ sizeof(TerminalDeviceBuff) - 1,
+ 0, 0, 0, 0);
+
+ /*
+ ** Return status
+ */
+ return status;
+
+}
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*----------------------------------------------------------------------------*/
+static void LogMessage (char *msg, ...)
+{
+ char *Month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+ static unsigned int pid = 0;
+ va_list args;
+ time_t CurTime;
+ struct tm *LocTime;
+ char MsgBuff[256];
+
+ /*
+ ** Get the process pid
+ */
+ if (pid == 0)
+ pid = getpid ();
+
+ /*
+ ** Convert the current time into local time
+ */
+ CurTime = time (NULL);
+ LocTime = localtime (&CurTime);
+
+ /*
+ ** Format the message buffer
+ */
+ sprintf (MsgBuff, "%02d-%s-%04d %02d:%02d:%02d [%08X] %s\n",
+ LocTime->tm_mday, Month[LocTime->tm_mon],
+ (LocTime->tm_year + 1900), LocTime->tm_hour, LocTime->tm_min,
+ LocTime->tm_sec, pid, msg);
+
+ /*
+ ** Get any variable arguments and add them to the print of the message
+ ** buffer
+ */
+ va_start (args, msg);
+ vfprintf (stderr, MsgBuff, args);
+ va_end (args);
+
+ /*
+ ** Flush standard error output
+ */
+ fsync (fileno (stderr));
+
+ return;
+
+}
+#endif
diff --git a/apps/lib/win32_init.c b/apps/lib/win32_init.c
new file mode 100644
index 000000000000..6d2be0c62942
--- /dev/null
+++ b/apps/lib/win32_init.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <windows.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+
+#if defined(CP_UTF8)
+
+static UINT saved_cp;
+static int newargc;
+static char **newargv;
+
+static void cleanup(void)
+{
+ int i;
+
+ SetConsoleOutputCP(saved_cp);
+
+ for (i = 0; i < newargc; i++)
+ free(newargv[i]);
+
+ free(newargv);
+}
+
+/*
+ * Incrementally [re]allocate newargv and keep it NULL-terminated.
+ */
+static int validate_argv(int argc)
+{
+ static int size = 0;
+
+ if (argc >= size) {
+ char **ptr;
+
+ while (argc >= size)
+ size += 64;
+
+ ptr = realloc(newargv, size * sizeof(newargv[0]));
+ if (ptr == NULL)
+ return 0;
+
+ (newargv = ptr)[argc] = NULL;
+ } else {
+ newargv[argc] = NULL;
+ }
+
+ return 1;
+}
+
+static int process_glob(WCHAR *wstr, int wlen)
+{
+ int i, slash, udlen;
+ WCHAR saved_char;
+ WIN32_FIND_DATAW data;
+ HANDLE h;
+
+ /*
+ * Note that we support wildcard characters only in filename part
+ * of the path, and not in directories. Windows users are used to
+ * this, that's why recursive glob processing is not implemented.
+ */
+ /*
+ * Start by looking for last slash or backslash, ...
+ */
+ for (slash = 0, i = 0; i < wlen; i++)
+ if (wstr[i] == L'/' || wstr[i] == L'\\')
+ slash = i + 1;
+ /*
+ * ... then look for asterisk or question mark in the file name.
+ */
+ for (i = slash; i < wlen; i++)
+ if (wstr[i] == L'*' || wstr[i] == L'?')
+ break;
+
+ if (i == wlen)
+ return 0; /* definitely not a glob */
+
+ saved_char = wstr[wlen];
+ wstr[wlen] = L'\0';
+ h = FindFirstFileW(wstr, &data);
+ wstr[wlen] = saved_char;
+ if (h == INVALID_HANDLE_VALUE)
+ return 0; /* not a valid glob, just pass... */
+
+ if (slash)
+ udlen = WideCharToMultiByte(CP_UTF8, 0, wstr, slash,
+ NULL, 0, NULL, NULL);
+ else
+ udlen = 0;
+
+ do {
+ int uflen;
+ char *arg;
+
+ /*
+ * skip over . and ..
+ */
+ if (data.cFileName[0] == L'.') {
+ if ((data.cFileName[1] == L'\0') ||
+ (data.cFileName[1] == L'.' && data.cFileName[2] == L'\0'))
+ continue;
+ }
+
+ if (!validate_argv(newargc + 1))
+ break;
+
+ /*
+ * -1 below means "scan for trailing '\0' *and* count it",
+ * so that |uflen| covers even trailing '\0'.
+ */
+ uflen = WideCharToMultiByte(CP_UTF8, 0, data.cFileName, -1,
+ NULL, 0, NULL, NULL);
+
+ arg = malloc(udlen + uflen);
+ if (arg == NULL)
+ break;
+
+ if (udlen)
+ WideCharToMultiByte(CP_UTF8, 0, wstr, slash,
+ arg, udlen, NULL, NULL);
+
+ WideCharToMultiByte(CP_UTF8, 0, data.cFileName, -1,
+ arg + udlen, uflen, NULL, NULL);
+
+ newargv[newargc++] = arg;
+ } while (FindNextFileW(h, &data));
+
+ CloseHandle(h);
+
+ return 1;
+}
+
+void win32_utf8argv(int *argc, char **argv[])
+{
+ const WCHAR *wcmdline;
+ WCHAR *warg, *wend, *p;
+ int wlen, ulen, valid = 1;
+ char *arg;
+
+ if (GetEnvironmentVariableW(L"OPENSSL_WIN32_UTF8", NULL, 0) == 0)
+ return;
+
+ newargc = 0;
+ newargv = NULL;
+ if (!validate_argv(newargc))
+ return;
+
+ wcmdline = GetCommandLineW();
+ if (wcmdline == NULL) return;
+
+ /*
+ * make a copy of the command line, since we might have to modify it...
+ */
+ wlen = wcslen(wcmdline);
+ p = _alloca((wlen + 1) * sizeof(WCHAR));
+ wcscpy(p, wcmdline);
+
+ while (*p != L'\0') {
+ int in_quote = 0;
+
+ if (*p == L' ' || *p == L'\t') {
+ p++; /* skip over whitespace */
+ continue;
+ }
+
+ /*
+ * Note: because we may need to fiddle with the number of backslashes,
+ * the argument string is copied into itself. This is safe because
+ * the number of characters will never expand.
+ */
+ warg = wend = p;
+ while (*p != L'\0'
+ && (in_quote || (*p != L' ' && *p != L'\t'))) {
+ switch (*p) {
+ case L'\\':
+ /*
+ * Microsoft documentation on how backslashes are treated
+ * is:
+ *
+ * + Backslashes are interpreted literally, unless they
+ * immediately precede a double quotation mark.
+ * + If an even number of backslashes is followed by a double
+ * quotation mark, one backslash is placed in the argv array
+ * for every pair of backslashes, and the double quotation
+ * mark is interpreted as a string delimiter.
+ * + If an odd number of backslashes is followed by a double
+ * quotation mark, one backslash is placed in the argv array
+ * for every pair of backslashes, and the double quotation
+ * mark is "escaped" by the remaining backslash, causing a
+ * literal double quotation mark (") to be placed in argv.
+ *
+ * Ref: https://msdn.microsoft.com/en-us/library/17w5ykft.aspx
+ *
+ * Though referred page doesn't mention it, multiple qouble
+ * quotes are also special. Pair of double quotes in quoted
+ * string is counted as single double quote.
+ */
+ {
+ const WCHAR *q = p;
+ int i;
+
+ while (*p == L'\\')
+ p++;
+
+ if (*p == L'"') {
+ int i;
+
+ for (i = (p - q) / 2; i > 0; i--)
+ *wend++ = L'\\';
+
+ /*
+ * if odd amount of backslashes before the quote,
+ * said quote is part of the argument, not a delimiter
+ */
+ if ((p - q) % 2 == 1)
+ *wend++ = *p++;
+ } else {
+ for (i = p - q; i > 0; i--)
+ *wend++ = L'\\';
+ }
+ }
+ break;
+ case L'"':
+ /*
+ * Without the preceding backslash (or when preceded with an
+ * even number of backslashes), the double quote is a simple
+ * string delimiter and just slightly change the parsing state
+ */
+ if (in_quote && p[1] == L'"')
+ *wend++ = *p++;
+ else
+ in_quote = !in_quote;
+ p++;
+ break;
+ default:
+ /*
+ * Any other non-delimiter character is just taken verbatim
+ */
+ *wend++ = *p++;
+ }
+ }
+
+ wlen = wend - warg;
+
+ if (wlen == 0 || !process_glob(warg, wlen)) {
+ if (!validate_argv(newargc + 1)) {
+ valid = 0;
+ break;
+ }
+
+ ulen = 0;
+ if (wlen > 0) {
+ ulen = WideCharToMultiByte(CP_UTF8, 0, warg, wlen,
+ NULL, 0, NULL, NULL);
+ if (ulen <= 0)
+ continue;
+ }
+
+ arg = malloc(ulen + 1);
+ if (arg == NULL) {
+ valid = 0;
+ break;
+ }
+
+ if (wlen > 0)
+ WideCharToMultiByte(CP_UTF8, 0, warg, wlen,
+ arg, ulen, NULL, NULL);
+ arg[ulen] = '\0';
+
+ newargv[newargc++] = arg;
+ }
+ }
+
+ if (valid) {
+ saved_cp = GetConsoleOutputCP();
+ SetConsoleOutputCP(CP_UTF8);
+
+ *argc = newargc;
+ *argv = newargv;
+
+ atexit(cleanup);
+ } else if (newargv != NULL) {
+ int i;
+
+ for (i = 0; i < newargc; i++)
+ free(newargv[i]);
+
+ free(newargv);
+
+ newargc = 0;
+ newargv = NULL;
+ }
+
+ return;
+}
+#else
+void win32_utf8argv(int *argc, char **argv[])
+{ return; }
+#endif
diff --git a/apps/list.c b/apps/list.c
new file mode 100644
index 000000000000..514abacfc835
--- /dev/null
+++ b/apps/list.c
@@ -0,0 +1,1706 @@
+/*
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* We need to use some deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/provider.h>
+#include <openssl/safestack.h>
+#include <openssl/kdf.h>
+#include <openssl/encoder.h>
+#include <openssl/decoder.h>
+#include <openssl/store.h>
+#include <openssl/core_names.h>
+#include <openssl/rand.h>
+#include "apps.h"
+#include "app_params.h"
+#include "progs.h"
+#include "opt.h"
+#include "names.h"
+
+static int verbose = 0;
+static const char *select_name = NULL;
+
+/* Checks to see if algorithms are fetchable */
+#define IS_FETCHABLE(type, TYPE) \
+ static int is_ ## type ## _fetchable(const TYPE *alg) \
+ { \
+ TYPE *impl; \
+ const char *propq = app_get0_propq(); \
+ OSSL_LIB_CTX *libctx = app_get0_libctx(); \
+ const char *name = TYPE ## _get0_name(alg); \
+ \
+ ERR_set_mark(); \
+ impl = TYPE ## _fetch(libctx, name, propq); \
+ ERR_pop_to_mark(); \
+ if (impl == NULL) \
+ return 0; \
+ TYPE ## _free(impl); \
+ return 1; \
+ }
+IS_FETCHABLE(cipher, EVP_CIPHER)
+IS_FETCHABLE(digest, EVP_MD)
+IS_FETCHABLE(mac, EVP_MAC)
+IS_FETCHABLE(kdf, EVP_KDF)
+IS_FETCHABLE(rand, EVP_RAND)
+IS_FETCHABLE(keymgmt, EVP_KEYMGMT)
+IS_FETCHABLE(signature, EVP_SIGNATURE)
+IS_FETCHABLE(kem, EVP_KEM)
+IS_FETCHABLE(asym_cipher, EVP_ASYM_CIPHER)
+IS_FETCHABLE(keyexch, EVP_KEYEXCH)
+IS_FETCHABLE(decoder, OSSL_DECODER)
+IS_FETCHABLE(encoder, OSSL_ENCODER)
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+static int include_legacy(void)
+{
+ return app_get0_propq() == NULL;
+}
+
+static void legacy_cipher_fn(const EVP_CIPHER *c,
+ const char *from, const char *to, void *arg)
+{
+ if (select_name != NULL
+ && (c == NULL
+ || OPENSSL_strcasecmp(select_name, EVP_CIPHER_get0_name(c)) != 0))
+ return;
+ if (c != NULL) {
+ BIO_printf(arg, " %s\n", EVP_CIPHER_get0_name(c));
+ } else {
+ if (from == NULL)
+ from = "<undefined>";
+ if (to == NULL)
+ to = "<undefined>";
+ BIO_printf(arg, " %s => %s\n", from, to);
+ }
+}
+#endif
+
+DEFINE_STACK_OF(EVP_CIPHER)
+static int cipher_cmp(const EVP_CIPHER * const *a,
+ const EVP_CIPHER * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_CIPHER_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_CIPHER_get0_provider(*b)));
+}
+
+static void collect_ciphers(EVP_CIPHER *cipher, void *stack)
+{
+ STACK_OF(EVP_CIPHER) *cipher_stack = stack;
+
+ if (is_cipher_fetchable(cipher)
+ && sk_EVP_CIPHER_push(cipher_stack, cipher) > 0)
+ EVP_CIPHER_up_ref(cipher);
+}
+
+static void list_ciphers(void)
+{
+ STACK_OF(EVP_CIPHER) *ciphers = sk_EVP_CIPHER_new(cipher_cmp);
+ int i;
+
+ if (ciphers == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (include_legacy()) {
+ BIO_printf(bio_out, "Legacy:\n");
+ EVP_CIPHER_do_all_sorted(legacy_cipher_fn, bio_out);
+ }
+#endif
+
+ BIO_printf(bio_out, "Provided:\n");
+ EVP_CIPHER_do_all_provided(app_get0_libctx(), collect_ciphers, ciphers);
+ sk_EVP_CIPHER_sort(ciphers);
+ for (i = 0; i < sk_EVP_CIPHER_num(ciphers); i++) {
+ const EVP_CIPHER *c = sk_EVP_CIPHER_value(ciphers, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_CIPHER_is_a(c, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_CIPHER_names_do_all(c, collect_names, names)) {
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_CIPHER_get0_provider(c)));
+
+ if (verbose) {
+ const char *desc = EVP_CIPHER_get0_description(c);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("retrievable algorithm parameters",
+ EVP_CIPHER_gettable_params(c), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_CIPHER_gettable_ctx_params(c), 4);
+ print_param_types("settable operation parameters",
+ EVP_CIPHER_settable_ctx_params(c), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_CIPHER_pop_free(ciphers, EVP_CIPHER_free);
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+static void legacy_md_fn(const EVP_MD *m,
+ const char *from, const char *to, void *arg)
+{
+ if (m != NULL) {
+ BIO_printf(arg, " %s\n", EVP_MD_get0_name(m));
+ } else {
+ if (from == NULL)
+ from = "<undefined>";
+ if (to == NULL)
+ to = "<undefined>";
+ BIO_printf((BIO *)arg, " %s => %s\n", from, to);
+ }
+}
+#endif
+
+DEFINE_STACK_OF(EVP_MD)
+static int md_cmp(const EVP_MD * const *a, const EVP_MD * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_MD_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_MD_get0_provider(*b)));
+}
+
+static void collect_digests(EVP_MD *digest, void *stack)
+{
+ STACK_OF(EVP_MD) *digest_stack = stack;
+
+ if (is_digest_fetchable(digest)
+ && sk_EVP_MD_push(digest_stack, digest) > 0)
+ EVP_MD_up_ref(digest);
+}
+
+static void list_digests(void)
+{
+ STACK_OF(EVP_MD) *digests = sk_EVP_MD_new(md_cmp);
+ int i;
+
+ if (digests == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (include_legacy()) {
+ BIO_printf(bio_out, "Legacy:\n");
+ EVP_MD_do_all_sorted(legacy_md_fn, bio_out);
+ }
+#endif
+
+ BIO_printf(bio_out, "Provided:\n");
+ EVP_MD_do_all_provided(app_get0_libctx(), collect_digests, digests);
+ sk_EVP_MD_sort(digests);
+ for (i = 0; i < sk_EVP_MD_num(digests); i++) {
+ const EVP_MD *m = sk_EVP_MD_value(digests, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_MD_is_a(m, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_MD_names_do_all(m, collect_names, names)) {
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_MD_get0_provider(m)));
+
+ if (verbose) {
+ const char *desc = EVP_MD_get0_description(m);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("retrievable algorithm parameters",
+ EVP_MD_gettable_params(m), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_MD_gettable_ctx_params(m), 4);
+ print_param_types("settable operation parameters",
+ EVP_MD_settable_ctx_params(m), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_MD_pop_free(digests, EVP_MD_free);
+}
+
+DEFINE_STACK_OF(EVP_MAC)
+static int mac_cmp(const EVP_MAC * const *a, const EVP_MAC * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_MAC_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_MAC_get0_provider(*b)));
+}
+
+static void collect_macs(EVP_MAC *mac, void *stack)
+{
+ STACK_OF(EVP_MAC) *mac_stack = stack;
+
+ if (is_mac_fetchable(mac)
+ && sk_EVP_MAC_push(mac_stack, mac) > 0)
+ EVP_MAC_up_ref(mac);
+}
+
+static void list_macs(void)
+{
+ STACK_OF(EVP_MAC) *macs = sk_EVP_MAC_new(mac_cmp);
+ int i;
+
+ if (macs == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+ BIO_printf(bio_out, "Provided MACs:\n");
+ EVP_MAC_do_all_provided(app_get0_libctx(), collect_macs, macs);
+ sk_EVP_MAC_sort(macs);
+ for (i = 0; i < sk_EVP_MAC_num(macs); i++) {
+ const EVP_MAC *m = sk_EVP_MAC_value(macs, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_MAC_is_a(m, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_MAC_names_do_all(m, collect_names, names)) {
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_MAC_get0_provider(m)));
+
+ if (verbose) {
+ const char *desc = EVP_MAC_get0_description(m);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("retrievable algorithm parameters",
+ EVP_MAC_gettable_params(m), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_MAC_gettable_ctx_params(m), 4);
+ print_param_types("settable operation parameters",
+ EVP_MAC_settable_ctx_params(m), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_MAC_pop_free(macs, EVP_MAC_free);
+}
+
+/*
+ * KDFs and PRFs
+ */
+DEFINE_STACK_OF(EVP_KDF)
+static int kdf_cmp(const EVP_KDF * const *a, const EVP_KDF * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_KDF_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_KDF_get0_provider(*b)));
+}
+
+static void collect_kdfs(EVP_KDF *kdf, void *stack)
+{
+ STACK_OF(EVP_KDF) *kdf_stack = stack;
+
+ if (is_kdf_fetchable(kdf)
+ && sk_EVP_KDF_push(kdf_stack, kdf) > 0)
+ EVP_KDF_up_ref(kdf);
+}
+
+static void list_kdfs(void)
+{
+ STACK_OF(EVP_KDF) *kdfs = sk_EVP_KDF_new(kdf_cmp);
+ int i;
+
+ if (kdfs == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+ BIO_printf(bio_out, "Provided KDFs and PDFs:\n");
+ EVP_KDF_do_all_provided(app_get0_libctx(), collect_kdfs, kdfs);
+ sk_EVP_KDF_sort(kdfs);
+ for (i = 0; i < sk_EVP_KDF_num(kdfs); i++) {
+ const EVP_KDF *k = sk_EVP_KDF_value(kdfs, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_KDF_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_KDF_names_do_all(k, collect_names, names)) {
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_KDF_get0_provider(k)));
+
+ if (verbose) {
+ const char *desc = EVP_KDF_get0_description(k);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("retrievable algorithm parameters",
+ EVP_KDF_gettable_params(k), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_KDF_gettable_ctx_params(k), 4);
+ print_param_types("settable operation parameters",
+ EVP_KDF_settable_ctx_params(k), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_KDF_pop_free(kdfs, EVP_KDF_free);
+}
+
+/*
+ * RANDs
+ */
+DEFINE_STACK_OF(EVP_RAND)
+
+static int rand_cmp(const EVP_RAND * const *a, const EVP_RAND * const *b)
+{
+ int ret = OPENSSL_strcasecmp(EVP_RAND_get0_name(*a), EVP_RAND_get0_name(*b));
+
+ if (ret == 0)
+ ret = strcmp(OSSL_PROVIDER_get0_name(EVP_RAND_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_RAND_get0_provider(*b)));
+
+ return ret;
+}
+
+static void collect_rands(EVP_RAND *rand, void *stack)
+{
+ STACK_OF(EVP_RAND) *rand_stack = stack;
+
+ if (is_rand_fetchable(rand)
+ && sk_EVP_RAND_push(rand_stack, rand) > 0)
+ EVP_RAND_up_ref(rand);
+}
+
+static void list_random_generators(void)
+{
+ STACK_OF(EVP_RAND) *rands = sk_EVP_RAND_new(rand_cmp);
+ int i;
+
+ if (rands == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+ BIO_printf(bio_out, "Provided RNGs and seed sources:\n");
+ EVP_RAND_do_all_provided(app_get0_libctx(), collect_rands, rands);
+ sk_EVP_RAND_sort(rands);
+ for (i = 0; i < sk_EVP_RAND_num(rands); i++) {
+ const EVP_RAND *m = sk_EVP_RAND_value(rands, i);
+
+ if (select_name != NULL
+ && OPENSSL_strcasecmp(EVP_RAND_get0_name(m), select_name) != 0)
+ continue;
+ BIO_printf(bio_out, " %s", EVP_RAND_get0_name(m));
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_RAND_get0_provider(m)));
+
+ if (verbose) {
+ const char *desc = EVP_RAND_get0_description(m);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("retrievable algorithm parameters",
+ EVP_RAND_gettable_params(m), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_RAND_gettable_ctx_params(m), 4);
+ print_param_types("settable operation parameters",
+ EVP_RAND_settable_ctx_params(m), 4);
+ }
+ }
+ sk_EVP_RAND_pop_free(rands, EVP_RAND_free);
+}
+
+static void display_random(const char *name, EVP_RAND_CTX *drbg)
+{
+ EVP_RAND *rand;
+ uint64_t u;
+ const char *p;
+ const OSSL_PARAM *gettables;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ unsigned char buf[1000];
+
+ BIO_printf(bio_out, "%s:\n", name);
+ if (drbg != NULL) {
+ rand = EVP_RAND_CTX_get0_rand(drbg);
+
+ BIO_printf(bio_out, " %s", EVP_RAND_get0_name(rand));
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_RAND_get0_provider(rand)));
+
+ switch (EVP_RAND_get_state(drbg)) {
+ case EVP_RAND_STATE_UNINITIALISED:
+ p = "uninitialised";
+ break;
+ case EVP_RAND_STATE_READY:
+ p = "ready";
+ break;
+ case EVP_RAND_STATE_ERROR:
+ p = "error";
+ break;
+ default:
+ p = "unknown";
+ break;
+ }
+ BIO_printf(bio_out, " state = %s\n", p);
+
+ gettables = EVP_RAND_gettable_ctx_params(rand);
+ if (gettables != NULL)
+ for (; gettables->key != NULL; gettables++) {
+ /* State has been dealt with already, so ignore */
+ if (OPENSSL_strcasecmp(gettables->key, OSSL_RAND_PARAM_STATE) == 0)
+ continue;
+ /* Outside of verbose mode, we skip non-string values */
+ if (gettables->data_type != OSSL_PARAM_UTF8_STRING
+ && gettables->data_type != OSSL_PARAM_UTF8_PTR
+ && !verbose)
+ continue;
+ params->key = gettables->key;
+ params->data_type = gettables->data_type;
+ if (gettables->data_type == OSSL_PARAM_UNSIGNED_INTEGER
+ || gettables->data_type == OSSL_PARAM_INTEGER) {
+ params->data = &u;
+ params->data_size = sizeof(u);
+ } else {
+ params->data = buf;
+ params->data_size = sizeof(buf);
+ }
+ params->return_size = 0;
+ if (EVP_RAND_CTX_get_params(drbg, params))
+ print_param_value(params, 2);
+ }
+ }
+}
+
+static void list_random_instances(void)
+{
+ display_random("primary", RAND_get0_primary(NULL));
+ display_random("public", RAND_get0_public(NULL));
+ display_random("private", RAND_get0_private(NULL));
+}
+
+/*
+ * Encoders
+ */
+DEFINE_STACK_OF(OSSL_ENCODER)
+static int encoder_cmp(const OSSL_ENCODER * const *a,
+ const OSSL_ENCODER * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(OSSL_ENCODER_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(OSSL_ENCODER_get0_provider(*b)));
+}
+
+static void collect_encoders(OSSL_ENCODER *encoder, void *stack)
+{
+ STACK_OF(OSSL_ENCODER) *encoder_stack = stack;
+
+ if (is_encoder_fetchable(encoder)
+ && sk_OSSL_ENCODER_push(encoder_stack, encoder) > 0)
+ OSSL_ENCODER_up_ref(encoder);
+}
+
+static void list_encoders(void)
+{
+ STACK_OF(OSSL_ENCODER) *encoders;
+ int i;
+
+ encoders = sk_OSSL_ENCODER_new(encoder_cmp);
+ if (encoders == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+ BIO_printf(bio_out, "Provided ENCODERs:\n");
+ OSSL_ENCODER_do_all_provided(app_get0_libctx(), collect_encoders,
+ encoders);
+ sk_OSSL_ENCODER_sort(encoders);
+
+ for (i = 0; i < sk_OSSL_ENCODER_num(encoders); i++) {
+ OSSL_ENCODER *k = sk_OSSL_ENCODER_value(encoders, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !OSSL_ENCODER_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && OSSL_ENCODER_names_do_all(k, collect_names, names)) {
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s (%s)\n",
+ OSSL_PROVIDER_get0_name(OSSL_ENCODER_get0_provider(k)),
+ OSSL_ENCODER_get0_properties(k));
+
+ if (verbose) {
+ const char *desc = OSSL_ENCODER_get0_description(k);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("settable operation parameters",
+ OSSL_ENCODER_settable_ctx_params(k), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_OSSL_ENCODER_pop_free(encoders, OSSL_ENCODER_free);
+}
+
+/*
+ * Decoders
+ */
+DEFINE_STACK_OF(OSSL_DECODER)
+static int decoder_cmp(const OSSL_DECODER * const *a,
+ const OSSL_DECODER * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(OSSL_DECODER_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(OSSL_DECODER_get0_provider(*b)));
+}
+
+static void collect_decoders(OSSL_DECODER *decoder, void *stack)
+{
+ STACK_OF(OSSL_DECODER) *decoder_stack = stack;
+
+ if (is_decoder_fetchable(decoder)
+ && sk_OSSL_DECODER_push(decoder_stack, decoder) > 0)
+ OSSL_DECODER_up_ref(decoder);
+}
+
+static void list_decoders(void)
+{
+ STACK_OF(OSSL_DECODER) *decoders;
+ int i;
+
+ decoders = sk_OSSL_DECODER_new(decoder_cmp);
+ if (decoders == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+ BIO_printf(bio_out, "Provided DECODERs:\n");
+ OSSL_DECODER_do_all_provided(app_get0_libctx(), collect_decoders,
+ decoders);
+ sk_OSSL_DECODER_sort(decoders);
+
+ for (i = 0; i < sk_OSSL_DECODER_num(decoders); i++) {
+ OSSL_DECODER *k = sk_OSSL_DECODER_value(decoders, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !OSSL_DECODER_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && OSSL_DECODER_names_do_all(k, collect_names, names)) {
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s (%s)\n",
+ OSSL_PROVIDER_get0_name(OSSL_DECODER_get0_provider(k)),
+ OSSL_DECODER_get0_properties(k));
+
+ if (verbose) {
+ const char *desc = OSSL_DECODER_get0_description(k);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("settable operation parameters",
+ OSSL_DECODER_settable_ctx_params(k), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_OSSL_DECODER_pop_free(decoders, OSSL_DECODER_free);
+}
+
+DEFINE_STACK_OF(EVP_KEYMGMT)
+static int keymanager_cmp(const EVP_KEYMGMT * const *a,
+ const EVP_KEYMGMT * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_KEYMGMT_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_KEYMGMT_get0_provider(*b)));
+}
+
+static void collect_keymanagers(EVP_KEYMGMT *km, void *stack)
+{
+ STACK_OF(EVP_KEYMGMT) *km_stack = stack;
+
+ if (is_keymgmt_fetchable(km)
+ && sk_EVP_KEYMGMT_push(km_stack, km) > 0)
+ EVP_KEYMGMT_up_ref(km);
+}
+
+static void list_keymanagers(void)
+{
+ int i;
+ STACK_OF(EVP_KEYMGMT) *km_stack = sk_EVP_KEYMGMT_new(keymanager_cmp);
+
+ EVP_KEYMGMT_do_all_provided(app_get0_libctx(), collect_keymanagers,
+ km_stack);
+ sk_EVP_KEYMGMT_sort(km_stack);
+
+ for (i = 0; i < sk_EVP_KEYMGMT_num(km_stack); i++) {
+ EVP_KEYMGMT *k = sk_EVP_KEYMGMT_value(km_stack, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_KEYMGMT_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_KEYMGMT_names_do_all(k, collect_names, names)) {
+ const char *desc = EVP_KEYMGMT_get0_description(k);
+
+ BIO_printf(bio_out, " Name: ");
+ if (desc != NULL)
+ BIO_printf(bio_out, "%s", desc);
+ else
+ BIO_printf(bio_out, "%s", sk_OPENSSL_CSTRING_value(names, 0));
+ BIO_printf(bio_out, "\n");
+ BIO_printf(bio_out, " Type: Provider Algorithm\n");
+ BIO_printf(bio_out, " IDs: ");
+ print_names(bio_out, names);
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_KEYMGMT_get0_provider(k)));
+
+ if (verbose) {
+ print_param_types("settable key generation parameters",
+ EVP_KEYMGMT_gen_settable_params(k), 4);
+ print_param_types("settable operation parameters",
+ EVP_KEYMGMT_settable_params(k), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_KEYMGMT_gettable_params(k), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_KEYMGMT_pop_free(km_stack, EVP_KEYMGMT_free);
+}
+
+DEFINE_STACK_OF(EVP_SIGNATURE)
+static int signature_cmp(const EVP_SIGNATURE * const *a,
+ const EVP_SIGNATURE * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_SIGNATURE_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_SIGNATURE_get0_provider(*b)));
+}
+
+static void collect_signatures(EVP_SIGNATURE *sig, void *stack)
+{
+ STACK_OF(EVP_SIGNATURE) *sig_stack = stack;
+
+ if (is_signature_fetchable(sig)
+ && sk_EVP_SIGNATURE_push(sig_stack, sig) > 0)
+ EVP_SIGNATURE_up_ref(sig);
+}
+
+static void list_signatures(void)
+{
+ int i, count = 0;
+ STACK_OF(EVP_SIGNATURE) *sig_stack = sk_EVP_SIGNATURE_new(signature_cmp);
+
+ EVP_SIGNATURE_do_all_provided(app_get0_libctx(), collect_signatures,
+ sig_stack);
+ sk_EVP_SIGNATURE_sort(sig_stack);
+
+ for (i = 0; i < sk_EVP_SIGNATURE_num(sig_stack); i++) {
+ EVP_SIGNATURE *k = sk_EVP_SIGNATURE_value(sig_stack, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_SIGNATURE_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_SIGNATURE_names_do_all(k, collect_names, names)) {
+ count++;
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_SIGNATURE_get0_provider(k)));
+
+ if (verbose) {
+ const char *desc = EVP_SIGNATURE_get0_description(k);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("settable operation parameters",
+ EVP_SIGNATURE_settable_ctx_params(k), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_SIGNATURE_gettable_ctx_params(k), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_SIGNATURE_pop_free(sig_stack, EVP_SIGNATURE_free);
+ if (count == 0)
+ BIO_printf(bio_out, " -\n");
+}
+
+DEFINE_STACK_OF(EVP_KEM)
+static int kem_cmp(const EVP_KEM * const *a,
+ const EVP_KEM * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_KEM_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_KEM_get0_provider(*b)));
+}
+
+static void collect_kem(EVP_KEM *kem, void *stack)
+{
+ STACK_OF(EVP_KEM) *kem_stack = stack;
+
+ if (is_kem_fetchable(kem)
+ && sk_EVP_KEM_push(kem_stack, kem) > 0)
+ EVP_KEM_up_ref(kem);
+}
+
+static void list_kems(void)
+{
+ int i, count = 0;
+ STACK_OF(EVP_KEM) *kem_stack = sk_EVP_KEM_new(kem_cmp);
+
+ EVP_KEM_do_all_provided(app_get0_libctx(), collect_kem, kem_stack);
+ sk_EVP_KEM_sort(kem_stack);
+
+ for (i = 0; i < sk_EVP_KEM_num(kem_stack); i++) {
+ EVP_KEM *k = sk_EVP_KEM_value(kem_stack, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_KEM_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_KEM_names_do_all(k, collect_names, names)) {
+ count++;
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_KEM_get0_provider(k)));
+
+ if (verbose) {
+ const char *desc = EVP_KEM_get0_description(k);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("settable operation parameters",
+ EVP_KEM_settable_ctx_params(k), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_KEM_gettable_ctx_params(k), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_KEM_pop_free(kem_stack, EVP_KEM_free);
+ if (count == 0)
+ BIO_printf(bio_out, " -\n");
+}
+
+DEFINE_STACK_OF(EVP_ASYM_CIPHER)
+static int asymcipher_cmp(const EVP_ASYM_CIPHER * const *a,
+ const EVP_ASYM_CIPHER * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_ASYM_CIPHER_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_ASYM_CIPHER_get0_provider(*b)));
+}
+
+static void collect_asymciph(EVP_ASYM_CIPHER *asym_cipher, void *stack)
+{
+ STACK_OF(EVP_ASYM_CIPHER) *asym_cipher_stack = stack;
+
+ if (is_asym_cipher_fetchable(asym_cipher)
+ && sk_EVP_ASYM_CIPHER_push(asym_cipher_stack, asym_cipher) > 0)
+ EVP_ASYM_CIPHER_up_ref(asym_cipher);
+}
+
+static void list_asymciphers(void)
+{
+ int i, count = 0;
+ STACK_OF(EVP_ASYM_CIPHER) *asymciph_stack =
+ sk_EVP_ASYM_CIPHER_new(asymcipher_cmp);
+
+ EVP_ASYM_CIPHER_do_all_provided(app_get0_libctx(), collect_asymciph,
+ asymciph_stack);
+ sk_EVP_ASYM_CIPHER_sort(asymciph_stack);
+
+ for (i = 0; i < sk_EVP_ASYM_CIPHER_num(asymciph_stack); i++) {
+ EVP_ASYM_CIPHER *k = sk_EVP_ASYM_CIPHER_value(asymciph_stack, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_ASYM_CIPHER_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL
+ && EVP_ASYM_CIPHER_names_do_all(k, collect_names, names)) {
+ count++;
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_ASYM_CIPHER_get0_provider(k)));
+
+ if (verbose) {
+ const char *desc = EVP_ASYM_CIPHER_get0_description(k);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("settable operation parameters",
+ EVP_ASYM_CIPHER_settable_ctx_params(k), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_ASYM_CIPHER_gettable_ctx_params(k), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_ASYM_CIPHER_pop_free(asymciph_stack, EVP_ASYM_CIPHER_free);
+ if (count == 0)
+ BIO_printf(bio_out, " -\n");
+}
+
+DEFINE_STACK_OF(EVP_KEYEXCH)
+static int kex_cmp(const EVP_KEYEXCH * const *a,
+ const EVP_KEYEXCH * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_KEYEXCH_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_KEYEXCH_get0_provider(*b)));
+}
+
+static void collect_kex(EVP_KEYEXCH *kex, void *stack)
+{
+ STACK_OF(EVP_KEYEXCH) *kex_stack = stack;
+
+ if (is_keyexch_fetchable(kex)
+ && sk_EVP_KEYEXCH_push(kex_stack, kex) > 0)
+ EVP_KEYEXCH_up_ref(kex);
+}
+
+static void list_keyexchanges(void)
+{
+ int i, count = 0;
+ STACK_OF(EVP_KEYEXCH) *kex_stack = sk_EVP_KEYEXCH_new(kex_cmp);
+
+ EVP_KEYEXCH_do_all_provided(app_get0_libctx(), collect_kex, kex_stack);
+ sk_EVP_KEYEXCH_sort(kex_stack);
+
+ for (i = 0; i < sk_EVP_KEYEXCH_num(kex_stack); i++) {
+ EVP_KEYEXCH *k = sk_EVP_KEYEXCH_value(kex_stack, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_KEYEXCH_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_KEYEXCH_names_do_all(k, collect_names, names)) {
+ count++;
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_KEYEXCH_get0_provider(k)));
+
+ if (verbose) {
+ const char *desc = EVP_KEYEXCH_get0_description(k);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("settable operation parameters",
+ EVP_KEYEXCH_settable_ctx_params(k), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_KEYEXCH_gettable_ctx_params(k), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_KEYEXCH_pop_free(kex_stack, EVP_KEYEXCH_free);
+ if (count == 0)
+ BIO_printf(bio_out, " -\n");
+}
+
+static void list_objects(void)
+{
+ int max_nid = OBJ_new_nid(0);
+ int i;
+ char *oid_buf = NULL;
+ int oid_size = 0;
+
+ /* Skip 0, since that's NID_undef */
+ for (i = 1; i < max_nid; i++) {
+ const ASN1_OBJECT *obj = OBJ_nid2obj(i);
+ const char *sn = OBJ_nid2sn(i);
+ const char *ln = OBJ_nid2ln(i);
+ int n = 0;
+
+ /*
+ * If one of the retrieved objects somehow generated an error,
+ * we ignore it. The check for NID_undef below will detect the
+ * error and simply skip to the next NID.
+ */
+ ERR_clear_error();
+
+ if (OBJ_obj2nid(obj) == NID_undef)
+ continue;
+
+ if ((n = OBJ_obj2txt(NULL, 0, obj, 1)) == 0) {
+ BIO_printf(bio_out, "# None-OID object: %s, %s\n", sn, ln);
+ continue;
+ }
+ if (n < 0)
+ break; /* Error */
+
+ if (n > oid_size) {
+ oid_buf = OPENSSL_realloc(oid_buf, n + 1);
+ if (oid_buf == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ break; /* Error */
+ }
+ oid_size = n + 1;
+ }
+ if (OBJ_obj2txt(oid_buf, oid_size, obj, 1) < 0)
+ break; /* Error */
+ if (ln == NULL || strcmp(sn, ln) == 0)
+ BIO_printf(bio_out, "%s = %s\n", sn, oid_buf);
+ else
+ BIO_printf(bio_out, "%s = %s, %s\n", sn, ln, oid_buf);
+ }
+
+ OPENSSL_free(oid_buf);
+}
+
+static void list_options_for_command(const char *command)
+{
+ const FUNCTION *fp;
+ const OPTIONS *o;
+
+ for (fp = functions; fp->name != NULL; fp++)
+ if (strcmp(fp->name, command) == 0)
+ break;
+ if (fp->name == NULL) {
+ BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n",
+ command);
+ return;
+ }
+
+ if ((o = fp->help) == NULL)
+ return;
+
+ for ( ; o->name != NULL; o++) {
+ char c = o->valtype;
+
+ if (o->name == OPT_PARAM_STR)
+ break;
+
+ if (o->name == OPT_HELP_STR
+ || o->name == OPT_MORE_STR
+ || o->name == OPT_SECTION_STR
+ || o->name[0] == '\0')
+ continue;
+ BIO_printf(bio_out, "%s %c\n", o->name, c == '\0' ? '-' : c);
+ }
+ /* Always output the -- marker since it is sometimes documented. */
+ BIO_printf(bio_out, "- -\n");
+}
+
+static int is_md_available(const char *name)
+{
+ EVP_MD *md;
+ const char *propq = app_get0_propq();
+
+ /* Look through providers' digests */
+ ERR_set_mark();
+ md = EVP_MD_fetch(app_get0_libctx(), name, propq);
+ ERR_pop_to_mark();
+ if (md != NULL) {
+ EVP_MD_free(md);
+ return 1;
+ }
+
+ return propq != NULL || get_digest_from_engine(name) == NULL ? 0 : 1;
+}
+
+static int is_cipher_available(const char *name)
+{
+ EVP_CIPHER *cipher;
+ const char *propq = app_get0_propq();
+
+ /* Look through providers' ciphers */
+ ERR_set_mark();
+ cipher = EVP_CIPHER_fetch(app_get0_libctx(), name, propq);
+ ERR_pop_to_mark();
+ if (cipher != NULL) {
+ EVP_CIPHER_free(cipher);
+ return 1;
+ }
+
+ return propq != NULL || get_cipher_from_engine(name) == NULL ? 0 : 1;
+}
+
+static void list_type(FUNC_TYPE ft, int one)
+{
+ FUNCTION *fp;
+ int i = 0;
+ DISPLAY_COLUMNS dc;
+
+ memset(&dc, 0, sizeof(dc));
+ if (!one)
+ calculate_columns(functions, &dc);
+
+ for (fp = functions; fp->name != NULL; fp++) {
+ if (fp->type != ft)
+ continue;
+ switch (ft) {
+ case FT_cipher:
+ if (!is_cipher_available(fp->name))
+ continue;
+ break;
+ case FT_md:
+ if (!is_md_available(fp->name))
+ continue;
+ break;
+ default:
+ break;
+ }
+ if (one) {
+ BIO_printf(bio_out, "%s\n", fp->name);
+ } else {
+ if (i % dc.columns == 0 && i > 0)
+ BIO_printf(bio_out, "\n");
+ BIO_printf(bio_out, "%-*s", dc.width, fp->name);
+ i++;
+ }
+ }
+ if (!one)
+ BIO_printf(bio_out, "\n\n");
+}
+
+static void list_pkey(void)
+{
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ int i;
+
+ if (select_name == NULL && include_legacy()) {
+ BIO_printf(bio_out, "Legacy:\n");
+ for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ int pkey_id, pkey_base_id, pkey_flags;
+ const char *pinfo, *pem_str;
+ ameth = EVP_PKEY_asn1_get0(i);
+ EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags,
+ &pinfo, &pem_str, ameth);
+ if (pkey_flags & ASN1_PKEY_ALIAS) {
+ BIO_printf(bio_out, " Name: %s\n", OBJ_nid2ln(pkey_id));
+ BIO_printf(bio_out, "\tAlias for: %s\n",
+ OBJ_nid2ln(pkey_base_id));
+ } else {
+ BIO_printf(bio_out, " Name: %s\n", pinfo);
+ BIO_printf(bio_out, "\tType: %s Algorithm\n",
+ pkey_flags & ASN1_PKEY_DYNAMIC ?
+ "External" : "Builtin");
+ BIO_printf(bio_out, "\tOID: %s\n", OBJ_nid2ln(pkey_id));
+ if (pem_str == NULL)
+ pem_str = "(none)";
+ BIO_printf(bio_out, "\tPEM string: %s\n", pem_str);
+ }
+ }
+ }
+#endif
+ BIO_printf(bio_out, "Provided:\n");
+ BIO_printf(bio_out, " Key Managers:\n");
+ list_keymanagers();
+}
+
+static void list_pkey_meth(void)
+{
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ size_t i;
+ size_t meth_count = EVP_PKEY_meth_get_count();
+
+ if (select_name == NULL && include_legacy()) {
+ BIO_printf(bio_out, "Legacy:\n");
+ for (i = 0; i < meth_count; i++) {
+ const EVP_PKEY_METHOD *pmeth = EVP_PKEY_meth_get0(i);
+ int pkey_id, pkey_flags;
+
+ EVP_PKEY_meth_get0_info(&pkey_id, &pkey_flags, pmeth);
+ BIO_printf(bio_out, " %s\n", OBJ_nid2ln(pkey_id));
+ BIO_printf(bio_out, "\tType: %s Algorithm\n",
+ pkey_flags & ASN1_PKEY_DYNAMIC ? "External" : "Builtin");
+ }
+ }
+#endif
+ BIO_printf(bio_out, "Provided:\n");
+ BIO_printf(bio_out, " Encryption:\n");
+ list_asymciphers();
+ BIO_printf(bio_out, " Key Exchange:\n");
+ list_keyexchanges();
+ BIO_printf(bio_out, " Signatures:\n");
+ list_signatures();
+ BIO_printf(bio_out, " Key encapsulation:\n");
+ list_kems();
+}
+
+DEFINE_STACK_OF(OSSL_STORE_LOADER)
+static int store_cmp(const OSSL_STORE_LOADER * const *a,
+ const OSSL_STORE_LOADER * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(OSSL_STORE_LOADER_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(OSSL_STORE_LOADER_get0_provider(*b)));
+}
+
+static void collect_store_loaders(OSSL_STORE_LOADER *store, void *stack)
+{
+ STACK_OF(OSSL_STORE_LOADER) *store_stack = stack;
+
+ if (sk_OSSL_STORE_LOADER_push(store_stack, store) > 0)
+ OSSL_STORE_LOADER_up_ref(store);
+}
+
+static void list_store_loaders(void)
+{
+ STACK_OF(OSSL_STORE_LOADER) *stores = sk_OSSL_STORE_LOADER_new(store_cmp);
+ int i;
+
+ if (stores == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+ BIO_printf(bio_out, "Provided STORE LOADERs:\n");
+ OSSL_STORE_LOADER_do_all_provided(app_get0_libctx(), collect_store_loaders,
+ stores);
+ sk_OSSL_STORE_LOADER_sort(stores);
+ for (i = 0; i < sk_OSSL_STORE_LOADER_num(stores); i++) {
+ const OSSL_STORE_LOADER *m = sk_OSSL_STORE_LOADER_value(stores, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !OSSL_STORE_LOADER_is_a(m, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && OSSL_STORE_LOADER_names_do_all(m, collect_names,
+ names)) {
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(OSSL_STORE_LOADER_get0_provider(m)));
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_OSSL_STORE_LOADER_pop_free(stores, OSSL_STORE_LOADER_free);
+}
+
+DEFINE_STACK_OF(OSSL_PROVIDER)
+static int provider_cmp(const OSSL_PROVIDER * const *a,
+ const OSSL_PROVIDER * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(*a), OSSL_PROVIDER_get0_name(*b));
+}
+
+static int collect_providers(OSSL_PROVIDER *provider, void *stack)
+{
+ STACK_OF(OSSL_PROVIDER) *provider_stack = stack;
+
+ sk_OSSL_PROVIDER_push(provider_stack, provider);
+ return 1;
+}
+
+static void list_provider_info(void)
+{
+ STACK_OF(OSSL_PROVIDER) *providers = sk_OSSL_PROVIDER_new(provider_cmp);
+ OSSL_PARAM params[5];
+ char *name, *version, *buildinfo;
+ int status;
+ int i;
+
+ if (providers == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+ BIO_printf(bio_out, "Providers:\n");
+ OSSL_PROVIDER_do_all(NULL, &collect_providers, providers);
+ sk_OSSL_PROVIDER_sort(providers);
+ for (i = 0; i < sk_OSSL_PROVIDER_num(providers); i++) {
+ const OSSL_PROVIDER *prov = sk_OSSL_PROVIDER_value(providers, i);
+
+ /* Query the "known" information parameters, the order matches below */
+ params[0] = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_NAME,
+ &name, 0);
+ params[1] = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_VERSION,
+ &version, 0);
+ params[2] = OSSL_PARAM_construct_int(OSSL_PROV_PARAM_STATUS, &status);
+ params[3] = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_BUILDINFO,
+ &buildinfo, 0);
+ params[4] = OSSL_PARAM_construct_end();
+ OSSL_PARAM_set_all_unmodified(params);
+ if (!OSSL_PROVIDER_get_params(prov, params)) {
+ BIO_printf(bio_err, "ERROR: Unable to query provider parameters\n");
+ return;
+ }
+
+ /* Print out the provider information, the params order matches above */
+ BIO_printf(bio_out, " %s\n", OSSL_PROVIDER_get0_name(prov));
+ if (OSSL_PARAM_modified(params))
+ BIO_printf(bio_out, " name: %s\n", name);
+ if (OSSL_PARAM_modified(params + 1))
+ BIO_printf(bio_out, " version: %s\n", version);
+ if (OSSL_PARAM_modified(params + 2))
+ BIO_printf(bio_out, " status: %sactive\n", status ? "" : "in");
+ if (verbose) {
+ if (OSSL_PARAM_modified(params + 3))
+ BIO_printf(bio_out, " build info: %s\n", buildinfo);
+ print_param_types("gettable provider parameters",
+ OSSL_PROVIDER_gettable_params(prov), 4);
+ }
+ }
+ sk_OSSL_PROVIDER_free(providers);
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+static void list_engines(void)
+{
+# ifndef OPENSSL_NO_ENGINE
+ ENGINE *e;
+
+ BIO_puts(bio_out, "Engines:\n");
+ e = ENGINE_get_first();
+ while (e) {
+ BIO_printf(bio_out, "%s\n", ENGINE_get_id(e));
+ e = ENGINE_get_next(e);
+ }
+# else
+ BIO_puts(bio_out, "Engine support is disabled.\n");
+# endif
+}
+#endif
+
+static void list_disabled(void)
+{
+ BIO_puts(bio_out, "Disabled algorithms:\n");
+#ifdef OPENSSL_NO_ARIA
+ BIO_puts(bio_out, "ARIA\n");
+#endif
+#ifdef OPENSSL_NO_BF
+ BIO_puts(bio_out, "BF\n");
+#endif
+#ifdef OPENSSL_NO_BLAKE2
+ BIO_puts(bio_out, "BLAKE2\n");
+#endif
+#ifdef OPENSSL_NO_CAMELLIA
+ BIO_puts(bio_out, "CAMELLIA\n");
+#endif
+#ifdef OPENSSL_NO_CAST
+ BIO_puts(bio_out, "CAST\n");
+#endif
+#ifdef OPENSSL_NO_CMAC
+ BIO_puts(bio_out, "CMAC\n");
+#endif
+#ifdef OPENSSL_NO_CMS
+ BIO_puts(bio_out, "CMS\n");
+#endif
+#ifdef OPENSSL_NO_COMP
+ BIO_puts(bio_out, "COMP\n");
+#endif
+#ifdef OPENSSL_NO_DES
+ BIO_puts(bio_out, "DES\n");
+#endif
+#ifdef OPENSSL_NO_DGRAM
+ BIO_puts(bio_out, "DGRAM\n");
+#endif
+#ifdef OPENSSL_NO_DH
+ BIO_puts(bio_out, "DH\n");
+#endif
+#ifdef OPENSSL_NO_DSA
+ BIO_puts(bio_out, "DSA\n");
+#endif
+#if defined(OPENSSL_NO_DTLS)
+ BIO_puts(bio_out, "DTLS\n");
+#endif
+#if defined(OPENSSL_NO_DTLS1)
+ BIO_puts(bio_out, "DTLS1\n");
+#endif
+#if defined(OPENSSL_NO_DTLS1_2)
+ BIO_puts(bio_out, "DTLS1_2\n");
+#endif
+#ifdef OPENSSL_NO_EC
+ BIO_puts(bio_out, "EC\n");
+#endif
+#ifdef OPENSSL_NO_EC2M
+ BIO_puts(bio_out, "EC2M\n");
+#endif
+#if defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0)
+ BIO_puts(bio_out, "ENGINE\n");
+#endif
+#ifdef OPENSSL_NO_GOST
+ BIO_puts(bio_out, "GOST\n");
+#endif
+#ifdef OPENSSL_NO_IDEA
+ BIO_puts(bio_out, "IDEA\n");
+#endif
+#ifdef OPENSSL_NO_MD2
+ BIO_puts(bio_out, "MD2\n");
+#endif
+#ifdef OPENSSL_NO_MD4
+ BIO_puts(bio_out, "MD4\n");
+#endif
+#ifdef OPENSSL_NO_MD5
+ BIO_puts(bio_out, "MD5\n");
+#endif
+#ifdef OPENSSL_NO_MDC2
+ BIO_puts(bio_out, "MDC2\n");
+#endif
+#ifdef OPENSSL_NO_OCB
+ BIO_puts(bio_out, "OCB\n");
+#endif
+#ifdef OPENSSL_NO_OCSP
+ BIO_puts(bio_out, "OCSP\n");
+#endif
+#ifdef OPENSSL_NO_PSK
+ BIO_puts(bio_out, "PSK\n");
+#endif
+#ifdef OPENSSL_NO_RC2
+ BIO_puts(bio_out, "RC2\n");
+#endif
+#ifdef OPENSSL_NO_RC4
+ BIO_puts(bio_out, "RC4\n");
+#endif
+#ifdef OPENSSL_NO_RC5
+ BIO_puts(bio_out, "RC5\n");
+#endif
+#ifdef OPENSSL_NO_RMD160
+ BIO_puts(bio_out, "RMD160\n");
+#endif
+#ifdef OPENSSL_NO_SCRYPT
+ BIO_puts(bio_out, "SCRYPT\n");
+#endif
+#ifdef OPENSSL_NO_SCTP
+ BIO_puts(bio_out, "SCTP\n");
+#endif
+#ifdef OPENSSL_NO_SEED
+ BIO_puts(bio_out, "SEED\n");
+#endif
+#ifdef OPENSSL_NO_SM2
+ BIO_puts(bio_out, "SM2\n");
+#endif
+#ifdef OPENSSL_NO_SM3
+ BIO_puts(bio_out, "SM3\n");
+#endif
+#ifdef OPENSSL_NO_SM4
+ BIO_puts(bio_out, "SM4\n");
+#endif
+#ifdef OPENSSL_NO_SOCK
+ BIO_puts(bio_out, "SOCK\n");
+#endif
+#ifdef OPENSSL_NO_SRP
+ BIO_puts(bio_out, "SRP\n");
+#endif
+#ifdef OPENSSL_NO_SRTP
+ BIO_puts(bio_out, "SRTP\n");
+#endif
+#ifdef OPENSSL_NO_SSL3
+ BIO_puts(bio_out, "SSL3\n");
+#endif
+#ifdef OPENSSL_NO_TLS1
+ BIO_puts(bio_out, "TLS1\n");
+#endif
+#ifdef OPENSSL_NO_TLS1_1
+ BIO_puts(bio_out, "TLS1_1\n");
+#endif
+#ifdef OPENSSL_NO_TLS1_2
+ BIO_puts(bio_out, "TLS1_2\n");
+#endif
+#ifdef OPENSSL_NO_WHIRLPOOL
+ BIO_puts(bio_out, "WHIRLPOOL\n");
+#endif
+#ifndef ZLIB
+ BIO_puts(bio_out, "ZLIB\n");
+#endif
+}
+
+/* Unified enum for help and list commands. */
+typedef enum HELPLIST_CHOICE {
+ OPT_COMMON,
+ OPT_ONE, OPT_VERBOSE,
+ OPT_COMMANDS, OPT_DIGEST_COMMANDS, OPT_MAC_ALGORITHMS, OPT_OPTIONS,
+ OPT_DIGEST_ALGORITHMS, OPT_CIPHER_COMMANDS, OPT_CIPHER_ALGORITHMS,
+ OPT_PK_ALGORITHMS, OPT_PK_METHOD, OPT_DISABLED,
+ OPT_KDF_ALGORITHMS, OPT_RANDOM_INSTANCES, OPT_RANDOM_GENERATORS,
+ OPT_ENCODERS, OPT_DECODERS, OPT_KEYMANAGERS, OPT_KEYEXCHANGE_ALGORITHMS,
+ OPT_KEM_ALGORITHMS, OPT_SIGNATURE_ALGORITHMS, OPT_ASYM_CIPHER_ALGORITHMS,
+ OPT_STORE_LOADERS, OPT_PROVIDER_INFO,
+ OPT_OBJECTS, OPT_SELECT_NAME,
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ OPT_ENGINES,
+#endif
+ OPT_PROV_ENUM
+} HELPLIST_CHOICE;
+
+const OPTIONS list_options[] = {
+
+ OPT_SECTION("General"),
+ {"help", OPT_HELP, '-', "Display this summary"},
+
+ OPT_SECTION("Output"),
+ {"1", OPT_ONE, '-', "List in one column"},
+ {"verbose", OPT_VERBOSE, '-', "Verbose listing"},
+ {"select", OPT_SELECT_NAME, 's', "Select a single algorithm"},
+ {"commands", OPT_COMMANDS, '-', "List of standard commands"},
+ {"standard-commands", OPT_COMMANDS, '-', "List of standard commands"},
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ {"digest-commands", OPT_DIGEST_COMMANDS, '-',
+ "List of message digest commands (deprecated)"},
+#endif
+ {"digest-algorithms", OPT_DIGEST_ALGORITHMS, '-',
+ "List of message digest algorithms"},
+ {"kdf-algorithms", OPT_KDF_ALGORITHMS, '-',
+ "List of key derivation and pseudo random function algorithms"},
+ {"random-instances", OPT_RANDOM_INSTANCES, '-',
+ "List the primary, public and private random number generator details"},
+ {"random-generators", OPT_RANDOM_GENERATORS, '-',
+ "List of random number generators"},
+ {"mac-algorithms", OPT_MAC_ALGORITHMS, '-',
+ "List of message authentication code algorithms"},
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ {"cipher-commands", OPT_CIPHER_COMMANDS, '-',
+ "List of cipher commands (deprecated)"},
+#endif
+ {"cipher-algorithms", OPT_CIPHER_ALGORITHMS, '-',
+ "List of symmetric cipher algorithms"},
+ {"encoders", OPT_ENCODERS, '-', "List of encoding methods" },
+ {"decoders", OPT_DECODERS, '-', "List of decoding methods" },
+ {"key-managers", OPT_KEYMANAGERS, '-', "List of key managers" },
+ {"key-exchange-algorithms", OPT_KEYEXCHANGE_ALGORITHMS, '-',
+ "List of key exchange algorithms" },
+ {"kem-algorithms", OPT_KEM_ALGORITHMS, '-',
+ "List of key encapsulation mechanism algorithms" },
+ {"signature-algorithms", OPT_SIGNATURE_ALGORITHMS, '-',
+ "List of signature algorithms" },
+ {"asymcipher-algorithms", OPT_ASYM_CIPHER_ALGORITHMS, '-',
+ "List of asymmetric cipher algorithms" },
+ {"public-key-algorithms", OPT_PK_ALGORITHMS, '-',
+ "List of public key algorithms"},
+ {"public-key-methods", OPT_PK_METHOD, '-',
+ "List of public key methods"},
+ {"store-loaders", OPT_STORE_LOADERS, '-',
+ "List of store loaders"},
+ {"providers", OPT_PROVIDER_INFO, '-',
+ "List of provider information"},
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ {"engines", OPT_ENGINES, '-',
+ "List of loaded engines"},
+#endif
+ {"disabled", OPT_DISABLED, '-', "List of disabled features"},
+ {"options", OPT_OPTIONS, 's',
+ "List options for specified command"},
+ {"objects", OPT_OBJECTS, '-',
+ "List built in objects (OID<->name mappings)"},
+
+ OPT_PROV_OPTIONS,
+ {NULL}
+};
+
+int list_main(int argc, char **argv)
+{
+ char *prog;
+ HELPLIST_CHOICE o;
+ int one = 0, done = 0;
+ struct {
+ unsigned int commands:1;
+ unsigned int random_instances:1;
+ unsigned int random_generators:1;
+ unsigned int digest_commands:1;
+ unsigned int digest_algorithms:1;
+ unsigned int kdf_algorithms:1;
+ unsigned int mac_algorithms:1;
+ unsigned int cipher_commands:1;
+ unsigned int cipher_algorithms:1;
+ unsigned int encoder_algorithms:1;
+ unsigned int decoder_algorithms:1;
+ unsigned int keymanager_algorithms:1;
+ unsigned int signature_algorithms:1;
+ unsigned int keyexchange_algorithms:1;
+ unsigned int kem_algorithms:1;
+ unsigned int asym_cipher_algorithms:1;
+ unsigned int pk_algorithms:1;
+ unsigned int pk_method:1;
+ unsigned int store_loaders:1;
+ unsigned int provider_info:1;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ unsigned int engines:1;
+#endif
+ unsigned int disabled:1;
+ unsigned int objects:1;
+ unsigned int options:1;
+ } todo = { 0, };
+
+ verbose = 0; /* Clear a possible previous call */
+
+ prog = opt_init(argc, argv, list_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF: /* Never hit, but suppresses warning */
+ case OPT_ERR:
+opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ return 1;
+ case OPT_HELP:
+ opt_help(list_options);
+ return 0;
+ case OPT_ONE:
+ one = 1;
+ break;
+ case OPT_COMMANDS:
+ todo.commands = 1;
+ break;
+ case OPT_DIGEST_COMMANDS:
+ todo.digest_commands = 1;
+ break;
+ case OPT_DIGEST_ALGORITHMS:
+ todo.digest_algorithms = 1;
+ break;
+ case OPT_KDF_ALGORITHMS:
+ todo.kdf_algorithms = 1;
+ break;
+ case OPT_RANDOM_INSTANCES:
+ todo.random_instances = 1;
+ break;
+ case OPT_RANDOM_GENERATORS:
+ todo.random_generators = 1;
+ break;
+ case OPT_MAC_ALGORITHMS:
+ todo.mac_algorithms = 1;
+ break;
+ case OPT_CIPHER_COMMANDS:
+ todo.cipher_commands = 1;
+ break;
+ case OPT_CIPHER_ALGORITHMS:
+ todo.cipher_algorithms = 1;
+ break;
+ case OPT_ENCODERS:
+ todo.encoder_algorithms = 1;
+ break;
+ case OPT_DECODERS:
+ todo.decoder_algorithms = 1;
+ break;
+ case OPT_KEYMANAGERS:
+ todo.keymanager_algorithms = 1;
+ break;
+ case OPT_SIGNATURE_ALGORITHMS:
+ todo.signature_algorithms = 1;
+ break;
+ case OPT_KEYEXCHANGE_ALGORITHMS:
+ todo.keyexchange_algorithms = 1;
+ break;
+ case OPT_KEM_ALGORITHMS:
+ todo.kem_algorithms = 1;
+ break;
+ case OPT_ASYM_CIPHER_ALGORITHMS:
+ todo.asym_cipher_algorithms = 1;
+ break;
+ case OPT_PK_ALGORITHMS:
+ todo.pk_algorithms = 1;
+ break;
+ case OPT_PK_METHOD:
+ todo.pk_method = 1;
+ break;
+ case OPT_STORE_LOADERS:
+ todo.store_loaders = 1;
+ break;
+ case OPT_PROVIDER_INFO:
+ todo.provider_info = 1;
+ break;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ case OPT_ENGINES:
+ todo.engines = 1;
+ break;
+#endif
+ case OPT_DISABLED:
+ todo.disabled = 1;
+ break;
+ case OPT_OBJECTS:
+ todo.objects = 1;
+ break;
+ case OPT_OPTIONS:
+ list_options_for_command(opt_arg());
+ break;
+ case OPT_VERBOSE:
+ verbose = 1;
+ break;
+ case OPT_SELECT_NAME:
+ select_name = opt_arg();
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ return 1;
+ break;
+ }
+ done = 1;
+ }
+
+ /* No extra arguments. */
+ if (opt_num_rest() != 0)
+ goto opthelp;
+
+ if (todo.commands)
+ list_type(FT_general, one);
+ if (todo.random_instances)
+ list_random_instances();
+ if (todo.random_generators)
+ list_random_generators();
+ if (todo.digest_commands)
+ list_type(FT_md, one);
+ if (todo.digest_algorithms)
+ list_digests();
+ if (todo.kdf_algorithms)
+ list_kdfs();
+ if (todo.mac_algorithms)
+ list_macs();
+ if (todo.cipher_commands)
+ list_type(FT_cipher, one);
+ if (todo.cipher_algorithms)
+ list_ciphers();
+ if (todo.encoder_algorithms)
+ list_encoders();
+ if (todo.decoder_algorithms)
+ list_decoders();
+ if (todo.keymanager_algorithms)
+ list_keymanagers();
+ if (todo.signature_algorithms)
+ list_signatures();
+ if (todo.asym_cipher_algorithms)
+ list_asymciphers();
+ if (todo.keyexchange_algorithms)
+ list_keyexchanges();
+ if (todo.kem_algorithms)
+ list_kems();
+ if (todo.pk_algorithms)
+ list_pkey();
+ if (todo.pk_method)
+ list_pkey_meth();
+ if (todo.store_loaders)
+ list_store_loaders();
+ if (todo.provider_info)
+ list_provider_info();
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (todo.engines)
+ list_engines();
+#endif
+ if (todo.disabled)
+ list_disabled();
+ if (todo.objects)
+ list_objects();
+
+ if (!done)
+ goto opthelp;
+
+ return 0;
+}
diff --git a/apps/mac.c b/apps/mac.c
new file mode 100644
index 000000000000..a9b6a265f49a
--- /dev/null
+++ b/apps/mac.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+
+#include "apps.h"
+#include "progs.h"
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
+
+#undef BUFSIZE
+#define BUFSIZE 1024*8
+
+typedef enum OPTION_choice {
+ OPT_COMMON,
+ OPT_MACOPT, OPT_BIN, OPT_IN, OPT_OUT,
+ OPT_CIPHER, OPT_DIGEST,
+ OPT_PROV_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS mac_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] mac_name\n"},
+
+ OPT_SECTION("General"),
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form"},
+ {"cipher", OPT_CIPHER, 's', "Cipher"},
+ {"digest", OPT_DIGEST, 's', "Digest"},
+ {OPT_MORE_STR, 1, '-', "See 'PARAMETER NAMES' in the EVP_MAC_ docs"},
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, '<', "Input file to MAC (default is stdin)"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output to filename rather than stdout"},
+ {"binary", OPT_BIN, '-',
+ "Output in binary format (default is hexadecimal)"},
+
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"mac_name", 0, 0, "MAC algorithm"},
+ {NULL}
+};
+
+static char *alloc_mac_algorithm_name(STACK_OF(OPENSSL_STRING) **optp,
+ const char *name, const char *arg)
+{
+ size_t len = strlen(name) + strlen(arg) + 2;
+ char *res;
+
+ if (*optp == NULL)
+ *optp = sk_OPENSSL_STRING_new_null();
+ if (*optp == NULL)
+ return NULL;
+
+ res = app_malloc(len, "algorithm name");
+ BIO_snprintf(res, len, "%s:%s", name, arg);
+ if (sk_OPENSSL_STRING_push(*optp, res))
+ return res;
+ OPENSSL_free(res);
+ return NULL;
+}
+
+int mac_main(int argc, char **argv)
+{
+ int ret = 1;
+ char *prog;
+ EVP_MAC *mac = NULL;
+ OPTION_CHOICE o;
+ EVP_MAC_CTX *ctx = NULL;
+ STACK_OF(OPENSSL_STRING) *opts = NULL;
+ unsigned char *buf = NULL;
+ size_t len;
+ int i;
+ BIO *in = NULL, *out = NULL;
+ const char *outfile = NULL;
+ const char *infile = NULL;
+ int out_bin = 0;
+ int inform = FORMAT_BINARY;
+ char *digest = NULL, *cipher = NULL;
+ OSSL_PARAM *params = NULL;
+
+ prog = opt_init(argc, argv, mac_options);
+ buf = app_malloc(BUFSIZE, "I/O buffer");
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ default:
+opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto err;
+ case OPT_HELP:
+ opt_help(mac_options);
+ ret = 0;
+ goto err;
+ case OPT_BIN:
+ out_bin = 1;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_MACOPT:
+ if (opts == NULL)
+ opts = sk_OPENSSL_STRING_new_null();
+ if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg()))
+ goto opthelp;
+ break;
+ case OPT_CIPHER:
+ OPENSSL_free(cipher);
+ cipher = alloc_mac_algorithm_name(&opts, "cipher", opt_arg());
+ if (cipher == NULL)
+ goto opthelp;
+ break;
+ case OPT_DIGEST:
+ OPENSSL_free(digest);
+ digest = alloc_mac_algorithm_name(&opts, "digest", opt_arg());
+ if (digest == NULL)
+ goto opthelp;
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto err;
+ break;
+ }
+ }
+
+ /* One argument, the MAC name. */
+ argc = opt_num_rest();
+ argv = opt_rest();
+ if (argc != 1)
+ goto opthelp;
+
+ mac = EVP_MAC_fetch(app_get0_libctx(), argv[0], app_get0_propq());
+ if (mac == NULL) {
+ BIO_printf(bio_err, "Invalid MAC name %s\n", argv[0]);
+ goto opthelp;
+ }
+
+ ctx = EVP_MAC_CTX_new(mac);
+ if (ctx == NULL)
+ goto err;
+
+ if (opts != NULL) {
+ int ok = 1;
+
+ params = app_params_new_from_opts(opts,
+ EVP_MAC_settable_ctx_params(mac));
+ if (params == NULL)
+ goto err;
+
+ if (!EVP_MAC_CTX_set_params(ctx, params)) {
+ BIO_printf(bio_err, "MAC parameter error\n");
+ ERR_print_errors(bio_err);
+ ok = 0;
+ }
+ app_params_free(params);
+ if (!ok)
+ goto err;
+ }
+
+ in = bio_open_default(infile, 'r', inform);
+ if (in == NULL)
+ goto err;
+
+ out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT);
+ if (out == NULL)
+ goto err;
+
+ if (!EVP_MAC_init(ctx, NULL, 0, NULL)) {
+ BIO_printf(bio_err, "EVP_MAC_Init failed\n");
+ goto err;
+ }
+
+ while (BIO_pending(in) || !BIO_eof(in)) {
+ i = BIO_read(in, (char *)buf, BUFSIZE);
+ if (i < 0) {
+ BIO_printf(bio_err, "Read Error in '%s'\n", infile);
+ ERR_print_errors(bio_err);
+ goto err;
+ }
+ if (i == 0)
+ break;
+ if (!EVP_MAC_update(ctx, buf, i)) {
+ BIO_printf(bio_err, "EVP_MAC_update failed\n");
+ goto err;
+ }
+ }
+
+ if (!EVP_MAC_final(ctx, NULL, &len, 0)) {
+ BIO_printf(bio_err, "EVP_MAC_final failed\n");
+ goto err;
+ }
+ if (len > BUFSIZE) {
+ BIO_printf(bio_err, "output len is too large\n");
+ goto err;
+ }
+
+ if (!EVP_MAC_final(ctx, buf, &len, BUFSIZE)) {
+ BIO_printf(bio_err, "EVP_MAC_final failed\n");
+ goto err;
+ }
+
+ if (out_bin) {
+ BIO_write(out, buf, len);
+ } else {
+ for (i = 0; i < (int)len; ++i)
+ BIO_printf(out, "%02X", buf[i]);
+ if (outfile == NULL)
+ BIO_printf(out,"\n");
+ }
+
+ ret = 0;
+err:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
+ OPENSSL_clear_free(buf, BUFSIZE);
+ OPENSSL_free(cipher);
+ OPENSSL_free(digest);
+ sk_OPENSSL_STRING_free(opts);
+ BIO_free(in);
+ BIO_free(out);
+ EVP_MAC_CTX_free(ctx);
+ EVP_MAC_free(mac);
+ return ret;
+}
diff --git a/apps/nseq.c b/apps/nseq.c
index a067c915926f..d5524370f26c 100644
--- a/apps/nseq.c
+++ b/apps/nseq.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -15,15 +15,23 @@
#include <openssl/err.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_TOSEQ, OPT_IN, OPT_OUT
+ OPT_COMMON,
+ OPT_TOSEQ, OPT_IN, OPT_OUT,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS nseq_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"toseq", OPT_TOSEQ, '-', "Output NS Sequence file"},
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file"},
+
+ OPT_SECTION("Output"),
+ {"toseq", OPT_TOSEQ, '-', "Output NS Sequence file"},
{"out", OPT_OUT, '>', "Output file"},
+
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -57,8 +65,14 @@ int nseq_main(int argc, char **argv)
case OPT_OUT:
outfile = opt_arg();
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
@@ -77,8 +91,10 @@ int nseq_main(int argc, char **argv)
seq->certs = sk_X509_new_null();
if (seq->certs == NULL)
goto end;
- while ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL)))
- sk_X509_push(seq->certs, x509);
+ while ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
+ if (!sk_X509_push(seq->certs, x509))
+ goto end;
+ }
if (!sk_X509_num(seq->certs)) {
BIO_printf(bio_err, "%s: Error reading certs file %s\n",
diff --git a/apps/ocsp.c b/apps/ocsp.c
index 8f20864cea51..821e224c6ce4 100644
--- a/apps/ocsp.c
+++ b/apps/ocsp.c
@@ -1,7 +1,7 @@
/*
* Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,8 +10,8 @@
#include <openssl/opensslconf.h>
#ifdef OPENSSL_SYS_VMS
-# define _XOPEN_SOURCE_EXTENDED/* So fd_set and friends get properly defined
- * on OpenVMS */
+ /* So fd_set and friends get properly defined on OpenVMS */
+# define _XOPEN_SOURCE_EXTENDED
#endif
#include <stdio.h>
@@ -22,6 +22,7 @@
/* Needs to be included before the openssl headers */
#include "apps.h"
+#include "http_server.h"
#include "progs.h"
#include "internal/sockets.h"
#include <openssl/e_os2.h>
@@ -31,37 +32,11 @@
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/x509v3.h>
-#include <openssl/rand.h>
-#ifndef HAVE_FORK
-#if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS)
-# define HAVE_FORK 0
-#else
-# define HAVE_FORK 1
-#endif
-#endif
-
-#if HAVE_FORK
-#undef NO_FORK
-#else
-#define NO_FORK
-#endif
-
-#if !defined(NO_FORK) && !defined(OPENSSL_NO_SOCK) \
- && !defined(OPENSSL_NO_POSIX_IO)
-# define OCSP_DAEMON
-# include <sys/types.h>
-# include <sys/wait.h>
-# include <syslog.h>
-# include <signal.h>
-# define MAXERRLEN 1000 /* limit error text sent to syslog to 1000 bytes */
-#else
-# undef LOG_INFO
-# undef LOG_WARNING
-# undef LOG_ERR
-# define LOG_INFO 0
-# define LOG_WARNING 1
-# define LOG_ERR 2
+#if defined(__TANDEM)
+# if defined(OPENSSL_TANDEM_FLOSS)
+# include <floss.h(floss_fork)>
+# endif
#endif
#if defined(OPENSSL_SYS_VXWORKS)
@@ -87,7 +62,7 @@ static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert,
static int add_ocsp_serial(OCSP_REQUEST **req, char *serial,
const EVP_MD *cert_id_md, X509 *issuer,
STACK_OF(OCSP_CERTID) *ids);
-static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
+static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
STACK_OF(OPENSSL_STRING) *names,
STACK_OF(OCSP_CERTID) *ids, long nsec,
long maxage);
@@ -96,76 +71,118 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req
EVP_PKEY *rkey, const EVP_MD *md,
STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(X509) *rother, unsigned long flags,
- int nmin, int ndays, int badsig);
+ int nmin, int ndays, int badsig,
+ const EVP_MD *resp_md);
static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser);
-static BIO *init_responder(const char *port);
-static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, int timeout);
-static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp);
-static void log_message(int level, const char *fmt, ...);
+static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio,
+ const char *port, int timeout);
+static int send_ocsp_response(BIO *cbio, const OCSP_RESPONSE *resp);
static char *prog;
-static int multi = 0;
-#ifdef OCSP_DAEMON
-static int acfd = (int) INVALID_SOCKET;
+#ifdef HTTP_DAEMON
static int index_changed(CA_DB *);
-static void spawn_loop(void);
-static int print_syslog(const char *str, size_t len, void *levPtr);
-static void socket_timeout(int signum);
-#endif
-
-#ifndef OPENSSL_NO_SOCK
-static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host,
- const char *path,
- const STACK_OF(CONF_VALUE) *headers,
- OCSP_REQUEST *req, int req_timeout);
#endif
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_OUTFILE, OPT_TIMEOUT, OPT_URL, OPT_HOST, OPT_PORT,
+#ifndef OPENSSL_NO_SOCK
+ OPT_PROXY, OPT_NO_PROXY,
+#endif
OPT_IGNORE_ERR, OPT_NOVERIFY, OPT_NONCE, OPT_NO_NONCE,
OPT_RESP_NO_CERTS, OPT_RESP_KEY_ID, OPT_NO_CERTS,
OPT_NO_SIGNATURE_VERIFY, OPT_NO_CERT_VERIFY, OPT_NO_CHAIN,
OPT_NO_CERT_CHECKS, OPT_NO_EXPLICIT, OPT_TRUST_OTHER,
OPT_NO_INTERN, OPT_BADSIG, OPT_TEXT, OPT_REQ_TEXT, OPT_RESP_TEXT,
OPT_REQIN, OPT_RESPIN, OPT_SIGNER, OPT_VAFILE, OPT_SIGN_OTHER,
- OPT_VERIFY_OTHER, OPT_CAFILE, OPT_CAPATH, OPT_NOCAFILE, OPT_NOCAPATH,
+ OPT_VERIFY_OTHER, OPT_CAFILE, OPT_CAPATH, OPT_CASTORE, OPT_NOCAFILE,
+ OPT_NOCAPATH, OPT_NOCASTORE,
OPT_VALIDITY_PERIOD, OPT_STATUS_AGE, OPT_SIGNKEY, OPT_REQOUT,
OPT_RESPOUT, OPT_PATH, OPT_ISSUER, OPT_CERT, OPT_SERIAL,
OPT_INDEX, OPT_CA, OPT_NMIN, OPT_REQUEST, OPT_NDAYS, OPT_RSIGNER,
OPT_RKEY, OPT_ROTHER, OPT_RMD, OPT_RSIGOPT, OPT_HEADER,
+ OPT_PASSIN,
+ OPT_RCID,
OPT_V_ENUM,
OPT_MD,
- OPT_MULTI
+ OPT_MULTI, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS ocsp_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"out", OPT_OUTFILE, '>', "Output filename"},
- {"timeout", OPT_TIMEOUT, 'p',
- "Connection timeout (in seconds) to the OCSP responder"},
- {"url", OPT_URL, 's', "Responder URL"},
- {"host", OPT_HOST, 's', "TCP/IP hostname:port to connect to"},
- {"port", OPT_PORT, 'p', "Port to run responder on"},
{"ignore_err", OPT_IGNORE_ERR, '-',
"Ignore error on OCSP request or response and continue running"},
- {"noverify", OPT_NOVERIFY, '-', "Don't verify response at all"},
- {"nonce", OPT_NONCE, '-', "Add OCSP nonce to request"},
- {"no_nonce", OPT_NO_NONCE, '-', "Don't add OCSP nonce to request"},
+ {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
+ {"CApath", OPT_CAPATH, '<', "Trusted certificates directory"},
+ {"CAstore", OPT_CASTORE, ':', "Trusted certificates store URI"},
+ {"no-CAfile", OPT_NOCAFILE, '-',
+ "Do not load the default certificates file"},
+ {"no-CApath", OPT_NOCAPATH, '-',
+ "Do not load certificates from the default certificates directory"},
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load certificates from the default certificates store"},
+
+ OPT_SECTION("Responder"),
+ {"timeout", OPT_TIMEOUT, 'p',
+ "Connection timeout (in seconds) to the OCSP responder"},
{"resp_no_certs", OPT_RESP_NO_CERTS, '-',
"Don't include any certificates in response"},
- {"resp_key_id", OPT_RESP_KEY_ID, '-',
- "Identify response by signing certificate key ID"},
-#ifdef OCSP_DAEMON
+#ifdef HTTP_DAEMON
{"multi", OPT_MULTI, 'p', "run multiple responder processes"},
#endif
{"no_certs", OPT_NO_CERTS, '-',
"Don't include any certificates in signed request"},
+ {"badsig", OPT_BADSIG, '-',
+ "Corrupt last byte of loaded OCSP response signature (for test)"},
+ {"CA", OPT_CA, '<', "CA certificate"},
+ {"nmin", OPT_NMIN, 'p', "Number of minutes before next update"},
+ {"nrequest", OPT_REQUEST, 'p',
+ "Number of requests to accept (default unlimited)"},
+ {"reqin", OPT_REQIN, 's', "File with the DER-encoded request"},
+ {"signer", OPT_SIGNER, '<', "Certificate to sign OCSP request with"},
+ {"sign_other", OPT_SIGN_OTHER, '<',
+ "Additional certificates to include in signed request"},
+ {"index", OPT_INDEX, '<', "Certificate status index file"},
+ {"ndays", OPT_NDAYS, 'p', "Number of days before next update"},
+ {"rsigner", OPT_RSIGNER, '<',
+ "Responder certificate to sign responses with"},
+ {"rkey", OPT_RKEY, '<', "Responder key to sign responses with"},
+ {"passin", OPT_PASSIN, 's', "Responder key pass phrase source"},
+ {"rother", OPT_ROTHER, '<', "Other certificates to include in response"},
+ {"rmd", OPT_RMD, 's', "Digest Algorithm to use in signature of OCSP response"},
+ {"rsigopt", OPT_RSIGOPT, 's', "OCSP response signature parameter in n:v form"},
+ {"header", OPT_HEADER, 's', "key=value header to add"},
+ {"rcid", OPT_RCID, 's', "Use specified algorithm for cert id in response"},
+ {"", OPT_MD, '-', "Any supported digest algorithm (sha1,sha256, ... )"},
+
+ OPT_SECTION("Client"),
+ {"url", OPT_URL, 's', "Responder URL"},
+ {"host", OPT_HOST, 's', "TCP/IP hostname:port to connect to"},
+ {"port", OPT_PORT, 'N', "Port to run responder on"},
+ {"path", OPT_PATH, 's', "Path to use in OCSP request"},
+#ifndef OPENSSL_NO_SOCK
+ {"proxy", OPT_PROXY, 's',
+ "[http[s]://]host[:port][/path] of HTTP(S) proxy to use; path is ignored"},
+ {"no_proxy", OPT_NO_PROXY, 's',
+ "List of addresses of servers not to use HTTP(S) proxy for"},
+ {OPT_MORE_STR, 0, 0,
+ "Default from environment variable 'no_proxy', else 'NO_PROXY', else none"},
+#endif
+ {"out", OPT_OUTFILE, '>', "Output filename"},
+ {"noverify", OPT_NOVERIFY, '-', "Don't verify response at all"},
+ {"nonce", OPT_NONCE, '-', "Add OCSP nonce to request"},
+ {"no_nonce", OPT_NO_NONCE, '-', "Don't add OCSP nonce to request"},
{"no_signature_verify", OPT_NO_SIGNATURE_VERIFY, '-',
"Don't check signature on response"},
+ {"resp_key_id", OPT_RESP_KEY_ID, '-',
+ "Identify response by signing certificate key ID"},
{"no_cert_verify", OPT_NO_CERT_VERIFY, '-',
"Don't check signing certificate"},
+ {"text", OPT_TEXT, '-', "Print text form of request and response"},
+ {"req_text", OPT_REQ_TEXT, '-', "Print text form of request"},
+ {"resp_text", OPT_RESP_TEXT, '-', "Print text form of response"},
{"no_chain", OPT_NO_CHAIN, '-', "Don't chain verify response"},
{"no_cert_checks", OPT_NO_CERT_CHECKS, '-',
"Don't do additional checks on signing certificate"},
@@ -175,57 +192,29 @@ const OPTIONS ocsp_options[] = {
"Don't verify additional certificates"},
{"no_intern", OPT_NO_INTERN, '-',
"Don't search certificates contained in response for signer"},
- {"badsig", OPT_BADSIG, '-',
- "Corrupt last byte of loaded OCSP response signature (for test)"},
- {"text", OPT_TEXT, '-', "Print text form of request and response"},
- {"req_text", OPT_REQ_TEXT, '-', "Print text form of request"},
- {"resp_text", OPT_RESP_TEXT, '-', "Print text form of response"},
- {"reqin", OPT_REQIN, 's', "File with the DER-encoded request"},
{"respin", OPT_RESPIN, 's', "File with the DER-encoded response"},
- {"signer", OPT_SIGNER, '<', "Certificate to sign OCSP request with"},
{"VAfile", OPT_VAFILE, '<', "Validator certificates file"},
- {"sign_other", OPT_SIGN_OTHER, '<',
- "Additional certificates to include in signed request"},
{"verify_other", OPT_VERIFY_OTHER, '<',
"Additional certificates to search for signer"},
- {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
- {"CApath", OPT_CAPATH, '<', "Trusted certificates directory"},
- {"no-CAfile", OPT_NOCAFILE, '-',
- "Do not load the default certificates file"},
- {"no-CApath", OPT_NOCAPATH, '-',
- "Do not load certificates from the default certificates directory"},
+ {"cert", OPT_CERT, '<', "Certificate to check"},
+ {"serial", OPT_SERIAL, 's', "Serial number to check"},
{"validity_period", OPT_VALIDITY_PERIOD, 'u',
"Maximum validity discrepancy in seconds"},
- {"status_age", OPT_STATUS_AGE, 'p', "Maximum status age in seconds"},
{"signkey", OPT_SIGNKEY, 's', "Private key to sign OCSP request with"},
{"reqout", OPT_REQOUT, 's', "Output file for the DER-encoded request"},
{"respout", OPT_RESPOUT, 's', "Output file for the DER-encoded response"},
- {"path", OPT_PATH, 's', "Path to use in OCSP request"},
{"issuer", OPT_ISSUER, '<', "Issuer certificate"},
- {"cert", OPT_CERT, '<', "Certificate to check"},
- {"serial", OPT_SERIAL, 's', "Serial number to check"},
- {"index", OPT_INDEX, '<', "Certificate status index file"},
- {"CA", OPT_CA, '<', "CA certificate"},
- {"nmin", OPT_NMIN, 'p', "Number of minutes before next update"},
- {"nrequest", OPT_REQUEST, 'p',
- "Number of requests to accept (default unlimited)"},
- {"ndays", OPT_NDAYS, 'p', "Number of days before next update"},
- {"rsigner", OPT_RSIGNER, '<',
- "Responder certificate to sign responses with"},
- {"rkey", OPT_RKEY, '<', "Responder key to sign responses with"},
- {"rother", OPT_ROTHER, '<', "Other certificates to include in response"},
- {"rmd", OPT_RMD, 's', "Digest Algorithm to use in signature of OCSP response"},
- {"rsigopt", OPT_RSIGOPT, 's', "OCSP response signature parameter in n:v form"},
- {"header", OPT_HEADER, 's', "key=value header to add"},
- {"", OPT_MD, '-', "Any supported digest algorithm (sha1,sha256, ... )"},
+ {"status_age", OPT_STATUS_AGE, 'p', "Maximum status age in seconds"},
+
OPT_V_OPTIONS,
+ OPT_PROV_OPTIONS,
{NULL}
};
int ocsp_main(int argc, char **argv)
{
BIO *acbio = NULL, *cbio = NULL, *derbio = NULL, *out = NULL;
- const EVP_MD *cert_id_md = NULL, *rsign_md = NULL;
+ EVP_MD *cert_id_md = NULL, *rsign_md = NULL;
STACK_OF(OPENSSL_STRING) *rsign_sigopts = NULL;
int trailing_md = 0;
CA_DB *rdb = NULL;
@@ -240,35 +229,37 @@ int ocsp_main(int argc, char **argv)
STACK_OF(X509) *issuers = NULL;
X509 *issuer = NULL, *cert = NULL;
STACK_OF(X509) *rca_cert = NULL;
+ EVP_MD *resp_certid_md = NULL;
X509 *signer = NULL, *rsigner = NULL;
X509_STORE *store = NULL;
X509_VERIFY_PARAM *vpm = NULL;
- const char *CAfile = NULL, *CApath = NULL;
- char *header, *value;
+ const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL;
+ char *header, *value, *respdigname = NULL;
char *host = NULL, *port = NULL, *path = "/", *outfile = NULL;
+#ifndef OPENSSL_NO_SOCK
+ char *opt_proxy = NULL;
+ char *opt_no_proxy = NULL;
+#endif
char *rca_filename = NULL, *reqin = NULL, *respin = NULL;
char *reqout = NULL, *respout = NULL, *ridx_filename = NULL;
char *rsignfile = NULL, *rkeyfile = NULL;
+ char *passinarg = NULL, *passin = NULL;
char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL;
char *signfile = NULL, *keyfile = NULL;
char *thost = NULL, *tport = NULL, *tpath = NULL;
- int noCAfile = 0, noCApath = 0;
+ int noCAfile = 0, noCApath = 0, noCAstore = 0;
int accept_count = -1, add_nonce = 1, noverify = 0, use_ssl = -1;
int vpmtouched = 0, badsig = 0, i, ignore_err = 0, nmin = 0, ndays = -1;
- int req_text = 0, resp_text = 0, ret = 1;
+ int req_text = 0, resp_text = 0, res, ret = 1;
int req_timeout = -1;
long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
OPTION_CHOICE o;
- reqnames = sk_OPENSSL_STRING_new_null();
- if (reqnames == NULL)
- goto end;
- ids = sk_OCSP_CERTID_new_null();
- if (ids == NULL)
+ if ((reqnames = sk_OPENSSL_STRING_new_null()) == NULL
+ || (ids = sk_OCSP_CERTID_new_null()) == NULL
+ || (vpm = X509_VERIFY_PARAM_new()) == NULL)
goto end;
- if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
- return 1;
prog = opt_init(argc, argv, ocsp_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -295,8 +286,10 @@ int ocsp_main(int argc, char **argv)
OPENSSL_free(tport);
OPENSSL_free(tpath);
thost = tport = tpath = NULL;
- if (!OCSP_parse_url(opt_arg(), &host, &port, &path, &use_ssl)) {
- BIO_printf(bio_err, "%s Error parsing URL\n", prog);
+ if (!OSSL_HTTP_parse_url(opt_arg(), &use_ssl, NULL /* userinfo */,
+ &host, &port, NULL /* port_num */,
+ &path, NULL /* qry */, NULL /* frag */)) {
+ BIO_printf(bio_err, "%s Error parsing -url argument\n", prog);
goto end;
}
thost = host;
@@ -309,6 +302,17 @@ int ocsp_main(int argc, char **argv)
case OPT_PORT:
port = opt_arg();
break;
+ case OPT_PATH:
+ path = opt_arg();
+ break;
+#ifndef OPENSSL_NO_SOCK
+ case OPT_PROXY:
+ opt_proxy = opt_arg();
+ break;
+ case OPT_NO_PROXY:
+ opt_no_proxy = opt_arg();
+ break;
+#endif
case OPT_IGNORE_ERR:
ignore_err = 1;
break;
@@ -388,12 +392,18 @@ int ocsp_main(int argc, char **argv)
case OPT_CAPATH:
CApath = opt_arg();
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
case OPT_NOCAPATH:
noCApath = 1;
break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
case OPT_V_CASES:
if (!opt_verify(o, vpm))
goto end;
@@ -414,26 +424,24 @@ int ocsp_main(int argc, char **argv)
case OPT_RESPOUT:
respout = opt_arg();
break;
- case OPT_PATH:
- path = opt_arg();
- break;
case OPT_ISSUER:
- issuer = load_cert(opt_arg(), FORMAT_PEM, "issuer certificate");
+ issuer = load_cert(opt_arg(), FORMAT_UNDEF, "issuer certificate");
if (issuer == NULL)
goto end;
if (issuers == NULL) {
if ((issuers = sk_X509_new_null()) == NULL)
goto end;
}
- sk_X509_push(issuers, issuer);
+ if (!sk_X509_push(issuers, issuer))
+ goto end;
break;
case OPT_CERT:
X509_free(cert);
- cert = load_cert(opt_arg(), FORMAT_PEM, "certificate");
+ cert = load_cert(opt_arg(), FORMAT_UNDEF, "certificate");
if (cert == NULL)
goto end;
if (cert_id_md == NULL)
- cert_id_md = EVP_sha1();
+ cert_id_md = (EVP_MD *)EVP_sha1();
if (!add_ocsp_cert(&req, cert, cert_id_md, issuer, ids))
goto end;
if (!sk_OPENSSL_STRING_push(reqnames, opt_arg()))
@@ -442,7 +450,7 @@ int ocsp_main(int argc, char **argv)
break;
case OPT_SERIAL:
if (cert_id_md == NULL)
- cert_id_md = EVP_sha1();
+ cert_id_md = (EVP_MD *)EVP_sha1();
if (!add_ocsp_serial(&req, opt_arg(), cert_id_md, issuer, ids))
goto end;
if (!sk_OPENSSL_STRING_push(reqnames, opt_arg()))
@@ -456,12 +464,12 @@ int ocsp_main(int argc, char **argv)
rca_filename = opt_arg();
break;
case OPT_NMIN:
- opt_int(opt_arg(), &nmin);
+ nmin = opt_int_arg();
if (ndays == -1)
ndays = 0;
break;
case OPT_REQUEST:
- opt_int(opt_arg(), &accept_count);
+ accept_count = opt_int_arg();
break;
case OPT_NDAYS:
ndays = atoi(opt_arg());
@@ -472,17 +480,20 @@ int ocsp_main(int argc, char **argv)
case OPT_RKEY:
rkeyfile = opt_arg();
break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
case OPT_ROTHER:
rcertfile = opt_arg();
break;
case OPT_RMD: /* Response MessageDigest */
- if (!opt_md(opt_arg(), &rsign_md))
- goto end;
+ respdigname = opt_arg();
break;
case OPT_RSIGOPT:
if (rsign_sigopts == NULL)
rsign_sigopts = sk_OPENSSL_STRING_new_null();
- if (rsign_sigopts == NULL || !sk_OPENSSL_STRING_push(rsign_sigopts, opt_arg()))
+ if (rsign_sigopts == NULL
+ || !sk_OPENSSL_STRING_push(rsign_sigopts, opt_arg()))
goto end;
break;
case OPT_HEADER:
@@ -496,6 +507,10 @@ int ocsp_main(int argc, char **argv)
if (!X509V3_add_value(header, value, &headers))
goto end;
break;
+ case OPT_RCID:
+ if (!opt_md(opt_arg(), &resp_certid_md))
+ goto opthelp;
+ break;
case OPT_MD:
if (trailing_md) {
BIO_printf(bio_err,
@@ -508,20 +523,32 @@ int ocsp_main(int argc, char **argv)
trailing_md = 1;
break;
case OPT_MULTI:
-#ifdef OCSP_DAEMON
+#ifdef HTTP_DAEMON
multi = atoi(opt_arg());
#endif
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
if (trailing_md) {
BIO_printf(bio_err, "%s: Digest must be before -cert or -serial\n",
prog);
goto opthelp;
}
- argc = opt_num_rest();
- if (argc != 0)
- goto opthelp;
+
+ if (respdigname != NULL) {
+ if (!opt_md(respdigname, &rsign_md))
+ goto end;
+ }
/* Have we anything to do? */
if (req == NULL && reqin == NULL
@@ -548,28 +575,36 @@ int ocsp_main(int argc, char **argv)
}
if (req == NULL && port != NULL) {
- acbio = init_responder(port);
+#ifndef OPENSSL_NO_SOCK
+ acbio = http_server_init_bio(prog, port);
if (acbio == NULL)
goto end;
+#else
+ BIO_printf(bio_err, "Cannot act as server - sockets not supported\n");
+ goto end;
+#endif
}
if (rsignfile != NULL) {
if (rkeyfile == NULL)
rkeyfile = rsignfile;
- rsigner = load_cert(rsignfile, FORMAT_PEM, "responder certificate");
+ rsigner = load_cert(rsignfile, FORMAT_UNDEF, "responder certificate");
if (rsigner == NULL) {
BIO_printf(bio_err, "Error loading responder certificate\n");
goto end;
}
- if (!load_certs(rca_filename, &rca_cert, FORMAT_PEM,
- NULL, "CA certificate"))
+ if (!load_certs(rca_filename, 0, &rca_cert, NULL, "CA certificates"))
goto end;
if (rcertfile != NULL) {
- if (!load_certs(rcertfile, &rother, FORMAT_PEM, NULL,
+ if (!load_certs(rcertfile, 0, &rother, NULL,
"responder other certificates"))
goto end;
}
- rkey = load_key(rkeyfile, FORMAT_PEM, 0, NULL, NULL,
+ if (!app_passwd(passinarg, NULL, &passin, NULL)) {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+ rkey = load_key(rkeyfile, FORMAT_UNDEF, 0, passin, NULL,
"responder private key");
if (rkey == NULL)
goto end;
@@ -585,25 +620,28 @@ int ocsp_main(int argc, char **argv)
if (ridx_filename != NULL) {
rdb = load_index(ridx_filename, NULL);
if (rdb == NULL || index_index(rdb) <= 0) {
+ BIO_printf(bio_err,
+ "Problem with index file: %s (could not load/parse file)\n",
+ ridx_filename);
ret = 1;
goto end;
}
}
-#ifdef OCSP_DAEMON
+#ifdef HTTP_DAEMON
if (multi && acbio != NULL)
- spawn_loop();
+ spawn_loop(prog);
if (acbio != NULL && req_timeout > 0)
signal(SIGALRM, socket_timeout);
#endif
if (acbio != NULL)
- log_message(LOG_INFO, "waiting for OCSP client connections...");
+ log_message(prog, LOG_INFO, "waiting for OCSP client connections...");
redo_accept:
if (acbio != NULL) {
-#ifdef OCSP_DAEMON
+#ifdef HTTP_DAEMON
if (index_changed(rdb)) {
CA_DB *newrdb = load_index(ridx_filename, NULL);
@@ -612,21 +650,24 @@ redo_accept:
rdb = newrdb;
} else {
free_index(newrdb);
- log_message(LOG_ERR, "error reloading updated index: %s",
+ log_message(prog, LOG_ERR, "error reloading updated index: %s",
ridx_filename);
}
}
#endif
req = NULL;
- if (!do_responder(&req, &cbio, acbio, req_timeout))
+ res = do_responder(&req, &cbio, acbio, port, req_timeout);
+ if (res == 0)
goto redo_accept;
if (req == NULL) {
- resp =
- OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST,
- NULL);
- send_ocsp_response(cbio, resp);
+ if (res == 1) {
+ resp =
+ OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST,
+ NULL);
+ send_ocsp_response(cbio, resp);
+ }
goto done_resp;
}
}
@@ -646,23 +687,23 @@ redo_accept:
if (signfile != NULL) {
if (keyfile == NULL)
keyfile = signfile;
- signer = load_cert(signfile, FORMAT_PEM, "signer certificate");
+ signer = load_cert(signfile, FORMAT_UNDEF, "signer certificate");
if (signer == NULL) {
BIO_printf(bio_err, "Error loading signer certificate\n");
goto end;
}
if (sign_certfile != NULL) {
- if (!load_certs(sign_certfile, &sign_other, FORMAT_PEM, NULL,
+ if (!load_certs(sign_certfile, 0, &sign_other, NULL,
"signer certificates"))
goto end;
}
- key = load_key(keyfile, FORMAT_PEM, 0, NULL, NULL,
+ key = load_key(keyfile, FORMAT_UNDEF, 0, NULL, NULL,
"signer private key");
if (key == NULL)
goto end;
- if (!OCSP_request_sign
- (req, signer, key, NULL, sign_other, sign_flags)) {
+ if (!OCSP_request_sign(req, signer, key, NULL,
+ sign_other, sign_flags)) {
BIO_printf(bio_err, "Error signing OCSP request\n");
goto end;
}
@@ -681,18 +722,21 @@ redo_accept:
if (rdb != NULL) {
make_ocsp_response(bio_err, &resp, req, rdb, rca_cert, rsigner, rkey,
- rsign_md, rsign_sigopts, rother, rflags, nmin, ndays, badsig);
+ rsign_md, rsign_sigopts, rother, rflags, nmin, ndays,
+ badsig, resp_certid_md);
+ if (resp == NULL)
+ goto end;
if (cbio != NULL)
send_ocsp_response(cbio, resp);
} else if (host != NULL) {
#ifndef OPENSSL_NO_SOCK
- resp = process_responder(req, host, path,
- port, use_ssl, headers, req_timeout);
+ resp = process_responder(req, host, port, path, opt_proxy, opt_no_proxy,
+ use_ssl, headers, req_timeout);
if (resp == NULL)
goto end;
#else
BIO_printf(bio_err,
- "Error creating connect BIO - sockets not supported.\n");
+ "Error creating connect BIO - sockets not supported\n");
goto end;
#endif
} else if (respin != NULL) {
@@ -752,15 +796,16 @@ redo_accept:
}
if (store == NULL) {
- store = setup_verify(CAfile, CApath, noCAfile, noCApath);
+ store = setup_verify(CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore);
if (!store)
goto end;
}
if (vpmtouched)
X509_STORE_set1_param(store, vpm);
if (verify_certfile != NULL) {
- if (!load_certs(verify_certfile, &verify_other, FORMAT_PEM, NULL,
- "validator certificate"))
+ if (!load_certs(verify_certfile, 0, &verify_other, NULL,
+ "validator certificates"))
goto end;
}
@@ -798,7 +843,8 @@ redo_accept:
}
}
- print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage);
+ if (!print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage))
+ ret = 1;
end:
ERR_print_errors(bio_err);
@@ -808,6 +854,9 @@ redo_accept:
sk_OPENSSL_STRING_free(rsign_sigopts);
EVP_PKEY_free(key);
EVP_PKEY_free(rkey);
+ EVP_MD_free(cert_id_md);
+ EVP_MD_free(rsign_md);
+ EVP_MD_free(resp_certid_md);
X509_free(cert);
sk_X509_pop_free(issuers, X509_free);
X509_free(rsigner);
@@ -831,41 +880,7 @@ redo_accept:
return ret;
}
-static void
-log_message(int level, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
-#ifdef OCSP_DAEMON
- if (multi) {
- char buf[1024];
- if (vsnprintf(buf, sizeof(buf), fmt, ap) > 0) {
- syslog(level, "%s", buf);
- }
- if (level >= LOG_ERR)
- ERR_print_errors_cb(print_syslog, &level);
- }
-#endif
- if (!multi) {
- BIO_printf(bio_err, "%s: ", prog);
- BIO_vprintf(bio_err, fmt, ap);
- BIO_printf(bio_err, "\n");
- }
- va_end(ap);
-}
-
-#ifdef OCSP_DAEMON
-
-static int print_syslog(const char *str, size_t len, void *levPtr)
-{
- int level = *(int *)levPtr;
- int ilen = (len > MAXERRLEN) ? MAXERRLEN : len;
-
- syslog(level, "%.*s", ilen, str);
-
- return ilen;
-}
+#ifdef HTTP_DAEMON
static int index_changed(CA_DB *rdb)
{
@@ -883,131 +898,6 @@ static int index_changed(CA_DB *rdb)
return 0;
}
-static void killall(int ret, pid_t *kidpids)
-{
- int i;
-
- for (i = 0; i < multi; ++i)
- if (kidpids[i] != 0)
- (void)kill(kidpids[i], SIGTERM);
- OPENSSL_free(kidpids);
- sleep(1);
- exit(ret);
-}
-
-static int termsig = 0;
-
-static void noteterm (int sig)
-{
- termsig = sig;
-}
-
-/*
- * Loop spawning up to `multi` child processes, only child processes return
- * from this function. The parent process loops until receiving a termination
- * signal, kills extant children and exits without returning.
- */
-static void spawn_loop(void)
-{
- pid_t *kidpids = NULL;
- int status;
- int procs = 0;
- int i;
-
- openlog(prog, LOG_PID, LOG_DAEMON);
-
- if (setpgid(0, 0)) {
- syslog(LOG_ERR, "fatal: error detaching from parent process group: %s",
- strerror(errno));
- exit(1);
- }
- kidpids = app_malloc(multi * sizeof(*kidpids), "child PID array");
- for (i = 0; i < multi; ++i)
- kidpids[i] = 0;
-
- signal(SIGINT, noteterm);
- signal(SIGTERM, noteterm);
-
- while (termsig == 0) {
- pid_t fpid;
-
- /*
- * Wait for a child to replace when we're at the limit.
- * Slow down if a child exited abnormally or waitpid() < 0
- */
- while (termsig == 0 && procs >= multi) {
- if ((fpid = waitpid(-1, &status, 0)) > 0) {
- for (i = 0; i < procs; ++i) {
- if (kidpids[i] == fpid) {
- kidpids[i] = 0;
- --procs;
- break;
- }
- }
- if (i >= multi) {
- syslog(LOG_ERR, "fatal: internal error: "
- "no matching child slot for pid: %ld",
- (long) fpid);
- killall(1, kidpids);
- }
- if (status != 0) {
- if (WIFEXITED(status))
- syslog(LOG_WARNING, "child process: %ld, exit status: %d",
- (long)fpid, WEXITSTATUS(status));
- else if (WIFSIGNALED(status))
- syslog(LOG_WARNING, "child process: %ld, term signal %d%s",
- (long)fpid, WTERMSIG(status),
-#ifdef WCOREDUMP
- WCOREDUMP(status) ? " (core dumped)" :
-#endif
- "");
- sleep(1);
- }
- break;
- } else if (errno != EINTR) {
- syslog(LOG_ERR, "fatal: waitpid(): %s", strerror(errno));
- killall(1, kidpids);
- }
- }
- if (termsig)
- break;
-
- switch(fpid = fork()) {
- case -1: /* error */
- /* System critically low on memory, pause and try again later */
- sleep(30);
- break;
- case 0: /* child */
- OPENSSL_free(kidpids);
- signal(SIGINT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
- if (termsig)
- _exit(0);
- if (RAND_poll() <= 0) {
- syslog(LOG_ERR, "fatal: RAND_poll() failed");
- _exit(1);
- }
- return;
- default: /* parent */
- for (i = 0; i < multi; ++i) {
- if (kidpids[i] == 0) {
- kidpids[i] = fpid;
- procs++;
- break;
- }
- }
- if (i >= multi) {
- syslog(LOG_ERR, "fatal: internal error: no free child slots");
- killall(1, kidpids);
- }
- break;
- }
- }
-
- /* The loop above can only break on termsig */
- syslog(LOG_INFO, "terminating on signal: %d", termsig);
- killall(0, kidpids);
-}
#endif
static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert,
@@ -1041,7 +931,7 @@ static int add_ocsp_serial(OCSP_REQUEST **req, char *serial,
STACK_OF(OCSP_CERTID) *ids)
{
OCSP_CERTID *id;
- X509_NAME *iname;
+ const X509_NAME *iname;
ASN1_BIT_STRING *ikey;
ASN1_INTEGER *sno;
@@ -1073,7 +963,7 @@ static int add_ocsp_serial(OCSP_REQUEST **req, char *serial,
return 0;
}
-static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
+static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
STACK_OF(OPENSSL_STRING) *names,
STACK_OF(OCSP_CERTID) *ids, long nsec,
long maxage)
@@ -1082,10 +972,13 @@ static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
const char *name;
int i, status, reason;
ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
+ int ret = 1;
- if (bs == NULL || req == NULL || !sk_OPENSSL_STRING_num(names)
- || !sk_OCSP_CERTID_num(ids))
- return;
+ if (req == NULL || !sk_OPENSSL_STRING_num(names))
+ return 1;
+
+ if (bs == NULL || !sk_OCSP_CERTID_num(ids))
+ return 0;
for (i = 0; i < sk_OCSP_CERTID_num(ids); i++) {
id = sk_OCSP_CERTID_value(ids, i);
@@ -1095,6 +988,7 @@ static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
if (!OCSP_resp_find_status(bs, id, &status, &reason,
&rev, &thisupd, &nextupd)) {
BIO_puts(out, "ERROR: No Status found.\n");
+ ret = 0;
continue;
}
@@ -1128,6 +1022,7 @@ static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
ASN1_GENERALIZEDTIME_print(out, rev);
BIO_puts(out, "\n");
}
+ return ret;
}
static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req,
@@ -1135,7 +1030,8 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req
EVP_PKEY *rkey, const EVP_MD *rmd,
STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(X509) *rother, unsigned long flags,
- int nmin, int ndays, int badsig)
+ int nmin, int ndays, int badsig,
+ const EVP_MD *resp_md)
{
ASN1_TIME *thisupd = NULL, *nextupd = NULL;
OCSP_CERTID *cid;
@@ -1166,6 +1062,8 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req
int found = 0;
ASN1_OBJECT *cert_id_md_oid;
const EVP_MD *cert_id_md;
+ OCSP_CERTID *cid_resp_md = NULL;
+
one = OCSP_request_onereq_get0(req, i);
cid = OCSP_onereq_get0_id(one);
@@ -1181,11 +1079,18 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req
X509 *ca_cert = sk_X509_value(ca, jj);
OCSP_CERTID *ca_id = OCSP_cert_to_id(cert_id_md, NULL, ca_cert);
- if (OCSP_id_issuer_cmp(ca_id, cid) == 0)
+ if (OCSP_id_issuer_cmp(ca_id, cid) == 0) {
found = 1;
-
+ if (resp_md != NULL)
+ cid_resp_md = OCSP_cert_to_id(resp_md, NULL, ca_cert);
+ }
OCSP_CERTID_free(ca_id);
}
+ OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid);
+ inf = lookup_serial(db, serial);
+
+ /* at this point, we can have cid be an alias of cid_resp_md */
+ cid = (cid_resp_md != NULL) ? cid_resp_md : cid;
if (!found) {
OCSP_basic_add1_status(bs, cid,
@@ -1193,8 +1098,6 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req
0, NULL, thisupd, nextupd);
continue;
}
- OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid);
- inf = lookup_serial(db, serial);
if (inf == NULL) {
OCSP_basic_add1_status(bs, cid,
V_OCSP_CERTSTATUS_UNKNOWN,
@@ -1209,10 +1112,16 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req
ASN1_GENERALIZEDTIME *invtm = NULL;
OCSP_SINGLERESP *single;
int reason = -1;
+
unpack_revinfo(&revtm, &reason, &inst, &invtm, inf[DB_rev_date]);
single = OCSP_basic_add1_status(bs, cid,
V_OCSP_CERTSTATUS_REVOKED,
reason, revtm, thisupd, nextupd);
+ if (single == NULL) {
+ *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR,
+ NULL);
+ goto end;
+ }
if (invtm != NULL)
OCSP_SINGLERESP_add1_ext_i2d(single, NID_invalidity_date,
invtm, 0, 0);
@@ -1224,6 +1133,7 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req
ASN1_TIME_free(revtm);
ASN1_GENERALIZEDTIME_free(invtm);
}
+ OCSP_CERTID_free(cid_resp_md);
}
OCSP_copy_nonce(bs, req);
@@ -1273,10 +1183,12 @@ static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser)
bn = ASN1_INTEGER_to_BN(ser, NULL);
OPENSSL_assert(bn); /* FIXME: should report an error at this
* point and abort */
- if (BN_is_zero(bn))
+ if (BN_is_zero(bn)) {
itmp = OPENSSL_strdup("00");
- else
+ OPENSSL_assert(itmp);
+ } else {
itmp = BN_bn2hex(bn);
+ }
row[DB_serial] = itmp;
BN_free(bn);
rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
@@ -1284,339 +1196,66 @@ static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser)
return rrow;
}
-/* Quick and dirty OCSP server: read in and parse input request */
-
-static BIO *init_responder(const char *port)
-{
-#ifdef OPENSSL_NO_SOCK
- BIO_printf(bio_err,
- "Error setting up accept BIO - sockets not supported.\n");
- return NULL;
-#else
- BIO *acbio = NULL, *bufbio = NULL;
-
- bufbio = BIO_new(BIO_f_buffer());
- if (bufbio == NULL)
- goto err;
- acbio = BIO_new(BIO_s_accept());
- if (acbio == NULL
- || BIO_set_bind_mode(acbio, BIO_BIND_REUSEADDR) < 0
- || BIO_set_accept_port(acbio, port) < 0) {
- log_message(LOG_ERR, "Error setting up accept BIO");
- goto err;
- }
-
- BIO_set_accept_bios(acbio, bufbio);
- bufbio = NULL;
- if (BIO_do_accept(acbio) <= 0) {
- log_message(LOG_ERR, "Error starting accept");
- goto err;
- }
-
- return acbio;
-
- err:
- BIO_free_all(acbio);
- BIO_free(bufbio);
- return NULL;
-#endif
-}
-
-#ifndef OPENSSL_NO_SOCK
-/*
- * Decode %xx URL-decoding in-place. Ignores mal-formed sequences.
- */
-static int urldecode(char *p)
-{
- unsigned char *out = (unsigned char *)p;
- unsigned char *save = out;
-
- for (; *p; p++) {
- if (*p != '%')
- *out++ = *p;
- else if (isxdigit(_UC(p[1])) && isxdigit(_UC(p[2]))) {
- /* Don't check, can't fail because of ixdigit() call. */
- *out++ = (OPENSSL_hexchar2int(p[1]) << 4)
- | OPENSSL_hexchar2int(p[2]);
- p += 2;
- }
- else
- return -1;
- }
- *out = '\0';
- return (int)(out - save);
-}
-#endif
-
-#ifdef OCSP_DAEMON
-static void socket_timeout(int signum)
-{
- if (acfd != (int)INVALID_SOCKET)
- (void)shutdown(acfd, SHUT_RD);
-}
-#endif
-
static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio,
- int timeout)
+ const char *port, int timeout)
{
-#ifdef OPENSSL_NO_SOCK
- return 0;
+#ifndef OPENSSL_NO_SOCK
+ return http_server_get_asn1_req(ASN1_ITEM_rptr(OCSP_REQUEST),
+ (ASN1_VALUE **)preq, NULL, pcbio, acbio,
+ NULL /* found_keep_alive */,
+ prog, port, 1 /* accept_get */, timeout);
#else
- int len;
- OCSP_REQUEST *req = NULL;
- char inbuf[2048], reqbuf[2048];
- char *p, *q;
- BIO *cbio = NULL, *getbio = NULL, *b64 = NULL;
- const char *client;
-
+ BIO_printf(bio_err,
+ "Error getting OCSP request - sockets not supported\n");
*preq = NULL;
-
- /* Connection loss before accept() is routine, ignore silently */
- if (BIO_do_accept(acbio) <= 0)
- return 0;
-
- cbio = BIO_pop(acbio);
- *pcbio = cbio;
- client = BIO_get_peer_name(cbio);
-
-# ifdef OCSP_DAEMON
- if (timeout > 0) {
- (void) BIO_get_fd(cbio, &acfd);
- alarm(timeout);
- }
-# endif
-
- /* Read the request line. */
- len = BIO_gets(cbio, reqbuf, sizeof(reqbuf));
- if (len <= 0)
- goto out;
-
- if (strncmp(reqbuf, "GET ", 4) == 0) {
- /* Expecting GET {sp} /URL {sp} HTTP/1.x */
- for (p = reqbuf + 4; *p == ' '; ++p)
- continue;
- if (*p != '/') {
- log_message(LOG_INFO, "Invalid request -- bad URL: %s", client);
- goto out;
- }
- p++;
-
- /* Splice off the HTTP version identifier. */
- for (q = p; *q; q++)
- if (*q == ' ')
- break;
- if (strncmp(q, " HTTP/1.", 8) != 0) {
- log_message(LOG_INFO,
- "Invalid request -- bad HTTP version: %s", client);
- goto out;
- }
- *q = '\0';
-
- /*
- * Skip "GET / HTTP..." requests often used by load-balancers. Note:
- * 'p' was incremented above to point to the first byte *after* the
- * leading slash, so with 'GET / ' it is now an empty string.
- */
- if (p[0] == '\0')
- goto out;
-
- len = urldecode(p);
- if (len <= 0) {
- log_message(LOG_INFO,
- "Invalid request -- bad URL encoding: %s", client);
- goto out;
- }
- if ((getbio = BIO_new_mem_buf(p, len)) == NULL
- || (b64 = BIO_new(BIO_f_base64())) == NULL) {
- log_message(LOG_ERR, "Could not allocate base64 bio: %s", client);
- goto out;
- }
- BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
- getbio = BIO_push(b64, getbio);
- } else if (strncmp(reqbuf, "POST ", 5) != 0) {
- log_message(LOG_INFO, "Invalid request -- bad HTTP verb: %s", client);
- goto out;
- }
-
- /* Read and skip past the headers. */
- for (;;) {
- len = BIO_gets(cbio, inbuf, sizeof(inbuf));
- if (len <= 0)
- goto out;
- if ((inbuf[0] == '\r') || (inbuf[0] == '\n'))
- break;
- }
-
-# ifdef OCSP_DAEMON
- /* Clear alarm before we close the client socket */
- alarm(0);
- timeout = 0;
-# endif
-
- /* Try to read OCSP request */
- if (getbio != NULL) {
- req = d2i_OCSP_REQUEST_bio(getbio, NULL);
- BIO_free_all(getbio);
- } else {
- req = d2i_OCSP_REQUEST_bio(cbio, NULL);
- }
-
- if (req == NULL)
- log_message(LOG_ERR, "Error parsing OCSP request");
-
- *preq = req;
-
-out:
-# ifdef OCSP_DAEMON
- if (timeout > 0)
- alarm(0);
- acfd = (int)INVALID_SOCKET;
-# endif
- return 1;
+ return 0;
#endif
}
-static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp)
+static int send_ocsp_response(BIO *cbio, const OCSP_RESPONSE *resp)
{
- char http_resp[] =
- "HTTP/1.0 200 OK\r\nContent-type: application/ocsp-response\r\n"
- "Content-Length: %d\r\n\r\n";
- if (cbio == NULL)
- return 0;
- BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL));
- i2d_OCSP_RESPONSE_bio(cbio, resp);
- (void)BIO_flush(cbio);
- return 1;
-}
-
#ifndef OPENSSL_NO_SOCK
-static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host,
- const char *path,
- const STACK_OF(CONF_VALUE) *headers,
- OCSP_REQUEST *req, int req_timeout)
-{
- int fd;
- int rv;
- int i;
- int add_host = 1;
- OCSP_REQ_CTX *ctx = NULL;
- OCSP_RESPONSE *rsp = NULL;
- fd_set confds;
- struct timeval tv;
-
- if (req_timeout != -1)
- BIO_set_nbio(cbio, 1);
-
- rv = BIO_do_connect(cbio);
-
- if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio))) {
- BIO_puts(bio_err, "Error connecting BIO\n");
- return NULL;
- }
-
- if (BIO_get_fd(cbio, &fd) < 0) {
- BIO_puts(bio_err, "Can't get connection fd\n");
- goto err;
- }
-
- if (req_timeout != -1 && rv <= 0) {
- FD_ZERO(&confds);
- openssl_fdset(fd, &confds);
- tv.tv_usec = 0;
- tv.tv_sec = req_timeout;
- rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
- if (rv == 0) {
- BIO_puts(bio_err, "Timeout on connect\n");
- return NULL;
- }
- }
-
- ctx = OCSP_sendreq_new(cbio, path, NULL, -1);
- if (ctx == NULL)
- return NULL;
-
- for (i = 0; i < sk_CONF_VALUE_num(headers); i++) {
- CONF_VALUE *hdr = sk_CONF_VALUE_value(headers, i);
- if (add_host == 1 && strcasecmp("host", hdr->name) == 0)
- add_host = 0;
- if (!OCSP_REQ_CTX_add1_header(ctx, hdr->name, hdr->value))
- goto err;
- }
-
- if (add_host == 1 && OCSP_REQ_CTX_add1_header(ctx, "Host", host) == 0)
- goto err;
-
- if (!OCSP_REQ_CTX_set1_req(ctx, req))
- goto err;
-
- for (;;) {
- rv = OCSP_sendreq_nbio(&rsp, ctx);
- if (rv != -1)
- break;
- if (req_timeout == -1)
- continue;
- FD_ZERO(&confds);
- openssl_fdset(fd, &confds);
- tv.tv_usec = 0;
- tv.tv_sec = req_timeout;
- if (BIO_should_read(cbio)) {
- rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv);
- } else if (BIO_should_write(cbio)) {
- rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
- } else {
- BIO_puts(bio_err, "Unexpected retry condition\n");
- goto err;
- }
- if (rv == 0) {
- BIO_puts(bio_err, "Timeout on request\n");
- break;
- }
- if (rv == -1) {
- BIO_puts(bio_err, "Select error\n");
- break;
- }
-
- }
- err:
- OCSP_REQ_CTX_free(ctx);
-
- return rsp;
+ return http_server_send_asn1_resp(cbio,
+ 0 /* no keep-alive */,
+ "application/ocsp-response",
+ ASN1_ITEM_rptr(OCSP_RESPONSE),
+ (const ASN1_VALUE *)resp);
+#else
+ BIO_printf(bio_err,
+ "Error sending OCSP response - sockets not supported\n");
+ return 0;
+#endif
}
-OCSP_RESPONSE *process_responder(OCSP_REQUEST *req,
- const char *host, const char *path,
- const char *port, int use_ssl,
- STACK_OF(CONF_VALUE) *headers,
+#ifndef OPENSSL_NO_SOCK
+OCSP_RESPONSE *process_responder(OCSP_REQUEST *req, const char *host,
+ const char *port, const char *path,
+ const char *proxy, const char *no_proxy,
+ int use_ssl, STACK_OF(CONF_VALUE) *headers,
int req_timeout)
{
- BIO *cbio = NULL;
SSL_CTX *ctx = NULL;
OCSP_RESPONSE *resp = NULL;
- cbio = BIO_new_connect(host);
- if (cbio == NULL) {
- BIO_printf(bio_err, "Error creating connect BIO\n");
- goto end;
- }
- if (port != NULL)
- BIO_set_conn_port(cbio, port);
if (use_ssl == 1) {
- BIO *sbio;
ctx = SSL_CTX_new(TLS_client_method());
if (ctx == NULL) {
BIO_printf(bio_err, "Error creating SSL context.\n");
goto end;
}
- SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
- sbio = BIO_new_ssl(ctx, 1);
- cbio = BIO_push(sbio, cbio);
}
- resp = query_responder(cbio, host, path, headers, req, req_timeout);
+ resp = (OCSP_RESPONSE *)
+ app_http_post_asn1(host, port, path, proxy, no_proxy,
+ ctx, headers, "application/ocsp-request",
+ (ASN1_VALUE *)req, ASN1_ITEM_rptr(OCSP_REQUEST),
+ "application/ocsp-response",
+ req_timeout, ASN1_ITEM_rptr(OCSP_RESPONSE));
+
if (resp == NULL)
BIO_printf(bio_err, "Error querying OCSP responder\n");
+
end:
- BIO_free_all(cbio);
SSL_CTX_free(ctx);
return resp;
}
diff --git a/apps/openssl.c b/apps/openssl.c
index f35d57f2648c..a3056c799f85 100644
--- a/apps/openssl.c
+++ b/apps/openssl.c
@@ -1,18 +1,18 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <internal/cryptlib.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/bio.h>
#include <openssl/crypto.h>
+#include <openssl/trace.h>
#include <openssl/lhash.h>
#include <openssl/conf.h>
#include <openssl/x509.h>
@@ -27,20 +27,8 @@
# include <unixio.h>
#endif
#include "apps.h"
-#define INCLUDE_FUNCTION_TABLE
#include "progs.h"
-/* Structure to hold the number of columns to be displayed and the
- * field width used to display them.
- */
-typedef struct {
- int columns;
- int width;
-} DISPLAY_COLUMNS;
-
-/* Special sentinel to exit the program. */
-#define EXIT_THE_PROGRAM (-1)
-
/*
* The LHASH callbacks ("hash" & "cmp") have been replaced by functions with
* the base prototypes (we cast each variable inside the function to the
@@ -49,32 +37,27 @@ typedef struct {
*/
static LHASH_OF(FUNCTION) *prog_init(void);
static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]);
-static void list_pkey(void);
-static void list_pkey_meth(void);
-static void list_type(FUNC_TYPE ft, int one);
-static void list_disabled(void);
char *default_config_file = NULL;
BIO *bio_in = NULL;
BIO *bio_out = NULL;
BIO *bio_err = NULL;
-static void calculate_columns(DISPLAY_COLUMNS *dc)
+static void warn_deprecated(const FUNCTION *fp)
{
- FUNCTION *f;
- int len, maxlen = 0;
-
- for (f = functions; f->name != NULL; ++f)
- if (f->type == FT_general || f->type == FT_md || f->type == FT_cipher)
- if ((len = strlen(f->name)) > maxlen)
- maxlen = len;
-
- dc->width = maxlen + 2;
- dc->columns = (80 - 1) / dc->width;
+ if (fp->deprecated_version != NULL)
+ BIO_printf(bio_err, "The command %s was deprecated in version %s.",
+ fp->name, fp->deprecated_version);
+ else
+ BIO_printf(bio_err, "The command %s is deprecated.", fp->name);
+ if (strcmp(fp->deprecated_alternative, DEPRECATED_NO_ALTERNATIVE) != 0)
+ BIO_printf(bio_err, " Use '%s' instead.", fp->deprecated_alternative);
+ BIO_printf(bio_err, "\n");
}
static int apps_startup(void)
{
+ const char *use_libctx = NULL;
#ifdef SIGPIPE
signal(SIGPIPE, SIG_IGN);
#endif
@@ -84,53 +67,186 @@ static int apps_startup(void)
| OPENSSL_INIT_LOAD_CONFIG, NULL))
return 0;
- setup_ui_method();
+ (void)setup_ui_method();
+ (void)setup_engine_loader();
+
+ /*
+ * NOTE: This is an undocumented feature required for testing only.
+ * There are no guarantees that it will exist in future builds.
+ */
+ use_libctx = getenv("OPENSSL_TEST_LIBCTX");
+ if (use_libctx != NULL) {
+ /* Set this to "1" to create a global libctx */
+ if (strcmp(use_libctx, "1") == 0) {
+ if (app_create_libctx() == NULL)
+ return 0;
+ }
+ }
return 1;
}
static void apps_shutdown(void)
{
+ app_providers_cleanup();
+ OSSL_LIB_CTX_free(app_get0_libctx());
+ destroy_engine_loader();
destroy_ui_method();
- destroy_prefix_method();
}
-static char *make_config_name(void)
+
+#ifndef OPENSSL_NO_TRACE
+typedef struct tracedata_st {
+ BIO *bio;
+ unsigned int ingroup:1;
+} tracedata;
+
+static size_t internal_trace_cb(const char *buf, size_t cnt,
+ int category, int cmd, void *vdata)
{
- const char *t;
- size_t len;
- char *p;
-
- if ((t = getenv("OPENSSL_CONF")) != NULL)
- return OPENSSL_strdup(t);
-
- t = X509_get_default_cert_area();
- len = strlen(t) + 1 + strlen(OPENSSL_CONF) + 1;
- p = app_malloc(len, "config filename buffer");
- strcpy(p, t);
-#ifndef OPENSSL_SYS_VMS
- strcat(p, "/");
-#endif
- strcat(p, OPENSSL_CONF);
+ int ret = 0;
+ tracedata *trace_data = vdata;
+ char buffer[256], *hex;
+ CRYPTO_THREAD_ID tid;
+
+ switch (cmd) {
+ case OSSL_TRACE_CTRL_BEGIN:
+ if (trace_data->ingroup) {
+ BIO_printf(bio_err, "ERROR: tracing already started\n");
+ return 0;
+ }
+ trace_data->ingroup = 1;
+
+ tid = CRYPTO_THREAD_get_current_id();
+ hex = OPENSSL_buf2hexstr((const unsigned char *)&tid, sizeof(tid));
+ BIO_snprintf(buffer, sizeof(buffer), "TRACE[%s]:%s: ",
+ hex == NULL ? "<null>" : hex,
+ OSSL_trace_get_category_name(category));
+ OPENSSL_free(hex);
+ BIO_set_prefix(trace_data->bio, buffer);
+ break;
+ case OSSL_TRACE_CTRL_WRITE:
+ if (!trace_data->ingroup) {
+ BIO_printf(bio_err, "ERROR: writing when tracing not started\n");
+ return 0;
+ }
+
+ ret = BIO_write(trace_data->bio, buf, cnt);
+ break;
+ case OSSL_TRACE_CTRL_END:
+ if (!trace_data->ingroup) {
+ BIO_printf(bio_err, "ERROR: finishing when tracing not started\n");
+ return 0;
+ }
+ trace_data->ingroup = 0;
+
+ BIO_set_prefix(trace_data->bio, NULL);
+
+ break;
+ }
+
+ return ret < 0 ? 0 : ret;
+}
+
+DEFINE_STACK_OF(tracedata)
+static STACK_OF(tracedata) *trace_data_stack;
- return p;
+static void tracedata_free(tracedata *data)
+{
+ BIO_free_all(data->bio);
+ OPENSSL_free(data);
}
+static STACK_OF(tracedata) *trace_data_stack;
+
+static void cleanup_trace(void)
+{
+ sk_tracedata_pop_free(trace_data_stack, tracedata_free);
+}
+
+static void setup_trace_category(int category)
+{
+ BIO *channel;
+ tracedata *trace_data;
+ BIO *bio = NULL;
+
+ if (OSSL_trace_enabled(category))
+ return;
+
+ bio = BIO_new(BIO_f_prefix());
+ channel = BIO_push(bio, dup_bio_err(FORMAT_TEXT));
+ trace_data = OPENSSL_zalloc(sizeof(*trace_data));
+
+ if (trace_data == NULL
+ || bio == NULL
+ || (trace_data->bio = channel) == NULL
+ || OSSL_trace_set_callback(category, internal_trace_cb,
+ trace_data) == 0
+ || sk_tracedata_push(trace_data_stack, trace_data) == 0) {
+
+ fprintf(stderr,
+ "warning: unable to setup trace callback for category '%s'.\n",
+ OSSL_trace_get_category_name(category));
+
+ OSSL_trace_set_callback(category, NULL, NULL);
+ BIO_free_all(channel);
+ }
+}
+
+static void setup_trace(const char *str)
+{
+ char *val;
+
+ /*
+ * We add this handler as early as possible to ensure it's executed
+ * as late as possible, i.e. after the TRACE code has done its cleanup
+ * (which happens last in OPENSSL_cleanup).
+ */
+ atexit(cleanup_trace);
+
+ trace_data_stack = sk_tracedata_new_null();
+ val = OPENSSL_strdup(str);
+
+ if (val != NULL) {
+ char *valp = val;
+ char *item;
+
+ for (valp = val; (item = strtok(valp, ",")) != NULL; valp = NULL) {
+ int category = OSSL_trace_get_category_num(item);
+
+ if (category == OSSL_TRACE_CATEGORY_ALL) {
+ while (++category < OSSL_TRACE_CATEGORY_NUM)
+ setup_trace_category(category);
+ break;
+ } else if (category > 0) {
+ setup_trace_category(category);
+ } else {
+ fprintf(stderr,
+ "warning: unknown trace category: '%s'.\n", item);
+ }
+ }
+ }
+
+ OPENSSL_free(val);
+}
+#endif /* OPENSSL_NO_TRACE */
+
+static char *help_argv[] = { "help", NULL };
+
int main(int argc, char *argv[])
{
FUNCTION f, *fp;
LHASH_OF(FUNCTION) *prog = NULL;
- char *p, *pname;
- char buf[1024];
- const char *prompt;
+ char *pname;
+ const char *fname;
ARGS arg;
- int first, n, i, ret = 0;
+ int global_help = 0;
+ int ret = 0;
arg.argv = NULL;
arg.size = 0;
/* Set up some of the environment. */
- default_config_file = make_config_name();
bio_in = dup_bio_in(FORMAT_TEXT);
bio_out = dup_bio_out(FORMAT_TEXT);
bio_err = dup_bio_err(FORMAT_TEXT);
@@ -138,319 +254,75 @@ int main(int argc, char *argv[])
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
argv = copy_argv(&argc, argv);
#elif defined(_WIN32)
- /*
- * Replace argv[] with UTF-8 encoded strings.
- */
+ /* Replace argv[] with UTF-8 encoded strings. */
win32_utf8argv(&argc, &argv);
#endif
- p = getenv("OPENSSL_DEBUG_MEMORY");
- if (p != NULL && strcmp(p, "on") == 0)
- CRYPTO_set_mem_debug(1);
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
-
- if (getenv("OPENSSL_FIPS")) {
- BIO_printf(bio_err, "FIPS mode not supported.\n");
- return 1;
- }
-
- if (!apps_startup()) {
- BIO_printf(bio_err,
- "FATAL: Startup failure (dev note: apps_startup() failed)\n");
- ERR_print_errors(bio_err);
- ret = 1;
- goto end;
- }
+#ifndef OPENSSL_NO_TRACE
+ setup_trace(getenv("OPENSSL_TRACE"));
+#endif
- prog = prog_init();
- if (prog == NULL) {
+ if ((fname = "apps_startup", !apps_startup())
+ || (fname = "prog_init", (prog = prog_init()) == NULL)) {
BIO_printf(bio_err,
- "FATAL: Startup failure (dev note: prog_init() failed)\n");
+ "FATAL: Startup failure (dev note: %s()) for %s\n",
+ fname, argv[0]);
ERR_print_errors(bio_err);
ret = 1;
goto end;
}
pname = opt_progname(argv[0]);
+ default_config_file = CONF_get1_default_config_file();
+ if (default_config_file == NULL)
+ app_bail_out("%s: could not get default config file\n", pname);
+
/* first check the program name */
f.name = pname;
fp = lh_FUNCTION_retrieve(prog, &f);
- if (fp != NULL) {
- argv[0] = pname;
- ret = fp->func(argc, argv);
- goto end;
- }
-
- /* If there is stuff on the command line, run with that. */
- if (argc != 1) {
+ if (fp == NULL) {
+ /* We assume we've been called as 'openssl ...' */
+ global_help = argc > 1
+ && (strcmp(argv[1], "-help") == 0 || strcmp(argv[1], "--help") == 0
+ || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--h") == 0);
argc--;
argv++;
- ret = do_cmd(prog, argc, argv);
- if (ret < 0)
- ret = 0;
- goto end;
+ opt_appname(argc == 1 || global_help ? "help" : argv[0]);
+ } else {
+ argv[0] = pname;
}
- /* ok, lets enter interactive mode */
- for (;;) {
- ret = 0;
- /* Read a line, continue reading if line ends with \ */
- for (p = buf, n = sizeof(buf), i = 0, first = 1; n > 0; first = 0) {
- prompt = first ? "OpenSSL> " : "> ";
- p[0] = '\0';
-#ifndef READLINE
- fputs(prompt, stdout);
- fflush(stdout);
- if (!fgets(p, n, stdin))
- goto end;
- if (p[0] == '\0')
- goto end;
- i = strlen(p);
- if (i <= 1)
- break;
- if (p[i - 2] != '\\')
- break;
- i -= 2;
- p += i;
- n -= i;
-#else
- {
- extern char *readline(const char *);
- extern void add_history(const char *cp);
- char *text;
-
- text = readline(prompt);
- if (text == NULL)
- goto end;
- i = strlen(text);
- if (i == 0 || i > n)
- break;
- if (text[i - 1] != '\\') {
- p += strlen(strcpy(p, text));
- free(text);
- add_history(buf);
- break;
- }
-
- text[i - 1] = '\0';
- p += strlen(strcpy(p, text));
- free(text);
- n -= i;
- }
-#endif
- }
+ /* If there's a command, run with that, otherwise "help". */
+ ret = argc == 0 || global_help
+ ? do_cmd(prog, 1, help_argv)
+ : do_cmd(prog, argc, argv);
- if (!chopup_args(&arg, buf)) {
- BIO_printf(bio_err, "Can't parse (no memory?)\n");
- break;
- }
-
- ret = do_cmd(prog, arg.argc, arg.argv);
- if (ret == EXIT_THE_PROGRAM) {
- ret = 0;
- goto end;
- }
- if (ret != 0)
- BIO_printf(bio_err, "error in %s\n", arg.argv[0]);
- (void)BIO_flush(bio_out);
- (void)BIO_flush(bio_err);
- }
- ret = 1;
end:
OPENSSL_free(default_config_file);
lh_FUNCTION_free(prog);
OPENSSL_free(arg.argv);
- app_RAND_write();
+ if (!app_RAND_write())
+ ret = EXIT_FAILURE;
BIO_free(bio_in);
BIO_free_all(bio_out);
apps_shutdown();
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
- if (CRYPTO_mem_leaks(bio_err) <= 0)
- ret = 1;
-#endif
- BIO_free(bio_err);
+ BIO_free_all(bio_err);
EXIT(ret);
}
-static void list_cipher_fn(const EVP_CIPHER *c,
- const char *from, const char *to, void *arg)
-{
- if (c != NULL) {
- BIO_printf(arg, "%s\n", EVP_CIPHER_name(c));
- } else {
- if (from == NULL)
- from = "<undefined>";
- if (to == NULL)
- to = "<undefined>";
- BIO_printf(arg, "%s => %s\n", from, to);
- }
-}
-
-static void list_md_fn(const EVP_MD *m,
- const char *from, const char *to, void *arg)
-{
- if (m != NULL) {
- BIO_printf(arg, "%s\n", EVP_MD_name(m));
- } else {
- if (from == NULL)
- from = "<undefined>";
- if (to == NULL)
- to = "<undefined>";
- BIO_printf((BIO *)arg, "%s => %s\n", from, to);
- }
-}
-
-static void list_missing_help(void)
-{
- const FUNCTION *fp;
- const OPTIONS *o;
-
- for (fp = functions; fp->name != NULL; fp++) {
- if ((o = fp->help) != NULL) {
- /* If there is help, list what flags are not documented. */
- for ( ; o->name != NULL; o++) {
- if (o->helpstr == NULL)
- BIO_printf(bio_out, "%s %s\n", fp->name, o->name);
- }
- } else if (fp->func != dgst_main) {
- /* If not aliased to the dgst command, */
- BIO_printf(bio_out, "%s *\n", fp->name);
- }
- }
-}
-
-static void list_options_for_command(const char *command)
-{
- const FUNCTION *fp;
- const OPTIONS *o;
-
- for (fp = functions; fp->name != NULL; fp++)
- if (strcmp(fp->name, command) == 0)
- break;
- if (fp->name == NULL) {
- BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n",
- command);
- return;
- }
-
- if ((o = fp->help) == NULL)
- return;
-
- for ( ; o->name != NULL; o++) {
- if (o->name == OPT_HELP_STR
- || o->name == OPT_MORE_STR
- || o->name[0] == '\0')
- continue;
- BIO_printf(bio_out, "%s %c\n", o->name, o->valtype);
- }
-}
-
-
-/* Unified enum for help and list commands. */
-typedef enum HELPLIST_CHOICE {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ONE,
- OPT_COMMANDS, OPT_DIGEST_COMMANDS, OPT_OPTIONS,
- OPT_DIGEST_ALGORITHMS, OPT_CIPHER_COMMANDS, OPT_CIPHER_ALGORITHMS,
- OPT_PK_ALGORITHMS, OPT_PK_METHOD, OPT_DISABLED, OPT_MISSING_HELP
-} HELPLIST_CHOICE;
-
-const OPTIONS list_options[] = {
- {"help", OPT_HELP, '-', "Display this summary"},
- {"1", OPT_ONE, '-', "List in one column"},
- {"commands", OPT_COMMANDS, '-', "List of standard commands"},
- {"digest-commands", OPT_DIGEST_COMMANDS, '-',
- "List of message digest commands"},
- {"digest-algorithms", OPT_DIGEST_ALGORITHMS, '-',
- "List of message digest algorithms"},
- {"cipher-commands", OPT_CIPHER_COMMANDS, '-', "List of cipher commands"},
- {"cipher-algorithms", OPT_CIPHER_ALGORITHMS, '-',
- "List of cipher algorithms"},
- {"public-key-algorithms", OPT_PK_ALGORITHMS, '-',
- "List of public key algorithms"},
- {"public-key-methods", OPT_PK_METHOD, '-',
- "List of public key methods"},
- {"disabled", OPT_DISABLED, '-',
- "List of disabled features"},
- {"missing-help", OPT_MISSING_HELP, '-',
- "List missing detailed help strings"},
- {"options", OPT_OPTIONS, 's',
- "List options for specified command"},
- {NULL}
-};
-
-int list_main(int argc, char **argv)
-{
- char *prog;
- HELPLIST_CHOICE o;
- int one = 0, done = 0;
-
- prog = opt_init(argc, argv, list_options);
- while ((o = opt_next()) != OPT_EOF) {
- switch (o) {
- case OPT_EOF: /* Never hit, but suppresses warning */
- case OPT_ERR:
-opthelp:
- BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
- return 1;
- case OPT_HELP:
- opt_help(list_options);
- break;
- case OPT_ONE:
- one = 1;
- break;
- case OPT_COMMANDS:
- list_type(FT_general, one);
- break;
- case OPT_DIGEST_COMMANDS:
- list_type(FT_md, one);
- break;
- case OPT_DIGEST_ALGORITHMS:
- EVP_MD_do_all_sorted(list_md_fn, bio_out);
- break;
- case OPT_CIPHER_COMMANDS:
- list_type(FT_cipher, one);
- break;
- case OPT_CIPHER_ALGORITHMS:
- EVP_CIPHER_do_all_sorted(list_cipher_fn, bio_out);
- break;
- case OPT_PK_ALGORITHMS:
- list_pkey();
- break;
- case OPT_PK_METHOD:
- list_pkey_meth();
- break;
- case OPT_DISABLED:
- list_disabled();
- break;
- case OPT_MISSING_HELP:
- list_missing_help();
- break;
- case OPT_OPTIONS:
- list_options_for_command(opt_arg());
- break;
- }
- done = 1;
- }
- if (opt_num_rest() != 0) {
- BIO_printf(bio_err, "Extra arguments given.\n");
- goto opthelp;
- }
-
- if (!done)
- goto opthelp;
-
- return 0;
-}
-
typedef enum HELP_CHOICE {
OPT_hERR = -1, OPT_hEOF = 0, OPT_hHELP
} HELP_CHOICE;
const OPTIONS help_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: help [options]\n"},
- {OPT_HELP_STR, 1, '-', " help [command]\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: help [options] [command]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_hHELP, '-', "Display this summary"},
+
+ OPT_PARAMETERS(),
+ {"command", 0, 0, "Name of command to display help (optional)"},
{NULL}
};
@@ -463,6 +335,7 @@ int help_main(int argc, char **argv)
char *prog;
HELP_CHOICE o;
DISPLAY_COLUMNS dc;
+ char *new_argv[3];
prog = opt_init(argc, argv, help_options);
while ((o = opt_next()) != OPT_hEOF) {
@@ -477,9 +350,8 @@ int help_main(int argc, char **argv)
}
}
+ /* One optional argument, the command to get help for. */
if (opt_num_rest() == 1) {
- char *new_argv[3];
-
new_argv[0] = opt_rest()[0];
new_argv[1] = "--help";
new_argv[2] = NULL;
@@ -490,8 +362,8 @@ int help_main(int argc, char **argv)
return 1;
}
- calculate_columns(&dc);
- BIO_printf(bio_err, "Standard commands");
+ calculate_columns(functions, &dc);
+ BIO_printf(bio_err, "%s:\n\nStandard commands", prog);
i = 0;
tp = FT_none;
for (fp = functions; fp->name != NULL; fp++) {
@@ -520,37 +392,13 @@ int help_main(int argc, char **argv)
return 0;
}
-static void list_type(FUNC_TYPE ft, int one)
-{
- FUNCTION *fp;
- int i = 0;
- DISPLAY_COLUMNS dc = {0};
-
- if (!one)
- calculate_columns(&dc);
-
- for (fp = functions; fp->name != NULL; fp++) {
- if (fp->type != ft)
- continue;
- if (one) {
- BIO_printf(bio_out, "%s\n", fp->name);
- } else {
- if (i % dc.columns == 0 && i > 0)
- BIO_printf(bio_out, "\n");
- BIO_printf(bio_out, "%-*s", dc.width, fp->name);
- i++;
- }
- }
- if (!one)
- BIO_printf(bio_out, "\n\n");
-}
-
static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[])
{
FUNCTION f, *fp;
if (argc <= 0 || argv[0] == NULL)
return 0;
+ memset(&f, 0, sizeof(f));
f.name = argv[0];
fp = lh_FUNCTION_retrieve(prog, &f);
if (fp == NULL) {
@@ -565,6 +413,8 @@ static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[])
}
}
if (fp != NULL) {
+ if (fp->deprecated_alternative != NULL)
+ warn_deprecated(fp);
return fp->func(argc, argv);
}
if ((strncmp(argv[0], "no-", 3)) == 0) {
@@ -580,61 +430,12 @@ static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[])
BIO_printf(bio_out, "%s\n", argv[0] + 3);
return 1;
}
- if (strcmp(argv[0], "quit") == 0 || strcmp(argv[0], "q") == 0 ||
- strcmp(argv[0], "exit") == 0 || strcmp(argv[0], "bye") == 0)
- /* Special value to mean "exit the program. */
- return EXIT_THE_PROGRAM;
BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n",
argv[0]);
return 1;
}
-static void list_pkey(void)
-{
- int i;
-
- for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
- const EVP_PKEY_ASN1_METHOD *ameth;
- int pkey_id, pkey_base_id, pkey_flags;
- const char *pinfo, *pem_str;
- ameth = EVP_PKEY_asn1_get0(i);
- EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags,
- &pinfo, &pem_str, ameth);
- if (pkey_flags & ASN1_PKEY_ALIAS) {
- BIO_printf(bio_out, "Name: %s\n", OBJ_nid2ln(pkey_id));
- BIO_printf(bio_out, "\tAlias for: %s\n",
- OBJ_nid2ln(pkey_base_id));
- } else {
- BIO_printf(bio_out, "Name: %s\n", pinfo);
- BIO_printf(bio_out, "\tType: %s Algorithm\n",
- pkey_flags & ASN1_PKEY_DYNAMIC ?
- "External" : "Builtin");
- BIO_printf(bio_out, "\tOID: %s\n", OBJ_nid2ln(pkey_id));
- if (pem_str == NULL)
- pem_str = "(none)";
- BIO_printf(bio_out, "\tPEM string: %s\n", pem_str);
- }
-
- }
-}
-
-static void list_pkey_meth(void)
-{
- size_t i;
- size_t meth_count = EVP_PKEY_meth_get_count();
-
- for (i = 0; i < meth_count; i++) {
- const EVP_PKEY_METHOD *pmeth = EVP_PKEY_meth_get0(i);
- int pkey_id, pkey_flags;
-
- EVP_PKEY_meth_get0_info(&pkey_id, &pkey_flags, pmeth);
- BIO_printf(bio_out, "%s\n", OBJ_nid2ln(pkey_id));
- BIO_printf(bio_out, "\tType: %s Algorithm\n",
- pkey_flags & ASN1_PKEY_DYNAMIC ? "External" : "Builtin");
- }
-}
-
static int function_cmp(const FUNCTION * a, const FUNCTION * b)
{
return strncmp(a->name, b->name, 8);
@@ -655,155 +456,6 @@ static int SortFnByName(const void *_f1, const void *_f2)
return strcmp(f1->name, f2->name);
}
-static void list_disabled(void)
-{
- BIO_puts(bio_out, "Disabled algorithms:\n");
-#ifdef OPENSSL_NO_ARIA
- BIO_puts(bio_out, "ARIA\n");
-#endif
-#ifdef OPENSSL_NO_BF
- BIO_puts(bio_out, "BF\n");
-#endif
-#ifdef OPENSSL_NO_BLAKE2
- BIO_puts(bio_out, "BLAKE2\n");
-#endif
-#ifdef OPENSSL_NO_CAMELLIA
- BIO_puts(bio_out, "CAMELLIA\n");
-#endif
-#ifdef OPENSSL_NO_CAST
- BIO_puts(bio_out, "CAST\n");
-#endif
-#ifdef OPENSSL_NO_CMAC
- BIO_puts(bio_out, "CMAC\n");
-#endif
-#ifdef OPENSSL_NO_CMS
- BIO_puts(bio_out, "CMS\n");
-#endif
-#ifdef OPENSSL_NO_COMP
- BIO_puts(bio_out, "COMP\n");
-#endif
-#ifdef OPENSSL_NO_DES
- BIO_puts(bio_out, "DES\n");
-#endif
-#ifdef OPENSSL_NO_DGRAM
- BIO_puts(bio_out, "DGRAM\n");
-#endif
-#ifdef OPENSSL_NO_DH
- BIO_puts(bio_out, "DH\n");
-#endif
-#ifdef OPENSSL_NO_DSA
- BIO_puts(bio_out, "DSA\n");
-#endif
-#if defined(OPENSSL_NO_DTLS)
- BIO_puts(bio_out, "DTLS\n");
-#endif
-#if defined(OPENSSL_NO_DTLS1)
- BIO_puts(bio_out, "DTLS1\n");
-#endif
-#if defined(OPENSSL_NO_DTLS1_2)
- BIO_puts(bio_out, "DTLS1_2\n");
-#endif
-#ifdef OPENSSL_NO_EC
- BIO_puts(bio_out, "EC\n");
-#endif
-#ifdef OPENSSL_NO_EC2M
- BIO_puts(bio_out, "EC2M\n");
-#endif
-#ifdef OPENSSL_NO_ENGINE
- BIO_puts(bio_out, "ENGINE\n");
-#endif
-#ifdef OPENSSL_NO_GOST
- BIO_puts(bio_out, "GOST\n");
-#endif
-#ifdef OPENSSL_NO_HEARTBEATS
- BIO_puts(bio_out, "HEARTBEATS\n");
-#endif
-#ifdef OPENSSL_NO_IDEA
- BIO_puts(bio_out, "IDEA\n");
-#endif
-#ifdef OPENSSL_NO_MD2
- BIO_puts(bio_out, "MD2\n");
-#endif
-#ifdef OPENSSL_NO_MD4
- BIO_puts(bio_out, "MD4\n");
-#endif
-#ifdef OPENSSL_NO_MD5
- BIO_puts(bio_out, "MD5\n");
-#endif
-#ifdef OPENSSL_NO_MDC2
- BIO_puts(bio_out, "MDC2\n");
-#endif
-#ifdef OPENSSL_NO_OCB
- BIO_puts(bio_out, "OCB\n");
-#endif
-#ifdef OPENSSL_NO_OCSP
- BIO_puts(bio_out, "OCSP\n");
-#endif
-#ifdef OPENSSL_NO_PSK
- BIO_puts(bio_out, "PSK\n");
-#endif
-#ifdef OPENSSL_NO_RC2
- BIO_puts(bio_out, "RC2\n");
-#endif
-#ifdef OPENSSL_NO_RC4
- BIO_puts(bio_out, "RC4\n");
-#endif
-#ifdef OPENSSL_NO_RC5
- BIO_puts(bio_out, "RC5\n");
-#endif
-#ifdef OPENSSL_NO_RMD160
- BIO_puts(bio_out, "RMD160\n");
-#endif
-#ifdef OPENSSL_NO_RSA
- BIO_puts(bio_out, "RSA\n");
-#endif
-#ifdef OPENSSL_NO_SCRYPT
- BIO_puts(bio_out, "SCRYPT\n");
-#endif
-#ifdef OPENSSL_NO_SCTP
- BIO_puts(bio_out, "SCTP\n");
-#endif
-#ifdef OPENSSL_NO_SEED
- BIO_puts(bio_out, "SEED\n");
-#endif
-#ifdef OPENSSL_NO_SM2
- BIO_puts(bio_out, "SM2\n");
-#endif
-#ifdef OPENSSL_NO_SM3
- BIO_puts(bio_out, "SM3\n");
-#endif
-#ifdef OPENSSL_NO_SM4
- BIO_puts(bio_out, "SM4\n");
-#endif
-#ifdef OPENSSL_NO_SOCK
- BIO_puts(bio_out, "SOCK\n");
-#endif
-#ifdef OPENSSL_NO_SRP
- BIO_puts(bio_out, "SRP\n");
-#endif
-#ifdef OPENSSL_NO_SRTP
- BIO_puts(bio_out, "SRTP\n");
-#endif
-#ifdef OPENSSL_NO_SSL3
- BIO_puts(bio_out, "SSL3\n");
-#endif
-#ifdef OPENSSL_NO_TLS1
- BIO_puts(bio_out, "TLS1\n");
-#endif
-#ifdef OPENSSL_NO_TLS1_1
- BIO_puts(bio_out, "TLS1_1\n");
-#endif
-#ifdef OPENSSL_NO_TLS1_2
- BIO_puts(bio_out, "TLS1_2\n");
-#endif
-#ifdef OPENSSL_NO_WHIRLPOOL
- BIO_puts(bio_out, "WHIRLPOOL\n");
-#endif
-#ifndef ZLIB
- BIO_puts(bio_out, "ZLIB\n");
-#endif
-}
-
static LHASH_OF(FUNCTION) *prog_init(void)
{
static LHASH_OF(FUNCTION) *ret = NULL;
diff --git a/apps/openssl.cnf b/apps/openssl.cnf
index 4acca4b0446f..03330e0120a2 100644
--- a/apps/openssl.cnf
+++ b/apps/openssl.cnf
@@ -1,7 +1,9 @@
#
# OpenSSL example configuration file.
-# This is mostly being used for generation of certificate requests.
+# See doc/man5/config.pod for more info.
#
+# This is mostly being used for generation of certificate requests,
+# but may be used for auto loading of providers
# Note that you can include other files from the main configuration
# file using the .include directive.
@@ -11,9 +13,15 @@
# defined.
HOME = .
+ # Use this in order to automatically load providers.
+openssl_conf = openssl_init
+
+# Comment out the next line to ignore configuration errors
+config_diagnostics = 1
+
# Extra OBJECT IDENTIFIER info:
-#oid_file = $ENV::HOME/.oid
-oid_section = new_oids
+# oid_file = $ENV::HOME/.oid
+oid_section = new_oids
# To use this configuration file with the "-extfile" option of the
# "openssl x509" utility, name here the section containing the
@@ -23,7 +31,6 @@ oid_section = new_oids
# X.509v3 extensions in its main [= default] section.)
[ new_oids ]
-
# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
# Add a simple OID like this:
# testoid1=1.2.3.4
@@ -35,6 +42,36 @@ tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7
+# For FIPS
+# Optionally include a file that is generated by the OpenSSL fipsinstall
+# application. This file contains configuration data required by the OpenSSL
+# fips provider. It contains a named section e.g. [fips_sect] which is
+# referenced from the [provider_sect] below.
+# Refer to the OpenSSL security policy for more information.
+# .include fipsmodule.cnf
+
+[openssl_init]
+providers = provider_sect
+
+# List of providers to load
+[provider_sect]
+default = default_sect
+# The fips section name should match the section name inside the
+# included fipsmodule.cnf.
+# fips = fips_sect
+
+# If no providers are activated explicitly, the default one is activated implicitly.
+# See man 7 OSSL_PROVIDER-default for more details.
+#
+# If you add a section explicitly activating any other provider(s), you most
+# probably need to explicitly activate the default provider, otherwise it
+# becomes unavailable in openssl. As a consequence applications depending on
+# OpenSSL may not work correctly which could lead to significant system
+# problems including inability to remotely access the system.
+[default_sect]
+# activate = 1
+
+
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
@@ -171,27 +208,9 @@ unstructuredName = An optional company name
basicConstraints=CA:FALSE
-# Here are some examples of the usage of nsCertType. If it is omitted
-# the certificate can be used for anything *except* object signing.
-
-# This is OK for an SSL server.
-# nsCertType = server
-
-# For an object signing certificate this would be used.
-# nsCertType = objsign
-
-# For normal client use this is typical
-# nsCertType = client, email
-
-# and for everything including object signing:
-# nsCertType = client, email, objsign
-
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
-# This will be displayed in Netscape's comment listbox.
-nsComment = "OpenSSL Generated Certificate"
-
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
@@ -206,13 +225,6 @@ authorityKeyIdentifier=keyid,issuer
# Copy subject details
# issuerAltName=issuer:copy
-#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
-#nsBaseUrl
-#nsRevocationUrl
-#nsRenewalUrl
-#nsCaPolicyUrl
-#nsSslServerName
-
# This is required for TSA certificates.
# extendedKeyUsage = critical,timeStamping
@@ -242,9 +254,6 @@ basicConstraints = critical,CA:true
# left out by default.
# keyUsage = cRLSign, keyCertSign
-# Some might want this also
-# nsCertType = sslCA, emailCA
-
# Include email address in subject alt name: another PKIX recommendation
# subjectAltName=email:copy
# Copy issuer details
@@ -272,27 +281,9 @@ authorityKeyIdentifier=keyid:always
basicConstraints=CA:FALSE
-# Here are some examples of the usage of nsCertType. If it is omitted
-# the certificate can be used for anything *except* object signing.
-
-# This is OK for an SSL server.
-# nsCertType = server
-
-# For an object signing certificate this would be used.
-# nsCertType = objsign
-
-# For normal client use this is typical
-# nsCertType = client, email
-
-# and for everything including object signing:
-# nsCertType = client, email, objsign
-
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
-# This will be displayed in Netscape's comment listbox.
-nsComment = "OpenSSL Generated Certificate"
-
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
@@ -307,13 +298,6 @@ authorityKeyIdentifier=keyid,issuer
# Copy subject details
# issuerAltName=issuer:copy
-#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
-#nsBaseUrl
-#nsRevocationUrl
-#nsRenewalUrl
-#nsCaPolicyUrl
-#nsSslServerName
-
# This really needs to be in place for it to be a proxy certificate.
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
@@ -348,3 +332,59 @@ ess_cert_id_chain = no # Must the ESS cert id chain be included?
# (optional, default: no)
ess_cert_id_alg = sha1 # algorithm to compute certificate
# identifier (optional, default: sha1)
+
+[insta] # CMP using Insta Demo CA
+# Message transfer
+server = pki.certificate.fi:8700
+# proxy = # set this as far as needed, e.g., http://192.168.1.1:8080
+# tls_use = 0
+path = pkix/
+
+# Server authentication
+recipient = "/C=FI/O=Insta Demo/CN=Insta Demo CA" # or set srvcert or issuer
+ignore_keyusage = 1 # potentially needed quirk
+unprotected_errors = 1 # potentially needed quirk
+extracertsout = insta.extracerts.pem
+
+# Client authentication
+ref = 3078 # user identification
+secret = pass:insta # can be used for both client and server side
+
+# Generic message options
+cmd = ir # default operation, can be overridden on cmd line with, e.g., kur
+
+# Certificate enrollment
+subject = "/CN=openssl-cmp-test"
+newkey = insta.priv.pem
+out_trusted = insta.ca.crt
+certout = insta.cert.pem
+
+[pbm] # Password-based protection for Insta CA
+# Server and client authentication
+ref = $insta::ref # 3078
+secret = $insta::secret # pass:insta
+
+[signature] # Signature-based protection for Insta CA
+# Server authentication
+trusted = insta.ca.crt # does not include keyUsage digitalSignature
+
+# Client authentication
+secret = # disable PBM
+key = $insta::newkey # insta.priv.pem
+cert = $insta::certout # insta.cert.pem
+
+[ir]
+cmd = ir
+
+[cr]
+cmd = cr
+
+[kur]
+# Certificate update
+cmd = kur
+oldcert = $insta::certout # insta.cert.pem
+
+[rr]
+# Certificate revocation
+cmd = rr
+oldcert = $insta::certout # insta.cert.pem
diff --git a/apps/opt.c b/apps/opt.c
deleted file mode 100644
index 666856535d5e..000000000000
--- a/apps/opt.c
+++ /dev/null
@@ -1,898 +0,0 @@
-/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-#include "apps.h"
-#include <string.h>
-#if !defined(OPENSSL_SYS_MSDOS)
-# include OPENSSL_UNISTD
-#endif
-
-#include <stdlib.h>
-#include <errno.h>
-#include <ctype.h>
-#include <limits.h>
-#include <openssl/bio.h>
-#include <openssl/x509v3.h>
-
-#define MAX_OPT_HELP_WIDTH 30
-const char OPT_HELP_STR[] = "--";
-const char OPT_MORE_STR[] = "---";
-
-/* Our state */
-static char **argv;
-static int argc;
-static int opt_index;
-static char *arg;
-static char *flag;
-static char *dunno;
-static const OPTIONS *unknown;
-static const OPTIONS *opts;
-static char prog[40];
-
-/*
- * Return the simple name of the program; removing various platform gunk.
- */
-#if defined(OPENSSL_SYS_WIN32)
-char *opt_progname(const char *argv0)
-{
- size_t i, n;
- const char *p;
- char *q;
-
- /* find the last '/', '\' or ':' */
- for (p = argv0 + strlen(argv0); --p > argv0;)
- if (*p == '/' || *p == '\\' || *p == ':') {
- p++;
- break;
- }
-
- /* Strip off trailing nonsense. */
- n = strlen(p);
- if (n > 4 &&
- (strcmp(&p[n - 4], ".exe") == 0 || strcmp(&p[n - 4], ".EXE") == 0))
- n -= 4;
-
- /* Copy over the name, in lowercase. */
- if (n > sizeof(prog) - 1)
- n = sizeof(prog) - 1;
- for (q = prog, i = 0; i < n; i++, p++)
- *q++ = tolower((unsigned char)*p);
- *q = '\0';
- return prog;
-}
-
-#elif defined(OPENSSL_SYS_VMS)
-
-char *opt_progname(const char *argv0)
-{
- const char *p, *q;
-
- /* Find last special character sys:[foo.bar]openssl */
- for (p = argv0 + strlen(argv0); --p > argv0;)
- if (*p == ':' || *p == ']' || *p == '>') {
- p++;
- break;
- }
-
- q = strrchr(p, '.');
- strncpy(prog, p, sizeof(prog) - 1);
- prog[sizeof(prog) - 1] = '\0';
- if (q != NULL && q - p < sizeof(prog))
- prog[q - p] = '\0';
- return prog;
-}
-
-#else
-
-char *opt_progname(const char *argv0)
-{
- const char *p;
-
- /* Could use strchr, but this is like the ones above. */
- for (p = argv0 + strlen(argv0); --p > argv0;)
- if (*p == '/') {
- p++;
- break;
- }
- strncpy(prog, p, sizeof(prog) - 1);
- prog[sizeof(prog) - 1] = '\0';
- return prog;
-}
-#endif
-
-char *opt_getprog(void)
-{
- return prog;
-}
-
-/* Set up the arg parsing. */
-char *opt_init(int ac, char **av, const OPTIONS *o)
-{
- /* Store state. */
- argc = ac;
- argv = av;
- opt_index = 1;
- opts = o;
- opt_progname(av[0]);
- unknown = NULL;
-
- for (; o->name; ++o) {
-#ifndef NDEBUG
- const OPTIONS *next;
- int duplicated, i;
-#endif
-
- if (o->name == OPT_HELP_STR || o->name == OPT_MORE_STR)
- continue;
-#ifndef NDEBUG
- i = o->valtype;
-
- /* Make sure options are legit. */
- assert(o->name[0] != '-');
- assert(o->retval > 0);
- switch (i) {
- case 0: case '-': case '/': case '<': case '>': case 'E': case 'F':
- case 'M': case 'U': case 'f': case 'l': case 'n': case 'p': case 's':
- case 'u': case 'c':
- break;
- default:
- assert(0);
- }
-
- /* Make sure there are no duplicates. */
- for (next = o + 1; next->name; ++next) {
- /*
- * Some compilers inline strcmp and the assert string is too long.
- */
- duplicated = strcmp(o->name, next->name) == 0;
- assert(!duplicated);
- }
-#endif
- if (o->name[0] == '\0') {
- assert(unknown == NULL);
- unknown = o;
- assert(unknown->valtype == 0 || unknown->valtype == '-');
- }
- }
- return prog;
-}
-
-static OPT_PAIR formats[] = {
- {"PEM/DER", OPT_FMT_PEMDER},
- {"pkcs12", OPT_FMT_PKCS12},
- {"smime", OPT_FMT_SMIME},
- {"engine", OPT_FMT_ENGINE},
- {"msblob", OPT_FMT_MSBLOB},
- {"nss", OPT_FMT_NSS},
- {"text", OPT_FMT_TEXT},
- {"http", OPT_FMT_HTTP},
- {"pvk", OPT_FMT_PVK},
- {NULL}
-};
-
-/* Print an error message about a failed format parse. */
-int opt_format_error(const char *s, unsigned long flags)
-{
- OPT_PAIR *ap;
-
- if (flags == OPT_FMT_PEMDER) {
- BIO_printf(bio_err, "%s: Bad format \"%s\"; must be pem or der\n",
- prog, s);
- } else {
- BIO_printf(bio_err, "%s: Bad format \"%s\"; must be one of:\n",
- prog, s);
- for (ap = formats; ap->name; ap++)
- if (flags & ap->retval)
- BIO_printf(bio_err, " %s\n", ap->name);
- }
- return 0;
-}
-
-/* Parse a format string, put it into *result; return 0 on failure, else 1. */
-int opt_format(const char *s, unsigned long flags, int *result)
-{
- switch (*s) {
- default:
- return 0;
- case 'D':
- case 'd':
- if ((flags & OPT_FMT_PEMDER) == 0)
- return opt_format_error(s, flags);
- *result = FORMAT_ASN1;
- break;
- case 'T':
- case 't':
- if ((flags & OPT_FMT_TEXT) == 0)
- return opt_format_error(s, flags);
- *result = FORMAT_TEXT;
- break;
- case 'N':
- case 'n':
- if ((flags & OPT_FMT_NSS) == 0)
- return opt_format_error(s, flags);
- if (strcmp(s, "NSS") != 0 && strcmp(s, "nss") != 0)
- return opt_format_error(s, flags);
- *result = FORMAT_NSS;
- break;
- case 'S':
- case 's':
- if ((flags & OPT_FMT_SMIME) == 0)
- return opt_format_error(s, flags);
- *result = FORMAT_SMIME;
- break;
- case 'M':
- case 'm':
- if ((flags & OPT_FMT_MSBLOB) == 0)
- return opt_format_error(s, flags);
- *result = FORMAT_MSBLOB;
- break;
- case 'E':
- case 'e':
- if ((flags & OPT_FMT_ENGINE) == 0)
- return opt_format_error(s, flags);
- *result = FORMAT_ENGINE;
- break;
- case 'H':
- case 'h':
- if ((flags & OPT_FMT_HTTP) == 0)
- return opt_format_error(s, flags);
- *result = FORMAT_HTTP;
- break;
- case '1':
- if ((flags & OPT_FMT_PKCS12) == 0)
- return opt_format_error(s, flags);
- *result = FORMAT_PKCS12;
- break;
- case 'P':
- case 'p':
- if (s[1] == '\0' || strcmp(s, "PEM") == 0 || strcmp(s, "pem") == 0) {
- if ((flags & OPT_FMT_PEMDER) == 0)
- return opt_format_error(s, flags);
- *result = FORMAT_PEM;
- } else if (strcmp(s, "PVK") == 0 || strcmp(s, "pvk") == 0) {
- if ((flags & OPT_FMT_PVK) == 0)
- return opt_format_error(s, flags);
- *result = FORMAT_PVK;
- } else if (strcmp(s, "P12") == 0 || strcmp(s, "p12") == 0
- || strcmp(s, "PKCS12") == 0 || strcmp(s, "pkcs12") == 0) {
- if ((flags & OPT_FMT_PKCS12) == 0)
- return opt_format_error(s, flags);
- *result = FORMAT_PKCS12;
- } else {
- return 0;
- }
- break;
- }
- return 1;
-}
-
-/* Parse a cipher name, put it in *EVP_CIPHER; return 0 on failure, else 1. */
-int opt_cipher(const char *name, const EVP_CIPHER **cipherp)
-{
- *cipherp = EVP_get_cipherbyname(name);
- if (*cipherp != NULL)
- return 1;
- BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name);
- return 0;
-}
-
-/*
- * Parse message digest name, put it in *EVP_MD; return 0 on failure, else 1.
- */
-int opt_md(const char *name, const EVP_MD **mdp)
-{
- *mdp = EVP_get_digestbyname(name);
- if (*mdp != NULL)
- return 1;
- BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name);
- return 0;
-}
-
-/* Look through a list of name/value pairs. */
-int opt_pair(const char *name, const OPT_PAIR* pairs, int *result)
-{
- const OPT_PAIR *pp;
-
- for (pp = pairs; pp->name; pp++)
- if (strcmp(pp->name, name) == 0) {
- *result = pp->retval;
- return 1;
- }
- BIO_printf(bio_err, "%s: Value must be one of:\n", prog);
- for (pp = pairs; pp->name; pp++)
- BIO_printf(bio_err, "\t%s\n", pp->name);
- return 0;
-}
-
-/* Parse an int, put it into *result; return 0 on failure, else 1. */
-int opt_int(const char *value, int *result)
-{
- long l;
-
- if (!opt_long(value, &l))
- return 0;
- *result = (int)l;
- if (*result != l) {
- BIO_printf(bio_err, "%s: Value \"%s\" outside integer range\n",
- prog, value);
- return 0;
- }
- return 1;
-}
-
-static void opt_number_error(const char *v)
-{
- size_t i = 0;
- struct strstr_pair_st {
- char *prefix;
- char *name;
- } b[] = {
- {"0x", "a hexadecimal"},
- {"0X", "a hexadecimal"},
- {"0", "an octal"}
- };
-
- for (i = 0; i < OSSL_NELEM(b); i++) {
- if (strncmp(v, b[i].prefix, strlen(b[i].prefix)) == 0) {
- BIO_printf(bio_err,
- "%s: Can't parse \"%s\" as %s number\n",
- prog, v, b[i].name);
- return;
- }
- }
- BIO_printf(bio_err, "%s: Can't parse \"%s\" as a number\n", prog, v);
- return;
-}
-
-/* Parse a long, put it into *result; return 0 on failure, else 1. */
-int opt_long(const char *value, long *result)
-{
- int oerrno = errno;
- long l;
- char *endp;
-
- errno = 0;
- l = strtol(value, &endp, 0);
- if (*endp
- || endp == value
- || ((l == LONG_MAX || l == LONG_MIN) && errno == ERANGE)
- || (l == 0 && errno != 0)) {
- opt_number_error(value);
- errno = oerrno;
- return 0;
- }
- *result = l;
- errno = oerrno;
- return 1;
-}
-
-#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
- defined(INTMAX_MAX) && defined(UINTMAX_MAX)
-
-/* Parse an intmax_t, put it into *result; return 0 on failure, else 1. */
-int opt_imax(const char *value, intmax_t *result)
-{
- int oerrno = errno;
- intmax_t m;
- char *endp;
-
- errno = 0;
- m = strtoimax(value, &endp, 0);
- if (*endp
- || endp == value
- || ((m == INTMAX_MAX || m == INTMAX_MIN) && errno == ERANGE)
- || (m == 0 && errno != 0)) {
- opt_number_error(value);
- errno = oerrno;
- return 0;
- }
- *result = m;
- errno = oerrno;
- return 1;
-}
-
-/* Parse a uintmax_t, put it into *result; return 0 on failure, else 1. */
-int opt_umax(const char *value, uintmax_t *result)
-{
- int oerrno = errno;
- uintmax_t m;
- char *endp;
-
- errno = 0;
- m = strtoumax(value, &endp, 0);
- if (*endp
- || endp == value
- || (m == UINTMAX_MAX && errno == ERANGE)
- || (m == 0 && errno != 0)) {
- opt_number_error(value);
- errno = oerrno;
- return 0;
- }
- *result = m;
- errno = oerrno;
- return 1;
-}
-#endif
-
-/*
- * Parse an unsigned long, put it into *result; return 0 on failure, else 1.
- */
-int opt_ulong(const char *value, unsigned long *result)
-{
- int oerrno = errno;
- char *endptr;
- unsigned long l;
-
- errno = 0;
- l = strtoul(value, &endptr, 0);
- if (*endptr
- || endptr == value
- || ((l == ULONG_MAX) && errno == ERANGE)
- || (l == 0 && errno != 0)) {
- opt_number_error(value);
- errno = oerrno;
- return 0;
- }
- *result = l;
- errno = oerrno;
- return 1;
-}
-
-/*
- * We pass opt as an int but cast it to "enum range" so that all the
- * items in the OPT_V_ENUM enumeration are caught; this makes -Wswitch
- * in gcc do the right thing.
- */
-enum range { OPT_V_ENUM };
-
-int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
-{
- int i;
- ossl_intmax_t t = 0;
- ASN1_OBJECT *otmp;
- X509_PURPOSE *xptmp;
- const X509_VERIFY_PARAM *vtmp;
-
- assert(vpm != NULL);
- assert(opt > OPT_V__FIRST);
- assert(opt < OPT_V__LAST);
-
- switch ((enum range)opt) {
- case OPT_V__FIRST:
- case OPT_V__LAST:
- return 0;
- case OPT_V_POLICY:
- otmp = OBJ_txt2obj(opt_arg(), 0);
- if (otmp == NULL) {
- BIO_printf(bio_err, "%s: Invalid Policy %s\n", prog, opt_arg());
- return 0;
- }
- X509_VERIFY_PARAM_add0_policy(vpm, otmp);
- break;
- case OPT_V_PURPOSE:
- /* purpose name -> purpose index */
- i = X509_PURPOSE_get_by_sname(opt_arg());
- if (i < 0) {
- BIO_printf(bio_err, "%s: Invalid purpose %s\n", prog, opt_arg());
- return 0;
- }
-
- /* purpose index -> purpose object */
- xptmp = X509_PURPOSE_get0(i);
-
- /* purpose object -> purpose value */
- i = X509_PURPOSE_get_id(xptmp);
-
- if (!X509_VERIFY_PARAM_set_purpose(vpm, i)) {
- BIO_printf(bio_err,
- "%s: Internal error setting purpose %s\n",
- prog, opt_arg());
- return 0;
- }
- break;
- case OPT_V_VERIFY_NAME:
- vtmp = X509_VERIFY_PARAM_lookup(opt_arg());
- if (vtmp == NULL) {
- BIO_printf(bio_err, "%s: Invalid verify name %s\n",
- prog, opt_arg());
- return 0;
- }
- X509_VERIFY_PARAM_set1(vpm, vtmp);
- break;
- case OPT_V_VERIFY_DEPTH:
- i = atoi(opt_arg());
- if (i >= 0)
- X509_VERIFY_PARAM_set_depth(vpm, i);
- break;
- case OPT_V_VERIFY_AUTH_LEVEL:
- i = atoi(opt_arg());
- if (i >= 0)
- X509_VERIFY_PARAM_set_auth_level(vpm, i);
- break;
- case OPT_V_ATTIME:
- if (!opt_imax(opt_arg(), &t))
- return 0;
- if (t != (time_t)t) {
- BIO_printf(bio_err, "%s: epoch time out of range %s\n",
- prog, opt_arg());
- return 0;
- }
- X509_VERIFY_PARAM_set_time(vpm, (time_t)t);
- break;
- case OPT_V_VERIFY_HOSTNAME:
- if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0))
- return 0;
- break;
- case OPT_V_VERIFY_EMAIL:
- if (!X509_VERIFY_PARAM_set1_email(vpm, opt_arg(), 0))
- return 0;
- break;
- case OPT_V_VERIFY_IP:
- if (!X509_VERIFY_PARAM_set1_ip_asc(vpm, opt_arg()))
- return 0;
- break;
- case OPT_V_IGNORE_CRITICAL:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_IGNORE_CRITICAL);
- break;
- case OPT_V_ISSUER_CHECKS:
- /* NOP, deprecated */
- break;
- case OPT_V_CRL_CHECK:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CRL_CHECK);
- break;
- case OPT_V_CRL_CHECK_ALL:
- X509_VERIFY_PARAM_set_flags(vpm,
- X509_V_FLAG_CRL_CHECK |
- X509_V_FLAG_CRL_CHECK_ALL);
- break;
- case OPT_V_POLICY_CHECK:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_POLICY_CHECK);
- break;
- case OPT_V_EXPLICIT_POLICY:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXPLICIT_POLICY);
- break;
- case OPT_V_INHIBIT_ANY:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_ANY);
- break;
- case OPT_V_INHIBIT_MAP:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_MAP);
- break;
- case OPT_V_X509_STRICT:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_X509_STRICT);
- break;
- case OPT_V_EXTENDED_CRL:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXTENDED_CRL_SUPPORT);
- break;
- case OPT_V_USE_DELTAS:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_USE_DELTAS);
- break;
- case OPT_V_POLICY_PRINT:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NOTIFY_POLICY);
- break;
- case OPT_V_CHECK_SS_SIG:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CHECK_SS_SIGNATURE);
- break;
- case OPT_V_TRUSTED_FIRST:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_TRUSTED_FIRST);
- break;
- case OPT_V_SUITEB_128_ONLY:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS_ONLY);
- break;
- case OPT_V_SUITEB_128:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS);
- break;
- case OPT_V_SUITEB_192:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_192_LOS);
- break;
- case OPT_V_PARTIAL_CHAIN:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN);
- break;
- case OPT_V_NO_ALT_CHAINS:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_ALT_CHAINS);
- break;
- case OPT_V_NO_CHECK_TIME:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME);
- break;
- case OPT_V_ALLOW_PROXY_CERTS:
- X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_ALLOW_PROXY_CERTS);
- break;
- }
- return 1;
-
-}
-
-/*
- * Parse the next flag (and value if specified), return 0 if done, -1 on
- * error, otherwise the flag's retval.
- */
-int opt_next(void)
-{
- char *p;
- const OPTIONS *o;
- int ival;
- long lval;
- unsigned long ulval;
- ossl_intmax_t imval;
- ossl_uintmax_t umval;
-
- /* Look at current arg; at end of the list? */
- arg = NULL;
- p = argv[opt_index];
- if (p == NULL)
- return 0;
-
- /* If word doesn't start with a -, we're done. */
- if (*p != '-')
- return 0;
-
- /* Hit "--" ? We're done. */
- opt_index++;
- if (strcmp(p, "--") == 0)
- return 0;
-
- /* Allow -nnn and --nnn */
- if (*++p == '-')
- p++;
- flag = p - 1;
-
- /* If we have --flag=foo, snip it off */
- if ((arg = strchr(p, '=')) != NULL)
- *arg++ = '\0';
- for (o = opts; o->name; ++o) {
- /* If not this option, move on to the next one. */
- if (strcmp(p, o->name) != 0)
- continue;
-
- /* If it doesn't take a value, make sure none was given. */
- if (o->valtype == 0 || o->valtype == '-') {
- if (arg) {
- BIO_printf(bio_err,
- "%s: Option -%s does not take a value\n", prog, p);
- return -1;
- }
- return o->retval;
- }
-
- /* Want a value; get the next param if =foo not used. */
- if (arg == NULL) {
- if (argv[opt_index] == NULL) {
- BIO_printf(bio_err,
- "%s: Option -%s needs a value\n", prog, o->name);
- return -1;
- }
- arg = argv[opt_index++];
- }
-
- /* Syntax-check value. */
- switch (o->valtype) {
- default:
- case 's':
- /* Just a string. */
- break;
- case '/':
- if (app_isdir(arg) > 0)
- break;
- BIO_printf(bio_err, "%s: Not a directory: %s\n", prog, arg);
- return -1;
- case '<':
- /* Input file. */
- break;
- case '>':
- /* Output file. */
- break;
- case 'p':
- case 'n':
- if (!opt_int(arg, &ival)
- || (o->valtype == 'p' && ival <= 0)) {
- BIO_printf(bio_err,
- "%s: Non-positive number \"%s\" for -%s\n",
- prog, arg, o->name);
- return -1;
- }
- break;
- case 'M':
- if (!opt_imax(arg, &imval)) {
- BIO_printf(bio_err,
- "%s: Invalid number \"%s\" for -%s\n",
- prog, arg, o->name);
- return -1;
- }
- break;
- case 'U':
- if (!opt_umax(arg, &umval)) {
- BIO_printf(bio_err,
- "%s: Invalid number \"%s\" for -%s\n",
- prog, arg, o->name);
- return -1;
- }
- break;
- case 'l':
- if (!opt_long(arg, &lval)) {
- BIO_printf(bio_err,
- "%s: Invalid number \"%s\" for -%s\n",
- prog, arg, o->name);
- return -1;
- }
- break;
- case 'u':
- if (!opt_ulong(arg, &ulval)) {
- BIO_printf(bio_err,
- "%s: Invalid number \"%s\" for -%s\n",
- prog, arg, o->name);
- return -1;
- }
- break;
- case 'c':
- case 'E':
- case 'F':
- case 'f':
- if (opt_format(arg,
- o->valtype == 'c' ? OPT_FMT_PDS :
- o->valtype == 'E' ? OPT_FMT_PDE :
- o->valtype == 'F' ? OPT_FMT_PEMDER
- : OPT_FMT_ANY, &ival))
- break;
- BIO_printf(bio_err,
- "%s: Invalid format \"%s\" for -%s\n",
- prog, arg, o->name);
- return -1;
- }
-
- /* Return the flag value. */
- return o->retval;
- }
- if (unknown != NULL) {
- dunno = p;
- return unknown->retval;
- }
- BIO_printf(bio_err, "%s: Option unknown option -%s\n", prog, p);
- return -1;
-}
-
-/* Return the most recent flag parameter. */
-char *opt_arg(void)
-{
- return arg;
-}
-
-/* Return the most recent flag. */
-char *opt_flag(void)
-{
- return flag;
-}
-
-/* Return the unknown option. */
-char *opt_unknown(void)
-{
- return dunno;
-}
-
-/* Return the rest of the arguments after parsing flags. */
-char **opt_rest(void)
-{
- return &argv[opt_index];
-}
-
-/* How many items in remaining args? */
-int opt_num_rest(void)
-{
- int i = 0;
- char **pp;
-
- for (pp = opt_rest(); *pp; pp++, i++)
- continue;
- return i;
-}
-
-/* Return a string describing the parameter type. */
-static const char *valtype2param(const OPTIONS *o)
-{
- switch (o->valtype) {
- case 0:
- case '-':
- return "";
- case 's':
- return "val";
- case '/':
- return "dir";
- case '<':
- return "infile";
- case '>':
- return "outfile";
- case 'p':
- return "+int";
- case 'n':
- return "int";
- case 'l':
- return "long";
- case 'u':
- return "ulong";
- case 'E':
- return "PEM|DER|ENGINE";
- case 'F':
- return "PEM|DER";
- case 'f':
- return "format";
- case 'M':
- return "intmax";
- case 'U':
- return "uintmax";
- }
- return "parm";
-}
-
-void opt_help(const OPTIONS *list)
-{
- const OPTIONS *o;
- int i;
- int standard_prolog;
- int width = 5;
- char start[80 + 1];
- char *p;
- const char *help;
-
- /* Starts with its own help message? */
- standard_prolog = list[0].name != OPT_HELP_STR;
-
- /* Find the widest help. */
- for (o = list; o->name; o++) {
- if (o->name == OPT_MORE_STR)
- continue;
- i = 2 + (int)strlen(o->name);
- if (o->valtype != '-')
- i += 1 + strlen(valtype2param(o));
- if (i < MAX_OPT_HELP_WIDTH && i > width)
- width = i;
- assert(i < (int)sizeof(start));
- }
-
- if (standard_prolog)
- BIO_printf(bio_err, "Usage: %s [options]\nValid options are:\n",
- prog);
-
- /* Now let's print. */
- for (o = list; o->name; o++) {
- help = o->helpstr ? o->helpstr : "(No additional info)";
- if (o->name == OPT_HELP_STR) {
- BIO_printf(bio_err, help, prog);
- continue;
- }
-
- /* Pad out prefix */
- memset(start, ' ', sizeof(start) - 1);
- start[sizeof(start) - 1] = '\0';
-
- if (o->name == OPT_MORE_STR) {
- /* Continuation of previous line; pad and print. */
- start[width] = '\0';
- BIO_printf(bio_err, "%s %s\n", start, help);
- continue;
- }
-
- /* Build up the "-flag [param]" part. */
- p = start;
- *p++ = ' ';
- *p++ = '-';
- if (o->name[0])
- p += strlen(strcpy(p, o->name));
- else
- *p++ = '*';
- if (o->valtype != '-') {
- *p++ = ' ';
- p += strlen(strcpy(p, valtype2param(o)));
- }
- *p = ' ';
- if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) {
- *p = '\0';
- BIO_printf(bio_err, "%s\n", start);
- memset(start, ' ', sizeof(start));
- }
- start[width] = '\0';
- BIO_printf(bio_err, "%s %s\n", start, help);
- }
-}
diff --git a/apps/passwd.c b/apps/passwd.c
index af08ccd4ac0f..64b2e76c147a 100644
--- a/apps/passwd.c
+++ b/apps/passwd.c
@@ -1,7 +1,7 @@
/*
* Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -16,13 +16,13 @@
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
-#ifndef OPENSSL_NO_DES
+#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_DEPRECATED_3_0)
# include <openssl/des.h>
#endif
#include <openssl/md5.h>
#include <openssl/sha.h>
-static unsigned const char cov_2char[64] = {
+static const unsigned char cov_2char[64] = {
/* from crypto/des/fcrypt.c */
0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44,
@@ -38,7 +38,6 @@ static const char ascii_dollar[] = { 0x24, 0x00 };
typedef enum {
passwd_unset = 0,
- passwd_crypt,
passwd_md5,
passwd_apr1,
passwd_sha256,
@@ -51,32 +50,43 @@ static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
int reverse, size_t pw_maxlen, passwd_modes mode);
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_IN,
OPT_NOVERIFY, OPT_QUIET, OPT_TABLE, OPT_REVERSE, OPT_APR1,
- OPT_1, OPT_5, OPT_6, OPT_CRYPT, OPT_AIXMD5, OPT_SALT, OPT_STDIN,
- OPT_R_ENUM
+ OPT_1, OPT_5, OPT_6, OPT_AIXMD5, OPT_SALT, OPT_STDIN,
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS passwd_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [password]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Read passwords from file"},
{"noverify", OPT_NOVERIFY, '-',
"Never verify when reading password from terminal"},
+ {"stdin", OPT_STDIN, '-', "Read passwords from stdin"},
+
+ OPT_SECTION("Output"),
{"quiet", OPT_QUIET, '-', "No warnings"},
{"table", OPT_TABLE, '-', "Format output as table"},
{"reverse", OPT_REVERSE, '-', "Switch table columns"},
+
+ OPT_SECTION("Cryptographic"),
{"salt", OPT_SALT, 's', "Use provided salt"},
- {"stdin", OPT_STDIN, '-', "Read passwords from stdin"},
{"6", OPT_6, '-', "SHA512-based password algorithm"},
{"5", OPT_5, '-', "SHA256-based password algorithm"},
{"apr1", OPT_APR1, '-', "MD5-based password algorithm, Apache variant"},
{"1", OPT_1, '-', "MD5-based password algorithm"},
{"aixmd5", OPT_AIXMD5, '-', "AIX MD5-based password algorithm"},
-#ifndef OPENSSL_NO_DES
- {"crypt", OPT_CRYPT, '-', "Standard Unix password algorithm (default)"},
-#endif
+
OPT_R_OPTIONS,
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"password", 0, 0, "Password text to digest (optional)"},
{NULL}
};
@@ -154,13 +164,6 @@ int passwd_main(int argc, char **argv)
goto opthelp;
mode = passwd_aixmd5;
break;
- case OPT_CRYPT:
-#ifndef OPENSSL_NO_DES
- if (mode != passwd_unset)
- goto opthelp;
- mode = passwd_crypt;
-#endif
- break;
case OPT_SALT:
passed_salt = 1;
salt = opt_arg();
@@ -175,11 +178,16 @@ int passwd_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* All remaining arguments are the password text */
argc = opt_num_rest();
argv = opt_rest();
-
if (*argv != NULL) {
if (pw_source_defined)
goto opthelp;
@@ -187,16 +195,14 @@ int passwd_main(int argc, char **argv)
passwds = argv;
}
+ if (!app_RAND_load())
+ goto end;
+
if (mode == passwd_unset) {
/* use default */
- mode = passwd_crypt;
+ mode = passwd_md5;
}
-#ifdef OPENSSL_NO_DES
- if (mode == passwd_crypt)
- goto opthelp;
-#endif
-
if (infile != NULL && in_stdin) {
BIO_printf(bio_err, "%s: Can't combine -in and -stdin\n", prog);
goto end;
@@ -212,9 +218,6 @@ int passwd_main(int argc, char **argv)
goto end;
}
- if (mode == passwd_crypt)
- pw_maxlen = 8;
-
if (passwds == NULL) {
/* no passwords on the command line */
@@ -413,7 +416,7 @@ static char *md5crypt(const char *passwd, const char *magic, const char *salt)
if (!EVP_DigestInit_ex(md2, EVP_md5(), NULL))
goto err;
if (!EVP_DigestUpdate(md2,
- (i & 1) ? (unsigned const char *)passwd : buf,
+ (i & 1) ? (const unsigned char *)passwd : buf,
(i & 1) ? passwd_len : sizeof(buf)))
goto err;
if (i % 3) {
@@ -425,7 +428,7 @@ static char *md5crypt(const char *passwd, const char *magic, const char *salt)
goto err;
}
if (!EVP_DigestUpdate(md2,
- (i & 1) ? buf : (unsigned const char *)passwd,
+ (i & 1) ? buf : (const unsigned char *)passwd,
(i & 1) ? sizeof(buf) : passwd_len))
goto err;
if (!EVP_DigestFinal_ex(md2, buf, NULL))
@@ -515,7 +518,7 @@ static char *shacrypt(const char *passwd, const char *magic, const char *salt)
EVP_MD_CTX *md = NULL, *md2 = NULL;
const EVP_MD *sha = NULL;
size_t passwd_len, salt_len, magic_len;
- unsigned int rounds = 5000; /* Default */
+ unsigned int rounds = ROUNDS_DEFAULT; /* Default */
char rounds_custom = 0;
char *p_bytes = NULL;
char *s_bytes = NULL;
@@ -627,7 +630,7 @@ static char *shacrypt(const char *passwd, const char *magic, const char *salt)
n = passwd_len;
while (n) {
if (!EVP_DigestUpdate(md,
- (n & 1) ? buf : (unsigned const char *)passwd,
+ (n & 1) ? buf : (const unsigned char *)passwd,
(n & 1) ? buf_size : passwd_len))
goto err;
n >>= 1;
@@ -673,7 +676,7 @@ static char *shacrypt(const char *passwd, const char *magic, const char *salt)
if (!EVP_DigestInit_ex(md2, sha, NULL))
goto err;
if (!EVP_DigestUpdate(md2,
- (n & 1) ? (unsigned const char *)p_bytes : buf,
+ (n & 1) ? (const unsigned char *)p_bytes : buf,
(n & 1) ? passwd_len : buf_size))
goto err;
if (n % 3) {
@@ -685,7 +688,7 @@ static char *shacrypt(const char *passwd, const char *magic, const char *salt)
goto err;
}
if (!EVP_DigestUpdate(md2,
- (n & 1) ? buf : (unsigned const char *)p_bytes,
+ (n & 1) ? buf : (const unsigned char *)p_bytes,
(n & 1) ? buf_size : passwd_len))
goto err;
if (!EVP_DigestFinal_ex(md2, buf, NULL))
@@ -785,11 +788,6 @@ static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
size_t saltlen = 0;
size_t i;
-#ifndef OPENSSL_NO_DES
- if (mode == passwd_crypt)
- saltlen = 2;
-#endif /* !OPENSSL_NO_DES */
-
if (mode == passwd_md5 || mode == passwd_apr1 || mode == passwd_aixmd5)
saltlen = 8;
@@ -828,10 +826,6 @@ static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
assert(strlen(passwd) <= pw_maxlen);
/* now compute password hash */
-#ifndef OPENSSL_NO_DES
- if (mode == passwd_crypt)
- hash = DES_crypt(passwd, *salt_p);
-#endif
if (mode == passwd_md5 || mode == passwd_apr1)
hash = md5crypt(passwd, (mode == passwd_md5 ? "1" : "apr1"), *salt_p);
if (mode == passwd_aixmd5)
diff --git a/apps/pkcs12.c b/apps/pkcs12.c
index 8c5d963b8c65..b442d358f8b7 100644
--- a/apps/pkcs12.c
+++ b/apps/pkcs12.c
@@ -1,13 +1,14 @@
/*
- * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/opensslconf.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -17,6 +18,8 @@
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/pkcs12.h>
+#include <openssl/provider.h>
+#include <openssl/kdf.h>
#define NOKEYS 0x1
#define NOCERTS 0x2
@@ -26,7 +29,13 @@
#define PASSWD_BUF_SIZE 2048
+#define WARN_EXPORT(opt) \
+ BIO_printf(bio_err, "Warning: -%s option ignored with -export\n", opt);
+#define WARN_NO_EXPORT(opt) \
+ BIO_printf(bio_err, "Warning: -%s option ignored without -export\n", opt);
+
static int get_cert_chain(X509 *cert, X509_STORE *store,
+ STACK_OF(X509) *untrusted_certs,
STACK_OF(X509) **chain);
int dump_certs_keys_p12(BIO *out, const PKCS12 *p12,
const char *pass, int passlen, int options,
@@ -46,100 +55,131 @@ int cert_load(BIO *in, STACK_OF(X509) *sk);
static int set_pbe(int *ppbe, const char *str);
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_CIPHER, OPT_NOKEYS, OPT_KEYEX, OPT_KEYSIG, OPT_NOCERTS, OPT_CLCERTS,
OPT_CACERTS, OPT_NOOUT, OPT_INFO, OPT_CHAIN, OPT_TWOPASS, OPT_NOMACVER,
- OPT_DESCERT, OPT_EXPORT, OPT_NOITER, OPT_MACITER, OPT_NOMACITER,
- OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE,
- OPT_INKEY, OPT_CERTFILE, OPT_NAME, OPT_CSP, OPT_CANAME,
+#ifndef OPENSSL_NO_DES
+ OPT_DESCERT,
+#endif
+ OPT_EXPORT, OPT_ITER, OPT_NOITER, OPT_MACITER, OPT_NOMACITER,
+ OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_NOENC, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE,
+ OPT_INKEY, OPT_CERTFILE, OPT_UNTRUSTED, OPT_PASSCERTS,
+ OPT_NAME, OPT_CSP, OPT_CANAME,
OPT_IN, OPT_OUT, OPT_PASSIN, OPT_PASSOUT, OPT_PASSWORD, OPT_CAPATH,
- OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_ENGINE,
- OPT_R_ENUM
+ OPT_CAFILE, OPT_CASTORE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, OPT_ENGINE,
+ OPT_R_ENUM, OPT_PROV_ENUM,
+#ifndef OPENSSL_NO_DES
+ OPT_LEGACY_ALG
+#endif
} OPTION_CHOICE;
const OPTIONS pkcs12_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+ {"password", OPT_PASSWORD, 's', "Set PKCS#12 import/export password source"},
+ {"twopass", OPT_TWOPASS, '-', "Separate MAC, encryption passwords"},
{"nokeys", OPT_NOKEYS, '-', "Don't output private keys"},
- {"keyex", OPT_KEYEX, '-', "Set MS key exchange type"},
- {"keysig", OPT_KEYSIG, '-', "Set MS key signature type"},
{"nocerts", OPT_NOCERTS, '-', "Don't output certificates"},
- {"clcerts", OPT_CLCERTS, '-', "Only output client certificates"},
- {"cacerts", OPT_CACERTS, '-', "Only output CA certificates"},
- {"noout", OPT_NOOUT, '-', "Don't output anything, just verify"},
- {"info", OPT_INFO, '-', "Print info about PKCS#12 structure"},
- {"chain", OPT_CHAIN, '-', "Add certificate chain"},
- {"twopass", OPT_TWOPASS, '-', "Separate MAC, encryption passwords"},
- {"nomacver", OPT_NOMACVER, '-', "Don't verify MAC"},
-#ifndef OPENSSL_NO_RC2
- {"descert", OPT_DESCERT, '-',
- "Encrypt output with 3DES (default RC2-40)"},
- {"certpbe", OPT_CERTPBE, 's',
- "Certificate PBE algorithm (default RC2-40)"},
-#else
- {"descert", OPT_DESCERT, '-', "Encrypt output with 3DES (the default)"},
- {"certpbe", OPT_CERTPBE, 's', "Certificate PBE algorithm (default 3DES)"},
+ {"noout", OPT_NOOUT, '-', "Don't output anything, just verify PKCS#12 input"},
+#ifndef OPENSSL_NO_DES
+ {"legacy", OPT_LEGACY_ALG, '-',
+# ifdef OPENSSL_NO_RC2
+ "Use legacy encryption algorithm 3DES_CBC for keys and certs"
+# else
+ "Use legacy encryption: 3DES_CBC for keys, RC2_CBC for certs"
+# endif
+ },
#endif
- {"export", OPT_EXPORT, '-', "Output PKCS12 file"},
- {"noiter", OPT_NOITER, '-', "Don't use encryption iteration"},
- {"maciter", OPT_MACITER, '-', "Use MAC iteration"},
- {"nomaciter", OPT_NOMACITER, '-', "Don't use MAC iteration"},
- {"nomac", OPT_NOMAC, '-', "Don't generate MAC"},
- {"LMK", OPT_LMK, '-',
- "Add local machine keyset attribute to private key"},
- {"nodes", OPT_NODES, '-', "Don't encrypt private keys"},
- {"macalg", OPT_MACALG, 's',
- "Digest algorithm used in MAC (default SHA1)"},
- {"keypbe", OPT_KEYPBE, 's', "Private key PBE algorithm (default 3DES)"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ OPT_PROV_OPTIONS,
OPT_R_OPTIONS,
- {"inkey", OPT_INKEY, 's', "Private key if not infile"},
- {"certfile", OPT_CERTFILE, '<', "Load certs from file"},
- {"name", OPT_NAME, 's', "Use name as friendly name"},
- {"CSP", OPT_CSP, 's', "Microsoft CSP name"},
- {"caname", OPT_CANAME, 's',
- "Use name as CA friendly name (can be repeated)"},
- {"in", OPT_IN, '<', "Input filename"},
- {"out", OPT_OUT, '>', "Output filename"},
- {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
- {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
- {"password", OPT_PASSWORD, 's', "Set import/export password source"},
- {"CApath", OPT_CAPATH, '/', "PEM-format directory of CA's"},
+
+ OPT_SECTION("PKCS#12 import (parsing PKCS#12)"),
+ {"info", OPT_INFO, '-', "Print info about PKCS#12 structure"},
+ {"nomacver", OPT_NOMACVER, '-', "Don't verify integrity MAC"},
+ {"clcerts", OPT_CLCERTS, '-', "Only output client certificates"},
+ {"cacerts", OPT_CACERTS, '-', "Only output CA certificates"},
+ {"", OPT_CIPHER, '-', "Any supported cipher for output encryption"},
+ {"noenc", OPT_NOENC, '-', "Don't encrypt private keys"},
+ {"nodes", OPT_NODES, '-', "Don't encrypt private keys; deprecated"},
+
+ OPT_SECTION("PKCS#12 output (export)"),
+ {"export", OPT_EXPORT, '-', "Create PKCS12 file"},
+ {"inkey", OPT_INKEY, 's', "Private key, else read from -in input file"},
+ {"certfile", OPT_CERTFILE, '<', "Extra certificates for PKCS12 output"},
+ {"passcerts", OPT_PASSCERTS, 's', "Certificate file pass phrase source"},
+ {"chain", OPT_CHAIN, '-', "Build and add certificate chain for EE cert,"},
+ {OPT_MORE_STR, 0, 0,
+ "which is the 1st cert from -in matching the private key (if given)"},
+ {"untrusted", OPT_UNTRUSTED, '<', "Untrusted certificates for chain building"},
{"CAfile", OPT_CAFILE, '<', "PEM-format file of CA's"},
+ {"CApath", OPT_CAPATH, '/', "PEM-format directory of CA's"},
+ {"CAstore", OPT_CASTORE, ':', "URI to store of CA's"},
{"no-CAfile", OPT_NOCAFILE, '-',
"Do not load the default certificates file"},
{"no-CApath", OPT_NOCAPATH, '-',
"Do not load certificates from the default certificates directory"},
- {"", OPT_CIPHER, '-', "Any supported cipher"},
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load certificates from the default certificates store"},
+ {"name", OPT_NAME, 's', "Use name as friendly name"},
+ {"caname", OPT_CANAME, 's',
+ "Use name as CA friendly name (can be repeated)"},
+ {"CSP", OPT_CSP, 's', "Microsoft CSP name"},
+ {"LMK", OPT_LMK, '-',
+ "Add local machine keyset attribute to private key"},
+ {"keyex", OPT_KEYEX, '-', "Set key type to MS key exchange"},
+ {"keysig", OPT_KEYSIG, '-', "Set key type to MS key signature"},
+ {"keypbe", OPT_KEYPBE, 's', "Private key PBE algorithm (default AES-256 CBC)"},
+ {"certpbe", OPT_CERTPBE, 's',
+ "Certificate PBE algorithm (default PBES2 with PBKDF2 and AES-256 CBC)"},
+#ifndef OPENSSL_NO_DES
+ {"descert", OPT_DESCERT, '-',
+ "Encrypt output with 3DES (default PBES2 with PBKDF2 and AES-256 CBC)"},
#endif
+ {"macalg", OPT_MACALG, 's',
+ "Digest algorithm to use in MAC (default SHA256)"},
+ {"iter", OPT_ITER, 'p', "Specify the iteration count for encryption and MAC"},
+ {"noiter", OPT_NOITER, '-', "Don't use encryption iteration"},
+ {"nomaciter", OPT_NOMACITER, '-', "Don't use MAC iteration)"},
+ {"maciter", OPT_MACITER, '-', "Unused, kept for backwards compatibility"},
+ {"nomac", OPT_NOMAC, '-', "Don't generate MAC"},
{NULL}
};
int pkcs12_main(int argc, char **argv)
{
char *infile = NULL, *outfile = NULL, *keyname = NULL, *certfile = NULL;
+ char *untrusted = NULL, *ciphername = NULL, *enc_flag = NULL;
+ char *passcertsarg = NULL, *passcerts = NULL;
char *name = NULL, *csp_name = NULL;
char pass[PASSWD_BUF_SIZE] = "", macpass[PASSWD_BUF_SIZE] = "";
- int export_cert = 0, options = 0, chain = 0, twopass = 0, keytype = 0;
- int iter = PKCS12_DEFAULT_ITER, maciter = PKCS12_DEFAULT_ITER;
-#ifndef OPENSSL_NO_RC2
- int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
-#else
- int cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
+ int export_pkcs12 = 0, options = 0, chain = 0, twopass = 0, keytype = 0;
+#ifndef OPENSSL_NO_DES
+ int use_legacy = 0;
#endif
- int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
+ /* use library defaults for the iter, maciter, cert, and key PBE */
+ int iter = 0, maciter = 0;
+ int cert_pbe = NID_undef;
+ int key_pbe = NID_undef;
int ret = 1, macver = 1, add_lmk = 0, private = 0;
int noprompt = 0;
char *passinarg = NULL, *passoutarg = NULL, *passarg = NULL;
char *passin = NULL, *passout = NULL, *macalg = NULL;
char *cpass = NULL, *mpass = NULL, *badpass = NULL;
- const char *CApath = NULL, *CAfile = NULL, *prog;
- int noCApath = 0, noCAfile = 0;
+ const char *CApath = NULL, *CAfile = NULL, *CAstore = NULL, *prog;
+ int noCApath = 0, noCAfile = 0, noCAstore = 0;
ENGINE *e = NULL;
BIO *in = NULL, *out = NULL;
PKCS12 *p12 = NULL;
STACK_OF(OPENSSL_STRING) *canames = NULL;
- const EVP_CIPHER *enc = EVP_des_ede3_cbc();
+ EVP_CIPHER *default_enc = (EVP_CIPHER *)EVP_aes_256_cbc();
+ EVP_CIPHER *enc = (EVP_CIPHER *)default_enc;
OPTION_CHOICE o;
prog = opt_init(argc, argv, pkcs12_options);
@@ -187,34 +227,47 @@ int pkcs12_main(int argc, char **argv)
case OPT_NOMACVER:
macver = 0;
break;
+#ifndef OPENSSL_NO_DES
case OPT_DESCERT:
cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
break;
+#endif
case OPT_EXPORT:
- export_cert = 1;
+ export_pkcs12 = 1;
+ break;
+ case OPT_NODES:
+ case OPT_NOENC:
+ /*
+ * |enc_flag| stores the name of the option used so it
+ * can be printed if an error message is output.
+ */
+ enc_flag = opt_flag() + 1;
+ enc = NULL;
+ ciphername = NULL;
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &enc))
- goto opthelp;
+ ciphername = opt_unknown();
+ enc_flag = opt_unknown();
+ break;
+ case OPT_ITER:
+ maciter = iter = opt_int_arg();
break;
case OPT_NOITER:
iter = 1;
break;
case OPT_MACITER:
- maciter = PKCS12_DEFAULT_ITER;
+ /* no-op */
break;
case OPT_NOMACITER:
maciter = 1;
break;
case OPT_NOMAC:
+ cert_pbe = -1;
maciter = -1;
break;
case OPT_MACALG:
macalg = opt_arg();
break;
- case OPT_NODES:
- enc = NULL;
- break;
case OPT_CERTPBE:
if (!set_pbe(&cert_pbe, opt_arg()))
goto opthelp;
@@ -233,6 +286,12 @@ int pkcs12_main(int argc, char **argv)
case OPT_CERTFILE:
certfile = opt_arg();
break;
+ case OPT_UNTRUSTED:
+ untrusted = opt_arg();
+ break;
+ case OPT_PASSCERTS:
+ passcertsarg = opt_arg();
+ break;
case OPT_NAME:
name = opt_arg();
break;
@@ -266,28 +325,145 @@ int pkcs12_main(int argc, char **argv)
case OPT_CAPATH:
CApath = opt_arg();
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
case OPT_CAFILE:
CAfile = opt_arg();
break;
case OPT_NOCAPATH:
noCApath = 1;
break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
+#ifndef OPENSSL_NO_DES
+ case OPT_LEGACY_ALG:
+ use_legacy = 1;
+ break;
+#endif
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
+ if (!app_RAND_load())
+ goto end;
+
+ if (ciphername != NULL) {
+ if (!opt_cipher_any(ciphername, &enc))
+ goto opthelp;
+ }
+ if (export_pkcs12) {
+ if ((options & INFO) != 0)
+ WARN_EXPORT("info");
+ if (macver == 0)
+ WARN_EXPORT("nomacver");
+ if ((options & CLCERTS) != 0)
+ WARN_EXPORT("clcerts");
+ if ((options & CACERTS) != 0)
+ WARN_EXPORT("cacerts");
+ if (enc != default_enc)
+ BIO_printf(bio_err,
+ "Warning: output encryption option -%s ignored with -export\n", enc_flag);
+ } else {
+ if (keyname != NULL)
+ WARN_NO_EXPORT("inkey");
+ if (certfile != NULL)
+ WARN_NO_EXPORT("certfile");
+ if (passcertsarg != NULL)
+ WARN_NO_EXPORT("passcerts");
+ if (chain)
+ WARN_NO_EXPORT("chain");
+ if (untrusted != NULL)
+ WARN_NO_EXPORT("untrusted");
+ if (CAfile != NULL)
+ WARN_NO_EXPORT("CAfile");
+ if (CApath != NULL)
+ WARN_NO_EXPORT("CApath");
+ if (CAstore != NULL)
+ WARN_NO_EXPORT("CAstore");
+ if (noCAfile)
+ WARN_NO_EXPORT("no-CAfile");
+ if (noCApath)
+ WARN_NO_EXPORT("no-CApath");
+ if (noCAstore)
+ WARN_NO_EXPORT("no-CAstore");
+ if (name != NULL)
+ WARN_NO_EXPORT("name");
+ if (canames != NULL)
+ WARN_NO_EXPORT("caname");
+ if (csp_name != NULL)
+ WARN_NO_EXPORT("CSP");
+ if (add_lmk)
+ WARN_NO_EXPORT("LMK");
+ if (keytype == KEY_EX)
+ WARN_NO_EXPORT("keyex");
+ if (keytype == KEY_SIG)
+ WARN_NO_EXPORT("keysig");
+ if (key_pbe != NID_undef)
+ WARN_NO_EXPORT("keypbe");
+ if (cert_pbe != NID_undef && cert_pbe != -1)
+ WARN_NO_EXPORT("certpbe and -descert");
+ if (macalg != NULL)
+ WARN_NO_EXPORT("macalg");
+ if (iter != 0)
+ WARN_NO_EXPORT("iter and -noiter");
+ if (maciter == 1)
+ WARN_NO_EXPORT("nomaciter");
+ if (cert_pbe == -1 && maciter == -1)
+ WARN_NO_EXPORT("nomac");
+ }
+#ifndef OPENSSL_NO_DES
+ if (use_legacy) {
+ /* load the legacy provider if not loaded already*/
+ if (!OSSL_PROVIDER_available(app_get0_libctx(), "legacy")) {
+ if (!app_provider_load(app_get0_libctx(), "legacy"))
+ goto end;
+ /* load the default provider explicitly */
+ if (!app_provider_load(app_get0_libctx(), "default"))
+ goto end;
+ }
+ if (cert_pbe == NID_undef) {
+ /* Adapt default algorithm */
+# ifndef OPENSSL_NO_RC2
+ cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
+# else
+ cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
+# endif
+ }
+
+ if (key_pbe == NID_undef)
+ key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
+ if (enc == default_enc)
+ enc = (EVP_CIPHER *)EVP_des_ede3_cbc();
+ if (macalg == NULL)
+ macalg = "sha1";
+ }
+#endif
+
private = 1;
+ if (!app_passwd(passcertsarg, NULL, &passcerts, NULL)) {
+ BIO_printf(bio_err, "Error getting certificate file password\n");
+ goto end;
+ }
+
if (passarg != NULL) {
- if (export_cert)
+ if (export_pkcs12)
passoutarg = passarg;
else
passinarg = passarg;
@@ -299,7 +475,7 @@ int pkcs12_main(int argc, char **argv)
}
if (cpass == NULL) {
- if (export_cert)
+ if (export_pkcs12)
cpass = passout;
else
cpass = passin;
@@ -309,7 +485,7 @@ int pkcs12_main(int argc, char **argv)
mpass = cpass;
noprompt = 1;
if (twopass) {
- if (export_cert)
+ if (export_pkcs12)
BIO_printf(bio_err, "Option -twopass cannot be used with -passout or -password\n");
else
BIO_printf(bio_err, "Option -twopass cannot be used with -passin or -password\n");
@@ -325,7 +501,7 @@ int pkcs12_main(int argc, char **argv)
if (1) {
#ifndef OPENSSL_NO_UI_CONSOLE
if (EVP_read_pw_string(
- macpass, sizeof(macpass), "Enter MAC Password:", export_cert)) {
+ macpass, sizeof(macpass), "Enter MAC Password:", export_pkcs12)) {
BIO_printf(bio_err, "Can't read Password\n");
goto end;
}
@@ -336,96 +512,126 @@ int pkcs12_main(int argc, char **argv)
}
}
- if (export_cert) {
+ if (export_pkcs12) {
EVP_PKEY *key = NULL;
- X509 *ucert = NULL, *x = NULL;
+ X509 *ee_cert = NULL, *x = NULL;
STACK_OF(X509) *certs = NULL;
- const EVP_MD *macmd = NULL;
+ STACK_OF(X509) *untrusted_certs = NULL;
+ EVP_MD *macmd = NULL;
unsigned char *catmp = NULL;
int i;
if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) {
- BIO_printf(bio_err, "Nothing to do!\n");
+ BIO_printf(bio_err, "Nothing to export due to -noout or -nocerts and -nokeys\n");
goto export_end;
}
- if (options & NOCERTS)
+ if ((options & NOCERTS) != 0) {
chain = 0;
+ BIO_printf(bio_err, "Warning: -chain option ignored with -nocerts\n");
+ }
if (!(options & NOKEYS)) {
key = load_key(keyname ? keyname : infile,
- FORMAT_PEM, 1, passin, e, "private key");
+ FORMAT_PEM, 1, passin, e,
+ keyname ?
+ "private key from -inkey file" :
+ "private key from -in file");
if (key == NULL)
goto export_end;
}
- /* Load in all certs in input file */
+ /* Load all certs in input file */
if (!(options & NOCERTS)) {
- if (!load_certs(infile, &certs, FORMAT_PEM, NULL,
- "certificates"))
+ if (!load_certs(infile, 1, &certs, passin,
+ "certificates from -in file"))
goto export_end;
+ if (sk_X509_num(certs) < 1) {
+ BIO_printf(bio_err, "No certificate in -in file %s\n", infile);
+ goto export_end;
+ }
if (key != NULL) {
/* Look for matching private key */
for (i = 0; i < sk_X509_num(certs); i++) {
x = sk_X509_value(certs, i);
if (X509_check_private_key(x, key)) {
- ucert = x;
+ ee_cert = x;
/* Zero keyid and alias */
- X509_keyid_set1(ucert, NULL, 0);
- X509_alias_set1(ucert, NULL, 0);
+ X509_keyid_set1(ee_cert, NULL, 0);
+ X509_alias_set1(ee_cert, NULL, 0);
/* Remove from list */
(void)sk_X509_delete(certs, i);
break;
}
}
- if (ucert == NULL) {
+ if (ee_cert == NULL) {
BIO_printf(bio_err,
- "No certificate matches private key\n");
+ "No cert in -in file '%s' matches private key\n",
+ infile);
goto export_end;
}
}
-
}
- /* Add any more certificates asked for */
- if (certfile != NULL) {
- if (!load_certs(certfile, &certs, FORMAT_PEM, NULL,
- "certificates from certfile"))
+ /* Load any untrusted certificates for chain building */
+ if (untrusted != NULL) {
+ if (!load_certs(untrusted, 0, &untrusted_certs, passcerts,
+ "untrusted certificates"))
goto export_end;
}
- /* If chaining get chain from user cert */
+ /* If chaining get chain from end entity cert */
if (chain) {
int vret;
STACK_OF(X509) *chain2;
X509_STORE *store;
- if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath))
+ X509 *ee_cert_tmp = ee_cert;
+
+ /* Assume the first cert if we haven't got anything else */
+ if (ee_cert_tmp == NULL && certs != NULL)
+ ee_cert_tmp = sk_X509_value(certs, 0);
+
+ if (ee_cert_tmp == NULL) {
+ BIO_printf(bio_err,
+ "No end entity certificate to check with -chain\n");
+ goto export_end;
+ }
+
+ if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore))
== NULL)
goto export_end;
- vret = get_cert_chain(ucert, store, &chain2);
+ vret = get_cert_chain(ee_cert_tmp, store, untrusted_certs, &chain2);
X509_STORE_free(store);
if (vret == X509_V_OK) {
- /* Exclude verified certificate */
- for (i = 1; i < sk_X509_num(chain2); i++)
- sk_X509_push(certs, sk_X509_value(chain2, i));
- /* Free first certificate */
- X509_free(sk_X509_value(chain2, 0));
- sk_X509_free(chain2);
+ int add_certs;
+ /* Remove from chain2 the first (end entity) certificate */
+ X509_free(sk_X509_shift(chain2));
+ /* Add the remaining certs (except for duplicates) */
+ add_certs = X509_add_certs(certs, chain2, X509_ADD_FLAG_UP_REF
+ | X509_ADD_FLAG_NO_DUP);
+ sk_X509_pop_free(chain2, X509_free);
+ if (!add_certs)
+ goto export_end;
} else {
if (vret != X509_V_ERR_UNSPECIFIED)
- BIO_printf(bio_err, "Error %s getting chain.\n",
+ BIO_printf(bio_err, "Error getting chain: %s\n",
X509_verify_cert_error_string(vret));
- else
- ERR_print_errors(bio_err);
goto export_end;
}
}
- /* Add any CA names */
+ /* Add any extra certificates asked for */
+ if (certfile != NULL) {
+ if (!load_certs(certfile, 0, &certs, passcerts,
+ "extra certificates from -certfile"))
+ goto export_end;
+ }
+ /* Add any CA names */
for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) {
catmp = (unsigned char *)sk_OPENSSL_STRING_value(canames, i);
X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
@@ -439,7 +645,7 @@ int pkcs12_main(int argc, char **argv)
if (add_lmk && key != NULL)
EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1);
- if (!noprompt) {
+ if (!noprompt && !(enc == NULL && maciter == -1)) {
/* To avoid bit rot */
if (1) {
#ifndef OPENSSL_NO_UI_CONSOLE
@@ -458,21 +664,27 @@ int pkcs12_main(int argc, char **argv)
if (!twopass)
OPENSSL_strlcpy(macpass, pass, sizeof(macpass));
- p12 = PKCS12_create(cpass, name, key, ucert, certs,
- key_pbe, cert_pbe, iter, -1, keytype);
+ p12 = PKCS12_create_ex(cpass, name, key, ee_cert, certs,
+ key_pbe, cert_pbe, iter, -1, keytype,
+ app_get0_libctx(), app_get0_propq());
- if (!p12) {
- ERR_print_errors(bio_err);
+ if (p12 == NULL) {
+ BIO_printf(bio_err, "Error creating PKCS12 structure for %s\n",
+ outfile);
goto export_end;
}
- if (macalg) {
+ if (macalg != NULL) {
if (!opt_md(macalg, &macmd))
goto opthelp;
}
if (maciter != -1)
- PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd);
+ if (!PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd)) {
+ BIO_printf(bio_err, "Error creating PKCS12 MAC; no PKCS12KDF support?\n");
+ BIO_printf(bio_err, "Use -nomac if MAC not required and PKCS12KDF support not available.\n");
+ goto export_end;
+ }
assert(private);
@@ -487,9 +699,12 @@ int pkcs12_main(int argc, char **argv)
export_end:
EVP_PKEY_free(key);
+ EVP_MD_free(macmd);
sk_X509_pop_free(certs, X509_free);
- X509_free(ucert);
+ sk_X509_pop_free(untrusted_certs, X509_free);
+ X509_free(ee_cert);
+ ERR_print_errors(bio_err);
goto end;
}
@@ -501,7 +716,12 @@ int pkcs12_main(int argc, char **argv)
if (out == NULL)
goto end;
- if ((p12 = d2i_PKCS12_bio(in, NULL)) == NULL) {
+ p12 = PKCS12_init_ex(NID_pkcs7_data, app_get0_libctx(), app_get0_propq());
+ if (p12 == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if ((p12 = d2i_PKCS12_bio(in, &p12)) == NULL) {
ERR_print_errors(bio_err);
goto end;
}
@@ -544,6 +764,16 @@ int pkcs12_main(int argc, char **argv)
tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L);
}
if (macver) {
+ EVP_KDF *pkcs12kdf;
+
+ pkcs12kdf = EVP_KDF_fetch(app_get0_libctx(), "PKCS12KDF",
+ app_get0_propq());
+ if (pkcs12kdf == NULL) {
+ BIO_printf(bio_err, "Error verifying PKCS12 MAC; no PKCS12KDF support.\n");
+ BIO_printf(bio_err, "Use -nomacver if MAC verification is not required.\n");
+ goto end;
+ }
+ EVP_KDF_free(pkcs12kdf);
/* If we enter empty password try no password first */
if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
/* If mac and crypto pass the same set it to NULL too */
@@ -557,6 +787,14 @@ int pkcs12_main(int argc, char **argv)
*/
unsigned char *utmp;
int utmplen;
+ unsigned long err = ERR_peek_error();
+
+ if (ERR_GET_LIB(err) == ERR_LIB_PKCS12
+ && ERR_GET_REASON(err) == PKCS12_R_MAC_ABSENT) {
+ BIO_printf(bio_err, "Warning: MAC is absent!\n");
+ goto dump;
+ }
+
utmp = OPENSSL_asc2uni(mpass, -1, NULL, &utmplen);
if (utmp == NULL)
goto end;
@@ -574,6 +812,7 @@ int pkcs12_main(int argc, char **argv)
}
}
+ dump:
assert(private);
if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout, enc)) {
BIO_printf(bio_err, "Error outputting keys and certificates\n");
@@ -588,6 +827,7 @@ int pkcs12_main(int argc, char **argv)
BIO_free_all(out);
sk_OPENSSL_STRING_free(canames);
OPENSSL_free(badpass);
+ OPENSSL_free(passcerts);
OPENSSL_free(passin);
OPENSSL_free(passout);
return ret;
@@ -725,6 +965,16 @@ int dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bag,
X509_free(x509);
break;
+ case NID_secretBag:
+ if (options & INFO)
+ BIO_printf(bio_err, "Secret bag\n");
+ print_attribs(out, attrs, "Bag Attributes");
+ BIO_printf(bio_err, "Bag Type: ");
+ i2a_ASN1_OBJECT(bio_err, PKCS12_SAFEBAG_get0_bag_type(bag));
+ BIO_printf(bio_err, "\nBag Value: ");
+ print_attribute(out, PKCS12_SAFEBAG_get0_bag_obj(bag));
+ return 1;
+
case NID_safeContentsBag:
if (options & INFO)
BIO_printf(bio_err, "Safe Contents bag\n");
@@ -744,18 +994,19 @@ int dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bag,
/* Given a single certificate return a verified chain or NULL if error */
static int get_cert_chain(X509 *cert, X509_STORE *store,
+ STACK_OF(X509) *untrusted_certs,
STACK_OF(X509) **chain)
{
X509_STORE_CTX *store_ctx = NULL;
STACK_OF(X509) *chn = NULL;
int i = 0;
- store_ctx = X509_STORE_CTX_new();
+ store_ctx = X509_STORE_CTX_new_ex(app_get0_libctx(), app_get0_propq());
if (store_ctx == NULL) {
i = X509_V_ERR_UNSPECIFIED;
goto end;
}
- if (!X509_STORE_CTX_init(store_ctx, store, cert, NULL)) {
+ if (!X509_STORE_CTX_init(store_ctx, store, cert, untrusted_certs)) {
i = X509_V_ERR_UNSPECIFIED;
goto end;
}
@@ -863,12 +1114,13 @@ static int alg_print(const X509_ALGOR *alg)
int cert_load(BIO *in, STACK_OF(X509) *sk)
{
- int ret;
+ int ret = 0;
X509 *cert;
- ret = 0;
+
while ((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
ret = 1;
- sk_X509_push(sk, cert);
+ if (!sk_X509_push(sk, cert))
+ return 0;
}
if (ret)
ERR_clear_error();
@@ -889,6 +1141,11 @@ void print_attribute(BIO *out, const ASN1_TYPE *av)
OPENSSL_free(value);
break;
+ case V_ASN1_UTF8STRING:
+ BIO_printf(out, "%.*s\n", av->value.utf8string->length,
+ av->value.utf8string->data);
+ break;
+
case V_ASN1_OCTET_STRING:
hex_prin(out, av->value.octet_string->data,
av->value.octet_string->length);
diff --git a/apps/pkcs7.c b/apps/pkcs7.c
index c3e9f5c69260..ba11e8151ae9 100644
--- a/apps/pkcs7.c
+++ b/apps/pkcs7.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -21,15 +21,24 @@
#include <openssl/pem.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOOUT,
- OPT_TEXT, OPT_PRINT, OPT_PRINT_CERTS, OPT_ENGINE
+ OPT_TEXT, OPT_PRINT, OPT_PRINT_CERTS, OPT_ENGINE,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS pkcs7_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file"},
+ {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
+
+ OPT_SECTION("Output"),
{"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
{"out", OPT_OUT, '>', "Output file"},
{"noout", OPT_NOOUT, '-', "Don't output encoded data"},
@@ -37,21 +46,21 @@ const OPTIONS pkcs7_options[] = {
{"print", OPT_PRINT, '-', "Print out all fields of the PKCS7 structure"},
{"print_certs", OPT_PRINT_CERTS, '-',
"Print_certs print any certs or crl in the input"},
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
+
+ OPT_PROV_OPTIONS,
{NULL}
};
int pkcs7_main(int argc, char **argv)
{
ENGINE *e = NULL;
- PKCS7 *p7 = NULL;
+ PKCS7 *p7 = NULL, *p7i;
BIO *in = NULL, *out = NULL;
int informat = FORMAT_PEM, outformat = FORMAT_PEM;
char *infile = NULL, *outfile = NULL, *prog;
int i, print_certs = 0, text = 0, noout = 0, p7_print = 0, ret = 1;
OPTION_CHOICE o;
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
prog = opt_init(argc, argv, pkcs7_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -94,8 +103,14 @@ int pkcs7_main(int argc, char **argv)
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
@@ -104,11 +119,18 @@ int pkcs7_main(int argc, char **argv)
if (in == NULL)
goto end;
+ p7 = PKCS7_new_ex(libctx, app_get0_propq());
+ if (p7 == NULL) {
+ BIO_printf(bio_err, "unable to allocate PKCS7 object\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
if (informat == FORMAT_ASN1)
- p7 = d2i_PKCS7_bio(in, NULL);
+ p7i = d2i_PKCS7_bio(in, &p7);
else
- p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
- if (p7 == NULL) {
+ p7i = PEM_read_bio_PKCS7(in, &p7, NULL, NULL);
+ if (p7i == NULL) {
BIO_printf(bio_err, "unable to load PKCS7 object\n");
ERR_print_errors(bio_err);
goto end;
diff --git a/apps/pkcs8.c b/apps/pkcs8.c
index 205536560ac1..6b09b909eb7a 100644
--- a/apps/pkcs8.c
+++ b/apps/pkcs8.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -18,7 +18,7 @@
#include <openssl/pkcs12.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT,
OPT_TOPK8, OPT_NOITER, OPT_NOCRYPT,
#ifndef OPENSSL_NO_SCRYPT
@@ -26,35 +26,44 @@ typedef enum OPTION_choice {
#endif
OPT_V2, OPT_V1, OPT_V2PRF, OPT_ITER, OPT_PASSIN, OPT_PASSOUT,
OPT_TRADITIONAL,
- OPT_R_ENUM
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS pkcs8_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'F', "Input format (DER or PEM)"},
- {"outform", OPT_OUTFORM, 'F', "Output format (DER or PEM)"},
- {"in", OPT_IN, '<', "Input file"},
- {"out", OPT_OUT, '>', "Output file"},
- {"topk8", OPT_TOPK8, '-', "Output PKCS8 file"},
- {"noiter", OPT_NOITER, '-', "Use 1 as iteration count"},
- {"nocrypt", OPT_NOCRYPT, '-', "Use or expect unencrypted private key"},
- OPT_R_OPTIONS,
- {"v2", OPT_V2, 's', "Use PKCS#5 v2.0 and cipher"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
{"v1", OPT_V1, 's', "Use PKCS#5 v1.5 and cipher"},
+ {"v2", OPT_V2, 's', "Use PKCS#5 v2.0 and cipher"},
{"v2prf", OPT_V2PRF, 's', "Set the PRF algorithm to use with PKCS#5 v2.0"},
- {"iter", OPT_ITER, 'p', "Specify the iteration count"},
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, '<', "Input file"},
+ {"inform", OPT_INFORM, 'F', "Input format (DER or PEM)"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"nocrypt", OPT_NOCRYPT, '-', "Use or expect unencrypted private key"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'F', "Output format (DER or PEM)"},
+ {"topk8", OPT_TOPK8, '-', "Output PKCS8 file"},
{"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
{"traditional", OPT_TRADITIONAL, '-', "use traditional format private key"},
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
+ {"iter", OPT_ITER, 'p', "Specify the iteration count"},
+ {"noiter", OPT_NOITER, '-', "Use 1 as iteration count"},
+
#ifndef OPENSSL_NO_SCRYPT
+ OPT_SECTION("Scrypt"),
{"scrypt", OPT_SCRYPT, '-', "Use scrypt algorithm"},
{"scrypt_N", OPT_SCRYPT_N, 's', "Set scrypt N parameter"},
{"scrypt_r", OPT_SCRYPT_R, 's', "Set scrypt r parameter"},
{"scrypt_p", OPT_SCRYPT_P, 's', "Set scrypt p parameter"},
#endif
+
+ OPT_R_OPTIONS,
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -65,8 +74,8 @@ int pkcs8_main(int argc, char **argv)
EVP_PKEY *pkey = NULL;
PKCS8_PRIV_KEY_INFO *p8inf = NULL;
X509_SIG *p8 = NULL;
- const EVP_CIPHER *cipher = NULL;
- char *infile = NULL, *outfile = NULL;
+ EVP_CIPHER *cipher = NULL;
+ char *infile = NULL, *outfile = NULL, *ciphername = NULL;
char *passinarg = NULL, *passoutarg = NULL, *prog;
#ifndef OPENSSL_NO_UI_CONSOLE
char pass[APP_PASS_LEN];
@@ -74,7 +83,7 @@ int pkcs8_main(int argc, char **argv)
char *passin = NULL, *passout = NULL, *p8pass = NULL;
OPTION_CHOICE o;
int nocrypt = 0, ret = 1, iter = PKCS12_DEFAULT_ITER;
- int informat = FORMAT_PEM, outformat = FORMAT_PEM, topk8 = 0, pbe_nid = -1;
+ int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, topk8 = 0, pbe_nid = -1;
int private = 0, traditional = 0;
#ifndef OPENSSL_NO_SCRYPT
long scrypt_N = 0, scrypt_r = 0, scrypt_p = 0;
@@ -119,12 +128,15 @@ int pkcs8_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_TRADITIONAL:
traditional = 1;
break;
case OPT_V2:
- if (!opt_cipher(opt_arg(), &cipher))
- goto opthelp;
+ ciphername = opt_arg();
break;
case OPT_V1:
pbe_nid = OBJ_txt2nid(opt_arg());
@@ -142,11 +154,10 @@ int pkcs8_main(int argc, char **argv)
goto opthelp;
}
if (cipher == NULL)
- cipher = EVP_aes_256_cbc();
+ cipher = (EVP_CIPHER *)EVP_aes_256_cbc();
break;
case OPT_ITER:
- if (!opt_int(opt_arg(), &iter))
- goto opthelp;
+ iter = opt_int_arg();
break;
case OPT_PASSIN:
passinarg = opt_arg();
@@ -163,7 +174,7 @@ int pkcs8_main(int argc, char **argv)
scrypt_r = 8;
scrypt_p = 1;
if (cipher == NULL)
- cipher = EVP_aes_256_cbc();
+ cipher = (EVP_CIPHER *)EVP_aes_256_cbc();
break;
case OPT_SCRYPT_N:
if (!opt_long(opt_arg(), &scrypt_N) || scrypt_N <= 0)
@@ -180,11 +191,20 @@ int pkcs8_main(int argc, char **argv)
#endif
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
private = 1;
+ if (!app_RAND_load())
+ goto end;
+
+ if (ciphername != NULL) {
+ if (!opt_cipher(ciphername, &cipher))
+ goto opthelp;
+ }
if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
BIO_printf(bio_err, "Error getting passwords\n");
@@ -192,9 +212,10 @@ int pkcs8_main(int argc, char **argv)
}
if ((pbe_nid == -1) && cipher == NULL)
- cipher = EVP_aes_256_cbc();
+ cipher = (EVP_CIPHER *)EVP_aes_256_cbc();
- in = bio_open_default(infile, 'r', informat);
+ in = bio_open_default(infile, 'r',
+ informat == FORMAT_UNDEF ? FORMAT_PEM : informat);
if (in == NULL)
goto end;
out = bio_open_owner(outfile, outformat, private);
@@ -278,7 +299,7 @@ int pkcs8_main(int argc, char **argv)
}
if (nocrypt) {
- if (informat == FORMAT_PEM) {
+ if (informat == FORMAT_PEM || informat == FORMAT_UNDEF) {
p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL);
} else if (informat == FORMAT_ASN1) {
p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL);
@@ -287,7 +308,7 @@ int pkcs8_main(int argc, char **argv)
goto end;
}
} else {
- if (informat == FORMAT_PEM) {
+ if (informat == FORMAT_PEM || informat == FORMAT_UNDEF) {
p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL);
} else if (informat == FORMAT_ASN1) {
p8 = d2i_PKCS8_bio(in, NULL);
@@ -349,6 +370,7 @@ int pkcs8_main(int argc, char **argv)
X509_SIG_free(p8);
PKCS8_PRIV_KEY_INFO_free(p8inf);
EVP_PKEY_free(pkey);
+ EVP_CIPHER_free(cipher);
release_engine(e);
BIO_free_all(out);
BIO_free(in);
diff --git a/apps/pkey.c b/apps/pkey.c
index 0dd5590bdc0b..196678533c1d 100644
--- a/apps/pkey.c
+++ b/apps/pkey.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,54 +11,77 @@
#include <string.h>
#include "apps.h"
#include "progs.h"
+#include "ec_common.h"
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/evp.h>
+#include <openssl/core_names.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_INFORM, OPT_OUTFORM, OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE,
OPT_IN, OPT_OUT, OPT_PUBIN, OPT_PUBOUT, OPT_TEXT_PUB,
- OPT_TEXT, OPT_NOOUT, OPT_MD, OPT_TRADITIONAL, OPT_CHECK, OPT_PUB_CHECK
+ OPT_TEXT, OPT_NOOUT, OPT_CIPHER, OPT_TRADITIONAL, OPT_CHECK, OPT_PUB_CHECK,
+ OPT_EC_PARAM_ENC, OPT_EC_CONV_FORM,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS pkey_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'f', "Input format (DER or PEM)"},
- {"outform", OPT_OUTFORM, 'F', "Output format (DER or PEM)"},
- {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
- {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
- {"in", OPT_IN, 's', "Input key"},
- {"out", OPT_OUT, '>', "Output file"},
- {"pubin", OPT_PUBIN, '-',
- "Read public key from input (default is private key)"},
- {"pubout", OPT_PUBOUT, '-', "Output public key, not private"},
- {"text_pub", OPT_TEXT_PUB, '-', "Only output public key components"},
- {"text", OPT_TEXT, '-', "Output in plaintext as well"},
- {"noout", OPT_NOOUT, '-', "Don't output the key"},
- {"", OPT_MD, '-', "Any supported cipher"},
- {"traditional", OPT_TRADITIONAL, '-',
- "Use traditional format for private keys"},
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
+ OPT_PROV_OPTIONS,
+
{"check", OPT_CHECK, '-', "Check key consistency"},
{"pubcheck", OPT_PUB_CHECK, '-', "Check public key consistency"},
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, 's', "Input key"},
+ {"inform", OPT_INFORM, 'f',
+ "Key input format (ENGINE, other values ignored)"},
+ {"passin", OPT_PASSIN, 's', "Key input pass phrase source"},
+ {"pubin", OPT_PUBIN, '-',
+ "Read only public components from key input"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file for encoded and/or text output"},
+ {"outform", OPT_OUTFORM, 'F', "Output encoding format (DER or PEM)"},
+ {"", OPT_CIPHER, '-', "Any supported cipher to be used for encryption"},
+ {"passout", OPT_PASSOUT, 's', "Output PEM file pass phrase source"},
+ {"traditional", OPT_TRADITIONAL, '-',
+ "Use traditional format for private key PEM output"},
+ {"pubout", OPT_PUBOUT, '-', "Restrict encoded output to public components"},
+ {"noout", OPT_NOOUT, '-', "Do not output the key in encoded form"},
+ {"text", OPT_TEXT, '-', "Output key components in plaintext"},
+ {"text_pub", OPT_TEXT_PUB, '-',
+ "Output only public key components in text form"},
+ {"ec_conv_form", OPT_EC_CONV_FORM, 's',
+ "Specifies the EC point conversion form in the encoding"},
+ {"ec_param_enc", OPT_EC_PARAM_ENC, 's',
+ "Specifies the way the EC parameters are encoded"},
+
{NULL}
};
int pkey_main(int argc, char **argv)
{
- BIO *in = NULL, *out = NULL;
+ BIO *out = NULL;
ENGINE *e = NULL;
EVP_PKEY *pkey = NULL;
- const EVP_CIPHER *cipher = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ EVP_CIPHER *cipher = NULL;
char *infile = NULL, *outfile = NULL, *passin = NULL, *passout = NULL;
- char *passinarg = NULL, *passoutarg = NULL, *prog;
+ char *passinarg = NULL, *passoutarg = NULL, *ciphername = NULL, *prog;
OPTION_CHOICE o;
- int informat = FORMAT_PEM, outformat = FORMAT_PEM;
- int pubin = 0, pubout = 0, pubtext = 0, text = 0, noout = 0, ret = 1;
+ int informat = FORMAT_UNDEF, outformat = FORMAT_PEM;
+ int pubin = 0, pubout = 0, text_pub = 0, text = 0, noout = 0, ret = 1;
int private = 0, traditional = 0, check = 0, pub_check = 0;
+#ifndef OPENSSL_NO_EC
+ char *asn1_encoding = NULL;
+ char *point_format = NULL;
+#endif
prog = opt_init(argc, argv, pkey_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -96,13 +119,13 @@ int pkey_main(int argc, char **argv)
outfile = opt_arg();
break;
case OPT_PUBIN:
- pubin = pubout = pubtext = 1;
+ pubin = pubout = 1;
break;
case OPT_PUBOUT:
pubout = 1;
break;
case OPT_TEXT_PUB:
- pubtext = text = 1;
+ text_pub = 1;
break;
case OPT_TEXT:
text = 1;
@@ -119,19 +142,69 @@ int pkey_main(int argc, char **argv)
case OPT_PUB_CHECK:
pub_check = 1;
break;
- case OPT_MD:
- if (!opt_cipher(opt_unknown(), &cipher))
+ case OPT_CIPHER:
+ ciphername = opt_unknown();
+ break;
+ case OPT_EC_CONV_FORM:
+#ifdef OPENSSL_NO_EC
+ goto opthelp;
+#else
+ point_format = opt_arg();
+ if (!opt_string(point_format, point_format_options))
goto opthelp;
+ break;
+#endif
+ case OPT_EC_PARAM_ENC:
+#ifdef OPENSSL_NO_EC
+ goto opthelp;
+#else
+ asn1_encoding = opt_arg();
+ if (!opt_string(asn1_encoding, asn1_encoding_options))
+ goto opthelp;
+ break;
+#endif
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
- private = !noout && !pubout ? 1 : 0;
- if (text && !pubtext)
- private = 1;
+ if (text && text_pub)
+ BIO_printf(bio_err,
+ "Warning: The -text option is ignored with -text_pub\n");
+ if (traditional && (noout || outformat != FORMAT_PEM))
+ BIO_printf(bio_err,
+ "Warning: The -traditional is ignored since there is no PEM output\n");
+
+ /* -pubout and -text is the same as -text_pub */
+ if (!text_pub && pubout && text) {
+ text = 0;
+ text_pub = 1;
+ }
+
+ private = (!noout && !pubout) || (text && !text_pub);
+ if (ciphername != NULL) {
+ if (!opt_cipher(ciphername, &cipher))
+ goto opthelp;
+ }
+ if (cipher == NULL) {
+ if (passoutarg != NULL)
+ BIO_printf(bio_err,
+ "Warning: The -passout option is ignored without a cipher option\n");
+ } else {
+ if (noout || outformat != FORMAT_PEM) {
+ BIO_printf(bio_err,
+ "Error: Cipher options are supported only for PEM output\n");
+ goto end;
+ }
+ }
if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
BIO_printf(bio_err, "Error getting passwords\n");
goto end;
@@ -148,9 +221,28 @@ int pkey_main(int argc, char **argv)
if (pkey == NULL)
goto end;
+#ifndef OPENSSL_NO_EC
+ if (asn1_encoding != NULL || point_format != NULL) {
+ OSSL_PARAM params[3], *p = params;
+
+ if (!EVP_PKEY_is_a(pkey, "EC"))
+ goto end;
+
+ if (asn1_encoding != NULL)
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING,
+ asn1_encoding, 0);
+ if (point_format != NULL)
+ *p++ = OSSL_PARAM_construct_utf8_string(
+ OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
+ point_format, 0);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_PKEY_set_params(pkey, params) <= 0)
+ goto end;
+ }
+#endif
+
if (check || pub_check) {
int r;
- EVP_PKEY_CTX *ctx;
ctx = EVP_PKEY_CTX_new(pkey, e);
if (ctx == NULL) {
@@ -158,7 +250,7 @@ int pkey_main(int argc, char **argv)
goto end;
}
- if (check)
+ if (check && !pubin)
r = EVP_PKEY_check(ctx);
else
r = EVP_PKEY_public_check(ctx);
@@ -170,17 +262,10 @@ int pkey_main(int argc, char **argv)
* Note: at least for RSA keys if this function returns
* -1, there will be no error reasons.
*/
- unsigned long err;
-
- BIO_printf(out, "Key is invalid\n");
-
- while ((err = ERR_peek_error()) != 0) {
- BIO_printf(out, "Detailed error: %s\n",
- ERR_reason_error_string(err));
- ERR_get_error(); /* remove err from error stack */
- }
+ BIO_printf(bio_err, "Key is invalid\n");
+ ERR_print_errors(bio_err);
+ goto end;
}
- EVP_PKEY_CTX_free(ctx);
}
if (!noout) {
@@ -202,6 +287,11 @@ int pkey_main(int argc, char **argv)
}
}
} else if (outformat == FORMAT_ASN1) {
+ if (text || text_pub) {
+ BIO_printf(bio_err,
+ "Error: Text output cannot be combined with DER output\n");
+ goto end;
+ }
if (pubout) {
if (!i2d_PUBKEY_bio(out, pkey))
goto end;
@@ -216,15 +306,13 @@ int pkey_main(int argc, char **argv)
}
}
- if (text) {
- if (pubtext) {
- if (EVP_PKEY_print_public(out, pkey, 0, NULL) <= 0)
- goto end;
- } else {
- assert(private);
- if (EVP_PKEY_print_private(out, pkey, 0, NULL) <= 0)
- goto end;
- }
+ if (text_pub) {
+ if (EVP_PKEY_print_public(out, pkey, 0, NULL) <= 0)
+ goto end;
+ } else if (text) {
+ assert(private);
+ if (EVP_PKEY_print_private(out, pkey, 0, NULL) <= 0)
+ goto end;
}
ret = 0;
@@ -232,10 +320,11 @@ int pkey_main(int argc, char **argv)
end:
if (ret != 0)
ERR_print_errors(bio_err);
+ EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
+ EVP_CIPHER_free(cipher);
release_engine(e);
BIO_free_all(out);
- BIO_free(in);
OPENSSL_free(passin);
OPENSSL_free(passout);
diff --git a/apps/pkeyparam.c b/apps/pkeyparam.c
index 41c3f532b345..b02882ccc296 100644
--- a/apps/pkeyparam.c
+++ b/apps/pkeyparam.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include "apps.h"
#include "progs.h"
#include <openssl/pem.h>
@@ -16,21 +17,29 @@
#include <openssl/evp.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_IN, OPT_OUT, OPT_TEXT, OPT_NOOUT,
- OPT_ENGINE, OPT_CHECK
+ OPT_ENGINE, OPT_CHECK,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS pkeyparam_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"in", OPT_IN, '<', "Input file"},
- {"out", OPT_OUT, '>', "Output file"},
- {"text", OPT_TEXT, '-', "Print parameters as text"},
- {"noout", OPT_NOOUT, '-', "Don't output encoded parameters"},
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
{"check", OPT_CHECK, '-', "Check key param consistency"},
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, '<', "Input file"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"text", OPT_TEXT, '-', "Print parameters as text"},
+ {"noout", OPT_NOOUT, '-', "Don't output encoded parameters"},
+
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -39,7 +48,8 @@ int pkeyparam_main(int argc, char **argv)
ENGINE *e = NULL;
BIO *in = NULL, *out = NULL;
EVP_PKEY *pkey = NULL;
- int text = 0, noout = 0, ret = 1, check = 0;
+ EVP_PKEY_CTX *ctx = NULL;
+ int text = 0, noout = 0, ret = EXIT_FAILURE, check = 0, r;
OPTION_CHOICE o;
char *infile = NULL, *outfile = NULL, *prog;
@@ -73,8 +83,14 @@ int pkeyparam_main(int argc, char **argv)
case OPT_CHECK:
check = 1;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
@@ -85,7 +101,8 @@ int pkeyparam_main(int argc, char **argv)
out = bio_open_default(outfile, 'w', FORMAT_PEM);
if (out == NULL)
goto end;
- pkey = PEM_read_bio_Parameters(in, NULL);
+ pkey = PEM_read_bio_Parameters_ex(in, NULL, app_get0_libctx(),
+ app_get0_propq());
if (pkey == NULL) {
BIO_printf(bio_err, "Error reading parameters\n");
ERR_print_errors(bio_err);
@@ -93,10 +110,11 @@ int pkeyparam_main(int argc, char **argv)
}
if (check) {
- int r;
- EVP_PKEY_CTX *ctx;
-
- ctx = EVP_PKEY_CTX_new(pkey, e);
+ if (e == NULL)
+ ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), pkey,
+ app_get0_propq());
+ else
+ ctx = EVP_PKEY_CTX_new(pkey, e);
if (ctx == NULL) {
ERR_print_errors(bio_err);
goto end;
@@ -111,17 +129,10 @@ int pkeyparam_main(int argc, char **argv)
* Note: at least for RSA keys if this function returns
* -1, there will be no error reasons.
*/
- unsigned long err;
-
- BIO_printf(out, "Parameters are invalid\n");
-
- while ((err = ERR_peek_error()) != 0) {
- BIO_printf(out, "Detailed error: %s\n",
- ERR_reason_error_string(err));
- ERR_get_error(); /* remove err from error stack */
- }
+ BIO_printf(bio_err, "Parameters are invalid\n");
+ ERR_print_errors(bio_err);
+ goto end;
}
- EVP_PKEY_CTX_free(ctx);
}
if (!noout)
@@ -130,9 +141,10 @@ int pkeyparam_main(int argc, char **argv)
if (text)
EVP_PKEY_print_params(out, pkey, 0, NULL);
- ret = 0;
+ ret = EXIT_SUCCESS;
end:
+ EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
release_engine(e);
BIO_free_all(out);
diff --git a/apps/pkeyutl.c b/apps/pkeyutl.c
index 831e14dab4b3..518a74166153 100644
--- a/apps/pkeyutl.c
+++ b/apps/pkeyutl.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,6 +13,7 @@
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
+#include <sys/stat.h>
#define KEY_NONE 0
#define KEY_PRIVKEY 1
@@ -22,7 +23,9 @@
static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
const char *keyfile, int keyform, int key_type,
char *passinarg, int pkey_op, ENGINE *e,
- const int impl);
+ const int impl, int rawin, EVP_PKEY **ppkey,
+ EVP_MD_CTX *mctx, const char *digestname,
+ OSSL_LIB_CTX *libctx, const char *propq);
static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
ENGINE *e);
@@ -31,69 +34,100 @@ static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
unsigned char *out, size_t *poutlen,
const unsigned char *in, size_t inlen);
+static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
+ EVP_PKEY *pkey, BIO *in,
+ int filesize, unsigned char *sig, int siglen,
+ unsigned char **out, size_t *poutlen);
+
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_ENGINE, OPT_ENGINE_IMPL, OPT_IN, OPT_OUT,
OPT_PUBIN, OPT_CERTIN, OPT_ASN1PARSE, OPT_HEXDUMP, OPT_SIGN,
OPT_VERIFY, OPT_VERIFYRECOVER, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT,
OPT_DERIVE, OPT_SIGFILE, OPT_INKEY, OPT_PEERKEY, OPT_PASSIN,
- OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_KDF, OPT_KDFLEN,
- OPT_R_ENUM
+ OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_PKEYOPT_PASSIN, OPT_KDF,
+ OPT_KDFLEN, OPT_R_ENUM, OPT_PROV_ENUM,
+ OPT_CONFIG,
+ OPT_RAWIN, OPT_DIGEST
} OPTION_CHOICE;
const OPTIONS pkeyutl_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+ {"engine_impl", OPT_ENGINE_IMPL, '-',
+ "Also use engine given by -engine for crypto operations"},
+#endif
+ {"sign", OPT_SIGN, '-', "Sign input data with private key"},
+ {"verify", OPT_VERIFY, '-', "Verify with public key"},
+ {"encrypt", OPT_ENCRYPT, '-', "Encrypt input data with public key"},
+ {"decrypt", OPT_DECRYPT, '-', "Decrypt input data with private key"},
+ {"derive", OPT_DERIVE, '-', "Derive shared secret"},
+ OPT_CONFIG_OPTION,
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file - default stdin"},
- {"out", OPT_OUT, '>', "Output file - default stdout"},
+ {"rawin", OPT_RAWIN, '-', "Indicate the input data is in raw form"},
{"pubin", OPT_PUBIN, '-', "Input is a public key"},
+ {"inkey", OPT_INKEY, 's', "Input private key file"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"peerkey", OPT_PEERKEY, 's', "Peer key file used in key derivation"},
+ {"peerform", OPT_PEERFORM, 'E', "Peer key format (DER/PEM/P12/ENGINE)"},
{"certin", OPT_CERTIN, '-', "Input is a cert with a public key"},
+ {"rev", OPT_REV, '-', "Reverse the order of the input buffer"},
+ {"sigfile", OPT_SIGFILE, '<', "Signature file (verify operation only)"},
+ {"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file - default stdout"},
{"asn1parse", OPT_ASN1PARSE, '-', "asn1parse the output data"},
{"hexdump", OPT_HEXDUMP, '-', "Hex dump output"},
- {"sign", OPT_SIGN, '-', "Sign input data with private key"},
- {"verify", OPT_VERIFY, '-', "Verify with public key"},
{"verifyrecover", OPT_VERIFYRECOVER, '-',
"Verify with public key, recover original data"},
- {"rev", OPT_REV, '-', "Reverse the order of the input buffer"},
- {"encrypt", OPT_ENCRYPT, '-', "Encrypt input data with public key"},
- {"decrypt", OPT_DECRYPT, '-', "Decrypt input data with private key"},
- {"derive", OPT_DERIVE, '-', "Derive shared secret"},
+
+ OPT_SECTION("Signing/Derivation"),
+ {"digest", OPT_DIGEST, 's',
+ "Specify the digest algorithm when signing the raw input data"},
+ {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"},
+ {"pkeyopt_passin", OPT_PKEYOPT_PASSIN, 's',
+ "Public key option that is read as a passphrase argument opt:passphrase"},
{"kdf", OPT_KDF, 's', "Use KDF algorithm"},
{"kdflen", OPT_KDFLEN, 'p', "KDF algorithm output length"},
- {"sigfile", OPT_SIGFILE, '<', "Signature file (verify operation only)"},
- {"inkey", OPT_INKEY, 's', "Input private key file"},
- {"peerkey", OPT_PEERKEY, 's', "Peer key file used in key derivation"},
- {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
- {"peerform", OPT_PEERFORM, 'E', "Peer key format - default PEM"},
- {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"},
- {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"},
+
OPT_R_OPTIONS,
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
- {"engine_impl", OPT_ENGINE_IMPL, '-',
- "Also use engine given by -engine for crypto operations"},
-#endif
+ OPT_PROV_OPTIONS,
{NULL}
};
int pkeyutl_main(int argc, char **argv)
{
+ CONF *conf = NULL;
BIO *in = NULL, *out = NULL;
ENGINE *e = NULL;
EVP_PKEY_CTX *ctx = NULL;
+ EVP_PKEY *pkey = NULL;
char *infile = NULL, *outfile = NULL, *sigfile = NULL, *passinarg = NULL;
char hexdump = 0, asn1parse = 0, rev = 0, *prog;
unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
OPTION_CHOICE o;
- int buf_inlen = 0, siglen = -1, keyform = FORMAT_PEM, peerform = FORMAT_PEM;
+ int buf_inlen = 0, siglen = -1;
+ int keyform = FORMAT_UNDEF, peerform = FORMAT_UNDEF;
int keysize = -1, pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
int engine_impl = 0;
int ret = 1, rv = -1;
size_t buf_outlen;
const char *inkey = NULL;
const char *peerkey = NULL;
- const char *kdfalg = NULL;
+ const char *kdfalg = NULL, *digestname = NULL;
int kdflen = 0;
STACK_OF(OPENSSL_STRING) *pkeyopts = NULL;
+ STACK_OF(OPENSSL_STRING) *pkeyopts_passin = NULL;
+ int rawin = 0;
+ EVP_MD_CTX *mctx = NULL;
+ EVP_MD *md = NULL;
+ int filesize = -1;
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
prog = opt_init(argc, argv, pkeyutl_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -129,17 +163,26 @@ int pkeyutl_main(int argc, char **argv)
passinarg = opt_arg();
break;
case OPT_PEERFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PDE, &peerform))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &peerform))
goto opthelp;
break;
case OPT_KEYFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyform))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
goto opthelp;
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
+ case OPT_CONFIG:
+ conf = app_load_config_modules(opt_arg());
+ if (conf == NULL)
+ goto end;
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
@@ -192,12 +235,51 @@ int pkeyutl_main(int argc, char **argv)
goto end;
}
break;
+ case OPT_PKEYOPT_PASSIN:
+ if ((pkeyopts_passin == NULL &&
+ (pkeyopts_passin = sk_OPENSSL_STRING_new_null()) == NULL) ||
+ sk_OPENSSL_STRING_push(pkeyopts_passin, opt_arg()) == 0) {
+ BIO_puts(bio_err, "out of memory\n");
+ goto end;
+ }
+ break;
+ case OPT_RAWIN:
+ rawin = 1;
+ break;
+ case OPT_DIGEST:
+ digestname = opt_arg();
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
+ if (!app_RAND_load())
+ goto end;
+
+ if (rawin && pkey_op != EVP_PKEY_OP_SIGN && pkey_op != EVP_PKEY_OP_VERIFY) {
+ BIO_printf(bio_err,
+ "%s: -rawin can only be used with -sign or -verify\n",
+ prog);
+ goto opthelp;
+ }
+
+ if (digestname != NULL && !rawin) {
+ BIO_printf(bio_err,
+ "%s: -digest can only be used with -rawin\n",
+ prog);
+ goto opthelp;
+ }
+
+ if (rawin && rev) {
+ BIO_printf(bio_err, "%s: -rev cannot be used with raw input\n",
+ prog);
+ goto opthelp;
+ }
+
if (kdfalg != NULL) {
if (kdflen == 0) {
BIO_printf(bio_err,
@@ -213,16 +295,22 @@ int pkeyutl_main(int argc, char **argv)
"%s: no peer key given (-peerkey parameter).\n", prog);
goto opthelp;
}
+
+ if (rawin) {
+ if ((mctx = EVP_MD_CTX_new()) == NULL) {
+ BIO_printf(bio_err, "Error: out of memory\n");
+ goto end;
+ }
+ }
ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type,
- passinarg, pkey_op, e, engine_impl);
+ passinarg, pkey_op, e, engine_impl, rawin, &pkey,
+ mctx, digestname, libctx, app_get0_propq());
if (ctx == NULL) {
BIO_printf(bio_err, "%s: Error initializing context\n", prog);
- ERR_print_errors(bio_err);
goto end;
}
if (peerkey != NULL && !setup_peer(ctx, peerform, peerkey, e)) {
BIO_printf(bio_err, "%s: Error setting up peer key\n", prog);
- ERR_print_errors(bio_err);
goto end;
}
if (pkeyopts != NULL) {
@@ -235,11 +323,58 @@ int pkeyutl_main(int argc, char **argv)
if (pkey_ctrl_string(ctx, opt) <= 0) {
BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n",
prog, opt);
- ERR_print_errors(bio_err);
goto end;
}
}
}
+ if (pkeyopts_passin != NULL) {
+ int num = sk_OPENSSL_STRING_num(pkeyopts_passin);
+ int i;
+
+ for (i = 0; i < num; i++) {
+ char *opt = sk_OPENSSL_STRING_value(pkeyopts_passin, i);
+ char *passin = strchr(opt, ':');
+ char *passwd;
+
+ if (passin == NULL) {
+ /* Get password interactively */
+ char passwd_buf[4096];
+ int r;
+
+ BIO_snprintf(passwd_buf, sizeof(passwd_buf), "Enter %s: ", opt);
+ r = EVP_read_pw_string(passwd_buf, sizeof(passwd_buf) - 1,
+ passwd_buf, 0);
+ if (r < 0) {
+ if (r == -2)
+ BIO_puts(bio_err, "user abort\n");
+ else
+ BIO_puts(bio_err, "entry failed\n");
+ goto end;
+ }
+ passwd = OPENSSL_strdup(passwd_buf);
+ if (passwd == NULL) {
+ BIO_puts(bio_err, "out of memory\n");
+ goto end;
+ }
+ } else {
+ /* Get password as a passin argument: First split option name
+ * and passphrase argument into two strings */
+ *passin = 0;
+ passin++;
+ if (app_passwd(passin, NULL, &passwd, NULL) == 0) {
+ BIO_printf(bio_err, "failed to get '%s'\n", opt);
+ goto end;
+ }
+ }
+
+ if (EVP_PKEY_CTX_ctrl_str(ctx, opt, passwd) <= 0) {
+ BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n",
+ prog, opt);
+ goto end;
+ }
+ OPENSSL_free(passwd);
+ }
+ }
if (sigfile != NULL && (pkey_op != EVP_PKEY_OP_VERIFY)) {
BIO_printf(bio_err,
@@ -255,6 +390,12 @@ int pkeyutl_main(int argc, char **argv)
if (pkey_op != EVP_PKEY_OP_DERIVE) {
in = bio_open_default(infile, 'r', FORMAT_BINARY);
+ if (infile != NULL) {
+ struct stat st;
+
+ if (stat(infile, &st) == 0 && st.st_size <= INT_MAX)
+ filesize = (int)st.st_size;
+ }
if (in == NULL)
goto end;
}
@@ -277,7 +418,8 @@ int pkeyutl_main(int argc, char **argv)
}
}
- if (in != NULL) {
+ /* Raw input data is handled elsewhere */
+ if (in != NULL && !rawin) {
/* Read the input data */
buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
if (buf_inlen < 0) {
@@ -296,8 +438,9 @@ int pkeyutl_main(int argc, char **argv)
}
}
- /* Sanity check the input */
- if (buf_inlen > EVP_MAX_MD_SIZE
+ /* Sanity check the input if the input is not raw */
+ if (!rawin
+ && buf_inlen > EVP_MAX_MD_SIZE
&& (pkey_op == EVP_PKEY_OP_SIGN
|| pkey_op == EVP_PKEY_OP_VERIFY)) {
BIO_printf(bio_err,
@@ -306,8 +449,13 @@ int pkeyutl_main(int argc, char **argv)
}
if (pkey_op == EVP_PKEY_OP_VERIFY) {
- rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
- buf_in, (size_t)buf_inlen);
+ if (rawin) {
+ rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, sig, siglen,
+ NULL, 0);
+ } else {
+ rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
+ buf_in, (size_t)buf_inlen);
+ }
if (rv == 1) {
BIO_puts(out, "Signature Verified Successfully\n");
ret = 0;
@@ -316,18 +464,24 @@ int pkeyutl_main(int argc, char **argv)
}
goto end;
}
- if (kdflen != 0) {
- buf_outlen = kdflen;
- rv = 1;
+ if (rawin) {
+ /* rawin allocates the buffer in do_raw_keyop() */
+ rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, NULL, 0,
+ &buf_out, (size_t *)&buf_outlen);
} else {
- rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
- buf_in, (size_t)buf_inlen);
- }
- if (rv > 0 && buf_outlen != 0) {
- buf_out = app_malloc(buf_outlen, "buffer output");
- rv = do_keyop(ctx, pkey_op,
- buf_out, (size_t *)&buf_outlen,
- buf_in, (size_t)buf_inlen);
+ if (kdflen != 0) {
+ buf_outlen = kdflen;
+ rv = 1;
+ } else {
+ rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
+ buf_in, (size_t)buf_inlen);
+ }
+ if (rv > 0 && buf_outlen != 0) {
+ buf_out = app_malloc(buf_outlen, "buffer output");
+ rv = do_keyop(ctx, pkey_op,
+ buf_out, (size_t *)&buf_outlen,
+ buf_in, (size_t)buf_inlen);
+ }
}
if (rv <= 0) {
if (pkey_op != EVP_PKEY_OP_DERIVE) {
@@ -335,14 +489,13 @@ int pkeyutl_main(int argc, char **argv)
} else {
BIO_puts(bio_err, "Key derivation failed\n");
}
- ERR_print_errors(bio_err);
goto end;
}
ret = 0;
if (asn1parse) {
if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
- ERR_print_errors(bio_err);
+ ERR_print_errors(bio_err); /* but still return success */
} else if (hexdump) {
BIO_dump(out, (char *)buf_out, buf_outlen);
} else {
@@ -350,7 +503,11 @@ int pkeyutl_main(int argc, char **argv)
}
end:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
+ EVP_MD_CTX_free(mctx);
EVP_PKEY_CTX_free(ctx);
+ EVP_MD_free(md);
release_engine(e);
BIO_free(in);
BIO_free_all(out);
@@ -358,13 +515,17 @@ int pkeyutl_main(int argc, char **argv)
OPENSSL_free(buf_out);
OPENSSL_free(sig);
sk_OPENSSL_STRING_free(pkeyopts);
+ sk_OPENSSL_STRING_free(pkeyopts_passin);
+ NCONF_free(conf);
return ret;
}
static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
const char *keyfile, int keyform, int key_type,
char *passinarg, int pkey_op, ENGINE *e,
- const int engine_impl)
+ const int engine_impl, int rawin,
+ EVP_PKEY **ppkey, EVP_MD_CTX *mctx, const char *digestname,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
@@ -372,6 +533,7 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
char *passin = NULL;
int rv = -1;
X509 *x;
+
if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT)
|| (pkey_op == EVP_PKEY_OP_DERIVE))
&& (key_type != KEY_PRIVKEY && kdfalg == NULL)) {
@@ -384,11 +546,11 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
}
switch (key_type) {
case KEY_PRIVKEY:
- pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key");
+ pkey = load_key(keyfile, keyform, 0, passin, e, "private key");
break;
case KEY_PUBKEY:
- pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "Public Key");
+ pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "public key");
break;
case KEY_CERT:
@@ -420,42 +582,68 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
goto end;
}
}
- ctx = EVP_PKEY_CTX_new_id(kdfnid, impl);
+ if (impl != NULL)
+ ctx = EVP_PKEY_CTX_new_id(kdfnid, impl);
+ else
+ ctx = EVP_PKEY_CTX_new_from_name(libctx, kdfalg, propq);
} else {
if (pkey == NULL)
goto end;
- *pkeysize = EVP_PKEY_size(pkey);
- ctx = EVP_PKEY_CTX_new(pkey, impl);
+
+ *pkeysize = EVP_PKEY_get_size(pkey);
+ if (impl != NULL)
+ ctx = EVP_PKEY_CTX_new(pkey, impl);
+ else
+ ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
+ if (ppkey != NULL)
+ *ppkey = pkey;
EVP_PKEY_free(pkey);
}
if (ctx == NULL)
goto end;
- switch (pkey_op) {
- case EVP_PKEY_OP_SIGN:
- rv = EVP_PKEY_sign_init(ctx);
- break;
+ if (rawin) {
+ EVP_MD_CTX_set_pkey_ctx(mctx, ctx);
- case EVP_PKEY_OP_VERIFY:
- rv = EVP_PKEY_verify_init(ctx);
- break;
+ switch (pkey_op) {
+ case EVP_PKEY_OP_SIGN:
+ rv = EVP_DigestSignInit_ex(mctx, NULL, digestname, libctx, propq,
+ pkey, NULL);
+ break;
- case EVP_PKEY_OP_VERIFYRECOVER:
- rv = EVP_PKEY_verify_recover_init(ctx);
- break;
+ case EVP_PKEY_OP_VERIFY:
+ rv = EVP_DigestVerifyInit_ex(mctx, NULL, digestname, libctx, propq,
+ pkey, NULL);
+ break;
+ }
- case EVP_PKEY_OP_ENCRYPT:
- rv = EVP_PKEY_encrypt_init(ctx);
- break;
+ } else {
+ switch (pkey_op) {
+ case EVP_PKEY_OP_SIGN:
+ rv = EVP_PKEY_sign_init(ctx);
+ break;
- case EVP_PKEY_OP_DECRYPT:
- rv = EVP_PKEY_decrypt_init(ctx);
- break;
+ case EVP_PKEY_OP_VERIFY:
+ rv = EVP_PKEY_verify_init(ctx);
+ break;
- case EVP_PKEY_OP_DERIVE:
- rv = EVP_PKEY_derive_init(ctx);
- break;
+ case EVP_PKEY_OP_VERIFYRECOVER:
+ rv = EVP_PKEY_verify_recover_init(ctx);
+ break;
+
+ case EVP_PKEY_OP_ENCRYPT:
+ rv = EVP_PKEY_encrypt_init(ctx);
+ break;
+
+ case EVP_PKEY_OP_DECRYPT:
+ rv = EVP_PKEY_decrypt_init(ctx);
+ break;
+
+ case EVP_PKEY_OP_DERIVE:
+ rv = EVP_PKEY_derive_init(ctx);
+ break;
+ }
}
if (rv <= 0) {
@@ -478,18 +666,15 @@ static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
if (peerform == FORMAT_ENGINE)
engine = e;
- peer = load_pubkey(file, peerform, 0, NULL, engine, "Peer Key");
+ peer = load_pubkey(file, peerform, 0, NULL, engine, "peer key");
if (peer == NULL) {
BIO_printf(bio_err, "Error reading peer key %s\n", file);
- ERR_print_errors(bio_err);
return 0;
}
- ret = EVP_PKEY_derive_set_peer(ctx, peer);
+ ret = EVP_PKEY_derive_set_peer(ctx, peer) > 0;
EVP_PKEY_free(peer);
- if (ret <= 0)
- ERR_print_errors(bio_err);
return ret;
}
@@ -522,3 +707,95 @@ static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
}
return rv;
}
+
+#define TBUF_MAXSIZE 2048
+
+static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
+ EVP_PKEY *pkey, BIO *in,
+ int filesize, unsigned char *sig, int siglen,
+ unsigned char **out, size_t *poutlen)
+{
+ int rv = 0;
+ unsigned char tbuf[TBUF_MAXSIZE];
+ unsigned char *mbuf = NULL;
+ int buf_len = 0;
+
+ /* Some algorithms only support oneshot digests */
+ if (EVP_PKEY_get_id(pkey) == EVP_PKEY_ED25519
+ || EVP_PKEY_get_id(pkey) == EVP_PKEY_ED448) {
+ if (filesize < 0) {
+ BIO_printf(bio_err,
+ "Error: unable to determine file size for oneshot operation\n");
+ goto end;
+ }
+ mbuf = app_malloc(filesize, "oneshot sign/verify buffer");
+ switch(pkey_op) {
+ case EVP_PKEY_OP_VERIFY:
+ buf_len = BIO_read(in, mbuf, filesize);
+ if (buf_len != filesize) {
+ BIO_printf(bio_err, "Error reading raw input data\n");
+ goto end;
+ }
+ rv = EVP_DigestVerify(mctx, sig, (size_t)siglen, mbuf, buf_len);
+ break;
+ case EVP_PKEY_OP_SIGN:
+ buf_len = BIO_read(in, mbuf, filesize);
+ if (buf_len != filesize) {
+ BIO_printf(bio_err, "Error reading raw input data\n");
+ goto end;
+ }
+ rv = EVP_DigestSign(mctx, NULL, poutlen, mbuf, buf_len);
+ if (rv == 1 && out != NULL) {
+ *out = app_malloc(*poutlen, "buffer output");
+ rv = EVP_DigestSign(mctx, *out, poutlen, mbuf, buf_len);
+ }
+ break;
+ }
+ goto end;
+ }
+
+ switch(pkey_op) {
+ case EVP_PKEY_OP_VERIFY:
+ for (;;) {
+ buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
+ if (buf_len == 0)
+ break;
+ if (buf_len < 0) {
+ BIO_printf(bio_err, "Error reading raw input data\n");
+ goto end;
+ }
+ rv = EVP_DigestVerifyUpdate(mctx, tbuf, (size_t)buf_len);
+ if (rv != 1) {
+ BIO_printf(bio_err, "Error verifying raw input data\n");
+ goto end;
+ }
+ }
+ rv = EVP_DigestVerifyFinal(mctx, sig, (size_t)siglen);
+ break;
+ case EVP_PKEY_OP_SIGN:
+ for (;;) {
+ buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
+ if (buf_len == 0)
+ break;
+ if (buf_len < 0) {
+ BIO_printf(bio_err, "Error reading raw input data\n");
+ goto end;
+ }
+ rv = EVP_DigestSignUpdate(mctx, tbuf, (size_t)buf_len);
+ if (rv != 1) {
+ BIO_printf(bio_err, "Error signing raw input data\n");
+ goto end;
+ }
+ }
+ rv = EVP_DigestSignFinal(mctx, NULL, poutlen);
+ if (rv == 1 && out != NULL) {
+ *out = app_malloc(*poutlen, "buffer output");
+ rv = EVP_DigestSignFinal(mctx, *out, poutlen);
+ }
+ break;
+ }
+
+ end:
+ OPENSSL_free(mbuf);
+ return rv;
+}
diff --git a/apps/prime.c b/apps/prime.c
index 694479764696..e269493d5cd7 100644
--- a/apps/prime.c
+++ b/apps/prime.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -14,28 +14,36 @@
#include <openssl/bn.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_HEX, OPT_GENERATE, OPT_BITS, OPT_SAFE, OPT_CHECKS
+ OPT_COMMON,
+ OPT_HEX, OPT_GENERATE, OPT_BITS, OPT_SAFE, OPT_CHECKS,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS prime_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] [number...]\n"},
- {OPT_HELP_STR, 1, '-',
- " number Number to check for primality\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"bits", OPT_BITS, 'p', "Size of number in bits"},
+ {"checks", OPT_CHECKS, 'p', "Number of checks"},
+
+ OPT_SECTION("Output"),
{"hex", OPT_HEX, '-', "Hex output"},
{"generate", OPT_GENERATE, '-', "Generate a prime"},
- {"bits", OPT_BITS, 'p', "Size of number in bits"},
{"safe", OPT_SAFE, '-',
"When used with -generate, generate a safe prime"},
- {"checks", OPT_CHECKS, 'p', "Number of checks"},
+
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"number", 0, 0, "Number(s) to check for primality if not generating"},
{NULL}
};
int prime_main(int argc, char **argv)
{
BIGNUM *bn = NULL;
- int hex = 0, checks = 20, generate = 0, bits = 0, safe = 0, ret = 1;
+ int hex = 0, generate = 0, bits = 0, safe = 0, ret = 1;
char *prog;
OPTION_CHOICE o;
@@ -64,20 +72,23 @@ opthelp:
safe = 1;
break;
case OPT_CHECKS:
- checks = atoi(opt_arg());
+ /* ignore parameter and argument */
+ opt_arg();
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
break;
}
}
+
+ /* Optional arguments are numbers to check. */
argc = opt_num_rest();
argv = opt_rest();
-
if (generate) {
- if (argc != 0) {
- BIO_printf(bio_err, "Extra arguments given.\n");
+ if (argc != 0)
goto opthelp;
- }
} else if (argc == 0) {
- BIO_printf(bio_err, "%s: No prime specified\n", prog);
goto opthelp;
}
@@ -121,7 +132,7 @@ opthelp:
BN_print(bio_out, bn);
BIO_printf(bio_out, " (%s) %s prime\n",
argv[0],
- BN_is_prime_ex(bn, checks, NULL, NULL)
+ BN_check_prime(bn, NULL, NULL)
? "is" : "is not");
}
}
diff --git a/apps/progs.pl b/apps/progs.pl
index 57671405dda0..29f9be13ca08 100644
--- a/apps/progs.pl
+++ b/apps/progs.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -14,17 +14,22 @@ use warnings;
use lib '.';
use configdata qw/@disablables %unified_info/;
+my $opt = shift @ARGV;
+die "Unrecognised option, must be -C or -H\n"
+ unless ($opt eq '-H' || $opt eq '-C');
+
my %commands = ();
my $cmdre = qr/^\s*int\s+([a-z_][a-z0-9_]*)_main\(\s*int\s+argc\s*,/;
my $apps_openssl = shift @ARGV;
-my $YEAR = [localtime()]->[5] + 1900;
+my $YEAR = [gmtime($ENV{SOURCE_DATE_EPOCH} || time())]->[5] + 1900;
# because the program apps/openssl has object files as sources, and
# they then have the corresponding C files as source, we need to chain
# the lookups in %unified_info
my @openssl_source =
map { @{$unified_info{sources}->{$_}} }
- grep { /\.o$/ }
+ grep { /\.o$/
+ && !$unified_info{attributes}->{sources}->{$apps_openssl}->{$_}->{nocheck} }
@{$unified_info{sources}->{$apps_openssl}};
foreach my $filename (@openssl_source) {
@@ -38,144 +43,178 @@ foreach my $filename (@openssl_source) {
@ARGV = sort keys %commands;
-print <<"EOF";
+if ($opt eq '-H') {
+ print <<"EOF";
/*
* WARNING: do not edit!
* Generated by apps/progs.pl
*
* Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-typedef enum FUNC_TYPE {
- FT_none, FT_general, FT_md, FT_cipher, FT_pkey,
- FT_md_alg, FT_cipher_alg
-} FUNC_TYPE;
-
-typedef struct function_st {
- FUNC_TYPE type;
- const char *name;
- int (*func)(int argc, char *argv[]);
- const OPTIONS *help;
-} FUNCTION;
-
-DEFINE_LHASH_OF(FUNCTION);
+#include "function.h"
EOF
-foreach (@ARGV) {
- printf "extern int %s_main(int argc, char *argv[]);\n", $_;
-}
-print "\n";
+ foreach (@ARGV) {
+ printf "extern int %s_main(int argc, char *argv[]);\n", $_;
+ }
+ print "\n";
-foreach (@ARGV) {
- printf "extern const OPTIONS %s_options[];\n", $_;
-}
-print "\n";
-
-my %cmd_disabler = (
- ciphers => "sock",
- genrsa => "rsa",
- rsautl => "rsa",
- gendsa => "dsa",
- dsaparam => "dsa",
- gendh => "dh",
- dhparam => "dh",
- ecparam => "ec",
- pkcs12 => "des",
-);
-
-print "#ifdef INCLUDE_FUNCTION_TABLE\n";
-print "static FUNCTION functions[] = {\n";
-foreach my $cmd ( @ARGV ) {
- my $str = " {FT_general, \"$cmd\", ${cmd}_main, ${cmd}_options},\n";
- if ($cmd =~ /^s_/) {
- print "#ifndef OPENSSL_NO_SOCK\n${str}#endif\n";
- } elsif (grep { $cmd eq $_ } @disablables) {
- print "#ifndef OPENSSL_NO_" . uc($cmd) . "\n${str}#endif\n";
- } elsif (my $disabler = $cmd_disabler{$cmd}) {
- print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n";
- } else {
- print $str;
+ foreach (@ARGV) {
+ printf "extern const OPTIONS %s_options[];\n", $_;
}
+ print "\n";
+ print "extern FUNCTION functions[];\n";
}
-my %md_disabler = (
- blake2b512 => "blake2",
- blake2s256 => "blake2",
-);
-foreach my $cmd (
- "md2", "md4", "md5",
- "gost",
- "sha1", "sha224", "sha256", "sha384",
- "sha512", "sha512-224", "sha512-256",
- "sha3-224", "sha3-256", "sha3-384", "sha3-512",
- "shake128", "shake256",
- "mdc2", "rmd160", "blake2b512", "blake2s256",
- "sm3"
-) {
- my $str = " {FT_md, \"$cmd\", dgst_main},\n";
- if (grep { $cmd eq $_ } @disablables) {
- print "#ifndef OPENSSL_NO_" . uc($cmd) . "\n${str}#endif\n";
- } elsif (my $disabler = $md_disabler{$cmd}) {
- print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n";
- } else {
- print $str;
+if ($opt eq '-C') {
+ print <<"EOF";
+/*
+ * WARNING: do not edit!
+ * Generated by apps/progs.pl
+ *
+ * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "progs.h"
+
+EOF
+
+ my %cmd_disabler = (
+ ciphers => "sock",
+ genrsa => "rsa",
+ gendsa => "dsa",
+ dsaparam => "dsa",
+ gendh => "dh",
+ dhparam => "dh",
+ ecparam => "ec",
+ );
+ my %cmd_deprecated = (
+# The format of this table is:
+# [0] = alternative command to use instead
+# [1] = deprecented in this version
+# [2] = preprocessor conditional for exclusing irrespective of deprecation
+# rsa => [ "pkey", "3_0", "rsa" ],
+# genrsa => [ "genpkey", "3_0", "rsa" ],
+ rsautl => [ "pkeyutl", "3_0", "rsa" ],
+# dhparam => [ "pkeyparam", "3_0", "dh" ],
+# dsaparam => [ "pkeyparam", "3_0", "dsa" ],
+# dsa => [ "pkey", "3_0", "dsa" ],
+# gendsa => [ "genpkey", "3_0", "dsa" ],
+# ec => [ "pkey", "3_0", "ec" ],
+# ecparam => [ "pkeyparam", "3_0", "ec" ],
+ );
+
+ print "FUNCTION functions[] = {\n";
+ foreach my $cmd ( @ARGV ) {
+ my $str =
+ " {FT_general, \"$cmd\", ${cmd}_main, ${cmd}_options, NULL, NULL},\n";
+ if ($cmd =~ /^s_/) {
+ print "#ifndef OPENSSL_NO_SOCK\n${str}#endif\n";
+ } elsif (my $deprecated = $cmd_deprecated{$cmd}) {
+ my @dep = @{$deprecated};
+ my $daltprg = $dep[0];
+ my $dver = $dep[1];
+ my $dsys = $dep[2];
+ print "#if !defined(OPENSSL_NO_DEPRECATED_" . $dver . ")";
+ if ($dsys) {
+ print " && !defined(OPENSSL_NO_" . uc($dsys) . ")";
+ }
+ $dver =~ s/_/./g;
+ my $dalt = "\"" . $daltprg . "\", \"" . $dver . "\"";
+ $str =~ s/NULL, NULL/$dalt/;
+ print "\n${str}#endif\n";
+ } elsif (grep { $cmd eq $_ } @disablables) {
+ print "#ifndef OPENSSL_NO_" . uc($cmd) . "\n${str}#endif\n";
+ } elsif (my $disabler = $cmd_disabler{$cmd}) {
+ print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n";
+ } else {
+ print $str;
+ }
}
-}
-my %cipher_disabler = (
- des3 => "des",
- desx => "des",
- cast5 => "cast",
-);
-foreach my $cmd (
- "aes-128-cbc", "aes-128-ecb",
- "aes-192-cbc", "aes-192-ecb",
- "aes-256-cbc", "aes-256-ecb",
- "aria-128-cbc", "aria-128-cfb",
- "aria-128-ctr", "aria-128-ecb", "aria-128-ofb",
- "aria-128-cfb1", "aria-128-cfb8",
- "aria-192-cbc", "aria-192-cfb",
- "aria-192-ctr", "aria-192-ecb", "aria-192-ofb",
- "aria-192-cfb1", "aria-192-cfb8",
- "aria-256-cbc", "aria-256-cfb",
- "aria-256-ctr", "aria-256-ecb", "aria-256-ofb",
- "aria-256-cfb1", "aria-256-cfb8",
- "camellia-128-cbc", "camellia-128-ecb",
- "camellia-192-cbc", "camellia-192-ecb",
- "camellia-256-cbc", "camellia-256-ecb",
- "base64", "zlib",
- "des", "des3", "desx", "idea", "seed", "rc4", "rc4-40",
- "rc2", "bf", "cast", "rc5",
- "des-ecb", "des-ede", "des-ede3",
- "des-cbc", "des-ede-cbc","des-ede3-cbc",
- "des-cfb", "des-ede-cfb","des-ede3-cfb",
- "des-ofb", "des-ede-ofb","des-ede3-ofb",
- "idea-cbc","idea-ecb", "idea-cfb", "idea-ofb",
- "seed-cbc","seed-ecb", "seed-cfb", "seed-ofb",
- "rc2-cbc", "rc2-ecb", "rc2-cfb","rc2-ofb", "rc2-64-cbc", "rc2-40-cbc",
- "bf-cbc", "bf-ecb", "bf-cfb", "bf-ofb",
- "cast5-cbc","cast5-ecb", "cast5-cfb","cast5-ofb",
- "cast-cbc", "rc5-cbc", "rc5-ecb", "rc5-cfb", "rc5-ofb",
- "sm4-cbc", "sm4-ecb", "sm4-cfb", "sm4-ofb", "sm4-ctr"
-) {
- my $str = " {FT_cipher, \"$cmd\", enc_main, enc_options},\n";
- (my $algo = $cmd) =~ s/-.*//g;
- if ($cmd eq "zlib") {
- print "#ifdef ZLIB\n${str}#endif\n";
- } elsif (grep { $algo eq $_ } @disablables) {
- print "#ifndef OPENSSL_NO_" . uc($algo) . "\n${str}#endif\n";
- } elsif (my $disabler = $cipher_disabler{$algo}) {
- print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n";
- } else {
- print $str;
+ my %md_disabler = (
+ blake2b512 => "blake2",
+ blake2s256 => "blake2",
+ );
+ foreach my $cmd (
+ "md2", "md4", "md5",
+ "sha1", "sha224", "sha256", "sha384",
+ "sha512", "sha512-224", "sha512-256",
+ "sha3-224", "sha3-256", "sha3-384", "sha3-512",
+ "shake128", "shake256",
+ "mdc2", "rmd160", "blake2b512", "blake2s256",
+ "sm3"
+ ) {
+ my $str = " {FT_md, \"$cmd\", dgst_main, NULL, NULL},\n";
+ if (grep { $cmd eq $_ } @disablables) {
+ print "#ifndef OPENSSL_NO_" . uc($cmd) . "\n${str}#endif\n";
+ } elsif (my $disabler = $md_disabler{$cmd}) {
+ print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n";
+ } else {
+ print $str;
+ }
}
-}
-print " {0, NULL, NULL}\n};\n";
-print "#endif\n";
+ my %cipher_disabler = (
+ des3 => "des",
+ desx => "des",
+ cast5 => "cast",
+ );
+ foreach my $cmd (
+ "aes-128-cbc", "aes-128-ecb",
+ "aes-192-cbc", "aes-192-ecb",
+ "aes-256-cbc", "aes-256-ecb",
+ "aria-128-cbc", "aria-128-cfb",
+ "aria-128-ctr", "aria-128-ecb", "aria-128-ofb",
+ "aria-128-cfb1", "aria-128-cfb8",
+ "aria-192-cbc", "aria-192-cfb",
+ "aria-192-ctr", "aria-192-ecb", "aria-192-ofb",
+ "aria-192-cfb1", "aria-192-cfb8",
+ "aria-256-cbc", "aria-256-cfb",
+ "aria-256-ctr", "aria-256-ecb", "aria-256-ofb",
+ "aria-256-cfb1", "aria-256-cfb8",
+ "camellia-128-cbc", "camellia-128-ecb",
+ "camellia-192-cbc", "camellia-192-ecb",
+ "camellia-256-cbc", "camellia-256-ecb",
+ "base64", "zlib",
+ "des", "des3", "desx", "idea", "seed", "rc4", "rc4-40",
+ "rc2", "bf", "cast", "rc5",
+ "des-ecb", "des-ede", "des-ede3",
+ "des-cbc", "des-ede-cbc","des-ede3-cbc",
+ "des-cfb", "des-ede-cfb","des-ede3-cfb",
+ "des-ofb", "des-ede-ofb","des-ede3-ofb",
+ "idea-cbc","idea-ecb", "idea-cfb", "idea-ofb",
+ "seed-cbc","seed-ecb", "seed-cfb", "seed-ofb",
+ "rc2-cbc", "rc2-ecb", "rc2-cfb","rc2-ofb", "rc2-64-cbc", "rc2-40-cbc",
+ "bf-cbc", "bf-ecb", "bf-cfb", "bf-ofb",
+ "cast5-cbc","cast5-ecb", "cast5-cfb","cast5-ofb",
+ "cast-cbc", "rc5-cbc", "rc5-ecb", "rc5-cfb", "rc5-ofb",
+ "sm4-cbc", "sm4-ecb", "sm4-cfb", "sm4-ofb", "sm4-ctr"
+ ) {
+ my $str = " {FT_cipher, \"$cmd\", enc_main, enc_options, NULL},\n";
+ (my $algo = $cmd) =~ s/-.*//g;
+ if ($cmd eq "zlib") {
+ print "#ifdef ZLIB\n${str}#endif\n";
+ } elsif (grep { $algo eq $_ } @disablables) {
+ print "#ifndef OPENSSL_NO_" . uc($algo) . "\n${str}#endif\n";
+ } elsif (my $disabler = $cipher_disabler{$algo}) {
+ print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n";
+ } else {
+ print $str;
+ }
+ }
+
+ print " {0, NULL, NULL, NULL, NULL}\n};\n";
+}
diff --git a/apps/rand.c b/apps/rand.c
index 4c6181507bd5..cbf495d5bc53 100644
--- a/apps/rand.c
+++ b/apps/rand.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -19,22 +19,30 @@
#include <openssl/rand.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_OUT, OPT_ENGINE, OPT_BASE64, OPT_HEX,
- OPT_R_ENUM
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS rand_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [flags] num\n"},
- {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] num\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"out", OPT_OUT, '>', "Output file"},
- OPT_R_OPTIONS,
- {"base64", OPT_BASE64, '-', "Base64 encode output"},
- {"hex", OPT_HEX, '-', "Hex encode output"},
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"base64", OPT_BASE64, '-', "Base64 encode output"},
+ {"hex", OPT_HEX, '-', "Hex encode output"},
+
+ OPT_R_OPTIONS,
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"num", 0, 0, "Number of bytes to generate"},
{NULL}
};
@@ -74,18 +82,26 @@ int rand_main(int argc, char **argv)
case OPT_HEX:
format = FORMAT_TEXT;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* Optional argument is number of bytes to generate. */
argc = opt_num_rest();
argv = opt_rest();
if (argc == 1) {
if (!opt_int(argv[0], &num) || num <= 0)
- goto end;
- } else if (argc > 0) {
- BIO_printf(bio_err, "Extra arguments given.\n");
+ goto opthelp;
+ } else if (argc != 0) {
goto opthelp;
}
+ if (!app_RAND_load())
+ goto end;
+
out = bio_open_default(outfile, 'w', format);
if (out == NULL)
goto end;
diff --git a/apps/rehash.c b/apps/rehash.c
index fc1dffe97497..e4a4e14fd497 100644
--- a/apps/rehash.c
+++ b/apps/rehash.c
@@ -1,8 +1,8 @@
/*
- * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2013-2014 Timo Teräs <timo.teras@gmail.com>
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -42,7 +42,6 @@
# include <openssl/pem.h>
# include <openssl/x509.h>
-
# ifndef PATH_MAX
# define PATH_MAX 4096
# endif
@@ -169,6 +168,12 @@ static int add_entry(enum Type type, unsigned int hash, const char *filename,
*ep = nilhentry;
ep->old_id = ~0;
ep->filename = OPENSSL_strdup(filename);
+ if (ep->filename == NULL) {
+ OPENSSL_free(ep);
+ ep = NULL;
+ BIO_printf(bio_err, "out of memory\n");
+ return 1;
+ }
if (bp->last_entry)
bp->last_entry->next = ep;
if (bp->first_entry == NULL)
@@ -209,7 +214,7 @@ static int handle_symlink(const char *filename, const char *fullpath)
return -1;
for (type = OSSL_NELEM(suffixes) - 1; type > 0; type--) {
const char *suffix = suffixes[type];
- if (strncasecmp(suffix, &filename[i], strlen(suffix)) == 0)
+ if (OPENSSL_strncasecmp(suffix, &filename[i], strlen(suffix)) == 0)
break;
}
i += strlen(suffixes[type]);
@@ -233,7 +238,7 @@ static int do_file(const char *filename, const char *fullpath, enum Hash h)
{
STACK_OF (X509_INFO) *inf = NULL;
X509_INFO *x;
- X509_NAME *name = NULL;
+ const X509_NAME *name = NULL;
BIO *b;
const char *ext;
unsigned char digest[EVP_MAX_MD_SIZE];
@@ -244,7 +249,7 @@ static int do_file(const char *filename, const char *fullpath, enum Hash h)
if ((ext = strrchr(filename, '.')) == NULL)
goto end;
for (i = 0; i < OSSL_NELEM(extensions); i++) {
- if (strcasecmp(extensions[i], ext + 1) == 0)
+ if (OPENSSL_strcasecmp(extensions[i], ext + 1) == 0)
break;
}
if (i >= OSSL_NELEM(extensions))
@@ -292,10 +297,23 @@ static int do_file(const char *filename, const char *fullpath, enum Hash h)
goto end;
}
if (name != NULL) {
- if ((h == HASH_NEW) || (h == HASH_BOTH))
- errs += add_entry(type, X509_NAME_hash(name), filename, digest, 1, ~0);
+ if (h == HASH_NEW || h == HASH_BOTH) {
+ int ok;
+ unsigned long hash_value =
+ X509_NAME_hash_ex(name,
+ app_get0_libctx(), app_get0_propq(), &ok);
+
+ if (ok) {
+ errs += add_entry(type, hash_value, filename, digest, 1, ~0);
+ } else {
+ BIO_printf(bio_err, "%s: error calculating SHA1 hash value\n",
+ opt_getprog());
+ errs++;
+ }
+ }
if ((h == HASH_OLD) || (h == HASH_BOTH))
- errs += add_entry(type, X509_NAME_hash_old(name), filename, digest, 1, ~0);
+ errs += add_entry(type, X509_NAME_hash_old(name),
+ filename, digest, 1, ~0);
}
end:
@@ -454,19 +472,28 @@ static int do_dir(const char *dirname, enum Hash h)
}
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_COMPAT, OPT_OLD, OPT_N, OPT_VERBOSE
+ OPT_COMMON,
+ OPT_COMPAT, OPT_OLD, OPT_N, OPT_VERBOSE,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS rehash_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert-directory...]\n"},
- {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [directory...]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"h", OPT_HELP, '-', "Display this summary"},
{"compat", OPT_COMPAT, '-', "Create both new- and old-style hash links"},
{"old", OPT_OLD, '-', "Use old-style hash to generate links"},
{"n", OPT_N, '-', "Do not remove existing links"},
+
+ OPT_SECTION("Output"),
{"v", OPT_VERBOSE, '-', "Verbose output"},
+
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"directory", 0, 0, "One or more directories to process (optional)"},
{NULL}
};
@@ -501,13 +528,19 @@ int rehash_main(int argc, char **argv)
case OPT_VERBOSE:
verbose = 1;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* Optional arguments are directories to scan. */
argc = opt_num_rest();
argv = opt_rest();
evpmd = EVP_sha1();
- evpmdsize = EVP_MD_size(evpmd);
+ evpmdsize = EVP_MD_get_size(evpmd);
if (*argv != NULL) {
while (*argv != NULL)
diff --git a/apps/req.c b/apps/req.c
index a603907cd5af..23757044ab7f 100644
--- a/apps/req.c
+++ b/apps/req.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -14,6 +14,7 @@
#include <ctype.h>
#include "apps.h"
#include "progs.h"
+#include <openssl/core_names.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/conf.h>
@@ -25,32 +26,29 @@
#include <openssl/pem.h>
#include <openssl/bn.h>
#include <openssl/lhash.h>
-#ifndef OPENSSL_NO_RSA
-# include <openssl/rsa.h>
-#endif
+#include <openssl/rsa.h>
#ifndef OPENSSL_NO_DSA
# include <openssl/dsa.h>
#endif
-#define SECTION "req"
-
-#define BITS "default_bits"
-#define KEYFILE "default_keyfile"
-#define PROMPT "prompt"
-#define DISTINGUISHED_NAME "distinguished_name"
-#define ATTRIBUTES "attributes"
-#define V3_EXTENSIONS "x509_extensions"
-#define REQ_EXTENSIONS "req_extensions"
-#define STRING_MASK "string_mask"
-#define UTF8_IN "utf8"
-
-#define DEFAULT_KEY_LENGTH 2048
-#define MIN_KEY_LENGTH 512
-
-static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *dn, int mutlirdn,
- int attribs, unsigned long chtype);
-static int build_subject(X509_REQ *req, const char *subj, unsigned long chtype,
- int multirdn);
+#define BITS "default_bits"
+#define KEYFILE "default_keyfile"
+#define PROMPT "prompt"
+#define DISTINGUISHED_NAME "distinguished_name"
+#define ATTRIBUTES "attributes"
+#define V3_EXTENSIONS "x509_extensions"
+#define REQ_EXTENSIONS "req_extensions"
+#define STRING_MASK "string_mask"
+#define UTF8_IN "utf8"
+
+#define DEFAULT_KEY_LENGTH 2048
+#define MIN_KEY_LENGTH 512
+#define DEFAULT_DAYS 30 /* default cert validity period in days */
+#define UNSET_DAYS -2 /* -1 may be used for testing expiration checks */
+#define EXT_COPY_UNSET -1
+
+static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, X509_NAME *fsubj,
+ int mutlirdn, int attribs, unsigned long chtype);
static int prompt_info(X509_REQ *req,
STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect,
STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect,
@@ -65,91 +63,113 @@ static int add_DN_object(X509_NAME *n, char *text, const char *def,
char *value, int nid, int n_min, int n_max,
unsigned long chtype, int mval);
static int genpkey_cb(EVP_PKEY_CTX *ctx);
-static int build_data(char *text, const char *def,
- char *value, int n_min, int n_max,
- char *buf, const int buf_size,
- const char *desc1, const char *desc2
- );
+static int build_data(char *text, const char *def, char *value,
+ int n_min, int n_max, char *buf, const int buf_size,
+ const char *desc1, const char *desc2);
static int req_check_len(int len, int n_min, int n_max);
static int check_end(const char *str, const char *end);
static int join(char buf[], size_t buf_size, const char *name,
const char *tail, const char *desc);
static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr,
- int *pkey_type, long *pkeylen,
- char **palgnam, ENGINE *keygen_engine);
+ char **pkeytype, long *pkeylen,
+ ENGINE *keygen_engine);
+
+static const char *section = "req";
static CONF *req_conf = NULL;
static CONF *addext_conf = NULL;
static int batch = 0;
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_KEYGEN_ENGINE, OPT_KEY,
OPT_PUBKEY, OPT_NEW, OPT_CONFIG, OPT_KEYFORM, OPT_IN, OPT_OUT,
OPT_KEYOUT, OPT_PASSIN, OPT_PASSOUT, OPT_NEWKEY,
- OPT_PKEYOPT, OPT_SIGOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS,
- OPT_VERIFY, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8,
+ OPT_PKEYOPT, OPT_SIGOPT, OPT_VFYOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS,
+ OPT_VERIFY, OPT_NOENC, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8,
OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509,
- OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, OPT_ADDEXT, OPT_EXTENSIONS,
+ OPT_CA, OPT_CAKEY,
+ OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL,
+ OPT_COPY_EXTENSIONS, OPT_ADDEXT, OPT_EXTENSIONS,
OPT_REQEXTS, OPT_PRECERT, OPT_MD,
- OPT_R_ENUM
+ OPT_SECTION,
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS req_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+ {"keygen_engine", OPT_KEYGEN_ENGINE, 's',
+ "Specify engine to be used for key generation operations"},
+#endif
+ {"in", OPT_IN, '<', "X.509 request input file (default stdin)"},
{"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
- {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
- {"in", OPT_IN, '<', "Input file"},
- {"out", OPT_OUT, '>', "Output file"},
- {"key", OPT_KEY, 's', "Private key to use"},
- {"keyform", OPT_KEYFORM, 'f', "Key file format"},
- {"pubkey", OPT_PUBKEY, '-', "Output public key"},
+ {"verify", OPT_VERIFY, '-', "Verify self-signature on the request"},
+
+ OPT_SECTION("Certificate"),
{"new", OPT_NEW, '-', "New request"},
{"config", OPT_CONFIG, '<', "Request template file"},
- {"keyout", OPT_KEYOUT, '>', "File to send the key to"},
- {"passin", OPT_PASSIN, 's', "Private key password source"},
- {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
- OPT_R_OPTIONS,
- {"newkey", OPT_NEWKEY, 's', "Specify as type:bits"},
- {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"},
- {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
- {"batch", OPT_BATCH, '-',
- "Do not ask anything during request generation"},
- {"newhdr", OPT_NEWHDR, '-', "Output \"NEW\" in the header lines"},
- {"modulus", OPT_MODULUS, '-', "RSA modulus"},
- {"verify", OPT_VERIFY, '-', "Verify signature on REQ"},
- {"nodes", OPT_NODES, '-', "Don't encrypt the output key"},
- {"noout", OPT_NOOUT, '-', "Do not output REQ"},
- {"verbose", OPT_VERBOSE, '-', "Verbose output"},
+ {"section", OPT_SECTION, 's', "Config section to use (default \"req\")"},
{"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"},
- {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
+ {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
{"reqopt", OPT_REQOPT, 's', "Various request text options"},
{"text", OPT_TEXT, '-', "Text form of request"},
{"x509", OPT_X509, '-',
- "Output a x509 structure instead of a cert request"},
+ "Output an X.509 certificate structure instead of a cert request"},
+ {"CA", OPT_CA, '<', "Issuer cert to use for signing a cert, implies -x509"},
+ {"CAkey", OPT_CAKEY, 's',
+ "Issuer private key to use with -CA; default is -CA arg"},
{OPT_MORE_STR, 1, 1, "(Required by some CA's)"},
- {"subj", OPT_SUBJ, 's', "Set or modify request subject"},
- {"subject", OPT_SUBJECT, '-', "Output the request's subject"},
+ {"subj", OPT_SUBJ, 's', "Set or modify subject of request or cert"},
+ {"subject", OPT_SUBJECT, '-',
+ "Print the subject of the output request or cert"},
{"multivalue-rdn", OPT_MULTIVALUE_RDN, '-',
- "Enable support for multivalued RDNs"},
+ "Deprecated; multi-valued RDNs support is always on."},
{"days", OPT_DAYS, 'p', "Number of days cert is valid for"},
{"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"},
+ {"copy_extensions", OPT_COPY_EXTENSIONS, 's',
+ "copy extensions from request when using -x509"},
{"addext", OPT_ADDEXT, 's',
"Additional cert extension key=value pair (may be given more than once)"},
{"extensions", OPT_EXTENSIONS, 's',
"Cert extension section (override value in config file)"},
{"reqexts", OPT_REQEXTS, 's',
"Request extension section (override value in config file)"},
- {"precert", OPT_PRECERT, '-', "Add a poison extension (implies -new)"},
+ {"precert", OPT_PRECERT, '-',
+ "Add a poison extension to the generated cert (implies -new)"},
+
+ OPT_SECTION("Keys and Signing"),
+ {"key", OPT_KEY, 's', "Key for signing, and to include unless -in given"},
+ {"keyform", OPT_KEYFORM, 'f', "Key file format (ENGINE, other values ignored)"},
+ {"pubkey", OPT_PUBKEY, '-', "Output public key"},
+ {"keyout", OPT_KEYOUT, '>', "File to write private key to"},
+ {"passin", OPT_PASSIN, 's', "Private key and certificate password source"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+ {"newkey", OPT_NEWKEY, 's',
+ "Generate new key with [<alg>:]<nbits> or <alg>[:<file>] or param:<file>"},
+ {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"},
+ {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
+ {"vfyopt", OPT_VFYOPT, 's', "Verification parameter in n:v form"},
{"", OPT_MD, '-', "Any supported digest"},
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
- {"keygen_engine", OPT_KEYGEN_ENGINE, 's',
- "Specify engine to be used for key generation operations"},
-#endif
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
+ {"batch", OPT_BATCH, '-',
+ "Do not ask anything during request generation"},
+ {"verbose", OPT_VERBOSE, '-', "Verbose output"},
+ {"noenc", OPT_NOENC, '-', "Don't encrypt private keys"},
+ {"nodes", OPT_NODES, '-', "Don't encrypt private keys; deprecated"},
+ {"noout", OPT_NOOUT, '-', "Do not output REQ"},
+ {"newhdr", OPT_NEWHDR, '-', "Output \"NEW\" in the header lines"},
+ {"modulus", OPT_MODULUS, '-', "RSA modulus"},
+
+ OPT_R_OPTIONS,
+ OPT_PROV_OPTIONS,
{NULL}
};
-
/*
* An LHASH of strings, where each string is an extension name.
*/
@@ -169,9 +189,8 @@ static void exts_cleanup(OPENSSL_STRING *x)
}
/*
- * Is the |kv| key already duplicated? This is remarkably tricky to get
- * right. Return 0 if unique, -1 on runtime error; 1 if found or a syntax
- * error.
+ * Is the |kv| key already duplicated? This is remarkably tricky to get right.
+ * Return 0 if unique, -1 on runtime error; 1 if found or a syntax error.
*/
static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
{
@@ -200,7 +219,7 @@ static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
*p = '\0';
/* Finally have a clean "key"; see if it's there [by attempt to add it]. */
- p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv);
+ p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING *)kv);
if (p != NULL) {
OPENSSL_free(p);
return 1;
@@ -215,36 +234,39 @@ static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
int req_main(int argc, char **argv)
{
ASN1_INTEGER *serial = NULL;
- BIO *in = NULL, *out = NULL;
+ BIO *out = NULL;
ENGINE *e = NULL, *gen_eng = NULL;
- EVP_PKEY *pkey = NULL;
+ EVP_PKEY *pkey = NULL, *CAkey = NULL;
EVP_PKEY_CTX *genctx = NULL;
- STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL;
+ STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL, *vfyopts = NULL;
LHASH_OF(OPENSSL_STRING) *addexts = NULL;
- X509 *x509ss = NULL;
+ X509 *new_x509 = NULL, *CAcert = NULL;
X509_REQ *req = NULL;
- const EVP_CIPHER *cipher = NULL;
- const EVP_MD *md_alg = NULL, *digest = NULL;
+ EVP_CIPHER *cipher = NULL;
+ EVP_MD *md = NULL;
+ int ext_copy = EXT_COPY_UNSET;
BIO *addext_bio = NULL;
- char *extensions = NULL, *infile = NULL;
- char *outfile = NULL, *keyfile = NULL;
+ char *extensions = NULL;
+ const char *infile = NULL, *CAfile = NULL, *CAkeyfile = NULL;
+ char *outfile = NULL, *keyfile = NULL, *digest = NULL;
char *keyalgstr = NULL, *p, *prog, *passargin = NULL, *passargout = NULL;
char *passin = NULL, *passout = NULL;
char *nofree_passin = NULL, *nofree_passout = NULL;
char *req_exts = NULL, *subj = NULL;
+ X509_NAME *fsubj = NULL;
char *template = default_config_file, *keyout = NULL;
const char *keyalg = NULL;
OPTION_CHOICE o;
- int ret = 1, x509 = 0, days = 0, i = 0, newreq = 0, verbose = 0;
- int pkey_type = -1, private = 0;
- int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyform = FORMAT_PEM;
- int modulus = 0, multirdn = 0, verify = 0, noout = 0, text = 0;
- int nodes = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0;
- long newkey = -1;
+ int days = UNSET_DAYS;
+ int ret = 1, gen_x509 = 0, i = 0, newreq = 0, verbose = 0;
+ int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyform = FORMAT_UNDEF;
+ int modulus = 0, multirdn = 1, verify = 0, noout = 0, text = 0;
+ int noenc = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0;
+ long newkey_len = -1;
unsigned long chtype = MBSTRING_ASC, reqflag = 0;
#ifndef OPENSSL_NO_DES
- cipher = EVP_des_ede3_cbc();
+ cipher = (EVP_CIPHER *)EVP_des_ede3_cbc();
#endif
prog = opt_init(argc, argv, req_options);
@@ -272,7 +294,7 @@ int req_main(int argc, char **argv)
break;
case OPT_KEYGEN_ENGINE:
#ifndef OPENSSL_NO_ENGINE
- gen_eng = ENGINE_by_id(opt_arg());
+ gen_eng = setup_engine(opt_arg(), 0);
if (gen_eng == NULL) {
BIO_printf(bio_err, "Can't find keygen engine %s\n", *argv);
goto opthelp;
@@ -291,6 +313,9 @@ int req_main(int argc, char **argv)
case OPT_CONFIG:
template = opt_arg();
break;
+ case OPT_SECTION:
+ section = opt_arg();
+ break;
case OPT_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
goto opthelp;
@@ -314,14 +339,19 @@ int req_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_NEWKEY:
keyalg = opt_arg();
newreq = 1;
break;
case OPT_PKEYOPT:
- if (!pkeyopts)
+ if (pkeyopts == NULL)
pkeyopts = sk_OPENSSL_STRING_new_null();
- if (!pkeyopts || !sk_OPENSSL_STRING_push(pkeyopts, opt_arg()))
+ if (pkeyopts == NULL
+ || !sk_OPENSSL_STRING_push(pkeyopts, opt_arg()))
goto opthelp;
break;
case OPT_SIGOPT:
@@ -330,6 +360,12 @@ int req_main(int argc, char **argv)
if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
goto opthelp;
break;
+ case OPT_VFYOPT:
+ if (!vfyopts)
+ vfyopts = sk_OPENSSL_STRING_new_null();
+ if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg()))
+ goto opthelp;
+ break;
case OPT_BATCH:
batch = 1;
break;
@@ -343,7 +379,8 @@ int req_main(int argc, char **argv)
verify = 1;
break;
case OPT_NODES:
- nodes = 1;
+ case OPT_NOENC:
+ noenc = 1;
break;
case OPT_NOOUT:
noout = 1;
@@ -366,10 +403,22 @@ int req_main(int argc, char **argv)
text = 1;
break;
case OPT_X509:
- x509 = 1;
+ gen_x509 = 1;
+ break;
+ case OPT_CA:
+ CAfile = opt_arg();
+ gen_x509 = 1;
+ break;
+ case OPT_CAKEY:
+ CAkeyfile = opt_arg();
break;
case OPT_DAYS:
days = atoi(opt_arg());
+ if (days < -1) {
+ BIO_printf(bio_err, "%s: -days parameter arg must be >= -1\n",
+ prog);
+ goto end;
+ }
break;
case OPT_SET_SERIAL:
if (serial != NULL) {
@@ -387,7 +436,14 @@ int req_main(int argc, char **argv)
subj = opt_arg();
break;
case OPT_MULTIVALUE_RDN:
- multirdn = 1;
+ /* obsolete */
+ break;
+ case OPT_COPY_EXTENSIONS:
+ if (!set_ext_copy(&ext_copy, opt_arg())) {
+ BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n",
+ opt_arg());
+ goto end;
+ }
break;
case OPT_ADDEXT:
p = opt_arg();
@@ -398,9 +454,11 @@ int req_main(int argc, char **argv)
goto end;
}
i = duplicated(addexts, p);
- if (i == 1)
+ if (i == 1) {
+ BIO_printf(bio_err, "Duplicate extension: %s\n", p);
goto opthelp;
- if (i < 0 || BIO_printf(addext_bio, "%s\n", opt_arg()) < 0)
+ }
+ if (i < 0 || BIO_printf(addext_bio, "%s\n", p) < 0)
goto end;
break;
case OPT_EXTENSIONS:
@@ -413,37 +471,39 @@ int req_main(int argc, char **argv)
newreq = precert = 1;
break;
case OPT_MD:
- if (!opt_md(opt_unknown(), &md_alg))
- goto opthelp;
- digest = md_alg;
+ digest = opt_unknown();
break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
- if (days && !x509)
- BIO_printf(bio_err, "Ignoring -days; not generating a certificate\n");
- if (x509 && infile == NULL)
- newreq = 1;
+ if (!app_RAND_load())
+ goto end;
- /* TODO: simplify this as pkey is still always NULL here */
- private = newreq && (pkey == NULL) ? 1 : 0;
+ if (!gen_x509) {
+ if (days != UNSET_DAYS)
+ BIO_printf(bio_err, "Ignoring -days without -x509; not generating a certificate\n");
+ if (ext_copy == EXT_COPY_NONE)
+ BIO_printf(bio_err, "Ignoring -copy_extensions 'none' when -x509 is not given\n");
+ }
+ if (gen_x509 && infile == NULL)
+ newreq = 1;
if (!app_passwd(passargin, passargout, &passin, &passout)) {
BIO_printf(bio_err, "Error getting passwords\n");
goto end;
}
- if (verbose)
- BIO_printf(bio_err, "Using configuration from %s\n", template);
- if ((req_conf = app_load_config(template)) == NULL)
+ if ((req_conf = app_load_config_verbose(template, verbose)) == NULL)
goto end;
- if (addext_bio) {
+ if (addext_bio != NULL) {
if (verbose)
BIO_printf(bio_err,
- "Using additional configuration from command line\n");
+ "Using additional configuration from -addext options\n");
if ((addext_conf = app_load_config_bio(addext_bio, NULL)) == NULL)
goto end;
}
@@ -455,14 +515,12 @@ int req_main(int argc, char **argv)
if (p == NULL)
ERR_clear_error();
if (p != NULL) {
- BIO *oid_bio;
+ BIO *oid_bio = BIO_new_file(p, "r");
- oid_bio = BIO_new_file(p, "r");
if (oid_bio == NULL) {
- /*-
- BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
- ERR_print_errors(bio_err);
- */
+ if (verbose)
+ BIO_printf(bio_err,
+ "Problems opening '%s' for extra OIDs\n", p);
} else {
OBJ_create_objects(oid_bio);
BIO_free(oid_bio);
@@ -472,59 +530,67 @@ int req_main(int argc, char **argv)
if (!add_oid_section(req_conf))
goto end;
- if (md_alg == NULL) {
- p = NCONF_get_string(req_conf, SECTION, "default_md");
- if (p == NULL) {
+ /* Check that any specified digest is fetchable */
+ if (digest != NULL) {
+ if (!opt_md(digest, &md)) {
ERR_clear_error();
- } else {
- if (!opt_md(p, &md_alg))
- goto opthelp;
- digest = md_alg;
+ goto opthelp;
}
+ EVP_MD_free(md);
+ } else {
+ /* No digest specified, default to configuration */
+ p = NCONF_get_string(req_conf, section, "default_md");
+ if (p == NULL)
+ ERR_clear_error();
+ else
+ digest = p;
}
if (extensions == NULL) {
- extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
+ extensions = NCONF_get_string(req_conf, section, V3_EXTENSIONS);
if (extensions == NULL)
ERR_clear_error();
}
if (extensions != NULL) {
/* Check syntax of file */
X509V3_CTX ctx;
+
X509V3_set_ctx_test(&ctx);
X509V3_set_nconf(&ctx, req_conf);
if (!X509V3_EXT_add_nconf(req_conf, &ctx, extensions, NULL)) {
BIO_printf(bio_err,
- "Error Loading extension section %s\n", extensions);
+ "Error checking x509 extension section %s\n",
+ extensions);
goto end;
}
}
if (addext_conf != NULL) {
/* Check syntax of command line extensions */
X509V3_CTX ctx;
+
X509V3_set_ctx_test(&ctx);
X509V3_set_nconf(&ctx, addext_conf);
if (!X509V3_EXT_add_nconf(addext_conf, &ctx, "default", NULL)) {
- BIO_printf(bio_err, "Error Loading command line extensions\n");
+ BIO_printf(bio_err, "Error checking extensions defined using -addext\n");
goto end;
}
}
if (passin == NULL) {
passin = nofree_passin =
- NCONF_get_string(req_conf, SECTION, "input_password");
+ NCONF_get_string(req_conf, section, "input_password");
if (passin == NULL)
ERR_clear_error();
}
if (passout == NULL) {
passout = nofree_passout =
- NCONF_get_string(req_conf, SECTION, "output_password");
+ NCONF_get_string(req_conf, section, "output_password");
if (passout == NULL)
ERR_clear_error();
}
- p = NCONF_get_string(req_conf, SECTION, STRING_MASK);
+ p = NCONF_get_string(req_conf, section, STRING_MASK);
if (p == NULL)
ERR_clear_error();
@@ -534,7 +600,7 @@ int req_main(int argc, char **argv)
}
if (chtype != MBSTRING_UTF8) {
- p = NCONF_get_string(req_conf, SECTION, UTF8_IN);
+ p = NCONF_get_string(req_conf, section, UTF8_IN);
if (p == NULL)
ERR_clear_error();
else if (strcmp(p, "yes") == 0)
@@ -542,134 +608,117 @@ int req_main(int argc, char **argv)
}
if (req_exts == NULL) {
- req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
+ req_exts = NCONF_get_string(req_conf, section, REQ_EXTENSIONS);
if (req_exts == NULL)
ERR_clear_error();
}
if (req_exts != NULL) {
/* Check syntax of file */
X509V3_CTX ctx;
+
X509V3_set_ctx_test(&ctx);
X509V3_set_nconf(&ctx, req_conf);
if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_exts, NULL)) {
BIO_printf(bio_err,
- "Error Loading request extension section %s\n",
+ "Error checking request extension section %s\n",
req_exts);
goto end;
}
}
if (keyfile != NULL) {
- pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key");
- if (pkey == NULL) {
- /* load_key() has already printed an appropriate message */
+ pkey = load_key(keyfile, keyform, 0, passin, e, "private key");
+ if (pkey == NULL)
goto end;
- } else {
- app_RAND_load_conf(req_conf, SECTION);
- }
+ app_RAND_load_conf(req_conf, section);
}
+ if (newreq && pkey == NULL) {
+ app_RAND_load_conf(req_conf, section);
- if (newreq && (pkey == NULL)) {
- app_RAND_load_conf(req_conf, SECTION);
+ if (!NCONF_get_number(req_conf, section, BITS, &newkey_len))
+ newkey_len = DEFAULT_KEY_LENGTH;
- if (!NCONF_get_number(req_conf, SECTION, BITS, &newkey)) {
- newkey = DEFAULT_KEY_LENGTH;
- }
-
- if (keyalg != NULL) {
- genctx = set_keygen_ctx(keyalg, &pkey_type, &newkey,
- &keyalgstr, gen_eng);
- if (genctx == NULL)
- goto end;
- }
+ genctx = set_keygen_ctx(keyalg, &keyalgstr, &newkey_len, gen_eng);
+ if (genctx == NULL)
+ goto end;
- if (newkey < MIN_KEY_LENGTH
- && (pkey_type == EVP_PKEY_RSA || pkey_type == EVP_PKEY_DSA)) {
- BIO_printf(bio_err, "private key length is too short,\n");
- BIO_printf(bio_err, "it needs to be at least %d bits, not %ld\n",
- MIN_KEY_LENGTH, newkey);
+ if (newkey_len < MIN_KEY_LENGTH
+ && (EVP_PKEY_CTX_is_a(genctx, "RSA")
+ || EVP_PKEY_CTX_is_a(genctx, "RSA-PSS")
+ || EVP_PKEY_CTX_is_a(genctx, "DSA"))) {
+ BIO_printf(bio_err, "Private key length too short, needs to be at least %d bits, not %ld.\n",
+ MIN_KEY_LENGTH, newkey_len);
goto end;
}
- if (pkey_type == EVP_PKEY_RSA && newkey > OPENSSL_RSA_MAX_MODULUS_BITS)
+ if (newkey_len > OPENSSL_RSA_MAX_MODULUS_BITS
+ && (EVP_PKEY_CTX_is_a(genctx, "RSA")
+ || EVP_PKEY_CTX_is_a(genctx, "RSA-PSS")))
BIO_printf(bio_err,
"Warning: It is not recommended to use more than %d bit for RSA keys.\n"
" Your key size is %ld! Larger key size may behave not as expected.\n",
- OPENSSL_RSA_MAX_MODULUS_BITS, newkey);
+ OPENSSL_RSA_MAX_MODULUS_BITS, newkey_len);
#ifndef OPENSSL_NO_DSA
- if (pkey_type == EVP_PKEY_DSA && newkey > OPENSSL_DSA_MAX_MODULUS_BITS)
+ if (EVP_PKEY_CTX_is_a(genctx, "DSA")
+ && newkey_len > OPENSSL_DSA_MAX_MODULUS_BITS)
BIO_printf(bio_err,
"Warning: It is not recommended to use more than %d bit for DSA keys.\n"
" Your key size is %ld! Larger key size may behave not as expected.\n",
- OPENSSL_DSA_MAX_MODULUS_BITS, newkey);
+ OPENSSL_DSA_MAX_MODULUS_BITS, newkey_len);
#endif
- if (genctx == NULL) {
- genctx = set_keygen_ctx(NULL, &pkey_type, &newkey,
- &keyalgstr, gen_eng);
- if (!genctx)
- goto end;
- }
-
if (pkeyopts != NULL) {
char *genopt;
for (i = 0; i < sk_OPENSSL_STRING_num(pkeyopts); i++) {
genopt = sk_OPENSSL_STRING_value(pkeyopts, i);
if (pkey_ctrl_string(genctx, genopt) <= 0) {
- BIO_printf(bio_err, "parameter error \"%s\"\n", genopt);
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Key parameter error \"%s\"\n", genopt);
goto end;
}
}
}
- if (pkey_type == EVP_PKEY_EC) {
- BIO_printf(bio_err, "Generating an EC private key\n");
- } else {
- BIO_printf(bio_err, "Generating a %s private key\n", keyalgstr);
- }
-
EVP_PKEY_CTX_set_cb(genctx, genpkey_cb);
EVP_PKEY_CTX_set_app_data(genctx, bio_err);
- if (EVP_PKEY_keygen(genctx, &pkey) <= 0) {
- BIO_puts(bio_err, "Error Generating Key\n");
- goto end;
- }
+ pkey = app_keygen(genctx, keyalgstr, newkey_len, verbose);
EVP_PKEY_CTX_free(genctx);
genctx = NULL;
+ }
+ if (keyout == NULL && keyfile == NULL) {
+ keyout = NCONF_get_string(req_conf, section, KEYFILE);
+ if (keyout == NULL)
+ ERR_clear_error();
+ }
- if (keyout == NULL) {
- keyout = NCONF_get_string(req_conf, SECTION, KEYFILE);
+ if (pkey != NULL && (keyfile == NULL || keyout != NULL)) {
+ if (verbose) {
+ BIO_printf(bio_err, "Writing private key to ");
if (keyout == NULL)
- ERR_clear_error();
+ BIO_printf(bio_err, "stdout\n");
+ else
+ BIO_printf(bio_err, "'%s'\n", keyout);
}
-
- if (keyout == NULL)
- BIO_printf(bio_err, "writing new private key to stdout\n");
- else
- BIO_printf(bio_err, "writing new private key to '%s'\n", keyout);
- out = bio_open_owner(keyout, outformat, private);
+ out = bio_open_owner(keyout, outformat, newreq);
if (out == NULL)
goto end;
- p = NCONF_get_string(req_conf, SECTION, "encrypt_rsa_key");
+ p = NCONF_get_string(req_conf, section, "encrypt_rsa_key");
if (p == NULL) {
ERR_clear_error();
- p = NCONF_get_string(req_conf, SECTION, "encrypt_key");
+ p = NCONF_get_string(req_conf, section, "encrypt_key");
if (p == NULL)
ERR_clear_error();
}
if ((p != NULL) && (strcmp(p, "no") == 0))
cipher = NULL;
- if (nodes)
+ if (noenc)
cipher = NULL;
i = 0;
loop:
- assert(private);
if (!PEM_write_bio_PrivateKey(out, pkey, cipher,
NULL, 0, NULL, passout)) {
if ((ERR_GET_REASON(ERR_peek_error()) ==
@@ -685,112 +734,151 @@ int req_main(int argc, char **argv)
BIO_printf(bio_err, "-----\n");
}
+ /*
+ * subj is expected to be in the format /type0=value0/type1=value1/type2=...
+ * where characters may be escaped by \
+ */
+ if (subj != NULL
+ && (fsubj = parse_name(subj, chtype, multirdn, "subject")) == NULL)
+ goto end;
+
if (!newreq) {
- in = bio_open_default(infile, 'r', informat);
- if (in == NULL)
+ req = load_csr(infile /* if NULL, reads from stdin */,
+ informat, "X509 request");
+ if (req == NULL)
goto end;
+ }
- if (informat == FORMAT_ASN1)
- req = d2i_X509_REQ_bio(in, NULL);
- else
- req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
- if (req == NULL) {
- BIO_printf(bio_err, "unable to load X509 request\n");
+ if (CAkeyfile == NULL)
+ CAkeyfile = CAfile;
+ if (CAkeyfile != NULL) {
+ if (CAfile == NULL) {
+ BIO_printf(bio_err,
+ "Warning: Ignoring -CAkey option since no -CA option is given\n");
+ } else {
+ if ((CAkey = load_key(CAkeyfile, FORMAT_UNDEF,
+ 0, passin, e,
+ CAkeyfile != CAfile
+ ? "issuer private key from -CAkey arg"
+ : "issuer private key from -CA arg")) == NULL)
+ goto end;
+ }
+ }
+ if (CAfile != NULL) {
+ if ((CAcert = load_cert_pass(CAfile, FORMAT_UNDEF, 1, passin,
+ "issuer cert from -CA arg")) == NULL)
+ goto end;
+ if (!X509_check_private_key(CAcert, CAkey)) {
+ BIO_printf(bio_err,
+ "Issuer CA certificate and key do not match\n");
goto end;
}
}
-
- if (newreq || x509) {
- if (pkey == NULL) {
- BIO_printf(bio_err, "you need to specify a private key\n");
+ if (newreq || gen_x509) {
+ if (CAcert == NULL && pkey == NULL) {
+ BIO_printf(bio_err, "Must provide a signature key using -key or"
+ " provide -CA / -CAkey\n");
goto end;
}
if (req == NULL) {
- req = X509_REQ_new();
+ req = X509_REQ_new_ex(app_get0_libctx(), app_get0_propq());
if (req == NULL) {
goto end;
}
- i = make_REQ(req, pkey, subj, multirdn, !x509, chtype);
- subj = NULL; /* done processing '-subj' option */
- if (!i) {
- BIO_printf(bio_err, "problems making Certificate Request\n");
+ if (!make_REQ(req, pkey, fsubj, multirdn, !gen_x509, chtype)){
+ BIO_printf(bio_err, "Error making certificate request\n");
goto end;
}
+ /* Note that -x509 can take over -key and -subj option values. */
}
- if (x509) {
- EVP_PKEY *tmppkey;
+ if (gen_x509) {
+ EVP_PKEY *pub_key = X509_REQ_get0_pubkey(req);
+ EVP_PKEY *issuer_key = CAcert != NULL ? CAkey : pkey;
X509V3_CTX ext_ctx;
- if ((x509ss = X509_new()) == NULL)
- goto end;
+ X509_NAME *issuer = CAcert != NULL ? X509_get_subject_name(CAcert) :
+ X509_REQ_get_subject_name(req);
+ X509_NAME *n_subj = fsubj != NULL ? fsubj :
+ X509_REQ_get_subject_name(req);
- /* Set version to V3 */
- if ((extensions != NULL || addext_conf != NULL)
- && !X509_set_version(x509ss, 2))
+ if ((new_x509 = X509_new_ex(app_get0_libctx(),
+ app_get0_propq())) == NULL)
goto end;
+
if (serial != NULL) {
- if (!X509_set_serialNumber(x509ss, serial))
+ if (!X509_set_serialNumber(new_x509, serial))
goto end;
} else {
- if (!rand_serial(NULL, X509_get_serialNumber(x509ss)))
+ if (!rand_serial(NULL, X509_get_serialNumber(new_x509)))
goto end;
}
- if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req)))
+ if (!X509_set_issuer_name(new_x509, issuer))
goto end;
- if (days == 0) {
- /* set default days if it's not specified */
- days = 30;
+ if (days == UNSET_DAYS) {
+ days = DEFAULT_DAYS;
}
- if (!set_cert_times(x509ss, NULL, NULL, days))
+ if (!set_cert_times(new_x509, NULL, NULL, days))
+ goto end;
+ if (!X509_set_subject_name(new_x509, n_subj))
goto end;
- if (!X509_set_subject_name
- (x509ss, X509_REQ_get_subject_name(req)))
+ if (!pub_key || !X509_set_pubkey(new_x509, pub_key))
goto end;
- tmppkey = X509_REQ_get0_pubkey(req);
- if (!tmppkey || !X509_set_pubkey(x509ss, tmppkey))
+ if (ext_copy == EXT_COPY_UNSET) {
+ if (infile != NULL)
+ BIO_printf(bio_err, "Warning: No -copy_extensions given; ignoring any extensions in the request\n");
+ } else if (!copy_extensions(new_x509, req, ext_copy)) {
+ BIO_printf(bio_err, "Error copying extensions from request\n");
goto end;
+ }
/* Set up V3 context struct */
-
- X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0);
+ X509V3_set_ctx(&ext_ctx, CAcert != NULL ? CAcert : new_x509,
+ new_x509, NULL, NULL, X509V3_CTX_REPLACE);
+ /* prepare fallback for AKID, but only if issuer cert == new_x509 */
+ if (CAcert == NULL) {
+ if (!X509V3_set_issuer_pkey(&ext_ctx, issuer_key))
+ goto end;
+ ERR_set_mark();
+ if (!X509_check_private_key(new_x509, issuer_key))
+ BIO_printf(bio_err,
+ "Warning: Signature key and public key of cert do not match\n");
+ ERR_pop_to_mark();
+ }
X509V3_set_nconf(&ext_ctx, req_conf);
/* Add extensions */
- if (extensions != NULL && !X509V3_EXT_add_nconf(req_conf,
- &ext_ctx, extensions,
- x509ss)) {
- BIO_printf(bio_err, "Error Loading extension section %s\n",
+ if (extensions != NULL
+ && !X509V3_EXT_add_nconf(req_conf, &ext_ctx, extensions,
+ new_x509)) {
+ BIO_printf(bio_err, "Error adding x509 extensions from section %s\n",
extensions);
goto end;
}
if (addext_conf != NULL
&& !X509V3_EXT_add_nconf(addext_conf, &ext_ctx, "default",
- x509ss)) {
- BIO_printf(bio_err, "Error Loading command line extensions\n");
+ new_x509)) {
+ BIO_printf(bio_err, "Error adding extensions defined via -addext\n");
goto end;
}
/* If a pre-cert was requested, we need to add a poison extension */
if (precert) {
- if (X509_add1_ext_i2d(x509ss, NID_ct_precert_poison, NULL, 1, 0)
- != 1) {
+ if (X509_add1_ext_i2d(new_x509, NID_ct_precert_poison,
+ NULL, 1, 0) != 1) {
BIO_printf(bio_err, "Error adding poison extension\n");
goto end;
}
}
- i = do_X509_sign(x509ss, pkey, digest, sigopts);
- if (!i) {
- ERR_print_errors(bio_err);
+ i = do_X509_sign(new_x509, issuer_key, digest, sigopts, &ext_ctx);
+ if (!i)
goto end;
- }
} else {
X509V3_CTX ext_ctx;
/* Set up V3 context struct */
-
X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
X509V3_set_nconf(&ext_ctx, req_conf);
@@ -798,49 +886,39 @@ int req_main(int argc, char **argv)
if (req_exts != NULL
&& !X509V3_EXT_REQ_add_nconf(req_conf, &ext_ctx,
req_exts, req)) {
- BIO_printf(bio_err, "Error Loading extension section %s\n",
+ BIO_printf(bio_err, "Error adding request extensions from section %s\n",
req_exts);
goto end;
}
if (addext_conf != NULL
&& !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx, "default",
req)) {
- BIO_printf(bio_err, "Error Loading command line extensions\n");
+ BIO_printf(bio_err, "Error adding extensions defined via -addext\n");
goto end;
}
i = do_X509_REQ_sign(req, pkey, digest, sigopts);
- if (!i) {
- ERR_print_errors(bio_err);
+ if (!i)
goto end;
- }
}
}
- if (subj && x509) {
- BIO_printf(bio_err, "Cannot modify certificate subject\n");
- goto end;
- }
-
- if (subj && !x509) {
+ if (subj != NULL && !newreq && !gen_x509) {
if (verbose) {
- BIO_printf(bio_err, "Modifying Request's Subject\n");
- print_name(bio_err, "old subject=",
- X509_REQ_get_subject_name(req), get_nameopt());
+ BIO_printf(out, "Modifying subject of certificate request\n");
+ print_name(out, "Old subject=", X509_REQ_get_subject_name(req));
}
- if (build_subject(req, subj, chtype, multirdn) == 0) {
- BIO_printf(bio_err, "ERROR: cannot modify subject\n");
- ret = 1;
+ if (!X509_REQ_set_subject_name(req, fsubj)) {
+ BIO_printf(bio_err, "Error modifying subject of certificate request\n");
goto end;
}
if (verbose) {
- print_name(bio_err, "new subject=",
- X509_REQ_get_subject_name(req), get_nameopt());
+ print_name(out, "New subject=", X509_REQ_get_subject_name(req));
}
}
- if (verify && !x509) {
+ if (verify) {
EVP_PKEY *tpubkey = pkey;
if (tpubkey == NULL) {
@@ -849,16 +927,14 @@ int req_main(int argc, char **argv)
goto end;
}
- i = X509_REQ_verify(req, tpubkey);
+ i = do_X509_REQ_verify(req, tpubkey, vfyopts);
- if (i < 0) {
+ if (i < 0)
goto end;
- } else if (i == 0) {
- BIO_printf(bio_err, "verify failure\n");
- ERR_print_errors(bio_err);
- } else { /* if (i > 0) */
- BIO_printf(bio_err, "verify OK\n");
- }
+ if (i == 0)
+ BIO_printf(bio_err, "Certificate request self-signature verify failure\n");
+ else /* i > 0 */
+ BIO_printf(bio_err, "Certificate request self-signature verify OK\n");
}
if (noout && !text && !modulus && !subject && !pubkey) {
@@ -878,62 +954,58 @@ int req_main(int argc, char **argv)
if (tpubkey == NULL) {
BIO_printf(bio_err, "Error getting public key\n");
- ERR_print_errors(bio_err);
goto end;
}
PEM_write_bio_PUBKEY(out, tpubkey);
}
if (text) {
- if (x509)
- ret = X509_print_ex(out, x509ss, get_nameopt(), reqflag);
+ if (gen_x509)
+ ret = X509_print_ex(out, new_x509, get_nameopt(), reqflag);
else
ret = X509_REQ_print_ex(out, req, get_nameopt(), reqflag);
if (ret == 0) {
- if (x509)
- BIO_printf(bio_err, "Error printing certificate\n");
+ if (gen_x509)
+ BIO_printf(bio_err, "Error printing certificate\n");
else
- BIO_printf(bio_err, "Error printing certificate request\n");
-
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Error printing certificate request\n");
goto end;
}
}
if (subject) {
- if (x509)
- print_name(out, "subject=", X509_get_subject_name(x509ss),
- get_nameopt());
- else
- print_name(out, "subject=", X509_REQ_get_subject_name(req),
- get_nameopt());
+ print_name(out, "subject=", gen_x509
+ ? X509_get_subject_name(new_x509)
+ : X509_REQ_get_subject_name(req));
}
if (modulus) {
EVP_PKEY *tpubkey;
- if (x509)
- tpubkey = X509_get0_pubkey(x509ss);
+ if (gen_x509)
+ tpubkey = X509_get0_pubkey(new_x509);
else
tpubkey = X509_REQ_get0_pubkey(req);
if (tpubkey == NULL) {
- fprintf(stdout, "Modulus=unavailable\n");
+ fprintf(stdout, "Modulus is unavailable\n");
goto end;
}
fprintf(stdout, "Modulus=");
-#ifndef OPENSSL_NO_RSA
- if (EVP_PKEY_base_id(tpubkey) == EVP_PKEY_RSA) {
- const BIGNUM *n;
- RSA_get0_key(EVP_PKEY_get0_RSA(tpubkey), &n, NULL, NULL);
+ if (EVP_PKEY_is_a(tpubkey, "RSA") || EVP_PKEY_is_a(tpubkey, "RSA-PSS")) {
+ BIGNUM *n = NULL;
+
+ if (!EVP_PKEY_get_bn_param(tpubkey, "n", &n))
+ goto end;
BN_print(out, n);
- } else
-#endif
+ BN_free(n);
+ } else {
fprintf(stdout, "Wrong Algorithm type");
+ }
fprintf(stdout, "\n");
}
- if (!noout && !x509) {
+ if (!noout && !gen_x509) {
if (outformat == FORMAT_ASN1)
i = i2d_X509_REQ_bio(out, req);
else if (newhdr)
@@ -941,17 +1013,17 @@ int req_main(int argc, char **argv)
else
i = PEM_write_bio_X509_REQ(out, req);
if (!i) {
- BIO_printf(bio_err, "unable to write X509 request\n");
+ BIO_printf(bio_err, "Unable to write certificate request\n");
goto end;
}
}
- if (!noout && x509 && (x509ss != NULL)) {
+ if (!noout && gen_x509 && new_x509 != NULL) {
if (outformat == FORMAT_ASN1)
- i = i2d_X509_bio(out, x509ss);
+ i = i2d_X509_bio(out, new_x509);
else
- i = PEM_write_bio_X509(out, x509ss);
+ i = PEM_write_bio_X509(out, new_x509);
if (!i) {
- BIO_printf(bio_err, "unable to write X509 certificate\n");
+ BIO_printf(bio_err, "Unable to write X509 certificate\n");
goto end;
}
}
@@ -963,20 +1035,23 @@ int req_main(int argc, char **argv)
NCONF_free(req_conf);
NCONF_free(addext_conf);
BIO_free(addext_bio);
- BIO_free(in);
BIO_free_all(out);
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(genctx);
sk_OPENSSL_STRING_free(pkeyopts);
sk_OPENSSL_STRING_free(sigopts);
+ sk_OPENSSL_STRING_free(vfyopts);
lh_OPENSSL_STRING_doall(addexts, exts_cleanup);
lh_OPENSSL_STRING_free(addexts);
#ifndef OPENSSL_NO_ENGINE
- ENGINE_free(gen_eng);
+ release_engine(gen_eng);
#endif
OPENSSL_free(keyalgstr);
X509_REQ_free(req);
- X509_free(x509ss);
+ X509_NAME_free(fsubj);
+ X509_free(new_x509);
+ X509_free(CAcert);
+ EVP_PKEY_free(CAkey);
ASN1_INTEGER_free(serial);
release_engine(e);
if (passin != nofree_passin)
@@ -986,50 +1061,48 @@ int req_main(int argc, char **argv)
return ret;
}
-static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn,
- int attribs, unsigned long chtype)
+static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, X509_NAME *fsubj,
+ int multirdn, int attribs, unsigned long chtype)
{
int ret = 0, i;
char no_prompt = 0;
- STACK_OF(CONF_VALUE) *dn_sk, *attr_sk = NULL;
+ STACK_OF(CONF_VALUE) *dn_sk = NULL, *attr_sk = NULL;
char *tmp, *dn_sect, *attr_sect;
- tmp = NCONF_get_string(req_conf, SECTION, PROMPT);
+ tmp = NCONF_get_string(req_conf, section, PROMPT);
if (tmp == NULL)
ERR_clear_error();
if ((tmp != NULL) && strcmp(tmp, "no") == 0)
no_prompt = 1;
- dn_sect = NCONF_get_string(req_conf, SECTION, DISTINGUISHED_NAME);
+ dn_sect = NCONF_get_string(req_conf, section, DISTINGUISHED_NAME);
if (dn_sect == NULL) {
- BIO_printf(bio_err, "unable to find '%s' in config\n",
- DISTINGUISHED_NAME);
- goto err;
- }
- dn_sk = NCONF_get_section(req_conf, dn_sect);
- if (dn_sk == NULL) {
- BIO_printf(bio_err, "unable to get '%s' section\n", dn_sect);
- goto err;
+ ERR_clear_error();
+ } else {
+ dn_sk = NCONF_get_section(req_conf, dn_sect);
+ if (dn_sk == NULL) {
+ BIO_printf(bio_err, "Unable to get '%s' section\n", dn_sect);
+ goto err;
+ }
}
- attr_sect = NCONF_get_string(req_conf, SECTION, ATTRIBUTES);
+ attr_sect = NCONF_get_string(req_conf, section, ATTRIBUTES);
if (attr_sect == NULL) {
ERR_clear_error();
- attr_sk = NULL;
} else {
attr_sk = NCONF_get_section(req_conf, attr_sect);
if (attr_sk == NULL) {
- BIO_printf(bio_err, "unable to get '%s' section\n", attr_sect);
+ BIO_printf(bio_err, "Unable to get '%s' section\n", attr_sect);
goto err;
}
}
- /* setup version number */
- if (!X509_REQ_set_version(req, 0L))
- goto err; /* version 1 */
+ /* so far there is only version 1 */
+ if (!X509_REQ_set_version(req, X509_REQ_VERSION_1))
+ goto err;
- if (subj)
- i = build_subject(req, subj, chtype, multirdn);
+ if (fsubj != NULL)
+ i = X509_REQ_set_subject_name(req, fsubj);
else if (no_prompt)
i = auto_info(req, dn_sk, attr_sk, attribs, chtype);
else
@@ -1046,26 +1119,6 @@ static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn,
return ret;
}
-/*
- * subject is expected to be in the format /type0=value0/type1=value1/type2=...
- * where characters may be escaped by \
- */
-static int build_subject(X509_REQ *req, const char *subject, unsigned long chtype,
- int multirdn)
-{
- X509_NAME *n;
-
- if ((n = parse_name(subject, chtype, multirdn)) == NULL)
- return 0;
-
- if (!X509_REQ_set_subject_name(req, n)) {
- X509_NAME_free(n);
- return 0;
- }
- X509_NAME_free(n);
- return 1;
-}
-
static int prompt_info(X509_REQ *req,
STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect,
STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect,
@@ -1079,8 +1132,7 @@ static int prompt_info(X509_REQ *req,
char *type, *value;
const char *def;
CONF_VALUE *v;
- X509_NAME *subj;
- subj = X509_REQ_get_subject_name(req);
+ X509_NAME *subj = X509_REQ_get_subject_name(req);
if (!batch) {
BIO_printf(bio_err,
@@ -1100,7 +1152,7 @@ static int prompt_info(X509_REQ *req,
if (sk_CONF_VALUE_num(dn_sk)) {
i = -1;
start:
- for ( ; ; ) {
+ for (;;) {
i++;
if (sk_CONF_VALUE_num(dn_sk) <= i)
break;
@@ -1152,7 +1204,6 @@ static int prompt_info(X509_REQ *req,
n_min = -1;
}
-
if (!join(buf, sizeof(buf), v->name, "_max", "Name"))
return 0;
if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) {
@@ -1165,8 +1216,7 @@ static int prompt_info(X509_REQ *req,
return 0;
}
if (X509_NAME_entry_count(subj) == 0) {
- BIO_printf(bio_err,
- "error, no objects specified in config file\n");
+ BIO_printf(bio_err, "Error: No objects specified in config file\n");
return 0;
}
@@ -1181,7 +1231,7 @@ static int prompt_info(X509_REQ *req,
i = -1;
start2:
- for ( ; ; ) {
+ for (;;) {
i++;
if ((attr_sk == NULL) || (sk_CONF_VALUE_num(attr_sk) <= i))
break;
@@ -1207,7 +1257,7 @@ static int prompt_info(X509_REQ *req,
value = NULL;
}
- if (!join(buf, sizeof(buf), type,"_min", "Name"))
+ if (!join(buf, sizeof(buf), type, "_min", "Name"))
return 0;
if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) {
ERR_clear_error();
@@ -1258,10 +1308,10 @@ static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk,
*/
for (p = v->name; *p; p++) {
#ifndef CHARSET_EBCDIC
- spec_char = ((*p == ':') || (*p == ',') || (*p == '.'));
+ spec_char = (*p == ':' || *p == ',' || *p == '.');
#else
- spec_char = ((*p == os_toascii[':']) || (*p == os_toascii[','])
- || (*p == os_toascii['.']));
+ spec_char = (*p == os_toascii[':'] || *p == os_toascii[',']
+ || *p == os_toascii['.']);
#endif
if (spec_char) {
p++;
@@ -1289,7 +1339,7 @@ static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk,
}
if (!X509_NAME_entry_count(subj)) {
- BIO_printf(bio_err, "error, no objects specified in config file\n");
+ BIO_printf(bio_err, "Error: No objects specified in config file\n");
return 0;
}
if (attribs) {
@@ -1339,19 +1389,15 @@ static int add_attribute_object(X509_REQ *req, char *text, const char *def,
if (!X509_REQ_add1_attr_by_NID(req, nid, chtype,
(unsigned char *)buf, -1)) {
BIO_printf(bio_err, "Error adding attribute\n");
- ERR_print_errors(bio_err);
ret = 0;
}
return ret;
}
-
-static int build_data(char *text, const char *def,
- char *value, int n_min, int n_max,
- char *buf, const int buf_size,
- const char *desc1, const char *desc2
- )
+static int build_data(char *text, const char *def, char *value,
+ int n_min, int n_max, char *buf, const int buf_size,
+ const char *desc1, const char *desc2)
{
int i;
start:
@@ -1386,7 +1432,7 @@ static int build_data(char *text, const char *def,
i = strlen(buf);
if (buf[i - 1] != '\n') {
- BIO_printf(bio_err, "weird input :-(\n");
+ BIO_printf(bio_err, "Missing newline at end of input\n");
return 0;
}
buf[--i] = '\0';
@@ -1403,16 +1449,14 @@ static int build_data(char *text, const char *def,
static int req_check_len(int len, int n_min, int n_max)
{
- if ((n_min > 0) && (len < n_min)) {
+ if (n_min > 0 && len < n_min) {
BIO_printf(bio_err,
- "string is too short, it needs to be at least %d bytes long\n",
- n_min);
+ "String too short, must be at least %d bytes long\n", n_min);
return 0;
}
- if ((n_max >= 0) && (len > n_max)) {
+ if (n_max >= 0 && len > n_max) {
BIO_printf(bio_err,
- "string is too long, it needs to be no more than %d bytes long\n",
- n_max);
+ "String too long, must be at most %d bytes long\n", n_max);
return 0;
}
return 1;
@@ -1451,66 +1495,71 @@ static int join(char buf[], size_t buf_size, const char *name,
}
static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr,
- int *pkey_type, long *pkeylen,
- char **palgnam, ENGINE *keygen_engine)
+ char **pkeytype, long *pkeylen,
+ ENGINE *keygen_engine)
{
EVP_PKEY_CTX *gctx = NULL;
EVP_PKEY *param = NULL;
long keylen = -1;
BIO *pbio = NULL;
+ const char *keytype = NULL;
+ size_t keytypelen = 0;
+ int expect_paramfile = 0;
const char *paramfile = NULL;
+ /* Treat the first part of gstr, and only that */
if (gstr == NULL) {
- *pkey_type = EVP_PKEY_RSA;
+ /*
+ * Special case: when no string given, default to RSA and the
+ * key length given by |*pkeylen|.
+ */
+ keytype = "RSA";
keylen = *pkeylen;
} else if (gstr[0] >= '0' && gstr[0] <= '9') {
- *pkey_type = EVP_PKEY_RSA;
- keylen = atol(gstr);
- *pkeylen = keylen;
- } else if (strncmp(gstr, "param:", 6) == 0) {
- paramfile = gstr + 6;
+ /* Special case: only keylength given from string, so default to RSA */
+ keytype = "RSA";
+ /* The second part treatment will do the rest */
} else {
const char *p = strchr(gstr, ':');
int len;
- ENGINE *tmpeng;
- const EVP_PKEY_ASN1_METHOD *ameth;
if (p != NULL)
len = p - gstr;
else
len = strlen(gstr);
- /*
- * The lookup of a the string will cover all engines so keep a note
- * of the implementation.
- */
- ameth = EVP_PKEY_asn1_find_str(&tmpeng, gstr, len);
-
- if (ameth == NULL) {
- BIO_printf(bio_err, "Unknown algorithm %.*s\n", len, gstr);
- return NULL;
- }
-
- EVP_PKEY_asn1_get0_info(NULL, pkey_type, NULL, NULL, NULL, ameth);
-#ifndef OPENSSL_NO_ENGINE
- ENGINE_finish(tmpeng);
-#endif
- if (*pkey_type == EVP_PKEY_RSA) {
- if (p != NULL) {
- keylen = atol(p + 1);
- *pkeylen = keylen;
- } else {
- keylen = *pkeylen;
+ if (strncmp(gstr, "param", len) == 0) {
+ expect_paramfile = 1;
+ if (p == NULL) {
+ BIO_printf(bio_err,
+ "Parameter file requested but no path given: %s\n",
+ gstr);
+ return NULL;
}
- } else if (p != NULL) {
- paramfile = p + 1;
+ } else {
+ keytype = gstr;
+ keytypelen = len;
}
+
+ if (p != NULL)
+ gstr = gstr + len + 1;
+ else
+ gstr = NULL;
+ }
+
+ /* Treat the second part of gstr, if there is one */
+ if (gstr != NULL) {
+ /* If the second part starts with a digit, we assume it's a size */
+ if (!expect_paramfile && gstr[0] >= '0' && gstr[0] <= '9')
+ keylen = atol(gstr);
+ else
+ paramfile = gstr;
}
if (paramfile != NULL) {
pbio = BIO_new_file(paramfile, "r");
if (pbio == NULL) {
- BIO_printf(bio_err, "Can't open parameter file %s\n", paramfile);
+ BIO_printf(bio_err, "Cannot open parameter file %s\n", paramfile);
return NULL;
}
param = PEM_read_bio_Parameters(pbio, NULL);
@@ -1532,62 +1581,83 @@ static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr,
BIO_printf(bio_err, "Error reading parameter file %s\n", paramfile);
return NULL;
}
- if (*pkey_type == -1) {
- *pkey_type = EVP_PKEY_id(param);
- } else if (*pkey_type != EVP_PKEY_base_id(param)) {
- BIO_printf(bio_err, "Key Type does not match parameters\n");
- EVP_PKEY_free(param);
- return NULL;
+ if (keytype == NULL) {
+ keytype = EVP_PKEY_get0_type_name(param);
+ if (keytype == NULL) {
+ EVP_PKEY_free(param);
+ BIO_puts(bio_err, "Unable to determine key type\n");
+ return NULL;
+ }
}
}
- if (palgnam != NULL) {
- const EVP_PKEY_ASN1_METHOD *ameth;
- ENGINE *tmpeng;
- const char *anam;
+ if (keytypelen > 0)
+ *pkeytype = OPENSSL_strndup(keytype, keytypelen);
+ else
+ *pkeytype = OPENSSL_strdup(keytype);
- ameth = EVP_PKEY_asn1_find(&tmpeng, *pkey_type);
- if (ameth == NULL) {
- BIO_puts(bio_err, "Internal error: can't find key algorithm\n");
- return NULL;
- }
- EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &anam, ameth);
- *palgnam = OPENSSL_strdup(anam);
-#ifndef OPENSSL_NO_ENGINE
- ENGINE_finish(tmpeng);
-#endif
+ if (*pkeytype == NULL) {
+ BIO_printf(bio_err, "Out of memory\n");
+ EVP_PKEY_free(param);
+ return NULL;
}
+ if (keylen >= 0)
+ *pkeylen = keylen;
+
if (param != NULL) {
- gctx = EVP_PKEY_CTX_new(param, keygen_engine);
- *pkeylen = EVP_PKEY_bits(param);
+ if (!EVP_PKEY_is_a(param, *pkeytype)) {
+ BIO_printf(bio_err, "Key type does not match parameters\n");
+ EVP_PKEY_free(param);
+ return NULL;
+ }
+
+ if (keygen_engine != NULL)
+ gctx = EVP_PKEY_CTX_new(param, keygen_engine);
+ else
+ gctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(),
+ param, app_get0_propq());
+ *pkeylen = EVP_PKEY_get_bits(param);
EVP_PKEY_free(param);
} else {
- gctx = EVP_PKEY_CTX_new_id(*pkey_type, keygen_engine);
+ if (keygen_engine != NULL) {
+ int pkey_id = get_legacy_pkey_id(app_get0_libctx(), *pkeytype,
+ keygen_engine);
+
+ if (pkey_id != NID_undef)
+ gctx = EVP_PKEY_CTX_new_id(pkey_id, keygen_engine);
+ } else {
+ gctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(),
+ *pkeytype, app_get0_propq());
+ }
}
if (gctx == NULL) {
BIO_puts(bio_err, "Error allocating keygen context\n");
- ERR_print_errors(bio_err);
return NULL;
}
if (EVP_PKEY_keygen_init(gctx) <= 0) {
BIO_puts(bio_err, "Error initializing keygen context\n");
- ERR_print_errors(bio_err);
EVP_PKEY_CTX_free(gctx);
return NULL;
}
-#ifndef OPENSSL_NO_RSA
- if ((*pkey_type == EVP_PKEY_RSA) && (keylen != -1)) {
- if (EVP_PKEY_CTX_set_rsa_keygen_bits(gctx, keylen) <= 0) {
- BIO_puts(bio_err, "Error setting RSA keysize\n");
- ERR_print_errors(bio_err);
+ if (keylen == -1 && (EVP_PKEY_CTX_is_a(gctx, "RSA")
+ || EVP_PKEY_CTX_is_a(gctx, "RSA-PSS")))
+ keylen = *pkeylen;
+
+ if (keylen != -1) {
+ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ size_t bits = keylen;
+
+ params[0] =
+ OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_BITS, &bits);
+ if (EVP_PKEY_CTX_set_params(gctx, params) <= 0) {
+ BIO_puts(bio_err, "Error setting keysize\n");
EVP_PKEY_CTX_free(gctx);
return NULL;
}
}
-#endif
return gctx;
}
@@ -1610,70 +1680,3 @@ static int genpkey_cb(EVP_PKEY_CTX *ctx)
(void)BIO_flush(b);
return 1;
}
-
-static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey,
- const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts)
-{
- EVP_PKEY_CTX *pkctx = NULL;
- int i, def_nid;
-
- if (ctx == NULL)
- return 0;
- /*
- * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is mandatory
- * for this algorithm.
- */
- if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) == 2
- && def_nid == NID_undef) {
- /* The signing algorithm requires there to be no digest */
- md = NULL;
- }
- if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey))
- return 0;
- for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
- char *sigopt = sk_OPENSSL_STRING_value(sigopts, i);
- if (pkey_ctrl_string(pkctx, sigopt) <= 0) {
- BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt);
- ERR_print_errors(bio_err);
- return 0;
- }
- }
- return 1;
-}
-
-int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md,
- STACK_OF(OPENSSL_STRING) *sigopts)
-{
- int rv;
- EVP_MD_CTX *mctx = EVP_MD_CTX_new();
-
- rv = do_sign_init(mctx, pkey, md, sigopts);
- if (rv > 0)
- rv = X509_sign_ctx(x, mctx);
- EVP_MD_CTX_free(mctx);
- return rv > 0 ? 1 : 0;
-}
-
-int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md,
- STACK_OF(OPENSSL_STRING) *sigopts)
-{
- int rv;
- EVP_MD_CTX *mctx = EVP_MD_CTX_new();
- rv = do_sign_init(mctx, pkey, md, sigopts);
- if (rv > 0)
- rv = X509_REQ_sign_ctx(x, mctx);
- EVP_MD_CTX_free(mctx);
- return rv > 0 ? 1 : 0;
-}
-
-int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md,
- STACK_OF(OPENSSL_STRING) *sigopts)
-{
- int rv;
- EVP_MD_CTX *mctx = EVP_MD_CTX_new();
- rv = do_sign_init(mctx, pkey, md, sigopts);
- if (rv > 0)
- rv = X509_CRL_sign_ctx(x, mctx);
- EVP_MD_CTX_free(mctx);
- return rv > 0 ? 1 : 0;
-}
diff --git a/apps/rsa.c b/apps/rsa.c
index aeda917cc768..0da342c38f2c 100644
--- a/apps/rsa.c
+++ b/apps/rsa.c
@@ -1,13 +1,17 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* Necessary for legacy RSA public key export */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <openssl/opensslconf.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -21,60 +25,119 @@
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/bn.h>
+#include <openssl/encoder.h>
+
+/*
+ * This include is to get OSSL_KEYMGMT_SELECT_*, which feels a bit
+ * much just for those macros... they might serve better as EVP macros.
+ */
+#include <openssl/core_dispatch.h>
+
+#ifndef OPENSSL_NO_RC4
+# define DEFAULT_PVK_ENCR_STRENGTH 2
+#else
+# define DEFAULT_PVK_ENCR_STRENGTH 0
+#endif
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT,
OPT_PUBIN, OPT_PUBOUT, OPT_PASSOUT, OPT_PASSIN,
OPT_RSAPUBKEY_IN, OPT_RSAPUBKEY_OUT,
/* Do not change the order here; see case statements below */
OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG,
- OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_CHECK, OPT_CIPHER
+ OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_CHECK, OPT_CIPHER,
+ OPT_PROV_ENUM, OPT_TRADITIONAL
} OPTION_CHOICE;
const OPTIONS rsa_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'f', "Input format, one of DER PEM"},
- {"outform", OPT_OUTFORM, 'f', "Output format, one of DER PEM PVK"},
+ {"check", OPT_CHECK, '-', "Verify key consistency"},
+ {"", OPT_CIPHER, '-', "Any supported cipher"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, 's', "Input file"},
- {"out", OPT_OUT, '>', "Output file"},
+ {"inform", OPT_INFORM, 'f', "Input format (DER/PEM/P12/ENGINE)"},
{"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
- {"pubout", OPT_PUBOUT, '-', "Output a public key"},
- {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
- {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"RSAPublicKey_in", OPT_RSAPUBKEY_IN, '-', "Input is an RSAPublicKey"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'f', "Output format, one of DER PEM PVK"},
+ {"pubout", OPT_PUBOUT, '-', "Output a public key"},
{"RSAPublicKey_out", OPT_RSAPUBKEY_OUT, '-', "Output is an RSAPublicKey"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
{"noout", OPT_NOOUT, '-', "Don't print key out"},
{"text", OPT_TEXT, '-', "Print the key in text"},
{"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"},
- {"check", OPT_CHECK, '-', "Verify key consistency"},
- {"", OPT_CIPHER, '-', "Any supported cipher"},
-#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4)
+ {"traditional", OPT_TRADITIONAL, '-',
+ "Use traditional format for private keys"},
+
+#ifndef OPENSSL_NO_RC4
+ OPT_SECTION("PVK"),
{"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"},
{"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"},
{"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"},
#endif
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
+
+ OPT_PROV_OPTIONS,
{NULL}
};
+static int try_legacy_encoding(EVP_PKEY *pkey, int outformat, int pubout,
+ BIO *out)
+{
+ int ret = 0;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ const RSA *rsa = EVP_PKEY_get0_RSA(pkey);
+
+ if (rsa == NULL)
+ return 0;
+
+ if (outformat == FORMAT_ASN1) {
+ if (pubout == 2)
+ ret = i2d_RSAPublicKey_bio(out, rsa) > 0;
+ else
+ ret = i2d_RSA_PUBKEY_bio(out, rsa) > 0;
+ } else if (outformat == FORMAT_PEM) {
+ if (pubout == 2)
+ ret = PEM_write_bio_RSAPublicKey(out, rsa) > 0;
+ else
+ ret = PEM_write_bio_RSA_PUBKEY(out, rsa) > 0;
+# ifndef OPENSSL_NO_DSA
+ } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) {
+ ret = i2b_PublicKey_bio(out, pkey) > 0;
+# endif
+ }
+#endif
+
+ return ret;
+}
+
int rsa_main(int argc, char **argv)
{
ENGINE *e = NULL;
BIO *out = NULL;
- RSA *rsa = NULL;
- const EVP_CIPHER *enc = NULL;
- char *infile = NULL, *outfile = NULL, *prog;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *pctx;
+ EVP_CIPHER *enc = NULL;
+ char *infile = NULL, *outfile = NULL, *ciphername = NULL, *prog;
char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL;
- int i, private = 0;
- int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, check = 0;
+ int private = 0;
+ int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, text = 0, check = 0;
int noout = 0, modulus = 0, pubin = 0, pubout = 0, ret = 1;
-#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4)
- int pvk_encr = 2;
-#endif
+ int pvk_encr = DEFAULT_PVK_ENCR_STRENGTH;
OPTION_CHOICE o;
+ int traditional = 0;
+ const char *output_type = NULL;
+ const char *output_structure = NULL;
+ int selection = 0;
+ OSSL_ENCODER_CTX *ectx = NULL;
prog = opt_init(argc, argv, rsa_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -126,9 +189,7 @@ int rsa_main(int argc, char **argv)
case OPT_PVK_STRONG: /* pvk_encr:= 2 */
case OPT_PVK_WEAK: /* pvk_encr:= 1 */
case OPT_PVK_NONE: /* pvk_encr:= 0 */
-#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4)
pvk_encr = (o - OPT_PVK_NONE);
-#endif
break;
case OPT_NOOUT:
noout = 1;
@@ -143,15 +204,27 @@ int rsa_main(int argc, char **argv)
check = 1;
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &enc))
- goto opthelp;
+ ciphername = opt_unknown();
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
+ case OPT_TRADITIONAL:
+ traditional = 1;
break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
+ if (ciphername != NULL) {
+ if (!opt_cipher(ciphername, &enc))
+ goto opthelp;
+ }
private = (text && !pubin) || (!pubout && !noout) ? 1 : 0;
if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
@@ -163,34 +236,31 @@ int rsa_main(int argc, char **argv)
goto end;
}
- {
- EVP_PKEY *pkey;
+ if (pubin) {
+ int tmpformat = FORMAT_UNDEF;
- if (pubin) {
- int tmpformat = -1;
- if (pubin == 2) {
- if (informat == FORMAT_PEM)
- tmpformat = FORMAT_PEMRSA;
- else if (informat == FORMAT_ASN1)
- tmpformat = FORMAT_ASN1RSA;
- } else {
- tmpformat = informat;
- }
-
- pkey = load_pubkey(infile, tmpformat, 1, passin, e, "Public Key");
+ if (pubin == 2) {
+ if (informat == FORMAT_PEM)
+ tmpformat = FORMAT_PEMRSA;
+ else if (informat == FORMAT_ASN1)
+ tmpformat = FORMAT_ASN1RSA;
} else {
- pkey = load_key(infile, informat, 1, passin, e, "Private Key");
+ tmpformat = informat;
}
- if (pkey != NULL)
- rsa = EVP_PKEY_get1_RSA(pkey);
- EVP_PKEY_free(pkey);
+ pkey = load_pubkey(infile, tmpformat, 1, passin, e, "public key");
+ } else {
+ pkey = load_key(infile, informat, 1, passin, e, "private key");
}
- if (rsa == NULL) {
+ if (pkey == NULL) {
ERR_print_errors(bio_err);
goto end;
}
+ if (!EVP_PKEY_is_a(pkey, "RSA") && !EVP_PKEY_is_a(pkey, "RSA-PSS")) {
+ BIO_printf(bio_err, "Not an RSA key\n");
+ goto end;
+ }
out = bio_open_owner(outfile, outformat, private);
if (out == NULL)
@@ -198,7 +268,8 @@ int rsa_main(int argc, char **argv)
if (text) {
assert(pubin || private);
- if (!RSA_print(out, rsa, 0)) {
+ if ((pubin && EVP_PKEY_print_public(out, pkey, 0, NULL) <= 0)
+ || (!pubin && EVP_PKEY_print_private(out, pkey, 0, NULL) <= 0)) {
perror(outfile);
ERR_print_errors(bio_err);
goto end;
@@ -206,30 +277,34 @@ int rsa_main(int argc, char **argv)
}
if (modulus) {
- const BIGNUM *n;
- RSA_get0_key(rsa, &n, NULL, NULL);
+ BIGNUM *n = NULL;
+
+ /* Every RSA key has an 'n' */
+ EVP_PKEY_get_bn_param(pkey, "n", &n);
BIO_printf(out, "Modulus=");
BN_print(out, n);
BIO_printf(out, "\n");
+ BN_free(n);
}
if (check) {
- int r = RSA_check_key_ex(rsa, NULL);
+ int r;
+
+ pctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
+ if (pctx == NULL) {
+ BIO_printf(bio_err, "RSA unable to create PKEY context\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ r = EVP_PKEY_check(pctx);
+ EVP_PKEY_CTX_free(pctx);
if (r == 1) {
BIO_printf(out, "RSA key ok\n");
} else if (r == 0) {
- unsigned long err;
-
- while ((err = ERR_peek_error()) != 0 &&
- ERR_GET_LIB(err) == ERR_LIB_RSA &&
- ERR_GET_FUNC(err) == RSA_F_RSA_CHECK_KEY_EX &&
- ERR_GET_REASON(err) != ERR_R_MALLOC_FAILURE) {
- BIO_printf(out, "RSA key error: %s\n",
- ERR_reason_error_string(err));
- ERR_get_error(); /* remove err from error stack */
- }
- } else if (r == -1) {
+ BIO_printf(bio_err, "RSA key not ok\n");
+ ERR_print_errors(bio_err);
+ } else if (r < 0) {
ERR_print_errors(bio_err);
goto end;
}
@@ -240,71 +315,100 @@ int rsa_main(int argc, char **argv)
goto end;
}
BIO_printf(bio_err, "writing RSA key\n");
+
+ /* Choose output type for the format */
if (outformat == FORMAT_ASN1) {
- if (pubout || pubin) {
- if (pubout == 2)
- i = i2d_RSAPublicKey_bio(out, rsa);
- else
- i = i2d_RSA_PUBKEY_bio(out, rsa);
- } else {
- assert(private);
- i = i2d_RSAPrivateKey_bio(out, rsa);
- }
+ output_type = "DER";
} else if (outformat == FORMAT_PEM) {
+ output_type = "PEM";
+ } else if (outformat == FORMAT_MSBLOB) {
+ output_type = "MSBLOB";
+ } else if (outformat == FORMAT_PVK) {
+ if (pubin) {
+ BIO_printf(bio_err, "PVK form impossible with public key input\n");
+ goto end;
+ }
+ output_type = "PVK";
+ } else {
+ BIO_printf(bio_err, "bad output format specified for outfile\n");
+ goto end;
+ }
+
+ /* Select what you want in the output */
+ if (pubout || pubin) {
+ selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+ } else {
+ assert(private);
+ selection = (OSSL_KEYMGMT_SELECT_KEYPAIR
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
+ }
+
+ /* For DER based output, select the desired output structure */
+ if (outformat == FORMAT_ASN1 || outformat == FORMAT_PEM) {
if (pubout || pubin) {
if (pubout == 2)
- i = PEM_write_bio_RSAPublicKey(out, rsa);
+ output_structure = "pkcs1"; /* "type-specific" would work too */
else
- i = PEM_write_bio_RSA_PUBKEY(out, rsa);
+ output_structure = "SubjectPublicKeyInfo";
} else {
assert(private);
- i = PEM_write_bio_RSAPrivateKey(out, rsa,
- enc, NULL, 0, NULL, passout);
+ if (traditional)
+ output_structure = "pkcs1"; /* "type-specific" would work too */
+ else
+ output_structure = "PrivateKeyInfo";
}
-#ifndef OPENSSL_NO_DSA
- } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) {
- EVP_PKEY *pk;
- pk = EVP_PKEY_new();
- if (pk == NULL)
- goto end;
+ }
- EVP_PKEY_set1_RSA(pk, rsa);
- if (outformat == FORMAT_PVK) {
- if (pubin) {
- BIO_printf(bio_err, "PVK form impossible with public key input\n");
- EVP_PKEY_free(pk);
- goto end;
- }
- assert(private);
-# ifdef OPENSSL_NO_RC4
- BIO_printf(bio_err, "PVK format not supported\n");
- EVP_PKEY_free(pk);
+ /* Now, perform the encoding */
+ ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection,
+ output_type, output_structure,
+ NULL);
+ if (OSSL_ENCODER_CTX_get_num_encoders(ectx) == 0) {
+ if ((!pubout && !pubin)
+ || !try_legacy_encoding(pkey, outformat, pubout, out))
+ BIO_printf(bio_err, "%s format not supported\n", output_type);
+ else
+ ret = 0;
+ goto end;
+ }
+
+ /* Passphrase setup */
+ if (enc != NULL)
+ OSSL_ENCODER_CTX_set_cipher(ectx, EVP_CIPHER_get0_name(enc), NULL);
+
+ /* Default passphrase prompter */
+ if (enc != NULL || outformat == FORMAT_PVK) {
+ OSSL_ENCODER_CTX_set_passphrase_ui(ectx, get_ui_method(), NULL);
+ if (passout != NULL)
+ /* When passout given, override the passphrase prompter */
+ OSSL_ENCODER_CTX_set_passphrase(ectx,
+ (const unsigned char *)passout,
+ strlen(passout));
+ }
+
+ /* PVK is a bit special... */
+ if (outformat == FORMAT_PVK) {
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] = OSSL_PARAM_construct_int("encrypt-level", &pvk_encr);
+ if (!OSSL_ENCODER_CTX_set_params(ectx, params)) {
+ BIO_printf(bio_err, "invalid PVK encryption level\n");
goto end;
-# else
- i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout);
-# endif
- } else if (pubin || pubout) {
- i = i2b_PublicKey_bio(out, pk);
- } else {
- assert(private);
- i = i2b_PrivateKey_bio(out, pk);
}
- EVP_PKEY_free(pk);
-#endif
- } else {
- BIO_printf(bio_err, "bad output format specified for outfile\n");
- goto end;
}
- if (i <= 0) {
+
+ if (!OSSL_ENCODER_to_bio(ectx, out)) {
BIO_printf(bio_err, "unable to write key\n");
ERR_print_errors(bio_err);
- } else {
- ret = 0;
+ goto end;
}
+ ret = 0;
end:
+ OSSL_ENCODER_CTX_free(ectx);
release_engine(e);
BIO_free_all(out);
- RSA_free(rsa);
+ EVP_PKEY_free(pkey);
+ EVP_CIPHER_free(enc);
OPENSSL_free(passin);
OPENSSL_free(passout);
return ret;
diff --git a/apps/rsautl.c b/apps/rsautl.c
index 0c0fa8eba30a..df29069bc1f4 100644
--- a/apps/rsautl.c
+++ b/apps/rsautl.c
@@ -1,13 +1,14 @@
/*
- * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/opensslconf.h>
+
#include "apps.h"
#include "progs.h"
#include <string.h>
@@ -25,40 +26,46 @@
#define KEY_CERT 3
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_ENGINE, OPT_IN, OPT_OUT, OPT_ASN1PARSE, OPT_HEXDUMP,
- OPT_RAW, OPT_OAEP, OPT_SSL, OPT_PKCS, OPT_X931,
+ OPT_RSA_RAW, OPT_OAEP, OPT_PKCS, OPT_X931,
OPT_SIGN, OPT_VERIFY, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT,
OPT_PUBIN, OPT_CERTIN, OPT_INKEY, OPT_PASSIN, OPT_KEYFORM,
- OPT_R_ENUM
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS rsautl_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"sign", OPT_SIGN, '-', "Sign with private key"},
+ {"verify", OPT_VERIFY, '-', "Verify with public key"},
+ {"encrypt", OPT_ENCRYPT, '-', "Encrypt with public key"},
+ {"decrypt", OPT_DECRYPT, '-', "Decrypt with private key"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file"},
- {"out", OPT_OUT, '>', "Output file"},
{"inkey", OPT_INKEY, 's', "Input key"},
- {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"},
+ {"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"},
{"pubin", OPT_PUBIN, '-', "Input is an RSA public"},
{"certin", OPT_CERTIN, '-', "Input is a cert carrying an RSA public key"},
- {"ssl", OPT_SSL, '-', "Use SSL v2 padding"},
- {"raw", OPT_RAW, '-', "Use no padding"},
+ {"rev", OPT_REV, '-', "Reverse the order of the input buffer"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"raw", OPT_RSA_RAW, '-', "Use no padding"},
{"pkcs", OPT_PKCS, '-', "Use PKCS#1 v1.5 padding (default)"},
+ {"x931", OPT_X931, '-', "Use ANSI X9.31 padding"},
{"oaep", OPT_OAEP, '-', "Use PKCS#1 OAEP"},
- {"sign", OPT_SIGN, '-', "Sign with private key"},
- {"verify", OPT_VERIFY, '-', "Verify with public key"},
{"asn1parse", OPT_ASN1PARSE, '-',
"Run output through asn1parse; useful with -verify"},
{"hexdump", OPT_HEXDUMP, '-', "Hex dump output"},
- {"x931", OPT_X931, '-', "Use ANSI X9.31 padding"},
- {"rev", OPT_REV, '-', "Reverse the order of the input buffer"},
- {"encrypt", OPT_ENCRYPT, '-', "Encrypt with public key"},
- {"decrypt", OPT_DECRYPT, '-', "Decrypt with private key"},
- {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+
OPT_R_OPTIONS,
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -67,14 +74,15 @@ int rsautl_main(int argc, char **argv)
BIO *in = NULL, *out = NULL;
ENGINE *e = NULL;
EVP_PKEY *pkey = NULL;
- RSA *rsa = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
X509 *x;
char *infile = NULL, *outfile = NULL, *keyfile = NULL;
char *passinarg = NULL, *passin = NULL, *prog;
char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY;
unsigned char *rsa_in = NULL, *rsa_out = NULL, pad = RSA_PKCS1_PADDING;
- int rsa_inlen, keyformat = FORMAT_PEM, keysize, ret = 1;
- int rsa_outlen = 0, hexdump = 0, asn1parse = 0, need_priv = 0, rev = 0;
+ size_t rsa_inlen, rsa_outlen = 0;
+ int keyformat = FORMAT_UNDEF, keysize, ret = 1, rv;
+ int hexdump = 0, asn1parse = 0, need_priv = 0, rev = 0;
OPTION_CHOICE o;
prog = opt_init(argc, argv, rsautl_options);
@@ -90,7 +98,7 @@ int rsautl_main(int argc, char **argv)
ret = 0;
goto end;
case OPT_KEYFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyformat))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat))
goto opthelp;
break;
case OPT_IN:
@@ -108,15 +116,12 @@ int rsautl_main(int argc, char **argv)
case OPT_HEXDUMP:
hexdump = 1;
break;
- case OPT_RAW:
+ case OPT_RSA_RAW:
pad = RSA_NO_PADDING;
break;
case OPT_OAEP:
pad = RSA_PKCS1_OAEP_PADDING;
break;
- case OPT_SSL:
- pad = RSA_SSLV23_PADDING;
- break;
case OPT_PKCS:
pad = RSA_PKCS1_PADDING;
break;
@@ -156,12 +161,21 @@ int rsautl_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
+ if (!app_RAND_load())
+ goto end;
+
if (need_priv && (key_type != KEY_PRIVKEY)) {
BIO_printf(bio_err, "A private key is needed for this operation\n");
goto end;
@@ -174,15 +188,15 @@ int rsautl_main(int argc, char **argv)
switch (key_type) {
case KEY_PRIVKEY:
- pkey = load_key(keyfile, keyformat, 0, passin, e, "Private Key");
+ pkey = load_key(keyfile, keyformat, 0, passin, e, "private key");
break;
case KEY_PUBKEY:
- pkey = load_pubkey(keyfile, keyformat, 0, NULL, e, "Public Key");
+ pkey = load_pubkey(keyfile, keyformat, 0, NULL, e, "public key");
break;
case KEY_CERT:
- x = load_cert(keyfile, keyformat, "Certificate");
+ x = load_cert(keyfile, FORMAT_UNDEF, "Certificate");
if (x) {
pkey = X509_get_pubkey(x);
X509_free(x);
@@ -193,15 +207,6 @@ int rsautl_main(int argc, char **argv)
if (pkey == NULL)
return 1;
- rsa = EVP_PKEY_get1_RSA(pkey);
- EVP_PKEY_free(pkey);
-
- if (rsa == NULL) {
- BIO_printf(bio_err, "Error getting RSA key\n");
- ERR_print_errors(bio_err);
- goto end;
- }
-
in = bio_open_default(infile, 'r', FORMAT_BINARY);
if (in == NULL)
goto end;
@@ -209,48 +214,58 @@ int rsautl_main(int argc, char **argv)
if (out == NULL)
goto end;
- keysize = RSA_size(rsa);
+ keysize = EVP_PKEY_get_size(pkey);
rsa_in = app_malloc(keysize * 2, "hold rsa key");
rsa_out = app_malloc(keysize, "output rsa key");
+ rsa_outlen = keysize;
/* Read the input data */
- rsa_inlen = BIO_read(in, rsa_in, keysize * 2);
- if (rsa_inlen < 0) {
+ rv = BIO_read(in, rsa_in, keysize * 2);
+ if (rv < 0) {
BIO_printf(bio_err, "Error reading input Data\n");
goto end;
}
+ rsa_inlen = rv;
if (rev) {
- int i;
+ size_t i;
unsigned char ctmp;
+
for (i = 0; i < rsa_inlen / 2; i++) {
ctmp = rsa_in[i];
rsa_in[i] = rsa_in[rsa_inlen - 1 - i];
rsa_in[rsa_inlen - 1 - i] = ctmp;
}
}
- switch (rsa_mode) {
+ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL)
+ goto end;
+
+ switch (rsa_mode) {
case RSA_VERIFY:
- rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
+ rv = EVP_PKEY_verify_recover_init(ctx) > 0
+ && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0
+ && EVP_PKEY_verify_recover(ctx, rsa_out, &rsa_outlen,
+ rsa_in, rsa_inlen) > 0;
break;
-
case RSA_SIGN:
- rsa_outlen =
- RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
+ rv = EVP_PKEY_sign_init(ctx) > 0
+ && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0
+ && EVP_PKEY_sign(ctx, rsa_out, &rsa_outlen, rsa_in, rsa_inlen) > 0;
break;
-
case RSA_ENCRYPT:
- rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
+ rv = EVP_PKEY_encrypt_init(ctx) > 0
+ && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0
+ && EVP_PKEY_encrypt(ctx, rsa_out, &rsa_outlen, rsa_in, rsa_inlen) > 0;
break;
-
case RSA_DECRYPT:
- rsa_outlen =
- RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
+ rv = EVP_PKEY_decrypt_init(ctx) > 0
+ && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0
+ && EVP_PKEY_decrypt(ctx, rsa_out, &rsa_outlen, rsa_in, rsa_inlen) > 0;
break;
}
- if (rsa_outlen < 0) {
+ if (!rv) {
BIO_printf(bio_err, "RSA operation error\n");
ERR_print_errors(bio_err);
goto end;
@@ -266,7 +281,8 @@ int rsautl_main(int argc, char **argv)
BIO_write(out, rsa_out, rsa_outlen);
}
end:
- RSA_free(rsa);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
release_engine(e);
BIO_free(in);
BIO_free_all(out);
diff --git a/apps/s_apps.h b/apps/s_apps.h
deleted file mode 100644
index f94e659e71e3..000000000000
--- a/apps/s_apps.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <openssl/opensslconf.h>
-
-#include <openssl/ssl.h>
-
-#define PORT "4433"
-#define PROTOCOL "tcp"
-
-typedef int (*do_server_cb)(int s, int stype, int prot, unsigned char *context);
-int do_server(int *accept_sock, const char *host, const char *port,
- int family, int type, int protocol, do_server_cb cb,
- unsigned char *context, int naccept, BIO *bio_s_out);
-
-int verify_callback(int ok, X509_STORE_CTX *ctx);
-
-int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file);
-int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
- STACK_OF(X509) *chain, int build_chain);
-int ssl_print_sigalgs(BIO *out, SSL *s);
-int ssl_print_point_formats(BIO *out, SSL *s);
-int ssl_print_groups(BIO *out, SSL *s, int noshared);
-int ssl_print_tmp_key(BIO *out, SSL *s);
-int init_client(int *sock, const char *host, const char *port,
- const char *bindhost, const char *bindport,
- int family, int type, int protocol);
-int should_retry(int i);
-
-long bio_dump_callback(BIO *bio, int cmd, const char *argp,
- int argi, long argl, long ret);
-
-void apps_ssl_info_callback(const SSL *s, int where, int ret);
-void msg_cb(int write_p, int version, int content_type, const void *buf,
- size_t len, SSL *ssl, void *arg);
-void tlsext_cb(SSL *s, int client_server, int type, const unsigned char *data,
- int len, void *arg);
-
-int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
- unsigned int *cookie_len);
-int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
- unsigned int cookie_len);
-
-#ifdef __VMS /* 31 char symbol name limit */
-# define generate_stateless_cookie_callback generate_stateless_cookie_cb
-# define verify_stateless_cookie_callback verify_stateless_cookie_cb
-#endif
-
-int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie,
- size_t *cookie_len);
-int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie,
- size_t cookie_len);
-
-typedef struct ssl_excert_st SSL_EXCERT;
-
-void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc);
-void ssl_excert_free(SSL_EXCERT *exc);
-int args_excert(int option, SSL_EXCERT **pexc);
-int load_excert(SSL_EXCERT **pexc);
-void print_verify_detail(SSL *s, BIO *bio);
-void print_ssl_summary(SSL *s);
-int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str, SSL_CTX *ctx);
-int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls,
- int crl_download);
-int ssl_load_stores(SSL_CTX *ctx, const char *vfyCApath,
- const char *vfyCAfile, const char *chCApath,
- const char *chCAfile, STACK_OF(X509_CRL) *crls,
- int crl_download);
-void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose);
-int set_keylog_file(SSL_CTX *ctx, const char *keylog_file);
-void print_ca_names(BIO *bio, SSL *s);
diff --git a/apps/s_cb.c b/apps/s_cb.c
deleted file mode 100644
index 2f94c13393a5..000000000000
--- a/apps/s_cb.c
+++ /dev/null
@@ -1,1548 +0,0 @@
-/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/* callback functions used by s_client, s_server, and s_time */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h> /* for memcpy() and strcmp() */
-#include "apps.h"
-#include <openssl/err.h>
-#include <openssl/rand.h>
-#include <openssl/x509.h>
-#include <openssl/ssl.h>
-#include <openssl/bn.h>
-#ifndef OPENSSL_NO_DH
-# include <openssl/dh.h>
-#endif
-#include "s_apps.h"
-
-#define COOKIE_SECRET_LENGTH 16
-
-VERIFY_CB_ARGS verify_args = { -1, 0, X509_V_OK, 0 };
-
-#ifndef OPENSSL_NO_SOCK
-static unsigned char cookie_secret[COOKIE_SECRET_LENGTH];
-static int cookie_initialized = 0;
-#endif
-static BIO *bio_keylog = NULL;
-
-static const char *lookup(int val, const STRINT_PAIR* list, const char* def)
-{
- for ( ; list->name; ++list)
- if (list->retval == val)
- return list->name;
- return def;
-}
-
-int verify_callback(int ok, X509_STORE_CTX *ctx)
-{
- X509 *err_cert;
- int err, depth;
-
- err_cert = X509_STORE_CTX_get_current_cert(ctx);
- err = X509_STORE_CTX_get_error(ctx);
- depth = X509_STORE_CTX_get_error_depth(ctx);
-
- if (!verify_args.quiet || !ok) {
- BIO_printf(bio_err, "depth=%d ", depth);
- if (err_cert != NULL) {
- X509_NAME_print_ex(bio_err,
- X509_get_subject_name(err_cert),
- 0, get_nameopt());
- BIO_puts(bio_err, "\n");
- } else {
- BIO_puts(bio_err, "<no cert>\n");
- }
- }
- if (!ok) {
- BIO_printf(bio_err, "verify error:num=%d:%s\n", err,
- X509_verify_cert_error_string(err));
- if (verify_args.depth < 0 || verify_args.depth >= depth) {
- if (!verify_args.return_error)
- ok = 1;
- verify_args.error = err;
- } else {
- ok = 0;
- verify_args.error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
- }
- }
- switch (err) {
- case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
- if (err_cert != NULL) {
- BIO_puts(bio_err, "issuer= ");
- X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert),
- 0, get_nameopt());
- BIO_puts(bio_err, "\n");
- }
- break;
- case X509_V_ERR_CERT_NOT_YET_VALID:
- case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
- if (err_cert != NULL) {
- BIO_printf(bio_err, "notBefore=");
- ASN1_TIME_print(bio_err, X509_get0_notBefore(err_cert));
- BIO_printf(bio_err, "\n");
- }
- break;
- case X509_V_ERR_CERT_HAS_EXPIRED:
- case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
- if (err_cert != NULL) {
- BIO_printf(bio_err, "notAfter=");
- ASN1_TIME_print(bio_err, X509_get0_notAfter(err_cert));
- BIO_printf(bio_err, "\n");
- }
- break;
- case X509_V_ERR_NO_EXPLICIT_POLICY:
- if (!verify_args.quiet)
- policies_print(ctx);
- break;
- }
- if (err == X509_V_OK && ok == 2 && !verify_args.quiet)
- policies_print(ctx);
- if (ok && !verify_args.quiet)
- BIO_printf(bio_err, "verify return:%d\n", ok);
- return ok;
-}
-
-int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file)
-{
- if (cert_file != NULL) {
- if (SSL_CTX_use_certificate_file(ctx, cert_file,
- SSL_FILETYPE_PEM) <= 0) {
- BIO_printf(bio_err, "unable to get certificate from '%s'\n",
- cert_file);
- ERR_print_errors(bio_err);
- return 0;
- }
- if (key_file == NULL)
- key_file = cert_file;
- if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) {
- BIO_printf(bio_err, "unable to get private key from '%s'\n",
- key_file);
- ERR_print_errors(bio_err);
- return 0;
- }
-
- /*
- * If we are using DSA, we can copy the parameters from the private
- * key
- */
-
- /*
- * Now we know that a key and cert have been set against the SSL
- * context
- */
- if (!SSL_CTX_check_private_key(ctx)) {
- BIO_printf(bio_err,
- "Private key does not match the certificate public key\n");
- return 0;
- }
- }
- return 1;
-}
-
-int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
- STACK_OF(X509) *chain, int build_chain)
-{
- int chflags = chain ? SSL_BUILD_CHAIN_FLAG_CHECK : 0;
- if (cert == NULL)
- return 1;
- if (SSL_CTX_use_certificate(ctx, cert) <= 0) {
- BIO_printf(bio_err, "error setting certificate\n");
- ERR_print_errors(bio_err);
- return 0;
- }
-
- if (SSL_CTX_use_PrivateKey(ctx, key) <= 0) {
- BIO_printf(bio_err, "error setting private key\n");
- ERR_print_errors(bio_err);
- return 0;
- }
-
- /*
- * Now we know that a key and cert have been set against the SSL context
- */
- if (!SSL_CTX_check_private_key(ctx)) {
- BIO_printf(bio_err,
- "Private key does not match the certificate public key\n");
- return 0;
- }
- if (chain && !SSL_CTX_set1_chain(ctx, chain)) {
- BIO_printf(bio_err, "error setting certificate chain\n");
- ERR_print_errors(bio_err);
- return 0;
- }
- if (build_chain && !SSL_CTX_build_cert_chain(ctx, chflags)) {
- BIO_printf(bio_err, "error building certificate chain\n");
- ERR_print_errors(bio_err);
- return 0;
- }
- return 1;
-}
-
-static STRINT_PAIR cert_type_list[] = {
- {"RSA sign", TLS_CT_RSA_SIGN},
- {"DSA sign", TLS_CT_DSS_SIGN},
- {"RSA fixed DH", TLS_CT_RSA_FIXED_DH},
- {"DSS fixed DH", TLS_CT_DSS_FIXED_DH},
- {"ECDSA sign", TLS_CT_ECDSA_SIGN},
- {"RSA fixed ECDH", TLS_CT_RSA_FIXED_ECDH},
- {"ECDSA fixed ECDH", TLS_CT_ECDSA_FIXED_ECDH},
- {"GOST01 Sign", TLS_CT_GOST01_SIGN},
- {"GOST12 Sign", TLS_CT_GOST12_SIGN},
- {NULL}
-};
-
-static void ssl_print_client_cert_types(BIO *bio, SSL *s)
-{
- const unsigned char *p;
- int i;
- int cert_type_num = SSL_get0_certificate_types(s, &p);
- if (!cert_type_num)
- return;
- BIO_puts(bio, "Client Certificate Types: ");
- for (i = 0; i < cert_type_num; i++) {
- unsigned char cert_type = p[i];
- const char *cname = lookup((int)cert_type, cert_type_list, NULL);
-
- if (i)
- BIO_puts(bio, ", ");
- if (cname != NULL)
- BIO_puts(bio, cname);
- else
- BIO_printf(bio, "UNKNOWN (%d),", cert_type);
- }
- BIO_puts(bio, "\n");
-}
-
-static const char *get_sigtype(int nid)
-{
- switch (nid) {
- case EVP_PKEY_RSA:
- return "RSA";
-
- case EVP_PKEY_RSA_PSS:
- return "RSA-PSS";
-
- case EVP_PKEY_DSA:
- return "DSA";
-
- case EVP_PKEY_EC:
- return "ECDSA";
-
- case NID_ED25519:
- return "Ed25519";
-
- case NID_ED448:
- return "Ed448";
-
- case NID_id_GostR3410_2001:
- return "gost2001";
-
- case NID_id_GostR3410_2012_256:
- return "gost2012_256";
-
- case NID_id_GostR3410_2012_512:
- return "gost2012_512";
-
- default:
- return NULL;
- }
-}
-
-static int do_print_sigalgs(BIO *out, SSL *s, int shared)
-{
- int i, nsig, client;
- client = SSL_is_server(s) ? 0 : 1;
- if (shared)
- nsig = SSL_get_shared_sigalgs(s, 0, NULL, NULL, NULL, NULL, NULL);
- else
- nsig = SSL_get_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL);
- if (nsig == 0)
- return 1;
-
- if (shared)
- BIO_puts(out, "Shared ");
-
- if (client)
- BIO_puts(out, "Requested ");
- BIO_puts(out, "Signature Algorithms: ");
- for (i = 0; i < nsig; i++) {
- int hash_nid, sign_nid;
- unsigned char rhash, rsign;
- const char *sstr = NULL;
- if (shared)
- SSL_get_shared_sigalgs(s, i, &sign_nid, &hash_nid, NULL,
- &rsign, &rhash);
- else
- SSL_get_sigalgs(s, i, &sign_nid, &hash_nid, NULL, &rsign, &rhash);
- if (i)
- BIO_puts(out, ":");
- sstr = get_sigtype(sign_nid);
- if (sstr)
- BIO_printf(out, "%s", sstr);
- else
- BIO_printf(out, "0x%02X", (int)rsign);
- if (hash_nid != NID_undef)
- BIO_printf(out, "+%s", OBJ_nid2sn(hash_nid));
- else if (sstr == NULL)
- BIO_printf(out, "+0x%02X", (int)rhash);
- }
- BIO_puts(out, "\n");
- return 1;
-}
-
-int ssl_print_sigalgs(BIO *out, SSL *s)
-{
- int nid;
- if (!SSL_is_server(s))
- ssl_print_client_cert_types(out, s);
- do_print_sigalgs(out, s, 0);
- do_print_sigalgs(out, s, 1);
- if (SSL_get_peer_signature_nid(s, &nid) && nid != NID_undef)
- BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(nid));
- if (SSL_get_peer_signature_type_nid(s, &nid))
- BIO_printf(out, "Peer signature type: %s\n", get_sigtype(nid));
- return 1;
-}
-
-#ifndef OPENSSL_NO_EC
-int ssl_print_point_formats(BIO *out, SSL *s)
-{
- int i, nformats;
- const char *pformats;
- nformats = SSL_get0_ec_point_formats(s, &pformats);
- if (nformats <= 0)
- return 1;
- BIO_puts(out, "Supported Elliptic Curve Point Formats: ");
- for (i = 0; i < nformats; i++, pformats++) {
- if (i)
- BIO_puts(out, ":");
- switch (*pformats) {
- case TLSEXT_ECPOINTFORMAT_uncompressed:
- BIO_puts(out, "uncompressed");
- break;
-
- case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime:
- BIO_puts(out, "ansiX962_compressed_prime");
- break;
-
- case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2:
- BIO_puts(out, "ansiX962_compressed_char2");
- break;
-
- default:
- BIO_printf(out, "unknown(%d)", (int)*pformats);
- break;
-
- }
- }
- BIO_puts(out, "\n");
- return 1;
-}
-
-int ssl_print_groups(BIO *out, SSL *s, int noshared)
-{
- int i, ngroups, *groups, nid;
- const char *gname;
-
- ngroups = SSL_get1_groups(s, NULL);
- if (ngroups <= 0)
- return 1;
- groups = app_malloc(ngroups * sizeof(int), "groups to print");
- SSL_get1_groups(s, groups);
-
- BIO_puts(out, "Supported Elliptic Groups: ");
- for (i = 0; i < ngroups; i++) {
- if (i)
- BIO_puts(out, ":");
- nid = groups[i];
- /* If unrecognised print out hex version */
- if (nid & TLSEXT_nid_unknown) {
- BIO_printf(out, "0x%04X", nid & 0xFFFF);
- } else {
- /* TODO(TLS1.3): Get group name here */
- /* Use NIST name for curve if it exists */
- gname = EC_curve_nid2nist(nid);
- if (gname == NULL)
- gname = OBJ_nid2sn(nid);
- BIO_printf(out, "%s", gname);
- }
- }
- OPENSSL_free(groups);
- if (noshared) {
- BIO_puts(out, "\n");
- return 1;
- }
- BIO_puts(out, "\nShared Elliptic groups: ");
- ngroups = SSL_get_shared_group(s, -1);
- for (i = 0; i < ngroups; i++) {
- if (i)
- BIO_puts(out, ":");
- nid = SSL_get_shared_group(s, i);
- /* TODO(TLS1.3): Convert for DH groups */
- gname = EC_curve_nid2nist(nid);
- if (gname == NULL)
- gname = OBJ_nid2sn(nid);
- BIO_printf(out, "%s", gname);
- }
- if (ngroups == 0)
- BIO_puts(out, "NONE");
- BIO_puts(out, "\n");
- return 1;
-}
-#endif
-
-int ssl_print_tmp_key(BIO *out, SSL *s)
-{
- EVP_PKEY *key;
-
- if (!SSL_get_peer_tmp_key(s, &key))
- return 1;
- BIO_puts(out, "Server Temp Key: ");
- switch (EVP_PKEY_id(key)) {
- case EVP_PKEY_RSA:
- BIO_printf(out, "RSA, %d bits\n", EVP_PKEY_bits(key));
- break;
-
- case EVP_PKEY_DH:
- BIO_printf(out, "DH, %d bits\n", EVP_PKEY_bits(key));
- break;
-#ifndef OPENSSL_NO_EC
- case EVP_PKEY_EC:
- {
- EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key);
- int nid;
- const char *cname;
- nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
- EC_KEY_free(ec);
- cname = EC_curve_nid2nist(nid);
- if (cname == NULL)
- cname = OBJ_nid2sn(nid);
- BIO_printf(out, "ECDH, %s, %d bits\n", cname, EVP_PKEY_bits(key));
- }
- break;
-#endif
- default:
- BIO_printf(out, "%s, %d bits\n", OBJ_nid2sn(EVP_PKEY_id(key)),
- EVP_PKEY_bits(key));
- }
- EVP_PKEY_free(key);
- return 1;
-}
-
-long bio_dump_callback(BIO *bio, int cmd, const char *argp,
- int argi, long argl, long ret)
-{
- BIO *out;
-
- out = (BIO *)BIO_get_callback_arg(bio);
- if (out == NULL)
- return ret;
-
- if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) {
- BIO_printf(out, "read from %p [%p] (%lu bytes => %ld (0x%lX))\n",
- (void *)bio, (void *)argp, (unsigned long)argi, ret, ret);
- BIO_dump(out, argp, (int)ret);
- return ret;
- } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) {
- BIO_printf(out, "write to %p [%p] (%lu bytes => %ld (0x%lX))\n",
- (void *)bio, (void *)argp, (unsigned long)argi, ret, ret);
- BIO_dump(out, argp, (int)ret);
- }
- return ret;
-}
-
-void apps_ssl_info_callback(const SSL *s, int where, int ret)
-{
- const char *str;
- int w;
-
- w = where & ~SSL_ST_MASK;
-
- if (w & SSL_ST_CONNECT)
- str = "SSL_connect";
- else if (w & SSL_ST_ACCEPT)
- str = "SSL_accept";
- else
- str = "undefined";
-
- if (where & SSL_CB_LOOP) {
- BIO_printf(bio_err, "%s:%s\n", str, SSL_state_string_long(s));
- } else if (where & SSL_CB_ALERT) {
- str = (where & SSL_CB_READ) ? "read" : "write";
- BIO_printf(bio_err, "SSL3 alert %s:%s:%s\n",
- str,
- SSL_alert_type_string_long(ret),
- SSL_alert_desc_string_long(ret));
- } else if (where & SSL_CB_EXIT) {
- if (ret == 0)
- BIO_printf(bio_err, "%s:failed in %s\n",
- str, SSL_state_string_long(s));
- else if (ret < 0)
- BIO_printf(bio_err, "%s:error in %s\n",
- str, SSL_state_string_long(s));
- }
-}
-
-static STRINT_PAIR ssl_versions[] = {
- {"SSL 3.0", SSL3_VERSION},
- {"TLS 1.0", TLS1_VERSION},
- {"TLS 1.1", TLS1_1_VERSION},
- {"TLS 1.2", TLS1_2_VERSION},
- {"TLS 1.3", TLS1_3_VERSION},
- {"DTLS 1.0", DTLS1_VERSION},
- {"DTLS 1.0 (bad)", DTLS1_BAD_VER},
- {NULL}
-};
-
-static STRINT_PAIR alert_types[] = {
- {" close_notify", 0},
- {" end_of_early_data", 1},
- {" unexpected_message", 10},
- {" bad_record_mac", 20},
- {" decryption_failed", 21},
- {" record_overflow", 22},
- {" decompression_failure", 30},
- {" handshake_failure", 40},
- {" bad_certificate", 42},
- {" unsupported_certificate", 43},
- {" certificate_revoked", 44},
- {" certificate_expired", 45},
- {" certificate_unknown", 46},
- {" illegal_parameter", 47},
- {" unknown_ca", 48},
- {" access_denied", 49},
- {" decode_error", 50},
- {" decrypt_error", 51},
- {" export_restriction", 60},
- {" protocol_version", 70},
- {" insufficient_security", 71},
- {" internal_error", 80},
- {" inappropriate_fallback", 86},
- {" user_canceled", 90},
- {" no_renegotiation", 100},
- {" missing_extension", 109},
- {" unsupported_extension", 110},
- {" certificate_unobtainable", 111},
- {" unrecognized_name", 112},
- {" bad_certificate_status_response", 113},
- {" bad_certificate_hash_value", 114},
- {" unknown_psk_identity", 115},
- {" certificate_required", 116},
- {NULL}
-};
-
-static STRINT_PAIR handshakes[] = {
- {", HelloRequest", SSL3_MT_HELLO_REQUEST},
- {", ClientHello", SSL3_MT_CLIENT_HELLO},
- {", ServerHello", SSL3_MT_SERVER_HELLO},
- {", HelloVerifyRequest", DTLS1_MT_HELLO_VERIFY_REQUEST},
- {", NewSessionTicket", SSL3_MT_NEWSESSION_TICKET},
- {", EndOfEarlyData", SSL3_MT_END_OF_EARLY_DATA},
- {", EncryptedExtensions", SSL3_MT_ENCRYPTED_EXTENSIONS},
- {", Certificate", SSL3_MT_CERTIFICATE},
- {", ServerKeyExchange", SSL3_MT_SERVER_KEY_EXCHANGE},
- {", CertificateRequest", SSL3_MT_CERTIFICATE_REQUEST},
- {", ServerHelloDone", SSL3_MT_SERVER_DONE},
- {", CertificateVerify", SSL3_MT_CERTIFICATE_VERIFY},
- {", ClientKeyExchange", SSL3_MT_CLIENT_KEY_EXCHANGE},
- {", Finished", SSL3_MT_FINISHED},
- {", CertificateUrl", SSL3_MT_CERTIFICATE_URL},
- {", CertificateStatus", SSL3_MT_CERTIFICATE_STATUS},
- {", SupplementalData", SSL3_MT_SUPPLEMENTAL_DATA},
- {", KeyUpdate", SSL3_MT_KEY_UPDATE},
-#ifndef OPENSSL_NO_NEXTPROTONEG
- {", NextProto", SSL3_MT_NEXT_PROTO},
-#endif
- {", MessageHash", SSL3_MT_MESSAGE_HASH},
- {NULL}
-};
-
-void msg_cb(int write_p, int version, int content_type, const void *buf,
- size_t len, SSL *ssl, void *arg)
-{
- BIO *bio = arg;
- const char *str_write_p = write_p ? ">>>" : "<<<";
- const char *str_version = lookup(version, ssl_versions, "???");
- const char *str_content_type = "", *str_details1 = "", *str_details2 = "";
- const unsigned char* bp = buf;
-
- if (version == SSL3_VERSION ||
- version == TLS1_VERSION ||
- version == TLS1_1_VERSION ||
- version == TLS1_2_VERSION ||
- version == TLS1_3_VERSION ||
- version == DTLS1_VERSION || version == DTLS1_BAD_VER) {
- switch (content_type) {
- case 20:
- str_content_type = ", ChangeCipherSpec";
- break;
- case 21:
- str_content_type = ", Alert";
- str_details1 = ", ???";
- if (len == 2) {
- switch (bp[0]) {
- case 1:
- str_details1 = ", warning";
- break;
- case 2:
- str_details1 = ", fatal";
- break;
- }
- str_details2 = lookup((int)bp[1], alert_types, " ???");
- }
- break;
- case 22:
- str_content_type = ", Handshake";
- str_details1 = "???";
- if (len > 0)
- str_details1 = lookup((int)bp[0], handshakes, "???");
- break;
- case 23:
- str_content_type = ", ApplicationData";
- break;
-#ifndef OPENSSL_NO_HEARTBEATS
- case 24:
- str_details1 = ", Heartbeat";
-
- if (len > 0) {
- switch (bp[0]) {
- case 1:
- str_details1 = ", HeartbeatRequest";
- break;
- case 2:
- str_details1 = ", HeartbeatResponse";
- break;
- }
- }
- break;
-#endif
- }
- }
-
- BIO_printf(bio, "%s %s%s [length %04lx]%s%s\n", str_write_p, str_version,
- str_content_type, (unsigned long)len, str_details1,
- str_details2);
-
- if (len > 0) {
- size_t num, i;
-
- BIO_printf(bio, " ");
- num = len;
- for (i = 0; i < num; i++) {
- if (i % 16 == 0 && i > 0)
- BIO_printf(bio, "\n ");
- BIO_printf(bio, " %02x", ((const unsigned char *)buf)[i]);
- }
- if (i < len)
- BIO_printf(bio, " ...");
- BIO_printf(bio, "\n");
- }
- (void)BIO_flush(bio);
-}
-
-static STRINT_PAIR tlsext_types[] = {
- {"server name", TLSEXT_TYPE_server_name},
- {"max fragment length", TLSEXT_TYPE_max_fragment_length},
- {"client certificate URL", TLSEXT_TYPE_client_certificate_url},
- {"trusted CA keys", TLSEXT_TYPE_trusted_ca_keys},
- {"truncated HMAC", TLSEXT_TYPE_truncated_hmac},
- {"status request", TLSEXT_TYPE_status_request},
- {"user mapping", TLSEXT_TYPE_user_mapping},
- {"client authz", TLSEXT_TYPE_client_authz},
- {"server authz", TLSEXT_TYPE_server_authz},
- {"cert type", TLSEXT_TYPE_cert_type},
- {"supported_groups", TLSEXT_TYPE_supported_groups},
- {"EC point formats", TLSEXT_TYPE_ec_point_formats},
- {"SRP", TLSEXT_TYPE_srp},
- {"signature algorithms", TLSEXT_TYPE_signature_algorithms},
- {"use SRTP", TLSEXT_TYPE_use_srtp},
- {"heartbeat", TLSEXT_TYPE_heartbeat},
- {"session ticket", TLSEXT_TYPE_session_ticket},
- {"renegotiation info", TLSEXT_TYPE_renegotiate},
- {"signed certificate timestamps", TLSEXT_TYPE_signed_certificate_timestamp},
- {"TLS padding", TLSEXT_TYPE_padding},
-#ifdef TLSEXT_TYPE_next_proto_neg
- {"next protocol", TLSEXT_TYPE_next_proto_neg},
-#endif
-#ifdef TLSEXT_TYPE_encrypt_then_mac
- {"encrypt-then-mac", TLSEXT_TYPE_encrypt_then_mac},
-#endif
-#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
- {"application layer protocol negotiation",
- TLSEXT_TYPE_application_layer_protocol_negotiation},
-#endif
-#ifdef TLSEXT_TYPE_extended_master_secret
- {"extended master secret", TLSEXT_TYPE_extended_master_secret},
-#endif
- {"key share", TLSEXT_TYPE_key_share},
- {"supported versions", TLSEXT_TYPE_supported_versions},
- {"psk", TLSEXT_TYPE_psk},
- {"psk kex modes", TLSEXT_TYPE_psk_kex_modes},
- {"certificate authorities", TLSEXT_TYPE_certificate_authorities},
- {"post handshake auth", TLSEXT_TYPE_post_handshake_auth},
- {NULL}
-};
-
-/* from rfc8446 4.2.3. + gost (https://tools.ietf.org/id/draft-smyshlyaev-tls12-gost-suites-04.html) */
-static STRINT_PAIR signature_tls13_scheme_list[] = {
- {"rsa_pkcs1_sha1", 0x0201 /* TLSEXT_SIGALG_rsa_pkcs1_sha1 */},
- {"ecdsa_sha1", 0x0203 /* TLSEXT_SIGALG_ecdsa_sha1 */},
-/* {"rsa_pkcs1_sha224", 0x0301 TLSEXT_SIGALG_rsa_pkcs1_sha224}, not in rfc8446 */
-/* {"ecdsa_sha224", 0x0303 TLSEXT_SIGALG_ecdsa_sha224} not in rfc8446 */
- {"rsa_pkcs1_sha256", 0x0401 /* TLSEXT_SIGALG_rsa_pkcs1_sha256 */},
- {"ecdsa_secp256r1_sha256", 0x0403 /* TLSEXT_SIGALG_ecdsa_secp256r1_sha256 */},
- {"rsa_pkcs1_sha384", 0x0501 /* TLSEXT_SIGALG_rsa_pkcs1_sha384 */},
- {"ecdsa_secp384r1_sha384", 0x0503 /* TLSEXT_SIGALG_ecdsa_secp384r1_sha384 */},
- {"rsa_pkcs1_sha512", 0x0601 /* TLSEXT_SIGALG_rsa_pkcs1_sha512 */},
- {"ecdsa_secp521r1_sha512", 0x0603 /* TLSEXT_SIGALG_ecdsa_secp521r1_sha512 */},
- {"rsa_pss_rsae_sha256", 0x0804 /* TLSEXT_SIGALG_rsa_pss_rsae_sha256 */},
- {"rsa_pss_rsae_sha384", 0x0805 /* TLSEXT_SIGALG_rsa_pss_rsae_sha384 */},
- {"rsa_pss_rsae_sha512", 0x0806 /* TLSEXT_SIGALG_rsa_pss_rsae_sha512 */},
- {"ed25519", 0x0807 /* TLSEXT_SIGALG_ed25519 */},
- {"ed448", 0x0808 /* TLSEXT_SIGALG_ed448 */},
- {"rsa_pss_pss_sha256", 0x0809 /* TLSEXT_SIGALG_rsa_pss_pss_sha256 */},
- {"rsa_pss_pss_sha384", 0x080a /* TLSEXT_SIGALG_rsa_pss_pss_sha384 */},
- {"rsa_pss_pss_sha512", 0x080b /* TLSEXT_SIGALG_rsa_pss_pss_sha512 */},
- {"gostr34102001", 0xeded /* TLSEXT_SIGALG_gostr34102001_gostr3411 */},
- {"gostr34102012_256", 0xeeee /* TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 */},
- {"gostr34102012_512", 0xefef /* TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 */},
- {NULL}
-};
-
-/* from rfc5246 7.4.1.4.1. */
-static STRINT_PAIR signature_tls12_alg_list[] = {
- {"anonymous", TLSEXT_signature_anonymous /* 0 */},
- {"RSA", TLSEXT_signature_rsa /* 1 */},
- {"DSA", TLSEXT_signature_dsa /* 2 */},
- {"ECDSA", TLSEXT_signature_ecdsa /* 3 */},
- {NULL}
-};
-
-/* from rfc5246 7.4.1.4.1. */
-static STRINT_PAIR signature_tls12_hash_list[] = {
- {"none", TLSEXT_hash_none /* 0 */},
- {"MD5", TLSEXT_hash_md5 /* 1 */},
- {"SHA1", TLSEXT_hash_sha1 /* 2 */},
- {"SHA224", TLSEXT_hash_sha224 /* 3 */},
- {"SHA256", TLSEXT_hash_sha256 /* 4 */},
- {"SHA384", TLSEXT_hash_sha384 /* 5 */},
- {"SHA512", TLSEXT_hash_sha512 /* 6 */},
- {NULL}
-};
-
-void tlsext_cb(SSL *s, int client_server, int type,
- const unsigned char *data, int len, void *arg)
-{
- BIO *bio = arg;
- const char *extname = lookup(type, tlsext_types, "unknown");
-
- BIO_printf(bio, "TLS %s extension \"%s\" (id=%d), len=%d\n",
- client_server ? "server" : "client", extname, type, len);
- BIO_dump(bio, (const char *)data, len);
- (void)BIO_flush(bio);
-}
-
-#ifndef OPENSSL_NO_SOCK
-int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
- unsigned int *cookie_len)
-{
- unsigned char *buffer;
- size_t length = 0;
- unsigned short port;
- BIO_ADDR *lpeer = NULL, *peer = NULL;
-
- /* Initialize a random secret */
- if (!cookie_initialized) {
- if (RAND_bytes(cookie_secret, COOKIE_SECRET_LENGTH) <= 0) {
- BIO_printf(bio_err, "error setting random cookie secret\n");
- return 0;
- }
- cookie_initialized = 1;
- }
-
- if (SSL_is_dtls(ssl)) {
- lpeer = peer = BIO_ADDR_new();
- if (peer == NULL) {
- BIO_printf(bio_err, "memory full\n");
- return 0;
- }
-
- /* Read peer information */
- (void)BIO_dgram_get_peer(SSL_get_rbio(ssl), peer);
- } else {
- peer = ourpeer;
- }
-
- /* Create buffer with peer's address and port */
- if (!BIO_ADDR_rawaddress(peer, NULL, &length)) {
- BIO_printf(bio_err, "Failed getting peer address\n");
- return 0;
- }
- OPENSSL_assert(length != 0);
- port = BIO_ADDR_rawport(peer);
- length += sizeof(port);
- buffer = app_malloc(length, "cookie generate buffer");
-
- memcpy(buffer, &port, sizeof(port));
- BIO_ADDR_rawaddress(peer, buffer + sizeof(port), NULL);
-
- /* Calculate HMAC of buffer using the secret */
- HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH,
- buffer, length, cookie, cookie_len);
-
- OPENSSL_free(buffer);
- BIO_ADDR_free(lpeer);
-
- return 1;
-}
-
-int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
- unsigned int cookie_len)
-{
- unsigned char result[EVP_MAX_MD_SIZE];
- unsigned int resultlength;
-
- /* Note: we check cookie_initialized because if it's not,
- * it cannot be valid */
- if (cookie_initialized
- && generate_cookie_callback(ssl, result, &resultlength)
- && cookie_len == resultlength
- && memcmp(result, cookie, resultlength) == 0)
- return 1;
-
- return 0;
-}
-
-int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie,
- size_t *cookie_len)
-{
- unsigned int temp;
- int res = generate_cookie_callback(ssl, cookie, &temp);
-
- if (res != 0)
- *cookie_len = temp;
- return res;
-}
-
-int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie,
- size_t cookie_len)
-{
- return verify_cookie_callback(ssl, cookie, cookie_len);
-}
-
-#endif
-
-/*
- * Example of extended certificate handling. Where the standard support of
- * one certificate per algorithm is not sufficient an application can decide
- * which certificate(s) to use at runtime based on whatever criteria it deems
- * appropriate.
- */
-
-/* Linked list of certificates, keys and chains */
-struct ssl_excert_st {
- int certform;
- const char *certfile;
- int keyform;
- const char *keyfile;
- const char *chainfile;
- X509 *cert;
- EVP_PKEY *key;
- STACK_OF(X509) *chain;
- int build_chain;
- struct ssl_excert_st *next, *prev;
-};
-
-static STRINT_PAIR chain_flags[] = {
- {"Overall Validity", CERT_PKEY_VALID},
- {"Sign with EE key", CERT_PKEY_SIGN},
- {"EE signature", CERT_PKEY_EE_SIGNATURE},
- {"CA signature", CERT_PKEY_CA_SIGNATURE},
- {"EE key parameters", CERT_PKEY_EE_PARAM},
- {"CA key parameters", CERT_PKEY_CA_PARAM},
- {"Explicitly sign with EE key", CERT_PKEY_EXPLICIT_SIGN},
- {"Issuer Name", CERT_PKEY_ISSUER_NAME},
- {"Certificate Type", CERT_PKEY_CERT_TYPE},
- {NULL}
-};
-
-static void print_chain_flags(SSL *s, int flags)
-{
- STRINT_PAIR *pp;
-
- for (pp = chain_flags; pp->name; ++pp)
- BIO_printf(bio_err, "\t%s: %s\n",
- pp->name,
- (flags & pp->retval) ? "OK" : "NOT OK");
- BIO_printf(bio_err, "\tSuite B: ");
- if (SSL_set_cert_flags(s, 0) & SSL_CERT_FLAG_SUITEB_128_LOS)
- BIO_puts(bio_err, flags & CERT_PKEY_SUITEB ? "OK\n" : "NOT OK\n");
- else
- BIO_printf(bio_err, "not tested\n");
-}
-
-/*
- * Very basic selection callback: just use any certificate chain reported as
- * valid. More sophisticated could prioritise according to local policy.
- */
-static int set_cert_cb(SSL *ssl, void *arg)
-{
- int i, rv;
- SSL_EXCERT *exc = arg;
-#ifdef CERT_CB_TEST_RETRY
- static int retry_cnt;
- if (retry_cnt < 5) {
- retry_cnt++;
- BIO_printf(bio_err,
- "Certificate callback retry test: count %d\n",
- retry_cnt);
- return -1;
- }
-#endif
- SSL_certs_clear(ssl);
-
- if (exc == NULL)
- return 1;
-
- /*
- * Go to end of list and traverse backwards since we prepend newer
- * entries this retains the original order.
- */
- while (exc->next != NULL)
- exc = exc->next;
-
- i = 0;
-
- while (exc != NULL) {
- i++;
- rv = SSL_check_chain(ssl, exc->cert, exc->key, exc->chain);
- BIO_printf(bio_err, "Checking cert chain %d:\nSubject: ", i);
- X509_NAME_print_ex(bio_err, X509_get_subject_name(exc->cert), 0,
- get_nameopt());
- BIO_puts(bio_err, "\n");
- print_chain_flags(ssl, rv);
- if (rv & CERT_PKEY_VALID) {
- if (!SSL_use_certificate(ssl, exc->cert)
- || !SSL_use_PrivateKey(ssl, exc->key)) {
- return 0;
- }
- /*
- * NB: we wouldn't normally do this as it is not efficient
- * building chains on each connection better to cache the chain
- * in advance.
- */
- if (exc->build_chain) {
- if (!SSL_build_cert_chain(ssl, 0))
- return 0;
- } else if (exc->chain != NULL) {
- if (!SSL_set1_chain(ssl, exc->chain))
- return 0;
- }
- }
- exc = exc->prev;
- }
- return 1;
-}
-
-void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc)
-{
- SSL_CTX_set_cert_cb(ctx, set_cert_cb, exc);
-}
-
-static int ssl_excert_prepend(SSL_EXCERT **pexc)
-{
- SSL_EXCERT *exc = app_malloc(sizeof(*exc), "prepend cert");
-
- memset(exc, 0, sizeof(*exc));
-
- exc->next = *pexc;
- *pexc = exc;
-
- if (exc->next) {
- exc->certform = exc->next->certform;
- exc->keyform = exc->next->keyform;
- exc->next->prev = exc;
- } else {
- exc->certform = FORMAT_PEM;
- exc->keyform = FORMAT_PEM;
- }
- return 1;
-
-}
-
-void ssl_excert_free(SSL_EXCERT *exc)
-{
- SSL_EXCERT *curr;
-
- if (exc == NULL)
- return;
- while (exc) {
- X509_free(exc->cert);
- EVP_PKEY_free(exc->key);
- sk_X509_pop_free(exc->chain, X509_free);
- curr = exc;
- exc = exc->next;
- OPENSSL_free(curr);
- }
-}
-
-int load_excert(SSL_EXCERT **pexc)
-{
- SSL_EXCERT *exc = *pexc;
- if (exc == NULL)
- return 1;
- /* If nothing in list, free and set to NULL */
- if (exc->certfile == NULL && exc->next == NULL) {
- ssl_excert_free(exc);
- *pexc = NULL;
- return 1;
- }
- for (; exc; exc = exc->next) {
- if (exc->certfile == NULL) {
- BIO_printf(bio_err, "Missing filename\n");
- return 0;
- }
- exc->cert = load_cert(exc->certfile, exc->certform,
- "Server Certificate");
- if (exc->cert == NULL)
- return 0;
- if (exc->keyfile != NULL) {
- exc->key = load_key(exc->keyfile, exc->keyform,
- 0, NULL, NULL, "Server Key");
- } else {
- exc->key = load_key(exc->certfile, exc->certform,
- 0, NULL, NULL, "Server Key");
- }
- if (exc->key == NULL)
- return 0;
- if (exc->chainfile != NULL) {
- if (!load_certs(exc->chainfile, &exc->chain, FORMAT_PEM, NULL,
- "Server Chain"))
- return 0;
- }
- }
- return 1;
-}
-
-enum range { OPT_X_ENUM };
-
-int args_excert(int opt, SSL_EXCERT **pexc)
-{
- SSL_EXCERT *exc = *pexc;
-
- assert(opt > OPT_X__FIRST);
- assert(opt < OPT_X__LAST);
-
- if (exc == NULL) {
- if (!ssl_excert_prepend(&exc)) {
- BIO_printf(bio_err, " %s: Error initialising xcert\n",
- opt_getprog());
- goto err;
- }
- *pexc = exc;
- }
-
- switch ((enum range)opt) {
- case OPT_X__FIRST:
- case OPT_X__LAST:
- return 0;
- case OPT_X_CERT:
- if (exc->certfile != NULL && !ssl_excert_prepend(&exc)) {
- BIO_printf(bio_err, "%s: Error adding xcert\n", opt_getprog());
- goto err;
- }
- *pexc = exc;
- exc->certfile = opt_arg();
- break;
- case OPT_X_KEY:
- if (exc->keyfile != NULL) {
- BIO_printf(bio_err, "%s: Key already specified\n", opt_getprog());
- goto err;
- }
- exc->keyfile = opt_arg();
- break;
- case OPT_X_CHAIN:
- if (exc->chainfile != NULL) {
- BIO_printf(bio_err, "%s: Chain already specified\n",
- opt_getprog());
- goto err;
- }
- exc->chainfile = opt_arg();
- break;
- case OPT_X_CHAIN_BUILD:
- exc->build_chain = 1;
- break;
- case OPT_X_CERTFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &exc->certform))
- return 0;
- break;
- case OPT_X_KEYFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &exc->keyform))
- return 0;
- break;
- }
- return 1;
-
- err:
- ERR_print_errors(bio_err);
- ssl_excert_free(exc);
- *pexc = NULL;
- return 0;
-}
-
-static void print_raw_cipherlist(SSL *s)
-{
- const unsigned char *rlist;
- static const unsigned char scsv_id[] = { 0, 0xFF };
- size_t i, rlistlen, num;
- if (!SSL_is_server(s))
- return;
- num = SSL_get0_raw_cipherlist(s, NULL);
- OPENSSL_assert(num == 2);
- rlistlen = SSL_get0_raw_cipherlist(s, &rlist);
- BIO_puts(bio_err, "Client cipher list: ");
- for (i = 0; i < rlistlen; i += num, rlist += num) {
- const SSL_CIPHER *c = SSL_CIPHER_find(s, rlist);
- if (i)
- BIO_puts(bio_err, ":");
- if (c != NULL) {
- BIO_puts(bio_err, SSL_CIPHER_get_name(c));
- } else if (memcmp(rlist, scsv_id, num) == 0) {
- BIO_puts(bio_err, "SCSV");
- } else {
- size_t j;
- BIO_puts(bio_err, "0x");
- for (j = 0; j < num; j++)
- BIO_printf(bio_err, "%02X", rlist[j]);
- }
- }
- BIO_puts(bio_err, "\n");
-}
-
-/*
- * Hex encoder for TLSA RRdata, not ':' delimited.
- */
-static char *hexencode(const unsigned char *data, size_t len)
-{
- static const char *hex = "0123456789abcdef";
- char *out;
- char *cp;
- size_t outlen = 2 * len + 1;
- int ilen = (int) outlen;
-
- if (outlen < len || ilen < 0 || outlen != (size_t)ilen) {
- BIO_printf(bio_err, "%s: %zu-byte buffer too large to hexencode\n",
- opt_getprog(), len);
- exit(1);
- }
- cp = out = app_malloc(ilen, "TLSA hex data buffer");
-
- while (len-- > 0) {
- *cp++ = hex[(*data >> 4) & 0x0f];
- *cp++ = hex[*data++ & 0x0f];
- }
- *cp = '\0';
- return out;
-}
-
-void print_verify_detail(SSL *s, BIO *bio)
-{
- int mdpth;
- EVP_PKEY *mspki;
- long verify_err = SSL_get_verify_result(s);
-
- if (verify_err == X509_V_OK) {
- const char *peername = SSL_get0_peername(s);
-
- BIO_printf(bio, "Verification: OK\n");
- if (peername != NULL)
- BIO_printf(bio, "Verified peername: %s\n", peername);
- } else {
- const char *reason = X509_verify_cert_error_string(verify_err);
-
- BIO_printf(bio, "Verification error: %s\n", reason);
- }
-
- if ((mdpth = SSL_get0_dane_authority(s, NULL, &mspki)) >= 0) {
- uint8_t usage, selector, mtype;
- const unsigned char *data = NULL;
- size_t dlen = 0;
- char *hexdata;
-
- mdpth = SSL_get0_dane_tlsa(s, &usage, &selector, &mtype, &data, &dlen);
-
- /*
- * The TLSA data field can be quite long when it is a certificate,
- * public key or even a SHA2-512 digest. Because the initial octets of
- * ASN.1 certificates and public keys contain mostly boilerplate OIDs
- * and lengths, we show the last 12 bytes of the data instead, as these
- * are more likely to distinguish distinct TLSA records.
- */
-#define TLSA_TAIL_SIZE 12
- if (dlen > TLSA_TAIL_SIZE)
- hexdata = hexencode(data + dlen - TLSA_TAIL_SIZE, TLSA_TAIL_SIZE);
- else
- hexdata = hexencode(data, dlen);
- BIO_printf(bio, "DANE TLSA %d %d %d %s%s %s at depth %d\n",
- usage, selector, mtype,
- (dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata,
- (mspki != NULL) ? "signed the certificate" :
- mdpth ? "matched TA certificate" : "matched EE certificate",
- mdpth);
- OPENSSL_free(hexdata);
- }
-}
-
-void print_ssl_summary(SSL *s)
-{
- const SSL_CIPHER *c;
- X509 *peer;
-
- BIO_printf(bio_err, "Protocol version: %s\n", SSL_get_version(s));
- print_raw_cipherlist(s);
- c = SSL_get_current_cipher(s);
- BIO_printf(bio_err, "Ciphersuite: %s\n", SSL_CIPHER_get_name(c));
- do_print_sigalgs(bio_err, s, 0);
- peer = SSL_get_peer_certificate(s);
- if (peer != NULL) {
- int nid;
-
- BIO_puts(bio_err, "Peer certificate: ");
- X509_NAME_print_ex(bio_err, X509_get_subject_name(peer),
- 0, get_nameopt());
- BIO_puts(bio_err, "\n");
- if (SSL_get_peer_signature_nid(s, &nid))
- BIO_printf(bio_err, "Hash used: %s\n", OBJ_nid2sn(nid));
- if (SSL_get_peer_signature_type_nid(s, &nid))
- BIO_printf(bio_err, "Signature type: %s\n", get_sigtype(nid));
- print_verify_detail(s, bio_err);
- } else {
- BIO_puts(bio_err, "No peer certificate\n");
- }
- X509_free(peer);
-#ifndef OPENSSL_NO_EC
- ssl_print_point_formats(bio_err, s);
- if (SSL_is_server(s))
- ssl_print_groups(bio_err, s, 1);
- else
- ssl_print_tmp_key(bio_err, s);
-#else
- if (!SSL_is_server(s))
- ssl_print_tmp_key(bio_err, s);
-#endif
-}
-
-int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str,
- SSL_CTX *ctx)
-{
- int i;
-
- SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
- for (i = 0; i < sk_OPENSSL_STRING_num(str); i += 2) {
- const char *flag = sk_OPENSSL_STRING_value(str, i);
- const char *arg = sk_OPENSSL_STRING_value(str, i + 1);
- if (SSL_CONF_cmd(cctx, flag, arg) <= 0) {
- if (arg != NULL)
- BIO_printf(bio_err, "Error with command: \"%s %s\"\n",
- flag, arg);
- else
- BIO_printf(bio_err, "Error with command: \"%s\"\n", flag);
- ERR_print_errors(bio_err);
- return 0;
- }
- }
- if (!SSL_CONF_CTX_finish(cctx)) {
- BIO_puts(bio_err, "Error finishing context\n");
- ERR_print_errors(bio_err);
- return 0;
- }
- return 1;
-}
-
-static int add_crls_store(X509_STORE *st, STACK_OF(X509_CRL) *crls)
-{
- X509_CRL *crl;
- int i;
- for (i = 0; i < sk_X509_CRL_num(crls); i++) {
- crl = sk_X509_CRL_value(crls, i);
- X509_STORE_add_crl(st, crl);
- }
- return 1;
-}
-
-int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, int crl_download)
-{
- X509_STORE *st;
- st = SSL_CTX_get_cert_store(ctx);
- add_crls_store(st, crls);
- if (crl_download)
- store_setup_crl_download(st);
- return 1;
-}
-
-int ssl_load_stores(SSL_CTX *ctx,
- const char *vfyCApath, const char *vfyCAfile,
- const char *chCApath, const char *chCAfile,
- STACK_OF(X509_CRL) *crls, int crl_download)
-{
- X509_STORE *vfy = NULL, *ch = NULL;
- int rv = 0;
- if (vfyCApath != NULL || vfyCAfile != NULL) {
- vfy = X509_STORE_new();
- if (vfy == NULL)
- goto err;
- if (!X509_STORE_load_locations(vfy, vfyCAfile, vfyCApath))
- goto err;
- add_crls_store(vfy, crls);
- SSL_CTX_set1_verify_cert_store(ctx, vfy);
- if (crl_download)
- store_setup_crl_download(vfy);
- }
- if (chCApath != NULL || chCAfile != NULL) {
- ch = X509_STORE_new();
- if (ch == NULL)
- goto err;
- if (!X509_STORE_load_locations(ch, chCAfile, chCApath))
- goto err;
- SSL_CTX_set1_chain_cert_store(ctx, ch);
- }
- rv = 1;
- err:
- X509_STORE_free(vfy);
- X509_STORE_free(ch);
- return rv;
-}
-
-/* Verbose print out of security callback */
-
-typedef struct {
- BIO *out;
- int verbose;
- int (*old_cb) (const SSL *s, const SSL_CTX *ctx, int op, int bits, int nid,
- void *other, void *ex);
-} security_debug_ex;
-
-static STRINT_PAIR callback_types[] = {
- {"Supported Ciphersuite", SSL_SECOP_CIPHER_SUPPORTED},
- {"Shared Ciphersuite", SSL_SECOP_CIPHER_SHARED},
- {"Check Ciphersuite", SSL_SECOP_CIPHER_CHECK},
-#ifndef OPENSSL_NO_DH
- {"Temp DH key bits", SSL_SECOP_TMP_DH},
-#endif
- {"Supported Curve", SSL_SECOP_CURVE_SUPPORTED},
- {"Shared Curve", SSL_SECOP_CURVE_SHARED},
- {"Check Curve", SSL_SECOP_CURVE_CHECK},
- {"Supported Signature Algorithm", SSL_SECOP_SIGALG_SUPPORTED},
- {"Shared Signature Algorithm", SSL_SECOP_SIGALG_SHARED},
- {"Check Signature Algorithm", SSL_SECOP_SIGALG_CHECK},
- {"Signature Algorithm mask", SSL_SECOP_SIGALG_MASK},
- {"Certificate chain EE key", SSL_SECOP_EE_KEY},
- {"Certificate chain CA key", SSL_SECOP_CA_KEY},
- {"Peer Chain EE key", SSL_SECOP_PEER_EE_KEY},
- {"Peer Chain CA key", SSL_SECOP_PEER_CA_KEY},
- {"Certificate chain CA digest", SSL_SECOP_CA_MD},
- {"Peer chain CA digest", SSL_SECOP_PEER_CA_MD},
- {"SSL compression", SSL_SECOP_COMPRESSION},
- {"Session ticket", SSL_SECOP_TICKET},
- {NULL}
-};
-
-static int security_callback_debug(const SSL *s, const SSL_CTX *ctx,
- int op, int bits, int nid,
- void *other, void *ex)
-{
- security_debug_ex *sdb = ex;
- int rv, show_bits = 1, cert_md = 0;
- const char *nm;
- int show_nm;
- rv = sdb->old_cb(s, ctx, op, bits, nid, other, ex);
- if (rv == 1 && sdb->verbose < 2)
- return 1;
- BIO_puts(sdb->out, "Security callback: ");
-
- nm = lookup(op, callback_types, NULL);
- show_nm = nm != NULL;
- switch (op) {
- case SSL_SECOP_TICKET:
- case SSL_SECOP_COMPRESSION:
- show_bits = 0;
- show_nm = 0;
- break;
- case SSL_SECOP_VERSION:
- BIO_printf(sdb->out, "Version=%s", lookup(nid, ssl_versions, "???"));
- show_bits = 0;
- show_nm = 0;
- break;
- case SSL_SECOP_CA_MD:
- case SSL_SECOP_PEER_CA_MD:
- cert_md = 1;
- break;
- case SSL_SECOP_SIGALG_SUPPORTED:
- case SSL_SECOP_SIGALG_SHARED:
- case SSL_SECOP_SIGALG_CHECK:
- case SSL_SECOP_SIGALG_MASK:
- show_nm = 0;
- break;
- }
- if (show_nm)
- BIO_printf(sdb->out, "%s=", nm);
-
- switch (op & SSL_SECOP_OTHER_TYPE) {
-
- case SSL_SECOP_OTHER_CIPHER:
- BIO_puts(sdb->out, SSL_CIPHER_get_name(other));
- break;
-
-#ifndef OPENSSL_NO_EC
- case SSL_SECOP_OTHER_CURVE:
- {
- const char *cname;
- cname = EC_curve_nid2nist(nid);
- if (cname == NULL)
- cname = OBJ_nid2sn(nid);
- BIO_puts(sdb->out, cname);
- }
- break;
-#endif
-#ifndef OPENSSL_NO_DH
- case SSL_SECOP_OTHER_DH:
- {
- DH *dh = other;
- BIO_printf(sdb->out, "%d", DH_bits(dh));
- break;
- }
-#endif
- case SSL_SECOP_OTHER_CERT:
- {
- if (cert_md) {
- int sig_nid = X509_get_signature_nid(other);
- BIO_puts(sdb->out, OBJ_nid2sn(sig_nid));
- } else {
- EVP_PKEY *pkey = X509_get0_pubkey(other);
- const char *algname = "";
- EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL,
- &algname, EVP_PKEY_get0_asn1(pkey));
- BIO_printf(sdb->out, "%s, bits=%d",
- algname, EVP_PKEY_bits(pkey));
- }
- break;
- }
- case SSL_SECOP_OTHER_SIGALG:
- {
- const unsigned char *salg = other;
- const char *sname = NULL;
- int raw_sig_code = (salg[0] << 8) + salg[1]; /* always big endian (msb, lsb) */
- /* raw_sig_code: signature_scheme from tls1.3, or signature_and_hash from tls1.2 */
-
- if (nm != NULL)
- BIO_printf(sdb->out, "%s", nm);
- else
- BIO_printf(sdb->out, "s_cb.c:security_callback_debug op=0x%x", op);
-
- sname = lookup(raw_sig_code, signature_tls13_scheme_list, NULL);
- if (sname != NULL) {
- BIO_printf(sdb->out, " scheme=%s", sname);
- } else {
- int alg_code = salg[1];
- int hash_code = salg[0];
- const char *alg_str = lookup(alg_code, signature_tls12_alg_list, NULL);
- const char *hash_str = lookup(hash_code, signature_tls12_hash_list, NULL);
-
- if (alg_str != NULL && hash_str != NULL)
- BIO_printf(sdb->out, " digest=%s, algorithm=%s", hash_str, alg_str);
- else
- BIO_printf(sdb->out, " scheme=unknown(0x%04x)", raw_sig_code);
- }
- }
-
- }
-
- if (show_bits)
- BIO_printf(sdb->out, ", security bits=%d", bits);
- BIO_printf(sdb->out, ": %s\n", rv ? "yes" : "no");
- return rv;
-}
-
-void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose)
-{
- static security_debug_ex sdb;
-
- sdb.out = bio_err;
- sdb.verbose = verbose;
- sdb.old_cb = SSL_CTX_get_security_callback(ctx);
- SSL_CTX_set_security_callback(ctx, security_callback_debug);
- SSL_CTX_set0_security_ex_data(ctx, &sdb);
-}
-
-static void keylog_callback(const SSL *ssl, const char *line)
-{
- if (bio_keylog == NULL) {
- BIO_printf(bio_err, "Keylog callback is invoked without valid file!\n");
- return;
- }
-
- /*
- * There might be concurrent writers to the keylog file, so we must ensure
- * that the given line is written at once.
- */
- BIO_printf(bio_keylog, "%s\n", line);
- (void)BIO_flush(bio_keylog);
-}
-
-int set_keylog_file(SSL_CTX *ctx, const char *keylog_file)
-{
- /* Close any open files */
- BIO_free_all(bio_keylog);
- bio_keylog = NULL;
-
- if (ctx == NULL || keylog_file == NULL) {
- /* Keylogging is disabled, OK. */
- return 0;
- }
-
- /*
- * Append rather than write in order to allow concurrent modification.
- * Furthermore, this preserves existing keylog files which is useful when
- * the tool is run multiple times.
- */
- bio_keylog = BIO_new_file(keylog_file, "a");
- if (bio_keylog == NULL) {
- BIO_printf(bio_err, "Error writing keylog file %s\n", keylog_file);
- return 1;
- }
-
- /* Write a header for seekable, empty files (this excludes pipes). */
- if (BIO_tell(bio_keylog) == 0) {
- BIO_puts(bio_keylog,
- "# SSL/TLS secrets log file, generated by OpenSSL\n");
- (void)BIO_flush(bio_keylog);
- }
- SSL_CTX_set_keylog_callback(ctx, keylog_callback);
- return 0;
-}
-
-void print_ca_names(BIO *bio, SSL *s)
-{
- const char *cs = SSL_is_server(s) ? "server" : "client";
- const STACK_OF(X509_NAME) *sk = SSL_get0_peer_CA_list(s);
- int i;
-
- if (sk == NULL || sk_X509_NAME_num(sk) == 0) {
- if (!SSL_is_server(s))
- BIO_printf(bio, "---\nNo %s certificate CA names sent\n", cs);
- return;
- }
-
- BIO_printf(bio, "---\nAcceptable %s certificate CA names\n",cs);
- for (i = 0; i < sk_X509_NAME_num(sk); i++) {
- X509_NAME_print_ex(bio, sk_X509_NAME_value(sk, i), 0, get_nameopt());
- BIO_write(bio, "\n", 1);
- }
-}
diff --git a/apps/s_client.c b/apps/s_client.c
index 00effc80375a..a9142386428d 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -1,8 +1,8 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -38,10 +38,8 @@ typedef unsigned int u_int;
#include <openssl/rand.h>
#include <openssl/ocsp.h>
#include <openssl/bn.h>
+#include <openssl/trace.h>
#include <openssl/async.h>
-#ifndef OPENSSL_NO_SRP
-# include <openssl/srp.h>
-#endif
#ifndef OPENSSL_NO_CT
# include <openssl/ct.h>
#endif
@@ -91,27 +89,6 @@ static int restore_errno(void)
return ret;
}
-static void do_ssl_shutdown(SSL *ssl)
-{
- int ret;
-
- do {
- /* We only do unidirectional shutdown */
- ret = SSL_shutdown(ssl);
- if (ret < 0) {
- switch (SSL_get_error(ssl, ret)) {
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- case SSL_ERROR_WANT_ASYNC:
- case SSL_ERROR_WANT_ASYNC_JOB:
- /* We just do busy waiting. Nothing clever */
- continue;
- }
- ret = 0;
- }
- } while (ret < 0);
-}
-
/* Default PSK identity and key */
static char *psk_identity = "Client_identity";
@@ -258,117 +235,6 @@ static int ssl_servername_cb(SSL *s, int *ad, void *arg)
return SSL_TLSEXT_ERR_OK;
}
-#ifndef OPENSSL_NO_SRP
-
-/* This is a context that we pass to all callbacks */
-typedef struct srp_arg_st {
- char *srppassin;
- char *srplogin;
- int msg; /* copy from c_msg */
- int debug; /* copy from c_debug */
- int amp; /* allow more groups */
- int strength; /* minimal size for N */
-} SRP_ARG;
-
-# define SRP_NUMBER_ITERATIONS_FOR_PRIME 64
-
-static int srp_Verify_N_and_g(const BIGNUM *N, const BIGNUM *g)
-{
- BN_CTX *bn_ctx = BN_CTX_new();
- BIGNUM *p = BN_new();
- BIGNUM *r = BN_new();
- int ret =
- g != NULL && N != NULL && bn_ctx != NULL && BN_is_odd(N) &&
- BN_is_prime_ex(N, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) == 1 &&
- p != NULL && BN_rshift1(p, N) &&
- /* p = (N-1)/2 */
- BN_is_prime_ex(p, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) == 1 &&
- r != NULL &&
- /* verify g^((N-1)/2) == -1 (mod N) */
- BN_mod_exp(r, g, p, N, bn_ctx) &&
- BN_add_word(r, 1) && BN_cmp(r, N) == 0;
-
- BN_free(r);
- BN_free(p);
- BN_CTX_free(bn_ctx);
- return ret;
-}
-
-/*-
- * This callback is used here for two purposes:
- * - extended debugging
- * - making some primality tests for unknown groups
- * The callback is only called for a non default group.
- *
- * An application does not need the call back at all if
- * only the standard groups are used. In real life situations,
- * client and server already share well known groups,
- * thus there is no need to verify them.
- * Furthermore, in case that a server actually proposes a group that
- * is not one of those defined in RFC 5054, it is more appropriate
- * to add the group to a static list and then compare since
- * primality tests are rather cpu consuming.
- */
-
-static int ssl_srp_verify_param_cb(SSL *s, void *arg)
-{
- SRP_ARG *srp_arg = (SRP_ARG *)arg;
- BIGNUM *N = NULL, *g = NULL;
-
- if (((N = SSL_get_srp_N(s)) == NULL) || ((g = SSL_get_srp_g(s)) == NULL))
- return 0;
- if (srp_arg->debug || srp_arg->msg || srp_arg->amp == 1) {
- BIO_printf(bio_err, "SRP parameters:\n");
- BIO_printf(bio_err, "\tN=");
- BN_print(bio_err, N);
- BIO_printf(bio_err, "\n\tg=");
- BN_print(bio_err, g);
- BIO_printf(bio_err, "\n");
- }
-
- if (SRP_check_known_gN_param(g, N))
- return 1;
-
- if (srp_arg->amp == 1) {
- if (srp_arg->debug)
- BIO_printf(bio_err,
- "SRP param N and g are not known params, going to check deeper.\n");
-
- /*
- * The srp_moregroups is a real debugging feature. Implementors
- * should rather add the value to the known ones. The minimal size
- * has already been tested.
- */
- if (BN_num_bits(g) <= BN_BITS && srp_Verify_N_and_g(N, g))
- return 1;
- }
- BIO_printf(bio_err, "SRP param N and g rejected.\n");
- return 0;
-}
-
-# define PWD_STRLEN 1024
-
-static char *ssl_give_srp_client_pwd_cb(SSL *s, void *arg)
-{
- SRP_ARG *srp_arg = (SRP_ARG *)arg;
- char *pass = app_malloc(PWD_STRLEN + 1, "SRP password buffer");
- PW_CB_DATA cb_tmp;
- int l;
-
- cb_tmp.password = (char *)srp_arg->srppassin;
- cb_tmp.prompt_info = "SRP user";
- if ((l = password_callback(pass, PWD_STRLEN, 0, &cb_tmp)) < 0) {
- BIO_printf(bio_err, "Can't read Password\n");
- OPENSSL_free(pass);
- return NULL;
- }
- *(pass + l) = '\0';
-
- return pass;
-}
-
-#endif
-
#ifndef OPENSSL_NO_NEXTPROTONEG
/* This the context that we pass to next_proto_cb */
typedef struct tlsextnextprotoctx_st {
@@ -563,7 +429,7 @@ static int tlsa_import_rrset(SSL *con, STACK_OF(OPENSSL_STRING) *rrset)
}
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_4, OPT_6, OPT_HOST, OPT_PORT, OPT_CONNECT, OPT_BIND, OPT_UNIX,
OPT_XMPPHOST, OPT_VERIFY, OPT_NAMEOPT,
OPT_CERT, OPT_CRL, OPT_CRL_DOWNLOAD, OPT_SESS_OUT, OPT_SESS_IN,
@@ -581,35 +447,56 @@ typedef enum OPTION_choice {
OPT_SSL3, OPT_SSL_CONFIG,
OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1,
OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_KEYFORM, OPT_PASS,
- OPT_CERT_CHAIN, OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH,
- OPT_KEY, OPT_RECONNECT, OPT_BUILD_CHAIN, OPT_CAFILE, OPT_NOCAFILE,
- OPT_CHAINCAFILE, OPT_VERIFYCAFILE, OPT_NEXTPROTONEG, OPT_ALPN,
+ OPT_CERT_CHAIN, OPT_KEY, OPT_RECONNECT, OPT_BUILD_CHAIN,
+ OPT_NEXTPROTONEG, OPT_ALPN,
+ OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH,
+ OPT_CAFILE, OPT_NOCAFILE, OPT_CHAINCAFILE, OPT_VERIFYCAFILE,
+ OPT_CASTORE, OPT_NOCASTORE, OPT_CHAINCASTORE, OPT_VERIFYCASTORE,
OPT_SERVERINFO, OPT_STARTTLS, OPT_SERVERNAME, OPT_NOSERVERNAME, OPT_ASYNC,
OPT_USE_SRTP, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, OPT_PROTOHOST,
OPT_MAXFRAGLEN, OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES,
OPT_READ_BUF, OPT_KEYLOG_FILE, OPT_EARLY_DATA, OPT_REQCAFILE,
OPT_V_ENUM,
OPT_X_ENUM,
- OPT_S_ENUM,
- OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_DANE_TLSA_DOMAIN,
+ OPT_S_ENUM, OPT_IGNORE_UNEXPECTED_EOF,
+ OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_PROXY_USER, OPT_PROXY_PASS,
+ OPT_DANE_TLSA_DOMAIN,
#ifndef OPENSSL_NO_CT
OPT_CT, OPT_NOCT, OPT_CTLOG_FILE,
#endif
OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME,
OPT_ENABLE_PHA,
OPT_SCTP_LABEL_BUG,
- OPT_R_ENUM
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS s_client_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [host:port]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+ {"ssl_client_engine", OPT_SSL_CLIENT_ENGINE, 's',
+ "Specify engine to be used for client certificate operations"},
+#endif
+ {"ssl_config", OPT_SSL_CONFIG, 's', "Use specified section for SSL_CTX configuration"},
+#ifndef OPENSSL_NO_CT
+ {"ct", OPT_CT, '-', "Request and parse SCTs (also enables OCSP stapling)"},
+ {"noct", OPT_NOCT, '-', "Do not request or parse SCTs (default)"},
+ {"ctlogfile", OPT_CTLOG_FILE, '<', "CT log list CONF file"},
+#endif
+
+ OPT_SECTION("Network"),
{"host", OPT_HOST, 's', "Use -connect instead"},
{"port", OPT_PORT, 'p', "Use -connect instead"},
{"connect", OPT_CONNECT, 's',
- "TCP/IP where to connect (default is :" PORT ")"},
+ "TCP/IP where to connect; default: " PORT ")"},
{"bind", OPT_BIND, 's', "bind local address for connection"},
{"proxy", OPT_PROXY, 's',
"Connect to via specified proxy to the real server"},
+ {"proxy_user", OPT_PROXY_USER, 's', "UserID for proxy authentication"},
+ {"proxy_pass", OPT_PROXY_PASS, 's', "Proxy authentication password source"},
#ifdef AF_UNIX
{"unix", OPT_UNIX, 's', "Connect over the specified Unix-domain socket"},
#endif
@@ -617,20 +504,38 @@ const OPTIONS s_client_options[] = {
#ifdef AF_INET6
{"6", OPT_6, '-', "Use IPv6 only"},
#endif
- {"verify", OPT_VERIFY, 'p', "Turn on peer certificate verification"},
- {"cert", OPT_CERT, '<', "Certificate file to use, PEM format assumed"},
+ {"maxfraglen", OPT_MAXFRAGLEN, 'p',
+ "Enable Maximum Fragment Length Negotiation (len values: 512, 1024, 2048 and 4096)"},
+ {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "},
+ {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p',
+ "Size used to split data for encrypt pipelines"},
+ {"max_pipelines", OPT_MAX_PIPELINES, 'p',
+ "Maximum number of encrypt/decrypt pipelines to be used"},
+ {"read_buf", OPT_READ_BUF, 'p',
+ "Default read buffer size to be used for connections"},
+ {"fallback_scsv", OPT_FALLBACKSCSV, '-', "Send the fallback SCSV"},
+
+ OPT_SECTION("Identity"),
+ {"cert", OPT_CERT, '<', "Client certificate file to use"},
{"certform", OPT_CERTFORM, 'F',
- "Certificate format (PEM or DER) PEM default"},
- {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
- {"key", OPT_KEY, 's', "Private key file to use, if not in -cert file"},
- {"keyform", OPT_KEYFORM, 'E', "Key format (PEM, DER or engine) PEM default"},
- {"pass", OPT_PASS, 's', "Private key file pass phrase source"},
+ "Client certificate file format (PEM/DER/P12); has no effect"},
+ {"cert_chain", OPT_CERT_CHAIN, '<',
+ "Client certificate chain file (in PEM format)"},
+ {"build_chain", OPT_BUILD_CHAIN, '-', "Build client certificate chain"},
+ {"key", OPT_KEY, 's', "Private key file to use; default: -cert file"},
+ {"keyform", OPT_KEYFORM, 'E', "Key format (ENGINE, other values ignored)"},
+ {"pass", OPT_PASS, 's', "Private key and cert file pass phrase source"},
+ {"verify", OPT_VERIFY, 'p', "Turn on peer certificate verification"},
+ {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
{"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
{"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"},
+ {"CAstore", OPT_CASTORE, ':', "URI to store of CA's"},
{"no-CAfile", OPT_NOCAFILE, '-',
"Do not load the default certificates file"},
{"no-CApath", OPT_NOCAPATH, '-',
"Do not load certificates from the default certificates directory"},
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load certificates from the default certificates store"},
{"requestCAfile", OPT_REQCAFILE, '<',
"PEM format file of CA names to send to the server"},
{"dane_tlsa_domain", OPT_DANE_TLSA_DOMAIN, 's', "DANE TLSA base domain"},
@@ -638,16 +543,19 @@ const OPTIONS s_client_options[] = {
"DANE TLSA rrdata presentation form"},
{"dane_ee_no_namechecks", OPT_DANE_EE_NO_NAME, '-',
"Disable name checks when matching DANE-EE(3) TLSA records"},
+ {"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity"},
+ {"psk", OPT_PSK, 's', "PSK in hex (without 0x)"},
+ {"psk_session", OPT_PSK_SESS, '<', "File to read PSK SSL session from"},
+ {"name", OPT_PROTOHOST, 's',
+ "Hostname to use for \"-starttls lmtp\", \"-starttls smtp\" or \"-starttls xmpp[-server]\""},
+
+ OPT_SECTION("Session"),
{"reconnect", OPT_RECONNECT, '-',
"Drop and re-make the connection with the same Session-ID"},
- {"showcerts", OPT_SHOWCERTS, '-',
- "Show all certificates sent by the server"},
- {"debug", OPT_DEBUG, '-', "Extra output"},
- {"msg", OPT_MSG, '-', "Show protocol messages"},
- {"msgfile", OPT_MSGFILE, '>',
- "File to send output of -msg or -trace, instead of stdout"},
- {"nbio_test", OPT_NBIO_TEST, '-', "More ssl protocol testing"},
- {"state", OPT_STATE, '-', "Print the ssl states"},
+ {"sess_out", OPT_SESS_OUT, '>', "File to write SSL session to"},
+ {"sess_in", OPT_SESS_IN, '<', "File to read SSL session from"},
+
+ OPT_SECTION("Input/Output"),
{"crlf", OPT_CRLF, '-', "Convert LF from terminal into CRLF"},
{"quiet", OPT_QUIET, '-', "No s_client output"},
{"ign_eof", OPT_IGN_EOF, '-', "Ignore input eof (default when -quiet)"},
@@ -656,47 +564,35 @@ const OPTIONS s_client_options[] = {
"Use the appropriate STARTTLS command before starting TLS"},
{"xmpphost", OPT_XMPPHOST, 's',
"Alias of -name option for \"-starttls xmpp[-server]\""},
- OPT_R_OPTIONS,
- {"sess_out", OPT_SESS_OUT, '>', "File to write SSL session to"},
- {"sess_in", OPT_SESS_IN, '<', "File to read SSL session from"},
-#ifndef OPENSSL_NO_SRTP
- {"use_srtp", OPT_USE_SRTP, 's',
- "Offer SRTP key management with a colon-separated profile list"},
-#endif
- {"keymatexport", OPT_KEYMATEXPORT, 's',
- "Export keying material using label"},
- {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p',
- "Export len bytes of keying material (default 20)"},
- {"maxfraglen", OPT_MAXFRAGLEN, 'p',
- "Enable Maximum Fragment Length Negotiation (len values: 512, 1024, 2048 and 4096)"},
- {"fallback_scsv", OPT_FALLBACKSCSV, '-', "Send the fallback SCSV"},
- {"name", OPT_PROTOHOST, 's',
- "Hostname to use for \"-starttls lmtp\", \"-starttls smtp\" or \"-starttls xmpp[-server]\""},
- {"CRL", OPT_CRL, '<', "CRL file to use"},
- {"crl_download", OPT_CRL_DOWNLOAD, '-', "Download CRL from distribution points"},
- {"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER) PEM is default"},
- {"verify_return_error", OPT_VERIFY_RET_ERROR, '-',
- "Close connection on verification error"},
- {"verify_quiet", OPT_VERIFY_QUIET, '-', "Restrict verify output to errors"},
{"brief", OPT_BRIEF, '-',
"Restrict output to brief summary of connection parameters"},
{"prexit", OPT_PREXIT, '-',
"Print session information when the program exits"},
+
+ OPT_SECTION("Debug"),
+ {"showcerts", OPT_SHOWCERTS, '-',
+ "Show all certificates sent by the server"},
+ {"debug", OPT_DEBUG, '-', "Extra output"},
+ {"msg", OPT_MSG, '-', "Show protocol messages"},
+ {"msgfile", OPT_MSGFILE, '>',
+ "File to send output of -msg or -trace, instead of stdout"},
+ {"nbio_test", OPT_NBIO_TEST, '-', "More ssl protocol testing"},
+ {"state", OPT_STATE, '-', "Print the ssl states"},
+ {"keymatexport", OPT_KEYMATEXPORT, 's',
+ "Export keying material using label"},
+ {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p',
+ "Export len bytes of keying material; default 20"},
{"security_debug", OPT_SECURITY_DEBUG, '-',
"Enable security debug messages"},
{"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-',
"Output more security debug output"},
- {"cert_chain", OPT_CERT_CHAIN, '<',
- "Certificate chain file (in PEM format)"},
- {"chainCApath", OPT_CHAINCAPATH, '/',
- "Use dir as certificate store path to build CA certificate chain"},
- {"verifyCApath", OPT_VERIFYCAPATH, '/',
- "Use dir as certificate store path to verify CA certificate"},
- {"build_chain", OPT_BUILD_CHAIN, '-', "Build certificate chain"},
- {"chainCAfile", OPT_CHAINCAFILE, '<',
- "CA file for certificate chain (PEM format)"},
- {"verifyCAfile", OPT_VERIFYCAFILE, '<',
- "CA file for certificate verification (PEM format)"},
+#ifndef OPENSSL_NO_SSL_TRACE
+ {"trace", OPT_TRACE, '-', "Show trace output of protocol messages"},
+#endif
+#ifdef WATT32
+ {"wdebug", OPT_WDEBUG, '-', "WATT-32 tcp debugging"},
+#endif
+ {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"},
{"nocommands", OPT_NOCMDS, '-', "Do not use interactive command letters"},
{"servername", OPT_SERVERNAME, 's',
"Set TLS extension servername (SNI) in ClientHello (default)"},
@@ -704,6 +600,8 @@ const OPTIONS s_client_options[] = {
"Do not send the server name (SNI) extension in the ClientHello"},
{"tlsextdebug", OPT_TLSEXTDEBUG, '-',
"Hex dump of all TLS extensions received"},
+ {"ignore_unexpected_eof", OPT_IGNORE_UNEXPECTED_EOF, '-',
+ "Do not treat lack of close_notify from a peer as an error"},
#ifndef OPENSSL_NO_OCSP
{"status", OPT_STATUS, '-', "Request certificate status from server"},
#endif
@@ -712,17 +610,9 @@ const OPTIONS s_client_options[] = {
{"alpn", OPT_ALPN, 's',
"Enable ALPN extension, considering named protocols supported (comma-separated list)"},
{"async", OPT_ASYNC, '-', "Support asynchronous operation"},
- {"ssl_config", OPT_SSL_CONFIG, 's', "Use specified configuration file"},
- {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "},
- {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p',
- "Size used to split data for encrypt pipelines"},
- {"max_pipelines", OPT_MAX_PIPELINES, 'p',
- "Maximum number of encrypt/decrypt pipelines to be used"},
- {"read_buf", OPT_READ_BUF, 'p',
- "Default read buffer size to be used for connections"},
- OPT_S_OPTIONS,
- OPT_V_OPTIONS,
- OPT_X_OPTIONS,
+ {"nbio", OPT_NBIO, '-', "Use non-blocking IO"},
+
+ OPT_SECTION("Protocol and version"),
#ifndef OPENSSL_NO_SSL3
{"ssl3", OPT_SSL3, '-', "Just use SSLv3"},
#endif
@@ -754,43 +644,54 @@ const OPTIONS s_client_options[] = {
{"sctp", OPT_SCTP, '-', "Use SCTP"},
{"sctp_label_bug", OPT_SCTP_LABEL_BUG, '-', "Enable SCTP label length bug"},
#endif
-#ifndef OPENSSL_NO_SSL_TRACE
- {"trace", OPT_TRACE, '-', "Show trace output of protocol messages"},
-#endif
-#ifdef WATT32
- {"wdebug", OPT_WDEBUG, '-', "WATT-32 tcp debugging"},
-#endif
- {"nbio", OPT_NBIO, '-', "Use non-blocking IO"},
- {"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity"},
- {"psk", OPT_PSK, 's', "PSK in hex (without 0x)"},
- {"psk_session", OPT_PSK_SESS, '<', "File to read PSK SSL session from"},
-#ifndef OPENSSL_NO_SRP
- {"srpuser", OPT_SRPUSER, 's', "SRP authentication for 'user'"},
- {"srppass", OPT_SRPPASS, 's', "Password for 'user'"},
- {"srp_lateuser", OPT_SRP_LATEUSER, '-',
- "SRP username into second ClientHello message"},
- {"srp_moregroups", OPT_SRP_MOREGROUPS, '-',
- "Tolerate other than the known g N values."},
- {"srp_strength", OPT_SRP_STRENGTH, 'p', "Minimal length in bits for N"},
-#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
{"nextprotoneg", OPT_NEXTPROTONEG, 's',
"Enable NPN extension, considering named protocols supported (comma-separated list)"},
#endif
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
- {"ssl_client_engine", OPT_SSL_CLIENT_ENGINE, 's',
- "Specify engine to be used for client certificate operations"},
-#endif
-#ifndef OPENSSL_NO_CT
- {"ct", OPT_CT, '-', "Request and parse SCTs (also enables OCSP stapling)"},
- {"noct", OPT_NOCT, '-', "Do not request or parse SCTs (default)"},
- {"ctlogfile", OPT_CTLOG_FILE, '<', "CT log list CONF file"},
-#endif
- {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"},
{"early_data", OPT_EARLY_DATA, '<', "File to send as early data"},
{"enable_pha", OPT_ENABLE_PHA, '-', "Enable post-handshake-authentication"},
- {NULL, OPT_EOF, 0x00, NULL}
+#ifndef OPENSSL_NO_SRTP
+ {"use_srtp", OPT_USE_SRTP, 's',
+ "Offer SRTP key management with a colon-separated profile list"},
+#endif
+#ifndef OPENSSL_NO_SRP
+ {"srpuser", OPT_SRPUSER, 's', "(deprecated) SRP authentication for 'user'"},
+ {"srppass", OPT_SRPPASS, 's', "(deprecated) Password for 'user'"},
+ {"srp_lateuser", OPT_SRP_LATEUSER, '-',
+ "(deprecated) SRP username into second ClientHello message"},
+ {"srp_moregroups", OPT_SRP_MOREGROUPS, '-',
+ "(deprecated) Tolerate other than the known g N values."},
+ {"srp_strength", OPT_SRP_STRENGTH, 'p',
+ "(deprecated) Minimal length in bits for N"},
+#endif
+
+ OPT_R_OPTIONS,
+ OPT_S_OPTIONS,
+ OPT_V_OPTIONS,
+ {"CRL", OPT_CRL, '<', "CRL file to use"},
+ {"crl_download", OPT_CRL_DOWNLOAD, '-', "Download CRL from distribution points"},
+ {"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER); default PEM"},
+ {"verify_return_error", OPT_VERIFY_RET_ERROR, '-',
+ "Close connection on verification error"},
+ {"verify_quiet", OPT_VERIFY_QUIET, '-', "Restrict verify output to errors"},
+ {"chainCAfile", OPT_CHAINCAFILE, '<',
+ "CA file for certificate chain (PEM format)"},
+ {"chainCApath", OPT_CHAINCAPATH, '/',
+ "Use dir as certificate store path to build CA certificate chain"},
+ {"chainCAstore", OPT_CHAINCASTORE, ':',
+ "CA store URI for certificate chain"},
+ {"verifyCAfile", OPT_VERIFYCAFILE, '<',
+ "CA file for certificate verification (PEM format)"},
+ {"verifyCApath", OPT_VERIFYCAPATH, '/',
+ "Use dir as certificate store path to verify CA certificate"},
+ {"verifyCAstore", OPT_VERIFYCASTORE, ':',
+ "CA store URI for certificate verification"},
+ OPT_X_OPTIONS,
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"host:port", 0, 0, "Where to connect; same as -connect option"},
+ {NULL}
};
typedef enum PROTOCOL_choice {
@@ -802,7 +703,6 @@ typedef enum PROTOCOL_choice {
PROTO_TELNET,
PROTO_XMPP,
PROTO_XMPP_SERVER,
- PROTO_CONNECT,
PROTO_IRC,
PROTO_MYSQL,
PROTO_POSTGRES,
@@ -896,29 +796,33 @@ int s_client_main(int argc, char **argv)
int dane_ee_no_name = 0;
STACK_OF(X509_CRL) *crls = NULL;
const SSL_METHOD *meth = TLS_client_method();
- const char *CApath = NULL, *CAfile = NULL;
- char *cbuf = NULL, *sbuf = NULL;
- char *mbuf = NULL, *proxystr = NULL, *connectstr = NULL, *bindstr = NULL;
+ const char *CApath = NULL, *CAfile = NULL, *CAstore = NULL;
+ char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL;
+ char *proxystr = NULL, *proxyuser = NULL;
+ char *proxypassarg = NULL, *proxypass = NULL;
+ char *connectstr = NULL, *bindstr = NULL;
char *cert_file = NULL, *key_file = NULL, *chain_file = NULL;
- char *chCApath = NULL, *chCAfile = NULL, *host = NULL;
- char *port = OPENSSL_strdup(PORT);
+ char *chCApath = NULL, *chCAfile = NULL, *chCAstore = NULL, *host = NULL;
+ char *thost = NULL, *tport = NULL;
+ char *port = NULL;
char *bindhost = NULL, *bindport = NULL;
- char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL;
+ char *passarg = NULL, *pass = NULL;
+ char *vfyCApath = NULL, *vfyCAfile = NULL, *vfyCAstore = NULL;
char *ReqCAfile = NULL;
char *sess_in = NULL, *crl_file = NULL, *p;
const char *protohost = NULL;
struct timeval timeout, *timeoutp;
fd_set readfds, writefds;
- int noCApath = 0, noCAfile = 0;
- int build_chain = 0, cbuf_len, cbuf_off, cert_format = FORMAT_PEM;
- int key_format = FORMAT_PEM, crlf = 0, full_log = 1, mbuf_len = 0;
+ int noCApath = 0, noCAfile = 0, noCAstore = 0;
+ int build_chain = 0, cbuf_len, cbuf_off, cert_format = FORMAT_UNDEF;
+ int key_format = FORMAT_UNDEF, crlf = 0, full_log = 1, mbuf_len = 0;
int prexit = 0;
int sdebug = 0;
int reconnect = 0, verify = SSL_VERIFY_NONE, vpmtouched = 0;
- int ret = 1, in_init = 1, i, nbio_test = 0, s = -1, k, width, state = 0;
+ int ret = 1, in_init = 1, i, nbio_test = 0, sock = -1, k, width, state = 0;
int sbuf_len, sbuf_off, cmdletters = 1;
int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0;
- int starttls_proto = PROTO_OFF, crl_format = FORMAT_PEM, crl_download = 0;
+ int starttls_proto = PROTO_OFF, crl_format = FORMAT_UNDEF, crl_download = 0;
int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending;
#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS)
int at_eof = 0;
@@ -983,6 +887,7 @@ int s_client_main(int argc, char **argv)
#ifndef OPENSSL_NO_SCTP
int sctp_label_bug = 0;
#endif
+ int ignore_unexpected_eof = 0;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
@@ -994,16 +899,16 @@ int s_client_main(int argc, char **argv)
# endif
#endif
- prog = opt_progname(argv[0]);
c_quiet = 0;
c_debug = 0;
c_showcerts = 0;
c_nbio = 0;
+ port = OPENSSL_strdup(PORT);
vpm = X509_VERIFY_PARAM_new();
cctx = SSL_CONF_CTX_new();
- if (vpm == NULL || cctx == NULL) {
- BIO_printf(bio_err, "%s: out of memory\n", prog);
+ if (port == NULL || vpm == NULL || cctx == NULL) {
+ BIO_printf(bio_err, "%s: out of memory\n", opt_getprog());
goto end;
}
@@ -1080,7 +985,12 @@ int s_client_main(int argc, char **argv)
break;
case OPT_PROXY:
proxystr = opt_arg();
- starttls_proto = PROTO_CONNECT;
+ break;
+ case OPT_PROXY_USER:
+ proxyuser = opt_arg();
+ break;
+ case OPT_PROXY_PASS:
+ proxypassarg = opt_arg();
break;
#ifdef AF_UNIX
case OPT_UNIX:
@@ -1120,7 +1030,7 @@ int s_client_main(int argc, char **argv)
sess_in = opt_arg();
break;
case OPT_CERTFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &cert_format))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &cert_format))
goto opthelp;
break;
case OPT_CRLFORM:
@@ -1156,6 +1066,9 @@ int s_client_main(int argc, char **argv)
if (!args_excert(o, &exc))
goto end;
break;
+ case OPT_IGNORE_UNEXPECTED_EOF:
+ ignore_unexpected_eof = 1;
+ break;
case OPT_PREXIT:
prexit = 1;
break;
@@ -1176,7 +1089,7 @@ int s_client_main(int argc, char **argv)
break;
case OPT_SSL_CLIENT_ENGINE:
#ifndef OPENSSL_NO_ENGINE
- ssl_client_engine = ENGINE_by_id(opt_arg());
+ ssl_client_engine = setup_engine(opt_arg(), 0);
if (ssl_client_engine == NULL) {
BIO_printf(bio_err, "Error getting client auth engine\n");
goto opthelp;
@@ -1187,6 +1100,10 @@ int s_client_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_IGN_EOF:
c_ign_eof = 1;
break;
@@ -1214,6 +1131,10 @@ int s_client_main(int argc, char **argv)
break;
case OPT_MSGFILE:
bio_c_msg = BIO_new_file(opt_arg(), "w");
+ if (bio_c_msg == NULL) {
+ BIO_printf(bio_err, "Error writing file %s\n", opt_arg());
+ goto end;
+ }
break;
case OPT_TRACE:
#ifndef OPENSSL_NO_SSL_TRACE
@@ -1370,7 +1291,7 @@ int s_client_main(int argc, char **argv)
fallback_scsv = 1;
break;
case OPT_KEYFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PDE, &key_format))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &key_format))
goto opthelp;
break;
case OPT_PASS:
@@ -1426,6 +1347,18 @@ int s_client_main(int argc, char **argv)
case OPT_VERIFYCAFILE:
vfyCAfile = opt_arg();
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
+ case OPT_CHAINCASTORE:
+ chCAstore = opt_arg();
+ break;
+ case OPT_VERIFYCASTORE:
+ vfyCAstore = opt_arg();
+ break;
case OPT_DANE_TLSA_DOMAIN:
dane_tlsa_domain = opt_arg();
break;
@@ -1530,6 +1463,25 @@ int s_client_main(int argc, char **argv)
break;
}
}
+
+ /* Optional argument is connect string if -connect not used. */
+ argc = opt_num_rest();
+ if (argc == 1) {
+ /* Don't allow -connect and a separate argument. */
+ if (connectstr != NULL) {
+ BIO_printf(bio_err,
+ "%s: cannot provide both -connect option and target parameter\n",
+ prog);
+ goto opthelp;
+ }
+ connect_type = use_inet;
+ freeandcopy(&connectstr, *opt_rest());
+ } else if (argc != 0) {
+ goto opthelp;
+ }
+ if (!app_RAND_load())
+ goto end;
+
if (count4or6 >= 2) {
BIO_printf(bio_err, "%s: Can't use both -4 and -6\n", prog);
goto opthelp;
@@ -1548,23 +1500,6 @@ int s_client_main(int argc, char **argv)
goto opthelp;
}
}
- argc = opt_num_rest();
- if (argc == 1) {
- /* If there's a positional argument, it's the equivalent of
- * OPT_CONNECT.
- * Don't allow -connect and a separate argument.
- */
- if (connectstr != NULL) {
- BIO_printf(bio_err,
- "%s: must not provide both -connect option and target parameter\n",
- prog);
- goto opthelp;
- }
- connect_type = use_inet;
- freeandcopy(&connectstr, *opt_rest());
- } else if (argc != 0) {
- goto opthelp;
- }
#ifndef OPENSSL_NO_NEXTPROTONEG
if (min_version == TLS1_3_VERSION && next_proto_neg_in != NULL) {
@@ -1572,46 +1507,57 @@ int s_client_main(int argc, char **argv)
goto opthelp;
}
#endif
- if (proxystr != NULL) {
+
+ if (connectstr != NULL) {
int res;
char *tmp_host = host, *tmp_port = port;
- if (connectstr == NULL) {
- BIO_printf(bio_err, "%s: -proxy requires use of -connect or target parameter\n", prog);
- goto opthelp;
- }
- res = BIO_parse_hostserv(proxystr, &host, &port, BIO_PARSE_PRIO_HOST);
+
+ res = BIO_parse_hostserv(connectstr, &host, &port, BIO_PARSE_PRIO_HOST);
if (tmp_host != host)
OPENSSL_free(tmp_host);
if (tmp_port != port)
OPENSSL_free(tmp_port);
if (!res) {
BIO_printf(bio_err,
- "%s: -proxy argument malformed or ambiguous\n", prog);
+ "%s: -connect argument or target parameter malformed or ambiguous\n",
+ prog);
goto end;
}
+ }
+
+ if (proxystr != NULL) {
+ int res;
+ char *tmp_host = host, *tmp_port = port;
+
+ if (host == NULL || port == NULL) {
+ BIO_printf(bio_err, "%s: -proxy requires use of -connect or target parameter\n", prog);
+ goto opthelp;
+ }
+
if (servername == NULL && !noservername) {
- res = BIO_parse_hostserv(connectstr, &sname_alloc, NULL, BIO_PARSE_PRIO_HOST);
- if (!res) {
- BIO_printf(bio_err,
- "%s: -connect argument malformed or ambiguous\n", prog);
+ servername = sname_alloc = OPENSSL_strdup(host);
+ if (sname_alloc == NULL) {
+ BIO_printf(bio_err, "%s: out of memory\n", prog);
goto end;
}
- servername = sname_alloc;
}
- } else {
- int res = 1;
- char *tmp_host = host, *tmp_port = port;
- if (connectstr != NULL)
- res = BIO_parse_hostserv(connectstr, &host, &port,
- BIO_PARSE_PRIO_HOST);
+
+ /* Retain the original target host:port for use in the HTTP proxy connect string */
+ thost = OPENSSL_strdup(host);
+ tport = OPENSSL_strdup(port);
+ if (thost == NULL || tport == NULL) {
+ BIO_printf(bio_err, "%s: out of memory\n", prog);
+ goto end;
+ }
+
+ res = BIO_parse_hostserv(proxystr, &host, &port, BIO_PARSE_PRIO_HOST);
if (tmp_host != host)
OPENSSL_free(tmp_host);
if (tmp_port != port)
OPENSSL_free(tmp_port);
if (!res) {
BIO_printf(bio_err,
- "%s: -connect argument or target parameter malformed or ambiguous\n",
- prog);
+ "%s: -proxy argument malformed or ambiguous\n", prog);
goto end;
}
}
@@ -1661,7 +1607,17 @@ int s_client_main(int argc, char **argv)
#endif
if (!app_passwd(passarg, NULL, &pass, NULL)) {
- BIO_printf(bio_err, "Error getting password\n");
+ BIO_printf(bio_err, "Error getting private key password\n");
+ goto end;
+ }
+
+ if (!app_passwd(proxypassarg, NULL, &proxypass, NULL)) {
+ BIO_printf(bio_err, "Error getting proxy password\n");
+ goto end;
+ }
+
+ if (proxypass != NULL && proxyuser == NULL) {
+ BIO_printf(bio_err, "Error: Must specify proxy_user with proxy_pass\n");
goto end;
}
@@ -1670,35 +1626,28 @@ int s_client_main(int argc, char **argv)
if (key_file != NULL) {
key = load_key(key_file, key_format, 0, pass, e,
- "client certificate private key file");
- if (key == NULL) {
- ERR_print_errors(bio_err);
+ "client certificate private key");
+ if (key == NULL)
goto end;
- }
}
if (cert_file != NULL) {
- cert = load_cert(cert_file, cert_format, "client certificate file");
- if (cert == NULL) {
- ERR_print_errors(bio_err);
+ cert = load_cert_pass(cert_file, cert_format, 1, pass,
+ "client certificate");
+ if (cert == NULL)
goto end;
- }
}
if (chain_file != NULL) {
- if (!load_certs(chain_file, &chain, FORMAT_PEM, NULL,
- "client certificate chain"))
+ if (!load_certs(chain_file, 0, &chain, pass, "client certificate chain"))
goto end;
}
if (crl_file != NULL) {
X509_CRL *crl;
- crl = load_crl(crl_file, crl_format);
- if (crl == NULL) {
- BIO_puts(bio_err, "Error loading CRL\n");
- ERR_print_errors(bio_err);
+ crl = load_crl(crl_file, crl_format, 0, "CRL");
+ if (crl == NULL)
goto end;
- }
crls = sk_X509_CRL_new_null();
if (crls == NULL || !sk_X509_CRL_push(crls, crl)) {
BIO_puts(bio_err, "Error adding CRL\n");
@@ -1714,10 +1663,21 @@ int s_client_main(int argc, char **argv)
if (bio_c_out == NULL) {
if (c_quiet && !c_debug) {
bio_c_out = BIO_new(BIO_s_null());
- if (c_msg && bio_c_msg == NULL)
+ if (c_msg && bio_c_msg == NULL) {
bio_c_msg = dup_bio_out(FORMAT_TEXT);
- } else if (bio_c_out == NULL)
+ if (bio_c_msg == NULL) {
+ BIO_printf(bio_err, "Out of memory\n");
+ goto end;
+ }
+ }
+ } else {
bio_c_out = dup_bio_out(FORMAT_TEXT);
+ }
+
+ if (bio_c_out == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ goto end;
+ }
}
#ifndef OPENSSL_NO_SRP
if (!app_passwd(srppass, NULL, &srp_arg.srppassin, NULL)) {
@@ -1726,7 +1686,7 @@ int s_client_main(int argc, char **argv)
}
#endif
- ctx = SSL_CTX_new(meth);
+ ctx = SSL_CTX_new_ex(app_get0_libctx(), app_get0_propq(), meth);
if (ctx == NULL) {
ERR_print_errors(bio_err);
goto end;
@@ -1761,6 +1721,9 @@ int s_client_main(int argc, char **argv)
&& SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
goto end;
+ if (ignore_unexpected_eof)
+ SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
+
if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) {
BIO_printf(bio_err, "Error setting verify params\n");
ERR_print_errors(bio_err);
@@ -1804,7 +1767,9 @@ int s_client_main(int argc, char **argv)
goto end;
}
- if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile,
+ if (!ssl_load_stores(ctx,
+ vfyCApath, vfyCAfile, vfyCAstore,
+ chCApath, chCAfile, chCAstore,
crls, crl_download)) {
BIO_printf(bio_err, "Error loading store locations\n");
ERR_print_errors(bio_err);
@@ -1826,10 +1791,10 @@ int s_client_main(int argc, char **argv)
if (!SSL_CTX_set_client_cert_engine(ctx, ssl_client_engine)) {
BIO_puts(bio_err, "Error setting client auth engine\n");
ERR_print_errors(bio_err);
- ENGINE_free(ssl_client_engine);
+ release_engine(ssl_client_engine);
goto end;
}
- ENGINE_free(ssl_client_engine);
+ release_engine(ssl_client_engine);
}
#endif
@@ -1933,7 +1898,8 @@ int s_client_main(int argc, char **argv)
SSL_CTX_set_verify(ctx, verify, verify_callback);
- if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) {
+ if (!ctx_set_verify_locations(ctx, CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore)) {
ERR_print_errors(bio_err);
goto end;
}
@@ -1948,21 +1914,10 @@ int s_client_main(int argc, char **argv)
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
}
-# ifndef OPENSSL_NO_SRP
- if (srp_arg.srplogin) {
- if (!srp_lateuser && !SSL_CTX_set_srp_username(ctx, srp_arg.srplogin)) {
- BIO_printf(bio_err, "Unable to set SRP username\n");
- goto end;
- }
- srp_arg.msg = c_msg;
- srp_arg.debug = c_debug;
- SSL_CTX_set_srp_cb_arg(ctx, &srp_arg);
- SSL_CTX_set_srp_client_pwd_callback(ctx, ssl_give_srp_client_pwd_cb);
- SSL_CTX_set_srp_strength(ctx, srp_arg.strength);
- if (c_msg || c_debug || srp_arg.amp == 0)
- SSL_CTX_set_srp_verify_param_callback(ctx,
- ssl_srp_verify_param_cb);
- }
+#ifndef OPENSSL_NO_SRP
+ if (srp_arg.srplogin != NULL
+ && !set_up_srp_arg(ctx, &srp_arg, srp_lateuser, c_msg, c_debug))
+ goto end;
# endif
if (dane_tlsa_domain != NULL) {
@@ -2023,7 +1978,7 @@ int s_client_main(int argc, char **argv)
if (!noservername && (servername != NULL || dane_tlsa_domain == NULL)) {
if (servername == NULL) {
- if(host == NULL || is_dNS_name(host))
+ if(host == NULL || is_dNS_name(host))
servername = (host == NULL) ? "localhost" : host;
}
if (servername != NULL && !SSL_set_tlsext_host_name(con, servername)) {
@@ -2059,16 +2014,16 @@ int s_client_main(int argc, char **argv)
}
re_start:
- if (init_client(&s, host, port, bindhost, bindport, socket_family,
+ if (init_client(&sock, host, port, bindhost, bindport, socket_family,
socket_type, protocol) == 0) {
BIO_printf(bio_err, "connect:errno=%d\n", get_last_socket_error());
- BIO_closesocket(s);
+ BIO_closesocket(sock);
goto end;
}
- BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s);
+ BIO_printf(bio_c_out, "CONNECTED(%08X)\n", sock);
if (c_nbio) {
- if (!BIO_socket_nbio(s, 1)) {
+ if (!BIO_socket_nbio(sock, 1)) {
ERR_print_errors(bio_err);
goto end;
}
@@ -2080,21 +2035,23 @@ int s_client_main(int argc, char **argv)
#ifndef OPENSSL_NO_SCTP
if (protocol == IPPROTO_SCTP)
- sbio = BIO_new_dgram_sctp(s, BIO_NOCLOSE);
+ sbio = BIO_new_dgram_sctp(sock, BIO_NOCLOSE);
else
#endif
- sbio = BIO_new_dgram(s, BIO_NOCLOSE);
+ sbio = BIO_new_dgram(sock, BIO_NOCLOSE);
- if ((peer_info.addr = BIO_ADDR_new()) == NULL) {
+ if (sbio == NULL || (peer_info.addr = BIO_ADDR_new()) == NULL) {
BIO_printf(bio_err, "memory allocation failure\n");
- BIO_closesocket(s);
+ BIO_free(sbio);
+ BIO_closesocket(sock);
goto end;
}
- if (!BIO_sock_info(s, BIO_SOCK_INFO_ADDRESS, &peer_info)) {
+ if (!BIO_sock_info(sock, BIO_SOCK_INFO_ADDRESS, &peer_info)) {
BIO_printf(bio_err, "getsockname:errno=%d\n",
get_last_socket_error());
+ BIO_free(sbio);
BIO_ADDR_free(peer_info.addr);
- BIO_closesocket(s);
+ BIO_closesocket(sock);
goto end;
}
@@ -2131,17 +2088,29 @@ int s_client_main(int argc, char **argv)
}
} else
#endif /* OPENSSL_NO_DTLS */
- sbio = BIO_new_socket(s, BIO_NOCLOSE);
+ sbio = BIO_new_socket(sock, BIO_NOCLOSE);
+
+ if (sbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ ERR_print_errors(bio_err);
+ BIO_closesocket(sock);
+ goto end;
+ }
if (nbio_test) {
BIO *test;
test = BIO_new(BIO_f_nbio_test());
+ if (test == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ BIO_free(sbio);
+ goto shut;
+ }
sbio = BIO_push(test, sbio);
}
if (c_debug) {
- BIO_set_callback(sbio, bio_dump_callback);
+ BIO_set_callback_ex(sbio, bio_dump_callback);
BIO_set_callback_arg(sbio, (char *)bio_c_out);
}
if (c_msg) {
@@ -2186,6 +2155,13 @@ int s_client_main(int argc, char **argv)
sbuf_len = 0;
sbuf_off = 0;
+ if (proxystr != NULL) {
+ /* Here we must use the connect string target host & port */
+ if (!OSSL_HTTP_proxy_connect(sbio, thost, tport, proxyuser, proxypass,
+ 0 /* no timeout */, bio_err, prog))
+ goto shut;
+ }
+
switch ((PROTOCOL_CHOICE) starttls_proto) {
case PROTO_OFF:
break;
@@ -2203,6 +2179,10 @@ int s_client_main(int argc, char **argv)
int foundit = 0;
BIO *fbio = BIO_new(BIO_f_buffer());
+ if (fbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ goto shut;
+ }
BIO_push(fbio, sbio);
/* Wait for multi-line response to end from LMTP or SMTP */
do {
@@ -2251,6 +2231,10 @@ int s_client_main(int argc, char **argv)
int foundit = 0;
BIO *fbio = BIO_new(BIO_f_buffer());
+ if (fbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ goto shut;
+ }
BIO_push(fbio, sbio);
BIO_gets(fbio, mbuf, BUFSIZZ);
/* STARTTLS command requires CAPABILITY... */
@@ -2278,6 +2262,10 @@ int s_client_main(int argc, char **argv)
{
BIO *fbio = BIO_new(BIO_f_buffer());
+ if (fbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ goto shut;
+ }
BIO_push(fbio, sbio);
/* wait for multi-line response to end from FTP */
do {
@@ -2361,64 +2349,15 @@ int s_client_main(int argc, char **argv)
goto shut;
}
break;
- case PROTO_CONNECT:
- {
- enum {
- error_proto, /* Wrong protocol, not even HTTP */
- error_connect, /* CONNECT failed */
- success
- } foundit = error_connect;
- BIO *fbio = BIO_new(BIO_f_buffer());
-
- BIO_push(fbio, sbio);
- BIO_printf(fbio, "CONNECT %s HTTP/1.0\r\n\r\n", connectstr);
- (void)BIO_flush(fbio);
- /*
- * The first line is the HTTP response. According to RFC 7230,
- * it's formatted exactly like this:
- *
- * HTTP/d.d ddd Reason text\r\n
- */
- mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
- if (mbuf_len < (int)strlen("HTTP/1.0 200")) {
- BIO_printf(bio_err,
- "%s: HTTP CONNECT failed, insufficient response "
- "from proxy (got %d octets)\n", prog, mbuf_len);
- (void)BIO_flush(fbio);
- BIO_pop(fbio);
- BIO_free(fbio);
- goto shut;
- }
- if (mbuf[8] != ' ') {
- BIO_printf(bio_err,
- "%s: HTTP CONNECT failed, incorrect response "
- "from proxy\n", prog);
- foundit = error_proto;
- } else if (mbuf[9] != '2') {
- BIO_printf(bio_err, "%s: HTTP CONNECT failed: %s ", prog,
- &mbuf[9]);
- } else {
- foundit = success;
- }
- if (foundit != error_proto) {
- /* Read past all following headers */
- do {
- mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
- } while (mbuf_len > 2);
- }
- (void)BIO_flush(fbio);
- BIO_pop(fbio);
- BIO_free(fbio);
- if (foundit != success) {
- goto shut;
- }
- }
- break;
case PROTO_IRC:
{
int numeric;
BIO *fbio = BIO_new(BIO_f_buffer());
+ if (fbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ goto end;
+ }
BIO_push(fbio, sbio);
BIO_printf(fbio, "STARTTLS\r\n");
(void)BIO_flush(fbio);
@@ -2579,17 +2518,25 @@ int s_client_main(int argc, char **argv)
int foundit = 0;
BIO *fbio = BIO_new(BIO_f_buffer());
+ if (fbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ goto end;
+ }
BIO_push(fbio, sbio);
BIO_gets(fbio, mbuf, BUFSIZZ);
/* STARTTLS command requires CAPABILITIES... */
BIO_printf(fbio, "CAPABILITIES\r\n");
(void)BIO_flush(fbio);
- /* wait for multi-line CAPABILITIES response */
- do {
- mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
- if (strstr(mbuf, "STARTTLS"))
- foundit = 1;
- } while (mbuf_len > 1 && mbuf[0] != '.');
+ BIO_gets(fbio, mbuf, BUFSIZZ);
+ /* no point in trying to parse the CAPABILITIES response if there is none */
+ if (strstr(mbuf, "101") != NULL) {
+ /* wait for multi-line CAPABILITIES response */
+ do {
+ mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
+ if (strstr(mbuf, "STARTTLS"))
+ foundit = 1;
+ } while (mbuf_len > 1 && mbuf[0] != '.');
+ }
(void)BIO_flush(fbio);
BIO_pop(fbio);
BIO_free(fbio);
@@ -2615,6 +2562,10 @@ int s_client_main(int argc, char **argv)
int foundit = 0;
BIO *fbio = BIO_new(BIO_f_buffer());
+ if (fbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ goto end;
+ }
BIO_push(fbio, sbio);
/* wait for multi-line response to end from Sieve */
do {
@@ -2674,8 +2625,9 @@ int s_client_main(int argc, char **argv)
BIO *ldapbio = BIO_new(BIO_s_mem());
CONF *cnf = NCONF_new(NULL);
- if (cnf == NULL) {
+ if (ldapbio == NULL || cnf == NULL) {
BIO_free(ldapbio);
+ NCONF_free(cnf);
goto end;
}
BIO_puts(ldapbio, ldap_tls_genconf);
@@ -2784,7 +2736,6 @@ int s_client_main(int argc, char **argv)
tty_on = 1;
if (in_init) {
in_init = 0;
-
if (c_brief) {
BIO_puts(bio_err, "CONNECTION ESTABLISHED\n");
print_ssl_summary(con);
@@ -3080,22 +3031,14 @@ int s_client_main(int argc, char **argv)
BIO_printf(bio_err, "RENEGOTIATING\n");
SSL_renegotiate(con);
cbuf_len = 0;
- } else if (!c_ign_eof && (cbuf[0] == 'K' || cbuf[0] == 'k' )
+ } else if (!c_ign_eof && (cbuf[0] == 'K' || cbuf[0] == 'k' )
&& cmdletters) {
BIO_printf(bio_err, "KEYUPDATE\n");
SSL_key_update(con,
cbuf[0] == 'K' ? SSL_KEY_UPDATE_REQUESTED
: SSL_KEY_UPDATE_NOT_REQUESTED);
cbuf_len = 0;
- }
-#ifndef OPENSSL_NO_HEARTBEATS
- else if ((!c_ign_eof) && (cbuf[0] == 'B' && cmdletters)) {
- BIO_printf(bio_err, "HEARTBEATING\n");
- SSL_heartbeat(con);
- cbuf_len = 0;
- }
-#endif
- else {
+ } else {
cbuf_len = i;
cbuf_off = 0;
#ifdef CHARSET_EBCDIC
@@ -3108,7 +3051,6 @@ int s_client_main(int argc, char **argv)
}
}
- ret = 0;
shut:
if (in_init)
print_stuff(bio_c_out, con, full_log);
@@ -3134,8 +3076,8 @@ int s_client_main(int argc, char **argv)
timeout.tv_usec = 500000; /* some extreme round-trip */
do {
FD_ZERO(&readfds);
- openssl_fdset(s, &readfds);
- } while (select(s + 1, &readfds, NULL, NULL, &timeout) > 0
+ openssl_fdset(sock, &readfds);
+ } while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0
&& BIO_read(sbio, sbuf, BUFSIZZ) > 0);
BIO_closesocket(SSL_get_fd(con));
@@ -3166,6 +3108,8 @@ int s_client_main(int argc, char **argv)
OPENSSL_free(bindport);
OPENSSL_free(host);
OPENSSL_free(port);
+ OPENSSL_free(thost);
+ OPENSSL_free(tport);
X509_VERIFY_PARAM_free(vpm);
ssl_excert_free(exc);
sk_OPENSSL_STRING_free(ssl_args);
@@ -3174,6 +3118,7 @@ int s_client_main(int argc, char **argv)
OPENSSL_clear_free(cbuf, BUFSIZZ);
OPENSSL_clear_free(sbuf, BUFSIZZ);
OPENSSL_clear_free(mbuf, BUFSIZZ);
+ clear_free(proxypass);
release_engine(e);
BIO_free(bio_c_out);
bio_c_out = NULL;
@@ -3187,6 +3132,7 @@ static void print_stuff(BIO *bio, SSL *s, int full)
X509 *peer = NULL;
STACK_OF(X509) *sk;
const SSL_CIPHER *c;
+ EVP_PKEY *public_key;
int i, istls13 = (SSL_version(s) == TLS1_3_VERSION);
long verify_result;
#ifndef OPENSSL_NO_COMP
@@ -3212,13 +3158,26 @@ static void print_stuff(BIO *bio, SSL *s, int full)
BIO_printf(bio, " i:");
X509_NAME_print_ex(bio, X509_get_issuer_name(sk_X509_value(sk, i)), 0, get_nameopt());
BIO_puts(bio, "\n");
+ public_key = X509_get_pubkey(sk_X509_value(sk, i));
+ if (public_key != NULL) {
+ BIO_printf(bio, " a:PKEY: %s, %d (bit); sigalg: %s\n",
+ OBJ_nid2sn(EVP_PKEY_get_base_id(public_key)),
+ EVP_PKEY_get_bits(public_key),
+ OBJ_nid2sn(X509_get_signature_nid(sk_X509_value(sk, i))));
+ EVP_PKEY_free(public_key);
+ }
+ BIO_printf(bio, " v:NotBefore: ");
+ ASN1_TIME_print(bio, X509_get0_notBefore(sk_X509_value(sk, i)));
+ BIO_printf(bio, "; NotAfter: ");
+ ASN1_TIME_print(bio, X509_get0_notAfter(sk_X509_value(sk, i)));
+ BIO_puts(bio, "\n");
if (c_showcerts)
PEM_write_bio_X509(bio, sk_X509_value(sk, i));
}
}
BIO_printf(bio, "---\n");
- peer = SSL_get_peer_certificate(s);
+ peer = SSL_get0_peer_certificate(s);
if (peer != NULL) {
BIO_printf(bio, "Server certificate\n");
@@ -3283,7 +3242,7 @@ static void print_stuff(BIO *bio, SSL *s, int full)
pktmp = X509_get0_pubkey(peer);
BIO_printf(bio, "Server public key is %d bit\n",
- EVP_PKEY_bits(pktmp));
+ EVP_PKEY_get_bits(pktmp));
}
BIO_printf(bio, "Secure Renegotiation IS%s supported\n",
SSL_get_secure_renegotiation_support(s) ? "" : " NOT");
@@ -3295,9 +3254,14 @@ static void print_stuff(BIO *bio, SSL *s, int full)
BIO_printf(bio, "Expansion: %s\n",
expansion ? SSL_COMP_get_name(expansion) : "NONE");
#endif
+#ifndef OPENSSL_NO_KTLS
+ if (BIO_get_ktls_send(SSL_get_wbio(s)))
+ BIO_printf(bio_err, "Using Kernel TLS for sending\n");
+ if (BIO_get_ktls_recv(SSL_get_rbio(s)))
+ BIO_printf(bio_err, "Using Kernel TLS for receiving\n");
+#endif
-#ifdef SSL_DEBUG
- {
+ if (OSSL_TRACE_ENABLED(TLS)) {
/* Print out local port of connection: useful for debugging */
int sock;
union BIO_sock_info_u info;
@@ -3310,7 +3274,6 @@ static void print_stuff(BIO *bio, SSL *s, int full)
}
BIO_ADDR_free(info.addr);
}
-#endif
#if !defined(OPENSSL_NO_NEXTPROTONEG)
if (next_proto.status != -1) {
@@ -3379,11 +3342,11 @@ static void print_stuff(BIO *bio, SSL *s, int full)
BIO_printf(bio, " Label: '%s'\n", keymatexportlabel);
BIO_printf(bio, " Length: %i bytes\n", keymatexportlen);
exportedkeymat = app_malloc(keymatexportlen, "export key");
- if (!SSL_export_keying_material(s, exportedkeymat,
+ if (SSL_export_keying_material(s, exportedkeymat,
keymatexportlen,
keymatexportlabel,
strlen(keymatexportlabel),
- NULL, 0, 0)) {
+ NULL, 0, 0) <= 0) {
BIO_printf(bio, " Error\n");
} else {
BIO_printf(bio, " Keying material: ");
@@ -3394,7 +3357,6 @@ static void print_stuff(BIO *bio, SSL *s, int full)
OPENSSL_free(exportedkeymat);
}
BIO_printf(bio, "---\n");
- X509_free(peer);
/* flush, or debugging output gets mixed with http response */
(void)BIO_flush(bio);
}
@@ -3510,7 +3472,7 @@ static int ldap_ExtendedResponse_parse(const char *buf, long rem)
}
/*
- * Host dNS Name verifier: used for checking that the hostname is in dNS format
+ * Host dNS Name verifier: used for checking that the hostname is in dNS format
* before setting it as SNI
*/
static int is_dNS_name(const char *host)
diff --git a/apps/s_server.c b/apps/s_server.c
index 1a42bf89c7a0..2b0b6ba381fb 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -3,7 +3,7 @@
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -21,6 +21,7 @@
#include <openssl/e_os2.h>
#include <openssl/async.h>
#include <openssl/ssl.h>
+#include <openssl/decoder.h>
#ifndef OPENSSL_NO_SOCK
@@ -47,12 +48,7 @@ typedef unsigned int u_int;
#ifndef OPENSSL_NO_DH
# include <openssl/dh.h>
#endif
-#ifndef OPENSSL_NO_RSA
-# include <openssl/rsa.h>
-#endif
-#ifndef OPENSSL_NO_SRP
-# include <openssl/srp.h>
-#endif
+#include <openssl/rsa.h>
#include "s_apps.h"
#include "timeouts.h"
#ifdef CHARSET_EBCDIC
@@ -71,9 +67,6 @@ static int generate_session_id(SSL *ssl, unsigned char *id,
unsigned int *id_len);
static void init_session_cache_ctx(SSL_CTX *sctx);
static void free_sessions(void);
-#ifndef OPENSSL_NO_DH
-static DH *load_dh_param(const char *dhfile);
-#endif
static void print_connection_info(SSL *con);
static const int bufsize = 16 * 1024;
@@ -103,6 +96,8 @@ static int keymatexportlen = 20;
static int async = 0;
+static int use_sendfile = 0;
+
static const char *session_id_prefix = NULL;
#ifndef OPENSSL_NO_DTLS
@@ -123,6 +118,8 @@ static SSL_SESSION *psksess = NULL;
static char *psk_identity = "Client_identity";
char *psk_key = NULL; /* by default PSK is not used */
+static char http_server_binmode = 0; /* for now: 0/1 = default/binary */
+
#ifndef OPENSSL_NO_PSK
static unsigned int psk_server_cb(SSL *ssl, const char *identity,
unsigned char *psk,
@@ -241,56 +238,7 @@ static int psk_find_session_cb(SSL *ssl, const unsigned char *identity,
}
#ifndef OPENSSL_NO_SRP
-/* This is a context that we pass to callbacks */
-typedef struct srpsrvparm_st {
- char *login;
- SRP_VBASE *vb;
- SRP_user_pwd *user;
-} srpsrvparm;
static srpsrvparm srp_callback_parm;
-
-/*
- * This callback pretends to require some asynchronous logic in order to
- * obtain a verifier. When the callback is called for a new connection we
- * return with a negative value. This will provoke the accept etc to return
- * with an LOOKUP_X509. The main logic of the reinvokes the suspended call
- * (which would normally occur after a worker has finished) and we set the
- * user parameters.
- */
-static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
-{
- srpsrvparm *p = (srpsrvparm *) arg;
- int ret = SSL3_AL_FATAL;
-
- if (p->login == NULL && p->user == NULL) {
- p->login = SSL_get_srp_username(s);
- BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login);
- return -1;
- }
-
- if (p->user == NULL) {
- BIO_printf(bio_err, "User %s doesn't exist\n", p->login);
- goto err;
- }
-
- if (SSL_set_srp_server_param
- (s, p->user->N, p->user->g, p->user->s, p->user->v,
- p->user->info) < 0) {
- *ad = SSL_AD_INTERNAL_ERROR;
- goto err;
- }
- BIO_printf(bio_err,
- "SRP parameters set: username = \"%s\" info=\"%s\" \n",
- p->login, p->user->info);
- ret = SSL_ERROR_NONE;
-
- err:
- SRP_user_pwd_free(p->user);
- p->user = NULL;
- p->login = NULL;
- return ret;
-}
-
#endif
static int local_argc = 0;
@@ -476,7 +424,7 @@ static int ssl_servername_cb(SSL *s, int *ad, void *arg)
BIO_printf(p->biodebug, "Hostname in TLS extension: \"");
while ((uc = *cp++) != 0)
BIO_printf(p->biodebug,
- isascii(uc) && isprint(uc) ? "%c" : "\\x%02x", uc);
+ (((uc) & ~127) == 0) && isprint(uc) ? "%c" : "\\x%02x", uc);
BIO_printf(p->biodebug, "\"\n");
}
@@ -484,7 +432,7 @@ static int ssl_servername_cb(SSL *s, int *ad, void *arg)
return SSL_TLSEXT_ERR_NOACK;
if (servername != NULL) {
- if (strcasecmp(servername, p->servername))
+ if (OPENSSL_strcasecmp(servername, p->servername))
return p->extension_error;
if (ctx2 != NULL) {
BIO_printf(p->biodebug, "Switching server context.\n");
@@ -501,6 +449,7 @@ typedef struct tlsextstatusctx_st {
char *respin;
/* Default responder to use */
char *host, *path, *port;
+ char *proxy, *no_proxy;
int use_ssl;
int verbose;
} tlsextstatusctx;
@@ -520,6 +469,7 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
OCSP_RESPONSE **resp)
{
char *host = NULL, *port = NULL, *path = NULL;
+ char *proxy = NULL, *no_proxy = NULL;
int use_ssl;
STACK_OF(OPENSSL_STRING) *aia = NULL;
X509 *x = NULL;
@@ -535,8 +485,8 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
x = SSL_get_certificate(s);
aia = X509_get1_ocsp(x);
if (aia != NULL) {
- if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0),
- &host, &port, &path, &use_ssl)) {
+ if (!OSSL_HTTP_parse_url(sk_OPENSSL_STRING_value(aia, 0), &use_ssl,
+ NULL, &host, &port, NULL, &path, NULL, NULL)) {
BIO_puts(bio_err, "cert_status: can't parse AIA URL\n");
goto err;
}
@@ -554,6 +504,8 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
port = srctx->port;
use_ssl = srctx->use_ssl;
}
+ proxy = srctx->proxy;
+ no_proxy = srctx->no_proxy;
inctx = X509_STORE_CTX_new();
if (inctx == NULL)
@@ -585,8 +537,8 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
if (!OCSP_REQUEST_add_ext(req, ext, -1))
goto err;
}
- *resp = process_responder(req, host, path, port, use_ssl, NULL,
- srctx->timeout);
+ *resp = process_responder(req, host, port, path, proxy, no_proxy,
+ use_ssl, NULL /* headers */, srctx->timeout);
if (*resp == NULL) {
BIO_puts(bio_err, "cert_status: error querying responder\n");
goto done;
@@ -716,7 +668,7 @@ static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,
if (SSL_select_next_proto
((unsigned char **)out, outlen, alpn_ctx->data, alpn_ctx->len, in,
inlen) != OPENSSL_NPN_NEGOTIATED) {
- return SSL_TLSEXT_ERR_NOACK;
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
}
if (!s_quiet) {
@@ -735,7 +687,8 @@ static int not_resumable_sess_cb(SSL *s, int is_forward_secure)
}
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE,
+ OPT_COMMON,
+ OPT_ENGINE,
OPT_4, OPT_6, OPT_ACCEPT, OPT_PORT, OPT_UNIX, OPT_UNLINK, OPT_NACCEPT,
OPT_VERIFY, OPT_NAMEOPT, OPT_UPPER_V_VERIFY, OPT_CONTEXT, OPT_CERT, OPT_CRL,
OPT_CRL_DOWNLOAD, OPT_SERVERINFO, OPT_CERTFORM, OPT_KEY, OPT_KEYFORM,
@@ -744,9 +697,12 @@ typedef enum OPTION_choice {
OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, OPT_NO_CACHE,
OPT_EXT_CACHE, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET,
OPT_BUILD_CHAIN, OPT_CAFILE, OPT_NOCAFILE, OPT_CHAINCAFILE,
- OPT_VERIFYCAFILE, OPT_NBIO, OPT_NBIO_TEST, OPT_IGN_EOF, OPT_NO_IGN_EOF,
+ OPT_VERIFYCAFILE,
+ OPT_CASTORE, OPT_NOCASTORE, OPT_CHAINCASTORE, OPT_VERIFYCASTORE,
+ OPT_NBIO, OPT_NBIO_TEST, OPT_IGN_EOF, OPT_NO_IGN_EOF,
OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_STATUS_VERBOSE,
- OPT_STATUS_TIMEOUT, OPT_STATUS_URL, OPT_STATUS_FILE, OPT_MSG, OPT_MSGFILE,
+ OPT_STATUS_TIMEOUT, OPT_PROXY, OPT_NO_PROXY, OPT_STATUS_URL,
+ OPT_STATUS_FILE, OPT_MSG, OPT_MSGFILE,
OPT_TRACE, OPT_SECURITY_DEBUG, OPT_SECURITY_DEBUG_VERBOSE, OPT_STATE,
OPT_CRLF, OPT_QUIET, OPT_BRIEF, OPT_NO_DHE,
OPT_NO_RESUME_EPHEMERAL, OPT_PSK_IDENTITY, OPT_PSK_HINT, OPT_PSK,
@@ -756,132 +712,154 @@ typedef enum OPTION_choice {
OPT_SSL3, OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1,
OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_LISTEN, OPT_STATELESS,
OPT_ID_PREFIX, OPT_SERVERNAME, OPT_SERVERNAME_FATAL,
- OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN,
+ OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN, OPT_SENDFILE,
OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN,
OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_RECV_MAX_EARLY, OPT_EARLY_DATA,
OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY, OPT_SCTP_LABEL_BUG,
+ OPT_HTTP_SERVER_BINMODE, OPT_NOCANAMES, OPT_IGNORE_UNEXPECTED_EOF,
OPT_R_ENUM,
OPT_S_ENUM,
OPT_V_ENUM,
- OPT_X_ENUM
+ OPT_X_ENUM,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS s_server_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"ssl_config", OPT_SSL_CONFIG, 's',
+ "Configure SSL_CTX using the given configuration value"},
+#ifndef OPENSSL_NO_SSL_TRACE
+ {"trace", OPT_TRACE, '-', "trace protocol messages"},
+#endif
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Network"),
{"port", OPT_PORT, 'p',
"TCP/IP port to listen on for connections (default is " PORT ")"},
{"accept", OPT_ACCEPT, 's',
"TCP/IP optional host and port to listen on for connections (default is *:" PORT ")"},
#ifdef AF_UNIX
{"unix", OPT_UNIX, 's', "Unix domain socket to accept on"},
+ {"unlink", OPT_UNLINK, '-', "For -unix, unlink existing socket first"},
#endif
{"4", OPT_4, '-', "Use IPv4 only"},
{"6", OPT_6, '-', "Use IPv6 only"},
-#ifdef AF_UNIX
- {"unlink", OPT_UNLINK, '-', "For -unix, unlink existing socket first"},
-#endif
+
+ OPT_SECTION("Identity"),
{"context", OPT_CONTEXT, 's', "Set session ID context"},
+ {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"},
+ {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
+ {"CAstore", OPT_CASTORE, ':', "URI to store of CA's"},
+ {"no-CAfile", OPT_NOCAFILE, '-',
+ "Do not load the default certificates file"},
+ {"no-CApath", OPT_NOCAPATH, '-',
+ "Do not load certificates from the default certificates directory"},
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load certificates from the default certificates store URI"},
+ {"nocert", OPT_NOCERT, '-', "Don't use any certificates (Anon-DH)"},
{"verify", OPT_VERIFY, 'n', "Turn on peer certificate verification"},
{"Verify", OPT_UPPER_V_VERIFY, 'n',
"Turn on peer certificate verification, must have a cert"},
- {"cert", OPT_CERT, '<', "Certificate file to use; default is " TEST_CERT},
- {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
- {"naccept", OPT_NACCEPT, 'p', "Terminate after #num connections"},
+ {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
+ {"cert", OPT_CERT, '<', "Server certificate file to use; default " TEST_CERT},
+ {"cert2", OPT_CERT2, '<',
+ "Certificate file to use for servername; default " TEST_CERT2},
+ {"certform", OPT_CERTFORM, 'F',
+ "Server certificate file format (PEM/DER/P12); has no effect"},
+ {"cert_chain", OPT_CERT_CHAIN, '<',
+ "Server certificate chain file in PEM format"},
+ {"build_chain", OPT_BUILD_CHAIN, '-', "Build server certificate chain"},
{"serverinfo", OPT_SERVERINFO, 's',
"PEM serverinfo file for certificate"},
- {"certform", OPT_CERTFORM, 'F',
- "Certificate format (PEM or DER) PEM default"},
{"key", OPT_KEY, 's',
- "Private Key if not in -cert; default is " TEST_CERT},
- {"keyform", OPT_KEYFORM, 'f',
- "Key format (PEM, DER or ENGINE) PEM default"},
- {"pass", OPT_PASS, 's', "Private key file pass phrase source"},
+ "Private key file to use; default is -cert file or else" TEST_CERT},
+ {"key2", OPT_KEY2, '<',
+ "-Private Key file to use for servername if not in -cert2"},
+ {"keyform", OPT_KEYFORM, 'f', "Key format (ENGINE, other values ignored)"},
+ {"pass", OPT_PASS, 's', "Private key and cert file pass phrase source"},
{"dcert", OPT_DCERT, '<',
- "Second certificate file to use (usually for DSA)"},
- {"dhparam", OPT_DHPARAM, '<', "DH parameters file to use"},
+ "Second server certificate file to use (usually for DSA)"},
{"dcertform", OPT_DCERTFORM, 'F',
- "Second certificate format (PEM or DER) PEM default"},
+ "Second server certificate file format (PEM/DER/P12); has no effect"},
+ {"dcert_chain", OPT_DCERT_CHAIN, '<',
+ "second server certificate chain file in PEM format"},
{"dkey", OPT_DKEY, '<',
"Second private key file to use (usually for DSA)"},
{"dkeyform", OPT_DKEYFORM, 'F',
- "Second key format (PEM, DER or ENGINE) PEM default"},
- {"dpass", OPT_DPASS, 's', "Second private key file pass phrase source"},
+ "Second key file format (ENGINE, other values ignored)"},
+ {"dpass", OPT_DPASS, 's',
+ "Second private key and cert file pass phrase source"},
+ {"dhparam", OPT_DHPARAM, '<', "DH parameters file to use"},
+ {"servername", OPT_SERVERNAME, 's',
+ "Servername for HostName TLS extension"},
+ {"servername_fatal", OPT_SERVERNAME_FATAL, '-',
+ "On servername mismatch send fatal alert (default warning alert)"},
{"nbio_test", OPT_NBIO_TEST, '-', "Test with the non-blocking test bio"},
{"crlf", OPT_CRLF, '-', "Convert LF from terminal into CRLF"},
- {"debug", OPT_DEBUG, '-', "Print more output"},
- {"msg", OPT_MSG, '-', "Show protocol messages"},
- {"msgfile", OPT_MSGFILE, '>',
- "File to send output of -msg or -trace, instead of stdout"},
- {"state", OPT_STATE, '-', "Print the SSL states"},
- {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"},
- {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
- {"no-CAfile", OPT_NOCAFILE, '-',
- "Do not load the default certificates file"},
- {"no-CApath", OPT_NOCAPATH, '-',
- "Do not load certificates from the default certificates directory"},
- {"nocert", OPT_NOCERT, '-', "Don't use any certificates (Anon-DH)"},
{"quiet", OPT_QUIET, '-', "No server output"},
{"no_resume_ephemeral", OPT_NO_RESUME_EPHEMERAL, '-',
"Disable caching and tickets if ephemeral (EC)DH is used"},
{"www", OPT_WWW, '-', "Respond to a 'GET /' with a status page"},
{"WWW", OPT_UPPER_WWW, '-', "Respond to a 'GET with the file ./path"},
- {"servername", OPT_SERVERNAME, 's',
- "Servername for HostName TLS extension"},
- {"servername_fatal", OPT_SERVERNAME_FATAL, '-',
- "mismatch send fatal alert (default warning alert)"},
- {"cert2", OPT_CERT2, '<',
- "Certificate file to use for servername; default is" TEST_CERT2},
- {"key2", OPT_KEY2, '<',
- "-Private Key file to use for servername if not in -cert2"},
+ {"ignore_unexpected_eof", OPT_IGNORE_UNEXPECTED_EOF, '-',
+ "Do not treat lack of close_notify from a peer as an error"},
{"tlsextdebug", OPT_TLSEXTDEBUG, '-',
"Hex dump of all TLS extensions received"},
{"HTTP", OPT_HTTP, '-', "Like -WWW but ./path includes HTTP headers"},
{"id_prefix", OPT_ID_PREFIX, 's',
"Generate SSL/TLS session IDs prefixed by arg"},
- OPT_R_OPTIONS,
{"keymatexport", OPT_KEYMATEXPORT, 's',
"Export keying material using label"},
{"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p',
- "Export len bytes of keying material (default 20)"},
+ "Export len bytes of keying material; default 20"},
{"CRL", OPT_CRL, '<', "CRL file to use"},
+ {"CRLform", OPT_CRLFORM, 'F', "CRL file format (PEM or DER); default PEM"},
{"crl_download", OPT_CRL_DOWNLOAD, '-',
- "Download CRL from distribution points"},
- {"cert_chain", OPT_CERT_CHAIN, '<',
- "certificate chain file in PEM format"},
- {"dcert_chain", OPT_DCERT_CHAIN, '<',
- "second certificate chain file in PEM format"},
+ "Download CRLs from distribution points in certificate CDP entries"},
+ {"chainCAfile", OPT_CHAINCAFILE, '<',
+ "CA file for certificate chain (PEM format)"},
{"chainCApath", OPT_CHAINCAPATH, '/',
"use dir as certificate store path to build CA certificate chain"},
+ {"chainCAstore", OPT_CHAINCASTORE, ':',
+ "use URI as certificate store to build CA certificate chain"},
+ {"verifyCAfile", OPT_VERIFYCAFILE, '<',
+ "CA file for certificate verification (PEM format)"},
{"verifyCApath", OPT_VERIFYCAPATH, '/',
"use dir as certificate store path to verify CA certificate"},
+ {"verifyCAstore", OPT_VERIFYCASTORE, ':',
+ "use URI as certificate store to verify CA certificate"},
{"no_cache", OPT_NO_CACHE, '-', "Disable session cache"},
{"ext_cache", OPT_EXT_CACHE, '-',
- "Disable internal cache, setup and use external cache"},
- {"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER) PEM is default"},
+ "Disable internal cache, set up and use external cache"},
{"verify_return_error", OPT_VERIFY_RET_ERROR, '-',
"Close connection on verification error"},
{"verify_quiet", OPT_VERIFY_QUIET, '-',
"No verify output except verify errors"},
- {"build_chain", OPT_BUILD_CHAIN, '-', "Build certificate chain"},
- {"chainCAfile", OPT_CHAINCAFILE, '<',
- "CA file for certificate chain (PEM format)"},
- {"verifyCAfile", OPT_VERIFYCAFILE, '<',
- "CA file for certificate verification (PEM format)"},
- {"ign_eof", OPT_IGN_EOF, '-', "ignore input eof (default when -quiet)"},
- {"no_ign_eof", OPT_NO_IGN_EOF, '-', "Do not ignore input eof"},
+ {"ign_eof", OPT_IGN_EOF, '-', "Ignore input EOF (default when -quiet)"},
+ {"no_ign_eof", OPT_NO_IGN_EOF, '-', "Do not ignore input EOF"},
+
#ifndef OPENSSL_NO_OCSP
+ OPT_SECTION("OCSP"),
{"status", OPT_STATUS, '-', "Request certificate status from server"},
{"status_verbose", OPT_STATUS_VERBOSE, '-',
"Print more output in certificate status callback"},
{"status_timeout", OPT_STATUS_TIMEOUT, 'n',
"Status request responder timeout"},
{"status_url", OPT_STATUS_URL, 's', "Status request fallback URL"},
+ {"proxy", OPT_PROXY, 's',
+ "[http[s]://]host[:port][/path] of HTTP(S) proxy to use; path is ignored"},
+ {"no_proxy", OPT_NO_PROXY, 's',
+ "List of addresses of servers not to use HTTP(S) proxy for"},
+ {OPT_MORE_STR, 0, 0,
+ "Default from environment variable 'no_proxy', else 'NO_PROXY', else none"},
{"status_file", OPT_STATUS_FILE, '<',
"File containing DER encoded OCSP Response"},
#endif
-#ifndef OPENSSL_NO_SSL_TRACE
- {"trace", OPT_TRACE, '-', "trace protocol messages"},
-#endif
+
+ OPT_SECTION("Debug"),
{"security_debug", OPT_SECURITY_DEBUG, '-',
"Print output from SSL/TLS security framework"},
{"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-',
@@ -889,21 +867,29 @@ const OPTIONS s_server_options[] = {
{"brief", OPT_BRIEF, '-',
"Restrict output to brief summary of connection parameters"},
{"rev", OPT_REV, '-',
- "act as a simple test server which just sends back with the received text reversed"},
+ "act as an echo server that sends back received text reversed"},
+ {"debug", OPT_DEBUG, '-', "Print more output"},
+ {"msg", OPT_MSG, '-', "Show protocol messages"},
+ {"msgfile", OPT_MSGFILE, '>',
+ "File to send output of -msg or -trace, instead of stdout"},
+ {"state", OPT_STATE, '-', "Print the SSL states"},
{"async", OPT_ASYNC, '-', "Operate in asynchronous mode"},
- {"ssl_config", OPT_SSL_CONFIG, 's',
- "Configure SSL_CTX using the configuration 'val'"},
- {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "},
- {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p',
- "Size used to split data for encrypt pipelines"},
{"max_pipelines", OPT_MAX_PIPELINES, 'p',
"Maximum number of encrypt/decrypt pipelines to be used"},
+ {"naccept", OPT_NACCEPT, 'p', "Terminate after #num connections"},
+ {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"},
+
+ OPT_SECTION("Network"),
+ {"nbio", OPT_NBIO, '-', "Use non-blocking IO"},
+ {"timeout", OPT_TIMEOUT, '-', "Enable timeouts"},
+ {"mtu", OPT_MTU, 'p', "Set link-layer MTU"},
{"read_buf", OPT_READ_BUF, 'p',
"Default read buffer size to be used for connections"},
- OPT_S_OPTIONS,
- OPT_V_OPTIONS,
- OPT_X_OPTIONS,
- {"nbio", OPT_NBIO, '-', "Use non-blocking IO"},
+ {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p',
+ "Size used to split data for encrypt pipelines"},
+ {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "},
+
+ OPT_SECTION("Server identity"),
{"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity to expect"},
#ifndef OPENSSL_NO_PSK
{"psk_hint", OPT_PSK_HINT, 's', "PSK identity hint to use"},
@@ -911,10 +897,25 @@ const OPTIONS s_server_options[] = {
{"psk", OPT_PSK, 's', "PSK in hex (without 0x)"},
{"psk_session", OPT_PSK_SESS, '<', "File to read PSK SSL session from"},
#ifndef OPENSSL_NO_SRP
- {"srpvfile", OPT_SRPVFILE, '<', "The verifier file for SRP"},
+ {"srpvfile", OPT_SRPVFILE, '<', "(deprecated) The verifier file for SRP"},
{"srpuserseed", OPT_SRPUSERSEED, 's',
- "A seed string for a default user salt"},
+ "(deprecated) A seed string for a default user salt"},
#endif
+
+ OPT_SECTION("Protocol and version"),
+ {"max_early_data", OPT_MAX_EARLY, 'n',
+ "The maximum number of bytes of early data as advertised in tickets"},
+ {"recv_max_early_data", OPT_RECV_MAX_EARLY, 'n',
+ "The maximum number of bytes of early data (hard limit)"},
+ {"early_data", OPT_EARLY_DATA, '-', "Attempt to read early data"},
+ {"num_tickets", OPT_S_NUM_TICKETS, 'n',
+ "The number of TLSv1.3 session tickets that a server will automatically issue" },
+ {"anti_replay", OPT_ANTI_REPLAY, '-', "Switch on anti-replay protection (default)"},
+ {"no_anti_replay", OPT_NO_ANTI_REPLAY, '-', "Switch off anti-replay protection"},
+ {"http_server_binmode", OPT_HTTP_SERVER_BINMODE, '-', "opening files in binary mode when acting as http server (-WWW and -HTTP)"},
+ {"no_ca_names", OPT_NOCANAMES, '-',
+ "Disable TLS Extension CA Names"},
+ {"stateless", OPT_STATELESS, '-', "Require TLSv1.3 cookies"},
#ifndef OPENSSL_NO_SSL3
{"ssl3", OPT_SSL3, '-', "Just talk SSLv3"},
#endif
@@ -932,12 +933,9 @@ const OPTIONS s_server_options[] = {
#endif
#ifndef OPENSSL_NO_DTLS
{"dtls", OPT_DTLS, '-', "Use any DTLS version"},
- {"timeout", OPT_TIMEOUT, '-', "Enable timeouts"},
- {"mtu", OPT_MTU, 'p', "Set link layer MTU"},
{"listen", OPT_LISTEN, '-',
"Listen for a DTLS ClientHello with a cookie and then connect"},
#endif
- {"stateless", OPT_STATELESS, '-', "Require TLSv1.3 cookies"},
#ifndef OPENSSL_NO_DTLS1
{"dtls1", OPT_DTLS1, '-', "Just talk DTLSv1"},
#endif
@@ -948,33 +946,27 @@ const OPTIONS s_server_options[] = {
{"sctp", OPT_SCTP, '-', "Use SCTP"},
{"sctp_label_bug", OPT_SCTP_LABEL_BUG, '-', "Enable SCTP label length bug"},
#endif
-#ifndef OPENSSL_NO_DH
- {"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"},
+#ifndef OPENSSL_NO_SRTP
+ {"use_srtp", OPT_SRTP_PROFILES, 's',
+ "Offer SRTP key management with a colon-separated profile list"},
#endif
+ {"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"},
#ifndef OPENSSL_NO_NEXTPROTONEG
{"nextprotoneg", OPT_NEXTPROTONEG, 's',
"Set the advertised protocols for the NPN extension (comma-separated list)"},
#endif
-#ifndef OPENSSL_NO_SRTP
- {"use_srtp", OPT_SRTP_PROFILES, 's',
- "Offer SRTP key management with a colon-separated profile list"},
-#endif
{"alpn", OPT_ALPN, 's',
"Set the advertised protocols for the ALPN extension (comma-separated list)"},
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#ifndef OPENSSL_NO_KTLS
+ {"sendfile", OPT_SENDFILE, '-', "Use sendfile to response file with -WWW"},
#endif
- {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"},
- {"max_early_data", OPT_MAX_EARLY, 'n',
- "The maximum number of bytes of early data as advertised in tickets"},
- {"recv_max_early_data", OPT_RECV_MAX_EARLY, 'n',
- "The maximum number of bytes of early data (hard limit)"},
- {"early_data", OPT_EARLY_DATA, '-', "Attempt to read early data"},
- {"num_tickets", OPT_S_NUM_TICKETS, 'n',
- "The number of TLSv1.3 session tickets that a server will automatically issue" },
- {"anti_replay", OPT_ANTI_REPLAY, '-', "Switch on anti-replay protection (default)"},
- {"no_anti_replay", OPT_NO_ANTI_REPLAY, '-', "Switch off anti-replay protection"},
- {NULL, OPT_EOF, 0, NULL}
+
+ OPT_R_OPTIONS,
+ OPT_S_OPTIONS,
+ OPT_V_OPTIONS,
+ OPT_X_OPTIONS,
+ OPT_PROV_OPTIONS,
+ {NULL}
};
#define IS_PROT_FLAG(o) \
@@ -993,28 +985,28 @@ int s_server_main(int argc, char *argv[])
STACK_OF(X509_CRL) *crls = NULL;
X509 *s_cert = NULL, *s_dcert = NULL;
X509_VERIFY_PARAM *vpm = NULL;
- const char *CApath = NULL, *CAfile = NULL, *chCApath = NULL, *chCAfile = NULL;
+ const char *CApath = NULL, *CAfile = NULL, *CAstore = NULL;
+ const char *chCApath = NULL, *chCAfile = NULL, *chCAstore = NULL;
char *dpassarg = NULL, *dpass = NULL;
- char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL;
+ char *passarg = NULL, *pass = NULL;
+ char *vfyCApath = NULL, *vfyCAfile = NULL, *vfyCAstore = NULL;
char *crl_file = NULL, *prog;
#ifdef AF_UNIX
int unlink_unix_path = 0;
#endif
do_server_cb server_cb;
int vpmtouched = 0, build_chain = 0, no_cache = 0, ext_cache = 0;
-#ifndef OPENSSL_NO_DH
char *dhfile = NULL;
int no_dhe = 0;
-#endif
int nocert = 0, ret = 1;
- int noCApath = 0, noCAfile = 0;
- int s_cert_format = FORMAT_PEM, s_key_format = FORMAT_PEM;
- int s_dcert_format = FORMAT_PEM, s_dkey_format = FORMAT_PEM;
+ int noCApath = 0, noCAfile = 0, noCAstore = 0;
+ int s_cert_format = FORMAT_UNDEF, s_key_format = FORMAT_UNDEF;
+ int s_dcert_format = FORMAT_UNDEF, s_dkey_format = FORMAT_UNDEF;
int rev = 0, naccept = -1, sdebug = 0;
int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0;
- int state = 0, crl_format = FORMAT_PEM, crl_download = 0;
+ int state = 0, crl_format = FORMAT_UNDEF, crl_download = 0;
char *host = NULL;
- char *port = BUF_strdup(PORT);
+ char *port = NULL;
unsigned char *context = NULL;
OPTION_CHOICE o;
EVP_PKEY *s_key2 = NULL;
@@ -1056,9 +1048,11 @@ int s_server_main(int argc, char *argv[])
const char *keylog_file = NULL;
int max_early_data = -1, recv_max_early_data = -1;
char *psksessf = NULL;
+ int no_ca_names = 0;
#ifndef OPENSSL_NO_SCTP
int sctp_label_bug = 0;
#endif
+ int ignore_unexpected_eof = 0;
/* Init of few remaining global variables */
local_argc = argc;
@@ -1073,10 +1067,12 @@ int s_server_main(int argc, char *argv[])
s_quiet = 0;
s_brief = 0;
async = 0;
+ use_sendfile = 0;
+ port = OPENSSL_strdup(PORT);
cctx = SSL_CONF_CTX_new();
vpm = X509_VERIFY_PARAM_new();
- if (cctx == NULL || vpm == NULL)
+ if (port == NULL || cctx == NULL || vpm == NULL)
goto end;
SSL_CONF_CTX_set_flags(cctx,
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CMDLINE);
@@ -1163,7 +1159,9 @@ int s_server_main(int argc, char *argv[])
#ifdef AF_UNIX
case OPT_UNIX:
socket_family = AF_UNIX;
- OPENSSL_free(host); host = BUF_strdup(opt_arg());
+ OPENSSL_free(host); host = OPENSSL_strdup(opt_arg());
+ if (host == NULL)
+ goto end;
OPENSSL_free(port); port = NULL;
break;
case OPT_UNLINK:
@@ -1209,7 +1207,7 @@ int s_server_main(int argc, char *argv[])
s_serverinfo_file = opt_arg();
break;
case OPT_CERTFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_cert_format))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_cert_format))
goto opthelp;
break;
case OPT_KEY:
@@ -1226,19 +1224,17 @@ int s_server_main(int argc, char *argv[])
s_chain_file = opt_arg();
break;
case OPT_DHPARAM:
-#ifndef OPENSSL_NO_DH
dhfile = opt_arg();
-#endif
break;
case OPT_DCERTFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dcert_format))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_dcert_format))
goto opthelp;
break;
case OPT_DCERT:
s_dcert_file = opt_arg();
break;
case OPT_DKEYFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dkey_format))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_dkey_format))
goto opthelp;
break;
case OPT_DPASS:
@@ -1265,6 +1261,18 @@ int s_server_main(int argc, char *argv[])
case OPT_VERIFYCAPATH:
vfyCApath = opt_arg();
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
+ case OPT_CHAINCASTORE:
+ chCAstore = opt_arg();
+ break;
+ case OPT_VERIFYCASTORE:
+ vfyCAstore = opt_arg();
+ break;
case OPT_NO_CACHE:
no_cache = 1;
break;
@@ -1352,14 +1360,23 @@ int s_server_main(int argc, char *argv[])
tlscstatp.timeout = atoi(opt_arg());
#endif
break;
+ case OPT_PROXY:
+#ifndef OPENSSL_NO_OCSP
+ tlscstatp.proxy = opt_arg();
+#endif
+ break;
+ case OPT_NO_PROXY:
+#ifndef OPENSSL_NO_OCSP
+ tlscstatp.no_proxy = opt_arg();
+#endif
+ break;
case OPT_STATUS_URL:
#ifndef OPENSSL_NO_OCSP
s_tlsextstatus = 1;
- if (!OCSP_parse_url(opt_arg(),
- &tlscstatp.host,
- &tlscstatp.port,
- &tlscstatp.path, &tlscstatp.use_ssl)) {
- BIO_printf(bio_err, "Error parsing URL\n");
+ if (!OSSL_HTTP_parse_url(opt_arg(), &tlscstatp.use_ssl, NULL,
+ &tlscstatp.host, &tlscstatp.port, NULL,
+ &tlscstatp.path, NULL, NULL)) {
+ BIO_printf(bio_err, "Error parsing -status_url argument\n");
goto end;
}
#endif
@@ -1375,6 +1392,10 @@ int s_server_main(int argc, char *argv[])
break;
case OPT_MSGFILE:
bio_s_msg = BIO_new_file(opt_arg(), "w");
+ if (bio_s_msg == NULL) {
+ BIO_printf(bio_err, "Error writing file %s\n", opt_arg());
+ goto end;
+ }
break;
case OPT_TRACE:
#ifndef OPENSSL_NO_SSL_TRACE
@@ -1400,9 +1421,7 @@ int s_server_main(int argc, char *argv[])
s_quiet = s_brief = verify_args.quiet = 1;
break;
case OPT_NO_DHE:
-#ifndef OPENSSL_NO_DH
no_dhe = 1;
-#endif
break;
case OPT_NO_RESUME_EPHEMERAL:
no_resume_ephemeral = 1;
@@ -1529,12 +1548,18 @@ int s_server_main(int argc, char *argv[])
session_id_prefix = opt_arg();
break;
case OPT_ENGINE:
- engine = setup_engine(opt_arg(), 1);
+#ifndef OPENSSL_NO_ENGINE
+ engine = setup_engine(opt_arg(), s_debug);
+#endif
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_SERVERNAME:
tlsextcbp.servername = opt_arg();
break;
@@ -1603,10 +1628,30 @@ int s_server_main(int argc, char *argv[])
if (max_early_data == -1)
max_early_data = SSL3_RT_MAX_PLAIN_LENGTH;
break;
+ case OPT_HTTP_SERVER_BINMODE:
+ http_server_binmode = 1;
+ break;
+ case OPT_NOCANAMES:
+ no_ca_names = 1;
+ break;
+ case OPT_SENDFILE:
+#ifndef OPENSSL_NO_KTLS
+ use_sendfile = 1;
+#endif
+ break;
+ case OPT_IGNORE_UNEXPECTED_EOF:
+ ignore_unexpected_eof = 1;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
- argv = opt_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ if (!app_RAND_load())
+ goto end;
#ifndef OPENSSL_NO_NEXTPROTONEG
if (min_version == TLS1_3_VERSION && next_proto_neg_in != NULL) {
@@ -1655,6 +1700,13 @@ int s_server_main(int argc, char *argv[])
}
#endif
+#ifndef OPENSSL_NO_KTLS
+ if (use_sendfile && www <= 1) {
+ BIO_printf(bio_err, "Can't use -sendfile without -WWW or -HTTP\n");
+ goto end;
+ }
+#endif
+
if (!app_passwd(passarg, dpassarg, &pass, &dpass)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
@@ -1671,40 +1723,32 @@ int s_server_main(int argc, char *argv[])
if (nocert == 0) {
s_key = load_key(s_key_file, s_key_format, 0, pass, engine,
- "server certificate private key file");
- if (s_key == NULL) {
- ERR_print_errors(bio_err);
+ "server certificate private key");
+ if (s_key == NULL)
goto end;
- }
- s_cert = load_cert(s_cert_file, s_cert_format,
- "server certificate file");
+ s_cert = load_cert_pass(s_cert_file, s_cert_format, 1, pass,
+ "server certificate");
- if (s_cert == NULL) {
- ERR_print_errors(bio_err);
+ if (s_cert == NULL)
goto end;
- }
if (s_chain_file != NULL) {
- if (!load_certs(s_chain_file, &s_chain, FORMAT_PEM, NULL,
+ if (!load_certs(s_chain_file, 0, &s_chain, NULL,
"server certificate chain"))
goto end;
}
if (tlsextcbp.servername != NULL) {
s_key2 = load_key(s_key_file2, s_key_format, 0, pass, engine,
- "second server certificate private key file");
- if (s_key2 == NULL) {
- ERR_print_errors(bio_err);
+ "second server certificate private key");
+ if (s_key2 == NULL)
goto end;
- }
- s_cert2 = load_cert(s_cert_file2, s_cert_format,
- "second server certificate file");
+ s_cert2 = load_cert_pass(s_cert_file2, s_cert_format, 1, pass,
+ "second server certificate");
- if (s_cert2 == NULL) {
- ERR_print_errors(bio_err);
+ if (s_cert2 == NULL)
goto end;
- }
}
}
#if !defined(OPENSSL_NO_NEXTPROTONEG)
@@ -1723,12 +1767,9 @@ int s_server_main(int argc, char *argv[])
if (crl_file != NULL) {
X509_CRL *crl;
- crl = load_crl(crl_file, crl_format);
- if (crl == NULL) {
- BIO_puts(bio_err, "Error loading CRL\n");
- ERR_print_errors(bio_err);
+ crl = load_crl(crl_file, crl_format, 0, "CRL");
+ if (crl == NULL)
goto end;
- }
crls = sk_X509_CRL_new_null();
if (crls == NULL || !sk_X509_CRL_push(crls, crl)) {
BIO_puts(bio_err, "Error adding CRL\n");
@@ -1744,21 +1785,19 @@ int s_server_main(int argc, char *argv[])
s_dkey_file = s_dcert_file;
s_dkey = load_key(s_dkey_file, s_dkey_format,
- 0, dpass, engine, "second certificate private key file");
- if (s_dkey == NULL) {
- ERR_print_errors(bio_err);
+ 0, dpass, engine, "second certificate private key");
+ if (s_dkey == NULL)
goto end;
- }
- s_dcert = load_cert(s_dcert_file, s_dcert_format,
- "second server certificate file");
+ s_dcert = load_cert_pass(s_dcert_file, s_dcert_format, 1, dpass,
+ "second server certificate");
if (s_dcert == NULL) {
ERR_print_errors(bio_err);
goto end;
}
if (s_dchain_file != NULL) {
- if (!load_certs(s_dchain_file, &s_dchain, FORMAT_PEM, NULL,
+ if (!load_certs(s_dchain_file, 0, &s_dchain, NULL,
"second server certificate chain"))
goto end;
}
@@ -1768,17 +1807,22 @@ int s_server_main(int argc, char *argv[])
if (bio_s_out == NULL) {
if (s_quiet && !s_debug) {
bio_s_out = BIO_new(BIO_s_null());
- if (s_msg && bio_s_msg == NULL)
+ if (s_msg && bio_s_msg == NULL) {
bio_s_msg = dup_bio_out(FORMAT_TEXT);
+ if (bio_s_msg == NULL) {
+ BIO_printf(bio_err, "Out of memory\n");
+ goto end;
+ }
+ }
} else {
- if (bio_s_out == NULL)
- bio_s_out = dup_bio_out(FORMAT_TEXT);
+ bio_s_out = dup_bio_out(FORMAT_TEXT);
}
}
-#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC)
- if (nocert)
-#endif
- {
+
+ if (bio_s_out == NULL)
+ goto end;
+
+ if (nocert) {
s_cert_file = NULL;
s_key_file = NULL;
s_dcert_file = NULL;
@@ -1787,7 +1831,7 @@ int s_server_main(int argc, char *argv[])
s_key_file2 = NULL;
}
- ctx = SSL_CTX_new(meth);
+ ctx = SSL_CTX_new_ex(app_get0_libctx(), app_get0_propq(), meth);
if (ctx == NULL) {
ERR_print_errors(bio_err);
goto end;
@@ -1809,7 +1853,6 @@ int s_server_main(int argc, char *argv[])
goto end;
}
}
-
#ifndef OPENSSL_NO_SCTP
if (protocol == IPPROTO_SCTP && sctp_label_bug == 1)
SSL_CTX_set_mode(ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG);
@@ -1833,7 +1876,6 @@ int s_server_main(int argc, char *argv[])
}
BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix);
}
- SSL_CTX_set_quiet_shutdown(ctx, 1);
if (exc != NULL)
ssl_ctx_set_excert(ctx, exc);
@@ -1850,6 +1892,13 @@ int s_server_main(int argc, char *argv[])
SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC);
}
+ if (no_ca_names) {
+ SSL_CTX_set_options(ctx, SSL_OP_DISABLE_TLSEXT_CA_NAMES);
+ }
+
+ if (ignore_unexpected_eof)
+ SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
+
if (max_send_fragment > 0
&& !SSL_CTX_set_max_send_fragment(ctx, max_send_fragment)) {
BIO_printf(bio_err, "%s: Max send fragment size %u is out of permitted range\n",
@@ -1884,7 +1933,8 @@ int s_server_main(int argc, char *argv[])
}
#endif
- if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) {
+ if (!ctx_set_verify_locations(ctx, CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore)) {
ERR_print_errors(bio_err);
goto end;
}
@@ -1896,7 +1946,9 @@ int s_server_main(int argc, char *argv[])
ssl_ctx_add_crls(ctx, crls, 0);
- if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile,
+ if (!ssl_load_stores(ctx,
+ vfyCApath, vfyCAfile, vfyCAstore,
+ chCApath, chCAfile, chCAstore,
crls, crl_download)) {
BIO_printf(bio_err, "Error loading store locations\n");
ERR_print_errors(bio_err);
@@ -1904,7 +1956,7 @@ int s_server_main(int argc, char *argv[])
}
if (s_cert2) {
- ctx2 = SSL_CTX_new(meth);
+ ctx2 = SSL_CTX_new_ex(app_get0_libctx(), app_get0_propq(), meth);
if (ctx2 == NULL) {
ERR_print_errors(bio_err);
goto end;
@@ -1928,7 +1980,6 @@ int s_server_main(int argc, char *argv[])
}
BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix);
}
- SSL_CTX_set_quiet_shutdown(ctx2, 1);
if (exc != NULL)
ssl_ctx_set_excert(ctx2, exc);
@@ -1945,8 +1996,8 @@ int s_server_main(int argc, char *argv[])
if (async)
SSL_CTX_set_mode(ctx2, SSL_MODE_ASYNC);
- if (!ctx_set_verify_locations(ctx2, CAfile, CApath, noCAfile,
- noCApath)) {
+ if (!ctx_set_verify_locations(ctx2, CAfile, noCAfile, CApath,
+ noCApath, CAstore, noCAstore)) {
ERR_print_errors(bio_err);
goto end;
}
@@ -1968,54 +2019,70 @@ int s_server_main(int argc, char *argv[])
if (alpn_ctx.data)
SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx);
-#ifndef OPENSSL_NO_DH
if (!no_dhe) {
- DH *dh = NULL;
+ EVP_PKEY *dhpkey = NULL;
if (dhfile != NULL)
- dh = load_dh_param(dhfile);
+ dhpkey = load_keyparams(dhfile, FORMAT_UNDEF, 0, "DH", "DH parameters");
else if (s_cert_file != NULL)
- dh = load_dh_param(s_cert_file);
+ dhpkey = load_keyparams_suppress(s_cert_file, FORMAT_UNDEF, 0, "DH",
+ "DH parameters", 1);
- if (dh != NULL) {
+ if (dhpkey != NULL) {
BIO_printf(bio_s_out, "Setting temp DH parameters\n");
} else {
BIO_printf(bio_s_out, "Using default temp DH parameters\n");
}
(void)BIO_flush(bio_s_out);
- if (dh == NULL) {
+ if (dhpkey == NULL) {
SSL_CTX_set_dh_auto(ctx, 1);
- } else if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
- BIO_puts(bio_err, "Error setting temp DH parameters\n");
- ERR_print_errors(bio_err);
- DH_free(dh);
- goto end;
+ } else {
+ /*
+ * We need 2 references: one for use by ctx and one for use by
+ * ctx2
+ */
+ if (!EVP_PKEY_up_ref(dhpkey)) {
+ EVP_PKEY_free(dhpkey);
+ goto end;
+ }
+ if (!SSL_CTX_set0_tmp_dh_pkey(ctx, dhpkey)) {
+ BIO_puts(bio_err, "Error setting temp DH parameters\n");
+ ERR_print_errors(bio_err);
+ /* Free 2 references */
+ EVP_PKEY_free(dhpkey);
+ EVP_PKEY_free(dhpkey);
+ goto end;
+ }
}
if (ctx2 != NULL) {
- if (!dhfile) {
- DH *dh2 = load_dh_param(s_cert_file2);
- if (dh2 != NULL) {
+ if (dhfile != NULL) {
+ EVP_PKEY *dhpkey2 = load_keyparams_suppress(s_cert_file2,
+ FORMAT_UNDEF,
+ 0, "DH",
+ "DH parameters", 1);
+
+ if (dhpkey2 != NULL) {
BIO_printf(bio_s_out, "Setting temp DH parameters\n");
(void)BIO_flush(bio_s_out);
- DH_free(dh);
- dh = dh2;
+ EVP_PKEY_free(dhpkey);
+ dhpkey = dhpkey2;
}
}
- if (dh == NULL) {
+ if (dhpkey == NULL) {
SSL_CTX_set_dh_auto(ctx2, 1);
- } else if (!SSL_CTX_set_tmp_dh(ctx2, dh)) {
+ } else if (!SSL_CTX_set0_tmp_dh_pkey(ctx2, dhpkey)) {
BIO_puts(bio_err, "Error setting temp DH parameters\n");
ERR_print_errors(bio_err);
- DH_free(dh);
+ EVP_PKEY_free(dhpkey);
goto end;
}
+ dhpkey = NULL;
}
- DH_free(dh);
+ EVP_PKEY_free(dhpkey);
}
-#endif
if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain, build_chain))
goto end;
@@ -2050,10 +2117,16 @@ int s_server_main(int argc, char *argv[])
SSL_CTX_set_psk_server_callback(ctx, psk_server_cb);
}
- if (!SSL_CTX_use_psk_identity_hint(ctx, psk_identity_hint)) {
- BIO_printf(bio_err, "error setting PSK identity hint to context\n");
- ERR_print_errors(bio_err);
- goto end;
+ if (psk_identity_hint != NULL) {
+ if (min_version == TLS1_3_VERSION) {
+ BIO_printf(bio_s_out, "PSK warning: there is NO identity hint in TLSv1.3\n");
+ } else {
+ if (!SSL_CTX_use_psk_identity_hint(ctx, psk_identity_hint)) {
+ BIO_printf(bio_err, "error setting PSK identity hint to context\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
}
#endif
if (psksessf != NULL) {
@@ -2112,20 +2185,9 @@ int s_server_main(int argc, char *argv[])
#ifndef OPENSSL_NO_SRP
if (srp_verifier_file != NULL) {
- srp_callback_parm.vb = SRP_VBASE_new(srpuserseed);
- srp_callback_parm.user = NULL;
- srp_callback_parm.login = NULL;
- if ((ret =
- SRP_VBASE_init(srp_callback_parm.vb,
- srp_verifier_file)) != SRP_NO_ERROR) {
- BIO_printf(bio_err,
- "Cannot initialize SRP verifier file \"%s\":ret=%d\n",
- srp_verifier_file, ret);
+ if (!set_up_srp_verifier_file(ctx, &srp_callback_parm, srpuserseed,
+ srp_verifier_file))
goto end;
- }
- SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback);
- SSL_CTX_set_srp_cb_arg(ctx, &srp_callback_parm);
- SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb);
} else
#endif
if (CAfile != NULL) {
@@ -2236,8 +2298,8 @@ static void print_stats(BIO *bio, SSL_CTX *ssl_ctx)
SSL_CTX_sess_get_cache_size(ssl_ctx));
}
-static long int count_reads_callback(BIO *bio, int cmd, const char *argp,
- int argi, long int argl, long int ret)
+static long int count_reads_callback(BIO *bio, int cmd, const char *argp, size_t len,
+ int argi, long argl, int ret, size_t *processed)
{
unsigned int *p_counter = (unsigned int *)BIO_get_callback_arg(bio);
@@ -2253,7 +2315,7 @@ static long int count_reads_callback(BIO *bio, int cmd, const char *argp,
if (s_debug) {
BIO_set_callback_arg(bio, (char *)bio_s_out);
- ret = bio_dump_callback(bio, cmd, argp, argi, argl, ret);
+ ret = (int)bio_dump_callback(bio, cmd, argp, len, argi, argl, ret, processed);
BIO_set_callback_arg(bio, (char *)p_counter);
}
@@ -2321,6 +2383,11 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
else
# endif
sbio = BIO_new_dgram(s, BIO_NOCLOSE);
+ if (sbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ ERR_print_errors(bio_err);
+ goto err;
+ }
if (enable_timeouts) {
timeout.tv_sec = 0;
@@ -2370,6 +2437,13 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
BIO *test;
test = BIO_new(BIO_f_nbio_test());
+ if (test == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ ret = -1;
+ BIO_free(sbio);
+ goto err;
+ }
+
sbio = BIO_push(test, sbio);
}
@@ -2377,7 +2451,7 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
SSL_set_accept_state(con);
/* SSL_set_fd(con,s); */
- BIO_set_callback(SSL_get_rbio(con), count_reads_callback);
+ BIO_set_callback_ex(SSL_get_rbio(con), count_reads_callback);
if (s_msg) {
#ifndef OPENSSL_NO_SSL_TRACE
if (s_msg == 2)
@@ -2536,14 +2610,6 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
*/
goto err;
}
-#ifndef OPENSSL_NO_HEARTBEATS
- if ((buf[0] == 'B') && ((buf[1] == '\n') || (buf[1] == '\r'))) {
- BIO_printf(bio_err, "HEARTBEATING\n");
- SSL_heartbeat(con);
- i = 0;
- continue;
- }
-#endif
if ((buf[0] == 'r') && ((buf[1] == '\n') || (buf[1] == '\r'))) {
SSL_renegotiate(con);
i = SSL_do_handshake(con);
@@ -2585,8 +2651,8 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
continue;
}
if (buf[0] == 'P') {
- static const char *str = "Lets print some clear text\n";
- BIO_write(SSL_get_wbio(con), str, strlen(str));
+ static const char str[] = "Lets print some clear text\n";
+ BIO_write(SSL_get_wbio(con), str, sizeof(str) -1);
}
if (buf[0] == 'S') {
print_stats(bio_s_out, SSL_get_SSL_CTX(con));
@@ -2609,15 +2675,9 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
#ifndef OPENSSL_NO_SRP
while (SSL_get_error(con, k) == SSL_ERROR_WANT_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during write\n");
- SRP_user_pwd_free(srp_callback_parm.user);
- srp_callback_parm.user =
- SRP_VBASE_get1_by_user(srp_callback_parm.vb,
- srp_callback_parm.login);
- if (srp_callback_parm.user)
- BIO_printf(bio_s_out, "LOOKUP done %s\n",
- srp_callback_parm.user->info);
- else
- BIO_printf(bio_s_out, "LOOKUP not successful\n");
+
+ lookup_srp_user(&srp_callback_parm, bio_s_out);
+
k = SSL_write(con, &(buf[l]), (unsigned int)i);
}
#endif
@@ -2688,7 +2748,6 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
ret = -1;
goto err;
}
-
if (i < 0) {
ret = 0;
goto err;
@@ -2702,15 +2761,9 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
#ifndef OPENSSL_NO_SRP
while (SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during read\n");
- SRP_user_pwd_free(srp_callback_parm.user);
- srp_callback_parm.user =
- SRP_VBASE_get1_by_user(srp_callback_parm.vb,
- srp_callback_parm.login);
- if (srp_callback_parm.user)
- BIO_printf(bio_s_out, "LOOKUP done %s\n",
- srp_callback_parm.user->info);
- else
- BIO_printf(bio_s_out, "LOOKUP not successful\n");
+
+ lookup_srp_user(&srp_callback_parm, bio_s_out);
+
i = SSL_read(con, (char *)buf, bufsize);
}
#endif
@@ -2757,7 +2810,7 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
err:
if (con != NULL) {
BIO_printf(bio_s_out, "shutting down SSL\n");
- SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+ do_ssl_shutdown(con);
SSL_free(con);
}
BIO_printf(bio_s_out, "CONNECTION CLOSED\n");
@@ -2852,15 +2905,9 @@ static int init_ssl_connection(SSL *con)
&& SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP during accept %s\n",
srp_callback_parm.login);
- SRP_user_pwd_free(srp_callback_parm.user);
- srp_callback_parm.user =
- SRP_VBASE_get1_by_user(srp_callback_parm.vb,
- srp_callback_parm.login);
- if (srp_callback_parm.user)
- BIO_printf(bio_s_out, "LOOKUP done %s\n",
- srp_callback_parm.user->info);
- else
- BIO_printf(bio_s_out, "LOOKUP not successful\n");
+
+ lookup_srp_user(&srp_callback_parm, bio_s_out);
+
i = SSL_accept(con);
if (i <= 0)
retry = is_retryable(con, i);
@@ -2909,12 +2956,11 @@ static void print_connection_info(SSL *con)
PEM_write_bio_SSL_SESSION(bio_s_out, SSL_get_session(con));
- peer = SSL_get_peer_certificate(con);
+ peer = SSL_get0_peer_certificate(con);
if (peer != NULL) {
BIO_printf(bio_s_out, "Client certificate\n");
PEM_write_bio_X509(bio_s_out, peer);
dump_cert_text(bio_s_out, peer);
- X509_free(peer);
peer = NULL;
}
@@ -2959,11 +3005,11 @@ static void print_connection_info(SSL *con)
BIO_printf(bio_s_out, " Label: '%s'\n", keymatexportlabel);
BIO_printf(bio_s_out, " Length: %i bytes\n", keymatexportlen);
exportedkeymat = app_malloc(keymatexportlen, "export key");
- if (!SSL_export_keying_material(con, exportedkeymat,
+ if (SSL_export_keying_material(con, exportedkeymat,
keymatexportlen,
keymatexportlabel,
strlen(keymatexportlabel),
- NULL, 0, 0)) {
+ NULL, 0, 0) <= 0) {
BIO_printf(bio_s_out, " Error\n");
} else {
BIO_printf(bio_s_out, " Keying material: ");
@@ -2973,25 +3019,16 @@ static void print_connection_info(SSL *con)
}
OPENSSL_free(exportedkeymat);
}
+#ifndef OPENSSL_NO_KTLS
+ if (BIO_get_ktls_send(SSL_get_wbio(con)))
+ BIO_printf(bio_err, "Using Kernel TLS for sending\n");
+ if (BIO_get_ktls_recv(SSL_get_rbio(con)))
+ BIO_printf(bio_err, "Using Kernel TLS for receiving\n");
+#endif
(void)BIO_flush(bio_s_out);
}
-#ifndef OPENSSL_NO_DH
-static DH *load_dh_param(const char *dhfile)
-{
- DH *ret = NULL;
- BIO *bio;
-
- if ((bio = BIO_new_file(dhfile, "r")) == NULL)
- goto err;
- ret = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
- err:
- BIO_free(bio);
- return ret;
-}
-#endif
-
static int www_body(int s, int stype, int prot, unsigned char *context)
{
char *buf = NULL;
@@ -3004,12 +3041,21 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
int total_bytes = 0;
#endif
int width;
+#ifndef OPENSSL_NO_KTLS
+ int use_sendfile_for_req = use_sendfile;
+#endif
fd_set readfds;
+ const char *opmode;
+#ifdef CHARSET_EBCDIC
+ BIO *filter;
+#endif
/* Set width for a select call if needed */
width = s + 1;
- buf = app_malloc(bufsize, "server www buffer");
+ /* as we use BIO_gets(), and it always null terminates data, we need
+ * to allocate 1 byte longer buffer to fit the full 2^14 byte record */
+ buf = app_malloc(bufsize + 1, "server www buffer");
io = BIO_new(BIO_f_buffer());
ssl_bio = BIO_new(BIO_f_ssl());
if ((io == NULL) || (ssl_bio == NULL))
@@ -3023,7 +3069,7 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
}
/* lets make the output buffer a reasonable size */
- if (!BIO_set_write_buffer_size(io, bufsize))
+ if (BIO_set_write_buffer_size(io, bufsize) <= 0)
goto err;
if ((con = SSL_new(ctx)) == NULL)
@@ -3042,10 +3088,21 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
}
sbio = BIO_new_socket(s, BIO_NOCLOSE);
+ if (sbio == NULL) {
+ SSL_free(con);
+ goto err;
+ }
+
if (s_nbio_test) {
BIO *test;
test = BIO_new(BIO_f_nbio_test());
+ if (test == NULL) {
+ SSL_free(con);
+ BIO_free(sbio);
+ goto err;
+ }
+
sbio = BIO_push(test, sbio);
}
SSL_set_bio(con, sbio, sbio);
@@ -3054,12 +3111,17 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
/* No need to free |con| after this. Done by BIO_free(ssl_bio) */
BIO_set_ssl(ssl_bio, con, BIO_CLOSE);
BIO_push(io, ssl_bio);
+ ssl_bio = NULL;
#ifdef CHARSET_EBCDIC
- io = BIO_push(BIO_new(BIO_f_ebcdic_filter()), io);
+ filter = BIO_new(BIO_f_ebcdic_filter());
+ if (filter == NULL)
+ goto err;
+
+ io = BIO_push(filter, io);
#endif
if (s_debug) {
- BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
+ BIO_set_callback_ex(SSL_get_rbio(con), bio_dump_callback);
BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
}
if (s_msg) {
@@ -3073,7 +3135,7 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
}
for (;;) {
- i = BIO_gets(io, buf, bufsize - 1);
+ i = BIO_gets(io, buf, bufsize + 1);
if (i < 0) { /* error */
if (!BIO_should_retry(io) && !SSL_waiting_for_async(con)) {
if (!s_quiet)
@@ -3085,21 +3147,13 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
if (BIO_should_io_special(io)
&& BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during read\n");
- SRP_user_pwd_free(srp_callback_parm.user);
- srp_callback_parm.user =
- SRP_VBASE_get1_by_user(srp_callback_parm.vb,
- srp_callback_parm.login);
- if (srp_callback_parm.user)
- BIO_printf(bio_s_out, "LOOKUP done %s\n",
- srp_callback_parm.user->info);
- else
- BIO_printf(bio_s_out, "LOOKUP not successful\n");
+
+ lookup_srp_user(&srp_callback_parm, bio_s_out);
+
continue;
}
#endif
-#if !defined(OPENSSL_SYS_MSDOS)
- sleep(1);
-#endif
+ ossl_sleep(1000);
continue;
}
} else if (i == 0) { /* end of input */
@@ -3146,7 +3200,7 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
* we're expecting to come from the client. If they haven't
* sent one there's not much we can do.
*/
- BIO_gets(io, buf, bufsize - 1);
+ BIO_gets(io, buf, bufsize + 1);
}
BIO_puts(io,
@@ -3228,12 +3282,11 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
BIO_printf(io, "---\n");
print_stats(io, SSL_get_SSL_CTX(con));
BIO_printf(io, "---\n");
- peer = SSL_get_peer_certificate(con);
+ peer = SSL_get0_peer_certificate(con);
if (peer != NULL) {
BIO_printf(io, "Client certificate\n");
X509_print(io, peer);
PEM_write_bio_X509(io, peer);
- X509_free(peer);
peer = NULL;
} else {
BIO_puts(io, "no client certificate available\n");
@@ -3304,9 +3357,10 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
break;
}
- if ((file = BIO_new_file(p, "r")) == NULL) {
+ opmode = (http_server_binmode == 1) ? "rb" : "r";
+ if ((file = BIO_new_file(p, opmode)) == NULL) {
BIO_puts(io, text);
- BIO_printf(io, "Error opening '%s'\r\n", p);
+ BIO_printf(io, "Error opening '%s' mode='%s'\r\n", p, opmode);
ERR_print_errors(io);
break;
}
@@ -3326,38 +3380,83 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
"HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n");
}
/* send the file */
- for (;;) {
- i = BIO_read(file, buf, bufsize);
- if (i <= 0)
- break;
+#ifndef OPENSSL_NO_KTLS
+ if (use_sendfile_for_req && !BIO_get_ktls_send(SSL_get_wbio(con))) {
+ BIO_printf(bio_err, "Warning: sendfile requested but KTLS is not available\n");
+ use_sendfile_for_req = 0;
+ }
+ if (use_sendfile_for_req) {
+ FILE *fp = NULL;
+ int fd;
+ struct stat st;
+ off_t offset = 0;
+ size_t filesize;
+
+ BIO_get_fp(file, &fp);
+ fd = fileno(fp);
+ if (fstat(fd, &st) < 0) {
+ BIO_printf(io, "Error fstat '%s'\r\n", p);
+ ERR_print_errors(io);
+ goto write_error;
+ }
-#ifdef RENEG
- total_bytes += i;
- BIO_printf(bio_err, "%d\n", i);
- if (total_bytes > 3 * 1024) {
- total_bytes = 0;
- BIO_printf(bio_err, "RENEGOTIATE\n");
- SSL_renegotiate(con);
+ filesize = st.st_size;
+ if (((int)BIO_flush(io)) < 0)
+ goto write_error;
+
+ for (;;) {
+ i = SSL_sendfile(con, fd, offset, filesize, 0);
+ if (i < 0) {
+ BIO_printf(io, "Error SSL_sendfile '%s'\r\n", p);
+ ERR_print_errors(io);
+ break;
+ } else {
+ offset += i;
+ filesize -= i;
+ }
+
+ if (filesize <= 0) {
+ if (!s_quiet)
+ BIO_printf(bio_err, "KTLS SENDFILE '%s' OK\n", p);
+
+ break;
+ }
}
+ } else
#endif
+ {
+ for (;;) {
+ i = BIO_read(file, buf, bufsize);
+ if (i <= 0)
+ break;
- for (j = 0; j < i;) {
#ifdef RENEG
- static count = 0;
- if (++count == 13) {
+ total_bytes += i;
+ BIO_printf(bio_err, "%d\n", i);
+ if (total_bytes > 3 * 1024) {
+ total_bytes = 0;
+ BIO_printf(bio_err, "RENEGOTIATE\n");
SSL_renegotiate(con);
}
#endif
- k = BIO_write(io, &(buf[j]), i - j);
- if (k <= 0) {
- if (!BIO_should_retry(io)
- && !SSL_waiting_for_async(con))
- goto write_error;
- else {
- BIO_printf(bio_s_out, "rwrite W BLOCK\n");
+
+ for (j = 0; j < i;) {
+#ifdef RENEG
+ static count = 0;
+ if (++count == 13)
+ SSL_renegotiate(con);
+#endif
+ k = BIO_write(io, &(buf[j]), i - j);
+ if (k <= 0) {
+ if (!BIO_should_retry(io)
+ && !SSL_waiting_for_async(con)) {
+ goto write_error;
+ } else {
+ BIO_printf(bio_s_out, "rwrite W BLOCK\n");
+ }
+ } else {
+ j += k;
}
- } else {
- j += k;
}
}
}
@@ -3377,10 +3476,11 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
}
end:
/* make sure we re-use sessions */
- SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+ do_ssl_shutdown(con);
err:
OPENSSL_free(buf);
+ BIO_free(ssl_bio);
BIO_free_all(io);
return ret;
}
@@ -3392,15 +3492,20 @@ static int rev_body(int s, int stype, int prot, unsigned char *context)
int ret = 1;
SSL *con;
BIO *io, *ssl_bio, *sbio;
+#ifdef CHARSET_EBCDIC
+ BIO *filter;
+#endif
- buf = app_malloc(bufsize, "server rev buffer");
+ /* as we use BIO_gets(), and it always null terminates data, we need
+ * to allocate 1 byte longer buffer to fit the full 2^14 byte record */
+ buf = app_malloc(bufsize + 1, "server rev buffer");
io = BIO_new(BIO_f_buffer());
ssl_bio = BIO_new(BIO_f_ssl());
if ((io == NULL) || (ssl_bio == NULL))
goto err;
/* lets make the output buffer a reasonable size */
- if (!BIO_set_write_buffer_size(io, bufsize))
+ if (BIO_set_write_buffer_size(io, bufsize) <= 0)
goto err;
if ((con = SSL_new(ctx)) == NULL)
@@ -3419,18 +3524,29 @@ static int rev_body(int s, int stype, int prot, unsigned char *context)
}
sbio = BIO_new_socket(s, BIO_NOCLOSE);
+ if (sbio == NULL) {
+ SSL_free(con);
+ ERR_print_errors(bio_err);
+ goto err;
+ }
+
SSL_set_bio(con, sbio, sbio);
SSL_set_accept_state(con);
/* No need to free |con| after this. Done by BIO_free(ssl_bio) */
BIO_set_ssl(ssl_bio, con, BIO_CLOSE);
BIO_push(io, ssl_bio);
+ ssl_bio = NULL;
#ifdef CHARSET_EBCDIC
- io = BIO_push(BIO_new(BIO_f_ebcdic_filter()), io);
+ filter = BIO_new(BIO_f_ebcdic_filter());
+ if (filter == NULL)
+ goto err;
+
+ io = BIO_push(filter, io);
#endif
if (s_debug) {
- BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
+ BIO_set_callback_ex(SSL_get_rbio(con), bio_dump_callback);
BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
}
if (s_msg) {
@@ -3456,15 +3572,9 @@ static int rev_body(int s, int stype, int prot, unsigned char *context)
if (BIO_should_io_special(io)
&& BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during accept\n");
- SRP_user_pwd_free(srp_callback_parm.user);
- srp_callback_parm.user =
- SRP_VBASE_get1_by_user(srp_callback_parm.vb,
- srp_callback_parm.login);
- if (srp_callback_parm.user)
- BIO_printf(bio_s_out, "LOOKUP done %s\n",
- srp_callback_parm.user->info);
- else
- BIO_printf(bio_s_out, "LOOKUP not successful\n");
+
+ lookup_srp_user(&srp_callback_parm, bio_s_out);
+
continue;
}
#endif
@@ -3473,7 +3583,7 @@ static int rev_body(int s, int stype, int prot, unsigned char *context)
print_ssl_summary(con);
for (;;) {
- i = BIO_gets(io, buf, bufsize - 1);
+ i = BIO_gets(io, buf, bufsize + 1);
if (i < 0) { /* error */
if (!BIO_should_retry(io)) {
if (!s_quiet)
@@ -3485,21 +3595,13 @@ static int rev_body(int s, int stype, int prot, unsigned char *context)
if (BIO_should_io_special(io)
&& BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during read\n");
- SRP_user_pwd_free(srp_callback_parm.user);
- srp_callback_parm.user =
- SRP_VBASE_get1_by_user(srp_callback_parm.vb,
- srp_callback_parm.login);
- if (srp_callback_parm.user)
- BIO_printf(bio_s_out, "LOOKUP done %s\n",
- srp_callback_parm.user->info);
- else
- BIO_printf(bio_s_out, "LOOKUP not successful\n");
+
+ lookup_srp_user(&srp_callback_parm, bio_s_out);
+
continue;
}
#endif
-#if !defined(OPENSSL_SYS_MSDOS)
- sleep(1);
-#endif
+ ossl_sleep(1000);
continue;
}
} else if (i == 0) { /* end of input */
@@ -3531,11 +3633,12 @@ static int rev_body(int s, int stype, int prot, unsigned char *context)
}
end:
/* make sure we re-use sessions */
- SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+ do_ssl_shutdown(con);
err:
OPENSSL_free(buf);
+ BIO_free(ssl_bio);
BIO_free_all(io);
return ret;
}
@@ -3545,6 +3648,8 @@ static int generate_session_id(SSL *ssl, unsigned char *id,
unsigned int *id_len)
{
unsigned int count = 0;
+ unsigned int session_id_prefix_len = strlen(session_id_prefix);
+
do {
if (RAND_bytes(id, *id_len) <= 0)
return 0;
@@ -3556,8 +3661,8 @@ static int generate_session_id(SSL *ssl, unsigned char *id,
* conflicts.
*/
memcpy(id, session_id_prefix,
- (strlen(session_id_prefix) < *id_len) ?
- strlen(session_id_prefix) : *id_len);
+ (session_id_prefix_len < *id_len) ?
+ session_id_prefix_len : *id_len);
}
while (SSL_has_matching_session_id(ssl, id, *id_len) &&
(++count < MAX_SESSION_ID_ATTEMPTS));
@@ -3568,7 +3673,7 @@ static int generate_session_id(SSL *ssl, unsigned char *id,
/*
* By default s_server uses an in-memory cache which caches SSL_SESSION
- * structures without any serialisation. This hides some bugs which only
+ * structures without any serialization. This hides some bugs which only
* become apparent in deployed servers. By implementing a basic external
* session cache some issues can be debugged using s_server.
*/
diff --git a/apps/s_socket.c b/apps/s_socket.c
deleted file mode 100644
index 96f16d2931cd..000000000000
--- a/apps/s_socket.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/* socket-related functions used by s_client and s_server */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <signal.h>
-#include <openssl/opensslconf.h>
-
-/*
- * With IPv6, it looks like Digital has mixed up the proper order of
- * recursive header file inclusion, resulting in the compiler complaining
- * that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is
- * needed to have fileno() declared correctly... So let's define u_int
- */
-#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT)
-# define __U_INT
-typedef unsigned int u_int;
-#endif
-
-#ifndef OPENSSL_NO_SOCK
-
-# include "apps.h"
-# include "s_apps.h"
-# include "internal/sockets.h"
-
-# include <openssl/bio.h>
-# include <openssl/err.h>
-
-/* Keep track of our peer's address for the cookie callback */
-BIO_ADDR *ourpeer = NULL;
-
-/*
- * init_client - helper routine to set up socket communication
- * @sock: pointer to storage of resulting socket.
- * @host: the host name or path (for AF_UNIX) to connect to.
- * @port: the port to connect to (ignored for AF_UNIX).
- * @bindhost: source host or path (for AF_UNIX).
- * @bindport: source port (ignored for AF_UNIX).
- * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or
- * AF_UNSPEC
- * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM
- * @protocol: socket protocol, e.g. IPPROTO_TCP or IPPROTO_UDP (or 0 for any)
- *
- * This will create a socket and use it to connect to a host:port, or if
- * family == AF_UNIX, to the path found in host.
- *
- * If the host has more than one address, it will try them one by one until
- * a successful connection is established. The resulting socket will be
- * found in *sock on success, it will be given INVALID_SOCKET otherwise.
- *
- * Returns 1 on success, 0 on failure.
- */
-int init_client(int *sock, const char *host, const char *port,
- const char *bindhost, const char *bindport,
- int family, int type, int protocol)
-{
- BIO_ADDRINFO *res = NULL;
- BIO_ADDRINFO *bindaddr = NULL;
- const BIO_ADDRINFO *ai = NULL;
- const BIO_ADDRINFO *bi = NULL;
- int found = 0;
- int ret;
-
- if (BIO_sock_init() != 1)
- return 0;
-
- ret = BIO_lookup_ex(host, port, BIO_LOOKUP_CLIENT, family, type, protocol,
- &res);
- if (ret == 0) {
- ERR_print_errors(bio_err);
- return 0;
- }
-
- if (bindhost != NULL || bindport != NULL) {
- ret = BIO_lookup_ex(bindhost, bindport, BIO_LOOKUP_CLIENT,
- family, type, protocol, &bindaddr);
- if (ret == 0) {
- ERR_print_errors (bio_err);
- goto out;
- }
- }
-
- ret = 0;
- for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
- /* Admittedly, these checks are quite paranoid, we should not get
- * anything in the BIO_ADDRINFO chain that we haven't
- * asked for. */
- OPENSSL_assert((family == AF_UNSPEC
- || family == BIO_ADDRINFO_family(ai))
- && (type == 0 || type == BIO_ADDRINFO_socktype(ai))
- && (protocol == 0
- || protocol == BIO_ADDRINFO_protocol(ai)));
-
- if (bindaddr != NULL) {
- for (bi = bindaddr; bi != NULL; bi = BIO_ADDRINFO_next(bi)) {
- if (BIO_ADDRINFO_family(bi) == BIO_ADDRINFO_family(ai))
- break;
- }
- if (bi == NULL)
- continue;
- ++found;
- }
-
- *sock = BIO_socket(BIO_ADDRINFO_family(ai), BIO_ADDRINFO_socktype(ai),
- BIO_ADDRINFO_protocol(ai), 0);
- if (*sock == INVALID_SOCKET) {
- /* Maybe the kernel doesn't support the socket family, even if
- * BIO_lookup() added it in the returned result...
- */
- continue;
- }
-
- if (bi != NULL) {
- if (!BIO_bind(*sock, BIO_ADDRINFO_address(bi),
- BIO_SOCK_REUSEADDR)) {
- BIO_closesocket(*sock);
- *sock = INVALID_SOCKET;
- break;
- }
- }
-
-#ifndef OPENSSL_NO_SCTP
- if (protocol == IPPROTO_SCTP) {
- /*
- * For SCTP we have to set various options on the socket prior to
- * connecting. This is done automatically by BIO_new_dgram_sctp().
- * We don't actually need the created BIO though so we free it again
- * immediately.
- */
- BIO *tmpbio = BIO_new_dgram_sctp(*sock, BIO_NOCLOSE);
-
- if (tmpbio == NULL) {
- ERR_print_errors(bio_err);
- return 0;
- }
- BIO_free(tmpbio);
- }
-#endif
-
- if (!BIO_connect(*sock, BIO_ADDRINFO_address(ai),
- BIO_ADDRINFO_protocol(ai) == IPPROTO_TCP ? BIO_SOCK_NODELAY : 0)) {
- BIO_closesocket(*sock);
- *sock = INVALID_SOCKET;
- continue;
- }
-
- /* Success, don't try any more addresses */
- break;
- }
-
- if (*sock == INVALID_SOCKET) {
- if (bindaddr != NULL && !found) {
- BIO_printf(bio_err, "Can't bind %saddress for %s%s%s\n",
- BIO_ADDRINFO_family(res) == AF_INET6 ? "IPv6 " :
- BIO_ADDRINFO_family(res) == AF_INET ? "IPv4 " :
- BIO_ADDRINFO_family(res) == AF_UNIX ? "unix " : "",
- bindhost != NULL ? bindhost : "",
- bindport != NULL ? ":" : "",
- bindport != NULL ? bindport : "");
- ERR_clear_error();
- ret = 0;
- }
- ERR_print_errors(bio_err);
- } else {
- /* Remove any stale errors from previous connection attempts */
- ERR_clear_error();
- ret = 1;
- }
-out:
- if (bindaddr != NULL) {
- BIO_ADDRINFO_free (bindaddr);
- }
- BIO_ADDRINFO_free(res);
- return ret;
-}
-
-/*
- * do_server - helper routine to perform a server operation
- * @accept_sock: pointer to storage of resulting socket.
- * @host: the host name or path (for AF_UNIX) to connect to.
- * @port: the port to connect to (ignored for AF_UNIX).
- * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or
- * AF_UNSPEC
- * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM
- * @cb: pointer to a function that receives the accepted socket and
- * should perform the communication with the connecting client.
- * @context: pointer to memory that's passed verbatim to the cb function.
- * @naccept: number of times an incoming connect should be accepted. If -1,
- * unlimited number.
- *
- * This will create a socket and use it to listen to a host:port, or if
- * family == AF_UNIX, to the path found in host, then start accepting
- * incoming connections and run cb on the resulting socket.
- *
- * 0 on failure, something other on success.
- */
-int do_server(int *accept_sock, const char *host, const char *port,
- int family, int type, int protocol, do_server_cb cb,
- unsigned char *context, int naccept, BIO *bio_s_out)
-{
- int asock = 0;
- int sock;
- int i;
- BIO_ADDRINFO *res = NULL;
- const BIO_ADDRINFO *next;
- int sock_family, sock_type, sock_protocol, sock_port;
- const BIO_ADDR *sock_address;
- int sock_family_fallback = AF_UNSPEC;
- const BIO_ADDR *sock_address_fallback = NULL;
- int sock_options = BIO_SOCK_REUSEADDR;
- int ret = 0;
-
- if (BIO_sock_init() != 1)
- return 0;
-
- if (!BIO_lookup_ex(host, port, BIO_LOOKUP_SERVER, family, type, protocol,
- &res)) {
- ERR_print_errors(bio_err);
- return 0;
- }
-
- /* Admittedly, these checks are quite paranoid, we should not get
- * anything in the BIO_ADDRINFO chain that we haven't asked for */
- OPENSSL_assert((family == AF_UNSPEC || family == BIO_ADDRINFO_family(res))
- && (type == 0 || type == BIO_ADDRINFO_socktype(res))
- && (protocol == 0 || protocol == BIO_ADDRINFO_protocol(res)));
-
- sock_family = BIO_ADDRINFO_family(res);
- sock_type = BIO_ADDRINFO_socktype(res);
- sock_protocol = BIO_ADDRINFO_protocol(res);
- sock_address = BIO_ADDRINFO_address(res);
- next = BIO_ADDRINFO_next(res);
- if (sock_family == AF_INET6)
- sock_options |= BIO_SOCK_V6_ONLY;
- if (next != NULL
- && BIO_ADDRINFO_socktype(next) == sock_type
- && BIO_ADDRINFO_protocol(next) == sock_protocol) {
- if (sock_family == AF_INET
- && BIO_ADDRINFO_family(next) == AF_INET6) {
- /* In case AF_INET6 is returned but not supported by the
- * kernel, retry with the first detected address family */
- sock_family_fallback = sock_family;
- sock_address_fallback = sock_address;
- sock_family = AF_INET6;
- sock_address = BIO_ADDRINFO_address(next);
- } else if (sock_family == AF_INET6
- && BIO_ADDRINFO_family(next) == AF_INET) {
- sock_options &= ~BIO_SOCK_V6_ONLY;
- }
- }
-
- asock = BIO_socket(sock_family, sock_type, sock_protocol, 0);
- if (asock == INVALID_SOCKET && sock_family_fallback != AF_UNSPEC) {
- asock = BIO_socket(sock_family_fallback, sock_type, sock_protocol, 0);
- sock_address = sock_address_fallback;
- }
- if (asock == INVALID_SOCKET
- || !BIO_listen(asock, sock_address, sock_options)) {
- BIO_ADDRINFO_free(res);
- ERR_print_errors(bio_err);
- if (asock != INVALID_SOCKET)
- BIO_closesocket(asock);
- goto end;
- }
-
-#ifndef OPENSSL_NO_SCTP
- if (protocol == IPPROTO_SCTP) {
- /*
- * For SCTP we have to set various options on the socket prior to
- * accepting. This is done automatically by BIO_new_dgram_sctp().
- * We don't actually need the created BIO though so we free it again
- * immediately.
- */
- BIO *tmpbio = BIO_new_dgram_sctp(asock, BIO_NOCLOSE);
-
- if (tmpbio == NULL) {
- BIO_closesocket(asock);
- ERR_print_errors(bio_err);
- goto end;
- }
- BIO_free(tmpbio);
- }
-#endif
-
- sock_port = BIO_ADDR_rawport(sock_address);
-
- BIO_ADDRINFO_free(res);
- res = NULL;
-
- if (sock_port == 0) {
- /* dynamically allocated port, report which one */
- union BIO_sock_info_u info;
- char *hostname = NULL;
- char *service = NULL;
- int success = 0;
-
- if ((info.addr = BIO_ADDR_new()) != NULL
- && BIO_sock_info(asock, BIO_SOCK_INFO_ADDRESS, &info)
- && (hostname = BIO_ADDR_hostname_string(info.addr, 1)) != NULL
- && (service = BIO_ADDR_service_string(info.addr, 1)) != NULL
- && BIO_printf(bio_s_out,
- strchr(hostname, ':') == NULL
- ? /* IPv4 */ "ACCEPT %s:%s\n"
- : /* IPv6 */ "ACCEPT [%s]:%s\n",
- hostname, service) > 0)
- success = 1;
-
- (void)BIO_flush(bio_s_out);
- OPENSSL_free(hostname);
- OPENSSL_free(service);
- BIO_ADDR_free(info.addr);
- if (!success) {
- BIO_closesocket(asock);
- ERR_print_errors(bio_err);
- goto end;
- }
- } else {
- (void)BIO_printf(bio_s_out, "ACCEPT\n");
- (void)BIO_flush(bio_s_out);
- }
-
- if (accept_sock != NULL)
- *accept_sock = asock;
- for (;;) {
- char sink[64];
- struct timeval timeout;
- fd_set readfds;
-
- if (type == SOCK_STREAM) {
- BIO_ADDR_free(ourpeer);
- ourpeer = BIO_ADDR_new();
- if (ourpeer == NULL) {
- BIO_closesocket(asock);
- ERR_print_errors(bio_err);
- goto end;
- }
- do {
- sock = BIO_accept_ex(asock, ourpeer, 0);
- } while (sock < 0 && BIO_sock_should_retry(sock));
- if (sock < 0) {
- ERR_print_errors(bio_err);
- BIO_closesocket(asock);
- break;
- }
- BIO_set_tcp_ndelay(sock, 1);
- i = (*cb)(sock, type, protocol, context);
-
- /*
- * If we ended with an alert being sent, but still with data in the
- * network buffer to be read, then calling BIO_closesocket() will
- * result in a TCP-RST being sent. On some platforms (notably
- * Windows) then this will result in the peer immediately abandoning
- * the connection including any buffered alert data before it has
- * had a chance to be read. Shutting down the sending side first,
- * and then closing the socket sends TCP-FIN first followed by
- * TCP-RST. This seems to allow the peer to read the alert data.
- */
- shutdown(sock, 1); /* SHUT_WR */
- /*
- * We just said we have nothing else to say, but it doesn't mean
- * that the other side has nothing. It's even recommended to
- * consume incoming data. [In testing context this ensures that
- * alerts are passed on...]
- */
- timeout.tv_sec = 0;
- timeout.tv_usec = 500000; /* some extreme round-trip */
- do {
- FD_ZERO(&readfds);
- openssl_fdset(sock, &readfds);
- } while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0
- && readsocket(sock, sink, sizeof(sink)) > 0);
-
- BIO_closesocket(sock);
- } else {
- i = (*cb)(asock, type, protocol, context);
- }
-
- if (naccept != -1)
- naccept--;
- if (i < 0 || naccept == 0) {
- BIO_closesocket(asock);
- ret = i;
- break;
- }
- }
- end:
-# ifdef AF_UNIX
- if (family == AF_UNIX)
- unlink(host);
-# endif
- BIO_ADDR_free(ourpeer);
- ourpeer = NULL;
- return ret;
-}
-
-#endif /* OPENSSL_NO_SOCK */
diff --git a/apps/s_time.c b/apps/s_time.c
index 1235e545c20a..1a58e19de53f 100644
--- a/apps/s_time.c
+++ b/apps/s_time.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -22,9 +22,9 @@
#include <openssl/pem.h>
#include "s_apps.h"
#include <openssl/err.h>
-#include <internal/sockets.h>
+#include "internal/sockets.h"
#if !defined(OPENSSL_SYS_MSDOS)
-# include OPENSSL_UNISTD
+# include <unistd.h>
#endif
#define SSL_CONNECT_NAME "localhost:4433"
@@ -43,40 +43,64 @@ static const char fmt_http_get_cmd[] = "GET %s HTTP/1.0\r\n\r\n";
static const size_t fmt_http_get_cmd_size = sizeof(fmt_http_get_cmd) - 2;
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_CONNECT, OPT_CIPHER, OPT_CIPHERSUITES, OPT_CERT, OPT_NAMEOPT, OPT_KEY,
- OPT_CAPATH, OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NEW, OPT_REUSE,
- OPT_BUGS, OPT_VERIFY, OPT_TIME, OPT_SSL3,
- OPT_WWW
+ OPT_CAPATH, OPT_CAFILE, OPT_CASTORE,
+ OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE,
+ OPT_NEW, OPT_REUSE, OPT_BUGS, OPT_VERIFY, OPT_TIME, OPT_SSL3,
+ OPT_WWW, OPT_TLS1, OPT_TLS1_1, OPT_TLS1_2, OPT_TLS1_3,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS s_time_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+
+ OPT_SECTION("Connection"),
{"connect", OPT_CONNECT, 's',
"Where to connect as post:port (default is " SSL_CONNECT_NAME ")"},
+ {"new", OPT_NEW, '-', "Just time new connections"},
+ {"reuse", OPT_REUSE, '-', "Just time connection reuse"},
+ {"bugs", OPT_BUGS, '-', "Turn on SSL bug compatibility"},
{"cipher", OPT_CIPHER, 's', "TLSv1.2 and below cipher list to be used"},
{"ciphersuites", OPT_CIPHERSUITES, 's',
"Specify TLSv1.3 ciphersuites to be used"},
+#ifndef OPENSSL_NO_SSL3
+ {"ssl3", OPT_SSL3, '-', "Just use SSLv3"},
+#endif
+#ifndef OPENSSL_NO_TLS1
+ {"tls1", OPT_TLS1, '-', "Just use TLSv1.0"},
+#endif
+#ifndef OPENSSL_NO_TLS1_1
+ {"tls1_1", OPT_TLS1_1, '-', "Just use TLSv1.1"},
+#endif
+#ifndef OPENSSL_NO_TLS1_2
+ {"tls1_2", OPT_TLS1_2, '-', "Just use TLSv1.2"},
+#endif
+#ifndef OPENSSL_NO_TLS1_3
+ {"tls1_3", OPT_TLS1_3, '-', "Just use TLSv1.3"},
+#endif
+ {"verify", OPT_VERIFY, 'p',
+ "Turn on peer certificate verification, set depth"},
+ {"time", OPT_TIME, 'p', "Seconds to collect data, default " SECONDSSTR},
+ {"www", OPT_WWW, 's', "Fetch specified page from the site"},
+
+ OPT_SECTION("Certificate"),
+ {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
{"cert", OPT_CERT, '<', "Cert file to use, PEM format assumed"},
- {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
{"key", OPT_KEY, '<', "File with key, PEM; default is -cert file"},
- {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
{"cafile", OPT_CAFILE, '<', "PEM format file of CA's"},
{"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"},
+ {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
+ {"CAstore", OPT_CASTORE, ':', "URI to store of CA's"},
{"no-CAfile", OPT_NOCAFILE, '-',
"Do not load the default certificates file"},
{"no-CApath", OPT_NOCAPATH, '-',
"Do not load certificates from the default certificates directory"},
- {"new", OPT_NEW, '-', "Just time new connections"},
- {"reuse", OPT_REUSE, '-', "Just time connection reuse"},
- {"bugs", OPT_BUGS, '-', "Turn on SSL bug compatibility"},
- {"verify", OPT_VERIFY, 'p',
- "Turn on peer certificate verification, set depth"},
- {"time", OPT_TIME, 'p', "Seconds to collect data, default " SECONDSSTR},
- {"www", OPT_WWW, 's', "Fetch specified page from the site"},
-#ifndef OPENSSL_NO_SSL3
- {"ssl3", OPT_SSL3, '-', "Just use SSLv3"},
-#endif
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load certificates from the default certificates store URI"},
+
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -94,15 +118,16 @@ int s_time_main(int argc, char **argv)
SSL *scon = NULL;
SSL_CTX *ctx = NULL;
const SSL_METHOD *meth = NULL;
- char *CApath = NULL, *CAfile = NULL, *cipher = NULL, *ciphersuites = NULL;
+ char *CApath = NULL, *CAfile = NULL, *CAstore = NULL;
+ char *cipher = NULL, *ciphersuites = NULL;
char *www_path = NULL;
char *host = SSL_CONNECT_NAME, *certfile = NULL, *keyfile = NULL, *prog;
double totalTime = 0.0;
- int noCApath = 0, noCAfile = 0;
+ int noCApath = 0, noCAfile = 0, noCAstore = 0;
int maxtime = SECONDS, nConn = 0, perform = 3, ret = 1, i, st_bugs = 0;
long bytes_read = 0, finishtime = 0;
OPTION_CHOICE o;
- int max_version = 0, ver, buf_len;
+ int min_version = 0, max_version = 0, ver, buf_len, fd;
size_t buf_size;
meth = TLS_client_method();
@@ -129,8 +154,7 @@ int s_time_main(int argc, char **argv)
perform = 1;
break;
case OPT_VERIFY:
- if (!opt_int(opt_arg(), &verify_args.depth))
- goto opthelp;
+ verify_args.depth = opt_int_arg();
BIO_printf(bio_err, "%s: verify depth is %d\n",
prog, verify_args.depth);
break;
@@ -156,6 +180,12 @@ int s_time_main(int argc, char **argv)
case OPT_NOCAFILE:
noCAfile = 1;
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
case OPT_CIPHER:
cipher = opt_arg();
break;
@@ -166,8 +196,7 @@ int s_time_main(int argc, char **argv)
st_bugs = 1;
break;
case OPT_TIME:
- if (!opt_int(opt_arg(), &maxtime))
- goto opthelp;
+ maxtime = opt_int_arg();
break;
case OPT_WWW:
www_path = opt_arg();
@@ -178,10 +207,33 @@ int s_time_main(int argc, char **argv)
}
break;
case OPT_SSL3:
+ min_version = SSL3_VERSION;
max_version = SSL3_VERSION;
break;
+ case OPT_TLS1:
+ min_version = TLS1_VERSION;
+ max_version = TLS1_VERSION;
+ break;
+ case OPT_TLS1_1:
+ min_version = TLS1_1_VERSION;
+ max_version = TLS1_1_VERSION;
+ break;
+ case OPT_TLS1_2:
+ min_version = TLS1_2_VERSION;
+ max_version = TLS1_2_VERSION;
+ break;
+ case OPT_TLS1_3:
+ min_version = TLS1_3_VERSION;
+ max_version = TLS1_3_VERSION;
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
@@ -192,8 +244,9 @@ int s_time_main(int argc, char **argv)
if ((ctx = SSL_CTX_new(meth)) == NULL)
goto end;
- SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_quiet_shutdown(ctx, 1);
+ if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
+ goto end;
if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
goto end;
@@ -206,7 +259,8 @@ int s_time_main(int argc, char **argv)
if (!set_cert_stuff(ctx, certfile, keyfile))
goto end;
- if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) {
+ if (!ctx_set_verify_locations(ctx, CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore)) {
ERR_print_errors(bio_err);
goto end;
}
@@ -289,7 +343,8 @@ int s_time_main(int argc, char **argv)
continue;
}
SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
- BIO_closesocket(SSL_get_fd(scon));
+ if ((fd = SSL_get_fd(scon)) >= 0)
+ BIO_closesocket(fd);
nConn = 0;
totalTime = 0.0;
@@ -316,7 +371,8 @@ int s_time_main(int argc, char **argv)
bytes_read += i;
}
SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
- BIO_closesocket(SSL_get_fd(scon));
+ if ((fd = SSL_get_fd(scon)) >= 0)
+ BIO_closesocket(fd);
nConn += 1;
if (SSL_session_reused(scon)) {
@@ -338,10 +394,13 @@ int s_time_main(int argc, char **argv)
printf
("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n",
nConn, totalTime, ((double)nConn / totalTime), bytes_read);
- printf
- ("%d connections in %ld real seconds, %ld bytes read per connection\n",
- nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn);
-
+ if (nConn > 0)
+ printf
+ ("%d connections in %ld real seconds, %ld bytes read per connection\n",
+ nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn);
+ else
+ printf("0 connections in %ld real seconds\n",
+ (long)time(NULL) - finishtime + maxtime);
ret = 0;
end:
@@ -362,12 +421,19 @@ static SSL *doConnection(SSL *scon, const char *host, SSL_CTX *ctx)
if ((conn = BIO_new(BIO_s_connect())) == NULL)
return NULL;
- BIO_set_conn_hostname(conn, host);
- BIO_set_conn_mode(conn, BIO_SOCK_NODELAY);
+ if (BIO_set_conn_hostname(conn, host) <= 0
+ || BIO_set_conn_mode(conn, BIO_SOCK_NODELAY) <= 0) {
+ BIO_free(conn);
+ return NULL;
+ }
- if (scon == NULL)
+ if (scon == NULL) {
serverCon = SSL_new(ctx);
- else {
+ if (serverCon == NULL) {
+ BIO_free(conn);
+ return NULL;
+ }
+ } else {
serverCon = scon;
SSL_set_connect_state(serverCon);
}
diff --git a/apps/sess_id.c b/apps/sess_id.c
index 8fd584f3b131..714c0f77877e 100644
--- a/apps/sess_id.c
+++ b/apps/sess_id.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -19,22 +19,27 @@
#include <openssl/ssl.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT,
OPT_TEXT, OPT_CERT, OPT_NOOUT, OPT_CONTEXT
} OPTION_CHOICE;
const OPTIONS sess_id_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"context", OPT_CONTEXT, 's', "Set the session ID context"},
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, 's', "Input file - default stdin"},
{"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file - default stdout"},
{"outform", OPT_OUTFORM, 'f',
"Output format - default PEM (PEM, DER or NSS)"},
- {"in", OPT_IN, 's', "Input file - default stdin"},
- {"out", OPT_OUT, '>', "Output file - default stdout"},
{"text", OPT_TEXT, '-', "Print ssl session id details"},
{"cert", OPT_CERT, '-', "Output certificate "},
{"noout", OPT_NOOUT, '-', "Don't output the encoded session info"},
- {"context", OPT_CONTEXT, 's', "Set the session ID context"},
{NULL}
};
@@ -91,6 +96,8 @@ int sess_id_main(int argc, char **argv)
break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
diff --git a/apps/smime.c b/apps/smime.c
index 6fd473775f45..a2ff0b5be75c 100644
--- a/apps/smime.c
+++ b/apps/smime.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -33,7 +33,7 @@ static int smime_cb(int ok, X509_STORE_CTX *ctx);
#define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_ENCRYPT, OPT_DECRYPT, OPT_SIGN, OPT_RESIGN, OPT_VERIFY,
OPT_PK7OUT, OPT_TEXT, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCHAIN,
OPT_NOCERTS, OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP,
@@ -41,76 +41,97 @@ typedef enum OPTION_choice {
OPT_CRLFEOL, OPT_ENGINE, OPT_PASSIN,
OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, OPT_MD,
OPT_CIPHER, OPT_INKEY, OPT_KEYFORM, OPT_CERTFILE, OPT_CAFILE,
- OPT_R_ENUM,
+ OPT_CAPATH, OPT_CASTORE, OPT_NOCAFILE, OPT_NOCAPATH, OPT_NOCASTORE,
+ OPT_R_ENUM, OPT_PROV_ENUM, OPT_CONFIG,
OPT_V_ENUM,
- OPT_CAPATH, OPT_NOCAFILE, OPT_NOCAPATH, OPT_IN, OPT_INFORM, OPT_OUT,
+ OPT_IN, OPT_INFORM, OPT_OUT,
OPT_OUTFORM, OPT_CONTENT
} OPTION_CHOICE;
const OPTIONS smime_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"},
- {OPT_HELP_STR, 1, '-',
- " cert.pem... recipient certs for encryption\n"},
- {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert...]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'c',
+ "Output format SMIME (default), PEM or DER"},
+ {"inkey", OPT_INKEY, 's',
+ "Input private key (if not signer or recipient)"},
+ {"keyform", OPT_KEYFORM, 'f', "Input private key format (ENGINE, other values ignored)"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {"stream", OPT_STREAM, '-', "Enable CMS streaming" },
+ {"indef", OPT_INDEF, '-', "Same as -stream" },
+ {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"},
+ OPT_CONFIG_OPTION,
+
+ OPT_SECTION("Action"),
{"encrypt", OPT_ENCRYPT, '-', "Encrypt message"},
{"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"},
{"sign", OPT_SIGN, '-', "Sign message"},
+ {"resign", OPT_RESIGN, '-', "Resign a signed message"},
{"verify", OPT_VERIFY, '-', "Verify signed message"},
+
+ OPT_SECTION("Signing/Encryption"),
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"},
+ {"", OPT_CIPHER, '-', "Any supported cipher"},
{"pk7out", OPT_PK7OUT, '-', "Output PKCS#7 structure"},
{"nointern", OPT_NOINTERN, '-',
"Don't search certificates in message for signer"},
- {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"},
- {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"},
- {"nocerts", OPT_NOCERTS, '-',
- "Don't include signers certificate when signing"},
{"nodetach", OPT_NODETACH, '-', "Use opaque signing"},
{"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"},
{"binary", OPT_BINARY, '-', "Don't translate message to text"},
- {"certfile", OPT_CERTFILE, '<', "Other certificates file"},
{"signer", OPT_SIGNER, 's', "Signer certificate file"},
- {"recip", OPT_RECIP, '<', "Recipient certificate file for decryption"},
- {"in", OPT_IN, '<', "Input file"},
- {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"},
- {"inkey", OPT_INKEY, 's',
- "Input private key (if not signer or recipient)"},
- {"keyform", OPT_KEYFORM, 'f', "Input private key format (PEM or ENGINE)"},
- {"out", OPT_OUT, '>', "Output file"},
- {"outform", OPT_OUTFORM, 'c',
- "Output format SMIME (default), PEM or DER"},
{"content", OPT_CONTENT, '<',
"Supply or override content for detached signature"},
+ {"nocerts", OPT_NOCERTS, '-',
+ "Don't include signers certificate when signing"},
+
+ OPT_SECTION("Verification/Decryption"),
+ {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"},
+ {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"},
+
+ {"certfile", OPT_CERTFILE, '<', "Other certificates file"},
+ {"recip", OPT_RECIP, '<', "Recipient certificate file for decryption"},
+
+ OPT_SECTION("Email"),
{"to", OPT_TO, 's', "To address"},
{"from", OPT_FROM, 's', "From address"},
{"subject", OPT_SUBJECT, 's', "Subject"},
{"text", OPT_TEXT, '-', "Include or delete text MIME headers"},
+ {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"},
+
+ OPT_SECTION("Certificate chain"),
{"CApath", OPT_CAPATH, '/', "Trusted certificates directory"},
{"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
+ {"CAstore", OPT_CASTORE, ':', "Trusted certificates store URI"},
{"no-CAfile", OPT_NOCAFILE, '-',
"Do not load the default certificates file"},
{"no-CApath", OPT_NOCAPATH, '-',
"Do not load certificates from the default certificates directory"},
- {"resign", OPT_RESIGN, '-', "Resign a signed message"},
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load certificates from the default certificates store"},
{"nochain", OPT_NOCHAIN, '-',
"set PKCS7_NOCHAIN so certificates contained in the message are not used as untrusted CAs" },
- {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"},
- {"stream", OPT_STREAM, '-', "Enable CMS streaming" },
- {"indef", OPT_INDEF, '-', "Same as -stream" },
- {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"},
{"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of CR only"},
+
OPT_R_OPTIONS,
- {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
- {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"},
- {"", OPT_CIPHER, '-', "Any supported cipher"},
OPT_V_OPTIONS,
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"cert", 0, 0, "Recipient certs, used when encrypting"},
{NULL}
};
int smime_main(int argc, char **argv)
{
+ CONF *conf = NULL;
BIO *in = NULL, *out = NULL, *indata = NULL;
EVP_PKEY *key = NULL;
PKCS7 *p7 = NULL;
@@ -119,20 +140,22 @@ int smime_main(int argc, char **argv)
X509 *cert = NULL, *recip = NULL, *signer = NULL;
X509_STORE *store = NULL;
X509_VERIFY_PARAM *vpm = NULL;
- const EVP_CIPHER *cipher = NULL;
- const EVP_MD *sign_md = NULL;
- const char *CAfile = NULL, *CApath = NULL, *prog = NULL;
+ EVP_CIPHER *cipher = NULL;
+ EVP_MD *sign_md = NULL;
+ const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL, *prog = NULL;
char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
char *infile = NULL, *outfile = NULL, *signerfile = NULL, *recipfile = NULL;
- char *passinarg = NULL, *passin = NULL, *to = NULL, *from = NULL, *subject = NULL;
+ char *passinarg = NULL, *passin = NULL, *to = NULL, *from = NULL;
+ char *subject = NULL, *digestname = NULL, *ciphername = NULL;
OPTION_CHOICE o;
- int noCApath = 0, noCAfile = 0;
+ int noCApath = 0, noCAfile = 0, noCAstore = 0;
int flags = PKCS7_DETACHED, operation = 0, ret = 0, indef = 0;
int informat = FORMAT_SMIME, outformat = FORMAT_SMIME, keyform =
- FORMAT_PEM;
+ FORMAT_UNDEF;
int vpmtouched = 0, rv = 0;
ENGINE *e = NULL;
const char *mime_eol = "\n";
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
return 1;
@@ -226,6 +249,15 @@ int smime_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
+ case OPT_CONFIG:
+ conf = app_load_config_modules(opt_arg());
+ if (conf == NULL)
+ goto end;
+ break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
@@ -262,12 +294,10 @@ int smime_main(int argc, char **argv)
recipfile = opt_arg();
break;
case OPT_MD:
- if (!opt_md(opt_arg(), &sign_md))
- goto opthelp;
+ digestname = opt_arg();
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &cipher))
- goto opthelp;
+ ciphername = opt_unknown();
break;
case OPT_INKEY:
/* If previous -inkey argument add signer to list */
@@ -302,12 +332,18 @@ int smime_main(int argc, char **argv)
case OPT_CAPATH:
CApath = opt_arg();
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
case OPT_NOCAPATH:
noCApath = 1;
break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
case OPT_CONTENT:
contfile = opt_arg();
break;
@@ -318,13 +354,31 @@ int smime_main(int argc, char **argv)
break;
}
}
+
+ /* Extra arguments are files with recipient keys. */
argc = opt_num_rest();
argv = opt_rest();
+ if (!app_RAND_load())
+ goto end;
+
+ if (digestname != NULL) {
+ if (!opt_md(digestname, &sign_md))
+ goto opthelp;
+ }
+ if (ciphername != NULL) {
+ if (!opt_cipher_any(ciphername, &cipher))
+ goto opthelp;
+ }
if (!(operation & SMIME_SIGNERS) && (skkeys != NULL || sksigners != NULL)) {
BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
goto opthelp;
}
+ if (!operation) {
+ BIO_puts(bio_err,
+ "No operation (-encrypt|-sign|...) specified\n");
+ goto opthelp;
+ }
if (operation & SMIME_SIGNERS) {
/* Check to see if any final signer needs to be appended */
@@ -360,8 +414,6 @@ int smime_main(int argc, char **argv)
BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
goto opthelp;
}
- } else if (!operation) {
- goto opthelp;
}
if (!app_passwd(passinarg, NULL, &passin, NULL)) {
@@ -387,7 +439,7 @@ int smime_main(int argc, char **argv)
if (operation == SMIME_ENCRYPT) {
if (cipher == NULL) {
#ifndef OPENSSL_NO_DES
- cipher = EVP_des_ede3_cbc();
+ cipher = (EVP_CIPHER *)EVP_des_ede3_cbc();
#else
BIO_printf(bio_err, "No cipher selected\n");
goto end;
@@ -397,7 +449,7 @@ int smime_main(int argc, char **argv)
if (encerts == NULL)
goto end;
while (*argv != NULL) {
- cert = load_cert(*argv, FORMAT_PEM,
+ cert = load_cert(*argv, FORMAT_UNDEF,
"recipient certificate file");
if (cert == NULL)
goto end;
@@ -408,15 +460,14 @@ int smime_main(int argc, char **argv)
}
if (certfile != NULL) {
- if (!load_certs(certfile, &other, FORMAT_PEM, NULL,
- "certificate file")) {
+ if (!load_certs(certfile, 0, &other, NULL, "certificates")) {
ERR_print_errors(bio_err);
goto end;
}
}
if (recipfile != NULL && (operation == SMIME_DECRYPT)) {
- if ((recip = load_cert(recipfile, FORMAT_PEM,
+ if ((recip = load_cert(recipfile, FORMAT_UNDEF,
"recipient certificate file")) == NULL) {
ERR_print_errors(bio_err);
goto end;
@@ -434,7 +485,7 @@ int smime_main(int argc, char **argv)
}
if (keyfile != NULL) {
- key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
+ key = load_key(keyfile, keyform, 0, passin, e, "signing key");
if (key == NULL)
goto end;
}
@@ -444,18 +495,25 @@ int smime_main(int argc, char **argv)
goto end;
if (operation & SMIME_IP) {
+ PKCS7 *p7_in = NULL;
+
+ p7 = PKCS7_new_ex(libctx, app_get0_propq());
+ if (p7 == NULL) {
+ BIO_printf(bio_err, "Error allocating PKCS7 object\n");
+ goto end;
+ }
if (informat == FORMAT_SMIME) {
- p7 = SMIME_read_PKCS7(in, &indata);
+ p7_in = SMIME_read_PKCS7_ex(in, &indata, &p7);
} else if (informat == FORMAT_PEM) {
- p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
+ p7_in = PEM_read_bio_PKCS7(in, &p7, NULL, NULL);
} else if (informat == FORMAT_ASN1) {
- p7 = d2i_PKCS7_bio(in, NULL);
+ p7_in = d2i_PKCS7_bio(in, &p7);
} else {
BIO_printf(bio_err, "Bad input format for PKCS#7 file\n");
goto end;
}
- if (p7 == NULL) {
+ if (p7_in == NULL) {
BIO_printf(bio_err, "Error reading S/MIME message\n");
goto end;
}
@@ -473,7 +531,8 @@ int smime_main(int argc, char **argv)
goto end;
if (operation == SMIME_VERIFY) {
- if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
+ if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore)) == NULL)
goto end;
X509_STORE_set_verify_cb(store, smime_cb);
if (vpmtouched)
@@ -485,7 +544,7 @@ int smime_main(int argc, char **argv)
if (operation == SMIME_ENCRYPT) {
if (indef)
flags |= PKCS7_STREAM;
- p7 = PKCS7_encrypt(encerts, in, cipher, flags);
+ p7 = PKCS7_encrypt_ex(encerts, in, cipher, flags, libctx, app_get0_propq());
} else if (operation & SMIME_SIGNERS) {
int i;
/*
@@ -500,7 +559,7 @@ int smime_main(int argc, char **argv)
flags |= PKCS7_STREAM;
}
flags |= PKCS7_PARTIAL;
- p7 = PKCS7_sign(NULL, NULL, other, in, flags);
+ p7 = PKCS7_sign_ex(NULL, NULL, other, in, flags, libctx, app_get0_propq());
if (p7 == NULL)
goto end;
if (flags & PKCS7_NOCERTS) {
@@ -515,13 +574,13 @@ int smime_main(int argc, char **argv)
for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
signerfile = sk_OPENSSL_STRING_value(sksigners, i);
keyfile = sk_OPENSSL_STRING_value(skkeys, i);
- signer = load_cert(signerfile, FORMAT_PEM,
- "signer certificate");
+ signer = load_cert(signerfile, FORMAT_UNDEF, "signer certificate");
if (signer == NULL)
goto end;
- key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
+ key = load_key(keyfile, keyform, 0, passin, e, "signing key");
if (key == NULL)
goto end;
+
if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags))
goto end;
X509_free(signer);
@@ -604,12 +663,15 @@ int smime_main(int argc, char **argv)
X509_free(recip);
X509_free(signer);
EVP_PKEY_free(key);
+ EVP_MD_free(sign_md);
+ EVP_CIPHER_free(cipher);
PKCS7_free(p7);
release_engine(e);
BIO_free(in);
BIO_free(indata);
BIO_free_all(out);
OPENSSL_free(passin);
+ NCONF_free(conf);
return ret;
}
diff --git a/apps/speed.c b/apps/speed.c
index 89bf18480fa1..addf7e32137f 100644
--- a/apps/speed.c
+++ b/apps/speed.c
@@ -1,20 +1,27 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#undef SECONDS
-#define SECONDS 3
-#define RSA_SECONDS 10
-#define DSA_SECONDS 10
-#define ECDSA_SECONDS 10
-#define ECDH_SECONDS 10
-#define EdDSA_SECONDS 10
+#define SECONDS 3
+#define PKEY_SECONDS 10
+
+#define RSA_SECONDS PKEY_SECONDS
+#define DSA_SECONDS PKEY_SECONDS
+#define ECDSA_SECONDS PKEY_SECONDS
+#define ECDH_SECONDS PKEY_SECONDS
+#define EdDSA_SECONDS PKEY_SECONDS
+#define SM2_SECONDS PKEY_SECONDS
+#define FFDH_SECONDS PKEY_SECONDS
+
+/* We need to use some deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
#include <stdio.h>
#include <stdlib.h>
@@ -22,14 +29,22 @@
#include <math.h>
#include "apps.h"
#include "progs.h"
+#include "internal/numbers.h"
#include <openssl/crypto.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
+#include <openssl/core_names.h>
#include <openssl/async.h>
#if !defined(OPENSSL_SYS_MSDOS)
-# include OPENSSL_UNISTD
+# include <unistd.h>
+#endif
+
+#if defined(__TANDEM)
+# if defined(OPENSSL_TANDEM_FLOSS)
+# include <floss.h(floss_fork)>
+# endif
#endif
#if defined(_WIN32)
@@ -37,66 +52,14 @@
#endif
#include <openssl/bn.h>
-#ifndef OPENSSL_NO_DES
-# include <openssl/des.h>
-#endif
-#include <openssl/aes.h>
-#ifndef OPENSSL_NO_CAMELLIA
-# include <openssl/camellia.h>
-#endif
-#ifndef OPENSSL_NO_MD2
-# include <openssl/md2.h>
-#endif
-#ifndef OPENSSL_NO_MDC2
-# include <openssl/mdc2.h>
-#endif
-#ifndef OPENSSL_NO_MD4
-# include <openssl/md4.h>
-#endif
-#ifndef OPENSSL_NO_MD5
-# include <openssl/md5.h>
-#endif
-#include <openssl/hmac.h>
-#include <openssl/sha.h>
-#ifndef OPENSSL_NO_RMD160
-# include <openssl/ripemd.h>
-#endif
-#ifndef OPENSSL_NO_WHIRLPOOL
-# include <openssl/whrlpool.h>
-#endif
-#ifndef OPENSSL_NO_RC4
-# include <openssl/rc4.h>
-#endif
-#ifndef OPENSSL_NO_RC5
-# include <openssl/rc5.h>
-#endif
-#ifndef OPENSSL_NO_RC2
-# include <openssl/rc2.h>
-#endif
-#ifndef OPENSSL_NO_IDEA
-# include <openssl/idea.h>
-#endif
-#ifndef OPENSSL_NO_SEED
-# include <openssl/seed.h>
-#endif
-#ifndef OPENSSL_NO_BF
-# include <openssl/blowfish.h>
-#endif
-#ifndef OPENSSL_NO_CAST
-# include <openssl/cast.h>
-#endif
-#ifndef OPENSSL_NO_RSA
-# include <openssl/rsa.h>
-# include "./testrsa.h"
+#include <openssl/rsa.h>
+#include "./testrsa.h"
+#ifndef OPENSSL_NO_DH
+# include <openssl/dh.h>
#endif
#include <openssl/x509.h>
-#ifndef OPENSSL_NO_DSA
-# include <openssl/dsa.h>
-# include "./testdsa.h"
-#endif
-#ifndef OPENSSL_NO_EC
-# include <openssl/ec.h>
-#endif
+#include <openssl/dsa.h>
+#include "./testdsa.h"
#include <openssl/modes.h>
#ifndef HAVE_FORK
@@ -104,6 +67,7 @@
# define HAVE_FORK 0
# else
# define HAVE_FORK 1
+# include <sys/wait.h>
# endif
#endif
@@ -116,6 +80,11 @@
#define MAX_MISALIGNMENT 63
#define MAX_ECDH_SIZE 256
#define MISALIGN 64
+#define MAX_FFDH_SIZE 1024
+
+#ifndef RSA_DEFAULT_PRIME_NUM
+# define RSA_DEFAULT_PRIME_NUM 2
+#endif
typedef struct openssl_speed_sec_st {
int sym;
@@ -124,70 +93,15 @@ typedef struct openssl_speed_sec_st {
int ecdsa;
int ecdh;
int eddsa;
+ int sm2;
+ int ffdh;
} openssl_speed_sec_t;
static volatile int run = 0;
-static int mr = 0;
+static int mr = 0; /* machine-readeable output format to merge fork results */
static int usertime = 1;
-#ifndef OPENSSL_NO_MD2
-static int EVP_Digest_MD2_loop(void *args);
-#endif
-
-#ifndef OPENSSL_NO_MDC2
-static int EVP_Digest_MDC2_loop(void *args);
-#endif
-#ifndef OPENSSL_NO_MD4
-static int EVP_Digest_MD4_loop(void *args);
-#endif
-#ifndef OPENSSL_NO_MD5
-static int MD5_loop(void *args);
-static int HMAC_loop(void *args);
-#endif
-static int SHA1_loop(void *args);
-static int SHA256_loop(void *args);
-static int SHA512_loop(void *args);
-#ifndef OPENSSL_NO_WHIRLPOOL
-static int WHIRLPOOL_loop(void *args);
-#endif
-#ifndef OPENSSL_NO_RMD160
-static int EVP_Digest_RMD160_loop(void *args);
-#endif
-#ifndef OPENSSL_NO_RC4
-static int RC4_loop(void *args);
-#endif
-#ifndef OPENSSL_NO_DES
-static int DES_ncbc_encrypt_loop(void *args);
-static int DES_ede3_cbc_encrypt_loop(void *args);
-#endif
-static int AES_cbc_128_encrypt_loop(void *args);
-static int AES_cbc_192_encrypt_loop(void *args);
-static int AES_ige_128_encrypt_loop(void *args);
-static int AES_cbc_256_encrypt_loop(void *args);
-static int AES_ige_192_encrypt_loop(void *args);
-static int AES_ige_256_encrypt_loop(void *args);
-static int CRYPTO_gcm128_aad_loop(void *args);
-static int RAND_bytes_loop(void *args);
-static int EVP_Update_loop(void *args);
-static int EVP_Update_loop_ccm(void *args);
-static int EVP_Update_loop_aead(void *args);
-static int EVP_Digest_loop(void *args);
-#ifndef OPENSSL_NO_RSA
-static int RSA_sign_loop(void *args);
-static int RSA_verify_loop(void *args);
-#endif
-#ifndef OPENSSL_NO_DSA
-static int DSA_sign_loop(void *args);
-static int DSA_verify_loop(void *args);
-#endif
-#ifndef OPENSSL_NO_EC
-static int ECDSA_sign_loop(void *args);
-static int ECDSA_verify_loop(void *args);
-static int EdDSA_sign_loop(void *args);
-static int EdDSA_verify_loop(void *args);
-#endif
-
static double Time_F(int s);
static void print_message(const char *s, long num, int length, int tm);
static void pkey_print_message(const char *str, const char *str2,
@@ -200,6 +114,7 @@ static int do_multi(int multi, int size_num);
static const int lengths_list[] = {
16, 64, 256, 1024, 8 * 1024, 16 * 1024
};
+#define SIZE_NUM OSSL_NELEM(lengths_list)
static const int *lengths = lengths_list;
static const int aead_lengths_list[] = {
@@ -272,17 +187,12 @@ static double Time_F(int s)
return ret;
}
#else
-static double Time_F(int s)
-{
- return app_tminterval(s, usertime);
-}
+# error "SIGALRM not defined and the platform is not Windows"
#endif
static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
const openssl_speed_sec_t *seconds);
-#define found(value, pairs, result)\
- opt_found(value, result, pairs, OSSL_NELEM(pairs))
static int opt_found(const char *name, unsigned int *result,
const OPT_PAIR pairs[], unsigned int nbelem)
{
@@ -295,23 +205,21 @@ static int opt_found(const char *name, unsigned int *result,
}
return 0;
}
+#define opt_found(value, pairs, result)\
+ opt_found(value, result, pairs, OSSL_NELEM(pairs))
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_ELAPSED, OPT_EVP, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI,
- OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM,
- OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD
+ OPT_COMMON,
+ OPT_ELAPSED, OPT_EVP, OPT_HMAC, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI,
+ OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM, OPT_PROV_ENUM,
+ OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD, OPT_CMAC
} OPTION_CHOICE;
const OPTIONS speed_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [options] ciphers...\n"},
- {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [algorithm...]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"evp", OPT_EVP, 's', "Use EVP-named cipher or digest"},
- {"decrypt", OPT_DECRYPT, '-',
- "Time decryption instead of encryption (only EVP)"},
- {"aead", OPT_AEAD, '-',
- "Benchmark EVP-named AEAD cipher in TLS-like sequence"},
{"mb", OPT_MB, '-',
"Enable (tls1>=1) multi-block mode on EVP-named cipher"},
{"mr", OPT_MR, '-', "Produce machine readable output"},
@@ -322,160 +230,114 @@ const OPTIONS speed_options[] = {
{"async_jobs", OPT_ASYNCJOBS, 'p',
"Enable async mode and start specified number of jobs"},
#endif
- OPT_R_OPTIONS,
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
+ {"primes", OPT_PRIMES, 'p', "Specify number of primes (for RSA only)"},
+
+ OPT_SECTION("Selection"),
+ {"evp", OPT_EVP, 's', "Use EVP-named cipher or digest"},
+ {"hmac", OPT_HMAC, 's', "HMAC using EVP-named digest"},
+ {"cmac", OPT_CMAC, 's', "CMAC using EVP-named cipher"},
+ {"decrypt", OPT_DECRYPT, '-',
+ "Time decryption instead of encryption (only EVP)"},
+ {"aead", OPT_AEAD, '-',
+ "Benchmark EVP-named AEAD cipher in TLS-like sequence"},
+
+ OPT_SECTION("Timing"),
{"elapsed", OPT_ELAPSED, '-',
"Use wall-clock time instead of CPU user time as divisor"},
- {"primes", OPT_PRIMES, 'p', "Specify number of primes (for RSA only)"},
{"seconds", OPT_SECONDS, 'p',
"Run benchmarks for specified amount of seconds"},
{"bytes", OPT_BYTES, 'p',
"Run [non-PKI] benchmarks on custom-sized buffer"},
{"misalign", OPT_MISALIGN, 'p',
"Use specified offset to mis-align buffers"},
+
+ OPT_R_OPTIONS,
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"algorithm", 0, 0, "Algorithm(s) to test (optional; otherwise tests all)"},
{NULL}
};
-#define D_MD2 0
-#define D_MDC2 1
-#define D_MD4 2
-#define D_MD5 3
-#define D_HMAC 4
-#define D_SHA1 5
-#define D_RMD160 6
-#define D_RC4 7
-#define D_CBC_DES 8
-#define D_EDE3_DES 9
-#define D_CBC_IDEA 10
-#define D_CBC_SEED 11
-#define D_CBC_RC2 12
-#define D_CBC_RC5 13
-#define D_CBC_BF 14
-#define D_CBC_CAST 15
-#define D_CBC_128_AES 16
-#define D_CBC_192_AES 17
-#define D_CBC_256_AES 18
-#define D_CBC_128_CML 19
-#define D_CBC_192_CML 20
-#define D_CBC_256_CML 21
-#define D_EVP 22
-#define D_SHA256 23
-#define D_SHA512 24
-#define D_WHIRLPOOL 25
-#define D_IGE_128_AES 26
-#define D_IGE_192_AES 27
-#define D_IGE_256_AES 28
-#define D_GHASH 29
-#define D_RAND 30
-/* name of algorithms to test */
-static const char *names[] = {
- "md2", "mdc2", "md4", "md5", "hmac(md5)", "sha1", "rmd160", "rc4",
- "des cbc", "des ede3", "idea cbc", "seed cbc",
- "rc2 cbc", "rc5-32/12 cbc", "blowfish cbc", "cast cbc",
- "aes-128 cbc", "aes-192 cbc", "aes-256 cbc",
- "camellia-128 cbc", "camellia-192 cbc", "camellia-256 cbc",
- "evp", "sha256", "sha512", "whirlpool",
- "aes-128 ige", "aes-192 ige", "aes-256 ige", "ghash",
- "rand"
+enum {
+ D_MD2, D_MDC2, D_MD4, D_MD5, D_SHA1, D_RMD160,
+ D_SHA256, D_SHA512, D_WHIRLPOOL, D_HMAC,
+ D_CBC_DES, D_EDE3_DES, D_RC4, D_CBC_IDEA, D_CBC_SEED,
+ D_CBC_RC2, D_CBC_RC5, D_CBC_BF, D_CBC_CAST,
+ D_CBC_128_AES, D_CBC_192_AES, D_CBC_256_AES,
+ D_CBC_128_CML, D_CBC_192_CML, D_CBC_256_CML,
+ D_EVP, D_GHASH, D_RAND, D_EVP_CMAC, ALGOR_NUM
+};
+/* name of algorithms to test. MUST BE KEEP IN SYNC with above enum ! */
+static const char *names[ALGOR_NUM] = {
+ "md2", "mdc2", "md4", "md5", "sha1", "rmd160",
+ "sha256", "sha512", "whirlpool", "hmac(md5)",
+ "des-cbc", "des-ede3", "rc4", "idea-cbc", "seed-cbc",
+ "rc2-cbc", "rc5-cbc", "blowfish", "cast-cbc",
+ "aes-128-cbc", "aes-192-cbc", "aes-256-cbc",
+ "camellia-128-cbc", "camellia-192-cbc", "camellia-256-cbc",
+ "evp", "ghash", "rand", "cmac"
};
-#define ALGOR_NUM OSSL_NELEM(names)
-/* list of configured algorithm (remaining) */
+/* list of configured algorithm (remaining), with some few alias */
static const OPT_PAIR doit_choices[] = {
-#ifndef OPENSSL_NO_MD2
{"md2", D_MD2},
-#endif
-#ifndef OPENSSL_NO_MDC2
{"mdc2", D_MDC2},
-#endif
-#ifndef OPENSSL_NO_MD4
{"md4", D_MD4},
-#endif
-#ifndef OPENSSL_NO_MD5
{"md5", D_MD5},
{"hmac", D_HMAC},
-#endif
{"sha1", D_SHA1},
{"sha256", D_SHA256},
{"sha512", D_SHA512},
-#ifndef OPENSSL_NO_WHIRLPOOL
{"whirlpool", D_WHIRLPOOL},
-#endif
-#ifndef OPENSSL_NO_RMD160
{"ripemd", D_RMD160},
{"rmd160", D_RMD160},
{"ripemd160", D_RMD160},
-#endif
-#ifndef OPENSSL_NO_RC4
{"rc4", D_RC4},
-#endif
-#ifndef OPENSSL_NO_DES
{"des-cbc", D_CBC_DES},
{"des-ede3", D_EDE3_DES},
-#endif
{"aes-128-cbc", D_CBC_128_AES},
{"aes-192-cbc", D_CBC_192_AES},
{"aes-256-cbc", D_CBC_256_AES},
- {"aes-128-ige", D_IGE_128_AES},
- {"aes-192-ige", D_IGE_192_AES},
- {"aes-256-ige", D_IGE_256_AES},
-#ifndef OPENSSL_NO_RC2
+ {"camellia-128-cbc", D_CBC_128_CML},
+ {"camellia-192-cbc", D_CBC_192_CML},
+ {"camellia-256-cbc", D_CBC_256_CML},
{"rc2-cbc", D_CBC_RC2},
{"rc2", D_CBC_RC2},
-#endif
-#ifndef OPENSSL_NO_RC5
{"rc5-cbc", D_CBC_RC5},
{"rc5", D_CBC_RC5},
-#endif
-#ifndef OPENSSL_NO_IDEA
{"idea-cbc", D_CBC_IDEA},
{"idea", D_CBC_IDEA},
-#endif
-#ifndef OPENSSL_NO_SEED
{"seed-cbc", D_CBC_SEED},
{"seed", D_CBC_SEED},
-#endif
-#ifndef OPENSSL_NO_BF
{"bf-cbc", D_CBC_BF},
{"blowfish", D_CBC_BF},
{"bf", D_CBC_BF},
-#endif
-#ifndef OPENSSL_NO_CAST
{"cast-cbc", D_CBC_CAST},
{"cast", D_CBC_CAST},
{"cast5", D_CBC_CAST},
-#endif
{"ghash", D_GHASH},
{"rand", D_RAND}
};
-static double results[ALGOR_NUM][OSSL_NELEM(lengths_list)];
+static double results[ALGOR_NUM][SIZE_NUM];
-#ifndef OPENSSL_NO_DSA
-# define R_DSA_512 0
-# define R_DSA_1024 1
-# define R_DSA_2048 2
-static const OPT_PAIR dsa_choices[] = {
+enum { R_DSA_512, R_DSA_1024, R_DSA_2048, DSA_NUM };
+static const OPT_PAIR dsa_choices[DSA_NUM] = {
{"dsa512", R_DSA_512},
{"dsa1024", R_DSA_1024},
{"dsa2048", R_DSA_2048}
};
-# define DSA_NUM OSSL_NELEM(dsa_choices)
-
static double dsa_results[DSA_NUM][2]; /* 2 ops: sign then verify */
-#endif /* OPENSSL_NO_DSA */
-
-#define R_RSA_512 0
-#define R_RSA_1024 1
-#define R_RSA_2048 2
-#define R_RSA_3072 3
-#define R_RSA_4096 4
-#define R_RSA_7680 5
-#define R_RSA_15360 6
-#ifndef OPENSSL_NO_RSA
-static const OPT_PAIR rsa_choices[] = {
+
+enum {
+ R_RSA_512, R_RSA_1024, R_RSA_2048, R_RSA_3072, R_RSA_4096, R_RSA_7680,
+ R_RSA_15360, RSA_NUM
+};
+static const OPT_PAIR rsa_choices[RSA_NUM] = {
{"rsa512", R_RSA_512},
{"rsa1024", R_RSA_1024},
{"rsa2048", R_RSA_2048},
@@ -484,49 +346,43 @@ static const OPT_PAIR rsa_choices[] = {
{"rsa7680", R_RSA_7680},
{"rsa15360", R_RSA_15360}
};
-# define RSA_NUM OSSL_NELEM(rsa_choices)
static double rsa_results[RSA_NUM][2]; /* 2 ops: sign then verify */
-#endif /* OPENSSL_NO_RSA */
-enum {
- R_EC_P160,
- R_EC_P192,
- R_EC_P224,
- R_EC_P256,
- R_EC_P384,
- R_EC_P521,
+#ifndef OPENSSL_NO_DH
+enum ff_params_t {
+ R_FFDH_2048, R_FFDH_3072, R_FFDH_4096, R_FFDH_6144, R_FFDH_8192, FFDH_NUM
+};
+
+static const OPT_PAIR ffdh_choices[FFDH_NUM] = {
+ {"ffdh2048", R_FFDH_2048},
+ {"ffdh3072", R_FFDH_3072},
+ {"ffdh4096", R_FFDH_4096},
+ {"ffdh6144", R_FFDH_6144},
+ {"ffdh8192", R_FFDH_8192},
+};
+
+static double ffdh_results[FFDH_NUM][1]; /* 1 op: derivation */
+#endif /* OPENSSL_NO_DH */
+
+enum ec_curves_t {
+ R_EC_P160, R_EC_P192, R_EC_P224, R_EC_P256, R_EC_P384, R_EC_P521,
#ifndef OPENSSL_NO_EC2M
- R_EC_K163,
- R_EC_K233,
- R_EC_K283,
- R_EC_K409,
- R_EC_K571,
- R_EC_B163,
- R_EC_B233,
- R_EC_B283,
- R_EC_B409,
- R_EC_B571,
+ R_EC_K163, R_EC_K233, R_EC_K283, R_EC_K409, R_EC_K571,
+ R_EC_B163, R_EC_B233, R_EC_B283, R_EC_B409, R_EC_B571,
#endif
- R_EC_BRP256R1,
- R_EC_BRP256T1,
- R_EC_BRP384R1,
- R_EC_BRP384T1,
- R_EC_BRP512R1,
- R_EC_BRP512T1,
- R_EC_X25519,
- R_EC_X448
+ R_EC_BRP256R1, R_EC_BRP256T1, R_EC_BRP384R1, R_EC_BRP384T1,
+ R_EC_BRP512R1, R_EC_BRP512T1, ECDSA_NUM
};
-
-#ifndef OPENSSL_NO_EC
-static OPT_PAIR ecdsa_choices[] = {
+/* list of ecdsa curves */
+static const OPT_PAIR ecdsa_choices[ECDSA_NUM] = {
{"ecdsap160", R_EC_P160},
{"ecdsap192", R_EC_P192},
{"ecdsap224", R_EC_P224},
{"ecdsap256", R_EC_P256},
{"ecdsap384", R_EC_P384},
{"ecdsap521", R_EC_P521},
-# ifndef OPENSSL_NO_EC2M
+#ifndef OPENSSL_NO_EC2M
{"ecdsak163", R_EC_K163},
{"ecdsak233", R_EC_K233},
{"ecdsak283", R_EC_K283},
@@ -537,7 +393,7 @@ static OPT_PAIR ecdsa_choices[] = {
{"ecdsab283", R_EC_B283},
{"ecdsab409", R_EC_B409},
{"ecdsab571", R_EC_B571},
-# endif
+#endif
{"ecdsabrp256r1", R_EC_BRP256R1},
{"ecdsabrp256t1", R_EC_BRP256T1},
{"ecdsabrp384r1", R_EC_BRP384R1},
@@ -545,18 +401,16 @@ static OPT_PAIR ecdsa_choices[] = {
{"ecdsabrp512r1", R_EC_BRP512R1},
{"ecdsabrp512t1", R_EC_BRP512T1}
};
-# define ECDSA_NUM OSSL_NELEM(ecdsa_choices)
-
-static double ecdsa_results[ECDSA_NUM][2]; /* 2 ops: sign then verify */
-
-static const OPT_PAIR ecdh_choices[] = {
+enum { R_EC_X25519 = ECDSA_NUM, R_EC_X448, EC_NUM };
+/* list of ecdh curves, extension of |ecdsa_choices| list above */
+static const OPT_PAIR ecdh_choices[EC_NUM] = {
{"ecdhp160", R_EC_P160},
{"ecdhp192", R_EC_P192},
{"ecdhp224", R_EC_P224},
{"ecdhp256", R_EC_P256},
{"ecdhp384", R_EC_P384},
{"ecdhp521", R_EC_P521},
-# ifndef OPENSSL_NO_EC2M
+#ifndef OPENSSL_NO_EC2M
{"ecdhk163", R_EC_K163},
{"ecdhk233", R_EC_K233},
{"ecdhk283", R_EC_K283},
@@ -567,7 +421,7 @@ static const OPT_PAIR ecdh_choices[] = {
{"ecdhb283", R_EC_B283},
{"ecdhb409", R_EC_B409},
{"ecdhb571", R_EC_B571},
-# endif
+#endif
{"ecdhbrp256r1", R_EC_BRP256R1},
{"ecdhbrp256t1", R_EC_BRP256T1},
{"ecdhbrp384r1", R_EC_BRP384R1},
@@ -577,28 +431,30 @@ static const OPT_PAIR ecdh_choices[] = {
{"ecdhx25519", R_EC_X25519},
{"ecdhx448", R_EC_X448}
};
-# define EC_NUM OSSL_NELEM(ecdh_choices)
-static double ecdh_results[EC_NUM][1]; /* 1 op: derivation */
+static double ecdh_results[EC_NUM][1]; /* 1 op: derivation */
+static double ecdsa_results[ECDSA_NUM][2]; /* 2 ops: sign then verify */
-#define R_EC_Ed25519 0
-#define R_EC_Ed448 1
-static OPT_PAIR eddsa_choices[] = {
+enum { R_EC_Ed25519, R_EC_Ed448, EdDSA_NUM };
+static const OPT_PAIR eddsa_choices[EdDSA_NUM] = {
{"ed25519", R_EC_Ed25519},
{"ed448", R_EC_Ed448}
-};
-# define EdDSA_NUM OSSL_NELEM(eddsa_choices)
+};
static double eddsa_results[EdDSA_NUM][2]; /* 2 ops: sign then verify */
-#endif /* OPENSSL_NO_EC */
-#ifndef SIGALRM
-# define COND(d) (count < (d))
-# define COUNT(d) (d)
-#else
-# define COND(unused_cond) (run && count<0x7fffffff)
-# define COUNT(d) (count)
-#endif /* SIGALRM */
+#ifndef OPENSSL_NO_SM2
+enum { R_EC_CURVESM2, SM2_NUM };
+static const OPT_PAIR sm2_choices[SM2_NUM] = {
+ {"curveSM2", R_EC_CURVESM2}
+};
+# define SM2_ID "TLSv1.3+GM+Cipher+Suite"
+# define SM2_ID_LEN sizeof("TLSv1.3+GM+Cipher+Suite") - 1
+static double sm2_results[SM2_NUM][2]; /* 2 ops: sign then verify */
+#endif /* OPENSSL_NO_SM2 */
+
+#define COND(unused_cond) (run && count < INT_MAX)
+#define COUNT(d) (count)
typedef struct loopargs_st {
ASYNC_JOB *inprogress_job;
@@ -608,25 +464,32 @@ typedef struct loopargs_st {
unsigned char *buf_malloc;
unsigned char *buf2_malloc;
unsigned char *key;
- unsigned int siglen;
+ size_t buflen;
size_t sigsize;
-#ifndef OPENSSL_NO_RSA
- RSA *rsa_key[RSA_NUM];
-#endif
-#ifndef OPENSSL_NO_DSA
- DSA *dsa_key[DSA_NUM];
-#endif
-#ifndef OPENSSL_NO_EC
- EC_KEY *ecdsa[ECDSA_NUM];
+ EVP_PKEY_CTX *rsa_sign_ctx[RSA_NUM];
+ EVP_PKEY_CTX *rsa_verify_ctx[RSA_NUM];
+ EVP_PKEY_CTX *dsa_sign_ctx[DSA_NUM];
+ EVP_PKEY_CTX *dsa_verify_ctx[DSA_NUM];
+ EVP_PKEY_CTX *ecdsa_sign_ctx[ECDSA_NUM];
+ EVP_PKEY_CTX *ecdsa_verify_ctx[ECDSA_NUM];
EVP_PKEY_CTX *ecdh_ctx[EC_NUM];
EVP_MD_CTX *eddsa_ctx[EdDSA_NUM];
+ EVP_MD_CTX *eddsa_ctx2[EdDSA_NUM];
+#ifndef OPENSSL_NO_SM2
+ EVP_MD_CTX *sm2_ctx[SM2_NUM];
+ EVP_MD_CTX *sm2_vfy_ctx[SM2_NUM];
+ EVP_PKEY *sm2_pkey[SM2_NUM];
+#endif
unsigned char *secret_a;
unsigned char *secret_b;
size_t outlen[EC_NUM];
+#ifndef OPENSSL_NO_DH
+ EVP_PKEY_CTX *ffdh_ctx[FFDH_NUM];
+ unsigned char *secret_ff_a;
+ unsigned char *secret_ff_b;
#endif
EVP_CIPHER_CTX *ctx;
- HMAC_CTX *hctx;
- GCM128_CONTEXT *gcm_ctx;
+ EVP_MAC_CTX *mctx;
} loopargs_t;
static int run_benchmark(int async_jobs, int (*loop_function) (void *),
loopargs_t * loopargs);
@@ -634,273 +497,216 @@ static int run_benchmark(int async_jobs, int (*loop_function) (void *),
static unsigned int testnum;
/* Nb of iterations to do per algorithm and key-size */
-static long c[ALGOR_NUM][OSSL_NELEM(lengths_list)];
+static long c[ALGOR_NUM][SIZE_NUM];
-#ifndef OPENSSL_NO_MD2
-static int EVP_Digest_MD2_loop(void *args)
+static char *evp_mac_mdname = "md5";
+static char *evp_hmac_name = NULL;
+static const char *evp_md_name = NULL;
+static char *evp_mac_ciphername = "aes-128-cbc";
+static char *evp_cmac_name = NULL;
+
+static int have_md(const char *name)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- unsigned char md2[MD2_DIGEST_LENGTH];
- int count;
+ int ret = 0;
+ EVP_MD *md = NULL;
- for (count = 0; COND(c[D_MD2][testnum]); count++) {
- if (!EVP_Digest(buf, (size_t)lengths[testnum], md2, NULL, EVP_md2(),
- NULL))
- return -1;
+ if (opt_md_silent(name, &md)) {
+ EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+
+ if (ctx != NULL && EVP_DigestInit(ctx, md) > 0)
+ ret = 1;
+ EVP_MD_CTX_free(ctx);
+ EVP_MD_free(md);
}
- return count;
+ return ret;
}
-#endif
-#ifndef OPENSSL_NO_MDC2
-static int EVP_Digest_MDC2_loop(void *args)
+static int have_cipher(const char *name)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- unsigned char mdc2[MDC2_DIGEST_LENGTH];
- int count;
+ int ret = 0;
+ EVP_CIPHER *cipher = NULL;
- for (count = 0; COND(c[D_MDC2][testnum]); count++) {
- if (!EVP_Digest(buf, (size_t)lengths[testnum], mdc2, NULL, EVP_mdc2(),
- NULL))
- return -1;
+ if (opt_cipher_silent(name, &cipher)) {
+ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+
+ if (ctx != NULL
+ && EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, 1) > 0)
+ ret = 1;
+ EVP_CIPHER_CTX_free(ctx);
+ EVP_CIPHER_free(cipher);
}
- return count;
+ return ret;
}
-#endif
-#ifndef OPENSSL_NO_MD4
-static int EVP_Digest_MD4_loop(void *args)
+static int EVP_Digest_loop(const char *mdname, int algindex, void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
- unsigned char md4[MD4_DIGEST_LENGTH];
+ unsigned char digest[EVP_MAX_MD_SIZE];
int count;
+ EVP_MD *md = NULL;
- for (count = 0; COND(c[D_MD4][testnum]); count++) {
- if (!EVP_Digest(buf, (size_t)lengths[testnum], md4, NULL, EVP_md4(),
- NULL))
- return -1;
+ if (!opt_md_silent(mdname, &md))
+ return -1;
+ for (count = 0; COND(c[algindex][testnum]); count++) {
+ if (!EVP_Digest(buf, (size_t)lengths[testnum], digest, NULL, md,
+ NULL)) {
+ count = -1;
+ break;
+ }
}
+ EVP_MD_free(md);
return count;
}
-#endif
-#ifndef OPENSSL_NO_MD5
-static int MD5_loop(void *args)
+static int EVP_Digest_md_loop(void *args)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- unsigned char md5[MD5_DIGEST_LENGTH];
- int count;
- for (count = 0; COND(c[D_MD5][testnum]); count++)
- MD5(buf, lengths[testnum], md5);
- return count;
+ return EVP_Digest_loop(evp_md_name, D_EVP, args);
}
-static int HMAC_loop(void *args)
+static int EVP_Digest_MD2_loop(void *args)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- HMAC_CTX *hctx = tempargs->hctx;
- unsigned char hmac[MD5_DIGEST_LENGTH];
- int count;
-
- for (count = 0; COND(c[D_HMAC][testnum]); count++) {
- HMAC_Init_ex(hctx, NULL, 0, NULL, NULL);
- HMAC_Update(hctx, buf, lengths[testnum]);
- HMAC_Final(hctx, hmac, NULL);
- }
- return count;
+ return EVP_Digest_loop("md2", D_MD2, args);
}
-#endif
-static int SHA1_loop(void *args)
+static int EVP_Digest_MDC2_loop(void *args)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- unsigned char sha[SHA_DIGEST_LENGTH];
- int count;
- for (count = 0; COND(c[D_SHA1][testnum]); count++)
- SHA1(buf, lengths[testnum], sha);
- return count;
+ return EVP_Digest_loop("mdc2", D_MDC2, args);
}
-static int SHA256_loop(void *args)
+static int EVP_Digest_MD4_loop(void *args)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- unsigned char sha256[SHA256_DIGEST_LENGTH];
- int count;
- for (count = 0; COND(c[D_SHA256][testnum]); count++)
- SHA256(buf, lengths[testnum], sha256);
- return count;
+ return EVP_Digest_loop("md4", D_MD4, args);
}
-static int SHA512_loop(void *args)
+static int MD5_loop(void *args)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- unsigned char sha512[SHA512_DIGEST_LENGTH];
- int count;
- for (count = 0; COND(c[D_SHA512][testnum]); count++)
- SHA512(buf, lengths[testnum], sha512);
- return count;
+ return EVP_Digest_loop("md5", D_MD5, args);
}
-#ifndef OPENSSL_NO_WHIRLPOOL
-static int WHIRLPOOL_loop(void *args)
+static int EVP_MAC_loop(int algindex, void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
- unsigned char whirlpool[WHIRLPOOL_DIGEST_LENGTH];
+ EVP_MAC_CTX *mctx = tempargs->mctx;
+ unsigned char mac[EVP_MAX_MD_SIZE];
int count;
- for (count = 0; COND(c[D_WHIRLPOOL][testnum]); count++)
- WHIRLPOOL(buf, lengths[testnum], whirlpool);
- return count;
-}
-#endif
-#ifndef OPENSSL_NO_RMD160
-static int EVP_Digest_RMD160_loop(void *args)
-{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- unsigned char rmd160[RIPEMD160_DIGEST_LENGTH];
- int count;
- for (count = 0; COND(c[D_RMD160][testnum]); count++) {
- if (!EVP_Digest(buf, (size_t)lengths[testnum], &(rmd160[0]),
- NULL, EVP_ripemd160(), NULL))
+ for (count = 0; COND(c[algindex][testnum]); count++) {
+ size_t outl;
+
+ if (!EVP_MAC_init(mctx, NULL, 0, NULL)
+ || !EVP_MAC_update(mctx, buf, lengths[testnum])
+ || !EVP_MAC_final(mctx, mac, &outl, sizeof(mac)))
return -1;
}
return count;
}
-#endif
-#ifndef OPENSSL_NO_RC4
-static RC4_KEY rc4_ks;
-static int RC4_loop(void *args)
+static int HMAC_loop(void *args)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- int count;
- for (count = 0; COND(c[D_RC4][testnum]); count++)
- RC4(&rc4_ks, (size_t)lengths[testnum], buf, buf);
- return count;
+ return EVP_MAC_loop(D_HMAC, args);
}
-#endif
-#ifndef OPENSSL_NO_DES
-static unsigned char DES_iv[8];
-static DES_key_schedule sch;
-static DES_key_schedule sch2;
-static DES_key_schedule sch3;
-static int DES_ncbc_encrypt_loop(void *args)
+static int CMAC_loop(void *args)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- int count;
- for (count = 0; COND(c[D_CBC_DES][testnum]); count++)
- DES_ncbc_encrypt(buf, buf, lengths[testnum], &sch,
- &DES_iv, DES_ENCRYPT);
- return count;
+ return EVP_MAC_loop(D_EVP_CMAC, args);
}
-static int DES_ede3_cbc_encrypt_loop(void *args)
+static int SHA1_loop(void *args)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- int count;
- for (count = 0; COND(c[D_EDE3_DES][testnum]); count++)
- DES_ede3_cbc_encrypt(buf, buf, lengths[testnum],
- &sch, &sch2, &sch3, &DES_iv, DES_ENCRYPT);
- return count;
+ return EVP_Digest_loop("sha1", D_SHA1, args);
}
-#endif
-
-#define MAX_BLOCK_SIZE 128
-static unsigned char iv[2 * MAX_BLOCK_SIZE / 8];
-static AES_KEY aes_ks1, aes_ks2, aes_ks3;
-static int AES_cbc_128_encrypt_loop(void *args)
+static int SHA256_loop(void *args)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- int count;
- for (count = 0; COND(c[D_CBC_128_AES][testnum]); count++)
- AES_cbc_encrypt(buf, buf,
- (size_t)lengths[testnum], &aes_ks1, iv, AES_ENCRYPT);
- return count;
+ return EVP_Digest_loop("sha256", D_SHA256, args);
}
-static int AES_cbc_192_encrypt_loop(void *args)
+static int SHA512_loop(void *args)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- int count;
- for (count = 0; COND(c[D_CBC_192_AES][testnum]); count++)
- AES_cbc_encrypt(buf, buf,
- (size_t)lengths[testnum], &aes_ks2, iv, AES_ENCRYPT);
- return count;
+ return EVP_Digest_loop("sha512", D_SHA512, args);
}
-static int AES_cbc_256_encrypt_loop(void *args)
+static int WHIRLPOOL_loop(void *args)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- int count;
- for (count = 0; COND(c[D_CBC_256_AES][testnum]); count++)
- AES_cbc_encrypt(buf, buf,
- (size_t)lengths[testnum], &aes_ks3, iv, AES_ENCRYPT);
- return count;
+ return EVP_Digest_loop("whirlpool", D_WHIRLPOOL, args);
}
-static int AES_ige_128_encrypt_loop(void *args)
+static int EVP_Digest_RMD160_loop(void *args)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- unsigned char *buf2 = tempargs->buf2;
- int count;
- for (count = 0; COND(c[D_IGE_128_AES][testnum]); count++)
- AES_ige_encrypt(buf, buf2,
- (size_t)lengths[testnum], &aes_ks1, iv, AES_ENCRYPT);
- return count;
+ return EVP_Digest_loop("ripemd160", D_RMD160, args);
}
-static int AES_ige_192_encrypt_loop(void *args)
+static int algindex;
+
+static int EVP_Cipher_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
- unsigned char *buf2 = tempargs->buf2;
int count;
- for (count = 0; COND(c[D_IGE_192_AES][testnum]); count++)
- AES_ige_encrypt(buf, buf2,
- (size_t)lengths[testnum], &aes_ks2, iv, AES_ENCRYPT);
+
+ if (tempargs->ctx == NULL)
+ return -1;
+ for (count = 0; COND(c[algindex][testnum]); count++)
+ if (EVP_Cipher(tempargs->ctx, buf, buf, (size_t)lengths[testnum]) <= 0)
+ return -1;
return count;
}
-static int AES_ige_256_encrypt_loop(void *args)
+static int GHASH_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
- unsigned char *buf2 = tempargs->buf2;
+ EVP_MAC_CTX *mctx = tempargs->mctx;
int count;
- for (count = 0; COND(c[D_IGE_256_AES][testnum]); count++)
- AES_ige_encrypt(buf, buf2,
- (size_t)lengths[testnum], &aes_ks3, iv, AES_ENCRYPT);
+
+ /* just do the update in the loop to be comparable with 1.1.1 */
+ for (count = 0; COND(c[D_GHASH][testnum]); count++) {
+ if (!EVP_MAC_update(mctx, buf, lengths[testnum]))
+ return -1;
+ }
return count;
}
-static int CRYPTO_gcm128_aad_loop(void *args)
+#define MAX_BLOCK_SIZE 128
+
+static unsigned char iv[2 * MAX_BLOCK_SIZE / 8];
+
+static EVP_CIPHER_CTX *init_evp_cipher_ctx(const char *ciphername,
+ const unsigned char *key,
+ int keylen)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- GCM128_CONTEXT *gcm_ctx = tempargs->gcm_ctx;
- int count;
- for (count = 0; COND(c[D_GHASH][testnum]); count++)
- CRYPTO_gcm128_aad(gcm_ctx, buf, lengths[testnum]);
- return count;
+ EVP_CIPHER_CTX *ctx = NULL;
+ EVP_CIPHER *cipher = NULL;
+
+ if (!opt_cipher_silent(ciphername, &cipher))
+ return NULL;
+
+ if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
+ goto end;
+
+ if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, 1)) {
+ EVP_CIPHER_CTX_free(ctx);
+ ctx = NULL;
+ goto end;
+ }
+
+ if (EVP_CIPHER_CTX_set_key_length(ctx, keylen) <= 0) {
+ EVP_CIPHER_CTX_free(ctx);
+ ctx = NULL;
+ goto end;
+ }
+
+ if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1)) {
+ EVP_CIPHER_CTX_free(ctx);
+ ctx = NULL;
+ goto end;
+ }
+
+end:
+ EVP_CIPHER_free(cipher);
+ return ctx;
}
static int RAND_bytes_loop(void *args)
@@ -914,7 +720,6 @@ static int RAND_bytes_loop(void *args)
return count;
}
-static long save_count = 0;
static int decrypt = 0;
static int EVP_Update_loop(void *args)
{
@@ -922,11 +727,9 @@ static int EVP_Update_loop(void *args)
unsigned char *buf = tempargs->buf;
EVP_CIPHER_CTX *ctx = tempargs->ctx;
int outl, count, rc;
-#ifndef SIGALRM
- int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
-#endif
+
if (decrypt) {
- for (count = 0; COND(nb_iter); count++) {
+ for (count = 0; COND(c[D_EVP][testnum]); count++) {
rc = EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
if (rc != 1) {
/* reset iv in case of counter overflow */
@@ -934,7 +737,7 @@ static int EVP_Update_loop(void *args)
}
}
} else {
- for (count = 0; COND(nb_iter); count++) {
+ for (count = 0; COND(c[D_EVP][testnum]); count++) {
rc = EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
if (rc != 1) {
/* reset iv in case of counter overflow */
@@ -961,29 +764,28 @@ static int EVP_Update_loop_ccm(void *args)
EVP_CIPHER_CTX *ctx = tempargs->ctx;
int outl, count;
unsigned char tag[12];
-#ifndef SIGALRM
- int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
-#endif
+
if (decrypt) {
- for (count = 0; COND(nb_iter); count++) {
- EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, sizeof(tag), tag);
+ for (count = 0; COND(c[D_EVP][testnum]); count++) {
+ (void)EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, sizeof(tag),
+ tag);
/* reset iv */
- EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
+ (void)EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
/* counter is reset on every update */
- EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+ (void)EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
}
} else {
- for (count = 0; COND(nb_iter); count++) {
+ for (count = 0; COND(c[D_EVP][testnum]); count++) {
/* restore iv length field */
- EVP_EncryptUpdate(ctx, NULL, &outl, NULL, lengths[testnum]);
+ (void)EVP_EncryptUpdate(ctx, NULL, &outl, NULL, lengths[testnum]);
/* counter is reset on every update */
- EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+ (void)EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
}
}
if (decrypt)
- EVP_DecryptFinal_ex(ctx, buf, &outl);
+ (void)EVP_DecryptFinal_ex(ctx, buf, &outl);
else
- EVP_EncryptFinal_ex(ctx, buf, &outl);
+ (void)EVP_EncryptFinal_ex(ctx, buf, &outl);
return count;
}
@@ -1000,48 +802,27 @@ static int EVP_Update_loop_aead(void *args)
int outl, count;
unsigned char aad[13] = { 0xcc };
unsigned char faketag[16] = { 0xcc };
-#ifndef SIGALRM
- int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
-#endif
+
if (decrypt) {
- for (count = 0; COND(nb_iter); count++) {
- EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
- EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
- sizeof(faketag), faketag);
- EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad));
- EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
- EVP_DecryptFinal_ex(ctx, buf + outl, &outl);
+ for (count = 0; COND(c[D_EVP][testnum]); count++) {
+ (void)EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
+ (void)EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
+ sizeof(faketag), faketag);
+ (void)EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad));
+ (void)EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+ (void)EVP_DecryptFinal_ex(ctx, buf + outl, &outl);
}
} else {
- for (count = 0; COND(nb_iter); count++) {
- EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv);
- EVP_EncryptUpdate(ctx, NULL, &outl, aad, sizeof(aad));
- EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
- EVP_EncryptFinal_ex(ctx, buf + outl, &outl);
+ for (count = 0; COND(c[D_EVP][testnum]); count++) {
+ (void)EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv);
+ (void)EVP_EncryptUpdate(ctx, NULL, &outl, aad, sizeof(aad));
+ (void)EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+ (void)EVP_EncryptFinal_ex(ctx, buf + outl, &outl);
}
}
return count;
}
-static const EVP_MD *evp_md = NULL;
-static int EVP_Digest_loop(void *args)
-{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- unsigned char md[EVP_MAX_MD_SIZE];
- int count;
-#ifndef SIGALRM
- int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
-#endif
-
- for (count = 0; COND(nb_iter); count++) {
- if (!EVP_Digest(buf, lengths[testnum], md, NULL, evp_md, NULL))
- return -1;
- }
- return count;
-}
-
-#ifndef OPENSSL_NO_RSA
static long rsa_c[RSA_NUM][2]; /* # RSA iteration test */
static int RSA_sign_loop(void *args)
@@ -1049,12 +830,14 @@ static int RSA_sign_loop(void *args)
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char *buf2 = tempargs->buf2;
- unsigned int *rsa_num = &tempargs->siglen;
- RSA **rsa_key = tempargs->rsa_key;
+ size_t *rsa_num = &tempargs->sigsize;
+ EVP_PKEY_CTX **rsa_sign_ctx = tempargs->rsa_sign_ctx;
int ret, count;
+
for (count = 0; COND(rsa_c[testnum][0]); count++) {
- ret = RSA_sign(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[testnum]);
- if (ret == 0) {
+ *rsa_num = tempargs->buflen;
+ ret = EVP_PKEY_sign(rsa_sign_ctx[testnum], buf2, rsa_num, buf, 36);
+ if (ret <= 0) {
BIO_printf(bio_err, "RSA sign failure\n");
ERR_print_errors(bio_err);
count = -1;
@@ -1069,12 +852,12 @@ static int RSA_verify_loop(void *args)
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char *buf2 = tempargs->buf2;
- unsigned int rsa_num = tempargs->siglen;
- RSA **rsa_key = tempargs->rsa_key;
+ size_t rsa_num = tempargs->sigsize;
+ EVP_PKEY_CTX **rsa_verify_ctx = tempargs->rsa_verify_ctx;
int ret, count;
+
for (count = 0; COND(rsa_c[testnum][1]); count++) {
- ret =
- RSA_verify(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[testnum]);
+ ret = EVP_PKEY_verify(rsa_verify_ctx[testnum], buf2, rsa_num, buf, 36);
if (ret <= 0) {
BIO_printf(bio_err, "RSA verify failure\n");
ERR_print_errors(bio_err);
@@ -1084,21 +867,41 @@ static int RSA_verify_loop(void *args)
}
return count;
}
-#endif
-#ifndef OPENSSL_NO_DSA
+#ifndef OPENSSL_NO_DH
+static long ffdh_c[FFDH_NUM][1];
+
+static int FFDH_derive_key_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ EVP_PKEY_CTX *ffdh_ctx = tempargs->ffdh_ctx[testnum];
+ unsigned char *derived_secret = tempargs->secret_ff_a;
+ int count;
+
+ for (count = 0; COND(ffdh_c[testnum][0]); count++) {
+ /* outlen can be overwritten with a too small value (no padding used) */
+ size_t outlen = MAX_FFDH_SIZE;
+
+ EVP_PKEY_derive(ffdh_ctx, derived_secret, &outlen);
+ }
+ return count;
+}
+#endif /* OPENSSL_NO_DH */
+
static long dsa_c[DSA_NUM][2];
static int DSA_sign_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char *buf2 = tempargs->buf2;
- DSA **dsa_key = tempargs->dsa_key;
- unsigned int *siglen = &tempargs->siglen;
+ size_t *dsa_num = &tempargs->sigsize;
+ EVP_PKEY_CTX **dsa_sign_ctx = tempargs->dsa_sign_ctx;
int ret, count;
+
for (count = 0; COND(dsa_c[testnum][0]); count++) {
- ret = DSA_sign(0, buf, 20, buf2, siglen, dsa_key[testnum]);
- if (ret == 0) {
+ *dsa_num = tempargs->buflen;
+ ret = EVP_PKEY_sign(dsa_sign_ctx[testnum], buf2, dsa_num, buf, 20);
+ if (ret <= 0) {
BIO_printf(bio_err, "DSA sign failure\n");
ERR_print_errors(bio_err);
count = -1;
@@ -1113,11 +916,12 @@ static int DSA_verify_loop(void *args)
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char *buf2 = tempargs->buf2;
- DSA **dsa_key = tempargs->dsa_key;
- unsigned int siglen = tempargs->siglen;
+ size_t dsa_num = tempargs->sigsize;
+ EVP_PKEY_CTX **dsa_verify_ctx = tempargs->dsa_verify_ctx;
int ret, count;
+
for (count = 0; COND(dsa_c[testnum][1]); count++) {
- ret = DSA_verify(0, buf, 20, buf2, siglen, dsa_key[testnum]);
+ ret = EVP_PKEY_verify(dsa_verify_ctx[testnum], buf2, dsa_num, buf, 20);
if (ret <= 0) {
BIO_printf(bio_err, "DSA verify failure\n");
ERR_print_errors(bio_err);
@@ -1127,21 +931,21 @@ static int DSA_verify_loop(void *args)
}
return count;
}
-#endif
-#ifndef OPENSSL_NO_EC
static long ecdsa_c[ECDSA_NUM][2];
static int ECDSA_sign_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
- EC_KEY **ecdsa = tempargs->ecdsa;
- unsigned char *ecdsasig = tempargs->buf2;
- unsigned int *ecdsasiglen = &tempargs->siglen;
+ unsigned char *buf2 = tempargs->buf2;
+ size_t *ecdsa_num = &tempargs->sigsize;
+ EVP_PKEY_CTX **ecdsa_sign_ctx = tempargs->ecdsa_sign_ctx;
int ret, count;
+
for (count = 0; COND(ecdsa_c[testnum][0]); count++) {
- ret = ECDSA_sign(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[testnum]);
- if (ret == 0) {
+ *ecdsa_num = tempargs->buflen;
+ ret = EVP_PKEY_sign(ecdsa_sign_ctx[testnum], buf2, ecdsa_num, buf, 20);
+ if (ret <= 0) {
BIO_printf(bio_err, "ECDSA sign failure\n");
ERR_print_errors(bio_err);
count = -1;
@@ -1155,13 +959,15 @@ static int ECDSA_verify_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
- EC_KEY **ecdsa = tempargs->ecdsa;
- unsigned char *ecdsasig = tempargs->buf2;
- unsigned int ecdsasiglen = tempargs->siglen;
+ unsigned char *buf2 = tempargs->buf2;
+ size_t ecdsa_num = tempargs->sigsize;
+ EVP_PKEY_CTX **ecdsa_verify_ctx = tempargs->ecdsa_verify_ctx;
int ret, count;
+
for (count = 0; COND(ecdsa_c[testnum][1]); count++) {
- ret = ECDSA_verify(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[testnum]);
- if (ret != 1) {
+ ret = EVP_PKEY_verify(ecdsa_verify_ctx[testnum], buf2, ecdsa_num,
+ buf, 20);
+ if (ret <= 0) {
BIO_printf(bio_err, "ECDSA verify failure\n");
ERR_print_errors(bio_err);
count = -1;
@@ -1214,7 +1020,7 @@ static int EdDSA_verify_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
- EVP_MD_CTX **edctx = tempargs->eddsa_ctx;
+ EVP_MD_CTX **edctx = tempargs->eddsa_ctx2;
unsigned char *eddsasig = tempargs->buf2;
size_t eddsasigsize = tempargs->sigsize;
int ret, count;
@@ -1230,7 +1036,75 @@ static int EdDSA_verify_loop(void *args)
}
return count;
}
-#endif /* OPENSSL_NO_EC */
+
+#ifndef OPENSSL_NO_SM2
+static long sm2_c[SM2_NUM][2];
+static int SM2_sign_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ EVP_MD_CTX **sm2ctx = tempargs->sm2_ctx;
+ unsigned char *sm2sig = tempargs->buf2;
+ size_t sm2sigsize;
+ int ret, count;
+ EVP_PKEY **sm2_pkey = tempargs->sm2_pkey;
+ const size_t max_size = EVP_PKEY_get_size(sm2_pkey[testnum]);
+
+ for (count = 0; COND(sm2_c[testnum][0]); count++) {
+ sm2sigsize = max_size;
+
+ if (!EVP_DigestSignInit(sm2ctx[testnum], NULL, EVP_sm3(),
+ NULL, sm2_pkey[testnum])) {
+ BIO_printf(bio_err, "SM2 init sign failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ ret = EVP_DigestSign(sm2ctx[testnum], sm2sig, &sm2sigsize,
+ buf, 20);
+ if (ret == 0) {
+ BIO_printf(bio_err, "SM2 sign failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ /* update the latest returned size and always use the fixed buffer size */
+ tempargs->sigsize = sm2sigsize;
+ }
+
+ return count;
+}
+
+static int SM2_verify_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ EVP_MD_CTX **sm2ctx = tempargs->sm2_vfy_ctx;
+ unsigned char *sm2sig = tempargs->buf2;
+ size_t sm2sigsize = tempargs->sigsize;
+ int ret, count;
+ EVP_PKEY **sm2_pkey = tempargs->sm2_pkey;
+
+ for (count = 0; COND(sm2_c[testnum][1]); count++) {
+ if (!EVP_DigestVerifyInit(sm2ctx[testnum], NULL, EVP_sm3(),
+ NULL, sm2_pkey[testnum])) {
+ BIO_printf(bio_err, "SM2 verify init failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ ret = EVP_DigestVerify(sm2ctx[testnum], sm2sig, sm2sigsize,
+ buf, 20);
+ if (ret != 1) {
+ BIO_printf(bio_err, "SM2 verify failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ }
+ return count;
+}
+#endif /* OPENSSL_NO_SM2 */
static int run_benchmark(int async_jobs,
int (*loop_function) (void *), loopargs_t * loopargs)
@@ -1383,124 +1257,170 @@ static int run_benchmark(int async_jobs,
return error ? -1 : total_op_count;
}
+typedef struct ec_curve_st {
+ const char *name;
+ unsigned int nid;
+ unsigned int bits;
+ size_t sigsize; /* only used for EdDSA curves */
+} EC_CURVE;
+
+static EVP_PKEY *get_ecdsa(const EC_CURVE *curve)
+{
+ EVP_PKEY_CTX *kctx = NULL;
+ EVP_PKEY *key = NULL;
+
+ /* Ensure that the error queue is empty */
+ if (ERR_peek_error()) {
+ BIO_printf(bio_err,
+ "WARNING: the error queue contains previous unhandled errors.\n");
+ ERR_print_errors(bio_err);
+ }
+
+ /*
+ * Let's try to create a ctx directly from the NID: this works for
+ * curves like Curve25519 that are not implemented through the low
+ * level EC interface.
+ * If this fails we try creating a EVP_PKEY_EC generic param ctx,
+ * then we set the curve by NID before deriving the actual keygen
+ * ctx for that specific curve.
+ */
+ kctx = EVP_PKEY_CTX_new_id(curve->nid, NULL);
+ if (kctx == NULL) {
+ EVP_PKEY_CTX *pctx = NULL;
+ EVP_PKEY *params = NULL;
+ /*
+ * If we reach this code EVP_PKEY_CTX_new_id() failed and a
+ * "int_ctx_new:unsupported algorithm" error was added to the
+ * error queue.
+ * We remove it from the error queue as we are handling it.
+ */
+ unsigned long error = ERR_peek_error();
+
+ if (error == ERR_peek_last_error() /* oldest and latest errors match */
+ /* check that the error origin matches */
+ && ERR_GET_LIB(error) == ERR_LIB_EVP
+ && (ERR_GET_REASON(error) == EVP_R_UNSUPPORTED_ALGORITHM
+ || ERR_GET_REASON(error) == ERR_R_UNSUPPORTED))
+ ERR_get_error(); /* pop error from queue */
+ if (ERR_peek_error()) {
+ BIO_printf(bio_err,
+ "Unhandled error in the error queue during EC key setup.\n");
+ ERR_print_errors(bio_err);
+ return NULL;
+ }
+
+ /* Create the context for parameter generation */
+ if ((pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL
+ || EVP_PKEY_paramgen_init(pctx) <= 0
+ || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx,
+ curve->nid) <= 0
+ || EVP_PKEY_paramgen(pctx, &params) <= 0) {
+ BIO_printf(bio_err, "EC params init failure.\n");
+ ERR_print_errors(bio_err);
+ EVP_PKEY_CTX_free(pctx);
+ return NULL;
+ }
+ EVP_PKEY_CTX_free(pctx);
+
+ /* Create the context for the key generation */
+ kctx = EVP_PKEY_CTX_new(params, NULL);
+ EVP_PKEY_free(params);
+ }
+ if (kctx == NULL
+ || EVP_PKEY_keygen_init(kctx) <= 0
+ || EVP_PKEY_keygen(kctx, &key) <= 0) {
+ BIO_printf(bio_err, "EC key generation failure.\n");
+ ERR_print_errors(bio_err);
+ key = NULL;
+ }
+ EVP_PKEY_CTX_free(kctx);
+ return key;
+}
+
+#define stop_it(do_it, test_num)\
+ memset(do_it + test_num, 0, OSSL_NELEM(do_it) - test_num);
+
int speed_main(int argc, char **argv)
{
ENGINE *e = NULL;
loopargs_t *loopargs = NULL;
const char *prog;
const char *engine_id = NULL;
- const EVP_CIPHER *evp_cipher = NULL;
+ EVP_CIPHER *evp_cipher = NULL;
+ EVP_MAC *mac = NULL;
double d = 0.0;
OPTION_CHOICE o;
int async_init = 0, multiblock = 0, pr_header = 0;
- int doit[ALGOR_NUM] = { 0 };
+ uint8_t doit[ALGOR_NUM] = { 0 };
int ret = 1, misalign = 0, lengths_single = 0, aead = 0;
long count = 0;
- unsigned int size_num = OSSL_NELEM(lengths_list);
- unsigned int i, k, loop, loopargs_len = 0, async_jobs = 0;
+ unsigned int size_num = SIZE_NUM;
+ unsigned int i, k, loopargs_len = 0, async_jobs = 0;
int keylen;
int buflen;
+ BIGNUM *bn = NULL;
+ EVP_PKEY_CTX *genctx = NULL;
#ifndef NO_FORK
int multi = 0;
#endif
-#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) \
- || !defined(OPENSSL_NO_EC)
- long rsa_count = 1;
-#endif
+ long op_count = 1;
openssl_speed_sec_t seconds = { SECONDS, RSA_SECONDS, DSA_SECONDS,
ECDSA_SECONDS, ECDH_SECONDS,
- EdDSA_SECONDS };
+ EdDSA_SECONDS, SM2_SECONDS,
+ FFDH_SECONDS };
- /* What follows are the buffers and key material. */
-#ifndef OPENSSL_NO_RC5
- RC5_32_KEY rc5_ks;
-#endif
-#ifndef OPENSSL_NO_RC2
- RC2_KEY rc2_ks;
-#endif
-#ifndef OPENSSL_NO_IDEA
- IDEA_KEY_SCHEDULE idea_ks;
-#endif
-#ifndef OPENSSL_NO_SEED
- SEED_KEY_SCHEDULE seed_ks;
-#endif
-#ifndef OPENSSL_NO_BF
- BF_KEY bf_ks;
-#endif
-#ifndef OPENSSL_NO_CAST
- CAST_KEY cast_ks;
-#endif
- static const unsigned char key16[16] = {
- 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
- 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12
- };
- static const unsigned char key24[24] = {
- 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
- 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
- 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34
- };
static const unsigned char key32[32] = {
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56
};
-#ifndef OPENSSL_NO_CAMELLIA
- static const unsigned char ckey24[24] = {
- 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
- 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
- 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34
- };
- static const unsigned char ckey32[32] = {
- 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
- 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
- 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,
- 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56
- };
- CAMELLIA_KEY camellia_ks1, camellia_ks2, camellia_ks3;
-#endif
-#ifndef OPENSSL_NO_DES
- static DES_cblock key = {
- 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0
- };
- static DES_cblock key2 = {
- 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12
- };
- static DES_cblock key3 = {
- 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34
- };
-#endif
-#ifndef OPENSSL_NO_RSA
- static const unsigned int rsa_bits[RSA_NUM] = {
- 512, 1024, 2048, 3072, 4096, 7680, 15360
- };
- static const unsigned char *rsa_data[RSA_NUM] = {
- test512, test1024, test2048, test3072, test4096, test7680, test15360
+ static const unsigned char deskey[] = {
+ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, /* key1 */
+ 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, /* key2 */
+ 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34 /* key3 */
};
- static const int rsa_data_length[RSA_NUM] = {
- sizeof(test512), sizeof(test1024),
- sizeof(test2048), sizeof(test3072),
- sizeof(test4096), sizeof(test7680),
- sizeof(test15360)
+ static const struct {
+ const unsigned char *data;
+ unsigned int length;
+ unsigned int bits;
+ } rsa_keys[] = {
+ { test512, sizeof(test512), 512 },
+ { test1024, sizeof(test1024), 1024 },
+ { test2048, sizeof(test2048), 2048 },
+ { test3072, sizeof(test3072), 3072 },
+ { test4096, sizeof(test4096), 4096 },
+ { test7680, sizeof(test7680), 7680 },
+ { test15360, sizeof(test15360), 15360 }
};
- int rsa_doit[RSA_NUM] = { 0 };
+ uint8_t rsa_doit[RSA_NUM] = { 0 };
int primes = RSA_DEFAULT_PRIME_NUM;
-#endif
-#ifndef OPENSSL_NO_DSA
+#ifndef OPENSSL_NO_DH
+ typedef struct ffdh_params_st {
+ const char *name;
+ unsigned int nid;
+ unsigned int bits;
+ } FFDH_PARAMS;
+
+ static const FFDH_PARAMS ffdh_params[FFDH_NUM] = {
+ {"ffdh2048", NID_ffdhe2048, 2048},
+ {"ffdh3072", NID_ffdhe3072, 3072},
+ {"ffdh4096", NID_ffdhe4096, 4096},
+ {"ffdh6144", NID_ffdhe6144, 6144},
+ {"ffdh8192", NID_ffdhe8192, 8192}
+ };
+ uint8_t ffdh_doit[FFDH_NUM] = { 0 };
+
+#endif /* OPENSSL_NO_DH */
static const unsigned int dsa_bits[DSA_NUM] = { 512, 1024, 2048 };
- int dsa_doit[DSA_NUM] = { 0 };
-#endif
-#ifndef OPENSSL_NO_EC
+ uint8_t dsa_doit[DSA_NUM] = { 0 };
/*
* We only test over the following curves as they are representative, To
* add tests over more curves, simply add the curve NID and curve name to
- * the following arrays and increase the |ecdh_choices| list accordingly.
+ * the following arrays and increase the |ecdh_choices| and |ecdsa_choices|
+ * lists accordingly.
*/
- static const struct {
- const char *name;
- unsigned int nid;
- unsigned int bits;
- } test_curves[] = {
+ static const EC_CURVE ec_curves[EC_NUM] = {
/* Prime Curves */
{"secp160r1", NID_secp160r1, 160},
{"nistp192", NID_X9_62_prime192v1, 192},
@@ -1508,7 +1428,7 @@ int speed_main(int argc, char **argv)
{"nistp256", NID_X9_62_prime256v1, 256},
{"nistp384", NID_secp384r1, 384},
{"nistp521", NID_secp521r1, 521},
-# ifndef OPENSSL_NO_EC2M
+#ifndef OPENSSL_NO_EC2M
/* Binary Curves */
{"nistk163", NID_sect163k1, 163},
{"nistk233", NID_sect233k1, 233},
@@ -1520,7 +1440,7 @@ int speed_main(int argc, char **argv)
{"nistb283", NID_sect283r1, 283},
{"nistb409", NID_sect409r1, 409},
{"nistb571", NID_sect571r1, 571},
-# endif
+#endif
{"brainpoolP256r1", NID_brainpoolP256r1, 256},
{"brainpoolP256t1", NID_brainpoolP256t1, 256},
{"brainpoolP384r1", NID_brainpoolP384r1, 384},
@@ -1531,22 +1451,36 @@ int speed_main(int argc, char **argv)
{"X25519", NID_X25519, 253},
{"X448", NID_X448, 448}
};
- static const struct {
- const char *name;
- unsigned int nid;
- unsigned int bits;
- size_t sigsize;
- } test_ed_curves[] = {
+ static const EC_CURVE ed_curves[EdDSA_NUM] = {
/* EdDSA */
{"Ed25519", NID_ED25519, 253, 64},
{"Ed448", NID_ED448, 456, 114}
};
- int ecdsa_doit[ECDSA_NUM] = { 0 };
- int ecdh_doit[EC_NUM] = { 0 };
- int eddsa_doit[EdDSA_NUM] = { 0 };
- OPENSSL_assert(OSSL_NELEM(test_curves) >= EC_NUM);
- OPENSSL_assert(OSSL_NELEM(test_ed_curves) >= EdDSA_NUM);
-#endif /* ndef OPENSSL_NO_EC */
+#ifndef OPENSSL_NO_SM2
+ static const EC_CURVE sm2_curves[SM2_NUM] = {
+ /* SM2 */
+ {"CurveSM2", NID_sm2, 256}
+ };
+ uint8_t sm2_doit[SM2_NUM] = { 0 };
+#endif
+ uint8_t ecdsa_doit[ECDSA_NUM] = { 0 };
+ uint8_t ecdh_doit[EC_NUM] = { 0 };
+ uint8_t eddsa_doit[EdDSA_NUM] = { 0 };
+
+ /* checks declarated curves against choices list. */
+ OPENSSL_assert(ed_curves[EdDSA_NUM - 1].nid == NID_ED448);
+ OPENSSL_assert(strcmp(eddsa_choices[EdDSA_NUM - 1].name, "ed448") == 0);
+
+ OPENSSL_assert(ec_curves[EC_NUM - 1].nid == NID_X448);
+ OPENSSL_assert(strcmp(ecdh_choices[EC_NUM - 1].name, "ecdhx448") == 0);
+
+ OPENSSL_assert(ec_curves[ECDSA_NUM - 1].nid == NID_brainpoolP512t1);
+ OPENSSL_assert(strcmp(ecdsa_choices[ECDSA_NUM - 1].name, "ecdsabrp512t1") == 0);
+
+#ifndef OPENSSL_NO_SM2
+ OPENSSL_assert(sm2_curves[SM2_NUM - 1].nid == NID_sm2);
+ OPENSSL_assert(strcmp(sm2_choices[SM2_NUM - 1].name, "curveSM2") == 0);
+#endif
prog = opt_init(argc, argv, speed_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -1564,18 +1498,43 @@ int speed_main(int argc, char **argv)
usertime = 0;
break;
case OPT_EVP:
- evp_md = NULL;
- evp_cipher = EVP_get_cipherbyname(opt_arg());
- if (evp_cipher == NULL)
- evp_md = EVP_get_digestbyname(opt_arg());
- if (evp_cipher == NULL && evp_md == NULL) {
+ if (doit[D_EVP]) {
+ BIO_printf(bio_err, "%s: -evp option cannot be used more than once\n", prog);
+ goto opterr;
+ }
+ ERR_set_mark();
+ if (!opt_cipher_silent(opt_arg(), &evp_cipher)) {
+ if (have_md(opt_arg()))
+ evp_md_name = opt_arg();
+ }
+ if (evp_cipher == NULL && evp_md_name == NULL) {
+ ERR_clear_last_mark();
BIO_printf(bio_err,
"%s: %s is an unknown cipher or digest\n",
prog, opt_arg());
goto end;
}
+ ERR_pop_to_mark();
doit[D_EVP] = 1;
break;
+ case OPT_HMAC:
+ if (!have_md(opt_arg())) {
+ BIO_printf(bio_err, "%s: %s is an unknown digest\n",
+ prog, opt_arg());
+ goto end;
+ }
+ evp_mac_mdname = opt_arg();
+ doit[D_HMAC] = 1;
+ break;
+ case OPT_CMAC:
+ if (!have_cipher(opt_arg())) {
+ BIO_printf(bio_err, "%s: %s is an unknown cipher\n",
+ prog, opt_arg());
+ goto end;
+ }
+ evp_mac_ciphername = opt_arg();
+ doit[D_EVP_CMAC] = 1;
+ break;
case OPT_DECRYPT:
decrypt = 1;
break;
@@ -1590,7 +1549,7 @@ int speed_main(int argc, char **argv)
case OPT_MULTI:
#ifndef NO_FORK
multi = atoi(opt_arg());
- if (multi >= INT_MAX / (int)sizeof(int)) {
+ if ((size_t)multi >= SIZE_MAX / sizeof(int)) {
BIO_printf(bio_err, "%s: multi argument too large\n", prog);
return 0;
}
@@ -1612,8 +1571,7 @@ int speed_main(int argc, char **argv)
#endif
break;
case OPT_MISALIGN:
- if (!opt_int(opt_arg(), &misalign))
- goto end;
+ misalign = opt_int_arg();
if (misalign > MISALIGN) {
BIO_printf(bio_err,
"%s: Maximum offset is %d\n", prog, MISALIGN);
@@ -1636,13 +1594,17 @@ int speed_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
- case OPT_PRIMES:
- if (!opt_int(opt_arg(), &primes))
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
goto end;
break;
+ case OPT_PRIMES:
+ primes = opt_int_arg();
+ break;
case OPT_SECONDS:
seconds.sym = seconds.rsa = seconds.dsa = seconds.ecdsa
- = seconds.ecdh = seconds.eddsa = atoi(opt_arg());
+ = seconds.ecdh = seconds.eddsa
+ = seconds.sm2 = seconds.ffdh = atoi(opt_arg());
break;
case OPT_BYTES:
lengths_single = atoi(opt_arg());
@@ -1654,89 +1616,112 @@ int speed_main(int argc, char **argv)
break;
}
}
+
+ /* Remaining arguments are algorithms. */
argc = opt_num_rest();
argv = opt_rest();
- /* Remaining arguments are algorithms. */
+ if (!app_RAND_load())
+ goto end;
+
for (; *argv; argv++) {
- if (found(*argv, doit_choices, &i)) {
+ const char *algo = *argv;
+
+ if (opt_found(algo, doit_choices, &i)) {
doit[i] = 1;
continue;
}
-#ifndef OPENSSL_NO_DES
- if (strcmp(*argv, "des") == 0) {
+ if (strcmp(algo, "des") == 0) {
doit[D_CBC_DES] = doit[D_EDE3_DES] = 1;
continue;
}
-#endif
- if (strcmp(*argv, "sha") == 0) {
+ if (strcmp(algo, "sha") == 0) {
doit[D_SHA1] = doit[D_SHA256] = doit[D_SHA512] = 1;
continue;
}
-#ifndef OPENSSL_NO_RSA
- if (strcmp(*argv, "openssl") == 0)
- continue;
- if (strcmp(*argv, "rsa") == 0) {
- for (loop = 0; loop < OSSL_NELEM(rsa_doit); loop++)
- rsa_doit[loop] = 1;
- continue;
- }
- if (found(*argv, rsa_choices, &i)) {
- rsa_doit[i] = 1;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (strcmp(algo, "openssl") == 0) /* just for compatibility */
continue;
- }
#endif
-#ifndef OPENSSL_NO_DSA
- if (strcmp(*argv, "dsa") == 0) {
- dsa_doit[R_DSA_512] = dsa_doit[R_DSA_1024] =
- dsa_doit[R_DSA_2048] = 1;
- continue;
+ if (strncmp(algo, "rsa", 3) == 0) {
+ if (algo[3] == '\0') {
+ memset(rsa_doit, 1, sizeof(rsa_doit));
+ continue;
+ }
+ if (opt_found(algo, rsa_choices, &i)) {
+ rsa_doit[i] = 1;
+ continue;
+ }
}
- if (found(*argv, dsa_choices, &i)) {
- dsa_doit[i] = 2;
- continue;
+#ifndef OPENSSL_NO_DH
+ if (strncmp(algo, "ffdh", 4) == 0) {
+ if (algo[4] == '\0') {
+ memset(ffdh_doit, 1, sizeof(ffdh_doit));
+ continue;
+ }
+ if (opt_found(algo, ffdh_choices, &i)) {
+ ffdh_doit[i] = 2;
+ continue;
+ }
}
#endif
- if (strcmp(*argv, "aes") == 0) {
+ if (strncmp(algo, "dsa", 3) == 0) {
+ if (algo[3] == '\0') {
+ memset(dsa_doit, 1, sizeof(dsa_doit));
+ continue;
+ }
+ if (opt_found(algo, dsa_choices, &i)) {
+ dsa_doit[i] = 2;
+ continue;
+ }
+ }
+ if (strcmp(algo, "aes") == 0) {
doit[D_CBC_128_AES] = doit[D_CBC_192_AES] = doit[D_CBC_256_AES] = 1;
continue;
}
-#ifndef OPENSSL_NO_CAMELLIA
- if (strcmp(*argv, "camellia") == 0) {
+ if (strcmp(algo, "camellia") == 0) {
doit[D_CBC_128_CML] = doit[D_CBC_192_CML] = doit[D_CBC_256_CML] = 1;
continue;
}
-#endif
-#ifndef OPENSSL_NO_EC
- if (strcmp(*argv, "ecdsa") == 0) {
- for (loop = 0; loop < OSSL_NELEM(ecdsa_doit); loop++)
- ecdsa_doit[loop] = 1;
- continue;
+ if (strncmp(algo, "ecdsa", 5) == 0) {
+ if (algo[5] == '\0') {
+ memset(ecdsa_doit, 1, sizeof(ecdsa_doit));
+ continue;
+ }
+ if (opt_found(algo, ecdsa_choices, &i)) {
+ ecdsa_doit[i] = 2;
+ continue;
+ }
}
- if (found(*argv, ecdsa_choices, &i)) {
- ecdsa_doit[i] = 2;
- continue;
+ if (strncmp(algo, "ecdh", 4) == 0) {
+ if (algo[4] == '\0') {
+ memset(ecdh_doit, 1, sizeof(ecdh_doit));
+ continue;
+ }
+ if (opt_found(algo, ecdh_choices, &i)) {
+ ecdh_doit[i] = 2;
+ continue;
+ }
}
- if (strcmp(*argv, "ecdh") == 0) {
- for (loop = 0; loop < OSSL_NELEM(ecdh_doit); loop++)
- ecdh_doit[loop] = 1;
+ if (strcmp(algo, "eddsa") == 0) {
+ memset(eddsa_doit, 1, sizeof(eddsa_doit));
continue;
}
- if (found(*argv, ecdh_choices, &i)) {
- ecdh_doit[i] = 2;
+ if (opt_found(algo, eddsa_choices, &i)) {
+ eddsa_doit[i] = 2;
continue;
}
- if (strcmp(*argv, "eddsa") == 0) {
- for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++)
- eddsa_doit[loop] = 1;
+#ifndef OPENSSL_NO_SM2
+ if (strcmp(algo, "sm2") == 0) {
+ memset(sm2_doit, 1, sizeof(sm2_doit));
continue;
}
- if (found(*argv, eddsa_choices, &i)) {
- eddsa_doit[i] = 2;
+ if (opt_found(algo, sm2_choices, &i)) {
+ sm2_doit[i] = 2;
continue;
}
#endif
- BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, *argv);
+ BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, algo);
goto end;
}
@@ -1745,22 +1730,22 @@ int speed_main(int argc, char **argv)
if (evp_cipher == NULL) {
BIO_printf(bio_err, "-aead can be used only with an AEAD cipher\n");
goto end;
- } else if (!(EVP_CIPHER_flags(evp_cipher) &
+ } else if (!(EVP_CIPHER_get_flags(evp_cipher) &
EVP_CIPH_FLAG_AEAD_CIPHER)) {
BIO_printf(bio_err, "%s is not an AEAD cipher\n",
- OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher)));
+ EVP_CIPHER_get0_name(evp_cipher));
goto end;
}
}
if (multiblock) {
if (evp_cipher == NULL) {
- BIO_printf(bio_err,"-mb can be used only with a multi-block"
- " capable cipher\n");
+ BIO_printf(bio_err, "-mb can be used only with a multi-block"
+ " capable cipher\n");
goto end;
- } else if (!(EVP_CIPHER_flags(evp_cipher) &
+ } else if (!(EVP_CIPHER_get_flags(evp_cipher) &
EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) {
BIO_printf(bio_err, "%s is not a multi-block capable\n",
- OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher)));
+ EVP_CIPHER_get0_name(evp_cipher));
goto end;
} else if (async_jobs > 0) {
BIO_printf(bio_err, "Async mode is not supported with -mb");
@@ -1794,6 +1779,10 @@ int speed_main(int argc, char **argv)
buflen = lengths[size_num - 1];
if (buflen < 36) /* size of random vector in RSA benchmark */
buflen = 36;
+ if (INT_MAX - (MAX_MISALIGNMENT + 1) < buflen) {
+ BIO_printf(bio_err, "Error: buffer size too large\n");
+ goto end;
+ }
buflen += MAX_MISALIGNMENT + 1;
loopargs[i].buf_malloc = app_malloc(buflen, "input buffer");
loopargs[i].buf2_malloc = app_malloc(buflen, "input buffer");
@@ -1803,9 +1792,13 @@ int speed_main(int argc, char **argv)
/* Align the start of buffers on a 64 byte boundary */
loopargs[i].buf = loopargs[i].buf_malloc + misalign;
loopargs[i].buf2 = loopargs[i].buf2_malloc + misalign;
-#ifndef OPENSSL_NO_EC
+ loopargs[i].buflen = buflen - misalign;
+ loopargs[i].sigsize = buflen - misalign;
loopargs[i].secret_a = app_malloc(MAX_ECDH_SIZE, "ECDH secret a");
loopargs[i].secret_b = app_malloc(MAX_ECDH_SIZE, "ECDH secret b");
+#ifndef OPENSSL_NO_DH
+ loopargs[i].secret_ff_a = app_malloc(MAX_FFDH_SIZE, "FFDH secret a");
+ loopargs[i].secret_ff_b = app_malloc(MAX_FFDH_SIZE, "FFDH secret b");
#endif
}
@@ -1818,25 +1811,43 @@ int speed_main(int argc, char **argv)
e = setup_engine(engine_id, 0);
/* No parameters; turn on everything. */
- if ((argc == 0) && !doit[D_EVP]) {
- for (i = 0; i < ALGOR_NUM; i++)
- if (i != D_EVP)
- doit[i] = 1;
-#ifndef OPENSSL_NO_RSA
- for (i = 0; i < RSA_NUM; i++)
- rsa_doit[i] = 1;
-#endif
-#ifndef OPENSSL_NO_DSA
- for (i = 0; i < DSA_NUM; i++)
- dsa_doit[i] = 1;
+ if (argc == 0 && !doit[D_EVP] && !doit[D_HMAC] && !doit[D_EVP_CMAC]) {
+ memset(doit, 1, sizeof(doit));
+ doit[D_EVP] = doit[D_EVP_CMAC] = 0;
+ ERR_set_mark();
+ for (i = D_MD2; i <= D_WHIRLPOOL; i++) {
+ if (!have_md(names[i]))
+ doit[i] = 0;
+ }
+ for (i = D_CBC_DES; i <= D_CBC_256_CML; i++) {
+ if (!have_cipher(names[i]))
+ doit[i] = 0;
+ }
+ if ((mac = EVP_MAC_fetch(app_get0_libctx(), "GMAC",
+ app_get0_propq())) != NULL) {
+ EVP_MAC_free(mac);
+ mac = NULL;
+ } else {
+ doit[D_GHASH] = 0;
+ }
+ if ((mac = EVP_MAC_fetch(app_get0_libctx(), "HMAC",
+ app_get0_propq())) != NULL) {
+ EVP_MAC_free(mac);
+ mac = NULL;
+ } else {
+ doit[D_HMAC] = 0;
+ }
+ ERR_pop_to_mark();
+ memset(rsa_doit, 1, sizeof(rsa_doit));
+#ifndef OPENSSL_NO_DH
+ memset(ffdh_doit, 1, sizeof(ffdh_doit));
#endif
-#ifndef OPENSSL_NO_EC
- for (loop = 0; loop < OSSL_NELEM(ecdsa_doit); loop++)
- ecdsa_doit[loop] = 1;
- for (loop = 0; loop < OSSL_NELEM(ecdh_doit); loop++)
- ecdh_doit[loop] = 1;
- for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++)
- eddsa_doit[loop] = 1;
+ memset(dsa_doit, 1, sizeof(dsa_doit));
+ memset(ecdsa_doit, 1, sizeof(ecdsa_doit));
+ memset(ecdh_doit, 1, sizeof(ecdh_doit));
+ memset(eddsa_doit, 1, sizeof(eddsa_doit));
+#ifndef OPENSSL_NO_SM2
+ memset(sm2_doit, 1, sizeof(sm2_doit));
#endif
}
for (i = 0; i < ALGOR_NUM; i++)
@@ -1848,308 +1859,10 @@ int speed_main(int argc, char **argv)
"You have chosen to measure elapsed time "
"instead of user CPU time.\n");
-#ifndef OPENSSL_NO_RSA
- for (i = 0; i < loopargs_len; i++) {
- if (primes > RSA_DEFAULT_PRIME_NUM) {
- /* for multi-prime RSA, skip this */
- break;
- }
- for (k = 0; k < RSA_NUM; k++) {
- const unsigned char *p;
-
- p = rsa_data[k];
- loopargs[i].rsa_key[k] =
- d2i_RSAPrivateKey(NULL, &p, rsa_data_length[k]);
- if (loopargs[i].rsa_key[k] == NULL) {
- BIO_printf(bio_err,
- "internal error loading RSA key number %d\n", k);
- goto end;
- }
- }
- }
-#endif
-#ifndef OPENSSL_NO_DSA
- for (i = 0; i < loopargs_len; i++) {
- loopargs[i].dsa_key[0] = get_dsa(512);
- loopargs[i].dsa_key[1] = get_dsa(1024);
- loopargs[i].dsa_key[2] = get_dsa(2048);
- }
-#endif
-#ifndef OPENSSL_NO_DES
- DES_set_key_unchecked(&key, &sch);
- DES_set_key_unchecked(&key2, &sch2);
- DES_set_key_unchecked(&key3, &sch3);
-#endif
- AES_set_encrypt_key(key16, 128, &aes_ks1);
- AES_set_encrypt_key(key24, 192, &aes_ks2);
- AES_set_encrypt_key(key32, 256, &aes_ks3);
-#ifndef OPENSSL_NO_CAMELLIA
- Camellia_set_key(key16, 128, &camellia_ks1);
- Camellia_set_key(ckey24, 192, &camellia_ks2);
- Camellia_set_key(ckey32, 256, &camellia_ks3);
-#endif
-#ifndef OPENSSL_NO_IDEA
- IDEA_set_encrypt_key(key16, &idea_ks);
-#endif
-#ifndef OPENSSL_NO_SEED
- SEED_set_key(key16, &seed_ks);
-#endif
-#ifndef OPENSSL_NO_RC4
- RC4_set_key(&rc4_ks, 16, key16);
-#endif
-#ifndef OPENSSL_NO_RC2
- RC2_set_key(&rc2_ks, 16, key16, 128);
-#endif
-#ifndef OPENSSL_NO_RC5
- RC5_32_set_key(&rc5_ks, 16, key16, 12);
-#endif
-#ifndef OPENSSL_NO_BF
- BF_set_key(&bf_ks, 16, key16);
-#endif
-#ifndef OPENSSL_NO_CAST
- CAST_set_key(&cast_ks, 16, key16);
-#endif
-#ifndef SIGALRM
-# ifndef OPENSSL_NO_DES
- BIO_printf(bio_err, "First we calculate the approximate speed ...\n");
- count = 10;
- do {
- long it;
- count *= 2;
- Time_F(START);
- for (it = count; it; it--)
- DES_ecb_encrypt((DES_cblock *)loopargs[0].buf,
- (DES_cblock *)loopargs[0].buf, &sch, DES_ENCRYPT);
- d = Time_F(STOP);
- } while (d < 3);
- save_count = count;
- c[D_MD2][0] = count / 10;
- c[D_MDC2][0] = count / 10;
- c[D_MD4][0] = count;
- c[D_MD5][0] = count;
- c[D_HMAC][0] = count;
- c[D_SHA1][0] = count;
- c[D_RMD160][0] = count;
- c[D_RC4][0] = count * 5;
- c[D_CBC_DES][0] = count;
- c[D_EDE3_DES][0] = count / 3;
- c[D_CBC_IDEA][0] = count;
- c[D_CBC_SEED][0] = count;
- c[D_CBC_RC2][0] = count;
- c[D_CBC_RC5][0] = count;
- c[D_CBC_BF][0] = count;
- c[D_CBC_CAST][0] = count;
- c[D_CBC_128_AES][0] = count;
- c[D_CBC_192_AES][0] = count;
- c[D_CBC_256_AES][0] = count;
- c[D_CBC_128_CML][0] = count;
- c[D_CBC_192_CML][0] = count;
- c[D_CBC_256_CML][0] = count;
- c[D_SHA256][0] = count;
- c[D_SHA512][0] = count;
- c[D_WHIRLPOOL][0] = count;
- c[D_IGE_128_AES][0] = count;
- c[D_IGE_192_AES][0] = count;
- c[D_IGE_256_AES][0] = count;
- c[D_GHASH][0] = count;
- c[D_RAND][0] = count;
-
- for (i = 1; i < size_num; i++) {
- long l0, l1;
-
- l0 = (long)lengths[0];
- l1 = (long)lengths[i];
-
- c[D_MD2][i] = c[D_MD2][0] * 4 * l0 / l1;
- c[D_MDC2][i] = c[D_MDC2][0] * 4 * l0 / l1;
- c[D_MD4][i] = c[D_MD4][0] * 4 * l0 / l1;
- c[D_MD5][i] = c[D_MD5][0] * 4 * l0 / l1;
- c[D_HMAC][i] = c[D_HMAC][0] * 4 * l0 / l1;
- c[D_SHA1][i] = c[D_SHA1][0] * 4 * l0 / l1;
- c[D_RMD160][i] = c[D_RMD160][0] * 4 * l0 / l1;
- c[D_SHA256][i] = c[D_SHA256][0] * 4 * l0 / l1;
- c[D_SHA512][i] = c[D_SHA512][0] * 4 * l0 / l1;
- c[D_WHIRLPOOL][i] = c[D_WHIRLPOOL][0] * 4 * l0 / l1;
- c[D_GHASH][i] = c[D_GHASH][0] * 4 * l0 / l1;
- c[D_RAND][i] = c[D_RAND][0] * 4 * l0 / l1;
-
- l0 = (long)lengths[i - 1];
-
- c[D_RC4][i] = c[D_RC4][i - 1] * l0 / l1;
- c[D_CBC_DES][i] = c[D_CBC_DES][i - 1] * l0 / l1;
- c[D_EDE3_DES][i] = c[D_EDE3_DES][i - 1] * l0 / l1;
- c[D_CBC_IDEA][i] = c[D_CBC_IDEA][i - 1] * l0 / l1;
- c[D_CBC_SEED][i] = c[D_CBC_SEED][i - 1] * l0 / l1;
- c[D_CBC_RC2][i] = c[D_CBC_RC2][i - 1] * l0 / l1;
- c[D_CBC_RC5][i] = c[D_CBC_RC5][i - 1] * l0 / l1;
- c[D_CBC_BF][i] = c[D_CBC_BF][i - 1] * l0 / l1;
- c[D_CBC_CAST][i] = c[D_CBC_CAST][i - 1] * l0 / l1;
- c[D_CBC_128_AES][i] = c[D_CBC_128_AES][i - 1] * l0 / l1;
- c[D_CBC_192_AES][i] = c[D_CBC_192_AES][i - 1] * l0 / l1;
- c[D_CBC_256_AES][i] = c[D_CBC_256_AES][i - 1] * l0 / l1;
- c[D_CBC_128_CML][i] = c[D_CBC_128_CML][i - 1] * l0 / l1;
- c[D_CBC_192_CML][i] = c[D_CBC_192_CML][i - 1] * l0 / l1;
- c[D_CBC_256_CML][i] = c[D_CBC_256_CML][i - 1] * l0 / l1;
- c[D_IGE_128_AES][i] = c[D_IGE_128_AES][i - 1] * l0 / l1;
- c[D_IGE_192_AES][i] = c[D_IGE_192_AES][i - 1] * l0 / l1;
- c[D_IGE_256_AES][i] = c[D_IGE_256_AES][i - 1] * l0 / l1;
- }
-
-# ifndef OPENSSL_NO_RSA
- rsa_c[R_RSA_512][0] = count / 2000;
- rsa_c[R_RSA_512][1] = count / 400;
- for (i = 1; i < RSA_NUM; i++) {
- rsa_c[i][0] = rsa_c[i - 1][0] / 8;
- rsa_c[i][1] = rsa_c[i - 1][1] / 4;
- if (rsa_doit[i] <= 1 && rsa_c[i][0] == 0)
- rsa_doit[i] = 0;
- else {
- if (rsa_c[i][0] == 0) {
- rsa_c[i][0] = 1; /* Set minimum iteration Nb to 1. */
- rsa_c[i][1] = 20;
- }
- }
- }
-# endif
-
-# ifndef OPENSSL_NO_DSA
- dsa_c[R_DSA_512][0] = count / 1000;
- dsa_c[R_DSA_512][1] = count / 1000 / 2;
- for (i = 1; i < DSA_NUM; i++) {
- dsa_c[i][0] = dsa_c[i - 1][0] / 4;
- dsa_c[i][1] = dsa_c[i - 1][1] / 4;
- if (dsa_doit[i] <= 1 && dsa_c[i][0] == 0)
- dsa_doit[i] = 0;
- else {
- if (dsa_c[i][0] == 0) {
- dsa_c[i][0] = 1; /* Set minimum iteration Nb to 1. */
- dsa_c[i][1] = 1;
- }
- }
- }
-# endif
-
-# ifndef OPENSSL_NO_EC
- ecdsa_c[R_EC_P160][0] = count / 1000;
- ecdsa_c[R_EC_P160][1] = count / 1000 / 2;
- for (i = R_EC_P192; i <= R_EC_P521; i++) {
- ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2;
- ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2;
- if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0)
- ecdsa_doit[i] = 0;
- else {
- if (ecdsa_c[i][0] == 0) {
- ecdsa_c[i][0] = 1;
- ecdsa_c[i][1] = 1;
- }
- }
- }
-# ifndef OPENSSL_NO_EC2M
- ecdsa_c[R_EC_K163][0] = count / 1000;
- ecdsa_c[R_EC_K163][1] = count / 1000 / 2;
- for (i = R_EC_K233; i <= R_EC_K571; i++) {
- ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2;
- ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2;
- if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0)
- ecdsa_doit[i] = 0;
- else {
- if (ecdsa_c[i][0] == 0) {
- ecdsa_c[i][0] = 1;
- ecdsa_c[i][1] = 1;
- }
- }
- }
- ecdsa_c[R_EC_B163][0] = count / 1000;
- ecdsa_c[R_EC_B163][1] = count / 1000 / 2;
- for (i = R_EC_B233; i <= R_EC_B571; i++) {
- ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2;
- ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2;
- if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0)
- ecdsa_doit[i] = 0;
- else {
- if (ecdsa_c[i][0] == 0) {
- ecdsa_c[i][0] = 1;
- ecdsa_c[i][1] = 1;
- }
- }
- }
-# endif
-
- ecdh_c[R_EC_P160][0] = count / 1000;
- for (i = R_EC_P192; i <= R_EC_P521; i++) {
- ecdh_c[i][0] = ecdh_c[i - 1][0] / 2;
- if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
- ecdh_doit[i] = 0;
- else {
- if (ecdh_c[i][0] == 0) {
- ecdh_c[i][0] = 1;
- }
- }
- }
-# ifndef OPENSSL_NO_EC2M
- ecdh_c[R_EC_K163][0] = count / 1000;
- for (i = R_EC_K233; i <= R_EC_K571; i++) {
- ecdh_c[i][0] = ecdh_c[i - 1][0] / 2;
- if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
- ecdh_doit[i] = 0;
- else {
- if (ecdh_c[i][0] == 0) {
- ecdh_c[i][0] = 1;
- }
- }
- }
- ecdh_c[R_EC_B163][0] = count / 1000;
- for (i = R_EC_B233; i <= R_EC_B571; i++) {
- ecdh_c[i][0] = ecdh_c[i - 1][0] / 2;
- if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
- ecdh_doit[i] = 0;
- else {
- if (ecdh_c[i][0] == 0) {
- ecdh_c[i][0] = 1;
- }
- }
- }
-# endif
- /* repeated code good to factorize */
- ecdh_c[R_EC_BRP256R1][0] = count / 1000;
- for (i = R_EC_BRP384R1; i <= R_EC_BRP512R1; i += 2) {
- ecdh_c[i][0] = ecdh_c[i - 2][0] / 2;
- if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
- ecdh_doit[i] = 0;
- else {
- if (ecdh_c[i][0] == 0) {
- ecdh_c[i][0] = 1;
- }
- }
- }
- ecdh_c[R_EC_BRP256T1][0] = count / 1000;
- for (i = R_EC_BRP384T1; i <= R_EC_BRP512T1; i += 2) {
- ecdh_c[i][0] = ecdh_c[i - 2][0] / 2;
- if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
- ecdh_doit[i] = 0;
- else {
- if (ecdh_c[i][0] == 0) {
- ecdh_c[i][0] = 1;
- }
- }
- }
- /* default iteration count for the last two EC Curves */
- ecdh_c[R_EC_X25519][0] = count / 1800;
- ecdh_c[R_EC_X448][0] = count / 7200;
-
- eddsa_c[R_EC_Ed25519][0] = count / 1800;
- eddsa_c[R_EC_Ed448][0] = count / 7200;
-# endif
-
-# else
-/* not worth fixing */
-# error "You cannot disable DES on systems without SIGALRM."
-# endif /* OPENSSL_NO_DES */
-#elif SIGALRM > 0
+#if SIGALRM > 0
signal(SIGALRM, alarmed);
-#endif /* SIGALRM */
+#endif
-#ifndef OPENSSL_NO_MD2
if (doit[D_MD2]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_MD2], c[D_MD2][testnum], lengths[testnum],
@@ -2158,10 +1871,11 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, EVP_Digest_MD2_loop, loopargs);
d = Time_F(STOP);
print_result(D_MD2, testnum, count, d);
+ if (count < 0)
+ break;
}
}
-#endif
-#ifndef OPENSSL_NO_MDC2
+
if (doit[D_MDC2]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_MDC2], c[D_MDC2][testnum], lengths[testnum],
@@ -2170,11 +1884,11 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, EVP_Digest_MDC2_loop, loopargs);
d = Time_F(STOP);
print_result(D_MDC2, testnum, count, d);
+ if (count < 0)
+ break;
}
}
-#endif
-#ifndef OPENSSL_NO_MD4
if (doit[D_MD4]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_MD4], c[D_MD4][testnum], lengths[testnum],
@@ -2183,11 +1897,11 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, EVP_Digest_MD4_loop, loopargs);
d = Time_F(STOP);
print_result(D_MD4, testnum, count, d);
+ if (count < 0)
+ break;
}
}
-#endif
-#ifndef OPENSSL_NO_MD5
if (doit[D_MD5]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_MD5], c[D_MD5][testnum], lengths[testnum],
@@ -2196,35 +1910,11 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, MD5_loop, loopargs);
d = Time_F(STOP);
print_result(D_MD5, testnum, count, d);
+ if (count < 0)
+ break;
}
}
- if (doit[D_HMAC]) {
- static const char hmac_key[] = "This is a key...";
- int len = strlen(hmac_key);
-
- for (i = 0; i < loopargs_len; i++) {
- loopargs[i].hctx = HMAC_CTX_new();
- if (loopargs[i].hctx == NULL) {
- BIO_printf(bio_err, "HMAC malloc failure, exiting...");
- exit(1);
- }
-
- HMAC_Init_ex(loopargs[i].hctx, hmac_key, len, EVP_md5(), NULL);
- }
- for (testnum = 0; testnum < size_num; testnum++) {
- print_message(names[D_HMAC], c[D_HMAC][testnum], lengths[testnum],
- seconds.sym);
- Time_F(START);
- count = run_benchmark(async_jobs, HMAC_loop, loopargs);
- d = Time_F(STOP);
- print_result(D_HMAC, testnum, count, d);
- }
- for (i = 0; i < loopargs_len; i++) {
- HMAC_CTX_free(loopargs[i].hctx);
- }
- }
-#endif
if (doit[D_SHA1]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_SHA1], c[D_SHA1][testnum], lengths[testnum],
@@ -2233,8 +1923,11 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, SHA1_loop, loopargs);
d = Time_F(STOP);
print_result(D_SHA1, testnum, count, d);
+ if (count < 0)
+ break;
}
}
+
if (doit[D_SHA256]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_SHA256], c[D_SHA256][testnum],
@@ -2243,8 +1936,11 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, SHA256_loop, loopargs);
d = Time_F(STOP);
print_result(D_SHA256, testnum, count, d);
+ if (count < 0)
+ break;
}
}
+
if (doit[D_SHA512]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_SHA512], c[D_SHA512][testnum],
@@ -2253,9 +1949,11 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, SHA512_loop, loopargs);
d = Time_F(STOP);
print_result(D_SHA512, testnum, count, d);
+ if (count < 0)
+ break;
}
}
-#ifndef OPENSSL_NO_WHIRLPOOL
+
if (doit[D_WHIRLPOOL]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_WHIRLPOOL], c[D_WHIRLPOOL][testnum],
@@ -2264,11 +1962,11 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, WHIRLPOOL_loop, loopargs);
d = Time_F(STOP);
print_result(D_WHIRLPOOL, testnum, count, d);
+ if (count < 0)
+ break;
}
}
-#endif
-#ifndef OPENSSL_NO_RMD160
if (doit[D_RMD160]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_RMD160], c[D_RMD160][testnum],
@@ -2277,319 +1975,215 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, EVP_Digest_RMD160_loop, loopargs);
d = Time_F(STOP);
print_result(D_RMD160, testnum, count, d);
+ if (count < 0)
+ break;
}
}
-#endif
-#ifndef OPENSSL_NO_RC4
- if (doit[D_RC4]) {
+
+ if (doit[D_HMAC]) {
+ static const char hmac_key[] = "This is a key...";
+ int len = strlen(hmac_key);
+ OSSL_PARAM params[3];
+
+ mac = EVP_MAC_fetch(app_get0_libctx(), "HMAC", app_get0_propq());
+ if (mac == NULL || evp_mac_mdname == NULL)
+ goto end;
+
+ evp_hmac_name = app_malloc(sizeof("hmac()") + strlen(evp_mac_mdname),
+ "HMAC name");
+ sprintf(evp_hmac_name, "hmac(%s)", evp_mac_mdname);
+ names[D_HMAC] = evp_hmac_name;
+
+ params[0] =
+ OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
+ evp_mac_mdname, 0);
+ params[1] =
+ OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ (char *)hmac_key, len);
+ params[2] = OSSL_PARAM_construct_end();
+
+ for (i = 0; i < loopargs_len; i++) {
+ loopargs[i].mctx = EVP_MAC_CTX_new(mac);
+ if (loopargs[i].mctx == NULL)
+ goto end;
+
+ if (!EVP_MAC_CTX_set_params(loopargs[i].mctx, params))
+ goto skip_hmac; /* Digest not found */
+ }
for (testnum = 0; testnum < size_num; testnum++) {
- print_message(names[D_RC4], c[D_RC4][testnum], lengths[testnum],
+ print_message(names[D_HMAC], c[D_HMAC][testnum], lengths[testnum],
seconds.sym);
Time_F(START);
- count = run_benchmark(async_jobs, RC4_loop, loopargs);
+ count = run_benchmark(async_jobs, HMAC_loop, loopargs);
d = Time_F(STOP);
- print_result(D_RC4, testnum, count, d);
+ print_result(D_HMAC, testnum, count, d);
+ if (count < 0)
+ break;
}
+ for (i = 0; i < loopargs_len; i++)
+ EVP_MAC_CTX_free(loopargs[i].mctx);
+ EVP_MAC_free(mac);
+ mac = NULL;
}
-#endif
-#ifndef OPENSSL_NO_DES
+skip_hmac:
if (doit[D_CBC_DES]) {
- for (testnum = 0; testnum < size_num; testnum++) {
+ int st = 1;
+
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].ctx = init_evp_cipher_ctx("des-cbc", deskey,
+ sizeof(deskey) / 3);
+ st = loopargs[i].ctx != NULL;
+ }
+ algindex = D_CBC_DES;
+ for (testnum = 0; st && testnum < size_num; testnum++) {
print_message(names[D_CBC_DES], c[D_CBC_DES][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
- count = run_benchmark(async_jobs, DES_ncbc_encrypt_loop, loopargs);
+ count = run_benchmark(async_jobs, EVP_Cipher_loop, loopargs);
d = Time_F(STOP);
print_result(D_CBC_DES, testnum, count, d);
}
+ for (i = 0; i < loopargs_len; i++)
+ EVP_CIPHER_CTX_free(loopargs[i].ctx);
}
if (doit[D_EDE3_DES]) {
- for (testnum = 0; testnum < size_num; testnum++) {
+ int st = 1;
+
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].ctx = init_evp_cipher_ctx("des-ede3-cbc", deskey,
+ sizeof(deskey));
+ st = loopargs[i].ctx != NULL;
+ }
+ algindex = D_EDE3_DES;
+ for (testnum = 0; st && testnum < size_num; testnum++) {
print_message(names[D_EDE3_DES], c[D_EDE3_DES][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count =
- run_benchmark(async_jobs, DES_ede3_cbc_encrypt_loop, loopargs);
+ run_benchmark(async_jobs, EVP_Cipher_loop, loopargs);
d = Time_F(STOP);
print_result(D_EDE3_DES, testnum, count, d);
}
+ for (i = 0; i < loopargs_len; i++)
+ EVP_CIPHER_CTX_free(loopargs[i].ctx);
}
-#endif
- if (doit[D_CBC_128_AES]) {
- for (testnum = 0; testnum < size_num; testnum++) {
- print_message(names[D_CBC_128_AES], c[D_CBC_128_AES][testnum],
- lengths[testnum], seconds.sym);
- Time_F(START);
- count =
- run_benchmark(async_jobs, AES_cbc_128_encrypt_loop, loopargs);
- d = Time_F(STOP);
- print_result(D_CBC_128_AES, testnum, count, d);
- }
- }
- if (doit[D_CBC_192_AES]) {
- for (testnum = 0; testnum < size_num; testnum++) {
- print_message(names[D_CBC_192_AES], c[D_CBC_192_AES][testnum],
- lengths[testnum], seconds.sym);
- Time_F(START);
- count =
- run_benchmark(async_jobs, AES_cbc_192_encrypt_loop, loopargs);
- d = Time_F(STOP);
- print_result(D_CBC_192_AES, testnum, count, d);
- }
- }
- if (doit[D_CBC_256_AES]) {
- for (testnum = 0; testnum < size_num; testnum++) {
- print_message(names[D_CBC_256_AES], c[D_CBC_256_AES][testnum],
- lengths[testnum], seconds.sym);
- Time_F(START);
- count =
- run_benchmark(async_jobs, AES_cbc_256_encrypt_loop, loopargs);
- d = Time_F(STOP);
- print_result(D_CBC_256_AES, testnum, count, d);
- }
- }
+ for (k = 0; k < 3; k++) {
+ algindex = D_CBC_128_AES + k;
+ if (doit[algindex]) {
+ int st = 1;
- if (doit[D_IGE_128_AES]) {
- for (testnum = 0; testnum < size_num; testnum++) {
- print_message(names[D_IGE_128_AES], c[D_IGE_128_AES][testnum],
- lengths[testnum], seconds.sym);
- Time_F(START);
- count =
- run_benchmark(async_jobs, AES_ige_128_encrypt_loop, loopargs);
- d = Time_F(STOP);
- print_result(D_IGE_128_AES, testnum, count, d);
+ keylen = 16 + k * 8;
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].ctx = init_evp_cipher_ctx(names[algindex],
+ key32, keylen);
+ st = loopargs[i].ctx != NULL;
+ }
+
+ for (testnum = 0; st && testnum < size_num; testnum++) {
+ print_message(names[algindex], c[algindex][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, EVP_Cipher_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(algindex, testnum, count, d);
+ }
+ for (i = 0; i < loopargs_len; i++)
+ EVP_CIPHER_CTX_free(loopargs[i].ctx);
}
}
- if (doit[D_IGE_192_AES]) {
- for (testnum = 0; testnum < size_num; testnum++) {
- print_message(names[D_IGE_192_AES], c[D_IGE_192_AES][testnum],
- lengths[testnum], seconds.sym);
- Time_F(START);
- count =
- run_benchmark(async_jobs, AES_ige_192_encrypt_loop, loopargs);
- d = Time_F(STOP);
- print_result(D_IGE_192_AES, testnum, count, d);
+
+ for (k = 0; k < 3; k++) {
+ algindex = D_CBC_128_CML + k;
+ if (doit[algindex]) {
+ int st = 1;
+
+ keylen = 16 + k * 8;
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].ctx = init_evp_cipher_ctx(names[algindex],
+ key32, keylen);
+ st = loopargs[i].ctx != NULL;
+ }
+
+ for (testnum = 0; st && testnum < size_num; testnum++) {
+ print_message(names[algindex], c[algindex][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, EVP_Cipher_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(algindex, testnum, count, d);
+ }
+ for (i = 0; i < loopargs_len; i++)
+ EVP_CIPHER_CTX_free(loopargs[i].ctx);
}
}
- if (doit[D_IGE_256_AES]) {
- for (testnum = 0; testnum < size_num; testnum++) {
- print_message(names[D_IGE_256_AES], c[D_IGE_256_AES][testnum],
- lengths[testnum], seconds.sym);
- Time_F(START);
- count =
- run_benchmark(async_jobs, AES_ige_256_encrypt_loop, loopargs);
- d = Time_F(STOP);
- print_result(D_IGE_256_AES, testnum, count, d);
+
+ for (algindex = D_RC4; algindex <= D_CBC_CAST; algindex++) {
+ if (doit[algindex]) {
+ int st = 1;
+
+ keylen = 16;
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].ctx = init_evp_cipher_ctx(names[algindex],
+ key32, keylen);
+ st = loopargs[i].ctx != NULL;
+ }
+
+ for (testnum = 0; st && testnum < size_num; testnum++) {
+ print_message(names[algindex], c[algindex][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, EVP_Cipher_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(algindex, testnum, count, d);
+ }
+ for (i = 0; i < loopargs_len; i++)
+ EVP_CIPHER_CTX_free(loopargs[i].ctx);
}
}
if (doit[D_GHASH]) {
+ static const char gmac_iv[] = "0123456789ab";
+ OSSL_PARAM params[3];
+
+ mac = EVP_MAC_fetch(app_get0_libctx(), "GMAC", app_get0_propq());
+ if (mac == NULL)
+ goto end;
+
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_CIPHER,
+ "aes-128-gcm", 0);
+ params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_IV,
+ (char *)gmac_iv,
+ sizeof(gmac_iv) - 1);
+ params[2] = OSSL_PARAM_construct_end();
+
for (i = 0; i < loopargs_len; i++) {
- loopargs[i].gcm_ctx =
- CRYPTO_gcm128_new(&aes_ks1, (block128_f) AES_encrypt);
- CRYPTO_gcm128_setiv(loopargs[i].gcm_ctx,
- (unsigned char *)"0123456789ab", 12);
- }
+ loopargs[i].mctx = EVP_MAC_CTX_new(mac);
+ if (loopargs[i].mctx == NULL)
+ goto end;
+ if (!EVP_MAC_init(loopargs[i].mctx, key32, 16, params))
+ goto end;
+ }
for (testnum = 0; testnum < size_num; testnum++) {
- print_message(names[D_GHASH], c[D_GHASH][testnum],
- lengths[testnum], seconds.sym);
+ print_message(names[D_GHASH], c[D_GHASH][testnum], lengths[testnum],
+ seconds.sym);
Time_F(START);
- count = run_benchmark(async_jobs, CRYPTO_gcm128_aad_loop, loopargs);
+ count = run_benchmark(async_jobs, GHASH_loop, loopargs);
d = Time_F(STOP);
print_result(D_GHASH, testnum, count, d);
+ if (count < 0)
+ break;
}
for (i = 0; i < loopargs_len; i++)
- CRYPTO_gcm128_release(loopargs[i].gcm_ctx);
- }
-#ifndef OPENSSL_NO_CAMELLIA
- if (doit[D_CBC_128_CML]) {
- if (async_jobs > 0) {
- BIO_printf(bio_err, "Async mode is not supported with %s\n",
- names[D_CBC_128_CML]);
- doit[D_CBC_128_CML] = 0;
- }
- for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
- print_message(names[D_CBC_128_CML], c[D_CBC_128_CML][testnum],
- lengths[testnum], seconds.sym);
- Time_F(START);
- for (count = 0; COND(c[D_CBC_128_CML][testnum]); count++)
- Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
- (size_t)lengths[testnum], &camellia_ks1,
- iv, CAMELLIA_ENCRYPT);
- d = Time_F(STOP);
- print_result(D_CBC_128_CML, testnum, count, d);
- }
- }
- if (doit[D_CBC_192_CML]) {
- if (async_jobs > 0) {
- BIO_printf(bio_err, "Async mode is not supported with %s\n",
- names[D_CBC_192_CML]);
- doit[D_CBC_192_CML] = 0;
- }
- for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
- print_message(names[D_CBC_192_CML], c[D_CBC_192_CML][testnum],
- lengths[testnum], seconds.sym);
- if (async_jobs > 0) {
- BIO_printf(bio_err, "Async mode is not supported, exiting...");
- exit(1);
- }
- Time_F(START);
- for (count = 0; COND(c[D_CBC_192_CML][testnum]); count++)
- Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
- (size_t)lengths[testnum], &camellia_ks2,
- iv, CAMELLIA_ENCRYPT);
- d = Time_F(STOP);
- print_result(D_CBC_192_CML, testnum, count, d);
- }
- }
- if (doit[D_CBC_256_CML]) {
- if (async_jobs > 0) {
- BIO_printf(bio_err, "Async mode is not supported with %s\n",
- names[D_CBC_256_CML]);
- doit[D_CBC_256_CML] = 0;
- }
- for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
- print_message(names[D_CBC_256_CML], c[D_CBC_256_CML][testnum],
- lengths[testnum], seconds.sym);
- Time_F(START);
- for (count = 0; COND(c[D_CBC_256_CML][testnum]); count++)
- Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
- (size_t)lengths[testnum], &camellia_ks3,
- iv, CAMELLIA_ENCRYPT);
- d = Time_F(STOP);
- print_result(D_CBC_256_CML, testnum, count, d);
- }
- }
-#endif
-#ifndef OPENSSL_NO_IDEA
- if (doit[D_CBC_IDEA]) {
- if (async_jobs > 0) {
- BIO_printf(bio_err, "Async mode is not supported with %s\n",
- names[D_CBC_IDEA]);
- doit[D_CBC_IDEA] = 0;
- }
- for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
- print_message(names[D_CBC_IDEA], c[D_CBC_IDEA][testnum],
- lengths[testnum], seconds.sym);
- Time_F(START);
- for (count = 0; COND(c[D_CBC_IDEA][testnum]); count++)
- IDEA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
- (size_t)lengths[testnum], &idea_ks,
- iv, IDEA_ENCRYPT);
- d = Time_F(STOP);
- print_result(D_CBC_IDEA, testnum, count, d);
- }
- }
-#endif
-#ifndef OPENSSL_NO_SEED
- if (doit[D_CBC_SEED]) {
- if (async_jobs > 0) {
- BIO_printf(bio_err, "Async mode is not supported with %s\n",
- names[D_CBC_SEED]);
- doit[D_CBC_SEED] = 0;
- }
- for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
- print_message(names[D_CBC_SEED], c[D_CBC_SEED][testnum],
- lengths[testnum], seconds.sym);
- Time_F(START);
- for (count = 0; COND(c[D_CBC_SEED][testnum]); count++)
- SEED_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
- (size_t)lengths[testnum], &seed_ks, iv, 1);
- d = Time_F(STOP);
- print_result(D_CBC_SEED, testnum, count, d);
- }
- }
-#endif
-#ifndef OPENSSL_NO_RC2
- if (doit[D_CBC_RC2]) {
- if (async_jobs > 0) {
- BIO_printf(bio_err, "Async mode is not supported with %s\n",
- names[D_CBC_RC2]);
- doit[D_CBC_RC2] = 0;
- }
- for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
- print_message(names[D_CBC_RC2], c[D_CBC_RC2][testnum],
- lengths[testnum], seconds.sym);
- if (async_jobs > 0) {
- BIO_printf(bio_err, "Async mode is not supported, exiting...");
- exit(1);
- }
- Time_F(START);
- for (count = 0; COND(c[D_CBC_RC2][testnum]); count++)
- RC2_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
- (size_t)lengths[testnum], &rc2_ks,
- iv, RC2_ENCRYPT);
- d = Time_F(STOP);
- print_result(D_CBC_RC2, testnum, count, d);
- }
- }
-#endif
-#ifndef OPENSSL_NO_RC5
- if (doit[D_CBC_RC5]) {
- if (async_jobs > 0) {
- BIO_printf(bio_err, "Async mode is not supported with %s\n",
- names[D_CBC_RC5]);
- doit[D_CBC_RC5] = 0;
- }
- for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
- print_message(names[D_CBC_RC5], c[D_CBC_RC5][testnum],
- lengths[testnum], seconds.sym);
- if (async_jobs > 0) {
- BIO_printf(bio_err, "Async mode is not supported, exiting...");
- exit(1);
- }
- Time_F(START);
- for (count = 0; COND(c[D_CBC_RC5][testnum]); count++)
- RC5_32_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
- (size_t)lengths[testnum], &rc5_ks,
- iv, RC5_ENCRYPT);
- d = Time_F(STOP);
- print_result(D_CBC_RC5, testnum, count, d);
- }
- }
-#endif
-#ifndef OPENSSL_NO_BF
- if (doit[D_CBC_BF]) {
- if (async_jobs > 0) {
- BIO_printf(bio_err, "Async mode is not supported with %s\n",
- names[D_CBC_BF]);
- doit[D_CBC_BF] = 0;
- }
- for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
- print_message(names[D_CBC_BF], c[D_CBC_BF][testnum],
- lengths[testnum], seconds.sym);
- Time_F(START);
- for (count = 0; COND(c[D_CBC_BF][testnum]); count++)
- BF_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
- (size_t)lengths[testnum], &bf_ks,
- iv, BF_ENCRYPT);
- d = Time_F(STOP);
- print_result(D_CBC_BF, testnum, count, d);
- }
+ EVP_MAC_CTX_free(loopargs[i].mctx);
+ EVP_MAC_free(mac);
+ mac = NULL;
}
-#endif
-#ifndef OPENSSL_NO_CAST
- if (doit[D_CBC_CAST]) {
- if (async_jobs > 0) {
- BIO_printf(bio_err, "Async mode is not supported with %s\n",
- names[D_CBC_CAST]);
- doit[D_CBC_CAST] = 0;
- }
- for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
- print_message(names[D_CBC_CAST], c[D_CBC_CAST][testnum],
- lengths[testnum], seconds.sym);
- Time_F(START);
- for (count = 0; COND(c[D_CBC_CAST][testnum]); count++)
- CAST_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
- (size_t)lengths[testnum], &cast_ks,
- iv, CAST_ENCRYPT);
- d = Time_F(STOP);
- print_result(D_CBC_CAST, testnum, count, d);
- }
- }
-#endif
+
if (doit[D_RAND]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_RAND], c[D_RAND][testnum], lengths[testnum],
@@ -2603,20 +2197,20 @@ int speed_main(int argc, char **argv)
if (doit[D_EVP]) {
if (evp_cipher != NULL) {
- int (*loopfunc)(void *args) = EVP_Update_loop;
+ int (*loopfunc) (void *) = EVP_Update_loop;
- if (multiblock && (EVP_CIPHER_flags(evp_cipher) &
+ if (multiblock && (EVP_CIPHER_get_flags(evp_cipher) &
EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) {
multiblock_speed(evp_cipher, lengths_single, &seconds);
ret = 0;
goto end;
}
- names[D_EVP] = OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher));
+ names[D_EVP] = EVP_CIPHER_get0_name(evp_cipher);
- if (EVP_CIPHER_mode(evp_cipher) == EVP_CIPH_CCM_MODE) {
+ if (EVP_CIPHER_get_mode(evp_cipher) == EVP_CIPH_CCM_MODE) {
loopfunc = EVP_Update_loop_ccm;
- } else if (aead && (EVP_CIPHER_flags(evp_cipher) &
+ } else if (aead && (EVP_CIPHER_get_flags(evp_cipher) &
EVP_CIPH_FLAG_AEAD_CIPHER)) {
loopfunc = EVP_Update_loop_aead;
if (lengths == lengths_list) {
@@ -2626,7 +2220,7 @@ int speed_main(int argc, char **argv)
}
for (testnum = 0; testnum < size_num; testnum++) {
- print_message(names[D_EVP], save_count, lengths[testnum],
+ print_message(names[D_EVP], c[D_EVP][testnum], lengths[testnum],
seconds.sym);
for (k = 0; k < loopargs_len; k++) {
@@ -2644,7 +2238,7 @@ int speed_main(int argc, char **argv)
EVP_CIPHER_CTX_set_padding(loopargs[k].ctx, 0);
- keylen = EVP_CIPHER_CTX_key_length(loopargs[k].ctx);
+ keylen = EVP_CIPHER_CTX_get_key_length(loopargs[k].ctx);
loopargs[k].key = app_malloc(keylen, "evp_cipher key");
EVP_CIPHER_CTX_rand_key(loopargs[k].ctx, loopargs[k].key);
if (!EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL,
@@ -2654,81 +2248,139 @@ int speed_main(int argc, char **argv)
exit(1);
}
OPENSSL_clear_free(loopargs[k].key, keylen);
+
+ /* SIV mode only allows for a single Update operation */
+ if (EVP_CIPHER_get_mode(evp_cipher) == EVP_CIPH_SIV_MODE)
+ (void)EVP_CIPHER_CTX_ctrl(loopargs[k].ctx,
+ EVP_CTRL_SET_SPEED, 1, NULL);
}
Time_F(START);
count = run_benchmark(async_jobs, loopfunc, loopargs);
d = Time_F(STOP);
- for (k = 0; k < loopargs_len; k++) {
+ for (k = 0; k < loopargs_len; k++)
EVP_CIPHER_CTX_free(loopargs[k].ctx);
- }
print_result(D_EVP, testnum, count, d);
}
- } else if (evp_md != NULL) {
- names[D_EVP] = OBJ_nid2ln(EVP_MD_type(evp_md));
+ } else if (evp_md_name != NULL) {
+ names[D_EVP] = evp_md_name;
for (testnum = 0; testnum < size_num; testnum++) {
- print_message(names[D_EVP], save_count, lengths[testnum],
+ print_message(names[D_EVP], c[D_EVP][testnum], lengths[testnum],
seconds.sym);
Time_F(START);
- count = run_benchmark(async_jobs, EVP_Digest_loop, loopargs);
+ count = run_benchmark(async_jobs, EVP_Digest_md_loop, loopargs);
d = Time_F(STOP);
print_result(D_EVP, testnum, count, d);
+ if (count < 0)
+ break;
}
}
}
+ if (doit[D_EVP_CMAC]) {
+ OSSL_PARAM params[3];
+ EVP_CIPHER *cipher = NULL;
+
+ mac = EVP_MAC_fetch(app_get0_libctx(), "CMAC", app_get0_propq());
+ if (mac == NULL || evp_mac_ciphername == NULL)
+ goto end;
+ if (!opt_cipher(evp_mac_ciphername, &cipher))
+ goto end;
+
+ keylen = EVP_CIPHER_get_key_length(cipher);
+ EVP_CIPHER_free(cipher);
+ if (keylen <= 0 || keylen > (int)sizeof(key32)) {
+ BIO_printf(bio_err, "\nRequested CMAC cipher with unsupported key length.\n");
+ goto end;
+ }
+ evp_cmac_name = app_malloc(sizeof("cmac()")
+ + strlen(evp_mac_ciphername), "CMAC name");
+ sprintf(evp_cmac_name, "cmac(%s)", evp_mac_ciphername);
+ names[D_EVP_CMAC] = evp_cmac_name;
+
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_CIPHER,
+ evp_mac_ciphername, 0);
+ params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ (char *)key32, keylen);
+ params[2] = OSSL_PARAM_construct_end();
+
+ for (i = 0; i < loopargs_len; i++) {
+ loopargs[i].mctx = EVP_MAC_CTX_new(mac);
+ if (loopargs[i].mctx == NULL)
+ goto end;
+
+ if (!EVP_MAC_CTX_set_params(loopargs[i].mctx, params))
+ goto end;
+ }
+
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_EVP_CMAC], c[D_EVP_CMAC][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, CMAC_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_EVP_CMAC, testnum, count, d);
+ if (count < 0)
+ break;
+ }
+ for (i = 0; i < loopargs_len; i++)
+ EVP_MAC_CTX_free(loopargs[i].mctx);
+ EVP_MAC_free(mac);
+ mac = NULL;
+ }
+
for (i = 0; i < loopargs_len; i++)
if (RAND_bytes(loopargs[i].buf, 36) <= 0)
goto end;
-#ifndef OPENSSL_NO_RSA
for (testnum = 0; testnum < RSA_NUM; testnum++) {
+ EVP_PKEY *rsa_key = NULL;
int st = 0;
+
if (!rsa_doit[testnum])
continue;
- for (i = 0; i < loopargs_len; i++) {
- if (primes > 2) {
- /* we haven't set keys yet, generate multi-prime RSA keys */
- BIGNUM *bn = BN_new();
-
- if (bn == NULL)
- goto end;
- if (!BN_set_word(bn, RSA_F4)) {
- BN_free(bn);
- goto end;
- }
- BIO_printf(bio_err, "Generate multi-prime RSA key for %s\n",
- rsa_choices[testnum].name);
+ if (primes > RSA_DEFAULT_PRIME_NUM) {
+ /* we haven't set keys yet, generate multi-prime RSA keys */
+ bn = BN_new();
+ st = bn != NULL
+ && BN_set_word(bn, RSA_F4)
+ && init_gen_str(&genctx, "RSA", NULL, 0, NULL, NULL)
+ && EVP_PKEY_CTX_set_rsa_keygen_bits(genctx, rsa_keys[testnum].bits) > 0
+ && EVP_PKEY_CTX_set1_rsa_keygen_pubexp(genctx, bn) > 0
+ && EVP_PKEY_CTX_set_rsa_keygen_primes(genctx, primes) > 0
+ && EVP_PKEY_keygen(genctx, &rsa_key);
+ BN_free(bn);
+ bn = NULL;
+ EVP_PKEY_CTX_free(genctx);
+ genctx = NULL;
+ } else {
+ const unsigned char *p = rsa_keys[testnum].data;
- loopargs[i].rsa_key[testnum] = RSA_new();
- if (loopargs[i].rsa_key[testnum] == NULL) {
- BN_free(bn);
- goto end;
- }
+ st = (rsa_key = d2i_PrivateKey(EVP_PKEY_RSA, NULL, &p,
+ rsa_keys[testnum].length)) != NULL;
+ }
- if (!RSA_generate_multi_prime_key(loopargs[i].rsa_key[testnum],
- rsa_bits[testnum],
- primes, bn, NULL)) {
- BN_free(bn);
- goto end;
- }
- BN_free(bn);
- }
- st = RSA_sign(NID_md5_sha1, loopargs[i].buf, 36, loopargs[i].buf2,
- &loopargs[i].siglen, loopargs[i].rsa_key[testnum]);
- if (st == 0)
- break;
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].rsa_sign_ctx[testnum] = EVP_PKEY_CTX_new(rsa_key, NULL);
+ loopargs[i].sigsize = loopargs[i].buflen;
+ if (loopargs[i].rsa_sign_ctx[testnum] == NULL
+ || EVP_PKEY_sign_init(loopargs[i].rsa_sign_ctx[testnum]) <= 0
+ || EVP_PKEY_sign(loopargs[i].rsa_sign_ctx[testnum],
+ loopargs[i].buf2,
+ &loopargs[i].sigsize,
+ loopargs[i].buf, 36) <= 0)
+ st = 0;
}
- if (st == 0) {
+ if (!st) {
BIO_printf(bio_err,
- "RSA sign failure. No RSA sign will be done.\n");
+ "RSA sign setup failure. No RSA sign will be done.\n");
ERR_print_errors(bio_err);
- rsa_count = 1;
+ op_count = 1;
} else {
pkey_print_message("private", "rsa",
- rsa_c[testnum][0], rsa_bits[testnum],
+ rsa_c[testnum][0], rsa_keys[testnum].bits,
seconds.rsa);
/* RSA_blinding_on(rsa_key[testnum],NULL); */
Time_F(START);
@@ -2737,25 +2389,30 @@ int speed_main(int argc, char **argv)
BIO_printf(bio_err,
mr ? "+R1:%ld:%d:%.2f\n"
: "%ld %u bits private RSA's in %.2fs\n",
- count, rsa_bits[testnum], d);
+ count, rsa_keys[testnum].bits, d);
rsa_results[testnum][0] = (double)count / d;
- rsa_count = count;
- }
-
- for (i = 0; i < loopargs_len; i++) {
- st = RSA_verify(NID_md5_sha1, loopargs[i].buf, 36, loopargs[i].buf2,
- loopargs[i].siglen, loopargs[i].rsa_key[testnum]);
- if (st <= 0)
- break;
+ op_count = count;
+ }
+
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].rsa_verify_ctx[testnum] = EVP_PKEY_CTX_new(rsa_key,
+ NULL);
+ if (loopargs[i].rsa_verify_ctx[testnum] == NULL
+ || EVP_PKEY_verify_init(loopargs[i].rsa_verify_ctx[testnum]) <= 0
+ || EVP_PKEY_verify(loopargs[i].rsa_verify_ctx[testnum],
+ loopargs[i].buf2,
+ loopargs[i].sigsize,
+ loopargs[i].buf, 36) <= 0)
+ st = 0;
}
- if (st <= 0) {
+ if (!st) {
BIO_printf(bio_err,
- "RSA verify failure. No RSA verify will be done.\n");
+ "RSA verify setup failure. No RSA verify will be done.\n");
ERR_print_errors(bio_err);
rsa_doit[testnum] = 0;
} else {
pkey_print_message("public", "rsa",
- rsa_c[testnum][1], rsa_bits[testnum],
+ rsa_c[testnum][1], rsa_keys[testnum].bits,
seconds.rsa);
Time_F(START);
count = run_benchmark(async_jobs, RSA_verify_loop, loopargs);
@@ -2763,41 +2420,44 @@ int speed_main(int argc, char **argv)
BIO_printf(bio_err,
mr ? "+R2:%ld:%d:%.2f\n"
: "%ld %u bits public RSA's in %.2fs\n",
- count, rsa_bits[testnum], d);
+ count, rsa_keys[testnum].bits, d);
rsa_results[testnum][1] = (double)count / d;
}
- if (rsa_count <= 1) {
+ if (op_count <= 1) {
/* if longer than 10s, don't do any more */
- for (testnum++; testnum < RSA_NUM; testnum++)
- rsa_doit[testnum] = 0;
+ stop_it(rsa_doit, testnum);
}
+ EVP_PKEY_free(rsa_key);
}
-#endif /* OPENSSL_NO_RSA */
-
- for (i = 0; i < loopargs_len; i++)
- if (RAND_bytes(loopargs[i].buf, 36) <= 0)
- goto end;
-#ifndef OPENSSL_NO_DSA
for (testnum = 0; testnum < DSA_NUM; testnum++) {
- int st = 0;
+ EVP_PKEY *dsa_key = NULL;
+ int st;
+
if (!dsa_doit[testnum])
continue;
- /* DSA_generate_key(dsa_key[testnum]); */
- /* DSA_sign_setup(dsa_key[testnum],NULL); */
- for (i = 0; i < loopargs_len; i++) {
- st = DSA_sign(0, loopargs[i].buf, 20, loopargs[i].buf2,
- &loopargs[i].siglen, loopargs[i].dsa_key[testnum]);
- if (st == 0)
- break;
+ st = (dsa_key = get_dsa(dsa_bits[testnum])) != NULL;
+
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].dsa_sign_ctx[testnum] = EVP_PKEY_CTX_new(dsa_key,
+ NULL);
+ loopargs[i].sigsize = loopargs[i].buflen;
+ if (loopargs[i].dsa_sign_ctx[testnum] == NULL
+ || EVP_PKEY_sign_init(loopargs[i].dsa_sign_ctx[testnum]) <= 0
+
+ || EVP_PKEY_sign(loopargs[i].dsa_sign_ctx[testnum],
+ loopargs[i].buf2,
+ &loopargs[i].sigsize,
+ loopargs[i].buf, 20) <= 0)
+ st = 0;
}
- if (st == 0) {
+ if (!st) {
BIO_printf(bio_err,
- "DSA sign failure. No DSA sign will be done.\n");
+ "DSA sign setup failure. No DSA sign will be done.\n");
ERR_print_errors(bio_err);
- rsa_count = 1;
+ op_count = 1;
} else {
pkey_print_message("sign", "dsa",
dsa_c[testnum][0], dsa_bits[testnum],
@@ -2810,18 +2470,23 @@ int speed_main(int argc, char **argv)
: "%ld %u bits DSA signs in %.2fs\n",
count, dsa_bits[testnum], d);
dsa_results[testnum][0] = (double)count / d;
- rsa_count = count;
- }
-
- for (i = 0; i < loopargs_len; i++) {
- st = DSA_verify(0, loopargs[i].buf, 20, loopargs[i].buf2,
- loopargs[i].siglen, loopargs[i].dsa_key[testnum]);
- if (st <= 0)
- break;
+ op_count = count;
+ }
+
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].dsa_verify_ctx[testnum] = EVP_PKEY_CTX_new(dsa_key,
+ NULL);
+ if (loopargs[i].dsa_verify_ctx[testnum] == NULL
+ || EVP_PKEY_verify_init(loopargs[i].dsa_verify_ctx[testnum]) <= 0
+ || EVP_PKEY_verify(loopargs[i].dsa_verify_ctx[testnum],
+ loopargs[i].buf2,
+ loopargs[i].sigsize,
+ loopargs[i].buf, 36) <= 0)
+ st = 0;
}
- if (st <= 0) {
+ if (!st) {
BIO_printf(bio_err,
- "DSA verify failure. No DSA verify will be done.\n");
+ "DSA verify setup failure. No DSA verify will be done.\n");
ERR_print_errors(bio_err);
dsa_doit[testnum] = 0;
} else {
@@ -2838,96 +2503,88 @@ int speed_main(int argc, char **argv)
dsa_results[testnum][1] = (double)count / d;
}
- if (rsa_count <= 1) {
+ if (op_count <= 1) {
/* if longer than 10s, don't do any more */
- for (testnum++; testnum < DSA_NUM; testnum++)
- dsa_doit[testnum] = 0;
+ stop_it(dsa_doit, testnum);
}
+ EVP_PKEY_free(dsa_key);
}
-#endif /* OPENSSL_NO_DSA */
-#ifndef OPENSSL_NO_EC
for (testnum = 0; testnum < ECDSA_NUM; testnum++) {
- int st = 1;
+ EVP_PKEY *ecdsa_key = NULL;
+ int st;
if (!ecdsa_doit[testnum])
- continue; /* Ignore Curve */
- for (i = 0; i < loopargs_len; i++) {
- loopargs[i].ecdsa[testnum] =
- EC_KEY_new_by_curve_name(test_curves[testnum].nid);
- if (loopargs[i].ecdsa[testnum] == NULL) {
+ continue;
+
+ st = (ecdsa_key = get_ecdsa(&ec_curves[testnum])) != NULL;
+
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].ecdsa_sign_ctx[testnum] = EVP_PKEY_CTX_new(ecdsa_key,
+ NULL);
+ loopargs[i].sigsize = loopargs[i].buflen;
+ if (loopargs[i].ecdsa_sign_ctx[testnum] == NULL
+ || EVP_PKEY_sign_init(loopargs[i].ecdsa_sign_ctx[testnum]) <= 0
+
+ || EVP_PKEY_sign(loopargs[i].ecdsa_sign_ctx[testnum],
+ loopargs[i].buf2,
+ &loopargs[i].sigsize,
+ loopargs[i].buf, 20) <= 0)
st = 0;
- break;
- }
}
- if (st == 0) {
- BIO_printf(bio_err, "ECDSA failure.\n");
+ if (!st) {
+ BIO_printf(bio_err,
+ "ECDSA sign setup failure. No ECDSA sign will be done.\n");
ERR_print_errors(bio_err);
- rsa_count = 1;
+ op_count = 1;
} else {
- for (i = 0; i < loopargs_len; i++) {
- EC_KEY_precompute_mult(loopargs[i].ecdsa[testnum], NULL);
- /* Perform ECDSA signature test */
- EC_KEY_generate_key(loopargs[i].ecdsa[testnum]);
- st = ECDSA_sign(0, loopargs[i].buf, 20, loopargs[i].buf2,
- &loopargs[i].siglen,
- loopargs[i].ecdsa[testnum]);
- if (st == 0)
- break;
- }
- if (st == 0) {
- BIO_printf(bio_err,
- "ECDSA sign failure. No ECDSA sign will be done.\n");
- ERR_print_errors(bio_err);
- rsa_count = 1;
- } else {
- pkey_print_message("sign", "ecdsa",
- ecdsa_c[testnum][0],
- test_curves[testnum].bits, seconds.ecdsa);
- Time_F(START);
- count = run_benchmark(async_jobs, ECDSA_sign_loop, loopargs);
- d = Time_F(STOP);
-
- BIO_printf(bio_err,
- mr ? "+R5:%ld:%u:%.2f\n" :
- "%ld %u bits ECDSA signs in %.2fs \n",
- count, test_curves[testnum].bits, d);
- ecdsa_results[testnum][0] = (double)count / d;
- rsa_count = count;
- }
-
- /* Perform ECDSA verification test */
- for (i = 0; i < loopargs_len; i++) {
- st = ECDSA_verify(0, loopargs[i].buf, 20, loopargs[i].buf2,
- loopargs[i].siglen,
- loopargs[i].ecdsa[testnum]);
- if (st != 1)
- break;
- }
- if (st != 1) {
- BIO_printf(bio_err,
- "ECDSA verify failure. No ECDSA verify will be done.\n");
- ERR_print_errors(bio_err);
- ecdsa_doit[testnum] = 0;
- } else {
- pkey_print_message("verify", "ecdsa",
- ecdsa_c[testnum][1],
- test_curves[testnum].bits, seconds.ecdsa);
- Time_F(START);
- count = run_benchmark(async_jobs, ECDSA_verify_loop, loopargs);
- d = Time_F(STOP);
- BIO_printf(bio_err,
- mr ? "+R6:%ld:%u:%.2f\n"
- : "%ld %u bits ECDSA verify in %.2fs\n",
- count, test_curves[testnum].bits, d);
- ecdsa_results[testnum][1] = (double)count / d;
- }
+ pkey_print_message("sign", "ecdsa",
+ ecdsa_c[testnum][0], ec_curves[testnum].bits,
+ seconds.ecdsa);
+ Time_F(START);
+ count = run_benchmark(async_jobs, ECDSA_sign_loop, loopargs);
+ d = Time_F(STOP);
+ BIO_printf(bio_err,
+ mr ? "+R5:%ld:%u:%.2f\n"
+ : "%ld %u bits ECDSA signs in %.2fs\n",
+ count, ec_curves[testnum].bits, d);
+ ecdsa_results[testnum][0] = (double)count / d;
+ op_count = count;
+ }
+
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].ecdsa_verify_ctx[testnum] = EVP_PKEY_CTX_new(ecdsa_key,
+ NULL);
+ if (loopargs[i].ecdsa_verify_ctx[testnum] == NULL
+ || EVP_PKEY_verify_init(loopargs[i].ecdsa_verify_ctx[testnum]) <= 0
+ || EVP_PKEY_verify(loopargs[i].ecdsa_verify_ctx[testnum],
+ loopargs[i].buf2,
+ loopargs[i].sigsize,
+ loopargs[i].buf, 20) <= 0)
+ st = 0;
+ }
+ if (!st) {
+ BIO_printf(bio_err,
+ "ECDSA verify setup failure. No ECDSA verify will be done.\n");
+ ERR_print_errors(bio_err);
+ ecdsa_doit[testnum] = 0;
+ } else {
+ pkey_print_message("verify", "ecdsa",
+ ecdsa_c[testnum][1], ec_curves[testnum].bits,
+ seconds.ecdsa);
+ Time_F(START);
+ count = run_benchmark(async_jobs, ECDSA_verify_loop, loopargs);
+ d = Time_F(STOP);
+ BIO_printf(bio_err,
+ mr ? "+R6:%ld:%u:%.2f\n"
+ : "%ld %u bits ECDSA verify in %.2fs\n",
+ count, ec_curves[testnum].bits, d);
+ ecdsa_results[testnum][1] = (double)count / d;
+ }
- if (rsa_count <= 1) {
- /* if longer than 10s, don't do any more */
- for (testnum++; testnum < ECDSA_NUM; testnum++)
- ecdsa_doit[testnum] = 0;
- }
+ if (op_count <= 1) {
+ /* if longer than 10s, don't do any more */
+ stop_it(ecdsa_doit, testnum);
}
}
@@ -2938,7 +2595,6 @@ int speed_main(int argc, char **argv)
continue;
for (i = 0; i < loopargs_len; i++) {
- EVP_PKEY_CTX *kctx = NULL;
EVP_PKEY_CTX *test_ctx = NULL;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *key_A = NULL;
@@ -2946,106 +2602,38 @@ int speed_main(int argc, char **argv)
size_t outlen;
size_t test_outlen;
- /* Ensure that the error queue is empty */
- if (ERR_peek_error()) {
- BIO_printf(bio_err,
- "WARNING: the error queue contains previous unhandled errors.\n");
- ERR_print_errors(bio_err);
- }
-
- /* Let's try to create a ctx directly from the NID: this works for
- * curves like Curve25519 that are not implemented through the low
- * level EC interface.
- * If this fails we try creating a EVP_PKEY_EC generic param ctx,
- * then we set the curve by NID before deriving the actual keygen
- * ctx for that specific curve. */
- kctx = EVP_PKEY_CTX_new_id(test_curves[testnum].nid, NULL); /* keygen ctx from NID */
- if (!kctx) {
- EVP_PKEY_CTX *pctx = NULL;
- EVP_PKEY *params = NULL;
-
- /* If we reach this code EVP_PKEY_CTX_new_id() failed and a
- * "int_ctx_new:unsupported algorithm" error was added to the
- * error queue.
- * We remove it from the error queue as we are handling it. */
- unsigned long error = ERR_peek_error(); /* peek the latest error in the queue */
- if (error == ERR_peek_last_error() && /* oldest and latest errors match */
- /* check that the error origin matches */
- ERR_GET_LIB(error) == ERR_LIB_EVP &&
- ERR_GET_FUNC(error) == EVP_F_INT_CTX_NEW &&
- ERR_GET_REASON(error) == EVP_R_UNSUPPORTED_ALGORITHM)
- ERR_get_error(); /* pop error from queue */
- if (ERR_peek_error()) {
- BIO_printf(bio_err,
- "Unhandled error in the error queue during ECDH init.\n");
- ERR_print_errors(bio_err);
- rsa_count = 1;
- break;
- }
-
- if ( /* Create the context for parameter generation */
- !(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) ||
- /* Initialise the parameter generation */
- !EVP_PKEY_paramgen_init(pctx) ||
- /* Set the curve by NID */
- !EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx,
- test_curves
- [testnum].nid) ||
- /* Create the parameter object params */
- !EVP_PKEY_paramgen(pctx, &params)) {
- ecdh_checks = 0;
- BIO_printf(bio_err, "ECDH EC params init failure.\n");
- ERR_print_errors(bio_err);
- rsa_count = 1;
- break;
- }
- /* Create the context for the key generation */
- kctx = EVP_PKEY_CTX_new(params, NULL);
-
- EVP_PKEY_free(params);
- params = NULL;
- EVP_PKEY_CTX_free(pctx);
- pctx = NULL;
- }
- if (kctx == NULL || /* keygen ctx is not null */
- EVP_PKEY_keygen_init(kctx) <= 0/* init keygen ctx */ ) {
- ecdh_checks = 0;
- BIO_printf(bio_err, "ECDH keygen failure.\n");
- ERR_print_errors(bio_err);
- rsa_count = 1;
- break;
- }
-
- if (EVP_PKEY_keygen(kctx, &key_A) <= 0 || /* generate secret key A */
- EVP_PKEY_keygen(kctx, &key_B) <= 0 || /* generate secret key B */
- !(ctx = EVP_PKEY_CTX_new(key_A, NULL)) || /* derivation ctx from skeyA */
- EVP_PKEY_derive_init(ctx) <= 0 || /* init derivation ctx */
- EVP_PKEY_derive_set_peer(ctx, key_B) <= 0 || /* set peer pubkey in ctx */
- EVP_PKEY_derive(ctx, NULL, &outlen) <= 0 || /* determine max length */
- outlen == 0 || /* ensure outlen is a valid size */
- outlen > MAX_ECDH_SIZE /* avoid buffer overflow */ ) {
+ if ((key_A = get_ecdsa(&ec_curves[testnum])) == NULL /* generate secret key A */
+ || (key_B = get_ecdsa(&ec_curves[testnum])) == NULL /* generate secret key B */
+ || (ctx = EVP_PKEY_CTX_new(key_A, NULL)) == NULL /* derivation ctx from skeyA */
+ || EVP_PKEY_derive_init(ctx) <= 0 /* init derivation ctx */
+ || EVP_PKEY_derive_set_peer(ctx, key_B) <= 0 /* set peer pubkey in ctx */
+ || EVP_PKEY_derive(ctx, NULL, &outlen) <= 0 /* determine max length */
+ || outlen == 0 /* ensure outlen is a valid size */
+ || outlen > MAX_ECDH_SIZE /* avoid buffer overflow */) {
ecdh_checks = 0;
BIO_printf(bio_err, "ECDH key generation failure.\n");
ERR_print_errors(bio_err);
- rsa_count = 1;
+ op_count = 1;
break;
}
- /* Here we perform a test run, comparing the output of a*B and b*A;
+ /*
+ * Here we perform a test run, comparing the output of a*B and b*A;
* we try this here and assume that further EVP_PKEY_derive calls
* never fail, so we can skip checks in the actually benchmarked
- * code, for maximum performance. */
- if (!(test_ctx = EVP_PKEY_CTX_new(key_B, NULL)) || /* test ctx from skeyB */
- !EVP_PKEY_derive_init(test_ctx) || /* init derivation test_ctx */
- !EVP_PKEY_derive_set_peer(test_ctx, key_A) || /* set peer pubkey in test_ctx */
- !EVP_PKEY_derive(test_ctx, NULL, &test_outlen) || /* determine max length */
- !EVP_PKEY_derive(ctx, loopargs[i].secret_a, &outlen) || /* compute a*B */
- !EVP_PKEY_derive(test_ctx, loopargs[i].secret_b, &test_outlen) || /* compute b*A */
- test_outlen != outlen /* compare output length */ ) {
+ * code, for maximum performance.
+ */
+ if ((test_ctx = EVP_PKEY_CTX_new(key_B, NULL)) == NULL /* test ctx from skeyB */
+ || EVP_PKEY_derive_init(test_ctx) <= 0 /* init derivation test_ctx */
+ || EVP_PKEY_derive_set_peer(test_ctx, key_A) <= 0 /* set peer pubkey in test_ctx */
+ || EVP_PKEY_derive(test_ctx, NULL, &test_outlen) <= 0 /* determine max length */
+ || EVP_PKEY_derive(ctx, loopargs[i].secret_a, &outlen) <= 0 /* compute a*B */
+ || EVP_PKEY_derive(test_ctx, loopargs[i].secret_b, &test_outlen) <= 0 /* compute b*A */
+ || test_outlen != outlen /* compare output length */) {
ecdh_checks = 0;
BIO_printf(bio_err, "ECDH computation failure.\n");
ERR_print_errors(bio_err);
- rsa_count = 1;
+ op_count = 1;
break;
}
@@ -3055,7 +2643,7 @@ int speed_main(int argc, char **argv)
ecdh_checks = 0;
BIO_printf(bio_err, "ECDH computations don't match.\n");
ERR_print_errors(bio_err);
- rsa_count = 1;
+ op_count = 1;
break;
}
@@ -3064,15 +2652,13 @@ int speed_main(int argc, char **argv)
EVP_PKEY_free(key_A);
EVP_PKEY_free(key_B);
- EVP_PKEY_CTX_free(kctx);
- kctx = NULL;
EVP_PKEY_CTX_free(test_ctx);
test_ctx = NULL;
}
if (ecdh_checks != 0) {
pkey_print_message("", "ecdh",
ecdh_c[testnum][0],
- test_curves[testnum].bits, seconds.ecdh);
+ ec_curves[testnum].bits, seconds.ecdh);
Time_F(START);
count =
run_benchmark(async_jobs, ECDH_EVP_derive_key_loop, loopargs);
@@ -3080,15 +2666,14 @@ int speed_main(int argc, char **argv)
BIO_printf(bio_err,
mr ? "+R7:%ld:%d:%.2f\n" :
"%ld %u-bits ECDH ops in %.2fs\n", count,
- test_curves[testnum].bits, d);
+ ec_curves[testnum].bits, d);
ecdh_results[testnum][0] = (double)count / d;
- rsa_count = count;
+ op_count = count;
}
- if (rsa_count <= 1) {
+ if (op_count <= 1) {
/* if longer than 10s, don't do any more */
- for (testnum++; testnum < OSSL_NELEM(ecdh_doit); testnum++)
- ecdh_doit[testnum] = 0;
+ stop_it(ecdh_doit, testnum);
}
}
@@ -3105,9 +2690,14 @@ int speed_main(int argc, char **argv)
st = 0;
break;
}
+ loopargs[i].eddsa_ctx2[testnum] = EVP_MD_CTX_new();
+ if (loopargs[i].eddsa_ctx2[testnum] == NULL) {
+ st = 0;
+ break;
+ }
- if ((ed_pctx = EVP_PKEY_CTX_new_id(test_ed_curves[testnum].nid, NULL))
- == NULL
+ if ((ed_pctx = EVP_PKEY_CTX_new_id(ed_curves[testnum].nid,
+ NULL)) == NULL
|| EVP_PKEY_keygen_init(ed_pctx) <= 0
|| EVP_PKEY_keygen(ed_pctx, &ed_pkey) <= 0) {
st = 0;
@@ -3122,16 +2712,24 @@ int speed_main(int argc, char **argv)
EVP_PKEY_free(ed_pkey);
break;
}
+ if (!EVP_DigestVerifyInit(loopargs[i].eddsa_ctx2[testnum], NULL,
+ NULL, NULL, ed_pkey)) {
+ st = 0;
+ EVP_PKEY_free(ed_pkey);
+ break;
+ }
+
EVP_PKEY_free(ed_pkey);
+ ed_pkey = NULL;
}
if (st == 0) {
BIO_printf(bio_err, "EdDSA failure.\n");
ERR_print_errors(bio_err);
- rsa_count = 1;
+ op_count = 1;
} else {
for (i = 0; i < loopargs_len; i++) {
/* Perform EdDSA signature test */
- loopargs[i].sigsize = test_ed_curves[testnum].sigsize;
+ loopargs[i].sigsize = ed_curves[testnum].sigsize;
st = EVP_DigestSign(loopargs[i].eddsa_ctx[testnum],
loopargs[i].buf2, &loopargs[i].sigsize,
loopargs[i].buf, 20);
@@ -3142,11 +2740,11 @@ int speed_main(int argc, char **argv)
BIO_printf(bio_err,
"EdDSA sign failure. No EdDSA sign will be done.\n");
ERR_print_errors(bio_err);
- rsa_count = 1;
+ op_count = 1;
} else {
- pkey_print_message("sign", test_ed_curves[testnum].name,
+ pkey_print_message("sign", ed_curves[testnum].name,
eddsa_c[testnum][0],
- test_ed_curves[testnum].bits, seconds.eddsa);
+ ed_curves[testnum].bits, seconds.eddsa);
Time_F(START);
count = run_benchmark(async_jobs, EdDSA_sign_loop, loopargs);
d = Time_F(STOP);
@@ -3154,15 +2752,14 @@ int speed_main(int argc, char **argv)
BIO_printf(bio_err,
mr ? "+R8:%ld:%u:%s:%.2f\n" :
"%ld %u bits %s signs in %.2fs \n",
- count, test_ed_curves[testnum].bits,
- test_ed_curves[testnum].name, d);
+ count, ed_curves[testnum].bits,
+ ed_curves[testnum].name, d);
eddsa_results[testnum][0] = (double)count / d;
- rsa_count = count;
+ op_count = count;
}
-
/* Perform EdDSA verification test */
for (i = 0; i < loopargs_len; i++) {
- st = EVP_DigestVerify(loopargs[i].eddsa_ctx[testnum],
+ st = EVP_DigestVerify(loopargs[i].eddsa_ctx2[testnum],
loopargs[i].buf2, loopargs[i].sigsize,
loopargs[i].buf, 20);
if (st != 1)
@@ -3174,62 +2771,360 @@ int speed_main(int argc, char **argv)
ERR_print_errors(bio_err);
eddsa_doit[testnum] = 0;
} else {
- pkey_print_message("verify", test_ed_curves[testnum].name,
+ pkey_print_message("verify", ed_curves[testnum].name,
eddsa_c[testnum][1],
- test_ed_curves[testnum].bits, seconds.eddsa);
+ ed_curves[testnum].bits, seconds.eddsa);
Time_F(START);
count = run_benchmark(async_jobs, EdDSA_verify_loop, loopargs);
d = Time_F(STOP);
BIO_printf(bio_err,
mr ? "+R9:%ld:%u:%s:%.2f\n"
: "%ld %u bits %s verify in %.2fs\n",
- count, test_ed_curves[testnum].bits,
- test_ed_curves[testnum].name, d);
+ count, ed_curves[testnum].bits,
+ ed_curves[testnum].name, d);
eddsa_results[testnum][1] = (double)count / d;
}
- if (rsa_count <= 1) {
+ if (op_count <= 1) {
+ /* if longer than 10s, don't do any more */
+ stop_it(eddsa_doit, testnum);
+ }
+ }
+ }
+
+#ifndef OPENSSL_NO_SM2
+ for (testnum = 0; testnum < SM2_NUM; testnum++) {
+ int st = 1;
+ EVP_PKEY *sm2_pkey = NULL;
+
+ if (!sm2_doit[testnum])
+ continue; /* Ignore Curve */
+ /* Init signing and verification */
+ for (i = 0; i < loopargs_len; i++) {
+ EVP_PKEY_CTX *sm2_pctx = NULL;
+ EVP_PKEY_CTX *sm2_vfy_pctx = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ st = 0;
+
+ loopargs[i].sm2_ctx[testnum] = EVP_MD_CTX_new();
+ loopargs[i].sm2_vfy_ctx[testnum] = EVP_MD_CTX_new();
+ if (loopargs[i].sm2_ctx[testnum] == NULL
+ || loopargs[i].sm2_vfy_ctx[testnum] == NULL)
+ break;
+
+ sm2_pkey = NULL;
+
+ st = !((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SM2, NULL)) == NULL
+ || EVP_PKEY_keygen_init(pctx) <= 0
+ || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx,
+ sm2_curves[testnum].nid) <= 0
+ || EVP_PKEY_keygen(pctx, &sm2_pkey) <= 0);
+ EVP_PKEY_CTX_free(pctx);
+ if (st == 0)
+ break;
+
+ st = 0; /* set back to zero */
+ /* attach it sooner to rely on main final cleanup */
+ loopargs[i].sm2_pkey[testnum] = sm2_pkey;
+ loopargs[i].sigsize = EVP_PKEY_get_size(sm2_pkey);
+
+ sm2_pctx = EVP_PKEY_CTX_new(sm2_pkey, NULL);
+ sm2_vfy_pctx = EVP_PKEY_CTX_new(sm2_pkey, NULL);
+ if (sm2_pctx == NULL || sm2_vfy_pctx == NULL) {
+ EVP_PKEY_CTX_free(sm2_vfy_pctx);
+ break;
+ }
+
+ /* attach them directly to respective ctx */
+ EVP_MD_CTX_set_pkey_ctx(loopargs[i].sm2_ctx[testnum], sm2_pctx);
+ EVP_MD_CTX_set_pkey_ctx(loopargs[i].sm2_vfy_ctx[testnum], sm2_vfy_pctx);
+
+ /*
+ * No need to allow user to set an explicit ID here, just use
+ * the one defined in the 'draft-yang-tls-tl13-sm-suites' I-D.
+ */
+ if (EVP_PKEY_CTX_set1_id(sm2_pctx, SM2_ID, SM2_ID_LEN) != 1
+ || EVP_PKEY_CTX_set1_id(sm2_vfy_pctx, SM2_ID, SM2_ID_LEN) != 1)
+ break;
+
+ if (!EVP_DigestSignInit(loopargs[i].sm2_ctx[testnum], NULL,
+ EVP_sm3(), NULL, sm2_pkey))
+ break;
+ if (!EVP_DigestVerifyInit(loopargs[i].sm2_vfy_ctx[testnum], NULL,
+ EVP_sm3(), NULL, sm2_pkey))
+ break;
+ st = 1; /* mark loop as succeeded */
+ }
+ if (st == 0) {
+ BIO_printf(bio_err, "SM2 init failure.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ } else {
+ for (i = 0; i < loopargs_len; i++) {
+ /* Perform SM2 signature test */
+ st = EVP_DigestSign(loopargs[i].sm2_ctx[testnum],
+ loopargs[i].buf2, &loopargs[i].sigsize,
+ loopargs[i].buf, 20);
+ if (st == 0)
+ break;
+ }
+ if (st == 0) {
+ BIO_printf(bio_err,
+ "SM2 sign failure. No SM2 sign will be done.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ } else {
+ pkey_print_message("sign", sm2_curves[testnum].name,
+ sm2_c[testnum][0],
+ sm2_curves[testnum].bits, seconds.sm2);
+ Time_F(START);
+ count = run_benchmark(async_jobs, SM2_sign_loop, loopargs);
+ d = Time_F(STOP);
+
+ BIO_printf(bio_err,
+ mr ? "+R10:%ld:%u:%s:%.2f\n" :
+ "%ld %u bits %s signs in %.2fs \n",
+ count, sm2_curves[testnum].bits,
+ sm2_curves[testnum].name, d);
+ sm2_results[testnum][0] = (double)count / d;
+ op_count = count;
+ }
+
+ /* Perform SM2 verification test */
+ for (i = 0; i < loopargs_len; i++) {
+ st = EVP_DigestVerify(loopargs[i].sm2_vfy_ctx[testnum],
+ loopargs[i].buf2, loopargs[i].sigsize,
+ loopargs[i].buf, 20);
+ if (st != 1)
+ break;
+ }
+ if (st != 1) {
+ BIO_printf(bio_err,
+ "SM2 verify failure. No SM2 verify will be done.\n");
+ ERR_print_errors(bio_err);
+ sm2_doit[testnum] = 0;
+ } else {
+ pkey_print_message("verify", sm2_curves[testnum].name,
+ sm2_c[testnum][1],
+ sm2_curves[testnum].bits, seconds.sm2);
+ Time_F(START);
+ count = run_benchmark(async_jobs, SM2_verify_loop, loopargs);
+ d = Time_F(STOP);
+ BIO_printf(bio_err,
+ mr ? "+R11:%ld:%u:%s:%.2f\n"
+ : "%ld %u bits %s verify in %.2fs\n",
+ count, sm2_curves[testnum].bits,
+ sm2_curves[testnum].name, d);
+ sm2_results[testnum][1] = (double)count / d;
+ }
+
+ if (op_count <= 1) {
/* if longer than 10s, don't do any more */
- for (testnum++; testnum < EdDSA_NUM; testnum++)
- eddsa_doit[testnum] = 0;
+ for (testnum++; testnum < SM2_NUM; testnum++)
+ sm2_doit[testnum] = 0;
}
}
}
+#endif /* OPENSSL_NO_SM2 */
+
+#ifndef OPENSSL_NO_DH
+ for (testnum = 0; testnum < FFDH_NUM; testnum++) {
+ int ffdh_checks = 1;
+
+ if (!ffdh_doit[testnum])
+ continue;
+
+ for (i = 0; i < loopargs_len; i++) {
+ EVP_PKEY *pkey_A = NULL;
+ EVP_PKEY *pkey_B = NULL;
+ EVP_PKEY_CTX *ffdh_ctx = NULL;
+ EVP_PKEY_CTX *test_ctx = NULL;
+ size_t secret_size;
+ size_t test_out;
+
+ /* Ensure that the error queue is empty */
+ if (ERR_peek_error()) {
+ BIO_printf(bio_err,
+ "WARNING: the error queue contains previous unhandled errors.\n");
+ ERR_print_errors(bio_err);
+ }
-#endif /* OPENSSL_NO_EC */
+ pkey_A = EVP_PKEY_new();
+ if (!pkey_A) {
+ BIO_printf(bio_err, "Error while initialising EVP_PKEY (out of memory?).\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ pkey_B = EVP_PKEY_new();
+ if (!pkey_B) {
+ BIO_printf(bio_err, "Error while initialising EVP_PKEY (out of memory?).\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+
+ ffdh_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL);
+ if (!ffdh_ctx) {
+ BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+
+ if (EVP_PKEY_keygen_init(ffdh_ctx) <= 0) {
+ BIO_printf(bio_err, "Error while initialising EVP_PKEY_CTX.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ if (EVP_PKEY_CTX_set_dh_nid(ffdh_ctx, ffdh_params[testnum].nid) <= 0) {
+ BIO_printf(bio_err, "Error setting DH key size for keygen.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+
+ if (EVP_PKEY_keygen(ffdh_ctx, &pkey_A) <= 0 ||
+ EVP_PKEY_keygen(ffdh_ctx, &pkey_B) <= 0) {
+ BIO_printf(bio_err, "FFDH key generation failure.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+
+ EVP_PKEY_CTX_free(ffdh_ctx);
+
+ /*
+ * check if the derivation works correctly both ways so that
+ * we know if future derive calls will fail, and we can skip
+ * error checking in benchmarked code
+ */
+ ffdh_ctx = EVP_PKEY_CTX_new(pkey_A, NULL);
+ if (ffdh_ctx == NULL) {
+ BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ if (EVP_PKEY_derive_init(ffdh_ctx) <= 0) {
+ BIO_printf(bio_err, "FFDH derivation context init failure.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ if (EVP_PKEY_derive_set_peer(ffdh_ctx, pkey_B) <= 0) {
+ BIO_printf(bio_err, "Assigning peer key for derivation failed.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ if (EVP_PKEY_derive(ffdh_ctx, NULL, &secret_size) <= 0) {
+ BIO_printf(bio_err, "Checking size of shared secret failed.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ if (secret_size > MAX_FFDH_SIZE) {
+ BIO_printf(bio_err, "Assertion failure: shared secret too large.\n");
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ if (EVP_PKEY_derive(ffdh_ctx,
+ loopargs[i].secret_ff_a,
+ &secret_size) <= 0) {
+ BIO_printf(bio_err, "Shared secret derive failure.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ /* Now check from side B */
+ test_ctx = EVP_PKEY_CTX_new(pkey_B, NULL);
+ if (!test_ctx) {
+ BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ if (EVP_PKEY_derive_init(test_ctx) <= 0 ||
+ EVP_PKEY_derive_set_peer(test_ctx, pkey_A) <= 0 ||
+ EVP_PKEY_derive(test_ctx, NULL, &test_out) <= 0 ||
+ EVP_PKEY_derive(test_ctx, loopargs[i].secret_ff_b, &test_out) <= 0 ||
+ test_out != secret_size) {
+ BIO_printf(bio_err, "FFDH computation failure.\n");
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+
+ /* compare the computed secrets */
+ if (CRYPTO_memcmp(loopargs[i].secret_ff_a,
+ loopargs[i].secret_ff_b, secret_size)) {
+ BIO_printf(bio_err, "FFDH computations don't match.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+
+ loopargs[i].ffdh_ctx[testnum] = ffdh_ctx;
+
+ EVP_PKEY_free(pkey_A);
+ pkey_A = NULL;
+ EVP_PKEY_free(pkey_B);
+ pkey_B = NULL;
+ EVP_PKEY_CTX_free(test_ctx);
+ test_ctx = NULL;
+ }
+ if (ffdh_checks != 0) {
+ pkey_print_message("", "ffdh", ffdh_c[testnum][0],
+ ffdh_params[testnum].bits, seconds.ffdh);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, FFDH_derive_key_loop, loopargs);
+ d = Time_F(STOP);
+ BIO_printf(bio_err,
+ mr ? "+R12:%ld:%d:%.2f\n" :
+ "%ld %u-bits FFDH ops in %.2fs\n", count,
+ ffdh_params[testnum].bits, d);
+ ffdh_results[testnum][0] = (double)count / d;
+ op_count = count;
+ }
+ if (op_count <= 1) {
+ /* if longer than 10s, don't do any more */
+ stop_it(ffdh_doit, testnum);
+ }
+ }
+#endif /* OPENSSL_NO_DH */
#ifndef NO_FORK
show_res:
#endif
if (!mr) {
- printf("%s\n", OpenSSL_version(OPENSSL_VERSION));
+ printf("version: %s\n", OpenSSL_version(OPENSSL_FULL_VERSION_STRING));
printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON));
- printf("options:");
- printf("%s ", BN_options());
-#ifndef OPENSSL_NO_MD2
- printf("%s ", MD2_options());
-#endif
-#ifndef OPENSSL_NO_RC4
- printf("%s ", RC4_options());
-#endif
-#ifndef OPENSSL_NO_DES
- printf("%s ", DES_options());
-#endif
- printf("%s ", AES_options());
-#ifndef OPENSSL_NO_IDEA
- printf("%s ", IDEA_options());
-#endif
-#ifndef OPENSSL_NO_BF
- printf("%s ", BF_options());
-#endif
- printf("\n%s\n", OpenSSL_version(OPENSSL_CFLAGS));
+ printf("options: %s\n", BN_options());
+ printf("%s\n", OpenSSL_version(OPENSSL_CFLAGS));
+ printf("%s\n", OpenSSL_version(OPENSSL_CPU_INFO));
}
if (pr_header) {
- if (mr)
+ if (mr) {
printf("+H");
- else {
- printf
- ("The 'numbers' are in 1000s of bytes per second processed.\n");
+ } else {
+ printf("The 'numbers' are in 1000s of bytes per second processed.\n");
printf("type ");
}
for (testnum = 0; testnum < size_num; testnum++)
@@ -3252,7 +3147,6 @@ int speed_main(int argc, char **argv)
}
printf("\n");
}
-#ifndef OPENSSL_NO_RSA
testnum = 1;
for (k = 0; k < RSA_NUM; k++) {
if (!rsa_doit[k])
@@ -3263,14 +3157,12 @@ int speed_main(int argc, char **argv)
}
if (mr)
printf("+F2:%u:%u:%f:%f\n",
- k, rsa_bits[k], rsa_results[k][0], rsa_results[k][1]);
+ k, rsa_keys[k].bits, rsa_results[k][0], rsa_results[k][1]);
else
printf("rsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
- rsa_bits[k], 1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1],
+ rsa_keys[k].bits, 1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1],
rsa_results[k][0], rsa_results[k][1]);
}
-#endif
-#ifndef OPENSSL_NO_DSA
testnum = 1;
for (k = 0; k < DSA_NUM; k++) {
if (!dsa_doit[k])
@@ -3287,8 +3179,6 @@ int speed_main(int argc, char **argv)
dsa_bits[k], 1.0 / dsa_results[k][0], 1.0 / dsa_results[k][1],
dsa_results[k][0], dsa_results[k][1]);
}
-#endif
-#ifndef OPENSSL_NO_EC
testnum = 1;
for (k = 0; k < OSSL_NELEM(ecdsa_doit); k++) {
if (!ecdsa_doit[k])
@@ -3300,11 +3190,11 @@ int speed_main(int argc, char **argv)
if (mr)
printf("+F4:%u:%u:%f:%f\n",
- k, test_curves[k].bits,
+ k, ec_curves[k].bits,
ecdsa_results[k][0], ecdsa_results[k][1]);
else
printf("%4u bits ecdsa (%s) %8.4fs %8.4fs %8.1f %8.1f\n",
- test_curves[k].bits, test_curves[k].name,
+ ec_curves[k].bits, ec_curves[k].name,
1.0 / ecdsa_results[k][0], 1.0 / ecdsa_results[k][1],
ecdsa_results[k][0], ecdsa_results[k][1]);
}
@@ -3319,12 +3209,12 @@ int speed_main(int argc, char **argv)
}
if (mr)
printf("+F5:%u:%u:%f:%f\n",
- k, test_curves[k].bits,
+ k, ec_curves[k].bits,
ecdh_results[k][0], 1.0 / ecdh_results[k][0]);
else
printf("%4u bits ecdh (%s) %8.4fs %8.1f\n",
- test_curves[k].bits, test_curves[k].name,
+ ec_curves[k].bits, ec_curves[k].name,
1.0 / ecdh_results[k][0], ecdh_results[k][0]);
}
@@ -3339,15 +3229,56 @@ int speed_main(int argc, char **argv)
if (mr)
printf("+F6:%u:%u:%s:%f:%f\n",
- k, test_ed_curves[k].bits, test_ed_curves[k].name,
+ k, ed_curves[k].bits, ed_curves[k].name,
eddsa_results[k][0], eddsa_results[k][1]);
else
printf("%4u bits EdDSA (%s) %8.4fs %8.4fs %8.1f %8.1f\n",
- test_ed_curves[k].bits, test_ed_curves[k].name,
+ ed_curves[k].bits, ed_curves[k].name,
1.0 / eddsa_results[k][0], 1.0 / eddsa_results[k][1],
eddsa_results[k][0], eddsa_results[k][1]);
}
+
+#ifndef OPENSSL_NO_SM2
+ testnum = 1;
+ for (k = 0; k < OSSL_NELEM(sm2_doit); k++) {
+ if (!sm2_doit[k])
+ continue;
+ if (testnum && !mr) {
+ printf("%30ssign verify sign/s verify/s\n", " ");
+ testnum = 0;
+ }
+
+ if (mr)
+ printf("+F7:%u:%u:%s:%f:%f\n",
+ k, sm2_curves[k].bits, sm2_curves[k].name,
+ sm2_results[k][0], sm2_results[k][1]);
+ else
+ printf("%4u bits SM2 (%s) %8.4fs %8.4fs %8.1f %8.1f\n",
+ sm2_curves[k].bits, sm2_curves[k].name,
+ 1.0 / sm2_results[k][0], 1.0 / sm2_results[k][1],
+ sm2_results[k][0], sm2_results[k][1]);
+ }
#endif
+#ifndef OPENSSL_NO_DH
+ testnum = 1;
+ for (k = 0; k < FFDH_NUM; k++) {
+ if (!ffdh_doit[k])
+ continue;
+ if (testnum && !mr) {
+ printf("%23sop op/s\n", " ");
+ testnum = 0;
+ }
+ if (mr)
+ printf("+F8:%u:%u:%f:%f\n",
+ k, ffdh_params[k].bits,
+ ffdh_results[k][0], 1.0 / ffdh_results[k][0]);
+
+ else
+ printf("%4u bits ffdh %8.4fs %8.1f\n",
+ ffdh_params[k].bits,
+ 1.0 / ffdh_results[k][0], ffdh_results[k][0]);
+ }
+#endif /* OPENSSL_NO_DH */
ret = 0;
@@ -3357,25 +3288,55 @@ int speed_main(int argc, char **argv)
OPENSSL_free(loopargs[i].buf_malloc);
OPENSSL_free(loopargs[i].buf2_malloc);
-#ifndef OPENSSL_NO_RSA
- for (k = 0; k < RSA_NUM; k++)
- RSA_free(loopargs[i].rsa_key[k]);
-#endif
-#ifndef OPENSSL_NO_DSA
- for (k = 0; k < DSA_NUM; k++)
- DSA_free(loopargs[i].dsa_key[k]);
+ BN_free(bn);
+ EVP_PKEY_CTX_free(genctx);
+ for (k = 0; k < RSA_NUM; k++) {
+ EVP_PKEY_CTX_free(loopargs[i].rsa_sign_ctx[k]);
+ EVP_PKEY_CTX_free(loopargs[i].rsa_verify_ctx[k]);
+ }
+#ifndef OPENSSL_NO_DH
+ OPENSSL_free(loopargs[i].secret_ff_a);
+ OPENSSL_free(loopargs[i].secret_ff_b);
+ for (k = 0; k < FFDH_NUM; k++)
+ EVP_PKEY_CTX_free(loopargs[i].ffdh_ctx[k]);
#endif
-#ifndef OPENSSL_NO_EC
- for (k = 0; k < ECDSA_NUM; k++)
- EC_KEY_free(loopargs[i].ecdsa[k]);
+ for (k = 0; k < DSA_NUM; k++) {
+ EVP_PKEY_CTX_free(loopargs[i].dsa_sign_ctx[k]);
+ EVP_PKEY_CTX_free(loopargs[i].dsa_verify_ctx[k]);
+ }
+ for (k = 0; k < ECDSA_NUM; k++) {
+ EVP_PKEY_CTX_free(loopargs[i].ecdsa_sign_ctx[k]);
+ EVP_PKEY_CTX_free(loopargs[i].ecdsa_verify_ctx[k]);
+ }
for (k = 0; k < EC_NUM; k++)
EVP_PKEY_CTX_free(loopargs[i].ecdh_ctx[k]);
- for (k = 0; k < EdDSA_NUM; k++)
+ for (k = 0; k < EdDSA_NUM; k++) {
EVP_MD_CTX_free(loopargs[i].eddsa_ctx[k]);
+ EVP_MD_CTX_free(loopargs[i].eddsa_ctx2[k]);
+ }
+#ifndef OPENSSL_NO_SM2
+ for (k = 0; k < SM2_NUM; k++) {
+ EVP_PKEY_CTX *pctx = NULL;
+
+ /* free signing ctx */
+ if (loopargs[i].sm2_ctx[k] != NULL
+ && (pctx = EVP_MD_CTX_get_pkey_ctx(loopargs[i].sm2_ctx[k])) != NULL)
+ EVP_PKEY_CTX_free(pctx);
+ EVP_MD_CTX_free(loopargs[i].sm2_ctx[k]);
+ /* free verification ctx */
+ if (loopargs[i].sm2_vfy_ctx[k] != NULL
+ && (pctx = EVP_MD_CTX_get_pkey_ctx(loopargs[i].sm2_vfy_ctx[k])) != NULL)
+ EVP_PKEY_CTX_free(pctx);
+ EVP_MD_CTX_free(loopargs[i].sm2_vfy_ctx[k]);
+ /* free pkey */
+ EVP_PKEY_free(loopargs[i].sm2_pkey[k]);
+ }
+#endif
OPENSSL_free(loopargs[i].secret_a);
OPENSSL_free(loopargs[i].secret_b);
-#endif
}
+ OPENSSL_free(evp_hmac_name);
+ OPENSSL_free(evp_cmac_name);
if (async_jobs > 0) {
for (i = 0; i < loopargs_len; i++)
@@ -3387,49 +3348,38 @@ int speed_main(int argc, char **argv)
}
OPENSSL_free(loopargs);
release_engine(e);
+ EVP_CIPHER_free(evp_cipher);
+ EVP_MAC_free(mac);
return ret;
}
static void print_message(const char *s, long num, int length, int tm)
{
-#ifdef SIGALRM
BIO_printf(bio_err,
mr ? "+DT:%s:%d:%d\n"
: "Doing %s for %ds on %d size blocks: ", s, tm, length);
(void)BIO_flush(bio_err);
run = 1;
alarm(tm);
-#else
- BIO_printf(bio_err,
- mr ? "+DN:%s:%ld:%d\n"
- : "Doing %s %ld times on %d size blocks: ", s, num, length);
- (void)BIO_flush(bio_err);
-#endif
}
static void pkey_print_message(const char *str, const char *str2, long num,
unsigned int bits, int tm)
{
-#ifdef SIGALRM
BIO_printf(bio_err,
mr ? "+DTP:%d:%s:%s:%d\n"
: "Doing %u bits %s %s's for %ds: ", bits, str, str2, tm);
(void)BIO_flush(bio_err);
run = 1;
alarm(tm);
-#else
- BIO_printf(bio_err,
- mr ? "+DNP:%ld:%d:%s:%s\n"
- : "Doing %ld %u bits %s %s's: ", num, bits, str, str2);
- (void)BIO_flush(bio_err);
-#endif
}
static void print_result(int alg, int run_no, int count, double time_used)
{
if (count == -1) {
- BIO_puts(bio_err, "EVP error!\n");
- exit(1);
+ BIO_printf(bio_err, "%s error!\n", names[alg]);
+ ERR_print_errors(bio_err);
+ return;
}
BIO_printf(bio_err,
mr ? "+R:%d:%s:%f\n"
@@ -3454,9 +3404,8 @@ static char *sstrsep(char **string, const char *delim)
delim++;
}
- while (!isdelim[(unsigned char)(**string)]) {
+ while (!isdelim[(unsigned char)(**string)])
(*string)++;
- }
if (**string) {
**string = 0;
@@ -3471,6 +3420,7 @@ static int do_multi(int multi, int size_num)
int n;
int fd[2];
int *fds;
+ int status;
static char sep[] = ":";
fds = app_malloc(sizeof(*fds) * multi, "fd buffer for do_multi");
@@ -3506,7 +3456,12 @@ static int do_multi(int multi, int size_num)
char buf[1024];
char *p;
- f = fdopen(fds[n], "r");
+ if ((f = fdopen(fds[n], "r")) == NULL) {
+ BIO_printf(bio_err, "fdopen failure with 0x%x\n",
+ errno);
+ OPENSSL_free(fds);
+ return 1;
+ }
while (fgets(buf, sizeof(buf), f)) {
p = strchr(buf, '\n');
if (p)
@@ -3540,9 +3495,7 @@ static int do_multi(int multi, int size_num)
d = atof(sstrsep(&p, sep));
rsa_results[k][1] += d;
- }
-# ifndef OPENSSL_NO_DSA
- else if (strncmp(buf, "+F3:", 4) == 0) {
+ } else if (strncmp(buf, "+F3:", 4) == 0) {
int k;
double d;
@@ -3555,10 +3508,7 @@ static int do_multi(int multi, int size_num)
d = atof(sstrsep(&p, sep));
dsa_results[k][1] += d;
- }
-# endif
-# ifndef OPENSSL_NO_EC
- else if (strncmp(buf, "+F4:", 4) == 0) {
+ } else if (strncmp(buf, "+F4:", 4) == 0) {
int k;
double d;
@@ -3595,19 +3545,59 @@ static int do_multi(int multi, int size_num)
d = atof(sstrsep(&p, sep));
eddsa_results[k][1] += d;
- }
-# endif
+# ifndef OPENSSL_NO_SM2
+ } else if (strncmp(buf, "+F7:", 4) == 0) {
+ int k;
+ double d;
- else if (strncmp(buf, "+H:", 3) == 0) {
+ p = buf + 4;
+ k = atoi(sstrsep(&p, sep));
+ sstrsep(&p, sep);
+ sstrsep(&p, sep);
+
+ d = atof(sstrsep(&p, sep));
+ sm2_results[k][0] += d;
+
+ d = atof(sstrsep(&p, sep));
+ sm2_results[k][1] += d;
+# endif /* OPENSSL_NO_SM2 */
+# ifndef OPENSSL_NO_DH
+ } else if (strncmp(buf, "+F8:", 4) == 0) {
+ int k;
+ double d;
+
+ p = buf + 4;
+ k = atoi(sstrsep(&p, sep));
+ sstrsep(&p, sep);
+
+ d = atof(sstrsep(&p, sep));
+ ffdh_results[k][0] += d;
+# endif /* OPENSSL_NO_DH */
+ } else if (strncmp(buf, "+H:", 3) == 0) {
;
- } else
+ } else {
BIO_printf(bio_err, "Unknown type '%s' from child %d\n", buf,
n);
+ }
}
fclose(f);
}
OPENSSL_free(fds);
+ for (n = 0; n < multi; ++n) {
+ while (wait(&status) == -1)
+ if (errno != EINTR) {
+ BIO_printf(bio_err, "Waitng for child failed with 0x%x\n",
+ errno);
+ return 1;
+ }
+ if (WIFEXITED(status) && WEXITSTATUS(status)) {
+ BIO_printf(bio_err, "Child exited with %d\n", WEXITSTATUS(status));
+ } else if (WIFSIGNALED(status)) {
+ BIO_printf(bio_err, "Child terminated by signal %d\n",
+ WTERMSIG(status));
+ }
+ }
return 1;
}
#endif
@@ -3620,8 +3610,8 @@ static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
const int *mblengths = mblengths_list;
int j, count, keylen, num = OSSL_NELEM(mblengths_list);
const char *alg_name;
- unsigned char *inp, *out, *key, no_key[32], no_iv[16];
- EVP_CIPHER_CTX *ctx;
+ unsigned char *inp = NULL, *out = NULL, *key, no_key[32], no_iv[16];
+ EVP_CIPHER_CTX *ctx = NULL;
double d = 0.0;
if (lengths_single) {
@@ -3631,22 +3621,32 @@ static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
inp = app_malloc(mblengths[num - 1], "multiblock input buffer");
out = app_malloc(mblengths[num - 1] + 1024, "multiblock output buffer");
- ctx = EVP_CIPHER_CTX_new();
- EVP_EncryptInit_ex(ctx, evp_cipher, NULL, NULL, no_iv);
+ if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
+ app_bail_out("failed to allocate cipher context\n");
+ if (!EVP_EncryptInit_ex(ctx, evp_cipher, NULL, NULL, no_iv))
+ app_bail_out("failed to initialise cipher context\n");
- keylen = EVP_CIPHER_CTX_key_length(ctx);
+ if ((keylen = EVP_CIPHER_CTX_get_key_length(ctx)) < 0) {
+ BIO_printf(bio_err, "Impossible negative key length: %d\n", keylen);
+ goto err;
+ }
key = app_malloc(keylen, "evp_cipher key");
- EVP_CIPHER_CTX_rand_key(ctx, key);
- EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL);
+ if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
+ app_bail_out("failed to generate random cipher key\n");
+ if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL))
+ app_bail_out("failed to set cipher key\n");
OPENSSL_clear_free(key, keylen);
- EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_MAC_KEY, sizeof(no_key), no_key);
- alg_name = OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher));
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_MAC_KEY,
+ sizeof(no_key), no_key) <= 0)
+ app_bail_out("failed to set AEAD key\n");
+ if ((alg_name = EVP_CIPHER_get0_name(evp_cipher)) == NULL)
+ app_bail_out("failed to get cipher name\n");
for (j = 0; j < num; j++) {
print_message(alg_name, 0, mblengths[j], seconds->sym);
Time_F(START);
- for (count = 0; run && count < 0x7fffffff; count++) {
+ for (count = 0; run && count < INT_MAX; count++) {
unsigned char aad[EVP_AEAD_TLS1_AAD_LEN];
EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
size_t len = mblengths[j];
@@ -3670,8 +3670,9 @@ static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
mb_param.out = out;
mb_param.inp = inp;
mb_param.len = len;
- EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
- sizeof(mb_param), &mb_param);
+ (void)EVP_CIPHER_CTX_ctrl(ctx,
+ EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
+ sizeof(mb_param), &mb_param);
} else {
int pad;
@@ -3717,6 +3718,7 @@ static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
fprintf(stdout, "\n");
}
+ err:
OPENSSL_free(inp);
OPENSSL_free(out);
EVP_CIPHER_CTX_free(ctx);
diff --git a/apps/spkac.c b/apps/spkac.c
index f384af6eb60b..d92be7d6450e 100644
--- a/apps/spkac.c
+++ b/apps/spkac.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -21,29 +21,38 @@
#include <openssl/pem.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_NOOUT, OPT_PUBKEY, OPT_VERIFY, OPT_IN, OPT_OUT,
OPT_ENGINE, OPT_KEY, OPT_CHALLENGE, OPT_PASSIN, OPT_SPKAC,
- OPT_SPKSECT, OPT_KEYFORM
+ OPT_SPKSECT, OPT_KEYFORM, OPT_DIGEST,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS spkac_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"spksect", OPT_SPKSECT, 's',
+ "Specify the name of an SPKAC-dedicated section of configuration"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file"},
- {"out", OPT_OUT, '>', "Output file"},
{"key", OPT_KEY, '<', "Create SPKAC using private key"},
- {"keyform", OPT_KEYFORM, 'f', "Private key file format - default PEM (PEM, DER, or ENGINE)"},
+ {"keyform", OPT_KEYFORM, 'f', "Private key file format (ENGINE, other values ignored)"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"challenge", OPT_CHALLENGE, 's', "Challenge string"},
{"spkac", OPT_SPKAC, 's', "Alternative SPKAC name"},
+
+ OPT_SECTION("Output"),
+ {"digest", OPT_DIGEST, 's', "Sign new SPKAC with the specified digest (default: MD5)" },
+ {"out", OPT_OUT, '>', "Output file"},
{"noout", OPT_NOOUT, '-', "Don't print SPKAC"},
{"pubkey", OPT_PUBKEY, '-', "Output public key"},
{"verify", OPT_VERIFY, '-', "Verify SPKAC signature"},
- {"spksect", OPT_SPKSECT, 's',
- "Specify the name of an SPKAC-dedicated section of configuration"},
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
+
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -58,8 +67,10 @@ int spkac_main(int argc, char **argv)
char *infile = NULL, *outfile = NULL, *passinarg = NULL, *passin = NULL;
char *spkstr = NULL, *prog;
const char *spkac = "SPKAC", *spksect = "default";
+ const char *digest = "MD5";
+ EVP_MD *md = NULL;
int i, ret = 1, verify = 0, noout = 0, pubkey = 0;
- int keyformat = FORMAT_PEM;
+ int keyformat = FORMAT_UNDEF;
OPTION_CHOICE o;
prog = opt_init(argc, argv, spkac_options);
@@ -108,11 +119,20 @@ int spkac_main(int argc, char **argv)
case OPT_SPKSECT:
spksect = opt_arg();
break;
+ case OPT_DIGEST:
+ digest = opt_arg();
+ break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
@@ -123,6 +143,9 @@ int spkac_main(int argc, char **argv)
}
if (keyfile != NULL) {
+ if (!opt_md(digest, &md))
+ goto end;
+
pkey = load_key(strcmp(keyfile, "-") ? keyfile : NULL,
keyformat, 1, passin, e, "private key");
if (pkey == NULL)
@@ -133,8 +156,15 @@ int spkac_main(int argc, char **argv)
if (challenge != NULL)
ASN1_STRING_set(spki->spkac->challenge,
challenge, (int)strlen(challenge));
- NETSCAPE_SPKI_set_pubkey(spki, pkey);
- NETSCAPE_SPKI_sign(spki, pkey, EVP_md5());
+ if (!NETSCAPE_SPKI_set_pubkey(spki, pkey)) {
+ BIO_printf(bio_err, "Error setting public key\n");
+ goto end;
+ }
+ i = NETSCAPE_SPKI_sign(spki, pkey, md);
+ if (i <= 0) {
+ BIO_printf(bio_err, "Error signing SPKAC\n");
+ goto end;
+ }
spkstr = NETSCAPE_SPKI_b64_encode(spki);
if (spkstr == NULL)
goto end;
@@ -192,6 +222,7 @@ int spkac_main(int argc, char **argv)
ret = 0;
end:
+ EVP_MD_free(md);
NCONF_free(conf);
NETSCAPE_SPKI_free(spki);
BIO_free_all(out);
diff --git a/apps/srp.c b/apps/srp.c
index 6c5817387973..a9466f830289 100644
--- a/apps/srp.c
+++ b/apps/srp.c
@@ -1,8 +1,8 @@
/*
- * Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2004, EdelKey Project. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,7 +11,11 @@
* for the EdelKey project.
*/
+/* SRP is deprecated, so we're going to have to use some deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <openssl/opensslconf.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -186,31 +190,42 @@ static char *srp_create_user(char *user, char **srp_verifier,
}
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_VERBOSE, OPT_CONFIG, OPT_NAME, OPT_SRPVFILE, OPT_ADD,
OPT_DELETE, OPT_MODIFY, OPT_LIST, OPT_GN, OPT_USERINFO,
- OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE, OPT_R_ENUM
+ OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE, OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS srp_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [user...]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"verbose", OPT_VERBOSE, '-', "Talk a lot while doing things"},
{"config", OPT_CONFIG, '<', "A config file"},
{"name", OPT_NAME, 's', "The particular srp definition to use"},
- {"srpvfile", OPT_SRPVFILE, '<', "The srp verifier file name"},
- {"add", OPT_ADD, '-', "Add a user and srp verifier"},
- {"modify", OPT_MODIFY, '-',
- "Modify the srp verifier of an existing user"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Action"),
+ {"add", OPT_ADD, '-', "Add a user and SRP verifier"},
+ {"modify", OPT_MODIFY, '-', "Modify the SRP verifier of an existing user"},
{"delete", OPT_DELETE, '-', "Delete user from verifier file"},
{"list", OPT_LIST, '-', "List users"},
+
+ OPT_SECTION("Configuration"),
+ {"srpvfile", OPT_SRPVFILE, '<', "The srp verifier file name"},
{"gn", OPT_GN, 's', "Set g and N values to be used for new verifier"},
{"userinfo", OPT_USERINFO, 's', "Additional info to be set for user"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+
OPT_R_OPTIONS,
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"user", 0, 0, "Username(s) to process (optional)"},
{NULL}
};
@@ -283,11 +298,20 @@ int srp_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* Optional parameters are usernames. */
argc = opt_num_rest();
argv = opt_rest();
+ if (!app_RAND_load())
+ goto end;
+
if (srpvfile != NULL && configfile != NULL) {
BIO_printf(bio_err,
"-srpvfile and -configfile cannot be specified together.\n");
@@ -320,10 +344,7 @@ int srp_main(int argc, char **argv)
if (configfile == NULL)
configfile = default_config_file;
- if (verbose)
- BIO_printf(bio_err, "Using configuration from %s\n",
- configfile);
- conf = app_load_config(configfile);
+ conf = app_load_config_verbose(configfile, verbose);
if (conf == NULL)
goto end;
if (configfile != default_config_file && !app_load_modules(conf))
@@ -358,8 +379,10 @@ int srp_main(int argc, char **argv)
srpvfile);
db = load_index(srpvfile, NULL);
- if (db == NULL)
+ if (db == NULL) {
+ BIO_printf(bio_err, "Problem with index file: %s (could not load/parse file)\n", srpvfile);
goto end;
+ }
/* Lets check some fields */
for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
diff --git a/apps/storeutl.c b/apps/storeutl.c
index 644fe28499d6..30c9915de3e8 100644
--- a/apps/storeutl.c
+++ b/apps/storeutl.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -19,24 +19,29 @@
static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
int expected, int criterion, OSSL_STORE_SEARCH *search,
int text, int noout, int recursive, int indent, BIO *out,
- const char *prog);
+ const char *prog, OSSL_LIB_CTX *libctx);
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE, OPT_OUT, OPT_PASSIN,
+ OPT_COMMON,
+ OPT_ENGINE, OPT_OUT, OPT_PASSIN,
OPT_NOOUT, OPT_TEXT, OPT_RECURSIVE,
OPT_SEARCHFOR_CERTS, OPT_SEARCHFOR_KEYS, OPT_SEARCHFOR_CRLS,
OPT_CRITERION_SUBJECT, OPT_CRITERION_ISSUER, OPT_CRITERION_SERIAL,
OPT_CRITERION_FINGERPRINT, OPT_CRITERION_ALIAS,
- OPT_MD
+ OPT_MD, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS storeutl_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [options] uri\nValid options are:\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] uri\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"out", OPT_OUT, '>', "Output file - default stdout"},
- {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
- {"text", OPT_TEXT, '-', "Print a text form of the objects"},
- {"noout", OPT_NOOUT, '-', "No PEM output, just status"},
+ {"", OPT_MD, '-', "Any supported digest"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Search"),
{"certs", OPT_SEARCHFOR_CERTS, '-', "Search for certificates only"},
{"keys", OPT_SEARCHFOR_KEYS, '-', "Search for keys only"},
{"crls", OPT_SEARCHFOR_CRLS, '-', "Search for CRLs only"},
@@ -45,11 +50,20 @@ const OPTIONS storeutl_options[] = {
{"serial", OPT_CRITERION_SERIAL, 's', "Search by issuer and serial, serial number"},
{"fingerprint", OPT_CRITERION_FINGERPRINT, 's', "Search by public key fingerprint, given in hex"},
{"alias", OPT_CRITERION_ALIAS, 's', "Search by alias"},
- {"", OPT_MD, '-', "Any supported digest"},
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
{"r", OPT_RECURSIVE, '-', "Recurse through names"},
+
+ OPT_SECTION("Input"),
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file - default stdout"},
+ {"text", OPT_TEXT, '-', "Print a text form of the objects"},
+ {"noout", OPT_NOOUT, '-', "No PEM output, just status"},
+
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"uri", 0, 0, "URI of the store object"},
{NULL}
};
@@ -68,9 +82,10 @@ int storeutl_main(int argc, char *argv[])
ASN1_INTEGER *serial = NULL;
unsigned char *fingerprint = NULL;
size_t fingerprintlen = 0;
- char *alias = NULL;
+ char *alias = NULL, *digestname = NULL;
OSSL_STORE_SEARCH *search = NULL;
- const EVP_MD *digest = NULL;
+ EVP_MD *digest = NULL;
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
@@ -142,16 +157,13 @@ int storeutl_main(int argc, char *argv[])
prog);
goto end;
}
- if ((subject = parse_name(opt_arg(), MBSTRING_UTF8, 1)) == NULL) {
- BIO_printf(bio_err, "%s: can't parse subject argument.\n",
- prog);
+ subject = parse_name(opt_arg(), MBSTRING_UTF8, 1, "subject");
+ if (subject == NULL)
goto end;
- }
break;
case OPT_CRITERION_ISSUER:
if (criterion != 0
- || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL
- && issuer != NULL)) {
+ && criterion != OSSL_STORE_SEARCH_BY_ISSUER_SERIAL) {
BIO_printf(bio_err, "%s: criterion already given.\n",
prog);
goto end;
@@ -162,16 +174,13 @@ int storeutl_main(int argc, char *argv[])
prog);
goto end;
}
- if ((issuer = parse_name(opt_arg(), MBSTRING_UTF8, 1)) == NULL) {
- BIO_printf(bio_err, "%s: can't parse issuer argument.\n",
- prog);
+ issuer = parse_name(opt_arg(), MBSTRING_UTF8, 1, "issuer");
+ if (issuer == NULL)
goto end;
- }
break;
case OPT_CRITERION_SERIAL:
if (criterion != 0
- || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL
- && serial != NULL)) {
+ && criterion != OSSL_STORE_SEARCH_BY_ISSUER_SERIAL) {
BIO_printf(bio_err, "%s: criterion already given.\n",
prog);
goto end;
@@ -237,20 +246,24 @@ int storeutl_main(int argc, char *argv[])
e = setup_engine(opt_arg(), 0);
break;
case OPT_MD:
- if (!opt_md(opt_unknown(), &digest))
- goto opthelp;
+ digestname = opt_unknown();
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* One argument, the URI */
argc = opt_num_rest();
argv = opt_rest();
-
- if (argc == 0) {
- BIO_printf(bio_err, "%s: No URI given, nothing to do...\n", prog);
- goto opthelp;
- }
- if (argc > 1) {
- BIO_printf(bio_err, "%s: Unknown extra parameters after URI\n", prog);
+ if (argc != 1)
goto opthelp;
+
+ if (digestname != NULL) {
+ if (!opt_md(digestname, &digest))
+ goto opthelp;
}
if (criterion != 0) {
@@ -305,9 +318,10 @@ int storeutl_main(int argc, char *argv[])
ret = process(argv[0], get_ui_method(), &pw_cb_data,
expected, criterion, search,
- text, noout, recursive, 0, out, prog);
+ text, noout, recursive, 0, out, prog, libctx);
end:
+ EVP_MD_free(digest);
OPENSSL_free(fingerprint);
OPENSSL_free(alias);
ASN1_INTEGER_free(serial);
@@ -336,12 +350,13 @@ static int indent_printf(int indent, BIO *bio, const char *format, ...)
static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
int expected, int criterion, OSSL_STORE_SEARCH *search,
int text, int noout, int recursive, int indent, BIO *out,
- const char *prog)
+ const char *prog, OSSL_LIB_CTX *libctx)
{
OSSL_STORE_CTX *store_ctx = NULL;
int ret = 1, items = 0;
- if ((store_ctx = OSSL_STORE_open(uri, uimeth, uidata, NULL, NULL))
+ if ((store_ctx = OSSL_STORE_open_ex(uri, libctx, app_get0_propq(), uimeth, uidata,
+ NULL, NULL, NULL))
== NULL) {
BIO_printf(bio_err, "Couldn't open file or uri %s\n", uri);
ERR_print_errors(bio_err);
@@ -379,18 +394,20 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
info == NULL ? NULL : OSSL_STORE_INFO_type_string(type);
if (info == NULL) {
- if (OSSL_STORE_eof(store_ctx))
- break;
-
if (OSSL_STORE_error(store_ctx)) {
if (recursive)
ERR_clear_error();
else
ERR_print_errors(bio_err);
+ if (OSSL_STORE_eof(store_ctx))
+ break;
ret++;
continue;
}
+ if (OSSL_STORE_eof(store_ctx))
+ break;
+
BIO_printf(bio_err,
"ERROR: OSSL_STORE_load() returned NULL without "
"eof or error indications\n");
@@ -422,7 +439,8 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
const char *suburi = OSSL_STORE_INFO_get0_NAME(info);
ret += process(suburi, uimeth, uidata,
expected, criterion, search,
- text, noout, recursive, indent + 2, out, prog);
+ text, noout, recursive, indent + 2, out, prog,
+ libctx);
}
break;
case OSSL_STORE_INFO_PARAMS:
@@ -433,6 +451,13 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
PEM_write_bio_Parameters(out,
OSSL_STORE_INFO_get0_PARAMS(info));
break;
+ case OSSL_STORE_INFO_PUBKEY:
+ if (text)
+ EVP_PKEY_print_public(out, OSSL_STORE_INFO_get0_PUBKEY(info),
+ 0, NULL);
+ if (!noout)
+ PEM_write_bio_PUBKEY(out, OSSL_STORE_INFO_get0_PUBKEY(info));
+ break;
case OSSL_STORE_INFO_PKEY:
if (text)
EVP_PKEY_print_private(out, OSSL_STORE_INFO_get0_PKEY(info),
diff --git a/apps/testdsa.h b/apps/testdsa.h
index 3c4b459db117..d80d2cf7f2d2 100644
--- a/apps/testdsa.h
+++ b/apps/testdsa.h
@@ -1,14 +1,16 @@
/*
- * Copyright 1998-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#include <openssl/param_build.h>
+
/* used by speed.c */
-DSA *get_dsa(int);
+EVP_PKEY *get_dsa(int);
static unsigned char dsa512_priv[] = {
0x65, 0xe5, 0xc7, 0x38, 0x60, 0x24, 0xb5, 0x89, 0xd4, 0x9c, 0xeb, 0x4c,
@@ -211,11 +213,14 @@ typedef struct testdsa_st {
st.q_l = sizeof(dsa##bits##_q); \
} while (0)
-DSA *get_dsa(int dsa_bits)
+EVP_PKEY *get_dsa(int dsa_bits)
{
- DSA *dsa;
+ EVP_PKEY *pkey = NULL;
BIGNUM *priv_key, *pub_key, *p, *q, *g;
+ EVP_PKEY_CTX *pctx;
testdsa dsa_t;
+ OSSL_PARAM_BLD *tmpl = NULL;
+ OSSL_PARAM *params = NULL;
switch (dsa_bits) {
case 512:
@@ -231,30 +236,44 @@ DSA *get_dsa(int dsa_bits)
return NULL;
}
- if ((dsa = DSA_new()) == NULL)
+ if ((pctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL)) == NULL)
return NULL;
+
priv_key = BN_bin2bn(dsa_t.priv, dsa_t.priv_l, NULL);
pub_key = BN_bin2bn(dsa_t.pub, dsa_t.pub_l, NULL);
p = BN_bin2bn(dsa_t.p, dsa_t.p_l, NULL);
q = BN_bin2bn(dsa_t.q, dsa_t.q_l, NULL);
g = BN_bin2bn(dsa_t.g, dsa_t.g_l, NULL);
- if ((priv_key == NULL) || (pub_key == NULL) || (p == NULL) || (q == NULL)
- || (g == NULL)) {
+ if (priv_key == NULL || pub_key == NULL || p == NULL || q == NULL
+ || g == NULL) {
goto err;
}
- if (!DSA_set0_pqg(dsa, p, q, g))
- goto err;
-
- if (!DSA_set0_key(dsa, pub_key, priv_key))
+ if ((tmpl = OSSL_PARAM_BLD_new()) == NULL
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P,
+ p)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q,
+ q)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G,
+ g)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
+ priv_key)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
+ pub_key)
+ || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
goto err;
- return dsa;
- err:
- DSA_free(dsa);
+ if (EVP_PKEY_fromdata_init(pctx) <= 0
+ || EVP_PKEY_fromdata(pctx, &pkey, EVP_PKEY_KEYPAIR,
+ params) <= 0)
+ pkey = NULL;
+err:
+ OSSL_PARAM_free(params);
+ OSSL_PARAM_BLD_free(tmpl);
BN_free(priv_key);
BN_free(pub_key);
BN_free(p);
BN_free(q);
BN_free(g);
- return NULL;
+ EVP_PKEY_CTX_free(pctx);
+ return pkey;
}
diff --git a/apps/testrsa.h b/apps/testrsa.h
index 1350ce54e3fb..8c3a967414c6 100644
--- a/apps/testrsa.h
+++ b/apps/testrsa.h
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/apps/timeouts.h b/apps/timeouts.h
index 7e606cba0b20..002852724763 100644
--- a/apps/timeouts.h
+++ b/apps/timeouts.h
@@ -1,7 +1,7 @@
/*
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/apps/ts.c b/apps/ts.c
index 66a0c810e0c3..57292e187cd2 100644
--- a/apps/ts.c
+++ b/apps/ts.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -63,60 +63,68 @@ static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial);
/* Verify related functions. */
static int verify_command(const char *data, const char *digest, const char *queryfile,
const char *in, int token_in,
- const char *CApath, const char *CAfile, const char *untrusted,
- X509_VERIFY_PARAM *vpm);
+ const char *CApath, const char *CAfile,
+ const char *CAstore,
+ char *untrusted, X509_VERIFY_PARAM *vpm);
static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest,
const char *queryfile,
const char *CApath, const char *CAfile,
- const char *untrusted,
+ const char *CAstore,
+ char *untrusted,
X509_VERIFY_PARAM *vpm);
static X509_STORE *create_cert_store(const char *CApath, const char *CAfile,
- X509_VERIFY_PARAM *vpm);
+ const char *CAstore, X509_VERIFY_PARAM *vpm);
static int verify_cb(int ok, X509_STORE_CTX *ctx);
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_ENGINE, OPT_CONFIG, OPT_SECTION, OPT_QUERY, OPT_DATA,
OPT_DIGEST, OPT_TSPOLICY, OPT_NO_NONCE, OPT_CERT,
OPT_IN, OPT_TOKEN_IN, OPT_OUT, OPT_TOKEN_OUT, OPT_TEXT,
OPT_REPLY, OPT_QUERYFILE, OPT_PASSIN, OPT_INKEY, OPT_SIGNER,
- OPT_CHAIN, OPT_VERIFY, OPT_CAPATH, OPT_CAFILE, OPT_UNTRUSTED,
- OPT_MD, OPT_V_ENUM, OPT_R_ENUM
+ OPT_CHAIN, OPT_VERIFY, OPT_CAPATH, OPT_CAFILE, OPT_CASTORE, OPT_UNTRUSTED,
+ OPT_MD, OPT_V_ENUM, OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS ts_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"config", OPT_CONFIG, '<', "Configuration file"},
{"section", OPT_SECTION, 's', "Section to use within config file"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {"inkey", OPT_INKEY, 's', "File with private key for reply"},
+ {"signer", OPT_SIGNER, 's', "Signer certificate file"},
+ {"chain", OPT_CHAIN, '<', "File with signer CA chain"},
+ {"CAfile", OPT_CAFILE, '<', "File with trusted CA certs"},
+ {"CApath", OPT_CAPATH, '/', "Path to trusted CA files"},
+ {"CAstore", OPT_CASTORE, ':', "URI to trusted CA store"},
+ {"untrusted", OPT_UNTRUSTED, '<', "Extra untrusted certs"},
+ {"token_in", OPT_TOKEN_IN, '-', "Input is a PKCS#7 file"},
+ {"token_out", OPT_TOKEN_OUT, '-', "Output is a PKCS#7 file"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"", OPT_MD, '-', "Any supported digest"},
+
+ OPT_SECTION("Query"),
{"query", OPT_QUERY, '-', "Generate a TS query"},
{"data", OPT_DATA, '<', "File to hash"},
{"digest", OPT_DIGEST, 's', "Digest (as a hex string)"},
- OPT_R_OPTIONS,
- {"tspolicy", OPT_TSPOLICY, 's', "Policy OID to use"},
- {"no_nonce", OPT_NO_NONCE, '-', "Do not include a nonce"},
+ {"queryfile", OPT_QUERYFILE, '<', "File containing a TS query"},
{"cert", OPT_CERT, '-', "Put cert request into query"},
{"in", OPT_IN, '<', "Input file"},
- {"token_in", OPT_TOKEN_IN, '-', "Input is a PKCS#7 file"},
+
+ OPT_SECTION("Verify"),
+ {"verify", OPT_VERIFY, '-', "Verify a TS response"},
+ {"reply", OPT_REPLY, '-', "Generate a TS reply"},
+ {"tspolicy", OPT_TSPOLICY, 's', "Policy OID to use"},
+ {"no_nonce", OPT_NO_NONCE, '-', "Do not include a nonce"},
{"out", OPT_OUT, '>', "Output file"},
- {"token_out", OPT_TOKEN_OUT, '-', "Output is a PKCS#7 file"},
{"text", OPT_TEXT, '-', "Output text (not DER)"},
- {"reply", OPT_REPLY, '-', "Generate a TS reply"},
- {"queryfile", OPT_QUERYFILE, '<', "File containing a TS query"},
- {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
- {"inkey", OPT_INKEY, 's', "File with private key for reply"},
- {"signer", OPT_SIGNER, 's', "Signer certificate file"},
- {"chain", OPT_CHAIN, '<', "File with signer CA chain"},
- {"verify", OPT_VERIFY, '-', "Verify a TS response"},
- {"CApath", OPT_CAPATH, '/', "Path to trusted CA files"},
- {"CAfile", OPT_CAFILE, '<', "File with trusted CA certs"},
- {"untrusted", OPT_UNTRUSTED, '<', "File with untrusted certs"},
- {"", OPT_MD, '-', "Any supported digest"},
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
- {OPT_HELP_STR, 1, '-', "\nOptions specific to 'ts -verify': \n"},
+
+ OPT_R_OPTIONS,
OPT_V_OPTIONS,
- {OPT_HELP_STR, 1, '-', "\n"},
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -124,41 +132,43 @@ const OPTIONS ts_options[] = {
* This command is so complex, special help is needed.
*/
static char* opt_helplist[] = {
+ "",
"Typical uses:",
- "ts -query [-rand file...] [-config file] [-data file]",
- " [-digest hexstring] [-tspolicy oid] [-no_nonce] [-cert]",
- " [-in file] [-out file] [-text]",
- " or",
- "ts -reply [-config file] [-section tsa_section]",
- " [-queryfile file] [-passin password]",
- " [-signer tsa_cert.pem] [-inkey private_key.pem]",
- " [-chain certs_file.pem] [-tspolicy oid]",
- " [-in file] [-token_in] [-out file] [-token_out]",
+ " openssl ts -query [-rand file...] [-config file] [-data file]",
+ " [-digest hexstring] [-tspolicy oid] [-no_nonce] [-cert]",
+ " [-in file] [-out file] [-text]",
+ "",
+ " openssl ts -reply [-config file] [-section tsa_section]",
+ " [-queryfile file] [-passin password]",
+ " [-signer tsa_cert.pem] [-inkey private_key.pem]",
+ " [-chain certs_file.pem] [-tspolicy oid]",
+ " [-in file] [-token_in] [-out file] [-token_out]",
#ifndef OPENSSL_NO_ENGINE
- " [-text] [-engine id]",
+ " [-text] [-engine id]",
#else
- " [-text]",
+ " [-text]",
#endif
- " or",
- "ts -verify -CApath dir -CAfile file.pem -untrusted file.pem",
- " [-data file] [-digest hexstring]",
- " [-queryfile file] -in file [-token_in]",
- " [[options specific to 'ts -verify']]",
+ "",
+ " openssl ts -verify -CApath dir -CAfile root-cert.pem -CAstore uri",
+ " -untrusted extra-certs.pem [-data file] [-digest hexstring]",
+ " [-queryfile request.tsq] -in response.tsr [-token_in] ...",
NULL,
};
int ts_main(int argc, char **argv)
{
CONF *conf = NULL;
- const char *CAfile = NULL, *untrusted = NULL, *prog;
+ const char *CAfile = NULL, *prog;
+ char *untrusted = NULL;
const char *configfile = default_config_file, *engine = NULL;
- const char *section = NULL;
+ const char *section = NULL, *digestname = NULL;
char **helpp;
char *password = NULL;
char *data = NULL, *digest = NULL, *policy = NULL;
char *in = NULL, *out = NULL, *queryfile = NULL, *passin = NULL;
char *inkey = NULL, *signer = NULL, *chain = NULL, *CApath = NULL;
- const EVP_MD *md = NULL;
+ char *CAstore = NULL;
+ EVP_MD *md = NULL;
OPTION_CHOICE o, mode = OPT_ERR;
int ret = 1, no_nonce = 0, cert = 0, text = 0;
int vpmtouched = 0;
@@ -208,6 +218,10 @@ int ts_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_TSPOLICY:
policy = opt_arg();
break;
@@ -253,6 +267,9 @@ int ts_main(int argc, char **argv)
case OPT_CAFILE:
CAfile = opt_arg();
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
case OPT_UNTRUSTED:
untrusted = opt_arg();
break;
@@ -260,8 +277,7 @@ int ts_main(int argc, char **argv)
engine = opt_arg();
break;
case OPT_MD:
- if (!opt_md(opt_unknown(), &md))
- goto opthelp;
+ digestname = opt_unknown();
break;
case OPT_V_CASES:
if (!opt_verify(o, vpm))
@@ -270,9 +286,19 @@ int ts_main(int argc, char **argv)
break;
}
}
- if (mode == OPT_ERR || opt_num_rest() != 0)
+
+ /* No extra arguments. */
+ argc = opt_num_rest();
+ if (argc != 0 || mode == OPT_ERR)
goto opthelp;
+ if (!app_RAND_load())
+ goto end;
+
+ if (digestname != NULL) {
+ if (!opt_md(digestname, &md))
+ goto opthelp;
+ }
if (mode == OPT_REPLY && passin &&
!app_passwd(passin, NULL, &password, NULL)) {
BIO_printf(bio_err, "Error getting password.\n");
@@ -309,7 +335,7 @@ int ts_main(int argc, char **argv)
if ((in == NULL) || !EXACTLY_ONE(queryfile, data, digest))
goto opthelp;
ret = !verify_command(data, digest, queryfile, in, token_in,
- CApath, CAfile, untrusted,
+ CApath, CAfile, CAstore, untrusted,
vpmtouched ? vpm : NULL);
} else {
goto opthelp;
@@ -317,6 +343,7 @@ int ts_main(int argc, char **argv)
end:
X509_VERIFY_PARAM_free(vpm);
+ EVP_MD_free(md);
NCONF_free(conf);
OPENSSL_free(password);
return ret;
@@ -423,7 +450,7 @@ static TS_REQ *create_query(BIO *data_bio, const char *digest, const EVP_MD *md,
ASN1_OBJECT *policy_obj = NULL;
ASN1_INTEGER *nonce_asn1 = NULL;
- if (md == NULL && (md = EVP_get_digestbyname("sha1")) == NULL)
+ if (md == NULL && (md = EVP_get_digestbyname("sha256")) == NULL)
goto err;
if ((ts_req = TS_REQ_new()) == NULL)
goto err;
@@ -433,7 +460,7 @@ static TS_REQ *create_query(BIO *data_bio, const char *digest, const EVP_MD *md,
goto err;
if ((algo = X509_ALGOR_new()) == NULL)
goto err;
- if ((algo->algorithm = OBJ_nid2obj(EVP_MD_type(md))) == NULL)
+ if ((algo->algorithm = OBJ_nid2obj(EVP_MD_get_type(md))) == NULL)
goto err;
if ((algo->parameter = ASN1_TYPE_new()) == NULL)
goto err;
@@ -482,7 +509,7 @@ static int create_digest(BIO *input, const char *digest, const EVP_MD *md,
int rv = 0;
EVP_MD_CTX *md_ctx = NULL;
- md_value_len = EVP_MD_size(md);
+ md_value_len = EVP_MD_get_size(md);
if (md_value_len < 0)
return 0;
@@ -502,11 +529,12 @@ static int create_digest(BIO *input, const char *digest, const EVP_MD *md,
}
if (!EVP_DigestFinal(md_ctx, *md_value, NULL))
goto err;
- md_value_len = EVP_MD_size(md);
+ md_value_len = EVP_MD_get_size(md);
} else {
long digest_len;
+
*md_value = OPENSSL_hexstr2buf(digest, &digest_len);
- if (!*md_value || md_value_len != digest_len) {
+ if (*md_value == NULL || md_value_len != digest_len) {
OPENSSL_free(*md_value);
*md_value = NULL;
BIO_printf(bio_err, "bad digest, %d bytes "
@@ -817,7 +845,8 @@ static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial)
static int verify_command(const char *data, const char *digest, const char *queryfile,
const char *in, int token_in,
- const char *CApath, const char *CAfile, const char *untrusted,
+ const char *CApath, const char *CAfile,
+ const char *CAstore, char *untrusted,
X509_VERIFY_PARAM *vpm)
{
BIO *in_bio = NULL;
@@ -837,7 +866,7 @@ static int verify_command(const char *data, const char *digest, const char *quer
}
if ((verify_ctx = create_verify_ctx(data, digest, queryfile,
- CApath, CAfile, untrusted,
+ CApath, CAfile, CAstore, untrusted,
vpm)) == NULL)
goto end;
@@ -864,10 +893,12 @@ static int verify_command(const char *data, const char *digest, const char *quer
static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest,
const char *queryfile,
const char *CApath, const char *CAfile,
- const char *untrusted,
+ const char *CAstore,
+ char *untrusted,
X509_VERIFY_PARAM *vpm)
{
TS_VERIFY_CTX *ctx = NULL;
+ STACK_OF(X509) *certs;
BIO *input = NULL;
TS_REQ *request = NULL;
int ret = 0;
@@ -912,14 +943,18 @@ static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest,
TS_VERIFY_CTX_add_flags(ctx, f | TS_VFY_SIGNATURE);
/* Initialising the X509_STORE object. */
- if (TS_VERIFY_CTX_set_store(ctx, create_cert_store(CApath, CAfile, vpm))
+ if (TS_VERIFY_CTX_set_store(ctx,
+ create_cert_store(CApath, CAfile, CAstore, vpm))
== NULL)
goto err;
- /* Loading untrusted certificates. */
- if (untrusted
- && TS_VERIFY_CTS_set_certs(ctx, TS_CONF_load_certs(untrusted)) == NULL)
- goto err;
+ /* Loading any extra untrusted certificates. */
+ if (untrusted != NULL) {
+ certs = load_certs_multifile(untrusted, NULL, "extra untrusted certs",
+ vpm);
+ if (certs == NULL || TS_VERIFY_CTX_set_certs(ctx, certs) == NULL)
+ goto err;
+ }
ret = 1;
err:
@@ -933,13 +968,18 @@ static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest,
}
static X509_STORE *create_cert_store(const char *CApath, const char *CAfile,
- X509_VERIFY_PARAM *vpm)
+ const char *CAstore, X509_VERIFY_PARAM *vpm)
{
X509_STORE *cert_ctx = NULL;
X509_LOOKUP *lookup = NULL;
- int i;
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
+ const char *propq = app_get0_propq();
cert_ctx = X509_STORE_new();
+ if (cert_ctx == NULL) {
+ BIO_printf(bio_err, "memory allocation failure\n");
+ return NULL;
+ }
X509_STORE_set_verify_cb(cert_ctx, verify_cb);
if (CApath != NULL) {
lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir());
@@ -947,8 +987,7 @@ static X509_STORE *create_cert_store(const char *CApath, const char *CAfile,
BIO_printf(bio_err, "memory allocation failure\n");
goto err;
}
- i = X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM);
- if (!i) {
+ if (X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM) <= 0) {
BIO_printf(bio_err, "Error loading directory %s\n", CApath);
goto err;
}
@@ -960,13 +999,25 @@ static X509_STORE *create_cert_store(const char *CApath, const char *CAfile,
BIO_printf(bio_err, "memory allocation failure\n");
goto err;
}
- i = X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM);
- if (!i) {
+ if (X509_LOOKUP_load_file_ex(lookup, CAfile, X509_FILETYPE_PEM, libctx,
+ propq) <= 0) {
BIO_printf(bio_err, "Error loading file %s\n", CAfile);
goto err;
}
}
+ if (CAstore != NULL) {
+ lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_store());
+ if (lookup == NULL) {
+ BIO_printf(bio_err, "memory allocation failure\n");
+ goto err;
+ }
+ if (X509_LOOKUP_load_store_ex(lookup, CAstore, libctx, propq) <= 0) {
+ BIO_printf(bio_err, "Error loading store URI %s\n", CAstore);
+ goto err;
+ }
+ }
+
if (vpm != NULL)
X509_STORE_set1_param(cert_ctx, vpm);
diff --git a/apps/tsget.in b/apps/tsget.in
index bec365e28ce5..3b5f83cf9b57 100644
--- a/apps/tsget.in
+++ b/apps/tsget.in
@@ -1,8 +1,8 @@
#!{- $config{HASHBANGPERL} -}
-# Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
# Copyright (c) 2002 The OpenTSA Project. All rights reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -21,10 +21,10 @@ sub read_body {
my $return_data = "";
my $data_len = length ${$state->{data}};
if ($state->{bytes} < $data_len) {
- $data_len = $data_len - $state->{bytes};
- $data_len = $maxlength if $data_len > $maxlength;
- $return_data = substr ${$state->{data}}, $state->{bytes}, $data_len;
- $state->{bytes} += $data_len;
+ $data_len = $data_len - $state->{bytes};
+ $data_len = $maxlength if $data_len > $maxlength;
+ $return_data = substr ${$state->{data}}, $state->{bytes}, $data_len;
+ $state->{bytes} += $data_len;
}
return $return_data;
}
@@ -47,14 +47,14 @@ sub create_curl {
$curl->setopt(CURLOPT_VERBOSE, 1) if $options{d};
$curl->setopt(CURLOPT_FAILONERROR, 1);
$curl->setopt(CURLOPT_USERAGENT,
- "OpenTSA tsget.pl/openssl-{- $config{version} -}");
+ "OpenTSA tsget.pl/openssl-{- $config{full_version} -}");
# Options for POST method.
$curl->setopt(CURLOPT_UPLOAD, 1);
$curl->setopt(CURLOPT_CUSTOMREQUEST, "POST");
$curl->setopt(CURLOPT_HTTPHEADER,
- ["Content-Type: application/timestamp-query",
- "Accept: application/timestamp-reply,application/timestamp-response"]);
+ ["Content-Type: application/timestamp-query",
+ "Accept: application/timestamp-reply,application/timestamp-response"]);
$curl->setopt(CURLOPT_READFUNCTION, \&read_body);
$curl->setopt(CURLOPT_HEADERFUNCTION, sub { return length($_[0]); });
@@ -63,8 +63,8 @@ sub create_curl {
# SSL related options.
$curl->setopt(CURLOPT_SSLKEYTYPE, "PEM");
- $curl->setopt(CURLOPT_SSL_VERIFYPEER, 1); # Verify server's certificate.
- $curl->setopt(CURLOPT_SSL_VERIFYHOST, 2); # Check server's CN.
+ $curl->setopt(CURLOPT_SSL_VERIFYPEER, 1); # Verify server's certificate.
+ $curl->setopt(CURLOPT_SSL_VERIFYHOST, 2); # Check server's CN.
$curl->setopt(CURLOPT_SSLKEY, $options{k}) if defined($options{k});
$curl->setopt(CURLOPT_SSLKEYPASSWD, $options{p}) if defined($options{p});
$curl->setopt(CURLOPT_SSLCERT, $options{c}) if defined($options{c});
@@ -101,15 +101,15 @@ sub get_timestamp {
my $error_string;
if ($error_code != 0) {
my $http_code = $curl->getinfo(CURLINFO_HTTP_CODE);
- $error_string = "could not get timestamp";
- $error_string .= ", http code: $http_code" unless $http_code == 0;
- $error_string .= ", curl code: $error_code";
- $error_string .= " ($::error_buf)" if defined($::error_buf);
+ $error_string = "could not get timestamp";
+ $error_string .= ", http code: $http_code" unless $http_code == 0;
+ $error_string .= ", curl code: $error_code";
+ $error_string .= " ($::error_buf)" if defined($::error_buf);
} else {
my $ct = $curl->getinfo(CURLINFO_CONTENT_TYPE);
- if (lc($ct) ne "application/timestamp-reply"
- && lc($ct) ne "application/timestamp-response") {
- $error_string = "unexpected content type returned: $ct";
+ if (lc($ct) ne "application/timestamp-reply"
+ && lc($ct) ne "application/timestamp-response") {
+ $error_string = "unexpected content type returned: $ct";
}
}
return ($ts_body, $error_string);
@@ -163,15 +163,15 @@ REQUEST: foreach (@ARGV) {
# Read request.
my $body;
if ($input eq "-") {
- # Read the request from STDIN;
- $body = <STDIN>;
+ # Read the request from STDIN;
+ $body = <STDIN>;
} else {
- # Read the request from file.
+ # Read the request from file.
open INPUT, "<" . $input
- or warn("$input: could not open input file: $!\n"), next REQUEST;
+ or warn("$input: could not open input file: $!\n"), next REQUEST;
$body = <INPUT>;
close INPUT
- or warn("$input: could not close input file: $!\n"), next REQUEST;
+ or warn("$input: could not close input file: $!\n"), next REQUEST;
}
# Send request.
@@ -179,21 +179,21 @@ REQUEST: foreach (@ARGV) {
my ($ts_body, $error) = get_timestamp $curl, \$body;
if (defined($error)) {
- die "$input: fatal error: $error\n";
+ die "$input: fatal error: $error\n";
}
STDERR->printflush(", reply received") if $options{v};
# Write response.
if ($output eq "-") {
- # Write to STDOUT.
+ # Write to STDOUT.
print $ts_body;
} else {
- # Write to file.
+ # Write to file.
open OUTPUT, ">", $output
- or warn("$output: could not open output file: $!\n"), next REQUEST;
+ or warn("$output: could not open output file: $!\n"), next REQUEST;
print OUTPUT $ts_body;
close OUTPUT
- or warn("$output: could not close output file: $!\n"), next REQUEST;
+ or warn("$output: could not close output file: $!\n"), next REQUEST;
}
STDERR->printflush(", $output written.\n") if $options{v};
}
diff --git a/apps/verify.c b/apps/verify.c
index 1f9385606046..3aae931f69df 100644
--- a/apps/verify.c
+++ b/apps/verify.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -21,42 +21,58 @@
static int cb(int ok, X509_STORE_CTX *ctx);
static int check(X509_STORE *ctx, const char *file,
STACK_OF(X509) *uchain, STACK_OF(X509) *tchain,
- STACK_OF(X509_CRL) *crls, int show_chain);
+ STACK_OF(X509_CRL) *crls, int show_chain,
+ STACK_OF(OPENSSL_STRING) *opts);
static int v_verbose = 0, vflags = 0;
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_ENGINE, OPT_CAPATH, OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE,
+ OPT_COMMON,
+ OPT_ENGINE, OPT_CAPATH, OPT_CAFILE, OPT_CASTORE,
+ OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE,
OPT_UNTRUSTED, OPT_TRUSTED, OPT_CRLFILE, OPT_CRL_DOWNLOAD, OPT_SHOW_CHAIN,
- OPT_V_ENUM, OPT_NAMEOPT,
- OPT_VERBOSE
+ OPT_V_ENUM, OPT_NAMEOPT, OPT_VFYOPT,
+ OPT_VERBOSE,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS verify_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"},
- {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert...]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
{"verbose", OPT_VERBOSE, '-',
"Print extra information about the operations being performed."},
- {"CApath", OPT_CAPATH, '/', "A directory of trusted certificates"},
+ {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
+
+ OPT_SECTION("Certificate chain"),
+ {"trusted", OPT_TRUSTED, '<', "A file of trusted certificates"},
{"CAfile", OPT_CAFILE, '<', "A file of trusted certificates"},
+ {"CApath", OPT_CAPATH, '/', "A directory of files with trusted certificates"},
+ {"CAstore", OPT_CASTORE, ':', "URI to a store of trusted certificates"},
{"no-CAfile", OPT_NOCAFILE, '-',
- "Do not load the default certificates file"},
+ "Do not load the default trusted certificates file"},
{"no-CApath", OPT_NOCAPATH, '-',
- "Do not load certificates from the default certificates directory"},
+ "Do not load trusted certificates from the default directory"},
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load trusted certificates from the default certificates store"},
{"untrusted", OPT_UNTRUSTED, '<', "A file of untrusted certificates"},
- {"trusted", OPT_TRUSTED, '<', "A file of trusted certificates"},
{"CRLfile", OPT_CRLFILE, '<',
"File containing one or more CRL's (in PEM format) to load"},
{"crl_download", OPT_CRL_DOWNLOAD, '-',
- "Attempt to download CRL information for this certificate"},
+ "Try downloading CRL information for certificates via their CDP entries"},
{"show_chain", OPT_SHOW_CHAIN, '-',
"Display information about the certificate chain"},
- {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
+
OPT_V_OPTIONS,
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
+ {"vfyopt", OPT_VFYOPT, 's', "Verification parameter in n:v form"},
+
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"cert", 0, 0, "Certificate(s) to verify (optional; stdin used otherwise)"},
{NULL}
};
@@ -65,10 +81,11 @@ int verify_main(int argc, char **argv)
ENGINE *e = NULL;
STACK_OF(X509) *untrusted = NULL, *trusted = NULL;
STACK_OF(X509_CRL) *crls = NULL;
+ STACK_OF(OPENSSL_STRING) *vfyopts = NULL;
X509_STORE *store = NULL;
X509_VERIFY_PARAM *vpm = NULL;
- const char *prog, *CApath = NULL, *CAfile = NULL;
- int noCApath = 0, noCAfile = 0;
+ const char *prog, *CApath = NULL, *CAfile = NULL, *CAstore = NULL;
+ int noCApath = 0, noCAfile = 0, noCAstore = 0;
int vpmtouched = 0, crl_download = 0, show_chain = 0, i = 0, ret = 1;
OPTION_CHOICE o;
@@ -80,24 +97,25 @@ int verify_main(int argc, char **argv)
switch (o) {
case OPT_EOF:
case OPT_ERR:
+ opthelp:
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
goto end;
case OPT_HELP:
opt_help(verify_options);
- BIO_printf(bio_err, "Recognized usages:\n");
+ BIO_printf(bio_err, "\nRecognized certificate chain purposes:\n");
for (i = 0; i < X509_PURPOSE_get_count(); i++) {
- X509_PURPOSE *ptmp;
- ptmp = X509_PURPOSE_get0(i);
- BIO_printf(bio_err, "\t%-10s\t%s\n",
+ X509_PURPOSE *ptmp = X509_PURPOSE_get0(i);
+
+ BIO_printf(bio_err, " %-15s %s\n",
X509_PURPOSE_get0_sname(ptmp),
X509_PURPOSE_get0_name(ptmp));
}
- BIO_printf(bio_err, "Recognized verify names:\n");
+ BIO_printf(bio_err, "Recognized certificate policy names:\n");
for (i = 0; i < X509_VERIFY_PARAM_get_count(); i++) {
- const X509_VERIFY_PARAM *vptmp;
- vptmp = X509_VERIFY_PARAM_get0(i);
- BIO_printf(bio_err, "\t%-10s\n",
+ const X509_VERIFY_PARAM *vptmp = X509_VERIFY_PARAM_get0(i);
+
+ BIO_printf(bio_err, " %s\n",
X509_VERIFY_PARAM_get0_name(vptmp));
}
ret = 0;
@@ -113,15 +131,21 @@ int verify_main(int argc, char **argv)
case OPT_CAFILE:
CAfile = opt_arg();
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
case OPT_NOCAPATH:
noCApath = 1;
break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
case OPT_UNTRUSTED:
/* Zero or more times */
- if (!load_certs(opt_arg(), &untrusted, FORMAT_PEM, NULL,
+ if (!load_certs(opt_arg(), 0, &untrusted, NULL,
"untrusted certificates"))
goto end;
break;
@@ -129,14 +153,13 @@ int verify_main(int argc, char **argv)
/* Zero or more times */
noCAfile = 1;
noCApath = 1;
- if (!load_certs(opt_arg(), &trusted, FORMAT_PEM, NULL,
- "trusted certificates"))
+ noCAstore = 1;
+ if (!load_certs(opt_arg(), 0, &trusted, NULL, "trusted certificates"))
goto end;
break;
case OPT_CRLFILE:
/* Zero or more times */
- if (!load_crls(opt_arg(), &crls, FORMAT_PEM, NULL,
- "other CRLs"))
+ if (!load_crls(opt_arg(), &crls, NULL, "other CRLs"))
goto end;
break;
case OPT_CRL_DOWNLOAD:
@@ -155,21 +178,36 @@ int verify_main(int argc, char **argv)
if (!set_nameopt(opt_arg()))
goto end;
break;
+ case OPT_VFYOPT:
+ if (!vfyopts)
+ vfyopts = sk_OPENSSL_STRING_new_null();
+ if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg()))
+ goto opthelp;
+ break;
case OPT_VERBOSE:
v_verbose = 1;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* Extra arguments are certificates to verify. */
argc = opt_num_rest();
argv = opt_rest();
- if (trusted != NULL && (CAfile || CApath)) {
+
+ if (trusted != NULL
+ && (CAfile != NULL || CApath != NULL || CAstore != NULL)) {
BIO_printf(bio_err,
- "%s: Cannot use -trusted with -CAfile or -CApath\n",
+ "%s: Cannot use -trusted with -CAfile, -CApath or -CAstore\n",
prog);
goto end;
}
- if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
+ if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore)) == NULL)
goto end;
X509_STORE_set_verify_cb(store, cb);
@@ -183,12 +221,13 @@ int verify_main(int argc, char **argv)
ret = 0;
if (argc < 1) {
- if (check(store, NULL, untrusted, trusted, crls, show_chain) != 1)
+ if (check(store, NULL, untrusted, trusted, crls, show_chain,
+ vfyopts) != 1)
ret = -1;
} else {
for (i = 0; i < argc; i++)
- if (check(store, argv[i], untrusted, trusted, crls,
- show_chain) != 1)
+ if (check(store, argv[i], untrusted, trusted, crls, show_chain,
+ vfyopts) != 1)
ret = -1;
}
@@ -198,13 +237,15 @@ int verify_main(int argc, char **argv)
sk_X509_pop_free(untrusted, X509_free);
sk_X509_pop_free(trusted, X509_free);
sk_X509_CRL_pop_free(crls, X509_CRL_free);
+ sk_OPENSSL_STRING_free(vfyopts);
release_engine(e);
return (ret < 0 ? 2 : ret);
}
static int check(X509_STORE *ctx, const char *file,
STACK_OF(X509) *uchain, STACK_OF(X509) *tchain,
- STACK_OF(X509_CRL) *crls, int show_chain)
+ STACK_OF(X509_CRL) *crls, int show_chain,
+ STACK_OF(OPENSSL_STRING) *opts)
{
X509 *x = NULL;
int i = 0, ret = 0;
@@ -212,22 +253,35 @@ static int check(X509_STORE *ctx, const char *file,
STACK_OF(X509) *chain = NULL;
int num_untrusted;
- x = load_cert(file, FORMAT_PEM, "certificate file");
+ x = load_cert(file, FORMAT_UNDEF, "certificate file");
if (x == NULL)
goto end;
+ if (opts != NULL) {
+ for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) {
+ char *opt = sk_OPENSSL_STRING_value(opts, i);
+ if (x509_ctrl_string(x, opt) <= 0) {
+ BIO_printf(bio_err, "parameter error \"%s\"\n", opt);
+ ERR_print_errors(bio_err);
+ X509_free(x);
+ return 0;
+ }
+ }
+ }
+
csc = X509_STORE_CTX_new();
if (csc == NULL) {
- printf("error %s: X.509 store context allocation failed\n",
- (file == NULL) ? "stdin" : file);
+ BIO_printf(bio_err, "error %s: X.509 store context allocation failed\n",
+ (file == NULL) ? "stdin" : file);
goto end;
}
X509_STORE_set_flags(ctx, vflags);
if (!X509_STORE_CTX_init(csc, ctx, x, uchain)) {
X509_STORE_CTX_free(csc);
- printf("error %s: X.509 store context initialization failed\n",
- (file == NULL) ? "stdin" : file);
+ BIO_printf(bio_err,
+ "error %s: X.509 store context initialization failed\n",
+ (file == NULL) ? "stdin" : file);
goto end;
}
if (tchain != NULL)
@@ -236,28 +290,30 @@ static int check(X509_STORE *ctx, const char *file,
X509_STORE_CTX_set0_crls(csc, crls);
i = X509_verify_cert(csc);
if (i > 0 && X509_STORE_CTX_get_error(csc) == X509_V_OK) {
- printf("%s: OK\n", (file == NULL) ? "stdin" : file);
+ BIO_printf(bio_out, "%s: OK\n", (file == NULL) ? "stdin" : file);
ret = 1;
if (show_chain) {
int j;
chain = X509_STORE_CTX_get1_chain(csc);
num_untrusted = X509_STORE_CTX_get_num_untrusted(csc);
- printf("Chain:\n");
+ BIO_printf(bio_out, "Chain:\n");
for (j = 0; j < sk_X509_num(chain); j++) {
X509 *cert = sk_X509_value(chain, j);
- printf("depth=%d: ", j);
+ BIO_printf(bio_out, "depth=%d: ", j);
X509_NAME_print_ex_fp(stdout,
X509_get_subject_name(cert),
0, get_nameopt());
if (j < num_untrusted)
- printf(" (untrusted)");
- printf("\n");
+ BIO_printf(bio_out, " (untrusted)");
+ BIO_printf(bio_out, "\n");
}
sk_X509_pop_free(chain, X509_free);
}
} else {
- printf("error %s: verification failed\n", (file == NULL) ? "stdin" : file);
+ BIO_printf(bio_err,
+ "error %s: verification failed\n",
+ (file == NULL) ? "stdin" : file);
}
X509_STORE_CTX_free(csc);
@@ -298,19 +354,34 @@ static int cb(int ok, X509_STORE_CTX *ctx)
policies_print(ctx);
/* fall thru */
case X509_V_ERR_CERT_HAS_EXPIRED:
- /* Continue even if the leaf is a self signed cert */
+ /* Continue even if the leaf is a self-signed cert */
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
/* Continue after extension errors too */
case X509_V_ERR_INVALID_CA:
case X509_V_ERR_INVALID_NON_CA:
case X509_V_ERR_PATH_LENGTH_EXCEEDED:
- case X509_V_ERR_INVALID_PURPOSE:
case X509_V_ERR_CRL_HAS_EXPIRED:
case X509_V_ERR_CRL_NOT_YET_VALID:
case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
+ /* errors due to strict conformance checking (-x509_strict) */
+ case X509_V_ERR_INVALID_PURPOSE:
+ case X509_V_ERR_PATHLEN_INVALID_FOR_NON_CA:
+ case X509_V_ERR_PATHLEN_WITHOUT_KU_KEY_CERT_SIGN:
+ case X509_V_ERR_CA_BCONS_NOT_CRITICAL:
+ case X509_V_ERR_CA_CERT_MISSING_KEY_USAGE:
+ case X509_V_ERR_KU_KEY_CERT_SIGN_INVALID_FOR_NON_CA:
+ case X509_V_ERR_ISSUER_NAME_EMPTY:
+ case X509_V_ERR_SUBJECT_NAME_EMPTY:
+ case X509_V_ERR_EMPTY_SUBJECT_SAN_NOT_CRITICAL:
+ case X509_V_ERR_EMPTY_SUBJECT_ALT_NAME:
+ case X509_V_ERR_SIGNATURE_ALGORITHM_INCONSISTENCY:
+ case X509_V_ERR_AUTHORITY_KEY_IDENTIFIER_CRITICAL:
+ case X509_V_ERR_SUBJECT_KEY_IDENTIFIER_CRITICAL:
+ case X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER:
+ case X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER:
+ case X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3:
ok = 1;
}
-
return ok;
}
diff --git a/apps/version.c b/apps/version.c
index 2aca1636152b..cab17a46bf18 100644
--- a/apps/version.c
+++ b/apps/version.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -15,56 +15,36 @@
#include <openssl/evp.h>
#include <openssl/crypto.h>
#include <openssl/bn.h>
-#ifndef OPENSSL_NO_MD2
-# include <openssl/md2.h>
-#endif
-#ifndef OPENSSL_NO_RC4
-# include <openssl/rc4.h>
-#endif
-#ifndef OPENSSL_NO_DES
-# include <openssl/des.h>
-#endif
-#ifndef OPENSSL_NO_IDEA
-# include <openssl/idea.h>
-#endif
-#ifndef OPENSSL_NO_BF
-# include <openssl/blowfish.h>
-#endif
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_B, OPT_D, OPT_E, OPT_F, OPT_O, OPT_P, OPT_V, OPT_A, OPT_R
+ OPT_COMMON,
+ OPT_B, OPT_D, OPT_E, OPT_M, OPT_F, OPT_O, OPT_P, OPT_V, OPT_A, OPT_R, OPT_C
} OPTION_CHOICE;
const OPTIONS version_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+
+ OPT_SECTION("Output"),
{"a", OPT_A, '-', "Show all data"},
{"b", OPT_B, '-', "Show build date"},
{"d", OPT_D, '-', "Show configuration directory"},
{"e", OPT_E, '-', "Show engines directory"},
+ {"m", OPT_M, '-', "Show modules directory"},
{"f", OPT_F, '-', "Show compiler flags used"},
{"o", OPT_O, '-', "Show some internal datatype options"},
{"p", OPT_P, '-', "Show target build platform"},
{"r", OPT_R, '-', "Show random seeding options"},
{"v", OPT_V, '-', "Show library version"},
+ {"c", OPT_C, '-', "Show CPU settings info"},
{NULL}
};
-#if defined(OPENSSL_RAND_SEED_DEVRANDOM) || defined(OPENSSL_RAND_SEED_EGD)
-static void printlist(const char *prefix, const char **dev)
-{
- printf("%s (", prefix);
- for ( ; *dev != NULL; dev++)
- printf(" \"%s\"", *dev);
- printf(" )");
-}
-#endif
-
int version_main(int argc, char **argv)
{
int ret = 1, dirty = 0, seed = 0;
int cflags = 0, version = 0, date = 0, options = 0, platform = 0, dir = 0;
- int engdir = 0;
+ int engdir = 0, moddir = 0, cpuinfo = 0;
char *prog;
OPTION_CHOICE o;
@@ -89,6 +69,9 @@ opthelp:
case OPT_E:
dirty = engdir = 1;
break;
+ case OPT_M:
+ dirty = moddir = 1;
+ break;
case OPT_F:
dirty = cflags = 1;
break;
@@ -104,48 +87,35 @@ opthelp:
case OPT_V:
dirty = version = 1;
break;
+ case OPT_C:
+ dirty = cpuinfo = 1;
+ break;
case OPT_A:
- seed = options = cflags = version = date = platform = dir = engdir
+ seed = options = cflags = version = date = platform
+ = dir = engdir = moddir = cpuinfo
= 1;
break;
}
}
- if (opt_num_rest() != 0) {
- BIO_printf(bio_err, "Extra parameters given.\n");
+
+ /* No extra arguments. */
+ argc = opt_num_rest();
+ if (argc != 0)
goto opthelp;
- }
+
if (!dirty)
version = 1;
- if (version) {
- if (OpenSSL_version_num() == OPENSSL_VERSION_NUMBER)
- printf("%s\n", OpenSSL_version(OPENSSL_VERSION));
- else
- printf("%s (Library: %s)\n",
- OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
- }
+ if (version)
+ printf("%s (Library: %s)\n",
+ OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
if (date)
printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON));
if (platform)
printf("%s\n", OpenSSL_version(OPENSSL_PLATFORM));
if (options) {
- printf("options: ");
- printf("%s ", BN_options());
-#ifndef OPENSSL_NO_MD2
- printf("%s ", MD2_options());
-#endif
-#ifndef OPENSSL_NO_RC4
- printf("%s ", RC4_options());
-#endif
-#ifndef OPENSSL_NO_DES
- printf("%s ", DES_options());
-#endif
-#ifndef OPENSSL_NO_IDEA
- printf("%s ", IDEA_options());
-#endif
-#ifndef OPENSSL_NO_BF
- printf("%s ", BF_options());
-#endif
+ printf("options: ");
+ printf(" %s", BN_options());
printf("\n");
}
if (cflags)
@@ -154,41 +124,28 @@ opthelp:
printf("%s\n", OpenSSL_version(OPENSSL_DIR));
if (engdir)
printf("%s\n", OpenSSL_version(OPENSSL_ENGINES_DIR));
+ if (moddir)
+ printf("%s\n", OpenSSL_version(OPENSSL_MODULES_DIR));
if (seed) {
- printf("Seeding source:");
-#ifdef OPENSSL_RAND_SEED_RTDSC
- printf(" rtdsc");
-#endif
-#ifdef OPENSSL_RAND_SEED_RDCPU
- printf(" rdrand ( rdseed rdrand )");
-#endif
-#ifdef OPENSSL_RAND_SEED_LIBRANDOM
- printf(" C-library-random");
-#endif
-#ifdef OPENSSL_RAND_SEED_GETRANDOM
- printf(" getrandom-syscall");
-#endif
-#ifdef OPENSSL_RAND_SEED_DEVRANDOM
- {
- static const char *dev[] = { DEVRANDOM, NULL };
- printlist(" random-device", dev);
- }
-#endif
-#ifdef OPENSSL_RAND_SEED_EGD
- {
- static const char *dev[] = { DEVRANDOM_EGD, NULL };
- printlist(" EGD", dev);
- }
-#endif
-#ifdef OPENSSL_RAND_SEED_NONE
- printf(" none");
-#endif
-#ifdef OPENSSL_RAND_SEED_OS
- printf(" os-specific");
-#endif
- printf("\n");
+ const char *src = OPENSSL_info(OPENSSL_INFO_SEED_SOURCE);
+ printf("Seeding source: %s\n", src ? src : "N/A");
}
+ if (cpuinfo)
+ printf("%s\n", OpenSSL_version(OPENSSL_CPU_INFO));
ret = 0;
end:
return ret;
}
+
+
+#if defined(__TANDEM) && defined(OPENSSL_VPROC)
+/*
+ * Define a VPROC function for the openssl program.
+ * This is used by platform version identification tools.
+ * Do not inline this procedure or make it static.
+ */
+# define OPENSSL_VPROC_STRING_(x) x##_OPENSSL
+# define OPENSSL_VPROC_STRING(x) OPENSSL_VPROC_STRING_(x)
+# define OPENSSL_VPROC_FUNC OPENSSL_VPROC_STRING(OPENSSL_VPROC)
+void OPENSSL_VPROC_FUNC(void) {}
+#endif
diff --git a/apps/x509.c b/apps/x509.c
index 8d4bf71a03ee..a919d787457c 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -21,162 +21,271 @@
#include <openssl/x509v3.h>
#include <openssl/objects.h>
#include <openssl/pem.h>
-#ifndef OPENSSL_NO_RSA
-# include <openssl/rsa.h>
-#endif
+#include <openssl/rsa.h>
#ifndef OPENSSL_NO_DSA
# include <openssl/dsa.h>
#endif
#undef POSTFIX
#define POSTFIX ".srl"
-#define DEF_DAYS 30
+#define DEFAULT_DAYS 30 /* default cert validity period in days */
+#define UNSET_DAYS -2 /* -1 is used for testing expiration checks */
+#define EXT_COPY_UNSET -1
static int callb(int ok, X509_STORE_CTX *ctx);
-static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
- const EVP_MD *digest, CONF *conf, const char *section,
- int preserve_dates);
-static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest,
- X509 *x, X509 *xca, EVP_PKEY *pkey,
- STACK_OF(OPENSSL_STRING) *sigopts, const char *serialfile,
- int create, int days, int clrext, CONF *conf,
- const char *section, ASN1_INTEGER *sno, int reqfile,
- int preserve_dates);
+static ASN1_INTEGER *x509_load_serial(const char *CAfile,
+ const char *serialfile, int create);
static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
-static int print_x509v3_exts(BIO *bio, X509 *x, const char *exts);
+static int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names);
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM,
- OPT_CAKEYFORM, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE,
- OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_SIGNKEY, OPT_CA,
- OPT_CAKEY, OPT_CASERIAL, OPT_SET_SERIAL, OPT_FORCE_PUBKEY,
- OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_NAMEOPT,
- OPT_C, OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL,
+ OPT_CAKEYFORM, OPT_VFYOPT, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE,
+ OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_KEY, OPT_SIGNKEY, OPT_CA, OPT_CAKEY,
+ OPT_CASERIAL, OPT_SET_SERIAL, OPT_NEW, OPT_FORCE_PUBKEY, OPT_SUBJ,
+ OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_DATEOPT, OPT_NAMEOPT,
+ OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL,
OPT_MODULUS, OPT_PUBKEY, OPT_X509TOREQ, OPT_TEXT, OPT_HASH,
OPT_ISSUER_HASH, OPT_SUBJECT, OPT_ISSUER, OPT_FINGERPRINT, OPT_DATES,
OPT_PURPOSE, OPT_STARTDATE, OPT_ENDDATE, OPT_CHECKEND, OPT_CHECKHOST,
OPT_CHECKEMAIL, OPT_CHECKIP, OPT_NOOUT, OPT_TRUSTOUT, OPT_CLRTRUST,
OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID,
- OPT_SUBJECT_HASH_OLD,
- OPT_ISSUER_HASH_OLD,
+ OPT_SUBJECT_HASH_OLD, OPT_ISSUER_HASH_OLD, OPT_COPY_EXTENSIONS,
OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES,
- OPT_R_ENUM, OPT_EXT
+ OPT_R_ENUM, OPT_PROV_ENUM, OPT_EXT
} OPTION_CHOICE;
const OPTIONS x509_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+
+ {"in", OPT_IN, '<',
+ "Certificate input, or CSR input file with -req (default stdin)"},
+ {"passin", OPT_PASSIN, 's', "Private key and cert file pass-phrase source"},
+ {"new", OPT_NEW, '-', "Generate a certificate from scratch"},
+ {"x509toreq", OPT_X509TOREQ, '-',
+ "Output a certification request (rather than a certificate)"},
+ {"req", OPT_REQ, '-', "Input is a CSR file (rather than a certificate)"},
+ {"copy_extensions", OPT_COPY_EXTENSIONS, 's',
+ "copy extensions when converting from CSR to x509 or vice versa"},
{"inform", OPT_INFORM, 'f',
- "Input format - default PEM (one of DER or PEM)"},
- {"in", OPT_IN, '<', "Input file - default stdin"},
- {"outform", OPT_OUTFORM, 'f',
- "Output format - default PEM (one of DER or PEM)"},
+ "CSR input file format (DER or PEM) - default PEM"},
+ {"vfyopt", OPT_VFYOPT, 's', "CSR verification parameter in n:v form"},
+ {"key", OPT_KEY, 's',
+ "Key for signing, and to include unless using -force_pubkey"},
+ {"signkey", OPT_SIGNKEY, 's',
+ "Same as -key"},
+ {"keyform", OPT_KEYFORM, 'E',
+ "Key input format (ENGINE, other values ignored)"},
{"out", OPT_OUT, '>', "Output file - default stdout"},
- {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"},
- {"passin", OPT_PASSIN, 's', "Private key password/pass-phrase source"},
+ {"outform", OPT_OUTFORM, 'f',
+ "Output format (DER or PEM) - default PEM"},
+ {"nocert", OPT_NOCERT, '-',
+ "No cert output (except for requested printing)"},
+ {"noout", OPT_NOOUT, '-', "No output (except for requested printing)"},
+
+ OPT_SECTION("Certificate printing"),
+ {"text", OPT_TEXT, '-', "Print the certificate in text form"},
+ {"dateopt", OPT_DATEOPT, 's', "Datetime format used for printing. (rfc_822/iso_8601). Default is rfc_822."},
+ {"certopt", OPT_CERTOPT, 's', "Various certificate text printing options"},
+ {"fingerprint", OPT_FINGERPRINT, '-', "Print the certificate fingerprint"},
+ {"alias", OPT_ALIAS, '-', "Print certificate alias"},
{"serial", OPT_SERIAL, '-', "Print serial number value"},
- {"subject_hash", OPT_HASH, '-', "Print subject hash value"},
- {"issuer_hash", OPT_ISSUER_HASH, '-', "Print issuer hash value"},
- {"hash", OPT_HASH, '-', "Synonym for -subject_hash"},
+ {"startdate", OPT_STARTDATE, '-', "Print the notBefore field"},
+ {"enddate", OPT_ENDDATE, '-', "Print the notAfter field"},
+ {"dates", OPT_DATES, '-', "Print both notBefore and notAfter fields"},
{"subject", OPT_SUBJECT, '-', "Print subject DN"},
{"issuer", OPT_ISSUER, '-', "Print issuer DN"},
+ {"nameopt", OPT_NAMEOPT, 's',
+ "Certificate subject/issuer name printing options"},
{"email", OPT_EMAIL, '-', "Print email address(es)"},
- {"startdate", OPT_STARTDATE, '-', "Set notBefore field"},
- {"enddate", OPT_ENDDATE, '-', "Set notAfter field"},
- {"purpose", OPT_PURPOSE, '-', "Print out certificate purposes"},
- {"dates", OPT_DATES, '-', "Both Before and After dates"},
- {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"},
- {"pubkey", OPT_PUBKEY, '-', "Output the public key"},
- {"fingerprint", OPT_FINGERPRINT, '-',
- "Print the certificate fingerprint"},
- {"alias", OPT_ALIAS, '-', "Output certificate alias"},
- {"noout", OPT_NOOUT, '-', "No output, just status"},
- {"nocert", OPT_NOCERT, '-', "No certificate output"},
+ {"hash", OPT_HASH, '-', "Synonym for -subject_hash (for backward compat)"},
+ {"subject_hash", OPT_HASH, '-', "Print subject hash value"},
+#ifndef OPENSSL_NO_MD5
+ {"subject_hash_old", OPT_SUBJECT_HASH_OLD, '-',
+ "Print old-style (MD5) subject hash value"},
+#endif
+ {"issuer_hash", OPT_ISSUER_HASH, '-', "Print issuer hash value"},
+#ifndef OPENSSL_NO_MD5
+ {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-',
+ "Print old-style (MD5) issuer hash value"},
+#endif
+ {"ext", OPT_EXT, 's',
+ "Restrict which X.509 extensions to print and/or copy"},
{"ocspid", OPT_OCSPID, '-',
"Print OCSP hash values for the subject name and public key"},
{"ocsp_uri", OPT_OCSP_URI, '-', "Print OCSP Responder URL(s)"},
- {"trustout", OPT_TRUSTOUT, '-', "Output a trusted certificate"},
- {"clrtrust", OPT_CLRTRUST, '-', "Clear all trusted purposes"},
- {"clrext", OPT_CLREXT, '-', "Clear all certificate extensions"},
- {"addtrust", OPT_ADDTRUST, 's', "Trust certificate for a given purpose"},
- {"addreject", OPT_ADDREJECT, 's',
- "Reject certificate for a given purpose"},
- {"setalias", OPT_SETALIAS, 's', "Set certificate alias"},
- {"days", OPT_DAYS, 'n',
- "How long till expiry of a signed certificate - def 30 days"},
+ {"purpose", OPT_PURPOSE, '-', "Print out certificate purposes"},
+ {"pubkey", OPT_PUBKEY, '-', "Print the public key in PEM format"},
+ {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"},
+
+ OPT_SECTION("Certificate checking"),
{"checkend", OPT_CHECKEND, 'M',
- "Check whether the cert expires in the next arg seconds"},
- {OPT_MORE_STR, 1, 1, "Exit 1 if so, 0 if not"},
- {"signkey", OPT_SIGNKEY, 's', "Self sign cert with arg"},
- {"x509toreq", OPT_X509TOREQ, '-',
- "Output a certification request object"},
- {"req", OPT_REQ, '-', "Input is a certificate request, sign and output"},
- {"CA", OPT_CA, '<', "Set the CA certificate, must be PEM format"},
- {"CAkey", OPT_CAKEY, 's',
- "The CA key, must be PEM format; if not in CAfile"},
- {"CAcreateserial", OPT_CACREATESERIAL, '-',
- "Create serial number file if it does not exist"},
- {"CAserial", OPT_CASERIAL, 's', "Serial file"},
- {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"},
- {"text", OPT_TEXT, '-', "Print the certificate in text form"},
- {"ext", OPT_EXT, 's', "Print various X509V3 extensions"},
- {"C", OPT_C, '-', "Print out C code forms"},
- {"extfile", OPT_EXTFILE, '<', "File with X509V3 extensions to add"},
- OPT_R_OPTIONS,
- {"extensions", OPT_EXTENSIONS, 's', "Section from config file to use"},
- {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
- {"certopt", OPT_CERTOPT, 's', "Various certificate text options"},
+ "Check whether cert expires in the next arg seconds"},
+ {OPT_MORE_STR, 1, 1, "Exit 1 (failure) if so, 0 if not"},
{"checkhost", OPT_CHECKHOST, 's', "Check certificate matches host"},
{"checkemail", OPT_CHECKEMAIL, 's', "Check certificate matches email"},
{"checkip", OPT_CHECKIP, 's', "Check certificate matches ipaddr"},
- {"CAform", OPT_CAFORM, 'F', "CA format - default PEM"},
- {"CAkeyform", OPT_CAKEYFORM, 'E', "CA key format - default PEM"},
- {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
- {"force_pubkey", OPT_FORCE_PUBKEY, '<', "Force the Key to put inside certificate"},
- {"next_serial", OPT_NEXT_SERIAL, '-', "Increment current certificate serial number"},
+
+ OPT_SECTION("Certificate output"),
+ {"set_serial", OPT_SET_SERIAL, 's',
+ "Serial number to use, overrides -CAserial"},
+ {"next_serial", OPT_NEXT_SERIAL, '-',
+ "Increment current certificate serial number"},
+ {"days", OPT_DAYS, 'n',
+ "Number of days until newly generated certificate expires - default 30"},
+ {"preserve_dates", OPT_PRESERVE_DATES, '-',
+ "Preserve existing validity dates"},
+ {"subj", OPT_SUBJ, 's', "Set or override certificate subject (and issuer)"},
+ {"force_pubkey", OPT_FORCE_PUBKEY, '<',
+ "Place the given key in new certificate"},
+ {"clrext", OPT_CLREXT, '-',
+ "Do not take over any extensions from the source certificate or request"},
+ {"extfile", OPT_EXTFILE, '<', "Config file with X509V3 extensions to add"},
+ {"extensions", OPT_EXTENSIONS, 's',
+ "Section of extfile to use - default: unnamed section"},
+ {"sigopt", OPT_SIGOPT, 's', "Signature parameter, in n:v form"},
+ {"badsig", OPT_BADSIG, '-',
+ "Corrupt last byte of certificate signature (for test)"},
+ {"", OPT_MD, '-', "Any supported digest, used for signing and printing"},
+
+ OPT_SECTION("Micro-CA"),
+ {"CA", OPT_CA, '<',
+ "Use the given CA certificate, conflicts with -key"},
+ {"CAform", OPT_CAFORM, 'F', "CA cert format (PEM/DER/P12); has no effect"},
+ {"CAkey", OPT_CAKEY, 's', "The corresponding CA key; default is -CA arg"},
+ {"CAkeyform", OPT_CAKEYFORM, 'E',
+ "CA key format (ENGINE, other values ignored)"},
+ {"CAserial", OPT_CASERIAL, 's',
+ "File that keeps track of CA-generated serial number"},
+ {"CAcreateserial", OPT_CACREATESERIAL, '-',
+ "Create CA serial number file if it does not exist"},
+
+ OPT_SECTION("Certificate trust output"),
+ {"trustout", OPT_TRUSTOUT, '-', "Mark certificate PEM output as trusted"},
+ {"setalias", OPT_SETALIAS, 's', "Set certificate alias (nickname)"},
+ {"clrtrust", OPT_CLRTRUST, '-', "Clear all trusted purposes"},
+ {"addtrust", OPT_ADDTRUST, 's', "Trust certificate for a given purpose"},
{"clrreject", OPT_CLRREJECT, '-',
"Clears all the prohibited or rejected uses of the certificate"},
- {"badsig", OPT_BADSIG, '-', "Corrupt last byte of certificate signature (for test)"},
- {"", OPT_MD, '-', "Any supported digest"},
-#ifndef OPENSSL_NO_MD5
- {"subject_hash_old", OPT_SUBJECT_HASH_OLD, '-',
- "Print old-style (MD5) subject hash value"},
- {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-',
- "Print old-style (MD5) issuer hash value"},
-#endif
+ {"addreject", OPT_ADDREJECT, 's',
+ "Reject certificate for a given purpose"},
+
+ OPT_R_OPTIONS,
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
- {"preserve_dates", OPT_PRESERVE_DATES, '-', "preserve existing dates when signing"},
+ OPT_PROV_OPTIONS,
{NULL}
};
+static void warn_copying(ASN1_OBJECT *excluded, const char *names)
+{
+ const char *sn = OBJ_nid2sn(OBJ_obj2nid(excluded));
+
+ if (names != NULL && strstr(names, sn) != NULL)
+ BIO_printf(bio_err,
+ "Warning: -ext should not specify copying %s extension to CSR; ignoring this\n",
+ sn);
+}
+
+static X509_REQ *x509_to_req(X509 *cert, int ext_copy, const char *names)
+{
+ const STACK_OF(X509_EXTENSION) *cert_exts = X509_get0_extensions(cert);
+ int i, n = sk_X509_EXTENSION_num(cert_exts /* may be NULL */);
+ ASN1_OBJECT *skid = OBJ_nid2obj(NID_subject_key_identifier);
+ ASN1_OBJECT *akid = OBJ_nid2obj(NID_authority_key_identifier);
+ STACK_OF(X509_EXTENSION) *exts;
+ X509_REQ *req = X509_to_X509_REQ(cert, NULL, NULL);
+
+ if (req == NULL)
+ return NULL;
+
+ /*
+ * Filter out SKID and AKID extensions, which make no sense in a CSR.
+ * If names is not NULL, copy only those extensions listed there.
+ */
+ warn_copying(skid, names);
+ warn_copying(akid, names);
+ if ((exts = sk_X509_EXTENSION_new_reserve(NULL, n)) == NULL)
+ goto err;
+ for (i = 0; i < n; i++) {
+ X509_EXTENSION *ex = sk_X509_EXTENSION_value(cert_exts, i);
+ ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex);
+
+ if (OBJ_cmp(obj, skid) != 0 && OBJ_cmp(obj, akid) != 0
+ && !sk_X509_EXTENSION_push(exts, ex))
+ goto err;
+ }
+
+ if (sk_X509_EXTENSION_num(exts) > 0) {
+ if (ext_copy != EXT_COPY_UNSET && ext_copy != EXT_COPY_NONE
+ && !X509_REQ_add_extensions(req, exts)) {
+ BIO_printf(bio_err, "Error copying extensions from certificate\n");
+ goto err;
+ }
+ }
+ sk_X509_EXTENSION_free(exts);
+ return req;
+
+ err:
+ sk_X509_EXTENSION_free(exts);
+ X509_REQ_free(req);
+ return NULL;
+}
+
+static int self_signed(X509_STORE *ctx, X509 *cert)
+{
+ X509_STORE_CTX *xsc = X509_STORE_CTX_new();
+ int ret = 0;
+
+ if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, cert, NULL)) {
+ BIO_printf(bio_err, "Error initialising X509 store\n");
+ } else {
+ X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
+ ret = X509_verify_cert(xsc) > 0;
+ }
+ X509_STORE_CTX_free(xsc);
+ return ret;
+}
+
int x509_main(int argc, char **argv)
{
ASN1_INTEGER *sno = NULL;
ASN1_OBJECT *objtmp = NULL;
BIO *out = NULL;
CONF *extconf = NULL;
- EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL;
+ int ext_copy = EXT_COPY_UNSET;
+ X509V3_CTX ext_ctx;
+ EVP_PKEY *privkey = NULL, *CAkey = NULL, *pubkey = NULL;
+ EVP_PKEY *pkey;
+ int newcert = 0;
+ char *subj = NULL, *digest = NULL;
+ X509_NAME *fsubj = NULL;
+ const unsigned long chtype = MBSTRING_ASC;
+ const int multirdn = 1;
STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
- STACK_OF(OPENSSL_STRING) *sigopts = NULL;
- X509 *x = NULL, *xca = NULL;
+ STACK_OF(OPENSSL_STRING) *sigopts = NULL, *vfyopts = NULL;
+ X509 *x = NULL, *xca = NULL, *issuer_cert;
X509_REQ *req = NULL, *rq = NULL;
X509_STORE *ctx = NULL;
- const EVP_MD *digest = NULL;
- char *CAkeyfile = NULL, *CAserial = NULL, *fkeyfile = NULL, *alias = NULL;
- char *checkhost = NULL, *checkemail = NULL, *checkip = NULL, *exts = NULL;
+ char *CAkeyfile = NULL, *CAserial = NULL, *pubkeyfile = NULL, *alias = NULL;
+ char *checkhost = NULL, *checkemail = NULL, *checkip = NULL;
+ char *ext_names = NULL;
char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL;
- char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL;
+ char *infile = NULL, *outfile = NULL, *privkeyfile = NULL, *CAfile = NULL;
char *prog;
- int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0;
- int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM;
+ int days = UNSET_DAYS; /* not explicitly set */
+ int x509toreq = 0, modulus = 0, print_pubkey = 0, pprint = 0;
+ int CAformat = FORMAT_UNDEF, CAkeyformat = FORMAT_UNDEF;
+ unsigned long dateopt = ASN1_DTFLGS_RFC822;
int fingerprint = 0, reqfile = 0, checkend = 0;
- int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
+ int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyformat = FORMAT_UNDEF;
int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0;
- int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0;
+ int noout = 0, CA_createserial = 0, email = 0;
int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0;
- int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0;
+ int ret = 1, i, j, num = 0, badsig = 0, clrext = 0, nocert = 0;
int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0, ext = 0;
int enddate = 0;
time_t checkoffset = 0;
@@ -206,7 +315,7 @@ int x509_main(int argc, char **argv)
ret = 0;
goto end;
case OPT_INFORM:
- if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
goto opthelp;
break;
case OPT_IN:
@@ -217,15 +326,15 @@ int x509_main(int argc, char **argv)
goto opthelp;
break;
case OPT_KEYFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyformat))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat))
goto opthelp;
break;
case OPT_CAFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAformat))
goto opthelp;
break;
case OPT_CAKEYFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PDE, &CAkeyformat))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAkeyformat))
goto opthelp;
break;
case OPT_OUT:
@@ -235,16 +344,40 @@ int x509_main(int argc, char **argv)
reqfile = 1;
break;
+ case OPT_DATEOPT:
+ if (!set_dateopt(&dateopt, opt_arg())) {
+ BIO_printf(bio_err,
+ "Invalid date format: %s\n", opt_arg());
+ goto end;
+ }
+ break;
+ case OPT_COPY_EXTENSIONS:
+ if (!set_ext_copy(&ext_copy, opt_arg())) {
+ BIO_printf(bio_err,
+ "Invalid extension copy option: %s\n", opt_arg());
+ goto end;
+ }
+ break;
+
case OPT_SIGOPT:
if (!sigopts)
sigopts = sk_OPENSSL_STRING_new_null();
if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
goto opthelp;
break;
- case OPT_DAYS:
- if (preserve_dates)
+ case OPT_VFYOPT:
+ if (!vfyopts)
+ vfyopts = sk_OPENSSL_STRING_new_null();
+ if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg()))
goto opthelp;
+ break;
+ case OPT_DAYS:
days = atoi(opt_arg());
+ if (days < -1) {
+ BIO_printf(bio_err, "%s: -days parameter arg must be >= -1\n",
+ prog);
+ goto end;
+ }
break;
case OPT_PASSIN:
passinarg = opt_arg();
@@ -256,16 +389,19 @@ int x509_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_EXTENSIONS:
extsect = opt_arg();
break;
+ case OPT_KEY:
case OPT_SIGNKEY:
- keyfile = opt_arg();
- sign_flag = ++num;
+ privkeyfile = opt_arg();
break;
case OPT_CA:
CAfile = opt_arg();
- CA_flag = ++num;
break;
case OPT_CAKEY:
CAkeyfile = opt_arg();
@@ -281,34 +417,35 @@ int x509_main(int argc, char **argv)
if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL)
goto opthelp;
break;
+ case OPT_NEW:
+ newcert = 1;
+ break;
case OPT_FORCE_PUBKEY:
- fkeyfile = opt_arg();
+ pubkeyfile = opt_arg();
+ break;
+ case OPT_SUBJ:
+ subj = opt_arg();
break;
case OPT_ADDTRUST:
+ if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL)
+ goto end;
if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
- BIO_printf(bio_err,
- "%s: Invalid trust object value %s\n",
+ BIO_printf(bio_err, "%s: Invalid trust object value %s\n",
prog, opt_arg());
goto opthelp;
}
- if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL)
- goto end;
sk_ASN1_OBJECT_push(trust, objtmp);
- objtmp = NULL;
trustout = 1;
break;
case OPT_ADDREJECT:
+ if (reject == NULL && (reject = sk_ASN1_OBJECT_new_null()) == NULL)
+ goto end;
if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
- BIO_printf(bio_err,
- "%s: Invalid reject object value %s\n",
+ BIO_printf(bio_err, "%s: Invalid reject object value %s\n",
prog, opt_arg());
goto opthelp;
}
- if (reject == NULL
- && (reject = sk_ASN1_OBJECT_new_null()) == NULL)
- goto end;
sk_ASN1_OBJECT_push(reject, objtmp);
- objtmp = NULL;
trustout = 1;
break;
case OPT_SETALIAS:
@@ -326,9 +463,6 @@ int x509_main(int argc, char **argv)
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
- case OPT_C:
- C = ++num;
- break;
case OPT_EMAIL:
email = ++num;
break;
@@ -345,10 +479,10 @@ int x509_main(int argc, char **argv)
modulus = ++num;
break;
case OPT_PUBKEY:
- pubkey = ++num;
+ print_pubkey = ++num;
break;
case OPT_X509TOREQ:
- x509req = ++num;
+ x509toreq = 1;
break;
case OPT_TEXT:
text = ++num;
@@ -382,7 +516,7 @@ int x509_main(int argc, char **argv)
break;
case OPT_EXT:
ext = ++num;
- exts = opt_arg();
+ ext_names = opt_arg();
break;
case OPT_NOCERT:
nocert = 1;
@@ -430,12 +564,12 @@ int x509_main(int argc, char **argv)
case OPT_CHECKEND:
checkend = 1;
{
- intmax_t temp = 0;
- if (!opt_imax(opt_arg(), &temp))
+ ossl_intmax_t temp = 0;
+ if (!opt_intmax(opt_arg(), &temp))
goto opthelp;
checkoffset = (time_t)temp;
- if ((intmax_t)checkoffset != temp) {
- BIO_printf(bio_err, "%s: checkend time out of range %s\n",
+ if ((ossl_intmax_t)checkoffset != temp) {
+ BIO_printf(bio_err, "%s: Checkend time out of range %s\n",
prog, opt_arg());
goto opthelp;
}
@@ -451,48 +585,103 @@ int x509_main(int argc, char **argv)
checkip = opt_arg();
break;
case OPT_PRESERVE_DATES:
- if (days != DEF_DAYS)
- goto opthelp;
preserve_dates = 1;
break;
case OPT_MD:
- if (!opt_md(opt_unknown(), &digest))
- goto opthelp;
+ digest = opt_unknown();
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
- argv = opt_rest();
- if (argc != 0) {
- BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]);
+ if (argc != 0)
goto opthelp;
+
+ if (!app_RAND_load())
+ goto end;
+
+ if (preserve_dates && days != UNSET_DAYS) {
+ BIO_printf(bio_err, "Cannot use -preserve_dates with -days option\n");
+ goto end;
}
+ if (days == UNSET_DAYS)
+ days = DEFAULT_DAYS;
if (!app_passwd(passinarg, NULL, &passin, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
- if (!X509_STORE_set_default_paths(ctx)) {
- ERR_print_errors(bio_err);
+ if (!X509_STORE_set_default_paths_ex(ctx, app_get0_libctx(),
+ app_get0_propq()))
+ goto end;
+
+ if (newcert && infile != NULL) {
+ BIO_printf(bio_err, "The -in option cannot be used with -new\n");
+ goto end;
+ }
+ if (newcert && reqfile) {
+ BIO_printf(bio_err,
+ "The -req option cannot be used with -new\n");
goto end;
}
+ if (privkeyfile != NULL) {
+ privkey = load_key(privkeyfile, keyformat, 0, passin, e, "private key");
+ if (privkey == NULL)
+ goto end;
+ }
+ if (pubkeyfile != NULL) {
+ if ((pubkey = load_pubkey(pubkeyfile, keyformat, 0, NULL, e,
+ "explicitly set public key")) == NULL)
+ goto end;
+ }
- if (fkeyfile != NULL) {
- fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key");
- if (fkey == NULL)
+ if (newcert) {
+ if (subj == NULL) {
+ BIO_printf(bio_err,
+ "The -new option requires a subject to be set using -subj\n");
goto end;
+ }
+ if (privkeyfile == NULL && pubkeyfile == NULL) {
+ BIO_printf(bio_err,
+ "The -new option requires using the -key or -force_pubkey option\n");
+ goto end;
+ }
}
+ if (subj != NULL
+ && (fsubj = parse_name(subj, chtype, multirdn, "subject")) == NULL)
+ goto end;
- if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) {
+ if (CAkeyfile == NULL)
CAkeyfile = CAfile;
- } else if ((CA_flag) && (CAkeyfile == NULL)) {
- BIO_printf(bio_err,
- "need to specify a CAkey if using the CA command\n");
- goto end;
+ if (CAfile != NULL) {
+ if (privkeyfile != NULL) {
+ BIO_printf(bio_err, "Cannot use both -key/-signkey and -CA option\n");
+ goto end;
+ }
+ } else {
+#define WARN_NO_CA(opt) BIO_printf(bio_err, \
+ "Warning: ignoring " opt " option since -CA option is not given\n");
+ if (CAkeyfile != NULL)
+ WARN_NO_CA("-CAkey");
+ if (CAkeyformat != FORMAT_UNDEF)
+ WARN_NO_CA("-CAkeyform");
+ if (CAformat != FORMAT_UNDEF)
+ WARN_NO_CA("-CAform");
+ if (CAserial != NULL)
+ WARN_NO_CA("-CAserial");
+ if (CA_createserial)
+ WARN_NO_CA("-CAcreateserial");
}
- if (extfile != NULL) {
+ if (extfile == NULL) {
+ if (extsect != NULL)
+ BIO_printf(bio_err,
+ "Warning: ignoring -extensions option without -extfile\n");
+ } else {
X509V3_CTX ctx2;
+
if ((extconf = app_load_config(extfile)) == NULL)
goto end;
if (extsect == NULL) {
@@ -506,92 +695,79 @@ int x509_main(int argc, char **argv)
X509V3_set_nconf(&ctx2, extconf);
if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) {
BIO_printf(bio_err,
- "Error Loading extension section %s\n", extsect);
- ERR_print_errors(bio_err);
+ "Error checking extension section %s\n", extsect);
goto end;
}
}
if (reqfile) {
- EVP_PKEY *pkey;
- BIO *in;
-
- if (!sign_flag && !CA_flag) {
- BIO_printf(bio_err, "We need a private key to sign with\n");
+ req = load_csr(infile, informat, "certificate request input");
+ if (req == NULL)
goto end;
- }
- in = bio_open_default(infile, 'r', informat);
- if (in == NULL)
- goto end;
- req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
- BIO_free(in);
-
- if (req == NULL) {
- ERR_print_errors(bio_err);
- goto end;
- }
if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) {
- BIO_printf(bio_err, "error unpacking public key\n");
+ BIO_printf(bio_err, "Error unpacking public key from CSR\n");
goto end;
}
- i = X509_REQ_verify(req, pkey);
- if (i < 0) {
- BIO_printf(bio_err, "Signature verification error\n");
- ERR_print_errors(bio_err);
+ i = do_X509_REQ_verify(req, pkey, vfyopts);
+ if (i <= 0) {
+ BIO_printf(bio_err, i < 0
+ ? "Error while verifying certificate request self-signature\n"
+ : "Certificate request self-signature did not match the contents\n");
goto end;
}
- if (i == 0) {
+ BIO_printf(bio_err, "Certificate request self-signature ok\n");
+
+ print_name(bio_err, "subject=", X509_REQ_get_subject_name(req));
+ } else if (!x509toreq && ext_copy != EXT_COPY_UNSET) {
+ BIO_printf(bio_err, "Warning: ignoring -copy_extensions since neither -x509toreq nor -req is given\n");
+ }
+
+ if (reqfile || newcert) {
+ if (preserve_dates)
BIO_printf(bio_err,
- "Signature did not match the certificate request\n");
+ "Warning: ignoring -preserve_dates option with -req or -new\n");
+ preserve_dates = 0;
+ if (privkeyfile == NULL && CAkeyfile == NULL) {
+ BIO_printf(bio_err,
+ "We need a private key to sign with, use -key or -CAkey or -CA with private key\n");
goto end;
- } else {
- BIO_printf(bio_err, "Signature ok\n");
}
-
- print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
- get_nameopt());
-
- if ((x = X509_new()) == NULL)
+ if ((x = X509_new_ex(app_get0_libctx(), app_get0_propq())) == NULL)
goto end;
-
- if (sno == NULL) {
+ if (CAfile == NULL && sno == NULL) {
sno = ASN1_INTEGER_new();
if (sno == NULL || !rand_serial(NULL, sno))
goto end;
- if (!X509_set_serialNumber(x, sno))
- goto end;
- ASN1_INTEGER_free(sno);
- sno = NULL;
- } else if (!X509_set_serialNumber(x, sno)) {
- goto end;
}
-
- if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req)))
- goto end;
- if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req)))
- goto end;
- if (!set_cert_times(x, NULL, NULL, days))
- goto end;
-
- if (fkey != NULL) {
- X509_set_pubkey(x, fkey);
- } else {
- pkey = X509_REQ_get0_pubkey(req);
- X509_set_pubkey(x, pkey);
+ if (req != NULL && ext_copy != EXT_COPY_UNSET) {
+ if (clrext && ext_copy != EXT_COPY_NONE) {
+ BIO_printf(bio_err, "Must not use -clrext together with -copy_extensions\n");
+ goto end;
+ } else if (!copy_extensions(x, req, ext_copy)) {
+ BIO_printf(bio_err, "Error copying extensions from request\n");
+ goto end;
+ }
}
} else {
- x = load_cert(infile, informat, "Certificate");
+ x = load_cert_pass(infile, informat, 1, passin, "certificate");
+ if (x == NULL)
+ goto end;
}
-
- if (x == NULL)
+ if ((fsubj != NULL || req != NULL)
+ && !X509_set_subject_name(x, fsubj != NULL ? fsubj :
+ X509_REQ_get_subject_name(req)))
goto end;
- if (CA_flag) {
- xca = load_cert(CAfile, CAformat, "CA Certificate");
+ if ((pubkey != NULL || privkey != NULL || req != NULL)
+ && !X509_set_pubkey(x, pubkey != NULL ? pubkey :
+ privkey != NULL ? privkey :
+ X509_REQ_get0_pubkey(req)))
+ goto end;
+
+ if (CAfile != NULL) {
+ xca = load_cert_pass(CAfile, CAformat, 1, passin, "CA certificate");
if (xca == NULL)
goto end;
- if (reqfile && !X509_set_issuer_name(x, X509_get_subject_name(xca)))
- goto end;
}
out = bio_open_default(outfile, 'w', outformat);
@@ -610,21 +786,120 @@ int x509_main(int argc, char **argv)
X509_reject_clear(x);
if (trust != NULL) {
- for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) {
- objtmp = sk_ASN1_OBJECT_value(trust, i);
- X509_add1_trust_object(x, objtmp);
- }
- objtmp = NULL;
+ for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++)
+ X509_add1_trust_object(x, sk_ASN1_OBJECT_value(trust, i));
}
if (reject != NULL) {
- for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) {
- objtmp = sk_ASN1_OBJECT_value(reject, i);
- X509_add1_reject_object(x, objtmp);
+ for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++)
+ X509_add1_reject_object(x, sk_ASN1_OBJECT_value(reject, i));
+ }
+
+ if (clrext && ext_names != NULL)
+ BIO_printf(bio_err, "Warning: Ignoring -ext since -clrext is given\n");
+ for (i = X509_get_ext_count(x) - 1; i >= 0; i--) {
+ X509_EXTENSION *ex = X509_get_ext(x, i);
+ const char *sn = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ex)));
+
+ if (clrext || (ext_names != NULL && strstr(ext_names, sn) == NULL))
+ X509_EXTENSION_free(X509_delete_ext(x, i));
+ }
+
+ issuer_cert = x;
+ if (CAfile != NULL) {
+ issuer_cert = xca;
+ if (sno == NULL)
+ sno = x509_load_serial(CAfile, CAserial, CA_createserial);
+ if (sno == NULL)
+ goto end;
+ if (!x509toreq && !reqfile && !newcert && !self_signed(ctx, x))
+ goto end;
+ }
+
+ if (sno != NULL && !X509_set_serialNumber(x, sno))
+ goto end;
+
+ if (reqfile || newcert || privkey != NULL || CAfile != NULL) {
+ if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
+ goto end;
+ if (!X509_set_issuer_name(x, X509_get_subject_name(issuer_cert)))
+ goto end;
+ }
+
+ X509V3_set_ctx(&ext_ctx, issuer_cert, x, NULL, NULL, X509V3_CTX_REPLACE);
+ /* prepare fallback for AKID, but only if issuer cert equals subject cert */
+ if (CAfile == NULL) {
+ if (!X509V3_set_issuer_pkey(&ext_ctx, privkey))
+ goto end;
+ }
+ if (extconf != NULL && !x509toreq) {
+ X509V3_set_nconf(&ext_ctx, extconf);
+ if (!X509V3_EXT_add_nconf(extconf, &ext_ctx, extsect, x)) {
+ BIO_printf(bio_err,
+ "Error adding extensions from section %s\n", extsect);
+ goto end;
}
- objtmp = NULL;
}
+ /* At this point the contents of the certificate x have been finished. */
+
+ pkey = X509_get0_pubkey(x);
+ if ((print_pubkey != 0 || modulus != 0) && pkey == NULL) {
+ BIO_printf(bio_err, "Error getting public key\n");
+ goto end;
+ }
+
+ if (x509toreq) { /* also works in conjunction with -req */
+ if (privkey == NULL) {
+ BIO_printf(bio_err, "Must specify request signing key using -key\n");
+ goto end;
+ }
+ if (clrext && ext_copy != EXT_COPY_NONE) {
+ BIO_printf(bio_err, "Must not use -clrext together with -copy_extensions\n");
+ goto end;
+ }
+ if ((rq = x509_to_req(x, ext_copy, ext_names)) == NULL)
+ goto end;
+ if (extconf != NULL) {
+ X509V3_set_nconf(&ext_ctx, extconf);
+ if (!X509V3_EXT_REQ_add_nconf(extconf, &ext_ctx, extsect, rq)) {
+ BIO_printf(bio_err,
+ "Error adding request extensions from section %s\n", extsect);
+ goto end;
+ }
+ }
+ if (!do_X509_REQ_sign(rq, privkey, digest, sigopts))
+ goto end;
+ if (!noout) {
+ if (outformat == FORMAT_ASN1) {
+ X509_REQ_print_ex(out, rq, get_nameopt(), X509_FLAG_COMPAT);
+ i = i2d_X509_bio(out, x);
+ } else {
+ i = PEM_write_bio_X509_REQ(out, rq);
+ }
+ if (!i) {
+ BIO_printf(bio_err,
+ "Unable to write certificate request\n");
+ goto end;
+ }
+ }
+ noout = 1;
+ } else if (privkey != NULL) {
+ if (!do_X509_sign(x, privkey, digest, sigopts, &ext_ctx))
+ goto end;
+ } else if (CAfile != NULL) {
+ if ((CAkey = load_key(CAkeyfile, CAkeyformat,
+ 0, passin, e, "CA private key")) == NULL)
+ goto end;
+ if (!X509_check_private_key(xca, CAkey)) {
+ BIO_printf(bio_err,
+ "CA certificate and CA private key do not match\n");
+ goto end;
+ }
+
+ if (!do_X509_sign(x, CAkey, digest, sigopts, &ext_ctx))
+ goto end;
+ }
if (badsig) {
const ASN1_BIT_STRING *signature;
@@ -632,236 +907,133 @@ int x509_main(int argc, char **argv)
corrupt_signature(signature);
}
- if (num) {
- for (i = 1; i <= num; i++) {
- if (issuer == i) {
- print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt());
- } else if (subject == i) {
- print_name(out, "subject=",
- X509_get_subject_name(x), get_nameopt());
- } else if (serial == i) {
- BIO_printf(out, "serial=");
- i2a_ASN1_INTEGER(out, X509_get_serialNumber(x));
- BIO_printf(out, "\n");
- } else if (next_serial == i) {
- ASN1_INTEGER *ser = X509_get_serialNumber(x);
- BIGNUM *bnser = ASN1_INTEGER_to_BN(ser, NULL);
-
- if (!bnser)
- goto end;
- if (!BN_add_word(bnser, 1))
- goto end;
- ser = BN_to_ASN1_INTEGER(bnser, NULL);
- if (!ser)
- goto end;
+ /* Process print options in the given order, as indicated by index i */
+ for (i = 1; i <= num; i++) {
+ if (i == issuer) {
+ print_name(out, "issuer=", X509_get_issuer_name(x));
+ } else if (i == subject) {
+ print_name(out, "subject=", X509_get_subject_name(x));
+ } else if (i == serial) {
+ BIO_printf(out, "serial=");
+ i2a_ASN1_INTEGER(out, X509_get0_serialNumber(x));
+ BIO_printf(out, "\n");
+ } else if (i == next_serial) {
+ ASN1_INTEGER *ser;
+ BIGNUM *bnser = ASN1_INTEGER_to_BN(X509_get0_serialNumber(x), NULL);
+
+ if (bnser == NULL)
+ goto end;
+ if (!BN_add_word(bnser, 1)
+ || (ser = BN_to_ASN1_INTEGER(bnser, NULL)) == NULL) {
BN_free(bnser);
- i2a_ASN1_INTEGER(out, ser);
- ASN1_INTEGER_free(ser);
- BIO_puts(out, "\n");
- } else if ((email == i) || (ocsp_uri == i)) {
- int j;
- STACK_OF(OPENSSL_STRING) *emlst;
- if (email == i)
- emlst = X509_get1_email(x);
- else
- emlst = X509_get1_ocsp(x);
- for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
- BIO_printf(out, "%s\n",
- sk_OPENSSL_STRING_value(emlst, j));
- X509_email_free(emlst);
- } else if (aliasout == i) {
- unsigned char *alstr;
- alstr = X509_alias_get0(x, NULL);
- if (alstr)
- BIO_printf(out, "%s\n", alstr);
- else
- BIO_puts(out, "<No Alias>\n");
- } else if (subject_hash == i) {
- BIO_printf(out, "%08lx\n", X509_subject_name_hash(x));
+ goto end;
}
+ BN_free(bnser);
+ i2a_ASN1_INTEGER(out, ser);
+ ASN1_INTEGER_free(ser);
+ BIO_puts(out, "\n");
+ } else if (i == email || i == ocsp_uri) {
+ STACK_OF(OPENSSL_STRING) *emlst =
+ i == email ? X509_get1_email(x) : X509_get1_ocsp(x);
+
+ for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
+ BIO_printf(out, "%s\n", sk_OPENSSL_STRING_value(emlst, j));
+ X509_email_free(emlst);
+ } else if (i == aliasout) {
+ unsigned char *alstr = X509_alias_get0(x, NULL);
+
+ if (alstr)
+ BIO_printf(out, "%s\n", alstr);
+ else
+ BIO_puts(out, "<No Alias>\n");
+ } else if (i == subject_hash) {
+ BIO_printf(out, "%08lx\n", X509_subject_name_hash(x));
#ifndef OPENSSL_NO_MD5
- else if (subject_hash_old == i) {
- BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x));
- }
+ } else if (i == subject_hash_old) {
+ BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x));
#endif
- else if (issuer_hash == i) {
- BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x));
- }
+ } else if (i == issuer_hash) {
+ BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x));
#ifndef OPENSSL_NO_MD5
- else if (issuer_hash_old == i) {
- BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x));
- }
+ } else if (i == issuer_hash_old) {
+ BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x));
#endif
- else if (pprint == i) {
- X509_PURPOSE *ptmp;
- int j;
- BIO_printf(out, "Certificate purposes:\n");
- for (j = 0; j < X509_PURPOSE_get_count(); j++) {
- ptmp = X509_PURPOSE_get0(j);
- purpose_print(out, x, ptmp);
- }
- } else if (modulus == i) {
- EVP_PKEY *pkey;
-
- pkey = X509_get0_pubkey(x);
- if (pkey == NULL) {
- BIO_printf(bio_err, "Modulus=unavailable\n");
- ERR_print_errors(bio_err);
- goto end;
- }
- BIO_printf(out, "Modulus=");
-#ifndef OPENSSL_NO_RSA
- if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
- const BIGNUM *n;
- RSA_get0_key(EVP_PKEY_get0_RSA(pkey), &n, NULL, NULL);
- BN_print(out, n);
- } else
-#endif
-#ifndef OPENSSL_NO_DSA
- if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) {
- const BIGNUM *dsapub = NULL;
- DSA_get0_key(EVP_PKEY_get0_DSA(pkey), &dsapub, NULL);
- BN_print(out, dsapub);
- } else
-#endif
- {
- BIO_printf(out, "Wrong Algorithm type");
- }
- BIO_printf(out, "\n");
- } else if (pubkey == i) {
- EVP_PKEY *pkey;
-
- pkey = X509_get0_pubkey(x);
- if (pkey == NULL) {
- BIO_printf(bio_err, "Error getting public key\n");
- ERR_print_errors(bio_err);
- goto end;
- }
- PEM_write_bio_PUBKEY(out, pkey);
- } else if (C == i) {
- unsigned char *d;
- char *m;
- int len;
-
- print_name(out, "/*\n"
- " * Subject: ", X509_get_subject_name(x), get_nameopt());
- print_name(out, " * Issuer: ", X509_get_issuer_name(x), get_nameopt());
- BIO_puts(out, " */\n");
-
- len = i2d_X509(x, NULL);
- m = app_malloc(len, "x509 name buffer");
- d = (unsigned char *)m;
- len = i2d_X509_NAME(X509_get_subject_name(x), &d);
- print_array(out, "the_subject_name", len, (unsigned char *)m);
- d = (unsigned char *)m;
- len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
- print_array(out, "the_public_key", len, (unsigned char *)m);
- d = (unsigned char *)m;
- len = i2d_X509(x, &d);
- print_array(out, "the_certificate", len, (unsigned char *)m);
- OPENSSL_free(m);
- } else if (text == i) {
- X509_print_ex(out, x, get_nameopt(), certflag);
- } else if (startdate == i) {
- BIO_puts(out, "notBefore=");
- ASN1_TIME_print(out, X509_get0_notBefore(x));
- BIO_puts(out, "\n");
- } else if (enddate == i) {
- BIO_puts(out, "notAfter=");
- ASN1_TIME_print(out, X509_get0_notAfter(x));
- BIO_puts(out, "\n");
- } else if (fingerprint == i) {
- int j;
- unsigned int n;
- unsigned char md[EVP_MAX_MD_SIZE];
- const EVP_MD *fdig = digest;
-
- if (fdig == NULL)
- fdig = EVP_sha1();
-
- if (!X509_digest(x, fdig, md, &n)) {
- BIO_printf(bio_err, "out of memory\n");
- goto end;
- }
- BIO_printf(out, "%s Fingerprint=",
- OBJ_nid2sn(EVP_MD_type(fdig)));
- for (j = 0; j < (int)n; j++) {
- BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n)
- ? '\n' : ':');
- }
+ } else if (i == pprint) {
+ BIO_printf(out, "Certificate purposes:\n");
+ for (j = 0; j < X509_PURPOSE_get_count(); j++)
+ purpose_print(out, x, X509_PURPOSE_get0(j));
+ } else if (i == modulus) {
+ BIO_printf(out, "Modulus=");
+ if (EVP_PKEY_is_a(pkey, "RSA") || EVP_PKEY_is_a(pkey, "RSA-PSS")) {
+ BIGNUM *n = NULL;
+
+ /* Every RSA key has an 'n' */
+ EVP_PKEY_get_bn_param(pkey, "n", &n);
+ BN_print(out, n);
+ BN_free(n);
+ } else if (EVP_PKEY_is_a(pkey, "DSA")) {
+ BIGNUM *dsapub = NULL;
+
+ /* Every DSA key has a 'pub' */
+ EVP_PKEY_get_bn_param(pkey, "pub", &dsapub);
+ BN_print(out, dsapub);
+ BN_free(dsapub);
+ } else {
+ BIO_printf(out, "No modulus for this public key type");
}
-
- /* should be in the library */
- else if ((sign_flag == i) && (x509req == 0)) {
- BIO_printf(bio_err, "Getting Private key\n");
- if (Upkey == NULL) {
- Upkey = load_key(keyfile, keyformat, 0,
- passin, e, "Private key");
- if (Upkey == NULL)
- goto end;
- }
-
- if (!sign(x, Upkey, days, clrext, digest, extconf, extsect, preserve_dates))
- goto end;
- } else if (CA_flag == i) {
- BIO_printf(bio_err, "Getting CA Private Key\n");
- if (CAkeyfile != NULL) {
- CApkey = load_key(CAkeyfile, CAkeyformat,
- 0, passin, e, "CA Private Key");
- if (CApkey == NULL)
- goto end;
- }
-
- if (!x509_certify(ctx, CAfile, digest, x, xca,
- CApkey, sigopts,
- CAserial, CA_createserial, days, clrext,
- extconf, extsect, sno, reqfile, preserve_dates))
- goto end;
- } else if (x509req == i) {
- EVP_PKEY *pk;
-
- BIO_printf(bio_err, "Getting request Private Key\n");
- if (keyfile == NULL) {
- BIO_printf(bio_err, "no request key file specified\n");
- goto end;
- } else {
- pk = load_key(keyfile, keyformat, 0,
- passin, e, "request key");
- if (pk == NULL)
- goto end;
- }
-
- BIO_printf(bio_err, "Generating certificate request\n");
-
- rq = X509_to_X509_REQ(x, pk, digest);
- EVP_PKEY_free(pk);
- if (rq == NULL) {
- ERR_print_errors(bio_err);
- goto end;
- }
- if (!noout) {
- X509_REQ_print_ex(out, rq, get_nameopt(), X509_FLAG_COMPAT);
- PEM_write_bio_X509_REQ(out, rq);
- }
- noout = 1;
- } else if (ocspid == i) {
- X509_ocspid_print(out, x);
- } else if (ext == i) {
- print_x509v3_exts(out, x, exts);
+ BIO_printf(out, "\n");
+ } else if (i == print_pubkey) {
+ PEM_write_bio_PUBKEY(out, pkey);
+ } else if (i == text) {
+ X509_print_ex(out, x, get_nameopt(), certflag);
+ } else if (i == startdate) {
+ BIO_puts(out, "notBefore=");
+ ASN1_TIME_print_ex(out, X509_get0_notBefore(x), dateopt);
+ BIO_puts(out, "\n");
+ } else if (i == enddate) {
+ BIO_puts(out, "notAfter=");
+ ASN1_TIME_print_ex(out, X509_get0_notAfter(x), dateopt);
+ BIO_puts(out, "\n");
+ } else if (i == fingerprint) {
+ unsigned int n;
+ unsigned char md[EVP_MAX_MD_SIZE];
+ const char *fdigname = digest;
+ EVP_MD *fdig;
+ int digres;
+
+ if (fdigname == NULL)
+ fdigname = "SHA1";
+
+ if ((fdig = EVP_MD_fetch(app_get0_libctx(), fdigname,
+ app_get0_propq())) == NULL) {
+ BIO_printf(bio_err, "Unknown digest\n");
+ goto end;
+ }
+ digres = X509_digest(x, fdig, md, &n);
+ EVP_MD_free(fdig);
+ if (!digres) {
+ BIO_printf(bio_err, "Out of memory\n");
+ goto end;
}
+
+ BIO_printf(out, "%s Fingerprint=", fdigname);
+ for (j = 0; j < (int)n; j++)
+ BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n) ? '\n' : ':');
+ } else if (i == ocspid) {
+ X509_ocspid_print(out, x);
+ } else if (i == ext) {
+ print_x509v3_exts(out, x, ext_names);
}
}
if (checkend) {
time_t tcheck = time(NULL) + checkoffset;
- if (X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0) {
+ ret = X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0;
+ if (ret)
BIO_printf(out, "Certificate will expire\n");
- ret = 1;
- } else {
+ else
BIO_printf(out, "Certificate will not expire\n");
- ret = 0;
- }
goto end;
}
@@ -880,33 +1052,36 @@ int x509_main(int argc, char **argv)
else
i = PEM_write_bio_X509(out, x);
} else {
- BIO_printf(bio_err, "bad output format specified for outfile\n");
+ BIO_printf(bio_err, "Bad output format specified for outfile\n");
goto end;
}
if (!i) {
- BIO_printf(bio_err, "unable to write certificate\n");
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Unable to write certificate\n");
goto end;
}
ret = 0;
+
end:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
NCONF_free(extconf);
BIO_free_all(out);
X509_STORE_free(ctx);
+ X509_NAME_free(fsubj);
X509_REQ_free(req);
X509_free(x);
X509_free(xca);
- EVP_PKEY_free(Upkey);
- EVP_PKEY_free(CApkey);
- EVP_PKEY_free(fkey);
+ EVP_PKEY_free(privkey);
+ EVP_PKEY_free(CAkey);
+ EVP_PKEY_free(pubkey);
sk_OPENSSL_STRING_free(sigopts);
+ sk_OPENSSL_STRING_free(vfyopts);
X509_REQ_free(rq);
ASN1_INTEGER_free(sno);
sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
- ASN1_OBJECT_free(objtmp);
release_engine(e);
- OPENSSL_free(passin);
+ clear_free(passin);
return ret;
}
@@ -934,7 +1109,7 @@ static ASN1_INTEGER *x509_load_serial(const char *CAfile,
goto end;
if (!BN_add_word(serial, 1)) {
- BIO_printf(bio_err, "add_word failure\n");
+ BIO_printf(bio_err, "Serial number increment failure\n");
goto end;
}
@@ -949,92 +1124,14 @@ static ASN1_INTEGER *x509_load_serial(const char *CAfile,
return bs;
}
-static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest,
- X509 *x, X509 *xca, EVP_PKEY *pkey,
- STACK_OF(OPENSSL_STRING) *sigopts,
- const char *serialfile, int create,
- int days, int clrext, CONF *conf, const char *section,
- ASN1_INTEGER *sno, int reqfile, int preserve_dates)
-{
- int ret = 0;
- ASN1_INTEGER *bs = NULL;
- X509_STORE_CTX *xsc = NULL;
- EVP_PKEY *upkey;
-
- upkey = X509_get0_pubkey(xca);
- if (upkey == NULL) {
- BIO_printf(bio_err, "Error obtaining CA X509 public key\n");
- goto end;
- }
- EVP_PKEY_copy_parameters(upkey, pkey);
-
- xsc = X509_STORE_CTX_new();
- if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, x, NULL)) {
- BIO_printf(bio_err, "Error initialising X509 store\n");
- goto end;
- }
- if (sno)
- bs = sno;
- else if ((bs = x509_load_serial(CAfile, serialfile, create)) == NULL)
- goto end;
-
- /*
- * NOTE: this certificate can/should be self signed, unless it was a
- * certificate request in which case it is not.
- */
- X509_STORE_CTX_set_cert(xsc, x);
- X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
- if (!reqfile && X509_verify_cert(xsc) <= 0)
- goto end;
-
- if (!X509_check_private_key(xca, pkey)) {
- BIO_printf(bio_err,
- "CA certificate and CA private key do not match\n");
- goto end;
- }
-
- if (!X509_set_issuer_name(x, X509_get_subject_name(xca)))
- goto end;
- if (!X509_set_serialNumber(x, bs))
- goto end;
-
- if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
- goto end;
-
- if (clrext) {
- while (X509_get_ext_count(x) > 0)
- X509_delete_ext(x, 0);
- }
-
- if (conf != NULL) {
- X509V3_CTX ctx2;
- X509_set_version(x, 2); /* version 3 certificate */
- X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
- X509V3_set_nconf(&ctx2, conf);
- if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x))
- goto end;
- }
-
- if (!do_X509_sign(x, pkey, digest, sigopts))
- goto end;
- ret = 1;
- end:
- X509_STORE_CTX_free(xsc);
- if (!ret)
- ERR_print_errors(bio_err);
- if (!sno)
- ASN1_INTEGER_free(bs);
- return ret;
-}
-
static int callb(int ok, X509_STORE_CTX *ctx)
{
int err;
X509 *err_cert;
/*
- * it is ok to use a self signed certificate This case will catch both
- * the initial ok == 0 and the final ok == 1 calls to this function
+ * It is ok to use a self-signed certificate. This case will catch both
+ * the initial ok == 0 and the final ok == 1 calls to this function.
*/
err = X509_STORE_CTX_get_error(ctx);
if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
@@ -1047,51 +1144,19 @@ static int callb(int ok, X509_STORE_CTX *ctx)
*/
if (ok) {
BIO_printf(bio_err,
- "error with certificate to be certified - should be self signed\n");
+ "Error with certificate to be certified - should be self-signed\n");
return 0;
} else {
err_cert = X509_STORE_CTX_get_current_cert(ctx);
- print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0);
+ print_name(bio_err, "subject=", X509_get_subject_name(err_cert));
BIO_printf(bio_err,
- "error with certificate - error %d at depth %d\n%s\n", err,
+ "Error with certificate - error %d at depth %d\n%s\n", err,
X509_STORE_CTX_get_error_depth(ctx),
X509_verify_cert_error_string(err));
return 1;
}
}
-/* self sign */
-static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
- const EVP_MD *digest, CONF *conf, const char *section,
- int preserve_dates)
-{
-
- if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
- goto err;
- if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
- goto err;
- if (!X509_set_pubkey(x, pkey))
- goto err;
- if (clrext) {
- while (X509_get_ext_count(x) > 0)
- X509_delete_ext(x, 0);
- }
- if (conf != NULL) {
- X509V3_CTX ctx;
- X509_set_version(x, 2); /* version 3 certificate */
- X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
- X509V3_set_nconf(&ctx, conf);
- if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
- goto err;
- }
- if (!X509_sign(x, pkey, digest))
- goto err;
- return 1;
- err:
- ERR_print_errors(bio_err);
- return 0;
-}
-
static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
{
int id, i, idret;
@@ -1150,7 +1215,7 @@ static int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names)
exts = X509_get0_extensions(x);
if ((num = sk_X509_EXTENSION_num(exts)) <= 0) {
- BIO_printf(bio, "No extensions in certificate\n");
+ BIO_printf(bio_err, "No extensions in certificate\n");
ret = 1;
goto end;
}
diff --git a/appveyor.yml b/appveyor.yml
index 6210391f204a..9bb6f04e0a44 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,5 +1,5 @@
image:
- - Visual Studio 2017
+ - Visual Studio 2017
platform:
- x64
@@ -12,17 +12,24 @@ environment:
configuration:
- shared
- - plain
- minimal
+for:
+ -
+ branches:
+ only:
+ - master
+ configuration:
+ - shared
+ - plain
+ - minimal
+
before_build:
- ps: >-
Install-Module VSSetup -Scope CurrentUser
- ps: >-
Get-VSSetupInstance -All
- ps: >-
- gci env:* | sort-object name
- - ps: >-
If ($env:Platform -Match "x86") {
$env:VCVARS_PLATFORM="x86"
$env:TARGET="VC-WIN32 no-asm --strict-warnings"
@@ -32,47 +39,44 @@ before_build:
}
- ps: >-
If ($env:Configuration -Match "shared") {
- $env:SHARED="no-makedepend"
+ $env:CONFIG_OPTS="enable-fips"
} ElseIf ($env:Configuration -Match "minimal") {
- $env:SHARED="no-shared no-dso no-makedepend no-aria no-async no-autoload-config no-blake2 no-bf no-camellia no-cast no-chacha no-cmac no-cms no-comp no-ct no-des no-dgram no-dh no-dsa no-dtls no-ec2m no-engine no-filenames no-gost no-idea no-mdc2 no-md4 no-multiblock no-nextprotoneg no-ocsp no-ocb no-poly1305 no-psk no-rc2 no-rc4 no-rmd160 no-seed no-siphash no-sm2 no-sm3 no-sm4 no-srp no-srtp no-ssl3 no-ssl3-method no-ts no-ui-console no-whirlpool no-asm -DOPENSSL_SMALL_FOOTPRINT"
+ $env:CONFIG_OPTS="no-bulk no-asm -DOPENSSL_SMALL_FOOTPRINT"
} Else {
- $env:SHARED="no-shared no-makedepend"
+ $env:CONFIG_OPTS="no-fips no-shared"
}
- call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" %VCVARS_PLATFORM%
- mkdir _build
- cd _build
- - perl ..\Configure %TARGET% %SHARED%
+ - perl ..\Configure %TARGET% no-makedepend %CONFIG_OPTS%
- perl configdata.pm --dump
- cd ..
- ps: >-
- if (-not $env:APPVEYOR_PULL_REQUEST_NUMBER`
- -or (&git log -1 $env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT |
- Select-String "\[extended tests\]") ) {
- $env:EXTENDED_TESTS="yes"
+ If ($env:BUILDONLY -or $env:MAKEVERBOSE) {
+ $env:NMAKE="nmake"
+ } Else {
+ $env:NMAKE="nmake /S"
}
+ - ps: >-
+ gci env:* | sort-object name
build_script:
- cd _build
- - ps: >-
- If ($env:Configuration -Match "shared" -or $env:EXTENDED_TESTS) {
- cmd /c "nmake build_all_generated 2>&1"
- cmd /c "nmake PERL=no-perl 2>&1"
- }
+ - "%NMAKE% build_all_generated"
+ - "%NMAKE% PERL=no-perl"
- cd ..
test_script:
- cd _build
- ps: >-
- If ($env:Configuration -Match "shared" -or $env:EXTENDED_TESTS) {
- if ($env:EXTENDED_TESTS) {
- cmd /c "nmake test V=1 2>&1"
- } Else {
- cmd /c "nmake test V=1 TESTS=-test_fuzz 2>&1"
- }
+ if ($env:Configuration -Match "plain") {
+ cmd /c "%NMAKE% test VERBOSE_FAILURE=yes 2>&1"
+ } Else {
+ cmd /c "%NMAKE% test VERBOSE_FAILURE=yes TESTS=-test_fuzz 2>&1"
}
- ps: >-
- if ($env:EXTENDED_TESTS) {
+ if ($env:Configuration -Match "shared") {
mkdir ..\_install
- cmd /c "nmake install DESTDIR=..\_install 2>&1"
+ cmd /c "%NMAKE% install DESTDIR=..\_install 2>&1"
}
- cd ..
diff --git a/build.info b/build.info
index 05c9bdd19c56..5a8421623b97 100644
--- a/build.info
+++ b/build.info
@@ -1,13 +1,14 @@
-{-
- our $sover = $config{shlib_version_number};
- our $sover_filename = $sover;
- $sover_filename =~ s|\.|_|g
- if $config{target} =~ /^mingw/ || $config{target} =~ /^VC-/;
- $sover_filename =
- sprintf "%02d%02d", split m|\.|, $config{shlib_version_number}
- if $config{target} =~ /^vms/;
- "";
--}
+# Note that some of these directories are filtered in Configure. Look for
+# %skipdir there for further explanations.
+
+SUBDIRS=crypto ssl apps util tools fuzz providers doc
+IF[{- !$disabled{tests} -}]
+ SUBDIRS=test
+ENDIF
+IF[{- !$disabled{'deprecated-3.0'} -}]
+ SUBDIRS=engines
+ENDIF
+
LIBS=libcrypto libssl
INCLUDE[libcrypto]=. include
INCLUDE[libssl]=. include
@@ -15,89 +16,77 @@ DEPEND[libssl]=libcrypto
# Empty DEPEND "indices" means the dependencies are expected to be built
# unconditionally before anything else.
-DEPEND[]=include/openssl/opensslconf.h include/crypto/bn_conf.h \
- include/crypto/dso_conf.h
-DEPEND[include/openssl/opensslconf.h]=configdata.pm
-GENERATE[include/openssl/opensslconf.h]=include/openssl/opensslconf.h.in
-DEPEND[include/crypto/bn_conf.h]=configdata.pm
+DEPEND[]=include/openssl/asn1.h \
+ include/openssl/asn1t.h \
+ include/openssl/bio.h \
+ include/openssl/cmp.h \
+ include/openssl/cms.h \
+ include/openssl/conf.h \
+ include/openssl/crmf.h \
+ include/openssl/crypto.h \
+ include/openssl/ct.h \
+ include/openssl/err.h \
+ include/openssl/ess.h \
+ include/openssl/fipskey.h \
+ include/openssl/lhash.h \
+ include/openssl/opensslv.h \
+ include/openssl/ocsp.h \
+ include/openssl/pkcs12.h \
+ include/openssl/pkcs7.h \
+ include/openssl/safestack.h \
+ include/openssl/srp.h \
+ include/openssl/ssl.h \
+ include/openssl/ui.h \
+ include/openssl/x509.h \
+ include/openssl/x509v3.h \
+ include/openssl/x509_vfy.h \
+ include/crypto/bn_conf.h include/crypto/dso_conf.h
+
+GENERATE[include/openssl/asn1.h]=include/openssl/asn1.h.in
+GENERATE[include/openssl/asn1t.h]=include/openssl/asn1t.h.in
+GENERATE[include/openssl/bio.h]=include/openssl/bio.h.in
+GENERATE[include/openssl/cmp.h]=include/openssl/cmp.h.in
+GENERATE[include/openssl/cms.h]=include/openssl/cms.h.in
+GENERATE[include/openssl/conf.h]=include/openssl/conf.h.in
+# include/openssl/configuration.h is generated by configdata.pm
+# We still need this information for the FIPS module checksum, but the attribute
+# 'skip' ensures that nothing is actually done with it.
+GENERATE[include/openssl/configuration.h]{skip}=include/openssl/configuration.h.in
+GENERATE[include/openssl/crmf.h]=include/openssl/crmf.h.in
+GENERATE[include/openssl/crypto.h]=include/openssl/crypto.h.in
+GENERATE[include/openssl/ct.h]=include/openssl/ct.h.in
+GENERATE[include/openssl/err.h]=include/openssl/err.h.in
+GENERATE[include/openssl/ess.h]=include/openssl/ess.h.in
+GENERATE[include/openssl/fipskey.h]=include/openssl/fipskey.h.in
+GENERATE[include/openssl/lhash.h]=include/openssl/lhash.h.in
+GENERATE[include/openssl/ocsp.h]=include/openssl/ocsp.h.in
+GENERATE[include/openssl/opensslv.h]=include/openssl/opensslv.h.in
+GENERATE[include/openssl/pkcs12.h]=include/openssl/pkcs12.h.in
+GENERATE[include/openssl/pkcs7.h]=include/openssl/pkcs7.h.in
+GENERATE[include/openssl/safestack.h]=include/openssl/safestack.h.in
+GENERATE[include/openssl/srp.h]=include/openssl/srp.h.in
+GENERATE[include/openssl/ssl.h]=include/openssl/ssl.h.in
+GENERATE[include/openssl/ui.h]=include/openssl/ui.h.in
+GENERATE[include/openssl/x509.h]=include/openssl/x509.h.in
+GENERATE[include/openssl/x509v3.h]=include/openssl/x509v3.h.in
+GENERATE[include/openssl/x509_vfy.h]=include/openssl/x509_vfy.h.in
GENERATE[include/crypto/bn_conf.h]=include/crypto/bn_conf.h.in
-DEPEND[include/crypto/dso_conf.h]=configdata.pm
GENERATE[include/crypto/dso_conf.h]=include/crypto/dso_conf.h.in
IF[{- defined $target{shared_defflag} -}]
- IF[{- $config{target} =~ /^mingw/ -}]
- GENERATE[libcrypto.def]=util/mkdef.pl crypto 32
- DEPEND[libcrypto.def]=util/libcrypto.num
- GENERATE[libssl.def]=util/mkdef.pl ssl 32
- DEPEND[libssl.def]=util/libssl.num
-
- SHARED_SOURCE[libcrypto]=libcrypto.def
- SHARED_SOURCE[libssl]=libssl.def
- ELSIF[{- $config{target} =~ /^aix/ -}]
- GENERATE[libcrypto.map]=util/mkdef.pl crypto aix
- DEPEND[libcrypto.map]=util/libcrypto.num
- GENERATE[libssl.map]=util/mkdef.pl ssl aix
- DEPEND[libssl.map]=util/libssl.num
-
- SHARED_SOURCE[libcrypto]=libcrypto.map
- SHARED_SOURCE[libssl]=libssl.map
- ELSE
- GENERATE[libcrypto.map]=util/mkdef.pl crypto linux
- DEPEND[libcrypto.map]=util/libcrypto.num
- GENERATE[libssl.map]=util/mkdef.pl ssl linux
- DEPEND[libssl.map]=util/libssl.num
+ SHARED_SOURCE[libcrypto]=libcrypto.ld
+ SHARED_SOURCE[libssl]=libssl.ld
- SHARED_SOURCE[libcrypto]=libcrypto.map
- SHARED_SOURCE[libssl]=libssl.map
- ENDIF
+ GENERATE[libcrypto.ld]=util/libcrypto.num libcrypto
+ GENERATE[libssl.ld]=util/libssl.num libssl
+ DEPEND[libcrypto.ld libssl.ld]=configdata.pm util/perl/OpenSSL/Ordinals.pm
ENDIF
-# VMS and VC don't have parametrised .def / .symvec generation, so they get
-# special treatment, since we know they do use these files
-IF[{- $config{target} =~ /^VC-/ -}]
- GENERATE[libcrypto.def]=util/mkdef.pl crypto 32
- DEPEND[libcrypto.def]=util/libcrypto.num
- GENERATE[libssl.def]=util/mkdef.pl ssl 32
- DEPEND[libssl.def]=util/libssl.num
- SHARED_SOURCE[libcrypto]=libcrypto.def
- SHARED_SOURCE[libssl]=libssl.def
-ELSIF[{- $config{target} =~ /^vms/ -}]
- GENERATE[libcrypto.opt]=util/mkdef.pl crypto "VMS"
- DEPEND[libcrypto.opt]=util/libcrypto.num
- GENERATE[libssl.opt]=util/mkdef.pl ssl "VMS"
- DEPEND[libssl.opt]=util/libssl.num
-
- SHARED_SOURCE[libcrypto]=libcrypto.opt
- SHARED_SOURCE[libssl]=libssl.opt
-ENDIF
-
-IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-)/ -}]
+IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}]
GENERATE[libcrypto.rc]=util/mkrc.pl libcrypto
GENERATE[libssl.rc]=util/mkrc.pl libssl
+ DEPEND[libcrypto.rc libssl.rc]=configdata.pm
SHARED_SOURCE[libcrypto]=libcrypto.rc
SHARED_SOURCE[libssl]=libssl.rc
ENDIF
-
-IF[{- $config{target} =~ /^Cygwin/ -}]
- SHARED_NAME[libcrypto]=cygcrypto-{- $sover_filename -}
- SHARED_NAME[libssl]=cygssl-{- $sover_filename -}
-ELSIF[{- $config{target} =~ /^mingw/ -}]
- SHARED_NAME[libcrypto]=libcrypto-{- $sover_filename -}{- $config{target} eq "mingw64" ? "-x64" : "" -}
- SHARED_NAME[libssl]=libssl-{- $sover_filename -}{- $config{target} eq "mingw64" ? "-x64" : "" -}
-ELSIF[{- $config{target} =~ /^VC-/ -}]
- SHARED_NAME[libcrypto]=libcrypto-{- $sover_filename -}{- $target{multilib} -}
- SHARED_NAME[libssl]=libssl-{- $sover_filename -}{- $target{multilib} -}
-ENDIF
-
-# VMS has a cultural standard where all libraries are prefixed.
-# For OpenSSL, the choice is 'ossl$' (this prefix was claimed in a
-# conversation with VSI, Tuesday January 26 2016)
-# Also, it seems it's usual to have the pointer size the libraries
-# were built for as part of the name.
-IF[{- $config{target} =~ /^vms/ -}]
- RENAME[libcrypto]=ossl$libcrypto{- $target{pointer_size} -}
- RENAME[libssl]=ossl$libssl{- $target{pointer_size} -}
- SHARED_NAME[libcrypto]=ossl$libcrypto{- $sover_filename -}_shr{- $target{pointer_size} -}
- SHARED_NAME[libssl]=ossl$libssl{- $sover_filename -}_shr{- $target{pointer_size} -}
-ENDIF
diff --git a/config b/config
index c7b035a0c57c..e194d4bde4f6 100755
--- a/config
+++ b/config
@@ -1,946 +1,10 @@
-#!/bin/sh
-# Copyright 1998-2022 The OpenSSL Project Authors. All Rights Reserved.
+#! /bin/sh
+# Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
-# OpenSSL config: determine the operating system and run ./Configure
-# Derived from minarch and GuessOS from Apache.
-#
-# Do "config -h" for usage information.
-SUFFIX=""
-DRYRUN="false"
-VERBOSE="false"
-EXE=""
THERE=`dirname $0`
-
-# pick up any command line args to config
-for i
-do
-case "$i" in
--d*) options=$options" --debug";;
--t*) DRYRUN="true" VERBOSE="true";;
--v*) VERBOSE="true";;
--h*) DRYRUN="true"; cat <<EOF
-Usage: config [options]
- -d Build with debugging when possible.
- -t Test mode, do not run the Configure perl script.
- -v Verbose mode, show the exact Configure call that is being made.
- -h This help.
-
-Any other text will be passed to the Configure perl script.
-See INSTALL for instructions.
-
-EOF
-;;
-*) i=`echo "$i" | sed -e "s|'|'\\\\\\''|g"`
- options="$options '$i'" ;;
-esac
-done
-
-# Environment that's being passed to Configure
-__CNF_CPPDEFINES=
-__CNF_CPPINCLUDES=
-__CNF_CPPFLAGS=
-__CNF_CFLAGS=
-__CNF_CXXFLAGS=
-__CNF_LDFLAGS=
-__CNF_LDLIBS=
-
-# First get uname entries that we use below
-
-[ "$MACHINE" ] || MACHINE=`(uname -m) 2>/dev/null` || MACHINE="unknown"
-[ "$RELEASE" ] || RELEASE=`(uname -r) 2>/dev/null` || RELEASE="unknown"
-[ "$SYSTEM" ] || SYSTEM=`(uname -s) 2>/dev/null` || SYSTEM="unknown"
-[ "$BUILD" ] || VERSION=`(uname -v) 2>/dev/null` || VERSION="unknown"
-
-
-# Now test for ISC and SCO, since it is has a braindamaged uname.
-#
-# We need to work around FreeBSD 1.1.5.1
-(
-XREL=`uname -X 2>/dev/null | grep "^Release" | awk '{print $3}'`
-if [ "x$XREL" != "x" ]; then
- if [ -f /etc/kconfig ]; then
- case "$XREL" in
- 4.0|4.1)
- echo "${MACHINE}-whatever-isc4"; exit 0
- ;;
- esac
- else
- case "$XREL" in
- 3.2v4.2)
- echo "whatever-whatever-sco3"; exit 0
- ;;
- 3.2v5.0*)
- echo "whatever-whatever-sco5"; exit 0
- ;;
- 4.2MP)
- case "x${VERSION}" in
- x2.0*) echo "whatever-whatever-unixware20"; exit 0 ;;
- x2.1*) echo "whatever-whatever-unixware21"; exit 0 ;;
- x2*) echo "whatever-whatever-unixware2"; exit 0 ;;
- esac
- ;;
- 4.2)
- echo "whatever-whatever-unixware1"; exit 0
- ;;
- 5*)
- case "x${VERSION}" in
- # We hardcode i586 in place of ${MACHINE} for the
- # following reason. The catch is that even though Pentium
- # is minimum requirement for platforms in question,
- # ${MACHINE} gets always assigned to i386. Now, problem
- # with i386 is that it makes ./config pass 386 to
- # ./Configure, which in turn makes make generate
- # inefficient SHA-1 (for this moment) code.
- x[678]*) echo "i586-sco-unixware7"; exit 0 ;;
- esac
- ;;
- esac
- fi
-fi
-# Now we simply scan though... In most cases, the SYSTEM info is enough
-#
-case "${SYSTEM}:${RELEASE}:${VERSION}:${MACHINE}" in
- A/UX:*)
- echo "m68k-apple-aux3"; exit 0
- ;;
-
- AIX:[3-9]:4:*)
- echo "${MACHINE}-ibm-aix"; exit 0
- ;;
-
- AIX:*:[5-9]:*)
- echo "${MACHINE}-ibm-aix"; exit 0
- ;;
-
- AIX:*)
- echo "${MACHINE}-ibm-aix3"; exit 0
- ;;
-
- HI-UX:*)
- echo "${MACHINE}-hi-hiux"; exit 0
- ;;
-
- HP-UX:*)
- HPUXVER=`echo ${RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- case "$HPUXVER" in
- 1[0-9].*) # HPUX 10 and 11 targets are unified
- echo "${MACHINE}-hp-hpux1x"; exit 0
- ;;
- *)
- echo "${MACHINE}-hp-hpux"; exit 0
- ;;
- esac
- ;;
-
- IRIX:6.*)
- echo "mips3-sgi-irix"; exit 0
- ;;
-
- IRIX64:*)
- echo "mips4-sgi-irix64"; exit 0
- ;;
-
- Linux:[2-9].*)
- echo "${MACHINE}-whatever-linux2"; exit 0
- ;;
-
- Linux:1.*)
- echo "${MACHINE}-whatever-linux1"; exit 0
- ;;
-
- GNU*)
- echo "hurd-x86"; exit 0;
- ;;
-
- LynxOS:*)
- echo "${MACHINE}-lynx-lynxos"; exit 0
- ;;
-
- BSD/OS:4.*) # BSD/OS always says 386
- echo "i486-whatever-bsdi4"; exit 0
- ;;
-
- BSD/386:*:*:*486*|BSD/OS:*:*:*:*486*)
- case `/sbin/sysctl -n hw.model` in
- Pentium*)
- echo "i586-whatever-bsdi"; exit 0
- ;;
- *)
- echo "i386-whatever-bsdi"; exit 0
- ;;
- esac;
- ;;
-
- BSD/386:*|BSD/OS:*)
- echo "${MACHINE}-whatever-bsdi"; exit 0
- ;;
-
- FreeBSD:*:*:*386*)
- VERS=`echo ${RELEASE} | sed -e 's/[-(].*//'`
- MACH=`sysctl -n hw.model`
- ARCH='whatever'
- case ${MACH} in
- *386* ) MACH="i386" ;;
- *486* ) MACH="i486" ;;
- Pentium\ II*) MACH="i686" ;;
- Pentium* ) MACH="i586" ;;
- * ) MACH="$MACHINE" ;;
- esac
- case ${MACH} in
- i[0-9]86 ) ARCH="pc" ;;
- esac
- echo "${MACH}-${ARCH}-freebsd${VERS}"; exit 0
- ;;
-
- DragonFly:*)
- echo "${MACHINE}-whatever-dragonfly"; exit 0
- ;;
-
- FreeBSD:*)
- echo "${MACHINE}-whatever-freebsd"; exit 0
- ;;
-
- Haiku:*)
- echo "${MACHINE}-whatever-haiku"; exit 0
- ;;
-
- NetBSD:*:*:*386*)
- echo "`(/usr/sbin/sysctl -n hw.model || /sbin/sysctl -n hw.model) | sed 's,.*\(.\)86-class.*,i\186,'`-whatever-netbsd"; exit 0
- ;;
-
- NetBSD:*)
- echo "${MACHINE}-whatever-netbsd"; exit 0
- ;;
-
- OpenBSD:*)
- echo "${MACHINE}-whatever-openbsd"; exit 0
- ;;
-
- OpenUNIX:*)
- echo "${MACHINE}-unknown-OpenUNIX${VERSION}"; exit 0
- ;;
-
- OSF1:*:*:*alpha*)
- OSFMAJOR=`echo ${RELEASE}| sed -e 's/^V\([0-9]*\)\..*$/\1/'`
- case "$OSFMAJOR" in
- 4|5)
- echo "${MACHINE}-dec-tru64"; exit 0
- ;;
- 1|2|3)
- echo "${MACHINE}-dec-osf"; exit 0
- ;;
- *)
- echo "${MACHINE}-dec-osf"; exit 0
- ;;
- esac
- ;;
-
- Paragon*:*:*:*)
- echo "i860-intel-osf1"; exit 0
- ;;
-
- Rhapsody:*)
- echo "ppc-apple-rhapsody"; exit 0
- ;;
-
- Darwin:*)
- case "$MACHINE" in
- Power*)
- echo "ppc-apple-darwin${VERSION}"
- ;;
- *)
- echo "${MACHINE}-apple-darwin${VERSION}"
- ;;
- esac
- exit 0
- ;;
-
- SunOS:5.*)
- echo "${MACHINE}-whatever-solaris2"; exit 0
- ;;
-
- SunOS:*)
- echo "${MACHINE}-sun-sunos4"; exit 0
- ;;
-
- UNIX_System_V:4.*:*)
- echo "${MACHINE}-whatever-sysv4"; exit 0
- ;;
-
- VOS:*:*:i786)
- echo "i386-stratus-vos"; exit 0
- ;;
-
- VOS:*:*:*)
- echo "hppa1.1-stratus-vos"; exit 0
- ;;
-
- *:4*:R4*:m88k)
- echo "${MACHINE}-whatever-sysv4"; exit 0
- ;;
-
- DYNIX/ptx:4*:*)
- echo "${MACHINE}-whatever-sysv4"; exit 0
- ;;
-
- *:4.0:3.0:3[34]?? | *:4.0:3.0:3[34]??,*)
- echo "i486-ncr-sysv4"; exit 0
- ;;
-
- ULTRIX:*)
- echo "${MACHINE}-unknown-ultrix"; exit 0
- ;;
-
- POSIX-BC*)
- echo "${MACHINE}-siemens-sysv4"; exit 0 # Here, $MACHINE == "BS2000"
- ;;
-
- machten:*)
- echo "${MACHINE}-tenon-${SYSTEM}"; exit 0;
- ;;
-
- library:*)
- echo "${MACHINE}-ncr-sysv4"; exit 0
- ;;
-
- ConvexOS:*:11.0:*)
- echo "${MACHINE}-v11-${SYSTEM}"; exit 0;
- ;;
-
- # The following combinations are supported
- # MINGW64* on x86_64 => mingw64
- # MINGW32* on x86_64 => mingw
- # MINGW32* on i?86 => mingw
- #
- # MINGW64* on i?86 isn't expected to work...
- MINGW64*:*:*:x86_64)
- echo "${MACHINE}-whatever-mingw64"; exit 0;
- ;;
- MINGW*)
- echo "${MACHINE}-whatever-mingw"; exit 0;
- ;;
- CYGWIN*)
- echo "${MACHINE}-pc-cygwin"; exit 0
- ;;
-
- vxworks*)
- echo "${MACHINE}-whatever-vxworks"; exit 0;
- ;;
-esac
-
-#
-# Ugg. These are all we can determine by what we know about
-# the output of uname. Be more creative:
-#
-
-# Do the Apollo stuff first. Here, we just simply assume
-# that the existence of the /usr/apollo directory is proof
-# enough
-if [ -d /usr/apollo ]; then
- echo "whatever-apollo-whatever"
- exit 0
-fi
-
-# Now NeXT
-ISNEXT=`hostinfo 2>/dev/null`
-case "$ISNEXT" in
- *'NeXT Mach 3.3'*)
- echo "whatever-next-nextstep3.3"; exit 0
- ;;
- *NeXT*)
- echo "whatever-next-nextstep"; exit 0
- ;;
-esac
-
-# At this point we gone through all the one's
-# we know of: Punt
-
-echo "${MACHINE}-whatever-${SYSTEM}"
-exit 0
-) 2>/dev/null | (
-
-# ---------------------------------------------------------------------------
-# this is where the translation occurs into SSLeay terms
-# ---------------------------------------------------------------------------
-
-# Only set CC if not supplied already
-if [ -z "$CROSS_COMPILE$CC" ]; then
- GCCVER=`sh -c "gcc -dumpversion" 2>/dev/null`
- if [ "$GCCVER" != "" ]; then
- # then strip off whatever prefix egcs prepends the number with...
- # Hopefully, this will work for any future prefixes as well.
- GCCVER=`echo $GCCVER | LC_ALL=C sed 's/^[a-zA-Z]*\-//'`
- # Since gcc 3.1 gcc --version behaviour has changed. gcc -dumpversion
- # does give us what we want though, so we use that. We just just the
- # major and minor version numbers.
- # peak single digit before and after first dot, e.g. 2.95.1 gives 29
- GCCVER=`echo $GCCVER | sed 's/\([0-9]\)\.\([0-9]\).*/\1\2/'`
- CC=gcc
- else
- CC=cc
- fi
-fi
-GCCVER=${GCCVER:-0}
-if [ "$SYSTEM" = "HP-UX" ];then
- # By default gcc is a ILP32 compiler (with long long == 64).
- GCC_BITS="32"
- if [ $GCCVER -ge 30 ]; then
- # PA64 support only came in with gcc 3.0.x.
- # We check if the preprocessor symbol __LP64__ is defined...
- if echo "__LP64__" | gcc -v -E -x c - 2>/dev/null | grep "^__LP64__" 2>&1 > /dev/null; then
- : # __LP64__ has slipped through, it therefore is not defined
- else
- GCC_BITS="64"
- fi
- fi
-fi
-if [ "$SYSTEM" = "SunOS" ]; then
- if [ $GCCVER -ge 30 ]; then
- # 64-bit ABI isn't officially supported in gcc 3.0, but it appears
- # to be working, at the very least 'make test' passes...
- if gcc -v -E -x c /dev/null 2>&1 | grep __arch64__ > /dev/null; then
- GCC_ARCH="-m64"
- else
- GCC_ARCH="-m32"
- fi
- fi
- # check for WorkShop C, expected output is "cc: blah-blah C x.x"
- CCVER=`(cc -V 2>&1) 2>/dev/null | \
- egrep -e '^cc: .* C [0-9]\.[0-9]' | \
- sed 's/.* C \([0-9]\)\.\([0-9]\).*/\1\2/'`
- CCVER=${CCVER:-0}
- if [ $MACHINE != i86pc -a $CCVER -gt 40 ]; then
- CC=cc # overrides gcc!!!
- if [ $CCVER -eq 50 ]; then
- echo "WARNING! Detected WorkShop C 5.0. Do make sure you have"
- echo " patch #107357-01 or later applied."
- sleep 5
- fi
- fi
-fi
-
-if [ "${SYSTEM}" = "AIX" ]; then # favor vendor cc over gcc
- (cc) 2>&1 | grep -iv "not found" > /dev/null && CC=cc
-fi
-
-CCVER=${CCVER:-0}
-
-# read the output of the embedded GuessOS
-read GUESSOS
-
-echo Operating system: $GUESSOS
-
-# now map the output into SSLeay terms ... really should hack into the
-# script above so we end up with values in vars but that would take
-# more time that I want to waste at the moment
-case "$GUESSOS" in
- uClinux*64*)
- OUT=uClinux-dist64
- ;;
- uClinux*)
- OUT=uClinux-dist
- ;;
- mips3-sgi-irix)
- OUT="irix-mips3-$CC"
- ;;
- mips4-sgi-irix64)
- echo "WARNING! If you wish to build 64-bit library, then you have to"
- echo " invoke '$THERE/Configure irix64-mips4-$CC' *manually*."
- if [ "$DRYRUN" = "false" -a -t 1 ]; then
- echo " You have about 5 seconds to press Ctrl-C to abort."
- (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1
- fi
- OUT="irix-mips3-$CC"
- ;;
- ppc-apple-rhapsody) OUT="rhapsody-ppc-cc" ;;
- ppc-apple-darwin*)
- ISA64=`(sysctl -n hw.optional.64bitops) 2>/dev/null`
- if [ "$ISA64" = "1" -a -z "$KERNEL_BITS" ]; then
- echo "WARNING! If you wish to build 64-bit library, then you have to"
- echo " invoke '$THERE/Configure darwin64-ppc-cc' *manually*."
- if [ "$DRYRUN" = "false" -a -t 1 ]; then
- echo " You have about 5 seconds to press Ctrl-C to abort."
- (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1
- fi
- fi
- if [ "$ISA64" = "1" -a "$KERNEL_BITS" = "64" ]; then
- OUT="darwin64-ppc-cc"
- else
- OUT="darwin-ppc-cc"
- fi ;;
- i?86-apple-darwin*)
- ISA64=`(sysctl -n hw.optional.x86_64) 2>/dev/null`
- if [ "$ISA64" = "1" -a -z "$KERNEL_BITS" ]; then
- echo "WARNING! If you wish to build 64-bit library, then you have to"
- echo " invoke 'KERNEL_BITS=64 $THERE/config $options'."
- if [ "$DRYRUN" = "false" -a -t 1 ]; then
- echo " You have about 5 seconds to press Ctrl-C to abort."
- (trap "stty `stty -g`; exit 1" 2; stty -icanon min 0 time 50; read waste; exit 0) <&1 || exit
- fi
- fi
- if [ "$ISA64" = "1" -a "$KERNEL_BITS" = "64" ]; then
- OUT="darwin64-x86_64-cc"
- else
- OUT="darwin-i386-cc"
- fi ;;
- x86_64-apple-darwin*)
- if [ "$KERNEL_BITS" = "32" ]; then
- OUT="darwin-i386-cc"
- else
- OUT="darwin64-x86_64-cc"
- fi ;;
- $MACHINE-apple-darwin*)
- OUT="darwin64-$MACHINE-cc"
- ;;
- armv6+7-*-iphoneos)
- __CNF_CFLAGS="$__CNF_CFLAGS -arch armv6 -arch armv7"
- __CNF_CXXFLAGS="$__CNF_CXXFLAGS -arch armv6 -arch armv7"
- OUT="iphoneos-cross" ;;
- *-*-iphoneos)
- __CNF_CFLAGS="$__CNF_CFLAGS -arch ${MACHINE}"
- __CNF_CXXFLAGS="$__CNF_CXXFLAGS -arch ${MACHINE}"
- OUT="iphoneos-cross" ;;
- arm64-*-iphoneos|*-*-ios64)
- OUT="ios64-cross" ;;
- alpha-*-linux2)
- ISA=`awk '/cpu model/{print$4;exit(0);}' /proc/cpuinfo`
- OUT="linux-alpha-$CC"
- if [ "$CC" = "gcc" ]; then
- case ${ISA:-generic} in
- EV5|EV45) __CNF_CFLAGS="$__CNF_CFLAGS -mcpu=ev5"
- __CNF_CXXFLAGS="$__CNF_CFLAGS -mcpu=ev5";;
- EV56|PCA56) __CNF_CFLAGS="$__CNF_CFLAGS -mcpu=ev56"
- __CNF_CXXFLAGS="$__CNF_CXXFLAGS -mcpu=ev56";;
- *) __CNF_CFLAGS="$__CNF_CFLAGS -mcpu=ev6"
- __CNF_CXXFLAGS="$__CNF_CXXFLAGS -mcpu=ev6";;
- esac
- fi
- ;;
- ppc64-*-linux2)
- if [ -z "$KERNEL_BITS" ]; then
- echo "WARNING! If you wish to build 64-bit library, then you have to"
- echo " invoke '$THERE/Configure linux-ppc64' *manually*."
- if [ "$DRYRUN" = "false" -a -t 1 ]; then
- echo " You have about 5 seconds to press Ctrl-C to abort."
- (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1
- fi
- fi
- if [ "$KERNEL_BITS" = "64" ]; then
- OUT="linux-ppc64"
- else
- OUT="linux-ppc"
- if (echo "__LP64__" | gcc -E -x c - 2>/dev/null | grep "^__LP64__" 2>&1 > /dev/null); then
- :;
- else
- __CNF_CFLAGS="$__CNF_CFLAGS -m32"
- __CNF_CXXFLAGS="$__CNF_CXXFLAGS -m32"
- fi
- fi
- ;;
- ppc64le-*-linux2) OUT="linux-ppc64le" ;;
- ppc-*-linux2) OUT="linux-ppc" ;;
- mips64*-*-linux2)
- echo "WARNING! If you wish to build 64-bit library, then you have to"
- echo " invoke '$THERE/Configure linux64-mips64' *manually*."
- if [ "$DRYRUN" = "false" -a -t 1 ]; then
- echo " You have about 5 seconds to press Ctrl-C to abort."
- (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1
- fi
- OUT="linux-mips64"
- ;;
- mips*-*-linux2) OUT="linux-mips32" ;;
- ppc60x-*-vxworks*) OUT="vxworks-ppc60x" ;;
- ppcgen-*-vxworks*) OUT="vxworks-ppcgen" ;;
- pentium-*-vxworks*) OUT="vxworks-pentium" ;;
- simlinux-*-vxworks*) OUT="vxworks-simlinux" ;;
- mips-*-vxworks*) OUT="vxworks-mips";;
- ia64-*-linux?) OUT="linux-ia64" ;;
- sparc64-*-linux2)
- echo "WARNING! If you *know* that your GNU C supports 64-bit/V9 ABI"
- echo " and wish to build 64-bit library, then you have to"
- echo " invoke '$THERE/Configure linux64-sparcv9' *manually*."
- if [ "$DRYRUN" = "false" -a -t 1 ]; then
- echo " You have about 5 seconds to press Ctrl-C to abort."
- (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1
- fi
- OUT="linux-sparcv9" ;;
- sparc-*-linux2)
- KARCH=`awk '/^type/{print$3;exit(0);}' /proc/cpuinfo`
- case ${KARCH:-sun4} in
- sun4u*) OUT="linux-sparcv9" ;;
- sun4m) OUT="linux-sparcv8" ;;
- sun4d) OUT="linux-sparcv8" ;;
- *) OUT="linux-generic32";
- __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" ;;
- esac ;;
- parisc*-*-linux2)
- # 64-bit builds under parisc64 linux are not supported and
- # compiler is expected to generate 32-bit objects...
- CPUARCH=`awk '/cpu family/{print substr($5,1,3); exit(0);}' /proc/cpuinfo`
- CPUSCHEDULE=`awk '/^cpu.[ ]*: PA/{print substr($3,3); exit(0);}' /proc/cpuinfo`
-
- # ??TODO ?? Model transformations
- # 0. CPU Architecture for the 1.1 processor has letter suffixes. We strip that off
- # assuming no further arch. identification will ever be used by GCC.
- # 1. I'm most concerned about whether is a 7300LC is closer to a 7100 versus a 7100LC.
- # 2. The variant 64-bit processors cause concern should GCC support explicit schedulers
- # for these chips in the future.
- # PA7300LC -> 7100LC (1.1)
- # PA8200 -> 8000 (2.0)
- # PA8500 -> 8000 (2.0)
- # PA8600 -> 8000 (2.0)
-
- CPUSCHEDULE=`echo $CPUSCHEDULE|sed -e 's/7300LC/7100LC/' -e 's/8.00/8000/'`
- # Finish Model transformations
-
- __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN"
- __CNF_CFLAGS="$__CNF_CFLAGS -mschedule=$CPUSCHEDULE -march=$CPUARCH"
- __CNF_CXXFLAGS="$__CNF_CXXFLAGS -mschedule=$CPUSCHEDULE -march=$CPUARCH"
- OUT="linux-generic32" ;;
- armv[1-3]*-*-linux2) OUT="linux-generic32" ;;
- armv[7-9]*-*-linux2) OUT="linux-armv4"
- __CNF_CFLAGS="$__CNF_CFLAGS -march=armv7-a"
- __CNF_CXXFLAGS="$__CNF_CXXFLAGS -march=armv7-a"
- ;;
- arm*-*-linux2) OUT="linux-armv4" ;;
- aarch64-*-linux2) OUT="linux-aarch64" ;;
- sh*b-*-linux2) OUT="linux-generic32";
- __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" ;;
- sh*-*-linux2) OUT="linux-generic32";
- __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DL_ENDIAN" ;;
- m68k*-*-linux2) OUT="linux-generic32";
- __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" ;;
- s390-*-linux2) OUT="linux-generic32";
- __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" ;;
- s390x-*-linux2)
- # To be uncommented when glibc bug is fixed, see Configure...
- #if egrep -e '^features.* highgprs' /proc/cpuinfo >/dev/null ; then
- # echo "WARNING! If you wish to build \"highgprs\" 32-bit library, then you"
- # echo " have to invoke './Configure linux32-s390x' *manually*."
- # if [ "$DRYRUN" = "false" -a -t -1 ]; then
- # echo " You have about 5 seconds to press Ctrl-C to abort."
- # (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1
- # fi
- #fi
- OUT="linux64-s390x"
- ;;
- x86_64-*-linux?)
- if $CC -dM -E -x c /dev/null 2>&1 | grep -q ILP32 > /dev/null; then
- OUT="linux-x32"
- else
- OUT="linux-x86_64"
- fi ;;
- *86-*-linux2)
- # On machines where the compiler understands -m32, prefer a
- # config target that uses it
- if $CC -m32 -E -x c /dev/null > /dev/null 2>&1; then
- OUT="linux-x86"
- else
- OUT="linux-elf"
- fi ;;
- *86-*-linux1) OUT="linux-aout" ;;
- *-*-linux?) OUT="linux-generic32" ;;
- sun4[uv]*-*-solaris2)
- OUT="solaris-sparcv9-$CC"
- ISA64=`(isainfo) 2>/dev/null | grep sparcv9`
- if [ "$ISA64" != "" -a "$KERNEL_BITS" = "" ]; then
- if [ "$CC" = "cc" -a $CCVER -ge 50 ]; then
- echo "WARNING! If you wish to build 64-bit library, then you have to"
- echo " invoke '$THERE/Configure solaris64-sparcv9-cc' *manually*."
- if [ "$DRYRUN" = "false" -a -t 1 ]; then
- echo " You have about 5 seconds to press Ctrl-C to abort."
- (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1
- fi
- elif [ "$CC" = "gcc" -a "$GCC_ARCH" = "-m64" ]; then
- # $GCC_ARCH denotes default ABI chosen by compiler driver
- # (first one found on the $PATH). I assume that user
- # expects certain consistency with the rest of his builds
- # and therefore switch over to 64-bit. <appro>
- OUT="solaris64-sparcv9-gcc"
- echo "WARNING! If you wish to build 32-bit library, then you have to"
- echo " invoke '$THERE/Configure solaris-sparcv9-gcc' *manually*."
- if [ "$DRYRUN" = "false" -a -t 1 ]; then
- echo " You have about 5 seconds to press Ctrl-C to abort."
- (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1
- fi
- elif [ "$GCC_ARCH" = "-m32" ]; then
- echo "NOTICE! If you *know* that your GNU C supports 64-bit/V9 ABI"
- echo " and wish to build 64-bit library, then you have to"
- echo " invoke '$THERE/Configure solaris64-sparcv9-gcc' *manually*."
- if [ "$DRYRUN" = "false" -a -t 1 ]; then
- echo " You have about 5 seconds to press Ctrl-C to abort."
- (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1
- fi
- fi
- fi
- if [ "$ISA64" != "" -a "$KERNEL_BITS" = "64" ]; then
- OUT="solaris64-sparcv9-$CC"
- fi
- ;;
- sun4m-*-solaris2) OUT="solaris-sparcv8-$CC" ;;
- sun4d-*-solaris2) OUT="solaris-sparcv8-$CC" ;;
- sun4*-*-solaris2) OUT="solaris-sparcv7-$CC" ;;
- *86*-*-solaris2)
- ISA64=`(isainfo) 2>/dev/null | grep amd64`
- if [ "$ISA64" != "" -a ${KERNEL_BITS:-64} -eq 64 ]; then
- OUT="solaris64-x86_64-$CC"
- else
- OUT="solaris-x86-$CC"
- if [ `uname -r | sed -e 's/5\.//'` -lt 10 ]; then
- options="$options no-sse2"
- fi
- fi
- ;;
- *-*-sunos4) OUT="sunos-$CC" ;;
-
- *86*-*-bsdi4) OUT="BSD-x86-elf"; options="$options no-sse2";
- __CNF_LDFLAGS="$__CNF_LDFLAGS -ldl" ;;
- alpha*-*-*bsd*) OUT="BSD-generic64";
- __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DL_ENDIAN" ;;
- powerpc64-*-*bsd*) OUT="BSD-generic64";
- __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" ;;
- riscv64-*-*bsd*) OUT="BSD-riscv64" ;;
- sparc64-*-*bsd*) OUT="BSD-sparc64" ;;
- ia64-*-*bsd*) OUT="BSD-ia64" ;;
- x86_64-*-dragonfly*) OUT="BSD-x86_64" ;;
- amd64-*-*bsd*) OUT="BSD-x86_64" ;;
- arm64-*-*bsd*) OUT="BSD-aarch64" ;;
- *86*-*-*bsd*) # mimic ld behaviour when it's looking for libc...
- if [ -L /usr/lib/libc.so ]; then # [Free|Net]BSD
- libc=/usr/lib/libc.so
- else # OpenBSD
- # ld searches for highest libc.so.* and so do we
- libc=`(ls /usr/lib/libc.so.* /lib/libc.so.* | tail -1) 2>/dev/null`
- fi
- case "`(file -L $libc) 2>/dev/null`" in
- *ELF*) OUT="BSD-x86-elf" ;;
- *) OUT="BSD-x86"; options="$options no-sse2" ;;
- esac ;;
- *-*-*bsd*) OUT="BSD-generic32" ;;
-
- x86_64-*-haiku) OUT="haiku-x86_64" ;;
- *-*-haiku) OUT="haiku-x86" ;;
-
- *-*-osf) OUT="osf1-alpha-cc" ;;
- *-*-tru64) OUT="tru64-alpha-cc" ;;
- *-*-[Uu]nix[Ww]are7)
- if [ "$CC" = "gcc" ]; then
- OUT="unixware-7-gcc" ; options="$options no-sse2"
- else
- OUT="unixware-7" ; options="$options no-sse2"
- __CNF_CPPFLAGS="$__CNF_CPPFLAGS -D__i386__"
- fi
- ;;
- *-*-[Uu]nix[Ww]are20*) OUT="unixware-2.0"; options="$options no-sse2 no-sha512" ;;
- *-*-[Uu]nix[Ww]are21*) OUT="unixware-2.1"; options="$options no-sse2 no-sha512" ;;
- *-*-vos)
- options="$options no-threads no-shared no-asm no-dso"
- EXE=".pm"
- OUT="vos-$CC" ;;
- BS2000-siemens-sysv4) OUT="BS2000-OSD" ;;
- *-hpux1*)
- if [ $CC = "gcc" -a $GCC_BITS = "64" ]; then
- OUT="hpux64-parisc2-gcc"
- fi
- [ "$KERNEL_BITS" ] || KERNEL_BITS=`(getconf KERNEL_BITS) 2>/dev/null`
- KERNEL_BITS=${KERNEL_BITS:-32}
- CPU_VERSION=`(getconf CPU_VERSION) 2>/dev/null`
- CPU_VERSION=${CPU_VERSION:-0}
- # See <sys/unistd.h> for further info on CPU_VERSION.
- if [ $CPU_VERSION -ge 768 ]; then # IA-64 CPU
- if [ $KERNEL_BITS -eq 64 -a "$CC" = "cc" ]; then
- OUT="hpux64-ia64-cc"
- else
- OUT="hpux-ia64-cc"
- fi
- elif [ $CPU_VERSION -ge 532 ]; then # PA-RISC 2.x CPU
- # PA-RISC 2.0 is no longer supported as separate 32-bit
- # target. This is compensated for by run-time detection
- # in most critical assembly modules and taking advantage
- # of 2.0 architecture in PA-RISC 1.1 build.
- OUT=${OUT:-"hpux-parisc1_1-${CC}"}
- if [ $KERNEL_BITS -eq 64 -a "$CC" = "cc" ]; then
- echo "WARNING! If you wish to build 64-bit library then you have to"
- echo " invoke '$THERE/Configure hpux64-parisc2-cc' *manually*."
- if [ "$DRYRUN" = "false" -a -t 1 ]; then
- echo " You have about 5 seconds to press Ctrl-C to abort."
- (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1
- fi
- fi
- elif [ $CPU_VERSION -ge 528 ]; then # PA-RISC 1.1+ CPU
- OUT="hpux-parisc1_1-${CC}"
- elif [ $CPU_VERSION -ge 523 ]; then # PA-RISC 1.0 CPU
- OUT="hpux-parisc-${CC}"
- else # Motorola(?) CPU
- OUT="hpux-$CC"
- fi
- __CNF_CPPFLAGS="$__CNF_CPPFLAGS -D_REENTRANT" ;;
- *-hpux) OUT="hpux-parisc-$CC" ;;
- *-aix)
- [ "$KERNEL_BITS" ] || KERNEL_BITS=`(getconf KERNEL_BITMODE) 2>/dev/null`
- KERNEL_BITS=${KERNEL_BITS:-32}
- OBJECT_MODE=${OBJECT_MODE:-32}
- if [ "$CC" = "gcc" ]; then
- OUT="aix-gcc"
- if [ $OBJECT_MODE -eq 64 ]; then
- echo 'Your $OBJECT_MODE was found to be set to 64'
- OUT="aix64-gcc"
- fi
- elif [ $OBJECT_MODE -eq 64 ]; then
- echo 'Your $OBJECT_MODE was found to be set to 64'
- OUT="aix64-cc"
- else
- OUT="aix-cc"
- if [ $KERNEL_BITS -eq 64 ]; then
- echo "WARNING! If you wish to build 64-bit kit, then you have to"
- echo " invoke '$THERE/Configure aix64-cc' *manually*."
- if [ "$DRYRUN" = "false" -a -t 1 ]; then
- echo " You have ~5 seconds to press Ctrl-C to abort."
- (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1
- fi
- fi
- fi
- if (lsattr -E -O -l `lsdev -c processor|awk '{print$1;exit}'` | grep -i powerpc) >/dev/null 2>&1; then
- : # this applies even to Power3 and later, as they return PowerPC_POWER[345]
- else
- options="$options no-asm"
- fi
- ;;
- # these are all covered by the catchall below
- i[3456]86-*-cygwin) OUT="Cygwin-x86" ;;
- *-*-cygwin) OUT="Cygwin-${MACHINE}" ;;
- x86-*-android|i?86-*-android) OUT="android-x86" ;;
- armv[7-9]*-*-android)
- OUT="android-armeabi"
- __CNF_CFLAGS="$__CNF_CFLAGS -march=armv7-a"
- __CNF_CXXFLAGS="$__CNF_CXXFLAGS -march=armv7-a";;
- arm*-*-android) OUT="android-armeabi" ;;
- *) OUT=`echo $GUESSOS | awk -F- '{print $3}'`;;
-esac
-
-# NB: This atalla support has been superseded by the ENGINE support
-# That contains its own header and definitions anyway. Support can
-# be enabled or disabled on any supported platform without external
-# headers, eg. by adding the "hw-atalla" switch to ./config or
-# perl Configure
-#
-# See whether we can compile Atalla support
-#if [ -f /usr/include/atasi.h ]
-#then
-# __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DATALLA"
-#fi
-
-if [ -n "$CONFIG_OPTIONS" ]; then
- options="$options $CONFIG_OPTIONS"
-fi
-
-# gcc < 2.8 does not support -march=ultrasparc
-if [ "$OUT" = solaris-sparcv9-gcc -a $GCCVER -lt 28 ]
-then
- echo "WARNING! Falling down to 'solaris-sparcv8-gcc'."
- echo " Upgrade to gcc-2.8 or later."
- sleep 5
- OUT=solaris-sparcv8-gcc
-fi
-if [ "$OUT" = "linux-sparcv9" -a $GCCVER -lt 28 ]
-then
- echo "WARNING! Falling down to 'linux-sparcv8'."
- echo " Upgrade to gcc-2.8 or later."
- sleep 5
- OUT=linux-sparcv8
-fi
-
-case "$GUESSOS" in
- i386-*) options="$options 386" ;;
-esac
-
-for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha sm2 sm3 sm4
-do
- if [ ! -d $THERE/crypto/$i ]
- then
- options="$options no-$i"
- fi
-done
-
-if [ -z "$OUT" ]; then
- OUT="$CC"
-fi
-
-if [ ".$PERL" = . ] ; then
- for i in . `echo $PATH | sed 's/:/ /g'`; do
- if [ -f "$i/perl5$EXE" ] ; then
- PERL="$i/perl5$EXE"
- break;
- fi;
- done
-fi
-
-if [ ".$PERL" = . ] ; then
- for i in . `echo $PATH | sed 's/:/ /g'`; do
- if [ -f "$i/perl$EXE" ] ; then
- if "$i/perl$EXE" -e 'exit($]<5.0)'; then
- PERL="$i/perl$EXE"
- break;
- fi;
- fi;
- done
-fi
-
-if [ ".$PERL" = . ] ; then
- echo "You need Perl 5."
- exit 1
-fi
-
-# run Configure to check to see if we need to specify the
-# compiler for the platform ... in which case we add it on
-# the end ... otherwise we leave it off
-
-$PERL $THERE/Configure LIST | grep "$OUT-$CC" > /dev/null
-if [ $? = "0" ]; then
- OUT="$OUT-$CC"
-fi
-
-OUT="$OUT"
-
-if [ "$OUT" = "darwin64-x86_64-cc" ]; then
- echo "WARNING! If you wish to build 32-bit libraries, then you have to"
- echo " invoke 'KERNEL_BITS=32 $THERE/config $options'."
-fi
-
-if $PERL $THERE/Configure LIST | grep "$OUT" > /dev/null; then
- if [ "$VERBOSE" = "true" ]; then
- echo /usr/bin/env \
- __CNF_CPPDEFINES="'$__CNF_CPPDEFINES'" \
- __CNF_CPPINCLUDES="'$__CNF_CPPINCLUDES'" \
- __CNF_CPPFLAGS="'$__CNF_CPPFLAGS'" \
- __CNF_CFLAGS="'$__CNF_CFLAGS'" \
- __CNF_CXXFLAGS="'$__CNF_CXXFLAGS'" \
- __CNF_LDFLAGS="'$__CNF_LDFLAGS'" \
- __CNF_LDLIBS="'$__CNF_LDLIBS'" \
- $PERL $THERE/Configure $OUT $options
- fi
- if [ "$DRYRUN" = "false" ]; then
- # eval to make sure quoted options, possibly with spaces inside,
- # are treated right
- eval /usr/bin/env \
- __CNF_CPPDEFINES="'$__CNF_CPPDEFINES'" \
- __CNF_CPPINCLUDES="'$__CNF_CPPINCLUDES'" \
- __CNF_CPPFLAGS="'$__CNF_CPPFLAGS'" \
- __CNF_CFLAGS="'$__CNF_CFLAGS'" \
- __CNF_CXXFLAGS="'$__CNF_CXXFLAGS'" \
- __CNF_LDFLAGS="'$__CNF_LDFLAGS'" \
- __CNF_LDLIBS="'$__CNF_LDLIBS'" \
- $PERL $THERE/Configure $OUT $options
- fi
-else
- echo "This system ($OUT) is not supported. See file INSTALL for details."
- exit 1
-fi
-
-# Do not add anothing from here on, so we don't lose the Configure exit code
-)
+exec "$THERE/Configure" "$@"
diff --git a/configdata.pm.in b/configdata.pm.in
new file mode 100644
index 000000000000..04b901144f47
--- /dev/null
+++ b/configdata.pm.in
@@ -0,0 +1,487 @@
+#! {- $config{HASHBANGPERL} -}
+# -*- mode: perl -*-
+{-
+ # We must make sourcedir() return an absolute path, because configdata.pm
+ # may be loaded as a module from any script in any directory, making
+ # relative paths untrustable. Because the result is used with 'use lib',
+ # we must ensure that it returns a Unix style path. Mixing File::Spec
+ # and File::Spec::Unix does just that.
+ use File::Spec::Unix;
+ use File::Spec;
+ use Cwd qw(abs_path);
+ sub _fixup_path {
+ my $path = shift;
+
+ # Make the path absolute at all times
+ $path = abs_path($path);
+
+ if ($^O eq 'VMS') {
+ # Convert any path of the VMS form VOLUME:[DIR1.DIR2]FILE to the
+ # Unix form /VOLUME/DIR1/DIR2/FILE, which is what VMS perl supports
+ # for 'use lib'.
+
+ # Start with spliting the native path
+ (my $vol, my $dirs, my $file) = File::Spec->splitpath($path);
+ my @dirs = File::Spec->splitdir($dirs);
+
+ # Reassemble it as a Unix path
+ $vol =~ s|:$||;
+ $dirs = File::Spec::Unix->catdir('', $vol, @dirs);
+ $path = File::Spec::Unix->catpath('', $dirs, $file);
+ }
+
+ return $path;
+ }
+ sub sourcedir {
+ return _fixup_path(File::Spec->catdir($config{sourcedir}, @_))
+ }
+ sub sourcefile {
+ return _fixup_path(File::Spec->catfile($config{sourcedir}, @_))
+ }
+ use lib sourcedir('util', 'perl');
+ use OpenSSL::Util;
+-}
+package configdata;
+
+use strict;
+use warnings;
+
+use Exporter;
+our @ISA = qw(Exporter);
+our @EXPORT = qw(
+ %config %target %disabled %withargs %unified_info
+ @disablables @disablables_int
+);
+
+our %config = ({- dump_data(\%config, indent => 0); -});
+our %target = ({- dump_data(\%target, indent => 0); -});
+our @disablables = ({- dump_data(\@disablables, indent => 0) -});
+our @disablables_int = ({- dump_data(\@disablables_int, indent => 0) -});
+our %disabled = ({- dump_data(\%disabled, indent => 0); -});
+our %withargs = ({- dump_data(\%withargs, indent => 0); -});
+our %unified_info = ({- dump_data(\%unified_info, indent => 0); -});
+
+# Unexported, only used by OpenSSL::Test::Utils::available_protocols()
+our %available_protocols = (
+ tls => [{- dump_data(\@tls, indent => 0) -}],
+ dtls => [{- dump_data(\@dtls, indent => 0) -}],
+);
+
+# The following data is only used when this files is use as a script
+my @makevars = ({- dump_data(\@makevars, indent => 0); -});
+my %disabled_info = ({- dump_data(\%disabled_info, indent => 0); -});
+my @user_crossable = qw( {- join (' ', @user_crossable) -} );
+
+# If run directly, we can give some answers, and even reconfigure
+unless (caller) {
+ use Getopt::Long;
+ use File::Spec::Functions;
+ use File::Basename;
+ use File::Compare qw(compare_text);
+ use File::Copy;
+ use Pod::Usage;
+
+ use lib '{- sourcedir('util', 'perl') -}';
+ use OpenSSL::fallback '{- sourcefile('external', 'perl', 'MODULES.txt') -}';
+
+ my $here = dirname($0);
+
+ if (scalar @ARGV == 0) {
+ # With no arguments, re-create the build file
+ # We do that in two steps, where the first step emits perl
+ # snipets.
+
+ my $buildfile = $config{build_file};
+ my $buildfile_template = "$buildfile.in";
+ my @autowarntext = (
+ 'WARNING: do not edit!',
+ "Generated by configdata.pm from "
+ .join(", ", @{$config{build_file_templates}}),
+ "via $buildfile_template"
+ );
+ my %gendata = (
+ config => \%config,
+ target => \%target,
+ disabled => \%disabled,
+ withargs => \%withargs,
+ unified_info => \%unified_info,
+ autowarntext => \@autowarntext,
+ );
+
+ use lib '.';
+ use lib '{- sourcedir('Configurations') -}';
+ use gentemplate;
+
+ open my $buildfile_template_fh, ">$buildfile_template"
+ or die "Trying to create $buildfile_template: $!";
+ foreach (@{$config{build_file_templates}}) {
+ copy($_, $buildfile_template_fh)
+ or die "Trying to copy $_ into $buildfile_template: $!";
+ }
+ gentemplate(output => $buildfile_template_fh, %gendata);
+ close $buildfile_template_fh;
+ print 'Created ',$buildfile_template,"\n";
+
+ use OpenSSL::Template;
+
+ my $prepend = <<'_____';
+use File::Spec::Functions;
+use lib '{- sourcedir('util', 'perl') -}';
+use lib '{- sourcedir('Configurations') -}';
+use lib '{- $config{builddir} -}';
+use platform;
+_____
+
+ my $tmpl;
+ open BUILDFILE, ">$buildfile.new"
+ or die "Trying to create $buildfile.new: $!";
+ $tmpl = OpenSSL::Template->new(TYPE => 'FILE',
+ SOURCE => $buildfile_template);
+ $tmpl->fill_in(FILENAME => $_,
+ OUTPUT => \*BUILDFILE,
+ HASH => \%gendata,
+ PREPEND => $prepend,
+ # To ensure that global variables and functions
+ # defined in one template stick around for the
+ # next, making them combinable
+ PACKAGE => 'OpenSSL::safe')
+ or die $Text::Template::ERROR;
+ close BUILDFILE;
+ rename("$buildfile.new", $buildfile)
+ or die "Trying to rename $buildfile.new to $buildfile: $!";
+ print 'Created ',$buildfile,"\n";
+
+ my $configuration_h =
+ catfile('include', 'openssl', 'configuration.h');
+ my $configuration_h_in =
+ catfile($config{sourcedir}, 'include', 'openssl', 'configuration.h.in');
+ open CONFIGURATION_H, ">${configuration_h}.new"
+ or die "Trying to create ${configuration_h}.new: $!";
+ $tmpl = OpenSSL::Template->new(TYPE => 'FILE',
+ SOURCE => $configuration_h_in);
+ $tmpl->fill_in(FILENAME => $_,
+ OUTPUT => \*CONFIGURATION_H,
+ HASH => \%gendata,
+ PREPEND => $prepend,
+ # To ensure that global variables and functions
+ # defined in one template stick around for the
+ # next, making them combinable
+ PACKAGE => 'OpenSSL::safe')
+ or die $Text::Template::ERROR;
+ close CONFIGURATION_H;
+
+ # When using stat() on Windows, we can get it to perform better by
+ # avoid some data. This doesn't affect the mtime field, so we're not
+ # losing anything...
+ ${^WIN32_SLOPPY_STAT} = 1;
+
+ my $update_configuration_h = 0;
+ if (-f $configuration_h) {
+ my $configuration_h_mtime = (stat($configuration_h))[9];
+ my $configuration_h_in_mtime = (stat($configuration_h_in))[9];
+
+ # If configuration.h.in was updated after the last configuration.h,
+ # or if configuration.h.new differs configuration.h, we update
+ # configuration.h
+ if ($configuration_h_mtime < $configuration_h_in_mtime
+ || compare_text("${configuration_h}.new", $configuration_h) != 0) {
+ $update_configuration_h = 1;
+ } else {
+ # If nothing has changed, let's just drop the new one and
+ # pretend like nothing happened
+ unlink "${configuration_h}.new"
+ }
+ } else {
+ $update_configuration_h = 1;
+ }
+
+ if ($update_configuration_h) {
+ rename("${configuration_h}.new", $configuration_h)
+ or die "Trying to rename ${configuration_h}.new to $configuration_h: $!";
+ print 'Created ',$configuration_h,"\n";
+ }
+
+ exit(0);
+ }
+
+ my $dump = undef;
+ my $cmdline = undef;
+ my $options = undef;
+ my $target = undef;
+ my $envvars = undef;
+ my $makevars = undef;
+ my $buildparams = undef;
+ my $reconf = undef;
+ my $verbose = undef;
+ my $query = undef;
+ my $help = undef;
+ my $man = undef;
+ GetOptions('dump|d' => \$dump,
+ 'command-line|c' => \$cmdline,
+ 'options|o' => \$options,
+ 'target|t' => \$target,
+ 'environment|e' => \$envvars,
+ 'make-variables|m' => \$makevars,
+ 'build-parameters|b' => \$buildparams,
+ 'reconfigure|reconf|r' => \$reconf,
+ 'verbose|v' => \$verbose,
+ 'query|q=s' => \$query,
+ 'help' => \$help,
+ 'man' => \$man)
+ or die "Errors in command line arguments\n";
+
+ # We allow extra arguments with --query. That allows constructs like
+ # this:
+ # ./configdata.pm --query 'get_sources(@ARGV)' file1 file2 file3
+ if (!$query && scalar @ARGV > 0) {
+ print STDERR <<"_____";
+Unrecognised arguments.
+For more information, do '$0 --help'
+_____
+ exit(2);
+ }
+
+ if ($help) {
+ pod2usage(-exitval => 0,
+ -verbose => 1);
+ }
+ if ($man) {
+ pod2usage(-exitval => 0,
+ -verbose => 2);
+ }
+ if ($dump || $cmdline) {
+ print "\nCommand line (with current working directory = $here):\n\n";
+ print ' ',join(' ',
+ $config{PERL},
+ catfile($config{sourcedir}, 'Configure'),
+ @{$config{perlargv}}), "\n";
+ print "\nPerl information:\n\n";
+ print ' ',$config{perl_cmd},"\n";
+ print ' ',$config{perl_version},' for ',$config{perl_archname},"\n";
+ }
+ if ($dump || $options) {
+ my $longest = 0;
+ my $longest2 = 0;
+ foreach my $what (@disablables) {
+ $longest = length($what) if $longest < length($what);
+ $longest2 = length($disabled{$what})
+ if $disabled{$what} && $longest2 < length($disabled{$what});
+ }
+ print "\nEnabled features:\n\n";
+ foreach my $what (@disablables) {
+ print " $what\n" unless $disabled{$what};
+ }
+ print "\nDisabled features:\n\n";
+ foreach my $what (@disablables) {
+ if ($disabled{$what}) {
+ print " $what", ' ' x ($longest - length($what) + 1),
+ "[$disabled{$what}]", ' ' x ($longest2 - length($disabled{$what}) + 1);
+ print $disabled_info{$what}->{macro}
+ if $disabled_info{$what}->{macro};
+ print ' (skip ',
+ join(', ', @{$disabled_info{$what}->{skipped}}),
+ ')'
+ if $disabled_info{$what}->{skipped};
+ print "\n";
+ }
+ }
+ }
+ if ($dump || $target) {
+ print "\nConfig target attributes:\n\n";
+ foreach (sort keys %target) {
+ next if $_ =~ m|^_| || $_ eq 'template';
+ my $quotify = sub {
+ map {
+ if (defined $_) {
+ (my $x = $_) =~ s|([\\\$\@"])|\\$1|g; "\"$x\""
+ } else {
+ "undef";
+ }
+ } @_;
+ };
+ print ' ', $_, ' => ';
+ if (ref($target{$_}) eq "ARRAY") {
+ print '[ ', join(', ', $quotify->(@{$target{$_}})), " ],\n";
+ } else {
+ print $quotify->($target{$_}), ",\n"
+ }
+ }
+ }
+ if ($dump || $envvars) {
+ print "\nRecorded environment:\n\n";
+ foreach (sort keys %{$config{perlenv}}) {
+ print ' ',$_,' = ',($config{perlenv}->{$_} || ''),"\n";
+ }
+ }
+ if ($dump || $makevars) {
+ print "\nMakevars:\n\n";
+ foreach my $var (@makevars) {
+ my $prefix = '';
+ $prefix = $config{CROSS_COMPILE}
+ if grep { $var eq $_ } @user_crossable;
+ $prefix //= '';
+ print ' ',$var,' ' x (16 - length $var),'= ',
+ (ref $config{$var} eq 'ARRAY'
+ ? join(' ', @{$config{$var}})
+ : $prefix.$config{$var}),
+ "\n"
+ if defined $config{$var};
+ }
+
+ my @buildfile = ($config{builddir}, $config{build_file});
+ unshift @buildfile, $here
+ unless file_name_is_absolute($config{builddir});
+ my $buildfile = canonpath(catdir(@buildfile));
+ print <<"_____";
+
+NOTE: These variables only represent the configuration view. The build file
+template may have processed these variables further, please have a look at the
+build file for more exact data:
+ $buildfile
+_____
+ }
+ if ($dump || $buildparams) {
+ my @buildfile = ($config{builddir}, $config{build_file});
+ unshift @buildfile, $here
+ unless file_name_is_absolute($config{builddir});
+ print "\nbuild file:\n\n";
+ print " ", canonpath(catfile(@buildfile)),"\n";
+
+ print "\nbuild file templates:\n\n";
+ foreach (@{$config{build_file_templates}}) {
+ my @tmpl = ($_);
+ unshift @tmpl, $here
+ unless file_name_is_absolute($config{sourcedir});
+ print ' ',canonpath(catfile(@tmpl)),"\n";
+ }
+ }
+ if ($reconf) {
+ if ($verbose) {
+ print 'Reconfiguring with: ', join(' ',@{$config{perlargv}}), "\n";
+ foreach (sort keys %{$config{perlenv}}) {
+ print ' ',$_,' = ',($config{perlenv}->{$_} || ""),"\n";
+ }
+ }
+
+ chdir $here;
+ exec $^X,catfile($config{sourcedir}, 'Configure'),'reconf';
+ }
+ if ($query) {
+ use OpenSSL::Config::Query;
+
+ my $confquery = OpenSSL::Config::Query->new(info => \%unified_info,
+ config => \%config);
+ my $result = eval "\$confquery->$query";
+
+ # We may need a result class with a printing function at some point.
+ # Until then, we assume that we get a scalar, or a list or a hash table
+ # with scalar values and simply print them in some orderly fashion.
+ if (ref $result eq 'ARRAY') {
+ print "$_\n" foreach @$result;
+ } elsif (ref $result eq 'HASH') {
+ print "$_ : \\\n ", join(" \\\n ", @{$result->{$_}}), "\n"
+ foreach sort keys %$result;
+ } elsif (ref $result eq 'SCALAR') {
+ print "$$result\n";
+ }
+ }
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+configdata.pm - configuration data for OpenSSL builds
+
+=head1 SYNOPSIS
+
+Interactive:
+
+ perl configdata.pm [options]
+
+As data bank module:
+
+ use configdata;
+
+=head1 DESCRIPTION
+
+This module can be used in two modes, interactively and as a module containing
+all the data recorded by OpenSSL's Configure script.
+
+When used interactively, simply run it as any perl script.
+If run with no arguments, it will rebuild the build file (Makefile or
+corresponding).
+With at least one option, it will instead get the information you ask for, or
+re-run the configuration process.
+See L</OPTIONS> below for more information.
+
+When loaded as a module, you get a few databanks with useful information to
+perform build related tasks. The databanks are:
+
+ %config Configured things.
+ %target The OpenSSL config target with all inheritances
+ resolved.
+ %disabled The features that are disabled.
+ @disablables The list of features that can be disabled.
+ %withargs All data given through --with-THING options.
+ %unified_info All information that was computed from the build.info
+ files.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--help>
+
+Print a brief help message and exit.
+
+=item B<--man>
+
+Print the manual page and exit.
+
+=item B<--dump> | B<-d>
+
+Print all relevant configuration data. This is equivalent to B<--command-line>
+B<--options> B<--target> B<--environment> B<--make-variables>
+B<--build-parameters>.
+
+=item B<--command-line> | B<-c>
+
+Print the current configuration command line.
+
+=item B<--options> | B<-o>
+
+Print the features, both enabled and disabled, and display defined macro and
+skipped directories where applicable.
+
+=item B<--target> | B<-t>
+
+Print the config attributes for this config target.
+
+=item B<--environment> | B<-e>
+
+Print the environment variables and their values at the time of configuration.
+
+=item B<--make-variables> | B<-m>
+
+Print the main make variables generated in the current configuration
+
+=item B<--build-parameters> | B<-b>
+
+Print the build parameters, i.e. build file and build file templates.
+
+=item B<--reconfigure> | B<--reconf> | B<-r>
+
+Re-run the configuration process.
+
+=item B<--verbose> | B<-v>
+
+Verbose output.
+
+=back
+
+=cut
+
+EOF
diff --git a/crypto/LPdir_unix.c b/crypto/LPdir_unix.c
index bbbec0aee138..bc0e924e46a7 100644
--- a/crypto/LPdir_unix.c
+++ b/crypto/LPdir_unix.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -141,7 +141,8 @@ const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory)
p--;
if (p > (*ctx)->entry_name && p[-1] == ';')
p[-1] = '\0';
- if (strcasecmp((*ctx)->entry_name, (*ctx)->previous_entry_name) == 0)
+ if (OPENSSL_strcasecmp((*ctx)->entry_name,
+ (*ctx)->previous_entry_name) == 0)
goto again;
}
#endif
diff --git a/crypto/README-sparse_array.md b/crypto/README-sparse_array.md
new file mode 100644
index 000000000000..bc2ff0cb8aee
--- /dev/null
+++ b/crypto/README-sparse_array.md
@@ -0,0 +1,156 @@
+Sparse Arrays
+=============
+
+The `sparse_array.c` file contains an implementation of a sparse array that
+attempts to be both space and time efficient.
+
+The sparse array is represented using a tree structure. Each node in the
+tree contains a block of pointers to either the user supplied leaf values or
+to another node.
+
+There are a number of parameters used to define the block size:
+
+ OPENSSL_SA_BLOCK_BITS Specifies the number of bits covered by each block
+ SA_BLOCK_MAX Specifies the number of pointers in each block
+ SA_BLOCK_MASK Specifies a bit mask to perform modulo block size
+ SA_BLOCK_MAX_LEVELS Indicates the maximum possible height of the tree
+
+These constants are inter-related:
+
+ SA_BLOCK_MAX = 2 ^ OPENSSL_SA_BLOCK_BITS
+ SA_BLOCK_MASK = SA_BLOCK_MAX - 1
+ SA_BLOCK_MAX_LEVELS = number of bits in size_t divided by
+ OPENSSL_SA_BLOCK_BITS rounded up to the next multiple
+ of OPENSSL_SA_BLOCK_BITS
+
+`OPENSSL_SA_BLOCK_BITS` can be defined at compile time and this overrides the
+built in setting.
+
+As a space and performance optimisation, the height of the tree is usually
+less than the maximum possible height. Only sufficient height is allocated to
+accommodate the largest index added to the data structure.
+
+The largest index used to add a value to the array determines the tree height:
+
+ +----------------------+---------------------+
+ | Largest Added Index | Height of Tree |
+ +----------------------+---------------------+
+ | SA_BLOCK_MAX - 1 | 1 |
+ | SA_BLOCK_MAX ^ 2 - 1 | 2 |
+ | SA_BLOCK_MAX ^ 3 - 1 | 3 |
+ | ... | ... |
+ | size_t max | SA_BLOCK_MAX_LEVELS |
+ +----------------------+---------------------+
+
+The tree height is dynamically increased as needed based on additions.
+
+An empty tree is represented by a NULL root pointer. Inserting a value at
+index 0 results in the allocation of a top level node full of null pointers
+except for the single pointer to the user's data (N = SA_BLOCK_MAX for
+brevity):
+
+ +----+
+ |Root|
+ |Node|
+ +-+--+
+ |
+ |
+ |
+ v
+ +-+-+---+---+---+---+
+ | 0 | 1 | 2 |...|N-1|
+ | |nil|nil|...|nil|
+ +-+-+---+---+---+---+
+ |
+ |
+ |
+ v
+ +-+--+
+ |User|
+ |Data|
+ +----+
+ Index 0
+
+Inserting at element 2N+1 creates a new root node and pushes down the old root
+node. It then creates a second second level node to hold the pointer to the
+user's new data:
+
+ +----+
+ |Root|
+ |Node|
+ +-+--+
+ |
+ |
+ |
+ v
+ +-+-+---+---+---+---+
+ | 0 | 1 | 2 |...|N-1|
+ | |nil| |...|nil|
+ +-+-+---+-+-+---+---+
+ | |
+ | +------------------+
+ | |
+ v v
+ +-+-+---+---+---+---+ +-+-+---+---+---+---+
+ | 0 | 1 | 2 |...|N-1| | 0 | 1 | 2 |...|N-1|
+ |nil| |nil|...|nil| |nil| |nil|...|nil|
+ +-+-+---+---+---+---+ +---+-+-+---+---+---+
+ | |
+ | |
+ | |
+ v v
+ +-+--+ +-+--+
+ |User| |User|
+ |Data| |Data|
+ +----+ +----+
+ Index 0 Index 2N+1
+
+The nodes themselves are allocated in a sparse manner. Only nodes which exist
+along a path from the root of the tree to an added leaf will be allocated.
+The complexity is hidden and nodes are allocated on an as needed basis.
+Because the data is expected to be sparse this doesn't result in a large waste
+of space.
+
+Values can be removed from the sparse array by setting their index position to
+NULL. The data structure does not attempt to reclaim nodes or reduce the
+height of the tree on removal. For example, now setting index 0 to NULL would
+result in:
+
+ +----+
+ |Root|
+ |Node|
+ +-+--+
+ |
+ |
+ |
+ v
+ +-+-+---+---+---+---+
+ | 0 | 1 | 2 |...|N-1|
+ | |nil| |...|nil|
+ +-+-+---+-+-+---+---+
+ | |
+ | +------------------+
+ | |
+ v v
+ +-+-+---+---+---+---+ +-+-+---+---+---+---+
+ | 0 | 1 | 2 |...|N-1| | 0 | 1 | 2 |...|N-1|
+ |nil|nil|nil|...|nil| |nil| |nil|...|nil|
+ +---+---+---+---+---+ +---+-+-+---+---+---+
+ |
+ |
+ |
+ v
+ +-+--+
+ |User|
+ |Data|
+ +----+
+ Index 2N+1
+
+Accesses to elements in the sparse array take O(log n) time where n is the
+largest element. The base of the logarithm is `SA_BLOCK_MAX`, so for moderately
+small indices (e.g. NIDs), single level (constant time) access is achievable.
+Space usage is O(minimum(m, n log(n)) where m is the number of elements in the
+array.
+
+Note: sparse arrays only include pointers to types.
+Thus, `SPARSE_ARRAY_OF(char)` can be used to store a string.
diff --git a/crypto/aes/aes_cbc.c b/crypto/aes/aes_cbc.c
index 342841fc4ff7..f2d5381b86d7 100644
--- a/crypto/aes/aes_cbc.c
+++ b/crypto/aes/aes_cbc.c
@@ -1,12 +1,19 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * AES low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/aes.h>
#include <openssl/modes.h>
diff --git a/crypto/aes/aes_cfb.c b/crypto/aes/aes_cfb.c
index f010e3c4ea9e..e5fcbb87f609 100644
--- a/crypto/aes/aes_cfb.c
+++ b/crypto/aes/aes_cfb.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * AES_encrypt is deprecated - but we need to use it to implement these other
+ * deprecated APIs.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/aes.h>
#include <openssl/modes.h>
diff --git a/crypto/aes/aes_core.c b/crypto/aes/aes_core.c
index ad00c729e700..3413ce8f4378 100644
--- a/crypto/aes/aes_core.c
+++ b/crypto/aes/aes_core.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -36,6 +36,13 @@
/* Note: rewritten a little bit to provide error control and an OpenSSL-
compatible API */
+/*
+ * AES low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
#include <assert.h>
#include <stdlib.h>
@@ -44,6 +51,15 @@
#include "aes_local.h"
#if defined(OPENSSL_AES_CONST_TIME) && !defined(AES_ASM)
+
+# if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
+# define U64(C) C##UI64
+# elif defined(__arch64__)
+# define U64(C) C##UL
+# else
+# define U64(C) C##ULL
+# endif
+
typedef union {
unsigned char b[8];
u32 w[2];
@@ -72,10 +88,10 @@ static void XtimeLong(u64 *w)
u64 a, b;
a = *w;
- b = a & 0x8080808080808080uLL;
+ b = a & U64(0x8080808080808080);
a ^= b;
b -= b >> 7;
- b &= 0x1B1B1B1B1B1B1B1BuLL;
+ b &= U64(0x1B1B1B1B1B1B1B1B);
b ^= a << 1;
*w = b;
}
@@ -222,89 +238,89 @@ static void SubLong(u64 *w)
u64 x, y, a1, a2, a3, a4, a5, a6;
x = *w;
- y = ((x & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((x & 0x0101010101010101uLL) << 7);
- x &= 0xDDDDDDDDDDDDDDDDuLL;
- x ^= y & 0x5757575757575757uLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0x1C1C1C1C1C1C1C1CuLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0x4A4A4A4A4A4A4A4AuLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0x4242424242424242uLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0x6464646464646464uLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0xE0E0E0E0E0E0E0E0uLL;
+ y = ((x & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((x & U64(0x0101010101010101)) << 7);
+ x &= U64(0xDDDDDDDDDDDDDDDD);
+ x ^= y & U64(0x5757575757575757);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0x1C1C1C1C1C1C1C1C);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0x4A4A4A4A4A4A4A4A);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0x4242424242424242);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0x6464646464646464);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0xE0E0E0E0E0E0E0E0);
a1 = x;
- a1 ^= (x & 0xF0F0F0F0F0F0F0F0uLL) >> 4;
- a2 = ((x & 0xCCCCCCCCCCCCCCCCuLL) >> 2) | ((x & 0x3333333333333333uLL) << 2);
+ a1 ^= (x & U64(0xF0F0F0F0F0F0F0F0)) >> 4;
+ a2 = ((x & U64(0xCCCCCCCCCCCCCCCC)) >> 2) | ((x & U64(0x3333333333333333)) << 2);
a3 = x & a1;
- a3 ^= (a3 & 0xAAAAAAAAAAAAAAAAuLL) >> 1;
- a3 ^= (((x << 1) & a1) ^ ((a1 << 1) & x)) & 0xAAAAAAAAAAAAAAAAuLL;
+ a3 ^= (a3 & U64(0xAAAAAAAAAAAAAAAA)) >> 1;
+ a3 ^= (((x << 1) & a1) ^ ((a1 << 1) & x)) & U64(0xAAAAAAAAAAAAAAAA);
a4 = a2 & a1;
- a4 ^= (a4 & 0xAAAAAAAAAAAAAAAAuLL) >> 1;
- a4 ^= (((a2 << 1) & a1) ^ ((a1 << 1) & a2)) & 0xAAAAAAAAAAAAAAAAuLL;
- a5 = (a3 & 0xCCCCCCCCCCCCCCCCuLL) >> 2;
- a3 ^= ((a4 << 2) ^ a4) & 0xCCCCCCCCCCCCCCCCuLL;
- a4 = a5 & 0x2222222222222222uLL;
+ a4 ^= (a4 & U64(0xAAAAAAAAAAAAAAAA)) >> 1;
+ a4 ^= (((a2 << 1) & a1) ^ ((a1 << 1) & a2)) & U64(0xAAAAAAAAAAAAAAAA);
+ a5 = (a3 & U64(0xCCCCCCCCCCCCCCCC)) >> 2;
+ a3 ^= ((a4 << 2) ^ a4) & U64(0xCCCCCCCCCCCCCCCC);
+ a4 = a5 & U64(0x2222222222222222);
a4 |= a4 >> 1;
- a4 ^= (a5 << 1) & 0x2222222222222222uLL;
+ a4 ^= (a5 << 1) & U64(0x2222222222222222);
a3 ^= a4;
- a5 = a3 & 0xA0A0A0A0A0A0A0A0uLL;
+ a5 = a3 & U64(0xA0A0A0A0A0A0A0A0);
a5 |= a5 >> 1;
- a5 ^= (a3 << 1) & 0xA0A0A0A0A0A0A0A0uLL;
- a4 = a5 & 0xC0C0C0C0C0C0C0C0uLL;
+ a5 ^= (a3 << 1) & U64(0xA0A0A0A0A0A0A0A0);
+ a4 = a5 & U64(0xC0C0C0C0C0C0C0C0);
a6 = a4 >> 2;
- a4 ^= (a5 << 2) & 0xC0C0C0C0C0C0C0C0uLL;
- a5 = a6 & 0x2020202020202020uLL;
+ a4 ^= (a5 << 2) & U64(0xC0C0C0C0C0C0C0C0);
+ a5 = a6 & U64(0x2020202020202020);
a5 |= a5 >> 1;
- a5 ^= (a6 << 1) & 0x2020202020202020uLL;
+ a5 ^= (a6 << 1) & U64(0x2020202020202020);
a4 |= a5;
a3 ^= a4 >> 4;
- a3 &= 0x0F0F0F0F0F0F0F0FuLL;
+ a3 &= U64(0x0F0F0F0F0F0F0F0F);
a2 = a3;
- a2 ^= (a3 & 0x0C0C0C0C0C0C0C0CuLL) >> 2;
+ a2 ^= (a3 & U64(0x0C0C0C0C0C0C0C0C)) >> 2;
a4 = a3 & a2;
- a4 ^= (a4 & 0x0A0A0A0A0A0A0A0AuLL) >> 1;
- a4 ^= (((a3 << 1) & a2) ^ ((a2 << 1) & a3)) & 0x0A0A0A0A0A0A0A0AuLL;
- a5 = a4 & 0x0808080808080808uLL;
+ a4 ^= (a4 & U64(0x0A0A0A0A0A0A0A0A)) >> 1;
+ a4 ^= (((a3 << 1) & a2) ^ ((a2 << 1) & a3)) & U64(0x0A0A0A0A0A0A0A0A);
+ a5 = a4 & U64(0x0808080808080808);
a5 |= a5 >> 1;
- a5 ^= (a4 << 1) & 0x0808080808080808uLL;
+ a5 ^= (a4 << 1) & U64(0x0808080808080808);
a4 ^= a5 >> 2;
- a4 &= 0x0303030303030303uLL;
- a4 ^= (a4 & 0x0202020202020202uLL) >> 1;
+ a4 &= U64(0x0303030303030303);
+ a4 ^= (a4 & U64(0x0202020202020202)) >> 1;
a4 |= a4 << 2;
a3 = a2 & a4;
- a3 ^= (a3 & 0x0A0A0A0A0A0A0A0AuLL) >> 1;
- a3 ^= (((a2 << 1) & a4) ^ ((a4 << 1) & a2)) & 0x0A0A0A0A0A0A0A0AuLL;
+ a3 ^= (a3 & U64(0x0A0A0A0A0A0A0A0A)) >> 1;
+ a3 ^= (((a2 << 1) & a4) ^ ((a4 << 1) & a2)) & U64(0x0A0A0A0A0A0A0A0A);
a3 |= a3 << 4;
- a2 = ((a1 & 0xCCCCCCCCCCCCCCCCuLL) >> 2) | ((a1 & 0x3333333333333333uLL) << 2);
+ a2 = ((a1 & U64(0xCCCCCCCCCCCCCCCC)) >> 2) | ((a1 & U64(0x3333333333333333)) << 2);
x = a1 & a3;
- x ^= (x & 0xAAAAAAAAAAAAAAAAuLL) >> 1;
- x ^= (((a1 << 1) & a3) ^ ((a3 << 1) & a1)) & 0xAAAAAAAAAAAAAAAAuLL;
+ x ^= (x & U64(0xAAAAAAAAAAAAAAAA)) >> 1;
+ x ^= (((a1 << 1) & a3) ^ ((a3 << 1) & a1)) & U64(0xAAAAAAAAAAAAAAAA);
a4 = a2 & a3;
- a4 ^= (a4 & 0xAAAAAAAAAAAAAAAAuLL) >> 1;
- a4 ^= (((a2 << 1) & a3) ^ ((a3 << 1) & a2)) & 0xAAAAAAAAAAAAAAAAuLL;
- a5 = (x & 0xCCCCCCCCCCCCCCCCuLL) >> 2;
- x ^= ((a4 << 2) ^ a4) & 0xCCCCCCCCCCCCCCCCuLL;
- a4 = a5 & 0x2222222222222222uLL;
+ a4 ^= (a4 & U64(0xAAAAAAAAAAAAAAAA)) >> 1;
+ a4 ^= (((a2 << 1) & a3) ^ ((a3 << 1) & a2)) & U64(0xAAAAAAAAAAAAAAAA);
+ a5 = (x & U64(0xCCCCCCCCCCCCCCCC)) >> 2;
+ x ^= ((a4 << 2) ^ a4) & U64(0xCCCCCCCCCCCCCCCC);
+ a4 = a5 & U64(0x2222222222222222);
a4 |= a4 >> 1;
- a4 ^= (a5 << 1) & 0x2222222222222222uLL;
+ a4 ^= (a5 << 1) & U64(0x2222222222222222);
x ^= a4;
- y = ((x & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((x & 0x0101010101010101uLL) << 7);
- x &= 0x3939393939393939uLL;
- x ^= y & 0x3F3F3F3F3F3F3F3FuLL;
- y = ((y & 0xFCFCFCFCFCFCFCFCuLL) >> 2) | ((y & 0x0303030303030303uLL) << 6);
- x ^= y & 0x9797979797979797uLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0x9B9B9B9B9B9B9B9BuLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0x3C3C3C3C3C3C3C3CuLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0xDDDDDDDDDDDDDDDDuLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0x7272727272727272uLL;
- x ^= 0x6363636363636363uLL;
+ y = ((x & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((x & U64(0x0101010101010101)) << 7);
+ x &= U64(0x3939393939393939);
+ x ^= y & U64(0x3F3F3F3F3F3F3F3F);
+ y = ((y & U64(0xFCFCFCFCFCFCFCFC)) >> 2) | ((y & U64(0x0303030303030303)) << 6);
+ x ^= y & U64(0x9797979797979797);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0x9B9B9B9B9B9B9B9B);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0x3C3C3C3C3C3C3C3C);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0xDDDDDDDDDDDDDDDD);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0x7272727272727272);
+ x ^= U64(0x6363636363636363);
*w = x;
}
@@ -316,93 +332,93 @@ static void InvSubLong(u64 *w)
u64 x, y, a1, a2, a3, a4, a5, a6;
x = *w;
- x ^= 0x6363636363636363uLL;
- y = ((x & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((x & 0x0101010101010101uLL) << 7);
- x &= 0xFDFDFDFDFDFDFDFDuLL;
- x ^= y & 0x5E5E5E5E5E5E5E5EuLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0xF3F3F3F3F3F3F3F3uLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0xF5F5F5F5F5F5F5F5uLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0x7878787878787878uLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0x7777777777777777uLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0x1515151515151515uLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0xA5A5A5A5A5A5A5A5uLL;
+ x ^= U64(0x6363636363636363);
+ y = ((x & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((x & U64(0x0101010101010101)) << 7);
+ x &= U64(0xFDFDFDFDFDFDFDFD);
+ x ^= y & U64(0x5E5E5E5E5E5E5E5E);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0xF3F3F3F3F3F3F3F3);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0xF5F5F5F5F5F5F5F5);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0x7878787878787878);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0x7777777777777777);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0x1515151515151515);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0xA5A5A5A5A5A5A5A5);
a1 = x;
- a1 ^= (x & 0xF0F0F0F0F0F0F0F0uLL) >> 4;
- a2 = ((x & 0xCCCCCCCCCCCCCCCCuLL) >> 2) | ((x & 0x3333333333333333uLL) << 2);
+ a1 ^= (x & U64(0xF0F0F0F0F0F0F0F0)) >> 4;
+ a2 = ((x & U64(0xCCCCCCCCCCCCCCCC)) >> 2) | ((x & U64(0x3333333333333333)) << 2);
a3 = x & a1;
- a3 ^= (a3 & 0xAAAAAAAAAAAAAAAAuLL) >> 1;
- a3 ^= (((x << 1) & a1) ^ ((a1 << 1) & x)) & 0xAAAAAAAAAAAAAAAAuLL;
+ a3 ^= (a3 & U64(0xAAAAAAAAAAAAAAAA)) >> 1;
+ a3 ^= (((x << 1) & a1) ^ ((a1 << 1) & x)) & U64(0xAAAAAAAAAAAAAAAA);
a4 = a2 & a1;
- a4 ^= (a4 & 0xAAAAAAAAAAAAAAAAuLL) >> 1;
- a4 ^= (((a2 << 1) & a1) ^ ((a1 << 1) & a2)) & 0xAAAAAAAAAAAAAAAAuLL;
- a5 = (a3 & 0xCCCCCCCCCCCCCCCCuLL) >> 2;
- a3 ^= ((a4 << 2) ^ a4) & 0xCCCCCCCCCCCCCCCCuLL;
- a4 = a5 & 0x2222222222222222uLL;
+ a4 ^= (a4 & U64(0xAAAAAAAAAAAAAAAA)) >> 1;
+ a4 ^= (((a2 << 1) & a1) ^ ((a1 << 1) & a2)) & U64(0xAAAAAAAAAAAAAAAA);
+ a5 = (a3 & U64(0xCCCCCCCCCCCCCCCC)) >> 2;
+ a3 ^= ((a4 << 2) ^ a4) & U64(0xCCCCCCCCCCCCCCCC);
+ a4 = a5 & U64(0x2222222222222222);
a4 |= a4 >> 1;
- a4 ^= (a5 << 1) & 0x2222222222222222uLL;
+ a4 ^= (a5 << 1) & U64(0x2222222222222222);
a3 ^= a4;
- a5 = a3 & 0xA0A0A0A0A0A0A0A0uLL;
+ a5 = a3 & U64(0xA0A0A0A0A0A0A0A0);
a5 |= a5 >> 1;
- a5 ^= (a3 << 1) & 0xA0A0A0A0A0A0A0A0uLL;
- a4 = a5 & 0xC0C0C0C0C0C0C0C0uLL;
+ a5 ^= (a3 << 1) & U64(0xA0A0A0A0A0A0A0A0);
+ a4 = a5 & U64(0xC0C0C0C0C0C0C0C0);
a6 = a4 >> 2;
- a4 ^= (a5 << 2) & 0xC0C0C0C0C0C0C0C0uLL;
- a5 = a6 & 0x2020202020202020uLL;
+ a4 ^= (a5 << 2) & U64(0xC0C0C0C0C0C0C0C0);
+ a5 = a6 & U64(0x2020202020202020);
a5 |= a5 >> 1;
- a5 ^= (a6 << 1) & 0x2020202020202020uLL;
+ a5 ^= (a6 << 1) & U64(0x2020202020202020);
a4 |= a5;
a3 ^= a4 >> 4;
- a3 &= 0x0F0F0F0F0F0F0F0FuLL;
+ a3 &= U64(0x0F0F0F0F0F0F0F0F);
a2 = a3;
- a2 ^= (a3 & 0x0C0C0C0C0C0C0C0CuLL) >> 2;
+ a2 ^= (a3 & U64(0x0C0C0C0C0C0C0C0C)) >> 2;
a4 = a3 & a2;
- a4 ^= (a4 & 0x0A0A0A0A0A0A0A0AuLL) >> 1;
- a4 ^= (((a3 << 1) & a2) ^ ((a2 << 1) & a3)) & 0x0A0A0A0A0A0A0A0AuLL;
- a5 = a4 & 0x0808080808080808uLL;
+ a4 ^= (a4 & U64(0x0A0A0A0A0A0A0A0A)) >> 1;
+ a4 ^= (((a3 << 1) & a2) ^ ((a2 << 1) & a3)) & U64(0x0A0A0A0A0A0A0A0A);
+ a5 = a4 & U64(0x0808080808080808);
a5 |= a5 >> 1;
- a5 ^= (a4 << 1) & 0x0808080808080808uLL;
+ a5 ^= (a4 << 1) & U64(0x0808080808080808);
a4 ^= a5 >> 2;
- a4 &= 0x0303030303030303uLL;
- a4 ^= (a4 & 0x0202020202020202uLL) >> 1;
+ a4 &= U64(0x0303030303030303);
+ a4 ^= (a4 & U64(0x0202020202020202)) >> 1;
a4 |= a4 << 2;
a3 = a2 & a4;
- a3 ^= (a3 & 0x0A0A0A0A0A0A0A0AuLL) >> 1;
- a3 ^= (((a2 << 1) & a4) ^ ((a4 << 1) & a2)) & 0x0A0A0A0A0A0A0A0AuLL;
+ a3 ^= (a3 & U64(0x0A0A0A0A0A0A0A0A)) >> 1;
+ a3 ^= (((a2 << 1) & a4) ^ ((a4 << 1) & a2)) & U64(0x0A0A0A0A0A0A0A0A);
a3 |= a3 << 4;
- a2 = ((a1 & 0xCCCCCCCCCCCCCCCCuLL) >> 2) | ((a1 & 0x3333333333333333uLL) << 2);
+ a2 = ((a1 & U64(0xCCCCCCCCCCCCCCCC)) >> 2) | ((a1 & U64(0x3333333333333333)) << 2);
x = a1 & a3;
- x ^= (x & 0xAAAAAAAAAAAAAAAAuLL) >> 1;
- x ^= (((a1 << 1) & a3) ^ ((a3 << 1) & a1)) & 0xAAAAAAAAAAAAAAAAuLL;
+ x ^= (x & U64(0xAAAAAAAAAAAAAAAA)) >> 1;
+ x ^= (((a1 << 1) & a3) ^ ((a3 << 1) & a1)) & U64(0xAAAAAAAAAAAAAAAA);
a4 = a2 & a3;
- a4 ^= (a4 & 0xAAAAAAAAAAAAAAAAuLL) >> 1;
- a4 ^= (((a2 << 1) & a3) ^ ((a3 << 1) & a2)) & 0xAAAAAAAAAAAAAAAAuLL;
- a5 = (x & 0xCCCCCCCCCCCCCCCCuLL) >> 2;
- x ^= ((a4 << 2) ^ a4) & 0xCCCCCCCCCCCCCCCCuLL;
- a4 = a5 & 0x2222222222222222uLL;
+ a4 ^= (a4 & U64(0xAAAAAAAAAAAAAAAA)) >> 1;
+ a4 ^= (((a2 << 1) & a3) ^ ((a3 << 1) & a2)) & U64(0xAAAAAAAAAAAAAAAA);
+ a5 = (x & U64(0xCCCCCCCCCCCCCCCC)) >> 2;
+ x ^= ((a4 << 2) ^ a4) & U64(0xCCCCCCCCCCCCCCCC);
+ a4 = a5 & U64(0x2222222222222222);
a4 |= a4 >> 1;
- a4 ^= (a5 << 1) & 0x2222222222222222uLL;
+ a4 ^= (a5 << 1) & U64(0x2222222222222222);
x ^= a4;
- y = ((x & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((x & 0x0101010101010101uLL) << 7);
- x &= 0xB5B5B5B5B5B5B5B5uLL;
- x ^= y & 0x4040404040404040uLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0x8080808080808080uLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0x1616161616161616uLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0xEBEBEBEBEBEBEBEBuLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0x9797979797979797uLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0xFBFBFBFBFBFBFBFBuLL;
- y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
- x ^= y & 0x7D7D7D7D7D7D7D7DuLL;
+ y = ((x & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((x & U64(0x0101010101010101)) << 7);
+ x &= U64(0xB5B5B5B5B5B5B5B5);
+ x ^= y & U64(0x4040404040404040);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0x8080808080808080);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0x1616161616161616);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0xEBEBEBEBEBEBEBEB);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0x9797979797979797);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0xFBFBFBFBFBFBFBFB);
+ y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+ x ^= y & U64(0x7D7D7D7D7D7D7D7D);
*w = x;
}
@@ -453,10 +469,10 @@ static void MixColumns(u64 *state)
for (c = 0; c < 2; c++) {
s1.d = state[c];
s.d = s1.d;
- s.d ^= ((s.d & 0xFFFF0000FFFF0000uLL) >> 16)
- | ((s.d & 0x0000FFFF0000FFFFuLL) << 16);
- s.d ^= ((s.d & 0xFF00FF00FF00FF00uLL) >> 8)
- | ((s.d & 0x00FF00FF00FF00FFuLL) << 8);
+ s.d ^= ((s.d & U64(0xFFFF0000FFFF0000)) >> 16)
+ | ((s.d & U64(0x0000FFFF0000FFFF)) << 16);
+ s.d ^= ((s.d & U64(0xFF00FF00FF00FF00)) >> 8)
+ | ((s.d & U64(0x00FF00FF00FF00FF)) << 8);
s.d ^= s1.d;
XtimeLong(&s1.d);
s.d ^= s1.d;
@@ -481,10 +497,10 @@ static void InvMixColumns(u64 *state)
for (c = 0; c < 2; c++) {
s1.d = state[c];
s.d = s1.d;
- s.d ^= ((s.d & 0xFFFF0000FFFF0000uLL) >> 16)
- | ((s.d & 0x0000FFFF0000FFFFuLL) << 16);
- s.d ^= ((s.d & 0xFF00FF00FF00FF00uLL) >> 8)
- | ((s.d & 0x00FF00FF00FF00FFuLL) << 8);
+ s.d ^= ((s.d & U64(0xFFFF0000FFFF0000)) >> 16)
+ | ((s.d & U64(0x0000FFFF0000FFFF)) << 16);
+ s.d ^= ((s.d & U64(0xFF00FF00FF00FF00)) >> 8)
+ | ((s.d & U64(0x00FF00FF00FF00FF)) << 8);
s.d ^= s1.d;
XtimeLong(&s1.d);
s.d ^= s1.d;
@@ -497,12 +513,12 @@ static void InvMixColumns(u64 *state)
s.b[6] ^= s1.b[7];
s.b[7] ^= s1.b[4];
XtimeLong(&s1.d);
- s1.d ^= ((s1.d & 0xFFFF0000FFFF0000uLL) >> 16)
- | ((s1.d & 0x0000FFFF0000FFFFuLL) << 16);
+ s1.d ^= ((s1.d & U64(0xFFFF0000FFFF0000)) >> 16)
+ | ((s1.d & U64(0x0000FFFF0000FFFF)) << 16);
s.d ^= s1.d;
XtimeLong(&s1.d);
- s1.d ^= ((s1.d & 0xFF00FF00FF00FF00uLL) >> 8)
- | ((s1.d & 0x00FF00FF00FF00FFuLL) << 8);
+ s1.d ^= ((s1.d & U64(0xFF00FF00FF00FF00)) >> 8)
+ | ((s1.d & U64(0x00FF00FF00FF00FF)) << 8);
s.d ^= s1.d;
state[c] = s.d;
}
diff --git a/crypto/aes/aes_ecb.c b/crypto/aes/aes_ecb.c
index 4fa360ca8b8d..e05afb0449cc 100644
--- a/crypto/aes/aes_ecb.c
+++ b/crypto/aes/aes_ecb.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,6 +9,12 @@
#include <assert.h>
+/*
+ * AES_encrypt/AES_decrypt are deprecated - but we need to use them to implement
+ * AES_ecb_encrypt
+ */
+#include "internal/deprecated.h"
+
#include <openssl/aes.h>
#include "aes_local.h"
diff --git a/crypto/aes/aes_ige.c b/crypto/aes/aes_ige.c
index 804b3a723d1f..72fcba7a0cf1 100644
--- a/crypto/aes/aes_ige.c
+++ b/crypto/aes/aes_ige.c
@@ -1,12 +1,18 @@
/*
* Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * AES_encrypt/AES_decrypt are deprecated - but we need to use them to implement
+ * these functions
+ */
+#include "internal/deprecated.h"
+
#include "internal/cryptlib.h"
#include <openssl/aes.h>
@@ -38,12 +44,13 @@ typedef struct {
/* N.B. The IV for this mode is _twice_ the block size */
+/* Use of this function is deprecated. */
void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc)
{
size_t n;
- size_t len = length;
+ size_t len = length / AES_BLOCK_SIZE;
if (length == 0)
return;
@@ -52,8 +59,6 @@ void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
OPENSSL_assert((length % AES_BLOCK_SIZE) == 0);
- len = length / AES_BLOCK_SIZE;
-
if (AES_ENCRYPT == enc) {
if (in != out &&
(UNALIGNED_MEMOPS_ARE_FAST
@@ -166,6 +171,14 @@ void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
/*
* Note that its effectively impossible to do biIGE in anything other
* than a single pass, so no provision is made for chaining.
+ *
+ * NB: The implementation of AES_bi_ige_encrypt has a bug. It is supposed to use
+ * 2 AES keys, but in fact only one is ever used. This bug has been present
+ * since this code was first implemented. It is believed to have minimal
+ * security impact in practice and has therefore not been fixed for backwards
+ * compatibility reasons.
+ *
+ * Use of this function is deprecated.
*/
/* N.B. The IV for this mode is _four times_ the block size */
diff --git a/crypto/aes/aes_local.h b/crypto/aes/aes_local.h
index a9c0059e52cc..69d17d6cde7b 100644
--- a/crypto/aes/aes_local.h
+++ b/crypto/aes/aes_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -24,7 +24,7 @@
# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
# endif
-typedef unsigned long long u64;
+typedef uint64_t u64;
# ifdef AES_LONG
typedef unsigned long u32;
# else
diff --git a/crypto/aes/aes_misc.c b/crypto/aes/aes_misc.c
index e0edc72ba71c..7f39bcf2b35f 100644
--- a/crypto/aes/aes_misc.c
+++ b/crypto/aes/aes_misc.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,11 +11,13 @@
#include <openssl/aes.h>
#include "aes_local.h"
+#ifndef OPENSSL_NO_DEPRECATED_3_0
const char *AES_options(void)
{
-#ifdef FULL_UNROLL
+# ifdef FULL_UNROLL
return "aes(full)";
-#else
+# else
return "aes(partial)";
-#endif
+# endif
}
+#endif
diff --git a/crypto/aes/aes_ofb.c b/crypto/aes/aes_ofb.c
index 215b53858eb6..58e47dc45e73 100644
--- a/crypto/aes/aes_ofb.c
+++ b/crypto/aes/aes_ofb.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * AES_encrypt is deprecated - but we need to use it to implement
+ * AES_ofb128_encrypt
+ */
+#include "internal/deprecated.h"
+
#include <openssl/aes.h>
#include <openssl/modes.h>
diff --git a/crypto/aes/aes_wrap.c b/crypto/aes/aes_wrap.c
index cae0b212297a..2187883aff91 100644
--- a/crypto/aes/aes_wrap.c
+++ b/crypto/aes/aes_wrap.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * AES_encrypt/AES_decrypt are deprecated - but we need to use them to implement
+ * these functions
+ */
+#include "internal/deprecated.h"
+
#include "internal/cryptlib.h"
#include <openssl/aes.h>
#include <openssl/modes.h>
diff --git a/crypto/aes/aes_x86core.c b/crypto/aes/aes_x86core.c
index 50b53abc1219..da525b6566c4 100644
--- a/crypto/aes/aes_x86core.c
+++ b/crypto/aes/aes_x86core.c
@@ -1,7 +1,7 @@
/*
* Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/aes/asm/aes-586.pl b/crypto/aes/asm/aes-586.pl
new file mode 100755
index 000000000000..7b4f9e1672f2
--- /dev/null
+++ b/crypto/aes/asm/aes-586.pl
@@ -0,0 +1,2998 @@
+#! /usr/bin/env perl
+# Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# Version 4.3.
+#
+# You might fail to appreciate this module performance from the first
+# try. If compared to "vanilla" linux-ia32-icc target, i.e. considered
+# to be *the* best Intel C compiler without -KPIC, performance appears
+# to be virtually identical... But try to re-configure with shared
+# library support... Aha! Intel compiler "suddenly" lags behind by 30%
+# [on P4, more on others]:-) And if compared to position-independent
+# code generated by GNU C, this code performs *more* than *twice* as
+# fast! Yes, all this buzz about PIC means that unlike other hand-
+# coded implementations, this one was explicitly designed to be safe
+# to use even in shared library context... This also means that this
+# code isn't necessarily absolutely fastest "ever," because in order
+# to achieve position independence an extra register has to be
+# off-loaded to stack, which affects the benchmark result.
+#
+# Special note about instruction choice. Do you recall RC4_INT code
+# performing poorly on P4? It might be the time to figure out why.
+# RC4_INT code implies effective address calculations in base+offset*4
+# form. Trouble is that it seems that offset scaling turned to be
+# critical path... At least eliminating scaling resulted in 2.8x RC4
+# performance improvement [as you might recall]. As AES code is hungry
+# for scaling too, I [try to] avoid the latter by favoring off-by-2
+# shifts and masking the result with 0xFF<<2 instead of "boring" 0xFF.
+#
+# As was shown by Dean Gaudet, the above note turned out to be
+# void. Performance improvement with off-by-2 shifts was observed on
+# intermediate implementation, which was spilling yet another register
+# to stack... Final offset*4 code below runs just a tad faster on P4,
+# but exhibits up to 10% improvement on other cores.
+#
+# Second version is "monolithic" replacement for aes_core.c, which in
+# addition to AES_[de|en]crypt implements AES_set_[de|en]cryption_key.
+# This made it possible to implement little-endian variant of the
+# algorithm without modifying the base C code. Motivating factor for
+# the undertaken effort was that it appeared that in tight IA-32
+# register window little-endian flavor could achieve slightly higher
+# Instruction Level Parallelism, and it indeed resulted in up to 15%
+# better performance on most recent µ-archs...
+#
+# Third version adds AES_cbc_encrypt implementation, which resulted in
+# up to 40% performance improvement of CBC benchmark results. 40% was
+# observed on P4 core, where "overall" improvement coefficient, i.e. if
+# compared to PIC generated by GCC and in CBC mode, was observed to be
+# as large as 4x:-) CBC performance is virtually identical to ECB now
+# and on some platforms even better, e.g. 17.6 "small" cycles/byte on
+# Opteron, because certain function prologues and epilogues are
+# effectively taken out of the loop...
+#
+# Version 3.2 implements compressed tables and prefetch of these tables
+# in CBC[!] mode. Former means that 3/4 of table references are now
+# misaligned, which unfortunately has negative impact on elder IA-32
+# implementations, Pentium suffered 30% penalty, PIII - 10%.
+#
+# Version 3.3 avoids L1 cache aliasing between stack frame and
+# S-boxes, and 3.4 - L1 cache aliasing even between key schedule. The
+# latter is achieved by copying the key schedule to controlled place in
+# stack. This unfortunately has rather strong impact on small block CBC
+# performance, ~2x deterioration on 16-byte block if compared to 3.3.
+#
+# Version 3.5 checks if there is L1 cache aliasing between user-supplied
+# key schedule and S-boxes and abstains from copying the former if
+# there is no. This allows end-user to consciously retain small block
+# performance by aligning key schedule in specific manner.
+#
+# Version 3.6 compresses Td4 to 256 bytes and prefetches it in ECB.
+#
+# Current ECB performance numbers for 128-bit key in CPU cycles per
+# processed byte [measure commonly used by AES benchmarkers] are:
+#
+# small footprint fully unrolled
+# P4 24 22
+# AMD K8 20 19
+# PIII 25 23
+# Pentium 81 78
+#
+# Version 3.7 reimplements outer rounds as "compact." Meaning that
+# first and last rounds reference compact 256 bytes S-box. This means
+# that first round consumes a lot more CPU cycles and that encrypt
+# and decrypt performance becomes asymmetric. Encrypt performance
+# drops by 10-12%, while decrypt - by 20-25%:-( 256 bytes S-box is
+# aggressively pre-fetched.
+#
+# Version 4.0 effectively rolls back to 3.6 and instead implements
+# additional set of functions, _[x86|sse]_AES_[en|de]crypt_compact,
+# which use exclusively 256 byte S-box. These functions are to be
+# called in modes not concealing plain text, such as ECB, or when
+# we're asked to process smaller amount of data [or unconditionally
+# on hyper-threading CPU]. Currently it's called unconditionally from
+# AES_[en|de]crypt, which affects all modes, but CBC. CBC routine
+# still needs to be modified to switch between slower and faster
+# mode when appropriate... But in either case benchmark landscape
+# changes dramatically and below numbers are CPU cycles per processed
+# byte for 128-bit key.
+#
+# ECB encrypt ECB decrypt CBC large chunk
+# P4 52[54] 83[95] 23
+# AMD K8 46[41] 66[70] 18
+# PIII 41[50] 60[77] 24
+# Core 2 31[36] 45[64] 18.5
+# Atom 76[100] 96[138] 60
+# Pentium 115 150 77
+#
+# Version 4.1 switches to compact S-box even in key schedule setup.
+#
+# Version 4.2 prefetches compact S-box in every SSE round or in other
+# words every cache-line is *guaranteed* to be accessed within ~50
+# cycles window. Why just SSE? Because it's needed on hyper-threading
+# CPU! Which is also why it's prefetched with 64 byte stride. Best
+# part is that it has no negative effect on performance:-)
+#
+# Version 4.3 implements switch between compact and non-compact block
+# functions in AES_cbc_encrypt depending on how much data was asked
+# to be processed in one stroke.
+#
+######################################################################
+# Timing attacks are classified in two classes: synchronous when
+# attacker consciously initiates cryptographic operation and collects
+# timing data of various character afterwards, and asynchronous when
+# malicious code is executed on same CPU simultaneously with AES,
+# instruments itself and performs statistical analysis of this data.
+#
+# As far as synchronous attacks go the root to the AES timing
+# vulnerability is twofold. Firstly, of 256 S-box elements at most 160
+# are referred to in single 128-bit block operation. Well, in C
+# implementation with 4 distinct tables it's actually as little as 40
+# references per 256 elements table, but anyway... Secondly, even
+# though S-box elements are clustered into smaller amount of cache-
+# lines, smaller than 160 and even 40, it turned out that for certain
+# plain-text pattern[s] or simply put chosen plain-text and given key
+# few cache-lines remain unaccessed during block operation. Now, if
+# attacker can figure out this access pattern, he can deduct the key
+# [or at least part of it]. The natural way to mitigate this kind of
+# attacks is to minimize the amount of cache-lines in S-box and/or
+# prefetch them to ensure that every one is accessed for more uniform
+# timing. But note that *if* plain-text was concealed in such way that
+# input to block function is distributed *uniformly*, then attack
+# wouldn't apply. Now note that some encryption modes, most notably
+# CBC, do mask the plain-text in this exact way [secure cipher output
+# is distributed uniformly]. Yes, one still might find input that
+# would reveal the information about given key, but if amount of
+# candidate inputs to be tried is larger than amount of possible key
+# combinations then attack becomes infeasible. This is why revised
+# AES_cbc_encrypt "dares" to switch to larger S-box when larger chunk
+# of data is to be processed in one stroke. The current size limit of
+# 512 bytes is chosen to provide same [diminishingly low] probability
+# for cache-line to remain untouched in large chunk operation with
+# large S-box as for single block operation with compact S-box and
+# surely needs more careful consideration...
+#
+# As for asynchronous attacks. There are two flavours: attacker code
+# being interleaved with AES on hyper-threading CPU at *instruction*
+# level, and two processes time sharing single core. As for latter.
+# Two vectors. 1. Given that attacker process has higher priority,
+# yield execution to process performing AES just before timer fires
+# off the scheduler, immediately regain control of CPU and analyze the
+# cache state. For this attack to be efficient attacker would have to
+# effectively slow down the operation by several *orders* of magnitude,
+# by ratio of time slice to duration of handful of AES rounds, which
+# unlikely to remain unnoticed. Not to mention that this also means
+# that he would spend correspondingly more time to collect enough
+# statistical data to mount the attack. It's probably appropriate to
+# say that if adversary reckons that this attack is beneficial and
+# risks to be noticed, you probably have larger problems having him
+# mere opportunity. In other words suggested code design expects you
+# to preclude/mitigate this attack by overall system security design.
+# 2. Attacker manages to make his code interrupt driven. In order for
+# this kind of attack to be feasible, interrupt rate has to be high
+# enough, again comparable to duration of handful of AES rounds. But
+# is there interrupt source of such rate? Hardly, not even 1Gbps NIC
+# generates interrupts at such raging rate...
+#
+# And now back to the former, hyper-threading CPU or more specifically
+# Intel P4. Recall that asynchronous attack implies that malicious
+# code instruments itself. And naturally instrumentation granularity
+# has be noticeably lower than duration of codepath accessing S-box.
+# Given that all cache-lines are accessed during that time that is.
+# Current implementation accesses *all* cache-lines within ~50 cycles
+# window, which is actually *less* than RDTSC latency on Intel P4!
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+$output = pop and open STDOUT,">$output";
+
+&asm_init($ARGV[0],$x86only = $ARGV[$#ARGV] eq "386");
+&static_label("AES_Te");
+&static_label("AES_Td");
+
+$s0="eax";
+$s1="ebx";
+$s2="ecx";
+$s3="edx";
+$key="edi";
+$acc="esi";
+$tbl="ebp";
+
+# stack frame layout in _[x86|sse]_AES_* routines, frame is allocated
+# by caller
+$__ra=&DWP(0,"esp"); # return address
+$__s0=&DWP(4,"esp"); # s0 backing store
+$__s1=&DWP(8,"esp"); # s1 backing store
+$__s2=&DWP(12,"esp"); # s2 backing store
+$__s3=&DWP(16,"esp"); # s3 backing store
+$__key=&DWP(20,"esp"); # pointer to key schedule
+$__end=&DWP(24,"esp"); # pointer to end of key schedule
+$__tbl=&DWP(28,"esp"); # %ebp backing store
+
+# stack frame layout in AES_[en|crypt] routines, which differs from
+# above by 4 and overlaps by %ebp backing store
+$_tbl=&DWP(24,"esp");
+$_esp=&DWP(28,"esp");
+
+sub _data_word() { my $i; while(defined($i=shift)) { &data_word($i,$i); } }
+
+$speed_limit=512; # chunks smaller than $speed_limit are
+ # processed with compact routine in CBC mode
+$small_footprint=1; # $small_footprint=1 code is ~5% slower [on
+ # recent µ-archs], but ~5 times smaller!
+ # I favor compact code to minimize cache
+ # contention and in hope to "collect" 5% back
+ # in real-life applications...
+
+$vertical_spin=0; # shift "vertically" defaults to 0, because of
+ # its proof-of-concept status...
+# Note that there is no decvert(), as well as last encryption round is
+# performed with "horizontal" shifts. This is because this "vertical"
+# implementation [one which groups shifts on a given $s[i] to form a
+# "column," unlike "horizontal" one, which groups shifts on different
+# $s[i] to form a "row"] is work in progress. It was observed to run
+# few percents faster on Intel cores, but not AMD. On AMD K8 core it's
+# whole 12% slower:-( So we face a trade-off... Shall it be resolved
+# some day? Till then the code is considered experimental and by
+# default remains dormant...
+
+sub encvert()
+{ my ($te,@s) = @_;
+ my ($v0,$v1) = ($acc,$key);
+
+ &mov ($v0,$s[3]); # copy s3
+ &mov (&DWP(4,"esp"),$s[2]); # save s2
+ &mov ($v1,$s[0]); # copy s0
+ &mov (&DWP(8,"esp"),$s[1]); # save s1
+
+ &movz ($s[2],&HB($s[0]));
+ &and ($s[0],0xFF);
+ &mov ($s[0],&DWP(0,$te,$s[0],8)); # s0>>0
+ &shr ($v1,16);
+ &mov ($s[3],&DWP(3,$te,$s[2],8)); # s0>>8
+ &movz ($s[1],&HB($v1));
+ &and ($v1,0xFF);
+ &mov ($s[2],&DWP(2,$te,$v1,8)); # s0>>16
+ &mov ($v1,$v0);
+ &mov ($s[1],&DWP(1,$te,$s[1],8)); # s0>>24
+
+ &and ($v0,0xFF);
+ &xor ($s[3],&DWP(0,$te,$v0,8)); # s3>>0
+ &movz ($v0,&HB($v1));
+ &shr ($v1,16);
+ &xor ($s[2],&DWP(3,$te,$v0,8)); # s3>>8
+ &movz ($v0,&HB($v1));
+ &and ($v1,0xFF);
+ &xor ($s[1],&DWP(2,$te,$v1,8)); # s3>>16
+ &mov ($v1,&DWP(4,"esp")); # restore s2
+ &xor ($s[0],&DWP(1,$te,$v0,8)); # s3>>24
+
+ &mov ($v0,$v1);
+ &and ($v1,0xFF);
+ &xor ($s[2],&DWP(0,$te,$v1,8)); # s2>>0
+ &movz ($v1,&HB($v0));
+ &shr ($v0,16);
+ &xor ($s[1],&DWP(3,$te,$v1,8)); # s2>>8
+ &movz ($v1,&HB($v0));
+ &and ($v0,0xFF);
+ &xor ($s[0],&DWP(2,$te,$v0,8)); # s2>>16
+ &mov ($v0,&DWP(8,"esp")); # restore s1
+ &xor ($s[3],&DWP(1,$te,$v1,8)); # s2>>24
+
+ &mov ($v1,$v0);
+ &and ($v0,0xFF);
+ &xor ($s[1],&DWP(0,$te,$v0,8)); # s1>>0
+ &movz ($v0,&HB($v1));
+ &shr ($v1,16);
+ &xor ($s[0],&DWP(3,$te,$v0,8)); # s1>>8
+ &movz ($v0,&HB($v1));
+ &and ($v1,0xFF);
+ &xor ($s[3],&DWP(2,$te,$v1,8)); # s1>>16
+ &mov ($key,$__key); # reincarnate v1 as key
+ &xor ($s[2],&DWP(1,$te,$v0,8)); # s1>>24
+}
+
+# Another experimental routine, which features "horizontal spin," but
+# eliminates one reference to stack. Strangely enough runs slower...
+sub enchoriz()
+{ my ($v0,$v1) = ($key,$acc);
+
+ &movz ($v0,&LB($s0)); # 3, 2, 1, 0*
+ &rotr ($s2,8); # 8,11,10, 9
+ &mov ($v1,&DWP(0,$te,$v0,8)); # 0
+ &movz ($v0,&HB($s1)); # 7, 6, 5*, 4
+ &rotr ($s3,16); # 13,12,15,14
+ &xor ($v1,&DWP(3,$te,$v0,8)); # 5
+ &movz ($v0,&HB($s2)); # 8,11,10*, 9
+ &rotr ($s0,16); # 1, 0, 3, 2
+ &xor ($v1,&DWP(2,$te,$v0,8)); # 10
+ &movz ($v0,&HB($s3)); # 13,12,15*,14
+ &xor ($v1,&DWP(1,$te,$v0,8)); # 15, t[0] collected
+ &mov ($__s0,$v1); # t[0] saved
+
+ &movz ($v0,&LB($s1)); # 7, 6, 5, 4*
+ &shr ($s1,16); # -, -, 7, 6
+ &mov ($v1,&DWP(0,$te,$v0,8)); # 4
+ &movz ($v0,&LB($s3)); # 13,12,15,14*
+ &xor ($v1,&DWP(2,$te,$v0,8)); # 14
+ &movz ($v0,&HB($s0)); # 1, 0, 3*, 2
+ &and ($s3,0xffff0000); # 13,12, -, -
+ &xor ($v1,&DWP(1,$te,$v0,8)); # 3
+ &movz ($v0,&LB($s2)); # 8,11,10, 9*
+ &or ($s3,$s1); # 13,12, 7, 6
+ &xor ($v1,&DWP(3,$te,$v0,8)); # 9, t[1] collected
+ &mov ($s1,$v1); # s[1]=t[1]
+
+ &movz ($v0,&LB($s0)); # 1, 0, 3, 2*
+ &shr ($s2,16); # -, -, 8,11
+ &mov ($v1,&DWP(2,$te,$v0,8)); # 2
+ &movz ($v0,&HB($s3)); # 13,12, 7*, 6
+ &xor ($v1,&DWP(1,$te,$v0,8)); # 7
+ &movz ($v0,&HB($s2)); # -, -, 8*,11
+ &xor ($v1,&DWP(0,$te,$v0,8)); # 8
+ &mov ($v0,$s3);
+ &shr ($v0,24); # 13
+ &xor ($v1,&DWP(3,$te,$v0,8)); # 13, t[2] collected
+
+ &movz ($v0,&LB($s2)); # -, -, 8,11*
+ &shr ($s0,24); # 1*
+ &mov ($s2,&DWP(1,$te,$v0,8)); # 11
+ &xor ($s2,&DWP(3,$te,$s0,8)); # 1
+ &mov ($s0,$__s0); # s[0]=t[0]
+ &movz ($v0,&LB($s3)); # 13,12, 7, 6*
+ &shr ($s3,16); # , ,13,12
+ &xor ($s2,&DWP(2,$te,$v0,8)); # 6
+ &mov ($key,$__key); # reincarnate v0 as key
+ &and ($s3,0xff); # , ,13,12*
+ &mov ($s3,&DWP(0,$te,$s3,8)); # 12
+ &xor ($s3,$s2); # s[2]=t[3] collected
+ &mov ($s2,$v1); # s[2]=t[2]
+}
+
+# More experimental code... SSE one... Even though this one eliminates
+# *all* references to stack, it's not faster...
+sub sse_encbody()
+{
+ &movz ($acc,&LB("eax")); # 0
+ &mov ("ecx",&DWP(0,$tbl,$acc,8)); # 0
+ &pshufw ("mm2","mm0",0x0d); # 7, 6, 3, 2
+ &movz ("edx",&HB("eax")); # 1
+ &mov ("edx",&DWP(3,$tbl,"edx",8)); # 1
+ &shr ("eax",16); # 5, 4
+
+ &movz ($acc,&LB("ebx")); # 10
+ &xor ("ecx",&DWP(2,$tbl,$acc,8)); # 10
+ &pshufw ("mm6","mm4",0x08); # 13,12, 9, 8
+ &movz ($acc,&HB("ebx")); # 11
+ &xor ("edx",&DWP(1,$tbl,$acc,8)); # 11
+ &shr ("ebx",16); # 15,14
+
+ &movz ($acc,&HB("eax")); # 5
+ &xor ("ecx",&DWP(3,$tbl,$acc,8)); # 5
+ &movq ("mm3",QWP(16,$key));
+ &movz ($acc,&HB("ebx")); # 15
+ &xor ("ecx",&DWP(1,$tbl,$acc,8)); # 15
+ &movd ("mm0","ecx"); # t[0] collected
+
+ &movz ($acc,&LB("eax")); # 4
+ &mov ("ecx",&DWP(0,$tbl,$acc,8)); # 4
+ &movd ("eax","mm2"); # 7, 6, 3, 2
+ &movz ($acc,&LB("ebx")); # 14
+ &xor ("ecx",&DWP(2,$tbl,$acc,8)); # 14
+ &movd ("ebx","mm6"); # 13,12, 9, 8
+
+ &movz ($acc,&HB("eax")); # 3
+ &xor ("ecx",&DWP(1,$tbl,$acc,8)); # 3
+ &movz ($acc,&HB("ebx")); # 9
+ &xor ("ecx",&DWP(3,$tbl,$acc,8)); # 9
+ &movd ("mm1","ecx"); # t[1] collected
+
+ &movz ($acc,&LB("eax")); # 2
+ &mov ("ecx",&DWP(2,$tbl,$acc,8)); # 2
+ &shr ("eax",16); # 7, 6
+ &punpckldq ("mm0","mm1"); # t[0,1] collected
+ &movz ($acc,&LB("ebx")); # 8
+ &xor ("ecx",&DWP(0,$tbl,$acc,8)); # 8
+ &shr ("ebx",16); # 13,12
+
+ &movz ($acc,&HB("eax")); # 7
+ &xor ("ecx",&DWP(1,$tbl,$acc,8)); # 7
+ &pxor ("mm0","mm3");
+ &movz ("eax",&LB("eax")); # 6
+ &xor ("edx",&DWP(2,$tbl,"eax",8)); # 6
+ &pshufw ("mm1","mm0",0x08); # 5, 4, 1, 0
+ &movz ($acc,&HB("ebx")); # 13
+ &xor ("ecx",&DWP(3,$tbl,$acc,8)); # 13
+ &xor ("ecx",&DWP(24,$key)); # t[2]
+ &movd ("mm4","ecx"); # t[2] collected
+ &movz ("ebx",&LB("ebx")); # 12
+ &xor ("edx",&DWP(0,$tbl,"ebx",8)); # 12
+ &shr ("ecx",16);
+ &movd ("eax","mm1"); # 5, 4, 1, 0
+ &mov ("ebx",&DWP(28,$key)); # t[3]
+ &xor ("ebx","edx");
+ &movd ("mm5","ebx"); # t[3] collected
+ &and ("ebx",0xffff0000);
+ &or ("ebx","ecx");
+
+ &punpckldq ("mm4","mm5"); # t[2,3] collected
+}
+
+######################################################################
+# "Compact" block function
+######################################################################
+
+sub enccompact()
+{ my $Fn = \&mov;
+ while ($#_>5) { pop(@_); $Fn=sub{}; }
+ my ($i,$te,@s)=@_;
+ my $tmp = $key;
+ my $out = $i==3?$s[0]:$acc;
+
+ # $Fn is used in first compact round and its purpose is to
+ # void restoration of some values from stack, so that after
+ # 4xenccompact with extra argument $key value is left there...
+ if ($i==3) { &$Fn ($key,$__key); }##%edx
+ else { &mov ($out,$s[0]); }
+ &and ($out,0xFF);
+ if ($i==1) { &shr ($s[0],16); }#%ebx[1]
+ if ($i==2) { &shr ($s[0],24); }#%ecx[2]
+ &movz ($out,&BP(-128,$te,$out,1));
+
+ if ($i==3) { $tmp=$s[1]; }##%eax
+ &movz ($tmp,&HB($s[1]));
+ &movz ($tmp,&BP(-128,$te,$tmp,1));
+ &shl ($tmp,8);
+ &xor ($out,$tmp);
+
+ if ($i==3) { $tmp=$s[2]; &mov ($s[1],$__s0); }##%ebx
+ else { &mov ($tmp,$s[2]);
+ &shr ($tmp,16); }
+ if ($i==2) { &and ($s[1],0xFF); }#%edx[2]
+ &and ($tmp,0xFF);
+ &movz ($tmp,&BP(-128,$te,$tmp,1));
+ &shl ($tmp,16);
+ &xor ($out,$tmp);
+
+ if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }##%ecx
+ elsif($i==2){ &movz ($tmp,&HB($s[3])); }#%ebx[2]
+ else { &mov ($tmp,$s[3]);
+ &shr ($tmp,24); }
+ &movz ($tmp,&BP(-128,$te,$tmp,1));
+ &shl ($tmp,24);
+ &xor ($out,$tmp);
+ if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); }
+ if ($i==3) { &mov ($s[3],$acc); }
+ &comment();
+}
+
+sub enctransform()
+{ my @s = ($s0,$s1,$s2,$s3);
+ my $i = shift;
+ my $tmp = $tbl;
+ my $r2 = $key ;
+
+ &and ($tmp,$s[$i]);
+ &lea ($r2,&DWP(0,$s[$i],$s[$i]));
+ &mov ($acc,$tmp);
+ &shr ($tmp,7);
+ &and ($r2,0xfefefefe);
+ &sub ($acc,$tmp);
+ &mov ($tmp,$s[$i]);
+ &and ($acc,0x1b1b1b1b);
+ &rotr ($tmp,16);
+ &xor ($acc,$r2); # r2
+ &mov ($r2,$s[$i]);
+
+ &xor ($s[$i],$acc); # r0 ^ r2
+ &rotr ($r2,16+8);
+ &xor ($acc,$tmp);
+ &rotl ($s[$i],24);
+ &xor ($acc,$r2);
+ &mov ($tmp,0x80808080) if ($i!=1);
+ &xor ($s[$i],$acc); # ROTATE(r2^r0,24) ^ r2
+}
+
+&function_begin_B("_x86_AES_encrypt_compact");
+ # note that caller is expected to allocate stack frame for me!
+ &mov ($__key,$key); # save key
+
+ &xor ($s0,&DWP(0,$key)); # xor with key
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &mov ($acc,&DWP(240,$key)); # load key->rounds
+ &lea ($acc,&DWP(-2,$acc,$acc));
+ &lea ($acc,&DWP(0,$key,$acc,8));
+ &mov ($__end,$acc); # end of key schedule
+
+ # prefetch Te4
+ &mov ($key,&DWP(0-128,$tbl));
+ &mov ($acc,&DWP(32-128,$tbl));
+ &mov ($key,&DWP(64-128,$tbl));
+ &mov ($acc,&DWP(96-128,$tbl));
+ &mov ($key,&DWP(128-128,$tbl));
+ &mov ($acc,&DWP(160-128,$tbl));
+ &mov ($key,&DWP(192-128,$tbl));
+ &mov ($acc,&DWP(224-128,$tbl));
+
+ &set_label("loop",16);
+
+ &enccompact(0,$tbl,$s0,$s1,$s2,$s3,1);
+ &enccompact(1,$tbl,$s1,$s2,$s3,$s0,1);
+ &enccompact(2,$tbl,$s2,$s3,$s0,$s1,1);
+ &enccompact(3,$tbl,$s3,$s0,$s1,$s2,1);
+ &mov ($tbl,0x80808080);
+ &enctransform(2);
+ &enctransform(3);
+ &enctransform(0);
+ &enctransform(1);
+ &mov ($key,$__key);
+ &mov ($tbl,$__tbl);
+ &add ($key,16); # advance rd_key
+ &xor ($s0,&DWP(0,$key));
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &cmp ($key,$__end);
+ &mov ($__key,$key);
+ &jb (&label("loop"));
+
+ &enccompact(0,$tbl,$s0,$s1,$s2,$s3);
+ &enccompact(1,$tbl,$s1,$s2,$s3,$s0);
+ &enccompact(2,$tbl,$s2,$s3,$s0,$s1);
+ &enccompact(3,$tbl,$s3,$s0,$s1,$s2);
+
+ &xor ($s0,&DWP(16,$key));
+ &xor ($s1,&DWP(20,$key));
+ &xor ($s2,&DWP(24,$key));
+ &xor ($s3,&DWP(28,$key));
+
+ &ret ();
+&function_end_B("_x86_AES_encrypt_compact");
+
+######################################################################
+# "Compact" SSE block function.
+######################################################################
+#
+# Performance is not actually extraordinary in comparison to pure
+# x86 code. In particular encrypt performance is virtually the same.
+# Decrypt performance on the other hand is 15-20% better on newer
+# µ-archs [but we're thankful for *any* improvement here], and ~50%
+# better on PIII:-) And additionally on the pros side this code
+# eliminates redundant references to stack and thus relieves/
+# minimizes the pressure on the memory bus.
+#
+# MMX register layout lsb
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | mm4 | mm0 |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | s3 | s2 | s1 | s0 |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+#
+# Indexes translate as s[N/4]>>(8*(N%4)), e.g. 5 means s1>>8.
+# In this terms encryption and decryption "compact" permutation
+# matrices can be depicted as following:
+#
+# encryption lsb # decryption lsb
+# +----++----+----+----+----+ # +----++----+----+----+----+
+# | t0 || 15 | 10 | 5 | 0 | # | t0 || 7 | 10 | 13 | 0 |
+# +----++----+----+----+----+ # +----++----+----+----+----+
+# | t1 || 3 | 14 | 9 | 4 | # | t1 || 11 | 14 | 1 | 4 |
+# +----++----+----+----+----+ # +----++----+----+----+----+
+# | t2 || 7 | 2 | 13 | 8 | # | t2 || 15 | 2 | 5 | 8 |
+# +----++----+----+----+----+ # +----++----+----+----+----+
+# | t3 || 11 | 6 | 1 | 12 | # | t3 || 3 | 6 | 9 | 12 |
+# +----++----+----+----+----+ # +----++----+----+----+----+
+#
+######################################################################
+# Why not xmm registers? Short answer. It was actually tested and
+# was not any faster, but *contrary*, most notably on Intel CPUs.
+# Longer answer. Main advantage of using mm registers is that movd
+# latency is lower, especially on Intel P4. While arithmetic
+# instructions are twice as many, they can be scheduled every cycle
+# and not every second one when they are operating on xmm register,
+# so that "arithmetic throughput" remains virtually the same. And
+# finally the code can be executed even on elder SSE-only CPUs:-)
+
+sub sse_enccompact()
+{
+ &pshufw ("mm1","mm0",0x08); # 5, 4, 1, 0
+ &pshufw ("mm5","mm4",0x0d); # 15,14,11,10
+ &movd ("eax","mm1"); # 5, 4, 1, 0
+ &movd ("ebx","mm5"); # 15,14,11,10
+ &mov ($__key,$key);
+
+ &movz ($acc,&LB("eax")); # 0
+ &movz ("edx",&HB("eax")); # 1
+ &pshufw ("mm2","mm0",0x0d); # 7, 6, 3, 2
+ &movz ("ecx",&BP(-128,$tbl,$acc,1)); # 0
+ &movz ($key,&LB("ebx")); # 10
+ &movz ("edx",&BP(-128,$tbl,"edx",1)); # 1
+ &shr ("eax",16); # 5, 4
+ &shl ("edx",8); # 1
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 10
+ &movz ($key,&HB("ebx")); # 11
+ &shl ($acc,16); # 10
+ &pshufw ("mm6","mm4",0x08); # 13,12, 9, 8
+ &or ("ecx",$acc); # 10
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 11
+ &movz ($key,&HB("eax")); # 5
+ &shl ($acc,24); # 11
+ &shr ("ebx",16); # 15,14
+ &or ("edx",$acc); # 11
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 5
+ &movz ($key,&HB("ebx")); # 15
+ &shl ($acc,8); # 5
+ &or ("ecx",$acc); # 5
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 15
+ &movz ($key,&LB("eax")); # 4
+ &shl ($acc,24); # 15
+ &or ("ecx",$acc); # 15
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 4
+ &movz ($key,&LB("ebx")); # 14
+ &movd ("eax","mm2"); # 7, 6, 3, 2
+ &movd ("mm0","ecx"); # t[0] collected
+ &movz ("ecx",&BP(-128,$tbl,$key,1)); # 14
+ &movz ($key,&HB("eax")); # 3
+ &shl ("ecx",16); # 14
+ &movd ("ebx","mm6"); # 13,12, 9, 8
+ &or ("ecx",$acc); # 14
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 3
+ &movz ($key,&HB("ebx")); # 9
+ &shl ($acc,24); # 3
+ &or ("ecx",$acc); # 3
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 9
+ &movz ($key,&LB("ebx")); # 8
+ &shl ($acc,8); # 9
+ &shr ("ebx",16); # 13,12
+ &or ("ecx",$acc); # 9
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 8
+ &movz ($key,&LB("eax")); # 2
+ &shr ("eax",16); # 7, 6
+ &movd ("mm1","ecx"); # t[1] collected
+ &movz ("ecx",&BP(-128,$tbl,$key,1)); # 2
+ &movz ($key,&HB("eax")); # 7
+ &shl ("ecx",16); # 2
+ &and ("eax",0xff); # 6
+ &or ("ecx",$acc); # 2
+
+ &punpckldq ("mm0","mm1"); # t[0,1] collected
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 7
+ &movz ($key,&HB("ebx")); # 13
+ &shl ($acc,24); # 7
+ &and ("ebx",0xff); # 12
+ &movz ("eax",&BP(-128,$tbl,"eax",1)); # 6
+ &or ("ecx",$acc); # 7
+ &shl ("eax",16); # 6
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 13
+ &or ("edx","eax"); # 6
+ &shl ($acc,8); # 13
+ &movz ("ebx",&BP(-128,$tbl,"ebx",1)); # 12
+ &or ("ecx",$acc); # 13
+ &or ("edx","ebx"); # 12
+ &mov ($key,$__key);
+ &movd ("mm4","ecx"); # t[2] collected
+ &movd ("mm5","edx"); # t[3] collected
+
+ &punpckldq ("mm4","mm5"); # t[2,3] collected
+}
+
+ if (!$x86only) {
+&function_begin_B("_sse_AES_encrypt_compact");
+ &pxor ("mm0",&QWP(0,$key)); # 7, 6, 5, 4, 3, 2, 1, 0
+ &pxor ("mm4",&QWP(8,$key)); # 15,14,13,12,11,10, 9, 8
+
+ # note that caller is expected to allocate stack frame for me!
+ &mov ($acc,&DWP(240,$key)); # load key->rounds
+ &lea ($acc,&DWP(-2,$acc,$acc));
+ &lea ($acc,&DWP(0,$key,$acc,8));
+ &mov ($__end,$acc); # end of key schedule
+
+ &mov ($s0,0x1b1b1b1b); # magic constant
+ &mov (&DWP(8,"esp"),$s0);
+ &mov (&DWP(12,"esp"),$s0);
+
+ # prefetch Te4
+ &mov ($s0,&DWP(0-128,$tbl));
+ &mov ($s1,&DWP(32-128,$tbl));
+ &mov ($s2,&DWP(64-128,$tbl));
+ &mov ($s3,&DWP(96-128,$tbl));
+ &mov ($s0,&DWP(128-128,$tbl));
+ &mov ($s1,&DWP(160-128,$tbl));
+ &mov ($s2,&DWP(192-128,$tbl));
+ &mov ($s3,&DWP(224-128,$tbl));
+
+ &set_label("loop",16);
+ &sse_enccompact();
+ &add ($key,16);
+ &cmp ($key,$__end);
+ &ja (&label("out"));
+
+ &movq ("mm2",&QWP(8,"esp"));
+ &pxor ("mm3","mm3"); &pxor ("mm7","mm7");
+ &movq ("mm1","mm0"); &movq ("mm5","mm4"); # r0
+ &pcmpgtb("mm3","mm0"); &pcmpgtb("mm7","mm4");
+ &pand ("mm3","mm2"); &pand ("mm7","mm2");
+ &pshufw ("mm2","mm0",0xb1); &pshufw ("mm6","mm4",0xb1);# ROTATE(r0,16)
+ &paddb ("mm0","mm0"); &paddb ("mm4","mm4");
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # = r2
+ &pshufw ("mm3","mm2",0xb1); &pshufw ("mm7","mm6",0xb1);# r0
+ &pxor ("mm1","mm0"); &pxor ("mm5","mm4"); # r0^r2
+ &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= ROTATE(r0,16)
+
+ &movq ("mm2","mm3"); &movq ("mm6","mm7");
+ &pslld ("mm3",8); &pslld ("mm7",8);
+ &psrld ("mm2",24); &psrld ("mm6",24);
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= r0<<8
+ &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= r0>>24
+
+ &movq ("mm3","mm1"); &movq ("mm7","mm5");
+ &movq ("mm2",&QWP(0,$key)); &movq ("mm6",&QWP(8,$key));
+ &psrld ("mm1",8); &psrld ("mm5",8);
+ &mov ($s0,&DWP(0-128,$tbl));
+ &pslld ("mm3",24); &pslld ("mm7",24);
+ &mov ($s1,&DWP(64-128,$tbl));
+ &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= (r2^r0)<<8
+ &mov ($s2,&DWP(128-128,$tbl));
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= (r2^r0)>>24
+ &mov ($s3,&DWP(192-128,$tbl));
+
+ &pxor ("mm0","mm2"); &pxor ("mm4","mm6");
+ &jmp (&label("loop"));
+
+ &set_label("out",16);
+ &pxor ("mm0",&QWP(0,$key));
+ &pxor ("mm4",&QWP(8,$key));
+
+ &ret ();
+&function_end_B("_sse_AES_encrypt_compact");
+ }
+
+######################################################################
+# Vanilla block function.
+######################################################################
+
+sub encstep()
+{ my ($i,$te,@s) = @_;
+ my $tmp = $key;
+ my $out = $i==3?$s[0]:$acc;
+
+ # lines marked with #%e?x[i] denote "reordered" instructions...
+ if ($i==3) { &mov ($key,$__key); }##%edx
+ else { &mov ($out,$s[0]);
+ &and ($out,0xFF); }
+ if ($i==1) { &shr ($s[0],16); }#%ebx[1]
+ if ($i==2) { &shr ($s[0],24); }#%ecx[2]
+ &mov ($out,&DWP(0,$te,$out,8));
+
+ if ($i==3) { $tmp=$s[1]; }##%eax
+ &movz ($tmp,&HB($s[1]));
+ &xor ($out,&DWP(3,$te,$tmp,8));
+
+ if ($i==3) { $tmp=$s[2]; &mov ($s[1],$__s0); }##%ebx
+ else { &mov ($tmp,$s[2]);
+ &shr ($tmp,16); }
+ if ($i==2) { &and ($s[1],0xFF); }#%edx[2]
+ &and ($tmp,0xFF);
+ &xor ($out,&DWP(2,$te,$tmp,8));
+
+ if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }##%ecx
+ elsif($i==2){ &movz ($tmp,&HB($s[3])); }#%ebx[2]
+ else { &mov ($tmp,$s[3]);
+ &shr ($tmp,24) }
+ &xor ($out,&DWP(1,$te,$tmp,8));
+ if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); }
+ if ($i==3) { &mov ($s[3],$acc); }
+ &comment();
+}
+
+sub enclast()
+{ my ($i,$te,@s)=@_;
+ my $tmp = $key;
+ my $out = $i==3?$s[0]:$acc;
+
+ if ($i==3) { &mov ($key,$__key); }##%edx
+ else { &mov ($out,$s[0]); }
+ &and ($out,0xFF);
+ if ($i==1) { &shr ($s[0],16); }#%ebx[1]
+ if ($i==2) { &shr ($s[0],24); }#%ecx[2]
+ &mov ($out,&DWP(2,$te,$out,8));
+ &and ($out,0x000000ff);
+
+ if ($i==3) { $tmp=$s[1]; }##%eax
+ &movz ($tmp,&HB($s[1]));
+ &mov ($tmp,&DWP(0,$te,$tmp,8));
+ &and ($tmp,0x0000ff00);
+ &xor ($out,$tmp);
+
+ if ($i==3) { $tmp=$s[2]; &mov ($s[1],$__s0); }##%ebx
+ else { &mov ($tmp,$s[2]);
+ &shr ($tmp,16); }
+ if ($i==2) { &and ($s[1],0xFF); }#%edx[2]
+ &and ($tmp,0xFF);
+ &mov ($tmp,&DWP(0,$te,$tmp,8));
+ &and ($tmp,0x00ff0000);
+ &xor ($out,$tmp);
+
+ if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }##%ecx
+ elsif($i==2){ &movz ($tmp,&HB($s[3])); }#%ebx[2]
+ else { &mov ($tmp,$s[3]);
+ &shr ($tmp,24); }
+ &mov ($tmp,&DWP(2,$te,$tmp,8));
+ &and ($tmp,0xff000000);
+ &xor ($out,$tmp);
+ if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); }
+ if ($i==3) { &mov ($s[3],$acc); }
+}
+
+&function_begin_B("_x86_AES_encrypt");
+ if ($vertical_spin) {
+ # I need high parts of volatile registers to be accessible...
+ &exch ($s1="edi",$key="ebx");
+ &mov ($s2="esi",$acc="ecx");
+ }
+
+ # note that caller is expected to allocate stack frame for me!
+ &mov ($__key,$key); # save key
+
+ &xor ($s0,&DWP(0,$key)); # xor with key
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &mov ($acc,&DWP(240,$key)); # load key->rounds
+
+ if ($small_footprint) {
+ &lea ($acc,&DWP(-2,$acc,$acc));
+ &lea ($acc,&DWP(0,$key,$acc,8));
+ &mov ($__end,$acc); # end of key schedule
+
+ &set_label("loop",16);
+ if ($vertical_spin) {
+ &encvert($tbl,$s0,$s1,$s2,$s3);
+ } else {
+ &encstep(0,$tbl,$s0,$s1,$s2,$s3);
+ &encstep(1,$tbl,$s1,$s2,$s3,$s0);
+ &encstep(2,$tbl,$s2,$s3,$s0,$s1);
+ &encstep(3,$tbl,$s3,$s0,$s1,$s2);
+ }
+ &add ($key,16); # advance rd_key
+ &xor ($s0,&DWP(0,$key));
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+ &cmp ($key,$__end);
+ &mov ($__key,$key);
+ &jb (&label("loop"));
+ }
+ else {
+ &cmp ($acc,10);
+ &jle (&label("10rounds"));
+ &cmp ($acc,12);
+ &jle (&label("12rounds"));
+
+ &set_label("14rounds",4);
+ for ($i=1;$i<3;$i++) {
+ if ($vertical_spin) {
+ &encvert($tbl,$s0,$s1,$s2,$s3);
+ } else {
+ &encstep(0,$tbl,$s0,$s1,$s2,$s3);
+ &encstep(1,$tbl,$s1,$s2,$s3,$s0);
+ &encstep(2,$tbl,$s2,$s3,$s0,$s1);
+ &encstep(3,$tbl,$s3,$s0,$s1,$s2);
+ }
+ &xor ($s0,&DWP(16*$i+0,$key));
+ &xor ($s1,&DWP(16*$i+4,$key));
+ &xor ($s2,&DWP(16*$i+8,$key));
+ &xor ($s3,&DWP(16*$i+12,$key));
+ }
+ &add ($key,32);
+ &mov ($__key,$key); # advance rd_key
+ &set_label("12rounds",4);
+ for ($i=1;$i<3;$i++) {
+ if ($vertical_spin) {
+ &encvert($tbl,$s0,$s1,$s2,$s3);
+ } else {
+ &encstep(0,$tbl,$s0,$s1,$s2,$s3);
+ &encstep(1,$tbl,$s1,$s2,$s3,$s0);
+ &encstep(2,$tbl,$s2,$s3,$s0,$s1);
+ &encstep(3,$tbl,$s3,$s0,$s1,$s2);
+ }
+ &xor ($s0,&DWP(16*$i+0,$key));
+ &xor ($s1,&DWP(16*$i+4,$key));
+ &xor ($s2,&DWP(16*$i+8,$key));
+ &xor ($s3,&DWP(16*$i+12,$key));
+ }
+ &add ($key,32);
+ &mov ($__key,$key); # advance rd_key
+ &set_label("10rounds",4);
+ for ($i=1;$i<10;$i++) {
+ if ($vertical_spin) {
+ &encvert($tbl,$s0,$s1,$s2,$s3);
+ } else {
+ &encstep(0,$tbl,$s0,$s1,$s2,$s3);
+ &encstep(1,$tbl,$s1,$s2,$s3,$s0);
+ &encstep(2,$tbl,$s2,$s3,$s0,$s1);
+ &encstep(3,$tbl,$s3,$s0,$s1,$s2);
+ }
+ &xor ($s0,&DWP(16*$i+0,$key));
+ &xor ($s1,&DWP(16*$i+4,$key));
+ &xor ($s2,&DWP(16*$i+8,$key));
+ &xor ($s3,&DWP(16*$i+12,$key));
+ }
+ }
+
+ if ($vertical_spin) {
+ # "reincarnate" some registers for "horizontal" spin...
+ &mov ($s1="ebx",$key="edi");
+ &mov ($s2="ecx",$acc="esi");
+ }
+ &enclast(0,$tbl,$s0,$s1,$s2,$s3);
+ &enclast(1,$tbl,$s1,$s2,$s3,$s0);
+ &enclast(2,$tbl,$s2,$s3,$s0,$s1);
+ &enclast(3,$tbl,$s3,$s0,$s1,$s2);
+
+ &add ($key,$small_footprint?16:160);
+ &xor ($s0,&DWP(0,$key));
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &ret ();
+
+&set_label("AES_Te",64); # Yes! I keep it in the code segment!
+ &_data_word(0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6);
+ &_data_word(0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591);
+ &_data_word(0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56);
+ &_data_word(0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec);
+ &_data_word(0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa);
+ &_data_word(0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb);
+ &_data_word(0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45);
+ &_data_word(0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b);
+ &_data_word(0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c);
+ &_data_word(0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83);
+ &_data_word(0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9);
+ &_data_word(0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a);
+ &_data_word(0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d);
+ &_data_word(0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f);
+ &_data_word(0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df);
+ &_data_word(0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea);
+ &_data_word(0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34);
+ &_data_word(0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b);
+ &_data_word(0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d);
+ &_data_word(0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413);
+ &_data_word(0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1);
+ &_data_word(0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6);
+ &_data_word(0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972);
+ &_data_word(0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85);
+ &_data_word(0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed);
+ &_data_word(0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511);
+ &_data_word(0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe);
+ &_data_word(0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b);
+ &_data_word(0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05);
+ &_data_word(0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1);
+ &_data_word(0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142);
+ &_data_word(0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf);
+ &_data_word(0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3);
+ &_data_word(0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e);
+ &_data_word(0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a);
+ &_data_word(0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6);
+ &_data_word(0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3);
+ &_data_word(0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b);
+ &_data_word(0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428);
+ &_data_word(0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad);
+ &_data_word(0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14);
+ &_data_word(0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8);
+ &_data_word(0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4);
+ &_data_word(0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2);
+ &_data_word(0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda);
+ &_data_word(0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949);
+ &_data_word(0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf);
+ &_data_word(0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810);
+ &_data_word(0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c);
+ &_data_word(0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697);
+ &_data_word(0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e);
+ &_data_word(0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f);
+ &_data_word(0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc);
+ &_data_word(0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c);
+ &_data_word(0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969);
+ &_data_word(0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27);
+ &_data_word(0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122);
+ &_data_word(0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433);
+ &_data_word(0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9);
+ &_data_word(0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5);
+ &_data_word(0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a);
+ &_data_word(0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0);
+ &_data_word(0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e);
+ &_data_word(0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c);
+
+#Te4 # four copies of Te4 to choose from to avoid L1 aliasing
+ &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+ &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+ &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+ &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+ &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+ &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+ &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+ &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+ &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+ &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+ &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+ &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+ &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+ &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+ &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+ &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+ &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+ &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+ &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+ &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+ &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+ &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+ &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+ &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+ &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+ &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+ &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+ &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+ &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+ &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+ &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+ &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+
+ &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+ &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+ &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+ &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+ &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+ &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+ &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+ &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+ &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+ &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+ &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+ &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+ &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+ &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+ &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+ &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+ &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+ &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+ &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+ &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+ &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+ &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+ &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+ &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+ &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+ &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+ &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+ &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+ &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+ &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+ &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+ &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+
+ &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+ &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+ &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+ &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+ &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+ &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+ &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+ &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+ &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+ &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+ &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+ &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+ &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+ &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+ &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+ &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+ &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+ &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+ &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+ &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+ &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+ &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+ &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+ &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+ &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+ &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+ &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+ &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+ &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+ &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+ &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+ &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+
+ &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+ &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+ &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+ &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+ &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+ &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+ &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+ &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+ &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+ &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+ &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+ &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+ &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+ &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+ &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+ &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+ &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+ &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+ &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+ &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+ &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+ &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+ &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+ &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+ &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+ &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+ &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+ &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+ &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+ &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+ &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+ &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+#rcon:
+ &data_word(0x00000001, 0x00000002, 0x00000004, 0x00000008);
+ &data_word(0x00000010, 0x00000020, 0x00000040, 0x00000080);
+ &data_word(0x0000001b, 0x00000036, 0x00000000, 0x00000000);
+ &data_word(0x00000000, 0x00000000, 0x00000000, 0x00000000);
+&function_end_B("_x86_AES_encrypt");
+
+# void AES_encrypt (const void *inp,void *out,const AES_KEY *key);
+&function_begin("AES_encrypt");
+ &mov ($acc,&wparam(0)); # load inp
+ &mov ($key,&wparam(2)); # load key
+
+ &mov ($s0,"esp");
+ &sub ("esp",36);
+ &and ("esp",-64); # align to cache-line
+
+ # place stack frame just "above" the key schedule
+ &lea ($s1,&DWP(-64-63,$key));
+ &sub ($s1,"esp");
+ &neg ($s1);
+ &and ($s1,0x3C0); # modulo 1024, but aligned to cache-line
+ &sub ("esp",$s1);
+ &add ("esp",4); # 4 is reserved for caller's return address
+ &mov ($_esp,$s0); # save stack pointer
+
+ &call (&label("pic_point")); # make it PIC!
+ &set_label("pic_point");
+ &blindpop($tbl);
+ &picmeup($s0,"OPENSSL_ia32cap_P",$tbl,&label("pic_point")) if (!$x86only);
+ &lea ($tbl,&DWP(&label("AES_Te")."-".&label("pic_point"),$tbl));
+
+ # pick Te4 copy which can't "overlap" with stack frame or key schedule
+ &lea ($s1,&DWP(768-4,"esp"));
+ &sub ($s1,$tbl);
+ &and ($s1,0x300);
+ &lea ($tbl,&DWP(2048+128,$tbl,$s1));
+
+ if (!$x86only) {
+ &bt (&DWP(0,$s0),25); # check for SSE bit
+ &jnc (&label("x86"));
+
+ &movq ("mm0",&QWP(0,$acc));
+ &movq ("mm4",&QWP(8,$acc));
+ &call ("_sse_AES_encrypt_compact");
+ &mov ("esp",$_esp); # restore stack pointer
+ &mov ($acc,&wparam(1)); # load out
+ &movq (&QWP(0,$acc),"mm0"); # write output data
+ &movq (&QWP(8,$acc),"mm4");
+ &emms ();
+ &function_end_A();
+ }
+ &set_label("x86",16);
+ &mov ($_tbl,$tbl);
+ &mov ($s0,&DWP(0,$acc)); # load input data
+ &mov ($s1,&DWP(4,$acc));
+ &mov ($s2,&DWP(8,$acc));
+ &mov ($s3,&DWP(12,$acc));
+ &call ("_x86_AES_encrypt_compact");
+ &mov ("esp",$_esp); # restore stack pointer
+ &mov ($acc,&wparam(1)); # load out
+ &mov (&DWP(0,$acc),$s0); # write output data
+ &mov (&DWP(4,$acc),$s1);
+ &mov (&DWP(8,$acc),$s2);
+ &mov (&DWP(12,$acc),$s3);
+&function_end("AES_encrypt");
+
+#--------------------------------------------------------------------#
+
+######################################################################
+# "Compact" block function
+######################################################################
+
+sub deccompact()
+{ my $Fn = \&mov;
+ while ($#_>5) { pop(@_); $Fn=sub{}; }
+ my ($i,$td,@s)=@_;
+ my $tmp = $key;
+ my $out = $i==3?$s[0]:$acc;
+
+ # $Fn is used in first compact round and its purpose is to
+ # void restoration of some values from stack, so that after
+ # 4xdeccompact with extra argument $key, $s0 and $s1 values
+ # are left there...
+ if($i==3) { &$Fn ($key,$__key); }
+ else { &mov ($out,$s[0]); }
+ &and ($out,0xFF);
+ &movz ($out,&BP(-128,$td,$out,1));
+
+ if ($i==3) { $tmp=$s[1]; }
+ &movz ($tmp,&HB($s[1]));
+ &movz ($tmp,&BP(-128,$td,$tmp,1));
+ &shl ($tmp,8);
+ &xor ($out,$tmp);
+
+ if ($i==3) { $tmp=$s[2]; &mov ($s[1],$acc); }
+ else { mov ($tmp,$s[2]); }
+ &shr ($tmp,16);
+ &and ($tmp,0xFF);
+ &movz ($tmp,&BP(-128,$td,$tmp,1));
+ &shl ($tmp,16);
+ &xor ($out,$tmp);
+
+ if ($i==3) { $tmp=$s[3]; &$Fn ($s[2],$__s1); }
+ else { &mov ($tmp,$s[3]); }
+ &shr ($tmp,24);
+ &movz ($tmp,&BP(-128,$td,$tmp,1));
+ &shl ($tmp,24);
+ &xor ($out,$tmp);
+ if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); }
+ if ($i==3) { &$Fn ($s[3],$__s0); }
+}
+
+# must be called with 2,3,0,1 as argument sequence!!!
+sub dectransform()
+{ my @s = ($s0,$s1,$s2,$s3);
+ my $i = shift;
+ my $tmp = $key;
+ my $tp2 = @s[($i+2)%4]; $tp2 = @s[2] if ($i==1);
+ my $tp4 = @s[($i+3)%4]; $tp4 = @s[3] if ($i==1);
+ my $tp8 = $tbl;
+
+ &mov ($tmp,0x80808080);
+ &and ($tmp,$s[$i]);
+ &mov ($acc,$tmp);
+ &shr ($tmp,7);
+ &lea ($tp2,&DWP(0,$s[$i],$s[$i]));
+ &sub ($acc,$tmp);
+ &and ($tp2,0xfefefefe);
+ &and ($acc,0x1b1b1b1b);
+ &xor ($tp2,$acc);
+ &mov ($tmp,0x80808080);
+
+ &and ($tmp,$tp2);
+ &mov ($acc,$tmp);
+ &shr ($tmp,7);
+ &lea ($tp4,&DWP(0,$tp2,$tp2));
+ &sub ($acc,$tmp);
+ &and ($tp4,0xfefefefe);
+ &and ($acc,0x1b1b1b1b);
+ &xor ($tp2,$s[$i]); # tp2^tp1
+ &xor ($tp4,$acc);
+ &mov ($tmp,0x80808080);
+
+ &and ($tmp,$tp4);
+ &mov ($acc,$tmp);
+ &shr ($tmp,7);
+ &lea ($tp8,&DWP(0,$tp4,$tp4));
+ &sub ($acc,$tmp);
+ &and ($tp8,0xfefefefe);
+ &and ($acc,0x1b1b1b1b);
+ &xor ($tp4,$s[$i]); # tp4^tp1
+ &rotl ($s[$i],8); # = ROTATE(tp1,8)
+ &xor ($tp8,$acc);
+
+ &xor ($s[$i],$tp2);
+ &xor ($tp2,$tp8);
+ &xor ($s[$i],$tp4);
+ &xor ($tp4,$tp8);
+ &rotl ($tp2,24);
+ &xor ($s[$i],$tp8); # ^= tp8^(tp4^tp1)^(tp2^tp1)
+ &rotl ($tp4,16);
+ &xor ($s[$i],$tp2); # ^= ROTATE(tp8^tp2^tp1,24)
+ &rotl ($tp8,8);
+ &xor ($s[$i],$tp4); # ^= ROTATE(tp8^tp4^tp1,16)
+ &mov ($s[0],$__s0) if($i==2); #prefetch $s0
+ &mov ($s[1],$__s1) if($i==3); #prefetch $s1
+ &mov ($s[2],$__s2) if($i==1);
+ &xor ($s[$i],$tp8); # ^= ROTATE(tp8,8)
+
+ &mov ($s[3],$__s3) if($i==1);
+ &mov (&DWP(4+4*$i,"esp"),$s[$i]) if($i>=2);
+}
+
+&function_begin_B("_x86_AES_decrypt_compact");
+ # note that caller is expected to allocate stack frame for me!
+ &mov ($__key,$key); # save key
+
+ &xor ($s0,&DWP(0,$key)); # xor with key
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &mov ($acc,&DWP(240,$key)); # load key->rounds
+
+ &lea ($acc,&DWP(-2,$acc,$acc));
+ &lea ($acc,&DWP(0,$key,$acc,8));
+ &mov ($__end,$acc); # end of key schedule
+
+ # prefetch Td4
+ &mov ($key,&DWP(0-128,$tbl));
+ &mov ($acc,&DWP(32-128,$tbl));
+ &mov ($key,&DWP(64-128,$tbl));
+ &mov ($acc,&DWP(96-128,$tbl));
+ &mov ($key,&DWP(128-128,$tbl));
+ &mov ($acc,&DWP(160-128,$tbl));
+ &mov ($key,&DWP(192-128,$tbl));
+ &mov ($acc,&DWP(224-128,$tbl));
+
+ &set_label("loop",16);
+
+ &deccompact(0,$tbl,$s0,$s3,$s2,$s1,1);
+ &deccompact(1,$tbl,$s1,$s0,$s3,$s2,1);
+ &deccompact(2,$tbl,$s2,$s1,$s0,$s3,1);
+ &deccompact(3,$tbl,$s3,$s2,$s1,$s0,1);
+ &dectransform(2);
+ &dectransform(3);
+ &dectransform(0);
+ &dectransform(1);
+ &mov ($key,$__key);
+ &mov ($tbl,$__tbl);
+ &add ($key,16); # advance rd_key
+ &xor ($s0,&DWP(0,$key));
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &cmp ($key,$__end);
+ &mov ($__key,$key);
+ &jb (&label("loop"));
+
+ &deccompact(0,$tbl,$s0,$s3,$s2,$s1);
+ &deccompact(1,$tbl,$s1,$s0,$s3,$s2);
+ &deccompact(2,$tbl,$s2,$s1,$s0,$s3);
+ &deccompact(3,$tbl,$s3,$s2,$s1,$s0);
+
+ &xor ($s0,&DWP(16,$key));
+ &xor ($s1,&DWP(20,$key));
+ &xor ($s2,&DWP(24,$key));
+ &xor ($s3,&DWP(28,$key));
+
+ &ret ();
+&function_end_B("_x86_AES_decrypt_compact");
+
+######################################################################
+# "Compact" SSE block function.
+######################################################################
+
+sub sse_deccompact()
+{
+ &pshufw ("mm1","mm0",0x0c); # 7, 6, 1, 0
+ &pshufw ("mm5","mm4",0x09); # 13,12,11,10
+ &movd ("eax","mm1"); # 7, 6, 1, 0
+ &movd ("ebx","mm5"); # 13,12,11,10
+ &mov ($__key,$key);
+
+ &movz ($acc,&LB("eax")); # 0
+ &movz ("edx",&HB("eax")); # 1
+ &pshufw ("mm2","mm0",0x06); # 3, 2, 5, 4
+ &movz ("ecx",&BP(-128,$tbl,$acc,1)); # 0
+ &movz ($key,&LB("ebx")); # 10
+ &movz ("edx",&BP(-128,$tbl,"edx",1)); # 1
+ &shr ("eax",16); # 7, 6
+ &shl ("edx",8); # 1
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 10
+ &movz ($key,&HB("ebx")); # 11
+ &shl ($acc,16); # 10
+ &pshufw ("mm6","mm4",0x03); # 9, 8,15,14
+ &or ("ecx",$acc); # 10
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 11
+ &movz ($key,&HB("eax")); # 7
+ &shl ($acc,24); # 11
+ &shr ("ebx",16); # 13,12
+ &or ("edx",$acc); # 11
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 7
+ &movz ($key,&HB("ebx")); # 13
+ &shl ($acc,24); # 7
+ &or ("ecx",$acc); # 7
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 13
+ &movz ($key,&LB("eax")); # 6
+ &shl ($acc,8); # 13
+ &movd ("eax","mm2"); # 3, 2, 5, 4
+ &or ("ecx",$acc); # 13
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 6
+ &movz ($key,&LB("ebx")); # 12
+ &shl ($acc,16); # 6
+ &movd ("ebx","mm6"); # 9, 8,15,14
+ &movd ("mm0","ecx"); # t[0] collected
+ &movz ("ecx",&BP(-128,$tbl,$key,1)); # 12
+ &movz ($key,&LB("eax")); # 4
+ &or ("ecx",$acc); # 12
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 4
+ &movz ($key,&LB("ebx")); # 14
+ &or ("edx",$acc); # 4
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 14
+ &movz ($key,&HB("eax")); # 5
+ &shl ($acc,16); # 14
+ &shr ("eax",16); # 3, 2
+ &or ("edx",$acc); # 14
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 5
+ &movz ($key,&HB("ebx")); # 15
+ &shr ("ebx",16); # 9, 8
+ &shl ($acc,8); # 5
+ &movd ("mm1","edx"); # t[1] collected
+ &movz ("edx",&BP(-128,$tbl,$key,1)); # 15
+ &movz ($key,&HB("ebx")); # 9
+ &shl ("edx",24); # 15
+ &and ("ebx",0xff); # 8
+ &or ("edx",$acc); # 15
+
+ &punpckldq ("mm0","mm1"); # t[0,1] collected
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 9
+ &movz ($key,&LB("eax")); # 2
+ &shl ($acc,8); # 9
+ &movz ("eax",&HB("eax")); # 3
+ &movz ("ebx",&BP(-128,$tbl,"ebx",1)); # 8
+ &or ("ecx",$acc); # 9
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 2
+ &or ("edx","ebx"); # 8
+ &shl ($acc,16); # 2
+ &movz ("eax",&BP(-128,$tbl,"eax",1)); # 3
+ &or ("edx",$acc); # 2
+ &shl ("eax",24); # 3
+ &or ("ecx","eax"); # 3
+ &mov ($key,$__key);
+ &movd ("mm4","edx"); # t[2] collected
+ &movd ("mm5","ecx"); # t[3] collected
+
+ &punpckldq ("mm4","mm5"); # t[2,3] collected
+}
+
+ if (!$x86only) {
+&function_begin_B("_sse_AES_decrypt_compact");
+ &pxor ("mm0",&QWP(0,$key)); # 7, 6, 5, 4, 3, 2, 1, 0
+ &pxor ("mm4",&QWP(8,$key)); # 15,14,13,12,11,10, 9, 8
+
+ # note that caller is expected to allocate stack frame for me!
+ &mov ($acc,&DWP(240,$key)); # load key->rounds
+ &lea ($acc,&DWP(-2,$acc,$acc));
+ &lea ($acc,&DWP(0,$key,$acc,8));
+ &mov ($__end,$acc); # end of key schedule
+
+ &mov ($s0,0x1b1b1b1b); # magic constant
+ &mov (&DWP(8,"esp"),$s0);
+ &mov (&DWP(12,"esp"),$s0);
+
+ # prefetch Td4
+ &mov ($s0,&DWP(0-128,$tbl));
+ &mov ($s1,&DWP(32-128,$tbl));
+ &mov ($s2,&DWP(64-128,$tbl));
+ &mov ($s3,&DWP(96-128,$tbl));
+ &mov ($s0,&DWP(128-128,$tbl));
+ &mov ($s1,&DWP(160-128,$tbl));
+ &mov ($s2,&DWP(192-128,$tbl));
+ &mov ($s3,&DWP(224-128,$tbl));
+
+ &set_label("loop",16);
+ &sse_deccompact();
+ &add ($key,16);
+ &cmp ($key,$__end);
+ &ja (&label("out"));
+
+ # ROTATE(x^y,N) == ROTATE(x,N)^ROTATE(y,N)
+ &movq ("mm3","mm0"); &movq ("mm7","mm4");
+ &movq ("mm2","mm0",1); &movq ("mm6","mm4",1);
+ &movq ("mm1","mm0"); &movq ("mm5","mm4");
+ &pshufw ("mm0","mm0",0xb1); &pshufw ("mm4","mm4",0xb1);# = ROTATE(tp0,16)
+ &pslld ("mm2",8); &pslld ("mm6",8);
+ &psrld ("mm3",8); &psrld ("mm7",8);
+ &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= tp0<<8
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp0>>8
+ &pslld ("mm2",16); &pslld ("mm6",16);
+ &psrld ("mm3",16); &psrld ("mm7",16);
+ &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= tp0<<24
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp0>>24
+
+ &movq ("mm3",&QWP(8,"esp"));
+ &pxor ("mm2","mm2"); &pxor ("mm6","mm6");
+ &pcmpgtb("mm2","mm1"); &pcmpgtb("mm6","mm5");
+ &pand ("mm2","mm3"); &pand ("mm6","mm3");
+ &paddb ("mm1","mm1"); &paddb ("mm5","mm5");
+ &pxor ("mm1","mm2"); &pxor ("mm5","mm6"); # tp2
+ &movq ("mm3","mm1"); &movq ("mm7","mm5");
+ &movq ("mm2","mm1"); &movq ("mm6","mm5");
+ &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp2
+ &pslld ("mm3",24); &pslld ("mm7",24);
+ &psrld ("mm2",8); &psrld ("mm6",8);
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp2<<24
+ &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= tp2>>8
+
+ &movq ("mm2",&QWP(8,"esp"));
+ &pxor ("mm3","mm3"); &pxor ("mm7","mm7");
+ &pcmpgtb("mm3","mm1"); &pcmpgtb("mm7","mm5");
+ &pand ("mm3","mm2"); &pand ("mm7","mm2");
+ &paddb ("mm1","mm1"); &paddb ("mm5","mm5");
+ &pxor ("mm1","mm3"); &pxor ("mm5","mm7"); # tp4
+ &pshufw ("mm3","mm1",0xb1); &pshufw ("mm7","mm5",0xb1);
+ &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp4
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= ROTATE(tp4,16)
+
+ &pxor ("mm3","mm3"); &pxor ("mm7","mm7");
+ &pcmpgtb("mm3","mm1"); &pcmpgtb("mm7","mm5");
+ &pand ("mm3","mm2"); &pand ("mm7","mm2");
+ &paddb ("mm1","mm1"); &paddb ("mm5","mm5");
+ &pxor ("mm1","mm3"); &pxor ("mm5","mm7"); # tp8
+ &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp8
+ &movq ("mm3","mm1"); &movq ("mm7","mm5");
+ &pshufw ("mm2","mm1",0xb1); &pshufw ("mm6","mm5",0xb1);
+ &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= ROTATE(tp8,16)
+ &pslld ("mm1",8); &pslld ("mm5",8);
+ &psrld ("mm3",8); &psrld ("mm7",8);
+ &movq ("mm2",&QWP(0,$key)); &movq ("mm6",&QWP(8,$key));
+ &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp8<<8
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp8>>8
+ &mov ($s0,&DWP(0-128,$tbl));
+ &pslld ("mm1",16); &pslld ("mm5",16);
+ &mov ($s1,&DWP(64-128,$tbl));
+ &psrld ("mm3",16); &psrld ("mm7",16);
+ &mov ($s2,&DWP(128-128,$tbl));
+ &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp8<<24
+ &mov ($s3,&DWP(192-128,$tbl));
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp8>>24
+
+ &pxor ("mm0","mm2"); &pxor ("mm4","mm6");
+ &jmp (&label("loop"));
+
+ &set_label("out",16);
+ &pxor ("mm0",&QWP(0,$key));
+ &pxor ("mm4",&QWP(8,$key));
+
+ &ret ();
+&function_end_B("_sse_AES_decrypt_compact");
+ }
+
+######################################################################
+# Vanilla block function.
+######################################################################
+
+sub decstep()
+{ my ($i,$td,@s) = @_;
+ my $tmp = $key;
+ my $out = $i==3?$s[0]:$acc;
+
+ # no instructions are reordered, as performance appears
+ # optimal... or rather that all attempts to reorder didn't
+ # result in better performance [which by the way is not a
+ # bit lower than encryption].
+ if($i==3) { &mov ($key,$__key); }
+ else { &mov ($out,$s[0]); }
+ &and ($out,0xFF);
+ &mov ($out,&DWP(0,$td,$out,8));
+
+ if ($i==3) { $tmp=$s[1]; }
+ &movz ($tmp,&HB($s[1]));
+ &xor ($out,&DWP(3,$td,$tmp,8));
+
+ if ($i==3) { $tmp=$s[2]; &mov ($s[1],$acc); }
+ else { &mov ($tmp,$s[2]); }
+ &shr ($tmp,16);
+ &and ($tmp,0xFF);
+ &xor ($out,&DWP(2,$td,$tmp,8));
+
+ if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }
+ else { &mov ($tmp,$s[3]); }
+ &shr ($tmp,24);
+ &xor ($out,&DWP(1,$td,$tmp,8));
+ if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); }
+ if ($i==3) { &mov ($s[3],$__s0); }
+ &comment();
+}
+
+sub declast()
+{ my ($i,$td,@s)=@_;
+ my $tmp = $key;
+ my $out = $i==3?$s[0]:$acc;
+
+ if($i==0) { &lea ($td,&DWP(2048+128,$td));
+ &mov ($tmp,&DWP(0-128,$td));
+ &mov ($acc,&DWP(32-128,$td));
+ &mov ($tmp,&DWP(64-128,$td));
+ &mov ($acc,&DWP(96-128,$td));
+ &mov ($tmp,&DWP(128-128,$td));
+ &mov ($acc,&DWP(160-128,$td));
+ &mov ($tmp,&DWP(192-128,$td));
+ &mov ($acc,&DWP(224-128,$td));
+ &lea ($td,&DWP(-128,$td)); }
+ if($i==3) { &mov ($key,$__key); }
+ else { &mov ($out,$s[0]); }
+ &and ($out,0xFF);
+ &movz ($out,&BP(0,$td,$out,1));
+
+ if ($i==3) { $tmp=$s[1]; }
+ &movz ($tmp,&HB($s[1]));
+ &movz ($tmp,&BP(0,$td,$tmp,1));
+ &shl ($tmp,8);
+ &xor ($out,$tmp);
+
+ if ($i==3) { $tmp=$s[2]; &mov ($s[1],$acc); }
+ else { mov ($tmp,$s[2]); }
+ &shr ($tmp,16);
+ &and ($tmp,0xFF);
+ &movz ($tmp,&BP(0,$td,$tmp,1));
+ &shl ($tmp,16);
+ &xor ($out,$tmp);
+
+ if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }
+ else { &mov ($tmp,$s[3]); }
+ &shr ($tmp,24);
+ &movz ($tmp,&BP(0,$td,$tmp,1));
+ &shl ($tmp,24);
+ &xor ($out,$tmp);
+ if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); }
+ if ($i==3) { &mov ($s[3],$__s0);
+ &lea ($td,&DWP(-2048,$td)); }
+}
+
+&function_begin_B("_x86_AES_decrypt");
+ # note that caller is expected to allocate stack frame for me!
+ &mov ($__key,$key); # save key
+
+ &xor ($s0,&DWP(0,$key)); # xor with key
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &mov ($acc,&DWP(240,$key)); # load key->rounds
+
+ if ($small_footprint) {
+ &lea ($acc,&DWP(-2,$acc,$acc));
+ &lea ($acc,&DWP(0,$key,$acc,8));
+ &mov ($__end,$acc); # end of key schedule
+ &set_label("loop",16);
+ &decstep(0,$tbl,$s0,$s3,$s2,$s1);
+ &decstep(1,$tbl,$s1,$s0,$s3,$s2);
+ &decstep(2,$tbl,$s2,$s1,$s0,$s3);
+ &decstep(3,$tbl,$s3,$s2,$s1,$s0);
+ &add ($key,16); # advance rd_key
+ &xor ($s0,&DWP(0,$key));
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+ &cmp ($key,$__end);
+ &mov ($__key,$key);
+ &jb (&label("loop"));
+ }
+ else {
+ &cmp ($acc,10);
+ &jle (&label("10rounds"));
+ &cmp ($acc,12);
+ &jle (&label("12rounds"));
+
+ &set_label("14rounds",4);
+ for ($i=1;$i<3;$i++) {
+ &decstep(0,$tbl,$s0,$s3,$s2,$s1);
+ &decstep(1,$tbl,$s1,$s0,$s3,$s2);
+ &decstep(2,$tbl,$s2,$s1,$s0,$s3);
+ &decstep(3,$tbl,$s3,$s2,$s1,$s0);
+ &xor ($s0,&DWP(16*$i+0,$key));
+ &xor ($s1,&DWP(16*$i+4,$key));
+ &xor ($s2,&DWP(16*$i+8,$key));
+ &xor ($s3,&DWP(16*$i+12,$key));
+ }
+ &add ($key,32);
+ &mov ($__key,$key); # advance rd_key
+ &set_label("12rounds",4);
+ for ($i=1;$i<3;$i++) {
+ &decstep(0,$tbl,$s0,$s3,$s2,$s1);
+ &decstep(1,$tbl,$s1,$s0,$s3,$s2);
+ &decstep(2,$tbl,$s2,$s1,$s0,$s3);
+ &decstep(3,$tbl,$s3,$s2,$s1,$s0);
+ &xor ($s0,&DWP(16*$i+0,$key));
+ &xor ($s1,&DWP(16*$i+4,$key));
+ &xor ($s2,&DWP(16*$i+8,$key));
+ &xor ($s3,&DWP(16*$i+12,$key));
+ }
+ &add ($key,32);
+ &mov ($__key,$key); # advance rd_key
+ &set_label("10rounds",4);
+ for ($i=1;$i<10;$i++) {
+ &decstep(0,$tbl,$s0,$s3,$s2,$s1);
+ &decstep(1,$tbl,$s1,$s0,$s3,$s2);
+ &decstep(2,$tbl,$s2,$s1,$s0,$s3);
+ &decstep(3,$tbl,$s3,$s2,$s1,$s0);
+ &xor ($s0,&DWP(16*$i+0,$key));
+ &xor ($s1,&DWP(16*$i+4,$key));
+ &xor ($s2,&DWP(16*$i+8,$key));
+ &xor ($s3,&DWP(16*$i+12,$key));
+ }
+ }
+
+ &declast(0,$tbl,$s0,$s3,$s2,$s1);
+ &declast(1,$tbl,$s1,$s0,$s3,$s2);
+ &declast(2,$tbl,$s2,$s1,$s0,$s3);
+ &declast(3,$tbl,$s3,$s2,$s1,$s0);
+
+ &add ($key,$small_footprint?16:160);
+ &xor ($s0,&DWP(0,$key));
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &ret ();
+
+&set_label("AES_Td",64); # Yes! I keep it in the code segment!
+ &_data_word(0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a);
+ &_data_word(0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b);
+ &_data_word(0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5);
+ &_data_word(0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5);
+ &_data_word(0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d);
+ &_data_word(0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b);
+ &_data_word(0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295);
+ &_data_word(0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e);
+ &_data_word(0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927);
+ &_data_word(0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d);
+ &_data_word(0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362);
+ &_data_word(0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9);
+ &_data_word(0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52);
+ &_data_word(0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566);
+ &_data_word(0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3);
+ &_data_word(0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed);
+ &_data_word(0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e);
+ &_data_word(0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4);
+ &_data_word(0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4);
+ &_data_word(0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd);
+ &_data_word(0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d);
+ &_data_word(0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060);
+ &_data_word(0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967);
+ &_data_word(0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879);
+ &_data_word(0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000);
+ &_data_word(0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c);
+ &_data_word(0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36);
+ &_data_word(0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624);
+ &_data_word(0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b);
+ &_data_word(0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c);
+ &_data_word(0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12);
+ &_data_word(0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14);
+ &_data_word(0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3);
+ &_data_word(0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b);
+ &_data_word(0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8);
+ &_data_word(0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684);
+ &_data_word(0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7);
+ &_data_word(0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177);
+ &_data_word(0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947);
+ &_data_word(0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322);
+ &_data_word(0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498);
+ &_data_word(0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f);
+ &_data_word(0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54);
+ &_data_word(0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382);
+ &_data_word(0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf);
+ &_data_word(0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb);
+ &_data_word(0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83);
+ &_data_word(0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef);
+ &_data_word(0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029);
+ &_data_word(0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235);
+ &_data_word(0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733);
+ &_data_word(0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117);
+ &_data_word(0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4);
+ &_data_word(0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546);
+ &_data_word(0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb);
+ &_data_word(0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d);
+ &_data_word(0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb);
+ &_data_word(0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a);
+ &_data_word(0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773);
+ &_data_word(0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478);
+ &_data_word(0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2);
+ &_data_word(0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff);
+ &_data_word(0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664);
+ &_data_word(0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0);
+
+#Td4: # four copies of Td4 to choose from to avoid L1 aliasing
+ &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+ &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+ &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+ &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+ &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+ &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+ &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+ &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+ &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+ &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+ &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+ &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+ &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+ &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+ &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+ &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+ &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+ &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+ &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+ &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+ &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+ &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+ &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+ &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+ &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+ &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+ &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+ &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+ &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+ &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+ &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+ &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+
+ &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+ &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+ &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+ &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+ &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+ &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+ &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+ &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+ &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+ &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+ &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+ &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+ &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+ &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+ &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+ &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+ &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+ &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+ &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+ &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+ &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+ &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+ &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+ &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+ &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+ &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+ &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+ &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+ &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+ &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+ &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+ &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+
+ &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+ &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+ &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+ &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+ &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+ &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+ &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+ &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+ &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+ &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+ &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+ &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+ &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+ &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+ &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+ &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+ &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+ &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+ &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+ &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+ &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+ &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+ &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+ &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+ &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+ &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+ &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+ &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+ &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+ &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+ &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+ &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+
+ &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+ &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+ &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+ &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+ &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+ &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+ &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+ &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+ &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+ &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+ &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+ &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+ &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+ &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+ &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+ &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+ &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+ &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+ &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+ &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+ &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+ &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+ &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+ &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+ &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+ &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+ &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+ &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+ &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+ &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+ &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+ &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+&function_end_B("_x86_AES_decrypt");
+
+# void AES_decrypt (const void *inp,void *out,const AES_KEY *key);
+&function_begin("AES_decrypt");
+ &mov ($acc,&wparam(0)); # load inp
+ &mov ($key,&wparam(2)); # load key
+
+ &mov ($s0,"esp");
+ &sub ("esp",36);
+ &and ("esp",-64); # align to cache-line
+
+ # place stack frame just "above" the key schedule
+ &lea ($s1,&DWP(-64-63,$key));
+ &sub ($s1,"esp");
+ &neg ($s1);
+ &and ($s1,0x3C0); # modulo 1024, but aligned to cache-line
+ &sub ("esp",$s1);
+ &add ("esp",4); # 4 is reserved for caller's return address
+ &mov ($_esp,$s0); # save stack pointer
+
+ &call (&label("pic_point")); # make it PIC!
+ &set_label("pic_point");
+ &blindpop($tbl);
+ &picmeup($s0,"OPENSSL_ia32cap_P",$tbl,&label("pic_point")) if(!$x86only);
+ &lea ($tbl,&DWP(&label("AES_Td")."-".&label("pic_point"),$tbl));
+
+ # pick Td4 copy which can't "overlap" with stack frame or key schedule
+ &lea ($s1,&DWP(768-4,"esp"));
+ &sub ($s1,$tbl);
+ &and ($s1,0x300);
+ &lea ($tbl,&DWP(2048+128,$tbl,$s1));
+
+ if (!$x86only) {
+ &bt (&DWP(0,$s0),25); # check for SSE bit
+ &jnc (&label("x86"));
+
+ &movq ("mm0",&QWP(0,$acc));
+ &movq ("mm4",&QWP(8,$acc));
+ &call ("_sse_AES_decrypt_compact");
+ &mov ("esp",$_esp); # restore stack pointer
+ &mov ($acc,&wparam(1)); # load out
+ &movq (&QWP(0,$acc),"mm0"); # write output data
+ &movq (&QWP(8,$acc),"mm4");
+ &emms ();
+ &function_end_A();
+ }
+ &set_label("x86",16);
+ &mov ($_tbl,$tbl);
+ &mov ($s0,&DWP(0,$acc)); # load input data
+ &mov ($s1,&DWP(4,$acc));
+ &mov ($s2,&DWP(8,$acc));
+ &mov ($s3,&DWP(12,$acc));
+ &call ("_x86_AES_decrypt_compact");
+ &mov ("esp",$_esp); # restore stack pointer
+ &mov ($acc,&wparam(1)); # load out
+ &mov (&DWP(0,$acc),$s0); # write output data
+ &mov (&DWP(4,$acc),$s1);
+ &mov (&DWP(8,$acc),$s2);
+ &mov (&DWP(12,$acc),$s3);
+&function_end("AES_decrypt");
+
+# void AES_cbc_encrypt (const void char *inp, unsigned char *out,
+# size_t length, const AES_KEY *key,
+# unsigned char *ivp,const int enc);
+{
+# stack frame layout
+# -4(%esp) # return address 0(%esp)
+# 0(%esp) # s0 backing store 4(%esp)
+# 4(%esp) # s1 backing store 8(%esp)
+# 8(%esp) # s2 backing store 12(%esp)
+# 12(%esp) # s3 backing store 16(%esp)
+# 16(%esp) # key backup 20(%esp)
+# 20(%esp) # end of key schedule 24(%esp)
+# 24(%esp) # %ebp backup 28(%esp)
+# 28(%esp) # %esp backup
+my $_inp=&DWP(32,"esp"); # copy of wparam(0)
+my $_out=&DWP(36,"esp"); # copy of wparam(1)
+my $_len=&DWP(40,"esp"); # copy of wparam(2)
+my $_key=&DWP(44,"esp"); # copy of wparam(3)
+my $_ivp=&DWP(48,"esp"); # copy of wparam(4)
+my $_tmp=&DWP(52,"esp"); # volatile variable
+#
+my $ivec=&DWP(60,"esp"); # ivec[16]
+my $aes_key=&DWP(76,"esp"); # copy of aes_key
+my $mark=&DWP(76+240,"esp"); # copy of aes_key->rounds
+
+&function_begin("AES_cbc_encrypt");
+ &mov ($s2 eq "ecx"? $s2 : "",&wparam(2)); # load len
+ &cmp ($s2,0);
+ &je (&label("drop_out"));
+
+ &call (&label("pic_point")); # make it PIC!
+ &set_label("pic_point");
+ &blindpop($tbl);
+ &picmeup($s0,"OPENSSL_ia32cap_P",$tbl,&label("pic_point")) if(!$x86only);
+
+ &cmp (&wparam(5),0);
+ &lea ($tbl,&DWP(&label("AES_Te")."-".&label("pic_point"),$tbl));
+ &jne (&label("picked_te"));
+ &lea ($tbl,&DWP(&label("AES_Td")."-".&label("AES_Te"),$tbl));
+ &set_label("picked_te");
+
+ # one can argue if this is required
+ &pushf ();
+ &cld ();
+
+ &cmp ($s2,$speed_limit);
+ &jb (&label("slow_way"));
+ &test ($s2,15);
+ &jnz (&label("slow_way"));
+ if (!$x86only) {
+ &bt (&DWP(0,$s0),28); # check for hyper-threading bit
+ &jc (&label("slow_way"));
+ }
+ # pre-allocate aligned stack frame...
+ &lea ($acc,&DWP(-80-244,"esp"));
+ &and ($acc,-64);
+
+ # ... and make sure it doesn't alias with $tbl modulo 4096
+ &mov ($s0,$tbl);
+ &lea ($s1,&DWP(2048+256,$tbl));
+ &mov ($s3,$acc);
+ &and ($s0,0xfff); # s = %ebp&0xfff
+ &and ($s1,0xfff); # e = (%ebp+2048+256)&0xfff
+ &and ($s3,0xfff); # p = %esp&0xfff
+
+ &cmp ($s3,$s1); # if (p>=e) %esp =- (p-e);
+ &jb (&label("tbl_break_out"));
+ &sub ($s3,$s1);
+ &sub ($acc,$s3);
+ &jmp (&label("tbl_ok"));
+ &set_label("tbl_break_out",4); # else %esp -= (p-s)&0xfff + framesz;
+ &sub ($s3,$s0);
+ &and ($s3,0xfff);
+ &add ($s3,384);
+ &sub ($acc,$s3);
+ &set_label("tbl_ok",4);
+
+ &lea ($s3,&wparam(0)); # obtain pointer to parameter block
+ &exch ("esp",$acc); # allocate stack frame
+ &add ("esp",4); # reserve for return address!
+ &mov ($_tbl,$tbl); # save %ebp
+ &mov ($_esp,$acc); # save %esp
+
+ &mov ($s0,&DWP(0,$s3)); # load inp
+ &mov ($s1,&DWP(4,$s3)); # load out
+ #&mov ($s2,&DWP(8,$s3)); # load len
+ &mov ($key,&DWP(12,$s3)); # load key
+ &mov ($acc,&DWP(16,$s3)); # load ivp
+ &mov ($s3,&DWP(20,$s3)); # load enc flag
+
+ &mov ($_inp,$s0); # save copy of inp
+ &mov ($_out,$s1); # save copy of out
+ &mov ($_len,$s2); # save copy of len
+ &mov ($_key,$key); # save copy of key
+ &mov ($_ivp,$acc); # save copy of ivp
+
+ &mov ($mark,0); # copy of aes_key->rounds = 0;
+ # do we copy key schedule to stack?
+ &mov ($s1 eq "ebx" ? $s1 : "",$key);
+ &mov ($s2 eq "ecx" ? $s2 : "",244/4);
+ &sub ($s1,$tbl);
+ &mov ("esi",$key);
+ &and ($s1,0xfff);
+ &lea ("edi",$aes_key);
+ &cmp ($s1,2048+256);
+ &jb (&label("do_copy"));
+ &cmp ($s1,4096-244);
+ &jb (&label("skip_copy"));
+ &set_label("do_copy",4);
+ &mov ($_key,"edi");
+ &data_word(0xA5F3F689); # rep movsd
+ &set_label("skip_copy");
+
+ &mov ($key,16);
+ &set_label("prefetch_tbl",4);
+ &mov ($s0,&DWP(0,$tbl));
+ &mov ($s1,&DWP(32,$tbl));
+ &mov ($s2,&DWP(64,$tbl));
+ &mov ($acc,&DWP(96,$tbl));
+ &lea ($tbl,&DWP(128,$tbl));
+ &sub ($key,1);
+ &jnz (&label("prefetch_tbl"));
+ &sub ($tbl,2048);
+
+ &mov ($acc,$_inp);
+ &mov ($key,$_ivp);
+
+ &cmp ($s3,0);
+ &je (&label("fast_decrypt"));
+
+#----------------------------- ENCRYPT -----------------------------#
+ &mov ($s0,&DWP(0,$key)); # load iv
+ &mov ($s1,&DWP(4,$key));
+
+ &set_label("fast_enc_loop",16);
+ &mov ($s2,&DWP(8,$key));
+ &mov ($s3,&DWP(12,$key));
+
+ &xor ($s0,&DWP(0,$acc)); # xor input data
+ &xor ($s1,&DWP(4,$acc));
+ &xor ($s2,&DWP(8,$acc));
+ &xor ($s3,&DWP(12,$acc));
+
+ &mov ($key,$_key); # load key
+ &call ("_x86_AES_encrypt");
+
+ &mov ($acc,$_inp); # load inp
+ &mov ($key,$_out); # load out
+
+ &mov (&DWP(0,$key),$s0); # save output data
+ &mov (&DWP(4,$key),$s1);
+ &mov (&DWP(8,$key),$s2);
+ &mov (&DWP(12,$key),$s3);
+
+ &lea ($acc,&DWP(16,$acc)); # advance inp
+ &mov ($s2,$_len); # load len
+ &mov ($_inp,$acc); # save inp
+ &lea ($s3,&DWP(16,$key)); # advance out
+ &mov ($_out,$s3); # save out
+ &sub ($s2,16); # decrease len
+ &mov ($_len,$s2); # save len
+ &jnz (&label("fast_enc_loop"));
+ &mov ($acc,$_ivp); # load ivp
+ &mov ($s2,&DWP(8,$key)); # restore last 2 dwords
+ &mov ($s3,&DWP(12,$key));
+ &mov (&DWP(0,$acc),$s0); # save ivec
+ &mov (&DWP(4,$acc),$s1);
+ &mov (&DWP(8,$acc),$s2);
+ &mov (&DWP(12,$acc),$s3);
+
+ &cmp ($mark,0); # was the key schedule copied?
+ &mov ("edi",$_key);
+ &je (&label("skip_ezero"));
+ # zero copy of key schedule
+ &mov ("ecx",240/4);
+ &xor ("eax","eax");
+ &align (4);
+ &data_word(0xABF3F689); # rep stosd
+ &set_label("skip_ezero");
+ &mov ("esp",$_esp);
+ &popf ();
+ &set_label("drop_out");
+ &function_end_A();
+ &pushf (); # kludge, never executed
+
+#----------------------------- DECRYPT -----------------------------#
+&set_label("fast_decrypt",16);
+
+ &cmp ($acc,$_out);
+ &je (&label("fast_dec_in_place")); # in-place processing...
+
+ &mov ($_tmp,$key);
+
+ &align (4);
+ &set_label("fast_dec_loop",16);
+ &mov ($s0,&DWP(0,$acc)); # read input
+ &mov ($s1,&DWP(4,$acc));
+ &mov ($s2,&DWP(8,$acc));
+ &mov ($s3,&DWP(12,$acc));
+
+ &mov ($key,$_key); # load key
+ &call ("_x86_AES_decrypt");
+
+ &mov ($key,$_tmp); # load ivp
+ &mov ($acc,$_len); # load len
+ &xor ($s0,&DWP(0,$key)); # xor iv
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &mov ($key,$_out); # load out
+ &mov ($acc,$_inp); # load inp
+
+ &mov (&DWP(0,$key),$s0); # write output
+ &mov (&DWP(4,$key),$s1);
+ &mov (&DWP(8,$key),$s2);
+ &mov (&DWP(12,$key),$s3);
+
+ &mov ($s2,$_len); # load len
+ &mov ($_tmp,$acc); # save ivp
+ &lea ($acc,&DWP(16,$acc)); # advance inp
+ &mov ($_inp,$acc); # save inp
+ &lea ($key,&DWP(16,$key)); # advance out
+ &mov ($_out,$key); # save out
+ &sub ($s2,16); # decrease len
+ &mov ($_len,$s2); # save len
+ &jnz (&label("fast_dec_loop"));
+ &mov ($key,$_tmp); # load temp ivp
+ &mov ($acc,$_ivp); # load user ivp
+ &mov ($s0,&DWP(0,$key)); # load iv
+ &mov ($s1,&DWP(4,$key));
+ &mov ($s2,&DWP(8,$key));
+ &mov ($s3,&DWP(12,$key));
+ &mov (&DWP(0,$acc),$s0); # copy back to user
+ &mov (&DWP(4,$acc),$s1);
+ &mov (&DWP(8,$acc),$s2);
+ &mov (&DWP(12,$acc),$s3);
+ &jmp (&label("fast_dec_out"));
+
+ &set_label("fast_dec_in_place",16);
+ &set_label("fast_dec_in_place_loop");
+ &mov ($s0,&DWP(0,$acc)); # read input
+ &mov ($s1,&DWP(4,$acc));
+ &mov ($s2,&DWP(8,$acc));
+ &mov ($s3,&DWP(12,$acc));
+
+ &lea ($key,$ivec);
+ &mov (&DWP(0,$key),$s0); # copy to temp
+ &mov (&DWP(4,$key),$s1);
+ &mov (&DWP(8,$key),$s2);
+ &mov (&DWP(12,$key),$s3);
+
+ &mov ($key,$_key); # load key
+ &call ("_x86_AES_decrypt");
+
+ &mov ($key,$_ivp); # load ivp
+ &mov ($acc,$_out); # load out
+ &xor ($s0,&DWP(0,$key)); # xor iv
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &mov (&DWP(0,$acc),$s0); # write output
+ &mov (&DWP(4,$acc),$s1);
+ &mov (&DWP(8,$acc),$s2);
+ &mov (&DWP(12,$acc),$s3);
+
+ &lea ($acc,&DWP(16,$acc)); # advance out
+ &mov ($_out,$acc); # save out
+
+ &lea ($acc,$ivec);
+ &mov ($s0,&DWP(0,$acc)); # read temp
+ &mov ($s1,&DWP(4,$acc));
+ &mov ($s2,&DWP(8,$acc));
+ &mov ($s3,&DWP(12,$acc));
+
+ &mov (&DWP(0,$key),$s0); # copy iv
+ &mov (&DWP(4,$key),$s1);
+ &mov (&DWP(8,$key),$s2);
+ &mov (&DWP(12,$key),$s3);
+
+ &mov ($acc,$_inp); # load inp
+ &mov ($s2,$_len); # load len
+ &lea ($acc,&DWP(16,$acc)); # advance inp
+ &mov ($_inp,$acc); # save inp
+ &sub ($s2,16); # decrease len
+ &mov ($_len,$s2); # save len
+ &jnz (&label("fast_dec_in_place_loop"));
+
+ &set_label("fast_dec_out",4);
+ &cmp ($mark,0); # was the key schedule copied?
+ &mov ("edi",$_key);
+ &je (&label("skip_dzero"));
+ # zero copy of key schedule
+ &mov ("ecx",240/4);
+ &xor ("eax","eax");
+ &align (4);
+ &data_word(0xABF3F689); # rep stosd
+ &set_label("skip_dzero");
+ &mov ("esp",$_esp);
+ &popf ();
+ &function_end_A();
+ &pushf (); # kludge, never executed
+
+#--------------------------- SLOW ROUTINE ---------------------------#
+&set_label("slow_way",16);
+
+ &mov ($s0,&DWP(0,$s0)) if (!$x86only);# load OPENSSL_ia32cap
+ &mov ($key,&wparam(3)); # load key
+
+ # pre-allocate aligned stack frame...
+ &lea ($acc,&DWP(-80,"esp"));
+ &and ($acc,-64);
+
+ # ... and make sure it doesn't alias with $key modulo 1024
+ &lea ($s1,&DWP(-80-63,$key));
+ &sub ($s1,$acc);
+ &neg ($s1);
+ &and ($s1,0x3C0); # modulo 1024, but aligned to cache-line
+ &sub ($acc,$s1);
+
+ # pick S-box copy which can't overlap with stack frame or $key
+ &lea ($s1,&DWP(768,$acc));
+ &sub ($s1,$tbl);
+ &and ($s1,0x300);
+ &lea ($tbl,&DWP(2048+128,$tbl,$s1));
+
+ &lea ($s3,&wparam(0)); # pointer to parameter block
+
+ &exch ("esp",$acc);
+ &add ("esp",4); # reserve for return address!
+ &mov ($_tbl,$tbl); # save %ebp
+ &mov ($_esp,$acc); # save %esp
+ &mov ($_tmp,$s0); # save OPENSSL_ia32cap
+
+ &mov ($s0,&DWP(0,$s3)); # load inp
+ &mov ($s1,&DWP(4,$s3)); # load out
+ #&mov ($s2,&DWP(8,$s3)); # load len
+ #&mov ($key,&DWP(12,$s3)); # load key
+ &mov ($acc,&DWP(16,$s3)); # load ivp
+ &mov ($s3,&DWP(20,$s3)); # load enc flag
+
+ &mov ($_inp,$s0); # save copy of inp
+ &mov ($_out,$s1); # save copy of out
+ &mov ($_len,$s2); # save copy of len
+ &mov ($_key,$key); # save copy of key
+ &mov ($_ivp,$acc); # save copy of ivp
+
+ &mov ($key,$acc);
+ &mov ($acc,$s0);
+
+ &cmp ($s3,0);
+ &je (&label("slow_decrypt"));
+
+#--------------------------- SLOW ENCRYPT ---------------------------#
+ &cmp ($s2,16);
+ &mov ($s3,$s1);
+ &jb (&label("slow_enc_tail"));
+
+ if (!$x86only) {
+ &bt ($_tmp,25); # check for SSE bit
+ &jnc (&label("slow_enc_x86"));
+
+ &movq ("mm0",&QWP(0,$key)); # load iv
+ &movq ("mm4",&QWP(8,$key));
+
+ &set_label("slow_enc_loop_sse",16);
+ &pxor ("mm0",&QWP(0,$acc)); # xor input data
+ &pxor ("mm4",&QWP(8,$acc));
+
+ &mov ($key,$_key);
+ &call ("_sse_AES_encrypt_compact");
+
+ &mov ($acc,$_inp); # load inp
+ &mov ($key,$_out); # load out
+ &mov ($s2,$_len); # load len
+
+ &movq (&QWP(0,$key),"mm0"); # save output data
+ &movq (&QWP(8,$key),"mm4");
+
+ &lea ($acc,&DWP(16,$acc)); # advance inp
+ &mov ($_inp,$acc); # save inp
+ &lea ($s3,&DWP(16,$key)); # advance out
+ &mov ($_out,$s3); # save out
+ &sub ($s2,16); # decrease len
+ &cmp ($s2,16);
+ &mov ($_len,$s2); # save len
+ &jae (&label("slow_enc_loop_sse"));
+ &test ($s2,15);
+ &jnz (&label("slow_enc_tail"));
+ &mov ($acc,$_ivp); # load ivp
+ &movq (&QWP(0,$acc),"mm0"); # save ivec
+ &movq (&QWP(8,$acc),"mm4");
+ &emms ();
+ &mov ("esp",$_esp);
+ &popf ();
+ &function_end_A();
+ &pushf (); # kludge, never executed
+ }
+ &set_label("slow_enc_x86",16);
+ &mov ($s0,&DWP(0,$key)); # load iv
+ &mov ($s1,&DWP(4,$key));
+
+ &set_label("slow_enc_loop_x86",4);
+ &mov ($s2,&DWP(8,$key));
+ &mov ($s3,&DWP(12,$key));
+
+ &xor ($s0,&DWP(0,$acc)); # xor input data
+ &xor ($s1,&DWP(4,$acc));
+ &xor ($s2,&DWP(8,$acc));
+ &xor ($s3,&DWP(12,$acc));
+
+ &mov ($key,$_key); # load key
+ &call ("_x86_AES_encrypt_compact");
+
+ &mov ($acc,$_inp); # load inp
+ &mov ($key,$_out); # load out
+
+ &mov (&DWP(0,$key),$s0); # save output data
+ &mov (&DWP(4,$key),$s1);
+ &mov (&DWP(8,$key),$s2);
+ &mov (&DWP(12,$key),$s3);
+
+ &mov ($s2,$_len); # load len
+ &lea ($acc,&DWP(16,$acc)); # advance inp
+ &mov ($_inp,$acc); # save inp
+ &lea ($s3,&DWP(16,$key)); # advance out
+ &mov ($_out,$s3); # save out
+ &sub ($s2,16); # decrease len
+ &cmp ($s2,16);
+ &mov ($_len,$s2); # save len
+ &jae (&label("slow_enc_loop_x86"));
+ &test ($s2,15);
+ &jnz (&label("slow_enc_tail"));
+ &mov ($acc,$_ivp); # load ivp
+ &mov ($s2,&DWP(8,$key)); # restore last dwords
+ &mov ($s3,&DWP(12,$key));
+ &mov (&DWP(0,$acc),$s0); # save ivec
+ &mov (&DWP(4,$acc),$s1);
+ &mov (&DWP(8,$acc),$s2);
+ &mov (&DWP(12,$acc),$s3);
+
+ &mov ("esp",$_esp);
+ &popf ();
+ &function_end_A();
+ &pushf (); # kludge, never executed
+
+ &set_label("slow_enc_tail",16);
+ &emms () if (!$x86only);
+ &mov ($key eq "edi"? $key:"",$s3); # load out to edi
+ &mov ($s1,16);
+ &sub ($s1,$s2);
+ &cmp ($key,$acc eq "esi"? $acc:""); # compare with inp
+ &je (&label("enc_in_place"));
+ &align (4);
+ &data_word(0xA4F3F689); # rep movsb # copy input
+ &jmp (&label("enc_skip_in_place"));
+ &set_label("enc_in_place");
+ &lea ($key,&DWP(0,$key,$s2));
+ &set_label("enc_skip_in_place");
+ &mov ($s2,$s1);
+ &xor ($s0,$s0);
+ &align (4);
+ &data_word(0xAAF3F689); # rep stosb # zero tail
+
+ &mov ($key,$_ivp); # restore ivp
+ &mov ($acc,$s3); # output as input
+ &mov ($s0,&DWP(0,$key));
+ &mov ($s1,&DWP(4,$key));
+ &mov ($_len,16); # len=16
+ &jmp (&label("slow_enc_loop_x86")); # one more spin...
+
+#--------------------------- SLOW DECRYPT ---------------------------#
+&set_label("slow_decrypt",16);
+ if (!$x86only) {
+ &bt ($_tmp,25); # check for SSE bit
+ &jnc (&label("slow_dec_loop_x86"));
+
+ &set_label("slow_dec_loop_sse",4);
+ &movq ("mm0",&QWP(0,$acc)); # read input
+ &movq ("mm4",&QWP(8,$acc));
+
+ &mov ($key,$_key);
+ &call ("_sse_AES_decrypt_compact");
+
+ &mov ($acc,$_inp); # load inp
+ &lea ($s0,$ivec);
+ &mov ($s1,$_out); # load out
+ &mov ($s2,$_len); # load len
+ &mov ($key,$_ivp); # load ivp
+
+ &movq ("mm1",&QWP(0,$acc)); # re-read input
+ &movq ("mm5",&QWP(8,$acc));
+
+ &pxor ("mm0",&QWP(0,$key)); # xor iv
+ &pxor ("mm4",&QWP(8,$key));
+
+ &movq (&QWP(0,$key),"mm1"); # copy input to iv
+ &movq (&QWP(8,$key),"mm5");
+
+ &sub ($s2,16); # decrease len
+ &jc (&label("slow_dec_partial_sse"));
+
+ &movq (&QWP(0,$s1),"mm0"); # write output
+ &movq (&QWP(8,$s1),"mm4");
+
+ &lea ($s1,&DWP(16,$s1)); # advance out
+ &mov ($_out,$s1); # save out
+ &lea ($acc,&DWP(16,$acc)); # advance inp
+ &mov ($_inp,$acc); # save inp
+ &mov ($_len,$s2); # save len
+ &jnz (&label("slow_dec_loop_sse"));
+ &emms ();
+ &mov ("esp",$_esp);
+ &popf ();
+ &function_end_A();
+ &pushf (); # kludge, never executed
+
+ &set_label("slow_dec_partial_sse",16);
+ &movq (&QWP(0,$s0),"mm0"); # save output to temp
+ &movq (&QWP(8,$s0),"mm4");
+ &emms ();
+
+ &add ($s2 eq "ecx" ? "ecx":"",16);
+ &mov ("edi",$s1); # out
+ &mov ("esi",$s0); # temp
+ &align (4);
+ &data_word(0xA4F3F689); # rep movsb # copy partial output
+
+ &mov ("esp",$_esp);
+ &popf ();
+ &function_end_A();
+ &pushf (); # kludge, never executed
+ }
+ &set_label("slow_dec_loop_x86",16);
+ &mov ($s0,&DWP(0,$acc)); # read input
+ &mov ($s1,&DWP(4,$acc));
+ &mov ($s2,&DWP(8,$acc));
+ &mov ($s3,&DWP(12,$acc));
+
+ &lea ($key,$ivec);
+ &mov (&DWP(0,$key),$s0); # copy to temp
+ &mov (&DWP(4,$key),$s1);
+ &mov (&DWP(8,$key),$s2);
+ &mov (&DWP(12,$key),$s3);
+
+ &mov ($key,$_key); # load key
+ &call ("_x86_AES_decrypt_compact");
+
+ &mov ($key,$_ivp); # load ivp
+ &mov ($acc,$_len); # load len
+ &xor ($s0,&DWP(0,$key)); # xor iv
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &sub ($acc,16);
+ &jc (&label("slow_dec_partial_x86"));
+
+ &mov ($_len,$acc); # save len
+ &mov ($acc,$_out); # load out
+
+ &mov (&DWP(0,$acc),$s0); # write output
+ &mov (&DWP(4,$acc),$s1);
+ &mov (&DWP(8,$acc),$s2);
+ &mov (&DWP(12,$acc),$s3);
+
+ &lea ($acc,&DWP(16,$acc)); # advance out
+ &mov ($_out,$acc); # save out
+
+ &lea ($acc,$ivec);
+ &mov ($s0,&DWP(0,$acc)); # read temp
+ &mov ($s1,&DWP(4,$acc));
+ &mov ($s2,&DWP(8,$acc));
+ &mov ($s3,&DWP(12,$acc));
+
+ &mov (&DWP(0,$key),$s0); # copy it to iv
+ &mov (&DWP(4,$key),$s1);
+ &mov (&DWP(8,$key),$s2);
+ &mov (&DWP(12,$key),$s3);
+
+ &mov ($acc,$_inp); # load inp
+ &lea ($acc,&DWP(16,$acc)); # advance inp
+ &mov ($_inp,$acc); # save inp
+ &jnz (&label("slow_dec_loop_x86"));
+ &mov ("esp",$_esp);
+ &popf ();
+ &function_end_A();
+ &pushf (); # kludge, never executed
+
+ &set_label("slow_dec_partial_x86",16);
+ &lea ($acc,$ivec);
+ &mov (&DWP(0,$acc),$s0); # save output to temp
+ &mov (&DWP(4,$acc),$s1);
+ &mov (&DWP(8,$acc),$s2);
+ &mov (&DWP(12,$acc),$s3);
+
+ &mov ($acc,$_inp);
+ &mov ($s0,&DWP(0,$acc)); # re-read input
+ &mov ($s1,&DWP(4,$acc));
+ &mov ($s2,&DWP(8,$acc));
+ &mov ($s3,&DWP(12,$acc));
+
+ &mov (&DWP(0,$key),$s0); # copy it to iv
+ &mov (&DWP(4,$key),$s1);
+ &mov (&DWP(8,$key),$s2);
+ &mov (&DWP(12,$key),$s3);
+
+ &mov ("ecx",$_len);
+ &mov ("edi",$_out);
+ &lea ("esi",$ivec);
+ &align (4);
+ &data_word(0xA4F3F689); # rep movsb # copy partial output
+
+ &mov ("esp",$_esp);
+ &popf ();
+&function_end("AES_cbc_encrypt");
+}
+
+#------------------------------------------------------------------#
+
+sub enckey()
+{
+ &movz ("esi",&LB("edx")); # rk[i]>>0
+ &movz ("ebx",&BP(-128,$tbl,"esi",1));
+ &movz ("esi",&HB("edx")); # rk[i]>>8
+ &shl ("ebx",24);
+ &xor ("eax","ebx");
+
+ &movz ("ebx",&BP(-128,$tbl,"esi",1));
+ &shr ("edx",16);
+ &movz ("esi",&LB("edx")); # rk[i]>>16
+ &xor ("eax","ebx");
+
+ &movz ("ebx",&BP(-128,$tbl,"esi",1));
+ &movz ("esi",&HB("edx")); # rk[i]>>24
+ &shl ("ebx",8);
+ &xor ("eax","ebx");
+
+ &movz ("ebx",&BP(-128,$tbl,"esi",1));
+ &shl ("ebx",16);
+ &xor ("eax","ebx");
+
+ &xor ("eax",&DWP(1024-128,$tbl,"ecx",4)); # rcon
+}
+
+&function_begin("_x86_AES_set_encrypt_key");
+ &mov ("esi",&wparam(1)); # user supplied key
+ &mov ("edi",&wparam(3)); # private key schedule
+
+ &test ("esi",-1);
+ &jz (&label("badpointer"));
+ &test ("edi",-1);
+ &jz (&label("badpointer"));
+
+ &call (&label("pic_point"));
+ &set_label("pic_point");
+ &blindpop($tbl);
+ &lea ($tbl,&DWP(&label("AES_Te")."-".&label("pic_point"),$tbl));
+ &lea ($tbl,&DWP(2048+128,$tbl));
+
+ # prefetch Te4
+ &mov ("eax",&DWP(0-128,$tbl));
+ &mov ("ebx",&DWP(32-128,$tbl));
+ &mov ("ecx",&DWP(64-128,$tbl));
+ &mov ("edx",&DWP(96-128,$tbl));
+ &mov ("eax",&DWP(128-128,$tbl));
+ &mov ("ebx",&DWP(160-128,$tbl));
+ &mov ("ecx",&DWP(192-128,$tbl));
+ &mov ("edx",&DWP(224-128,$tbl));
+
+ &mov ("ecx",&wparam(2)); # number of bits in key
+ &cmp ("ecx",128);
+ &je (&label("10rounds"));
+ &cmp ("ecx",192);
+ &je (&label("12rounds"));
+ &cmp ("ecx",256);
+ &je (&label("14rounds"));
+ &mov ("eax",-2); # invalid number of bits
+ &jmp (&label("exit"));
+
+ &set_label("10rounds");
+ &mov ("eax",&DWP(0,"esi")); # copy first 4 dwords
+ &mov ("ebx",&DWP(4,"esi"));
+ &mov ("ecx",&DWP(8,"esi"));
+ &mov ("edx",&DWP(12,"esi"));
+ &mov (&DWP(0,"edi"),"eax");
+ &mov (&DWP(4,"edi"),"ebx");
+ &mov (&DWP(8,"edi"),"ecx");
+ &mov (&DWP(12,"edi"),"edx");
+
+ &xor ("ecx","ecx");
+ &jmp (&label("10shortcut"));
+
+ &align (4);
+ &set_label("10loop");
+ &mov ("eax",&DWP(0,"edi")); # rk[0]
+ &mov ("edx",&DWP(12,"edi")); # rk[3]
+ &set_label("10shortcut");
+ &enckey ();
+
+ &mov (&DWP(16,"edi"),"eax"); # rk[4]
+ &xor ("eax",&DWP(4,"edi"));
+ &mov (&DWP(20,"edi"),"eax"); # rk[5]
+ &xor ("eax",&DWP(8,"edi"));
+ &mov (&DWP(24,"edi"),"eax"); # rk[6]
+ &xor ("eax",&DWP(12,"edi"));
+ &mov (&DWP(28,"edi"),"eax"); # rk[7]
+ &inc ("ecx");
+ &add ("edi",16);
+ &cmp ("ecx",10);
+ &jl (&label("10loop"));
+
+ &mov (&DWP(80,"edi"),10); # setup number of rounds
+ &xor ("eax","eax");
+ &jmp (&label("exit"));
+
+ &set_label("12rounds");
+ &mov ("eax",&DWP(0,"esi")); # copy first 6 dwords
+ &mov ("ebx",&DWP(4,"esi"));
+ &mov ("ecx",&DWP(8,"esi"));
+ &mov ("edx",&DWP(12,"esi"));
+ &mov (&DWP(0,"edi"),"eax");
+ &mov (&DWP(4,"edi"),"ebx");
+ &mov (&DWP(8,"edi"),"ecx");
+ &mov (&DWP(12,"edi"),"edx");
+ &mov ("ecx",&DWP(16,"esi"));
+ &mov ("edx",&DWP(20,"esi"));
+ &mov (&DWP(16,"edi"),"ecx");
+ &mov (&DWP(20,"edi"),"edx");
+
+ &xor ("ecx","ecx");
+ &jmp (&label("12shortcut"));
+
+ &align (4);
+ &set_label("12loop");
+ &mov ("eax",&DWP(0,"edi")); # rk[0]
+ &mov ("edx",&DWP(20,"edi")); # rk[5]
+ &set_label("12shortcut");
+ &enckey ();
+
+ &mov (&DWP(24,"edi"),"eax"); # rk[6]
+ &xor ("eax",&DWP(4,"edi"));
+ &mov (&DWP(28,"edi"),"eax"); # rk[7]
+ &xor ("eax",&DWP(8,"edi"));
+ &mov (&DWP(32,"edi"),"eax"); # rk[8]
+ &xor ("eax",&DWP(12,"edi"));
+ &mov (&DWP(36,"edi"),"eax"); # rk[9]
+
+ &cmp ("ecx",7);
+ &je (&label("12break"));
+ &inc ("ecx");
+
+ &xor ("eax",&DWP(16,"edi"));
+ &mov (&DWP(40,"edi"),"eax"); # rk[10]
+ &xor ("eax",&DWP(20,"edi"));
+ &mov (&DWP(44,"edi"),"eax"); # rk[11]
+
+ &add ("edi",24);
+ &jmp (&label("12loop"));
+
+ &set_label("12break");
+ &mov (&DWP(72,"edi"),12); # setup number of rounds
+ &xor ("eax","eax");
+ &jmp (&label("exit"));
+
+ &set_label("14rounds");
+ &mov ("eax",&DWP(0,"esi")); # copy first 8 dwords
+ &mov ("ebx",&DWP(4,"esi"));
+ &mov ("ecx",&DWP(8,"esi"));
+ &mov ("edx",&DWP(12,"esi"));
+ &mov (&DWP(0,"edi"),"eax");
+ &mov (&DWP(4,"edi"),"ebx");
+ &mov (&DWP(8,"edi"),"ecx");
+ &mov (&DWP(12,"edi"),"edx");
+ &mov ("eax",&DWP(16,"esi"));
+ &mov ("ebx",&DWP(20,"esi"));
+ &mov ("ecx",&DWP(24,"esi"));
+ &mov ("edx",&DWP(28,"esi"));
+ &mov (&DWP(16,"edi"),"eax");
+ &mov (&DWP(20,"edi"),"ebx");
+ &mov (&DWP(24,"edi"),"ecx");
+ &mov (&DWP(28,"edi"),"edx");
+
+ &xor ("ecx","ecx");
+ &jmp (&label("14shortcut"));
+
+ &align (4);
+ &set_label("14loop");
+ &mov ("edx",&DWP(28,"edi")); # rk[7]
+ &set_label("14shortcut");
+ &mov ("eax",&DWP(0,"edi")); # rk[0]
+
+ &enckey ();
+
+ &mov (&DWP(32,"edi"),"eax"); # rk[8]
+ &xor ("eax",&DWP(4,"edi"));
+ &mov (&DWP(36,"edi"),"eax"); # rk[9]
+ &xor ("eax",&DWP(8,"edi"));
+ &mov (&DWP(40,"edi"),"eax"); # rk[10]
+ &xor ("eax",&DWP(12,"edi"));
+ &mov (&DWP(44,"edi"),"eax"); # rk[11]
+
+ &cmp ("ecx",6);
+ &je (&label("14break"));
+ &inc ("ecx");
+
+ &mov ("edx","eax");
+ &mov ("eax",&DWP(16,"edi")); # rk[4]
+ &movz ("esi",&LB("edx")); # rk[11]>>0
+ &movz ("ebx",&BP(-128,$tbl,"esi",1));
+ &movz ("esi",&HB("edx")); # rk[11]>>8
+ &xor ("eax","ebx");
+
+ &movz ("ebx",&BP(-128,$tbl,"esi",1));
+ &shr ("edx",16);
+ &shl ("ebx",8);
+ &movz ("esi",&LB("edx")); # rk[11]>>16
+ &xor ("eax","ebx");
+
+ &movz ("ebx",&BP(-128,$tbl,"esi",1));
+ &movz ("esi",&HB("edx")); # rk[11]>>24
+ &shl ("ebx",16);
+ &xor ("eax","ebx");
+
+ &movz ("ebx",&BP(-128,$tbl,"esi",1));
+ &shl ("ebx",24);
+ &xor ("eax","ebx");
+
+ &mov (&DWP(48,"edi"),"eax"); # rk[12]
+ &xor ("eax",&DWP(20,"edi"));
+ &mov (&DWP(52,"edi"),"eax"); # rk[13]
+ &xor ("eax",&DWP(24,"edi"));
+ &mov (&DWP(56,"edi"),"eax"); # rk[14]
+ &xor ("eax",&DWP(28,"edi"));
+ &mov (&DWP(60,"edi"),"eax"); # rk[15]
+
+ &add ("edi",32);
+ &jmp (&label("14loop"));
+
+ &set_label("14break");
+ &mov (&DWP(48,"edi"),14); # setup number of rounds
+ &xor ("eax","eax");
+ &jmp (&label("exit"));
+
+ &set_label("badpointer");
+ &mov ("eax",-1);
+ &set_label("exit");
+&function_end("_x86_AES_set_encrypt_key");
+
+# int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+# AES_KEY *key)
+&function_begin_B("AES_set_encrypt_key");
+ &call ("_x86_AES_set_encrypt_key");
+ &ret ();
+&function_end_B("AES_set_encrypt_key");
+
+sub deckey()
+{ my ($i,$key,$tp1,$tp2,$tp4,$tp8) = @_;
+ my $tmp = $tbl;
+
+ &mov ($tmp,0x80808080);
+ &and ($tmp,$tp1);
+ &lea ($tp2,&DWP(0,$tp1,$tp1));
+ &mov ($acc,$tmp);
+ &shr ($tmp,7);
+ &sub ($acc,$tmp);
+ &and ($tp2,0xfefefefe);
+ &and ($acc,0x1b1b1b1b);
+ &xor ($tp2,$acc);
+ &mov ($tmp,0x80808080);
+
+ &and ($tmp,$tp2);
+ &lea ($tp4,&DWP(0,$tp2,$tp2));
+ &mov ($acc,$tmp);
+ &shr ($tmp,7);
+ &sub ($acc,$tmp);
+ &and ($tp4,0xfefefefe);
+ &and ($acc,0x1b1b1b1b);
+ &xor ($tp2,$tp1); # tp2^tp1
+ &xor ($tp4,$acc);
+ &mov ($tmp,0x80808080);
+
+ &and ($tmp,$tp4);
+ &lea ($tp8,&DWP(0,$tp4,$tp4));
+ &mov ($acc,$tmp);
+ &shr ($tmp,7);
+ &xor ($tp4,$tp1); # tp4^tp1
+ &sub ($acc,$tmp);
+ &and ($tp8,0xfefefefe);
+ &and ($acc,0x1b1b1b1b);
+ &rotl ($tp1,8); # = ROTATE(tp1,8)
+ &xor ($tp8,$acc);
+
+ &mov ($tmp,&DWP(4*($i+1),$key)); # modulo-scheduled load
+
+ &xor ($tp1,$tp2);
+ &xor ($tp2,$tp8);
+ &xor ($tp1,$tp4);
+ &rotl ($tp2,24);
+ &xor ($tp4,$tp8);
+ &xor ($tp1,$tp8); # ^= tp8^(tp4^tp1)^(tp2^tp1)
+ &rotl ($tp4,16);
+ &xor ($tp1,$tp2); # ^= ROTATE(tp8^tp2^tp1,24)
+ &rotl ($tp8,8);
+ &xor ($tp1,$tp4); # ^= ROTATE(tp8^tp4^tp1,16)
+ &mov ($tp2,$tmp);
+ &xor ($tp1,$tp8); # ^= ROTATE(tp8,8)
+
+ &mov (&DWP(4*$i,$key),$tp1);
+}
+
+# int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+# AES_KEY *key)
+&function_begin_B("AES_set_decrypt_key");
+ &call ("_x86_AES_set_encrypt_key");
+ &cmp ("eax",0);
+ &je (&label("proceed"));
+ &ret ();
+
+ &set_label("proceed");
+ &push ("ebp");
+ &push ("ebx");
+ &push ("esi");
+ &push ("edi");
+
+ &mov ("esi",&wparam(2));
+ &mov ("ecx",&DWP(240,"esi")); # pull number of rounds
+ &lea ("ecx",&DWP(0,"","ecx",4));
+ &lea ("edi",&DWP(0,"esi","ecx",4)); # pointer to last chunk
+
+ &set_label("invert",4); # invert order of chunks
+ &mov ("eax",&DWP(0,"esi"));
+ &mov ("ebx",&DWP(4,"esi"));
+ &mov ("ecx",&DWP(0,"edi"));
+ &mov ("edx",&DWP(4,"edi"));
+ &mov (&DWP(0,"edi"),"eax");
+ &mov (&DWP(4,"edi"),"ebx");
+ &mov (&DWP(0,"esi"),"ecx");
+ &mov (&DWP(4,"esi"),"edx");
+ &mov ("eax",&DWP(8,"esi"));
+ &mov ("ebx",&DWP(12,"esi"));
+ &mov ("ecx",&DWP(8,"edi"));
+ &mov ("edx",&DWP(12,"edi"));
+ &mov (&DWP(8,"edi"),"eax");
+ &mov (&DWP(12,"edi"),"ebx");
+ &mov (&DWP(8,"esi"),"ecx");
+ &mov (&DWP(12,"esi"),"edx");
+ &add ("esi",16);
+ &sub ("edi",16);
+ &cmp ("esi","edi");
+ &jne (&label("invert"));
+
+ &mov ($key,&wparam(2));
+ &mov ($acc,&DWP(240,$key)); # pull number of rounds
+ &lea ($acc,&DWP(-2,$acc,$acc));
+ &lea ($acc,&DWP(0,$key,$acc,8));
+ &mov (&wparam(2),$acc);
+
+ &mov ($s0,&DWP(16,$key)); # modulo-scheduled load
+ &set_label("permute",4); # permute the key schedule
+ &add ($key,16);
+ &deckey (0,$key,$s0,$s1,$s2,$s3);
+ &deckey (1,$key,$s1,$s2,$s3,$s0);
+ &deckey (2,$key,$s2,$s3,$s0,$s1);
+ &deckey (3,$key,$s3,$s0,$s1,$s2);
+ &cmp ($key,&wparam(2));
+ &jb (&label("permute"));
+
+ &xor ("eax","eax"); # return success
+&function_end("AES_set_decrypt_key");
+&asciz("AES for x86, CRYPTOGAMS by <appro\@openssl.org>");
+
+&asm_finish();
+
+close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/aes/asm/aes-armv4.pl b/crypto/aes/asm/aes-armv4.pl
index 1112eef50c0b..fc9ff7d3e4ee 100644
--- a/crypto/aes/asm/aes-armv4.pl
+++ b/crypto/aes/asm/aes-armv4.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -39,9 +39,10 @@
# Profiler-assisted and platform-specific optimization resulted in 16%
# improvement on Cortex A8 core and ~21.5 cycles per byte.
-$flavour = shift;
-if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour && $flavour ne "void") {
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -49,9 +50,10 @@ if ($flavour && $flavour ne "void") {
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
- open STDOUT,"| \"$^X\" $xlate $flavour $output";
+ open STDOUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
} else {
- open STDOUT,">$output";
+ $output and open STDOUT,">$output";
}
$s0="r0";
@@ -76,7 +78,6 @@ $code=<<___;
# define __ARM_ARCH__ __LINUX_ARM_ARCH__
#endif
-.text
#if defined(__thumb2__) && !defined(__APPLE__)
.syntax unified
.thumb
@@ -85,6 +86,8 @@ $code=<<___;
#undef __thumb2__
#endif
+.text
+
.type AES_Te,%object
.align 5
AES_Te:
diff --git a/crypto/aes/asm/aes-c64xplus.pl b/crypto/aes/asm/aes-c64xplus.pl
index cad3fcd06e36..fa9a132d90fb 100644
--- a/crypto/aes/asm/aes-c64xplus.pl
+++ b/crypto/aes/asm/aes-c64xplus.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -37,8 +37,7 @@
# cost of 8x increased pressure on L1D. 8x because you'd have
# to interleave both Te and Td tables...
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
($TEA,$TEB)=("A5","B5");
($KPA,$KPB)=("A3","B1");
diff --git a/crypto/aes/asm/aes-ia64.S b/crypto/aes/asm/aes-ia64.S
index 03f79b7ae3b7..ad9e466bbc18 100644
--- a/crypto/aes/asm/aes-ia64.S
+++ b/crypto/aes/asm/aes-ia64.S
@@ -1,6 +1,6 @@
// Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
//
-// Licensed under the OpenSSL license (the "License"). You may not use
+// Licensed under the Apache License 2.0 (the "License"). You may not use
// this file except in compliance with the License. You can obtain a copy
// in the file LICENSE in the source distribution or at
// https://www.openssl.org/source/license.html
@@ -8,7 +8,7 @@
// ====================================================================
// Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
// project. Rights for redistribution and usage in source and binary
-// forms are granted according to the OpenSSL license.
+// forms are granted according to the License.
// ====================================================================
//
// What's wrong with compiler generated code? Compiler never uses
diff --git a/crypto/aes/asm/aes-mips.pl b/crypto/aes/asm/aes-mips.pl
index b5601e90ea3f..290621acc2cf 100644
--- a/crypto/aes/asm/aes-mips.pl
+++ b/crypto/aes/asm/aes-mips.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -34,6 +34,11 @@
# instead, code path is chosen upon pre-process time, pass -mips32r2
# or/and -msmartmips.
+# February 2019
+#
+# Normalize MIPS32R2 AES table address calculation by always using EXT
+# instruction. This reduces the standard codebase by another 10%.
+
######################################################################
# There is a number of MIPS ABI in use, O32 and N32/64 are most
# widely used. Then there is a new contender: NUBI. It appears that if
@@ -60,8 +65,12 @@
# ($t0,$t1,$t2,$t3,$t8,$t9)=map("\$$_",(12..15,24,25));
# ($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7)=map("\$$_",(16..23));
# ($gp,$sp,$fp,$ra)=map("\$$_",(28..31));
-#
-$flavour = shift || "o32"; # supported flavours are o32,n32,64,nubi32,nubi64
+
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+$flavour ||= "o32"; # supported flavours are o32,n32,64,nubi32,nubi64
if ($flavour =~ /64|n32/i) {
$PTR_LA="dla";
@@ -90,17 +99,13 @@ $pf = ($flavour =~ /nubi/i) ? $t0 : $t2;
$big_endian=(`echo MIPSEB | $ENV{CC} -E -`=~/MIPSEB/)?0:1 if ($ENV{CC});
-for (@ARGV) { $output=$_ if (/\w[\w\-]*\.\w+$/); }
-open STDOUT,">$output";
-
if (!defined($big_endian))
{ $big_endian=(unpack('L',pack('N',1))==1); }
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
-
my ($MSB,$LSB)=(0,3); # automatically converted to little-endian
+$output and open STDOUT,">$output";
+
$code.=<<___;
#include "mips_arch.h"
@@ -224,6 +229,33 @@ _mips_AES_encrypt:
_xtr $i0,$s1,16-2
#else
+#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
+ move $i0,$Tbl
+ move $i1,$Tbl
+ move $i2,$Tbl
+ move $i3,$Tbl
+ ext $t0,$s1,16,8
+.Loop_enc:
+ ext $t1,$s2,16,8
+ ext $t2,$s3,16,8
+ ext $t3,$s0,16,8
+ $PTR_INS $i0,$t0,2,8
+ $PTR_INS $i1,$t1,2,8
+ $PTR_INS $i2,$t2,2,8
+ $PTR_INS $i3,$t3,2,8
+ lw $t0,0($i0) # Te1[s1>>16]
+ ext $t4,$s2,8,8
+ lw $t1,0($i1) # Te1[s2>>16]
+ ext $t5,$s3,8,8
+ lw $t2,0($i2) # Te1[s3>>16]
+ ext $t6,$s0,8,8
+ lw $t3,0($i3) # Te1[s0>>16]
+ ext $t7,$s1,8,8
+ $PTR_INS $i0,$t4,2,8
+ $PTR_INS $i1,$t5,2,8
+ $PTR_INS $i2,$t6,2,8
+ $PTR_INS $i3,$t7,2,8
+#else
_xtr $i0,$s1,16-2
.Loop_enc:
_xtr $i1,$s2,16-2
@@ -237,16 +269,6 @@ _mips_AES_encrypt:
$PTR_ADD $i1,$Tbl
$PTR_ADD $i2,$Tbl
$PTR_ADD $i3,$Tbl
-#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
- lw $t0,0($i0) # Te1[s1>>16]
- _xtr $i0,$s2,8-2
- lw $t1,0($i1) # Te1[s2>>16]
- _xtr $i1,$s3,8-2
- lw $t2,0($i2) # Te1[s3>>16]
- _xtr $i2,$s0,8-2
- lw $t3,0($i3) # Te1[s0>>16]
- _xtr $i3,$s1,8-2
-#else
lwl $t0,3($i0) # Te1[s1>>16]
lwl $t1,3($i1) # Te1[s2>>16]
lwl $t2,3($i2) # Te1[s3>>16]
@@ -259,7 +281,6 @@ _mips_AES_encrypt:
_xtr $i2,$s0,8-2
lwr $t3,2($i3) # Te1[s0>>16]
_xtr $i3,$s1,8-2
-#endif
and $i0,0x3fc
and $i1,0x3fc
and $i2,0x3fc
@@ -268,6 +289,7 @@ _mips_AES_encrypt:
$PTR_ADD $i1,$Tbl
$PTR_ADD $i2,$Tbl
$PTR_ADD $i3,$Tbl
+#endif
#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
rotr $t0,$t0,8
rotr $t1,$t1,8
@@ -275,22 +297,18 @@ _mips_AES_encrypt:
rotr $t3,$t3,8
# if defined(_MIPSEL)
lw $t4,0($i0) # Te2[s2>>8]
- _xtr $i0,$s3,0-2
+ ext $t8,$s3,0,8
lw $t5,0($i1) # Te2[s3>>8]
- _xtr $i1,$s0,0-2
+ ext $t9,$s0,0,8
lw $t6,0($i2) # Te2[s0>>8]
- _xtr $i2,$s1,0-2
+ ext $t10,$s1,0,8
lw $t7,0($i3) # Te2[s1>>8]
- _xtr $i3,$s2,0-2
+ ext $t11,$s2,0,8
+ $PTR_INS $i0,$t8,2,8
+ $PTR_INS $i1,$t9,2,8
+ $PTR_INS $i2,$t10,2,8
+ $PTR_INS $i3,$t11,2,8
- and $i0,0x3fc
- and $i1,0x3fc
- and $i2,0x3fc
- and $i3,0x3fc
- $PTR_ADD $i0,$Tbl
- $PTR_ADD $i1,$Tbl
- $PTR_ADD $i2,$Tbl
- $PTR_ADD $i3,$Tbl
lw $t8,0($i0) # Te3[s3]
$PTR_INS $i0,$s0,2,8
lw $t9,0($i1) # Te3[s0]
@@ -411,6 +429,9 @@ _mips_AES_encrypt:
xor $s3,$t3
.set noreorder
bnez $cnt,.Loop_enc
+#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
+ ext $t0,$s1,16,8
+#endif
_xtr $i0,$s1,16-2
#endif
@@ -812,6 +833,33 @@ _mips_AES_decrypt:
_xtr $i0,$s3,16-2
#else
+#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
+ move $i0,$Tbl
+ move $i1,$Tbl
+ move $i2,$Tbl
+ move $i3,$Tbl
+ ext $t0,$s3,16,8
+.Loop_dec:
+ ext $t1,$s0,16,8
+ ext $t2,$s1,16,8
+ ext $t3,$s2,16,8
+ $PTR_INS $i0,$t0,2,8
+ $PTR_INS $i1,$t1,2,8
+ $PTR_INS $i2,$t2,2,8
+ $PTR_INS $i3,$t3,2,8
+ lw $t0,0($i0) # Td1[s3>>16]
+ ext $t4,$s2,8,8
+ lw $t1,0($i1) # Td1[s0>>16]
+ ext $t5,$s3,8,8
+ lw $t2,0($i2) # Td1[s1>>16]
+ ext $t6,$s0,8,8
+ lw $t3,0($i3) # Td1[s2>>16]
+ ext $t7,$s1,8,8
+ $PTR_INS $i0,$t4,2,8
+ $PTR_INS $i1,$t5,2,8
+ $PTR_INS $i2,$t6,2,8
+ $PTR_INS $i3,$t7,2,8
+#else
_xtr $i0,$s3,16-2
.Loop_dec:
_xtr $i1,$s0,16-2
@@ -825,16 +873,6 @@ _mips_AES_decrypt:
$PTR_ADD $i1,$Tbl
$PTR_ADD $i2,$Tbl
$PTR_ADD $i3,$Tbl
-#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
- lw $t0,0($i0) # Td1[s3>>16]
- _xtr $i0,$s2,8-2
- lw $t1,0($i1) # Td1[s0>>16]
- _xtr $i1,$s3,8-2
- lw $t2,0($i2) # Td1[s1>>16]
- _xtr $i2,$s0,8-2
- lw $t3,0($i3) # Td1[s2>>16]
- _xtr $i3,$s1,8-2
-#else
lwl $t0,3($i0) # Td1[s3>>16]
lwl $t1,3($i1) # Td1[s0>>16]
lwl $t2,3($i2) # Td1[s1>>16]
@@ -847,8 +885,6 @@ _mips_AES_decrypt:
_xtr $i2,$s0,8-2
lwr $t3,2($i3) # Td1[s2>>16]
_xtr $i3,$s1,8-2
-#endif
-
and $i0,0x3fc
and $i1,0x3fc
and $i2,0x3fc
@@ -857,6 +893,7 @@ _mips_AES_decrypt:
$PTR_ADD $i1,$Tbl
$PTR_ADD $i2,$Tbl
$PTR_ADD $i3,$Tbl
+#endif
#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
rotr $t0,$t0,8
rotr $t1,$t1,8
@@ -864,22 +901,17 @@ _mips_AES_decrypt:
rotr $t3,$t3,8
# if defined(_MIPSEL)
lw $t4,0($i0) # Td2[s2>>8]
- _xtr $i0,$s1,0-2
+ ext $t8,$s1,0,8
lw $t5,0($i1) # Td2[s3>>8]
- _xtr $i1,$s2,0-2
+ ext $t9,$s2,0,8
lw $t6,0($i2) # Td2[s0>>8]
- _xtr $i2,$s3,0-2
+ ext $t10,$s3,0,8
lw $t7,0($i3) # Td2[s1>>8]
- _xtr $i3,$s0,0-2
-
- and $i0,0x3fc
- and $i1,0x3fc
- and $i2,0x3fc
- and $i3,0x3fc
- $PTR_ADD $i0,$Tbl
- $PTR_ADD $i1,$Tbl
- $PTR_ADD $i2,$Tbl
- $PTR_ADD $i3,$Tbl
+ ext $t11,$s0,0,8
+ $PTR_INS $i0,$t8,2,8
+ $PTR_INS $i1,$t9,2,8
+ $PTR_INS $i2,$t10,2,8
+ $PTR_INS $i3,$t11,2,8
lw $t8,0($i0) # Td3[s1]
$PTR_INS $i0,$s0,2,8
lw $t9,0($i1) # Td3[s2]
@@ -1001,6 +1033,10 @@ _mips_AES_decrypt:
xor $s3,$t3
.set noreorder
bnez $cnt,.Loop_dec
+#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
+ ext $t0,$s3,16,8
+#endif
+
_xtr $i0,$s3,16-2
#endif
diff --git a/crypto/aes/asm/aes-parisc.pl b/crypto/aes/asm/aes-parisc.pl
index 5b07fac3d004..3d55eec9bb37 100644
--- a/crypto/aes/asm/aes-parisc.pl
+++ b/crypto/aes/asm/aes-parisc.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -28,9 +28,12 @@
#
# Special thanks to polarhome.com for providing HP-UX account.
-$flavour = shift;
-$output = shift;
-open STDOUT,">$output";
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+
+$output and open STDOUT,">$output";
if ($flavour =~ /64/) {
$LEVEL ="2.0W";
diff --git a/crypto/aes/asm/aes-ppc.pl b/crypto/aes/asm/aes-ppc.pl
index bb4ee84ae337..595182c89bf3 100644
--- a/crypto/aes/asm/aes-ppc.pl
+++ b/crypto/aes/asm/aes-ppc.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -36,7 +36,10 @@
# ppc_AES_encrypt_compact operates at 42 cycles per byte, while
# ppc_AES_decrypt_compact - at 55 (in 64-bit build).
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /64/) {
$SIZE_T =8;
@@ -59,7 +62,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
+open STDOUT,"| $^X $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
$FRAME=32*$SIZE_T;
diff --git a/crypto/aes/asm/aes-s390x.pl b/crypto/aes/asm/aes-s390x.pl
index 4cb8f4331742..5d1283f57690 100644
--- a/crypto/aes/asm/aes-s390x.pl
+++ b/crypto/aes/asm/aes-s390x.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -89,7 +89,10 @@
# instructions, which deliver ~70% improvement at 8KB block size over
# vanilla km-based code, 37% - at most like 512-bytes block size.
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /3[12]/) {
$SIZE_T=4;
@@ -99,8 +102,7 @@ if ($flavour =~ /3[12]/) {
$g="g";
}
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$output and open STDOUT,">$output";
$softonly=0; # allow hardware support
diff --git a/crypto/aes/asm/aes-sparcv9.pl b/crypto/aes/asm/aes-sparcv9.pl
index 1b37a9203c27..d15640e3d76b 100755
--- a/crypto/aes/asm/aes-sparcv9.pl
+++ b/crypto/aes/asm/aes-sparcv9.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -10,7 +10,7 @@
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
# project. Rights for redistribution and usage in source and binary
-# forms are granted according to the OpenSSL license.
+# forms are granted according to the License.
# ====================================================================
#
# Version 1.1
@@ -37,8 +37,7 @@
# optimal decrypt procedure]. Compared to GNU C generated code both
# procedures are more than 60% faster:-)
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
$frame="STACK_FRAME";
$bias="STACK_BIAS";
@@ -83,7 +82,10 @@ sub _data_word()
}
$code.=<<___;
-#include "sparc_arch.h"
+#ifndef __ASSEMBLER__
+# define __ASSEMBLER__ 1
+#endif
+#include "crypto/sparc_arch.h"
#ifdef __arch64__
.register %g2,#scratch
diff --git a/crypto/aes/asm/aes-x86_64.pl b/crypto/aes/asm/aes-x86_64.pl
new file mode 100755
index 000000000000..25f7ded947ed
--- /dev/null
+++ b/crypto/aes/asm/aes-x86_64.pl
@@ -0,0 +1,2927 @@
+#! /usr/bin/env perl
+# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# Version 2.1.
+#
+# aes-*-cbc benchmarks are improved by >70% [compared to gcc 3.3.2 on
+# Opteron 240 CPU] plus all the bells-n-whistles from 32-bit version
+# [you'll notice a lot of resemblance], such as compressed S-boxes
+# in little-endian byte order, prefetch of these tables in CBC mode,
+# as well as avoiding L1 cache aliasing between stack frame and key
+# schedule and already mentioned tables, compressed Td4...
+#
+# Performance in number of cycles per processed byte for 128-bit key:
+#
+# ECB encrypt ECB decrypt CBC large chunk
+# AMD64 33 43 13.0
+# EM64T 38 56 18.6(*)
+# Core 2 30 42 14.5(*)
+# Atom 65 86 32.1(*)
+#
+# (*) with hyper-threading off
+
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
+*STDOUT=*OUT;
+
+$verticalspin=1; # unlike 32-bit version $verticalspin performs
+ # ~15% better on both AMD and Intel cores
+$speed_limit=512; # see aes-586.pl for details
+
+$code=".text\n";
+
+$s0="%eax";
+$s1="%ebx";
+$s2="%ecx";
+$s3="%edx";
+$acc0="%esi"; $mask80="%rsi";
+$acc1="%edi"; $maskfe="%rdi";
+$acc2="%ebp"; $mask1b="%rbp";
+$inp="%r8";
+$out="%r9";
+$t0="%r10d";
+$t1="%r11d";
+$t2="%r12d";
+$rnds="%r13d";
+$sbox="%r14";
+$key="%r15";
+
+sub hi() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1h/; $r; }
+sub lo() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1l/;
+ $r =~ s/%[er]([sd]i)/%\1l/;
+ $r =~ s/%(r[0-9]+)[d]?/%\1b/; $r; }
+sub LO() { my $r=shift; $r =~ s/%r([a-z]+)/%e\1/;
+ $r =~ s/%r([0-9]+)/%r\1d/; $r; }
+sub _data_word()
+{ my $i;
+ while(defined($i=shift)) { $code.=sprintf".long\t0x%08x,0x%08x\n",$i,$i; }
+}
+sub data_word()
+{ my $i;
+ my $last=pop(@_);
+ $code.=".long\t";
+ while(defined($i=shift)) { $code.=sprintf"0x%08x,",$i; }
+ $code.=sprintf"0x%08x\n",$last;
+}
+
+sub data_byte()
+{ my $i;
+ my $last=pop(@_);
+ $code.=".byte\t";
+ while(defined($i=shift)) { $code.=sprintf"0x%02x,",$i&0xff; }
+ $code.=sprintf"0x%02x\n",$last&0xff;
+}
+
+sub encvert()
+{ my $t3="%r8d"; # zaps $inp!
+
+$code.=<<___;
+ # favor 3-way issue Opteron pipeline...
+ movzb `&lo("$s0")`,$acc0
+ movzb `&lo("$s1")`,$acc1
+ movzb `&lo("$s2")`,$acc2
+ mov 0($sbox,$acc0,8),$t0
+ mov 0($sbox,$acc1,8),$t1
+ mov 0($sbox,$acc2,8),$t2
+
+ movzb `&hi("$s1")`,$acc0
+ movzb `&hi("$s2")`,$acc1
+ movzb `&lo("$s3")`,$acc2
+ xor 3($sbox,$acc0,8),$t0
+ xor 3($sbox,$acc1,8),$t1
+ mov 0($sbox,$acc2,8),$t3
+
+ movzb `&hi("$s3")`,$acc0
+ shr \$16,$s2
+ movzb `&hi("$s0")`,$acc2
+ xor 3($sbox,$acc0,8),$t2
+ shr \$16,$s3
+ xor 3($sbox,$acc2,8),$t3
+
+ shr \$16,$s1
+ lea 16($key),$key
+ shr \$16,$s0
+
+ movzb `&lo("$s2")`,$acc0
+ movzb `&lo("$s3")`,$acc1
+ movzb `&lo("$s0")`,$acc2
+ xor 2($sbox,$acc0,8),$t0
+ xor 2($sbox,$acc1,8),$t1
+ xor 2($sbox,$acc2,8),$t2
+
+ movzb `&hi("$s3")`,$acc0
+ movzb `&hi("$s0")`,$acc1
+ movzb `&lo("$s1")`,$acc2
+ xor 1($sbox,$acc0,8),$t0
+ xor 1($sbox,$acc1,8),$t1
+ xor 2($sbox,$acc2,8),$t3
+
+ mov 12($key),$s3
+ movzb `&hi("$s1")`,$acc1
+ movzb `&hi("$s2")`,$acc2
+ mov 0($key),$s0
+ xor 1($sbox,$acc1,8),$t2
+ xor 1($sbox,$acc2,8),$t3
+
+ mov 4($key),$s1
+ mov 8($key),$s2
+ xor $t0,$s0
+ xor $t1,$s1
+ xor $t2,$s2
+ xor $t3,$s3
+___
+}
+
+sub enclastvert()
+{ my $t3="%r8d"; # zaps $inp!
+
+$code.=<<___;
+ movzb `&lo("$s0")`,$acc0
+ movzb `&lo("$s1")`,$acc1
+ movzb `&lo("$s2")`,$acc2
+ movzb 2($sbox,$acc0,8),$t0
+ movzb 2($sbox,$acc1,8),$t1
+ movzb 2($sbox,$acc2,8),$t2
+
+ movzb `&lo("$s3")`,$acc0
+ movzb `&hi("$s1")`,$acc1
+ movzb `&hi("$s2")`,$acc2
+ movzb 2($sbox,$acc0,8),$t3
+ mov 0($sbox,$acc1,8),$acc1 #$t0
+ mov 0($sbox,$acc2,8),$acc2 #$t1
+
+ and \$0x0000ff00,$acc1
+ and \$0x0000ff00,$acc2
+
+ xor $acc1,$t0
+ xor $acc2,$t1
+ shr \$16,$s2
+
+ movzb `&hi("$s3")`,$acc0
+ movzb `&hi("$s0")`,$acc1
+ shr \$16,$s3
+ mov 0($sbox,$acc0,8),$acc0 #$t2
+ mov 0($sbox,$acc1,8),$acc1 #$t3
+
+ and \$0x0000ff00,$acc0
+ and \$0x0000ff00,$acc1
+ shr \$16,$s1
+ xor $acc0,$t2
+ xor $acc1,$t3
+ shr \$16,$s0
+
+ movzb `&lo("$s2")`,$acc0
+ movzb `&lo("$s3")`,$acc1
+ movzb `&lo("$s0")`,$acc2
+ mov 0($sbox,$acc0,8),$acc0 #$t0
+ mov 0($sbox,$acc1,8),$acc1 #$t1
+ mov 0($sbox,$acc2,8),$acc2 #$t2
+
+ and \$0x00ff0000,$acc0
+ and \$0x00ff0000,$acc1
+ and \$0x00ff0000,$acc2
+
+ xor $acc0,$t0
+ xor $acc1,$t1
+ xor $acc2,$t2
+
+ movzb `&lo("$s1")`,$acc0
+ movzb `&hi("$s3")`,$acc1
+ movzb `&hi("$s0")`,$acc2
+ mov 0($sbox,$acc0,8),$acc0 #$t3
+ mov 2($sbox,$acc1,8),$acc1 #$t0
+ mov 2($sbox,$acc2,8),$acc2 #$t1
+
+ and \$0x00ff0000,$acc0
+ and \$0xff000000,$acc1
+ and \$0xff000000,$acc2
+
+ xor $acc0,$t3
+ xor $acc1,$t0
+ xor $acc2,$t1
+
+ movzb `&hi("$s1")`,$acc0
+ movzb `&hi("$s2")`,$acc1
+ mov 16+12($key),$s3
+ mov 2($sbox,$acc0,8),$acc0 #$t2
+ mov 2($sbox,$acc1,8),$acc1 #$t3
+ mov 16+0($key),$s0
+
+ and \$0xff000000,$acc0
+ and \$0xff000000,$acc1
+
+ xor $acc0,$t2
+ xor $acc1,$t3
+
+ mov 16+4($key),$s1
+ mov 16+8($key),$s2
+ xor $t0,$s0
+ xor $t1,$s1
+ xor $t2,$s2
+ xor $t3,$s3
+___
+}
+
+sub encstep()
+{ my ($i,@s) = @_;
+ my $tmp0=$acc0;
+ my $tmp1=$acc1;
+ my $tmp2=$acc2;
+ my $out=($t0,$t1,$t2,$s[0])[$i];
+
+ if ($i==3) {
+ $tmp0=$s[1];
+ $tmp1=$s[2];
+ $tmp2=$s[3];
+ }
+ $code.=" movzb ".&lo($s[0]).",$out\n";
+ $code.=" mov $s[2],$tmp1\n" if ($i!=3);
+ $code.=" lea 16($key),$key\n" if ($i==0);
+
+ $code.=" movzb ".&hi($s[1]).",$tmp0\n";
+ $code.=" mov 0($sbox,$out,8),$out\n";
+
+ $code.=" shr \$16,$tmp1\n";
+ $code.=" mov $s[3],$tmp2\n" if ($i!=3);
+ $code.=" xor 3($sbox,$tmp0,8),$out\n";
+
+ $code.=" movzb ".&lo($tmp1).",$tmp1\n";
+ $code.=" shr \$24,$tmp2\n";
+ $code.=" xor 4*$i($key),$out\n";
+
+ $code.=" xor 2($sbox,$tmp1,8),$out\n";
+ $code.=" xor 1($sbox,$tmp2,8),$out\n";
+
+ $code.=" mov $t0,$s[1]\n" if ($i==3);
+ $code.=" mov $t1,$s[2]\n" if ($i==3);
+ $code.=" mov $t2,$s[3]\n" if ($i==3);
+ $code.="\n";
+}
+
+sub enclast()
+{ my ($i,@s)=@_;
+ my $tmp0=$acc0;
+ my $tmp1=$acc1;
+ my $tmp2=$acc2;
+ my $out=($t0,$t1,$t2,$s[0])[$i];
+
+ if ($i==3) {
+ $tmp0=$s[1];
+ $tmp1=$s[2];
+ $tmp2=$s[3];
+ }
+ $code.=" movzb ".&lo($s[0]).",$out\n";
+ $code.=" mov $s[2],$tmp1\n" if ($i!=3);
+
+ $code.=" mov 2($sbox,$out,8),$out\n";
+ $code.=" shr \$16,$tmp1\n";
+ $code.=" mov $s[3],$tmp2\n" if ($i!=3);
+
+ $code.=" and \$0x000000ff,$out\n";
+ $code.=" movzb ".&hi($s[1]).",$tmp0\n";
+ $code.=" movzb ".&lo($tmp1).",$tmp1\n";
+ $code.=" shr \$24,$tmp2\n";
+
+ $code.=" mov 0($sbox,$tmp0,8),$tmp0\n";
+ $code.=" mov 0($sbox,$tmp1,8),$tmp1\n";
+ $code.=" mov 2($sbox,$tmp2,8),$tmp2\n";
+
+ $code.=" and \$0x0000ff00,$tmp0\n";
+ $code.=" and \$0x00ff0000,$tmp1\n";
+ $code.=" and \$0xff000000,$tmp2\n";
+
+ $code.=" xor $tmp0,$out\n";
+ $code.=" mov $t0,$s[1]\n" if ($i==3);
+ $code.=" xor $tmp1,$out\n";
+ $code.=" mov $t1,$s[2]\n" if ($i==3);
+ $code.=" xor $tmp2,$out\n";
+ $code.=" mov $t2,$s[3]\n" if ($i==3);
+ $code.="\n";
+}
+
+$code.=<<___;
+.type _x86_64_AES_encrypt,\@abi-omnipotent
+.align 16
+_x86_64_AES_encrypt:
+.cfi_startproc
+ xor 0($key),$s0 # xor with key
+ xor 4($key),$s1
+ xor 8($key),$s2
+ xor 12($key),$s3
+
+ mov 240($key),$rnds # load key->rounds
+ sub \$1,$rnds
+ jmp .Lenc_loop
+.align 16
+.Lenc_loop:
+___
+ if ($verticalspin) { &encvert(); }
+ else { &encstep(0,$s0,$s1,$s2,$s3);
+ &encstep(1,$s1,$s2,$s3,$s0);
+ &encstep(2,$s2,$s3,$s0,$s1);
+ &encstep(3,$s3,$s0,$s1,$s2);
+ }
+$code.=<<___;
+ sub \$1,$rnds
+ jnz .Lenc_loop
+___
+ if ($verticalspin) { &enclastvert(); }
+ else { &enclast(0,$s0,$s1,$s2,$s3);
+ &enclast(1,$s1,$s2,$s3,$s0);
+ &enclast(2,$s2,$s3,$s0,$s1);
+ &enclast(3,$s3,$s0,$s1,$s2);
+ $code.=<<___;
+ xor 16+0($key),$s0 # xor with key
+ xor 16+4($key),$s1
+ xor 16+8($key),$s2
+ xor 16+12($key),$s3
+___
+ }
+$code.=<<___;
+ .byte 0xf3,0xc3 # rep ret
+.cfi_endproc
+.size _x86_64_AES_encrypt,.-_x86_64_AES_encrypt
+___
+
+# it's possible to implement this by shifting tN by 8, filling least
+# significant byte with byte load and finally bswap-ing at the end,
+# but such partial register load kills Core 2...
+sub enccompactvert()
+{ my ($t3,$t4,$t5)=("%r8d","%r9d","%r13d");
+
+$code.=<<___;
+ movzb `&lo("$s0")`,$t0
+ movzb `&lo("$s1")`,$t1
+ movzb `&lo("$s2")`,$t2
+ movzb `&lo("$s3")`,$t3
+ movzb `&hi("$s1")`,$acc0
+ movzb `&hi("$s2")`,$acc1
+ shr \$16,$s2
+ movzb `&hi("$s3")`,$acc2
+ movzb ($sbox,$t0,1),$t0
+ movzb ($sbox,$t1,1),$t1
+ movzb ($sbox,$t2,1),$t2
+ movzb ($sbox,$t3,1),$t3
+
+ movzb ($sbox,$acc0,1),$t4 #$t0
+ movzb `&hi("$s0")`,$acc0
+ movzb ($sbox,$acc1,1),$t5 #$t1
+ movzb `&lo("$s2")`,$acc1
+ movzb ($sbox,$acc2,1),$acc2 #$t2
+ movzb ($sbox,$acc0,1),$acc0 #$t3
+
+ shl \$8,$t4
+ shr \$16,$s3
+ shl \$8,$t5
+ xor $t4,$t0
+ shr \$16,$s0
+ movzb `&lo("$s3")`,$t4
+ shr \$16,$s1
+ xor $t5,$t1
+ shl \$8,$acc2
+ movzb `&lo("$s0")`,$t5
+ movzb ($sbox,$acc1,1),$acc1 #$t0
+ xor $acc2,$t2
+
+ shl \$8,$acc0
+ movzb `&lo("$s1")`,$acc2
+ shl \$16,$acc1
+ xor $acc0,$t3
+ movzb ($sbox,$t4,1),$t4 #$t1
+ movzb `&hi("$s3")`,$acc0
+ movzb ($sbox,$t5,1),$t5 #$t2
+ xor $acc1,$t0
+
+ shr \$8,$s2
+ movzb `&hi("$s0")`,$acc1
+ shl \$16,$t4
+ shr \$8,$s1
+ shl \$16,$t5
+ xor $t4,$t1
+ movzb ($sbox,$acc2,1),$acc2 #$t3
+ movzb ($sbox,$acc0,1),$acc0 #$t0
+ movzb ($sbox,$acc1,1),$acc1 #$t1
+ movzb ($sbox,$s2,1),$s3 #$t3
+ movzb ($sbox,$s1,1),$s2 #$t2
+
+ shl \$16,$acc2
+ xor $t5,$t2
+ shl \$24,$acc0
+ xor $acc2,$t3
+ shl \$24,$acc1
+ xor $acc0,$t0
+ shl \$24,$s3
+ xor $acc1,$t1
+ shl \$24,$s2
+ mov $t0,$s0
+ mov $t1,$s1
+ xor $t2,$s2
+ xor $t3,$s3
+___
+}
+
+sub enctransform_ref()
+{ my $sn = shift;
+ my ($acc,$r2,$tmp)=("%r8d","%r9d","%r13d");
+
+$code.=<<___;
+ mov $sn,$acc
+ and \$0x80808080,$acc
+ mov $acc,$tmp
+ shr \$7,$tmp
+ lea ($sn,$sn),$r2
+ sub $tmp,$acc
+ and \$0xfefefefe,$r2
+ and \$0x1b1b1b1b,$acc
+ mov $sn,$tmp
+ xor $acc,$r2
+
+ xor $r2,$sn
+ rol \$24,$sn
+ xor $r2,$sn
+ ror \$16,$tmp
+ xor $tmp,$sn
+ ror \$8,$tmp
+ xor $tmp,$sn
+___
+}
+
+# unlike decrypt case it does not pay off to parallelize enctransform
+sub enctransform()
+{ my ($t3,$r20,$r21)=($acc2,"%r8d","%r9d");
+
+$code.=<<___;
+ mov \$0x80808080,$t0
+ mov \$0x80808080,$t1
+ and $s0,$t0
+ and $s1,$t1
+ mov $t0,$acc0
+ mov $t1,$acc1
+ shr \$7,$t0
+ lea ($s0,$s0),$r20
+ shr \$7,$t1
+ lea ($s1,$s1),$r21
+ sub $t0,$acc0
+ sub $t1,$acc1
+ and \$0xfefefefe,$r20
+ and \$0xfefefefe,$r21
+ and \$0x1b1b1b1b,$acc0
+ and \$0x1b1b1b1b,$acc1
+ mov $s0,$t0
+ mov $s1,$t1
+ xor $acc0,$r20
+ xor $acc1,$r21
+
+ xor $r20,$s0
+ xor $r21,$s1
+ mov \$0x80808080,$t2
+ rol \$24,$s0
+ mov \$0x80808080,$t3
+ rol \$24,$s1
+ and $s2,$t2
+ and $s3,$t3
+ xor $r20,$s0
+ xor $r21,$s1
+ mov $t2,$acc0
+ ror \$16,$t0
+ mov $t3,$acc1
+ ror \$16,$t1
+ lea ($s2,$s2),$r20
+ shr \$7,$t2
+ xor $t0,$s0
+ shr \$7,$t3
+ xor $t1,$s1
+ ror \$8,$t0
+ lea ($s3,$s3),$r21
+ ror \$8,$t1
+ sub $t2,$acc0
+ sub $t3,$acc1
+ xor $t0,$s0
+ xor $t1,$s1
+
+ and \$0xfefefefe,$r20
+ and \$0xfefefefe,$r21
+ and \$0x1b1b1b1b,$acc0
+ and \$0x1b1b1b1b,$acc1
+ mov $s2,$t2
+ mov $s3,$t3
+ xor $acc0,$r20
+ xor $acc1,$r21
+
+ ror \$16,$t2
+ xor $r20,$s2
+ ror \$16,$t3
+ xor $r21,$s3
+ rol \$24,$s2
+ mov 0($sbox),$acc0 # prefetch Te4
+ rol \$24,$s3
+ xor $r20,$s2
+ mov 64($sbox),$acc1
+ xor $r21,$s3
+ mov 128($sbox),$r20
+ xor $t2,$s2
+ ror \$8,$t2
+ xor $t3,$s3
+ ror \$8,$t3
+ xor $t2,$s2
+ mov 192($sbox),$r21
+ xor $t3,$s3
+___
+}
+
+$code.=<<___;
+.type _x86_64_AES_encrypt_compact,\@abi-omnipotent
+.align 16
+_x86_64_AES_encrypt_compact:
+.cfi_startproc
+ lea 128($sbox),$inp # size optimization
+ mov 0-128($inp),$acc1 # prefetch Te4
+ mov 32-128($inp),$acc2
+ mov 64-128($inp),$t0
+ mov 96-128($inp),$t1
+ mov 128-128($inp),$acc1
+ mov 160-128($inp),$acc2
+ mov 192-128($inp),$t0
+ mov 224-128($inp),$t1
+ jmp .Lenc_loop_compact
+.align 16
+.Lenc_loop_compact:
+ xor 0($key),$s0 # xor with key
+ xor 4($key),$s1
+ xor 8($key),$s2
+ xor 12($key),$s3
+ lea 16($key),$key
+___
+ &enccompactvert();
+$code.=<<___;
+ cmp 16(%rsp),$key
+ je .Lenc_compact_done
+___
+ &enctransform();
+$code.=<<___;
+ jmp .Lenc_loop_compact
+.align 16
+.Lenc_compact_done:
+ xor 0($key),$s0
+ xor 4($key),$s1
+ xor 8($key),$s2
+ xor 12($key),$s3
+ .byte 0xf3,0xc3 # rep ret
+.cfi_endproc
+.size _x86_64_AES_encrypt_compact,.-_x86_64_AES_encrypt_compact
+___
+
+# void AES_encrypt (const void *inp,void *out,const AES_KEY *key);
+$code.=<<___;
+.globl AES_encrypt
+.type AES_encrypt,\@function,3
+.align 16
+.globl asm_AES_encrypt
+.hidden asm_AES_encrypt
+asm_AES_encrypt:
+AES_encrypt:
+.cfi_startproc
+ endbranch
+ mov %rsp,%rax
+.cfi_def_cfa_register %rax
+ push %rbx
+.cfi_push %rbx
+ push %rbp
+.cfi_push %rbp
+ push %r12
+.cfi_push %r12
+ push %r13
+.cfi_push %r13
+ push %r14
+.cfi_push %r14
+ push %r15
+.cfi_push %r15
+
+ # allocate frame "above" key schedule
+ lea -63(%rdx),%rcx # %rdx is key argument
+ and \$-64,%rsp
+ sub %rsp,%rcx
+ neg %rcx
+ and \$0x3c0,%rcx
+ sub %rcx,%rsp
+ sub \$32,%rsp
+
+ mov %rsi,16(%rsp) # save out
+ mov %rax,24(%rsp) # save original stack pointer
+.cfi_cfa_expression %rsp+24,deref,+8
+.Lenc_prologue:
+
+ mov %rdx,$key
+ mov 240($key),$rnds # load rounds
+
+ mov 0(%rdi),$s0 # load input vector
+ mov 4(%rdi),$s1
+ mov 8(%rdi),$s2
+ mov 12(%rdi),$s3
+
+ shl \$4,$rnds
+ lea ($key,$rnds),%rbp
+ mov $key,(%rsp) # key schedule
+ mov %rbp,8(%rsp) # end of key schedule
+
+ # pick Te4 copy which can't "overlap" with stack frame or key schedule
+ lea .LAES_Te+2048(%rip),$sbox
+ lea 768(%rsp),%rbp
+ sub $sbox,%rbp
+ and \$0x300,%rbp
+ lea ($sbox,%rbp),$sbox
+
+ call _x86_64_AES_encrypt_compact
+
+ mov 16(%rsp),$out # restore out
+ mov 24(%rsp),%rsi # restore saved stack pointer
+.cfi_def_cfa %rsi,8
+ mov $s0,0($out) # write output vector
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+ mov -48(%rsi),%r15
+.cfi_restore %r15
+ mov -40(%rsi),%r14
+.cfi_restore %r14
+ mov -32(%rsi),%r13
+.cfi_restore %r13
+ mov -24(%rsi),%r12
+.cfi_restore %r12
+ mov -16(%rsi),%rbp
+.cfi_restore %rbp
+ mov -8(%rsi),%rbx
+.cfi_restore %rbx
+ lea (%rsi),%rsp
+.cfi_def_cfa_register %rsp
+.Lenc_epilogue:
+ ret
+.cfi_endproc
+.size AES_encrypt,.-AES_encrypt
+___
+
+#------------------------------------------------------------------#
+
+sub decvert()
+{ my $t3="%r8d"; # zaps $inp!
+
+$code.=<<___;
+ # favor 3-way issue Opteron pipeline...
+ movzb `&lo("$s0")`,$acc0
+ movzb `&lo("$s1")`,$acc1
+ movzb `&lo("$s2")`,$acc2
+ mov 0($sbox,$acc0,8),$t0
+ mov 0($sbox,$acc1,8),$t1
+ mov 0($sbox,$acc2,8),$t2
+
+ movzb `&hi("$s3")`,$acc0
+ movzb `&hi("$s0")`,$acc1
+ movzb `&lo("$s3")`,$acc2
+ xor 3($sbox,$acc0,8),$t0
+ xor 3($sbox,$acc1,8),$t1
+ mov 0($sbox,$acc2,8),$t3
+
+ movzb `&hi("$s1")`,$acc0
+ shr \$16,$s0
+ movzb `&hi("$s2")`,$acc2
+ xor 3($sbox,$acc0,8),$t2
+ shr \$16,$s3
+ xor 3($sbox,$acc2,8),$t3
+
+ shr \$16,$s1
+ lea 16($key),$key
+ shr \$16,$s2
+
+ movzb `&lo("$s2")`,$acc0
+ movzb `&lo("$s3")`,$acc1
+ movzb `&lo("$s0")`,$acc2
+ xor 2($sbox,$acc0,8),$t0
+ xor 2($sbox,$acc1,8),$t1
+ xor 2($sbox,$acc2,8),$t2
+
+ movzb `&hi("$s1")`,$acc0
+ movzb `&hi("$s2")`,$acc1
+ movzb `&lo("$s1")`,$acc2
+ xor 1($sbox,$acc0,8),$t0
+ xor 1($sbox,$acc1,8),$t1
+ xor 2($sbox,$acc2,8),$t3
+
+ movzb `&hi("$s3")`,$acc0
+ mov 12($key),$s3
+ movzb `&hi("$s0")`,$acc2
+ xor 1($sbox,$acc0,8),$t2
+ mov 0($key),$s0
+ xor 1($sbox,$acc2,8),$t3
+
+ xor $t0,$s0
+ mov 4($key),$s1
+ mov 8($key),$s2
+ xor $t2,$s2
+ xor $t1,$s1
+ xor $t3,$s3
+___
+}
+
+sub declastvert()
+{ my $t3="%r8d"; # zaps $inp!
+
+$code.=<<___;
+ lea 2048($sbox),$sbox # size optimization
+ movzb `&lo("$s0")`,$acc0
+ movzb `&lo("$s1")`,$acc1
+ movzb `&lo("$s2")`,$acc2
+ movzb ($sbox,$acc0,1),$t0
+ movzb ($sbox,$acc1,1),$t1
+ movzb ($sbox,$acc2,1),$t2
+
+ movzb `&lo("$s3")`,$acc0
+ movzb `&hi("$s3")`,$acc1
+ movzb `&hi("$s0")`,$acc2
+ movzb ($sbox,$acc0,1),$t3
+ movzb ($sbox,$acc1,1),$acc1 #$t0
+ movzb ($sbox,$acc2,1),$acc2 #$t1
+
+ shl \$8,$acc1
+ shl \$8,$acc2
+
+ xor $acc1,$t0
+ xor $acc2,$t1
+ shr \$16,$s3
+
+ movzb `&hi("$s1")`,$acc0
+ movzb `&hi("$s2")`,$acc1
+ shr \$16,$s0
+ movzb ($sbox,$acc0,1),$acc0 #$t2
+ movzb ($sbox,$acc1,1),$acc1 #$t3
+
+ shl \$8,$acc0
+ shl \$8,$acc1
+ shr \$16,$s1
+ xor $acc0,$t2
+ xor $acc1,$t3
+ shr \$16,$s2
+
+ movzb `&lo("$s2")`,$acc0
+ movzb `&lo("$s3")`,$acc1
+ movzb `&lo("$s0")`,$acc2
+ movzb ($sbox,$acc0,1),$acc0 #$t0
+ movzb ($sbox,$acc1,1),$acc1 #$t1
+ movzb ($sbox,$acc2,1),$acc2 #$t2
+
+ shl \$16,$acc0
+ shl \$16,$acc1
+ shl \$16,$acc2
+
+ xor $acc0,$t0
+ xor $acc1,$t1
+ xor $acc2,$t2
+
+ movzb `&lo("$s1")`,$acc0
+ movzb `&hi("$s1")`,$acc1
+ movzb `&hi("$s2")`,$acc2
+ movzb ($sbox,$acc0,1),$acc0 #$t3
+ movzb ($sbox,$acc1,1),$acc1 #$t0
+ movzb ($sbox,$acc2,1),$acc2 #$t1
+
+ shl \$16,$acc0
+ shl \$24,$acc1
+ shl \$24,$acc2
+
+ xor $acc0,$t3
+ xor $acc1,$t0
+ xor $acc2,$t1
+
+ movzb `&hi("$s3")`,$acc0
+ movzb `&hi("$s0")`,$acc1
+ mov 16+12($key),$s3
+ movzb ($sbox,$acc0,1),$acc0 #$t2
+ movzb ($sbox,$acc1,1),$acc1 #$t3
+ mov 16+0($key),$s0
+
+ shl \$24,$acc0
+ shl \$24,$acc1
+
+ xor $acc0,$t2
+ xor $acc1,$t3
+
+ mov 16+4($key),$s1
+ mov 16+8($key),$s2
+ lea -2048($sbox),$sbox
+ xor $t0,$s0
+ xor $t1,$s1
+ xor $t2,$s2
+ xor $t3,$s3
+___
+}
+
+sub decstep()
+{ my ($i,@s) = @_;
+ my $tmp0=$acc0;
+ my $tmp1=$acc1;
+ my $tmp2=$acc2;
+ my $out=($t0,$t1,$t2,$s[0])[$i];
+
+ $code.=" mov $s[0],$out\n" if ($i!=3);
+ $tmp1=$s[2] if ($i==3);
+ $code.=" mov $s[2],$tmp1\n" if ($i!=3);
+ $code.=" and \$0xFF,$out\n";
+
+ $code.=" mov 0($sbox,$out,8),$out\n";
+ $code.=" shr \$16,$tmp1\n";
+ $tmp2=$s[3] if ($i==3);
+ $code.=" mov $s[3],$tmp2\n" if ($i!=3);
+
+ $tmp0=$s[1] if ($i==3);
+ $code.=" movzb ".&hi($s[1]).",$tmp0\n";
+ $code.=" and \$0xFF,$tmp1\n";
+ $code.=" shr \$24,$tmp2\n";
+
+ $code.=" xor 3($sbox,$tmp0,8),$out\n";
+ $code.=" xor 2($sbox,$tmp1,8),$out\n";
+ $code.=" xor 1($sbox,$tmp2,8),$out\n";
+
+ $code.=" mov $t2,$s[1]\n" if ($i==3);
+ $code.=" mov $t1,$s[2]\n" if ($i==3);
+ $code.=" mov $t0,$s[3]\n" if ($i==3);
+ $code.="\n";
+}
+
+sub declast()
+{ my ($i,@s)=@_;
+ my $tmp0=$acc0;
+ my $tmp1=$acc1;
+ my $tmp2=$acc2;
+ my $out=($t0,$t1,$t2,$s[0])[$i];
+
+ $code.=" mov $s[0],$out\n" if ($i!=3);
+ $tmp1=$s[2] if ($i==3);
+ $code.=" mov $s[2],$tmp1\n" if ($i!=3);
+ $code.=" and \$0xFF,$out\n";
+
+ $code.=" movzb 2048($sbox,$out,1),$out\n";
+ $code.=" shr \$16,$tmp1\n";
+ $tmp2=$s[3] if ($i==3);
+ $code.=" mov $s[3],$tmp2\n" if ($i!=3);
+
+ $tmp0=$s[1] if ($i==3);
+ $code.=" movzb ".&hi($s[1]).",$tmp0\n";
+ $code.=" and \$0xFF,$tmp1\n";
+ $code.=" shr \$24,$tmp2\n";
+
+ $code.=" movzb 2048($sbox,$tmp0,1),$tmp0\n";
+ $code.=" movzb 2048($sbox,$tmp1,1),$tmp1\n";
+ $code.=" movzb 2048($sbox,$tmp2,1),$tmp2\n";
+
+ $code.=" shl \$8,$tmp0\n";
+ $code.=" shl \$16,$tmp1\n";
+ $code.=" shl \$24,$tmp2\n";
+
+ $code.=" xor $tmp0,$out\n";
+ $code.=" mov $t2,$s[1]\n" if ($i==3);
+ $code.=" xor $tmp1,$out\n";
+ $code.=" mov $t1,$s[2]\n" if ($i==3);
+ $code.=" xor $tmp2,$out\n";
+ $code.=" mov $t0,$s[3]\n" if ($i==3);
+ $code.="\n";
+}
+
+$code.=<<___;
+.type _x86_64_AES_decrypt,\@abi-omnipotent
+.align 16
+_x86_64_AES_decrypt:
+.cfi_startproc
+ xor 0($key),$s0 # xor with key
+ xor 4($key),$s1
+ xor 8($key),$s2
+ xor 12($key),$s3
+
+ mov 240($key),$rnds # load key->rounds
+ sub \$1,$rnds
+ jmp .Ldec_loop
+.align 16
+.Ldec_loop:
+___
+ if ($verticalspin) { &decvert(); }
+ else { &decstep(0,$s0,$s3,$s2,$s1);
+ &decstep(1,$s1,$s0,$s3,$s2);
+ &decstep(2,$s2,$s1,$s0,$s3);
+ &decstep(3,$s3,$s2,$s1,$s0);
+ $code.=<<___;
+ lea 16($key),$key
+ xor 0($key),$s0 # xor with key
+ xor 4($key),$s1
+ xor 8($key),$s2
+ xor 12($key),$s3
+___
+ }
+$code.=<<___;
+ sub \$1,$rnds
+ jnz .Ldec_loop
+___
+ if ($verticalspin) { &declastvert(); }
+ else { &declast(0,$s0,$s3,$s2,$s1);
+ &declast(1,$s1,$s0,$s3,$s2);
+ &declast(2,$s2,$s1,$s0,$s3);
+ &declast(3,$s3,$s2,$s1,$s0);
+ $code.=<<___;
+ xor 16+0($key),$s0 # xor with key
+ xor 16+4($key),$s1
+ xor 16+8($key),$s2
+ xor 16+12($key),$s3
+___
+ }
+$code.=<<___;
+ .byte 0xf3,0xc3 # rep ret
+.cfi_endproc
+.size _x86_64_AES_decrypt,.-_x86_64_AES_decrypt
+___
+
+sub deccompactvert()
+{ my ($t3,$t4,$t5)=("%r8d","%r9d","%r13d");
+
+$code.=<<___;
+ movzb `&lo("$s0")`,$t0
+ movzb `&lo("$s1")`,$t1
+ movzb `&lo("$s2")`,$t2
+ movzb `&lo("$s3")`,$t3
+ movzb `&hi("$s3")`,$acc0
+ movzb `&hi("$s0")`,$acc1
+ shr \$16,$s3
+ movzb `&hi("$s1")`,$acc2
+ movzb ($sbox,$t0,1),$t0
+ movzb ($sbox,$t1,1),$t1
+ movzb ($sbox,$t2,1),$t2
+ movzb ($sbox,$t3,1),$t3
+
+ movzb ($sbox,$acc0,1),$t4 #$t0
+ movzb `&hi("$s2")`,$acc0
+ movzb ($sbox,$acc1,1),$t5 #$t1
+ movzb ($sbox,$acc2,1),$acc2 #$t2
+ movzb ($sbox,$acc0,1),$acc0 #$t3
+
+ shr \$16,$s2
+ shl \$8,$t5
+ shl \$8,$t4
+ movzb `&lo("$s2")`,$acc1
+ shr \$16,$s0
+ xor $t4,$t0
+ shr \$16,$s1
+ movzb `&lo("$s3")`,$t4
+
+ shl \$8,$acc2
+ xor $t5,$t1
+ shl \$8,$acc0
+ movzb `&lo("$s0")`,$t5
+ movzb ($sbox,$acc1,1),$acc1 #$t0
+ xor $acc2,$t2
+ movzb `&lo("$s1")`,$acc2
+
+ shl \$16,$acc1
+ xor $acc0,$t3
+ movzb ($sbox,$t4,1),$t4 #$t1
+ movzb `&hi("$s1")`,$acc0
+ movzb ($sbox,$acc2,1),$acc2 #$t3
+ xor $acc1,$t0
+ movzb ($sbox,$t5,1),$t5 #$t2
+ movzb `&hi("$s2")`,$acc1
+
+ shl \$16,$acc2
+ shl \$16,$t4
+ shl \$16,$t5
+ xor $acc2,$t3
+ movzb `&hi("$s3")`,$acc2
+ xor $t4,$t1
+ shr \$8,$s0
+ xor $t5,$t2
+
+ movzb ($sbox,$acc0,1),$acc0 #$t0
+ movzb ($sbox,$acc1,1),$s1 #$t1
+ movzb ($sbox,$acc2,1),$s2 #$t2
+ movzb ($sbox,$s0,1),$s3 #$t3
+
+ mov $t0,$s0
+ shl \$24,$acc0
+ shl \$24,$s1
+ shl \$24,$s2
+ xor $acc0,$s0
+ shl \$24,$s3
+ xor $t1,$s1
+ xor $t2,$s2
+ xor $t3,$s3
+___
+}
+
+# parallelized version! input is pair of 64-bit values: %rax=s1.s0
+# and %rcx=s3.s2, output is four 32-bit values in %eax=s0, %ebx=s1,
+# %ecx=s2 and %edx=s3.
+sub dectransform()
+{ my ($tp10,$tp20,$tp40,$tp80,$acc0)=("%rax","%r8", "%r9", "%r10","%rbx");
+ my ($tp18,$tp28,$tp48,$tp88,$acc8)=("%rcx","%r11","%r12","%r13","%rdx");
+ my $prefetch = shift;
+
+$code.=<<___;
+ mov $mask80,$tp40
+ mov $mask80,$tp48
+ and $tp10,$tp40
+ and $tp18,$tp48
+ mov $tp40,$acc0
+ mov $tp48,$acc8
+ shr \$7,$tp40
+ lea ($tp10,$tp10),$tp20
+ shr \$7,$tp48
+ lea ($tp18,$tp18),$tp28
+ sub $tp40,$acc0
+ sub $tp48,$acc8
+ and $maskfe,$tp20
+ and $maskfe,$tp28
+ and $mask1b,$acc0
+ and $mask1b,$acc8
+ xor $acc0,$tp20
+ xor $acc8,$tp28
+ mov $mask80,$tp80
+ mov $mask80,$tp88
+
+ and $tp20,$tp80
+ and $tp28,$tp88
+ mov $tp80,$acc0
+ mov $tp88,$acc8
+ shr \$7,$tp80
+ lea ($tp20,$tp20),$tp40
+ shr \$7,$tp88
+ lea ($tp28,$tp28),$tp48
+ sub $tp80,$acc0
+ sub $tp88,$acc8
+ and $maskfe,$tp40
+ and $maskfe,$tp48
+ and $mask1b,$acc0
+ and $mask1b,$acc8
+ xor $acc0,$tp40
+ xor $acc8,$tp48
+ mov $mask80,$tp80
+ mov $mask80,$tp88
+
+ and $tp40,$tp80
+ and $tp48,$tp88
+ mov $tp80,$acc0
+ mov $tp88,$acc8
+ shr \$7,$tp80
+ xor $tp10,$tp20 # tp2^=tp1
+ shr \$7,$tp88
+ xor $tp18,$tp28 # tp2^=tp1
+ sub $tp80,$acc0
+ sub $tp88,$acc8
+ lea ($tp40,$tp40),$tp80
+ lea ($tp48,$tp48),$tp88
+ xor $tp10,$tp40 # tp4^=tp1
+ xor $tp18,$tp48 # tp4^=tp1
+ and $maskfe,$tp80
+ and $maskfe,$tp88
+ and $mask1b,$acc0
+ and $mask1b,$acc8
+ xor $acc0,$tp80
+ xor $acc8,$tp88
+
+ xor $tp80,$tp10 # tp1^=tp8
+ xor $tp88,$tp18 # tp1^=tp8
+ xor $tp80,$tp20 # tp2^tp1^=tp8
+ xor $tp88,$tp28 # tp2^tp1^=tp8
+ mov $tp10,$acc0
+ mov $tp18,$acc8
+ xor $tp80,$tp40 # tp4^tp1^=tp8
+ shr \$32,$acc0
+ xor $tp88,$tp48 # tp4^tp1^=tp8
+ shr \$32,$acc8
+ xor $tp20,$tp80 # tp8^=tp8^tp2^tp1=tp2^tp1
+ rol \$8,`&LO("$tp10")` # ROTATE(tp1^tp8,8)
+ xor $tp28,$tp88 # tp8^=tp8^tp2^tp1=tp2^tp1
+ rol \$8,`&LO("$tp18")` # ROTATE(tp1^tp8,8)
+ xor $tp40,$tp80 # tp2^tp1^=tp8^tp4^tp1=tp8^tp4^tp2
+ rol \$8,`&LO("$acc0")` # ROTATE(tp1^tp8,8)
+ xor $tp48,$tp88 # tp2^tp1^=tp8^tp4^tp1=tp8^tp4^tp2
+
+ rol \$8,`&LO("$acc8")` # ROTATE(tp1^tp8,8)
+ xor `&LO("$tp80")`,`&LO("$tp10")`
+ shr \$32,$tp80
+ xor `&LO("$tp88")`,`&LO("$tp18")`
+ shr \$32,$tp88
+ xor `&LO("$tp80")`,`&LO("$acc0")`
+ xor `&LO("$tp88")`,`&LO("$acc8")`
+
+ mov $tp20,$tp80
+ rol \$24,`&LO("$tp20")` # ROTATE(tp2^tp1^tp8,24)
+ mov $tp28,$tp88
+ rol \$24,`&LO("$tp28")` # ROTATE(tp2^tp1^tp8,24)
+ shr \$32,$tp80
+ xor `&LO("$tp20")`,`&LO("$tp10")`
+ shr \$32,$tp88
+ xor `&LO("$tp28")`,`&LO("$tp18")`
+ rol \$24,`&LO("$tp80")` # ROTATE(tp2^tp1^tp8,24)
+ mov $tp40,$tp20
+ rol \$24,`&LO("$tp88")` # ROTATE(tp2^tp1^tp8,24)
+ mov $tp48,$tp28
+ shr \$32,$tp20
+ xor `&LO("$tp80")`,`&LO("$acc0")`
+ shr \$32,$tp28
+ xor `&LO("$tp88")`,`&LO("$acc8")`
+
+ `"mov 0($sbox),$mask80" if ($prefetch)`
+ rol \$16,`&LO("$tp40")` # ROTATE(tp4^tp1^tp8,16)
+ `"mov 64($sbox),$maskfe" if ($prefetch)`
+ rol \$16,`&LO("$tp48")` # ROTATE(tp4^tp1^tp8,16)
+ `"mov 128($sbox),$mask1b" if ($prefetch)`
+ rol \$16,`&LO("$tp20")` # ROTATE(tp4^tp1^tp8,16)
+ `"mov 192($sbox),$tp80" if ($prefetch)`
+ xor `&LO("$tp40")`,`&LO("$tp10")`
+ rol \$16,`&LO("$tp28")` # ROTATE(tp4^tp1^tp8,16)
+ xor `&LO("$tp48")`,`&LO("$tp18")`
+ `"mov 256($sbox),$tp88" if ($prefetch)`
+ xor `&LO("$tp20")`,`&LO("$acc0")`
+ xor `&LO("$tp28")`,`&LO("$acc8")`
+___
+}
+
+$code.=<<___;
+.type _x86_64_AES_decrypt_compact,\@abi-omnipotent
+.align 16
+_x86_64_AES_decrypt_compact:
+.cfi_startproc
+ lea 128($sbox),$inp # size optimization
+ mov 0-128($inp),$acc1 # prefetch Td4
+ mov 32-128($inp),$acc2
+ mov 64-128($inp),$t0
+ mov 96-128($inp),$t1
+ mov 128-128($inp),$acc1
+ mov 160-128($inp),$acc2
+ mov 192-128($inp),$t0
+ mov 224-128($inp),$t1
+ jmp .Ldec_loop_compact
+
+.align 16
+.Ldec_loop_compact:
+ xor 0($key),$s0 # xor with key
+ xor 4($key),$s1
+ xor 8($key),$s2
+ xor 12($key),$s3
+ lea 16($key),$key
+___
+ &deccompactvert();
+$code.=<<___;
+ cmp 16(%rsp),$key
+ je .Ldec_compact_done
+
+ mov 256+0($sbox),$mask80
+ shl \$32,%rbx
+ shl \$32,%rdx
+ mov 256+8($sbox),$maskfe
+ or %rbx,%rax
+ or %rdx,%rcx
+ mov 256+16($sbox),$mask1b
+___
+ &dectransform(1);
+$code.=<<___;
+ jmp .Ldec_loop_compact
+.align 16
+.Ldec_compact_done:
+ xor 0($key),$s0
+ xor 4($key),$s1
+ xor 8($key),$s2
+ xor 12($key),$s3
+ .byte 0xf3,0xc3 # rep ret
+.cfi_endproc
+.size _x86_64_AES_decrypt_compact,.-_x86_64_AES_decrypt_compact
+___
+
+# void AES_decrypt (const void *inp,void *out,const AES_KEY *key);
+$code.=<<___;
+.globl AES_decrypt
+.type AES_decrypt,\@function,3
+.align 16
+.globl asm_AES_decrypt
+.hidden asm_AES_decrypt
+asm_AES_decrypt:
+AES_decrypt:
+.cfi_startproc
+ endbranch
+ mov %rsp,%rax
+.cfi_def_cfa_register %rax
+ push %rbx
+.cfi_push %rbx
+ push %rbp
+.cfi_push %rbp
+ push %r12
+.cfi_push %r12
+ push %r13
+.cfi_push %r13
+ push %r14
+.cfi_push %r14
+ push %r15
+.cfi_push %r15
+
+ # allocate frame "above" key schedule
+ lea -63(%rdx),%rcx # %rdx is key argument
+ and \$-64,%rsp
+ sub %rsp,%rcx
+ neg %rcx
+ and \$0x3c0,%rcx
+ sub %rcx,%rsp
+ sub \$32,%rsp
+
+ mov %rsi,16(%rsp) # save out
+ mov %rax,24(%rsp) # save original stack pointer
+.cfi_cfa_expression %rsp+24,deref,+8
+.Ldec_prologue:
+
+ mov %rdx,$key
+ mov 240($key),$rnds # load rounds
+
+ mov 0(%rdi),$s0 # load input vector
+ mov 4(%rdi),$s1
+ mov 8(%rdi),$s2
+ mov 12(%rdi),$s3
+
+ shl \$4,$rnds
+ lea ($key,$rnds),%rbp
+ mov $key,(%rsp) # key schedule
+ mov %rbp,8(%rsp) # end of key schedule
+
+ # pick Td4 copy which can't "overlap" with stack frame or key schedule
+ lea .LAES_Td+2048(%rip),$sbox
+ lea 768(%rsp),%rbp
+ sub $sbox,%rbp
+ and \$0x300,%rbp
+ lea ($sbox,%rbp),$sbox
+ shr \$3,%rbp # recall "magic" constants!
+ add %rbp,$sbox
+
+ call _x86_64_AES_decrypt_compact
+
+ mov 16(%rsp),$out # restore out
+ mov 24(%rsp),%rsi # restore saved stack pointer
+.cfi_def_cfa %rsi,8
+ mov $s0,0($out) # write output vector
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+ mov -48(%rsi),%r15
+.cfi_restore %r15
+ mov -40(%rsi),%r14
+.cfi_restore %r14
+ mov -32(%rsi),%r13
+.cfi_restore %r13
+ mov -24(%rsi),%r12
+.cfi_restore %r12
+ mov -16(%rsi),%rbp
+.cfi_restore %rbp
+ mov -8(%rsi),%rbx
+.cfi_restore %rbx
+ lea (%rsi),%rsp
+.cfi_def_cfa_register %rsp
+.Ldec_epilogue:
+ ret
+.cfi_endproc
+.size AES_decrypt,.-AES_decrypt
+___
+#------------------------------------------------------------------#
+
+sub enckey()
+{
+$code.=<<___;
+ movz %dl,%esi # rk[i]>>0
+ movzb -128(%rbp,%rsi),%ebx
+ movz %dh,%esi # rk[i]>>8
+ shl \$24,%ebx
+ xor %ebx,%eax
+
+ movzb -128(%rbp,%rsi),%ebx
+ shr \$16,%edx
+ movz %dl,%esi # rk[i]>>16
+ xor %ebx,%eax
+
+ movzb -128(%rbp,%rsi),%ebx
+ movz %dh,%esi # rk[i]>>24
+ shl \$8,%ebx
+ xor %ebx,%eax
+
+ movzb -128(%rbp,%rsi),%ebx
+ shl \$16,%ebx
+ xor %ebx,%eax
+
+ xor 1024-128(%rbp,%rcx,4),%eax # rcon
+___
+}
+
+# int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+# AES_KEY *key)
+$code.=<<___;
+.globl AES_set_encrypt_key
+.type AES_set_encrypt_key,\@function,3
+.align 16
+AES_set_encrypt_key:
+.cfi_startproc
+ endbranch
+ push %rbx
+.cfi_push %rbx
+ push %rbp
+.cfi_push %rbp
+ push %r12 # redundant, but allows to share
+.cfi_push %r12
+ push %r13 # exception handler...
+.cfi_push %r13
+ push %r14
+.cfi_push %r14
+ push %r15
+.cfi_push %r15
+ sub \$8,%rsp
+.cfi_adjust_cfa_offset 8
+.Lenc_key_prologue:
+
+ call _x86_64_AES_set_encrypt_key
+
+ mov 40(%rsp),%rbp
+.cfi_restore %rbp
+ mov 48(%rsp),%rbx
+.cfi_restore %rbx
+ add \$56,%rsp
+.cfi_adjust_cfa_offset -56
+.Lenc_key_epilogue:
+ ret
+.cfi_endproc
+.size AES_set_encrypt_key,.-AES_set_encrypt_key
+
+.type _x86_64_AES_set_encrypt_key,\@abi-omnipotent
+.align 16
+_x86_64_AES_set_encrypt_key:
+.cfi_startproc
+ mov %esi,%ecx # %ecx=bits
+ mov %rdi,%rsi # %rsi=userKey
+ mov %rdx,%rdi # %rdi=key
+
+ test \$-1,%rsi
+ jz .Lbadpointer
+ test \$-1,%rdi
+ jz .Lbadpointer
+
+ lea .LAES_Te(%rip),%rbp
+ lea 2048+128(%rbp),%rbp
+
+ # prefetch Te4
+ mov 0-128(%rbp),%eax
+ mov 32-128(%rbp),%ebx
+ mov 64-128(%rbp),%r8d
+ mov 96-128(%rbp),%edx
+ mov 128-128(%rbp),%eax
+ mov 160-128(%rbp),%ebx
+ mov 192-128(%rbp),%r8d
+ mov 224-128(%rbp),%edx
+
+ cmp \$128,%ecx
+ je .L10rounds
+ cmp \$192,%ecx
+ je .L12rounds
+ cmp \$256,%ecx
+ je .L14rounds
+ mov \$-2,%rax # invalid number of bits
+ jmp .Lexit
+
+.L10rounds:
+ mov 0(%rsi),%rax # copy first 4 dwords
+ mov 8(%rsi),%rdx
+ mov %rax,0(%rdi)
+ mov %rdx,8(%rdi)
+
+ shr \$32,%rdx
+ xor %ecx,%ecx
+ jmp .L10shortcut
+.align 4
+.L10loop:
+ mov 0(%rdi),%eax # rk[0]
+ mov 12(%rdi),%edx # rk[3]
+.L10shortcut:
+___
+ &enckey ();
+$code.=<<___;
+ mov %eax,16(%rdi) # rk[4]
+ xor 4(%rdi),%eax
+ mov %eax,20(%rdi) # rk[5]
+ xor 8(%rdi),%eax
+ mov %eax,24(%rdi) # rk[6]
+ xor 12(%rdi),%eax
+ mov %eax,28(%rdi) # rk[7]
+ add \$1,%ecx
+ lea 16(%rdi),%rdi
+ cmp \$10,%ecx
+ jl .L10loop
+
+ movl \$10,80(%rdi) # setup number of rounds
+ xor %rax,%rax
+ jmp .Lexit
+
+.L12rounds:
+ mov 0(%rsi),%rax # copy first 6 dwords
+ mov 8(%rsi),%rbx
+ mov 16(%rsi),%rdx
+ mov %rax,0(%rdi)
+ mov %rbx,8(%rdi)
+ mov %rdx,16(%rdi)
+
+ shr \$32,%rdx
+ xor %ecx,%ecx
+ jmp .L12shortcut
+.align 4
+.L12loop:
+ mov 0(%rdi),%eax # rk[0]
+ mov 20(%rdi),%edx # rk[5]
+.L12shortcut:
+___
+ &enckey ();
+$code.=<<___;
+ mov %eax,24(%rdi) # rk[6]
+ xor 4(%rdi),%eax
+ mov %eax,28(%rdi) # rk[7]
+ xor 8(%rdi),%eax
+ mov %eax,32(%rdi) # rk[8]
+ xor 12(%rdi),%eax
+ mov %eax,36(%rdi) # rk[9]
+
+ cmp \$7,%ecx
+ je .L12break
+ add \$1,%ecx
+
+ xor 16(%rdi),%eax
+ mov %eax,40(%rdi) # rk[10]
+ xor 20(%rdi),%eax
+ mov %eax,44(%rdi) # rk[11]
+
+ lea 24(%rdi),%rdi
+ jmp .L12loop
+.L12break:
+ movl \$12,72(%rdi) # setup number of rounds
+ xor %rax,%rax
+ jmp .Lexit
+
+.L14rounds:
+ mov 0(%rsi),%rax # copy first 8 dwords
+ mov 8(%rsi),%rbx
+ mov 16(%rsi),%rcx
+ mov 24(%rsi),%rdx
+ mov %rax,0(%rdi)
+ mov %rbx,8(%rdi)
+ mov %rcx,16(%rdi)
+ mov %rdx,24(%rdi)
+
+ shr \$32,%rdx
+ xor %ecx,%ecx
+ jmp .L14shortcut
+.align 4
+.L14loop:
+ mov 0(%rdi),%eax # rk[0]
+ mov 28(%rdi),%edx # rk[4]
+.L14shortcut:
+___
+ &enckey ();
+$code.=<<___;
+ mov %eax,32(%rdi) # rk[8]
+ xor 4(%rdi),%eax
+ mov %eax,36(%rdi) # rk[9]
+ xor 8(%rdi),%eax
+ mov %eax,40(%rdi) # rk[10]
+ xor 12(%rdi),%eax
+ mov %eax,44(%rdi) # rk[11]
+
+ cmp \$6,%ecx
+ je .L14break
+ add \$1,%ecx
+
+ mov %eax,%edx
+ mov 16(%rdi),%eax # rk[4]
+ movz %dl,%esi # rk[11]>>0
+ movzb -128(%rbp,%rsi),%ebx
+ movz %dh,%esi # rk[11]>>8
+ xor %ebx,%eax
+
+ movzb -128(%rbp,%rsi),%ebx
+ shr \$16,%edx
+ shl \$8,%ebx
+ movz %dl,%esi # rk[11]>>16
+ xor %ebx,%eax
+
+ movzb -128(%rbp,%rsi),%ebx
+ movz %dh,%esi # rk[11]>>24
+ shl \$16,%ebx
+ xor %ebx,%eax
+
+ movzb -128(%rbp,%rsi),%ebx
+ shl \$24,%ebx
+ xor %ebx,%eax
+
+ mov %eax,48(%rdi) # rk[12]
+ xor 20(%rdi),%eax
+ mov %eax,52(%rdi) # rk[13]
+ xor 24(%rdi),%eax
+ mov %eax,56(%rdi) # rk[14]
+ xor 28(%rdi),%eax
+ mov %eax,60(%rdi) # rk[15]
+
+ lea 32(%rdi),%rdi
+ jmp .L14loop
+.L14break:
+ movl \$14,48(%rdi) # setup number of rounds
+ xor %rax,%rax
+ jmp .Lexit
+
+.Lbadpointer:
+ mov \$-1,%rax
+.Lexit:
+ .byte 0xf3,0xc3 # rep ret
+.cfi_endproc
+.size _x86_64_AES_set_encrypt_key,.-_x86_64_AES_set_encrypt_key
+___
+
+sub deckey_ref()
+{ my ($i,$ptr,$te,$td) = @_;
+ my ($tp1,$tp2,$tp4,$tp8,$acc)=("%eax","%ebx","%edi","%edx","%r8d");
+$code.=<<___;
+ mov $i($ptr),$tp1
+ mov $tp1,$acc
+ and \$0x80808080,$acc
+ mov $acc,$tp4
+ shr \$7,$tp4
+ lea 0($tp1,$tp1),$tp2
+ sub $tp4,$acc
+ and \$0xfefefefe,$tp2
+ and \$0x1b1b1b1b,$acc
+ xor $tp2,$acc
+ mov $acc,$tp2
+
+ and \$0x80808080,$acc
+ mov $acc,$tp8
+ shr \$7,$tp8
+ lea 0($tp2,$tp2),$tp4
+ sub $tp8,$acc
+ and \$0xfefefefe,$tp4
+ and \$0x1b1b1b1b,$acc
+ xor $tp1,$tp2 # tp2^tp1
+ xor $tp4,$acc
+ mov $acc,$tp4
+
+ and \$0x80808080,$acc
+ mov $acc,$tp8
+ shr \$7,$tp8
+ sub $tp8,$acc
+ lea 0($tp4,$tp4),$tp8
+ xor $tp1,$tp4 # tp4^tp1
+ and \$0xfefefefe,$tp8
+ and \$0x1b1b1b1b,$acc
+ xor $acc,$tp8
+
+ xor $tp8,$tp1 # tp1^tp8
+ rol \$8,$tp1 # ROTATE(tp1^tp8,8)
+ xor $tp8,$tp2 # tp2^tp1^tp8
+ xor $tp8,$tp4 # tp4^tp1^tp8
+ xor $tp2,$tp8
+ xor $tp4,$tp8 # tp8^(tp8^tp4^tp1)^(tp8^tp2^tp1)=tp8^tp4^tp2
+
+ xor $tp8,$tp1
+ rol \$24,$tp2 # ROTATE(tp2^tp1^tp8,24)
+ xor $tp2,$tp1
+ rol \$16,$tp4 # ROTATE(tp4^tp1^tp8,16)
+ xor $tp4,$tp1
+
+ mov $tp1,$i($ptr)
+___
+}
+
+# int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+# AES_KEY *key)
+$code.=<<___;
+.globl AES_set_decrypt_key
+.type AES_set_decrypt_key,\@function,3
+.align 16
+AES_set_decrypt_key:
+.cfi_startproc
+ endbranch
+ push %rbx
+.cfi_push %rbx
+ push %rbp
+.cfi_push %rbp
+ push %r12
+.cfi_push %r12
+ push %r13
+.cfi_push %r13
+ push %r14
+.cfi_push %r14
+ push %r15
+.cfi_push %r15
+ push %rdx # save key schedule
+.cfi_adjust_cfa_offset 8
+.Ldec_key_prologue:
+
+ call _x86_64_AES_set_encrypt_key
+ mov (%rsp),%r8 # restore key schedule
+ cmp \$0,%eax
+ jne .Labort
+
+ mov 240(%r8),%r14d # pull number of rounds
+ xor %rdi,%rdi
+ lea (%rdi,%r14d,4),%rcx
+ mov %r8,%rsi
+ lea (%r8,%rcx,4),%rdi # pointer to last chunk
+.align 4
+.Linvert:
+ mov 0(%rsi),%rax
+ mov 8(%rsi),%rbx
+ mov 0(%rdi),%rcx
+ mov 8(%rdi),%rdx
+ mov %rax,0(%rdi)
+ mov %rbx,8(%rdi)
+ mov %rcx,0(%rsi)
+ mov %rdx,8(%rsi)
+ lea 16(%rsi),%rsi
+ lea -16(%rdi),%rdi
+ cmp %rsi,%rdi
+ jne .Linvert
+
+ lea .LAES_Te+2048+1024(%rip),%rax # rcon
+
+ mov 40(%rax),$mask80
+ mov 48(%rax),$maskfe
+ mov 56(%rax),$mask1b
+
+ mov %r8,$key
+ sub \$1,%r14d
+.align 4
+.Lpermute:
+ lea 16($key),$key
+ mov 0($key),%rax
+ mov 8($key),%rcx
+___
+ &dectransform ();
+$code.=<<___;
+ mov %eax,0($key)
+ mov %ebx,4($key)
+ mov %ecx,8($key)
+ mov %edx,12($key)
+ sub \$1,%r14d
+ jnz .Lpermute
+
+ xor %rax,%rax
+.Labort:
+ mov 8(%rsp),%r15
+.cfi_restore %r15
+ mov 16(%rsp),%r14
+.cfi_restore %r14
+ mov 24(%rsp),%r13
+.cfi_restore %r13
+ mov 32(%rsp),%r12
+.cfi_restore %r12
+ mov 40(%rsp),%rbp
+.cfi_restore %rbp
+ mov 48(%rsp),%rbx
+.cfi_restore %rbx
+ add \$56,%rsp
+.cfi_adjust_cfa_offset -56
+.Ldec_key_epilogue:
+ ret
+.cfi_endproc
+.size AES_set_decrypt_key,.-AES_set_decrypt_key
+___
+
+# void AES_cbc_encrypt (const void char *inp, unsigned char *out,
+# size_t length, const AES_KEY *key,
+# unsigned char *ivp,const int enc);
+{
+# stack frame layout
+# -8(%rsp) return address
+my $keyp="0(%rsp)"; # one to pass as $key
+my $keyend="8(%rsp)"; # &(keyp->rd_key[4*keyp->rounds])
+my $_rsp="16(%rsp)"; # saved %rsp
+my $_inp="24(%rsp)"; # copy of 1st parameter, inp
+my $_out="32(%rsp)"; # copy of 2nd parameter, out
+my $_len="40(%rsp)"; # copy of 3rd parameter, length
+my $_key="48(%rsp)"; # copy of 4th parameter, key
+my $_ivp="56(%rsp)"; # copy of 5th parameter, ivp
+my $ivec="64(%rsp)"; # ivec[16]
+my $aes_key="80(%rsp)"; # copy of aes_key
+my $mark="80+240(%rsp)"; # copy of aes_key->rounds
+
+$code.=<<___;
+.globl AES_cbc_encrypt
+.type AES_cbc_encrypt,\@function,6
+.align 16
+.extern OPENSSL_ia32cap_P
+.globl asm_AES_cbc_encrypt
+.hidden asm_AES_cbc_encrypt
+asm_AES_cbc_encrypt:
+AES_cbc_encrypt:
+.cfi_startproc
+ endbranch
+ cmp \$0,%rdx # check length
+ je .Lcbc_epilogue
+ pushfq
+# This could be .cfi_push 49, but libunwind fails on registers it does not
+# recognize. See https://bugzilla.redhat.com/show_bug.cgi?id=217087.
+.cfi_adjust_cfa_offset 8
+ push %rbx
+.cfi_push %rbx
+ push %rbp
+.cfi_push %rbp
+ push %r12
+.cfi_push %r12
+ push %r13
+.cfi_push %r13
+ push %r14
+.cfi_push %r14
+ push %r15
+.cfi_push %r15
+.Lcbc_prologue:
+
+ cld
+ mov %r9d,%r9d # clear upper half of enc
+
+ lea .LAES_Te(%rip),$sbox
+ lea .LAES_Td(%rip),%r10
+ cmp \$0,%r9
+ cmoveq %r10,$sbox
+
+.cfi_remember_state
+ mov OPENSSL_ia32cap_P(%rip),%r10d
+ cmp \$$speed_limit,%rdx
+ jb .Lcbc_slow_prologue
+ test \$15,%rdx
+ jnz .Lcbc_slow_prologue
+ bt \$28,%r10d
+ jc .Lcbc_slow_prologue
+
+ # allocate aligned stack frame...
+ lea -88-248(%rsp),$key
+ and \$-64,$key
+
+ # ... and make sure it doesn't alias with AES_T[ed] modulo 4096
+ mov $sbox,%r10
+ lea 2304($sbox),%r11
+ mov $key,%r12
+ and \$0xFFF,%r10 # s = $sbox&0xfff
+ and \$0xFFF,%r11 # e = ($sbox+2048)&0xfff
+ and \$0xFFF,%r12 # p = %rsp&0xfff
+
+ cmp %r11,%r12 # if (p=>e) %rsp =- (p-e);
+ jb .Lcbc_te_break_out
+ sub %r11,%r12
+ sub %r12,$key
+ jmp .Lcbc_te_ok
+.Lcbc_te_break_out: # else %rsp -= (p-s)&0xfff + framesz
+ sub %r10,%r12
+ and \$0xFFF,%r12
+ add \$320,%r12
+ sub %r12,$key
+.align 4
+.Lcbc_te_ok:
+
+ xchg %rsp,$key
+.cfi_def_cfa_register $key
+ #add \$8,%rsp # reserve for return address!
+ mov $key,$_rsp # save %rsp
+.cfi_cfa_expression $_rsp,deref,+64
+.Lcbc_fast_body:
+ mov %rdi,$_inp # save copy of inp
+ mov %rsi,$_out # save copy of out
+ mov %rdx,$_len # save copy of len
+ mov %rcx,$_key # save copy of key
+ mov %r8,$_ivp # save copy of ivp
+ movl \$0,$mark # copy of aes_key->rounds = 0;
+ mov %r8,%rbp # rearrange input arguments
+ mov %r9,%rbx
+ mov %rsi,$out
+ mov %rdi,$inp
+ mov %rcx,$key
+
+ mov 240($key),%eax # key->rounds
+ # do we copy key schedule to stack?
+ mov $key,%r10
+ sub $sbox,%r10
+ and \$0xfff,%r10
+ cmp \$2304,%r10
+ jb .Lcbc_do_ecopy
+ cmp \$4096-248,%r10
+ jb .Lcbc_skip_ecopy
+.align 4
+.Lcbc_do_ecopy:
+ mov $key,%rsi
+ lea $aes_key,%rdi
+ lea $aes_key,$key
+ mov \$240/8,%ecx
+ .long 0x90A548F3 # rep movsq
+ mov %eax,(%rdi) # copy aes_key->rounds
+.Lcbc_skip_ecopy:
+ mov $key,$keyp # save key pointer
+
+ mov \$18,%ecx
+.align 4
+.Lcbc_prefetch_te:
+ mov 0($sbox),%r10
+ mov 32($sbox),%r11
+ mov 64($sbox),%r12
+ mov 96($sbox),%r13
+ lea 128($sbox),$sbox
+ sub \$1,%ecx
+ jnz .Lcbc_prefetch_te
+ lea -2304($sbox),$sbox
+
+ cmp \$0,%rbx
+ je .LFAST_DECRYPT
+
+#----------------------------- ENCRYPT -----------------------------#
+ mov 0(%rbp),$s0 # load iv
+ mov 4(%rbp),$s1
+ mov 8(%rbp),$s2
+ mov 12(%rbp),$s3
+
+.align 4
+.Lcbc_fast_enc_loop:
+ xor 0($inp),$s0
+ xor 4($inp),$s1
+ xor 8($inp),$s2
+ xor 12($inp),$s3
+ mov $keyp,$key # restore key
+ mov $inp,$_inp # if ($verticalspin) save inp
+
+ call _x86_64_AES_encrypt
+
+ mov $_inp,$inp # if ($verticalspin) restore inp
+ mov $_len,%r10
+ mov $s0,0($out)
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+ lea 16($inp),$inp
+ lea 16($out),$out
+ sub \$16,%r10
+ test \$-16,%r10
+ mov %r10,$_len
+ jnz .Lcbc_fast_enc_loop
+ mov $_ivp,%rbp # restore ivp
+ mov $s0,0(%rbp) # save ivec
+ mov $s1,4(%rbp)
+ mov $s2,8(%rbp)
+ mov $s3,12(%rbp)
+
+ jmp .Lcbc_fast_cleanup
+
+#----------------------------- DECRYPT -----------------------------#
+.align 16
+.LFAST_DECRYPT:
+ cmp $inp,$out
+ je .Lcbc_fast_dec_in_place
+
+ mov %rbp,$ivec
+.align 4
+.Lcbc_fast_dec_loop:
+ mov 0($inp),$s0 # read input
+ mov 4($inp),$s1
+ mov 8($inp),$s2
+ mov 12($inp),$s3
+ mov $keyp,$key # restore key
+ mov $inp,$_inp # if ($verticalspin) save inp
+
+ call _x86_64_AES_decrypt
+
+ mov $ivec,%rbp # load ivp
+ mov $_inp,$inp # if ($verticalspin) restore inp
+ mov $_len,%r10 # load len
+ xor 0(%rbp),$s0 # xor iv
+ xor 4(%rbp),$s1
+ xor 8(%rbp),$s2
+ xor 12(%rbp),$s3
+ mov $inp,%rbp # current input, next iv
+
+ sub \$16,%r10
+ mov %r10,$_len # update len
+ mov %rbp,$ivec # update ivp
+
+ mov $s0,0($out) # write output
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+ lea 16($inp),$inp
+ lea 16($out),$out
+ jnz .Lcbc_fast_dec_loop
+ mov $_ivp,%r12 # load user ivp
+ mov 0(%rbp),%r10 # load iv
+ mov 8(%rbp),%r11
+ mov %r10,0(%r12) # copy back to user
+ mov %r11,8(%r12)
+ jmp .Lcbc_fast_cleanup
+
+.align 16
+.Lcbc_fast_dec_in_place:
+ mov 0(%rbp),%r10 # copy iv to stack
+ mov 8(%rbp),%r11
+ mov %r10,0+$ivec
+ mov %r11,8+$ivec
+.align 4
+.Lcbc_fast_dec_in_place_loop:
+ mov 0($inp),$s0 # load input
+ mov 4($inp),$s1
+ mov 8($inp),$s2
+ mov 12($inp),$s3
+ mov $keyp,$key # restore key
+ mov $inp,$_inp # if ($verticalspin) save inp
+
+ call _x86_64_AES_decrypt
+
+ mov $_inp,$inp # if ($verticalspin) restore inp
+ mov $_len,%r10
+ xor 0+$ivec,$s0
+ xor 4+$ivec,$s1
+ xor 8+$ivec,$s2
+ xor 12+$ivec,$s3
+
+ mov 0($inp),%r11 # load input
+ mov 8($inp),%r12
+ sub \$16,%r10
+ jz .Lcbc_fast_dec_in_place_done
+
+ mov %r11,0+$ivec # copy input to iv
+ mov %r12,8+$ivec
+
+ mov $s0,0($out) # save output [zaps input]
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+ lea 16($inp),$inp
+ lea 16($out),$out
+ mov %r10,$_len
+ jmp .Lcbc_fast_dec_in_place_loop
+.Lcbc_fast_dec_in_place_done:
+ mov $_ivp,%rdi
+ mov %r11,0(%rdi) # copy iv back to user
+ mov %r12,8(%rdi)
+
+ mov $s0,0($out) # save output [zaps input]
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+.align 4
+.Lcbc_fast_cleanup:
+ cmpl \$0,$mark # was the key schedule copied?
+ lea $aes_key,%rdi
+ je .Lcbc_exit
+ mov \$240/8,%ecx
+ xor %rax,%rax
+ .long 0x90AB48F3 # rep stosq
+
+ jmp .Lcbc_exit
+
+#--------------------------- SLOW ROUTINE ---------------------------#
+.align 16
+.Lcbc_slow_prologue:
+.cfi_restore_state
+ # allocate aligned stack frame...
+ lea -88(%rsp),%rbp
+ and \$-64,%rbp
+ # ... just "above" key schedule
+ lea -88-63(%rcx),%r10
+ sub %rbp,%r10
+ neg %r10
+ and \$0x3c0,%r10
+ sub %r10,%rbp
+
+ xchg %rsp,%rbp
+.cfi_def_cfa_register %rbp
+ #add \$8,%rsp # reserve for return address!
+ mov %rbp,$_rsp # save %rsp
+.cfi_cfa_expression $_rsp,deref,+64
+.Lcbc_slow_body:
+ #mov %rdi,$_inp # save copy of inp
+ #mov %rsi,$_out # save copy of out
+ #mov %rdx,$_len # save copy of len
+ #mov %rcx,$_key # save copy of key
+ mov %r8,$_ivp # save copy of ivp
+ mov %r8,%rbp # rearrange input arguments
+ mov %r9,%rbx
+ mov %rsi,$out
+ mov %rdi,$inp
+ mov %rcx,$key
+ mov %rdx,%r10
+
+ mov 240($key),%eax
+ mov $key,$keyp # save key pointer
+ shl \$4,%eax
+ lea ($key,%rax),%rax
+ mov %rax,$keyend
+
+ # pick Te4 copy which can't "overlap" with stack frame or key schedule
+ lea 2048($sbox),$sbox
+ lea 768-8(%rsp),%rax
+ sub $sbox,%rax
+ and \$0x300,%rax
+ lea ($sbox,%rax),$sbox
+
+ cmp \$0,%rbx
+ je .LSLOW_DECRYPT
+
+#--------------------------- SLOW ENCRYPT ---------------------------#
+ test \$-16,%r10 # check upon length
+ mov 0(%rbp),$s0 # load iv
+ mov 4(%rbp),$s1
+ mov 8(%rbp),$s2
+ mov 12(%rbp),$s3
+ jz .Lcbc_slow_enc_tail # short input...
+
+.align 4
+.Lcbc_slow_enc_loop:
+ xor 0($inp),$s0
+ xor 4($inp),$s1
+ xor 8($inp),$s2
+ xor 12($inp),$s3
+ mov $keyp,$key # restore key
+ mov $inp,$_inp # save inp
+ mov $out,$_out # save out
+ mov %r10,$_len # save len
+
+ call _x86_64_AES_encrypt_compact
+
+ mov $_inp,$inp # restore inp
+ mov $_out,$out # restore out
+ mov $_len,%r10 # restore len
+ mov $s0,0($out)
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+ lea 16($inp),$inp
+ lea 16($out),$out
+ sub \$16,%r10
+ test \$-16,%r10
+ jnz .Lcbc_slow_enc_loop
+ test \$15,%r10
+ jnz .Lcbc_slow_enc_tail
+ mov $_ivp,%rbp # restore ivp
+ mov $s0,0(%rbp) # save ivec
+ mov $s1,4(%rbp)
+ mov $s2,8(%rbp)
+ mov $s3,12(%rbp)
+
+ jmp .Lcbc_exit
+
+.align 4
+.Lcbc_slow_enc_tail:
+ mov %rax,%r11
+ mov %rcx,%r12
+ mov %r10,%rcx
+ mov $inp,%rsi
+ mov $out,%rdi
+ .long 0x9066A4F3 # rep movsb
+ mov \$16,%rcx # zero tail
+ sub %r10,%rcx
+ xor %rax,%rax
+ .long 0x9066AAF3 # rep stosb
+ mov $out,$inp # this is not a mistake!
+ mov \$16,%r10 # len=16
+ mov %r11,%rax
+ mov %r12,%rcx
+ jmp .Lcbc_slow_enc_loop # one more spin...
+#--------------------------- SLOW DECRYPT ---------------------------#
+.align 16
+.LSLOW_DECRYPT:
+ shr \$3,%rax
+ add %rax,$sbox # recall "magic" constants!
+
+ mov 0(%rbp),%r11 # copy iv to stack
+ mov 8(%rbp),%r12
+ mov %r11,0+$ivec
+ mov %r12,8+$ivec
+
+.align 4
+.Lcbc_slow_dec_loop:
+ mov 0($inp),$s0 # load input
+ mov 4($inp),$s1
+ mov 8($inp),$s2
+ mov 12($inp),$s3
+ mov $keyp,$key # restore key
+ mov $inp,$_inp # save inp
+ mov $out,$_out # save out
+ mov %r10,$_len # save len
+
+ call _x86_64_AES_decrypt_compact
+
+ mov $_inp,$inp # restore inp
+ mov $_out,$out # restore out
+ mov $_len,%r10
+ xor 0+$ivec,$s0
+ xor 4+$ivec,$s1
+ xor 8+$ivec,$s2
+ xor 12+$ivec,$s3
+
+ mov 0($inp),%r11 # load input
+ mov 8($inp),%r12
+ sub \$16,%r10
+ jc .Lcbc_slow_dec_partial
+ jz .Lcbc_slow_dec_done
+
+ mov %r11,0+$ivec # copy input to iv
+ mov %r12,8+$ivec
+
+ mov $s0,0($out) # save output [can zap input]
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+ lea 16($inp),$inp
+ lea 16($out),$out
+ jmp .Lcbc_slow_dec_loop
+.Lcbc_slow_dec_done:
+ mov $_ivp,%rdi
+ mov %r11,0(%rdi) # copy iv back to user
+ mov %r12,8(%rdi)
+
+ mov $s0,0($out) # save output [can zap input]
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+ jmp .Lcbc_exit
+
+.align 4
+.Lcbc_slow_dec_partial:
+ mov $_ivp,%rdi
+ mov %r11,0(%rdi) # copy iv back to user
+ mov %r12,8(%rdi)
+
+ mov $s0,0+$ivec # save output to stack
+ mov $s1,4+$ivec
+ mov $s2,8+$ivec
+ mov $s3,12+$ivec
+
+ mov $out,%rdi
+ lea $ivec,%rsi
+ lea 16(%r10),%rcx
+ .long 0x9066A4F3 # rep movsb
+ jmp .Lcbc_exit
+
+.align 16
+.Lcbc_exit:
+ mov $_rsp,%rsi
+.cfi_def_cfa %rsi,64
+ mov (%rsi),%r15
+.cfi_restore %r15
+ mov 8(%rsi),%r14
+.cfi_restore %r14
+ mov 16(%rsi),%r13
+.cfi_restore %r13
+ mov 24(%rsi),%r12
+.cfi_restore %r12
+ mov 32(%rsi),%rbp
+.cfi_restore %rbp
+ mov 40(%rsi),%rbx
+.cfi_restore %rbx
+ lea 48(%rsi),%rsp
+.cfi_def_cfa %rsp,16
+.Lcbc_popfq:
+ popfq
+# This could be .cfi_pop 49, but libunwind fails on registers it does not
+# recognize. See https://bugzilla.redhat.com/show_bug.cgi?id=217087.
+.cfi_adjust_cfa_offset -8
+.Lcbc_epilogue:
+ ret
+.cfi_endproc
+.size AES_cbc_encrypt,.-AES_cbc_encrypt
+___
+}
+
+$code.=<<___;
+.align 64
+.LAES_Te:
+___
+ &_data_word(0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6);
+ &_data_word(0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591);
+ &_data_word(0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56);
+ &_data_word(0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec);
+ &_data_word(0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa);
+ &_data_word(0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb);
+ &_data_word(0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45);
+ &_data_word(0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b);
+ &_data_word(0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c);
+ &_data_word(0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83);
+ &_data_word(0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9);
+ &_data_word(0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a);
+ &_data_word(0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d);
+ &_data_word(0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f);
+ &_data_word(0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df);
+ &_data_word(0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea);
+ &_data_word(0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34);
+ &_data_word(0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b);
+ &_data_word(0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d);
+ &_data_word(0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413);
+ &_data_word(0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1);
+ &_data_word(0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6);
+ &_data_word(0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972);
+ &_data_word(0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85);
+ &_data_word(0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed);
+ &_data_word(0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511);
+ &_data_word(0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe);
+ &_data_word(0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b);
+ &_data_word(0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05);
+ &_data_word(0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1);
+ &_data_word(0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142);
+ &_data_word(0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf);
+ &_data_word(0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3);
+ &_data_word(0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e);
+ &_data_word(0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a);
+ &_data_word(0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6);
+ &_data_word(0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3);
+ &_data_word(0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b);
+ &_data_word(0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428);
+ &_data_word(0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad);
+ &_data_word(0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14);
+ &_data_word(0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8);
+ &_data_word(0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4);
+ &_data_word(0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2);
+ &_data_word(0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda);
+ &_data_word(0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949);
+ &_data_word(0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf);
+ &_data_word(0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810);
+ &_data_word(0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c);
+ &_data_word(0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697);
+ &_data_word(0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e);
+ &_data_word(0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f);
+ &_data_word(0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc);
+ &_data_word(0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c);
+ &_data_word(0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969);
+ &_data_word(0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27);
+ &_data_word(0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122);
+ &_data_word(0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433);
+ &_data_word(0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9);
+ &_data_word(0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5);
+ &_data_word(0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a);
+ &_data_word(0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0);
+ &_data_word(0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e);
+ &_data_word(0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c);
+
+#Te4 # four copies of Te4 to choose from to avoid L1 aliasing
+ &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+ &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+ &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+ &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+ &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+ &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+ &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+ &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+ &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+ &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+ &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+ &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+ &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+ &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+ &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+ &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+ &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+ &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+ &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+ &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+ &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+ &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+ &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+ &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+ &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+ &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+ &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+ &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+ &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+ &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+ &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+ &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+
+ &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+ &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+ &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+ &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+ &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+ &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+ &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+ &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+ &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+ &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+ &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+ &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+ &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+ &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+ &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+ &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+ &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+ &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+ &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+ &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+ &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+ &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+ &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+ &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+ &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+ &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+ &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+ &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+ &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+ &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+ &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+ &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+
+ &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+ &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+ &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+ &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+ &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+ &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+ &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+ &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+ &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+ &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+ &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+ &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+ &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+ &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+ &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+ &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+ &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+ &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+ &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+ &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+ &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+ &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+ &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+ &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+ &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+ &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+ &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+ &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+ &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+ &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+ &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+ &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+
+ &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+ &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+ &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+ &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+ &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+ &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+ &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+ &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+ &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+ &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+ &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+ &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+ &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+ &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+ &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+ &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+ &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+ &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+ &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+ &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+ &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+ &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+ &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+ &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+ &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+ &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+ &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+ &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+ &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+ &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+ &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+ &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+#rcon:
+$code.=<<___;
+ .long 0x00000001, 0x00000002, 0x00000004, 0x00000008
+ .long 0x00000010, 0x00000020, 0x00000040, 0x00000080
+ .long 0x0000001b, 0x00000036, 0x80808080, 0x80808080
+ .long 0xfefefefe, 0xfefefefe, 0x1b1b1b1b, 0x1b1b1b1b
+___
+$code.=<<___;
+.align 64
+.LAES_Td:
+___
+ &_data_word(0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a);
+ &_data_word(0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b);
+ &_data_word(0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5);
+ &_data_word(0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5);
+ &_data_word(0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d);
+ &_data_word(0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b);
+ &_data_word(0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295);
+ &_data_word(0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e);
+ &_data_word(0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927);
+ &_data_word(0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d);
+ &_data_word(0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362);
+ &_data_word(0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9);
+ &_data_word(0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52);
+ &_data_word(0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566);
+ &_data_word(0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3);
+ &_data_word(0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed);
+ &_data_word(0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e);
+ &_data_word(0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4);
+ &_data_word(0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4);
+ &_data_word(0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd);
+ &_data_word(0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d);
+ &_data_word(0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060);
+ &_data_word(0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967);
+ &_data_word(0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879);
+ &_data_word(0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000);
+ &_data_word(0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c);
+ &_data_word(0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36);
+ &_data_word(0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624);
+ &_data_word(0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b);
+ &_data_word(0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c);
+ &_data_word(0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12);
+ &_data_word(0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14);
+ &_data_word(0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3);
+ &_data_word(0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b);
+ &_data_word(0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8);
+ &_data_word(0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684);
+ &_data_word(0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7);
+ &_data_word(0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177);
+ &_data_word(0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947);
+ &_data_word(0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322);
+ &_data_word(0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498);
+ &_data_word(0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f);
+ &_data_word(0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54);
+ &_data_word(0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382);
+ &_data_word(0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf);
+ &_data_word(0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb);
+ &_data_word(0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83);
+ &_data_word(0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef);
+ &_data_word(0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029);
+ &_data_word(0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235);
+ &_data_word(0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733);
+ &_data_word(0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117);
+ &_data_word(0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4);
+ &_data_word(0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546);
+ &_data_word(0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb);
+ &_data_word(0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d);
+ &_data_word(0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb);
+ &_data_word(0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a);
+ &_data_word(0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773);
+ &_data_word(0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478);
+ &_data_word(0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2);
+ &_data_word(0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff);
+ &_data_word(0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664);
+ &_data_word(0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0);
+
+#Td4: # four copies of Td4 to choose from to avoid L1 aliasing
+ &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+ &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+ &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+ &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+ &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+ &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+ &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+ &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+ &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+ &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+ &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+ &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+ &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+ &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+ &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+ &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+ &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+ &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+ &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+ &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+ &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+ &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+ &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+ &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+ &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+ &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+ &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+ &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+ &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+ &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+ &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+ &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+$code.=<<___;
+ .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+ .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+___
+ &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+ &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+ &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+ &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+ &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+ &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+ &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+ &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+ &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+ &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+ &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+ &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+ &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+ &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+ &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+ &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+ &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+ &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+ &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+ &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+ &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+ &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+ &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+ &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+ &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+ &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+ &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+ &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+ &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+ &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+ &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+ &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+$code.=<<___;
+ .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+ .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+___
+ &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+ &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+ &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+ &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+ &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+ &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+ &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+ &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+ &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+ &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+ &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+ &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+ &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+ &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+ &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+ &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+ &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+ &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+ &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+ &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+ &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+ &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+ &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+ &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+ &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+ &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+ &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+ &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+ &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+ &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+ &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+ &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+$code.=<<___;
+ .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+ .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+___
+ &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+ &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+ &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+ &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+ &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+ &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+ &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+ &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+ &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+ &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+ &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+ &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+ &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+ &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+ &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+ &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+ &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+ &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+ &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+ &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+ &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+ &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+ &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+ &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+ &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+ &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+ &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+ &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+ &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+ &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+ &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+ &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+$code.=<<___;
+ .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+ .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+.asciz "AES for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
+.align 64
+___
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+.type block_se_handler,\@abi-omnipotent
+.align 16
+block_se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<prologue label
+ jb .Lin_block_prologue
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lin_block_prologue
+
+ mov 24(%rax),%rax # pull saved real stack pointer
+
+ mov -8(%rax),%rbx
+ mov -16(%rax),%rbp
+ mov -24(%rax),%r12
+ mov -32(%rax),%r13
+ mov -40(%rax),%r14
+ mov -48(%rax),%r15
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R15
+
+.Lin_block_prologue:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ jmp .Lcommon_seh_exit
+.size block_se_handler,.-block_se_handler
+
+.type key_se_handler,\@abi-omnipotent
+.align 16
+key_se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<prologue label
+ jb .Lin_key_prologue
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lin_key_prologue
+
+ lea 56(%rax),%rax
+
+ mov -8(%rax),%rbx
+ mov -16(%rax),%rbp
+ mov -24(%rax),%r12
+ mov -32(%rax),%r13
+ mov -40(%rax),%r14
+ mov -48(%rax),%r15
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R15
+
+.Lin_key_prologue:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ jmp .Lcommon_seh_exit
+.size key_se_handler,.-key_se_handler
+
+.type cbc_se_handler,\@abi-omnipotent
+.align 16
+cbc_se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ lea .Lcbc_prologue(%rip),%r10
+ cmp %r10,%rbx # context->Rip<.Lcbc_prologue
+ jb .Lin_cbc_prologue
+
+ lea .Lcbc_fast_body(%rip),%r10
+ cmp %r10,%rbx # context->Rip<.Lcbc_fast_body
+ jb .Lin_cbc_frame_setup
+
+ lea .Lcbc_slow_prologue(%rip),%r10
+ cmp %r10,%rbx # context->Rip<.Lcbc_slow_prologue
+ jb .Lin_cbc_body
+
+ lea .Lcbc_slow_body(%rip),%r10
+ cmp %r10,%rbx # context->Rip<.Lcbc_slow_body
+ jb .Lin_cbc_frame_setup
+
+.Lin_cbc_body:
+ mov 152($context),%rax # pull context->Rsp
+
+ lea .Lcbc_epilogue(%rip),%r10
+ cmp %r10,%rbx # context->Rip>=.Lcbc_epilogue
+ jae .Lin_cbc_prologue
+
+ lea 8(%rax),%rax
+
+ lea .Lcbc_popfq(%rip),%r10
+ cmp %r10,%rbx # context->Rip>=.Lcbc_popfq
+ jae .Lin_cbc_prologue
+
+ mov `16-8`(%rax),%rax # biased $_rsp
+ lea 56(%rax),%rax
+
+.Lin_cbc_frame_setup:
+ mov -16(%rax),%rbx
+ mov -24(%rax),%rbp
+ mov -32(%rax),%r12
+ mov -40(%rax),%r13
+ mov -48(%rax),%r14
+ mov -56(%rax),%r15
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R15
+
+.Lin_cbc_prologue:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+.Lcommon_seh_exit:
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$`1232/8`,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size cbc_se_handler,.-cbc_se_handler
+
+.section .pdata
+.align 4
+ .rva .LSEH_begin_AES_encrypt
+ .rva .LSEH_end_AES_encrypt
+ .rva .LSEH_info_AES_encrypt
+
+ .rva .LSEH_begin_AES_decrypt
+ .rva .LSEH_end_AES_decrypt
+ .rva .LSEH_info_AES_decrypt
+
+ .rva .LSEH_begin_AES_set_encrypt_key
+ .rva .LSEH_end_AES_set_encrypt_key
+ .rva .LSEH_info_AES_set_encrypt_key
+
+ .rva .LSEH_begin_AES_set_decrypt_key
+ .rva .LSEH_end_AES_set_decrypt_key
+ .rva .LSEH_info_AES_set_decrypt_key
+
+ .rva .LSEH_begin_AES_cbc_encrypt
+ .rva .LSEH_end_AES_cbc_encrypt
+ .rva .LSEH_info_AES_cbc_encrypt
+
+.section .xdata
+.align 8
+.LSEH_info_AES_encrypt:
+ .byte 9,0,0,0
+ .rva block_se_handler
+ .rva .Lenc_prologue,.Lenc_epilogue # HandlerData[]
+.LSEH_info_AES_decrypt:
+ .byte 9,0,0,0
+ .rva block_se_handler
+ .rva .Ldec_prologue,.Ldec_epilogue # HandlerData[]
+.LSEH_info_AES_set_encrypt_key:
+ .byte 9,0,0,0
+ .rva key_se_handler
+ .rva .Lenc_key_prologue,.Lenc_key_epilogue # HandlerData[]
+.LSEH_info_AES_set_decrypt_key:
+ .byte 9,0,0,0
+ .rva key_se_handler
+ .rva .Ldec_key_prologue,.Ldec_key_epilogue # HandlerData[]
+.LSEH_info_AES_cbc_encrypt:
+ .byte 9,0,0,0
+ .rva cbc_se_handler
+___
+}
+
+$code =~ s/\`([^\`]*)\`/eval($1)/gem;
+
+print $code;
+
+close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/aes/asm/aesfx-sparcv9.pl b/crypto/aes/asm/aesfx-sparcv9.pl
index 1678c4f786f2..27233d03af7b 100644
--- a/crypto/aes/asm/aesfx-sparcv9.pl
+++ b/crypto/aes/asm/aesfx-sparcv9.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -33,14 +33,16 @@
# instructions and improve single-block and short-input performance
# with misaligned data.
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
{
my ($inp,$out,$key,$rounds,$tmp,$mask) = map("%o$_",(0..5));
$code.=<<___;
-#include "sparc_arch.h"
+#ifndef __ASSEMBLER__
+# define __ASSEMBLER__ 1
+#endif
+#include "crypto/sparc_arch.h"
#define LOCALS (STACK_BIAS+STACK_FRAME)
diff --git a/crypto/aes/asm/aesni-mb-x86_64.pl b/crypto/aes/asm/aesni-mb-x86_64.pl
index a80cfdc13948..dde15b1ef7ee 100644
--- a/crypto/aes/asm/aesni-mb-x86_64.pl
+++ b/crypto/aes/asm/aesni-mb-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -42,9 +42,10 @@
# (*) Sandy/Ivy Bridge are known to handle high interleave factors
# suboptimally;
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -53,6 +54,11 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86_64-support.pl";
+
+$ptr_size=&pointer_size($flavour);
+
$avx=0;
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
@@ -74,7 +80,8 @@ if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|.*based on LLVM) ([0
$avx = ($2>=3.0) + ($2>3.0);
}
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
# void aesni_multi_cbc_encrypt (
@@ -86,6 +93,8 @@ $inp="%rdi"; # 1st arg
$key="%rsi"; # 2nd arg
$num="%edx";
+$inp_elm_size=2*$ptr_size+8+16;
+
@inptr=map("%r$_",(8..11));
@outptr=map("%r$_",(12..15));
@@ -161,21 +170,25 @@ $code.=<<___;
.Lenc4x_body:
movdqu ($key),$zero # 0-round key
lea 0x78($key),$key # size optimization
- lea 40*2($inp),$inp
+ lea $inp_elm_size*2($inp),$inp
.Lenc4x_loop_grande:
mov $num,24(%rsp) # original $num
xor $num,$num
___
for($i=0;$i<4;$i++) {
+ $inptr_reg=&pointer_register($flavour,@inptr[$i]);
+ $outptr_reg=&pointer_register($flavour,@outptr[$i]);
$code.=<<___;
- mov `40*$i+16-40*2`($inp),$one # borrow $one for number of blocks
- mov `40*$i+0-40*2`($inp),@inptr[$i]
+ # borrow $one for number of blocks
+ mov `$inp_elm_size*$i+2*$ptr_size-$inp_elm_size*2`($inp),$one
+ mov `$inp_elm_size*$i+0-$inp_elm_size*2`($inp),$inptr_reg
cmp $num,$one
- mov `40*$i+8-40*2`($inp),@outptr[$i]
+ mov `$inp_elm_size*$i+$ptr_size-$inp_elm_size*2`($inp),$outptr_reg
cmovg $one,$num # find maximum
test $one,$one
- movdqu `40*$i+24-40*2`($inp),@out[$i] # load IV
+ # load IV
+ movdqu `$inp_elm_size*$i+2*$ptr_size+8-$inp_elm_size*2`($inp),@out[$i]
mov $one,`32+4*$i`(%rsp) # initialize counters
cmovle %rsp,@inptr[$i] # cancel input
___
@@ -333,14 +346,15 @@ $code.=<<___;
#pxor @inp[0],@out[0]
#pxor @inp[1],@out[1]
- #movdqu @out[0],`40*0+24-40*2`($inp) # output iv FIX ME!
+ # output iv FIX ME!
+ #movdqu @out[0],`$inp_elm_size*0+2*$ptr_size+8-$inp_elm_size*2`($inp)
#pxor @inp[2],@out[2]
- #movdqu @out[1],`40*1+24-40*2`($inp)
+ #movdqu @out[1],`$inp_elm_size*1+2*$ptr_size+8-$inp_elm_size*2`($inp)
#pxor @inp[3],@out[3]
- #movdqu @out[2],`40*2+24-40*2`($inp) # won't fix, let caller
- #movdqu @out[3],`40*3+24-40*2`($inp) # figure this out...
+ #movdqu @out[2],`$inp_elm_size*2+2*$ptr_size+8-$inp_elm_size*2`($inp) # won't fix, let caller
+ #movdqu @out[3],`$inp_elm_size*3+2*$ptr_size+8-$inp_elm_size*2`($inp) # figure this out...
- lea `40*4`($inp),$inp
+ lea `$inp_elm_size*4`($inp),$inp
dec $num
jnz .Lenc4x_loop_grande
@@ -438,21 +452,25 @@ $code.=<<___;
.Ldec4x_body:
movdqu ($key),$zero # 0-round key
lea 0x78($key),$key # size optimization
- lea 40*2($inp),$inp
+ lea $inp_elm_size*2($inp),$inp
.Ldec4x_loop_grande:
mov $num,24(%rsp) # original $num
xor $num,$num
___
for($i=0;$i<4;$i++) {
+ $inptr_reg=&pointer_register($flavour,@inptr[$i]);
+ $outptr_reg=&pointer_register($flavour,@outptr[$i]);
$code.=<<___;
- mov `40*$i+16-40*2`($inp),$one # borrow $one for number of blocks
- mov `40*$i+0-40*2`($inp),@inptr[$i]
+ # borrow $one for number of blocks
+ mov `$inp_elm_size*$i+2*$ptr_size-$inp_elm_size*2`($inp),$one
+ mov `$inp_elm_size*$i+0-$inp_elm_size*2`($inp),$inptr_reg
cmp $num,$one
- mov `40*$i+8-40*2`($inp),@outptr[$i]
+ mov `$inp_elm_size*$i+$ptr_size-$inp_elm_size*2`($inp),$outptr_reg
cmovg $one,$num # find maximum
test $one,$one
- movdqu `40*$i+24-40*2`($inp),@inp[$i] # load IV
+ # load IV
+ movdqu `$inp_elm_size*$i+2*$ptr_size+8-$inp_elm_size*2`($inp),@inp[$i]
mov $one,`32+4*$i`(%rsp) # initialize counters
cmovle %rsp,@inptr[$i] # cancel input
___
@@ -608,7 +626,7 @@ $code.=<<___;
.cfi_def_cfa %rax,8
mov 24(%rsp),$num
- lea `40*4`($inp),$inp
+ lea `$inp_elm_size*4`($inp),$inp
dec $num
jnz .Ldec4x_loop_grande
@@ -707,7 +725,7 @@ $code.=<<___;
vzeroupper
vmovdqu ($key),$zero # 0-round key
lea 0x78($key),$key # size optimization
- lea 40*4($inp),$inp
+ lea `$inp_elm_size*4`($inp),$inp
shr \$1,$num
.Lenc8x_loop_grande:
@@ -716,14 +734,20 @@ $code.=<<___;
___
for($i=0;$i<8;$i++) {
my $temp = $i ? $offload : $offset;
+ $ptr_reg=&pointer_register($flavour,@ptr[$i]);
+ $temp_reg=&pointer_register($flavour,$temp);
$code.=<<___;
- mov `40*$i+16-40*4`($inp),$one # borrow $one for number of blocks
- mov `40*$i+0-40*4`($inp),@ptr[$i] # input pointer
+ # borrow $one for number of blocks
+ mov `$inp_elm_size*$i+2*$ptr_size-$inp_elm_size*4`($inp),$one
+ # input pointer
+ mov `$inp_elm_size*$i+0-$inp_elm_size*4`($inp),$ptr_reg
cmp $num,$one
- mov `40*$i+8-40*4`($inp),$temp # output pointer
+ # output pointer
+ mov `$inp_elm_size*$i+$ptr_size-$inp_elm_size*4`($inp),$temp_reg
cmovg $one,$num # find maximum
test $one,$one
- vmovdqu `40*$i+24-40*4`($inp),@out[$i] # load IV
+ # load IV
+ vmovdqu `$inp_elm_size*$i+2*$ptr_size+8-$inp_elm_size*4`($inp),@out[$i]
mov $one,`32+4*$i`(%rsp) # initialize counters
cmovle %rsp,@ptr[$i] # cancel input
sub @ptr[$i],$temp # distance between input and output
@@ -908,7 +932,7 @@ $code.=<<___;
mov 16(%rsp),%rax # original %rsp
.cfi_def_cfa %rax,8
#mov 24(%rsp),$num
- #lea `40*8`($inp),$inp
+ #lea `$inp_elm_size*8`($inp),$inp
#dec $num
#jnz .Lenc8x_loop_grande
@@ -1000,7 +1024,7 @@ $code.=<<___;
vzeroupper
vmovdqu ($key),$zero # 0-round key
lea 0x78($key),$key # size optimization
- lea 40*4($inp),$inp
+ lea `$inp_elm_size*4`($inp),$inp
shr \$1,$num
.Ldec8x_loop_grande:
@@ -1009,14 +1033,20 @@ $code.=<<___;
___
for($i=0;$i<8;$i++) {
my $temp = $i ? $offload : $offset;
+ $ptr_reg=&pointer_register($flavour,@ptr[$i]);
+ $temp_reg=&pointer_register($flavour,$temp);
$code.=<<___;
- mov `40*$i+16-40*4`($inp),$one # borrow $one for number of blocks
- mov `40*$i+0-40*4`($inp),@ptr[$i] # input pointer
+ # borrow $one for number of blocks
+ mov `$inp_elm_size*$i+2*$ptr_size-$inp_elm_size*4`($inp),$one
+ # input pointer
+ mov `$inp_elm_size*$i+0-$inp_elm_size*4`($inp),$ptr_reg
cmp $num,$one
- mov `40*$i+8-40*4`($inp),$temp # output pointer
+ # output pointer
+ mov `$inp_elm_size*$i+$ptr_size-$inp_elm_size*4`($inp),$temp_reg
cmovg $one,$num # find maximum
test $one,$one
- vmovdqu `40*$i+24-40*4`($inp),@out[$i] # load IV
+ # load IV
+ vmovdqu `$inp_elm_size*$i+2*$ptr_size+8-$inp_elm_size*4`($inp),@out[$i]
mov $one,`32+4*$i`(%rsp) # initialize counters
cmovle %rsp,@ptr[$i] # cancel input
sub @ptr[$i],$temp # distance between input and output
@@ -1232,7 +1262,7 @@ $code.=<<___;
mov 16(%rsp),%rax # original %rsp
.cfi_def_cfa %rax,8
#mov 24(%rsp),$num
- #lea `40*8`($inp),$inp
+ #lea `$inp_elm_size*8`($inp),$inp
#dec $num
#jnz .Ldec8x_loop_grande
diff --git a/crypto/aes/asm/aesni-sha1-x86_64.pl b/crypto/aes/asm/aesni-sha1-x86_64.pl
index 04fd13be5e09..dbe33a3f1a02 100644
--- a/crypto/aes/asm/aesni-sha1-x86_64.pl
+++ b/crypto/aes/asm/aesni-sha1-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -88,9 +88,10 @@
# (**) Execution is fully dominated by integer code sequence and
# SIMD still hardly shows [in single-process benchmark;-]
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -114,7 +115,8 @@ $shaext=1; ### set to zero if compiling for 1.0.1
$stitched_decrypt=0;
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
# void aesni_cbc_sha1_enc(const void *inp,
diff --git a/crypto/aes/asm/aesni-sha256-x86_64.pl b/crypto/aes/asm/aesni-sha256-x86_64.pl
index ff9b18507da0..5521766a6a7d 100644
--- a/crypto/aes/asm/aesni-sha256-x86_64.pl
+++ b/crypto/aes/asm/aesni-sha256-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -44,9 +44,10 @@
# -evp aes-256-cbc-hmac-sha256' will vary by percent or two;
# (***) these are SHAEXT results;
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -77,7 +78,8 @@ if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|.*based on LLVM) ([0
$shaext=$avx; ### set to zero if compiling for 1.0.1
$avx=1 if (!$shaext && $avx);
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
$func="aesni_cbc_sha256_enc";
diff --git a/crypto/aes/asm/aesni-x86.pl b/crypto/aes/asm/aesni-x86.pl
index 3502940d5233..d8cc378b5f9b 100644
--- a/crypto/aes/asm/aesni-x86.pl
+++ b/crypto/aes/asm/aesni-x86.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2009-2022 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -76,9 +76,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output = pop;
-open OUT,">$output";
-*STDOUT=*OUT;
+$output = pop and open STDOUT,">$output";
&asm_init($ARGV[0]);
diff --git a/crypto/aes/asm/aesni-x86_64.pl b/crypto/aes/asm/aesni-x86_64.pl
index f8c2e2393438..09c8f78890ed 100644
--- a/crypto/aes/asm/aesni-x86_64.pl
+++ b/crypto/aes/asm/aesni-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -192,9 +192,10 @@ $PREFIX="aesni"; # if $PREFIX is set to "AES", the script
# generates drop-in replacement for
# crypto/aes/asm/aes-x86_64.pl:-)
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -203,7 +204,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
$movkey = $PREFIX eq "aesni" ? "movups" : "movups";
@@ -275,6 +277,7 @@ $code.=<<___;
.align 16
${PREFIX}_encrypt:
.cfi_startproc
+ endbranch
movups ($inp),$inout0 # load input
mov 240($key),$rounds # key->rounds
___
@@ -293,6 +296,7 @@ $code.=<<___;
.align 16
${PREFIX}_decrypt:
.cfi_startproc
+ endbranch
movups ($inp),$inout0 # load input
mov 240($key),$rounds # key->rounds
___
@@ -613,6 +617,7 @@ $code.=<<___;
.align 16
aesni_ecb_encrypt:
.cfi_startproc
+ endbranch
___
$code.=<<___ if ($win64);
lea -0x58(%rsp),%rsp
@@ -985,6 +990,7 @@ $code.=<<___;
.align 16
aesni_ccm64_encrypt_blocks:
.cfi_startproc
+ endbranch
___
$code.=<<___ if ($win64);
lea -0x58(%rsp),%rsp
@@ -1077,6 +1083,7 @@ $code.=<<___;
.align 16
aesni_ccm64_decrypt_blocks:
.cfi_startproc
+ endbranch
___
$code.=<<___ if ($win64);
lea -0x58(%rsp),%rsp
@@ -1203,6 +1210,7 @@ $code.=<<___;
.align 16
aesni_ctr32_encrypt_blocks:
.cfi_startproc
+ endbranch
cmp \$1,$len
jne .Lctr32_bulk
@@ -1775,6 +1783,7 @@ $code.=<<___;
.align 16
aesni_xts_encrypt:
.cfi_startproc
+ endbranch
lea (%rsp),%r11 # frame pointer
.cfi_def_cfa_register %r11
push %rbp
@@ -2258,6 +2267,7 @@ $code.=<<___;
.align 16
aesni_xts_decrypt:
.cfi_startproc
+ endbranch
lea (%rsp),%r11 # frame pointer
.cfi_def_cfa_register %r11
push %rbp
@@ -2783,6 +2793,7 @@ $code.=<<___;
.align 32
aesni_ocb_encrypt:
.cfi_startproc
+ endbranch
lea (%rsp),%rax
push %rbx
.cfi_push %rbx
@@ -3249,6 +3260,7 @@ __ocb_encrypt1:
.align 32
aesni_ocb_decrypt:
.cfi_startproc
+ endbranch
lea (%rsp),%rax
push %rbx
.cfi_push %rbx
@@ -3737,6 +3749,7 @@ $code.=<<___;
.align 16
${PREFIX}_cbc_encrypt:
.cfi_startproc
+ endbranch
test $len,$len # check length
jz .Lcbc_ret
diff --git a/crypto/aes/asm/aesp8-ppc.pl b/crypto/aes/asm/aesp8-ppc.pl
index 22a538f9e24f..60cf86f52aed 100755
--- a/crypto/aes/asm/aesp8-ppc.pl
+++ b/crypto/aes/asm/aesp8-ppc.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -43,7 +43,10 @@
# POWER9[le] 4.02/0.86 0.84 1.05
# POWER9[be] 3.99/0.78 0.79 0.97
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /64/) {
$SIZE_T =8;
@@ -70,7 +73,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
+open STDOUT,"| $^X $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
$FRAME=8*$SIZE_T;
$prefix="aes_p8";
diff --git a/crypto/aes/asm/aest4-sparcv9.pl b/crypto/aes/asm/aest4-sparcv9.pl
index 478c97eb6feb..c04b5f3cdaf8 100644
--- a/crypto/aes/asm/aest4-sparcv9.pl
+++ b/crypto/aes/asm/aest4-sparcv9.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -75,8 +75,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "sparcv9_modes.pl";
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
$::evp=1; # if $evp is set to 0, script generates module with
# AES_[en|de]crypt, AES_set_[en|de]crypt_key and AES_cbc_encrypt entry
@@ -92,7 +91,10 @@ $::evp=1; # if $evp is set to 0, script generates module with
my ($inp,$out,$key,$rounds,$tmp,$mask)=map("%o$_",(0..5));
$code.=<<___;
-#include "sparc_arch.h"
+#ifndef __ASSEMBLER__
+# define __ASSEMBLER__ 1
+#endif
+#include "crypto/sparc_arch.h"
#ifdef __arch64__
.register %g2,#scratch
diff --git a/crypto/aes/asm/aesv8-armx.pl b/crypto/aes/asm/aesv8-armx.pl
index 7edc436a53ca..6a7bf05d1b35 100755
--- a/crypto/aes/asm/aesv8-armx.pl
+++ b/crypto/aes/asm/aesv8-armx.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2014-2022 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -27,44 +27,72 @@
# CBC encrypt case. On Cortex-A57 parallelizable mode performance
# seems to be limited by sheer amount of NEON instructions...
#
+# April 2019
+#
+# Key to performance of parallelize-able modes is round instruction
+# interleaving. But which factor to use? There is optimal one for
+# each combination of instruction latency and issue rate, beyond
+# which increasing interleave factor doesn't pay off. While on cons
+# side we have code size increase and resource waste on platforms for
+# which interleave factor is too high. In other words you want it to
+# be just right. So far interleave factor of 3x was serving well all
+# platforms. But for ThunderX2 optimal interleave factor was measured
+# to be 5x...
+#
# Performance in cycles per byte processed with 128-bit key:
#
# CBC enc CBC dec CTR
# Apple A7 2.39 1.20 1.20
-# Cortex-A53 1.32 1.29 1.46
-# Cortex-A57(*) 1.95 0.85 0.93
-# Denver 1.96 0.86 0.80
-# Mongoose 1.33 1.20 1.20
-# Kryo 1.26 0.94 1.00
+# Cortex-A53 1.32 1.17/1.29(**) 1.36/1.46
+# Cortex-A57(*) 1.95 0.82/0.85 0.89/0.93
+# Cortex-A72 1.33 0.85/0.88 0.92/0.96
+# Denver 1.96 0.65/0.86 0.76/0.80
+# Mongoose 1.33 1.23/1.20 1.30/1.20
+# Kryo 1.26 0.87/0.94 1.00/1.00
+# ThunderX2 5.95 1.25 1.30
#
# (*) original 3.64/1.34/1.32 results were for r0p0 revision
# and are still same even for updated module;
+# (**) numbers after slash are for 32-bit code, which is 3x-
+# interleaved;
-$flavour = shift;
-$output = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
$prefix="aes_v8";
+$_byte = ($flavour =~ /win/ ? "DCB" : ".byte");
+
$code=<<___;
#include "arm_arch.h"
#if __ARM_MAX_ARCH__>=7
-.text
___
-$code.=".arch armv8-a+crypto\n" if ($flavour =~ /64/);
+$code.=".arch armv8-a+crypto\n.text\n" if ($flavour =~ /64/);
$code.=<<___ if ($flavour !~ /64/);
.arch armv7-a // don't confuse not-so-latest binutils with argv8 :-)
.fpu neon
+#ifdef __thumb2__
+.syntax unified
+.thumb
+# define INST(a,b,c,d) $_byte c,d|0xc,a,b
+#else
.code 32
-#undef __thumb2__
+# define INST(a,b,c,d) $_byte a,b,c,d
+#endif
+
+.text
___
# Assembler mnemonics are an eclectic mix of 32- and 64-bit syntax,
@@ -361,6 +389,836 @@ ___
&gen_block("en");
&gen_block("de");
}}}
+
+# Performance in cycles per byte.
+# Processed with AES-ECB different key size.
+# It shows the value before and after optimization as below:
+# (before/after):
+#
+# AES-128-ECB AES-192-ECB AES-256-ECB
+# Cortex-A57 1.85/0.82 2.16/0.96 2.47/1.10
+# Cortex-A72 1.64/0.85 1.82/0.99 2.13/1.14
+
+# Optimization is implemented by loop unrolling and interleaving.
+# Commonly, we choose the unrolling factor as 5, if the input
+# data size smaller than 5 blocks, but not smaller than 3 blocks,
+# choose 3 as the unrolling factor.
+# If the input data size dsize >= 5*16 bytes, then take 5 blocks
+# as one iteration, every loop the left size lsize -= 5*16.
+# If 5*16 > lsize >= 3*16 bytes, take 3 blocks as one iteration,
+# every loop lsize -=3*16.
+# If lsize < 3*16 bytes, treat them as the tail, interleave the
+# two blocks AES instructions.
+# There is one special case, if the original input data size dsize
+# = 16 bytes, we will treat it seperately to improve the
+# performance: one independent code block without LR, FP load and
+# store, just looks like what the original ECB implementation does.
+
+{{{
+my ($inp,$out,$len,$key)=map("x$_",(0..3));
+my ($enc,$rounds,$cnt,$key_,$step)=("w4","w5","w6","x7","x8");
+my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$tmp2,$rndlast)=map("q$_",(0..7));
+
+my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1);
+
+### q7 last round key
+### q10-q15 q7 Last 7 round keys
+### q8-q9 preloaded round keys except last 7 keys for big size
+### q5, q6, q8-q9 preloaded round keys except last 7 keys for only 16 byte
+
+{
+my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9));
+
+my ($dat3,$in3,$tmp3); # used only in 64-bit mode
+my ($dat4,$in4,$tmp4);
+if ($flavour =~ /64/) {
+ ($dat2,$dat3,$dat4,$in2,$in3,$in4,$tmp3,$tmp4)=map("q$_",(16..23));
+}
+
+$code.=<<___;
+.globl ${prefix}_ecb_encrypt
+.type ${prefix}_ecb_encrypt,%function
+.align 5
+${prefix}_ecb_encrypt:
+___
+$code.=<<___ if ($flavour =~ /64/);
+ subs $len,$len,#16
+ // Original input data size bigger than 16, jump to big size processing.
+ b.ne .Lecb_big_size
+ vld1.8 {$dat0},[$inp]
+ cmp $enc,#0 // en- or decrypting?
+ ldr $rounds,[$key,#240]
+ vld1.32 {q5-q6},[$key],#32 // load key schedule...
+
+ b.eq .Lecb_small_dec
+ aese $dat0,q5
+ aesmc $dat0,$dat0
+ vld1.32 {q8-q9},[$key],#32 // load key schedule...
+ aese $dat0,q6
+ aesmc $dat0,$dat0
+ subs $rounds,$rounds,#10 // if rounds==10, jump to aes-128-ecb processing
+ b.eq .Lecb_128_enc
+.Lecb_round_loop:
+ aese $dat0,q8
+ aesmc $dat0,$dat0
+ vld1.32 {q8},[$key],#16 // load key schedule...
+ aese $dat0,q9
+ aesmc $dat0,$dat0
+ vld1.32 {q9},[$key],#16 // load key schedule...
+ subs $rounds,$rounds,#2 // bias
+ b.gt .Lecb_round_loop
+.Lecb_128_enc:
+ vld1.32 {q10-q11},[$key],#32 // load key schedule...
+ aese $dat0,q8
+ aesmc $dat0,$dat0
+ aese $dat0,q9
+ aesmc $dat0,$dat0
+ vld1.32 {q12-q13},[$key],#32 // load key schedule...
+ aese $dat0,q10
+ aesmc $dat0,$dat0
+ aese $dat0,q11
+ aesmc $dat0,$dat0
+ vld1.32 {q14-q15},[$key],#32 // load key schedule...
+ aese $dat0,q12
+ aesmc $dat0,$dat0
+ aese $dat0,q13
+ aesmc $dat0,$dat0
+ vld1.32 {$rndlast},[$key]
+ aese $dat0,q14
+ aesmc $dat0,$dat0
+ aese $dat0,q15
+ veor $dat0,$dat0,$rndlast
+ vst1.8 {$dat0},[$out]
+ b .Lecb_Final_abort
+.Lecb_small_dec:
+ aesd $dat0,q5
+ aesimc $dat0,$dat0
+ vld1.32 {q8-q9},[$key],#32 // load key schedule...
+ aesd $dat0,q6
+ aesimc $dat0,$dat0
+ subs $rounds,$rounds,#10 // bias
+ b.eq .Lecb_128_dec
+.Lecb_dec_round_loop:
+ aesd $dat0,q8
+ aesimc $dat0,$dat0
+ vld1.32 {q8},[$key],#16 // load key schedule...
+ aesd $dat0,q9
+ aesimc $dat0,$dat0
+ vld1.32 {q9},[$key],#16 // load key schedule...
+ subs $rounds,$rounds,#2 // bias
+ b.gt .Lecb_dec_round_loop
+.Lecb_128_dec:
+ vld1.32 {q10-q11},[$key],#32 // load key schedule...
+ aesd $dat0,q8
+ aesimc $dat0,$dat0
+ aesd $dat0,q9
+ aesimc $dat0,$dat0
+ vld1.32 {q12-q13},[$key],#32 // load key schedule...
+ aesd $dat0,q10
+ aesimc $dat0,$dat0
+ aesd $dat0,q11
+ aesimc $dat0,$dat0
+ vld1.32 {q14-q15},[$key],#32 // load key schedule...
+ aesd $dat0,q12
+ aesimc $dat0,$dat0
+ aesd $dat0,q13
+ aesimc $dat0,$dat0
+ vld1.32 {$rndlast},[$key]
+ aesd $dat0,q14
+ aesimc $dat0,$dat0
+ aesd $dat0,q15
+ veor $dat0,$dat0,$rndlast
+ vst1.8 {$dat0},[$out]
+ b .Lecb_Final_abort
+.Lecb_big_size:
+___
+$code.=<<___ if ($flavour =~ /64/);
+ stp x29,x30,[sp,#-16]!
+ add x29,sp,#0
+___
+$code.=<<___ if ($flavour !~ /64/);
+ mov ip,sp
+ stmdb sp!,{r4-r8,lr}
+ vstmdb sp!,{d8-d15} @ ABI specification says so
+ ldmia ip,{r4-r5} @ load remaining args
+ subs $len,$len,#16
+___
+$code.=<<___;
+ mov $step,#16
+ b.lo .Lecb_done
+ cclr $step,eq
+
+ cmp $enc,#0 // en- or decrypting?
+ ldr $rounds,[$key,#240]
+ and $len,$len,#-16
+ vld1.8 {$dat},[$inp],$step
+
+ vld1.32 {q8-q9},[$key] // load key schedule...
+ sub $rounds,$rounds,#6
+ add $key_,$key,x5,lsl#4 // pointer to last 7 round keys
+ sub $rounds,$rounds,#2
+ vld1.32 {q10-q11},[$key_],#32
+ vld1.32 {q12-q13},[$key_],#32
+ vld1.32 {q14-q15},[$key_],#32
+ vld1.32 {$rndlast},[$key_]
+
+ add $key_,$key,#32
+ mov $cnt,$rounds
+ b.eq .Lecb_dec
+
+ vld1.8 {$dat1},[$inp],#16
+ subs $len,$len,#32 // bias
+ add $cnt,$rounds,#2
+ vorr $in1,$dat1,$dat1
+ vorr $dat2,$dat1,$dat1
+ vorr $dat1,$dat,$dat
+ b.lo .Lecb_enc_tail
+
+ vorr $dat1,$in1,$in1
+ vld1.8 {$dat2},[$inp],#16
+___
+$code.=<<___ if ($flavour =~ /64/);
+ cmp $len,#32
+ b.lo .Loop3x_ecb_enc
+
+ vld1.8 {$dat3},[$inp],#16
+ vld1.8 {$dat4},[$inp],#16
+ sub $len,$len,#32 // bias
+ mov $cnt,$rounds
+
+.Loop5x_ecb_enc:
+ aese $dat0,q8
+ aesmc $dat0,$dat0
+ aese $dat1,q8
+ aesmc $dat1,$dat1
+ aese $dat2,q8
+ aesmc $dat2,$dat2
+ aese $dat3,q8
+ aesmc $dat3,$dat3
+ aese $dat4,q8
+ aesmc $dat4,$dat4
+ vld1.32 {q8},[$key_],#16
+ subs $cnt,$cnt,#2
+ aese $dat0,q9
+ aesmc $dat0,$dat0
+ aese $dat1,q9
+ aesmc $dat1,$dat1
+ aese $dat2,q9
+ aesmc $dat2,$dat2
+ aese $dat3,q9
+ aesmc $dat3,$dat3
+ aese $dat4,q9
+ aesmc $dat4,$dat4
+ vld1.32 {q9},[$key_],#16
+ b.gt .Loop5x_ecb_enc
+
+ aese $dat0,q8
+ aesmc $dat0,$dat0
+ aese $dat1,q8
+ aesmc $dat1,$dat1
+ aese $dat2,q8
+ aesmc $dat2,$dat2
+ aese $dat3,q8
+ aesmc $dat3,$dat3
+ aese $dat4,q8
+ aesmc $dat4,$dat4
+ cmp $len,#0x40 // because .Lecb_enc_tail4x
+ sub $len,$len,#0x50
+
+ aese $dat0,q9
+ aesmc $dat0,$dat0
+ aese $dat1,q9
+ aesmc $dat1,$dat1
+ aese $dat2,q9
+ aesmc $dat2,$dat2
+ aese $dat3,q9
+ aesmc $dat3,$dat3
+ aese $dat4,q9
+ aesmc $dat4,$dat4
+ csel x6,xzr,$len,gt // borrow x6, $cnt, "gt" is not typo
+ mov $key_,$key
+
+ aese $dat0,q10
+ aesmc $dat0,$dat0
+ aese $dat1,q10
+ aesmc $dat1,$dat1
+ aese $dat2,q10
+ aesmc $dat2,$dat2
+ aese $dat3,q10
+ aesmc $dat3,$dat3
+ aese $dat4,q10
+ aesmc $dat4,$dat4
+ add $inp,$inp,x6 // $inp is adjusted in such way that
+ // at exit from the loop $dat1-$dat4
+ // are loaded with last "words"
+ add x6,$len,#0x60 // because .Lecb_enc_tail4x
+
+ aese $dat0,q11
+ aesmc $dat0,$dat0
+ aese $dat1,q11
+ aesmc $dat1,$dat1
+ aese $dat2,q11
+ aesmc $dat2,$dat2
+ aese $dat3,q11
+ aesmc $dat3,$dat3
+ aese $dat4,q11
+ aesmc $dat4,$dat4
+
+ aese $dat0,q12
+ aesmc $dat0,$dat0
+ aese $dat1,q12
+ aesmc $dat1,$dat1
+ aese $dat2,q12
+ aesmc $dat2,$dat2
+ aese $dat3,q12
+ aesmc $dat3,$dat3
+ aese $dat4,q12
+ aesmc $dat4,$dat4
+
+ aese $dat0,q13
+ aesmc $dat0,$dat0
+ aese $dat1,q13
+ aesmc $dat1,$dat1
+ aese $dat2,q13
+ aesmc $dat2,$dat2
+ aese $dat3,q13
+ aesmc $dat3,$dat3
+ aese $dat4,q13
+ aesmc $dat4,$dat4
+
+ aese $dat0,q14
+ aesmc $dat0,$dat0
+ aese $dat1,q14
+ aesmc $dat1,$dat1
+ aese $dat2,q14
+ aesmc $dat2,$dat2
+ aese $dat3,q14
+ aesmc $dat3,$dat3
+ aese $dat4,q14
+ aesmc $dat4,$dat4
+
+ aese $dat0,q15
+ vld1.8 {$in0},[$inp],#16
+ aese $dat1,q15
+ vld1.8 {$in1},[$inp],#16
+ aese $dat2,q15
+ vld1.8 {$in2},[$inp],#16
+ aese $dat3,q15
+ vld1.8 {$in3},[$inp],#16
+ aese $dat4,q15
+ vld1.8 {$in4},[$inp],#16
+ cbz x6,.Lecb_enc_tail4x
+ vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
+ veor $tmp0,$rndlast,$dat0
+ vorr $dat0,$in0,$in0
+ veor $tmp1,$rndlast,$dat1
+ vorr $dat1,$in1,$in1
+ veor $tmp2,$rndlast,$dat2
+ vorr $dat2,$in2,$in2
+ veor $tmp3,$rndlast,$dat3
+ vorr $dat3,$in3,$in3
+ veor $tmp4,$rndlast,$dat4
+ vst1.8 {$tmp0},[$out],#16
+ vorr $dat4,$in4,$in4
+ vst1.8 {$tmp1},[$out],#16
+ mov $cnt,$rounds
+ vst1.8 {$tmp2},[$out],#16
+ vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
+ vst1.8 {$tmp3},[$out],#16
+ vst1.8 {$tmp4},[$out],#16
+ b.hs .Loop5x_ecb_enc
+
+ add $len,$len,#0x50
+ cbz $len,.Lecb_done
+
+ add $cnt,$rounds,#2
+ subs $len,$len,#0x30
+ vorr $dat0,$in2,$in2
+ vorr $dat1,$in3,$in3
+ vorr $dat2,$in4,$in4
+ b.lo .Lecb_enc_tail
+
+ b .Loop3x_ecb_enc
+
+.align 4
+.Lecb_enc_tail4x:
+ veor $tmp1,$rndlast,$dat1
+ veor $tmp2,$rndlast,$dat2
+ veor $tmp3,$rndlast,$dat3
+ veor $tmp4,$rndlast,$dat4
+ vst1.8 {$tmp1},[$out],#16
+ vst1.8 {$tmp2},[$out],#16
+ vst1.8 {$tmp3},[$out],#16
+ vst1.8 {$tmp4},[$out],#16
+
+ b .Lecb_done
+.align 4
+___
+$code.=<<___;
+.Loop3x_ecb_enc:
+ aese $dat0,q8
+ aesmc $dat0,$dat0
+ aese $dat1,q8
+ aesmc $dat1,$dat1
+ aese $dat2,q8
+ aesmc $dat2,$dat2
+ vld1.32 {q8},[$key_],#16
+ subs $cnt,$cnt,#2
+ aese $dat0,q9
+ aesmc $dat0,$dat0
+ aese $dat1,q9
+ aesmc $dat1,$dat1
+ aese $dat2,q9
+ aesmc $dat2,$dat2
+ vld1.32 {q9},[$key_],#16
+ b.gt .Loop3x_ecb_enc
+
+ aese $dat0,q8
+ aesmc $dat0,$dat0
+ aese $dat1,q8
+ aesmc $dat1,$dat1
+ aese $dat2,q8
+ aesmc $dat2,$dat2
+ subs $len,$len,#0x30
+ mov.lo x6,$len // x6, $cnt, is zero at this point
+ aese $dat0,q9
+ aesmc $dat0,$dat0
+ aese $dat1,q9
+ aesmc $dat1,$dat1
+ aese $dat2,q9
+ aesmc $dat2,$dat2
+ add $inp,$inp,x6 // $inp is adjusted in such way that
+ // at exit from the loop $dat1-$dat2
+ // are loaded with last "words"
+ mov $key_,$key
+ aese $dat0,q12
+ aesmc $dat0,$dat0
+ aese $dat1,q12
+ aesmc $dat1,$dat1
+ aese $dat2,q12
+ aesmc $dat2,$dat2
+ vld1.8 {$in0},[$inp],#16
+ aese $dat0,q13
+ aesmc $dat0,$dat0
+ aese $dat1,q13
+ aesmc $dat1,$dat1
+ aese $dat2,q13
+ aesmc $dat2,$dat2
+ vld1.8 {$in1},[$inp],#16
+ aese $dat0,q14
+ aesmc $dat0,$dat0
+ aese $dat1,q14
+ aesmc $dat1,$dat1
+ aese $dat2,q14
+ aesmc $dat2,$dat2
+ vld1.8 {$in2},[$inp],#16
+ aese $dat0,q15
+ aese $dat1,q15
+ aese $dat2,q15
+ vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
+ add $cnt,$rounds,#2
+ veor $tmp0,$rndlast,$dat0
+ veor $tmp1,$rndlast,$dat1
+ veor $dat2,$dat2,$rndlast
+ vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
+ vst1.8 {$tmp0},[$out],#16
+ vorr $dat0,$in0,$in0
+ vst1.8 {$tmp1},[$out],#16
+ vorr $dat1,$in1,$in1
+ vst1.8 {$dat2},[$out],#16
+ vorr $dat2,$in2,$in2
+ b.hs .Loop3x_ecb_enc
+
+ cmn $len,#0x30
+ b.eq .Lecb_done
+ nop
+
+.Lecb_enc_tail:
+ aese $dat1,q8
+ aesmc $dat1,$dat1
+ aese $dat2,q8
+ aesmc $dat2,$dat2
+ vld1.32 {q8},[$key_],#16
+ subs $cnt,$cnt,#2
+ aese $dat1,q9
+ aesmc $dat1,$dat1
+ aese $dat2,q9
+ aesmc $dat2,$dat2
+ vld1.32 {q9},[$key_],#16
+ b.gt .Lecb_enc_tail
+
+ aese $dat1,q8
+ aesmc $dat1,$dat1
+ aese $dat2,q8
+ aesmc $dat2,$dat2
+ aese $dat1,q9
+ aesmc $dat1,$dat1
+ aese $dat2,q9
+ aesmc $dat2,$dat2
+ aese $dat1,q12
+ aesmc $dat1,$dat1
+ aese $dat2,q12
+ aesmc $dat2,$dat2
+ cmn $len,#0x20
+ aese $dat1,q13
+ aesmc $dat1,$dat1
+ aese $dat2,q13
+ aesmc $dat2,$dat2
+ aese $dat1,q14
+ aesmc $dat1,$dat1
+ aese $dat2,q14
+ aesmc $dat2,$dat2
+ aese $dat1,q15
+ aese $dat2,q15
+ b.eq .Lecb_enc_one
+ veor $tmp1,$rndlast,$dat1
+ veor $tmp2,$rndlast,$dat2
+ vst1.8 {$tmp1},[$out],#16
+ vst1.8 {$tmp2},[$out],#16
+ b .Lecb_done
+
+.Lecb_enc_one:
+ veor $tmp1,$rndlast,$dat2
+ vst1.8 {$tmp1},[$out],#16
+ b .Lecb_done
+___
+
+$code.=<<___;
+.align 5
+.Lecb_dec:
+ vld1.8 {$dat1},[$inp],#16
+ subs $len,$len,#32 // bias
+ add $cnt,$rounds,#2
+ vorr $in1,$dat1,$dat1
+ vorr $dat2,$dat1,$dat1
+ vorr $dat1,$dat,$dat
+ b.lo .Lecb_dec_tail
+
+ vorr $dat1,$in1,$in1
+ vld1.8 {$dat2},[$inp],#16
+___
+$code.=<<___ if ($flavour =~ /64/);
+ cmp $len,#32
+ b.lo .Loop3x_ecb_dec
+
+ vld1.8 {$dat3},[$inp],#16
+ vld1.8 {$dat4},[$inp],#16
+ sub $len,$len,#32 // bias
+ mov $cnt,$rounds
+
+.Loop5x_ecb_dec:
+ aesd $dat0,q8
+ aesimc $dat0,$dat0
+ aesd $dat1,q8
+ aesimc $dat1,$dat1
+ aesd $dat2,q8
+ aesimc $dat2,$dat2
+ aesd $dat3,q8
+ aesimc $dat3,$dat3
+ aesd $dat4,q8
+ aesimc $dat4,$dat4
+ vld1.32 {q8},[$key_],#16
+ subs $cnt,$cnt,#2
+ aesd $dat0,q9
+ aesimc $dat0,$dat0
+ aesd $dat1,q9
+ aesimc $dat1,$dat1
+ aesd $dat2,q9
+ aesimc $dat2,$dat2
+ aesd $dat3,q9
+ aesimc $dat3,$dat3
+ aesd $dat4,q9
+ aesimc $dat4,$dat4
+ vld1.32 {q9},[$key_],#16
+ b.gt .Loop5x_ecb_dec
+
+ aesd $dat0,q8
+ aesimc $dat0,$dat0
+ aesd $dat1,q8
+ aesimc $dat1,$dat1
+ aesd $dat2,q8
+ aesimc $dat2,$dat2
+ aesd $dat3,q8
+ aesimc $dat3,$dat3
+ aesd $dat4,q8
+ aesimc $dat4,$dat4
+ cmp $len,#0x40 // because .Lecb_tail4x
+ sub $len,$len,#0x50
+
+ aesd $dat0,q9
+ aesimc $dat0,$dat0
+ aesd $dat1,q9
+ aesimc $dat1,$dat1
+ aesd $dat2,q9
+ aesimc $dat2,$dat2
+ aesd $dat3,q9
+ aesimc $dat3,$dat3
+ aesd $dat4,q9
+ aesimc $dat4,$dat4
+ csel x6,xzr,$len,gt // borrow x6, $cnt, "gt" is not typo
+ mov $key_,$key
+
+ aesd $dat0,q10
+ aesimc $dat0,$dat0
+ aesd $dat1,q10
+ aesimc $dat1,$dat1
+ aesd $dat2,q10
+ aesimc $dat2,$dat2
+ aesd $dat3,q10
+ aesimc $dat3,$dat3
+ aesd $dat4,q10
+ aesimc $dat4,$dat4
+ add $inp,$inp,x6 // $inp is adjusted in such way that
+ // at exit from the loop $dat1-$dat4
+ // are loaded with last "words"
+ add x6,$len,#0x60 // because .Lecb_tail4x
+
+ aesd $dat0,q11
+ aesimc $dat0,$dat0
+ aesd $dat1,q11
+ aesimc $dat1,$dat1
+ aesd $dat2,q11
+ aesimc $dat2,$dat2
+ aesd $dat3,q11
+ aesimc $dat3,$dat3
+ aesd $dat4,q11
+ aesimc $dat4,$dat4
+
+ aesd $dat0,q12
+ aesimc $dat0,$dat0
+ aesd $dat1,q12
+ aesimc $dat1,$dat1
+ aesd $dat2,q12
+ aesimc $dat2,$dat2
+ aesd $dat3,q12
+ aesimc $dat3,$dat3
+ aesd $dat4,q12
+ aesimc $dat4,$dat4
+
+ aesd $dat0,q13
+ aesimc $dat0,$dat0
+ aesd $dat1,q13
+ aesimc $dat1,$dat1
+ aesd $dat2,q13
+ aesimc $dat2,$dat2
+ aesd $dat3,q13
+ aesimc $dat3,$dat3
+ aesd $dat4,q13
+ aesimc $dat4,$dat4
+
+ aesd $dat0,q14
+ aesimc $dat0,$dat0
+ aesd $dat1,q14
+ aesimc $dat1,$dat1
+ aesd $dat2,q14
+ aesimc $dat2,$dat2
+ aesd $dat3,q14
+ aesimc $dat3,$dat3
+ aesd $dat4,q14
+ aesimc $dat4,$dat4
+
+ aesd $dat0,q15
+ vld1.8 {$in0},[$inp],#16
+ aesd $dat1,q15
+ vld1.8 {$in1},[$inp],#16
+ aesd $dat2,q15
+ vld1.8 {$in2},[$inp],#16
+ aesd $dat3,q15
+ vld1.8 {$in3},[$inp],#16
+ aesd $dat4,q15
+ vld1.8 {$in4},[$inp],#16
+ cbz x6,.Lecb_tail4x
+ vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
+ veor $tmp0,$rndlast,$dat0
+ vorr $dat0,$in0,$in0
+ veor $tmp1,$rndlast,$dat1
+ vorr $dat1,$in1,$in1
+ veor $tmp2,$rndlast,$dat2
+ vorr $dat2,$in2,$in2
+ veor $tmp3,$rndlast,$dat3
+ vorr $dat3,$in3,$in3
+ veor $tmp4,$rndlast,$dat4
+ vst1.8 {$tmp0},[$out],#16
+ vorr $dat4,$in4,$in4
+ vst1.8 {$tmp1},[$out],#16
+ mov $cnt,$rounds
+ vst1.8 {$tmp2},[$out],#16
+ vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
+ vst1.8 {$tmp3},[$out],#16
+ vst1.8 {$tmp4},[$out],#16
+ b.hs .Loop5x_ecb_dec
+
+ add $len,$len,#0x50
+ cbz $len,.Lecb_done
+
+ add $cnt,$rounds,#2
+ subs $len,$len,#0x30
+ vorr $dat0,$in2,$in2
+ vorr $dat1,$in3,$in3
+ vorr $dat2,$in4,$in4
+ b.lo .Lecb_dec_tail
+
+ b .Loop3x_ecb_dec
+
+.align 4
+.Lecb_tail4x:
+ veor $tmp1,$rndlast,$dat1
+ veor $tmp2,$rndlast,$dat2
+ veor $tmp3,$rndlast,$dat3
+ veor $tmp4,$rndlast,$dat4
+ vst1.8 {$tmp1},[$out],#16
+ vst1.8 {$tmp2},[$out],#16
+ vst1.8 {$tmp3},[$out],#16
+ vst1.8 {$tmp4},[$out],#16
+
+ b .Lecb_done
+.align 4
+___
+$code.=<<___;
+.Loop3x_ecb_dec:
+ aesd $dat0,q8
+ aesimc $dat0,$dat0
+ aesd $dat1,q8
+ aesimc $dat1,$dat1
+ aesd $dat2,q8
+ aesimc $dat2,$dat2
+ vld1.32 {q8},[$key_],#16
+ subs $cnt,$cnt,#2
+ aesd $dat0,q9
+ aesimc $dat0,$dat0
+ aesd $dat1,q9
+ aesimc $dat1,$dat1
+ aesd $dat2,q9
+ aesimc $dat2,$dat2
+ vld1.32 {q9},[$key_],#16
+ b.gt .Loop3x_ecb_dec
+
+ aesd $dat0,q8
+ aesimc $dat0,$dat0
+ aesd $dat1,q8
+ aesimc $dat1,$dat1
+ aesd $dat2,q8
+ aesimc $dat2,$dat2
+ subs $len,$len,#0x30
+ mov.lo x6,$len // x6, $cnt, is zero at this point
+ aesd $dat0,q9
+ aesimc $dat0,$dat0
+ aesd $dat1,q9
+ aesimc $dat1,$dat1
+ aesd $dat2,q9
+ aesimc $dat2,$dat2
+ add $inp,$inp,x6 // $inp is adjusted in such way that
+ // at exit from the loop $dat1-$dat2
+ // are loaded with last "words"
+ mov $key_,$key
+ aesd $dat0,q12
+ aesimc $dat0,$dat0
+ aesd $dat1,q12
+ aesimc $dat1,$dat1
+ aesd $dat2,q12
+ aesimc $dat2,$dat2
+ vld1.8 {$in0},[$inp],#16
+ aesd $dat0,q13
+ aesimc $dat0,$dat0
+ aesd $dat1,q13
+ aesimc $dat1,$dat1
+ aesd $dat2,q13
+ aesimc $dat2,$dat2
+ vld1.8 {$in1},[$inp],#16
+ aesd $dat0,q14
+ aesimc $dat0,$dat0
+ aesd $dat1,q14
+ aesimc $dat1,$dat1
+ aesd $dat2,q14
+ aesimc $dat2,$dat2
+ vld1.8 {$in2},[$inp],#16
+ aesd $dat0,q15
+ aesd $dat1,q15
+ aesd $dat2,q15
+ vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
+ add $cnt,$rounds,#2
+ veor $tmp0,$rndlast,$dat0
+ veor $tmp1,$rndlast,$dat1
+ veor $dat2,$dat2,$rndlast
+ vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
+ vst1.8 {$tmp0},[$out],#16
+ vorr $dat0,$in0,$in0
+ vst1.8 {$tmp1},[$out],#16
+ vorr $dat1,$in1,$in1
+ vst1.8 {$dat2},[$out],#16
+ vorr $dat2,$in2,$in2
+ b.hs .Loop3x_ecb_dec
+
+ cmn $len,#0x30
+ b.eq .Lecb_done
+ nop
+
+.Lecb_dec_tail:
+ aesd $dat1,q8
+ aesimc $dat1,$dat1
+ aesd $dat2,q8
+ aesimc $dat2,$dat2
+ vld1.32 {q8},[$key_],#16
+ subs $cnt,$cnt,#2
+ aesd $dat1,q9
+ aesimc $dat1,$dat1
+ aesd $dat2,q9
+ aesimc $dat2,$dat2
+ vld1.32 {q9},[$key_],#16
+ b.gt .Lecb_dec_tail
+
+ aesd $dat1,q8
+ aesimc $dat1,$dat1
+ aesd $dat2,q8
+ aesimc $dat2,$dat2
+ aesd $dat1,q9
+ aesimc $dat1,$dat1
+ aesd $dat2,q9
+ aesimc $dat2,$dat2
+ aesd $dat1,q12
+ aesimc $dat1,$dat1
+ aesd $dat2,q12
+ aesimc $dat2,$dat2
+ cmn $len,#0x20
+ aesd $dat1,q13
+ aesimc $dat1,$dat1
+ aesd $dat2,q13
+ aesimc $dat2,$dat2
+ aesd $dat1,q14
+ aesimc $dat1,$dat1
+ aesd $dat2,q14
+ aesimc $dat2,$dat2
+ aesd $dat1,q15
+ aesd $dat2,q15
+ b.eq .Lecb_dec_one
+ veor $tmp1,$rndlast,$dat1
+ veor $tmp2,$rndlast,$dat2
+ vst1.8 {$tmp1},[$out],#16
+ vst1.8 {$tmp2},[$out],#16
+ b .Lecb_done
+
+.Lecb_dec_one:
+ veor $tmp1,$rndlast,$dat2
+ vst1.8 {$tmp1},[$out],#16
+
+.Lecb_done:
+___
+}
+$code.=<<___ if ($flavour !~ /64/);
+ vldmia sp!,{d8-d15}
+ ldmia sp!,{r4-r8,pc}
+___
+$code.=<<___ if ($flavour =~ /64/);
+ ldr x29,[sp],#16
+___
+$code.=<<___ if ($flavour =~ /64/);
+.Lecb_Final_abort:
+ ret
+___
+$code.=<<___;
+.size ${prefix}_ecb_encrypt,.-${prefix}_ecb_encrypt
+___
+}}}
{{{
my ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4)); my $enc="w5";
my ($rounds,$cnt,$key_,$step,$step1)=($enc,"w6","x7","x8","x12");
@@ -519,6 +1377,13 @@ $code.=<<___;
___
{
my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9));
+
+my ($dat3,$in3,$tmp3); # used only in 64-bit mode
+my ($dat4,$in4,$tmp4);
+if ($flavour =~ /64/) {
+ ($dat2,$dat3,$dat4,$in2,$in3,$in4,$tmp3,$tmp4)=map("q$_",(16..23));
+}
+
$code.=<<___;
.align 5
.Lcbc_dec:
@@ -535,7 +1400,196 @@ $code.=<<___;
vorr $in0,$dat,$dat
vorr $in1,$dat1,$dat1
vorr $in2,$dat2,$dat2
+___
+$code.=<<___ if ($flavour =~ /64/);
+ cmp $len,#32
+ b.lo .Loop3x_cbc_dec
+
+ vld1.8 {$dat3},[$inp],#16
+ vld1.8 {$dat4},[$inp],#16
+ sub $len,$len,#32 // bias
+ mov $cnt,$rounds
+ vorr $in3,$dat3,$dat3
+ vorr $in4,$dat4,$dat4
+
+.Loop5x_cbc_dec:
+ aesd $dat0,q8
+ aesimc $dat0,$dat0
+ aesd $dat1,q8
+ aesimc $dat1,$dat1
+ aesd $dat2,q8
+ aesimc $dat2,$dat2
+ aesd $dat3,q8
+ aesimc $dat3,$dat3
+ aesd $dat4,q8
+ aesimc $dat4,$dat4
+ vld1.32 {q8},[$key_],#16
+ subs $cnt,$cnt,#2
+ aesd $dat0,q9
+ aesimc $dat0,$dat0
+ aesd $dat1,q9
+ aesimc $dat1,$dat1
+ aesd $dat2,q9
+ aesimc $dat2,$dat2
+ aesd $dat3,q9
+ aesimc $dat3,$dat3
+ aesd $dat4,q9
+ aesimc $dat4,$dat4
+ vld1.32 {q9},[$key_],#16
+ b.gt .Loop5x_cbc_dec
+
+ aesd $dat0,q8
+ aesimc $dat0,$dat0
+ aesd $dat1,q8
+ aesimc $dat1,$dat1
+ aesd $dat2,q8
+ aesimc $dat2,$dat2
+ aesd $dat3,q8
+ aesimc $dat3,$dat3
+ aesd $dat4,q8
+ aesimc $dat4,$dat4
+ cmp $len,#0x40 // because .Lcbc_tail4x
+ sub $len,$len,#0x50
+
+ aesd $dat0,q9
+ aesimc $dat0,$dat0
+ aesd $dat1,q9
+ aesimc $dat1,$dat1
+ aesd $dat2,q9
+ aesimc $dat2,$dat2
+ aesd $dat3,q9
+ aesimc $dat3,$dat3
+ aesd $dat4,q9
+ aesimc $dat4,$dat4
+ csel x6,xzr,$len,gt // borrow x6, $cnt, "gt" is not typo
+ mov $key_,$key
+ aesd $dat0,q10
+ aesimc $dat0,$dat0
+ aesd $dat1,q10
+ aesimc $dat1,$dat1
+ aesd $dat2,q10
+ aesimc $dat2,$dat2
+ aesd $dat3,q10
+ aesimc $dat3,$dat3
+ aesd $dat4,q10
+ aesimc $dat4,$dat4
+ add $inp,$inp,x6 // $inp is adjusted in such way that
+ // at exit from the loop $dat1-$dat4
+ // are loaded with last "words"
+ add x6,$len,#0x60 // because .Lcbc_tail4x
+
+ aesd $dat0,q11
+ aesimc $dat0,$dat0
+ aesd $dat1,q11
+ aesimc $dat1,$dat1
+ aesd $dat2,q11
+ aesimc $dat2,$dat2
+ aesd $dat3,q11
+ aesimc $dat3,$dat3
+ aesd $dat4,q11
+ aesimc $dat4,$dat4
+
+ aesd $dat0,q12
+ aesimc $dat0,$dat0
+ aesd $dat1,q12
+ aesimc $dat1,$dat1
+ aesd $dat2,q12
+ aesimc $dat2,$dat2
+ aesd $dat3,q12
+ aesimc $dat3,$dat3
+ aesd $dat4,q12
+ aesimc $dat4,$dat4
+
+ aesd $dat0,q13
+ aesimc $dat0,$dat0
+ aesd $dat1,q13
+ aesimc $dat1,$dat1
+ aesd $dat2,q13
+ aesimc $dat2,$dat2
+ aesd $dat3,q13
+ aesimc $dat3,$dat3
+ aesd $dat4,q13
+ aesimc $dat4,$dat4
+
+ aesd $dat0,q14
+ aesimc $dat0,$dat0
+ aesd $dat1,q14
+ aesimc $dat1,$dat1
+ aesd $dat2,q14
+ aesimc $dat2,$dat2
+ aesd $dat3,q14
+ aesimc $dat3,$dat3
+ aesd $dat4,q14
+ aesimc $dat4,$dat4
+
+ veor $tmp0,$ivec,$rndlast
+ aesd $dat0,q15
+ veor $tmp1,$in0,$rndlast
+ vld1.8 {$in0},[$inp],#16
+ aesd $dat1,q15
+ veor $tmp2,$in1,$rndlast
+ vld1.8 {$in1},[$inp],#16
+ aesd $dat2,q15
+ veor $tmp3,$in2,$rndlast
+ vld1.8 {$in2},[$inp],#16
+ aesd $dat3,q15
+ veor $tmp4,$in3,$rndlast
+ vld1.8 {$in3},[$inp],#16
+ aesd $dat4,q15
+ vorr $ivec,$in4,$in4
+ vld1.8 {$in4},[$inp],#16
+ cbz x6,.Lcbc_tail4x
+ vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
+ veor $tmp0,$tmp0,$dat0
+ vorr $dat0,$in0,$in0
+ veor $tmp1,$tmp1,$dat1
+ vorr $dat1,$in1,$in1
+ veor $tmp2,$tmp2,$dat2
+ vorr $dat2,$in2,$in2
+ veor $tmp3,$tmp3,$dat3
+ vorr $dat3,$in3,$in3
+ veor $tmp4,$tmp4,$dat4
+ vst1.8 {$tmp0},[$out],#16
+ vorr $dat4,$in4,$in4
+ vst1.8 {$tmp1},[$out],#16
+ mov $cnt,$rounds
+ vst1.8 {$tmp2},[$out],#16
+ vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
+ vst1.8 {$tmp3},[$out],#16
+ vst1.8 {$tmp4},[$out],#16
+ b.hs .Loop5x_cbc_dec
+
+ add $len,$len,#0x50
+ cbz $len,.Lcbc_done
+
+ add $cnt,$rounds,#2
+ subs $len,$len,#0x30
+ vorr $dat0,$in2,$in2
+ vorr $in0,$in2,$in2
+ vorr $dat1,$in3,$in3
+ vorr $in1,$in3,$in3
+ vorr $dat2,$in4,$in4
+ vorr $in2,$in4,$in4
+ b.lo .Lcbc_dec_tail
+
+ b .Loop3x_cbc_dec
+
+.align 4
+.Lcbc_tail4x:
+ veor $tmp1,$tmp0,$dat1
+ veor $tmp2,$tmp2,$dat2
+ veor $tmp3,$tmp3,$dat3
+ veor $tmp4,$tmp4,$dat4
+ vst1.8 {$tmp1},[$out],#16
+ vst1.8 {$tmp2},[$out],#16
+ vst1.8 {$tmp3},[$out],#16
+ vst1.8 {$tmp4},[$out],#16
+
+ b .Lcbc_done
+.align 4
+___
+$code.=<<___;
.Loop3x_cbc_dec:
aesd $dat0,q8
aesimc $dat0,$dat0
@@ -696,6 +1750,9 @@ my $step="x12"; # aliases with $tctr2
my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7));
my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9));
+# used only in 64-bit mode...
+my ($dat3,$dat4,$in3,$in4)=map("q$_",(16..23));
+
my ($dat,$tmp)=($dat0,$tmp0);
### q8-q15 preloaded key schedule
@@ -767,6 +1824,173 @@ $code.=<<___ if ($flavour !~ /64/);
sub $len,$len,#3 // bias
vorr $dat2,$ivec,$ivec
___
+$code.=<<___ if ($flavour =~ /64/);
+ cmp $len,#32
+ b.lo .Loop3x_ctr32
+
+ add w13,$ctr,#1
+ add w14,$ctr,#2
+ vorr $dat3,$dat0,$dat0
+ rev w13,w13
+ vorr $dat4,$dat0,$dat0
+ rev w14,w14
+ vmov.32 ${dat3}[3],w13
+ sub $len,$len,#2 // bias
+ vmov.32 ${dat4}[3],w14
+ add $ctr,$ctr,#2
+ b .Loop5x_ctr32
+
+.align 4
+.Loop5x_ctr32:
+ aese $dat0,q8
+ aesmc $dat0,$dat0
+ aese $dat1,q8
+ aesmc $dat1,$dat1
+ aese $dat2,q8
+ aesmc $dat2,$dat2
+ aese $dat3,q8
+ aesmc $dat3,$dat3
+ aese $dat4,q8
+ aesmc $dat4,$dat4
+ vld1.32 {q8},[$key_],#16
+ subs $cnt,$cnt,#2
+ aese $dat0,q9
+ aesmc $dat0,$dat0
+ aese $dat1,q9
+ aesmc $dat1,$dat1
+ aese $dat2,q9
+ aesmc $dat2,$dat2
+ aese $dat3,q9
+ aesmc $dat3,$dat3
+ aese $dat4,q9
+ aesmc $dat4,$dat4
+ vld1.32 {q9},[$key_],#16
+ b.gt .Loop5x_ctr32
+
+ mov $key_,$key
+ aese $dat0,q8
+ aesmc $dat0,$dat0
+ aese $dat1,q8
+ aesmc $dat1,$dat1
+ aese $dat2,q8
+ aesmc $dat2,$dat2
+ aese $dat3,q8
+ aesmc $dat3,$dat3
+ aese $dat4,q8
+ aesmc $dat4,$dat4
+ vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
+
+ aese $dat0,q9
+ aesmc $dat0,$dat0
+ aese $dat1,q9
+ aesmc $dat1,$dat1
+ aese $dat2,q9
+ aesmc $dat2,$dat2
+ aese $dat3,q9
+ aesmc $dat3,$dat3
+ aese $dat4,q9
+ aesmc $dat4,$dat4
+ vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
+
+ aese $dat0,q12
+ aesmc $dat0,$dat0
+ add $tctr0,$ctr,#1
+ add $tctr1,$ctr,#2
+ aese $dat1,q12
+ aesmc $dat1,$dat1
+ add $tctr2,$ctr,#3
+ add w13,$ctr,#4
+ aese $dat2,q12
+ aesmc $dat2,$dat2
+ add w14,$ctr,#5
+ rev $tctr0,$tctr0
+ aese $dat3,q12
+ aesmc $dat3,$dat3
+ rev $tctr1,$tctr1
+ rev $tctr2,$tctr2
+ aese $dat4,q12
+ aesmc $dat4,$dat4
+ rev w13,w13
+ rev w14,w14
+
+ aese $dat0,q13
+ aesmc $dat0,$dat0
+ aese $dat1,q13
+ aesmc $dat1,$dat1
+ aese $dat2,q13
+ aesmc $dat2,$dat2
+ aese $dat3,q13
+ aesmc $dat3,$dat3
+ aese $dat4,q13
+ aesmc $dat4,$dat4
+
+ aese $dat0,q14
+ aesmc $dat0,$dat0
+ vld1.8 {$in0},[$inp],#16
+ aese $dat1,q14
+ aesmc $dat1,$dat1
+ vld1.8 {$in1},[$inp],#16
+ aese $dat2,q14
+ aesmc $dat2,$dat2
+ vld1.8 {$in2},[$inp],#16
+ aese $dat3,q14
+ aesmc $dat3,$dat3
+ vld1.8 {$in3},[$inp],#16
+ aese $dat4,q14
+ aesmc $dat4,$dat4
+ vld1.8 {$in4},[$inp],#16
+
+ aese $dat0,q15
+ veor $in0,$in0,$rndlast
+ aese $dat1,q15
+ veor $in1,$in1,$rndlast
+ aese $dat2,q15
+ veor $in2,$in2,$rndlast
+ aese $dat3,q15
+ veor $in3,$in3,$rndlast
+ aese $dat4,q15
+ veor $in4,$in4,$rndlast
+
+ veor $in0,$in0,$dat0
+ vorr $dat0,$ivec,$ivec
+ veor $in1,$in1,$dat1
+ vorr $dat1,$ivec,$ivec
+ veor $in2,$in2,$dat2
+ vorr $dat2,$ivec,$ivec
+ veor $in3,$in3,$dat3
+ vorr $dat3,$ivec,$ivec
+ veor $in4,$in4,$dat4
+ vorr $dat4,$ivec,$ivec
+
+ vst1.8 {$in0},[$out],#16
+ vmov.32 ${dat0}[3],$tctr0
+ vst1.8 {$in1},[$out],#16
+ vmov.32 ${dat1}[3],$tctr1
+ vst1.8 {$in2},[$out],#16
+ vmov.32 ${dat2}[3],$tctr2
+ vst1.8 {$in3},[$out],#16
+ vmov.32 ${dat3}[3],w13
+ vst1.8 {$in4},[$out],#16
+ vmov.32 ${dat4}[3],w14
+
+ mov $cnt,$rounds
+ cbz $len,.Lctr32_done
+
+ add $ctr,$ctr,#5
+ subs $len,$len,#5
+ b.hs .Loop5x_ctr32
+
+ add $len,$len,#5
+ sub $ctr,$ctr,#5
+
+ cmp $len,#2
+ mov $step,#16
+ cclr $step,lo
+ b.ls .Lctr32_tail
+
+ sub $len,$len,#3 // bias
+ add $ctr,$ctr,#3
+___
$code.=<<___;
b .Loop3x_ctr32
@@ -967,6 +2191,1432 @@ $code.=<<___;
.size ${prefix}_ctr32_encrypt_blocks,.-${prefix}_ctr32_encrypt_blocks
___
}}}
+# Performance in cycles per byte.
+# Processed with AES-XTS different key size.
+# It shows the value before and after optimization as below:
+# (before/after):
+#
+# AES-128-XTS AES-256-XTS
+# Cortex-A57 3.36/1.09 4.02/1.37
+# Cortex-A72 3.03/1.02 3.28/1.33
+
+# Optimization is implemented by loop unrolling and interleaving.
+# Commonly, we choose the unrolling factor as 5, if the input
+# data size smaller than 5 blocks, but not smaller than 3 blocks,
+# choose 3 as the unrolling factor.
+# If the input data size dsize >= 5*16 bytes, then take 5 blocks
+# as one iteration, every loop the left size lsize -= 5*16.
+# If lsize < 5*16 bytes, treat them as the tail. Note: left 4*16 bytes
+# will be processed specially, which be integrated into the 5*16 bytes
+# loop to improve the efficiency.
+# There is one special case, if the original input data size dsize
+# = 16 bytes, we will treat it seperately to improve the
+# performance: one independent code block without LR, FP load and
+# store.
+# Encryption will process the (length -tailcnt) bytes as mentioned
+# previously, then encrypt the composite block as last second
+# cipher block.
+# Decryption will process the (length -tailcnt -1) bytes as mentioned
+# previously, then decrypt the last second cipher block to get the
+# last plain block(tail), decrypt the composite block as last second
+# plain text block.
+
+{{{
+my ($inp,$out,$len,$key1,$key2,$ivp)=map("x$_",(0..5));
+my ($rounds0,$rounds,$key_,$step,$ivl,$ivh)=("w5","w6","x7","x8","x9","x10");
+my ($tmpoutp,$loutp,$l2outp,$tmpinp)=("x13","w14","w15","x20");
+my ($tailcnt,$midnum,$midnumx,$constnum,$constnumx)=("x21","w22","x22","w19","x19");
+my ($xoffset,$tmpmx,$tmpmw)=("x6","x11","w11");
+my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$tmp2,$rndlast)=map("q$_",(0..7));
+my ($iv0,$iv1,$iv2,$iv3,$iv4)=("v6.16b","v8.16b","v9.16b","v10.16b","v11.16b");
+my ($ivd00,$ivd01,$ivd20,$ivd21)=("d6","v6.d[1]","d9","v9.d[1]");
+my ($ivd10,$ivd11,$ivd30,$ivd31,$ivd40,$ivd41)=("d8","v8.d[1]","d10","v10.d[1]","d11","v11.d[1]");
+
+my ($tmpin)=("v26.16b");
+my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1);
+
+# q7 last round key
+# q10-q15, q7 Last 7 round keys
+# q8-q9 preloaded round keys except last 7 keys for big size
+# q20, q21, q8-q9 preloaded round keys except last 7 keys for only 16 byte
+
+
+my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9));
+
+my ($dat3,$in3,$tmp3); # used only in 64-bit mode
+my ($dat4,$in4,$tmp4);
+if ($flavour =~ /64/) {
+ ($dat2,$dat3,$dat4,$in2,$in3,$in4,$tmp3,$tmp4)=map("q$_",(16..23));
+}
+
+$code.=<<___ if ($flavour =~ /64/);
+.globl ${prefix}_xts_encrypt
+.type ${prefix}_xts_encrypt,%function
+.align 5
+${prefix}_xts_encrypt:
+___
+$code.=<<___ if ($flavour =~ /64/);
+ cmp $len,#16
+ // Original input data size bigger than 16, jump to big size processing.
+ b.ne .Lxts_enc_big_size
+ // Encrypt the iv with key2, as the first XEX iv.
+ ldr $rounds,[$key2,#240]
+ vld1.8 {$dat},[$key2],#16
+ vld1.8 {$iv0},[$ivp]
+ sub $rounds,$rounds,#2
+ vld1.8 {$dat1},[$key2],#16
+
+.Loop_enc_iv_enc:
+ aese $iv0,$dat
+ aesmc $iv0,$iv0
+ vld1.32 {$dat},[$key2],#16
+ subs $rounds,$rounds,#2
+ aese $iv0,$dat1
+ aesmc $iv0,$iv0
+ vld1.32 {$dat1},[$key2],#16
+ b.gt .Loop_enc_iv_enc
+
+ aese $iv0,$dat
+ aesmc $iv0,$iv0
+ vld1.32 {$dat},[$key2]
+ aese $iv0,$dat1
+ veor $iv0,$iv0,$dat
+
+ vld1.8 {$dat0},[$inp]
+ veor $dat0,$iv0,$dat0
+
+ ldr $rounds,[$key1,#240]
+ vld1.32 {q20-q21},[$key1],#32 // load key schedule...
+
+ aese $dat0,q20
+ aesmc $dat0,$dat0
+ vld1.32 {q8-q9},[$key1],#32 // load key schedule...
+ aese $dat0,q21
+ aesmc $dat0,$dat0
+ subs $rounds,$rounds,#10 // if rounds==10, jump to aes-128-xts processing
+ b.eq .Lxts_128_enc
+.Lxts_enc_round_loop:
+ aese $dat0,q8
+ aesmc $dat0,$dat0
+ vld1.32 {q8},[$key1],#16 // load key schedule...
+ aese $dat0,q9
+ aesmc $dat0,$dat0
+ vld1.32 {q9},[$key1],#16 // load key schedule...
+ subs $rounds,$rounds,#2 // bias
+ b.gt .Lxts_enc_round_loop
+.Lxts_128_enc:
+ vld1.32 {q10-q11},[$key1],#32 // load key schedule...
+ aese $dat0,q8
+ aesmc $dat0,$dat0
+ aese $dat0,q9
+ aesmc $dat0,$dat0
+ vld1.32 {q12-q13},[$key1],#32 // load key schedule...
+ aese $dat0,q10
+ aesmc $dat0,$dat0
+ aese $dat0,q11
+ aesmc $dat0,$dat0
+ vld1.32 {q14-q15},[$key1],#32 // load key schedule...
+ aese $dat0,q12
+ aesmc $dat0,$dat0
+ aese $dat0,q13
+ aesmc $dat0,$dat0
+ vld1.32 {$rndlast},[$key1]
+ aese $dat0,q14
+ aesmc $dat0,$dat0
+ aese $dat0,q15
+ veor $dat0,$dat0,$rndlast
+ veor $dat0,$dat0,$iv0
+ vst1.8 {$dat0},[$out]
+ b .Lxts_enc_final_abort
+
+.align 4
+.Lxts_enc_big_size:
+___
+$code.=<<___ if ($flavour =~ /64/);
+ stp $constnumx,$tmpinp,[sp,#-64]!
+ stp $tailcnt,$midnumx,[sp,#48]
+ stp $ivd10,$ivd20,[sp,#32]
+ stp $ivd30,$ivd40,[sp,#16]
+
+ // tailcnt store the tail value of length%16.
+ and $tailcnt,$len,#0xf
+ and $len,$len,#-16
+ subs $len,$len,#16
+ mov $step,#16
+ b.lo .Lxts_abort
+ csel $step,xzr,$step,eq
+
+ // Firstly, encrypt the iv with key2, as the first iv of XEX.
+ ldr $rounds,[$key2,#240]
+ vld1.32 {$dat},[$key2],#16
+ vld1.8 {$iv0},[$ivp]
+ sub $rounds,$rounds,#2
+ vld1.32 {$dat1},[$key2],#16
+
+.Loop_iv_enc:
+ aese $iv0,$dat
+ aesmc $iv0,$iv0
+ vld1.32 {$dat},[$key2],#16
+ subs $rounds,$rounds,#2
+ aese $iv0,$dat1
+ aesmc $iv0,$iv0
+ vld1.32 {$dat1},[$key2],#16
+ b.gt .Loop_iv_enc
+
+ aese $iv0,$dat
+ aesmc $iv0,$iv0
+ vld1.32 {$dat},[$key2]
+ aese $iv0,$dat1
+ veor $iv0,$iv0,$dat
+
+ // The iv for second block
+ // $ivl- iv(low), $ivh - iv(high)
+ // the five ivs stored into, $iv0,$iv1,$iv2,$iv3,$iv4
+ fmov $ivl,$ivd00
+ fmov $ivh,$ivd01
+ mov $constnum,#0x87
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr#31
+ eor $ivl,$tmpmx,$ivl,lsl#1
+ fmov $ivd10,$ivl
+ fmov $ivd11,$ivh
+
+ ldr $rounds0,[$key1,#240] // next starting point
+ vld1.8 {$dat},[$inp],$step
+
+ vld1.32 {q8-q9},[$key1] // load key schedule...
+ sub $rounds0,$rounds0,#6
+ add $key_,$key1,$ivp,lsl#4 // pointer to last 7 round keys
+ sub $rounds0,$rounds0,#2
+ vld1.32 {q10-q11},[$key_],#32
+ vld1.32 {q12-q13},[$key_],#32
+ vld1.32 {q14-q15},[$key_],#32
+ vld1.32 {$rndlast},[$key_]
+
+ add $key_,$key1,#32
+ mov $rounds,$rounds0
+
+ // Encryption
+.Lxts_enc:
+ vld1.8 {$dat2},[$inp],#16
+ subs $len,$len,#32 // bias
+ add $rounds,$rounds0,#2
+ vorr $in1,$dat,$dat
+ vorr $dat1,$dat,$dat
+ vorr $in3,$dat,$dat
+ vorr $in2,$dat2,$dat2
+ vorr $in4,$dat2,$dat2
+ b.lo .Lxts_inner_enc_tail
+ veor $dat,$dat,$iv0 // before encryption, xor with iv
+ veor $dat2,$dat2,$iv1
+
+ // The iv for third block
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr#31
+ eor $ivl,$tmpmx,$ivl,lsl#1
+ fmov $ivd20,$ivl
+ fmov $ivd21,$ivh
+
+
+ vorr $dat1,$dat2,$dat2
+ vld1.8 {$dat2},[$inp],#16
+ vorr $in0,$dat,$dat
+ vorr $in1,$dat1,$dat1
+ veor $in2,$dat2,$iv2 // the third block
+ veor $dat2,$dat2,$iv2
+ cmp $len,#32
+ b.lo .Lxts_outer_enc_tail
+
+ // The iv for fourth block
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr#31
+ eor $ivl,$tmpmx,$ivl,lsl#1
+ fmov $ivd30,$ivl
+ fmov $ivd31,$ivh
+
+ vld1.8 {$dat3},[$inp],#16
+ // The iv for fifth block
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr#31
+ eor $ivl,$tmpmx,$ivl,lsl#1
+ fmov $ivd40,$ivl
+ fmov $ivd41,$ivh
+
+ vld1.8 {$dat4},[$inp],#16
+ veor $dat3,$dat3,$iv3 // the fourth block
+ veor $dat4,$dat4,$iv4
+ sub $len,$len,#32 // bias
+ mov $rounds,$rounds0
+ b .Loop5x_xts_enc
+
+.align 4
+.Loop5x_xts_enc:
+ aese $dat0,q8
+ aesmc $dat0,$dat0
+ aese $dat1,q8
+ aesmc $dat1,$dat1
+ aese $dat2,q8
+ aesmc $dat2,$dat2
+ aese $dat3,q8
+ aesmc $dat3,$dat3
+ aese $dat4,q8
+ aesmc $dat4,$dat4
+ vld1.32 {q8},[$key_],#16
+ subs $rounds,$rounds,#2
+ aese $dat0,q9
+ aesmc $dat0,$dat0
+ aese $dat1,q9
+ aesmc $dat1,$dat1
+ aese $dat2,q9
+ aesmc $dat2,$dat2
+ aese $dat3,q9
+ aesmc $dat3,$dat3
+ aese $dat4,q9
+ aesmc $dat4,$dat4
+ vld1.32 {q9},[$key_],#16
+ b.gt .Loop5x_xts_enc
+
+ aese $dat0,q8
+ aesmc $dat0,$dat0
+ aese $dat1,q8
+ aesmc $dat1,$dat1
+ aese $dat2,q8
+ aesmc $dat2,$dat2
+ aese $dat3,q8
+ aesmc $dat3,$dat3
+ aese $dat4,q8
+ aesmc $dat4,$dat4
+ subs $len,$len,#0x50 // because .Lxts_enc_tail4x
+
+ aese $dat0,q9
+ aesmc $dat0,$dat0
+ aese $dat1,q9
+ aesmc $dat1,$dat1
+ aese $dat2,q9
+ aesmc $dat2,$dat2
+ aese $dat3,q9
+ aesmc $dat3,$dat3
+ aese $dat4,q9
+ aesmc $dat4,$dat4
+ csel $xoffset,xzr,$len,gt // borrow x6, w6, "gt" is not typo
+ mov $key_,$key1
+
+ aese $dat0,q10
+ aesmc $dat0,$dat0
+ aese $dat1,q10
+ aesmc $dat1,$dat1
+ aese $dat2,q10
+ aesmc $dat2,$dat2
+ aese $dat3,q10
+ aesmc $dat3,$dat3
+ aese $dat4,q10
+ aesmc $dat4,$dat4
+ add $inp,$inp,$xoffset // x0 is adjusted in such way that
+ // at exit from the loop v1.16b-v26.16b
+ // are loaded with last "words"
+ add $xoffset,$len,#0x60 // because .Lxts_enc_tail4x
+
+ aese $dat0,q11
+ aesmc $dat0,$dat0
+ aese $dat1,q11
+ aesmc $dat1,$dat1
+ aese $dat2,q11
+ aesmc $dat2,$dat2
+ aese $dat3,q11
+ aesmc $dat3,$dat3
+ aese $dat4,q11
+ aesmc $dat4,$dat4
+
+ aese $dat0,q12
+ aesmc $dat0,$dat0
+ aese $dat1,q12
+ aesmc $dat1,$dat1
+ aese $dat2,q12
+ aesmc $dat2,$dat2
+ aese $dat3,q12
+ aesmc $dat3,$dat3
+ aese $dat4,q12
+ aesmc $dat4,$dat4
+
+ aese $dat0,q13
+ aesmc $dat0,$dat0
+ aese $dat1,q13
+ aesmc $dat1,$dat1
+ aese $dat2,q13
+ aesmc $dat2,$dat2
+ aese $dat3,q13
+ aesmc $dat3,$dat3
+ aese $dat4,q13
+ aesmc $dat4,$dat4
+
+ aese $dat0,q14
+ aesmc $dat0,$dat0
+ aese $dat1,q14
+ aesmc $dat1,$dat1
+ aese $dat2,q14
+ aesmc $dat2,$dat2
+ aese $dat3,q14
+ aesmc $dat3,$dat3
+ aese $dat4,q14
+ aesmc $dat4,$dat4
+
+ veor $tmp0,$rndlast,$iv0
+ aese $dat0,q15
+ // The iv for first block of one iteration
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr#31
+ eor $ivl,$tmpmx,$ivl,lsl#1
+ fmov $ivd00,$ivl
+ fmov $ivd01,$ivh
+ veor $tmp1,$rndlast,$iv1
+ vld1.8 {$in0},[$inp],#16
+ aese $dat1,q15
+ // The iv for second block
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr#31
+ eor $ivl,$tmpmx,$ivl,lsl#1
+ fmov $ivd10,$ivl
+ fmov $ivd11,$ivh
+ veor $tmp2,$rndlast,$iv2
+ vld1.8 {$in1},[$inp],#16
+ aese $dat2,q15
+ // The iv for third block
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr#31
+ eor $ivl,$tmpmx,$ivl,lsl#1
+ fmov $ivd20,$ivl
+ fmov $ivd21,$ivh
+ veor $tmp3,$rndlast,$iv3
+ vld1.8 {$in2},[$inp],#16
+ aese $dat3,q15
+ // The iv for fourth block
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr#31
+ eor $ivl,$tmpmx,$ivl,lsl#1
+ fmov $ivd30,$ivl
+ fmov $ivd31,$ivh
+ veor $tmp4,$rndlast,$iv4
+ vld1.8 {$in3},[$inp],#16
+ aese $dat4,q15
+
+ // The iv for fifth block
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr #31
+ eor $ivl,$tmpmx,$ivl,lsl #1
+ fmov $ivd40,$ivl
+ fmov $ivd41,$ivh
+
+ vld1.8 {$in4},[$inp],#16
+ cbz $xoffset,.Lxts_enc_tail4x
+ vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
+ veor $tmp0,$tmp0,$dat0
+ veor $dat0,$in0,$iv0
+ veor $tmp1,$tmp1,$dat1
+ veor $dat1,$in1,$iv1
+ veor $tmp2,$tmp2,$dat2
+ veor $dat2,$in2,$iv2
+ veor $tmp3,$tmp3,$dat3
+ veor $dat3,$in3,$iv3
+ veor $tmp4,$tmp4,$dat4
+ vst1.8 {$tmp0},[$out],#16
+ veor $dat4,$in4,$iv4
+ vst1.8 {$tmp1},[$out],#16
+ mov $rounds,$rounds0
+ vst1.8 {$tmp2},[$out],#16
+ vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
+ vst1.8 {$tmp3},[$out],#16
+ vst1.8 {$tmp4},[$out],#16
+ b.hs .Loop5x_xts_enc
+
+
+ // If left 4 blocks, borrow the five block's processing.
+ cmn $len,#0x10
+ b.ne .Loop5x_enc_after
+ vorr $iv4,$iv3,$iv3
+ vorr $iv3,$iv2,$iv2
+ vorr $iv2,$iv1,$iv1
+ vorr $iv1,$iv0,$iv0
+ fmov $ivl,$ivd40
+ fmov $ivh,$ivd41
+ veor $dat0,$iv0,$in0
+ veor $dat1,$iv1,$in1
+ veor $dat2,$in2,$iv2
+ veor $dat3,$in3,$iv3
+ veor $dat4,$in4,$iv4
+ b.eq .Loop5x_xts_enc
+
+.Loop5x_enc_after:
+ add $len,$len,#0x50
+ cbz $len,.Lxts_enc_done
+
+ add $rounds,$rounds0,#2
+ subs $len,$len,#0x30
+ b.lo .Lxts_inner_enc_tail
+
+ veor $dat0,$iv0,$in2
+ veor $dat1,$iv1,$in3
+ veor $dat2,$in4,$iv2
+ b .Lxts_outer_enc_tail
+
+.align 4
+.Lxts_enc_tail4x:
+ add $inp,$inp,#16
+ veor $tmp1,$dat1,$tmp1
+ vst1.8 {$tmp1},[$out],#16
+ veor $tmp2,$dat2,$tmp2
+ vst1.8 {$tmp2},[$out],#16
+ veor $tmp3,$dat3,$tmp3
+ veor $tmp4,$dat4,$tmp4
+ vst1.8 {$tmp3-$tmp4},[$out],#32
+
+ b .Lxts_enc_done
+.align 4
+.Lxts_outer_enc_tail:
+ aese $dat0,q8
+ aesmc $dat0,$dat0
+ aese $dat1,q8
+ aesmc $dat1,$dat1
+ aese $dat2,q8
+ aesmc $dat2,$dat2
+ vld1.32 {q8},[$key_],#16
+ subs $rounds,$rounds,#2
+ aese $dat0,q9
+ aesmc $dat0,$dat0
+ aese $dat1,q9
+ aesmc $dat1,$dat1
+ aese $dat2,q9
+ aesmc $dat2,$dat2
+ vld1.32 {q9},[$key_],#16
+ b.gt .Lxts_outer_enc_tail
+
+ aese $dat0,q8
+ aesmc $dat0,$dat0
+ aese $dat1,q8
+ aesmc $dat1,$dat1
+ aese $dat2,q8
+ aesmc $dat2,$dat2
+ veor $tmp0,$iv0,$rndlast
+ subs $len,$len,#0x30
+ // The iv for first block
+ fmov $ivl,$ivd20
+ fmov $ivh,$ivd21
+ //mov $constnum,#0x87
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr#31
+ eor $ivl,$tmpmx,$ivl,lsl#1
+ fmov $ivd00,$ivl
+ fmov $ivd01,$ivh
+ veor $tmp1,$iv1,$rndlast
+ csel $xoffset,$len,$xoffset,lo // x6, w6, is zero at this point
+ aese $dat0,q9
+ aesmc $dat0,$dat0
+ aese $dat1,q9
+ aesmc $dat1,$dat1
+ aese $dat2,q9
+ aesmc $dat2,$dat2
+ veor $tmp2,$iv2,$rndlast
+
+ add $xoffset,$xoffset,#0x20
+ add $inp,$inp,$xoffset
+ mov $key_,$key1
+
+ aese $dat0,q12
+ aesmc $dat0,$dat0
+ aese $dat1,q12
+ aesmc $dat1,$dat1
+ aese $dat2,q12
+ aesmc $dat2,$dat2
+ aese $dat0,q13
+ aesmc $dat0,$dat0
+ aese $dat1,q13
+ aesmc $dat1,$dat1
+ aese $dat2,q13
+ aesmc $dat2,$dat2
+ aese $dat0,q14
+ aesmc $dat0,$dat0
+ aese $dat1,q14
+ aesmc $dat1,$dat1
+ aese $dat2,q14
+ aesmc $dat2,$dat2
+ aese $dat0,q15
+ aese $dat1,q15
+ aese $dat2,q15
+ vld1.8 {$in2},[$inp],#16
+ add $rounds,$rounds0,#2
+ vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
+ veor $tmp0,$tmp0,$dat0
+ veor $tmp1,$tmp1,$dat1
+ veor $dat2,$dat2,$tmp2
+ vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
+ vst1.8 {$tmp0},[$out],#16
+ vst1.8 {$tmp1},[$out],#16
+ vst1.8 {$dat2},[$out],#16
+ cmn $len,#0x30
+ b.eq .Lxts_enc_done
+.Lxts_encxor_one:
+ vorr $in3,$in1,$in1
+ vorr $in4,$in2,$in2
+ nop
+
+.Lxts_inner_enc_tail:
+ cmn $len,#0x10
+ veor $dat1,$in3,$iv0
+ veor $dat2,$in4,$iv1
+ b.eq .Lxts_enc_tail_loop
+ veor $dat2,$in4,$iv0
+.Lxts_enc_tail_loop:
+ aese $dat1,q8
+ aesmc $dat1,$dat1
+ aese $dat2,q8
+ aesmc $dat2,$dat2
+ vld1.32 {q8},[$key_],#16
+ subs $rounds,$rounds,#2
+ aese $dat1,q9
+ aesmc $dat1,$dat1
+ aese $dat2,q9
+ aesmc $dat2,$dat2
+ vld1.32 {q9},[$key_],#16
+ b.gt .Lxts_enc_tail_loop
+
+ aese $dat1,q8
+ aesmc $dat1,$dat1
+ aese $dat2,q8
+ aesmc $dat2,$dat2
+ aese $dat1,q9
+ aesmc $dat1,$dat1
+ aese $dat2,q9
+ aesmc $dat2,$dat2
+ aese $dat1,q12
+ aesmc $dat1,$dat1
+ aese $dat2,q12
+ aesmc $dat2,$dat2
+ cmn $len,#0x20
+ aese $dat1,q13
+ aesmc $dat1,$dat1
+ aese $dat2,q13
+ aesmc $dat2,$dat2
+ veor $tmp1,$iv0,$rndlast
+ aese $dat1,q14
+ aesmc $dat1,$dat1
+ aese $dat2,q14
+ aesmc $dat2,$dat2
+ veor $tmp2,$iv1,$rndlast
+ aese $dat1,q15
+ aese $dat2,q15
+ b.eq .Lxts_enc_one
+ veor $tmp1,$tmp1,$dat1
+ vst1.8 {$tmp1},[$out],#16
+ veor $tmp2,$tmp2,$dat2
+ vorr $iv0,$iv1,$iv1
+ vst1.8 {$tmp2},[$out],#16
+ fmov $ivl,$ivd10
+ fmov $ivh,$ivd11
+ mov $constnum,#0x87
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr #31
+ eor $ivl,$tmpmx,$ivl,lsl #1
+ fmov $ivd00,$ivl
+ fmov $ivd01,$ivh
+ b .Lxts_enc_done
+
+.Lxts_enc_one:
+ veor $tmp1,$tmp1,$dat2
+ vorr $iv0,$iv0,$iv0
+ vst1.8 {$tmp1},[$out],#16
+ fmov $ivl,$ivd00
+ fmov $ivh,$ivd01
+ mov $constnum,#0x87
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr #31
+ eor $ivl,$tmpmx,$ivl,lsl #1
+ fmov $ivd00,$ivl
+ fmov $ivd01,$ivh
+ b .Lxts_enc_done
+.align 5
+.Lxts_enc_done:
+ // Process the tail block with cipher stealing.
+ tst $tailcnt,#0xf
+ b.eq .Lxts_abort
+
+ mov $tmpinp,$inp
+ mov $tmpoutp,$out
+ sub $out,$out,#16
+.composite_enc_loop:
+ subs $tailcnt,$tailcnt,#1
+ ldrb $l2outp,[$out,$tailcnt]
+ ldrb $loutp,[$tmpinp,$tailcnt]
+ strb $l2outp,[$tmpoutp,$tailcnt]
+ strb $loutp,[$out,$tailcnt]
+ b.gt .composite_enc_loop
+.Lxts_enc_load_done:
+ vld1.8 {$tmpin},[$out]
+ veor $tmpin,$tmpin,$iv0
+
+ // Encrypt the composite block to get the last second encrypted text block
+ ldr $rounds,[$key1,#240] // load key schedule...
+ vld1.8 {$dat},[$key1],#16
+ sub $rounds,$rounds,#2
+ vld1.8 {$dat1},[$key1],#16 // load key schedule...
+.Loop_final_enc:
+ aese $tmpin,$dat0
+ aesmc $tmpin,$tmpin
+ vld1.32 {$dat0},[$key1],#16
+ subs $rounds,$rounds,#2
+ aese $tmpin,$dat1
+ aesmc $tmpin,$tmpin
+ vld1.32 {$dat1},[$key1],#16
+ b.gt .Loop_final_enc
+
+ aese $tmpin,$dat0
+ aesmc $tmpin,$tmpin
+ vld1.32 {$dat0},[$key1]
+ aese $tmpin,$dat1
+ veor $tmpin,$tmpin,$dat0
+ veor $tmpin,$tmpin,$iv0
+ vst1.8 {$tmpin},[$out]
+
+.Lxts_abort:
+ ldp $tailcnt,$midnumx,[sp,#48]
+ ldp $ivd10,$ivd20,[sp,#32]
+ ldp $ivd30,$ivd40,[sp,#16]
+ ldp $constnumx,$tmpinp,[sp],#64
+.Lxts_enc_final_abort:
+ ret
+.size ${prefix}_xts_encrypt,.-${prefix}_xts_encrypt
+___
+
+}}}
+{{{
+my ($inp,$out,$len,$key1,$key2,$ivp)=map("x$_",(0..5));
+my ($rounds0,$rounds,$key_,$step,$ivl,$ivh)=("w5","w6","x7","x8","x9","x10");
+my ($tmpoutp,$loutp,$l2outp,$tmpinp)=("x13","w14","w15","x20");
+my ($tailcnt,$midnum,$midnumx,$constnum,$constnumx)=("x21","w22","x22","w19","x19");
+my ($xoffset,$tmpmx,$tmpmw)=("x6","x11","w11");
+my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$tmp2,$rndlast)=map("q$_",(0..7));
+my ($iv0,$iv1,$iv2,$iv3,$iv4,$tmpin)=("v6.16b","v8.16b","v9.16b","v10.16b","v11.16b","v26.16b");
+my ($ivd00,$ivd01,$ivd20,$ivd21)=("d6","v6.d[1]","d9","v9.d[1]");
+my ($ivd10,$ivd11,$ivd30,$ivd31,$ivd40,$ivd41)=("d8","v8.d[1]","d10","v10.d[1]","d11","v11.d[1]");
+
+my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1);
+
+# q7 last round key
+# q10-q15, q7 Last 7 round keys
+# q8-q9 preloaded round keys except last 7 keys for big size
+# q20, q21, q8-q9 preloaded round keys except last 7 keys for only 16 byte
+
+{
+my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9));
+
+my ($dat3,$in3,$tmp3); # used only in 64-bit mode
+my ($dat4,$in4,$tmp4);
+if ($flavour =~ /64/) {
+ ($dat2,$dat3,$dat4,$in2,$in3,$in4,$tmp3,$tmp4)=map("q$_",(16..23));
+}
+
+$code.=<<___ if ($flavour =~ /64/);
+.globl ${prefix}_xts_decrypt
+.type ${prefix}_xts_decrypt,%function
+.align 5
+${prefix}_xts_decrypt:
+___
+$code.=<<___ if ($flavour =~ /64/);
+ cmp $len,#16
+ // Original input data size bigger than 16, jump to big size processing.
+ b.ne .Lxts_dec_big_size
+ // Encrypt the iv with key2, as the first XEX iv.
+ ldr $rounds,[$key2,#240]
+ vld1.8 {$dat},[$key2],#16
+ vld1.8 {$iv0},[$ivp]
+ sub $rounds,$rounds,#2
+ vld1.8 {$dat1},[$key2],#16
+
+.Loop_dec_small_iv_enc:
+ aese $iv0,$dat
+ aesmc $iv0,$iv0
+ vld1.32 {$dat},[$key2],#16
+ subs $rounds,$rounds,#2
+ aese $iv0,$dat1
+ aesmc $iv0,$iv0
+ vld1.32 {$dat1},[$key2],#16
+ b.gt .Loop_dec_small_iv_enc
+
+ aese $iv0,$dat
+ aesmc $iv0,$iv0
+ vld1.32 {$dat},[$key2]
+ aese $iv0,$dat1
+ veor $iv0,$iv0,$dat
+
+ vld1.8 {$dat0},[$inp]
+ veor $dat0,$iv0,$dat0
+
+ ldr $rounds,[$key1,#240]
+ vld1.32 {q20-q21},[$key1],#32 // load key schedule...
+
+ aesd $dat0,q20
+ aesimc $dat0,$dat0
+ vld1.32 {q8-q9},[$key1],#32 // load key schedule...
+ aesd $dat0,q21
+ aesimc $dat0,$dat0
+ subs $rounds,$rounds,#10 // bias
+ b.eq .Lxts_128_dec
+.Lxts_dec_round_loop:
+ aesd $dat0,q8
+ aesimc $dat0,$dat0
+ vld1.32 {q8},[$key1],#16 // load key schedule...
+ aesd $dat0,q9
+ aesimc $dat0,$dat0
+ vld1.32 {q9},[$key1],#16 // load key schedule...
+ subs $rounds,$rounds,#2 // bias
+ b.gt .Lxts_dec_round_loop
+.Lxts_128_dec:
+ vld1.32 {q10-q11},[$key1],#32 // load key schedule...
+ aesd $dat0,q8
+ aesimc $dat0,$dat0
+ aesd $dat0,q9
+ aesimc $dat0,$dat0
+ vld1.32 {q12-q13},[$key1],#32 // load key schedule...
+ aesd $dat0,q10
+ aesimc $dat0,$dat0
+ aesd $dat0,q11
+ aesimc $dat0,$dat0
+ vld1.32 {q14-q15},[$key1],#32 // load key schedule...
+ aesd $dat0,q12
+ aesimc $dat0,$dat0
+ aesd $dat0,q13
+ aesimc $dat0,$dat0
+ vld1.32 {$rndlast},[$key1]
+ aesd $dat0,q14
+ aesimc $dat0,$dat0
+ aesd $dat0,q15
+ veor $dat0,$dat0,$rndlast
+ veor $dat0,$iv0,$dat0
+ vst1.8 {$dat0},[$out]
+ b .Lxts_dec_final_abort
+.Lxts_dec_big_size:
+___
+$code.=<<___ if ($flavour =~ /64/);
+ stp $constnumx,$tmpinp,[sp,#-64]!
+ stp $tailcnt,$midnumx,[sp,#48]
+ stp $ivd10,$ivd20,[sp,#32]
+ stp $ivd30,$ivd40,[sp,#16]
+
+ and $tailcnt,$len,#0xf
+ and $len,$len,#-16
+ subs $len,$len,#16
+ mov $step,#16
+ b.lo .Lxts_dec_abort
+
+ // Encrypt the iv with key2, as the first XEX iv
+ ldr $rounds,[$key2,#240]
+ vld1.8 {$dat},[$key2],#16
+ vld1.8 {$iv0},[$ivp]
+ sub $rounds,$rounds,#2
+ vld1.8 {$dat1},[$key2],#16
+
+.Loop_dec_iv_enc:
+ aese $iv0,$dat
+ aesmc $iv0,$iv0
+ vld1.32 {$dat},[$key2],#16
+ subs $rounds,$rounds,#2
+ aese $iv0,$dat1
+ aesmc $iv0,$iv0
+ vld1.32 {$dat1},[$key2],#16
+ b.gt .Loop_dec_iv_enc
+
+ aese $iv0,$dat
+ aesmc $iv0,$iv0
+ vld1.32 {$dat},[$key2]
+ aese $iv0,$dat1
+ veor $iv0,$iv0,$dat
+
+ // The iv for second block
+ // $ivl- iv(low), $ivh - iv(high)
+ // the five ivs stored into, $iv0,$iv1,$iv2,$iv3,$iv4
+ fmov $ivl,$ivd00
+ fmov $ivh,$ivd01
+ mov $constnum,#0x87
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr #31
+ eor $ivl,$tmpmx,$ivl,lsl #1
+ fmov $ivd10,$ivl
+ fmov $ivd11,$ivh
+
+ ldr $rounds0,[$key1,#240] // load rounds number
+
+ // The iv for third block
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr #31
+ eor $ivl,$tmpmx,$ivl,lsl #1
+ fmov $ivd20,$ivl
+ fmov $ivd21,$ivh
+
+ vld1.32 {q8-q9},[$key1] // load key schedule...
+ sub $rounds0,$rounds0,#6
+ add $key_,$key1,$ivp,lsl#4 // pointer to last 7 round keys
+ sub $rounds0,$rounds0,#2
+ vld1.32 {q10-q11},[$key_],#32 // load key schedule...
+ vld1.32 {q12-q13},[$key_],#32
+ vld1.32 {q14-q15},[$key_],#32
+ vld1.32 {$rndlast},[$key_]
+
+ // The iv for fourth block
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr #31
+ eor $ivl,$tmpmx,$ivl,lsl #1
+ fmov $ivd30,$ivl
+ fmov $ivd31,$ivh
+
+ add $key_,$key1,#32
+ mov $rounds,$rounds0
+ b .Lxts_dec
+
+ // Decryption
+.align 5
+.Lxts_dec:
+ tst $tailcnt,#0xf
+ b.eq .Lxts_dec_begin
+ subs $len,$len,#16
+ csel $step,xzr,$step,eq
+ vld1.8 {$dat},[$inp],#16
+ b.lo .Lxts_done
+ sub $inp,$inp,#16
+.Lxts_dec_begin:
+ vld1.8 {$dat},[$inp],$step
+ subs $len,$len,#32 // bias
+ add $rounds,$rounds0,#2
+ vorr $in1,$dat,$dat
+ vorr $dat1,$dat,$dat
+ vorr $in3,$dat,$dat
+ vld1.8 {$dat2},[$inp],#16
+ vorr $in2,$dat2,$dat2
+ vorr $in4,$dat2,$dat2
+ b.lo .Lxts_inner_dec_tail
+ veor $dat,$dat,$iv0 // before decryt, xor with iv
+ veor $dat2,$dat2,$iv1
+
+ vorr $dat1,$dat2,$dat2
+ vld1.8 {$dat2},[$inp],#16
+ vorr $in0,$dat,$dat
+ vorr $in1,$dat1,$dat1
+ veor $in2,$dat2,$iv2 // third block xox with third iv
+ veor $dat2,$dat2,$iv2
+ cmp $len,#32
+ b.lo .Lxts_outer_dec_tail
+
+ vld1.8 {$dat3},[$inp],#16
+
+ // The iv for fifth block
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr #31
+ eor $ivl,$tmpmx,$ivl,lsl #1
+ fmov $ivd40,$ivl
+ fmov $ivd41,$ivh
+
+ vld1.8 {$dat4},[$inp],#16
+ veor $dat3,$dat3,$iv3 // the fourth block
+ veor $dat4,$dat4,$iv4
+ sub $len,$len,#32 // bias
+ mov $rounds,$rounds0
+ b .Loop5x_xts_dec
+
+.align 4
+.Loop5x_xts_dec:
+ aesd $dat0,q8
+ aesimc $dat0,$dat0
+ aesd $dat1,q8
+ aesimc $dat1,$dat1
+ aesd $dat2,q8
+ aesimc $dat2,$dat2
+ aesd $dat3,q8
+ aesimc $dat3,$dat3
+ aesd $dat4,q8
+ aesimc $dat4,$dat4
+ vld1.32 {q8},[$key_],#16 // load key schedule...
+ subs $rounds,$rounds,#2
+ aesd $dat0,q9
+ aesimc $dat0,$dat0
+ aesd $dat1,q9
+ aesimc $dat1,$dat1
+ aesd $dat2,q9
+ aesimc $dat2,$dat2
+ aesd $dat3,q9
+ aesimc $dat3,$dat3
+ aesd $dat4,q9
+ aesimc $dat4,$dat4
+ vld1.32 {q9},[$key_],#16 // load key schedule...
+ b.gt .Loop5x_xts_dec
+
+ aesd $dat0,q8
+ aesimc $dat0,$dat0
+ aesd $dat1,q8
+ aesimc $dat1,$dat1
+ aesd $dat2,q8
+ aesimc $dat2,$dat2
+ aesd $dat3,q8
+ aesimc $dat3,$dat3
+ aesd $dat4,q8
+ aesimc $dat4,$dat4
+ subs $len,$len,#0x50 // because .Lxts_dec_tail4x
+
+ aesd $dat0,q9
+ aesimc $dat0,$dat
+ aesd $dat1,q9
+ aesimc $dat1,$dat1
+ aesd $dat2,q9
+ aesimc $dat2,$dat2
+ aesd $dat3,q9
+ aesimc $dat3,$dat3
+ aesd $dat4,q9
+ aesimc $dat4,$dat4
+ csel $xoffset,xzr,$len,gt // borrow x6, w6, "gt" is not typo
+ mov $key_,$key1
+
+ aesd $dat0,q10
+ aesimc $dat0,$dat0
+ aesd $dat1,q10
+ aesimc $dat1,$dat1
+ aesd $dat2,q10
+ aesimc $dat2,$dat2
+ aesd $dat3,q10
+ aesimc $dat3,$dat3
+ aesd $dat4,q10
+ aesimc $dat4,$dat4
+ add $inp,$inp,$xoffset // x0 is adjusted in such way that
+ // at exit from the loop v1.16b-v26.16b
+ // are loaded with last "words"
+ add $xoffset,$len,#0x60 // because .Lxts_dec_tail4x
+
+ aesd $dat0,q11
+ aesimc $dat0,$dat0
+ aesd $dat1,q11
+ aesimc $dat1,$dat1
+ aesd $dat2,q11
+ aesimc $dat2,$dat2
+ aesd $dat3,q11
+ aesimc $dat3,$dat3
+ aesd $dat4,q11
+ aesimc $dat4,$dat4
+
+ aesd $dat0,q12
+ aesimc $dat0,$dat0
+ aesd $dat1,q12
+ aesimc $dat1,$dat1
+ aesd $dat2,q12
+ aesimc $dat2,$dat2
+ aesd $dat3,q12
+ aesimc $dat3,$dat3
+ aesd $dat4,q12
+ aesimc $dat4,$dat4
+
+ aesd $dat0,q13
+ aesimc $dat0,$dat0
+ aesd $dat1,q13
+ aesimc $dat1,$dat1
+ aesd $dat2,q13
+ aesimc $dat2,$dat2
+ aesd $dat3,q13
+ aesimc $dat3,$dat3
+ aesd $dat4,q13
+ aesimc $dat4,$dat4
+
+ aesd $dat0,q14
+ aesimc $dat0,$dat0
+ aesd $dat1,q14
+ aesimc $dat1,$dat1
+ aesd $dat2,q14
+ aesimc $dat2,$dat2
+ aesd $dat3,q14
+ aesimc $dat3,$dat3
+ aesd $dat4,q14
+ aesimc $dat4,$dat4
+
+ veor $tmp0,$rndlast,$iv0
+ aesd $dat0,q15
+ // The iv for first block of next iteration.
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr #31
+ eor $ivl,$tmpmx,$ivl,lsl #1
+ fmov $ivd00,$ivl
+ fmov $ivd01,$ivh
+ veor $tmp1,$rndlast,$iv1
+ vld1.8 {$in0},[$inp],#16
+ aesd $dat1,q15
+ // The iv for second block
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr #31
+ eor $ivl,$tmpmx,$ivl,lsl #1
+ fmov $ivd10,$ivl
+ fmov $ivd11,$ivh
+ veor $tmp2,$rndlast,$iv2
+ vld1.8 {$in1},[$inp],#16
+ aesd $dat2,q15
+ // The iv for third block
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr #31
+ eor $ivl,$tmpmx,$ivl,lsl #1
+ fmov $ivd20,$ivl
+ fmov $ivd21,$ivh
+ veor $tmp3,$rndlast,$iv3
+ vld1.8 {$in2},[$inp],#16
+ aesd $dat3,q15
+ // The iv for fourth block
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr #31
+ eor $ivl,$tmpmx,$ivl,lsl #1
+ fmov $ivd30,$ivl
+ fmov $ivd31,$ivh
+ veor $tmp4,$rndlast,$iv4
+ vld1.8 {$in3},[$inp],#16
+ aesd $dat4,q15
+
+ // The iv for fifth block
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr #31
+ eor $ivl,$tmpmx,$ivl,lsl #1
+ fmov $ivd40,$ivl
+ fmov $ivd41,$ivh
+
+ vld1.8 {$in4},[$inp],#16
+ cbz $xoffset,.Lxts_dec_tail4x
+ vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
+ veor $tmp0,$tmp0,$dat0
+ veor $dat0,$in0,$iv0
+ veor $tmp1,$tmp1,$dat1
+ veor $dat1,$in1,$iv1
+ veor $tmp2,$tmp2,$dat2
+ veor $dat2,$in2,$iv2
+ veor $tmp3,$tmp3,$dat3
+ veor $dat3,$in3,$iv3
+ veor $tmp4,$tmp4,$dat4
+ vst1.8 {$tmp0},[$out],#16
+ veor $dat4,$in4,$iv4
+ vst1.8 {$tmp1},[$out],#16
+ mov $rounds,$rounds0
+ vst1.8 {$tmp2},[$out],#16
+ vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
+ vst1.8 {$tmp3},[$out],#16
+ vst1.8 {$tmp4},[$out],#16
+ b.hs .Loop5x_xts_dec
+
+ cmn $len,#0x10
+ b.ne .Loop5x_dec_after
+ // If x2($len) equal to -0x10, the left blocks is 4.
+ // After specially processing, utilize the five blocks processing again.
+ // It will use the following IVs: $iv0,$iv0,$iv1,$iv2,$iv3.
+ vorr $iv4,$iv3,$iv3
+ vorr $iv3,$iv2,$iv2
+ vorr $iv2,$iv1,$iv1
+ vorr $iv1,$iv0,$iv0
+ fmov $ivl,$ivd40
+ fmov $ivh,$ivd41
+ veor $dat0,$iv0,$in0
+ veor $dat1,$iv1,$in1
+ veor $dat2,$in2,$iv2
+ veor $dat3,$in3,$iv3
+ veor $dat4,$in4,$iv4
+ b.eq .Loop5x_xts_dec
+
+.Loop5x_dec_after:
+ add $len,$len,#0x50
+ cbz $len,.Lxts_done
+
+ add $rounds,$rounds0,#2
+ subs $len,$len,#0x30
+ b.lo .Lxts_inner_dec_tail
+
+ veor $dat0,$iv0,$in2
+ veor $dat1,$iv1,$in3
+ veor $dat2,$in4,$iv2
+ b .Lxts_outer_dec_tail
+
+.align 4
+.Lxts_dec_tail4x:
+ add $inp,$inp,#16
+ vld1.32 {$dat0},[$inp],#16
+ veor $tmp1,$dat1,$tmp0
+ vst1.8 {$tmp1},[$out],#16
+ veor $tmp2,$dat2,$tmp2
+ vst1.8 {$tmp2},[$out],#16
+ veor $tmp3,$dat3,$tmp3
+ veor $tmp4,$dat4,$tmp4
+ vst1.8 {$tmp3-$tmp4},[$out],#32
+
+ b .Lxts_done
+.align 4
+.Lxts_outer_dec_tail:
+ aesd $dat0,q8
+ aesimc $dat0,$dat0
+ aesd $dat1,q8
+ aesimc $dat1,$dat1
+ aesd $dat2,q8
+ aesimc $dat2,$dat2
+ vld1.32 {q8},[$key_],#16
+ subs $rounds,$rounds,#2
+ aesd $dat0,q9
+ aesimc $dat0,$dat0
+ aesd $dat1,q9
+ aesimc $dat1,$dat1
+ aesd $dat2,q9
+ aesimc $dat2,$dat2
+ vld1.32 {q9},[$key_],#16
+ b.gt .Lxts_outer_dec_tail
+
+ aesd $dat0,q8
+ aesimc $dat0,$dat0
+ aesd $dat1,q8
+ aesimc $dat1,$dat1
+ aesd $dat2,q8
+ aesimc $dat2,$dat2
+ veor $tmp0,$iv0,$rndlast
+ subs $len,$len,#0x30
+ // The iv for first block
+ fmov $ivl,$ivd20
+ fmov $ivh,$ivd21
+ mov $constnum,#0x87
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr #31
+ eor $ivl,$tmpmx,$ivl,lsl #1
+ fmov $ivd00,$ivl
+ fmov $ivd01,$ivh
+ veor $tmp1,$iv1,$rndlast
+ csel $xoffset,$len,$xoffset,lo // x6, w6, is zero at this point
+ aesd $dat0,q9
+ aesimc $dat0,$dat0
+ aesd $dat1,q9
+ aesimc $dat1,$dat1
+ aesd $dat2,q9
+ aesimc $dat2,$dat2
+ veor $tmp2,$iv2,$rndlast
+ // The iv for second block
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr #31
+ eor $ivl,$tmpmx,$ivl,lsl #1
+ fmov $ivd10,$ivl
+ fmov $ivd11,$ivh
+
+ add $xoffset,$xoffset,#0x20
+ add $inp,$inp,$xoffset // $inp is adjusted to the last data
+
+ mov $key_,$key1
+
+ // The iv for third block
+ extr $midnumx,$ivh,$ivh,#32
+ extr $ivh,$ivh,$ivl,#63
+ and $tmpmw,$constnum,$midnum,asr #31
+ eor $ivl,$tmpmx,$ivl,lsl #1
+ fmov $ivd20,$ivl
+ fmov $ivd21,$ivh
+
+ aesd $dat0,q12
+ aesimc $dat0,$dat0
+ aesd $dat1,q12
+ aesimc $dat1,$dat1
+ aesd $dat2,q12
+ aesimc $dat2,$dat2
+ aesd $dat0,q13
+ aesimc $dat0,$dat0
+ aesd $dat1,q13
+ aesimc $dat1,$dat1
+ aesd $dat2,q13
+ aesimc $dat2,$dat2
+ aesd $dat0,q14
+ aesimc $dat0,$dat0
+ aesd $dat1,q14
+ aesimc $dat1,$dat1
+ aesd $dat2,q14
+ aesimc $dat2,$dat2
+ vld1.8 {$in2},[$inp],#16
+ aesd $dat0,q15
+ aesd $dat1,q15
+ aesd $dat2,q15
+ vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
+ add $rounds,$rounds0,#2
+ veor $tmp0,$tmp0,$dat0
+ veor $tmp1,$tmp1,$dat1
+ veor $dat2,$dat2,$tmp2
+ vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
+ vst1.8 {$tmp0},[$out],#16
+ vst1.8 {$tmp1},[$out],#16
+ vst1.8 {$dat2},[$out],#16
+
+ cmn $len,#0x30
+ add $len,$len,#0x30
+ b.eq .Lxts_done
+ sub $len,$len,#0x30
+ vorr $in3,$in1,$in1
+ vorr $in4,$in2,$in2
+ nop
+
+.Lxts_inner_dec_tail:
+ // $len == -0x10 means two blocks left.
+ cmn $len,#0x10
+ veor $dat1,$in3,$iv0
+ veor $dat2,$in4,$iv1
+ b.eq .Lxts_dec_tail_loop
+ veor $dat2,$in4,$iv0
+.Lxts_dec_tail_loop:
+ aesd $dat1,q8
+ aesimc $dat1,$dat1
+ aesd $dat2,q8
+ aesimc $dat2,$dat2
+ vld1.32 {q8},[$key_],#16
+ subs $rounds,$rounds,#2
+ aesd $dat1,q9
+ aesimc $dat1,$dat1
+ aesd $dat2,q9
+ aesimc $dat2,$dat2
+ vld1.32 {q9},[$key_],#16
+ b.gt .Lxts_dec_tail_loop
+
+ aesd $dat1,q8
+ aesimc $dat1,$dat1
+ aesd $dat2,q8
+ aesimc $dat2,$dat2
+ aesd $dat1,q9
+ aesimc $dat1,$dat1
+ aesd $dat2,q9
+ aesimc $dat2,$dat2
+ aesd $dat1,q12
+ aesimc $dat1,$dat1
+ aesd $dat2,q12
+ aesimc $dat2,$dat2
+ cmn $len,#0x20
+ aesd $dat1,q13
+ aesimc $dat1,$dat1
+ aesd $dat2,q13
+ aesimc $dat2,$dat2
+ veor $tmp1,$iv0,$rndlast
+ aesd $dat1,q14
+ aesimc $dat1,$dat1
+ aesd $dat2,q14
+ aesimc $dat2,$dat2
+ veor $tmp2,$iv1,$rndlast
+ aesd $dat1,q15
+ aesd $dat2,q15
+ b.eq .Lxts_dec_one
+ veor $tmp1,$tmp1,$dat1
+ veor $tmp2,$tmp2,$dat2
+ vorr $iv0,$iv2,$iv2
+ vorr $iv1,$iv3,$iv3
+ vst1.8 {$tmp1},[$out],#16
+ vst1.8 {$tmp2},[$out],#16
+ add $len,$len,#16
+ b .Lxts_done
+
+.Lxts_dec_one:
+ veor $tmp1,$tmp1,$dat2
+ vorr $iv0,$iv1,$iv1
+ vorr $iv1,$iv2,$iv2
+ vst1.8 {$tmp1},[$out],#16
+ add $len,$len,#32
+
+.Lxts_done:
+ tst $tailcnt,#0xf
+ b.eq .Lxts_dec_abort
+ // Processing the last two blocks with cipher stealing.
+ mov x7,x3
+ cbnz x2,.Lxts_dec_1st_done
+ vld1.32 {$dat0},[$inp],#16
+
+ // Decrypt the last secod block to get the last plain text block
+.Lxts_dec_1st_done:
+ eor $tmpin,$dat0,$iv1
+ ldr $rounds,[$key1,#240]
+ vld1.32 {$dat0},[$key1],#16
+ sub $rounds,$rounds,#2
+ vld1.32 {$dat1},[$key1],#16
+.Loop_final_2nd_dec:
+ aesd $tmpin,$dat0
+ aesimc $tmpin,$tmpin
+ vld1.32 {$dat0},[$key1],#16 // load key schedule...
+ subs $rounds,$rounds,#2
+ aesd $tmpin,$dat1
+ aesimc $tmpin,$tmpin
+ vld1.32 {$dat1},[$key1],#16 // load key schedule...
+ b.gt .Loop_final_2nd_dec
+
+ aesd $tmpin,$dat0
+ aesimc $tmpin,$tmpin
+ vld1.32 {$dat0},[$key1]
+ aesd $tmpin,$dat1
+ veor $tmpin,$tmpin,$dat0
+ veor $tmpin,$tmpin,$iv1
+ vst1.8 {$tmpin},[$out]
+
+ mov $tmpinp,$inp
+ add $tmpoutp,$out,#16
+
+ // Composite the tailcnt "16 byte not aligned block" into the last second plain blocks
+ // to get the last encrypted block.
+.composite_dec_loop:
+ subs $tailcnt,$tailcnt,#1
+ ldrb $l2outp,[$out,$tailcnt]
+ ldrb $loutp,[$tmpinp,$tailcnt]
+ strb $l2outp,[$tmpoutp,$tailcnt]
+ strb $loutp,[$out,$tailcnt]
+ b.gt .composite_dec_loop
+.Lxts_dec_load_done:
+ vld1.8 {$tmpin},[$out]
+ veor $tmpin,$tmpin,$iv0
+
+ // Decrypt the composite block to get the last second plain text block
+ ldr $rounds,[$key_,#240]
+ vld1.8 {$dat},[$key_],#16
+ sub $rounds,$rounds,#2
+ vld1.8 {$dat1},[$key_],#16
+.Loop_final_dec:
+ aesd $tmpin,$dat0
+ aesimc $tmpin,$tmpin
+ vld1.32 {$dat0},[$key_],#16 // load key schedule...
+ subs $rounds,$rounds,#2
+ aesd $tmpin,$dat1
+ aesimc $tmpin,$tmpin
+ vld1.32 {$dat1},[$key_],#16 // load key schedule...
+ b.gt .Loop_final_dec
+
+ aesd $tmpin,$dat0
+ aesimc $tmpin,$tmpin
+ vld1.32 {$dat0},[$key_]
+ aesd $tmpin,$dat1
+ veor $tmpin,$tmpin,$dat0
+ veor $tmpin,$tmpin,$iv0
+ vst1.8 {$tmpin},[$out]
+
+.Lxts_dec_abort:
+ ldp $tailcnt,$midnumx,[sp,#48]
+ ldp $ivd10,$ivd20,[sp,#32]
+ ldp $ivd30,$ivd40,[sp,#16]
+ ldp $constnumx,$tmpinp,[sp],#64
+
+.Lxts_dec_final_abort:
+ ret
+.size ${prefix}_xts_decrypt,.-${prefix}_xts_decrypt
+___
+}
+}}}
$code.=<<___;
#endif
___
@@ -1025,7 +3675,7 @@ if ($flavour =~ /64/) { ######## 64-bit code
# since ARMv7 instructions are always encoded little-endian.
# correct solution is to use .inst directive, but older
# assemblers don't implement it:-(
- sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s",
+ sprintf "INST(0x%02x,0x%02x,0x%02x,0x%02x)\t@ %s %s",
$word&0xff,($word>>8)&0xff,
($word>>16)&0xff,($word>>24)&0xff,
$mnemonic,$arg;
@@ -1066,14 +3716,17 @@ if ($flavour =~ /64/) { ######## 64-bit code
s/\],#[0-9]+/]!/o;
s/[v]?(aes\w+)\s+([qv].*)/unaes($1,$2)/geo or
- s/cclr\s+([^,]+),\s*([a-z]+)/mov$2 $1,#0/o or
+ s/cclr\s+([^,]+),\s*([a-z]+)/mov.$2 $1,#0/o or
s/vtbl\.8\s+(.*)/unvtbl($1)/geo or
s/vdup\.32\s+(.*)/unvdup32($1)/geo or
s/vmov\.32\s+(.*)/unvmov32($1)/geo or
s/^(\s+)b\./$1b/o or
- s/^(\s+)mov\./$1mov/o or
s/^(\s+)ret/$1bx\tlr/o;
+ if (s/^(\s+)mov\.([a-z]+)/$1mov$2/) {
+ print " it $2\n";
+ }
+
print $_,"\n";
}
}
diff --git a/crypto/aes/asm/bsaes-armv7.pl b/crypto/aes/asm/bsaes-armv7.pl
index 2b9f241ce8b0..9c5dd5839acb 100644
--- a/crypto/aes/asm/bsaes-armv7.pl
+++ b/crypto/aes/asm/bsaes-armv7.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -50,9 +50,10 @@
# April-August 2013
# Add CBC, CTR and XTS subroutines and adapt for kernel use; courtesy of Ard.
-$flavour = shift;
-if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour && $flavour ne "void") {
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -60,9 +61,10 @@ if ($flavour && $flavour ne "void") {
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
- open STDOUT,"| \"$^X\" $xlate $flavour $output";
+ open STDOUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
} else {
- open STDOUT,">$output";
+ $output and open STDOUT,">$output";
}
my ($inp,$out,$len,$key)=("r0","r1","r2","r3");
@@ -728,7 +730,6 @@ $code.=<<___;
.arch armv7-a
.fpu neon
-.text
.syntax unified @ ARMv7-capable assembler is expected to handle this
#if defined(__thumb2__) && !defined(__APPLE__)
.thumb
@@ -737,6 +738,8 @@ $code.=<<___;
# undef __thumb2__
#endif
+.text
+
.type _bsaes_decrypt8,%function
.align 4
_bsaes_decrypt8:
@@ -1116,18 +1119,18 @@ $code.=<<___;
.extern AES_cbc_encrypt
.extern AES_decrypt
-.global bsaes_cbc_encrypt
-.type bsaes_cbc_encrypt,%function
+.global ossl_bsaes_cbc_encrypt
+.type ossl_bsaes_cbc_encrypt,%function
.align 5
-bsaes_cbc_encrypt:
+ossl_bsaes_cbc_encrypt:
#ifndef __KERNEL__
cmp $len, #128
#ifndef __thumb__
blo AES_cbc_encrypt
#else
- bhs 1f
+ bhs .Lcbc_do_bsaes
b AES_cbc_encrypt
-1:
+.Lcbc_do_bsaes:
#endif
#endif
@@ -1381,7 +1384,7 @@ bsaes_cbc_encrypt:
vst1.8 {@XMM[15]}, [$ivp] @ return IV
VFP_ABI_POP
ldmia sp!, {r4-r10, pc}
-.size bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
+.size ossl_bsaes_cbc_encrypt,.-ossl_bsaes_cbc_encrypt
___
}
{
@@ -1391,10 +1394,10 @@ my $keysched = "sp";
$code.=<<___;
.extern AES_encrypt
-.global bsaes_ctr32_encrypt_blocks
-.type bsaes_ctr32_encrypt_blocks,%function
+.global ossl_bsaes_ctr32_encrypt_blocks
+.type ossl_bsaes_ctr32_encrypt_blocks,%function
.align 5
-bsaes_ctr32_encrypt_blocks:
+ossl_bsaes_ctr32_encrypt_blocks:
cmp $len, #8 @ use plain AES for
blo .Lctr_enc_short @ small sizes
@@ -1617,7 +1620,7 @@ bsaes_ctr32_encrypt_blocks:
vstmia sp!, {q0-q1}
ldmia sp!, {r4-r8, pc}
-.size bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
+.size ossl_bsaes_ctr32_encrypt_blocks,.-ossl_bsaes_ctr32_encrypt_blocks
___
}
{
@@ -1632,10 +1635,10 @@ my $twmask=@XMM[5];
my @T=@XMM[6..7];
$code.=<<___;
-.globl bsaes_xts_encrypt
-.type bsaes_xts_encrypt,%function
+.globl ossl_bsaes_xts_encrypt
+.type ossl_bsaes_xts_encrypt,%function
.align 4
-bsaes_xts_encrypt:
+ossl_bsaes_xts_encrypt:
mov ip, sp
stmdb sp!, {r4-r10, lr} @ 0x20
VFP_ABI_PUSH
@@ -2034,12 +2037,12 @@ $code.=<<___;
VFP_ABI_POP
ldmia sp!, {r4-r10, pc} @ return
-.size bsaes_xts_encrypt,.-bsaes_xts_encrypt
+.size ossl_bsaes_xts_encrypt,.-ossl_bsaes_xts_encrypt
-.globl bsaes_xts_decrypt
-.type bsaes_xts_decrypt,%function
+.globl ossl_bsaes_xts_decrypt
+.type ossl_bsaes_xts_decrypt,%function
.align 4
-bsaes_xts_decrypt:
+ossl_bsaes_xts_decrypt:
mov ip, sp
stmdb sp!, {r4-r10, lr} @ 0x20
VFP_ABI_PUSH
@@ -2469,7 +2472,7 @@ $code.=<<___;
VFP_ABI_POP
ldmia sp!, {r4-r10, pc} @ return
-.size bsaes_xts_decrypt,.-bsaes_xts_decrypt
+.size ossl_bsaes_xts_decrypt,.-ossl_bsaes_xts_decrypt
___
}
$code.=<<___;
diff --git a/crypto/aes/asm/bsaes-x86_64.pl b/crypto/aes/asm/bsaes-x86_64.pl
new file mode 100644
index 000000000000..6498cfe908c8
--- /dev/null
+++ b/crypto/aes/asm/bsaes-x86_64.pl
@@ -0,0 +1,3243 @@
+#! /usr/bin/env perl
+# Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+
+###################################################################
+### AES-128 [originally in CTR mode] ###
+### bitsliced implementation for Intel Core 2 processors ###
+### requires support of SSE extensions up to SSSE3 ###
+### Author: Emilia Käsper and Peter Schwabe ###
+### Date: 2009-03-19 ###
+### Public domain ###
+### ###
+### See http://homes.esat.kuleuven.be/~ekasper/#software for ###
+### further information. ###
+###################################################################
+#
+# September 2011.
+#
+# Started as transliteration to "perlasm" the original code has
+# undergone following changes:
+#
+# - code was made position-independent;
+# - rounds were folded into a loop resulting in >5x size reduction
+# from 12.5KB to 2.2KB;
+# - above was possible thanks to mixcolumns() modification that
+# allowed to feed its output back to aesenc[last], this was
+# achieved at cost of two additional inter-registers moves;
+# - some instruction reordering and interleaving;
+# - this module doesn't implement key setup subroutine, instead it
+# relies on conversion of "conventional" key schedule as returned
+# by AES_set_encrypt_key (see discussion below);
+# - first and last round keys are treated differently, which allowed
+# to skip one shiftrows(), reduce bit-sliced key schedule and
+# speed-up conversion by 22%;
+# - support for 192- and 256-bit keys was added;
+#
+# Resulting performance in CPU cycles spent to encrypt one byte out
+# of 4096-byte buffer with 128-bit key is:
+#
+# Emilia's this(*) difference
+#
+# Core 2 9.30 8.69 +7%
+# Nehalem(**) 7.63 6.88 +11%
+# Atom 17.1 16.4 +4%
+# Silvermont - 12.9
+# Goldmont - 8.85
+#
+# (*) Comparison is not completely fair, because "this" is ECB,
+# i.e. no extra processing such as counter values calculation
+# and xor-ing input as in Emilia's CTR implementation is
+# performed. However, the CTR calculations stand for not more
+# than 1% of total time, so comparison is *rather* fair.
+#
+# (**) Results were collected on Westmere, which is considered to
+# be equivalent to Nehalem for this code.
+#
+# As for key schedule conversion subroutine. Interface to OpenSSL
+# relies on per-invocation on-the-fly conversion. This naturally
+# has impact on performance, especially for short inputs. Conversion
+# time in CPU cycles and its ratio to CPU cycles spent in 8x block
+# function is:
+#
+# conversion conversion/8x block
+# Core 2 240 0.22
+# Nehalem 180 0.20
+# Atom 430 0.20
+#
+# The ratio values mean that 128-byte blocks will be processed
+# 16-18% slower, 256-byte blocks - 9-10%, 384-byte blocks - 6-7%,
+# etc. Then keep in mind that input sizes not divisible by 128 are
+# *effectively* slower, especially shortest ones, e.g. consecutive
+# 144-byte blocks are processed 44% slower than one would expect,
+# 272 - 29%, 400 - 22%, etc. Yet, despite all these "shortcomings"
+# it's still faster than ["hyper-threading-safe" code path in]
+# aes-x86_64.pl on all lengths above 64 bytes...
+#
+# October 2011.
+#
+# Add decryption procedure. Performance in CPU cycles spent to decrypt
+# one byte out of 4096-byte buffer with 128-bit key is:
+#
+# Core 2 9.98
+# Nehalem 7.80
+# Atom 17.9
+# Silvermont 14.0
+# Goldmont 10.2
+#
+# November 2011.
+#
+# Add bsaes_xts_[en|de]crypt. Less-than-80-bytes-block performance is
+# suboptimal, but XTS is meant to be used with larger blocks...
+#
+# <appro@openssl.org>
+
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
+*STDOUT=*OUT;
+
+my ($inp,$out,$len,$key,$ivp)=("%rdi","%rsi","%rdx","%rcx");
+my @XMM=map("%xmm$_",(15,0..14)); # best on Atom, +10% over (0..15)
+my $ecb=0; # suppress unreferenced ECB subroutines, spare some space...
+
+{
+my ($key,$rounds,$const)=("%rax","%r10d","%r11");
+
+sub Sbox {
+# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
+# output in lsb > [b0, b1, b4, b6, b3, b7, b2, b5] < msb
+my @b=@_[0..7];
+my @t=@_[8..11];
+my @s=@_[12..15];
+ &InBasisChange (@b);
+ &Inv_GF256 (@b[6,5,0,3,7,1,4,2],@t,@s);
+ &OutBasisChange (@b[7,1,4,2,6,5,0,3]);
+}
+
+sub InBasisChange {
+# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
+# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
+my @b=@_[0..7];
+$code.=<<___;
+ pxor @b[6], @b[5]
+ pxor @b[1], @b[2]
+ pxor @b[0], @b[3]
+ pxor @b[2], @b[6]
+ pxor @b[0], @b[5]
+
+ pxor @b[3], @b[6]
+ pxor @b[7], @b[3]
+ pxor @b[5], @b[7]
+ pxor @b[4], @b[3]
+ pxor @b[5], @b[4]
+ pxor @b[1], @b[3]
+
+ pxor @b[7], @b[2]
+ pxor @b[5], @b[1]
+___
+}
+
+sub OutBasisChange {
+# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
+# output in lsb > [b6, b1, b2, b4, b7, b0, b3, b5] < msb
+my @b=@_[0..7];
+$code.=<<___;
+ pxor @b[6], @b[0]
+ pxor @b[4], @b[1]
+ pxor @b[0], @b[2]
+ pxor @b[6], @b[4]
+ pxor @b[1], @b[6]
+
+ pxor @b[5], @b[1]
+ pxor @b[3], @b[5]
+ pxor @b[7], @b[3]
+ pxor @b[5], @b[7]
+ pxor @b[5], @b[2]
+
+ pxor @b[7], @b[4]
+___
+}
+
+sub InvSbox {
+# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
+# output in lsb > [b0, b1, b6, b4, b2, b7, b3, b5] < msb
+my @b=@_[0..7];
+my @t=@_[8..11];
+my @s=@_[12..15];
+ &InvInBasisChange (@b);
+ &Inv_GF256 (@b[5,1,2,6,3,7,0,4],@t,@s);
+ &InvOutBasisChange (@b[3,7,0,4,5,1,2,6]);
+}
+
+sub InvInBasisChange { # OutBasisChange in reverse
+my @b=@_[5,1,2,6,3,7,0,4];
+$code.=<<___
+ pxor @b[7], @b[4]
+
+ pxor @b[5], @b[7]
+ pxor @b[5], @b[2]
+ pxor @b[7], @b[3]
+ pxor @b[3], @b[5]
+ pxor @b[5], @b[1]
+
+ pxor @b[1], @b[6]
+ pxor @b[0], @b[2]
+ pxor @b[6], @b[4]
+ pxor @b[6], @b[0]
+ pxor @b[4], @b[1]
+___
+}
+
+sub InvOutBasisChange { # InBasisChange in reverse
+my @b=@_[2,5,7,3,6,1,0,4];
+$code.=<<___;
+ pxor @b[5], @b[1]
+ pxor @b[7], @b[2]
+
+ pxor @b[1], @b[3]
+ pxor @b[5], @b[4]
+ pxor @b[5], @b[7]
+ pxor @b[4], @b[3]
+ pxor @b[0], @b[5]
+ pxor @b[7], @b[3]
+ pxor @b[2], @b[6]
+ pxor @b[1], @b[2]
+ pxor @b[3], @b[6]
+
+ pxor @b[0], @b[3]
+ pxor @b[6], @b[5]
+___
+}
+
+sub Mul_GF4 {
+#;*************************************************************
+#;* Mul_GF4: Input x0-x1,y0-y1 Output x0-x1 Temp t0 (8) *
+#;*************************************************************
+my ($x0,$x1,$y0,$y1,$t0)=@_;
+$code.=<<___;
+ movdqa $y0, $t0
+ pxor $y1, $t0
+ pand $x0, $t0
+ pxor $x1, $x0
+ pand $y0, $x1
+ pand $y1, $x0
+ pxor $x1, $x0
+ pxor $t0, $x1
+___
+}
+
+sub Mul_GF4_N { # not used, see next subroutine
+# multiply and scale by N
+my ($x0,$x1,$y0,$y1,$t0)=@_;
+$code.=<<___;
+ movdqa $y0, $t0
+ pxor $y1, $t0
+ pand $x0, $t0
+ pxor $x1, $x0
+ pand $y0, $x1
+ pand $y1, $x0
+ pxor $x0, $x1
+ pxor $t0, $x0
+___
+}
+
+sub Mul_GF4_N_GF4 {
+# interleaved Mul_GF4_N and Mul_GF4
+my ($x0,$x1,$y0,$y1,$t0,
+ $x2,$x3,$y2,$y3,$t1)=@_;
+$code.=<<___;
+ movdqa $y0, $t0
+ movdqa $y2, $t1
+ pxor $y1, $t0
+ pxor $y3, $t1
+ pand $x0, $t0
+ pand $x2, $t1
+ pxor $x1, $x0
+ pxor $x3, $x2
+ pand $y0, $x1
+ pand $y2, $x3
+ pand $y1, $x0
+ pand $y3, $x2
+ pxor $x0, $x1
+ pxor $x3, $x2
+ pxor $t0, $x0
+ pxor $t1, $x3
+___
+}
+sub Mul_GF16_2 {
+my @x=@_[0..7];
+my @y=@_[8..11];
+my @t=@_[12..15];
+$code.=<<___;
+ movdqa @x[0], @t[0]
+ movdqa @x[1], @t[1]
+___
+ &Mul_GF4 (@x[0], @x[1], @y[0], @y[1], @t[2]);
+$code.=<<___;
+ pxor @x[2], @t[0]
+ pxor @x[3], @t[1]
+ pxor @y[2], @y[0]
+ pxor @y[3], @y[1]
+___
+ Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3],
+ @x[2], @x[3], @y[2], @y[3], @t[2]);
+$code.=<<___;
+ pxor @t[0], @x[0]
+ pxor @t[0], @x[2]
+ pxor @t[1], @x[1]
+ pxor @t[1], @x[3]
+
+ movdqa @x[4], @t[0]
+ movdqa @x[5], @t[1]
+ pxor @x[6], @t[0]
+ pxor @x[7], @t[1]
+___
+ &Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3],
+ @x[6], @x[7], @y[2], @y[3], @t[2]);
+$code.=<<___;
+ pxor @y[2], @y[0]
+ pxor @y[3], @y[1]
+___
+ &Mul_GF4 (@x[4], @x[5], @y[0], @y[1], @t[3]);
+$code.=<<___;
+ pxor @t[0], @x[4]
+ pxor @t[0], @x[6]
+ pxor @t[1], @x[5]
+ pxor @t[1], @x[7]
+___
+}
+sub Inv_GF256 {
+#;********************************************************************
+#;* Inv_GF256: Input x0-x7 Output x0-x7 Temp t0-t3,s0-s3 (144) *
+#;********************************************************************
+my @x=@_[0..7];
+my @t=@_[8..11];
+my @s=@_[12..15];
+# direct optimizations from hardware
+$code.=<<___;
+ movdqa @x[4], @t[3]
+ movdqa @x[5], @t[2]
+ movdqa @x[1], @t[1]
+ movdqa @x[7], @s[1]
+ movdqa @x[0], @s[0]
+
+ pxor @x[6], @t[3]
+ pxor @x[7], @t[2]
+ pxor @x[3], @t[1]
+ movdqa @t[3], @s[2]
+ pxor @x[6], @s[1]
+ movdqa @t[2], @t[0]
+ pxor @x[2], @s[0]
+ movdqa @t[3], @s[3]
+
+ por @t[1], @t[2]
+ por @s[0], @t[3]
+ pxor @t[0], @s[3]
+ pand @s[0], @s[2]
+ pxor @t[1], @s[0]
+ pand @t[1], @t[0]
+ pand @s[0], @s[3]
+ movdqa @x[3], @s[0]
+ pxor @x[2], @s[0]
+ pand @s[0], @s[1]
+ pxor @s[1], @t[3]
+ pxor @s[1], @t[2]
+ movdqa @x[4], @s[1]
+ movdqa @x[1], @s[0]
+ pxor @x[5], @s[1]
+ pxor @x[0], @s[0]
+ movdqa @s[1], @t[1]
+ pand @s[0], @s[1]
+ por @s[0], @t[1]
+ pxor @s[1], @t[0]
+ pxor @s[3], @t[3]
+ pxor @s[2], @t[2]
+ pxor @s[3], @t[1]
+ movdqa @x[7], @s[0]
+ pxor @s[2], @t[0]
+ movdqa @x[6], @s[1]
+ pxor @s[2], @t[1]
+ movdqa @x[5], @s[2]
+ pand @x[3], @s[0]
+ movdqa @x[4], @s[3]
+ pand @x[2], @s[1]
+ pand @x[1], @s[2]
+ por @x[0], @s[3]
+ pxor @s[0], @t[3]
+ pxor @s[1], @t[2]
+ pxor @s[2], @t[1]
+ pxor @s[3], @t[0]
+
+ #Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3
+
+ # new smaller inversion
+
+ movdqa @t[3], @s[0]
+ pand @t[1], @t[3]
+ pxor @t[2], @s[0]
+
+ movdqa @t[0], @s[2]
+ movdqa @s[0], @s[3]
+ pxor @t[3], @s[2]
+ pand @s[2], @s[3]
+
+ movdqa @t[1], @s[1]
+ pxor @t[2], @s[3]
+ pxor @t[0], @s[1]
+
+ pxor @t[2], @t[3]
+
+ pand @t[3], @s[1]
+
+ movdqa @s[2], @t[2]
+ pxor @t[0], @s[1]
+
+ pxor @s[1], @t[2]
+ pxor @s[1], @t[1]
+
+ pand @t[0], @t[2]
+
+ pxor @t[2], @s[2]
+ pxor @t[2], @t[1]
+
+ pand @s[3], @s[2]
+
+ pxor @s[0], @s[2]
+___
+# output in s3, s2, s1, t1
+
+# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \t2, \t3, \t0, \t1, \s0, \s1, \s2, \s3
+
+# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3
+ &Mul_GF16_2(@x,@s[3,2,1],@t[1],@s[0],@t[0,2,3]);
+
+### output msb > [x3,x2,x1,x0,x7,x6,x5,x4] < lsb
+}
+
+# AES linear components
+
+sub ShiftRows {
+my @x=@_[0..7];
+my $mask=pop;
+$code.=<<___;
+ pxor 0x00($key),@x[0]
+ pxor 0x10($key),@x[1]
+ pxor 0x20($key),@x[2]
+ pxor 0x30($key),@x[3]
+ pshufb $mask,@x[0]
+ pshufb $mask,@x[1]
+ pxor 0x40($key),@x[4]
+ pxor 0x50($key),@x[5]
+ pshufb $mask,@x[2]
+ pshufb $mask,@x[3]
+ pxor 0x60($key),@x[6]
+ pxor 0x70($key),@x[7]
+ pshufb $mask,@x[4]
+ pshufb $mask,@x[5]
+ pshufb $mask,@x[6]
+ pshufb $mask,@x[7]
+ lea 0x80($key),$key
+___
+}
+
+sub MixColumns {
+# modified to emit output in order suitable for feeding back to aesenc[last]
+my @x=@_[0..7];
+my @t=@_[8..15];
+my $inv=@_[16]; # optional
+$code.=<<___;
+ pshufd \$0x93, @x[0], @t[0] # x0 <<< 32
+ pshufd \$0x93, @x[1], @t[1]
+ pxor @t[0], @x[0] # x0 ^ (x0 <<< 32)
+ pshufd \$0x93, @x[2], @t[2]
+ pxor @t[1], @x[1]
+ pshufd \$0x93, @x[3], @t[3]
+ pxor @t[2], @x[2]
+ pshufd \$0x93, @x[4], @t[4]
+ pxor @t[3], @x[3]
+ pshufd \$0x93, @x[5], @t[5]
+ pxor @t[4], @x[4]
+ pshufd \$0x93, @x[6], @t[6]
+ pxor @t[5], @x[5]
+ pshufd \$0x93, @x[7], @t[7]
+ pxor @t[6], @x[6]
+ pxor @t[7], @x[7]
+
+ pxor @x[0], @t[1]
+ pxor @x[7], @t[0]
+ pxor @x[7], @t[1]
+ pshufd \$0x4E, @x[0], @x[0] # (x0 ^ (x0 <<< 32)) <<< 64)
+ pxor @x[1], @t[2]
+ pshufd \$0x4E, @x[1], @x[1]
+ pxor @x[4], @t[5]
+ pxor @t[0], @x[0]
+ pxor @x[5], @t[6]
+ pxor @t[1], @x[1]
+ pxor @x[3], @t[4]
+ pshufd \$0x4E, @x[4], @t[0]
+ pxor @x[6], @t[7]
+ pshufd \$0x4E, @x[5], @t[1]
+ pxor @x[2], @t[3]
+ pshufd \$0x4E, @x[3], @x[4]
+ pxor @x[7], @t[3]
+ pshufd \$0x4E, @x[7], @x[5]
+ pxor @x[7], @t[4]
+ pshufd \$0x4E, @x[6], @x[3]
+ pxor @t[4], @t[0]
+ pshufd \$0x4E, @x[2], @x[6]
+ pxor @t[5], @t[1]
+___
+$code.=<<___ if (!$inv);
+ pxor @t[3], @x[4]
+ pxor @t[7], @x[5]
+ pxor @t[6], @x[3]
+ movdqa @t[0], @x[2]
+ pxor @t[2], @x[6]
+ movdqa @t[1], @x[7]
+___
+$code.=<<___ if ($inv);
+ pxor @x[4], @t[3]
+ pxor @t[7], @x[5]
+ pxor @x[3], @t[6]
+ movdqa @t[0], @x[3]
+ pxor @t[2], @x[6]
+ movdqa @t[6], @x[2]
+ movdqa @t[1], @x[7]
+ movdqa @x[6], @x[4]
+ movdqa @t[3], @x[6]
+___
+}
+
+sub InvMixColumns_orig {
+my @x=@_[0..7];
+my @t=@_[8..15];
+
+$code.=<<___;
+ # multiplication by 0x0e
+ pshufd \$0x93, @x[7], @t[7]
+ movdqa @x[2], @t[2]
+ pxor @x[5], @x[7] # 7 5
+ pxor @x[5], @x[2] # 2 5
+ pshufd \$0x93, @x[0], @t[0]
+ movdqa @x[5], @t[5]
+ pxor @x[0], @x[5] # 5 0 [1]
+ pxor @x[1], @x[0] # 0 1
+ pshufd \$0x93, @x[1], @t[1]
+ pxor @x[2], @x[1] # 1 25
+ pxor @x[6], @x[0] # 01 6 [2]
+ pxor @x[3], @x[1] # 125 3 [4]
+ pshufd \$0x93, @x[3], @t[3]
+ pxor @x[0], @x[2] # 25 016 [3]
+ pxor @x[7], @x[3] # 3 75
+ pxor @x[6], @x[7] # 75 6 [0]
+ pshufd \$0x93, @x[6], @t[6]
+ movdqa @x[4], @t[4]
+ pxor @x[4], @x[6] # 6 4
+ pxor @x[3], @x[4] # 4 375 [6]
+ pxor @x[7], @x[3] # 375 756=36
+ pxor @t[5], @x[6] # 64 5 [7]
+ pxor @t[2], @x[3] # 36 2
+ pxor @t[4], @x[3] # 362 4 [5]
+ pshufd \$0x93, @t[5], @t[5]
+___
+ my @y = @x[7,5,0,2,1,3,4,6];
+$code.=<<___;
+ # multiplication by 0x0b
+ pxor @y[0], @y[1]
+ pxor @t[0], @y[0]
+ pxor @t[1], @y[1]
+ pshufd \$0x93, @t[2], @t[2]
+ pxor @t[5], @y[0]
+ pxor @t[6], @y[1]
+ pxor @t[7], @y[0]
+ pshufd \$0x93, @t[4], @t[4]
+ pxor @t[6], @t[7] # clobber t[7]
+ pxor @y[0], @y[1]
+
+ pxor @t[0], @y[3]
+ pshufd \$0x93, @t[0], @t[0]
+ pxor @t[1], @y[2]
+ pxor @t[1], @y[4]
+ pxor @t[2], @y[2]
+ pshufd \$0x93, @t[1], @t[1]
+ pxor @t[2], @y[3]
+ pxor @t[2], @y[5]
+ pxor @t[7], @y[2]
+ pshufd \$0x93, @t[2], @t[2]
+ pxor @t[3], @y[3]
+ pxor @t[3], @y[6]
+ pxor @t[3], @y[4]
+ pshufd \$0x93, @t[3], @t[3]
+ pxor @t[4], @y[7]
+ pxor @t[4], @y[5]
+ pxor @t[7], @y[7]
+ pxor @t[5], @y[3]
+ pxor @t[4], @y[4]
+ pxor @t[5], @t[7] # clobber t[7] even more
+
+ pxor @t[7], @y[5]
+ pshufd \$0x93, @t[4], @t[4]
+ pxor @t[7], @y[6]
+ pxor @t[7], @y[4]
+
+ pxor @t[5], @t[7]
+ pshufd \$0x93, @t[5], @t[5]
+ pxor @t[6], @t[7] # restore t[7]
+
+ # multiplication by 0x0d
+ pxor @y[7], @y[4]
+ pxor @t[4], @y[7]
+ pshufd \$0x93, @t[6], @t[6]
+ pxor @t[0], @y[2]
+ pxor @t[5], @y[7]
+ pxor @t[2], @y[2]
+ pshufd \$0x93, @t[7], @t[7]
+
+ pxor @y[1], @y[3]
+ pxor @t[1], @y[1]
+ pxor @t[0], @y[0]
+ pxor @t[0], @y[3]
+ pxor @t[5], @y[1]
+ pxor @t[5], @y[0]
+ pxor @t[7], @y[1]
+ pshufd \$0x93, @t[0], @t[0]
+ pxor @t[6], @y[0]
+ pxor @y[1], @y[3]
+ pxor @t[1], @y[4]
+ pshufd \$0x93, @t[1], @t[1]
+
+ pxor @t[7], @y[7]
+ pxor @t[2], @y[4]
+ pxor @t[2], @y[5]
+ pshufd \$0x93, @t[2], @t[2]
+ pxor @t[6], @y[2]
+ pxor @t[3], @t[6] # clobber t[6]
+ pxor @y[7], @y[4]
+ pxor @t[6], @y[3]
+
+ pxor @t[6], @y[6]
+ pxor @t[5], @y[5]
+ pxor @t[4], @y[6]
+ pshufd \$0x93, @t[4], @t[4]
+ pxor @t[6], @y[5]
+ pxor @t[7], @y[6]
+ pxor @t[3], @t[6] # restore t[6]
+
+ pshufd \$0x93, @t[5], @t[5]
+ pshufd \$0x93, @t[6], @t[6]
+ pshufd \$0x93, @t[7], @t[7]
+ pshufd \$0x93, @t[3], @t[3]
+
+ # multiplication by 0x09
+ pxor @y[1], @y[4]
+ pxor @y[1], @t[1] # t[1]=y[1]
+ pxor @t[5], @t[0] # clobber t[0]
+ pxor @t[5], @t[1]
+ pxor @t[0], @y[3]
+ pxor @y[0], @t[0] # t[0]=y[0]
+ pxor @t[6], @t[1]
+ pxor @t[7], @t[6] # clobber t[6]
+ pxor @t[1], @y[4]
+ pxor @t[4], @y[7]
+ pxor @y[4], @t[4] # t[4]=y[4]
+ pxor @t[3], @y[6]
+ pxor @y[3], @t[3] # t[3]=y[3]
+ pxor @t[2], @y[5]
+ pxor @y[2], @t[2] # t[2]=y[2]
+ pxor @t[7], @t[3]
+ pxor @y[5], @t[5] # t[5]=y[5]
+ pxor @t[6], @t[2]
+ pxor @t[6], @t[5]
+ pxor @y[6], @t[6] # t[6]=y[6]
+ pxor @y[7], @t[7] # t[7]=y[7]
+
+ movdqa @t[0],@XMM[0]
+ movdqa @t[1],@XMM[1]
+ movdqa @t[2],@XMM[2]
+ movdqa @t[3],@XMM[3]
+ movdqa @t[4],@XMM[4]
+ movdqa @t[5],@XMM[5]
+ movdqa @t[6],@XMM[6]
+ movdqa @t[7],@XMM[7]
+___
+}
+
+sub InvMixColumns {
+my @x=@_[0..7];
+my @t=@_[8..15];
+
+# Thanks to Jussi Kivilinna for providing pointer to
+#
+# | 0e 0b 0d 09 | | 02 03 01 01 | | 05 00 04 00 |
+# | 09 0e 0b 0d | = | 01 02 03 01 | x | 00 05 00 04 |
+# | 0d 09 0e 0b | | 01 01 02 03 | | 04 00 05 00 |
+# | 0b 0d 09 0e | | 03 01 01 02 | | 00 04 00 05 |
+
+$code.=<<___;
+ # multiplication by 0x05-0x00-0x04-0x00
+ pshufd \$0x4E, @x[0], @t[0]
+ pshufd \$0x4E, @x[6], @t[6]
+ pxor @x[0], @t[0]
+ pshufd \$0x4E, @x[7], @t[7]
+ pxor @x[6], @t[6]
+ pshufd \$0x4E, @x[1], @t[1]
+ pxor @x[7], @t[7]
+ pshufd \$0x4E, @x[2], @t[2]
+ pxor @x[1], @t[1]
+ pshufd \$0x4E, @x[3], @t[3]
+ pxor @x[2], @t[2]
+ pxor @t[6], @x[0]
+ pxor @t[6], @x[1]
+ pshufd \$0x4E, @x[4], @t[4]
+ pxor @x[3], @t[3]
+ pxor @t[0], @x[2]
+ pxor @t[1], @x[3]
+ pshufd \$0x4E, @x[5], @t[5]
+ pxor @x[4], @t[4]
+ pxor @t[7], @x[1]
+ pxor @t[2], @x[4]
+ pxor @x[5], @t[5]
+
+ pxor @t[7], @x[2]
+ pxor @t[6], @x[3]
+ pxor @t[6], @x[4]
+ pxor @t[3], @x[5]
+ pxor @t[4], @x[6]
+ pxor @t[7], @x[4]
+ pxor @t[7], @x[5]
+ pxor @t[5], @x[7]
+___
+ &MixColumns (@x,@t,1); # flipped 2<->3 and 4<->6
+}
+
+sub aesenc { # not used
+my @b=@_[0..7];
+my @t=@_[8..15];
+$code.=<<___;
+ movdqa 0x30($const),@t[0] # .LSR
+___
+ &ShiftRows (@b,@t[0]);
+ &Sbox (@b,@t);
+ &MixColumns (@b[0,1,4,6,3,7,2,5],@t);
+}
+
+sub aesenclast { # not used
+my @b=@_[0..7];
+my @t=@_[8..15];
+$code.=<<___;
+ movdqa 0x40($const),@t[0] # .LSRM0
+___
+ &ShiftRows (@b,@t[0]);
+ &Sbox (@b,@t);
+$code.=<<___
+ pxor 0x00($key),@b[0]
+ pxor 0x10($key),@b[1]
+ pxor 0x20($key),@b[4]
+ pxor 0x30($key),@b[6]
+ pxor 0x40($key),@b[3]
+ pxor 0x50($key),@b[7]
+ pxor 0x60($key),@b[2]
+ pxor 0x70($key),@b[5]
+___
+}
+
+sub swapmove {
+my ($a,$b,$n,$mask,$t)=@_;
+$code.=<<___;
+ movdqa $b,$t
+ psrlq \$$n,$b
+ pxor $a,$b
+ pand $mask,$b
+ pxor $b,$a
+ psllq \$$n,$b
+ pxor $t,$b
+___
+}
+sub swapmove2x {
+my ($a0,$b0,$a1,$b1,$n,$mask,$t0,$t1)=@_;
+$code.=<<___;
+ movdqa $b0,$t0
+ psrlq \$$n,$b0
+ movdqa $b1,$t1
+ psrlq \$$n,$b1
+ pxor $a0,$b0
+ pxor $a1,$b1
+ pand $mask,$b0
+ pand $mask,$b1
+ pxor $b0,$a0
+ psllq \$$n,$b0
+ pxor $b1,$a1
+ psllq \$$n,$b1
+ pxor $t0,$b0
+ pxor $t1,$b1
+___
+}
+
+sub bitslice {
+my @x=reverse(@_[0..7]);
+my ($t0,$t1,$t2,$t3)=@_[8..11];
+$code.=<<___;
+ movdqa 0x00($const),$t0 # .LBS0
+ movdqa 0x10($const),$t1 # .LBS1
+___
+ &swapmove2x(@x[0,1,2,3],1,$t0,$t2,$t3);
+ &swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
+$code.=<<___;
+ movdqa 0x20($const),$t0 # .LBS2
+___
+ &swapmove2x(@x[0,2,1,3],2,$t1,$t2,$t3);
+ &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
+
+ &swapmove2x(@x[0,4,1,5],4,$t0,$t2,$t3);
+ &swapmove2x(@x[2,6,3,7],4,$t0,$t2,$t3);
+}
+
+$code.=<<___;
+.text
+
+.extern asm_AES_encrypt
+.extern asm_AES_decrypt
+
+.type _bsaes_encrypt8,\@abi-omnipotent
+.align 64
+_bsaes_encrypt8:
+.cfi_startproc
+ lea .LBS0(%rip), $const # constants table
+
+ movdqa ($key), @XMM[9] # round 0 key
+ lea 0x10($key), $key
+ movdqa 0x50($const), @XMM[8] # .LM0SR
+ pxor @XMM[9], @XMM[0] # xor with round0 key
+ pxor @XMM[9], @XMM[1]
+ pxor @XMM[9], @XMM[2]
+ pxor @XMM[9], @XMM[3]
+ pshufb @XMM[8], @XMM[0]
+ pshufb @XMM[8], @XMM[1]
+ pxor @XMM[9], @XMM[4]
+ pxor @XMM[9], @XMM[5]
+ pshufb @XMM[8], @XMM[2]
+ pshufb @XMM[8], @XMM[3]
+ pxor @XMM[9], @XMM[6]
+ pxor @XMM[9], @XMM[7]
+ pshufb @XMM[8], @XMM[4]
+ pshufb @XMM[8], @XMM[5]
+ pshufb @XMM[8], @XMM[6]
+ pshufb @XMM[8], @XMM[7]
+_bsaes_encrypt8_bitslice:
+___
+ &bitslice (@XMM[0..7, 8..11]);
+$code.=<<___;
+ dec $rounds
+ jmp .Lenc_sbox
+.align 16
+.Lenc_loop:
+___
+ &ShiftRows (@XMM[0..7, 8]);
+$code.=".Lenc_sbox:\n";
+ &Sbox (@XMM[0..7, 8..15]);
+$code.=<<___;
+ dec $rounds
+ jl .Lenc_done
+___
+ &MixColumns (@XMM[0,1,4,6,3,7,2,5, 8..15]);
+$code.=<<___;
+ movdqa 0x30($const), @XMM[8] # .LSR
+ jnz .Lenc_loop
+ movdqa 0x40($const), @XMM[8] # .LSRM0
+ jmp .Lenc_loop
+.align 16
+.Lenc_done:
+___
+ # output in lsb > [t0, t1, t4, t6, t3, t7, t2, t5] < msb
+ &bitslice (@XMM[0,1,4,6,3,7,2,5, 8..11]);
+$code.=<<___;
+ movdqa ($key), @XMM[8] # last round key
+ pxor @XMM[8], @XMM[4]
+ pxor @XMM[8], @XMM[6]
+ pxor @XMM[8], @XMM[3]
+ pxor @XMM[8], @XMM[7]
+ pxor @XMM[8], @XMM[2]
+ pxor @XMM[8], @XMM[5]
+ pxor @XMM[8], @XMM[0]
+ pxor @XMM[8], @XMM[1]
+ ret
+.cfi_endproc
+.size _bsaes_encrypt8,.-_bsaes_encrypt8
+
+.type _bsaes_decrypt8,\@abi-omnipotent
+.align 64
+_bsaes_decrypt8:
+.cfi_startproc
+ lea .LBS0(%rip), $const # constants table
+
+ movdqa ($key), @XMM[9] # round 0 key
+ lea 0x10($key), $key
+ movdqa -0x30($const), @XMM[8] # .LM0ISR
+ pxor @XMM[9], @XMM[0] # xor with round0 key
+ pxor @XMM[9], @XMM[1]
+ pxor @XMM[9], @XMM[2]
+ pxor @XMM[9], @XMM[3]
+ pshufb @XMM[8], @XMM[0]
+ pshufb @XMM[8], @XMM[1]
+ pxor @XMM[9], @XMM[4]
+ pxor @XMM[9], @XMM[5]
+ pshufb @XMM[8], @XMM[2]
+ pshufb @XMM[8], @XMM[3]
+ pxor @XMM[9], @XMM[6]
+ pxor @XMM[9], @XMM[7]
+ pshufb @XMM[8], @XMM[4]
+ pshufb @XMM[8], @XMM[5]
+ pshufb @XMM[8], @XMM[6]
+ pshufb @XMM[8], @XMM[7]
+___
+ &bitslice (@XMM[0..7, 8..11]);
+$code.=<<___;
+ dec $rounds
+ jmp .Ldec_sbox
+.align 16
+.Ldec_loop:
+___
+ &ShiftRows (@XMM[0..7, 8]);
+$code.=".Ldec_sbox:\n";
+ &InvSbox (@XMM[0..7, 8..15]);
+$code.=<<___;
+ dec $rounds
+ jl .Ldec_done
+___
+ &InvMixColumns (@XMM[0,1,6,4,2,7,3,5, 8..15]);
+$code.=<<___;
+ movdqa -0x10($const), @XMM[8] # .LISR
+ jnz .Ldec_loop
+ movdqa -0x20($const), @XMM[8] # .LISRM0
+ jmp .Ldec_loop
+.align 16
+.Ldec_done:
+___
+ &bitslice (@XMM[0,1,6,4,2,7,3,5, 8..11]);
+$code.=<<___;
+ movdqa ($key), @XMM[8] # last round key
+ pxor @XMM[8], @XMM[6]
+ pxor @XMM[8], @XMM[4]
+ pxor @XMM[8], @XMM[2]
+ pxor @XMM[8], @XMM[7]
+ pxor @XMM[8], @XMM[3]
+ pxor @XMM[8], @XMM[5]
+ pxor @XMM[8], @XMM[0]
+ pxor @XMM[8], @XMM[1]
+ ret
+.cfi_endproc
+.size _bsaes_decrypt8,.-_bsaes_decrypt8
+___
+}
+{
+my ($out,$inp,$rounds,$const)=("%rax","%rcx","%r10d","%r11");
+
+sub bitslice_key {
+my @x=reverse(@_[0..7]);
+my ($bs0,$bs1,$bs2,$t2,$t3)=@_[8..12];
+
+ &swapmove (@x[0,1],1,$bs0,$t2,$t3);
+$code.=<<___;
+ #&swapmove(@x[2,3],1,$t0,$t2,$t3);
+ movdqa @x[0], @x[2]
+ movdqa @x[1], @x[3]
+___
+ #&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
+
+ &swapmove2x (@x[0,2,1,3],2,$bs1,$t2,$t3);
+$code.=<<___;
+ #&swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
+ movdqa @x[0], @x[4]
+ movdqa @x[2], @x[6]
+ movdqa @x[1], @x[5]
+ movdqa @x[3], @x[7]
+___
+ &swapmove2x (@x[0,4,1,5],4,$bs2,$t2,$t3);
+ &swapmove2x (@x[2,6,3,7],4,$bs2,$t2,$t3);
+}
+
+$code.=<<___;
+.type _bsaes_key_convert,\@abi-omnipotent
+.align 16
+_bsaes_key_convert:
+.cfi_startproc
+ lea .Lmasks(%rip), $const
+ movdqu ($inp), %xmm7 # load round 0 key
+ lea 0x10($inp), $inp
+ movdqa 0x00($const), %xmm0 # 0x01...
+ movdqa 0x10($const), %xmm1 # 0x02...
+ movdqa 0x20($const), %xmm2 # 0x04...
+ movdqa 0x30($const), %xmm3 # 0x08...
+ movdqa 0x40($const), %xmm4 # .LM0
+ pcmpeqd %xmm5, %xmm5 # .LNOT
+
+ movdqu ($inp), %xmm6 # load round 1 key
+ movdqa %xmm7, ($out) # save round 0 key
+ lea 0x10($out), $out
+ dec $rounds
+ jmp .Lkey_loop
+.align 16
+.Lkey_loop:
+ pshufb %xmm4, %xmm6 # .LM0
+
+ movdqa %xmm0, %xmm8
+ movdqa %xmm1, %xmm9
+
+ pand %xmm6, %xmm8
+ pand %xmm6, %xmm9
+ movdqa %xmm2, %xmm10
+ pcmpeqb %xmm0, %xmm8
+ psllq \$4, %xmm0 # 0x10...
+ movdqa %xmm3, %xmm11
+ pcmpeqb %xmm1, %xmm9
+ psllq \$4, %xmm1 # 0x20...
+
+ pand %xmm6, %xmm10
+ pand %xmm6, %xmm11
+ movdqa %xmm0, %xmm12
+ pcmpeqb %xmm2, %xmm10
+ psllq \$4, %xmm2 # 0x40...
+ movdqa %xmm1, %xmm13
+ pcmpeqb %xmm3, %xmm11
+ psllq \$4, %xmm3 # 0x80...
+
+ movdqa %xmm2, %xmm14
+ movdqa %xmm3, %xmm15
+ pxor %xmm5, %xmm8 # "pnot"
+ pxor %xmm5, %xmm9
+
+ pand %xmm6, %xmm12
+ pand %xmm6, %xmm13
+ movdqa %xmm8, 0x00($out) # write bit-sliced round key
+ pcmpeqb %xmm0, %xmm12
+ psrlq \$4, %xmm0 # 0x01...
+ movdqa %xmm9, 0x10($out)
+ pcmpeqb %xmm1, %xmm13
+ psrlq \$4, %xmm1 # 0x02...
+ lea 0x10($inp), $inp
+
+ pand %xmm6, %xmm14
+ pand %xmm6, %xmm15
+ movdqa %xmm10, 0x20($out)
+ pcmpeqb %xmm2, %xmm14
+ psrlq \$4, %xmm2 # 0x04...
+ movdqa %xmm11, 0x30($out)
+ pcmpeqb %xmm3, %xmm15
+ psrlq \$4, %xmm3 # 0x08...
+ movdqu ($inp), %xmm6 # load next round key
+
+ pxor %xmm5, %xmm13 # "pnot"
+ pxor %xmm5, %xmm14
+ movdqa %xmm12, 0x40($out)
+ movdqa %xmm13, 0x50($out)
+ movdqa %xmm14, 0x60($out)
+ movdqa %xmm15, 0x70($out)
+ lea 0x80($out),$out
+ dec $rounds
+ jnz .Lkey_loop
+
+ movdqa 0x50($const), %xmm7 # .L63
+ #movdqa %xmm6, ($out) # don't save last round key
+ ret
+.cfi_endproc
+.size _bsaes_key_convert,.-_bsaes_key_convert
+___
+}
+
+if (0 && !$win64) { # following four functions are unsupported interface
+ # used for benchmarking...
+$code.=<<___;
+.globl bsaes_enc_key_convert
+.type bsaes_enc_key_convert,\@function,2
+.align 16
+bsaes_enc_key_convert:
+ mov 240($inp),%r10d # pass rounds
+ mov $inp,%rcx # pass key
+ mov $out,%rax # pass key schedule
+ call _bsaes_key_convert
+ pxor %xmm6,%xmm7 # fix up last round key
+ movdqa %xmm7,(%rax) # save last round key
+ ret
+.size bsaes_enc_key_convert,.-bsaes_enc_key_convert
+
+.globl bsaes_encrypt_128
+.type bsaes_encrypt_128,\@function,4
+.align 16
+bsaes_encrypt_128:
+.Lenc128_loop:
+ movdqu 0x00($inp), @XMM[0] # load input
+ movdqu 0x10($inp), @XMM[1]
+ movdqu 0x20($inp), @XMM[2]
+ movdqu 0x30($inp), @XMM[3]
+ movdqu 0x40($inp), @XMM[4]
+ movdqu 0x50($inp), @XMM[5]
+ movdqu 0x60($inp), @XMM[6]
+ movdqu 0x70($inp), @XMM[7]
+ mov $key, %rax # pass the $key
+ lea 0x80($inp), $inp
+ mov \$10,%r10d
+
+ call _bsaes_encrypt8
+
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[4], 0x20($out)
+ movdqu @XMM[6], 0x30($out)
+ movdqu @XMM[3], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[2], 0x60($out)
+ movdqu @XMM[5], 0x70($out)
+ lea 0x80($out), $out
+ sub \$0x80,$len
+ ja .Lenc128_loop
+ ret
+.size bsaes_encrypt_128,.-bsaes_encrypt_128
+
+.globl bsaes_dec_key_convert
+.type bsaes_dec_key_convert,\@function,2
+.align 16
+bsaes_dec_key_convert:
+ mov 240($inp),%r10d # pass rounds
+ mov $inp,%rcx # pass key
+ mov $out,%rax # pass key schedule
+ call _bsaes_key_convert
+ pxor ($out),%xmm7 # fix up round 0 key
+ movdqa %xmm6,(%rax) # save last round key
+ movdqa %xmm7,($out)
+ ret
+.size bsaes_dec_key_convert,.-bsaes_dec_key_convert
+
+.globl bsaes_decrypt_128
+.type bsaes_decrypt_128,\@function,4
+.align 16
+bsaes_decrypt_128:
+.Ldec128_loop:
+ movdqu 0x00($inp), @XMM[0] # load input
+ movdqu 0x10($inp), @XMM[1]
+ movdqu 0x20($inp), @XMM[2]
+ movdqu 0x30($inp), @XMM[3]
+ movdqu 0x40($inp), @XMM[4]
+ movdqu 0x50($inp), @XMM[5]
+ movdqu 0x60($inp), @XMM[6]
+ movdqu 0x70($inp), @XMM[7]
+ mov $key, %rax # pass the $key
+ lea 0x80($inp), $inp
+ mov \$10,%r10d
+
+ call _bsaes_decrypt8
+
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[3], 0x60($out)
+ movdqu @XMM[5], 0x70($out)
+ lea 0x80($out), $out
+ sub \$0x80,$len
+ ja .Ldec128_loop
+ ret
+.size bsaes_decrypt_128,.-bsaes_decrypt_128
+___
+}
+{
+######################################################################
+#
+# OpenSSL interface
+#
+my ($arg1,$arg2,$arg3,$arg4,$arg5,$arg6)=$win64 ? ("%rcx","%rdx","%r8","%r9","%r10","%r11d")
+ : ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d");
+my ($inp,$out,$len,$key)=("%r12","%r13","%r14","%r15");
+
+if ($ecb) {
+$code.=<<___;
+.globl bsaes_ecb_encrypt_blocks
+.type bsaes_ecb_encrypt_blocks,\@abi-omnipotent
+.align 16
+bsaes_ecb_encrypt_blocks:
+.cfi_startproc
+ mov %rsp, %rax
+.Lecb_enc_prologue:
+ push %rbp
+.cfi_push %rbp
+ push %rbx
+.cfi_push %rbx
+ push %r12
+.cfi_push %r12
+ push %r13
+.cfi_push %r13
+ push %r14
+.cfi_push %r14
+ push %r15
+.cfi_push %r15
+ lea -0x48(%rsp),%rsp
+.cfi_adjust_cfa_offset 0x48
+___
+$code.=<<___ if ($win64);
+ lea -0xa0(%rsp), %rsp
+ movaps %xmm6, 0x40(%rsp)
+ movaps %xmm7, 0x50(%rsp)
+ movaps %xmm8, 0x60(%rsp)
+ movaps %xmm9, 0x70(%rsp)
+ movaps %xmm10, 0x80(%rsp)
+ movaps %xmm11, 0x90(%rsp)
+ movaps %xmm12, 0xa0(%rsp)
+ movaps %xmm13, 0xb0(%rsp)
+ movaps %xmm14, 0xc0(%rsp)
+ movaps %xmm15, 0xd0(%rsp)
+.Lecb_enc_body:
+___
+$code.=<<___;
+ mov %rsp,%rbp # backup %rsp
+.cfi_def_cfa_register %rbp
+ mov 240($arg4),%eax # rounds
+ mov $arg1,$inp # backup arguments
+ mov $arg2,$out
+ mov $arg3,$len
+ mov $arg4,$key
+ cmp \$8,$arg3
+ jb .Lecb_enc_short
+
+ mov %eax,%ebx # backup rounds
+ shl \$7,%rax # 128 bytes per inner round key
+ sub \$`128-32`,%rax # size of bit-sliced key schedule
+ sub %rax,%rsp
+ mov %rsp,%rax # pass key schedule
+ mov $key,%rcx # pass key
+ mov %ebx,%r10d # pass rounds
+ call _bsaes_key_convert
+ pxor %xmm6,%xmm7 # fix up last round key
+ movdqa %xmm7,(%rax) # save last round key
+
+ sub \$8,$len
+.Lecb_enc_loop:
+ movdqu 0x00($inp), @XMM[0] # load input
+ movdqu 0x10($inp), @XMM[1]
+ movdqu 0x20($inp), @XMM[2]
+ movdqu 0x30($inp), @XMM[3]
+ movdqu 0x40($inp), @XMM[4]
+ movdqu 0x50($inp), @XMM[5]
+ mov %rsp, %rax # pass key schedule
+ movdqu 0x60($inp), @XMM[6]
+ mov %ebx,%r10d # pass rounds
+ movdqu 0x70($inp), @XMM[7]
+ lea 0x80($inp), $inp
+
+ call _bsaes_encrypt8
+
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[4], 0x20($out)
+ movdqu @XMM[6], 0x30($out)
+ movdqu @XMM[3], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[2], 0x60($out)
+ movdqu @XMM[5], 0x70($out)
+ lea 0x80($out), $out
+ sub \$8,$len
+ jnc .Lecb_enc_loop
+
+ add \$8,$len
+ jz .Lecb_enc_done
+
+ movdqu 0x00($inp), @XMM[0] # load input
+ mov %rsp, %rax # pass key schedule
+ mov %ebx,%r10d # pass rounds
+ cmp \$2,$len
+ jb .Lecb_enc_one
+ movdqu 0x10($inp), @XMM[1]
+ je .Lecb_enc_two
+ movdqu 0x20($inp), @XMM[2]
+ cmp \$4,$len
+ jb .Lecb_enc_three
+ movdqu 0x30($inp), @XMM[3]
+ je .Lecb_enc_four
+ movdqu 0x40($inp), @XMM[4]
+ cmp \$6,$len
+ jb .Lecb_enc_five
+ movdqu 0x50($inp), @XMM[5]
+ je .Lecb_enc_six
+ movdqu 0x60($inp), @XMM[6]
+ call _bsaes_encrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[4], 0x20($out)
+ movdqu @XMM[6], 0x30($out)
+ movdqu @XMM[3], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[2], 0x60($out)
+ jmp .Lecb_enc_done
+.align 16
+.Lecb_enc_six:
+ call _bsaes_encrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[4], 0x20($out)
+ movdqu @XMM[6], 0x30($out)
+ movdqu @XMM[3], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ jmp .Lecb_enc_done
+.align 16
+.Lecb_enc_five:
+ call _bsaes_encrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[4], 0x20($out)
+ movdqu @XMM[6], 0x30($out)
+ movdqu @XMM[3], 0x40($out)
+ jmp .Lecb_enc_done
+.align 16
+.Lecb_enc_four:
+ call _bsaes_encrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[4], 0x20($out)
+ movdqu @XMM[6], 0x30($out)
+ jmp .Lecb_enc_done
+.align 16
+.Lecb_enc_three:
+ call _bsaes_encrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[4], 0x20($out)
+ jmp .Lecb_enc_done
+.align 16
+.Lecb_enc_two:
+ call _bsaes_encrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ jmp .Lecb_enc_done
+.align 16
+.Lecb_enc_one:
+ call _bsaes_encrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ jmp .Lecb_enc_done
+.align 16
+.Lecb_enc_short:
+ lea ($inp), $arg1
+ lea ($out), $arg2
+ lea ($key), $arg3
+ call asm_AES_encrypt
+ lea 16($inp), $inp
+ lea 16($out), $out
+ dec $len
+ jnz .Lecb_enc_short
+
+.Lecb_enc_done:
+ lea (%rsp),%rax
+ pxor %xmm0, %xmm0
+.Lecb_enc_bzero: # wipe key schedule [if any]
+ movdqa %xmm0, 0x00(%rax)
+ movdqa %xmm0, 0x10(%rax)
+ lea 0x20(%rax), %rax
+ cmp %rax, %rbp
+ jb .Lecb_enc_bzero
+
+ lea 0x78(%rbp),%rax
+.cfi_def_cfa %rax,8
+___
+$code.=<<___ if ($win64);
+ movaps 0x40(%rbp), %xmm6
+ movaps 0x50(%rbp), %xmm7
+ movaps 0x60(%rbp), %xmm8
+ movaps 0x70(%rbp), %xmm9
+ movaps 0x80(%rbp), %xmm10
+ movaps 0x90(%rbp), %xmm11
+ movaps 0xa0(%rbp), %xmm12
+ movaps 0xb0(%rbp), %xmm13
+ movaps 0xc0(%rbp), %xmm14
+ movaps 0xd0(%rbp), %xmm15
+ lea 0xa0(%rax), %rax
+.Lecb_enc_tail:
+___
+$code.=<<___;
+ mov -48(%rax), %r15
+.cfi_restore %r15
+ mov -40(%rax), %r14
+.cfi_restore %r14
+ mov -32(%rax), %r13
+.cfi_restore %r13
+ mov -24(%rax), %r12
+.cfi_restore %r12
+ mov -16(%rax), %rbx
+.cfi_restore %rbx
+ mov -8(%rax), %rbp
+.cfi_restore %rbp
+ lea (%rax), %rsp # restore %rsp
+.cfi_def_cfa_register %rsp
+.Lecb_enc_epilogue:
+ ret
+.cfi_endproc
+.size bsaes_ecb_encrypt_blocks,.-bsaes_ecb_encrypt_blocks
+
+.globl bsaes_ecb_decrypt_blocks
+.type bsaes_ecb_decrypt_blocks,\@abi-omnipotent
+.align 16
+bsaes_ecb_decrypt_blocks:
+.cfi_startproc
+ mov %rsp, %rax
+.Lecb_dec_prologue:
+ push %rbp
+.cfi_push %rbp
+ push %rbx
+.cfi_push %rbx
+ push %r12
+.cfi_push %r12
+ push %r13
+.cfi_push %r13
+ push %r14
+.cfi_push %r14
+ push %r15
+.cfi_push %r15
+ lea -0x48(%rsp),%rsp
+.cfi_adjust_cfa_offset 0x48
+___
+$code.=<<___ if ($win64);
+ lea -0xa0(%rsp), %rsp
+ movaps %xmm6, 0x40(%rsp)
+ movaps %xmm7, 0x50(%rsp)
+ movaps %xmm8, 0x60(%rsp)
+ movaps %xmm9, 0x70(%rsp)
+ movaps %xmm10, 0x80(%rsp)
+ movaps %xmm11, 0x90(%rsp)
+ movaps %xmm12, 0xa0(%rsp)
+ movaps %xmm13, 0xb0(%rsp)
+ movaps %xmm14, 0xc0(%rsp)
+ movaps %xmm15, 0xd0(%rsp)
+.Lecb_dec_body:
+___
+$code.=<<___;
+ mov %rsp,%rbp # backup %rsp
+.cfi_def_cfa_register %rbp
+ mov 240($arg4),%eax # rounds
+ mov $arg1,$inp # backup arguments
+ mov $arg2,$out
+ mov $arg3,$len
+ mov $arg4,$key
+ cmp \$8,$arg3
+ jb .Lecb_dec_short
+
+ mov %eax,%ebx # backup rounds
+ shl \$7,%rax # 128 bytes per inner round key
+ sub \$`128-32`,%rax # size of bit-sliced key schedule
+ sub %rax,%rsp
+ mov %rsp,%rax # pass key schedule
+ mov $key,%rcx # pass key
+ mov %ebx,%r10d # pass rounds
+ call _bsaes_key_convert
+ pxor (%rsp),%xmm7 # fix up 0 round key
+ movdqa %xmm6,(%rax) # save last round key
+ movdqa %xmm7,(%rsp)
+
+ sub \$8,$len
+.Lecb_dec_loop:
+ movdqu 0x00($inp), @XMM[0] # load input
+ movdqu 0x10($inp), @XMM[1]
+ movdqu 0x20($inp), @XMM[2]
+ movdqu 0x30($inp), @XMM[3]
+ movdqu 0x40($inp), @XMM[4]
+ movdqu 0x50($inp), @XMM[5]
+ mov %rsp, %rax # pass key schedule
+ movdqu 0x60($inp), @XMM[6]
+ mov %ebx,%r10d # pass rounds
+ movdqu 0x70($inp), @XMM[7]
+ lea 0x80($inp), $inp
+
+ call _bsaes_decrypt8
+
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[3], 0x60($out)
+ movdqu @XMM[5], 0x70($out)
+ lea 0x80($out), $out
+ sub \$8,$len
+ jnc .Lecb_dec_loop
+
+ add \$8,$len
+ jz .Lecb_dec_done
+
+ movdqu 0x00($inp), @XMM[0] # load input
+ mov %rsp, %rax # pass key schedule
+ mov %ebx,%r10d # pass rounds
+ cmp \$2,$len
+ jb .Lecb_dec_one
+ movdqu 0x10($inp), @XMM[1]
+ je .Lecb_dec_two
+ movdqu 0x20($inp), @XMM[2]
+ cmp \$4,$len
+ jb .Lecb_dec_three
+ movdqu 0x30($inp), @XMM[3]
+ je .Lecb_dec_four
+ movdqu 0x40($inp), @XMM[4]
+ cmp \$6,$len
+ jb .Lecb_dec_five
+ movdqu 0x50($inp), @XMM[5]
+ je .Lecb_dec_six
+ movdqu 0x60($inp), @XMM[6]
+ call _bsaes_decrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[3], 0x60($out)
+ jmp .Lecb_dec_done
+.align 16
+.Lecb_dec_six:
+ call _bsaes_decrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ jmp .Lecb_dec_done
+.align 16
+.Lecb_dec_five:
+ call _bsaes_decrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ jmp .Lecb_dec_done
+.align 16
+.Lecb_dec_four:
+ call _bsaes_decrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ jmp .Lecb_dec_done
+.align 16
+.Lecb_dec_three:
+ call _bsaes_decrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ jmp .Lecb_dec_done
+.align 16
+.Lecb_dec_two:
+ call _bsaes_decrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ jmp .Lecb_dec_done
+.align 16
+.Lecb_dec_one:
+ call _bsaes_decrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ jmp .Lecb_dec_done
+.align 16
+.Lecb_dec_short:
+ lea ($inp), $arg1
+ lea ($out), $arg2
+ lea ($key), $arg3
+ call asm_AES_decrypt
+ lea 16($inp), $inp
+ lea 16($out), $out
+ dec $len
+ jnz .Lecb_dec_short
+
+.Lecb_dec_done:
+ lea (%rsp),%rax
+ pxor %xmm0, %xmm0
+.Lecb_dec_bzero: # wipe key schedule [if any]
+ movdqa %xmm0, 0x00(%rax)
+ movdqa %xmm0, 0x10(%rax)
+ lea 0x20(%rax), %rax
+ cmp %rax, %rbp
+ jb .Lecb_dec_bzero
+
+ lea 0x78(%rbp),%rax
+.cfi_def_cfa %rax,8
+___
+$code.=<<___ if ($win64);
+ movaps 0x40(%rbp), %xmm6
+ movaps 0x50(%rbp), %xmm7
+ movaps 0x60(%rbp), %xmm8
+ movaps 0x70(%rbp), %xmm9
+ movaps 0x80(%rbp), %xmm10
+ movaps 0x90(%rbp), %xmm11
+ movaps 0xa0(%rbp), %xmm12
+ movaps 0xb0(%rbp), %xmm13
+ movaps 0xc0(%rbp), %xmm14
+ movaps 0xd0(%rbp), %xmm15
+ lea 0xa0(%rax), %rax
+.Lecb_dec_tail:
+___
+$code.=<<___;
+ mov -48(%rax), %r15
+.cfi_restore %r15
+ mov -40(%rax), %r14
+.cfi_restore %r14
+ mov -32(%rax), %r13
+.cfi_restore %r13
+ mov -24(%rax), %r12
+.cfi_restore %r12
+ mov -16(%rax), %rbx
+.cfi_restore %rbx
+ mov -8(%rax), %rbp
+.cfi_restore %rbp
+ lea (%rax), %rsp # restore %rsp
+.cfi_def_cfa_register %rsp
+.Lecb_dec_epilogue:
+ ret
+.cfi_endproc
+.size bsaes_ecb_decrypt_blocks,.-bsaes_ecb_decrypt_blocks
+___
+}
+$code.=<<___;
+.extern asm_AES_cbc_encrypt
+.globl ossl_bsaes_cbc_encrypt
+.type ossl_bsaes_cbc_encrypt,\@abi-omnipotent
+.align 16
+ossl_bsaes_cbc_encrypt:
+.cfi_startproc
+ endbranch
+___
+$code.=<<___ if ($win64);
+ mov 48(%rsp),$arg6 # pull direction flag
+___
+$code.=<<___;
+ cmp \$0,$arg6
+ jne asm_AES_cbc_encrypt
+ cmp \$128,$arg3
+ jb asm_AES_cbc_encrypt
+
+ mov %rsp, %rax
+.Lcbc_dec_prologue:
+ push %rbp
+.cfi_push %rbp
+ push %rbx
+.cfi_push %rbx
+ push %r12
+.cfi_push %r12
+ push %r13
+.cfi_push %r13
+ push %r14
+.cfi_push %r14
+ push %r15
+.cfi_push %r15
+ lea -0x48(%rsp), %rsp
+.cfi_adjust_cfa_offset 0x48
+___
+$code.=<<___ if ($win64);
+ mov 0xa0(%rsp),$arg5 # pull ivp
+ lea -0xa0(%rsp), %rsp
+ movaps %xmm6, 0x40(%rsp)
+ movaps %xmm7, 0x50(%rsp)
+ movaps %xmm8, 0x60(%rsp)
+ movaps %xmm9, 0x70(%rsp)
+ movaps %xmm10, 0x80(%rsp)
+ movaps %xmm11, 0x90(%rsp)
+ movaps %xmm12, 0xa0(%rsp)
+ movaps %xmm13, 0xb0(%rsp)
+ movaps %xmm14, 0xc0(%rsp)
+ movaps %xmm15, 0xd0(%rsp)
+.Lcbc_dec_body:
+___
+$code.=<<___;
+ mov %rsp, %rbp # backup %rsp
+.cfi_def_cfa_register %rbp
+ mov 240($arg4), %eax # rounds
+ mov $arg1, $inp # backup arguments
+ mov $arg2, $out
+ mov $arg3, $len
+ mov $arg4, $key
+ mov $arg5, %rbx
+ shr \$4, $len # bytes to blocks
+
+ mov %eax, %edx # rounds
+ shl \$7, %rax # 128 bytes per inner round key
+ sub \$`128-32`, %rax # size of bit-sliced key schedule
+ sub %rax, %rsp
+
+ mov %rsp, %rax # pass key schedule
+ mov $key, %rcx # pass key
+ mov %edx, %r10d # pass rounds
+ call _bsaes_key_convert
+ pxor (%rsp),%xmm7 # fix up 0 round key
+ movdqa %xmm6,(%rax) # save last round key
+ movdqa %xmm7,(%rsp)
+
+ movdqu (%rbx), @XMM[15] # load IV
+ sub \$8,$len
+.Lcbc_dec_loop:
+ movdqu 0x00($inp), @XMM[0] # load input
+ movdqu 0x10($inp), @XMM[1]
+ movdqu 0x20($inp), @XMM[2]
+ movdqu 0x30($inp), @XMM[3]
+ movdqu 0x40($inp), @XMM[4]
+ movdqu 0x50($inp), @XMM[5]
+ mov %rsp, %rax # pass key schedule
+ movdqu 0x60($inp), @XMM[6]
+ mov %edx,%r10d # pass rounds
+ movdqu 0x70($inp), @XMM[7]
+ movdqa @XMM[15], 0x20(%rbp) # put aside IV
+
+ call _bsaes_decrypt8
+
+ pxor 0x20(%rbp), @XMM[0] # ^= IV
+ movdqu 0x00($inp), @XMM[8] # re-load input
+ movdqu 0x10($inp), @XMM[9]
+ pxor @XMM[8], @XMM[1]
+ movdqu 0x20($inp), @XMM[10]
+ pxor @XMM[9], @XMM[6]
+ movdqu 0x30($inp), @XMM[11]
+ pxor @XMM[10], @XMM[4]
+ movdqu 0x40($inp), @XMM[12]
+ pxor @XMM[11], @XMM[2]
+ movdqu 0x50($inp), @XMM[13]
+ pxor @XMM[12], @XMM[7]
+ movdqu 0x60($inp), @XMM[14]
+ pxor @XMM[13], @XMM[3]
+ movdqu 0x70($inp), @XMM[15] # IV
+ pxor @XMM[14], @XMM[5]
+ movdqu @XMM[0], 0x00($out) # write output
+ lea 0x80($inp), $inp
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[3], 0x60($out)
+ movdqu @XMM[5], 0x70($out)
+ lea 0x80($out), $out
+ sub \$8,$len
+ jnc .Lcbc_dec_loop
+
+ add \$8,$len
+ jz .Lcbc_dec_done
+
+ movdqu 0x00($inp), @XMM[0] # load input
+ mov %rsp, %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+ cmp \$2,$len
+ jb .Lcbc_dec_one
+ movdqu 0x10($inp), @XMM[1]
+ je .Lcbc_dec_two
+ movdqu 0x20($inp), @XMM[2]
+ cmp \$4,$len
+ jb .Lcbc_dec_three
+ movdqu 0x30($inp), @XMM[3]
+ je .Lcbc_dec_four
+ movdqu 0x40($inp), @XMM[4]
+ cmp \$6,$len
+ jb .Lcbc_dec_five
+ movdqu 0x50($inp), @XMM[5]
+ je .Lcbc_dec_six
+ movdqu 0x60($inp), @XMM[6]
+ movdqa @XMM[15], 0x20(%rbp) # put aside IV
+ call _bsaes_decrypt8
+ pxor 0x20(%rbp), @XMM[0] # ^= IV
+ movdqu 0x00($inp), @XMM[8] # re-load input
+ movdqu 0x10($inp), @XMM[9]
+ pxor @XMM[8], @XMM[1]
+ movdqu 0x20($inp), @XMM[10]
+ pxor @XMM[9], @XMM[6]
+ movdqu 0x30($inp), @XMM[11]
+ pxor @XMM[10], @XMM[4]
+ movdqu 0x40($inp), @XMM[12]
+ pxor @XMM[11], @XMM[2]
+ movdqu 0x50($inp), @XMM[13]
+ pxor @XMM[12], @XMM[7]
+ movdqu 0x60($inp), @XMM[15] # IV
+ pxor @XMM[13], @XMM[3]
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[3], 0x60($out)
+ jmp .Lcbc_dec_done
+.align 16
+.Lcbc_dec_six:
+ movdqa @XMM[15], 0x20(%rbp) # put aside IV
+ call _bsaes_decrypt8
+ pxor 0x20(%rbp), @XMM[0] # ^= IV
+ movdqu 0x00($inp), @XMM[8] # re-load input
+ movdqu 0x10($inp), @XMM[9]
+ pxor @XMM[8], @XMM[1]
+ movdqu 0x20($inp), @XMM[10]
+ pxor @XMM[9], @XMM[6]
+ movdqu 0x30($inp), @XMM[11]
+ pxor @XMM[10], @XMM[4]
+ movdqu 0x40($inp), @XMM[12]
+ pxor @XMM[11], @XMM[2]
+ movdqu 0x50($inp), @XMM[15] # IV
+ pxor @XMM[12], @XMM[7]
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ jmp .Lcbc_dec_done
+.align 16
+.Lcbc_dec_five:
+ movdqa @XMM[15], 0x20(%rbp) # put aside IV
+ call _bsaes_decrypt8
+ pxor 0x20(%rbp), @XMM[0] # ^= IV
+ movdqu 0x00($inp), @XMM[8] # re-load input
+ movdqu 0x10($inp), @XMM[9]
+ pxor @XMM[8], @XMM[1]
+ movdqu 0x20($inp), @XMM[10]
+ pxor @XMM[9], @XMM[6]
+ movdqu 0x30($inp), @XMM[11]
+ pxor @XMM[10], @XMM[4]
+ movdqu 0x40($inp), @XMM[15] # IV
+ pxor @XMM[11], @XMM[2]
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ jmp .Lcbc_dec_done
+.align 16
+.Lcbc_dec_four:
+ movdqa @XMM[15], 0x20(%rbp) # put aside IV
+ call _bsaes_decrypt8
+ pxor 0x20(%rbp), @XMM[0] # ^= IV
+ movdqu 0x00($inp), @XMM[8] # re-load input
+ movdqu 0x10($inp), @XMM[9]
+ pxor @XMM[8], @XMM[1]
+ movdqu 0x20($inp), @XMM[10]
+ pxor @XMM[9], @XMM[6]
+ movdqu 0x30($inp), @XMM[15] # IV
+ pxor @XMM[10], @XMM[4]
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ jmp .Lcbc_dec_done
+.align 16
+.Lcbc_dec_three:
+ movdqa @XMM[15], 0x20(%rbp) # put aside IV
+ call _bsaes_decrypt8
+ pxor 0x20(%rbp), @XMM[0] # ^= IV
+ movdqu 0x00($inp), @XMM[8] # re-load input
+ movdqu 0x10($inp), @XMM[9]
+ pxor @XMM[8], @XMM[1]
+ movdqu 0x20($inp), @XMM[15] # IV
+ pxor @XMM[9], @XMM[6]
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ jmp .Lcbc_dec_done
+.align 16
+.Lcbc_dec_two:
+ movdqa @XMM[15], 0x20(%rbp) # put aside IV
+ call _bsaes_decrypt8
+ pxor 0x20(%rbp), @XMM[0] # ^= IV
+ movdqu 0x00($inp), @XMM[8] # re-load input
+ movdqu 0x10($inp), @XMM[15] # IV
+ pxor @XMM[8], @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ jmp .Lcbc_dec_done
+.align 16
+.Lcbc_dec_one:
+ lea ($inp), $arg1
+ lea 0x20(%rbp), $arg2 # buffer output
+ lea ($key), $arg3
+ call asm_AES_decrypt # doesn't touch %xmm
+ pxor 0x20(%rbp), @XMM[15] # ^= IV
+ movdqu @XMM[15], ($out) # write output
+ movdqa @XMM[0], @XMM[15] # IV
+
+.Lcbc_dec_done:
+ movdqu @XMM[15], (%rbx) # return IV
+ lea (%rsp), %rax
+ pxor %xmm0, %xmm0
+.Lcbc_dec_bzero: # wipe key schedule [if any]
+ movdqa %xmm0, 0x00(%rax)
+ movdqa %xmm0, 0x10(%rax)
+ lea 0x20(%rax), %rax
+ cmp %rax, %rbp
+ ja .Lcbc_dec_bzero
+
+ lea 0x78(%rbp),%rax
+.cfi_def_cfa %rax,8
+___
+$code.=<<___ if ($win64);
+ movaps 0x40(%rbp), %xmm6
+ movaps 0x50(%rbp), %xmm7
+ movaps 0x60(%rbp), %xmm8
+ movaps 0x70(%rbp), %xmm9
+ movaps 0x80(%rbp), %xmm10
+ movaps 0x90(%rbp), %xmm11
+ movaps 0xa0(%rbp), %xmm12
+ movaps 0xb0(%rbp), %xmm13
+ movaps 0xc0(%rbp), %xmm14
+ movaps 0xd0(%rbp), %xmm15
+ lea 0xa0(%rax), %rax
+.Lcbc_dec_tail:
+___
+$code.=<<___;
+ mov -48(%rax), %r15
+.cfi_restore %r15
+ mov -40(%rax), %r14
+.cfi_restore %r14
+ mov -32(%rax), %r13
+.cfi_restore %r13
+ mov -24(%rax), %r12
+.cfi_restore %r12
+ mov -16(%rax), %rbx
+.cfi_restore %rbx
+ mov -8(%rax), %rbp
+.cfi_restore %rbp
+ lea (%rax), %rsp # restore %rsp
+.cfi_def_cfa_register %rsp
+.Lcbc_dec_epilogue:
+ ret
+.cfi_endproc
+.size ossl_bsaes_cbc_encrypt,.-ossl_bsaes_cbc_encrypt
+
+.globl ossl_bsaes_ctr32_encrypt_blocks
+.type ossl_bsaes_ctr32_encrypt_blocks,\@abi-omnipotent
+.align 16
+ossl_bsaes_ctr32_encrypt_blocks:
+.cfi_startproc
+ endbranch
+ mov %rsp, %rax
+.Lctr_enc_prologue:
+ push %rbp
+.cfi_push %rbp
+ push %rbx
+.cfi_push %rbx
+ push %r12
+.cfi_push %r12
+ push %r13
+.cfi_push %r13
+ push %r14
+.cfi_push %r14
+ push %r15
+.cfi_push %r15
+ lea -0x48(%rsp), %rsp
+.cfi_adjust_cfa_offset 0x48
+___
+$code.=<<___ if ($win64);
+ mov 0xa0(%rsp),$arg5 # pull ivp
+ lea -0xa0(%rsp), %rsp
+ movaps %xmm6, 0x40(%rsp)
+ movaps %xmm7, 0x50(%rsp)
+ movaps %xmm8, 0x60(%rsp)
+ movaps %xmm9, 0x70(%rsp)
+ movaps %xmm10, 0x80(%rsp)
+ movaps %xmm11, 0x90(%rsp)
+ movaps %xmm12, 0xa0(%rsp)
+ movaps %xmm13, 0xb0(%rsp)
+ movaps %xmm14, 0xc0(%rsp)
+ movaps %xmm15, 0xd0(%rsp)
+.Lctr_enc_body:
+___
+$code.=<<___;
+ mov %rsp, %rbp # backup %rsp
+.cfi_def_cfa_register %rbp
+ movdqu ($arg5), %xmm0 # load counter
+ mov 240($arg4), %eax # rounds
+ mov $arg1, $inp # backup arguments
+ mov $arg2, $out
+ mov $arg3, $len
+ mov $arg4, $key
+ movdqa %xmm0, 0x20(%rbp) # copy counter
+ cmp \$8, $arg3
+ jb .Lctr_enc_short
+
+ mov %eax, %ebx # rounds
+ shl \$7, %rax # 128 bytes per inner round key
+ sub \$`128-32`, %rax # size of bit-sliced key schedule
+ sub %rax, %rsp
+
+ mov %rsp, %rax # pass key schedule
+ mov $key, %rcx # pass key
+ mov %ebx, %r10d # pass rounds
+ call _bsaes_key_convert
+ pxor %xmm6,%xmm7 # fix up last round key
+ movdqa %xmm7,(%rax) # save last round key
+
+ movdqa (%rsp), @XMM[9] # load round0 key
+ lea .LADD1(%rip), %r11
+ movdqa 0x20(%rbp), @XMM[0] # counter copy
+ movdqa -0x20(%r11), @XMM[8] # .LSWPUP
+ pshufb @XMM[8], @XMM[9] # byte swap upper part
+ pshufb @XMM[8], @XMM[0]
+ movdqa @XMM[9], (%rsp) # save adjusted round0 key
+ jmp .Lctr_enc_loop
+.align 16
+.Lctr_enc_loop:
+ movdqa @XMM[0], 0x20(%rbp) # save counter
+ movdqa @XMM[0], @XMM[1] # prepare 8 counter values
+ movdqa @XMM[0], @XMM[2]
+ paddd 0x00(%r11), @XMM[1] # .LADD1
+ movdqa @XMM[0], @XMM[3]
+ paddd 0x10(%r11), @XMM[2] # .LADD2
+ movdqa @XMM[0], @XMM[4]
+ paddd 0x20(%r11), @XMM[3] # .LADD3
+ movdqa @XMM[0], @XMM[5]
+ paddd 0x30(%r11), @XMM[4] # .LADD4
+ movdqa @XMM[0], @XMM[6]
+ paddd 0x40(%r11), @XMM[5] # .LADD5
+ movdqa @XMM[0], @XMM[7]
+ paddd 0x50(%r11), @XMM[6] # .LADD6
+ paddd 0x60(%r11), @XMM[7] # .LADD7
+
+ # Borrow prologue from _bsaes_encrypt8 to use the opportunity
+ # to flip byte order in 32-bit counter
+ movdqa (%rsp), @XMM[9] # round 0 key
+ lea 0x10(%rsp), %rax # pass key schedule
+ movdqa -0x10(%r11), @XMM[8] # .LSWPUPM0SR
+ pxor @XMM[9], @XMM[0] # xor with round0 key
+ pxor @XMM[9], @XMM[1]
+ pxor @XMM[9], @XMM[2]
+ pxor @XMM[9], @XMM[3]
+ pshufb @XMM[8], @XMM[0]
+ pshufb @XMM[8], @XMM[1]
+ pxor @XMM[9], @XMM[4]
+ pxor @XMM[9], @XMM[5]
+ pshufb @XMM[8], @XMM[2]
+ pshufb @XMM[8], @XMM[3]
+ pxor @XMM[9], @XMM[6]
+ pxor @XMM[9], @XMM[7]
+ pshufb @XMM[8], @XMM[4]
+ pshufb @XMM[8], @XMM[5]
+ pshufb @XMM[8], @XMM[6]
+ pshufb @XMM[8], @XMM[7]
+ lea .LBS0(%rip), %r11 # constants table
+ mov %ebx,%r10d # pass rounds
+
+ call _bsaes_encrypt8_bitslice
+
+ sub \$8,$len
+ jc .Lctr_enc_loop_done
+
+ movdqu 0x00($inp), @XMM[8] # load input
+ movdqu 0x10($inp), @XMM[9]
+ movdqu 0x20($inp), @XMM[10]
+ movdqu 0x30($inp), @XMM[11]
+ movdqu 0x40($inp), @XMM[12]
+ movdqu 0x50($inp), @XMM[13]
+ movdqu 0x60($inp), @XMM[14]
+ movdqu 0x70($inp), @XMM[15]
+ lea 0x80($inp),$inp
+ pxor @XMM[0], @XMM[8]
+ movdqa 0x20(%rbp), @XMM[0] # load counter
+ pxor @XMM[9], @XMM[1]
+ movdqu @XMM[8], 0x00($out) # write output
+ pxor @XMM[10], @XMM[4]
+ movdqu @XMM[1], 0x10($out)
+ pxor @XMM[11], @XMM[6]
+ movdqu @XMM[4], 0x20($out)
+ pxor @XMM[12], @XMM[3]
+ movdqu @XMM[6], 0x30($out)
+ pxor @XMM[13], @XMM[7]
+ movdqu @XMM[3], 0x40($out)
+ pxor @XMM[14], @XMM[2]
+ movdqu @XMM[7], 0x50($out)
+ pxor @XMM[15], @XMM[5]
+ movdqu @XMM[2], 0x60($out)
+ lea .LADD1(%rip), %r11
+ movdqu @XMM[5], 0x70($out)
+ lea 0x80($out), $out
+ paddd 0x70(%r11), @XMM[0] # .LADD8
+ jnz .Lctr_enc_loop
+
+ jmp .Lctr_enc_done
+.align 16
+.Lctr_enc_loop_done:
+ add \$8, $len
+ movdqu 0x00($inp), @XMM[8] # load input
+ pxor @XMM[8], @XMM[0]
+ movdqu @XMM[0], 0x00($out) # write output
+ cmp \$2,$len
+ jb .Lctr_enc_done
+ movdqu 0x10($inp), @XMM[9]
+ pxor @XMM[9], @XMM[1]
+ movdqu @XMM[1], 0x10($out)
+ je .Lctr_enc_done
+ movdqu 0x20($inp), @XMM[10]
+ pxor @XMM[10], @XMM[4]
+ movdqu @XMM[4], 0x20($out)
+ cmp \$4,$len
+ jb .Lctr_enc_done
+ movdqu 0x30($inp), @XMM[11]
+ pxor @XMM[11], @XMM[6]
+ movdqu @XMM[6], 0x30($out)
+ je .Lctr_enc_done
+ movdqu 0x40($inp), @XMM[12]
+ pxor @XMM[12], @XMM[3]
+ movdqu @XMM[3], 0x40($out)
+ cmp \$6,$len
+ jb .Lctr_enc_done
+ movdqu 0x50($inp), @XMM[13]
+ pxor @XMM[13], @XMM[7]
+ movdqu @XMM[7], 0x50($out)
+ je .Lctr_enc_done
+ movdqu 0x60($inp), @XMM[14]
+ pxor @XMM[14], @XMM[2]
+ movdqu @XMM[2], 0x60($out)
+ jmp .Lctr_enc_done
+
+.align 16
+.Lctr_enc_short:
+ lea 0x20(%rbp), $arg1
+ lea 0x30(%rbp), $arg2
+ lea ($key), $arg3
+ call asm_AES_encrypt
+ movdqu ($inp), @XMM[1]
+ lea 16($inp), $inp
+ mov 0x2c(%rbp), %eax # load 32-bit counter
+ bswap %eax
+ pxor 0x30(%rbp), @XMM[1]
+ inc %eax # increment
+ movdqu @XMM[1], ($out)
+ bswap %eax
+ lea 16($out), $out
+ mov %eax, 0x2c(%rsp) # save 32-bit counter
+ dec $len
+ jnz .Lctr_enc_short
+
+.Lctr_enc_done:
+ lea (%rsp), %rax
+ pxor %xmm0, %xmm0
+.Lctr_enc_bzero: # wipe key schedule [if any]
+ movdqa %xmm0, 0x00(%rax)
+ movdqa %xmm0, 0x10(%rax)
+ lea 0x20(%rax), %rax
+ cmp %rax, %rbp
+ ja .Lctr_enc_bzero
+
+ lea 0x78(%rbp),%rax
+.cfi_def_cfa %rax,8
+___
+$code.=<<___ if ($win64);
+ movaps 0x40(%rbp), %xmm6
+ movaps 0x50(%rbp), %xmm7
+ movaps 0x60(%rbp), %xmm8
+ movaps 0x70(%rbp), %xmm9
+ movaps 0x80(%rbp), %xmm10
+ movaps 0x90(%rbp), %xmm11
+ movaps 0xa0(%rbp), %xmm12
+ movaps 0xb0(%rbp), %xmm13
+ movaps 0xc0(%rbp), %xmm14
+ movaps 0xd0(%rbp), %xmm15
+ lea 0xa0(%rax), %rax
+.Lctr_enc_tail:
+___
+$code.=<<___;
+ mov -48(%rax), %r15
+.cfi_restore %r15
+ mov -40(%rax), %r14
+.cfi_restore %r14
+ mov -32(%rax), %r13
+.cfi_restore %r13
+ mov -24(%rax), %r12
+.cfi_restore %r12
+ mov -16(%rax), %rbx
+.cfi_restore %rbx
+ mov -8(%rax), %rbp
+.cfi_restore %rbp
+ lea (%rax), %rsp # restore %rsp
+.cfi_def_cfa_register %rsp
+.Lctr_enc_epilogue:
+ ret
+.cfi_endproc
+.size ossl_bsaes_ctr32_encrypt_blocks,.-ossl_bsaes_ctr32_encrypt_blocks
+___
+######################################################################
+# void bsaes_xts_[en|de]crypt(const char *inp,char *out,size_t len,
+# const AES_KEY *key1, const AES_KEY *key2,
+# const unsigned char iv[16]);
+#
+my ($twmask,$twres,$twtmp)=@XMM[13..15];
+$arg6=~s/d$//;
+
+$code.=<<___;
+.globl ossl_bsaes_xts_encrypt
+.type ossl_bsaes_xts_encrypt,\@abi-omnipotent
+.align 16
+ossl_bsaes_xts_encrypt:
+.cfi_startproc
+ mov %rsp, %rax
+.Lxts_enc_prologue:
+ push %rbp
+.cfi_push %rbp
+ push %rbx
+.cfi_push %rbx
+ push %r12
+.cfi_push %r12
+ push %r13
+.cfi_push %r13
+ push %r14
+.cfi_push %r14
+ push %r15
+.cfi_push %r15
+ lea -0x48(%rsp), %rsp
+.cfi_adjust_cfa_offset 0x48
+___
+$code.=<<___ if ($win64);
+ mov 0xa0(%rsp),$arg5 # pull key2
+ mov 0xa8(%rsp),$arg6 # pull ivp
+ lea -0xa0(%rsp), %rsp
+ movaps %xmm6, 0x40(%rsp)
+ movaps %xmm7, 0x50(%rsp)
+ movaps %xmm8, 0x60(%rsp)
+ movaps %xmm9, 0x70(%rsp)
+ movaps %xmm10, 0x80(%rsp)
+ movaps %xmm11, 0x90(%rsp)
+ movaps %xmm12, 0xa0(%rsp)
+ movaps %xmm13, 0xb0(%rsp)
+ movaps %xmm14, 0xc0(%rsp)
+ movaps %xmm15, 0xd0(%rsp)
+.Lxts_enc_body:
+___
+$code.=<<___;
+ mov %rsp, %rbp # backup %rsp
+.cfi_def_cfa_register %rbp
+ mov $arg1, $inp # backup arguments
+ mov $arg2, $out
+ mov $arg3, $len
+ mov $arg4, $key
+
+ lea ($arg6), $arg1
+ lea 0x20(%rbp), $arg2
+ lea ($arg5), $arg3
+ call asm_AES_encrypt # generate initial tweak
+
+ mov 240($key), %eax # rounds
+ mov $len, %rbx # backup $len
+
+ mov %eax, %edx # rounds
+ shl \$7, %rax # 128 bytes per inner round key
+ sub \$`128-32`, %rax # size of bit-sliced key schedule
+ sub %rax, %rsp
+
+ mov %rsp, %rax # pass key schedule
+ mov $key, %rcx # pass key
+ mov %edx, %r10d # pass rounds
+ call _bsaes_key_convert
+ pxor %xmm6, %xmm7 # fix up last round key
+ movdqa %xmm7, (%rax) # save last round key
+
+ and \$-16, $len
+ sub \$0x80, %rsp # place for tweak[8]
+ movdqa 0x20(%rbp), @XMM[7] # initial tweak
+
+ pxor $twtmp, $twtmp
+ movdqa .Lxts_magic(%rip), $twmask
+ pcmpgtd @XMM[7], $twtmp # broadcast upper bits
+
+ sub \$0x80, $len
+ jc .Lxts_enc_short
+ jmp .Lxts_enc_loop
+
+.align 16
+.Lxts_enc_loop:
+___
+ for ($i=0;$i<7;$i++) {
+ $code.=<<___;
+ pshufd \$0x13, $twtmp, $twres
+ pxor $twtmp, $twtmp
+ movdqa @XMM[7], @XMM[$i]
+ movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i]
+ paddq @XMM[7], @XMM[7] # psllq 1,$tweak
+ pand $twmask, $twres # isolate carry and residue
+ pcmpgtd @XMM[7], $twtmp # broadcast upper bits
+ pxor $twres, @XMM[7]
+___
+ $code.=<<___ if ($i>=1);
+ movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1]
+___
+ $code.=<<___ if ($i>=2);
+ pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[]
+___
+ }
+$code.=<<___;
+ movdqu 0x60($inp), @XMM[8+6]
+ pxor @XMM[8+5], @XMM[5]
+ movdqu 0x70($inp), @XMM[8+7]
+ lea 0x80($inp), $inp
+ movdqa @XMM[7], 0x70(%rsp)
+ pxor @XMM[8+6], @XMM[6]
+ lea 0x80(%rsp), %rax # pass key schedule
+ pxor @XMM[8+7], @XMM[7]
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_encrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[4]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[6]
+ movdqu @XMM[4], 0x20($out)
+ pxor 0x40(%rsp), @XMM[3]
+ movdqu @XMM[6], 0x30($out)
+ pxor 0x50(%rsp), @XMM[7]
+ movdqu @XMM[3], 0x40($out)
+ pxor 0x60(%rsp), @XMM[2]
+ movdqu @XMM[7], 0x50($out)
+ pxor 0x70(%rsp), @XMM[5]
+ movdqu @XMM[2], 0x60($out)
+ movdqu @XMM[5], 0x70($out)
+ lea 0x80($out), $out
+
+ movdqa 0x70(%rsp), @XMM[7] # prepare next iteration tweak
+ pxor $twtmp, $twtmp
+ movdqa .Lxts_magic(%rip), $twmask
+ pcmpgtd @XMM[7], $twtmp
+ pshufd \$0x13, $twtmp, $twres
+ pxor $twtmp, $twtmp
+ paddq @XMM[7], @XMM[7] # psllq 1,$tweak
+ pand $twmask, $twres # isolate carry and residue
+ pcmpgtd @XMM[7], $twtmp # broadcast upper bits
+ pxor $twres, @XMM[7]
+
+ sub \$0x80,$len
+ jnc .Lxts_enc_loop
+
+.Lxts_enc_short:
+ add \$0x80, $len
+ jz .Lxts_enc_done
+___
+ for ($i=0;$i<7;$i++) {
+ $code.=<<___;
+ pshufd \$0x13, $twtmp, $twres
+ pxor $twtmp, $twtmp
+ movdqa @XMM[7], @XMM[$i]
+ movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i]
+ paddq @XMM[7], @XMM[7] # psllq 1,$tweak
+ pand $twmask, $twres # isolate carry and residue
+ pcmpgtd @XMM[7], $twtmp # broadcast upper bits
+ pxor $twres, @XMM[7]
+___
+ $code.=<<___ if ($i>=1);
+ movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1]
+ cmp \$`0x10*$i`,$len
+ je .Lxts_enc_$i
+___
+ $code.=<<___ if ($i>=2);
+ pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[]
+___
+ }
+$code.=<<___;
+ movdqu 0x60($inp), @XMM[8+6]
+ pxor @XMM[8+5], @XMM[5]
+ movdqa @XMM[7], 0x70(%rsp)
+ lea 0x70($inp), $inp
+ pxor @XMM[8+6], @XMM[6]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_encrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[4]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[6]
+ movdqu @XMM[4], 0x20($out)
+ pxor 0x40(%rsp), @XMM[3]
+ movdqu @XMM[6], 0x30($out)
+ pxor 0x50(%rsp), @XMM[7]
+ movdqu @XMM[3], 0x40($out)
+ pxor 0x60(%rsp), @XMM[2]
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[2], 0x60($out)
+ lea 0x70($out), $out
+
+ movdqa 0x70(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_enc_done
+.align 16
+.Lxts_enc_6:
+ pxor @XMM[8+4], @XMM[4]
+ lea 0x60($inp), $inp
+ pxor @XMM[8+5], @XMM[5]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_encrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[4]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[6]
+ movdqu @XMM[4], 0x20($out)
+ pxor 0x40(%rsp), @XMM[3]
+ movdqu @XMM[6], 0x30($out)
+ pxor 0x50(%rsp), @XMM[7]
+ movdqu @XMM[3], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ lea 0x60($out), $out
+
+ movdqa 0x60(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_enc_done
+.align 16
+.Lxts_enc_5:
+ pxor @XMM[8+3], @XMM[3]
+ lea 0x50($inp), $inp
+ pxor @XMM[8+4], @XMM[4]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_encrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[4]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[6]
+ movdqu @XMM[4], 0x20($out)
+ pxor 0x40(%rsp), @XMM[3]
+ movdqu @XMM[6], 0x30($out)
+ movdqu @XMM[3], 0x40($out)
+ lea 0x50($out), $out
+
+ movdqa 0x50(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_enc_done
+.align 16
+.Lxts_enc_4:
+ pxor @XMM[8+2], @XMM[2]
+ lea 0x40($inp), $inp
+ pxor @XMM[8+3], @XMM[3]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_encrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[4]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[6]
+ movdqu @XMM[4], 0x20($out)
+ movdqu @XMM[6], 0x30($out)
+ lea 0x40($out), $out
+
+ movdqa 0x40(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_enc_done
+.align 16
+.Lxts_enc_3:
+ pxor @XMM[8+1], @XMM[1]
+ lea 0x30($inp), $inp
+ pxor @XMM[8+2], @XMM[2]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_encrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[4]
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[4], 0x20($out)
+ lea 0x30($out), $out
+
+ movdqa 0x30(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_enc_done
+.align 16
+.Lxts_enc_2:
+ pxor @XMM[8+0], @XMM[0]
+ lea 0x20($inp), $inp
+ pxor @XMM[8+1], @XMM[1]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_encrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ lea 0x20($out), $out
+
+ movdqa 0x20(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_enc_done
+.align 16
+.Lxts_enc_1:
+ pxor @XMM[0], @XMM[8]
+ lea 0x10($inp), $inp
+ movdqa @XMM[8], 0x20(%rbp)
+ lea 0x20(%rbp), $arg1
+ lea 0x20(%rbp), $arg2
+ lea ($key), $arg3
+ call asm_AES_encrypt # doesn't touch %xmm
+ pxor 0x20(%rbp), @XMM[0] # ^= tweak[]
+ #pxor @XMM[8], @XMM[0]
+ #lea 0x80(%rsp), %rax # pass key schedule
+ #mov %edx, %r10d # pass rounds
+ #call _bsaes_encrypt8
+ #pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ movdqu @XMM[0], 0x00($out) # write output
+ lea 0x10($out), $out
+
+ movdqa 0x10(%rsp), @XMM[7] # next iteration tweak
+
+.Lxts_enc_done:
+ and \$15, %ebx
+ jz .Lxts_enc_ret
+ mov $out, %rdx
+
+.Lxts_enc_steal:
+ movzb ($inp), %eax
+ movzb -16(%rdx), %ecx
+ lea 1($inp), $inp
+ mov %al, -16(%rdx)
+ mov %cl, 0(%rdx)
+ lea 1(%rdx), %rdx
+ sub \$1,%ebx
+ jnz .Lxts_enc_steal
+
+ movdqu -16($out), @XMM[0]
+ lea 0x20(%rbp), $arg1
+ pxor @XMM[7], @XMM[0]
+ lea 0x20(%rbp), $arg2
+ movdqa @XMM[0], 0x20(%rbp)
+ lea ($key), $arg3
+ call asm_AES_encrypt # doesn't touch %xmm
+ pxor 0x20(%rbp), @XMM[7]
+ movdqu @XMM[7], -16($out)
+
+.Lxts_enc_ret:
+ lea (%rsp), %rax
+ pxor %xmm0, %xmm0
+.Lxts_enc_bzero: # wipe key schedule [if any]
+ movdqa %xmm0, 0x00(%rax)
+ movdqa %xmm0, 0x10(%rax)
+ lea 0x20(%rax), %rax
+ cmp %rax, %rbp
+ ja .Lxts_enc_bzero
+
+ lea 0x78(%rbp),%rax
+.cfi_def_cfa %rax,8
+___
+$code.=<<___ if ($win64);
+ movaps 0x40(%rbp), %xmm6
+ movaps 0x50(%rbp), %xmm7
+ movaps 0x60(%rbp), %xmm8
+ movaps 0x70(%rbp), %xmm9
+ movaps 0x80(%rbp), %xmm10
+ movaps 0x90(%rbp), %xmm11
+ movaps 0xa0(%rbp), %xmm12
+ movaps 0xb0(%rbp), %xmm13
+ movaps 0xc0(%rbp), %xmm14
+ movaps 0xd0(%rbp), %xmm15
+ lea 0xa0(%rax), %rax
+.Lxts_enc_tail:
+___
+$code.=<<___;
+ mov -48(%rax), %r15
+.cfi_restore %r15
+ mov -40(%rax), %r14
+.cfi_restore %r14
+ mov -32(%rax), %r13
+.cfi_restore %r13
+ mov -24(%rax), %r12
+.cfi_restore %r12
+ mov -16(%rax), %rbx
+.cfi_restore %rbx
+ mov -8(%rax), %rbp
+.cfi_restore %rbp
+ lea (%rax), %rsp # restore %rsp
+.cfi_def_cfa_register %rsp
+.Lxts_enc_epilogue:
+ ret
+.cfi_endproc
+.size ossl_bsaes_xts_encrypt,.-ossl_bsaes_xts_encrypt
+
+.globl ossl_bsaes_xts_decrypt
+.type ossl_bsaes_xts_decrypt,\@abi-omnipotent
+.align 16
+ossl_bsaes_xts_decrypt:
+.cfi_startproc
+ mov %rsp, %rax
+.Lxts_dec_prologue:
+ push %rbp
+.cfi_push %rbp
+ push %rbx
+.cfi_push %rbx
+ push %r12
+.cfi_push %r12
+ push %r13
+.cfi_push %r13
+ push %r14
+.cfi_push %r14
+ push %r15
+.cfi_push %r15
+ lea -0x48(%rsp), %rsp
+.cfi_adjust_cfa_offset 0x48
+___
+$code.=<<___ if ($win64);
+ mov 0xa0(%rsp),$arg5 # pull key2
+ mov 0xa8(%rsp),$arg6 # pull ivp
+ lea -0xa0(%rsp), %rsp
+ movaps %xmm6, 0x40(%rsp)
+ movaps %xmm7, 0x50(%rsp)
+ movaps %xmm8, 0x60(%rsp)
+ movaps %xmm9, 0x70(%rsp)
+ movaps %xmm10, 0x80(%rsp)
+ movaps %xmm11, 0x90(%rsp)
+ movaps %xmm12, 0xa0(%rsp)
+ movaps %xmm13, 0xb0(%rsp)
+ movaps %xmm14, 0xc0(%rsp)
+ movaps %xmm15, 0xd0(%rsp)
+.Lxts_dec_body:
+___
+$code.=<<___;
+ mov %rsp, %rbp # backup %rsp
+ mov $arg1, $inp # backup arguments
+ mov $arg2, $out
+ mov $arg3, $len
+ mov $arg4, $key
+
+ lea ($arg6), $arg1
+ lea 0x20(%rbp), $arg2
+ lea ($arg5), $arg3
+ call asm_AES_encrypt # generate initial tweak
+
+ mov 240($key), %eax # rounds
+ mov $len, %rbx # backup $len
+
+ mov %eax, %edx # rounds
+ shl \$7, %rax # 128 bytes per inner round key
+ sub \$`128-32`, %rax # size of bit-sliced key schedule
+ sub %rax, %rsp
+
+ mov %rsp, %rax # pass key schedule
+ mov $key, %rcx # pass key
+ mov %edx, %r10d # pass rounds
+ call _bsaes_key_convert
+ pxor (%rsp), %xmm7 # fix up round 0 key
+ movdqa %xmm6, (%rax) # save last round key
+ movdqa %xmm7, (%rsp)
+
+ xor %eax, %eax # if ($len%16) len-=16;
+ and \$-16, $len
+ test \$15, %ebx
+ setnz %al
+ shl \$4, %rax
+ sub %rax, $len
+
+ sub \$0x80, %rsp # place for tweak[8]
+ movdqa 0x20(%rbp), @XMM[7] # initial tweak
+
+ pxor $twtmp, $twtmp
+ movdqa .Lxts_magic(%rip), $twmask
+ pcmpgtd @XMM[7], $twtmp # broadcast upper bits
+
+ sub \$0x80, $len
+ jc .Lxts_dec_short
+ jmp .Lxts_dec_loop
+
+.align 16
+.Lxts_dec_loop:
+___
+ for ($i=0;$i<7;$i++) {
+ $code.=<<___;
+ pshufd \$0x13, $twtmp, $twres
+ pxor $twtmp, $twtmp
+ movdqa @XMM[7], @XMM[$i]
+ movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i]
+ paddq @XMM[7], @XMM[7] # psllq 1,$tweak
+ pand $twmask, $twres # isolate carry and residue
+ pcmpgtd @XMM[7], $twtmp # broadcast upper bits
+ pxor $twres, @XMM[7]
+___
+ $code.=<<___ if ($i>=1);
+ movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1]
+___
+ $code.=<<___ if ($i>=2);
+ pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[]
+___
+ }
+$code.=<<___;
+ movdqu 0x60($inp), @XMM[8+6]
+ pxor @XMM[8+5], @XMM[5]
+ movdqu 0x70($inp), @XMM[8+7]
+ lea 0x80($inp), $inp
+ movdqa @XMM[7], 0x70(%rsp)
+ pxor @XMM[8+6], @XMM[6]
+ lea 0x80(%rsp), %rax # pass key schedule
+ pxor @XMM[8+7], @XMM[7]
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_decrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[6]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[4]
+ movdqu @XMM[6], 0x20($out)
+ pxor 0x40(%rsp), @XMM[2]
+ movdqu @XMM[4], 0x30($out)
+ pxor 0x50(%rsp), @XMM[7]
+ movdqu @XMM[2], 0x40($out)
+ pxor 0x60(%rsp), @XMM[3]
+ movdqu @XMM[7], 0x50($out)
+ pxor 0x70(%rsp), @XMM[5]
+ movdqu @XMM[3], 0x60($out)
+ movdqu @XMM[5], 0x70($out)
+ lea 0x80($out), $out
+
+ movdqa 0x70(%rsp), @XMM[7] # prepare next iteration tweak
+ pxor $twtmp, $twtmp
+ movdqa .Lxts_magic(%rip), $twmask
+ pcmpgtd @XMM[7], $twtmp
+ pshufd \$0x13, $twtmp, $twres
+ pxor $twtmp, $twtmp
+ paddq @XMM[7], @XMM[7] # psllq 1,$tweak
+ pand $twmask, $twres # isolate carry and residue
+ pcmpgtd @XMM[7], $twtmp # broadcast upper bits
+ pxor $twres, @XMM[7]
+
+ sub \$0x80,$len
+ jnc .Lxts_dec_loop
+
+.Lxts_dec_short:
+ add \$0x80, $len
+ jz .Lxts_dec_done
+___
+ for ($i=0;$i<7;$i++) {
+ $code.=<<___;
+ pshufd \$0x13, $twtmp, $twres
+ pxor $twtmp, $twtmp
+ movdqa @XMM[7], @XMM[$i]
+ movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i]
+ paddq @XMM[7], @XMM[7] # psllq 1,$tweak
+ pand $twmask, $twres # isolate carry and residue
+ pcmpgtd @XMM[7], $twtmp # broadcast upper bits
+ pxor $twres, @XMM[7]
+___
+ $code.=<<___ if ($i>=1);
+ movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1]
+ cmp \$`0x10*$i`,$len
+ je .Lxts_dec_$i
+___
+ $code.=<<___ if ($i>=2);
+ pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[]
+___
+ }
+$code.=<<___;
+ movdqu 0x60($inp), @XMM[8+6]
+ pxor @XMM[8+5], @XMM[5]
+ movdqa @XMM[7], 0x70(%rsp)
+ lea 0x70($inp), $inp
+ pxor @XMM[8+6], @XMM[6]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_decrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[6]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[4]
+ movdqu @XMM[6], 0x20($out)
+ pxor 0x40(%rsp), @XMM[2]
+ movdqu @XMM[4], 0x30($out)
+ pxor 0x50(%rsp), @XMM[7]
+ movdqu @XMM[2], 0x40($out)
+ pxor 0x60(%rsp), @XMM[3]
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[3], 0x60($out)
+ lea 0x70($out), $out
+
+ movdqa 0x70(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_dec_done
+.align 16
+.Lxts_dec_6:
+ pxor @XMM[8+4], @XMM[4]
+ lea 0x60($inp), $inp
+ pxor @XMM[8+5], @XMM[5]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_decrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[6]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[4]
+ movdqu @XMM[6], 0x20($out)
+ pxor 0x40(%rsp), @XMM[2]
+ movdqu @XMM[4], 0x30($out)
+ pxor 0x50(%rsp), @XMM[7]
+ movdqu @XMM[2], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ lea 0x60($out), $out
+
+ movdqa 0x60(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_dec_done
+.align 16
+.Lxts_dec_5:
+ pxor @XMM[8+3], @XMM[3]
+ lea 0x50($inp), $inp
+ pxor @XMM[8+4], @XMM[4]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_decrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[6]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[4]
+ movdqu @XMM[6], 0x20($out)
+ pxor 0x40(%rsp), @XMM[2]
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ lea 0x50($out), $out
+
+ movdqa 0x50(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_dec_done
+.align 16
+.Lxts_dec_4:
+ pxor @XMM[8+2], @XMM[2]
+ lea 0x40($inp), $inp
+ pxor @XMM[8+3], @XMM[3]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_decrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[6]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[4]
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ lea 0x40($out), $out
+
+ movdqa 0x40(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_dec_done
+.align 16
+.Lxts_dec_3:
+ pxor @XMM[8+1], @XMM[1]
+ lea 0x30($inp), $inp
+ pxor @XMM[8+2], @XMM[2]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_decrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[6]
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ lea 0x30($out), $out
+
+ movdqa 0x30(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_dec_done
+.align 16
+.Lxts_dec_2:
+ pxor @XMM[8+0], @XMM[0]
+ lea 0x20($inp), $inp
+ pxor @XMM[8+1], @XMM[1]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_decrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ lea 0x20($out), $out
+
+ movdqa 0x20(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_dec_done
+.align 16
+.Lxts_dec_1:
+ pxor @XMM[0], @XMM[8]
+ lea 0x10($inp), $inp
+ movdqa @XMM[8], 0x20(%rbp)
+ lea 0x20(%rbp), $arg1
+ lea 0x20(%rbp), $arg2
+ lea ($key), $arg3
+ call asm_AES_decrypt # doesn't touch %xmm
+ pxor 0x20(%rbp), @XMM[0] # ^= tweak[]
+ #pxor @XMM[8], @XMM[0]
+ #lea 0x80(%rsp), %rax # pass key schedule
+ #mov %edx, %r10d # pass rounds
+ #call _bsaes_decrypt8
+ #pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ movdqu @XMM[0], 0x00($out) # write output
+ lea 0x10($out), $out
+
+ movdqa 0x10(%rsp), @XMM[7] # next iteration tweak
+
+.Lxts_dec_done:
+ and \$15, %ebx
+ jz .Lxts_dec_ret
+
+ pxor $twtmp, $twtmp
+ movdqa .Lxts_magic(%rip), $twmask
+ pcmpgtd @XMM[7], $twtmp
+ pshufd \$0x13, $twtmp, $twres
+ movdqa @XMM[7], @XMM[6]
+ paddq @XMM[7], @XMM[7] # psllq 1,$tweak
+ pand $twmask, $twres # isolate carry and residue
+ movdqu ($inp), @XMM[0]
+ pxor $twres, @XMM[7]
+
+ lea 0x20(%rbp), $arg1
+ pxor @XMM[7], @XMM[0]
+ lea 0x20(%rbp), $arg2
+ movdqa @XMM[0], 0x20(%rbp)
+ lea ($key), $arg3
+ call asm_AES_decrypt # doesn't touch %xmm
+ pxor 0x20(%rbp), @XMM[7]
+ mov $out, %rdx
+ movdqu @XMM[7], ($out)
+
+.Lxts_dec_steal:
+ movzb 16($inp), %eax
+ movzb (%rdx), %ecx
+ lea 1($inp), $inp
+ mov %al, (%rdx)
+ mov %cl, 16(%rdx)
+ lea 1(%rdx), %rdx
+ sub \$1,%ebx
+ jnz .Lxts_dec_steal
+
+ movdqu ($out), @XMM[0]
+ lea 0x20(%rbp), $arg1
+ pxor @XMM[6], @XMM[0]
+ lea 0x20(%rbp), $arg2
+ movdqa @XMM[0], 0x20(%rbp)
+ lea ($key), $arg3
+ call asm_AES_decrypt # doesn't touch %xmm
+ pxor 0x20(%rbp), @XMM[6]
+ movdqu @XMM[6], ($out)
+
+.Lxts_dec_ret:
+ lea (%rsp), %rax
+ pxor %xmm0, %xmm0
+.Lxts_dec_bzero: # wipe key schedule [if any]
+ movdqa %xmm0, 0x00(%rax)
+ movdqa %xmm0, 0x10(%rax)
+ lea 0x20(%rax), %rax
+ cmp %rax, %rbp
+ ja .Lxts_dec_bzero
+
+ lea 0x78(%rbp),%rax
+.cfi_def_cfa %rax,8
+___
+$code.=<<___ if ($win64);
+ movaps 0x40(%rbp), %xmm6
+ movaps 0x50(%rbp), %xmm7
+ movaps 0x60(%rbp), %xmm8
+ movaps 0x70(%rbp), %xmm9
+ movaps 0x80(%rbp), %xmm10
+ movaps 0x90(%rbp), %xmm11
+ movaps 0xa0(%rbp), %xmm12
+ movaps 0xb0(%rbp), %xmm13
+ movaps 0xc0(%rbp), %xmm14
+ movaps 0xd0(%rbp), %xmm15
+ lea 0xa0(%rax), %rax
+.Lxts_dec_tail:
+___
+$code.=<<___;
+ mov -48(%rax), %r15
+.cfi_restore %r15
+ mov -40(%rax), %r14
+.cfi_restore %r14
+ mov -32(%rax), %r13
+.cfi_restore %r13
+ mov -24(%rax), %r12
+.cfi_restore %r12
+ mov -16(%rax), %rbx
+.cfi_restore %rbx
+ mov -8(%rax), %rbp
+.cfi_restore %rbp
+ lea (%rax), %rsp # restore %rsp
+.cfi_def_cfa_register %rsp
+.Lxts_dec_epilogue:
+ ret
+.cfi_endproc
+.size ossl_bsaes_xts_decrypt,.-ossl_bsaes_xts_decrypt
+___
+}
+$code.=<<___;
+.type _bsaes_const,\@object
+.align 64
+_bsaes_const:
+.LM0ISR: # InvShiftRows constants
+ .quad 0x0a0e0206070b0f03, 0x0004080c0d010509
+.LISRM0:
+ .quad 0x01040b0e0205080f, 0x0306090c00070a0d
+.LISR:
+ .quad 0x0504070602010003, 0x0f0e0d0c080b0a09
+.LBS0: # bit-slice constants
+ .quad 0x5555555555555555, 0x5555555555555555
+.LBS1:
+ .quad 0x3333333333333333, 0x3333333333333333
+.LBS2:
+ .quad 0x0f0f0f0f0f0f0f0f, 0x0f0f0f0f0f0f0f0f
+.LSR: # shiftrows constants
+ .quad 0x0504070600030201, 0x0f0e0d0c0a09080b
+.LSRM0:
+ .quad 0x0304090e00050a0f, 0x01060b0c0207080d
+.LM0SR:
+ .quad 0x0a0e02060f03070b, 0x0004080c05090d01
+.LSWPUP: # byte-swap upper dword
+ .quad 0x0706050403020100, 0x0c0d0e0f0b0a0908
+.LSWPUPM0SR:
+ .quad 0x0a0d02060c03070b, 0x0004080f05090e01
+.LADD1: # counter increment constants
+ .quad 0x0000000000000000, 0x0000000100000000
+.LADD2:
+ .quad 0x0000000000000000, 0x0000000200000000
+.LADD3:
+ .quad 0x0000000000000000, 0x0000000300000000
+.LADD4:
+ .quad 0x0000000000000000, 0x0000000400000000
+.LADD5:
+ .quad 0x0000000000000000, 0x0000000500000000
+.LADD6:
+ .quad 0x0000000000000000, 0x0000000600000000
+.LADD7:
+ .quad 0x0000000000000000, 0x0000000700000000
+.LADD8:
+ .quad 0x0000000000000000, 0x0000000800000000
+.Lxts_magic:
+ .long 0x87,0,1,0
+.Lmasks:
+ .quad 0x0101010101010101, 0x0101010101010101
+ .quad 0x0202020202020202, 0x0202020202020202
+ .quad 0x0404040404040404, 0x0404040404040404
+ .quad 0x0808080808080808, 0x0808080808080808
+.LM0:
+ .quad 0x02060a0e03070b0f, 0x0004080c0105090d
+.L63:
+ .quad 0x6363636363636363, 0x6363636363636363
+.asciz "Bit-sliced AES for x86_64/SSSE3, Emilia Käsper, Peter Schwabe, Andy Polyakov"
+.align 64
+.size _bsaes_const,.-_bsaes_const
+___
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+.type se_handler,\@abi-omnipotent
+.align 16
+se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<=prologue label
+ jbe .Lin_prologue
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lin_prologue
+
+ mov 8(%r11),%r10d # HandlerData[2]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=tail label
+ jae .Lin_tail
+
+ mov 160($context),%rax # pull context->Rbp
+
+ lea 0x40(%rax),%rsi # %xmm save area
+ lea 512($context),%rdi # &context.Xmm6
+ mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax)
+ .long 0xa548f3fc # cld; rep movsq
+ lea 0xa0+0x78(%rax),%rax # adjust stack pointer
+
+.Lin_tail:
+ mov -48(%rax),%rbp
+ mov -40(%rax),%rbx
+ mov -32(%rax),%r12
+ mov -24(%rax),%r13
+ mov -16(%rax),%r14
+ mov -8(%rax),%r15
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R15
+
+.Lin_prologue:
+ mov %rax,152($context) # restore context->Rsp
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$`1232/8`,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size se_handler,.-se_handler
+
+.section .pdata
+.align 4
+___
+$code.=<<___ if ($ecb);
+ .rva .Lecb_enc_prologue
+ .rva .Lecb_enc_epilogue
+ .rva .Lecb_enc_info
+
+ .rva .Lecb_dec_prologue
+ .rva .Lecb_dec_epilogue
+ .rva .Lecb_dec_info
+___
+$code.=<<___;
+ .rva .Lcbc_dec_prologue
+ .rva .Lcbc_dec_epilogue
+ .rva .Lcbc_dec_info
+
+ .rva .Lctr_enc_prologue
+ .rva .Lctr_enc_epilogue
+ .rva .Lctr_enc_info
+
+ .rva .Lxts_enc_prologue
+ .rva .Lxts_enc_epilogue
+ .rva .Lxts_enc_info
+
+ .rva .Lxts_dec_prologue
+ .rva .Lxts_dec_epilogue
+ .rva .Lxts_dec_info
+
+.section .xdata
+.align 8
+___
+$code.=<<___ if ($ecb);
+.Lecb_enc_info:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lecb_enc_body,.Lecb_enc_epilogue # HandlerData[]
+ .rva .Lecb_enc_tail
+ .long 0
+.Lecb_dec_info:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lecb_dec_body,.Lecb_dec_epilogue # HandlerData[]
+ .rva .Lecb_dec_tail
+ .long 0
+___
+$code.=<<___;
+.Lcbc_dec_info:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lcbc_dec_body,.Lcbc_dec_epilogue # HandlerData[]
+ .rva .Lcbc_dec_tail
+ .long 0
+.Lctr_enc_info:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lctr_enc_body,.Lctr_enc_epilogue # HandlerData[]
+ .rva .Lctr_enc_tail
+ .long 0
+.Lxts_enc_info:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lxts_enc_body,.Lxts_enc_epilogue # HandlerData[]
+ .rva .Lxts_enc_tail
+ .long 0
+.Lxts_dec_info:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lxts_dec_body,.Lxts_dec_epilogue # HandlerData[]
+ .rva .Lxts_dec_tail
+ .long 0
+___
+}
+
+$code =~ s/\`([^\`]*)\`/eval($1)/gem;
+
+print $code;
+
+close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/aes/asm/vpaes-armv8.pl b/crypto/aes/asm/vpaes-armv8.pl
index 7a9ffbd7d94c..dcd5065e68c0 100755
--- a/crypto/aes/asm/vpaes-armv8.pl
+++ b/crypto/aes/asm/vpaes-armv8.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -30,6 +30,7 @@
# Denver(***) 16.6(**) 15.1/17.8(**) [8.80/9.93 ]
# Apple A7(***) 22.7(**) 10.9/14.3 [8.45/10.0 ]
# Mongoose(***) 26.3(**) 21.0/25.0(**) [13.3/16.8 ]
+# ThunderX2(***) 39.4(**) 33.8/48.6(**)
#
# (*) ECB denotes approximate result for parallelizable modes
# such as CBC decrypt, CTR, etc.;
@@ -37,15 +38,18 @@
# code, but it's constant-time and therefore preferred;
# (***) presented for reference/comparison purposes;
-$flavour = shift;
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
$code.=<<___;
@@ -150,12 +154,12 @@ my ($sb1u,$sb1t,$sb2u,$sb2t) = map("v$_.16b",(24..27));
my ($sb9u,$sb9t,$sbdu,$sbdt,$sbbu,$sbbt,$sbeu,$sbet)=map("v$_.16b",(24..31));
$code.=<<___;
-##
-## _aes_preheat
-##
-## Fills register %r10 -> .aes_consts (so you can -fPIC)
-## and %xmm9-%xmm15 as specified below.
-##
+//
+// _aes_preheat
+//
+// Fills register %r10 -> .aes_consts (so you can -fPIC)
+// and %xmm9-%xmm15 as specified below.
+//
.type _vpaes_encrypt_preheat,%function
.align 4
_vpaes_encrypt_preheat:
@@ -167,21 +171,21 @@ _vpaes_encrypt_preheat:
ret
.size _vpaes_encrypt_preheat,.-_vpaes_encrypt_preheat
-##
-## _aes_encrypt_core
-##
-## AES-encrypt %xmm0.
-##
-## Inputs:
-## %xmm0 = input
-## %xmm9-%xmm15 as in _vpaes_preheat
-## (%rdx) = scheduled keys
-##
-## Output in %xmm0
-## Clobbers %xmm1-%xmm5, %r9, %r10, %r11, %rax
-## Preserves %xmm6 - %xmm8 so you get some local vectors
-##
-##
+//
+// _aes_encrypt_core
+//
+// AES-encrypt %xmm0.
+//
+// Inputs:
+// %xmm0 = input
+// %xmm9-%xmm15 as in _vpaes_preheat
+// (%rdx) = scheduled keys
+//
+// Output in %xmm0
+// Clobbers %xmm1-%xmm5, %r9, %r10, %r11, %rax
+// Preserves %xmm6 - %xmm8 so you get some local vectors
+//
+//
.type _vpaes_encrypt_core,%function
.align 4
_vpaes_encrypt_core:
@@ -387,11 +391,11 @@ _vpaes_decrypt_preheat:
ret
.size _vpaes_decrypt_preheat,.-_vpaes_decrypt_preheat
-##
-## Decryption core
-##
-## Same API as encryption core.
-##
+//
+// Decryption core
+//
+// Same API as encryption core.
+//
.type _vpaes_decrypt_core,%function
.align 4
_vpaes_decrypt_core:
@@ -643,11 +647,11 @@ my ($inp,$bits,$out,$dir)=("x0","w1","x2","w3");
my ($invlo,$invhi,$iptlo,$ipthi,$rcon) = map("v$_.16b",(18..21,8));
$code.=<<___;
-########################################################
-## ##
-## AES key schedule ##
-## ##
-########################################################
+////////////////////////////////////////////////////////
+// //
+// AES key schedule //
+// //
+////////////////////////////////////////////////////////
.type _vpaes_key_preheat,%function
.align 4
_vpaes_key_preheat:
@@ -703,14 +707,14 @@ _vpaes_schedule_core:
b.eq .Lschedule_192
// 128: fall though
-##
-## .schedule_128
-##
-## 128-bit specific part of key schedule.
-##
-## This schedule is really simple, because all its parts
-## are accomplished by the subroutines.
-##
+//
+// .schedule_128
+//
+// 128-bit specific part of key schedule.
+//
+// This schedule is really simple, because all its parts
+// are accomplished by the subroutines.
+//
.Lschedule_128:
mov $inp, #10 // mov \$10, %esi
@@ -721,21 +725,21 @@ _vpaes_schedule_core:
bl _vpaes_schedule_mangle // write output
b .Loop_schedule_128
-##
-## .aes_schedule_192
-##
-## 192-bit specific part of key schedule.
-##
-## The main body of this schedule is the same as the 128-bit
-## schedule, but with more smearing. The long, high side is
-## stored in %xmm7 as before, and the short, low side is in
-## the high bits of %xmm6.
-##
-## This schedule is somewhat nastier, however, because each
-## round produces 192 bits of key material, or 1.5 round keys.
-## Therefore, on each cycle we do 2 rounds and produce 3 round
-## keys.
-##
+//
+// .aes_schedule_192
+//
+// 192-bit specific part of key schedule.
+//
+// The main body of this schedule is the same as the 128-bit
+// schedule, but with more smearing. The long, high side is
+// stored in %xmm7 as before, and the short, low side is in
+// the high bits of %xmm6.
+//
+// This schedule is somewhat nastier, however, because each
+// round produces 192 bits of key material, or 1.5 round keys.
+// Therefore, on each cycle we do 2 rounds and produce 3 round
+// keys.
+//
.align 4
.Lschedule_192:
sub $inp, $inp, #8
@@ -759,16 +763,16 @@ _vpaes_schedule_core:
bl _vpaes_schedule_192_smear
b .Loop_schedule_192
-##
-## .aes_schedule_256
-##
-## 256-bit specific part of key schedule.
-##
-## The structure here is very similar to the 128-bit
-## schedule, but with an additional "low side" in
-## %xmm6. The low side's rounds are the same as the
-## high side's, except no rcon and no rotation.
-##
+//
+// .aes_schedule_256
+//
+// 256-bit specific part of key schedule.
+//
+// The structure here is very similar to the 128-bit
+// schedule, but with an additional "low side" in
+// %xmm6. The low side's rounds are the same as the
+// high side's, except no rcon and no rotation.
+//
.align 4
.Lschedule_256:
ld1 {v0.16b}, [$inp] // vmovdqu 16(%rdi),%xmm0 # load key part 2 (unaligned)
@@ -795,16 +799,16 @@ _vpaes_schedule_core:
b .Loop_schedule_256
-##
-## .aes_schedule_mangle_last
-##
-## Mangler for last round of key schedule
-## Mangles %xmm0
-## when encrypting, outputs out(%xmm0) ^ 63
-## when decrypting, outputs unskew(%xmm0)
-##
-## Always called right before return... jumps to cleanup and exits
-##
+//
+// .aes_schedule_mangle_last
+//
+// Mangler for last round of key schedule
+// Mangles %xmm0
+// when encrypting, outputs out(%xmm0) ^ 63
+// when decrypting, outputs unskew(%xmm0)
+//
+// Always called right before return... jumps to cleanup and exits
+//
.align 4
.Lschedule_mangle_last:
// schedule last round key from xmm0
@@ -838,20 +842,20 @@ _vpaes_schedule_core:
ret
.size _vpaes_schedule_core,.-_vpaes_schedule_core
-##
-## .aes_schedule_192_smear
-##
-## Smear the short, low side in the 192-bit key schedule.
-##
-## Inputs:
-## %xmm7: high side, b a x y
-## %xmm6: low side, d c 0 0
-## %xmm13: 0
-##
-## Outputs:
-## %xmm6: b+c+d b+c 0 0
-## %xmm0: b+c+d b+c b a
-##
+//
+// .aes_schedule_192_smear
+//
+// Smear the short, low side in the 192-bit key schedule.
+//
+// Inputs:
+// %xmm7: high side, b a x y
+// %xmm6: low side, d c 0 0
+// %xmm13: 0
+//
+// Outputs:
+// %xmm6: b+c+d b+c 0 0
+// %xmm0: b+c+d b+c b a
+//
.type _vpaes_schedule_192_smear,%function
.align 4
_vpaes_schedule_192_smear:
@@ -867,24 +871,24 @@ _vpaes_schedule_192_smear:
ret
.size _vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear
-##
-## .aes_schedule_round
-##
-## Runs one main round of the key schedule on %xmm0, %xmm7
-##
-## Specifically, runs subbytes on the high dword of %xmm0
-## then rotates it by one byte and xors into the low dword of
-## %xmm7.
-##
-## Adds rcon from low byte of %xmm8, then rotates %xmm8 for
-## next rcon.
-##
-## Smears the dwords of %xmm7 by xoring the low into the
-## second low, result into third, result into highest.
-##
-## Returns results in %xmm7 = %xmm0.
-## Clobbers %xmm1-%xmm4, %r11.
-##
+//
+// .aes_schedule_round
+//
+// Runs one main round of the key schedule on %xmm0, %xmm7
+//
+// Specifically, runs subbytes on the high dword of %xmm0
+// then rotates it by one byte and xors into the low dword of
+// %xmm7.
+//
+// Adds rcon from low byte of %xmm8, then rotates %xmm8 for
+// next rcon.
+//
+// Smears the dwords of %xmm7 by xoring the low into the
+// second low, result into third, result into highest.
+//
+// Returns results in %xmm7 = %xmm0.
+// Clobbers %xmm1-%xmm4, %r11.
+//
.type _vpaes_schedule_round,%function
.align 4
_vpaes_schedule_round:
@@ -932,15 +936,15 @@ _vpaes_schedule_low_round:
ret
.size _vpaes_schedule_round,.-_vpaes_schedule_round
-##
-## .aes_schedule_transform
-##
-## Linear-transform %xmm0 according to tables at (%r11)
-##
-## Requires that %xmm9 = 0x0F0F... as in preheat
-## Output in %xmm0
-## Clobbers %xmm1, %xmm2
-##
+//
+// .aes_schedule_transform
+//
+// Linear-transform %xmm0 according to tables at (%r11)
+//
+// Requires that %xmm9 = 0x0F0F... as in preheat
+// Output in %xmm0
+// Clobbers %xmm1, %xmm2
+//
.type _vpaes_schedule_transform,%function
.align 4
_vpaes_schedule_transform:
@@ -954,29 +958,29 @@ _vpaes_schedule_transform:
ret
.size _vpaes_schedule_transform,.-_vpaes_schedule_transform
-##
-## .aes_schedule_mangle
-##
-## Mangle xmm0 from (basis-transformed) standard version
-## to our version.
-##
-## On encrypt,
-## xor with 0x63
-## multiply by circulant 0,1,1,1
-## apply shiftrows transform
-##
-## On decrypt,
-## xor with 0x63
-## multiply by "inverse mixcolumns" circulant E,B,D,9
-## deskew
-## apply shiftrows transform
-##
-##
-## Writes out to (%rdx), and increments or decrements it
-## Keeps track of round number mod 4 in %r8
-## Preserves xmm0
-## Clobbers xmm1-xmm5
-##
+//
+// .aes_schedule_mangle
+//
+// Mangle xmm0 from (basis-transformed) standard version
+// to our version.
+//
+// On encrypt,
+// xor with 0x63
+// multiply by circulant 0,1,1,1
+// apply shiftrows transform
+//
+// On decrypt,
+// xor with 0x63
+// multiply by "inverse mixcolumns" circulant E,B,D,9
+// deskew
+// apply shiftrows transform
+//
+//
+// Writes out to (%rdx), and increments or decrements it
+// Keeps track of round number mod 4 in %r8
+// Preserves xmm0
+// Clobbers xmm1-xmm5
+//
.type _vpaes_schedule_mangle,%function
.align 4
_vpaes_schedule_mangle:
diff --git a/crypto/aes/asm/vpaes-ppc.pl b/crypto/aes/asm/vpaes-ppc.pl
index 0260a5c9bff0..7af47c630e71 100644
--- a/crypto/aes/asm/vpaes-ppc.pl
+++ b/crypto/aes/asm/vpaes-ppc.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -35,7 +35,10 @@
# (**) Inadequate POWER6 performance is due to astronomic AltiVec
# latency, 9 cycles per simple logical operation.
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /64/) {
$SIZE_T =8;
@@ -61,7 +64,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
+open STDOUT,"| $^X $xlate $flavour \"$output\""
+ || die "can't call $xlate: $!";
$code.=<<___;
.machine "any"
diff --git a/crypto/aes/asm/vpaes-x86.pl b/crypto/aes/asm/vpaes-x86.pl
index fb02a413345a..b206e934b48b 100644
--- a/crypto/aes/asm/vpaes-x86.pl
+++ b/crypto/aes/asm/vpaes-x86.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -58,9 +58,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output = pop;
-open OUT,">$output";
-*STDOUT=*OUT;
+$output = pop and open STDOUT,">$output";
&asm_init($ARGV[0],$x86only = $ARGV[$#ARGV] eq "386");
diff --git a/crypto/aes/asm/vpaes-x86_64.pl b/crypto/aes/asm/vpaes-x86_64.pl
index 099a686a4d5d..845528f41ac2 100644
--- a/crypto/aes/asm/vpaes-x86_64.pl
+++ b/crypto/aes/asm/vpaes-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -54,9 +54,10 @@
#
# <appro@openssl.org>
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -65,7 +66,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
$PREFIX="vpaes";
@@ -696,6 +698,7 @@ _vpaes_schedule_mangle:
.align 16
${PREFIX}_set_encrypt_key:
.cfi_startproc
+ endbranch
___
$code.=<<___ if ($win64);
lea -0xb8(%rsp),%rsp
@@ -746,6 +749,7 @@ $code.=<<___;
.align 16
${PREFIX}_set_decrypt_key:
.cfi_startproc
+ endbranch
___
$code.=<<___ if ($win64);
lea -0xb8(%rsp),%rsp
@@ -801,6 +805,7 @@ $code.=<<___;
.align 16
${PREFIX}_encrypt:
.cfi_startproc
+ endbranch
___
$code.=<<___ if ($win64);
lea -0xb8(%rsp),%rsp
@@ -846,6 +851,7 @@ $code.=<<___;
.align 16
${PREFIX}_decrypt:
.cfi_startproc
+ endbranch
___
$code.=<<___ if ($win64);
lea -0xb8(%rsp),%rsp
@@ -897,6 +903,7 @@ $code.=<<___;
.align 16
${PREFIX}_cbc_encrypt:
.cfi_startproc
+ endbranch
xchg $key,$len
___
($len,$key)=($key,$len);
diff --git a/crypto/aes/build.info b/crypto/aes/build.info
index 0f04863640de..b250903fa6e2 100644
--- a/crypto/aes/build.info
+++ b/crypto/aes/build.info
@@ -1,64 +1,128 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- aes_misc.c aes_ecb.c aes_cfb.c aes_ofb.c \
- aes_ige.c aes_wrap.c {- $target{aes_asm_src} -}
+
+$AESASM=aes_core.c aes_cbc.c
+IF[{- !$disabled{asm} -}]
+ $AESASM_x86=aes-586.S
+ $AESDEF_x86=AES_ASM
+ $AESASM_x86_sse2=vpaes-x86.S aesni-x86.S
+ $AESDEF_x86_sse2=VPAES_ASM OPENSSL_IA32_SSE2
+
+ $AESASM_x86_64=\
+ aes-x86_64.s vpaes-x86_64.s bsaes-x86_64.s aesni-x86_64.s \
+ aesni-sha1-x86_64.s aesni-sha256-x86_64.s aesni-mb-x86_64.s
+ $AESDEF_x86_64=AES_ASM VPAES_ASM BSAES_ASM
+
+ $AESASM_ia64=aes_core.c aes_cbc.c aes-ia64.s
+ $AESDEF_ia64=AES_ASM
+
+ $AESASM_sparcv9=\
+ aes_core.c aes_cbc.c aes-sparcv9.S aest4-sparcv9.S aesfx-sparcv9.S
+ $AESDEF_sparcv9=AES_ASM
+
+ $AESASM_mips32=aes_cbc.c aes-mips.S
+ $AESDEF_mips32=AES_ASM
+ $AESASM_mips64=$AESASM_mips32
+ $AESDEF_mips64=$AESDEF_mips32
+
+ $AESASM_s390x=aes-s390x.S
+ # aes-390x.S implements AES_ctr32_encrypt and AES_xts_[en|de]crypt
+ $AESDEF_s390x=AES_ASM AES_CTR_ASM AES_XTS_ASM
+
+ $AESASM_armv4=aes_cbc.c aes-armv4.S bsaes-armv7.S aesv8-armx.S
+ $AESDEF_armv4=AES_ASM BSAES_ASM
+ $AESASM_aarch64=aes_core.c aes_cbc.c aesv8-armx.S vpaes-armv8.S
+ $AESDEF_aarch64=VPAES_ASM
+
+ $AESASM_parisc11=aes_core.c aes_cbc.c aes-parisc.s
+ $AESDEF_parisc11=AES_ASM
+ $AESASM_parisc20_64=$AESASM_parisc11
+ $AESDEF_parisc20_64=$AESDEF_parisc11
+
+ $AESASM_ppc32=aes_core.c aes_cbc.c aes-ppc.s vpaes-ppc.s aesp8-ppc.s
+ $AESDEF_ppc32=AES_ASM VPAES_ASM
+ $AESASM_ppc64=$AESASM_ppc32
+ $AESDEF_ppc64=$AESDEF_ppc32
+
+ $AESASM_c64xplus=aes-c64xplus.s aes_cbc.c
+ # aes-c64xplus.s implements AES_ctr32_encrypt
+ $AESDEF_c64xplus=AES_ASM AES_CTR_ASM
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+ IF[$AESASM_{- $target{asm_arch} -}]
+ $AESASM=$AESASM_{- $target{asm_arch} -}
+ $AESDEF=$AESDEF_{- $target{asm_arch} -}
+ IF[{- !$disabled{sse2} -}]
+ $AESASM=$AESASM $AESASM_{- $target{asm_arch} -}_sse2
+ $AESDEF=$AESDEF $AESDEF_{- $target{asm_arch} -}_sse2
+ ENDIF
+ ENDIF
+ENDIF
+
+$COMMON=aes_misc.c aes_ecb.c $AESASM
+SOURCE[../../libcrypto]=$COMMON aes_cfb.c aes_ofb.c aes_wrap.c
+IF[{- !$disabled{'deprecated-3.0'} -}]
+ SOURCE[../../libcrypto]=aes_ige.c
+ENDIF
+SOURCE[../../providers/libfips.a]=$COMMON
+
+# Implementations are now spread across several libraries, so the defines
+# need to be applied to all affected libraries and modules.
+DEFINE[../../libcrypto]=$AESDEF
+DEFINE[../../providers/libfips.a]=$AESDEF
+DEFINE[../../providers/libdefault.a]=$AESDEF
+# We only need to include the AESDEF stuff in the legacy provider when it's a
+# separate module and it's dynamically linked with libcrypto. Otherwise, it
+# already gets everything that the static libcrypto.a has, and doesn't need it
+# added again.
+IF[{- !$disabled{module} && !$disabled{shared} -}]
+ DEFINE[../providers/liblegacy.a]=$AESDEF
+ENDIF
GENERATE[aes-ia64.s]=asm/aes-ia64.S
-GENERATE[aes-586.s]=asm/aes-586.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-DEPEND[aes-586.s]=../perlasm/x86asm.pl
-GENERATE[vpaes-x86.s]=asm/vpaes-x86.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-DEPEND[vpaes-586.s]=../perlasm/x86asm.pl
-GENERATE[aesni-x86.s]=asm/aesni-x86.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-DEPEND[aesni-586.s]=../perlasm/x86asm.pl
-
-GENERATE[aes-x86_64.s]=asm/aes-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[vpaes-x86_64.s]=asm/vpaes-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[bsaes-x86_64.s]=asm/bsaes-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[aesni-x86_64.s]=asm/aesni-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[aesni-sha1-x86_64.s]=asm/aesni-sha1-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[aesni-sha256-x86_64.s]=asm/aesni-sha256-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[aesni-mb-x86_64.s]=asm/aesni-mb-x86_64.pl $(PERLASM_SCHEME)
-
-GENERATE[aes-sparcv9.S]=asm/aes-sparcv9.pl $(PERLASM_SCHEME)
+GENERATE[aes-586.S]=asm/aes-586.pl
+DEPEND[aes-586.S]=../perlasm/x86asm.pl
+GENERATE[vpaes-x86.S]=asm/vpaes-x86.pl
+DEPEND[vpaes-586.S]=../perlasm/x86asm.pl
+GENERATE[aesni-x86.S]=asm/aesni-x86.pl
+DEPEND[aesni-586.S]=../perlasm/x86asm.pl
+
+GENERATE[aes-x86_64.s]=asm/aes-x86_64.pl
+GENERATE[vpaes-x86_64.s]=asm/vpaes-x86_64.pl
+GENERATE[bsaes-x86_64.s]=asm/bsaes-x86_64.pl
+GENERATE[aesni-x86_64.s]=asm/aesni-x86_64.pl
+GENERATE[aesni-sha1-x86_64.s]=asm/aesni-sha1-x86_64.pl
+GENERATE[aesni-sha256-x86_64.s]=asm/aesni-sha256-x86_64.pl
+GENERATE[aesni-mb-x86_64.s]=asm/aesni-mb-x86_64.pl
+
+GENERATE[aes-sparcv9.S]=asm/aes-sparcv9.pl
INCLUDE[aes-sparcv9.o]=..
-GENERATE[aest4-sparcv9.S]=asm/aest4-sparcv9.pl $(PERLASM_SCHEME)
+GENERATE[aest4-sparcv9.S]=asm/aest4-sparcv9.pl
INCLUDE[aest4-sparcv9.o]=..
DEPEND[aest4-sparcv9.S]=../perlasm/sparcv9_modes.pl
-GENERATE[aesfx-sparcv9.S]=asm/aesfx-sparcv9.pl $(PERLASM_SCHEME)
+GENERATE[aesfx-sparcv9.S]=asm/aesfx-sparcv9.pl
INCLUDE[aesfx-sparcv9.o]=..
-GENERATE[aes-ppc.s]=asm/aes-ppc.pl $(PERLASM_SCHEME)
-GENERATE[vpaes-ppc.s]=asm/vpaes-ppc.pl $(PERLASM_SCHEME)
-GENERATE[aesp8-ppc.s]=asm/aesp8-ppc.pl $(PERLASM_SCHEME)
+GENERATE[aes-ppc.s]=asm/aes-ppc.pl
+GENERATE[vpaes-ppc.s]=asm/vpaes-ppc.pl
+GENERATE[aesp8-ppc.s]=asm/aesp8-ppc.pl
-GENERATE[aes-parisc.s]=asm/aes-parisc.pl $(PERLASM_SCHEME)
+GENERATE[aes-parisc.s]=asm/aes-parisc.pl
-GENERATE[aes-mips.S]=asm/aes-mips.pl $(PERLASM_SCHEME)
+GENERATE[aes-mips.S]=asm/aes-mips.pl
INCLUDE[aes-mips.o]=..
-GENERATE[aesv8-armx.S]=asm/aesv8-armx.pl $(PERLASM_SCHEME)
+GENERATE[aesv8-armx.S]=asm/aesv8-armx.pl
INCLUDE[aesv8-armx.o]=..
-GENERATE[vpaes-armv8.S]=asm/vpaes-armv8.pl $(PERLASM_SCHEME)
+GENERATE[vpaes-armv8.S]=asm/vpaes-armv8.pl
-GENERATE[aes-armv4.S]=asm/aes-armv4.pl $(PERLASM_SCHEME)
+GENERATE[aes-armv4.S]=asm/aes-armv4.pl
INCLUDE[aes-armv4.o]=..
-GENERATE[bsaes-armv7.S]=asm/bsaes-armv7.pl $(PERLASM_SCHEME)
+GENERATE[bsaes-armv7.S]=asm/bsaes-armv7.pl
INCLUDE[bsaes-armv7.o]=..
-GENERATE[aes-s390x.S]=asm/aes-s390x.pl $(PERLASM_SCHEME)
+GENERATE[aes-s390x.S]=asm/aes-s390x.pl
INCLUDE[aes-s390x.o]=..
-BEGINRAW[Makefile]
-##### AES assembler implementations
-
-# GNU make "catch all"
-{- $builddir -}/aes-%.S: {- $sourcedir -}/asm/aes-%.pl
- CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@
-{- $builddir -}/bsaes-%.S: {- $sourcedir -}/asm/bsaes-%.pl
- CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@
-
-ENDRAW[Makefile]
+GENERATE[aes-c64xplus.S]=asm/aes-c64xplus.pl
diff --git a/crypto/aria/aria.c b/crypto/aria/aria.c
index ce55d5266429..5e60bc521023 100644
--- a/crypto/aria/aria.c
+++ b/crypto/aria/aria.c
@@ -1,8 +1,8 @@
/*
- * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -468,8 +468,8 @@ static const uint32_t X2[256] = {
(Y) = (TMP2) ^ rotr32((TMP) ^ (TMP2), 16); \
} while(0)
-void aria_encrypt(const unsigned char *in, unsigned char *out,
- const ARIA_KEY *key)
+void ossl_aria_encrypt(const unsigned char *in, unsigned char *out,
+ const ARIA_KEY *key)
{
register uint32_t reg0, reg1, reg2, reg3;
int Nr;
@@ -535,8 +535,8 @@ void aria_encrypt(const unsigned char *in, unsigned char *out,
PUT_U32_BE(out, 3, reg3);
}
-int aria_set_encrypt_key(const unsigned char *userKey, const int bits,
- ARIA_KEY *key)
+int ossl_aria_set_encrypt_key(const unsigned char *userKey, const int bits,
+ ARIA_KEY *key)
{
register uint32_t reg0, reg1, reg2, reg3;
uint32_t w0[4], w1[4], w2[4], w3[4];
@@ -667,8 +667,8 @@ int aria_set_encrypt_key(const unsigned char *userKey, const int bits,
return 0;
}
-int aria_set_decrypt_key(const unsigned char *userKey, const int bits,
- ARIA_KEY *key)
+int ossl_aria_set_decrypt_key(const unsigned char *userKey, const int bits,
+ ARIA_KEY *key)
{
ARIA_u128 *rk_head;
ARIA_u128 *rk_tail;
@@ -676,7 +676,7 @@ int aria_set_decrypt_key(const unsigned char *userKey, const int bits,
register uint32_t reg0, reg1, reg2, reg3;
uint32_t s0, s1, s2, s3;
- const int r = aria_set_encrypt_key(userKey, bits, key);
+ const int r = ossl_aria_set_encrypt_key(userKey, bits, key);
if (r != 0) {
return r;
@@ -1007,7 +1007,7 @@ static void sl2(ARIA_c128 o, const ARIA_u128 *x, const ARIA_u128 *y)
{
unsigned int i;
for (i = 0; i < ARIA_BLOCK_SIZE; i += 4) {
- o[i ] = sb3[x->c[i ] ^ y->c[i ]];
+ o[i ] = sb3[x->c[i ] ^ y->c[i ]];
o[i + 1] = sb4[x->c[i + 1] ^ y->c[i + 1]];
o[i + 2] = sb1[x->c[i + 2] ^ y->c[i + 2]];
o[i + 3] = sb2[x->c[i + 3] ^ y->c[i + 3]];
@@ -1106,8 +1106,8 @@ static void do_encrypt(unsigned char *o, const unsigned char *pin,
* Encrypt a single block
* in and out can overlap
*/
-void aria_encrypt(const unsigned char *in, unsigned char *out,
- const ARIA_KEY *key)
+void ossl_aria_encrypt(const unsigned char *in, unsigned char *out,
+ const ARIA_KEY *key)
{
assert(in != NULL && out != NULL && key != NULL);
do_encrypt(out, in, key->rounds, key->rd_key);
@@ -1119,8 +1119,8 @@ void aria_encrypt(const unsigned char *in, unsigned char *out,
* We short circuit execution of the last two
* or four rotations based on the key size.
*/
-int aria_set_encrypt_key(const unsigned char *userKey, const int bits,
- ARIA_KEY *key)
+int ossl_aria_set_encrypt_key(const unsigned char *userKey, const int bits,
+ ARIA_KEY *key)
{
const ARIA_u128 *ck1, *ck2, *ck3;
ARIA_u128 kr, w0, w1, w2, w3;
@@ -1192,11 +1192,11 @@ int aria_set_encrypt_key(const unsigned char *userKey, const int bits,
/*
* Expand the cipher key into the decryption key schedule.
*/
-int aria_set_decrypt_key(const unsigned char *userKey, const int bits,
- ARIA_KEY *key)
+int ossl_aria_set_decrypt_key(const unsigned char *userKey, const int bits,
+ ARIA_KEY *key)
{
ARIA_KEY ek;
- const int r = aria_set_encrypt_key(userKey, bits, &ek);
+ const int r = ossl_aria_set_encrypt_key(userKey, bits, &ek);
unsigned int i, rounds = ek.rounds;
if (r == 0) {
diff --git a/crypto/arm64cpuid.pl b/crypto/arm64cpuid.pl
index 319927e6c729..ac76dd449f37 100755
--- a/crypto/arm64cpuid.pl
+++ b/crypto/arm64cpuid.pl
@@ -1,21 +1,24 @@
#! /usr/bin/env perl
# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
-$flavour = shift;
-$output = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
( $xlate="${dir}perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
$code.=<<___;
@@ -78,6 +81,13 @@ _armv8_sha512_probe:
ret
.size _armv8_sha512_probe,.-_armv8_sha512_probe
+.globl _armv8_cpuid_probe
+.type _armv8_cpuid_probe,%function
+_armv8_cpuid_probe:
+ mrs x0, midr_el1
+ ret
+.size _armv8_cpuid_probe,.-_armv8_cpuid_probe
+
.globl OPENSSL_cleanse
.type OPENSSL_cleanse,%function
.align 5
diff --git a/crypto/arm_arch.h b/crypto/arm_arch.h
index 8b7105571d78..45d7e1556475 100644
--- a/crypto/arm_arch.h
+++ b/crypto/arm_arch.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -71,6 +71,8 @@
# ifndef __ASSEMBLER__
extern unsigned int OPENSSL_armcap_P;
+extern unsigned int OPENSSL_arm_midr;
+extern unsigned int OPENSSL_armv8_rsa_neonized;
# endif
# define ARMV7_NEON (1<<0)
@@ -80,5 +82,48 @@ extern unsigned int OPENSSL_armcap_P;
# define ARMV8_SHA256 (1<<4)
# define ARMV8_PMULL (1<<5)
# define ARMV8_SHA512 (1<<6)
+# define ARMV8_CPUID (1<<7)
+/*
+ * MIDR_EL1 system register
+ *
+ * 63___ _ ___32_31___ _ ___24_23_____20_19_____16_15__ _ __4_3_______0
+ * | | | | | | |
+ * |RES0 | Implementer | Variant | Arch | PartNum |Revision|
+ * |____ _ _____|_____ _ _____|_________|_______ _|____ _ ___|________|
+ *
+ */
+
+# define ARM_CPU_IMP_ARM 0x41
+
+# define ARM_CPU_PART_CORTEX_A72 0xD08
+# define ARM_CPU_PART_N1 0xD0C
+
+# define MIDR_PARTNUM_SHIFT 4
+# define MIDR_PARTNUM_MASK (0xfffU << MIDR_PARTNUM_SHIFT)
+# define MIDR_PARTNUM(midr) \
+ (((midr) & MIDR_PARTNUM_MASK) >> MIDR_PARTNUM_SHIFT)
+
+# define MIDR_IMPLEMENTER_SHIFT 24
+# define MIDR_IMPLEMENTER_MASK (0xffU << MIDR_IMPLEMENTER_SHIFT)
+# define MIDR_IMPLEMENTER(midr) \
+ (((midr) & MIDR_IMPLEMENTER_MASK) >> MIDR_IMPLEMENTER_SHIFT)
+
+# define MIDR_ARCHITECTURE_SHIFT 16
+# define MIDR_ARCHITECTURE_MASK (0xfU << MIDR_ARCHITECTURE_SHIFT)
+# define MIDR_ARCHITECTURE(midr) \
+ (((midr) & MIDR_ARCHITECTURE_MASK) >> MIDR_ARCHITECTURE_SHIFT)
+
+# define MIDR_CPU_MODEL_MASK \
+ (MIDR_IMPLEMENTER_MASK | \
+ MIDR_PARTNUM_MASK | \
+ MIDR_ARCHITECTURE_MASK)
+
+# define MIDR_CPU_MODEL(imp, partnum) \
+ (((imp) << MIDR_IMPLEMENTER_SHIFT) | \
+ (0xfU << MIDR_ARCHITECTURE_SHIFT) | \
+ ((partnum) << MIDR_PARTNUM_SHIFT))
+
+# define MIDR_IS_CPU_MODEL(midr, imp, partnum) \
+ (((midr) & MIDR_CPU_MODEL_MASK) == MIDR_CPU_MODEL(imp, partnum))
#endif
diff --git a/crypto/armcap.c b/crypto/armcap.c
index 48c5d4d64e32..c021330e32fd 100644
--- a/crypto/armcap.c
+++ b/crypto/armcap.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,11 +13,16 @@
#include <setjmp.h>
#include <signal.h>
#include <openssl/crypto.h>
+#ifdef __APPLE__
+#include <sys/sysctl.h>
+#endif
#include "internal/cryptlib.h"
#include "arm_arch.h"
unsigned int OPENSSL_armcap_P = 0;
+unsigned int OPENSSL_arm_midr = 0;
+unsigned int OPENSSL_armv8_rsa_neonized = 0;
#if __ARM_MAX_ARCH__<7
void OPENSSL_cpuid_setup(void)
@@ -48,6 +53,7 @@ void _armv8_sha256_probe(void);
void _armv8_pmull_probe(void);
# ifdef __aarch64__
void _armv8_sha512_probe(void);
+unsigned int _armv8_cpuid_probe(void);
# endif
uint32_t _armv7_tick(void);
@@ -130,6 +136,7 @@ static unsigned long getauxval(unsigned long key)
# define HWCAP_CE_PMULL (1 << 4)
# define HWCAP_CE_SHA1 (1 << 5)
# define HWCAP_CE_SHA256 (1 << 6)
+# define HWCAP_CPUID (1 << 11)
# define HWCAP_CE_SHA512 (1 << 21)
# endif
@@ -144,12 +151,15 @@ void OPENSSL_cpuid_setup(void)
return;
trigger = 1;
+ OPENSSL_armcap_P = 0;
+
if ((e = getenv("OPENSSL_armcap"))) {
OPENSSL_armcap_P = (unsigned int)strtoul(e, NULL, 0);
return;
}
-# if defined(__APPLE__) && !defined(__aarch64__)
+# if defined(__APPLE__)
+# if !defined(__aarch64__)
/*
* Capability probing by catching SIGILL appears to be problematic
* on iOS. But since Apple universe is "monocultural", it's actually
@@ -165,9 +175,16 @@ void OPENSSL_cpuid_setup(void)
* Unified code works because it never triggers SIGILL on Apple
* devices...
*/
-# endif
+# else
+ {
+ unsigned int sha512;
+ size_t len = sizeof(sha512);
- OPENSSL_armcap_P = 0;
+ if (sysctlbyname("hw.optional.armv8_2_sha512", &sha512, &len, NULL, 0) == 0 && sha512 == 1)
+ OPENSSL_armcap_P |= ARMV8_SHA512;
+ }
+# endif
+# endif
# ifdef OSSL_IMPLEMENT_GETAUXVAL
if (getauxval(HWCAP) & HWCAP_NEON) {
@@ -190,6 +207,9 @@ void OPENSSL_cpuid_setup(void)
# ifdef __aarch64__
if (hwcap & HWCAP_CE_SHA512)
OPENSSL_armcap_P |= ARMV8_SHA512;
+
+ if (hwcap & HWCAP_CPUID)
+ OPENSSL_armcap_P |= ARMV8_CPUID;
# endif
}
# endif
@@ -237,13 +257,24 @@ void OPENSSL_cpuid_setup(void)
}
# endif
- /* Things that getauxval didn't tell us */
- if (sigsetjmp(ill_jmp, 1) == 0) {
- _armv7_tick();
- OPENSSL_armcap_P |= ARMV7_TICK;
- }
+ /*
+ * Probing for ARMV7_TICK is known to produce unreliable results,
+ * so we will only use the feature when the user explicitly enables
+ * it with OPENSSL_armcap.
+ */
sigaction(SIGILL, &ill_oact, NULL);
sigprocmask(SIG_SETMASK, &oset, NULL);
+
+# ifdef __aarch64__
+ if (OPENSSL_armcap_P & ARMV8_CPUID)
+ OPENSSL_arm_midr = _armv8_cpuid_probe();
+
+ if ((MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72) ||
+ MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N1)) &&
+ (OPENSSL_armcap_P & ARMV7_NEON)) {
+ OPENSSL_armv8_rsa_neonized = 1;
+ }
+# endif
}
#endif
diff --git a/crypto/armv4cpuid.pl b/crypto/armv4cpuid.pl
index d1b71f836f10..8991fd4afe8e 100644
--- a/crypto/armv4cpuid.pl
+++ b/crypto/armv4cpuid.pl
@@ -1,27 +1,29 @@
#! /usr/bin/env perl
# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
-$flavour = shift;
-$output = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
( $xlate="${dir}perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
$code.=<<___;
#include "arm_arch.h"
-.text
#if defined(__thumb2__) && !defined(__APPLE__)
.syntax unified
.thumb
@@ -30,6 +32,8 @@ $code.=<<___;
#undef __thumb2__
#endif
+.text
+
.align 5
.global OPENSSL_atomic_add
.type OPENSSL_atomic_add,%function
diff --git a/crypto/asn1/a_bitstr.c b/crypto/asn1/a_bitstr.c
index f462dd107368..7c256493571e 100644
--- a/crypto/asn1/a_bitstr.c
+++ b/crypto/asn1/a_bitstr.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -18,7 +18,7 @@ int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
return ASN1_STRING_set(x, d, len);
}
-int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
+int ossl_i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
{
int ret, j, bits, len;
unsigned char *p, *d;
@@ -76,8 +76,8 @@ int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
return ret;
}
-ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
- const unsigned char **pp, long len)
+ASN1_BIT_STRING *ossl_c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
+ const unsigned char **pp, long len)
{
ASN1_BIT_STRING *ret = NULL;
const unsigned char *p;
@@ -134,7 +134,7 @@ ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
*pp = p;
return ret;
err:
- ASN1err(ASN1_F_C2I_ASN1_BIT_STRING, i);
+ ERR_raise(ERR_LIB_ASN1, i);
if ((a == NULL) || (*a != ret))
ASN1_BIT_STRING_free(ret);
return NULL;
@@ -164,7 +164,7 @@ int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
return 1; /* Don't need to set */
c = OPENSSL_clear_realloc(a->data, a->length, w + 1);
if (c == NULL) {
- ASN1err(ASN1_F_ASN1_BIT_STRING_SET_BIT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
if (w + 1 - a->length > 0)
diff --git a/crypto/asn1/a_d2i_fp.c b/crypto/asn1/a_d2i_fp.c
index a452b3deba08..e8602053f974 100644
--- a/crypto/asn1/a_d2i_fp.c
+++ b/crypto/asn1/a_d2i_fp.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,6 +13,7 @@
#include "internal/numbers.h"
#include <openssl/buffer.h>
#include <openssl/asn1.h>
+#include "internal/asn1.h"
#include "crypto/asn1.h"
#ifndef NO_OLD_ASN1
@@ -24,7 +25,7 @@ void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x)
void *ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- ASN1err(ASN1_F_ASN1_D2I_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB);
return NULL;
}
BIO_set_fp(b, in, BIO_NOCLOSE);
@@ -54,39 +55,53 @@ void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x)
#endif
-void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
+void *ASN1_item_d2i_bio_ex(const ASN1_ITEM *it, BIO *in, void *x,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
BUF_MEM *b = NULL;
const unsigned char *p;
void *ret = NULL;
int len;
+ if (in == NULL)
+ return NULL;
len = asn1_d2i_read_bio(in, &b);
if (len < 0)
goto err;
p = (const unsigned char *)b->data;
- ret = ASN1_item_d2i(x, &p, len, it);
+ ret = ASN1_item_d2i_ex(x, &p, len, it, libctx, propq);
err:
BUF_MEM_free(b);
return ret;
}
+void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
+{
+ return ASN1_item_d2i_bio_ex(it, in, x, NULL, NULL);
+}
+
#ifndef OPENSSL_NO_STDIO
-void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
+void *ASN1_item_d2i_fp_ex(const ASN1_ITEM *it, FILE *in, void *x,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
BIO *b;
char *ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- ASN1err(ASN1_F_ASN1_ITEM_D2I_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB);
return NULL;
}
BIO_set_fp(b, in, BIO_NOCLOSE);
- ret = ASN1_item_d2i_bio(it, b, x);
+ ret = ASN1_item_d2i_bio_ex(it, b, x, libctx, propq);
BIO_free(b);
return ret;
}
+
+void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
+{
+ return ASN1_item_d2i_fp_ex(it, in, x, NULL, NULL);
+}
#endif
#define HEADER_SIZE 8
@@ -100,6 +115,7 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
uint32_t eos = 0;
size_t off = 0;
size_t len = 0;
+ size_t diff;
const unsigned char *q;
long slen;
@@ -107,27 +123,28 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
b = BUF_MEM_new();
if (b == NULL) {
- ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
- ERR_clear_error();
+ ERR_set_mark();
for (;;) {
- if (want >= (len - off)) {
- want -= (len - off);
+ diff = len - off;
+ if (want >= diff) {
+ want -= diff;
if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) {
- ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
i = BIO_read(in, &(b->data[len]), want);
- if ((i < 0) && ((len - off) == 0)) {
- ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA);
+ if (i < 0 && diff == 0) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA);
goto err;
}
if (i > 0) {
if (len + i < len) {
- ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG);
goto err;
}
len += i;
@@ -137,15 +154,17 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
p = (unsigned char *)&(b->data[off]);
q = p;
- inf = ASN1_get_object(&q, &slen, &tag, &xclass, len - off);
+ diff = len - off;
+ if (diff == 0)
+ goto err;
+ inf = ASN1_get_object(&q, &slen, &tag, &xclass, diff);
if (inf & 0x80) {
unsigned long e;
- e = ERR_GET_REASON(ERR_peek_error());
+ e = ERR_GET_REASON(ERR_peek_last_error());
if (e != ASN1_R_TOO_LONG)
goto err;
- else
- ERR_clear_error(); /* clear error */
+ ERR_pop_to_mark();
}
i = q - p; /* header length */
off += i; /* end of data */
@@ -153,7 +172,7 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
if (inf & 1) {
/* no data body so go round again */
if (eos == UINT32_MAX) {
- ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_HEADER_TOO_LONG);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_HEADER_TOO_LONG);
goto err;
}
eos++;
@@ -174,7 +193,7 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
want -= (len - off);
if (want > INT_MAX /* BIO_read takes an int length */ ||
len + want < len) {
- ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG);
goto err;
}
while (want > 0) {
@@ -187,15 +206,14 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
size_t chunk = want > chunk_max ? chunk_max : want;
if (!BUF_MEM_grow_clean(b, len + chunk)) {
- ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
want -= chunk;
while (chunk > 0) {
i = BIO_read(in, &(b->data[len]), chunk);
if (i <= 0) {
- ASN1err(ASN1_F_ASN1_D2I_READ_BIO,
- ASN1_R_NOT_ENOUGH_DATA);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA);
goto err;
}
/*
@@ -210,7 +228,7 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
}
}
if (off + slen < off) {
- ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG);
goto err;
}
off += slen;
@@ -222,13 +240,14 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
}
if (off > INT_MAX) {
- ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG);
goto err;
}
*pb = b;
return off;
err:
+ ERR_clear_last_mark();
BUF_MEM_free(b);
return -1;
}
diff --git a/crypto/asn1/a_digest.c b/crypto/asn1/a_digest.c
index cc3532ea7df2..72cc8807799d 100644
--- a/crypto/asn1/a_digest.c
+++ b/crypto/asn1/a_digest.c
@@ -1,24 +1,29 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include "internal/cryptlib.h"
+#include <openssl/engine.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include <openssl/x509.h>
+#include "crypto/x509.h"
-#ifndef NO_ASN1_OLD
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
unsigned char *md, unsigned int *len)
@@ -28,11 +33,11 @@ int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
inl = i2d(data, NULL);
if (inl <= 0) {
- ASN1err(ASN1_F_ASN1_DIGEST, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
return 0;
}
if ((str = OPENSSL_malloc(inl)) == NULL) {
- ASN1err(ASN1_F_ASN1_DIGEST, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
p = str;
@@ -48,20 +53,42 @@ int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
#endif
-int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn,
- unsigned char *md, unsigned int *len)
+int ossl_asn1_item_digest_ex(const ASN1_ITEM *it, const EVP_MD *md, void *asn,
+ unsigned char *data, unsigned int *len,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
- int i;
+ int i, ret = 0;
unsigned char *str = NULL;
+ EVP_MD *fetched_md = (EVP_MD *)md;
i = ASN1_item_i2d(asn, &str, it);
- if (!str)
+ if (i < 0 || str == NULL)
return 0;
- if (!EVP_Digest(str, i, md, len, type, NULL)) {
- OPENSSL_free(str);
- return 0;
+ if (EVP_MD_get0_provider(md) == NULL) {
+#if !defined(OPENSSL_NO_ENGINE)
+ ENGINE *tmpeng = ENGINE_get_digest_engine(EVP_MD_get_type(md));
+
+ if (tmpeng != NULL)
+ ENGINE_finish(tmpeng);
+ else
+#endif
+ fetched_md = EVP_MD_fetch(libctx, EVP_MD_get0_name(md), propq);
}
+ if (fetched_md == NULL)
+ goto err;
+
+ ret = EVP_Digest(str, i, data, len, fetched_md, NULL);
+err:
OPENSSL_free(str);
- return 1;
+ if (fetched_md != md)
+ EVP_MD_free(fetched_md);
+ return ret;
}
+
+int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *md, void *asn,
+ unsigned char *data, unsigned int *len)
+{
+ return ossl_asn1_item_digest_ex(it, md, asn, data, len, NULL, NULL);
+}
+
diff --git a/crypto/asn1/a_dup.c b/crypto/asn1/a_dup.c
index 50af6b000609..93e8b2aa8dab 100644
--- a/crypto/asn1/a_dup.c
+++ b/crypto/asn1/a_dup.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,11 +9,11 @@
#include <stdio.h>
#include "internal/cryptlib.h"
-#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
#ifndef NO_OLD_ASN1
-void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x)
+void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, const void *x)
{
unsigned char *b, *p;
const unsigned char *p2;
@@ -24,9 +24,12 @@ void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x)
return NULL;
i = i2d(x, NULL);
+ if (i <= 0)
+ return NULL;
+
b = OPENSSL_malloc(i + 10);
if (b == NULL) {
- ASN1err(ASN1_F_ASN1_DUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
p = b;
@@ -46,23 +49,49 @@ void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x)
* decode.
*/
-void *ASN1_item_dup(const ASN1_ITEM *it, void *x)
+void *ASN1_item_dup(const ASN1_ITEM *it, const void *x)
{
+ ASN1_aux_cb *asn1_cb = NULL;
unsigned char *b = NULL;
const unsigned char *p;
long i;
- void *ret;
+ ASN1_VALUE *ret;
+ OSSL_LIB_CTX *libctx = NULL;
+ const char *propq = NULL;
if (x == NULL)
return NULL;
+ if (it->itype == ASN1_ITYPE_SEQUENCE || it->itype == ASN1_ITYPE_CHOICE
+ || it->itype == ASN1_ITYPE_NDEF_SEQUENCE) {
+ const ASN1_AUX *aux = it->funcs;
+
+ asn1_cb = aux != NULL ? aux->asn1_cb : NULL;
+ }
+
+ if (asn1_cb != NULL) {
+ if (!asn1_cb(ASN1_OP_DUP_PRE, (ASN1_VALUE **)&x, it, NULL)
+ || !asn1_cb(ASN1_OP_GET0_LIBCTX, (ASN1_VALUE **)&x, it, &libctx)
+ || !asn1_cb(ASN1_OP_GET0_PROPQ, (ASN1_VALUE **)&x, it, &propq))
+ goto auxerr;
+ }
+
i = ASN1_item_i2d(x, &b, it);
if (b == NULL) {
- ASN1err(ASN1_F_ASN1_ITEM_DUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
p = b;
- ret = ASN1_item_d2i(NULL, &p, i, it);
+ ret = ASN1_item_d2i_ex(NULL, &p, i, it, libctx, propq);
OPENSSL_free(b);
+
+ if (asn1_cb != NULL
+ && !asn1_cb(ASN1_OP_DUP_POST, &ret, it, (void *)x))
+ goto auxerr;
+
return ret;
+
+ auxerr:
+ ERR_raise_data(ERR_LIB_ASN1, ASN1_R_AUX_ERROR, "Type=%s", it->sname);
+ return NULL;
}
diff --git a/crypto/asn1/a_gentm.c b/crypto/asn1/a_gentm.c
index 133bbb1581cb..0c06ac3c4163 100644
--- a/crypto/asn1/a_gentm.c
+++ b/crypto/asn1/a_gentm.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -16,14 +16,18 @@
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include "asn1_local.h"
+#include <openssl/asn1t.h>
+
+IMPLEMENT_ASN1_DUP_FUNCTION(ASN1_GENERALIZEDTIME)
/* This is the primary function used to parse ASN1_GENERALIZEDTIME */
-int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
+static int asn1_generalizedtime_to_tm(struct tm *tm,
+ const ASN1_GENERALIZEDTIME *d)
{
- /* wrapper around asn1_time_to_tm */
+ /* wrapper around ossl_asn1_time_to_tm */
if (d->type != V_ASN1_GENERALIZEDTIME)
return 0;
- return asn1_time_to_tm(tm, d);
+ return ossl_asn1_time_to_tm(tm, d);
}
int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
@@ -71,7 +75,7 @@ ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
return NULL;
}
- return asn1_time_from_tm(s, ts, V_ASN1_GENERALIZEDTIME);
+ return ossl_asn1_time_from_tm(s, ts, V_ASN1_GENERALIZEDTIME);
}
int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)
diff --git a/crypto/asn1/a_i2d_fp.c b/crypto/asn1/a_i2d_fp.c
index 980c65a25d2d..4cc4773666c4 100644
--- a/crypto/asn1/a_i2d_fp.c
+++ b/crypto/asn1/a_i2d_fp.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -15,13 +15,13 @@
#ifndef NO_OLD_ASN1
# ifndef OPENSSL_NO_STDIO
-int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x)
+int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, const void *x)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- ASN1err(ASN1_F_ASN1_I2D_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, out, BIO_NOCLOSE);
@@ -31,7 +31,7 @@ int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x)
}
# endif
-int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x)
+int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, const void *x)
{
char *b;
unsigned char *p;
@@ -43,7 +43,7 @@ int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x)
b = OPENSSL_malloc(n);
if (b == NULL) {
- ASN1err(ASN1_F_ASN1_I2D_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -68,13 +68,13 @@ int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x)
#endif
#ifndef OPENSSL_NO_STDIO
-int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
+int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, const void *x)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- ASN1err(ASN1_F_ASN1_ITEM_I2D_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, out, BIO_NOCLOSE);
@@ -84,14 +84,14 @@ int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
}
#endif
-int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
+int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, const void *x)
{
unsigned char *b = NULL;
int i, j = 0, n, ret = 1;
n = ASN1_item_i2d(x, &b, it);
if (b == NULL) {
- ASN1err(ASN1_F_ASN1_ITEM_I2D_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -109,3 +109,21 @@ int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
OPENSSL_free(b);
return ret;
}
+
+BIO *ASN1_item_i2d_mem_bio(const ASN1_ITEM *it, const ASN1_VALUE *val)
+{
+ BIO *res;
+
+ if (it == NULL || val == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+
+ if ((res = BIO_new(BIO_s_mem())) == NULL)
+ return NULL;
+ if (ASN1_item_i2d_bio(it, res, val) <= 0) {
+ BIO_free(res);
+ res = NULL;
+ }
+ return res;
+}
diff --git a/crypto/asn1/a_int.c b/crypto/asn1/a_int.c
index 9c1a9f52b5e6..19e41ec73e35 100644
--- a/crypto/asn1/a_int.c
+++ b/crypto/asn1/a_int.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -79,8 +79,14 @@ static void twos_complement(unsigned char *dst, const unsigned char *src,
unsigned int carry = pad & 1;
/* Begin at the end of the encoding */
- dst += len;
- src += len;
+ if (len != 0) {
+ /*
+ * if len == 0 then src/dst could be NULL, and this would be undefined
+ * behaviour.
+ */
+ dst += len;
+ src += len;
+ }
/* two's complement value: ~value + 1 */
while (len-- != 0) {
*(--dst) = (unsigned char)(carry += *(--src) ^ pad);
@@ -151,7 +157,7 @@ static size_t c2i_ibuf(unsigned char *b, int *pneg,
int neg, pad;
/* Zero content length is illegal */
if (plen == 0) {
- ASN1err(ASN1_F_C2I_IBUF, ASN1_R_ILLEGAL_ZERO_CONTENT);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT);
return 0;
}
neg = p[0] & 0x80;
@@ -184,7 +190,7 @@ static size_t c2i_ibuf(unsigned char *b, int *pneg,
}
/* reject illegal padding: first two octets MSB can't match */
if (pad && (neg == (p[1] & 0x80))) {
- ASN1err(ASN1_F_C2I_IBUF, ASN1_R_ILLEGAL_PADDING);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_PADDING);
return 0;
}
@@ -198,7 +204,7 @@ static size_t c2i_ibuf(unsigned char *b, int *pneg,
return plen;
}
-int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
+int ossl_i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
{
return i2c_ibuf(a->data, a->length, a->type & V_ASN1_NEG, pp);
}
@@ -210,7 +216,7 @@ static int asn1_get_uint64(uint64_t *pr, const unsigned char *b, size_t blen)
uint64_t r;
if (blen > sizeof(*pr)) {
- ASN1err(ASN1_F_ASN1_GET_UINT64, ASN1_R_TOO_LARGE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
return 0;
}
if (b == NULL)
@@ -262,14 +268,14 @@ static int asn1_get_int64(int64_t *pr, const unsigned char *b, size_t blen,
* on ones'-complement system. */
*pr = (int64_t)(0 - r);
} else {
- ASN1err(ASN1_F_ASN1_GET_INT64, ASN1_R_TOO_SMALL);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL);
return 0;
}
} else {
if (r <= INT64_MAX) {
*pr = (int64_t)r;
} else {
- ASN1err(ASN1_F_ASN1_GET_INT64, ASN1_R_TOO_LARGE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
return 0;
}
}
@@ -277,8 +283,8 @@ static int asn1_get_int64(int64_t *pr, const unsigned char *b, size_t blen,
}
/* Convert ASN1 INTEGER content octets to ASN1_INTEGER structure */
-ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
- long len)
+ASN1_INTEGER *ossl_c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
+ long len)
{
ASN1_INTEGER *ret = NULL;
size_t r;
@@ -302,16 +308,18 @@ ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
c2i_ibuf(ret->data, &neg, *pp, len);
- if (neg)
+ if (neg != 0)
ret->type |= V_ASN1_NEG;
+ else
+ ret->type &= ~V_ASN1_NEG;
*pp += len;
if (a != NULL)
(*a) = ret;
return ret;
err:
- ASN1err(ASN1_F_C2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
- if ((a == NULL) || (*a != ret))
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
+ if (a == NULL || *a != ret)
ASN1_INTEGER_free(ret);
return NULL;
}
@@ -319,11 +327,11 @@ ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
static int asn1_string_get_int64(int64_t *pr, const ASN1_STRING *a, int itype)
{
if (a == NULL) {
- ASN1err(ASN1_F_ASN1_STRING_GET_INT64, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if ((a->type & ~V_ASN1_NEG) != itype) {
- ASN1err(ASN1_F_ASN1_STRING_GET_INT64, ASN1_R_WRONG_INTEGER_TYPE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_INTEGER_TYPE);
return 0;
}
return asn1_get_int64(pr, a->data, a->length, a->type & V_ASN1_NEG);
@@ -354,15 +362,15 @@ static int asn1_string_get_uint64(uint64_t *pr, const ASN1_STRING *a,
int itype)
{
if (a == NULL) {
- ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if ((a->type & ~V_ASN1_NEG) != itype) {
- ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ASN1_R_WRONG_INTEGER_TYPE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_INTEGER_TYPE);
return 0;
}
if (a->type & V_ASN1_NEG) {
- ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
return 0;
}
return asn1_get_uint64(pr, a->data, a->length);
@@ -390,7 +398,7 @@ ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
ASN1_INTEGER *ret = NULL;
const unsigned char *p;
unsigned char *s;
- long len;
+ long len = 0;
int inf, tag, xclass;
int i;
@@ -413,6 +421,10 @@ ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
goto err;
}
+ if (len < 0) {
+ i = ASN1_R_ILLEGAL_NEGATIVE_VALUE;
+ goto err;
+ }
/*
* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
* a missing NULL parameter.
@@ -440,7 +452,7 @@ ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
*pp = p;
return ret;
err:
- ASN1err(ASN1_F_D2I_ASN1_UINTEGER, i);
+ ERR_raise(ERR_LIB_ASN1, i);
if ((a == NULL) || (*a != ret))
ASN1_INTEGER_free(ret);
return NULL;
@@ -460,7 +472,7 @@ static ASN1_STRING *bn_to_asn1_string(const BIGNUM *bn, ASN1_STRING *ai,
}
if (ret == NULL) {
- ASN1err(ASN1_F_BN_TO_ASN1_STRING, ERR_R_NESTED_ASN1_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
goto err;
}
@@ -473,7 +485,7 @@ static ASN1_STRING *bn_to_asn1_string(const BIGNUM *bn, ASN1_STRING *ai,
len = 1;
if (ASN1_STRING_set(ret, NULL, len) == 0) {
- ASN1err(ASN1_F_BN_TO_ASN1_STRING, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -496,13 +508,13 @@ static BIGNUM *asn1_string_to_bn(const ASN1_INTEGER *ai, BIGNUM *bn,
BIGNUM *ret;
if ((ai->type & ~V_ASN1_NEG) != itype) {
- ASN1err(ASN1_F_ASN1_STRING_TO_BN, ASN1_R_WRONG_INTEGER_TYPE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_INTEGER_TYPE);
return NULL;
}
ret = BN_bin2bn(ai->data, ai->length, bn);
if (ret == NULL) {
- ASN1err(ASN1_F_ASN1_STRING_TO_BN, ASN1_R_BN_LIB);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_BN_LIB);
return NULL;
}
if (ai->type & V_ASN1_NEG)
@@ -603,7 +615,8 @@ BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn)
}
/* Internal functions used by x_int64.c */
-int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len)
+int ossl_c2i_uint64_int(uint64_t *ret, int *neg,
+ const unsigned char **pp, long len)
{
unsigned char buf[sizeof(uint64_t)];
size_t buflen;
@@ -612,14 +625,14 @@ int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len)
if (buflen == 0)
return 0;
if (buflen > sizeof(uint64_t)) {
- ASN1err(ASN1_F_C2I_UINT64_INT, ASN1_R_TOO_LARGE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
return 0;
}
(void)c2i_ibuf(buf, neg, *pp, len);
return asn1_get_uint64(ret, buf, buflen);
}
-int i2c_uint64_int(unsigned char *p, uint64_t r, int neg)
+int ossl_i2c_uint64_int(unsigned char *p, uint64_t r, int neg)
{
unsigned char buf[sizeof(uint64_t)];
size_t off;
diff --git a/crypto/asn1/a_mbstr.c b/crypto/asn1/a_mbstr.c
index bdb697ab30c1..22dea873eeba 100644
--- a/crypto/asn1/a_mbstr.c
+++ b/crypto/asn1/a_mbstr.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,6 +10,7 @@
#include <stdio.h>
#include "crypto/ctype.h"
#include "internal/cryptlib.h"
+#include "internal/unicode.h"
#include <openssl/asn1.h>
static int traverse_string(const unsigned char *p, int len, int inform,
@@ -49,20 +50,20 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
ASN1_STRING *dest;
unsigned char *p;
int nchar;
- char strbuf[32];
int (*cpyfunc) (unsigned long, void *) = NULL;
if (len == -1)
len = strlen((const char *)in);
if (!mask)
mask = DIRSTRING_TYPE;
+ if (len < 0)
+ return -1;
/* First do a string check and work out the number of characters */
switch (inform) {
case MBSTRING_BMP:
if (len & 1) {
- ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
- ASN1_R_INVALID_BMPSTRING_LENGTH);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
return -1;
}
nchar = len >> 1;
@@ -70,8 +71,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
case MBSTRING_UNIV:
if (len & 3) {
- ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
- ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
return -1;
}
nchar = len >> 2;
@@ -82,7 +82,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
/* This counts the characters and does utf8 syntax checking */
ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
if (ret < 0) {
- ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_INVALID_UTF8STRING);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_UTF8STRING);
return -1;
}
break;
@@ -92,27 +92,25 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
break;
default:
- ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_UNKNOWN_FORMAT);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT);
return -1;
}
if ((minsize > 0) && (nchar < minsize)) {
- ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_SHORT);
- BIO_snprintf(strbuf, sizeof(strbuf), "%ld", minsize);
- ERR_add_error_data(2, "minsize=", strbuf);
+ ERR_raise_data(ERR_LIB_ASN1, ASN1_R_STRING_TOO_SHORT,
+ "minsize=%ld", minsize);
return -1;
}
if ((maxsize > 0) && (nchar > maxsize)) {
- ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_LONG);
- BIO_snprintf(strbuf, sizeof(strbuf), "%ld", maxsize);
- ERR_add_error_data(2, "maxsize=", strbuf);
+ ERR_raise_data(ERR_LIB_ASN1, ASN1_R_STRING_TOO_LONG,
+ "maxsize=%ld", maxsize);
return -1;
}
/* Now work out minimal type (if any) */
if (traverse_string(in, len, inform, type_str, &mask) < 0) {
- ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_ILLEGAL_CHARACTERS);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_CHARACTERS);
return -1;
}
@@ -149,7 +147,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
free_out = 1;
dest = ASN1_STRING_type_new(str_type);
if (dest == NULL) {
- ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
*out = dest;
@@ -157,7 +155,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
/* If both the same type just copy across */
if (inform == outform) {
if (!ASN1_STRING_set(dest, in, len)) {
- ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
return str_type;
@@ -189,7 +187,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
if ((p = OPENSSL_malloc(outlen + 1)) == NULL) {
if (free_out)
ASN1_STRING_free(dest);
- ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
dest->length = outlen;
@@ -247,6 +245,9 @@ static int traverse_string(const unsigned char *p, int len, int inform,
static int in_utf8(unsigned long value, void *arg)
{
int *nchar;
+
+ if (!is_unicode_valid(value))
+ return -2;
nchar = arg;
(*nchar)++;
return 1;
@@ -256,9 +257,13 @@ static int in_utf8(unsigned long value, void *arg)
static int out_utf8(unsigned long value, void *arg)
{
- int *outlen;
+ int *outlen, len;
+
+ len = UTF8_putc(NULL, -1, value);
+ if (len <= 0)
+ return len;
outlen = arg;
- *outlen += UTF8_putc(NULL, -1, value);
+ *outlen += len;
return 1;
}
@@ -283,6 +288,8 @@ static int type_str(unsigned long value, void *arg)
types &= ~B_ASN1_T61STRING;
if ((types & B_ASN1_BMPSTRING) && (value > 0xffff))
types &= ~B_ASN1_BMPSTRING;
+ if ((types & B_ASN1_UTF8STRING) && !is_unicode_valid(value))
+ types &= ~B_ASN1_UTF8STRING;
if (!types)
return -1;
*((unsigned long *)arg) = types;
diff --git a/crypto/asn1/a_object.c b/crypto/asn1/a_object.c
index 8ade9e50a7cb..c96c36e73029 100644
--- a/crypto/asn1/a_object.c
+++ b/crypto/asn1/a_object.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -32,7 +32,7 @@ int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp)
if (*pp == NULL) {
if ((p = allocated = OPENSSL_malloc(objsize)) == NULL) {
- ASN1err(ASN1_F_I2D_ASN1_OBJECT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
} else {
@@ -70,12 +70,12 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
if ((c >= '0') && (c <= '2')) {
first = c - '0';
} else {
- ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_FIRST_NUM_TOO_LARGE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_FIRST_NUM_TOO_LARGE);
goto err;
}
if (num <= 0) {
- ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_MISSING_SECOND_NUMBER);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_SECOND_NUMBER);
goto err;
}
c = *(p++);
@@ -84,7 +84,7 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
if (num <= 0)
break;
if ((c != '.') && (c != ' ')) {
- ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_SEPARATOR);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_SEPARATOR);
goto err;
}
l = 0;
@@ -97,7 +97,7 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
if ((c == ' ') || (c == '.'))
break;
if (!ossl_isdigit(c)) {
- ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_DIGIT);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_DIGIT);
goto err;
}
if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) {
@@ -116,8 +116,7 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
}
if (len == 0) {
if ((first < 2) && (l >= 40)) {
- ASN1err(ASN1_F_A2D_ASN1_OBJECT,
- ASN1_R_SECOND_NUMBER_TOO_LARGE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_SECOND_NUMBER_TOO_LARGE);
goto err;
}
if (use_bn) {
@@ -136,8 +135,10 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
OPENSSL_free(tmp);
tmpsize = blsize + 32;
tmp = OPENSSL_malloc(tmpsize);
- if (tmp == NULL)
+ if (tmp == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
+ }
}
while (blsize--) {
BN_ULONG t = BN_div_word(bl, 0x80L);
@@ -157,7 +158,7 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
}
if (out != NULL) {
if (len + i > olen) {
- ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_BUFFER_TOO_SMALL);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_BUFFER_TOO_SMALL);
goto err;
}
while (--i > 0)
@@ -191,8 +192,12 @@ int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a)
return BIO_write(bp, "NULL", 4);
i = i2t_ASN1_OBJECT(buf, sizeof(buf), a);
if (i > (int)(sizeof(buf) - 1)) {
+ if (i > INT_MAX - 1) { /* catch an integer overflow */
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_LENGTH_TOO_LONG);
+ return -1;
+ }
if ((p = OPENSSL_malloc(i + 1)) == NULL) {
- ASN1err(ASN1_F_I2A_ASN1_OBJECT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
i2t_ASN1_OBJECT(p, i + 1, a);
@@ -227,17 +232,17 @@ ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
i = ASN1_R_EXPECTING_AN_OBJECT;
goto err;
}
- ret = c2i_ASN1_OBJECT(a, &p, len);
+ ret = ossl_c2i_ASN1_OBJECT(a, &p, len);
if (ret)
*pp = p;
return ret;
err:
- ASN1err(ASN1_F_D2I_ASN1_OBJECT, i);
+ ERR_raise(ERR_LIB_ASN1, i);
return NULL;
}
-ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
- long len)
+ASN1_OBJECT *ossl_c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
+ long len)
{
ASN1_OBJECT *ret = NULL, tobj;
const unsigned char *p;
@@ -251,7 +256,7 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
*/
if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
p[len - 1] & 0x80) {
- ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
return NULL;
}
/* Now 0 < len <= INT_MAX, so the cast is safe. */
@@ -281,7 +286,7 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
}
for (i = 0; i < length; i++, p++) {
if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
- ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
return NULL;
}
}
@@ -329,7 +334,7 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
*pp = p;
return ret;
err:
- ASN1err(ASN1_F_C2I_ASN1_OBJECT, i);
+ ERR_raise(ERR_LIB_ASN1, i);
if ((a == NULL) || (*a != ret))
ASN1_OBJECT_free(ret);
return NULL;
@@ -341,7 +346,7 @@ ASN1_OBJECT *ASN1_OBJECT_new(void)
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- ASN1err(ASN1_F_ASN1_OBJECT_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
@@ -353,9 +358,11 @@ void ASN1_OBJECT_free(ASN1_OBJECT *a)
if (a == NULL)
return;
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
-#ifndef CONST_STRICT /* disable purely for compile-time strict
- * const checking. Doing this on a "real"
- * compile will cause memory leaks */
+#ifndef CONST_STRICT
+ /*
+ * Disable purely for compile-time strict const checking. Doing this
+ * on a "real" compile will cause memory leaks
+ */
OPENSSL_free((void*)a->sn);
OPENSSL_free((void*)a->ln);
#endif
diff --git a/crypto/asn1/a_octet.c b/crypto/asn1/a_octet.c
index 2e1205caea00..fcb2ef0a7d08 100644
--- a/crypto/asn1/a_octet.c
+++ b/crypto/asn1/a_octet.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/asn1/a_print.c b/crypto/asn1/a_print.c
index 3790e82bb13a..d2768f74bdcd 100644
--- a/crypto/asn1/a_print.c
+++ b/crypto/asn1/a_print.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/asn1/a_sign.c b/crypto/asn1/a_sign.c
index 72381b665551..302045cfcdfa 100644
--- a/crypto/asn1/a_sign.c
+++ b/crypto/asn1/a_sign.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -18,10 +18,11 @@
#include <openssl/x509.h>
#include <openssl/objects.h>
#include <openssl/buffer.h>
+#include <openssl/core_names.h>
#include "crypto/asn1.h"
#include "crypto/evp.h"
-#ifndef NO_ASN1_OLD
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey,
@@ -34,7 +35,7 @@ int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
X509_ALGOR *a;
if (ctx == NULL) {
- ASN1err(ASN1_F_ASN1_SIGN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
for (i = 0; i < 2; i++) {
@@ -61,27 +62,27 @@ int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
ASN1_OBJECT_free(a->algorithm);
a->algorithm = OBJ_nid2obj(type->pkey_type);
if (a->algorithm == NULL) {
- ASN1err(ASN1_F_ASN1_SIGN, ASN1_R_UNKNOWN_OBJECT_TYPE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_OBJECT_TYPE);
goto err;
}
if (a->algorithm->length == 0) {
- ASN1err(ASN1_F_ASN1_SIGN,
- ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
+ ERR_raise(ERR_LIB_ASN1,
+ ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
goto err;
}
}
inl = i2d(data, NULL);
if (inl <= 0) {
- ASN1err(ASN1_F_ASN1_SIGN, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
goto err;
}
inll = (size_t)inl;
buf_in = OPENSSL_malloc(inll);
- outll = outl = EVP_PKEY_size(pkey);
+ outll = outl = EVP_PKEY_get_size(pkey);
buf_out = OPENSSL_malloc(outll);
if (buf_in == NULL || buf_out == NULL) {
outl = 0;
- ASN1err(ASN1_F_ASN1_SIGN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
p = buf_in;
@@ -92,7 +93,7 @@ int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
|| !EVP_SignFinal(ctx, (unsigned char *)buf_out,
(unsigned int *)&outl, pkey)) {
outl = 0;
- ASN1err(ASN1_F_ASN1_SIGN, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
goto err;
}
OPENSSL_free(signature->data);
@@ -114,54 +115,104 @@ int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
#endif
-int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1,
- X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *asn,
- EVP_PKEY *pkey, const EVP_MD *type)
+int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
+ ASN1_BIT_STRING *signature, const void *data,
+ EVP_PKEY *pkey, const EVP_MD *md)
{
- int rv;
- EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+ return ASN1_item_sign_ex(it, algor1, algor2, signature, data, NULL, pkey,
+ md, NULL, NULL);
+}
+
+int ASN1_item_sign_ex(const ASN1_ITEM *it, X509_ALGOR *algor1,
+ X509_ALGOR *algor2, ASN1_BIT_STRING *signature,
+ const void *data, const ASN1_OCTET_STRING *id,
+ EVP_PKEY *pkey, const EVP_MD *md, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ int rv = 0;
+ EVP_MD_CTX *ctx = evp_md_ctx_new_ex(pkey, id, libctx, propq);
if (ctx == NULL) {
- ASN1err(ASN1_F_ASN1_ITEM_SIGN, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- if (!EVP_DigestSignInit(ctx, NULL, type, NULL, pkey)) {
- EVP_MD_CTX_free(ctx);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
+ /* We can use the non _ex variant here since the pkey is already setup */
+ if (!EVP_DigestSignInit(ctx, NULL, md, NULL, pkey))
+ goto err;
- rv = ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, ctx);
+ rv = ASN1_item_sign_ctx(it, algor1, algor2, signature, data, ctx);
+ err:
+ EVP_PKEY_CTX_free(EVP_MD_CTX_get_pkey_ctx(ctx));
EVP_MD_CTX_free(ctx);
return rv;
}
-int ASN1_item_sign_ctx(const ASN1_ITEM *it,
- X509_ALGOR *algor1, X509_ALGOR *algor2,
- ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
+int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1,
+ X509_ALGOR *algor2, ASN1_BIT_STRING *signature,
+ const void *data, EVP_MD_CTX *ctx)
{
- const EVP_MD *type;
+ const EVP_MD *md;
EVP_PKEY *pkey;
unsigned char *buf_in = NULL, *buf_out = NULL;
size_t inl = 0, outl = 0, outll = 0;
int signid, paramtype, buf_len = 0;
- int rv;
+ int rv, pkey_id;
- type = EVP_MD_CTX_md(ctx);
- pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx));
+ md = EVP_MD_CTX_get0_md(ctx);
+ pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
if (pkey == NULL) {
- ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
goto err;
}
if (pkey->ameth == NULL) {
- ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
- goto err;
- }
+ EVP_PKEY_CTX *pctx = EVP_MD_CTX_get_pkey_ctx(ctx);
+ OSSL_PARAM params[2];
+ unsigned char aid[128];
+ size_t aid_len = 0;
+
+ if (pctx == NULL
+ || !EVP_PKEY_CTX_IS_SIGNATURE_OP(pctx)) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
+ goto err;
+ }
- if (pkey->ameth->item_sign) {
- rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2, signature);
+ params[0] =
+ OSSL_PARAM_construct_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID,
+ aid, sizeof(aid));
+ params[1] = OSSL_PARAM_construct_end();
+
+ if (EVP_PKEY_CTX_get_params(pctx, params) <= 0)
+ goto err;
+
+ if ((aid_len = params[0].return_size) == 0) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
+ goto err;
+ }
+
+ if (algor1 != NULL) {
+ const unsigned char *pp = aid;
+
+ if (d2i_X509_ALGOR(&algor1, &pp, aid_len) == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+
+ if (algor2 != NULL) {
+ const unsigned char *pp = aid;
+
+ if (d2i_X509_ALGOR(&algor2, &pp, aid_len) == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+
+ rv = 3;
+ } else if (pkey->ameth->item_sign) {
+ rv = pkey->ameth->item_sign(ctx, it, data, algor1, algor2, signature);
if (rv == 1)
outl = signature->length;
/*-
@@ -172,7 +223,7 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it,
* 3: ASN1 method sets algorithm identifiers: just sign.
*/
if (rv <= 0)
- ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
if (rv <= 1)
goto err;
} else {
@@ -180,15 +231,19 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it,
}
if (rv == 2) {
- if (type == NULL) {
- ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
goto err;
}
- if (!OBJ_find_sigid_by_algs(&signid,
- EVP_MD_nid(type),
- pkey->ameth->pkey_id)) {
- ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,
- ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
+
+ pkey_id =
+#ifndef OPENSSL_NO_SM2
+ EVP_PKEY_get_id(pkey) == NID_sm2 ? NID_sm2 :
+#endif
+ pkey->ameth->pkey_id;
+
+ if (!OBJ_find_sigid_by_algs(&signid, EVP_MD_nid(md), pkey_id)) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
goto err;
}
@@ -204,24 +259,29 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it,
}
- buf_len = ASN1_item_i2d(asn, &buf_in, it);
+ buf_len = ASN1_item_i2d(data, &buf_in, it);
if (buf_len <= 0) {
outl = 0;
- ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
goto err;
}
inl = buf_len;
- outll = outl = EVP_PKEY_size(pkey);
+ if (!EVP_DigestSign(ctx, NULL, &outll, buf_in, inl)) {
+ outl = 0;
+ ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
+ goto err;
+ }
+ outl = outll;
buf_out = OPENSSL_malloc(outll);
if (buf_in == NULL || buf_out == NULL) {
outl = 0;
- ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EVP_DigestSign(ctx, buf_out, &outl, buf_in, inl)) {
outl = 0;
- ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
goto err;
}
OPENSSL_free(signature->data);
diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c
index 284dde274c9f..b31761aae6f5 100644
--- a/crypto/asn1/a_strex.c
+++ b/crypto/asn1/a_strex.c
@@ -1,7 +1,7 @@
/*
* Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -32,7 +32,7 @@
ASN1_STRFLGS_ESC_MSB)
/*
- * Three IO functions for sending data to memory, a BIO and and a FILE
+ * Three IO functions for sending data to memory, a BIO and a FILE
* pointer.
*/
static int send_bio_chars(void *arg, const void *buf, int len)
@@ -152,13 +152,13 @@ static int do_buf(unsigned char *buf, int buflen,
switch (charwidth) {
case 4:
if (buflen & 3) {
- ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
return -1;
}
break;
case 2:
if (buflen & 1) {
- ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_BMPSTRING_LENGTH);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
return -1;
}
break;
@@ -283,7 +283,7 @@ static int do_dump(unsigned long lflags, char_io *io_ch, void *arg,
if (der_len <= 0)
return -1;
if ((der_buf = OPENSSL_malloc(der_len)) == NULL) {
- ASN1err(ASN1_F_DO_DUMP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
p = der_buf;
diff --git a/crypto/asn1/a_strnid.c b/crypto/asn1/a_strnid.c
index f19a9de647b1..9e54db929282 100644
--- a/crypto/asn1/a_strnid.c
+++ b/crypto/asn1/a_strnid.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -51,7 +51,7 @@ int ASN1_STRING_set_default_mask_asc(const char *p)
char *end;
if (strncmp(p, "MASK:", 5) == 0) {
- if (!p[5])
+ if (p[5] == '\0')
return 0;
mask = strtoul(p + 5, &end, 0);
if (*end)
@@ -129,6 +129,9 @@ ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
int idx;
ASN1_STRING_TABLE fnd;
+ /* "stable" can be impacted by config, so load the config file first */
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+
fnd.nid = nid;
if (stable) {
idx = sk_ASN1_STRING_TABLE_find(stable, &fnd);
@@ -157,7 +160,7 @@ static ASN1_STRING_TABLE *stable_get(int nid)
if (tmp != NULL && tmp->flags & STABLE_FLAGS_MALLOC)
return tmp;
if ((rv = OPENSSL_zalloc(sizeof(*rv))) == NULL) {
- ASN1err(ASN1_F_STABLE_GET, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (!sk_ASN1_STRING_TABLE_push(stable, rv)) {
@@ -187,7 +190,7 @@ int ASN1_STRING_TABLE_add(int nid,
tmp = stable_get(nid);
if (tmp == NULL) {
- ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
if (minsize >= 0)
diff --git a/crypto/asn1/a_time.c b/crypto/asn1/a_time.c
index 54e0de1931c2..9b3074e47e84 100644
--- a/crypto/asn1/a_time.c
+++ b/crypto/asn1/a_time.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -16,6 +16,7 @@
#include <stdio.h>
#include <time.h>
+#include "crypto/asn1.h"
#include "crypto/ctype.h"
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
@@ -24,6 +25,7 @@
IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
+IMPLEMENT_ASN1_DUP_FUNCTION(ASN1_TIME)
static int is_utc(const int year)
{
@@ -71,7 +73,7 @@ static void determine_days(struct tm *tm)
tm->tm_wday = (d + (13 * m) / 5 + y + y / 4 + c / 4 + 5 * c + 6) % 7;
}
-int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
+int ossl_asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
{
static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
@@ -128,14 +130,14 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
i++;
break;
}
- if (!ascii_isdigit(a[o]))
+ if (!ossl_ascii_isdigit(a[o]))
goto err;
n = a[o] - num_zero;
/* incomplete 2-digital number */
if (++o == l)
goto err;
- if (!ascii_isdigit(a[o]))
+ if (!ossl_ascii_isdigit(a[o]))
goto err;
n = (n * 10) + a[o] - num_zero;
/* no more bytes to read, but we haven't seen time-zone yet */
@@ -196,7 +198,7 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
if (++o == l)
goto err;
i = o;
- while ((o < l) && ascii_isdigit(a[o]))
+ while ((o < l) && ossl_ascii_isdigit(a[o]))
o++;
/* Must have at least one digit after decimal point */
if (i == o)
@@ -227,11 +229,11 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
if (o + 4 != l)
goto err;
for (i = end; i < end + 2; i++) {
- if (!ascii_isdigit(a[o]))
+ if (!ossl_ascii_isdigit(a[o]))
goto err;
n = a[o] - num_zero;
o++;
- if (!ascii_isdigit(a[o]))
+ if (!ossl_ascii_isdigit(a[o]))
goto err;
n = (n * 10) + a[o] - num_zero;
i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i;
@@ -262,7 +264,7 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
return 0;
}
-ASN1_TIME *asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type)
+ASN1_TIME *ossl_asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type)
{
char* p;
ASN1_TIME *tmps = NULL;
@@ -327,14 +329,14 @@ ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
ts = OPENSSL_gmtime(&t, &data);
if (ts == NULL) {
- ASN1err(ASN1_F_ASN1_TIME_ADJ, ASN1_R_ERROR_GETTING_TIME);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_GETTING_TIME);
return NULL;
}
if (offset_day || offset_sec) {
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
return NULL;
}
- return asn1_time_from_tm(s, ts, V_ASN1_UNDEF);
+ return ossl_asn1_time_from_tm(s, ts, V_ASN1_UNDEF);
}
int ASN1_TIME_check(const ASN1_TIME *t)
@@ -359,7 +361,7 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
if (out != NULL)
ret = *out;
- ret = asn1_time_from_tm(ret, &tm, V_ASN1_GENERALIZEDTIME);
+ ret = ossl_asn1_time_from_tm(ret, &tm, V_ASN1_GENERALIZEDTIME);
if (out != NULL && ret != NULL)
*out = ret;
@@ -408,7 +410,7 @@ int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str)
*/
if (s != NULL && t.type == V_ASN1_GENERALIZEDTIME) {
- if (!asn1_time_to_tm(&tm, &t))
+ if (!ossl_asn1_time_to_tm(&tm, &t))
goto out;
if (is_utc(tm.tm_year)) {
t.length -= 2;
@@ -418,8 +420,10 @@ int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str)
* new t.data would be freed after ASN1_STRING_copy is done.
*/
t.data = OPENSSL_zalloc(t.length + 1);
- if (t.data == NULL)
+ if (t.data == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto out;
+ }
memcpy(t.data, str + 2, t.length);
t.type = V_ASN1_UTCTIME;
}
@@ -446,7 +450,7 @@ int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm)
return 0;
}
- return asn1_time_to_tm(tm, s);
+ return ossl_asn1_time_to_tm(tm, s);
}
int ASN1_TIME_diff(int *pday, int *psec,
@@ -466,17 +470,31 @@ static const char _asn1_mon[12][4] = {
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
+/* prints the time with the default date format (RFC 822) */
int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
{
+ return ASN1_TIME_print_ex(bp, tm, ASN1_DTFLGS_RFC822);
+}
+
+/* returns 1 on success, 0 on BIO write error or parse failure */
+int ASN1_TIME_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags)
+{
+ return ossl_asn1_time_print_ex(bp, tm, flags) > 0;
+}
+
+
+/* prints the time with the date format of ISO 8601 */
+/* returns 0 on BIO write error, else -1 in case of parse failure, else 1 */
+int ossl_asn1_time_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags)
+{
char *v;
int gmt = 0, l;
struct tm stm;
const char upper_z = 0x5A, period = 0x2E;
- if (!asn1_time_to_tm(&stm, tm)) {
- /* asn1_time_to_tm will check the time type */
- goto err;
- }
+ /* ossl_asn1_time_to_tm will check the time type */
+ if (!ossl_asn1_time_to_tm(&stm, tm))
+ return BIO_write(bp, "Bad time value", 14) ? -1 : 0;
l = tm->length;
v = (char *)tm->data;
@@ -494,23 +512,38 @@ int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
if (tm->length > 15 && v[14] == period) {
f = &v[14];
f_len = 1;
- while (14 + f_len < l && ascii_isdigit(f[f_len]))
+ while (14 + f_len < l && ossl_ascii_isdigit(f[f_len]))
++f_len;
}
- return BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
+ if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
+ return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d%.*s%s",
+ stm.tm_year + 1900, stm.tm_mon + 1,
+ stm.tm_mday, stm.tm_hour,
+ stm.tm_min, stm.tm_sec, f_len, f,
+ (gmt ? "Z" : "")) > 0;
+ }
+ else {
+ return BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
_asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
stm.tm_min, stm.tm_sec, f_len, f, stm.tm_year + 1900,
(gmt ? " GMT" : "")) > 0;
+ }
} else {
- return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s",
+ if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
+ return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d%s",
+ stm.tm_year + 1900, stm.tm_mon + 1,
+ stm.tm_mday, stm.tm_hour,
+ stm.tm_min, stm.tm_sec,
+ (gmt ? "Z" : "")) > 0;
+ }
+ else {
+ return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s",
_asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
stm.tm_min, stm.tm_sec, stm.tm_year + 1900,
(gmt ? " GMT" : "")) > 0;
+ }
}
- err:
- BIO_write(bp, "Bad time value", 14);
- return 0;
}
int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t)
@@ -541,7 +574,7 @@ int ASN1_TIME_normalize(ASN1_TIME *t)
if (!ASN1_TIME_to_tm(t, &tm))
return 0;
- return asn1_time_from_tm(t, &tm, V_ASN1_UNDEF) != NULL;
+ return ossl_asn1_time_from_tm(t, &tm, V_ASN1_UNDEF) != NULL;
}
int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b)
diff --git a/crypto/asn1/a_type.c b/crypto/asn1/a_type.c
index 4a96315df03b..6b638bd80c18 100644
--- a/crypto/asn1/a_type.c
+++ b/crypto/asn1/a_type.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -29,7 +29,7 @@ void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
&& a->type != V_ASN1_NULL
&& a->value.ptr != NULL) {
ASN1_TYPE **tmp_a = &a;
- asn1_primitive_free((ASN1_VALUE **)tmp_a, NULL, 0);
+ ossl_asn1_primitive_free((ASN1_VALUE **)tmp_a, NULL, 0);
}
a->type = type;
if (type == V_ASN1_BOOLEAN)
diff --git a/crypto/asn1/a_utctm.c b/crypto/asn1/a_utctm.c
index 0ff37b16c51f..323941ba97e2 100644
--- a/crypto/asn1/a_utctm.c
+++ b/crypto/asn1/a_utctm.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,19 +12,22 @@
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include "asn1_local.h"
+#include <openssl/asn1t.h>
+
+IMPLEMENT_ASN1_DUP_FUNCTION(ASN1_UTCTIME)
/* This is the primary function used to parse ASN1_UTCTIME */
-int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
+int ossl_asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
{
- /* wrapper around ans1_time_to_tm */
+ /* wrapper around ossl_asn1_time_to_tm */
if (d->type != V_ASN1_UTCTIME)
return 0;
- return asn1_time_to_tm(tm, d);
+ return ossl_asn1_time_to_tm(tm, d);
}
int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
{
- return asn1_utctime_to_tm(NULL, d);
+ return ossl_asn1_utctime_to_tm(NULL, d);
}
/* Sets the string via simple copy without cleaning it up */
@@ -66,7 +69,7 @@ ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
return NULL;
}
- return asn1_time_from_tm(s, ts, V_ASN1_UTCTIME);
+ return ossl_asn1_time_from_tm(s, ts, V_ASN1_UTCTIME);
}
int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
@@ -74,7 +77,7 @@ int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
struct tm stm, ttm;
int day, sec;
- if (!asn1_utctime_to_tm(&stm, s))
+ if (!ossl_asn1_utctime_to_tm(&stm, s))
return -2;
if (OPENSSL_gmtime(&t, &ttm) == NULL)
diff --git a/crypto/asn1/a_utf8.c b/crypto/asn1/a_utf8.c
index e2dc09f6aee5..6572726cf1e5 100644
--- a/crypto/asn1/a_utf8.c
+++ b/crypto/asn1/a_utf8.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,6 +9,7 @@
#include <stdio.h>
#include "internal/cryptlib.h"
+#include "internal/unicode.h"
#include <openssl/asn1.h>
/* UTF8 utilities */
@@ -58,6 +59,8 @@ int UTF8_getc(const unsigned char *str, int len, unsigned long *val)
value |= *p++ & 0x3f;
if (value < 0x800)
return -4;
+ if (is_unicode_surrogate(value))
+ return -2;
ret = 3;
} else if ((*p & 0xf8) == 0xf0) {
if (len < 4)
@@ -73,40 +76,6 @@ int UTF8_getc(const unsigned char *str, int len, unsigned long *val)
if (value < 0x10000)
return -4;
ret = 4;
- } else if ((*p & 0xfc) == 0xf8) {
- if (len < 5)
- return -1;
- if (((p[1] & 0xc0) != 0x80)
- || ((p[2] & 0xc0) != 0x80)
- || ((p[3] & 0xc0) != 0x80)
- || ((p[4] & 0xc0) != 0x80))
- return -3;
- value = ((unsigned long)(*p++ & 0x3)) << 24;
- value |= ((unsigned long)(*p++ & 0x3f)) << 18;
- value |= ((unsigned long)(*p++ & 0x3f)) << 12;
- value |= (*p++ & 0x3f) << 6;
- value |= *p++ & 0x3f;
- if (value < 0x200000)
- return -4;
- ret = 5;
- } else if ((*p & 0xfe) == 0xfc) {
- if (len < 6)
- return -1;
- if (((p[1] & 0xc0) != 0x80)
- || ((p[2] & 0xc0) != 0x80)
- || ((p[3] & 0xc0) != 0x80)
- || ((p[4] & 0xc0) != 0x80)
- || ((p[5] & 0xc0) != 0x80))
- return -3;
- value = ((unsigned long)(*p++ & 0x1)) << 30;
- value |= ((unsigned long)(*p++ & 0x3f)) << 24;
- value |= ((unsigned long)(*p++ & 0x3f)) << 18;
- value |= ((unsigned long)(*p++ & 0x3f)) << 12;
- value |= (*p++ & 0x3f) << 6;
- value |= *p++ & 0x3f;
- if (value < 0x4000000)
- return -4;
- ret = 6;
} else
return -2;
*val = value;
@@ -116,15 +85,15 @@ int UTF8_getc(const unsigned char *str, int len, unsigned long *val)
/*
* This takes a character 'value' and writes the UTF8 encoded value in 'str'
* where 'str' is a buffer containing 'len' characters. Returns the number of
- * characters written or -1 if 'len' is too small. 'str' can be set to NULL
- * in which case it just returns the number of characters. It will need at
- * most 6 characters.
+ * characters written, -1 if 'len' is too small or -2 if 'value' is out of
+ * range. 'str' can be set to NULL in which case it just returns the number of
+ * characters. It will need at most 4 characters.
*/
int UTF8_putc(unsigned char *str, int len, unsigned long value)
{
if (!str)
- len = 6; /* Maximum we will need */
+ len = 4; /* Maximum we will need */
else if (len <= 0)
return -1;
if (value < 0x80) {
@@ -142,6 +111,8 @@ int UTF8_putc(unsigned char *str, int len, unsigned long value)
return 2;
}
if (value < 0x10000) {
+ if (is_unicode_surrogate(value))
+ return -2;
if (len < 3)
return -1;
if (str) {
@@ -151,7 +122,7 @@ int UTF8_putc(unsigned char *str, int len, unsigned long value)
}
return 3;
}
- if (value < 0x200000) {
+ if (value < UNICODE_LIMIT) {
if (len < 4)
return -1;
if (str) {
@@ -162,27 +133,5 @@ int UTF8_putc(unsigned char *str, int len, unsigned long value)
}
return 4;
}
- if (value < 0x4000000) {
- if (len < 5)
- return -1;
- if (str) {
- *str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8);
- *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
- *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
- *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
- *str = (unsigned char)((value & 0x3f) | 0x80);
- }
- return 5;
- }
- if (len < 6)
- return -1;
- if (str) {
- *str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc);
- *str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80);
- *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
- *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
- *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
- *str = (unsigned char)((value & 0x3f) | 0x80);
- }
- return 6;
+ return -2;
}
diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c
index 4b5f54234fa5..9bf9bdd14ecc 100644
--- a/crypto/asn1/a_verify.c
+++ b/crypto/asn1/a_verify.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -20,8 +20,9 @@
#include <openssl/evp.h>
#include "crypto/asn1.h"
#include "crypto/evp.h"
+#include "crypto/rsa.h"
-#ifndef NO_ASN1_OLD
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature,
char *data, EVP_PKEY *pkey)
@@ -32,29 +33,29 @@ int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature,
int ret = -1, i, inl;
if (ctx == NULL) {
- ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
i = OBJ_obj2nid(a->algorithm);
type = EVP_get_digestbyname(OBJ_nid2sn(i));
if (type == NULL) {
- ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
goto err;
}
if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
- ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
goto err;
}
inl = i2d(data, NULL);
if (inl <= 0) {
- ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
goto err;
}
buf_in = OPENSSL_malloc((unsigned int)inl);
if (buf_in == NULL) {
- ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
p = buf_in;
@@ -66,14 +67,14 @@ int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature,
OPENSSL_clear_free(buf_in, (unsigned int)inl);
if (!ret) {
- ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
goto err;
}
ret = -1;
if (EVP_VerifyFinal(ctx, (unsigned char *)signature->data,
(unsigned int)signature->length, pkey) <= 0) {
- ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
ret = 0;
goto err;
}
@@ -85,81 +86,127 @@ int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature,
#endif
-int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
- ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
+int ASN1_item_verify(const ASN1_ITEM *it, const X509_ALGOR *alg,
+ const ASN1_BIT_STRING *signature, const void *data,
+ EVP_PKEY *pkey)
{
- EVP_MD_CTX *ctx = NULL;
+ return ASN1_item_verify_ex(it, alg, signature, data, NULL, pkey, NULL, NULL);
+}
+
+int ASN1_item_verify_ex(const ASN1_ITEM *it, const X509_ALGOR *alg,
+ const ASN1_BIT_STRING *signature, const void *data,
+ const ASN1_OCTET_STRING *id, EVP_PKEY *pkey,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ EVP_MD_CTX *ctx;
+ int rv = -1;
+
+ if ((ctx = evp_md_ctx_new_ex(pkey, id, libctx, propq)) != NULL) {
+ rv = ASN1_item_verify_ctx(it, alg, signature, data, ctx);
+ EVP_PKEY_CTX_free(EVP_MD_CTX_get_pkey_ctx(ctx));
+ EVP_MD_CTX_free(ctx);
+ }
+ return rv;
+}
+
+int ASN1_item_verify_ctx(const ASN1_ITEM *it, const X509_ALGOR *alg,
+ const ASN1_BIT_STRING *signature, const void *data,
+ EVP_MD_CTX *ctx)
+{
+ EVP_PKEY *pkey;
unsigned char *buf_in = NULL;
int ret = -1, inl = 0;
int mdnid, pknid;
size_t inll = 0;
- if (!pkey) {
- ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_PASSED_NULL_PARAMETER);
+ pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
+
+ if (pkey == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
- ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
return -1;
}
- ctx = EVP_MD_CTX_new();
- if (ctx == NULL) {
- ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
/* Convert signature OID into digest and public key OIDs */
- if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid)) {
- ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
+ if (!OBJ_find_sigid_algs(OBJ_obj2nid(alg->algorithm), &mdnid, &pknid)) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
goto err;
}
- if (mdnid == NID_undef) {
- if (!pkey->ameth || !pkey->ameth->item_verify) {
- ASN1err(ASN1_F_ASN1_ITEM_VERIFY,
- ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
+
+ if (mdnid == NID_undef && evp_pkey_is_legacy(pkey)) {
+ if (pkey->ameth == NULL || pkey->ameth->item_verify == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
goto err;
}
- ret = pkey->ameth->item_verify(ctx, it, asn, a, signature, pkey);
+ ret = pkey->ameth->item_verify(ctx, it, data, alg, signature, pkey);
/*
- * Return value of 2 means carry on, anything else means we exit
- * straight away: either a fatal error of the underlying verification
- * routine handles all verification.
+ * Return values meaning:
+ * <=0: error.
+ * 1: method does everything.
+ * 2: carry on as normal, method has called EVP_DigestVerifyInit()
*/
- if (ret != 2)
+ if (ret <= 0)
+ ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
+ if (ret <= 1)
goto err;
- ret = -1;
} else {
- const EVP_MD *type = EVP_get_digestbynid(mdnid);
-
- if (type == NULL) {
- ASN1err(ASN1_F_ASN1_ITEM_VERIFY,
- ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
- goto err;
- }
-
- /* Check public key OID matches public key type */
- if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) {
- ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
- goto err;
- }
+ const EVP_MD *type = NULL;
- if (!EVP_DigestVerifyInit(ctx, NULL, type, NULL, pkey)) {
- ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB);
- ret = 0;
- goto err;
+ /*
+ * We don't yet have the ability for providers to be able to handle
+ * X509_ALGOR style parameters. Fortunately the only one that needs this
+ * so far is RSA-PSS, so we just special case this for now. In some
+ * future version of OpenSSL we should push this to the provider.
+ */
+ if (mdnid == NID_undef && pknid == EVP_PKEY_RSA_PSS) {
+ if (!EVP_PKEY_is_a(pkey, "RSA") && !EVP_PKEY_is_a(pkey, "RSA-PSS")) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
+ goto err;
+ }
+ /* This function also calls EVP_DigestVerifyInit */
+ if (ossl_rsa_pss_to_ctx(ctx, NULL, alg, pkey) <= 0) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ } else {
+ /* Check public key OID matches public key type */
+ if (!EVP_PKEY_is_a(pkey, OBJ_nid2sn(pknid))) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
+ goto err;
+ }
+
+ if (mdnid != NID_undef) {
+ type = EVP_get_digestbynid(mdnid);
+ if (type == NULL) {
+ ERR_raise(ERR_LIB_ASN1,
+ ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
+ goto err;
+ }
+ }
+
+ /*
+ * Note that some algorithms (notably Ed25519 and Ed448) may allow
+ * a NULL digest value.
+ */
+ if (!EVP_DigestVerifyInit(ctx, NULL, type, NULL, pkey)) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
+ ret = 0;
+ goto err;
+ }
}
-
}
- inl = ASN1_item_i2d(asn, &buf_in, it);
+ inl = ASN1_item_i2d(data, &buf_in, it);
if (inl <= 0) {
- ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
goto err;
}
if (buf_in == NULL) {
- ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
inll = inl;
@@ -167,12 +214,11 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
ret = EVP_DigestVerify(ctx, signature->data, (size_t)signature->length,
buf_in, inl);
if (ret <= 0) {
- ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
goto err;
}
ret = 1;
err:
OPENSSL_clear_free(buf_in, inll);
- EVP_MD_CTX_free(ctx);
return ret;
}
diff --git a/crypto/asn1/ameth_lib.c b/crypto/asn1/ameth_lib.c
index 5e8c3ed1d5b0..8b15da3beed6 100644
--- a/crypto/asn1/ameth_lib.c
+++ b/crypto/asn1/ameth_lib.c
@@ -1,13 +1,15 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include "e_os.h" /* for strncasecmp */
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "internal/cryptlib.h"
#include <stdio.h>
#include <openssl/asn1t.h>
@@ -56,6 +58,7 @@ static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type)
{
EVP_PKEY_ASN1_METHOD tmp;
const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret;
+
tmp.pkey_id = type;
if (app_methods) {
int idx;
@@ -64,7 +67,7 @@ static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type)
return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
}
ret = OBJ_bsearch_ameth(&t, standard_methods, OSSL_NELEM(standard_methods));
- if (!ret || !*ret)
+ if (ret == NULL || *ret == NULL)
return NULL;
return *ret;
}
@@ -130,7 +133,7 @@ const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
continue;
if ((int)strlen(ameth->pem_str) == len
- && strncasecmp(ameth->pem_str, str, len) == 0)
+ && OPENSSL_strncasecmp(ameth->pem_str, str, len) == 0)
return ameth;
}
return NULL;
@@ -152,7 +155,7 @@ int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
&& (ameth->pkey_flags & ASN1_PKEY_ALIAS) != 0)
|| (ameth->pem_str != NULL
&& (ameth->pkey_flags & ASN1_PKEY_ALIAS) == 0))) {
- EVPerr(EVP_F_EVP_PKEY_ASN1_ADD0, ERR_R_PASSED_INVALID_ARGUMENT);
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
@@ -164,8 +167,8 @@ int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
tmp.pkey_id = ameth->pkey_id;
if (sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp) >= 0) {
- EVPerr(EVP_F_EVP_PKEY_ASN1_ADD0,
- EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED);
+ ERR_raise(ERR_LIB_EVP,
+ EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED);
return 0;
}
@@ -219,8 +222,10 @@ EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
{
EVP_PKEY_ASN1_METHOD *ameth = OPENSSL_zalloc(sizeof(*ameth));
- if (ameth == NULL)
+ if (ameth == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
+ }
ameth->pkey_id = id;
ameth->pkey_base_id = id;
@@ -228,13 +233,13 @@ EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
if (info) {
ameth->info = OPENSSL_strdup(info);
- if (!ameth->info)
+ if (ameth->info == NULL)
goto err;
}
if (pem_str) {
ameth->pem_str = OPENSSL_strdup(pem_str);
- if (!ameth->pem_str)
+ if (ameth->pem_str == NULL)
goto err;
}
@@ -242,46 +247,27 @@ EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
err:
EVP_PKEY_asn1_free(ameth);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
-
}
void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst,
const EVP_PKEY_ASN1_METHOD *src)
{
-
- dst->pub_decode = src->pub_decode;
- dst->pub_encode = src->pub_encode;
- dst->pub_cmp = src->pub_cmp;
- dst->pub_print = src->pub_print;
-
- dst->priv_decode = src->priv_decode;
- dst->priv_encode = src->priv_encode;
- dst->priv_print = src->priv_print;
-
- dst->old_priv_encode = src->old_priv_encode;
- dst->old_priv_decode = src->old_priv_decode;
-
- dst->pkey_size = src->pkey_size;
- dst->pkey_bits = src->pkey_bits;
-
- dst->param_decode = src->param_decode;
- dst->param_encode = src->param_encode;
- dst->param_missing = src->param_missing;
- dst->param_copy = src->param_copy;
- dst->param_cmp = src->param_cmp;
- dst->param_print = src->param_print;
-
- dst->pkey_free = src->pkey_free;
- dst->pkey_ctrl = src->pkey_ctrl;
-
- dst->item_sign = src->item_sign;
- dst->item_verify = src->item_verify;
-
- dst->siginf_set = src->siginf_set;
-
- dst->pkey_check = src->pkey_check;
-
+ int pkey_id = dst->pkey_id;
+ int pkey_base_id = dst->pkey_base_id;
+ unsigned long pkey_flags = dst->pkey_flags;
+ char *pem_str = dst->pem_str;
+ char *info = dst->info;
+
+ *dst = *src;
+
+ /* We only copy the function pointers so restore the other values */
+ dst->pkey_id = pkey_id;
+ dst->pkey_base_id = pkey_base_id;
+ dst->pkey_flags = pkey_flags;
+ dst->pem_str = pem_str;
+ dst->info = info;
}
void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
@@ -295,7 +281,7 @@ void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
int (*pub_decode) (EVP_PKEY *pk,
- X509_PUBKEY *pub),
+ const X509_PUBKEY *pub),
int (*pub_encode) (X509_PUBKEY *pub,
const EVP_PKEY *pk),
int (*pub_cmp) (const EVP_PKEY *a,
@@ -376,13 +362,13 @@ void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth,
int (*item_verify) (EVP_MD_CTX *ctx,
const ASN1_ITEM *it,
- void *asn,
- X509_ALGOR *a,
- ASN1_BIT_STRING *sig,
+ const void *data,
+ const X509_ALGOR *a,
+ const ASN1_BIT_STRING *sig,
EVP_PKEY *pkey),
int (*item_sign) (EVP_MD_CTX *ctx,
const ASN1_ITEM *it,
- void *asn,
+ const void *data,
X509_ALGOR *alg1,
X509_ALGOR *alg2,
ASN1_BIT_STRING *sig))
diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c
index cc0a59ca4c8b..a7b32e3a6e1a 100644
--- a/crypto/asn1/asn1_err.c
+++ b/crypto/asn1/asn1_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,150 +10,10 @@
#include <openssl/err.h>
#include <openssl/asn1err.h>
+#include "crypto/asn1err.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA ASN1_str_functs[] = {
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2D_ASN1_OBJECT, 0), "a2d_ASN1_OBJECT"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2I_ASN1_INTEGER, 0), "a2i_ASN1_INTEGER"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2I_ASN1_STRING, 0), "a2i_ASN1_STRING"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_APPEND_EXP, 0), "append_exp"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_BIO_INIT, 0), "asn1_bio_init"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_BIT_STRING_SET_BIT, 0),
- "ASN1_BIT_STRING_set_bit"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_CB, 0), "asn1_cb"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_CHECK_TLEN, 0), "asn1_check_tlen"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_COLLECT, 0), "asn1_collect"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_EX_PRIMITIVE, 0),
- "asn1_d2i_ex_primitive"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_FP, 0), "ASN1_d2i_fp"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_READ_BIO, 0), "asn1_d2i_read_bio"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DIGEST, 0), "ASN1_digest"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DO_ADB, 0), "asn1_do_adb"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DO_LOCK, 0), "asn1_do_lock"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DUP, 0), "ASN1_dup"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ENC_SAVE, 0), "asn1_enc_save"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_EX_C2I, 0), "asn1_ex_c2i"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_FIND_END, 0), "asn1_find_end"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GENERALIZEDTIME_ADJ, 0),
- "ASN1_GENERALIZEDTIME_adj"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GENERATE_V3, 0), "ASN1_generate_v3"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_INT64, 0), "asn1_get_int64"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_OBJECT, 0), "ASN1_get_object"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_UINT64, 0), "asn1_get_uint64"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_I2D_BIO, 0), "ASN1_i2d_bio"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_I2D_FP, 0), "ASN1_i2d_fp"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_D2I_FP, 0), "ASN1_item_d2i_fp"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_DUP, 0), "ASN1_item_dup"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_EMBED_D2I, 0),
- "asn1_item_embed_d2i"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_EMBED_NEW, 0),
- "asn1_item_embed_new"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_EX_I2D, 0), "ASN1_item_ex_i2d"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_FLAGS_I2D, 0),
- "asn1_item_flags_i2d"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_I2D_BIO, 0), "ASN1_item_i2d_bio"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_I2D_FP, 0), "ASN1_item_i2d_fp"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_PACK, 0), "ASN1_item_pack"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_SIGN, 0), "ASN1_item_sign"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_SIGN_CTX, 0),
- "ASN1_item_sign_ctx"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_UNPACK, 0), "ASN1_item_unpack"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_VERIFY, 0), "ASN1_item_verify"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_MBSTRING_NCOPY, 0),
- "ASN1_mbstring_ncopy"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_OBJECT_NEW, 0), "ASN1_OBJECT_new"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_OUTPUT_DATA, 0), "asn1_output_data"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_PCTX_NEW, 0), "ASN1_PCTX_new"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_PRIMITIVE_NEW, 0),
- "asn1_primitive_new"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_SCTX_NEW, 0), "ASN1_SCTX_new"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_SIGN, 0), "ASN1_sign"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STR2TYPE, 0), "asn1_str2type"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_GET_INT64, 0),
- "asn1_string_get_int64"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_GET_UINT64, 0),
- "asn1_string_get_uint64"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_SET, 0), "ASN1_STRING_set"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TABLE_ADD, 0),
- "ASN1_STRING_TABLE_add"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TO_BN, 0), "asn1_string_to_bn"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TYPE_NEW, 0),
- "ASN1_STRING_type_new"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_EX_D2I, 0),
- "asn1_template_ex_d2i"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_NEW, 0), "asn1_template_new"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 0),
- "asn1_template_noexp_d2i"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TIME_ADJ, 0), "ASN1_TIME_adj"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING, 0),
- "ASN1_TYPE_get_int_octetstring"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TYPE_GET_OCTETSTRING, 0),
- "ASN1_TYPE_get_octetstring"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_UTCTIME_ADJ, 0), "ASN1_UTCTIME_adj"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_VERIFY, 0), "ASN1_verify"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_B64_READ_ASN1, 0), "b64_read_asn1"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_B64_WRITE_ASN1, 0), "B64_write_ASN1"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BIO_NEW_NDEF, 0), "BIO_new_NDEF"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BITSTR_CB, 0), "bitstr_cb"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BN_TO_ASN1_STRING, 0), "bn_to_asn1_string"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_BIT_STRING, 0),
- "c2i_ASN1_BIT_STRING"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_INTEGER, 0), "c2i_ASN1_INTEGER"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_OBJECT, 0), "c2i_ASN1_OBJECT"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_IBUF, 0), "c2i_ibuf"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_UINT64_INT, 0), "c2i_uint64_int"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_COLLECT_DATA, 0), "collect_data"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_ASN1_OBJECT, 0), "d2i_ASN1_OBJECT"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_ASN1_UINTEGER, 0), "d2i_ASN1_UINTEGER"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_AUTOPRIVATEKEY, 0),
- "d2i_AutoPrivateKey"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PRIVATEKEY, 0), "d2i_PrivateKey"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PUBLICKEY, 0), "d2i_PublicKey"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_BUF, 0), "do_buf"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_CREATE, 0), "do_create"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_DUMP, 0), "do_dump"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_TCREATE, 0), "do_tcreate"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2A_ASN1_OBJECT, 0), "i2a_ASN1_OBJECT"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_ASN1_BIO_STREAM, 0),
- "i2d_ASN1_bio_stream"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_ASN1_OBJECT, 0), "i2d_ASN1_OBJECT"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_DSA_PUBKEY, 0), "i2d_DSA_PUBKEY"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_EC_PUBKEY, 0), "i2d_EC_PUBKEY"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_PRIVATEKEY, 0), "i2d_PrivateKey"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_PUBLICKEY, 0), "i2d_PublicKey"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_RSA_PUBKEY, 0), "i2d_RSA_PUBKEY"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_LONG_C2I, 0), "long_c2i"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_NDEF_PREFIX, 0), "ndef_prefix"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_NDEF_SUFFIX, 0), "ndef_suffix"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_OID_MODULE_INIT, 0), "oid_module_init"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PARSE_TAGGING, 0), "parse_tagging"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE2_SET_IV, 0), "PKCS5_pbe2_set_iv"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE2_SET_SCRYPT, 0),
- "PKCS5_pbe2_set_scrypt"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE_SET, 0), "PKCS5_pbe_set"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE_SET0_ALGOR, 0),
- "PKCS5_pbe_set0_algor"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBKDF2_SET, 0), "PKCS5_pbkdf2_set"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_SCRYPT_SET, 0), "pkcs5_scrypt_set"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_SMIME_READ_ASN1, 0), "SMIME_read_ASN1"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_SMIME_TEXT, 0), "SMIME_text"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_STABLE_GET, 0), "stable_get"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_STBL_MODULE_INIT, 0), "stbl_module_init"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT32_C2I, 0), "uint32_c2i"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT32_NEW, 0), "uint32_new"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT64_C2I, 0), "uint64_c2i"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT64_NEW, 0), "uint64_new"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_CRL_ADD0_REVOKED, 0),
- "X509_CRL_add0_revoked"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_INFO_NEW, 0), "X509_INFO_new"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_ENCODE, 0), "x509_name_encode"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_EX_D2I, 0), "x509_name_ex_d2i"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_EX_NEW, 0), "x509_name_ex_new"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_PKEY_NEW, 0), "X509_PKEY_new"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA ASN1_str_reasons[] = {
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ADDING_OBJECT), "adding object"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_PARSE_ERROR), "asn1 parse error"},
@@ -249,6 +109,7 @@ static const ERR_STRING_DATA ASN1_str_reasons[] = {
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_UTF8STRING),
"invalid utf8string"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_VALUE), "invalid value"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_LENGTH_TOO_LONG), "length too long"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_LIST_ERROR), "list error"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_NO_CONTENT_TYPE),
"mime no content type"},
@@ -313,6 +174,7 @@ static const ERR_STRING_DATA ASN1_str_reasons[] = {
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNEXPECTED_EOC), "unexpected eoc"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH),
"universalstring is wrong length"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_DIGEST), "unknown digest"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_FORMAT), "unknown format"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM),
"unknown message digest algorithm"},
@@ -340,13 +202,11 @@ static const ERR_STRING_DATA ASN1_str_reasons[] = {
#endif
-int ERR_load_ASN1_strings(void)
+int ossl_err_load_ASN1_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(ASN1_str_functs[0].error) == NULL) {
- ERR_load_strings_const(ASN1_str_functs);
+ if (ERR_reason_error_string(ASN1_str_reasons[0].error) == NULL)
ERR_load_strings_const(ASN1_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/asn1/asn1_gen.c b/crypto/asn1/asn1_gen.c
index 493a693aa384..64620a4f28a7 100644
--- a/crypto/asn1/asn1_gen.c
+++ b/crypto/asn1/asn1_gen.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -91,7 +91,7 @@ ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf)
int err = 0;
ASN1_TYPE *ret = generate_v3(str, cnf, 0, &err);
if (err)
- ASN1err(ASN1_F_ASN1_GENERATE_V3, err);
+ ERR_raise(ERR_LIB_ASN1, err);
return ret;
}
@@ -263,8 +263,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
utype = asn1_str2tag(elem, len);
if (utype == -1) {
- ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_TAG);
- ERR_add_error_data(2, "tag=", elem);
+ ERR_raise_data(ERR_LIB_ASN1, ASN1_R_UNKNOWN_TAG, "tag=%s", elem);
return -1;
}
@@ -274,7 +273,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
arg->str = vstart;
/* If no value and not end of string, error */
if (!vstart && elem[len]) {
- ASN1err(ASN1_F_ASN1_CB, ASN1_R_MISSING_VALUE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_VALUE);
return -1;
}
return 0;
@@ -285,7 +284,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
case ASN1_GEN_FLAG_IMP:
/* Check for illegal multiple IMPLICIT tagging */
if (arg->imp_tag != -1) {
- ASN1err(ASN1_F_ASN1_CB, ASN1_R_ILLEGAL_NESTED_TAGGING);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING);
return -1;
}
if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class))
@@ -322,7 +321,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
case ASN1_GEN_FLAG_FORMAT:
if (!vstart) {
- ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT);
return -1;
}
if (strncmp(vstart, "ASCII", 5) == 0)
@@ -334,7 +333,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
else if (strncmp(vstart, "BITLIST", 7) == 0)
arg->format = ASN1_GEN_FORMAT_BITLIST;
else {
- ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT);
return -1;
}
break;
@@ -347,7 +346,6 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
{
- char erch[2];
long tag_num;
char *eptr;
if (!vstart)
@@ -357,7 +355,7 @@ static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
if (eptr && *eptr && (eptr > vstart + vlen))
return 0;
if (tag_num < 0) {
- ASN1err(ASN1_F_PARSE_TAGGING, ASN1_R_INVALID_NUMBER);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_NUMBER);
return 0;
}
*ptag = tag_num;
@@ -386,10 +384,8 @@ static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
break;
default:
- erch[0] = *eptr;
- erch[1] = 0;
- ASN1err(ASN1_F_PARSE_TAGGING, ASN1_R_INVALID_MODIFIER);
- ERR_add_error_data(2, "Char=", erch);
+ ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_MODIFIER,
+ "Char=%c", *eptr);
return 0;
}
@@ -469,12 +465,12 @@ static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
tag_exp_type *exp_tmp;
/* Can only have IMPLICIT if permitted */
if ((arg->imp_tag != -1) && !imp_ok) {
- ASN1err(ASN1_F_APPEND_EXP, ASN1_R_ILLEGAL_IMPLICIT_TAG);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_IMPLICIT_TAG);
return 0;
}
if (arg->exp_count == ASN1_FLAG_EXP_MAX) {
- ASN1err(ASN1_F_APPEND_EXP, ASN1_R_DEPTH_EXCEEDED);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_DEPTH_EXCEEDED);
return 0;
}
@@ -568,7 +564,8 @@ static int asn1_str2tag(const char *tagstr, int len)
tntmp = tnst;
for (i = 0; i < OSSL_NELEM(tnst); i++, tntmp++) {
- if ((len == tntmp->len) && (strncmp(tntmp->strnam, tagstr, len) == 0))
+ if ((len == tntmp->len)
+ && (OPENSSL_strncasecmp(tntmp->strnam, tagstr, len) == 0))
return tntmp->tag;
}
@@ -584,7 +581,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
int no_unused = 1;
if ((atmp = ASN1_TYPE_new()) == NULL) {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -595,21 +592,21 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
case V_ASN1_NULL:
if (str && *str) {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_NULL_VALUE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NULL_VALUE);
goto bad_form;
}
break;
case V_ASN1_BOOLEAN:
if (format != ASN1_GEN_FORMAT_ASCII) {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_NOT_ASCII_FORMAT);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ASCII_FORMAT);
goto bad_form;
}
vtmp.name = NULL;
vtmp.section = NULL;
vtmp.value = (char *)str;
if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_BOOLEAN);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_BOOLEAN);
goto bad_str;
}
break;
@@ -617,23 +614,23 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED:
if (format != ASN1_GEN_FORMAT_ASCII) {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
goto bad_form;
}
if ((atmp->value.integer
= s2i_ASN1_INTEGER(NULL, str)) == NULL) {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_INTEGER);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_INTEGER);
goto bad_str;
}
break;
case V_ASN1_OBJECT:
if (format != ASN1_GEN_FORMAT_ASCII) {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
goto bad_form;
}
if ((atmp->value.object = OBJ_txt2obj(str, 0)) == NULL) {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_OBJECT);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_OBJECT);
goto bad_str;
}
break;
@@ -641,20 +638,20 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
case V_ASN1_UTCTIME:
case V_ASN1_GENERALIZEDTIME:
if (format != ASN1_GEN_FORMAT_ASCII) {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_TIME_NOT_ASCII_FORMAT);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TIME_NOT_ASCII_FORMAT);
goto bad_form;
}
if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto bad_str;
}
if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto bad_str;
}
atmp->value.asn1_string->type = utype;
if (!ASN1_TIME_check(atmp->value.asn1_string)) {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_TIME_VALUE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_TIME_VALUE);
goto bad_str;
}
@@ -674,13 +671,13 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
else if (format == ASN1_GEN_FORMAT_UTF8)
format = MBSTRING_UTF8;
else {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_FORMAT);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_FORMAT);
goto bad_form;
}
if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str,
-1, format, ASN1_tag2bit(utype)) <= 0) {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto bad_str;
}
@@ -689,13 +686,13 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
case V_ASN1_BIT_STRING:
case V_ASN1_OCTET_STRING:
if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto bad_form;
}
if (format == ASN1_GEN_FORMAT_HEX) {
if ((rdata = OPENSSL_hexstr2buf(str, &rdlen)) == NULL) {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_HEX);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_HEX);
goto bad_str;
}
atmp->value.asn1_string->data = rdata;
@@ -707,13 +704,13 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
&& (utype == V_ASN1_BIT_STRING)) {
if (!CONF_parse_list
(str, ',', 1, bitstr_cb, atmp->value.bit_string)) {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_LIST_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_LIST_ERROR);
goto bad_str;
}
no_unused = 0;
} else {
- ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
goto bad_form;
}
@@ -726,7 +723,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
break;
default:
- ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_UNSUPPORTED_TYPE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_TYPE);
goto bad_str;
}
@@ -752,11 +749,11 @@ static int bitstr_cb(const char *elem, int len, void *bitstr)
if (eptr && *eptr && (eptr != elem + len))
return 0;
if (bitnum < 0) {
- ASN1err(ASN1_F_BITSTR_CB, ASN1_R_INVALID_NUMBER);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_NUMBER);
return 0;
}
if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) {
- ASN1err(ASN1_F_BITSTR_CB, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
diff --git a/crypto/asn1/asn1_item_list.c b/crypto/asn1/asn1_item_list.c
index 9798192f4be2..b5a83ba8914b 100644
--- a/crypto/asn1/asn1_item_list.c
+++ b/crypto/asn1/asn1_item_list.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use the low level ASN1 items until they are removed */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
diff --git a/crypto/asn1/asn1_item_list.h b/crypto/asn1/asn1_item_list.h
index db8107ed1b19..1432012b7c7c 100644
--- a/crypto/asn1/asn1_item_list.h
+++ b/crypto/asn1/asn1_item_list.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -63,8 +63,10 @@ static ASN1_ITEM_EXP *asn1_item_list[] = {
ASN1_ITEM_ref(DIST_POINT_NAME),
ASN1_ITEM_ref(DIST_POINT),
#ifndef OPENSSL_NO_EC
+# ifndef OPENSSL_NO_DEPRECATED_3_0
ASN1_ITEM_ref(ECPARAMETERS),
ASN1_ITEM_ref(ECPKPARAMETERS),
+# endif
#endif
ASN1_ITEM_ref(EDIPARTYNAME),
ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
@@ -78,7 +80,7 @@ static ASN1_ITEM_EXP *asn1_item_list[] = {
ASN1_ITEM_ref(IPAddressRange),
#endif
ASN1_ITEM_ref(ISSUING_DIST_POINT),
-#if OPENSSL_API_COMPAT < 0x10200000L
+#ifndef OPENSSL_NO_DEPRECATED_3_0
ASN1_ITEM_ref(LONG),
#endif
ASN1_ITEM_ref(NAME_CONSTRAINTS),
@@ -134,7 +136,7 @@ static ASN1_ITEM_EXP *asn1_item_list[] = {
ASN1_ITEM_ref(POLICY_MAPPING),
ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION),
ASN1_ITEM_ref(PROXY_POLICY),
-#ifndef OPENSSL_NO_RSA
+#ifndef OPENSSL_NO_DEPRECATED_3_0
ASN1_ITEM_ref(RSAPrivateKey),
ASN1_ITEM_ref(RSAPublicKey),
ASN1_ITEM_ref(RSA_OAEP_PARAMS),
@@ -145,6 +147,7 @@ static ASN1_ITEM_EXP *asn1_item_list[] = {
#endif
ASN1_ITEM_ref(SXNETID),
ASN1_ITEM_ref(SXNET),
+ ASN1_ITEM_ref(ISSUER_SIGN_TOOL),
ASN1_ITEM_ref(USERNOTICE),
ASN1_ITEM_ref(X509_ALGORS),
ASN1_ITEM_ref(X509_ALGOR),
@@ -164,7 +167,7 @@ static ASN1_ITEM_EXP *asn1_item_list[] = {
ASN1_ITEM_ref(X509_SIG),
ASN1_ITEM_ref(X509_VAL),
ASN1_ITEM_ref(X509),
-#if OPENSSL_API_COMPAT < 0x10200000L
+#ifndef OPENSSL_NO_DEPRECATED_3_0
ASN1_ITEM_ref(ZLONG),
#endif
ASN1_ITEM_ref(INT32),
diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c
index b9b7ad8e9e02..5359cbc11720 100644
--- a/crypto/asn1/asn1_lib.c
+++ b/crypto/asn1/asn1_lib.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -22,11 +22,13 @@ static int _asn1_check_infinite_end(const unsigned char **p, long len)
/*
* If there is 0 or 1 byte left, the length check should pick things up
*/
- if (len <= 0)
- return 1;
- else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) {
- (*p) += 2;
+ if (len <= 0) {
return 1;
+ } else {
+ if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) {
+ (*p) += 2;
+ return 1;
+ }
}
return 0;
}
@@ -45,13 +47,15 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
int *pclass, long omax)
{
int i, ret;
- long l;
+ long len;
const unsigned char *p = *pp;
int tag, xclass, inf;
long max = omax;
- if (!max)
- goto err;
+ if (omax <= 0) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL);
+ return 0x80;
+ }
ret = (*p & V_ASN1_CONSTRUCTED);
xclass = (*p & V_ASN1_PRIVATE);
i = *p & V_ASN1_PRIMITIVE_TAG;
@@ -59,18 +63,18 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
p++;
if (--max == 0)
goto err;
- l = 0;
+ len = 0;
while (*p & 0x80) {
- l <<= 7L;
- l |= *(p++) & 0x7f;
+ len <<= 7L;
+ len |= *(p++) & 0x7f;
if (--max == 0)
goto err;
- if (l > (INT_MAX >> 7L))
+ if (len > (INT_MAX >> 7L))
goto err;
}
- l <<= 7L;
- l |= *(p++) & 0x7f;
- tag = (int)l;
+ len <<= 7L;
+ len |= *(p++) & 0x7f;
+ tag = (int)len;
if (--max == 0)
goto err;
} else {
@@ -88,7 +92,7 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
goto err;
if (*plength > (omax - (p - *pp))) {
- ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_TOO_LONG);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG);
/*
* Set this so that even if things are not long enough the values are
* set correctly
@@ -98,7 +102,7 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
*pp = p;
return ret | inf;
err:
- ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_HEADER_TOO_LONG);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_HEADER_TOO_LONG);
return 0x80;
}
@@ -141,8 +145,9 @@ static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
}
if (ret > LONG_MAX)
return 0;
- } else
+ } else {
ret = i;
+ }
}
*pp = p;
*rl = (long)ret;
@@ -150,7 +155,7 @@ static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
}
/*
- * class 0 is constructed constructed == 2 for indefinite length constructed
+ * constructed == 2 for indefinite length constructed
*/
void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
int xclass)
@@ -160,9 +165,9 @@ void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
i |= (xclass & V_ASN1_PRIVATE);
- if (tag < 31)
+ if (tag < 31) {
*(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
- else {
+ } else {
*(p++) = i | V_ASN1_PRIMITIVE_TAG;
for (i = 0, ttag = tag; ttag > 0; i++)
ttag >>= 7;
@@ -185,6 +190,7 @@ void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
int ASN1_put_eoc(unsigned char **pp)
{
unsigned char *p = *pp;
+
*p++ = 0;
*p++ = 0;
*pp = p;
@@ -194,20 +200,21 @@ int ASN1_put_eoc(unsigned char **pp)
static void asn1_put_length(unsigned char **pp, int length)
{
unsigned char *p = *pp;
- int i, l;
- if (length <= 127)
+ int i, len;
+
+ if (length <= 127) {
*(p++) = (unsigned char)length;
- else {
- l = length;
- for (i = 0; l > 0; i++)
- l >>= 8;
+ } else {
+ len = length;
+ for (i = 0; len > 0; i++)
+ len >>= 8;
*(p++) = i | 0x80;
- l = i;
+ len = i;
while (i-- > 0) {
p[i] = length & 0xff;
length >>= 8;
}
- p += l;
+ p += len;
}
*pp = p;
}
@@ -215,6 +222,7 @@ static void asn1_put_length(unsigned char **pp, int length)
int ASN1_object_size(int constructed, int length, int tag)
{
int ret = 1;
+
if (length < 0)
return -1;
if (tag >= 31) {
@@ -256,6 +264,7 @@ int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
{
ASN1_STRING *ret;
+
if (!str)
return NULL;
ret = ASN1_STRING_new();
@@ -287,7 +296,7 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len_in)
* '\0' terminator even though this isn't strictly necessary.
*/
if (len > INT_MAX - 1) {
- ASN1err(0, ASN1_R_TOO_LARGE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
return 0;
}
if ((size_t)str->length <= len || str->data == NULL) {
@@ -299,7 +308,7 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len_in)
str->data = OPENSSL_realloc(c, len + 1);
#endif
if (str->data == NULL) {
- ASN1err(ASN1_F_ASN1_STRING_SET, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
str->data = c;
return 0;
}
@@ -340,14 +349,14 @@ ASN1_STRING *ASN1_STRING_type_new(int type)
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- ASN1err(ASN1_F_ASN1_STRING_TYPE_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->type = type;
return ret;
}
-void asn1_string_embed_free(ASN1_STRING *a, int embed)
+void ossl_asn1_string_embed_free(ASN1_STRING *a, int embed)
{
if (a == NULL)
return;
@@ -361,7 +370,7 @@ void ASN1_STRING_free(ASN1_STRING *a)
{
if (a == NULL)
return;
- asn1_string_embed_free(a, a->flags & ASN1_STRING_FLAG_EMBED);
+ ossl_asn1_string_embed_free(a, a->flags & ASN1_STRING_FLAG_EMBED);
}
void ASN1_STRING_clear_free(ASN1_STRING *a)
@@ -385,8 +394,9 @@ int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
return a->type - b->type;
else
return i;
- } else
+ } else {
return i;
+ }
}
int ASN1_STRING_length(const ASN1_STRING *x)
@@ -394,10 +404,12 @@ int ASN1_STRING_length(const ASN1_STRING *x)
return x->length;
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
void ASN1_STRING_length_set(ASN1_STRING *x, int len)
{
x->length = len;
}
+#endif
int ASN1_STRING_type(const ASN1_STRING *x)
{
@@ -409,9 +421,50 @@ const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
return x->data;
}
-# if OPENSSL_API_COMPAT < 0x10100000L
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
unsigned char *ASN1_STRING_data(ASN1_STRING *x)
{
return x->data;
}
#endif
+
+/* |max_len| excludes NUL terminator and may be 0 to indicate no restriction */
+char *ossl_sk_ASN1_UTF8STRING2text(STACK_OF(ASN1_UTF8STRING) *text,
+ const char *sep, size_t max_len)
+{
+ int i;
+ ASN1_UTF8STRING *current;
+ size_t length = 0, sep_len;
+ char *result = NULL;
+ char *p;
+
+ if (sep == NULL)
+ sep = "";
+ sep_len = strlen(sep);
+
+ for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) {
+ current = sk_ASN1_UTF8STRING_value(text, i);
+ if (i > 0)
+ length += sep_len;
+ length += ASN1_STRING_length(current);
+ if (max_len != 0 && length > max_len)
+ return NULL;
+ }
+ if ((result = OPENSSL_malloc(length + 1)) == NULL)
+ return NULL;
+
+ p = result;
+ for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) {
+ current = sk_ASN1_UTF8STRING_value(text, i);
+ length = ASN1_STRING_length(current);
+ if (i > 0 && sep_len > 0) {
+ strncpy(p, sep, sep_len + 1); /* using + 1 to silence gcc warning */
+ p += sep_len;
+ }
+ strncpy(p, (const char *)ASN1_STRING_get0_data(current), length);
+ p += length;
+ }
+ *p = '\0';
+
+ return result;
+}
diff --git a/crypto/asn1/asn1_local.h b/crypto/asn1/asn1_local.h
index cec141721b34..f73bd8fc6a30 100644
--- a/crypto/asn1/asn1_local.h
+++ b/crypto/asn1/asn1_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2005-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,9 +9,11 @@
/* Internal ASN1 structures and functions: not for application use */
-int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d);
-int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
-int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
+typedef const ASN1_VALUE const_ASN1_VALUE;
+SKM_DEFINE_STACK_OF(const_ASN1_VALUE, const ASN1_VALUE, ASN1_VALUE)
+
+int ossl_asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d);
+int ossl_asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
/* ASN1 scan context structure */
@@ -43,41 +45,50 @@ DEFINE_STACK_OF(MIME_PARAM)
typedef struct mime_header_st MIME_HEADER;
DEFINE_STACK_OF(MIME_HEADER)
-void asn1_string_embed_free(ASN1_STRING *a, int embed);
+void ossl_asn1_string_embed_free(ASN1_STRING *a, int embed);
-int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it);
-int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
- const ASN1_ITEM *it);
+int ossl_asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int ossl_asn1_get_choice_selector_const(const ASN1_VALUE **pval,
+ const ASN1_ITEM *it);
+int ossl_asn1_set_choice_selector(ASN1_VALUE **pval, int value,
+ const ASN1_ITEM *it);
-ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+ASN1_VALUE **ossl_asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+const ASN1_VALUE **ossl_asn1_get_const_field_ptr(const ASN1_VALUE **pval,
+ const ASN1_TEMPLATE *tt);
-const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
- int nullerr);
+const ASN1_TEMPLATE *ossl_asn1_do_adb(const ASN1_VALUE *val,
+ const ASN1_TEMPLATE *tt,
+ int nullerr);
-int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it);
+int ossl_asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it);
-void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it);
-void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
-int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
- const ASN1_ITEM *it);
-int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
- const ASN1_ITEM *it);
+void ossl_asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it);
+void ossl_asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int ossl_asn1_enc_restore(int *len, unsigned char **out, const ASN1_VALUE **pval,
+ const ASN1_ITEM *it);
+int ossl_asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
+ const ASN1_ITEM *it);
-void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed);
-void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed);
-void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+void ossl_asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed);
+void ossl_asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed);
+void ossl_asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
-ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
- long length);
-int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp);
-ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
- const unsigned char **pp, long length);
-int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp);
-ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
- long length);
+ASN1_OBJECT *ossl_c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
+ long length);
+int ossl_i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp);
+ASN1_BIT_STRING *ossl_c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
+ const unsigned char **pp, long length);
+int ossl_i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp);
+ASN1_INTEGER *ossl_c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
+ long length);
/* Internal functions used by x_int64.c */
-int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len);
-int i2c_uint64_int(unsigned char *p, uint64_t r, int neg);
+int ossl_c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp,
+ long len);
+int ossl_i2c_uint64_int(unsigned char *p, uint64_t r, int neg);
+
+ASN1_TIME *ossl_asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type);
-ASN1_TIME *asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type);
+int ossl_asn1_item_ex_new_intern(ASN1_VALUE **pval, const ASN1_ITEM *it,
+ OSSL_LIB_CTX *libctx, const char *propq);
diff --git a/crypto/asn1/asn1_par.c b/crypto/asn1/asn1_par.c
deleted file mode 100644
index a32fa47f2206..000000000000
--- a/crypto/asn1/asn1_par.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/buffer.h>
-#include <openssl/objects.h>
-#include <openssl/asn1.h>
-
-#ifndef ASN1_PARSE_MAXDEPTH
-#define ASN1_PARSE_MAXDEPTH 128
-#endif
-
-static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
- int indent);
-static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
- int offset, int depth, int indent, int dump);
-static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
- int indent)
-{
- static const char fmt[] = "%-18s";
- char str[128];
- const char *p;
-
- if (constructed & V_ASN1_CONSTRUCTED)
- p = "cons: ";
- else
- p = "prim: ";
- if (BIO_write(bp, p, 6) < 6)
- goto err;
- BIO_indent(bp, indent, 128);
-
- p = str;
- if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
- BIO_snprintf(str, sizeof(str), "priv [ %d ] ", tag);
- else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
- BIO_snprintf(str, sizeof(str), "cont [ %d ]", tag);
- else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
- BIO_snprintf(str, sizeof(str), "appl [ %d ]", tag);
- else if (tag > 30)
- BIO_snprintf(str, sizeof(str), "<ASN1 %d>", tag);
- else
- p = ASN1_tag2str(tag);
-
- if (BIO_printf(bp, fmt, p) <= 0)
- goto err;
- return 1;
- err:
- return 0;
-}
-
-int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
-{
- return asn1_parse2(bp, &pp, len, 0, 0, indent, 0);
-}
-
-int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent,
- int dump)
-{
- return asn1_parse2(bp, &pp, len, 0, 0, indent, dump);
-}
-
-static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
- int offset, int depth, int indent, int dump)
-{
- const unsigned char *p, *ep, *tot, *op, *opp;
- long len;
- int tag, xclass, ret = 0;
- int nl, hl, j, r;
- ASN1_OBJECT *o = NULL;
- ASN1_OCTET_STRING *os = NULL;
- ASN1_INTEGER *ai = NULL;
- ASN1_ENUMERATED *ae = NULL;
- /* ASN1_BMPSTRING *bmp=NULL; */
- int dump_indent, dump_cont = 0;
-
- if (depth > ASN1_PARSE_MAXDEPTH) {
- BIO_puts(bp, "BAD RECURSION DEPTH\n");
- return 0;
- }
-
- dump_indent = 6; /* Because we know BIO_dump_indent() */
- p = *pp;
- tot = p + length;
- while (length > 0) {
- op = p;
- j = ASN1_get_object(&p, &len, &tag, &xclass, length);
- if (j & 0x80) {
- if (BIO_write(bp, "Error in encoding\n", 18) <= 0)
- goto end;
- ret = 0;
- goto end;
- }
- hl = (p - op);
- length -= hl;
- /*
- * if j == 0x21 it is a constructed indefinite length object
- */
- if (BIO_printf(bp, "%5ld:", (long)offset + (long)(op - *pp))
- <= 0)
- goto end;
-
- if (j != (V_ASN1_CONSTRUCTED | 1)) {
- if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ",
- depth, (long)hl, len) <= 0)
- goto end;
- } else {
- if (BIO_printf(bp, "d=%-2d hl=%ld l=inf ", depth, (long)hl) <= 0)
- goto end;
- }
- if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0))
- goto end;
- if (j & V_ASN1_CONSTRUCTED) {
- const unsigned char *sp = p;
-
- ep = p + len;
- if (BIO_write(bp, "\n", 1) <= 0)
- goto end;
- if (len > length) {
- BIO_printf(bp, "length is greater than %ld\n", length);
- ret = 0;
- goto end;
- }
- if ((j == 0x21) && (len == 0)) {
- for (;;) {
- r = asn1_parse2(bp, &p, (long)(tot - p),
- offset + (p - *pp), depth + 1,
- indent, dump);
- if (r == 0) {
- ret = 0;
- goto end;
- }
- if ((r == 2) || (p >= tot)) {
- len = p - sp;
- break;
- }
- }
- } else {
- long tmp = len;
-
- while (p < ep) {
- sp = p;
- r = asn1_parse2(bp, &p, tmp,
- offset + (p - *pp), depth + 1,
- indent, dump);
- if (r == 0) {
- ret = 0;
- goto end;
- }
- tmp -= p - sp;
- }
- }
- } else if (xclass != 0) {
- p += len;
- if (BIO_write(bp, "\n", 1) <= 0)
- goto end;
- } else {
- nl = 0;
- if ((tag == V_ASN1_PRINTABLESTRING) ||
- (tag == V_ASN1_T61STRING) ||
- (tag == V_ASN1_IA5STRING) ||
- (tag == V_ASN1_VISIBLESTRING) ||
- (tag == V_ASN1_NUMERICSTRING) ||
- (tag == V_ASN1_UTF8STRING) ||
- (tag == V_ASN1_UTCTIME) || (tag == V_ASN1_GENERALIZEDTIME)) {
- if (BIO_write(bp, ":", 1) <= 0)
- goto end;
- if ((len > 0) && BIO_write(bp, (const char *)p, (int)len)
- != (int)len)
- goto end;
- } else if (tag == V_ASN1_OBJECT) {
- opp = op;
- if (d2i_ASN1_OBJECT(&o, &opp, len + hl) != NULL) {
- if (BIO_write(bp, ":", 1) <= 0)
- goto end;
- i2a_ASN1_OBJECT(bp, o);
- } else {
- if (BIO_puts(bp, ":BAD OBJECT") <= 0)
- goto end;
- dump_cont = 1;
- }
- } else if (tag == V_ASN1_BOOLEAN) {
- if (len != 1) {
- if (BIO_puts(bp, ":BAD BOOLEAN") <= 0)
- goto end;
- dump_cont = 1;
- }
- if (len > 0)
- BIO_printf(bp, ":%u", p[0]);
- } else if (tag == V_ASN1_BMPSTRING) {
- /* do the BMP thang */
- } else if (tag == V_ASN1_OCTET_STRING) {
- int i, printable = 1;
-
- opp = op;
- os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl);
- if (os != NULL && os->length > 0) {
- opp = os->data;
- /*
- * testing whether the octet string is printable
- */
- for (i = 0; i < os->length; i++) {
- if (((opp[i] < ' ') &&
- (opp[i] != '\n') &&
- (opp[i] != '\r') &&
- (opp[i] != '\t')) || (opp[i] > '~')) {
- printable = 0;
- break;
- }
- }
- if (printable)
- /* printable string */
- {
- if (BIO_write(bp, ":", 1) <= 0)
- goto end;
- if (BIO_write(bp, (const char *)opp, os->length) <= 0)
- goto end;
- } else if (!dump)
- /*
- * not printable => print octet string as hex dump
- */
- {
- if (BIO_write(bp, "[HEX DUMP]:", 11) <= 0)
- goto end;
- for (i = 0; i < os->length; i++) {
- if (BIO_printf(bp, "%02X", opp[i]) <= 0)
- goto end;
- }
- } else
- /* print the normal dump */
- {
- if (!nl) {
- if (BIO_write(bp, "\n", 1) <= 0)
- goto end;
- }
- if (BIO_dump_indent(bp,
- (const char *)opp,
- ((dump == -1 || dump >
- os->
- length) ? os->length : dump),
- dump_indent) <= 0)
- goto end;
- nl = 1;
- }
- }
- ASN1_OCTET_STRING_free(os);
- os = NULL;
- } else if (tag == V_ASN1_INTEGER) {
- int i;
-
- opp = op;
- ai = d2i_ASN1_INTEGER(NULL, &opp, len + hl);
- if (ai != NULL) {
- if (BIO_write(bp, ":", 1) <= 0)
- goto end;
- if (ai->type == V_ASN1_NEG_INTEGER)
- if (BIO_write(bp, "-", 1) <= 0)
- goto end;
- for (i = 0; i < ai->length; i++) {
- if (BIO_printf(bp, "%02X", ai->data[i]) <= 0)
- goto end;
- }
- if (ai->length == 0) {
- if (BIO_write(bp, "00", 2) <= 0)
- goto end;
- }
- } else {
- if (BIO_puts(bp, ":BAD INTEGER") <= 0)
- goto end;
- dump_cont = 1;
- }
- ASN1_INTEGER_free(ai);
- ai = NULL;
- } else if (tag == V_ASN1_ENUMERATED) {
- int i;
-
- opp = op;
- ae = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl);
- if (ae != NULL) {
- if (BIO_write(bp, ":", 1) <= 0)
- goto end;
- if (ae->type == V_ASN1_NEG_ENUMERATED)
- if (BIO_write(bp, "-", 1) <= 0)
- goto end;
- for (i = 0; i < ae->length; i++) {
- if (BIO_printf(bp, "%02X", ae->data[i]) <= 0)
- goto end;
- }
- if (ae->length == 0) {
- if (BIO_write(bp, "00", 2) <= 0)
- goto end;
- }
- } else {
- if (BIO_puts(bp, ":BAD ENUMERATED") <= 0)
- goto end;
- dump_cont = 1;
- }
- ASN1_ENUMERATED_free(ae);
- ae = NULL;
- } else if (len > 0 && dump) {
- if (!nl) {
- if (BIO_write(bp, "\n", 1) <= 0)
- goto end;
- }
- if (BIO_dump_indent(bp, (const char *)p,
- ((dump == -1 || dump > len) ? len : dump),
- dump_indent) <= 0)
- goto end;
- nl = 1;
- }
- if (dump_cont) {
- int i;
- const unsigned char *tmp = op + hl;
- if (BIO_puts(bp, ":[") <= 0)
- goto end;
- for (i = 0; i < len; i++) {
- if (BIO_printf(bp, "%02X", tmp[i]) <= 0)
- goto end;
- }
- if (BIO_puts(bp, "]") <= 0)
- goto end;
- dump_cont = 0;
- }
-
- if (!nl) {
- if (BIO_write(bp, "\n", 1) <= 0)
- goto end;
- }
- p += len;
- if ((tag == V_ASN1_EOC) && (xclass == 0)) {
- ret = 2; /* End of sequence */
- goto end;
- }
- }
- length -= len;
- }
- ret = 1;
- end:
- ASN1_OBJECT_free(o);
- ASN1_OCTET_STRING_free(os);
- ASN1_INTEGER_free(ai);
- ASN1_ENUMERATED_free(ae);
- *pp = p;
- return ret;
-}
-
-const char *ASN1_tag2str(int tag)
-{
- static const char *const tag2str[] = {
- /* 0-4 */
- "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING",
- /* 5-9 */
- "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL",
- /* 10-13 */
- "ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>",
- /* 15-17 */
- "<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET",
- /* 18-20 */
- "NUMERICSTRING", "PRINTABLESTRING", "T61STRING",
- /* 21-24 */
- "VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME",
- /* 25-27 */
- "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING",
- /* 28-30 */
- "UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING"
- };
-
- if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
- tag &= ~0x100;
-
- if (tag < 0 || tag > 30)
- return "(unknown)";
- return tag2str[tag];
-}
diff --git a/crypto/asn1/asn1_parse.c b/crypto/asn1/asn1_parse.c
new file mode 100644
index 000000000000..04d7ef66cfc9
--- /dev/null
+++ b/crypto/asn1/asn1_parse.c
@@ -0,0 +1,387 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/buffer.h>
+#include <openssl/objects.h>
+#include <openssl/asn1.h>
+
+#ifndef ASN1_PARSE_MAXDEPTH
+#define ASN1_PARSE_MAXDEPTH 128
+#endif
+
+static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
+ int offset, int depth, int indent, int dump);
+static int asn1_print_info(BIO *bp, long offset, int depth, int hl, long len,
+ int tag, int xclass, int constructed, int indent)
+{
+ char str[128];
+ const char *p;
+ int pop_f_prefix = 0;
+ long saved_indent = -1;
+ int i = 0;
+ BIO *bio = NULL;
+
+ if (constructed & V_ASN1_CONSTRUCTED)
+ p = "cons: ";
+ else
+ p = "prim: ";
+ if (constructed != (V_ASN1_CONSTRUCTED | 1)) {
+ if (BIO_snprintf(str, sizeof(str), "%5ld:d=%-2d hl=%ld l=%4ld %s",
+ offset, depth, (long)hl, len, p) <= 0)
+ goto err;
+ } else {
+ if (BIO_snprintf(str, sizeof(str), "%5ld:d=%-2d hl=%ld l=inf %s",
+ offset, depth, (long)hl, p) <= 0)
+ goto err;
+ }
+ if (bp != NULL) {
+ if (BIO_set_prefix(bp, str) <= 0) {
+ if ((bio = BIO_new(BIO_f_prefix())) == NULL
+ || (bp = BIO_push(bio, bp)) == NULL)
+ goto err;
+ pop_f_prefix = 1;
+ }
+ saved_indent = BIO_get_indent(bp);
+ if (BIO_set_prefix(bp, str) <= 0 || BIO_set_indent(bp, indent) < 0)
+ goto err;
+ }
+
+ /*
+ * BIO_set_prefix made a copy of |str|, so we can safely use it for
+ * something else, ASN.1 tag printout.
+ */
+ p = str;
+ if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
+ BIO_snprintf(str, sizeof(str), "priv [ %d ] ", tag);
+ else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
+ BIO_snprintf(str, sizeof(str), "cont [ %d ]", tag);
+ else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
+ BIO_snprintf(str, sizeof(str), "appl [ %d ]", tag);
+ else if (tag > 30)
+ BIO_snprintf(str, sizeof(str), "<ASN1 %d>", tag);
+ else
+ p = ASN1_tag2str(tag);
+
+ i = (BIO_printf(bp, "%-18s", p) > 0);
+ err:
+ if (saved_indent >= 0)
+ BIO_set_indent(bp, saved_indent);
+ if (pop_f_prefix)
+ BIO_pop(bp);
+ BIO_free(bio);
+ return i;
+}
+
+int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
+{
+ return asn1_parse2(bp, &pp, len, 0, 0, indent, 0);
+}
+
+int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent,
+ int dump)
+{
+ return asn1_parse2(bp, &pp, len, 0, 0, indent, dump);
+}
+
+static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
+ int offset, int depth, int indent, int dump)
+{
+ const unsigned char *p, *ep, *tot, *op, *opp;
+ long len;
+ int tag, xclass, ret = 0;
+ int nl, hl, j, r;
+ ASN1_OBJECT *o = NULL;
+ ASN1_OCTET_STRING *os = NULL;
+ ASN1_INTEGER *ai = NULL;
+ ASN1_ENUMERATED *ae = NULL;
+ /* ASN1_BMPSTRING *bmp=NULL; */
+ int dump_indent, dump_cont = 0;
+
+ if (depth > ASN1_PARSE_MAXDEPTH) {
+ BIO_puts(bp, "BAD RECURSION DEPTH\n");
+ return 0;
+ }
+
+ dump_indent = 6; /* Because we know BIO_dump_indent() */
+ p = *pp;
+ tot = p + length;
+ while (length > 0) {
+ op = p;
+ j = ASN1_get_object(&p, &len, &tag, &xclass, length);
+ if (j & 0x80) {
+ BIO_puts(bp, "Error in encoding\n");
+ goto end;
+ }
+ hl = (p - op);
+ length -= hl;
+ /*
+ * if j == 0x21 it is a constructed indefinite length object
+ */
+ if (!asn1_print_info(bp, (long)offset + (long)(op - *pp), depth,
+ hl, len, tag, xclass, j, (indent) ? depth : 0))
+ goto end;
+ if (j & V_ASN1_CONSTRUCTED) {
+ const unsigned char *sp = p;
+
+ ep = p + len;
+ if (BIO_write(bp, "\n", 1) <= 0)
+ goto end;
+ if (len > length) {
+ BIO_printf(bp, "length is greater than %ld\n", length);
+ goto end;
+ }
+ if ((j == 0x21) && (len == 0)) {
+ for (;;) {
+ r = asn1_parse2(bp, &p, (long)(tot - p),
+ offset + (p - *pp), depth + 1,
+ indent, dump);
+ if (r == 0)
+ goto end;
+ if ((r == 2) || (p >= tot)) {
+ len = p - sp;
+ break;
+ }
+ }
+ } else {
+ long tmp = len;
+
+ while (p < ep) {
+ sp = p;
+ r = asn1_parse2(bp, &p, tmp,
+ offset + (p - *pp), depth + 1,
+ indent, dump);
+ if (r == 0)
+ goto end;
+ tmp -= p - sp;
+ }
+ }
+ } else if (xclass != 0) {
+ p += len;
+ if (BIO_write(bp, "\n", 1) <= 0)
+ goto end;
+ } else {
+ nl = 0;
+ if ((tag == V_ASN1_PRINTABLESTRING) ||
+ (tag == V_ASN1_T61STRING) ||
+ (tag == V_ASN1_IA5STRING) ||
+ (tag == V_ASN1_VISIBLESTRING) ||
+ (tag == V_ASN1_NUMERICSTRING) ||
+ (tag == V_ASN1_UTF8STRING) ||
+ (tag == V_ASN1_UTCTIME) || (tag == V_ASN1_GENERALIZEDTIME)) {
+ if (BIO_write(bp, ":", 1) <= 0)
+ goto end;
+ if ((len > 0) && BIO_write(bp, (const char *)p, (int)len)
+ != (int)len)
+ goto end;
+ } else if (tag == V_ASN1_OBJECT) {
+ opp = op;
+ if (d2i_ASN1_OBJECT(&o, &opp, len + hl) != NULL) {
+ if (BIO_write(bp, ":", 1) <= 0)
+ goto end;
+ i2a_ASN1_OBJECT(bp, o);
+ } else {
+ if (BIO_puts(bp, ":BAD OBJECT") <= 0)
+ goto end;
+ dump_cont = 1;
+ }
+ } else if (tag == V_ASN1_BOOLEAN) {
+ if (len != 1) {
+ if (BIO_puts(bp, ":BAD BOOLEAN") <= 0)
+ goto end;
+ dump_cont = 1;
+ }
+ if (len > 0)
+ BIO_printf(bp, ":%u", p[0]);
+ } else if (tag == V_ASN1_BMPSTRING) {
+ /* do the BMP thang */
+ } else if (tag == V_ASN1_OCTET_STRING) {
+ int i, printable = 1;
+
+ opp = op;
+ os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl);
+ if (os != NULL && os->length > 0) {
+ opp = os->data;
+ /*
+ * testing whether the octet string is printable
+ */
+ for (i = 0; i < os->length; i++) {
+ if (((opp[i] < ' ') &&
+ (opp[i] != '\n') &&
+ (opp[i] != '\r') &&
+ (opp[i] != '\t')) || (opp[i] > '~')) {
+ printable = 0;
+ break;
+ }
+ }
+ if (printable)
+ /* printable string */
+ {
+ if (BIO_write(bp, ":", 1) <= 0)
+ goto end;
+ if (BIO_write(bp, (const char *)opp, os->length) <= 0)
+ goto end;
+ } else if (!dump)
+ /*
+ * not printable => print octet string as hex dump
+ */
+ {
+ if (BIO_write(bp, "[HEX DUMP]:", 11) <= 0)
+ goto end;
+ for (i = 0; i < os->length; i++) {
+ if (BIO_printf(bp, "%02X", opp[i]) <= 0)
+ goto end;
+ }
+ } else
+ /* print the normal dump */
+ {
+ if (!nl) {
+ if (BIO_write(bp, "\n", 1) <= 0)
+ goto end;
+ }
+ if (BIO_dump_indent(bp,
+ (const char *)opp,
+ ((dump == -1 || dump >
+ os->
+ length) ? os->length : dump),
+ dump_indent) <= 0)
+ goto end;
+ nl = 1;
+ }
+ }
+ ASN1_OCTET_STRING_free(os);
+ os = NULL;
+ } else if (tag == V_ASN1_INTEGER) {
+ int i;
+
+ opp = op;
+ ai = d2i_ASN1_INTEGER(NULL, &opp, len + hl);
+ if (ai != NULL) {
+ if (BIO_write(bp, ":", 1) <= 0)
+ goto end;
+ if (ai->type == V_ASN1_NEG_INTEGER)
+ if (BIO_write(bp, "-", 1) <= 0)
+ goto end;
+ for (i = 0; i < ai->length; i++) {
+ if (BIO_printf(bp, "%02X", ai->data[i]) <= 0)
+ goto end;
+ }
+ if (ai->length == 0) {
+ if (BIO_write(bp, "00", 2) <= 0)
+ goto end;
+ }
+ } else {
+ if (BIO_puts(bp, ":BAD INTEGER") <= 0)
+ goto end;
+ dump_cont = 1;
+ }
+ ASN1_INTEGER_free(ai);
+ ai = NULL;
+ } else if (tag == V_ASN1_ENUMERATED) {
+ int i;
+
+ opp = op;
+ ae = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl);
+ if (ae != NULL) {
+ if (BIO_write(bp, ":", 1) <= 0)
+ goto end;
+ if (ae->type == V_ASN1_NEG_ENUMERATED)
+ if (BIO_write(bp, "-", 1) <= 0)
+ goto end;
+ for (i = 0; i < ae->length; i++) {
+ if (BIO_printf(bp, "%02X", ae->data[i]) <= 0)
+ goto end;
+ }
+ if (ae->length == 0) {
+ if (BIO_write(bp, "00", 2) <= 0)
+ goto end;
+ }
+ } else {
+ if (BIO_puts(bp, ":BAD ENUMERATED") <= 0)
+ goto end;
+ dump_cont = 1;
+ }
+ ASN1_ENUMERATED_free(ae);
+ ae = NULL;
+ } else if (len > 0 && dump) {
+ if (!nl) {
+ if (BIO_write(bp, "\n", 1) <= 0)
+ goto end;
+ }
+ if (BIO_dump_indent(bp, (const char *)p,
+ ((dump == -1 || dump > len) ? len : dump),
+ dump_indent) <= 0)
+ goto end;
+ nl = 1;
+ }
+ if (dump_cont) {
+ int i;
+ const unsigned char *tmp = op + hl;
+ if (BIO_puts(bp, ":[") <= 0)
+ goto end;
+ for (i = 0; i < len; i++) {
+ if (BIO_printf(bp, "%02X", tmp[i]) <= 0)
+ goto end;
+ }
+ if (BIO_puts(bp, "]") <= 0)
+ goto end;
+ dump_cont = 0;
+ }
+
+ if (!nl) {
+ if (BIO_write(bp, "\n", 1) <= 0)
+ goto end;
+ }
+ p += len;
+ if ((tag == V_ASN1_EOC) && (xclass == 0)) {
+ ret = 2; /* End of sequence */
+ goto end;
+ }
+ }
+ length -= len;
+ }
+ ret = 1;
+ end:
+ ASN1_OBJECT_free(o);
+ ASN1_OCTET_STRING_free(os);
+ ASN1_INTEGER_free(ai);
+ ASN1_ENUMERATED_free(ae);
+ *pp = p;
+ return ret;
+}
+
+const char *ASN1_tag2str(int tag)
+{
+ static const char *const tag2str[] = {
+ /* 0-4 */
+ "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING",
+ /* 5-9 */
+ "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL",
+ /* 10-13 */
+ "ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>",
+ /* 15-17 */
+ "<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET",
+ /* 18-20 */
+ "NUMERICSTRING", "PRINTABLESTRING", "T61STRING",
+ /* 21-24 */
+ "VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME",
+ /* 25-27 */
+ "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING",
+ /* 28-30 */
+ "UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING"
+ };
+
+ if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
+ tag &= ~0x100;
+
+ if (tag < 0 || tag > 30)
+ return "(unknown)";
+ return tag2str[tag];
+}
diff --git a/crypto/asn1/asn_mime.c b/crypto/asn1/asn_mime.c
index 36853612b69c..b44b0f36858b 100644
--- a/crypto/asn1/asn_mime.c
+++ b/crypto/asn1/asn_mime.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -14,6 +14,7 @@
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
+#include <openssl/cms.h>
#include "crypto/evp.h"
#include "internal/bio.h"
#include "asn1_local.h"
@@ -53,7 +54,7 @@ static int mime_param_cmp(const MIME_PARAM *const *a,
const MIME_PARAM *const *b);
static void mime_param_free(MIME_PARAM *param);
static int mime_bound_check(char *line, int linelen, const char *bound, int blen);
-static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret);
+static int multi_split(BIO *bio, int flags, const char *bound, STACK_OF(BIO) **ret);
static int strip_eol(char *linebuf, int *plen, int flags);
static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, const char *name);
static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name);
@@ -64,18 +65,24 @@ static void mime_hdr_free(MIME_HEADER *hdr);
/* Output an ASN1 structure in BER format streaming if necessary */
+/* unfortunately cannot constify this due to CMS_stream() and PKCS7_stream() */
int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
const ASN1_ITEM *it)
{
+ int rv = 1;
+
/* If streaming create stream BIO and copy all content through it */
if (flags & SMIME_STREAM) {
BIO *bio, *tbio;
bio = BIO_new_NDEF(out, val, it);
if (!bio) {
- ASN1err(ASN1_F_I2D_ASN1_BIO_STREAM, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
- SMIME_crlf_copy(in, bio, flags);
+ if (!SMIME_crlf_copy(in, bio, flags)) {
+ rv = 0;
+ }
+
(void)BIO_flush(bio);
/* Free up successive BIOs until we hit the old output BIO */
do {
@@ -90,7 +97,7 @@ int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
*/
else
ASN1_item_i2d_bio(it, out, val);
- return 1;
+ return rv;
}
/* Base 64 read and write of ASN1 structure */
@@ -102,7 +109,7 @@ static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
int r;
b64 = BIO_new(BIO_f_base64());
if (b64 == NULL) {
- ASN1err(ASN1_F_B64_WRITE_ASN1, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
/*
@@ -128,19 +135,20 @@ int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
return r;
}
-static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it)
+static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it, ASN1_VALUE **x,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
BIO *b64;
ASN1_VALUE *val;
if ((b64 = BIO_new(BIO_f_base64())) == NULL) {
- ASN1err(ASN1_F_B64_READ_ASN1, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
bio = BIO_push(b64, bio);
- val = ASN1_item_d2i_bio(it, bio, NULL);
+ val = ASN1_item_d2i_bio_ex(it, bio, x, libctx, propq);
if (!val)
- ASN1err(ASN1_F_B64_READ_ASN1, ASN1_R_DECODE_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_DECODE_ERROR);
(void)BIO_flush(bio);
BIO_pop(bio);
BIO_free(b64);
@@ -207,9 +215,9 @@ static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs)
goto err;
default:
- if (have_unknown)
+ if (have_unknown) {
write_comma = 0;
- else {
+ } else {
BIO_puts(out, "unknown");
have_unknown = 1;
}
@@ -227,14 +235,16 @@ static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs)
/* SMIME sender */
-int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
- int ctype_nid, int econt_nid,
- STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it)
+int SMIME_write_ASN1_ex(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+ int ctype_nid, int econt_nid,
+ STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
char bound[33], c;
int i;
const char *mime_prefix, *mime_eol, *cname = "smime.p7m";
const char *msg_type = NULL;
+
if (flags & SMIME_OLDMIME)
mime_prefix = "application/x-pkcs7-";
else
@@ -247,7 +257,7 @@ int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
if ((flags & SMIME_DETACHED) && data) {
/* We want multipart/signed */
/* Generate a random boundary */
- if (RAND_bytes((unsigned char *)bound, 32) <= 0)
+ if (RAND_bytes_ex(libctx, (unsigned char *)bound, 32, 0) <= 0)
return 0;
for (i = 0; i < 32; i++) {
c = bound[i] & 0xf;
@@ -288,9 +298,9 @@ int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
/* Determine smime-type header */
- if (ctype_nid == NID_pkcs7_enveloped)
+ if (ctype_nid == NID_pkcs7_enveloped) {
msg_type = "enveloped-data";
- else if (ctype_nid == NID_pkcs7_signed) {
+ } else if (ctype_nid == NID_pkcs7_signed) {
if (econt_nid == NID_id_smime_ct_receipt)
msg_type = "signed-receipt";
else if (sk_X509_ALGOR_num(mdalgs) >= 0)
@@ -317,8 +327,17 @@ int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
return 1;
}
+int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+ int ctype_nid, int econt_nid,
+ STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it)
+{
+ return SMIME_write_ASN1_ex(bio, val, data, flags, ctype_nid, econt_nid,
+ mdalgs, it, NULL, NULL);
+}
+
/* Handle output of ASN1 data */
+/* cannot constify val because of CMS_dataFinal() */
static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
const ASN1_ITEM *it)
{
@@ -332,12 +351,11 @@ static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
* set up to finalise when it is written through.
*/
if (!(flags & SMIME_DETACHED) || (flags & PKCS7_REUSE_DIGEST)) {
- SMIME_crlf_copy(data, out, flags);
- return 1;
+ return SMIME_crlf_copy(data, out, flags);
}
if (!aux || !aux->asn1_cb) {
- ASN1err(ASN1_F_ASN1_OUTPUT_DATA, ASN1_R_STREAMING_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_STREAMING_NOT_SUPPORTED);
return 0;
}
@@ -351,7 +369,8 @@ static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
return 0;
/* Copy data across, passing through filter BIOs for processing */
- SMIME_crlf_copy(data, sarg.ndef_bio, flags);
+ if (!SMIME_crlf_copy(data, sarg.ndef_bio, flags))
+ rv = 0;
/* Finalize structure */
if (aux->asn1_cb(ASN1_OP_DETACHED_POST, &val, it, &sarg) <= 0)
@@ -375,7 +394,9 @@ static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
* opaque this is set to NULL
*/
-ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
+ASN1_VALUE *SMIME_read_ASN1_ex(BIO *bio, int flags, BIO **bcont,
+ const ASN1_ITEM *it, ASN1_VALUE **x,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
BIO *asnin;
STACK_OF(MIME_HEADER) *headers = NULL;
@@ -389,14 +410,14 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
*bcont = NULL;
if ((headers = mime_parse_hdr(bio)) == NULL) {
- ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_PARSE_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_PARSE_ERROR);
return NULL;
}
if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
|| hdr->value == NULL) {
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
- ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_CONTENT_TYPE);
return NULL;
}
@@ -405,15 +426,15 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
if (strcmp(hdr->value, "multipart/signed") == 0) {
/* Split into two parts */
prm = mime_param_find(hdr, "boundary");
- if (!prm || !prm->param_value) {
+ if (prm == NULL || prm->param_value == NULL) {
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
- ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY);
return NULL;
}
- ret = multi_split(bio, prm->param_value, &parts);
+ ret = multi_split(bio, flags, prm->param_value, &parts);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
if (!ret || (sk_BIO_num(parts) != 2)) {
- ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE);
sk_BIO_pop_free(parts, BIO_vfree);
return NULL;
}
@@ -422,7 +443,7 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
asnin = sk_BIO_value(parts, 1);
if ((headers = mime_parse_hdr(asnin)) == NULL) {
- ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_SIG_PARSE_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_SIG_PARSE_ERROR);
sk_BIO_pop_free(parts, BIO_vfree);
return NULL;
}
@@ -432,23 +453,23 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
|| hdr->value == NULL) {
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
- ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE);
sk_BIO_pop_free(parts, BIO_vfree);
return NULL;
}
if (strcmp(hdr->value, "application/x-pkcs7-signature") &&
strcmp(hdr->value, "application/pkcs7-signature")) {
- ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_SIG_INVALID_MIME_TYPE);
- ERR_add_error_data(2, "type: ", hdr->value);
+ ERR_raise_data(ERR_LIB_ASN1, ASN1_R_SIG_INVALID_MIME_TYPE,
+ "type: %s", hdr->value);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
sk_BIO_pop_free(parts, BIO_vfree);
return NULL;
}
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
/* Read in ASN1 */
- if ((val = b64_read_asn1(asnin, it)) == NULL) {
- ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR);
+ if ((val = b64_read_asn1(asnin, it, x, libctx, propq)) == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR);
sk_BIO_pop_free(parts, BIO_vfree);
return NULL;
}
@@ -457,8 +478,9 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
*bcont = sk_BIO_value(parts, 0);
BIO_free(asnin);
sk_BIO_free(parts);
- } else
+ } else {
sk_BIO_pop_free(parts, BIO_vfree);
+ }
return val;
}
@@ -466,20 +488,24 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
if (strcmp(hdr->value, "application/x-pkcs7-mime") &&
strcmp(hdr->value, "application/pkcs7-mime")) {
- ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_INVALID_MIME_TYPE);
- ERR_add_error_data(2, "type: ", hdr->value);
+ ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_MIME_TYPE,
+ "type: %s", hdr->value);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
return NULL;
}
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
- if ((val = b64_read_asn1(bio, it)) == NULL) {
- ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_PARSE_ERROR);
+ if ((val = b64_read_asn1(bio, it, x, libctx, propq)) == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ASN1_PARSE_ERROR);
return NULL;
}
return val;
+}
+ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
+{
+ return SMIME_read_ASN1_ex(bio, 0, bcont, it, NULL, NULL, NULL);
}
/* Copy text from one BIO to another making the output CRLF at EOL */
@@ -495,8 +521,10 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
* when streaming as we don't end up with one OCTET STRING per line.
*/
bf = BIO_new(BIO_f_buffer());
- if (bf == NULL)
+ if (bf == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
+ }
out = BIO_push(bf, out);
if (flags & SMIME_BINARY) {
while ((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0)
@@ -507,7 +535,7 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) {
eol = strip_eol(linebuf, &len, flags);
- if (len) {
+ if (len > 0) {
/* Not EOF: write out all CRLF */
if (flags & SMIME_ASCIICRLF) {
int i;
@@ -518,10 +546,11 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
BIO_write(out, linebuf, len);
if (eol)
BIO_write(out, "\r\n", 2);
- } else if (flags & SMIME_ASCIICRLF)
+ } else if (flags & SMIME_ASCIICRLF) {
eolcnt++;
- else if (eol)
+ } else if (eol) {
BIO_write(out, "\r\n", 2);
+ }
}
}
ret = BIO_flush(out);
@@ -542,18 +571,18 @@ int SMIME_text(BIO *in, BIO *out)
MIME_HEADER *hdr;
if ((headers = mime_parse_hdr(in)) == NULL) {
- ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_PARSE_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_PARSE_ERROR);
return 0;
}
if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
|| hdr->value == NULL) {
- ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_NO_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_NO_CONTENT_TYPE);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
return 0;
}
if (strcmp(hdr->value, "text/plain")) {
- ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_INVALID_MIME_TYPE);
- ERR_add_error_data(2, "type: ", hdr->value);
+ ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_MIME_TYPE,
+ "type: %s", hdr->value);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
return 0;
}
@@ -570,7 +599,7 @@ int SMIME_text(BIO *in, BIO *out)
* canonical parts in a STACK of bios
*/
-static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret)
+static int multi_split(BIO *bio, int flags, const char *bound, STACK_OF(BIO) **ret)
{
char linebuf[MAX_SMLEN];
int len, blen;
@@ -587,7 +616,7 @@ static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret)
*ret = parts;
if (*ret == NULL)
return 0;
- while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
+ while ((len = BIO_get_line(bio, linebuf, MAX_SMLEN)) > 0) {
state = mime_bound_check(linebuf, len, bound, blen);
if (state == 1) {
first = 1;
@@ -598,9 +627,9 @@ static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret)
return 0;
}
return 1;
- } else if (part) {
- /* Strip CR+LF from linebuf */
- next_eol = strip_eol(linebuf, &len, 0);
+ } else if (part != 0) {
+ /* Strip (possibly CR +) LF from linebuf */
+ next_eol = strip_eol(linebuf, &len, flags);
if (first) {
first = 0;
if (bpart)
@@ -612,10 +641,20 @@ static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret)
if (bpart == NULL)
return 0;
BIO_set_mem_eof_return(bpart, 0);
- } else if (eol)
- BIO_write(bpart, "\r\n", 2);
+ } else if (eol) {
+ if (
+#ifndef OPENSSL_NO_CMS
+ (flags & CMS_BINARY) == 0
+#else
+ 1
+#endif
+ || (flags & SMIME_CRLFEOL) != 0)
+ BIO_write(bpart, "\r\n", 2);
+ else
+ BIO_write(bpart, "\n", 1);
+ }
eol = next_eol;
- if (len)
+ if (len > 0)
BIO_write(bpart, linebuf, len);
}
}
@@ -739,15 +778,16 @@ static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio)
goto err;
mhdr = new_hdr;
new_hdr = NULL;
- } else if (state == MIME_VALUE)
+ } else if (state == MIME_VALUE) {
mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
+ }
if (p == linebuf)
break; /* Blank line means end of headers */
}
return headers;
-err:
+ err:
mime_hdr_free(new_hdr);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
return NULL;
@@ -762,7 +802,7 @@ static char *strip_ends(char *name)
static char *strip_start(char *name)
{
char *p, c;
- /* Look for first non white space or quote */
+ /* Look for first non whitespace or quote */
for (p = name; (c = *p); p++) {
if (c == '"') {
/* Next char is start of string if non null */
@@ -783,7 +823,7 @@ static char *strip_end(char *name)
char *p, c;
if (!name)
return NULL;
- /* Look for first non white space or quote */
+ /* Look for first non whitespace or quote */
for (p = name + strlen(name) - 1; p >= name; p--) {
c = *p;
if (c == '"') {
@@ -869,8 +909,8 @@ static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *va
static int mime_hdr_cmp(const MIME_HEADER *const *a,
const MIME_HEADER *const *b)
{
- if (!(*a)->name || !(*b)->name)
- return ! !(*a)->name - ! !(*b)->name;
+ if ((*a)->name == NULL || (*b)->name == NULL)
+ return ((*a)->name != NULL) - ((*b)->name != NULL);
return strcmp((*a)->name, (*b)->name);
}
@@ -878,8 +918,8 @@ static int mime_hdr_cmp(const MIME_HEADER *const *a,
static int mime_param_cmp(const MIME_PARAM *const *a,
const MIME_PARAM *const *b)
{
- if (!(*a)->param_name || !(*b)->param_name)
- return ! !(*a)->param_name - ! !(*b)->param_name;
+ if ((*a)->param_name == NULL || (*b)->param_name == NULL)
+ return ((*a)->param_name != NULL) - ((*b)->param_name != NULL);
return strcmp((*a)->param_name, (*b)->param_name);
}
@@ -959,11 +999,26 @@ static int strip_eol(char *linebuf, int *plen, int flags)
char *p, c;
int is_eol = 0;
+#ifndef OPENSSL_NO_CMS
+ if ((flags & CMS_BINARY) != 0) {
+ if (len <= 0 || linebuf[len - 1] != '\n')
+ return 0;
+ if ((flags & SMIME_CRLFEOL) != 0) {
+ if (len <= 1 || linebuf[len - 2] != '\r')
+ return 0;
+ len--;
+ }
+ len--;
+ *plen = len;
+ return 1;
+ }
+#endif
+
for (p = linebuf + len - 1; len > 0; len--, p--) {
c = *p;
if (c == '\n') {
is_eol = 1;
- } else if (is_eol && flags & SMIME_ASCIICRLF && c == 32) {
+ } else if (is_eol && (flags & SMIME_ASCIICRLF) != 0 && c == 32) {
/* Strip trailing space on a line; 32 == ASCII for ' ' */
continue;
} else if (c != '\r') {
diff --git a/crypto/asn1/asn_moid.c b/crypto/asn1/asn_moid.c
index 732ce972aa29..526219c1a723 100644
--- a/crypto/asn1/asn_moid.c
+++ b/crypto/asn1/asn_moid.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -29,13 +29,13 @@ static int oid_module_init(CONF_IMODULE *md, const CONF *cnf)
oid_section = CONF_imodule_get_value(md);
if ((sktmp = NCONF_get_section(cnf, oid_section)) == NULL) {
- ASN1err(ASN1_F_OID_MODULE_INIT, ASN1_R_ERROR_LOADING_SECTION);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_LOADING_SECTION);
return 0;
}
for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
oval = sk_CONF_VALUE_value(sktmp, i);
if (!do_create(oval->value, oval->name)) {
- ASN1err(ASN1_F_OID_MODULE_INIT, ASN1_R_ADDING_OBJECT);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ADDING_OBJECT);
return 0;
}
}
@@ -84,7 +84,7 @@ static int do_create(const char *value, const char *name)
}
p++;
if ((lntmp = OPENSSL_malloc((p - ln) + 1)) == NULL) {
- ASN1err(ASN1_F_DO_CREATE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(lntmp, ln, p - ln);
diff --git a/crypto/asn1/asn_mstbl.c b/crypto/asn1/asn_mstbl.c
index ddcbcd07fe6e..3543cd22568f 100644
--- a/crypto/asn1/asn_mstbl.c
+++ b/crypto/asn1/asn_mstbl.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2012-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -26,13 +26,13 @@ static int stbl_module_init(CONF_IMODULE *md, const CONF *cnf)
stbl_section = CONF_imodule_get_value(md);
if ((sktmp = NCONF_get_section(cnf, stbl_section)) == NULL) {
- ASN1err(ASN1_F_STBL_MODULE_INIT, ASN1_R_ERROR_LOADING_SECTION);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_LOADING_SECTION);
return 0;
}
for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
mval = sk_CONF_VALUE_value(sktmp, i);
if (!do_tcreate(mval->value, mval->name)) {
- ASN1err(ASN1_F_STBL_MODULE_INIT, ASN1_R_INVALID_VALUE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_VALUE);
return 0;
}
}
@@ -96,17 +96,17 @@ static int do_tcreate(const char *value, const char *name)
rv = 1;
err:
if (rv == 0) {
- ASN1err(ASN1_F_DO_TCREATE, ASN1_R_INVALID_STRING_TABLE_VALUE);
if (cnf)
- ERR_add_error_data(4, "field=", cnf->name,
- ", value=", cnf->value);
+ ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_STRING_TABLE_VALUE,
+ "field=%s, value=%s", cnf->name, cnf->value);
else
- ERR_add_error_data(4, "name=", name, ", value=", value);
+ ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_STRING_TABLE_VALUE,
+ "name=%s, value=%s", name, value);
} else {
rv = ASN1_STRING_TABLE_add(nid, tbl_min, tbl_max,
tbl_mask, tbl_flags);
if (!rv)
- ASN1err(ASN1_F_DO_TCREATE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
}
sk_CONF_VALUE_pop_free(lst, X509V3_conf_free);
return rv;
diff --git a/crypto/asn1/asn_pack.c b/crypto/asn1/asn_pack.c
index 63bc30675655..292e6d817697 100644
--- a/crypto/asn1/asn_pack.c
+++ b/crypto/asn1/asn_pack.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -19,7 +19,7 @@ ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
if (oct == NULL || *oct == NULL) {
if ((octmp = ASN1_STRING_new()) == NULL) {
- ASN1err(ASN1_F_ASN1_ITEM_PACK, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else {
@@ -30,11 +30,11 @@ ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
octmp->data = NULL;
if ((octmp->length = ASN1_item_i2d(obj, &octmp->data, it)) == 0) {
- ASN1err(ASN1_F_ASN1_ITEM_PACK, ASN1_R_ENCODE_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ENCODE_ERROR);
goto err;
}
if (octmp->data == NULL) {
- ASN1err(ASN1_F_ASN1_ITEM_PACK, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -57,6 +57,6 @@ void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it)
p = oct->data;
if ((ret = ASN1_item_d2i(NULL, &p, oct->length, it)) == NULL)
- ASN1err(ASN1_F_ASN1_ITEM_UNPACK, ASN1_R_DECODE_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_DECODE_ERROR);
return ret;
}
diff --git a/crypto/asn1/bio_asn1.c b/crypto/asn1/bio_asn1.c
index 17b0d1aa6cad..0ff239120451 100644
--- a/crypto/asn1/bio_asn1.c
+++ b/crypto/asn1/bio_asn1.c
@@ -1,7 +1,7 @@
/*
* Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -79,10 +79,8 @@ static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
static const BIO_METHOD methods_asn1 = {
BIO_TYPE_ASN1,
"asn1",
- /* TODO: Convert to new style write function */
bwrite_conv,
asn1_bio_write,
- /* TODO: Convert to new style read function */
bread_conv,
asn1_bio_read,
asn1_bio_puts,
@@ -102,8 +100,10 @@ static int asn1_bio_new(BIO *b)
{
BIO_ASN1_BUF_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
- if (ctx == NULL)
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
+ }
if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) {
OPENSSL_free(ctx);
return 0;
@@ -116,8 +116,8 @@ static int asn1_bio_new(BIO *b)
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
{
- if ((ctx->buf = OPENSSL_malloc(size)) == NULL) {
- ASN1err(ASN1_F_ASN1_BIO_INIT, ERR_R_MALLOC_FAILURE);
+ if (size <= 0 || (ctx->buf = OPENSSL_malloc(size)) == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
ctx->bufsize = size;
diff --git a/crypto/asn1/bio_ndef.c b/crypto/asn1/bio_ndef.c
index c8a776b482d0..e5b5319d7fd0 100644
--- a/crypto/asn1/bio_ndef.c
+++ b/crypto/asn1/bio_ndef.c
@@ -1,7 +1,7 @@
/*
* Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -64,7 +64,7 @@ BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
BIO *pop_bio = NULL;
if (!aux || !aux->asn1_cb) {
- ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_STREAMING_NOT_SUPPORTED);
return NULL;
}
ndef_aux = OPENSSL_zalloc(sizeof(*ndef_aux));
@@ -132,7 +132,7 @@ static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
unsigned char *p;
int derlen;
- if (!parg)
+ if (parg == NULL)
return 0;
ndef_aux = *(NDEF_SUPPORT **)parg;
@@ -141,15 +141,15 @@ static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
if (derlen < 0)
return 0;
if ((p = OPENSSL_malloc(derlen)) == NULL) {
- ASN1err(ASN1_F_NDEF_PREFIX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
ndef_aux->derbuf = p;
*pbuf = p;
- derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
+ ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
- if (!*ndef_aux->boundary)
+ if (*ndef_aux->boundary == NULL)
return 0;
*plen = *ndef_aux->boundary - *pbuf;
@@ -162,7 +162,7 @@ static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
{
NDEF_SUPPORT *ndef_aux;
- if (!parg)
+ if (parg == NULL)
return 0;
ndef_aux = *(NDEF_SUPPORT **)parg;
@@ -197,7 +197,7 @@ static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
const ASN1_AUX *aux;
ASN1_STREAM_ARG sarg;
- if (!parg)
+ if (parg == NULL)
return 0;
ndef_aux = *(NDEF_SUPPORT **)parg;
@@ -213,8 +213,10 @@ static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
return 0;
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
+ if (derlen < 0)
+ return 0;
if ((p = OPENSSL_malloc(derlen)) == NULL) {
- ASN1err(ASN1_F_NDEF_SUFFIX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -222,7 +224,7 @@ static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
*pbuf = p;
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
- if (!*ndef_aux->boundary)
+ if (*ndef_aux->boundary == NULL)
return 0;
*pbuf = *ndef_aux->boundary;
*plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
diff --git a/crypto/asn1/build.info b/crypto/asn1/build.info
index d3e92c81acfe..33b86fdd31f5 100644
--- a/crypto/asn1/build.info
+++ b/crypto/asn1/build.info
@@ -4,13 +4,20 @@ SOURCE[../../libcrypto]=\
a_print.c a_type.c a_dup.c a_d2i_fp.c a_i2d_fp.c \
a_utf8.c a_sign.c a_digest.c a_verify.c a_mbstr.c a_strex.c \
x_algor.c x_val.c x_sig.c x_bignum.c \
- x_long.c x_int64.c x_info.c x_spki.c nsseq.c \
- d2i_pu.c d2i_pr.c i2d_pu.c i2d_pr.c\
+ x_int64.c x_info.c x_spki.c nsseq.c \
+ d2i_pu.c d2i_pr.c i2d_evp.c \
t_pkey.c t_spki.c t_bitst.c \
tasn_new.c tasn_fre.c tasn_enc.c tasn_dec.c tasn_utl.c tasn_typ.c \
tasn_prn.c tasn_scn.c ameth_lib.c \
- f_int.c f_string.c n_pkey.c \
+ f_int.c f_string.c \
x_pkey.c bio_asn1.c bio_ndef.c asn_mime.c \
- asn1_gen.c asn1_par.c asn1_lib.c asn1_err.c a_strnid.c \
+ asn1_gen.c asn1_parse.c asn1_lib.c asn1_err.c a_strnid.c \
evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p5_scrypt.c p8_pkey.c \
- asn_moid.c asn_mstbl.c asn1_item_list.c
+ asn_moid.c asn_mstbl.c asn1_item_list.c \
+ d2i_param.c
+IF[{- !$disabled{'rsa'} and !$disabled{'rc4'} -}]
+ SOURCE[../../libcrypto]=n_pkey.c
+ENDIF
+IF[{- !$disabled{'deprecated-3.0'} -}]
+ SOURCE[../../libcrypto]=x_long.c
+ENDIF
diff --git a/crypto/asn1/charmap.h b/crypto/asn1/charmap.h
index 5630291bd58c..ac1eb076cc26 100644
--- a/crypto/asn1/charmap.h
+++ b/crypto/asn1/charmap.h
@@ -2,9 +2,9 @@
* WARNING: do not edit!
* Generated by crypto/asn1/charmap.pl
*
- * Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/asn1/charmap.pl b/crypto/asn1/charmap.pl
index 52fa5a7900ca..78053dee15fb 100644
--- a/crypto/asn1/charmap.pl
+++ b/crypto/asn1/charmap.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -87,6 +87,7 @@ $arr[ord("?")] |= $PSTRING_CHAR;
# Year the file was generated.
my $YEAR = OpenSSL::copyright::year_of($0);
+
print <<EOF;
/*
* WARNING: do not edit!
@@ -94,7 +95,7 @@ print <<EOF;
*
* Copyright 2000-$YEAR The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/asn1/d2i_param.c b/crypto/asn1/d2i_param.c
new file mode 100644
index 000000000000..1a0e2bfe6da4
--- /dev/null
+++ b/crypto/asn1/d2i_param.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/evp.h>
+#include <openssl/asn1.h>
+#include "internal/asn1.h"
+#include "crypto/asn1.h"
+#include "crypto/evp.h"
+
+EVP_PKEY *d2i_KeyParams(int type, EVP_PKEY **a, const unsigned char **pp,
+ long length)
+{
+ EVP_PKEY *ret = NULL;
+
+ if ((a == NULL) || (*a == NULL)) {
+ if ((ret = EVP_PKEY_new()) == NULL)
+ return NULL;
+ } else
+ ret = *a;
+
+ if (type != EVP_PKEY_get_id(ret) && !EVP_PKEY_set_type(ret, type))
+ goto err;
+
+ if (ret->ameth == NULL || ret->ameth->param_decode == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_TYPE);
+ goto err;
+ }
+
+ if (!ret->ameth->param_decode(ret, pp, length))
+ goto err;
+
+ if (a != NULL)
+ (*a) = ret;
+ return ret;
+err:
+ if (a == NULL || *a != ret)
+ EVP_PKEY_free(ret);
+ return NULL;
+}
+
+EVP_PKEY *d2i_KeyParams_bio(int type, EVP_PKEY **a, BIO *in)
+{
+ BUF_MEM *b = NULL;
+ const unsigned char *p;
+ void *ret = NULL;
+ int len;
+
+ len = asn1_d2i_read_bio(in, &b);
+ if (len < 0)
+ goto err;
+
+ p = (unsigned char *)b->data;
+ ret = d2i_KeyParams(type, a, &p, len);
+err:
+ BUF_MEM_free(b);
+ return ret;
+}
diff --git a/crypto/asn1/d2i_pr.c b/crypto/asn1/d2i_pr.c
index 2094963036fe..720b7fd6c050 100644
--- a/crypto/asn1/d2i_pr.c
+++ b/crypto/asn1/d2i_pr.c
@@ -1,32 +1,89 @@
/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
+#include <openssl/decoder.h>
#include <openssl/engine.h>
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include "crypto/asn1.h"
#include "crypto/evp.h"
+#include "internal/asn1.h"
-EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
- long length)
+static EVP_PKEY *
+d2i_PrivateKey_decoder(int keytype, EVP_PKEY **a, const unsigned char **pp,
+ long length, OSSL_LIB_CTX *libctx, const char *propq)
+{
+ OSSL_DECODER_CTX *dctx = NULL;
+ size_t len = length;
+ EVP_PKEY *pkey = NULL, *bak_a = NULL;
+ EVP_PKEY **ppkey = &pkey;
+ const char *key_name = NULL;
+ const char *input_structures[] = { "type-specific", "PrivateKeyInfo", NULL };
+ int i, ret;
+
+ if (keytype != EVP_PKEY_NONE) {
+ key_name = evp_pkey_type2name(keytype);
+ if (key_name == NULL)
+ return NULL;
+ }
+
+ for (i = 0; i < (int)OSSL_NELEM(input_structures); ++i) {
+ const unsigned char *p = *pp;
+
+ if (a != NULL && (bak_a = *a) != NULL)
+ ppkey = a;
+ dctx = OSSL_DECODER_CTX_new_for_pkey(ppkey, "DER",
+ input_structures[i], key_name,
+ EVP_PKEY_KEYPAIR, libctx, propq);
+ if (a != NULL)
+ *a = bak_a;
+ if (dctx == NULL)
+ continue;
+
+ ret = OSSL_DECODER_from_data(dctx, pp, &len);
+ OSSL_DECODER_CTX_free(dctx);
+ if (ret) {
+ if (*ppkey != NULL
+ && evp_keymgmt_util_has(*ppkey, OSSL_KEYMGMT_SELECT_PRIVATE_KEY)) {
+ if (a != NULL)
+ *a = *ppkey;
+ return *ppkey;
+ }
+ *pp = p;
+ goto err;
+ }
+ }
+ /* Fall through to error if all decodes failed */
+err:
+ if (ppkey != a)
+ EVP_PKEY_free(*ppkey);
+ return NULL;
+}
+
+EVP_PKEY *
+ossl_d2i_PrivateKey_legacy(int keytype, EVP_PKEY **a, const unsigned char **pp,
+ long length, OSSL_LIB_CTX *libctx, const char *propq)
{
EVP_PKEY *ret;
const unsigned char *p = *pp;
- if ((a == NULL) || (*a == NULL)) {
+ if (a == NULL || *a == NULL) {
if ((ret = EVP_PKEY_new()) == NULL) {
- ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
return NULL;
}
} else {
@@ -37,35 +94,45 @@ EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
#endif
}
- if (!EVP_PKEY_set_type(ret, type)) {
- ASN1err(ASN1_F_D2I_PRIVATEKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
+ if (!EVP_PKEY_set_type(ret, keytype)) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
goto err;
}
+ ERR_set_mark();
if (!ret->ameth->old_priv_decode ||
!ret->ameth->old_priv_decode(ret, &p, length)) {
- if (ret->ameth->priv_decode) {
+ if (ret->ameth->priv_decode != NULL
+ || ret->ameth->priv_decode_ex != NULL) {
EVP_PKEY *tmp;
PKCS8_PRIV_KEY_INFO *p8 = NULL;
p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
- if (!p8)
+ if (p8 == NULL) {
+ ERR_clear_last_mark();
goto err;
- tmp = EVP_PKCS82PKEY(p8);
+ }
+ tmp = evp_pkcs82pkey_legacy(p8, libctx, propq);
PKCS8_PRIV_KEY_INFO_free(p8);
- if (tmp == NULL)
+ if (tmp == NULL) {
+ ERR_clear_last_mark();
goto err;
+ }
EVP_PKEY_free(ret);
ret = tmp;
- if (EVP_PKEY_type(type) != EVP_PKEY_base_id(ret))
+ ERR_pop_to_mark();
+ if (EVP_PKEY_type(keytype) != EVP_PKEY_get_base_id(ret))
goto err;
} else {
- ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB);
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
goto err;
}
+ } else {
+ ERR_clear_last_mark();
}
*pp = p;
if (a != NULL)
- (*a) = ret;
+ *a = ret;
return ret;
err:
if (a == NULL || *a != ret)
@@ -73,58 +140,36 @@ EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
return NULL;
}
-/*
- * This works like d2i_PrivateKey() except it automatically works out the
- * type
- */
-
-static EVP_PKEY *key_as_pkcs8(const unsigned char **pp, long length, int *carry_on)
+EVP_PKEY *d2i_PrivateKey_ex(int keytype, EVP_PKEY **a, const unsigned char **pp,
+ long length, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
- const unsigned char *p = *pp;
- PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
EVP_PKEY *ret;
- if (p8 == NULL)
- return NULL;
-
- ret = EVP_PKCS82PKEY(p8);
+ ret = d2i_PrivateKey_decoder(keytype, a, pp, length, libctx, propq);
+ /* try the legacy path if the decoder failed */
if (ret == NULL)
- *carry_on = 0;
-
- PKCS8_PRIV_KEY_INFO_free(p8);
-
- if (ret != NULL)
- *pp = p;
-
+ ret = ossl_d2i_PrivateKey_legacy(keytype, a, pp, length, libctx, propq);
return ret;
}
-EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
- long length)
+EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
+ long length)
+{
+ return d2i_PrivateKey_ex(type, a, pp, length, NULL, NULL);
+}
+
+static EVP_PKEY *d2i_AutoPrivateKey_legacy(EVP_PKEY **a,
+ const unsigned char **pp,
+ long length,
+ OSSL_LIB_CTX *libctx,
+ const char *propq)
{
STACK_OF(ASN1_TYPE) *inkey;
const unsigned char *p;
int keytype;
- EVP_PKEY *ret = NULL;
- int carry_on = 1;
-
- ERR_set_mark();
- ret = key_as_pkcs8(pp, length, &carry_on);
- if (ret != NULL) {
- ERR_clear_last_mark();
- if (a != NULL)
- *a = ret;
- return ret;
- }
- if (carry_on == 0) {
- ERR_clear_last_mark();
- ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY,
- ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
- return NULL;
- }
p = *pp;
-
/*
* Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): by
* analyzing it we can determine the passed structure: this assumes the
@@ -136,19 +181,55 @@ EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
* Since we only need to discern "traditional format" RSA and DSA keys we
* can just count the elements.
*/
- if (sk_ASN1_TYPE_num(inkey) == 6)
+ if (sk_ASN1_TYPE_num(inkey) == 6) {
keytype = EVP_PKEY_DSA;
- else if (sk_ASN1_TYPE_num(inkey) == 4)
+ } else if (sk_ASN1_TYPE_num(inkey) == 4) {
keytype = EVP_PKEY_EC;
- else
+ } else if (sk_ASN1_TYPE_num(inkey) == 3) { /* This seems to be PKCS8, not
+ * traditional format */
+ PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
+ EVP_PKEY *ret;
+
+ sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
+ if (p8 == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+ return NULL;
+ }
+ ret = evp_pkcs82pkey_legacy(p8, libctx, propq);
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ if (ret == NULL)
+ return NULL;
+ *pp = p;
+ if (a != NULL) {
+ *a = ret;
+ }
+ return ret;
+ } else {
keytype = EVP_PKEY_RSA;
+ }
sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
+ return ossl_d2i_PrivateKey_legacy(keytype, a, pp, length, libctx, propq);
+}
- ret = d2i_PrivateKey(keytype, a, pp, length);
- if (ret != NULL)
- ERR_pop_to_mark();
- else
- ERR_clear_last_mark();
+/*
+ * This works like d2i_PrivateKey() except it passes the keytype as
+ * EVP_PKEY_NONE, which then figures out the type during decoding.
+ */
+EVP_PKEY *d2i_AutoPrivateKey_ex(EVP_PKEY **a, const unsigned char **pp,
+ long length, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ EVP_PKEY *ret;
+ ret = d2i_PrivateKey_decoder(EVP_PKEY_NONE, a, pp, length, libctx, propq);
+ /* try the legacy path if the decoder failed */
+ if (ret == NULL)
+ ret = d2i_AutoPrivateKey_legacy(a, pp, length, libctx, propq);
return ret;
}
+
+EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
+ long length)
+{
+ return d2i_AutoPrivateKey_ex(a, pp, length, NULL, NULL);
+}
diff --git a/crypto/asn1/d2i_pu.c b/crypto/asn1/d2i_pu.c
index 8327ac16ca9c..cf7825c43903 100644
--- a/crypto/asn1/d2i_pu.c
+++ b/crypto/asn1/d2i_pu.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
@@ -23,55 +29,70 @@ EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp,
long length)
{
EVP_PKEY *ret;
+ EVP_PKEY *copy = NULL;
if ((a == NULL) || (*a == NULL)) {
if ((ret = EVP_PKEY_new()) == NULL) {
- ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
return NULL;
}
- } else
+ } else {
ret = *a;
- if (type != EVP_PKEY_id(ret) && !EVP_PKEY_set_type(ret, type)) {
- ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB);
+#ifndef OPENSSL_NO_EC
+ if (evp_pkey_is_provided(ret)
+ && EVP_PKEY_get_base_id(ret) == EVP_PKEY_EC) {
+ if (!evp_pkey_copy_downgraded(&copy, ret))
+ goto err;
+ }
+#endif
+ }
+
+ if ((type != EVP_PKEY_get_id(ret) || copy != NULL)
+ && !EVP_PKEY_set_type(ret, type)) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
goto err;
}
- switch (EVP_PKEY_id(ret)) {
-#ifndef OPENSSL_NO_RSA
+ switch (EVP_PKEY_get_base_id(ret)) {
case EVP_PKEY_RSA:
if ((ret->pkey.rsa = d2i_RSAPublicKey(NULL, pp, length)) == NULL) {
- ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
goto err;
}
break;
-#endif
#ifndef OPENSSL_NO_DSA
case EVP_PKEY_DSA:
- /* TMP UGLY CAST */
if (!d2i_DSAPublicKey(&ret->pkey.dsa, pp, length)) {
- ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
goto err;
}
break;
#endif
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
+ if (copy != NULL) {
+ /* use downgraded parameters from copy */
+ ret->pkey.ec = copy->pkey.ec;
+ copy->pkey.ec = NULL;
+ }
if (!o2i_ECPublicKey(&ret->pkey.ec, pp, length)) {
- ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
goto err;
}
break;
#endif
default:
- ASN1err(ASN1_F_D2I_PUBLICKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
goto err;
}
if (a != NULL)
(*a) = ret;
+ EVP_PKEY_free(copy);
return ret;
err:
if (a == NULL || *a != ret)
EVP_PKEY_free(ret);
+ EVP_PKEY_free(copy);
return NULL;
}
diff --git a/crypto/asn1/evp_asn1.c b/crypto/asn1/evp_asn1.c
index 895085a520a1..13d8ed3893ab 100644
--- a/crypto/asn1/evp_asn1.c
+++ b/crypto/asn1/evp_asn1.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,6 +11,7 @@
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
+#include "crypto/asn1.h"
int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len)
{
@@ -26,14 +27,17 @@ int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len)
return 1;
}
-/* int max_len: for returned value */
+/* int max_len: for returned value
+ * if passing NULL in data, nothing is copied but the necessary length
+ * for it is returned.
+ */
int ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len)
{
int ret, num;
const unsigned char *p;
if ((a->type != V_ASN1_OCTET_STRING) || (a->value.octet_string == NULL)) {
- ASN1err(ASN1_F_ASN1_TYPE_GET_OCTETSTRING, ASN1_R_DATA_IS_WRONG);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_DATA_IS_WRONG);
return -1;
}
p = ASN1_STRING_get0_data(a->value.octet_string);
@@ -42,7 +46,36 @@ int ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_l
num = ret;
else
num = max_len;
- memcpy(data, p, num);
+ if (num > 0 && data != NULL)
+ memcpy(data, p, num);
+ return ret;
+}
+
+static ossl_inline void asn1_type_init_oct(ASN1_OCTET_STRING *oct,
+ unsigned char *data, int len)
+{
+ oct->data = data;
+ oct->type = V_ASN1_OCTET_STRING;
+ oct->length = len;
+ oct->flags = 0;
+}
+
+static int asn1_type_get_int_oct(ASN1_OCTET_STRING *oct, int32_t anum,
+ long *num, unsigned char *data, int max_len)
+{
+ int ret = ASN1_STRING_length(oct), n;
+
+ if (num != NULL)
+ *num = anum;
+
+ if (max_len > ret)
+ n = ret;
+ else
+ n = max_len;
+
+ if (data != NULL)
+ memcpy(data, ASN1_STRING_get0_data(oct), n);
+
return ret;
}
@@ -66,25 +99,18 @@ int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num, unsigned char *data,
atmp.num = num;
atmp.oct = &oct;
- oct.data = data;
- oct.type = V_ASN1_OCTET_STRING;
- oct.length = len;
- oct.flags = 0;
+ asn1_type_init_oct(&oct, data, len);
if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(asn1_int_oct), &atmp, &a))
return 1;
return 0;
}
-/*
- * we return the actual length...
- */
-/* int max_len: for returned value */
int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num,
unsigned char *data, int max_len)
{
asn1_int_oct *atmp = NULL;
- int ret = -1, n;
+ int ret = -1;
if ((a->type != V_ASN1_SEQUENCE) || (a->value.sequence == NULL)) {
goto err;
@@ -95,21 +121,67 @@ int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num,
if (atmp == NULL)
goto err;
- if (num != NULL)
- *num = atmp->num;
+ ret = asn1_type_get_int_oct(atmp->oct, atmp->num, num, data, max_len);
- ret = ASN1_STRING_length(atmp->oct);
- if (max_len > ret)
- n = ret;
- else
- n = max_len;
-
- if (data != NULL)
- memcpy(data, ASN1_STRING_get0_data(atmp->oct), n);
if (ret == -1) {
err:
- ASN1err(ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING, ASN1_R_DATA_IS_WRONG);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_DATA_IS_WRONG);
}
M_ASN1_free_of(atmp, asn1_int_oct);
return ret;
}
+
+typedef struct {
+ ASN1_OCTET_STRING *oct;
+ int32_t num;
+} asn1_oct_int;
+
+/*
+ * Defined in RFC 5084 -
+ * Section 2. "Content-Authenticated Encryption Algorithms"
+ */
+ASN1_SEQUENCE(asn1_oct_int) = {
+ ASN1_SIMPLE(asn1_oct_int, oct, ASN1_OCTET_STRING),
+ ASN1_EMBED(asn1_oct_int, num, INT32)
+} static_ASN1_SEQUENCE_END(asn1_oct_int)
+
+DECLARE_ASN1_ITEM(asn1_oct_int)
+
+int ossl_asn1_type_set_octetstring_int(ASN1_TYPE *a, long num,
+ unsigned char *data, int len)
+{
+ asn1_oct_int atmp;
+ ASN1_OCTET_STRING oct;
+
+ atmp.num = num;
+ atmp.oct = &oct;
+ asn1_type_init_oct(&oct, data, len);
+
+ if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(asn1_oct_int), &atmp, &a))
+ return 1;
+ return 0;
+}
+
+int ossl_asn1_type_get_octetstring_int(const ASN1_TYPE *a, long *num,
+ unsigned char *data, int max_len)
+{
+ asn1_oct_int *atmp = NULL;
+ int ret = -1;
+
+ if ((a->type != V_ASN1_SEQUENCE) || (a->value.sequence == NULL))
+ goto err;
+
+ atmp = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(asn1_oct_int), a);
+
+ if (atmp == NULL)
+ goto err;
+
+ ret = asn1_type_get_int_oct(atmp->oct, atmp->num, num, data, max_len);
+
+ if (ret == -1) {
+ err:
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_DATA_IS_WRONG);
+ }
+ M_ASN1_free_of(atmp, asn1_oct_int);
+ return ret;
+}
diff --git a/crypto/asn1/f_int.c b/crypto/asn1/f_int.c
index 3a18381173d4..d41e0069af63 100644
--- a/crypto/asn1/f_int.c
+++ b/crypto/asn1/f_int.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -100,7 +100,7 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
k = 0;
i -= again;
if (i % 2 != 0) {
- ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_ODD_NUMBER_OF_CHARS);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
OPENSSL_free(s);
return 0;
}
@@ -108,7 +108,7 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
if (num + i > slen) {
sp = OPENSSL_clear_realloc(s, slen, num + i * 2);
if (sp == NULL) {
- ASN1err(ASN1_F_A2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
OPENSSL_free(s);
return 0;
}
@@ -119,8 +119,7 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
for (n = 0; n < 2; n++) {
m = OPENSSL_hexchar2int(bufp[k + n]);
if (m < 0) {
- ASN1err(ASN1_F_A2I_ASN1_INTEGER,
- ASN1_R_NON_HEX_CHARACTERS);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_NON_HEX_CHARACTERS);
goto err;
}
s[num + j] <<= 4;
@@ -137,7 +136,7 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
bs->data = s;
return 1;
err:
- ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_SHORT_LINE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_SHORT_LINE);
OPENSSL_free(s);
return 0;
}
diff --git a/crypto/asn1/f_string.c b/crypto/asn1/f_string.c
index 53dfec71b5d4..4b65110d9866 100644
--- a/crypto/asn1/f_string.c
+++ b/crypto/asn1/f_string.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -91,7 +91,7 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
k = 0;
i -= again;
if (i % 2 != 0) {
- ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_ODD_NUMBER_OF_CHARS);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
OPENSSL_free(s);
return 0;
}
@@ -99,7 +99,7 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
if (num + i > slen) {
sp = OPENSSL_realloc(s, (unsigned int)num + i * 2);
if (sp == NULL) {
- ASN1err(ASN1_F_A2I_ASN1_STRING, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
OPENSSL_free(s);
return 0;
}
@@ -110,8 +110,7 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
for (n = 0; n < 2; n++) {
m = OPENSSL_hexchar2int(bufp[k + n]);
if (m < 0) {
- ASN1err(ASN1_F_A2I_ASN1_STRING,
- ASN1_R_NON_HEX_CHARACTERS);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_NON_HEX_CHARACTERS);
OPENSSL_free(s);
return 0;
}
@@ -130,7 +129,7 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
return 1;
err:
- ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_SHORT_LINE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_SHORT_LINE);
OPENSSL_free(s);
return 0;
}
diff --git a/crypto/asn1/i2d_evp.c b/crypto/asn1/i2d_evp.c
new file mode 100644
index 000000000000..0d66411be8fd
--- /dev/null
+++ b/crypto/asn1/i2d_evp.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/evp.h>
+#include <openssl/encoder.h>
+#include <openssl/buffer.h>
+#include <openssl/x509.h>
+#include <openssl/rsa.h> /* For i2d_RSAPublicKey */
+#include <openssl/dsa.h> /* For i2d_DSAPublicKey */
+#include <openssl/ec.h> /* For i2o_ECPublicKey */
+#include "crypto/asn1.h"
+#include "crypto/evp.h"
+
+struct type_and_structure_st {
+ const char *output_type;
+ const char *output_structure;
+};
+
+static int i2d_provided(const EVP_PKEY *a, int selection,
+ const struct type_and_structure_st *output_info,
+ unsigned char **pp)
+{
+ OSSL_ENCODER_CTX *ctx = NULL;
+ int ret;
+
+ for (ret = -1;
+ ret == -1 && output_info->output_type != NULL;
+ output_info++) {
+ /*
+ * The i2d_ calls don't take a boundary length for *pp. However,
+ * OSSL_ENCODER_to_data() needs one, so we make one up. Because
+ * OSSL_ENCODER_to_data() decrements this number by the amount of
+ * bytes written, we need to calculate the length written further
+ * down, when pp != NULL.
+ */
+ size_t len = INT_MAX;
+ int pp_was_NULL = (pp == NULL || *pp == NULL);
+
+ ctx = OSSL_ENCODER_CTX_new_for_pkey(a, selection,
+ output_info->output_type,
+ output_info->output_structure,
+ NULL);
+ if (ctx == NULL)
+ return -1;
+ if (OSSL_ENCODER_to_data(ctx, pp, &len)) {
+ if (pp_was_NULL)
+ ret = (int)len;
+ else
+ ret = INT_MAX - (int)len;
+ }
+ OSSL_ENCODER_CTX_free(ctx);
+ ctx = NULL;
+ }
+
+ if (ret == -1)
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_TYPE);
+ return ret;
+}
+
+int i2d_KeyParams(const EVP_PKEY *a, unsigned char **pp)
+{
+ if (evp_pkey_is_provided(a)) {
+ static const struct type_and_structure_st output_info[] = {
+ { "DER", "type-specific" },
+ { NULL, }
+ };
+
+ return i2d_provided(a, EVP_PKEY_KEY_PARAMETERS, output_info, pp);
+ }
+ if (a->ameth != NULL && a->ameth->param_encode != NULL)
+ return a->ameth->param_encode(a, pp);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_TYPE);
+ return -1;
+}
+
+int i2d_KeyParams_bio(BIO *bp, const EVP_PKEY *pkey)
+{
+ return ASN1_i2d_bio_of(EVP_PKEY, i2d_KeyParams, bp, pkey);
+}
+
+int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp)
+{
+ if (evp_pkey_is_provided(a)) {
+ static const struct type_and_structure_st output_info[] = {
+ { "DER", "type-specific" },
+ { "DER", "PrivateKeyInfo" },
+ { NULL, }
+ };
+
+ return i2d_provided(a, EVP_PKEY_KEYPAIR, output_info, pp);
+ }
+ if (a->ameth != NULL && a->ameth->old_priv_encode != NULL) {
+ return a->ameth->old_priv_encode(a, pp);
+ }
+ if (a->ameth != NULL && a->ameth->priv_encode != NULL) {
+ PKCS8_PRIV_KEY_INFO *p8 = EVP_PKEY2PKCS8(a);
+ int ret = 0;
+
+ if (p8 != NULL) {
+ ret = i2d_PKCS8_PRIV_KEY_INFO(p8, pp);
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ }
+ return ret;
+ }
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+ return -1;
+}
+
+int i2d_PublicKey(const EVP_PKEY *a, unsigned char **pp)
+{
+ if (evp_pkey_is_provided(a)) {
+ static const struct type_and_structure_st output_info[] = {
+ { "DER", "type-specific" },
+ { "blob", NULL }, /* for EC */
+ { NULL, }
+ };
+
+ return i2d_provided(a, EVP_PKEY_PUBLIC_KEY, output_info, pp);
+ }
+ switch (EVP_PKEY_get_base_id(a)) {
+ case EVP_PKEY_RSA:
+ return i2d_RSAPublicKey(EVP_PKEY_get0_RSA(a), pp);
+#ifndef OPENSSL_NO_DSA
+ case EVP_PKEY_DSA:
+ return i2d_DSAPublicKey(EVP_PKEY_get0_DSA(a), pp);
+#endif
+#ifndef OPENSSL_NO_EC
+ case EVP_PKEY_EC:
+ return i2o_ECPublicKey(EVP_PKEY_get0_EC_KEY(a), pp);
+#endif
+ default:
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+ return -1;
+ }
+}
diff --git a/crypto/asn1/i2d_pr.c b/crypto/asn1/i2d_pr.c
deleted file mode 100644
index 0374c0bfbdc0..000000000000
--- a/crypto/asn1/i2d_pr.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-#include "crypto/asn1.h"
-#include "crypto/evp.h"
-
-int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp)
-{
- if (a->ameth && a->ameth->old_priv_encode) {
- return a->ameth->old_priv_encode(a, pp);
- }
- if (a->ameth && a->ameth->priv_encode) {
- PKCS8_PRIV_KEY_INFO *p8 = EVP_PKEY2PKCS8(a);
- int ret = 0;
- if (p8 != NULL) {
- ret = i2d_PKCS8_PRIV_KEY_INFO(p8, pp);
- PKCS8_PRIV_KEY_INFO_free(p8);
- }
- return ret;
- }
- ASN1err(ASN1_F_I2D_PRIVATEKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
- return -1;
-}
diff --git a/crypto/asn1/i2d_pu.c b/crypto/asn1/i2d_pu.c
deleted file mode 100644
index 8986c43cbee5..000000000000
--- a/crypto/asn1/i2d_pu.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/bn.h>
-#include <openssl/evp.h>
-#include <openssl/objects.h>
-#include <openssl/rsa.h>
-#include <openssl/dsa.h>
-#include <openssl/ec.h>
-
-int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp)
-{
- switch (EVP_PKEY_id(a)) {
-#ifndef OPENSSL_NO_RSA
- case EVP_PKEY_RSA:
- return i2d_RSAPublicKey(EVP_PKEY_get0_RSA(a), pp);
-#endif
-#ifndef OPENSSL_NO_DSA
- case EVP_PKEY_DSA:
- return i2d_DSAPublicKey(EVP_PKEY_get0_DSA(a), pp);
-#endif
-#ifndef OPENSSL_NO_EC
- case EVP_PKEY_EC:
- return i2o_ECPublicKey(EVP_PKEY_get0_EC_KEY(a), pp);
-#endif
- default:
- ASN1err(ASN1_F_I2D_PUBLICKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
- return -1;
- }
-}
diff --git a/crypto/asn1/n_pkey.c b/crypto/asn1/n_pkey.c
index d1fb8a146d62..eb0918f79f97 100644
--- a/crypto/asn1/n_pkey.c
+++ b/crypto/asn1/n_pkey.c
@@ -1,26 +1,26 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include "openssl/opensslconf.h"
-#ifdef OPENSSL_NO_RSA
-NON_EMPTY_TRANSLATION_UNIT
-#else
-
-# include "internal/cryptlib.h"
-# include <stdio.h>
-# include <openssl/rsa.h>
-# include <openssl/objects.h>
-# include <openssl/asn1t.h>
-# include <openssl/evp.h>
-# include <openssl/x509.h>
-
-# ifndef OPENSSL_NO_RC4
+#include <openssl/opensslconf.h>
+#include "internal/cryptlib.h"
+#include <stdio.h>
+#include <openssl/rsa.h>
+#include <openssl/objects.h>
+#include <openssl/asn1t.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+#define ASN1_BROKEN_SEQUENCE(tname) \
+ static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \
+ ASN1_SEQUENCE(tname)
+#define static_ASN1_BROKEN_SEQUENCE_END(stname) \
+ static_ASN1_SEQUENCE_END_ref(stname, stname)
typedef struct netscape_pkey_st {
int32_t version;
@@ -43,9 +43,9 @@ ASN1_BROKEN_SEQUENCE(NETSCAPE_ENCRYPTED_PKEY) = {
ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, enckey, X509_SIG)
} static_ASN1_BROKEN_SEQUENCE_END(NETSCAPE_ENCRYPTED_PKEY)
-DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY)
-DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY,NETSCAPE_ENCRYPTED_PKEY)
-IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY)
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_ENCRYPTED_PKEY)
+DECLARE_ASN1_ENCODE_FUNCTIONS_name(NETSCAPE_ENCRYPTED_PKEY, NETSCAPE_ENCRYPTED_PKEY)
+IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_ENCRYPTED_PKEY)
ASN1_SEQUENCE(NETSCAPE_PKEY) = {
ASN1_EMBED(NETSCAPE_PKEY, version, INT32),
@@ -53,10 +53,6 @@ ASN1_SEQUENCE(NETSCAPE_PKEY) = {
ASN1_SIMPLE(NETSCAPE_PKEY, private_key, ASN1_OCTET_STRING)
} static_ASN1_SEQUENCE_END(NETSCAPE_PKEY)
-DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_PKEY)
-DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_PKEY,NETSCAPE_PKEY)
-IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_PKEY)
-
-# endif /* OPENSSL_NO_RC4 */
-
-#endif
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_PKEY)
+DECLARE_ASN1_ENCODE_FUNCTIONS_name(NETSCAPE_PKEY, NETSCAPE_PKEY)
+IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_PKEY)
diff --git a/crypto/asn1/nsseq.c b/crypto/asn1/nsseq.c
index c7baf40d30f5..09dc24f25f8d 100644
--- a/crypto/asn1/nsseq.c
+++ b/crypto/asn1/nsseq.c
@@ -1,7 +1,7 @@
/*
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/asn1/p5_pbe.c b/crypto/asn1/p5_pbe.c
index ab7e16898fa3..9bc8aaa7a31e 100644
--- a/crypto/asn1/p5_pbe.c
+++ b/crypto/asn1/p5_pbe.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -24,8 +24,9 @@ IMPLEMENT_ASN1_FUNCTIONS(PBEPARAM)
/* Set an algorithm identifier for a PKCS#5 PBE algorithm */
-int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
- const unsigned char *salt, int saltlen)
+int PKCS5_pbe_set0_algor_ex(X509_ALGOR *algor, int alg, int iter,
+ const unsigned char *salt, int saltlen,
+ OSSL_LIB_CTX *ctx)
{
PBEPARAM *pbe = NULL;
ASN1_STRING *pbe_str = NULL;
@@ -33,33 +34,35 @@ int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
pbe = PBEPARAM_new();
if (pbe == NULL) {
- ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
if (iter <= 0)
iter = PKCS5_DEFAULT_ITER;
if (!ASN1_INTEGER_set(pbe->iter, iter)) {
- ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!saltlen)
saltlen = PKCS5_SALT_LEN;
+ if (saltlen < 0)
+ goto err;
sstr = OPENSSL_malloc(saltlen);
if (sstr == NULL) {
- ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
if (salt)
memcpy(sstr, salt, saltlen);
- else if (RAND_bytes(sstr, saltlen) <= 0)
+ else if (RAND_bytes_ex(ctx, sstr, saltlen, 0) <= 0)
goto err;
ASN1_STRING_set0(pbe->salt, sstr, saltlen);
sstr = NULL;
if (!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str)) {
- ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -76,21 +79,35 @@ int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
return 0;
}
+int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
+ const unsigned char *salt, int saltlen)
+{
+ return PKCS5_pbe_set0_algor_ex(algor, alg, iter, salt, saltlen, NULL);
+}
+
/* Return an algorithm identifier for a PKCS#5 PBE algorithm */
-X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
- const unsigned char *salt, int saltlen)
+X509_ALGOR *PKCS5_pbe_set_ex(int alg, int iter,
+ const unsigned char *salt, int saltlen,
+ OSSL_LIB_CTX *ctx)
{
X509_ALGOR *ret;
ret = X509_ALGOR_new();
if (ret == NULL) {
- ASN1err(ASN1_F_PKCS5_PBE_SET, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
- if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen))
+ if (PKCS5_pbe_set0_algor_ex(ret, alg, iter, salt, saltlen, ctx))
return ret;
X509_ALGOR_free(ret);
return NULL;
}
+
+X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
+ const unsigned char *salt, int saltlen)
+{
+ return PKCS5_pbe_set_ex(alg, iter, salt, saltlen, NULL);
+}
+
diff --git a/crypto/asn1/p5_pbev2.c b/crypto/asn1/p5_pbev2.c
index f91ba08f1ea4..711743a77b59 100644
--- a/crypto/asn1/p5_pbev2.c
+++ b/crypto/asn1/p5_pbev2.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,6 +10,8 @@
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
+#include <openssl/core.h>
+#include <openssl/core_names.h>
#include <openssl/x509.h>
#include <openssl/rand.h>
@@ -37,20 +39,20 @@ IMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM)
* and IV.
*/
-X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
- unsigned char *salt, int saltlen,
- unsigned char *aiv, int prf_nid)
+X509_ALGOR *PKCS5_pbe2_set_iv_ex(const EVP_CIPHER *cipher, int iter,
+ unsigned char *salt, int saltlen,
+ unsigned char *aiv, int prf_nid,
+ OSSL_LIB_CTX *libctx)
{
X509_ALGOR *scheme = NULL, *ret = NULL;
- int alg_nid, keylen;
+ int alg_nid, keylen, ivlen;
EVP_CIPHER_CTX *ctx = NULL;
unsigned char iv[EVP_MAX_IV_LENGTH];
PBE2PARAM *pbe2 = NULL;
- alg_nid = EVP_CIPHER_type(cipher);
+ alg_nid = EVP_CIPHER_get_type(cipher);
if (alg_nid == NID_undef) {
- ASN1err(ASN1_F_PKCS5_PBE2_SET_IV,
- ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
goto err;
}
@@ -64,10 +66,11 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
goto merr;
/* Create random IV */
- if (EVP_CIPHER_iv_length(cipher)) {
+ ivlen = EVP_CIPHER_get_iv_length(cipher);
+ if (ivlen > 0) {
if (aiv)
- memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher));
- else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) <= 0)
+ memcpy(iv, aiv, ivlen);
+ else if (RAND_bytes_ex(libctx, iv, ivlen, 0) <= 0)
goto err;
}
@@ -79,25 +82,26 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0))
goto err;
if (EVP_CIPHER_param_to_asn1(ctx, scheme->parameter) <= 0) {
- ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
goto err;
}
/*
* If prf NID unspecified see if cipher has a preference. An error is OK
* here: just means use default PRF.
*/
+ ERR_set_mark();
if ((prf_nid == -1) &&
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0) {
- ERR_clear_error();
prf_nid = NID_hmacWithSHA256;
}
+ ERR_pop_to_mark();
EVP_CIPHER_CTX_free(ctx);
ctx = NULL;
/* If its RC2 then we'd better setup the key length */
if (alg_nid == NID_rc2_cbc)
- keylen = EVP_CIPHER_key_length(cipher);
+ keylen = EVP_CIPHER_get_key_length(cipher);
else
keylen = -1;
@@ -105,9 +109,10 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
X509_ALGOR_free(pbe2->keyfunc);
- pbe2->keyfunc = PKCS5_pbkdf2_set(iter, salt, saltlen, prf_nid, keylen);
+ pbe2->keyfunc = PKCS5_pbkdf2_set_ex(iter, salt, saltlen, prf_nid, keylen,
+ libctx);
- if (!pbe2->keyfunc)
+ if (pbe2->keyfunc == NULL)
goto merr;
/* Now set up top level AlgorithmIdentifier */
@@ -129,7 +134,7 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
return ret;
merr:
- ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
err:
EVP_CIPHER_CTX_free(ctx);
@@ -140,14 +145,25 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
return NULL;
}
+X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
+ unsigned char *salt, int saltlen,
+ unsigned char *aiv, int prf_nid)
+{
+ return PKCS5_pbe2_set_iv_ex(cipher, iter, salt, saltlen, aiv, prf_nid,
+ NULL);
+}
+
X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
unsigned char *salt, int saltlen)
{
- return PKCS5_pbe2_set_iv(cipher, iter, salt, saltlen, NULL, -1);
+ return PKCS5_pbe2_set_iv_ex(cipher, iter, salt, saltlen, NULL, -1,
+ NULL);
}
-X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
- int prf_nid, int keylen)
+
+X509_ALGOR *PKCS5_pbkdf2_set_ex(int iter, unsigned char *salt, int saltlen,
+ int prf_nid, int keylen,
+ OSSL_LIB_CTX *libctx)
{
X509_ALGOR *keyfunc = NULL;
PBKDF2PARAM *kdf = NULL;
@@ -161,6 +177,8 @@ X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
kdf->salt->value.octet_string = osalt;
kdf->salt->type = V_ASN1_OCTET_STRING;
+ if (saltlen < 0)
+ goto merr;
if (saltlen == 0)
saltlen = PKCS5_SALT_LEN;
if ((osalt->data = OPENSSL_malloc(saltlen)) == NULL)
@@ -170,7 +188,7 @@ X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
if (salt)
memcpy(osalt->data, salt, saltlen);
- else if (RAND_bytes(osalt->data, saltlen) <= 0)
+ else if (RAND_bytes_ex(libctx, osalt->data, saltlen, 0) <= 0)
goto merr;
if (iter <= 0)
@@ -214,8 +232,15 @@ X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
return keyfunc;
merr:
- ASN1err(ASN1_F_PKCS5_PBKDF2_SET, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
PBKDF2PARAM_free(kdf);
X509_ALGOR_free(keyfunc);
return NULL;
}
+
+X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
+ int prf_nid, int keylen)
+{
+ return PKCS5_pbkdf2_set_ex(iter, salt, saltlen, prf_nid, keylen, NULL);
+}
+
diff --git a/crypto/asn1/p5_scrypt.c b/crypto/asn1/p5_scrypt.c
index 1491d96ec8d3..a02190d0dc11 100644
--- a/crypto/asn1/p5_scrypt.c
+++ b/crypto/asn1/p5_scrypt.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,10 +10,12 @@
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
+#include <openssl/core_names.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/rand.h>
+#include "crypto/evp.h"
#ifndef OPENSSL_NO_SCRYPT
/* PKCS#5 scrypt password based encryption structures */
@@ -49,20 +51,18 @@ X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
PBE2PARAM *pbe2 = NULL;
if (!cipher) {
- ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
goto err;
}
if (EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) {
- ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT,
- ASN1_R_INVALID_SCRYPT_PARAMETERS);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_SCRYPT_PARAMETERS);
goto err;
}
- alg_nid = EVP_CIPHER_type(cipher);
+ alg_nid = EVP_CIPHER_get_type(cipher);
if (alg_nid == NID_undef) {
- ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT,
- ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
goto err;
}
@@ -79,10 +79,10 @@ X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
goto merr;
/* Create random IV */
- if (EVP_CIPHER_iv_length(cipher)) {
+ if (EVP_CIPHER_get_iv_length(cipher)) {
if (aiv)
- memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher));
- else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) <= 0)
+ memcpy(iv, aiv, EVP_CIPHER_get_iv_length(cipher));
+ else if (RAND_bytes(iv, EVP_CIPHER_get_iv_length(cipher)) <= 0)
goto err;
}
@@ -94,8 +94,7 @@ X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0) == 0)
goto err;
if (EVP_CIPHER_param_to_asn1(ctx, scheme->parameter) <= 0) {
- ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT,
- ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
goto err;
}
EVP_CIPHER_CTX_free(ctx);
@@ -104,7 +103,7 @@ X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
/* If its RC2 then we'd better setup the key length */
if (alg_nid == NID_rc2_cbc)
- keylen = EVP_CIPHER_key_length(cipher);
+ keylen = EVP_CIPHER_get_key_length(cipher);
/* Setup keyfunc */
@@ -135,7 +134,7 @@ X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
return ret;
merr:
- ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
err:
PBE2PARAM_free(pbe2);
@@ -202,26 +201,27 @@ static X509_ALGOR *pkcs5_scrypt_set(const unsigned char *salt, size_t saltlen,
return keyfunc;
merr:
- ASN1err(ASN1_F_PKCS5_SCRYPT_SET, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
err:
SCRYPT_PARAMS_free(sparam);
X509_ALGOR_free(keyfunc);
return NULL;
}
-int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
- int passlen, ASN1_TYPE *param,
- const EVP_CIPHER *c, const EVP_MD *md, int en_de)
+int PKCS5_v2_scrypt_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass,
+ int passlen, ASN1_TYPE *param,
+ const EVP_CIPHER *c, const EVP_MD *md, int en_de,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
unsigned char *salt, key[EVP_MAX_KEY_LENGTH];
uint64_t p, r, N;
size_t saltlen;
size_t keylen = 0;
- int rv = 0;
+ int t, rv = 0;
SCRYPT_PARAMS *sparam = NULL;
- if (EVP_CIPHER_CTX_cipher(ctx) == NULL) {
- EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_NO_CIPHER_SET);
+ if (EVP_CIPHER_CTX_get0_cipher(ctx) == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
goto err;
}
@@ -230,11 +230,16 @@ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
sparam = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(SCRYPT_PARAMS), param);
if (sparam == NULL) {
- EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_DECODE_ERROR);
+ ERR_raise(ERR_LIB_EVP, EVP_R_DECODE_ERROR);
goto err;
}
- keylen = EVP_CIPHER_CTX_key_length(ctx);
+ t = EVP_CIPHER_CTX_get_key_length(ctx);
+ if (t < 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH);
+ goto err;
+ }
+ keylen = t;
/* Now check the parameters of sparam */
@@ -242,8 +247,7 @@ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
uint64_t spkeylen;
if ((ASN1_INTEGER_get_uint64(&spkeylen, sparam->keyLength) == 0)
|| (spkeylen != keylen)) {
- EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN,
- EVP_R_UNSUPPORTED_KEYLENGTH);
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEYLENGTH);
goto err;
}
}
@@ -251,9 +255,9 @@ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
if (ASN1_INTEGER_get_uint64(&N, sparam->costParameter) == 0
|| ASN1_INTEGER_get_uint64(&r, sparam->blockSize) == 0
|| ASN1_INTEGER_get_uint64(&p, sparam->parallelizationParameter) == 0
- || EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) {
- EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN,
- EVP_R_ILLEGAL_SCRYPT_PARAMETERS);
+ || EVP_PBE_scrypt_ex(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0,
+ libctx, propq) == 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_ILLEGAL_SCRYPT_PARAMETERS);
goto err;
}
@@ -261,8 +265,8 @@ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
salt = sparam->salt->data;
saltlen = sparam->salt->length;
- if (EVP_PBE_scrypt(pass, passlen, salt, saltlen, N, r, p, 0, key, keylen)
- == 0)
+ if (EVP_PBE_scrypt_ex(pass, passlen, salt, saltlen, N, r, p, 0, key,
+ keylen, libctx, propq) == 0)
goto err;
rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de);
err:
@@ -271,4 +275,12 @@ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
SCRYPT_PARAMS_free(sparam);
return rv;
}
+
+int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
+ int passlen, ASN1_TYPE *param,
+ const EVP_CIPHER *c, const EVP_MD *md, int en_de)
+{
+ return PKCS5_v2_scrypt_keyivgen_ex(ctx, pass, passlen, param, c, md, en_de, NULL, NULL);
+}
+
#endif /* OPENSSL_NO_SCRYPT */
diff --git a/crypto/asn1/p8_pkey.c b/crypto/asn1/p8_pkey.c
index ab509b1ac976..dee188519c22 100644
--- a/crypto/asn1/p8_pkey.c
+++ b/crypto/asn1/p8_pkey.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -78,3 +78,14 @@ int PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type,
return 1;
return 0;
}
+
+int PKCS8_pkey_add1_attr_by_OBJ(PKCS8_PRIV_KEY_INFO *p8, const ASN1_OBJECT *obj, int type,
+ const unsigned char *bytes, int len)
+{
+ return (X509at_add1_attr_by_OBJ(&p8->attributes, obj, type, bytes, len) != NULL);
+}
+
+int PKCS8_pkey_add1_attr(PKCS8_PRIV_KEY_INFO *p8, X509_ATTRIBUTE *attr)
+{
+ return (X509at_add1_attr(&p8->attributes, attr) != NULL);
+}
diff --git a/crypto/asn1/standard_methods.h b/crypto/asn1/standard_methods.h
index e74de55ffeb6..0b0c7ef6864f 100644
--- a/crypto/asn1/standard_methods.h
+++ b/crypto/asn1/standard_methods.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,49 +13,35 @@
* is used to search it.
*/
static const EVP_PKEY_ASN1_METHOD *standard_methods[] = {
-#ifndef OPENSSL_NO_RSA
- &rsa_asn1_meths[0],
- &rsa_asn1_meths[1],
-#endif
+ &ossl_rsa_asn1_meths[0],
+ &ossl_rsa_asn1_meths[1],
#ifndef OPENSSL_NO_DH
- &dh_asn1_meth,
+ &ossl_dh_asn1_meth,
#endif
#ifndef OPENSSL_NO_DSA
- &dsa_asn1_meths[0],
- &dsa_asn1_meths[1],
- &dsa_asn1_meths[2],
- &dsa_asn1_meths[3],
- &dsa_asn1_meths[4],
+ &ossl_dsa_asn1_meths[0],
+ &ossl_dsa_asn1_meths[1],
+ &ossl_dsa_asn1_meths[2],
+ &ossl_dsa_asn1_meths[3],
+ &ossl_dsa_asn1_meths[4],
#endif
#ifndef OPENSSL_NO_EC
- &eckey_asn1_meth,
-#endif
- &hmac_asn1_meth,
-#ifndef OPENSSL_NO_CMAC
- &cmac_asn1_meth,
-#endif
-#ifndef OPENSSL_NO_RSA
- &rsa_pss_asn1_meth,
+ &ossl_eckey_asn1_meth,
#endif
+ &ossl_rsa_pss_asn1_meth,
#ifndef OPENSSL_NO_DH
- &dhx_asn1_meth,
+ &ossl_dhx_asn1_meth,
#endif
#ifndef OPENSSL_NO_EC
- &ecx25519_asn1_meth,
- &ecx448_asn1_meth,
-#endif
-#ifndef OPENSSL_NO_POLY1305
- &poly1305_asn1_meth,
-#endif
-#ifndef OPENSSL_NO_SIPHASH
- &siphash_asn1_meth,
+ &ossl_ecx25519_asn1_meth,
+ &ossl_ecx448_asn1_meth,
#endif
#ifndef OPENSSL_NO_EC
- &ed25519_asn1_meth,
- &ed448_asn1_meth,
+ &ossl_ed25519_asn1_meth,
+ &ossl_ed448_asn1_meth,
#endif
#ifndef OPENSSL_NO_SM2
- &sm2_asn1_meth,
+ &ossl_sm2_asn1_meth,
#endif
};
diff --git a/crypto/asn1/t_bitst.c b/crypto/asn1/t_bitst.c
index c0aeca4c78cc..e7b817f78e15 100644
--- a/crypto/asn1/t_bitst.c
+++ b/crypto/asn1/t_bitst.c
@@ -1,7 +1,7 @@
/*
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/asn1/t_pkey.c b/crypto/asn1/t_pkey.c
index 651622aedc8f..03579c877cfc 100644
--- a/crypto/asn1/t_pkey.c
+++ b/crypto/asn1/t_pkey.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/asn1/t_spki.c b/crypto/asn1/t_spki.c
index 3d4aea8ad9a4..0397f1f9ee50 100644
--- a/crypto/asn1/t_spki.c
+++ b/crypto/asn1/t_spki.c
@@ -1,7 +1,7 @@
/*
* Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -30,7 +30,7 @@ int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki)
BIO_printf(out, " Public Key Algorithm: %s\n",
(i == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(i));
pkey = X509_PUBKEY_get(spki->spkac->pubkey);
- if (!pkey)
+ if (pkey == NULL)
BIO_printf(out, " Unable to load public key\n");
else {
EVP_PKEY_print_public(out, pkey, 4, NULL);
diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c
index 82577b1edefe..11198087a57b 100644
--- a/crypto/asn1/tasn_dec.c
+++ b/crypto/asn1/tasn_dec.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -17,7 +17,6 @@
#include "internal/numbers.h"
#include "asn1_local.h"
-
/*
* Constructed types with a recursive definition (such as can be found in PKCS7)
* could eventually exceed the stack given malicious input with excessive
@@ -29,7 +28,8 @@
static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
long len, const ASN1_ITEM *it,
int tag, int aclass, char opt, ASN1_TLC *ctx,
- int depth);
+ int depth, OSSL_LIB_CTX *libctx,
+ const char *propq);
static int asn1_check_eoc(const unsigned char **in, long len);
static int asn1_find_end(const unsigned char **in, long len, char inf);
@@ -47,11 +47,13 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
static int asn1_template_ex_d2i(ASN1_VALUE **pval,
const unsigned char **in, long len,
const ASN1_TEMPLATE *tt, char opt,
- ASN1_TLC *ctx, int depth);
+ ASN1_TLC *ctx, int depth, OSSL_LIB_CTX *libctx,
+ const char *propq);
static int asn1_template_noexp_d2i(ASN1_VALUE **val,
const unsigned char **in, long len,
const ASN1_TEMPLATE *tt, char opt,
- ASN1_TLC *ctx, int depth);
+ ASN1_TLC *ctx, int depth,
+ OSSL_LIB_CTX *libctx, const char *propq);
static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
const unsigned char **in, long len,
const ASN1_ITEM *it,
@@ -67,7 +69,7 @@ static const unsigned long tag2bit[32] = {
/* tags 4- 7 */
B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN,
/* tags 8-11 */
- B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN,
+ B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, 0, B_ASN1_UNKNOWN,
/* tags 12-15 */
B_ASN1_UTF8STRING, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN,
/* tags 16-19 */
@@ -91,9 +93,9 @@ unsigned long ASN1_tag2bit(int tag)
/* Macro to initialize and invalidate the cache */
-#define asn1_tlc_clear(c) if (c) (c)->valid = 0
+#define asn1_tlc_clear(c) do { if ((c) != NULL) (c)->valid = 0; } while (0)
/* Version to avoid compiler warning about 'c' always non-NULL */
-#define asn1_tlc_clear_nc(c) (c)->valid = 0
+#define asn1_tlc_clear_nc(c) do {(c)->valid = 0; } while (0)
/*
* Decode an ASN1 item, this currently behaves just like a standard 'd2i'
@@ -102,29 +104,54 @@ unsigned long ASN1_tag2bit(int tag)
* this will simply be a special case.
*/
-ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,
- const unsigned char **in, long len,
- const ASN1_ITEM *it)
+static int asn1_item_ex_d2i_intern(ASN1_VALUE **pval, const unsigned char **in,
+ long len, const ASN1_ITEM *it, int tag,
+ int aclass, char opt, ASN1_TLC *ctx,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ int rv;
+
+ if (pval == NULL || it == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ rv = asn1_item_embed_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0,
+ libctx, propq);
+ if (rv <= 0)
+ ASN1_item_ex_free(pval, it);
+ return rv;
+}
+
+int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
+ const ASN1_ITEM *it,
+ int tag, int aclass, char opt, ASN1_TLC *ctx)
+{
+ return asn1_item_ex_d2i_intern(pval, in, len, it, tag, aclass, opt, ctx,
+ NULL, NULL);
+}
+
+ASN1_VALUE *ASN1_item_d2i_ex(ASN1_VALUE **pval,
+ const unsigned char **in, long len,
+ const ASN1_ITEM *it, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
ASN1_TLC c;
ASN1_VALUE *ptmpval = NULL;
- if (!pval)
+
+ if (pval == NULL)
pval = &ptmpval;
asn1_tlc_clear_nc(&c);
- if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0)
+ if (asn1_item_ex_d2i_intern(pval, in, len, it, -1, 0, 0, &c, libctx,
+ propq) > 0)
return *pval;
return NULL;
}
-int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
- const ASN1_ITEM *it,
- int tag, int aclass, char opt, ASN1_TLC *ctx)
+ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,
+ const unsigned char **in, long len,
+ const ASN1_ITEM *it)
{
- int rv;
- rv = asn1_item_embed_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0);
- if (rv <= 0)
- ASN1_item_ex_free(pval, it);
- return rv;
+ return ASN1_item_d2i_ex(pval, in, len, it, NULL, NULL);
}
/*
@@ -135,11 +162,12 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
long len, const ASN1_ITEM *it,
int tag, int aclass, char opt, ASN1_TLC *ctx,
- int depth)
+ int depth, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
const ASN1_TEMPLATE *tt, *errtt = NULL;
const ASN1_EXTERN_FUNCS *ef;
- const ASN1_AUX *aux = it->funcs;
+ const ASN1_AUX *aux;
ASN1_aux_cb *asn1_cb;
const unsigned char *p = NULL, *q;
unsigned char oclass;
@@ -149,15 +177,23 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
int otag;
int ret = 0;
ASN1_VALUE **pchptr;
- if (!pval)
+
+ if (pval == NULL || it == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
return 0;
+ }
+ if (len <= 0) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL);
+ return 0;
+ }
+ aux = it->funcs;
if (aux && aux->asn1_cb)
asn1_cb = aux->asn1_cb;
else
asn1_cb = 0;
if (++depth > ASN1_MAX_CONSTRUCTED_NEST) {
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_NESTED_TOO_DEEP);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_NESTED_TOO_DEEP);
goto err;
}
@@ -171,12 +207,12 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
* template in the template itself.
*/
if ((tag != -1) || opt) {
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I,
- ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);
+ ERR_raise(ERR_LIB_ASN1,
+ ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);
goto err;
}
- return asn1_template_ex_d2i(pval, in, len,
- it->templates, opt, ctx, depth);
+ return asn1_template_ex_d2i(pval, in, len, it->templates, opt, ctx,
+ depth, libctx, propq);
}
return asn1_d2i_ex_primitive(pval, in, len, it,
tag, aclass, opt, ctx);
@@ -187,7 +223,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
* if tag != -1, then this looks like an error in the template.
*/
if (tag != -1) {
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_BAD_TEMPLATE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE);
goto err;
}
@@ -196,7 +232,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL,
&p, len, -1, 0, 1, ctx);
if (!ret) {
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
goto err;
}
@@ -205,7 +241,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
/* If OPTIONAL, assume this is OK */
if (opt)
return -1;
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MSTRING_NOT_UNIVERSAL);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_MSTRING_NOT_UNIVERSAL);
goto err;
}
@@ -214,7 +250,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
/* If OPTIONAL, assume this is OK */
if (opt)
return -1;
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MSTRING_WRONG_TAG);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_MSTRING_WRONG_TAG);
goto err;
}
return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0, ctx);
@@ -222,6 +258,9 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
case ASN1_ITYPE_EXTERN:
/* Use new style d2i */
ef = it->funcs;
+ if (ef->asn1_ex_d2i_ex != NULL)
+ return ef->asn1_ex_d2i_ex(pval, in, len, it, tag, aclass, opt, ctx,
+ libctx, propq);
return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx);
case ASN1_ITYPE_CHOICE:
@@ -230,7 +269,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
* if tag != -1, then this looks like an error in the template.
*/
if (tag != -1) {
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_BAD_TEMPLATE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE);
goto err;
}
@@ -238,25 +277,26 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
goto auxerr;
if (*pval) {
/* Free up and zero CHOICE value if initialised */
- i = asn1_get_choice_selector(pval, it);
+ i = ossl_asn1_get_choice_selector(pval, it);
if ((i >= 0) && (i < it->tcount)) {
tt = it->templates + i;
- pchptr = asn1_get_field_ptr(pval, tt);
- asn1_template_free(pchptr, tt);
- asn1_set_choice_selector(pval, -1, it);
+ pchptr = ossl_asn1_get_field_ptr(pval, tt);
+ ossl_asn1_template_free(pchptr, tt);
+ ossl_asn1_set_choice_selector(pval, -1, it);
}
- } else if (!ASN1_item_ex_new(pval, it)) {
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR);
+ } else if (!ossl_asn1_item_ex_new_intern(pval, it, libctx, propq)) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
goto err;
}
/* CHOICE type, try each possibility in turn */
p = *in;
for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
- pchptr = asn1_get_field_ptr(pval, tt);
+ pchptr = ossl_asn1_get_field_ptr(pval, tt);
/*
* We mark field as OPTIONAL so its absence can be recognised.
*/
- ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx, depth);
+ ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx, depth,
+ libctx, propq);
/* If field not present, try the next one */
if (ret == -1)
continue;
@@ -267,9 +307,9 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
* Must be an ASN1 parsing error.
* Free up any partial choice value
*/
- asn1_template_free(pchptr, tt);
+ ossl_asn1_template_free(pchptr, tt);
errtt = tt;
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
goto err;
}
@@ -281,11 +321,11 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
ASN1_item_ex_free(pval, it);
return -1;
}
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_NO_MATCHING_CHOICE_TYPE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE);
goto err;
}
- asn1_set_choice_selector(pval, i, it);
+ ossl_asn1_set_choice_selector(pval, i, it);
if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
goto auxerr;
@@ -306,7 +346,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst,
&p, len, tag, aclass, opt, ctx);
if (!ret) {
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
goto err;
} else if (ret == -1)
return -1;
@@ -318,12 +358,13 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
else
seq_nolen = seq_eoc;
if (!cst) {
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_SEQUENCE_NOT_CONSTRUCTED);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_SEQUENCE_NOT_CONSTRUCTED);
goto err;
}
- if (!*pval && !ASN1_item_ex_new(pval, it)) {
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR);
+ if (*pval == NULL
+ && !ossl_asn1_item_ex_new_intern(pval, it, libctx, propq)) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
goto err;
}
@@ -335,11 +376,11 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
if (tt->flags & ASN1_TFLG_ADB_MASK) {
const ASN1_TEMPLATE *seqtt;
ASN1_VALUE **pseqval;
- seqtt = asn1_do_adb(pval, tt, 0);
+ seqtt = ossl_asn1_do_adb(*pval, tt, 0);
if (seqtt == NULL)
continue;
- pseqval = asn1_get_field_ptr(pval, seqtt);
- asn1_template_free(pseqval, seqtt);
+ pseqval = ossl_asn1_get_field_ptr(pval, seqtt);
+ ossl_asn1_template_free(pseqval, seqtt);
}
}
@@ -347,22 +388,21 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
const ASN1_TEMPLATE *seqtt;
ASN1_VALUE **pseqval;
- seqtt = asn1_do_adb(pval, tt, 1);
+ seqtt = ossl_asn1_do_adb(*pval, tt, 1);
if (seqtt == NULL)
goto err;
- pseqval = asn1_get_field_ptr(pval, seqtt);
+ pseqval = ossl_asn1_get_field_ptr(pval, seqtt);
/* Have we ran out of data? */
if (!len)
break;
q = p;
if (asn1_check_eoc(&p, len)) {
if (!seq_eoc) {
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_UNEXPECTED_EOC);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNEXPECTED_EOC);
goto err;
}
len -= p - q;
seq_eoc = 0;
- q = p;
break;
}
/*
@@ -380,7 +420,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
*/
ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx,
- depth);
+ depth, libctx, propq);
if (!ret) {
errtt = seqtt;
goto err;
@@ -388,7 +428,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
/*
* OPTIONAL component absent. Free and zero the field.
*/
- asn1_template_free(pseqval, seqtt);
+ ossl_asn1_template_free(pseqval, seqtt);
continue;
}
/* Update length */
@@ -397,12 +437,12 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
/* Check for EOC if expecting one */
if (seq_eoc && !asn1_check_eoc(&p, len)) {
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MISSING_EOC);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_EOC);
goto err;
}
/* Check all data read */
if (!seq_nolen && len) {
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_SEQUENCE_LENGTH_MISMATCH);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_SEQUENCE_LENGTH_MISMATCH);
goto err;
}
@@ -413,21 +453,21 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
*/
for (; i < it->tcount; tt++, i++) {
const ASN1_TEMPLATE *seqtt;
- seqtt = asn1_do_adb(pval, tt, 1);
+ seqtt = ossl_asn1_do_adb(*pval, tt, 1);
if (seqtt == NULL)
goto err;
if (seqtt->flags & ASN1_TFLG_OPTIONAL) {
ASN1_VALUE **pseqval;
- pseqval = asn1_get_field_ptr(pval, seqtt);
- asn1_template_free(pseqval, seqtt);
+ pseqval = ossl_asn1_get_field_ptr(pval, seqtt);
+ ossl_asn1_template_free(pseqval, seqtt);
} else {
errtt = seqtt;
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_FIELD_MISSING);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_FIELD_MISSING);
goto err;
}
}
/* Save encoding */
- if (!asn1_enc_save(pval, *in, p - *in, it))
+ if (!ossl_asn1_enc_save(pval, *in, p - *in, it))
goto auxerr;
if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
goto auxerr;
@@ -438,7 +478,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
return 0;
}
auxerr:
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_AUX_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_AUX_ERROR);
err:
if (errtt)
ERR_add_error_data(4, "Field=", errtt->field_name,
@@ -456,7 +496,8 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
static int asn1_template_ex_d2i(ASN1_VALUE **val,
const unsigned char **in, long inlen,
const ASN1_TEMPLATE *tt, char opt,
- ASN1_TLC *ctx, int depth)
+ ASN1_TLC *ctx, int depth,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
int flags, aclass;
int ret;
@@ -481,19 +522,19 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
&p, inlen, tt->tag, aclass, opt, ctx);
q = p;
if (!ret) {
- ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
return 0;
} else if (ret == -1)
return -1;
if (!cst) {
- ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I,
- ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED);
return 0;
}
/* We've found the field so it can't be OPTIONAL now */
- ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx, depth);
+ ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx, depth, libctx,
+ propq);
if (!ret) {
- ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
return 0;
}
/* We read the field in OK so update length */
@@ -501,7 +542,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
if (exp_eoc) {
/* If NDEF we must have an EOC here */
if (!asn1_check_eoc(&p, len)) {
- ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ASN1_R_MISSING_EOC);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_EOC);
goto err;
}
} else {
@@ -509,13 +550,13 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
* Otherwise we must hit the EXPLICIT tag end or its an error
*/
if (len) {
- ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I,
- ASN1_R_EXPLICIT_LENGTH_MISMATCH);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_EXPLICIT_LENGTH_MISMATCH);
goto err;
}
}
} else
- return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx, depth);
+ return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx, depth,
+ libctx, propq);
*in = p;
return 1;
@@ -527,7 +568,8 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
static int asn1_template_noexp_d2i(ASN1_VALUE **val,
const unsigned char **in, long len,
const ASN1_TEMPLATE *tt, char opt,
- ASN1_TLC *ctx, int depth)
+ ASN1_TLC *ctx, int depth,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
int flags, aclass;
int ret;
@@ -539,7 +581,6 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
aclass = flags & ASN1_TFLG_TAG_CLASS;
p = *in;
- q = p;
/*
* If field is embedded then val needs fixing so it is a pointer to
@@ -569,11 +610,11 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL,
&p, len, sktag, skaclass, opt, ctx);
if (!ret) {
- ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
return 0;
} else if (ret == -1)
return -1;
- if (!*val)
+ if (*val == NULL)
*val = (ASN1_VALUE *)sk_ASN1_VALUE_new_null();
else {
/*
@@ -587,8 +628,8 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
}
}
- if (!*val) {
- ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_MALLOC_FAILURE);
+ if (*val == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -599,8 +640,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
/* See if EOC found */
if (asn1_check_eoc(&p, len)) {
if (!sk_eoc) {
- ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
- ASN1_R_UNEXPECTED_EOC);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNEXPECTED_EOC);
goto err;
}
len -= p - q;
@@ -608,42 +648,41 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
break;
}
skfield = NULL;
- if (!asn1_item_embed_d2i(&skfield, &p, len,
+ if (asn1_item_embed_d2i(&skfield, &p, len,
ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx,
- depth)) {
- ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
- ERR_R_NESTED_ASN1_ERROR);
+ depth, libctx, propq) <= 0) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
/* |skfield| may be partially allocated despite failure. */
ASN1_item_free(skfield, ASN1_ITEM_ptr(tt->item));
goto err;
}
len -= p - q;
if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) {
- ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
ASN1_item_free(skfield, ASN1_ITEM_ptr(tt->item));
goto err;
}
}
if (sk_eoc) {
- ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ASN1_R_MISSING_EOC);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_EOC);
goto err;
}
} else if (flags & ASN1_TFLG_IMPTAG) {
/* IMPLICIT tagging */
ret = asn1_item_embed_d2i(val, &p, len,
ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt,
- ctx, depth);
+ ctx, depth, libctx, propq);
if (!ret) {
- ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
goto err;
} else if (ret == -1)
return -1;
} else {
/* Nothing special */
ret = asn1_item_embed_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item),
- -1, 0, opt, ctx, depth);
+ -1, 0, opt, ctx, depth, libctx, propq);
if (!ret) {
- ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
goto err;
} else if (ret == -1)
return -1;
@@ -668,8 +707,9 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
BUF_MEM buf = { 0, NULL, 0, 0 };
const unsigned char *cont = NULL;
long len;
- if (!pval) {
- ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_NULL);
+
+ if (pval == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NULL);
return 0; /* Should never happen */
}
@@ -683,19 +723,18 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
/* If type is ANY need to figure out type from tag */
unsigned char oclass;
if (tag >= 0) {
- ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_TAGGED_ANY);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_TAGGED_ANY);
return 0;
}
if (opt) {
- ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE,
- ASN1_R_ILLEGAL_OPTIONAL_ANY);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_OPTIONAL_ANY);
return 0;
}
p = *in;
ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL,
&p, inlen, -1, 0, 0, ctx);
if (!ret) {
- ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
return 0;
}
if (oclass != V_ASN1_UNIVERSAL)
@@ -710,7 +749,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst,
&p, inlen, tag, aclass, opt, ctx);
if (!ret) {
- ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
return 0;
} else if (ret == -1)
return -1;
@@ -727,8 +766,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
}
/* SEQUENCE and SET must be constructed */
else if (!cst) {
- ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE,
- ASN1_R_TYPE_NOT_CONSTRUCTED);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED);
return 0;
}
@@ -746,7 +784,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN
|| utype == V_ASN1_OBJECT || utype == V_ASN1_INTEGER
|| utype == V_ASN1_ENUMERATED) {
- ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_TYPE_NOT_PRIMITIVE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TYPE_NOT_PRIMITIVE);
return 0;
}
@@ -764,7 +802,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
len = buf.length;
/* Append a final null to string */
if (!BUF_MEM_grow_clean(&buf, len + 1)) {
- ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
buf.data[len] = 0;
@@ -805,7 +843,7 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
return pf->prim_c2i(pval, cont, len, utype, free_cont, it);
/* If ANY type clear type and set pointer to internal value */
if (it->utype == V_ASN1_ANY) {
- if (!*pval) {
+ if (*pval == NULL) {
typ = ASN1_TYPE_new();
if (typ == NULL)
goto err;
@@ -820,13 +858,13 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
}
switch (utype) {
case V_ASN1_OBJECT:
- if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len))
+ if (!ossl_c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len))
goto err;
break;
case V_ASN1_NULL:
if (len) {
- ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_NULL_IS_WRONG_LENGTH);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_NULL_IS_WRONG_LENGTH);
goto err;
}
*pval = (ASN1_VALUE *)1;
@@ -834,7 +872,7 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
case V_ASN1_BOOLEAN:
if (len != 1) {
- ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_BOOLEAN_IS_WRONG_LENGTH);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH);
goto err;
} else {
ASN1_BOOLEAN *tbool;
@@ -844,14 +882,14 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
break;
case V_ASN1_BIT_STRING:
- if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len))
+ if (!ossl_c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len))
goto err;
break;
case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED:
tint = (ASN1_INTEGER **)pval;
- if (!c2i_ASN1_INTEGER(tint, &cont, len))
+ if (!ossl_c2i_ASN1_INTEGER(tint, &cont, len))
goto err;
/* Fixup type to match the expected form */
(*tint)->type = utype | ((*tint)->type & V_ASN1_NEG);
@@ -876,19 +914,18 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
case V_ASN1_SEQUENCE:
default:
if (utype == V_ASN1_BMPSTRING && (len & 1)) {
- ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_BMPSTRING_IS_WRONG_LENGTH);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_BMPSTRING_IS_WRONG_LENGTH);
goto err;
}
if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) {
- ASN1err(ASN1_F_ASN1_EX_C2I,
- ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
goto err;
}
/* All based on ASN1_STRING and handled the same */
- if (!*pval) {
+ if (*pval == NULL) {
stmp = ASN1_STRING_type_new(utype);
if (stmp == NULL) {
- ASN1err(ASN1_F_ASN1_EX_C2I, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
*pval = (ASN1_VALUE *)stmp;
@@ -904,7 +941,7 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
*free_cont = 0;
} else {
if (!ASN1_STRING_set(stmp, cont, len)) {
- ASN1err(ASN1_F_ASN1_EX_C2I, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
ASN1_STRING_free(stmp);
*pval = NULL;
goto err;
@@ -962,12 +999,12 @@ static int asn1_find_end(const unsigned char **in, long len, char inf)
/* Just read in a header: only care about the length */
if (!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len,
-1, 0, 0, NULL)) {
- ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
return 0;
}
if (inf) {
if (expected_eoc == UINT32_MAX) {
- ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
return 0;
}
expected_eoc++;
@@ -977,7 +1014,7 @@ static int asn1_find_end(const unsigned char **in, long len, char inf)
len -= p - q;
}
if (expected_eoc) {
- ASN1err(ASN1_F_ASN1_FIND_END, ASN1_R_MISSING_EOC);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_EOC);
return 0;
}
*in = p;
@@ -1024,7 +1061,7 @@ static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
* EOC is illegal outside indefinite length constructed form
*/
if (!inf) {
- ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_UNEXPECTED_EOC);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNEXPECTED_EOC);
return 0;
}
inf = 0;
@@ -1033,14 +1070,14 @@ static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p,
len, tag, aclass, 0, NULL)) {
- ASN1err(ASN1_F_ASN1_COLLECT, ERR_R_NESTED_ASN1_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
return 0;
}
/* If indefinite length constructed update max length */
if (cst) {
if (depth >= ASN1_MAX_STRING_NEST) {
- ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_NESTED_ASN1_STRING);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_NESTED_ASN1_STRING);
return 0;
}
if (!asn1_collect(buf, &p, plen, ininf, tag, aclass, depth + 1))
@@ -1050,7 +1087,7 @@ static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
len -= p - q;
}
if (inf) {
- ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_MISSING_EOC);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_EOC);
return 0;
}
*in = p;
@@ -1063,7 +1100,7 @@ static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen)
if (buf) {
len = buf->length;
if (!BUF_MEM_grow_clean(buf, len + plen)) {
- ASN1err(ASN1_F_COLLECT_DATA, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(buf->data + len, *p, plen);
@@ -1077,10 +1114,11 @@ static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen)
static int asn1_check_eoc(const unsigned char **in, long len)
{
const unsigned char *p;
+
if (len < 2)
return 0;
p = *in;
- if (!p[0] && !p[1]) {
+ if (p[0] == '\0' && p[1] == '\0') {
*in += 2;
return 1;
}
@@ -1106,7 +1144,11 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
p = *in;
q = p;
- if (ctx && ctx->valid) {
+ if (len <= 0) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL);
+ goto err;
+ }
+ if (ctx != NULL && ctx->valid) {
i = ctx->ret;
plen = ctx->plen;
pclass = ctx->pclass;
@@ -1114,7 +1156,7 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
p += ctx->hdrlen;
} else {
i = ASN1_get_object(&p, &plen, &ptag, &pclass, len);
- if (ctx) {
+ if (ctx != NULL) {
ctx->ret = i;
ctx->plen = plen;
ctx->pclass = pclass;
@@ -1125,29 +1167,26 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
* If definite length, and no error, length + header can't exceed
* total amount of data available.
*/
- if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) {
- ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_TOO_LONG);
- asn1_tlc_clear(ctx);
- return 0;
+ if ((i & 0x81) == 0 && (plen + ctx->hdrlen) > len) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG);
+ goto err;
}
}
}
- if (i & 0x80) {
- ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_BAD_OBJECT_HEADER);
- asn1_tlc_clear(ctx);
- return 0;
+ if ((i & 0x80) != 0) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_OBJECT_HEADER);
+ goto err;
}
if (exptag >= 0) {
- if ((exptag != ptag) || (expclass != pclass)) {
+ if (exptag != ptag || expclass != pclass) {
/*
* If type is OPTIONAL, not an error: indicate missing type.
*/
- if (opt)
+ if (opt != 0)
return -1;
- asn1_tlc_clear(ctx);
- ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_WRONG_TAG);
- return 0;
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_TAG);
+ goto err;
}
/*
* We have a tag and class match: assume we are going to do something
@@ -1156,24 +1195,28 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
asn1_tlc_clear(ctx);
}
- if (i & 1)
+ if ((i & 1) != 0)
plen = len - (p - q);
- if (inf)
+ if (inf != NULL)
*inf = i & 1;
- if (cst)
+ if (cst != NULL)
*cst = i & V_ASN1_CONSTRUCTED;
- if (olen)
+ if (olen != NULL)
*olen = plen;
- if (oclass)
+ if (oclass != NULL)
*oclass = pclass;
- if (otag)
+ if (otag != NULL)
*otag = ptag;
*in = p;
return 1;
+
+ err:
+ asn1_tlc_clear(ctx);
+ return 0;
}
diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c
index bcc96337bca4..3ea18b0280dd 100644
--- a/crypto/asn1/tasn_enc.c
+++ b/crypto/asn1/tasn_enc.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -16,16 +16,17 @@
#include "crypto/asn1.h"
#include "asn1_local.h"
-static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
+static int asn1_i2d_ex_primitive(const ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass);
-static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
+static int asn1_set_seq_out(STACK_OF(const_ASN1_VALUE) *sk,
+ unsigned char **out,
int skcontlen, const ASN1_ITEM *item,
int do_sort, int iclass);
-static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
+static int asn1_template_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
const ASN1_TEMPLATE *tt, int tag, int aclass);
-static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
+static int asn1_item_flags_i2d(const ASN1_VALUE *val, unsigned char **out,
const ASN1_ITEM *it, int flags);
-static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
+static int asn1_ex_i2c(const ASN1_VALUE **pval, unsigned char *cout, int *putype,
const ASN1_ITEM *it);
/*
@@ -33,13 +34,13 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
* indefinite length constructed encoding, where appropriate
*/
-int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
+int ASN1_item_ndef_i2d(const ASN1_VALUE *val, unsigned char **out,
const ASN1_ITEM *it)
{
return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
}
-int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
+int ASN1_item_i2d(const ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
{
return asn1_item_flags_i2d(val, out, it, 0);
}
@@ -51,10 +52,10 @@ int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
* allocated and populated with the encoding.
*/
-static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
+static int asn1_item_flags_i2d(const ASN1_VALUE *val, unsigned char **out,
const ASN1_ITEM *it, int flags)
{
- if (out && !*out) {
+ if (out != NULL && *out == NULL) {
unsigned char *p, *buf;
int len;
@@ -62,7 +63,7 @@ static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
if (len <= 0)
return len;
if ((buf = OPENSSL_malloc(len)) == NULL) {
- ASN1err(ASN1_F_ASN1_ITEM_FLAGS_I2D, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
p = buf;
@@ -79,20 +80,22 @@ static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
* performs the normal item handling: it can be used in external types.
*/
-int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
+int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass)
{
const ASN1_TEMPLATE *tt = NULL;
int i, seqcontlen, seqlen, ndef = 1;
const ASN1_EXTERN_FUNCS *ef;
const ASN1_AUX *aux = it->funcs;
- ASN1_aux_cb *asn1_cb = 0;
+ ASN1_aux_const_cb *asn1_cb = NULL;
- if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
+ if ((it->itype != ASN1_ITYPE_PRIMITIVE) && *pval == NULL)
return 0;
- if (aux && aux->asn1_cb)
- asn1_cb = aux->asn1_cb;
+ if (aux != NULL) {
+ asn1_cb = ((aux->flags & ASN1_AFLG_CONST_CB) != 0) ? aux->asn1_const_cb
+ : (ASN1_aux_const_cb *)aux->asn1_cb; /* backward compatibility */
+ }
switch (it->itype) {
@@ -108,7 +111,7 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
* if tag != -1, then this looks like an error in the template.
*/
if (tag != -1) {
- ASN1err(ASN1_F_ASN1_ITEM_EX_I2D, ASN1_R_BAD_TEMPLATE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE);
return -1;
}
return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
@@ -119,17 +122,17 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
* if tag != -1, then this looks like an error in the template.
*/
if (tag != -1) {
- ASN1err(ASN1_F_ASN1_ITEM_EX_I2D, ASN1_R_BAD_TEMPLATE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE);
return -1;
}
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
return 0;
- i = asn1_get_choice_selector(pval, it);
+ i = ossl_asn1_get_choice_selector_const(pval, it);
if ((i >= 0) && (i < it->tcount)) {
- ASN1_VALUE **pchval;
+ const ASN1_VALUE **pchval;
const ASN1_TEMPLATE *chtt;
chtt = it->templates + i;
- pchval = asn1_get_field_ptr(pval, chtt);
+ pchval = ossl_asn1_get_const_field_ptr(pval, chtt);
return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass);
}
/* Fixme: error condition if selector out of range */
@@ -149,7 +152,7 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
/* fall through */
case ASN1_ITYPE_SEQUENCE:
- i = asn1_enc_restore(&seqcontlen, out, pval, it);
+ i = ossl_asn1_enc_restore(&seqcontlen, out, pval, it);
/* An error occurred */
if (i < 0)
return 0;
@@ -170,12 +173,12 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
/* First work out sequence content length */
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
const ASN1_TEMPLATE *seqtt;
- ASN1_VALUE **pseqval;
+ const ASN1_VALUE **pseqval;
int tmplen;
- seqtt = asn1_do_adb(pval, tt, 1);
+ seqtt = ossl_asn1_do_adb(*pval, tt, 1);
if (!seqtt)
return 0;
- pseqval = asn1_get_field_ptr(pval, seqtt);
+ pseqval = ossl_asn1_get_const_field_ptr(pval, seqtt);
tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass);
if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen))
return -1;
@@ -189,11 +192,11 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
const ASN1_TEMPLATE *seqtt;
- ASN1_VALUE **pseqval;
- seqtt = asn1_do_adb(pval, tt, 1);
+ const ASN1_VALUE **pseqval;
+ seqtt = ossl_asn1_do_adb(*pval, tt, 1);
if (!seqtt)
return 0;
- pseqval = asn1_get_field_ptr(pval, seqtt);
+ pseqval = ossl_asn1_get_const_field_ptr(pval, seqtt);
/* FIXME: check for errors in enhanced version */
asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
}
@@ -210,12 +213,12 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
return 0;
}
-static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
+static int asn1_template_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
const ASN1_TEMPLATE *tt, int tag, int iclass)
{
- int i, ret, flags, ttag, tclass, ndef;
- ASN1_VALUE *tval;
- flags = tt->flags;
+ const int flags = tt->flags;
+ int i, ret, ttag, tclass, ndef, len;
+ const ASN1_VALUE *tval;
/*
* If field is embedded then val needs fixing so it is a pointer to
@@ -266,12 +269,12 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
if (flags & ASN1_TFLG_SK_MASK) {
/* SET OF, SEQUENCE OF */
- STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
+ STACK_OF(const_ASN1_VALUE) *sk = (STACK_OF(const_ASN1_VALUE) *)*pval;
int isset, sktag, skaclass;
int skcontlen, sklen;
- ASN1_VALUE *skitem;
+ const ASN1_VALUE *skitem;
- if (!*pval)
+ if (*pval == NULL)
return 0;
if (flags & ASN1_TFLG_SET_OF) {
@@ -299,14 +302,17 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
/* Determine total length of items */
skcontlen = 0;
- for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
- int tmplen;
- skitem = sk_ASN1_VALUE_value(sk, i);
- tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
- -1, iclass);
- if (tmplen == -1 || (skcontlen > INT_MAX - tmplen))
+ for (i = 0; i < sk_const_ASN1_VALUE_num(sk); i++) {
+ skitem = sk_const_ASN1_VALUE_value(sk, i);
+ len = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
+ -1, iclass);
+ if (len == -1 || (skcontlen > INT_MAX - len))
return -1;
- skcontlen += tmplen;
+ if (len == 0 && (tt->flags & ASN1_TFLG_OPTIONAL) == 0) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT);
+ return -1;
+ }
+ skcontlen += len;
}
sklen = ASN1_object_size(ndef, skcontlen, sktag);
if (sklen == -1)
@@ -342,8 +348,13 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
/* EXPLICIT tagging */
/* Find length of tagged item */
i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass);
- if (!i)
+ if (i == 0) {
+ if ((tt->flags & ASN1_TFLG_OPTIONAL) == 0) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT);
+ return -1;
+ }
return 0;
+ }
/* Find length of EXPLICIT tag */
ret = ASN1_object_size(ndef, i, ttag);
if (out && ret != -1) {
@@ -357,9 +368,13 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
}
/* Either normal or IMPLICIT tagging: combine class and flags */
- return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
- ttag, tclass | iclass);
-
+ len = ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
+ ttag, tclass | iclass);
+ if (len == 0 && (tt->flags & ASN1_TFLG_OPTIONAL) == 0) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT);
+ return -1;
+ }
+ return len;
}
/* Temporary structure used to hold DER encoding of items for SET OF */
@@ -367,7 +382,7 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
typedef struct {
unsigned char *data;
int length;
- ASN1_VALUE *field;
+ const ASN1_VALUE *field;
} DER_ENC;
static int der_cmp(const void *a, const void *b)
@@ -383,34 +398,38 @@ static int der_cmp(const void *a, const void *b)
/* Output the content octets of SET OF or SEQUENCE OF */
-static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
+static int asn1_set_seq_out(STACK_OF(const_ASN1_VALUE) *sk,
+ unsigned char **out,
int skcontlen, const ASN1_ITEM *item,
int do_sort, int iclass)
{
- int i;
- ASN1_VALUE *skitem;
+ int i, ret = 0;
+ const ASN1_VALUE *skitem;
unsigned char *tmpdat = NULL, *p = NULL;
DER_ENC *derlst = NULL, *tder;
+
if (do_sort) {
/* Don't need to sort less than 2 items */
- if (sk_ASN1_VALUE_num(sk) < 2)
+ if (sk_const_ASN1_VALUE_num(sk) < 2)
do_sort = 0;
else {
- derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
+ derlst = OPENSSL_malloc(sk_const_ASN1_VALUE_num(sk)
* sizeof(*derlst));
- if (derlst == NULL)
+ if (derlst == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
+ }
tmpdat = OPENSSL_malloc(skcontlen);
if (tmpdat == NULL) {
- OPENSSL_free(derlst);
- return 0;
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
+ goto err;
}
}
}
/* If not sorting just output each item */
if (!do_sort) {
- for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
- skitem = sk_ASN1_VALUE_value(sk, i);
+ for (i = 0; i < sk_const_ASN1_VALUE_num(sk); i++) {
+ skitem = sk_const_ASN1_VALUE_value(sk, i);
ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
}
return 1;
@@ -418,33 +437,35 @@ static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
p = tmpdat;
/* Doing sort: build up a list of each member's DER encoding */
- for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
- skitem = sk_ASN1_VALUE_value(sk, i);
+ for (i = 0, tder = derlst; i < sk_const_ASN1_VALUE_num(sk); i++, tder++) {
+ skitem = sk_const_ASN1_VALUE_value(sk, i);
tder->data = p;
tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
tder->field = skitem;
}
/* Now sort them */
- qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
+ qsort(derlst, sk_const_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
/* Output sorted DER encoding */
p = *out;
- for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
+ for (i = 0, tder = derlst; i < sk_const_ASN1_VALUE_num(sk); i++, tder++) {
memcpy(p, tder->data, tder->length);
p += tder->length;
}
*out = p;
/* If do_sort is 2 then reorder the STACK */
if (do_sort == 2) {
- for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
- (void)sk_ASN1_VALUE_set(sk, i, tder->field);
+ for (i = 0, tder = derlst; i < sk_const_ASN1_VALUE_num(sk); i++, tder++)
+ (void)sk_const_ASN1_VALUE_set(sk, i, tder->field);
}
+ ret = 1;
+err:
OPENSSL_free(derlst);
OPENSSL_free(tmpdat);
- return 1;
+ return ret;
}
-static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
+static int asn1_i2d_ex_primitive(const ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass)
{
int len;
@@ -504,7 +525,7 @@ static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
/* Produce content octets from a structure */
-static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
+static int asn1_ex_i2c(const ASN1_VALUE **pval, unsigned char *cout, int *putype,
const ASN1_ITEM *it)
{
ASN1_BOOLEAN *tbool = NULL;
@@ -522,7 +543,7 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
/* Should type be omitted? */
if ((it->itype != ASN1_ITYPE_PRIMITIVE)
|| (it->utype != V_ASN1_BOOLEAN)) {
- if (!*pval)
+ if (*pval == NULL)
return -1;
}
@@ -537,7 +558,7 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
typ = (ASN1_TYPE *)*pval;
utype = typ->type;
*putype = utype;
- pval = &typ->value.asn1_value;
+ pval = (const ASN1_VALUE **)&typ->value.asn1_value; /* actually is const */
} else
utype = *putype;
@@ -574,15 +595,15 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
break;
case V_ASN1_BIT_STRING:
- return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
- cout ? &cout : NULL);
+ return ossl_i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
+ cout ? &cout : NULL);
case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED:
/*
* These are all have the same content format as ASN1_INTEGER
*/
- return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
+ return ossl_i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
case V_ASN1_OCTET_STRING:
case V_ASN1_NUMERICSTRING:
diff --git a/crypto/asn1/tasn_fre.c b/crypto/asn1/tasn_fre.c
index 2916bef7863a..13aa6a728e2c 100644
--- a/crypto/asn1/tasn_fre.c
+++ b/crypto/asn1/tasn_fre.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -17,15 +17,15 @@
void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
{
- asn1_item_embed_free(&val, it, 0);
+ ossl_asn1_item_embed_free(&val, it, 0);
}
void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
- asn1_item_embed_free(pval, it, 0);
+ ossl_asn1_item_embed_free(pval, it, 0);
}
-void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
+void ossl_asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
{
const ASN1_TEMPLATE *tt = NULL, *seqtt;
const ASN1_EXTERN_FUNCS *ef;
@@ -33,9 +33,9 @@ void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
ASN1_aux_cb *asn1_cb;
int i;
- if (!pval)
+ if (pval == NULL)
return;
- if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
+ if ((it->itype != ASN1_ITYPE_PRIMITIVE) && *pval == NULL)
return;
if (aux && aux->asn1_cb)
asn1_cb = aux->asn1_cb;
@@ -46,13 +46,13 @@ void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
case ASN1_ITYPE_PRIMITIVE:
if (it->templates)
- asn1_template_free(pval, it->templates);
+ ossl_asn1_template_free(pval, it->templates);
else
- asn1_primitive_free(pval, it, embed);
+ ossl_asn1_primitive_free(pval, it, embed);
break;
case ASN1_ITYPE_MSTRING:
- asn1_primitive_free(pval, it, embed);
+ ossl_asn1_primitive_free(pval, it, embed);
break;
case ASN1_ITYPE_CHOICE:
@@ -61,13 +61,13 @@ void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
if (i == 2)
return;
}
- i = asn1_get_choice_selector(pval, it);
+ i = ossl_asn1_get_choice_selector(pval, it);
if ((i >= 0) && (i < it->tcount)) {
ASN1_VALUE **pchval;
tt = it->templates + i;
- pchval = asn1_get_field_ptr(pval, tt);
- asn1_template_free(pchval, tt);
+ pchval = ossl_asn1_get_field_ptr(pval, tt);
+ ossl_asn1_template_free(pchval, tt);
}
if (asn1_cb)
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
@@ -85,14 +85,14 @@ void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
case ASN1_ITYPE_NDEF_SEQUENCE:
case ASN1_ITYPE_SEQUENCE:
- if (asn1_do_lock(pval, -1, it) != 0) /* if error or ref-counter > 0 */
+ if (ossl_asn1_do_lock(pval, -1, it) != 0) /* if error or ref-counter > 0 */
return;
if (asn1_cb) {
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
if (i == 2)
return;
}
- asn1_enc_free(pval, it);
+ ossl_asn1_enc_free(pval, it);
/*
* If we free up as normal we will invalidate any ANY DEFINED BY
* field and we won't be able to determine the type of the field it
@@ -103,11 +103,11 @@ void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
ASN1_VALUE **pseqval;
tt--;
- seqtt = asn1_do_adb(pval, tt, 0);
+ seqtt = ossl_asn1_do_adb(*pval, tt, 0);
if (!seqtt)
continue;
- pseqval = asn1_get_field_ptr(pval, seqtt);
- asn1_template_free(pseqval, seqtt);
+ pseqval = ossl_asn1_get_field_ptr(pval, seqtt);
+ ossl_asn1_template_free(pseqval, seqtt);
}
if (asn1_cb)
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
@@ -119,7 +119,7 @@ void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
}
}
-void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
+void ossl_asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
int embed = tt->flags & ASN1_TFLG_EMBED;
ASN1_VALUE *tval;
@@ -134,16 +134,16 @@ void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
ASN1_VALUE *vtmp = sk_ASN1_VALUE_value(sk, i);
- asn1_item_embed_free(&vtmp, ASN1_ITEM_ptr(tt->item), embed);
+ ossl_asn1_item_embed_free(&vtmp, ASN1_ITEM_ptr(tt->item), embed);
}
sk_ASN1_VALUE_free(sk);
*pval = NULL;
} else {
- asn1_item_embed_free(pval, ASN1_ITEM_ptr(tt->item), embed);
+ ossl_asn1_item_embed_free(pval, ASN1_ITEM_ptr(tt->item), embed);
}
}
-void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
+void ossl_asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
{
int utype;
@@ -168,15 +168,15 @@ void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
utype = typ->type;
pval = &typ->value.asn1_value;
- if (!*pval)
+ if (*pval == NULL)
return;
} else if (it->itype == ASN1_ITYPE_MSTRING) {
utype = -1;
- if (!*pval)
+ if (*pval == NULL)
return;
} else {
utype = it->utype;
- if ((utype != V_ASN1_BOOLEAN) && !*pval)
+ if ((utype != V_ASN1_BOOLEAN) && *pval == NULL)
return;
}
@@ -196,12 +196,12 @@ void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
break;
case V_ASN1_ANY:
- asn1_primitive_free(pval, NULL, 0);
+ ossl_asn1_primitive_free(pval, NULL, 0);
OPENSSL_free(*pval);
break;
default:
- asn1_string_embed_free((ASN1_STRING *)*pval, embed);
+ ossl_asn1_string_embed_free((ASN1_STRING *)*pval, embed);
break;
}
*pval = NULL;
diff --git a/crypto/asn1/tasn_new.c b/crypto/asn1/tasn_new.c
index 287f2af33b58..4b624bbdd4e5 100644
--- a/crypto/asn1/tasn_new.c
+++ b/crypto/asn1/tasn_new.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -16,11 +16,13 @@
#include "asn1_local.h"
static int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
- int embed);
+ int embed, OSSL_LIB_CTX *libctx,
+ const char *propq);
static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
int embed);
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
-static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
+ OSSL_LIB_CTX *libctx, const char *propq);
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
@@ -32,14 +34,31 @@ ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
return NULL;
}
+ASN1_VALUE *ASN1_item_new_ex(const ASN1_ITEM *it, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ ASN1_VALUE *ret = NULL;
+ if (asn1_item_embed_new(&ret, it, 0, libctx, propq) > 0)
+ return ret;
+ return NULL;
+}
+
/* Allocate an ASN1 structure */
+
+int ossl_asn1_item_ex_new_intern(ASN1_VALUE **pval, const ASN1_ITEM *it,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ return asn1_item_embed_new(pval, it, 0, libctx, propq);
+}
+
int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
- return asn1_item_embed_new(pval, it, 0);
+ return asn1_item_embed_new(pval, it, 0, NULL, NULL);
}
-int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
+int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
const ASN1_TEMPLATE *tt = NULL;
const ASN1_EXTERN_FUNCS *ef;
@@ -52,23 +71,24 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
else
asn1_cb = 0;
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
- OPENSSL_mem_debug_push(it->sname ? it->sname : "asn1_item_embed_new");
-#endif
-
switch (it->itype) {
case ASN1_ITYPE_EXTERN:
ef = it->funcs;
- if (ef && ef->asn1_ex_new) {
- if (!ef->asn1_ex_new(pval, it))
- goto memerr;
+ if (ef != NULL) {
+ if (ef->asn1_ex_new_ex != NULL) {
+ if (!ef->asn1_ex_new_ex(pval, it, libctx, propq))
+ goto memerr;
+ } else if (ef->asn1_ex_new != NULL) {
+ if (!ef->asn1_ex_new(pval, it))
+ goto memerr;
+ }
}
break;
case ASN1_ITYPE_PRIMITIVE:
if (it->templates) {
- if (!asn1_template_new(pval, it->templates))
+ if (!asn1_template_new(pval, it->templates, libctx, propq))
goto memerr;
} else if (!asn1_primitive_new(pval, it, embed))
goto memerr;
@@ -85,9 +105,6 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
if (!i)
goto auxerr;
if (i == 2) {
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
- OPENSSL_mem_debug_pop();
-#endif
return 1;
}
}
@@ -98,7 +115,7 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
if (*pval == NULL)
goto memerr;
}
- asn1_set_choice_selector(pval, -1, it);
+ ossl_asn1_set_choice_selector(pval, -1, it);
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
goto auxerr2;
break;
@@ -110,9 +127,6 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
if (!i)
goto auxerr;
if (i == 2) {
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
- OPENSSL_mem_debug_pop();
-#endif
return 1;
}
}
@@ -124,44 +138,35 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
goto memerr;
}
/* 0 : init. lock */
- if (asn1_do_lock(pval, 0, it) < 0) {
+ if (ossl_asn1_do_lock(pval, 0, it) < 0) {
if (!embed) {
OPENSSL_free(*pval);
*pval = NULL;
}
goto memerr;
}
- asn1_enc_init(pval, it);
+ ossl_asn1_enc_init(pval, it);
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
- pseqval = asn1_get_field_ptr(pval, tt);
- if (!asn1_template_new(pseqval, tt))
+ pseqval = ossl_asn1_get_field_ptr(pval, tt);
+ if (!asn1_template_new(pseqval, tt, libctx, propq))
goto memerr2;
}
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
goto auxerr2;
break;
}
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
- OPENSSL_mem_debug_pop();
-#endif
return 1;
memerr2:
- asn1_item_embed_free(pval, it, embed);
+ ossl_asn1_item_embed_free(pval, it, embed);
memerr:
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ERR_R_MALLOC_FAILURE);
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
- OPENSSL_mem_debug_pop();
-#endif
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
auxerr2:
- asn1_item_embed_free(pval, it, embed);
+ ossl_asn1_item_embed_free(pval, it, embed);
auxerr:
- ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ASN1_R_AUX_ERROR);
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
- OPENSSL_mem_debug_pop();
-#endif
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_AUX_ERROR);
return 0;
}
@@ -199,7 +204,8 @@ static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
}
}
-static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
+static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
int embed = tt->flags & ASN1_TFLG_EMBED;
@@ -219,16 +225,12 @@ static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
*pval = NULL;
return 1;
}
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
- OPENSSL_mem_debug_push(tt->field_name
- ? tt->field_name : "asn1_template_new");
-#endif
/* If SET OF or SEQUENCE OF, its a STACK */
if (tt->flags & ASN1_TFLG_SK_MASK) {
STACK_OF(ASN1_VALUE) *skval;
skval = sk_ASN1_VALUE_new_null();
if (!skval) {
- ASN1err(ASN1_F_ASN1_TEMPLATE_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
ret = 0;
goto done;
}
@@ -237,11 +239,8 @@ static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
goto done;
}
/* Otherwise pass it back to the item routine */
- ret = asn1_item_embed_new(pval, it, embed);
+ ret = asn1_item_embed_new(pval, it, embed, libctx, propq);
done:
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
- OPENSSL_mem_debug_pop();
-#endif
return ret;
}
@@ -300,7 +299,7 @@ static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
case V_ASN1_ANY:
if ((typ = OPENSSL_malloc(sizeof(*typ))) == NULL) {
- ASN1err(ASN1_F_ASN1_PRIMITIVE_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
typ->value.ptr = NULL;
diff --git a/crypto/asn1/tasn_prn.c b/crypto/asn1/tasn_prn.c
index 56d5ea0f39e3..7d8618e26c22 100644
--- a/crypto/asn1/tasn_prn.c
+++ b/crypto/asn1/tasn_prn.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -38,7 +38,7 @@ ASN1_PCTX *ASN1_PCTX_new(void)
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- ASN1err(ASN1_F_ASN1_PCTX_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
return ret;
@@ -101,15 +101,15 @@ void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags)
/* Main print routines */
-static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
+static int asn1_item_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent,
const ASN1_ITEM *it,
const char *fname, const char *sname,
int nohdr, const ASN1_PCTX *pctx);
-static int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
+static int asn1_template_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent,
const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx);
-static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
+static int asn1_primitive_print(BIO *out, const ASN1_VALUE **fld,
const ASN1_ITEM *it, int indent,
const char *fname, const char *sname,
const ASN1_PCTX *pctx);
@@ -118,7 +118,7 @@ static int asn1_print_fsname(BIO *out, int indent,
const char *fname, const char *sname,
const ASN1_PCTX *pctx);
-int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent,
+int ASN1_item_print(BIO *out, const ASN1_VALUE *ifld, int indent,
const ASN1_ITEM *it, const ASN1_PCTX *pctx)
{
const char *sname;
@@ -131,25 +131,25 @@ int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent,
return asn1_item_print_ctx(out, &ifld, indent, it, NULL, sname, 0, pctx);
}
-static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
+static int asn1_item_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent,
const ASN1_ITEM *it,
const char *fname, const char *sname,
int nohdr, const ASN1_PCTX *pctx)
{
const ASN1_TEMPLATE *tt;
const ASN1_EXTERN_FUNCS *ef;
- ASN1_VALUE **tmpfld;
+ const ASN1_VALUE **tmpfld;
const ASN1_AUX *aux = it->funcs;
- ASN1_aux_cb *asn1_cb;
+ ASN1_aux_const_cb *asn1_cb = NULL;
ASN1_PRINT_ARG parg;
int i;
- if (aux && aux->asn1_cb) {
+ if (aux != NULL) {
parg.out = out;
parg.indent = indent;
parg.pctx = pctx;
- asn1_cb = aux->asn1_cb;
- } else
- asn1_cb = 0;
+ asn1_cb = ((aux->flags & ASN1_AFLG_CONST_CB) != 0) ? aux->asn1_const_cb
+ : (ASN1_aux_const_cb *)aux->asn1_cb; /* backward compatibility */
+ }
if (((it->itype != ASN1_ITYPE_PRIMITIVE)
|| (it->utype != V_ASN1_BOOLEAN)) && *fld == NULL) {
@@ -195,7 +195,7 @@ static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
case ASN1_ITYPE_CHOICE:
/* CHOICE type, get selector */
- i = asn1_get_choice_selector(fld, it);
+ i = ossl_asn1_get_choice_selector_const(fld, it);
/* This should never happen... */
if ((i < 0) || (i >= it->tcount)) {
if (BIO_printf(out, "ERROR: selector [%d] invalid\n", i) <= 0)
@@ -203,7 +203,7 @@ static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
return 1;
}
tt = it->templates + i;
- tmpfld = asn1_get_field_ptr(fld, tt);
+ tmpfld = ossl_asn1_get_const_field_ptr(fld, tt);
if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
return 0;
break;
@@ -233,10 +233,10 @@ static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
/* Print each field entry */
for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
const ASN1_TEMPLATE *seqtt;
- seqtt = asn1_do_adb(fld, tt, 1);
+ seqtt = ossl_asn1_do_adb(*fld, tt, 1);
if (!seqtt)
return 0;
- tmpfld = asn1_get_field_ptr(fld, seqtt);
+ tmpfld = ossl_asn1_get_const_field_ptr(fld, seqtt);
if (!asn1_template_print_ctx(out, tmpfld,
indent + 2, seqtt, pctx))
return 0;
@@ -261,12 +261,12 @@ static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
return 1;
}
-static int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
+static int asn1_template_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent,
const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
{
int i, flags;
const char *sname, *fname;
- ASN1_VALUE *tfld;
+ const ASN1_VALUE *tfld;
flags = tt->flags;
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
sname = ASN1_ITEM_ptr(tt->item)->sname;
@@ -282,14 +282,14 @@ static int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
* a pointer to a field.
*/
if (flags & ASN1_TFLG_EMBED) {
- tfld = (ASN1_VALUE *)fld;
+ tfld = (const ASN1_VALUE *)fld;
fld = &tfld;
}
if (flags & ASN1_TFLG_SK_MASK) {
char *tname;
- ASN1_VALUE *skitem;
- STACK_OF(ASN1_VALUE) *stack;
+ const ASN1_VALUE *skitem;
+ STACK_OF(const_ASN1_VALUE) *stack;
/* SET OF, SEQUENCE OF */
if (fname) {
@@ -304,12 +304,12 @@ static int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
} else if (BIO_printf(out, "%*s%s:\n", indent, "", fname) <= 0)
return 0;
}
- stack = (STACK_OF(ASN1_VALUE) *)*fld;
- for (i = 0; i < sk_ASN1_VALUE_num(stack); i++) {
+ stack = (STACK_OF(const_ASN1_VALUE) *)*fld;
+ for (i = 0; i < sk_const_ASN1_VALUE_num(stack); i++) {
if ((i > 0) && (BIO_puts(out, "\n") <= 0))
return 0;
- skitem = sk_ASN1_VALUE_value(stack, i);
+ skitem = sk_const_ASN1_VALUE_value(stack, i);
if (!asn1_item_print_ctx(out, &skitem, indent + 2,
ASN1_ITEM_ptr(tt->item), NULL, NULL, 1,
pctx))
@@ -430,7 +430,7 @@ static int asn1_print_obstring(BIO *out, const ASN1_STRING *str, int indent)
return 1;
}
-static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
+static int asn1_primitive_print(BIO *out, const ASN1_VALUE **fld,
const ASN1_ITEM *it, int indent,
const char *fname, const char *sname,
const ASN1_PCTX *pctx)
@@ -456,9 +456,9 @@ static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
str = (ASN1_STRING *)*fld;
}
if (utype == V_ASN1_ANY) {
- ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
+ const ASN1_TYPE *atype = (const ASN1_TYPE *)*fld;
utype = atype->type;
- fld = &atype->value.asn1_value;
+ fld = (const ASN1_VALUE **)&atype->value.asn1_value; /* actually is const */
str = (ASN1_STRING *)*fld;
if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
pname = NULL;
diff --git a/crypto/asn1/tasn_scn.c b/crypto/asn1/tasn_scn.c
index f0f218ae8bbe..bde697ee9925 100644
--- a/crypto/asn1/tasn_scn.c
+++ b/crypto/asn1/tasn_scn.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -27,7 +27,7 @@ ASN1_SCTX *ASN1_SCTX_new(int (*scan_cb) (ASN1_SCTX *ctx))
ASN1_SCTX *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- ASN1err(ASN1_F_ASN1_SCTX_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->scan_cb = scan_cb;
diff --git a/crypto/asn1/tasn_typ.c b/crypto/asn1/tasn_typ.c
index 98d987901413..8095e32370fc 100644
--- a/crypto/asn1/tasn_typ.c
+++ b/crypto/asn1/tasn_typ.c
@@ -1,7 +1,7 @@
/*
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -80,5 +80,5 @@ ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, ASN1_SET_ANY, ASN1_ANY)
ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY)
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY)
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY)
diff --git a/crypto/asn1/tasn_utl.c b/crypto/asn1/tasn_utl.c
index a448685e19a9..e5f25d88df69 100644
--- a/crypto/asn1/tasn_utl.c
+++ b/crypto/asn1/tasn_utl.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -26,9 +26,18 @@
* Given an ASN1_ITEM CHOICE type return the selector value
*/
-int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it)
+int ossl_asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
int *sel = offset2ptr(*pval, it->utype);
+
+ return *sel;
+}
+
+int ossl_asn1_get_choice_selector_const(const ASN1_VALUE **pval,
+ const ASN1_ITEM *it)
+{
+ int *sel = offset2ptr(*pval, it->utype);
+
return *sel;
}
@@ -36,10 +45,11 @@ int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it)
* Given an ASN1_ITEM CHOICE type set the selector value, return old value.
*/
-int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
- const ASN1_ITEM *it)
+int ossl_asn1_set_choice_selector(ASN1_VALUE **pval, int value,
+ const ASN1_ITEM *it)
{
int *sel, ret;
+
sel = offset2ptr(*pval, it->utype);
ret = *sel;
*sel = value;
@@ -55,7 +65,7 @@ int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
* It returns -1 on initialisation error.
* Used by ASN1_SEQUENCE construct of X509, X509_REQ, X509_CRL objects
*/
-int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
+int ossl_asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
{
const ASN1_AUX *aux;
CRYPTO_REF_COUNT *lck;
@@ -66,7 +76,7 @@ int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
&& (it->itype != ASN1_ITYPE_NDEF_SEQUENCE))
return 0;
aux = it->funcs;
- if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT))
+ if (aux == NULL || (aux->flags & ASN1_AFLG_REFCOUNT) == 0)
return 0;
lck = offset2ptr(*pval, aux->ref_offset);
lock = offset2ptr(*pval, aux->ref_lock);
@@ -76,7 +86,7 @@ int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
*lck = ret = 1;
*lock = CRYPTO_THREAD_lock_new();
if (*lock == NULL) {
- ASN1err(ASN1_F_ASN1_DO_LOCK, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
break;
@@ -87,9 +97,7 @@ int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
case -1:
if (!CRYPTO_DOWN_REF(lck, &ret, *lock))
return -1; /* failed */
-#ifdef REF_PRINT
- fprintf(stderr, "%p:%4d:%s\n", it, ret, it->sname);
-#endif
+ REF_PRINT_EX(it->sname, ret, (void *)it);
REF_ASSERT_ISNT(ret < 0);
if (ret == 0) {
CRYPTO_THREAD_lock_free(*lock);
@@ -104,30 +112,44 @@ int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
const ASN1_AUX *aux;
- if (!pval || !*pval)
+
+ if (pval == NULL || *pval == NULL)
+ return NULL;
+ aux = it->funcs;
+ if (aux == NULL || (aux->flags & ASN1_AFLG_ENCODING) == 0)
+ return NULL;
+ return offset2ptr(*pval, aux->enc_offset);
+}
+
+static const ASN1_ENCODING *asn1_get_const_enc_ptr(const ASN1_VALUE **pval,
+ const ASN1_ITEM *it)
+{
+ const ASN1_AUX *aux;
+
+ if (pval == NULL || *pval == NULL)
return NULL;
aux = it->funcs;
- if (!aux || !(aux->flags & ASN1_AFLG_ENCODING))
+ if (aux == NULL || (aux->flags & ASN1_AFLG_ENCODING) == 0)
return NULL;
return offset2ptr(*pval, aux->enc_offset);
}
-void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it)
+void ossl_asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
- ASN1_ENCODING *enc;
- enc = asn1_get_enc_ptr(pval, it);
- if (enc) {
+ ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it);
+
+ if (enc != NULL) {
enc->enc = NULL;
enc->len = 0;
enc->modified = 1;
}
}
-void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+void ossl_asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
- ASN1_ENCODING *enc;
- enc = asn1_get_enc_ptr(pval, it);
- if (enc) {
+ ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it);
+
+ if (enc != NULL) {
OPENSSL_free(enc->enc);
enc->enc = NULL;
enc->len = 0;
@@ -135,17 +157,19 @@ void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
}
}
-int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
- const ASN1_ITEM *it)
+int ossl_asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
+ const ASN1_ITEM *it)
{
- ASN1_ENCODING *enc;
- enc = asn1_get_enc_ptr(pval, it);
- if (!enc)
+ ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it);
+
+ if (enc == NULL)
return 1;
OPENSSL_free(enc->enc);
+ if (inlen <= 0)
+ return 0;
if ((enc->enc = OPENSSL_malloc(inlen)) == NULL) {
- ASN1err(ASN1_F_ASN1_ENC_SAVE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(enc->enc, in, inlen);
@@ -155,27 +179,27 @@ int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
return 1;
}
-int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
- const ASN1_ITEM *it)
+int ossl_asn1_enc_restore(int *len, unsigned char **out, const ASN1_VALUE **pval,
+ const ASN1_ITEM *it)
{
- ASN1_ENCODING *enc;
- enc = asn1_get_enc_ptr(pval, it);
- if (!enc || enc->modified)
+ const ASN1_ENCODING *enc = asn1_get_const_enc_ptr(pval, it);
+
+ if (enc == NULL || enc->modified)
return 0;
if (out) {
memcpy(*out, enc->enc, enc->len);
*out += enc->len;
}
- if (len)
+ if (len != NULL)
*len = enc->len;
return 1;
}
/* Given an ASN1_TEMPLATE get a pointer to a field */
-ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
+ASN1_VALUE **ossl_asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
- ASN1_VALUE **pvaltmp;
- pvaltmp = offset2ptr(*pval, tt->offset);
+ ASN1_VALUE **pvaltmp = offset2ptr(*pval, tt->offset);
+
/*
* NOTE for BOOLEAN types the field is just a plain int so we can't
* return int **, so settle for (int *).
@@ -183,31 +207,40 @@ ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
return pvaltmp;
}
+/* Given an ASN1_TEMPLATE get a const pointer to a field */
+const ASN1_VALUE **ossl_asn1_get_const_field_ptr(const ASN1_VALUE **pval,
+ const ASN1_TEMPLATE *tt)
+{
+ return offset2ptr(*pval, tt->offset);
+}
+
/*
* Handle ANY DEFINED BY template, find the selector, look up the relevant
* ASN1_TEMPLATE in the table and return it.
*/
-const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
- int nullerr)
+const ASN1_TEMPLATE *ossl_asn1_do_adb(const ASN1_VALUE *val,
+ const ASN1_TEMPLATE *tt,
+ int nullerr)
{
const ASN1_ADB *adb;
const ASN1_ADB_TABLE *atbl;
long selector;
- ASN1_VALUE **sfld;
+ const ASN1_VALUE **sfld;
int i;
- if (!(tt->flags & ASN1_TFLG_ADB_MASK))
+
+ if ((tt->flags & ASN1_TFLG_ADB_MASK) == 0)
return tt;
/* Else ANY DEFINED BY ... get the table */
adb = ASN1_ADB_ptr(tt->item);
/* Get the selector field */
- sfld = offset2ptr(*pval, adb->offset);
+ sfld = offset2ptr(val, adb->offset);
/* Check if NULL */
if (*sfld == NULL) {
- if (!adb->null_tt)
+ if (adb->null_tt == NULL)
goto err;
return adb->null_tt;
}
@@ -216,14 +249,14 @@ const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
* Convert type to a long: NB: don't check for NID_undef here because it
* might be a legitimate value in the table
*/
- if (tt->flags & ASN1_TFLG_ADB_OID)
+ if ((tt->flags & ASN1_TFLG_ADB_OID) != 0)
selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld);
else
selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld);
/* Let application callback translate value */
if (adb->adb_cb != NULL && adb->adb_cb(&selector) == 0) {
- ASN1err(ASN1_F_ASN1_DO_ADB, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
return NULL;
}
@@ -248,6 +281,6 @@ const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
err:
/* FIXME: should log the value or OID of unsupported type */
if (nullerr)
- ASN1err(ASN1_F_ASN1_DO_ADB, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
return NULL;
}
diff --git a/crypto/asn1/tbl_standard.h b/crypto/asn1/tbl_standard.h
index 777a73448246..3e8fe81eebdd 100644
--- a/crypto/asn1/tbl_standard.h
+++ b/crypto/asn1/tbl_standard.h
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -56,6 +56,7 @@ static const ASN1_STRING_TABLE tbl_standard[] = {
{NID_SNILS, 1, 11, B_ASN1_NUMERICSTRING, STABLE_NO_MASK},
{NID_countryCode3c, 3, 3, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
{NID_countryCode3n, 3, 3, B_ASN1_NUMERICSTRING, STABLE_NO_MASK},
- {NID_dnsName, 0, -1, B_ASN1_UTF8STRING, STABLE_NO_MASK}
+ {NID_dnsName, 0, -1, B_ASN1_UTF8STRING, STABLE_NO_MASK},
+ {NID_id_on_SmtpUTF8Mailbox, 1, ub_email_address, B_ASN1_UTF8STRING, STABLE_NO_MASK}
};
diff --git a/crypto/asn1/x_algor.c b/crypto/asn1/x_algor.c
index c9a8f1e9d1d4..c0a5f76803ee 100644
--- a/crypto/asn1/x_algor.c
+++ b/crypto/asn1/x_algor.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1998-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,6 +11,8 @@
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
+#include <openssl/err.h>
+#include "crypto/asn1.h"
#include "crypto/evp.h"
ASN1_SEQUENCE(X509_ALGOR) = {
@@ -78,7 +80,7 @@ void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md)
else
param_type = V_ASN1_NULL;
- X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
+ X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_get_type(md)), param_type, NULL);
}
@@ -96,7 +98,7 @@ int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b)
int X509_ALGOR_copy(X509_ALGOR *dest, const X509_ALGOR *src)
{
if (src == NULL || dest == NULL)
- return 0;
+ return 0;
if (dest->algorithm)
ASN1_OBJECT_free(dest->algorithm);
@@ -108,9 +110,9 @@ int X509_ALGOR_copy(X509_ALGOR *dest, const X509_ALGOR *src)
if (src->algorithm)
if ((dest->algorithm = OBJ_dup(src->algorithm)) == NULL)
- return 0;
+ return 0;
- if (src->parameter) {
+ if (src->parameter != NULL) {
dest->parameter = ASN1_TYPE_new();
if (dest->parameter == NULL)
return 0;
@@ -118,9 +120,71 @@ int X509_ALGOR_copy(X509_ALGOR *dest, const X509_ALGOR *src)
/* Assuming this is also correct for a BOOL.
* set does copy as a side effect.
*/
- if (ASN1_TYPE_set1(dest->parameter,
- src->parameter->type, src->parameter->value.ptr) == 0)
+ if (ASN1_TYPE_set1(dest->parameter, src->parameter->type,
+ src->parameter->value.ptr) == 0)
return 0;
}
+
+ return 1;
+}
+
+/* allocate and set algorithm ID from EVP_MD, default SHA1 */
+int ossl_x509_algor_new_from_md(X509_ALGOR **palg, const EVP_MD *md)
+{
+ /* Default is SHA1 so no need to create it - still success */
+ if (md == NULL || EVP_MD_is_a(md, "SHA1"))
+ return 1;
+ *palg = X509_ALGOR_new();
+ if (*palg == NULL)
+ return 0;
+ X509_ALGOR_set_md(*palg, md);
return 1;
}
+
+/* convert algorithm ID to EVP_MD, default SHA1 */
+const EVP_MD *ossl_x509_algor_get_md(X509_ALGOR *alg)
+{
+ const EVP_MD *md;
+
+ if (alg == NULL)
+ return EVP_sha1();
+ md = EVP_get_digestbyobj(alg->algorithm);
+ if (md == NULL)
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_DIGEST);
+ return md;
+}
+
+X509_ALGOR *ossl_x509_algor_mgf1_decode(X509_ALGOR *alg)
+{
+ if (OBJ_obj2nid(alg->algorithm) != NID_mgf1)
+ return NULL;
+ return ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR),
+ alg->parameter);
+}
+
+/* Allocate and set MGF1 algorithm ID from EVP_MD */
+int ossl_x509_algor_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md)
+{
+ X509_ALGOR *algtmp = NULL;
+ ASN1_STRING *stmp = NULL;
+
+ *palg = NULL;
+ if (mgf1md == NULL || EVP_MD_is_a(mgf1md, "SHA1"))
+ return 1;
+ /* need to embed algorithm ID inside another */
+ if (!ossl_x509_algor_new_from_md(&algtmp, mgf1md))
+ goto err;
+ if (ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp) == NULL)
+ goto err;
+ *palg = X509_ALGOR_new();
+ if (*palg == NULL)
+ goto err;
+ X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
+ stmp = NULL;
+ err:
+ ASN1_STRING_free(stmp);
+ X509_ALGOR_free(algtmp);
+ if (*palg != NULL)
+ return 1;
+ return 0;
+}
diff --git a/crypto/asn1/x_bignum.c b/crypto/asn1/x_bignum.c
index c6b3accd3a10..3ae58a49f0b2 100644
--- a/crypto/asn1/x_bignum.c
+++ b/crypto/asn1/x_bignum.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -25,13 +25,13 @@ static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static int bn_secure_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
-static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
+static int bn_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype,
const ASN1_ITEM *it);
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it);
static int bn_secure_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it);
-static int bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
+static int bn_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it,
int indent, const ASN1_PCTX *pctx);
static ASN1_PRIMITIVE_FUNCS bignum_pf = {
@@ -91,7 +91,7 @@ static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
*pval = NULL;
}
-static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
+static int bn_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype,
const ASN1_ITEM *it)
{
BIGNUM *bn;
@@ -146,7 +146,7 @@ static int bn_secure_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
return ret;
}
-static int bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
+static int bn_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it,
int indent, const ASN1_PCTX *pctx)
{
if (!BN_print(out, *(BIGNUM **)pval))
diff --git a/crypto/asn1/x_info.c b/crypto/asn1/x_info.c
index 8d99f07c6361..f8bc4789884e 100644
--- a/crypto/asn1/x_info.c
+++ b/crypto/asn1/x_info.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -19,7 +19,7 @@ X509_INFO *X509_INFO_new(void)
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- ASN1err(ASN1_F_X509_INFO_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
diff --git a/crypto/asn1/x_int64.c b/crypto/asn1/x_int64.c
index 96c1a259e1fe..eb78c7e36723 100644
--- a/crypto/asn1/x_int64.c
+++ b/crypto/asn1/x_int64.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -29,7 +29,7 @@
static int uint64_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
if ((*pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint64_t))) == NULL) {
- ASN1err(ASN1_F_UINT64_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
@@ -46,8 +46,8 @@ static void uint64_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
**(uint64_t **)pval = 0;
}
-static int uint64_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
- const ASN1_ITEM *it)
+static int uint64_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype,
+ const ASN1_ITEM *it)
{
uint64_t utmp;
int neg = 0;
@@ -62,16 +62,16 @@ static int uint64_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
return -1;
if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
&& (int64_t)utmp < 0) {
- /* i2c_uint64_int() assumes positive values */
+ /* ossl_i2c_uint64_int() assumes positive values */
utmp = 0 - utmp;
neg = 1;
}
- return i2c_uint64_int(cont, utmp, neg);
+ return ossl_i2c_uint64_int(cont, utmp, neg);
}
static int uint64_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
- int utype, char *free_cont, const ASN1_ITEM *it)
+ int utype, char *free_cont, const ASN1_ITEM *it)
{
uint64_t utmp = 0;
char *cp;
@@ -91,19 +91,19 @@ static int uint64_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
if (len == 0)
goto long_compat;
- if (!c2i_uint64_int(&utmp, &neg, &cont, len))
+ if (!ossl_c2i_uint64_int(&utmp, &neg, &cont, len))
return 0;
if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) {
- ASN1err(ASN1_F_UINT64_C2I, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
return 0;
}
if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
&& !neg && utmp > INT64_MAX) {
- ASN1err(ASN1_F_UINT64_C2I, ASN1_R_TOO_LARGE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
return 0;
}
if (neg)
- /* c2i_uint64_int() returns positive values */
+ /* ossl_c2i_uint64_int() returns positive values */
utmp = 0 - utmp;
long_compat:
@@ -111,7 +111,7 @@ static int uint64_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
return 1;
}
-static int uint64_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
+static int uint64_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it,
int indent, const ASN1_PCTX *pctx)
{
if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED)
@@ -124,7 +124,7 @@ static int uint64_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
static int uint32_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
if ((*pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint32_t))) == NULL) {
- ASN1err(ASN1_F_UINT32_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
@@ -141,8 +141,8 @@ static void uint32_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
**(uint32_t **)pval = 0;
}
-static int uint32_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
- const ASN1_ITEM *it)
+static int uint32_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype,
+ const ASN1_ITEM *it)
{
uint32_t utmp;
int neg = 0;
@@ -157,12 +157,12 @@ static int uint32_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
return -1;
if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
&& (int32_t)utmp < 0) {
- /* i2c_uint64_int() assumes positive values */
+ /* ossl_i2c_uint64_int() assumes positive values */
utmp = 0 - utmp;
neg = 1;
}
- return i2c_uint64_int(cont, (uint64_t)utmp, neg);
+ return ossl_i2c_uint64_int(cont, (uint64_t)utmp, neg);
}
/*
@@ -173,7 +173,7 @@ static int uint32_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
#define ABS_INT32_MIN ((uint32_t)INT32_MAX + 1)
static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
- int utype, char *free_cont, const ASN1_ITEM *it)
+ int utype, char *free_cont, const ASN1_ITEM *it)
{
uint64_t utmp = 0;
uint32_t utmp2 = 0;
@@ -194,22 +194,22 @@ static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
if (len == 0)
goto long_compat;
- if (!c2i_uint64_int(&utmp, &neg, &cont, len))
+ if (!ossl_c2i_uint64_int(&utmp, &neg, &cont, len))
return 0;
if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) {
- ASN1err(ASN1_F_UINT32_C2I, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
return 0;
}
if (neg) {
if (utmp > ABS_INT32_MIN) {
- ASN1err(ASN1_F_UINT32_C2I, ASN1_R_TOO_SMALL);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL);
return 0;
}
utmp = 0 - utmp;
} else {
if (((it->size & INTxx_FLAG_SIGNED) != 0 && utmp > INT32_MAX)
|| ((it->size & INTxx_FLAG_SIGNED) == 0 && utmp > UINT32_MAX)) {
- ASN1err(ASN1_F_UINT32_C2I, ASN1_R_TOO_LARGE);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
return 0;
}
}
@@ -220,7 +220,7 @@ static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
return 1;
}
-static int uint32_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
+static int uint32_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it,
int indent, const ASN1_PCTX *pctx)
{
if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED)
diff --git a/crypto/asn1/x_long.c b/crypto/asn1/x_long.c
index bf9371ef55aa..0685780f08a0 100644
--- a/crypto/asn1/x_long.c
+++ b/crypto/asn1/x_long.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,10 +11,6 @@
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
-#if !(OPENSSL_API_COMPAT < 0x10200000L)
-NON_EMPTY_TRANSLATION_UNIT
-#else
-
#define COPY_SIZE(a, b) (sizeof(a) < sizeof(b) ? sizeof(a) : sizeof(b))
/*
@@ -25,11 +21,11 @@ NON_EMPTY_TRANSLATION_UNIT
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
-static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
+static int long_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype,
const ASN1_ITEM *it);
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it);
-static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
+static int long_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it,
int indent, const ASN1_PCTX *pctx);
static ASN1_PRIMITIVE_FUNCS long_pf = {
@@ -86,7 +82,7 @@ static int num_bits_ulong(unsigned long value)
return (int)ret;
}
-static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
+static int long_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype,
const ASN1_ITEM *it)
{
long ltmp;
@@ -156,7 +152,7 @@ static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
}
}
if (len > (int)sizeof(long)) {
- ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
return 0;
}
@@ -167,7 +163,7 @@ static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
else
sign = 0;
} else if (((sign ^ cont[0]) & 0x80) == 0) { /* same sign bit? */
- ASN1err(ASN1_F_LONG_C2I, ASN1_R_ILLEGAL_PADDING);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_PADDING);
return 0;
}
utmp = 0;
@@ -177,20 +173,20 @@ static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
}
ltmp = (long)utmp;
if (ltmp < 0) {
- ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
return 0;
}
if (sign)
ltmp = -ltmp - 1;
if (ltmp == it->size) {
- ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
return 0;
}
memcpy(pval, &ltmp, COPY_SIZE(*pval, ltmp));
return 1;
}
-static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
+static int long_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it,
int indent, const ASN1_PCTX *pctx)
{
long l;
@@ -198,4 +194,3 @@ static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
memcpy(&l, pval, COPY_SIZE(*pval, l));
return BIO_printf(out, "%ld\n", l);
}
-#endif
diff --git a/crypto/asn1/x_pkey.c b/crypto/asn1/x_pkey.c
index 593049f0f26e..b63c7c6489f4 100644
--- a/crypto/asn1/x_pkey.c
+++ b/crypto/asn1/x_pkey.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -29,7 +29,7 @@ X509_PKEY *X509_PKEY_new(void)
return ret;
err:
X509_PKEY_free(ret);
- ASN1err(ASN1_F_X509_PKEY_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
diff --git a/crypto/asn1/x_sig.c b/crypto/asn1/x_sig.c
index fb24e240cba8..759a9566531e 100644
--- a/crypto/asn1/x_sig.c
+++ b/crypto/asn1/x_sig.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/asn1/x_spki.c b/crypto/asn1/x_spki.c
index 0d72a3f3a9d2..2d7de66eb79c 100644
--- a/crypto/asn1/x_spki.c
+++ b/crypto/asn1/x_spki.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/asn1/x_val.c b/crypto/asn1/x_val.c
index d1f1d3bff989..a4e57cbcc714 100644
--- a/crypto/asn1/x_val.c
+++ b/crypto/asn1/x_val.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/asn1_dsa.c b/crypto/asn1_dsa.c
new file mode 100644
index 000000000000..0782fe7c2a54
--- /dev/null
+++ b/crypto/asn1_dsa.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * A simple ASN.1 DER encoder/decoder for DSA-Sig-Value and ECDSA-Sig-Value.
+ *
+ * DSA-Sig-Value ::= SEQUENCE {
+ * r INTEGER,
+ * s INTEGER
+ * }
+ *
+ * ECDSA-Sig-Value ::= SEQUENCE {
+ * r INTEGER,
+ * s INTEGER
+ * }
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/bn.h>
+#include "crypto/asn1_dsa.h"
+#include "internal/packet.h"
+
+#define ID_SEQUENCE 0x30
+#define ID_INTEGER 0x02
+
+/*
+ * Outputs the encoding of the length octets for a DER value with a content
+ * length of cont_len bytes to pkt. The maximum supported content length is
+ * 65535 (0xffff) bytes.
+ *
+ * Returns 1 on success or 0 on error.
+ */
+int ossl_encode_der_length(WPACKET *pkt, size_t cont_len)
+{
+ if (cont_len > 0xffff)
+ return 0; /* Too large for supported length encodings */
+
+ if (cont_len > 0xff) {
+ if (!WPACKET_put_bytes_u8(pkt, 0x82)
+ || !WPACKET_put_bytes_u16(pkt, cont_len))
+ return 0;
+ } else {
+ if (cont_len > 0x7f
+ && !WPACKET_put_bytes_u8(pkt, 0x81))
+ return 0;
+ if (!WPACKET_put_bytes_u8(pkt, cont_len))
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Outputs the DER encoding of a positive ASN.1 INTEGER to pkt.
+ *
+ * Results in an error if n is negative or too large.
+ *
+ * Returns 1 on success or 0 on error.
+ */
+int ossl_encode_der_integer(WPACKET *pkt, const BIGNUM *n)
+{
+ unsigned char *bnbytes;
+ size_t cont_len;
+
+ if (BN_is_negative(n))
+ return 0;
+
+ /*
+ * Calculate the ASN.1 INTEGER DER content length for n.
+ * This is the number of whole bytes required to represent n (i.e. rounded
+ * down), plus one.
+ * If n is zero then the content is a single zero byte (length = 1).
+ * If the number of bits of n is a multiple of 8 then an extra zero padding
+ * byte is included to ensure that the value is still treated as positive
+ * in the INTEGER two's complement representation.
+ */
+ cont_len = BN_num_bits(n) / 8 + 1;
+
+ if (!WPACKET_start_sub_packet(pkt)
+ || !WPACKET_put_bytes_u8(pkt, ID_INTEGER)
+ || !ossl_encode_der_length(pkt, cont_len)
+ || !WPACKET_allocate_bytes(pkt, cont_len, &bnbytes)
+ || !WPACKET_close(pkt))
+ return 0;
+
+ if (bnbytes != NULL
+ && BN_bn2binpad(n, bnbytes, (int)cont_len) != (int)cont_len)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Outputs the DER encoding of a DSA-Sig-Value or ECDSA-Sig-Value to pkt. pkt
+ * may be initialised with a NULL buffer which enables pkt to be used to
+ * calculate how many bytes would be needed.
+ *
+ * Returns 1 on success or 0 on error.
+ */
+int ossl_encode_der_dsa_sig(WPACKET *pkt, const BIGNUM *r, const BIGNUM *s)
+{
+ WPACKET tmppkt, *dummypkt;
+ size_t cont_len;
+ int isnull = WPACKET_is_null_buf(pkt);
+
+ if (!WPACKET_start_sub_packet(pkt))
+ return 0;
+
+ if (!isnull) {
+ if (!WPACKET_init_null(&tmppkt, 0))
+ return 0;
+ dummypkt = &tmppkt;
+ } else {
+ /* If the input packet has a NULL buffer, we don't need a dummy packet */
+ dummypkt = pkt;
+ }
+
+ /* Calculate the content length */
+ if (!ossl_encode_der_integer(dummypkt, r)
+ || !ossl_encode_der_integer(dummypkt, s)
+ || !WPACKET_get_length(dummypkt, &cont_len)
+ || (!isnull && !WPACKET_finish(dummypkt))) {
+ if (!isnull)
+ WPACKET_cleanup(dummypkt);
+ return 0;
+ }
+
+ /* Add the tag and length bytes */
+ if (!WPACKET_put_bytes_u8(pkt, ID_SEQUENCE)
+ || !ossl_encode_der_length(pkt, cont_len)
+ /*
+ * Really encode the integers. We already wrote to the main pkt
+ * if it had a NULL buffer, so don't do it again
+ */
+ || (!isnull && !ossl_encode_der_integer(pkt, r))
+ || (!isnull && !ossl_encode_der_integer(pkt, s))
+ || !WPACKET_close(pkt))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Decodes the DER length octets in pkt and initialises subpkt with the
+ * following bytes of that length.
+ *
+ * Returns 1 on success or 0 on failure.
+ */
+int ossl_decode_der_length(PACKET *pkt, PACKET *subpkt)
+{
+ unsigned int byte;
+
+ if (!PACKET_get_1(pkt, &byte))
+ return 0;
+
+ if (byte < 0x80)
+ return PACKET_get_sub_packet(pkt, subpkt, (size_t)byte);
+ if (byte == 0x81)
+ return PACKET_get_length_prefixed_1(pkt, subpkt);
+ if (byte == 0x82)
+ return PACKET_get_length_prefixed_2(pkt, subpkt);
+
+ /* Too large, invalid, or not DER. */
+ return 0;
+}
+
+/*
+ * Decodes a single ASN.1 INTEGER value from pkt, which must be DER encoded,
+ * and updates n with the decoded value.
+ *
+ * The BIGNUM, n, must have already been allocated by calling BN_new().
+ * pkt must not be NULL.
+ *
+ * An attempt to consume more than len bytes results in an error.
+ * Returns 1 on success or 0 on error.
+ *
+ * If the PACKET is supposed to only contain a single INTEGER value with no
+ * trailing garbage then it is up to the caller to verify that all bytes
+ * were consumed.
+ */
+int ossl_decode_der_integer(PACKET *pkt, BIGNUM *n)
+{
+ PACKET contpkt, tmppkt;
+ unsigned int tag, tmp;
+
+ /* Check we have an integer and get the content bytes */
+ if (!PACKET_get_1(pkt, &tag)
+ || tag != ID_INTEGER
+ || !ossl_decode_der_length(pkt, &contpkt))
+ return 0;
+
+ /* Peek ahead at the first bytes to check for proper encoding */
+ tmppkt = contpkt;
+ /* The INTEGER must be positive */
+ if (!PACKET_get_1(&tmppkt, &tmp)
+ || (tmp & 0x80) != 0)
+ return 0;
+ /* If there a zero padding byte the next byte must have the msb set */
+ if (PACKET_remaining(&tmppkt) > 0 && tmp == 0) {
+ if (!PACKET_get_1(&tmppkt, &tmp)
+ || (tmp & 0x80) == 0)
+ return 0;
+ }
+
+ if (BN_bin2bn(PACKET_data(&contpkt),
+ (int)PACKET_remaining(&contpkt), n) == NULL)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Decodes a single DSA-Sig-Value or ECDSA-Sig-Value from *ppin, which must be
+ * DER encoded, updates r and s with the decoded values, and increments *ppin
+ * past the data that was consumed.
+ *
+ * The BIGNUMs, r and s, must have already been allocated by calls to BN_new().
+ * ppin and *ppin must not be NULL.
+ *
+ * An attempt to consume more than len bytes results in an error.
+ * Returns the number of bytes of input consumed or 0 if an error occurs.
+ *
+ * If the buffer is supposed to only contain a single [EC]DSA-Sig-Value with no
+ * trailing garbage then it is up to the caller to verify that all bytes
+ * were consumed.
+ */
+size_t ossl_decode_der_dsa_sig(BIGNUM *r, BIGNUM *s,
+ const unsigned char **ppin, size_t len)
+{
+ size_t consumed;
+ PACKET pkt, contpkt;
+ unsigned int tag;
+
+ if (!PACKET_buf_init(&pkt, *ppin, len)
+ || !PACKET_get_1(&pkt, &tag)
+ || tag != ID_SEQUENCE
+ || !ossl_decode_der_length(&pkt, &contpkt)
+ || !ossl_decode_der_integer(&contpkt, r)
+ || !ossl_decode_der_integer(&contpkt, s)
+ || PACKET_remaining(&contpkt) != 0)
+ return 0;
+
+ consumed = PACKET_data(&pkt) - *ppin;
+ *ppin += consumed;
+ return consumed;
+}
diff --git a/crypto/async/arch/async_null.c b/crypto/async/arch/async_null.c
index 26801f873130..675c1d35bf0c 100644
--- a/crypto/async/arch/async_null.c
+++ b/crypto/async/arch/async_null.c
@@ -1,7 +1,7 @@
/*
* Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/async/arch/async_null.h b/crypto/async/arch/async_null.h
index aef40b5d9ee0..c62aba69a874 100644
--- a/crypto/async/arch/async_null.h
+++ b/crypto/async/arch/async_null.h
@@ -1,7 +1,7 @@
/*
* Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/async/arch/async_posix.c b/crypto/async/arch/async_posix.c
index 95678d4fa686..e107e09a352f 100644
--- a/crypto/async/arch/async_posix.c
+++ b/crypto/async/arch/async_posix.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -34,7 +34,9 @@ void async_local_cleanup(void)
int async_fibre_makecontext(async_fibre *fibre)
{
+#ifndef USE_SWAPCONTEXT
fibre->env_init = 0;
+#endif
if (getcontext(&fibre->fibre) == 0) {
fibre->fibre.uc_stack.ss_sp = OPENSSL_malloc(STACKSIZE);
if (fibre->fibre.uc_stack.ss_sp != NULL) {
diff --git a/crypto/async/arch/async_posix.h b/crypto/async/arch/async_posix.h
index 873c0316ddf3..a17c6b8e68af 100644
--- a/crypto/async/arch/async_posix.h
+++ b/crypto/async/arch/async_posix.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -25,17 +25,47 @@
# define ASYNC_POSIX
# define ASYNC_ARCH
+# if defined(__CET__) || defined(__ia64__)
+/*
+ * When Intel CET is enabled, makecontext will create a different
+ * shadow stack for each context. async_fibre_swapcontext cannot
+ * use _longjmp. It must call swapcontext to swap shadow stack as
+ * well as normal stack.
+ * On IA64 the register stack engine is not saved across setjmp/longjmp. Here
+ * swapcontext() performs correctly.
+ */
+# define USE_SWAPCONTEXT
+# endif
+# if defined(__aarch64__) && defined(__clang__) \
+ && defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1
+/*
+ * setjmp/longjmp don't currently work with BTI on all libc implementations
+ * when compiled by clang. This is because clang doesn't put a BTI after the
+ * call to setjmp where it returns the second time. This then fails on libc
+ * implementations - notably glibc - which use an indirect jump to there.
+ * So use the swapcontext implementation, which does work.
+ * See https://github.com/llvm/llvm-project/issues/48888.
+ */
+# define USE_SWAPCONTEXT
+# endif
# include <ucontext.h>
-# include <setjmp.h>
+# ifndef USE_SWAPCONTEXT
+# include <setjmp.h>
+# endif
typedef struct async_fibre_st {
ucontext_t fibre;
+# ifndef USE_SWAPCONTEXT
jmp_buf env;
int env_init;
+# endif
} async_fibre;
static ossl_inline int async_fibre_swapcontext(async_fibre *o, async_fibre *n, int r)
{
+# ifdef USE_SWAPCONTEXT
+ swapcontext(&o->fibre, &n->fibre);
+# else
o->env_init = 1;
if (!r || !_setjmp(o->env)) {
@@ -44,6 +74,7 @@ static ossl_inline int async_fibre_swapcontext(async_fibre *o, async_fibre *n, i
else
setcontext(&n->fibre);
}
+# endif
return 1;
}
diff --git a/crypto/async/arch/async_win.h b/crypto/async/arch/async_win.h
index 61cfdd72dec6..0fab95996e27 100644
--- a/crypto/async/arch/async_win.h
+++ b/crypto/async/arch/async_win.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -26,8 +26,16 @@ typedef struct async_fibre_st {
# define async_fibre_swapcontext(o,n,r) \
(SwitchToFiber((n)->fibre), 1)
-# define async_fibre_makecontext(c) \
+
+# if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
+# define async_fibre_makecontext(c) \
+ ((c)->fibre = CreateFiberEx(0, 0, FIBER_FLAG_FLOAT_SWITCH, \
+ async_start_func_win, 0))
+# else
+# define async_fibre_makecontext(c) \
((c)->fibre = CreateFiber(0, async_start_func_win, 0))
+# endif
+
# define async_fibre_free(f) (DeleteFiber((f)->fibre))
int async_fibre_init_dispatcher(async_fibre *fibre);
diff --git a/crypto/async/async.c b/crypto/async/async.c
index 326015c605e9..a320d455b7bb 100644
--- a/crypto/async/async.c
+++ b/crypto/async/async.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -30,16 +30,18 @@
static CRYPTO_THREAD_LOCAL ctxkey;
static CRYPTO_THREAD_LOCAL poolkey;
+static void async_delete_thread_state(void *arg);
+
static async_ctx *async_ctx_new(void)
{
async_ctx *nctx;
- if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_ASYNC))
+ if (!ossl_init_thread_start(NULL, NULL, async_delete_thread_state))
return NULL;
nctx = OPENSSL_malloc(sizeof(*nctx));
if (nctx == NULL) {
- ASYNCerr(ASYNC_F_ASYNC_CTX_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -81,7 +83,7 @@ static ASYNC_JOB *async_job_new(void)
job = OPENSSL_zalloc(sizeof(*job));
if (job == NULL) {
- ASYNCerr(ASYNC_F_ASYNC_JOB_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -136,6 +138,10 @@ static void async_release_job(ASYNC_JOB *job) {
async_pool *pool;
pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey);
+ if (pool == NULL) {
+ ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR);
+ return;
+ }
OPENSSL_free(job->funcargs);
job->funcargs = NULL;
sk_ASYNC_JOB_push(pool->jobs, job);
@@ -146,6 +152,10 @@ void async_start_func(void)
ASYNC_JOB *job;
async_ctx *ctx = async_get_ctx();
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR);
+ return;
+ }
while (1) {
/* Run the job */
job = ctx->currjob;
@@ -159,7 +169,7 @@ void async_start_func(void)
* Should not happen. Getting here will close the thread...can't do
* much about it
*/
- ASYNCerr(ASYNC_F_ASYNC_START_FUNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
+ ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
}
}
}
@@ -168,6 +178,7 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
int (*func)(void *), void *args, size_t size)
{
async_ctx *ctx;
+ OSSL_LIB_CTX *libctx;
if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL))
return ASYNC_ERR;
@@ -178,7 +189,7 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
if (ctx == NULL)
return ASYNC_ERR;
- if (*job)
+ if (*job != NULL)
ctx->currjob = *job;
for (;;) {
@@ -200,19 +211,38 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
}
if (ctx->currjob->status == ASYNC_JOB_PAUSED) {
+ if (*job == NULL)
+ return ASYNC_ERR;
ctx->currjob = *job;
+
+ /*
+ * Restore the default libctx to what it was the last time the
+ * fibre ran
+ */
+ libctx = OSSL_LIB_CTX_set0_default(ctx->currjob->libctx);
+ if (libctx == NULL) {
+ /* Failed to set the default context */
+ ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
/* Resume previous job */
if (!async_fibre_swapcontext(&ctx->dispatcher,
&ctx->currjob->fibrectx, 1)) {
- ASYNCerr(ASYNC_F_ASYNC_START_JOB,
- ASYNC_R_FAILED_TO_SWAP_CONTEXT);
+ ctx->currjob->libctx = OSSL_LIB_CTX_set0_default(libctx);
+ ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
goto err;
}
+ /*
+ * In case the fibre changed the default libctx we set it back
+ * again to what it was originally, and remember what it had
+ * been changed to.
+ */
+ ctx->currjob->libctx = OSSL_LIB_CTX_set0_default(libctx);
continue;
}
/* Should not happen */
- ASYNCerr(ASYNC_F_ASYNC_START_JOB, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR);
async_release_job(ctx->currjob);
ctx->currjob = NULL;
*job = NULL;
@@ -226,7 +256,7 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
if (args != NULL) {
ctx->currjob->funcargs = OPENSSL_malloc(size);
if (ctx->currjob->funcargs == NULL) {
- ASYNCerr(ASYNC_F_ASYNC_START_JOB, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE);
async_release_job(ctx->currjob);
ctx->currjob = NULL;
return ASYNC_ERR;
@@ -238,11 +268,17 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
ctx->currjob->func = func;
ctx->currjob->waitctx = wctx;
+ libctx = ossl_lib_ctx_get_concrete(NULL);
if (!async_fibre_swapcontext(&ctx->dispatcher,
&ctx->currjob->fibrectx, 1)) {
- ASYNCerr(ASYNC_F_ASYNC_START_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
+ ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
goto err;
}
+ /*
+ * In case the fibre changed the default libctx we set it back again
+ * to what it was, and remember what it had been changed to.
+ */
+ ctx->currjob->libctx = OSSL_LIB_CTX_set0_default(libctx);
}
err:
@@ -272,7 +308,7 @@ int ASYNC_pause_job(void)
if (!async_fibre_swapcontext(&job->fibrectx,
&ctx->dispatcher, 1)) {
- ASYNCerr(ASYNC_F_ASYNC_PAUSE_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
+ ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
return 0;
}
/* Reset counts of added and deleted fds */
@@ -285,7 +321,7 @@ static void async_empty_pool(async_pool *pool)
{
ASYNC_JOB *job;
- if (!pool || !pool->jobs)
+ if (pool == NULL || pool->jobs == NULL)
return;
do {
@@ -319,25 +355,25 @@ int ASYNC_init_thread(size_t max_size, size_t init_size)
size_t curr_size = 0;
if (init_size > max_size) {
- ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ASYNC_R_INVALID_POOL_SIZE);
+ ERR_raise(ERR_LIB_ASYNC, ASYNC_R_INVALID_POOL_SIZE);
return 0;
}
if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL))
return 0;
- if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_ASYNC))
+ if (!ossl_init_thread_start(NULL, NULL, async_delete_thread_state))
return 0;
pool = OPENSSL_zalloc(sizeof(*pool));
if (pool == NULL) {
- ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE);
return 0;
}
pool->jobs = sk_ASYNC_JOB_new_reserve(NULL, init_size);
if (pool->jobs == NULL) {
- ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE);
OPENSSL_free(pool);
return 0;
}
@@ -362,7 +398,7 @@ int ASYNC_init_thread(size_t max_size, size_t init_size)
}
pool->curr_size = curr_size;
if (!CRYPTO_THREAD_set_local(&poolkey, pool)) {
- ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ASYNC_R_FAILED_TO_SET_POOL);
+ ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SET_POOL);
goto err;
}
@@ -374,7 +410,7 @@ err:
return 0;
}
-void async_delete_thread_state(void)
+static void async_delete_thread_state(void *arg)
{
async_pool *pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey);
@@ -393,7 +429,7 @@ void ASYNC_cleanup_thread(void)
if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL))
return;
- async_delete_thread_state();
+ async_delete_thread_state(NULL);
}
ASYNC_JOB *ASYNC_get_current_job(void)
diff --git a/crypto/async/async_err.c b/crypto/async/async_err.c
index fd5527aae8c9..34db12fb969c 100644
--- a/crypto/async/async_err.c
+++ b/crypto/async/async_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,22 +10,10 @@
#include <openssl/err.h>
#include <openssl/asyncerr.h>
+#include "crypto/asyncerr.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA ASYNC_str_functs[] = {
- {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_CTX_NEW, 0), "async_ctx_new"},
- {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_INIT_THREAD, 0),
- "ASYNC_init_thread"},
- {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_JOB_NEW, 0), "async_job_new"},
- {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_PAUSE_JOB, 0), "ASYNC_pause_job"},
- {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_START_FUNC, 0), "async_start_func"},
- {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_START_JOB, 0), "ASYNC_start_job"},
- {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD, 0),
- "ASYNC_WAIT_CTX_set_wait_fd"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA ASYNC_str_reasons[] = {
{ERR_PACK(ERR_LIB_ASYNC, 0, ASYNC_R_FAILED_TO_SET_POOL),
"failed to set pool"},
@@ -39,13 +27,11 @@ static const ERR_STRING_DATA ASYNC_str_reasons[] = {
#endif
-int ERR_load_ASYNC_strings(void)
+int ossl_err_load_ASYNC_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(ASYNC_str_functs[0].error) == NULL) {
- ERR_load_strings_const(ASYNC_str_functs);
+ if (ERR_reason_error_string(ASYNC_str_reasons[0].error) == NULL)
ERR_load_strings_const(ASYNC_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/async/async_local.h b/crypto/async/async_local.h
index dd1a85e02684..c06f413cf604 100644
--- a/crypto/async/async_local.h
+++ b/crypto/async/async_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -43,6 +43,7 @@ struct async_job_st {
int ret;
int status;
ASYNC_WAIT_CTX *waitctx;
+ OSSL_LIB_CTX *libctx;
};
struct fd_lookup_st {
@@ -59,6 +60,9 @@ struct async_wait_ctx_st {
struct fd_lookup_st *fds;
size_t numadd;
size_t numdel;
+ ASYNC_callback_fn callback;
+ void *callback_arg;
+ int status;
};
DEFINE_STACK_OF(ASYNC_JOB)
diff --git a/crypto/async/async_wait.c b/crypto/async/async_wait.c
index 7723f949a67e..df7d29302182 100644
--- a/crypto/async/async_wait.c
+++ b/crypto/async/async_wait.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -48,7 +48,7 @@ int ASYNC_WAIT_CTX_set_wait_fd(ASYNC_WAIT_CTX *ctx, const void *key,
struct fd_lookup_st *fdlookup;
if ((fdlookup = OPENSSL_zalloc(sizeof(*fdlookup))) == NULL) {
- ASYNCerr(ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -182,6 +182,41 @@ int ASYNC_WAIT_CTX_clear_fd(ASYNC_WAIT_CTX *ctx, const void *key)
return 0;
}
+int ASYNC_WAIT_CTX_set_callback(ASYNC_WAIT_CTX *ctx,
+ ASYNC_callback_fn callback,
+ void *callback_arg)
+{
+ if (ctx == NULL)
+ return 0;
+
+ ctx->callback = callback;
+ ctx->callback_arg = callback_arg;
+ return 1;
+}
+
+int ASYNC_WAIT_CTX_get_callback(ASYNC_WAIT_CTX *ctx,
+ ASYNC_callback_fn *callback,
+ void **callback_arg)
+{
+ if (ctx->callback == NULL)
+ return 0;
+
+ *callback = ctx->callback;
+ *callback_arg = ctx->callback_arg;
+ return 1;
+}
+
+int ASYNC_WAIT_CTX_set_status(ASYNC_WAIT_CTX *ctx, int status)
+{
+ ctx->status = status;
+ return 1;
+}
+
+int ASYNC_WAIT_CTX_get_status(ASYNC_WAIT_CTX *ctx)
+{
+ return ctx->status;
+}
+
void async_wait_ctx_reset_counts(ASYNC_WAIT_CTX *ctx)
{
struct fd_lookup_st *curr, *prev = NULL;
diff --git a/crypto/bf/asm/bf-586.pl b/crypto/bf/asm/bf-586.pl
index cddc17bddafa..336448635ab3 100644
--- a/crypto/bf/asm/bf-586.pl
+++ b/crypto/bf/asm/bf-586.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -12,8 +12,7 @@ push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
require "cbc.pl";
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386");
diff --git a/crypto/bf/bf_cfb64.c b/crypto/bf/bf_cfb64.c
index 12332c540d66..d7a92662042b 100644
--- a/crypto/bf/bf_cfb64.c
+++ b/crypto/bf/bf_cfb64.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * BF low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/blowfish.h>
#include "bf_local.h"
diff --git a/crypto/bf/bf_ecb.c b/crypto/bf/bf_ecb.c
index 38e784cc2dad..b02768261d8b 100644
--- a/crypto/bf/bf_ecb.c
+++ b/crypto/bf/bf_ecb.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * BF low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/blowfish.h>
#include "bf_local.h"
#include <openssl/opensslv.h>
diff --git a/crypto/bf/bf_enc.c b/crypto/bf/bf_enc.c
index 423a4697a51e..40ddaf4af61b 100644
--- a/crypto/bf/bf_enc.c
+++ b/crypto/bf/bf_enc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * BF low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/blowfish.h>
#include "bf_local.h"
diff --git a/crypto/bf/bf_local.h b/crypto/bf/bf_local.h
index 8c76976fa4d9..080f37a5f94c 100644
--- a/crypto/bf/bf_local.h
+++ b/crypto/bf/bf_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/bf/bf_ofb64.c b/crypto/bf/bf_ofb64.c
index 5d75401fcca5..086c3f07f0bc 100644
--- a/crypto/bf/bf_ofb64.c
+++ b/crypto/bf/bf_ofb64.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * BF low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/blowfish.h>
#include "bf_local.h"
diff --git a/crypto/bf/bf_pi.h b/crypto/bf/bf_pi.h
index a054b03f8122..8b9896e7f3e0 100644
--- a/crypto/bf/bf_pi.h
+++ b/crypto/bf/bf_pi.h
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/bf/bf_skey.c b/crypto/bf/bf_skey.c
index ed29cf9153a4..9728be297c17 100644
--- a/crypto/bf/bf_skey.c
+++ b/crypto/bf/bf_skey.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * BF low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <string.h>
#include <openssl/blowfish.h>
diff --git a/crypto/bf/build.info b/crypto/bf/build.info
index 29adc8ce5072..d24ab5ae573d 100644
--- a/crypto/bf/build.info
+++ b/crypto/bf/build.info
@@ -1,7 +1,25 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=bf_skey.c bf_ecb.c bf_cfb64.c bf_ofb64.c \
- {- $target{bf_asm_src} -}
-GENERATE[bf-586.s]=asm/bf-586.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-DEPEND[bf-586.s]=../perlasm/x86asm.pl ../perlasm/cbc.pl
+$BFASM=bf_enc.c
+IF[{- !$disabled{asm} -}]
+ $BFASM_x86=bf-586.S
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one
+ IF[$BFASM_{- $target{asm_arch} -}]
+ $BFASM=$BFASM_{- $target{asm_arch} -}
+ ENDIF
+ENDIF
+
+$ALL=bf_skey.c bf_ecb.c bf_cfb64.c bf_ofb64.c $BFASM
+
+SOURCE[../../libcrypto]=$ALL
+
+# When all deprecated symbols are removed, libcrypto doesn't export the
+# blowfish functions, so we must include them directly in liblegacy.a
+IF[{- $disabled{'deprecated-3.0'} && !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../../providers/liblegacy.a]=$ALL
+ENDIF
+
+GENERATE[bf-586.S]=asm/bf-586.pl
+DEPEND[bf-586.S]=../perlasm/x86asm.pl ../perlasm/cbc.pl
diff --git a/crypto/bio/b_addr.c b/crypto/bio/b_addr.c
deleted file mode 100644
index 0af7a330bc68..000000000000
--- a/crypto/bio/b_addr.c
+++ /dev/null
@@ -1,928 +0,0 @@
-/*
- * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-#endif
-
-#include <assert.h>
-#include <string.h>
-
-#include "bio_local.h"
-#include <openssl/crypto.h>
-
-#ifndef OPENSSL_NO_SOCK
-#include <openssl/err.h>
-#include <openssl/buffer.h>
-#include "internal/thread_once.h"
-
-CRYPTO_RWLOCK *bio_lookup_lock;
-static CRYPTO_ONCE bio_lookup_init = CRYPTO_ONCE_STATIC_INIT;
-
-/*
- * Throughout this file and bio_local.h, the existence of the macro
- * AI_PASSIVE is used to detect the availability of struct addrinfo,
- * getnameinfo() and getaddrinfo(). If that macro doesn't exist,
- * we use our own implementation instead, using gethostbyname,
- * getservbyname and a few other.
- */
-
-/**********************************************************************
- *
- * Address structure
- *
- */
-
-BIO_ADDR *BIO_ADDR_new(void)
-{
- BIO_ADDR *ret = OPENSSL_zalloc(sizeof(*ret));
-
- if (ret == NULL) {
- BIOerr(BIO_F_BIO_ADDR_NEW, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- ret->sa.sa_family = AF_UNSPEC;
- return ret;
-}
-
-void BIO_ADDR_free(BIO_ADDR *ap)
-{
- OPENSSL_free(ap);
-}
-
-void BIO_ADDR_clear(BIO_ADDR *ap)
-{
- memset(ap, 0, sizeof(*ap));
- ap->sa.sa_family = AF_UNSPEC;
-}
-
-/*
- * BIO_ADDR_make - non-public routine to fill a BIO_ADDR with the contents
- * of a struct sockaddr.
- */
-int BIO_ADDR_make(BIO_ADDR *ap, const struct sockaddr *sa)
-{
- if (sa->sa_family == AF_INET) {
- memcpy(&(ap->s_in), sa, sizeof(struct sockaddr_in));
- return 1;
- }
-#ifdef AF_INET6
- if (sa->sa_family == AF_INET6) {
- memcpy(&(ap->s_in6), sa, sizeof(struct sockaddr_in6));
- return 1;
- }
-#endif
-#ifdef AF_UNIX
- if (sa->sa_family == AF_UNIX) {
- memcpy(&(ap->s_un), sa, sizeof(struct sockaddr_un));
- return 1;
- }
-#endif
-
- return 0;
-}
-
-int BIO_ADDR_rawmake(BIO_ADDR *ap, int family,
- const void *where, size_t wherelen,
- unsigned short port)
-{
-#ifdef AF_UNIX
- if (family == AF_UNIX) {
- if (wherelen + 1 > sizeof(ap->s_un.sun_path))
- return 0;
- memset(&ap->s_un, 0, sizeof(ap->s_un));
- ap->s_un.sun_family = family;
- strncpy(ap->s_un.sun_path, where, sizeof(ap->s_un.sun_path) - 1);
- return 1;
- }
-#endif
- if (family == AF_INET) {
- if (wherelen != sizeof(struct in_addr))
- return 0;
- memset(&ap->s_in, 0, sizeof(ap->s_in));
- ap->s_in.sin_family = family;
- ap->s_in.sin_port = port;
- ap->s_in.sin_addr = *(struct in_addr *)where;
- return 1;
- }
-#ifdef AF_INET6
- if (family == AF_INET6) {
- if (wherelen != sizeof(struct in6_addr))
- return 0;
- memset(&ap->s_in6, 0, sizeof(ap->s_in6));
- ap->s_in6.sin6_family = family;
- ap->s_in6.sin6_port = port;
- ap->s_in6.sin6_addr = *(struct in6_addr *)where;
- return 1;
- }
-#endif
-
- return 0;
-}
-
-int BIO_ADDR_family(const BIO_ADDR *ap)
-{
- return ap->sa.sa_family;
-}
-
-int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l)
-{
- size_t len = 0;
- const void *addrptr = NULL;
-
- if (ap->sa.sa_family == AF_INET) {
- len = sizeof(ap->s_in.sin_addr);
- addrptr = &ap->s_in.sin_addr;
- }
-#ifdef AF_INET6
- else if (ap->sa.sa_family == AF_INET6) {
- len = sizeof(ap->s_in6.sin6_addr);
- addrptr = &ap->s_in6.sin6_addr;
- }
-#endif
-#ifdef AF_UNIX
- else if (ap->sa.sa_family == AF_UNIX) {
- len = strlen(ap->s_un.sun_path);
- addrptr = &ap->s_un.sun_path;
- }
-#endif
-
- if (addrptr == NULL)
- return 0;
-
- if (p != NULL) {
- memcpy(p, addrptr, len);
- }
- if (l != NULL)
- *l = len;
-
- return 1;
-}
-
-unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap)
-{
- if (ap->sa.sa_family == AF_INET)
- return ap->s_in.sin_port;
-#ifdef AF_INET6
- if (ap->sa.sa_family == AF_INET6)
- return ap->s_in6.sin6_port;
-#endif
- return 0;
-}
-
-/*-
- * addr_strings - helper function to get host and service names
- * @ap: the BIO_ADDR that has the input info
- * @numeric: 0 if actual names should be returned, 1 if the numeric
- * representation should be returned.
- * @hostname: a pointer to a pointer to a memory area to store the
- * host name or numeric representation. Unused if NULL.
- * @service: a pointer to a pointer to a memory area to store the
- * service name or numeric representation. Unused if NULL.
- *
- * The return value is 0 on failure, with the error code in the error
- * stack, and 1 on success.
- */
-static int addr_strings(const BIO_ADDR *ap, int numeric,
- char **hostname, char **service)
-{
- if (BIO_sock_init() != 1)
- return 0;
-
- if (1) {
-#ifdef AI_PASSIVE
- int ret = 0;
- char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = "";
- int flags = 0;
-
- if (numeric)
- flags |= NI_NUMERICHOST | NI_NUMERICSERV;
-
- if ((ret = getnameinfo(BIO_ADDR_sockaddr(ap),
- BIO_ADDR_sockaddr_size(ap),
- host, sizeof(host), serv, sizeof(serv),
- flags)) != 0) {
-# ifdef EAI_SYSTEM
- if (ret == EAI_SYSTEM) {
- SYSerr(SYS_F_GETNAMEINFO, get_last_socket_error());
- BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB);
- } else
-# endif
- {
- BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB);
- ERR_add_error_data(1, gai_strerror(ret));
- }
- return 0;
- }
-
- /* VMS getnameinfo() has a bug, it doesn't fill in serv, which
- * leaves it with whatever garbage that happens to be there.
- * However, we initialise serv with the empty string (serv[0]
- * is therefore NUL), so it gets real easy to detect when things
- * didn't go the way one might expect.
- */
- if (serv[0] == '\0') {
- BIO_snprintf(serv, sizeof(serv), "%d",
- ntohs(BIO_ADDR_rawport(ap)));
- }
-
- if (hostname != NULL)
- *hostname = OPENSSL_strdup(host);
- if (service != NULL)
- *service = OPENSSL_strdup(serv);
- } else {
-#endif
- if (hostname != NULL)
- *hostname = OPENSSL_strdup(inet_ntoa(ap->s_in.sin_addr));
- if (service != NULL) {
- char serv[6]; /* port is 16 bits => max 5 decimal digits */
- BIO_snprintf(serv, sizeof(serv), "%d", ntohs(ap->s_in.sin_port));
- *service = OPENSSL_strdup(serv);
- }
- }
-
- if ((hostname != NULL && *hostname == NULL)
- || (service != NULL && *service == NULL)) {
- if (hostname != NULL) {
- OPENSSL_free(*hostname);
- *hostname = NULL;
- }
- if (service != NULL) {
- OPENSSL_free(*service);
- *service = NULL;
- }
- BIOerr(BIO_F_ADDR_STRINGS, ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- return 1;
-}
-
-char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric)
-{
- char *hostname = NULL;
-
- if (addr_strings(ap, numeric, &hostname, NULL))
- return hostname;
-
- return NULL;
-}
-
-char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric)
-{
- char *service = NULL;
-
- if (addr_strings(ap, numeric, NULL, &service))
- return service;
-
- return NULL;
-}
-
-char *BIO_ADDR_path_string(const BIO_ADDR *ap)
-{
-#ifdef AF_UNIX
- if (ap->sa.sa_family == AF_UNIX)
- return OPENSSL_strdup(ap->s_un.sun_path);
-#endif
- return NULL;
-}
-
-/*
- * BIO_ADDR_sockaddr - non-public routine to return the struct sockaddr
- * for a given BIO_ADDR. In reality, this is simply a type safe cast.
- * The returned struct sockaddr is const, so it can't be tampered with.
- */
-const struct sockaddr *BIO_ADDR_sockaddr(const BIO_ADDR *ap)
-{
- return &(ap->sa);
-}
-
-/*
- * BIO_ADDR_sockaddr_noconst - non-public function that does the same
- * as BIO_ADDR_sockaddr, but returns a non-const. USE WITH CARE, as
- * it allows you to tamper with the data (and thereby the contents
- * of the input BIO_ADDR).
- */
-struct sockaddr *BIO_ADDR_sockaddr_noconst(BIO_ADDR *ap)
-{
- return &(ap->sa);
-}
-
-/*
- * BIO_ADDR_sockaddr_size - non-public function that returns the size
- * of the struct sockaddr the BIO_ADDR is using. If the protocol family
- * isn't set or is something other than AF_INET, AF_INET6 or AF_UNIX,
- * the size of the BIO_ADDR type is returned.
- */
-socklen_t BIO_ADDR_sockaddr_size(const BIO_ADDR *ap)
-{
- if (ap->sa.sa_family == AF_INET)
- return sizeof(ap->s_in);
-#ifdef AF_INET6
- if (ap->sa.sa_family == AF_INET6)
- return sizeof(ap->s_in6);
-#endif
-#ifdef AF_UNIX
- if (ap->sa.sa_family == AF_UNIX)
- return sizeof(ap->s_un);
-#endif
- return sizeof(*ap);
-}
-
-/**********************************************************************
- *
- * Address info database
- *
- */
-
-const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai)
-{
- if (bai != NULL)
- return bai->bai_next;
- return NULL;
-}
-
-int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai)
-{
- if (bai != NULL)
- return bai->bai_family;
- return 0;
-}
-
-int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai)
-{
- if (bai != NULL)
- return bai->bai_socktype;
- return 0;
-}
-
-int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai)
-{
- if (bai != NULL) {
- if (bai->bai_protocol != 0)
- return bai->bai_protocol;
-
-#ifdef AF_UNIX
- if (bai->bai_family == AF_UNIX)
- return 0;
-#endif
-
- switch (bai->bai_socktype) {
- case SOCK_STREAM:
- return IPPROTO_TCP;
- case SOCK_DGRAM:
- return IPPROTO_UDP;
- default:
- break;
- }
- }
- return 0;
-}
-
-/*
- * BIO_ADDRINFO_sockaddr_size - non-public function that returns the size
- * of the struct sockaddr inside the BIO_ADDRINFO.
- */
-socklen_t BIO_ADDRINFO_sockaddr_size(const BIO_ADDRINFO *bai)
-{
- if (bai != NULL)
- return bai->bai_addrlen;
- return 0;
-}
-
-/*
- * BIO_ADDRINFO_sockaddr - non-public function that returns bai_addr
- * as the struct sockaddr it is.
- */
-const struct sockaddr *BIO_ADDRINFO_sockaddr(const BIO_ADDRINFO *bai)
-{
- if (bai != NULL)
- return bai->bai_addr;
- return NULL;
-}
-
-const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai)
-{
- if (bai != NULL)
- return (BIO_ADDR *)bai->bai_addr;
- return NULL;
-}
-
-void BIO_ADDRINFO_free(BIO_ADDRINFO *bai)
-{
- if (bai == NULL)
- return;
-
-#ifdef AI_PASSIVE
-# ifdef AF_UNIX
-# define _cond bai->bai_family != AF_UNIX
-# else
-# define _cond 1
-# endif
- if (_cond) {
- freeaddrinfo(bai);
- return;
- }
-#endif
-
- /* Free manually when we know that addrinfo_wrap() was used.
- * See further comment above addrinfo_wrap()
- */
- while (bai != NULL) {
- BIO_ADDRINFO *next = bai->bai_next;
- OPENSSL_free(bai->bai_addr);
- OPENSSL_free(bai);
- bai = next;
- }
-}
-
-/**********************************************************************
- *
- * Service functions
- *
- */
-
-/*-
- * The specs in hostserv can take these forms:
- *
- * host:service => *host = "host", *service = "service"
- * host:* => *host = "host", *service = NULL
- * host: => *host = "host", *service = NULL
- * :service => *host = NULL, *service = "service"
- * *:service => *host = NULL, *service = "service"
- *
- * in case no : is present in the string, the result depends on
- * hostserv_prio, as follows:
- *
- * when hostserv_prio == BIO_PARSE_PRIO_HOST
- * host => *host = "host", *service untouched
- *
- * when hostserv_prio == BIO_PARSE_PRIO_SERV
- * service => *host untouched, *service = "service"
- *
- */
-int BIO_parse_hostserv(const char *hostserv, char **host, char **service,
- enum BIO_hostserv_priorities hostserv_prio)
-{
- const char *h = NULL; size_t hl = 0;
- const char *p = NULL; size_t pl = 0;
-
- if (*hostserv == '[') {
- if ((p = strchr(hostserv, ']')) == NULL)
- goto spec_err;
- h = hostserv + 1;
- hl = p - h;
- p++;
- if (*p == '\0')
- p = NULL;
- else if (*p != ':')
- goto spec_err;
- else {
- p++;
- pl = strlen(p);
- }
- } else {
- const char *p2 = strrchr(hostserv, ':');
- p = strchr(hostserv, ':');
-
- /*-
- * Check for more than one colon. There are three possible
- * interpretations:
- * 1. IPv6 address with port number, last colon being separator.
- * 2. IPv6 address only.
- * 3. IPv6 address only if hostserv_prio == BIO_PARSE_PRIO_HOST,
- * IPv6 address and port number if hostserv_prio == BIO_PARSE_PRIO_SERV
- * Because of this ambiguity, we currently choose to make it an
- * error.
- */
- if (p != p2)
- goto amb_err;
-
- if (p != NULL) {
- h = hostserv;
- hl = p - h;
- p++;
- pl = strlen(p);
- } else if (hostserv_prio == BIO_PARSE_PRIO_HOST) {
- h = hostserv;
- hl = strlen(h);
- } else {
- p = hostserv;
- pl = strlen(p);
- }
- }
-
- if (p != NULL && strchr(p, ':'))
- goto spec_err;
-
- if (h != NULL && host != NULL) {
- if (hl == 0
- || (hl == 1 && h[0] == '*')) {
- *host = NULL;
- } else {
- *host = OPENSSL_strndup(h, hl);
- if (*host == NULL)
- goto memerr;
- }
- }
- if (p != NULL && service != NULL) {
- if (pl == 0
- || (pl == 1 && p[0] == '*')) {
- *service = NULL;
- } else {
- *service = OPENSSL_strndup(p, pl);
- if (*service == NULL)
- goto memerr;
- }
- }
-
- return 1;
- amb_err:
- BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_AMBIGUOUS_HOST_OR_SERVICE);
- return 0;
- spec_err:
- BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_MALFORMED_HOST_OR_SERVICE);
- return 0;
- memerr:
- BIOerr(BIO_F_BIO_PARSE_HOSTSERV, ERR_R_MALLOC_FAILURE);
- return 0;
-}
-
-/* addrinfo_wrap is used to build our own addrinfo "chain".
- * (it has only one entry, so calling it a chain may be a stretch)
- * It should ONLY be called when getaddrinfo() and friends
- * aren't available, OR when dealing with a non IP protocol
- * family, such as AF_UNIX
- *
- * the return value is 1 on success, or 0 on failure, which
- * only happens if a memory allocation error occurred.
- */
-static int addrinfo_wrap(int family, int socktype,
- const void *where, size_t wherelen,
- unsigned short port,
- BIO_ADDRINFO **bai)
-{
- if ((*bai = OPENSSL_zalloc(sizeof(**bai))) == NULL) {
- BIOerr(BIO_F_ADDRINFO_WRAP, ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- (*bai)->bai_family = family;
- (*bai)->bai_socktype = socktype;
- if (socktype == SOCK_STREAM)
- (*bai)->bai_protocol = IPPROTO_TCP;
- if (socktype == SOCK_DGRAM)
- (*bai)->bai_protocol = IPPROTO_UDP;
-#ifdef AF_UNIX
- if (family == AF_UNIX)
- (*bai)->bai_protocol = 0;
-#endif
- {
- /* Magic: We know that BIO_ADDR_sockaddr_noconst is really
- just an advanced cast of BIO_ADDR* to struct sockaddr *
- by the power of union, so while it may seem that we're
- creating a memory leak here, we are not. It will be
- all right. */
- BIO_ADDR *addr = BIO_ADDR_new();
- if (addr != NULL) {
- BIO_ADDR_rawmake(addr, family, where, wherelen, port);
- (*bai)->bai_addr = BIO_ADDR_sockaddr_noconst(addr);
- }
- }
- (*bai)->bai_next = NULL;
- if ((*bai)->bai_addr == NULL) {
- BIO_ADDRINFO_free(*bai);
- *bai = NULL;
- return 0;
- }
- return 1;
-}
-
-DEFINE_RUN_ONCE_STATIC(do_bio_lookup_init)
-{
- if (!OPENSSL_init_crypto(0, NULL))
- return 0;
- bio_lookup_lock = CRYPTO_THREAD_lock_new();
- return bio_lookup_lock != NULL;
-}
-
-int BIO_lookup(const char *host, const char *service,
- enum BIO_lookup_type lookup_type,
- int family, int socktype, BIO_ADDRINFO **res)
-{
- return BIO_lookup_ex(host, service, lookup_type, family, socktype, 0, res);
-}
-
-/*-
- * BIO_lookup_ex - look up the node and service you want to connect to.
- * @node: the node you want to connect to.
- * @service: the service you want to connect to.
- * @lookup_type: declare intent with the result, client or server.
- * @family: the address family you want to use. Use AF_UNSPEC for any, or
- * AF_INET, AF_INET6 or AF_UNIX.
- * @socktype: The socket type you want to use. Can be SOCK_STREAM, SOCK_DGRAM
- * or 0 for all.
- * @protocol: The protocol to use, e.g. IPPROTO_TCP or IPPROTO_UDP or 0 for all.
- * Note that some platforms may not return IPPROTO_SCTP without
- * explicitly requesting it (i.e. IPPROTO_SCTP may not be returned
- * with 0 for the protocol)
- * @res: Storage place for the resulting list of returned addresses
- *
- * This will do a lookup of the node and service that you want to connect to.
- * It returns a linked list of different addresses you can try to connect to.
- *
- * When no longer needed you should call BIO_ADDRINFO_free() to free the result.
- *
- * The return value is 1 on success or 0 in case of error.
- */
-int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
- int family, int socktype, int protocol, BIO_ADDRINFO **res)
-{
- int ret = 0; /* Assume failure */
-
- switch(family) {
- case AF_INET:
-#ifdef AF_INET6
- case AF_INET6:
-#endif
-#ifdef AF_UNIX
- case AF_UNIX:
-#endif
-#ifdef AF_UNSPEC
- case AF_UNSPEC:
-#endif
- break;
- default:
- BIOerr(BIO_F_BIO_LOOKUP_EX, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY);
- return 0;
- }
-
-#ifdef AF_UNIX
- if (family == AF_UNIX) {
- if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res))
- return 1;
- else
- BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE);
- return 0;
- }
-#endif
-
- if (BIO_sock_init() != 1)
- return 0;
-
- if (1) {
-#ifdef AI_PASSIVE
- int gai_ret = 0, old_ret = 0;
- struct addrinfo hints;
-
- memset(&hints, 0, sizeof(hints));
-
- hints.ai_family = family;
- hints.ai_socktype = socktype;
- hints.ai_protocol = protocol;
-# ifdef AI_ADDRCONFIG
-# ifdef AF_UNSPEC
- if (host != NULL && family == AF_UNSPEC)
-# endif
- hints.ai_flags |= AI_ADDRCONFIG;
-# endif
-
- if (lookup_type == BIO_LOOKUP_SERVER)
- hints.ai_flags |= AI_PASSIVE;
-
- /* Note that |res| SHOULD be a 'struct addrinfo **' thanks to
- * macro magic in bio_local.h
- */
-# if defined(AI_ADDRCONFIG) && defined(AI_NUMERICHOST)
- retry:
-# endif
- switch ((gai_ret = getaddrinfo(host, service, &hints, res))) {
-# ifdef EAI_SYSTEM
- case EAI_SYSTEM:
- SYSerr(SYS_F_GETADDRINFO, get_last_socket_error());
- BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_SYS_LIB);
- break;
-# endif
-# ifdef EAI_MEMORY
- case EAI_MEMORY:
- BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE);
- break;
-# endif
- case 0:
- ret = 1; /* Success */
- break;
- default:
-# if defined(AI_ADDRCONFIG) && defined(AI_NUMERICHOST)
- if (hints.ai_flags & AI_ADDRCONFIG) {
- hints.ai_flags &= ~AI_ADDRCONFIG;
- hints.ai_flags |= AI_NUMERICHOST;
- old_ret = gai_ret;
- goto retry;
- }
-# endif
- BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_SYS_LIB);
- ERR_add_error_data(1, gai_strerror(old_ret ? old_ret : gai_ret));
- break;
- }
- } else {
-#endif
- const struct hostent *he;
-/*
- * Because struct hostent is defined for 32-bit pointers only with
- * VMS C, we need to make sure that '&he_fallback_address' and
- * '&he_fallback_addresses' are 32-bit pointers
- */
-#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
-# pragma pointer_size save
-# pragma pointer_size 32
-#endif
- /* Windows doesn't seem to have in_addr_t */
-#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
- static uint32_t he_fallback_address;
- static const char *he_fallback_addresses[] =
- { (char *)&he_fallback_address, NULL };
-#else
- static in_addr_t he_fallback_address;
- static const char *he_fallback_addresses[] =
- { (char *)&he_fallback_address, NULL };
-#endif
- static const struct hostent he_fallback =
- { NULL, NULL, AF_INET, sizeof(he_fallback_address),
- (char **)&he_fallback_addresses };
-#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
-# pragma pointer_size restore
-#endif
-
- struct servent *se;
- /* Apparently, on WIN64, s_proto and s_port have traded places... */
-#ifdef _WIN64
- struct servent se_fallback = { NULL, NULL, NULL, 0 };
-#else
- struct servent se_fallback = { NULL, NULL, 0, NULL };
-#endif
-
- if (!RUN_ONCE(&bio_lookup_init, do_bio_lookup_init)) {
- BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE);
- ret = 0;
- goto err;
- }
-
- CRYPTO_THREAD_write_lock(bio_lookup_lock);
- he_fallback_address = INADDR_ANY;
- if (host == NULL) {
- he = &he_fallback;
- switch(lookup_type) {
- case BIO_LOOKUP_CLIENT:
- he_fallback_address = INADDR_LOOPBACK;
- break;
- case BIO_LOOKUP_SERVER:
- he_fallback_address = INADDR_ANY;
- break;
- default:
- /* We forgot to handle a lookup type! */
- assert("We forgot to handle a lookup type!" == NULL);
- BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_INTERNAL_ERROR);
- ret = 0;
- goto err;
- }
- } else {
- he = gethostbyname(host);
-
- if (he == NULL) {
-#ifndef OPENSSL_SYS_WINDOWS
- /*
- * This might be misleading, because h_errno is used as if
- * it was errno. To minimize mixup add 1000. Underlying
- * reason for this is that hstrerror is declared obsolete,
- * not to mention that a) h_errno is not always guaranteed
- * to be meaningless; b) hstrerror can reside in yet another
- * library, linking for sake of hstrerror is an overkill;
- * c) this path is not executed on contemporary systems
- * anyway [above getaddrinfo/gai_strerror is]. We just let
- * system administrator figure this out...
- */
-# if defined(OPENSSL_SYS_VXWORKS)
- /* h_errno doesn't exist on VxWorks */
- SYSerr(SYS_F_GETHOSTBYNAME, 1000 );
-# else
- SYSerr(SYS_F_GETHOSTBYNAME, 1000 + h_errno);
-# endif
-#else
- SYSerr(SYS_F_GETHOSTBYNAME, WSAGetLastError());
-#endif
- ret = 0;
- goto err;
- }
- }
-
- if (service == NULL) {
- se_fallback.s_port = 0;
- se_fallback.s_proto = NULL;
- se = &se_fallback;
- } else {
- char *endp = NULL;
- long portnum = strtol(service, &endp, 10);
-
-/*
- * Because struct servent is defined for 32-bit pointers only with
- * VMS C, we need to make sure that 'proto' is a 32-bit pointer.
- */
-#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
-# pragma pointer_size save
-# pragma pointer_size 32
-#endif
- char *proto = NULL;
-#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
-# pragma pointer_size restore
-#endif
-
- switch (socktype) {
- case SOCK_STREAM:
- proto = "tcp";
- break;
- case SOCK_DGRAM:
- proto = "udp";
- break;
- }
-
- if (endp != service && *endp == '\0'
- && portnum > 0 && portnum < 65536) {
- se_fallback.s_port = htons((unsigned short)portnum);
- se_fallback.s_proto = proto;
- se = &se_fallback;
- } else if (endp == service) {
- se = getservbyname(service, proto);
-
- if (se == NULL) {
-#ifndef OPENSSL_SYS_WINDOWS
- SYSerr(SYS_F_GETSERVBYNAME, errno);
-#else
- SYSerr(SYS_F_GETSERVBYNAME, WSAGetLastError());
-#endif
- goto err;
- }
- } else {
- BIOerr(BIO_F_BIO_LOOKUP_EX, BIO_R_MALFORMED_HOST_OR_SERVICE);
- goto err;
- }
- }
-
- *res = NULL;
-
- {
-/*
- * Because hostent::h_addr_list is an array of 32-bit pointers with VMS C,
- * we must make sure our iterator designates the same element type, hence
- * the pointer size dance.
- */
-#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
-# pragma pointer_size save
-# pragma pointer_size 32
-#endif
- char **addrlistp;
-#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
-# pragma pointer_size restore
-#endif
- size_t addresses;
- BIO_ADDRINFO *tmp_bai = NULL;
-
- /* The easiest way to create a linked list from an
- array is to start from the back */
- for(addrlistp = he->h_addr_list; *addrlistp != NULL;
- addrlistp++)
- ;
-
- for(addresses = addrlistp - he->h_addr_list;
- addrlistp--, addresses-- > 0; ) {
- if (!addrinfo_wrap(he->h_addrtype, socktype,
- *addrlistp, he->h_length,
- se->s_port, &tmp_bai))
- goto addrinfo_malloc_err;
- tmp_bai->bai_next = *res;
- *res = tmp_bai;
- continue;
- addrinfo_malloc_err:
- BIO_ADDRINFO_free(*res);
- *res = NULL;
- BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE);
- ret = 0;
- goto err;
- }
-
- ret = 1;
- }
- err:
- CRYPTO_THREAD_unlock(bio_lookup_lock);
- }
-
- return ret;
-}
-
-#endif /* OPENSSL_NO_SOCK */
diff --git a/crypto/bio/b_dump.c b/crypto/bio/b_dump.c
deleted file mode 100644
index f175e244b233..000000000000
--- a/crypto/bio/b_dump.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * Stolen from tjh's ssl/ssl_trc.c stuff.
- */
-
-#include <stdio.h>
-#include "bio_local.h"
-
-#define DUMP_WIDTH 16
-#define DUMP_WIDTH_LESS_INDENT(i) (DUMP_WIDTH - ((i - (i > 6 ? 6 : i) + 3) / 4))
-
-#define SPACE(buf, pos, n) (sizeof(buf) - (pos) > (n))
-
-int BIO_dump_cb(int (*cb) (const void *data, size_t len, void *u),
- void *u, const char *s, int len)
-{
- return BIO_dump_indent_cb(cb, u, s, len, 0);
-}
-
-int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u),
- void *u, const char *s, int len, int indent)
-{
- int ret = 0;
- char buf[288 + 1];
- int i, j, rows, n;
- unsigned char ch;
- int dump_width;
-
- if (indent < 0)
- indent = 0;
- else if (indent > 64)
- indent = 64;
-
- dump_width = DUMP_WIDTH_LESS_INDENT(indent);
- rows = len / dump_width;
- if ((rows * dump_width) < len)
- rows++;
- for (i = 0; i < rows; i++) {
- n = BIO_snprintf(buf, sizeof(buf), "%*s%04x - ", indent, "",
- i * dump_width);
- for (j = 0; j < dump_width; j++) {
- if (SPACE(buf, n, 3)) {
- if (((i * dump_width) + j) >= len) {
- strcpy(buf + n, " ");
- } else {
- ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff;
- BIO_snprintf(buf + n, 4, "%02x%c", ch,
- j == 7 ? '-' : ' ');
- }
- n += 3;
- }
- }
- if (SPACE(buf, n, 2)) {
- strcpy(buf + n, " ");
- n += 2;
- }
- for (j = 0; j < dump_width; j++) {
- if (((i * dump_width) + j) >= len)
- break;
- if (SPACE(buf, n, 1)) {
- ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff;
-#ifndef CHARSET_EBCDIC
- buf[n++] = ((ch >= ' ') && (ch <= '~')) ? ch : '.';
-#else
- buf[n++] = ((ch >= os_toascii[' ']) && (ch <= os_toascii['~']))
- ? os_toebcdic[ch]
- : '.';
-#endif
- buf[n] = '\0';
- }
- }
- if (SPACE(buf, n, 1)) {
- buf[n++] = '\n';
- buf[n] = '\0';
- }
- /*
- * if this is the last call then update the ddt_dump thing so that we
- * will move the selection point in the debug window
- */
- ret += cb((void *)buf, n, u);
- }
- return ret;
-}
-
-#ifndef OPENSSL_NO_STDIO
-static int write_fp(const void *data, size_t len, void *fp)
-{
- return UP_fwrite(data, len, 1, fp);
-}
-
-int BIO_dump_fp(FILE *fp, const char *s, int len)
-{
- return BIO_dump_cb(write_fp, fp, s, len);
-}
-
-int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent)
-{
- return BIO_dump_indent_cb(write_fp, fp, s, len, indent);
-}
-#endif
-
-static int write_bio(const void *data, size_t len, void *bp)
-{
- return BIO_write((BIO *)bp, (const char *)data, len);
-}
-
-int BIO_dump(BIO *bp, const char *s, int len)
-{
- return BIO_dump_cb(write_bio, bp, s, len);
-}
-
-int BIO_dump_indent(BIO *bp, const char *s, int len, int indent)
-{
- return BIO_dump_indent_cb(write_bio, bp, s, len, indent);
-}
-
-int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data,
- int datalen)
-{
- int i, j = 0;
-
- if (datalen < 1)
- return 1;
-
- for (i = 0; i < datalen - 1; i++) {
- if (i && !j)
- BIO_printf(out, "%*s", indent, "");
-
- BIO_printf(out, "%02X:", data[i]);
-
- j = (j + 1) % width;
- if (!j)
- BIO_printf(out, "\n");
- }
-
- if (i && !j)
- BIO_printf(out, "%*s", indent, "");
- BIO_printf(out, "%02X", data[datalen - 1]);
- return 1;
-}
diff --git a/crypto/bio/b_print.c b/crypto/bio/b_print.c
deleted file mode 100644
index 45d4e9f004b1..000000000000
--- a/crypto/bio/b_print.c
+++ /dev/null
@@ -1,954 +0,0 @@
-/*
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include <string.h>
-#include "internal/cryptlib.h"
-#include "crypto/ctype.h"
-#include "internal/numbers.h"
-#include <openssl/bio.h>
-#include <openssl/opensslconf.h>
-
-/*
- * Copyright Patrick Powell 1995
- * This code is based on code written by Patrick Powell <papowell@astart.com>
- * It may be used for any purpose as long as this notice remains intact
- * on all source code distributions.
- */
-
-#ifdef HAVE_LONG_DOUBLE
-# define LDOUBLE long double
-#else
-# define LDOUBLE double
-#endif
-
-static int fmtstr(char **, char **, size_t *, size_t *,
- const char *, int, int, int);
-static int fmtint(char **, char **, size_t *, size_t *,
- int64_t, int, int, int, int);
-#ifndef OPENSSL_SYS_UEFI
-static int fmtfp(char **, char **, size_t *, size_t *,
- LDOUBLE, int, int, int, int);
-#endif
-static int doapr_outch(char **, char **, size_t *, size_t *, int);
-static int _dopr(char **sbuffer, char **buffer,
- size_t *maxlen, size_t *retlen, int *truncated,
- const char *format, va_list args);
-
-/* format read states */
-#define DP_S_DEFAULT 0
-#define DP_S_FLAGS 1
-#define DP_S_MIN 2
-#define DP_S_DOT 3
-#define DP_S_MAX 4
-#define DP_S_MOD 5
-#define DP_S_CONV 6
-#define DP_S_DONE 7
-
-/* format flags - Bits */
-/* left-aligned padding */
-#define DP_F_MINUS (1 << 0)
-/* print an explicit '+' for a value with positive sign */
-#define DP_F_PLUS (1 << 1)
-/* print an explicit ' ' for a value with positive sign */
-#define DP_F_SPACE (1 << 2)
-/* print 0/0x prefix for octal/hex and decimal point for floating point */
-#define DP_F_NUM (1 << 3)
-/* print leading zeroes */
-#define DP_F_ZERO (1 << 4)
-/* print HEX in UPPPERcase */
-#define DP_F_UP (1 << 5)
-/* treat value as unsigned */
-#define DP_F_UNSIGNED (1 << 6)
-
-/* conversion flags */
-#define DP_C_SHORT 1
-#define DP_C_LONG 2
-#define DP_C_LDOUBLE 3
-#define DP_C_LLONG 4
-#define DP_C_SIZE 5
-
-/* Floating point formats */
-#define F_FORMAT 0
-#define E_FORMAT 1
-#define G_FORMAT 2
-
-/* some handy macros */
-#define char_to_int(p) (p - '0')
-#define OSSL_MAX(p,q) ((p >= q) ? p : q)
-
-static int
-_dopr(char **sbuffer,
- char **buffer,
- size_t *maxlen,
- size_t *retlen, int *truncated, const char *format, va_list args)
-{
- char ch;
- int64_t value;
-#ifndef OPENSSL_SYS_UEFI
- LDOUBLE fvalue;
-#endif
- char *strvalue;
- int min;
- int max;
- int state;
- int flags;
- int cflags;
- size_t currlen;
-
- state = DP_S_DEFAULT;
- flags = currlen = cflags = min = 0;
- max = -1;
- ch = *format++;
-
- while (state != DP_S_DONE) {
- if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
- state = DP_S_DONE;
-
- switch (state) {
- case DP_S_DEFAULT:
- if (ch == '%')
- state = DP_S_FLAGS;
- else
- if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
- return 0;
- ch = *format++;
- break;
- case DP_S_FLAGS:
- switch (ch) {
- case '-':
- flags |= DP_F_MINUS;
- ch = *format++;
- break;
- case '+':
- flags |= DP_F_PLUS;
- ch = *format++;
- break;
- case ' ':
- flags |= DP_F_SPACE;
- ch = *format++;
- break;
- case '#':
- flags |= DP_F_NUM;
- ch = *format++;
- break;
- case '0':
- flags |= DP_F_ZERO;
- ch = *format++;
- break;
- default:
- state = DP_S_MIN;
- break;
- }
- break;
- case DP_S_MIN:
- if (ossl_isdigit(ch)) {
- min = 10 * min + char_to_int(ch);
- ch = *format++;
- } else if (ch == '*') {
- min = va_arg(args, int);
- ch = *format++;
- state = DP_S_DOT;
- } else
- state = DP_S_DOT;
- break;
- case DP_S_DOT:
- if (ch == '.') {
- state = DP_S_MAX;
- ch = *format++;
- } else
- state = DP_S_MOD;
- break;
- case DP_S_MAX:
- if (ossl_isdigit(ch)) {
- if (max < 0)
- max = 0;
- max = 10 * max + char_to_int(ch);
- ch = *format++;
- } else if (ch == '*') {
- max = va_arg(args, int);
- ch = *format++;
- state = DP_S_MOD;
- } else
- state = DP_S_MOD;
- break;
- case DP_S_MOD:
- switch (ch) {
- case 'h':
- cflags = DP_C_SHORT;
- ch = *format++;
- break;
- case 'l':
- if (*format == 'l') {
- cflags = DP_C_LLONG;
- format++;
- } else
- cflags = DP_C_LONG;
- ch = *format++;
- break;
- case 'q':
- case 'j':
- cflags = DP_C_LLONG;
- ch = *format++;
- break;
- case 'L':
- cflags = DP_C_LDOUBLE;
- ch = *format++;
- break;
- case 'z':
- cflags = DP_C_SIZE;
- ch = *format++;
- break;
- default:
- break;
- }
- state = DP_S_CONV;
- break;
- case DP_S_CONV:
- switch (ch) {
- case 'd':
- case 'i':
- switch (cflags) {
- case DP_C_SHORT:
- value = (short int)va_arg(args, int);
- break;
- case DP_C_LONG:
- value = va_arg(args, long int);
- break;
- case DP_C_LLONG:
- value = va_arg(args, int64_t);
- break;
- case DP_C_SIZE:
- value = va_arg(args, ossl_ssize_t);
- break;
- default:
- value = va_arg(args, int);
- break;
- }
- if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min,
- max, flags))
- return 0;
- break;
- case 'X':
- flags |= DP_F_UP;
- /* FALLTHROUGH */
- case 'x':
- case 'o':
- case 'u':
- flags |= DP_F_UNSIGNED;
- switch (cflags) {
- case DP_C_SHORT:
- value = (unsigned short int)va_arg(args, unsigned int);
- break;
- case DP_C_LONG:
- value = va_arg(args, unsigned long int);
- break;
- case DP_C_LLONG:
- value = va_arg(args, uint64_t);
- break;
- case DP_C_SIZE:
- value = va_arg(args, size_t);
- break;
- default:
- value = va_arg(args, unsigned int);
- break;
- }
- if (!fmtint(sbuffer, buffer, &currlen, maxlen, value,
- ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
- min, max, flags))
- return 0;
- break;
-#ifndef OPENSSL_SYS_UEFI
- case 'f':
- if (cflags == DP_C_LDOUBLE)
- fvalue = va_arg(args, LDOUBLE);
- else
- fvalue = va_arg(args, double);
- if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
- flags, F_FORMAT))
- return 0;
- break;
- case 'E':
- flags |= DP_F_UP;
- /* fall thru */
- case 'e':
- if (cflags == DP_C_LDOUBLE)
- fvalue = va_arg(args, LDOUBLE);
- else
- fvalue = va_arg(args, double);
- if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
- flags, E_FORMAT))
- return 0;
- break;
- case 'G':
- flags |= DP_F_UP;
- /* fall thru */
- case 'g':
- if (cflags == DP_C_LDOUBLE)
- fvalue = va_arg(args, LDOUBLE);
- else
- fvalue = va_arg(args, double);
- if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
- flags, G_FORMAT))
- return 0;
- break;
-#else
- case 'f':
- case 'E':
- case 'e':
- case 'G':
- case 'g':
- /* not implemented for UEFI */
- ERR_raise(ERR_LIB_BIO, ERR_R_UNSUPPORTED);
- return 0;
-#endif
- case 'c':
- if (!doapr_outch(sbuffer, buffer, &currlen, maxlen,
- va_arg(args, int)))
- return 0;
- break;
- case 's':
- strvalue = va_arg(args, char *);
- if (max < 0) {
- if (buffer)
- max = INT_MAX;
- else
- max = *maxlen;
- }
- if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
- flags, min, max))
- return 0;
- break;
- case 'p':
- value = (size_t)va_arg(args, void *);
- if (!fmtint(sbuffer, buffer, &currlen, maxlen,
- value, 16, min, max, flags | DP_F_NUM))
- return 0;
- break;
- case 'n':
- {
- int *num;
- num = va_arg(args, int *);
- *num = currlen;
- }
- break;
- case '%':
- if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
- return 0;
- break;
- case 'w':
- /* not supported yet, treat as next char */
- ch = *format++;
- break;
- default:
- /* unknown, skip */
- break;
- }
- ch = *format++;
- state = DP_S_DEFAULT;
- flags = cflags = min = 0;
- max = -1;
- break;
- case DP_S_DONE:
- break;
- default:
- break;
- }
- }
- /*
- * We have to truncate if there is no dynamic buffer and we have filled the
- * static buffer.
- */
- if (buffer == NULL) {
- *truncated = (currlen > *maxlen - 1);
- if (*truncated)
- currlen = *maxlen - 1;
- }
- if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))
- return 0;
- *retlen = currlen - 1;
- return 1;
-}
-
-static int
-fmtstr(char **sbuffer,
- char **buffer,
- size_t *currlen,
- size_t *maxlen, const char *value, int flags, int min, int max)
-{
- int padlen;
- size_t strln;
- int cnt = 0;
-
- if (value == 0)
- value = "<NULL>";
-
- strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max);
-
- padlen = min - strln;
- if (min < 0 || padlen < 0)
- padlen = 0;
- if (max >= 0) {
- /*
- * Calculate the maximum output including padding.
- * Make sure max doesn't overflow into negativity
- */
- if (max < INT_MAX - padlen)
- max += padlen;
- else
- max = INT_MAX;
- }
- if (flags & DP_F_MINUS)
- padlen = -padlen;
-
- while ((padlen > 0) && (max < 0 || cnt < max)) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
- return 0;
- --padlen;
- ++cnt;
- }
- while (strln > 0 && (max < 0 || cnt < max)) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))
- return 0;
- --strln;
- ++cnt;
- }
- while ((padlen < 0) && (max < 0 || cnt < max)) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
- return 0;
- ++padlen;
- ++cnt;
- }
- return 1;
-}
-
-static int
-fmtint(char **sbuffer,
- char **buffer,
- size_t *currlen,
- size_t *maxlen, int64_t value, int base, int min, int max, int flags)
-{
- int signvalue = 0;
- const char *prefix = "";
- uint64_t uvalue;
- char convert[DECIMAL_SIZE(value) + 3];
- int place = 0;
- int spadlen = 0;
- int zpadlen = 0;
- int caps = 0;
-
- if (max < 0)
- max = 0;
- uvalue = value;
- if (!(flags & DP_F_UNSIGNED)) {
- if (value < 0) {
- signvalue = '-';
- uvalue = 0 - (uint64_t)value;
- } else if (flags & DP_F_PLUS)
- signvalue = '+';
- else if (flags & DP_F_SPACE)
- signvalue = ' ';
- }
- if (flags & DP_F_NUM) {
- if (base == 8)
- prefix = "0";
- if (base == 16)
- prefix = "0x";
- }
- if (flags & DP_F_UP)
- caps = 1;
- do {
- convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
- [uvalue % (unsigned)base];
- uvalue = (uvalue / (unsigned)base);
- } while (uvalue && (place < (int)sizeof(convert)));
- if (place == sizeof(convert))
- place--;
- convert[place] = 0;
-
- zpadlen = max - place;
- spadlen =
- min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
- if (zpadlen < 0)
- zpadlen = 0;
- if (spadlen < 0)
- spadlen = 0;
- if (flags & DP_F_ZERO) {
- zpadlen = OSSL_MAX(zpadlen, spadlen);
- spadlen = 0;
- }
- if (flags & DP_F_MINUS)
- spadlen = -spadlen;
-
- /* spaces */
- while (spadlen > 0) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
- return 0;
- --spadlen;
- }
-
- /* sign */
- if (signvalue)
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
- return 0;
-
- /* prefix */
- while (*prefix) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix))
- return 0;
- prefix++;
- }
-
- /* zeros */
- if (zpadlen > 0) {
- while (zpadlen > 0) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
- return 0;
- --zpadlen;
- }
- }
- /* digits */
- while (place > 0) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]))
- return 0;
- }
-
- /* left justified spaces */
- while (spadlen < 0) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
- return 0;
- ++spadlen;
- }
- return 1;
-}
-
-#ifndef OPENSSL_SYS_UEFI
-
-static LDOUBLE abs_val(LDOUBLE value)
-{
- LDOUBLE result = value;
- if (value < 0)
- result = -value;
- return result;
-}
-
-static LDOUBLE pow_10(int in_exp)
-{
- LDOUBLE result = 1;
- while (in_exp) {
- result *= 10;
- in_exp--;
- }
- return result;
-}
-
-static long roundv(LDOUBLE value)
-{
- long intpart;
- intpart = (long)value;
- value = value - intpart;
- if (value >= 0.5)
- intpart++;
- return intpart;
-}
-
-static int
-fmtfp(char **sbuffer,
- char **buffer,
- size_t *currlen,
- size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags, int style)
-{
- int signvalue = 0;
- LDOUBLE ufvalue;
- LDOUBLE tmpvalue;
- char iconvert[20];
- char fconvert[20];
- char econvert[20];
- int iplace = 0;
- int fplace = 0;
- int eplace = 0;
- int padlen = 0;
- int zpadlen = 0;
- long exp = 0;
- unsigned long intpart;
- unsigned long fracpart;
- unsigned long max10;
- int realstyle;
-
- if (max < 0)
- max = 6;
-
- if (fvalue < 0)
- signvalue = '-';
- else if (flags & DP_F_PLUS)
- signvalue = '+';
- else if (flags & DP_F_SPACE)
- signvalue = ' ';
-
- /*
- * G_FORMAT sometimes prints like E_FORMAT and sometimes like F_FORMAT
- * depending on the number to be printed. Work out which one it is and use
- * that from here on.
- */
- if (style == G_FORMAT) {
- if (fvalue == 0.0) {
- realstyle = F_FORMAT;
- } else if (fvalue < 0.0001) {
- realstyle = E_FORMAT;
- } else if ((max == 0 && fvalue >= 10)
- || (max > 0 && fvalue >= pow_10(max))) {
- realstyle = E_FORMAT;
- } else {
- realstyle = F_FORMAT;
- }
- } else {
- realstyle = style;
- }
-
- if (style != F_FORMAT) {
- tmpvalue = fvalue;
- /* Calculate the exponent */
- if (fvalue != 0.0) {
- while (tmpvalue < 1) {
- tmpvalue *= 10;
- exp--;
- }
- while (tmpvalue > 10) {
- tmpvalue /= 10;
- exp++;
- }
- }
- if (style == G_FORMAT) {
- /*
- * In G_FORMAT the "precision" represents significant digits. We
- * always have at least 1 significant digit.
- */
- if (max == 0)
- max = 1;
- /* Now convert significant digits to decimal places */
- if (realstyle == F_FORMAT) {
- max -= (exp + 1);
- if (max < 0) {
- /*
- * Should not happen. If we're in F_FORMAT then exp < max?
- */
- return 0;
- }
- } else {
- /*
- * In E_FORMAT there is always one significant digit in front
- * of the decimal point, so:
- * significant digits == 1 + decimal places
- */
- max--;
- }
- }
- if (realstyle == E_FORMAT)
- fvalue = tmpvalue;
- }
- ufvalue = abs_val(fvalue);
- /*
- * By subtracting 65535 (2^16-1) we cancel the low order 15 bits
- * of ULONG_MAX to avoid using imprecise floating point values.
- */
- if (ufvalue >= (double)(ULONG_MAX - 65535) + 65536.0) {
- /* Number too big */
- return 0;
- }
- intpart = (unsigned long)ufvalue;
-
- /*
- * sorry, we only support 9 digits past the decimal because of our
- * conversion method
- */
- if (max > 9)
- max = 9;
-
- /*
- * we "cheat" by converting the fractional part to integer by multiplying
- * by a factor of 10
- */
- max10 = roundv(pow_10(max));
- fracpart = roundv(pow_10(max) * (ufvalue - intpart));
-
- if (fracpart >= max10) {
- intpart++;
- fracpart -= max10;
- }
-
- /* convert integer part */
- do {
- iconvert[iplace++] = "0123456789"[intpart % 10];
- intpart = (intpart / 10);
- } while (intpart && (iplace < (int)sizeof(iconvert)));
- if (iplace == sizeof(iconvert))
- iplace--;
- iconvert[iplace] = 0;
-
- /* convert fractional part */
- while (fplace < max) {
- if (style == G_FORMAT && fplace == 0 && (fracpart % 10) == 0) {
- /* We strip trailing zeros in G_FORMAT */
- max--;
- fracpart = fracpart / 10;
- if (fplace < max)
- continue;
- break;
- }
- fconvert[fplace++] = "0123456789"[fracpart % 10];
- fracpart = (fracpart / 10);
- }
-
- if (fplace == sizeof(fconvert))
- fplace--;
- fconvert[fplace] = 0;
-
- /* convert exponent part */
- if (realstyle == E_FORMAT) {
- int tmpexp;
- if (exp < 0)
- tmpexp = -exp;
- else
- tmpexp = exp;
-
- do {
- econvert[eplace++] = "0123456789"[tmpexp % 10];
- tmpexp = (tmpexp / 10);
- } while (tmpexp > 0 && eplace < (int)sizeof(econvert));
- /* Exponent is huge!! Too big to print */
- if (tmpexp > 0)
- return 0;
- /* Add a leading 0 for single digit exponents */
- if (eplace == 1)
- econvert[eplace++] = '0';
- }
-
- /*
- * -1 for decimal point (if we have one, i.e. max > 0),
- * another -1 if we are printing a sign
- */
- padlen = min - iplace - max - (max > 0 ? 1 : 0) - ((signvalue) ? 1 : 0);
- /* Take some off for exponent prefix "+e" and exponent */
- if (realstyle == E_FORMAT)
- padlen -= 2 + eplace;
- zpadlen = max - fplace;
- if (zpadlen < 0)
- zpadlen = 0;
- if (padlen < 0)
- padlen = 0;
- if (flags & DP_F_MINUS)
- padlen = -padlen;
-
- if ((flags & DP_F_ZERO) && (padlen > 0)) {
- if (signvalue) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
- return 0;
- --padlen;
- signvalue = 0;
- }
- while (padlen > 0) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
- return 0;
- --padlen;
- }
- }
- while (padlen > 0) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
- return 0;
- --padlen;
- }
- if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
- return 0;
-
- while (iplace > 0) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]))
- return 0;
- }
-
- /*
- * Decimal point. This should probably use locale to find the correct
- * char to print out.
- */
- if (max > 0 || (flags & DP_F_NUM)) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.'))
- return 0;
-
- while (fplace > 0) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen,
- fconvert[--fplace]))
- return 0;
- }
- }
- while (zpadlen > 0) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
- return 0;
- --zpadlen;
- }
- if (realstyle == E_FORMAT) {
- char ech;
-
- if ((flags & DP_F_UP) == 0)
- ech = 'e';
- else
- ech = 'E';
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ech))
- return 0;
- if (exp < 0) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '-'))
- return 0;
- } else {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '+'))
- return 0;
- }
- while (eplace > 0) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen,
- econvert[--eplace]))
- return 0;
- }
- }
-
- while (padlen < 0) {
- if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
- return 0;
- ++padlen;
- }
- return 1;
-}
-
-#endif /* OPENSSL_SYS_UEFI */
-
-#define BUFFER_INC 1024
-
-static int
-doapr_outch(char **sbuffer,
- char **buffer, size_t *currlen, size_t *maxlen, int c)
-{
- /* If we haven't at least one buffer, someone has done a big booboo */
- if (!ossl_assert(*sbuffer != NULL || buffer != NULL))
- return 0;
-
- /* |currlen| must always be <= |*maxlen| */
- if (!ossl_assert(*currlen <= *maxlen))
- return 0;
-
- if (buffer && *currlen == *maxlen) {
- if (*maxlen > INT_MAX - BUFFER_INC)
- return 0;
-
- *maxlen += BUFFER_INC;
- if (*buffer == NULL) {
- if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) {
- BIOerr(BIO_F_DOAPR_OUTCH, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- if (*currlen > 0) {
- if (!ossl_assert(*sbuffer != NULL))
- return 0;
- memcpy(*buffer, *sbuffer, *currlen);
- }
- *sbuffer = NULL;
- } else {
- char *tmpbuf;
- tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
- if (tmpbuf == NULL)
- return 0;
- *buffer = tmpbuf;
- }
- }
-
- if (*currlen < *maxlen) {
- if (*sbuffer)
- (*sbuffer)[(*currlen)++] = (char)c;
- else
- (*buffer)[(*currlen)++] = (char)c;
- }
-
- return 1;
-}
-
-/***************************************************************************/
-
-int BIO_printf(BIO *bio, const char *format, ...)
-{
- va_list args;
- int ret;
-
- va_start(args, format);
-
- ret = BIO_vprintf(bio, format, args);
-
- va_end(args);
- return ret;
-}
-
-int BIO_vprintf(BIO *bio, const char *format, va_list args)
-{
- int ret;
- size_t retlen;
- char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable
- * in small-stack environments, like threads
- * or DOS programs. */
- char *hugebufp = hugebuf;
- size_t hugebufsize = sizeof(hugebuf);
- char *dynbuf = NULL;
- int ignored;
-
- dynbuf = NULL;
- if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format,
- args)) {
- OPENSSL_free(dynbuf);
- return -1;
- }
- if (dynbuf) {
- ret = BIO_write(bio, dynbuf, (int)retlen);
- OPENSSL_free(dynbuf);
- } else {
- ret = BIO_write(bio, hugebuf, (int)retlen);
- }
- return ret;
-}
-
-/*
- * As snprintf is not available everywhere, we provide our own
- * implementation. This function has nothing to do with BIOs, but it's
- * closely related to BIO_printf, and we need *some* name prefix ... (XXX the
- * function should be renamed, but to what?)
- */
-int BIO_snprintf(char *buf, size_t n, const char *format, ...)
-{
- va_list args;
- int ret;
-
- va_start(args, format);
-
- ret = BIO_vsnprintf(buf, n, format, args);
-
- va_end(args);
- return ret;
-}
-
-int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
-{
- size_t retlen;
- int truncated;
-
- if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
- return -1;
-
- if (truncated)
- /*
- * In case of truncation, return -1 like traditional snprintf.
- * (Current drafts for ISO/IEC 9899 say snprintf should return the
- * number of characters that would have been written, had the buffer
- * been large enough.)
- */
- return -1;
- else
- return (retlen <= INT_MAX) ? (int)retlen : -1;
-}
diff --git a/crypto/bio/b_sock.c b/crypto/bio/b_sock.c
deleted file mode 100644
index df431e6d523d..000000000000
--- a/crypto/bio/b_sock.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include "bio_local.h"
-#ifndef OPENSSL_NO_SOCK
-# define SOCKET_PROTOCOL IPPROTO_TCP
-# ifdef SO_MAXCONN
-# define MAX_LISTEN SO_MAXCONN
-# elif defined(SOMAXCONN)
-# define MAX_LISTEN SOMAXCONN
-# else
-# define MAX_LISTEN 32
-# endif
-# if defined(OPENSSL_SYS_WINDOWS)
-static int wsa_init_done = 0;
-# endif
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-int BIO_get_host_ip(const char *str, unsigned char *ip)
-{
- BIO_ADDRINFO *res = NULL;
- int ret = 0;
-
- if (BIO_sock_init() != 1)
- return 0; /* don't generate another error code here */
-
- if (BIO_lookup(str, NULL, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) {
- size_t l;
-
- if (BIO_ADDRINFO_family(res) != AF_INET) {
- BIOerr(BIO_F_BIO_GET_HOST_IP,
- BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
- } else if (BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), NULL, &l)) {
- /*
- * Because only AF_INET addresses will reach this far, we can assert
- * that l should be 4
- */
- if (ossl_assert(l == 4))
- ret = BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), ip, &l);
- }
- BIO_ADDRINFO_free(res);
- } else {
- ERR_add_error_data(2, "host=", str);
- }
-
- return ret;
-}
-
-int BIO_get_port(const char *str, unsigned short *port_ptr)
-{
- BIO_ADDRINFO *res = NULL;
- int ret = 0;
-
- if (str == NULL) {
- BIOerr(BIO_F_BIO_GET_PORT, BIO_R_NO_PORT_DEFINED);
- return 0;
- }
-
- if (BIO_sock_init() != 1)
- return 0; /* don't generate another error code here */
-
- if (BIO_lookup(NULL, str, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) {
- if (BIO_ADDRINFO_family(res) != AF_INET) {
- BIOerr(BIO_F_BIO_GET_PORT,
- BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET);
- } else {
- *port_ptr = ntohs(BIO_ADDR_rawport(BIO_ADDRINFO_address(res)));
- ret = 1;
- }
- BIO_ADDRINFO_free(res);
- } else {
- ERR_add_error_data(2, "host=", str);
- }
-
- return ret;
-}
-# endif
-
-int BIO_sock_error(int sock)
-{
- int j = 0, i;
- socklen_t size = sizeof(j);
-
- /*
- * Note: under Windows the third parameter is of type (char *) whereas
- * under other systems it is (void *) if you don't have a cast it will
- * choke the compiler: if you do have a cast then you can either go for
- * (char *) or (void *).
- */
- i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, &size);
- if (i < 0)
- return get_last_socket_error();
- else
- return j;
-}
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-struct hostent *BIO_gethostbyname(const char *name)
-{
- /*
- * Caching gethostbyname() results forever is wrong, so we have to let
- * the true gethostbyname() worry about this
- */
- return gethostbyname(name);
-}
-# endif
-
-int BIO_sock_init(void)
-{
-# ifdef OPENSSL_SYS_WINDOWS
- static struct WSAData wsa_state;
-
- if (!wsa_init_done) {
- int err;
-
- wsa_init_done = 1;
- memset(&wsa_state, 0, sizeof(wsa_state));
- /*
- * Not making wsa_state available to the rest of the code is formally
- * wrong. But the structures we use are [believed to be] invariable
- * among Winsock DLLs, while API availability is [expected to be]
- * probed at run-time with DSO_global_lookup.
- */
- if (WSAStartup(0x0202, &wsa_state) != 0) {
- err = WSAGetLastError();
- SYSerr(SYS_F_WSASTARTUP, err);
- BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP);
- return -1;
- }
- }
-# endif /* OPENSSL_SYS_WINDOWS */
-# ifdef WATT32
- extern int _watt_do_exit;
- _watt_do_exit = 0; /* don't make sock_init() call exit() */
- if (sock_init())
- return -1;
-# endif
-
- return 1;
-}
-
-void bio_sock_cleanup_int(void)
-{
-# ifdef OPENSSL_SYS_WINDOWS
- if (wsa_init_done) {
- wsa_init_done = 0;
- WSACleanup();
- }
-# endif
-}
-
-int BIO_socket_ioctl(int fd, long type, void *arg)
-{
- int i;
-
-# ifdef __DJGPP__
- i = ioctlsocket(fd, type, (char *)arg);
-# else
-# if defined(OPENSSL_SYS_VMS)
- /*-
- * 2011-02-18 SMS.
- * VMS ioctl() can't tolerate a 64-bit "void *arg", but we
- * observe that all the consumers pass in an "unsigned long *",
- * so we arrange a local copy with a short pointer, and use
- * that, instead.
- */
-# if __INITIAL_POINTER_SIZE == 64
-# define ARG arg_32p
-# pragma pointer_size save
-# pragma pointer_size 32
- unsigned long arg_32;
- unsigned long *arg_32p;
-# pragma pointer_size restore
- arg_32p = &arg_32;
- arg_32 = *((unsigned long *)arg);
-# else /* __INITIAL_POINTER_SIZE == 64 */
-# define ARG arg
-# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
-# else /* defined(OPENSSL_SYS_VMS) */
-# define ARG arg
-# endif /* defined(OPENSSL_SYS_VMS) [else] */
-
- i = ioctlsocket(fd, type, ARG);
-# endif /* __DJGPP__ */
- if (i < 0)
- SYSerr(SYS_F_IOCTLSOCKET, get_last_socket_error());
- return i;
-}
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-int BIO_get_accept_socket(char *host, int bind_mode)
-{
- int s = INVALID_SOCKET;
- char *h = NULL, *p = NULL;
- BIO_ADDRINFO *res = NULL;
-
- if (!BIO_parse_hostserv(host, &h, &p, BIO_PARSE_PRIO_SERV))
- return INVALID_SOCKET;
-
- if (BIO_sock_init() != 1)
- return INVALID_SOCKET;
-
- if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0)
- goto err;
-
- if ((s = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res),
- BIO_ADDRINFO_protocol(res), 0)) == INVALID_SOCKET) {
- s = INVALID_SOCKET;
- goto err;
- }
-
- if (!BIO_listen(s, BIO_ADDRINFO_address(res),
- bind_mode ? BIO_SOCK_REUSEADDR : 0)) {
- BIO_closesocket(s);
- s = INVALID_SOCKET;
- }
-
- err:
- BIO_ADDRINFO_free(res);
- OPENSSL_free(h);
- OPENSSL_free(p);
-
- return s;
-}
-
-int BIO_accept(int sock, char **ip_port)
-{
- BIO_ADDR res;
- int ret = -1;
-
- ret = BIO_accept_ex(sock, &res, 0);
- if (ret == (int)INVALID_SOCKET) {
- if (BIO_sock_should_retry(ret)) {
- ret = -2;
- goto end;
- }
- SYSerr(SYS_F_ACCEPT, get_last_socket_error());
- BIOerr(BIO_F_BIO_ACCEPT, BIO_R_ACCEPT_ERROR);
- goto end;
- }
-
- if (ip_port != NULL) {
- char *host = BIO_ADDR_hostname_string(&res, 1);
- char *port = BIO_ADDR_service_string(&res, 1);
- if (host != NULL && port != NULL)
- *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2);
- else
- *ip_port = NULL;
-
- if (*ip_port == NULL) {
- BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE);
- BIO_closesocket(ret);
- ret = (int)INVALID_SOCKET;
- } else {
- strcpy(*ip_port, host);
- strcat(*ip_port, ":");
- strcat(*ip_port, port);
- }
- OPENSSL_free(host);
- OPENSSL_free(port);
- }
-
- end:
- return ret;
-}
-# endif
-
-int BIO_set_tcp_ndelay(int s, int on)
-{
- int ret = 0;
-# if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
- int opt;
-
-# ifdef SOL_TCP
- opt = SOL_TCP;
-# else
-# ifdef IPPROTO_TCP
- opt = IPPROTO_TCP;
-# endif
-# endif
-
- ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on));
-# endif
- return (ret == 0);
-}
-
-int BIO_socket_nbio(int s, int mode)
-{
- int ret = -1;
- int l;
-
- l = mode;
-# ifdef FIONBIO
- l = mode;
-
- ret = BIO_socket_ioctl(s, FIONBIO, &l);
-# elif defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(FNDELAY))
- /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
-
- l = fcntl(s, F_GETFL, 0);
- if (l == -1) {
- SYSerr(SYS_F_FCNTL, get_last_sys_error());
- ret = -1;
- } else {
-# if defined(O_NONBLOCK)
- l &= ~O_NONBLOCK;
-# else
- l &= ~FNDELAY; /* BSD4.x */
-# endif
- if (mode) {
-# if defined(O_NONBLOCK)
- l |= O_NONBLOCK;
-# else
- l |= FNDELAY; /* BSD4.x */
-# endif
- }
- ret = fcntl(s, F_SETFL, l);
-
- if (ret < 0) {
- SYSerr(SYS_F_FCNTL, get_last_sys_error());
- }
- }
-# else
- /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
- BIOerr(BIO_F_BIO_SOCKET_NBIO, ERR_R_PASSED_INVALID_ARGUMENT);
-# endif
-
- return (ret == 0);
-}
-
-int BIO_sock_info(int sock,
- enum BIO_sock_info_type type, union BIO_sock_info_u *info)
-{
- switch (type) {
- case BIO_SOCK_INFO_ADDRESS:
- {
- socklen_t addr_len;
- int ret = 0;
- addr_len = sizeof(*info->addr);
- ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr),
- &addr_len);
- if (ret == -1) {
- SYSerr(SYS_F_GETSOCKNAME, get_last_socket_error());
- BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_ERROR);
- return 0;
- }
- if ((size_t)addr_len > sizeof(*info->addr)) {
- BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS);
- return 0;
- }
- }
- break;
- default:
- BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_UNKNOWN_INFO_TYPE);
- return 0;
- }
- return 1;
-}
-
-#endif
diff --git a/crypto/bio/b_sock2.c b/crypto/bio/b_sock2.c
deleted file mode 100644
index 104ff31b0d2e..000000000000
--- a/crypto/bio/b_sock2.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include "bio_local.h"
-
-#include <openssl/err.h>
-
-#ifndef OPENSSL_NO_SOCK
-# ifdef SO_MAXCONN
-# define MAX_LISTEN SO_MAXCONN
-# elif defined(SOMAXCONN)
-# define MAX_LISTEN SOMAXCONN
-# else
-# define MAX_LISTEN 32
-# endif
-
-/*-
- * BIO_socket - create a socket
- * @domain: the socket domain (AF_INET, AF_INET6, AF_UNIX, ...)
- * @socktype: the socket type (SOCK_STEAM, SOCK_DGRAM)
- * @protocol: the protocol to use (IPPROTO_TCP, IPPROTO_UDP)
- * @options: BIO socket options (currently unused)
- *
- * Creates a socket. This should be called before calling any
- * of BIO_connect and BIO_listen.
- *
- * Returns the file descriptor on success or INVALID_SOCKET on failure. On
- * failure errno is set, and a status is added to the OpenSSL error stack.
- */
-int BIO_socket(int domain, int socktype, int protocol, int options)
-{
- int sock = -1;
-
- if (BIO_sock_init() != 1)
- return INVALID_SOCKET;
-
- sock = socket(domain, socktype, protocol);
- if (sock == -1) {
- SYSerr(SYS_F_SOCKET, get_last_socket_error());
- BIOerr(BIO_F_BIO_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET);
- return INVALID_SOCKET;
- }
-
- return sock;
-}
-
-/*-
- * BIO_connect - connect to an address
- * @sock: the socket to connect with
- * @addr: the address to connect to
- * @options: BIO socket options
- *
- * Connects to the address using the given socket and options.
- *
- * Options can be a combination of the following:
- * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
- * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
- * - BIO_SOCK_NODELAY: don't delay small messages.
- *
- * options holds BIO socket options that can be used
- * You should call this for every address returned by BIO_lookup
- * until the connection is successful.
- *
- * Returns 1 on success or 0 on failure. On failure errno is set
- * and an error status is added to the OpenSSL error stack.
- */
-int BIO_connect(int sock, const BIO_ADDR *addr, int options)
-{
- const int on = 1;
-
- if (sock == -1) {
- BIOerr(BIO_F_BIO_CONNECT, BIO_R_INVALID_SOCKET);
- return 0;
- }
-
- if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
- return 0;
-
- if (options & BIO_SOCK_KEEPALIVE) {
- if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
- (const void *)&on, sizeof(on)) != 0) {
- SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
- BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_KEEPALIVE);
- return 0;
- }
- }
-
- if (options & BIO_SOCK_NODELAY) {
- if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
- (const void *)&on, sizeof(on)) != 0) {
- SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
- BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_NODELAY);
- return 0;
- }
- }
-
- if (connect(sock, BIO_ADDR_sockaddr(addr),
- BIO_ADDR_sockaddr_size(addr)) == -1) {
- if (!BIO_sock_should_retry(-1)) {
- SYSerr(SYS_F_CONNECT, get_last_socket_error());
- BIOerr(BIO_F_BIO_CONNECT, BIO_R_CONNECT_ERROR);
- }
- return 0;
- }
- return 1;
-}
-
-/*-
- * BIO_bind - bind socket to address
- * @sock: the socket to set
- * @addr: local address to bind to
- * @options: BIO socket options
- *
- * Binds to the address using the given socket and options.
- *
- * Options can be a combination of the following:
- * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
- * for a recently closed port.
- *
- * When restarting the program it could be that the port is still in use. If
- * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
- * It's recommended that you use this.
- */
-int BIO_bind(int sock, const BIO_ADDR *addr, int options)
-{
-# ifndef OPENSSL_SYS_WINDOWS
- int on = 1;
-# endif
-
- if (sock == -1) {
- BIOerr(BIO_F_BIO_BIND, BIO_R_INVALID_SOCKET);
- return 0;
- }
-
-# ifndef OPENSSL_SYS_WINDOWS
- /*
- * SO_REUSEADDR has different behavior on Windows than on
- * other operating systems, don't set it there.
- */
- if (options & BIO_SOCK_REUSEADDR) {
- if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
- (const void *)&on, sizeof(on)) != 0) {
- SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
- BIOerr(BIO_F_BIO_BIND, BIO_R_UNABLE_TO_REUSEADDR);
- return 0;
- }
- }
-# endif
-
- if (bind(sock, BIO_ADDR_sockaddr(addr), BIO_ADDR_sockaddr_size(addr)) != 0) {
- SYSerr(SYS_F_BIND, get_last_socket_error());
- BIOerr(BIO_F_BIO_BIND, BIO_R_UNABLE_TO_BIND_SOCKET);
- return 0;
- }
-
- return 1;
-}
-
-/*-
- * BIO_listen - Creates a listen socket
- * @sock: the socket to listen with
- * @addr: local address to bind to
- * @options: BIO socket options
- *
- * Binds to the address using the given socket and options, then
- * starts listening for incoming connections.
- *
- * Options can be a combination of the following:
- * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
- * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
- * - BIO_SOCK_NODELAY: don't delay small messages.
- * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
- * for a recently closed port.
- * - BIO_SOCK_V6_ONLY: When creating an IPv6 socket, make it listen only
- * for IPv6 addresses and not IPv4 addresses mapped to IPv6.
- *
- * It's recommended that you set up both an IPv6 and IPv4 listen socket, and
- * then check both for new clients that connect to it. You want to set up
- * the socket as non-blocking in that case since else it could hang.
- *
- * Not all operating systems support IPv4 addresses on an IPv6 socket, and for
- * others it's an option. If you pass the BIO_LISTEN_V6_ONLY it will try to
- * create the IPv6 sockets to only listen for IPv6 connection.
- *
- * It could be that the first BIO_listen() call will listen to all the IPv6
- * and IPv4 addresses and that then trying to bind to the IPv4 address will
- * fail. We can't tell the difference between already listening ourself to
- * it and someone else listening to it when failing and errno is EADDRINUSE, so
- * it's recommended to not give an error in that case if the first call was
- * successful.
- *
- * When restarting the program it could be that the port is still in use. If
- * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
- * It's recommended that you use this.
- */
-int BIO_listen(int sock, const BIO_ADDR *addr, int options)
-{
- int on = 1;
- int socktype;
- socklen_t socktype_len = sizeof(socktype);
-
- if (sock == -1) {
- BIOerr(BIO_F_BIO_LISTEN, BIO_R_INVALID_SOCKET);
- return 0;
- }
-
- if (getsockopt(sock, SOL_SOCKET, SO_TYPE,
- (void *)&socktype, &socktype_len) != 0
- || socktype_len != sizeof(socktype)) {
- SYSerr(SYS_F_GETSOCKOPT, get_last_socket_error());
- BIOerr(BIO_F_BIO_LISTEN, BIO_R_GETTING_SOCKTYPE);
- return 0;
- }
-
- if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
- return 0;
-
- if (options & BIO_SOCK_KEEPALIVE) {
- if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
- (const void *)&on, sizeof(on)) != 0) {
- SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
- BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_KEEPALIVE);
- return 0;
- }
- }
-
- if (options & BIO_SOCK_NODELAY) {
- if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
- (const void *)&on, sizeof(on)) != 0) {
- SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
- BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_NODELAY);
- return 0;
- }
- }
-
- /* On OpenBSD it is always ipv6 only with ipv6 sockets thus read-only */
-# if defined(IPV6_V6ONLY) && !defined(__OpenBSD__)
- if (BIO_ADDR_family(addr) == AF_INET6) {
- /*
- * Note: Windows default of IPV6_V6ONLY is ON, and Linux is OFF.
- * Therefore we always have to use setsockopt here.
- */
- on = options & BIO_SOCK_V6_ONLY ? 1 : 0;
- if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
- (const void *)&on, sizeof(on)) != 0) {
- SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
- BIOerr(BIO_F_BIO_LISTEN, BIO_R_LISTEN_V6_ONLY);
- return 0;
- }
- }
-# endif
-
- if (!BIO_bind(sock, addr, options))
- return 0;
-
- if (socktype != SOCK_DGRAM && listen(sock, MAX_LISTEN) == -1) {
- SYSerr(SYS_F_LISTEN, get_last_socket_error());
- BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_LISTEN_SOCKET);
- return 0;
- }
-
- return 1;
-}
-
-/*-
- * BIO_accept_ex - Accept new incoming connections
- * @sock: the listening socket
- * @addr: the BIO_ADDR to store the peer address in
- * @options: BIO socket options, applied on the accepted socket.
- *
- */
-int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options)
-{
- socklen_t len;
- int accepted_sock;
- BIO_ADDR locaddr;
- BIO_ADDR *addr = addr_ == NULL ? &locaddr : addr_;
-
- len = sizeof(*addr);
- accepted_sock = accept(accept_sock,
- BIO_ADDR_sockaddr_noconst(addr), &len);
- if (accepted_sock == -1) {
- if (!BIO_sock_should_retry(accepted_sock)) {
- SYSerr(SYS_F_ACCEPT, get_last_socket_error());
- BIOerr(BIO_F_BIO_ACCEPT_EX, BIO_R_ACCEPT_ERROR);
- }
- return INVALID_SOCKET;
- }
-
- if (!BIO_socket_nbio(accepted_sock, (options & BIO_SOCK_NONBLOCK) != 0)) {
- closesocket(accepted_sock);
- return INVALID_SOCKET;
- }
-
- return accepted_sock;
-}
-
-/*-
- * BIO_closesocket - Close a socket
- * @sock: the socket to close
- */
-int BIO_closesocket(int sock)
-{
- if (closesocket(sock) < 0)
- return 0;
- return 1;
-}
-#endif
diff --git a/crypto/bio/bf_buff.c b/crypto/bio/bf_buff.c
index 51ae1f918d87..53bd02fe1416 100644
--- a/crypto/bio/bf_buff.c
+++ b/crypto/bio/bf_buff.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -25,10 +25,8 @@ static long buffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
static const BIO_METHOD methods_buffer = {
BIO_TYPE_BUFFER,
"buffer",
- /* TODO: Convert to new style write function */
bwrite_conv,
buffer_write,
- /* TODO: Convert to new style read function */
bread_conv,
buffer_read,
buffer_puts,
@@ -289,7 +287,9 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr)
break;
case BIO_C_SET_BUFF_READ_DATA:
if (num > ctx->ibuf_size) {
- p1 = OPENSSL_malloc((int)num);
+ if (num <= 0)
+ return 0;
+ p1 = OPENSSL_malloc((size_t)num);
if (p1 == NULL)
goto malloc_error;
OPENSSL_free(ctx->ibuf);
@@ -318,12 +318,14 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr)
p1 = ctx->ibuf;
p2 = ctx->obuf;
if ((ibs > DEFAULT_BUFFER_SIZE) && (ibs != ctx->ibuf_size)) {
- p1 = OPENSSL_malloc((int)num);
+ if (num <= 0)
+ return 0;
+ p1 = OPENSSL_malloc((size_t)num);
if (p1 == NULL)
goto malloc_error;
}
if ((obs > DEFAULT_BUFFER_SIZE) && (obs != ctx->obuf_size)) {
- p2 = OPENSSL_malloc((int)num);
+ p2 = OPENSSL_malloc((size_t)num);
if (p2 == NULL) {
if (p1 != ctx->ibuf)
OPENSSL_free(p1);
@@ -381,8 +383,8 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr)
break;
case BIO_CTRL_DUP:
dbio = (BIO *)ptr;
- if (!BIO_set_read_buffer_size(dbio, ctx->ibuf_size) ||
- !BIO_set_write_buffer_size(dbio, ctx->obuf_size))
+ if (BIO_set_read_buffer_size(dbio, ctx->ibuf_size) <= 0 ||
+ BIO_set_write_buffer_size(dbio, ctx->obuf_size) <= 0)
ret = 0;
break;
case BIO_CTRL_PEEK:
@@ -404,22 +406,15 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr)
}
return ret;
malloc_error:
- BIOerr(BIO_F_BUFFER_CTRL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
static long buffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
- long ret = 1;
-
if (b->next_bio == NULL)
return 0;
- switch (cmd) {
- default:
- ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
- break;
- }
- return ret;
+ return BIO_callback_ctrl(b->next_bio, cmd, fp);
}
static int buffer_gets(BIO *b, char *buf, int size)
diff --git a/crypto/bio/bf_lbuf.c b/crypto/bio/bf_lbuf.c
index 72f9901813ea..6908e64d3652 100644
--- a/crypto/bio/bf_lbuf.c
+++ b/crypto/bio/bf_lbuf.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -30,10 +30,8 @@ static long linebuffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
static const BIO_METHOD methods_linebuffer = {
BIO_TYPE_LINEBUFFER,
"linebuffer",
- /* TODO: Convert to new style write function */
bwrite_conv,
linebuffer_write,
- /* TODO: Convert to new style read function */
bread_conv,
linebuffer_read,
linebuffer_puts,
@@ -60,12 +58,12 @@ static int linebuffer_new(BIO *bi)
BIO_LINEBUFFER_CTX *ctx;
if ((ctx = OPENSSL_malloc(sizeof(*ctx))) == NULL) {
- BIOerr(BIO_F_LINEBUFFER_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
ctx->obuf = OPENSSL_malloc(DEFAULT_LINEBUFFER_SIZE);
if (ctx->obuf == NULL) {
- BIOerr(BIO_F_LINEBUFFER_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ctx);
return 0;
}
@@ -232,10 +230,12 @@ static long linebuffer_ctrl(BIO *b, int cmd, long num, void *ptr)
}
break;
case BIO_C_SET_BUFF_SIZE:
+ if (num > INT_MAX)
+ return 0;
obs = (int)num;
p = ctx->obuf;
if ((obs > DEFAULT_LINEBUFFER_SIZE) && (obs != ctx->obuf_size)) {
- p = OPENSSL_malloc((int)num);
+ p = OPENSSL_malloc((size_t)obs);
if (p == NULL)
goto malloc_error;
}
@@ -284,7 +284,7 @@ static long linebuffer_ctrl(BIO *b, int cmd, long num, void *ptr)
break;
case BIO_CTRL_DUP:
dbio = (BIO *)ptr;
- if (!BIO_set_write_buffer_size(dbio, ctx->obuf_size))
+ if (BIO_set_write_buffer_size(dbio, ctx->obuf_size) <= 0)
ret = 0;
break;
default:
@@ -295,22 +295,15 @@ static long linebuffer_ctrl(BIO *b, int cmd, long num, void *ptr)
}
return ret;
malloc_error:
- BIOerr(BIO_F_LINEBUFFER_CTRL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
static long linebuffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
- long ret = 1;
-
if (b->next_bio == NULL)
return 0;
- switch (cmd) {
- default:
- ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
- break;
- }
- return ret;
+ return BIO_callback_ctrl(b->next_bio, cmd, fp);
}
static int linebuffer_gets(BIO *b, char *buf, int size)
diff --git a/crypto/bio/bf_nbio.c b/crypto/bio/bf_nbio.c
index dd7011ab669f..f9ea1730ba31 100644
--- a/crypto/bio/bf_nbio.c
+++ b/crypto/bio/bf_nbio.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -34,10 +34,8 @@ typedef struct nbio_test_st {
static const BIO_METHOD methods_nbiof = {
BIO_TYPE_NBIO_TEST,
"non-blocking IO test filter",
- /* TODO: Convert to new style write function */
bwrite_conv,
nbiof_write,
- /* TODO: Convert to new style read function */
bread_conv,
nbiof_read,
nbiof_puts,
@@ -58,7 +56,7 @@ static int nbiof_new(BIO *bi)
NBIO_TEST *nt;
if ((nt = OPENSSL_zalloc(sizeof(*nt))) == NULL) {
- BIOerr(BIO_F_NBIOF_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
nt->lrn = -1;
@@ -173,16 +171,9 @@ static long nbiof_ctrl(BIO *b, int cmd, long num, void *ptr)
static long nbiof_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
- long ret = 1;
-
if (b->next_bio == NULL)
return 0;
- switch (cmd) {
- default:
- ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
- break;
- }
- return ret;
+ return BIO_callback_ctrl(b->next_bio, cmd, fp);
}
static int nbiof_gets(BIO *bp, char *buf, int size)
diff --git a/crypto/bio/bf_null.c b/crypto/bio/bf_null.c
index 48c6be692a5d..7add76a4ca5c 100644
--- a/crypto/bio/bf_null.c
+++ b/crypto/bio/bf_null.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -25,10 +25,8 @@ static long nullf_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
static const BIO_METHOD methods_nullf = {
BIO_TYPE_NULL_FILTER,
"NULL filter",
- /* TODO: Convert to new style write function */
bwrite_conv,
nullf_write,
- /* TODO: Convert to new style read function */
bread_conv,
nullf_read,
nullf_puts,
@@ -95,16 +93,9 @@ static long nullf_ctrl(BIO *b, int cmd, long num, void *ptr)
static long nullf_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
- long ret = 1;
-
if (b->next_bio == NULL)
return 0;
- switch (cmd) {
- default:
- ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
- break;
- }
- return ret;
+ return BIO_callback_ctrl(b->next_bio, cmd, fp);
}
static int nullf_gets(BIO *bp, char *buf, int size)
diff --git a/crypto/bio/bf_prefix.c b/crypto/bio/bf_prefix.c
new file mode 100644
index 000000000000..872efa13b559
--- /dev/null
+++ b/crypto/bio/bf_prefix.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "bio_local.h"
+
+static int prefix_write(BIO *b, const char *out, size_t outl,
+ size_t *numwritten);
+static int prefix_read(BIO *b, char *buf, size_t size, size_t *numread);
+static int prefix_puts(BIO *b, const char *str);
+static int prefix_gets(BIO *b, char *str, int size);
+static long prefix_ctrl(BIO *b, int cmd, long arg1, void *arg2);
+static int prefix_create(BIO *b);
+static int prefix_destroy(BIO *b);
+static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp);
+
+static const BIO_METHOD prefix_meth = {
+ BIO_TYPE_BUFFER,
+ "prefix",
+ prefix_write,
+ NULL,
+ prefix_read,
+ NULL,
+ prefix_puts,
+ prefix_gets,
+ prefix_ctrl,
+ prefix_create,
+ prefix_destroy,
+ prefix_callback_ctrl,
+};
+
+const BIO_METHOD *BIO_f_prefix(void)
+{
+ return &prefix_meth;
+}
+
+typedef struct prefix_ctx_st {
+ char *prefix; /* Text prefix, given by user */
+ unsigned int indent; /* Indentation amount, given by user */
+
+ int linestart; /* flag to indicate we're at the line start */
+} PREFIX_CTX;
+
+static int prefix_create(BIO *b)
+{
+ PREFIX_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx == NULL)
+ return 0;
+
+ ctx->prefix = NULL;
+ ctx->indent = 0;
+ ctx->linestart = 1;
+ BIO_set_data(b, ctx);
+ BIO_set_init(b, 1);
+ return 1;
+}
+
+static int prefix_destroy(BIO *b)
+{
+ PREFIX_CTX *ctx = BIO_get_data(b);
+
+ OPENSSL_free(ctx->prefix);
+ OPENSSL_free(ctx);
+ return 1;
+}
+
+static int prefix_read(BIO *b, char *in, size_t size, size_t *numread)
+{
+ return BIO_read_ex(BIO_next(b), in, size, numread);
+}
+
+static int prefix_write(BIO *b, const char *out, size_t outl,
+ size_t *numwritten)
+{
+ PREFIX_CTX *ctx = BIO_get_data(b);
+
+ if (ctx == NULL)
+ return 0;
+
+ /*
+ * If no prefix is set or if it's empty, and no indentation amount is set,
+ * we've got nothing to do here
+ */
+ if ((ctx->prefix == NULL || *ctx->prefix == '\0')
+ && ctx->indent == 0) {
+ /*
+ * We do note if what comes next will be a new line, though, so we're
+ * prepared to handle prefix and indentation the next time around.
+ */
+ if (outl > 0)
+ ctx->linestart = (out[outl-1] == '\n');
+ return BIO_write_ex(BIO_next(b), out, outl, numwritten);
+ }
+
+ *numwritten = 0;
+
+ while (outl > 0) {
+ size_t i;
+ char c;
+
+ /*
+ * If we know that we're at the start of the line, output prefix and
+ * indentation.
+ */
+ if (ctx->linestart) {
+ size_t dontcare;
+
+ if (ctx->prefix != NULL
+ && !BIO_write_ex(BIO_next(b), ctx->prefix, strlen(ctx->prefix),
+ &dontcare))
+ return 0;
+ BIO_printf(BIO_next(b), "%*s", ctx->indent, "");
+ ctx->linestart = 0;
+ }
+
+ /* Now, go look for the next LF, or the end of the string */
+ for (i = 0, c = '\0'; i < outl && (c = out[i]) != '\n'; i++)
+ continue;
+ if (c == '\n')
+ i++;
+
+ /* Output what we found so far */
+ while (i > 0) {
+ size_t num = 0;
+
+ if (!BIO_write_ex(BIO_next(b), out, i, &num))
+ return 0;
+ out += num;
+ outl -= num;
+ *numwritten += num;
+ i -= num;
+ }
+
+ /* If we found a LF, what follows is a new line, so take note */
+ if (c == '\n')
+ ctx->linestart = 1;
+ }
+
+ return 1;
+}
+
+static long prefix_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+ long ret = 0;
+ PREFIX_CTX *ctx;
+
+ if (b == NULL || (ctx = BIO_get_data(b)) == NULL)
+ return -1;
+
+ switch (cmd) {
+ case BIO_CTRL_SET_PREFIX:
+ OPENSSL_free(ctx->prefix);
+ if (ptr == NULL) {
+ ctx->prefix = NULL;
+ ret = 1;
+ } else {
+ ctx->prefix = OPENSSL_strdup((const char *)ptr);
+ ret = ctx->prefix != NULL;
+ }
+ break;
+ case BIO_CTRL_SET_INDENT:
+ if (num >= 0) {
+ ctx->indent = (unsigned int)num;
+ ret = 1;
+ }
+ break;
+ case BIO_CTRL_GET_INDENT:
+ ret = (long)ctx->indent;
+ break;
+ default:
+ /* Commands that we intercept before passing them along */
+ switch (cmd) {
+ case BIO_C_FILE_SEEK:
+ case BIO_CTRL_RESET:
+ ctx->linestart = 1;
+ break;
+ }
+ if (BIO_next(b) != NULL)
+ ret = BIO_ctrl(BIO_next(b), cmd, num, ptr);
+ break;
+ }
+ return ret;
+}
+
+static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
+{
+ return BIO_callback_ctrl(BIO_next(b), cmd, fp);
+}
+
+static int prefix_gets(BIO *b, char *buf, int size)
+{
+ return BIO_gets(BIO_next(b), buf, size);
+}
+
+static int prefix_puts(BIO *b, const char *str)
+{
+ return BIO_write(b, str, strlen(str));
+}
diff --git a/crypto/bio/bf_readbuff.c b/crypto/bio/bf_readbuff.c
new file mode 100644
index 000000000000..135ccef83bf3
--- /dev/null
+++ b/crypto/bio/bf_readbuff.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This is a read only BIO filter that can be used to add BIO_tell() and
+ * BIO_seek() support to source/sink BIO's (such as a file BIO that uses stdin).
+ * It does this by caching ALL data read from the BIO source/sink into a
+ * resizable memory buffer.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include "bio_local.h"
+#include "internal/cryptlib.h"
+
+#define DEFAULT_BUFFER_SIZE 4096
+
+static int readbuffer_write(BIO *h, const char *buf, int num);
+static int readbuffer_read(BIO *h, char *buf, int size);
+static int readbuffer_puts(BIO *h, const char *str);
+static int readbuffer_gets(BIO *h, char *str, int size);
+static long readbuffer_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int readbuffer_new(BIO *h);
+static int readbuffer_free(BIO *data);
+static long readbuffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
+
+static const BIO_METHOD methods_readbuffer = {
+ BIO_TYPE_BUFFER,
+ "readbuffer",
+ bwrite_conv,
+ readbuffer_write,
+ bread_conv,
+ readbuffer_read,
+ readbuffer_puts,
+ readbuffer_gets,
+ readbuffer_ctrl,
+ readbuffer_new,
+ readbuffer_free,
+ readbuffer_callback_ctrl,
+};
+
+const BIO_METHOD *BIO_f_readbuffer(void)
+{
+ return &methods_readbuffer;
+}
+
+static int readbuffer_new(BIO *bi)
+{
+ BIO_F_BUFFER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx == NULL)
+ return 0;
+ ctx->ibuf_size = DEFAULT_BUFFER_SIZE;
+ ctx->ibuf = OPENSSL_zalloc(DEFAULT_BUFFER_SIZE);
+ if (ctx->ibuf == NULL) {
+ OPENSSL_free(ctx);
+ return 0;
+ }
+
+ bi->init = 1;
+ bi->ptr = (char *)ctx;
+ bi->flags = 0;
+ return 1;
+}
+
+static int readbuffer_free(BIO *a)
+{
+ BIO_F_BUFFER_CTX *b;
+
+ if (a == NULL)
+ return 0;
+ b = (BIO_F_BUFFER_CTX *)a->ptr;
+ OPENSSL_free(b->ibuf);
+ OPENSSL_free(a->ptr);
+ a->ptr = NULL;
+ a->init = 0;
+ a->flags = 0;
+ return 1;
+}
+
+static int readbuffer_resize(BIO_F_BUFFER_CTX *ctx, int sz)
+{
+ char *tmp;
+
+ /* Figure out how many blocks are required */
+ sz += (ctx->ibuf_off + DEFAULT_BUFFER_SIZE - 1);
+ sz = DEFAULT_BUFFER_SIZE * (sz / DEFAULT_BUFFER_SIZE);
+
+ /* Resize if the buffer is not big enough */
+ if (sz > ctx->ibuf_size) {
+ tmp = OPENSSL_realloc(ctx->ibuf, sz);
+ if (tmp == NULL)
+ return 0;
+ ctx->ibuf = tmp;
+ ctx->ibuf_size = sz;
+ }
+ return 1;
+}
+
+static int readbuffer_read(BIO *b, char *out, int outl)
+{
+ int i, num = 0;
+ BIO_F_BUFFER_CTX *ctx;
+
+ if (out == NULL || outl == 0)
+ return 0;
+ ctx = (BIO_F_BUFFER_CTX *)b->ptr;
+
+ if ((ctx == NULL) || (b->next_bio == NULL))
+ return 0;
+ BIO_clear_retry_flags(b);
+
+ for (;;) {
+ i = ctx->ibuf_len;
+ /* If there is something in the buffer just read it. */
+ if (i != 0) {
+ if (i > outl)
+ i = outl;
+ memcpy(out, &(ctx->ibuf[ctx->ibuf_off]), i);
+ ctx->ibuf_off += i;
+ ctx->ibuf_len -= i;
+ num += i;
+ /* Exit if we have read the bytes required out of the buffer */
+ if (outl == i)
+ return num;
+ outl -= i;
+ out += i;
+ }
+
+ /* Only gets here if the buffer has been consumed */
+ if (!readbuffer_resize(ctx, outl))
+ return 0;
+
+ /* Do some buffering by reading from the next bio */
+ i = BIO_read(b->next_bio, ctx->ibuf + ctx->ibuf_off, outl);
+ if (i <= 0) {
+ BIO_copy_next_retry(b);
+ if (i < 0)
+ return ((num > 0) ? num : i);
+ else
+ return num; /* i == 0 */
+ }
+ ctx->ibuf_len = i;
+ }
+}
+
+static int readbuffer_write(BIO *b, const char *in, int inl)
+{
+ return 0;
+}
+static int readbuffer_puts(BIO *b, const char *str)
+{
+ return 0;
+}
+
+static long readbuffer_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+ BIO_F_BUFFER_CTX *ctx;
+ long ret = 1, sz;
+
+ ctx = (BIO_F_BUFFER_CTX *)b->ptr;
+
+ switch (cmd) {
+ case BIO_CTRL_EOF:
+ if (ctx->ibuf_len > 0)
+ return 0;
+ if (b->next_bio == NULL)
+ return 1;
+ ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+ break;
+
+ case BIO_C_FILE_SEEK:
+ case BIO_CTRL_RESET:
+ sz = ctx->ibuf_off + ctx->ibuf_len;
+ /* Assume it can only seek backwards */
+ if (num < 0 || num > sz)
+ return 0;
+ ctx->ibuf_off = num;
+ ctx->ibuf_len = sz - num;
+ break;
+
+ case BIO_C_FILE_TELL:
+ case BIO_CTRL_INFO:
+ ret = (long)ctx->ibuf_off;
+ break;
+ case BIO_CTRL_PENDING:
+ ret = (long)ctx->ibuf_len;
+ if (ret == 0) {
+ if (b->next_bio == NULL)
+ return 0;
+ ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+ }
+ break;
+ case BIO_CTRL_DUP:
+ case BIO_CTRL_FLUSH:
+ ret = 1;
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+static long readbuffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
+{
+ if (b->next_bio == NULL)
+ return 0;
+ return BIO_callback_ctrl(b->next_bio, cmd, fp);
+}
+
+static int readbuffer_gets(BIO *b, char *buf, int size)
+{
+ BIO_F_BUFFER_CTX *ctx;
+ int num = 0, num_chars, found_newline;
+ char *p;
+ int i, j;
+
+ if (size == 0)
+ return 0;
+ --size; /* the passed in size includes the terminator - so remove it here */
+ ctx = (BIO_F_BUFFER_CTX *)b->ptr;
+ BIO_clear_retry_flags(b);
+
+ /* If data is already buffered then use this first */
+ if (ctx->ibuf_len > 0) {
+ p = ctx->ibuf + ctx->ibuf_off;
+ found_newline = 0;
+ for (num_chars = 0;
+ (num_chars < ctx->ibuf_len) && (num_chars < size);
+ num_chars++) {
+ *buf++ = p[num_chars];
+ if (p[num_chars] == '\n') {
+ found_newline = 1;
+ num_chars++;
+ break;
+ }
+ }
+ num += num_chars;
+ size -= num_chars;
+ ctx->ibuf_len -= num_chars;
+ ctx->ibuf_off += num_chars;
+ if (found_newline || size == 0) {
+ *buf = '\0';
+ return num;
+ }
+ }
+ /*
+ * If there is no buffered data left then read any remaining data from the
+ * next bio.
+ */
+
+ /* Resize if we have to */
+ if (!readbuffer_resize(ctx, 1 + size))
+ return 0;
+ /*
+ * Read more data from the next bio using BIO_read_ex:
+ * Note we cannot use BIO_gets() here as it does not work on a
+ * binary stream that contains 0x00. (Since strlen() will stop at
+ * any 0x00 not at the last read '\n' in a FILE bio).
+ * Also note that some applications open and close the file bio
+ * multiple times and need to read the next available block when using
+ * stdin - so we need to READ one byte at a time!
+ */
+ p = ctx->ibuf + ctx->ibuf_off;
+ for (i = 0; i < size; ++i) {
+ j = BIO_read(b->next_bio, p, 1);
+ if (j <= 0) {
+ BIO_copy_next_retry(b);
+ *buf = '\0';
+ return num > 0 ? num : j;
+ }
+ *buf++ = *p;
+ num++;
+ ctx->ibuf_off++;
+ if (*p == '\n')
+ break;
+ ++p;
+ }
+ *buf = '\0';
+ return num;
+}
diff --git a/crypto/bio/bio_addr.c b/crypto/bio/bio_addr.c
new file mode 100644
index 000000000000..a80774bbd7ca
--- /dev/null
+++ b/crypto/bio/bio_addr.c
@@ -0,0 +1,939 @@
+/*
+ * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+/*
+ * VC configurations may define UNICODE, to indicate to the C RTL that
+ * WCHAR functions are preferred.
+ * This affects functions like gai_strerror(), which is implemented as
+ * an alias macro for gai_strerrorA() (which returns a const char *) or
+ * gai_strerrorW() (which returns a const WCHAR *). This source file
+ * assumes POSIX declarations, so prefer the non-UNICODE definitions.
+ */
+#undef UNICODE
+
+#include <assert.h>
+#include <string.h>
+
+#include "bio_local.h"
+#include <openssl/crypto.h>
+
+#ifndef OPENSSL_NO_SOCK
+#include <openssl/err.h>
+#include <openssl/buffer.h>
+#include "internal/thread_once.h"
+
+CRYPTO_RWLOCK *bio_lookup_lock;
+static CRYPTO_ONCE bio_lookup_init = CRYPTO_ONCE_STATIC_INIT;
+
+/*
+ * Throughout this file and bio_local.h, the existence of the macro
+ * AI_PASSIVE is used to detect the availability of struct addrinfo,
+ * getnameinfo() and getaddrinfo(). If that macro doesn't exist,
+ * we use our own implementation instead, using gethostbyname,
+ * getservbyname and a few other.
+ */
+
+/**********************************************************************
+ *
+ * Address structure
+ *
+ */
+
+BIO_ADDR *BIO_ADDR_new(void)
+{
+ BIO_ADDR *ret = OPENSSL_zalloc(sizeof(*ret));
+
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ ret->sa.sa_family = AF_UNSPEC;
+ return ret;
+}
+
+void BIO_ADDR_free(BIO_ADDR *ap)
+{
+ OPENSSL_free(ap);
+}
+
+void BIO_ADDR_clear(BIO_ADDR *ap)
+{
+ memset(ap, 0, sizeof(*ap));
+ ap->sa.sa_family = AF_UNSPEC;
+}
+
+/*
+ * BIO_ADDR_make - non-public routine to fill a BIO_ADDR with the contents
+ * of a struct sockaddr.
+ */
+int BIO_ADDR_make(BIO_ADDR *ap, const struct sockaddr *sa)
+{
+ if (sa->sa_family == AF_INET) {
+ memcpy(&(ap->s_in), sa, sizeof(struct sockaddr_in));
+ return 1;
+ }
+#ifdef AF_INET6
+ if (sa->sa_family == AF_INET6) {
+ memcpy(&(ap->s_in6), sa, sizeof(struct sockaddr_in6));
+ return 1;
+ }
+#endif
+#ifdef AF_UNIX
+ if (sa->sa_family == AF_UNIX) {
+ memcpy(&(ap->s_un), sa, sizeof(struct sockaddr_un));
+ return 1;
+ }
+#endif
+
+ return 0;
+}
+
+int BIO_ADDR_rawmake(BIO_ADDR *ap, int family,
+ const void *where, size_t wherelen,
+ unsigned short port)
+{
+#ifdef AF_UNIX
+ if (family == AF_UNIX) {
+ if (wherelen + 1 > sizeof(ap->s_un.sun_path))
+ return 0;
+ memset(&ap->s_un, 0, sizeof(ap->s_un));
+ ap->s_un.sun_family = family;
+ strncpy(ap->s_un.sun_path, where, sizeof(ap->s_un.sun_path) - 1);
+ return 1;
+ }
+#endif
+ if (family == AF_INET) {
+ if (wherelen != sizeof(struct in_addr))
+ return 0;
+ memset(&ap->s_in, 0, sizeof(ap->s_in));
+ ap->s_in.sin_family = family;
+ ap->s_in.sin_port = port;
+ ap->s_in.sin_addr = *(struct in_addr *)where;
+ return 1;
+ }
+#ifdef AF_INET6
+ if (family == AF_INET6) {
+ if (wherelen != sizeof(struct in6_addr))
+ return 0;
+ memset(&ap->s_in6, 0, sizeof(ap->s_in6));
+ ap->s_in6.sin6_family = family;
+ ap->s_in6.sin6_port = port;
+ ap->s_in6.sin6_addr = *(struct in6_addr *)where;
+ return 1;
+ }
+#endif
+
+ return 0;
+}
+
+int BIO_ADDR_family(const BIO_ADDR *ap)
+{
+ return ap->sa.sa_family;
+}
+
+int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l)
+{
+ size_t len = 0;
+ const void *addrptr = NULL;
+
+ if (ap->sa.sa_family == AF_INET) {
+ len = sizeof(ap->s_in.sin_addr);
+ addrptr = &ap->s_in.sin_addr;
+ }
+#ifdef AF_INET6
+ else if (ap->sa.sa_family == AF_INET6) {
+ len = sizeof(ap->s_in6.sin6_addr);
+ addrptr = &ap->s_in6.sin6_addr;
+ }
+#endif
+#ifdef AF_UNIX
+ else if (ap->sa.sa_family == AF_UNIX) {
+ len = strlen(ap->s_un.sun_path);
+ addrptr = &ap->s_un.sun_path;
+ }
+#endif
+
+ if (addrptr == NULL)
+ return 0;
+
+ if (p != NULL) {
+ memcpy(p, addrptr, len);
+ }
+ if (l != NULL)
+ *l = len;
+
+ return 1;
+}
+
+unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap)
+{
+ if (ap->sa.sa_family == AF_INET)
+ return ap->s_in.sin_port;
+#ifdef AF_INET6
+ if (ap->sa.sa_family == AF_INET6)
+ return ap->s_in6.sin6_port;
+#endif
+ return 0;
+}
+
+/*-
+ * addr_strings - helper function to get host and service names
+ * @ap: the BIO_ADDR that has the input info
+ * @numeric: 0 if actual names should be returned, 1 if the numeric
+ * representation should be returned.
+ * @hostname: a pointer to a pointer to a memory area to store the
+ * host name or numeric representation. Unused if NULL.
+ * @service: a pointer to a pointer to a memory area to store the
+ * service name or numeric representation. Unused if NULL.
+ *
+ * The return value is 0 on failure, with the error code in the error
+ * stack, and 1 on success.
+ */
+static int addr_strings(const BIO_ADDR *ap, int numeric,
+ char **hostname, char **service)
+{
+ if (BIO_sock_init() != 1)
+ return 0;
+
+ if (1) {
+#ifdef AI_PASSIVE
+ int ret = 0;
+ char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = "";
+ int flags = 0;
+
+ if (numeric)
+ flags |= NI_NUMERICHOST | NI_NUMERICSERV;
+
+ if ((ret = getnameinfo(BIO_ADDR_sockaddr(ap),
+ BIO_ADDR_sockaddr_size(ap),
+ host, sizeof(host), serv, sizeof(serv),
+ flags)) != 0) {
+# ifdef EAI_SYSTEM
+ if (ret == EAI_SYSTEM) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling getnameinfo()");
+ } else
+# endif
+ {
+ ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB, gai_strerror(ret));
+ }
+ return 0;
+ }
+
+ /* VMS getnameinfo() has a bug, it doesn't fill in serv, which
+ * leaves it with whatever garbage that happens to be there.
+ * However, we initialise serv with the empty string (serv[0]
+ * is therefore NUL), so it gets real easy to detect when things
+ * didn't go the way one might expect.
+ */
+ if (serv[0] == '\0') {
+ BIO_snprintf(serv, sizeof(serv), "%d",
+ ntohs(BIO_ADDR_rawport(ap)));
+ }
+
+ if (hostname != NULL)
+ *hostname = OPENSSL_strdup(host);
+ if (service != NULL)
+ *service = OPENSSL_strdup(serv);
+ } else {
+#endif
+ if (hostname != NULL)
+ *hostname = OPENSSL_strdup(inet_ntoa(ap->s_in.sin_addr));
+ if (service != NULL) {
+ char serv[6]; /* port is 16 bits => max 5 decimal digits */
+ BIO_snprintf(serv, sizeof(serv), "%d", ntohs(ap->s_in.sin_port));
+ *service = OPENSSL_strdup(serv);
+ }
+ }
+
+ if ((hostname != NULL && *hostname == NULL)
+ || (service != NULL && *service == NULL)) {
+ if (hostname != NULL) {
+ OPENSSL_free(*hostname);
+ *hostname = NULL;
+ }
+ if (service != NULL) {
+ OPENSSL_free(*service);
+ *service = NULL;
+ }
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ return 1;
+}
+
+char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric)
+{
+ char *hostname = NULL;
+
+ if (addr_strings(ap, numeric, &hostname, NULL))
+ return hostname;
+
+ return NULL;
+}
+
+char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric)
+{
+ char *service = NULL;
+
+ if (addr_strings(ap, numeric, NULL, &service))
+ return service;
+
+ return NULL;
+}
+
+char *BIO_ADDR_path_string(const BIO_ADDR *ap)
+{
+#ifdef AF_UNIX
+ if (ap->sa.sa_family == AF_UNIX)
+ return OPENSSL_strdup(ap->s_un.sun_path);
+#endif
+ return NULL;
+}
+
+/*
+ * BIO_ADDR_sockaddr - non-public routine to return the struct sockaddr
+ * for a given BIO_ADDR. In reality, this is simply a type safe cast.
+ * The returned struct sockaddr is const, so it can't be tampered with.
+ */
+const struct sockaddr *BIO_ADDR_sockaddr(const BIO_ADDR *ap)
+{
+ return &(ap->sa);
+}
+
+/*
+ * BIO_ADDR_sockaddr_noconst - non-public function that does the same
+ * as BIO_ADDR_sockaddr, but returns a non-const. USE WITH CARE, as
+ * it allows you to tamper with the data (and thereby the contents
+ * of the input BIO_ADDR).
+ */
+struct sockaddr *BIO_ADDR_sockaddr_noconst(BIO_ADDR *ap)
+{
+ return &(ap->sa);
+}
+
+/*
+ * BIO_ADDR_sockaddr_size - non-public function that returns the size
+ * of the struct sockaddr the BIO_ADDR is using. If the protocol family
+ * isn't set or is something other than AF_INET, AF_INET6 or AF_UNIX,
+ * the size of the BIO_ADDR type is returned.
+ */
+socklen_t BIO_ADDR_sockaddr_size(const BIO_ADDR *ap)
+{
+ if (ap->sa.sa_family == AF_INET)
+ return sizeof(ap->s_in);
+#ifdef AF_INET6
+ if (ap->sa.sa_family == AF_INET6)
+ return sizeof(ap->s_in6);
+#endif
+#ifdef AF_UNIX
+ if (ap->sa.sa_family == AF_UNIX)
+ return sizeof(ap->s_un);
+#endif
+ return sizeof(*ap);
+}
+
+/**********************************************************************
+ *
+ * Address info database
+ *
+ */
+
+const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai)
+{
+ if (bai != NULL)
+ return bai->bai_next;
+ return NULL;
+}
+
+int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai)
+{
+ if (bai != NULL)
+ return bai->bai_family;
+ return 0;
+}
+
+int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai)
+{
+ if (bai != NULL)
+ return bai->bai_socktype;
+ return 0;
+}
+
+int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai)
+{
+ if (bai != NULL) {
+ if (bai->bai_protocol != 0)
+ return bai->bai_protocol;
+
+#ifdef AF_UNIX
+ if (bai->bai_family == AF_UNIX)
+ return 0;
+#endif
+
+ switch (bai->bai_socktype) {
+ case SOCK_STREAM:
+ return IPPROTO_TCP;
+ case SOCK_DGRAM:
+ return IPPROTO_UDP;
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+/*
+ * BIO_ADDRINFO_sockaddr_size - non-public function that returns the size
+ * of the struct sockaddr inside the BIO_ADDRINFO.
+ */
+socklen_t BIO_ADDRINFO_sockaddr_size(const BIO_ADDRINFO *bai)
+{
+ if (bai != NULL)
+ return bai->bai_addrlen;
+ return 0;
+}
+
+/*
+ * BIO_ADDRINFO_sockaddr - non-public function that returns bai_addr
+ * as the struct sockaddr it is.
+ */
+const struct sockaddr *BIO_ADDRINFO_sockaddr(const BIO_ADDRINFO *bai)
+{
+ if (bai != NULL)
+ return bai->bai_addr;
+ return NULL;
+}
+
+const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai)
+{
+ if (bai != NULL)
+ return (BIO_ADDR *)bai->bai_addr;
+ return NULL;
+}
+
+void BIO_ADDRINFO_free(BIO_ADDRINFO *bai)
+{
+ if (bai == NULL)
+ return;
+
+#ifdef AI_PASSIVE
+# ifdef AF_UNIX
+# define _cond bai->bai_family != AF_UNIX
+# else
+# define _cond 1
+# endif
+ if (_cond) {
+ freeaddrinfo(bai);
+ return;
+ }
+#endif
+
+ /* Free manually when we know that addrinfo_wrap() was used.
+ * See further comment above addrinfo_wrap()
+ */
+ while (bai != NULL) {
+ BIO_ADDRINFO *next = bai->bai_next;
+ OPENSSL_free(bai->bai_addr);
+ OPENSSL_free(bai);
+ bai = next;
+ }
+}
+
+/**********************************************************************
+ *
+ * Service functions
+ *
+ */
+
+/*-
+ * The specs in hostserv can take these forms:
+ *
+ * host:service => *host = "host", *service = "service"
+ * host:* => *host = "host", *service = NULL
+ * host: => *host = "host", *service = NULL
+ * :service => *host = NULL, *service = "service"
+ * *:service => *host = NULL, *service = "service"
+ *
+ * in case no : is present in the string, the result depends on
+ * hostserv_prio, as follows:
+ *
+ * when hostserv_prio == BIO_PARSE_PRIO_HOST
+ * host => *host = "host", *service untouched
+ *
+ * when hostserv_prio == BIO_PARSE_PRIO_SERV
+ * service => *host untouched, *service = "service"
+ *
+ */
+int BIO_parse_hostserv(const char *hostserv, char **host, char **service,
+ enum BIO_hostserv_priorities hostserv_prio)
+{
+ const char *h = NULL; size_t hl = 0;
+ const char *p = NULL; size_t pl = 0;
+
+ if (*hostserv == '[') {
+ if ((p = strchr(hostserv, ']')) == NULL)
+ goto spec_err;
+ h = hostserv + 1;
+ hl = p - h;
+ p++;
+ if (*p == '\0')
+ p = NULL;
+ else if (*p != ':')
+ goto spec_err;
+ else {
+ p++;
+ pl = strlen(p);
+ }
+ } else {
+ const char *p2 = strrchr(hostserv, ':');
+ p = strchr(hostserv, ':');
+
+ /*-
+ * Check for more than one colon. There are three possible
+ * interpretations:
+ * 1. IPv6 address with port number, last colon being separator.
+ * 2. IPv6 address only.
+ * 3. IPv6 address only if hostserv_prio == BIO_PARSE_PRIO_HOST,
+ * IPv6 address and port number if hostserv_prio == BIO_PARSE_PRIO_SERV
+ * Because of this ambiguity, we currently choose to make it an
+ * error.
+ */
+ if (p != p2)
+ goto amb_err;
+
+ if (p != NULL) {
+ h = hostserv;
+ hl = p - h;
+ p++;
+ pl = strlen(p);
+ } else if (hostserv_prio == BIO_PARSE_PRIO_HOST) {
+ h = hostserv;
+ hl = strlen(h);
+ } else {
+ p = hostserv;
+ pl = strlen(p);
+ }
+ }
+
+ if (p != NULL && strchr(p, ':'))
+ goto spec_err;
+
+ if (h != NULL && host != NULL) {
+ if (hl == 0
+ || (hl == 1 && h[0] == '*')) {
+ *host = NULL;
+ } else {
+ *host = OPENSSL_strndup(h, hl);
+ if (*host == NULL)
+ goto memerr;
+ }
+ }
+ if (p != NULL && service != NULL) {
+ if (pl == 0
+ || (pl == 1 && p[0] == '*')) {
+ *service = NULL;
+ } else {
+ *service = OPENSSL_strndup(p, pl);
+ if (*service == NULL)
+ goto memerr;
+ }
+ }
+
+ return 1;
+ amb_err:
+ ERR_raise(ERR_LIB_BIO, BIO_R_AMBIGUOUS_HOST_OR_SERVICE);
+ return 0;
+ spec_err:
+ ERR_raise(ERR_LIB_BIO, BIO_R_MALFORMED_HOST_OR_SERVICE);
+ return 0;
+ memerr:
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
+ return 0;
+}
+
+/* addrinfo_wrap is used to build our own addrinfo "chain".
+ * (it has only one entry, so calling it a chain may be a stretch)
+ * It should ONLY be called when getaddrinfo() and friends
+ * aren't available, OR when dealing with a non IP protocol
+ * family, such as AF_UNIX
+ *
+ * the return value is 1 on success, or 0 on failure, which
+ * only happens if a memory allocation error occurred.
+ */
+static int addrinfo_wrap(int family, int socktype,
+ const void *where, size_t wherelen,
+ unsigned short port,
+ BIO_ADDRINFO **bai)
+{
+ if ((*bai = OPENSSL_zalloc(sizeof(**bai))) == NULL) {
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ (*bai)->bai_family = family;
+ (*bai)->bai_socktype = socktype;
+ if (socktype == SOCK_STREAM)
+ (*bai)->bai_protocol = IPPROTO_TCP;
+ if (socktype == SOCK_DGRAM)
+ (*bai)->bai_protocol = IPPROTO_UDP;
+#ifdef AF_UNIX
+ if (family == AF_UNIX)
+ (*bai)->bai_protocol = 0;
+#endif
+ {
+ /* Magic: We know that BIO_ADDR_sockaddr_noconst is really
+ just an advanced cast of BIO_ADDR* to struct sockaddr *
+ by the power of union, so while it may seem that we're
+ creating a memory leak here, we are not. It will be
+ all right. */
+ BIO_ADDR *addr = BIO_ADDR_new();
+ if (addr != NULL) {
+ BIO_ADDR_rawmake(addr, family, where, wherelen, port);
+ (*bai)->bai_addr = BIO_ADDR_sockaddr_noconst(addr);
+ }
+ }
+ (*bai)->bai_next = NULL;
+ if ((*bai)->bai_addr == NULL) {
+ BIO_ADDRINFO_free(*bai);
+ *bai = NULL;
+ return 0;
+ }
+ return 1;
+}
+
+DEFINE_RUN_ONCE_STATIC(do_bio_lookup_init)
+{
+ bio_lookup_lock = CRYPTO_THREAD_lock_new();
+ return bio_lookup_lock != NULL;
+}
+
+int BIO_lookup(const char *host, const char *service,
+ enum BIO_lookup_type lookup_type,
+ int family, int socktype, BIO_ADDRINFO **res)
+{
+ return BIO_lookup_ex(host, service, lookup_type, family, socktype, 0, res);
+}
+
+/*-
+ * BIO_lookup_ex - look up the host and service you want to connect to.
+ * @host: the host (or node, in case family == AF_UNIX) you want to connect to.
+ * @service: the service you want to connect to.
+ * @lookup_type: declare intent with the result, client or server.
+ * @family: the address family you want to use. Use AF_UNSPEC for any, or
+ * AF_INET, AF_INET6 or AF_UNIX.
+ * @socktype: The socket type you want to use. Can be SOCK_STREAM, SOCK_DGRAM
+ * or 0 for all.
+ * @protocol: The protocol to use, e.g. IPPROTO_TCP or IPPROTO_UDP or 0 for all.
+ * Note that some platforms may not return IPPROTO_SCTP without
+ * explicitly requesting it (i.e. IPPROTO_SCTP may not be returned
+ * with 0 for the protocol)
+ * @res: Storage place for the resulting list of returned addresses
+ *
+ * This will do a lookup of the host and service that you want to connect to.
+ * It returns a linked list of different addresses you can try to connect to.
+ *
+ * When no longer needed you should call BIO_ADDRINFO_free() to free the result.
+ *
+ * The return value is 1 on success or 0 in case of error.
+ */
+int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
+ int family, int socktype, int protocol, BIO_ADDRINFO **res)
+{
+ int ret = 0; /* Assume failure */
+
+ switch(family) {
+ case AF_INET:
+#ifdef AF_INET6
+ case AF_INET6:
+#endif
+#ifdef AF_UNIX
+ case AF_UNIX:
+#endif
+#ifdef AF_UNSPEC
+ case AF_UNSPEC:
+#endif
+ break;
+ default:
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY);
+ return 0;
+ }
+
+#ifdef AF_UNIX
+ if (family == AF_UNIX) {
+ if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res))
+ return 1;
+ else
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+#endif
+
+ if (BIO_sock_init() != 1)
+ return 0;
+
+ if (1) {
+#ifdef AI_PASSIVE
+ int gai_ret = 0, old_ret = 0;
+ struct addrinfo hints;
+
+ memset(&hints, 0, sizeof(hints));
+
+ hints.ai_family = family;
+ hints.ai_socktype = socktype;
+ hints.ai_protocol = protocol;
+# ifdef AI_ADDRCONFIG
+# ifdef AF_UNSPEC
+ if (host != NULL && family == AF_UNSPEC)
+# endif
+ hints.ai_flags |= AI_ADDRCONFIG;
+# endif
+
+ if (lookup_type == BIO_LOOKUP_SERVER)
+ hints.ai_flags |= AI_PASSIVE;
+
+ /* Note that |res| SHOULD be a 'struct addrinfo **' thanks to
+ * macro magic in bio_local.h
+ */
+# if defined(AI_ADDRCONFIG) && defined(AI_NUMERICHOST)
+ retry:
+# endif
+ switch ((gai_ret = getaddrinfo(host, service, &hints, res))) {
+# ifdef EAI_SYSTEM
+ case EAI_SYSTEM:
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling getaddrinfo()");
+ ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB);
+ break;
+# endif
+# ifdef EAI_MEMORY
+ case EAI_MEMORY:
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
+ break;
+# endif
+ case 0:
+ ret = 1; /* Success */
+ break;
+ default:
+# if defined(AI_ADDRCONFIG) && defined(AI_NUMERICHOST)
+ if (hints.ai_flags & AI_ADDRCONFIG) {
+ hints.ai_flags &= ~AI_ADDRCONFIG;
+ hints.ai_flags |= AI_NUMERICHOST;
+ old_ret = gai_ret;
+ goto retry;
+ }
+# endif
+ ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB,
+ gai_strerror(old_ret ? old_ret : gai_ret));
+ break;
+ }
+ } else {
+#endif
+ const struct hostent *he;
+/*
+ * Because struct hostent is defined for 32-bit pointers only with
+ * VMS C, we need to make sure that '&he_fallback_address' and
+ * '&he_fallback_addresses' are 32-bit pointers
+ */
+#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
+# pragma pointer_size save
+# pragma pointer_size 32
+#endif
+ /* Windows doesn't seem to have in_addr_t */
+#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
+ static uint32_t he_fallback_address;
+ static const char *he_fallback_addresses[] =
+ { (char *)&he_fallback_address, NULL };
+#else
+ static in_addr_t he_fallback_address;
+ static const char *he_fallback_addresses[] =
+ { (char *)&he_fallback_address, NULL };
+#endif
+ static const struct hostent he_fallback =
+ { NULL, NULL, AF_INET, sizeof(he_fallback_address),
+ (char **)&he_fallback_addresses };
+#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
+# pragma pointer_size restore
+#endif
+
+ struct servent *se;
+ /* Apparently, on WIN64, s_proto and s_port have traded places... */
+#ifdef _WIN64
+ struct servent se_fallback = { NULL, NULL, NULL, 0 };
+#else
+ struct servent se_fallback = { NULL, NULL, 0, NULL };
+#endif
+
+ if (!RUN_ONCE(&bio_lookup_init, do_bio_lookup_init)) {
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
+ ret = 0;
+ goto err;
+ }
+
+ if (!CRYPTO_THREAD_write_lock(bio_lookup_lock)) {
+ ret = 0;
+ goto err;
+ }
+ he_fallback_address = INADDR_ANY;
+ if (host == NULL) {
+ he = &he_fallback;
+ switch(lookup_type) {
+ case BIO_LOOKUP_CLIENT:
+ he_fallback_address = INADDR_LOOPBACK;
+ break;
+ case BIO_LOOKUP_SERVER:
+ he_fallback_address = INADDR_ANY;
+ break;
+ default:
+ /* We forgot to handle a lookup type! */
+ assert("We forgot to handle a lookup type!" == NULL);
+ ERR_raise(ERR_LIB_BIO, ERR_R_INTERNAL_ERROR);
+ ret = 0;
+ goto err;
+ }
+ } else {
+ he = gethostbyname(host);
+
+ if (he == NULL) {
+#ifndef OPENSSL_SYS_WINDOWS
+ /*
+ * This might be misleading, because h_errno is used as if
+ * it was errno. To minimize mixup add 1000. Underlying
+ * reason for this is that hstrerror is declared obsolete,
+ * not to mention that a) h_errno is not always guaranteed
+ * to be meaningless; b) hstrerror can reside in yet another
+ * library, linking for sake of hstrerror is an overkill;
+ * c) this path is not executed on contemporary systems
+ * anyway [above getaddrinfo/gai_strerror is]. We just let
+ * system administrator figure this out...
+ */
+# if defined(OPENSSL_SYS_VXWORKS)
+ /* h_errno doesn't exist on VxWorks */
+ ERR_raise_data(ERR_LIB_SYS, 1000,
+ "calling gethostbyname()");
+# else
+ ERR_raise_data(ERR_LIB_SYS, 1000 + h_errno,
+ "calling gethostbyname()");
+# endif
+#else
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling gethostbyname()");
+#endif
+ ret = 0;
+ goto err;
+ }
+ }
+
+ if (service == NULL) {
+ se_fallback.s_port = 0;
+ se_fallback.s_proto = NULL;
+ se = &se_fallback;
+ } else {
+ char *endp = NULL;
+ long portnum = strtol(service, &endp, 10);
+
+/*
+ * Because struct servent is defined for 32-bit pointers only with
+ * VMS C, we need to make sure that 'proto' is a 32-bit pointer.
+ */
+#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
+# pragma pointer_size save
+# pragma pointer_size 32
+#endif
+ char *proto = NULL;
+#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
+# pragma pointer_size restore
+#endif
+
+ switch (socktype) {
+ case SOCK_STREAM:
+ proto = "tcp";
+ break;
+ case SOCK_DGRAM:
+ proto = "udp";
+ break;
+ }
+
+ if (endp != service && *endp == '\0'
+ && portnum > 0 && portnum < 65536) {
+ se_fallback.s_port = htons((unsigned short)portnum);
+ se_fallback.s_proto = proto;
+ se = &se_fallback;
+ } else if (endp == service) {
+ se = getservbyname(service, proto);
+
+ if (se == NULL) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling getservbyname()");
+ goto err;
+ }
+ } else {
+ ERR_raise(ERR_LIB_BIO, BIO_R_MALFORMED_HOST_OR_SERVICE);
+ goto err;
+ }
+ }
+
+ *res = NULL;
+
+ {
+/*
+ * Because hostent::h_addr_list is an array of 32-bit pointers with VMS C,
+ * we must make sure our iterator designates the same element type, hence
+ * the pointer size dance.
+ */
+#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
+# pragma pointer_size save
+# pragma pointer_size 32
+#endif
+ char **addrlistp;
+#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
+# pragma pointer_size restore
+#endif
+ size_t addresses;
+ BIO_ADDRINFO *tmp_bai = NULL;
+
+ /* The easiest way to create a linked list from an
+ array is to start from the back */
+ for(addrlistp = he->h_addr_list; *addrlistp != NULL;
+ addrlistp++)
+ ;
+
+ for(addresses = addrlistp - he->h_addr_list;
+ addrlistp--, addresses-- > 0; ) {
+ if (!addrinfo_wrap(he->h_addrtype, socktype,
+ *addrlistp, he->h_length,
+ se->s_port, &tmp_bai))
+ goto addrinfo_malloc_err;
+ tmp_bai->bai_next = *res;
+ *res = tmp_bai;
+ continue;
+ addrinfo_malloc_err:
+ BIO_ADDRINFO_free(*res);
+ *res = NULL;
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
+ ret = 0;
+ goto err;
+ }
+
+ ret = 1;
+ }
+ err:
+ CRYPTO_THREAD_unlock(bio_lookup_lock);
+ }
+
+ return ret;
+}
+
+#endif /* OPENSSL_NO_SOCK */
diff --git a/crypto/bio/bio_cb.c b/crypto/bio/bio_cb.c
index a153100a8825..522a05369dc7 100644
--- a/crypto/bio/bio_cb.c
+++ b/crypto/bio/bio_cb.c
@@ -1,12 +1,14 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -14,25 +16,25 @@
#include "internal/cryptlib.h"
#include <openssl/err.h>
-long BIO_debug_callback(BIO *bio, int cmd, const char *argp,
- int argi, long argl, long ret)
+long BIO_debug_callback_ex(BIO *bio, int cmd, const char *argp, size_t len,
+ int argi, long argl, int ret, size_t *processed)
{
BIO *b;
char buf[256];
char *p;
- long r = 1;
- int len, left;
+ int left;
+ size_t l = 0;
- if (BIO_CB_RETURN & cmd)
- r = ret;
+ if (processed != NULL)
+ l = *processed;
- len = BIO_snprintf(buf, sizeof(buf), "BIO[%p]: ", (void *)bio);
+ left = BIO_snprintf(buf, sizeof(buf), "BIO[%p]: ", (void *)bio);
/* Ignore errors and continue printing the other information. */
- if (len < 0)
- len = 0;
- p = buf + len;
- left = sizeof(buf) - len;
+ if (left < 0)
+ left = 0;
+ p = buf + left;
+ left = sizeof(buf) - left;
switch (cmd) {
case BIO_CB_FREE:
@@ -40,47 +42,47 @@ long BIO_debug_callback(BIO *bio, int cmd, const char *argp,
break;
case BIO_CB_READ:
if (bio->method->type & BIO_TYPE_DESCRIPTOR)
- BIO_snprintf(p, left, "read(%d,%lu) - %s fd=%d\n",
- bio->num, (unsigned long)argi,
+ BIO_snprintf(p, left, "read(%d,%zu) - %s fd=%d\n",
+ bio->num, len,
bio->method->name, bio->num);
else
- BIO_snprintf(p, left, "read(%d,%lu) - %s\n",
- bio->num, (unsigned long)argi, bio->method->name);
+ BIO_snprintf(p, left, "read(%d,%zu) - %s\n",
+ bio->num, len, bio->method->name);
break;
case BIO_CB_WRITE:
if (bio->method->type & BIO_TYPE_DESCRIPTOR)
- BIO_snprintf(p, left, "write(%d,%lu) - %s fd=%d\n",
- bio->num, (unsigned long)argi,
+ BIO_snprintf(p, left, "write(%d,%zu) - %s fd=%d\n",
+ bio->num, len,
bio->method->name, bio->num);
else
- BIO_snprintf(p, left, "write(%d,%lu) - %s\n",
- bio->num, (unsigned long)argi, bio->method->name);
+ BIO_snprintf(p, left, "write(%d,%zu) - %s\n",
+ bio->num, len, bio->method->name);
break;
case BIO_CB_PUTS:
BIO_snprintf(p, left, "puts() - %s\n", bio->method->name);
break;
case BIO_CB_GETS:
- BIO_snprintf(p, left, "gets(%lu) - %s\n", (unsigned long)argi,
+ BIO_snprintf(p, left, "gets(%zu) - %s\n", len,
bio->method->name);
break;
case BIO_CB_CTRL:
- BIO_snprintf(p, left, "ctrl(%lu) - %s\n", (unsigned long)argi,
+ BIO_snprintf(p, left, "ctrl(%d) - %s\n", argi,
bio->method->name);
break;
case BIO_CB_RETURN | BIO_CB_READ:
- BIO_snprintf(p, left, "read return %ld\n", ret);
+ BIO_snprintf(p, left, "read return %d processed: %zu\n", ret, l);
break;
case BIO_CB_RETURN | BIO_CB_WRITE:
- BIO_snprintf(p, left, "write return %ld\n", ret);
+ BIO_snprintf(p, left, "write return %d processed: %zu\n", ret, l);
break;
case BIO_CB_RETURN | BIO_CB_GETS:
- BIO_snprintf(p, left, "gets return %ld\n", ret);
+ BIO_snprintf(p, left, "gets return %d processed: %zu\n", ret, l);
break;
case BIO_CB_RETURN | BIO_CB_PUTS:
- BIO_snprintf(p, left, "puts return %ld\n", ret);
+ BIO_snprintf(p, left, "puts return %d processed: %zu\n", ret, l);
break;
case BIO_CB_RETURN | BIO_CB_CTRL:
- BIO_snprintf(p, left, "ctrl return %ld\n", ret);
+ BIO_snprintf(p, left, "ctrl return %d\n", ret);
break;
default:
BIO_snprintf(p, left, "bio callback - unknown type (%d)\n", cmd);
@@ -94,5 +96,19 @@ long BIO_debug_callback(BIO *bio, int cmd, const char *argp,
else
fputs(buf, stderr);
#endif
- return r;
+ return ret;
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+long BIO_debug_callback(BIO *bio, int cmd, const char *argp,
+ int argi, long argl, long ret)
+{
+ size_t processed = 0;
+
+ if (ret > 0)
+ processed = (size_t)ret;
+ BIO_debug_callback_ex(bio, cmd, argp, (size_t)argi,
+ argi, argl, ret > 0 ? 1 : (int)ret, &processed);
+ return ret;
}
+#endif
diff --git a/crypto/bio/bio_dump.c b/crypto/bio/bio_dump.c
new file mode 100644
index 000000000000..c453da62688c
--- /dev/null
+++ b/crypto/bio/bio_dump.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Stolen from tjh's ssl/ssl_trc.c stuff.
+ */
+
+#include <stdio.h>
+#include "bio_local.h"
+
+#define DUMP_WIDTH 16
+#define DUMP_WIDTH_LESS_INDENT(i) (DUMP_WIDTH - ((i - (i > 6 ? 6 : i) + 3) / 4))
+
+#define SPACE(buf, pos, n) (sizeof(buf) - (pos) > (n))
+
+int BIO_dump_cb(int (*cb) (const void *data, size_t len, void *u),
+ void *u, const void *s, int len)
+{
+ return BIO_dump_indent_cb(cb, u, s, len, 0);
+}
+
+int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u),
+ void *u, const void *v, int len, int indent)
+{
+ const unsigned char *s = v;
+ int res, ret = 0;
+ char buf[288 + 1];
+ int i, j, rows, n;
+ unsigned char ch;
+ int dump_width;
+
+ if (indent < 0)
+ indent = 0;
+ else if (indent > 64)
+ indent = 64;
+
+ dump_width = DUMP_WIDTH_LESS_INDENT(indent);
+ rows = len / dump_width;
+ if ((rows * dump_width) < len)
+ rows++;
+ for (i = 0; i < rows; i++) {
+ n = BIO_snprintf(buf, sizeof(buf), "%*s%04x - ", indent, "",
+ i * dump_width);
+ for (j = 0; j < dump_width; j++) {
+ if (SPACE(buf, n, 3)) {
+ if (((i * dump_width) + j) >= len) {
+ strcpy(buf + n, " ");
+ } else {
+ ch = *(s + i * dump_width + j) & 0xff;
+ BIO_snprintf(buf + n, 4, "%02x%c", ch,
+ j == 7 ? '-' : ' ');
+ }
+ n += 3;
+ }
+ }
+ if (SPACE(buf, n, 2)) {
+ strcpy(buf + n, " ");
+ n += 2;
+ }
+ for (j = 0; j < dump_width; j++) {
+ if (((i * dump_width) + j) >= len)
+ break;
+ if (SPACE(buf, n, 1)) {
+ ch = *(s + i * dump_width + j) & 0xff;
+#ifndef CHARSET_EBCDIC
+ buf[n++] = ((ch >= ' ') && (ch <= '~')) ? ch : '.';
+#else
+ buf[n++] = ((ch >= os_toascii[' ']) && (ch <= os_toascii['~']))
+ ? os_toebcdic[ch]
+ : '.';
+#endif
+ buf[n] = '\0';
+ }
+ }
+ if (SPACE(buf, n, 1)) {
+ buf[n++] = '\n';
+ buf[n] = '\0';
+ }
+ /*
+ * if this is the last call then update the ddt_dump thing so that we
+ * will move the selection point in the debug window
+ */
+ res = cb((void *)buf, n, u);
+ if (res < 0)
+ return res;
+ ret += res;
+ }
+ return ret;
+}
+
+#ifndef OPENSSL_NO_STDIO
+static int write_fp(const void *data, size_t len, void *fp)
+{
+ return UP_fwrite(data, len, 1, fp);
+}
+
+int BIO_dump_fp(FILE *fp, const void *s, int len)
+{
+ return BIO_dump_cb(write_fp, fp, s, len);
+}
+
+int BIO_dump_indent_fp(FILE *fp, const void *s, int len, int indent)
+{
+ return BIO_dump_indent_cb(write_fp, fp, s, len, indent);
+}
+#endif
+
+static int write_bio(const void *data, size_t len, void *bp)
+{
+ return BIO_write((BIO *)bp, (const char *)data, len);
+}
+
+int BIO_dump(BIO *bp, const void *s, int len)
+{
+ return BIO_dump_cb(write_bio, bp, s, len);
+}
+
+int BIO_dump_indent(BIO *bp, const void *s, int len, int indent)
+{
+ return BIO_dump_indent_cb(write_bio, bp, s, len, indent);
+}
+
+int BIO_hex_string(BIO *out, int indent, int width, const void *data,
+ int datalen)
+{
+ const unsigned char *d = data;
+ int i, j = 0;
+
+ if (datalen < 1)
+ return 1;
+
+ for (i = 0; i < datalen - 1; i++) {
+ if (i && !j)
+ BIO_printf(out, "%*s", indent, "");
+
+ BIO_printf(out, "%02X:", d[i]);
+
+ j = (j + 1) % width;
+ if (!j)
+ BIO_printf(out, "\n");
+ }
+
+ if (i && !j)
+ BIO_printf(out, "%*s", indent, "");
+ BIO_printf(out, "%02X", d[datalen - 1]);
+ return 1;
+}
diff --git a/crypto/bio/bio_err.c b/crypto/bio/bio_err.c
index 7aa9dabb2915..7a36c61148a7 100644
--- a/crypto/bio/bio_err.c
+++ b/crypto/bio/bio_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,69 +10,10 @@
#include <openssl/err.h>
#include <openssl/bioerr.h>
+#include "crypto/bioerr.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA BIO_str_functs[] = {
- {ERR_PACK(ERR_LIB_BIO, BIO_F_ACPT_STATE, 0), "acpt_state"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_ADDRINFO_WRAP, 0), "addrinfo_wrap"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_ADDR_STRINGS, 0), "addr_strings"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ACCEPT, 0), "BIO_accept"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ACCEPT_EX, 0), "BIO_accept_ex"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ACCEPT_NEW, 0), "BIO_ACCEPT_new"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ADDR_NEW, 0), "BIO_ADDR_new"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_BIND, 0), "BIO_bind"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CALLBACK_CTRL, 0), "BIO_callback_ctrl"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CONNECT, 0), "BIO_connect"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CONNECT_NEW, 0), "BIO_CONNECT_new"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CTRL, 0), "BIO_ctrl"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GETS, 0), "BIO_gets"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GET_HOST_IP, 0), "BIO_get_host_ip"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GET_NEW_INDEX, 0), "BIO_get_new_index"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GET_PORT, 0), "BIO_get_port"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_LISTEN, 0), "BIO_listen"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_LOOKUP, 0), "BIO_lookup"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_LOOKUP_EX, 0), "BIO_lookup_ex"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_MAKE_PAIR, 0), "bio_make_pair"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_METH_NEW, 0), "BIO_meth_new"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW, 0), "BIO_new"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW_DGRAM_SCTP, 0), "BIO_new_dgram_sctp"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW_FILE, 0), "BIO_new_file"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW_MEM_BUF, 0), "BIO_new_mem_buf"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NREAD, 0), "BIO_nread"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NREAD0, 0), "BIO_nread0"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NWRITE, 0), "BIO_nwrite"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NWRITE0, 0), "BIO_nwrite0"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_PARSE_HOSTSERV, 0), "BIO_parse_hostserv"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_PUTS, 0), "BIO_puts"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_READ, 0), "BIO_read"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_READ_EX, 0), "BIO_read_ex"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_READ_INTERN, 0), "bio_read_intern"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCKET, 0), "BIO_socket"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCKET_NBIO, 0), "BIO_socket_nbio"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCK_INFO, 0), "BIO_sock_info"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCK_INIT, 0), "BIO_sock_init"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_WRITE, 0), "BIO_write"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_WRITE_EX, 0), "BIO_write_ex"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_WRITE_INTERN, 0), "bio_write_intern"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BUFFER_CTRL, 0), "buffer_ctrl"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_CONN_CTRL, 0), "conn_ctrl"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_CONN_STATE, 0), "conn_state"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_DGRAM_SCTP_NEW, 0), "dgram_sctp_new"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_DGRAM_SCTP_READ, 0), "dgram_sctp_read"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_DGRAM_SCTP_WRITE, 0), "dgram_sctp_write"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_DOAPR_OUTCH, 0), "doapr_outch"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_FILE_CTRL, 0), "file_ctrl"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_FILE_READ, 0), "file_read"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_LINEBUFFER_CTRL, 0), "linebuffer_ctrl"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_LINEBUFFER_NEW, 0), "linebuffer_new"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_MEM_WRITE, 0), "mem_write"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_NBIOF_NEW, 0), "nbiof_new"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_SLG_WRITE, 0), "slg_write"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_SSL_NEW, 0), "SSL_new"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA BIO_str_reasons[] = {
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_ACCEPT_ERROR), "accept error"},
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET),
@@ -82,6 +23,7 @@ static const ERR_STRING_DATA BIO_str_reasons[] = {
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_BAD_FOPEN_MODE), "bad fopen mode"},
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_BROKEN_PIPE), "broken pipe"},
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_CONNECT_ERROR), "connect error"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_CONNECT_TIMEOUT), "connect timeout"},
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET),
"gethostbyname addr is not af inet"},
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_GETSOCKNAME_ERROR), "getsockname error"},
@@ -104,7 +46,8 @@ static const ERR_STRING_DATA BIO_str_reasons[] = {
"no hostname or service specified"},
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_PORT_DEFINED), "no port defined"},
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_SUCH_FILE), "no such file"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NULL_PARAMETER), "null parameter"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_TRANSFER_ERROR), "transfer error"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_TRANSFER_TIMEOUT), "transfer timeout"},
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_BIND_SOCKET),
"unable to bind socket"},
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_CREATE_SOCKET),
@@ -133,13 +76,11 @@ static const ERR_STRING_DATA BIO_str_reasons[] = {
#endif
-int ERR_load_BIO_strings(void)
+int ossl_err_load_BIO_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(BIO_str_functs[0].error) == NULL) {
- ERR_load_strings_const(BIO_str_functs);
+ if (ERR_reason_error_string(BIO_str_reasons[0].error) == NULL)
ERR_load_strings_const(BIO_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c
index d2202e537b30..ecc16a5ee36a 100644
--- a/crypto/bio/bio_lib.c
+++ b/crypto/bio/bio_lib.c
@@ -1,26 +1,32 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <stdio.h>
#include <errno.h>
#include <openssl/crypto.h>
+#include "internal/numbers.h"
#include "bio_local.h"
-#include "internal/cryptlib.h"
-
/*
* Helper macro for the callback to determine whether an operator expects a
* len parameter or not
*/
-#define HAS_LEN_OPER(o) ((o) == BIO_CB_READ || (o) == BIO_CB_WRITE || \
- (o) == BIO_CB_GETS)
+#define HAS_LEN_OPER(o) ((o) == BIO_CB_READ || (o) == BIO_CB_WRITE \
+ || (o) == BIO_CB_GETS)
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HAS_CALLBACK(b) ((b)->callback != NULL || (b)->callback_ex != NULL)
+#else
+# define HAS_CALLBACK(b) ((b)->callback_ex != NULL)
+#endif
/*
* Helper function to work out whether to call the new style callback or the old
* one, and translate between the two.
@@ -29,14 +35,18 @@
* for the "long" used for "inret"
*/
static long bio_call_callback(BIO *b, int oper, const char *argp, size_t len,
- int argi, long argl, long inret, size_t *processed)
+ int argi, long argl, long inret,
+ size_t *processed)
{
- long ret;
+ long ret = inret;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int bareoper;
if (b->callback_ex != NULL)
+#endif
return b->callback_ex(b, oper, argp, len, argi, argl, inret, processed);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
/* Strip off any BIO_CB_RETURN flag */
bareoper = oper & ~BIO_CB_RETURN;
@@ -64,19 +74,20 @@ static long bio_call_callback(BIO *b, int oper, const char *argp, size_t len,
*processed = (size_t)ret;
ret = 1;
}
-
+#endif
return ret;
}
-BIO *BIO_new(const BIO_METHOD *method)
+BIO *BIO_new_ex(OSSL_LIB_CTX *libctx, const BIO_METHOD *method)
{
BIO *bio = OPENSSL_zalloc(sizeof(*bio));
if (bio == NULL) {
- BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return NULL;
}
+ bio->libctx = libctx;
bio->method = method;
bio->shutdown = 1;
bio->references = 1;
@@ -86,13 +97,13 @@ BIO *BIO_new(const BIO_METHOD *method)
bio->lock = CRYPTO_THREAD_lock_new();
if (bio->lock == NULL) {
- BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
goto err;
}
if (method->create != NULL && !method->create(bio)) {
- BIOerr(BIO_F_BIO_NEW, ERR_R_INIT_FAIL);
+ ERR_raise(ERR_LIB_BIO, ERR_R_INIT_FAIL);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
CRYPTO_THREAD_lock_free(bio->lock);
goto err;
@@ -107,6 +118,11 @@ err:
return NULL;
}
+BIO *BIO_new(const BIO_METHOD *method)
+{
+ return BIO_new_ex(NULL, method);
+}
+
int BIO_free(BIO *a)
{
int ret;
@@ -122,10 +138,10 @@ int BIO_free(BIO *a)
return 1;
REF_ASSERT_ISNT(ret < 0);
- if (a->callback != NULL || a->callback_ex != NULL) {
+ if (HAS_CALLBACK(a)) {
ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL);
if (ret <= 0)
- return ret;
+ return 0;
}
if ((a->method != NULL) && (a->method->destroy != NULL))
@@ -184,7 +200,7 @@ int BIO_up_ref(BIO *a)
REF_PRINT_COUNT("BIO", a);
REF_ASSERT_ISNT(i < 2);
- return ((i > 1) ? 1 : 0);
+ return i > 1;
}
void BIO_clear_flags(BIO *b, int flags)
@@ -202,6 +218,7 @@ void BIO_set_flags(BIO *b, int flags)
b->flags |= flags;
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
BIO_callback_fn BIO_get_callback(const BIO *b)
{
return b->callback;
@@ -211,6 +228,7 @@ void BIO_set_callback(BIO *b, BIO_callback_fn cb)
{
b->callback = cb;
}
+#endif
BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b)
{
@@ -252,19 +270,23 @@ static int bio_read_intern(BIO *b, void *data, size_t dlen, size_t *readbytes)
{
int ret;
- if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) {
- BIOerr(BIO_F_BIO_READ_INTERN, BIO_R_UNSUPPORTED_METHOD);
+ if (b == NULL) {
+ ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+ if (b->method == NULL || b->method->bread == NULL) {
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
- if ((b->callback != NULL || b->callback_ex != NULL) &&
+ if (HAS_CALLBACK(b) &&
((ret = (int)bio_call_callback(b, BIO_CB_READ, data, dlen, 0, 0L, 1L,
NULL)) <= 0))
return ret;
if (!b->init) {
- BIOerr(BIO_F_BIO_READ_INTERN, BIO_R_UNINITIALIZED);
- return -2;
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
+ return -1;
}
ret = b->method->bread(b, data, dlen, readbytes);
@@ -272,13 +294,13 @@ static int bio_read_intern(BIO *b, void *data, size_t dlen, size_t *readbytes)
if (ret > 0)
b->num_read += (uint64_t)*readbytes;
- if (b->callback != NULL || b->callback_ex != NULL)
+ if (HAS_CALLBACK(b))
ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, data,
dlen, 0, 0L, ret, readbytes);
/* Shouldn't happen */
if (ret > 0 && *readbytes > dlen) {
- BIOerr(BIO_F_BIO_READ_INTERN, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_BIO, ERR_R_INTERNAL_ERROR);
return -1;
}
@@ -305,50 +327,50 @@ int BIO_read(BIO *b, void *data, int dlen)
int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes)
{
- int ret;
-
- ret = bio_read_intern(b, data, dlen, readbytes);
-
- if (ret > 0)
- ret = 1;
- else
- ret = 0;
-
- return ret;
+ return bio_read_intern(b, data, dlen, readbytes) > 0;
}
static int bio_write_intern(BIO *b, const void *data, size_t dlen,
size_t *written)
{
+ size_t local_written;
int ret;
+ if (written != NULL)
+ *written = 0;
+ /*
+ * b == NULL is not an error but just means that zero bytes are written.
+ * Do not raise an error here.
+ */
if (b == NULL)
return 0;
- if ((b->method == NULL) || (b->method->bwrite == NULL)) {
- BIOerr(BIO_F_BIO_WRITE_INTERN, BIO_R_UNSUPPORTED_METHOD);
+ if (b->method == NULL || b->method->bwrite == NULL) {
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
- if ((b->callback != NULL || b->callback_ex != NULL) &&
+ if (HAS_CALLBACK(b) &&
((ret = (int)bio_call_callback(b, BIO_CB_WRITE, data, dlen, 0, 0L, 1L,
NULL)) <= 0))
return ret;
if (!b->init) {
- BIOerr(BIO_F_BIO_WRITE_INTERN, BIO_R_UNINITIALIZED);
- return -2;
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
+ return -1;
}
- ret = b->method->bwrite(b, data, dlen, written);
+ ret = b->method->bwrite(b, data, dlen, &local_written);
if (ret > 0)
- b->num_write += (uint64_t)*written;
+ b->num_write += (uint64_t)local_written;
- if (b->callback != NULL || b->callback_ex != NULL)
+ if (HAS_CALLBACK(b))
ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, data,
- dlen, 0, 0L, ret, written);
+ dlen, 0, 0L, ret, &local_written);
+ if (written != NULL)
+ *written = local_written;
return ret;
}
@@ -357,13 +379,13 @@ int BIO_write(BIO *b, const void *data, int dlen)
size_t written;
int ret;
- if (dlen < 0)
+ if (dlen <= 0)
return 0;
ret = bio_write_intern(b, data, (size_t)dlen, &written);
if (ret > 0) {
- /* *written should always be <= dlen */
+ /* written should always be <= dlen */
ret = (int)written;
}
@@ -372,16 +394,8 @@ int BIO_write(BIO *b, const void *data, int dlen)
int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written)
{
- int ret;
-
- ret = bio_write_intern(b, data, dlen, written);
-
- if (ret > 0)
- ret = 1;
- else
- ret = 0;
-
- return ret;
+ return bio_write_intern(b, data, dlen, written) > 0
+ || (b != NULL && dlen == 0); /* order is important for *written */
}
int BIO_puts(BIO *b, const char *buf)
@@ -389,20 +403,24 @@ int BIO_puts(BIO *b, const char *buf)
int ret;
size_t written = 0;
- if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) {
- BIOerr(BIO_F_BIO_PUTS, BIO_R_UNSUPPORTED_METHOD);
+ if (b == NULL) {
+ ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+ if (b->method == NULL || b->method->bputs == NULL) {
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
- if (b->callback != NULL || b->callback_ex != NULL) {
+ if (HAS_CALLBACK(b)) {
ret = (int)bio_call_callback(b, BIO_CB_PUTS, buf, 0, 0, 0L, 1L, NULL);
if (ret <= 0)
return ret;
}
if (!b->init) {
- BIOerr(BIO_F_BIO_PUTS, BIO_R_UNINITIALIZED);
- return -2;
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
+ return -1;
}
ret = b->method->bputs(b, buf);
@@ -413,13 +431,13 @@ int BIO_puts(BIO *b, const char *buf)
ret = 1;
}
- if (b->callback != NULL || b->callback_ex != NULL)
+ if (HAS_CALLBACK(b))
ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN, buf, 0, 0,
0L, ret, &written);
if (ret > 0) {
if (written > INT_MAX) {
- BIOerr(BIO_F_BIO_PUTS, BIO_R_LENGTH_TOO_LONG);
+ ERR_raise(ERR_LIB_BIO, BIO_R_LENGTH_TOO_LONG);
ret = -1;
} else {
ret = (int)written;
@@ -434,25 +452,29 @@ int BIO_gets(BIO *b, char *buf, int size)
int ret;
size_t readbytes = 0;
- if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) {
- BIOerr(BIO_F_BIO_GETS, BIO_R_UNSUPPORTED_METHOD);
+ if (b == NULL) {
+ ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+ if (b->method == NULL || b->method->bgets == NULL) {
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if (size < 0) {
- BIOerr(BIO_F_BIO_GETS, BIO_R_INVALID_ARGUMENT);
- return 0;
+ ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
+ return -1;
}
- if (b->callback != NULL || b->callback_ex != NULL) {
+ if (HAS_CALLBACK(b)) {
ret = (int)bio_call_callback(b, BIO_CB_GETS, buf, size, 0, 0L, 1, NULL);
if (ret <= 0)
return ret;
}
if (!b->init) {
- BIOerr(BIO_F_BIO_GETS, BIO_R_UNINITIALIZED);
- return -2;
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
+ return -1;
}
ret = b->method->bgets(b, buf, size);
@@ -462,7 +484,7 @@ int BIO_gets(BIO *b, char *buf, int size)
ret = 1;
}
- if (b->callback != NULL || b->callback_ex != NULL)
+ if (HAS_CALLBACK(b))
ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, buf, size,
0, 0L, ret, &readbytes);
@@ -477,6 +499,37 @@ int BIO_gets(BIO *b, char *buf, int size)
return ret;
}
+int BIO_get_line(BIO *bio, char *buf, int size)
+{
+ int ret = 0;
+ char *ptr = buf;
+
+ if (buf == NULL) {
+ ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+ if (size <= 0) {
+ ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
+ return -1;
+ }
+ *buf = '\0';
+
+ if (bio == NULL) {
+ ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+ if (!bio->init) {
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
+ return -1;
+ }
+
+ while (size-- > 1 && (ret = BIO_read(bio, ptr, 1)) > 0)
+ if (*ptr++ == '\n')
+ break;
+ *ptr = '\0';
+ return ret > 0 || BIO_eof(bio) ? ptr - buf : ret;
+}
+
int BIO_indent(BIO *b, int indent, int max)
{
if (indent < 0)
@@ -512,14 +565,13 @@ long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
long ret;
if (b == NULL)
- return 0;
-
- if ((b->method == NULL) || (b->method->ctrl == NULL)) {
- BIOerr(BIO_F_BIO_CTRL, BIO_R_UNSUPPORTED_METHOD);
+ return -1;
+ if (b->method == NULL || b->method->ctrl == NULL) {
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
- if (b->callback != NULL || b->callback_ex != NULL) {
+ if (HAS_CALLBACK(b)) {
ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg, 1L, NULL);
if (ret <= 0)
return ret;
@@ -527,7 +579,7 @@ long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
ret = b->method->ctrl(b, cmd, larg, parg);
- if (b->callback != NULL || b->callback_ex != NULL)
+ if (HAS_CALLBACK(b))
ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, cmd,
larg, ret, NULL);
@@ -539,15 +591,14 @@ long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
long ret;
if (b == NULL)
- return 0;
-
- if ((b->method == NULL) || (b->method->callback_ctrl == NULL)
- || (cmd != BIO_CTRL_SET_CALLBACK)) {
- BIOerr(BIO_F_BIO_CALLBACK_CTRL, BIO_R_UNSUPPORTED_METHOD);
+ return -2;
+ if (b->method == NULL || b->method->callback_ctrl == NULL
+ || cmd != BIO_CTRL_SET_CALLBACK) {
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
- if (b->callback != NULL || b->callback_ex != NULL) {
+ if (HAS_CALLBACK(b)) {
ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0, cmd, 0, 1L,
NULL);
if (ret <= 0)
@@ -556,7 +607,7 @@ long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
ret = b->method->callback_ctrl(b, cmd, fp);
- if (b->callback != NULL || b->callback_ex != NULL)
+ if (HAS_CALLBACK(b))
ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, 0,
cmd, 0, ret, NULL);
@@ -570,12 +621,28 @@ long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
*/
size_t BIO_ctrl_pending(BIO *bio)
{
- return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
+ long ret = BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
+
+ if (ret < 0)
+ ret = 0;
+#if LONG_MAX > SIZE_MAX
+ if (ret > SIZE_MAX)
+ ret = SIZE_MAX;
+#endif
+ return (size_t)ret;
}
size_t BIO_ctrl_wpending(BIO *bio)
{
- return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
+ long ret = BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
+
+ if (ret < 0)
+ ret = 0;
+#if LONG_MAX > SIZE_MAX
+ if (ret > SIZE_MAX)
+ ret = SIZE_MAX;
+#endif
+ return (size_t)ret;
}
/* put the 'bio' on the end of b's list of operators */
@@ -649,8 +716,10 @@ BIO *BIO_find_type(BIO *bio, int type)
{
int mt, mask;
- if (bio == NULL)
+ if (bio == NULL) {
+ ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
+ }
mask = type & 0xff;
do {
if (bio->method != NULL) {
@@ -659,8 +728,9 @@ BIO *BIO_find_type(BIO *bio, int type)
if (!mask) {
if (mt & type)
return bio;
- } else if (mt == type)
+ } else if (mt == type) {
return bio;
+ }
}
bio = bio->next_bio;
} while (bio != NULL);
@@ -702,7 +772,9 @@ BIO *BIO_dup_chain(BIO *in)
for (bio = in; bio != NULL; bio = bio->next_bio) {
if ((new_bio = BIO_new(bio->method)) == NULL)
goto err;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
new_bio->callback = bio->callback;
+#endif
new_bio->callback_ex = bio->callback_ex;
new_bio->cb_arg = bio->cb_arg;
new_bio->init = bio->init;
@@ -750,7 +822,7 @@ int BIO_set_ex_data(BIO *bio, int idx, void *data)
return CRYPTO_set_ex_data(&(bio->ex_data), idx, data);
}
-void *BIO_get_ex_data(BIO *bio, int idx)
+void *BIO_get_ex_data(const BIO *bio, int idx)
{
return CRYPTO_get_ex_data(&(bio->ex_data), idx);
}
@@ -784,3 +856,127 @@ void bio_cleanup(void)
CRYPTO_THREAD_lock_free(bio_type_lock);
bio_type_lock = NULL;
}
+
+/* Internal variant of the below BIO_wait() not calling BIOerr() */
+static int bio_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds)
+{
+#ifndef OPENSSL_NO_SOCK
+ int fd;
+#endif
+ long sec_diff;
+
+ if (max_time == 0) /* no timeout */
+ return 1;
+
+#ifndef OPENSSL_NO_SOCK
+ if (BIO_get_fd(bio, &fd) > 0 && fd < FD_SETSIZE)
+ return BIO_socket_wait(fd, BIO_should_read(bio), max_time);
+#endif
+ /* fall back to polling since no sockets are available */
+
+ sec_diff = (long)(max_time - time(NULL)); /* might overflow */
+ if (sec_diff < 0)
+ return 0; /* clearly timeout */
+
+ /* now take a nap at most the given number of milliseconds */
+ if (sec_diff == 0) { /* we are below the 1 seconds resolution of max_time */
+ if (nap_milliseconds > 1000)
+ nap_milliseconds = 1000;
+ } else { /* for sec_diff > 0, take min(sec_diff * 1000, nap_milliseconds) */
+ if ((unsigned long)sec_diff * 1000 < nap_milliseconds)
+ nap_milliseconds = (unsigned int)sec_diff * 1000;
+ }
+ ossl_sleep(nap_milliseconds);
+ return 1;
+}
+
+/*-
+ * Wait on (typically socket-based) BIO at most until max_time.
+ * Succeed immediately if max_time == 0.
+ * If sockets are not available support polling: succeed after waiting at most
+ * the number of nap_milliseconds in order to avoid a tight busy loop.
+ * Call BIOerr(...) on timeout or error.
+ * Returns -1 on error, 0 on timeout, and 1 on success.
+ */
+int BIO_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds)
+{
+ int rv = bio_wait(bio, max_time, nap_milliseconds);
+
+ if (rv <= 0)
+ ERR_raise(ERR_LIB_BIO,
+ rv == 0 ? BIO_R_TRANSFER_TIMEOUT : BIO_R_TRANSFER_ERROR);
+ return rv;
+}
+
+/*
+ * Connect via given BIO using BIO_do_connect() until success/timeout/error.
+ * Parameter timeout == 0 means no timeout, < 0 means exactly one try.
+ * For non-blocking and potentially even non-socket BIOs perform polling with
+ * the given density: between polls sleep nap_milliseconds using BIO_wait()
+ * in order to avoid a tight busy loop.
+ * Returns -1 on error, 0 on timeout, and 1 on success.
+ */
+int BIO_do_connect_retry(BIO *bio, int timeout, int nap_milliseconds)
+{
+ int blocking = timeout <= 0;
+ time_t max_time = timeout > 0 ? time(NULL) + timeout : 0;
+ int rv;
+
+ if (bio == NULL) {
+ ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+
+ if (nap_milliseconds < 0)
+ nap_milliseconds = 100;
+ BIO_set_nbio(bio, !blocking);
+
+ retry:
+ ERR_set_mark();
+ rv = BIO_do_connect(bio);
+
+ if (rv <= 0) { /* could be timeout or retryable error or fatal error */
+ int err = ERR_peek_last_error();
+ int reason = ERR_GET_REASON(err);
+ int do_retry = BIO_should_retry(bio); /* may be 1 only if !blocking */
+
+ if (ERR_GET_LIB(err) == ERR_LIB_BIO) {
+ switch (reason) {
+ case ERR_R_SYS_LIB:
+ /*
+ * likely retryable system error occurred, which may be
+ * EAGAIN (resource temporarily unavailable) some 40 secs after
+ * calling getaddrinfo(): Temporary failure in name resolution
+ * or a premature ETIMEDOUT, some 30 seconds after connect()
+ */
+ case BIO_R_CONNECT_ERROR:
+ case BIO_R_NBIO_CONNECT_ERROR:
+ /* some likely retryable connection error occurred */
+ (void)BIO_reset(bio); /* often needed to avoid retry failure */
+ do_retry = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ if (timeout >= 0 && do_retry) {
+ ERR_pop_to_mark();
+ /* will not actually wait if timeout == 0 (i.e., blocking BIO): */
+ rv = bio_wait(bio, max_time, nap_milliseconds);
+ if (rv > 0)
+ goto retry;
+ ERR_raise(ERR_LIB_BIO,
+ rv == 0 ? BIO_R_CONNECT_TIMEOUT : BIO_R_CONNECT_ERROR);
+ } else {
+ ERR_clear_last_mark();
+ rv = -1;
+ if (err == 0) /* missing error queue entry */
+ /* workaround: general error */
+ ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR);
+ }
+ } else {
+ ERR_clear_last_mark();
+ }
+
+ return rv;
+}
diff --git a/crypto/bio/bio_local.h b/crypto/bio/bio_local.h
index 8b2122129396..749e8f810c30 100644
--- a/crypto/bio/bio_local.h
+++ b/crypto/bio/bio_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,7 +9,6 @@
#include "e_os.h"
#include "internal/sockets.h"
-#include "internal/refcount.h"
/* BEGIN BIO_ADDRINFO/BIO_ADDR stuff. */
@@ -30,7 +29,7 @@
# ifdef OSSL_INTERNAL_CRYPTLIB_H
# error internal/cryptlib.h included before bio_local.h
# endif
-# ifdef HEADER_BIO_H
+# ifdef OPENSSL_BIO_H
# error openssl/bio.h included before bio_local.h
# endif
@@ -88,6 +87,7 @@ union bio_addr_st {
#include "internal/cryptlib.h"
#include "internal/bio.h"
+#include "internal/refcount.h"
typedef struct bio_f_buffer_ctx_struct {
/*-
@@ -113,9 +113,12 @@ typedef struct bio_f_buffer_ctx_struct {
} BIO_F_BUFFER_CTX;
struct bio_st {
+ OSSL_LIB_CTX *libctx;
const BIO_METHOD *method;
/* bio, mode, argp, argi, argl, ret */
+#ifndef OPENSSL_NO_DEPRECATED_3_0
BIO_callback_fn callback;
+#endif
BIO_callback_fn_ex callback_ex;
char *cb_arg; /* first argument for the callback */
int init;
@@ -152,7 +155,7 @@ extern CRYPTO_RWLOCK *bio_type_lock;
void bio_sock_cleanup_int(void);
-#if BIO_FLAGS_UPLINK==0
+#if BIO_FLAGS_UPLINK_INTERNAL==0
/* Shortcut UPLINK calls on most platforms... */
# define UP_stdin stdin
# define UP_stdout stdout
diff --git a/crypto/bio/bio_meth.c b/crypto/bio/bio_meth.c
index da116461922e..469715ba09eb 100644
--- a/crypto/bio/bio_meth.c
+++ b/crypto/bio/bio_meth.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -25,7 +25,7 @@ int BIO_get_new_index(void)
int newval;
if (!RUN_ONCE(&bio_type_init, do_bio_type_init)) {
- BIOerr(BIO_F_BIO_GET_NEW_INDEX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return -1;
}
if (!CRYPTO_UP_REF(&bio_count, &newval, bio_type_lock))
@@ -40,7 +40,7 @@ BIO_METHOD *BIO_meth_new(int type, const char *name)
if (biom == NULL
|| (biom->name = OPENSSL_strdup(name)) == NULL) {
OPENSSL_free(biom);
- BIOerr(BIO_F_BIO_METH_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return NULL;
}
biom->type = type;
diff --git a/crypto/bio/bio_print.c b/crypto/bio/bio_print.c
new file mode 100644
index 000000000000..4c9c3af7cfd6
--- /dev/null
+++ b/crypto/bio/bio_print.c
@@ -0,0 +1,960 @@
+/*
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "internal/cryptlib.h"
+#include "crypto/ctype.h"
+#include "internal/numbers.h"
+#include <openssl/bio.h>
+#include <openssl/configuration.h>
+
+/*
+ * Copyright Patrick Powell 1995
+ * This code is based on code written by Patrick Powell <papowell@astart.com>
+ * It may be used for any purpose as long as this notice remains intact
+ * on all source code distributions.
+ */
+
+#ifdef HAVE_LONG_DOUBLE
+# define LDOUBLE long double
+#else
+# define LDOUBLE double
+#endif
+
+static int fmtstr(char **, char **, size_t *, size_t *,
+ const char *, int, int, int);
+static int fmtint(char **, char **, size_t *, size_t *,
+ int64_t, int, int, int, int);
+#ifndef OPENSSL_SYS_UEFI
+static int fmtfp(char **, char **, size_t *, size_t *,
+ LDOUBLE, int, int, int, int);
+#endif
+static int doapr_outch(char **, char **, size_t *, size_t *, int);
+static int _dopr(char **sbuffer, char **buffer,
+ size_t *maxlen, size_t *retlen, int *truncated,
+ const char *format, va_list args);
+
+/* format read states */
+#define DP_S_DEFAULT 0
+#define DP_S_FLAGS 1
+#define DP_S_MIN 2
+#define DP_S_DOT 3
+#define DP_S_MAX 4
+#define DP_S_MOD 5
+#define DP_S_CONV 6
+#define DP_S_DONE 7
+
+/* format flags - Bits */
+/* left-aligned padding */
+#define DP_F_MINUS (1 << 0)
+/* print an explicit '+' for a value with positive sign */
+#define DP_F_PLUS (1 << 1)
+/* print an explicit ' ' for a value with positive sign */
+#define DP_F_SPACE (1 << 2)
+/* print 0/0x prefix for octal/hex and decimal point for floating point */
+#define DP_F_NUM (1 << 3)
+/* print leading zeroes */
+#define DP_F_ZERO (1 << 4)
+/* print HEX in UPPPERcase */
+#define DP_F_UP (1 << 5)
+/* treat value as unsigned */
+#define DP_F_UNSIGNED (1 << 6)
+
+/* conversion flags */
+#define DP_C_SHORT 1
+#define DP_C_LONG 2
+#define DP_C_LDOUBLE 3
+#define DP_C_LLONG 4
+#define DP_C_SIZE 5
+
+/* Floating point formats */
+#define F_FORMAT 0
+#define E_FORMAT 1
+#define G_FORMAT 2
+
+/* some handy macros */
+#define char_to_int(p) (p - '0')
+#define OSSL_MAX(p,q) ((p >= q) ? p : q)
+
+static int
+_dopr(char **sbuffer,
+ char **buffer,
+ size_t *maxlen,
+ size_t *retlen, int *truncated, const char *format, va_list args)
+{
+ char ch;
+ int64_t value;
+#ifndef OPENSSL_SYS_UEFI
+ LDOUBLE fvalue;
+#endif
+ char *strvalue;
+ int min;
+ int max;
+ int state;
+ int flags;
+ int cflags;
+ size_t currlen;
+
+ state = DP_S_DEFAULT;
+ flags = currlen = cflags = min = 0;
+ max = -1;
+ ch = *format++;
+
+ while (state != DP_S_DONE) {
+ if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
+ state = DP_S_DONE;
+
+ switch (state) {
+ case DP_S_DEFAULT:
+ if (ch == '%')
+ state = DP_S_FLAGS;
+ else
+ if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
+ return 0;
+ ch = *format++;
+ break;
+ case DP_S_FLAGS:
+ switch (ch) {
+ case '-':
+ flags |= DP_F_MINUS;
+ ch = *format++;
+ break;
+ case '+':
+ flags |= DP_F_PLUS;
+ ch = *format++;
+ break;
+ case ' ':
+ flags |= DP_F_SPACE;
+ ch = *format++;
+ break;
+ case '#':
+ flags |= DP_F_NUM;
+ ch = *format++;
+ break;
+ case '0':
+ flags |= DP_F_ZERO;
+ ch = *format++;
+ break;
+ default:
+ state = DP_S_MIN;
+ break;
+ }
+ break;
+ case DP_S_MIN:
+ if (ossl_isdigit(ch)) {
+ min = 10 * min + char_to_int(ch);
+ ch = *format++;
+ } else if (ch == '*') {
+ min = va_arg(args, int);
+ ch = *format++;
+ state = DP_S_DOT;
+ } else
+ state = DP_S_DOT;
+ break;
+ case DP_S_DOT:
+ if (ch == '.') {
+ state = DP_S_MAX;
+ ch = *format++;
+ } else
+ state = DP_S_MOD;
+ break;
+ case DP_S_MAX:
+ if (ossl_isdigit(ch)) {
+ if (max < 0)
+ max = 0;
+ max = 10 * max + char_to_int(ch);
+ ch = *format++;
+ } else if (ch == '*') {
+ max = va_arg(args, int);
+ ch = *format++;
+ state = DP_S_MOD;
+ } else
+ state = DP_S_MOD;
+ break;
+ case DP_S_MOD:
+ switch (ch) {
+ case 'h':
+ cflags = DP_C_SHORT;
+ ch = *format++;
+ break;
+ case 'l':
+ if (*format == 'l') {
+ cflags = DP_C_LLONG;
+ format++;
+ } else
+ cflags = DP_C_LONG;
+ ch = *format++;
+ break;
+ case 'q':
+ case 'j':
+ cflags = DP_C_LLONG;
+ ch = *format++;
+ break;
+ case 'L':
+ cflags = DP_C_LDOUBLE;
+ ch = *format++;
+ break;
+ case 'z':
+ cflags = DP_C_SIZE;
+ ch = *format++;
+ break;
+ default:
+ break;
+ }
+ state = DP_S_CONV;
+ break;
+ case DP_S_CONV:
+ switch (ch) {
+ case 'd':
+ case 'i':
+ switch (cflags) {
+ case DP_C_SHORT:
+ value = (short int)va_arg(args, int);
+ break;
+ case DP_C_LONG:
+ value = va_arg(args, long int);
+ break;
+ case DP_C_LLONG:
+ value = va_arg(args, int64_t);
+ break;
+ case DP_C_SIZE:
+ value = va_arg(args, ossl_ssize_t);
+ break;
+ default:
+ value = va_arg(args, int);
+ break;
+ }
+ if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min,
+ max, flags))
+ return 0;
+ break;
+ case 'X':
+ flags |= DP_F_UP;
+ /* FALLTHROUGH */
+ case 'x':
+ case 'o':
+ case 'u':
+ flags |= DP_F_UNSIGNED;
+ switch (cflags) {
+ case DP_C_SHORT:
+ value = (unsigned short int)va_arg(args, unsigned int);
+ break;
+ case DP_C_LONG:
+ value = va_arg(args, unsigned long int);
+ break;
+ case DP_C_LLONG:
+ value = va_arg(args, uint64_t);
+ break;
+ case DP_C_SIZE:
+ value = va_arg(args, size_t);
+ break;
+ default:
+ value = va_arg(args, unsigned int);
+ break;
+ }
+ if (!fmtint(sbuffer, buffer, &currlen, maxlen, value,
+ ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
+ min, max, flags))
+ return 0;
+ break;
+#ifndef OPENSSL_SYS_UEFI
+ case 'f':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, LDOUBLE);
+ else
+ fvalue = va_arg(args, double);
+ if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
+ flags, F_FORMAT))
+ return 0;
+ break;
+ case 'E':
+ flags |= DP_F_UP;
+ /* fall thru */
+ case 'e':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, LDOUBLE);
+ else
+ fvalue = va_arg(args, double);
+ if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
+ flags, E_FORMAT))
+ return 0;
+ break;
+ case 'G':
+ flags |= DP_F_UP;
+ /* fall thru */
+ case 'g':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, LDOUBLE);
+ else
+ fvalue = va_arg(args, double);
+ if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
+ flags, G_FORMAT))
+ return 0;
+ break;
+#else
+ case 'f':
+ case 'E':
+ case 'e':
+ case 'G':
+ case 'g':
+ /* not implemented for UEFI */
+ ERR_raise(ERR_LIB_BIO, ERR_R_UNSUPPORTED);
+ return 0;
+#endif
+ case 'c':
+ if (!doapr_outch(sbuffer, buffer, &currlen, maxlen,
+ va_arg(args, int)))
+ return 0;
+ break;
+ case 's':
+ strvalue = va_arg(args, char *);
+ if (max < 0) {
+ if (buffer)
+ max = INT_MAX;
+ else
+ max = *maxlen;
+ }
+ if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
+ flags, min, max))
+ return 0;
+ break;
+ case 'p':
+ value = (size_t)va_arg(args, void *);
+ if (!fmtint(sbuffer, buffer, &currlen, maxlen,
+ value, 16, min, max, flags | DP_F_NUM))
+ return 0;
+ break;
+ case 'n':
+ {
+ int *num;
+ num = va_arg(args, int *);
+ *num = currlen;
+ }
+ break;
+ case '%':
+ if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
+ return 0;
+ break;
+ case 'w':
+ /* not supported yet, treat as next char */
+ format++;
+ break;
+ default:
+ /* unknown, skip */
+ break;
+ }
+ ch = *format++;
+ state = DP_S_DEFAULT;
+ flags = cflags = min = 0;
+ max = -1;
+ break;
+ case DP_S_DONE:
+ break;
+ default:
+ break;
+ }
+ }
+ /*
+ * We have to truncate if there is no dynamic buffer and we have filled the
+ * static buffer.
+ */
+ if (buffer == NULL) {
+ *truncated = (currlen > *maxlen - 1);
+ if (*truncated)
+ currlen = *maxlen - 1;
+ }
+ if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))
+ return 0;
+ *retlen = currlen - 1;
+ return 1;
+}
+
+static int
+fmtstr(char **sbuffer,
+ char **buffer,
+ size_t *currlen,
+ size_t *maxlen, const char *value, int flags, int min, int max)
+{
+ int padlen;
+ size_t strln;
+ int cnt = 0;
+
+ if (value == 0)
+ value = "<NULL>";
+
+ strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max);
+
+ padlen = min - strln;
+ if (min < 0 || padlen < 0)
+ padlen = 0;
+ if (max >= 0) {
+ /*
+ * Calculate the maximum output including padding.
+ * Make sure max doesn't overflow into negativity
+ */
+ if (max < INT_MAX - padlen)
+ max += padlen;
+ else
+ max = INT_MAX;
+ }
+ if (flags & DP_F_MINUS)
+ padlen = -padlen;
+
+ while ((padlen > 0) && (max < 0 || cnt < max)) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+ return 0;
+ --padlen;
+ ++cnt;
+ }
+ while (strln > 0 && (max < 0 || cnt < max)) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))
+ return 0;
+ --strln;
+ ++cnt;
+ }
+ while ((padlen < 0) && (max < 0 || cnt < max)) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+ return 0;
+ ++padlen;
+ ++cnt;
+ }
+ return 1;
+}
+
+static int
+fmtint(char **sbuffer,
+ char **buffer,
+ size_t *currlen,
+ size_t *maxlen, int64_t value, int base, int min, int max, int flags)
+{
+ int signvalue = 0;
+ const char *prefix = "";
+ uint64_t uvalue;
+ char convert[DECIMAL_SIZE(value) + 3];
+ int place = 0;
+ int spadlen = 0;
+ int zpadlen = 0;
+ int caps = 0;
+
+ if (max < 0)
+ max = 0;
+ uvalue = value;
+ if (!(flags & DP_F_UNSIGNED)) {
+ if (value < 0) {
+ signvalue = '-';
+ uvalue = 0 - (uint64_t)value;
+ } else if (flags & DP_F_PLUS)
+ signvalue = '+';
+ else if (flags & DP_F_SPACE)
+ signvalue = ' ';
+ }
+ if (flags & DP_F_NUM) {
+ if (base == 8)
+ prefix = "0";
+ if (base == 16)
+ prefix = "0x";
+ }
+ if (flags & DP_F_UP)
+ caps = 1;
+ do {
+ convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+ [uvalue % (unsigned)base];
+ uvalue = (uvalue / (unsigned)base);
+ } while (uvalue && (place < (int)sizeof(convert)));
+ if (place == sizeof(convert))
+ place--;
+ convert[place] = 0;
+
+ zpadlen = max - place;
+ spadlen =
+ min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
+ if (zpadlen < 0)
+ zpadlen = 0;
+ if (spadlen < 0)
+ spadlen = 0;
+ if (flags & DP_F_ZERO) {
+ zpadlen = OSSL_MAX(zpadlen, spadlen);
+ spadlen = 0;
+ }
+ if (flags & DP_F_MINUS)
+ spadlen = -spadlen;
+
+ /* spaces */
+ while (spadlen > 0) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+ return 0;
+ --spadlen;
+ }
+
+ /* sign */
+ if (signvalue)
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
+ return 0;
+
+ /* prefix */
+ while (*prefix) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix))
+ return 0;
+ prefix++;
+ }
+
+ /* zeros */
+ if (zpadlen > 0) {
+ while (zpadlen > 0) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
+ return 0;
+ --zpadlen;
+ }
+ }
+ /* digits */
+ while (place > 0) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]))
+ return 0;
+ }
+
+ /* left justified spaces */
+ while (spadlen < 0) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+ return 0;
+ ++spadlen;
+ }
+ return 1;
+}
+
+#ifndef OPENSSL_SYS_UEFI
+
+static LDOUBLE abs_val(LDOUBLE value)
+{
+ LDOUBLE result = value;
+ if (value < 0)
+ result = -value;
+ return result;
+}
+
+static LDOUBLE pow_10(int in_exp)
+{
+ LDOUBLE result = 1;
+ while (in_exp) {
+ result *= 10;
+ in_exp--;
+ }
+ return result;
+}
+
+static long roundv(LDOUBLE value)
+{
+ long intpart;
+ intpart = (long)value;
+ value = value - intpart;
+ if (value >= 0.5)
+ intpart++;
+ return intpart;
+}
+
+static int
+fmtfp(char **sbuffer,
+ char **buffer,
+ size_t *currlen,
+ size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags, int style)
+{
+ int signvalue = 0;
+ LDOUBLE ufvalue;
+ LDOUBLE tmpvalue;
+ char iconvert[20];
+ char fconvert[20];
+ char econvert[20];
+ int iplace = 0;
+ int fplace = 0;
+ int eplace = 0;
+ int padlen = 0;
+ int zpadlen = 0;
+ long exp = 0;
+ unsigned long intpart;
+ unsigned long fracpart;
+ unsigned long max10;
+ int realstyle;
+
+ if (max < 0)
+ max = 6;
+
+ if (fvalue < 0)
+ signvalue = '-';
+ else if (flags & DP_F_PLUS)
+ signvalue = '+';
+ else if (flags & DP_F_SPACE)
+ signvalue = ' ';
+
+ /*
+ * G_FORMAT sometimes prints like E_FORMAT and sometimes like F_FORMAT
+ * depending on the number to be printed. Work out which one it is and use
+ * that from here on.
+ */
+ if (style == G_FORMAT) {
+ if (fvalue == 0.0) {
+ realstyle = F_FORMAT;
+ } else if (fvalue < 0.0001) {
+ realstyle = E_FORMAT;
+ } else if ((max == 0 && fvalue >= 10)
+ || (max > 0 && fvalue >= pow_10(max))) {
+ realstyle = E_FORMAT;
+ } else {
+ realstyle = F_FORMAT;
+ }
+ } else {
+ realstyle = style;
+ }
+
+ if (style != F_FORMAT) {
+ tmpvalue = fvalue;
+ /* Calculate the exponent */
+ if (fvalue != 0.0) {
+ while (tmpvalue < 1) {
+ tmpvalue *= 10;
+ exp--;
+ }
+ while (tmpvalue > 10) {
+ tmpvalue /= 10;
+ exp++;
+ }
+ }
+ if (style == G_FORMAT) {
+ /*
+ * In G_FORMAT the "precision" represents significant digits. We
+ * always have at least 1 significant digit.
+ */
+ if (max == 0)
+ max = 1;
+ /* Now convert significant digits to decimal places */
+ if (realstyle == F_FORMAT) {
+ max -= (exp + 1);
+ if (max < 0) {
+ /*
+ * Should not happen. If we're in F_FORMAT then exp < max?
+ */
+ (void)doapr_outch(sbuffer, buffer, currlen, maxlen, '\0');
+ return 0;
+ }
+ } else {
+ /*
+ * In E_FORMAT there is always one significant digit in front
+ * of the decimal point, so:
+ * significant digits == 1 + decimal places
+ */
+ max--;
+ }
+ }
+ if (realstyle == E_FORMAT)
+ fvalue = tmpvalue;
+ }
+ ufvalue = abs_val(fvalue);
+ /*
+ * By subtracting 65535 (2^16-1) we cancel the low order 15 bits
+ * of ULONG_MAX to avoid using imprecise floating point values.
+ */
+ if (ufvalue >= (double)(ULONG_MAX - 65535) + 65536.0) {
+ /* Number too big */
+ (void)doapr_outch(sbuffer, buffer, currlen, maxlen, '\0');
+ return 0;
+ }
+ intpart = (unsigned long)ufvalue;
+
+ /*
+ * sorry, we only support 9 digits past the decimal because of our
+ * conversion method
+ */
+ if (max > 9)
+ max = 9;
+
+ /*
+ * we "cheat" by converting the fractional part to integer by multiplying
+ * by a factor of 10
+ */
+ max10 = roundv(pow_10(max));
+ fracpart = roundv(pow_10(max) * (ufvalue - intpart));
+
+ if (fracpart >= max10) {
+ intpart++;
+ fracpart -= max10;
+ }
+
+ /* convert integer part */
+ do {
+ iconvert[iplace++] = "0123456789"[intpart % 10];
+ intpart = (intpart / 10);
+ } while (intpart && (iplace < (int)sizeof(iconvert)));
+ if (iplace == sizeof(iconvert))
+ iplace--;
+ iconvert[iplace] = 0;
+
+ /* convert fractional part */
+ while (fplace < max) {
+ if (style == G_FORMAT && fplace == 0 && (fracpart % 10) == 0) {
+ /* We strip trailing zeros in G_FORMAT */
+ max--;
+ fracpart = fracpart / 10;
+ if (fplace < max)
+ continue;
+ break;
+ }
+ fconvert[fplace++] = "0123456789"[fracpart % 10];
+ fracpart = (fracpart / 10);
+ }
+
+ if (fplace == sizeof(fconvert))
+ fplace--;
+ fconvert[fplace] = 0;
+
+ /* convert exponent part */
+ if (realstyle == E_FORMAT) {
+ int tmpexp;
+ if (exp < 0)
+ tmpexp = -exp;
+ else
+ tmpexp = exp;
+
+ do {
+ econvert[eplace++] = "0123456789"[tmpexp % 10];
+ tmpexp = (tmpexp / 10);
+ } while (tmpexp > 0 && eplace < (int)sizeof(econvert));
+ /* Exponent is huge!! Too big to print */
+ if (tmpexp > 0) {
+ (void)doapr_outch(sbuffer, buffer, currlen, maxlen, '\0');
+ return 0;
+ }
+ /* Add a leading 0 for single digit exponents */
+ if (eplace == 1)
+ econvert[eplace++] = '0';
+ }
+
+ /*
+ * -1 for decimal point (if we have one, i.e. max > 0),
+ * another -1 if we are printing a sign
+ */
+ padlen = min - iplace - max - (max > 0 ? 1 : 0) - ((signvalue) ? 1 : 0);
+ /* Take some off for exponent prefix "+e" and exponent */
+ if (realstyle == E_FORMAT)
+ padlen -= 2 + eplace;
+ zpadlen = max - fplace;
+ if (zpadlen < 0)
+ zpadlen = 0;
+ if (padlen < 0)
+ padlen = 0;
+ if (flags & DP_F_MINUS)
+ padlen = -padlen;
+
+ if ((flags & DP_F_ZERO) && (padlen > 0)) {
+ if (signvalue) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
+ return 0;
+ --padlen;
+ signvalue = 0;
+ }
+ while (padlen > 0) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
+ return 0;
+ --padlen;
+ }
+ }
+ while (padlen > 0) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+ return 0;
+ --padlen;
+ }
+ if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
+ return 0;
+
+ while (iplace > 0) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]))
+ return 0;
+ }
+
+ /*
+ * Decimal point. This should probably use locale to find the correct
+ * char to print out.
+ */
+ if (max > 0 || (flags & DP_F_NUM)) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.'))
+ return 0;
+
+ while (fplace > 0) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen,
+ fconvert[--fplace]))
+ return 0;
+ }
+ }
+ while (zpadlen > 0) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
+ return 0;
+ --zpadlen;
+ }
+ if (realstyle == E_FORMAT) {
+ char ech;
+
+ if ((flags & DP_F_UP) == 0)
+ ech = 'e';
+ else
+ ech = 'E';
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ech))
+ return 0;
+ if (exp < 0) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '-'))
+ return 0;
+ } else {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '+'))
+ return 0;
+ }
+ while (eplace > 0) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen,
+ econvert[--eplace]))
+ return 0;
+ }
+ }
+
+ while (padlen < 0) {
+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+ return 0;
+ ++padlen;
+ }
+ return 1;
+}
+
+#endif /* OPENSSL_SYS_UEFI */
+
+#define BUFFER_INC 1024
+
+static int
+doapr_outch(char **sbuffer,
+ char **buffer, size_t *currlen, size_t *maxlen, int c)
+{
+ /* If we haven't at least one buffer, someone has done a big booboo */
+ if (!ossl_assert(*sbuffer != NULL || buffer != NULL))
+ return 0;
+
+ /* |currlen| must always be <= |*maxlen| */
+ if (!ossl_assert(*currlen <= *maxlen))
+ return 0;
+
+ if (buffer && *currlen == *maxlen) {
+ if (*maxlen > INT_MAX - BUFFER_INC)
+ return 0;
+
+ *maxlen += BUFFER_INC;
+ if (*buffer == NULL) {
+ if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) {
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (*currlen > 0) {
+ if (!ossl_assert(*sbuffer != NULL))
+ return 0;
+ memcpy(*buffer, *sbuffer, *currlen);
+ }
+ *sbuffer = NULL;
+ } else {
+ char *tmpbuf;
+
+ tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
+ if (tmpbuf == NULL) {
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ *buffer = tmpbuf;
+ }
+ }
+
+ if (*currlen < *maxlen) {
+ if (*sbuffer)
+ (*sbuffer)[(*currlen)++] = (char)c;
+ else
+ (*buffer)[(*currlen)++] = (char)c;
+ }
+
+ return 1;
+}
+
+/***************************************************************************/
+
+int BIO_printf(BIO *bio, const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+
+ ret = BIO_vprintf(bio, format, args);
+
+ va_end(args);
+ return ret;
+}
+
+int BIO_vprintf(BIO *bio, const char *format, va_list args)
+{
+ int ret;
+ size_t retlen;
+ char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable
+ * in small-stack environments, like threads
+ * or DOS programs. */
+ char *hugebufp = hugebuf;
+ size_t hugebufsize = sizeof(hugebuf);
+ char *dynbuf = NULL;
+ int ignored;
+
+ dynbuf = NULL;
+ if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format,
+ args)) {
+ OPENSSL_free(dynbuf);
+ return -1;
+ }
+ if (dynbuf) {
+ ret = BIO_write(bio, dynbuf, (int)retlen);
+ OPENSSL_free(dynbuf);
+ } else {
+ ret = BIO_write(bio, hugebuf, (int)retlen);
+ }
+ return ret;
+}
+
+/*
+ * As snprintf is not available everywhere, we provide our own
+ * implementation. This function has nothing to do with BIOs, but it's
+ * closely related to BIO_printf, and we need *some* name prefix ... (XXX the
+ * function should be renamed, but to what?)
+ */
+int BIO_snprintf(char *buf, size_t n, const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+
+ ret = BIO_vsnprintf(buf, n, format, args);
+
+ va_end(args);
+ return ret;
+}
+
+int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
+{
+ size_t retlen;
+ int truncated;
+
+ if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
+ return -1;
+
+ if (truncated)
+ /*
+ * In case of truncation, return -1 like traditional snprintf.
+ * (Current drafts for ISO/IEC 9899 say snprintf should return the
+ * number of characters that would have been written, had the buffer
+ * been large enough.)
+ */
+ return -1;
+ return (retlen <= INT_MAX) ? (int)retlen : -1;
+}
diff --git a/crypto/bio/bio_sock.c b/crypto/bio/bio_sock.c
new file mode 100644
index 000000000000..476cbcc5cef1
--- /dev/null
+++ b/crypto/bio/bio_sock.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "bio_local.h"
+#ifndef OPENSSL_NO_SOCK
+# define SOCKET_PROTOCOL IPPROTO_TCP
+# ifdef SO_MAXCONN
+# define MAX_LISTEN SO_MAXCONN
+# elif defined(SOMAXCONN)
+# define MAX_LISTEN SOMAXCONN
+# else
+# define MAX_LISTEN 32
+# endif
+# if defined(OPENSSL_SYS_WINDOWS)
+static int wsa_init_done = 0;
+# endif
+
+# if defined __TANDEM
+# include <unistd.h>
+# include <sys/time.h> /* select */
+# if defined(OPENSSL_TANDEM_FLOSS)
+# include <floss.h(floss_select)>
+# endif
+# elif defined _WIN32
+# include <winsock.h> /* for type fd_set */
+# else
+# include <unistd.h>
+# if defined __VMS
+# include <sys/socket.h>
+# elif defined _HPUX_SOURCE
+# include <sys/time.h>
+# else
+# include <sys/select.h>
+# endif
+# endif
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+int BIO_get_host_ip(const char *str, unsigned char *ip)
+{
+ BIO_ADDRINFO *res = NULL;
+ int ret = 0;
+
+ if (BIO_sock_init() != 1)
+ return 0; /* don't generate another error code here */
+
+ if (BIO_lookup(str, NULL, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) {
+ size_t l;
+
+ if (BIO_ADDRINFO_family(res) != AF_INET) {
+ ERR_raise(ERR_LIB_BIO, BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
+ } else if (BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), NULL, &l)) {
+ /*
+ * Because only AF_INET addresses will reach this far, we can assert
+ * that l should be 4
+ */
+ if (ossl_assert(l == 4))
+ ret = BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), ip, &l);
+ }
+ BIO_ADDRINFO_free(res);
+ } else {
+ ERR_add_error_data(2, "host=", str);
+ }
+
+ return ret;
+}
+
+int BIO_get_port(const char *str, unsigned short *port_ptr)
+{
+ BIO_ADDRINFO *res = NULL;
+ int ret = 0;
+
+ if (str == NULL) {
+ ERR_raise(ERR_LIB_BIO, BIO_R_NO_PORT_DEFINED);
+ return 0;
+ }
+
+ if (BIO_sock_init() != 1)
+ return 0; /* don't generate another error code here */
+
+ if (BIO_lookup(NULL, str, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) {
+ if (BIO_ADDRINFO_family(res) != AF_INET) {
+ ERR_raise(ERR_LIB_BIO, BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET);
+ } else {
+ *port_ptr = ntohs(BIO_ADDR_rawport(BIO_ADDRINFO_address(res)));
+ ret = 1;
+ }
+ BIO_ADDRINFO_free(res);
+ } else {
+ ERR_add_error_data(2, "host=", str);
+ }
+
+ return ret;
+}
+# endif
+
+int BIO_sock_error(int sock)
+{
+ int j = 0, i;
+ socklen_t size = sizeof(j);
+
+ /*
+ * Note: under Windows the third parameter is of type (char *) whereas
+ * under other systems it is (void *) if you don't have a cast it will
+ * choke the compiler: if you do have a cast then you can either go for
+ * (char *) or (void *).
+ */
+ i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, &size);
+ if (i < 0)
+ return get_last_socket_error();
+ else
+ return j;
+}
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+struct hostent *BIO_gethostbyname(const char *name)
+{
+ /*
+ * Caching gethostbyname() results forever is wrong, so we have to let
+ * the true gethostbyname() worry about this
+ */
+ return gethostbyname(name);
+}
+# endif
+
+int BIO_sock_init(void)
+{
+# ifdef OPENSSL_SYS_WINDOWS
+ static struct WSAData wsa_state;
+
+ if (!wsa_init_done) {
+ wsa_init_done = 1;
+ memset(&wsa_state, 0, sizeof(wsa_state));
+ /*
+ * Not making wsa_state available to the rest of the code is formally
+ * wrong. But the structures we use are [believed to be] invariable
+ * among Winsock DLLs, while API availability is [expected to be]
+ * probed at run-time with DSO_global_lookup.
+ */
+ if (WSAStartup(0x0202, &wsa_state) != 0) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling wsastartup()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_WSASTARTUP);
+ return -1;
+ }
+ }
+# endif /* OPENSSL_SYS_WINDOWS */
+# ifdef WATT32
+ extern int _watt_do_exit;
+ _watt_do_exit = 0; /* don't make sock_init() call exit() */
+ if (sock_init())
+ return -1;
+# endif
+
+ return 1;
+}
+
+void bio_sock_cleanup_int(void)
+{
+# ifdef OPENSSL_SYS_WINDOWS
+ if (wsa_init_done) {
+ wsa_init_done = 0;
+ WSACleanup();
+ }
+# endif
+}
+
+int BIO_socket_ioctl(int fd, long type, void *arg)
+{
+ int i;
+
+# ifdef __DJGPP__
+ i = ioctlsocket(fd, type, (char *)arg);
+# else
+# if defined(OPENSSL_SYS_VMS)
+ /*-
+ * 2011-02-18 SMS.
+ * VMS ioctl() can't tolerate a 64-bit "void *arg", but we
+ * observe that all the consumers pass in an "unsigned long *",
+ * so we arrange a local copy with a short pointer, and use
+ * that, instead.
+ */
+# if __INITIAL_POINTER_SIZE == 64
+# define ARG arg_32p
+# pragma pointer_size save
+# pragma pointer_size 32
+ unsigned long arg_32;
+ unsigned long *arg_32p;
+# pragma pointer_size restore
+ arg_32p = &arg_32;
+ arg_32 = *((unsigned long *)arg);
+# else /* __INITIAL_POINTER_SIZE == 64 */
+# define ARG arg
+# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
+# else /* defined(OPENSSL_SYS_VMS) */
+# define ARG arg
+# endif /* defined(OPENSSL_SYS_VMS) [else] */
+
+ i = ioctlsocket(fd, type, ARG);
+# endif /* __DJGPP__ */
+ if (i < 0)
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling ioctlsocket()");
+ return i;
+}
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+int BIO_get_accept_socket(char *host, int bind_mode)
+{
+ int s = INVALID_SOCKET;
+ char *h = NULL, *p = NULL;
+ BIO_ADDRINFO *res = NULL;
+
+ if (!BIO_parse_hostserv(host, &h, &p, BIO_PARSE_PRIO_SERV))
+ return INVALID_SOCKET;
+
+ if (BIO_sock_init() != 1)
+ return INVALID_SOCKET;
+
+ if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0)
+ goto err;
+
+ if ((s = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res),
+ BIO_ADDRINFO_protocol(res), 0)) == INVALID_SOCKET) {
+ s = INVALID_SOCKET;
+ goto err;
+ }
+
+ if (!BIO_listen(s, BIO_ADDRINFO_address(res),
+ bind_mode ? BIO_SOCK_REUSEADDR : 0)) {
+ BIO_closesocket(s);
+ s = INVALID_SOCKET;
+ }
+
+ err:
+ BIO_ADDRINFO_free(res);
+ OPENSSL_free(h);
+ OPENSSL_free(p);
+
+ return s;
+}
+
+int BIO_accept(int sock, char **ip_port)
+{
+ BIO_ADDR res;
+ int ret = -1;
+
+ ret = BIO_accept_ex(sock, &res, 0);
+ if (ret == (int)INVALID_SOCKET) {
+ if (BIO_sock_should_retry(ret)) {
+ ret = -2;
+ goto end;
+ }
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling accept()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR);
+ goto end;
+ }
+
+ if (ip_port != NULL) {
+ char *host = BIO_ADDR_hostname_string(&res, 1);
+ char *port = BIO_ADDR_service_string(&res, 1);
+ if (host != NULL && port != NULL)
+ *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2);
+ else
+ *ip_port = NULL;
+
+ if (*ip_port == NULL) {
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
+ BIO_closesocket(ret);
+ ret = (int)INVALID_SOCKET;
+ } else {
+ strcpy(*ip_port, host);
+ strcat(*ip_port, ":");
+ strcat(*ip_port, port);
+ }
+ OPENSSL_free(host);
+ OPENSSL_free(port);
+ }
+
+ end:
+ return ret;
+}
+# endif
+
+int BIO_set_tcp_ndelay(int s, int on)
+{
+ int ret = 0;
+# if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
+ int opt;
+
+# ifdef SOL_TCP
+ opt = SOL_TCP;
+# else
+# ifdef IPPROTO_TCP
+ opt = IPPROTO_TCP;
+# endif
+# endif
+
+ ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on));
+# endif
+ return (ret == 0);
+}
+
+int BIO_socket_nbio(int s, int mode)
+{
+ int ret = -1;
+ int l;
+
+ l = mode;
+# ifdef FIONBIO
+ l = mode;
+
+ ret = BIO_socket_ioctl(s, FIONBIO, &l);
+# elif defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(FNDELAY))
+ /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
+
+ l = fcntl(s, F_GETFL, 0);
+ if (l == -1) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
+ "calling fcntl()");
+ ret = -1;
+ } else {
+# if defined(O_NONBLOCK)
+ l &= ~O_NONBLOCK;
+# else
+ l &= ~FNDELAY; /* BSD4.x */
+# endif
+ if (mode) {
+# if defined(O_NONBLOCK)
+ l |= O_NONBLOCK;
+# else
+ l |= FNDELAY; /* BSD4.x */
+# endif
+ }
+ ret = fcntl(s, F_SETFL, l);
+
+ if (ret < 0) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
+ "calling fcntl()");
+ }
+ }
+# else
+ /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
+ ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_INVALID_ARGUMENT);
+# endif
+
+ return (ret == 0);
+}
+
+int BIO_sock_info(int sock,
+ enum BIO_sock_info_type type, union BIO_sock_info_u *info)
+{
+ switch (type) {
+ case BIO_SOCK_INFO_ADDRESS:
+ {
+ socklen_t addr_len;
+ int ret = 0;
+ addr_len = sizeof(*info->addr);
+ ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr),
+ &addr_len);
+ if (ret == -1) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling getsockname()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_ERROR);
+ return 0;
+ }
+ if ((size_t)addr_len > sizeof(*info->addr)) {
+ ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS);
+ return 0;
+ }
+ }
+ break;
+ default:
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNKNOWN_INFO_TYPE);
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Wait on fd at most until max_time; succeed immediately if max_time == 0.
+ * If for_read == 0 then assume to wait for writing, else wait for reading.
+ * Returns -1 on error, 0 on timeout, and 1 on success.
+ */
+int BIO_socket_wait(int fd, int for_read, time_t max_time)
+{
+ fd_set confds;
+ struct timeval tv;
+ time_t now;
+
+ if (fd < 0 || fd >= FD_SETSIZE)
+ return -1;
+ if (max_time == 0)
+ return 1;
+
+ now = time(NULL);
+ if (max_time < now)
+ return 0;
+
+ FD_ZERO(&confds);
+ openssl_fdset(fd, &confds);
+ tv.tv_usec = 0;
+ tv.tv_sec = (long)(max_time - now); /* might overflow */
+ return select(fd + 1, for_read ? &confds : NULL,
+ for_read ? NULL : &confds, NULL, &tv);
+}
+#endif /* !defined(OPENSSL_NO_SOCK) */
diff --git a/crypto/bio/bio_sock2.c b/crypto/bio/bio_sock2.c
new file mode 100644
index 000000000000..8bdad0c0b6ae
--- /dev/null
+++ b/crypto/bio/bio_sock2.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "bio_local.h"
+#include "internal/ktls.h"
+
+#include <openssl/err.h>
+
+#ifndef OPENSSL_NO_SOCK
+# ifdef SO_MAXCONN
+# define MAX_LISTEN SO_MAXCONN
+# elif defined(SOMAXCONN)
+# define MAX_LISTEN SOMAXCONN
+# else
+# define MAX_LISTEN 32
+# endif
+
+/*-
+ * BIO_socket - create a socket
+ * @domain: the socket domain (AF_INET, AF_INET6, AF_UNIX, ...)
+ * @socktype: the socket type (SOCK_STEAM, SOCK_DGRAM)
+ * @protocol: the protocol to use (IPPROTO_TCP, IPPROTO_UDP)
+ * @options: BIO socket options (currently unused)
+ *
+ * Creates a socket. This should be called before calling any
+ * of BIO_connect and BIO_listen.
+ *
+ * Returns the file descriptor on success or INVALID_SOCKET on failure. On
+ * failure errno is set, and a status is added to the OpenSSL error stack.
+ */
+int BIO_socket(int domain, int socktype, int protocol, int options)
+{
+ int sock = -1;
+
+ if (BIO_sock_init() != 1)
+ return INVALID_SOCKET;
+
+ sock = socket(domain, socktype, protocol);
+ if (sock == -1) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling socket()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET);
+ return INVALID_SOCKET;
+ }
+
+ return sock;
+}
+
+/*-
+ * BIO_connect - connect to an address
+ * @sock: the socket to connect with
+ * @addr: the address to connect to
+ * @options: BIO socket options
+ *
+ * Connects to the address using the given socket and options.
+ *
+ * Options can be a combination of the following:
+ * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
+ * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
+ * - BIO_SOCK_NODELAY: don't delay small messages.
+ *
+ * options holds BIO socket options that can be used
+ * You should call this for every address returned by BIO_lookup
+ * until the connection is successful.
+ *
+ * Returns 1 on success or 0 on failure. On failure errno is set
+ * and an error status is added to the OpenSSL error stack.
+ */
+int BIO_connect(int sock, const BIO_ADDR *addr, int options)
+{
+ const int on = 1;
+
+ if (sock == -1) {
+ ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET);
+ return 0;
+ }
+
+ if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
+ return 0;
+
+ if (options & BIO_SOCK_KEEPALIVE) {
+ if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
+ (const void *)&on, sizeof(on)) != 0) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling setsockopt()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_KEEPALIVE);
+ return 0;
+ }
+ }
+
+ if (options & BIO_SOCK_NODELAY) {
+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+ (const void *)&on, sizeof(on)) != 0) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling setsockopt()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_NODELAY);
+ return 0;
+ }
+ }
+
+ if (connect(sock, BIO_ADDR_sockaddr(addr),
+ BIO_ADDR_sockaddr_size(addr)) == -1) {
+ if (!BIO_sock_should_retry(-1)) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling connect()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR);
+ }
+ return 0;
+ }
+# ifndef OPENSSL_NO_KTLS
+ /*
+ * The new socket is created successfully regardless of ktls_enable.
+ * ktls_enable doesn't change any functionality of the socket, except
+ * changing the setsockopt to enable the processing of ktls_start.
+ * Thus, it is not a problem to call it for non-TLS sockets.
+ */
+ ktls_enable(sock);
+# endif
+ return 1;
+}
+
+/*-
+ * BIO_bind - bind socket to address
+ * @sock: the socket to set
+ * @addr: local address to bind to
+ * @options: BIO socket options
+ *
+ * Binds to the address using the given socket and options.
+ *
+ * Options can be a combination of the following:
+ * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
+ * for a recently closed port.
+ *
+ * When restarting the program it could be that the port is still in use. If
+ * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
+ * It's recommended that you use this.
+ */
+int BIO_bind(int sock, const BIO_ADDR *addr, int options)
+{
+# ifndef OPENSSL_SYS_WINDOWS
+ int on = 1;
+# endif
+
+ if (sock == -1) {
+ ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET);
+ return 0;
+ }
+
+# ifndef OPENSSL_SYS_WINDOWS
+ /*
+ * SO_REUSEADDR has different behavior on Windows than on
+ * other operating systems, don't set it there.
+ */
+ if (options & BIO_SOCK_REUSEADDR) {
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+ (const void *)&on, sizeof(on)) != 0) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling setsockopt()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_REUSEADDR);
+ return 0;
+ }
+ }
+# endif
+
+ if (bind(sock, BIO_ADDR_sockaddr(addr), BIO_ADDR_sockaddr_size(addr)) != 0) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error() /* may be 0 */,
+ "calling bind()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_BIND_SOCKET);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*-
+ * BIO_listen - Creates a listen socket
+ * @sock: the socket to listen with
+ * @addr: local address to bind to
+ * @options: BIO socket options
+ *
+ * Binds to the address using the given socket and options, then
+ * starts listening for incoming connections.
+ *
+ * Options can be a combination of the following:
+ * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
+ * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
+ * - BIO_SOCK_NODELAY: don't delay small messages.
+ * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
+ * for a recently closed port.
+ * - BIO_SOCK_V6_ONLY: When creating an IPv6 socket, make it listen only
+ * for IPv6 addresses and not IPv4 addresses mapped to IPv6.
+ *
+ * It's recommended that you set up both an IPv6 and IPv4 listen socket, and
+ * then check both for new clients that connect to it. You want to set up
+ * the socket as non-blocking in that case since else it could hang.
+ *
+ * Not all operating systems support IPv4 addresses on an IPv6 socket, and for
+ * others it's an option. If you pass the BIO_LISTEN_V6_ONLY it will try to
+ * create the IPv6 sockets to only listen for IPv6 connection.
+ *
+ * It could be that the first BIO_listen() call will listen to all the IPv6
+ * and IPv4 addresses and that then trying to bind to the IPv4 address will
+ * fail. We can't tell the difference between already listening ourself to
+ * it and someone else listening to it when failing and errno is EADDRINUSE, so
+ * it's recommended to not give an error in that case if the first call was
+ * successful.
+ *
+ * When restarting the program it could be that the port is still in use. If
+ * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
+ * It's recommended that you use this.
+ */
+int BIO_listen(int sock, const BIO_ADDR *addr, int options)
+{
+ int on = 1;
+ int socktype;
+ socklen_t socktype_len = sizeof(socktype);
+
+ if (sock == -1) {
+ ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET);
+ return 0;
+ }
+
+ if (getsockopt(sock, SOL_SOCKET, SO_TYPE,
+ (void *)&socktype, &socktype_len) != 0
+ || socktype_len != sizeof(socktype)) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling getsockopt()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_GETTING_SOCKTYPE);
+ return 0;
+ }
+
+ if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
+ return 0;
+
+ if (options & BIO_SOCK_KEEPALIVE) {
+ if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
+ (const void *)&on, sizeof(on)) != 0) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling setsockopt()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_KEEPALIVE);
+ return 0;
+ }
+ }
+
+ if (options & BIO_SOCK_NODELAY) {
+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+ (const void *)&on, sizeof(on)) != 0) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling setsockopt()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_NODELAY);
+ return 0;
+ }
+ }
+
+ /* On OpenBSD it is always ipv6 only with ipv6 sockets thus read-only */
+# if defined(IPV6_V6ONLY) && !defined(__OpenBSD__)
+ if (BIO_ADDR_family(addr) == AF_INET6) {
+ /*
+ * Note: Windows default of IPV6_V6ONLY is ON, and Linux is OFF.
+ * Therefore we always have to use setsockopt here.
+ */
+ on = options & BIO_SOCK_V6_ONLY ? 1 : 0;
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ (const void *)&on, sizeof(on)) != 0) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling setsockopt()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_LISTEN_V6_ONLY);
+ return 0;
+ }
+ }
+# endif
+
+ if (!BIO_bind(sock, addr, options))
+ return 0;
+
+ if (socktype != SOCK_DGRAM && listen(sock, MAX_LISTEN) == -1) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling listen()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_LISTEN_SOCKET);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*-
+ * BIO_accept_ex - Accept new incoming connections
+ * @sock: the listening socket
+ * @addr: the BIO_ADDR to store the peer address in
+ * @options: BIO socket options, applied on the accepted socket.
+ *
+ */
+int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options)
+{
+ socklen_t len;
+ int accepted_sock;
+ BIO_ADDR locaddr;
+ BIO_ADDR *addr = addr_ == NULL ? &locaddr : addr_;
+
+ len = sizeof(*addr);
+ accepted_sock = accept(accept_sock,
+ BIO_ADDR_sockaddr_noconst(addr), &len);
+ if (accepted_sock == -1) {
+ if (!BIO_sock_should_retry(accepted_sock)) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling accept()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR);
+ }
+ return INVALID_SOCKET;
+ }
+
+ if (!BIO_socket_nbio(accepted_sock, (options & BIO_SOCK_NONBLOCK) != 0)) {
+ closesocket(accepted_sock);
+ return INVALID_SOCKET;
+ }
+
+ return accepted_sock;
+}
+
+/*-
+ * BIO_closesocket - Close a socket
+ * @sock: the socket to close
+ */
+int BIO_closesocket(int sock)
+{
+ if (sock < 0 || closesocket(sock) < 0)
+ return 0;
+ return 1;
+}
+#endif
diff --git a/crypto/bio/bss_acpt.c b/crypto/bio/bss_acpt.c
index 4461eae2333d..1cda96733548 100644
--- a/crypto/bio/bss_acpt.c
+++ b/crypto/bio/bss_acpt.c
@@ -1,12 +1,14 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <stdio.h>
#include <errno.h>
#include "bio_local.h"
@@ -54,10 +56,8 @@ static void BIO_ACCEPT_free(BIO_ACCEPT *a);
static const BIO_METHOD methods_acceptp = {
BIO_TYPE_ACCEPT,
"socket accept",
- /* TODO: Convert to new style write function */
bwrite_conv,
acpt_write,
- /* TODO: Convert to new style read function */
bread_conv,
acpt_read,
acpt_puts,
@@ -93,7 +93,7 @@ static BIO_ACCEPT *BIO_ACCEPT_new(void)
BIO_ACCEPT *ret;
if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
- BIOerr(BIO_F_BIO_ACCEPT_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->accept_family = BIO_FAMILY_IPANY;
@@ -156,10 +156,10 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c)
switch (c->state) {
case ACPT_S_BEFORE:
if (c->param_addr == NULL && c->param_serv == NULL) {
- BIOerr(BIO_F_ACPT_STATE, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED);
- ERR_add_error_data(4,
- "hostname=", c->param_addr,
- " service=", c->param_serv);
+ ERR_raise_data(ERR_LIB_BIO,
+ BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED,
+ "hostname=%s, service=%s",
+ c->param_addr, c->param_serv);
goto exit_loop;
}
@@ -192,7 +192,7 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c)
family = AF_INET6;
} else {
#endif
- BIOerr(BIO_F_ACPT_STATE, BIO_R_UNAVAILABLE_IP_FAMILY);
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNAVAILABLE_IP_FAMILY);
goto exit_loop;
}
break;
@@ -203,7 +203,7 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c)
family = AF_UNSPEC;
break;
default:
- BIOerr(BIO_F_ACPT_STATE, BIO_R_UNSUPPORTED_IP_FAMILY);
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_IP_FAMILY);
goto exit_loop;
}
if (BIO_lookup(c->param_addr, c->param_serv, BIO_LOOKUP_SERVER,
@@ -211,26 +211,31 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c)
goto exit_loop;
}
if (c->addr_first == NULL) {
- BIOerr(BIO_F_ACPT_STATE, BIO_R_LOOKUP_RETURNED_NOTHING);
+ ERR_raise(ERR_LIB_BIO, BIO_R_LOOKUP_RETURNED_NOTHING);
goto exit_loop;
}
- /* We're currently not iterating, but set this as preparation
- * for possible future development in that regard
- */
c->addr_iter = c->addr_first;
c->state = ACPT_S_CREATE_SOCKET;
break;
case ACPT_S_CREATE_SOCKET:
+ ERR_set_mark();
s = BIO_socket(BIO_ADDRINFO_family(c->addr_iter),
BIO_ADDRINFO_socktype(c->addr_iter),
BIO_ADDRINFO_protocol(c->addr_iter), 0);
if (s == (int)INVALID_SOCKET) {
- SYSerr(SYS_F_SOCKET, get_last_socket_error());
- ERR_add_error_data(4,
- "hostname=", c->param_addr,
- " service=", c->param_serv);
- BIOerr(BIO_F_ACPT_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET);
+ if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter)) != NULL) {
+ /*
+ * if there are more addresses to try, do that first
+ */
+ ERR_pop_to_mark();
+ break;
+ }
+ ERR_clear_last_mark();
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling socket(%s, %s)",
+ c->param_addr, c->param_serv);
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET);
goto exit_loop;
}
c->accept_sock = s;
@@ -306,9 +311,11 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c)
if (bio == NULL)
goto exit_loop;
+ BIO_set_callback_ex(bio, BIO_get_callback_ex(b));
+#ifndef OPENSSL_NO_DEPRECATED_3_0
BIO_set_callback(bio, BIO_get_callback(b));
+#endif
BIO_set_callback_arg(bio, BIO_get_callback_arg(b));
-
/*
* If the accept BIO has an bio_chain, we dup it and put the new
* socket at the end.
diff --git a/crypto/bio/bss_bio.c b/crypto/bio/bss_bio.c
index c97349e43282..7fa8778cae10 100644
--- a/crypto/bio/bss_bio.c
+++ b/crypto/bio/bss_bio.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -38,10 +38,8 @@ static void bio_destroy_pair(BIO *bio);
static const BIO_METHOD methods_biop = {
BIO_TYPE_BIO,
"BIO pair",
- /* TODO: Convert to new style write function */
bwrite_conv,
bio_write,
- /* TODO: Convert to new style read function */
bread_conv,
bio_read,
bio_puts,
@@ -286,7 +284,7 @@ static int bio_write(BIO *bio, const char *buf, int num_)
b->request = 0;
if (b->closed) {
/* we already closed */
- BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE);
+ ERR_raise(ERR_LIB_BIO, BIO_R_BROKEN_PIPE);
return -1;
}
@@ -362,7 +360,7 @@ static ossl_ssize_t bio_nwrite0(BIO *bio, char **buf)
b->request = 0;
if (b->closed) {
- BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE);
+ ERR_raise(ERR_LIB_BIO, BIO_R_BROKEN_PIPE);
return -1;
}
@@ -427,10 +425,10 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr)
case BIO_C_SET_WRITE_BUF_SIZE:
if (b->peer) {
- BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE);
+ ERR_raise(ERR_LIB_BIO, BIO_R_IN_USE);
ret = 0;
} else if (num == 0) {
- BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT);
+ ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
ret = 0;
} else {
size_t new_size = num;
@@ -616,14 +614,14 @@ static int bio_make_pair(BIO *bio1, BIO *bio2)
b2 = bio2->ptr;
if (b1->peer != NULL || b2->peer != NULL) {
- BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE);
+ ERR_raise(ERR_LIB_BIO, BIO_R_IN_USE);
return 0;
}
if (b1->buf == NULL) {
b1->buf = OPENSSL_malloc(b1->size);
if (b1->buf == NULL) {
- BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
b1->len = 0;
@@ -633,7 +631,7 @@ static int bio_make_pair(BIO *bio1, BIO *bio2)
if (b2->buf == NULL) {
b2->buf = OPENSSL_malloc(b2->size);
if (b2->buf == NULL) {
- BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
b2->len = 0;
@@ -750,7 +748,7 @@ int BIO_nread0(BIO *bio, char **buf)
long ret;
if (!bio->init) {
- BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED);
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
return -2;
}
@@ -766,7 +764,7 @@ int BIO_nread(BIO *bio, char **buf, int num)
int ret;
if (!bio->init) {
- BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED);
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
return -2;
}
@@ -781,7 +779,7 @@ int BIO_nwrite0(BIO *bio, char **buf)
long ret;
if (!bio->init) {
- BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED);
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
return -2;
}
@@ -797,7 +795,7 @@ int BIO_nwrite(BIO *bio, char **buf, int num)
int ret;
if (!bio->init) {
- BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED);
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
return -2;
}
diff --git a/crypto/bio/bss_conn.c b/crypto/bio/bss_conn.c
index 807a82b23ba2..0d91f25fe70e 100644
--- a/crypto/bio/bss_conn.c
+++ b/crypto/bio/bss_conn.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,6 +11,7 @@
#include <errno.h>
#include "bio_local.h"
+#include "internal/ktls.h"
#ifndef OPENSSL_NO_SOCK
@@ -20,6 +21,9 @@ typedef struct bio_connect_st {
char *param_hostname;
char *param_service;
int connect_mode;
+# ifndef OPENSSL_NO_KTLS
+ unsigned char record_type;
+# endif
BIO_ADDRINFO *addr_first;
const BIO_ADDRINFO *addr_iter;
@@ -59,10 +63,8 @@ void BIO_CONNECT_free(BIO_CONNECT *a);
static const BIO_METHOD methods_connectp = {
BIO_TYPE_CONNECT,
"socket connect",
- /* TODO: Convert to new style write function */
bwrite_conv,
conn_write,
- /* TODO: Convert to new style read function */
bread_conv,
conn_read,
conn_puts,
@@ -85,10 +87,10 @@ static int conn_state(BIO *b, BIO_CONNECT *c)
switch (c->state) {
case BIO_CONN_S_BEFORE:
if (c->param_hostname == NULL && c->param_service == NULL) {
- BIOerr(BIO_F_CONN_STATE, BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED);
- ERR_add_error_data(4,
- "hostname=", c->param_hostname,
- " service=", c->param_service);
+ ERR_raise_data(ERR_LIB_BIO,
+ BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED,
+ "hostname=%s service=%s",
+ c->param_hostname, c->param_service);
goto exit_loop;
}
c->state = BIO_CONN_S_GET_ADDR;
@@ -107,7 +109,7 @@ static int conn_state(BIO *b, BIO_CONNECT *c)
family = AF_INET6;
} else {
#endif
- BIOerr(BIO_F_CONN_STATE, BIO_R_UNAVAILABLE_IP_FAMILY);
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNAVAILABLE_IP_FAMILY);
goto exit_loop;
}
break;
@@ -118,7 +120,7 @@ static int conn_state(BIO *b, BIO_CONNECT *c)
family = AF_UNSPEC;
break;
default:
- BIOerr(BIO_F_CONN_STATE, BIO_R_UNSUPPORTED_IP_FAMILY);
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_IP_FAMILY);
goto exit_loop;
}
if (BIO_lookup(c->param_hostname, c->param_service,
@@ -127,7 +129,7 @@ static int conn_state(BIO *b, BIO_CONNECT *c)
goto exit_loop;
}
if (c->addr_first == NULL) {
- BIOerr(BIO_F_CONN_STATE, BIO_R_LOOKUP_RETURNED_NOTHING);
+ ERR_raise(ERR_LIB_BIO, BIO_R_LOOKUP_RETURNED_NOTHING);
goto exit_loop;
}
c->addr_iter = c->addr_first;
@@ -139,11 +141,10 @@ static int conn_state(BIO *b, BIO_CONNECT *c)
BIO_ADDRINFO_socktype(c->addr_iter),
BIO_ADDRINFO_protocol(c->addr_iter), 0);
if (ret == (int)INVALID_SOCKET) {
- SYSerr(SYS_F_SOCKET, get_last_socket_error());
- ERR_add_error_data(4,
- "hostname=", c->param_hostname,
- " service=", c->param_service);
- BIOerr(BIO_F_CONN_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET);
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling socket(%s, %s)",
+ c->param_hostname, c->param_service);
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET);
goto exit_loop;
}
b->num = ret;
@@ -152,6 +153,7 @@ static int conn_state(BIO *b, BIO_CONNECT *c)
case BIO_CONN_S_CONNECT:
BIO_clear_retry_flags(b);
+ ERR_set_mark();
ret = BIO_connect(b->num, BIO_ADDRINFO_address(c->addr_iter),
BIO_SOCK_KEEPALIVE | c->connect_mode);
b->retry_reason = 0;
@@ -160,7 +162,7 @@ static int conn_state(BIO *b, BIO_CONNECT *c)
BIO_set_retry_special(b);
c->state = BIO_CONN_S_BLOCKED_CONNECT;
b->retry_reason = BIO_RR_CONNECT;
- ERR_clear_error();
+ ERR_pop_to_mark();
} else if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter))
!= NULL) {
/*
@@ -168,23 +170,27 @@ static int conn_state(BIO *b, BIO_CONNECT *c)
*/
BIO_closesocket(b->num);
c->state = BIO_CONN_S_CREATE_SOCKET;
- ERR_clear_error();
+ ERR_pop_to_mark();
break;
} else {
- SYSerr(SYS_F_CONNECT, get_last_socket_error());
- ERR_add_error_data(4,
- "hostname=", c->param_hostname,
- " service=", c->param_service);
+ ERR_clear_last_mark();
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling connect(%s, %s)",
+ c->param_hostname, c->param_service);
c->state = BIO_CONN_S_CONNECT_ERROR;
break;
}
goto exit_loop;
} else {
+ ERR_clear_last_mark();
c->state = BIO_CONN_S_OK;
}
break;
case BIO_CONN_S_BLOCKED_CONNECT:
+ /* wait for socket being writable, before querying BIO_sock_error */
+ if (BIO_socket_wait(b->num, 0, time(NULL)) == 0)
+ break;
i = BIO_sock_error(b->num);
if (i != 0) {
BIO_clear_retry_flags(b);
@@ -194,22 +200,30 @@ static int conn_state(BIO *b, BIO_CONNECT *c)
*/
BIO_closesocket(b->num);
c->state = BIO_CONN_S_CREATE_SOCKET;
- ERR_clear_error();
break;
}
- SYSerr(SYS_F_CONNECT, i);
- ERR_add_error_data(4,
- "hostname=", c->param_hostname,
- " service=", c->param_service);
- BIOerr(BIO_F_CONN_STATE, BIO_R_NBIO_CONNECT_ERROR);
+ ERR_raise_data(ERR_LIB_SYS, i,
+ "calling connect(%s, %s)",
+ c->param_hostname, c->param_service);
+ ERR_raise(ERR_LIB_BIO, BIO_R_NBIO_CONNECT_ERROR);
ret = 0;
goto exit_loop;
- } else
+ } else {
c->state = BIO_CONN_S_OK;
+# ifndef OPENSSL_NO_KTLS
+ /*
+ * The new socket is created successfully regardless of ktls_enable.
+ * ktls_enable doesn't change any functionality of the socket, except
+ * changing the setsockopt to enable the processing of ktls_start.
+ * Thus, it is not a problem to call it for non-TLS sockets.
+ */
+ ktls_enable(b->num);
+# endif
+ }
break;
case BIO_CONN_S_CONNECT_ERROR:
- BIOerr(BIO_F_CONN_STATE, BIO_R_CONNECT_ERROR);
+ ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR);
ret = 0;
goto exit_loop;
@@ -240,7 +254,7 @@ BIO_CONNECT *BIO_CONNECT_new(void)
BIO_CONNECT *ret;
if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
- BIOerr(BIO_F_BIO_CONNECT_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->state = BIO_CONN_S_BEFORE;
@@ -320,7 +334,12 @@ static int conn_read(BIO *b, char *out, int outl)
if (out != NULL) {
clear_socket_error();
- ret = readsocket(b->num, out, outl);
+# ifndef OPENSSL_NO_KTLS
+ if (BIO_get_ktls_recv(b))
+ ret = ktls_read_record(b->num, out, outl);
+ else
+# endif
+ ret = readsocket(b->num, out, outl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (BIO_sock_should_retry(ret))
@@ -345,7 +364,16 @@ static int conn_write(BIO *b, const char *in, int inl)
}
clear_socket_error();
- ret = writesocket(b->num, in, inl);
+# ifndef OPENSSL_NO_KTLS
+ if (BIO_should_ktls_ctrl_msg_flag(b)) {
+ ret = ktls_send_ctrl_message(b->num, data->record_type, in, inl);
+ if (ret >= 0) {
+ ret = inl;
+ BIO_clear_ktls_ctrl_msg_flag(b);
+ }
+ } else
+# endif
+ ret = writesocket(b->num, in, inl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (BIO_sock_should_retry(ret))
@@ -361,6 +389,9 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
const char **pptr = NULL;
long ret = 1;
BIO_CONNECT *data;
+# ifndef OPENSSL_NO_KTLS
+ ktls_crypto_info_t *crypto_info;
+# endif
data = (BIO_CONNECT *)b->ptr;
@@ -518,8 +549,29 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
}
break;
case BIO_CTRL_EOF:
- ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0;
+ ret = (b->flags & BIO_FLAGS_IN_EOF) != 0;
+ break;
+# ifndef OPENSSL_NO_KTLS
+ case BIO_CTRL_SET_KTLS:
+ crypto_info = (ktls_crypto_info_t *)ptr;
+ ret = ktls_start(b->num, crypto_info, num);
+ if (ret)
+ BIO_set_ktls_flag(b, num);
+ break;
+ case BIO_CTRL_GET_KTLS_SEND:
+ return BIO_should_ktls_flag(b, 1) != 0;
+ case BIO_CTRL_GET_KTLS_RECV:
+ return BIO_should_ktls_flag(b, 0) != 0;
+ case BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG:
+ BIO_set_ktls_ctrl_msg_flag(b);
+ data->record_type = num;
+ ret = 0;
+ break;
+ case BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG:
+ BIO_clear_ktls_ctrl_msg_flag(b);
+ ret = 0;
break;
+# endif
default:
ret = 0;
break;
diff --git a/crypto/bio/bss_core.c b/crypto/bio/bss_core.c
new file mode 100644
index 000000000000..7a84b20460c8
--- /dev/null
+++ b/crypto/bio/bss_core.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_dispatch.h>
+#include "bio_local.h"
+#include "internal/cryptlib.h"
+
+typedef struct {
+ OSSL_FUNC_BIO_read_ex_fn *c_bio_read_ex;
+ OSSL_FUNC_BIO_write_ex_fn *c_bio_write_ex;
+ OSSL_FUNC_BIO_gets_fn *c_bio_gets;
+ OSSL_FUNC_BIO_puts_fn *c_bio_puts;
+ OSSL_FUNC_BIO_ctrl_fn *c_bio_ctrl;
+ OSSL_FUNC_BIO_up_ref_fn *c_bio_up_ref;
+ OSSL_FUNC_BIO_free_fn *c_bio_free;
+} BIO_CORE_GLOBALS;
+
+static void bio_core_globals_free(void *vbcg)
+{
+ OPENSSL_free(vbcg);
+}
+
+static void *bio_core_globals_new(OSSL_LIB_CTX *ctx)
+{
+ return OPENSSL_zalloc(sizeof(BIO_CORE_GLOBALS));
+}
+
+static const OSSL_LIB_CTX_METHOD bio_core_globals_method = {
+ OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
+ bio_core_globals_new,
+ bio_core_globals_free,
+};
+
+static ossl_inline BIO_CORE_GLOBALS *get_globals(OSSL_LIB_CTX *libctx)
+{
+ return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_BIO_CORE_INDEX,
+ &bio_core_globals_method);
+}
+
+static int bio_core_read_ex(BIO *bio, char *data, size_t data_len,
+ size_t *bytes_read)
+{
+ BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx);
+
+ if (bcgbl == NULL || bcgbl->c_bio_read_ex == NULL)
+ return 0;
+ return bcgbl->c_bio_read_ex(BIO_get_data(bio), data, data_len, bytes_read);
+}
+
+static int bio_core_write_ex(BIO *bio, const char *data, size_t data_len,
+ size_t *written)
+{
+ BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx);
+
+ if (bcgbl == NULL || bcgbl->c_bio_write_ex == NULL)
+ return 0;
+ return bcgbl->c_bio_write_ex(BIO_get_data(bio), data, data_len, written);
+}
+
+static long bio_core_ctrl(BIO *bio, int cmd, long num, void *ptr)
+{
+ BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx);
+
+ if (bcgbl == NULL || bcgbl->c_bio_ctrl == NULL)
+ return -1;
+ return bcgbl->c_bio_ctrl(BIO_get_data(bio), cmd, num, ptr);
+}
+
+static int bio_core_gets(BIO *bio, char *buf, int size)
+{
+ BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx);
+
+ if (bcgbl == NULL || bcgbl->c_bio_gets == NULL)
+ return -1;
+ return bcgbl->c_bio_gets(BIO_get_data(bio), buf, size);
+}
+
+static int bio_core_puts(BIO *bio, const char *str)
+{
+ BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx);
+
+ if (bcgbl == NULL || bcgbl->c_bio_puts == NULL)
+ return -1;
+ return bcgbl->c_bio_puts(BIO_get_data(bio), str);
+}
+
+static int bio_core_new(BIO *bio)
+{
+ BIO_set_init(bio, 1);
+
+ return 1;
+}
+
+static int bio_core_free(BIO *bio)
+{
+ BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx);
+
+ if (bcgbl == NULL)
+ return 0;
+
+ BIO_set_init(bio, 0);
+ bcgbl->c_bio_free(BIO_get_data(bio));
+
+ return 1;
+}
+
+static const BIO_METHOD corebiometh = {
+ BIO_TYPE_CORE_TO_PROV,
+ "BIO to Core filter",
+ bio_core_write_ex,
+ NULL,
+ bio_core_read_ex,
+ NULL,
+ bio_core_puts,
+ bio_core_gets,
+ bio_core_ctrl,
+ bio_core_new,
+ bio_core_free,
+ NULL,
+};
+
+const BIO_METHOD *BIO_s_core(void)
+{
+ return &corebiometh;
+}
+
+BIO *BIO_new_from_core_bio(OSSL_LIB_CTX *libctx, OSSL_CORE_BIO *corebio)
+{
+ BIO *outbio;
+ BIO_CORE_GLOBALS *bcgbl = get_globals(libctx);
+
+ /* Check the library context has been initialised with the callbacks */
+ if (bcgbl == NULL || (bcgbl->c_bio_write_ex == NULL && bcgbl->c_bio_read_ex == NULL))
+ return NULL;
+
+ if ((outbio = BIO_new_ex(libctx, BIO_s_core())) == NULL)
+ return NULL;
+
+ if (!bcgbl->c_bio_up_ref(corebio)) {
+ BIO_free(outbio);
+ return NULL;
+ }
+ BIO_set_data(outbio, corebio);
+ return outbio;
+}
+
+int ossl_bio_init_core(OSSL_LIB_CTX *libctx, const OSSL_DISPATCH *fns)
+{
+ BIO_CORE_GLOBALS *bcgbl = get_globals(libctx);
+
+ if (bcgbl == NULL)
+ return 0;
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_BIO_READ_EX:
+ if (bcgbl->c_bio_read_ex == NULL)
+ bcgbl->c_bio_read_ex = OSSL_FUNC_BIO_read_ex(fns);
+ break;
+ case OSSL_FUNC_BIO_WRITE_EX:
+ if (bcgbl->c_bio_write_ex == NULL)
+ bcgbl->c_bio_write_ex = OSSL_FUNC_BIO_write_ex(fns);
+ break;
+ case OSSL_FUNC_BIO_GETS:
+ if (bcgbl->c_bio_gets == NULL)
+ bcgbl->c_bio_gets = OSSL_FUNC_BIO_gets(fns);
+ break;
+ case OSSL_FUNC_BIO_PUTS:
+ if (bcgbl->c_bio_puts == NULL)
+ bcgbl->c_bio_puts = OSSL_FUNC_BIO_puts(fns);
+ break;
+ case OSSL_FUNC_BIO_CTRL:
+ if (bcgbl->c_bio_ctrl == NULL)
+ bcgbl->c_bio_ctrl = OSSL_FUNC_BIO_ctrl(fns);
+ break;
+ case OSSL_FUNC_BIO_UP_REF:
+ if (bcgbl->c_bio_up_ref == NULL)
+ bcgbl->c_bio_up_ref = OSSL_FUNC_BIO_up_ref(fns);
+ break;
+ case OSSL_FUNC_BIO_FREE:
+ if (bcgbl->c_bio_free == NULL)
+ bcgbl->c_bio_free = OSSL_FUNC_BIO_free(fns);
+ break;
+ }
+ }
+
+ return 1;
+}
diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c
index c87ba4d26508..8ca1cf64ed47 100644
--- a/crypto/bio/bss_dgram.c
+++ b/crypto/bio/bss_dgram.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -57,6 +57,8 @@ static int dgram_sctp_puts(BIO *h, const char *str);
static long dgram_sctp_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static int dgram_sctp_new(BIO *h);
static int dgram_sctp_free(BIO *data);
+static int dgram_sctp_wait_for_dry(BIO *b);
+static int dgram_sctp_msg_waiting(BIO *b);
# ifdef SCTP_AUTHENTICATION_EVENT
static void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification
*snp);
@@ -70,10 +72,8 @@ static void get_current_time(struct timeval *t);
static const BIO_METHOD methods_dgramp = {
BIO_TYPE_DGRAM,
"datagram socket",
- /* TODO: Convert to new style write function */
bwrite_conv,
dgram_write,
- /* TODO: Convert to new style read function */
bread_conv,
dgram_read,
dgram_puts,
@@ -88,10 +88,8 @@ static const BIO_METHOD methods_dgramp = {
static const BIO_METHOD methods_dgramp_sctp = {
BIO_TYPE_DGRAM_SCTP,
"datagram sctp socket",
- /* TODO: Convert to new style write function */
bwrite_conv,
dgram_sctp_write,
- /* TODO: Convert to new style write function */
bread_conv,
dgram_sctp_read,
dgram_sctp_puts,
@@ -128,7 +126,7 @@ typedef struct bio_dgram_sctp_data_st {
struct bio_dgram_sctp_sndinfo sndinfo;
struct bio_dgram_sctp_rcvinfo rcvinfo;
struct bio_dgram_sctp_prinfo prinfo;
- void (*handle_notifications) (BIO *bio, void *context, void *buf);
+ BIO_dgram_sctp_notification_handler_fn handle_notifications;
void *notification_context;
int in_handshake;
int ccs_rcvd;
@@ -197,12 +195,6 @@ static void dgram_adjust_rcv_timeout(BIO *b)
{
# if defined(SO_RCVTIMEO)
bio_dgram_data *data = (bio_dgram_data *)b->ptr;
- union {
- size_t s;
- int i;
- } sz = {
- 0
- };
/* Is a timer active? */
if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) {
@@ -212,21 +204,21 @@ static void dgram_adjust_rcv_timeout(BIO *b)
# ifdef OPENSSL_SYS_WINDOWS
int timeout;
- sz.i = sizeof(timeout);
+ int sz = sizeof(timeout);
if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
- (void *)&timeout, &sz.i) < 0) {
+ (void *)&timeout, &sz) < 0) {
perror("getsockopt");
} else {
data->socket_timeout.tv_sec = timeout / 1000;
data->socket_timeout.tv_usec = (timeout % 1000) * 1000;
}
# else
- sz.i = sizeof(data->socket_timeout);
+ socklen_t sz = sizeof(data->socket_timeout);
if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
- &(data->socket_timeout), (void *)&sz) < 0) {
+ &(data->socket_timeout), &sz) < 0) {
perror("getsockopt");
- } else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0)
- OPENSSL_assert(sz.s <= sizeof(data->socket_timeout));
+ } else
+ OPENSSL_assert(sz <= sizeof(data->socket_timeout));
# endif
/* Get current time */
@@ -609,19 +601,14 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
break;
case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
{
- union {
- size_t s;
- int i;
- } sz = {
- 0
- };
# ifdef OPENSSL_SYS_WINDOWS
+ int sz = 0;
int timeout;
struct timeval *tv = (struct timeval *)ptr;
- sz.i = sizeof(timeout);
+ sz = sizeof(timeout);
if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
- (void *)&timeout, &sz.i) < 0) {
+ (void *)&timeout, &sz) < 0) {
perror("getsockopt");
ret = -1;
} else {
@@ -630,16 +617,15 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
ret = sizeof(*tv);
}
# else
- sz.i = sizeof(struct timeval);
+ socklen_t sz = sizeof(struct timeval);
if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
- ptr, (void *)&sz) < 0) {
+ ptr, &sz) < 0) {
perror("getsockopt");
ret = -1;
- } else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0) {
- OPENSSL_assert(sz.s <= sizeof(struct timeval));
- ret = (int)sz.s;
- } else
- ret = sz.i;
+ } else {
+ OPENSSL_assert(sz <= sizeof(struct timeval));
+ ret = (int)sz;
+ }
# endif
}
break;
@@ -666,19 +652,14 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
break;
case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
{
- union {
- size_t s;
- int i;
- } sz = {
- 0
- };
# ifdef OPENSSL_SYS_WINDOWS
+ int sz = 0;
int timeout;
struct timeval *tv = (struct timeval *)ptr;
- sz.i = sizeof(timeout);
+ sz = sizeof(timeout);
if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
- (void *)&timeout, &sz.i) < 0) {
+ (void *)&timeout, &sz) < 0) {
perror("getsockopt");
ret = -1;
} else {
@@ -687,16 +668,15 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
ret = sizeof(*tv);
}
# else
- sz.i = sizeof(struct timeval);
+ socklen_t sz = sizeof(struct timeval);
if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
- ptr, (void *)&sz) < 0) {
+ ptr, &sz) < 0) {
perror("getsockopt");
ret = -1;
- } else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0) {
- OPENSSL_assert(sz.s <= sizeof(struct timeval));
- ret = (int)sz.s;
- } else
- ret = sz.i;
+ } else {
+ OPENSSL_assert(sz <= sizeof(struct timeval));
+ ret = (int)sz;
+ }
# endif
}
break;
@@ -845,8 +825,8 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag)
sizeof(struct sctp_authchunk));
if (ret < 0) {
BIO_vfree(bio);
- BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB);
- ERR_add_error_data(1, "Ensure SCTP AUTH chunks are enabled in kernel");
+ ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB,
+ "Ensure SCTP AUTH chunks are enabled in kernel");
return NULL;
}
auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE;
@@ -855,8 +835,8 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag)
sizeof(struct sctp_authchunk));
if (ret < 0) {
BIO_vfree(bio);
- BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB);
- ERR_add_error_data(1, "Ensure SCTP AUTH chunks are enabled in kernel");
+ ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB,
+ "Ensure SCTP AUTH chunks are enabled in kernel");
return NULL;
}
@@ -893,10 +873,9 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag)
if (!auth_data || !auth_forward) {
BIO_vfree(bio);
- BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB);
- ERR_add_error_data(1,
- "Ensure SCTP AUTH chunks are enabled on the "
- "underlying socket");
+ ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB,
+ "Ensure SCTP AUTH chunks are enabled on the "
+ "underlying socket");
return NULL;
}
@@ -960,7 +939,7 @@ static int dgram_sctp_new(BIO *bi)
bi->init = 0;
bi->num = 0;
if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL) {
- BIOerr(BIO_F_DGRAM_SCTP_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
# ifdef SCTP_PR_SCTP_NONE
@@ -1011,7 +990,6 @@ static int dgram_sctp_read(BIO *b, char *out, int outl)
int ret = 0, n = 0, i, optval;
socklen_t optlen;
bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;
- union sctp_notification *snp;
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg;
@@ -1077,8 +1055,10 @@ static int dgram_sctp_read(BIO *b, char *out, int outl)
}
if (msg.msg_flags & MSG_NOTIFICATION) {
- snp = (union sctp_notification *)out;
- if (snp->sn_header.sn_type == SCTP_SENDER_DRY_EVENT) {
+ union sctp_notification snp;
+
+ memcpy(&snp, out, sizeof(snp));
+ if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT) {
# ifdef SCTP_EVENT
struct sctp_event event;
# else
@@ -1118,17 +1098,19 @@ static int dgram_sctp_read(BIO *b, char *out, int outl)
# endif
}
# ifdef SCTP_AUTHENTICATION_EVENT
- if (snp->sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
- dgram_sctp_handle_auth_free_key_event(b, snp);
+ if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
+ dgram_sctp_handle_auth_free_key_event(b, &snp);
# endif
if (data->handle_notifications != NULL)
data->handle_notifications(b, data->notification_context,
(void *)out);
+ memset(&snp, 0, sizeof(snp));
memset(out, 0, outl);
- } else
+ } else {
ret += n;
+ }
}
while ((msg.msg_flags & MSG_NOTIFICATION) && (msg.msg_flags & MSG_EOR)
&& (ret < outl));
@@ -1195,7 +1177,7 @@ static int dgram_sctp_read(BIO *b, char *out, int outl)
(socklen_t) (sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
authchunks = OPENSSL_malloc(optlen);
if (authchunks == NULL) {
- BIOerr(BIO_F_DGRAM_SCTP_READ, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return -1;
}
memset(authchunks, 0, optlen);
@@ -1215,7 +1197,7 @@ static int dgram_sctp_read(BIO *b, char *out, int outl)
OPENSSL_free(authchunks);
if (!auth_data || !auth_forward) {
- BIOerr(BIO_F_DGRAM_SCTP_READ, BIO_R_CONNECT_ERROR);
+ ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR);
return -1;
}
@@ -1566,6 +1548,10 @@ static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
else
data->save_shutdown = 0;
break;
+ case BIO_CTRL_DGRAM_SCTP_WAIT_FOR_DRY:
+ return dgram_sctp_wait_for_dry(b);
+ case BIO_CTRL_DGRAM_SCTP_MSG_WAITING:
+ return dgram_sctp_msg_waiting(b);
default:
/*
@@ -1578,11 +1564,8 @@ static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
}
int BIO_dgram_sctp_notification_cb(BIO *b,
- void (*handle_notifications) (BIO *bio,
- void
- *context,
- void *buf),
- void *context)
+ BIO_dgram_sctp_notification_handler_fn handle_notifications,
+ void *context)
{
bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;
@@ -1610,6 +1593,11 @@ int BIO_dgram_sctp_notification_cb(BIO *b,
*/
int BIO_dgram_sctp_wait_for_dry(BIO *b)
{
+ return (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SCTP_WAIT_FOR_DRY, 0, NULL);
+}
+
+static int dgram_sctp_wait_for_dry(BIO *b)
+{
int is_dry = 0;
int sockflags = 0;
int n, ret;
@@ -1768,6 +1756,11 @@ int BIO_dgram_sctp_wait_for_dry(BIO *b)
int BIO_dgram_sctp_msg_waiting(BIO *b)
{
+ return (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SCTP_MSG_WAITING, 0, NULL);
+}
+
+static int dgram_sctp_msg_waiting(BIO *b)
+{
int n, sockflags;
union sctp_notification snp;
struct msghdr msg;
@@ -1907,22 +1900,22 @@ static void get_current_time(struct timeval *t)
{
# if defined(_WIN32)
SYSTEMTIME st;
- union {
- unsigned __int64 ul;
- FILETIME ft;
- } now;
+ unsigned __int64 now_ul;
+ FILETIME now_ft;
GetSystemTime(&st);
- SystemTimeToFileTime(&st, &now.ft);
+ SystemTimeToFileTime(&st, &now_ft);
+ now_ul = ((unsigned __int64)now_ft.dwHighDateTime << 32) | now_ft.dwLowDateTime;
# ifdef __MINGW32__
- now.ul -= 116444736000000000ULL;
+ now_ul -= 116444736000000000ULL;
# else
- now.ul -= 116444736000000000UI64; /* re-bias to 1/1/1970 */
+ now_ul -= 116444736000000000UI64; /* re-bias to 1/1/1970 */
# endif
- t->tv_sec = (long)(now.ul / 10000000);
- t->tv_usec = ((int)(now.ul % 10000000)) / 10;
+ t->tv_sec = (long)(now_ul / 10000000);
+ t->tv_usec = ((int)(now_ul % 10000000)) / 10;
# else
- gettimeofday(t, NULL);
+ if (gettimeofday(t, NULL) < 0)
+ perror("gettimeofday");
# endif
}
diff --git a/crypto/bio/bss_fd.c b/crypto/bio/bss_fd.c
index ccbe1626baf2..f756225edb21 100644
--- a/crypto/bio/bss_fd.c
+++ b/crypto/bio/bss_fd.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -60,10 +60,8 @@ int BIO_fd_should_retry(int s);
static const BIO_METHOD methods_fdp = {
BIO_TYPE_FD,
"file descriptor",
- /* TODO: Convert to new style write function */
bwrite_conv,
fd_write,
- /* TODO: Convert to new style read function */
bread_conv,
fd_read,
fd_puts,
@@ -94,7 +92,7 @@ static int fd_new(BIO *bi)
bi->init = 0;
bi->num = -1;
bi->ptr = NULL;
- bi->flags = BIO_FLAGS_UPLINK; /* essentially redundant */
+ bi->flags = BIO_FLAGS_UPLINK_INTERNAL; /* essentially redundant */
return 1;
}
@@ -107,7 +105,7 @@ static int fd_free(BIO *a)
UP_close(a->num);
}
a->init = 0;
- a->flags = BIO_FLAGS_UPLINK;
+ a->flags = BIO_FLAGS_UPLINK_INTERNAL;
}
return 1;
}
@@ -189,7 +187,7 @@ static long fd_ctrl(BIO *b, int cmd, long num, void *ptr)
ret = 1;
break;
case BIO_CTRL_EOF:
- ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0;
+ ret = (b->flags & BIO_FLAGS_IN_EOF) != 0;
break;
default:
ret = 0;
diff --git a/crypto/bio/bss_file.c b/crypto/bio/bss_file.c
index 1a70ce799404..a6143b6abcf6 100644
--- a/crypto/bio/bss_file.c
+++ b/crypto/bio/bss_file.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -42,10 +42,8 @@ static int file_free(BIO *data);
static const BIO_METHOD methods_filep = {
BIO_TYPE_FILE,
"FILE pointer",
- /* TODO: Convert to new style write function */
bwrite_conv,
file_write,
- /* TODO: Convert to new style read function */
bread_conv,
file_read,
file_puts,
@@ -66,16 +64,17 @@ BIO *BIO_new_file(const char *filename, const char *mode)
fp_flags |= BIO_FP_TEXT;
if (file == NULL) {
- SYSerr(SYS_F_FOPEN, get_last_sys_error());
- ERR_add_error_data(5, "fopen('", filename, "','", mode, "')");
+ ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
+ "calling fopen(%s, %s)",
+ filename, mode);
if (errno == ENOENT
#ifdef ENXIO
|| errno == ENXIO
#endif
)
- BIOerr(BIO_F_BIO_NEW_FILE, BIO_R_NO_SUCH_FILE);
+ ERR_raise(ERR_LIB_BIO, BIO_R_NO_SUCH_FILE);
else
- BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB);
+ ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB);
return NULL;
}
if ((ret = BIO_new(BIO_s_file())) == NULL) {
@@ -83,8 +82,8 @@ BIO *BIO_new_file(const char *filename, const char *mode)
return NULL;
}
- BIO_clear_flags(ret, BIO_FLAGS_UPLINK); /* we did fopen -> we disengage
- * UPLINK */
+ /* we did fopen -> we disengage UPLINK */
+ BIO_clear_flags(ret, BIO_FLAGS_UPLINK_INTERNAL);
BIO_set_fp(ret, file, fp_flags);
return ret;
}
@@ -97,7 +96,7 @@ BIO *BIO_new_fp(FILE *stream, int close_flag)
return NULL;
/* redundant flag, left for documentation purposes */
- BIO_set_flags(ret, BIO_FLAGS_UPLINK);
+ BIO_set_flags(ret, BIO_FLAGS_UPLINK_INTERNAL);
BIO_set_fp(ret, stream, close_flag);
return ret;
}
@@ -112,7 +111,7 @@ static int file_new(BIO *bi)
bi->init = 0;
bi->num = 0;
bi->ptr = NULL;
- bi->flags = BIO_FLAGS_UPLINK; /* default to UPLINK */
+ bi->flags = BIO_FLAGS_UPLINK_INTERNAL; /* default to UPLINK */
return 1;
}
@@ -122,12 +121,12 @@ static int file_free(BIO *a)
return 0;
if (a->shutdown) {
if ((a->init) && (a->ptr != NULL)) {
- if (a->flags & BIO_FLAGS_UPLINK)
+ if (a->flags & BIO_FLAGS_UPLINK_INTERNAL)
UP_fclose(a->ptr);
else
fclose(a->ptr);
a->ptr = NULL;
- a->flags = BIO_FLAGS_UPLINK;
+ a->flags = BIO_FLAGS_UPLINK_INTERNAL;
}
a->init = 0;
}
@@ -139,15 +138,16 @@ static int file_read(BIO *b, char *out, int outl)
int ret = 0;
if (b->init && (out != NULL)) {
- if (b->flags & BIO_FLAGS_UPLINK)
+ if (b->flags & BIO_FLAGS_UPLINK_INTERNAL)
ret = UP_fread(out, 1, (int)outl, b->ptr);
else
ret = fread(out, 1, (int)outl, (FILE *)b->ptr);
if (ret == 0
- && (b->flags & BIO_FLAGS_UPLINK) ? UP_ferror((FILE *)b->ptr) :
- ferror((FILE *)b->ptr)) {
- SYSerr(SYS_F_FREAD, get_last_sys_error());
- BIOerr(BIO_F_FILE_READ, ERR_R_SYS_LIB);
+ && (b->flags & BIO_FLAGS_UPLINK_INTERNAL
+ ? UP_ferror((FILE *)b->ptr) : ferror((FILE *)b->ptr))) {
+ ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
+ "calling fread()");
+ ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB);
ret = -1;
}
}
@@ -159,7 +159,7 @@ static int file_write(BIO *b, const char *in, int inl)
int ret = 0;
if (b->init && (in != NULL)) {
- if (b->flags & BIO_FLAGS_UPLINK)
+ if (b->flags & BIO_FLAGS_UPLINK_INTERNAL)
ret = UP_fwrite(in, (int)inl, 1, b->ptr);
else
ret = fwrite(in, (int)inl, 1, (FILE *)b->ptr);
@@ -186,20 +186,20 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr)
switch (cmd) {
case BIO_C_FILE_SEEK:
case BIO_CTRL_RESET:
- if (b->flags & BIO_FLAGS_UPLINK)
+ if (b->flags & BIO_FLAGS_UPLINK_INTERNAL)
ret = (long)UP_fseek(b->ptr, num, 0);
else
ret = (long)fseek(fp, num, 0);
break;
case BIO_CTRL_EOF:
- if (b->flags & BIO_FLAGS_UPLINK)
+ if (b->flags & BIO_FLAGS_UPLINK_INTERNAL)
ret = (long)UP_feof(fp);
else
ret = (long)feof(fp);
break;
case BIO_C_FILE_TELL:
case BIO_CTRL_INFO:
- if (b->flags & BIO_FLAGS_UPLINK)
+ if (b->flags & BIO_FLAGS_UPLINK_INTERNAL)
ret = UP_ftell(b->ptr);
else
ret = ftell(fp);
@@ -209,22 +209,22 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr)
b->shutdown = (int)num & BIO_CLOSE;
b->ptr = ptr;
b->init = 1;
-# if BIO_FLAGS_UPLINK!=0
+# if BIO_FLAGS_UPLINK_INTERNAL!=0
# if defined(__MINGW32__) && defined(__MSVCRT__) && !defined(_IOB_ENTRIES)
# define _IOB_ENTRIES 20
# endif
/* Safety net to catch purely internal BIO_set_fp calls */
-# if defined(_MSC_VER) && _MSC_VER>=1900
+# if (defined(_MSC_VER) && _MSC_VER>=1900) || defined(__BORLANDC__)
if (ptr == stdin || ptr == stdout || ptr == stderr)
- BIO_clear_flags(b, BIO_FLAGS_UPLINK);
+ BIO_clear_flags(b, BIO_FLAGS_UPLINK_INTERNAL);
# elif defined(_IOB_ENTRIES)
if ((size_t)ptr >= (size_t)stdin &&
(size_t)ptr < (size_t)(stdin + _IOB_ENTRIES))
- BIO_clear_flags(b, BIO_FLAGS_UPLINK);
+ BIO_clear_flags(b, BIO_FLAGS_UPLINK_INTERNAL);
# endif
# endif
# ifdef UP_fsetmod
- if (b->flags & BIO_FLAGS_UPLINK)
+ if (b->flags & BIO_FLAGS_UPLINK_INTERNAL)
UP_fsetmod(b->ptr, (char)((num & BIO_FP_TEXT) ? 't' : 'b'));
else
# endif
@@ -235,6 +235,15 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr)
_setmode(fd, _O_TEXT);
else
_setmode(fd, _O_BINARY);
+ /*
+ * Reports show that ftell() isn't trustable in text mode.
+ * This has been confirmed as a bug in the Universal C RTL, see
+ * https://developercommunity.visualstudio.com/content/problem/425878/fseek-ftell-fail-in-text-mode-for-unix-style-text.html
+ * The suggested work-around from Microsoft engineering is to
+ * turn off buffering until the bug is resolved.
+ */
+ if ((num & BIO_FP_TEXT) != 0)
+ setvbuf((FILE *)ptr, NULL, _IONBF, 0);
# elif defined(OPENSSL_SYS_MSDOS)
int fd = fileno((FILE *)ptr);
/* Set correct text/binary mode */
@@ -270,7 +279,7 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr)
else if (num & BIO_FP_READ)
OPENSSL_strlcpy(p, "r", sizeof(p));
else {
- BIOerr(BIO_F_FILE_CTRL, BIO_R_BAD_FOPEN_MODE);
+ ERR_raise(ERR_LIB_BIO, BIO_R_BAD_FOPEN_MODE);
ret = 0;
break;
}
@@ -285,16 +294,17 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr)
# endif
fp = openssl_fopen(ptr, p);
if (fp == NULL) {
- SYSerr(SYS_F_FOPEN, get_last_sys_error());
- ERR_add_error_data(5, "fopen('", ptr, "','", p, "')");
- BIOerr(BIO_F_FILE_CTRL, ERR_R_SYS_LIB);
+ ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
+ "calling fopen(%s, %s)",
+ ptr, p);
+ ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB);
ret = 0;
break;
}
b->ptr = fp;
b->init = 1;
- BIO_clear_flags(b, BIO_FLAGS_UPLINK); /* we did fopen -> we disengage
- * UPLINK */
+ /* we did fopen -> we disengage UPLINK */
+ BIO_clear_flags(b, BIO_FLAGS_UPLINK_INTERNAL);
break;
case BIO_C_GET_FILE_PTR:
/* the ptr parameter is actually a FILE ** in this case. */
@@ -310,12 +320,12 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr)
b->shutdown = (int)num;
break;
case BIO_CTRL_FLUSH:
- st = b->flags & BIO_FLAGS_UPLINK
+ st = b->flags & BIO_FLAGS_UPLINK_INTERNAL
? UP_fflush(b->ptr) : fflush((FILE *)b->ptr);
if (st == EOF) {
- SYSerr(SYS_F_FFLUSH, get_last_sys_error());
- ERR_add_error_data(1, "fflush()");
- BIOerr(BIO_F_FILE_CTRL, ERR_R_SYS_LIB);
+ ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
+ "calling fflush()");
+ ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB);
ret = 0;
}
break;
@@ -339,7 +349,7 @@ static int file_gets(BIO *bp, char *buf, int size)
int ret = 0;
buf[0] = '\0';
- if (bp->flags & BIO_FLAGS_UPLINK) {
+ if (bp->flags & BIO_FLAGS_UPLINK_INTERNAL) {
if (!UP_fgets(buf, size, bp->ptr))
goto err;
} else {
@@ -395,10 +405,8 @@ static int file_free(BIO *a)
static const BIO_METHOD methods_filep = {
BIO_TYPE_FILE,
"FILE pointer",
- /* TODO: Convert to new style write function */
bwrite_conv,
file_write,
- /* TODO: Convert to new style read function */
bread_conv,
file_read,
file_puts,
diff --git a/crypto/bio/bss_log.c b/crypto/bio/bss_log.c
index b9579faaa2a5..82abfd5cec63 100644
--- a/crypto/bio/bss_log.c
+++ b/crypto/bio/bss_log.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -87,7 +87,6 @@ static void xcloselog(BIO *bp);
static const BIO_METHOD methods_slg = {
BIO_TYPE_MEM,
"syslog",
- /* TODO: Convert to new style write function */
bwrite_conv,
slg_write,
NULL, /* slg_write_old, */
@@ -196,8 +195,10 @@ static int slg_write(BIO *b, const char *in, int inl)
/* The default */
};
+ if (inl < 0)
+ return 0;
if ((buf = OPENSSL_malloc(inl + 1)) == NULL) {
- BIOerr(BIO_F_SLG_WRITE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(buf, in, inl);
diff --git a/crypto/bio/bss_mem.c b/crypto/bio/bss_mem.c
index 2420b26553e0..9153c1f1cd81 100644
--- a/crypto/bio/bss_mem.c
+++ b/crypto/bio/bss_mem.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -26,10 +26,8 @@ static int mem_buf_sync(BIO *h);
static const BIO_METHOD mem_method = {
BIO_TYPE_MEM,
"memory buffer",
- /* TODO: Convert to new style write function */
bwrite_conv,
mem_write,
- /* TODO: Convert to new style read function */
bread_conv,
mem_read,
mem_puts,
@@ -43,10 +41,8 @@ static const BIO_METHOD mem_method = {
static const BIO_METHOD secmem_method = {
BIO_TYPE_MEM,
"secure memory buffer",
- /* TODO: Convert to new style write function */
bwrite_conv,
mem_write,
- /* TODO: Convert to new style read function */
bread_conv,
mem_read,
mem_puts,
@@ -91,7 +87,7 @@ BIO *BIO_new_mem_buf(const void *buf, int len)
size_t sz;
if (buf == NULL) {
- BIOerr(BIO_F_BIO_NEW_MEM_BUF, BIO_R_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
sz = (len < 0) ? strlen(buf) : (size_t)len;
@@ -176,6 +172,7 @@ static int mem_buf_free(BIO *a)
/*
* Reallocate memory buffer if read pointer differs
+ * NOT FOR RDONLY
*/
static int mem_buf_sync(BIO *b)
{
@@ -220,17 +217,17 @@ static int mem_write(BIO *b, const char *in, int inl)
int blen;
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
- if (in == NULL) {
- BIOerr(BIO_F_MEM_WRITE, BIO_R_NULL_PARAMETER);
- goto end;
- }
if (b->flags & BIO_FLAGS_MEM_RDONLY) {
- BIOerr(BIO_F_MEM_WRITE, BIO_R_WRITE_TO_READ_ONLY_BIO);
+ ERR_raise(ERR_LIB_BIO, BIO_R_WRITE_TO_READ_ONLY_BIO);
goto end;
}
BIO_clear_retry_flags(b);
if (inl == 0)
return 0;
+ if (in == NULL) {
+ ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
+ goto end;
+ }
blen = bbm->readp->length;
mem_buf_sync(b);
if (BUF_MEM_grow_clean(bbm->buf, blen + inl) == 0)
@@ -247,12 +244,18 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr)
long ret = 1;
char **pptr;
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
- BUF_MEM *bm;
+ BUF_MEM *bm, *bo; /* bio_mem, bio_other */
+ long off, remain;
- if (b->flags & BIO_FLAGS_MEM_RDONLY)
+ if (b->flags & BIO_FLAGS_MEM_RDONLY) {
bm = bbm->buf;
- else
+ bo = bbm->readp;
+ } else {
bm = bbm->readp;
+ bo = bbm->buf;
+ }
+ off = (bm->data == bo->data) ? 0 : bm->data - bo->data;
+ remain = bm->length;
switch (cmd) {
case BIO_CTRL_RESET:
@@ -270,6 +273,18 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr)
}
}
break;
+ case BIO_C_FILE_SEEK:
+ if (num < 0 || num > off + remain)
+ return -1; /* Can't see outside of the current buffer */
+
+ bm->data = (num != 0) ? bo->data + num : bo->data;
+ bm->length = bo->length - num;
+ bm->max = bo->max - num;
+ off = num;
+ /* FALLTHRU */
+ case BIO_C_FILE_TELL:
+ ret = off;
+ break;
case BIO_CTRL_EOF:
ret = (long)(bm->length == 0);
break;
@@ -280,7 +295,7 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr)
ret = (long)bm->length;
if (ptr != NULL) {
pptr = (char **)ptr;
- *pptr = (char *)bm->data;
+ *pptr = (char *)(bm->data);
}
break;
case BIO_C_SET_BUF_MEM:
diff --git a/crypto/bio/bss_null.c b/crypto/bio/bss_null.c
index e73ce7841d41..ba266f186c21 100644
--- a/crypto/bio/bss_null.c
+++ b/crypto/bio/bss_null.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -20,10 +20,8 @@ static long null_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static const BIO_METHOD null_method = {
BIO_TYPE_NULL,
"NULL",
- /* TODO: Convert to new style write function */
bwrite_conv,
null_write,
- /* TODO: Convert to new style read function */
bread_conv,
null_read,
null_puts,
diff --git a/crypto/bio/bss_sock.c b/crypto/bio/bss_sock.c
index 6251f3d46a17..f5d88102303a 100644
--- a/crypto/bio/bss_sock.c
+++ b/crypto/bio/bss_sock.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,6 +11,7 @@
#include <errno.h>
#include "bio_local.h"
#include "internal/cryptlib.h"
+#include "internal/ktls.h"
#ifndef OPENSSL_NO_SOCK
@@ -37,10 +38,8 @@ int BIO_sock_should_retry(int s);
static const BIO_METHOD methods_sockp = {
BIO_TYPE_SOCKET,
"socket",
- /* TODO: Convert to new style write function */
bwrite_conv,
sock_write,
- /* TODO: Convert to new style read function */
bread_conv,
sock_read,
sock_puts,
@@ -64,6 +63,17 @@ BIO *BIO_new_socket(int fd, int close_flag)
if (ret == NULL)
return NULL;
BIO_set_fd(ret, fd, close_flag);
+# ifndef OPENSSL_NO_KTLS
+ {
+ /*
+ * The new socket is created successfully regardless of ktls_enable.
+ * ktls_enable doesn't change any functionality of the socket, except
+ * changing the setsockopt to enable the processing of ktls_start.
+ * Thus, it is not a problem to call it for non-TLS sockets.
+ */
+ ktls_enable(fd);
+ }
+# endif
return ret;
}
@@ -96,7 +106,12 @@ static int sock_read(BIO *b, char *out, int outl)
if (out != NULL) {
clear_socket_error();
- ret = readsocket(b->num, out, outl);
+# ifndef OPENSSL_NO_KTLS
+ if (BIO_get_ktls_recv(b))
+ ret = ktls_read_record(b->num, out, outl);
+ else
+# endif
+ ret = readsocket(b->num, out, outl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (BIO_sock_should_retry(ret))
@@ -110,10 +125,20 @@ static int sock_read(BIO *b, char *out, int outl)
static int sock_write(BIO *b, const char *in, int inl)
{
- int ret;
+ int ret = 0;
clear_socket_error();
- ret = writesocket(b->num, in, inl);
+# ifndef OPENSSL_NO_KTLS
+ if (BIO_should_ktls_ctrl_msg_flag(b)) {
+ unsigned char record_type = (intptr_t)b->ptr;
+ ret = ktls_send_ctrl_message(b->num, record_type, in, inl);
+ if (ret >= 0) {
+ ret = inl;
+ BIO_clear_ktls_ctrl_msg_flag(b);
+ }
+ } else
+# endif
+ ret = writesocket(b->num, in, inl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (BIO_sock_should_retry(ret))
@@ -126,6 +151,9 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr)
{
long ret = 1;
int *ip;
+# ifndef OPENSSL_NO_KTLS
+ ktls_crypto_info_t *crypto_info;
+# endif
switch (cmd) {
case BIO_C_SET_FD:
@@ -153,8 +181,29 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr)
case BIO_CTRL_FLUSH:
ret = 1;
break;
+# ifndef OPENSSL_NO_KTLS
+ case BIO_CTRL_SET_KTLS:
+ crypto_info = (ktls_crypto_info_t *)ptr;
+ ret = ktls_start(b->num, crypto_info, num);
+ if (ret)
+ BIO_set_ktls_flag(b, num);
+ break;
+ case BIO_CTRL_GET_KTLS_SEND:
+ return BIO_should_ktls_flag(b, 1) != 0;
+ case BIO_CTRL_GET_KTLS_RECV:
+ return BIO_should_ktls_flag(b, 0) != 0;
+ case BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG:
+ BIO_set_ktls_ctrl_msg_flag(b);
+ b->ptr = (void *)num;
+ ret = 0;
+ break;
+ case BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG:
+ BIO_clear_ktls_ctrl_msg_flag(b);
+ ret = 0;
+ break;
+# endif
case BIO_CTRL_EOF:
- ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0;
+ ret = (b->flags & BIO_FLAGS_IN_EOF) != 0;
break;
default:
ret = 0;
diff --git a/crypto/bio/build.info b/crypto/bio/build.info
index d1e7d73c5509..b203ed5e63fe 100644
--- a/crypto/bio/build.info
+++ b/crypto/bio/build.info
@@ -1,8 +1,18 @@
LIBS=../../libcrypto
+
+# Base library
SOURCE[../../libcrypto]=\
bio_lib.c bio_cb.c bio_err.c \
- bss_mem.c bss_null.c bss_fd.c \
- bss_file.c bss_sock.c bss_conn.c \
- bf_null.c bf_buff.c b_print.c b_dump.c b_addr.c \
- b_sock.c b_sock2.c bss_acpt.c bf_nbio.c bss_log.c bss_bio.c \
- bss_dgram.c bio_meth.c bf_lbuf.c
+ bio_print.c bio_dump.c bio_addr.c \
+ bio_sock.c bio_sock2.c \
+ bio_meth.c ossl_core_bio.c
+
+# Source / sink implementations
+SOURCE[../../libcrypto]=\
+ bss_null.c bss_mem.c bss_bio.c bss_fd.c bss_file.c \
+ bss_sock.c bss_conn.c bss_acpt.c bss_dgram.c \
+ bss_log.c bss_core.c
+
+# Filters
+SOURCE[../../libcrypto]=\
+ bf_null.c bf_buff.c bf_lbuf.c bf_nbio.c bf_prefix.c bf_readbuff.c
diff --git a/crypto/bio/ossl_core_bio.c b/crypto/bio/ossl_core_bio.c
new file mode 100644
index 000000000000..328302ea34e6
--- /dev/null
+++ b/crypto/bio/ossl_core_bio.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core.h>
+#include "bio_local.h"
+
+/*-
+ * Core BIO structure
+ * This is distinct from a BIO to prevent casting between the two which could
+ * lead to versioning problems.
+ */
+struct ossl_core_bio_st {
+ CRYPTO_REF_COUNT ref_cnt;
+ CRYPTO_RWLOCK *ref_lock;
+ BIO *bio;
+};
+
+static OSSL_CORE_BIO *core_bio_new(void)
+{
+ OSSL_CORE_BIO *cb = OPENSSL_malloc(sizeof(*cb));
+
+ if (cb == NULL || (cb->ref_lock = CRYPTO_THREAD_lock_new()) == NULL) {
+ OPENSSL_free(cb);
+ return NULL;
+ }
+ cb->ref_cnt = 1;
+ return cb;
+}
+
+int ossl_core_bio_up_ref(OSSL_CORE_BIO *cb)
+{
+ int ref = 0;
+
+ return CRYPTO_UP_REF(&cb->ref_cnt, &ref, cb->ref_lock);
+}
+
+int ossl_core_bio_free(OSSL_CORE_BIO *cb)
+{
+ int ref = 0, res = 1;
+
+ if (cb != NULL) {
+ CRYPTO_DOWN_REF(&cb->ref_cnt, &ref, cb->ref_lock);
+ if (ref <= 0) {
+ res = BIO_free(cb->bio);
+ CRYPTO_THREAD_lock_free(cb->ref_lock);
+ OPENSSL_free(cb);
+ }
+ }
+ return res;
+}
+
+OSSL_CORE_BIO *ossl_core_bio_new_from_bio(BIO *bio)
+{
+ OSSL_CORE_BIO *cb = core_bio_new();
+
+ if (cb == NULL || !BIO_up_ref(bio)) {
+ ossl_core_bio_free(cb);
+ return NULL;
+ }
+ cb->bio = bio;
+ return cb;
+}
+
+static OSSL_CORE_BIO *core_bio_new_from_new_bio(BIO *bio)
+{
+ OSSL_CORE_BIO *cb = NULL;
+
+ if (bio == NULL)
+ return NULL;
+ if ((cb = core_bio_new()) == NULL) {
+ BIO_free(bio);
+ return NULL;
+ }
+ cb->bio = bio;
+ return cb;
+}
+
+OSSL_CORE_BIO *ossl_core_bio_new_file(const char *filename, const char *mode)
+{
+ return core_bio_new_from_new_bio(BIO_new_file(filename, mode));
+}
+
+OSSL_CORE_BIO *ossl_core_bio_new_mem_buf(const void *buf, int len)
+{
+ return core_bio_new_from_new_bio(BIO_new_mem_buf(buf, len));
+}
+
+int ossl_core_bio_read_ex(OSSL_CORE_BIO *cb, void *data, size_t dlen,
+ size_t *readbytes)
+{
+ return BIO_read_ex(cb->bio, data, dlen, readbytes);
+}
+
+int ossl_core_bio_write_ex(OSSL_CORE_BIO *cb, const void *data, size_t dlen,
+ size_t *written)
+{
+ return BIO_write_ex(cb->bio, data, dlen, written);
+}
+
+int ossl_core_bio_gets(OSSL_CORE_BIO *cb, char *buf, int size)
+{
+ return BIO_gets(cb->bio, buf, size);
+}
+
+int ossl_core_bio_puts(OSSL_CORE_BIO *cb, const char *buf)
+{
+ return BIO_puts(cb->bio, buf);
+}
+
+long ossl_core_bio_ctrl(OSSL_CORE_BIO *cb, int cmd, long larg, void *parg)
+{
+ return BIO_ctrl(cb->bio, cmd, larg, parg);
+}
+
+int ossl_core_bio_vprintf(OSSL_CORE_BIO *cb, const char *format, va_list args)
+{
+ return BIO_vprintf(cb->bio, format, args);
+}
diff --git a/crypto/blake2/blake2_impl.h b/crypto/blake2/blake2_impl.h
deleted file mode 100644
index 80b717e79c08..000000000000
--- a/crypto/blake2/blake2_impl.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * Derived from the BLAKE2 reference implementation written by Samuel Neves.
- * Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
- * More information about the BLAKE2 hash function and its implementations
- * can be found at https://blake2.net.
- */
-
-#include <string.h>
-
-static ossl_inline uint32_t load32(const uint8_t *src)
-{
- const union {
- long one;
- char little;
- } is_endian = { 1 };
-
- if (is_endian.little) {
- uint32_t w;
- memcpy(&w, src, sizeof(w));
- return w;
- } else {
- uint32_t w = ((uint32_t)src[0])
- | ((uint32_t)src[1] << 8)
- | ((uint32_t)src[2] << 16)
- | ((uint32_t)src[3] << 24);
- return w;
- }
-}
-
-static ossl_inline uint64_t load64(const uint8_t *src)
-{
- const union {
- long one;
- char little;
- } is_endian = { 1 };
-
- if (is_endian.little) {
- uint64_t w;
- memcpy(&w, src, sizeof(w));
- return w;
- } else {
- uint64_t w = ((uint64_t)src[0])
- | ((uint64_t)src[1] << 8)
- | ((uint64_t)src[2] << 16)
- | ((uint64_t)src[3] << 24)
- | ((uint64_t)src[4] << 32)
- | ((uint64_t)src[5] << 40)
- | ((uint64_t)src[6] << 48)
- | ((uint64_t)src[7] << 56);
- return w;
- }
-}
-
-static ossl_inline void store32(uint8_t *dst, uint32_t w)
-{
- const union {
- long one;
- char little;
- } is_endian = { 1 };
-
- if (is_endian.little) {
- memcpy(dst, &w, sizeof(w));
- } else {
- uint8_t *p = (uint8_t *)dst;
- int i;
-
- for (i = 0; i < 4; i++)
- p[i] = (uint8_t)(w >> (8 * i));
- }
-}
-
-static ossl_inline void store64(uint8_t *dst, uint64_t w)
-{
- const union {
- long one;
- char little;
- } is_endian = { 1 };
-
- if (is_endian.little) {
- memcpy(dst, &w, sizeof(w));
- } else {
- uint8_t *p = (uint8_t *)dst;
- int i;
-
- for (i = 0; i < 8; i++)
- p[i] = (uint8_t)(w >> (8 * i));
- }
-}
-
-static ossl_inline uint64_t load48(const uint8_t *src)
-{
- uint64_t w = ((uint64_t)src[0])
- | ((uint64_t)src[1] << 8)
- | ((uint64_t)src[2] << 16)
- | ((uint64_t)src[3] << 24)
- | ((uint64_t)src[4] << 32)
- | ((uint64_t)src[5] << 40);
- return w;
-}
-
-static ossl_inline void store48(uint8_t *dst, uint64_t w)
-{
- uint8_t *p = (uint8_t *)dst;
- p[0] = (uint8_t)w;
- p[1] = (uint8_t)(w>>8);
- p[2] = (uint8_t)(w>>16);
- p[3] = (uint8_t)(w>>24);
- p[4] = (uint8_t)(w>>32);
- p[5] = (uint8_t)(w>>40);
-}
-
-static ossl_inline uint32_t rotr32(const uint32_t w, const unsigned int c)
-{
- return (w >> c) | (w << (32 - c));
-}
-
-static ossl_inline uint64_t rotr64(const uint64_t w, const unsigned int c)
-{
- return (w >> c) | (w << (64 - c));
-}
diff --git a/crypto/blake2/blake2_local.h b/crypto/blake2/blake2_local.h
deleted file mode 100644
index 926bae944c17..000000000000
--- a/crypto/blake2/blake2_local.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * Derived from the BLAKE2 reference implementation written by Samuel Neves.
- * Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
- * More information about the BLAKE2 hash function and its implementations
- * can be found at https://blake2.net.
- */
-
-#include <stddef.h>
-
-#define BLAKE2S_BLOCKBYTES 64
-#define BLAKE2S_OUTBYTES 32
-#define BLAKE2S_KEYBYTES 32
-#define BLAKE2S_SALTBYTES 8
-#define BLAKE2S_PERSONALBYTES 8
-
-#define BLAKE2B_BLOCKBYTES 128
-#define BLAKE2B_OUTBYTES 64
-#define BLAKE2B_KEYBYTES 64
-#define BLAKE2B_SALTBYTES 16
-#define BLAKE2B_PERSONALBYTES 16
-
-struct blake2s_param_st {
- uint8_t digest_length; /* 1 */
- uint8_t key_length; /* 2 */
- uint8_t fanout; /* 3 */
- uint8_t depth; /* 4 */
- uint8_t leaf_length[4];/* 8 */
- uint8_t node_offset[6];/* 14 */
- uint8_t node_depth; /* 15 */
- uint8_t inner_length; /* 16 */
- uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
- uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
-};
-
-typedef struct blake2s_param_st BLAKE2S_PARAM;
-
-struct blake2s_ctx_st {
- uint32_t h[8];
- uint32_t t[2];
- uint32_t f[2];
- uint8_t buf[BLAKE2S_BLOCKBYTES];
- size_t buflen;
-};
-
-struct blake2b_param_st {
- uint8_t digest_length; /* 1 */
- uint8_t key_length; /* 2 */
- uint8_t fanout; /* 3 */
- uint8_t depth; /* 4 */
- uint8_t leaf_length[4];/* 8 */
- uint8_t node_offset[8];/* 16 */
- uint8_t node_depth; /* 17 */
- uint8_t inner_length; /* 18 */
- uint8_t reserved[14]; /* 32 */
- uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
- uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
-};
-
-typedef struct blake2b_param_st BLAKE2B_PARAM;
-
-struct blake2b_ctx_st {
- uint64_t h[8];
- uint64_t t[2];
- uint64_t f[2];
- uint8_t buf[BLAKE2B_BLOCKBYTES];
- size_t buflen;
-};
-
-#define BLAKE2B_DIGEST_LENGTH 64
-#define BLAKE2S_DIGEST_LENGTH 32
-
-typedef struct blake2s_ctx_st BLAKE2S_CTX;
-typedef struct blake2b_ctx_st BLAKE2B_CTX;
-
-int BLAKE2b_Init(BLAKE2B_CTX *c);
-int BLAKE2b_Update(BLAKE2B_CTX *c, const void *data, size_t datalen);
-int BLAKE2b_Final(unsigned char *md, BLAKE2B_CTX *c);
-
-int BLAKE2s_Init(BLAKE2S_CTX *c);
-int BLAKE2s_Update(BLAKE2S_CTX *c, const void *data, size_t datalen);
-int BLAKE2s_Final(unsigned char *md, BLAKE2S_CTX *c);
diff --git a/crypto/blake2/blake2b.c b/crypto/blake2/blake2b.c
deleted file mode 100644
index fc6e5f1a3f3c..000000000000
--- a/crypto/blake2/blake2b.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * Derived from the BLAKE2 reference implementation written by Samuel Neves.
- * Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
- * More information about the BLAKE2 hash function and its implementations
- * can be found at https://blake2.net.
- */
-
-#include <assert.h>
-#include <string.h>
-#include <openssl/crypto.h>
-
-#include "blake2_local.h"
-#include "blake2_impl.h"
-
-static const uint64_t blake2b_IV[8] =
-{
- 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
- 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
- 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
- 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
-};
-
-static const uint8_t blake2b_sigma[12][16] =
-{
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
- { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
- { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
- { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
- { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
- { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
- { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
- { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
- { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
- { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
- { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
-};
-
-/* Set that it's the last block we'll compress */
-static ossl_inline void blake2b_set_lastblock(BLAKE2B_CTX *S)
-{
- S->f[0] = -1;
-}
-
-/* Initialize the hashing state. */
-static ossl_inline void blake2b_init0(BLAKE2B_CTX *S)
-{
- int i;
-
- memset(S, 0, sizeof(BLAKE2B_CTX));
- for (i = 0; i < 8; ++i) {
- S->h[i] = blake2b_IV[i];
- }
-}
-
-/* init xors IV with input parameter block */
-static void blake2b_init_param(BLAKE2B_CTX *S, const BLAKE2B_PARAM *P)
-{
- size_t i;
- const uint8_t *p = (const uint8_t *)(P);
- blake2b_init0(S);
-
- /* The param struct is carefully hand packed, and should be 64 bytes on
- * every platform. */
- assert(sizeof(BLAKE2B_PARAM) == 64);
- /* IV XOR ParamBlock */
- for (i = 0; i < 8; ++i) {
- S->h[i] ^= load64(p + sizeof(S->h[i]) * i);
- }
-}
-
-/* Initialize the hashing context. Always returns 1. */
-int BLAKE2b_Init(BLAKE2B_CTX *c)
-{
- BLAKE2B_PARAM P[1];
- P->digest_length = BLAKE2B_DIGEST_LENGTH;
- P->key_length = 0;
- P->fanout = 1;
- P->depth = 1;
- store32(P->leaf_length, 0);
- store64(P->node_offset, 0);
- P->node_depth = 0;
- P->inner_length = 0;
- memset(P->reserved, 0, sizeof(P->reserved));
- memset(P->salt, 0, sizeof(P->salt));
- memset(P->personal, 0, sizeof(P->personal));
- blake2b_init_param(c, P);
- return 1;
-}
-
-/* Permute the state while xoring in the block of data. */
-static void blake2b_compress(BLAKE2B_CTX *S,
- const uint8_t *blocks,
- size_t len)
-{
- uint64_t m[16];
- uint64_t v[16];
- int i;
- size_t increment;
-
- /*
- * There are two distinct usage vectors for this function:
- *
- * a) BLAKE2b_Update uses it to process complete blocks,
- * possibly more than one at a time;
- *
- * b) BLAK2b_Final uses it to process last block, always
- * single but possibly incomplete, in which case caller
- * pads input with zeros.
- */
- assert(len < BLAKE2B_BLOCKBYTES || len % BLAKE2B_BLOCKBYTES == 0);
-
- /*
- * Since last block is always processed with separate call,
- * |len| not being multiple of complete blocks can be observed
- * only with |len| being less than BLAKE2B_BLOCKBYTES ("less"
- * including even zero), which is why following assignment doesn't
- * have to reside inside the main loop below.
- */
- increment = len < BLAKE2B_BLOCKBYTES ? len : BLAKE2B_BLOCKBYTES;
-
- for (i = 0; i < 8; ++i) {
- v[i] = S->h[i];
- }
-
- do {
- for (i = 0; i < 16; ++i) {
- m[i] = load64(blocks + i * sizeof(m[i]));
- }
-
- /* blake2b_increment_counter */
- S->t[0] += increment;
- S->t[1] += (S->t[0] < increment);
-
- v[8] = blake2b_IV[0];
- v[9] = blake2b_IV[1];
- v[10] = blake2b_IV[2];
- v[11] = blake2b_IV[3];
- v[12] = S->t[0] ^ blake2b_IV[4];
- v[13] = S->t[1] ^ blake2b_IV[5];
- v[14] = S->f[0] ^ blake2b_IV[6];
- v[15] = S->f[1] ^ blake2b_IV[7];
-#define G(r,i,a,b,c,d) \
- do { \
- a = a + b + m[blake2b_sigma[r][2*i+0]]; \
- d = rotr64(d ^ a, 32); \
- c = c + d; \
- b = rotr64(b ^ c, 24); \
- a = a + b + m[blake2b_sigma[r][2*i+1]]; \
- d = rotr64(d ^ a, 16); \
- c = c + d; \
- b = rotr64(b ^ c, 63); \
- } while (0)
-#define ROUND(r) \
- do { \
- G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
- G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
- G(r,2,v[ 2],v[ 6],v[10],v[14]); \
- G(r,3,v[ 3],v[ 7],v[11],v[15]); \
- G(r,4,v[ 0],v[ 5],v[10],v[15]); \
- G(r,5,v[ 1],v[ 6],v[11],v[12]); \
- G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
- G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
- } while (0)
-#if defined(OPENSSL_SMALL_FOOTPRINT)
- /* 3x size reduction on x86_64, almost 7x on ARMv8, 9x on ARMv4 */
- for (i = 0; i < 12; i++) {
- ROUND(i);
- }
-#else
- ROUND(0);
- ROUND(1);
- ROUND(2);
- ROUND(3);
- ROUND(4);
- ROUND(5);
- ROUND(6);
- ROUND(7);
- ROUND(8);
- ROUND(9);
- ROUND(10);
- ROUND(11);
-#endif
-
- for (i = 0; i < 8; ++i) {
- S->h[i] = v[i] ^= v[i + 8] ^ S->h[i];
- }
-#undef G
-#undef ROUND
- blocks += increment;
- len -= increment;
- } while (len);
-}
-
-/* Absorb the input data into the hash state. Always returns 1. */
-int BLAKE2b_Update(BLAKE2B_CTX *c, const void *data, size_t datalen)
-{
- const uint8_t *in = data;
- size_t fill;
-
- /*
- * Intuitively one would expect intermediate buffer, c->buf, to
- * store incomplete blocks. But in this case we are interested to
- * temporarily stash even complete blocks, because last one in the
- * stream has to be treated in special way, and at this point we
- * don't know if last block in *this* call is last one "ever". This
- * is the reason for why |datalen| is compared as >, and not >=.
- */
- fill = sizeof(c->buf) - c->buflen;
- if (datalen > fill) {
- if (c->buflen) {
- memcpy(c->buf + c->buflen, in, fill); /* Fill buffer */
- blake2b_compress(c, c->buf, BLAKE2B_BLOCKBYTES);
- c->buflen = 0;
- in += fill;
- datalen -= fill;
- }
- if (datalen > BLAKE2B_BLOCKBYTES) {
- size_t stashlen = datalen % BLAKE2B_BLOCKBYTES;
- /*
- * If |datalen| is a multiple of the blocksize, stash
- * last complete block, it can be final one...
- */
- stashlen = stashlen ? stashlen : BLAKE2B_BLOCKBYTES;
- datalen -= stashlen;
- blake2b_compress(c, in, datalen);
- in += datalen;
- datalen = stashlen;
- }
- }
-
- assert(datalen <= BLAKE2B_BLOCKBYTES);
-
- memcpy(c->buf + c->buflen, in, datalen);
- c->buflen += datalen; /* Be lazy, do not compress */
-
- return 1;
-}
-
-/*
- * Calculate the final hash and save it in md.
- * Always returns 1.
- */
-int BLAKE2b_Final(unsigned char *md, BLAKE2B_CTX *c)
-{
- int i;
-
- blake2b_set_lastblock(c);
- /* Padding */
- memset(c->buf + c->buflen, 0, sizeof(c->buf) - c->buflen);
- blake2b_compress(c, c->buf, c->buflen);
-
- /* Output full hash to message digest */
- for (i = 0; i < 8; ++i) {
- store64(md + sizeof(c->h[i]) * i, c->h[i]);
- }
-
- OPENSSL_cleanse(c, sizeof(BLAKE2B_CTX));
- return 1;
-}
diff --git a/crypto/blake2/blake2s.c b/crypto/blake2/blake2s.c
deleted file mode 100644
index d072e05ca364..000000000000
--- a/crypto/blake2/blake2s.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * Derived from the BLAKE2 reference implementation written by Samuel Neves.
- * Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
- * More information about the BLAKE2 hash function and its implementations
- * can be found at https://blake2.net.
- */
-
-#include <assert.h>
-#include <string.h>
-#include <openssl/crypto.h>
-
-#include "blake2_local.h"
-#include "blake2_impl.h"
-
-static const uint32_t blake2s_IV[8] =
-{
- 0x6A09E667U, 0xBB67AE85U, 0x3C6EF372U, 0xA54FF53AU,
- 0x510E527FU, 0x9B05688CU, 0x1F83D9ABU, 0x5BE0CD19U
-};
-
-static const uint8_t blake2s_sigma[10][16] =
-{
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
- { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
- { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
- { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
- { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
- { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
- { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
- { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
- { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
- { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
-};
-
-/* Set that it's the last block we'll compress */
-static ossl_inline void blake2s_set_lastblock(BLAKE2S_CTX *S)
-{
- S->f[0] = -1;
-}
-
-/* Initialize the hashing state. */
-static ossl_inline void blake2s_init0(BLAKE2S_CTX *S)
-{
- int i;
-
- memset(S, 0, sizeof(BLAKE2S_CTX));
- for (i = 0; i < 8; ++i) {
- S->h[i] = blake2s_IV[i];
- }
-}
-
-/* init2 xors IV with input parameter block */
-static void blake2s_init_param(BLAKE2S_CTX *S, const BLAKE2S_PARAM *P)
-{
- const uint8_t *p = (const uint8_t *)(P);
- size_t i;
-
- /* The param struct is carefully hand packed, and should be 32 bytes on
- * every platform. */
- assert(sizeof(BLAKE2S_PARAM) == 32);
- blake2s_init0(S);
- /* IV XOR ParamBlock */
- for (i = 0; i < 8; ++i) {
- S->h[i] ^= load32(&p[i*4]);
- }
-}
-
-/* Initialize the hashing context. Always returns 1. */
-int BLAKE2s_Init(BLAKE2S_CTX *c)
-{
- BLAKE2S_PARAM P[1];
-
- P->digest_length = BLAKE2S_DIGEST_LENGTH;
- P->key_length = 0;
- P->fanout = 1;
- P->depth = 1;
- store32(P->leaf_length, 0);
- store48(P->node_offset, 0);
- P->node_depth = 0;
- P->inner_length = 0;
- memset(P->salt, 0, sizeof(P->salt));
- memset(P->personal, 0, sizeof(P->personal));
- blake2s_init_param(c, P);
- return 1;
-}
-
-/* Permute the state while xoring in the block of data. */
-static void blake2s_compress(BLAKE2S_CTX *S,
- const uint8_t *blocks,
- size_t len)
-{
- uint32_t m[16];
- uint32_t v[16];
- size_t i;
- size_t increment;
-
- /*
- * There are two distinct usage vectors for this function:
- *
- * a) BLAKE2s_Update uses it to process complete blocks,
- * possibly more than one at a time;
- *
- * b) BLAK2s_Final uses it to process last block, always
- * single but possibly incomplete, in which case caller
- * pads input with zeros.
- */
- assert(len < BLAKE2S_BLOCKBYTES || len % BLAKE2S_BLOCKBYTES == 0);
-
- /*
- * Since last block is always processed with separate call,
- * |len| not being multiple of complete blocks can be observed
- * only with |len| being less than BLAKE2S_BLOCKBYTES ("less"
- * including even zero), which is why following assignment doesn't
- * have to reside inside the main loop below.
- */
- increment = len < BLAKE2S_BLOCKBYTES ? len : BLAKE2S_BLOCKBYTES;
-
- for (i = 0; i < 8; ++i) {
- v[i] = S->h[i];
- }
-
- do {
- for (i = 0; i < 16; ++i) {
- m[i] = load32(blocks + i * sizeof(m[i]));
- }
-
- /* blake2s_increment_counter */
- S->t[0] += increment;
- S->t[1] += (S->t[0] < increment);
-
- v[ 8] = blake2s_IV[0];
- v[ 9] = blake2s_IV[1];
- v[10] = blake2s_IV[2];
- v[11] = blake2s_IV[3];
- v[12] = S->t[0] ^ blake2s_IV[4];
- v[13] = S->t[1] ^ blake2s_IV[5];
- v[14] = S->f[0] ^ blake2s_IV[6];
- v[15] = S->f[1] ^ blake2s_IV[7];
-#define G(r,i,a,b,c,d) \
- do { \
- a = a + b + m[blake2s_sigma[r][2*i+0]]; \
- d = rotr32(d ^ a, 16); \
- c = c + d; \
- b = rotr32(b ^ c, 12); \
- a = a + b + m[blake2s_sigma[r][2*i+1]]; \
- d = rotr32(d ^ a, 8); \
- c = c + d; \
- b = rotr32(b ^ c, 7); \
- } while (0)
-#define ROUND(r) \
- do { \
- G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
- G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
- G(r,2,v[ 2],v[ 6],v[10],v[14]); \
- G(r,3,v[ 3],v[ 7],v[11],v[15]); \
- G(r,4,v[ 0],v[ 5],v[10],v[15]); \
- G(r,5,v[ 1],v[ 6],v[11],v[12]); \
- G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
- G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
- } while (0)
-#if defined(OPENSSL_SMALL_FOOTPRINT)
- /* almost 3x reduction on x86_64, 4.5x on ARMv8, 4x on ARMv4 */
- for (i = 0; i < 10; i++) {
- ROUND(i);
- }
-#else
- ROUND(0);
- ROUND(1);
- ROUND(2);
- ROUND(3);
- ROUND(4);
- ROUND(5);
- ROUND(6);
- ROUND(7);
- ROUND(8);
- ROUND(9);
-#endif
-
- for (i = 0; i < 8; ++i) {
- S->h[i] = v[i] ^= v[i + 8] ^ S->h[i];
- }
-#undef G
-#undef ROUND
- blocks += increment;
- len -= increment;
- } while (len);
-}
-
-/* Absorb the input data into the hash state. Always returns 1. */
-int BLAKE2s_Update(BLAKE2S_CTX *c, const void *data, size_t datalen)
-{
- const uint8_t *in = data;
- size_t fill;
-
- /*
- * Intuitively one would expect intermediate buffer, c->buf, to
- * store incomplete blocks. But in this case we are interested to
- * temporarily stash even complete blocks, because last one in the
- * stream has to be treated in special way, and at this point we
- * don't know if last block in *this* call is last one "ever". This
- * is the reason for why |datalen| is compared as >, and not >=.
- */
- fill = sizeof(c->buf) - c->buflen;
- if (datalen > fill) {
- if (c->buflen) {
- memcpy(c->buf + c->buflen, in, fill); /* Fill buffer */
- blake2s_compress(c, c->buf, BLAKE2S_BLOCKBYTES);
- c->buflen = 0;
- in += fill;
- datalen -= fill;
- }
- if (datalen > BLAKE2S_BLOCKBYTES) {
- size_t stashlen = datalen % BLAKE2S_BLOCKBYTES;
- /*
- * If |datalen| is a multiple of the blocksize, stash
- * last complete block, it can be final one...
- */
- stashlen = stashlen ? stashlen : BLAKE2S_BLOCKBYTES;
- datalen -= stashlen;
- blake2s_compress(c, in, datalen);
- in += datalen;
- datalen = stashlen;
- }
- }
-
- assert(datalen <= BLAKE2S_BLOCKBYTES);
-
- memcpy(c->buf + c->buflen, in, datalen);
- c->buflen += datalen; /* Be lazy, do not compress */
-
- return 1;
-}
-
-/*
- * Calculate the final hash and save it in md.
- * Always returns 1.
- */
-int BLAKE2s_Final(unsigned char *md, BLAKE2S_CTX *c)
-{
- int i;
-
- blake2s_set_lastblock(c);
- /* Padding */
- memset(c->buf + c->buflen, 0, sizeof(c->buf) - c->buflen);
- blake2s_compress(c, c->buf, c->buflen);
-
- /* Output full hash to temp buffer */
- for (i = 0; i < 8; ++i) {
- store32(md + sizeof(c->h[i]) * i, c->h[i]);
- }
-
- OPENSSL_cleanse(c, sizeof(BLAKE2S_CTX));
- return 1;
-}
diff --git a/crypto/blake2/build.info b/crypto/blake2/build.info
deleted file mode 100644
index 0036f084826e..000000000000
--- a/crypto/blake2/build.info
+++ /dev/null
@@ -1,3 +0,0 @@
-LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- blake2b.c blake2s.c m_blake2b.c m_blake2s.c
diff --git a/crypto/blake2/m_blake2b.c b/crypto/blake2/m_blake2b.c
deleted file mode 100644
index ce4d8f95652f..000000000000
--- a/crypto/blake2/m_blake2b.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * Derived from the BLAKE2 reference implementation written by Samuel Neves.
- * Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
- * More information about the BLAKE2 hash function and its implementations
- * can be found at https://blake2.net.
- */
-
-#include "internal/cryptlib.h"
-
-#ifndef OPENSSL_NO_BLAKE2
-
-# include <openssl/evp.h>
-# include <openssl/objects.h>
-# include "blake2_local.h"
-# include "crypto/evp.h"
-
-static int init(EVP_MD_CTX *ctx)
-{
- return BLAKE2b_Init(EVP_MD_CTX_md_data(ctx));
-}
-
-static int update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- return BLAKE2b_Update(EVP_MD_CTX_md_data(ctx), data, count);
-}
-
-static int final(EVP_MD_CTX *ctx, unsigned char *md)
-{
- return BLAKE2b_Final(md, EVP_MD_CTX_md_data(ctx));
-}
-
-static const EVP_MD blake2b_md = {
- NID_blake2b512,
- 0,
- BLAKE2B_DIGEST_LENGTH,
- 0,
- init,
- update,
- final,
- NULL,
- NULL,
- BLAKE2B_BLOCKBYTES,
- sizeof(EVP_MD *) + sizeof(BLAKE2B_CTX),
-};
-
-const EVP_MD *EVP_blake2b512(void)
-{
- return &blake2b_md;
-}
-#endif
diff --git a/crypto/blake2/m_blake2s.c b/crypto/blake2/m_blake2s.c
deleted file mode 100644
index b8fb048b30bf..000000000000
--- a/crypto/blake2/m_blake2s.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * Derived from the BLAKE2 reference implementation written by Samuel Neves.
- * Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
- * More information about the BLAKE2 hash function and its implementations
- * can be found at https://blake2.net.
- */
-
-#include "internal/cryptlib.h"
-
-#ifndef OPENSSL_NO_BLAKE2
-
-# include <openssl/evp.h>
-# include <openssl/objects.h>
-# include "blake2_local.h"
-# include "crypto/evp.h"
-
-static int init(EVP_MD_CTX *ctx)
-{
- return BLAKE2s_Init(EVP_MD_CTX_md_data(ctx));
-}
-
-static int update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- return BLAKE2s_Update(EVP_MD_CTX_md_data(ctx), data, count);
-}
-
-static int final(EVP_MD_CTX *ctx, unsigned char *md)
-{
- return BLAKE2s_Final(md, EVP_MD_CTX_md_data(ctx));
-}
-
-static const EVP_MD blake2s_md = {
- NID_blake2s256,
- 0,
- BLAKE2S_DIGEST_LENGTH,
- 0,
- init,
- update,
- final,
- NULL,
- NULL,
- BLAKE2S_BLOCKBYTES,
- sizeof(EVP_MD *) + sizeof(BLAKE2S_CTX),
-};
-
-const EVP_MD *EVP_blake2s256(void)
-{
- return &blake2s_md;
-}
-#endif
diff --git a/crypto/bn/README.pod b/crypto/bn/README.pod
index 5d5c4fa99fa1..1286fc0d4132 100644
--- a/crypto/bn/README.pod
+++ b/crypto/bn/README.pod
@@ -233,7 +233,7 @@ L<bn(3)>
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/crypto/bn/asm/armv4-gf2m.pl b/crypto/bn/asm/armv4-gf2m.pl
index 3a83cb855007..d380c89f1f2b 100644
--- a/crypto/bn/asm/armv4-gf2m.pl
+++ b/crypto/bn/asm/armv4-gf2m.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -39,9 +39,10 @@
#
# http://conradoplg.cryptoland.net/files/2010/12/mocrysen13.pdf
-$flavour = shift;
-if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour && $flavour ne "void") {
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -49,21 +50,23 @@ if ($flavour && $flavour ne "void") {
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
- open STDOUT,"| \"$^X\" $xlate $flavour $output";
+ open STDOUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $1";
} else {
- open STDOUT,">$output";
+ $output and open STDOUT,">$output";
}
$code=<<___;
#include "arm_arch.h"
-.text
#if defined(__thumb2__)
.syntax unified
.thumb
#else
.code 32
#endif
+
+.text
___
################
# private interface to mul_1x1_ialu
@@ -176,11 +179,13 @@ bn_GF2m_mul_2x2:
#if __ARM_MAX_ARCH__>=7
stmdb sp!,{r10,lr}
ldr r12,.LOPENSSL_armcap
+# if !defined(_WIN32)
adr r10,.LOPENSSL_armcap
ldr r12,[r12,r10]
-#ifdef __APPLE__
+# endif
+# if defined(__APPLE__) || defined(_WIN32)
ldr r12,[r12]
-#endif
+# endif
tst r12,#ARMV7_NEON
itt ne
ldrne r10,[sp],#8
@@ -310,7 +315,11 @@ $code.=<<___;
#if __ARM_MAX_ARCH__>=7
.align 5
.LOPENSSL_armcap:
+# ifdef _WIN32
+.word OPENSSL_armcap_P
+# else
.word OPENSSL_armcap_P-.
+# endif
#endif
.asciz "GF(2^m) Multiplication for ARMv4/NEON, CRYPTOGAMS by <appro\@openssl.org>"
.align 5
diff --git a/crypto/bn/asm/armv4-mont.pl b/crypto/bn/asm/armv4-mont.pl
index eadc8bbf6322..c26df751a5eb 100644
--- a/crypto/bn/asm/armv4-mont.pl
+++ b/crypto/bn/asm/armv4-mont.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -54,9 +54,10 @@
# integer-only on Cortex-A8, ~10-210% on Cortex-A15, ~70-450% on
# Snapdragon S4.
-$flavour = shift;
-if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour && $flavour ne "void") {
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -64,9 +65,10 @@ if ($flavour && $flavour ne "void") {
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
- open STDOUT,"| \"$^X\" $xlate $flavour $output";
+ open STDOUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $1";
} else {
- open STDOUT,">$output";
+ $output and open STDOUT,">$output";
}
$num="r0"; # starts as num argument, but holds &tp[num-1]
@@ -97,7 +99,6 @@ $_num="$num,#15*4"; $_bpend=$_num;
$code=<<___;
#include "arm_arch.h"
-.text
#if defined(__thumb2__)
.syntax unified
.thumb
@@ -105,10 +106,16 @@ $code=<<___;
.code 32
#endif
+.text
+
#if __ARM_MAX_ARCH__>=7
.align 5
.LOPENSSL_armcap:
+# ifdef _WIN32
+.word OPENSSL_armcap_P
+# else
.word OPENSSL_armcap_P-.Lbn_mul_mont
+# endif
#endif
.global bn_mul_mont
@@ -122,12 +129,14 @@ bn_mul_mont:
#if __ARM_MAX_ARCH__>=7
tst ip,#7
bne .Lialu
- adr r0,.Lbn_mul_mont
- ldr r2,.LOPENSSL_armcap
+ ldr r0,.LOPENSSL_armcap
+#if !defined(_WIN32)
+ adr r2,.Lbn_mul_mont
ldr r0,[r0,r2]
-#ifdef __APPLE__
+# endif
+# if defined(__APPLE__) || defined(_WIN32)
ldr r0,[r0]
-#endif
+# endif
tst r0,#ARMV7_NEON @ NEON available?
ldmia sp, {r0,r2}
beq .Lialu
diff --git a/crypto/bn/asm/armv8-mont.pl b/crypto/bn/asm/armv8-mont.pl
index bc9a18dc4ce6..54d2e8245f15 100755
--- a/crypto/bn/asm/armv8-mont.pl
+++ b/crypto/bn/asm/armv8-mont.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -40,15 +40,18 @@
# 50-70% improvement for RSA4096 sign. RSA2048 sign is ~25% faster
# on Cortex-A57 and ~60-100% faster on others.
-$flavour = shift;
-$output = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $1";
*STDOUT=*OUT;
($lo0,$hi0,$aj,$m0,$alo,$ahi,
@@ -64,16 +67,34 @@ $n0="x4"; # const BN_ULONG *n0,
$num="x5"; # int num);
$code.=<<___;
+#ifndef __KERNEL__
+# include "arm_arch.h"
+.extern OPENSSL_armv8_rsa_neonized
+.hidden OPENSSL_armv8_rsa_neonized
+#endif
.text
.globl bn_mul_mont
.type bn_mul_mont,%function
.align 5
bn_mul_mont:
+.Lbn_mul_mont:
+ tst $num,#3
+ b.ne .Lmul_mont
+ cmp $num,#32
+ b.le .Lscalar_impl
+#ifndef __KERNEL__
+ adrp x17,OPENSSL_armv8_rsa_neonized
+ ldr w17,[x17,#:lo12:OPENSSL_armv8_rsa_neonized]
+ cbnz w17, bn_mul8x_mont_neon
+#endif
+
+.Lscalar_impl:
tst $num,#7
b.eq __bn_sqr8x_mont
tst $num,#3
b.eq __bn_mul4x_mont
+
.Lmul_mont:
stp x29,x30,[sp,#-64]!
add x29,sp,#0
@@ -197,7 +218,7 @@ bn_mul_mont:
mul $nlo,$nj,$m1 // np[j]*m1
adds $lo1,$lo1,$lo0
umulh $nhi,$nj,$m1
- str $lo1,[$tp,#-16] // tp[j-1]
+ stur $lo1,[$tp,#-16] // tp[j-1]
cbnz $j,.Linner
.Linner_skip:
@@ -253,13 +274,13 @@ bn_mul_mont:
csel $nj,$tj,$aj,lo // did it borrow?
ldr $tj,[$tp],#8
ldr $aj,[$rp],#8
- str xzr,[$tp,#-16] // wipe tp
- str $nj,[$rp,#-16]
+ stur xzr,[$tp,#-16] // wipe tp
+ stur $nj,[$rp,#-16]
cbnz $num,.Lcond_copy
csel $nj,$tj,$aj,lo
- str xzr,[$tp,#-8] // wipe tp
- str $nj,[$rp,#-8]
+ stur xzr,[$tp,#-8] // wipe tp
+ stur $nj,[$rp,#-8]
ldp x19,x20,[x29,#16]
mov sp,x29
@@ -271,6 +292,369 @@ bn_mul_mont:
.size bn_mul_mont,.-bn_mul_mont
___
{
+my ($A0,$A1,$N0,$N1)=map("v$_",(0..3));
+my ($Z,$Temp)=("v4.16b","v5");
+my @ACC=map("v$_",(6..13));
+my ($Bi,$Ni,$M0)=map("v$_",(28..30));
+my $sBi="s28";
+my $sM0="s30";
+my $zero="v14";
+my $temp="v15";
+my $ACCTemp="v16";
+
+my ($rptr,$aptr,$bptr,$nptr,$n0,$num)=map("x$_",(0..5));
+my ($tinptr,$toutptr,$inner,$outer,$bnptr)=map("x$_",(6..11));
+
+$code.=<<___;
+.type bn_mul8x_mont_neon,%function
+.align 5
+bn_mul8x_mont_neon:
+ stp x29,x30,[sp,#-80]!
+ mov x16,sp
+ stp d8,d9,[sp,#16]
+ stp d10,d11,[sp,#32]
+ stp d12,d13,[sp,#48]
+ stp d14,d15,[sp,#64]
+ lsl $num,$num,#1
+ eor $zero.16b,$zero.16b,$zero.16b
+
+.align 4
+.LNEON_8n:
+ eor @ACC[0].16b,@ACC[0].16b,@ACC[0].16b
+ sub $toutptr,sp,#128
+ eor @ACC[1].16b,@ACC[1].16b,@ACC[1].16b
+ sub $toutptr,$toutptr,$num,lsl#4
+ eor @ACC[2].16b,@ACC[2].16b,@ACC[2].16b
+ and $toutptr,$toutptr,#-64
+ eor @ACC[3].16b,@ACC[3].16b,@ACC[3].16b
+ mov sp,$toutptr // alloca
+ eor @ACC[4].16b,@ACC[4].16b,@ACC[4].16b
+ add $toutptr,$toutptr,#256
+ eor @ACC[5].16b,@ACC[5].16b,@ACC[5].16b
+ sub $inner,$num,#8
+ eor @ACC[6].16b,@ACC[6].16b,@ACC[6].16b
+ eor @ACC[7].16b,@ACC[7].16b,@ACC[7].16b
+
+.LNEON_8n_init:
+ st1 {@ACC[0].2d,@ACC[1].2d},[$toutptr],#32
+ subs $inner,$inner,#8
+ st1 {@ACC[2].2d,@ACC[3].2d},[$toutptr],#32
+ st1 {@ACC[4].2d,@ACC[5].2d},[$toutptr],#32
+ st1 {@ACC[6].2d,@ACC[7].2d},[$toutptr],#32
+ bne .LNEON_8n_init
+
+ add $tinptr,sp,#256
+ ld1 {$A0.4s,$A1.4s},[$aptr],#32
+ add $bnptr,sp,#8
+ ldr $sM0,[$n0],#4
+ mov $outer,$num
+ b .LNEON_8n_outer
+
+.align 4
+.LNEON_8n_outer:
+ ldr $sBi,[$bptr],#4 // *b++
+ uxtl $Bi.4s,$Bi.4h
+ add $toutptr,sp,#128
+ ld1 {$N0.4s,$N1.4s},[$nptr],#32
+
+ umlal @ACC[0].2d,$Bi.2s,$A0.s[0]
+ umlal @ACC[1].2d,$Bi.2s,$A0.s[1]
+ umlal @ACC[2].2d,$Bi.2s,$A0.s[2]
+ shl $Ni.2d,@ACC[0].2d,#16
+ ext $Ni.16b,$Ni.16b,$Ni.16b,#8
+ umlal @ACC[3].2d,$Bi.2s,$A0.s[3]
+ add $Ni.2d,$Ni.2d,@ACC[0].2d
+ umlal @ACC[4].2d,$Bi.2s,$A1.s[0]
+ mul $Ni.2s,$Ni.2s,$M0.2s
+ umlal @ACC[5].2d,$Bi.2s,$A1.s[1]
+ st1 {$Bi.2s},[sp] // put aside smashed b[8*i+0]
+ umlal @ACC[6].2d,$Bi.2s,$A1.s[2]
+ uxtl $Ni.4s,$Ni.4h
+ umlal @ACC[7].2d,$Bi.2s,$A1.s[3]
+___
+for ($i=0; $i<7;) {
+$code.=<<___;
+ ldr $sBi,[$bptr],#4 // *b++
+ umlal @ACC[0].2d,$Ni.2s,$N0.s[0]
+ umlal @ACC[1].2d,$Ni.2s,$N0.s[1]
+ uxtl $Bi.4s,$Bi.4h
+ umlal @ACC[2].2d,$Ni.2s,$N0.s[2]
+ ushr $temp.2d,@ACC[0].2d,#16
+ umlal @ACC[3].2d,$Ni.2s,$N0.s[3]
+ umlal @ACC[4].2d,$Ni.2s,$N1.s[0]
+ ext @ACC[0].16b,@ACC[0].16b,@ACC[0].16b,#8
+ add @ACC[0].2d,@ACC[0].2d,$temp.2d
+ umlal @ACC[5].2d,$Ni.2s,$N1.s[1]
+ ushr @ACC[0].2d,@ACC[0].2d,#16
+ umlal @ACC[6].2d,$Ni.2s,$N1.s[2]
+ umlal @ACC[7].2d,$Ni.2s,$N1.s[3]
+ add $ACCTemp.2d,@ACC[1].2d,@ACC[0].2d
+ ins @ACC[1].d[0],$ACCTemp.d[0]
+ st1 {$Ni.2s},[$bnptr],#8 // put aside smashed m[8*i+$i]
+___
+ push(@ACC,shift(@ACC)); $i++;
+$code.=<<___;
+ umlal @ACC[0].2d,$Bi.2s,$A0.s[0]
+ ld1 {@ACC[7].2d},[$tinptr],#16
+ umlal @ACC[1].2d,$Bi.2s,$A0.s[1]
+ umlal @ACC[2].2d,$Bi.2s,$A0.s[2]
+ shl $Ni.2d,@ACC[0].2d,#16
+ ext $Ni.16b,$Ni.16b,$Ni.16b,#8
+ umlal @ACC[3].2d,$Bi.2s,$A0.s[3]
+ add $Ni.2d,$Ni.2d,@ACC[0].2d
+ umlal @ACC[4].2d,$Bi.2s,$A1.s[0]
+ mul $Ni.2s,$Ni.2s,$M0.2s
+ umlal @ACC[5].2d,$Bi.2s,$A1.s[1]
+ st1 {$Bi.2s},[$bnptr],#8 // put aside smashed b[8*i+$i]
+ umlal @ACC[6].2d,$Bi.2s,$A1.s[2]
+ uxtl $Ni.4s,$Ni.4h
+ umlal @ACC[7].2d,$Bi.2s,$A1.s[3]
+___
+}
+$code.=<<___;
+ ld1 {$Bi.2s},[sp] // pull smashed b[8*i+0]
+ umlal @ACC[0].2d,$Ni.2s,$N0.s[0]
+ ld1 {$A0.4s,$A1.4s},[$aptr],#32
+ umlal @ACC[1].2d,$Ni.2s,$N0.s[1]
+ umlal @ACC[2].2d,$Ni.2s,$N0.s[2]
+ mov $Temp.16b,@ACC[0].16b
+ ushr $Temp.2d,$Temp.2d,#16
+ ext @ACC[0].16b,@ACC[0].16b,@ACC[0].16b,#8
+ umlal @ACC[3].2d,$Ni.2s,$N0.s[3]
+ umlal @ACC[4].2d,$Ni.2s,$N1.s[0]
+ add @ACC[0].2d,@ACC[0].2d,$Temp.2d
+ umlal @ACC[5].2d,$Ni.2s,$N1.s[1]
+ ushr @ACC[0].2d,@ACC[0].2d,#16
+ eor $temp.16b,$temp.16b,$temp.16b
+ ins @ACC[0].d[1],$temp.d[0]
+ umlal @ACC[6].2d,$Ni.2s,$N1.s[2]
+ umlal @ACC[7].2d,$Ni.2s,$N1.s[3]
+ add @ACC[1].2d,@ACC[1].2d,@ACC[0].2d
+ st1 {$Ni.2s},[$bnptr],#8 // put aside smashed m[8*i+$i]
+ add $bnptr,sp,#8 // rewind
+___
+ push(@ACC,shift(@ACC));
+$code.=<<___;
+ sub $inner,$num,#8
+ b .LNEON_8n_inner
+
+.align 4
+.LNEON_8n_inner:
+ subs $inner,$inner,#8
+ umlal @ACC[0].2d,$Bi.2s,$A0.s[0]
+ ld1 {@ACC[7].2d},[$tinptr]
+ umlal @ACC[1].2d,$Bi.2s,$A0.s[1]
+ ld1 {$Ni.2s},[$bnptr],#8 // pull smashed m[8*i+0]
+ umlal @ACC[2].2d,$Bi.2s,$A0.s[2]
+ ld1 {$N0.4s,$N1.4s},[$nptr],#32
+ umlal @ACC[3].2d,$Bi.2s,$A0.s[3]
+ b.eq .LInner_jump
+ add $tinptr,$tinptr,#16 // don't advance in last iteration
+.LInner_jump:
+ umlal @ACC[4].2d,$Bi.2s,$A1.s[0]
+ umlal @ACC[5].2d,$Bi.2s,$A1.s[1]
+ umlal @ACC[6].2d,$Bi.2s,$A1.s[2]
+ umlal @ACC[7].2d,$Bi.2s,$A1.s[3]
+___
+for ($i=1; $i<8; $i++) {
+$code.=<<___;
+ ld1 {$Bi.2s},[$bnptr],#8 // pull smashed b[8*i+$i]
+ umlal @ACC[0].2d,$Ni.2s,$N0.s[0]
+ umlal @ACC[1].2d,$Ni.2s,$N0.s[1]
+ umlal @ACC[2].2d,$Ni.2s,$N0.s[2]
+ umlal @ACC[3].2d,$Ni.2s,$N0.s[3]
+ umlal @ACC[4].2d,$Ni.2s,$N1.s[0]
+ umlal @ACC[5].2d,$Ni.2s,$N1.s[1]
+ umlal @ACC[6].2d,$Ni.2s,$N1.s[2]
+ umlal @ACC[7].2d,$Ni.2s,$N1.s[3]
+ st1 {@ACC[0].2d},[$toutptr],#16
+___
+ push(@ACC,shift(@ACC));
+$code.=<<___;
+ umlal @ACC[0].2d,$Bi.2s,$A0.s[0]
+ ld1 {@ACC[7].2d},[$tinptr]
+ umlal @ACC[1].2d,$Bi.2s,$A0.s[1]
+ ld1 {$Ni.2s},[$bnptr],#8 // pull smashed m[8*i+$i]
+ umlal @ACC[2].2d,$Bi.2s,$A0.s[2]
+ b.eq .LInner_jump$i
+ add $tinptr,$tinptr,#16 // don't advance in last iteration
+.LInner_jump$i:
+ umlal @ACC[3].2d,$Bi.2s,$A0.s[3]
+ umlal @ACC[4].2d,$Bi.2s,$A1.s[0]
+ umlal @ACC[5].2d,$Bi.2s,$A1.s[1]
+ umlal @ACC[6].2d,$Bi.2s,$A1.s[2]
+ umlal @ACC[7].2d,$Bi.2s,$A1.s[3]
+___
+}
+$code.=<<___;
+ b.ne .LInner_after_rewind$i
+ sub $aptr,$aptr,$num,lsl#2 // rewind
+.LInner_after_rewind$i:
+ umlal @ACC[0].2d,$Ni.2s,$N0.s[0]
+ ld1 {$Bi.2s},[sp] // pull smashed b[8*i+0]
+ umlal @ACC[1].2d,$Ni.2s,$N0.s[1]
+ ld1 {$A0.4s,$A1.4s},[$aptr],#32
+ umlal @ACC[2].2d,$Ni.2s,$N0.s[2]
+ add $bnptr,sp,#8 // rewind
+ umlal @ACC[3].2d,$Ni.2s,$N0.s[3]
+ umlal @ACC[4].2d,$Ni.2s,$N1.s[0]
+ umlal @ACC[5].2d,$Ni.2s,$N1.s[1]
+ umlal @ACC[6].2d,$Ni.2s,$N1.s[2]
+ st1 {@ACC[0].2d},[$toutptr],#16
+ umlal @ACC[7].2d,$Ni.2s,$N1.s[3]
+
+ bne .LNEON_8n_inner
+___
+ push(@ACC,shift(@ACC));
+$code.=<<___;
+ add $tinptr,sp,#128
+ st1 {@ACC[0].2d,@ACC[1].2d},[$toutptr],#32
+ eor $N0.16b,$N0.16b,$N0.16b // $N0
+ st1 {@ACC[2].2d,@ACC[3].2d},[$toutptr],#32
+ eor $N1.16b,$N1.16b,$N1.16b // $N1
+ st1 {@ACC[4].2d,@ACC[5].2d},[$toutptr],#32
+ st1 {@ACC[6].2d},[$toutptr]
+
+ subs $outer,$outer,#8
+ ld1 {@ACC[0].2d,@ACC[1].2d},[$tinptr],#32
+ ld1 {@ACC[2].2d,@ACC[3].2d},[$tinptr],#32
+ ld1 {@ACC[4].2d,@ACC[5].2d},[$tinptr],#32
+ ld1 {@ACC[6].2d,@ACC[7].2d},[$tinptr],#32
+
+ b.eq .LInner_8n_jump_2steps
+ sub $nptr,$nptr,$num,lsl#2 // rewind
+ b .LNEON_8n_outer
+
+.LInner_8n_jump_2steps:
+ add $toutptr,sp,#128
+ st1 {$N0.2d,$N1.2d}, [sp],#32 // start wiping stack frame
+ mov $Temp.16b,@ACC[0].16b
+ ushr $temp.2d,@ACC[0].2d,#16
+ ext @ACC[0].16b,@ACC[0].16b,@ACC[0].16b,#8
+ st1 {$N0.2d,$N1.2d}, [sp],#32
+ add @ACC[0].2d,@ACC[0].2d,$temp.2d
+ st1 {$N0.2d,$N1.2d}, [sp],#32
+ ushr $temp.2d,@ACC[0].2d,#16
+ st1 {$N0.2d,$N1.2d}, [sp],#32
+ zip1 @ACC[0].4h,$Temp.4h,@ACC[0].4h
+ ins $temp.d[1],$zero.d[0]
+
+ mov $inner,$num
+ b .LNEON_tail_entry
+
+.align 4
+.LNEON_tail:
+ add @ACC[0].2d,@ACC[0].2d,$temp.2d
+ mov $Temp.16b,@ACC[0].16b
+ ushr $temp.2d,@ACC[0].2d,#16
+ ext @ACC[0].16b,@ACC[0].16b,@ACC[0].16b,#8
+ ld1 {@ACC[2].2d,@ACC[3].2d}, [$tinptr],#32
+ add @ACC[0].2d,@ACC[0].2d,$temp.2d
+ ld1 {@ACC[4].2d,@ACC[5].2d}, [$tinptr],#32
+ ushr $temp.2d,@ACC[0].2d,#16
+ ld1 {@ACC[6].2d,@ACC[7].2d}, [$tinptr],#32
+ zip1 @ACC[0].4h,$Temp.4h,@ACC[0].4h
+ ins $temp.d[1],$zero.d[0]
+
+.LNEON_tail_entry:
+___
+for ($i=1; $i<8; $i++) {
+$code.=<<___;
+ add @ACC[1].2d,@ACC[1].2d,$temp.2d
+ st1 {@ACC[0].s}[0], [$toutptr],#4
+ ushr $temp.2d,@ACC[1].2d,#16
+ mov $Temp.16b,@ACC[1].16b
+ ext @ACC[1].16b,@ACC[1].16b,@ACC[1].16b,#8
+ add @ACC[1].2d,@ACC[1].2d,$temp.2d
+ ushr $temp.2d,@ACC[1].2d,#16
+ zip1 @ACC[1].4h,$Temp.4h,@ACC[1].4h
+ ins $temp.d[1],$zero.d[0]
+___
+ push(@ACC,shift(@ACC));
+}
+ push(@ACC,shift(@ACC));
+$code.=<<___;
+ ld1 {@ACC[0].2d,@ACC[1].2d}, [$tinptr],#32
+ subs $inner,$inner,#8
+ st1 {@ACC[7].s}[0], [$toutptr],#4
+ bne .LNEON_tail
+
+ st1 {$temp.s}[0], [$toutptr],#4 // top-most bit
+ sub $nptr,$nptr,$num,lsl#2 // rewind $nptr
+ subs $aptr,sp,#0 // clear carry flag
+ add $bptr,sp,$num,lsl#2
+
+.LNEON_sub:
+ ldp w4,w5,[$aptr],#8
+ ldp w6,w7,[$aptr],#8
+ ldp w8,w9,[$nptr],#8
+ ldp w10,w11,[$nptr],#8
+ sbcs w8,w4,w8
+ sbcs w9,w5,w9
+ sbcs w10,w6,w10
+ sbcs w11,w7,w11
+ sub x17,$bptr,$aptr
+ stp w8,w9,[$rptr],#8
+ stp w10,w11,[$rptr],#8
+ cbnz x17,.LNEON_sub
+
+ ldr w10, [$aptr] // load top-most bit
+ mov x11,sp
+ eor v0.16b,v0.16b,v0.16b
+ sub x11,$bptr,x11 // this is num*4
+ eor v1.16b,v1.16b,v1.16b
+ mov $aptr,sp
+ sub $rptr,$rptr,x11 // rewind $rptr
+ mov $nptr,$bptr // second 3/4th of frame
+ sbcs w10,w10,wzr // result is carry flag
+
+.LNEON_copy_n_zap:
+ ldp w4,w5,[$aptr],#8
+ ldp w6,w7,[$aptr],#8
+ ldp w8,w9,[$rptr],#8
+ ldp w10,w11,[$rptr]
+ sub $rptr,$rptr,#8
+ b.cs .LCopy_1
+ mov w8,w4
+ mov w9,w5
+ mov w10,w6
+ mov w11,w7
+.LCopy_1:
+ st1 {v0.2d,v1.2d}, [$nptr],#32 // wipe
+ st1 {v0.2d,v1.2d}, [$nptr],#32 // wipe
+ ldp w4,w5,[$aptr],#8
+ ldp w6,w7,[$aptr],#8
+ stp w8,w9,[$rptr],#8
+ stp w10,w11,[$rptr],#8
+ sub $aptr,$aptr,#32
+ ldp w8,w9,[$rptr],#8
+ ldp w10,w11,[$rptr]
+ sub $rptr,$rptr,#8
+ b.cs .LCopy_2
+ mov w8, w4
+ mov w9, w5
+ mov w10, w6
+ mov w11, w7
+.LCopy_2:
+ st1 {v0.2d,v1.2d}, [$aptr],#32 // wipe
+ st1 {v0.2d,v1.2d}, [$nptr],#32 // wipe
+ sub x17,$bptr,$aptr // preserves carry
+ stp w8,w9,[$rptr],#8
+ stp w10,w11,[$rptr],#8
+ cbnz x17,.LNEON_copy_n_zap
+
+ mov sp,x16
+ ldp d14,d15,[sp,#64]
+ ldp d12,d13,[sp,#48]
+ ldp d10,d11,[sp,#32]
+ ldp d8,d9,[sp,#16]
+ ldr x29,[sp],#80
+ ret // bx lr
+
+.size bn_mul8x_mont_neon,.-bn_mul8x_mont_neon
+___
+}
+{
########################################################################
# Following is ARMv8 adaptation of sqrx8x_mont from x86_64-mont5 module.
@@ -596,7 +980,7 @@ __bn_sqr8x_mont:
ldp $a4,$a5,[$tp,#8*4]
ldp $a6,$a7,[$tp,#8*6]
adds $acc0,$acc0,$a0
- ldr $n0,[$rp,#-8*8]
+ ldur $n0,[$rp,#-8*8]
adcs $acc1,$acc1,$a1
ldp $a0,$a1,[$ap,#8*0]
adcs $acc2,$acc2,$a2
@@ -794,7 +1178,7 @@ $code.=<<___;
//adc $carry,xzr,xzr // moved below
cbz $cnt,.Lsqr8x8_post_condition
- ldr $n0,[$tp,#-8*8]
+ ldur $n0,[$tp,#-8*8]
ldp $a0,$a1,[$np,#8*0]
ldp $a2,$a3,[$np,#8*2]
ldp $a4,$a5,[$np,#8*4]
@@ -852,7 +1236,7 @@ $code.=<<___;
ldp $a6,$a7,[$tp,#8*6]
cbz $cnt,.Lsqr8x_tail_break
- ldr $n0,[$rp,#-8*8]
+ ldur $n0,[$rp,#-8*8]
adds $acc0,$acc0,$a0
adcs $acc1,$acc1,$a1
ldp $a0,$a1,[$np,#8*0]
diff --git a/crypto/bn/asm/bn-586.pl b/crypto/bn/asm/bn-586.pl
index e0422405d5f3..56a9229add9d 100644
--- a/crypto/bn/asm/bn-586.pl
+++ b/crypto/bn/asm/bn-586.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -11,8 +11,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
&asm_init($ARGV[0]);
diff --git a/crypto/bn/asm/bn-c64xplus.asm b/crypto/bn/asm/bn-c64xplus.asm
index de6d37728fba..e273d37c1fc3 100644
--- a/crypto/bn/asm/bn-c64xplus.asm
+++ b/crypto/bn/asm/bn-c64xplus.asm
@@ -1,6 +1,6 @@
;; Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
;;
-;; Licensed under the OpenSSL license (the "License"). You may not use
+;; Licensed under the Apache License 2.0 (the "License"). You may not use
;; this file except in compliance with the License. You can obtain a copy
;; in the file LICENSE in the source distribution or at
;; https://www.openssl.org/source/license.html
@@ -10,8 +10,7 @@
;; project.
;;
;; Rights for redistribution and usage in source and binary forms are
-;; granted according to the OpenSSL license. Warranty of any kind is
-;; disclaimed.
+;; granted according to the License. Warranty of any kind is disclaimed.
;;====================================================================
;; Compiler-generated multiply-n-add SPLOOP runs at 12*n cycles, n
;; being the number of 32-bit words, addition - 8*n. Corresponding 4x
diff --git a/crypto/bn/asm/c64xplus-gf2m.pl b/crypto/bn/asm/c64xplus-gf2m.pl
index 3bb8d120e96a..5b58f3ac5478 100644
--- a/crypto/bn/asm/c64xplus-gf2m.pl
+++ b/crypto/bn/asm/c64xplus-gf2m.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -23,8 +23,7 @@
# totally unfair, because this module utilizes Galois Field Multiply
# instruction.
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
($rp,$a1,$a0,$b1,$b0)=("A4","B4","A6","B6","A8"); # argument vector
diff --git a/crypto/bn/asm/co-586.pl b/crypto/bn/asm/co-586.pl
index 3c34fa885c30..139d95dae843 100644
--- a/crypto/bn/asm/co-586.pl
+++ b/crypto/bn/asm/co-586.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -10,8 +10,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
&asm_init($ARGV[0]);
diff --git a/crypto/bn/asm/ia64-mont.pl b/crypto/bn/asm/ia64-mont.pl
index 7a4e74d71942..ab0ad9d1b395 100644
--- a/crypto/bn/asm/ia64-mont.pl
+++ b/crypto/bn/asm/ia64-mont.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -67,7 +67,8 @@
# hereafter less for longer keys, while verify - by 74-13%.
# DSA performance improves by 115-30%.
-$output=pop;
+# $output is the last argument if it looks like a file (it has an extension)
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
if ($^O eq "hpux") {
$ADDP="addp4";
diff --git a/crypto/bn/asm/ia64.S b/crypto/bn/asm/ia64.S
index 0a26735c6979..0d64e98c48b0 100644
--- a/crypto/bn/asm/ia64.S
+++ b/crypto/bn/asm/ia64.S
@@ -3,9 +3,9 @@
.ident "ia64.S, Version 2.1"
.ident "IA-64 ISA artwork by Andy Polyakov <appro@openssl.org>"
-// Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
+// Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
//
-// Licensed under the OpenSSL license (the "License"). You may not use
+// Licensed under the Apache License 2.0 (the "License"). You may not use
// this file except in compliance with the License. You can obtain a copy
// in the file LICENSE in the source distribution or at
// https://www.openssl.org/source/license.html
@@ -16,8 +16,7 @@
// project.
//
// Rights for redistribution and usage in source and binary forms are
-// granted according to the OpenSSL license. Warranty of any kind is
-// disclaimed.
+// granted according to the License. Warranty of any kind is disclaimed.
// ====================================================================
//
// Version 2.x is Itanium2 re-tune. Few words about how Itanium2 is
diff --git a/crypto/bn/asm/mips-mont.pl b/crypto/bn/asm/mips-mont.pl
index 3b79a4b186d7..687cc90928b4 100644
--- a/crypto/bn/asm/mips-mont.pl
+++ b/crypto/bn/asm/mips-mont.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -52,8 +52,12 @@
# ($t0,$t1,$t2,$t3,$t8,$t9)=map("\$$_",(12..15,24,25));
# ($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7)=map("\$$_",(16..23));
# ($gp,$sp,$fp,$ra)=map("\$$_",(28..31));
-#
-$flavour = shift || "o32"; # supported flavours are o32,n32,64,nubi32,nubi64
+
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+# supported flavours are o32,n32,64,nubi32,nubi64, default is o32
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : "o32";
if ($flavour =~ /64|n32/i) {
$PTR_ADD="daddu"; # incidentally works even on n32
@@ -74,8 +78,7 @@ $SAVED_REGS_MASK = ($flavour =~ /nubi/i) ? 0x00fff000 : 0x00ff0000;
#
######################################################################
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$output and open STDOUT,">$output";
if ($flavour =~ /64|n32/i) {
$LD="ld";
diff --git a/crypto/bn/asm/mips.pl b/crypto/bn/asm/mips.pl
index 76fe82334f88..bc18826d08f8 100644
--- a/crypto/bn/asm/mips.pl
+++ b/crypto/bn/asm/mips.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2010-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -12,8 +12,7 @@
# project.
#
# Rights for redistribution and usage in source and binary forms are
-# granted according to the OpenSSL license. Warranty of any kind is
-# disclaimed.
+# granted according to the License. Warranty of any kind is disclaimed.
# ====================================================================
@@ -55,9 +54,10 @@
# has to content with 40-85% improvement depending on benchmark and
# key length, more for longer keys.
-$flavour = shift || "o32";
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : "o32";
if ($flavour =~ /64|n32/i) {
$LD="ld";
@@ -92,6 +92,8 @@ if ($flavour =~ /64|n32/i) {
$code="#if !(defined (__mips_isa_rev) && (__mips_isa_rev >= 6))\n.set mips2\n#endif\n";
}
+$output and open STDOUT,">$output";
+
# Below is N32/64 register layout used in the original module.
#
($zero,$at,$v0,$v1)=map("\$$_",(0..3));
diff --git a/crypto/bn/asm/parisc-mont.pl b/crypto/bn/asm/parisc-mont.pl
index 6a7c714a156e..d6ca83c40bac 100644
--- a/crypto/bn/asm/parisc-mont.pl
+++ b/crypto/bn/asm/parisc-mont.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -69,10 +69,12 @@
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
-$flavour = shift;
-$output = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
-open STDOUT,">$output";
+$output and open STDOUT,">$output";
if ($flavour =~ /64/) {
$LEVEL ="2.0W";
diff --git a/crypto/bn/asm/ppc-mont.pl b/crypto/bn/asm/ppc-mont.pl
index 278314c57bd6..c3072f0d5f84 100644
--- a/crypto/bn/asm/ppc-mont.pl
+++ b/crypto/bn/asm/ppc-mont.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -41,7 +41,10 @@
# builds. On low-end 32-bit processors performance improvement turned
# to be marginal...
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /32/) {
$BITS= 32;
@@ -94,7 +97,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
+open STDOUT,"| $^X $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
$sp="r1";
$toc="r2";
diff --git a/crypto/bn/asm/ppc.pl b/crypto/bn/asm/ppc.pl
index a8d3f14e9b8e..5015f7e7efe1 100644
--- a/crypto/bn/asm/ppc.pl
+++ b/crypto/bn/asm/ppc.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -103,7 +103,10 @@
# Performance increase of ~60%
# Based on submission from Suresh N. Chari of IBM
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /32/) {
$BITS= 32;
@@ -159,7 +162,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
+open STDOUT,"| $^X $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
$data=<<EOF;
#--------------------------------------------------------------------
diff --git a/crypto/bn/asm/ppc64-mont-fixed.pl b/crypto/bn/asm/ppc64-mont-fixed.pl
new file mode 100755
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/crypto/bn/asm/ppc64-mont-fixed.pl
diff --git a/crypto/bn/asm/ppc64-mont.pl b/crypto/bn/asm/ppc64-mont.pl
index b55fd46c824f..59fae341e07a 100644
--- a/crypto/bn/asm/ppc64-mont.pl
+++ b/crypto/bn/asm/ppc64-mont.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -80,7 +80,10 @@
# ppc-mont.pl, but improvement coefficient is not as impressive
# for longer keys...
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /32/) {
$SIZE_T=4;
@@ -108,7 +111,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
+open STDOUT,"| $^X $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
$FRAME=64; # padded frame header
$TRANSFER=16*8;
diff --git a/crypto/bn/asm/rsaz-avx2.pl b/crypto/bn/asm/rsaz-avx2.pl
index 0be771febc16..3d0e342a6b8c 100755
--- a/crypto/bn/asm/rsaz-avx2.pl
+++ b/crypto/bn/asm/rsaz-avx2.pl
@@ -2,7 +2,7 @@
# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved.
# Copyright (c) 2012, Intel Corporation. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -37,9 +37,10 @@
# (***) scalar AD*X code is faster than AVX2 and is preferred code
# path for Broadwell;
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -72,7 +73,8 @@ if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|based on LLVM) ([0-9
$addx = ($ver>=3.03);
}
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT = *OUT;
if ($avx>1) {{{
diff --git a/crypto/bn/asm/rsaz-avx512.pl b/crypto/bn/asm/rsaz-avx512.pl
new file mode 100644
index 000000000000..8d1d19f6c728
--- /dev/null
+++ b/crypto/bn/asm/rsaz-avx512.pl
@@ -0,0 +1,754 @@
+# Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright (c) 2020, Intel Corporation. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+#
+#
+# Originally written by Ilya Albrekht, Sergey Kirillov and Andrey Matyukov
+# Intel Corporation
+#
+# December 2020
+#
+# Initial release.
+#
+# Implementation utilizes 256-bit (ymm) registers to avoid frequency scaling issues.
+#
+# IceLake-Client @ 1.3GHz
+# |---------+----------------------+--------------+-------------|
+# | | OpenSSL 3.0.0-alpha9 | this | Unit |
+# |---------+----------------------+--------------+-------------|
+# | rsa2048 | 2 127 659 | 1 015 625 | cycles/sign |
+# | | 611 | 1280 / +109% | sign/s |
+# |---------+----------------------+--------------+-------------|
+#
+
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+$avx512ifma=0;
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
+ =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
+ $avx512ifma = ($1>=2.26);
+}
+
+if (!$avx512 && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
+ `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)(?:\.([0-9]+))?/) {
+ $avx512ifma = ($1==2.11 && $2>=8) + ($1>=2.12);
+}
+
+if (!$avx512 && `$ENV{CC} -v 2>&1`
+ =~ /(Apple)?\s*((?:clang|LLVM) version|.*based on LLVM) ([0-9]+)\.([0-9]+)\.([0-9]+)?/) {
+ my $ver = $3 + $4/100.0 + $5/10000.0; # 3.1.0->3.01, 3.10.1->3.1001
+ if ($1) {
+ # Apple conditions, they use a different version series, see
+ # https://en.wikipedia.org/wiki/Xcode#Xcode_7.0_-_10.x_(since_Free_On-Device_Development)_2
+ # clang 7.0.0 is Apple clang 10.0.1
+ $avx512ifma = ($ver>=10.0001)
+ } else {
+ $avx512ifma = ($3>=7.0);
+ }
+}
+
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
+*STDOUT=*OUT;
+
+if ($avx512ifma>0) {{{
+@_6_args_universal_ABI = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9");
+
+$code.=<<___;
+.extern OPENSSL_ia32cap_P
+.globl ossl_rsaz_avx512ifma_eligible
+.type ossl_rsaz_avx512ifma_eligible,\@abi-omnipotent
+.align 32
+ossl_rsaz_avx512ifma_eligible:
+ mov OPENSSL_ia32cap_P+8(%rip), %ecx
+ xor %eax,%eax
+ and \$`1<<31|1<<21|1<<17|1<<16`, %ecx # avx512vl + avx512ifma + avx512dq + avx512f
+ cmp \$`1<<31|1<<21|1<<17|1<<16`, %ecx
+ cmove %ecx,%eax
+ ret
+.size ossl_rsaz_avx512ifma_eligible, .-ossl_rsaz_avx512ifma_eligible
+___
+
+###############################################################################
+# Almost Montgomery Multiplication (AMM) for 20-digit number in radix 2^52.
+#
+# AMM is defined as presented in the paper
+# "Efficient Software Implementations of Modular Exponentiation" by Shay Gueron.
+#
+# The input and output are presented in 2^52 radix domain, i.e.
+# |res|, |a|, |b|, |m| are arrays of 20 64-bit qwords with 12 high bits zeroed.
+# |k0| is a Montgomery coefficient, which is here k0 = -1/m mod 2^64
+# (note, the implementation counts only 52 bits from it).
+#
+# NB: the AMM implementation does not perform "conditional" subtraction step as
+# specified in the original algorithm as according to the paper "Enhanced Montgomery
+# Multiplication" by Shay Gueron (see Lemma 1), the result will be always < 2*2^1024
+# and can be used as a direct input to the next AMM iteration.
+# This post-condition is true, provided the correct parameter |s| is choosen, i.e.
+# s >= n + 2 * k, which matches our case: 1040 > 1024 + 2 * 1.
+#
+# void ossl_rsaz_amm52x20_x1_256(BN_ULONG *res,
+# const BN_ULONG *a,
+# const BN_ULONG *b,
+# const BN_ULONG *m,
+# BN_ULONG k0);
+###############################################################################
+{
+# input parameters ("%rdi","%rsi","%rdx","%rcx","%r8")
+my ($res,$a,$b,$m,$k0) = @_6_args_universal_ABI;
+
+my $mask52 = "%rax";
+my $acc0_0 = "%r9";
+my $acc0_0_low = "%r9d";
+my $acc0_1 = "%r15";
+my $acc0_1_low = "%r15d";
+my $b_ptr = "%r11";
+
+my $iter = "%ebx";
+
+my $zero = "%ymm0";
+my ($R0_0,$R0_0h,$R1_0,$R1_0h,$R2_0) = ("%ymm1", map("%ymm$_",(16..19)));
+my ($R0_1,$R0_1h,$R1_1,$R1_1h,$R2_1) = ("%ymm2", map("%ymm$_",(20..23)));
+my $Bi = "%ymm3";
+my $Yi = "%ymm4";
+
+# Registers mapping for normalization.
+# We can reuse Bi, Yi registers here.
+my $TMP = $Bi;
+my $mask52x4 = $Yi;
+my ($T0,$T0h,$T1,$T1h,$T2) = map("%ymm$_", (24..28));
+
+sub amm52x20_x1() {
+# _data_offset - offset in the |a| or |m| arrays pointing to the beginning
+# of data for corresponding AMM operation;
+# _b_offset - offset in the |b| array pointing to the next qword digit;
+my ($_data_offset,$_b_offset,$_acc,$_R0,$_R0h,$_R1,$_R1h,$_R2,$_k0) = @_;
+my $_R0_xmm = $_R0;
+$_R0_xmm =~ s/%y/%x/;
+$code.=<<___;
+ movq $_b_offset($b_ptr), %r13 # b[i]
+
+ vpbroadcastq %r13, $Bi # broadcast b[i]
+ movq $_data_offset($a), %rdx
+ mulx %r13, %r13, %r12 # a[0]*b[i] = (t0,t2)
+ addq %r13, $_acc # acc += t0
+ movq %r12, %r10
+ adcq \$0, %r10 # t2 += CF
+
+ movq $_k0, %r13
+ imulq $_acc, %r13 # acc * k0
+ andq $mask52, %r13 # yi = (acc * k0) & mask52
+
+ vpbroadcastq %r13, $Yi # broadcast y[i]
+ movq $_data_offset($m), %rdx
+ mulx %r13, %r13, %r12 # yi * m[0] = (t0,t1)
+ addq %r13, $_acc # acc += t0
+ adcq %r12, %r10 # t2 += (t1 + CF)
+
+ shrq \$52, $_acc
+ salq \$12, %r10
+ or %r10, $_acc # acc = ((acc >> 52) | (t2 << 12))
+
+ vpmadd52luq `$_data_offset+64*0`($a), $Bi, $_R0
+ vpmadd52luq `$_data_offset+64*0+32`($a), $Bi, $_R0h
+ vpmadd52luq `$_data_offset+64*1`($a), $Bi, $_R1
+ vpmadd52luq `$_data_offset+64*1+32`($a), $Bi, $_R1h
+ vpmadd52luq `$_data_offset+64*2`($a), $Bi, $_R2
+
+ vpmadd52luq `$_data_offset+64*0`($m), $Yi, $_R0
+ vpmadd52luq `$_data_offset+64*0+32`($m), $Yi, $_R0h
+ vpmadd52luq `$_data_offset+64*1`($m), $Yi, $_R1
+ vpmadd52luq `$_data_offset+64*1+32`($m), $Yi, $_R1h
+ vpmadd52luq `$_data_offset+64*2`($m), $Yi, $_R2
+
+ # Shift accumulators right by 1 qword, zero extending the highest one
+ valignq \$1, $_R0, $_R0h, $_R0
+ valignq \$1, $_R0h, $_R1, $_R0h
+ valignq \$1, $_R1, $_R1h, $_R1
+ valignq \$1, $_R1h, $_R2, $_R1h
+ valignq \$1, $_R2, $zero, $_R2
+
+ vmovq $_R0_xmm, %r13
+ addq %r13, $_acc # acc += R0[0]
+
+ vpmadd52huq `$_data_offset+64*0`($a), $Bi, $_R0
+ vpmadd52huq `$_data_offset+64*0+32`($a), $Bi, $_R0h
+ vpmadd52huq `$_data_offset+64*1`($a), $Bi, $_R1
+ vpmadd52huq `$_data_offset+64*1+32`($a), $Bi, $_R1h
+ vpmadd52huq `$_data_offset+64*2`($a), $Bi, $_R2
+
+ vpmadd52huq `$_data_offset+64*0`($m), $Yi, $_R0
+ vpmadd52huq `$_data_offset+64*0+32`($m), $Yi, $_R0h
+ vpmadd52huq `$_data_offset+64*1`($m), $Yi, $_R1
+ vpmadd52huq `$_data_offset+64*1+32`($m), $Yi, $_R1h
+ vpmadd52huq `$_data_offset+64*2`($m), $Yi, $_R2
+___
+}
+
+# Normalization routine: handles carry bits in R0..R2 QWs and
+# gets R0..R2 back to normalized 2^52 representation.
+#
+# Uses %r8-14,%e[bcd]x
+sub amm52x20_x1_norm {
+my ($_acc,$_R0,$_R0h,$_R1,$_R1h,$_R2) = @_;
+$code.=<<___;
+ # Put accumulator to low qword in R0
+ vpbroadcastq $_acc, $TMP
+ vpblendd \$3, $TMP, $_R0, $_R0
+
+ # Extract "carries" (12 high bits) from each QW of R0..R2
+ # Save them to LSB of QWs in T0..T2
+ vpsrlq \$52, $_R0, $T0
+ vpsrlq \$52, $_R0h, $T0h
+ vpsrlq \$52, $_R1, $T1
+ vpsrlq \$52, $_R1h, $T1h
+ vpsrlq \$52, $_R2, $T2
+
+ # "Shift left" T0..T2 by 1 QW
+ valignq \$3, $T1h, $T2, $T2
+ valignq \$3, $T1, $T1h, $T1h
+ valignq \$3, $T0h, $T1, $T1
+ valignq \$3, $T0, $T0h, $T0h
+ valignq \$3, $zero, $T0, $T0
+
+ # Drop "carries" from R0..R2 QWs
+ vpandq $mask52x4, $_R0, $_R0
+ vpandq $mask52x4, $_R0h, $_R0h
+ vpandq $mask52x4, $_R1, $_R1
+ vpandq $mask52x4, $_R1h, $_R1h
+ vpandq $mask52x4, $_R2, $_R2
+
+ # Sum R0..R2 with corresponding adjusted carries
+ vpaddq $T0, $_R0, $_R0
+ vpaddq $T0h, $_R0h, $_R0h
+ vpaddq $T1, $_R1, $_R1
+ vpaddq $T1h, $_R1h, $_R1h
+ vpaddq $T2, $_R2, $_R2
+
+ # Now handle carry bits from this addition
+ # Get mask of QWs which 52-bit parts overflow...
+ vpcmpuq \$1, $_R0, $mask52x4, %k1 # OP=lt
+ vpcmpuq \$1, $_R0h, $mask52x4, %k2
+ vpcmpuq \$1, $_R1, $mask52x4, %k3
+ vpcmpuq \$1, $_R1h, $mask52x4, %k4
+ vpcmpuq \$1, $_R2, $mask52x4, %k5
+ kmovb %k1, %r14d # k1
+ kmovb %k2, %r13d # k1h
+ kmovb %k3, %r12d # k2
+ kmovb %k4, %r11d # k2h
+ kmovb %k5, %r10d # k3
+
+ # ...or saturated
+ vpcmpuq \$0, $_R0, $mask52x4, %k1 # OP=eq
+ vpcmpuq \$0, $_R0h, $mask52x4, %k2
+ vpcmpuq \$0, $_R1, $mask52x4, %k3
+ vpcmpuq \$0, $_R1h, $mask52x4, %k4
+ vpcmpuq \$0, $_R2, $mask52x4, %k5
+ kmovb %k1, %r9d # k4
+ kmovb %k2, %r8d # k4h
+ kmovb %k3, %ebx # k5
+ kmovb %k4, %ecx # k5h
+ kmovb %k5, %edx # k6
+
+ # Get mask of QWs where carries shall be propagated to.
+ # Merge 4-bit masks to 8-bit values to use add with carry.
+ shl \$4, %r13b
+ or %r13b, %r14b
+ shl \$4, %r11b
+ or %r11b, %r12b
+
+ add %r14b, %r14b
+ adc %r12b, %r12b
+ adc %r10b, %r10b
+
+ shl \$4, %r8b
+ or %r8b,%r9b
+ shl \$4, %cl
+ or %cl, %bl
+
+ add %r9b, %r14b
+ adc %bl, %r12b
+ adc %dl, %r10b
+
+ xor %r9b, %r14b
+ xor %bl, %r12b
+ xor %dl, %r10b
+
+ kmovb %r14d, %k1
+ shr \$4, %r14b
+ kmovb %r14d, %k2
+ kmovb %r12d, %k3
+ shr \$4, %r12b
+ kmovb %r12d, %k4
+ kmovb %r10d, %k5
+
+ # Add carries according to the obtained mask
+ vpsubq $mask52x4, $_R0, ${_R0}{%k1}
+ vpsubq $mask52x4, $_R0h, ${_R0h}{%k2}
+ vpsubq $mask52x4, $_R1, ${_R1}{%k3}
+ vpsubq $mask52x4, $_R1h, ${_R1h}{%k4}
+ vpsubq $mask52x4, $_R2, ${_R2}{%k5}
+
+ vpandq $mask52x4, $_R0, $_R0
+ vpandq $mask52x4, $_R0h, $_R0h
+ vpandq $mask52x4, $_R1, $_R1
+ vpandq $mask52x4, $_R1h, $_R1h
+ vpandq $mask52x4, $_R2, $_R2
+___
+}
+
+$code.=<<___;
+.text
+
+.globl ossl_rsaz_amm52x20_x1_256
+.type ossl_rsaz_amm52x20_x1_256,\@function,5
+.align 32
+ossl_rsaz_amm52x20_x1_256:
+.cfi_startproc
+ endbranch
+ push %rbx
+.cfi_push %rbx
+ push %rbp
+.cfi_push %rbp
+ push %r12
+.cfi_push %r12
+ push %r13
+.cfi_push %r13
+ push %r14
+.cfi_push %r14
+ push %r15
+.cfi_push %r15
+.Lrsaz_amm52x20_x1_256_body:
+
+ # Zeroing accumulators
+ vpxord $zero, $zero, $zero
+ vmovdqa64 $zero, $R0_0
+ vmovdqa64 $zero, $R0_0h
+ vmovdqa64 $zero, $R1_0
+ vmovdqa64 $zero, $R1_0h
+ vmovdqa64 $zero, $R2_0
+
+ xorl $acc0_0_low, $acc0_0_low
+
+ movq $b, $b_ptr # backup address of b
+ movq \$0xfffffffffffff, $mask52 # 52-bit mask
+
+ # Loop over 20 digits unrolled by 4
+ mov \$5, $iter
+
+.align 32
+.Lloop5:
+___
+ foreach my $idx (0..3) {
+ &amm52x20_x1(0,8*$idx,$acc0_0,$R0_0,$R0_0h,$R1_0,$R1_0h,$R2_0,$k0);
+ }
+$code.=<<___;
+ lea `4*8`($b_ptr), $b_ptr
+ dec $iter
+ jne .Lloop5
+
+ vmovdqa64 .Lmask52x4(%rip), $mask52x4
+___
+ &amm52x20_x1_norm($acc0_0,$R0_0,$R0_0h,$R1_0,$R1_0h,$R2_0);
+$code.=<<___;
+
+ vmovdqu64 $R0_0, ($res)
+ vmovdqu64 $R0_0h, 32($res)
+ vmovdqu64 $R1_0, 64($res)
+ vmovdqu64 $R1_0h, 96($res)
+ vmovdqu64 $R2_0, 128($res)
+
+ vzeroupper
+ mov 0(%rsp),%r15
+.cfi_restore %r15
+ mov 8(%rsp),%r14
+.cfi_restore %r14
+ mov 16(%rsp),%r13
+.cfi_restore %r13
+ mov 24(%rsp),%r12
+.cfi_restore %r12
+ mov 32(%rsp),%rbp
+.cfi_restore %rbp
+ mov 40(%rsp),%rbx
+.cfi_restore %rbx
+ lea 48(%rsp),%rsp
+.cfi_adjust_cfa_offset -48
+.Lrsaz_amm52x20_x1_256_epilogue:
+ ret
+.cfi_endproc
+.size ossl_rsaz_amm52x20_x1_256, .-ossl_rsaz_amm52x20_x1_256
+___
+
+$code.=<<___;
+.data
+.align 32
+.Lmask52x4:
+ .quad 0xfffffffffffff
+ .quad 0xfffffffffffff
+ .quad 0xfffffffffffff
+ .quad 0xfffffffffffff
+___
+
+###############################################################################
+# Dual Almost Montgomery Multiplication for 20-digit number in radix 2^52
+#
+# See description of ossl_rsaz_amm52x20_x1_256() above for details about Almost
+# Montgomery Multiplication algorithm and function input parameters description.
+#
+# This function does two AMMs for two independent inputs, hence dual.
+#
+# void ossl_rsaz_amm52x20_x2_256(BN_ULONG out[2][20],
+# const BN_ULONG a[2][20],
+# const BN_ULONG b[2][20],
+# const BN_ULONG m[2][20],
+# const BN_ULONG k0[2]);
+###############################################################################
+
+$code.=<<___;
+.text
+
+.globl ossl_rsaz_amm52x20_x2_256
+.type ossl_rsaz_amm52x20_x2_256,\@function,5
+.align 32
+ossl_rsaz_amm52x20_x2_256:
+.cfi_startproc
+ endbranch
+ push %rbx
+.cfi_push %rbx
+ push %rbp
+.cfi_push %rbp
+ push %r12
+.cfi_push %r12
+ push %r13
+.cfi_push %r13
+ push %r14
+.cfi_push %r14
+ push %r15
+.cfi_push %r15
+.Lrsaz_amm52x20_x2_256_body:
+
+ # Zeroing accumulators
+ vpxord $zero, $zero, $zero
+ vmovdqa64 $zero, $R0_0
+ vmovdqa64 $zero, $R0_0h
+ vmovdqa64 $zero, $R1_0
+ vmovdqa64 $zero, $R1_0h
+ vmovdqa64 $zero, $R2_0
+ vmovdqa64 $zero, $R0_1
+ vmovdqa64 $zero, $R0_1h
+ vmovdqa64 $zero, $R1_1
+ vmovdqa64 $zero, $R1_1h
+ vmovdqa64 $zero, $R2_1
+
+ xorl $acc0_0_low, $acc0_0_low
+ xorl $acc0_1_low, $acc0_1_low
+
+ movq $b, $b_ptr # backup address of b
+ movq \$0xfffffffffffff, $mask52 # 52-bit mask
+
+ mov \$20, $iter
+
+.align 32
+.Lloop20:
+___
+ &amm52x20_x1( 0, 0,$acc0_0,$R0_0,$R0_0h,$R1_0,$R1_0h,$R2_0,"($k0)");
+ # 20*8 = offset of the next dimension in two-dimension array
+ &amm52x20_x1(20*8,20*8,$acc0_1,$R0_1,$R0_1h,$R1_1,$R1_1h,$R2_1,"8($k0)");
+$code.=<<___;
+ lea 8($b_ptr), $b_ptr
+ dec $iter
+ jne .Lloop20
+
+ vmovdqa64 .Lmask52x4(%rip), $mask52x4
+___
+ &amm52x20_x1_norm($acc0_0,$R0_0,$R0_0h,$R1_0,$R1_0h,$R2_0);
+ &amm52x20_x1_norm($acc0_1,$R0_1,$R0_1h,$R1_1,$R1_1h,$R2_1);
+$code.=<<___;
+
+ vmovdqu64 $R0_0, ($res)
+ vmovdqu64 $R0_0h, 32($res)
+ vmovdqu64 $R1_0, 64($res)
+ vmovdqu64 $R1_0h, 96($res)
+ vmovdqu64 $R2_0, 128($res)
+
+ vmovdqu64 $R0_1, 160($res)
+ vmovdqu64 $R0_1h, 192($res)
+ vmovdqu64 $R1_1, 224($res)
+ vmovdqu64 $R1_1h, 256($res)
+ vmovdqu64 $R2_1, 288($res)
+
+ vzeroupper
+ mov 0(%rsp),%r15
+.cfi_restore %r15
+ mov 8(%rsp),%r14
+.cfi_restore %r14
+ mov 16(%rsp),%r13
+.cfi_restore %r13
+ mov 24(%rsp),%r12
+.cfi_restore %r12
+ mov 32(%rsp),%rbp
+.cfi_restore %rbp
+ mov 40(%rsp),%rbx
+.cfi_restore %rbx
+ lea 48(%rsp),%rsp
+.cfi_adjust_cfa_offset -48
+.Lrsaz_amm52x20_x2_256_epilogue:
+ ret
+.cfi_endproc
+.size ossl_rsaz_amm52x20_x2_256, .-ossl_rsaz_amm52x20_x2_256
+___
+}
+
+###############################################################################
+# Constant time extraction from the precomputed table of powers base^i, where
+# i = 0..2^EXP_WIN_SIZE-1
+#
+# The input |red_table| contains precomputations for two independent base values,
+# so the |tbl_idx| indicates for which base shall we extract the value.
+# |red_table_idx| is a power index.
+#
+# Extracted value (output) is 20 digit number in 2^52 radix.
+#
+# void ossl_extract_multiplier_2x20_win5(BN_ULONG *red_Y,
+# const BN_ULONG red_table[1 << EXP_WIN_SIZE][2][20],
+# int red_table_idx,
+# int tbl_idx); # 0 or 1
+#
+# EXP_WIN_SIZE = 5
+###############################################################################
+{
+# input parameters
+my ($out,$red_tbl,$red_tbl_idx,$tbl_idx) = @_6_args_universal_ABI;
+
+my ($t0,$t1,$t2,$t3,$t4) = map("%ymm$_", (0..4));
+my $t4xmm = $t4;
+$t4xmm =~ s/%y/%x/;
+my ($tmp0,$tmp1,$tmp2,$tmp3,$tmp4) = map("%ymm$_", (16..20));
+my ($cur_idx,$idx,$ones) = map("%ymm$_", (21..23));
+
+$code.=<<___;
+.text
+
+.align 32
+.globl ossl_extract_multiplier_2x20_win5
+.type ossl_extract_multiplier_2x20_win5,\@function,4
+ossl_extract_multiplier_2x20_win5:
+.cfi_startproc
+ endbranch
+ leaq ($tbl_idx,$tbl_idx,4), %rax
+ salq \$5, %rax
+ addq %rax, $red_tbl
+
+ vmovdqa64 .Lones(%rip), $ones # broadcast ones
+ vpbroadcastq $red_tbl_idx, $idx
+ leaq `(1<<5)*2*20*8`($red_tbl), %rax # holds end of the tbl
+
+ vpxor $t4xmm, $t4xmm, $t4xmm
+ vmovdqa64 $t4, $t3 # zeroing t0..4, cur_idx
+ vmovdqa64 $t4, $t2
+ vmovdqa64 $t4, $t1
+ vmovdqa64 $t4, $t0
+ vmovdqa64 $t4, $cur_idx
+
+.align 32
+.Lloop:
+ vpcmpq \$0, $cur_idx, $idx, %k1 # mask of (idx == cur_idx)
+ addq \$320, $red_tbl # 320 = 2 * 20 digits * 8 bytes
+ vpaddq $ones, $cur_idx, $cur_idx # increment cur_idx
+ vmovdqu64 -320($red_tbl), $tmp0 # load data from red_tbl
+ vmovdqu64 -288($red_tbl), $tmp1
+ vmovdqu64 -256($red_tbl), $tmp2
+ vmovdqu64 -224($red_tbl), $tmp3
+ vmovdqu64 -192($red_tbl), $tmp4
+ vpblendmq $tmp0, $t0, ${t0}{%k1} # extract data when mask is not zero
+ vpblendmq $tmp1, $t1, ${t1}{%k1}
+ vpblendmq $tmp2, $t2, ${t2}{%k1}
+ vpblendmq $tmp3, $t3, ${t3}{%k1}
+ vpblendmq $tmp4, $t4, ${t4}{%k1}
+ cmpq $red_tbl, %rax
+ jne .Lloop
+
+ vmovdqu64 $t0, ($out) # store t0..4
+ vmovdqu64 $t1, 32($out)
+ vmovdqu64 $t2, 64($out)
+ vmovdqu64 $t3, 96($out)
+ vmovdqu64 $t4, 128($out)
+
+ ret
+.cfi_endproc
+.size ossl_extract_multiplier_2x20_win5, .-ossl_extract_multiplier_2x20_win5
+___
+$code.=<<___;
+.data
+.align 32
+.Lones:
+ .quad 1,1,1,1
+___
+}
+
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___
+.extern __imp_RtlVirtualUnwind
+.type rsaz_def_handler,\@abi-omnipotent
+.align 16
+rsaz_def_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<.Lprologue
+ jb .Lcommon_seh_tail
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=.Lepilogue
+ jae .Lcommon_seh_tail
+
+ lea 48(%rax),%rax
+
+ mov -8(%rax),%rbx
+ mov -16(%rax),%rbp
+ mov -24(%rax),%r12
+ mov -32(%rax),%r13
+ mov -40(%rax),%r14
+ mov -48(%rax),%r15
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R14
+
+.Lcommon_seh_tail:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$154,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size rsaz_def_handler,.-rsaz_def_handler
+
+.section .pdata
+.align 4
+ .rva .LSEH_begin_ossl_rsaz_amm52x20_x1_256
+ .rva .LSEH_end_ossl_rsaz_amm52x20_x1_256
+ .rva .LSEH_info_ossl_rsaz_amm52x20_x1_256
+
+ .rva .LSEH_begin_ossl_rsaz_amm52x20_x2_256
+ .rva .LSEH_end_ossl_rsaz_amm52x20_x2_256
+ .rva .LSEH_info_ossl_rsaz_amm52x20_x2_256
+
+ .rva .LSEH_begin_ossl_extract_multiplier_2x20_win5
+ .rva .LSEH_end_ossl_extract_multiplier_2x20_win5
+ .rva .LSEH_info_ossl_extract_multiplier_2x20_win5
+
+.section .xdata
+.align 8
+.LSEH_info_ossl_rsaz_amm52x20_x1_256:
+ .byte 9,0,0,0
+ .rva rsaz_def_handler
+ .rva .Lrsaz_amm52x20_x1_256_body,.Lrsaz_amm52x20_x1_256_epilogue
+.LSEH_info_ossl_rsaz_amm52x20_x2_256:
+ .byte 9,0,0,0
+ .rva rsaz_def_handler
+ .rva .Lrsaz_amm52x20_x2_256_body,.Lrsaz_amm52x20_x2_256_epilogue
+.LSEH_info_ossl_extract_multiplier_2x20_win5:
+ .byte 9,0,0,0
+ .rva rsaz_def_handler
+ .rva .LSEH_begin_ossl_extract_multiplier_2x20_win5,.LSEH_begin_ossl_extract_multiplier_2x20_win5
+___
+}
+}}} else {{{ # fallback for old assembler
+$code.=<<___;
+.text
+
+.globl ossl_rsaz_avx512ifma_eligible
+.type ossl_rsaz_avx512ifma_eligible,\@abi-omnipotent
+ossl_rsaz_avx512ifma_eligible:
+ xor %eax,%eax
+ ret
+.size ossl_rsaz_avx512ifma_eligible, .-ossl_rsaz_avx512ifma_eligible
+
+.globl ossl_rsaz_amm52x20_x1_256
+.globl ossl_rsaz_amm52x20_x2_256
+.globl ossl_extract_multiplier_2x20_win5
+.type ossl_rsaz_amm52x20_x1_256,\@abi-omnipotent
+ossl_rsaz_amm52x20_x1_256:
+ossl_rsaz_amm52x20_x2_256:
+ossl_extract_multiplier_2x20_win5:
+ .byte 0x0f,0x0b # ud2
+ ret
+.size ossl_rsaz_amm52x20_x1_256, .-ossl_rsaz_amm52x20_x1_256
+___
+}}}
+
+$code =~ s/\`([^\`]*)\`/eval $1/gem;
+print $code;
+close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/bn/asm/rsaz-x86_64.pl b/crypto/bn/asm/rsaz-x86_64.pl
index cf08ce9b8356..5c7d526fa37a 100755
--- a/crypto/bn/asm/rsaz-x86_64.pl
+++ b/crypto/bn/asm/rsaz-x86_64.pl
@@ -2,7 +2,7 @@
# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved.
# Copyright (c) 2012, Intel Corporation. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -52,9 +52,10 @@
# purposes;
# (**) MULX was attempted, but found to give only marginal improvement;
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -63,7 +64,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
diff --git a/crypto/bn/asm/s390x-gf2m.pl b/crypto/bn/asm/s390x-gf2m.pl
index a7e4b8a97d30..038a6bc97440 100644
--- a/crypto/bn/asm/s390x-gf2m.pl
+++ b/crypto/bn/asm/s390x-gf2m.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -32,7 +32,10 @@
# so that improvement coefficients can vary from one specific
# setup to another.
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /3[12]/) {
$SIZE_T=4;
@@ -42,8 +45,7 @@ if ($flavour =~ /3[12]/) {
$g="g";
}
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$output and open STDOUT,">$output";
$stdframe=16*$SIZE_T+4*8;
diff --git a/crypto/bn/asm/s390x-mont.pl b/crypto/bn/asm/s390x-mont.pl
index bc8c8951e060..af088ccae10d 100644
--- a/crypto/bn/asm/s390x-mont.pl
+++ b/crypto/bn/asm/s390x-mont.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -51,7 +51,10 @@
# On z990 it was measured to perform 2.6-2.2 times better than
# compiler-generated code, less for longer keys...
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /3[12]/) {
$SIZE_T=4;
@@ -61,8 +64,7 @@ if ($flavour =~ /3[12]/) {
$g="g";
}
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$output and open STDOUT,">$output";
$stdframe=16*$SIZE_T+4*8;
diff --git a/crypto/bn/asm/s390x.S b/crypto/bn/asm/s390x.S
index b666c41a88a4..65a0898739b6 100644
--- a/crypto/bn/asm/s390x.S
+++ b/crypto/bn/asm/s390x.S
@@ -2,7 +2,7 @@
// ====================================================================
// Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
//
-// Licensed under the OpenSSL license (the "License"). You may not use
+// Licensed under the Apache License 2.0 (the "License"). You may not use
// this file except in compliance with the License. You can obtain a copy
// in the file LICENSE in the source distribution or at
// https://www.openssl.org/source/license.html
diff --git a/crypto/bn/asm/sparct4-mont.pl b/crypto/bn/asm/sparct4-mont.pl
index 62e297a01692..8a3bedc9af42 100755
--- a/crypto/bn/asm/sparct4-mont.pl
+++ b/crypto/bn/asm/sparct4-mont.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -83,11 +83,13 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "sparcv9_modes.pl";
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
$code.=<<___;
-#include "sparc_arch.h"
+#ifndef __ASSEMBLER__
+# define __ASSEMBLER__ 1
+#endif
+#include "crypto/sparc_arch.h"
#ifdef __arch64__
.register %g2,#scratch
diff --git a/crypto/bn/asm/sparcv8.S b/crypto/bn/asm/sparcv8.S
index 75d72eb92c74..94487008443e 100644
--- a/crypto/bn/asm/sparcv8.S
+++ b/crypto/bn/asm/sparcv8.S
@@ -5,7 +5,7 @@
* ====================================================================
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/bn/asm/sparcv8plus.S b/crypto/bn/asm/sparcv8plus.S
index d520ffa7c248..696dc7b5fe09 100644
--- a/crypto/bn/asm/sparcv8plus.S
+++ b/crypto/bn/asm/sparcv8plus.S
@@ -3,9 +3,9 @@
/*
* ====================================================================
- * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/bn/asm/sparcv9-gf2m.pl b/crypto/bn/asm/sparcv9-gf2m.pl
index 238a93dca56c..9f773f183c96 100644
--- a/crypto/bn/asm/sparcv9-gf2m.pl
+++ b/crypto/bn/asm/sparcv9-gf2m.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -25,8 +25,7 @@
# ~100-230% faster than gcc-generated code and ~35-90% faster than
# the pure SPARCv9 code path.
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
$locals=16*8;
@@ -39,7 +38,10 @@ $tab="%l0";
($lo,$hi,$b)=("%g1",$a8,"%o7"); $a=$lo;
$code.=<<___;
-#include <sparc_arch.h>
+#ifndef __ASSEMBLER__
+# define __ASSEMBLER__ 1
+#endif
+#include "crypto/sparc_arch.h"
#ifdef __arch64__
.register %g2,#scratch
diff --git a/crypto/bn/asm/sparcv9-mont.pl b/crypto/bn/asm/sparcv9-mont.pl
index d1a3c2bc4343..fe51fcaf81c7 100644
--- a/crypto/bn/asm/sparcv9-mont.pl
+++ b/crypto/bn/asm/sparcv9-mont.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -49,8 +49,7 @@
# module still have hidden potential [see TODO list there], which is
# estimated to be larger than 20%...
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
# int bn_mul_mont(
$rp="%i0"; # BN_ULONG *rp,
@@ -84,7 +83,10 @@ $tpj="%l7";
$fname="bn_mul_mont_int";
$code=<<___;
-#include "sparc_arch.h"
+#ifndef __ASSEMBLER__
+# define __ASSEMBLER__ 1
+#endif
+#include "crypto/sparc_arch.h"
.section ".text",#alloc,#execinstr
diff --git a/crypto/bn/asm/sparcv9a-mont.pl b/crypto/bn/asm/sparcv9a-mont.pl
index 7a1fca1263a9..08773bc75835 100755
--- a/crypto/bn/asm/sparcv9a-mont.pl
+++ b/crypto/bn/asm/sparcv9a-mont.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -62,8 +62,10 @@
# key length, more for longer keys] on USI&II cores and 30-80% - on
# USIII&IV.
-$output = pop;
-open STDOUT,">$output";
+# $output is the last argument if it looks like a file (it has an extension)
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+
+$output and open STDOUT,">$output";
$fname="bn_mul_mont_fpu";
@@ -124,7 +126,10 @@ $nhia="%f56"; $nhib="%f58"; $nhic="%f60"; $nhid="%f62";
$ASI_FL16_P=0xD2; # magic ASI value to engage 16-bit FP load
$code=<<___;
-#include "sparc_arch.h"
+#ifndef __ASSEMBLER__
+# define __ASSEMBLER__ 1
+#endif
+#include "crypto/sparc_arch.h"
.section ".text",#alloc,#execinstr
diff --git a/crypto/bn/asm/via-mont.pl b/crypto/bn/asm/via-mont.pl
index 9dbc8d458792..365dc652fe51 100644
--- a/crypto/bn/asm/via-mont.pl
+++ b/crypto/bn/asm/via-mont.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -88,8 +88,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
&asm_init($ARGV[0]);
diff --git a/crypto/bn/asm/vis3-mont.pl b/crypto/bn/asm/vis3-mont.pl
index d797af8745dc..f7e6c38635ac 100644
--- a/crypto/bn/asm/vis3-mont.pl
+++ b/crypto/bn/asm/vis3-mont.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -25,14 +25,16 @@
# for reference purposes, because T4 has dedicated Montgomery
# multiplication and squaring *instructions* that deliver even more.
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
$frame = "STACK_FRAME";
$bias = "STACK_BIAS";
$code.=<<___;
-#include "sparc_arch.h"
+#ifndef __ASSEMBLER__
+# define __ASSEMBLER__ 1
+#endif
+#include "crypto/sparc_arch.h"
#ifdef __arch64__
.register %g2,#scratch
diff --git a/crypto/bn/asm/x86-gf2m.pl b/crypto/bn/asm/x86-gf2m.pl
index 436d90b11ea4..469effd39e56 100644
--- a/crypto/bn/asm/x86-gf2m.pl
+++ b/crypto/bn/asm/x86-gf2m.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -43,8 +43,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
&asm_init($ARGV[0],$x86only = $ARGV[$#ARGV] eq "386");
diff --git a/crypto/bn/asm/x86-mont.pl b/crypto/bn/asm/x86-mont.pl
index 2103f806b65a..8fff9e1d3686 100755
--- a/crypto/bn/asm/x86-mont.pl
+++ b/crypto/bn/asm/x86-mont.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -37,8 +37,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
&asm_init($ARGV[0]);
diff --git a/crypto/bn/asm/x86_64-gcc.c b/crypto/bn/asm/x86_64-gcc.c
index e6fdaadf0e91..68453b3d5276 100644
--- a/crypto/bn/asm/x86_64-gcc.c
+++ b/crypto/bn/asm/x86_64-gcc.c
@@ -1,7 +1,7 @@
/*
* Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -18,8 +18,7 @@
* project.
*
* Rights for redistribution and usage in source and binary forms are
- * granted according to the OpenSSL license. Warranty of any kind is
- * disclaimed.
+ * granted according to the License. Warranty of any kind is disclaimed.
*
* Q. Version 0.1? It doesn't sound like Andy, he used to assign real
* versions, like 1.0...
diff --git a/crypto/bn/asm/x86_64-gf2m.pl b/crypto/bn/asm/x86_64-gf2m.pl
index 655f13c89ee8..4c4dfc41ffe6 100644
--- a/crypto/bn/asm/x86_64-gf2m.pl
+++ b/crypto/bn/asm/x86_64-gf2m.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -27,9 +27,10 @@
# these coefficients are not ones for bn_GF2m_mul_2x2 itself, as not
# all CPU time is burnt in it...
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -38,7 +39,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
($lo,$hi)=("%rax","%rdx"); $a=$lo;
diff --git a/crypto/bn/asm/x86_64-mont.pl b/crypto/bn/asm/x86_64-mont.pl
index f14d4e63b975..140072b899dc 100755
--- a/crypto/bn/asm/x86_64-mont.pl
+++ b/crypto/bn/asm/x86_64-mont.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -46,9 +46,10 @@
#
# Add MULX/ADOX/ADCX code path.
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -57,7 +58,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
diff --git a/crypto/bn/asm/x86_64-mont5.pl b/crypto/bn/asm/x86_64-mont5.pl
index 33cb769c36d5..185d9e76ce23 100755
--- a/crypto/bn/asm/x86_64-mont5.pl
+++ b/crypto/bn/asm/x86_64-mont5.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -31,9 +31,10 @@
# the np argument is not just modulus value, but one interleaved
# with 0. This is to optimize post-condition...
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -42,7 +43,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
diff --git a/crypto/bn/bn_add.c b/crypto/bn/bn_add.c
index 8ffe49618a8b..ae3e549e4430 100644
--- a/crypto/bn/bn_add.c
+++ b/crypto/bn/bn_add.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -136,7 +136,7 @@ int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
dif = max - min;
if (dif < 0) { /* hmm... should not be happening */
- BNerr(BN_F_BN_USUB, BN_R_ARG2_LT_ARG3);
+ ERR_raise(ERR_LIB_BN, BN_R_ARG2_LT_ARG3);
return 0;
}
diff --git a/crypto/bn/bn_asm.c b/crypto/bn/bn_asm.c
index 4d83a8cf1115..257701d9dc7c 100644
--- a/crypto/bn/bn_asm.c
+++ b/crypto/bn/bn_asm.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/bn/bn_blind.c b/crypto/bn/bn_blind.c
index dd5beea7c93e..0b6d1bccc2a2 100644
--- a/crypto/bn/bn_blind.c
+++ b/crypto/bn/bn_blind.c
@@ -1,7 +1,7 @@
/*
* Copyright 1998-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -20,13 +20,13 @@ BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod)
bn_check_top(mod);
if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
- BNerr(BN_F_BN_BLINDING_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
- BNerr(BN_F_BN_BLINDING_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
@@ -81,7 +81,7 @@ int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx)
int ret = 0;
if ((b->A == NULL) || (b->Ai == NULL)) {
- BNerr(BN_F_BN_BLINDING_UPDATE, BN_R_NOT_INITIALIZED);
+ ERR_raise(ERR_LIB_BN, BN_R_NOT_INITIALIZED);
goto err;
}
@@ -124,7 +124,7 @@ int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx)
bn_check_top(n);
if ((b->A == NULL) || (b->Ai == NULL)) {
- BNerr(BN_F_BN_BLINDING_CONVERT_EX, BN_R_NOT_INITIALIZED);
+ ERR_raise(ERR_LIB_BN, BN_R_NOT_INITIALIZED);
return 0;
}
@@ -158,7 +158,7 @@ int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b,
bn_check_top(n);
if (r == NULL && (r = b->Ai) == NULL) {
- BNerr(BN_F_BN_BLINDING_INVERT_EX, BN_R_NOT_INITIALIZED);
+ ERR_raise(ERR_LIB_BN, BN_R_NOT_INITIALIZED);
return 0;
}
@@ -256,7 +256,7 @@ BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
do {
int rv;
- if (!BN_priv_rand_range(ret->A, ret->mod))
+ if (!BN_priv_rand_range_ex(ret->A, ret->mod, 0, ctx))
goto err;
if (int_bn_mod_inverse(ret->Ai, ret->A, ret->mod, ctx, &rv))
break;
@@ -268,7 +268,7 @@ BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
goto err;
if (retry_counter-- == 0) {
- BNerr(BN_F_BN_BLINDING_CREATE_PARAM, BN_R_TOO_MANY_ITERATIONS);
+ ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS);
goto err;
}
} while (1);
diff --git a/crypto/bn/bn_const.c b/crypto/bn/bn_const.c
index 39dd61202ad7..a36e0ac792dd 100644
--- a/crypto/bn/bn_const.c
+++ b/crypto/bn/bn_const.c
@@ -1,13 +1,17 @@
/*
- * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/bn.h>
+#include "crypto/bn_dh.h"
+
+#define COPY_BN(dst, src) (dst != NULL) ? BN_copy(dst, &src) : BN_dup(&src)
+
/*-
* "First Oakley Default Group" from RFC2409, section 6.1.
@@ -80,33 +84,7 @@ BIGNUM *BN_get_rfc2409_prime_1024(BIGNUM *bn)
BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *bn)
{
- static const unsigned char RFC3526_PRIME_1536[] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
- 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
- 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
- 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
- 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
- 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
- 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
- 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
- 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
- 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
- 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
- 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
- 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
- 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
- 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
- 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
- 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
- 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
- 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
- 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
- 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
- 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- };
- return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), bn);
+ return COPY_BN(bn, ossl_bignum_modp_1536_p);
}
/*-
@@ -119,41 +97,7 @@ BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *bn)
BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *bn)
{
- static const unsigned char RFC3526_PRIME_2048[] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
- 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
- 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
- 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
- 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
- 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
- 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
- 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
- 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
- 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
- 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
- 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
- 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
- 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
- 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
- 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
- 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
- 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
- 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
- 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
- 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
- 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
- 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
- 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
- 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
- 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
- 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
- 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
- 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
- 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- };
- return BN_bin2bn(RFC3526_PRIME_2048, sizeof(RFC3526_PRIME_2048), bn);
+ return COPY_BN(bn, ossl_bignum_modp_2048_p);
}
/*-
@@ -166,57 +110,7 @@ BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *bn)
BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *bn)
{
- static const unsigned char RFC3526_PRIME_3072[] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
- 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
- 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
- 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
- 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
- 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
- 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
- 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
- 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
- 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
- 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
- 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
- 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
- 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
- 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
- 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
- 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
- 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
- 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
- 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
- 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
- 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
- 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
- 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
- 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
- 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
- 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
- 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
- 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
- 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
- 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
- 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
- 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
- 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
- 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
- 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
- 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
- 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
- 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
- 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
- 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
- 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
- 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
- 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
- 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
- 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- };
- return BN_bin2bn(RFC3526_PRIME_3072, sizeof(RFC3526_PRIME_3072), bn);
+ return COPY_BN(bn, ossl_bignum_modp_3072_p);
}
/*-
@@ -229,73 +123,7 @@ BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *bn)
BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *bn)
{
- static const unsigned char RFC3526_PRIME_4096[] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
- 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
- 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
- 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
- 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
- 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
- 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
- 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
- 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
- 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
- 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
- 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
- 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
- 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
- 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
- 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
- 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
- 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
- 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
- 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
- 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
- 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
- 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
- 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
- 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
- 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
- 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
- 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
- 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
- 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
- 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
- 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
- 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
- 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
- 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
- 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
- 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
- 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
- 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
- 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
- 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
- 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
- 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
- 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
- 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
- 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
- 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
- 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
- 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
- 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
- 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
- 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
- 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
- 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
- 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
- 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
- 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
- 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
- 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
- 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
- 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
- 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- };
- return BN_bin2bn(RFC3526_PRIME_4096, sizeof(RFC3526_PRIME_4096), bn);
+ return COPY_BN(bn, ossl_bignum_modp_4096_p);
}
/*-
@@ -308,105 +136,7 @@ BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *bn)
BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *bn)
{
- static const unsigned char RFC3526_PRIME_6144[] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
- 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
- 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
- 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
- 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
- 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
- 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
- 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
- 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
- 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
- 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
- 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
- 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
- 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
- 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
- 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
- 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
- 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
- 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
- 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
- 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
- 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
- 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
- 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
- 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
- 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
- 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
- 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
- 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
- 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
- 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
- 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
- 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
- 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
- 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
- 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
- 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
- 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
- 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
- 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
- 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
- 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
- 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
- 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
- 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
- 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
- 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
- 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
- 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
- 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
- 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
- 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
- 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
- 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
- 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
- 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
- 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
- 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
- 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
- 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
- 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
- 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
- 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26,
- 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE,
- 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
- 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E,
- 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE,
- 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
- 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18,
- 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED,
- 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
- 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B,
- 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42,
- 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
- 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC,
- 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03,
- 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
- 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82,
- 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E,
- 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
- 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE,
- 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5,
- 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
- 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8,
- 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0,
- 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
- 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76,
- 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0,
- 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
- 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32,
- 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68,
- 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
- 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6,
- 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xCC, 0x40, 0x24,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- };
- return BN_bin2bn(RFC3526_PRIME_6144, sizeof(RFC3526_PRIME_6144), bn);
+ return COPY_BN(bn, ossl_bignum_modp_6144_p);
}
/*-
@@ -419,135 +149,5 @@ BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *bn)
BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *bn)
{
- static const unsigned char RFC3526_PRIME_8192[] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
- 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
- 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
- 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
- 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
- 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
- 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
- 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
- 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
- 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
- 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
- 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
- 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
- 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
- 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
- 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
- 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
- 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
- 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
- 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
- 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
- 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
- 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
- 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
- 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
- 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
- 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
- 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
- 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
- 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
- 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
- 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
- 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
- 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
- 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
- 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
- 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
- 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
- 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
- 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
- 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
- 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
- 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
- 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
- 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
- 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
- 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
- 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
- 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
- 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
- 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
- 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
- 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
- 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
- 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
- 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
- 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
- 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
- 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
- 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
- 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
- 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
- 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26,
- 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE,
- 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
- 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E,
- 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE,
- 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
- 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18,
- 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED,
- 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
- 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B,
- 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42,
- 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
- 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC,
- 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03,
- 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
- 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82,
- 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E,
- 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
- 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE,
- 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5,
- 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
- 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8,
- 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0,
- 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
- 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76,
- 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0,
- 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
- 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32,
- 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68,
- 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
- 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6,
- 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59,
- 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4,
- 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C,
- 0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA,
- 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00,
- 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED,
- 0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66,
- 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68,
- 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78,
- 0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D,
- 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9,
- 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07,
- 0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7,
- 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B,
- 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD,
- 0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8,
- 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A,
- 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6,
- 0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D,
- 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36,
- 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1,
- 0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D,
- 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1,
- 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73,
- 0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68,
- 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92,
- 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7,
- 0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B,
- 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47,
- 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA,
- 0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF,
- 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71,
- 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- };
- return BN_bin2bn(RFC3526_PRIME_8192, sizeof(RFC3526_PRIME_8192), bn);
+ return COPY_BN(bn, ossl_bignum_modp_8192_p);
}
diff --git a/crypto/bn/bn_conv.c b/crypto/bn/bn_conv.c
new file mode 100644
index 000000000000..75054f5d6a6c
--- /dev/null
+++ b/crypto/bn/bn_conv.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include "crypto/ctype.h"
+#include "bn_local.h"
+
+static const char Hex[] = "0123456789ABCDEF";
+
+/* Must 'OPENSSL_free' the returned data */
+char *BN_bn2hex(const BIGNUM *a)
+{
+ int i, j, v, z = 0;
+ char *buf;
+ char *p;
+
+ if (BN_is_zero(a))
+ return OPENSSL_strdup("0");
+ buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2);
+ if (buf == NULL) {
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ p = buf;
+ if (a->neg)
+ *p++ = '-';
+ for (i = a->top - 1; i >= 0; i--) {
+ for (j = BN_BITS2 - 8; j >= 0; j -= 8) {
+ /* strip leading zeros */
+ v = (int)((a->d[i] >> j) & 0xff);
+ if (z || v != 0) {
+ *p++ = Hex[v >> 4];
+ *p++ = Hex[v & 0x0f];
+ z = 1;
+ }
+ }
+ }
+ *p = '\0';
+ err:
+ return buf;
+}
+
+#ifndef FIPS_MODULE
+/* No BIO_snprintf in FIPS_MODULE */
+/* Must 'OPENSSL_free' the returned data */
+char *BN_bn2dec(const BIGNUM *a)
+{
+ int i = 0, num, ok = 0, n, tbytes;
+ char *buf = NULL;
+ char *p;
+ BIGNUM *t = NULL;
+ BN_ULONG *bn_data = NULL, *lp;
+ int bn_data_num;
+
+ /*-
+ * get an upper bound for the length of the decimal integer
+ * num <= (BN_num_bits(a) + 1) * log(2)
+ * <= 3 * BN_num_bits(a) * 0.101 + log(2) + 1 (rounding error)
+ * <= 3 * BN_num_bits(a) / 10 + 3 * BN_num_bits / 1000 + 1 + 1
+ */
+ i = BN_num_bits(a) * 3;
+ num = (i / 10 + i / 1000 + 1) + 1;
+ tbytes = num + 3; /* negative and terminator and one spare? */
+ bn_data_num = num / BN_DEC_NUM + 1;
+ bn_data = OPENSSL_malloc(bn_data_num * sizeof(BN_ULONG));
+ buf = OPENSSL_malloc(tbytes);
+ if (buf == NULL || bn_data == NULL) {
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if ((t = BN_dup(a)) == NULL)
+ goto err;
+
+ p = buf;
+ lp = bn_data;
+ if (BN_is_zero(t)) {
+ *p++ = '0';
+ *p++ = '\0';
+ } else {
+ if (BN_is_negative(t))
+ *p++ = '-';
+
+ while (!BN_is_zero(t)) {
+ if (lp - bn_data >= bn_data_num)
+ goto err;
+ *lp = BN_div_word(t, BN_DEC_CONV);
+ if (*lp == (BN_ULONG)-1)
+ goto err;
+ lp++;
+ }
+ lp--;
+ /*
+ * We now have a series of blocks, BN_DEC_NUM chars in length, where
+ * the last one needs truncation. The blocks need to be reversed in
+ * order.
+ */
+ n = BIO_snprintf(p, tbytes - (size_t)(p - buf), BN_DEC_FMT1, *lp);
+ if (n < 0)
+ goto err;
+ p += n;
+ while (lp != bn_data) {
+ lp--;
+ n = BIO_snprintf(p, tbytes - (size_t)(p - buf), BN_DEC_FMT2, *lp);
+ if (n < 0)
+ goto err;
+ p += n;
+ }
+ }
+ ok = 1;
+ err:
+ OPENSSL_free(bn_data);
+ BN_free(t);
+ if (ok)
+ return buf;
+ OPENSSL_free(buf);
+ return NULL;
+}
+#endif
+
+int BN_hex2bn(BIGNUM **bn, const char *a)
+{
+ BIGNUM *ret = NULL;
+ BN_ULONG l = 0;
+ int neg = 0, h, m, i, j, k, c;
+ int num;
+
+ if (a == NULL || *a == '\0')
+ return 0;
+
+ if (*a == '-') {
+ neg = 1;
+ a++;
+ }
+
+ for (i = 0; i <= INT_MAX / 4 && ossl_isxdigit(a[i]); i++)
+ continue;
+
+ if (i == 0 || i > INT_MAX / 4)
+ return 0;
+
+ num = i + neg;
+ if (bn == NULL)
+ return num;
+
+ /* a is the start of the hex digits, and it is 'i' long */
+ if (*bn == NULL) {
+ if ((ret = BN_new()) == NULL)
+ return 0;
+ } else {
+ ret = *bn;
+ if (BN_get_flags(ret, BN_FLG_STATIC_DATA)) {
+ ERR_raise(ERR_LIB_BN, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ BN_zero(ret);
+ }
+
+ /* i is the number of hex digits */
+ if (bn_expand(ret, i * 4) == NULL)
+ goto err;
+
+ j = i; /* least significant 'hex' */
+ m = 0;
+ h = 0;
+ while (j > 0) {
+ m = (BN_BYTES * 2 <= j) ? BN_BYTES * 2 : j;
+ l = 0;
+ for (;;) {
+ c = a[j - m];
+ k = OPENSSL_hexchar2int(c);
+ if (k < 0)
+ k = 0; /* paranoia */
+ l = (l << 4) | k;
+
+ if (--m <= 0) {
+ ret->d[h++] = l;
+ break;
+ }
+ }
+ j -= BN_BYTES * 2;
+ }
+ ret->top = h;
+ bn_correct_top(ret);
+
+ *bn = ret;
+ bn_check_top(ret);
+ /* Don't set the negative flag if it's zero. */
+ if (ret->top != 0)
+ ret->neg = neg;
+ return num;
+ err:
+ if (*bn == NULL)
+ BN_free(ret);
+ return 0;
+}
+
+int BN_dec2bn(BIGNUM **bn, const char *a)
+{
+ BIGNUM *ret = NULL;
+ BN_ULONG l = 0;
+ int neg = 0, i, j;
+ int num;
+
+ if (a == NULL || *a == '\0')
+ return 0;
+ if (*a == '-') {
+ neg = 1;
+ a++;
+ }
+
+ for (i = 0; i <= INT_MAX / 4 && ossl_isdigit(a[i]); i++)
+ continue;
+
+ if (i == 0 || i > INT_MAX / 4)
+ goto err;
+
+ num = i + neg;
+ if (bn == NULL)
+ return num;
+
+ /*
+ * a is the start of the digits, and it is 'i' long. We chop it into
+ * BN_DEC_NUM digits at a time
+ */
+ if (*bn == NULL) {
+ if ((ret = BN_new()) == NULL)
+ return 0;
+ } else {
+ ret = *bn;
+ BN_zero(ret);
+ }
+
+ /* i is the number of digits, a bit of an over expand */
+ if (bn_expand(ret, i * 4) == NULL)
+ goto err;
+
+ j = BN_DEC_NUM - i % BN_DEC_NUM;
+ if (j == BN_DEC_NUM)
+ j = 0;
+ l = 0;
+ while (--i >= 0) {
+ l *= 10;
+ l += *a - '0';
+ a++;
+ if (++j == BN_DEC_NUM) {
+ if (!BN_mul_word(ret, BN_DEC_CONV)
+ || !BN_add_word(ret, l))
+ goto err;
+ l = 0;
+ j = 0;
+ }
+ }
+
+ bn_correct_top(ret);
+ *bn = ret;
+ bn_check_top(ret);
+ /* Don't set the negative flag if it's zero. */
+ if (ret->top != 0)
+ ret->neg = neg;
+ return num;
+ err:
+ if (*bn == NULL)
+ BN_free(ret);
+ return 0;
+}
+
+int BN_asc2bn(BIGNUM **bn, const char *a)
+{
+ const char *p = a;
+
+ if (*p == '-')
+ p++;
+
+ if (p[0] == '0' && (p[1] == 'X' || p[1] == 'x')) {
+ if (!BN_hex2bn(bn, p + 2))
+ return 0;
+ } else {
+ if (!BN_dec2bn(bn, p))
+ return 0;
+ }
+ /* Don't set the negative flag if it's zero. */
+ if (*a == '-' && (*bn)->top != 0)
+ (*bn)->neg = 1;
+ return 1;
+}
diff --git a/crypto/bn/bn_ctx.c b/crypto/bn/bn_ctx.c
index 042cb247d37f..35a7ddbab737 100644
--- a/crypto/bn/bn_ctx.c
+++ b/crypto/bn/bn_ctx.c
@@ -1,28 +1,16 @@
/*
- * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#include <openssl/trace.h>
#include "internal/cryptlib.h"
#include "bn_local.h"
-/*-
- * TODO list
- *
- * 1. Check a bunch of "(words+1)" type hacks in various bignum functions and
- * check they can be safely removed.
- * - Check +1 and other ugliness in BN_from_montgomery()
- *
- * 2. Consider allowing a BN_new_ex() that, at least, lets you specify an
- * appropriate 'block' size that will be honoured by bn_expand_internal() to
- * prevent piddly little reallocations. OTOH, profiling bignum expansions in
- * BN_CTX doesn't show this to be a big issue.
- */
-
/* How many bignums are in each "pool item"; */
#define BN_CTX_POOL_SIZE 16
/* The stack frame info is resizing, set a first-time expansion size; */
@@ -85,93 +73,105 @@ struct bignum_ctx {
int too_many;
/* Flags. */
int flags;
+ /* The library context */
+ OSSL_LIB_CTX *libctx;
};
-/* Enable this to find BN_CTX bugs */
-#ifdef BN_CTX_DEBUG
-static const char *ctxdbg_cur = NULL;
-static void ctxdbg(BN_CTX *ctx)
+#ifndef FIPS_MODULE
+/* Debugging functionality */
+static void ctxdbg(BIO *channel, const char *text, BN_CTX *ctx)
{
unsigned int bnidx = 0, fpidx = 0;
BN_POOL_ITEM *item = ctx->pool.head;
BN_STACK *stack = &ctx->stack;
- fprintf(stderr, "(%16p): ", ctx);
+
+ BIO_printf(channel, "%s\n", text);
+ BIO_printf(channel, " (%16p): ", (void*)ctx);
while (bnidx < ctx->used) {
- fprintf(stderr, "%03x ", item->vals[bnidx++ % BN_CTX_POOL_SIZE].dmax);
+ BIO_printf(channel, "%03x ",
+ item->vals[bnidx++ % BN_CTX_POOL_SIZE].dmax);
if (!(bnidx % BN_CTX_POOL_SIZE))
item = item->next;
}
- fprintf(stderr, "\n");
+ BIO_printf(channel, "\n");
bnidx = 0;
- fprintf(stderr, " : ");
+ BIO_printf(channel, " %16s : ", "");
while (fpidx < stack->depth) {
while (bnidx++ < stack->indexes[fpidx])
- fprintf(stderr, " ");
- fprintf(stderr, "^^^ ");
+ BIO_printf(channel, " ");
+ BIO_printf(channel, "^^^ ");
bnidx++;
fpidx++;
}
- fprintf(stderr, "\n");
+ BIO_printf(channel, "\n");
}
-# define CTXDBG_ENTRY(str, ctx) do { \
- ctxdbg_cur = (str); \
- fprintf(stderr,"Starting %s\n", ctxdbg_cur); \
- ctxdbg(ctx); \
- } while(0)
-# define CTXDBG_EXIT(ctx) do { \
- fprintf(stderr,"Ending %s\n", ctxdbg_cur); \
- ctxdbg(ctx); \
- } while(0)
-# define CTXDBG_RET(ctx,ret)
+# define CTXDBG(str, ctx) \
+ OSSL_TRACE_BEGIN(BN_CTX) { \
+ ctxdbg(trc_out, str, ctx); \
+ } OSSL_TRACE_END(BN_CTX)
#else
-# define CTXDBG_ENTRY(str, ctx)
-# define CTXDBG_EXIT(ctx)
-# define CTXDBG_RET(ctx,ret)
-#endif
-
+/* We do not want tracing in FIPS module */
+# define CTXDBG(str, ctx) do {} while(0)
+#endif /* FIPS_MODULE */
-BN_CTX *BN_CTX_new(void)
+BN_CTX *BN_CTX_new_ex(OSSL_LIB_CTX *ctx)
{
BN_CTX *ret;
if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
- BNerr(BN_F_BN_CTX_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return NULL;
}
/* Initialise the structure */
BN_POOL_init(&ret->pool);
BN_STACK_init(&ret->stack);
+ ret->libctx = ctx;
return ret;
}
-BN_CTX *BN_CTX_secure_new(void)
+#ifndef FIPS_MODULE
+BN_CTX *BN_CTX_new(void)
{
- BN_CTX *ret = BN_CTX_new();
+ return BN_CTX_new_ex(NULL);
+}
+#endif
+
+BN_CTX *BN_CTX_secure_new_ex(OSSL_LIB_CTX *ctx)
+{
+ BN_CTX *ret = BN_CTX_new_ex(ctx);
if (ret != NULL)
ret->flags = BN_FLG_SECURE;
return ret;
}
+#ifndef FIPS_MODULE
+BN_CTX *BN_CTX_secure_new(void)
+{
+ return BN_CTX_secure_new_ex(NULL);
+}
+#endif
+
void BN_CTX_free(BN_CTX *ctx)
{
if (ctx == NULL)
return;
-#ifdef BN_CTX_DEBUG
- {
+#ifndef FIPS_MODULE
+ OSSL_TRACE_BEGIN(BN_CTX) {
BN_POOL_ITEM *pool = ctx->pool.head;
- fprintf(stderr, "BN_CTX_free, stack-size=%d, pool-bignums=%d\n",
- ctx->stack.size, ctx->pool.size);
- fprintf(stderr, "dmaxs: ");
+ BIO_printf(trc_out,
+ "BN_CTX_free(): stack-size=%d, pool-bignums=%d\n",
+ ctx->stack.size, ctx->pool.size);
+ BIO_printf(trc_out, " dmaxs: ");
while (pool) {
unsigned loop = 0;
while (loop < BN_CTX_POOL_SIZE)
- fprintf(stderr, "%02x ", pool->vals[loop++].dmax);
+ BIO_printf(trc_out, "%02x ", pool->vals[loop++].dmax);
pool = pool->next;
}
- fprintf(stderr, "\n");
- }
+ BIO_printf(trc_out, "\n");
+ } OSSL_TRACE_END(BN_CTX);
#endif
BN_STACK_finish(&ctx->stack);
BN_POOL_finish(&ctx->pool);
@@ -180,23 +180,23 @@ void BN_CTX_free(BN_CTX *ctx)
void BN_CTX_start(BN_CTX *ctx)
{
- CTXDBG_ENTRY("BN_CTX_start", ctx);
+ CTXDBG("ENTER BN_CTX_start()", ctx);
/* If we're already overflowing ... */
if (ctx->err_stack || ctx->too_many)
ctx->err_stack++;
/* (Try to) get a new frame pointer */
else if (!BN_STACK_push(&ctx->stack, ctx->used)) {
- BNerr(BN_F_BN_CTX_START, BN_R_TOO_MANY_TEMPORARY_VARIABLES);
+ ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_TEMPORARY_VARIABLES);
ctx->err_stack++;
}
- CTXDBG_EXIT(ctx);
+ CTXDBG("LEAVE BN_CTX_start()", ctx);
}
void BN_CTX_end(BN_CTX *ctx)
{
if (ctx == NULL)
return;
- CTXDBG_ENTRY("BN_CTX_end", ctx);
+ CTXDBG("ENTER BN_CTX_end()", ctx);
if (ctx->err_stack)
ctx->err_stack--;
else {
@@ -208,14 +208,14 @@ void BN_CTX_end(BN_CTX *ctx)
/* Unjam "too_many" in case "get" had failed */
ctx->too_many = 0;
}
- CTXDBG_EXIT(ctx);
+ CTXDBG("LEAVE BN_CTX_end()", ctx);
}
BIGNUM *BN_CTX_get(BN_CTX *ctx)
{
BIGNUM *ret;
- CTXDBG_ENTRY("BN_CTX_get", ctx);
+ CTXDBG("ENTER BN_CTX_get()", ctx);
if (ctx->err_stack || ctx->too_many)
return NULL;
if ((ret = BN_POOL_get(&ctx->pool, ctx->flags)) == NULL) {
@@ -224,7 +224,7 @@ BIGNUM *BN_CTX_get(BN_CTX *ctx)
* the error stack.
*/
ctx->too_many = 1;
- BNerr(BN_F_BN_CTX_GET, BN_R_TOO_MANY_TEMPORARY_VARIABLES);
+ ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_TEMPORARY_VARIABLES);
return NULL;
}
/* OK, make sure the returned bignum is "zero" */
@@ -232,10 +232,17 @@ BIGNUM *BN_CTX_get(BN_CTX *ctx)
/* clear BN_FLG_CONSTTIME if leaked from previous frames */
ret->flags &= (~BN_FLG_CONSTTIME);
ctx->used++;
- CTXDBG_RET(ctx, ret);
+ CTXDBG("LEAVE BN_CTX_get()", ctx);
return ret;
}
+OSSL_LIB_CTX *ossl_bn_get_libctx(BN_CTX *ctx)
+{
+ if (ctx == NULL)
+ return NULL;
+ return ctx->libctx;
+}
+
/************/
/* BN_STACK */
/************/
@@ -262,7 +269,7 @@ static int BN_STACK_push(BN_STACK *st, unsigned int idx)
unsigned int *newitems;
if ((newitems = OPENSSL_malloc(sizeof(*newitems) * newsize)) == NULL) {
- BNerr(BN_F_BN_STACK_PUSH, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return 0;
}
if (st->depth)
@@ -316,7 +323,7 @@ static BIGNUM *BN_POOL_get(BN_POOL *p, int flag)
BN_POOL_ITEM *item;
if ((item = OPENSSL_malloc(sizeof(*item))) == NULL) {
- BNerr(BN_F_BN_POOL_GET, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return NULL;
}
for (loop = 0, bn = item->vals; loop++ < BN_CTX_POOL_SIZE; bn++) {
diff --git a/crypto/bn/bn_depr.c b/crypto/bn/bn_depr.c
index b60269cd57a6..d55397016a51 100644
--- a/crypto/bn/bn_depr.c
+++ b/crypto/bn/bn_depr.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,14 +13,11 @@
*/
#include <openssl/opensslconf.h>
-#if OPENSSL_API_COMPAT >= 0x00908000L
-NON_EMPTY_TRANSLATION_UNIT
-#else
-# include <stdio.h>
-# include <time.h>
-# include "internal/cryptlib.h"
-# include "bn_local.h"
+#include <stdio.h>
+#include <time.h>
+#include "internal/cryptlib.h"
+#include "bn_local.h"
BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe,
const BIGNUM *add, const BIGNUM *rem,
@@ -52,7 +49,7 @@ int BN_is_prime(const BIGNUM *a, int checks,
{
BN_GENCB cb;
BN_GENCB_set_old(&cb, callback, cb_arg);
- return BN_is_prime_ex(a, checks, ctx_passed, &cb);
+ return ossl_bn_check_prime(a, checks, ctx_passed, 0, &cb);
}
int BN_is_prime_fasttest(const BIGNUM *a, int checks,
@@ -62,7 +59,5 @@ int BN_is_prime_fasttest(const BIGNUM *a, int checks,
{
BN_GENCB cb;
BN_GENCB_set_old(&cb, callback, cb_arg);
- return BN_is_prime_fasttest_ex(a, checks, ctx_passed,
- do_trial_division, &cb);
+ return ossl_bn_check_prime(a, checks, ctx_passed, do_trial_division, &cb);
}
-#endif
diff --git a/crypto/bn/bn_dh.c b/crypto/bn/bn_dh.c
index 58c44f0b179e..c0967e534c8c 100644
--- a/crypto/bn/bn_dh.c
+++ b/crypto/bn/bn_dh.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,503 +10,1045 @@
#include "bn_local.h"
#include "internal/nelem.h"
-#ifndef OPENSSL_NO_DH
-#include <openssl/dh.h>
-#include "crypto/bn_dh.h"
-/* DH parameters from RFC5114 */
+# include <openssl/dh.h>
+# include "crypto/bn_dh.h"
# if BN_BITS2 == 64
-static const BN_ULONG dh1024_160_p[] = {
- 0xDF1FB2BC2E4A4371ULL, 0xE68CFDA76D4DA708ULL, 0x45BF37DF365C1A65ULL,
- 0xA151AF5F0DC8B4BDULL, 0xFAA31A4FF55BCCC0ULL, 0x4EFFD6FAE5644738ULL,
- 0x98488E9C219A7372ULL, 0xACCBDD7D90C4BD70ULL, 0x24975C3CD49B83BFULL,
- 0x13ECB4AEA9061123ULL, 0x9838EF1E2EE652C0ULL, 0x6073E28675A23D18ULL,
- 0x9A6A9DCA52D23B61ULL, 0x52C99FBCFB06A3C6ULL, 0xDE92DE5EAE5D54ECULL,
- 0xB10B8F96A080E01DULL
-};
+# define BN_DEF(lo, hi) (BN_ULONG)hi << 32 | lo
+# else
+# define BN_DEF(lo, hi) lo, hi
+# endif
-static const BN_ULONG dh1024_160_g[] = {
- 0x855E6EEB22B3B2E5ULL, 0x858F4DCEF97C2A24ULL, 0x2D779D5918D08BC8ULL,
- 0xD662A4D18E73AFA3ULL, 0x1DBF0A0169B6A28AULL, 0xA6A24C087A091F53ULL,
- 0x909D0D2263F80A76ULL, 0xD7FBD7D3B9A92EE1ULL, 0x5E91547F9E2749F4ULL,
- 0x160217B4B01B886AULL, 0x777E690F5504F213ULL, 0x266FEA1E5C41564BULL,
- 0xD6406CFF14266D31ULL, 0xF8104DD258AC507FULL, 0x6765A442EFB99905ULL,
- 0xA4D1CBD5C3FD3412ULL
-};
+/* DH parameters from RFC3526 */
-static const BN_ULONG dh1024_160_q[] = {
- 0x64B7CB9D49462353ULL, 0x81A8DF278ABA4E7DULL, 0x00000000F518AA87ULL
+# ifndef FIPS_MODULE
+/*
+ * "1536-bit MODP Group" from RFC3526, Section 2.
+ *
+ * The prime is: 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 }
+ *
+ * RFC3526 specifies a generator of 2.
+ * RFC2412 specifies a generator of 22.
+ */
+static const BN_ULONG modp_1536_p[] = {
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0xCA237327, 0xF1746C08),
+ BN_DEF(0x4ABC9804, 0x670C354E), BN_DEF(0x7096966D, 0x9ED52907),
+ BN_DEF(0x208552BB, 0x1C62F356), BN_DEF(0xDCA3AD96, 0x83655D23),
+ BN_DEF(0xFD24CF5F, 0x69163FA8), BN_DEF(0x1C55D39A, 0x98DA4836),
+ BN_DEF(0xA163BF05, 0xC2007CB8), BN_DEF(0xECE45B3D, 0x49286651),
+ BN_DEF(0x7C4B1FE6, 0xAE9F2411), BN_DEF(0x5A899FA5, 0xEE386BFB),
+ BN_DEF(0xF406B7ED, 0x0BFF5CB6), BN_DEF(0xA637ED6B, 0xF44C42E9),
+ BN_DEF(0x625E7EC6, 0xE485B576), BN_DEF(0x6D51C245, 0x4FE1356D),
+ BN_DEF(0xF25F1437, 0x302B0A6D), BN_DEF(0xCD3A431B, 0xEF9519B3),
+ BN_DEF(0x8E3404DD, 0x514A0879), BN_DEF(0x3B139B22, 0x020BBEA6),
+ BN_DEF(0x8A67CC74, 0x29024E08), BN_DEF(0x80DC1CD1, 0xC4C6628B),
+ BN_DEF(0x2168C234, 0xC90FDAA2), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF)
};
-
-static const BN_ULONG dh2048_224_p[] = {
- 0x0AC4DFFE0C10E64FULL, 0xCF9DE5384E71B81CULL, 0x7EF363E2FFA31F71ULL,
- 0xE3FB73C16B8E75B9ULL, 0xC9B53DCF4BA80A29ULL, 0x23F10B0E16E79763ULL,
- 0xC52172E413042E9BULL, 0xBE60E69CC928B2B9ULL, 0x80CD86A1B9E587E8ULL,
- 0x315D75E198C641A4ULL, 0xCDF93ACC44328387ULL, 0x15987D9ADC0A486DULL,
- 0x7310F7121FD5A074ULL, 0x278273C7DE31EFDCULL, 0x1602E714415D9330ULL,
- 0x81286130BC8985DBULL, 0xB3BF8A3170918836ULL, 0x6A00E0A0B9C49708ULL,
- 0xC6BA0B2C8BBC27BEULL, 0xC9F98D11ED34DBF6ULL, 0x7AD5B7D0B6C12207ULL,
- 0xD91E8FEF55B7394BULL, 0x9037C9EDEFDA4DF8ULL, 0x6D3F8152AD6AC212ULL,
- 0x1DE6B85A1274A0A6ULL, 0xEB3D688A309C180EULL, 0xAF9A3C407BA1DF15ULL,
- 0xE6FA141DF95A56DBULL, 0xB54B1597B61D0A75ULL, 0xA20D64E5683B9FD1ULL,
- 0xD660FAA79559C51FULL, 0xAD107E1E9123A9D0ULL
+/* q = (p - 1) / 2 */
+static const BN_ULONG modp_1536_q[] = {
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x6511B993, 0x78BA3604),
+ BN_DEF(0x255E4C02, 0xB3861AA7), BN_DEF(0xB84B4B36, 0xCF6A9483),
+ BN_DEF(0x1042A95D, 0x0E3179AB), BN_DEF(0xEE51D6CB, 0xC1B2AE91),
+ BN_DEF(0x7E9267AF, 0x348B1FD4), BN_DEF(0x0E2AE9CD, 0xCC6D241B),
+ BN_DEF(0x50B1DF82, 0xE1003E5C), BN_DEF(0xF6722D9E, 0x24943328),
+ BN_DEF(0xBE258FF3, 0xD74F9208), BN_DEF(0xAD44CFD2, 0xF71C35FD),
+ BN_DEF(0x7A035BF6, 0x85FFAE5B), BN_DEF(0xD31BF6B5, 0x7A262174),
+ BN_DEF(0x312F3F63, 0xF242DABB), BN_DEF(0xB6A8E122, 0xA7F09AB6),
+ BN_DEF(0xF92F8A1B, 0x98158536), BN_DEF(0xE69D218D, 0xF7CA8CD9),
+ BN_DEF(0xC71A026E, 0x28A5043C), BN_DEF(0x1D89CD91, 0x0105DF53),
+ BN_DEF(0x4533E63A, 0x94812704), BN_DEF(0xC06E0E68, 0x62633145),
+ BN_DEF(0x10B4611A, 0xE487ED51), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF)
};
+# endif /* FIPS_MODULE */
-static const BN_ULONG dh2048_224_g[] = {
- 0x84B890D3191F2BFAULL, 0x81BC087F2A7065B3ULL, 0x19C418E1F6EC0179ULL,
- 0x7B5A0F1C71CFFF4CULL, 0xEDFE72FE9B6AA4BDULL, 0x81E1BCFE94B30269ULL,
- 0x566AFBB48D6C0191ULL, 0xB539CCE3409D13CDULL, 0x6AA21E7F5F2FF381ULL,
- 0xD9E263E4770589EFULL, 0x10E183EDD19963DDULL, 0xB70A8137150B8EEBULL,
- 0x051AE3D428C8F8ACULL, 0xBB77A86F0C1AB15BULL, 0x6E3025E316A330EFULL,
- 0x19529A45D6F83456ULL, 0xF180EB34118E98D1ULL, 0xB5F6C6B250717CBEULL,
- 0x09939D54DA7460CDULL, 0xE247150422EA1ED4ULL, 0xB8A762D0521BC98AULL,
- 0xF4D027275AC1348BULL, 0xC17669101999024AULL, 0xBE5E9001A8D66AD7ULL,
- 0xC57DB17C620A8652ULL, 0xAB739D7700C29F52ULL, 0xDD921F01A70C4AFAULL,
- 0xA6824A4E10B9A6F0ULL, 0x74866A08CFE4FFE3ULL, 0x6CDEBE7B89998CAFULL,
- 0x9DF30B5C8FFDAC50ULL, 0xAC4032EF4F2D9AE3ULL
+/*-
+ * "2048-bit MODP Group" from RFC3526, Section 3.
+ *
+ * The prime is: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }
+ *
+ * RFC3526 specifies a generator of 2.
+ */
+static const BN_ULONG modp_2048_p[] = {
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x8AACAA68, 0x15728E5A),
+ BN_DEF(0x98FA0510, 0x15D22618), BN_DEF(0xEA956AE5, 0x3995497C),
+ BN_DEF(0x95581718, 0xDE2BCBF6), BN_DEF(0x6F4C52C9, 0xB5C55DF0),
+ BN_DEF(0xEC07A28F, 0x9B2783A2), BN_DEF(0x180E8603, 0xE39E772C),
+ BN_DEF(0x2E36CE3B, 0x32905E46), BN_DEF(0xCA18217C, 0xF1746C08),
+ BN_DEF(0x4ABC9804, 0x670C354E), BN_DEF(0x7096966D, 0x9ED52907),
+ BN_DEF(0x208552BB, 0x1C62F356), BN_DEF(0xDCA3AD96, 0x83655D23),
+ BN_DEF(0xFD24CF5F, 0x69163FA8), BN_DEF(0x1C55D39A, 0x98DA4836),
+ BN_DEF(0xA163BF05, 0xC2007CB8), BN_DEF(0xECE45B3D, 0x49286651),
+ BN_DEF(0x7C4B1FE6, 0xAE9F2411), BN_DEF(0x5A899FA5, 0xEE386BFB),
+ BN_DEF(0xF406B7ED, 0x0BFF5CB6), BN_DEF(0xA637ED6B, 0xF44C42E9),
+ BN_DEF(0x625E7EC6, 0xE485B576), BN_DEF(0x6D51C245, 0x4FE1356D),
+ BN_DEF(0xF25F1437, 0x302B0A6D), BN_DEF(0xCD3A431B, 0xEF9519B3),
+ BN_DEF(0x8E3404DD, 0x514A0879), BN_DEF(0x3B139B22, 0x020BBEA6),
+ BN_DEF(0x8A67CC74, 0x29024E08), BN_DEF(0x80DC1CD1, 0xC4C6628B),
+ BN_DEF(0x2168C234, 0xC90FDAA2), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF)
};
-
-static const BN_ULONG dh2048_224_q[] = {
- 0xBF389A99B36371EBULL, 0x1F80535A4738CEBCULL, 0xC58D93FE99717710ULL,
- 0x00000000801C0D34ULL
+/* q = (p - 1) / 2 */
+static const BN_ULONG modp_2048_q[] = {
+ BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), BN_DEF(0x45565534, 0x0AB9472D),
+ BN_DEF(0x4C7D0288, 0x8AE9130C), BN_DEF(0x754AB572, 0x1CCAA4BE),
+ BN_DEF(0x4AAC0B8C, 0xEF15E5FB), BN_DEF(0x37A62964, 0xDAE2AEF8),
+ BN_DEF(0x7603D147, 0xCD93C1D1), BN_DEF(0x0C074301, 0xF1CF3B96),
+ BN_DEF(0x171B671D, 0x19482F23), BN_DEF(0x650C10BE, 0x78BA3604),
+ BN_DEF(0x255E4C02, 0xB3861AA7), BN_DEF(0xB84B4B36, 0xCF6A9483),
+ BN_DEF(0x1042A95D, 0x0E3179AB), BN_DEF(0xEE51D6CB, 0xC1B2AE91),
+ BN_DEF(0x7E9267AF, 0x348B1FD4), BN_DEF(0x0E2AE9CD, 0xCC6D241B),
+ BN_DEF(0x50B1DF82, 0xE1003E5C), BN_DEF(0xF6722D9E, 0x24943328),
+ BN_DEF(0xBE258FF3, 0xD74F9208), BN_DEF(0xAD44CFD2, 0xF71C35FD),
+ BN_DEF(0x7A035BF6, 0x85FFAE5B), BN_DEF(0xD31BF6B5, 0x7A262174),
+ BN_DEF(0x312F3F63, 0xF242DABB), BN_DEF(0xB6A8E122, 0xA7F09AB6),
+ BN_DEF(0xF92F8A1B, 0x98158536), BN_DEF(0xE69D218D, 0xF7CA8CD9),
+ BN_DEF(0xC71A026E, 0x28A5043C), BN_DEF(0x1D89CD91, 0x0105DF53),
+ BN_DEF(0x4533E63A, 0x94812704), BN_DEF(0xC06E0E68, 0x62633145),
+ BN_DEF(0x10B4611A, 0xE487ED51), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF),
};
-static const BN_ULONG dh2048_256_p[] = {
- 0xDB094AE91E1A1597ULL, 0x693877FAD7EF09CAULL, 0x6116D2276E11715FULL,
- 0xA4B54330C198AF12ULL, 0x75F26375D7014103ULL, 0xC3A3960A54E710C3ULL,
- 0xDED4010ABD0BE621ULL, 0xC0B857F689962856ULL, 0xB3CA3F7971506026ULL,
- 0x1CCACB83E6B486F6ULL, 0x67E144E514056425ULL, 0xF6A167B5A41825D9ULL,
- 0x3AD8347796524D8EULL, 0xF13C6D9A51BFA4ABULL, 0x2D52526735488A0EULL,
- 0xB63ACAE1CAA6B790ULL, 0x4FDB70C581B23F76ULL, 0xBC39A0BF12307F5CULL,
- 0xB941F54EB1E59BB8ULL, 0x6C5BFC11D45F9088ULL, 0x22E0B1EF4275BF7BULL,
- 0x91F9E6725B4758C0ULL, 0x5A8A9D306BCF67EDULL, 0x209E0C6497517ABDULL,
- 0x3BF4296D830E9A7CULL, 0x16C3D91134096FAAULL, 0xFAF7DF4561B2AA30ULL,
- 0xE00DF8F1D61957D4ULL, 0x5D2CEED4435E3B00ULL, 0x8CEEF608660DD0F2ULL,
- 0xFFBBD19C65195999ULL, 0x87A8E61DB4B6663CULL
+/*-
+ * "3072-bit MODP Group" from RFC3526, Section 4.
+ *
+ * The prime is: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 }
+ *
+ * RFC3526 specifies a generator of 2.
+ */
+static const BN_ULONG modp_3072_p[] = {
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0xA93AD2CA, 0x4B82D120),
+ BN_DEF(0xE0FD108E, 0x43DB5BFC), BN_DEF(0x74E5AB31, 0x08E24FA0),
+ BN_DEF(0xBAD946E2, 0x770988C0), BN_DEF(0x7A615D6C, 0xBBE11757),
+ BN_DEF(0x177B200C, 0x521F2B18), BN_DEF(0x3EC86A64, 0xD8760273),
+ BN_DEF(0xD98A0864, 0xF12FFA06), BN_DEF(0x1AD2EE6B, 0xCEE3D226),
+ BN_DEF(0x4A25619D, 0x1E8C94E0), BN_DEF(0xDB0933D7, 0xABF5AE8C),
+ BN_DEF(0xA6E1E4C7, 0xB3970F85), BN_DEF(0x5D060C7D, 0x8AEA7157),
+ BN_DEF(0x58DBEF0A, 0xECFB8504), BN_DEF(0xDF1CBA64, 0xA85521AB),
+ BN_DEF(0x04507A33, 0xAD33170D), BN_DEF(0x8AAAC42D, 0x15728E5A),
+ BN_DEF(0x98FA0510, 0x15D22618), BN_DEF(0xEA956AE5, 0x3995497C),
+ BN_DEF(0x95581718, 0xDE2BCBF6), BN_DEF(0x6F4C52C9, 0xB5C55DF0),
+ BN_DEF(0xEC07A28F, 0x9B2783A2), BN_DEF(0x180E8603, 0xE39E772C),
+ BN_DEF(0x2E36CE3B, 0x32905E46), BN_DEF(0xCA18217C, 0xF1746C08),
+ BN_DEF(0x4ABC9804, 0x670C354E), BN_DEF(0x7096966D, 0x9ED52907),
+ BN_DEF(0x208552BB, 0x1C62F356), BN_DEF(0xDCA3AD96, 0x83655D23),
+ BN_DEF(0xFD24CF5F, 0x69163FA8), BN_DEF(0x1C55D39A, 0x98DA4836),
+ BN_DEF(0xA163BF05, 0xC2007CB8), BN_DEF(0xECE45B3D, 0x49286651),
+ BN_DEF(0x7C4B1FE6, 0xAE9F2411), BN_DEF(0x5A899FA5, 0xEE386BFB),
+ BN_DEF(0xF406B7ED, 0x0BFF5CB6), BN_DEF(0xA637ED6B, 0xF44C42E9),
+ BN_DEF(0x625E7EC6, 0xE485B576), BN_DEF(0x6D51C245, 0x4FE1356D),
+ BN_DEF(0xF25F1437, 0x302B0A6D), BN_DEF(0xCD3A431B, 0xEF9519B3),
+ BN_DEF(0x8E3404DD, 0x514A0879), BN_DEF(0x3B139B22, 0x020BBEA6),
+ BN_DEF(0x8A67CC74, 0x29024E08), BN_DEF(0x80DC1CD1, 0xC4C6628B),
+ BN_DEF(0x2168C234, 0xC90FDAA2), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF)
};
-
-static const BN_ULONG dh2048_256_g[] = {
- 0x664B4C0F6CC41659ULL, 0x5E2327CFEF98C582ULL, 0xD647D148D4795451ULL,
- 0x2F63078490F00EF8ULL, 0x184B523D1DB246C3ULL, 0xC7891428CDC67EB6ULL,
- 0x7FD028370DF92B52ULL, 0xB3353BBB64E0EC37ULL, 0xECD06E1557CD0915ULL,
- 0xB7D2BBD2DF016199ULL, 0xC8484B1E052588B9ULL, 0xDB2A3B7313D3FE14ULL,
- 0xD052B985D182EA0AULL, 0xA4BD1BFFE83B9C80ULL, 0xDFC967C1FB3F2E55ULL,
- 0xB5045AF2767164E1ULL, 0x1D14348F6F2F9193ULL, 0x64E67982428EBC83ULL,
- 0x8AC376D282D6ED38ULL, 0x777DE62AAAB8A862ULL, 0xDDF463E5E9EC144BULL,
- 0x0196F931C77A57F2ULL, 0xA55AE31341000A65ULL, 0x901228F8C28CBB18ULL,
- 0xBC3773BF7E8C6F62ULL, 0xBE3A6C1B0C6B47B1ULL, 0xFF4FED4AAC0BB555ULL,
- 0x10DBC15077BE463FULL, 0x07F4793A1A0BA125ULL, 0x4CA7B18F21EF2054ULL,
- 0x2E77506660EDBD48ULL, 0x3FB32C9B73134D0BULL
+/* q = (p - 1) / 2 */
+static const BN_ULONG modp_3072_q[] = {
+ BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), BN_DEF(0x549D6965, 0x25C16890),
+ BN_DEF(0x707E8847, 0xA1EDADFE), BN_DEF(0x3A72D598, 0x047127D0),
+ BN_DEF(0x5D6CA371, 0x3B84C460), BN_DEF(0xBD30AEB6, 0x5DF08BAB),
+ BN_DEF(0x0BBD9006, 0x290F958C), BN_DEF(0x9F643532, 0x6C3B0139),
+ BN_DEF(0x6CC50432, 0xF897FD03), BN_DEF(0x0D697735, 0xE771E913),
+ BN_DEF(0x2512B0CE, 0x8F464A70), BN_DEF(0x6D8499EB, 0xD5FAD746),
+ BN_DEF(0xD370F263, 0xD9CB87C2), BN_DEF(0xAE83063E, 0x457538AB),
+ BN_DEF(0x2C6DF785, 0x767DC282), BN_DEF(0xEF8E5D32, 0xD42A90D5),
+ BN_DEF(0x82283D19, 0xD6998B86), BN_DEF(0x45556216, 0x0AB9472D),
+ BN_DEF(0x4C7D0288, 0x8AE9130C), BN_DEF(0x754AB572, 0x1CCAA4BE),
+ BN_DEF(0x4AAC0B8C, 0xEF15E5FB), BN_DEF(0x37A62964, 0xDAE2AEF8),
+ BN_DEF(0x7603D147, 0xCD93C1D1), BN_DEF(0x0C074301, 0xF1CF3B96),
+ BN_DEF(0x171B671D, 0x19482F23), BN_DEF(0x650C10BE, 0x78BA3604),
+ BN_DEF(0x255E4C02, 0xB3861AA7), BN_DEF(0xB84B4B36, 0xCF6A9483),
+ BN_DEF(0x1042A95D, 0x0E3179AB), BN_DEF(0xEE51D6CB, 0xC1B2AE91),
+ BN_DEF(0x7E9267AF, 0x348B1FD4), BN_DEF(0x0E2AE9CD, 0xCC6D241B),
+ BN_DEF(0x50B1DF82, 0xE1003E5C), BN_DEF(0xF6722D9E, 0x24943328),
+ BN_DEF(0xBE258FF3, 0xD74F9208), BN_DEF(0xAD44CFD2, 0xF71C35FD),
+ BN_DEF(0x7A035BF6, 0x85FFAE5B), BN_DEF(0xD31BF6B5, 0x7A262174),
+ BN_DEF(0x312F3F63, 0xF242DABB), BN_DEF(0xB6A8E122, 0xA7F09AB6),
+ BN_DEF(0xF92F8A1B, 0x98158536), BN_DEF(0xE69D218D, 0xF7CA8CD9),
+ BN_DEF(0xC71A026E, 0x28A5043C), BN_DEF(0x1D89CD91, 0x0105DF53),
+ BN_DEF(0x4533E63A, 0x94812704), BN_DEF(0xC06E0E68, 0x62633145),
+ BN_DEF(0x10B4611A, 0xE487ED51), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF),
};
-static const BN_ULONG dh2048_256_q[] = {
- 0xA308B0FE64F5FBD3ULL, 0x99B1A47D1EB3750BULL, 0xB447997640129DA2ULL,
- 0x8CF83642A709A097ULL
+/*-
+ * "4096-bit MODP Group" from RFC3526, Section 5.
+ *
+ * The prime is: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 }
+ *
+ * RFC3526 specifies a generator of 2.
+ */
+static const BN_ULONG modp_4096_p[] = {
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x34063199, 0x4DF435C9),
+ BN_DEF(0x90A6C08F, 0x86FFB7DC), BN_DEF(0x8D8FDDC1, 0x93B4EA98),
+ BN_DEF(0xD5B05AA9, 0xD0069127), BN_DEF(0x2170481C, 0xB81BDD76),
+ BN_DEF(0xCEE2D7AF, 0x1F612970), BN_DEF(0x515BE7ED, 0x233BA186),
+ BN_DEF(0xA090C3A2, 0x99B2964F), BN_DEF(0x4E6BC05D, 0x287C5947),
+ BN_DEF(0x1FBECAA6, 0x2E8EFC14), BN_DEF(0x04DE8EF9, 0xDBBBC2DB),
+ BN_DEF(0x2AD44CE8, 0x2583E9CA), BN_DEF(0xB6150BDA, 0x1A946834),
+ BN_DEF(0x6AF4E23C, 0x99C32718), BN_DEF(0xBDBA5B26, 0x88719A10),
+ BN_DEF(0xA787E6D7, 0x1A723C12), BN_DEF(0xA9210801, 0x4B82D120),
+ BN_DEF(0xE0FD108E, 0x43DB5BFC), BN_DEF(0x74E5AB31, 0x08E24FA0),
+ BN_DEF(0xBAD946E2, 0x770988C0), BN_DEF(0x7A615D6C, 0xBBE11757),
+ BN_DEF(0x177B200C, 0x521F2B18), BN_DEF(0x3EC86A64, 0xD8760273),
+ BN_DEF(0xD98A0864, 0xF12FFA06), BN_DEF(0x1AD2EE6B, 0xCEE3D226),
+ BN_DEF(0x4A25619D, 0x1E8C94E0), BN_DEF(0xDB0933D7, 0xABF5AE8C),
+ BN_DEF(0xA6E1E4C7, 0xB3970F85), BN_DEF(0x5D060C7D, 0x8AEA7157),
+ BN_DEF(0x58DBEF0A, 0xECFB8504), BN_DEF(0xDF1CBA64, 0xA85521AB),
+ BN_DEF(0x04507A33, 0xAD33170D), BN_DEF(0x8AAAC42D, 0x15728E5A),
+ BN_DEF(0x98FA0510, 0x15D22618), BN_DEF(0xEA956AE5, 0x3995497C),
+ BN_DEF(0x95581718, 0xDE2BCBF6), BN_DEF(0x6F4C52C9, 0xB5C55DF0),
+ BN_DEF(0xEC07A28F, 0x9B2783A2), BN_DEF(0x180E8603, 0xE39E772C),
+ BN_DEF(0x2E36CE3B, 0x32905E46), BN_DEF(0xCA18217C, 0xF1746C08),
+ BN_DEF(0x4ABC9804, 0x670C354E), BN_DEF(0x7096966D, 0x9ED52907),
+ BN_DEF(0x208552BB, 0x1C62F356), BN_DEF(0xDCA3AD96, 0x83655D23),
+ BN_DEF(0xFD24CF5F, 0x69163FA8), BN_DEF(0x1C55D39A, 0x98DA4836),
+ BN_DEF(0xA163BF05, 0xC2007CB8), BN_DEF(0xECE45B3D, 0x49286651),
+ BN_DEF(0x7C4B1FE6, 0xAE9F2411), BN_DEF(0x5A899FA5, 0xEE386BFB),
+ BN_DEF(0xF406B7ED, 0x0BFF5CB6), BN_DEF(0xA637ED6B, 0xF44C42E9),
+ BN_DEF(0x625E7EC6, 0xE485B576), BN_DEF(0x6D51C245, 0x4FE1356D),
+ BN_DEF(0xF25F1437, 0x302B0A6D), BN_DEF(0xCD3A431B, 0xEF9519B3),
+ BN_DEF(0x8E3404DD, 0x514A0879), BN_DEF(0x3B139B22, 0x020BBEA6),
+ BN_DEF(0x8A67CC74, 0x29024E08), BN_DEF(0x80DC1CD1, 0xC4C6628B),
+ BN_DEF(0x2168C234, 0xC90FDAA2), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF)
};
-
-/* Primes from RFC 7919 */
-static const BN_ULONG ffdhe2048_p[] = {
- 0xFFFFFFFFFFFFFFFFULL, 0x886B423861285C97ULL, 0xC6F34A26C1B2EFFAULL,
- 0xC58EF1837D1683B2ULL, 0x3BB5FCBC2EC22005ULL, 0xC3FE3B1B4C6FAD73ULL,
- 0x8E4F1232EEF28183ULL, 0x9172FE9CE98583FFULL, 0xC03404CD28342F61ULL,
- 0x9E02FCE1CDF7E2ECULL, 0x0B07A7C8EE0A6D70ULL, 0xAE56EDE76372BB19ULL,
- 0x1D4F42A3DE394DF4ULL, 0xB96ADAB760D7F468ULL, 0xD108A94BB2C8E3FBULL,
- 0xBC0AB182B324FB61ULL, 0x30ACCA4F483A797AULL, 0x1DF158A136ADE735ULL,
- 0xE2A689DAF3EFE872ULL, 0x984F0C70E0E68B77ULL, 0xB557135E7F57C935ULL,
- 0x856365553DED1AF3ULL, 0x2433F51F5F066ED0ULL, 0xD3DF1ED5D5FD6561ULL,
- 0xF681B202AEC4617AULL, 0x7D2FE363630C75D8ULL, 0xCC939DCE249B3EF9ULL,
- 0xA9E13641146433FBULL, 0xD8B9C583CE2D3695ULL, 0xAFDC5620273D3CF1ULL,
- 0xADF85458A2BB4A9AULL, 0xFFFFFFFFFFFFFFFFULL
+/* q = (p - 1) / 2 */
+static const BN_ULONG modp_4096_q[] = {
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x9A0318CC, 0xA6FA1AE4),
+ BN_DEF(0x48536047, 0xC37FDBEE), BN_DEF(0x46C7EEE0, 0xC9DA754C),
+ BN_DEF(0xEAD82D54, 0x68034893), BN_DEF(0x10B8240E, 0xDC0DEEBB),
+ BN_DEF(0x67716BD7, 0x8FB094B8), BN_DEF(0x28ADF3F6, 0x119DD0C3),
+ BN_DEF(0xD04861D1, 0xCCD94B27), BN_DEF(0xA735E02E, 0x143E2CA3),
+ BN_DEF(0x0FDF6553, 0x97477E0A), BN_DEF(0x826F477C, 0x6DDDE16D),
+ BN_DEF(0x156A2674, 0x12C1F4E5), BN_DEF(0x5B0A85ED, 0x0D4A341A),
+ BN_DEF(0x357A711E, 0x4CE1938C), BN_DEF(0x5EDD2D93, 0xC438CD08),
+ BN_DEF(0x53C3F36B, 0x8D391E09), BN_DEF(0x54908400, 0x25C16890),
+ BN_DEF(0x707E8847, 0xA1EDADFE), BN_DEF(0x3A72D598, 0x047127D0),
+ BN_DEF(0x5D6CA371, 0x3B84C460), BN_DEF(0xBD30AEB6, 0x5DF08BAB),
+ BN_DEF(0x0BBD9006, 0x290F958C), BN_DEF(0x9F643532, 0x6C3B0139),
+ BN_DEF(0x6CC50432, 0xF897FD03), BN_DEF(0x0D697735, 0xE771E913),
+ BN_DEF(0x2512B0CE, 0x8F464A70), BN_DEF(0x6D8499EB, 0xD5FAD746),
+ BN_DEF(0xD370F263, 0xD9CB87C2), BN_DEF(0xAE83063E, 0x457538AB),
+ BN_DEF(0x2C6DF785, 0x767DC282), BN_DEF(0xEF8E5D32, 0xD42A90D5),
+ BN_DEF(0x82283D19, 0xD6998B86), BN_DEF(0x45556216, 0x0AB9472D),
+ BN_DEF(0x4C7D0288, 0x8AE9130C), BN_DEF(0x754AB572, 0x1CCAA4BE),
+ BN_DEF(0x4AAC0B8C, 0xEF15E5FB), BN_DEF(0x37A62964, 0xDAE2AEF8),
+ BN_DEF(0x7603D147, 0xCD93C1D1), BN_DEF(0x0C074301, 0xF1CF3B96),
+ BN_DEF(0x171B671D, 0x19482F23), BN_DEF(0x650C10BE, 0x78BA3604),
+ BN_DEF(0x255E4C02, 0xB3861AA7), BN_DEF(0xB84B4B36, 0xCF6A9483),
+ BN_DEF(0x1042A95D, 0x0E3179AB), BN_DEF(0xEE51D6CB, 0xC1B2AE91),
+ BN_DEF(0x7E9267AF, 0x348B1FD4), BN_DEF(0x0E2AE9CD, 0xCC6D241B),
+ BN_DEF(0x50B1DF82, 0xE1003E5C), BN_DEF(0xF6722D9E, 0x24943328),
+ BN_DEF(0xBE258FF3, 0xD74F9208), BN_DEF(0xAD44CFD2, 0xF71C35FD),
+ BN_DEF(0x7A035BF6, 0x85FFAE5B), BN_DEF(0xD31BF6B5, 0x7A262174),
+ BN_DEF(0x312F3F63, 0xF242DABB), BN_DEF(0xB6A8E122, 0xA7F09AB6),
+ BN_DEF(0xF92F8A1B, 0x98158536), BN_DEF(0xE69D218D, 0xF7CA8CD9),
+ BN_DEF(0xC71A026E, 0x28A5043C), BN_DEF(0x1D89CD91, 0x0105DF53),
+ BN_DEF(0x4533E63A, 0x94812704), BN_DEF(0xC06E0E68, 0x62633145),
+ BN_DEF(0x10B4611A, 0xE487ED51), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF),
};
-static const BN_ULONG ffdhe3072_p[] = {
- 0xFFFFFFFFFFFFFFFFULL, 0x25E41D2B66C62E37ULL, 0x3C1B20EE3FD59D7CULL,
- 0x0ABCD06BFA53DDEFULL, 0x1DBF9A42D5C4484EULL, 0xABC521979B0DEADAULL,
- 0xE86D2BC522363A0DULL, 0x5CAE82AB9C9DF69EULL, 0x64F2E21E71F54BFFULL,
- 0xF4FD4452E2D74DD3ULL, 0xB4130C93BC437944ULL, 0xAEFE130985139270ULL,
- 0x598CB0FAC186D91CULL, 0x7AD91D2691F7F7EEULL, 0x61B46FC9D6E6C907ULL,
- 0xBC34F4DEF99C0238ULL, 0xDE355B3B6519035BULL, 0x886B4238611FCFDCULL,
- 0xC6F34A26C1B2EFFAULL, 0xC58EF1837D1683B2ULL, 0x3BB5FCBC2EC22005ULL,
- 0xC3FE3B1B4C6FAD73ULL, 0x8E4F1232EEF28183ULL, 0x9172FE9CE98583FFULL,
- 0xC03404CD28342F61ULL, 0x9E02FCE1CDF7E2ECULL, 0x0B07A7C8EE0A6D70ULL,
- 0xAE56EDE76372BB19ULL, 0x1D4F42A3DE394DF4ULL, 0xB96ADAB760D7F468ULL,
- 0xD108A94BB2C8E3FBULL, 0xBC0AB182B324FB61ULL, 0x30ACCA4F483A797AULL,
- 0x1DF158A136ADE735ULL, 0xE2A689DAF3EFE872ULL, 0x984F0C70E0E68B77ULL,
- 0xB557135E7F57C935ULL, 0x856365553DED1AF3ULL, 0x2433F51F5F066ED0ULL,
- 0xD3DF1ED5D5FD6561ULL, 0xF681B202AEC4617AULL, 0x7D2FE363630C75D8ULL,
- 0xCC939DCE249B3EF9ULL, 0xA9E13641146433FBULL, 0xD8B9C583CE2D3695ULL,
- 0xAFDC5620273D3CF1ULL, 0xADF85458A2BB4A9AULL, 0xFFFFFFFFFFFFFFFFULL
+/*-
+ * "6144-bit MODP Group" from RFC3526, Section 6.
+ *
+ * The prime is: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 }
+ *
+ * RFC3526 specifies a generator of 2.
+ */
+static const BN_ULONG modp_6144_p[] = {
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x6DCC4024, 0xE694F91E),
+ BN_DEF(0x0B7474D6, 0x12BF2D5B), BN_DEF(0x3F4860EE, 0x043E8F66),
+ BN_DEF(0x6E3C0468, 0x387FE8D7), BN_DEF(0x2EF29632, 0xDA56C9EC),
+ BN_DEF(0xA313D55C, 0xEB19CCB1), BN_DEF(0x8A1FBFF0, 0xF550AA3D),
+ BN_DEF(0xB7C5DA76, 0x06A1D58B), BN_DEF(0xF29BE328, 0xA79715EE),
+ BN_DEF(0x0F8037E0, 0x14CC5ED2), BN_DEF(0xBF48E1D8, 0xCC8F6D7E),
+ BN_DEF(0x2B4154AA, 0x4BD407B2), BN_DEF(0xFF585AC5, 0x0F1D45B7),
+ BN_DEF(0x36CC88BE, 0x23A97A7E), BN_DEF(0xBEC7E8F3, 0x59E7C97F),
+ BN_DEF(0x900B1C9E, 0xB5A84031), BN_DEF(0x46980C82, 0xD55E702F),
+ BN_DEF(0x6E74FEF6, 0xF482D7CE), BN_DEF(0xD1721D03, 0xF032EA15),
+ BN_DEF(0xC64B92EC, 0x5983CA01), BN_DEF(0x378CD2BF, 0x6FB8F401),
+ BN_DEF(0x2BD7AF42, 0x33205151), BN_DEF(0xE6CC254B, 0xDB7F1447),
+ BN_DEF(0xCED4BB1B, 0x44CE6CBA), BN_DEF(0xCF9B14ED, 0xDA3EDBEB),
+ BN_DEF(0x865A8918, 0x179727B0), BN_DEF(0x9027D831, 0xB06A53ED),
+ BN_DEF(0x413001AE, 0xE5DB382F), BN_DEF(0xAD9E530E, 0xF8FF9406),
+ BN_DEF(0x3DBA37BD, 0xC9751E76), BN_DEF(0x602646DE, 0xC1D4DCB2),
+ BN_DEF(0xD27C7026, 0x36C3FAB4), BN_DEF(0x34028492, 0x4DF435C9),
+ BN_DEF(0x90A6C08F, 0x86FFB7DC), BN_DEF(0x8D8FDDC1, 0x93B4EA98),
+ BN_DEF(0xD5B05AA9, 0xD0069127), BN_DEF(0x2170481C, 0xB81BDD76),
+ BN_DEF(0xCEE2D7AF, 0x1F612970), BN_DEF(0x515BE7ED, 0x233BA186),
+ BN_DEF(0xA090C3A2, 0x99B2964F), BN_DEF(0x4E6BC05D, 0x287C5947),
+ BN_DEF(0x1FBECAA6, 0x2E8EFC14), BN_DEF(0x04DE8EF9, 0xDBBBC2DB),
+ BN_DEF(0x2AD44CE8, 0x2583E9CA), BN_DEF(0xB6150BDA, 0x1A946834),
+ BN_DEF(0x6AF4E23C, 0x99C32718), BN_DEF(0xBDBA5B26, 0x88719A10),
+ BN_DEF(0xA787E6D7, 0x1A723C12), BN_DEF(0xA9210801, 0x4B82D120),
+ BN_DEF(0xE0FD108E, 0x43DB5BFC), BN_DEF(0x74E5AB31, 0x08E24FA0),
+ BN_DEF(0xBAD946E2, 0x770988C0), BN_DEF(0x7A615D6C, 0xBBE11757),
+ BN_DEF(0x177B200C, 0x521F2B18), BN_DEF(0x3EC86A64, 0xD8760273),
+ BN_DEF(0xD98A0864, 0xF12FFA06), BN_DEF(0x1AD2EE6B, 0xCEE3D226),
+ BN_DEF(0x4A25619D, 0x1E8C94E0), BN_DEF(0xDB0933D7, 0xABF5AE8C),
+ BN_DEF(0xA6E1E4C7, 0xB3970F85), BN_DEF(0x5D060C7D, 0x8AEA7157),
+ BN_DEF(0x58DBEF0A, 0xECFB8504), BN_DEF(0xDF1CBA64, 0xA85521AB),
+ BN_DEF(0x04507A33, 0xAD33170D), BN_DEF(0x8AAAC42D, 0x15728E5A),
+ BN_DEF(0x98FA0510, 0x15D22618), BN_DEF(0xEA956AE5, 0x3995497C),
+ BN_DEF(0x95581718, 0xDE2BCBF6), BN_DEF(0x6F4C52C9, 0xB5C55DF0),
+ BN_DEF(0xEC07A28F, 0x9B2783A2), BN_DEF(0x180E8603, 0xE39E772C),
+ BN_DEF(0x2E36CE3B, 0x32905E46), BN_DEF(0xCA18217C, 0xF1746C08),
+ BN_DEF(0x4ABC9804, 0x670C354E), BN_DEF(0x7096966D, 0x9ED52907),
+ BN_DEF(0x208552BB, 0x1C62F356), BN_DEF(0xDCA3AD96, 0x83655D23),
+ BN_DEF(0xFD24CF5F, 0x69163FA8), BN_DEF(0x1C55D39A, 0x98DA4836),
+ BN_DEF(0xA163BF05, 0xC2007CB8), BN_DEF(0xECE45B3D, 0x49286651),
+ BN_DEF(0x7C4B1FE6, 0xAE9F2411), BN_DEF(0x5A899FA5, 0xEE386BFB),
+ BN_DEF(0xF406B7ED, 0x0BFF5CB6), BN_DEF(0xA637ED6B, 0xF44C42E9),
+ BN_DEF(0x625E7EC6, 0xE485B576), BN_DEF(0x6D51C245, 0x4FE1356D),
+ BN_DEF(0xF25F1437, 0x302B0A6D), BN_DEF(0xCD3A431B, 0xEF9519B3),
+ BN_DEF(0x8E3404DD, 0x514A0879), BN_DEF(0x3B139B22, 0x020BBEA6),
+ BN_DEF(0x8A67CC74, 0x29024E08), BN_DEF(0x80DC1CD1, 0xC4C6628B),
+ BN_DEF(0x2168C234, 0xC90FDAA2), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF)
};
-
-static const BN_ULONG ffdhe4096_p[] = {
- 0xFFFFFFFFFFFFFFFFULL, 0xC68A007E5E655F6AULL, 0x4DB5A851F44182E1ULL,
- 0x8EC9B55A7F88A46BULL, 0x0A8291CDCEC97DCFULL, 0x2A4ECEA9F98D0ACCULL,
- 0x1A1DB93D7140003CULL, 0x092999A333CB8B7AULL, 0x6DC778F971AD0038ULL,
- 0xA907600A918130C4ULL, 0xED6A1E012D9E6832ULL, 0x7135C886EFB4318AULL,
- 0x87F55BA57E31CC7AULL, 0x7763CF1D55034004ULL, 0xAC7D5F42D69F6D18ULL,
- 0x7930E9E4E58857B6ULL, 0x6E6F52C3164DF4FBULL, 0x25E41D2B669E1EF1ULL,
- 0x3C1B20EE3FD59D7CULL, 0x0ABCD06BFA53DDEFULL, 0x1DBF9A42D5C4484EULL,
- 0xABC521979B0DEADAULL, 0xE86D2BC522363A0DULL, 0x5CAE82AB9C9DF69EULL,
- 0x64F2E21E71F54BFFULL, 0xF4FD4452E2D74DD3ULL, 0xB4130C93BC437944ULL,
- 0xAEFE130985139270ULL, 0x598CB0FAC186D91CULL, 0x7AD91D2691F7F7EEULL,
- 0x61B46FC9D6E6C907ULL, 0xBC34F4DEF99C0238ULL, 0xDE355B3B6519035BULL,
- 0x886B4238611FCFDCULL, 0xC6F34A26C1B2EFFAULL, 0xC58EF1837D1683B2ULL,
- 0x3BB5FCBC2EC22005ULL, 0xC3FE3B1B4C6FAD73ULL, 0x8E4F1232EEF28183ULL,
- 0x9172FE9CE98583FFULL, 0xC03404CD28342F61ULL, 0x9E02FCE1CDF7E2ECULL,
- 0x0B07A7C8EE0A6D70ULL, 0xAE56EDE76372BB19ULL, 0x1D4F42A3DE394DF4ULL,
- 0xB96ADAB760D7F468ULL, 0xD108A94BB2C8E3FBULL, 0xBC0AB182B324FB61ULL,
- 0x30ACCA4F483A797AULL, 0x1DF158A136ADE735ULL, 0xE2A689DAF3EFE872ULL,
- 0x984F0C70E0E68B77ULL, 0xB557135E7F57C935ULL, 0x856365553DED1AF3ULL,
- 0x2433F51F5F066ED0ULL, 0xD3DF1ED5D5FD6561ULL, 0xF681B202AEC4617AULL,
- 0x7D2FE363630C75D8ULL, 0xCC939DCE249B3EF9ULL, 0xA9E13641146433FBULL,
- 0xD8B9C583CE2D3695ULL, 0xAFDC5620273D3CF1ULL, 0xADF85458A2BB4A9AULL,
- 0xFFFFFFFFFFFFFFFFULL
+/* q = (p - 1) / 2 */
+static const BN_ULONG modp_6144_q[] = {
+ BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), BN_DEF(0x36E62012, 0x734A7C8F),
+ BN_DEF(0x85BA3A6B, 0x095F96AD), BN_DEF(0x1FA43077, 0x021F47B3),
+ BN_DEF(0xB71E0234, 0x1C3FF46B), BN_DEF(0x17794B19, 0x6D2B64F6),
+ BN_DEF(0xD189EAAE, 0x758CE658), BN_DEF(0xC50FDFF8, 0x7AA8551E),
+ BN_DEF(0xDBE2ED3B, 0x0350EAC5), BN_DEF(0x794DF194, 0x53CB8AF7),
+ BN_DEF(0x07C01BF0, 0x0A662F69), BN_DEF(0x5FA470EC, 0x6647B6BF),
+ BN_DEF(0x15A0AA55, 0xA5EA03D9), BN_DEF(0xFFAC2D62, 0x078EA2DB),
+ BN_DEF(0x1B66445F, 0x91D4BD3F), BN_DEF(0xDF63F479, 0x2CF3E4BF),
+ BN_DEF(0xC8058E4F, 0x5AD42018), BN_DEF(0xA34C0641, 0x6AAF3817),
+ BN_DEF(0x373A7F7B, 0xFA416BE7), BN_DEF(0xE8B90E81, 0x7819750A),
+ BN_DEF(0xE325C976, 0xACC1E500), BN_DEF(0x9BC6695F, 0x37DC7A00),
+ BN_DEF(0x95EBD7A1, 0x999028A8), BN_DEF(0xF36612A5, 0xEDBF8A23),
+ BN_DEF(0x676A5D8D, 0xA267365D), BN_DEF(0xE7CD8A76, 0x6D1F6DF5),
+ BN_DEF(0x432D448C, 0x8BCB93D8), BN_DEF(0xC813EC18, 0x583529F6),
+ BN_DEF(0xA09800D7, 0x72ED9C17), BN_DEF(0x56CF2987, 0xFC7FCA03),
+ BN_DEF(0x1EDD1BDE, 0x64BA8F3B), BN_DEF(0x3013236F, 0x60EA6E59),
+ BN_DEF(0x693E3813, 0x1B61FD5A), BN_DEF(0x9A014249, 0xA6FA1AE4),
+ BN_DEF(0x48536047, 0xC37FDBEE), BN_DEF(0x46C7EEE0, 0xC9DA754C),
+ BN_DEF(0xEAD82D54, 0x68034893), BN_DEF(0x10B8240E, 0xDC0DEEBB),
+ BN_DEF(0x67716BD7, 0x8FB094B8), BN_DEF(0x28ADF3F6, 0x119DD0C3),
+ BN_DEF(0xD04861D1, 0xCCD94B27), BN_DEF(0xA735E02E, 0x143E2CA3),
+ BN_DEF(0x0FDF6553, 0x97477E0A), BN_DEF(0x826F477C, 0x6DDDE16D),
+ BN_DEF(0x156A2674, 0x12C1F4E5), BN_DEF(0x5B0A85ED, 0x0D4A341A),
+ BN_DEF(0x357A711E, 0x4CE1938C), BN_DEF(0x5EDD2D93, 0xC438CD08),
+ BN_DEF(0x53C3F36B, 0x8D391E09), BN_DEF(0x54908400, 0x25C16890),
+ BN_DEF(0x707E8847, 0xA1EDADFE), BN_DEF(0x3A72D598, 0x047127D0),
+ BN_DEF(0x5D6CA371, 0x3B84C460), BN_DEF(0xBD30AEB6, 0x5DF08BAB),
+ BN_DEF(0x0BBD9006, 0x290F958C), BN_DEF(0x9F643532, 0x6C3B0139),
+ BN_DEF(0x6CC50432, 0xF897FD03), BN_DEF(0x0D697735, 0xE771E913),
+ BN_DEF(0x2512B0CE, 0x8F464A70), BN_DEF(0x6D8499EB, 0xD5FAD746),
+ BN_DEF(0xD370F263, 0xD9CB87C2), BN_DEF(0xAE83063E, 0x457538AB),
+ BN_DEF(0x2C6DF785, 0x767DC282), BN_DEF(0xEF8E5D32, 0xD42A90D5),
+ BN_DEF(0x82283D19, 0xD6998B86), BN_DEF(0x45556216, 0x0AB9472D),
+ BN_DEF(0x4C7D0288, 0x8AE9130C), BN_DEF(0x754AB572, 0x1CCAA4BE),
+ BN_DEF(0x4AAC0B8C, 0xEF15E5FB), BN_DEF(0x37A62964, 0xDAE2AEF8),
+ BN_DEF(0x7603D147, 0xCD93C1D1), BN_DEF(0x0C074301, 0xF1CF3B96),
+ BN_DEF(0x171B671D, 0x19482F23), BN_DEF(0x650C10BE, 0x78BA3604),
+ BN_DEF(0x255E4C02, 0xB3861AA7), BN_DEF(0xB84B4B36, 0xCF6A9483),
+ BN_DEF(0x1042A95D, 0x0E3179AB), BN_DEF(0xEE51D6CB, 0xC1B2AE91),
+ BN_DEF(0x7E9267AF, 0x348B1FD4), BN_DEF(0x0E2AE9CD, 0xCC6D241B),
+ BN_DEF(0x50B1DF82, 0xE1003E5C), BN_DEF(0xF6722D9E, 0x24943328),
+ BN_DEF(0xBE258FF3, 0xD74F9208), BN_DEF(0xAD44CFD2, 0xF71C35FD),
+ BN_DEF(0x7A035BF6, 0x85FFAE5B), BN_DEF(0xD31BF6B5, 0x7A262174),
+ BN_DEF(0x312F3F63, 0xF242DABB), BN_DEF(0xB6A8E122, 0xA7F09AB6),
+ BN_DEF(0xF92F8A1B, 0x98158536), BN_DEF(0xE69D218D, 0xF7CA8CD9),
+ BN_DEF(0xC71A026E, 0x28A5043C), BN_DEF(0x1D89CD91, 0x0105DF53),
+ BN_DEF(0x4533E63A, 0x94812704), BN_DEF(0xC06E0E68, 0x62633145),
+ BN_DEF(0x10B4611A, 0xE487ED51), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF),
};
-static const BN_ULONG ffdhe6144_p[] = {
- 0xFFFFFFFFFFFFFFFFULL, 0xA40E329CD0E40E65ULL, 0xA41D570D7938DAD4ULL,
- 0x62A69526D43161C1ULL, 0x3FDD4A8E9ADB1E69ULL, 0x5B3B71F9DC6B80D6ULL,
- 0xEC9D1810C6272B04ULL, 0x8CCF2DD5CACEF403ULL, 0xE49F5235C95B9117ULL,
- 0x505DC82DB854338AULL, 0x62292C311562A846ULL, 0xD72B03746AE77F5EULL,
- 0xF9C9091B462D538CULL, 0x0AE8DB5847A67CBEULL, 0xB3A739C122611682ULL,
- 0xEEAAC0232A281BF6ULL, 0x94C6651E77CAF992ULL, 0x763E4E4B94B2BBC1ULL,
- 0x587E38DA0077D9B4ULL, 0x7FB29F8C183023C3ULL, 0x0ABEC1FFF9E3A26EULL,
- 0xA00EF092350511E3ULL, 0xB855322EDB6340D8ULL, 0xA52471F7A9A96910ULL,
- 0x388147FB4CFDB477ULL, 0x9B1F5C3E4E46041FULL, 0xCDAD0657FCCFEC71ULL,
- 0xB38E8C334C701C3AULL, 0x917BDD64B1C0FD4CULL, 0x3BB454329B7624C8ULL,
- 0x23BA4442CAF53EA6ULL, 0x4E677D2C38532A3AULL, 0x0BFD64B645036C7AULL,
- 0xC68A007E5E0DD902ULL, 0x4DB5A851F44182E1ULL, 0x8EC9B55A7F88A46BULL,
- 0x0A8291CDCEC97DCFULL, 0x2A4ECEA9F98D0ACCULL, 0x1A1DB93D7140003CULL,
- 0x092999A333CB8B7AULL, 0x6DC778F971AD0038ULL, 0xA907600A918130C4ULL,
- 0xED6A1E012D9E6832ULL, 0x7135C886EFB4318AULL, 0x87F55BA57E31CC7AULL,
- 0x7763CF1D55034004ULL, 0xAC7D5F42D69F6D18ULL, 0x7930E9E4E58857B6ULL,
- 0x6E6F52C3164DF4FBULL, 0x25E41D2B669E1EF1ULL, 0x3C1B20EE3FD59D7CULL,
- 0x0ABCD06BFA53DDEFULL, 0x1DBF9A42D5C4484EULL, 0xABC521979B0DEADAULL,
- 0xE86D2BC522363A0DULL, 0x5CAE82AB9C9DF69EULL, 0x64F2E21E71F54BFFULL,
- 0xF4FD4452E2D74DD3ULL, 0xB4130C93BC437944ULL, 0xAEFE130985139270ULL,
- 0x598CB0FAC186D91CULL, 0x7AD91D2691F7F7EEULL, 0x61B46FC9D6E6C907ULL,
- 0xBC34F4DEF99C0238ULL, 0xDE355B3B6519035BULL, 0x886B4238611FCFDCULL,
- 0xC6F34A26C1B2EFFAULL, 0xC58EF1837D1683B2ULL, 0x3BB5FCBC2EC22005ULL,
- 0xC3FE3B1B4C6FAD73ULL, 0x8E4F1232EEF28183ULL, 0x9172FE9CE98583FFULL,
- 0xC03404CD28342F61ULL, 0x9E02FCE1CDF7E2ECULL, 0x0B07A7C8EE0A6D70ULL,
- 0xAE56EDE76372BB19ULL, 0x1D4F42A3DE394DF4ULL, 0xB96ADAB760D7F468ULL,
- 0xD108A94BB2C8E3FBULL, 0xBC0AB182B324FB61ULL, 0x30ACCA4F483A797AULL,
- 0x1DF158A136ADE735ULL, 0xE2A689DAF3EFE872ULL, 0x984F0C70E0E68B77ULL,
- 0xB557135E7F57C935ULL, 0x856365553DED1AF3ULL, 0x2433F51F5F066ED0ULL,
- 0xD3DF1ED5D5FD6561ULL, 0xF681B202AEC4617AULL, 0x7D2FE363630C75D8ULL,
- 0xCC939DCE249B3EF9ULL, 0xA9E13641146433FBULL, 0xD8B9C583CE2D3695ULL,
- 0xAFDC5620273D3CF1ULL, 0xADF85458A2BB4A9AULL, 0xFFFFFFFFFFFFFFFFULL
+/*
+ * "8192-bit MODP Group" from RFC3526, Section 7.
+ *
+ * The prime is: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 }
+ *
+ * RFC3526 specifies a generator of 2.
+ */
+static const BN_ULONG modp_8192_p[] = {
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x98EDD3DF, 0x60C980DD),
+ BN_DEF(0x80B96E71, 0xC81F56E8), BN_DEF(0x765694DF, 0x9E3050E2),
+ BN_DEF(0x5677E9AA, 0x9558E447), BN_DEF(0xFC026E47, 0xC9190DA6),
+ BN_DEF(0xD5EE382B, 0x889A002E), BN_DEF(0x481C6CD7, 0x4009438B),
+ BN_DEF(0xEB879F92, 0x359046F4), BN_DEF(0x1ECFA268, 0xFAF36BC3),
+ BN_DEF(0x7EE74D73, 0xB1D510BD), BN_DEF(0x5DED7EA1, 0xF9AB4819),
+ BN_DEF(0x0846851D, 0x64F31CC5), BN_DEF(0xA0255DC1, 0x4597E899),
+ BN_DEF(0x74AB6A36, 0xDF310EE0), BN_DEF(0x3F44F82D, 0x6D2A13F8),
+ BN_DEF(0xB3A278A6, 0x062B3CF5), BN_DEF(0xED5BDD3A, 0x79683303),
+ BN_DEF(0xA2C087E8, 0xFA9D4B7F), BN_DEF(0x2F8385DD, 0x4BCBC886),
+ BN_DEF(0x6CEA306B, 0x3473FC64), BN_DEF(0x1A23F0C7, 0x13EB57A8),
+ BN_DEF(0xA4037C07, 0x22222E04), BN_DEF(0xFC848AD9, 0xE3FDB8BE),
+ BN_DEF(0xE39D652D, 0x238F16CB), BN_DEF(0x2BF1C978, 0x3423B474),
+ BN_DEF(0x5AE4F568, 0x3AAB639C), BN_DEF(0x6BA42466, 0x2576F693),
+ BN_DEF(0x8AFC47ED, 0x741FA7BF), BN_DEF(0x8D9DD300, 0x3BC832B6),
+ BN_DEF(0x73B931BA, 0xD8BEC4D0), BN_DEF(0xA932DF8C, 0x38777CB6),
+ BN_DEF(0x12FEE5E4, 0x74A3926F), BN_DEF(0x6DBE1159, 0xE694F91E),
+ BN_DEF(0x0B7474D6, 0x12BF2D5B), BN_DEF(0x3F4860EE, 0x043E8F66),
+ BN_DEF(0x6E3C0468, 0x387FE8D7), BN_DEF(0x2EF29632, 0xDA56C9EC),
+ BN_DEF(0xA313D55C, 0xEB19CCB1), BN_DEF(0x8A1FBFF0, 0xF550AA3D),
+ BN_DEF(0xB7C5DA76, 0x06A1D58B), BN_DEF(0xF29BE328, 0xA79715EE),
+ BN_DEF(0x0F8037E0, 0x14CC5ED2), BN_DEF(0xBF48E1D8, 0xCC8F6D7E),
+ BN_DEF(0x2B4154AA, 0x4BD407B2), BN_DEF(0xFF585AC5, 0x0F1D45B7),
+ BN_DEF(0x36CC88BE, 0x23A97A7E), BN_DEF(0xBEC7E8F3, 0x59E7C97F),
+ BN_DEF(0x900B1C9E, 0xB5A84031), BN_DEF(0x46980C82, 0xD55E702F),
+ BN_DEF(0x6E74FEF6, 0xF482D7CE), BN_DEF(0xD1721D03, 0xF032EA15),
+ BN_DEF(0xC64B92EC, 0x5983CA01), BN_DEF(0x378CD2BF, 0x6FB8F401),
+ BN_DEF(0x2BD7AF42, 0x33205151), BN_DEF(0xE6CC254B, 0xDB7F1447),
+ BN_DEF(0xCED4BB1B, 0x44CE6CBA), BN_DEF(0xCF9B14ED, 0xDA3EDBEB),
+ BN_DEF(0x865A8918, 0x179727B0), BN_DEF(0x9027D831, 0xB06A53ED),
+ BN_DEF(0x413001AE, 0xE5DB382F), BN_DEF(0xAD9E530E, 0xF8FF9406),
+ BN_DEF(0x3DBA37BD, 0xC9751E76), BN_DEF(0x602646DE, 0xC1D4DCB2),
+ BN_DEF(0xD27C7026, 0x36C3FAB4), BN_DEF(0x34028492, 0x4DF435C9),
+ BN_DEF(0x90A6C08F, 0x86FFB7DC), BN_DEF(0x8D8FDDC1, 0x93B4EA98),
+ BN_DEF(0xD5B05AA9, 0xD0069127), BN_DEF(0x2170481C, 0xB81BDD76),
+ BN_DEF(0xCEE2D7AF, 0x1F612970), BN_DEF(0x515BE7ED, 0x233BA186),
+ BN_DEF(0xA090C3A2, 0x99B2964F), BN_DEF(0x4E6BC05D, 0x287C5947),
+ BN_DEF(0x1FBECAA6, 0x2E8EFC14), BN_DEF(0x04DE8EF9, 0xDBBBC2DB),
+ BN_DEF(0x2AD44CE8, 0x2583E9CA), BN_DEF(0xB6150BDA, 0x1A946834),
+ BN_DEF(0x6AF4E23C, 0x99C32718), BN_DEF(0xBDBA5B26, 0x88719A10),
+ BN_DEF(0xA787E6D7, 0x1A723C12), BN_DEF(0xA9210801, 0x4B82D120),
+ BN_DEF(0xE0FD108E, 0x43DB5BFC), BN_DEF(0x74E5AB31, 0x08E24FA0),
+ BN_DEF(0xBAD946E2, 0x770988C0), BN_DEF(0x7A615D6C, 0xBBE11757),
+ BN_DEF(0x177B200C, 0x521F2B18), BN_DEF(0x3EC86A64, 0xD8760273),
+ BN_DEF(0xD98A0864, 0xF12FFA06), BN_DEF(0x1AD2EE6B, 0xCEE3D226),
+ BN_DEF(0x4A25619D, 0x1E8C94E0), BN_DEF(0xDB0933D7, 0xABF5AE8C),
+ BN_DEF(0xA6E1E4C7, 0xB3970F85), BN_DEF(0x5D060C7D, 0x8AEA7157),
+ BN_DEF(0x58DBEF0A, 0xECFB8504), BN_DEF(0xDF1CBA64, 0xA85521AB),
+ BN_DEF(0x04507A33, 0xAD33170D), BN_DEF(0x8AAAC42D, 0x15728E5A),
+ BN_DEF(0x98FA0510, 0x15D22618), BN_DEF(0xEA956AE5, 0x3995497C),
+ BN_DEF(0x95581718, 0xDE2BCBF6), BN_DEF(0x6F4C52C9, 0xB5C55DF0),
+ BN_DEF(0xEC07A28F, 0x9B2783A2), BN_DEF(0x180E8603, 0xE39E772C),
+ BN_DEF(0x2E36CE3B, 0x32905E46), BN_DEF(0xCA18217C, 0xF1746C08),
+ BN_DEF(0x4ABC9804, 0x670C354E), BN_DEF(0x7096966D, 0x9ED52907),
+ BN_DEF(0x208552BB, 0x1C62F356), BN_DEF(0xDCA3AD96, 0x83655D23),
+ BN_DEF(0xFD24CF5F, 0x69163FA8), BN_DEF(0x1C55D39A, 0x98DA4836),
+ BN_DEF(0xA163BF05, 0xC2007CB8), BN_DEF(0xECE45B3D, 0x49286651),
+ BN_DEF(0x7C4B1FE6, 0xAE9F2411), BN_DEF(0x5A899FA5, 0xEE386BFB),
+ BN_DEF(0xF406B7ED, 0x0BFF5CB6), BN_DEF(0xA637ED6B, 0xF44C42E9),
+ BN_DEF(0x625E7EC6, 0xE485B576), BN_DEF(0x6D51C245, 0x4FE1356D),
+ BN_DEF(0xF25F1437, 0x302B0A6D), BN_DEF(0xCD3A431B, 0xEF9519B3),
+ BN_DEF(0x8E3404DD, 0x514A0879), BN_DEF(0x3B139B22, 0x020BBEA6),
+ BN_DEF(0x8A67CC74, 0x29024E08), BN_DEF(0x80DC1CD1, 0xC4C6628B),
+ BN_DEF(0x2168C234, 0xC90FDAA2), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF)
};
-
-static const BN_ULONG ffdhe8192_p[] = {
- 0xFFFFFFFFFFFFFFFFULL, 0xD68C8BB7C5C6424CULL, 0x011E2A94838FF88CULL,
- 0x0822E506A9F4614EULL, 0x97D11D49F7A8443DULL, 0xA6BBFDE530677F0DULL,
- 0x2F741EF8C1FE86FEULL, 0xFAFABE1C5D71A87EULL, 0xDED2FBABFBE58A30ULL,
- 0xB6855DFE72B0A66EULL, 0x1EFC8CE0BA8A4FE8ULL, 0x83F81D4A3F2FA457ULL,
- 0xA1FE3075A577E231ULL, 0xD5B8019488D9C0A0ULL, 0x624816CDAD9A95F9ULL,
- 0x99E9E31650C1217BULL, 0x51AA691E0E423CFCULL, 0x1C217E6C3826E52CULL,
- 0x51A8A93109703FEEULL, 0xBB7099876A460E74ULL, 0x541FC68C9C86B022ULL,
- 0x59160CC046FD8251ULL, 0x2846C0BA35C35F5CULL, 0x54504AC78B758282ULL,
- 0x29388839D2AF05E4ULL, 0xCB2C0F1CC01BD702ULL, 0x555B2F747C932665ULL,
- 0x86B63142A3AB8829ULL, 0x0B8CC3BDF64B10EFULL, 0x687FEB69EDD1CC5EULL,
- 0xFDB23FCEC9509D43ULL, 0x1E425A31D951AE64ULL, 0x36AD004CF600C838ULL,
- 0xA40E329CCFF46AAAULL, 0xA41D570D7938DAD4ULL, 0x62A69526D43161C1ULL,
- 0x3FDD4A8E9ADB1E69ULL, 0x5B3B71F9DC6B80D6ULL, 0xEC9D1810C6272B04ULL,
- 0x8CCF2DD5CACEF403ULL, 0xE49F5235C95B9117ULL, 0x505DC82DB854338AULL,
- 0x62292C311562A846ULL, 0xD72B03746AE77F5EULL, 0xF9C9091B462D538CULL,
- 0x0AE8DB5847A67CBEULL, 0xB3A739C122611682ULL, 0xEEAAC0232A281BF6ULL,
- 0x94C6651E77CAF992ULL, 0x763E4E4B94B2BBC1ULL, 0x587E38DA0077D9B4ULL,
- 0x7FB29F8C183023C3ULL, 0x0ABEC1FFF9E3A26EULL, 0xA00EF092350511E3ULL,
- 0xB855322EDB6340D8ULL, 0xA52471F7A9A96910ULL, 0x388147FB4CFDB477ULL,
- 0x9B1F5C3E4E46041FULL, 0xCDAD0657FCCFEC71ULL, 0xB38E8C334C701C3AULL,
- 0x917BDD64B1C0FD4CULL, 0x3BB454329B7624C8ULL, 0x23BA4442CAF53EA6ULL,
- 0x4E677D2C38532A3AULL, 0x0BFD64B645036C7AULL, 0xC68A007E5E0DD902ULL,
- 0x4DB5A851F44182E1ULL, 0x8EC9B55A7F88A46BULL, 0x0A8291CDCEC97DCFULL,
- 0x2A4ECEA9F98D0ACCULL, 0x1A1DB93D7140003CULL, 0x092999A333CB8B7AULL,
- 0x6DC778F971AD0038ULL, 0xA907600A918130C4ULL, 0xED6A1E012D9E6832ULL,
- 0x7135C886EFB4318AULL, 0x87F55BA57E31CC7AULL, 0x7763CF1D55034004ULL,
- 0xAC7D5F42D69F6D18ULL, 0x7930E9E4E58857B6ULL, 0x6E6F52C3164DF4FBULL,
- 0x25E41D2B669E1EF1ULL, 0x3C1B20EE3FD59D7CULL, 0x0ABCD06BFA53DDEFULL,
- 0x1DBF9A42D5C4484EULL, 0xABC521979B0DEADAULL, 0xE86D2BC522363A0DULL,
- 0x5CAE82AB9C9DF69EULL, 0x64F2E21E71F54BFFULL, 0xF4FD4452E2D74DD3ULL,
- 0xB4130C93BC437944ULL, 0xAEFE130985139270ULL, 0x598CB0FAC186D91CULL,
- 0x7AD91D2691F7F7EEULL, 0x61B46FC9D6E6C907ULL, 0xBC34F4DEF99C0238ULL,
- 0xDE355B3B6519035BULL, 0x886B4238611FCFDCULL, 0xC6F34A26C1B2EFFAULL,
- 0xC58EF1837D1683B2ULL, 0x3BB5FCBC2EC22005ULL, 0xC3FE3B1B4C6FAD73ULL,
- 0x8E4F1232EEF28183ULL, 0x9172FE9CE98583FFULL, 0xC03404CD28342F61ULL,
- 0x9E02FCE1CDF7E2ECULL, 0x0B07A7C8EE0A6D70ULL, 0xAE56EDE76372BB19ULL,
- 0x1D4F42A3DE394DF4ULL, 0xB96ADAB760D7F468ULL, 0xD108A94BB2C8E3FBULL,
- 0xBC0AB182B324FB61ULL, 0x30ACCA4F483A797AULL, 0x1DF158A136ADE735ULL,
- 0xE2A689DAF3EFE872ULL, 0x984F0C70E0E68B77ULL, 0xB557135E7F57C935ULL,
- 0x856365553DED1AF3ULL, 0x2433F51F5F066ED0ULL, 0xD3DF1ED5D5FD6561ULL,
- 0xF681B202AEC4617AULL, 0x7D2FE363630C75D8ULL, 0xCC939DCE249B3EF9ULL,
- 0xA9E13641146433FBULL, 0xD8B9C583CE2D3695ULL, 0xAFDC5620273D3CF1ULL,
- 0xADF85458A2BB4A9AULL, 0xFFFFFFFFFFFFFFFFULL
+/* q = (p - 1) / 2 */
+static const BN_ULONG modp_8192_q[] = {
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0xCC76E9EF, 0xB064C06E),
+ BN_DEF(0x405CB738, 0xE40FAB74), BN_DEF(0x3B2B4A6F, 0x4F182871),
+ BN_DEF(0xAB3BF4D5, 0xCAAC7223), BN_DEF(0x7E013723, 0xE48C86D3),
+ BN_DEF(0x6AF71C15, 0xC44D0017), BN_DEF(0xA40E366B, 0x2004A1C5),
+ BN_DEF(0x75C3CFC9, 0x1AC8237A), BN_DEF(0x8F67D134, 0xFD79B5E1),
+ BN_DEF(0xBF73A6B9, 0xD8EA885E), BN_DEF(0xAEF6BF50, 0xFCD5A40C),
+ BN_DEF(0x8423428E, 0xB2798E62), BN_DEF(0xD012AEE0, 0x22CBF44C),
+ BN_DEF(0x3A55B51B, 0xEF988770), BN_DEF(0x1FA27C16, 0x369509FC),
+ BN_DEF(0xD9D13C53, 0x03159E7A), BN_DEF(0xF6ADEE9D, 0x3CB41981),
+ BN_DEF(0xD16043F4, 0xFD4EA5BF), BN_DEF(0x17C1C2EE, 0xA5E5E443),
+ BN_DEF(0x36751835, 0x9A39FE32), BN_DEF(0x0D11F863, 0x89F5ABD4),
+ BN_DEF(0x5201BE03, 0x91111702), BN_DEF(0x7E42456C, 0xF1FEDC5F),
+ BN_DEF(0xF1CEB296, 0x11C78B65), BN_DEF(0x15F8E4BC, 0x1A11DA3A),
+ BN_DEF(0x2D727AB4, 0x1D55B1CE), BN_DEF(0xB5D21233, 0x92BB7B49),
+ BN_DEF(0xC57E23F6, 0x3A0FD3DF), BN_DEF(0x46CEE980, 0x1DE4195B),
+ BN_DEF(0x39DC98DD, 0x6C5F6268), BN_DEF(0x54996FC6, 0x1C3BBE5B),
+ BN_DEF(0x897F72F2, 0xBA51C937), BN_DEF(0x36DF08AC, 0x734A7C8F),
+ BN_DEF(0x85BA3A6B, 0x095F96AD), BN_DEF(0x1FA43077, 0x021F47B3),
+ BN_DEF(0xB71E0234, 0x1C3FF46B), BN_DEF(0x17794B19, 0x6D2B64F6),
+ BN_DEF(0xD189EAAE, 0x758CE658), BN_DEF(0xC50FDFF8, 0x7AA8551E),
+ BN_DEF(0xDBE2ED3B, 0x0350EAC5), BN_DEF(0x794DF194, 0x53CB8AF7),
+ BN_DEF(0x07C01BF0, 0x0A662F69), BN_DEF(0x5FA470EC, 0x6647B6BF),
+ BN_DEF(0x15A0AA55, 0xA5EA03D9), BN_DEF(0xFFAC2D62, 0x078EA2DB),
+ BN_DEF(0x1B66445F, 0x91D4BD3F), BN_DEF(0xDF63F479, 0x2CF3E4BF),
+ BN_DEF(0xC8058E4F, 0x5AD42018), BN_DEF(0xA34C0641, 0x6AAF3817),
+ BN_DEF(0x373A7F7B, 0xFA416BE7), BN_DEF(0xE8B90E81, 0x7819750A),
+ BN_DEF(0xE325C976, 0xACC1E500), BN_DEF(0x9BC6695F, 0x37DC7A00),
+ BN_DEF(0x95EBD7A1, 0x999028A8), BN_DEF(0xF36612A5, 0xEDBF8A23),
+ BN_DEF(0x676A5D8D, 0xA267365D), BN_DEF(0xE7CD8A76, 0x6D1F6DF5),
+ BN_DEF(0x432D448C, 0x8BCB93D8), BN_DEF(0xC813EC18, 0x583529F6),
+ BN_DEF(0xA09800D7, 0x72ED9C17), BN_DEF(0x56CF2987, 0xFC7FCA03),
+ BN_DEF(0x1EDD1BDE, 0x64BA8F3B), BN_DEF(0x3013236F, 0x60EA6E59),
+ BN_DEF(0x693E3813, 0x1B61FD5A), BN_DEF(0x9A014249, 0xA6FA1AE4),
+ BN_DEF(0x48536047, 0xC37FDBEE), BN_DEF(0x46C7EEE0, 0xC9DA754C),
+ BN_DEF(0xEAD82D54, 0x68034893), BN_DEF(0x10B8240E, 0xDC0DEEBB),
+ BN_DEF(0x67716BD7, 0x8FB094B8), BN_DEF(0x28ADF3F6, 0x119DD0C3),
+ BN_DEF(0xD04861D1, 0xCCD94B27), BN_DEF(0xA735E02E, 0x143E2CA3),
+ BN_DEF(0x0FDF6553, 0x97477E0A), BN_DEF(0x826F477C, 0x6DDDE16D),
+ BN_DEF(0x156A2674, 0x12C1F4E5), BN_DEF(0x5B0A85ED, 0x0D4A341A),
+ BN_DEF(0x357A711E, 0x4CE1938C), BN_DEF(0x5EDD2D93, 0xC438CD08),
+ BN_DEF(0x53C3F36B, 0x8D391E09), BN_DEF(0x54908400, 0x25C16890),
+ BN_DEF(0x707E8847, 0xA1EDADFE), BN_DEF(0x3A72D598, 0x047127D0),
+ BN_DEF(0x5D6CA371, 0x3B84C460), BN_DEF(0xBD30AEB6, 0x5DF08BAB),
+ BN_DEF(0x0BBD9006, 0x290F958C), BN_DEF(0x9F643532, 0x6C3B0139),
+ BN_DEF(0x6CC50432, 0xF897FD03), BN_DEF(0x0D697735, 0xE771E913),
+ BN_DEF(0x2512B0CE, 0x8F464A70), BN_DEF(0x6D8499EB, 0xD5FAD746),
+ BN_DEF(0xD370F263, 0xD9CB87C2), BN_DEF(0xAE83063E, 0x457538AB),
+ BN_DEF(0x2C6DF785, 0x767DC282), BN_DEF(0xEF8E5D32, 0xD42A90D5),
+ BN_DEF(0x82283D19, 0xD6998B86), BN_DEF(0x45556216, 0x0AB9472D),
+ BN_DEF(0x4C7D0288, 0x8AE9130C), BN_DEF(0x754AB572, 0x1CCAA4BE),
+ BN_DEF(0x4AAC0B8C, 0xEF15E5FB), BN_DEF(0x37A62964, 0xDAE2AEF8),
+ BN_DEF(0x7603D147, 0xCD93C1D1), BN_DEF(0x0C074301, 0xF1CF3B96),
+ BN_DEF(0x171B671D, 0x19482F23), BN_DEF(0x650C10BE, 0x78BA3604),
+ BN_DEF(0x255E4C02, 0xB3861AA7), BN_DEF(0xB84B4B36, 0xCF6A9483),
+ BN_DEF(0x1042A95D, 0x0E3179AB), BN_DEF(0xEE51D6CB, 0xC1B2AE91),
+ BN_DEF(0x7E9267AF, 0x348B1FD4), BN_DEF(0x0E2AE9CD, 0xCC6D241B),
+ BN_DEF(0x50B1DF82, 0xE1003E5C), BN_DEF(0xF6722D9E, 0x24943328),
+ BN_DEF(0xBE258FF3, 0xD74F9208), BN_DEF(0xAD44CFD2, 0xF71C35FD),
+ BN_DEF(0x7A035BF6, 0x85FFAE5B), BN_DEF(0xD31BF6B5, 0x7A262174),
+ BN_DEF(0x312F3F63, 0xF242DABB), BN_DEF(0xB6A8E122, 0xA7F09AB6),
+ BN_DEF(0xF92F8A1B, 0x98158536), BN_DEF(0xE69D218D, 0xF7CA8CD9),
+ BN_DEF(0xC71A026E, 0x28A5043C), BN_DEF(0x1D89CD91, 0x0105DF53),
+ BN_DEF(0x4533E63A, 0x94812704), BN_DEF(0xC06E0E68, 0x62633145),
+ BN_DEF(0x10B4611A, 0xE487ED51), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF),
};
-# elif BN_BITS2 == 32
-
+/* DH parameters from RFC5114 */
static const BN_ULONG dh1024_160_p[] = {
- 0x2E4A4371, 0xDF1FB2BC, 0x6D4DA708, 0xE68CFDA7, 0x365C1A65, 0x45BF37DF,
- 0x0DC8B4BD, 0xA151AF5F, 0xF55BCCC0, 0xFAA31A4F, 0xE5644738, 0x4EFFD6FA,
- 0x219A7372, 0x98488E9C, 0x90C4BD70, 0xACCBDD7D, 0xD49B83BF, 0x24975C3C,
- 0xA9061123, 0x13ECB4AE, 0x2EE652C0, 0x9838EF1E, 0x75A23D18, 0x6073E286,
- 0x52D23B61, 0x9A6A9DCA, 0xFB06A3C6, 0x52C99FBC, 0xAE5D54EC, 0xDE92DE5E,
- 0xA080E01D, 0xB10B8F96
+ BN_DEF(0x2E4A4371, 0xDF1FB2BC), BN_DEF(0x6D4DA708, 0xE68CFDA7),
+ BN_DEF(0x365C1A65, 0x45BF37DF), BN_DEF(0x0DC8B4BD, 0xA151AF5F),
+ BN_DEF(0xF55BCCC0, 0xFAA31A4F), BN_DEF(0xE5644738, 0x4EFFD6FA),
+ BN_DEF(0x219A7372, 0x98488E9C), BN_DEF(0x90C4BD70, 0xACCBDD7D),
+ BN_DEF(0xD49B83BF, 0x24975C3C), BN_DEF(0xA9061123, 0x13ECB4AE),
+ BN_DEF(0x2EE652C0, 0x9838EF1E), BN_DEF(0x75A23D18, 0x6073E286),
+ BN_DEF(0x52D23B61, 0x9A6A9DCA), BN_DEF(0xFB06A3C6, 0x52C99FBC),
+ BN_DEF(0xAE5D54EC, 0xDE92DE5E), BN_DEF(0xA080E01D, 0xB10B8F96)
};
-
-static const BN_ULONG dh1024_160_g[] = {
- 0x22B3B2E5, 0x855E6EEB, 0xF97C2A24, 0x858F4DCE, 0x18D08BC8, 0x2D779D59,
- 0x8E73AFA3, 0xD662A4D1, 0x69B6A28A, 0x1DBF0A01, 0x7A091F53, 0xA6A24C08,
- 0x63F80A76, 0x909D0D22, 0xB9A92EE1, 0xD7FBD7D3, 0x9E2749F4, 0x5E91547F,
- 0xB01B886A, 0x160217B4, 0x5504F213, 0x777E690F, 0x5C41564B, 0x266FEA1E,
- 0x14266D31, 0xD6406CFF, 0x58AC507F, 0xF8104DD2, 0xEFB99905, 0x6765A442,
- 0xC3FD3412, 0xA4D1CBD5
-};
-
static const BN_ULONG dh1024_160_q[] = {
- 0x49462353, 0x64B7CB9D, 0x8ABA4E7D, 0x81A8DF27, 0xF518AA87
+ BN_DEF(0x49462353, 0x64B7CB9D), BN_DEF(0x8ABA4E7D, 0x81A8DF27),
+ (BN_ULONG)0xF518AA87
};
-
-static const BN_ULONG dh2048_224_p[] = {
- 0x0C10E64F, 0x0AC4DFFE, 0x4E71B81C, 0xCF9DE538, 0xFFA31F71, 0x7EF363E2,
- 0x6B8E75B9, 0xE3FB73C1, 0x4BA80A29, 0xC9B53DCF, 0x16E79763, 0x23F10B0E,
- 0x13042E9B, 0xC52172E4, 0xC928B2B9, 0xBE60E69C, 0xB9E587E8, 0x80CD86A1,
- 0x98C641A4, 0x315D75E1, 0x44328387, 0xCDF93ACC, 0xDC0A486D, 0x15987D9A,
- 0x1FD5A074, 0x7310F712, 0xDE31EFDC, 0x278273C7, 0x415D9330, 0x1602E714,
- 0xBC8985DB, 0x81286130, 0x70918836, 0xB3BF8A31, 0xB9C49708, 0x6A00E0A0,
- 0x8BBC27BE, 0xC6BA0B2C, 0xED34DBF6, 0xC9F98D11, 0xB6C12207, 0x7AD5B7D0,
- 0x55B7394B, 0xD91E8FEF, 0xEFDA4DF8, 0x9037C9ED, 0xAD6AC212, 0x6D3F8152,
- 0x1274A0A6, 0x1DE6B85A, 0x309C180E, 0xEB3D688A, 0x7BA1DF15, 0xAF9A3C40,
- 0xF95A56DB, 0xE6FA141D, 0xB61D0A75, 0xB54B1597, 0x683B9FD1, 0xA20D64E5,
- 0x9559C51F, 0xD660FAA7, 0x9123A9D0, 0xAD107E1E
+static const BN_ULONG dh1024_160_g[] = {
+ BN_DEF(0x22B3B2E5, 0x855E6EEB), BN_DEF(0xF97C2A24, 0x858F4DCE),
+ BN_DEF(0x18D08BC8, 0x2D779D59), BN_DEF(0x8E73AFA3, 0xD662A4D1),
+ BN_DEF(0x69B6A28A, 0x1DBF0A01), BN_DEF(0x7A091F53, 0xA6A24C08),
+ BN_DEF(0x63F80A76, 0x909D0D22), BN_DEF(0xB9A92EE1, 0xD7FBD7D3),
+ BN_DEF(0x9E2749F4, 0x5E91547F), BN_DEF(0xB01B886A, 0x160217B4),
+ BN_DEF(0x5504F213, 0x777E690F), BN_DEF(0x5C41564B, 0x266FEA1E),
+ BN_DEF(0x14266D31, 0xD6406CFF), BN_DEF(0x58AC507F, 0xF8104DD2),
+ BN_DEF(0xEFB99905, 0x6765A442), BN_DEF(0xC3FD3412, 0xA4D1CBD5)
};
-static const BN_ULONG dh2048_224_g[] = {
- 0x191F2BFA, 0x84B890D3, 0x2A7065B3, 0x81BC087F, 0xF6EC0179, 0x19C418E1,
- 0x71CFFF4C, 0x7B5A0F1C, 0x9B6AA4BD, 0xEDFE72FE, 0x94B30269, 0x81E1BCFE,
- 0x8D6C0191, 0x566AFBB4, 0x409D13CD, 0xB539CCE3, 0x5F2FF381, 0x6AA21E7F,
- 0x770589EF, 0xD9E263E4, 0xD19963DD, 0x10E183ED, 0x150B8EEB, 0xB70A8137,
- 0x28C8F8AC, 0x051AE3D4, 0x0C1AB15B, 0xBB77A86F, 0x16A330EF, 0x6E3025E3,
- 0xD6F83456, 0x19529A45, 0x118E98D1, 0xF180EB34, 0x50717CBE, 0xB5F6C6B2,
- 0xDA7460CD, 0x09939D54, 0x22EA1ED4, 0xE2471504, 0x521BC98A, 0xB8A762D0,
- 0x5AC1348B, 0xF4D02727, 0x1999024A, 0xC1766910, 0xA8D66AD7, 0xBE5E9001,
- 0x620A8652, 0xC57DB17C, 0x00C29F52, 0xAB739D77, 0xA70C4AFA, 0xDD921F01,
- 0x10B9A6F0, 0xA6824A4E, 0xCFE4FFE3, 0x74866A08, 0x89998CAF, 0x6CDEBE7B,
- 0x8FFDAC50, 0x9DF30B5C, 0x4F2D9AE3, 0xAC4032EF
+static const BN_ULONG dh2048_224_p[] = {
+ BN_DEF(0x0C10E64F, 0x0AC4DFFE), BN_DEF(0x4E71B81C, 0xCF9DE538),
+ BN_DEF(0xFFA31F71, 0x7EF363E2), BN_DEF(0x6B8E75B9, 0xE3FB73C1),
+ BN_DEF(0x4BA80A29, 0xC9B53DCF), BN_DEF(0x16E79763, 0x23F10B0E),
+ BN_DEF(0x13042E9B, 0xC52172E4), BN_DEF(0xC928B2B9, 0xBE60E69C),
+ BN_DEF(0xB9E587E8, 0x80CD86A1), BN_DEF(0x98C641A4, 0x315D75E1),
+ BN_DEF(0x44328387, 0xCDF93ACC), BN_DEF(0xDC0A486D, 0x15987D9A),
+ BN_DEF(0x1FD5A074, 0x7310F712), BN_DEF(0xDE31EFDC, 0x278273C7),
+ BN_DEF(0x415D9330, 0x1602E714), BN_DEF(0xBC8985DB, 0x81286130),
+ BN_DEF(0x70918836, 0xB3BF8A31), BN_DEF(0xB9C49708, 0x6A00E0A0),
+ BN_DEF(0x8BBC27BE, 0xC6BA0B2C), BN_DEF(0xED34DBF6, 0xC9F98D11),
+ BN_DEF(0xB6C12207, 0x7AD5B7D0), BN_DEF(0x55B7394B, 0xD91E8FEF),
+ BN_DEF(0xEFDA4DF8, 0x9037C9ED), BN_DEF(0xAD6AC212, 0x6D3F8152),
+ BN_DEF(0x1274A0A6, 0x1DE6B85A), BN_DEF(0x309C180E, 0xEB3D688A),
+ BN_DEF(0x7BA1DF15, 0xAF9A3C40), BN_DEF(0xF95A56DB, 0xE6FA141D),
+ BN_DEF(0xB61D0A75, 0xB54B1597), BN_DEF(0x683B9FD1, 0xA20D64E5),
+ BN_DEF(0x9559C51F, 0xD660FAA7), BN_DEF(0x9123A9D0, 0xAD107E1E)
};
-
static const BN_ULONG dh2048_224_q[] = {
- 0xB36371EB, 0xBF389A99, 0x4738CEBC, 0x1F80535A, 0x99717710, 0xC58D93FE,
- 0x801C0D34
+ BN_DEF(0xB36371EB, 0xBF389A99), BN_DEF(0x4738CEBC, 0x1F80535A),
+ BN_DEF(0x99717710, 0xC58D93FE), (BN_ULONG)0x801C0D34
};
-
-static const BN_ULONG dh2048_256_p[] = {
- 0x1E1A1597, 0xDB094AE9, 0xD7EF09CA, 0x693877FA, 0x6E11715F, 0x6116D227,
- 0xC198AF12, 0xA4B54330, 0xD7014103, 0x75F26375, 0x54E710C3, 0xC3A3960A,
- 0xBD0BE621, 0xDED4010A, 0x89962856, 0xC0B857F6, 0x71506026, 0xB3CA3F79,
- 0xE6B486F6, 0x1CCACB83, 0x14056425, 0x67E144E5, 0xA41825D9, 0xF6A167B5,
- 0x96524D8E, 0x3AD83477, 0x51BFA4AB, 0xF13C6D9A, 0x35488A0E, 0x2D525267,
- 0xCAA6B790, 0xB63ACAE1, 0x81B23F76, 0x4FDB70C5, 0x12307F5C, 0xBC39A0BF,
- 0xB1E59BB8, 0xB941F54E, 0xD45F9088, 0x6C5BFC11, 0x4275BF7B, 0x22E0B1EF,
- 0x5B4758C0, 0x91F9E672, 0x6BCF67ED, 0x5A8A9D30, 0x97517ABD, 0x209E0C64,
- 0x830E9A7C, 0x3BF4296D, 0x34096FAA, 0x16C3D911, 0x61B2AA30, 0xFAF7DF45,
- 0xD61957D4, 0xE00DF8F1, 0x435E3B00, 0x5D2CEED4, 0x660DD0F2, 0x8CEEF608,
- 0x65195999, 0xFFBBD19C, 0xB4B6663C, 0x87A8E61D
+static const BN_ULONG dh2048_224_g[] = {
+ BN_DEF(0x191F2BFA, 0x84B890D3), BN_DEF(0x2A7065B3, 0x81BC087F),
+ BN_DEF(0xF6EC0179, 0x19C418E1), BN_DEF(0x71CFFF4C, 0x7B5A0F1C),
+ BN_DEF(0x9B6AA4BD, 0xEDFE72FE), BN_DEF(0x94B30269, 0x81E1BCFE),
+ BN_DEF(0x8D6C0191, 0x566AFBB4), BN_DEF(0x409D13CD, 0xB539CCE3),
+ BN_DEF(0x5F2FF381, 0x6AA21E7F), BN_DEF(0x770589EF, 0xD9E263E4),
+ BN_DEF(0xD19963DD, 0x10E183ED), BN_DEF(0x150B8EEB, 0xB70A8137),
+ BN_DEF(0x28C8F8AC, 0x051AE3D4), BN_DEF(0x0C1AB15B, 0xBB77A86F),
+ BN_DEF(0x16A330EF, 0x6E3025E3), BN_DEF(0xD6F83456, 0x19529A45),
+ BN_DEF(0x118E98D1, 0xF180EB34), BN_DEF(0x50717CBE, 0xB5F6C6B2),
+ BN_DEF(0xDA7460CD, 0x09939D54), BN_DEF(0x22EA1ED4, 0xE2471504),
+ BN_DEF(0x521BC98A, 0xB8A762D0), BN_DEF(0x5AC1348B, 0xF4D02727),
+ BN_DEF(0x1999024A, 0xC1766910), BN_DEF(0xA8D66AD7, 0xBE5E9001),
+ BN_DEF(0x620A8652, 0xC57DB17C), BN_DEF(0x00C29F52, 0xAB739D77),
+ BN_DEF(0xA70C4AFA, 0xDD921F01), BN_DEF(0x10B9A6F0, 0xA6824A4E),
+ BN_DEF(0xCFE4FFE3, 0x74866A08), BN_DEF(0x89998CAF, 0x6CDEBE7B),
+ BN_DEF(0x8FFDAC50, 0x9DF30B5C), BN_DEF(0x4F2D9AE3, 0xAC4032EF)
};
-static const BN_ULONG dh2048_256_g[] = {
- 0x6CC41659, 0x664B4C0F, 0xEF98C582, 0x5E2327CF, 0xD4795451, 0xD647D148,
- 0x90F00EF8, 0x2F630784, 0x1DB246C3, 0x184B523D, 0xCDC67EB6, 0xC7891428,
- 0x0DF92B52, 0x7FD02837, 0x64E0EC37, 0xB3353BBB, 0x57CD0915, 0xECD06E15,
- 0xDF016199, 0xB7D2BBD2, 0x052588B9, 0xC8484B1E, 0x13D3FE14, 0xDB2A3B73,
- 0xD182EA0A, 0xD052B985, 0xE83B9C80, 0xA4BD1BFF, 0xFB3F2E55, 0xDFC967C1,
- 0x767164E1, 0xB5045AF2, 0x6F2F9193, 0x1D14348F, 0x428EBC83, 0x64E67982,
- 0x82D6ED38, 0x8AC376D2, 0xAAB8A862, 0x777DE62A, 0xE9EC144B, 0xDDF463E5,
- 0xC77A57F2, 0x0196F931, 0x41000A65, 0xA55AE313, 0xC28CBB18, 0x901228F8,
- 0x7E8C6F62, 0xBC3773BF, 0x0C6B47B1, 0xBE3A6C1B, 0xAC0BB555, 0xFF4FED4A,
- 0x77BE463F, 0x10DBC150, 0x1A0BA125, 0x07F4793A, 0x21EF2054, 0x4CA7B18F,
- 0x60EDBD48, 0x2E775066, 0x73134D0B, 0x3FB32C9B
+static const BN_ULONG dh2048_256_p[] = {
+ BN_DEF(0x1E1A1597, 0xDB094AE9), BN_DEF(0xD7EF09CA, 0x693877FA),
+ BN_DEF(0x6E11715F, 0x6116D227), BN_DEF(0xC198AF12, 0xA4B54330),
+ BN_DEF(0xD7014103, 0x75F26375), BN_DEF(0x54E710C3, 0xC3A3960A),
+ BN_DEF(0xBD0BE621, 0xDED4010A), BN_DEF(0x89962856, 0xC0B857F6),
+ BN_DEF(0x71506026, 0xB3CA3F79), BN_DEF(0xE6B486F6, 0x1CCACB83),
+ BN_DEF(0x14056425, 0x67E144E5), BN_DEF(0xA41825D9, 0xF6A167B5),
+ BN_DEF(0x96524D8E, 0x3AD83477), BN_DEF(0x51BFA4AB, 0xF13C6D9A),
+ BN_DEF(0x35488A0E, 0x2D525267), BN_DEF(0xCAA6B790, 0xB63ACAE1),
+ BN_DEF(0x81B23F76, 0x4FDB70C5), BN_DEF(0x12307F5C, 0xBC39A0BF),
+ BN_DEF(0xB1E59BB8, 0xB941F54E), BN_DEF(0xD45F9088, 0x6C5BFC11),
+ BN_DEF(0x4275BF7B, 0x22E0B1EF), BN_DEF(0x5B4758C0, 0x91F9E672),
+ BN_DEF(0x6BCF67ED, 0x5A8A9D30), BN_DEF(0x97517ABD, 0x209E0C64),
+ BN_DEF(0x830E9A7C, 0x3BF4296D), BN_DEF(0x34096FAA, 0x16C3D911),
+ BN_DEF(0x61B2AA30, 0xFAF7DF45), BN_DEF(0xD61957D4, 0xE00DF8F1),
+ BN_DEF(0x435E3B00, 0x5D2CEED4), BN_DEF(0x660DD0F2, 0x8CEEF608),
+ BN_DEF(0x65195999, 0xFFBBD19C), BN_DEF(0xB4B6663C, 0x87A8E61D)
};
-
static const BN_ULONG dh2048_256_q[] = {
- 0x64F5FBD3, 0xA308B0FE, 0x1EB3750B, 0x99B1A47D, 0x40129DA2, 0xB4479976,
- 0xA709A097, 0x8CF83642
+ BN_DEF(0x64F5FBD3, 0xA308B0FE), BN_DEF(0x1EB3750B, 0x99B1A47D),
+ BN_DEF(0x40129DA2, 0xB4479976), BN_DEF(0xA709A097, 0x8CF83642)
+};
+static const BN_ULONG dh2048_256_g[] = {
+ BN_DEF(0x6CC41659, 0x664B4C0F), BN_DEF(0xEF98C582, 0x5E2327CF),
+ BN_DEF(0xD4795451, 0xD647D148), BN_DEF(0x90F00EF8, 0x2F630784),
+ BN_DEF(0x1DB246C3, 0x184B523D), BN_DEF(0xCDC67EB6, 0xC7891428),
+ BN_DEF(0x0DF92B52, 0x7FD02837), BN_DEF(0x64E0EC37, 0xB3353BBB),
+ BN_DEF(0x57CD0915, 0xECD06E15), BN_DEF(0xDF016199, 0xB7D2BBD2),
+ BN_DEF(0x052588B9, 0xC8484B1E), BN_DEF(0x13D3FE14, 0xDB2A3B73),
+ BN_DEF(0xD182EA0A, 0xD052B985), BN_DEF(0xE83B9C80, 0xA4BD1BFF),
+ BN_DEF(0xFB3F2E55, 0xDFC967C1), BN_DEF(0x767164E1, 0xB5045AF2),
+ BN_DEF(0x6F2F9193, 0x1D14348F), BN_DEF(0x428EBC83, 0x64E67982),
+ BN_DEF(0x82D6ED38, 0x8AC376D2), BN_DEF(0xAAB8A862, 0x777DE62A),
+ BN_DEF(0xE9EC144B, 0xDDF463E5), BN_DEF(0xC77A57F2, 0x0196F931),
+ BN_DEF(0x41000A65, 0xA55AE313), BN_DEF(0xC28CBB18, 0x901228F8),
+ BN_DEF(0x7E8C6F62, 0xBC3773BF), BN_DEF(0x0C6B47B1, 0xBE3A6C1B),
+ BN_DEF(0xAC0BB555, 0xFF4FED4A), BN_DEF(0x77BE463F, 0x10DBC150),
+ BN_DEF(0x1A0BA125, 0x07F4793A), BN_DEF(0x21EF2054, 0x4CA7B18F),
+ BN_DEF(0x60EDBD48, 0x2E775066), BN_DEF(0x73134D0B, 0x3FB32C9B)
};
/* Primes from RFC 7919 */
-
static const BN_ULONG ffdhe2048_p[] = {
- 0xFFFFFFFF, 0xFFFFFFFF, 0x61285C97, 0x886B4238, 0xC1B2EFFA, 0xC6F34A26,
- 0x7D1683B2, 0xC58EF183, 0x2EC22005, 0x3BB5FCBC, 0x4C6FAD73, 0xC3FE3B1B,
- 0xEEF28183, 0x8E4F1232, 0xE98583FF, 0x9172FE9C, 0x28342F61, 0xC03404CD,
- 0xCDF7E2EC, 0x9E02FCE1, 0xEE0A6D70, 0x0B07A7C8, 0x6372BB19, 0xAE56EDE7,
- 0xDE394DF4, 0x1D4F42A3, 0x60D7F468, 0xB96ADAB7, 0xB2C8E3FB, 0xD108A94B,
- 0xB324FB61, 0xBC0AB182, 0x483A797A, 0x30ACCA4F, 0x36ADE735, 0x1DF158A1,
- 0xF3EFE872, 0xE2A689DA, 0xE0E68B77, 0x984F0C70, 0x7F57C935, 0xB557135E,
- 0x3DED1AF3, 0x85636555, 0x5F066ED0, 0x2433F51F, 0xD5FD6561, 0xD3DF1ED5,
- 0xAEC4617A, 0xF681B202, 0x630C75D8, 0x7D2FE363, 0x249B3EF9, 0xCC939DCE,
- 0x146433FB, 0xA9E13641, 0xCE2D3695, 0xD8B9C583, 0x273D3CF1, 0xAFDC5620,
- 0xA2BB4A9A, 0xADF85458, 0xFFFFFFFF, 0xFFFFFFFF
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x61285C97, 0x886B4238),
+ BN_DEF(0xC1B2EFFA, 0xC6F34A26), BN_DEF(0x7D1683B2, 0xC58EF183),
+ BN_DEF(0x2EC22005, 0x3BB5FCBC), BN_DEF(0x4C6FAD73, 0xC3FE3B1B),
+ BN_DEF(0xEEF28183, 0x8E4F1232), BN_DEF(0xE98583FF, 0x9172FE9C),
+ BN_DEF(0x28342F61, 0xC03404CD), BN_DEF(0xCDF7E2EC, 0x9E02FCE1),
+ BN_DEF(0xEE0A6D70, 0x0B07A7C8), BN_DEF(0x6372BB19, 0xAE56EDE7),
+ BN_DEF(0xDE394DF4, 0x1D4F42A3), BN_DEF(0x60D7F468, 0xB96ADAB7),
+ BN_DEF(0xB2C8E3FB, 0xD108A94B), BN_DEF(0xB324FB61, 0xBC0AB182),
+ BN_DEF(0x483A797A, 0x30ACCA4F), BN_DEF(0x36ADE735, 0x1DF158A1),
+ BN_DEF(0xF3EFE872, 0xE2A689DA), BN_DEF(0xE0E68B77, 0x984F0C70),
+ BN_DEF(0x7F57C935, 0xB557135E), BN_DEF(0x3DED1AF3, 0x85636555),
+ BN_DEF(0x5F066ED0, 0x2433F51F), BN_DEF(0xD5FD6561, 0xD3DF1ED5),
+ BN_DEF(0xAEC4617A, 0xF681B202), BN_DEF(0x630C75D8, 0x7D2FE363),
+ BN_DEF(0x249B3EF9, 0xCC939DCE), BN_DEF(0x146433FB, 0xA9E13641),
+ BN_DEF(0xCE2D3695, 0xD8B9C583), BN_DEF(0x273D3CF1, 0xAFDC5620),
+ BN_DEF(0xA2BB4A9A, 0xADF85458), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF)
+};
+/* q = (p - 1) / 2 */
+static const BN_ULONG ffdhe2048_q[] = {
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x30942E4B, 0x4435A11C),
+ BN_DEF(0x60D977FD, 0x6379A513), BN_DEF(0xBE8B41D9, 0xE2C778C1),
+ BN_DEF(0x17611002, 0x9DDAFE5E), BN_DEF(0xA637D6B9, 0xE1FF1D8D),
+ BN_DEF(0x777940C1, 0xC7278919), BN_DEF(0x74C2C1FF, 0xC8B97F4E),
+ BN_DEF(0x941A17B0, 0x601A0266), BN_DEF(0xE6FBF176, 0x4F017E70),
+ BN_DEF(0x770536B8, 0x8583D3E4), BN_DEF(0xB1B95D8C, 0x572B76F3),
+ BN_DEF(0xEF1CA6FA, 0x0EA7A151), BN_DEF(0xB06BFA34, 0xDCB56D5B),
+ BN_DEF(0xD96471FD, 0xE88454A5), BN_DEF(0x59927DB0, 0x5E0558C1),
+ BN_DEF(0xA41D3CBD, 0x98566527), BN_DEF(0x9B56F39A, 0x0EF8AC50),
+ BN_DEF(0x79F7F439, 0xF15344ED), BN_DEF(0x707345BB, 0xCC278638),
+ BN_DEF(0x3FABE49A, 0xDAAB89AF), BN_DEF(0x9EF68D79, 0x42B1B2AA),
+ BN_DEF(0xAF833768, 0x9219FA8F), BN_DEF(0xEAFEB2B0, 0x69EF8F6A),
+ BN_DEF(0x576230BD, 0x7B40D901), BN_DEF(0xB1863AEC, 0xBE97F1B1),
+ BN_DEF(0x124D9F7C, 0xE649CEE7), BN_DEF(0x8A3219FD, 0xD4F09B20),
+ BN_DEF(0xE7169B4A, 0xEC5CE2C1), BN_DEF(0x139E9E78, 0x57EE2B10),
+ BN_DEF(0x515DA54D, 0xD6FC2A2C), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF),
};
static const BN_ULONG ffdhe3072_p[] = {
- 0xFFFFFFFF, 0xFFFFFFFF, 0x66C62E37, 0x25E41D2B, 0x3FD59D7C, 0x3C1B20EE,
- 0xFA53DDEF, 0x0ABCD06B, 0xD5C4484E, 0x1DBF9A42, 0x9B0DEADA, 0xABC52197,
- 0x22363A0D, 0xE86D2BC5, 0x9C9DF69E, 0x5CAE82AB, 0x71F54BFF, 0x64F2E21E,
- 0xE2D74DD3, 0xF4FD4452, 0xBC437944, 0xB4130C93, 0x85139270, 0xAEFE1309,
- 0xC186D91C, 0x598CB0FA, 0x91F7F7EE, 0x7AD91D26, 0xD6E6C907, 0x61B46FC9,
- 0xF99C0238, 0xBC34F4DE, 0x6519035B, 0xDE355B3B, 0x611FCFDC, 0x886B4238,
- 0xC1B2EFFA, 0xC6F34A26, 0x7D1683B2, 0xC58EF183, 0x2EC22005, 0x3BB5FCBC,
- 0x4C6FAD73, 0xC3FE3B1B, 0xEEF28183, 0x8E4F1232, 0xE98583FF, 0x9172FE9C,
- 0x28342F61, 0xC03404CD, 0xCDF7E2EC, 0x9E02FCE1, 0xEE0A6D70, 0x0B07A7C8,
- 0x6372BB19, 0xAE56EDE7, 0xDE394DF4, 0x1D4F42A3, 0x60D7F468, 0xB96ADAB7,
- 0xB2C8E3FB, 0xD108A94B, 0xB324FB61, 0xBC0AB182, 0x483A797A, 0x30ACCA4F,
- 0x36ADE735, 0x1DF158A1, 0xF3EFE872, 0xE2A689DA, 0xE0E68B77, 0x984F0C70,
- 0x7F57C935, 0xB557135E, 0x3DED1AF3, 0x85636555, 0x5F066ED0, 0x2433F51F,
- 0xD5FD6561, 0xD3DF1ED5, 0xAEC4617A, 0xF681B202, 0x630C75D8, 0x7D2FE363,
- 0x249B3EF9, 0xCC939DCE, 0x146433FB, 0xA9E13641, 0xCE2D3695, 0xD8B9C583,
- 0x273D3CF1, 0xAFDC5620, 0xA2BB4A9A, 0xADF85458, 0xFFFFFFFF, 0xFFFFFFFF
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x66C62E37, 0x25E41D2B),
+ BN_DEF(0x3FD59D7C, 0x3C1B20EE), BN_DEF(0xFA53DDEF, 0x0ABCD06B),
+ BN_DEF(0xD5C4484E, 0x1DBF9A42), BN_DEF(0x9B0DEADA, 0xABC52197),
+ BN_DEF(0x22363A0D, 0xE86D2BC5), BN_DEF(0x9C9DF69E, 0x5CAE82AB),
+ BN_DEF(0x71F54BFF, 0x64F2E21E), BN_DEF(0xE2D74DD3, 0xF4FD4452),
+ BN_DEF(0xBC437944, 0xB4130C93), BN_DEF(0x85139270, 0xAEFE1309),
+ BN_DEF(0xC186D91C, 0x598CB0FA), BN_DEF(0x91F7F7EE, 0x7AD91D26),
+ BN_DEF(0xD6E6C907, 0x61B46FC9), BN_DEF(0xF99C0238, 0xBC34F4DE),
+ BN_DEF(0x6519035B, 0xDE355B3B), BN_DEF(0x611FCFDC, 0x886B4238),
+ BN_DEF(0xC1B2EFFA, 0xC6F34A26), BN_DEF(0x7D1683B2, 0xC58EF183),
+ BN_DEF(0x2EC22005, 0x3BB5FCBC), BN_DEF(0x4C6FAD73, 0xC3FE3B1B),
+ BN_DEF(0xEEF28183, 0x8E4F1232), BN_DEF(0xE98583FF, 0x9172FE9C),
+ BN_DEF(0x28342F61, 0xC03404CD), BN_DEF(0xCDF7E2EC, 0x9E02FCE1),
+ BN_DEF(0xEE0A6D70, 0x0B07A7C8), BN_DEF(0x6372BB19, 0xAE56EDE7),
+ BN_DEF(0xDE394DF4, 0x1D4F42A3), BN_DEF(0x60D7F468, 0xB96ADAB7),
+ BN_DEF(0xB2C8E3FB, 0xD108A94B), BN_DEF(0xB324FB61, 0xBC0AB182),
+ BN_DEF(0x483A797A, 0x30ACCA4F), BN_DEF(0x36ADE735, 0x1DF158A1),
+ BN_DEF(0xF3EFE872, 0xE2A689DA), BN_DEF(0xE0E68B77, 0x984F0C70),
+ BN_DEF(0x7F57C935, 0xB557135E), BN_DEF(0x3DED1AF3, 0x85636555),
+ BN_DEF(0x5F066ED0, 0x2433F51F), BN_DEF(0xD5FD6561, 0xD3DF1ED5),
+ BN_DEF(0xAEC4617A, 0xF681B202), BN_DEF(0x630C75D8, 0x7D2FE363),
+ BN_DEF(0x249B3EF9, 0xCC939DCE), BN_DEF(0x146433FB, 0xA9E13641),
+ BN_DEF(0xCE2D3695, 0xD8B9C583), BN_DEF(0x273D3CF1, 0xAFDC5620),
+ BN_DEF(0xA2BB4A9A, 0xADF85458), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF)
+};
+/* q = (p - 1) / 2 */
+static const BN_ULONG ffdhe3072_q[] = {
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0xB363171B, 0x12F20E95),
+ BN_DEF(0x1FEACEBE, 0x9E0D9077), BN_DEF(0xFD29EEF7, 0x055E6835),
+ BN_DEF(0x6AE22427, 0x0EDFCD21), BN_DEF(0xCD86F56D, 0xD5E290CB),
+ BN_DEF(0x911B1D06, 0x743695E2), BN_DEF(0xCE4EFB4F, 0xAE574155),
+ BN_DEF(0x38FAA5FF, 0xB279710F), BN_DEF(0x716BA6E9, 0x7A7EA229),
+ BN_DEF(0xDE21BCA2, 0x5A098649), BN_DEF(0xC289C938, 0x577F0984),
+ BN_DEF(0x60C36C8E, 0x2CC6587D), BN_DEF(0x48FBFBF7, 0xBD6C8E93),
+ BN_DEF(0xEB736483, 0x30DA37E4), BN_DEF(0x7CCE011C, 0xDE1A7A6F),
+ BN_DEF(0xB28C81AD, 0x6F1AAD9D), BN_DEF(0x308FE7EE, 0x4435A11C),
+ BN_DEF(0x60D977FD, 0x6379A513), BN_DEF(0xBE8B41D9, 0xE2C778C1),
+ BN_DEF(0x17611002, 0x9DDAFE5E), BN_DEF(0xA637D6B9, 0xE1FF1D8D),
+ BN_DEF(0x777940C1, 0xC7278919), BN_DEF(0x74C2C1FF, 0xC8B97F4E),
+ BN_DEF(0x941A17B0, 0x601A0266), BN_DEF(0xE6FBF176, 0x4F017E70),
+ BN_DEF(0x770536B8, 0x8583D3E4), BN_DEF(0xB1B95D8C, 0x572B76F3),
+ BN_DEF(0xEF1CA6FA, 0x0EA7A151), BN_DEF(0xB06BFA34, 0xDCB56D5B),
+ BN_DEF(0xD96471FD, 0xE88454A5), BN_DEF(0x59927DB0, 0x5E0558C1),
+ BN_DEF(0xA41D3CBD, 0x98566527), BN_DEF(0x9B56F39A, 0x0EF8AC50),
+ BN_DEF(0x79F7F439, 0xF15344ED), BN_DEF(0x707345BB, 0xCC278638),
+ BN_DEF(0x3FABE49A, 0xDAAB89AF), BN_DEF(0x9EF68D79, 0x42B1B2AA),
+ BN_DEF(0xAF833768, 0x9219FA8F), BN_DEF(0xEAFEB2B0, 0x69EF8F6A),
+ BN_DEF(0x576230BD, 0x7B40D901), BN_DEF(0xB1863AEC, 0xBE97F1B1),
+ BN_DEF(0x124D9F7C, 0xE649CEE7), BN_DEF(0x8A3219FD, 0xD4F09B20),
+ BN_DEF(0xE7169B4A, 0xEC5CE2C1), BN_DEF(0x139E9E78, 0x57EE2B10),
+ BN_DEF(0x515DA54D, 0xD6FC2A2C), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF),
};
static const BN_ULONG ffdhe4096_p[] = {
- 0xFFFFFFFF, 0xFFFFFFFF, 0x5E655F6A, 0xC68A007E, 0xF44182E1, 0x4DB5A851,
- 0x7F88A46B, 0x8EC9B55A, 0xCEC97DCF, 0x0A8291CD, 0xF98D0ACC, 0x2A4ECEA9,
- 0x7140003C, 0x1A1DB93D, 0x33CB8B7A, 0x092999A3, 0x71AD0038, 0x6DC778F9,
- 0x918130C4, 0xA907600A, 0x2D9E6832, 0xED6A1E01, 0xEFB4318A, 0x7135C886,
- 0x7E31CC7A, 0x87F55BA5, 0x55034004, 0x7763CF1D, 0xD69F6D18, 0xAC7D5F42,
- 0xE58857B6, 0x7930E9E4, 0x164DF4FB, 0x6E6F52C3, 0x669E1EF1, 0x25E41D2B,
- 0x3FD59D7C, 0x3C1B20EE, 0xFA53DDEF, 0x0ABCD06B, 0xD5C4484E, 0x1DBF9A42,
- 0x9B0DEADA, 0xABC52197, 0x22363A0D, 0xE86D2BC5, 0x9C9DF69E, 0x5CAE82AB,
- 0x71F54BFF, 0x64F2E21E, 0xE2D74DD3, 0xF4FD4452, 0xBC437944, 0xB4130C93,
- 0x85139270, 0xAEFE1309, 0xC186D91C, 0x598CB0FA, 0x91F7F7EE, 0x7AD91D26,
- 0xD6E6C907, 0x61B46FC9, 0xF99C0238, 0xBC34F4DE, 0x6519035B, 0xDE355B3B,
- 0x611FCFDC, 0x886B4238, 0xC1B2EFFA, 0xC6F34A26, 0x7D1683B2, 0xC58EF183,
- 0x2EC22005, 0x3BB5FCBC, 0x4C6FAD73, 0xC3FE3B1B, 0xEEF28183, 0x8E4F1232,
- 0xE98583FF, 0x9172FE9C, 0x28342F61, 0xC03404CD, 0xCDF7E2EC, 0x9E02FCE1,
- 0xEE0A6D70, 0x0B07A7C8, 0x6372BB19, 0xAE56EDE7, 0xDE394DF4, 0x1D4F42A3,
- 0x60D7F468, 0xB96ADAB7, 0xB2C8E3FB, 0xD108A94B, 0xB324FB61, 0xBC0AB182,
- 0x483A797A, 0x30ACCA4F, 0x36ADE735, 0x1DF158A1, 0xF3EFE872, 0xE2A689DA,
- 0xE0E68B77, 0x984F0C70, 0x7F57C935, 0xB557135E, 0x3DED1AF3, 0x85636555,
- 0x5F066ED0, 0x2433F51F, 0xD5FD6561, 0xD3DF1ED5, 0xAEC4617A, 0xF681B202,
- 0x630C75D8, 0x7D2FE363, 0x249B3EF9, 0xCC939DCE, 0x146433FB, 0xA9E13641,
- 0xCE2D3695, 0xD8B9C583, 0x273D3CF1, 0xAFDC5620, 0xA2BB4A9A, 0xADF85458,
- 0xFFFFFFFF, 0xFFFFFFFF
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x5E655F6A, 0xC68A007E),
+ BN_DEF(0xF44182E1, 0x4DB5A851), BN_DEF(0x7F88A46B, 0x8EC9B55A),
+ BN_DEF(0xCEC97DCF, 0x0A8291CD), BN_DEF(0xF98D0ACC, 0x2A4ECEA9),
+ BN_DEF(0x7140003C, 0x1A1DB93D), BN_DEF(0x33CB8B7A, 0x092999A3),
+ BN_DEF(0x71AD0038, 0x6DC778F9), BN_DEF(0x918130C4, 0xA907600A),
+ BN_DEF(0x2D9E6832, 0xED6A1E01), BN_DEF(0xEFB4318A, 0x7135C886),
+ BN_DEF(0x7E31CC7A, 0x87F55BA5), BN_DEF(0x55034004, 0x7763CF1D),
+ BN_DEF(0xD69F6D18, 0xAC7D5F42), BN_DEF(0xE58857B6, 0x7930E9E4),
+ BN_DEF(0x164DF4FB, 0x6E6F52C3), BN_DEF(0x669E1EF1, 0x25E41D2B),
+ BN_DEF(0x3FD59D7C, 0x3C1B20EE), BN_DEF(0xFA53DDEF, 0x0ABCD06B),
+ BN_DEF(0xD5C4484E, 0x1DBF9A42), BN_DEF(0x9B0DEADA, 0xABC52197),
+ BN_DEF(0x22363A0D, 0xE86D2BC5), BN_DEF(0x9C9DF69E, 0x5CAE82AB),
+ BN_DEF(0x71F54BFF, 0x64F2E21E), BN_DEF(0xE2D74DD3, 0xF4FD4452),
+ BN_DEF(0xBC437944, 0xB4130C93), BN_DEF(0x85139270, 0xAEFE1309),
+ BN_DEF(0xC186D91C, 0x598CB0FA), BN_DEF(0x91F7F7EE, 0x7AD91D26),
+ BN_DEF(0xD6E6C907, 0x61B46FC9), BN_DEF(0xF99C0238, 0xBC34F4DE),
+ BN_DEF(0x6519035B, 0xDE355B3B), BN_DEF(0x611FCFDC, 0x886B4238),
+ BN_DEF(0xC1B2EFFA, 0xC6F34A26), BN_DEF(0x7D1683B2, 0xC58EF183),
+ BN_DEF(0x2EC22005, 0x3BB5FCBC), BN_DEF(0x4C6FAD73, 0xC3FE3B1B),
+ BN_DEF(0xEEF28183, 0x8E4F1232), BN_DEF(0xE98583FF, 0x9172FE9C),
+ BN_DEF(0x28342F61, 0xC03404CD), BN_DEF(0xCDF7E2EC, 0x9E02FCE1),
+ BN_DEF(0xEE0A6D70, 0x0B07A7C8), BN_DEF(0x6372BB19, 0xAE56EDE7),
+ BN_DEF(0xDE394DF4, 0x1D4F42A3), BN_DEF(0x60D7F468, 0xB96ADAB7),
+ BN_DEF(0xB2C8E3FB, 0xD108A94B), BN_DEF(0xB324FB61, 0xBC0AB182),
+ BN_DEF(0x483A797A, 0x30ACCA4F), BN_DEF(0x36ADE735, 0x1DF158A1),
+ BN_DEF(0xF3EFE872, 0xE2A689DA), BN_DEF(0xE0E68B77, 0x984F0C70),
+ BN_DEF(0x7F57C935, 0xB557135E), BN_DEF(0x3DED1AF3, 0x85636555),
+ BN_DEF(0x5F066ED0, 0x2433F51F), BN_DEF(0xD5FD6561, 0xD3DF1ED5),
+ BN_DEF(0xAEC4617A, 0xF681B202), BN_DEF(0x630C75D8, 0x7D2FE363),
+ BN_DEF(0x249B3EF9, 0xCC939DCE), BN_DEF(0x146433FB, 0xA9E13641),
+ BN_DEF(0xCE2D3695, 0xD8B9C583), BN_DEF(0x273D3CF1, 0xAFDC5620),
+ BN_DEF(0xA2BB4A9A, 0xADF85458), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF)
+};
+/* q = (p - 1) / 2 */
+static const BN_ULONG ffdhe4096_q[] = {
+ BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), BN_DEF(0x2F32AFB5, 0xE345003F),
+ BN_DEF(0xFA20C170, 0xA6DAD428), BN_DEF(0x3FC45235, 0xC764DAAD),
+ BN_DEF(0xE764BEE7, 0x054148E6), BN_DEF(0xFCC68566, 0x15276754),
+ BN_DEF(0xB8A0001E, 0x0D0EDC9E), BN_DEF(0x99E5C5BD, 0x0494CCD1),
+ BN_DEF(0xB8D6801C, 0x36E3BC7C), BN_DEF(0x48C09862, 0x5483B005),
+ BN_DEF(0x96CF3419, 0x76B50F00), BN_DEF(0x77DA18C5, 0x389AE443),
+ BN_DEF(0xBF18E63D, 0x43FAADD2), BN_DEF(0xAA81A002, 0x3BB1E78E),
+ BN_DEF(0x6B4FB68C, 0x563EAFA1), BN_DEF(0x72C42BDB, 0xBC9874F2),
+ BN_DEF(0x8B26FA7D, 0xB737A961), BN_DEF(0xB34F0F78, 0x12F20E95),
+ BN_DEF(0x1FEACEBE, 0x9E0D9077), BN_DEF(0xFD29EEF7, 0x055E6835),
+ BN_DEF(0x6AE22427, 0x0EDFCD21), BN_DEF(0xCD86F56D, 0xD5E290CB),
+ BN_DEF(0x911B1D06, 0x743695E2), BN_DEF(0xCE4EFB4F, 0xAE574155),
+ BN_DEF(0x38FAA5FF, 0xB279710F), BN_DEF(0x716BA6E9, 0x7A7EA229),
+ BN_DEF(0xDE21BCA2, 0x5A098649), BN_DEF(0xC289C938, 0x577F0984),
+ BN_DEF(0x60C36C8E, 0x2CC6587D), BN_DEF(0x48FBFBF7, 0xBD6C8E93),
+ BN_DEF(0xEB736483, 0x30DA37E4), BN_DEF(0x7CCE011C, 0xDE1A7A6F),
+ BN_DEF(0xB28C81AD, 0x6F1AAD9D), BN_DEF(0x308FE7EE, 0x4435A11C),
+ BN_DEF(0x60D977FD, 0x6379A513), BN_DEF(0xBE8B41D9, 0xE2C778C1),
+ BN_DEF(0x17611002, 0x9DDAFE5E), BN_DEF(0xA637D6B9, 0xE1FF1D8D),
+ BN_DEF(0x777940C1, 0xC7278919), BN_DEF(0x74C2C1FF, 0xC8B97F4E),
+ BN_DEF(0x941A17B0, 0x601A0266), BN_DEF(0xE6FBF176, 0x4F017E70),
+ BN_DEF(0x770536B8, 0x8583D3E4), BN_DEF(0xB1B95D8C, 0x572B76F3),
+ BN_DEF(0xEF1CA6FA, 0x0EA7A151), BN_DEF(0xB06BFA34, 0xDCB56D5B),
+ BN_DEF(0xD96471FD, 0xE88454A5), BN_DEF(0x59927DB0, 0x5E0558C1),
+ BN_DEF(0xA41D3CBD, 0x98566527), BN_DEF(0x9B56F39A, 0x0EF8AC50),
+ BN_DEF(0x79F7F439, 0xF15344ED), BN_DEF(0x707345BB, 0xCC278638),
+ BN_DEF(0x3FABE49A, 0xDAAB89AF), BN_DEF(0x9EF68D79, 0x42B1B2AA),
+ BN_DEF(0xAF833768, 0x9219FA8F), BN_DEF(0xEAFEB2B0, 0x69EF8F6A),
+ BN_DEF(0x576230BD, 0x7B40D901), BN_DEF(0xB1863AEC, 0xBE97F1B1),
+ BN_DEF(0x124D9F7C, 0xE649CEE7), BN_DEF(0x8A3219FD, 0xD4F09B20),
+ BN_DEF(0xE7169B4A, 0xEC5CE2C1), BN_DEF(0x139E9E78, 0x57EE2B10),
+ BN_DEF(0x515DA54D, 0xD6FC2A2C), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF),
};
static const BN_ULONG ffdhe6144_p[] = {
- 0xFFFFFFFF, 0xFFFFFFFF, 0xD0E40E65, 0xA40E329C, 0x7938DAD4, 0xA41D570D,
- 0xD43161C1, 0x62A69526, 0x9ADB1E69, 0x3FDD4A8E, 0xDC6B80D6, 0x5B3B71F9,
- 0xC6272B04, 0xEC9D1810, 0xCACEF403, 0x8CCF2DD5, 0xC95B9117, 0xE49F5235,
- 0xB854338A, 0x505DC82D, 0x1562A846, 0x62292C31, 0x6AE77F5E, 0xD72B0374,
- 0x462D538C, 0xF9C9091B, 0x47A67CBE, 0x0AE8DB58, 0x22611682, 0xB3A739C1,
- 0x2A281BF6, 0xEEAAC023, 0x77CAF992, 0x94C6651E, 0x94B2BBC1, 0x763E4E4B,
- 0x0077D9B4, 0x587E38DA, 0x183023C3, 0x7FB29F8C, 0xF9E3A26E, 0x0ABEC1FF,
- 0x350511E3, 0xA00EF092, 0xDB6340D8, 0xB855322E, 0xA9A96910, 0xA52471F7,
- 0x4CFDB477, 0x388147FB, 0x4E46041F, 0x9B1F5C3E, 0xFCCFEC71, 0xCDAD0657,
- 0x4C701C3A, 0xB38E8C33, 0xB1C0FD4C, 0x917BDD64, 0x9B7624C8, 0x3BB45432,
- 0xCAF53EA6, 0x23BA4442, 0x38532A3A, 0x4E677D2C, 0x45036C7A, 0x0BFD64B6,
- 0x5E0DD902, 0xC68A007E, 0xF44182E1, 0x4DB5A851, 0x7F88A46B, 0x8EC9B55A,
- 0xCEC97DCF, 0x0A8291CD, 0xF98D0ACC, 0x2A4ECEA9, 0x7140003C, 0x1A1DB93D,
- 0x33CB8B7A, 0x092999A3, 0x71AD0038, 0x6DC778F9, 0x918130C4, 0xA907600A,
- 0x2D9E6832, 0xED6A1E01, 0xEFB4318A, 0x7135C886, 0x7E31CC7A, 0x87F55BA5,
- 0x55034004, 0x7763CF1D, 0xD69F6D18, 0xAC7D5F42, 0xE58857B6, 0x7930E9E4,
- 0x164DF4FB, 0x6E6F52C3, 0x669E1EF1, 0x25E41D2B, 0x3FD59D7C, 0x3C1B20EE,
- 0xFA53DDEF, 0x0ABCD06B, 0xD5C4484E, 0x1DBF9A42, 0x9B0DEADA, 0xABC52197,
- 0x22363A0D, 0xE86D2BC5, 0x9C9DF69E, 0x5CAE82AB, 0x71F54BFF, 0x64F2E21E,
- 0xE2D74DD3, 0xF4FD4452, 0xBC437944, 0xB4130C93, 0x85139270, 0xAEFE1309,
- 0xC186D91C, 0x598CB0FA, 0x91F7F7EE, 0x7AD91D26, 0xD6E6C907, 0x61B46FC9,
- 0xF99C0238, 0xBC34F4DE, 0x6519035B, 0xDE355B3B, 0x611FCFDC, 0x886B4238,
- 0xC1B2EFFA, 0xC6F34A26, 0x7D1683B2, 0xC58EF183, 0x2EC22005, 0x3BB5FCBC,
- 0x4C6FAD73, 0xC3FE3B1B, 0xEEF28183, 0x8E4F1232, 0xE98583FF, 0x9172FE9C,
- 0x28342F61, 0xC03404CD, 0xCDF7E2EC, 0x9E02FCE1, 0xEE0A6D70, 0x0B07A7C8,
- 0x6372BB19, 0xAE56EDE7, 0xDE394DF4, 0x1D4F42A3, 0x60D7F468, 0xB96ADAB7,
- 0xB2C8E3FB, 0xD108A94B, 0xB324FB61, 0xBC0AB182, 0x483A797A, 0x30ACCA4F,
- 0x36ADE735, 0x1DF158A1, 0xF3EFE872, 0xE2A689DA, 0xE0E68B77, 0x984F0C70,
- 0x7F57C935, 0xB557135E, 0x3DED1AF3, 0x85636555, 0x5F066ED0, 0x2433F51F,
- 0xD5FD6561, 0xD3DF1ED5, 0xAEC4617A, 0xF681B202, 0x630C75D8, 0x7D2FE363,
- 0x249B3EF9, 0xCC939DCE, 0x146433FB, 0xA9E13641, 0xCE2D3695, 0xD8B9C583,
- 0x273D3CF1, 0xAFDC5620, 0xA2BB4A9A, 0xADF85458, 0xFFFFFFFF, 0xFFFFFFFF
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0xD0E40E65, 0xA40E329C),
+ BN_DEF(0x7938DAD4, 0xA41D570D), BN_DEF(0xD43161C1, 0x62A69526),
+ BN_DEF(0x9ADB1E69, 0x3FDD4A8E), BN_DEF(0xDC6B80D6, 0x5B3B71F9),
+ BN_DEF(0xC6272B04, 0xEC9D1810), BN_DEF(0xCACEF403, 0x8CCF2DD5),
+ BN_DEF(0xC95B9117, 0xE49F5235), BN_DEF(0xB854338A, 0x505DC82D),
+ BN_DEF(0x1562A846, 0x62292C31), BN_DEF(0x6AE77F5E, 0xD72B0374),
+ BN_DEF(0x462D538C, 0xF9C9091B), BN_DEF(0x47A67CBE, 0x0AE8DB58),
+ BN_DEF(0x22611682, 0xB3A739C1), BN_DEF(0x2A281BF6, 0xEEAAC023),
+ BN_DEF(0x77CAF992, 0x94C6651E), BN_DEF(0x94B2BBC1, 0x763E4E4B),
+ BN_DEF(0x0077D9B4, 0x587E38DA), BN_DEF(0x183023C3, 0x7FB29F8C),
+ BN_DEF(0xF9E3A26E, 0x0ABEC1FF), BN_DEF(0x350511E3, 0xA00EF092),
+ BN_DEF(0xDB6340D8, 0xB855322E), BN_DEF(0xA9A96910, 0xA52471F7),
+ BN_DEF(0x4CFDB477, 0x388147FB), BN_DEF(0x4E46041F, 0x9B1F5C3E),
+ BN_DEF(0xFCCFEC71, 0xCDAD0657), BN_DEF(0x4C701C3A, 0xB38E8C33),
+ BN_DEF(0xB1C0FD4C, 0x917BDD64), BN_DEF(0x9B7624C8, 0x3BB45432),
+ BN_DEF(0xCAF53EA6, 0x23BA4442), BN_DEF(0x38532A3A, 0x4E677D2C),
+ BN_DEF(0x45036C7A, 0x0BFD64B6), BN_DEF(0x5E0DD902, 0xC68A007E),
+ BN_DEF(0xF44182E1, 0x4DB5A851), BN_DEF(0x7F88A46B, 0x8EC9B55A),
+ BN_DEF(0xCEC97DCF, 0x0A8291CD), BN_DEF(0xF98D0ACC, 0x2A4ECEA9),
+ BN_DEF(0x7140003C, 0x1A1DB93D), BN_DEF(0x33CB8B7A, 0x092999A3),
+ BN_DEF(0x71AD0038, 0x6DC778F9), BN_DEF(0x918130C4, 0xA907600A),
+ BN_DEF(0x2D9E6832, 0xED6A1E01), BN_DEF(0xEFB4318A, 0x7135C886),
+ BN_DEF(0x7E31CC7A, 0x87F55BA5), BN_DEF(0x55034004, 0x7763CF1D),
+ BN_DEF(0xD69F6D18, 0xAC7D5F42), BN_DEF(0xE58857B6, 0x7930E9E4),
+ BN_DEF(0x164DF4FB, 0x6E6F52C3), BN_DEF(0x669E1EF1, 0x25E41D2B),
+ BN_DEF(0x3FD59D7C, 0x3C1B20EE), BN_DEF(0xFA53DDEF, 0x0ABCD06B),
+ BN_DEF(0xD5C4484E, 0x1DBF9A42), BN_DEF(0x9B0DEADA, 0xABC52197),
+ BN_DEF(0x22363A0D, 0xE86D2BC5), BN_DEF(0x9C9DF69E, 0x5CAE82AB),
+ BN_DEF(0x71F54BFF, 0x64F2E21E), BN_DEF(0xE2D74DD3, 0xF4FD4452),
+ BN_DEF(0xBC437944, 0xB4130C93), BN_DEF(0x85139270, 0xAEFE1309),
+ BN_DEF(0xC186D91C, 0x598CB0FA), BN_DEF(0x91F7F7EE, 0x7AD91D26),
+ BN_DEF(0xD6E6C907, 0x61B46FC9), BN_DEF(0xF99C0238, 0xBC34F4DE),
+ BN_DEF(0x6519035B, 0xDE355B3B), BN_DEF(0x611FCFDC, 0x886B4238),
+ BN_DEF(0xC1B2EFFA, 0xC6F34A26), BN_DEF(0x7D1683B2, 0xC58EF183),
+ BN_DEF(0x2EC22005, 0x3BB5FCBC), BN_DEF(0x4C6FAD73, 0xC3FE3B1B),
+ BN_DEF(0xEEF28183, 0x8E4F1232), BN_DEF(0xE98583FF, 0x9172FE9C),
+ BN_DEF(0x28342F61, 0xC03404CD), BN_DEF(0xCDF7E2EC, 0x9E02FCE1),
+ BN_DEF(0xEE0A6D70, 0x0B07A7C8), BN_DEF(0x6372BB19, 0xAE56EDE7),
+ BN_DEF(0xDE394DF4, 0x1D4F42A3), BN_DEF(0x60D7F468, 0xB96ADAB7),
+ BN_DEF(0xB2C8E3FB, 0xD108A94B), BN_DEF(0xB324FB61, 0xBC0AB182),
+ BN_DEF(0x483A797A, 0x30ACCA4F), BN_DEF(0x36ADE735, 0x1DF158A1),
+ BN_DEF(0xF3EFE872, 0xE2A689DA), BN_DEF(0xE0E68B77, 0x984F0C70),
+ BN_DEF(0x7F57C935, 0xB557135E), BN_DEF(0x3DED1AF3, 0x85636555),
+ BN_DEF(0x5F066ED0, 0x2433F51F), BN_DEF(0xD5FD6561, 0xD3DF1ED5),
+ BN_DEF(0xAEC4617A, 0xF681B202), BN_DEF(0x630C75D8, 0x7D2FE363),
+ BN_DEF(0x249B3EF9, 0xCC939DCE), BN_DEF(0x146433FB, 0xA9E13641),
+ BN_DEF(0xCE2D3695, 0xD8B9C583), BN_DEF(0x273D3CF1, 0xAFDC5620),
+ BN_DEF(0xA2BB4A9A, 0xADF85458), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF)
+};
+/* q = (p - 1) / 2 */
+static const BN_ULONG ffdhe6144_q[] = {
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x68720732, 0x5207194E),
+ BN_DEF(0xBC9C6D6A, 0xD20EAB86), BN_DEF(0x6A18B0E0, 0xB1534A93),
+ BN_DEF(0x4D6D8F34, 0x1FEEA547), BN_DEF(0xEE35C06B, 0x2D9DB8FC),
+ BN_DEF(0x63139582, 0xF64E8C08), BN_DEF(0xE5677A01, 0xC66796EA),
+ BN_DEF(0xE4ADC88B, 0x724FA91A), BN_DEF(0xDC2A19C5, 0x282EE416),
+ BN_DEF(0x8AB15423, 0x31149618), BN_DEF(0x3573BFAF, 0x6B9581BA),
+ BN_DEF(0xA316A9C6, 0x7CE4848D), BN_DEF(0x23D33E5F, 0x05746DAC),
+ BN_DEF(0x91308B41, 0x59D39CE0), BN_DEF(0x95140DFB, 0x77556011),
+ BN_DEF(0x3BE57CC9, 0xCA63328F), BN_DEF(0xCA595DE0, 0x3B1F2725),
+ BN_DEF(0x003BECDA, 0xAC3F1C6D), BN_DEF(0x0C1811E1, 0x3FD94FC6),
+ BN_DEF(0xFCF1D137, 0x855F60FF), BN_DEF(0x1A8288F1, 0x50077849),
+ BN_DEF(0x6DB1A06C, 0x5C2A9917), BN_DEF(0xD4D4B488, 0xD29238FB),
+ BN_DEF(0xA67EDA3B, 0x9C40A3FD), BN_DEF(0x2723020F, 0xCD8FAE1F),
+ BN_DEF(0xFE67F638, 0x66D6832B), BN_DEF(0xA6380E1D, 0x59C74619),
+ BN_DEF(0x58E07EA6, 0x48BDEEB2), BN_DEF(0x4DBB1264, 0x1DDA2A19),
+ BN_DEF(0x657A9F53, 0x11DD2221), BN_DEF(0x1C29951D, 0x2733BE96),
+ BN_DEF(0x2281B63D, 0x05FEB25B), BN_DEF(0x2F06EC81, 0xE345003F),
+ BN_DEF(0xFA20C170, 0xA6DAD428), BN_DEF(0x3FC45235, 0xC764DAAD),
+ BN_DEF(0xE764BEE7, 0x054148E6), BN_DEF(0xFCC68566, 0x15276754),
+ BN_DEF(0xB8A0001E, 0x0D0EDC9E), BN_DEF(0x99E5C5BD, 0x0494CCD1),
+ BN_DEF(0xB8D6801C, 0x36E3BC7C), BN_DEF(0x48C09862, 0x5483B005),
+ BN_DEF(0x96CF3419, 0x76B50F00), BN_DEF(0x77DA18C5, 0x389AE443),
+ BN_DEF(0xBF18E63D, 0x43FAADD2), BN_DEF(0xAA81A002, 0x3BB1E78E),
+ BN_DEF(0x6B4FB68C, 0x563EAFA1), BN_DEF(0x72C42BDB, 0xBC9874F2),
+ BN_DEF(0x8B26FA7D, 0xB737A961), BN_DEF(0xB34F0F78, 0x12F20E95),
+ BN_DEF(0x1FEACEBE, 0x9E0D9077), BN_DEF(0xFD29EEF7, 0x055E6835),
+ BN_DEF(0x6AE22427, 0x0EDFCD21), BN_DEF(0xCD86F56D, 0xD5E290CB),
+ BN_DEF(0x911B1D06, 0x743695E2), BN_DEF(0xCE4EFB4F, 0xAE574155),
+ BN_DEF(0x38FAA5FF, 0xB279710F), BN_DEF(0x716BA6E9, 0x7A7EA229),
+ BN_DEF(0xDE21BCA2, 0x5A098649), BN_DEF(0xC289C938, 0x577F0984),
+ BN_DEF(0x60C36C8E, 0x2CC6587D), BN_DEF(0x48FBFBF7, 0xBD6C8E93),
+ BN_DEF(0xEB736483, 0x30DA37E4), BN_DEF(0x7CCE011C, 0xDE1A7A6F),
+ BN_DEF(0xB28C81AD, 0x6F1AAD9D), BN_DEF(0x308FE7EE, 0x4435A11C),
+ BN_DEF(0x60D977FD, 0x6379A513), BN_DEF(0xBE8B41D9, 0xE2C778C1),
+ BN_DEF(0x17611002, 0x9DDAFE5E), BN_DEF(0xA637D6B9, 0xE1FF1D8D),
+ BN_DEF(0x777940C1, 0xC7278919), BN_DEF(0x74C2C1FF, 0xC8B97F4E),
+ BN_DEF(0x941A17B0, 0x601A0266), BN_DEF(0xE6FBF176, 0x4F017E70),
+ BN_DEF(0x770536B8, 0x8583D3E4), BN_DEF(0xB1B95D8C, 0x572B76F3),
+ BN_DEF(0xEF1CA6FA, 0x0EA7A151), BN_DEF(0xB06BFA34, 0xDCB56D5B),
+ BN_DEF(0xD96471FD, 0xE88454A5), BN_DEF(0x59927DB0, 0x5E0558C1),
+ BN_DEF(0xA41D3CBD, 0x98566527), BN_DEF(0x9B56F39A, 0x0EF8AC50),
+ BN_DEF(0x79F7F439, 0xF15344ED), BN_DEF(0x707345BB, 0xCC278638),
+ BN_DEF(0x3FABE49A, 0xDAAB89AF), BN_DEF(0x9EF68D79, 0x42B1B2AA),
+ BN_DEF(0xAF833768, 0x9219FA8F), BN_DEF(0xEAFEB2B0, 0x69EF8F6A),
+ BN_DEF(0x576230BD, 0x7B40D901), BN_DEF(0xB1863AEC, 0xBE97F1B1),
+ BN_DEF(0x124D9F7C, 0xE649CEE7), BN_DEF(0x8A3219FD, 0xD4F09B20),
+ BN_DEF(0xE7169B4A, 0xEC5CE2C1), BN_DEF(0x139E9E78, 0x57EE2B10),
+ BN_DEF(0x515DA54D, 0xD6FC2A2C), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF),
};
static const BN_ULONG ffdhe8192_p[] = {
- 0xFFFFFFFF, 0xFFFFFFFF, 0xC5C6424C, 0xD68C8BB7, 0x838FF88C, 0x011E2A94,
- 0xA9F4614E, 0x0822E506, 0xF7A8443D, 0x97D11D49, 0x30677F0D, 0xA6BBFDE5,
- 0xC1FE86FE, 0x2F741EF8, 0x5D71A87E, 0xFAFABE1C, 0xFBE58A30, 0xDED2FBAB,
- 0x72B0A66E, 0xB6855DFE, 0xBA8A4FE8, 0x1EFC8CE0, 0x3F2FA457, 0x83F81D4A,
- 0xA577E231, 0xA1FE3075, 0x88D9C0A0, 0xD5B80194, 0xAD9A95F9, 0x624816CD,
- 0x50C1217B, 0x99E9E316, 0x0E423CFC, 0x51AA691E, 0x3826E52C, 0x1C217E6C,
- 0x09703FEE, 0x51A8A931, 0x6A460E74, 0xBB709987, 0x9C86B022, 0x541FC68C,
- 0x46FD8251, 0x59160CC0, 0x35C35F5C, 0x2846C0BA, 0x8B758282, 0x54504AC7,
- 0xD2AF05E4, 0x29388839, 0xC01BD702, 0xCB2C0F1C, 0x7C932665, 0x555B2F74,
- 0xA3AB8829, 0x86B63142, 0xF64B10EF, 0x0B8CC3BD, 0xEDD1CC5E, 0x687FEB69,
- 0xC9509D43, 0xFDB23FCE, 0xD951AE64, 0x1E425A31, 0xF600C838, 0x36AD004C,
- 0xCFF46AAA, 0xA40E329C, 0x7938DAD4, 0xA41D570D, 0xD43161C1, 0x62A69526,
- 0x9ADB1E69, 0x3FDD4A8E, 0xDC6B80D6, 0x5B3B71F9, 0xC6272B04, 0xEC9D1810,
- 0xCACEF403, 0x8CCF2DD5, 0xC95B9117, 0xE49F5235, 0xB854338A, 0x505DC82D,
- 0x1562A846, 0x62292C31, 0x6AE77F5E, 0xD72B0374, 0x462D538C, 0xF9C9091B,
- 0x47A67CBE, 0x0AE8DB58, 0x22611682, 0xB3A739C1, 0x2A281BF6, 0xEEAAC023,
- 0x77CAF992, 0x94C6651E, 0x94B2BBC1, 0x763E4E4B, 0x0077D9B4, 0x587E38DA,
- 0x183023C3, 0x7FB29F8C, 0xF9E3A26E, 0x0ABEC1FF, 0x350511E3, 0xA00EF092,
- 0xDB6340D8, 0xB855322E, 0xA9A96910, 0xA52471F7, 0x4CFDB477, 0x388147FB,
- 0x4E46041F, 0x9B1F5C3E, 0xFCCFEC71, 0xCDAD0657, 0x4C701C3A, 0xB38E8C33,
- 0xB1C0FD4C, 0x917BDD64, 0x9B7624C8, 0x3BB45432, 0xCAF53EA6, 0x23BA4442,
- 0x38532A3A, 0x4E677D2C, 0x45036C7A, 0x0BFD64B6, 0x5E0DD902, 0xC68A007E,
- 0xF44182E1, 0x4DB5A851, 0x7F88A46B, 0x8EC9B55A, 0xCEC97DCF, 0x0A8291CD,
- 0xF98D0ACC, 0x2A4ECEA9, 0x7140003C, 0x1A1DB93D, 0x33CB8B7A, 0x092999A3,
- 0x71AD0038, 0x6DC778F9, 0x918130C4, 0xA907600A, 0x2D9E6832, 0xED6A1E01,
- 0xEFB4318A, 0x7135C886, 0x7E31CC7A, 0x87F55BA5, 0x55034004, 0x7763CF1D,
- 0xD69F6D18, 0xAC7D5F42, 0xE58857B6, 0x7930E9E4, 0x164DF4FB, 0x6E6F52C3,
- 0x669E1EF1, 0x25E41D2B, 0x3FD59D7C, 0x3C1B20EE, 0xFA53DDEF, 0x0ABCD06B,
- 0xD5C4484E, 0x1DBF9A42, 0x9B0DEADA, 0xABC52197, 0x22363A0D, 0xE86D2BC5,
- 0x9C9DF69E, 0x5CAE82AB, 0x71F54BFF, 0x64F2E21E, 0xE2D74DD3, 0xF4FD4452,
- 0xBC437944, 0xB4130C93, 0x85139270, 0xAEFE1309, 0xC186D91C, 0x598CB0FA,
- 0x91F7F7EE, 0x7AD91D26, 0xD6E6C907, 0x61B46FC9, 0xF99C0238, 0xBC34F4DE,
- 0x6519035B, 0xDE355B3B, 0x611FCFDC, 0x886B4238, 0xC1B2EFFA, 0xC6F34A26,
- 0x7D1683B2, 0xC58EF183, 0x2EC22005, 0x3BB5FCBC, 0x4C6FAD73, 0xC3FE3B1B,
- 0xEEF28183, 0x8E4F1232, 0xE98583FF, 0x9172FE9C, 0x28342F61, 0xC03404CD,
- 0xCDF7E2EC, 0x9E02FCE1, 0xEE0A6D70, 0x0B07A7C8, 0x6372BB19, 0xAE56EDE7,
- 0xDE394DF4, 0x1D4F42A3, 0x60D7F468, 0xB96ADAB7, 0xB2C8E3FB, 0xD108A94B,
- 0xB324FB61, 0xBC0AB182, 0x483A797A, 0x30ACCA4F, 0x36ADE735, 0x1DF158A1,
- 0xF3EFE872, 0xE2A689DA, 0xE0E68B77, 0x984F0C70, 0x7F57C935, 0xB557135E,
- 0x3DED1AF3, 0x85636555, 0x5F066ED0, 0x2433F51F, 0xD5FD6561, 0xD3DF1ED5,
- 0xAEC4617A, 0xF681B202, 0x630C75D8, 0x7D2FE363, 0x249B3EF9, 0xCC939DCE,
- 0x146433FB, 0xA9E13641, 0xCE2D3695, 0xD8B9C583, 0x273D3CF1, 0xAFDC5620,
- 0xA2BB4A9A, 0xADF85458, 0xFFFFFFFF, 0xFFFFFFFF
+ BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0xC5C6424C, 0xD68C8BB7),
+ BN_DEF(0x838FF88C, 0x011E2A94), BN_DEF(0xA9F4614E, 0x0822E506),
+ BN_DEF(0xF7A8443D, 0x97D11D49), BN_DEF(0x30677F0D, 0xA6BBFDE5),
+ BN_DEF(0xC1FE86FE, 0x2F741EF8), BN_DEF(0x5D71A87E, 0xFAFABE1C),
+ BN_DEF(0xFBE58A30, 0xDED2FBAB), BN_DEF(0x72B0A66E, 0xB6855DFE),
+ BN_DEF(0xBA8A4FE8, 0x1EFC8CE0), BN_DEF(0x3F2FA457, 0x83F81D4A),
+ BN_DEF(0xA577E231, 0xA1FE3075), BN_DEF(0x88D9C0A0, 0xD5B80194),
+ BN_DEF(0xAD9A95F9, 0x624816CD), BN_DEF(0x50C1217B, 0x99E9E316),
+ BN_DEF(0x0E423CFC, 0x51AA691E), BN_DEF(0x3826E52C, 0x1C217E6C),
+ BN_DEF(0x09703FEE, 0x51A8A931), BN_DEF(0x6A460E74, 0xBB709987),
+ BN_DEF(0x9C86B022, 0x541FC68C), BN_DEF(0x46FD8251, 0x59160CC0),
+ BN_DEF(0x35C35F5C, 0x2846C0BA), BN_DEF(0x8B758282, 0x54504AC7),
+ BN_DEF(0xD2AF05E4, 0x29388839), BN_DEF(0xC01BD702, 0xCB2C0F1C),
+ BN_DEF(0x7C932665, 0x555B2F74), BN_DEF(0xA3AB8829, 0x86B63142),
+ BN_DEF(0xF64B10EF, 0x0B8CC3BD), BN_DEF(0xEDD1CC5E, 0x687FEB69),
+ BN_DEF(0xC9509D43, 0xFDB23FCE), BN_DEF(0xD951AE64, 0x1E425A31),
+ BN_DEF(0xF600C838, 0x36AD004C), BN_DEF(0xCFF46AAA, 0xA40E329C),
+ BN_DEF(0x7938DAD4, 0xA41D570D), BN_DEF(0xD43161C1, 0x62A69526),
+ BN_DEF(0x9ADB1E69, 0x3FDD4A8E), BN_DEF(0xDC6B80D6, 0x5B3B71F9),
+ BN_DEF(0xC6272B04, 0xEC9D1810), BN_DEF(0xCACEF403, 0x8CCF2DD5),
+ BN_DEF(0xC95B9117, 0xE49F5235), BN_DEF(0xB854338A, 0x505DC82D),
+ BN_DEF(0x1562A846, 0x62292C31), BN_DEF(0x6AE77F5E, 0xD72B0374),
+ BN_DEF(0x462D538C, 0xF9C9091B), BN_DEF(0x47A67CBE, 0x0AE8DB58),
+ BN_DEF(0x22611682, 0xB3A739C1), BN_DEF(0x2A281BF6, 0xEEAAC023),
+ BN_DEF(0x77CAF992, 0x94C6651E), BN_DEF(0x94B2BBC1, 0x763E4E4B),
+ BN_DEF(0x0077D9B4, 0x587E38DA), BN_DEF(0x183023C3, 0x7FB29F8C),
+ BN_DEF(0xF9E3A26E, 0x0ABEC1FF), BN_DEF(0x350511E3, 0xA00EF092),
+ BN_DEF(0xDB6340D8, 0xB855322E), BN_DEF(0xA9A96910, 0xA52471F7),
+ BN_DEF(0x4CFDB477, 0x388147FB), BN_DEF(0x4E46041F, 0x9B1F5C3E),
+ BN_DEF(0xFCCFEC71, 0xCDAD0657), BN_DEF(0x4C701C3A, 0xB38E8C33),
+ BN_DEF(0xB1C0FD4C, 0x917BDD64), BN_DEF(0x9B7624C8, 0x3BB45432),
+ BN_DEF(0xCAF53EA6, 0x23BA4442), BN_DEF(0x38532A3A, 0x4E677D2C),
+ BN_DEF(0x45036C7A, 0x0BFD64B6), BN_DEF(0x5E0DD902, 0xC68A007E),
+ BN_DEF(0xF44182E1, 0x4DB5A851), BN_DEF(0x7F88A46B, 0x8EC9B55A),
+ BN_DEF(0xCEC97DCF, 0x0A8291CD), BN_DEF(0xF98D0ACC, 0x2A4ECEA9),
+ BN_DEF(0x7140003C, 0x1A1DB93D), BN_DEF(0x33CB8B7A, 0x092999A3),
+ BN_DEF(0x71AD0038, 0x6DC778F9), BN_DEF(0x918130C4, 0xA907600A),
+ BN_DEF(0x2D9E6832, 0xED6A1E01), BN_DEF(0xEFB4318A, 0x7135C886),
+ BN_DEF(0x7E31CC7A, 0x87F55BA5), BN_DEF(0x55034004, 0x7763CF1D),
+ BN_DEF(0xD69F6D18, 0xAC7D5F42), BN_DEF(0xE58857B6, 0x7930E9E4),
+ BN_DEF(0x164DF4FB, 0x6E6F52C3), BN_DEF(0x669E1EF1, 0x25E41D2B),
+ BN_DEF(0x3FD59D7C, 0x3C1B20EE), BN_DEF(0xFA53DDEF, 0x0ABCD06B),
+ BN_DEF(0xD5C4484E, 0x1DBF9A42), BN_DEF(0x9B0DEADA, 0xABC52197),
+ BN_DEF(0x22363A0D, 0xE86D2BC5), BN_DEF(0x9C9DF69E, 0x5CAE82AB),
+ BN_DEF(0x71F54BFF, 0x64F2E21E), BN_DEF(0xE2D74DD3, 0xF4FD4452),
+ BN_DEF(0xBC437944, 0xB4130C93), BN_DEF(0x85139270, 0xAEFE1309),
+ BN_DEF(0xC186D91C, 0x598CB0FA), BN_DEF(0x91F7F7EE, 0x7AD91D26),
+ BN_DEF(0xD6E6C907, 0x61B46FC9), BN_DEF(0xF99C0238, 0xBC34F4DE),
+ BN_DEF(0x6519035B, 0xDE355B3B), BN_DEF(0x611FCFDC, 0x886B4238),
+ BN_DEF(0xC1B2EFFA, 0xC6F34A26), BN_DEF(0x7D1683B2, 0xC58EF183),
+ BN_DEF(0x2EC22005, 0x3BB5FCBC), BN_DEF(0x4C6FAD73, 0xC3FE3B1B),
+ BN_DEF(0xEEF28183, 0x8E4F1232), BN_DEF(0xE98583FF, 0x9172FE9C),
+ BN_DEF(0x28342F61, 0xC03404CD), BN_DEF(0xCDF7E2EC, 0x9E02FCE1),
+ BN_DEF(0xEE0A6D70, 0x0B07A7C8), BN_DEF(0x6372BB19, 0xAE56EDE7),
+ BN_DEF(0xDE394DF4, 0x1D4F42A3), BN_DEF(0x60D7F468, 0xB96ADAB7),
+ BN_DEF(0xB2C8E3FB, 0xD108A94B), BN_DEF(0xB324FB61, 0xBC0AB182),
+ BN_DEF(0x483A797A, 0x30ACCA4F), BN_DEF(0x36ADE735, 0x1DF158A1),
+ BN_DEF(0xF3EFE872, 0xE2A689DA), BN_DEF(0xE0E68B77, 0x984F0C70),
+ BN_DEF(0x7F57C935, 0xB557135E), BN_DEF(0x3DED1AF3, 0x85636555),
+ BN_DEF(0x5F066ED0, 0x2433F51F), BN_DEF(0xD5FD6561, 0xD3DF1ED5),
+ BN_DEF(0xAEC4617A, 0xF681B202), BN_DEF(0x630C75D8, 0x7D2FE363),
+ BN_DEF(0x249B3EF9, 0xCC939DCE), BN_DEF(0x146433FB, 0xA9E13641),
+ BN_DEF(0xCE2D3695, 0xD8B9C583), BN_DEF(0x273D3CF1, 0xAFDC5620),
+ BN_DEF(0xA2BB4A9A, 0xADF85458), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF)
+};
+/* q = (p - 1) / 2 */
+static const BN_ULONG ffdhe8192_q[] = {
+ BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), BN_DEF(0xE2E32126, 0x6B4645DB),
+ BN_DEF(0x41C7FC46, 0x008F154A), BN_DEF(0x54FA30A7, 0x84117283),
+ BN_DEF(0xFBD4221E, 0xCBE88EA4), BN_DEF(0x9833BF86, 0x535DFEF2),
+ BN_DEF(0x60FF437F, 0x17BA0F7C), BN_DEF(0x2EB8D43F, 0x7D7D5F0E),
+ BN_DEF(0xFDF2C518, 0x6F697DD5), BN_DEF(0x39585337, 0x5B42AEFF),
+ BN_DEF(0x5D4527F4, 0x8F7E4670), BN_DEF(0x1F97D22B, 0xC1FC0EA5),
+ BN_DEF(0xD2BBF118, 0x50FF183A), BN_DEF(0x446CE050, 0xEADC00CA),
+ BN_DEF(0xD6CD4AFC, 0xB1240B66), BN_DEF(0x286090BD, 0x4CF4F18B),
+ BN_DEF(0x07211E7E, 0x28D5348F), BN_DEF(0x1C137296, 0x0E10BF36),
+ BN_DEF(0x84B81FF7, 0x28D45498), BN_DEF(0xB523073A, 0x5DB84CC3),
+ BN_DEF(0x4E435811, 0xAA0FE346), BN_DEF(0x237EC128, 0x2C8B0660),
+ BN_DEF(0x1AE1AFAE, 0x1423605D), BN_DEF(0xC5BAC141, 0x2A282563),
+ BN_DEF(0xE95782F2, 0x149C441C), BN_DEF(0x600DEB81, 0xE596078E),
+ BN_DEF(0x3E499332, 0xAAAD97BA), BN_DEF(0x51D5C414, 0xC35B18A1),
+ BN_DEF(0xFB258877, 0x05C661DE), BN_DEF(0xF6E8E62F, 0xB43FF5B4),
+ BN_DEF(0x64A84EA1, 0x7ED91FE7), BN_DEF(0xECA8D732, 0x0F212D18),
+ BN_DEF(0x7B00641C, 0x1B568026), BN_DEF(0x67FA3555, 0x5207194E),
+ BN_DEF(0xBC9C6D6A, 0xD20EAB86), BN_DEF(0x6A18B0E0, 0xB1534A93),
+ BN_DEF(0x4D6D8F34, 0x1FEEA547), BN_DEF(0xEE35C06B, 0x2D9DB8FC),
+ BN_DEF(0x63139582, 0xF64E8C08), BN_DEF(0xE5677A01, 0xC66796EA),
+ BN_DEF(0xE4ADC88B, 0x724FA91A), BN_DEF(0xDC2A19C5, 0x282EE416),
+ BN_DEF(0x8AB15423, 0x31149618), BN_DEF(0x3573BFAF, 0x6B9581BA),
+ BN_DEF(0xA316A9C6, 0x7CE4848D), BN_DEF(0x23D33E5F, 0x05746DAC),
+ BN_DEF(0x91308B41, 0x59D39CE0), BN_DEF(0x95140DFB, 0x77556011),
+ BN_DEF(0x3BE57CC9, 0xCA63328F), BN_DEF(0xCA595DE0, 0x3B1F2725),
+ BN_DEF(0x003BECDA, 0xAC3F1C6D), BN_DEF(0x0C1811E1, 0x3FD94FC6),
+ BN_DEF(0xFCF1D137, 0x855F60FF), BN_DEF(0x1A8288F1, 0x50077849),
+ BN_DEF(0x6DB1A06C, 0x5C2A9917), BN_DEF(0xD4D4B488, 0xD29238FB),
+ BN_DEF(0xA67EDA3B, 0x9C40A3FD), BN_DEF(0x2723020F, 0xCD8FAE1F),
+ BN_DEF(0xFE67F638, 0x66D6832B), BN_DEF(0xA6380E1D, 0x59C74619),
+ BN_DEF(0x58E07EA6, 0x48BDEEB2), BN_DEF(0x4DBB1264, 0x1DDA2A19),
+ BN_DEF(0x657A9F53, 0x11DD2221), BN_DEF(0x1C29951D, 0x2733BE96),
+ BN_DEF(0x2281B63D, 0x05FEB25B), BN_DEF(0x2F06EC81, 0xE345003F),
+ BN_DEF(0xFA20C170, 0xA6DAD428), BN_DEF(0x3FC45235, 0xC764DAAD),
+ BN_DEF(0xE764BEE7, 0x054148E6), BN_DEF(0xFCC68566, 0x15276754),
+ BN_DEF(0xB8A0001E, 0x0D0EDC9E), BN_DEF(0x99E5C5BD, 0x0494CCD1),
+ BN_DEF(0xB8D6801C, 0x36E3BC7C), BN_DEF(0x48C09862, 0x5483B005),
+ BN_DEF(0x96CF3419, 0x76B50F00), BN_DEF(0x77DA18C5, 0x389AE443),
+ BN_DEF(0xBF18E63D, 0x43FAADD2), BN_DEF(0xAA81A002, 0x3BB1E78E),
+ BN_DEF(0x6B4FB68C, 0x563EAFA1), BN_DEF(0x72C42BDB, 0xBC9874F2),
+ BN_DEF(0x8B26FA7D, 0xB737A961), BN_DEF(0xB34F0F78, 0x12F20E95),
+ BN_DEF(0x1FEACEBE, 0x9E0D9077), BN_DEF(0xFD29EEF7, 0x055E6835),
+ BN_DEF(0x6AE22427, 0x0EDFCD21), BN_DEF(0xCD86F56D, 0xD5E290CB),
+ BN_DEF(0x911B1D06, 0x743695E2), BN_DEF(0xCE4EFB4F, 0xAE574155),
+ BN_DEF(0x38FAA5FF, 0xB279710F), BN_DEF(0x716BA6E9, 0x7A7EA229),
+ BN_DEF(0xDE21BCA2, 0x5A098649), BN_DEF(0xC289C938, 0x577F0984),
+ BN_DEF(0x60C36C8E, 0x2CC6587D), BN_DEF(0x48FBFBF7, 0xBD6C8E93),
+ BN_DEF(0xEB736483, 0x30DA37E4), BN_DEF(0x7CCE011C, 0xDE1A7A6F),
+ BN_DEF(0xB28C81AD, 0x6F1AAD9D), BN_DEF(0x308FE7EE, 0x4435A11C),
+ BN_DEF(0x60D977FD, 0x6379A513), BN_DEF(0xBE8B41D9, 0xE2C778C1),
+ BN_DEF(0x17611002, 0x9DDAFE5E), BN_DEF(0xA637D6B9, 0xE1FF1D8D),
+ BN_DEF(0x777940C1, 0xC7278919), BN_DEF(0x74C2C1FF, 0xC8B97F4E),
+ BN_DEF(0x941A17B0, 0x601A0266), BN_DEF(0xE6FBF176, 0x4F017E70),
+ BN_DEF(0x770536B8, 0x8583D3E4), BN_DEF(0xB1B95D8C, 0x572B76F3),
+ BN_DEF(0xEF1CA6FA, 0x0EA7A151), BN_DEF(0xB06BFA34, 0xDCB56D5B),
+ BN_DEF(0xD96471FD, 0xE88454A5), BN_DEF(0x59927DB0, 0x5E0558C1),
+ BN_DEF(0xA41D3CBD, 0x98566527), BN_DEF(0x9B56F39A, 0x0EF8AC50),
+ BN_DEF(0x79F7F439, 0xF15344ED), BN_DEF(0x707345BB, 0xCC278638),
+ BN_DEF(0x3FABE49A, 0xDAAB89AF), BN_DEF(0x9EF68D79, 0x42B1B2AA),
+ BN_DEF(0xAF833768, 0x9219FA8F), BN_DEF(0xEAFEB2B0, 0x69EF8F6A),
+ BN_DEF(0x576230BD, 0x7B40D901), BN_DEF(0xB1863AEC, 0xBE97F1B1),
+ BN_DEF(0x124D9F7C, 0xE649CEE7), BN_DEF(0x8A3219FD, 0xD4F09B20),
+ BN_DEF(0xE7169B4A, 0xEC5CE2C1), BN_DEF(0x139E9E78, 0x57EE2B10),
+ BN_DEF(0x515DA54D, 0xD6FC2A2C), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF),
};
-
-# else
-# error "unsupported BN_BITS2"
-# endif
/* Macro to make a BIGNUM from static data */
-# define make_dh_bn(x) extern const BIGNUM _bignum_##x; \
- const BIGNUM _bignum_##x = { (BN_ULONG *) x, \
- OSSL_NELEM(x),\
- OSSL_NELEM(x),\
- 0, BN_FLG_STATIC_DATA };
+# define make_dh_bn(x) \
+ extern const BIGNUM ossl_bignum_##x; \
+ const BIGNUM ossl_bignum_##x = { \
+ (BN_ULONG *) x, \
+ OSSL_NELEM(x), \
+ OSSL_NELEM(x), \
+ 0, BN_FLG_STATIC_DATA };
static const BN_ULONG value_2 = 2;
-const BIGNUM _bignum_const_2 =
- { (BN_ULONG *)&value_2, 1, 1, 0, BN_FLG_STATIC_DATA };
+const BIGNUM ossl_bignum_const_2 = {
+ (BN_ULONG *)&value_2, 1, 1, 0, BN_FLG_STATIC_DATA
+};
make_dh_bn(dh1024_160_p)
-make_dh_bn(dh1024_160_g)
make_dh_bn(dh1024_160_q)
+make_dh_bn(dh1024_160_g)
make_dh_bn(dh2048_224_p)
-make_dh_bn(dh2048_224_g)
make_dh_bn(dh2048_224_q)
+make_dh_bn(dh2048_224_g)
make_dh_bn(dh2048_256_p)
-make_dh_bn(dh2048_256_g)
make_dh_bn(dh2048_256_q)
+make_dh_bn(dh2048_256_g)
make_dh_bn(ffdhe2048_p)
+make_dh_bn(ffdhe2048_q)
make_dh_bn(ffdhe3072_p)
+make_dh_bn(ffdhe3072_q)
make_dh_bn(ffdhe4096_p)
+make_dh_bn(ffdhe4096_q)
make_dh_bn(ffdhe6144_p)
+make_dh_bn(ffdhe6144_q)
make_dh_bn(ffdhe8192_p)
+make_dh_bn(ffdhe8192_q)
-
-#endif
+# ifndef FIPS_MODULE
+make_dh_bn(modp_1536_p)
+make_dh_bn(modp_1536_q)
+# endif
+make_dh_bn(modp_2048_p)
+make_dh_bn(modp_2048_q)
+make_dh_bn(modp_3072_p)
+make_dh_bn(modp_3072_q)
+make_dh_bn(modp_4096_p)
+make_dh_bn(modp_4096_q)
+make_dh_bn(modp_6144_p)
+make_dh_bn(modp_6144_q)
+make_dh_bn(modp_8192_p)
+make_dh_bn(modp_8192_q)
diff --git a/crypto/bn/bn_div.c b/crypto/bn/bn_div.c
index 4273618825cc..ff66baa48f22 100644
--- a/crypto/bn/bn_div.c
+++ b/crypto/bn/bn_div.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -24,7 +24,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
bn_check_top(m);
bn_check_top(d);
if (BN_is_zero(d)) {
- BNerr(BN_F_BN_DIV, BN_R_DIV_BY_ZERO);
+ ERR_raise(ERR_LIB_BN, BN_R_DIV_BY_ZERO);
return 0;
}
@@ -97,7 +97,7 @@ BN_ULONG bn_div_3_words(const BN_ULONG *m, BN_ULONG d1, BN_ULONG d0);
*/
# if BN_BITS2 == 64 && defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16
# undef BN_ULLONG
-# define BN_ULLONG __uint128_t
+# define BN_ULLONG uint128_t
# define BN_LLONG
# endif
@@ -212,7 +212,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
int ret;
if (BN_is_zero(divisor)) {
- BNerr(BN_F_BN_DIV, BN_R_DIV_BY_ZERO);
+ ERR_raise(ERR_LIB_BN, BN_R_DIV_BY_ZERO);
return 0;
}
@@ -222,7 +222,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
* BN_DEBUG builds)
*/
if (divisor->d[divisor->top - 1] == 0) {
- BNerr(BN_F_BN_DIV, BN_R_NOT_INITIALIZED);
+ ERR_raise(ERR_LIB_BN, BN_R_NOT_INITIALIZED);
return 0;
}
diff --git a/crypto/bn/bn_err.c b/crypto/bn/bn_err.c
index 6f5464b54054..953be9ed4717 100644
--- a/crypto/bn/bn_err.c
+++ b/crypto/bn/bn_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,74 +10,10 @@
#include <openssl/err.h>
#include <openssl/bnerr.h>
+#include "crypto/bnerr.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA BN_str_functs[] = {
- {ERR_PACK(ERR_LIB_BN, BN_F_BNRAND, 0), "bnrand"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BNRAND_RANGE, 0), "bnrand_range"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_BLINDING_CONVERT_EX, 0),
- "BN_BLINDING_convert_ex"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_BLINDING_CREATE_PARAM, 0),
- "BN_BLINDING_create_param"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_BLINDING_INVERT_EX, 0),
- "BN_BLINDING_invert_ex"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_BLINDING_NEW, 0), "BN_BLINDING_new"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_BLINDING_UPDATE, 0), "BN_BLINDING_update"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_BN2DEC, 0), "BN_bn2dec"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_BN2HEX, 0), "BN_bn2hex"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_COMPUTE_WNAF, 0), "bn_compute_wNAF"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_GET, 0), "BN_CTX_get"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_NEW, 0), "BN_CTX_new"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_START, 0), "BN_CTX_start"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_DIV, 0), "BN_div"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_DIV_RECP, 0), "BN_div_recp"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_EXP, 0), "BN_exp"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_EXPAND_INTERNAL, 0), "bn_expand_internal"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_GENCB_NEW, 0), "BN_GENCB_new"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_GENERATE_DSA_NONCE, 0),
- "BN_generate_dsa_nonce"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_GENERATE_PRIME_EX, 0),
- "BN_generate_prime_ex"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD, 0), "BN_GF2m_mod"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_EXP, 0), "BN_GF2m_mod_exp"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_MUL, 0), "BN_GF2m_mod_mul"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_SOLVE_QUAD, 0),
- "BN_GF2m_mod_solve_quad"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, 0),
- "BN_GF2m_mod_solve_quad_arr"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_SQR, 0), "BN_GF2m_mod_sqr"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_SQRT, 0), "BN_GF2m_mod_sqrt"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_LSHIFT, 0), "BN_lshift"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP2_MONT, 0), "BN_mod_exp2_mont"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP_MONT, 0), "BN_mod_exp_mont"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP_MONT_CONSTTIME, 0),
- "BN_mod_exp_mont_consttime"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP_MONT_WORD, 0),
- "BN_mod_exp_mont_word"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP_RECP, 0), "BN_mod_exp_recp"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP_SIMPLE, 0), "BN_mod_exp_simple"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_INVERSE, 0), "BN_mod_inverse"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_INVERSE_NO_BRANCH, 0),
- "BN_mod_inverse_no_branch"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_LSHIFT_QUICK, 0), "BN_mod_lshift_quick"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_SQRT, 0), "BN_mod_sqrt"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_MONT_CTX_NEW, 0), "BN_MONT_CTX_new"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_MPI2BN, 0), "BN_mpi2bn"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_NEW, 0), "BN_new"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_POOL_GET, 0), "BN_POOL_get"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_RAND, 0), "BN_rand"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_RAND_RANGE, 0), "BN_rand_range"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_RECP_CTX_NEW, 0), "BN_RECP_CTX_new"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_RSHIFT, 0), "BN_rshift"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_SET_WORDS, 0), "bn_set_words"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_STACK_PUSH, 0), "BN_STACK_push"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_USUB, 0), "BN_usub"},
- {ERR_PACK(ERR_LIB_BN, BN_F_OSSL_BN_RSA_DO_UNBLIND, 0),
- "ossl_bn_rsa_do_unblind"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA BN_str_reasons[] = {
{ERR_PACK(ERR_LIB_BN, 0, BN_R_ARG2_LT_ARG3), "arg2 lt arg3"},
{ERR_PACK(ERR_LIB_BN, 0, BN_R_BAD_RECIPROCAL), "bad reciprocal"},
@@ -96,7 +32,9 @@ static const ERR_STRING_DATA BN_str_reasons[] = {
{ERR_PACK(ERR_LIB_BN, 0, BN_R_NOT_A_SQUARE), "not a square"},
{ERR_PACK(ERR_LIB_BN, 0, BN_R_NOT_INITIALIZED), "not initialized"},
{ERR_PACK(ERR_LIB_BN, 0, BN_R_NO_INVERSE), "no inverse"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_NO_PRIME_CANDIDATE), "no prime candidate"},
{ERR_PACK(ERR_LIB_BN, 0, BN_R_NO_SOLUTION), "no solution"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_NO_SUITABLE_DIGEST), "no suitable digest"},
{ERR_PACK(ERR_LIB_BN, 0, BN_R_PRIVATE_KEY_TOO_LARGE),
"private key too large"},
{ERR_PACK(ERR_LIB_BN, 0, BN_R_P_IS_NOT_PRIME), "p is not prime"},
@@ -108,13 +46,11 @@ static const ERR_STRING_DATA BN_str_reasons[] = {
#endif
-int ERR_load_BN_strings(void)
+int ossl_err_load_BN_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(BN_str_functs[0].error) == NULL) {
- ERR_load_strings_const(BN_str_functs);
+ if (ERR_reason_error_string(BN_str_reasons[0].error) == NULL)
ERR_load_strings_const(BN_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c
index 517e3c29fc70..4e169ae1f9a4 100644
--- a/crypto/bn/bn_exp.c
+++ b/crypto/bn/bn_exp.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -29,8 +29,7 @@
#undef SPARC_T4_MONT
#if defined(OPENSSL_BN_ASM_MONT) && (defined(__sparc__) || defined(__sparc))
-# include "sparc_arch.h"
-extern unsigned int OPENSSL_sparcv9cap_P[];
+# include "crypto/sparc_arch.h"
# define SPARC_T4_MONT
#endif
@@ -55,7 +54,7 @@ int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0
|| BN_get_flags(a, BN_FLG_CONSTTIME) != 0) {
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
- BNerr(BN_F_BN_EXP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
@@ -181,7 +180,7 @@ int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|| BN_get_flags(a, BN_FLG_CONSTTIME) != 0
|| BN_get_flags(m, BN_FLG_CONSTTIME) != 0) {
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
- BNerr(BN_F_BN_MOD_EXP_RECP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
@@ -262,7 +261,6 @@ int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
* a window to do. To do this we need to scan forward until the last
* set bit before the end of the window
*/
- j = wstart;
wvalue = 1;
wend = 0;
for (i = 1; i < window; i++) {
@@ -319,7 +317,7 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
bn_check_top(m);
if (!BN_is_odd(m)) {
- BNerr(BN_F_BN_MOD_EXP_MONT, BN_R_CALLED_WITH_EVEN_MODULUS);
+ ERR_raise(ERR_LIB_BN, BN_R_CALLED_WITH_EVEN_MODULUS);
return 0;
}
@@ -421,7 +419,6 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
* a window to do. To do this we need to scan forward until the last
* set bit before the end of the window
*/
- j = wstart;
wvalue = 1;
wend = 0;
for (i = 1; i < window; i++) {
@@ -623,7 +620,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
bn_check_top(m);
if (!BN_is_odd(m)) {
- BNerr(BN_F_BN_MOD_EXP_MONT_CONSTTIME, BN_R_CALLED_WITH_EVEN_MODULUS);
+ ERR_raise(ERR_LIB_BN, BN_R_CALLED_WITH_EVEN_MODULUS);
return 0;
}
@@ -841,7 +838,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
/*
* BN_to_montgomery can contaminate words above .top [in
- * BN_DEBUG[_DEBUG] build]...
+ * BN_DEBUG build...
*/
for (i = am.top; i < top; i++)
am.d[i] = 0;
@@ -950,7 +947,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
/*
* BN_to_montgomery can contaminate words above .top [in
- * BN_DEBUG[_DEBUG] build]...
+ * BN_DEBUG build...
*/
for (i = am.top; i < top; i++)
am.d[i] = 0;
@@ -1184,7 +1181,7 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0
|| BN_get_flags(m, BN_FLG_CONSTTIME) != 0) {
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
- BNerr(BN_F_BN_MOD_EXP_MONT_WORD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
@@ -1192,7 +1189,7 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
bn_check_top(m);
if (!BN_is_odd(m)) {
- BNerr(BN_F_BN_MOD_EXP_MONT_WORD, BN_R_CALLED_WITH_EVEN_MODULUS);
+ ERR_raise(ERR_LIB_BN, BN_R_CALLED_WITH_EVEN_MODULUS);
return 0;
}
if (m->top == 1)
@@ -1316,7 +1313,7 @@ int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|| BN_get_flags(a, BN_FLG_CONSTTIME) != 0
|| BN_get_flags(m, BN_FLG_CONSTTIME) != 0) {
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
- BNerr(BN_F_BN_MOD_EXP_SIMPLE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
@@ -1383,7 +1380,6 @@ int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
* a window to do. To do this we need to scan forward until the last
* set bit before the end of the window
*/
- j = wstart;
wvalue = 1;
wend = 0;
for (i = 1; i < window; i++) {
@@ -1422,3 +1418,85 @@ int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
bn_check_top(r);
return ret;
}
+
+/*
+ * This is a variant of modular exponentiation optimization that does
+ * parallel 2-primes exponentiation using 256-bit (AVX512VL) AVX512_IFMA ISA
+ * in 52-bit binary redundant representation.
+ * If such instructions are not available, or input data size is not supported,
+ * it falls back to two BN_mod_exp_mont_consttime() calls.
+ */
+int BN_mod_exp_mont_consttime_x2(BIGNUM *rr1, const BIGNUM *a1, const BIGNUM *p1,
+ const BIGNUM *m1, BN_MONT_CTX *in_mont1,
+ BIGNUM *rr2, const BIGNUM *a2, const BIGNUM *p2,
+ const BIGNUM *m2, BN_MONT_CTX *in_mont2,
+ BN_CTX *ctx)
+{
+ int ret = 0;
+
+#ifdef RSAZ_ENABLED
+ BN_MONT_CTX *mont1 = NULL;
+ BN_MONT_CTX *mont2 = NULL;
+
+ if (ossl_rsaz_avx512ifma_eligible() &&
+ ((a1->top == 16) && (p1->top == 16) && (BN_num_bits(m1) == 1024) &&
+ (a2->top == 16) && (p2->top == 16) && (BN_num_bits(m2) == 1024))) {
+
+ if (bn_wexpand(rr1, 16) == NULL)
+ goto err;
+ if (bn_wexpand(rr2, 16) == NULL)
+ goto err;
+
+ /* Ensure that montgomery contexts are initialized */
+ if (in_mont1 != NULL) {
+ mont1 = in_mont1;
+ } else {
+ if ((mont1 = BN_MONT_CTX_new()) == NULL)
+ goto err;
+ if (!BN_MONT_CTX_set(mont1, m1, ctx))
+ goto err;
+ }
+ if (in_mont2 != NULL) {
+ mont2 = in_mont2;
+ } else {
+ if ((mont2 = BN_MONT_CTX_new()) == NULL)
+ goto err;
+ if (!BN_MONT_CTX_set(mont2, m2, ctx))
+ goto err;
+ }
+
+ ret = ossl_rsaz_mod_exp_avx512_x2(rr1->d, a1->d, p1->d, m1->d,
+ mont1->RR.d, mont1->n0[0],
+ rr2->d, a2->d, p2->d, m2->d,
+ mont2->RR.d, mont2->n0[0],
+ 1024 /* factor bit size */);
+
+ rr1->top = 16;
+ rr1->neg = 0;
+ bn_correct_top(rr1);
+ bn_check_top(rr1);
+
+ rr2->top = 16;
+ rr2->neg = 0;
+ bn_correct_top(rr2);
+ bn_check_top(rr2);
+
+ goto err;
+ }
+#endif
+
+ /* rr1 = a1^p1 mod m1 */
+ ret = BN_mod_exp_mont_consttime(rr1, a1, p1, m1, ctx, in_mont1);
+ /* rr2 = a2^p2 mod m2 */
+ ret &= BN_mod_exp_mont_consttime(rr2, a2, p2, m2, ctx, in_mont2);
+
+#ifdef RSAZ_ENABLED
+err:
+ if (in_mont2 == NULL)
+ BN_MONT_CTX_free(mont2);
+ if (in_mont1 == NULL)
+ BN_MONT_CTX_free(mont1);
+#endif
+
+ return ret;
+}
diff --git a/crypto/bn/bn_exp2.c b/crypto/bn/bn_exp2.c
index eac0896e6869..f5e29fd14de3 100644
--- a/crypto/bn/bn_exp2.c
+++ b/crypto/bn/bn_exp2.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -33,7 +33,7 @@ int BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1,
bn_check_top(m);
if (!BN_is_odd(m)) {
- BNerr(BN_F_BN_MOD_EXP2_MONT, BN_R_CALLED_WITH_EVEN_MODULUS);
+ ERR_raise(ERR_LIB_BN, BN_R_CALLED_WITH_EVEN_MODULUS);
return 0;
}
bits1 = BN_num_bits(p1);
diff --git a/crypto/bn/bn_gcd.c b/crypto/bn/bn_gcd.c
index 6190bf1eddb0..59d024f674eb 100644
--- a/crypto/bn/bn_gcd.c
+++ b/crypto/bn/bn_gcd.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -520,16 +520,16 @@ BIGNUM *BN_mod_inverse(BIGNUM *in,
int noinv = 0;
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(NULL);
if (ctx == NULL) {
- BNerr(BN_F_BN_MOD_INVERSE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return NULL;
}
}
rv = int_bn_mod_inverse(in, a, n, ctx, &noinv);
if (noinv)
- BNerr(BN_F_BN_MOD_INVERSE, BN_R_NO_INVERSE);
+ ERR_raise(ERR_LIB_BN, BN_R_NO_INVERSE);
BN_CTX_free(new_ctx);
return rv;
}
diff --git a/crypto/bn/bn_gf2m.c b/crypto/bn/bn_gf2m.c
index a2ea86755182..304c2ea08d0e 100644
--- a/crypto/bn/bn_gf2m.c
+++ b/crypto/bn/bn_gf2m.c
@@ -1,8 +1,8 @@
/*
- * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -297,7 +297,7 @@ int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[])
bn_check_top(a);
- if (!p[0]) {
+ if (p[0] == 0) {
/* reduction mod 1 => return 0 */
BN_zero(r);
return 1;
@@ -395,7 +395,7 @@ int BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p)
bn_check_top(p);
ret = BN_GF2m_poly2arr(p, arr, OSSL_NELEM(arr));
if (!ret || ret > (int)OSSL_NELEM(arr)) {
- BNerr(BN_F_BN_GF2M_MOD, BN_R_INVALID_LENGTH);
+ ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH);
return 0;
}
ret = BN_GF2m_mod_arr(r, a, arr);
@@ -467,15 +467,20 @@ int BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
{
int ret = 0;
const int max = BN_num_bits(p) + 1;
- int *arr = NULL;
+ int *arr;
+
bn_check_top(a);
bn_check_top(b);
bn_check_top(p);
- if ((arr = OPENSSL_malloc(sizeof(*arr) * max)) == NULL)
- goto err;
+
+ arr = OPENSSL_malloc(sizeof(*arr) * max);
+ if (arr == NULL) {
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
ret = BN_GF2m_poly2arr(p, arr, max);
if (!ret || ret > max) {
- BNerr(BN_F_BN_GF2M_MOD_MUL, BN_R_INVALID_LENGTH);
+ ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH);
goto err;
}
ret = BN_GF2m_mod_mul_arr(r, a, b, arr, ctx);
@@ -525,15 +530,19 @@ int BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
{
int ret = 0;
const int max = BN_num_bits(p) + 1;
- int *arr = NULL;
+ int *arr;
bn_check_top(a);
bn_check_top(p);
- if ((arr = OPENSSL_malloc(sizeof(*arr) * max)) == NULL)
- goto err;
+
+ arr = OPENSSL_malloc(sizeof(*arr) * max);
+ if (arr == NULL) {
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
ret = BN_GF2m_poly2arr(p, arr, max);
if (!ret || ret > max) {
- BNerr(BN_F_BN_GF2M_MOD_SQR, BN_R_INVALID_LENGTH);
+ ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH);
goto err;
}
ret = BN_GF2m_mod_sqr_arr(r, a, arr, ctx);
@@ -706,8 +715,8 @@ static int BN_GF2m_mod_inv_vartime(BIGNUM *r, const BIGNUM *a,
ret = 1;
err:
-# ifdef BN_DEBUG /* BN_CTX_end would complain about the
- * expanded form */
+# ifdef BN_DEBUG
+ /* BN_CTX_end would complain about the expanded form */
bn_correct_top(c);
bn_correct_top(u);
bn_correct_top(v);
@@ -732,8 +741,8 @@ int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
/* generate blinding value */
do {
- if (!BN_priv_rand(b, BN_num_bits(p) - 1,
- BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
+ if (!BN_priv_rand_ex(b, BN_num_bits(p) - 1,
+ BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0, ctx))
goto err;
} while (BN_is_zero(b));
@@ -899,15 +908,20 @@ int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
{
int ret = 0;
const int max = BN_num_bits(p) + 1;
- int *arr = NULL;
+ int *arr;
+
bn_check_top(a);
bn_check_top(b);
bn_check_top(p);
- if ((arr = OPENSSL_malloc(sizeof(*arr) * max)) == NULL)
- goto err;
+
+ arr = OPENSSL_malloc(sizeof(*arr) * max);
+ if (arr == NULL) {
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
ret = BN_GF2m_poly2arr(p, arr, max);
if (!ret || ret > max) {
- BNerr(BN_F_BN_GF2M_MOD_EXP, BN_R_INVALID_LENGTH);
+ ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH);
goto err;
}
ret = BN_GF2m_mod_exp_arr(r, a, b, arr, ctx);
@@ -929,7 +943,7 @@ int BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a, const int p[],
bn_check_top(a);
- if (!p[0]) {
+ if (p[0] == 0) {
/* reduction mod 1 => return 0 */
BN_zero(r);
return 1;
@@ -959,14 +973,19 @@ int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
{
int ret = 0;
const int max = BN_num_bits(p) + 1;
- int *arr = NULL;
+ int *arr;
+
bn_check_top(a);
bn_check_top(p);
- if ((arr = OPENSSL_malloc(sizeof(*arr) * max)) == NULL)
- goto err;
+
+ arr = OPENSSL_malloc(sizeof(*arr) * max);
+ if (arr == NULL) {
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
ret = BN_GF2m_poly2arr(p, arr, max);
if (!ret || ret > max) {
- BNerr(BN_F_BN_GF2M_MOD_SQRT, BN_R_INVALID_LENGTH);
+ ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH);
goto err;
}
ret = BN_GF2m_mod_sqrt_arr(r, a, arr, ctx);
@@ -988,7 +1007,7 @@ int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a_, const int p[],
bn_check_top(a_);
- if (!p[0]) {
+ if (p[0] == 0) {
/* reduction mod 1 => return 0 */
BN_zero(r);
return 1;
@@ -1031,7 +1050,8 @@ int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a_, const int p[],
if (tmp == NULL)
goto err;
do {
- if (!BN_priv_rand(rho, p[0], BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
+ if (!BN_priv_rand_ex(rho, p[0], BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY,
+ 0, ctx))
goto err;
if (!BN_GF2m_mod_arr(rho, rho, p))
goto err;
@@ -1053,7 +1073,7 @@ int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a_, const int p[],
count++;
} while (BN_is_zero(w) && (count < MAX_ITERATIONS));
if (BN_is_zero(w)) {
- BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, BN_R_TOO_MANY_ITERATIONS);
+ ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS);
goto err;
}
}
@@ -1063,7 +1083,7 @@ int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a_, const int p[],
if (!BN_GF2m_add(w, z, w))
goto err;
if (BN_GF2m_cmp(w, a)) {
- BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, BN_R_NO_SOLUTION);
+ ERR_raise(ERR_LIB_BN, BN_R_NO_SOLUTION);
goto err;
}
@@ -1089,14 +1109,19 @@ int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
{
int ret = 0;
const int max = BN_num_bits(p) + 1;
- int *arr = NULL;
+ int *arr;
+
bn_check_top(a);
bn_check_top(p);
- if ((arr = OPENSSL_malloc(sizeof(*arr) * max)) == NULL)
+
+ arr = OPENSSL_malloc(sizeof(*arr) * max);
+ if (arr == NULL) {
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
goto err;
+ }
ret = BN_GF2m_poly2arr(p, arr, max);
if (!ret || ret > max) {
- BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD, BN_R_INVALID_LENGTH);
+ ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH);
goto err;
}
ret = BN_GF2m_mod_solve_quad_arr(r, a, arr, ctx);
diff --git a/crypto/bn/bn_intern.c b/crypto/bn/bn_intern.c
index 147b4fa022cf..c0f7f5fea604 100644
--- a/crypto/bn/bn_intern.c
+++ b/crypto/bn/bn_intern.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -30,7 +30,7 @@ signed char *bn_compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)
if (BN_is_zero(scalar)) {
r = OPENSSL_malloc(1);
if (r == NULL) {
- BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
goto err;
}
r[0] = 0;
@@ -40,7 +40,7 @@ signed char *bn_compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)
if (w <= 0 || w > 7) { /* 'signed char' can represent integers with
* absolute values less than 2^7 */
- BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR);
goto err;
}
bit = 1 << w; /* at most 128 */
@@ -52,7 +52,7 @@ signed char *bn_compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)
}
if (scalar->d == NULL || scalar->top == 0) {
- BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -63,7 +63,7 @@ signed char *bn_compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)
* BN_num_bits(scalar) + 1)
*/
if (r == NULL) {
- BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
goto err;
}
window_val = scalar->d[0] & mask;
@@ -98,7 +98,7 @@ signed char *bn_compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)
}
if (digit <= -bit || digit >= bit || !(digit & 1)) {
- BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -110,7 +110,7 @@ signed char *bn_compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)
*/
if (window_val != 0 && window_val != next_bit
&& window_val != bit) {
- BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR);
goto err;
}
}
@@ -121,13 +121,13 @@ signed char *bn_compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)
window_val += bit * BN_is_bit_set(scalar, j + w);
if (window_val > next_bit) {
- BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (j > len + 1) {
- BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR);
goto err;
}
*ret_len = j;
@@ -188,7 +188,7 @@ void bn_set_static_words(BIGNUM *a, const BN_ULONG *words, int size)
int bn_set_words(BIGNUM *a, const BN_ULONG *words, int num_words)
{
if (bn_wexpand(a, num_words) == NULL) {
- BNerr(BN_F_BN_SET_WORDS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return 0;
}
diff --git a/crypto/bn/bn_kron.c b/crypto/bn/bn_kron.c
index c1e09d272120..8258536dcace 100644
--- a/crypto/bn/bn_kron.c
+++ b/crypto/bn/bn_kron.c
@@ -1,7 +1,7 @@
/*
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c
index eb4a31849bef..7ad6842560b4 100644
--- a/crypto/bn/bn_lib.c
+++ b/crypto/bn/bn_lib.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,12 +10,13 @@
#include <assert.h>
#include <limits.h>
#include "internal/cryptlib.h"
+#include "internal/endian.h"
#include "bn_local.h"
#include <openssl/opensslconf.h>
#include "internal/constant_time.h"
/* This stuff appears to be completely unused, so is deprecated */
-#if OPENSSL_API_COMPAT < 0x00908000L
+#ifndef OPENSSL_NO_DEPRECATED_0_9_8
/*-
* For a 32 bit machine
* 2 - 4 == 128
@@ -244,7 +245,7 @@ BIGNUM *BN_new(void)
BIGNUM *ret;
if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
- BNerr(BN_F_BN_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->flags = BN_FLG_MALLOCED;
@@ -267,11 +268,11 @@ static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
BN_ULONG *a = NULL;
if (words > (INT_MAX / (4 * BN_BITS2))) {
- BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_BIGNUM_TOO_LONG);
+ ERR_raise(ERR_LIB_BN, BN_R_BIGNUM_TOO_LONG);
return NULL;
}
if (BN_get_flags(b, BN_FLG_STATIC_DATA)) {
- BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
+ ERR_raise(ERR_LIB_BN, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
return NULL;
}
if (BN_get_flags(b, BN_FLG_SECURE))
@@ -279,7 +280,7 @@ static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
else
a = OPENSSL_zalloc(words * sizeof(*a));
if (a == NULL) {
- BNerr(BN_F_BN_EXPAND_INTERNAL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -504,7 +505,8 @@ int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen, endianess_t endiane
/* Swipe through whole available data and don't give away padded zero. */
atop = a->dmax * BN_BYTES;
if (atop == 0) {
- OPENSSL_cleanse(to, tolen);
+ if (tolen != 0)
+ memset(to, '\0', tolen);
return tolen;
}
@@ -593,6 +595,24 @@ int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen)
return bn2binpad(a, to, tolen, little);
}
+BIGNUM *BN_native2bn(const unsigned char *s, int len, BIGNUM *ret)
+{
+ DECLARE_IS_ENDIAN;
+
+ if (IS_LITTLE_ENDIAN)
+ return BN_lebin2bn(s, len, ret);
+ return BN_bin2bn(s, len, ret);
+}
+
+int BN_bn2nativepad(const BIGNUM *a, unsigned char *to, int tolen)
+{
+ DECLARE_IS_ENDIAN;
+
+ if (IS_LITTLE_ENDIAN)
+ return BN_bn2lebinpad(a, to, tolen);
+ return BN_bn2binpad(a, to, tolen);
+}
+
int BN_ucmp(const BIGNUM *a, const BIGNUM *b)
{
int i;
@@ -947,7 +967,7 @@ BN_GENCB *BN_GENCB_new(void)
BN_GENCB *ret;
if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) {
- BNerr(BN_F_BN_GENCB_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return NULL;
}
diff --git a/crypto/bn/bn_local.h b/crypto/bn/bn_local.h
index 30b7614fdbb2..2cc445607e18 100644
--- a/crypto/bn/bn_local.h
+++ b/crypto/bn/bn_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -22,18 +22,25 @@
# endif
# include "crypto/bn.h"
+# include "internal/cryptlib.h"
+# include "internal/numbers.h"
/*
* These preprocessor symbols control various aspects of the bignum headers
* and library code. They're not defined by any "normal" configuration, as
- * they are intended for development and testing purposes. NB: defining all
- * three can be useful for debugging application code as well as openssl
+ * they are intended for development and testing purposes. NB: defining
+ * them can be useful for debugging application code as well as openssl
* itself. BN_DEBUG - turn on various debugging alterations to the bignum
- * code BN_DEBUG_RAND - uses random poisoning of unused words to trip up
- * mismanagement of bignum internals. You must also define BN_DEBUG.
+ * code BN_RAND_DEBUG - uses random poisoning of unused words to trip up
+ * mismanagement of bignum internals. Enable BN_RAND_DEBUG is known to
+ * break some of the OpenSSL tests.
*/
-/* #define BN_DEBUG */
-/* #define BN_DEBUG_RAND */
+# if defined(BN_RAND_DEBUG) && !defined(BN_DEBUG)
+# define BN_DEBUG
+# endif
+# if defined(BN_RAND_DEBUG)
+# include <openssl/rand.h>
+# endif
/*
* This should limit the stack usage due to alloca to about 4K.
@@ -145,7 +152,7 @@
* bn_check_top() is as before.
* - if BN_DEBUG *is* defined;
* - bn_check_top() tries to pollute unused words even if the bignum 'top' is
- * consistent. (ed: only if BN_DEBUG_RAND is defined)
+ * consistent. (ed: only if BN_RAND_DEBUG is defined)
* - bn_fix_top() maps to bn_check_top() rather than "fixing" anything.
* The idea is to have debug builds flag up inconsistent bignums when they
* occur. If that occurs in a bn_fix_top(), we examine the code in question; if
@@ -171,7 +178,7 @@
* all operations manipulating the bit in question in non-BN_DEBUG build.
*/
# define BN_FLG_FIXED_TOP 0x10000
-# ifdef BN_DEBUG_RAND
+# ifdef BN_RAND_DEBUG
# define bn_pollute(a) \
do { \
const BIGNUM *_bnum1 = (a); \
@@ -182,7 +189,7 @@
* wouldn't be constructed with top!=dmax. */ \
BN_ULONG *_not_const; \
memcpy(&_not_const, &_bnum1->d, sizeof(_not_const)); \
- RAND_bytes(&_tmp_char, 1); /* Debug only - safe to ignore error return */\
+ (void)RAND_bytes(&_tmp_char, 1); /* Debug only - safe to ignore error return */\
memset(_not_const + _bnum1->top, _tmp_char, \
sizeof(*_not_const) * (_bnum1->dmax - _bnum1->top)); \
} \
@@ -408,9 +415,9 @@ struct bn_blinding_st {
*/
# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16 && \
(defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG))
-# define BN_UMULT_HIGH(a,b) (((__uint128_t)(a)*(b))>>64)
+# define BN_UMULT_HIGH(a,b) (((uint128_t)(a)*(b))>>64)
# define BN_UMULT_LOHI(low,high,a,b) ({ \
- __uint128_t ret=(__uint128_t)(a)*(b); \
+ uint128_t ret=(uint128_t)(a)*(b); \
(high)=ret>>64; (low)=ret; })
# elif defined(__alpha) && (defined(SIXTY_FOUR_BIT_LONG) || defined(SIXTY_FOUR_BIT))
# if defined(__DECC)
@@ -483,7 +490,7 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b,
# endif /* cpu */
# endif /* OPENSSL_NO_ASM */
-# ifdef BN_DEBUG_RAND
+# ifdef BN_RAND_DEBUG
# define bn_clear_top2max(a) \
{ \
int ind = (a)->dmax - (a)->top; \
@@ -699,4 +706,7 @@ static ossl_inline BIGNUM *bn_expand(BIGNUM *a, int bits)
return bn_expand2((a),(bits+BN_BITS2-1)/BN_BITS2);
}
+int ossl_bn_check_prime(const BIGNUM *w, int checks, BN_CTX *ctx,
+ int do_trial_division, BN_GENCB *cb);
+
#endif
diff --git a/crypto/bn/bn_mod.c b/crypto/bn/bn_mod.c
index f7d2e2650ed8..7f5afa25ecc8 100644
--- a/crypto/bn/bn_mod.c
+++ b/crypto/bn/bn_mod.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -56,9 +56,13 @@ int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
if (bn_wexpand(r, mtop) == NULL)
return 0;
- if (mtop > sizeof(storage) / sizeof(storage[0])
- && (tp = OPENSSL_malloc(mtop * sizeof(BN_ULONG))) == NULL)
- return 0;
+ if (mtop > sizeof(storage) / sizeof(storage[0])) {
+ tp = OPENSSL_malloc(mtop * sizeof(BN_ULONG));
+ if (tp == NULL) {
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
ap = a->d != NULL ? a->d : tp;
bp = b->d != NULL ? b->d : tp;
@@ -291,7 +295,7 @@ int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m)
/* max_shift >= 0 */
if (max_shift < 0) {
- BNerr(BN_F_BN_MOD_LSHIFT_QUICK, BN_R_INPUT_NOT_REDUCED);
+ ERR_raise(ERR_LIB_BN, BN_R_INPUT_NOT_REDUCED);
return 0;
}
diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c
index 7617b0df5e70..1c5d66bbf863 100644
--- a/crypto/bn/bn_mont.c
+++ b/crypto/bn/bn_mont.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -230,7 +230,7 @@ BN_MONT_CTX *BN_MONT_CTX_new(void)
BN_MONT_CTX *ret;
if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) {
- BNerr(BN_F_BN_MONT_CTX_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -430,14 +430,15 @@ BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_RWLOCK *lock,
{
BN_MONT_CTX *ret;
- CRYPTO_THREAD_read_lock(lock);
+ if (!CRYPTO_THREAD_read_lock(lock))
+ return NULL;
ret = *pmont;
CRYPTO_THREAD_unlock(lock);
if (ret)
return ret;
/*
- * We don't want to serialise globally while doing our lazy-init math in
+ * We don't want to serialize globally while doing our lazy-init math in
* BN_MONT_CTX_set. That punishes threads that are doing independent
* things. Instead, punish the case where more than one thread tries to
* lazy-init the same 'pmont', by having each do the lazy-init math work
@@ -453,7 +454,11 @@ BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_RWLOCK *lock,
}
/* The locked compare-and-set, after the local work is done. */
- CRYPTO_THREAD_write_lock(lock);
+ if (!CRYPTO_THREAD_write_lock(lock)) {
+ BN_MONT_CTX_free(ret);
+ return NULL;
+ }
+
if (*pmont) {
BN_MONT_CTX_free(ret);
ret = *pmont;
diff --git a/crypto/bn/bn_mpi.c b/crypto/bn/bn_mpi.c
index 0902da5d076e..4eba0ae57002 100644
--- a/crypto/bn/bn_mpi.c
+++ b/crypto/bn/bn_mpi.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -46,13 +46,13 @@ BIGNUM *BN_mpi2bn(const unsigned char *d, int n, BIGNUM *ain)
BIGNUM *a = NULL;
if (n < 4 || (d[0] & 0x80) != 0) {
- BNerr(BN_F_BN_MPI2BN, BN_R_INVALID_LENGTH);
+ ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH);
return NULL;
}
len = ((long)d[0] << 24) | ((long)d[1] << 16) | ((int)d[2] << 8) | (int)
d[3];
if ((len + 4) != n) {
- BNerr(BN_F_BN_MPI2BN, BN_R_ENCODING_ERROR);
+ ERR_raise(ERR_LIB_BN, BN_R_ENCODING_ERROR);
return NULL;
}
diff --git a/crypto/bn/bn_mul.c b/crypto/bn/bn_mul.c
index 6743e7be8166..dc6b6f5a1215 100644
--- a/crypto/bn/bn_mul.c
+++ b/crypto/bn/bn_mul.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/bn/bn_nist.c b/crypto/bn/bn_nist.c
index c29e62ed3fef..da10c4054a3e 100644
--- a/crypto/bn/bn_nist.c
+++ b/crypto/bn/bn_nist.c
@@ -1,7 +1,7 @@
/*
* Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -184,7 +184,7 @@ static const BN_ULONG _nist_p_521_sqr[] = {
# error "unsupported BN_BITS2"
#endif
-static const BIGNUM _bignum_nist_p_192 = {
+static const BIGNUM ossl_bignum_nist_p_192 = {
(BN_ULONG *)_nist_p_192[0],
BN_NIST_192_TOP,
BN_NIST_192_TOP,
@@ -192,7 +192,7 @@ static const BIGNUM _bignum_nist_p_192 = {
BN_FLG_STATIC_DATA
};
-static const BIGNUM _bignum_nist_p_224 = {
+static const BIGNUM ossl_bignum_nist_p_224 = {
(BN_ULONG *)_nist_p_224[0],
BN_NIST_224_TOP,
BN_NIST_224_TOP,
@@ -200,7 +200,7 @@ static const BIGNUM _bignum_nist_p_224 = {
BN_FLG_STATIC_DATA
};
-static const BIGNUM _bignum_nist_p_256 = {
+static const BIGNUM ossl_bignum_nist_p_256 = {
(BN_ULONG *)_nist_p_256[0],
BN_NIST_256_TOP,
BN_NIST_256_TOP,
@@ -208,7 +208,7 @@ static const BIGNUM _bignum_nist_p_256 = {
BN_FLG_STATIC_DATA
};
-static const BIGNUM _bignum_nist_p_384 = {
+static const BIGNUM ossl_bignum_nist_p_384 = {
(BN_ULONG *)_nist_p_384[0],
BN_NIST_384_TOP,
BN_NIST_384_TOP,
@@ -216,7 +216,7 @@ static const BIGNUM _bignum_nist_p_384 = {
BN_FLG_STATIC_DATA
};
-static const BIGNUM _bignum_nist_p_521 = {
+static const BIGNUM ossl_bignum_nist_p_521 = {
(BN_ULONG *)_nist_p_521,
BN_NIST_521_TOP,
BN_NIST_521_TOP,
@@ -226,27 +226,27 @@ static const BIGNUM _bignum_nist_p_521 = {
const BIGNUM *BN_get0_nist_prime_192(void)
{
- return &_bignum_nist_p_192;
+ return &ossl_bignum_nist_p_192;
}
const BIGNUM *BN_get0_nist_prime_224(void)
{
- return &_bignum_nist_p_224;
+ return &ossl_bignum_nist_p_224;
}
const BIGNUM *BN_get0_nist_prime_256(void)
{
- return &_bignum_nist_p_256;
+ return &ossl_bignum_nist_p_256;
}
const BIGNUM *BN_get0_nist_prime_384(void)
{
- return &_bignum_nist_p_384;
+ return &ossl_bignum_nist_p_384;
}
const BIGNUM *BN_get0_nist_prime_521(void)
{
- return &_bignum_nist_p_521;
+ return &ossl_bignum_nist_p_521;
}
/*
@@ -339,16 +339,16 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
} buf;
BN_ULONG c_d[BN_NIST_192_TOP], *res;
PTR_SIZE_INT mask;
- static const BIGNUM _bignum_nist_p_192_sqr = {
+ static const BIGNUM ossl_bignum_nist_p_192_sqr = {
(BN_ULONG *)_nist_p_192_sqr,
OSSL_NELEM(_nist_p_192_sqr),
OSSL_NELEM(_nist_p_192_sqr),
0, BN_FLG_STATIC_DATA
};
- field = &_bignum_nist_p_192; /* just to make sure */
+ field = &ossl_bignum_nist_p_192; /* just to make sure */
- if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_192_sqr) >= 0)
+ if (BN_is_negative(a) || BN_ucmp(a, &ossl_bignum_nist_p_192_sqr) >= 0)
return BN_nnmod(r, a, field, ctx);
i = BN_ucmp(field, a);
@@ -484,16 +484,16 @@ int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
bn_addsub_f f;
PTR_SIZE_INT p;
} u;
- static const BIGNUM _bignum_nist_p_224_sqr = {
+ static const BIGNUM ossl_bignum_nist_p_224_sqr = {
(BN_ULONG *)_nist_p_224_sqr,
OSSL_NELEM(_nist_p_224_sqr),
OSSL_NELEM(_nist_p_224_sqr),
0, BN_FLG_STATIC_DATA
};
- field = &_bignum_nist_p_224; /* just to make sure */
+ field = &ossl_bignum_nist_p_224; /* just to make sure */
- if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_224_sqr) >= 0)
+ if (BN_is_negative(a) || BN_ucmp(a, &ossl_bignum_nist_p_224_sqr) >= 0)
return BN_nnmod(r, a, field, ctx);
i = BN_ucmp(field, a);
@@ -665,16 +665,16 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
bn_addsub_f f;
PTR_SIZE_INT p;
} u;
- static const BIGNUM _bignum_nist_p_256_sqr = {
+ static const BIGNUM ossl_bignum_nist_p_256_sqr = {
(BN_ULONG *)_nist_p_256_sqr,
OSSL_NELEM(_nist_p_256_sqr),
OSSL_NELEM(_nist_p_256_sqr),
0, BN_FLG_STATIC_DATA
};
- field = &_bignum_nist_p_256; /* just to make sure */
+ field = &ossl_bignum_nist_p_256; /* just to make sure */
- if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_256_sqr) >= 0)
+ if (BN_is_negative(a) || BN_ucmp(a, &ossl_bignum_nist_p_256_sqr) >= 0)
return BN_nnmod(r, a, field, ctx);
i = BN_ucmp(field, a);
@@ -911,16 +911,16 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
bn_addsub_f f;
PTR_SIZE_INT p;
} u;
- static const BIGNUM _bignum_nist_p_384_sqr = {
+ static const BIGNUM ossl_bignum_nist_p_384_sqr = {
(BN_ULONG *)_nist_p_384_sqr,
OSSL_NELEM(_nist_p_384_sqr),
OSSL_NELEM(_nist_p_384_sqr),
0, BN_FLG_STATIC_DATA
};
- field = &_bignum_nist_p_384; /* just to make sure */
+ field = &ossl_bignum_nist_p_384; /* just to make sure */
- if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_384_sqr) >= 0)
+ if (BN_is_negative(a) || BN_ucmp(a, &ossl_bignum_nist_p_384_sqr) >= 0)
return BN_nnmod(r, a, field, ctx);
i = BN_ucmp(field, a);
@@ -1169,16 +1169,16 @@ int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
int top = a->top, i;
BN_ULONG *r_d, *a_d = a->d, t_d[BN_NIST_521_TOP], val, tmp, *res;
PTR_SIZE_INT mask;
- static const BIGNUM _bignum_nist_p_521_sqr = {
+ static const BIGNUM ossl_bignum_nist_p_521_sqr = {
(BN_ULONG *)_nist_p_521_sqr,
OSSL_NELEM(_nist_p_521_sqr),
OSSL_NELEM(_nist_p_521_sqr),
0, BN_FLG_STATIC_DATA
};
- field = &_bignum_nist_p_521; /* just to make sure */
+ field = &ossl_bignum_nist_p_521; /* just to make sure */
- if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_521_sqr) >= 0)
+ if (BN_is_negative(a) || BN_ucmp(a, &ossl_bignum_nist_p_521_sqr) >= 0)
return BN_nnmod(r, a, field, ctx);
i = BN_ucmp(field, a);
@@ -1236,15 +1236,15 @@ int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
int (*BN_nist_mod_func(const BIGNUM *p)) (BIGNUM *r, const BIGNUM *a,
const BIGNUM *field, BN_CTX *ctx) {
- if (BN_ucmp(&_bignum_nist_p_192, p) == 0)
+ if (BN_ucmp(&ossl_bignum_nist_p_192, p) == 0)
return BN_nist_mod_192;
- if (BN_ucmp(&_bignum_nist_p_224, p) == 0)
+ if (BN_ucmp(&ossl_bignum_nist_p_224, p) == 0)
return BN_nist_mod_224;
- if (BN_ucmp(&_bignum_nist_p_256, p) == 0)
+ if (BN_ucmp(&ossl_bignum_nist_p_256, p) == 0)
return BN_nist_mod_256;
- if (BN_ucmp(&_bignum_nist_p_384, p) == 0)
+ if (BN_ucmp(&ossl_bignum_nist_p_384, p) == 0)
return BN_nist_mod_384;
- if (BN_ucmp(&_bignum_nist_p_521, p) == 0)
+ if (BN_ucmp(&ossl_bignum_nist_p_521, p) == 0)
return BN_nist_mod_521;
return 0;
}
diff --git a/crypto/bn/bn_ppc.c b/crypto/bn/bn_ppc.c
new file mode 100644
index 000000000000..3ee76ea96574
--- /dev/null
+++ b/crypto/bn/bn_ppc.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2009-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/bn.h>
+#include "crypto/ppc_arch.h"
+#include "bn_local.h"
+
+int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ const BN_ULONG *np, const BN_ULONG *n0, int num)
+{
+ int bn_mul_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ const BN_ULONG *np, const BN_ULONG *n0, int num);
+ int bn_mul4x_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ const BN_ULONG *np, const BN_ULONG *n0, int num);
+
+ if (num < 4)
+ return 0;
+
+ if ((num & 3) == 0)
+ return bn_mul4x_mont_int(rp, ap, bp, np, n0, num);
+
+ /*
+ * There used to be [optional] call to bn_mul_mont_fpu64 here,
+ * but above subroutine is faster on contemporary processors.
+ * Formulation means that there might be old processors where
+ * FPU code path would be faster, POWER6 perhaps, but there was
+ * no opportunity to figure it out...
+ */
+
+ return bn_mul_mont_int(rp, ap, bp, np, n0, num);
+}
diff --git a/crypto/bn/bn_prime.c b/crypto/bn/bn_prime.c
index d0cf3779fa50..ddd31a025254 100644
--- a/crypto/bn/bn_prime.c
+++ b/crypto/bn/bn_prime.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -19,16 +19,85 @@
*/
#include "bn_prime.h"
-static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1,
- const BIGNUM *a1_odd, int k, BN_CTX *ctx,
- BN_MONT_CTX *mont);
-static int probable_prime(BIGNUM *rnd, int bits, int safe, prime_t *mods);
+static int probable_prime(BIGNUM *rnd, int bits, int safe, prime_t *mods,
+ BN_CTX *ctx);
static int probable_prime_dh(BIGNUM *rnd, int bits, int safe, prime_t *mods,
const BIGNUM *add, const BIGNUM *rem,
BN_CTX *ctx);
+static int bn_is_prime_int(const BIGNUM *w, int checks, BN_CTX *ctx,
+ int do_trial_division, BN_GENCB *cb);
#define square(x) ((BN_ULONG)(x) * (BN_ULONG)(x))
+#if BN_BITS2 == 64
+# define BN_DEF(lo, hi) (BN_ULONG)hi<<32|lo
+#else
+# define BN_DEF(lo, hi) lo, hi
+#endif
+
+/*
+ * See SP800 89 5.3.3 (Step f)
+ * The product of the set of primes ranging from 3 to 751
+ * Generated using process in test/bn_internal_test.c test_bn_small_factors().
+ * This includes 751 (which is not currently included in SP 800-89).
+ */
+static const BN_ULONG small_prime_factors[] = {
+ BN_DEF(0x3ef4e3e1, 0xc4309333), BN_DEF(0xcd2d655f, 0x71161eb6),
+ BN_DEF(0x0bf94862, 0x95e2238c), BN_DEF(0x24f7912b, 0x3eb233d3),
+ BN_DEF(0xbf26c483, 0x6b55514b), BN_DEF(0x5a144871, 0x0a84d817),
+ BN_DEF(0x9b82210a, 0x77d12fee), BN_DEF(0x97f050b3, 0xdb5b93c2),
+ BN_DEF(0x4d6c026b, 0x4acad6b9), BN_DEF(0x54aec893, 0xeb7751f3),
+ BN_DEF(0x36bc85c4, 0xdba53368), BN_DEF(0x7f5ec78e, 0xd85a1b28),
+ BN_DEF(0x6b322244, 0x2eb072d8), BN_DEF(0x5e2b3aea, 0xbba51112),
+ BN_DEF(0x0e2486bf, 0x36ed1a6c), BN_DEF(0xec0c5727, 0x5f270460),
+ (BN_ULONG)0x000017b1
+};
+
+#define BN_SMALL_PRIME_FACTORS_TOP OSSL_NELEM(small_prime_factors)
+static const BIGNUM _bignum_small_prime_factors = {
+ (BN_ULONG *)small_prime_factors,
+ BN_SMALL_PRIME_FACTORS_TOP,
+ BN_SMALL_PRIME_FACTORS_TOP,
+ 0,
+ BN_FLG_STATIC_DATA
+};
+
+const BIGNUM *ossl_bn_get0_small_factors(void)
+{
+ return &_bignum_small_prime_factors;
+}
+
+/*
+ * Calculate the number of trial divisions that gives the best speed in
+ * combination with Miller-Rabin prime test, based on the sized of the prime.
+ */
+static int calc_trial_divisions(int bits)
+{
+ if (bits <= 512)
+ return 64;
+ else if (bits <= 1024)
+ return 128;
+ else if (bits <= 2048)
+ return 384;
+ else if (bits <= 4096)
+ return 1024;
+ return NUMPRIMES;
+}
+
+/*
+ * Use a minimum of 64 rounds of Miller-Rabin, which should give a false
+ * positive rate of 2^-128. If the size of the prime is larger than 2048
+ * the user probably wants a higher security level than 128, so switch
+ * to 128 rounds giving a false positive rate of 2^-256.
+ * Returns the number of rounds.
+ */
+static int bn_mr_min_checks(int bits)
+{
+ if (bits > 2048)
+ return 128;
+ return 64;
+}
+
int BN_GENCB_call(BN_GENCB *cb, int a, int b)
{
/* No callback means continue */
@@ -51,19 +120,19 @@ int BN_GENCB_call(BN_GENCB *cb, int a, int b)
return 0;
}
-int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
- const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb)
+int BN_generate_prime_ex2(BIGNUM *ret, int bits, int safe,
+ const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb,
+ BN_CTX *ctx)
{
BIGNUM *t;
int found = 0;
int i, j, c1 = 0;
- BN_CTX *ctx = NULL;
prime_t *mods = NULL;
- int checks = BN_prime_checks_for_size(bits);
+ int checks = bn_mr_min_checks(bits);
if (bits < 2) {
/* There are no prime numbers this small. */
- BNerr(BN_F_BN_GENERATE_PRIME_EX, BN_R_BITS_TOO_SMALL);
+ ERR_raise(ERR_LIB_BN, BN_R_BITS_TOO_SMALL);
return 0;
} else if (add == NULL && safe && bits < 6 && bits != 3) {
/*
@@ -71,17 +140,16 @@ int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
* But the following two safe primes with less than 6 bits (11, 23)
* are unreachable for BN_rand with BN_RAND_TOP_TWO.
*/
- BNerr(BN_F_BN_GENERATE_PRIME_EX, BN_R_BITS_TOO_SMALL);
+ ERR_raise(ERR_LIB_BN, BN_R_BITS_TOO_SMALL);
return 0;
}
mods = OPENSSL_zalloc(sizeof(*mods) * NUMPRIMES);
- if (mods == NULL)
- goto err;
+ if (mods == NULL) {
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
- ctx = BN_CTX_new();
- if (ctx == NULL)
- goto err;
BN_CTX_start(ctx);
t = BN_CTX_get(ctx);
if (t == NULL)
@@ -89,7 +157,7 @@ int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
loop:
/* make a random number and set the top and bottom bits */
if (add == NULL) {
- if (!probable_prime(ret, bits, safe, mods))
+ if (!probable_prime(ret, bits, safe, mods, ctx))
goto err;
} else {
if (!probable_prime_dh(ret, bits, safe, mods, add, rem, ctx))
@@ -101,7 +169,7 @@ int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
goto err;
if (!safe) {
- i = BN_is_prime_fasttest_ex(ret, checks, ctx, 0, cb);
+ i = bn_is_prime_int(ret, checks, ctx, 0, cb);
if (i == -1)
goto err;
if (i == 0)
@@ -115,13 +183,13 @@ int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
goto err;
for (i = 0; i < checks; i++) {
- j = BN_is_prime_fasttest_ex(ret, 1, ctx, 0, cb);
+ j = bn_is_prime_int(ret, 1, ctx, 0, cb);
if (j == -1)
goto err;
if (j == 0)
goto loop;
- j = BN_is_prime_fasttest_ex(t, 1, ctx, 0, cb);
+ j = bn_is_prime_int(t, 1, ctx, 0, cb);
if (j == -1)
goto err;
if (j == 0)
@@ -137,152 +205,292 @@ int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
err:
OPENSSL_free(mods);
BN_CTX_end(ctx);
- BN_CTX_free(ctx);
bn_check_top(ret);
return found;
}
+#ifndef FIPS_MODULE
+int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
+ const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb)
+{
+ BN_CTX *ctx = BN_CTX_new();
+ int retval;
+
+ if (ctx == NULL)
+ return 0;
+
+ retval = BN_generate_prime_ex2(ret, bits, safe, add, rem, cb, ctx);
+
+ BN_CTX_free(ctx);
+ return retval;
+}
+#endif
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int BN_is_prime_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed,
BN_GENCB *cb)
{
- return BN_is_prime_fasttest_ex(a, checks, ctx_passed, 0, cb);
+ return ossl_bn_check_prime(a, checks, ctx_passed, 0, cb);
}
-int BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed,
+int BN_is_prime_fasttest_ex(const BIGNUM *w, int checks, BN_CTX *ctx,
int do_trial_division, BN_GENCB *cb)
{
- int i, j, ret = -1;
- int k;
- BN_CTX *ctx = NULL;
- BIGNUM *A1, *A1_odd, *A3, *check; /* taken from ctx */
- BN_MONT_CTX *mont = NULL;
+ return ossl_bn_check_prime(w, checks, ctx, do_trial_division, cb);
+}
+#endif
- /* Take care of the really small primes 2 & 3 */
- if (BN_is_word(a, 2) || BN_is_word(a, 3))
- return 1;
+/* Wrapper around bn_is_prime_int that sets the minimum number of checks */
+int ossl_bn_check_prime(const BIGNUM *w, int checks, BN_CTX *ctx,
+ int do_trial_division, BN_GENCB *cb)
+{
+ int min_checks = bn_mr_min_checks(BN_num_bits(w));
+
+ if (checks < min_checks)
+ checks = min_checks;
+
+ return bn_is_prime_int(w, checks, ctx, do_trial_division, cb);
+}
+
+int BN_check_prime(const BIGNUM *p, BN_CTX *ctx, BN_GENCB *cb)
+{
+ return ossl_bn_check_prime(p, 0, ctx, 1, cb);
+}
+
+/*
+ * Tests that |w| is probably prime
+ * See FIPS 186-4 C.3.1 Miller Rabin Probabilistic Primality Test.
+ *
+ * Returns 0 when composite, 1 when probable prime, -1 on error.
+ */
+static int bn_is_prime_int(const BIGNUM *w, int checks, BN_CTX *ctx,
+ int do_trial_division, BN_GENCB *cb)
+{
+ int i, status, ret = -1;
+#ifndef FIPS_MODULE
+ BN_CTX *ctxlocal = NULL;
+#else
+
+ if (ctx == NULL)
+ return -1;
+#endif
- /* Check odd and bigger than 1 */
- if (!BN_is_odd(a) || BN_cmp(a, BN_value_one()) <= 0)
+ /* w must be bigger than 1 */
+ if (BN_cmp(w, BN_value_one()) <= 0)
return 0;
- if (checks == BN_prime_checks)
- checks = BN_prime_checks_for_size(BN_num_bits(a));
+ /* w must be odd */
+ if (BN_is_odd(w)) {
+ /* Take care of the really small prime 3 */
+ if (BN_is_word(w, 3))
+ return 1;
+ } else {
+ /* 2 is the only even prime */
+ return BN_is_word(w, 2);
+ }
/* first look for small factors */
if (do_trial_division) {
- for (i = 1; i < NUMPRIMES; i++) {
- BN_ULONG mod = BN_mod_word(a, primes[i]);
+ int trial_divisions = calc_trial_divisions(BN_num_bits(w));
+
+ for (i = 1; i < trial_divisions; i++) {
+ BN_ULONG mod = BN_mod_word(w, primes[i]);
if (mod == (BN_ULONG)-1)
- goto err;
+ return -1;
if (mod == 0)
- return BN_is_word(a, primes[i]);
+ return BN_is_word(w, primes[i]);
}
if (!BN_GENCB_call(cb, 1, -1))
- goto err;
+ return -1;
}
-
- if (ctx_passed != NULL)
- ctx = ctx_passed;
- else if ((ctx = BN_CTX_new()) == NULL)
+#ifndef FIPS_MODULE
+ if (ctx == NULL && (ctxlocal = ctx = BN_CTX_new()) == NULL)
goto err;
- BN_CTX_start(ctx);
+#endif
- A1 = BN_CTX_get(ctx);
- A3 = BN_CTX_get(ctx);
- A1_odd = BN_CTX_get(ctx);
- check = BN_CTX_get(ctx);
- if (check == NULL)
+ if (!ossl_bn_miller_rabin_is_prime(w, checks, ctx, cb, 0, &status)) {
+ ret = -1;
goto err;
+ }
+ ret = (status == BN_PRIMETEST_PROBABLY_PRIME);
+err:
+#ifndef FIPS_MODULE
+ BN_CTX_free(ctxlocal);
+#endif
+ return ret;
+}
- /* compute A1 := a - 1 */
- if (!BN_copy(A1, a) || !BN_sub_word(A1, 1))
+/*
+ * Refer to FIPS 186-4 C.3.2 Enhanced Miller-Rabin Probabilistic Primality Test.
+ * OR C.3.1 Miller-Rabin Probabilistic Primality Test (if enhanced is zero).
+ * The Step numbers listed in the code refer to the enhanced case.
+ *
+ * if enhanced is set, then status returns one of the following:
+ * BN_PRIMETEST_PROBABLY_PRIME
+ * BN_PRIMETEST_COMPOSITE_WITH_FACTOR
+ * BN_PRIMETEST_COMPOSITE_NOT_POWER_OF_PRIME
+ * if enhanced is zero, then status returns either
+ * BN_PRIMETEST_PROBABLY_PRIME or
+ * BN_PRIMETEST_COMPOSITE
+ *
+ * returns 0 if there was an error, otherwise it returns 1.
+ */
+int ossl_bn_miller_rabin_is_prime(const BIGNUM *w, int iterations, BN_CTX *ctx,
+ BN_GENCB *cb, int enhanced, int *status)
+{
+ int i, j, a, ret = 0;
+ BIGNUM *g, *w1, *w3, *x, *m, *z, *b;
+ BN_MONT_CTX *mont = NULL;
+
+ /* w must be odd */
+ if (!BN_is_odd(w))
+ return 0;
+
+ BN_CTX_start(ctx);
+ g = BN_CTX_get(ctx);
+ w1 = BN_CTX_get(ctx);
+ w3 = BN_CTX_get(ctx);
+ x = BN_CTX_get(ctx);
+ m = BN_CTX_get(ctx);
+ z = BN_CTX_get(ctx);
+ b = BN_CTX_get(ctx);
+
+ if (!(b != NULL
+ /* w1 := w - 1 */
+ && BN_copy(w1, w)
+ && BN_sub_word(w1, 1)
+ /* w3 := w - 3 */
+ && BN_copy(w3, w)
+ && BN_sub_word(w3, 3)))
goto err;
- /* compute A3 := a - 3 */
- if (!BN_copy(A3, a) || !BN_sub_word(A3, 3))
+
+ /* check w is larger than 3, otherwise the random b will be too small */
+ if (BN_is_zero(w3) || BN_is_negative(w3))
goto err;
- /* write A1 as A1_odd * 2^k */
- k = 1;
- while (!BN_is_bit_set(A1, k))
- k++;
- if (!BN_rshift(A1_odd, A1, k))
+ /* (Step 1) Calculate largest integer 'a' such that 2^a divides w-1 */
+ a = 1;
+ while (!BN_is_bit_set(w1, a))
+ a++;
+ /* (Step 2) m = (w-1) / 2^a */
+ if (!BN_rshift(m, w1, a))
goto err;
/* Montgomery setup for computations mod a */
mont = BN_MONT_CTX_new();
- if (mont == NULL)
- goto err;
- if (!BN_MONT_CTX_set(mont, a, ctx))
+ if (mont == NULL || !BN_MONT_CTX_set(mont, w, ctx))
goto err;
- for (i = 0; i < checks; i++) {
- /* 1 < check < a-1 */
- if (!BN_priv_rand_range(check, A3) || !BN_add_word(check, 2))
+ if (iterations == 0)
+ iterations = bn_mr_min_checks(BN_num_bits(w));
+
+ /* (Step 4) */
+ for (i = 0; i < iterations; ++i) {
+ /* (Step 4.1) obtain a Random string of bits b where 1 < b < w-1 */
+ if (!BN_priv_rand_range_ex(b, w3, 0, ctx)
+ || !BN_add_word(b, 2)) /* 1 < b < w-1 */
goto err;
- j = witness(check, a, A1, A1_odd, k, ctx, mont);
- if (j == -1)
+ if (enhanced) {
+ /* (Step 4.3) */
+ if (!BN_gcd(g, b, w, ctx))
+ goto err;
+ /* (Step 4.4) */
+ if (!BN_is_one(g)) {
+ *status = BN_PRIMETEST_COMPOSITE_WITH_FACTOR;
+ ret = 1;
+ goto err;
+ }
+ }
+ /* (Step 4.5) z = b^m mod w */
+ if (!BN_mod_exp_mont(z, b, m, w, ctx, mont))
goto err;
- if (j) {
- ret = 0;
+ /* (Step 4.6) if (z = 1 or z = w-1) */
+ if (BN_is_one(z) || BN_cmp(z, w1) == 0)
+ goto outer_loop;
+ /* (Step 4.7) for j = 1 to a-1 */
+ for (j = 1; j < a ; ++j) {
+ /* (Step 4.7.1 - 4.7.2) x = z. z = x^2 mod w */
+ if (!BN_copy(x, z) || !BN_mod_mul(z, x, x, w, ctx))
+ goto err;
+ /* (Step 4.7.3) */
+ if (BN_cmp(z, w1) == 0)
+ goto outer_loop;
+ /* (Step 4.7.4) */
+ if (BN_is_one(z))
+ goto composite;
+ }
+ /* At this point z = b^((w-1)/2) mod w */
+ /* (Steps 4.8 - 4.9) x = z, z = x^2 mod w */
+ if (!BN_copy(x, z) || !BN_mod_mul(z, x, x, w, ctx))
+ goto err;
+ /* (Step 4.10) */
+ if (BN_is_one(z))
+ goto composite;
+ /* (Step 4.11) x = b^(w-1) mod w */
+ if (!BN_copy(x, z))
goto err;
+composite:
+ if (enhanced) {
+ /* (Step 4.1.2) g = GCD(x-1, w) */
+ if (!BN_sub_word(x, 1) || !BN_gcd(g, x, w, ctx))
+ goto err;
+ /* (Steps 4.1.3 - 4.1.4) */
+ if (BN_is_one(g))
+ *status = BN_PRIMETEST_COMPOSITE_NOT_POWER_OF_PRIME;
+ else
+ *status = BN_PRIMETEST_COMPOSITE_WITH_FACTOR;
+ } else {
+ *status = BN_PRIMETEST_COMPOSITE;
}
+ ret = 1;
+ goto err;
+outer_loop: ;
+ /* (Step 4.1.5) */
if (!BN_GENCB_call(cb, 1, i))
goto err;
}
+ /* (Step 5) */
+ *status = BN_PRIMETEST_PROBABLY_PRIME;
ret = 1;
- err:
- if (ctx != NULL) {
- BN_CTX_end(ctx);
- if (ctx_passed == NULL)
- BN_CTX_free(ctx);
- }
+err:
+ BN_clear(g);
+ BN_clear(w1);
+ BN_clear(w3);
+ BN_clear(x);
+ BN_clear(m);
+ BN_clear(z);
+ BN_clear(b);
+ BN_CTX_end(ctx);
BN_MONT_CTX_free(mont);
-
return ret;
}
-static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1,
- const BIGNUM *a1_odd, int k, BN_CTX *ctx,
- BN_MONT_CTX *mont)
-{
- if (!BN_mod_exp_mont(w, w, a1_odd, a, ctx, mont)) /* w := w^a1_odd mod a */
- return -1;
- if (BN_is_one(w))
- return 0; /* probably prime */
- if (BN_cmp(w, a1) == 0)
- return 0; /* w == -1 (mod a), 'a' is probably prime */
- while (--k) {
- if (!BN_mod_mul(w, w, w, a, ctx)) /* w := w^2 mod a */
- return -1;
- if (BN_is_one(w))
- return 1; /* 'a' is composite, otherwise a previous 'w'
- * would have been == -1 (mod 'a') */
- if (BN_cmp(w, a1) == 0)
- return 0; /* w == -1 (mod a), 'a' is probably prime */
- }
- /*
- * If we get here, 'w' is the (a-1)/2-th power of the original 'w', and
- * it is neither -1 nor +1 -- so 'a' cannot be prime
- */
- bn_check_top(w);
- return 1;
-}
-
-static int probable_prime(BIGNUM *rnd, int bits, int safe, prime_t *mods)
+/*
+ * Generate a random number of |bits| bits that is probably prime by sieving.
+ * If |safe| != 0, it generates a safe prime.
+ * |mods| is a preallocated array that gets reused when called again.
+ *
+ * The probably prime is saved in |rnd|.
+ *
+ * Returns 1 on success and 0 on error.
+ */
+static int probable_prime(BIGNUM *rnd, int bits, int safe, prime_t *mods,
+ BN_CTX *ctx)
{
int i;
BN_ULONG delta;
- BN_ULONG maxdelta = BN_MASK2 - primes[NUMPRIMES - 1];
+ int trial_divisions = calc_trial_divisions(bits);
+ BN_ULONG maxdelta = BN_MASK2 - primes[trial_divisions - 1];
again:
- /* TODO: Not all primes are private */
- if (!BN_priv_rand(rnd, bits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ODD))
+ if (!BN_priv_rand_ex(rnd, bits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ODD, 0,
+ ctx))
return 0;
if (safe && !BN_set_bit(rnd, 1))
return 0;
/* we now have a random number 'rnd' to test. */
- for (i = 1; i < NUMPRIMES; i++) {
+ for (i = 1; i < trial_divisions; i++) {
BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]);
if (mod == (BN_ULONG)-1)
return 0;
@@ -290,7 +498,7 @@ static int probable_prime(BIGNUM *rnd, int bits, int safe, prime_t *mods)
}
delta = 0;
loop:
- for (i = 1; i < NUMPRIMES; i++) {
+ for (i = 1; i < trial_divisions; i++) {
/*
* check that rnd is a prime and also that
* gcd(rnd-1,primes) == 1 (except for 2)
@@ -317,6 +525,14 @@ static int probable_prime(BIGNUM *rnd, int bits, int safe, prime_t *mods)
return 1;
}
+/*
+ * Generate a random number |rnd| of |bits| bits that is probably prime
+ * and satisfies |rnd| % |add| == |rem| by sieving.
+ * If |safe| != 0, it generates a safe prime.
+ * |mods| is a preallocated array that gets reused when called again.
+ *
+ * Returns 1 on success and 0 on error.
+ */
static int probable_prime_dh(BIGNUM *rnd, int bits, int safe, prime_t *mods,
const BIGNUM *add, const BIGNUM *rem,
BN_CTX *ctx)
@@ -324,7 +540,8 @@ static int probable_prime_dh(BIGNUM *rnd, int bits, int safe, prime_t *mods,
int i, ret = 0;
BIGNUM *t1;
BN_ULONG delta;
- BN_ULONG maxdelta = BN_MASK2 - primes[NUMPRIMES - 1];
+ int trial_divisions = calc_trial_divisions(bits);
+ BN_ULONG maxdelta = BN_MASK2 - primes[trial_divisions - 1];
BN_CTX_start(ctx);
if ((t1 = BN_CTX_get(ctx)) == NULL)
@@ -334,7 +551,7 @@ static int probable_prime_dh(BIGNUM *rnd, int bits, int safe, prime_t *mods,
maxdelta = BN_MASK2 - BN_get_word(add);
again:
- if (!BN_rand(rnd, bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD))
+ if (!BN_rand_ex(rnd, bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD, 0, ctx))
goto err;
/* we need ((rnd-rem) % add) == 0 */
@@ -358,7 +575,7 @@ static int probable_prime_dh(BIGNUM *rnd, int bits, int safe, prime_t *mods,
}
/* we now have a random number 'rnd' to test. */
- for (i = 1; i < NUMPRIMES; i++) {
+ for (i = 1; i < trial_divisions; i++) {
BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]);
if (mod == (BN_ULONG)-1)
goto err;
@@ -366,7 +583,7 @@ static int probable_prime_dh(BIGNUM *rnd, int bits, int safe, prime_t *mods,
}
delta = 0;
loop:
- for (i = 1; i < NUMPRIMES; i++) {
+ for (i = 1; i < trial_divisions; i++) {
/* check that rnd is a prime */
if (bits <= 31 && delta <= 0x7fffffff
&& square(primes[i]) > BN_get_word(rnd) + delta)
diff --git a/crypto/bn/bn_prime.h b/crypto/bn/bn_prime.h
index 8f2d7e995a01..8a859ac02e26 100644
--- a/crypto/bn/bn_prime.h
+++ b/crypto/bn/bn_prime.h
@@ -2,9 +2,9 @@
* WARNING: do not edit!
* Generated by crypto/bn/bn_prime.pl
*
- * Copyright 1998-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/bn/bn_prime.pl b/crypto/bn/bn_prime.pl
index d2eaac6564f8..a7a764627b94 100644
--- a/crypto/bn/bn_prime.pl
+++ b/crypto/bn/bn_prime.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 1998-2022 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -11,6 +11,7 @@ use OpenSSL::copyright;
# The year the output file is generated.
my $YEAR = OpenSSL::copyright::year_of($0);
+
print <<"EOF";
/*
* WARNING: do not edit!
@@ -18,7 +19,7 @@ print <<"EOF";
*
* Copyright 1998-$YEAR The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/bn/bn_print.c b/crypto/bn/bn_print.c
index 17ac6e7cac1c..ccc954c5b1c0 100644
--- a/crypto/bn/bn_print.c
+++ b/crypto/bn/bn_print.c
@@ -1,292 +1,19 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
-#include "crypto/ctype.h"
-#include <limits.h>
-#include "internal/cryptlib.h"
-#include <openssl/buffer.h>
+#include <openssl/bio.h>
#include "bn_local.h"
static const char Hex[] = "0123456789ABCDEF";
-/* Must 'OPENSSL_free' the returned data */
-char *BN_bn2hex(const BIGNUM *a)
-{
- int i, j, v, z = 0;
- char *buf;
- char *p;
-
- if (BN_is_zero(a))
- return OPENSSL_strdup("0");
- buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2);
- if (buf == NULL) {
- BNerr(BN_F_BN_BN2HEX, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- p = buf;
- if (a->neg)
- *p++ = '-';
- for (i = a->top - 1; i >= 0; i--) {
- for (j = BN_BITS2 - 8; j >= 0; j -= 8) {
- /* strip leading zeros */
- v = (int)((a->d[i] >> j) & 0xff);
- if (z || v != 0) {
- *p++ = Hex[v >> 4];
- *p++ = Hex[v & 0x0f];
- z = 1;
- }
- }
- }
- *p = '\0';
- err:
- return buf;
-}
-
-/* Must 'OPENSSL_free' the returned data */
-char *BN_bn2dec(const BIGNUM *a)
-{
- int i = 0, num, ok = 0, n, tbytes;
- char *buf = NULL;
- char *p;
- BIGNUM *t = NULL;
- BN_ULONG *bn_data = NULL, *lp;
- int bn_data_num;
-
- /*-
- * get an upper bound for the length of the decimal integer
- * num <= (BN_num_bits(a) + 1) * log(2)
- * <= 3 * BN_num_bits(a) * 0.101 + log(2) + 1 (rounding error)
- * <= 3 * BN_num_bits(a) / 10 + 3 * BN_num_bits / 1000 + 1 + 1
- */
- i = BN_num_bits(a) * 3;
- num = (i / 10 + i / 1000 + 1) + 1;
- tbytes = num + 3; /* negative and terminator and one spare? */
- bn_data_num = num / BN_DEC_NUM + 1;
- bn_data = OPENSSL_malloc(bn_data_num * sizeof(BN_ULONG));
- buf = OPENSSL_malloc(tbytes);
- if (buf == NULL || bn_data == NULL) {
- BNerr(BN_F_BN_BN2DEC, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if ((t = BN_dup(a)) == NULL)
- goto err;
-
- p = buf;
- lp = bn_data;
- if (BN_is_zero(t)) {
- *p++ = '0';
- *p++ = '\0';
- } else {
- if (BN_is_negative(t))
- *p++ = '-';
-
- while (!BN_is_zero(t)) {
- if (lp - bn_data >= bn_data_num)
- goto err;
- *lp = BN_div_word(t, BN_DEC_CONV);
- if (*lp == (BN_ULONG)-1)
- goto err;
- lp++;
- }
- lp--;
- /*
- * We now have a series of blocks, BN_DEC_NUM chars in length, where
- * the last one needs truncation. The blocks need to be reversed in
- * order.
- */
- n = BIO_snprintf(p, tbytes - (size_t)(p - buf), BN_DEC_FMT1, *lp);
- if (n < 0)
- goto err;
- p += n;
- while (lp != bn_data) {
- lp--;
- n = BIO_snprintf(p, tbytes - (size_t)(p - buf), BN_DEC_FMT2, *lp);
- if (n < 0)
- goto err;
- p += n;
- }
- }
- ok = 1;
- err:
- OPENSSL_free(bn_data);
- BN_free(t);
- if (ok)
- return buf;
- OPENSSL_free(buf);
- return NULL;
-}
-
-int BN_hex2bn(BIGNUM **bn, const char *a)
-{
- BIGNUM *ret = NULL;
- BN_ULONG l = 0;
- int neg = 0, h, m, i, j, k, c;
- int num;
-
- if (a == NULL || *a == '\0')
- return 0;
-
- if (*a == '-') {
- neg = 1;
- a++;
- }
-
- for (i = 0; i <= INT_MAX / 4 && ossl_isxdigit(a[i]); i++)
- continue;
-
- if (i == 0 || i > INT_MAX / 4)
- return 0;
-
- num = i + neg;
- if (bn == NULL)
- return num;
-
- /* a is the start of the hex digits, and it is 'i' long */
- if (*bn == NULL) {
- if ((ret = BN_new()) == NULL)
- return 0;
- } else {
- ret = *bn;
- BN_zero(ret);
- }
-
- /* i is the number of hex digits */
- if (bn_expand(ret, i * 4) == NULL)
- goto err;
-
- j = i; /* least significant 'hex' */
- m = 0;
- h = 0;
- while (j > 0) {
- m = (BN_BYTES * 2 <= j) ? BN_BYTES * 2 : j;
- l = 0;
- for (;;) {
- c = a[j - m];
- k = OPENSSL_hexchar2int(c);
- if (k < 0)
- k = 0; /* paranoia */
- l = (l << 4) | k;
-
- if (--m <= 0) {
- ret->d[h++] = l;
- break;
- }
- }
- j -= BN_BYTES * 2;
- }
- ret->top = h;
- bn_correct_top(ret);
-
- *bn = ret;
- bn_check_top(ret);
- /* Don't set the negative flag if it's zero. */
- if (ret->top != 0)
- ret->neg = neg;
- return num;
- err:
- if (*bn == NULL)
- BN_free(ret);
- return 0;
-}
-
-int BN_dec2bn(BIGNUM **bn, const char *a)
-{
- BIGNUM *ret = NULL;
- BN_ULONG l = 0;
- int neg = 0, i, j;
- int num;
-
- if (a == NULL || *a == '\0')
- return 0;
- if (*a == '-') {
- neg = 1;
- a++;
- }
-
- for (i = 0; i <= INT_MAX / 4 && ossl_isdigit(a[i]); i++)
- continue;
-
- if (i == 0 || i > INT_MAX / 4)
- goto err;
-
- num = i + neg;
- if (bn == NULL)
- return num;
-
- /*
- * a is the start of the digits, and it is 'i' long. We chop it into
- * BN_DEC_NUM digits at a time
- */
- if (*bn == NULL) {
- if ((ret = BN_new()) == NULL)
- return 0;
- } else {
- ret = *bn;
- BN_zero(ret);
- }
-
- /* i is the number of digits, a bit of an over expand */
- if (bn_expand(ret, i * 4) == NULL)
- goto err;
-
- j = BN_DEC_NUM - i % BN_DEC_NUM;
- if (j == BN_DEC_NUM)
- j = 0;
- l = 0;
- while (--i >= 0) {
- l *= 10;
- l += *a - '0';
- a++;
- if (++j == BN_DEC_NUM) {
- if (!BN_mul_word(ret, BN_DEC_CONV)
- || !BN_add_word(ret, l))
- goto err;
- l = 0;
- j = 0;
- }
- }
-
- bn_correct_top(ret);
- *bn = ret;
- bn_check_top(ret);
- /* Don't set the negative flag if it's zero. */
- if (ret->top != 0)
- ret->neg = neg;
- return num;
- err:
- if (*bn == NULL)
- BN_free(ret);
- return 0;
-}
-
-int BN_asc2bn(BIGNUM **bn, const char *a)
-{
- const char *p = a;
-
- if (*p == '-')
- p++;
-
- if (p[0] == '0' && (p[1] == 'X' || p[1] == 'x')) {
- if (!BN_hex2bn(bn, p + 2))
- return 0;
- } else {
- if (!BN_dec2bn(bn, p))
- return 0;
- }
- /* Don't set the negative flag if it's zero. */
- if (*a == '-' && (*bn)->top != 0)
- (*bn)->neg = 1;
- return 1;
-}
-
-# ifndef OPENSSL_NO_STDIO
+#ifndef OPENSSL_NO_STDIO
int BN_print_fp(FILE *fp, const BIGNUM *a)
{
BIO *b;
@@ -299,7 +26,7 @@ int BN_print_fp(FILE *fp, const BIGNUM *a)
BIO_free(b);
return ret;
}
-# endif
+#endif
int BN_print(BIO *bp, const BIGNUM *a)
{
diff --git a/crypto/bn/bn_rand.c b/crypto/bn/bn_rand.c
index 6b4b50a068f1..2ca426ff76ed 100644
--- a/crypto/bn/bn_rand.c
+++ b/crypto/bn/bn_rand.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,18 +10,22 @@
#include <stdio.h>
#include <time.h>
#include "internal/cryptlib.h"
+#include "crypto/rand.h"
#include "bn_local.h"
#include <openssl/rand.h>
#include <openssl/sha.h>
+#include <openssl/evp.h>
typedef enum bnrand_flag_e {
NORMAL, TESTING, PRIVATE
} BNRAND_FLAG;
-static int bnrand(BNRAND_FLAG flag, BIGNUM *rnd, int bits, int top, int bottom)
+static int bnrand(BNRAND_FLAG flag, BIGNUM *rnd, int bits, int top, int bottom,
+ unsigned int strength, BN_CTX *ctx)
{
unsigned char *buf = NULL;
int b, ret = 0, bit, bytes, mask;
+ OSSL_LIB_CTX *libctx = ossl_bn_get_libctx(ctx);
if (bits == 0) {
if (top != BN_RAND_TOP_ANY || bottom != BN_RAND_BOTTOM_ANY)
@@ -38,12 +42,13 @@ static int bnrand(BNRAND_FLAG flag, BIGNUM *rnd, int bits, int top, int bottom)
buf = OPENSSL_malloc(bytes);
if (buf == NULL) {
- BNerr(BN_F_BNRAND, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
goto err;
}
/* make a random number and set the top and bottom bits */
- b = flag == NORMAL ? RAND_bytes(buf, bytes) : RAND_priv_bytes(buf, bytes);
+ b = flag == NORMAL ? RAND_bytes_ex(libctx, buf, bytes, strength)
+ : RAND_priv_bytes_ex(libctx, buf, bytes, strength);
if (b <= 0)
goto err;
@@ -55,7 +60,7 @@ static int bnrand(BNRAND_FLAG flag, BIGNUM *rnd, int bits, int top, int bottom)
unsigned char c;
for (i = 0; i < bytes; i++) {
- if (RAND_bytes(&c, 1) <= 0)
+ if (RAND_bytes_ex(libctx, &c, 1, strength) <= 0)
goto err;
if (c >= 128 && i > 0)
buf[i] = buf[i - 1];
@@ -90,33 +95,54 @@ static int bnrand(BNRAND_FLAG flag, BIGNUM *rnd, int bits, int top, int bottom)
return ret;
toosmall:
- BNerr(BN_F_BNRAND, BN_R_BITS_TOO_SMALL);
+ ERR_raise(ERR_LIB_BN, BN_R_BITS_TOO_SMALL);
return 0;
}
+int BN_rand_ex(BIGNUM *rnd, int bits, int top, int bottom,
+ unsigned int strength, BN_CTX *ctx)
+{
+ return bnrand(NORMAL, rnd, bits, top, bottom, strength, ctx);
+}
+#ifndef FIPS_MODULE
int BN_rand(BIGNUM *rnd, int bits, int top, int bottom)
{
- return bnrand(NORMAL, rnd, bits, top, bottom);
+ return bnrand(NORMAL, rnd, bits, top, bottom, 0, NULL);
}
int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom)
{
- return bnrand(TESTING, rnd, bits, top, bottom);
+ return bnrand(TESTING, rnd, bits, top, bottom, 0, NULL);
+}
+#endif
+
+int BN_priv_rand_ex(BIGNUM *rnd, int bits, int top, int bottom,
+ unsigned int strength, BN_CTX *ctx)
+{
+ return bnrand(PRIVATE, rnd, bits, top, bottom, strength, ctx);
}
+#ifndef FIPS_MODULE
int BN_priv_rand(BIGNUM *rnd, int bits, int top, int bottom)
{
- return bnrand(PRIVATE, rnd, bits, top, bottom);
+ return bnrand(PRIVATE, rnd, bits, top, bottom, 0, NULL);
}
+#endif
/* random number r: 0 <= r < range */
-static int bnrand_range(BNRAND_FLAG flag, BIGNUM *r, const BIGNUM *range)
+static int bnrand_range(BNRAND_FLAG flag, BIGNUM *r, const BIGNUM *range,
+ unsigned int strength, BN_CTX *ctx)
{
int n;
int count = 100;
+ if (r == NULL) {
+ ERR_raise(ERR_LIB_BN, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
if (range->neg || BN_is_zero(range)) {
- BNerr(BN_F_BNRAND_RANGE, BN_R_INVALID_RANGE);
+ ERR_raise(ERR_LIB_BN, BN_R_INVALID_RANGE);
return 0;
}
@@ -132,7 +158,8 @@ static int bnrand_range(BNRAND_FLAG flag, BIGNUM *r, const BIGNUM *range)
* than range
*/
do {
- if (!bnrand(flag, r, n + 1, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
+ if (!bnrand(flag, r, n + 1, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY,
+ strength, ctx))
return 0;
/*
@@ -150,7 +177,7 @@ static int bnrand_range(BNRAND_FLAG flag, BIGNUM *r, const BIGNUM *range)
}
if (!--count) {
- BNerr(BN_F_BNRAND_RANGE, BN_R_TOO_MANY_ITERATIONS);
+ ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS);
return 0;
}
@@ -159,11 +186,12 @@ static int bnrand_range(BNRAND_FLAG flag, BIGNUM *r, const BIGNUM *range)
} else {
do {
/* range = 11..._2 or range = 101..._2 */
- if (!bnrand(flag, r, n, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
+ if (!bnrand(flag, r, n, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0,
+ ctx))
return 0;
if (!--count) {
- BNerr(BN_F_BNRAND_RANGE, BN_R_TOO_MANY_ITERATIONS);
+ ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS);
return 0;
}
}
@@ -174,16 +202,32 @@ static int bnrand_range(BNRAND_FLAG flag, BIGNUM *r, const BIGNUM *range)
return 1;
}
+int BN_rand_range_ex(BIGNUM *r, const BIGNUM *range, unsigned int strength,
+ BN_CTX *ctx)
+{
+ return bnrand_range(NORMAL, r, range, strength, ctx);
+}
+
+#ifndef FIPS_MODULE
int BN_rand_range(BIGNUM *r, const BIGNUM *range)
{
- return bnrand_range(NORMAL, r, range);
+ return bnrand_range(NORMAL, r, range, 0, NULL);
}
+#endif
+int BN_priv_rand_range_ex(BIGNUM *r, const BIGNUM *range, unsigned int strength,
+ BN_CTX *ctx)
+{
+ return bnrand_range(PRIVATE, r, range, strength, ctx);
+}
+
+#ifndef FIPS_MODULE
int BN_priv_rand_range(BIGNUM *r, const BIGNUM *range)
{
- return bnrand_range(PRIVATE, r, range);
+ return bnrand_range(PRIVATE, r, range, 0, NULL);
}
+# ifndef OPENSSL_NO_DEPRECATED_3_0
int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom)
{
return BN_rand(rnd, bits, top, bottom);
@@ -193,6 +237,8 @@ int BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range)
{
return BN_rand_range(r, range);
}
+# endif
+#endif
/*
* BN_generate_dsa_nonce generates a random number 0 <= out < range. Unlike
@@ -206,7 +252,7 @@ int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range,
const BIGNUM *priv, const unsigned char *message,
size_t message_len, BN_CTX *ctx)
{
- SHA512_CTX sha;
+ EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
/*
* We use 512 bits of random data per iteration to ensure that we have at
* least |range| bits of randomness.
@@ -217,8 +263,13 @@ int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range,
/* We generate |range|+8 bytes of random output. */
const unsigned num_k_bytes = BN_num_bytes(range) + 8;
unsigned char private_bytes[96];
- unsigned char *k_bytes;
+ unsigned char *k_bytes = NULL;
int ret = 0;
+ EVP_MD *md = NULL;
+ OSSL_LIB_CTX *libctx = ossl_bn_get_libctx(ctx);
+
+ if (mdctx == NULL)
+ goto err;
k_bytes = OPENSSL_malloc(num_k_bytes);
if (k_bytes == NULL)
@@ -231,19 +282,27 @@ int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range,
* large and we don't handle this case in order to avoid leaking the
* length of the private key.
*/
- BNerr(BN_F_BN_GENERATE_DSA_NONCE, BN_R_PRIVATE_KEY_TOO_LARGE);
+ ERR_raise(ERR_LIB_BN, BN_R_PRIVATE_KEY_TOO_LARGE);
goto err;
}
+ md = EVP_MD_fetch(libctx, "SHA512", NULL);
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_BN, BN_R_NO_SUITABLE_DIGEST);
+ goto err;
+ }
for (done = 0; done < num_k_bytes;) {
- if (RAND_priv_bytes(random_bytes, sizeof(random_bytes)) != 1)
+ if (RAND_priv_bytes_ex(libctx, random_bytes, sizeof(random_bytes), 0) <= 0)
+ goto err;
+
+ if (!EVP_DigestInit_ex(mdctx, md, NULL)
+ || !EVP_DigestUpdate(mdctx, &done, sizeof(done))
+ || !EVP_DigestUpdate(mdctx, private_bytes,
+ sizeof(private_bytes))
+ || !EVP_DigestUpdate(mdctx, message, message_len)
+ || !EVP_DigestUpdate(mdctx, random_bytes, sizeof(random_bytes))
+ || !EVP_DigestFinal_ex(mdctx, digest, NULL))
goto err;
- SHA512_Init(&sha);
- SHA512_Update(&sha, &done, sizeof(done));
- SHA512_Update(&sha, private_bytes, sizeof(private_bytes));
- SHA512_Update(&sha, message, message_len);
- SHA512_Update(&sha, random_bytes, sizeof(random_bytes));
- SHA512_Final(digest, &sha);
todo = num_k_bytes - done;
if (todo > SHA512_DIGEST_LENGTH)
@@ -259,7 +318,11 @@ int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range,
ret = 1;
err:
- OPENSSL_free(k_bytes);
+ EVP_MD_CTX_free(mdctx);
+ EVP_MD_free(md);
+ OPENSSL_clear_free(k_bytes, num_k_bytes);
+ OPENSSL_cleanse(digest, sizeof(digest));
+ OPENSSL_cleanse(random_bytes, sizeof(random_bytes));
OPENSSL_cleanse(private_bytes, sizeof(private_bytes));
return ret;
}
diff --git a/crypto/bn/bn_recp.c b/crypto/bn/bn_recp.c
index e82231334123..96a6b19ab0da 100644
--- a/crypto/bn/bn_recp.c
+++ b/crypto/bn/bn_recp.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -22,7 +22,7 @@ BN_RECP_CTX *BN_RECP_CTX_new(void)
BN_RECP_CTX *ret;
if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
- BNerr(BN_F_BN_RECP_CTX_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -146,7 +146,7 @@ int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
j = 0;
while (BN_ucmp(r, &(recp->N)) >= 0) {
if (j++ > 2) {
- BNerr(BN_F_BN_DIV_RECP, BN_R_BAD_RECIPROCAL);
+ ERR_raise(ERR_LIB_BN, BN_R_BAD_RECIPROCAL);
goto err;
}
if (!BN_usub(r, r, &(recp->N)))
diff --git a/crypto/bn/bn_rsa_fips186_4.c b/crypto/bn/bn_rsa_fips186_4.c
new file mode 100644
index 000000000000..abce1aa2d830
--- /dev/null
+++ b/crypto/bn/bn_rsa_fips186_4.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2018-2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * According to NIST SP800-131A "Transitioning the use of cryptographic
+ * algorithms and key lengths" Generation of 1024 bit RSA keys are no longer
+ * allowed for signatures (Table 2) or key transport (Table 5). In the code
+ * below any attempt to generate 1024 bit RSA keys will result in an error (Note
+ * that digital signature verification can still use deprecated 1024 bit keys).
+ *
+ * FIPS 186-4 relies on the use of the auxiliary primes p1, p2, q1 and q2 that
+ * must be generated before the module generates the RSA primes p and q.
+ * Table B.1 in FIPS 186-4 specifies RSA modulus lengths of 2048 and
+ * 3072 bits only, the min/max total length of the auxiliary primes.
+ * FIPS 186-5 Table A.1 includes an additional entry for 4096 which has been
+ * included here.
+ */
+#include <stdio.h>
+#include <openssl/bn.h>
+#include "bn_local.h"
+#include "crypto/bn.h"
+#include "internal/nelem.h"
+
+#if BN_BITS2 == 64
+# define BN_DEF(lo, hi) (BN_ULONG)hi<<32|lo
+#else
+# define BN_DEF(lo, hi) lo, hi
+#endif
+
+/* 1 / sqrt(2) * 2^256, rounded up */
+static const BN_ULONG inv_sqrt_2_val[] = {
+ BN_DEF(0x83339916UL, 0xED17AC85UL), BN_DEF(0x893BA84CUL, 0x1D6F60BAUL),
+ BN_DEF(0x754ABE9FUL, 0x597D89B3UL), BN_DEF(0xF9DE6484UL, 0xB504F333UL)
+};
+
+const BIGNUM ossl_bn_inv_sqrt_2 = {
+ (BN_ULONG *)inv_sqrt_2_val,
+ OSSL_NELEM(inv_sqrt_2_val),
+ OSSL_NELEM(inv_sqrt_2_val),
+ 0,
+ BN_FLG_STATIC_DATA
+};
+
+/*
+ * FIPS 186-5 Table A.1. "Min length of auxiliary primes p1, p2, q1, q2".
+ * (FIPS 186-5 has an entry for >= 4096 bits).
+ *
+ * Params:
+ * nbits The key size in bits.
+ * Returns:
+ * The minimum size of the auxiliary primes or 0 if nbits is invalid.
+ */
+static int bn_rsa_fips186_5_aux_prime_min_size(int nbits)
+{
+ if (nbits >= 4096)
+ return 201;
+ if (nbits >= 3072)
+ return 171;
+ if (nbits >= 2048)
+ return 141;
+ return 0;
+}
+
+/*
+ * FIPS 186-5 Table A.1 "Max of len(p1) + len(p2) and
+ * len(q1) + len(q2) for p,q Probable Primes".
+ * (FIPS 186-5 has an entry for >= 4096 bits).
+ * Params:
+ * nbits The key size in bits.
+ * Returns:
+ * The maximum length or 0 if nbits is invalid.
+ */
+static int bn_rsa_fips186_5_aux_prime_max_sum_size_for_prob_primes(int nbits)
+{
+ if (nbits >= 4096)
+ return 2030;
+ if (nbits >= 3072)
+ return 1518;
+ if (nbits >= 2048)
+ return 1007;
+ return 0;
+}
+
+/*
+ * Find the first odd integer that is a probable prime.
+ *
+ * See section FIPS 186-4 B.3.6 (Steps 4.2/5.2).
+ *
+ * Params:
+ * Xp1 The passed in starting point to find a probably prime.
+ * p1 The returned probable prime (first odd integer >= Xp1)
+ * ctx A BN_CTX object.
+ * cb An optional BIGNUM callback.
+ * Returns: 1 on success otherwise it returns 0.
+ */
+static int bn_rsa_fips186_4_find_aux_prob_prime(const BIGNUM *Xp1,
+ BIGNUM *p1, BN_CTX *ctx,
+ BN_GENCB *cb)
+{
+ int ret = 0;
+ int i = 0;
+ int tmp = 0;
+
+ if (BN_copy(p1, Xp1) == NULL)
+ return 0;
+ BN_set_flags(p1, BN_FLG_CONSTTIME);
+
+ /* Find the first odd number >= Xp1 that is probably prime */
+ for(;;) {
+ i++;
+ BN_GENCB_call(cb, 0, i);
+ /* MR test with trial division */
+ tmp = BN_check_prime(p1, ctx, cb);
+ if (tmp > 0)
+ break;
+ if (tmp < 0)
+ goto err;
+ /* Get next odd number */
+ if (!BN_add_word(p1, 2))
+ goto err;
+ }
+ BN_GENCB_call(cb, 2, i);
+ ret = 1;
+err:
+ return ret;
+}
+
+/*
+ * Generate a probable prime (p or q).
+ *
+ * See FIPS 186-4 B.3.6 (Steps 4 & 5)
+ *
+ * Params:
+ * p The returned probable prime.
+ * Xpout An optionally returned random number used during generation of p.
+ * p1, p2 The returned auxiliary primes. If NULL they are not returned.
+ * Xp An optional passed in value (that is random number used during
+ * generation of p).
+ * Xp1, Xp2 Optional passed in values that are normally generated
+ * internally. Used to find p1, p2.
+ * nlen The bit length of the modulus (the key size).
+ * e The public exponent.
+ * ctx A BN_CTX object.
+ * cb An optional BIGNUM callback.
+ * Returns: 1 on success otherwise it returns 0.
+ */
+int ossl_bn_rsa_fips186_4_gen_prob_primes(BIGNUM *p, BIGNUM *Xpout,
+ BIGNUM *p1, BIGNUM *p2,
+ const BIGNUM *Xp, const BIGNUM *Xp1,
+ const BIGNUM *Xp2, int nlen,
+ const BIGNUM *e, BN_CTX *ctx,
+ BN_GENCB *cb)
+{
+ int ret = 0;
+ BIGNUM *p1i = NULL, *p2i = NULL, *Xp1i = NULL, *Xp2i = NULL;
+ int bitlen;
+
+ if (p == NULL || Xpout == NULL)
+ return 0;
+
+ BN_CTX_start(ctx);
+
+ p1i = (p1 != NULL) ? p1 : BN_CTX_get(ctx);
+ p2i = (p2 != NULL) ? p2 : BN_CTX_get(ctx);
+ Xp1i = (Xp1 != NULL) ? (BIGNUM *)Xp1 : BN_CTX_get(ctx);
+ Xp2i = (Xp2 != NULL) ? (BIGNUM *)Xp2 : BN_CTX_get(ctx);
+ if (p1i == NULL || p2i == NULL || Xp1i == NULL || Xp2i == NULL)
+ goto err;
+
+ bitlen = bn_rsa_fips186_5_aux_prime_min_size(nlen);
+ if (bitlen == 0)
+ goto err;
+
+ /* (Steps 4.1/5.1): Randomly generate Xp1 if it is not passed in */
+ if (Xp1 == NULL) {
+ /* Set the top and bottom bits to make it odd and the correct size */
+ if (!BN_priv_rand_ex(Xp1i, bitlen, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD,
+ 0, ctx))
+ goto err;
+ }
+ /* (Steps 4.1/5.1): Randomly generate Xp2 if it is not passed in */
+ if (Xp2 == NULL) {
+ /* Set the top and bottom bits to make it odd and the correct size */
+ if (!BN_priv_rand_ex(Xp2i, bitlen, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD,
+ 0, ctx))
+ goto err;
+ }
+
+ /* (Steps 4.2/5.2) - find first auxiliary probable primes */
+ if (!bn_rsa_fips186_4_find_aux_prob_prime(Xp1i, p1i, ctx, cb)
+ || !bn_rsa_fips186_4_find_aux_prob_prime(Xp2i, p2i, ctx, cb))
+ goto err;
+ /* (Table B.1) auxiliary prime Max length check */
+ if ((BN_num_bits(p1i) + BN_num_bits(p2i)) >=
+ bn_rsa_fips186_5_aux_prime_max_sum_size_for_prob_primes(nlen))
+ goto err;
+ /* (Steps 4.3/5.3) - generate prime */
+ if (!ossl_bn_rsa_fips186_4_derive_prime(p, Xpout, Xp, p1i, p2i, nlen, e,
+ ctx, cb))
+ goto err;
+ ret = 1;
+err:
+ /* Zeroize any internally generated values that are not returned */
+ if (p1 == NULL)
+ BN_clear(p1i);
+ if (p2 == NULL)
+ BN_clear(p2i);
+ if (Xp1 == NULL)
+ BN_clear(Xp1i);
+ if (Xp2 == NULL)
+ BN_clear(Xp2i);
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+/*
+ * Constructs a probable prime (a candidate for p or q) using 2 auxiliary
+ * prime numbers and the Chinese Remainder Theorem.
+ *
+ * See FIPS 186-4 C.9 "Compute a Probable Prime Factor Based on Auxiliary
+ * Primes". Used by FIPS 186-4 B.3.6 Section (4.3) for p and Section (5.3) for q.
+ *
+ * Params:
+ * Y The returned prime factor (private_prime_factor) of the modulus n.
+ * X The returned random number used during generation of the prime factor.
+ * Xin An optional passed in value for X used for testing purposes.
+ * r1 An auxiliary prime.
+ * r2 An auxiliary prime.
+ * nlen The desired length of n (the RSA modulus).
+ * e The public exponent.
+ * ctx A BN_CTX object.
+ * cb An optional BIGNUM callback object.
+ * Returns: 1 on success otherwise it returns 0.
+ * Assumptions:
+ * Y, X, r1, r2, e are not NULL.
+ */
+int ossl_bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin,
+ const BIGNUM *r1, const BIGNUM *r2,
+ int nlen, const BIGNUM *e, BN_CTX *ctx,
+ BN_GENCB *cb)
+{
+ int ret = 0;
+ int i, imax;
+ int bits = nlen >> 1;
+ BIGNUM *tmp, *R, *r1r2x2, *y1, *r1x2;
+ BIGNUM *base, *range;
+
+ BN_CTX_start(ctx);
+
+ base = BN_CTX_get(ctx);
+ range = BN_CTX_get(ctx);
+ R = BN_CTX_get(ctx);
+ tmp = BN_CTX_get(ctx);
+ r1r2x2 = BN_CTX_get(ctx);
+ y1 = BN_CTX_get(ctx);
+ r1x2 = BN_CTX_get(ctx);
+ if (r1x2 == NULL)
+ goto err;
+
+ if (Xin != NULL && BN_copy(X, Xin) == NULL)
+ goto err;
+
+ /*
+ * We need to generate a random number X in the range
+ * 1/sqrt(2) * 2^(nlen/2) <= X < 2^(nlen/2).
+ * We can rewrite that as:
+ * base = 1/sqrt(2) * 2^(nlen/2)
+ * range = ((2^(nlen/2))) - (1/sqrt(2) * 2^(nlen/2))
+ * X = base + random(range)
+ * We only have the first 256 bit of 1/sqrt(2)
+ */
+ if (Xin == NULL) {
+ if (bits < BN_num_bits(&ossl_bn_inv_sqrt_2))
+ goto err;
+ if (!BN_lshift(base, &ossl_bn_inv_sqrt_2,
+ bits - BN_num_bits(&ossl_bn_inv_sqrt_2))
+ || !BN_lshift(range, BN_value_one(), bits)
+ || !BN_sub(range, range, base))
+ goto err;
+ }
+
+ if (!(BN_lshift1(r1x2, r1)
+ /* (Step 1) GCD(2r1, r2) = 1 */
+ && BN_gcd(tmp, r1x2, r2, ctx)
+ && BN_is_one(tmp)
+ /* (Step 2) R = ((r2^-1 mod 2r1) * r2) - ((2r1^-1 mod r2)*2r1) */
+ && BN_mod_inverse(R, r2, r1x2, ctx)
+ && BN_mul(R, R, r2, ctx) /* R = (r2^-1 mod 2r1) * r2 */
+ && BN_mod_inverse(tmp, r1x2, r2, ctx)
+ && BN_mul(tmp, tmp, r1x2, ctx) /* tmp = (2r1^-1 mod r2)*2r1 */
+ && BN_sub(R, R, tmp)
+ /* Calculate 2r1r2 */
+ && BN_mul(r1r2x2, r1x2, r2, ctx)))
+ goto err;
+ /* Make positive by adding the modulus */
+ if (BN_is_negative(R) && !BN_add(R, R, r1r2x2))
+ goto err;
+
+ /*
+ * In FIPS 186-4 imax was set to 5 * nlen/2.
+ * Analysis by Allen Roginsky (See https://csrc.nist.gov/CSRC/media/Publications/fips/186/4/final/documents/comments-received-fips186-4-december-2015.pdf
+ * page 68) indicates this has a 1 in 2 million chance of failure.
+ * The number has been updated to 20 * nlen/2 as used in
+ * FIPS186-5 Appendix B.9 Step 9.
+ */
+ imax = 20 * bits; /* max = 20/2 * nbits */
+ for (;;) {
+ if (Xin == NULL) {
+ /*
+ * (Step 3) Choose Random X such that
+ * sqrt(2) * 2^(nlen/2-1) <= Random X <= (2^(nlen/2)) - 1.
+ */
+ if (!BN_priv_rand_range_ex(X, range, 0, ctx) || !BN_add(X, X, base))
+ goto end;
+ }
+ /* (Step 4) Y = X + ((R - X) mod 2r1r2) */
+ if (!BN_mod_sub(Y, R, X, r1r2x2, ctx) || !BN_add(Y, Y, X))
+ goto err;
+ /* (Step 5) */
+ i = 0;
+ for (;;) {
+ /* (Step 6) */
+ if (BN_num_bits(Y) > bits) {
+ if (Xin == NULL)
+ break; /* Randomly Generated X so Go back to Step 3 */
+ else
+ goto err; /* X is not random so it will always fail */
+ }
+ BN_GENCB_call(cb, 0, 2);
+
+ /* (Step 7) If GCD(Y-1) == 1 & Y is probably prime then return Y */
+ if (BN_copy(y1, Y) == NULL
+ || !BN_sub_word(y1, 1)
+ || !BN_gcd(tmp, y1, e, ctx))
+ goto err;
+ if (BN_is_one(tmp)) {
+ int rv = BN_check_prime(Y, ctx, cb);
+
+ if (rv > 0)
+ goto end;
+ if (rv < 0)
+ goto err;
+ }
+ /* (Step 8-10) */
+ if (++i >= imax) {
+ ERR_raise(ERR_LIB_BN, BN_R_NO_PRIME_CANDIDATE);
+ goto err;
+ }
+ if (!BN_add(Y, Y, r1r2x2))
+ goto err;
+ }
+ }
+end:
+ ret = 1;
+ BN_GENCB_call(cb, 3, 0);
+err:
+ BN_clear(y1);
+ BN_CTX_end(ctx);
+ return ret;
+}
diff --git a/crypto/bn/bn_shift.c b/crypto/bn/bn_shift.c
index 210a83f586d2..8fcb04324e6d 100644
--- a/crypto/bn/bn_shift.c
+++ b/crypto/bn/bn_shift.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -83,7 +83,7 @@ int BN_lshift(BIGNUM *r, const BIGNUM *a, int n)
int ret;
if (n < 0) {
- BNerr(BN_F_BN_LSHIFT, BN_R_INVALID_SHIFT);
+ ERR_raise(ERR_LIB_BN, BN_R_INVALID_SHIFT);
return 0;
}
@@ -152,7 +152,7 @@ int BN_rshift(BIGNUM *r, const BIGNUM *a, int n)
int ret = 0;
if (n < 0) {
- BNerr(BN_F_BN_RSHIFT, BN_R_INVALID_SHIFT);
+ ERR_raise(ERR_LIB_BN, BN_R_INVALID_SHIFT);
return 0;
}
diff --git a/crypto/bn/bn_sparc.c b/crypto/bn/bn_sparc.c
new file mode 100644
index 000000000000..a810c3b1faee
--- /dev/null
+++ b/crypto/bn/bn_sparc.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include <openssl/bn.h>
+#include "internal/cryptlib.h"
+#include "crypto/sparc_arch.h"
+#include "bn_local.h" /* for definition of bn_mul_mont */
+
+int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ const BN_ULONG *np, const BN_ULONG *n0, int num)
+{
+ int bn_mul_mont_vis3(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ const BN_ULONG *np, const BN_ULONG *n0, int num);
+ int bn_mul_mont_fpu(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ const BN_ULONG *np, const BN_ULONG *n0, int num);
+ int bn_mul_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ const BN_ULONG *np, const BN_ULONG *n0, int num);
+
+ if (!(num & 1) && num >= 6) {
+ if ((num & 15) == 0 && num <= 64 &&
+ (OPENSSL_sparcv9cap_P[1] & (CFR_MONTMUL | CFR_MONTSQR)) ==
+ (CFR_MONTMUL | CFR_MONTSQR)) {
+ typedef int (*bn_mul_mont_f) (BN_ULONG *rp, const BN_ULONG *ap,
+ const BN_ULONG *bp,
+ const BN_ULONG *np,
+ const BN_ULONG *n0);
+ int bn_mul_mont_t4_8(BN_ULONG *rp, const BN_ULONG *ap,
+ const BN_ULONG *bp, const BN_ULONG *np,
+ const BN_ULONG *n0);
+ int bn_mul_mont_t4_16(BN_ULONG *rp, const BN_ULONG *ap,
+ const BN_ULONG *bp, const BN_ULONG *np,
+ const BN_ULONG *n0);
+ int bn_mul_mont_t4_24(BN_ULONG *rp, const BN_ULONG *ap,
+ const BN_ULONG *bp, const BN_ULONG *np,
+ const BN_ULONG *n0);
+ int bn_mul_mont_t4_32(BN_ULONG *rp, const BN_ULONG *ap,
+ const BN_ULONG *bp, const BN_ULONG *np,
+ const BN_ULONG *n0);
+ static const bn_mul_mont_f funcs[4] = {
+ bn_mul_mont_t4_8, bn_mul_mont_t4_16,
+ bn_mul_mont_t4_24, bn_mul_mont_t4_32
+ };
+ bn_mul_mont_f worker = funcs[num / 16 - 1];
+
+ if ((*worker) (rp, ap, bp, np, n0))
+ return 1;
+ /* retry once and fall back */
+ if ((*worker) (rp, ap, bp, np, n0))
+ return 1;
+ return bn_mul_mont_vis3(rp, ap, bp, np, n0, num);
+ }
+ if ((OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS3))
+ return bn_mul_mont_vis3(rp, ap, bp, np, n0, num);
+ else if (num >= 8 &&
+ /*
+ * bn_mul_mont_fpu doesn't use FMADD, we just use the
+ * flag to detect when FPU path is preferable in cases
+ * when current heuristics is unreliable. [it works
+ * out because FMADD-capable processors where FPU
+ * code path is undesirable are also VIS3-capable and
+ * VIS3 code path takes precedence.]
+ */
+ ( (OPENSSL_sparcv9cap_P[0] & SPARCV9_FMADD) ||
+ (OPENSSL_sparcv9cap_P[0] &
+ (SPARCV9_PREFER_FPU | SPARCV9_VIS1)) ==
+ (SPARCV9_PREFER_FPU | SPARCV9_VIS1) ))
+ return bn_mul_mont_fpu(rp, ap, bp, np, n0, num);
+ }
+ return bn_mul_mont_int(rp, ap, bp, np, n0, num);
+}
diff --git a/crypto/bn/bn_sqr.c b/crypto/bn/bn_sqr.c
index 7f3a179177b6..990bed90b590 100644
--- a/crypto/bn/bn_sqr.c
+++ b/crypto/bn/bn_sqr.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/bn/bn_sqrt.c b/crypto/bn/bn_sqrt.c
index 6a42ce8a9413..5c77e72132d4 100644
--- a/crypto/bn/bn_sqrt.c
+++ b/crypto/bn/bn_sqrt.c
@@ -1,7 +1,7 @@
/*
* Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -23,6 +23,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
int r;
BIGNUM *A, *b, *q, *t, *x, *y;
int e, i, j;
+ int used_ctx = 0;
if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) {
if (BN_abs_is_word(p, 2)) {
@@ -39,7 +40,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
return ret;
}
- BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME);
+ ERR_raise(ERR_LIB_BN, BN_R_P_IS_NOT_PRIME);
return NULL;
}
@@ -58,6 +59,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
}
BN_CTX_start(ctx);
+ used_ctx = 1;
A = BN_CTX_get(ctx);
b = BN_CTX_get(ctx);
q = BN_CTX_get(ctx);
@@ -181,7 +183,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
if (!BN_set_word(y, i))
goto end;
} else {
- if (!BN_priv_rand(y, BN_num_bits(p), 0, 0))
+ if (!BN_priv_rand_ex(y, BN_num_bits(p), 0, 0, 0, ctx))
goto end;
if (BN_ucmp(y, p) >= 0) {
if (!(p->neg ? BN_add : BN_sub) (y, y, p))
@@ -198,7 +200,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
goto end;
if (r == 0) {
/* m divides p */
- BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME);
+ ERR_raise(ERR_LIB_BN, BN_R_P_IS_NOT_PRIME);
goto end;
}
}
@@ -210,7 +212,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
* than just bad luck. Even if p is not prime, we should have found
* some y such that r == -1.
*/
- BNerr(BN_F_BN_MOD_SQRT, BN_R_TOO_MANY_ITERATIONS);
+ ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS);
goto end;
}
@@ -225,7 +227,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
if (!BN_mod_exp(y, y, q, p, ctx))
goto end;
if (BN_is_one(y)) {
- BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME);
+ ERR_raise(ERR_LIB_BN, BN_R_P_IS_NOT_PRIME);
goto end;
}
@@ -317,7 +319,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
}
/* If not found, a is not a square or p is not prime. */
if (i >= e) {
- BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE);
+ ERR_raise(ERR_LIB_BN, BN_R_NOT_A_SQUARE);
goto end;
}
@@ -348,7 +350,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
err = 1;
if (!err && 0 != BN_cmp(x, A)) {
- BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE);
+ ERR_raise(ERR_LIB_BN, BN_R_NOT_A_SQUARE);
err = 1;
}
}
@@ -359,7 +361,8 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
BN_clear_free(ret);
ret = NULL;
}
- BN_CTX_end(ctx);
+ if (used_ctx)
+ BN_CTX_end(ctx);
bn_check_top(ret);
return ret;
}
diff --git a/crypto/bn/bn_srp.c b/crypto/bn/bn_srp.c
index 820757be60e3..ffb8fc61e0fe 100644
--- a/crypto/bn/bn_srp.c
+++ b/crypto/bn/bn_srp.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -48,7 +48,7 @@ static const BN_ULONG bn_group_1024_value[] = {
bn_pack4(0xEEAF, 0x0AB9, 0xADB3, 0x8DD6)
};
-const BIGNUM bn_group_1024 = {
+const BIGNUM ossl_bn_group_1024 = {
(BN_ULONG *)bn_group_1024_value,
OSSL_NELEM(bn_group_1024_value),
OSSL_NELEM(bn_group_1024_value),
@@ -83,7 +83,7 @@ static const BN_ULONG bn_group_1536_value[] = {
bn_pack4(0x9DEF, 0x3CAF, 0xB939, 0x277A)
};
-const BIGNUM bn_group_1536 = {
+const BIGNUM ossl_bn_group_1536 = {
(BN_ULONG *)bn_group_1536_value,
OSSL_NELEM(bn_group_1536_value),
OSSL_NELEM(bn_group_1536_value),
@@ -126,7 +126,7 @@ static const BN_ULONG bn_group_2048_value[] = {
bn_pack4(0xAC6B, 0xDB41, 0x324A, 0x9A9B)
};
-const BIGNUM bn_group_2048 = {
+const BIGNUM ossl_bn_group_2048 = {
(BN_ULONG *)bn_group_2048_value,
OSSL_NELEM(bn_group_2048_value),
OSSL_NELEM(bn_group_2048_value),
@@ -185,7 +185,7 @@ static const BN_ULONG bn_group_3072_value[] = {
bn_pack4(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF)
};
-const BIGNUM bn_group_3072 = {
+const BIGNUM ossl_bn_group_3072 = {
(BN_ULONG *)bn_group_3072_value,
OSSL_NELEM(bn_group_3072_value),
OSSL_NELEM(bn_group_3072_value),
@@ -260,7 +260,7 @@ static const BN_ULONG bn_group_4096_value[] = {
bn_pack4(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF)
};
-const BIGNUM bn_group_4096 = {
+const BIGNUM ossl_bn_group_4096 = {
(BN_ULONG *)bn_group_4096_value,
OSSL_NELEM(bn_group_4096_value),
OSSL_NELEM(bn_group_4096_value),
@@ -367,7 +367,7 @@ static const BN_ULONG bn_group_6144_value[] = {
bn_pack4(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF)
};
-const BIGNUM bn_group_6144 = {
+const BIGNUM ossl_bn_group_6144 = {
(BN_ULONG *)bn_group_6144_value,
OSSL_NELEM(bn_group_6144_value),
OSSL_NELEM(bn_group_6144_value),
@@ -506,7 +506,7 @@ static const BN_ULONG bn_group_8192_value[] = {
bn_pack4(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF)
};
-const BIGNUM bn_group_8192 = {
+const BIGNUM ossl_bn_group_8192 = {
(BN_ULONG *)bn_group_8192_value,
OSSL_NELEM(bn_group_8192_value),
OSSL_NELEM(bn_group_8192_value),
@@ -516,7 +516,7 @@ const BIGNUM bn_group_8192 = {
static const BN_ULONG bn_generator_19_value[] = { 19 };
-const BIGNUM bn_generator_19 = {
+const BIGNUM ossl_bn_generator_19 = {
(BN_ULONG *)bn_generator_19_value,
1,
1,
@@ -525,7 +525,7 @@ const BIGNUM bn_generator_19 = {
};
static const BN_ULONG bn_generator_5_value[] = { 5 };
-const BIGNUM bn_generator_5 = {
+const BIGNUM ossl_bn_generator_5 = {
(BN_ULONG *)bn_generator_5_value,
1,
1,
@@ -534,7 +534,7 @@ const BIGNUM bn_generator_5 = {
};
static const BN_ULONG bn_generator_2_value[] = { 2 };
-const BIGNUM bn_generator_2 = {
+const BIGNUM ossl_bn_generator_2 = {
(BN_ULONG *)bn_generator_2_value,
1,
1,
diff --git a/crypto/bn/bn_word.c b/crypto/bn/bn_word.c
index 18fb3030a8f4..93c014793e22 100644
--- a/crypto/bn/bn_word.c
+++ b/crypto/bn/bn_word.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/bn/bn_x931p.c b/crypto/bn/bn_x931p.c
index 009950259d41..20d35cf7afbd 100644
--- a/crypto/bn/bn_x931p.c
+++ b/crypto/bn/bn_x931p.c
@@ -1,12 +1,14 @@
/*
- * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <stdio.h>
#include <openssl/bn.h>
#include "bn_local.h"
@@ -30,7 +32,7 @@ static int bn_x931_derive_pi(BIGNUM *pi, const BIGNUM *Xpi, BN_CTX *ctx,
i++;
BN_GENCB_call(cb, 0, i);
/* NB 27 MR is specified in X9.31 */
- is_prime = BN_is_prime_fasttest_ex(pi, 27, ctx, 1, cb);
+ is_prime = BN_check_prime(pi, ctx, cb);
if (is_prime < 0)
return 0;
if (is_prime)
@@ -131,7 +133,7 @@ int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
* offering similar or better guarantees 50 MR is considerably
* better.
*/
- int r = BN_is_prime_fasttest_ex(p, 50, ctx, 1, cb);
+ int r = BN_check_prime(p, ctx, cb);
if (r < 0)
goto err;
if (r)
@@ -173,8 +175,9 @@ int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx)
* - 1. By setting the top two bits we ensure that the lower bound is
* exceeded.
*/
- if (!BN_priv_rand(Xp, nbits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY))
- goto err;
+ if (!BN_priv_rand_ex(Xp, nbits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY, 0,
+ ctx))
+ return 0;
BN_CTX_start(ctx);
t = BN_CTX_get(ctx);
@@ -182,7 +185,8 @@ int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx)
goto err;
for (i = 0; i < 1000; i++) {
- if (!BN_priv_rand(Xq, nbits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY))
+ if (!BN_priv_rand_ex(Xq, nbits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY, 0,
+ ctx))
goto err;
/* Check that |Xp - Xq| > 2^(nbits - 100) */
@@ -227,9 +231,9 @@ int BN_X931_generate_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
if (Xp1 == NULL || Xp2 == NULL)
goto error;
- if (!BN_priv_rand(Xp1, 101, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
+ if (!BN_priv_rand_ex(Xp1, 101, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY, 0, ctx))
goto error;
- if (!BN_priv_rand(Xp2, 101, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
+ if (!BN_priv_rand_ex(Xp2, 101, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY, 0, ctx))
goto error;
if (!BN_X931_derive_prime_ex(p, p1, p2, Xp, Xp1, Xp2, e, ctx, cb))
goto error;
diff --git a/crypto/bn/build.info b/crypto/bn/build.info
index c9fe2fdada69..f4ff6192393e 100644
--- a/crypto/bn/build.info
+++ b/crypto/bn/build.info
@@ -1,67 +1,177 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- bn_add.c bn_div.c bn_exp.c bn_lib.c bn_ctx.c bn_mul.c bn_mod.c \
- bn_print.c bn_rand.c bn_shift.c bn_word.c bn_blind.c \
- bn_kron.c bn_sqrt.c bn_gcd.c bn_prime.c bn_err.c bn_sqr.c \
- {- $target{bn_asm_src} -} \
+
+$BNASM=bn_asm.c
+IF[{- !$disabled{asm} -}]
+ # Define source files and macros per asm architecture
+ # Known macros are:
+ #
+ # OPENSSL_BN_ASM_PART_WORDS For any collection with /-586/ file names
+ # OPENSSL_BN_ASM_MONT For any collection with /-mont/ file names
+ # OPENSSL_BN_ASM_MONT5 For any collection with /-mont5/ file names
+ # OPENSSL_BN_ASM_GF2m For any collection with /-gf2m/ file names
+ # OPENSSL_IA32_SSE2 For any collection with /86/ file names
+ # when sse2 is enabled
+ # BN_DIV3W For any collection with /-div3w/ file names
+ #
+ # All variables are named in such a way that they can be "indexed" with
+ # $target{asm_arch}
+
+ $BNASM_x86=bn-586.S co-586.S x86-mont.S x86-gf2m.S
+ # bn-586 is the only one implementing bn_*_part_words
+ # => OPENSSL_BN_ASM_PART_WORDS
+ $BNDEF_x86=OPENSSL_BN_ASM_PART_WORDS OPENSSL_BN_ASM_MONT OPENSSL_BN_ASM_GF2m
+ $BNDEF_x86_sse2=OPENSSL_IA32_SSE2
+
+ $BNASM_x86_64=\
+ x86_64-mont.s x86_64-mont5.s x86_64-gf2m.s rsaz_exp.c rsaz-x86_64.s \
+ rsaz-avx2.s rsaz_exp_x2.c rsaz-avx512.s
+ IF[{- $config{target} !~ /^VC/ -}]
+ $BNASM_x86_64=asm/x86_64-gcc.c $BNASM_x86_64
+ ELSE
+ $BNASM_x86_64=bn_asm.c $BNASM_x86_64
+ ENDIF
+ $BNDEF_x86_64=OPENSSL_BN_ASM_MONT OPENSSL_BN_ASM_MONT5 OPENSSL_BN_ASM_GF2m
+ $BNDEF_x86_64_sse2=OPENSSL_IA32_SSE2
+
+ IF[{- $config{target} !~ /^VC/ -}]
+ $BNASM_ia64=bn-ia64.s ia64-mont.s
+ ELSE
+ $BNASM_ia64=bn_asm.c ia64-mont.s
+ ENDIF
+
+ $BNASM_sparcv9=asm/sparcv8plus.S sparcv9-mont.S sparcv9a-mont.S vis3-mont.S \
+ sparct4-mont.S bn_sparc.c
+ $BNDEF_sparcv9=OPENSSL_BN_ASM_MONT
+ $BNASM_sparcv9_ec2m=sparcv9-gf2m.S
+ $BNDEF_sparcv9_ec2m=OPENSSL_BN_ASM_GF2m
+
+ $BNASM_sparcv8=asm/sparcv8.S
+
+ $BNASM_alpha=bn_asm.c alpha-mont.S
+ $BNDEF_alpha=OPENSSL_BN_ASM_MONT
+
+ $BNASM_mips32=bn-mips.S mips-mont.S
+ $BNDEF_mips32=OPENSSL_BN_ASM_MONT
+ $BNASM_mips64=$BNASM_mips32
+ $BNDEF_mips64=$BNDEF_mips32
+
+ IF[{- ($target{perlasm_scheme} // '') eq '31' -}]
+ $BNASM_s390x=bn_asm.c s390x-mont.S
+ ELSE
+ $BNASM_s390x=asm/s390x.S s390x-mont.S
+ ENDIF
+ $BNDEF_s390x=OPENSSL_BN_ASM_MONT
+ $BNASM_s390x_ec2m=s390x-gf2m.s
+ $BNDEF_s390x_ec2m=OPENSSL_BN_ASM_GF2m
+
+ $BNASM_armv4=bn_asm.c armv4-mont.S
+ $BNDEF_armv4=OPENSSL_BN_ASM_MONT
+ $BNASM_armv4_ec2m=armv4-gf2m.S
+ $BNDEF_armv4_ec2m=OPENSSL_BN_ASM_GF2m
+
+ $BNASM_aarch64=bn_asm.c armv8-mont.S
+ $BNDEF_aarch64=OPENSSL_BN_ASM_MONT
+
+ $BNASM_parisc11=bn_asm.c parisc-mont.s
+ $BNDEF_parisc11=OPENSSL_BN_ASM_MONT
+ $BNASM_parisc20_64=$BNASM_parisc11
+ $BNDEF_parisc20_64=$BNDEF_parisc11
+
+ $BNASM_ppc32=bn_ppc.c bn-ppc.s ppc-mont.s
+ $BNDEF_ppc32=OPENSSL_BN_ASM_MONT
+ $BNASM_ppc64=$BNASM_ppc32
+ $BNDEF_ppc64=$BNDEF_ppc32
+
+ $BNASM_c64xplus=asm/bn-c64xplus.asm
+ $BNASM_c64xplus_ec2m=c64xplus-gf2m.s
+ $BNDEF_c64xplus_ec2m=OPENSSL_BN_ASM_GF2m
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate ones, and define the appropriate macros
+ IF[$BNASM_{- $target{asm_arch} -}]
+ $BNASM=$BNASM_{- $target{asm_arch} -}
+ $BNDEF=$BNDEF_{- $target{asm_arch} -}
+ IF[{- !$disabled{ec2m} -}]
+ $BNASM=$BNASM $BNASM_{- $target{asm_arch} -}_ec2m
+ $BNDEF=$BNDEF $BNDEF_{- $target{asm_arch} -}_ec2m
+ ENDIF
+ IF[{- !$disabled{sse2} -}]
+ $BNDEF=$BNDEF $BNDEF_{- $target{asm_arch} -}_sse2
+ ENDIF
+ ENDIF
+ENDIF
+
+$COMMON=bn_add.c bn_div.c bn_exp.c bn_lib.c bn_ctx.c bn_mul.c \
+ bn_mod.c bn_conv.c bn_rand.c bn_shift.c bn_word.c bn_blind.c \
+ bn_kron.c bn_sqrt.c bn_gcd.c bn_prime.c bn_sqr.c \
bn_recp.c bn_mont.c bn_mpi.c bn_exp2.c bn_gf2m.c bn_nist.c \
- bn_depr.c bn_const.c bn_x931p.c bn_intern.c bn_dh.c bn_srp.c \
- rsa_sup_mul.c
+ bn_intern.c bn_dh.c bn_rsa_fips186_4.c bn_const.c rsa_sup_mul.c
+SOURCE[../../libcrypto]=$COMMON $BNASM bn_print.c bn_err.c bn_srp.c
+DEFINE[../../libcrypto]=$BNDEF
+IF[{- !$disabled{'deprecated-0.9.8'} -}]
+ SOURCE[../../libcrypto]=bn_depr.c
+ENDIF
+IF[{- !$disabled{'deprecated-3.0'} -}]
+ SOURCE[../../libcrypto]=bn_x931p.c
+ENDIF
+SOURCE[../../providers/libfips.a]=$COMMON $BNASM
+DEFINE[../../providers/libfips.a]=$BNDEF
+# Implementations are now spread across several libraries, so the defines
+# need to be applied to all affected libraries and modules.
+DEFINE[../../providers/libcommon.a]=$BNDEF
INCLUDE[bn_exp.o]=..
-GENERATE[bn-586.s]=asm/bn-586.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-DEPEND[bn-586.s]=../perlasm/x86asm.pl
-GENERATE[co-586.s]=asm/co-586.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-DEPEND[co-586.s]=../perlasm/x86asm.pl
-GENERATE[x86-mont.s]=asm/x86-mont.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-DEPEND[x86-mont.s]=../perlasm/x86asm.pl
-GENERATE[x86-gf2m.s]=asm/x86-gf2m.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-DEPEND[x86-gf2m.s]=../perlasm/x86asm.pl
-
-GENERATE[sparcv9a-mont.S]=asm/sparcv9a-mont.pl $(PERLASM_SCHEME)
+GENERATE[bn-586.S]=asm/bn-586.pl
+DEPEND[bn-586.S]=../perlasm/x86asm.pl
+GENERATE[co-586.S]=asm/co-586.pl
+DEPEND[co-586.S]=../perlasm/x86asm.pl
+GENERATE[x86-mont.S]=asm/x86-mont.pl
+DEPEND[x86-mont.S]=../perlasm/x86asm.pl
+GENERATE[x86-gf2m.S]=asm/x86-gf2m.pl
+DEPEND[x86-gf2m.S]=../perlasm/x86asm.pl
+
+GENERATE[sparcv9a-mont.S]=asm/sparcv9a-mont.pl
INCLUDE[sparcv9a-mont.o]=..
-GENERATE[sparcv9-mont.S]=asm/sparcv9-mont.pl $(PERLASM_SCHEME)
+GENERATE[sparcv9-mont.S]=asm/sparcv9-mont.pl
INCLUDE[sparcv9-mont.o]=..
-GENERATE[vis3-mont.S]=asm/vis3-mont.pl $(PERLASM_SCHEME)
+GENERATE[vis3-mont.S]=asm/vis3-mont.pl
INCLUDE[vis3-mont.o]=..
-GENERATE[sparct4-mont.S]=asm/sparct4-mont.pl $(PERLASM_SCHEME)
+GENERATE[sparct4-mont.S]=asm/sparct4-mont.pl
INCLUDE[sparct4-mont.o]=..
-GENERATE[sparcv9-gf2m.S]=asm/sparcv9-gf2m.pl $(PERLASM_SCHEME)
+GENERATE[sparcv9-gf2m.S]=asm/sparcv9-gf2m.pl
INCLUDE[sparcv9-gf2m.o]=..
-GENERATE[bn-mips.S]=asm/mips.pl $(PERLASM_SCHEME)
+GENERATE[bn-mips.S]=asm/mips.pl
INCLUDE[bn-mips.o]=..
-GENERATE[mips-mont.S]=asm/mips-mont.pl $(PERLASM_SCHEME)
+GENERATE[mips-mont.S]=asm/mips-mont.pl
INCLUDE[mips-mont.o]=..
-GENERATE[s390x-mont.S]=asm/s390x-mont.pl $(PERLASM_SCHEME)
-GENERATE[s390x-gf2m.s]=asm/s390x-gf2m.pl $(PERLASM_SCHEME)
+GENERATE[s390x-mont.S]=asm/s390x-mont.pl
+GENERATE[s390x-gf2m.s]=asm/s390x-gf2m.pl
-GENERATE[x86_64-mont.s]=asm/x86_64-mont.pl $(PERLASM_SCHEME)
-GENERATE[x86_64-mont5.s]=asm/x86_64-mont5.pl $(PERLASM_SCHEME)
-GENERATE[x86_64-gf2m.s]=asm/x86_64-gf2m.pl $(PERLASM_SCHEME)
-GENERATE[rsaz-x86_64.s]=asm/rsaz-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[rsaz-avx2.s]=asm/rsaz-avx2.pl $(PERLASM_SCHEME)
+GENERATE[x86_64-mont.s]=asm/x86_64-mont.pl
+GENERATE[x86_64-mont5.s]=asm/x86_64-mont5.pl
+GENERATE[x86_64-gf2m.s]=asm/x86_64-gf2m.pl
+GENERATE[rsaz-x86_64.s]=asm/rsaz-x86_64.pl
+GENERATE[rsaz-avx2.s]=asm/rsaz-avx2.pl
+GENERATE[rsaz-avx512.s]=asm/rsaz-avx512.pl
GENERATE[bn-ia64.s]=asm/ia64.S
-GENERATE[ia64-mont.s]=asm/ia64-mont.pl $(LIB_CFLAGS) $(LIB_CPPFLAGS)
+GENERATE[ia64-mont.s]=asm/ia64-mont.pl
-GENERATE[parisc-mont.s]=asm/parisc-mont.pl $(PERLASM_SCHEME)
+GENERATE[parisc-mont.s]=asm/parisc-mont.pl
# ppc - AIX, Linux, MacOS X...
-GENERATE[bn-ppc.s]=asm/ppc.pl $(PERLASM_SCHEME)
-GENERATE[ppc-mont.s]=asm/ppc-mont.pl $(PERLASM_SCHEME)
-GENERATE[ppc64-mont.s]=asm/ppc64-mont.pl $(PERLASM_SCHEME)
+GENERATE[bn-ppc.s]=asm/ppc.pl
+GENERATE[ppc-mont.s]=asm/ppc-mont.pl
+GENERATE[ppc64-mont.s]=asm/ppc64-mont.pl
-GENERATE[alpha-mont.S]=asm/alpha-mont.pl $(PERLASM_SCHEME)
+GENERATE[alpha-mont.S]=asm/alpha-mont.pl
-GENERATE[armv4-mont.S]=asm/armv4-mont.pl $(PERLASM_SCHEME)
+GENERATE[armv4-mont.S]=asm/armv4-mont.pl
INCLUDE[armv4-mont.o]=..
-GENERATE[armv4-gf2m.S]=asm/armv4-gf2m.pl $(PERLASM_SCHEME)
+GENERATE[armv4-gf2m.S]=asm/armv4-gf2m.pl
INCLUDE[armv4-gf2m.o]=..
-GENERATE[armv8-mont.S]=asm/armv8-mont.pl $(PERLASM_SCHEME)
+GENERATE[armv8-mont.S]=asm/armv8-mont.pl
+INCLUDE[armv8-mont.o]=..
diff --git a/crypto/bn/rsa_sup_mul.c b/crypto/bn/rsa_sup_mul.c
index acafefd5febf..0e0d02e1946e 100644
--- a/crypto/bn/rsa_sup_mul.c
+++ b/crypto/bn/rsa_sup_mul.c
@@ -5,6 +5,7 @@
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/rsaerr.h>
+#include "internal/endian.h"
#include "internal/numbers.h"
#include "internal/constant_time.h"
#include "bn_local.h"
@@ -12,8 +13,7 @@
# if BN_BYTES == 8
typedef uint64_t limb_t;
# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16
-/* nonstandard; implemented by gcc on 64-bit platforms */
-typedef __uint128_t limb2_t;
+typedef uint128_t limb2_t;
# define HAVE_LIMB2_T
# endif
# define LIMB_BIT_SIZE 64
@@ -439,7 +439,7 @@ static void mod_montgomery(limb_t *ret, limb_t *a, size_t anum, limb_t *mod,
/* add multiples of the modulus to the value until R divides it cleanly */
for (i = modnum; i > 0; i--, rp--) {
- v = _mul_add_limb(rp, mod, modnum, rp[modnum - 1] * ni0, tmp2);
+ v = _mul_add_limb(rp, mod, modnum, rp[modnum-1] * ni0, tmp2);
v = v + carry + rp[-1];
carry |= (v != rp[-1]);
carry &= (v <= rp[-1]);
@@ -467,48 +467,38 @@ static void BN_to_limb(const BIGNUM *bn, limb_t *buf, size_t limbs)
#if LIMB_BYTE_SIZE == 8
static ossl_inline uint64_t be64(uint64_t host)
{
- const union {
- long one;
- char little;
- } is_endian = { 1 };
-
- if (is_endian.little) {
- uint64_t big = 0;
-
- big |= (host & 0xff00000000000000) >> 56;
- big |= (host & 0x00ff000000000000) >> 40;
- big |= (host & 0x0000ff0000000000) >> 24;
- big |= (host & 0x000000ff00000000) >> 8;
- big |= (host & 0x00000000ff000000) << 8;
- big |= (host & 0x0000000000ff0000) << 24;
- big |= (host & 0x000000000000ff00) << 40;
- big |= (host & 0x00000000000000ff) << 56;
- return big;
- } else {
+ uint64_t big = 0;
+ DECLARE_IS_ENDIAN;
+
+ if (!IS_LITTLE_ENDIAN)
return host;
- }
+
+ big |= (host & 0xff00000000000000) >> 56;
+ big |= (host & 0x00ff000000000000) >> 40;
+ big |= (host & 0x0000ff0000000000) >> 24;
+ big |= (host & 0x000000ff00000000) >> 8;
+ big |= (host & 0x00000000ff000000) << 8;
+ big |= (host & 0x0000000000ff0000) << 24;
+ big |= (host & 0x000000000000ff00) << 40;
+ big |= (host & 0x00000000000000ff) << 56;
+ return big;
}
#else
/* Not all platforms have htobe32(). */
static ossl_inline uint32_t be32(uint32_t host)
{
- const union {
- long one;
- char little;
- } is_endian = { 1 };
-
- if (is_endian.little) {
- uint32_t big = 0;
-
- big |= (host & 0xff000000) >> 24;
- big |= (host & 0x00ff0000) >> 8;
- big |= (host & 0x0000ff00) << 8;
- big |= (host & 0x000000ff) << 24;
- return big;
- } else {
+ uint32_t big = 0;
+ DECLARE_IS_ENDIAN;
+
+ if (!IS_LITTLE_ENDIAN)
return host;
- }
+
+ big |= (host & 0xff000000) >> 24;
+ big |= (host & 0x00ff0000) >> 8;
+ big |= (host & 0x0000ff00) << 8;
+ big |= (host & 0x000000ff) << 24;
+ return big;
}
#endif
@@ -579,7 +569,7 @@ int ossl_bn_rsa_do_unblind(const BIGNUM *intermediate,
/* modulus size in bytes can be equal to num but after limbs conversion it becomes bigger */
if (num < BN_num_bytes(to_mod)) {
- BNerr(BN_F_OSSL_BN_RSA_DO_UNBLIND, ERR_R_PASSED_INVALID_ARGUMENT);
+ ERR_raise(ERR_LIB_BN, ERR_R_PASSED_INVALID_ARGUMENT);
goto err;
}
diff --git a/crypto/bn/rsaz_exp.c b/crypto/bn/rsaz_exp.c
index a2ab58bbeb4c..2a1ff09eefc9 100644
--- a/crypto/bn/rsaz_exp.c
+++ b/crypto/bn/rsaz_exp.c
@@ -2,7 +2,7 @@
* Copyright 2013-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2012, Intel Corporation. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/bn/rsaz_exp.h b/crypto/bn/rsaz_exp.h
index 1532a7e07179..e27e9f047138 100644
--- a/crypto/bn/rsaz_exp.h
+++ b/crypto/bn/rsaz_exp.h
@@ -1,8 +1,8 @@
/*
* Copyright 2013-2022 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright (c) 2012, Intel Corporation. All Rights Reserved.
+ * Copyright (c) 2020, Intel Corporation. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -37,6 +37,23 @@ void RSAZ_512_mod_exp(BN_ULONG result[8],
const BN_ULONG m_norm[8], BN_ULONG k0,
const BN_ULONG RR[8]);
+
+int ossl_rsaz_avx512ifma_eligible(void);
+
+int ossl_rsaz_mod_exp_avx512_x2(BN_ULONG *res1,
+ const BN_ULONG *base1,
+ const BN_ULONG *exponent1,
+ const BN_ULONG *m1,
+ const BN_ULONG *RR1,
+ BN_ULONG k0_1,
+ BN_ULONG *res2,
+ const BN_ULONG *base2,
+ const BN_ULONG *exponent2,
+ const BN_ULONG *m2,
+ const BN_ULONG *RR2,
+ BN_ULONG k0_2,
+ int factor_size);
+
static ossl_inline void bn_select_words(BN_ULONG *r, BN_ULONG mask,
const BN_ULONG *a,
const BN_ULONG *b, size_t num)
diff --git a/crypto/bn/rsaz_exp_x2.c b/crypto/bn/rsaz_exp_x2.c
new file mode 100644
index 000000000000..b19050dfee8c
--- /dev/null
+++ b/crypto/bn/rsaz_exp_x2.c
@@ -0,0 +1,575 @@
+/*
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2020, Intel Corporation. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ *
+ * Originally written by Ilya Albrekht, Sergey Kirillov and Andrey Matyukov
+ * Intel Corporation
+ *
+ */
+
+#include <openssl/opensslconf.h>
+#include <openssl/crypto.h>
+#include "rsaz_exp.h"
+
+#ifndef RSAZ_ENABLED
+NON_EMPTY_TRANSLATION_UNIT
+#else
+# include <assert.h>
+# include <string.h>
+
+# if defined(__GNUC__)
+# define ALIGN64 __attribute__((aligned(64)))
+# elif defined(_MSC_VER)
+# define ALIGN64 __declspec(align(64))
+# else
+# define ALIGN64
+# endif
+
+# define ALIGN_OF(ptr, boundary) \
+ ((unsigned char *)(ptr) + (boundary - (((size_t)(ptr)) & (boundary - 1))))
+
+/* Internal radix */
+# define DIGIT_SIZE (52)
+/* 52-bit mask */
+# define DIGIT_MASK ((uint64_t)0xFFFFFFFFFFFFF)
+
+# define BITS2WORD8_SIZE(x) (((x) + 7) >> 3)
+# define BITS2WORD64_SIZE(x) (((x) + 63) >> 6)
+
+static ossl_inline uint64_t get_digit52(const uint8_t *in, int in_len);
+static ossl_inline void put_digit52(uint8_t *out, int out_len, uint64_t digit);
+static void to_words52(BN_ULONG *out, int out_len, const BN_ULONG *in,
+ int in_bitsize);
+static void from_words52(BN_ULONG *bn_out, int out_bitsize, const BN_ULONG *in);
+static ossl_inline void set_bit(BN_ULONG *a, int idx);
+
+/* Number of |digit_size|-bit digits in |bitsize|-bit value */
+static ossl_inline int number_of_digits(int bitsize, int digit_size)
+{
+ return (bitsize + digit_size - 1) / digit_size;
+}
+
+typedef void (*AMM52)(BN_ULONG *res, const BN_ULONG *base,
+ const BN_ULONG *exp, const BN_ULONG *m, BN_ULONG k0);
+typedef void (*EXP52_x2)(BN_ULONG *res, const BN_ULONG *base,
+ const BN_ULONG *exp[2], const BN_ULONG *m,
+ const BN_ULONG *rr, const BN_ULONG k0[2]);
+
+/*
+ * For details of the methods declared below please refer to
+ * crypto/bn/asm/rsaz-avx512.pl
+ *
+ * Naming notes:
+ * amm = Almost Montgomery Multiplication
+ * ams = Almost Montgomery Squaring
+ * 52x20 - data represented as array of 20 digits in 52-bit radix
+ * _x1_/_x2_ - 1 or 2 independent inputs/outputs
+ * _256 suffix - uses 256-bit (AVX512VL) registers
+ */
+
+/*AMM = Almost Montgomery Multiplication. */
+void ossl_rsaz_amm52x20_x1_256(BN_ULONG *res, const BN_ULONG *base,
+ const BN_ULONG *exp, const BN_ULONG *m,
+ BN_ULONG k0);
+static void RSAZ_exp52x20_x2_256(BN_ULONG *res, const BN_ULONG *base,
+ const BN_ULONG *exp[2], const BN_ULONG *m,
+ const BN_ULONG *rr, const BN_ULONG k0[2]);
+void ossl_rsaz_amm52x20_x2_256(BN_ULONG *out, const BN_ULONG *a,
+ const BN_ULONG *b, const BN_ULONG *m,
+ const BN_ULONG k0[2]);
+void ossl_extract_multiplier_2x20_win5(BN_ULONG *red_Y,
+ const BN_ULONG *red_table,
+ int red_table_idx, int tbl_idx);
+
+/*
+ * Dual Montgomery modular exponentiation using prime moduli of the
+ * same bit size, optimized with AVX512 ISA.
+ *
+ * Input and output parameters for each exponentiation are independent and
+ * denoted here by index |i|, i = 1..2.
+ *
+ * Input and output are all in regular 2^64 radix.
+ *
+ * Each moduli shall be |factor_size| bit size.
+ *
+ * NOTE: currently only 2x1024 case is supported.
+ *
+ * [out] res|i| - result of modular exponentiation: array of qword values
+ * in regular (2^64) radix. Size of array shall be enough
+ * to hold |factor_size| bits.
+ * [in] base|i| - base
+ * [in] exp|i| - exponent
+ * [in] m|i| - moduli
+ * [in] rr|i| - Montgomery parameter RR = R^2 mod m|i|
+ * [in] k0_|i| - Montgomery parameter k0 = -1/m|i| mod 2^64
+ * [in] factor_size - moduli bit size
+ *
+ * \return 0 in case of failure,
+ * 1 in case of success.
+ */
+int ossl_rsaz_mod_exp_avx512_x2(BN_ULONG *res1,
+ const BN_ULONG *base1,
+ const BN_ULONG *exp1,
+ const BN_ULONG *m1,
+ const BN_ULONG *rr1,
+ BN_ULONG k0_1,
+ BN_ULONG *res2,
+ const BN_ULONG *base2,
+ const BN_ULONG *exp2,
+ const BN_ULONG *m2,
+ const BN_ULONG *rr2,
+ BN_ULONG k0_2,
+ int factor_size)
+{
+ int ret = 0;
+
+ /*
+ * Number of word-size (BN_ULONG) digits to store exponent in redundant
+ * representation.
+ */
+ int exp_digits = number_of_digits(factor_size + 2, DIGIT_SIZE);
+ int coeff_pow = 4 * (DIGIT_SIZE * exp_digits - factor_size);
+ BN_ULONG *base1_red, *m1_red, *rr1_red;
+ BN_ULONG *base2_red, *m2_red, *rr2_red;
+ BN_ULONG *coeff_red;
+ BN_ULONG *storage = NULL;
+ BN_ULONG *storage_aligned = NULL;
+ BN_ULONG storage_len_bytes = 7 * exp_digits * sizeof(BN_ULONG);
+
+ /* AMM = Almost Montgomery Multiplication */
+ AMM52 amm = NULL;
+ /* Dual (2-exps in parallel) exponentiation */
+ EXP52_x2 exp_x2 = NULL;
+
+ const BN_ULONG *exp[2] = {0};
+ BN_ULONG k0[2] = {0};
+
+ /* Only 1024-bit factor size is supported now */
+ switch (factor_size) {
+ case 1024:
+ amm = ossl_rsaz_amm52x20_x1_256;
+ exp_x2 = RSAZ_exp52x20_x2_256;
+ break;
+ default:
+ goto err;
+ }
+
+ storage = (BN_ULONG *)OPENSSL_malloc(storage_len_bytes + 64);
+ if (storage == NULL)
+ goto err;
+ storage_aligned = (BN_ULONG *)ALIGN_OF(storage, 64);
+
+ /* Memory layout for red(undant) representations */
+ base1_red = storage_aligned;
+ base2_red = storage_aligned + 1 * exp_digits;
+ m1_red = storage_aligned + 2 * exp_digits;
+ m2_red = storage_aligned + 3 * exp_digits;
+ rr1_red = storage_aligned + 4 * exp_digits;
+ rr2_red = storage_aligned + 5 * exp_digits;
+ coeff_red = storage_aligned + 6 * exp_digits;
+
+ /* Convert base_i, m_i, rr_i, from regular to 52-bit radix */
+ to_words52(base1_red, exp_digits, base1, factor_size);
+ to_words52(base2_red, exp_digits, base2, factor_size);
+ to_words52(m1_red, exp_digits, m1, factor_size);
+ to_words52(m2_red, exp_digits, m2, factor_size);
+ to_words52(rr1_red, exp_digits, rr1, factor_size);
+ to_words52(rr2_red, exp_digits, rr2, factor_size);
+
+ /*
+ * Compute target domain Montgomery converters RR' for each modulus
+ * based on precomputed original domain's RR.
+ *
+ * RR -> RR' transformation steps:
+ * (1) coeff = 2^k
+ * (2) t = AMM(RR,RR) = RR^2 / R' mod m
+ * (3) RR' = AMM(t, coeff) = RR^2 * 2^k / R'^2 mod m
+ * where
+ * k = 4 * (52 * digits52 - modlen)
+ * R = 2^(64 * ceil(modlen/64)) mod m
+ * RR = R^2 mod M
+ * R' = 2^(52 * ceil(modlen/52)) mod m
+ *
+ * modlen = 1024: k = 64, RR = 2^2048 mod m, RR' = 2^2080 mod m
+ */
+ memset(coeff_red, 0, exp_digits * sizeof(BN_ULONG));
+ /* (1) in reduced domain representation */
+ set_bit(coeff_red, 64 * (int)(coeff_pow / 52) + coeff_pow % 52);
+
+ amm(rr1_red, rr1_red, rr1_red, m1_red, k0_1); /* (2) for m1 */
+ amm(rr1_red, rr1_red, coeff_red, m1_red, k0_1); /* (3) for m1 */
+
+ amm(rr2_red, rr2_red, rr2_red, m2_red, k0_2); /* (2) for m2 */
+ amm(rr2_red, rr2_red, coeff_red, m2_red, k0_2); /* (3) for m2 */
+
+ exp[0] = exp1;
+ exp[1] = exp2;
+
+ k0[0] = k0_1;
+ k0[1] = k0_2;
+
+ exp_x2(rr1_red, base1_red, exp, m1_red, rr1_red, k0);
+
+ /* Convert rr_i back to regular radix */
+ from_words52(res1, factor_size, rr1_red);
+ from_words52(res2, factor_size, rr2_red);
+
+ /* bn_reduce_once_in_place expects number of BN_ULONG, not bit size */
+ factor_size /= sizeof(BN_ULONG) * 8;
+
+ bn_reduce_once_in_place(res1, /*carry=*/0, m1, storage, factor_size);
+ bn_reduce_once_in_place(res2, /*carry=*/0, m2, storage, factor_size);
+
+ ret = 1;
+err:
+ if (storage != NULL) {
+ OPENSSL_cleanse(storage, storage_len_bytes);
+ OPENSSL_free(storage);
+ }
+ return ret;
+}
+
+/*
+ * Dual 1024-bit w-ary modular exponentiation using prime moduli of the same
+ * bit size using Almost Montgomery Multiplication, optimized with AVX512_IFMA
+ * ISA.
+ *
+ * The parameter w (window size) = 5.
+ *
+ * [out] res - result of modular exponentiation: 2x20 qword
+ * values in 2^52 radix.
+ * [in] base - base (2x20 qword values in 2^52 radix)
+ * [in] exp - array of 2 pointers to 16 qword values in 2^64 radix.
+ * Exponent is not converted to redundant representation.
+ * [in] m - moduli (2x20 qword values in 2^52 radix)
+ * [in] rr - Montgomery parameter for 2 moduli: RR = 2^2080 mod m.
+ * (2x20 qword values in 2^52 radix)
+ * [in] k0 - Montgomery parameter for 2 moduli: k0 = -1/m mod 2^64
+ *
+ * \return (void).
+ */
+static void RSAZ_exp52x20_x2_256(BN_ULONG *out, /* [2][20] */
+ const BN_ULONG *base, /* [2][20] */
+ const BN_ULONG *exp[2], /* 2x16 */
+ const BN_ULONG *m, /* [2][20] */
+ const BN_ULONG *rr, /* [2][20] */
+ const BN_ULONG k0[2])
+{
+# define BITSIZE_MODULUS (1024)
+# define EXP_WIN_SIZE (5)
+# define EXP_WIN_MASK ((1U << EXP_WIN_SIZE) - 1)
+/*
+ * Number of digits (64-bit words) in redundant representation to handle
+ * modulus bits
+ */
+# define RED_DIGITS (20)
+# define EXP_DIGITS (16)
+# define DAMM ossl_rsaz_amm52x20_x2_256
+/*
+ * Squaring is done using multiplication now. That can be a subject of
+ * optimization in future.
+ */
+# define DAMS(r,a,m,k0) \
+ ossl_rsaz_amm52x20_x2_256((r),(a),(a),(m),(k0))
+
+ /* Allocate stack for red(undant) result Y and multiplier X */
+ ALIGN64 BN_ULONG red_Y[2][RED_DIGITS];
+ ALIGN64 BN_ULONG red_X[2][RED_DIGITS];
+
+ /* Allocate expanded exponent */
+ ALIGN64 BN_ULONG expz[2][EXP_DIGITS + 1];
+
+ /* Pre-computed table of base powers */
+ ALIGN64 BN_ULONG red_table[1U << EXP_WIN_SIZE][2][RED_DIGITS];
+
+ int idx;
+
+ memset(red_Y, 0, sizeof(red_Y));
+ memset(red_table, 0, sizeof(red_table));
+ memset(red_X, 0, sizeof(red_X));
+
+ /*
+ * Compute table of powers base^i, i = 0, ..., (2^EXP_WIN_SIZE) - 1
+ * table[0] = mont(x^0) = mont(1)
+ * table[1] = mont(x^1) = mont(x)
+ */
+ red_X[0][0] = 1;
+ red_X[1][0] = 1;
+ DAMM(red_table[0][0], (const BN_ULONG*)red_X, rr, m, k0);
+ DAMM(red_table[1][0], base, rr, m, k0);
+
+ for (idx = 1; idx < (int)((1U << EXP_WIN_SIZE) / 2); idx++) {
+ DAMS(red_table[2 * idx + 0][0], red_table[1 * idx][0], m, k0);
+ DAMM(red_table[2 * idx + 1][0], red_table[2 * idx][0], red_table[1][0], m, k0);
+ }
+
+ /* Copy and expand exponents */
+ memcpy(expz[0], exp[0], EXP_DIGITS * sizeof(BN_ULONG));
+ expz[0][EXP_DIGITS] = 0;
+ memcpy(expz[1], exp[1], EXP_DIGITS * sizeof(BN_ULONG));
+ expz[1][EXP_DIGITS] = 0;
+
+ /* Exponentiation */
+ {
+ const int rem = BITSIZE_MODULUS % EXP_WIN_SIZE;
+ BN_ULONG table_idx_mask = EXP_WIN_MASK;
+
+ int exp_bit_no = BITSIZE_MODULUS - rem;
+ int exp_chunk_no = exp_bit_no / 64;
+ int exp_chunk_shift = exp_bit_no % 64;
+
+ BN_ULONG red_table_idx_0, red_table_idx_1;
+
+ /*
+ * If rem == 0, then
+ * exp_bit_no = modulus_bitsize - exp_win_size
+ * However, this isn't possible because rem is { 1024, 1536, 2048 } % 5
+ * which is { 4, 1, 3 } respectively.
+ *
+ * If this assertion ever fails the fix above is easy.
+ */
+ OPENSSL_assert(rem != 0);
+
+ /* Process 1-st exp window - just init result */
+ red_table_idx_0 = expz[0][exp_chunk_no];
+ red_table_idx_1 = expz[1][exp_chunk_no];
+ /*
+ * The function operates with fixed moduli sizes divisible by 64,
+ * thus table index here is always in supported range [0, EXP_WIN_SIZE).
+ */
+ red_table_idx_0 >>= exp_chunk_shift;
+ red_table_idx_1 >>= exp_chunk_shift;
+
+ ossl_extract_multiplier_2x20_win5(red_Y[0], (const BN_ULONG*)red_table,
+ (int)red_table_idx_0, 0);
+ ossl_extract_multiplier_2x20_win5(red_Y[1], (const BN_ULONG*)red_table,
+ (int)red_table_idx_1, 1);
+
+ /* Process other exp windows */
+ for (exp_bit_no -= EXP_WIN_SIZE; exp_bit_no >= 0; exp_bit_no -= EXP_WIN_SIZE) {
+ /* Extract pre-computed multiplier from the table */
+ {
+ BN_ULONG T;
+
+ exp_chunk_no = exp_bit_no / 64;
+ exp_chunk_shift = exp_bit_no % 64;
+ {
+ red_table_idx_0 = expz[0][exp_chunk_no];
+ T = expz[0][exp_chunk_no + 1];
+
+ red_table_idx_0 >>= exp_chunk_shift;
+ /*
+ * Get additional bits from then next quadword
+ * when 64-bit boundaries are crossed.
+ */
+ if (exp_chunk_shift > 64 - EXP_WIN_SIZE) {
+ T <<= (64 - exp_chunk_shift);
+ red_table_idx_0 ^= T;
+ }
+ red_table_idx_0 &= table_idx_mask;
+
+ ossl_extract_multiplier_2x20_win5(red_X[0],
+ (const BN_ULONG*)red_table,
+ (int)red_table_idx_0, 0);
+ }
+ {
+ red_table_idx_1 = expz[1][exp_chunk_no];
+ T = expz[1][exp_chunk_no + 1];
+
+ red_table_idx_1 >>= exp_chunk_shift;
+ /*
+ * Get additional bits from then next quadword
+ * when 64-bit boundaries are crossed.
+ */
+ if (exp_chunk_shift > 64 - EXP_WIN_SIZE) {
+ T <<= (64 - exp_chunk_shift);
+ red_table_idx_1 ^= T;
+ }
+ red_table_idx_1 &= table_idx_mask;
+
+ ossl_extract_multiplier_2x20_win5(red_X[1],
+ (const BN_ULONG*)red_table,
+ (int)red_table_idx_1, 1);
+ }
+ }
+
+ /* Series of squaring */
+ DAMS((BN_ULONG*)red_Y, (const BN_ULONG*)red_Y, m, k0);
+ DAMS((BN_ULONG*)red_Y, (const BN_ULONG*)red_Y, m, k0);
+ DAMS((BN_ULONG*)red_Y, (const BN_ULONG*)red_Y, m, k0);
+ DAMS((BN_ULONG*)red_Y, (const BN_ULONG*)red_Y, m, k0);
+ DAMS((BN_ULONG*)red_Y, (const BN_ULONG*)red_Y, m, k0);
+
+ DAMM((BN_ULONG*)red_Y, (const BN_ULONG*)red_Y, (const BN_ULONG*)red_X, m, k0);
+ }
+ }
+
+ /*
+ *
+ * NB: After the last AMM of exponentiation in Montgomery domain, the result
+ * may be 1025-bit, but the conversion out of Montgomery domain performs an
+ * AMM(x,1) which guarantees that the final result is less than |m|, so no
+ * conditional subtraction is needed here. See "Efficient Software
+ * Implementations of Modular Exponentiation" (by Shay Gueron) paper for details.
+ */
+
+ /* Convert result back in regular 2^52 domain */
+ memset(red_X, 0, sizeof(red_X));
+ red_X[0][0] = 1;
+ red_X[1][0] = 1;
+ DAMM(out, (const BN_ULONG*)red_Y, (const BN_ULONG*)red_X, m, k0);
+
+ /* Clear exponents */
+ OPENSSL_cleanse(expz, sizeof(expz));
+ OPENSSL_cleanse(red_Y, sizeof(red_Y));
+
+# undef DAMS
+# undef DAMM
+# undef EXP_DIGITS
+# undef RED_DIGITS
+# undef EXP_WIN_MASK
+# undef EXP_WIN_SIZE
+# undef BITSIZE_MODULUS
+}
+
+static ossl_inline uint64_t get_digit52(const uint8_t *in, int in_len)
+{
+ uint64_t digit = 0;
+
+ assert(in != NULL);
+
+ for (; in_len > 0; in_len--) {
+ digit <<= 8;
+ digit += (uint64_t)(in[in_len - 1]);
+ }
+ return digit;
+}
+
+/*
+ * Convert array of words in regular (base=2^64) representation to array of
+ * words in redundant (base=2^52) one.
+ */
+static void to_words52(BN_ULONG *out, int out_len,
+ const BN_ULONG *in, int in_bitsize)
+{
+ uint8_t *in_str = NULL;
+
+ assert(out != NULL);
+ assert(in != NULL);
+ /* Check destination buffer capacity */
+ assert(out_len >= number_of_digits(in_bitsize, DIGIT_SIZE));
+
+ in_str = (uint8_t *)in;
+
+ for (; in_bitsize >= (2 * DIGIT_SIZE); in_bitsize -= (2 * DIGIT_SIZE), out += 2) {
+ uint64_t digit;
+
+ memcpy(&digit, in_str, sizeof(digit));
+ out[0] = digit & DIGIT_MASK;
+ in_str += 6;
+ memcpy(&digit, in_str, sizeof(digit));
+ out[1] = (digit >> 4) & DIGIT_MASK;
+ in_str += 7;
+ out_len -= 2;
+ }
+
+ if (in_bitsize > DIGIT_SIZE) {
+ uint64_t digit = get_digit52(in_str, 7);
+
+ out[0] = digit & DIGIT_MASK;
+ in_str += 6;
+ in_bitsize -= DIGIT_SIZE;
+ digit = get_digit52(in_str, BITS2WORD8_SIZE(in_bitsize));
+ out[1] = digit >> 4;
+ out += 2;
+ out_len -= 2;
+ } else if (in_bitsize > 0) {
+ out[0] = get_digit52(in_str, BITS2WORD8_SIZE(in_bitsize));
+ out++;
+ out_len--;
+ }
+
+ while (out_len > 0) {
+ *out = 0;
+ out_len--;
+ out++;
+ }
+}
+
+static ossl_inline void put_digit52(uint8_t *pStr, int strLen, uint64_t digit)
+{
+ assert(pStr != NULL);
+
+ for (; strLen > 0; strLen--) {
+ *pStr++ = (uint8_t)(digit & 0xFF);
+ digit >>= 8;
+ }
+}
+
+/*
+ * Convert array of words in redundant (base=2^52) representation to array of
+ * words in regular (base=2^64) one.
+ */
+static void from_words52(BN_ULONG *out, int out_bitsize, const BN_ULONG *in)
+{
+ int i;
+ int out_len = BITS2WORD64_SIZE(out_bitsize);
+
+ assert(out != NULL);
+ assert(in != NULL);
+
+ for (i = 0; i < out_len; i++)
+ out[i] = 0;
+
+ {
+ uint8_t *out_str = (uint8_t *)out;
+
+ for (; out_bitsize >= (2 * DIGIT_SIZE);
+ out_bitsize -= (2 * DIGIT_SIZE), in += 2) {
+ uint64_t digit;
+
+ digit = in[0];
+ memcpy(out_str, &digit, sizeof(digit));
+ out_str += 6;
+ digit = digit >> 48 | in[1] << 4;
+ memcpy(out_str, &digit, sizeof(digit));
+ out_str += 7;
+ }
+
+ if (out_bitsize > DIGIT_SIZE) {
+ put_digit52(out_str, 7, in[0]);
+ out_str += 6;
+ out_bitsize -= DIGIT_SIZE;
+ put_digit52(out_str, BITS2WORD8_SIZE(out_bitsize),
+ (in[1] << 4 | in[0] >> 48));
+ } else if (out_bitsize) {
+ put_digit52(out_str, BITS2WORD8_SIZE(out_bitsize), in[0]);
+ }
+ }
+}
+
+/*
+ * Set bit at index |idx| in the words array |a|.
+ * It does not do any boundaries checks, make sure the index is valid before
+ * calling the function.
+ */
+static ossl_inline void set_bit(BN_ULONG *a, int idx)
+{
+ assert(a != NULL);
+
+ {
+ int i, j;
+
+ i = idx / BN_BITS2;
+ j = idx % BN_BITS2;
+ a[i] |= (((BN_ULONG)1) << j);
+ }
+}
+
+#endif
diff --git a/crypto/bsearch.c b/crypto/bsearch.c
new file mode 100644
index 000000000000..f812c4f8ef0f
--- /dev/null
+++ b/crypto/bsearch.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stddef.h>
+#include "internal/cryptlib.h"
+
+const void *ossl_bsearch(const void *key, const void *base, int num,
+ int size, int (*cmp) (const void *, const void *),
+ int flags)
+{
+ const char *base_ = base;
+ int l, h, i = 0, c = 0;
+ const char *p = NULL;
+
+ if (num == 0)
+ return NULL;
+ l = 0;
+ h = num;
+ while (l < h) {
+ i = (l + h) / 2;
+ p = &(base_[i * size]);
+ c = (*cmp) (key, p);
+ if (c < 0)
+ h = i;
+ else if (c > 0)
+ l = i + 1;
+ else
+ break;
+ }
+ if (c != 0 && !(flags & OSSL_BSEARCH_VALUE_ON_NOMATCH))
+ p = NULL;
+ else if (c == 0 && (flags & OSSL_BSEARCH_FIRST_VALUE_ON_MATCH)) {
+ while (i > 0 && (*cmp) (key, &(base_[(i - 1) * size])) == 0)
+ i--;
+ p = &(base_[i * size]);
+ }
+ return p;
+}
diff --git a/crypto/buffer/buf_err.c b/crypto/buffer/buf_err.c
index 7e6e53226a93..9233b0a23c17 100644
--- a/crypto/buffer/buf_err.c
+++ b/crypto/buffer/buf_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,29 +10,21 @@
#include <openssl/err.h>
#include <openssl/buffererr.h>
+#include "crypto/buffererr.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA BUF_str_functs[] = {
- {ERR_PACK(ERR_LIB_BUF, BUF_F_BUF_MEM_GROW, 0), "BUF_MEM_grow"},
- {ERR_PACK(ERR_LIB_BUF, BUF_F_BUF_MEM_GROW_CLEAN, 0), "BUF_MEM_grow_clean"},
- {ERR_PACK(ERR_LIB_BUF, BUF_F_BUF_MEM_NEW, 0), "BUF_MEM_new"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA BUF_str_reasons[] = {
{0, NULL}
};
#endif
-int ERR_load_BUF_strings(void)
+int ossl_err_load_BUF_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(BUF_str_functs[0].error) == NULL) {
- ERR_load_strings_const(BUF_str_functs);
+ if (ERR_reason_error_string(BUF_str_reasons[0].error) == NULL)
ERR_load_strings_const(BUF_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/buffer/buffer.c b/crypto/buffer/buffer.c
index 72258abb9e5e..db1ea38b195a 100644
--- a/crypto/buffer/buffer.c
+++ b/crypto/buffer/buffer.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -34,7 +34,7 @@ BUF_MEM *BUF_MEM_new(void)
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- BUFerr(BUF_F_BUF_MEM_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE);
return NULL;
}
return ret;
@@ -87,7 +87,7 @@ size_t BUF_MEM_grow(BUF_MEM *str, size_t len)
}
/* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */
if (len > LIMIT_BEFORE_EXPANSION) {
- BUFerr(BUF_F_BUF_MEM_GROW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE);
return 0;
}
n = (len + 3) / 3 * 4;
@@ -96,7 +96,7 @@ size_t BUF_MEM_grow(BUF_MEM *str, size_t len)
else
ret = OPENSSL_realloc(str->data, n);
if (ret == NULL) {
- BUFerr(BUF_F_BUF_MEM_GROW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE);
len = 0;
} else {
str->data = ret;
@@ -125,7 +125,7 @@ size_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len)
}
/* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */
if (len > LIMIT_BEFORE_EXPANSION) {
- BUFerr(BUF_F_BUF_MEM_GROW_CLEAN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE);
return 0;
}
n = (len + 3) / 3 * 4;
@@ -134,7 +134,7 @@ size_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len)
else
ret = OPENSSL_clear_realloc(str->data, str->max, n);
if (ret == NULL) {
- BUFerr(BUF_F_BUF_MEM_GROW_CLEAN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE);
len = 0;
} else {
str->data = ret;
diff --git a/crypto/buffer/build.info b/crypto/buffer/build.info
index 54da1f92a834..6f31397be722 100644
--- a/crypto/buffer/build.info
+++ b/crypto/buffer/build.info
@@ -1,2 +1,3 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=buffer.c buf_err.c
+SOURCE[../../providers/libfips.a]=buffer.c
diff --git a/crypto/build.info b/crypto/build.info
index 2c619c62e843..16584234feb7 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -1,39 +1,140 @@
+# Note that these directories are filtered in Configure. Look for %skipdir
+# there for further explanations.
+SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 conf \
+ txt_db pkcs7 pkcs12 ui kdf store property \
+ md2 md4 md5 sha mdc2 hmac ripemd whrlpool poly1305 \
+ siphash sm3 des aes rc2 rc4 rc5 idea aria bf cast camellia \
+ seed sm4 chacha modes bn ec rsa dsa dh sm2 dso engine \
+ err comp http ocsp cms ts srp cmac ct async ess crmf cmp encode_decode \
+ ffc
+
LIBS=../libcrypto
-SOURCE[../libcrypto]=\
- cryptlib.c mem.c mem_dbg.c cversion.c ex_data.c cpt_err.c \
- ebcdic.c uid.c o_time.c o_str.c o_dir.c o_fopen.c ctype.c \
- threads_pthread.c threads_win.c threads_none.c getenv.c \
- o_init.c o_fips.c mem_sec.c init.c {- $target{cpuid_asm_src} -} \
- {- $target{uplink_aux_src} -}
-EXTRA= ../ms/uplink-x86.pl ../ms/uplink.c ../ms/applink.c \
- x86cpuid.pl x86_64cpuid.pl ia64cpuid.S \
- ppccpuid.pl pariscid.pl alphacpuid.pl arm64cpuid.pl armv4cpuid.pl
+$UPLINKSRC=
+$UPLINKDEF=
+IF[{- !$disabled{uplink} -}]
+ $UPLINKSRC_common=../ms/uplink.c
+ $UPLINKSRC_x86=$UPLINKSRC_common uplink-x86.S
+ $UPLINKSRC_x86_64=$UPLINKSRC_common uplink-x86_64.s
+ $UPLINKSRC_ia64=$UPLINKSRC_common uplink-ia64.s
+
+ IF[$UPLINKSRC_{- $target{uplink_arch} -}]
+ $UPLINKSRC=$UPLINKSRC_{- $target{uplink_arch} -}
+ $UPLINKDEF=OPENSSL_USE_APPLINK
+ ENDIF
+ENDIF
+
+$CPUIDASM=mem_clr.c
+$CPUIDDEF=
+IF[{- !$disabled{asm} && $config{processor} ne '386' -}]
+ $CPUIDASM_x86=x86cpuid.S
+
+ $CPUIDASM_x86_64=x86_64cpuid.s
+
+ $CPUIDASM_ia64=ia64cpuid.s
+
+ $CPUIDASM_sparcv9=sparcv9cap.c sparccpuid.S
+
+ $CPUIDASM_alpha=alphacpuid.s
+
+ $CPUIDASM_s390x=s390xcap.c s390xcpuid.S
+
+ $CPUIDASM_armv4=armcap.c armv4cpuid.S
+
+ $CPUIDASM_aarch64=armcap.c arm64cpuid.S
+
+ $CPUIDASM_parisc11=pariscid.s
+ $CPUIDASM_parisc20_64=$CPUIDASM_parisc11
+
+ $CPUIDASM_ppc32=ppccpuid.s ppccap.c
+ $CPUIDASM_ppc64=$CPUIDASM_ppc32
+
+ $CPUIDASM_c64xplus=c64xpluscpuid.s
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+ IF[$CPUIDASM_{- $target{asm_arch} -}]
+ $CPUIDASM=$CPUIDASM_{- $target{asm_arch} -}
+ $CPUIDDEF=OPENSSL_CPUID_OBJ
+ ENDIF
+ENDIF
+
+# CPUID support. We need to add that explicitly in every shared library and
+# provider module that uses it. ctype.c is included here because the CPUID
+# uses functions from there to parse magic environment variables.
+$CPUID_COMMON=$CPUIDASM cpuid.c ctype.c
+INCLUDE[cpuid.o]=..
+
+SOURCE[../libcrypto]=$CPUID_COMMON
+DEFINE[../libcrypto]=$CPUIDDEF
+SOURCE[../providers/libfips.a]=$CPUID_COMMON
+DEFINE[../providers/libfips.a]=$CPUIDDEF
+# We only need to include the CPUID stuff in the legacy provider when it's a
+# separate module and it's dynamically linked with libcrypto. Otherwise, it
+# already gets everything that the static libcrypto.a has, and doesn't need it
+# added again.
+IF[{- !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../providers/liblegacy.a]=$CPUID_COMMON
+ DEFINE[../providers/liblegacy.a]=$CPUIDDEF
+ENDIF
+
+# Implementations are now spread across several libraries, so the CPUID define
+# need to be applied to all affected libraries and modules.
+DEFINE[../providers/libcommon.a]=$CPUIDDEF
+DEFINE[../providers/libdefault.a]=$CPUIDDEF
+
+# The Core
+$CORE_COMMON=provider_core.c provider_predefined.c \
+ core_fetch.c core_algorithm.c core_namemap.c self_test_core.c
+
+SOURCE[../libcrypto]=$CORE_COMMON provider_conf.c
+SOURCE[../providers/libfips.a]=$CORE_COMMON
+
+# Central utilities
+$UTIL_COMMON=\
+ cryptlib.c params.c params_from_text.c bsearch.c ex_data.c o_str.c \
+ threads_pthread.c threads_win.c threads_none.c initthread.c \
+ context.c sparse_array.c asn1_dsa.c packet.c param_build.c \
+ param_build_set.c der_writer.c threads_lib.c params_dup.c
+
+IF[{- !$disabled{shared} -}]
+ SOURCE[../libssl]=sparse_array.c
+ENDIF
+
+SOURCE[../libcrypto]=$UTIL_COMMON \
+ mem.c mem_sec.c \
+ cversion.c info.c cpt_err.c ebcdic.c uid.c o_time.c o_dir.c \
+ o_fopen.c getenv.c o_init.c init.c trace.c provider.c provider_child.c \
+ punycode.c passphrase.c
+SOURCE[../providers/libfips.a]=$UTIL_COMMON
+
+SOURCE[../libcrypto]=$UPLINKSRC
+DEFINE[../libcrypto]=$UPLINKDEF
+
+DEPEND[info.o]=buildinf.h
DEPEND[cversion.o]=buildinf.h
GENERATE[buildinf.h]=../util/mkbuildinf.pl "$(CC) $(LIB_CFLAGS) $(CPPFLAGS_Q)" "$(PLATFORM)"
-DEPEND[buildinf.h]=../configdata.pm
-GENERATE[uplink-x86.s]=../ms/uplink-x86.pl $(PERLASM_SCHEME)
-GENERATE[uplink-x86_64.s]=../ms/uplink-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[uplink-ia64.s]=../ms/uplink-ia64.pl $(PERLASM_SCHEME)
+GENERATE[uplink-x86.S]=../ms/uplink-x86.pl
+GENERATE[uplink-x86_64.s]=../ms/uplink-x86_64.pl
+GENERATE[uplink-ia64.s]=../ms/uplink-ia64.pl
-GENERATE[x86cpuid.s]=x86cpuid.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
+GENERATE[x86cpuid.S]=x86cpuid.pl
DEPEND[x86cpuid.s]=perlasm/x86asm.pl
-GENERATE[x86_64cpuid.s]=x86_64cpuid.pl $(PERLASM_SCHEME)
+GENERATE[x86_64cpuid.s]=x86_64cpuid.pl
GENERATE[ia64cpuid.s]=ia64cpuid.S
-GENERATE[ppccpuid.s]=ppccpuid.pl $(PERLASM_SCHEME)
-GENERATE[pariscid.s]=pariscid.pl $(PERLASM_SCHEME)
+GENERATE[ppccpuid.s]=ppccpuid.pl
+GENERATE[pariscid.s]=pariscid.pl
GENERATE[alphacpuid.s]=alphacpuid.pl
-GENERATE[arm64cpuid.S]=arm64cpuid.pl $(PERLASM_SCHEME)
+GENERATE[arm64cpuid.S]=arm64cpuid.pl
INCLUDE[arm64cpuid.o]=.
-GENERATE[armv4cpuid.S]=armv4cpuid.pl $(PERLASM_SCHEME)
+GENERATE[armv4cpuid.S]=armv4cpuid.pl
INCLUDE[armv4cpuid.o]=.
-GENERATE[s390xcpuid.S]=s390xcpuid.pl $(PERLASM_SCHEME)
+GENERATE[s390xcpuid.S]=s390xcpuid.pl
INCLUDE[s390xcpuid.o]=.
-IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-)/ -}]
+IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}]
SHARED_SOURCE[../libcrypto]=dllmain.c
ENDIF
diff --git a/crypto/c64xpluscpuid.pl b/crypto/c64xpluscpuid.pl
index 9aeee574ebf8..20728c03bc69 100644
--- a/crypto/c64xpluscpuid.pl
+++ b/crypto/c64xpluscpuid.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
diff --git a/crypto/camellia/asm/cmll-x86.pl b/crypto/camellia/asm/cmll-x86.pl
index cd514acfae4a..284d31ca9435 100644
--- a/crypto/camellia/asm/cmll-x86.pl
+++ b/crypto/camellia/asm/cmll-x86.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -49,8 +49,7 @@ require "x86asm.pl";
$OPENSSL=1;
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386");
diff --git a/crypto/camellia/asm/cmll-x86_64.pl b/crypto/camellia/asm/cmll-x86_64.pl
index 59e1840160ff..7e069614d915 100644
--- a/crypto/camellia/asm/cmll-x86_64.pl
+++ b/crypto/camellia/asm/cmll-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -36,9 +36,10 @@
# EM64T, pre-Core2 Intel x86_64 CPU, is not as impressive, because it
# apparently emulates some of 64-bit operations in [32-bit] microcode.
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -47,7 +48,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
sub hi() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1h/; $r; }
@@ -685,6 +687,7 @@ $code.=<<___;
.align 16
Camellia_cbc_encrypt:
.cfi_startproc
+ endbranch
cmp \$0,%rdx
je .Lcbc_abort
push %rbx
diff --git a/crypto/camellia/asm/cmllt4-sparcv9.pl b/crypto/camellia/asm/cmllt4-sparcv9.pl
index 71a40f6af90c..86e38d65c476 100644
--- a/crypto/camellia/asm/cmllt4-sparcv9.pl
+++ b/crypto/camellia/asm/cmllt4-sparcv9.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -53,8 +53,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "sparcv9_modes.pl";
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
$::evp=1; # if $evp is set to 0, script generates module with
# Camellia_[en|de]crypt, Camellia_set_key and Camellia_cbc_encrypt
@@ -67,7 +66,10 @@ $::evp=1; # if $evp is set to 0, script generates module with
my ($inp,$out,$key,$rounds,$tmp,$mask)=map("%o$_",(0..5));
$code=<<___;
-#include "sparc_arch.h"
+#ifndef __ASSEMBLER__
+# define __ASSEMBLER__ 1
+#endif
+#include "crypto/sparc_arch.h"
.text
diff --git a/crypto/camellia/build.info b/crypto/camellia/build.info
index e36a19bd4d0b..f13cd8c958be 100644
--- a/crypto/camellia/build.info
+++ b/crypto/camellia/build.info
@@ -1,13 +1,25 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- cmll_ecb.c cmll_ofb.c cmll_cfb.c cmll_ctr.c \
- {- $target{cmll_asm_src} -}
-
-GENERATE[cmll-x86.s]=asm/cmll-x86.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) \
- $(PROCESSOR)
-DEPEND[cmll-x86.s]=../perlasm/x86asm.pl
-GENERATE[cmll-x86_64.s]=asm/cmll-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[cmllt4-sparcv9.S]=asm/cmllt4-sparcv9.pl $(PERLASM_SCHEME)
+
+$CMLLASM=camellia.c cmll_misc.c cmll_cbc.c
+IF[{- !$disabled{asm} -}]
+ $CMLLASM_x86=cmll-x86.S
+ $CMLLASM_x86_64=cmll-x86_64.s cmll_misc.c
+ $CMLLASM_sparcv9=camellia.c cmll_misc.c cmll_cbc.c cmllt4-sparcv9.S
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one
+ IF[$CMLLASM_{- $target{asm_arch} -}]
+ $CMLLASM=$CMLLASM_{- $target{asm_arch} -}
+ $CMLLDEF=CMLL_ASM
+ ENDIF
+ENDIF
+
+SOURCE[../../libcrypto]=cmll_ecb.c cmll_ofb.c cmll_cfb.c cmll_ctr.c $CMLLASM
+DEFINE[../../libcrypto]=$CMLLDEF
+
+GENERATE[cmll-x86.S]=asm/cmll-x86.pl
+DEPEND[cmll-x86.S]=../perlasm/x86asm.pl
+GENERATE[cmll-x86_64.s]=asm/cmll-x86_64.pl
+GENERATE[cmllt4-sparcv9.S]=asm/cmllt4-sparcv9.pl
INCLUDE[cmllt4-sparcv9.o]=..
DEPEND[cmllt4-sparcv9.S]=../perlasm/sparcv9_modes.pl
diff --git a/crypto/camellia/camellia.c b/crypto/camellia/camellia.c
index f623864bc413..a4de9f891ab8 100644
--- a/crypto/camellia/camellia.c
+++ b/crypto/camellia/camellia.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -39,6 +39,12 @@
* words reasonable performance even with not so modern compilers.
*/
+/*
+ * Camellia low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/camellia.h>
#include "cmll_local.h"
#include <string.h>
@@ -493,9 +499,9 @@ void Camellia_DecryptBlock_Rounds(int grandRounds, const u8 ciphertext[],
PUTU32(plaintext + 12, s1);
}
-void Camellia_DecryptBlock(int keyBitLength, const u8 plaintext[],
- const KEY_TABLE_TYPE keyTable, u8 ciphertext[])
+void Camellia_DecryptBlock(int keyBitLength, const u8 ciphertext[],
+ const KEY_TABLE_TYPE keyTable, u8 plaintext[])
{
Camellia_DecryptBlock_Rounds(keyBitLength == 128 ? 3 : 4,
- plaintext, keyTable, ciphertext);
+ ciphertext, keyTable, plaintext);
}
diff --git a/crypto/camellia/cmll_cbc.c b/crypto/camellia/cmll_cbc.c
index b19171ded26b..140681a9bd26 100644
--- a/crypto/camellia/cmll_cbc.c
+++ b/crypto/camellia/cmll_cbc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * Camellia low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/camellia.h>
#include <openssl/modes.h>
diff --git a/crypto/camellia/cmll_cfb.c b/crypto/camellia/cmll_cfb.c
index 4f49eaded66c..8a92572d9395 100644
--- a/crypto/camellia/cmll_cfb.c
+++ b/crypto/camellia/cmll_cfb.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * Camellia low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/camellia.h>
#include <openssl/modes.h>
diff --git a/crypto/camellia/cmll_ctr.c b/crypto/camellia/cmll_ctr.c
index 161d1e18c136..26d875e34c41 100644
--- a/crypto/camellia/cmll_ctr.c
+++ b/crypto/camellia/cmll_ctr.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * Camellia low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/camellia.h>
#include <openssl/modes.h>
diff --git a/crypto/camellia/cmll_ecb.c b/crypto/camellia/cmll_ecb.c
index 5760d1ed35fc..86ffbd51e6c2 100644
--- a/crypto/camellia/cmll_ecb.c
+++ b/crypto/camellia/cmll_ecb.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * Camellia low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/camellia.h>
#include "cmll_local.h"
diff --git a/crypto/camellia/cmll_local.h b/crypto/camellia/cmll_local.h
index d16baa55facc..c1d940d3d8f8 100644
--- a/crypto/camellia/cmll_local.h
+++ b/crypto/camellia/cmll_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/camellia/cmll_misc.c b/crypto/camellia/cmll_misc.c
index d8fc3738c404..f98dff7e3daa 100644
--- a/crypto/camellia/cmll_misc.c
+++ b/crypto/camellia/cmll_misc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * Camellia low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/opensslv.h>
#include <openssl/camellia.h>
#include "cmll_local.h"
diff --git a/crypto/camellia/cmll_ofb.c b/crypto/camellia/cmll_ofb.c
index b43c685c751f..4eeb0b5b75ee 100644
--- a/crypto/camellia/cmll_ofb.c
+++ b/crypto/camellia/cmll_ofb.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * Camellia low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/camellia.h>
#include <openssl/modes.h>
diff --git a/crypto/cast/asm/cast-586.pl b/crypto/cast/asm/cast-586.pl
index 04710819380a..044d703c1278 100644
--- a/crypto/cast/asm/cast-586.pl
+++ b/crypto/cast/asm/cast-586.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -18,8 +18,7 @@ push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
require "cbc.pl";
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386");
diff --git a/crypto/cast/build.info b/crypto/cast/build.info
index b0f59f38002c..4395f0ac22a2 100644
--- a/crypto/cast/build.info
+++ b/crypto/cast/build.info
@@ -1,7 +1,26 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- c_skey.c c_ecb.c {- $target{cast_asm_src} -} c_cfb64.c c_ofb64.c
-GENERATE[cast-586.s]=asm/cast-586.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-DEPEND[cast-586.s]=../perlasm/x86asm.pl ../perlasm/cbc.pl
+$CASTASM=c_enc.c
+# CAST assembly source is not PIC
+IF[{- !$disabled{asm} && $disabled{pic} -}]
+ $CASTASM_x86=cast-586.S
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one
+ IF[$CASTASM_{- $target{asm_arch} -}]
+ $CASTASM=$CASTASM_{- $target{asm_arch} -}
+ ENDIF
+ENDIF
+
+$ALL=c_skey.c c_ecb.c $CASTASM c_cfb64.c c_ofb64.c
+
+SOURCE[../../libcrypto]=$ALL
+
+# When all deprecated symbols are removed, libcrypto doesn't export the
+# cast functions, so we must include them directly in liblegacy.a
+IF[{- $disabled{'deprecated-3.0'} && !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../../providers/liblegacy.a]=$ALL
+ENDIF
+
+GENERATE[cast-586.S]=asm/cast-586.pl
+DEPEND[cast-586.S]=../perlasm/x86asm.pl ../perlasm/cbc.pl
diff --git a/crypto/cast/c_cfb64.c b/crypto/cast/c_cfb64.c
index 72221595382b..97081734ecb7 100644
--- a/crypto/cast/c_cfb64.c
+++ b/crypto/cast/c_cfb64.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * CAST low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/cast.h>
#include "cast_local.h"
diff --git a/crypto/cast/c_ecb.c b/crypto/cast/c_ecb.c
index 6fe093f75b1b..a0ab660f8489 100644
--- a/crypto/cast/c_ecb.c
+++ b/crypto/cast/c_ecb.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * CAST low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/cast.h>
#include "cast_local.h"
#include <openssl/opensslv.h>
diff --git a/crypto/cast/c_enc.c b/crypto/cast/c_enc.c
index d27d1fc0a54f..4ed945a50887 100644
--- a/crypto/cast/c_enc.c
+++ b/crypto/cast/c_enc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * CAST low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/cast.h>
#include "cast_local.h"
diff --git a/crypto/cast/c_ofb64.c b/crypto/cast/c_ofb64.c
index 49c0cfade577..d4aa10ff6867 100644
--- a/crypto/cast/c_ofb64.c
+++ b/crypto/cast/c_ofb64.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * CAST low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/cast.h>
#include "cast_local.h"
diff --git a/crypto/cast/c_skey.c b/crypto/cast/c_skey.c
index 0311482d20dd..030e20ea3147 100644
--- a/crypto/cast/c_skey.c
+++ b/crypto/cast/c_skey.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * CAST low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/cast.h>
#include "cast_local.h"
#include "cast_s.h"
diff --git a/crypto/cast/cast_local.h b/crypto/cast/cast_local.h
index 35e89930a8c0..4434a342002a 100644
--- a/crypto/cast/cast_local.h
+++ b/crypto/cast/cast_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/cast/cast_s.h b/crypto/cast/cast_s.h
index b27415b967f5..57163d17e124 100644
--- a/crypto/cast/cast_s.h
+++ b/crypto/cast/cast_s.h
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/chacha/asm/chacha-armv4.pl b/crypto/chacha/asm/chacha-armv4.pl
index 81c616add313..0aa13519eb83 100755
--- a/crypto/chacha/asm/chacha-armv4.pl
+++ b/crypto/chacha/asm/chacha-armv4.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -34,9 +34,10 @@
# but then Snapdragon S4 and Cortex-A8 results get
# 20-25% worse;
-$flavour = shift;
-if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour && $flavour ne "void") {
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -44,9 +45,10 @@ if ($flavour && $flavour ne "void") {
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
- open STDOUT,"| \"$^X\" $xlate $flavour $output";
+ open STDOUT,"| \"$^X\" $xlate $flavour $output"
+ or die "can't call $xlate: $!";
} else {
- open STDOUT,">$output";
+ $output and open STDOUT,">$output";
}
sub AUTOLOAD() # thunk [simplified] x86-style perlasm
@@ -171,7 +173,6 @@ my @ret;
$code.=<<___;
#include "arm_arch.h"
-.text
#if defined(__thumb2__) || defined(__clang__)
.syntax unified
#endif
@@ -185,6 +186,8 @@ $code.=<<___;
#define ldrhsb ldrbhs
#endif
+.text
+
.align 5
.Lsigma:
.long 0x61707865,0x3320646e,0x79622d32,0x6b206574 @ endian-neutral
@@ -192,7 +195,11 @@ $code.=<<___;
.long 1,0,0,0
#if __ARM_MAX_ARCH__>=7
.LOPENSSL_armcap:
+# ifdef _WIN32
+.word OPENSSL_armcap_P
+# else
.word OPENSSL_armcap_P-.LChaCha20_ctr32
+# endif
#else
.word -1
#endif
@@ -219,8 +226,10 @@ ChaCha20_ctr32:
cmp r2,#192 @ test len
bls .Lshort
ldr r4,[r14,#-32]
+# if !defined(_WIN32)
ldr r4,[r14,r4]
-# ifdef __APPLE__
+# endif
+# if defined(__APPLE__) || defined(_WIN32)
ldr r4,[r4]
# endif
tst r4,#ARMV7_NEON
diff --git a/crypto/chacha/asm/chacha-armv8.pl b/crypto/chacha/asm/chacha-armv8.pl
index 84c98014803b..dcdc4a04e367 100755
--- a/crypto/chacha/asm/chacha-armv8.pl
+++ b/crypto/chacha/asm/chacha-armv8.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -18,32 +18,44 @@
#
# ChaCha20 for ARMv8.
#
+# April 2019
+#
+# Replace 3xNEON+1xIALU code path with 4+1. 4+1 is actually fastest
+# option on most(*), but not all, processors, yet 6+2 is retained.
+# This is because penalties are considered tolerable in comparison to
+# improvement on processors where 6+2 helps. Most notably +37% on
+# ThunderX2. It's server-oriented processor which will have to serve
+# as many requests as possible. While others are mostly clients, when
+# performance doesn't have to be absolute top-notch, just fast enough,
+# as majority of time is spent "entertaining" relatively slow human.
+#
# Performance in cycles per byte out of large buffer.
#
-# IALU/gcc-4.9 3xNEON+1xIALU 6xNEON+2xIALU
+# IALU/gcc-4.9 4xNEON+1xIALU 6xNEON+2xIALU
#
-# Apple A7 5.50/+49% 3.33 1.70
-# Cortex-A53 8.40/+80% 4.72 4.72(*)
-# Cortex-A57 8.06/+43% 4.90 4.43(**)
-# Denver 4.50/+82% 2.63 2.67(*)
-# X-Gene 9.50/+46% 8.82 8.89(*)
-# Mongoose 8.00/+44% 3.64 3.25
-# Kryo 8.17/+50% 4.83 4.65
+# Apple A7 5.50/+49% 2.72 1.60
+# Cortex-A53 8.40/+80% 4.06 4.45(*)
+# Cortex-A57 8.06/+43% 4.15 4.40(*)
+# Denver 4.50/+82% 2.30 2.70(*)
+# X-Gene 9.50/+46% 8.20 8.90(*)
+# Mongoose 8.00/+44% 2.74 3.12(*)
+# Kryo 8.17/+50% 4.47 4.65(*)
+# ThunderX2 7.22/+48% 5.64 4.10
#
-# (*) it's expected that doubling interleave factor doesn't help
-# all processors, only those with higher NEON latency and
-# higher instruction issue rate;
-# (**) expected improvement was actually higher;
+# (*) slower than 4+1:-(
-$flavour=shift;
-$output=shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
sub AUTOLOAD() # thunk [simplified] x86-style perlasm
@@ -120,42 +132,37 @@ my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
}
$code.=<<___;
-#include "arm_arch.h"
-
-.text
-
+#ifndef __KERNEL__
+# include "arm_arch.h"
.extern OPENSSL_armcap_P
.hidden OPENSSL_armcap_P
+#endif
+
+.text
.align 5
.Lsigma:
.quad 0x3320646e61707865,0x6b20657479622d32 // endian-neutral
.Lone:
-.long 1,0,0,0
-.LOPENSSL_armcap_P:
-#ifdef __ILP32__
-.long OPENSSL_armcap_P-.
-#else
-.quad OPENSSL_armcap_P-.
-#endif
-.asciz "ChaCha20 for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
+.long 1,2,3,4
+.Lrot24:
+.long 0x02010003,0x06050407,0x0a09080b,0x0e0d0c0f
+.asciz "ChaCha20 for ARMv8, CRYPTOGAMS by \@dot-asm"
.globl ChaCha20_ctr32
.type ChaCha20_ctr32,%function
.align 5
ChaCha20_ctr32:
cbz $len,.Labort
- adr @x[0],.LOPENSSL_armcap_P
cmp $len,#192
b.lo .Lshort
-#ifdef __ILP32__
- ldrsw @x[1],[@x[0]]
-#else
- ldr @x[1],[@x[0]]
-#endif
- ldr w17,[@x[1],@x[0]]
+
+#ifndef __KERNEL__
+ adrp x17,OPENSSL_armcap_P
+ ldr w17,[x17,#:lo12:OPENSSL_armcap_P]
tst w17,#ARMV7_NEON
- b.ne ChaCha20_neon
+ b.ne .LChaCha20_neon
+#endif
.Lshort:
.inst 0xd503233f // paciasp
@@ -174,7 +181,7 @@ ChaCha20_ctr32:
ldp @d[2],@d[3],[$key] // load key
ldp @d[4],@d[5],[$key,#16]
ldp @d[6],@d[7],[$ctr] // load counter
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
ror @d[2],@d[2],#32
ror @d[3],@d[3],#32
ror @d[4],@d[4],#32
@@ -243,7 +250,7 @@ $code.=<<___;
add @x[14],@x[14],@x[15],lsl#32
ldp @x[13],@x[15],[$inp,#48]
add $inp,$inp,#64
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
rev @x[0],@x[0]
rev @x[2],@x[2]
rev @x[4],@x[4]
@@ -300,7 +307,7 @@ $code.=<<___;
add @x[10],@x[10],@x[11],lsl#32
add @x[12],@x[12],@x[13],lsl#32
add @x[14],@x[14],@x[15],lsl#32
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
rev @x[0],@x[0]
rev @x[2],@x[2]
rev @x[4],@x[4]
@@ -341,46 +348,91 @@ $code.=<<___;
___
{{{
-my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2,$T0,$T1,$T2,$T3) =
- map("v$_.4s",(0..7,16..23));
-my (@K)=map("v$_.4s",(24..30));
-my $ONE="v31.4s";
+my @K = map("v$_.4s",(0..3));
+my ($xt0,$xt1,$xt2,$xt3, $CTR,$ROT24) = map("v$_.4s",(4..9));
+my @X = map("v$_.4s",(16,20,24,28, 17,21,25,29, 18,22,26,30, 19,23,27,31));
+my ($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3,
+ $xc0,$xc1,$xc2,$xc3, $xd0,$xd1,$xd2,$xd3) = @X;
-sub NEONROUND {
-my $odd = pop;
-my ($a,$b,$c,$d,$t)=@_;
+sub NEON_lane_ROUND {
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+my @x=map("'$_'",@X);
(
- "&add ('$a','$a','$b')",
- "&eor ('$d','$d','$a')",
- "&rev32_16 ('$d','$d')", # vrot ($d,16)
-
- "&add ('$c','$c','$d')",
- "&eor ('$t','$b','$c')",
- "&ushr ('$b','$t',20)",
- "&sli ('$b','$t',12)",
-
- "&add ('$a','$a','$b')",
- "&eor ('$t','$d','$a')",
- "&ushr ('$d','$t',24)",
- "&sli ('$d','$t',8)",
-
- "&add ('$c','$c','$d')",
- "&eor ('$t','$b','$c')",
- "&ushr ('$b','$t',25)",
- "&sli ('$b','$t',7)",
-
- "&ext ('$c','$c','$c',8)",
- "&ext ('$d','$d','$d',$odd?4:12)",
- "&ext ('$b','$b','$b',$odd?12:4)"
+ "&add (@x[$a0],@x[$a0],@x[$b0])", # Q1
+ "&add (@x[$a1],@x[$a1],@x[$b1])", # Q2
+ "&add (@x[$a2],@x[$a2],@x[$b2])", # Q3
+ "&add (@x[$a3],@x[$a3],@x[$b3])", # Q4
+ "&eor (@x[$d0],@x[$d0],@x[$a0])",
+ "&eor (@x[$d1],@x[$d1],@x[$a1])",
+ "&eor (@x[$d2],@x[$d2],@x[$a2])",
+ "&eor (@x[$d3],@x[$d3],@x[$a3])",
+ "&rev32_16 (@x[$d0],@x[$d0])",
+ "&rev32_16 (@x[$d1],@x[$d1])",
+ "&rev32_16 (@x[$d2],@x[$d2])",
+ "&rev32_16 (@x[$d3],@x[$d3])",
+
+ "&add (@x[$c0],@x[$c0],@x[$d0])",
+ "&add (@x[$c1],@x[$c1],@x[$d1])",
+ "&add (@x[$c2],@x[$c2],@x[$d2])",
+ "&add (@x[$c3],@x[$c3],@x[$d3])",
+ "&eor ('$xt0',@x[$b0],@x[$c0])",
+ "&eor ('$xt1',@x[$b1],@x[$c1])",
+ "&eor ('$xt2',@x[$b2],@x[$c2])",
+ "&eor ('$xt3',@x[$b3],@x[$c3])",
+ "&ushr (@x[$b0],'$xt0',20)",
+ "&ushr (@x[$b1],'$xt1',20)",
+ "&ushr (@x[$b2],'$xt2',20)",
+ "&ushr (@x[$b3],'$xt3',20)",
+ "&sli (@x[$b0],'$xt0',12)",
+ "&sli (@x[$b1],'$xt1',12)",
+ "&sli (@x[$b2],'$xt2',12)",
+ "&sli (@x[$b3],'$xt3',12)",
+
+ "&add (@x[$a0],@x[$a0],@x[$b0])",
+ "&add (@x[$a1],@x[$a1],@x[$b1])",
+ "&add (@x[$a2],@x[$a2],@x[$b2])",
+ "&add (@x[$a3],@x[$a3],@x[$b3])",
+ "&eor ('$xt0',@x[$d0],@x[$a0])",
+ "&eor ('$xt1',@x[$d1],@x[$a1])",
+ "&eor ('$xt2',@x[$d2],@x[$a2])",
+ "&eor ('$xt3',@x[$d3],@x[$a3])",
+ "&tbl (@x[$d0],'{$xt0}','$ROT24')",
+ "&tbl (@x[$d1],'{$xt1}','$ROT24')",
+ "&tbl (@x[$d2],'{$xt2}','$ROT24')",
+ "&tbl (@x[$d3],'{$xt3}','$ROT24')",
+
+ "&add (@x[$c0],@x[$c0],@x[$d0])",
+ "&add (@x[$c1],@x[$c1],@x[$d1])",
+ "&add (@x[$c2],@x[$c2],@x[$d2])",
+ "&add (@x[$c3],@x[$c3],@x[$d3])",
+ "&eor ('$xt0',@x[$b0],@x[$c0])",
+ "&eor ('$xt1',@x[$b1],@x[$c1])",
+ "&eor ('$xt2',@x[$b2],@x[$c2])",
+ "&eor ('$xt3',@x[$b3],@x[$c3])",
+ "&ushr (@x[$b0],'$xt0',25)",
+ "&ushr (@x[$b1],'$xt1',25)",
+ "&ushr (@x[$b2],'$xt2',25)",
+ "&ushr (@x[$b3],'$xt3',25)",
+ "&sli (@x[$b0],'$xt0',7)",
+ "&sli (@x[$b1],'$xt1',7)",
+ "&sli (@x[$b2],'$xt2',7)",
+ "&sli (@x[$b3],'$xt3',7)"
);
}
$code.=<<___;
+#ifdef __KERNEL__
+.globl ChaCha20_neon
+#endif
.type ChaCha20_neon,%function
.align 5
ChaCha20_neon:
+.LChaCha20_neon:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-96]!
add x29,sp,#0
@@ -403,8 +455,9 @@ ChaCha20_neon:
ld1 {@K[1],@K[2]},[$key]
ldp @d[6],@d[7],[$ctr] // load counter
ld1 {@K[3]},[$ctr]
- ld1 {$ONE},[@x[0]]
-#ifdef __ARMEB__
+ stp d8,d9,[sp] // meet ABI requirements
+ ld1 {$CTR,$ROT24},[@x[0]]
+#ifdef __AARCH64EB__
rev64 @K[0],@K[0]
ror @d[2],@d[2],#32
ror @d[3],@d[3],#32
@@ -413,115 +466,129 @@ ChaCha20_neon:
ror @d[6],@d[6],#32
ror @d[7],@d[7],#32
#endif
- add @K[3],@K[3],$ONE // += 1
- add @K[4],@K[3],$ONE
- add @K[5],@K[4],$ONE
- shl $ONE,$ONE,#2 // 1 -> 4
.Loop_outer_neon:
- mov.32 @x[0],@d[0] // unpack key block
- lsr @x[1],@d[0],#32
- mov $A0,@K[0]
- mov.32 @x[2],@d[1]
- lsr @x[3],@d[1],#32
- mov $A1,@K[0]
- mov.32 @x[4],@d[2]
- lsr @x[5],@d[2],#32
- mov $A2,@K[0]
- mov.32 @x[6],@d[3]
- mov $B0,@K[1]
- lsr @x[7],@d[3],#32
- mov $B1,@K[1]
- mov.32 @x[8],@d[4]
- mov $B2,@K[1]
- lsr @x[9],@d[4],#32
- mov $D0,@K[3]
- mov.32 @x[10],@d[5]
- mov $D1,@K[4]
- lsr @x[11],@d[5],#32
- mov $D2,@K[5]
- mov.32 @x[12],@d[6]
- mov $C0,@K[2]
- lsr @x[13],@d[6],#32
- mov $C1,@K[2]
- mov.32 @x[14],@d[7]
- mov $C2,@K[2]
- lsr @x[15],@d[7],#32
+ dup $xa0,@{K[0]}[0] // unpack key block
+ mov.32 @x[0],@d[0]
+ dup $xa1,@{K[0]}[1]
+ lsr @x[1],@d[0],#32
+ dup $xa2,@{K[0]}[2]
+ mov.32 @x[2],@d[1]
+ dup $xa3,@{K[0]}[3]
+ lsr @x[3],@d[1],#32
+ dup $xb0,@{K[1]}[0]
+ mov.32 @x[4],@d[2]
+ dup $xb1,@{K[1]}[1]
+ lsr @x[5],@d[2],#32
+ dup $xb2,@{K[1]}[2]
+ mov.32 @x[6],@d[3]
+ dup $xb3,@{K[1]}[3]
+ lsr @x[7],@d[3],#32
+ dup $xd0,@{K[3]}[0]
+ mov.32 @x[8],@d[4]
+ dup $xd1,@{K[3]}[1]
+ lsr @x[9],@d[4],#32
+ dup $xd2,@{K[3]}[2]
+ mov.32 @x[10],@d[5]
+ dup $xd3,@{K[3]}[3]
+ lsr @x[11],@d[5],#32
+ add $xd0,$xd0,$CTR
+ mov.32 @x[12],@d[6]
+ dup $xc0,@{K[2]}[0]
+ lsr @x[13],@d[6],#32
+ dup $xc1,@{K[2]}[1]
+ mov.32 @x[14],@d[7]
+ dup $xc2,@{K[2]}[2]
+ lsr @x[15],@d[7],#32
+ dup $xc3,@{K[2]}[3]
mov $ctr,#10
- subs $len,$len,#256
+ subs $len,$len,#320
.Loop_neon:
sub $ctr,$ctr,#1
___
- my @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0);
- my @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0);
- my @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0);
- my @thread3=&ROUND(0,4,8,12);
-
- foreach (@thread0) {
- eval; eval(shift(@thread3));
- eval(shift(@thread1)); eval(shift(@thread3));
- eval(shift(@thread2)); eval(shift(@thread3));
- }
-
- @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1);
- @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1);
- @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1);
- @thread3=&ROUND(0,5,10,15);
+ my @plus_one=&ROUND(0,4,8,12);
+ foreach (&NEON_lane_ROUND(0,4,8,12)) { eval; eval(shift(@plus_one)); }
- foreach (@thread0) {
- eval; eval(shift(@thread3));
- eval(shift(@thread1)); eval(shift(@thread3));
- eval(shift(@thread2)); eval(shift(@thread3));
- }
+ @plus_one=&ROUND(0,5,10,15);
+ foreach (&NEON_lane_ROUND(0,5,10,15)) { eval; eval(shift(@plus_one)); }
$code.=<<___;
cbnz $ctr,.Loop_neon
- add.32 @x[0],@x[0],@d[0] // accumulate key block
- add $A0,$A0,@K[0]
- add @x[1],@x[1],@d[0],lsr#32
- add $A1,$A1,@K[0]
- add.32 @x[2],@x[2],@d[1]
- add $A2,$A2,@K[0]
- add @x[3],@x[3],@d[1],lsr#32
- add $C0,$C0,@K[2]
- add.32 @x[4],@x[4],@d[2]
- add $C1,$C1,@K[2]
- add @x[5],@x[5],@d[2],lsr#32
- add $C2,$C2,@K[2]
- add.32 @x[6],@x[6],@d[3]
- add $D0,$D0,@K[3]
- add @x[7],@x[7],@d[3],lsr#32
- add.32 @x[8],@x[8],@d[4]
- add $D1,$D1,@K[4]
- add @x[9],@x[9],@d[4],lsr#32
- add.32 @x[10],@x[10],@d[5]
- add $D2,$D2,@K[5]
- add @x[11],@x[11],@d[5],lsr#32
- add.32 @x[12],@x[12],@d[6]
- add $B0,$B0,@K[1]
- add @x[13],@x[13],@d[6],lsr#32
- add.32 @x[14],@x[14],@d[7]
- add $B1,$B1,@K[1]
- add @x[15],@x[15],@d[7],lsr#32
- add $B2,$B2,@K[1]
+ add $xd0,$xd0,$CTR
+
+ zip1 $xt0,$xa0,$xa1 // transpose data
+ zip1 $xt1,$xa2,$xa3
+ zip2 $xt2,$xa0,$xa1
+ zip2 $xt3,$xa2,$xa3
+ zip1.64 $xa0,$xt0,$xt1
+ zip2.64 $xa1,$xt0,$xt1
+ zip1.64 $xa2,$xt2,$xt3
+ zip2.64 $xa3,$xt2,$xt3
+
+ zip1 $xt0,$xb0,$xb1
+ zip1 $xt1,$xb2,$xb3
+ zip2 $xt2,$xb0,$xb1
+ zip2 $xt3,$xb2,$xb3
+ zip1.64 $xb0,$xt0,$xt1
+ zip2.64 $xb1,$xt0,$xt1
+ zip1.64 $xb2,$xt2,$xt3
+ zip2.64 $xb3,$xt2,$xt3
+
+ zip1 $xt0,$xc0,$xc1
+ add.32 @x[0],@x[0],@d[0] // accumulate key block
+ zip1 $xt1,$xc2,$xc3
+ add @x[1],@x[1],@d[0],lsr#32
+ zip2 $xt2,$xc0,$xc1
+ add.32 @x[2],@x[2],@d[1]
+ zip2 $xt3,$xc2,$xc3
+ add @x[3],@x[3],@d[1],lsr#32
+ zip1.64 $xc0,$xt0,$xt1
+ add.32 @x[4],@x[4],@d[2]
+ zip2.64 $xc1,$xt0,$xt1
+ add @x[5],@x[5],@d[2],lsr#32
+ zip1.64 $xc2,$xt2,$xt3
+ add.32 @x[6],@x[6],@d[3]
+ zip2.64 $xc3,$xt2,$xt3
+ add @x[7],@x[7],@d[3],lsr#32
+
+ zip1 $xt0,$xd0,$xd1
+ add.32 @x[8],@x[8],@d[4]
+ zip1 $xt1,$xd2,$xd3
+ add @x[9],@x[9],@d[4],lsr#32
+ zip2 $xt2,$xd0,$xd1
+ add.32 @x[10],@x[10],@d[5]
+ zip2 $xt3,$xd2,$xd3
+ add @x[11],@x[11],@d[5],lsr#32
+ zip1.64 $xd0,$xt0,$xt1
+ add.32 @x[12],@x[12],@d[6]
+ zip2.64 $xd1,$xt0,$xt1
+ add @x[13],@x[13],@d[6],lsr#32
+ zip1.64 $xd2,$xt2,$xt3
+ add.32 @x[14],@x[14],@d[7]
+ zip2.64 $xd3,$xt2,$xt3
+ add @x[15],@x[15],@d[7],lsr#32
b.lo .Ltail_neon
add @x[0],@x[0],@x[1],lsl#32 // pack
add @x[2],@x[2],@x[3],lsl#32
ldp @x[1],@x[3],[$inp,#0] // load input
+ add $xa0,$xa0,@K[0] // accumulate key block
add @x[4],@x[4],@x[5],lsl#32
add @x[6],@x[6],@x[7],lsl#32
ldp @x[5],@x[7],[$inp,#16]
+ add $xb0,$xb0,@K[1]
add @x[8],@x[8],@x[9],lsl#32
add @x[10],@x[10],@x[11],lsl#32
ldp @x[9],@x[11],[$inp,#32]
+ add $xc0,$xc0,@K[2]
add @x[12],@x[12],@x[13],lsl#32
add @x[14],@x[14],@x[15],lsl#32
ldp @x[13],@x[15],[$inp,#48]
+ add $xd0,$xd0,@K[3]
add $inp,$inp,#64
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
rev @x[0],@x[0]
rev @x[2],@x[2]
rev @x[4],@x[4]
@@ -531,48 +598,68 @@ $code.=<<___;
rev @x[12],@x[12]
rev @x[14],@x[14]
#endif
- ld1.8 {$T0-$T3},[$inp],#64
+ ld1.8 {$xt0-$xt3},[$inp],#64
eor @x[0],@x[0],@x[1]
+ add $xa1,$xa1,@K[0]
eor @x[2],@x[2],@x[3]
+ add $xb1,$xb1,@K[1]
eor @x[4],@x[4],@x[5]
+ add $xc1,$xc1,@K[2]
eor @x[6],@x[6],@x[7]
+ add $xd1,$xd1,@K[3]
eor @x[8],@x[8],@x[9]
- eor $A0,$A0,$T0
+ eor $xa0,$xa0,$xt0
+ movi $xt0,#5
eor @x[10],@x[10],@x[11]
- eor $B0,$B0,$T1
+ eor $xb0,$xb0,$xt1
eor @x[12],@x[12],@x[13]
- eor $C0,$C0,$T2
+ eor $xc0,$xc0,$xt2
eor @x[14],@x[14],@x[15]
- eor $D0,$D0,$T3
- ld1.8 {$T0-$T3},[$inp],#64
+ eor $xd0,$xd0,$xt3
+ add $CTR,$CTR,$xt0 // += 5
+ ld1.8 {$xt0-$xt3},[$inp],#64
stp @x[0],@x[2],[$out,#0] // store output
- add @d[6],@d[6],#4 // increment counter
+ add @d[6],@d[6],#5 // increment counter
stp @x[4],@x[6],[$out,#16]
- add @K[3],@K[3],$ONE // += 4
stp @x[8],@x[10],[$out,#32]
- add @K[4],@K[4],$ONE
stp @x[12],@x[14],[$out,#48]
- add @K[5],@K[5],$ONE
add $out,$out,#64
- st1.8 {$A0-$D0},[$out],#64
- ld1.8 {$A0-$D0},[$inp],#64
-
- eor $A1,$A1,$T0
- eor $B1,$B1,$T1
- eor $C1,$C1,$T2
- eor $D1,$D1,$T3
- st1.8 {$A1-$D1},[$out],#64
-
- eor $A2,$A2,$A0
- eor $B2,$B2,$B0
- eor $C2,$C2,$C0
- eor $D2,$D2,$D0
- st1.8 {$A2-$D2},[$out],#64
+ st1.8 {$xa0-$xd0},[$out],#64
+ add $xa2,$xa2,@K[0]
+ add $xb2,$xb2,@K[1]
+ add $xc2,$xc2,@K[2]
+ add $xd2,$xd2,@K[3]
+ ld1.8 {$xa0-$xd0},[$inp],#64
+
+ eor $xa1,$xa1,$xt0
+ eor $xb1,$xb1,$xt1
+ eor $xc1,$xc1,$xt2
+ eor $xd1,$xd1,$xt3
+ st1.8 {$xa1-$xd1},[$out],#64
+ add $xa3,$xa3,@K[0]
+ add $xb3,$xb3,@K[1]
+ add $xc3,$xc3,@K[2]
+ add $xd3,$xd3,@K[3]
+ ld1.8 {$xa1-$xd1},[$inp],#64
+
+ eor $xa2,$xa2,$xa0
+ eor $xb2,$xb2,$xb0
+ eor $xc2,$xc2,$xc0
+ eor $xd2,$xd2,$xd0
+ st1.8 {$xa2-$xd2},[$out],#64
+
+ eor $xa3,$xa3,$xa1
+ eor $xb3,$xb3,$xb1
+ eor $xc3,$xc3,$xc1
+ eor $xd3,$xd3,$xd1
+ st1.8 {$xa3-$xd3},[$out],#64
b.hi .Loop_outer_neon
+ ldp d8,d9,[sp] // meet ABI requirements
+
ldp x19,x20,[x29,#16]
add sp,sp,#64
ldp x21,x22,[x29,#32]
@@ -583,8 +670,10 @@ $code.=<<___;
.inst 0xd50323bf // autiasp
ret
+.align 4
.Ltail_neon:
- add $len,$len,#256
+ add $len,$len,#320
+ ldp d8,d9,[sp] // meet ABI requirements
cmp $len,#64
b.lo .Less_than_64
@@ -601,7 +690,7 @@ $code.=<<___;
add @x[14],@x[14],@x[15],lsl#32
ldp @x[13],@x[15],[$inp,#48]
add $inp,$inp,#64
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
rev @x[0],@x[0]
rev @x[2],@x[2]
rev @x[4],@x[4]
@@ -621,48 +710,68 @@ $code.=<<___;
eor @x[14],@x[14],@x[15]
stp @x[0],@x[2],[$out,#0] // store output
- add @d[6],@d[6],#4 // increment counter
+ add $xa0,$xa0,@K[0] // accumulate key block
stp @x[4],@x[6],[$out,#16]
+ add $xb0,$xb0,@K[1]
stp @x[8],@x[10],[$out,#32]
+ add $xc0,$xc0,@K[2]
stp @x[12],@x[14],[$out,#48]
+ add $xd0,$xd0,@K[3]
add $out,$out,#64
b.eq .Ldone_neon
sub $len,$len,#64
cmp $len,#64
- b.lo .Less_than_128
-
- ld1.8 {$T0-$T3},[$inp],#64
- eor $A0,$A0,$T0
- eor $B0,$B0,$T1
- eor $C0,$C0,$T2
- eor $D0,$D0,$T3
- st1.8 {$A0-$D0},[$out],#64
+ b.lo .Last_neon
+
+ ld1.8 {$xt0-$xt3},[$inp],#64
+ eor $xa0,$xa0,$xt0
+ eor $xb0,$xb0,$xt1
+ eor $xc0,$xc0,$xt2
+ eor $xd0,$xd0,$xt3
+ st1.8 {$xa0-$xd0},[$out],#64
b.eq .Ldone_neon
+
+ add $xa0,$xa1,@K[0]
+ add $xb0,$xb1,@K[1]
sub $len,$len,#64
+ add $xc0,$xc1,@K[2]
cmp $len,#64
- b.lo .Less_than_192
-
- ld1.8 {$T0-$T3},[$inp],#64
- eor $A1,$A1,$T0
- eor $B1,$B1,$T1
- eor $C1,$C1,$T2
- eor $D1,$D1,$T3
- st1.8 {$A1-$D1},[$out],#64
+ add $xd0,$xd1,@K[3]
+ b.lo .Last_neon
+
+ ld1.8 {$xt0-$xt3},[$inp],#64
+ eor $xa1,$xa0,$xt0
+ eor $xb1,$xb0,$xt1
+ eor $xc1,$xc0,$xt2
+ eor $xd1,$xd0,$xt3
+ st1.8 {$xa1-$xd1},[$out],#64
b.eq .Ldone_neon
- sub $len,$len,#64
- st1.8 {$A2-$D2},[sp]
- b .Last_neon
+ add $xa0,$xa2,@K[0]
+ add $xb0,$xb2,@K[1]
+ sub $len,$len,#64
+ add $xc0,$xc2,@K[2]
+ cmp $len,#64
+ add $xd0,$xd2,@K[3]
+ b.lo .Last_neon
+
+ ld1.8 {$xt0-$xt3},[$inp],#64
+ eor $xa2,$xa0,$xt0
+ eor $xb2,$xb0,$xt1
+ eor $xc2,$xc0,$xt2
+ eor $xd2,$xd0,$xt3
+ st1.8 {$xa2-$xd2},[$out],#64
+ b.eq .Ldone_neon
-.Less_than_128:
- st1.8 {$A0-$D0},[sp]
- b .Last_neon
-.Less_than_192:
- st1.8 {$A1-$D1},[sp]
- b .Last_neon
+ add $xa0,$xa3,@K[0]
+ add $xb0,$xb3,@K[1]
+ add $xc0,$xc3,@K[2]
+ add $xd0,$xd3,@K[3]
+ sub $len,$len,#64
-.align 4
.Last_neon:
+ st1.8 {$xa0-$xd0},[sp]
+
sub $out,$out,#1
add $inp,$inp,$len
add $out,$out,$len
@@ -695,9 +804,41 @@ $code.=<<___;
.size ChaCha20_neon,.-ChaCha20_neon
___
{
+my @K = map("v$_.4s",(0..6));
my ($T0,$T1,$T2,$T3,$T4,$T5)=@K;
my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2,
- $A3,$B3,$C3,$D3,$A4,$B4,$C4,$D4,$A5,$B5,$C5,$D5) = map("v$_.4s",(0..23));
+ $A3,$B3,$C3,$D3,$A4,$B4,$C4,$D4,$A5,$B5,$C5,$D5) = map("v$_.4s",(8..31));
+my $rot24 = @K[6];
+my $ONE = "v7.4s";
+
+sub NEONROUND {
+my $odd = pop;
+my ($a,$b,$c,$d,$t)=@_;
+
+ (
+ "&add ('$a','$a','$b')",
+ "&eor ('$d','$d','$a')",
+ "&rev32_16 ('$d','$d')", # vrot ($d,16)
+
+ "&add ('$c','$c','$d')",
+ "&eor ('$t','$b','$c')",
+ "&ushr ('$b','$t',20)",
+ "&sli ('$b','$t',12)",
+
+ "&add ('$a','$a','$b')",
+ "&eor ('$d','$d','$a')",
+ "&tbl ('$d','{$d}','$rot24')",
+
+ "&add ('$c','$c','$d')",
+ "&eor ('$t','$b','$c')",
+ "&ushr ('$b','$t',25)",
+ "&sli ('$b','$t',7)",
+
+ "&ext ('$c','$c','$c',8)",
+ "&ext ('$d','$d','$d',$odd?4:12)",
+ "&ext ('$b','$b','$b',$odd?12:4)"
+ );
+}
$code.=<<___;
.type ChaCha20_512_neon,%function
@@ -717,6 +858,7 @@ ChaCha20_512_neon:
.L512_or_more_neon:
sub sp,sp,#128+64
+ eor $ONE,$ONE,$ONE
ldp @d[0],@d[1],[@x[0]] // load sigma
ld1 {@K[0]},[@x[0]],#16
ldp @d[2],@d[3],[$key] // load key
@@ -724,8 +866,9 @@ ChaCha20_512_neon:
ld1 {@K[1],@K[2]},[$key]
ldp @d[6],@d[7],[$ctr] // load counter
ld1 {@K[3]},[$ctr]
- ld1 {$ONE},[@x[0]]
-#ifdef __ARMEB__
+ ld1 {$ONE}[0],[@x[0]]
+ add $key,@x[0],#16 // .Lrot24
+#ifdef __AARCH64EB__
rev64 @K[0],@K[0]
ror @d[2],@d[2],#32
ror @d[3],@d[3],#32
@@ -792,9 +935,10 @@ ChaCha20_512_neon:
mov $C4,@K[2]
stp @K[3],@K[4],[sp,#48] // off-load key block, variable part
mov $C5,@K[2]
- str @K[5],[sp,#80]
+ stp @K[5],@K[6],[sp,#80]
mov $ctr,#5
+ ld1 {$rot24},[$key]
subs $len,$len,#512
.Loop_upper_neon:
sub $ctr,$ctr,#1
@@ -867,7 +1011,7 @@ $code.=<<___;
add @x[14],@x[14],@x[15],lsl#32
ldp @x[13],@x[15],[$inp,#48]
add $inp,$inp,#64
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
rev @x[0],@x[0]
rev @x[2],@x[2]
rev @x[4],@x[4]
@@ -956,6 +1100,7 @@ $code.=<<___;
add.32 @x[2],@x[2],@d[1]
ldp @K[4],@K[5],[sp,#64]
add @x[3],@x[3],@d[1],lsr#32
+ ldr @K[6],[sp,#96]
add $A0,$A0,@K[0]
add.32 @x[4],@x[4],@d[2]
add $A1,$A1,@K[0]
@@ -1008,7 +1153,7 @@ $code.=<<___;
add $inp,$inp,#64
add $B5,$B5,@K[1]
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
rev @x[0],@x[0]
rev @x[2],@x[2]
rev @x[4],@x[4]
@@ -1086,26 +1231,26 @@ $code.=<<___;
b.hs .Loop_outer_512_neon
adds $len,$len,#512
- ushr $A0,$ONE,#2 // 4 -> 1
+ ushr $ONE,$ONE,#1 // 4 -> 2
- ldp d8,d9,[sp,#128+0] // meet ABI requirements
- ldp d10,d11,[sp,#128+16]
+ ldp d10,d11,[sp,#128+16] // meet ABI requirements
ldp d12,d13,[sp,#128+32]
ldp d14,d15,[sp,#128+48]
- stp @K[0],$ONE,[sp,#0] // wipe off-load area
- stp @K[0],$ONE,[sp,#32]
- stp @K[0],$ONE,[sp,#64]
+ stp @K[0],@K[0],[sp,#0] // wipe off-load area
+ stp @K[0],@K[0],[sp,#32]
+ stp @K[0],@K[0],[sp,#64]
b.eq .Ldone_512_neon
+ sub $key,$key,#16 // .Lone
cmp $len,#192
- sub @K[3],@K[3],$A0 // -= 1
- sub @K[4],@K[4],$A0
- sub @K[5],@K[5],$A0
add sp,sp,#128
+ sub @K[3],@K[3],$ONE // -= 2
+ ld1 {$CTR,$ROT24},[$key]
b.hs .Loop_outer_neon
+ ldp d8,d9,[sp,#0] // meet ABI requirements
eor @K[1],@K[1],@K[1]
eor @K[2],@K[2],@K[2]
eor @K[3],@K[3],@K[3]
@@ -1115,6 +1260,7 @@ $code.=<<___;
b .Loop_outer
.Ldone_512_neon:
+ ldp d8,d9,[sp,#128+0] // meet ABI requirements
ldp x19,x20,[x29,#16]
add sp,sp,#128+64
ldp x21,x22,[x29,#32]
@@ -1133,9 +1279,11 @@ foreach (split("\n",$code)) {
s/\`([^\`]*)\`/eval $1/geo;
(s/\b([a-z]+)\.32\b/$1/ and (s/x([0-9]+)/w$1/g or 1)) or
- (m/\b(eor|ext|mov)\b/ and (s/\.4s/\.16b/g or 1)) or
+ (m/\b(eor|ext|mov|tbl)\b/ and (s/\.4s/\.16b/g or 1)) or
(s/\b((?:ld|st)1)\.8\b/$1/ and (s/\.4s/\.16b/g or 1)) or
(m/\b(ld|st)[rp]\b/ and (s/v([0-9]+)\.4s/q$1/g or 1)) or
+ (m/\b(dup|ld1)\b/ and (s/\.4(s}?\[[0-3]\])/.$1/g or 1)) or
+ (s/\b(zip[12])\.64\b/$1/ and (s/\.4s/\.2d/g or 1)) or
(s/\brev32\.16\b/rev32/ and (s/\.4s/\.8h/g or 1));
#s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo;
diff --git a/crypto/chacha/asm/chacha-c64xplus.pl b/crypto/chacha/asm/chacha-c64xplus.pl
index 4bd18a4f8f95..a10f7c0aff3f 100755
--- a/crypto/chacha/asm/chacha-c64xplus.pl
+++ b/crypto/chacha/asm/chacha-c64xplus.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -24,8 +24,7 @@
# dependent on input length. This module on the other hand is free
# from such limitation.
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
($OUT,$INP,$LEN,$KEYB,$COUNTERA)=("A4","B4","A6","B6","A8");
($KEYA,$COUNTERB,$STEP)=("A7","B7","A3");
diff --git a/crypto/chacha/asm/chacha-ia64.pl b/crypto/chacha/asm/chacha-ia64.pl
new file mode 100644
index 000000000000..b13d97285575
--- /dev/null
+++ b/crypto/chacha/asm/chacha-ia64.pl
@@ -0,0 +1,291 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov, @dot-asm, initially for use with OpenSSL.
+# ====================================================================
+#
+# ChaCha20 for Itanium.
+#
+# March 2019
+#
+# Itanium 9xxx, which has pair of shifters, manages to process one byte
+# in 9.3 cycles. This aligns perfectly with theoretical estimate.
+# On the other hand, pre-9000 CPU has single shifter and each extr/dep
+# pairs below takes additional cycle. Then final input->xor->output
+# pass runs slower than expected... Overall result is 15.6 cpb, two
+# cycles more than theoretical estimate.
+
+$output = pop and open STDOUT, ">$output";
+
+my @k = map("r$_",(16..31));
+my @x = map("r$_",(38..53));
+my @y = map("r$_",(8..11));
+my @z = map("r$_",(15,35..37));
+my ($out,$inp,$len,$key,$counter) = map("r$_",(32..36));
+
+$code.=<<___;
+#if defined(_HPUX_SOURCE)
+# if !defined(_LP64)
+# define ADDP addp4
+# else
+# define ADDP add
+# endif
+#else
+# define ADDP add
+#endif
+
+.text
+
+.global ChaCha20_ctr32#
+.proc ChaCha20_ctr32#
+.align 32
+ChaCha20_ctr32:
+ .prologue
+ .save ar.pfs,r2
+{ .mmi; alloc r2=ar.pfs,5,17,0,0
+ ADDP @k[11]=4,$key
+ .save ar.lc,r3
+ mov r3=ar.lc }
+{ .mmi; ADDP $key=0,$key
+ ADDP $counter=0,$counter
+ .save pr,r14
+ mov r14=pr };;
+
+ .body
+{ .mlx; ld4 @k[4]=[$key],8
+ movl @k[0]=0x61707865 }
+{ .mlx; ld4 @k[5]=[@k[11]],8
+ movl @k[1]=0x3320646e };;
+{ .mlx; ld4 @k[6]=[$key],8
+ movl @k[2]=0x79622d32 }
+{ .mlx; ld4 @k[7]=[@k[11]],8
+ movl @k[3]=0x6b206574 };;
+{ .mmi; ld4 @k[8]=[$key],8
+ ld4 @k[9]=[@k[11]],8
+ add @k[15]=4,$counter };;
+{ .mmi; ld4 @k[10]=[$key]
+ ld4 @k[11]=[@k[11]]
+ mov @x[0]=@k[0] };;
+{ .mmi; ld4 @k[12]=[$counter],8
+ ld4 @k[13]=[@k[15]],8
+ mov @x[1]=@k[1] };;
+{ .mmi; ld4 @k[14]=[$counter]
+ ld4 @k[15]=[@k[15]]
+ mov @x[2]=@k[2] }
+{ .mmi; mov @x[3]=@k[3]
+ mov @x[4]=@k[4]
+ mov @x[5]=@k[5] };;
+{ .mmi; mov @x[6]=@k[6]
+ mov @x[7]=@k[7]
+ mov @x[8]=@k[8] }
+{ .mmi; mov @x[9]=@k[9]
+ mov @x[10]=@k[10]
+ mov @x[11]=@k[11] }
+{ .mmi; mov @x[12]=@k[12]
+ mov @x[13]=@k[13]
+ mov @x[14]=@k[14] };;
+
+.Loop_outer:
+{ .mii; mov @x[15]=@k[15]
+ mov ar.lc=9
+ mov ar.ec=1 }
+{ .mmb; cmp.geu p6,p0=64,$len
+ sub @z[1]=64,$len
+ brp.loop.imp .Loop_top,.Loop_end-16 };;
+
+.Loop_top:
+___
+sub ROUND {
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+
+$code.=<<___;
+{ .mmi; add @x[$a0]=@x[$a0],@x[$b0]
+ add @x[$a1]=@x[$a1],@x[$b1]
+ add @x[$a2]=@x[$a2],@x[$b2] };;
+{ .mmi; add @x[$a3]=@x[$a3],@x[$b3]
+ xor @x[$d0]=@x[$d0],@x[$a0]
+ xor @x[$d1]=@x[$d1],@x[$a1] };;
+{ .mmi; xor @x[$d2]=@x[$d2],@x[$a2]
+ xor @x[$d3]=@x[$d3],@x[$a3]
+ extr.u @y[0]=@x[$d0],16,16 };;
+{ .mii; extr.u @y[1]=@x[$d1],16,16
+ dep @x[$d0]=@x[$d0],@y[0],16,16 };;
+{ .mii; add @x[$c0]=@x[$c0],@x[$d0]
+ extr.u @y[2]=@x[$d2],16,16
+ dep @x[$d1]=@x[$d1],@y[1],16,16 };;
+{ .mii; add @x[$c1]=@x[$c1],@x[$d1]
+ xor @x[$b0]=@x[$b0],@x[$c0]
+ extr.u @y[3]=@x[$d3],16,16 };;
+{ .mii; xor @x[$b1]=@x[$b1],@x[$c1]
+ dep @x[$d2]=@x[$d2],@y[2],16,16
+ dep @x[$d3]=@x[$d3],@y[3],16,16 };;
+{ .mmi; add @x[$c2]=@x[$c2],@x[$d2]
+ add @x[$c3]=@x[$c3],@x[$d3]
+ extr.u @y[0]=@x[$b0],20,12 };;
+{ .mmi; xor @x[$b2]=@x[$b2],@x[$c2]
+ xor @x[$b3]=@x[$b3],@x[$c3]
+ dep.z @x[$b0]=@x[$b0],12,20 };;
+{ .mii; or @x[$b0]=@x[$b0],@y[0]
+ extr.u @y[1]=@x[$b1],20,12
+ dep.z @x[$b1]=@x[$b1],12,20 };;
+{ .mii; add @x[$a0]=@x[$a0],@x[$b0]
+ extr.u @y[2]=@x[$b2],20,12
+ extr.u @y[3]=@x[$b3],20,12 }
+{ .mii; or @x[$b1]=@x[$b1],@y[1]
+ dep.z @x[$b2]=@x[$b2],12,20
+ dep.z @x[$b3]=@x[$b3],12,20 };;
+{ .mmi; or @x[$b2]=@x[$b2],@y[2]
+ or @x[$b3]=@x[$b3],@y[3]
+ add @x[$a1]=@x[$a1],@x[$b1] };;
+{ .mmi; add @x[$a2]=@x[$a2],@x[$b2]
+ add @x[$a3]=@x[$a3],@x[$b3]
+ xor @x[$d0]=@x[$d0],@x[$a0] };;
+{ .mii; xor @x[$d1]=@x[$d1],@x[$a1]
+ extr.u @y[0]=@x[$d0],24,8
+ dep.z @x[$d0]=@x[$d0],8,24 };;
+{ .mii; or @x[$d0]=@x[$d0],@y[0]
+ extr.u @y[1]=@x[$d1],24,8
+ dep.z @x[$d1]=@x[$d1],8,24 };;
+{ .mmi; or @x[$d1]=@x[$d1],@y[1]
+ xor @x[$d2]=@x[$d2],@x[$a2]
+ xor @x[$d3]=@x[$d3],@x[$a3] };;
+{ .mii; add @x[$c0]=@x[$c0],@x[$d0]
+ extr.u @y[2]=@x[$d2],24,8
+ dep.z @x[$d2]=@x[$d2],8,24 };;
+{ .mii; xor @x[$b0]=@x[$b0],@x[$c0]
+ extr.u @y[3]=@x[$d3],24,8
+ dep.z @x[$d3]=@x[$d3],8,24 };;
+{ .mmi; or @x[$d2]=@x[$d2],@y[2]
+ or @x[$d3]=@x[$d3],@y[3]
+ extr.u @y[0]=@x[$b0],25,7 };;
+{ .mmi; add @x[$c1]=@x[$c1],@x[$d1]
+ add @x[$c2]=@x[$c2],@x[$d2]
+ dep.z @x[$b0]=@x[$b0],7,25 };;
+{ .mmi; xor @x[$b1]=@x[$b1],@x[$c1]
+ xor @x[$b2]=@x[$b2],@x[$c2]
+ add @x[$c3]=@x[$c3],@x[$d3] };;
+{ .mii; xor @x[$b3]=@x[$b3],@x[$c3]
+ extr.u @y[1]=@x[$b1],25,7
+ dep.z @x[$b1]=@x[$b1],7,25 };;
+{ .mii; or @x[$b0]=@x[$b0],@y[0]
+ extr.u @y[2]=@x[$b2],25,7
+ dep.z @x[$b2]=@x[$b2],7,25 };;
+{ .mii; or @x[$b1]=@x[$b1],@y[1]
+ extr.u @y[3]=@x[$b3],25,7
+ dep.z @x[$b3]=@x[$b3],7,25 };;
+___
+$code.=<<___ if ($d0 == 12);
+{ .mmi; or @x[$b2]=@x[$b2],@y[2]
+ or @x[$b3]=@x[$b3],@y[3]
+ mov @z[0]=-1 };;
+___
+$code.=<<___ if ($d0 == 15);
+{ .mmb; or @x[$b2]=@x[$b2],@y[2]
+ or @x[$b3]=@x[$b3],@y[3]
+ br.ctop.sptk .Loop_top };;
+___
+}
+ &ROUND(0, 4, 8, 12);
+ &ROUND(0, 5, 10, 15);
+$code.=<<___;
+.Loop_end:
+
+{ .mmi; add @x[0]=@x[0],@k[0]
+ add @x[1]=@x[1],@k[1]
+(p6) shr.u @z[0]=@z[0],@z[1] }
+{ .mmb; add @x[2]=@x[2],@k[2]
+ add @x[3]=@x[3],@k[3]
+ clrrrb.pr };;
+{ .mmi; add @x[4]=@x[4],@k[4]
+ add @x[5]=@x[5],@k[5]
+ add @x[6]=@x[6],@k[6] }
+{ .mmi; add @x[7]=@x[7],@k[7]
+ add @x[8]=@x[8],@k[8]
+ add @x[9]=@x[9],@k[9] }
+{ .mmi; add @x[10]=@x[10],@k[10]
+ add @x[11]=@x[11],@k[11]
+ add @x[12]=@x[12],@k[12] }
+{ .mmi; add @x[13]=@x[13],@k[13]
+ add @x[14]=@x[14],@k[14]
+ add @x[15]=@x[15],@k[15] }
+{ .mmi; add @k[12]=1,@k[12] // next counter
+ mov pr=@z[0],0x1ffff };;
+
+//////////////////////////////////////////////////////////////////
+// Each predicate bit corresponds to byte to be processed. Note
+// that p0 is wired to 1, but it works out, because there always
+// is at least one byte to process...
+{ .mmi; (p0) ld1 @z[0]=[$inp],1
+ shr.u @y[1]=@x[0],8 };;
+{ .mmi; (p1) ld1 @z[1]=[$inp],1
+ (p2) shr.u @y[2]=@x[0],16 };;
+{ .mmi; (p2) ld1 @z[2]=[$inp],1
+ (p0) xor @z[0]=@z[0],@x[0]
+ (p3) shr.u @y[3]=@x[0],24 };;
+___
+for(my $i0=0; $i0<60; $i0+=4) {
+my ($i1, $i2, $i3, $i4, $i5, $i6, $i7) = map($i0+$_,(1..7));
+my $k = $i0/4+1;
+
+$code.=<<___;
+{ .mmi; (p$i3) ld1 @z[3]=[$inp],1
+ (p$i0) st1 [$out]=@z[0],1
+ (p$i1) xor @z[1]=@z[1],@y[1] };;
+{ .mmi; (p$i4) ld1 @z[0]=[$inp],1
+ (p$i5) shr.u @y[1]=@x[$k],8 }
+{ .mmi; (p$i1) st1 [$out]=@z[1],1
+ (p$i2) xor @z[2]=@z[2],@y[2]
+ (p1) mov @x[$k-1]=@k[$k-1] };;
+{ .mfi; (p$i5) ld1 @z[1]=[$inp],1
+ (p$i6) shr.u @y[2]=@x[$k],16 }
+{ .mfi; (p$i2) st1 [$out]=@z[2],1
+ (p$i3) xor @z[3]=@z[3],@y[3] };;
+{ .mfi; (p$i6) ld1 @z[2]=[$inp],1
+ (p$i7) shr.u @y[3]=@x[$k],24 }
+___
+$code.=<<___ if ($i0==0); # p1,p2 are available for reuse in first round
+{ .mmi; (p$i3) st1 [$out]=@z[3],1
+ (p$i4) xor @z[0]=@z[0],@x[$k]
+ cmp.ltu p1,p2=64,$len };;
+___
+$code.=<<___ if ($i0>0);
+{ .mfi; (p$i3) st1 [$out]=@z[3],1
+ (p$i4) xor @z[0]=@z[0],@x[$k] };;
+___
+}
+$code.=<<___;
+{ .mmi; (p63) ld1 @z[3]=[$inp],1
+ (p60) st1 [$out]=@z[0],1
+ (p61) xor @z[1]=@z[1],@y[1] };;
+{ .mmi; (p61) st1 [$out]=@z[1],1
+ (p62) xor @z[2]=@z[2],@y[2] };;
+{ .mmi; (p62) st1 [$out]=@z[2],1
+ (p63) xor @z[3]=@z[3],@y[3]
+ (p2) mov ar.lc=r3 };;
+{ .mib; (p63) st1 [$out]=@z[3],1
+ (p1) add $len=-64,$len
+(p1) br.dptk.many .Loop_outer };;
+
+{ .mmi; mov @k[4]=0 // wipe key material
+ mov @k[5]=0
+ mov @k[6]=0 }
+{ .mmi; mov @k[7]=0
+ mov @k[8]=0
+ mov @k[9]=0 }
+{ .mmi; mov @k[10]=0
+ mov @k[11]=0
+ mov @k[12]=0 }
+{ .mmi; mov @k[13]=0
+ mov @k[14]=0
+ mov @k[15]=0 }
+{ .mib; mov pr=r14,0x1ffff
+ br.ret.sptk.many b0 };;
+.endp ChaCha20_ctr32#
+stringz "ChaCha20 for IA64, CRYPTOGAMS by \@dot-asm"
+___
+
+print $code;
+close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/chacha/asm/chacha-ppc.pl b/crypto/chacha/asm/chacha-ppc.pl
index 3073deac17ee..60982dddb211 100755
--- a/crypto/chacha/asm/chacha-ppc.pl
+++ b/crypto/chacha/asm/chacha-ppc.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -44,7 +44,10 @@
# instructions, which is why switch to vector-only code pays
# off that much;
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /64/) {
$SIZE_T =8;
@@ -69,7 +72,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
+open STDOUT,"| $^X $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
$LOCALS=6*$SIZE_T;
$FRAME=$LOCALS+64+18*$SIZE_T; # 64 is for local variables
diff --git a/crypto/chacha/asm/chacha-s390x.pl b/crypto/chacha/asm/chacha-s390x.pl
index dd66a9c60309..9e29ebccb596 100755
--- a/crypto/chacha/asm/chacha-s390x.pl
+++ b/crypto/chacha/asm/chacha-s390x.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -20,41 +20,53 @@
#
# 3 times faster than compiler-generated code.
-$flavour = shift;
+#
+# August 2018
+#
+# Add vx code path: 4x"vertical".
+#
+# Copyright IBM Corp. 2018
+# Author: Patrick Steuer <patrick.steuer@de.ibm.com>
+
+#
+# February 2019
+#
+# Add 6x"horizontal" VX implementation. It's ~25% faster than IBM's
+# 4x"vertical" submission [on z13] and >3 faster than scalar code.
+# But to harness overheads revert to transliteration of VSX code path
+# from chacha-ppc module, which is also 4x"vertical", to handle inputs
+# not longer than 256 bytes.
+
+use strict;
+use FindBin qw($Bin);
+use lib "$Bin/../..";
+use perlasm::s390x qw(:DEFAULT :VX :EI AUTOLOAD LABEL INCLUDE);
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+
+my ($z,$SIZE_T);
if ($flavour =~ /3[12]/) {
+ $z=0; # S/390 ABI
$SIZE_T=4;
- $g="";
} else {
+ $z=1; # zSeries ABI
$SIZE_T=8;
- $g="g";
-}
-
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
-
-sub AUTOLOAD() # thunk [simplified] x86-style perlasm
-{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://;
- $code .= "\t$opcode\t".join(',',@_)."\n";
}
my $sp="%r15";
-
my $stdframe=16*$SIZE_T+4*8;
-my $frame=$stdframe+4*20;
-
-my ($out,$inp,$len,$key,$counter)=map("%r$_",(2..6));
+sub ROUND {
my @x=map("%r$_",(0..7,"x","x","x","x",(10..13)));
my @t=map("%r$_",(8,9));
-
-sub ROUND {
my ($a0,$b0,$c0,$d0)=@_;
my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
-my ($xc,$xc_)=map("\"$_\"",@t);
-my @x=map("\"$_\"",@x);
+my ($xc,$xc_)=map("$_",@t);
# Consider order in which variables are addressed by their
# index:
@@ -78,249 +90,967 @@ my @x=map("\"$_\"",@x);
# 'c' stores and loads in the middle, but none in the beginning
# or end.
- (
- "&alr (@x[$a0],@x[$b0])", # Q1
- "&alr (@x[$a1],@x[$b1])", # Q2
- "&xr (@x[$d0],@x[$a0])",
- "&xr (@x[$d1],@x[$a1])",
- "&rll (@x[$d0],@x[$d0],16)",
- "&rll (@x[$d1],@x[$d1],16)",
-
- "&alr ($xc,@x[$d0])",
- "&alr ($xc_,@x[$d1])",
- "&xr (@x[$b0],$xc)",
- "&xr (@x[$b1],$xc_)",
- "&rll (@x[$b0],@x[$b0],12)",
- "&rll (@x[$b1],@x[$b1],12)",
-
- "&alr (@x[$a0],@x[$b0])",
- "&alr (@x[$a1],@x[$b1])",
- "&xr (@x[$d0],@x[$a0])",
- "&xr (@x[$d1],@x[$a1])",
- "&rll (@x[$d0],@x[$d0],8)",
- "&rll (@x[$d1],@x[$d1],8)",
-
- "&alr ($xc,@x[$d0])",
- "&alr ($xc_,@x[$d1])",
- "&xr (@x[$b0],$xc)",
- "&xr (@x[$b1],$xc_)",
- "&rll (@x[$b0],@x[$b0],7)",
- "&rll (@x[$b1],@x[$b1],7)",
-
- "&stm ($xc,$xc_,'$stdframe+4*8+4*$c0($sp)')", # reload pair of 'c's
- "&lm ($xc,$xc_,'$stdframe+4*8+4*$c2($sp)')",
-
- "&alr (@x[$a2],@x[$b2])", # Q3
- "&alr (@x[$a3],@x[$b3])", # Q4
- "&xr (@x[$d2],@x[$a2])",
- "&xr (@x[$d3],@x[$a3])",
- "&rll (@x[$d2],@x[$d2],16)",
- "&rll (@x[$d3],@x[$d3],16)",
-
- "&alr ($xc,@x[$d2])",
- "&alr ($xc_,@x[$d3])",
- "&xr (@x[$b2],$xc)",
- "&xr (@x[$b3],$xc_)",
- "&rll (@x[$b2],@x[$b2],12)",
- "&rll (@x[$b3],@x[$b3],12)",
-
- "&alr (@x[$a2],@x[$b2])",
- "&alr (@x[$a3],@x[$b3])",
- "&xr (@x[$d2],@x[$a2])",
- "&xr (@x[$d3],@x[$a3])",
- "&rll (@x[$d2],@x[$d2],8)",
- "&rll (@x[$d3],@x[$d3],8)",
-
- "&alr ($xc,@x[$d2])",
- "&alr ($xc_,@x[$d3])",
- "&xr (@x[$b2],$xc)",
- "&xr (@x[$b3],$xc_)",
- "&rll (@x[$b2],@x[$b2],7)",
- "&rll (@x[$b3],@x[$b3],7)"
- );
+ alr (@x[$a0],@x[$b0]); # Q1
+ alr (@x[$a1],@x[$b1]); # Q2
+ xr (@x[$d0],@x[$a0]);
+ xr (@x[$d1],@x[$a1]);
+ rll (@x[$d0],@x[$d0],16);
+ rll (@x[$d1],@x[$d1],16);
+
+ alr ($xc,@x[$d0]);
+ alr ($xc_,@x[$d1]);
+ xr (@x[$b0],$xc);
+ xr (@x[$b1],$xc_);
+ rll (@x[$b0],@x[$b0],12);
+ rll (@x[$b1],@x[$b1],12);
+
+ alr (@x[$a0],@x[$b0]);
+ alr (@x[$a1],@x[$b1]);
+ xr (@x[$d0],@x[$a0]);
+ xr (@x[$d1],@x[$a1]);
+ rll (@x[$d0],@x[$d0],8);
+ rll (@x[$d1],@x[$d1],8);
+
+ alr ($xc,@x[$d0]);
+ alr ($xc_,@x[$d1]);
+ xr (@x[$b0],$xc);
+ xr (@x[$b1],$xc_);
+ rll (@x[$b0],@x[$b0],7);
+ rll (@x[$b1],@x[$b1],7);
+
+ stm ($xc,$xc_,"$stdframe+4*8+4*$c0($sp)"); # reload pair of 'c's
+ lm ($xc,$xc_,"$stdframe+4*8+4*$c2($sp)");
+
+ alr (@x[$a2],@x[$b2]); # Q3
+ alr (@x[$a3],@x[$b3]); # Q4
+ xr (@x[$d2],@x[$a2]);
+ xr (@x[$d3],@x[$a3]);
+ rll (@x[$d2],@x[$d2],16);
+ rll (@x[$d3],@x[$d3],16);
+
+ alr ($xc,@x[$d2]);
+ alr ($xc_,@x[$d3]);
+ xr (@x[$b2],$xc);
+ xr (@x[$b3],$xc_);
+ rll (@x[$b2],@x[$b2],12);
+ rll (@x[$b3],@x[$b3],12);
+
+ alr (@x[$a2],@x[$b2]);
+ alr (@x[$a3],@x[$b3]);
+ xr (@x[$d2],@x[$a2]);
+ xr (@x[$d3],@x[$a3]);
+ rll (@x[$d2],@x[$d2],8);
+ rll (@x[$d3],@x[$d3],8);
+
+ alr ($xc,@x[$d2]);
+ alr ($xc_,@x[$d3]);
+ xr (@x[$b2],$xc);
+ xr (@x[$b3],$xc_);
+ rll (@x[$b2],@x[$b2],7);
+ rll (@x[$b3],@x[$b3],7);
+}
+
+sub VX_lane_ROUND {
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+my @x=map("%v$_",(0..15));
+
+ vaf (@x[$a0],@x[$a0],@x[$b0]); # Q1
+ vx (@x[$d0],@x[$d0],@x[$a0]);
+ verllf (@x[$d0],@x[$d0],16);
+ vaf (@x[$a1],@x[$a1],@x[$b1]); # Q2
+ vx (@x[$d1],@x[$d1],@x[$a1]);
+ verllf (@x[$d1],@x[$d1],16);
+ vaf (@x[$a2],@x[$a2],@x[$b2]); # Q3
+ vx (@x[$d2],@x[$d2],@x[$a2]);
+ verllf (@x[$d2],@x[$d2],16);
+ vaf (@x[$a3],@x[$a3],@x[$b3]); # Q4
+ vx (@x[$d3],@x[$d3],@x[$a3]);
+ verllf (@x[$d3],@x[$d3],16);
+
+ vaf (@x[$c0],@x[$c0],@x[$d0]);
+ vx (@x[$b0],@x[$b0],@x[$c0]);
+ verllf (@x[$b0],@x[$b0],12);
+ vaf (@x[$c1],@x[$c1],@x[$d1]);
+ vx (@x[$b1],@x[$b1],@x[$c1]);
+ verllf (@x[$b1],@x[$b1],12);
+ vaf (@x[$c2],@x[$c2],@x[$d2]);
+ vx (@x[$b2],@x[$b2],@x[$c2]);
+ verllf (@x[$b2],@x[$b2],12);
+ vaf (@x[$c3],@x[$c3],@x[$d3]);
+ vx (@x[$b3],@x[$b3],@x[$c3]);
+ verllf (@x[$b3],@x[$b3],12);
+
+ vaf (@x[$a0],@x[$a0],@x[$b0]);
+ vx (@x[$d0],@x[$d0],@x[$a0]);
+ verllf (@x[$d0],@x[$d0],8);
+ vaf (@x[$a1],@x[$a1],@x[$b1]);
+ vx (@x[$d1],@x[$d1],@x[$a1]);
+ verllf (@x[$d1],@x[$d1],8);
+ vaf (@x[$a2],@x[$a2],@x[$b2]);
+ vx (@x[$d2],@x[$d2],@x[$a2]);
+ verllf (@x[$d2],@x[$d2],8);
+ vaf (@x[$a3],@x[$a3],@x[$b3]);
+ vx (@x[$d3],@x[$d3],@x[$a3]);
+ verllf (@x[$d3],@x[$d3],8);
+
+ vaf (@x[$c0],@x[$c0],@x[$d0]);
+ vx (@x[$b0],@x[$b0],@x[$c0]);
+ verllf (@x[$b0],@x[$b0],7);
+ vaf (@x[$c1],@x[$c1],@x[$d1]);
+ vx (@x[$b1],@x[$b1],@x[$c1]);
+ verllf (@x[$b1],@x[$b1],7);
+ vaf (@x[$c2],@x[$c2],@x[$d2]);
+ vx (@x[$b2],@x[$b2],@x[$c2]);
+ verllf (@x[$b2],@x[$b2],7);
+ vaf (@x[$c3],@x[$c3],@x[$d3]);
+ vx (@x[$b3],@x[$b3],@x[$c3]);
+ verllf (@x[$b3],@x[$b3],7);
+}
+
+sub VX_ROUND {
+my @a=@_[0..5];
+my @b=@_[6..11];
+my @c=@_[12..17];
+my @d=@_[18..23];
+my $odd=@_[24];
+
+ vaf (@a[$_],@a[$_],@b[$_]) for (0..5);
+ vx (@d[$_],@d[$_],@a[$_]) for (0..5);
+ verllf (@d[$_],@d[$_],16) for (0..5);
+
+ vaf (@c[$_],@c[$_],@d[$_]) for (0..5);
+ vx (@b[$_],@b[$_],@c[$_]) for (0..5);
+ verllf (@b[$_],@b[$_],12) for (0..5);
+
+ vaf (@a[$_],@a[$_],@b[$_]) for (0..5);
+ vx (@d[$_],@d[$_],@a[$_]) for (0..5);
+ verllf (@d[$_],@d[$_],8) for (0..5);
+
+ vaf (@c[$_],@c[$_],@d[$_]) for (0..5);
+ vx (@b[$_],@b[$_],@c[$_]) for (0..5);
+ verllf (@b[$_],@b[$_],7) for (0..5);
+
+ vsldb (@c[$_],@c[$_],@c[$_],8) for (0..5);
+ vsldb (@b[$_],@b[$_],@b[$_],$odd?12:4) for (0..5);
+ vsldb (@d[$_],@d[$_],@d[$_],$odd?4:12) for (0..5);
+}
+
+PERLASM_BEGIN($output);
+
+INCLUDE ("s390x_arch.h");
+TEXT ();
+
+################
+# void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp, size_t len,
+# const unsigned int key[8], const unsigned int counter[4])
+my ($out,$inp,$len,$key,$counter)=map("%r$_",(2..6));
+{
+my $frame=$stdframe+4*20;
+my @x=map("%r$_",(0..7,"x","x","x","x",(10..13)));
+my @t=map("%r$_",(8,9));
+
+GLOBL ("ChaCha20_ctr32");
+TYPE ("ChaCha20_ctr32","\@function");
+ALIGN (32);
+LABEL ("ChaCha20_ctr32");
+ larl ("%r1","OPENSSL_s390xcap_P");
+
+ lghi ("%r0",64);
+&{$z? \&ltgr:\&ltr} ($len,$len); # len==0?
+ bzr ("%r14");
+ lg ("%r1","S390X_STFLE+16(%r1)");
+&{$z? \&clgr:\&clr} ($len,"%r0");
+ jle (".Lshort");
+
+ tmhh ("%r1",0x4000); # check for vx bit
+ jnz (".LChaCha20_ctr32_vx");
+
+LABEL (".Lshort");
+&{$z? \&aghi:\&ahi} ($len,-64);
+&{$z? \&lghi:\&lhi} ("%r1",-$frame);
+&{$z? \&stmg:\&stm} ("%r6","%r15","6*$SIZE_T($sp)");
+&{$z? \&slgr:\&slr} ($out,$inp); # difference
+ la ($len,"0($inp,$len)"); # end of input minus 64
+ larl ("%r7",".Lsigma");
+ lgr ("%r0",$sp);
+ la ($sp,"0(%r1,$sp)");
+&{$z? \&stg:\&st} ("%r0","0($sp)");
+
+ lmg ("%r8","%r11","0($key)"); # load key
+ lmg ("%r12","%r13","0($counter)"); # load counter
+ lmg ("%r6","%r7","0(%r7)"); # load sigma constant
+
+ la ("%r14","0($inp)");
+&{$z? \&stg:\&st} ($out,"$frame+3*$SIZE_T($sp)");
+&{$z? \&stg:\&st} ($len,"$frame+4*$SIZE_T($sp)");
+ stmg ("%r6","%r13","$stdframe($sp)");# copy key schedule to stack
+ srlg (@x[12],"%r12",32); # 32-bit counter value
+ j (".Loop_outer");
+
+ALIGN (16);
+LABEL (".Loop_outer");
+ lm (@x[0],@x[7],"$stdframe+4*0($sp)"); # load x[0]-x[7]
+ lm (@t[0],@t[1],"$stdframe+4*10($sp)"); # load x[10]-x[11]
+ lm (@x[13],@x[15],"$stdframe+4*13($sp)"); # load x[13]-x[15]
+ stm (@t[0],@t[1],"$stdframe+4*8+4*10($sp)");# offload x[10]-x[11]
+ lm (@t[0],@t[1],"$stdframe+4*8($sp)"); # load x[8]-x[9]
+ st (@x[12],"$stdframe+4*12($sp)"); # save counter
+&{$z? \&stg:\&st} ("%r14","$frame+2*$SIZE_T($sp)");# save input pointer
+ lhi ("%r14",10);
+ j (".Loop");
+
+ALIGN (4);
+LABEL (".Loop");
+ ROUND (0, 4, 8,12);
+ ROUND (0, 5,10,15);
+ brct ("%r14",".Loop");
+
+&{$z? \&lg:\&l} ("%r14","$frame+2*$SIZE_T($sp)");# pull input pointer
+ stm (@t[0],@t[1],"$stdframe+4*8+4*8($sp)"); # offload x[8]-x[9]
+&{$z? \&lmg:\&lm} (@t[0],@t[1],"$frame+3*$SIZE_T($sp)");
+
+ al (@x[0],"$stdframe+4*0($sp)"); # accumulate key schedule
+ al (@x[1],"$stdframe+4*1($sp)");
+ al (@x[2],"$stdframe+4*2($sp)");
+ al (@x[3],"$stdframe+4*3($sp)");
+ al (@x[4],"$stdframe+4*4($sp)");
+ al (@x[5],"$stdframe+4*5($sp)");
+ al (@x[6],"$stdframe+4*6($sp)");
+ al (@x[7],"$stdframe+4*7($sp)");
+ lrvr (@x[0],@x[0]);
+ lrvr (@x[1],@x[1]);
+ lrvr (@x[2],@x[2]);
+ lrvr (@x[3],@x[3]);
+ lrvr (@x[4],@x[4]);
+ lrvr (@x[5],@x[5]);
+ lrvr (@x[6],@x[6]);
+ lrvr (@x[7],@x[7]);
+ al (@x[12],"$stdframe+4*12($sp)");
+ al (@x[13],"$stdframe+4*13($sp)");
+ al (@x[14],"$stdframe+4*14($sp)");
+ al (@x[15],"$stdframe+4*15($sp)");
+ lrvr (@x[12],@x[12]);
+ lrvr (@x[13],@x[13]);
+ lrvr (@x[14],@x[14]);
+ lrvr (@x[15],@x[15]);
+
+ la (@t[0],"0(@t[0],%r14)"); # reconstruct output pointer
+&{$z? \&clgr:\&clr} ("%r14",@t[1]);
+ jh (".Ltail");
+
+ x (@x[0],"4*0(%r14)"); # xor with input
+ x (@x[1],"4*1(%r14)");
+ st (@x[0],"4*0(@t[0])"); # store output
+ x (@x[2],"4*2(%r14)");
+ st (@x[1],"4*1(@t[0])");
+ x (@x[3],"4*3(%r14)");
+ st (@x[2],"4*2(@t[0])");
+ x (@x[4],"4*4(%r14)");
+ st (@x[3],"4*3(@t[0])");
+ lm (@x[0],@x[3],"$stdframe+4*8+4*8($sp)"); # load x[8]-x[11]
+ x (@x[5],"4*5(%r14)");
+ st (@x[4],"4*4(@t[0])");
+ x (@x[6],"4*6(%r14)");
+ al (@x[0],"$stdframe+4*8($sp)");
+ st (@x[5],"4*5(@t[0])");
+ x (@x[7],"4*7(%r14)");
+ al (@x[1],"$stdframe+4*9($sp)");
+ st (@x[6],"4*6(@t[0])");
+ x (@x[12],"4*12(%r14)");
+ al (@x[2],"$stdframe+4*10($sp)");
+ st (@x[7],"4*7(@t[0])");
+ x (@x[13],"4*13(%r14)");
+ al (@x[3],"$stdframe+4*11($sp)");
+ st (@x[12],"4*12(@t[0])");
+ x (@x[14],"4*14(%r14)");
+ st (@x[13],"4*13(@t[0])");
+ x (@x[15],"4*15(%r14)");
+ st (@x[14],"4*14(@t[0])");
+ lrvr (@x[0],@x[0]);
+ st (@x[15],"4*15(@t[0])");
+ lrvr (@x[1],@x[1]);
+ lrvr (@x[2],@x[2]);
+ lrvr (@x[3],@x[3]);
+ lhi (@x[12],1);
+ x (@x[0],"4*8(%r14)");
+ al (@x[12],"$stdframe+4*12($sp)"); # increment counter
+ x (@x[1],"4*9(%r14)");
+ st (@x[0],"4*8(@t[0])");
+ x (@x[2],"4*10(%r14)");
+ st (@x[1],"4*9(@t[0])");
+ x (@x[3],"4*11(%r14)");
+ st (@x[2],"4*10(@t[0])");
+ st (@x[3],"4*11(@t[0])");
+
+&{$z? \&clgr:\&clr} ("%r14",@t[1]); # done yet?
+ la ("%r14","64(%r14)");
+ jl (".Loop_outer");
+
+LABEL (".Ldone");
+ xgr ("%r0","%r0");
+ xgr ("%r1","%r1");
+ xgr ("%r2","%r2");
+ xgr ("%r3","%r3");
+ stmg ("%r0","%r3","$stdframe+4*4($sp)"); # wipe key copy
+ stmg ("%r0","%r3","$stdframe+4*12($sp)");
+
+&{$z? \&lmg:\&lm} ("%r6","%r15","$frame+6*$SIZE_T($sp)");
+ br ("%r14");
+
+ALIGN (16);
+LABEL (".Ltail");
+ la (@t[1],"64($t[1])");
+ stm (@x[0],@x[7],"$stdframe+4*0($sp)");
+&{$z? \&slgr:\&slr} (@t[1],"%r14");
+ lm (@x[0],@x[3],"$stdframe+4*8+4*8($sp)");
+&{$z? \&lghi:\&lhi} (@x[6],0);
+ stm (@x[12],@x[15],"$stdframe+4*12($sp)");
+ al (@x[0],"$stdframe+4*8($sp)");
+ al (@x[1],"$stdframe+4*9($sp)");
+ al (@x[2],"$stdframe+4*10($sp)");
+ al (@x[3],"$stdframe+4*11($sp)");
+ lrvr (@x[0],@x[0]);
+ lrvr (@x[1],@x[1]);
+ lrvr (@x[2],@x[2]);
+ lrvr (@x[3],@x[3]);
+ stm (@x[0],@x[3],"$stdframe+4*8($sp)");
+
+LABEL (".Loop_tail");
+ llgc (@x[4],"0(@x[6],%r14)");
+ llgc (@x[5],"$stdframe(@x[6],$sp)");
+ xr (@x[5],@x[4]);
+ stc (@x[5],"0(@x[6],@t[0])");
+ la (@x[6],"1(@x[6])");
+ brct (@t[1],".Loop_tail");
+
+ j (".Ldone");
+SIZE ("ChaCha20_ctr32",".-ChaCha20_ctr32");
}
-$code.=<<___;
-.text
-
-.globl ChaCha20_ctr32
-.type ChaCha20_ctr32,\@function
-.align 32
-ChaCha20_ctr32:
- lt${g}r $len,$len # $len==0?
- bzr %r14
- a${g}hi $len,-64
- l${g}hi %r1,-$frame
- stm${g} %r6,%r15,`6*$SIZE_T`($sp)
- sl${g}r $out,$inp # difference
- la $len,0($inp,$len) # end of input minus 64
- larl %r7,.Lsigma
- lgr %r0,$sp
- la $sp,0(%r1,$sp)
- st${g} %r0,0($sp)
-
- lmg %r8,%r11,0($key) # load key
- lmg %r12,%r13,0($counter) # load counter
- lmg %r6,%r7,0(%r7) # load sigma constant
-
- la %r14,0($inp)
- st${g} $out,$frame+3*$SIZE_T($sp)
- st${g} $len,$frame+4*$SIZE_T($sp)
- stmg %r6,%r13,$stdframe($sp) # copy key schedule to stack
- srlg @x[12],%r12,32 # 32-bit counter value
- j .Loop_outer
-
-.align 16
-.Loop_outer:
- lm @x[0],@x[7],$stdframe+4*0($sp) # load x[0]-x[7]
- lm @t[0],@t[1],$stdframe+4*10($sp) # load x[10]-x[11]
- lm @x[13],@x[15],$stdframe+4*13($sp) # load x[13]-x[15]
- stm @t[0],@t[1],$stdframe+4*8+4*10($sp) # offload x[10]-x[11]
- lm @t[0],@t[1],$stdframe+4*8($sp) # load x[8]-x[9]
- st @x[12],$stdframe+4*12($sp) # save counter
- st${g} %r14,$frame+2*$SIZE_T($sp) # save input pointer
- lhi %r14,10
- j .Loop
-
-.align 4
-.Loop:
-___
- foreach (&ROUND(0, 4, 8,12)) { eval; }
- foreach (&ROUND(0, 5,10,15)) { eval; }
-$code.=<<___;
- brct %r14,.Loop
-
- l${g} %r14,$frame+2*$SIZE_T($sp) # pull input pointer
- stm @t[0],@t[1],$stdframe+4*8+4*8($sp) # offload x[8]-x[9]
- lm${g} @t[0],@t[1],$frame+3*$SIZE_T($sp)
-
- al @x[0],$stdframe+4*0($sp) # accumulate key schedule
- al @x[1],$stdframe+4*1($sp)
- al @x[2],$stdframe+4*2($sp)
- al @x[3],$stdframe+4*3($sp)
- al @x[4],$stdframe+4*4($sp)
- al @x[5],$stdframe+4*5($sp)
- al @x[6],$stdframe+4*6($sp)
- al @x[7],$stdframe+4*7($sp)
- lrvr @x[0],@x[0]
- lrvr @x[1],@x[1]
- lrvr @x[2],@x[2]
- lrvr @x[3],@x[3]
- lrvr @x[4],@x[4]
- lrvr @x[5],@x[5]
- lrvr @x[6],@x[6]
- lrvr @x[7],@x[7]
- al @x[12],$stdframe+4*12($sp)
- al @x[13],$stdframe+4*13($sp)
- al @x[14],$stdframe+4*14($sp)
- al @x[15],$stdframe+4*15($sp)
- lrvr @x[12],@x[12]
- lrvr @x[13],@x[13]
- lrvr @x[14],@x[14]
- lrvr @x[15],@x[15]
-
- la @t[0],0(@t[0],%r14) # reconstruct output pointer
- cl${g}r %r14,@t[1]
- jh .Ltail
-
- x @x[0],4*0(%r14) # xor with input
- x @x[1],4*1(%r14)
- st @x[0],4*0(@t[0]) # store output
- x @x[2],4*2(%r14)
- st @x[1],4*1(@t[0])
- x @x[3],4*3(%r14)
- st @x[2],4*2(@t[0])
- x @x[4],4*4(%r14)
- st @x[3],4*3(@t[0])
- lm @x[0],@x[3],$stdframe+4*8+4*8($sp) # load x[8]-x[11]
- x @x[5],4*5(%r14)
- st @x[4],4*4(@t[0])
- x @x[6],4*6(%r14)
- al @x[0],$stdframe+4*8($sp)
- st @x[5],4*5(@t[0])
- x @x[7],4*7(%r14)
- al @x[1],$stdframe+4*9($sp)
- st @x[6],4*6(@t[0])
- x @x[12],4*12(%r14)
- al @x[2],$stdframe+4*10($sp)
- st @x[7],4*7(@t[0])
- x @x[13],4*13(%r14)
- al @x[3],$stdframe+4*11($sp)
- st @x[12],4*12(@t[0])
- x @x[14],4*14(%r14)
- st @x[13],4*13(@t[0])
- x @x[15],4*15(%r14)
- st @x[14],4*14(@t[0])
- lrvr @x[0],@x[0]
- st @x[15],4*15(@t[0])
- lrvr @x[1],@x[1]
- lrvr @x[2],@x[2]
- lrvr @x[3],@x[3]
- lhi @x[12],1
- x @x[0],4*8(%r14)
- al @x[12],$stdframe+4*12($sp) # increment counter
- x @x[1],4*9(%r14)
- st @x[0],4*8(@t[0])
- x @x[2],4*10(%r14)
- st @x[1],4*9(@t[0])
- x @x[3],4*11(%r14)
- st @x[2],4*10(@t[0])
- st @x[3],4*11(@t[0])
-
- cl${g}r %r14,@t[1] # done yet?
- la %r14,64(%r14)
- jl .Loop_outer
-
-.Ldone:
- xgr %r0,%r0
- xgr %r1,%r1
- xgr %r2,%r2
- xgr %r3,%r3
- stmg %r0,%r3,$stdframe+4*4($sp) # wipe key copy
- stmg %r0,%r3,$stdframe+4*12($sp)
-
- lm${g} %r6,%r15,`$frame+6*$SIZE_T`($sp)
- br %r14
-
-.align 16
-.Ltail:
- la @t[1],64($t[1])
- stm @x[0],@x[7],$stdframe+4*0($sp)
- sl${g}r @t[1],%r14
- lm @x[0],@x[3],$stdframe+4*8+4*8($sp)
- l${g}hi @x[6],0
- stm @x[12],@x[15],$stdframe+4*12($sp)
- al @x[0],$stdframe+4*8($sp)
- al @x[1],$stdframe+4*9($sp)
- al @x[2],$stdframe+4*10($sp)
- al @x[3],$stdframe+4*11($sp)
- lrvr @x[0],@x[0]
- lrvr @x[1],@x[1]
- lrvr @x[2],@x[2]
- lrvr @x[3],@x[3]
- stm @x[0],@x[3],$stdframe+4*8($sp)
-
-.Loop_tail:
- llgc @x[4],0(@x[6],%r14)
- llgc @x[5],$stdframe(@x[6],$sp)
- xr @x[5],@x[4]
- stc @x[5],0(@x[6],@t[0])
- la @x[6],1(@x[6])
- brct @t[1],.Loop_tail
-
- j .Ldone
-.size ChaCha20_ctr32,.-ChaCha20_ctr32
-
-.align 32
-.Lsigma:
-.long 0x61707865,0x3320646e,0x79622d32,0x6b206574 # endian-neutral
-.asciz "ChaCha20 for s390x, CRYPTOGAMS by <appro\@openssl.org>"
-.align 4
-___
-
-foreach (split("\n",$code)) {
- s/\`([^\`]*)\`/eval $1/ge;
-
- print $_,"\n";
+########################################################################
+# 4x"vertical" layout minimizes amount of instructions, but pipeline
+# runs underutilized [because of vector instructions' high latency].
+# On the other hand minimum amount of data it takes to fully utilize
+# the pipeline is higher, so that effectively, short inputs would be
+# processed slower. Hence this code path targeting <=256 bytes lengths.
+#
+{
+my ($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3,
+ $xc0,$xc1,$xc2,$xc3, $xd0,$xd1,$xd2,$xd3)=map("%v$_",(0..15));
+my @K=map("%v$_",(16..19));
+my $CTR="%v26";
+my ($xt0,$xt1,$xt2,$xt3)=map("%v$_",(27..30));
+my $beperm="%v31";
+my ($x00,$x10,$x20,$x30)=(0,map("r$_",(8..10)));
+my $FRAME=$stdframe+4*16;
+
+ALIGN (32);
+LABEL ("ChaCha20_ctr32_4x");
+LABEL (".LChaCha20_ctr32_4x");
+&{$z? \&stmg:\&stm} ("%r6","%r7","6*$SIZE_T($sp)");
+if (!$z) {
+ std ("%f4","16*$SIZE_T+2*8($sp)");
+ std ("%f6","16*$SIZE_T+3*8($sp)");
}
-close STDOUT or die "error closing STDOUT: $!";
+&{$z? \&lghi:\&lhi} ("%r1",-$FRAME);
+ lgr ("%r0",$sp);
+ la ($sp,"0(%r1,$sp)");
+&{$z? \&stg:\&st} ("%r0","0($sp)"); # back-chain
+if ($z) {
+ std ("%f8","$stdframe+8*0($sp)");
+ std ("%f9","$stdframe+8*1($sp)");
+ std ("%f10","$stdframe+8*2($sp)");
+ std ("%f11","$stdframe+8*3($sp)");
+ std ("%f12","$stdframe+8*4($sp)");
+ std ("%f13","$stdframe+8*5($sp)");
+ std ("%f14","$stdframe+8*6($sp)");
+ std ("%f15","$stdframe+8*7($sp)");
+}
+ larl ("%r7",".Lsigma");
+ lhi ("%r0",10);
+ lhi ("%r1",0);
+
+ vl (@K[0],"0(%r7)"); # load sigma
+ vl (@K[1],"0($key)"); # load key
+ vl (@K[2],"16($key)");
+ vl (@K[3],"0($counter)"); # load counter
+
+ vl ($beperm,"0x40(%r7)");
+ vl ($xt1,"0x50(%r7)");
+ vrepf ($CTR,@K[3],0);
+ vlvgf (@K[3],"%r1",0); # clear @K[3].word[0]
+ vaf ($CTR,$CTR,$xt1);
+
+#LABEL (".Loop_outer_4x");
+ vlm ($xa0,$xa3,"0x60(%r7)"); # load [smashed] sigma
+
+ vrepf ($xb0,@K[1],0); # smash the key
+ vrepf ($xb1,@K[1],1);
+ vrepf ($xb2,@K[1],2);
+ vrepf ($xb3,@K[1],3);
+
+ vrepf ($xc0,@K[2],0);
+ vrepf ($xc1,@K[2],1);
+ vrepf ($xc2,@K[2],2);
+ vrepf ($xc3,@K[2],3);
+
+ vlr ($xd0,$CTR);
+ vrepf ($xd1,@K[3],1);
+ vrepf ($xd2,@K[3],2);
+ vrepf ($xd3,@K[3],3);
+
+LABEL (".Loop_4x");
+ VX_lane_ROUND(0, 4, 8,12);
+ VX_lane_ROUND(0, 5,10,15);
+ brct ("%r0",".Loop_4x");
+
+ vaf ($xd0,$xd0,$CTR);
+
+ vmrhf ($xt0,$xa0,$xa1); # transpose data
+ vmrhf ($xt1,$xa2,$xa3);
+ vmrlf ($xt2,$xa0,$xa1);
+ vmrlf ($xt3,$xa2,$xa3);
+ vpdi ($xa0,$xt0,$xt1,0b0000);
+ vpdi ($xa1,$xt0,$xt1,0b0101);
+ vpdi ($xa2,$xt2,$xt3,0b0000);
+ vpdi ($xa3,$xt2,$xt3,0b0101);
+
+ vmrhf ($xt0,$xb0,$xb1);
+ vmrhf ($xt1,$xb2,$xb3);
+ vmrlf ($xt2,$xb0,$xb1);
+ vmrlf ($xt3,$xb2,$xb3);
+ vpdi ($xb0,$xt0,$xt1,0b0000);
+ vpdi ($xb1,$xt0,$xt1,0b0101);
+ vpdi ($xb2,$xt2,$xt3,0b0000);
+ vpdi ($xb3,$xt2,$xt3,0b0101);
+
+ vmrhf ($xt0,$xc0,$xc1);
+ vmrhf ($xt1,$xc2,$xc3);
+ vmrlf ($xt2,$xc0,$xc1);
+ vmrlf ($xt3,$xc2,$xc3);
+ vpdi ($xc0,$xt0,$xt1,0b0000);
+ vpdi ($xc1,$xt0,$xt1,0b0101);
+ vpdi ($xc2,$xt2,$xt3,0b0000);
+ vpdi ($xc3,$xt2,$xt3,0b0101);
+
+ vmrhf ($xt0,$xd0,$xd1);
+ vmrhf ($xt1,$xd2,$xd3);
+ vmrlf ($xt2,$xd0,$xd1);
+ vmrlf ($xt3,$xd2,$xd3);
+ vpdi ($xd0,$xt0,$xt1,0b0000);
+ vpdi ($xd1,$xt0,$xt1,0b0101);
+ vpdi ($xd2,$xt2,$xt3,0b0000);
+ vpdi ($xd3,$xt2,$xt3,0b0101);
+
+ #vrepif ($xt0,4);
+ #vaf ($CTR,$CTR,$xt0); # next counter value
+
+ vaf ($xa0,$xa0,@K[0]);
+ vaf ($xb0,$xb0,@K[1]);
+ vaf ($xc0,$xc0,@K[2]);
+ vaf ($xd0,$xd0,@K[3]);
+
+ vperm ($xa0,$xa0,$xa0,$beperm);
+ vperm ($xb0,$xb0,$xb0,$beperm);
+ vperm ($xc0,$xc0,$xc0,$beperm);
+ vperm ($xd0,$xd0,$xd0,$beperm);
+
+ #&{$z? \&clgfi:\&clfi} ($len,0x40);
+ #jl (".Ltail_4x");
+
+ vlm ($xt0,$xt3,"0($inp)");
+
+ vx ($xt0,$xt0,$xa0);
+ vx ($xt1,$xt1,$xb0);
+ vx ($xt2,$xt2,$xc0);
+ vx ($xt3,$xt3,$xd0);
+
+ vstm ($xt0,$xt3,"0($out)");
+
+ la ($inp,"0x40($inp)");
+ la ($out,"0x40($out)");
+&{$z? \&aghi:\&ahi} ($len,-0x40);
+ #je (".Ldone_4x");
+
+ vaf ($xa0,$xa1,@K[0]);
+ vaf ($xb0,$xb1,@K[1]);
+ vaf ($xc0,$xc1,@K[2]);
+ vaf ($xd0,$xd1,@K[3]);
+
+ vperm ($xa0,$xa0,$xa0,$beperm);
+ vperm ($xb0,$xb0,$xb0,$beperm);
+ vperm ($xc0,$xc0,$xc0,$beperm);
+ vperm ($xd0,$xd0,$xd0,$beperm);
+
+&{$z? \&clgfi:\&clfi} ($len,0x40);
+ jl (".Ltail_4x");
+
+ vlm ($xt0,$xt3,"0($inp)");
+
+ vx ($xt0,$xt0,$xa0);
+ vx ($xt1,$xt1,$xb0);
+ vx ($xt2,$xt2,$xc0);
+ vx ($xt3,$xt3,$xd0);
+
+ vstm ($xt0,$xt3,"0($out)");
+
+ la ($inp,"0x40($inp)");
+ la ($out,"0x40($out)");
+&{$z? \&aghi:\&ahi} ($len,-0x40);
+ je (".Ldone_4x");
+
+ vaf ($xa0,$xa2,@K[0]);
+ vaf ($xb0,$xb2,@K[1]);
+ vaf ($xc0,$xc2,@K[2]);
+ vaf ($xd0,$xd2,@K[3]);
+
+ vperm ($xa0,$xa0,$xa0,$beperm);
+ vperm ($xb0,$xb0,$xb0,$beperm);
+ vperm ($xc0,$xc0,$xc0,$beperm);
+ vperm ($xd0,$xd0,$xd0,$beperm);
+
+&{$z? \&clgfi:\&clfi} ($len,0x40);
+ jl (".Ltail_4x");
+
+ vlm ($xt0,$xt3,"0($inp)");
+
+ vx ($xt0,$xt0,$xa0);
+ vx ($xt1,$xt1,$xb0);
+ vx ($xt2,$xt2,$xc0);
+ vx ($xt3,$xt3,$xd0);
+
+ vstm ($xt0,$xt3,"0($out)");
+
+ la ($inp,"0x40($inp)");
+ la ($out,"0x40($out)");
+&{$z? \&aghi:\&ahi} ($len,-0x40);
+ je (".Ldone_4x");
+
+ vaf ($xa0,$xa3,@K[0]);
+ vaf ($xb0,$xb3,@K[1]);
+ vaf ($xc0,$xc3,@K[2]);
+ vaf ($xd0,$xd3,@K[3]);
+
+ vperm ($xa0,$xa0,$xa0,$beperm);
+ vperm ($xb0,$xb0,$xb0,$beperm);
+ vperm ($xc0,$xc0,$xc0,$beperm);
+ vperm ($xd0,$xd0,$xd0,$beperm);
+
+&{$z? \&clgfi:\&clfi} ($len,0x40);
+ jl (".Ltail_4x");
+
+ vlm ($xt0,$xt3,"0($inp)");
+
+ vx ($xt0,$xt0,$xa0);
+ vx ($xt1,$xt1,$xb0);
+ vx ($xt2,$xt2,$xc0);
+ vx ($xt3,$xt3,$xd0);
+
+ vstm ($xt0,$xt3,"0($out)");
+
+ #la $inp,0x40($inp));
+ #la $out,0x40($out));
+ #lhi %r0,10);
+ #&{$z? \&aghi:\&ahi} $len,-0x40);
+ #jne .Loop_outer_4x);
+
+LABEL (".Ldone_4x");
+if (!$z) {
+ ld ("%f4","$FRAME+16*$SIZE_T+2*8($sp)");
+ ld ("%f6","$FRAME+16*$SIZE_T+3*8($sp)");
+} else {
+ ld ("%f8","$stdframe+8*0($sp)");
+ ld ("%f9","$stdframe+8*1($sp)");
+ ld ("%f10","$stdframe+8*2($sp)");
+ ld ("%f11","$stdframe+8*3($sp)");
+ ld ("%f12","$stdframe+8*4($sp)");
+ ld ("%f13","$stdframe+8*5($sp)");
+ ld ("%f14","$stdframe+8*6($sp)");
+ ld ("%f15","$stdframe+8*7($sp)");
+}
+&{$z? \&lmg:\&lm} ("%r6","%r7","$FRAME+6*$SIZE_T($sp)");
+ la ($sp,"$FRAME($sp)");
+ br ("%r14");
+
+ALIGN (16);
+LABEL (".Ltail_4x");
+if (!$z) {
+ vlr ($xt0,$xb0);
+ ld ("%f4","$FRAME+16*$SIZE_T+2*8($sp)");
+ ld ("%f6","$FRAME+16*$SIZE_T+3*8($sp)");
+
+ vst ($xa0,"$stdframe+0x00($sp)");
+ vst ($xt0,"$stdframe+0x10($sp)");
+ vst ($xc0,"$stdframe+0x20($sp)");
+ vst ($xd0,"$stdframe+0x30($sp)");
+} else {
+ vlr ($xt0,$xc0);
+ ld ("%f8","$stdframe+8*0($sp)");
+ ld ("%f9","$stdframe+8*1($sp)");
+ ld ("%f10","$stdframe+8*2($sp)");
+ ld ("%f11","$stdframe+8*3($sp)");
+ vlr ($xt1,$xd0);
+ ld ("%f12","$stdframe+8*4($sp)");
+ ld ("%f13","$stdframe+8*5($sp)");
+ ld ("%f14","$stdframe+8*6($sp)");
+ ld ("%f15","$stdframe+8*7($sp)");
+
+ vst ($xa0,"$stdframe+0x00($sp)");
+ vst ($xb0,"$stdframe+0x10($sp)");
+ vst ($xt0,"$stdframe+0x20($sp)");
+ vst ($xt1,"$stdframe+0x30($sp)");
+}
+ lghi ("%r1",0);
+
+LABEL (".Loop_tail_4x");
+ llgc ("%r5","0(%r1,$inp)");
+ llgc ("%r6","$stdframe(%r1,$sp)");
+ xr ("%r6","%r5");
+ stc ("%r6","0(%r1,$out)");
+ la ("%r1","1(%r1)");
+ brct ($len,".Loop_tail_4x");
+
+&{$z? \&lmg:\&lm} ("%r6","%r7","$FRAME+6*$SIZE_T($sp)");
+ la ($sp,"$FRAME($sp)");
+ br ("%r14");
+SIZE ("ChaCha20_ctr32_4x",".-ChaCha20_ctr32_4x");
+}
+
+########################################################################
+# 6x"horizontal" layout is optimal fit for the platform in its current
+# shape, more specifically for given vector instructions' latency. Well,
+# computational part of 8x"vertical" would be faster, but it consumes
+# all registers and dealing with that will diminish the return...
+#
+{
+my ($a0,$b0,$c0,$d0, $a1,$b1,$c1,$d1,
+ $a2,$b2,$c2,$d2, $a3,$b3,$c3,$d3,
+ $a4,$b4,$c4,$d4, $a5,$b5,$c5,$d5)=map("%v$_",(0..23));
+my @K=map("%v$_",(27,24..26));
+my ($t0,$t1,$t2,$t3)=map("%v$_",27..30);
+my $beperm="%v31";
+my $FRAME=$stdframe + 4*16;
+
+GLOBL ("ChaCha20_ctr32_vx");
+ALIGN (32);
+LABEL ("ChaCha20_ctr32_vx");
+LABEL (".LChaCha20_ctr32_vx");
+&{$z? \&clgfi:\&clfi} ($len,256);
+ jle (".LChaCha20_ctr32_4x");
+&{$z? \&stmg:\&stm} ("%r6","%r7","6*$SIZE_T($sp)");
+if (!$z) {
+ std ("%f4","16*$SIZE_T+2*8($sp)");
+ std ("%f6","16*$SIZE_T+3*8($sp)");
+}
+&{$z? \&lghi:\&lhi} ("%r1",-$FRAME);
+ lgr ("%r0",$sp);
+ la ($sp,"0(%r1,$sp)");
+&{$z? \&stg:\&st} ("%r0","0($sp)"); # back-chain
+if ($z) {
+ std ("%f8","$FRAME-8*8($sp)");
+ std ("%f9","$FRAME-8*7($sp)");
+ std ("%f10","$FRAME-8*6($sp)");
+ std ("%f11","$FRAME-8*5($sp)");
+ std ("%f12","$FRAME-8*4($sp)");
+ std ("%f13","$FRAME-8*3($sp)");
+ std ("%f14","$FRAME-8*2($sp)");
+ std ("%f15","$FRAME-8*1($sp)");
+}
+ larl ("%r7",".Lsigma");
+ lhi ("%r0",10);
+
+ vlm (@K[1],@K[2],"0($key)"); # load key
+ vl (@K[3],"0($counter)"); # load counter
+
+ vlm (@K[0],"$beperm","0(%r7)"); # load sigma, increments, ...
+
+LABEL (".Loop_outer_vx");
+ vlr ($a0,@K[0]);
+ vlr ($b0,@K[1]);
+ vlr ($a1,@K[0]);
+ vlr ($b1,@K[1]);
+ vlr ($a2,@K[0]);
+ vlr ($b2,@K[1]);
+ vlr ($a3,@K[0]);
+ vlr ($b3,@K[1]);
+ vlr ($a4,@K[0]);
+ vlr ($b4,@K[1]);
+ vlr ($a5,@K[0]);
+ vlr ($b5,@K[1]);
+
+ vlr ($d0,@K[3]);
+ vaf ($d1,@K[3],$t1); # K[3]+1
+ vaf ($d2,@K[3],$t2); # K[3]+2
+ vaf ($d3,@K[3],$t3); # K[3]+3
+ vaf ($d4,$d2,$t2); # K[3]+4
+ vaf ($d5,$d2,$t3); # K[3]+5
+
+ vlr ($c0,@K[2]);
+ vlr ($c1,@K[2]);
+ vlr ($c2,@K[2]);
+ vlr ($c3,@K[2]);
+ vlr ($c4,@K[2]);
+ vlr ($c5,@K[2]);
+
+ vlr ($t1,$d1);
+ vlr ($t2,$d2);
+ vlr ($t3,$d3);
+
+ALIGN (4);
+LABEL (".Loop_vx");
+
+ VX_ROUND($a0,$a1,$a2,$a3,$a4,$a5,
+ $b0,$b1,$b2,$b3,$b4,$b5,
+ $c0,$c1,$c2,$c3,$c4,$c5,
+ $d0,$d1,$d2,$d3,$d4,$d5,
+ 0);
+
+ VX_ROUND($a0,$a1,$a2,$a3,$a4,$a5,
+ $b0,$b1,$b2,$b3,$b4,$b5,
+ $c0,$c1,$c2,$c3,$c4,$c5,
+ $d0,$d1,$d2,$d3,$d4,$d5,
+ 1);
+
+ brct ("%r0",".Loop_vx");
+
+ vaf ($a0,$a0,@K[0]);
+ vaf ($b0,$b0,@K[1]);
+ vaf ($c0,$c0,@K[2]);
+ vaf ($d0,$d0,@K[3]);
+ vaf ($a1,$a1,@K[0]);
+ vaf ($d1,$d1,$t1); # +K[3]+1
+
+ vperm ($a0,$a0,$a0,$beperm);
+ vperm ($b0,$b0,$b0,$beperm);
+ vperm ($c0,$c0,$c0,$beperm);
+ vperm ($d0,$d0,$d0,$beperm);
+
+&{$z? \&clgfi:\&clfi} ($len,0x40);
+ jl (".Ltail_vx");
+
+ vaf ($d2,$d2,$t2); # +K[3]+2
+ vaf ($d3,$d3,$t3); # +K[3]+3
+ vlm ($t0,$t3,"0($inp)");
+
+ vx ($a0,$a0,$t0);
+ vx ($b0,$b0,$t1);
+ vx ($c0,$c0,$t2);
+ vx ($d0,$d0,$t3);
+
+ vlm (@K[0],$t3,"0(%r7)"); # re-load sigma and increments
+
+ vstm ($a0,$d0,"0($out)");
+
+ la ($inp,"0x40($inp)");
+ la ($out,"0x40($out)");
+&{$z? \&aghi:\&ahi} ($len,-0x40);
+ je (".Ldone_vx");
+
+ vaf ($b1,$b1,@K[1]);
+ vaf ($c1,$c1,@K[2]);
+
+ vperm ($a0,$a1,$a1,$beperm);
+ vperm ($b0,$b1,$b1,$beperm);
+ vperm ($c0,$c1,$c1,$beperm);
+ vperm ($d0,$d1,$d1,$beperm);
+
+&{$z? \&clgfi:\&clfi} ($len,0x40);
+ jl (".Ltail_vx");
+
+ vlm ($a1,$d1,"0($inp)");
+
+ vx ($a0,$a0,$a1);
+ vx ($b0,$b0,$b1);
+ vx ($c0,$c0,$c1);
+ vx ($d0,$d0,$d1);
+
+ vstm ($a0,$d0,"0($out)");
+
+ la ($inp,"0x40($inp)");
+ la ($out,"0x40($out)");
+&{$z? \&aghi:\&ahi} ($len,-0x40);
+ je (".Ldone_vx");
+
+ vaf ($a2,$a2,@K[0]);
+ vaf ($b2,$b2,@K[1]);
+ vaf ($c2,$c2,@K[2]);
+
+ vperm ($a0,$a2,$a2,$beperm);
+ vperm ($b0,$b2,$b2,$beperm);
+ vperm ($c0,$c2,$c2,$beperm);
+ vperm ($d0,$d2,$d2,$beperm);
+
+&{$z? \&clgfi:\&clfi} ($len,0x40);
+ jl (".Ltail_vx");
+
+ vlm ($a1,$d1,"0($inp)");
+
+ vx ($a0,$a0,$a1);
+ vx ($b0,$b0,$b1);
+ vx ($c0,$c0,$c1);
+ vx ($d0,$d0,$d1);
+
+ vstm ($a0,$d0,"0($out)");
+
+ la ($inp,"0x40($inp)");
+ la ($out,"0x40($out)");
+&{$z? \&aghi:\&ahi} ($len,-0x40);
+ je (".Ldone_vx");
+
+ vaf ($a3,$a3,@K[0]);
+ vaf ($b3,$b3,@K[1]);
+ vaf ($c3,$c3,@K[2]);
+ vaf ($d2,@K[3],$t3); # K[3]+3
+
+ vperm ($a0,$a3,$a3,$beperm);
+ vperm ($b0,$b3,$b3,$beperm);
+ vperm ($c0,$c3,$c3,$beperm);
+ vperm ($d0,$d3,$d3,$beperm);
+
+&{$z? \&clgfi:\&clfi} ($len,0x40);
+ jl (".Ltail_vx");
+
+ vaf ($d3,$d2,$t1); # K[3]+4
+ vlm ($a1,$d1,"0($inp)");
+
+ vx ($a0,$a0,$a1);
+ vx ($b0,$b0,$b1);
+ vx ($c0,$c0,$c1);
+ vx ($d0,$d0,$d1);
+
+ vstm ($a0,$d0,"0($out)");
+
+ la ($inp,"0x40($inp)");
+ la ($out,"0x40($out)");
+&{$z? \&aghi:\&ahi} ($len,-0x40);
+ je (".Ldone_vx");
+
+ vaf ($a4,$a4,@K[0]);
+ vaf ($b4,$b4,@K[1]);
+ vaf ($c4,$c4,@K[2]);
+ vaf ($d4,$d4,$d3); # +K[3]+4
+ vaf ($d3,$d3,$t1); # K[3]+5
+ vaf (@K[3],$d2,$t3); # K[3]+=6
+
+ vperm ($a0,$a4,$a4,$beperm);
+ vperm ($b0,$b4,$b4,$beperm);
+ vperm ($c0,$c4,$c4,$beperm);
+ vperm ($d0,$d4,$d4,$beperm);
+
+&{$z? \&clgfi:\&clfi} ($len,0x40);
+ jl (".Ltail_vx");
+
+ vlm ($a1,$d1,"0($inp)");
+
+ vx ($a0,$a0,$a1);
+ vx ($b0,$b0,$b1);
+ vx ($c0,$c0,$c1);
+ vx ($d0,$d0,$d1);
+
+ vstm ($a0,$d0,"0($out)");
+
+ la ($inp,"0x40($inp)");
+ la ($out,"0x40($out)");
+&{$z? \&aghi:\&ahi} ($len,-0x40);
+ je (".Ldone_vx");
+
+ vaf ($a5,$a5,@K[0]);
+ vaf ($b5,$b5,@K[1]);
+ vaf ($c5,$c5,@K[2]);
+ vaf ($d5,$d5,$d3); # +K[3]+5
+
+ vperm ($a0,$a5,$a5,$beperm);
+ vperm ($b0,$b5,$b5,$beperm);
+ vperm ($c0,$c5,$c5,$beperm);
+ vperm ($d0,$d5,$d5,$beperm);
+
+&{$z? \&clgfi:\&clfi} ($len,0x40);
+ jl (".Ltail_vx");
+
+ vlm ($a1,$d1,"0($inp)");
+
+ vx ($a0,$a0,$a1);
+ vx ($b0,$b0,$b1);
+ vx ($c0,$c0,$c1);
+ vx ($d0,$d0,$d1);
+
+ vstm ($a0,$d0,"0($out)");
+
+ la ($inp,"0x40($inp)");
+ la ($out,"0x40($out)");
+ lhi ("%r0",10);
+&{$z? \&aghi:\&ahi} ($len,-0x40);
+ jne (".Loop_outer_vx");
+
+LABEL (".Ldone_vx");
+if (!$z) {
+ ld ("%f4","$FRAME+16*$SIZE_T+2*8($sp)");
+ ld ("%f6","$FRAME+16*$SIZE_T+3*8($sp)");
+} else {
+ ld ("%f8","$FRAME-8*8($sp)");
+ ld ("%f9","$FRAME-8*7($sp)");
+ ld ("%f10","$FRAME-8*6($sp)");
+ ld ("%f11","$FRAME-8*5($sp)");
+ ld ("%f12","$FRAME-8*4($sp)");
+ ld ("%f13","$FRAME-8*3($sp)");
+ ld ("%f14","$FRAME-8*2($sp)");
+ ld ("%f15","$FRAME-8*1($sp)");
+}
+&{$z? \&lmg:\&lm} ("%r6","%r7","$FRAME+6*$SIZE_T($sp)");
+ la ($sp,"$FRAME($sp)");
+ br ("%r14");
+
+ALIGN (16);
+LABEL (".Ltail_vx");
+if (!$z) {
+ ld ("%f4","$FRAME+16*$SIZE_T+2*8($sp)");
+ ld ("%f6","$FRAME+16*$SIZE_T+3*8($sp)");
+} else {
+ ld ("%f8","$FRAME-8*8($sp)");
+ ld ("%f9","$FRAME-8*7($sp)");
+ ld ("%f10","$FRAME-8*6($sp)");
+ ld ("%f11","$FRAME-8*5($sp)");
+ ld ("%f12","$FRAME-8*4($sp)");
+ ld ("%f13","$FRAME-8*3($sp)");
+ ld ("%f14","$FRAME-8*2($sp)");
+ ld ("%f15","$FRAME-8*1($sp)");
+}
+ vstm ($a0,$d0,"$stdframe($sp)");
+ lghi ("%r1",0);
+
+LABEL (".Loop_tail_vx");
+ llgc ("%r5","0(%r1,$inp)");
+ llgc ("%r6","$stdframe(%r1,$sp)");
+ xr ("%r6","%r5");
+ stc ("%r6","0(%r1,$out)");
+ la ("%r1","1(%r1)");
+ brct ($len,".Loop_tail_vx");
+
+&{$z? \&lmg:\&lm} ("%r6","%r7","$FRAME+6*$SIZE_T($sp)");
+ la ($sp,"$FRAME($sp)");
+ br ("%r14");
+SIZE ("ChaCha20_ctr32_vx",".-ChaCha20_ctr32_vx");
+}
+################
+
+ALIGN (32);
+LABEL (".Lsigma");
+LONG (0x61707865,0x3320646e,0x79622d32,0x6b206574); # endian-neutral sigma
+LONG (1,0,0,0);
+LONG (2,0,0,0);
+LONG (3,0,0,0);
+LONG (0x03020100,0x07060504,0x0b0a0908,0x0f0e0d0c); # byte swap
+
+LONG (0,1,2,3);
+LONG (0x61707865,0x61707865,0x61707865,0x61707865); # smashed sigma
+LONG (0x3320646e,0x3320646e,0x3320646e,0x3320646e);
+LONG (0x79622d32,0x79622d32,0x79622d32,0x79622d32);
+LONG (0x6b206574,0x6b206574,0x6b206574,0x6b206574);
+
+ASCIZ ("\"ChaCha20 for s390x, CRYPTOGAMS by <appro\@openssl.org>\"");
+ALIGN (4);
+
+PERLASM_END();
diff --git a/crypto/chacha/asm/chacha-x86.pl b/crypto/chacha/asm/chacha-x86.pl
index 492fda5f114c..d0e83d88cec3 100755
--- a/crypto/chacha/asm/chacha-x86.pl
+++ b/crypto/chacha/asm/chacha-x86.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -40,8 +40,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output=pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386");
diff --git a/crypto/chacha/asm/chacha-x86_64.pl b/crypto/chacha/asm/chacha-x86_64.pl
index c0e5d863dcb2..cdb900c037fd 100755
--- a/crypto/chacha/asm/chacha-x86_64.pl
+++ b/crypto/chacha/asm/chacha-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -58,9 +58,10 @@
# (vi) even though Skylake-X can execute AVX512F code and deliver 0.57
# cpb in single thread, the corresponding capability is suppressed;
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -89,7 +90,8 @@ if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|.*based on LLVM) ([0
$avx = ($2>=3.0) + ($2>3.0);
}
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
# input parameter block
diff --git a/crypto/chacha/build.info b/crypto/chacha/build.info
index e75ca72b67d4..e7159dc066dc 100644
--- a/crypto/chacha/build.info
+++ b/crypto/chacha/build.info
@@ -1,20 +1,40 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]={- $target{chacha_asm_src} -}
-GENERATE[chacha-x86.s]=asm/chacha-x86.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-GENERATE[chacha-x86_64.s]=asm/chacha-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[chacha-ppc.s]=asm/chacha-ppc.pl $(PERLASM_SCHEME)
-GENERATE[chacha-armv4.S]=asm/chacha-armv4.pl $(PERLASM_SCHEME)
+$CHACHAASM=chacha_enc.c
+IF[{- !$disabled{asm} -}]
+ $CHACHAASM_x86=chacha-x86.S
+ $CHACHAASM_x86_64=chacha-x86_64.s
+
+ $CHACHAASM_ia64=chacha-ia64.s
+
+ $CHACHAASM_s390x=chacha-s390x.S
+
+ $CHACHAASM_armv4=chacha-armv4.S
+ $CHACHAASM_aarch64=chacha-armv8.S
+
+ $CHACHAASM_ppc32=chacha_ppc.c chacha-ppc.s
+ $CHACHAASM_ppc64=$CHACHAASM_ppc32
+
+ $CHACHAASM_c64xplus=chacha-c64xplus.s
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one
+ IF[$CHACHAASM_{- $target{asm_arch} -}]
+ $CHACHAASM=$CHACHAASM_{- $target{asm_arch} -}
+ ENDIF
+ENDIF
+
+SOURCE[../../libcrypto]=$CHACHAASM
+
+GENERATE[chacha-x86.S]=asm/chacha-x86.pl
+GENERATE[chacha-x86_64.s]=asm/chacha-x86_64.pl
+GENERATE[chacha-ppc.s]=asm/chacha-ppc.pl
+GENERATE[chacha-armv4.S]=asm/chacha-armv4.pl
INCLUDE[chacha-armv4.o]=..
-GENERATE[chacha-armv8.S]=asm/chacha-armv8.pl $(PERLASM_SCHEME)
+GENERATE[chacha-armv8.S]=asm/chacha-armv8.pl
INCLUDE[chacha-armv8.o]=..
-GENERATE[chacha-s390x.S]=asm/chacha-s390x.pl $(PERLASM_SCHEME)
INCLUDE[chacha-s390x.o]=..
-
-BEGINRAW[Makefile(unix)]
-##### CHACHA assembler implementations
-
-{- $builddir -}/chacha-%.S: {- $sourcedir -}/asm/chacha-%.pl
- CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@
-ENDRAW[Makefile(unix)]
+GENERATE[chacha-c64xplus.S]=asm/chacha-c64xplus.pl
+GENERATE[chacha-s390x.S]=asm/chacha-s390x.pl
+GENERATE[chacha-ia64.S]=asm/chacha-ia64.pl
+GENERATE[chacha-ia64.s]=chacha-ia64.S
diff --git a/crypto/chacha/chacha_enc.c b/crypto/chacha/chacha_enc.c
index 18251eac08de..c5d1d63d8027 100644
--- a/crypto/chacha/chacha_enc.c
+++ b/crypto/chacha/chacha_enc.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,6 +11,7 @@
#include <string.h>
+#include "internal/endian.h"
#include "crypto/chacha.h"
#include "crypto/ctype.h"
@@ -43,10 +44,7 @@ static void chacha20_core(chacha_buf *output, const u32 input[16])
{
u32 x[16];
int i;
- const union {
- long one;
- char little;
- } is_endian = { 1 };
+ DECLARE_IS_ENDIAN;
memcpy(x, input, sizeof(x));
@@ -61,7 +59,7 @@ static void chacha20_core(chacha_buf *output, const u32 input[16])
QUARTERROUND(3, 4, 9, 14);
}
- if (is_endian.little) {
+ if (IS_LITTLE_ENDIAN) {
for (i = 0; i < 16; ++i)
output->u[i] = x[i] + input[i];
} else {
diff --git a/crypto/chacha/chacha_ppc.c b/crypto/chacha/chacha_ppc.c
new file mode 100644
index 000000000000..5319040cc167
--- /dev/null
+++ b/crypto/chacha/chacha_ppc.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2009-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/opensslconf.h>
+#include "crypto/chacha.h"
+#include "crypto/ppc_arch.h"
+
+void ChaCha20_ctr32_int(unsigned char *out, const unsigned char *inp,
+ size_t len, const unsigned int key[8],
+ const unsigned int counter[4]);
+void ChaCha20_ctr32_vmx(unsigned char *out, const unsigned char *inp,
+ size_t len, const unsigned int key[8],
+ const unsigned int counter[4]);
+void ChaCha20_ctr32_vsx(unsigned char *out, const unsigned char *inp,
+ size_t len, const unsigned int key[8],
+ const unsigned int counter[4]);
+void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp,
+ size_t len, const unsigned int key[8],
+ const unsigned int counter[4])
+{
+ OPENSSL_ppccap_P & PPC_CRYPTO207
+ ? ChaCha20_ctr32_vsx(out, inp, len, key, counter)
+ : OPENSSL_ppccap_P & PPC_ALTIVEC
+ ? ChaCha20_ctr32_vmx(out, inp, len, key, counter)
+ : ChaCha20_ctr32_int(out, inp, len, key, counter);
+}
diff --git a/crypto/cmac/build.info b/crypto/cmac/build.info
index c8a4949a0729..0c0e50941f67 100644
--- a/crypto/cmac/build.info
+++ b/crypto/cmac/build.info
@@ -1,2 +1,6 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=cmac.c cm_ameth.c cm_pmeth.c
+
+$COMMON=cmac.c
+
+SOURCE[../../libcrypto]=$COMMON
+SOURCE[../../providers/libfips.a]=$COMMON
diff --git a/crypto/cmac/cm_ameth.c b/crypto/cmac/cm_ameth.c
deleted file mode 100644
index 82adf18c8019..000000000000
--- a/crypto/cmac/cm_ameth.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/evp.h>
-#include <openssl/cmac.h>
-#include "crypto/asn1.h"
-
-/*
- * CMAC "ASN1" method. This is just here to indicate the maximum CMAC output
- * length and to free up a CMAC key.
- */
-
-static int cmac_size(const EVP_PKEY *pkey)
-{
- return EVP_MAX_BLOCK_LENGTH;
-}
-
-static void cmac_key_free(EVP_PKEY *pkey)
-{
- CMAC_CTX *cmctx = EVP_PKEY_get0(pkey);
- CMAC_CTX_free(cmctx);
-}
-
-const EVP_PKEY_ASN1_METHOD cmac_asn1_meth = {
- EVP_PKEY_CMAC,
- EVP_PKEY_CMAC,
- 0,
-
- "CMAC",
- "OpenSSL CMAC method",
-
- 0, 0, 0, 0,
-
- 0, 0, 0,
-
- cmac_size,
- 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-
- cmac_key_free,
- 0,
- 0, 0
-};
diff --git a/crypto/cmac/cm_pmeth.c b/crypto/cmac/cm_pmeth.c
deleted file mode 100644
index 5574f25be868..000000000000
--- a/crypto/cmac/cm_pmeth.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-#include <openssl/evp.h>
-#include <openssl/cmac.h>
-#include "crypto/evp.h"
-
-/* The context structure and "key" is simply a CMAC_CTX */
-
-static int pkey_cmac_init(EVP_PKEY_CTX *ctx)
-{
- ctx->data = CMAC_CTX_new();
- if (ctx->data == NULL)
- return 0;
- ctx->keygen_info_count = 0;
- return 1;
-}
-
-static int pkey_cmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
-{
- if (!pkey_cmac_init(dst))
- return 0;
- if (!CMAC_CTX_copy(dst->data, src->data))
- return 0;
- return 1;
-}
-
-static void pkey_cmac_cleanup(EVP_PKEY_CTX *ctx)
-{
- CMAC_CTX_free(ctx->data);
-}
-
-static int pkey_cmac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
-{
- CMAC_CTX *cmkey = CMAC_CTX_new();
- CMAC_CTX *cmctx = ctx->data;
- if (cmkey == NULL)
- return 0;
- if (!CMAC_CTX_copy(cmkey, cmctx)) {
- CMAC_CTX_free(cmkey);
- return 0;
- }
- EVP_PKEY_assign(pkey, EVP_PKEY_CMAC, cmkey);
-
- return 1;
-}
-
-static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- if (!CMAC_Update(EVP_MD_CTX_pkey_ctx(ctx)->data, data, count))
- return 0;
- return 1;
-}
-
-static int cmac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
-{
- EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
- EVP_MD_CTX_set_update_fn(mctx, int_update);
- return 1;
-}
-
-static int cmac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
- EVP_MD_CTX *mctx)
-{
- return CMAC_Final(ctx->data, sig, siglen);
-}
-
-static int pkey_cmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
-{
- CMAC_CTX *cmctx = ctx->data;
- switch (type) {
-
- case EVP_PKEY_CTRL_SET_MAC_KEY:
- if (!p2 || p1 < 0)
- return 0;
- if (!CMAC_Init(cmctx, p2, p1, NULL, NULL))
- return 0;
- break;
-
- case EVP_PKEY_CTRL_CIPHER:
- if (!CMAC_Init(cmctx, NULL, 0, p2, ctx->engine))
- return 0;
- break;
-
- case EVP_PKEY_CTRL_MD:
- if (ctx->pkey && !CMAC_CTX_copy(ctx->data,
- (CMAC_CTX *)ctx->pkey->pkey.ptr))
- return 0;
- if (!CMAC_Init(cmctx, NULL, 0, NULL, NULL))
- return 0;
- break;
-
- default:
- return -2;
-
- }
- return 1;
-}
-
-static int pkey_cmac_ctrl_str(EVP_PKEY_CTX *ctx,
- const char *type, const char *value)
-{
- if (!value) {
- return 0;
- }
- if (strcmp(type, "cipher") == 0) {
- const EVP_CIPHER *c;
- c = EVP_get_cipherbyname(value);
- if (!c)
- return 0;
- return pkey_cmac_ctrl(ctx, EVP_PKEY_CTRL_CIPHER, -1, (void *)c);
- }
- if (strcmp(type, "key") == 0)
- return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
- if (strcmp(type, "hexkey") == 0)
- return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
- return -2;
-}
-
-const EVP_PKEY_METHOD cmac_pkey_meth = {
- EVP_PKEY_CMAC,
- EVP_PKEY_FLAG_SIGCTX_CUSTOM,
- pkey_cmac_init,
- pkey_cmac_copy,
- pkey_cmac_cleanup,
-
- 0, 0,
-
- 0,
- pkey_cmac_keygen,
-
- 0, 0,
-
- 0, 0,
-
- 0, 0,
-
- cmac_signctx_init,
- cmac_signctx,
-
- 0, 0,
-
- 0, 0,
-
- 0, 0,
-
- 0, 0,
-
- pkey_cmac_ctrl,
- pkey_cmac_ctrl_str
-};
diff --git a/crypto/cmac/cmac.c b/crypto/cmac/cmac.c
index 1fac53101687..7f94727085e5 100644
--- a/crypto/cmac/cmac.c
+++ b/crypto/cmac/cmac.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2010-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * CMAC low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -48,7 +54,7 @@ CMAC_CTX *CMAC_CTX_new(void)
CMAC_CTX *ctx;
if ((ctx = OPENSSL_malloc(sizeof(*ctx))) == NULL) {
- CRYPTOerr(CRYPTO_F_CMAC_CTX_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return NULL;
}
ctx->cctx = EVP_CIPHER_CTX_new();
@@ -87,11 +93,13 @@ void CMAC_CTX_free(CMAC_CTX *ctx)
int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in)
{
int bl;
+
if (in->nlast_block == -1)
return 0;
+ if ((bl = EVP_CIPHER_CTX_get_block_size(in->cctx)) < 0)
+ return 0;
if (!EVP_CIPHER_CTX_copy(out->cctx, in->cctx))
return 0;
- bl = EVP_CIPHER_CTX_block_size(in->cctx);
memcpy(out->k1, in->k1, bl);
memcpy(out->k2, in->k2, bl);
memcpy(out->tbl, in->tbl, bl);
@@ -104,6 +112,7 @@ int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
const EVP_CIPHER *cipher, ENGINE *impl)
{
static const unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH] = { 0 };
+
/* All zeros means restart */
if (!key && !cipher && !impl && keylen == 0) {
/* Not initialised */
@@ -111,7 +120,7 @@ int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
return 0;
if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, zero_iv))
return 0;
- memset(ctx->tbl, 0, EVP_CIPHER_CTX_block_size(ctx->cctx));
+ memset(ctx->tbl, 0, EVP_CIPHER_CTX_get_block_size(ctx->cctx));
ctx->nlast_block = 0;
return 1;
}
@@ -128,13 +137,14 @@ int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
/* If anything fails then ensure we can't use this ctx */
ctx->nlast_block = -1;
- if (!EVP_CIPHER_CTX_cipher(ctx->cctx))
+ if (EVP_CIPHER_CTX_get0_cipher(ctx->cctx) == NULL)
return 0;
- if (!EVP_CIPHER_CTX_set_key_length(ctx->cctx, keylen))
+ if (EVP_CIPHER_CTX_set_key_length(ctx->cctx, keylen) <= 0)
return 0;
if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, key, zero_iv))
return 0;
- bl = EVP_CIPHER_CTX_block_size(ctx->cctx);
+ if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) < 0)
+ return 0;
if (EVP_Cipher(ctx->cctx, ctx->tbl, zero_iv, bl) <= 0)
return 0;
make_kn(ctx->k1, ctx->tbl, bl);
@@ -153,15 +163,18 @@ int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
int CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen)
{
const unsigned char *data = in;
- size_t bl;
+ int bl;
+
if (ctx->nlast_block == -1)
return 0;
if (dlen == 0)
return 1;
- bl = EVP_CIPHER_CTX_block_size(ctx->cctx);
+ if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) < 0)
+ return 0;
/* Copy into partial block if we need to */
if (ctx->nlast_block > 0) {
size_t nleft;
+
nleft = bl - ctx->nlast_block;
if (dlen < nleft)
nleft = dlen;
@@ -177,7 +190,7 @@ int CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen)
return 0;
}
/* Encrypt all but one of the complete blocks left */
- while (dlen > bl) {
+ while (dlen > (size_t)bl) {
if (EVP_Cipher(ctx->cctx, ctx->tbl, data, bl) <= 0)
return 0;
dlen -= bl;
@@ -193,10 +206,13 @@ int CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen)
int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen)
{
int i, bl, lb;
+
if (ctx->nlast_block == -1)
return 0;
- bl = EVP_CIPHER_CTX_block_size(ctx->cctx);
- *poutlen = (size_t)bl;
+ if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) < 0)
+ return 0;
+ if (poutlen != NULL)
+ *poutlen = (size_t)bl;
if (!out)
return 1;
lb = ctx->nlast_block;
@@ -211,7 +227,7 @@ int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen)
for (i = 0; i < bl; i++)
out[i] = ctx->last_block[i] ^ ctx->k2[i];
}
- if (!EVP_Cipher(ctx->cctx, out, out, bl)) {
+ if (EVP_Cipher(ctx->cctx, out, out, bl) <= 0) {
OPENSSL_cleanse(out, bl);
return 0;
}
diff --git a/crypto/cmp/build.info b/crypto/cmp/build.info
new file mode 100644
index 000000000000..a2a57c14ec10
--- /dev/null
+++ b/crypto/cmp/build.info
@@ -0,0 +1,4 @@
+LIBS=../../libcrypto
+SOURCE[../../libcrypto]= cmp_asn.c cmp_ctx.c cmp_err.c cmp_util.c \
+ cmp_status.c cmp_hdr.c cmp_protect.c cmp_msg.c cmp_vfy.c \
+ cmp_server.c cmp_client.c cmp_http.c
diff --git a/crypto/cmp/cmp_asn.c b/crypto/cmp/cmp_asn.c
new file mode 100644
index 000000000000..0ca107554c96
--- /dev/null
+++ b/crypto/cmp/cmp_asn.c
@@ -0,0 +1,459 @@
+/*
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/asn1t.h>
+
+#include "cmp_local.h"
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <openssl/cmp.h>
+#include <openssl/crmf.h>
+
+/* ASN.1 declarations from RFC4210 */
+ASN1_SEQUENCE(OSSL_CMP_REVANNCONTENT) = {
+ /* OSSL_CMP_PKISTATUS is effectively ASN1_INTEGER so it is used directly */
+ ASN1_SIMPLE(OSSL_CMP_REVANNCONTENT, status, ASN1_INTEGER),
+ ASN1_SIMPLE(OSSL_CMP_REVANNCONTENT, certId, OSSL_CRMF_CERTID),
+ ASN1_SIMPLE(OSSL_CMP_REVANNCONTENT, willBeRevokedAt, ASN1_GENERALIZEDTIME),
+ ASN1_SIMPLE(OSSL_CMP_REVANNCONTENT, badSinceDate, ASN1_GENERALIZEDTIME),
+ ASN1_OPT(OSSL_CMP_REVANNCONTENT, crlDetails, X509_EXTENSIONS)
+} ASN1_SEQUENCE_END(OSSL_CMP_REVANNCONTENT)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_REVANNCONTENT)
+
+
+ASN1_SEQUENCE(OSSL_CMP_CHALLENGE) = {
+ ASN1_OPT(OSSL_CMP_CHALLENGE, owf, X509_ALGOR),
+ ASN1_SIMPLE(OSSL_CMP_CHALLENGE, witness, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(OSSL_CMP_CHALLENGE, challenge, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(OSSL_CMP_CHALLENGE)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CHALLENGE)
+
+
+ASN1_ITEM_TEMPLATE(OSSL_CMP_POPODECKEYCHALLCONTENT) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0,
+ OSSL_CMP_POPODECKEYCHALLCONTENT, OSSL_CMP_CHALLENGE)
+ASN1_ITEM_TEMPLATE_END(OSSL_CMP_POPODECKEYCHALLCONTENT)
+
+
+ASN1_ITEM_TEMPLATE(OSSL_CMP_POPODECKEYRESPCONTENT) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0,
+ OSSL_CMP_POPODECKEYRESPCONTENT, ASN1_INTEGER)
+ASN1_ITEM_TEMPLATE_END(OSSL_CMP_POPODECKEYRESPCONTENT)
+
+
+ASN1_SEQUENCE(OSSL_CMP_CAKEYUPDANNCONTENT) = {
+ /* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+ ASN1_SIMPLE(OSSL_CMP_CAKEYUPDANNCONTENT, oldWithNew, X509),
+ /* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+ ASN1_SIMPLE(OSSL_CMP_CAKEYUPDANNCONTENT, newWithOld, X509),
+ /* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+ ASN1_SIMPLE(OSSL_CMP_CAKEYUPDANNCONTENT, newWithNew, X509)
+} ASN1_SEQUENCE_END(OSSL_CMP_CAKEYUPDANNCONTENT)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CAKEYUPDANNCONTENT)
+
+
+ASN1_SEQUENCE(OSSL_CMP_ERRORMSGCONTENT) = {
+ ASN1_SIMPLE(OSSL_CMP_ERRORMSGCONTENT, pKIStatusInfo, OSSL_CMP_PKISI),
+ ASN1_OPT(OSSL_CMP_ERRORMSGCONTENT, errorCode, ASN1_INTEGER),
+ /*
+ * OSSL_CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING
+ * so it is used directly
+ *
+ */
+ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ERRORMSGCONTENT, errorDetails,
+ ASN1_UTF8STRING)
+} ASN1_SEQUENCE_END(OSSL_CMP_ERRORMSGCONTENT)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ERRORMSGCONTENT)
+
+ASN1_ADB_TEMPLATE(infotypeandvalue_default) = ASN1_OPT(OSSL_CMP_ITAV,
+ infoValue.other,
+ ASN1_ANY);
+/* ITAV means InfoTypeAndValue */
+ASN1_ADB(OSSL_CMP_ITAV) = {
+ /* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+ ADB_ENTRY(NID_id_it_caProtEncCert, ASN1_OPT(OSSL_CMP_ITAV,
+ infoValue.caProtEncCert, X509)),
+ ADB_ENTRY(NID_id_it_signKeyPairTypes,
+ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV,
+ infoValue.signKeyPairTypes, X509_ALGOR)),
+ ADB_ENTRY(NID_id_it_encKeyPairTypes,
+ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV,
+ infoValue.encKeyPairTypes, X509_ALGOR)),
+ ADB_ENTRY(NID_id_it_preferredSymmAlg,
+ ASN1_OPT(OSSL_CMP_ITAV, infoValue.preferredSymmAlg,
+ X509_ALGOR)),
+ ADB_ENTRY(NID_id_it_caKeyUpdateInfo,
+ ASN1_OPT(OSSL_CMP_ITAV, infoValue.caKeyUpdateInfo,
+ OSSL_CMP_CAKEYUPDANNCONTENT)),
+ ADB_ENTRY(NID_id_it_currentCRL,
+ ASN1_OPT(OSSL_CMP_ITAV, infoValue.currentCRL, X509_CRL)),
+ ADB_ENTRY(NID_id_it_unsupportedOIDs,
+ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV,
+ infoValue.unsupportedOIDs, ASN1_OBJECT)),
+ ADB_ENTRY(NID_id_it_keyPairParamReq,
+ ASN1_OPT(OSSL_CMP_ITAV, infoValue.keyPairParamReq,
+ ASN1_OBJECT)),
+ ADB_ENTRY(NID_id_it_keyPairParamRep,
+ ASN1_OPT(OSSL_CMP_ITAV, infoValue.keyPairParamRep,
+ X509_ALGOR)),
+ ADB_ENTRY(NID_id_it_revPassphrase,
+ ASN1_OPT(OSSL_CMP_ITAV, infoValue.revPassphrase,
+ OSSL_CRMF_ENCRYPTEDVALUE)),
+ ADB_ENTRY(NID_id_it_implicitConfirm,
+ ASN1_OPT(OSSL_CMP_ITAV, infoValue.implicitConfirm,
+ ASN1_NULL)),
+ ADB_ENTRY(NID_id_it_confirmWaitTime,
+ ASN1_OPT(OSSL_CMP_ITAV, infoValue.confirmWaitTime,
+ ASN1_GENERALIZEDTIME)),
+ ADB_ENTRY(NID_id_it_origPKIMessage,
+ ASN1_OPT(OSSL_CMP_ITAV, infoValue.origPKIMessage,
+ OSSL_CMP_MSGS)),
+ ADB_ENTRY(NID_id_it_suppLangTags,
+ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.suppLangTagsValue,
+ ASN1_UTF8STRING)),
+} ASN1_ADB_END(OSSL_CMP_ITAV, 0, infoType, 0,
+ &infotypeandvalue_default_tt, NULL);
+
+
+ASN1_SEQUENCE(OSSL_CMP_ITAV) = {
+ ASN1_SIMPLE(OSSL_CMP_ITAV, infoType, ASN1_OBJECT),
+ ASN1_ADB_OBJECT(OSSL_CMP_ITAV)
+} ASN1_SEQUENCE_END(OSSL_CMP_ITAV)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ITAV)
+IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CMP_ITAV)
+
+OSSL_CMP_ITAV *OSSL_CMP_ITAV_create(ASN1_OBJECT *type, ASN1_TYPE *value)
+{
+ OSSL_CMP_ITAV *itav;
+
+ if (type == NULL || (itav = OSSL_CMP_ITAV_new()) == NULL)
+ return NULL;
+ OSSL_CMP_ITAV_set0(itav, type, value);
+ return itav;
+}
+
+void OSSL_CMP_ITAV_set0(OSSL_CMP_ITAV *itav, ASN1_OBJECT *type,
+ ASN1_TYPE *value)
+{
+ itav->infoType = type;
+ itav->infoValue.other = value;
+}
+
+ASN1_OBJECT *OSSL_CMP_ITAV_get0_type(const OSSL_CMP_ITAV *itav)
+{
+ if (itav == NULL)
+ return NULL;
+ return itav->infoType;
+}
+
+ASN1_TYPE *OSSL_CMP_ITAV_get0_value(const OSSL_CMP_ITAV *itav)
+{
+ if (itav == NULL)
+ return NULL;
+ return itav->infoValue.other;
+}
+
+int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p,
+ OSSL_CMP_ITAV *itav)
+{
+ int created = 0;
+
+ if (itav_sk_p == NULL || itav == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ goto err;
+ }
+
+ if (*itav_sk_p == NULL) {
+ if ((*itav_sk_p = sk_OSSL_CMP_ITAV_new_null()) == NULL)
+ goto err;
+ created = 1;
+ }
+ if (!sk_OSSL_CMP_ITAV_push(*itav_sk_p, itav))
+ goto err;
+ return 1;
+
+ err:
+ if (created != 0) {
+ sk_OSSL_CMP_ITAV_free(*itav_sk_p);
+ *itav_sk_p = NULL;
+ }
+ return 0;
+}
+
+/* get ASN.1 encoded integer, return -1 on error */
+int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a)
+{
+ int64_t res;
+
+ if (!ASN1_INTEGER_get_int64(&res, a)) {
+ ERR_raise(ERR_LIB_CMP, ASN1_R_INVALID_NUMBER);
+ return -1;
+ }
+ if (res < INT_MIN) {
+ ERR_raise(ERR_LIB_CMP, ASN1_R_TOO_SMALL);
+ return -1;
+ }
+ if (res > INT_MAX) {
+ ERR_raise(ERR_LIB_CMP, ASN1_R_TOO_LARGE);
+ return -1;
+ }
+ return (int)res;
+}
+
+static int ossl_cmp_msg_cb(int operation, ASN1_VALUE **pval,
+ const ASN1_ITEM *it, void *exarg)
+{
+ OSSL_CMP_MSG *msg = (OSSL_CMP_MSG *)*pval;
+
+ switch (operation) {
+ case ASN1_OP_FREE_POST:
+ OPENSSL_free(msg->propq);
+ break;
+
+ case ASN1_OP_DUP_POST:
+ {
+ OSSL_CMP_MSG *old = exarg;
+
+ if (!ossl_cmp_msg_set0_libctx(msg, old->libctx, old->propq))
+ return 0;
+ }
+ break;
+ case ASN1_OP_GET0_LIBCTX:
+ {
+ OSSL_LIB_CTX **libctx = exarg;
+
+ *libctx = msg->libctx;
+ }
+ break;
+ case ASN1_OP_GET0_PROPQ:
+ {
+ const char **propq = exarg;
+
+ *propq = msg->propq;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 1;
+}
+
+ASN1_CHOICE(OSSL_CMP_CERTORENCCERT) = {
+ /* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+ ASN1_EXP(OSSL_CMP_CERTORENCCERT, value.certificate, X509, 0),
+ ASN1_EXP(OSSL_CMP_CERTORENCCERT, value.encryptedCert,
+ OSSL_CRMF_ENCRYPTEDVALUE, 1),
+} ASN1_CHOICE_END(OSSL_CMP_CERTORENCCERT)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CERTORENCCERT)
+
+
+ASN1_SEQUENCE(OSSL_CMP_CERTIFIEDKEYPAIR) = {
+ ASN1_SIMPLE(OSSL_CMP_CERTIFIEDKEYPAIR, certOrEncCert,
+ OSSL_CMP_CERTORENCCERT),
+ ASN1_EXP_OPT(OSSL_CMP_CERTIFIEDKEYPAIR, privateKey,
+ OSSL_CRMF_ENCRYPTEDVALUE, 0),
+ ASN1_EXP_OPT(OSSL_CMP_CERTIFIEDKEYPAIR, publicationInfo,
+ OSSL_CRMF_PKIPUBLICATIONINFO, 1)
+} ASN1_SEQUENCE_END(OSSL_CMP_CERTIFIEDKEYPAIR)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CERTIFIEDKEYPAIR)
+
+
+ASN1_SEQUENCE(OSSL_CMP_REVDETAILS) = {
+ ASN1_SIMPLE(OSSL_CMP_REVDETAILS, certDetails, OSSL_CRMF_CERTTEMPLATE),
+ ASN1_OPT(OSSL_CMP_REVDETAILS, crlEntryDetails, X509_EXTENSIONS)
+} ASN1_SEQUENCE_END(OSSL_CMP_REVDETAILS)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_REVDETAILS)
+
+
+ASN1_ITEM_TEMPLATE(OSSL_CMP_REVREQCONTENT) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, OSSL_CMP_REVREQCONTENT,
+ OSSL_CMP_REVDETAILS)
+ASN1_ITEM_TEMPLATE_END(OSSL_CMP_REVREQCONTENT)
+
+
+ASN1_SEQUENCE(OSSL_CMP_REVREPCONTENT) = {
+ ASN1_SEQUENCE_OF(OSSL_CMP_REVREPCONTENT, status, OSSL_CMP_PKISI),
+ ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_REVREPCONTENT, revCerts, OSSL_CRMF_CERTID,
+ 0),
+ ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_REVREPCONTENT, crls, X509_CRL, 1)
+} ASN1_SEQUENCE_END(OSSL_CMP_REVREPCONTENT)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_REVREPCONTENT)
+
+
+ASN1_SEQUENCE(OSSL_CMP_KEYRECREPCONTENT) = {
+ ASN1_SIMPLE(OSSL_CMP_KEYRECREPCONTENT, status, OSSL_CMP_PKISI),
+ ASN1_EXP_OPT(OSSL_CMP_KEYRECREPCONTENT, newSigCert, X509, 0),
+ ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_KEYRECREPCONTENT, caCerts, X509, 1),
+ ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_KEYRECREPCONTENT, keyPairHist,
+ OSSL_CMP_CERTIFIEDKEYPAIR, 2)
+} ASN1_SEQUENCE_END(OSSL_CMP_KEYRECREPCONTENT)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_KEYRECREPCONTENT)
+
+
+ASN1_ITEM_TEMPLATE(OSSL_CMP_PKISTATUS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_UNIVERSAL, 0, status, ASN1_INTEGER)
+ASN1_ITEM_TEMPLATE_END(OSSL_CMP_PKISTATUS)
+
+ASN1_SEQUENCE(OSSL_CMP_PKISI) = {
+ ASN1_SIMPLE(OSSL_CMP_PKISI, status, OSSL_CMP_PKISTATUS),
+ /*
+ * CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING
+ * so it is used directly
+ */
+ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_PKISI, statusString, ASN1_UTF8STRING),
+ /*
+ * OSSL_CMP_PKIFAILUREINFO is effectively ASN1_BIT_STRING so used directly
+ */
+ ASN1_OPT(OSSL_CMP_PKISI, failInfo, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(OSSL_CMP_PKISI)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_PKISI)
+IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CMP_PKISI)
+
+ASN1_SEQUENCE(OSSL_CMP_CERTSTATUS) = {
+ ASN1_SIMPLE(OSSL_CMP_CERTSTATUS, certHash, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(OSSL_CMP_CERTSTATUS, certReqId, ASN1_INTEGER),
+ ASN1_OPT(OSSL_CMP_CERTSTATUS, statusInfo, OSSL_CMP_PKISI)
+} ASN1_SEQUENCE_END(OSSL_CMP_CERTSTATUS)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CERTSTATUS)
+
+ASN1_ITEM_TEMPLATE(OSSL_CMP_CERTCONFIRMCONTENT) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, OSSL_CMP_CERTCONFIRMCONTENT,
+ OSSL_CMP_CERTSTATUS)
+ASN1_ITEM_TEMPLATE_END(OSSL_CMP_CERTCONFIRMCONTENT)
+
+ASN1_SEQUENCE(OSSL_CMP_CERTRESPONSE) = {
+ ASN1_SIMPLE(OSSL_CMP_CERTRESPONSE, certReqId, ASN1_INTEGER),
+ ASN1_SIMPLE(OSSL_CMP_CERTRESPONSE, status, OSSL_CMP_PKISI),
+ ASN1_OPT(OSSL_CMP_CERTRESPONSE, certifiedKeyPair,
+ OSSL_CMP_CERTIFIEDKEYPAIR),
+ ASN1_OPT(OSSL_CMP_CERTRESPONSE, rspInfo, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(OSSL_CMP_CERTRESPONSE)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CERTRESPONSE)
+
+ASN1_SEQUENCE(OSSL_CMP_POLLREQ) = {
+ ASN1_SIMPLE(OSSL_CMP_POLLREQ, certReqId, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(OSSL_CMP_POLLREQ)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_POLLREQ)
+
+ASN1_ITEM_TEMPLATE(OSSL_CMP_POLLREQCONTENT) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, OSSL_CMP_POLLREQCONTENT,
+ OSSL_CMP_POLLREQ)
+ASN1_ITEM_TEMPLATE_END(OSSL_CMP_POLLREQCONTENT)
+
+ASN1_SEQUENCE(OSSL_CMP_POLLREP) = {
+ ASN1_SIMPLE(OSSL_CMP_POLLREP, certReqId, ASN1_INTEGER),
+ ASN1_SIMPLE(OSSL_CMP_POLLREP, checkAfter, ASN1_INTEGER),
+ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_POLLREP, reason, ASN1_UTF8STRING),
+} ASN1_SEQUENCE_END(OSSL_CMP_POLLREP)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_POLLREP)
+
+ASN1_ITEM_TEMPLATE(OSSL_CMP_POLLREPCONTENT) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0,
+ OSSL_CMP_POLLREPCONTENT,
+ OSSL_CMP_POLLREP)
+ASN1_ITEM_TEMPLATE_END(OSSL_CMP_POLLREPCONTENT)
+
+ASN1_SEQUENCE(OSSL_CMP_CERTREPMESSAGE) = {
+ /* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+ ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_CERTREPMESSAGE, caPubs, X509, 1),
+ ASN1_SEQUENCE_OF(OSSL_CMP_CERTREPMESSAGE, response, OSSL_CMP_CERTRESPONSE)
+} ASN1_SEQUENCE_END(OSSL_CMP_CERTREPMESSAGE)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CERTREPMESSAGE)
+
+ASN1_ITEM_TEMPLATE(OSSL_CMP_GENMSGCONTENT) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, OSSL_CMP_GENMSGCONTENT,
+ OSSL_CMP_ITAV)
+ASN1_ITEM_TEMPLATE_END(OSSL_CMP_GENMSGCONTENT)
+
+ASN1_ITEM_TEMPLATE(OSSL_CMP_GENREPCONTENT) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, OSSL_CMP_GENREPCONTENT,
+ OSSL_CMP_ITAV)
+ASN1_ITEM_TEMPLATE_END(OSSL_CMP_GENREPCONTENT)
+
+ASN1_ITEM_TEMPLATE(OSSL_CMP_CRLANNCONTENT) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0,
+ OSSL_CMP_CRLANNCONTENT, X509_CRL)
+ASN1_ITEM_TEMPLATE_END(OSSL_CMP_CRLANNCONTENT)
+
+ASN1_CHOICE(OSSL_CMP_PKIBODY) = {
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.ir, OSSL_CRMF_MSGS, 0),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.ip, OSSL_CMP_CERTREPMESSAGE, 1),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.cr, OSSL_CRMF_MSGS, 2),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.cp, OSSL_CMP_CERTREPMESSAGE, 3),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.p10cr, X509_REQ, 4),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.popdecc,
+ OSSL_CMP_POPODECKEYCHALLCONTENT, 5),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.popdecr,
+ OSSL_CMP_POPODECKEYRESPCONTENT, 6),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.kur, OSSL_CRMF_MSGS, 7),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.kup, OSSL_CMP_CERTREPMESSAGE, 8),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.krr, OSSL_CRMF_MSGS, 9),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.krp, OSSL_CMP_KEYRECREPCONTENT, 10),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.rr, OSSL_CMP_REVREQCONTENT, 11),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.rp, OSSL_CMP_REVREPCONTENT, 12),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.ccr, OSSL_CRMF_MSGS, 13),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.ccp, OSSL_CMP_CERTREPMESSAGE, 14),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.ckuann, OSSL_CMP_CAKEYUPDANNCONTENT, 15),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.cann, X509, 16),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.rann, OSSL_CMP_REVANNCONTENT, 17),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.crlann, OSSL_CMP_CRLANNCONTENT, 18),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.pkiconf, ASN1_ANY, 19),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.nested, OSSL_CMP_MSGS, 20),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.genm, OSSL_CMP_GENMSGCONTENT, 21),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.genp, OSSL_CMP_GENREPCONTENT, 22),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.error, OSSL_CMP_ERRORMSGCONTENT, 23),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.certConf, OSSL_CMP_CERTCONFIRMCONTENT, 24),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.pollReq, OSSL_CMP_POLLREQCONTENT, 25),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.pollRep, OSSL_CMP_POLLREPCONTENT, 26),
+} ASN1_CHOICE_END(OSSL_CMP_PKIBODY)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_PKIBODY)
+
+ASN1_SEQUENCE(OSSL_CMP_PKIHEADER) = {
+ ASN1_SIMPLE(OSSL_CMP_PKIHEADER, pvno, ASN1_INTEGER),
+ ASN1_SIMPLE(OSSL_CMP_PKIHEADER, sender, GENERAL_NAME),
+ ASN1_SIMPLE(OSSL_CMP_PKIHEADER, recipient, GENERAL_NAME),
+ ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, messageTime, ASN1_GENERALIZEDTIME, 0),
+ ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, protectionAlg, X509_ALGOR, 1),
+ ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, senderKID, ASN1_OCTET_STRING, 2),
+ ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, recipKID, ASN1_OCTET_STRING, 3),
+ ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, transactionID, ASN1_OCTET_STRING, 4),
+ ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, senderNonce, ASN1_OCTET_STRING, 5),
+ ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, recipNonce, ASN1_OCTET_STRING, 6),
+ /*
+ * OSSL_CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING
+ * so it is used directly
+ */
+ ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_PKIHEADER, freeText, ASN1_UTF8STRING, 7),
+ ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_PKIHEADER, generalInfo,
+ OSSL_CMP_ITAV, 8)
+} ASN1_SEQUENCE_END(OSSL_CMP_PKIHEADER)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_PKIHEADER)
+
+ASN1_SEQUENCE(OSSL_CMP_PROTECTEDPART) = {
+ ASN1_SIMPLE(OSSL_CMP_MSG, header, OSSL_CMP_PKIHEADER),
+ ASN1_SIMPLE(OSSL_CMP_MSG, body, OSSL_CMP_PKIBODY)
+} ASN1_SEQUENCE_END(OSSL_CMP_PROTECTEDPART)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_PROTECTEDPART)
+
+ASN1_SEQUENCE_cb(OSSL_CMP_MSG, ossl_cmp_msg_cb) = {
+ ASN1_SIMPLE(OSSL_CMP_MSG, header, OSSL_CMP_PKIHEADER),
+ ASN1_SIMPLE(OSSL_CMP_MSG, body, OSSL_CMP_PKIBODY),
+ ASN1_EXP_OPT(OSSL_CMP_MSG, protection, ASN1_BIT_STRING, 0),
+ /* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+ ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_MSG, extraCerts, X509, 1)
+} ASN1_SEQUENCE_END_cb(OSSL_CMP_MSG, OSSL_CMP_MSG)
+IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CMP_MSG)
+
+ASN1_ITEM_TEMPLATE(OSSL_CMP_MSGS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, OSSL_CMP_MSGS,
+ OSSL_CMP_MSG)
+ASN1_ITEM_TEMPLATE_END(OSSL_CMP_MSGS)
diff --git a/crypto/cmp/cmp_client.c b/crypto/cmp/cmp_client.c
new file mode 100644
index 000000000000..22ae7d07e82d
--- /dev/null
+++ b/crypto/cmp/cmp_client.c
@@ -0,0 +1,890 @@
+/*
+ * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "cmp_local.h"
+#include "internal/cryptlib.h"
+#include "e_os.h" /* ossl_sleep() */
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <openssl/bio.h>
+#include <openssl/cmp.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/x509v3.h>
+#include <openssl/cmp_util.h>
+
+#define IS_CREP(t) ((t) == OSSL_CMP_PKIBODY_IP || (t) == OSSL_CMP_PKIBODY_CP \
+ || (t) == OSSL_CMP_PKIBODY_KUP)
+
+/*-
+ * Evaluate whether there's an exception (violating the standard) configured for
+ * handling negative responses without protection or with invalid protection.
+ * Returns 1 on acceptance, 0 on rejection, or -1 on (internal) error.
+ */
+static int unprotected_exception(const OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *rep,
+ int invalid_protection,
+ int expected_type /* ignored here */)
+{
+ int rcvd_type = OSSL_CMP_MSG_get_bodytype(rep /* may be NULL */);
+ const char *msg_type = NULL;
+
+ if (!ossl_assert(ctx != NULL && rep != NULL))
+ return -1;
+
+ if (!ctx->unprotectedErrors)
+ return 0;
+
+ switch (rcvd_type) {
+ case OSSL_CMP_PKIBODY_ERROR:
+ msg_type = "error response";
+ break;
+ case OSSL_CMP_PKIBODY_RP:
+ {
+ OSSL_CMP_PKISI *si =
+ ossl_cmp_revrepcontent_get_pkisi(rep->body->value.rp,
+ OSSL_CMP_REVREQSID);
+
+ if (si == NULL)
+ return -1;
+ if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_rejection)
+ msg_type = "revocation response message with rejection status";
+ break;
+ }
+ case OSSL_CMP_PKIBODY_PKICONF:
+ msg_type = "PKI Confirmation message";
+ break;
+ default:
+ if (IS_CREP(rcvd_type)) {
+ OSSL_CMP_CERTREPMESSAGE *crepmsg = rep->body->value.ip;
+ OSSL_CMP_CERTRESPONSE *crep =
+ ossl_cmp_certrepmessage_get0_certresponse(crepmsg,
+ -1 /* any rid */);
+
+ if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1)
+ return -1;
+ if (crep == NULL)
+ return -1;
+ if (ossl_cmp_pkisi_get_status(crep->status)
+ == OSSL_CMP_PKISTATUS_rejection)
+ msg_type = "CertRepMessage with rejection status";
+ }
+ }
+ if (msg_type == NULL)
+ return 0;
+ ossl_cmp_log2(WARN, ctx, "ignoring %s protection of %s",
+ invalid_protection ? "invalid" : "missing", msg_type);
+ return 1;
+}
+
+/* Save error info from PKIStatusInfo field of a certresponse into ctx */
+static int save_statusInfo(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si)
+{
+ int i;
+ OSSL_CMP_PKIFREETEXT *ss;
+
+ if (!ossl_assert(ctx != NULL && si != NULL))
+ return 0;
+
+ ctx->status = ossl_cmp_pkisi_get_status(si);
+ if (ctx->status < OSSL_CMP_PKISTATUS_accepted)
+ return 0;
+
+ ctx->failInfoCode = ossl_cmp_pkisi_get_pkifailureinfo(si);
+
+ if (!ossl_cmp_ctx_set0_statusString(ctx, sk_ASN1_UTF8STRING_new_null())
+ || (ctx->statusString == NULL))
+ return 0;
+
+ ss = si->statusString; /* may be NULL */
+ for (i = 0; i < sk_ASN1_UTF8STRING_num(ss); i++) {
+ ASN1_UTF8STRING *str = sk_ASN1_UTF8STRING_value(ss, i);
+
+ if (!sk_ASN1_UTF8STRING_push(ctx->statusString, ASN1_STRING_dup(str)))
+ return 0;
+ }
+ return 1;
+}
+
+/*-
+ * Perform the generic aspects of sending a request and receiving a response.
+ * Returns 1 on success and provides the received PKIMESSAGE in *rep.
+ * Returns 0 on error.
+ * Regardless of success, caller is responsible for freeing *rep (unless NULL).
+ */
+static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
+ OSSL_CMP_MSG **rep, int expected_type)
+{
+ int begin_transaction =
+ expected_type != OSSL_CMP_PKIBODY_POLLREP
+ && expected_type != OSSL_CMP_PKIBODY_PKICONF;
+ const char *req_type_str =
+ ossl_cmp_bodytype_to_string(OSSL_CMP_MSG_get_bodytype(req));
+ const char *expected_type_str = ossl_cmp_bodytype_to_string(expected_type);
+ int bak_msg_timeout = ctx->msg_timeout;
+ int bt;
+ time_t now = time(NULL);
+ int time_left;
+ OSSL_CMP_transfer_cb_t transfer_cb = ctx->transfer_cb;
+
+ if (transfer_cb == NULL)
+ transfer_cb = OSSL_CMP_MSG_http_perform;
+ *rep = NULL;
+
+ if (ctx->total_timeout != 0 /* not waiting indefinitely */) {
+ if (begin_transaction)
+ ctx->end_time = now + ctx->total_timeout;
+ if (now >= ctx->end_time) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_TOTAL_TIMEOUT);
+ return 0;
+ }
+ if (!ossl_assert(ctx->end_time - now < INT_MAX)) {
+ /* actually cannot happen due to assignment in initial_certreq() */
+ ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
+ return 0;
+ }
+ time_left = (int)(ctx->end_time - now);
+ if (ctx->msg_timeout == 0 || time_left < ctx->msg_timeout)
+ ctx->msg_timeout = time_left;
+ }
+
+ /* should print error queue since transfer_cb may call ERR_clear_error() */
+ OSSL_CMP_CTX_print_errors(ctx);
+
+ ossl_cmp_log1(INFO, ctx, "sending %s", req_type_str);
+
+ *rep = (*transfer_cb)(ctx, req);
+ ctx->msg_timeout = bak_msg_timeout;
+
+ if (*rep == NULL) {
+ ERR_raise_data(ERR_LIB_CMP,
+ ctx->total_timeout != 0 && time(NULL) >= ctx->end_time ?
+ CMP_R_TOTAL_TIMEOUT : CMP_R_TRANSFER_ERROR,
+ "request sent: %s, expected response: %s",
+ req_type_str, expected_type_str);
+ return 0;
+ }
+
+ bt = OSSL_CMP_MSG_get_bodytype(*rep);
+ /*
+ * The body type in the 'bt' variable is not yet verified.
+ * Still we use this preliminary value already for a progress report because
+ * the following msg verification may also produce log entries and may fail.
+ */
+ ossl_cmp_log1(INFO, ctx, "received %s", ossl_cmp_bodytype_to_string(bt));
+
+ /* copy received extraCerts to ctx->extraCertsIn so they can be retrieved */
+ if (bt != OSSL_CMP_PKIBODY_POLLREP && bt != OSSL_CMP_PKIBODY_PKICONF
+ && !ossl_cmp_ctx_set1_extraCertsIn(ctx, (*rep)->extraCerts))
+ return 0;
+
+ if (!ossl_cmp_msg_check_update(ctx, *rep, unprotected_exception,
+ expected_type))
+ return 0;
+
+ if (bt == expected_type
+ /* as an answer to polling, there could be IP/CP/KUP: */
+ || (IS_CREP(bt) && expected_type == OSSL_CMP_PKIBODY_POLLREP))
+ return 1;
+
+ /* received message type is not one of the expected ones (e.g., error) */
+ ERR_raise(ERR_LIB_CMP, bt == OSSL_CMP_PKIBODY_ERROR ? CMP_R_RECEIVED_ERROR :
+ CMP_R_UNEXPECTED_PKIBODY); /* in next line for mkerr.pl */
+
+ if (bt != OSSL_CMP_PKIBODY_ERROR) {
+ ERR_add_error_data(3, "message type is '",
+ ossl_cmp_bodytype_to_string(bt), "'");
+ } else {
+ OSSL_CMP_ERRORMSGCONTENT *emc = (*rep)->body->value.error;
+ OSSL_CMP_PKISI *si = emc->pKIStatusInfo;
+ char buf[OSSL_CMP_PKISI_BUFLEN];
+
+ if (save_statusInfo(ctx, si)
+ && OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf,
+ sizeof(buf)) != NULL)
+ ERR_add_error_data(1, buf);
+ if (emc->errorCode != NULL
+ && BIO_snprintf(buf, sizeof(buf), "; errorCode: %08lX",
+ ASN1_INTEGER_get(emc->errorCode)) > 0)
+ ERR_add_error_data(1, buf);
+ if (emc->errorDetails != NULL) {
+ char *text = ossl_sk_ASN1_UTF8STRING2text(emc->errorDetails, ", ",
+ OSSL_CMP_PKISI_BUFLEN - 1);
+
+ if (text != NULL && *text != '\0')
+ ERR_add_error_data(2, "; errorDetails: ", text);
+ OPENSSL_free(text);
+ }
+ if (ctx->status != OSSL_CMP_PKISTATUS_rejection) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKISTATUS);
+ if (ctx->status == OSSL_CMP_PKISTATUS_waiting)
+ ctx->status = OSSL_CMP_PKISTATUS_rejection;
+ }
+ }
+ return 0;
+}
+
+/*-
+ * When a 'waiting' PKIStatus has been received, this function is used to
+ * poll, which should yield a pollRep or finally a CertRepMessage in ip/cp/kup.
+ * On receiving a pollRep, which includes a checkAfter value, it return this
+ * value if sleep == 0, else it sleeps as long as indicated and retries.
+ *
+ * A transaction timeout is enabled if ctx->total_timeout is != 0.
+ * In this case polling will continue until the timeout is reached and then
+ * polling is done a last time even if this is before the "checkAfter" time.
+ *
+ * Returns -1 on receiving pollRep if sleep == 0, setting the checkAfter value.
+ * Returns 1 on success and provides the received PKIMESSAGE in *rep.
+ * In this case the caller is responsible for freeing *rep.
+ * Returns 0 on error (which includes the case that timeout has been reached).
+ */
+static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
+ OSSL_CMP_MSG **rep, int *checkAfter)
+{
+ OSSL_CMP_MSG *preq = NULL;
+ OSSL_CMP_MSG *prep = NULL;
+
+ ossl_cmp_info(ctx,
+ "received 'waiting' PKIStatus, starting to poll for response");
+ *rep = NULL;
+ for (;;) {
+ if ((preq = ossl_cmp_pollReq_new(ctx, rid)) == NULL)
+ goto err;
+
+ if (!send_receive_check(ctx, preq, &prep, OSSL_CMP_PKIBODY_POLLREP))
+ goto err;
+
+ /* handle potential pollRep */
+ if (OSSL_CMP_MSG_get_bodytype(prep) == OSSL_CMP_PKIBODY_POLLREP) {
+ OSSL_CMP_POLLREPCONTENT *prc = prep->body->value.pollRep;
+ OSSL_CMP_POLLREP *pollRep = NULL;
+ int64_t check_after;
+ char str[OSSL_CMP_PKISI_BUFLEN];
+ int len;
+
+ if (sk_OSSL_CMP_POLLREP_num(prc) > 1) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED);
+ goto err;
+ }
+ pollRep = ossl_cmp_pollrepcontent_get0_pollrep(prc, rid);
+ if (pollRep == NULL)
+ goto err;
+
+ if (!ASN1_INTEGER_get_int64(&check_after, pollRep->checkAfter)) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_BAD_CHECKAFTER_IN_POLLREP);
+ goto err;
+ }
+ if (check_after < 0 || (uint64_t)check_after
+ > (sleep ? ULONG_MAX / 1000 : INT_MAX)) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_CHECKAFTER_OUT_OF_RANGE);
+ if (BIO_snprintf(str, OSSL_CMP_PKISI_BUFLEN, "value = %jd",
+ check_after) >= 0)
+ ERR_add_error_data(1, str);
+ goto err;
+ }
+
+ if (pollRep->reason == NULL
+ || (len = BIO_snprintf(str, OSSL_CMP_PKISI_BUFLEN,
+ " with reason = '")) < 0) {
+ *str = '\0';
+ } else {
+ char *text = ossl_sk_ASN1_UTF8STRING2text(pollRep->reason, ", ",
+ sizeof(str) - len - 2);
+
+ if (text == NULL
+ || BIO_snprintf(str + len, sizeof(str) - len,
+ "%s'", text) < 0)
+ *str = '\0';
+ OPENSSL_free(text);
+ }
+ ossl_cmp_log2(INFO, ctx,
+ "received polling response%s; checkAfter = %ld seconds",
+ str, check_after);
+
+ if (ctx->total_timeout != 0) { /* timeout is not infinite */
+ const int exp = 5; /* expected max time per msg round trip */
+ int64_t time_left = (int64_t)(ctx->end_time - exp - time(NULL));
+
+ if (time_left <= 0) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_TOTAL_TIMEOUT);
+ goto err;
+ }
+ if (time_left < check_after)
+ check_after = time_left;
+ /* poll one last time just when timeout was reached */
+ }
+
+ OSSL_CMP_MSG_free(preq);
+ preq = NULL;
+ OSSL_CMP_MSG_free(prep);
+ prep = NULL;
+ if (sleep) {
+ ossl_sleep((unsigned long)(1000 * check_after));
+ } else {
+ if (checkAfter != NULL)
+ *checkAfter = (int)check_after;
+ return -1; /* exits the loop */
+ }
+ } else {
+ ossl_cmp_info(ctx, "received ip/cp/kup after polling");
+ /* any other body type has been rejected by send_receive_check() */
+ break;
+ }
+ }
+ if (prep == NULL)
+ goto err;
+
+ OSSL_CMP_MSG_free(preq);
+ *rep = prep;
+
+ return 1;
+ err:
+ OSSL_CMP_MSG_free(preq);
+ OSSL_CMP_MSG_free(prep);
+ return 0;
+}
+
+/*
+ * Send certConf for IR, CR or KUR sequences and check response,
+ * not modifying ctx->status during the certConf exchange
+ */
+int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int fail_info,
+ const char *txt)
+{
+ OSSL_CMP_MSG *certConf;
+ OSSL_CMP_MSG *PKIconf = NULL;
+ int res = 0;
+
+ /* OSSL_CMP_certConf_new() also checks if all necessary options are set */
+ if ((certConf = ossl_cmp_certConf_new(ctx, fail_info, txt)) == NULL)
+ goto err;
+
+ res = send_receive_check(ctx, certConf, &PKIconf, OSSL_CMP_PKIBODY_PKICONF);
+
+ err:
+ OSSL_CMP_MSG_free(certConf);
+ OSSL_CMP_MSG_free(PKIconf);
+ return res;
+}
+
+/* Send given error and check response */
+int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info,
+ const char *txt, int errorCode, const char *details)
+{
+ OSSL_CMP_MSG *error = NULL;
+ OSSL_CMP_PKISI *si = NULL;
+ OSSL_CMP_MSG *PKIconf = NULL;
+ int res = 0;
+
+ /* not overwriting ctx->status on error exchange */
+ if ((si = OSSL_CMP_STATUSINFO_new(status, fail_info, txt)) == NULL)
+ goto err;
+ /* ossl_cmp_error_new() also checks if all necessary options are set */
+ if ((error = ossl_cmp_error_new(ctx, si, errorCode, details, 0)) == NULL)
+ goto err;
+
+ res = send_receive_check(ctx, error, &PKIconf, OSSL_CMP_PKIBODY_PKICONF);
+
+ err:
+ OSSL_CMP_MSG_free(error);
+ OSSL_CMP_PKISI_free(si);
+ OSSL_CMP_MSG_free(PKIconf);
+ return res;
+}
+
+/*-
+ * Retrieve a copy of the certificate, if any, from the given CertResponse.
+ * Take into account PKIStatusInfo of CertResponse in ctx, report it on error.
+ * Returns NULL if not found or on error.
+ */
+static X509 *get1_cert_status(OSSL_CMP_CTX *ctx, int bodytype,
+ OSSL_CMP_CERTRESPONSE *crep)
+{
+ char buf[OSSL_CMP_PKISI_BUFLEN];
+ X509 *crt = NULL;
+ EVP_PKEY *privkey;
+
+ if (!ossl_assert(ctx != NULL && crep != NULL))
+ return NULL;
+
+ privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
+ switch (ossl_cmp_pkisi_get_status(crep->status)) {
+ case OSSL_CMP_PKISTATUS_waiting:
+ ossl_cmp_err(ctx,
+ "received \"waiting\" status for cert when actually aiming to extract cert");
+ ERR_raise(ERR_LIB_CMP, CMP_R_ENCOUNTERED_WAITING);
+ goto err;
+ case OSSL_CMP_PKISTATUS_grantedWithMods:
+ ossl_cmp_warn(ctx, "received \"grantedWithMods\" for certificate");
+ break;
+ case OSSL_CMP_PKISTATUS_accepted:
+ break;
+ /* get all information in case of a rejection before going to error */
+ case OSSL_CMP_PKISTATUS_rejection:
+ ossl_cmp_err(ctx, "received \"rejection\" status rather than cert");
+ ERR_raise(ERR_LIB_CMP, CMP_R_REQUEST_REJECTED_BY_SERVER);
+ goto err;
+ case OSSL_CMP_PKISTATUS_revocationWarning:
+ ossl_cmp_warn(ctx,
+ "received \"revocationWarning\" - a revocation of the cert is imminent");
+ break;
+ case OSSL_CMP_PKISTATUS_revocationNotification:
+ ossl_cmp_warn(ctx,
+ "received \"revocationNotification\" - a revocation of the cert has occurred");
+ break;
+ case OSSL_CMP_PKISTATUS_keyUpdateWarning:
+ if (bodytype != OSSL_CMP_PKIBODY_KUR) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_ENCOUNTERED_KEYUPDATEWARNING);
+ goto err;
+ }
+ break;
+ default:
+ ossl_cmp_log1(ERROR, ctx,
+ "received unsupported PKIStatus %d for certificate",
+ ctx->status);
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_PKISTATUS);
+ goto err;
+ }
+ crt = ossl_cmp_certresponse_get1_cert(crep, ctx, privkey);
+ if (crt == NULL) /* according to PKIStatus, we can expect a cert */
+ ERR_raise(ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_FOUND);
+
+ return crt;
+
+ err:
+ if (OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, sizeof(buf)) != NULL)
+ ERR_add_error_data(1, buf);
+ return NULL;
+}
+
+/*-
+ * Callback fn validating that the new certificate can be verified, using
+ * ctx->certConf_cb_arg, which has been initialized using opt_out_trusted, and
+ * ctx->untrusted, which at this point already contains msg->extraCerts.
+ * Returns 0 on acceptance, else a bit field reflecting PKIFailureInfo.
+ * Quoting from RFC 4210 section 5.1. Overall PKI Message:
+ * The extraCerts field can contain certificates that may be useful to
+ * the recipient. For example, this can be used by a CA or RA to
+ * present an end entity with certificates that it needs to verify its
+ * own new certificate (if, for example, the CA that issued the end
+ * entity's certificate is not a root CA for the end entity). Note that
+ * this field does not necessarily contain a certification path; the
+ * recipient may have to sort, select from, or otherwise process the
+ * extra certificates in order to use them.
+ * Note: While often handy, there is no hard requirement by CMP that
+ * an EE must be able to validate the certificates it gets enrolled.
+ */
+int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
+ const char **text)
+{
+ X509_STORE *out_trusted = OSSL_CMP_CTX_get_certConf_cb_arg(ctx);
+ STACK_OF(X509) *chain = NULL;
+ (void)text; /* make (artificial) use of var to prevent compiler warning */
+
+ if (fail_info != 0) /* accept any error flagged by CMP core library */
+ return fail_info;
+
+ ossl_cmp_debug(ctx, "trying to build chain for newly enrolled cert");
+ chain = X509_build_chain(cert, ctx->untrusted, out_trusted /* maybe NULL */,
+ 0, ctx->libctx, ctx->propq);
+ if (sk_X509_num(chain) > 0)
+ X509_free(sk_X509_shift(chain)); /* remove leaf (EE) cert */
+ if (out_trusted != NULL) {
+ if (chain == NULL) {
+ ossl_cmp_err(ctx, "failed building chain for newly enrolled cert");
+ fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_incorrectData;
+ } else {
+ ossl_cmp_debug(ctx,
+ "succeeded building proper chain for newly enrolled cert");
+ }
+ } else if (chain == NULL) {
+ ossl_cmp_warn(ctx, "could not build approximate chain for newly enrolled cert, resorting to received extraCerts");
+ chain = OSSL_CMP_CTX_get1_extraCertsIn(ctx);
+ } else {
+ ossl_cmp_debug(ctx,
+ "success building approximate chain for newly enrolled cert");
+ }
+ (void)ossl_cmp_ctx_set1_newChain(ctx, chain);
+ sk_X509_pop_free(chain, X509_free);
+
+ return fail_info;
+}
+
+/*-
+ * Perform the generic handling of certificate responses for IR/CR/KUR/P10CR.
+ * Returns -1 on receiving pollRep if sleep == 0, setting the checkAfter value.
+ * Returns 1 on success and provides the received PKIMESSAGE in *resp.
+ * Returns 0 on error (which includes the case that timeout has been reached).
+ * Regardless of success, caller is responsible for freeing *resp (unless NULL).
+ */
+static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
+ OSSL_CMP_MSG **resp, int *checkAfter,
+ int req_type, int expected_type)
+{
+ EVP_PKEY *rkey = OSSL_CMP_CTX_get0_newPkey(ctx /* may be NULL */, 0);
+ int fail_info = 0; /* no failure */
+ const char *txt = NULL;
+ OSSL_CMP_CERTREPMESSAGE *crepmsg;
+ OSSL_CMP_CERTRESPONSE *crep;
+ OSSL_CMP_certConf_cb_t cb;
+ X509 *cert;
+ char *subj = NULL;
+ int ret = 1;
+
+ if (!ossl_assert(ctx != NULL))
+ return 0;
+
+ retry:
+ crepmsg = (*resp)->body->value.ip; /* same for cp and kup */
+ if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED);
+ return 0;
+ }
+ crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid);
+ if (crep == NULL)
+ return 0;
+ if (!save_statusInfo(ctx, crep->status))
+ return 0;
+ if (rid == -1) {
+ /* for OSSL_CMP_PKIBODY_P10CR learn CertReqId from response */
+ rid = ossl_cmp_asn1_get_int(crep->certReqId);
+ if (rid == -1) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
+ return 0;
+ }
+ }
+
+ if (ossl_cmp_pkisi_get_status(crep->status) == OSSL_CMP_PKISTATUS_waiting) {
+ OSSL_CMP_MSG_free(*resp);
+ *resp = NULL;
+ if ((ret = poll_for_response(ctx, sleep, rid, resp, checkAfter)) != 0) {
+ if (ret == -1) /* at this point implies sleep == 0 */
+ return ret; /* waiting */
+ goto retry; /* got ip/cp/kup, which may still indicate 'waiting' */
+ } else {
+ ERR_raise(ERR_LIB_CMP, CMP_R_POLLING_FAILED);
+ return 0;
+ }
+ }
+
+ cert = get1_cert_status(ctx, (*resp)->body->type, crep);
+ if (cert == NULL) {
+ ERR_add_error_data(1, "; cannot extract certificate from response");
+ return 0;
+ }
+ if (!ossl_cmp_ctx_set0_newCert(ctx, cert))
+ return 0;
+
+ /*
+ * if the CMP server returned certificates in the caPubs field, copy them
+ * to the context so that they can be retrieved if necessary
+ */
+ if (crepmsg->caPubs != NULL
+ && !ossl_cmp_ctx_set1_caPubs(ctx, crepmsg->caPubs))
+ return 0;
+
+ subj = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
+ if (rkey != NULL
+ /* X509_check_private_key() also works if rkey is just public key */
+ && !(X509_check_private_key(ctx->newCert, rkey))) {
+ fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_incorrectData;
+ txt = "public key in new certificate does not match our enrollment key";
+ /*-
+ * not calling (void)ossl_cmp_exchange_error(ctx,
+ * OSSL_CMP_PKISTATUS_rejection, fail_info, txt)
+ * not throwing CMP_R_CERTIFICATE_NOT_ACCEPTED with txt
+ * not returning 0
+ * since we better leave this for the certConf_cb to decide
+ */
+ }
+
+ /*
+ * Execute the certification checking callback function,
+ * which can determine whether to accept a newly enrolled certificate.
+ * It may overrule the pre-decision reflected in 'fail_info' and '*txt'.
+ */
+ cb = ctx->certConf_cb != NULL ? ctx->certConf_cb : OSSL_CMP_certConf_cb;
+ if ((fail_info = cb(ctx, ctx->newCert, fail_info, &txt)) != 0
+ && txt == NULL)
+ txt = "CMP client did not accept it";
+ if (fail_info != 0) /* immediately log error before any certConf exchange */
+ ossl_cmp_log1(ERROR, ctx,
+ "rejecting newly enrolled cert with subject: %s", subj);
+ if (!ctx->disableConfirm
+ && !ossl_cmp_hdr_has_implicitConfirm((*resp)->header)) {
+ if (!ossl_cmp_exchange_certConf(ctx, fail_info, txt))
+ ret = 0;
+ }
+
+ /* not throwing failure earlier as transfer_cb may call ERR_clear_error() */
+ if (fail_info != 0) {
+ ERR_raise_data(ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_ACCEPTED,
+ "rejecting newly enrolled cert with subject: %s; %s",
+ subj, txt);
+ ret = 0;
+ }
+ OPENSSL_free(subj);
+ return ret;
+}
+
+static int initial_certreq(OSSL_CMP_CTX *ctx,
+ int req_type, const OSSL_CRMF_MSG *crm,
+ OSSL_CMP_MSG **p_rep, int rep_type)
+{
+ OSSL_CMP_MSG *req;
+ int res;
+
+ ctx->status = OSSL_CMP_PKISTATUS_request;
+ if (!ossl_cmp_ctx_set0_newCert(ctx, NULL))
+ return 0;
+
+ /* also checks if all necessary options are set */
+ if ((req = ossl_cmp_certreq_new(ctx, req_type, crm)) == NULL)
+ return 0;
+
+ ctx->status = OSSL_CMP_PKISTATUS_trans;
+ res = send_receive_check(ctx, req, p_rep, rep_type);
+ OSSL_CMP_MSG_free(req);
+ return res;
+}
+
+int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type,
+ const OSSL_CRMF_MSG *crm, int *checkAfter)
+{
+ OSSL_CMP_MSG *rep = NULL;
+ int is_p10 = req_type == OSSL_CMP_PKIBODY_P10CR;
+ int rid = is_p10 ? -1 : OSSL_CMP_CERTREQID;
+ int rep_type = is_p10 ? OSSL_CMP_PKIBODY_CP : req_type + 1;
+ int res = 0;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (ctx->status != OSSL_CMP_PKISTATUS_waiting) { /* not polling already */
+ if (!initial_certreq(ctx, req_type, crm, &rep, rep_type))
+ goto err;
+ } else {
+ if (req_type < 0)
+ return ossl_cmp_exchange_error(ctx, OSSL_CMP_PKISTATUS_rejection,
+ 0, "polling aborted",
+ 0 /* errorCode */, "by application");
+ res = poll_for_response(ctx, 0 /* no sleep */, rid, &rep, checkAfter);
+ if (res <= 0) /* waiting or error */
+ return res;
+ }
+ res = cert_response(ctx, 0 /* no sleep */, rid, &rep, checkAfter,
+ req_type, rep_type);
+
+ err:
+ OSSL_CMP_MSG_free(rep);
+ return res;
+}
+
+/*-
+ * Do the full sequence CR/IR/KUR/P10CR, CP/IP/KUP/CP,
+ * certConf, PKIconf, and polling if required.
+ * Will sleep as long as indicated by the server (according to checkAfter).
+ * All enrollment options need to be present in the context.
+ * Returns pointer to received certificate, or NULL if none was received.
+ */
+X509 *OSSL_CMP_exec_certreq(OSSL_CMP_CTX *ctx, int req_type,
+ const OSSL_CRMF_MSG *crm)
+{
+
+ OSSL_CMP_MSG *rep = NULL;
+ int is_p10 = req_type == OSSL_CMP_PKIBODY_P10CR;
+ int rid = is_p10 ? -1 : OSSL_CMP_CERTREQID;
+ int rep_type = is_p10 ? OSSL_CMP_PKIBODY_CP : req_type + 1;
+ X509 *result = NULL;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+
+ if (!initial_certreq(ctx, req_type, crm, &rep, rep_type))
+ goto err;
+
+ if (cert_response(ctx, 1 /* sleep */, rid, &rep, NULL, req_type, rep_type)
+ <= 0)
+ goto err;
+
+ result = ctx->newCert;
+ err:
+ OSSL_CMP_MSG_free(rep);
+ return result;
+}
+
+int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx)
+{
+ OSSL_CMP_MSG *rr = NULL;
+ OSSL_CMP_MSG *rp = NULL;
+ const int num_RevDetails = 1;
+ const int rsid = OSSL_CMP_REVREQSID;
+ OSSL_CMP_REVREPCONTENT *rrep = NULL;
+ OSSL_CMP_PKISI *si = NULL;
+ char buf[OSSL_CMP_PKISI_BUFLEN];
+ int ret = 0;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
+ return 0;
+ }
+ ctx->status = OSSL_CMP_PKISTATUS_request;
+ if (ctx->oldCert == NULL && ctx->p10CSR == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_REFERENCE_CERT);
+ return 0;
+ }
+
+ /* OSSL_CMP_rr_new() also checks if all necessary options are set */
+ if ((rr = ossl_cmp_rr_new(ctx)) == NULL)
+ goto end;
+
+ ctx->status = OSSL_CMP_PKISTATUS_trans;
+ if (!send_receive_check(ctx, rr, &rp, OSSL_CMP_PKIBODY_RP))
+ goto end;
+
+ rrep = rp->body->value.rp;
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ if (sk_OSSL_CMP_PKISI_num(rrep->status) != num_RevDetails) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_RP_COMPONENT_COUNT);
+ goto end;
+ }
+#else
+ if (sk_OSSL_CMP_PKISI_num(rrep->status) < 1) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_RP_COMPONENT_COUNT);
+ goto end;
+ }
+#endif
+
+ /* evaluate PKIStatus field */
+ si = ossl_cmp_revrepcontent_get_pkisi(rrep, rsid);
+ if (!save_statusInfo(ctx, si))
+ goto err;
+ switch (ossl_cmp_pkisi_get_status(si)) {
+ case OSSL_CMP_PKISTATUS_accepted:
+ ossl_cmp_info(ctx, "revocation accepted (PKIStatus=accepted)");
+ ret = 1;
+ break;
+ case OSSL_CMP_PKISTATUS_grantedWithMods:
+ ossl_cmp_info(ctx, "revocation accepted (PKIStatus=grantedWithMods)");
+ ret = 1;
+ break;
+ case OSSL_CMP_PKISTATUS_rejection:
+ ERR_raise(ERR_LIB_CMP, CMP_R_REQUEST_REJECTED_BY_SERVER);
+ goto err;
+ case OSSL_CMP_PKISTATUS_revocationWarning:
+ ossl_cmp_info(ctx, "revocation accepted (PKIStatus=revocationWarning)");
+ ret = 1;
+ break;
+ case OSSL_CMP_PKISTATUS_revocationNotification:
+ /* interpretation as warning or error depends on CA */
+ ossl_cmp_warn(ctx,
+ "revocation accepted (PKIStatus=revocationNotification)");
+ ret = 1;
+ break;
+ case OSSL_CMP_PKISTATUS_waiting:
+ case OSSL_CMP_PKISTATUS_keyUpdateWarning:
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKISTATUS);
+ goto err;
+ default:
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_PKISTATUS);
+ goto err;
+ }
+
+ /* check any present CertId in optional revCerts field */
+ if (sk_OSSL_CRMF_CERTID_num(rrep->revCerts) >= 1) {
+ OSSL_CRMF_CERTID *cid;
+ OSSL_CRMF_CERTTEMPLATE *tmpl =
+ sk_OSSL_CMP_REVDETAILS_value(rr->body->value.rr, rsid)->certDetails;
+ const X509_NAME *issuer = OSSL_CRMF_CERTTEMPLATE_get0_issuer(tmpl);
+ const ASN1_INTEGER *serial = OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(tmpl);
+
+ if (sk_OSSL_CRMF_CERTID_num(rrep->revCerts) != num_RevDetails) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_RP_COMPONENT_COUNT);
+ ret = 0;
+ goto err;
+ }
+ if ((cid = ossl_cmp_revrepcontent_get_CertId(rrep, rsid)) == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_CERTID);
+ ret = 0;
+ goto err;
+ }
+ if (X509_NAME_cmp(issuer, OSSL_CRMF_CERTID_get0_issuer(cid)) != 0) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_CERTID_IN_RP);
+ ret = 0;
+ goto err;
+#endif
+ }
+ if (ASN1_INTEGER_cmp(serial,
+ OSSL_CRMF_CERTID_get0_serialNumber(cid)) != 0) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_SERIAL_IN_RP);
+ ret = 0;
+ goto err;
+#endif
+ }
+ }
+
+ /* check number of any optionally present crls */
+ if (rrep->crls != NULL && sk_X509_CRL_num(rrep->crls) != num_RevDetails) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_RP_COMPONENT_COUNT);
+ ret = 0;
+ goto err;
+ }
+
+ err:
+ if (ret == 0
+ && OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, sizeof(buf)) != NULL)
+ ERR_add_error_data(1, buf);
+
+ end:
+ OSSL_CMP_MSG_free(rr);
+ OSSL_CMP_MSG_free(rp);
+ return ret;
+}
+
+STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx)
+{
+ OSSL_CMP_MSG *genm;
+ OSSL_CMP_MSG *genp = NULL;
+ STACK_OF(OSSL_CMP_ITAV) *itavs = NULL;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
+ return NULL;
+ }
+ ctx->status = OSSL_CMP_PKISTATUS_request;
+
+ if ((genm = ossl_cmp_genm_new(ctx)) == NULL)
+ goto err;
+
+ ctx->status = OSSL_CMP_PKISTATUS_trans;
+ if (!send_receive_check(ctx, genm, &genp, OSSL_CMP_PKIBODY_GENP))
+ goto err;
+ ctx->status = OSSL_CMP_PKISTATUS_accepted;
+
+ itavs = genp->body->value.genp;
+ if (itavs == NULL)
+ itavs = sk_OSSL_CMP_ITAV_new_null();
+ /* received stack of itavs not to be freed with the genp */
+ genp->body->value.genp = NULL;
+
+ err:
+ OSSL_CMP_MSG_free(genm);
+ OSSL_CMP_MSG_free(genp);
+
+ return itavs; /* NULL indicates error case */
+}
diff --git a/crypto/cmp/cmp_ctx.c b/crypto/cmp/cmp_ctx.c
new file mode 100644
index 000000000000..4b610b746e45
--- /dev/null
+++ b/crypto/cmp/cmp_ctx.c
@@ -0,0 +1,1157 @@
+/*
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/trace.h>
+#include <openssl/bio.h>
+#include <openssl/ocsp.h> /* for OCSP_REVOKED_STATUS_* */
+
+#include "cmp_local.h"
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <openssl/cmp.h>
+#include <openssl/crmf.h>
+#include <openssl/err.h>
+
+/*
+ * Get current certificate store containing trusted root CA certs
+ */
+X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return ctx->trusted;
+}
+
+/*
+ * Set certificate store containing trusted (root) CA certs and possibly CRLs
+ * and a cert verification callback function used for CMP server authentication.
+ * Any already existing store entry is freed. Given NULL, the entry is reset.
+ */
+int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ X509_STORE_free(ctx->trusted);
+ ctx->trusted = store;
+ return 1;
+}
+
+/* Get current list of non-trusted intermediate certs */
+STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted(const OSSL_CMP_CTX *ctx)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return ctx->untrusted;
+}
+
+/*
+ * Set untrusted certificates for path construction in authentication of
+ * the CMP server and potentially others (TLS server, newly enrolled cert).
+ */
+int OSSL_CMP_CTX_set1_untrusted(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs)
+{
+ STACK_OF(X509) *untrusted = NULL;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (!ossl_x509_add_certs_new(&untrusted, certs,
+ X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
+ goto err;
+ sk_X509_pop_free(ctx->untrusted, X509_free);
+ ctx->untrusted = untrusted;
+ return 1;
+ err:
+ sk_X509_pop_free(untrusted, X509_free);
+ return 0;
+}
+
+static int cmp_ctx_set_md(OSSL_CMP_CTX *ctx, EVP_MD **pmd, int nid)
+{
+ EVP_MD *md = EVP_MD_fetch(ctx->libctx, OBJ_nid2sn(nid), ctx->propq);
+ /* fetching in advance to be able to throw error early if unsupported */
+
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_ALGORITHM);
+ return 0;
+ }
+ EVP_MD_free(*pmd);
+ *pmd = md;
+ return 1;
+}
+
+/*
+ * Allocates and initializes OSSL_CMP_CTX context structure with default values.
+ * Returns new context on success, NULL on error
+ */
+OSSL_CMP_CTX *OSSL_CMP_CTX_new(OSSL_LIB_CTX *libctx, const char *propq)
+{
+ OSSL_CMP_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx == NULL)
+ goto err;
+
+ ctx->libctx = libctx;
+ if (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL)
+ goto oom;
+
+ ctx->log_verbosity = OSSL_CMP_LOG_INFO;
+
+ ctx->status = OSSL_CMP_PKISTATUS_unspecified;
+ ctx->failInfoCode = -1;
+
+ ctx->keep_alive = 1;
+ ctx->msg_timeout = -1;
+
+ if ((ctx->untrusted = sk_X509_new_null()) == NULL)
+ goto oom;
+
+ ctx->pbm_slen = 16;
+ if (!cmp_ctx_set_md(ctx, &ctx->pbm_owf, NID_sha256))
+ goto err;
+ ctx->pbm_itercnt = 500;
+ ctx->pbm_mac = NID_hmac_sha1;
+
+ if (!cmp_ctx_set_md(ctx, &ctx->digest, NID_sha256))
+ goto err;
+ ctx->popoMethod = OSSL_CRMF_POPO_SIGNATURE;
+ ctx->revocationReason = CRL_REASON_NONE;
+
+ /* all other elements are initialized to 0 or NULL, respectively */
+ return ctx;
+
+ oom:
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
+ err:
+ OSSL_CMP_CTX_free(ctx);
+ return NULL;
+}
+
+#define OSSL_CMP_ITAVs_free(itavs) \
+ sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free);
+#define X509_EXTENSIONS_free(exts) \
+ sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free)
+#define OSSL_CMP_PKIFREETEXT_free(text) \
+ sk_ASN1_UTF8STRING_pop_free(text, ASN1_UTF8STRING_free)
+
+/* Prepare the OSSL_CMP_CTX for next use, partly re-initializing OSSL_CMP_CTX */
+int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (ctx->http_ctx != NULL) {
+ (void)OSSL_HTTP_close(ctx->http_ctx, 1);
+ ossl_cmp_debug(ctx, "disconnected from CMP server");
+ ctx->http_ctx = NULL;
+ }
+ ctx->status = OSSL_CMP_PKISTATUS_unspecified;
+ ctx->failInfoCode = -1;
+
+ OSSL_CMP_ITAVs_free(ctx->genm_ITAVs);
+ ctx->genm_ITAVs = NULL;
+
+ return ossl_cmp_ctx_set0_statusString(ctx, NULL)
+ && ossl_cmp_ctx_set0_newCert(ctx, NULL)
+ && ossl_cmp_ctx_set1_newChain(ctx, NULL)
+ && ossl_cmp_ctx_set1_caPubs(ctx, NULL)
+ && ossl_cmp_ctx_set1_extraCertsIn(ctx, NULL)
+ && ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL)
+ && OSSL_CMP_CTX_set1_transactionID(ctx, NULL)
+ && OSSL_CMP_CTX_set1_senderNonce(ctx, NULL)
+ && ossl_cmp_ctx_set1_recipNonce(ctx, NULL);
+}
+
+/* Frees OSSL_CMP_CTX variables allocated in OSSL_CMP_CTX_new() */
+void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ if (ctx->http_ctx != NULL) {
+ (void)OSSL_HTTP_close(ctx->http_ctx, 1);
+ ossl_cmp_debug(ctx, "disconnected from CMP server");
+ }
+ OPENSSL_free(ctx->propq);
+ OPENSSL_free(ctx->serverPath);
+ OPENSSL_free(ctx->server);
+ OPENSSL_free(ctx->proxy);
+ OPENSSL_free(ctx->no_proxy);
+
+ X509_free(ctx->srvCert);
+ X509_free(ctx->validatedSrvCert);
+ X509_NAME_free(ctx->expected_sender);
+ X509_STORE_free(ctx->trusted);
+ sk_X509_pop_free(ctx->untrusted, X509_free);
+
+ X509_free(ctx->cert);
+ sk_X509_pop_free(ctx->chain, X509_free);
+ EVP_PKEY_free(ctx->pkey);
+ ASN1_OCTET_STRING_free(ctx->referenceValue);
+ if (ctx->secretValue != NULL)
+ OPENSSL_cleanse(ctx->secretValue->data, ctx->secretValue->length);
+ ASN1_OCTET_STRING_free(ctx->secretValue);
+ EVP_MD_free(ctx->pbm_owf);
+
+ X509_NAME_free(ctx->recipient);
+ EVP_MD_free(ctx->digest);
+ ASN1_OCTET_STRING_free(ctx->transactionID);
+ ASN1_OCTET_STRING_free(ctx->senderNonce);
+ ASN1_OCTET_STRING_free(ctx->recipNonce);
+ sk_OSSL_CMP_ITAV_pop_free(ctx->geninfo_ITAVs, OSSL_CMP_ITAV_free);
+ sk_X509_pop_free(ctx->extraCertsOut, X509_free);
+
+ EVP_PKEY_free(ctx->newPkey);
+ X509_NAME_free(ctx->issuer);
+ X509_NAME_free(ctx->subjectName);
+ sk_GENERAL_NAME_pop_free(ctx->subjectAltNames, GENERAL_NAME_free);
+ sk_X509_EXTENSION_pop_free(ctx->reqExtensions, X509_EXTENSION_free);
+ sk_POLICYINFO_pop_free(ctx->policies, POLICYINFO_free);
+ X509_free(ctx->oldCert);
+ X509_REQ_free(ctx->p10CSR);
+
+ sk_OSSL_CMP_ITAV_pop_free(ctx->genm_ITAVs, OSSL_CMP_ITAV_free);
+
+ sk_ASN1_UTF8STRING_pop_free(ctx->statusString, ASN1_UTF8STRING_free);
+ X509_free(ctx->newCert);
+ sk_X509_pop_free(ctx->newChain, X509_free);
+ sk_X509_pop_free(ctx->caPubs, X509_free);
+ sk_X509_pop_free(ctx->extraCertsIn, X509_free);
+
+ OPENSSL_free(ctx);
+}
+
+int ossl_cmp_ctx_set_status(OSSL_CMP_CTX *ctx, int status)
+{
+ if (!ossl_assert(ctx != NULL))
+ return 0;
+ ctx->status = status;
+ return 1;
+}
+
+/*
+ * Returns the PKIStatus from the last CertRepMessage
+ * or Revocation Response or error message, -1 on error
+ */
+int OSSL_CMP_CTX_get_status(const OSSL_CMP_CTX *ctx)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return -1;
+ }
+ return ctx->status;
+}
+
+/*
+ * Returns the statusString from the last CertRepMessage
+ * or Revocation Response or error message, NULL on error
+ */
+OSSL_CMP_PKIFREETEXT *OSSL_CMP_CTX_get0_statusString(const OSSL_CMP_CTX *ctx)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return ctx->statusString;
+}
+
+int ossl_cmp_ctx_set0_statusString(OSSL_CMP_CTX *ctx,
+ OSSL_CMP_PKIFREETEXT *text)
+{
+ if (!ossl_assert(ctx != NULL))
+ return 0;
+ sk_ASN1_UTF8STRING_pop_free(ctx->statusString, ASN1_UTF8STRING_free);
+ ctx->statusString = text;
+ return 1;
+}
+
+int ossl_cmp_ctx_set0_validatedSrvCert(OSSL_CMP_CTX *ctx, X509 *cert)
+{
+ if (!ossl_assert(ctx != NULL))
+ return 0;
+ X509_free(ctx->validatedSrvCert);
+ ctx->validatedSrvCert = cert;
+ return 1;
+}
+
+/* Set callback function for checking if the cert is ok or should be rejected */
+int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_certConf_cb_t cb)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ ctx->certConf_cb = cb;
+ return 1;
+}
+
+/*
+ * Set argument, respectively a pointer to a structure containing arguments,
+ * optionally to be used by the certConf callback.
+ */
+int OSSL_CMP_CTX_set_certConf_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ ctx->certConf_cb_arg = arg;
+ return 1;
+}
+
+/*
+ * Get argument, respectively the pointer to a structure containing arguments,
+ * optionally to be used by certConf callback.
+ * Returns callback argument set previously (NULL if not set or on error)
+ */
+void *OSSL_CMP_CTX_get_certConf_cb_arg(const OSSL_CMP_CTX *ctx)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return ctx->certConf_cb_arg;
+}
+
+#ifndef OPENSSL_NO_TRACE
+static size_t ossl_cmp_log_trace_cb(const char *buf, size_t cnt,
+ int category, int cmd, void *vdata)
+{
+ OSSL_CMP_CTX *ctx = vdata;
+ const char *msg;
+ OSSL_CMP_severity level = -1;
+ char *func = NULL;
+ char *file = NULL;
+ int line = 0;
+
+ if (buf == NULL || cnt == 0 || cmd != OSSL_TRACE_CTRL_WRITE || ctx == NULL)
+ return 0;
+ if (ctx->log_cb == NULL)
+ return 1; /* silently drop message */
+
+ msg = ossl_cmp_log_parse_metadata(buf, &level, &func, &file, &line);
+
+ if (level > ctx->log_verbosity) /* excludes the case level is unknown */
+ goto end; /* suppress output since severity is not sufficient */
+
+ if (!ctx->log_cb(func != NULL ? func : "(no func)",
+ file != NULL ? file : "(no file)",
+ line, level, msg))
+ cnt = 0;
+
+ end:
+ OPENSSL_free(func);
+ OPENSSL_free(file);
+ return cnt;
+}
+#endif
+
+/* Print CMP log messages (i.e., diagnostic info) via the log cb of the ctx */
+int ossl_cmp_print_log(OSSL_CMP_severity level, const OSSL_CMP_CTX *ctx,
+ const char *func, const char *file, int line,
+ const char *level_str, const char *format, ...)
+{
+ va_list args;
+ char hugebuf[1024 * 2];
+ int res = 0;
+
+ if (ctx == NULL || ctx->log_cb == NULL)
+ return 1; /* silently drop message */
+
+ if (level > ctx->log_verbosity) /* excludes the case level is unknown */
+ return 1; /* suppress output since severity is not sufficient */
+
+ if (format == NULL)
+ return 0;
+
+ va_start(args, format);
+
+ if (func == NULL)
+ func = "(unset function name)";
+ if (file == NULL)
+ file = "(unset file name)";
+ if (level_str == NULL)
+ level_str = "(unset level string)";
+
+#ifndef OPENSSL_NO_TRACE
+ if (OSSL_TRACE_ENABLED(CMP)) {
+ OSSL_TRACE_BEGIN(CMP) {
+ int printed =
+ BIO_snprintf(hugebuf, sizeof(hugebuf),
+ "%s:%s:%d:" OSSL_CMP_LOG_PREFIX "%s: ",
+ func, file, line, level_str);
+ if (printed > 0 && (size_t)printed < sizeof(hugebuf)) {
+ if (BIO_vsnprintf(hugebuf + printed,
+ sizeof(hugebuf) - printed, format, args) > 0)
+ res = BIO_puts(trc_out, hugebuf) > 0;
+ }
+ } OSSL_TRACE_END(CMP);
+ }
+#else /* compensate for disabled trace API */
+ {
+ if (BIO_vsnprintf(hugebuf, sizeof(hugebuf), format, args) > 0)
+ res = ctx->log_cb(func, file, line, level, hugebuf);
+ }
+#endif
+ va_end(args);
+ return res;
+}
+
+/* Set a callback function for error reporting and logging messages */
+int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_log_cb_t cb)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ ctx->log_cb = cb;
+
+#ifndef OPENSSL_NO_TRACE
+ /* do also in case cb == NULL, to switch off logging output: */
+ if (!OSSL_trace_set_callback(OSSL_TRACE_CATEGORY_CMP,
+ ossl_cmp_log_trace_cb, ctx))
+ return 0;
+#endif
+
+ return 1;
+}
+
+/* Print OpenSSL and CMP errors via the log cb of the ctx or ERR_print_errors */
+void OSSL_CMP_CTX_print_errors(const OSSL_CMP_CTX *ctx)
+{
+ if (ctx != NULL && OSSL_CMP_LOG_ERR > ctx->log_verbosity)
+ return; /* suppress output since severity is not sufficient */
+ OSSL_CMP_print_errors_cb(ctx == NULL ? NULL : ctx->log_cb);
+}
+
+/*
+ * Set or clear the reference value to be used for identification
+ * (i.e., the user name) when using PBMAC.
+ */
+int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx,
+ const unsigned char *ref, int len)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ return ossl_cmp_asn1_octet_string_set1_bytes(&ctx->referenceValue, ref,
+ len);
+}
+
+/* Set or clear the password to be used for protecting messages with PBMAC */
+int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx, const unsigned char *sec,
+ const int len)
+{
+ ASN1_OCTET_STRING *secretValue = NULL;
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (ossl_cmp_asn1_octet_string_set1_bytes(&secretValue, sec, len) != 1)
+ return 0;
+ if (ctx->secretValue != NULL) {
+ OPENSSL_cleanse(ctx->secretValue->data, ctx->secretValue->length);
+ ASN1_OCTET_STRING_free(ctx->secretValue);
+ }
+ ctx->secretValue = secretValue;
+ return 1;
+}
+
+/* Returns the cert chain computed by OSSL_CMP_certConf_cb(), NULL on error */
+STACK_OF(X509) *OSSL_CMP_CTX_get1_newChain(const OSSL_CMP_CTX *ctx)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return X509_chain_up_ref(ctx->newChain);
+}
+
+/*
+ * Copies any given stack of inbound X509 certificates to newChain
+ * of the OSSL_CMP_CTX structure so that they may be retrieved later.
+ */
+int ossl_cmp_ctx_set1_newChain(OSSL_CMP_CTX *ctx, STACK_OF(X509) *newChain)
+{
+ if (!ossl_assert(ctx != NULL))
+ return 0;
+
+ sk_X509_pop_free(ctx->newChain, X509_free);
+ ctx->newChain = NULL;
+ return newChain == NULL ||
+ (ctx->newChain = X509_chain_up_ref(newChain)) != NULL;
+}
+
+/* Returns the stack of extraCerts received in CertRepMessage, NULL on error */
+STACK_OF(X509) *OSSL_CMP_CTX_get1_extraCertsIn(const OSSL_CMP_CTX *ctx)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return X509_chain_up_ref(ctx->extraCertsIn);
+}
+
+/*
+ * Copies any given stack of inbound X509 certificates to extraCertsIn
+ * of the OSSL_CMP_CTX structure so that they may be retrieved later.
+ */
+int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx,
+ STACK_OF(X509) *extraCertsIn)
+{
+ if (!ossl_assert(ctx != NULL))
+ return 0;
+
+ sk_X509_pop_free(ctx->extraCertsIn, X509_free);
+ ctx->extraCertsIn = NULL;
+ return extraCertsIn == NULL
+ || (ctx->extraCertsIn = X509_chain_up_ref(extraCertsIn)) != NULL;
+}
+
+/*
+ * Copies any given stack as the new stack of X509
+ * certificates to send out in the extraCerts field.
+ */
+int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx,
+ STACK_OF(X509) *extraCertsOut)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ sk_X509_pop_free(ctx->extraCertsOut, X509_free);
+ ctx->extraCertsOut = NULL;
+ return extraCertsOut == NULL
+ || (ctx->extraCertsOut = X509_chain_up_ref(extraCertsOut)) != NULL;
+}
+
+/*
+ * Add the given policy info object
+ * to the X509_EXTENSIONS of the requested certificate template.
+ */
+int OSSL_CMP_CTX_push0_policy(OSSL_CMP_CTX *ctx, POLICYINFO *pinfo)
+{
+ if (ctx == NULL || pinfo == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (ctx->policies == NULL
+ && (ctx->policies = CERTIFICATEPOLICIES_new()) == NULL)
+ return 0;
+
+ return sk_POLICYINFO_push(ctx->policies, pinfo);
+}
+
+/* Add an ITAV for geninfo of the PKI message header */
+int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ return OSSL_CMP_ITAV_push0_stack_item(&ctx->geninfo_ITAVs, itav);
+}
+
+int OSSL_CMP_CTX_reset_geninfo_ITAVs(OSSL_CMP_CTX *ctx)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ OSSL_CMP_ITAVs_free(ctx->geninfo_ITAVs);
+ ctx->geninfo_ITAVs = NULL;
+ return 1;
+}
+
+/* Add an itav for the body of outgoing general messages */
+int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ return OSSL_CMP_ITAV_push0_stack_item(&ctx->genm_ITAVs, itav);
+}
+
+/*
+ * Returns a duplicate of the stack of X509 certificates that
+ * were received in the caPubs field of the last CertRepMessage.
+ * Returns NULL on error
+ */
+STACK_OF(X509) *OSSL_CMP_CTX_get1_caPubs(const OSSL_CMP_CTX *ctx)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return X509_chain_up_ref(ctx->caPubs);
+}
+
+/*
+ * Copies any given stack of certificates to the given
+ * OSSL_CMP_CTX structure so that they may be retrieved later.
+ */
+int ossl_cmp_ctx_set1_caPubs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *caPubs)
+{
+ if (!ossl_assert(ctx != NULL))
+ return 0;
+
+ sk_X509_pop_free(ctx->caPubs, X509_free);
+ ctx->caPubs = NULL;
+ return caPubs == NULL || (ctx->caPubs = X509_chain_up_ref(caPubs)) != NULL;
+}
+
+#define char_dup OPENSSL_strdup
+#define char_free OPENSSL_free
+#define DEFINE_OSSL_CMP_CTX_set1(FIELD, TYPE) /* this uses _dup */ \
+int OSSL_CMP_CTX_set1_##FIELD(OSSL_CMP_CTX *ctx, const TYPE *val) \
+{ \
+ TYPE *val_dup = NULL; \
+ \
+ if (ctx == NULL) { \
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \
+ return 0; \
+ } \
+ \
+ if (val != NULL && (val_dup = TYPE##_dup(val)) == NULL) \
+ return 0; \
+ TYPE##_free(ctx->FIELD); \
+ ctx->FIELD = val_dup; \
+ return 1; \
+}
+
+#define X509_invalid(cert) (!ossl_x509v3_cache_extensions(cert))
+#define EVP_PKEY_invalid(key) 0
+#define DEFINE_OSSL_CMP_CTX_set1_up_ref(FIELD, TYPE) \
+int OSSL_CMP_CTX_set1_##FIELD(OSSL_CMP_CTX *ctx, TYPE *val) \
+{ \
+ if (ctx == NULL) { \
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \
+ return 0; \
+ } \
+ \
+ /* prevent misleading error later on malformed cert or provider issue */ \
+ if (val != NULL && TYPE##_invalid(val)) { \
+ ERR_raise(ERR_LIB_CMP, CMP_R_POTENTIALLY_INVALID_CERTIFICATE); \
+ return 0; \
+ } \
+ if (val != NULL && !TYPE##_up_ref(val)) \
+ return 0; \
+ TYPE##_free(ctx->FIELD); \
+ ctx->FIELD = val; \
+ return 1; \
+}
+
+/*
+ * Pins the server certificate to be directly trusted (even if it is expired)
+ * for verifying response messages.
+ * Cert pointer is not consumed. It may be NULL to clear the entry.
+ */
+DEFINE_OSSL_CMP_CTX_set1_up_ref(srvCert, X509)
+
+/* Set the X509 name of the recipient. Set in the PKIHeader */
+DEFINE_OSSL_CMP_CTX_set1(recipient, X509_NAME)
+
+/* Store the X509 name of the expected sender in the PKIHeader of responses */
+DEFINE_OSSL_CMP_CTX_set1(expected_sender, X509_NAME)
+
+/* Set the X509 name of the issuer. Set in the PKIHeader */
+DEFINE_OSSL_CMP_CTX_set1(issuer, X509_NAME)
+
+/*
+ * Set the subject name that will be placed in the certificate
+ * request. This will be the subject name on the received certificate.
+ */
+DEFINE_OSSL_CMP_CTX_set1(subjectName, X509_NAME)
+
+/* Set the X.509v3 certificate request extensions to be used in IR/CR/KUR */
+int OSSL_CMP_CTX_set0_reqExtensions(OSSL_CMP_CTX *ctx, X509_EXTENSIONS *exts)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (sk_GENERAL_NAME_num(ctx->subjectAltNames) > 0 && exts != NULL
+ && X509v3_get_ext_by_NID(exts, NID_subject_alt_name, -1) >= 0) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_SAN_SOURCES);
+ return 0;
+ }
+ sk_X509_EXTENSION_pop_free(ctx->reqExtensions, X509_EXTENSION_free);
+ ctx->reqExtensions = exts;
+ return 1;
+}
+
+/* returns 1 if ctx contains a Subject Alternative Name extension, else 0 */
+int OSSL_CMP_CTX_reqExtensions_have_SAN(OSSL_CMP_CTX *ctx)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return -1;
+ }
+ /* if one of the following conditions 'fail' this is not an error */
+ return ctx->reqExtensions != NULL
+ && X509v3_get_ext_by_NID(ctx->reqExtensions,
+ NID_subject_alt_name, -1) >= 0;
+}
+
+/*
+ * Add a GENERAL_NAME structure that will be added to the CRMF
+ * request's extensions field to request subject alternative names.
+ */
+int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx,
+ const GENERAL_NAME *name)
+{
+ GENERAL_NAME *name_dup;
+
+ if (ctx == NULL || name == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (OSSL_CMP_CTX_reqExtensions_have_SAN(ctx) == 1) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_SAN_SOURCES);
+ return 0;
+ }
+
+ if (ctx->subjectAltNames == NULL
+ && (ctx->subjectAltNames = sk_GENERAL_NAME_new_null()) == NULL)
+ return 0;
+ if ((name_dup = GENERAL_NAME_dup(name)) == NULL)
+ return 0;
+ if (!sk_GENERAL_NAME_push(ctx->subjectAltNames, name_dup)) {
+ GENERAL_NAME_free(name_dup);
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Set our own client certificate, used for example in KUR and when
+ * doing the IR with existing certificate.
+ */
+DEFINE_OSSL_CMP_CTX_set1_up_ref(cert, X509)
+
+int OSSL_CMP_CTX_build_cert_chain(OSSL_CMP_CTX *ctx, X509_STORE *own_trusted,
+ STACK_OF(X509) *candidates)
+{
+ STACK_OF(X509) *chain;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (!ossl_x509_add_certs_new(&ctx->untrusted, candidates,
+ X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
+ return 0;
+
+ ossl_cmp_debug(ctx, "trying to build chain for own CMP signer cert");
+ chain = X509_build_chain(ctx->cert, ctx->untrusted, own_trusted, 0,
+ ctx->libctx, ctx->propq);
+ if (chain == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_FAILED_BUILDING_OWN_CHAIN);
+ return 0;
+ }
+ ossl_cmp_debug(ctx, "success building chain for own CMP signer cert");
+ ctx->chain = chain;
+ return 1;
+}
+
+/*
+ * Set the old certificate that we are updating in KUR
+ * or the certificate to be revoked in RR, respectively.
+ * Also used as reference cert (defaulting to cert) for deriving subject DN
+ * and SANs. Its issuer is used as default recipient in the CMP message header.
+ */
+DEFINE_OSSL_CMP_CTX_set1_up_ref(oldCert, X509)
+
+/* Set the PKCS#10 CSR to be sent in P10CR */
+DEFINE_OSSL_CMP_CTX_set1(p10CSR, X509_REQ)
+
+/*
+ * Set the (newly received in IP/KUP/CP) certificate in the context.
+ * This only permits for one cert to be enrolled at a time.
+ */
+int ossl_cmp_ctx_set0_newCert(OSSL_CMP_CTX *ctx, X509 *cert)
+{
+ if (!ossl_assert(ctx != NULL))
+ return 0;
+
+ X509_free(ctx->newCert);
+ ctx->newCert = cert;
+ return 1;
+}
+
+/*
+ * Get the (newly received in IP/KUP/CP) client certificate from the context
+ * This only permits for one client cert to be received...
+ */
+X509 *OSSL_CMP_CTX_get0_newCert(const OSSL_CMP_CTX *ctx)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return ctx->newCert;
+}
+
+/* Set the client's current private key */
+DEFINE_OSSL_CMP_CTX_set1_up_ref(pkey, EVP_PKEY)
+
+/* Set new key pair. Used e.g. when doing Key Update */
+int OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_CTX *ctx, int priv, EVP_PKEY *pkey)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ EVP_PKEY_free(ctx->newPkey);
+ ctx->newPkey = pkey;
+ ctx->newPkey_priv = priv;
+ return 1;
+}
+
+/* Get the private/public key to use for cert enrollment, or NULL on error */
+EVP_PKEY *OSSL_CMP_CTX_get0_newPkey(const OSSL_CMP_CTX *ctx, int priv)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+
+ if (ctx->newPkey != NULL)
+ return priv && !ctx->newPkey_priv ? NULL : ctx->newPkey;
+ if (ctx->p10CSR != NULL)
+ return priv ? NULL : X509_REQ_get0_pubkey(ctx->p10CSR);
+ return ctx->pkey; /* may be NULL */
+}
+
+/* Set the given transactionID to the context */
+int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx,
+ const ASN1_OCTET_STRING *id)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ return ossl_cmp_asn1_octet_string_set1(&ctx->transactionID, id);
+}
+
+/* Set the nonce to be used for the recipNonce in the message created next */
+int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
+ const ASN1_OCTET_STRING *nonce)
+{
+ if (!ossl_assert(ctx != NULL))
+ return 0;
+ return ossl_cmp_asn1_octet_string_set1(&ctx->recipNonce, nonce);
+}
+
+/* Stores the given nonce as the last senderNonce sent out */
+int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx,
+ const ASN1_OCTET_STRING *nonce)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ return ossl_cmp_asn1_octet_string_set1(&ctx->senderNonce, nonce);
+}
+
+/* Set the proxy server to use for HTTP(S) connections */
+DEFINE_OSSL_CMP_CTX_set1(proxy, char)
+
+/* Set the (HTTP) host name of the CMP server */
+DEFINE_OSSL_CMP_CTX_set1(server, char)
+
+/* Set the server exclusion list of the HTTP proxy server */
+DEFINE_OSSL_CMP_CTX_set1(no_proxy, char)
+
+/* Set the http connect/disconnect callback function to be used for HTTP(S) */
+int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_HTTP_bio_cb_t cb)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ ctx->http_cb = cb;
+ return 1;
+}
+
+/* Set argument optionally to be used by the http connect/disconnect callback */
+int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ ctx->http_cb_arg = arg;
+ return 1;
+}
+
+/*
+ * Get argument optionally to be used by the http connect/disconnect callback
+ * Returns callback argument set previously (NULL if not set or on error)
+ */
+void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return ctx->http_cb_arg;
+}
+
+/* Set callback function for sending CMP request and receiving response */
+int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_transfer_cb_t cb)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ ctx->transfer_cb = cb;
+ return 1;
+}
+
+/* Set argument optionally to be used by the transfer callback */
+int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ ctx->transfer_cb_arg = arg;
+ return 1;
+}
+
+/*
+ * Get argument optionally to be used by the transfer callback.
+ * Returns callback argument set previously (NULL if not set or on error)
+ */
+void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return ctx->transfer_cb_arg;
+}
+
+/** Set the HTTP server port to be used */
+int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ ctx->serverPort = port;
+ return 1;
+}
+
+/* Set the HTTP path to be used on the server (e.g "pkix/") */
+DEFINE_OSSL_CMP_CTX_set1(serverPath, char)
+
+/* Set the failInfo error code as bit encoding in OSSL_CMP_CTX */
+int ossl_cmp_ctx_set_failInfoCode(OSSL_CMP_CTX *ctx, int fail_info)
+{
+ if (!ossl_assert(ctx != NULL))
+ return 0;
+ ctx->failInfoCode = fail_info;
+ return 1;
+}
+
+/*
+ * Get the failInfo error code in OSSL_CMP_CTX as bit encoding.
+ * Returns bit string as integer on success, -1 on error
+ */
+int OSSL_CMP_CTX_get_failInfoCode(const OSSL_CMP_CTX *ctx)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return -1;
+ }
+ return ctx->failInfoCode;
+}
+
+/* Set a Boolean or integer option of the context to the "val" arg */
+int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val)
+{
+ int min_val;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ switch (opt) {
+ case OSSL_CMP_OPT_REVOCATION_REASON:
+ min_val = OCSP_REVOKED_STATUS_NOSTATUS;
+ break;
+ case OSSL_CMP_OPT_POPO_METHOD:
+ min_val = OSSL_CRMF_POPO_NONE;
+ break;
+ default:
+ min_val = 0;
+ break;
+ }
+ if (val < min_val) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_VALUE_TOO_SMALL);
+ return 0;
+ }
+
+ switch (opt) {
+ case OSSL_CMP_OPT_LOG_VERBOSITY:
+ if (val > OSSL_CMP_LOG_MAX) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_VALUE_TOO_LARGE);
+ return 0;
+ }
+ ctx->log_verbosity = val;
+ break;
+ case OSSL_CMP_OPT_IMPLICIT_CONFIRM:
+ ctx->implicitConfirm = val;
+ break;
+ case OSSL_CMP_OPT_DISABLE_CONFIRM:
+ ctx->disableConfirm = val;
+ break;
+ case OSSL_CMP_OPT_UNPROTECTED_SEND:
+ ctx->unprotectedSend = val;
+ break;
+ case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
+ ctx->unprotectedErrors = val;
+ break;
+ case OSSL_CMP_OPT_VALIDITY_DAYS:
+ ctx->days = val;
+ break;
+ case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT:
+ ctx->SubjectAltName_nodefault = val;
+ break;
+ case OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL:
+ ctx->setSubjectAltNameCritical = val;
+ break;
+ case OSSL_CMP_OPT_POLICIES_CRITICAL:
+ ctx->setPoliciesCritical = val;
+ break;
+ case OSSL_CMP_OPT_IGNORE_KEYUSAGE:
+ ctx->ignore_keyusage = val;
+ break;
+ case OSSL_CMP_OPT_POPO_METHOD:
+ if (val > OSSL_CRMF_POPO_KEYAGREE) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_VALUE_TOO_LARGE);
+ return 0;
+ }
+ ctx->popoMethod = val;
+ break;
+ case OSSL_CMP_OPT_DIGEST_ALGNID:
+ if (!cmp_ctx_set_md(ctx, &ctx->digest, val))
+ return 0;
+ break;
+ case OSSL_CMP_OPT_OWF_ALGNID:
+ if (!cmp_ctx_set_md(ctx, &ctx->pbm_owf, val))
+ return 0;
+ break;
+ case OSSL_CMP_OPT_MAC_ALGNID:
+ ctx->pbm_mac = val;
+ break;
+ case OSSL_CMP_OPT_KEEP_ALIVE:
+ ctx->keep_alive = val;
+ break;
+ case OSSL_CMP_OPT_MSG_TIMEOUT:
+ ctx->msg_timeout = val;
+ break;
+ case OSSL_CMP_OPT_TOTAL_TIMEOUT:
+ ctx->total_timeout = val;
+ break;
+ case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR:
+ ctx->permitTAInExtraCertsForIR = val;
+ break;
+ case OSSL_CMP_OPT_REVOCATION_REASON:
+ if (val > OCSP_REVOKED_STATUS_AACOMPROMISE) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_VALUE_TOO_LARGE);
+ return 0;
+ }
+ ctx->revocationReason = val;
+ break;
+ default:
+ ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_OPTION);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Reads a Boolean or integer option value from the context.
+ * Returns -1 on error (which is the default OSSL_CMP_OPT_REVOCATION_REASON)
+ */
+int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return -1;
+ }
+
+ switch (opt) {
+ case OSSL_CMP_OPT_LOG_VERBOSITY:
+ return ctx->log_verbosity;
+ case OSSL_CMP_OPT_IMPLICIT_CONFIRM:
+ return ctx->implicitConfirm;
+ case OSSL_CMP_OPT_DISABLE_CONFIRM:
+ return ctx->disableConfirm;
+ case OSSL_CMP_OPT_UNPROTECTED_SEND:
+ return ctx->unprotectedSend;
+ case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
+ return ctx->unprotectedErrors;
+ case OSSL_CMP_OPT_VALIDITY_DAYS:
+ return ctx->days;
+ case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT:
+ return ctx->SubjectAltName_nodefault;
+ case OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL:
+ return ctx->setSubjectAltNameCritical;
+ case OSSL_CMP_OPT_POLICIES_CRITICAL:
+ return ctx->setPoliciesCritical;
+ case OSSL_CMP_OPT_IGNORE_KEYUSAGE:
+ return ctx->ignore_keyusage;
+ case OSSL_CMP_OPT_POPO_METHOD:
+ return ctx->popoMethod;
+ case OSSL_CMP_OPT_DIGEST_ALGNID:
+ return EVP_MD_get_type(ctx->digest);
+ case OSSL_CMP_OPT_OWF_ALGNID:
+ return EVP_MD_get_type(ctx->pbm_owf);
+ case OSSL_CMP_OPT_MAC_ALGNID:
+ return ctx->pbm_mac;
+ case OSSL_CMP_OPT_KEEP_ALIVE:
+ return ctx->keep_alive;
+ case OSSL_CMP_OPT_MSG_TIMEOUT:
+ return ctx->msg_timeout;
+ case OSSL_CMP_OPT_TOTAL_TIMEOUT:
+ return ctx->total_timeout;
+ case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR:
+ return ctx->permitTAInExtraCertsForIR;
+ case OSSL_CMP_OPT_REVOCATION_REASON:
+ return ctx->revocationReason;
+ default:
+ ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_OPTION);
+ return -1;
+ }
+}
diff --git a/crypto/cmp/cmp_err.c b/crypto/cmp/cmp_err.c
new file mode 100644
index 000000000000..fe7b96348bae
--- /dev/null
+++ b/crypto/cmp/cmp_err.c
@@ -0,0 +1,178 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/cmperr.h>
+#include "crypto/cmperr.h"
+
+#ifndef OPENSSL_NO_CMP
+
+# ifndef OPENSSL_NO_ERR
+
+static const ERR_STRING_DATA CMP_str_reasons[] = {
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ALGORITHM_NOT_SUPPORTED),
+ "algorithm not supported"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_BAD_CHECKAFTER_IN_POLLREP),
+ "bad checkafter in pollrep"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_BAD_REQUEST_ID), "bad request id"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTHASH_UNMATCHED), "certhash unmatched"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTID_NOT_FOUND), "certid not found"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTIFICATE_NOT_ACCEPTED),
+ "certificate not accepted"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTIFICATE_NOT_FOUND),
+ "certificate not found"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTREQMSG_NOT_FOUND),
+ "certreqmsg not found"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTRESPONSE_NOT_FOUND),
+ "certresponse not found"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERT_AND_KEY_DO_NOT_MATCH),
+ "cert and key do not match"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CHECKAFTER_OUT_OF_RANGE),
+ "checkafter out of range"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ENCOUNTERED_KEYUPDATEWARNING),
+ "encountered keyupdatewarning"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ENCOUNTERED_WAITING),
+ "encountered waiting"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CALCULATING_PROTECTION),
+ "error calculating protection"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_CERTCONF),
+ "error creating certconf"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_CERTREP),
+ "error creating certrep"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_CERTREQ),
+ "error creating certreq"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_ERROR),
+ "error creating error"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_GENM),
+ "error creating genm"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_GENP),
+ "error creating genp"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_PKICONF),
+ "error creating pkiconf"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_POLLREP),
+ "error creating pollrep"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_POLLREQ),
+ "error creating pollreq"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_RP), "error creating rp"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_RR), "error creating rr"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PARSING_PKISTATUS),
+ "error parsing pkistatus"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PROCESSING_MESSAGE),
+ "error processing message"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PROTECTING_MESSAGE),
+ "error protecting message"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_SETTING_CERTHASH),
+ "error setting certhash"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_UNEXPECTED_CERTCONF),
+ "error unexpected certconf"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_VALIDATING_PROTECTION),
+ "error validating protection"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_VALIDATING_SIGNATURE),
+ "error validating signature"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_BUILDING_OWN_CHAIN),
+ "failed building own chain"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_EXTRACTING_PUBKEY),
+ "failed extracting pubkey"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILURE_OBTAINING_RANDOM),
+ "failure obtaining random"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAIL_INFO_OUT_OF_RANGE),
+ "fail info out of range"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ARGS), "invalid args"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_OPTION), "invalid option"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_CERTID), "missing certid"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION),
+ "missing key input for creating protection"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE),
+ "missing key usage digitalsignature"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_P10CSR), "missing p10csr"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_PBM_SECRET), "missing pbm secret"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_PRIVATE_KEY),
+ "missing private key"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_PROTECTION), "missing protection"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_REFERENCE_CERT),
+ "missing reference cert"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_SECRET), "missing secret"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_SENDER_IDENTIFICATION),
+ "missing sender identification"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_TRUST_ANCHOR),
+ "missing trust anchor"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_TRUST_STORE),
+ "missing trust store"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED),
+ "multiple requests not supported"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED),
+ "multiple responses not supported"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_SAN_SOURCES),
+ "multiple san sources"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_NO_STDIO), "no stdio"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_NO_SUITABLE_SENDER_CERT),
+ "no suitable sender cert"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_NULL_ARGUMENT), "null argument"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_PKIBODY_ERROR), "pkibody error"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_PKISTATUSINFO_NOT_FOUND),
+ "pkistatusinfo not found"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_POLLING_FAILED), "polling failed"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_POTENTIALLY_INVALID_CERTIFICATE),
+ "potentially invalid certificate"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_RECEIVED_ERROR), "received error"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_RECIPNONCE_UNMATCHED),
+ "recipnonce unmatched"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_REQUEST_NOT_ACCEPTED),
+ "request not accepted"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_REQUEST_REJECTED_BY_SERVER),
+ "request rejected by server"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED),
+ "sender generalname type not supported"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG),
+ "srvcert does not validate msg"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TOTAL_TIMEOUT), "total timeout"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSACTIONID_UNMATCHED),
+ "transactionid unmatched"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSFER_ERROR), "transfer error"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKIBODY), "unexpected pkibody"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKISTATUS),
+ "unexpected pkistatus"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PVNO), "unexpected pvno"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_ALGORITHM_ID),
+ "unknown algorithm id"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_CERT_TYPE), "unknown cert type"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_PKISTATUS), "unknown pkistatus"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_ALGORITHM),
+ "unsupported algorithm"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_KEY_TYPE),
+ "unsupported key type"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC),
+ "unsupported protection alg dhbasedmac"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_VALUE_TOO_LARGE), "value too large"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_VALUE_TOO_SMALL), "value too small"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_ALGORITHM_OID),
+ "wrong algorithm oid"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_CERTID), "wrong certid"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_CERTID_IN_RP), "wrong certid in rp"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_PBM_VALUE), "wrong pbm value"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_RP_COMPONENT_COUNT),
+ "wrong rp component count"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_SERIAL_IN_RP), "wrong serial in rp"},
+ {0, NULL}
+};
+
+# endif
+
+int ossl_err_load_CMP_strings(void)
+{
+# ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(CMP_str_reasons[0].error) == NULL)
+ ERR_load_strings_const(CMP_str_reasons);
+# endif
+ return 1;
+}
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/crypto/cmp/cmp_hdr.c b/crypto/cmp/cmp_hdr.c
new file mode 100644
index 000000000000..8c553af61a53
--- /dev/null
+++ b/crypto/cmp/cmp_hdr.c
@@ -0,0 +1,369 @@
+/*
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* CMP functions for PKIHeader handling */
+
+#include "cmp_local.h"
+
+#include <openssl/rand.h>
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <openssl/asn1t.h>
+#include <openssl/cmp.h>
+#include <openssl/err.h>
+
+int ossl_cmp_hdr_set_pvno(OSSL_CMP_PKIHEADER *hdr, int pvno)
+{
+ if (!ossl_assert(hdr != NULL))
+ return 0;
+ return ASN1_INTEGER_set(hdr->pvno, pvno);
+}
+
+int ossl_cmp_hdr_get_pvno(const OSSL_CMP_PKIHEADER *hdr)
+{
+ int64_t pvno;
+
+ if (!ossl_assert(hdr != NULL))
+ return -1;
+ if (!ASN1_INTEGER_get_int64(&pvno, hdr->pvno) || pvno < 0 || pvno > INT_MAX)
+ return -1;
+ return (int)pvno;
+}
+
+int ossl_cmp_hdr_get_protection_nid(const OSSL_CMP_PKIHEADER *hdr)
+{
+ if (!ossl_assert(hdr != NULL)
+ || hdr->protectionAlg == NULL)
+ return NID_undef;
+ return OBJ_obj2nid(hdr->protectionAlg->algorithm);
+}
+
+ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_transactionID(const
+ OSSL_CMP_PKIHEADER *hdr)
+{
+ if (hdr == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return hdr->transactionID;
+}
+
+ASN1_OCTET_STRING *ossl_cmp_hdr_get0_senderNonce(const OSSL_CMP_PKIHEADER *hdr)
+{
+ if (!ossl_assert(hdr != NULL))
+ return NULL;
+ return hdr->senderNonce;
+}
+
+ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr)
+{
+ if (hdr == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return hdr->recipNonce;
+}
+
+/* a NULL-DN as an empty sequence of RDNs */
+int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name)
+{
+ return name == NULL
+ || (name->type == GEN_DIRNAME && IS_NULL_DN(name->d.directoryName));
+}
+
+/* assign to *tgt a copy of src (which may be NULL to indicate an empty DN) */
+static int set1_general_name(GENERAL_NAME **tgt, const X509_NAME *src)
+{
+ GENERAL_NAME *name;
+
+ if (!ossl_assert(tgt != NULL))
+ return 0;
+ if ((name = GENERAL_NAME_new()) == NULL)
+ goto err;
+ name->type = GEN_DIRNAME;
+
+ if (src == NULL) { /* NULL-DN */
+ if ((name->d.directoryName = X509_NAME_new()) == NULL)
+ goto err;
+ } else if (!X509_NAME_set(&name->d.directoryName, src)) {
+ goto err;
+ }
+
+ GENERAL_NAME_free(*tgt);
+ *tgt = name;
+
+ return 1;
+
+ err:
+ GENERAL_NAME_free(name);
+ return 0;
+}
+
+/*
+ * Set the sender name in PKIHeader.
+ * when nm is NULL, sender is set to an empty string
+ * returns 1 on success, 0 on error
+ */
+int ossl_cmp_hdr_set1_sender(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm)
+{
+ if (!ossl_assert(hdr != NULL))
+ return 0;
+ return set1_general_name(&hdr->sender, nm);
+}
+
+int ossl_cmp_hdr_set1_recipient(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm)
+{
+ if (!ossl_assert(hdr != NULL))
+ return 0;
+ return set1_general_name(&hdr->recipient, nm);
+}
+
+int ossl_cmp_hdr_update_messageTime(OSSL_CMP_PKIHEADER *hdr)
+{
+ if (!ossl_assert(hdr != NULL))
+ return 0;
+ if (hdr->messageTime == NULL
+ && (hdr->messageTime = ASN1_GENERALIZEDTIME_new()) == NULL)
+ return 0;
+ return ASN1_GENERALIZEDTIME_set(hdr->messageTime, time(NULL)) != NULL;
+}
+
+/* assign to *tgt a random byte array of given length */
+static int set_random(ASN1_OCTET_STRING **tgt, OSSL_CMP_CTX *ctx, size_t len)
+{
+ unsigned char *bytes = OPENSSL_malloc(len);
+ int res = 0;
+
+ if (bytes == NULL || RAND_bytes_ex(ctx->libctx, bytes, len, 0) <= 0)
+ ERR_raise(ERR_LIB_CMP, CMP_R_FAILURE_OBTAINING_RANDOM);
+ else
+ res = ossl_cmp_asn1_octet_string_set1_bytes(tgt, bytes, len);
+ OPENSSL_free(bytes);
+ return res;
+}
+
+int ossl_cmp_hdr_set1_senderKID(OSSL_CMP_PKIHEADER *hdr,
+ const ASN1_OCTET_STRING *senderKID)
+{
+ if (!ossl_assert(hdr != NULL))
+ return 0;
+ return ossl_cmp_asn1_octet_string_set1(&hdr->senderKID, senderKID);
+}
+
+/* push the given text string to the given PKIFREETEXT ft */
+int ossl_cmp_hdr_push0_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text)
+{
+ if (!ossl_assert(hdr != NULL && text != NULL))
+ return 0;
+
+ if (hdr->freeText == NULL
+ && (hdr->freeText = sk_ASN1_UTF8STRING_new_null()) == NULL)
+ return 0;
+
+ return sk_ASN1_UTF8STRING_push(hdr->freeText, text);
+}
+
+int ossl_cmp_hdr_push1_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text)
+{
+ if (!ossl_assert(hdr != NULL && text != NULL))
+ return 0;
+
+ if (hdr->freeText == NULL
+ && (hdr->freeText = sk_ASN1_UTF8STRING_new_null()) == NULL)
+ return 0;
+
+ return
+ ossl_cmp_sk_ASN1_UTF8STRING_push_str(hdr->freeText, (char *)text->data,
+ text->length);
+}
+
+int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr,
+ OSSL_CMP_ITAV *itav)
+{
+ if (!ossl_assert(hdr != NULL && itav != NULL))
+ return 0;
+ return OSSL_CMP_ITAV_push0_stack_item(&hdr->generalInfo, itav);
+}
+
+int ossl_cmp_hdr_generalInfo_push1_items(OSSL_CMP_PKIHEADER *hdr,
+ const STACK_OF(OSSL_CMP_ITAV) *itavs)
+{
+ int i;
+ OSSL_CMP_ITAV *itav;
+
+ if (!ossl_assert(hdr != NULL))
+ return 0;
+
+ for (i = 0; i < sk_OSSL_CMP_ITAV_num(itavs); i++) {
+ itav = OSSL_CMP_ITAV_dup(sk_OSSL_CMP_ITAV_value(itavs, i));
+ if (itav == NULL)
+ return 0;
+
+ if (!ossl_cmp_hdr_generalInfo_push0_item(hdr, itav)) {
+ OSSL_CMP_ITAV_free(itav);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int ossl_cmp_hdr_set_implicitConfirm(OSSL_CMP_PKIHEADER *hdr)
+{
+ OSSL_CMP_ITAV *itav;
+ ASN1_TYPE *asn1null;
+
+ if (!ossl_assert(hdr != NULL))
+ return 0;
+ asn1null = (ASN1_TYPE *)ASN1_NULL_new();
+ if (asn1null == NULL)
+ return 0;
+ if ((itav = OSSL_CMP_ITAV_create(OBJ_nid2obj(NID_id_it_implicitConfirm),
+ asn1null)) == NULL)
+ goto err;
+ if (!ossl_cmp_hdr_generalInfo_push0_item(hdr, itav))
+ goto err;
+ return 1;
+
+ err:
+ ASN1_TYPE_free(asn1null);
+ OSSL_CMP_ITAV_free(itav);
+ return 0;
+}
+
+/* return 1 if implicitConfirm in the generalInfo field of the header is set */
+int ossl_cmp_hdr_has_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr)
+{
+ int itavCount;
+ int i;
+ OSSL_CMP_ITAV *itav;
+
+ if (!ossl_assert(hdr != NULL))
+ return 0;
+
+ itavCount = sk_OSSL_CMP_ITAV_num(hdr->generalInfo);
+ for (i = 0; i < itavCount; i++) {
+ itav = sk_OSSL_CMP_ITAV_value(hdr->generalInfo, i);
+ if (itav != NULL
+ && OBJ_obj2nid(itav->infoType) == NID_id_it_implicitConfirm)
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * set ctx->transactionID in CMP header
+ * if ctx->transactionID is NULL, a random one is created with 128 bit
+ * according to section 5.1.1:
+ *
+ * It is RECOMMENDED that the clients fill the transactionID field with
+ * 128 bits of (pseudo-) random data for the start of a transaction to
+ * reduce the probability of having the transactionID in use at the server.
+ */
+int ossl_cmp_hdr_set_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr)
+{
+ if (ctx->transactionID == NULL) {
+ char *tid;
+
+ if (!set_random(&ctx->transactionID, ctx,
+ OSSL_CMP_TRANSACTIONID_LENGTH))
+ return 0;
+ tid = OPENSSL_buf2hexstr(ctx->transactionID->data,
+ ctx->transactionID->length);
+ if (tid != NULL)
+ ossl_cmp_log1(DEBUG, ctx,
+ "Starting new transaction with ID=%s", tid);
+ OPENSSL_free(tid);
+ }
+
+ return ossl_cmp_asn1_octet_string_set1(&hdr->transactionID,
+ ctx->transactionID);
+}
+
+/* fill in all fields of the hdr according to the info given in ctx */
+int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr)
+{
+ const X509_NAME *sender;
+ const X509_NAME *rcp = NULL;
+
+ if (!ossl_assert(ctx != NULL && hdr != NULL))
+ return 0;
+
+ /* set the CMP version */
+ if (!ossl_cmp_hdr_set_pvno(hdr, OSSL_CMP_PVNO))
+ return 0;
+
+ /*
+ * If neither protection cert nor oldCert nor subject are given,
+ * sender name is not known to the client and thus set to NULL-DN
+ */
+ sender = ctx->cert != NULL ? X509_get_subject_name(ctx->cert) :
+ ctx->oldCert != NULL ? X509_get_subject_name(ctx->oldCert) :
+ ctx->subjectName;
+ if (!ossl_cmp_hdr_set1_sender(hdr, sender))
+ return 0;
+
+ /* determine recipient entry in PKIHeader */
+ if (ctx->recipient != NULL)
+ rcp = ctx->recipient;
+ else if (ctx->srvCert != NULL)
+ rcp = X509_get_subject_name(ctx->srvCert);
+ else if (ctx->issuer != NULL)
+ rcp = ctx->issuer;
+ else if (ctx->oldCert != NULL)
+ rcp = X509_get_issuer_name(ctx->oldCert);
+ else if (ctx->cert != NULL)
+ rcp = X509_get_issuer_name(ctx->cert);
+ if (!ossl_cmp_hdr_set1_recipient(hdr, rcp))
+ return 0;
+
+ /* set current time as message time */
+ if (!ossl_cmp_hdr_update_messageTime(hdr))
+ return 0;
+
+ if (ctx->recipNonce != NULL
+ && !ossl_cmp_asn1_octet_string_set1(&hdr->recipNonce,
+ ctx->recipNonce))
+ return 0;
+
+ if (!ossl_cmp_hdr_set_transactionID(ctx, hdr))
+ return 0;
+
+ /*-
+ * set random senderNonce
+ * according to section 5.1.1:
+ *
+ * senderNonce present
+ * -- 128 (pseudo-)random bits
+ * The senderNonce and recipNonce fields protect the PKIMessage against
+ * replay attacks. The senderNonce will typically be 128 bits of
+ * (pseudo-) random data generated by the sender, whereas the recipNonce
+ * is copied from the senderNonce of the previous message in the
+ * transaction.
+ */
+ if (!set_random(&hdr->senderNonce, ctx, OSSL_CMP_SENDERNONCE_LENGTH))
+ return 0;
+
+ /* store senderNonce - for cmp with recipNonce in next outgoing msg */
+ if (!OSSL_CMP_CTX_set1_senderNonce(ctx, hdr->senderNonce))
+ return 0;
+
+ /*-
+ * freeText [7] PKIFreeText OPTIONAL,
+ * -- this may be used to indicate context-specific instructions
+ * -- (this field is intended for human consumption)
+ */
+ if (ctx->freeText != NULL
+ && !ossl_cmp_hdr_push1_freeText(hdr, ctx->freeText))
+ return 0;
+
+ return 1;
+}
diff --git a/crypto/cmp/cmp_http.c b/crypto/cmp/cmp_http.c
new file mode 100644
index 000000000000..d29bfa8674ad
--- /dev/null
+++ b/crypto/cmp/cmp_http.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/http.h>
+#include "internal/sockets.h"
+
+#include <openssl/cmp.h>
+#include "cmp_local.h"
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <openssl/bio.h>
+#include <openssl/buffer.h>
+#include <openssl/cmp.h>
+#include <openssl/err.h>
+
+static int keep_alive(int keep_alive, int body_type)
+{
+ if (keep_alive != 0
+ /*
+ * Ask for persistent connection only if may need more round trips.
+ * Do so even with disableConfirm because polling might be needed.
+ */
+ && body_type != OSSL_CMP_PKIBODY_IR
+ && body_type != OSSL_CMP_PKIBODY_CR
+ && body_type != OSSL_CMP_PKIBODY_P10CR
+ && body_type != OSSL_CMP_PKIBODY_KUR
+ && body_type != OSSL_CMP_PKIBODY_POLLREQ)
+ keep_alive = 0;
+ return keep_alive;
+}
+
+/*
+ * Send the PKIMessage req and on success return the response, else NULL.
+ * Any previous error queue entries will likely be removed by ERR_clear_error().
+ */
+OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *req)
+{
+ char server_port[32] = { '\0' };
+ STACK_OF(CONF_VALUE) *headers = NULL;
+ const char content_type_pkix[] = "application/pkixcmp";
+ int tls_used;
+ const ASN1_ITEM *it = ASN1_ITEM_rptr(OSSL_CMP_MSG);
+ BIO *req_mem, *rsp;
+ OSSL_CMP_MSG *res = NULL;
+
+ if (ctx == NULL || req == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+
+ if (!X509V3_add_value("Pragma", "no-cache", &headers))
+ return NULL;
+ if ((req_mem = ASN1_item_i2d_mem_bio(it, (const ASN1_VALUE *)req)) == NULL)
+ goto err;
+
+ if (ctx->serverPort != 0)
+ BIO_snprintf(server_port, sizeof(server_port), "%d", ctx->serverPort);
+ tls_used = OSSL_CMP_CTX_get_http_cb_arg(ctx) != NULL;
+ if (ctx->http_ctx == NULL)
+ ossl_cmp_log3(DEBUG, ctx, "connecting to CMP server %s:%s%s",
+ ctx->server, server_port, tls_used ? " using TLS" : "");
+
+ rsp = OSSL_HTTP_transfer(&ctx->http_ctx, ctx->server, server_port,
+ ctx->serverPath, tls_used,
+ ctx->proxy, ctx->no_proxy,
+ NULL /* bio */, NULL /* rbio */,
+ ctx->http_cb, OSSL_CMP_CTX_get_http_cb_arg(ctx),
+ 0 /* buf_size */, headers,
+ content_type_pkix, req_mem,
+ content_type_pkix, 1 /* expect_asn1 */,
+ OSSL_HTTP_DEFAULT_MAX_RESP_LEN,
+ ctx->msg_timeout,
+ keep_alive(ctx->keep_alive, req->body->type));
+ BIO_free(req_mem);
+ res = (OSSL_CMP_MSG *)ASN1_item_d2i_bio(it, rsp, NULL);
+ BIO_free(rsp);
+
+ if (ctx->http_ctx == NULL)
+ ossl_cmp_debug(ctx, "disconnected from CMP server");
+ /*
+ * Note that on normal successful end of the transaction the connection
+ * is not closed at this level, but this will be done by the CMP client
+ * application via OSSL_CMP_CTX_free() or OSSL_CMP_CTX_reinit().
+ */
+ if (res != NULL)
+ ossl_cmp_debug(ctx, "finished reading response from CMP server");
+ err:
+ sk_CONF_VALUE_pop_free(headers, X509V3_conf_free);
+ return res;
+}
diff --git a/crypto/cmp/cmp_local.h b/crypto/cmp/cmp_local.h
new file mode 100644
index 000000000000..3da021043b81
--- /dev/null
+++ b/crypto/cmp/cmp_local.h
@@ -0,0 +1,930 @@
+/*
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_CMP_LOCAL_H
+# define OSSL_CRYPTO_CMP_LOCAL_H
+
+# include "internal/cryptlib.h"
+
+# include <openssl/cmp.h>
+# include <openssl/err.h>
+
+/* explicit #includes not strictly needed since implied by the above: */
+# include <openssl/crmf.h>
+# include <openssl/types.h>
+# include <openssl/safestack.h>
+# include <openssl/x509.h>
+# include <openssl/x509v3.h>
+# include "crypto/x509.h"
+
+#define IS_NULL_DN(name) (X509_NAME_get_entry(name, 0) == NULL)
+
+/*
+ * this structure is used to store the context for CMP sessions
+ */
+struct ossl_cmp_ctx_st {
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+ OSSL_CMP_log_cb_t log_cb; /* log callback for error/debug/etc. output */
+ OSSL_CMP_severity log_verbosity; /* level of verbosity of log output */
+
+ /* message transfer */
+ OSSL_CMP_transfer_cb_t transfer_cb; /* default: OSSL_CMP_MSG_http_perform */
+ void *transfer_cb_arg; /* allows to store optional argument to cb */
+ /* HTTP-based transfer */
+ OSSL_HTTP_REQ_CTX *http_ctx;
+ char *serverPath;
+ char *server;
+ int serverPort;
+ char *proxy;
+ char *no_proxy;
+ int keep_alive; /* persistent connection: 0=no, 1=prefer, 2=require */
+ int msg_timeout; /* max seconds to wait for each CMP message round trip */
+ int total_timeout; /* max number of seconds an enrollment may take, incl. */
+ /* attempts polling for a response if a 'waiting' PKIStatus is received */
+ time_t end_time; /* session start time + totaltimeout */
+ OSSL_HTTP_bio_cb_t http_cb;
+ void *http_cb_arg; /* allows to store optional argument to cb */
+
+ /* server authentication */
+ /*
+ * unprotectedErrors may be set as workaround for broken server responses:
+ * accept missing or invalid protection of regular error messages, negative
+ * certificate responses (ip/cp/kup), revocation responses (rp), and PKIConf
+ */
+ int unprotectedErrors;
+ X509 *srvCert; /* certificate used to identify the server */
+ X509 *validatedSrvCert; /* caches any already validated server cert */
+ X509_NAME *expected_sender; /* expected sender in header of response */
+ X509_STORE *trusted; /* trust store maybe w CRLs and cert verify callback */
+ STACK_OF(X509) *untrusted; /* untrusted (intermediate CA) certs */
+ int ignore_keyusage; /* ignore key usage entry when validating certs */
+ /*
+ * permitTAInExtraCertsForIR allows use of root certs in extracerts
+ * when validating message protection; this is used for 3GPP-style E.7
+ */
+ int permitTAInExtraCertsForIR;
+
+ /* client authentication */
+ int unprotectedSend; /* send unprotected PKI messages */
+ X509 *cert; /* protection cert used to identify and sign for MSG_SIG_ALG */
+ STACK_OF(X509) *chain; /* (cached) chain of protection cert including it */
+ EVP_PKEY *pkey; /* the key pair corresponding to cert */
+ ASN1_OCTET_STRING *referenceValue; /* optional user name for MSG_MAC_ALG */
+ ASN1_OCTET_STRING *secretValue; /* password/shared secret for MSG_MAC_ALG */
+ /* PBMParameters for MSG_MAC_ALG */
+ size_t pbm_slen; /* salt length, currently fixed to 16 */
+ EVP_MD *pbm_owf; /* one-way function (OWF), default: SHA256 */
+ int pbm_itercnt; /* OWF iteration count, currently fixed to 500 */
+ int pbm_mac; /* NID of MAC algorithm, default: HMAC-SHA1 as per RFC 4210 */
+
+ /* CMP message header and extra certificates */
+ X509_NAME *recipient; /* to set in recipient in pkiheader */
+ EVP_MD *digest; /* digest used in MSG_SIG_ALG and POPO, default SHA256 */
+ ASN1_OCTET_STRING *transactionID; /* the current transaction ID */
+ ASN1_OCTET_STRING *senderNonce; /* last nonce sent */
+ ASN1_OCTET_STRING *recipNonce; /* last nonce received */
+ ASN1_UTF8STRING *freeText; /* optional string to include each msg */
+ STACK_OF(OSSL_CMP_ITAV) *geninfo_ITAVs;
+ int implicitConfirm; /* set implicitConfirm in IR/KUR/CR messages */
+ int disableConfirm; /* disable certConf in IR/KUR/CR for broken servers */
+ STACK_OF(X509) *extraCertsOut; /* to be included in request messages */
+
+ /* certificate template */
+ EVP_PKEY *newPkey; /* explicit new private/public key for cert enrollment */
+ int newPkey_priv; /* flag indicating if newPkey contains private key */
+ X509_NAME *issuer; /* issuer name to used in cert template */
+ int days; /* Number of days new certificates are asked to be valid for */
+ X509_NAME *subjectName; /* subject name to be used in cert template */
+ STACK_OF(GENERAL_NAME) *subjectAltNames; /* to add to the cert template */
+ int SubjectAltName_nodefault;
+ int setSubjectAltNameCritical;
+ X509_EXTENSIONS *reqExtensions; /* exts to be added to cert template */
+ CERTIFICATEPOLICIES *policies; /* policies to be included in extensions */
+ int setPoliciesCritical;
+ int popoMethod; /* Proof-of-possession mechanism; default: signature */
+ X509 *oldCert; /* cert to be updated (via KUR) or to be revoked (via RR) */
+ X509_REQ *p10CSR; /* for P10CR: PKCS#10 CSR to be sent */
+
+ /* misc body contents */
+ int revocationReason; /* revocation reason code to be included in RR */
+ STACK_OF(OSSL_CMP_ITAV) *genm_ITAVs; /* content of general message */
+
+ /* result returned in responses */
+ int status; /* PKIStatus of last received IP/CP/KUP/RP/error or -1 */
+ OSSL_CMP_PKIFREETEXT *statusString; /* of last IP/CP/KUP/RP/error */
+ int failInfoCode; /* failInfoCode of last received IP/CP/KUP/error, or -1 */
+ X509 *newCert; /* newly enrolled cert received from the CA */
+ STACK_OF(X509) *newChain; /* chain of newly enrolled cert received */
+ STACK_OF(X509) *caPubs; /* CA certs received from server (in IP message) */
+ STACK_OF(X509) *extraCertsIn; /* extraCerts received from server */
+
+ /* certificate confirmation */
+ OSSL_CMP_certConf_cb_t certConf_cb; /* callback for app checking new cert */
+ void *certConf_cb_arg; /* allows to store an argument individual to cb */
+} /* OSSL_CMP_CTX */;
+
+/*
+ * ##########################################################################
+ * ASN.1 DECLARATIONS
+ * ##########################################################################
+ */
+
+/*-
+ * RevAnnContent ::= SEQUENCE {
+ * status PKIStatus,
+ * certId CertId,
+ * willBeRevokedAt GeneralizedTime,
+ * badSinceDate GeneralizedTime,
+ * crlDetails Extensions OPTIONAL
+ * -- extra CRL details (e.g., crl number, reason, location, etc.)
+ * }
+ */
+typedef struct ossl_cmp_revanncontent_st {
+ ASN1_INTEGER *status;
+ OSSL_CRMF_CERTID *certId;
+ ASN1_GENERALIZEDTIME *willBeRevokedAt;
+ ASN1_GENERALIZEDTIME *badSinceDate;
+ X509_EXTENSIONS *crlDetails;
+} OSSL_CMP_REVANNCONTENT;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_REVANNCONTENT)
+
+/*-
+ * Challenge ::= SEQUENCE {
+ * owf AlgorithmIdentifier OPTIONAL,
+ *
+ * -- MUST be present in the first Challenge; MAY be omitted in
+ * -- any subsequent Challenge in POPODecKeyChallContent (if
+ * -- omitted, then the owf used in the immediately preceding
+ * -- Challenge is to be used).
+ *
+ * witness OCTET STRING,
+ * -- the result of applying the one-way function (owf) to a
+ * -- randomly-generated INTEGER, A. [Note that a different
+ * -- INTEGER MUST be used for each Challenge.]
+ * challenge OCTET STRING
+ * -- the encryption (under the public key for which the cert.
+ * -- request is being made) of Rand, where Rand is specified as
+ * -- Rand ::= SEQUENCE {
+ * -- int INTEGER,
+ * -- - the randomly-generated INTEGER A (above)
+ * -- sender GeneralName
+ * -- - the sender's name (as included in PKIHeader)
+ * -- }
+ * }
+ */
+typedef struct ossl_cmp_challenge_st {
+ X509_ALGOR *owf;
+ ASN1_OCTET_STRING *witness;
+ ASN1_OCTET_STRING *challenge;
+} OSSL_CMP_CHALLENGE;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CHALLENGE)
+
+/*-
+ * CAKeyUpdAnnContent ::= SEQUENCE {
+ * oldWithNew Certificate,
+ * newWithOld Certificate,
+ * newWithNew Certificate
+ * }
+ */
+typedef struct ossl_cmp_cakeyupdanncontent_st {
+ X509 *oldWithNew;
+ X509 *newWithOld;
+ X509 *newWithNew;
+} OSSL_CMP_CAKEYUPDANNCONTENT;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CAKEYUPDANNCONTENT)
+
+/*-
+ * declared already here as it will be used in OSSL_CMP_MSG (nested) and
+ * infoType and infoValue
+ */
+typedef STACK_OF(OSSL_CMP_MSG) OSSL_CMP_MSGS;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_MSGS)
+
+/*-
+ * InfoTypeAndValue ::= SEQUENCE {
+ * infoType OBJECT IDENTIFIER,
+ * infoValue ANY DEFINED BY infoType OPTIONAL
+ * }
+ */
+struct ossl_cmp_itav_st {
+ ASN1_OBJECT *infoType;
+ union {
+ char *ptr;
+ /* NID_id_it_caProtEncCert - CA Protocol Encryption Certificate */
+ X509 *caProtEncCert;
+ /* NID_id_it_signKeyPairTypes - Signing Key Pair Types */
+ STACK_OF(X509_ALGOR) *signKeyPairTypes;
+ /* NID_id_it_encKeyPairTypes - Encryption/Key Agreement Key Pair Types */
+ STACK_OF(X509_ALGOR) *encKeyPairTypes;
+ /* NID_id_it_preferredSymmAlg - Preferred Symmetric Algorithm */
+ X509_ALGOR *preferredSymmAlg;
+ /* NID_id_it_caKeyUpdateInfo - Updated CA Key Pair */
+ OSSL_CMP_CAKEYUPDANNCONTENT *caKeyUpdateInfo;
+ /* NID_id_it_currentCRL - CRL */
+ X509_CRL *currentCRL;
+ /* NID_id_it_unsupportedOIDs - Unsupported Object Identifiers */
+ STACK_OF(ASN1_OBJECT) *unsupportedOIDs;
+ /* NID_id_it_keyPairParamReq - Key Pair Parameters Request */
+ ASN1_OBJECT *keyPairParamReq;
+ /* NID_id_it_keyPairParamRep - Key Pair Parameters Response */
+ X509_ALGOR *keyPairParamRep;
+ /* NID_id_it_revPassphrase - Revocation Passphrase */
+ OSSL_CRMF_ENCRYPTEDVALUE *revPassphrase;
+ /* NID_id_it_implicitConfirm - ImplicitConfirm */
+ ASN1_NULL *implicitConfirm;
+ /* NID_id_it_confirmWaitTime - ConfirmWaitTime */
+ ASN1_GENERALIZEDTIME *confirmWaitTime;
+ /* NID_id_it_origPKIMessage - origPKIMessage */
+ OSSL_CMP_MSGS *origPKIMessage;
+ /* NID_id_it_suppLangTags - Supported Language Tags */
+ STACK_OF(ASN1_UTF8STRING) *suppLangTagsValue;
+ /* this is to be used for so far undeclared objects */
+ ASN1_TYPE *other;
+ } infoValue;
+} /* OSSL_CMP_ITAV */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ITAV)
+
+typedef struct ossl_cmp_certorenccert_st {
+ int type;
+ union {
+ X509 *certificate;
+ OSSL_CRMF_ENCRYPTEDVALUE *encryptedCert;
+ } value;
+} OSSL_CMP_CERTORENCCERT;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTORENCCERT)
+
+/*-
+ * CertifiedKeyPair ::= SEQUENCE {
+ * certOrEncCert CertOrEncCert,
+ * privateKey [0] EncryptedValue OPTIONAL,
+ * -- see [CRMF] for comment on encoding
+ * publicationInfo [1] PKIPublicationInfo OPTIONAL
+ * }
+ */
+typedef struct ossl_cmp_certifiedkeypair_st {
+ OSSL_CMP_CERTORENCCERT *certOrEncCert;
+ OSSL_CRMF_ENCRYPTEDVALUE *privateKey;
+ OSSL_CRMF_PKIPUBLICATIONINFO *publicationInfo;
+} OSSL_CMP_CERTIFIEDKEYPAIR;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTIFIEDKEYPAIR)
+
+/*-
+ * PKIStatusInfo ::= SEQUENCE {
+ * status PKIStatus,
+ * statusString PKIFreeText OPTIONAL,
+ * failInfo PKIFailureInfo OPTIONAL
+ * }
+ */
+struct ossl_cmp_pkisi_st {
+ OSSL_CMP_PKISTATUS *status;
+ OSSL_CMP_PKIFREETEXT *statusString;
+ OSSL_CMP_PKIFAILUREINFO *failInfo;
+} /* OSSL_CMP_PKISI */;
+
+/*-
+ * RevReqContent ::= SEQUENCE OF RevDetails
+ *
+ * RevDetails ::= SEQUENCE {
+ * certDetails CertTemplate,
+ * crlEntryDetails Extensions OPTIONAL
+ * }
+ */
+struct ossl_cmp_revdetails_st {
+ OSSL_CRMF_CERTTEMPLATE *certDetails;
+ X509_EXTENSIONS *crlEntryDetails;
+} /* OSSL_CMP_REVDETAILS */;
+typedef struct ossl_cmp_revdetails_st OSSL_CMP_REVDETAILS;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_REVDETAILS)
+DEFINE_STACK_OF(OSSL_CMP_REVDETAILS)
+
+/*-
+ * RevRepContent ::= SEQUENCE {
+ * status SEQUENCE SIZE (1..MAX) OF PKIStatusInfo,
+ * -- in same order as was sent in RevReqContent
+ * revCerts [0] SEQUENCE SIZE (1..MAX) OF CertId
+ * OPTIONAL,
+ * -- IDs for which revocation was requested
+ * -- (same order as status)
+ * crls [1] SEQUENCE SIZE (1..MAX) OF CertificateList
+ * OPTIONAL
+ * -- the resulting CRLs (there may be more than one)
+ * }
+ */
+struct ossl_cmp_revrepcontent_st {
+ STACK_OF(OSSL_CMP_PKISI) *status;
+ STACK_OF(OSSL_CRMF_CERTID) *revCerts;
+ STACK_OF(X509_CRL) *crls;
+} /* OSSL_CMP_REVREPCONTENT */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_REVREPCONTENT)
+
+/*-
+ * KeyRecRepContent ::= SEQUENCE {
+ * status PKIStatusInfo,
+ * newSigCert [0] Certificate OPTIONAL,
+ * caCerts [1] SEQUENCE SIZE (1..MAX) OF
+ * Certificate OPTIONAL,
+ * keyPairHist [2] SEQUENCE SIZE (1..MAX) OF
+ * CertifiedKeyPair OPTIONAL
+ * }
+ */
+typedef struct ossl_cmp_keyrecrepcontent_st {
+ OSSL_CMP_PKISI *status;
+ X509 *newSigCert;
+ STACK_OF(X509) *caCerts;
+ STACK_OF(OSSL_CMP_CERTIFIEDKEYPAIR) *keyPairHist;
+} OSSL_CMP_KEYRECREPCONTENT;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_KEYRECREPCONTENT)
+
+/*-
+ * ErrorMsgContent ::= SEQUENCE {
+ * pKIStatusInfo PKIStatusInfo,
+ * errorCode INTEGER OPTIONAL,
+ * -- implementation-specific error codes
+ * errorDetails PKIFreeText OPTIONAL
+ * -- implementation-specific error details
+ * }
+ */
+typedef struct ossl_cmp_errormsgcontent_st {
+ OSSL_CMP_PKISI *pKIStatusInfo;
+ ASN1_INTEGER *errorCode;
+ OSSL_CMP_PKIFREETEXT *errorDetails;
+} OSSL_CMP_ERRORMSGCONTENT;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ERRORMSGCONTENT)
+
+/*-
+ * CertConfirmContent ::= SEQUENCE OF CertStatus
+ *
+ * CertStatus ::= SEQUENCE {
+ * certHash OCTET STRING,
+ * -- the hash of the certificate, using the same hash algorithm
+ * -- as is used to create and verify the certificate signature
+ * certReqId INTEGER,
+ * -- to match this confirmation with the corresponding req/rep
+ * statusInfo PKIStatusInfo OPTIONAL
+ * }
+ */
+struct ossl_cmp_certstatus_st {
+ ASN1_OCTET_STRING *certHash;
+ ASN1_INTEGER *certReqId;
+ OSSL_CMP_PKISI *statusInfo;
+} /* OSSL_CMP_CERTSTATUS */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTSTATUS)
+typedef STACK_OF(OSSL_CMP_CERTSTATUS) OSSL_CMP_CERTCONFIRMCONTENT;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTCONFIRMCONTENT)
+
+/*-
+ * CertResponse ::= SEQUENCE {
+ * certReqId INTEGER,
+ * -- to match this response with corresponding request (a value
+ * -- of -1 is to be used if certReqId is not specified in the
+ * -- corresponding request)
+ * status PKIStatusInfo,
+ * certifiedKeyPair CertifiedKeyPair OPTIONAL,
+ * rspInfo OCTET STRING OPTIONAL
+ * -- analogous to the id-regInfo-utf8Pairs string defined
+ * -- for regInfo in CertReqMsg [CRMF]
+ * }
+ */
+struct ossl_cmp_certresponse_st {
+ ASN1_INTEGER *certReqId;
+ OSSL_CMP_PKISI *status;
+ OSSL_CMP_CERTIFIEDKEYPAIR *certifiedKeyPair;
+ ASN1_OCTET_STRING *rspInfo;
+} /* OSSL_CMP_CERTRESPONSE */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTRESPONSE)
+
+/*-
+ * CertRepMessage ::= SEQUENCE {
+ * caPubs [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+ * OPTIONAL,
+ * response SEQUENCE OF CertResponse
+ * }
+ */
+struct ossl_cmp_certrepmessage_st {
+ STACK_OF(X509) *caPubs;
+ STACK_OF(OSSL_CMP_CERTRESPONSE) *response;
+} /* OSSL_CMP_CERTREPMESSAGE */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTREPMESSAGE)
+
+/*-
+ * PollReqContent ::= SEQUENCE OF SEQUENCE {
+ * certReqId INTEGER
+ * }
+ */
+typedef struct ossl_cmp_pollreq_st {
+ ASN1_INTEGER *certReqId;
+} OSSL_CMP_POLLREQ;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POLLREQ)
+DEFINE_STACK_OF(OSSL_CMP_POLLREQ)
+typedef STACK_OF(OSSL_CMP_POLLREQ) OSSL_CMP_POLLREQCONTENT;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POLLREQCONTENT)
+
+/*-
+ * PollRepContent ::= SEQUENCE OF SEQUENCE {
+ * certReqId INTEGER,
+ * checkAfter INTEGER, -- time in seconds
+ * reason PKIFreeText OPTIONAL
+ * }
+ */
+struct ossl_cmp_pollrep_st {
+ ASN1_INTEGER *certReqId;
+ ASN1_INTEGER *checkAfter;
+ OSSL_CMP_PKIFREETEXT *reason;
+} /* OSSL_CMP_POLLREP */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POLLREP)
+DEFINE_STACK_OF(OSSL_CMP_POLLREP)
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POLLREPCONTENT)
+
+/*-
+ * PKIHeader ::= SEQUENCE {
+ * pvno INTEGER { cmp1999(1), cmp2000(2) },
+ * sender GeneralName,
+ * -- identifies the sender
+ * recipient GeneralName,
+ * -- identifies the intended recipient
+ * messageTime [0] GeneralizedTime OPTIONAL,
+ * -- time of production of this message (used when sender
+ * -- believes that the transport will be "suitable"; i.e.,
+ * -- that the time will still be meaningful upon receipt)
+ * protectionAlg [1] AlgorithmIdentifier OPTIONAL,
+ * -- algorithm used for calculation of protection bits
+ * senderKID [2] KeyIdentifier OPTIONAL,
+ * recipKID [3] KeyIdentifier OPTIONAL,
+ * -- to identify specific keys used for protection
+ * transactionID [4] OCTET STRING OPTIONAL,
+ * -- identifies the transaction; i.e., this will be the same in
+ * -- corresponding request, response, certConf, and PKIConf
+ * -- messages
+ * senderNonce [5] OCTET STRING OPTIONAL,
+ * recipNonce [6] OCTET STRING OPTIONAL,
+ * -- nonces used to provide replay protection, senderNonce
+ * -- is inserted by the creator of this message; recipNonce
+ * -- is a nonce previously inserted in a related message by
+ * -- the intended recipient of this message
+ * freeText [7] PKIFreeText OPTIONAL,
+ * -- this may be used to indicate context-specific instructions
+ * -- (this field is intended for human consumption)
+ * generalInfo [8] SEQUENCE SIZE (1..MAX) OF
+ * InfoTypeAndValue OPTIONAL
+ * -- this may be used to convey context-specific information
+ * -- (this field not primarily intended for human consumption)
+ * }
+ */
+struct ossl_cmp_pkiheader_st {
+ ASN1_INTEGER *pvno;
+ GENERAL_NAME *sender;
+ GENERAL_NAME *recipient;
+ ASN1_GENERALIZEDTIME *messageTime; /* 0 */
+ X509_ALGOR *protectionAlg; /* 1 */
+ ASN1_OCTET_STRING *senderKID; /* 2 */
+ ASN1_OCTET_STRING *recipKID; /* 3 */
+ ASN1_OCTET_STRING *transactionID; /* 4 */
+ ASN1_OCTET_STRING *senderNonce; /* 5 */
+ ASN1_OCTET_STRING *recipNonce; /* 6 */
+ OSSL_CMP_PKIFREETEXT *freeText; /* 7 */
+ STACK_OF(OSSL_CMP_ITAV) *generalInfo; /* 8 */
+} /* OSSL_CMP_PKIHEADER */;
+
+typedef STACK_OF(OSSL_CMP_CHALLENGE) OSSL_CMP_POPODECKEYCHALLCONTENT;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POPODECKEYCHALLCONTENT)
+typedef STACK_OF(ASN1_INTEGER) OSSL_CMP_POPODECKEYRESPCONTENT;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POPODECKEYRESPCONTENT)
+typedef STACK_OF(OSSL_CMP_REVDETAILS) OSSL_CMP_REVREQCONTENT;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_REVREQCONTENT)
+typedef STACK_OF(X509_CRL) OSSL_CMP_CRLANNCONTENT;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CRLANNCONTENT)
+typedef STACK_OF(OSSL_CMP_ITAV) OSSL_CMP_GENMSGCONTENT;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_GENMSGCONTENT)
+typedef STACK_OF(OSSL_CMP_ITAV) OSSL_CMP_GENREPCONTENT;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_GENREPCONTENT)
+
+/*-
+ * PKIBody ::= CHOICE { -- message-specific body elements
+ * ir [0] CertReqMessages, --Initialization Request
+ * ip [1] CertRepMessage, --Initialization Response
+ * cr [2] CertReqMessages, --Certification Request
+ * cp [3] CertRepMessage, --Certification Response
+ * p10cr [4] CertificationRequest, --imported from [PKCS10]
+ * popdecc [5] POPODecKeyChallContent, --pop Challenge
+ * popdecr [6] POPODecKeyRespContent, --pop Response
+ * kur [7] CertReqMessages, --Key Update Request
+ * kup [8] CertRepMessage, --Key Update Response
+ * krr [9] CertReqMessages, --Key Recovery Request
+ * krp [10] KeyRecRepContent, --Key Recovery Response
+ * rr [11] RevReqContent, --Revocation Request
+ * rp [12] RevRepContent, --Revocation Response
+ * ccr [13] CertReqMessages, --Cross-Cert. Request
+ * ccp [14] CertRepMessage, --Cross-Cert. Response
+ * ckuann [15] CAKeyUpdAnnContent, --CA Key Update Ann.
+ * cann [16] CertAnnContent, --Certificate Ann.
+ * rann [17] RevAnnContent, --Revocation Ann.
+ * crlann [18] CRLAnnContent, --CRL Announcement
+ * pkiconf [19] PKIConfirmContent, --Confirmation
+ * nested [20] NestedMessageContent, --Nested Message
+ * genm [21] GenMsgContent, --General Message
+ * genp [22] GenRepContent, --General Response
+ * error [23] ErrorMsgContent, --Error Message
+ * certConf [24] CertConfirmContent, --Certificate confirm
+ * pollReq [25] PollReqContent, --Polling request
+ * pollRep [26] PollRepContent --Polling response
+ * }
+ */
+typedef struct ossl_cmp_pkibody_st {
+ int type;
+ union {
+ OSSL_CRMF_MSGS *ir; /* 0 */
+ OSSL_CMP_CERTREPMESSAGE *ip; /* 1 */
+ OSSL_CRMF_MSGS *cr; /* 2 */
+ OSSL_CMP_CERTREPMESSAGE *cp; /* 3 */
+ /*-
+ * p10cr [4] CertificationRequest, --imported from [PKCS10]
+ *
+ * PKCS10_CERTIFICATIONREQUEST is effectively X509_REQ
+ * so it is used directly
+ */
+ X509_REQ *p10cr; /* 4 */
+ /*-
+ * popdecc [5] POPODecKeyChallContent, --pop Challenge
+ *
+ * POPODecKeyChallContent ::= SEQUENCE OF Challenge
+ */
+ OSSL_CMP_POPODECKEYCHALLCONTENT *popdecc; /* 5 */
+ /*-
+ * popdecr [6] POPODecKeyRespContent, --pop Response
+ *
+ * POPODecKeyRespContent ::= SEQUENCE OF INTEGER
+ */
+ OSSL_CMP_POPODECKEYRESPCONTENT *popdecr; /* 6 */
+ OSSL_CRMF_MSGS *kur; /* 7 */
+ OSSL_CMP_CERTREPMESSAGE *kup; /* 8 */
+ OSSL_CRMF_MSGS *krr; /* 9 */
+
+ /*-
+ * krp [10] KeyRecRepContent, --Key Recovery Response
+ */
+ OSSL_CMP_KEYRECREPCONTENT *krp; /* 10 */
+ /*-
+ * rr [11] RevReqContent, --Revocation Request
+ */
+ OSSL_CMP_REVREQCONTENT *rr; /* 11 */
+ /*-
+ * rp [12] RevRepContent, --Revocation Response
+ */
+ OSSL_CMP_REVREPCONTENT *rp; /* 12 */
+ /*-
+ * ccr [13] CertReqMessages, --Cross-Cert. Request
+ */
+ OSSL_CRMF_MSGS *ccr; /* 13 */
+ /*-
+ * ccp [14] CertRepMessage, --Cross-Cert. Response
+ */
+ OSSL_CMP_CERTREPMESSAGE *ccp; /* 14 */
+ /*-
+ * ckuann [15] CAKeyUpdAnnContent, --CA Key Update Ann.
+ */
+ OSSL_CMP_CAKEYUPDANNCONTENT *ckuann; /* 15 */
+ /*-
+ * cann [16] CertAnnContent, --Certificate Ann.
+ * OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly
+ */
+ X509 *cann; /* 16 */
+ /*-
+ * rann [17] RevAnnContent, --Revocation Ann.
+ */
+ OSSL_CMP_REVANNCONTENT *rann; /* 17 */
+ /*-
+ * crlann [18] CRLAnnContent, --CRL Announcement
+ * CRLAnnContent ::= SEQUENCE OF CertificateList
+ */
+ OSSL_CMP_CRLANNCONTENT *crlann; /* 18 */
+ /*-
+ * PKIConfirmContent ::= NULL
+ * pkiconf [19] PKIConfirmContent, --Confirmation
+ * OSSL_CMP_PKICONFIRMCONTENT would be only a typedef of ASN1_NULL
+ * OSSL_CMP_CONFIRMCONTENT *pkiconf;
+ *
+ * NOTE: this should ASN1_NULL according to the RFC
+ * but there might be a struct in it when sent from faulty servers...
+ */
+ ASN1_TYPE *pkiconf; /* 19 */
+ /*-
+ * nested [20] NestedMessageContent, --Nested Message
+ * NestedMessageContent ::= PKIMessages
+ */
+ OSSL_CMP_MSGS *nested; /* 20 */
+ /*-
+ * genm [21] GenMsgContent, --General Message
+ * GenMsgContent ::= SEQUENCE OF InfoTypeAndValue
+ */
+ OSSL_CMP_GENMSGCONTENT *genm; /* 21 */
+ /*-
+ * genp [22] GenRepContent, --General Response
+ * GenRepContent ::= SEQUENCE OF InfoTypeAndValue
+ */
+ OSSL_CMP_GENREPCONTENT *genp; /* 22 */
+ /*-
+ * error [23] ErrorMsgContent, --Error Message
+ */
+ OSSL_CMP_ERRORMSGCONTENT *error; /* 23 */
+ /*-
+ * certConf [24] CertConfirmContent, --Certificate confirm
+ */
+ OSSL_CMP_CERTCONFIRMCONTENT *certConf; /* 24 */
+ /*-
+ * pollReq [25] PollReqContent, --Polling request
+ */
+ OSSL_CMP_POLLREQCONTENT *pollReq; /* 25 */
+ /*-
+ * pollRep [26] PollRepContent --Polling response
+ */
+ OSSL_CMP_POLLREPCONTENT *pollRep; /* 26 */
+ } value;
+} OSSL_CMP_PKIBODY;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PKIBODY)
+
+/*-
+ * PKIProtection ::= BIT STRING
+ *
+ * PKIMessages ::= SEQUENCE SIZE (1..MAX) OF PKIMessage
+ *
+ * PKIMessage ::= SEQUENCE {
+ * header PKIHeader,
+ * body PKIBody,
+ * protection [0] PKIProtection OPTIONAL,
+ * extraCerts [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+ * OPTIONAL
+ * }
+ */
+struct ossl_cmp_msg_st {
+ OSSL_CMP_PKIHEADER *header;
+ OSSL_CMP_PKIBODY *body;
+ ASN1_BIT_STRING *protection; /* 0 */
+ /* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+ STACK_OF(X509) *extraCerts; /* 1 */
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+} /* OSSL_CMP_MSG */;
+OSSL_CMP_MSG *OSSL_CMP_MSG_new(OSSL_LIB_CTX *libctx, const char *propq);
+void OSSL_CMP_MSG_free(OSSL_CMP_MSG *msg);
+
+/*-
+ * ProtectedPart ::= SEQUENCE {
+ * header PKIHeader,
+ * body PKIBody
+ * }
+ */
+typedef struct ossl_cmp_protectedpart_st {
+ OSSL_CMP_PKIHEADER *header;
+ OSSL_CMP_PKIBODY *body;
+} OSSL_CMP_PROTECTEDPART;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PROTECTEDPART)
+
+/*-
+ * this is not defined here as it is already in CRMF:
+ * id-PasswordBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 13}
+ * PBMParameter ::= SEQUENCE {
+ * salt OCTET STRING,
+ * -- note: implementations MAY wish to limit acceptable sizes
+ * -- of this string to values appropriate for their environment
+ * -- in order to reduce the risk of denial-of-service attacks
+ * owf AlgorithmIdentifier,
+ * -- AlgId for a One-Way Function (SHA-1 recommended)
+ * iterationCount INTEGER,
+ * -- number of times the OWF is applied
+ * -- note: implementations MAY wish to limit acceptable sizes
+ * -- of this integer to values appropriate for their environment
+ * -- in order to reduce the risk of denial-of-service attacks
+ * mac AlgorithmIdentifier
+ * -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
+ * } -- or HMAC [RFC2104, RFC2202])
+ */
+/*-
+ * id-DHBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 30}
+ * DHBMParameter ::= SEQUENCE {
+ * owf AlgorithmIdentifier,
+ * -- AlgId for a One-Way Function (SHA-1 recommended)
+ * mac AlgorithmIdentifier
+ * -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
+ * } -- or HMAC [RFC2104, RFC2202])
+ */
+/*-
+ * The following is not cared for, because it is described in section 5.2.5
+ * that this is beyond the scope of CMP
+ * OOBCert ::= CMPCertificate
+ *
+ * OOBCertHash ::= SEQUENCE {
+ * hashAlg [0] AlgorithmIdentifier OPTIONAL,
+ * certId [1] CertId OPTIONAL,
+ * hashVal BIT STRING
+ * -- hashVal is calculated over the DER encoding of the
+ * -- self-signed certificate with the identifier certID.
+ * }
+ */
+
+/* from cmp_asn.c */
+int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a);
+
+/* from cmp_util.c */
+const char *ossl_cmp_log_parse_metadata(const char *buf,
+ OSSL_CMP_severity *level, char **func,
+ char **file, int *line);
+# define ossl_cmp_add_error_data(txt) ERR_add_error_txt(" : ", txt)
+# define ossl_cmp_add_error_line(txt) ERR_add_error_txt("\n", txt)
+/* The two functions manipulating X509_STORE could be generally useful */
+int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
+ int only_self_issued);
+STACK_OF(X509) *ossl_cmp_X509_STORE_get1_certs(X509_STORE *store);
+int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING) *sk,
+ const char *text, int len);
+int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt,
+ const ASN1_OCTET_STRING *src);
+int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING **tgt,
+ const unsigned char *bytes, int len);
+
+/* from cmp_ctx.c */
+int ossl_cmp_print_log(OSSL_CMP_severity level, const OSSL_CMP_CTX *ctx,
+ const char *func, const char *file, int line,
+ const char *level_str, const char *format, ...);
+# define ossl_cmp_log(level, ctx, msg) \
+ ossl_cmp_print_log(OSSL_CMP_LOG_##level, ctx, OPENSSL_FUNC, OPENSSL_FILE, \
+ OPENSSL_LINE, #level, "%s", msg)
+# define ossl_cmp_log1(level, ctx, fmt, arg1) \
+ ossl_cmp_print_log(OSSL_CMP_LOG_##level, ctx, OPENSSL_FUNC, OPENSSL_FILE, \
+ OPENSSL_LINE, #level, fmt, arg1)
+# define ossl_cmp_log2(level, ctx, fmt, arg1, arg2) \
+ ossl_cmp_print_log(OSSL_CMP_LOG_##level, ctx, OPENSSL_FUNC, OPENSSL_FILE, \
+ OPENSSL_LINE, #level, fmt, arg1, arg2)
+# define ossl_cmp_log3(level, ctx, fmt, arg1, arg2, arg3) \
+ ossl_cmp_print_log(OSSL_CMP_LOG_##level, ctx, OPENSSL_FUNC, OPENSSL_FILE, \
+ OPENSSL_LINE, #level, fmt, arg1, arg2, arg3)
+# define ossl_cmp_log4(level, ctx, fmt, arg1, arg2, arg3, arg4) \
+ ossl_cmp_print_log(OSSL_CMP_LOG_##level, ctx, OPENSSL_FUNC, OPENSSL_FILE, \
+ OPENSSL_LINE, #level, fmt, arg1, arg2, arg3, arg4)
+# define OSSL_CMP_LOG_ERROR OSSL_CMP_LOG_ERR
+# define OSSL_CMP_LOG_WARN OSSL_CMP_LOG_WARNING
+# define ossl_cmp_alert(ctx, msg) ossl_cmp_log(ALERT, ctx, msg)
+# define ossl_cmp_err(ctx, msg) ossl_cmp_log(ERROR, ctx, msg)
+# define ossl_cmp_warn(ctx, msg) ossl_cmp_log(WARN, ctx, msg)
+# define ossl_cmp_info(ctx, msg) ossl_cmp_log(INFO, ctx, msg)
+# define ossl_cmp_debug(ctx, msg) ossl_cmp_log(DEBUG, ctx, msg)
+# define ossl_cmp_trace(ctx, msg) ossl_cmp_log(TRACE, ctx, msg)
+int ossl_cmp_ctx_set0_validatedSrvCert(OSSL_CMP_CTX *ctx, X509 *cert);
+int ossl_cmp_ctx_set_status(OSSL_CMP_CTX *ctx, int status);
+int ossl_cmp_ctx_set0_statusString(OSSL_CMP_CTX *ctx,
+ OSSL_CMP_PKIFREETEXT *text);
+int ossl_cmp_ctx_set_failInfoCode(OSSL_CMP_CTX *ctx, int fail_info);
+int ossl_cmp_ctx_set0_newCert(OSSL_CMP_CTX *ctx, X509 *cert);
+int ossl_cmp_ctx_set1_newChain(OSSL_CMP_CTX *ctx, STACK_OF(X509) *newChain);
+int ossl_cmp_ctx_set1_caPubs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *caPubs);
+int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx,
+ STACK_OF(X509) *extraCertsIn);
+int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
+ const ASN1_OCTET_STRING *nonce);
+
+/* from cmp_status.c */
+int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si);
+const char *ossl_cmp_PKIStatus_to_string(int status);
+OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusString(const OSSL_CMP_PKISI *s);
+int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si);
+int ossl_cmp_pkisi_check_pkifailureinfo(const OSSL_CMP_PKISI *si, int index);
+
+/* from cmp_hdr.c */
+int ossl_cmp_hdr_set_pvno(OSSL_CMP_PKIHEADER *hdr, int pvno);
+int ossl_cmp_hdr_get_pvno(const OSSL_CMP_PKIHEADER *hdr);
+int ossl_cmp_hdr_get_protection_nid(const OSSL_CMP_PKIHEADER *hdr);
+ASN1_OCTET_STRING *ossl_cmp_hdr_get0_senderNonce(const OSSL_CMP_PKIHEADER *hdr);
+int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name);
+int ossl_cmp_hdr_set1_sender(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm);
+int ossl_cmp_hdr_set1_recipient(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm);
+int ossl_cmp_hdr_update_messageTime(OSSL_CMP_PKIHEADER *hdr);
+int ossl_cmp_hdr_set1_senderKID(OSSL_CMP_PKIHEADER *hdr,
+ const ASN1_OCTET_STRING *senderKID);
+int ossl_cmp_hdr_push0_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text);
+int ossl_cmp_hdr_push1_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text);
+int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr,
+ OSSL_CMP_ITAV *itav);
+int ossl_cmp_hdr_generalInfo_push1_items(OSSL_CMP_PKIHEADER *hdr,
+ const STACK_OF(OSSL_CMP_ITAV) *itavs);
+int ossl_cmp_hdr_set_implicitConfirm(OSSL_CMP_PKIHEADER *hdr);
+int ossl_cmp_hdr_has_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr);
+# define OSSL_CMP_TRANSACTIONID_LENGTH 16
+# define OSSL_CMP_SENDERNONCE_LENGTH 16
+int ossl_cmp_hdr_set_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr);
+int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr);
+
+/* from cmp_msg.c */
+/* OSSL_CMP_MSG bodytype ASN.1 choice IDs */
+# define OSSL_CMP_PKIBODY_IR 0
+# define OSSL_CMP_PKIBODY_IP 1
+# define OSSL_CMP_PKIBODY_CR 2
+# define OSSL_CMP_PKIBODY_CP 3
+# define OSSL_CMP_PKIBODY_P10CR 4
+# define OSSL_CMP_PKIBODY_POPDECC 5
+# define OSSL_CMP_PKIBODY_POPDECR 6
+# define OSSL_CMP_PKIBODY_KUR 7
+# define OSSL_CMP_PKIBODY_KUP 8
+# define OSSL_CMP_PKIBODY_KRR 9
+# define OSSL_CMP_PKIBODY_KRP 10
+# define OSSL_CMP_PKIBODY_RR 11
+# define OSSL_CMP_PKIBODY_RP 12
+# define OSSL_CMP_PKIBODY_CCR 13
+# define OSSL_CMP_PKIBODY_CCP 14
+# define OSSL_CMP_PKIBODY_CKUANN 15
+# define OSSL_CMP_PKIBODY_CANN 16
+# define OSSL_CMP_PKIBODY_RANN 17
+# define OSSL_CMP_PKIBODY_CRLANN 18
+# define OSSL_CMP_PKIBODY_PKICONF 19
+# define OSSL_CMP_PKIBODY_NESTED 20
+# define OSSL_CMP_PKIBODY_GENM 21
+# define OSSL_CMP_PKIBODY_GENP 22
+# define OSSL_CMP_PKIBODY_ERROR 23
+# define OSSL_CMP_PKIBODY_CERTCONF 24
+# define OSSL_CMP_PKIBODY_POLLREQ 25
+# define OSSL_CMP_PKIBODY_POLLREP 26
+# define OSSL_CMP_PKIBODY_TYPE_MAX OSSL_CMP_PKIBODY_POLLREP
+/* certReqId for the first - and so far only - certificate request */
+# define OSSL_CMP_CERTREQID 0
+/* sequence id for the first - and so far only - revocation request */
+# define OSSL_CMP_REVREQSID 0
+int ossl_cmp_msg_set0_libctx(OSSL_CMP_MSG *msg, OSSL_LIB_CTX *libctx,
+ const char *propq);
+const char *ossl_cmp_bodytype_to_string(int type);
+int ossl_cmp_msg_set_bodytype(OSSL_CMP_MSG *msg, int type);
+OSSL_CMP_MSG *ossl_cmp_msg_create(OSSL_CMP_CTX *ctx, int bodytype);
+OSSL_CMP_MSG *ossl_cmp_certreq_new(OSSL_CMP_CTX *ctx, int bodytype,
+ const OSSL_CRMF_MSG *crm);
+OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype,
+ int certReqId, const OSSL_CMP_PKISI *si,
+ X509 *cert, const X509 *encryption_recip,
+ STACK_OF(X509) *chain, STACK_OF(X509) *caPubs,
+ int unprotectedErrors);
+OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx);
+OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si,
+ const OSSL_CRMF_CERTID *cid,
+ int unprotectedErrors);
+OSSL_CMP_MSG *ossl_cmp_pkiconf_new(OSSL_CMP_CTX *ctx);
+OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
+ int64_t poll_after);
+int ossl_cmp_msg_gen_push0_ITAV(OSSL_CMP_MSG *msg, OSSL_CMP_ITAV *itav);
+int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
+ const STACK_OF(OSSL_CMP_ITAV) *itavs);
+OSSL_CMP_MSG *ossl_cmp_genm_new(OSSL_CMP_CTX *ctx);
+OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx,
+ const STACK_OF(OSSL_CMP_ITAV) *itavs);
+OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si,
+ int64_t errorCode, const char *details,
+ int unprotected);
+int ossl_cmp_certstatus_set0_certHash(OSSL_CMP_CERTSTATUS *certStatus,
+ ASN1_OCTET_STRING *hash);
+OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
+ const char *text);
+OSSL_CMP_MSG *ossl_cmp_pollReq_new(OSSL_CMP_CTX *ctx, int crid);
+OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
+ int64_t poll_after);
+OSSL_CMP_PKISI *
+ossl_cmp_revrepcontent_get_pkisi(OSSL_CMP_REVREPCONTENT *rrep, int rsid);
+OSSL_CRMF_CERTID *ossl_cmp_revrepcontent_get_CertId(OSSL_CMP_REVREPCONTENT *rc,
+ int rsid);
+OSSL_CMP_POLLREP *
+ossl_cmp_pollrepcontent_get0_pollrep(const OSSL_CMP_POLLREPCONTENT *prc,
+ int rid);
+OSSL_CMP_CERTRESPONSE *
+ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm,
+ int rid);
+X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CERTRESPONSE *crep,
+ const OSSL_CMP_CTX *ctx, EVP_PKEY *pkey);
+OSSL_CMP_MSG *ossl_cmp_msg_load(const char *file);
+
+/* from cmp_protect.c */
+int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
+ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *msg);
+int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
+
+/* from cmp_vfy.c */
+typedef int (*ossl_cmp_allow_unprotected_cb_t)(const OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *msg,
+ int invalid_protection, int arg);
+int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
+ ossl_cmp_allow_unprotected_cb_t cb, int cb_arg);
+int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
+ ossl_cmp_allow_unprotected_cb_t cb, int cb_arg);
+int ossl_cmp_verify_popo(const OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *msg, int accept_RAVerified);
+
+/* from cmp_client.c */
+int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int fail_info,
+ const char *txt);
+int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info,
+ const char *txt, int errorCode, const char *detail);
+
+#endif /* !defined(OSSL_CRYPTO_CMP_LOCAL_H) */
diff --git a/crypto/cmp/cmp_msg.c b/crypto/cmp/cmp_msg.c
new file mode 100644
index 000000000000..b244f1e17f0d
--- /dev/null
+++ b/crypto/cmp/cmp_msg.c
@@ -0,0 +1,1170 @@
+/*
+ * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* CMP functions for PKIMessage construction */
+
+#include "cmp_local.h"
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <openssl/asn1t.h>
+#include <openssl/cmp.h>
+#include <openssl/crmf.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+
+OSSL_CMP_MSG *OSSL_CMP_MSG_new(OSSL_LIB_CTX *libctx, const char *propq)
+{
+ OSSL_CMP_MSG *msg = NULL;
+
+ msg = (OSSL_CMP_MSG *)ASN1_item_new_ex(ASN1_ITEM_rptr(OSSL_CMP_MSG),
+ libctx, propq);
+ if (!ossl_cmp_msg_set0_libctx(msg, libctx, propq)) {
+ OSSL_CMP_MSG_free(msg);
+ msg = NULL;
+ }
+ return msg;
+}
+
+void OSSL_CMP_MSG_free(OSSL_CMP_MSG *msg)
+{
+ ASN1_item_free((ASN1_VALUE *)msg, ASN1_ITEM_rptr(OSSL_CMP_MSG));
+}
+
+/*
+ * This should only be used if the X509 object was embedded inside another
+ * asn1 object and it needs a libctx to operate.
+ * Use OSSL_CMP_MSG_new() instead if possible.
+ */
+int ossl_cmp_msg_set0_libctx(OSSL_CMP_MSG *msg, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ if (msg != NULL) {
+ msg->libctx = libctx;
+ OPENSSL_free(msg->propq);
+ msg->propq = NULL;
+ if (propq != NULL) {
+ msg->propq = OPENSSL_strdup(propq);
+ if (msg->propq == NULL)
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg)
+{
+ if (msg == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return msg->header;
+}
+
+const char *ossl_cmp_bodytype_to_string(int type)
+{
+ static const char *type_names[] = {
+ "IR", "IP", "CR", "CP", "P10CR",
+ "POPDECC", "POPDECR", "KUR", "KUP",
+ "KRR", "KRP", "RR", "RP", "CCR", "CCP",
+ "CKUANN", "CANN", "RANN", "CRLANN", "PKICONF", "NESTED",
+ "GENM", "GENP", "ERROR", "CERTCONF", "POLLREQ", "POLLREP",
+ };
+
+ if (type < 0 || type > OSSL_CMP_PKIBODY_TYPE_MAX)
+ return "illegal body type";
+ return type_names[type];
+}
+
+int ossl_cmp_msg_set_bodytype(OSSL_CMP_MSG *msg, int type)
+{
+ if (!ossl_assert(msg != NULL && msg->body != NULL))
+ return 0;
+
+ msg->body->type = type;
+ return 1;
+}
+
+int OSSL_CMP_MSG_get_bodytype(const OSSL_CMP_MSG *msg)
+{
+ if (!ossl_assert(msg != NULL && msg->body != NULL))
+ return -1;
+
+ return msg->body->type;
+}
+
+/* Add an extension to the referenced extension stack, which may be NULL */
+static int add1_extension(X509_EXTENSIONS **pexts, int nid, int crit, void *ex)
+{
+ X509_EXTENSION *ext;
+ int res;
+
+ if (!ossl_assert(pexts != NULL)) /* pointer to var must not be NULL */
+ return 0;
+
+ if ((ext = X509V3_EXT_i2d(nid, crit, ex)) == NULL)
+ return 0;
+
+ res = X509v3_add_ext(pexts, ext, 0) != NULL;
+ X509_EXTENSION_free(ext);
+ return res;
+}
+
+/* Add extension list to the referenced extension stack, which may be NULL */
+static int add_extensions(STACK_OF(X509_EXTENSION) **target,
+ const STACK_OF(X509_EXTENSION) *exts)
+{
+ int i;
+
+ if (target == NULL)
+ return 0;
+
+ for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
+ X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
+ ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext);
+ int idx = X509v3_get_ext_by_OBJ(*target, obj, -1);
+
+ /* Does extension exist in target? */
+ if (idx != -1) {
+ /* Delete all extensions of same type */
+ do {
+ X509_EXTENSION_free(sk_X509_EXTENSION_delete(*target, idx));
+ idx = X509v3_get_ext_by_OBJ(*target, obj, -1);
+ } while (idx != -1);
+ }
+ if (!X509v3_add_ext(target, ext, -1))
+ return 0;
+ }
+ return 1;
+}
+
+/* Add a CRL revocation reason code to extension stack, which may be NULL */
+static int add_crl_reason_extension(X509_EXTENSIONS **pexts, int reason_code)
+{
+ ASN1_ENUMERATED *val = ASN1_ENUMERATED_new();
+ int res = 0;
+
+ if (val != NULL && ASN1_ENUMERATED_set(val, reason_code))
+ res = add1_extension(pexts, NID_crl_reason, 0 /* non-critical */, val);
+ ASN1_ENUMERATED_free(val);
+ return res;
+}
+
+OSSL_CMP_MSG *ossl_cmp_msg_create(OSSL_CMP_CTX *ctx, int bodytype)
+{
+ OSSL_CMP_MSG *msg = NULL;
+
+ if (!ossl_assert(ctx != NULL))
+ return NULL;
+
+ if ((msg = OSSL_CMP_MSG_new(ctx->libctx, ctx->propq)) == NULL)
+ return NULL;
+ if (!ossl_cmp_hdr_init(ctx, msg->header)
+ || !ossl_cmp_msg_set_bodytype(msg, bodytype))
+ goto err;
+ if (ctx->geninfo_ITAVs != NULL
+ && !ossl_cmp_hdr_generalInfo_push1_items(msg->header,
+ ctx->geninfo_ITAVs))
+ goto err;
+
+ switch (bodytype) {
+ case OSSL_CMP_PKIBODY_IR:
+ case OSSL_CMP_PKIBODY_CR:
+ case OSSL_CMP_PKIBODY_KUR:
+ if ((msg->body->value.ir = OSSL_CRMF_MSGS_new()) == NULL)
+ goto err;
+ return msg;
+
+ case OSSL_CMP_PKIBODY_P10CR:
+ if (ctx->p10CSR == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_P10CSR);
+ goto err;
+ }
+ if ((msg->body->value.p10cr = X509_REQ_dup(ctx->p10CSR)) == NULL)
+ goto err;
+ return msg;
+
+ case OSSL_CMP_PKIBODY_IP:
+ case OSSL_CMP_PKIBODY_CP:
+ case OSSL_CMP_PKIBODY_KUP:
+ if ((msg->body->value.ip = OSSL_CMP_CERTREPMESSAGE_new()) == NULL)
+ goto err;
+ return msg;
+
+ case OSSL_CMP_PKIBODY_RR:
+ if ((msg->body->value.rr = sk_OSSL_CMP_REVDETAILS_new_null()) == NULL)
+ goto err;
+ return msg;
+ case OSSL_CMP_PKIBODY_RP:
+ if ((msg->body->value.rp = OSSL_CMP_REVREPCONTENT_new()) == NULL)
+ goto err;
+ return msg;
+
+ case OSSL_CMP_PKIBODY_CERTCONF:
+ if ((msg->body->value.certConf =
+ sk_OSSL_CMP_CERTSTATUS_new_null()) == NULL)
+ goto err;
+ return msg;
+ case OSSL_CMP_PKIBODY_PKICONF:
+ if ((msg->body->value.pkiconf = ASN1_TYPE_new()) == NULL)
+ goto err;
+ ASN1_TYPE_set(msg->body->value.pkiconf, V_ASN1_NULL, NULL);
+ return msg;
+
+ case OSSL_CMP_PKIBODY_POLLREQ:
+ if ((msg->body->value.pollReq = sk_OSSL_CMP_POLLREQ_new_null()) == NULL)
+ goto err;
+ return msg;
+ case OSSL_CMP_PKIBODY_POLLREP:
+ if ((msg->body->value.pollRep = sk_OSSL_CMP_POLLREP_new_null()) == NULL)
+ goto err;
+ return msg;
+
+ case OSSL_CMP_PKIBODY_GENM:
+ case OSSL_CMP_PKIBODY_GENP:
+ if ((msg->body->value.genm = sk_OSSL_CMP_ITAV_new_null()) == NULL)
+ goto err;
+ return msg;
+
+ case OSSL_CMP_PKIBODY_ERROR:
+ if ((msg->body->value.error = OSSL_CMP_ERRORMSGCONTENT_new()) == NULL)
+ goto err;
+ return msg;
+
+ default:
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ goto err;
+ }
+
+ err:
+ OSSL_CMP_MSG_free(msg);
+ return NULL;
+}
+
+#define HAS_SAN(ctx) \
+ (sk_GENERAL_NAME_num((ctx)->subjectAltNames) > 0 \
+ || OSSL_CMP_CTX_reqExtensions_have_SAN(ctx) == 1)
+
+static const X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, int for_KUR,
+ const X509_NAME *ref_subj)
+{
+ if (ctx->subjectName != NULL)
+ return IS_NULL_DN(ctx->subjectName) ? NULL : ctx->subjectName;
+ if (ctx->p10CSR != NULL) /* first default is from any given CSR */
+ return X509_REQ_get_subject_name(ctx->p10CSR);
+ if (for_KUR || !HAS_SAN(ctx))
+ /*
+ * For KUR, copy subject from any reference cert as fallback.
+ * For IR or CR, do the same only if there is no subjectAltName.
+ */
+ return ref_subj;
+ return NULL;
+}
+
+OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid)
+{
+ OSSL_CRMF_MSG *crm = NULL;
+ X509 *refcert = ctx->oldCert != NULL ? ctx->oldCert : ctx->cert;
+ /* refcert defaults to current client cert */
+ EVP_PKEY *rkey = OSSL_CMP_CTX_get0_newPkey(ctx, 0);
+ STACK_OF(GENERAL_NAME) *default_sans = NULL;
+ const X509_NAME *ref_subj =
+ refcert != NULL ? X509_get_subject_name(refcert) : NULL;
+ const X509_NAME *subject = determine_subj(ctx, for_KUR, ref_subj);
+ const X509_NAME *issuer = ctx->issuer != NULL || refcert == NULL
+ ? (IS_NULL_DN(ctx->issuer) ? NULL : ctx->issuer)
+ : X509_get_issuer_name(refcert);
+ int crit = ctx->setSubjectAltNameCritical || subject == NULL;
+ /* RFC5280: subjectAltName MUST be critical if subject is null */
+ X509_EXTENSIONS *exts = NULL;
+
+ if (rkey == NULL && ctx->p10CSR != NULL)
+ rkey = X509_REQ_get0_pubkey(ctx->p10CSR);
+ if (rkey == NULL && refcert != NULL)
+ rkey = X509_get0_pubkey(refcert);
+ if (rkey == NULL)
+ rkey = ctx->pkey; /* default is independent of ctx->oldCert */
+ if (rkey == NULL) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+#endif
+ }
+ if (for_KUR && refcert == NULL && ctx->p10CSR == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_REFERENCE_CERT);
+ return NULL;
+ }
+ if ((crm = OSSL_CRMF_MSG_new()) == NULL)
+ return NULL;
+ if (!OSSL_CRMF_MSG_set_certReqId(crm, rid)
+ /*
+ * fill certTemplate, corresponding to CertificationRequestInfo
+ * of PKCS#10. The rkey param cannot be NULL so far -
+ * it could be NULL if centralized key creation was supported
+ */
+ || !OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_MSG_get0_tmpl(crm), rkey,
+ subject, issuer, NULL /* serial */))
+ goto err;
+ if (ctx->days != 0) {
+ time_t now = time(NULL);
+ ASN1_TIME *notBefore = ASN1_TIME_adj(NULL, now, 0, 0);
+ ASN1_TIME *notAfter = ASN1_TIME_adj(NULL, now, ctx->days, 0);
+
+ if (notBefore == NULL
+ || notAfter == NULL
+ || !OSSL_CRMF_MSG_set0_validity(crm, notBefore, notAfter)) {
+ ASN1_TIME_free(notBefore);
+ ASN1_TIME_free(notAfter);
+ goto err;
+ }
+ }
+
+ /* extensions */
+ if (ctx->p10CSR != NULL
+ && (exts = X509_REQ_get_extensions(ctx->p10CSR)) == NULL)
+ goto err;
+ if (!ctx->SubjectAltName_nodefault && !HAS_SAN(ctx) && refcert != NULL
+ && (default_sans = X509V3_get_d2i(X509_get0_extensions(refcert),
+ NID_subject_alt_name, NULL, NULL))
+ != NULL
+ && !add1_extension(&exts, NID_subject_alt_name, crit, default_sans))
+ goto err;
+ if (ctx->reqExtensions != NULL /* augment/override existing ones */
+ && !add_extensions(&exts, ctx->reqExtensions))
+ goto err;
+ if (sk_GENERAL_NAME_num(ctx->subjectAltNames) > 0
+ && !add1_extension(&exts, NID_subject_alt_name,
+ crit, ctx->subjectAltNames))
+ goto err;
+ if (ctx->policies != NULL
+ && !add1_extension(&exts, NID_certificate_policies,
+ ctx->setPoliciesCritical, ctx->policies))
+ goto err;
+ if (!OSSL_CRMF_MSG_set0_extensions(crm, exts))
+ goto err;
+ exts = NULL;
+ /* end fill certTemplate, now set any controls */
+
+ /* for KUR, set OldCertId according to D.6 */
+ if (for_KUR && refcert != NULL) {
+ OSSL_CRMF_CERTID *cid =
+ OSSL_CRMF_CERTID_gen(X509_get_issuer_name(refcert),
+ X509_get0_serialNumber(refcert));
+ int ret;
+
+ if (cid == NULL)
+ goto err;
+ ret = OSSL_CRMF_MSG_set1_regCtrl_oldCertID(crm, cid);
+ OSSL_CRMF_CERTID_free(cid);
+ if (ret == 0)
+ goto err;
+ }
+
+ goto end;
+
+ err:
+ OSSL_CRMF_MSG_free(crm);
+ crm = NULL;
+
+ end:
+ sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+ sk_GENERAL_NAME_pop_free(default_sans, GENERAL_NAME_free);
+ return crm;
+}
+
+OSSL_CMP_MSG *ossl_cmp_certreq_new(OSSL_CMP_CTX *ctx, int type,
+ const OSSL_CRMF_MSG *crm)
+{
+ OSSL_CMP_MSG *msg;
+ OSSL_CRMF_MSG *local_crm = NULL;
+
+ if (!ossl_assert(ctx != NULL))
+ return NULL;
+
+ if (type != OSSL_CMP_PKIBODY_IR && type != OSSL_CMP_PKIBODY_CR
+ && type != OSSL_CMP_PKIBODY_KUR && type != OSSL_CMP_PKIBODY_P10CR) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
+ return NULL;
+ }
+ if (type == OSSL_CMP_PKIBODY_P10CR && crm != NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
+ return NULL;
+ }
+
+ if ((msg = ossl_cmp_msg_create(ctx, type)) == NULL)
+ goto err;
+
+ /* header */
+ if (ctx->implicitConfirm && !ossl_cmp_hdr_set_implicitConfirm(msg->header))
+ goto err;
+
+ /* body */
+ /* For P10CR the content has already been set in OSSL_CMP_MSG_create */
+ if (type != OSSL_CMP_PKIBODY_P10CR) {
+ EVP_PKEY *privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
+
+ /*
+ * privkey is NULL in case ctx->newPkey does not include a private key.
+ * We then may try to use ctx->pkey as fallback/default, but only
+ * if ctx-> newPkey does not include a (non-matching) public key:
+ */
+ if (privkey == NULL && OSSL_CMP_CTX_get0_newPkey(ctx, 0) == NULL)
+ privkey = ctx->pkey; /* default is independent of ctx->oldCert */
+ if (ctx->popoMethod == OSSL_CRMF_POPO_SIGNATURE && privkey == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY);
+ goto err;
+ }
+ if (crm == NULL) {
+ local_crm = OSSL_CMP_CTX_setup_CRM(ctx,
+ type == OSSL_CMP_PKIBODY_KUR,
+ OSSL_CMP_CERTREQID);
+ if (local_crm == NULL
+ || !OSSL_CRMF_MSG_create_popo(ctx->popoMethod, local_crm,
+ privkey, ctx->digest,
+ ctx->libctx, ctx->propq))
+ goto err;
+ } else {
+ if ((local_crm = OSSL_CRMF_MSG_dup(crm)) == NULL)
+ goto err;
+ }
+
+ /* value.ir is same for cr and kur */
+ if (!sk_OSSL_CRMF_MSG_push(msg->body->value.ir, local_crm))
+ goto err;
+ local_crm = NULL;
+ }
+
+ if (!ossl_cmp_msg_protect(ctx, msg))
+ goto err;
+
+ return msg;
+
+ err:
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTREQ);
+ OSSL_CRMF_MSG_free(local_crm);
+ OSSL_CMP_MSG_free(msg);
+ return NULL;
+}
+
+OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype,
+ int certReqId, const OSSL_CMP_PKISI *si,
+ X509 *cert, const X509 *encryption_recip,
+ STACK_OF(X509) *chain, STACK_OF(X509) *caPubs,
+ int unprotectedErrors)
+{
+ OSSL_CMP_MSG *msg = NULL;
+ OSSL_CMP_CERTREPMESSAGE *repMsg = NULL;
+ OSSL_CMP_CERTRESPONSE *resp = NULL;
+ int status = OSSL_CMP_PKISTATUS_unspecified;
+
+ if (!ossl_assert(ctx != NULL && si != NULL))
+ return NULL;
+
+ if ((msg = ossl_cmp_msg_create(ctx, bodytype)) == NULL)
+ goto err;
+ repMsg = msg->body->value.ip; /* value.ip is same for cp and kup */
+
+ /* header */
+ if (ctx->implicitConfirm && !ossl_cmp_hdr_set_implicitConfirm(msg->header))
+ goto err;
+
+ /* body */
+ if ((resp = OSSL_CMP_CERTRESPONSE_new()) == NULL)
+ goto err;
+ OSSL_CMP_PKISI_free(resp->status);
+ if ((resp->status = OSSL_CMP_PKISI_dup(si)) == NULL
+ || !ASN1_INTEGER_set(resp->certReqId, certReqId))
+ goto err;
+
+ status = ossl_cmp_pkisi_get_status(resp->status);
+ if (status != OSSL_CMP_PKISTATUS_rejection
+ && status != OSSL_CMP_PKISTATUS_waiting && cert != NULL) {
+ if (encryption_recip != NULL) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_UNSUPPORTED);
+ goto err;
+ }
+
+ if ((resp->certifiedKeyPair = OSSL_CMP_CERTIFIEDKEYPAIR_new())
+ == NULL)
+ goto err;
+ resp->certifiedKeyPair->certOrEncCert->type =
+ OSSL_CMP_CERTORENCCERT_CERTIFICATE;
+ if (!X509_up_ref(cert))
+ goto err;
+ resp->certifiedKeyPair->certOrEncCert->value.certificate = cert;
+ }
+
+ if (!sk_OSSL_CMP_CERTRESPONSE_push(repMsg->response, resp))
+ goto err;
+ resp = NULL;
+
+ if (bodytype == OSSL_CMP_PKIBODY_IP && caPubs != NULL
+ && (repMsg->caPubs = X509_chain_up_ref(caPubs)) == NULL)
+ goto err;
+ if (sk_X509_num(chain) > 0
+ && !ossl_x509_add_certs_new(&msg->extraCerts, chain,
+ X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
+ goto err;
+
+ if (!unprotectedErrors
+ || ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_rejection)
+ if (!ossl_cmp_msg_protect(ctx, msg))
+ goto err;
+
+ return msg;
+
+ err:
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTREP);
+ OSSL_CMP_CERTRESPONSE_free(resp);
+ OSSL_CMP_MSG_free(msg);
+ return NULL;
+}
+
+OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx)
+{
+ OSSL_CMP_MSG *msg = NULL;
+ OSSL_CMP_REVDETAILS *rd;
+ int ret;
+
+ if (!ossl_assert(ctx != NULL && (ctx->oldCert != NULL
+ || ctx->p10CSR != NULL)))
+ return NULL;
+
+ if ((rd = OSSL_CMP_REVDETAILS_new()) == NULL)
+ goto err;
+
+ /* Fill the template from the contents of the certificate to be revoked */
+ ret = ctx->oldCert != NULL
+ ? OSSL_CRMF_CERTTEMPLATE_fill(rd->certDetails,
+ NULL /* pubkey would be redundant */,
+ NULL /* subject would be redundant */,
+ X509_get_issuer_name(ctx->oldCert),
+ X509_get0_serialNumber(ctx->oldCert))
+ : OSSL_CRMF_CERTTEMPLATE_fill(rd->certDetails,
+ X509_REQ_get0_pubkey(ctx->p10CSR),
+ X509_REQ_get_subject_name(ctx->p10CSR),
+ NULL, NULL);
+ if (!ret)
+ goto err;
+
+ /* revocation reason code is optional */
+ if (ctx->revocationReason != CRL_REASON_NONE
+ && !add_crl_reason_extension(&rd->crlEntryDetails,
+ ctx->revocationReason))
+ goto err;
+
+ if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_RR)) == NULL)
+ goto err;
+
+ if (!sk_OSSL_CMP_REVDETAILS_push(msg->body->value.rr, rd))
+ goto err;
+ rd = NULL;
+ /* Revocation Passphrase according to section 5.3.19.9 could be set here */
+
+ if (!ossl_cmp_msg_protect(ctx, msg))
+ goto err;
+
+ return msg;
+
+ err:
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_RR);
+ OSSL_CMP_MSG_free(msg);
+ OSSL_CMP_REVDETAILS_free(rd);
+ return NULL;
+}
+
+OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si,
+ const OSSL_CRMF_CERTID *cid, int unprotectedErrors)
+{
+ OSSL_CMP_REVREPCONTENT *rep = NULL;
+ OSSL_CMP_PKISI *si1 = NULL;
+ OSSL_CRMF_CERTID *cid_copy = NULL;
+ OSSL_CMP_MSG *msg = NULL;
+
+ if (!ossl_assert(ctx != NULL && si != NULL))
+ return NULL;
+
+ if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_RP)) == NULL)
+ goto err;
+ rep = msg->body->value.rp;
+
+ if ((si1 = OSSL_CMP_PKISI_dup(si)) == NULL)
+ goto err;
+
+ if (!sk_OSSL_CMP_PKISI_push(rep->status, si1)) {
+ OSSL_CMP_PKISI_free(si1);
+ goto err;
+ }
+
+ if ((rep->revCerts = sk_OSSL_CRMF_CERTID_new_null()) == NULL)
+ goto err;
+ if (cid != NULL) {
+ if ((cid_copy = OSSL_CRMF_CERTID_dup(cid)) == NULL)
+ goto err;
+ if (!sk_OSSL_CRMF_CERTID_push(rep->revCerts, cid_copy)) {
+ OSSL_CRMF_CERTID_free(cid_copy);
+ goto err;
+ }
+ }
+
+ if (!unprotectedErrors
+ || ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_rejection)
+ if (!ossl_cmp_msg_protect(ctx, msg))
+ goto err;
+
+ return msg;
+
+ err:
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_RP);
+ OSSL_CMP_MSG_free(msg);
+ return NULL;
+}
+
+OSSL_CMP_MSG *ossl_cmp_pkiconf_new(OSSL_CMP_CTX *ctx)
+{
+ OSSL_CMP_MSG *msg;
+
+ if (!ossl_assert(ctx != NULL))
+ return NULL;
+
+ if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_PKICONF)) == NULL)
+ goto err;
+ if (ossl_cmp_msg_protect(ctx, msg))
+ return msg;
+
+ err:
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_PKICONF);
+ OSSL_CMP_MSG_free(msg);
+ return NULL;
+}
+
+int ossl_cmp_msg_gen_push0_ITAV(OSSL_CMP_MSG *msg, OSSL_CMP_ITAV *itav)
+{
+ int bodytype;
+
+ if (!ossl_assert(msg != NULL && itav != NULL))
+ return 0;
+
+ bodytype = OSSL_CMP_MSG_get_bodytype(msg);
+ if (bodytype != OSSL_CMP_PKIBODY_GENM
+ && bodytype != OSSL_CMP_PKIBODY_GENP) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
+ return 0;
+ }
+
+ /* value.genp has the same structure, so this works for genp as well */
+ return OSSL_CMP_ITAV_push0_stack_item(&msg->body->value.genm, itav);
+}
+
+int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
+ const STACK_OF(OSSL_CMP_ITAV) *itavs)
+{
+ int i;
+ OSSL_CMP_ITAV *itav = NULL;
+
+ if (!ossl_assert(msg != NULL))
+ return 0;
+
+ for (i = 0; i < sk_OSSL_CMP_ITAV_num(itavs); i++) {
+ itav = OSSL_CMP_ITAV_dup(sk_OSSL_CMP_ITAV_value(itavs, i));
+ if (itav == NULL
+ || !ossl_cmp_msg_gen_push0_ITAV(msg, itav)) {
+ OSSL_CMP_ITAV_free(itav);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * Creates a new General Message/Response with an empty itav stack
+ * returns a pointer to the PKIMessage on success, NULL on error
+ */
+static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx,
+ const STACK_OF(OSSL_CMP_ITAV) *itavs,
+ int body_type, int err_code)
+{
+ OSSL_CMP_MSG *msg = NULL;
+
+ if (!ossl_assert(ctx != NULL))
+ return NULL;
+
+ if ((msg = ossl_cmp_msg_create(ctx, body_type)) == NULL)
+ return NULL;
+
+ if (itavs != NULL && !ossl_cmp_msg_gen_push1_ITAVs(msg, itavs))
+ goto err;
+
+ if (!ossl_cmp_msg_protect(ctx, msg))
+ goto err;
+
+ return msg;
+
+ err:
+ ERR_raise(ERR_LIB_CMP, err_code);
+ OSSL_CMP_MSG_free(msg);
+ return NULL;
+}
+
+OSSL_CMP_MSG *ossl_cmp_genm_new(OSSL_CMP_CTX *ctx)
+{
+ return gen_new(ctx, ctx->genm_ITAVs,
+ OSSL_CMP_PKIBODY_GENM, CMP_R_ERROR_CREATING_GENM);
+}
+
+OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx,
+ const STACK_OF(OSSL_CMP_ITAV) *itavs)
+{
+ return gen_new(ctx, itavs,
+ OSSL_CMP_PKIBODY_GENP, CMP_R_ERROR_CREATING_GENP);
+}
+
+OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si,
+ int64_t errorCode, const char *details,
+ int unprotected)
+{
+ OSSL_CMP_MSG *msg = NULL;
+ const char *lib = NULL, *reason = NULL;
+ OSSL_CMP_PKIFREETEXT *ft;
+
+ if (!ossl_assert(ctx != NULL && si != NULL))
+ return NULL;
+
+ if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_ERROR)) == NULL)
+ goto err;
+
+ OSSL_CMP_PKISI_free(msg->body->value.error->pKIStatusInfo);
+ if ((msg->body->value.error->pKIStatusInfo = OSSL_CMP_PKISI_dup(si))
+ == NULL)
+ goto err;
+ if ((msg->body->value.error->errorCode = ASN1_INTEGER_new()) == NULL)
+ goto err;
+ if (!ASN1_INTEGER_set_int64(msg->body->value.error->errorCode, errorCode))
+ goto err;
+ if (errorCode > 0
+ && (uint64_t)errorCode < ((uint64_t)ERR_SYSTEM_FLAG << 1)) {
+ lib = ERR_lib_error_string((unsigned long)errorCode);
+ reason = ERR_reason_error_string((unsigned long)errorCode);
+ }
+ if (lib != NULL || reason != NULL || details != NULL) {
+ if ((ft = sk_ASN1_UTF8STRING_new_null()) == NULL)
+ goto err;
+ msg->body->value.error->errorDetails = ft;
+ if (lib != NULL && *lib != '\0'
+ && !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, lib, -1))
+ goto err;
+ if (reason != NULL && *reason != '\0'
+ && !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, reason, -1))
+ goto err;
+ if (details != NULL
+ && !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, details, -1))
+ goto err;
+ }
+
+ if (!unprotected && !ossl_cmp_msg_protect(ctx, msg))
+ goto err;
+ return msg;
+
+ err:
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_ERROR);
+ OSSL_CMP_MSG_free(msg);
+ return NULL;
+}
+
+/*
+ * Set the certHash field of a OSSL_CMP_CERTSTATUS structure.
+ * This is used in the certConf message, for example,
+ * to confirm that the certificate was received successfully.
+ */
+int ossl_cmp_certstatus_set0_certHash(OSSL_CMP_CERTSTATUS *certStatus,
+ ASN1_OCTET_STRING *hash)
+{
+ if (!ossl_assert(certStatus != NULL))
+ return 0;
+ ASN1_OCTET_STRING_free(certStatus->certHash);
+ certStatus->certHash = hash;
+ return 1;
+}
+
+OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
+ const char *text)
+{
+ OSSL_CMP_MSG *msg = NULL;
+ OSSL_CMP_CERTSTATUS *certStatus = NULL;
+ ASN1_OCTET_STRING *certHash = NULL;
+ OSSL_CMP_PKISI *sinfo;
+
+ if (!ossl_assert(ctx != NULL && ctx->newCert != NULL))
+ return NULL;
+
+ if ((unsigned)fail_info > OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_FAIL_INFO_OUT_OF_RANGE);
+ return NULL;
+ }
+
+ if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_CERTCONF)) == NULL)
+ goto err;
+
+ if ((certStatus = OSSL_CMP_CERTSTATUS_new()) == NULL)
+ goto err;
+ /* consume certStatus into msg right away so it gets deallocated with msg */
+ if (!sk_OSSL_CMP_CERTSTATUS_push(msg->body->value.certConf, certStatus))
+ goto err;
+ /* set the ID of the certReq */
+ if (!ASN1_INTEGER_set(certStatus->certReqId, OSSL_CMP_CERTREQID))
+ goto err;
+ /*
+ * The hash of the certificate, using the same hash algorithm
+ * as is used to create and verify the certificate signature.
+ * If not available, a default hash algorithm is used.
+ */
+ if ((certHash = X509_digest_sig(ctx->newCert, NULL, NULL)) == NULL)
+ goto err;
+
+ if (!ossl_cmp_certstatus_set0_certHash(certStatus, certHash))
+ goto err;
+ certHash = NULL;
+ /*
+ * For any particular CertStatus, omission of the statusInfo field
+ * indicates ACCEPTANCE of the specified certificate. Alternatively,
+ * explicit status details (with respect to acceptance or rejection) MAY
+ * be provided in the statusInfo field, perhaps for auditing purposes at
+ * the CA/RA.
+ */
+ sinfo = fail_info != 0 ?
+ OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection, fail_info, text) :
+ OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_accepted, 0, text);
+ if (sinfo == NULL)
+ goto err;
+ certStatus->statusInfo = sinfo;
+
+ if (!ossl_cmp_msg_protect(ctx, msg))
+ goto err;
+
+ return msg;
+
+ err:
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTCONF);
+ OSSL_CMP_MSG_free(msg);
+ ASN1_OCTET_STRING_free(certHash);
+ return NULL;
+}
+
+OSSL_CMP_MSG *ossl_cmp_pollReq_new(OSSL_CMP_CTX *ctx, int crid)
+{
+ OSSL_CMP_MSG *msg = NULL;
+ OSSL_CMP_POLLREQ *preq = NULL;
+
+ if (!ossl_assert(ctx != NULL))
+ return NULL;
+
+ if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_POLLREQ)) == NULL)
+ goto err;
+
+ if ((preq = OSSL_CMP_POLLREQ_new()) == NULL
+ || !ASN1_INTEGER_set(preq->certReqId, crid)
+ || !sk_OSSL_CMP_POLLREQ_push(msg->body->value.pollReq, preq))
+ goto err;
+
+ preq = NULL;
+ if (!ossl_cmp_msg_protect(ctx, msg))
+ goto err;
+
+ return msg;
+
+ err:
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_POLLREQ);
+ OSSL_CMP_POLLREQ_free(preq);
+ OSSL_CMP_MSG_free(msg);
+ return NULL;
+}
+
+OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
+ int64_t poll_after)
+{
+ OSSL_CMP_MSG *msg;
+ OSSL_CMP_POLLREP *prep;
+
+ if (!ossl_assert(ctx != NULL))
+ return NULL;
+
+ if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_POLLREP)) == NULL)
+ goto err;
+ if ((prep = OSSL_CMP_POLLREP_new()) == NULL)
+ goto err;
+ if (!sk_OSSL_CMP_POLLREP_push(msg->body->value.pollRep, prep))
+ goto err;
+ if (!ASN1_INTEGER_set(prep->certReqId, crid))
+ goto err;
+ if (!ASN1_INTEGER_set_int64(prep->checkAfter, poll_after))
+ goto err;
+
+ if (!ossl_cmp_msg_protect(ctx, msg))
+ goto err;
+ return msg;
+
+ err:
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_POLLREP);
+ OSSL_CMP_MSG_free(msg);
+ return NULL;
+}
+
+/*-
+ * returns the status field of the RevRepContent with the given
+ * request/sequence id inside a revocation response.
+ * RevRepContent has the revocation statuses in same order as they were sent in
+ * RevReqContent.
+ * returns NULL on error
+ */
+OSSL_CMP_PKISI *
+ossl_cmp_revrepcontent_get_pkisi(OSSL_CMP_REVREPCONTENT *rrep, int rsid)
+{
+ OSSL_CMP_PKISI *status;
+
+ if (!ossl_assert(rrep != NULL))
+ return NULL;
+
+ if ((status = sk_OSSL_CMP_PKISI_value(rrep->status, rsid)) != NULL)
+ return status;
+
+ ERR_raise(ERR_LIB_CMP, CMP_R_PKISTATUSINFO_NOT_FOUND);
+ return NULL;
+}
+
+/*
+ * returns the CertId field in the revCerts part of the RevRepContent
+ * with the given request/sequence id inside a revocation response.
+ * RevRepContent has the CertIds in same order as they were sent in
+ * RevReqContent.
+ * returns NULL on error
+ */
+OSSL_CRMF_CERTID *
+ossl_cmp_revrepcontent_get_CertId(OSSL_CMP_REVREPCONTENT *rrep, int rsid)
+{
+ OSSL_CRMF_CERTID *cid = NULL;
+
+ if (!ossl_assert(rrep != NULL))
+ return NULL;
+
+ if ((cid = sk_OSSL_CRMF_CERTID_value(rrep->revCerts, rsid)) != NULL)
+ return cid;
+
+ ERR_raise(ERR_LIB_CMP, CMP_R_CERTID_NOT_FOUND);
+ return NULL;
+}
+
+static int suitable_rid(const ASN1_INTEGER *certReqId, int rid)
+{
+ int trid;
+
+ if (rid == -1)
+ return 1;
+
+ trid = ossl_cmp_asn1_get_int(certReqId);
+
+ if (trid == -1) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
+ return 0;
+ }
+ return rid == trid;
+}
+
+/*
+ * returns a pointer to the PollResponse with the given CertReqId
+ * (or the first one in case -1) inside a PollRepContent
+ * returns NULL on error or if no suitable PollResponse available
+ */
+OSSL_CMP_POLLREP *
+ossl_cmp_pollrepcontent_get0_pollrep(const OSSL_CMP_POLLREPCONTENT *prc,
+ int rid)
+{
+ OSSL_CMP_POLLREP *pollRep = NULL;
+ int i;
+
+ if (!ossl_assert(prc != NULL))
+ return NULL;
+
+ for (i = 0; i < sk_OSSL_CMP_POLLREP_num(prc); i++) {
+ pollRep = sk_OSSL_CMP_POLLREP_value(prc, i);
+ if (suitable_rid(pollRep->certReqId, rid))
+ return pollRep;
+ }
+
+ ERR_raise_data(ERR_LIB_CMP, CMP_R_CERTRESPONSE_NOT_FOUND,
+ "expected certReqId = %d", rid);
+ return NULL;
+}
+
+/*
+ * returns a pointer to the CertResponse with the given CertReqId
+ * (or the first one in case -1) inside a CertRepMessage
+ * returns NULL on error or if no suitable CertResponse available
+ */
+OSSL_CMP_CERTRESPONSE *
+ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm,
+ int rid)
+{
+ OSSL_CMP_CERTRESPONSE *crep = NULL;
+ int i;
+
+ if (!ossl_assert(crm != NULL && crm->response != NULL))
+ return NULL;
+
+ for (i = 0; i < sk_OSSL_CMP_CERTRESPONSE_num(crm->response); i++) {
+ crep = sk_OSSL_CMP_CERTRESPONSE_value(crm->response, i);
+ if (suitable_rid(crep->certReqId, rid))
+ return crep;
+ }
+
+ ERR_raise_data(ERR_LIB_CMP, CMP_R_CERTRESPONSE_NOT_FOUND,
+ "expected certReqId = %d", rid);
+ return NULL;
+}
+
+/*-
+ * Retrieve the newly enrolled certificate from the given certResponse crep.
+ * In case of indirect POPO uses the libctx and propq from ctx and private key.
+ * Returns a pointer to a copy of the found certificate, or NULL if not found.
+ */
+X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CERTRESPONSE *crep,
+ const OSSL_CMP_CTX *ctx, EVP_PKEY *pkey)
+{
+ OSSL_CMP_CERTORENCCERT *coec;
+ X509 *crt = NULL;
+
+ if (!ossl_assert(crep != NULL && ctx != NULL))
+ return NULL;
+
+ if (crep->certifiedKeyPair
+ && (coec = crep->certifiedKeyPair->certOrEncCert) != NULL) {
+ switch (coec->type) {
+ case OSSL_CMP_CERTORENCCERT_CERTIFICATE:
+ crt = X509_dup(coec->value.certificate);
+ break;
+ case OSSL_CMP_CERTORENCCERT_ENCRYPTEDCERT:
+ /* cert encrypted for indirect PoP; RFC 4210, 5.2.8.2 */
+ if (pkey == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY);
+ return NULL;
+ }
+ crt =
+ OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(coec->value.encryptedCert,
+ ctx->libctx, ctx->propq,
+ pkey);
+ break;
+ default:
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_CERT_TYPE);
+ return NULL;
+ }
+ }
+ if (crt == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_FOUND);
+ else
+ (void)ossl_x509_set0_libctx(crt, ctx->libctx, ctx->propq);
+ return crt;
+}
+
+int OSSL_CMP_MSG_update_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
+{
+ if (ctx == NULL || msg == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (!ossl_cmp_hdr_set_transactionID(ctx, msg->header))
+ return 0;
+ return msg->header->protectionAlg == NULL
+ || ossl_cmp_msg_protect(ctx, msg);
+}
+
+OSSL_CMP_MSG *OSSL_CMP_MSG_read(const char *file, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ OSSL_CMP_MSG *msg;
+ BIO *bio = NULL;
+
+ if (file == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+
+ msg = OSSL_CMP_MSG_new(libctx, propq);
+ if (msg == NULL){
+ ERR_raise(ERR_LIB_CMP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if ((bio = BIO_new_file(file, "rb")) == NULL
+ || d2i_OSSL_CMP_MSG_bio(bio, &msg) == NULL) {
+ OSSL_CMP_MSG_free(msg);
+ msg = NULL;
+ }
+ BIO_free(bio);
+ return msg;
+}
+
+int OSSL_CMP_MSG_write(const char *file, const OSSL_CMP_MSG *msg)
+{
+ BIO *bio;
+ int res;
+
+ if (file == NULL || msg == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return -1;
+ }
+
+ bio = BIO_new_file(file, "wb");
+ if (bio == NULL)
+ return -2;
+ res = i2d_OSSL_CMP_MSG_bio(bio, msg);
+ BIO_free(bio);
+ return res;
+}
+
+OSSL_CMP_MSG *d2i_OSSL_CMP_MSG(OSSL_CMP_MSG **msg, const unsigned char **in,
+ long len)
+{
+ OSSL_LIB_CTX *libctx = NULL;
+ const char *propq = NULL;
+
+ if (msg != NULL && *msg != NULL) {
+ libctx = (*msg)->libctx;
+ propq = (*msg)->propq;
+ }
+
+ return (OSSL_CMP_MSG *)ASN1_item_d2i_ex((ASN1_VALUE **)msg, in, len,
+ ASN1_ITEM_rptr(OSSL_CMP_MSG),
+ libctx, propq);
+}
+
+int i2d_OSSL_CMP_MSG(const OSSL_CMP_MSG *msg, unsigned char **out)
+{
+ return ASN1_item_i2d((const ASN1_VALUE *)msg, out,
+ ASN1_ITEM_rptr(OSSL_CMP_MSG));
+}
+
+OSSL_CMP_MSG *d2i_OSSL_CMP_MSG_bio(BIO *bio, OSSL_CMP_MSG **msg)
+{
+ OSSL_LIB_CTX *libctx = NULL;
+ const char *propq = NULL;
+
+ if (msg != NULL && *msg != NULL) {
+ libctx = (*msg)->libctx;
+ propq = (*msg)->propq;
+ }
+
+ return ASN1_item_d2i_bio_ex(ASN1_ITEM_rptr(OSSL_CMP_MSG), bio, msg, libctx,
+ propq);
+}
+
+int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg)
+{
+ return ASN1_i2d_bio_of(OSSL_CMP_MSG, i2d_OSSL_CMP_MSG, bio, msg);
+}
diff --git a/crypto/cmp/cmp_protect.c b/crypto/cmp/cmp_protect.c
new file mode 100644
index 000000000000..02526196ad2a
--- /dev/null
+++ b/crypto/cmp/cmp_protect.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "cmp_local.h"
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <openssl/asn1t.h>
+#include <openssl/cmp.h>
+#include <openssl/crmf.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+
+/*
+ * This function is also used by the internal verify_PBMAC() in cmp_vfy.c.
+ *
+ * Calculate protection for given PKImessage according to
+ * the algorithm and parameters in the message header's protectionAlg
+ * using the credentials, library context, and property criteria in the ctx.
+ *
+ * returns ASN1_BIT_STRING representing the protection on success, else NULL
+ */
+ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *msg)
+{
+ ASN1_BIT_STRING *prot = NULL;
+ OSSL_CMP_PROTECTEDPART prot_part;
+ const ASN1_OBJECT *algorOID = NULL;
+ const void *ppval = NULL;
+ int pptype = 0;
+
+ if (!ossl_assert(ctx != NULL && msg != NULL))
+ return NULL;
+
+ /* construct data to be signed */
+ prot_part.header = msg->header;
+ prot_part.body = msg->body;
+
+ if (msg->header->protectionAlg == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_ALGORITHM_ID);
+ return NULL;
+ }
+ X509_ALGOR_get0(&algorOID, &pptype, &ppval, msg->header->protectionAlg);
+
+ if (OBJ_obj2nid(algorOID) == NID_id_PasswordBasedMAC) {
+ int len;
+ size_t prot_part_der_len;
+ unsigned char *prot_part_der = NULL;
+ size_t sig_len;
+ unsigned char *protection = NULL;
+ OSSL_CRMF_PBMPARAMETER *pbm = NULL;
+ ASN1_STRING *pbm_str = NULL;
+ const unsigned char *pbm_str_uc = NULL;
+
+ if (ctx->secretValue == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PBM_SECRET);
+ return NULL;
+ }
+ if (ppval == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CALCULATING_PROTECTION);
+ return NULL;
+ }
+
+ len = i2d_OSSL_CMP_PROTECTEDPART(&prot_part, &prot_part_der);
+ if (len < 0 || prot_part_der == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CALCULATING_PROTECTION);
+ goto end;
+ }
+ prot_part_der_len = (size_t)len;
+
+ pbm_str = (ASN1_STRING *)ppval;
+ pbm_str_uc = pbm_str->data;
+ pbm = d2i_OSSL_CRMF_PBMPARAMETER(NULL, &pbm_str_uc, pbm_str->length);
+ if (pbm == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_ALGORITHM_OID);
+ goto end;
+ }
+
+ if (!OSSL_CRMF_pbm_new(ctx->libctx, ctx->propq,
+ pbm, prot_part_der, prot_part_der_len,
+ ctx->secretValue->data, ctx->secretValue->length,
+ &protection, &sig_len))
+ goto end;
+
+ if ((prot = ASN1_BIT_STRING_new()) == NULL)
+ goto end;
+ /* OpenSSL defaults all bit strings to be encoded as ASN.1 NamedBitList */
+ prot->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+ prot->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+ if (!ASN1_BIT_STRING_set(prot, protection, sig_len)) {
+ ASN1_BIT_STRING_free(prot);
+ prot = NULL;
+ }
+ end:
+ OSSL_CRMF_PBMPARAMETER_free(pbm);
+ OPENSSL_free(protection);
+ OPENSSL_free(prot_part_der);
+ return prot;
+ } else {
+ int md_nid;
+ const EVP_MD *md = NULL;
+
+ if (ctx->pkey == NULL) {
+ ERR_raise(ERR_LIB_CMP,
+ CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION);
+ return NULL;
+ }
+ if (!OBJ_find_sigid_algs(OBJ_obj2nid(algorOID), &md_nid, NULL)
+ || (md = EVP_get_digestbynid(md_nid)) == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_ALGORITHM_ID);
+ return NULL;
+ }
+
+ if ((prot = ASN1_BIT_STRING_new()) == NULL)
+ return NULL;
+ if (ASN1_item_sign_ex(ASN1_ITEM_rptr(OSSL_CMP_PROTECTEDPART), NULL,
+ NULL, prot, &prot_part, NULL, ctx->pkey, md,
+ ctx->libctx, ctx->propq))
+ return prot;
+ ASN1_BIT_STRING_free(prot);
+ return NULL;
+ }
+}
+
+int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
+{
+ if (!ossl_assert(ctx != NULL && msg != NULL))
+ return 0;
+
+ /* Add first ctx->cert and its chain if using signature-based protection */
+ if (!ctx->unprotectedSend && ctx->secretValue == NULL
+ && ctx->cert != NULL && ctx->pkey != NULL) {
+ int prepend = X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
+ | X509_ADD_FLAG_PREPEND | X509_ADD_FLAG_NO_SS;
+
+ /* if not yet done try to build chain using available untrusted certs */
+ if (ctx->chain == NULL) {
+ ossl_cmp_debug(ctx,
+ "trying to build chain for own CMP signer cert");
+ ctx->chain = X509_build_chain(ctx->cert, ctx->untrusted, NULL, 0,
+ ctx->libctx, ctx->propq);
+ if (ctx->chain != NULL) {
+ ossl_cmp_debug(ctx,
+ "success building chain for own CMP signer cert");
+ } else {
+ /* dump errors to avoid confusion when printing further ones */
+ OSSL_CMP_CTX_print_errors(ctx);
+ ossl_cmp_warn(ctx,
+ "could not build chain for own CMP signer cert");
+ }
+ }
+ if (ctx->chain != NULL) {
+ if (!ossl_x509_add_certs_new(&msg->extraCerts, ctx->chain, prepend))
+ return 0;
+ } else {
+ /* make sure that at least our own signer cert is included first */
+ if (!ossl_x509_add_cert_new(&msg->extraCerts, ctx->cert, prepend))
+ return 0;
+ ossl_cmp_debug(ctx, "fallback: adding just own CMP signer cert");
+ }
+ }
+
+ /* add any additional certificates from ctx->extraCertsOut */
+ if (!ossl_x509_add_certs_new(&msg->extraCerts, ctx->extraCertsOut,
+ X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
+ return 0;
+
+ /* in case extraCerts are empty list avoid empty ASN.1 sequence */
+ if (sk_X509_num(msg->extraCerts) == 0) {
+ sk_X509_free(msg->extraCerts);
+ msg->extraCerts = NULL;
+ }
+ return 1;
+}
+
+/*
+ * Create an X509_ALGOR structure for PasswordBasedMAC protection based on
+ * the pbm settings in the context
+ */
+static int set_pbmac_algor(const OSSL_CMP_CTX *ctx, X509_ALGOR **alg)
+{
+ OSSL_CRMF_PBMPARAMETER *pbm = NULL;
+ unsigned char *pbm_der = NULL;
+ int pbm_der_len;
+ ASN1_STRING *pbm_str = NULL;
+
+ if (!ossl_assert(ctx != NULL))
+ return 0;
+
+ pbm = OSSL_CRMF_pbmp_new(ctx->libctx, ctx->pbm_slen,
+ EVP_MD_get_type(ctx->pbm_owf), ctx->pbm_itercnt,
+ ctx->pbm_mac);
+ pbm_str = ASN1_STRING_new();
+ if (pbm == NULL || pbm_str == NULL)
+ goto err;
+
+ if ((pbm_der_len = i2d_OSSL_CRMF_PBMPARAMETER(pbm, &pbm_der)) < 0)
+ goto err;
+
+ if (!ASN1_STRING_set(pbm_str, pbm_der, pbm_der_len))
+ goto err;
+ if (*alg == NULL && (*alg = X509_ALGOR_new()) == NULL)
+ goto err;
+ OPENSSL_free(pbm_der);
+
+ X509_ALGOR_set0(*alg, OBJ_nid2obj(NID_id_PasswordBasedMAC),
+ V_ASN1_SEQUENCE, pbm_str);
+ OSSL_CRMF_PBMPARAMETER_free(pbm);
+ return 1;
+
+ err:
+ ASN1_STRING_free(pbm_str);
+ OPENSSL_free(pbm_der);
+ OSSL_CRMF_PBMPARAMETER_free(pbm);
+ return 0;
+}
+
+static int set_sig_algor(const OSSL_CMP_CTX *ctx, X509_ALGOR **alg)
+{
+ int nid = 0;
+ ASN1_OBJECT *algo = NULL;
+
+ if (!OBJ_find_sigid_by_algs(&nid, EVP_MD_get_type(ctx->digest),
+ EVP_PKEY_get_id(ctx->pkey))) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_KEY_TYPE);
+ return 0;
+ }
+ if ((algo = OBJ_nid2obj(nid)) == NULL)
+ return 0;
+ if (*alg == NULL && (*alg = X509_ALGOR_new()) == NULL)
+ return 0;
+
+ if (X509_ALGOR_set0(*alg, algo, V_ASN1_UNDEF, NULL))
+ return 1;
+ ASN1_OBJECT_free(algo);
+ return 0;
+}
+
+static int set_senderKID(const OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg,
+ const ASN1_OCTET_STRING *id)
+{
+ if (id == NULL)
+ id = ctx->referenceValue; /* standard for PBM, fallback for sig-based */
+ return id == NULL || ossl_cmp_hdr_set1_senderKID(msg->header, id);
+}
+
+int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
+{
+ if (!ossl_assert(ctx != NULL && msg != NULL))
+ return 0;
+
+ /*
+ * For the case of re-protection remove pre-existing protection.
+ */
+ X509_ALGOR_free(msg->header->protectionAlg);
+ msg->header->protectionAlg = NULL;
+ ASN1_BIT_STRING_free(msg->protection);
+ msg->protection = NULL;
+
+ if (ctx->unprotectedSend) {
+ if (!set_senderKID(ctx, msg, NULL))
+ goto err;
+ } else if (ctx->secretValue != NULL) {
+ /* use PasswordBasedMac according to 5.1.3.1 if secretValue is given */
+ if (!set_pbmac_algor(ctx, &msg->header->protectionAlg))
+ goto err;
+ if (!set_senderKID(ctx, msg, NULL))
+ goto err;
+
+ /*
+ * will add any additional certificates from ctx->extraCertsOut
+ * while not needed to validate the protection certificate,
+ * the option to do this might be handy for certain use cases
+ */
+ } else if (ctx->cert != NULL && ctx->pkey != NULL) {
+ /* use MSG_SIG_ALG according to 5.1.3.3 if client cert and key given */
+
+ /* make sure that key and certificate match */
+ if (!X509_check_private_key(ctx->cert, ctx->pkey)) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_CERT_AND_KEY_DO_NOT_MATCH);
+ goto err;
+ }
+
+ if (!set_sig_algor(ctx, &msg->header->protectionAlg))
+ goto err;
+ /* set senderKID to keyIdentifier of the cert according to 5.1.1 */
+ if (!set_senderKID(ctx, msg, X509_get0_subject_key_id(ctx->cert)))
+ goto err;
+
+ /*
+ * will add ctx->cert followed, if possible, by its chain built
+ * from ctx->untrusted, and then ctx->extraCertsOut
+ */
+ } else {
+ ERR_raise(ERR_LIB_CMP,
+ CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION);
+ goto err;
+ }
+ if (!ctx->unprotectedSend
+ && ((msg->protection = ossl_cmp_calc_protection(ctx, msg)) == NULL))
+ goto err;
+
+ /*
+ * For signature-based protection add ctx->cert followed by its chain.
+ * Finally add any additional certificates from ctx->extraCertsOut;
+ * even if not needed to validate the protection
+ * the option to do this might be handy for certain use cases.
+ */
+ if (!ossl_cmp_msg_add_extraCerts(ctx, msg))
+ goto err;
+
+ /*
+ * As required by RFC 4210 section 5.1.1., if the sender name is not known
+ * to the client it set to NULL-DN. In this case for identification at least
+ * the senderKID must be set, where we took the referenceValue as fallback.
+ */
+ if (!(ossl_cmp_general_name_is_NULL_DN(msg->header->sender)
+ && msg->header->senderKID == NULL))
+ return 1;
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_SENDER_IDENTIFICATION);
+
+ err:
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROTECTING_MESSAGE);
+ return 0;
+}
diff --git a/crypto/cmp/cmp_server.c b/crypto/cmp/cmp_server.c
new file mode 100644
index 000000000000..946c32c45ebf
--- /dev/null
+++ b/crypto/cmp/cmp_server.c
@@ -0,0 +1,644 @@
+/*
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* general CMP server functions */
+
+#include <openssl/asn1t.h>
+
+#include "cmp_local.h"
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <openssl/cmp.h>
+#include <openssl/err.h>
+
+/* the context for the generic CMP server */
+struct ossl_cmp_srv_ctx_st
+{
+ OSSL_CMP_CTX *ctx; /* Client CMP context, partly reused for srv */
+ void *custom_ctx; /* pointer to specific server context */
+
+ OSSL_CMP_SRV_cert_request_cb_t process_cert_request;
+ OSSL_CMP_SRV_rr_cb_t process_rr;
+ OSSL_CMP_SRV_genm_cb_t process_genm;
+ OSSL_CMP_SRV_error_cb_t process_error;
+ OSSL_CMP_SRV_certConf_cb_t process_certConf;
+ OSSL_CMP_SRV_pollReq_cb_t process_pollReq;
+
+ int sendUnprotectedErrors; /* Send error and rejection msgs unprotected */
+ int acceptUnprotected; /* Accept requests with no/invalid prot. */
+ int acceptRAVerified; /* Accept ir/cr/kur with POPO RAVerified */
+ int grantImplicitConfirm; /* Grant implicit confirmation if requested */
+
+}; /* OSSL_CMP_SRV_CTX */
+
+void OSSL_CMP_SRV_CTX_free(OSSL_CMP_SRV_CTX *srv_ctx)
+{
+ if (srv_ctx == NULL)
+ return;
+
+ OSSL_CMP_CTX_free(srv_ctx->ctx);
+ OPENSSL_free(srv_ctx);
+}
+
+OSSL_CMP_SRV_CTX *OSSL_CMP_SRV_CTX_new(OSSL_LIB_CTX *libctx, const char *propq)
+{
+ OSSL_CMP_SRV_CTX *ctx = OPENSSL_zalloc(sizeof(OSSL_CMP_SRV_CTX));
+
+ if (ctx == NULL)
+ goto err;
+
+ if ((ctx->ctx = OSSL_CMP_CTX_new(libctx, propq)) == NULL)
+ goto err;
+
+ /* all other elements are initialized to 0 or NULL, respectively */
+ return ctx;
+ err:
+ OSSL_CMP_SRV_CTX_free(ctx);
+ return NULL;
+}
+
+int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx,
+ OSSL_CMP_SRV_cert_request_cb_t process_cert_request,
+ OSSL_CMP_SRV_rr_cb_t process_rr,
+ OSSL_CMP_SRV_genm_cb_t process_genm,
+ OSSL_CMP_SRV_error_cb_t process_error,
+ OSSL_CMP_SRV_certConf_cb_t process_certConf,
+ OSSL_CMP_SRV_pollReq_cb_t process_pollReq)
+{
+ if (srv_ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ srv_ctx->custom_ctx = custom_ctx;
+ srv_ctx->process_cert_request = process_cert_request;
+ srv_ctx->process_rr = process_rr;
+ srv_ctx->process_genm = process_genm;
+ srv_ctx->process_error = process_error;
+ srv_ctx->process_certConf = process_certConf;
+ srv_ctx->process_pollReq = process_pollReq;
+ return 1;
+}
+
+OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx)
+{
+ if (srv_ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return srv_ctx->ctx;
+}
+
+void *OSSL_CMP_SRV_CTX_get0_custom_ctx(const OSSL_CMP_SRV_CTX *srv_ctx)
+{
+ if (srv_ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return srv_ctx->custom_ctx;
+}
+
+int OSSL_CMP_SRV_CTX_set_send_unprotected_errors(OSSL_CMP_SRV_CTX *srv_ctx,
+ int val)
+{
+ if (srv_ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ srv_ctx->sendUnprotectedErrors = val != 0;
+ return 1;
+}
+
+int OSSL_CMP_SRV_CTX_set_accept_unprotected(OSSL_CMP_SRV_CTX *srv_ctx, int val)
+{
+ if (srv_ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ srv_ctx->acceptUnprotected = val != 0;
+ return 1;
+}
+
+int OSSL_CMP_SRV_CTX_set_accept_raverified(OSSL_CMP_SRV_CTX *srv_ctx, int val)
+{
+ if (srv_ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ srv_ctx->acceptRAVerified = val != 0;
+ return 1;
+}
+
+int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx,
+ int val)
+{
+ if (srv_ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ srv_ctx->grantImplicitConfirm = val != 0;
+ return 1;
+}
+
+/*
+ * Processes an ir/cr/p10cr/kur and returns a certification response.
+ * Only handles the first certification request contained in req
+ * returns an ip/cp/kup on success and NULL on error
+ */
+static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req)
+{
+ OSSL_CMP_MSG *msg = NULL;
+ OSSL_CMP_PKISI *si = NULL;
+ X509 *certOut = NULL;
+ STACK_OF(X509) *chainOut = NULL, *caPubs = NULL;
+ const OSSL_CRMF_MSG *crm = NULL;
+ const X509_REQ *p10cr = NULL;
+ int bodytype;
+ int certReqId;
+
+ if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
+ return NULL;
+
+ switch (OSSL_CMP_MSG_get_bodytype(req)) {
+ case OSSL_CMP_PKIBODY_P10CR:
+ case OSSL_CMP_PKIBODY_CR:
+ bodytype = OSSL_CMP_PKIBODY_CP;
+ break;
+ case OSSL_CMP_PKIBODY_IR:
+ bodytype = OSSL_CMP_PKIBODY_IP;
+ break;
+ case OSSL_CMP_PKIBODY_KUR:
+ bodytype = OSSL_CMP_PKIBODY_KUP;
+ break;
+ default:
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ return NULL;
+ }
+
+ if (OSSL_CMP_MSG_get_bodytype(req) == OSSL_CMP_PKIBODY_P10CR) {
+ certReqId = OSSL_CMP_CERTREQID;
+ p10cr = req->body->value.p10cr;
+ } else {
+ OSSL_CRMF_MSGS *reqs = req->body->value.ir; /* same for cr and kur */
+
+ if (sk_OSSL_CRMF_MSG_num(reqs) != 1) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
+ return NULL;
+ }
+
+ if ((crm = sk_OSSL_CRMF_MSG_value(reqs, OSSL_CMP_CERTREQID)) == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_CERTREQMSG_NOT_FOUND);
+ return NULL;
+ }
+ certReqId = OSSL_CRMF_MSG_get_certReqId(crm);
+ }
+
+ if (!ossl_cmp_verify_popo(srv_ctx->ctx, req, srv_ctx->acceptRAVerified)) {
+ /* Proof of possession could not be verified */
+ si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection,
+ 1 << OSSL_CMP_PKIFAILUREINFO_badPOP,
+ ERR_reason_error_string(ERR_peek_error()));
+ if (si == NULL)
+ return NULL;
+ } else {
+ OSSL_CMP_PKIHEADER *hdr = OSSL_CMP_MSG_get0_header(req);
+
+ si = srv_ctx->process_cert_request(srv_ctx, req, certReqId, crm, p10cr,
+ &certOut, &chainOut, &caPubs);
+ if (si == NULL)
+ goto err;
+ /* set OSSL_CMP_OPT_IMPLICIT_CONFIRM if and only if transaction ends */
+ if (!OSSL_CMP_CTX_set_option(srv_ctx->ctx,
+ OSSL_CMP_OPT_IMPLICIT_CONFIRM,
+ ossl_cmp_hdr_has_implicitConfirm(hdr)
+ && srv_ctx->grantImplicitConfirm
+ /* do not set if polling starts: */
+ && certOut != NULL))
+ goto err;
+ }
+
+ msg = ossl_cmp_certrep_new(srv_ctx->ctx, bodytype, certReqId, si,
+ certOut, NULL /* enc */, chainOut, caPubs,
+ srv_ctx->sendUnprotectedErrors);
+ if (msg == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTREP);
+
+ err:
+ OSSL_CMP_PKISI_free(si);
+ X509_free(certOut);
+ sk_X509_pop_free(chainOut, X509_free);
+ sk_X509_pop_free(caPubs, X509_free);
+ return msg;
+}
+
+static OSSL_CMP_MSG *process_rr(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req)
+{
+ OSSL_CMP_MSG *msg = NULL;
+ OSSL_CMP_REVDETAILS *details;
+ OSSL_CRMF_CERTID *certId = NULL;
+ OSSL_CRMF_CERTTEMPLATE *tmpl;
+ const X509_NAME *issuer;
+ const ASN1_INTEGER *serial;
+ OSSL_CMP_PKISI *si;
+
+ if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
+ return NULL;
+
+ if (sk_OSSL_CMP_REVDETAILS_num(req->body->value.rr) != 1) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
+ return NULL;
+ }
+
+ if ((details = sk_OSSL_CMP_REVDETAILS_value(req->body->value.rr,
+ OSSL_CMP_REVREQSID)) == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
+ return NULL;
+ }
+
+ tmpl = details->certDetails;
+ issuer = OSSL_CRMF_CERTTEMPLATE_get0_issuer(tmpl);
+ serial = OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(tmpl);
+ if (issuer != NULL && serial != NULL
+ && (certId = OSSL_CRMF_CERTID_gen(issuer, serial)) == NULL)
+ return NULL;
+ if ((si = srv_ctx->process_rr(srv_ctx, req, issuer, serial)) == NULL)
+ goto err;
+
+ if ((msg = ossl_cmp_rp_new(srv_ctx->ctx, si, certId,
+ srv_ctx->sendUnprotectedErrors)) == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_RR);
+
+ err:
+ OSSL_CRMF_CERTID_free(certId);
+ OSSL_CMP_PKISI_free(si);
+ return msg;
+}
+
+/*
+ * Processes genm and creates a genp message mirroring the contents of the
+ * incoming message
+ */
+static OSSL_CMP_MSG *process_genm(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req)
+{
+ OSSL_CMP_GENMSGCONTENT *itavs;
+ OSSL_CMP_MSG *msg;
+
+ if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
+ return NULL;
+
+ if (!srv_ctx->process_genm(srv_ctx, req, req->body->value.genm, &itavs))
+ return NULL;
+
+ msg = ossl_cmp_genp_new(srv_ctx->ctx, itavs);
+ sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free);
+ return msg;
+}
+
+static OSSL_CMP_MSG *process_error(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req)
+{
+ OSSL_CMP_ERRORMSGCONTENT *errorContent;
+ OSSL_CMP_MSG *msg;
+
+ if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
+ return NULL;
+ errorContent = req->body->value.error;
+ srv_ctx->process_error(srv_ctx, req, errorContent->pKIStatusInfo,
+ errorContent->errorCode, errorContent->errorDetails);
+
+ if ((msg = ossl_cmp_pkiconf_new(srv_ctx->ctx)) == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_PKICONF);
+ return msg;
+}
+
+static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req)
+{
+ OSSL_CMP_CTX *ctx;
+ OSSL_CMP_CERTCONFIRMCONTENT *ccc;
+ int num;
+ OSSL_CMP_MSG *msg = NULL;
+ OSSL_CMP_CERTSTATUS *status = NULL;
+
+ if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
+ return NULL;
+
+ ctx = srv_ctx->ctx;
+ ccc = req->body->value.certConf;
+ num = sk_OSSL_CMP_CERTSTATUS_num(ccc);
+
+ if (OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM) == 1
+ || ctx->status != OSSL_CMP_PKISTATUS_trans) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_UNEXPECTED_CERTCONF);
+ return NULL;
+ }
+
+ if (num == 0) {
+ ossl_cmp_err(ctx, "certificate rejected by client");
+ } else {
+ if (num > 1)
+ ossl_cmp_warn(ctx, "All CertStatus but the first will be ignored");
+ status = sk_OSSL_CMP_CERTSTATUS_value(ccc, OSSL_CMP_CERTREQID);
+ }
+
+ if (status != NULL) {
+ int certReqId = ossl_cmp_asn1_get_int(status->certReqId);
+ ASN1_OCTET_STRING *certHash = status->certHash;
+ OSSL_CMP_PKISI *si = status->statusInfo;
+
+ if (!srv_ctx->process_certConf(srv_ctx, req, certReqId, certHash, si))
+ return NULL; /* reason code may be: CMP_R_CERTHASH_UNMATCHED */
+
+ if (si != NULL
+ && ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_accepted) {
+ int pki_status = ossl_cmp_pkisi_get_status(si);
+ const char *str = ossl_cmp_PKIStatus_to_string(pki_status);
+
+ ossl_cmp_log2(INFO, ctx, "certificate rejected by client %s %s",
+ str == NULL ? "without" : "with",
+ str == NULL ? "PKIStatus" : str);
+ }
+ }
+
+ if ((msg = ossl_cmp_pkiconf_new(ctx)) == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_PKICONF);
+ return msg;
+}
+
+static OSSL_CMP_MSG *process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req)
+{
+ OSSL_CMP_POLLREQCONTENT *prc;
+ OSSL_CMP_POLLREQ *pr;
+ int certReqId;
+ OSSL_CMP_MSG *certReq;
+ int64_t check_after = 0;
+ OSSL_CMP_MSG *msg = NULL;
+
+ if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
+ return NULL;
+
+ prc = req->body->value.pollReq;
+ if (sk_OSSL_CMP_POLLREQ_num(prc) != 1) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
+ return NULL;
+ }
+
+ pr = sk_OSSL_CMP_POLLREQ_value(prc, 0);
+ certReqId = ossl_cmp_asn1_get_int(pr->certReqId);
+ if (!srv_ctx->process_pollReq(srv_ctx, req, certReqId,
+ &certReq, &check_after))
+ return NULL;
+
+ if (certReq != NULL) {
+ msg = process_cert_request(srv_ctx, certReq);
+ OSSL_CMP_MSG_free(certReq);
+ } else {
+ if ((msg = ossl_cmp_pollRep_new(srv_ctx->ctx, certReqId,
+ check_after)) == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_POLLREP);
+ }
+ return msg;
+}
+
+/*
+ * Determine whether missing/invalid protection of request message is allowed.
+ * Return 1 on acceptance, 0 on rejection, or -1 on (internal) error.
+ */
+static int unprotected_exception(const OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *req,
+ int invalid_protection,
+ int accept_unprotected_requests)
+{
+ if (!ossl_assert(ctx != NULL && req != NULL))
+ return -1;
+
+ if (accept_unprotected_requests) {
+ ossl_cmp_log1(WARN, ctx, "ignoring %s protection of request message",
+ invalid_protection ? "invalid" : "missing");
+ return 1;
+ }
+ if (OSSL_CMP_MSG_get_bodytype(req) == OSSL_CMP_PKIBODY_ERROR
+ && OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS) == 1) {
+ ossl_cmp_warn(ctx, "ignoring missing protection of error message");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * returns created message and NULL on internal error
+ */
+OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req)
+{
+ OSSL_CMP_CTX *ctx;
+ ASN1_OCTET_STRING *backup_secret;
+ OSSL_CMP_PKIHEADER *hdr;
+ int req_type, rsp_type;
+ int res;
+ OSSL_CMP_MSG *rsp = NULL;
+
+ if (srv_ctx == NULL || srv_ctx->ctx == NULL
+ || req == NULL || req->body == NULL
+ || (hdr = OSSL_CMP_MSG_get0_header(req)) == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ ctx = srv_ctx->ctx;
+ backup_secret = ctx->secretValue;
+ req_type = OSSL_CMP_MSG_get_bodytype(req);
+ ossl_cmp_log1(DEBUG, ctx,
+ "received %s", ossl_cmp_bodytype_to_string(req_type));
+
+ /*
+ * Some things need to be done already before validating the message in
+ * order to be able to send an error message as far as needed and possible.
+ */
+ if (hdr->sender->type != GEN_DIRNAME) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
+ goto err;
+ }
+ if (!OSSL_CMP_CTX_set1_recipient(ctx, hdr->sender->d.directoryName))
+ goto err;
+
+ switch (req_type) {
+ case OSSL_CMP_PKIBODY_IR:
+ case OSSL_CMP_PKIBODY_CR:
+ case OSSL_CMP_PKIBODY_P10CR:
+ case OSSL_CMP_PKIBODY_KUR:
+ case OSSL_CMP_PKIBODY_RR:
+ case OSSL_CMP_PKIBODY_GENM:
+ case OSSL_CMP_PKIBODY_ERROR:
+ if (ctx->transactionID != NULL) {
+ char *tid;
+
+ tid = OPENSSL_buf2hexstr(ctx->transactionID->data,
+ ctx->transactionID->length);
+ if (tid != NULL)
+ ossl_cmp_log1(WARN, ctx,
+ "Assuming that last transaction with ID=%s got aborted",
+ tid);
+ OPENSSL_free(tid);
+ }
+ /* start of a new transaction, reset transactionID and senderNonce */
+ if (!OSSL_CMP_CTX_set1_transactionID(ctx, NULL)
+ || !OSSL_CMP_CTX_set1_senderNonce(ctx, NULL))
+ goto err;
+ break;
+ default:
+ /* transactionID should be already initialized */
+ if (ctx->transactionID == NULL) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ goto err;
+#endif
+ }
+ }
+
+ res = ossl_cmp_msg_check_update(ctx, req, unprotected_exception,
+ srv_ctx->acceptUnprotected);
+ if (ctx->secretValue != NULL && ctx->pkey != NULL
+ && ossl_cmp_hdr_get_protection_nid(hdr) != NID_id_PasswordBasedMAC)
+ ctx->secretValue = NULL; /* use MSG_SIG_ALG when protecting rsp */
+ if (!res)
+ goto err;
+
+ switch (req_type) {
+ case OSSL_CMP_PKIBODY_IR:
+ case OSSL_CMP_PKIBODY_CR:
+ case OSSL_CMP_PKIBODY_P10CR:
+ case OSSL_CMP_PKIBODY_KUR:
+ if (srv_ctx->process_cert_request == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ else
+ rsp = process_cert_request(srv_ctx, req);
+ break;
+ case OSSL_CMP_PKIBODY_RR:
+ if (srv_ctx->process_rr == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ else
+ rsp = process_rr(srv_ctx, req);
+ break;
+ case OSSL_CMP_PKIBODY_GENM:
+ if (srv_ctx->process_genm == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ else
+ rsp = process_genm(srv_ctx, req);
+ break;
+ case OSSL_CMP_PKIBODY_ERROR:
+ if (srv_ctx->process_error == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ else
+ rsp = process_error(srv_ctx, req);
+ break;
+ case OSSL_CMP_PKIBODY_CERTCONF:
+ if (srv_ctx->process_certConf == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ else
+ rsp = process_certConf(srv_ctx, req);
+ break;
+ case OSSL_CMP_PKIBODY_POLLREQ:
+ if (srv_ctx->process_pollReq == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ else
+ rsp = process_pollReq(srv_ctx, req);
+ break;
+ default:
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ break;
+ }
+
+ err:
+ if (rsp == NULL) {
+ /* on error, try to respond with CMP error message to client */
+ const char *data = NULL, *reason = NULL;
+ int flags = 0;
+ unsigned long err = ERR_peek_error_data(&data, &flags);
+ int fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_badRequest;
+ OSSL_CMP_PKISI *si = NULL;
+
+ if (ctx->transactionID == NULL) {
+ /* ignore any (extra) error in next two function calls: */
+ (void)OSSL_CMP_CTX_set1_transactionID(ctx, hdr->transactionID);
+ (void)ossl_cmp_ctx_set1_recipNonce(ctx, hdr->senderNonce);
+ }
+
+ if ((flags & ERR_TXT_STRING) == 0 || *data == '\0')
+ data = NULL;
+ reason = ERR_reason_error_string(err);
+ if ((si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection,
+ fail_info, reason)) != NULL) {
+ rsp = ossl_cmp_error_new(srv_ctx->ctx, si, err,
+ data, srv_ctx->sendUnprotectedErrors);
+ OSSL_CMP_PKISI_free(si);
+ }
+ }
+ OSSL_CMP_CTX_print_errors(ctx);
+ ctx->secretValue = backup_secret;
+
+ rsp_type =
+ rsp != NULL ? OSSL_CMP_MSG_get_bodytype(rsp) : OSSL_CMP_PKIBODY_ERROR;
+ if (rsp != NULL)
+ ossl_cmp_log1(DEBUG, ctx,
+ "sending %s", ossl_cmp_bodytype_to_string(rsp_type));
+ else
+ ossl_cmp_log(ERR, ctx, "cannot send proper CMP response");
+
+ /* determine whether to keep the transaction open or not */
+ ctx->status = OSSL_CMP_PKISTATUS_trans;
+ switch (rsp_type) {
+ case OSSL_CMP_PKIBODY_IP:
+ case OSSL_CMP_PKIBODY_CP:
+ case OSSL_CMP_PKIBODY_KUP:
+ if (OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM) == 0)
+ break;
+ /* fall through */
+
+ case OSSL_CMP_PKIBODY_RP:
+ case OSSL_CMP_PKIBODY_PKICONF:
+ case OSSL_CMP_PKIBODY_GENP:
+ case OSSL_CMP_PKIBODY_ERROR:
+ (void)OSSL_CMP_CTX_set1_transactionID(ctx, NULL);
+ (void)OSSL_CMP_CTX_set1_senderNonce(ctx, NULL);
+ ctx->status = OSSL_CMP_PKISTATUS_unspecified; /* transaction closed */
+
+ default: /* not closing transaction in other cases */
+ break;
+ }
+ return rsp;
+}
+
+/*
+ * Server interface that may substitute OSSL_CMP_MSG_http_perform at the client.
+ * The OSSL_CMP_SRV_CTX must be set as client_ctx->transfer_cb_arg.
+ * returns received message on success, else NULL and pushes an element on the
+ * error stack.
+ */
+OSSL_CMP_MSG *OSSL_CMP_CTX_server_perform(OSSL_CMP_CTX *client_ctx,
+ const OSSL_CMP_MSG *req)
+{
+ OSSL_CMP_SRV_CTX *srv_ctx = NULL;
+
+ if (client_ctx == NULL || req == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+
+ if ((srv_ctx = OSSL_CMP_CTX_get_transfer_cb_arg(client_ctx)) == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_TRANSFER_ERROR);
+ return NULL;
+ }
+
+ return OSSL_CMP_SRV_process_request(srv_ctx, req);
+}
diff --git a/crypto/cmp/cmp_status.c b/crypto/cmp/cmp_status.c
new file mode 100644
index 000000000000..bfe6cd9906b8
--- /dev/null
+++ b/crypto/cmp/cmp_status.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* CMP functions for PKIStatusInfo handling and PKIMessage decomposition */
+
+#include <string.h>
+
+#include "cmp_local.h"
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <time.h>
+#include <openssl/cmp.h>
+#include <openssl/crmf.h>
+#include <openssl/err.h> /* needed in case config no-deprecated */
+#include <openssl/engine.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/x509.h>
+#include <openssl/asn1err.h> /* for ASN1_R_TOO_SMALL and ASN1_R_TOO_LARGE */
+
+/* CMP functions related to PKIStatus */
+
+int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si)
+{
+ if (!ossl_assert(si != NULL && si->status != NULL))
+ return -1;
+ return ossl_cmp_asn1_get_int(si->status);
+}
+
+const char *ossl_cmp_PKIStatus_to_string(int status)
+{
+ switch (status) {
+ case OSSL_CMP_PKISTATUS_accepted:
+ return "PKIStatus: accepted";
+ case OSSL_CMP_PKISTATUS_grantedWithMods:
+ return "PKIStatus: granted with modifications";
+ case OSSL_CMP_PKISTATUS_rejection:
+ return "PKIStatus: rejection";
+ case OSSL_CMP_PKISTATUS_waiting:
+ return "PKIStatus: waiting";
+ case OSSL_CMP_PKISTATUS_revocationWarning:
+ return "PKIStatus: revocation warning - a revocation of the cert is imminent";
+ case OSSL_CMP_PKISTATUS_revocationNotification:
+ return "PKIStatus: revocation notification - a revocation of the cert has occurred";
+ case OSSL_CMP_PKISTATUS_keyUpdateWarning:
+ return "PKIStatus: key update warning - update already done for the cert";
+ default:
+ ERR_raise_data(ERR_LIB_CMP, CMP_R_ERROR_PARSING_PKISTATUS,
+ "PKIStatus: invalid=%d", status);
+ return NULL;
+ }
+}
+
+OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusString(const OSSL_CMP_PKISI *si)
+{
+ if (!ossl_assert(si != NULL))
+ return NULL;
+ return si->statusString;
+}
+
+int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si)
+{
+ int i;
+ int res = 0;
+
+ if (!ossl_assert(si != NULL))
+ return -1;
+ if (si->failInfo != NULL)
+ for (i = 0; i <= OSSL_CMP_PKIFAILUREINFO_MAX; i++)
+ if (ASN1_BIT_STRING_get_bit(si->failInfo, i))
+ res |= 1 << i;
+ return res;
+}
+
+/*-
+ * convert PKIFailureInfo number to human-readable string
+ * returns pointer to static string, or NULL on error
+ */
+static const char *CMP_PKIFAILUREINFO_to_string(int number)
+{
+ switch (number) {
+ case OSSL_CMP_PKIFAILUREINFO_badAlg:
+ return "badAlg";
+ case OSSL_CMP_PKIFAILUREINFO_badMessageCheck:
+ return "badMessageCheck";
+ case OSSL_CMP_PKIFAILUREINFO_badRequest:
+ return "badRequest";
+ case OSSL_CMP_PKIFAILUREINFO_badTime:
+ return "badTime";
+ case OSSL_CMP_PKIFAILUREINFO_badCertId:
+ return "badCertId";
+ case OSSL_CMP_PKIFAILUREINFO_badDataFormat:
+ return "badDataFormat";
+ case OSSL_CMP_PKIFAILUREINFO_wrongAuthority:
+ return "wrongAuthority";
+ case OSSL_CMP_PKIFAILUREINFO_incorrectData:
+ return "incorrectData";
+ case OSSL_CMP_PKIFAILUREINFO_missingTimeStamp:
+ return "missingTimeStamp";
+ case OSSL_CMP_PKIFAILUREINFO_badPOP:
+ return "badPOP";
+ case OSSL_CMP_PKIFAILUREINFO_certRevoked:
+ return "certRevoked";
+ case OSSL_CMP_PKIFAILUREINFO_certConfirmed:
+ return "certConfirmed";
+ case OSSL_CMP_PKIFAILUREINFO_wrongIntegrity:
+ return "wrongIntegrity";
+ case OSSL_CMP_PKIFAILUREINFO_badRecipientNonce:
+ return "badRecipientNonce";
+ case OSSL_CMP_PKIFAILUREINFO_timeNotAvailable:
+ return "timeNotAvailable";
+ case OSSL_CMP_PKIFAILUREINFO_unacceptedPolicy:
+ return "unacceptedPolicy";
+ case OSSL_CMP_PKIFAILUREINFO_unacceptedExtension:
+ return "unacceptedExtension";
+ case OSSL_CMP_PKIFAILUREINFO_addInfoNotAvailable:
+ return "addInfoNotAvailable";
+ case OSSL_CMP_PKIFAILUREINFO_badSenderNonce:
+ return "badSenderNonce";
+ case OSSL_CMP_PKIFAILUREINFO_badCertTemplate:
+ return "badCertTemplate";
+ case OSSL_CMP_PKIFAILUREINFO_signerNotTrusted:
+ return "signerNotTrusted";
+ case OSSL_CMP_PKIFAILUREINFO_transactionIdInUse:
+ return "transactionIdInUse";
+ case OSSL_CMP_PKIFAILUREINFO_unsupportedVersion:
+ return "unsupportedVersion";
+ case OSSL_CMP_PKIFAILUREINFO_notAuthorized:
+ return "notAuthorized";
+ case OSSL_CMP_PKIFAILUREINFO_systemUnavail:
+ return "systemUnavail";
+ case OSSL_CMP_PKIFAILUREINFO_systemFailure:
+ return "systemFailure";
+ case OSSL_CMP_PKIFAILUREINFO_duplicateCertReq:
+ return "duplicateCertReq";
+ default:
+ return NULL; /* illegal failure number */
+ }
+}
+
+int ossl_cmp_pkisi_check_pkifailureinfo(const OSSL_CMP_PKISI *si, int bit_index)
+{
+ if (!ossl_assert(si != NULL && si->failInfo != NULL))
+ return -1;
+ if (bit_index < 0 || bit_index > OSSL_CMP_PKIFAILUREINFO_MAX) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
+ return -1;
+ }
+
+ return ASN1_BIT_STRING_get_bit(si->failInfo, bit_index);
+}
+
+/*-
+ * place human-readable error string created from PKIStatusInfo in given buffer
+ * returns pointer to the same buffer containing the string, or NULL on error
+ */
+static
+char *snprint_PKIStatusInfo_parts(int status, int fail_info,
+ const OSSL_CMP_PKIFREETEXT *status_strings,
+ char *buf, size_t bufsize)
+{
+ int failure;
+ const char *status_string, *failure_string;
+ ASN1_UTF8STRING *text;
+ int i;
+ int printed_chars;
+ int failinfo_found = 0;
+ int n_status_strings;
+ char *write_ptr = buf;
+
+ if (buf == NULL
+ || status < 0
+ || (status_string = ossl_cmp_PKIStatus_to_string(status)) == NULL)
+ return NULL;
+
+#define ADVANCE_BUFFER \
+ if (printed_chars < 0 || (size_t)printed_chars >= bufsize) \
+ return NULL; \
+ write_ptr += printed_chars; \
+ bufsize -= printed_chars;
+
+ printed_chars = BIO_snprintf(write_ptr, bufsize, "%s", status_string);
+ ADVANCE_BUFFER;
+
+ /*
+ * failInfo is optional and may be empty;
+ * if present, print failInfo before statusString because it is more concise
+ */
+ if (fail_info != -1 && fail_info != 0) {
+ printed_chars = BIO_snprintf(write_ptr, bufsize, "; PKIFailureInfo: ");
+ ADVANCE_BUFFER;
+ for (failure = 0; failure <= OSSL_CMP_PKIFAILUREINFO_MAX; failure++) {
+ if ((fail_info & (1 << failure)) != 0) {
+ failure_string = CMP_PKIFAILUREINFO_to_string(failure);
+ if (failure_string != NULL) {
+ printed_chars = BIO_snprintf(write_ptr, bufsize, "%s%s",
+ failinfo_found ? ", " : "",
+ failure_string);
+ ADVANCE_BUFFER;
+ failinfo_found = 1;
+ }
+ }
+ }
+ }
+ if (!failinfo_found && status != OSSL_CMP_PKISTATUS_accepted
+ && status != OSSL_CMP_PKISTATUS_grantedWithMods) {
+ printed_chars = BIO_snprintf(write_ptr, bufsize, "; <no failure info>");
+ ADVANCE_BUFFER;
+ }
+
+ /* statusString sequence is optional and may be empty */
+ n_status_strings = sk_ASN1_UTF8STRING_num(status_strings);
+ if (n_status_strings > 0) {
+ printed_chars = BIO_snprintf(write_ptr, bufsize, "; StatusString%s: ",
+ n_status_strings > 1 ? "s" : "");
+ ADVANCE_BUFFER;
+ for (i = 0; i < n_status_strings; i++) {
+ text = sk_ASN1_UTF8STRING_value(status_strings, i);
+ printed_chars = BIO_snprintf(write_ptr, bufsize, "\"%.*s\"%s",
+ ASN1_STRING_length(text),
+ ASN1_STRING_get0_data(text),
+ i < n_status_strings - 1 ? ", " : "");
+ ADVANCE_BUFFER;
+ }
+ }
+#undef ADVANCE_BUFFER
+ return buf;
+}
+
+char *OSSL_CMP_snprint_PKIStatusInfo(const OSSL_CMP_PKISI *statusInfo,
+ char *buf, size_t bufsize)
+{
+ int failure_info;
+
+ if (statusInfo == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+
+ failure_info = ossl_cmp_pkisi_get_pkifailureinfo(statusInfo);
+
+ return snprint_PKIStatusInfo_parts(ASN1_INTEGER_get(statusInfo->status),
+ failure_info,
+ statusInfo->statusString, buf, bufsize);
+}
+
+char *OSSL_CMP_CTX_snprint_PKIStatus(const OSSL_CMP_CTX *ctx, char *buf,
+ size_t bufsize)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+
+ return snprint_PKIStatusInfo_parts(OSSL_CMP_CTX_get_status(ctx),
+ OSSL_CMP_CTX_get_failInfoCode(ctx),
+ OSSL_CMP_CTX_get0_statusString(ctx),
+ buf, bufsize);
+}
+
+/*-
+ * Creates a new PKIStatusInfo structure and fills it in
+ * returns a pointer to the structure on success, NULL on error
+ * note: strongly overlaps with TS_RESP_CTX_set_status_info()
+ * and TS_RESP_CTX_add_failure_info() in ../ts/ts_rsp_sign.c
+ */
+OSSL_CMP_PKISI *OSSL_CMP_STATUSINFO_new(int status, int fail_info,
+ const char *text)
+{
+ OSSL_CMP_PKISI *si = OSSL_CMP_PKISI_new();
+ ASN1_UTF8STRING *utf8_text = NULL;
+ int failure;
+
+ if (si == NULL)
+ goto err;
+ if (!ASN1_INTEGER_set(si->status, status))
+ goto err;
+
+ if (text != NULL) {
+ if ((utf8_text = ASN1_UTF8STRING_new()) == NULL
+ || !ASN1_STRING_set(utf8_text, text, -1))
+ goto err;
+ if ((si->statusString = sk_ASN1_UTF8STRING_new_null()) == NULL)
+ goto err;
+ if (!sk_ASN1_UTF8STRING_push(si->statusString, utf8_text))
+ goto err;
+ /* Ownership is lost. */
+ utf8_text = NULL;
+ }
+
+ for (failure = 0; failure <= OSSL_CMP_PKIFAILUREINFO_MAX; failure++) {
+ if ((fail_info & (1 << failure)) != 0) {
+ if (si->failInfo == NULL
+ && (si->failInfo = ASN1_BIT_STRING_new()) == NULL)
+ goto err;
+ if (!ASN1_BIT_STRING_set_bit(si->failInfo, failure, 1))
+ goto err;
+ }
+ }
+ return si;
+
+ err:
+ OSSL_CMP_PKISI_free(si);
+ ASN1_UTF8STRING_free(utf8_text);
+ return NULL;
+}
diff --git a/crypto/cmp/cmp_util.c b/crypto/cmp/cmp_util.c
new file mode 100644
index 000000000000..7cf27cc9d4b4
--- /dev/null
+++ b/crypto/cmp/cmp_util.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/cmp_util.h>
+#include "cmp_local.h" /* just for decls of internal functions defined here */
+#include <openssl/cmperr.h>
+#include <openssl/err.h> /* should be implied by cmperr.h */
+#include <openssl/x509v3.h>
+
+/*
+ * use trace API for CMP-specific logging, prefixed by "CMP " and severity
+ */
+
+int OSSL_CMP_log_open(void) /* is designed to be idempotent */
+{
+#ifdef OPENSSL_NO_TRACE
+ return 1;
+#else
+# ifndef OPENSSL_NO_STDIO
+ BIO *bio = BIO_new_fp(stdout, BIO_NOCLOSE);
+
+ if (bio != NULL && OSSL_trace_set_channel(OSSL_TRACE_CATEGORY_CMP, bio))
+ return 1;
+ BIO_free(bio);
+# endif
+ ERR_raise(ERR_LIB_CMP, CMP_R_NO_STDIO);
+ return 0;
+#endif
+}
+
+void OSSL_CMP_log_close(void) /* is designed to be idempotent */
+{
+ (void)OSSL_trace_set_channel(OSSL_TRACE_CATEGORY_CMP, NULL);
+}
+
+/* return >= 0 if level contains logging level, possibly preceded by "CMP " */
+#define max_level_len 5 /* = max length of the below strings, e.g., "EMERG" */
+static OSSL_CMP_severity parse_level(const char *level)
+{
+ const char *end_level = strchr(level, ':');
+ int len;
+ char level_copy[max_level_len + 1];
+
+ if (end_level == NULL)
+ return -1;
+
+ if (strncmp(level, OSSL_CMP_LOG_PREFIX,
+ strlen(OSSL_CMP_LOG_PREFIX)) == 0)
+ level += strlen(OSSL_CMP_LOG_PREFIX);
+ len = end_level - level;
+ if (len > max_level_len)
+ return -1;
+ OPENSSL_strlcpy(level_copy, level, len + 1);
+ return
+ strcmp(level_copy, "EMERG") == 0 ? OSSL_CMP_LOG_EMERG :
+ strcmp(level_copy, "ALERT") == 0 ? OSSL_CMP_LOG_ALERT :
+ strcmp(level_copy, "CRIT") == 0 ? OSSL_CMP_LOG_CRIT :
+ strcmp(level_copy, "ERROR") == 0 ? OSSL_CMP_LOG_ERR :
+ strcmp(level_copy, "WARN") == 0 ? OSSL_CMP_LOG_WARNING :
+ strcmp(level_copy, "NOTE") == 0 ? OSSL_CMP_LOG_NOTICE :
+ strcmp(level_copy, "INFO") == 0 ? OSSL_CMP_LOG_INFO :
+ strcmp(level_copy, "DEBUG") == 0 ? OSSL_CMP_LOG_DEBUG :
+ -1;
+}
+
+const char *ossl_cmp_log_parse_metadata(const char *buf,
+ OSSL_CMP_severity *level,
+ char **func, char **file, int *line)
+{
+ const char *p_func = buf;
+ const char *p_file = buf == NULL ? NULL : strchr(buf, ':');
+ const char *p_level = buf;
+ const char *msg = buf;
+
+ *level = -1;
+ *func = NULL;
+ *file = NULL;
+ *line = 0;
+
+ if (p_file != NULL) {
+ const char *p_line = strchr(++p_file, ':');
+
+ if ((*level = parse_level(buf)) < 0 && p_line != NULL) {
+ /* check if buf contains location info and logging level */
+ char *p_level_tmp = (char *)p_level;
+ const long line_number = strtol(++p_line, &p_level_tmp, 10);
+
+ p_level = p_level_tmp;
+ if (p_level > p_line && *(p_level++) == ':') {
+ if ((*level = parse_level(p_level)) >= 0) {
+ *func = OPENSSL_strndup(p_func, p_file - 1 - p_func);
+ *file = OPENSSL_strndup(p_file, p_line - 1 - p_file);
+ /* no real problem if OPENSSL_strndup() returns NULL */
+ *line = (int)line_number;
+ msg = strchr(p_level, ':');
+ if (msg != NULL && *++msg == ' ')
+ msg++;
+ }
+ }
+ }
+ }
+ return msg;
+}
+
+#define UNKNOWN_FUNC "(unknown function)" /* the default for OPENSSL_FUNC */
+/*
+ * substitute fallback if component/function name is NULL or empty or contains
+ * just pseudo-information "(unknown function)" due to -pedantic and macros.h
+ */
+static const char *improve_location_name(const char *func, const char *fallback)
+{
+ if (fallback == NULL)
+ return func == NULL ? UNKNOWN_FUNC : func;
+
+ return func == NULL || *func == '\0' || strcmp(func, UNKNOWN_FUNC) == 0
+ ? fallback : func;
+}
+
+int OSSL_CMP_print_to_bio(BIO *bio, const char *component, const char *file,
+ int line, OSSL_CMP_severity level, const char *msg)
+{
+ const char *level_string =
+ level == OSSL_CMP_LOG_EMERG ? "EMERG" :
+ level == OSSL_CMP_LOG_ALERT ? "ALERT" :
+ level == OSSL_CMP_LOG_CRIT ? "CRIT" :
+ level == OSSL_CMP_LOG_ERR ? "error" :
+ level == OSSL_CMP_LOG_WARNING ? "warning" :
+ level == OSSL_CMP_LOG_NOTICE ? "NOTE" :
+ level == OSSL_CMP_LOG_INFO ? "info" :
+ level == OSSL_CMP_LOG_DEBUG ? "DEBUG" : "(unknown level)";
+
+#ifndef NDEBUG
+ if (BIO_printf(bio, "%s:%s:%d:", improve_location_name(component, "CMP"),
+ file, line) < 0)
+ return 0;
+#endif
+ return BIO_printf(bio, OSSL_CMP_LOG_PREFIX"%s: %s\n",
+ level_string, msg) >= 0;
+}
+
+#define ERR_PRINT_BUF_SIZE 4096
+/* this is similar to ERR_print_errors_cb, but uses the CMP-specific cb type */
+void OSSL_CMP_print_errors_cb(OSSL_CMP_log_cb_t log_fn)
+{
+ unsigned long err;
+ char msg[ERR_PRINT_BUF_SIZE];
+ const char *file = NULL, *func = NULL, *data = NULL;
+ int line, flags;
+
+ while ((err = ERR_get_error_all(&file, &line, &func, &data, &flags)) != 0) {
+ const char *component =
+ improve_location_name(func, ERR_lib_error_string(err));
+ unsigned long reason = ERR_GET_REASON(err);
+ const char *rs = NULL;
+ char rsbuf[256];
+
+#ifndef OPENSSL_NO_ERR
+ if (ERR_SYSTEM_ERROR(err)) {
+ if (openssl_strerror_r(reason, rsbuf, sizeof(rsbuf)))
+ rs = rsbuf;
+ } else {
+ rs = ERR_reason_error_string(err);
+ }
+#endif
+ if (rs == NULL) {
+ BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", reason);
+ rs = rsbuf;
+ }
+ if (data != NULL && (flags & ERR_TXT_STRING) != 0)
+ BIO_snprintf(msg, sizeof(msg), "%s:%s", rs, data);
+ else
+ BIO_snprintf(msg, sizeof(msg), "%s", rs);
+
+ if (log_fn == NULL) {
+#ifndef OPENSSL_NO_STDIO
+ BIO *bio = BIO_new_fp(stderr, BIO_NOCLOSE);
+
+ if (bio != NULL) {
+ OSSL_CMP_print_to_bio(bio, component, file, line,
+ OSSL_CMP_LOG_ERR, msg);
+ BIO_free(bio);
+ }
+#else
+ /* ERR_raise(ERR_LIB_CMP, CMP_R_NO_STDIO) makes no sense during error printing */
+#endif
+ } else {
+ if (log_fn(component, file, line, OSSL_CMP_LOG_ERR, msg) <= 0)
+ break; /* abort outputting the error report */
+ }
+ }
+}
+
+int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
+ int only_self_signed)
+{
+ int i;
+
+ if (store == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (certs == NULL)
+ return 1;
+ for (i = 0; i < sk_X509_num(certs); i++) {
+ X509 *cert = sk_X509_value(certs, i);
+
+ if (!only_self_signed || X509_self_signed(cert, 0) == 1)
+ if (!X509_STORE_add_cert(store, cert)) /* ups cert ref counter */
+ return 0;
+ }
+ return 1;
+}
+
+int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING) *sk,
+ const char *text, int len)
+{
+ ASN1_UTF8STRING *utf8string;
+
+ if (!ossl_assert(sk != NULL && text != NULL))
+ return 0;
+ if ((utf8string = ASN1_UTF8STRING_new()) == NULL)
+ return 0;
+ if (!ASN1_STRING_set(utf8string, text, len))
+ goto err;
+ if (!sk_ASN1_UTF8STRING_push(sk, utf8string))
+ goto err;
+ return 1;
+
+ err:
+ ASN1_UTF8STRING_free(utf8string);
+ return 0;
+}
+
+int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt,
+ const ASN1_OCTET_STRING *src)
+{
+ ASN1_OCTET_STRING *new;
+ if (tgt == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (*tgt == src) /* self-assignment */
+ return 1;
+
+ if (src != NULL) {
+ if ((new = ASN1_OCTET_STRING_dup(src)) == NULL)
+ return 0;
+ } else {
+ new = NULL;
+ }
+
+ ASN1_OCTET_STRING_free(*tgt);
+ *tgt = new;
+ return 1;
+}
+
+int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING **tgt,
+ const unsigned char *bytes, int len)
+{
+ ASN1_OCTET_STRING *new = NULL;
+
+ if (tgt == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (bytes != NULL) {
+ if ((new = ASN1_OCTET_STRING_new()) == NULL
+ || !(ASN1_OCTET_STRING_set(new, bytes, len))) {
+ ASN1_OCTET_STRING_free(new);
+ return 0;
+ }
+ }
+
+ ASN1_OCTET_STRING_free(*tgt);
+ *tgt = new;
+ return 1;
+}
diff --git a/crypto/cmp/cmp_vfy.c b/crypto/cmp/cmp_vfy.c
new file mode 100644
index 000000000000..99cd56cb091f
--- /dev/null
+++ b/crypto/cmp/cmp_vfy.c
@@ -0,0 +1,856 @@
+/*
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2020
+ * Copyright Siemens AG 2015-2020
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* CMP functions for PKIMessage checking */
+
+#include "cmp_local.h"
+#include <openssl/cmp_util.h>
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <openssl/asn1t.h>
+#include <openssl/cmp.h>
+#include <openssl/crmf.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+
+/* Verify a message protected by signature according to RFC section 5.1.3.3 */
+static int verify_signature(const OSSL_CMP_CTX *cmp_ctx,
+ const OSSL_CMP_MSG *msg, X509 *cert)
+{
+ OSSL_CMP_PROTECTEDPART prot_part;
+ EVP_PKEY *pubkey = NULL;
+ BIO *bio;
+ int res = 0;
+
+ if (!ossl_assert(cmp_ctx != NULL && msg != NULL && cert != NULL))
+ return 0;
+
+ bio = BIO_new(BIO_s_mem()); /* may be NULL */
+
+ /* verify that keyUsage, if present, contains digitalSignature */
+ if (!cmp_ctx->ignore_keyusage
+ && (X509_get_key_usage(cert) & X509v3_KU_DIGITAL_SIGNATURE) == 0) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE);
+ goto sig_err;
+ }
+
+ pubkey = X509_get_pubkey(cert);
+ if (pubkey == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_FAILED_EXTRACTING_PUBKEY);
+ goto sig_err;
+ }
+
+ prot_part.header = msg->header;
+ prot_part.body = msg->body;
+
+ if (ASN1_item_verify_ex(ASN1_ITEM_rptr(OSSL_CMP_PROTECTEDPART),
+ msg->header->protectionAlg, msg->protection,
+ &prot_part, NULL, pubkey, cmp_ctx->libctx,
+ cmp_ctx->propq) > 0) {
+ res = 1;
+ goto end;
+ }
+
+ sig_err:
+ res = ossl_x509_print_ex_brief(bio, cert, X509_FLAG_NO_EXTENSIONS);
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_SIGNATURE);
+ if (res)
+ ERR_add_error_mem_bio("\n", bio);
+ res = 0;
+
+ end:
+ EVP_PKEY_free(pubkey);
+ BIO_free(bio);
+
+ return res;
+}
+
+/* Verify a message protected with PBMAC */
+static int verify_PBMAC(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
+{
+ ASN1_BIT_STRING *protection = NULL;
+ int valid = 0;
+
+ /* generate expected protection for the message */
+ if ((protection = ossl_cmp_calc_protection(ctx, msg)) == NULL)
+ return 0; /* failed to generate protection string! */
+
+ valid = msg->protection != NULL && msg->protection->length >= 0
+ && msg->protection->type == protection->type
+ && msg->protection->length == protection->length
+ && CRYPTO_memcmp(msg->protection->data, protection->data,
+ protection->length) == 0;
+ ASN1_BIT_STRING_free(protection);
+ if (!valid)
+ ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_PBM_VALUE);
+
+ return valid;
+}
+
+/*-
+ * Attempt to validate certificate and path using any given store with trusted
+ * certs (possibly including CRLs and a cert verification callback function)
+ * and non-trusted intermediate certs from the given ctx.
+ *
+ * Returns 1 on successful validation and 0 otherwise.
+ */
+int OSSL_CMP_validate_cert_path(const OSSL_CMP_CTX *ctx,
+ X509_STORE *trusted_store, X509 *cert)
+{
+ int valid = 0;
+ X509_STORE_CTX *csc = NULL;
+ int err;
+
+ if (ctx == NULL || cert == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (trusted_store == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_TRUST_STORE);
+ return 0;
+ }
+
+ if ((csc = X509_STORE_CTX_new_ex(ctx->libctx, ctx->propq)) == NULL
+ || !X509_STORE_CTX_init(csc, trusted_store,
+ cert, ctx->untrusted))
+ goto err;
+
+ valid = X509_verify_cert(csc) > 0;
+
+ /* make sure suitable error is queued even if callback did not do */
+ err = ERR_peek_last_error();
+ if (!valid && ERR_GET_REASON(err) != CMP_R_POTENTIALLY_INVALID_CERTIFICATE)
+ ERR_raise(ERR_LIB_CMP, CMP_R_POTENTIALLY_INVALID_CERTIFICATE);
+
+ err:
+ /* directly output any fresh errors, needed for check_msg_find_cert() */
+ OSSL_CMP_CTX_print_errors(ctx);
+ X509_STORE_CTX_free(csc);
+ return valid;
+}
+
+/* Return 0 if expect_name != NULL and there is no matching actual_name */
+static int check_name(const OSSL_CMP_CTX *ctx, int log_success,
+ const char *actual_desc, const X509_NAME *actual_name,
+ const char *expect_desc, const X509_NAME *expect_name)
+{
+ char *str;
+
+ if (expect_name == NULL)
+ return 1; /* no expectation, thus trivially fulfilled */
+
+ /* make sure that a matching name is there */
+ if (actual_name == NULL) {
+ ossl_cmp_log1(WARN, ctx, "missing %s", actual_desc);
+ return 0;
+ }
+ str = X509_NAME_oneline(actual_name, NULL, 0);
+ if (X509_NAME_cmp(actual_name, expect_name) == 0) {
+ if (log_success && str != NULL)
+ ossl_cmp_log2(INFO, ctx, " subject matches %s: %s", expect_desc,
+ str);
+ OPENSSL_free(str);
+ return 1;
+ }
+
+ if (str != NULL)
+ ossl_cmp_log2(INFO, ctx, " actual name in %s = %s", actual_desc, str);
+ OPENSSL_free(str);
+ if ((str = X509_NAME_oneline(expect_name, NULL, 0)) != NULL)
+ ossl_cmp_log2(INFO, ctx, " does not match %s = %s", expect_desc, str);
+ OPENSSL_free(str);
+ return 0;
+}
+
+/* Return 0 if skid != NULL and there is no matching subject key ID in cert */
+static int check_kid(const OSSL_CMP_CTX *ctx,
+ const ASN1_OCTET_STRING *ckid,
+ const ASN1_OCTET_STRING *skid)
+{
+ char *str;
+
+ if (skid == NULL)
+ return 1; /* no expectation, thus trivially fulfilled */
+
+ /* make sure that the expected subject key identifier is there */
+ if (ckid == NULL) {
+ ossl_cmp_warn(ctx, "missing Subject Key Identifier in certificate");
+ return 0;
+ }
+ str = OPENSSL_buf2hexstr(ckid->data, ckid->length);
+ if (ASN1_OCTET_STRING_cmp(ckid, skid) == 0) {
+ if (str != NULL)
+ ossl_cmp_log1(INFO, ctx, " subjectKID matches senderKID: %s", str);
+ OPENSSL_free(str);
+ return 1;
+ }
+
+ if (str != NULL)
+ ossl_cmp_log1(INFO, ctx, " cert Subject Key Identifier = %s", str);
+ OPENSSL_free(str);
+ if ((str = OPENSSL_buf2hexstr(skid->data, skid->length)) != NULL)
+ ossl_cmp_log1(INFO, ctx, " does not match senderKID = %s", str);
+ OPENSSL_free(str);
+ return 0;
+}
+
+static int already_checked(const X509 *cert,
+ const STACK_OF(X509) *already_checked)
+{
+ int i;
+
+ for (i = sk_X509_num(already_checked /* may be NULL */); i > 0; i--)
+ if (X509_cmp(sk_X509_value(already_checked, i - 1), cert) == 0)
+ return 1;
+ return 0;
+}
+
+/*-
+ * Check if the given cert is acceptable as sender cert of the given message.
+ * The subject DN must match, the subject key ID as well if present in the msg,
+ * and the cert must be current (checked if ctx->trusted is not NULL).
+ * Note that cert revocation etc. is checked by OSSL_CMP_validate_cert_path().
+ *
+ * Returns 0 on error or not acceptable, else 1.
+ */
+static int cert_acceptable(const OSSL_CMP_CTX *ctx,
+ const char *desc1, const char *desc2, X509 *cert,
+ const STACK_OF(X509) *already_checked1,
+ const STACK_OF(X509) *already_checked2,
+ const OSSL_CMP_MSG *msg)
+{
+ X509_STORE *ts = ctx->trusted;
+ int self_issued = X509_check_issued(cert, cert) == X509_V_OK;
+ char *str;
+ X509_VERIFY_PARAM *vpm = ts != NULL ? X509_STORE_get0_param(ts) : NULL;
+ int time_cmp;
+
+ ossl_cmp_log3(INFO, ctx, " considering %s%s %s with..",
+ self_issued ? "self-issued ": "", desc1, desc2);
+ if ((str = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0)) != NULL)
+ ossl_cmp_log1(INFO, ctx, " subject = %s", str);
+ OPENSSL_free(str);
+ if (!self_issued) {
+ str = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
+ if (str != NULL)
+ ossl_cmp_log1(INFO, ctx, " issuer = %s", str);
+ OPENSSL_free(str);
+ }
+
+ if (already_checked(cert, already_checked1)
+ || already_checked(cert, already_checked2)) {
+ ossl_cmp_info(ctx, " cert has already been checked");
+ return 0;
+ }
+
+ time_cmp = X509_cmp_timeframe(vpm, X509_get0_notBefore(cert),
+ X509_get0_notAfter(cert));
+ if (time_cmp != 0) {
+ ossl_cmp_warn(ctx, time_cmp > 0 ? "cert has expired"
+ : "cert is not yet valid");
+ return 0;
+ }
+
+ if (!check_name(ctx, 1,
+ "cert subject", X509_get_subject_name(cert),
+ "sender field", msg->header->sender->d.directoryName))
+ return 0;
+
+ if (!check_kid(ctx, X509_get0_subject_key_id(cert), msg->header->senderKID))
+ return 0;
+ /* prevent misleading error later in case x509v3_cache_extensions() fails */
+ if (!ossl_x509v3_cache_extensions(cert)) {
+ ossl_cmp_warn(ctx, "cert appears to be invalid");
+ return 0;
+ }
+ if (!verify_signature(ctx, msg, cert)) {
+ ossl_cmp_warn(ctx, "msg signature verification failed");
+ return 0;
+ }
+ /* acceptable also if there is no senderKID in msg header */
+ ossl_cmp_info(ctx, " cert seems acceptable");
+ return 1;
+}
+
+static int check_cert_path(const OSSL_CMP_CTX *ctx, X509_STORE *store,
+ X509 *scrt)
+{
+ if (OSSL_CMP_validate_cert_path(ctx, store, scrt))
+ return 1;
+
+ ossl_cmp_warn(ctx,
+ "msg signature validates but cert path validation failed");
+ return 0;
+}
+
+/*
+ * Exceptional handling for 3GPP TS 33.310 [3G/LTE Network Domain Security
+ * (NDS); Authentication Framework (AF)], only to use for IP messages
+ * and if the ctx option is explicitly set: use self-issued certificates
+ * from extraCerts as trust anchor to validate sender cert -
+ * provided it also can validate the newly enrolled certificate
+ */
+static int check_cert_path_3gpp(const OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *msg, X509 *scrt)
+{
+ int valid = 0;
+ X509_STORE *store;
+
+ if (!ctx->permitTAInExtraCertsForIR)
+ return 0;
+
+ if ((store = X509_STORE_new()) == NULL
+ || !ossl_cmp_X509_STORE_add1_certs(store, msg->extraCerts,
+ 1 /* self-issued only */))
+ goto err;
+
+ /* store does not include CRLs */
+ valid = OSSL_CMP_validate_cert_path(ctx, store, scrt);
+ if (!valid) {
+ ossl_cmp_warn(ctx,
+ "also exceptional 3GPP mode cert path validation failed");
+ } else {
+ /*
+ * verify that the newly enrolled certificate (which assumed rid ==
+ * OSSL_CMP_CERTREQID) can also be validated with the same trusted store
+ */
+ EVP_PKEY *pkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
+ OSSL_CMP_CERTRESPONSE *crep =
+ ossl_cmp_certrepmessage_get0_certresponse(msg->body->value.ip,
+ OSSL_CMP_CERTREQID);
+ X509 *newcrt = ossl_cmp_certresponse_get1_cert(crep, ctx, pkey);
+ /*
+ * maybe better use get_cert_status() from cmp_client.c, which catches
+ * errors
+ */
+ valid = OSSL_CMP_validate_cert_path(ctx, store, newcrt);
+ X509_free(newcrt);
+ }
+
+ err:
+ X509_STORE_free(store);
+ return valid;
+}
+
+static int check_msg_given_cert(const OSSL_CMP_CTX *ctx, X509 *cert,
+ const OSSL_CMP_MSG *msg)
+{
+ return cert_acceptable(ctx, "previously validated", "sender cert",
+ cert, NULL, NULL, msg)
+ && (check_cert_path(ctx, ctx->trusted, cert)
+ || check_cert_path_3gpp(ctx, msg, cert));
+}
+
+/*-
+ * Try all certs in given list for verifying msg, normally or in 3GPP mode.
+ * If already_checked1 == NULL then certs are assumed to be the msg->extraCerts.
+ * On success cache the found cert using ossl_cmp_ctx_set0_validatedSrvCert().
+ */
+static int check_msg_with_certs(OSSL_CMP_CTX *ctx, const STACK_OF(X509) *certs,
+ const char *desc,
+ const STACK_OF(X509) *already_checked1,
+ const STACK_OF(X509) *already_checked2,
+ const OSSL_CMP_MSG *msg, int mode_3gpp)
+{
+ int in_extraCerts = already_checked1 == NULL;
+ int n_acceptable_certs = 0;
+ int i;
+
+ if (sk_X509_num(certs) <= 0) {
+ ossl_cmp_log1(WARN, ctx, "no %s", desc);
+ return 0;
+ }
+
+ for (i = 0; i < sk_X509_num(certs); i++) { /* certs may be NULL */
+ X509 *cert = sk_X509_value(certs, i);
+
+ if (!ossl_assert(cert != NULL))
+ return 0;
+ if (!cert_acceptable(ctx, "cert from", desc, cert,
+ already_checked1, already_checked2, msg))
+ continue;
+ n_acceptable_certs++;
+ if (mode_3gpp ? check_cert_path_3gpp(ctx, msg, cert)
+ : check_cert_path(ctx, ctx->trusted, cert)) {
+ /* store successful sender cert for further msgs in transaction */
+ if (!X509_up_ref(cert))
+ return 0;
+ if (!ossl_cmp_ctx_set0_validatedSrvCert(ctx, cert)) {
+ X509_free(cert);
+ return 0;
+ }
+ return 1;
+ }
+ }
+ if (in_extraCerts && n_acceptable_certs == 0)
+ ossl_cmp_warn(ctx, "no acceptable cert in extraCerts");
+ return 0;
+}
+
+/*-
+ * Verify msg trying first ctx->untrusted, which should include extraCerts
+ * at its front, then trying the trusted certs in truststore (if any) of ctx.
+ * On success cache the found cert using ossl_cmp_ctx_set0_validatedSrvCert().
+ */
+static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
+ int mode_3gpp)
+{
+ int ret = 0;
+
+ if (mode_3gpp
+ && ((!ctx->permitTAInExtraCertsForIR
+ || OSSL_CMP_MSG_get_bodytype(msg) != OSSL_CMP_PKIBODY_IP)))
+ return 0;
+
+ ossl_cmp_info(ctx,
+ mode_3gpp ? "normal mode failed; trying now 3GPP mode trusting extraCerts"
+ : "trying first normal mode using trust store");
+ if (check_msg_with_certs(ctx, msg->extraCerts, "extraCerts",
+ NULL, NULL, msg, mode_3gpp))
+ return 1;
+ if (check_msg_with_certs(ctx, ctx->untrusted, "untrusted certs",
+ msg->extraCerts, NULL, msg, mode_3gpp))
+ return 1;
+
+ if (ctx->trusted == NULL) {
+ ossl_cmp_warn(ctx, mode_3gpp ? "no self-issued extraCerts"
+ : "no trusted store");
+ } else {
+ STACK_OF(X509) *trusted = X509_STORE_get1_all_certs(ctx->trusted);
+ ret = check_msg_with_certs(ctx, trusted,
+ mode_3gpp ? "self-issued extraCerts"
+ : "certs in trusted store",
+ msg->extraCerts, ctx->untrusted,
+ msg, mode_3gpp);
+ sk_X509_pop_free(trusted, X509_free);
+ }
+ return ret;
+}
+
+static int no_log_cb(const char *func, const char *file, int line,
+ OSSL_CMP_severity level, const char *msg)
+{
+ return 1;
+}
+
+/*-
+ * Verify message signature with any acceptable and valid candidate cert.
+ * On success cache the found cert using ossl_cmp_ctx_set0_validatedSrvCert().
+ */
+static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
+{
+ X509 *scrt = ctx->validatedSrvCert; /* previous successful sender cert */
+ GENERAL_NAME *sender = msg->header->sender;
+ char *sname = NULL;
+ char *skid_str = NULL;
+ const ASN1_OCTET_STRING *skid = msg->header->senderKID;
+ OSSL_CMP_log_cb_t backup_log_cb = ctx->log_cb;
+ int res = 0;
+
+ if (sender == NULL || msg->body == NULL)
+ return 0; /* other NULL cases already have been checked */
+ if (sender->type != GEN_DIRNAME) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
+ return 0;
+ }
+
+ /* dump any hitherto errors to avoid confusion when printing further ones */
+ OSSL_CMP_CTX_print_errors(ctx);
+
+ /* enable clearing irrelevant errors in attempts to validate sender certs */
+ (void)ERR_set_mark();
+ ctx->log_cb = no_log_cb; /* temporarily disable logging */
+
+ /*
+ * try first cached scrt, used successfully earlier in same transaction,
+ * for validating this and any further msgs where extraCerts may be left out
+ */
+ if (scrt != NULL) {
+ if (check_msg_given_cert(ctx, scrt, msg)) {
+ ctx->log_cb = backup_log_cb;
+ (void)ERR_pop_to_mark();
+ return 1;
+ }
+ /* cached sender cert has shown to be no more successfully usable */
+ (void)ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL);
+ /* re-do the above check (just) for adding diagnostic information */
+ ossl_cmp_info(ctx,
+ "trying to verify msg signature with previously validated cert");
+ (void)check_msg_given_cert(ctx, scrt, msg);
+ }
+
+ res = check_msg_all_certs(ctx, msg, 0 /* using ctx->trusted */)
+ || check_msg_all_certs(ctx, msg, 1 /* 3gpp */);
+ ctx->log_cb = backup_log_cb;
+ if (res) {
+ /* discard any diagnostic information on trying to use certs */
+ (void)ERR_pop_to_mark();
+ goto end;
+ }
+ /* failed finding a sender cert that verifies the message signature */
+ (void)ERR_clear_last_mark();
+
+ sname = X509_NAME_oneline(sender->d.directoryName, NULL, 0);
+ skid_str = skid == NULL ? NULL
+ : OPENSSL_buf2hexstr(skid->data, skid->length);
+ if (ctx->log_cb != NULL) {
+ ossl_cmp_info(ctx, "trying to verify msg signature with a valid cert that..");
+ if (sname != NULL)
+ ossl_cmp_log1(INFO, ctx, "matches msg sender = %s", sname);
+ if (skid_str != NULL)
+ ossl_cmp_log1(INFO, ctx, "matches msg senderKID = %s", skid_str);
+ else
+ ossl_cmp_info(ctx, "while msg header does not contain senderKID");
+ /* re-do the above checks (just) for adding diagnostic information */
+ (void)check_msg_all_certs(ctx, msg, 0 /* using ctx->trusted */);
+ (void)check_msg_all_certs(ctx, msg, 1 /* 3gpp */);
+ }
+
+ ERR_raise(ERR_LIB_CMP, CMP_R_NO_SUITABLE_SENDER_CERT);
+ if (sname != NULL) {
+ ERR_add_error_txt(NULL, "for msg sender name = ");
+ ERR_add_error_txt(NULL, sname);
+ }
+ if (skid_str != NULL) {
+ ERR_add_error_txt(" and ", "for msg senderKID = ");
+ ERR_add_error_txt(NULL, skid_str);
+ }
+
+ end:
+ OPENSSL_free(sname);
+ OPENSSL_free(skid_str);
+ return res;
+}
+
+/*-
+ * Validate the protection of the given PKIMessage using either password-
+ * based mac (PBM) or a signature algorithm. In the case of signature algorithm,
+ * the sender certificate can have been pinned by providing it in ctx->srvCert,
+ * else it is searched in msg->extraCerts, ctx->untrusted, in ctx->trusted
+ * (in this order) and is path is validated against ctx->trusted.
+ * On success cache the found cert using ossl_cmp_ctx_set0_validatedSrvCert().
+ *
+ * If ctx->permitTAInExtraCertsForIR is true and when validating a CMP IP msg,
+ * the trust anchor for validating the IP msg may be taken from msg->extraCerts
+ * if a self-issued certificate is found there that can be used to
+ * validate the enrolled certificate returned in the IP.
+ * This is according to the need given in 3GPP TS 33.310.
+ *
+ * Returns 1 on success, 0 on error or validation failed.
+ */
+int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
+{
+ X509 *scrt;
+
+ ossl_cmp_debug(ctx, "validating CMP message");
+ if (ctx == NULL || msg == NULL
+ || msg->header == NULL || msg->body == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (msg->header->protectionAlg == NULL /* unprotected message */
+ || msg->protection == NULL || msg->protection->data == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PROTECTION);
+ return 0;
+ }
+
+ switch (ossl_cmp_hdr_get_protection_nid(msg->header)) {
+ /* 5.1.3.1. Shared Secret Information */
+ case NID_id_PasswordBasedMAC:
+ if (ctx->secretValue == NULL) {
+ ossl_cmp_info(ctx, "no secret available for verifying PBM-based CMP message protection");
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_SECRET);
+ return 0;
+ }
+ if (verify_PBMAC(ctx, msg)) {
+ /*
+ * RFC 4210, 5.3.2: 'Note that if the PKI Message Protection is
+ * "shared secret information", then any certificate transported in
+ * the caPubs field may be directly trusted as a root CA
+ * certificate by the initiator.'
+ */
+ switch (OSSL_CMP_MSG_get_bodytype(msg)) {
+ case -1:
+ return 0;
+ case OSSL_CMP_PKIBODY_IP:
+ case OSSL_CMP_PKIBODY_CP:
+ case OSSL_CMP_PKIBODY_KUP:
+ case OSSL_CMP_PKIBODY_CCP:
+ if (ctx->trusted != NULL) {
+ STACK_OF(X509) *certs = msg->body->value.ip->caPubs;
+ /* value.ip is same for cp, kup, and ccp */
+
+ if (!ossl_cmp_X509_STORE_add1_certs(ctx->trusted, certs, 0))
+ /* adds both self-issued and not self-issued certs */
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+ ossl_cmp_debug(ctx,
+ "sucessfully validated PBM-based CMP message protection");
+ return 1;
+ }
+ ossl_cmp_warn(ctx, "verifying PBM-based CMP message protection failed");
+ break;
+
+ /*
+ * 5.1.3.2 DH Key Pairs
+ * Not yet supported
+ */
+ case NID_id_DHBasedMac:
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC);
+ break;
+
+ /*
+ * 5.1.3.3. Signature
+ */
+ default:
+ scrt = ctx->srvCert;
+ if (scrt == NULL) {
+ if (ctx->trusted == NULL) {
+ ossl_cmp_info(ctx, "no trust store nor pinned server cert available for verifying signature-based CMP message protection");
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_TRUST_ANCHOR);
+ return 0;
+ }
+ if (check_msg_find_cert(ctx, msg))
+ return 1;
+ } else { /* use pinned sender cert */
+ /* use ctx->srvCert for signature check even if not acceptable */
+ if (verify_signature(ctx, msg, scrt)) {
+ ossl_cmp_debug(ctx,
+ "sucessfully validated signature-based CMP message protection");
+
+ return 1;
+ }
+ ossl_cmp_warn(ctx, "CMP message signature verification failed");
+ ERR_raise(ERR_LIB_CMP, CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG);
+ }
+ break;
+ }
+ return 0;
+}
+
+
+/*-
+ * Check received message (i.e., response by server or request from client)
+ * Any msg->extraCerts are prepended to ctx->untrusted.
+ *
+ * Ensures that:
+ * its sender is of appropriate type (curently only X509_NAME) and
+ * matches any expected sender or srvCert subject given in the ctx
+ * it has a valid body type
+ * its protection is valid (or invalid/absent, but only if a callback function
+ * is present and yields a positive result using also the supplied argument)
+ * its transaction ID matches the previous transaction ID stored in ctx (if any)
+ * its recipNonce matches the previous senderNonce stored in the ctx (if any)
+ *
+ * If everything is fine:
+ * learns the senderNonce from the received message,
+ * learns the transaction ID if it is not yet in ctx,
+ * and makes any certs in caPubs directly trusted.
+ *
+ * Returns 1 on success, 0 on error.
+ */
+int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
+ ossl_cmp_allow_unprotected_cb_t cb, int cb_arg)
+{
+ OSSL_CMP_PKIHEADER *hdr;
+ const X509_NAME *expected_sender;
+
+ if (!ossl_assert(ctx != NULL && msg != NULL && msg->header != NULL))
+ return 0;
+ hdr = OSSL_CMP_MSG_get0_header(msg);
+
+ /* validate sender name of received msg */
+ if (hdr->sender->type != GEN_DIRNAME) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
+ return 0;
+ }
+ /*
+ * Compare actual sender name of response with expected sender name.
+ * Mitigates risk to accept misused PBM secret
+ * or misused certificate of an unauthorized entity of a trusted hierarchy.
+ */
+ expected_sender = ctx->expected_sender;
+ if (expected_sender == NULL && ctx->srvCert != NULL)
+ expected_sender = X509_get_subject_name(ctx->srvCert);
+ if (!check_name(ctx, 0, "sender DN field", hdr->sender->d.directoryName,
+ "expected sender", expected_sender))
+ return 0;
+ /* Note: if recipient was NULL-DN it could be learned here if needed */
+
+ if (sk_X509_num(msg->extraCerts) > 10)
+ ossl_cmp_warn(ctx,
+ "received CMP message contains more than 10 extraCerts");
+ /*
+ * Store any provided extraCerts in ctx for use in OSSL_CMP_validate_msg()
+ * and for future use, such that they are available to ctx->certConf_cb and
+ * the peer does not need to send them again in the same transaction.
+ * Note that it does not help validating the message before storing the
+ * extraCerts because they do not belong to the protected msg part anyway.
+ * For efficiency, the extraCerts are prepended so they get used first.
+ */
+ if (!X509_add_certs(ctx->untrusted, msg->extraCerts,
+ /* this allows self-signed certs */
+ X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
+ | X509_ADD_FLAG_PREPEND))
+ return 0;
+
+ /* validate message protection */
+ if (hdr->protectionAlg != NULL) {
+ /* detect explicitly permitted exceptions for invalid protection */
+ if (!OSSL_CMP_validate_msg(ctx, msg)
+ && (cb == NULL || (*cb)(ctx, msg, 1, cb_arg) <= 0)) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_PROTECTION);
+ return 0;
+#endif
+ }
+ } else {
+ /* detect explicitly permitted exceptions for missing protection */
+ if (cb == NULL || (*cb)(ctx, msg, 0, cb_arg) <= 0) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PROTECTION);
+ return 0;
+#endif
+ }
+ }
+
+ /* check CMP version number in header */
+ if (ossl_cmp_hdr_get_pvno(hdr) != OSSL_CMP_PVNO) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PVNO);
+ return 0;
+#endif
+ }
+
+ if (OSSL_CMP_MSG_get_bodytype(msg) < 0) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ ERR_raise(ERR_LIB_CMP, CMP_R_PKIBODY_ERROR);
+ return 0;
+#endif
+ }
+
+ /* compare received transactionID with the expected one in previous msg */
+ if (ctx->transactionID != NULL
+ && (hdr->transactionID == NULL
+ || ASN1_OCTET_STRING_cmp(ctx->transactionID,
+ hdr->transactionID) != 0)) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ ERR_raise(ERR_LIB_CMP, CMP_R_TRANSACTIONID_UNMATCHED);
+ return 0;
+#endif
+ }
+
+ /* compare received nonce with the one we sent */
+ if (ctx->senderNonce != NULL
+ && (msg->header->recipNonce == NULL
+ || ASN1_OCTET_STRING_cmp(ctx->senderNonce,
+ hdr->recipNonce) != 0)) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ ERR_raise(ERR_LIB_CMP, CMP_R_RECIPNONCE_UNMATCHED);
+ return 0;
+#endif
+ }
+
+ /*
+ * RFC 4210 section 5.1.1 states: the recipNonce is copied from
+ * the senderNonce of the previous message in the transaction.
+ * --> Store for setting in next message
+ */
+ if (!ossl_cmp_ctx_set1_recipNonce(ctx, hdr->senderNonce))
+ return 0;
+
+ /* if not yet present, learn transactionID */
+ if (ctx->transactionID == NULL
+ && !OSSL_CMP_CTX_set1_transactionID(ctx, hdr->transactionID))
+ return -1;
+
+ /*
+ * Store any provided extraCerts in ctx for future use,
+ * such that they are available to ctx->certConf_cb and
+ * the peer does not need to send them again in the same transaction.
+ * For efficiency, the extraCerts are prepended so they get used first.
+ */
+ if (!X509_add_certs(ctx->untrusted, msg->extraCerts,
+ /* this allows self-signed certs */
+ X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
+ | X509_ADD_FLAG_PREPEND))
+ return -1;
+
+ if (ossl_cmp_hdr_get_protection_nid(hdr) == NID_id_PasswordBasedMAC) {
+ /*
+ * RFC 4210, 5.3.2: 'Note that if the PKI Message Protection is
+ * "shared secret information", then any certificate transported in
+ * the caPubs field may be directly trusted as a root CA
+ * certificate by the initiator.'
+ */
+ switch (OSSL_CMP_MSG_get_bodytype(msg)) {
+ case OSSL_CMP_PKIBODY_IP:
+ case OSSL_CMP_PKIBODY_CP:
+ case OSSL_CMP_PKIBODY_KUP:
+ case OSSL_CMP_PKIBODY_CCP:
+ if (ctx->trusted != NULL) {
+ STACK_OF(X509) *certs = msg->body->value.ip->caPubs;
+ /* value.ip is same for cp, kup, and ccp */
+
+ if (!ossl_cmp_X509_STORE_add1_certs(ctx->trusted, certs, 0))
+ /* adds both self-issued and not self-issued certs */
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return 1;
+}
+
+int ossl_cmp_verify_popo(const OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *msg, int acceptRAVerified)
+{
+ if (!ossl_assert(msg != NULL && msg->body != NULL))
+ return 0;
+ switch (msg->body->type) {
+ case OSSL_CMP_PKIBODY_P10CR:
+ {
+ X509_REQ *req = msg->body->value.p10cr;
+
+ if (X509_REQ_verify_ex(req, X509_REQ_get0_pubkey(req), ctx->libctx,
+ ctx->propq) <= 0) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ ERR_raise(ERR_LIB_CMP, CMP_R_REQUEST_NOT_ACCEPTED);
+ return 0;
+#endif
+ }
+ }
+ break;
+ case OSSL_CMP_PKIBODY_IR:
+ case OSSL_CMP_PKIBODY_CR:
+ case OSSL_CMP_PKIBODY_KUR:
+ if (!OSSL_CRMF_MSGS_verify_popo(msg->body->value.ir, OSSL_CMP_CERTREQID,
+ acceptRAVerified,
+ ctx->libctx, ctx->propq)) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ return 0;
+#endif
+ }
+ break;
+ default:
+ ERR_raise(ERR_LIB_CMP, CMP_R_PKIBODY_ERROR);
+ return 0;
+ }
+ return 1;
+}
diff --git a/crypto/cms/build.info b/crypto/cms/build.info
index cb675436ef06..5fabea7c53d1 100644
--- a/crypto/cms/build.info
+++ b/crypto/cms/build.info
@@ -2,4 +2,4 @@ LIBS=../../libcrypto
SOURCE[../../libcrypto]= \
cms_lib.c cms_asn1.c cms_att.c cms_io.c cms_smime.c cms_err.c \
cms_sd.c cms_dd.c cms_cd.c cms_env.c cms_enc.c cms_ess.c \
- cms_pwri.c cms_kari.c
+ cms_pwri.c cms_kari.c cms_rsa.c cms_dh.c cms_ec.c
diff --git a/crypto/cms/cms_asn1.c b/crypto/cms/cms_asn1.c
index 08069d72a29e..72cd14317d47 100644
--- a/crypto/cms/cms_asn1.c
+++ b/crypto/cms/cms_asn1.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -245,6 +245,17 @@ ASN1_NDEF_SEQUENCE(CMS_EncryptedData) = {
ASN1_IMP_SET_OF_OPT(CMS_EncryptedData, unprotectedAttrs, X509_ATTRIBUTE, 1)
} ASN1_NDEF_SEQUENCE_END(CMS_EncryptedData)
+/* Defined in RFC 5083 - Section 2.1. AuthEnvelopedData Type */
+ASN1_NDEF_SEQUENCE(CMS_AuthEnvelopedData) = {
+ ASN1_EMBED(CMS_AuthEnvelopedData, version, INT32),
+ ASN1_IMP_OPT(CMS_AuthEnvelopedData, originatorInfo, CMS_OriginatorInfo, 0),
+ ASN1_SET_OF(CMS_AuthEnvelopedData, recipientInfos, CMS_RecipientInfo),
+ ASN1_SIMPLE(CMS_AuthEnvelopedData, authEncryptedContentInfo, CMS_EncryptedContentInfo),
+ ASN1_IMP_SET_OF_OPT(CMS_AuthEnvelopedData, authAttrs, X509_ALGOR, 2),
+ ASN1_SIMPLE(CMS_AuthEnvelopedData, mac, ASN1_OCTET_STRING),
+ ASN1_IMP_SET_OF_OPT(CMS_AuthEnvelopedData, unauthAttrs, X509_ALGOR, 3)
+} ASN1_NDEF_SEQUENCE_END(CMS_AuthEnvelopedData)
+
ASN1_NDEF_SEQUENCE(CMS_AuthenticatedData) = {
ASN1_EMBED(CMS_AuthenticatedData, version, INT32),
ASN1_IMP_OPT(CMS_AuthenticatedData, originatorInfo, CMS_OriginatorInfo, 0),
@@ -273,6 +284,7 @@ ASN1_ADB(CMS_ContentInfo) = {
ADB_ENTRY(NID_pkcs7_enveloped, ASN1_NDEF_EXP(CMS_ContentInfo, d.envelopedData, CMS_EnvelopedData, 0)),
ADB_ENTRY(NID_pkcs7_digest, ASN1_NDEF_EXP(CMS_ContentInfo, d.digestedData, CMS_DigestedData, 0)),
ADB_ENTRY(NID_pkcs7_encrypted, ASN1_NDEF_EXP(CMS_ContentInfo, d.encryptedData, CMS_EncryptedData, 0)),
+ ADB_ENTRY(NID_id_smime_ct_authEnvelopedData, ASN1_NDEF_EXP(CMS_ContentInfo, d.authEnvelopedData, CMS_AuthEnvelopedData, 0)),
ADB_ENTRY(NID_id_smime_ct_authData, ASN1_NDEF_EXP(CMS_ContentInfo, d.authenticatedData, CMS_AuthenticatedData, 0)),
ADB_ENTRY(NID_id_smime_ct_compressedData, ASN1_NDEF_EXP(CMS_ContentInfo, d.compressedData, CMS_CompressedData, 0)),
} ASN1_ADB_END(CMS_ContentInfo, 0, contentType, 0, &cms_default_tt, NULL);
diff --git a/crypto/cms/cms_att.c b/crypto/cms/cms_att.c
index 4f716619193a..5b99516b29a1 100644
--- a/crypto/cms/cms_att.c
+++ b/crypto/cms/cms_att.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2008-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -125,7 +125,8 @@ int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si,
return 0;
}
-void *CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, const ASN1_OBJECT *oid,
+void *CMS_signed_get0_data_by_OBJ(const CMS_SignerInfo *si,
+ const ASN1_OBJECT *oid,
int lastpos, int type)
{
return X509at_get0_data_by_OBJ(si->signedAttrs, oid, lastpos, type);
@@ -262,7 +263,7 @@ static int cms_check_attribute(int nid, int flags, int type,
* attributes. Only one instance of each is allowed, with each of these
* attributes containing a single attribute value in its set.
*/
-int CMS_si_check_attributes(const CMS_SignerInfo *si)
+int ossl_cms_si_check_attributes(const CMS_SignerInfo *si)
{
int i;
int have_signed_attrs = (CMS_signed_get_attr_count(si) > 0);
@@ -276,7 +277,7 @@ int CMS_si_check_attributes(const CMS_SignerInfo *si)
si->signedAttrs, have_signed_attrs)
|| !cms_check_attribute(nid, flags, CMS_ATTR_F_UNSIGNED,
si->unsignedAttrs, have_unsigned_attrs)) {
- CMSerr(CMS_F_CMS_SI_CHECK_ATTRIBUTES, CMS_R_ATTRIBUTE_ERROR);
+ ERR_raise(ERR_LIB_CMS, CMS_R_ATTRIBUTE_ERROR);
return 0;
}
}
diff --git a/crypto/cms/cms_cd.c b/crypto/cms/cms_cd.c
index 45365b8ba247..6de6d55e58d8 100644
--- a/crypto/cms/cms_cd.c
+++ b/crypto/cms/cms_cd.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -21,20 +21,22 @@
/* CMS CompressedData Utilities */
-CMS_ContentInfo *cms_CompressedData_create(int comp_nid)
+CMS_ContentInfo *ossl_cms_CompressedData_create(int comp_nid,
+ OSSL_LIB_CTX *libctx,
+ const char *propq)
{
CMS_ContentInfo *cms;
CMS_CompressedData *cd;
+
/*
* Will need something cleverer if there is ever more than one
* compression algorithm or parameters have some meaning...
*/
if (comp_nid != NID_zlib_compression) {
- CMSerr(CMS_F_CMS_COMPRESSEDDATA_CREATE,
- CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
return NULL;
}
- cms = CMS_ContentInfo_new();
+ cms = CMS_ContentInfo_new_ex(libctx, propq);
if (cms == NULL)
return NULL;
@@ -60,20 +62,19 @@ CMS_ContentInfo *cms_CompressedData_create(int comp_nid)
return NULL;
}
-BIO *cms_CompressedData_init_bio(CMS_ContentInfo *cms)
+BIO *ossl_cms_CompressedData_init_bio(const CMS_ContentInfo *cms)
{
CMS_CompressedData *cd;
const ASN1_OBJECT *compoid;
+
if (OBJ_obj2nid(cms->contentType) != NID_id_smime_ct_compressedData) {
- CMSerr(CMS_F_CMS_COMPRESSEDDATA_INIT_BIO,
- CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA);
return NULL;
}
cd = cms->d.compressedData;
X509_ALGOR_get0(&compoid, NULL, NULL, cd->compressionAlgorithm);
if (OBJ_obj2nid(compoid) != NID_zlib_compression) {
- CMSerr(CMS_F_CMS_COMPRESSEDDATA_INIT_BIO,
- CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
return NULL;
}
return BIO_new(BIO_f_zlib());
diff --git a/crypto/cms/cms_dd.c b/crypto/cms/cms_dd.c
index 0df2e698c237..6a7c049ef316 100644
--- a/crypto/cms/cms_dd.c
+++ b/crypto/cms/cms_dd.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -17,11 +17,14 @@
/* CMS DigestedData Utilities */
-CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md)
+CMS_ContentInfo *ossl_cms_DigestedData_create(const EVP_MD *md,
+ OSSL_LIB_CTX *libctx,
+ const char *propq)
{
CMS_ContentInfo *cms;
CMS_DigestedData *dd;
- cms = CMS_ContentInfo_new();
+
+ cms = CMS_ContentInfo_new_ex(libctx, propq);
if (cms == NULL)
return NULL;
@@ -45,14 +48,16 @@ CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md)
return NULL;
}
-BIO *cms_DigestedData_init_bio(CMS_ContentInfo *cms)
+BIO *ossl_cms_DigestedData_init_bio(const CMS_ContentInfo *cms)
{
- CMS_DigestedData *dd;
- dd = cms->d.digestedData;
- return cms_DigestAlgorithm_init_bio(dd->digestAlgorithm);
+ CMS_DigestedData *dd = cms->d.digestedData;
+
+ return ossl_cms_DigestAlgorithm_init_bio(dd->digestAlgorithm,
+ ossl_cms_get0_cmsctx(cms));
}
-int cms_DigestedData_do_final(CMS_ContentInfo *cms, BIO *chain, int verify)
+int ossl_cms_DigestedData_do_final(const CMS_ContentInfo *cms, BIO *chain,
+ int verify)
{
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
unsigned char md[EVP_MAX_MD_SIZE];
@@ -61,13 +66,13 @@ int cms_DigestedData_do_final(CMS_ContentInfo *cms, BIO *chain, int verify)
CMS_DigestedData *dd;
if (mctx == NULL) {
- CMSerr(CMS_F_CMS_DIGESTEDDATA_DO_FINAL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
dd = cms->d.digestedData;
- if (!cms_DigestAlgorithm_find_ctx(mctx, chain, dd->digestAlgorithm))
+ if (!ossl_cms_DigestAlgorithm_find_ctx(mctx, chain, dd->digestAlgorithm))
goto err;
if (EVP_DigestFinal_ex(mctx, md, &mdlen) <= 0)
@@ -75,14 +80,12 @@ int cms_DigestedData_do_final(CMS_ContentInfo *cms, BIO *chain, int verify)
if (verify) {
if (mdlen != (unsigned int)dd->digest->length) {
- CMSerr(CMS_F_CMS_DIGESTEDDATA_DO_FINAL,
- CMS_R_MESSAGEDIGEST_WRONG_LENGTH);
+ ERR_raise(ERR_LIB_CMS, CMS_R_MESSAGEDIGEST_WRONG_LENGTH);
goto err;
}
if (memcmp(md, dd->digest->data, mdlen))
- CMSerr(CMS_F_CMS_DIGESTEDDATA_DO_FINAL,
- CMS_R_VERIFICATION_FAILURE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_VERIFICATION_FAILURE);
else
r = 1;
} else {
diff --git a/crypto/cms/cms_dh.c b/crypto/cms/cms_dh.c
new file mode 100644
index 000000000000..7cc36f835f21
--- /dev/null
+++ b/crypto/cms/cms_dh.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <assert.h>
+#include <openssl/cms.h>
+#include <openssl/dh.h>
+#include <openssl/err.h>
+#include <openssl/core_names.h>
+#include "internal/sizes.h"
+#include "crypto/evp.h"
+#include "cms_local.h"
+
+static int dh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
+ X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
+{
+ const ASN1_OBJECT *aoid;
+ int atype;
+ const void *aval;
+ ASN1_INTEGER *public_key = NULL;
+ int rv = 0;
+ EVP_PKEY *pkpeer = NULL, *pk = NULL;
+ BIGNUM *bnpub = NULL;
+ const unsigned char *p;
+ unsigned char *buf = NULL;
+ int plen;
+
+ X509_ALGOR_get0(&aoid, &atype, &aval, alg);
+ if (OBJ_obj2nid(aoid) != NID_dhpublicnumber)
+ goto err;
+ /* Only absent parameters allowed in RFC XXXX */
+ if (atype != V_ASN1_UNDEF && atype == V_ASN1_NULL)
+ goto err;
+
+ pk = EVP_PKEY_CTX_get0_pkey(pctx);
+ if (pk == NULL || !EVP_PKEY_is_a(pk, "DHX"))
+ goto err;
+
+ /* Get public key */
+ plen = ASN1_STRING_length(pubkey);
+ p = ASN1_STRING_get0_data(pubkey);
+ if (p == NULL || plen == 0)
+ goto err;
+
+ if ((public_key = d2i_ASN1_INTEGER(NULL, &p, plen)) == NULL)
+ goto err;
+ /*
+ * Pad to full p parameter size as that is checked by
+ * EVP_PKEY_set1_encoded_public_key()
+ */
+ plen = EVP_PKEY_get_size(pk);
+ if ((bnpub = ASN1_INTEGER_to_BN(public_key, NULL)) == NULL)
+ goto err;
+ if ((buf = OPENSSL_malloc(plen)) == NULL)
+ goto err;
+ if (BN_bn2binpad(bnpub, buf, plen) < 0)
+ goto err;
+
+ pkpeer = EVP_PKEY_new();
+ if (pkpeer == NULL
+ || !EVP_PKEY_copy_parameters(pkpeer, pk)
+ || !EVP_PKEY_set1_encoded_public_key(pkpeer, buf, plen))
+ goto err;
+
+ if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
+ rv = 1;
+ err:
+ ASN1_INTEGER_free(public_key);
+ BN_free(bnpub);
+ OPENSSL_free(buf);
+ EVP_PKEY_free(pkpeer);
+ return rv;
+}
+
+static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
+{
+ int rv = 0;
+ X509_ALGOR *alg, *kekalg = NULL;
+ ASN1_OCTET_STRING *ukm;
+ const unsigned char *p;
+ unsigned char *dukm = NULL;
+ size_t dukmlen = 0;
+ int keylen, plen;
+ EVP_CIPHER *kekcipher = NULL;
+ EVP_CIPHER_CTX *kekctx;
+ char name[OSSL_MAX_NAME_SIZE];
+
+ if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
+ goto err;
+
+ /*
+ * For DH we only have one OID permissible. If ever any more get defined
+ * we will need something cleverer.
+ */
+ if (OBJ_obj2nid(alg->algorithm) != NID_id_smime_alg_ESDH) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_KDF_PARAMETER_ERROR);
+ goto err;
+ }
+
+ if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, EVP_PKEY_DH_KDF_X9_42) <= 0
+ || EVP_PKEY_CTX_set_dh_kdf_md(pctx, EVP_sha1()) <= 0)
+ goto err;
+
+ if (alg->parameter->type != V_ASN1_SEQUENCE)
+ goto err;
+
+ p = alg->parameter->value.sequence->data;
+ plen = alg->parameter->value.sequence->length;
+ kekalg = d2i_X509_ALGOR(NULL, &p, plen);
+ if (kekalg == NULL)
+ goto err;
+ kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
+ if (kekctx == NULL)
+ goto err;
+
+ if (OBJ_obj2txt(name, sizeof(name), kekalg->algorithm, 0) <= 0)
+ goto err;
+
+ kekcipher = EVP_CIPHER_fetch(pctx->libctx, name, pctx->propquery);
+ if (kekcipher == NULL
+ || EVP_CIPHER_get_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
+ goto err;
+ if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
+ goto err;
+ if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
+ goto err;
+
+ keylen = EVP_CIPHER_CTX_get_key_length(kekctx);
+ if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
+ goto err;
+ /* Use OBJ_nid2obj to ensure we use built in OID that isn't freed */
+ if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx,
+ OBJ_nid2obj(EVP_CIPHER_get_type(kekcipher)))
+ <= 0)
+ goto err;
+
+ if (ukm != NULL) {
+ dukmlen = ASN1_STRING_length(ukm);
+ dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), dukmlen);
+ if (dukm == NULL)
+ goto err;
+ }
+
+ if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
+ goto err;
+ dukm = NULL;
+
+ rv = 1;
+ err:
+ X509_ALGOR_free(kekalg);
+ EVP_CIPHER_free(kekcipher);
+ OPENSSL_free(dukm);
+ return rv;
+}
+
+static int dh_cms_decrypt(CMS_RecipientInfo *ri)
+{
+ EVP_PKEY_CTX *pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+
+ if (pctx == NULL)
+ return 0;
+ /* See if we need to set peer key */
+ if (!EVP_PKEY_CTX_get0_peerkey(pctx)) {
+ X509_ALGOR *alg;
+ ASN1_BIT_STRING *pubkey;
+
+ if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
+ NULL, NULL, NULL))
+ return 0;
+ if (alg == NULL || pubkey == NULL)
+ return 0;
+ if (!dh_cms_set_peerkey(pctx, alg, pubkey)) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_PEER_KEY_ERROR);
+ return 0;
+ }
+ }
+ /* Set DH derivation parameters and initialise unwrap context */
+ if (!dh_cms_set_shared_info(pctx, ri)) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_SHARED_INFO_ERROR);
+ return 0;
+ }
+ return 1;
+}
+
+static int dh_cms_encrypt(CMS_RecipientInfo *ri)
+{
+ EVP_PKEY_CTX *pctx;
+ EVP_PKEY *pkey;
+ EVP_CIPHER_CTX *ctx;
+ int keylen;
+ X509_ALGOR *talg, *wrap_alg = NULL;
+ const ASN1_OBJECT *aoid;
+ ASN1_BIT_STRING *pubkey;
+ ASN1_STRING *wrap_str;
+ ASN1_OCTET_STRING *ukm;
+ unsigned char *penc = NULL, *dukm = NULL;
+ int penclen;
+ size_t dukmlen = 0;
+ int rv = 0;
+ int kdf_type, wrap_nid;
+ const EVP_MD *kdf_md;
+
+ pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+ if (pctx == NULL)
+ return 0;
+ /* Get ephemeral key */
+ pkey = EVP_PKEY_CTX_get0_pkey(pctx);
+ if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
+ NULL, NULL, NULL))
+ goto err;
+
+ /* Is everything uninitialised? */
+ X509_ALGOR_get0(&aoid, NULL, NULL, talg);
+ if (aoid == OBJ_nid2obj(NID_undef)) {
+ BIGNUM *bn_pub_key = NULL;
+ ASN1_INTEGER *pubk;
+
+ if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, &bn_pub_key))
+ goto err;
+
+ pubk = BN_to_ASN1_INTEGER(bn_pub_key, NULL);
+ BN_free(bn_pub_key);
+ if (pubk == NULL)
+ goto err;
+
+ /* Set the key */
+ penclen = i2d_ASN1_INTEGER(pubk, &penc);
+ ASN1_INTEGER_free(pubk);
+ if (penclen <= 0)
+ goto err;
+ ASN1_STRING_set0(pubkey, penc, penclen);
+ pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+ pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+
+ penc = NULL;
+ X509_ALGOR_set0(talg, OBJ_nid2obj(NID_dhpublicnumber),
+ V_ASN1_UNDEF, NULL);
+ }
+
+ /* See if custom parameters set */
+ kdf_type = EVP_PKEY_CTX_get_dh_kdf_type(pctx);
+ if (kdf_type <= 0 || EVP_PKEY_CTX_get_dh_kdf_md(pctx, &kdf_md) <= 0)
+ goto err;
+
+ if (kdf_type == EVP_PKEY_DH_KDF_NONE) {
+ kdf_type = EVP_PKEY_DH_KDF_X9_42;
+ if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, kdf_type) <= 0)
+ goto err;
+ } else if (kdf_type != EVP_PKEY_DH_KDF_X9_42)
+ /* Unknown KDF */
+ goto err;
+ if (kdf_md == NULL) {
+ /* Only SHA1 supported */
+ kdf_md = EVP_sha1();
+ if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, kdf_md) <= 0)
+ goto err;
+ } else if (EVP_MD_get_type(kdf_md) != NID_sha1)
+ /* Unsupported digest */
+ goto err;
+
+ if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
+ goto err;
+
+ /* Get wrap NID */
+ ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
+ wrap_nid = EVP_CIPHER_CTX_get_type(ctx);
+ if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx, OBJ_nid2obj(wrap_nid)) <= 0)
+ goto err;
+ keylen = EVP_CIPHER_CTX_get_key_length(ctx);
+
+ /* Package wrap algorithm in an AlgorithmIdentifier */
+
+ wrap_alg = X509_ALGOR_new();
+ if (wrap_alg == NULL)
+ goto err;
+ wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
+ wrap_alg->parameter = ASN1_TYPE_new();
+ if (wrap_alg->parameter == NULL)
+ goto err;
+ if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
+ goto err;
+ if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
+ ASN1_TYPE_free(wrap_alg->parameter);
+ wrap_alg->parameter = NULL;
+ }
+
+ if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
+ goto err;
+
+ if (ukm != NULL) {
+ dukmlen = ASN1_STRING_length(ukm);
+ dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), dukmlen);
+ if (dukm == NULL)
+ goto err;
+ }
+
+ if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
+ goto err;
+ dukm = NULL;
+
+ /*
+ * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
+ * of another AlgorithmIdentifier.
+ */
+ penc = NULL;
+ penclen = i2d_X509_ALGOR(wrap_alg, &penc);
+ if (penc == NULL || penclen == 0)
+ goto err;
+ wrap_str = ASN1_STRING_new();
+ if (wrap_str == NULL)
+ goto err;
+ ASN1_STRING_set0(wrap_str, penc, penclen);
+ penc = NULL;
+ X509_ALGOR_set0(talg, OBJ_nid2obj(NID_id_smime_alg_ESDH),
+ V_ASN1_SEQUENCE, wrap_str);
+
+ rv = 1;
+
+ err:
+ OPENSSL_free(penc);
+ X509_ALGOR_free(wrap_alg);
+ OPENSSL_free(dukm);
+ return rv;
+}
+
+int ossl_cms_dh_envelope(CMS_RecipientInfo *ri, int decrypt)
+{
+ assert(decrypt == 0 || decrypt == 1);
+
+ if (decrypt == 1)
+ return dh_cms_decrypt(ri);
+
+ if (decrypt == 0)
+ return dh_cms_encrypt(ri);
+
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+ return 0;
+}
diff --git a/crypto/cms/cms_ec.c b/crypto/cms/cms_ec.c
new file mode 100644
index 000000000000..8ecf730aa7b0
--- /dev/null
+++ b/crypto/cms/cms_ec.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <assert.h>
+#include <openssl/cms.h>
+#include <openssl/err.h>
+#include <openssl/decoder.h>
+#include "internal/sizes.h"
+#include "crypto/evp.h"
+#include "cms_local.h"
+
+static EVP_PKEY *pkey_type2param(int ptype, const void *pval,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ OSSL_DECODER_CTX *ctx = NULL;
+
+ if (ptype == V_ASN1_SEQUENCE) {
+ const ASN1_STRING *pstr = pval;
+ const unsigned char *pm = pstr->data;
+ size_t pmlen = (size_t)pstr->length;
+ int selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
+
+ ctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", NULL, "EC",
+ selection, libctx, propq);
+ if (ctx == NULL)
+ goto err;
+
+ if (!OSSL_DECODER_from_data(ctx, &pm, &pmlen)) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_DECODE_ERROR);
+ goto err;
+ }
+ OSSL_DECODER_CTX_free(ctx);
+ return pkey;
+ } else if (ptype == V_ASN1_OBJECT) {
+ const ASN1_OBJECT *poid = pval;
+ char groupname[OSSL_MAX_NAME_SIZE];
+
+ /* type == V_ASN1_OBJECT => the parameters are given by an asn1 OID */
+ pctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", propq);
+ if (pctx == NULL || EVP_PKEY_paramgen_init(pctx) <= 0)
+ goto err;
+ if (OBJ_obj2txt(groupname, sizeof(groupname), poid, 0) <= 0
+ || EVP_PKEY_CTX_set_group_name(pctx, groupname) <= 0) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_DECODE_ERROR);
+ goto err;
+ }
+ if (EVP_PKEY_paramgen(pctx, &pkey) <= 0)
+ goto err;
+ EVP_PKEY_CTX_free(pctx);
+ return pkey;
+ }
+
+ ERR_raise(ERR_LIB_CMS, CMS_R_DECODE_ERROR);
+ return NULL;
+
+ err:
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(pctx);
+ OSSL_DECODER_CTX_free(ctx);
+ return NULL;
+}
+
+static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
+ X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
+{
+ const ASN1_OBJECT *aoid;
+ int atype;
+ const void *aval;
+ int rv = 0;
+ EVP_PKEY *pkpeer = NULL;
+ const unsigned char *p;
+ int plen;
+
+ X509_ALGOR_get0(&aoid, &atype, &aval, alg);
+ if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey)
+ goto err;
+
+ /* If absent parameters get group from main key */
+ if (atype == V_ASN1_UNDEF || atype == V_ASN1_NULL) {
+ EVP_PKEY *pk;
+
+ pk = EVP_PKEY_CTX_get0_pkey(pctx);
+ if (pk == NULL)
+ goto err;
+
+ pkpeer = EVP_PKEY_new();
+ if (pkpeer == NULL)
+ goto err;
+ if (!EVP_PKEY_copy_parameters(pkpeer, pk))
+ goto err;
+ } else {
+ pkpeer = pkey_type2param(atype, aval,
+ EVP_PKEY_CTX_get0_libctx(pctx),
+ EVP_PKEY_CTX_get0_propq(pctx));
+ if (pkpeer == NULL)
+ goto err;
+ }
+ /* We have parameters now set public key */
+ plen = ASN1_STRING_length(pubkey);
+ p = ASN1_STRING_get0_data(pubkey);
+ if (p == NULL || plen == 0)
+ goto err;
+
+ if (!EVP_PKEY_set1_encoded_public_key(pkpeer, p, plen))
+ goto err;
+
+ if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
+ rv = 1;
+ err:
+ EVP_PKEY_free(pkpeer);
+ return rv;
+}
+
+/* Set KDF parameters based on KDF NID */
+static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid)
+{
+ int kdf_nid, kdfmd_nid, cofactor;
+ const EVP_MD *kdf_md;
+
+ if (eckdf_nid == NID_undef)
+ return 0;
+
+ /* Lookup KDF type, cofactor mode and digest */
+ if (!OBJ_find_sigid_algs(eckdf_nid, &kdfmd_nid, &kdf_nid))
+ return 0;
+
+ if (kdf_nid == NID_dh_std_kdf)
+ cofactor = 0;
+ else if (kdf_nid == NID_dh_cofactor_kdf)
+ cofactor = 1;
+ else
+ return 0;
+
+ if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0)
+ return 0;
+
+ if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0)
+ return 0;
+
+ kdf_md = EVP_get_digestbynid(kdfmd_nid);
+ if (!kdf_md)
+ return 0;
+
+ if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
+ return 0;
+ return 1;
+}
+
+static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
+{
+ int rv = 0;
+ X509_ALGOR *alg, *kekalg = NULL;
+ ASN1_OCTET_STRING *ukm;
+ const unsigned char *p;
+ unsigned char *der = NULL;
+ int plen, keylen;
+ EVP_CIPHER *kekcipher = NULL;
+ EVP_CIPHER_CTX *kekctx;
+ char name[OSSL_MAX_NAME_SIZE];
+
+ if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
+ return 0;
+
+ if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_KDF_PARAMETER_ERROR);
+ return 0;
+ }
+
+ if (alg->parameter->type != V_ASN1_SEQUENCE)
+ return 0;
+
+ p = alg->parameter->value.sequence->data;
+ plen = alg->parameter->value.sequence->length;
+ kekalg = d2i_X509_ALGOR(NULL, &p, plen);
+ if (kekalg == NULL)
+ goto err;
+ kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
+ if (kekctx == NULL)
+ goto err;
+ OBJ_obj2txt(name, sizeof(name), kekalg->algorithm, 0);
+ kekcipher = EVP_CIPHER_fetch(pctx->libctx, name, pctx->propquery);
+ if (kekcipher == NULL || EVP_CIPHER_get_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
+ goto err;
+ if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
+ goto err;
+ if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
+ goto err;
+
+ keylen = EVP_CIPHER_CTX_get_key_length(kekctx);
+ if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
+ goto err;
+
+ plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen);
+
+ if (plen <= 0)
+ goto err;
+
+ if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0)
+ goto err;
+ der = NULL;
+
+ rv = 1;
+ err:
+ EVP_CIPHER_free(kekcipher);
+ X509_ALGOR_free(kekalg);
+ OPENSSL_free(der);
+ return rv;
+}
+
+static int ecdh_cms_decrypt(CMS_RecipientInfo *ri)
+{
+ EVP_PKEY_CTX *pctx;
+
+ pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+ if (pctx == NULL)
+ return 0;
+ /* See if we need to set peer key */
+ if (!EVP_PKEY_CTX_get0_peerkey(pctx)) {
+ X509_ALGOR *alg;
+ ASN1_BIT_STRING *pubkey;
+
+ if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
+ NULL, NULL, NULL))
+ return 0;
+ if (alg == NULL || pubkey == NULL)
+ return 0;
+ if (!ecdh_cms_set_peerkey(pctx, alg, pubkey)) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_PEER_KEY_ERROR);
+ return 0;
+ }
+ }
+ /* Set ECDH derivation parameters and initialise unwrap context */
+ if (!ecdh_cms_set_shared_info(pctx, ri)) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_SHARED_INFO_ERROR);
+ return 0;
+ }
+ return 1;
+}
+
+static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
+{
+ EVP_PKEY_CTX *pctx;
+ EVP_PKEY *pkey;
+ EVP_CIPHER_CTX *ctx;
+ int keylen;
+ X509_ALGOR *talg, *wrap_alg = NULL;
+ const ASN1_OBJECT *aoid;
+ ASN1_BIT_STRING *pubkey;
+ ASN1_STRING *wrap_str;
+ ASN1_OCTET_STRING *ukm;
+ unsigned char *penc = NULL;
+ size_t penclen;
+ int rv = 0;
+ int ecdh_nid, kdf_type, kdf_nid, wrap_nid;
+ const EVP_MD *kdf_md;
+
+ pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+ if (pctx == NULL)
+ return 0;
+ /* Get ephemeral key */
+ pkey = EVP_PKEY_CTX_get0_pkey(pctx);
+ if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
+ NULL, NULL, NULL))
+ goto err;
+ X509_ALGOR_get0(&aoid, NULL, NULL, talg);
+ /* Is everything uninitialised? */
+ if (aoid == OBJ_nid2obj(NID_undef)) {
+ /* Set the key */
+
+ penclen = EVP_PKEY_get1_encoded_public_key(pkey, &penc);
+ ASN1_STRING_set0(pubkey, penc, penclen);
+ pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+ pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+
+ penc = NULL;
+ X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
+ V_ASN1_UNDEF, NULL);
+ }
+
+ /* See if custom parameters set */
+ kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx);
+ if (kdf_type <= 0)
+ goto err;
+ if (EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md) <= 0)
+ goto err;
+ ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx);
+ if (ecdh_nid < 0)
+ goto err;
+ else if (ecdh_nid == 0)
+ ecdh_nid = NID_dh_std_kdf;
+ else if (ecdh_nid == 1)
+ ecdh_nid = NID_dh_cofactor_kdf;
+
+ if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) {
+ kdf_type = EVP_PKEY_ECDH_KDF_X9_63;
+ if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0)
+ goto err;
+ } else
+ /* Unknown KDF */
+ goto err;
+ if (kdf_md == NULL) {
+ /* Fixme later for better MD */
+ kdf_md = EVP_sha1();
+ if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
+ goto err;
+ }
+
+ if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
+ goto err;
+
+ /* Lookup NID for KDF+cofactor+digest */
+
+ if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_get_type(kdf_md), ecdh_nid))
+ goto err;
+ /* Get wrap NID */
+ ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
+ wrap_nid = EVP_CIPHER_CTX_get_type(ctx);
+ keylen = EVP_CIPHER_CTX_get_key_length(ctx);
+
+ /* Package wrap algorithm in an AlgorithmIdentifier */
+
+ wrap_alg = X509_ALGOR_new();
+ if (wrap_alg == NULL)
+ goto err;
+ wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
+ wrap_alg->parameter = ASN1_TYPE_new();
+ if (wrap_alg->parameter == NULL)
+ goto err;
+ if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
+ goto err;
+ if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
+ ASN1_TYPE_free(wrap_alg->parameter);
+ wrap_alg->parameter = NULL;
+ }
+
+ if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
+ goto err;
+
+ penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen);
+
+ if (penclen == 0)
+ goto err;
+
+ if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0)
+ goto err;
+ penc = NULL;
+
+ /*
+ * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
+ * of another AlgorithmIdentifier.
+ */
+ penclen = i2d_X509_ALGOR(wrap_alg, &penc);
+ if (penc == NULL || penclen == 0)
+ goto err;
+ wrap_str = ASN1_STRING_new();
+ if (wrap_str == NULL)
+ goto err;
+ ASN1_STRING_set0(wrap_str, penc, penclen);
+ penc = NULL;
+ X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str);
+
+ rv = 1;
+
+ err:
+ OPENSSL_free(penc);
+ X509_ALGOR_free(wrap_alg);
+ return rv;
+}
+
+int ossl_cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt)
+{
+ assert(decrypt == 0 || decrypt == 1);
+
+ if (decrypt == 1)
+ return ecdh_cms_decrypt(ri);
+
+ if (decrypt == 0)
+ return ecdh_cms_encrypt(ri);
+
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+ return 0;
+}
+
+/* ECDSA and DSA implementation is the same */
+int ossl_cms_ecdsa_dsa_sign(CMS_SignerInfo *si, int verify)
+{
+ assert(verify == 0 || verify == 1);
+
+ if (verify == 0) {
+ int snid, hnid;
+ X509_ALGOR *alg1, *alg2;
+ EVP_PKEY *pkey = si->pkey;
+
+ CMS_SignerInfo_get0_algs(si, NULL, NULL, &alg1, &alg2);
+ if (alg1 == NULL || alg1->algorithm == NULL)
+ return -1;
+ hnid = OBJ_obj2nid(alg1->algorithm);
+ if (hnid == NID_undef)
+ return -1;
+ if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_get_id(pkey)))
+ return -1;
+ X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
+ }
+ return 1;
+}
diff --git a/crypto/cms/cms_enc.c b/crypto/cms/cms_enc.c
index 6f077b339a87..f7007c12319e 100644
--- a/crypto/cms/cms_enc.c
+++ b/crypto/cms/cms_enc.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -14,84 +14,114 @@
#include <openssl/err.h>
#include <openssl/cms.h>
#include <openssl/rand.h>
+#include "crypto/evp.h"
#include "cms_local.h"
/* CMS EncryptedData Utilities */
/* Return BIO based on EncryptedContentInfo and key */
-BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
+BIO *ossl_cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec,
+ const CMS_CTX *cms_ctx)
{
BIO *b;
EVP_CIPHER_CTX *ctx;
- const EVP_CIPHER *ciph;
+ EVP_CIPHER *fetched_ciph = NULL;
+ const EVP_CIPHER *cipher = NULL;
X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
+ evp_cipher_aead_asn1_params aparams;
unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL;
unsigned char *tkey = NULL;
+ int len;
+ int ivlen = 0;
size_t tkeylen = 0;
-
int ok = 0;
-
int enc, keep_key = 0;
+ OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(cms_ctx);
+ const char *propq = ossl_cms_ctx_get0_propq(cms_ctx);
enc = ec->cipher ? 1 : 0;
b = BIO_new(BIO_f_cipher());
if (b == NULL) {
- CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return NULL;
}
BIO_get_cipher_ctx(b, &ctx);
+ (void)ERR_set_mark();
if (enc) {
- ciph = ec->cipher;
+ cipher = ec->cipher;
/*
* If not keeping key set cipher to NULL so subsequent calls decrypt.
*/
- if (ec->key)
+ if (ec->key != NULL)
ec->cipher = NULL;
} else {
- ciph = EVP_get_cipherbyobj(calg->algorithm);
-
- if (!ciph) {
- CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_UNKNOWN_CIPHER);
- goto err;
- }
+ cipher = EVP_get_cipherbyobj(calg->algorithm);
+ }
+ if (cipher != NULL) {
+ fetched_ciph = EVP_CIPHER_fetch(libctx, EVP_CIPHER_get0_name(cipher),
+ propq);
+ if (fetched_ciph != NULL)
+ cipher = fetched_ciph;
}
+ if (cipher == NULL) {
+ (void)ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_CIPHER);
+ goto err;
+ }
+ (void)ERR_pop_to_mark();
- if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, enc) <= 0) {
- CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
- CMS_R_CIPHER_INITIALISATION_ERROR);
+ if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc) <= 0) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_INITIALISATION_ERROR);
goto err;
}
if (enc) {
- int ivlen;
-
- calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
+ calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_get_type(ctx));
if (calg->algorithm == NULL) {
- CMSerr(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM);
goto err;
}
/* Generate a random IV if we need one */
- ivlen = EVP_CIPHER_CTX_iv_length(ctx);
+ ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
+ if (ivlen < 0) {
+ ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB);
+ goto err;
+ }
+
if (ivlen > 0) {
- if (RAND_bytes(iv, ivlen) <= 0)
+ if (RAND_bytes_ex(libctx, iv, ivlen, 0) <= 0)
goto err;
piv = iv;
}
- } else if (EVP_CIPHER_asn1_to_param(ctx, calg->parameter) <= 0) {
- CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
- CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
- goto err;
+ } else {
+ if (evp_cipher_asn1_to_param_ex(ctx, calg->parameter, &aparams) <= 0) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
+ goto err;
+ }
+ if ((EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)) {
+ piv = aparams.iv;
+ if (ec->taglen > 0
+ && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
+ ec->taglen, ec->tag) <= 0) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_AEAD_SET_TAG_ERROR);
+ goto err;
+ }
+ }
}
- tkeylen = EVP_CIPHER_CTX_key_length(ctx);
+ len = EVP_CIPHER_CTX_get_key_length(ctx);
+ if (len <= 0)
+ goto err;
+ tkeylen = (size_t)len;
+
/* Generate random session key */
if (!enc || !ec->key) {
tkey = OPENSSL_malloc(tkeylen);
if (tkey == NULL) {
- CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0)
@@ -117,8 +147,7 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
* which may be useful in MMA.
*/
if (enc || ec->debug) {
- CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
- CMS_R_INVALID_KEY_LENGTH);
+ ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
goto err;
} else {
/* Use random key */
@@ -132,19 +161,25 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
}
if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0) {
- CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
- CMS_R_CIPHER_INITIALISATION_ERROR);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_INITIALISATION_ERROR);
goto err;
}
if (enc) {
calg->parameter = ASN1_TYPE_new();
if (calg->parameter == NULL) {
- CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (EVP_CIPHER_param_to_asn1(ctx, calg->parameter) <= 0) {
- CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
- CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
+ if ((EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)) {
+ memcpy(aparams.iv, piv, ivlen);
+ aparams.iv_len = ivlen;
+ aparams.tag_len = EVP_CIPHER_CTX_get_tag_length(ctx);
+ if (aparams.tag_len <= 0)
+ goto err;
+ }
+
+ if (evp_cipher_param_to_asn1_ex(ctx, calg->parameter, &aparams) <= 0) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
goto err;
}
/* If parameter type not set omit parameter */
@@ -156,6 +191,7 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
ok = 1;
err:
+ EVP_CIPHER_free(fetched_ciph);
if (!keep_key || !ok) {
OPENSSL_clear_free(ec->key, ec->keylen);
ec->key = NULL;
@@ -167,20 +203,21 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
return NULL;
}
-int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
- const EVP_CIPHER *cipher,
- const unsigned char *key, size_t keylen)
+int ossl_cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
+ const EVP_CIPHER *cipher,
+ const unsigned char *key, size_t keylen,
+ const CMS_CTX *cms_ctx)
{
ec->cipher = cipher;
if (key) {
if ((ec->key = OPENSSL_malloc(keylen)) == NULL) {
- CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(ec->key, key, keylen);
}
ec->keylen = keylen;
- if (cipher)
+ if (cipher != NULL)
ec->contentType = OBJ_nid2obj(NID_pkcs7_data);
return 1;
}
@@ -189,30 +226,33 @@ int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
const unsigned char *key, size_t keylen)
{
CMS_EncryptedContentInfo *ec;
+
if (!key || !keylen) {
- CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NO_KEY);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_KEY);
return 0;
}
if (ciph) {
cms->d.encryptedData = M_ASN1_new_of(CMS_EncryptedData);
if (!cms->d.encryptedData) {
- CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return 0;
}
cms->contentType = OBJ_nid2obj(NID_pkcs7_encrypted);
cms->d.encryptedData->version = 0;
} else if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted) {
- CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NOT_ENCRYPTED_DATA);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_ENCRYPTED_DATA);
return 0;
}
ec = cms->d.encryptedData->encryptedContentInfo;
- return cms_EncryptedContent_init(ec, ciph, key, keylen);
+ return ossl_cms_EncryptedContent_init(ec, ciph, key, keylen,
+ ossl_cms_get0_cmsctx(cms));
}
-BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms)
+BIO *ossl_cms_EncryptedData_init_bio(const CMS_ContentInfo *cms)
{
CMS_EncryptedData *enc = cms->d.encryptedData;
if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs)
enc->version = 2;
- return cms_EncryptedContent_init_bio(enc->encryptedContentInfo);
+ return ossl_cms_EncryptedContent_init_bio(enc->encryptedContentInfo,
+ ossl_cms_get0_cmsctx(cms));
}
diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c
index 962a0137542a..51a1d7df848c 100644
--- a/crypto/cms/cms_env.c
+++ b/crypto/cms/cms_env.c
@@ -1,7 +1,7 @@
/*
* Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,29 +13,60 @@
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/cms.h>
-#include <openssl/aes.h>
-#include "cms_local.h"
+#include <openssl/evp.h>
+#include "internal/sizes.h"
#include "crypto/asn1.h"
#include "crypto/evp.h"
+#include "crypto/x509.h"
+#include "cms_local.h"
/* CMS EnvelopedData Utilities */
+static void cms_env_set_version(CMS_EnvelopedData *env);
+
+#define CMS_ENVELOPED_STANDARD 1
+#define CMS_ENVELOPED_AUTH 2
+
+static int cms_get_enveloped_type(const CMS_ContentInfo *cms)
+{
+ int nid = OBJ_obj2nid(cms->contentType);
+
+ switch (nid) {
+ case NID_pkcs7_enveloped:
+ return CMS_ENVELOPED_STANDARD;
+
+ case NID_id_smime_ct_authEnvelopedData:
+ return CMS_ENVELOPED_AUTH;
-CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms)
+ default:
+ ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
+ return 0;
+ }
+}
+
+CMS_EnvelopedData *ossl_cms_get0_enveloped(CMS_ContentInfo *cms)
{
if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) {
- CMSerr(CMS_F_CMS_GET0_ENVELOPED,
- CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
return NULL;
}
return cms->d.envelopedData;
}
+CMS_AuthEnvelopedData *ossl_cms_get0_auth_enveloped(CMS_ContentInfo *cms)
+{
+ if (OBJ_obj2nid(cms->contentType) != NID_id_smime_ct_authEnvelopedData) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
+ return NULL;
+ }
+ return cms->d.authEnvelopedData;
+}
+
static CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms)
{
if (cms->d.other == NULL) {
cms->d.envelopedData = M_ASN1_new_of(CMS_EnvelopedData);
- if (!cms->d.envelopedData) {
- CMSerr(CMS_F_CMS_ENVELOPED_DATA_INIT, ERR_R_MALLOC_FAILURE);
+ if (cms->d.envelopedData == NULL) {
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return NULL;
}
cms->d.envelopedData->version = 0;
@@ -45,10 +76,30 @@ static CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms)
cms->contentType = OBJ_nid2obj(NID_pkcs7_enveloped);
return cms->d.envelopedData;
}
- return cms_get0_enveloped(cms);
+ return ossl_cms_get0_enveloped(cms);
}
-int cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd)
+static CMS_AuthEnvelopedData *
+cms_auth_enveloped_data_init(CMS_ContentInfo *cms)
+{
+ if (cms->d.other == NULL) {
+ cms->d.authEnvelopedData = M_ASN1_new_of(CMS_AuthEnvelopedData);
+ if (cms->d.authEnvelopedData == NULL) {
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ /* Defined in RFC 5083 - Section 2.1. "AuthEnvelopedData Type" */
+ cms->d.authEnvelopedData->version = 0;
+ cms->d.authEnvelopedData->authEncryptedContentInfo->contentType =
+ OBJ_nid2obj(NID_pkcs7_data);
+ ASN1_OBJECT_free(cms->contentType);
+ cms->contentType = OBJ_nid2obj(NID_id_smime_ct_authEnvelopedData);
+ return cms->d.authEnvelopedData;
+ }
+ return ossl_cms_get0_auth_enveloped(cms);
+}
+
+int ossl_cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd)
{
EVP_PKEY *pkey;
int i;
@@ -56,35 +107,96 @@ int cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd)
pkey = ri->d.ktri->pkey;
else if (ri->type == CMS_RECIPINFO_AGREE) {
EVP_PKEY_CTX *pctx = ri->d.kari->pctx;
- if (!pctx)
+
+ if (pctx == NULL)
return 0;
pkey = EVP_PKEY_CTX_get0_pkey(pctx);
- if (!pkey)
+ if (pkey == NULL)
return 0;
} else
return 0;
- if (!pkey->ameth || !pkey->ameth->pkey_ctrl)
+
+ if (EVP_PKEY_is_a(pkey, "DHX") || EVP_PKEY_is_a(pkey, "DH"))
+ return ossl_cms_dh_envelope(ri, cmd);
+ else if (EVP_PKEY_is_a(pkey, "EC"))
+ return ossl_cms_ecdh_envelope(ri, cmd);
+ else if (EVP_PKEY_is_a(pkey, "RSA"))
+ return ossl_cms_rsa_envelope(ri, cmd);
+
+ /* Something else? We'll give engines etc a chance to handle this */
+ if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL)
return 1;
i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_ENVELOPE, cmd, ri);
if (i == -2) {
- CMSerr(CMS_F_CMS_ENV_ASN1_CTRL,
- CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
return 0;
}
if (i <= 0) {
- CMSerr(CMS_F_CMS_ENV_ASN1_CTRL, CMS_R_CTRL_FAILURE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CTRL_FAILURE);
return 0;
}
return 1;
}
+CMS_EncryptedContentInfo* ossl_cms_get0_env_enc_content(const CMS_ContentInfo *cms)
+{
+ switch (cms_get_enveloped_type(cms)) {
+ case CMS_ENVELOPED_STANDARD:
+ return cms->d.envelopedData->encryptedContentInfo;
+
+ case CMS_ENVELOPED_AUTH:
+ return cms->d.authEnvelopedData->authEncryptedContentInfo;
+
+ default:
+ return NULL;
+ }
+}
+
STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms)
{
- CMS_EnvelopedData *env;
- env = cms_get0_enveloped(cms);
- if (!env)
+ switch (cms_get_enveloped_type(cms)) {
+ case CMS_ENVELOPED_STANDARD:
+ return cms->d.envelopedData->recipientInfos;
+
+ case CMS_ENVELOPED_AUTH:
+ return cms->d.authEnvelopedData->recipientInfos;
+
+ default:
return NULL;
- return env->recipientInfos;
+ }
+}
+
+void ossl_cms_RecipientInfos_set_cmsctx(CMS_ContentInfo *cms)
+{
+ int i;
+ CMS_RecipientInfo *ri;
+ const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
+ STACK_OF(CMS_RecipientInfo) *rinfos = CMS_get0_RecipientInfos(cms);
+
+ for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) {
+ ri = sk_CMS_RecipientInfo_value(rinfos, i);
+ if (ri != NULL) {
+ switch (ri->type) {
+ case CMS_RECIPINFO_AGREE:
+ ri->d.kari->cms_ctx = ctx;
+ break;
+ case CMS_RECIPINFO_TRANS:
+ ri->d.ktri->cms_ctx = ctx;
+ ossl_x509_set0_libctx(ri->d.ktri->recip,
+ ossl_cms_ctx_get0_libctx(ctx),
+ ossl_cms_ctx_get0_propq(ctx));
+ break;
+ case CMS_RECIPINFO_KEK:
+ ri->d.kekri->cms_ctx = ctx;
+ break;
+ case CMS_RECIPINFO_PASS:
+ ri->d.pwri->cms_ctx = ctx;
+ break;
+ default:
+ break;
+ }
+ }
+ }
}
int CMS_RecipientInfo_type(CMS_RecipientInfo *ri)
@@ -101,32 +213,72 @@ EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri)
return NULL;
}
-CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
+CMS_ContentInfo *CMS_EnvelopedData_create_ex(const EVP_CIPHER *cipher,
+ OSSL_LIB_CTX *libctx,
+ const char *propq)
{
CMS_ContentInfo *cms;
CMS_EnvelopedData *env;
- cms = CMS_ContentInfo_new();
+
+ cms = CMS_ContentInfo_new_ex(libctx, propq);
if (cms == NULL)
goto merr;
env = cms_enveloped_data_init(cms);
if (env == NULL)
goto merr;
- if (!cms_EncryptedContent_init(env->encryptedContentInfo,
- cipher, NULL, 0))
+
+ if (!ossl_cms_EncryptedContent_init(env->encryptedContentInfo, cipher, NULL,
+ 0, ossl_cms_get0_cmsctx(cms)))
+ goto merr;
+ return cms;
+ merr:
+ CMS_ContentInfo_free(cms);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
+ return NULL;
+}
+
+CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
+{
+ return CMS_EnvelopedData_create_ex(cipher, NULL, NULL);
+}
+
+CMS_ContentInfo *
+CMS_AuthEnvelopedData_create_ex(const EVP_CIPHER *cipher, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ CMS_ContentInfo *cms;
+ CMS_AuthEnvelopedData *aenv;
+
+ cms = CMS_ContentInfo_new_ex(libctx, propq);
+ if (cms == NULL)
+ goto merr;
+ aenv = cms_auth_enveloped_data_init(cms);
+ if (aenv == NULL)
+ goto merr;
+ if (!ossl_cms_EncryptedContent_init(aenv->authEncryptedContentInfo,
+ cipher, NULL, 0,
+ ossl_cms_get0_cmsctx(cms)))
goto merr;
return cms;
merr:
CMS_ContentInfo_free(cms);
- CMSerr(CMS_F_CMS_ENVELOPEDDATA_CREATE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return NULL;
}
+
+CMS_ContentInfo *CMS_AuthEnvelopedData_create(const EVP_CIPHER *cipher)
+{
+ return CMS_AuthEnvelopedData_create_ex(cipher, NULL, NULL);
+}
+
/* Key Transport Recipient Info (KTRI) routines */
/* Initialise a ktri based on passed certificate and key */
static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
- EVP_PKEY *pk, unsigned int flags)
+ EVP_PKEY *pk, unsigned int flags,
+ const CMS_CTX *ctx)
{
CMS_KeyTransRecipientInfo *ktri;
int idtype;
@@ -137,6 +289,7 @@ static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
ri->type = CMS_RECIPINFO_TRANS;
ktri = ri->d.ktri;
+ ktri->cms_ctx = ctx;
if (flags & CMS_USE_KEYID) {
ktri->version = 2;
@@ -151,7 +304,7 @@ static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
* structure.
*/
- if (!cms_set1_SignerIdentifier(ktri->rid, recip, idtype))
+ if (!ossl_cms_set1_SignerIdentifier(ktri->rid, recip, idtype, ctx))
return 0;
X509_up_ref(recip);
@@ -161,12 +314,14 @@ static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
ktri->recip = recip;
if (flags & CMS_KEY_PARAM) {
- ktri->pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
+ ktri->pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx),
+ ktri->pkey,
+ ossl_cms_ctx_get0_propq(ctx));
if (ktri->pctx == NULL)
return 0;
if (EVP_PKEY_encrypt_init(ktri->pctx) <= 0)
return 0;
- } else if (!cms_env_asn1_ctrl(ri, 0))
+ } else if (!ossl_cms_env_asn1_ctrl(ri, 0))
return 0;
return 1;
}
@@ -175,67 +330,75 @@ static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
* Add a recipient certificate using appropriate type of RecipientInfo
*/
-CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
- X509 *recip, unsigned int flags)
+CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip,
+ EVP_PKEY *originatorPrivKey,
+ X509 *originator, unsigned int flags)
{
CMS_RecipientInfo *ri = NULL;
- CMS_EnvelopedData *env;
+ STACK_OF(CMS_RecipientInfo) *ris;
EVP_PKEY *pk = NULL;
- env = cms_get0_enveloped(cms);
- if (!env)
+ const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
+
+ ris = CMS_get0_RecipientInfos(cms);
+ if (ris == NULL)
goto err;
/* Initialize recipient info */
ri = M_ASN1_new_of(CMS_RecipientInfo);
- if (!ri)
+ if (ri == NULL)
goto merr;
pk = X509_get0_pubkey(recip);
- if (!pk) {
- CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_ERROR_GETTING_PUBLIC_KEY);
+ if (pk == NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_GETTING_PUBLIC_KEY);
goto err;
}
- switch (cms_pkey_get_ri_type(pk)) {
+ switch (ossl_cms_pkey_get_ri_type(pk)) {
case CMS_RECIPINFO_TRANS:
- if (!cms_RecipientInfo_ktri_init(ri, recip, pk, flags))
+ if (!cms_RecipientInfo_ktri_init(ri, recip, pk, flags, ctx))
goto err;
break;
case CMS_RECIPINFO_AGREE:
- if (!cms_RecipientInfo_kari_init(ri, recip, pk, flags))
+ if (!ossl_cms_RecipientInfo_kari_init(ri, recip, pk, originator,
+ originatorPrivKey, flags, ctx))
goto err;
break;
default:
- CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
- CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
goto err;
}
- if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
+ if (!sk_CMS_RecipientInfo_push(ris, ri))
goto merr;
return ri;
merr:
- CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
err:
M_ASN1_free_of(ri, CMS_RecipientInfo);
return NULL;
}
+CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip,
+ unsigned int flags)
+{
+ return CMS_add1_recipient(cms, recip, NULL, NULL, flags);
+}
+
int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
EVP_PKEY **pk, X509 **recip,
X509_ALGOR **palg)
{
CMS_KeyTransRecipientInfo *ktri;
if (ri->type != CMS_RECIPINFO_TRANS) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS,
- CMS_R_NOT_KEY_TRANSPORT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT);
return 0;
}
@@ -257,29 +420,28 @@ int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri,
{
CMS_KeyTransRecipientInfo *ktri;
if (ri->type != CMS_RECIPINFO_TRANS) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID,
- CMS_R_NOT_KEY_TRANSPORT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT);
return 0;
}
ktri = ri->d.ktri;
- return cms_SignerIdentifier_get0_signer_id(ktri->rid, keyid, issuer, sno);
+ return ossl_cms_SignerIdentifier_get0_signer_id(ktri->rid, keyid, issuer,
+ sno);
}
int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert)
{
if (ri->type != CMS_RECIPINFO_TRANS) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP,
- CMS_R_NOT_KEY_TRANSPORT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT);
return -2;
}
- return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert);
+ return ossl_cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert);
}
int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey)
{
if (ri->type != CMS_RECIPINFO_TRANS) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY, CMS_R_NOT_KEY_TRANSPORT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT);
return 0;
}
EVP_PKEY_free(ri->d.ktri->pkey);
@@ -289,7 +451,7 @@ int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey)
/* Encrypt content key in key transport recipient info */
-static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms,
+static int cms_RecipientInfo_ktri_encrypt(const CMS_ContentInfo *cms,
CMS_RecipientInfo *ri)
{
CMS_KeyTransRecipientInfo *ktri;
@@ -297,23 +459,26 @@ static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms,
EVP_PKEY_CTX *pctx;
unsigned char *ek = NULL;
size_t eklen;
+ const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
int ret = 0;
if (ri->type != CMS_RECIPINFO_TRANS) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_NOT_KEY_TRANSPORT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT);
return 0;
}
ktri = ri->d.ktri;
- ec = cms->d.envelopedData->encryptedContentInfo;
+ ec = ossl_cms_get0_env_enc_content(cms);
pctx = ktri->pctx;
if (pctx) {
- if (!cms_env_asn1_ctrl(ri, 0))
+ if (!ossl_cms_env_asn1_ctrl(ri, 0))
goto err;
} else {
- pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
+ pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx),
+ ktri->pkey,
+ ossl_cms_ctx_get0_propq(ctx));
if (pctx == NULL)
return 0;
@@ -321,19 +486,13 @@ static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms,
goto err;
}
- if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT,
- EVP_PKEY_CTRL_CMS_ENCRYPT, 0, ri) <= 0) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_CTRL_ERROR);
- goto err;
- }
-
if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0)
goto err;
ek = OPENSSL_malloc(eklen);
if (ek == NULL) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -350,7 +509,6 @@ static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms,
ktri->pctx = NULL;
OPENSSL_free(ek);
return ret;
-
}
/* Decrypt content key from KTRI */
@@ -364,42 +522,54 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
size_t eklen;
int ret = 0;
size_t fixlen = 0;
+ const EVP_CIPHER *cipher = NULL;
+ EVP_CIPHER *fetched_cipher = NULL;
CMS_EncryptedContentInfo *ec;
- ec = cms->d.envelopedData->encryptedContentInfo;
+ const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
+ OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(ctx);
+ const char *propq = ossl_cms_ctx_get0_propq(ctx);
+
+ ec = ossl_cms_get0_env_enc_content(cms);
if (ktri->pkey == NULL) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_NO_PRIVATE_KEY);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_PRIVATE_KEY);
return 0;
}
if (cms->d.envelopedData->encryptedContentInfo->havenocert
&& !cms->d.envelopedData->encryptedContentInfo->debug) {
X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
- const EVP_CIPHER *ciph = EVP_get_cipherbyobj(calg->algorithm);
+ char name[OSSL_MAX_NAME_SIZE];
+
+ OBJ_obj2txt(name, sizeof(name), calg->algorithm, 0);
- if (ciph == NULL) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_UNKNOWN_CIPHER);
+ (void)ERR_set_mark();
+ fetched_cipher = EVP_CIPHER_fetch(libctx, name, propq);
+
+ if (fetched_cipher != NULL)
+ cipher = fetched_cipher;
+ else
+ cipher = EVP_get_cipherbyobj(calg->algorithm);
+ if (cipher == NULL) {
+ (void)ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_CIPHER);
return 0;
}
+ (void)ERR_pop_to_mark();
- fixlen = EVP_CIPHER_key_length(ciph);
+ fixlen = EVP_CIPHER_get_key_length(cipher);
+ EVP_CIPHER_free(fetched_cipher);
}
- ktri->pctx = EVP_PKEY_CTX_new(pkey, NULL);
+ ktri->pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
if (ktri->pctx == NULL)
- return 0;
-
- if (EVP_PKEY_decrypt_init(ktri->pctx) <= 0)
goto err;
- if (!cms_env_asn1_ctrl(ri, 1))
+ if (EVP_PKEY_decrypt_init(ktri->pctx) <= 0)
goto err;
- if (EVP_PKEY_CTX_ctrl(ktri->pctx, -1, EVP_PKEY_OP_DECRYPT,
- EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CTRL_ERROR);
+ if (!ossl_cms_env_asn1_ctrl(ri, 1))
goto err;
- }
if (EVP_PKEY_decrypt(ktri->pctx, NULL, &eklen,
ktri->encryptedKey->data,
@@ -407,9 +577,8 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
goto err;
ek = OPENSSL_malloc(eklen);
-
if (ek == NULL) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -418,7 +587,7 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
ktri->encryptedKey->length) <= 0
|| eklen == 0
|| (fixlen != 0 && eklen != fixlen)) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CMS_LIB);
goto err;
}
@@ -445,7 +614,7 @@ int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri,
ASN1_OCTET_STRING tmp_os;
CMS_KEKRecipientInfo *kekri;
if (ri->type != CMS_RECIPINFO_KEK) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP, CMS_R_NOT_KEK);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEK);
return -2;
}
kekri = ri->d.kekri;
@@ -483,10 +652,10 @@ CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
ASN1_TYPE *otherType)
{
CMS_RecipientInfo *ri = NULL;
- CMS_EnvelopedData *env;
CMS_KEKRecipientInfo *kekri;
- env = cms_get0_enveloped(cms);
- if (!env)
+ STACK_OF(CMS_RecipientInfo) *ris = CMS_get0_RecipientInfos(cms);
+
+ if (ris == NULL)
goto err;
if (nid == NID_undef) {
@@ -504,7 +673,7 @@ CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
break;
default:
- CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, CMS_R_INVALID_KEY_LENGTH);
+ ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
goto err;
}
@@ -513,13 +682,12 @@ CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
size_t exp_keylen = aes_wrap_keylen(nid);
if (!exp_keylen) {
- CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,
- CMS_R_UNSUPPORTED_KEK_ALGORITHM);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEK_ALGORITHM);
goto err;
}
if (keylen != exp_keylen) {
- CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, CMS_R_INVALID_KEY_LENGTH);
+ ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
goto err;
}
@@ -543,7 +711,7 @@ CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
goto merr;
}
- if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
+ if (!sk_CMS_RecipientInfo_push(ris, ri))
goto merr;
/* After this point no calls can fail */
@@ -568,11 +736,10 @@ CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
return ri;
merr:
- CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
err:
M_ASN1_free_of(ri, CMS_RecipientInfo);
return NULL;
-
}
int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
@@ -584,7 +751,7 @@ int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
{
CMS_KEKIdentifier *rkid;
if (ri->type != CMS_RECIPINFO_KEK) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID, CMS_R_NOT_KEK);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEK);
return 0;
}
rkid = ri->d.kekri->kekid;
@@ -614,7 +781,7 @@ int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
{
CMS_KEKRecipientInfo *kekri;
if (ri->type != CMS_RECIPINFO_KEK) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY, CMS_R_NOT_KEK);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEK);
return 0;
}
@@ -624,44 +791,83 @@ int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
return 1;
}
+static EVP_CIPHER *cms_get_key_wrap_cipher(size_t keylen, const CMS_CTX *ctx)
+{
+ const char *alg = NULL;
+
+ switch(keylen) {
+ case 16:
+ alg = "AES-128-WRAP";
+ break;
+ case 24:
+ alg = "AES-192-WRAP";
+ break;
+ case 32:
+ alg = "AES-256-WRAP";
+ break;
+ default:
+ return NULL;
+ }
+ return EVP_CIPHER_fetch(ossl_cms_ctx_get0_libctx(ctx), alg,
+ ossl_cms_ctx_get0_propq(ctx));
+}
+
+
/* Encrypt content key in KEK recipient info */
-static int cms_RecipientInfo_kekri_encrypt(CMS_ContentInfo *cms,
+static int cms_RecipientInfo_kekri_encrypt(const CMS_ContentInfo *cms,
CMS_RecipientInfo *ri)
{
CMS_EncryptedContentInfo *ec;
CMS_KEKRecipientInfo *kekri;
- AES_KEY actx;
unsigned char *wkey = NULL;
int wkeylen;
int r = 0;
+ EVP_CIPHER *cipher = NULL;
+ int outlen = 0;
+ EVP_CIPHER_CTX *ctx = NULL;
+ const CMS_CTX *cms_ctx = ossl_cms_get0_cmsctx(cms);
- ec = cms->d.envelopedData->encryptedContentInfo;
+ ec = ossl_cms_get0_env_enc_content(cms);
+ if (ec == NULL)
+ return 0;
kekri = ri->d.kekri;
- if (!kekri->key) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_NO_KEY);
+ if (kekri->key == NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_KEY);
return 0;
}
- if (AES_set_encrypt_key(kekri->key, kekri->keylen << 3, &actx)) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT,
- CMS_R_ERROR_SETTING_KEY);
+ cipher = cms_get_key_wrap_cipher(kekri->keylen, cms_ctx);
+ if (cipher == NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
goto err;
}
+ /* 8 byte prefix for AES wrap ciphers */
wkey = OPENSSL_malloc(ec->keylen + 8);
-
if (wkey == NULL) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
- wkeylen = AES_wrap_key(&actx, NULL, wkey, ec->key, ec->keylen);
+ ctx = EVP_CIPHER_CTX_new();
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
- if (wkeylen <= 0) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_WRAP_ERROR);
+ EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
+ if (!EVP_EncryptInit_ex(ctx, cipher, NULL, kekri->key, NULL)
+ || !EVP_EncryptUpdate(ctx, wkey, &wkeylen, ec->key, ec->keylen)
+ || !EVP_EncryptFinal_ex(ctx, wkey + wkeylen, &outlen)) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_WRAP_ERROR);
+ goto err;
+ }
+ wkeylen += outlen;
+ if (!ossl_assert((size_t)wkeylen == ec->keylen + 8)) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_WRAP_ERROR);
goto err;
}
@@ -670,13 +876,12 @@ static int cms_RecipientInfo_kekri_encrypt(CMS_ContentInfo *cms,
r = 1;
err:
-
+ EVP_CIPHER_free(cipher);
if (!r)
OPENSSL_free(wkey);
- OPENSSL_cleanse(&actx, sizeof(actx));
+ EVP_CIPHER_CTX_free(ctx);
return r;
-
}
/* Decrypt content key in KEK recipient info */
@@ -686,56 +891,65 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
{
CMS_EncryptedContentInfo *ec;
CMS_KEKRecipientInfo *kekri;
- AES_KEY actx;
unsigned char *ukey = NULL;
int ukeylen;
int r = 0, wrap_nid;
+ EVP_CIPHER *cipher = NULL;
+ int outlen = 0;
+ EVP_CIPHER_CTX *ctx = NULL;
+ const CMS_CTX *cms_ctx = ossl_cms_get0_cmsctx(cms);
- ec = cms->d.envelopedData->encryptedContentInfo;
+ ec = ossl_cms_get0_env_enc_content(cms);
+ if (ec == NULL)
+ return 0;
kekri = ri->d.kekri;
if (!kekri->key) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_NO_KEY);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_KEY);
return 0;
}
wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm);
if (aes_wrap_keylen(wrap_nid) != kekri->keylen) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
- CMS_R_INVALID_KEY_LENGTH);
+ ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
return 0;
}
/* If encrypted key length is invalid don't bother */
if (kekri->encryptedKey->length < 16) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
- CMS_R_INVALID_ENCRYPTED_KEY_LENGTH);
+ ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_ENCRYPTED_KEY_LENGTH);
goto err;
}
- if (AES_set_decrypt_key(kekri->key, kekri->keylen << 3, &actx)) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
- CMS_R_ERROR_SETTING_KEY);
+ cipher = cms_get_key_wrap_cipher(kekri->keylen, cms_ctx);
+ if (cipher == NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
goto err;
}
ukey = OPENSSL_malloc(kekri->encryptedKey->length - 8);
-
if (ukey == NULL) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
- ukeylen = AES_unwrap_key(&actx, NULL, ukey,
- kekri->encryptedKey->data,
- kekri->encryptedKey->length);
+ ctx = EVP_CIPHER_CTX_new();
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
- if (ukeylen <= 0) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_UNWRAP_ERROR);
+ if (!EVP_DecryptInit_ex(ctx, cipher, NULL, kekri->key, NULL)
+ || !EVP_DecryptUpdate(ctx, ukey, &ukeylen,
+ kekri->encryptedKey->data,
+ kekri->encryptedKey->length)
+ || !EVP_DecryptFinal_ex(ctx, ukey + ukeylen, &outlen)) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNWRAP_ERROR);
goto err;
}
+ ukeylen += outlen;
OPENSSL_clear_free(ec->key, ec->keylen);
ec->key = ukey;
@@ -744,13 +958,12 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
r = 1;
err:
-
+ EVP_CIPHER_free(cipher);
if (!r)
OPENSSL_free(ukey);
- OPENSSL_cleanse(&actx, sizeof(actx));
+ EVP_CIPHER_CTX_free(ctx);
return r;
-
}
int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
@@ -763,33 +976,31 @@ int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
return cms_RecipientInfo_kekri_decrypt(cms, ri);
case CMS_RECIPINFO_PASS:
- return cms_RecipientInfo_pwri_crypt(cms, ri, 0);
+ return ossl_cms_RecipientInfo_pwri_crypt(cms, ri, 0);
default:
- CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT,
- CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE);
return 0;
}
}
-int CMS_RecipientInfo_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
+int CMS_RecipientInfo_encrypt(const CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
{
switch (ri->type) {
case CMS_RECIPINFO_TRANS:
return cms_RecipientInfo_ktri_encrypt(cms, ri);
case CMS_RECIPINFO_AGREE:
- return cms_RecipientInfo_kari_encrypt(cms, ri);
+ return ossl_cms_RecipientInfo_kari_encrypt(cms, ri);
case CMS_RECIPINFO_KEK:
return cms_RecipientInfo_kekri_encrypt(cms, ri);
case CMS_RECIPINFO_PASS:
- return cms_RecipientInfo_pwri_crypt(cms, ri, 1);
+ return ossl_cms_RecipientInfo_pwri_crypt(cms, ri, 1);
default:
- CMSerr(CMS_F_CMS_RECIPIENTINFO_ENCRYPT,
- CMS_R_UNSUPPORTED_RECIPIENT_TYPE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_RECIPIENT_TYPE);
return 0;
}
}
@@ -857,50 +1068,219 @@ static void cms_env_set_version(CMS_EnvelopedData *env)
env->version = 0;
}
-BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
+static int cms_env_encrypt_content_key(const CMS_ContentInfo *cms,
+ STACK_OF(CMS_RecipientInfo) *ris)
+{
+ int i;
+ CMS_RecipientInfo *ri;
+
+ for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
+ ri = sk_CMS_RecipientInfo_value(ris, i);
+ if (CMS_RecipientInfo_encrypt(cms, ri) <= 0)
+ return -1;
+ }
+ return 1;
+}
+
+static void cms_env_clear_ec(CMS_EncryptedContentInfo *ec)
+{
+ ec->cipher = NULL;
+ OPENSSL_clear_free(ec->key, ec->keylen);
+ ec->key = NULL;
+ ec->keylen = 0;
+}
+
+static BIO *cms_EnvelopedData_Decryption_init_bio(CMS_ContentInfo *cms)
+{
+ CMS_EncryptedContentInfo *ec = cms->d.envelopedData->encryptedContentInfo;
+ BIO *contentBio = ossl_cms_EncryptedContent_init_bio(ec,
+ ossl_cms_get0_cmsctx(cms));
+ EVP_CIPHER_CTX *ctx = NULL;
+
+ if (contentBio == NULL)
+ return NULL;
+
+ BIO_get_cipher_ctx(contentBio, &ctx);
+ if (ctx == NULL) {
+ BIO_free(contentBio);
+ return NULL;
+ }
+ /*
+ * If the selected cipher supports unprotected attributes,
+ * deal with it using special ctrl function
+ */
+ if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx))
+ & EVP_CIPH_FLAG_CIPHER_WITH_MAC) != 0
+ && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PROCESS_UNPROTECTED, 0,
+ cms->d.envelopedData->unprotectedAttrs) <= 0) {
+ BIO_free(contentBio);
+ return NULL;
+ }
+ return contentBio;
+}
+
+static BIO *cms_EnvelopedData_Encryption_init_bio(CMS_ContentInfo *cms)
{
CMS_EncryptedContentInfo *ec;
STACK_OF(CMS_RecipientInfo) *rinfos;
- CMS_RecipientInfo *ri;
- int i, ok = 0;
+ int ok = 0;
BIO *ret;
+ CMS_EnvelopedData *env = cms->d.envelopedData;
/* Get BIO first to set up key */
- ec = cms->d.envelopedData->encryptedContentInfo;
- ret = cms_EncryptedContent_init_bio(ec);
+ ec = env->encryptedContentInfo;
+ ret = ossl_cms_EncryptedContent_init_bio(ec, ossl_cms_get0_cmsctx(cms));
- /* If error or no cipher end of processing */
-
- if (!ret || !ec->cipher)
+ /* If error end of processing */
+ if (!ret)
return ret;
/* Now encrypt content key according to each RecipientInfo type */
+ rinfos = env->recipientInfos;
+ if (cms_env_encrypt_content_key(cms, rinfos) < 0) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_SETTING_RECIPIENTINFO);
+ goto err;
+ }
- rinfos = cms->d.envelopedData->recipientInfos;
+ /* And finally set the version */
+ cms_env_set_version(env);
- for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) {
- ri = sk_CMS_RecipientInfo_value(rinfos, i);
- if (CMS_RecipientInfo_encrypt(cms, ri) <= 0) {
- CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
- CMS_R_ERROR_SETTING_RECIPIENTINFO);
- goto err;
- }
+ ok = 1;
+
+ err:
+ cms_env_clear_ec(ec);
+ if (ok)
+ return ret;
+ BIO_free(ret);
+ return NULL;
+}
+
+BIO *ossl_cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
+{
+ if (cms->d.envelopedData->encryptedContentInfo->cipher != NULL) {
+ /* If cipher is set it's encryption */
+ return cms_EnvelopedData_Encryption_init_bio(cms);
+ }
+
+ /* If cipher is not set it's decryption */
+ return cms_EnvelopedData_Decryption_init_bio(cms);
+}
+
+BIO *ossl_cms_AuthEnvelopedData_init_bio(CMS_ContentInfo *cms)
+{
+ CMS_EncryptedContentInfo *ec;
+ STACK_OF(CMS_RecipientInfo) *rinfos;
+ int ok = 0;
+ BIO *ret;
+ CMS_AuthEnvelopedData *aenv = cms->d.authEnvelopedData;
+
+ /* Get BIO first to set up key */
+ ec = aenv->authEncryptedContentInfo;
+ /* Set tag for decryption */
+ if (ec->cipher == NULL) {
+ ec->tag = aenv->mac->data;
+ ec->taglen = aenv->mac->length;
+ }
+ ret = ossl_cms_EncryptedContent_init_bio(ec, ossl_cms_get0_cmsctx(cms));
+
+ /* If error or no cipher end of processing */
+ if (ret == NULL || ec->cipher == NULL)
+ return ret;
+
+ /* Now encrypt content key according to each RecipientInfo type */
+ rinfos = aenv->recipientInfos;
+ if (cms_env_encrypt_content_key(cms, rinfos) < 0) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_SETTING_RECIPIENTINFO);
+ goto err;
}
- cms_env_set_version(cms->d.envelopedData);
+
+ /* And finally set the version */
+ aenv->version = 0;
ok = 1;
err:
- ec->cipher = NULL;
- OPENSSL_clear_free(ec->key, ec->keylen);
- ec->key = NULL;
- ec->keylen = 0;
+ cms_env_clear_ec(ec);
if (ok)
return ret;
BIO_free(ret);
return NULL;
+}
+
+int ossl_cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain)
+{
+ CMS_EnvelopedData *env = NULL;
+ EVP_CIPHER_CTX *ctx = NULL;
+ BIO *mbio = BIO_find_type(chain, BIO_TYPE_CIPHER);
+
+ env = ossl_cms_get0_enveloped(cms);
+ if (env == NULL)
+ return 0;
+
+ if (mbio == NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_NOT_FOUND);
+ return 0;
+ }
+
+ BIO_get_cipher_ctx(mbio, &ctx);
+
+ /*
+ * If the selected cipher supports unprotected attributes,
+ * deal with it using special ctrl function
+ */
+ if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx))
+ & EVP_CIPH_FLAG_CIPHER_WITH_MAC) != 0) {
+ if (env->unprotectedAttrs == NULL)
+ env->unprotectedAttrs = sk_X509_ATTRIBUTE_new_null();
+
+ if (env->unprotectedAttrs == NULL) {
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PROCESS_UNPROTECTED,
+ 1, env->unprotectedAttrs) <= 0) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_CTRL_FAILURE);
+ return 0;
+ }
+ }
+ cms_env_set_version(cms->d.envelopedData);
+ return 1;
+}
+
+int ossl_cms_AuthEnvelopedData_final(CMS_ContentInfo *cms, BIO *cmsbio)
+{
+ EVP_CIPHER_CTX *ctx;
+ unsigned char *tag = NULL;
+ int taglen, ok = 0;
+
+ BIO_get_cipher_ctx(cmsbio, &ctx);
+
+ /*
+ * The tag is set only for encryption. There is nothing to do for
+ * decryption.
+ */
+ if (!EVP_CIPHER_CTX_is_encrypting(ctx))
+ return 1;
+
+ taglen = EVP_CIPHER_CTX_get_tag_length(ctx);
+ if (taglen <= 0
+ || (tag = OPENSSL_malloc(taglen)) == NULL
+ || EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen,
+ tag) <= 0) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_GET_TAG);
+ goto err;
+ }
+
+ if (!ASN1_OCTET_STRING_set(cms->d.authEnvelopedData->mac, tag, taglen))
+ goto err;
+
+ ok = 1;
+err:
+ OPENSSL_free(tag);
+ return ok;
}
/*
@@ -908,8 +1288,24 @@ BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
* retain compatibility with previous behaviour if the ctrl value isn't
* supported we assume key transport.
*/
-int cms_pkey_get_ri_type(EVP_PKEY *pk)
+int ossl_cms_pkey_get_ri_type(EVP_PKEY *pk)
{
+ /* Check types that we know about */
+ if (EVP_PKEY_is_a(pk, "DH"))
+ return CMS_RECIPINFO_AGREE;
+ else if (EVP_PKEY_is_a(pk, "DHX"))
+ return CMS_RECIPINFO_AGREE;
+ else if (EVP_PKEY_is_a(pk, "DSA"))
+ return CMS_RECIPINFO_NONE;
+ else if (EVP_PKEY_is_a(pk, "EC"))
+ return CMS_RECIPINFO_AGREE;
+ else if (EVP_PKEY_is_a(pk, "RSA"))
+ return CMS_RECIPINFO_TRANS;
+
+ /*
+ * Otherwise this might ben an engine implementation, so see if we can get
+ * the type from the ameth.
+ */
if (pk->ameth && pk->ameth->pkey_ctrl) {
int i, r;
i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_RI_TYPE, 0, &r);
@@ -918,3 +1314,23 @@ int cms_pkey_get_ri_type(EVP_PKEY *pk)
}
return CMS_RECIPINFO_TRANS;
}
+
+int ossl_cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type)
+{
+ int supportedRiType;
+
+ if (pk->ameth != NULL && pk->ameth->pkey_ctrl != NULL) {
+ int i, r;
+
+ i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED,
+ ri_type, &r);
+ if (i > 0)
+ return r;
+ }
+
+ supportedRiType = ossl_cms_pkey_get_ri_type(pk);
+ if (supportedRiType < 0)
+ return 0;
+
+ return (supportedRiType == ri_type);
+}
diff --git a/crypto/cms/cms_err.c b/crypto/cms/cms_err.c
index 408fe13b87d9..dcbea201c8e5 100644
--- a/crypto/cms/cms_err.c
+++ b/crypto/cms/cms_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,150 +10,11 @@
#include <openssl/err.h>
#include <openssl/cmserr.h>
+#include "crypto/cmserr.h"
-#ifndef OPENSSL_NO_ERR
+#ifndef OPENSSL_NO_CMS
-static const ERR_STRING_DATA CMS_str_functs[] = {
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CHECK_CONTENT, 0), "check_content"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD0_CERT, 0), "CMS_add0_cert"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD0_RECIPIENT_KEY, 0),
- "CMS_add0_recipient_key"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, 0),
- "CMS_add0_recipient_password"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_RECEIPTREQUEST, 0),
- "CMS_add1_ReceiptRequest"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_RECIPIENT_CERT, 0),
- "CMS_add1_recipient_cert"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_SIGNER, 0), "CMS_add1_signer"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_SIGNINGTIME, 0),
- "cms_add1_signingTime"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_COMPRESS, 0), "CMS_compress"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_COMPRESSEDDATA_CREATE, 0),
- "cms_CompressedData_create"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_COMPRESSEDDATA_INIT_BIO, 0),
- "cms_CompressedData_init_bio"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_COPY_CONTENT, 0), "cms_copy_content"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_COPY_MESSAGEDIGEST, 0),
- "cms_copy_messageDigest"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DATA, 0), "CMS_data"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DATAFINAL, 0), "CMS_dataFinal"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DATAINIT, 0), "CMS_dataInit"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DECRYPT, 0), "CMS_decrypt"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DECRYPT_SET1_KEY, 0),
- "CMS_decrypt_set1_key"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DECRYPT_SET1_PASSWORD, 0),
- "CMS_decrypt_set1_password"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DECRYPT_SET1_PKEY, 0),
- "CMS_decrypt_set1_pkey"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DIGESTALGORITHM_FIND_CTX, 0),
- "cms_DigestAlgorithm_find_ctx"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, 0),
- "cms_DigestAlgorithm_init_bio"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DIGESTEDDATA_DO_FINAL, 0),
- "cms_DigestedData_do_final"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DIGEST_VERIFY, 0), "CMS_digest_verify"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENCODE_RECEIPT, 0), "cms_encode_Receipt"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENCRYPT, 0), "CMS_encrypt"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENCRYPTEDCONTENT_INIT, 0),
- "cms_EncryptedContent_init"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, 0),
- "cms_EncryptedContent_init_bio"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENCRYPTEDDATA_DECRYPT, 0),
- "CMS_EncryptedData_decrypt"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, 0),
- "CMS_EncryptedData_encrypt"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, 0),
- "CMS_EncryptedData_set1_key"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENVELOPEDDATA_CREATE, 0),
- "CMS_EnvelopedData_create"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENVELOPEDDATA_INIT_BIO, 0),
- "cms_EnvelopedData_init_bio"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENVELOPED_DATA_INIT, 0),
- "cms_enveloped_data_init"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENV_ASN1_CTRL, 0), "cms_env_asn1_ctrl"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_FINAL, 0), "CMS_final"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_GET0_CERTIFICATE_CHOICES, 0),
- "cms_get0_certificate_choices"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_GET0_CONTENT, 0), "CMS_get0_content"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_GET0_ECONTENT_TYPE, 0),
- "cms_get0_econtent_type"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_GET0_ENVELOPED, 0), "cms_get0_enveloped"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_GET0_REVOCATION_CHOICES, 0),
- "cms_get0_revocation_choices"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_GET0_SIGNED, 0), "cms_get0_signed"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_MSGSIGDIGEST_ADD1, 0),
- "cms_msgSigDigest_add1"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECEIPTREQUEST_CREATE0, 0),
- "CMS_ReceiptRequest_create0"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECEIPT_VERIFY, 0), "cms_Receipt_verify"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_DECRYPT, 0),
- "CMS_RecipientInfo_decrypt"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_ENCRYPT, 0),
- "CMS_RecipientInfo_encrypt"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT, 0),
- "cms_RecipientInfo_kari_encrypt"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG, 0),
- "CMS_RecipientInfo_kari_get0_alg"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID, 0),
- "CMS_RecipientInfo_kari_get0_orig_id"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS, 0),
- "CMS_RecipientInfo_kari_get0_reks"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP, 0),
- "CMS_RecipientInfo_kari_orig_id_cmp"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, 0),
- "cms_RecipientInfo_kekri_decrypt"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, 0),
- "cms_RecipientInfo_kekri_encrypt"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID, 0),
- "CMS_RecipientInfo_kekri_get0_id"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP, 0),
- "CMS_RecipientInfo_kekri_id_cmp"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP, 0),
- "CMS_RecipientInfo_ktri_cert_cmp"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, 0),
- "cms_RecipientInfo_ktri_decrypt"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, 0),
- "cms_RecipientInfo_ktri_encrypt"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS, 0),
- "CMS_RecipientInfo_ktri_get0_algs"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID, 0),
- "CMS_RecipientInfo_ktri_get0_signer_id"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, 0),
- "cms_RecipientInfo_pwri_crypt"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_SET0_KEY, 0),
- "CMS_RecipientInfo_set0_key"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD, 0),
- "CMS_RecipientInfo_set0_password"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_SET0_PKEY, 0),
- "CMS_RecipientInfo_set0_pkey"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SD_ASN1_CTRL, 0), "cms_sd_asn1_ctrl"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SET1_IAS, 0), "cms_set1_ias"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SET1_KEYID, 0), "cms_set1_keyid"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SET1_SIGNERIDENTIFIER, 0),
- "cms_set1_SignerIdentifier"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SET_DETACHED, 0), "CMS_set_detached"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SIGN, 0), "CMS_sign"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SIGNED_DATA_INIT, 0),
- "cms_signed_data_init"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, 0),
- "cms_SignerInfo_content_sign"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SIGNERINFO_SIGN, 0),
- "CMS_SignerInfo_sign"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SIGNERINFO_VERIFY, 0),
- "CMS_SignerInfo_verify"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SIGNERINFO_VERIFY_CERT, 0),
- "cms_signerinfo_verify_cert"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, 0),
- "CMS_SignerInfo_verify_content"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SIGN_RECEIPT, 0), "CMS_sign_receipt"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SI_CHECK_ATTRIBUTES, 0),
- "CMS_si_check_attributes"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_STREAM, 0), "CMS_stream"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_UNCOMPRESS, 0), "CMS_uncompress"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_VERIFY, 0), "CMS_verify"},
- {ERR_PACK(ERR_LIB_CMS, CMS_F_KEK_UNWRAP_KEY, 0), "kek_unwrap_key"},
- {0, NULL}
-};
+# ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA CMS_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ADD_SIGNER_ERROR), "add signer error"},
@@ -164,6 +25,9 @@ static const ERR_STRING_DATA CMS_str_reasons[] = {
"certificate has no keyid"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CERTIFICATE_VERIFY_ERROR),
"certificate verify error"},
+ {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CIPHER_AEAD_SET_TAG_ERROR),
+ "cipher aead set tag error"},
+ {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CIPHER_GET_TAG), "cipher get tag"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CIPHER_INITIALISATION_ERROR),
"cipher initialisation error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR),
@@ -186,6 +50,7 @@ static const ERR_STRING_DATA CMS_str_reasons[] = {
"content verify error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CTRL_ERROR), "ctrl error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CTRL_FAILURE), "ctrl failure"},
+ {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_DECODE_ERROR), "decode error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_DECRYPT_ERROR), "decrypt error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_GETTING_PUBLIC_KEY),
"error getting public key"},
@@ -194,11 +59,18 @@ static const ERR_STRING_DATA CMS_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_SETTING_KEY), "error setting key"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_SETTING_RECIPIENTINFO),
"error setting recipientinfo"},
+ {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR),
+ "ess signing certid mismatch error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_ENCRYPTED_KEY_LENGTH),
"invalid encrypted key length"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER),
"invalid key encryption parameter"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_KEY_LENGTH), "invalid key length"},
+ {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_LABEL), "invalid label"},
+ {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_OAEP_PARAMETERS),
+ "invalid oaep parameters"},
+ {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_KDF_PARAMETER_ERROR),
+ "kdf parameter error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MD_BIO_INIT_ERROR), "md bio init error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH),
"messagedigest attribute wrong length"},
@@ -237,11 +109,13 @@ static const ERR_STRING_DATA CMS_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_PUBLIC_KEY), "no public key"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_RECEIPT_REQUEST), "no receipt request"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_SIGNERS), "no signers"},
+ {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_PEER_KEY_ERROR), "peer key error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE),
"private key does not match certificate"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_RECEIPT_DECODE_ERROR),
"receipt decode error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_RECIPIENT_ERROR), "recipient error"},
+ {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_SHARED_INFO_ERROR), "shared info error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND),
"signer certificate not found"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_SIGNFINAL_ERROR), "signfinal error"},
@@ -268,10 +142,14 @@ static const ERR_STRING_DATA CMS_str_reasons[] = {
"unsupported content encryption algorithm"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_CONTENT_TYPE),
"unsupported content type"},
+ {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_ENCRYPTION_TYPE),
+ "unsupported encryption type"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_KEK_ALGORITHM),
"unsupported kek algorithm"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM),
"unsupported key encryption algorithm"},
+ {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_LABEL_SOURCE),
+ "unsupported label source"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE),
"unsupported recipientinfo type"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_RECIPIENT_TYPE),
@@ -285,15 +163,16 @@ static const ERR_STRING_DATA CMS_str_reasons[] = {
{0, NULL}
};
-#endif
+# endif
-int ERR_load_CMS_strings(void)
+int ossl_err_load_CMS_strings(void)
{
-#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(CMS_str_functs[0].error) == NULL) {
- ERR_load_strings_const(CMS_str_functs);
+# ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(CMS_str_reasons[0].error) == NULL)
ERR_load_strings_const(CMS_str_reasons);
- }
-#endif
+# endif
return 1;
}
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/crypto/cms/cms_ess.c b/crypto/cms/cms_ess.c
index a21c443ae85e..6c43dd102a91 100644
--- a/crypto/cms/cms_ess.c
+++ b/crypto/cms/cms_ess.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -14,42 +14,111 @@
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/cms.h>
+#include <openssl/ess.h>
+#include "crypto/ess.h"
+#include "crypto/x509.h"
#include "cms_local.h"
IMPLEMENT_ASN1_FUNCTIONS(CMS_ReceiptRequest)
-/* ESS services: for now just Signed Receipt related */
+/* ESS services */
int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr)
{
ASN1_STRING *str;
- CMS_ReceiptRequest *rr = NULL;
- if (prr)
+ CMS_ReceiptRequest *rr;
+ ASN1_OBJECT *obj = OBJ_nid2obj(NID_id_smime_aa_receiptRequest);
+
+ if (prr != NULL)
*prr = NULL;
- str = CMS_signed_get0_data_by_OBJ(si,
- OBJ_nid2obj
- (NID_id_smime_aa_receiptRequest), -3,
- V_ASN1_SEQUENCE);
- if (!str)
+ str = CMS_signed_get0_data_by_OBJ(si, obj, -3, V_ASN1_SEQUENCE);
+ if (str == NULL)
return 0;
rr = ASN1_item_unpack(str, ASN1_ITEM_rptr(CMS_ReceiptRequest));
- if (!rr)
+ if (rr == NULL)
return -1;
- if (prr)
+ if (prr != NULL)
*prr = rr;
else
CMS_ReceiptRequest_free(rr);
return 1;
}
-CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
- int allorfirst,
- STACK_OF(GENERAL_NAMES)
- *receiptList, STACK_OF(GENERAL_NAMES)
- *receiptsTo)
+/*
+ * Returns 0 if attribute is not found, 1 if found,
+ * or -1 on attribute parsing failure.
+ */
+static int ossl_cms_signerinfo_get_signing_cert(const CMS_SignerInfo *si,
+ ESS_SIGNING_CERT **psc)
{
- CMS_ReceiptRequest *rr = NULL;
+ ASN1_STRING *str;
+ ESS_SIGNING_CERT *sc;
+ ASN1_OBJECT *obj = OBJ_nid2obj(NID_id_smime_aa_signingCertificate);
+
+ if (psc != NULL)
+ *psc = NULL;
+ str = CMS_signed_get0_data_by_OBJ(si, obj, -3, V_ASN1_SEQUENCE);
+ if (str == NULL)
+ return 0;
+
+ sc = ASN1_item_unpack(str, ASN1_ITEM_rptr(ESS_SIGNING_CERT));
+ if (sc == NULL)
+ return -1;
+ if (psc != NULL)
+ *psc = sc;
+ else
+ ESS_SIGNING_CERT_free(sc);
+ return 1;
+}
+
+/*
+ * Returns 0 if attribute is not found, 1 if found,
+ * or -1 on attribute parsing failure.
+ */
+static int ossl_cms_signerinfo_get_signing_cert_v2(const CMS_SignerInfo *si,
+ ESS_SIGNING_CERT_V2 **psc)
+{
+ ASN1_STRING *str;
+ ESS_SIGNING_CERT_V2 *sc;
+ ASN1_OBJECT *obj = OBJ_nid2obj(NID_id_smime_aa_signingCertificateV2);
+
+ if (psc != NULL)
+ *psc = NULL;
+ str = CMS_signed_get0_data_by_OBJ(si, obj, -3, V_ASN1_SEQUENCE);
+ if (str == NULL)
+ return 0;
+
+ sc = ASN1_item_unpack(str, ASN1_ITEM_rptr(ESS_SIGNING_CERT_V2));
+ if (sc == NULL)
+ return -1;
+ if (psc != NULL)
+ *psc = sc;
+ else
+ ESS_SIGNING_CERT_V2_free(sc);
+ return 1;
+}
+
+int ossl_cms_check_signing_certs(const CMS_SignerInfo *si,
+ const STACK_OF(X509) *chain)
+{
+ ESS_SIGNING_CERT *ss = NULL;
+ ESS_SIGNING_CERT_V2 *ssv2 = NULL;
+ int ret = ossl_cms_signerinfo_get_signing_cert(si, &ss) >= 0
+ && ossl_cms_signerinfo_get_signing_cert_v2(si, &ssv2) >= 0
+ && OSSL_ESS_check_signing_certs(ss, ssv2, chain, 1) > 0;
+
+ ESS_SIGNING_CERT_free(ss);
+ ESS_SIGNING_CERT_V2_free(ssv2);
+ return ret;
+}
+
+CMS_ReceiptRequest *CMS_ReceiptRequest_create0_ex(
+ unsigned char *id, int idlen, int allorfirst,
+ STACK_OF(GENERAL_NAMES) *receiptList, STACK_OF(GENERAL_NAMES) *receiptsTo,
+ OSSL_LIB_CTX *libctx)
+{
+ CMS_ReceiptRequest *rr;
rr = CMS_ReceiptRequest_new();
if (rr == NULL)
@@ -59,14 +128,15 @@ CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
else {
if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL, 32))
goto merr;
- if (RAND_bytes(rr->signedContentIdentifier->data, 32) <= 0)
+ if (RAND_bytes_ex(libctx, rr->signedContentIdentifier->data, 32,
+ 0) <= 0)
goto err;
}
sk_GENERAL_NAMES_pop_free(rr->receiptsTo, GENERAL_NAMES_free);
rr->receiptsTo = receiptsTo;
- if (receiptList) {
+ if (receiptList != NULL) {
rr->receiptsFrom->type = 1;
rr->receiptsFrom->d.receiptList = receiptList;
} else {
@@ -77,7 +147,7 @@ CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
return rr;
merr:
- CMSerr(CMS_F_CMS_RECEIPTREQUEST_CREATE0, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
err:
CMS_ReceiptRequest_free(rr);
@@ -85,6 +155,14 @@ CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
}
+CMS_ReceiptRequest *CMS_ReceiptRequest_create0(
+ unsigned char *id, int idlen, int allorfirst,
+ STACK_OF(GENERAL_NAMES) *receiptList, STACK_OF(GENERAL_NAMES) *receiptsTo)
+{
+ return CMS_ReceiptRequest_create0_ex(id, idlen, allorfirst, receiptList,
+ receiptsTo, NULL);
+}
+
int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr)
{
unsigned char *rrder = NULL;
@@ -102,7 +180,7 @@ int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr)
merr:
if (!r)
- CMSerr(CMS_F_CMS_ADD1_RECEIPTREQUEST, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
OPENSSL_free(rrder);
@@ -116,20 +194,20 @@ void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
STACK_OF(GENERAL_NAMES) **plist,
STACK_OF(GENERAL_NAMES) **prto)
{
- if (pcid)
+ if (pcid != NULL)
*pcid = rr->signedContentIdentifier;
if (rr->receiptsFrom->type == 0) {
- if (pallorfirst)
+ if (pallorfirst != NULL)
*pallorfirst = (int)rr->receiptsFrom->d.allOrFirstTier;
- if (plist)
+ if (plist != NULL)
*plist = NULL;
} else {
- if (pallorfirst)
+ if (pallorfirst != NULL)
*pallorfirst = -1;
- if (plist)
+ if (plist != NULL)
*plist = rr->receiptsFrom->d.receiptList;
}
- if (prto)
+ if (prto != NULL)
*prto = rr->receiptsTo;
}
@@ -138,29 +216,32 @@ void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
static int cms_msgSigDigest(CMS_SignerInfo *si,
unsigned char *dig, unsigned int *diglen)
{
- const EVP_MD *md;
- md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
+ const EVP_MD *md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
+
if (md == NULL)
return 0;
- if (!ASN1_item_digest(ASN1_ITEM_rptr(CMS_Attributes_Verify), md,
- si->signedAttrs, dig, diglen))
+ if (!ossl_asn1_item_digest_ex(ASN1_ITEM_rptr(CMS_Attributes_Verify), md,
+ si->signedAttrs, dig, diglen,
+ ossl_cms_ctx_get0_libctx(si->cms_ctx),
+ ossl_cms_ctx_get0_propq(si->cms_ctx)))
return 0;
return 1;
}
/* Add a msgSigDigest attribute to a SignerInfo */
-int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src)
+int ossl_cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src)
{
unsigned char dig[EVP_MAX_MD_SIZE];
unsigned int diglen;
+
if (!cms_msgSigDigest(src, dig, &diglen)) {
- CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, CMS_R_MSGSIGDIGEST_ERROR);
+ ERR_raise(ERR_LIB_CMS, CMS_R_MSGSIGDIGEST_ERROR);
return 0;
}
if (!CMS_signed_add1_attr_by_NID(dest, NID_id_smime_aa_msgSigDigest,
V_ASN1_OCTET_STRING, dig, diglen)) {
- CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
@@ -168,7 +249,7 @@ int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src)
/* Verify signed receipt after it has already passed normal CMS verify */
-int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms)
+int ossl_cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms)
{
int r = 0, i;
CMS_ReceiptRequest *rr = NULL;
@@ -187,27 +268,27 @@ int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms)
goto err;
if (sk_CMS_SignerInfo_num(sis) != 1) {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NEED_ONE_SIGNER);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NEED_ONE_SIGNER);
goto err;
}
/* Check receipt content type */
if (OBJ_obj2nid(CMS_get0_eContentType(cms)) != NID_id_smime_ct_receipt) {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NOT_A_SIGNED_RECEIPT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_A_SIGNED_RECEIPT);
goto err;
}
/* Extract and decode receipt content */
pcont = CMS_get0_content(cms);
- if (!pcont || !*pcont) {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_CONTENT);
+ if (pcont == NULL || *pcont == NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_CONTENT);
goto err;
}
rct = ASN1_item_unpack(*pcont, ASN1_ITEM_rptr(CMS_Receipt));
if (!rct) {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_RECEIPT_DECODE_ERROR);
+ ERR_raise(ERR_LIB_CMS, CMS_R_RECEIPT_DECODE_ERROR);
goto err;
}
@@ -220,7 +301,7 @@ int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms)
}
if (i == sk_CMS_SignerInfo_num(osis)) {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_MATCHING_SIGNATURE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_SIGNATURE);
goto err;
}
@@ -234,23 +315,22 @@ int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms)
V_ASN1_OCTET_STRING);
if (!msig) {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_MSGSIGDIGEST);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_MSGSIGDIGEST);
goto err;
}
if (!cms_msgSigDigest(osi, dig, &diglen)) {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_MSGSIGDIGEST_ERROR);
+ ERR_raise(ERR_LIB_CMS, CMS_R_MSGSIGDIGEST_ERROR);
goto err;
}
if (diglen != (unsigned int)msig->length) {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_MSGSIGDIGEST_WRONG_LENGTH);
+ ERR_raise(ERR_LIB_CMS, CMS_R_MSGSIGDIGEST_WRONG_LENGTH);
goto err;
}
if (memcmp(dig, msig->data, diglen)) {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY,
- CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE);
goto err;
}
@@ -260,27 +340,27 @@ int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms)
OBJ_nid2obj(NID_pkcs9_contentType),
-3, V_ASN1_OBJECT);
if (!octype) {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_CONTENT_TYPE);
goto err;
}
/* Compare details in receipt request */
if (OBJ_cmp(octype, rct->contentType)) {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_CONTENT_TYPE_MISMATCH);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_MISMATCH);
goto err;
}
/* Get original receipt request details */
if (CMS_get1_ReceiptRequest(osi, &rr) <= 0) {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_RECEIPT_REQUEST);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_RECEIPT_REQUEST);
goto err;
}
if (ASN1_STRING_cmp(rr->signedContentIdentifier,
rct->signedContentIdentifier)) {
- CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_CONTENTIDENTIFIER_MISMATCH);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CONTENTIDENTIFIER_MISMATCH);
goto err;
}
@@ -298,7 +378,7 @@ int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms)
* SignedData ContentInfo.
*/
-ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si)
+ASN1_OCTET_STRING *ossl_cms_encode_Receipt(CMS_SignerInfo *si)
{
CMS_Receipt rct;
CMS_ReceiptRequest *rr = NULL;
@@ -310,7 +390,7 @@ ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si)
/* Get original receipt request details */
if (CMS_get1_ReceiptRequest(si, &rr) <= 0) {
- CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_RECEIPT_REQUEST);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_RECEIPT_REQUEST);
goto err;
}
@@ -320,7 +400,7 @@ ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si)
OBJ_nid2obj(NID_pkcs9_contentType),
-3, V_ASN1_OBJECT);
if (!ctype) {
- CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_CONTENT_TYPE);
goto err;
}
diff --git a/crypto/cms/cms_io.c b/crypto/cms/cms_io.c
index b37e485f5a28..dab70af73c33 100644
--- a/crypto/cms/cms_io.c
+++ b/crypto/cms/cms_io.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -14,6 +14,7 @@
#include <openssl/cms.h>
#include "cms_local.h"
+/* unfortunately cannot constify BIO_new_NDEF() due to this and PKCS7_stream() */
int CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms)
{
ASN1_OCTET_STRING **pos;
@@ -28,13 +29,24 @@ int CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms)
*boundary = &(*pos)->data;
return 1;
}
- CMSerr(CMS_F_CMS_STREAM, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return 0;
}
CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms)
{
- return ASN1_item_d2i_bio(ASN1_ITEM_rptr(CMS_ContentInfo), bp, cms);
+ CMS_ContentInfo *ci;
+ const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms == NULL ? NULL : *cms);
+
+ ci = ASN1_item_d2i_bio_ex(ASN1_ITEM_rptr(CMS_ContentInfo), bp, cms,
+ ossl_cms_ctx_get0_libctx(ctx),
+ ossl_cms_ctx_get0_propq(ctx));
+ if (ci != NULL) {
+ ERR_set_mark();
+ ossl_cms_resolve_libctx(ci);
+ ERR_pop_to_mark();
+ }
+ return ci;
}
int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms)
@@ -42,7 +54,7 @@ int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms)
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(CMS_ContentInfo), bp, cms);
}
-IMPLEMENT_PEM_rw_const(CMS, CMS_ContentInfo, PEM_STRING_CMS, CMS_ContentInfo)
+IMPLEMENT_PEM_rw(CMS, CMS_ContentInfo, PEM_STRING_CMS, CMS_ContentInfo)
BIO *BIO_new_CMS(BIO *out, CMS_ContentInfo *cms)
{
@@ -70,19 +82,40 @@ int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags)
STACK_OF(X509_ALGOR) *mdalgs;
int ctype_nid = OBJ_obj2nid(cms->contentType);
int econt_nid = OBJ_obj2nid(CMS_get0_eContentType(cms));
+ const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
+
if (ctype_nid == NID_pkcs7_signed)
mdalgs = cms->d.signedData->digestAlgorithms;
else
mdalgs = NULL;
- return SMIME_write_ASN1(bio, (ASN1_VALUE *)cms, data, flags,
- ctype_nid, econt_nid, mdalgs,
- ASN1_ITEM_rptr(CMS_ContentInfo));
+ return SMIME_write_ASN1_ex(bio, (ASN1_VALUE *)cms, data, flags, ctype_nid,
+ econt_nid, mdalgs,
+ ASN1_ITEM_rptr(CMS_ContentInfo),
+ ossl_cms_ctx_get0_libctx(ctx),
+ ossl_cms_ctx_get0_propq(ctx));
+}
+
+CMS_ContentInfo *SMIME_read_CMS_ex(BIO *bio, int flags, BIO **bcont,
+ CMS_ContentInfo **cms)
+{
+ CMS_ContentInfo *ci;
+ const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms == NULL ? NULL : *cms);
+
+ ci = (CMS_ContentInfo *)SMIME_read_ASN1_ex(bio, flags, bcont,
+ ASN1_ITEM_rptr(CMS_ContentInfo),
+ (ASN1_VALUE **)cms,
+ ossl_cms_ctx_get0_libctx(ctx),
+ ossl_cms_ctx_get0_propq(ctx));
+ if (ci != NULL) {
+ ERR_set_mark();
+ ossl_cms_resolve_libctx(ci);
+ ERR_pop_to_mark();
+ }
+ return ci;
}
CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont)
{
- return (CMS_ContentInfo *)SMIME_read_ASN1(bio, bcont,
- ASN1_ITEM_rptr
- (CMS_ContentInfo));
+ return SMIME_read_CMS_ex(bio, 0, bcont, NULL);
}
diff --git a/crypto/cms/cms_kari.c b/crypto/cms/cms_kari.c
index cafc3040ac70..a2f422a78d8b 100644
--- a/crypto/cms/cms_kari.c
+++ b/crypto/cms/cms_kari.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2013-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * Low level key APIs (DH etc) are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/pem.h>
@@ -24,8 +30,7 @@ int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri,
ASN1_OCTET_STRING **pukm)
{
if (ri->type != CMS_RECIPINFO_AGREE) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG,
- CMS_R_NOT_KEY_AGREEMENT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT);
return 0;
}
if (palg)
@@ -41,8 +46,7 @@ STACK_OF(CMS_RecipientEncryptedKey)
*CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri)
{
if (ri->type != CMS_RECIPINFO_AGREE) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS,
- CMS_R_NOT_KEY_AGREEMENT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT);
return NULL;
}
return ri->d.kari->recipientEncryptedKeys;
@@ -56,9 +60,9 @@ int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri,
ASN1_INTEGER **sno)
{
CMS_OriginatorIdentifierOrKey *oik;
+
if (ri->type != CMS_RECIPINFO_AGREE) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID,
- CMS_R_NOT_KEY_AGREEMENT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT);
return 0;
}
oik = ri->d.kari->originator;
@@ -93,16 +97,16 @@ int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri,
int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert)
{
CMS_OriginatorIdentifierOrKey *oik;
+
if (ri->type != CMS_RECIPINFO_AGREE) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP,
- CMS_R_NOT_KEY_AGREEMENT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT);
return -2;
}
oik = ri->d.kari->originator;
if (oik->type == CMS_OIK_ISSUER_SERIAL)
- return cms_ias_cert_cmp(oik->d.issuerAndSerialNumber, cert);
+ return ossl_cms_ias_cert_cmp(oik->d.issuerAndSerialNumber, cert);
else if (oik->type == CMS_OIK_KEYIDENTIFIER)
- return cms_keyid_cert_cmp(oik->d.subjectKeyIdentifier, cert);
+ return ossl_cms_keyid_cert_cmp(oik->d.subjectKeyIdentifier, cert);
return -1;
}
@@ -113,6 +117,7 @@ int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek,
X509_NAME **issuer, ASN1_INTEGER **sno)
{
CMS_KeyAgreeRecipientIdentifier *rid = rek->rid;
+
if (rid->type == CMS_REK_ISSUER_SERIAL) {
if (issuer)
*issuer = rid->d.issuerAndSerialNumber->issuer;
@@ -144,26 +149,40 @@ int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek,
X509 *cert)
{
CMS_KeyAgreeRecipientIdentifier *rid = rek->rid;
+
if (rid->type == CMS_REK_ISSUER_SERIAL)
- return cms_ias_cert_cmp(rid->d.issuerAndSerialNumber, cert);
+ return ossl_cms_ias_cert_cmp(rid->d.issuerAndSerialNumber, cert);
else if (rid->type == CMS_REK_KEYIDENTIFIER)
- return cms_keyid_cert_cmp(rid->d.rKeyId->subjectKeyIdentifier, cert);
+ return ossl_cms_keyid_cert_cmp(rid->d.rKeyId->subjectKeyIdentifier,
+ cert);
else
return -1;
}
-int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk)
+int CMS_RecipientInfo_kari_set0_pkey_and_peer(CMS_RecipientInfo *ri,
+ EVP_PKEY *pk, X509 *peer)
{
EVP_PKEY_CTX *pctx;
CMS_KeyAgreeRecipientInfo *kari = ri->d.kari;
EVP_PKEY_CTX_free(kari->pctx);
kari->pctx = NULL;
- if (!pk)
+ if (pk == NULL)
return 1;
- pctx = EVP_PKEY_CTX_new(pk, NULL);
- if (!pctx || EVP_PKEY_derive_init(pctx) <= 0)
+
+ pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(kari->cms_ctx),
+ pk,
+ ossl_cms_ctx_get0_propq(kari->cms_ctx));
+ if (pctx == NULL || EVP_PKEY_derive_init(pctx) <= 0)
goto err;
+
+ if (peer != NULL) {
+ EVP_PKEY *pub_pkey = X509_get0_pubkey(peer);
+
+ if (EVP_PKEY_derive_set_peer(pctx, pub_pkey) <= 0)
+ goto err;
+ }
+
kari->pctx = pctx;
return 1;
err:
@@ -171,6 +190,11 @@ int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk)
return 0;
}
+int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk)
+{
+ return CMS_RecipientInfo_kari_set0_pkey_and_peer(ri, pk, NULL);
+}
+
EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri)
{
if (ri->type == CMS_RECIPINFO_AGREE)
@@ -193,7 +217,8 @@ static int cms_kek_cipher(unsigned char **pout, size_t *poutlen,
int rv = 0;
unsigned char *out = NULL;
int outlen;
- keklen = EVP_CIPHER_CTX_key_length(kari->ctx);
+
+ keklen = EVP_CIPHER_CTX_get_key_length(kari->ctx);
if (keklen > EVP_MAX_KEY_LENGTH)
return 0;
/* Derive KEK */
@@ -234,15 +259,16 @@ int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms,
size_t enckeylen;
size_t ceklen;
CMS_EncryptedContentInfo *ec;
+
enckeylen = rek->encryptedKey->length;
enckey = rek->encryptedKey->data;
/* Setup all parameters to derive KEK */
- if (!cms_env_asn1_ctrl(ri, 1))
+ if (!ossl_cms_env_asn1_ctrl(ri, 1))
goto err;
/* Attempt to decrypt CEK */
if (!cms_kek_cipher(&cek, &ceklen, enckey, enckeylen, ri->d.kari, 0))
goto err;
- ec = cms->d.envelopedData->encryptedContentInfo;
+ ec = ossl_cms_get0_env_enc_content(cms);
OPENSSL_clear_free(ec->key, ec->keylen);
ec->key = cek;
ec->keylen = ceklen;
@@ -260,16 +286,20 @@ static int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari,
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *ekey = NULL;
int rv = 0;
- pctx = EVP_PKEY_CTX_new(pk, NULL);
- if (!pctx)
+ const CMS_CTX *ctx = kari->cms_ctx;
+ OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(ctx);
+ const char *propq = ossl_cms_ctx_get0_propq(ctx);
+
+ pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pk, propq);
+ if (pctx == NULL)
goto err;
if (EVP_PKEY_keygen_init(pctx) <= 0)
goto err;
if (EVP_PKEY_keygen(pctx, &ekey) <= 0)
goto err;
EVP_PKEY_CTX_free(pctx);
- pctx = EVP_PKEY_CTX_new(ekey, NULL);
- if (!pctx)
+ pctx = EVP_PKEY_CTX_new_from_pkey(libctx, ekey, propq);
+ if (pctx == NULL)
goto err;
if (EVP_PKEY_derive_init(pctx) <= 0)
goto err;
@@ -282,21 +312,48 @@ static int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari,
return rv;
}
+/* Set originator private key and initialise context based on it */
+static int cms_kari_set_originator_private_key(CMS_KeyAgreeRecipientInfo *kari,
+ EVP_PKEY *originatorPrivKey )
+{
+ EVP_PKEY_CTX *pctx = NULL;
+ int rv = 0;
+ const CMS_CTX *ctx = kari->cms_ctx;
+
+ pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx),
+ originatorPrivKey,
+ ossl_cms_ctx_get0_propq(ctx));
+ if (pctx == NULL)
+ goto err;
+ if (EVP_PKEY_derive_init(pctx) <= 0)
+ goto err;
+
+ kari->pctx = pctx;
+ rv = 1;
+ err:
+ if (rv == 0)
+ EVP_PKEY_CTX_free(pctx);
+ return rv;
+}
+
/* Initialise a kari based on passed certificate and key */
-int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
- EVP_PKEY *pk, unsigned int flags)
+int ossl_cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
+ EVP_PKEY *recipPubKey, X509 *originator,
+ EVP_PKEY *originatorPrivKey,
+ unsigned int flags, const CMS_CTX *ctx)
{
CMS_KeyAgreeRecipientInfo *kari;
CMS_RecipientEncryptedKey *rek = NULL;
ri->d.kari = M_ASN1_new_of(CMS_KeyAgreeRecipientInfo);
- if (!ri->d.kari)
+ if (ri->d.kari == NULL)
return 0;
ri->type = CMS_RECIPINFO_AGREE;
kari = ri->d.kari;
kari->version = 3;
+ kari->cms_ctx = ctx;
rek = M_ASN1_new_of(CMS_RecipientEncryptedKey);
if (rek == NULL)
@@ -312,59 +369,112 @@ int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
rek->rid->d.rKeyId = M_ASN1_new_of(CMS_RecipientKeyIdentifier);
if (rek->rid->d.rKeyId == NULL)
return 0;
- if (!cms_set1_keyid(&rek->rid->d.rKeyId->subjectKeyIdentifier, recip))
+ if (!ossl_cms_set1_keyid(&rek->rid->d.rKeyId->subjectKeyIdentifier, recip))
return 0;
} else {
rek->rid->type = CMS_REK_ISSUER_SERIAL;
- if (!cms_set1_ias(&rek->rid->d.issuerAndSerialNumber, recip))
+ if (!ossl_cms_set1_ias(&rek->rid->d.issuerAndSerialNumber, recip))
return 0;
}
- /* Create ephemeral key */
- if (!cms_kari_create_ephemeral_key(kari, pk))
- return 0;
+ if (originatorPrivKey == NULL && originator == NULL) {
+ /* Create ephemeral key */
+ if (!cms_kari_create_ephemeral_key(kari, recipPubKey))
+ return 0;
+ } else {
+ /* Use originator key */
+ CMS_OriginatorIdentifierOrKey *oik = ri->d.kari->originator;
- EVP_PKEY_up_ref(pk);
- rek->pkey = pk;
+ if (originatorPrivKey == NULL || originator == NULL)
+ return 0;
+
+ if (flags & CMS_USE_ORIGINATOR_KEYID) {
+ oik->type = CMS_OIK_KEYIDENTIFIER;
+ oik->d.subjectKeyIdentifier = ASN1_OCTET_STRING_new();
+ if (oik->d.subjectKeyIdentifier == NULL)
+ return 0;
+ if (!ossl_cms_set1_keyid(&oik->d.subjectKeyIdentifier, originator))
+ return 0;
+ } else {
+ oik->type = CMS_REK_ISSUER_SERIAL;
+ if (!ossl_cms_set1_ias(&oik->d.issuerAndSerialNumber, originator))
+ return 0;
+ }
+
+ if (!cms_kari_set_originator_private_key(kari, originatorPrivKey))
+ return 0;
+ }
+
+ EVP_PKEY_up_ref(recipPubKey);
+ rek->pkey = recipPubKey;
return 1;
}
static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari,
const EVP_CIPHER *cipher)
{
+ const CMS_CTX *cms_ctx = kari->cms_ctx;
EVP_CIPHER_CTX *ctx = kari->ctx;
const EVP_CIPHER *kekcipher;
- int keylen = EVP_CIPHER_key_length(cipher);
- /* If a suitable wrap algorithm is already set nothing to do */
- kekcipher = EVP_CIPHER_CTX_cipher(ctx);
+ EVP_CIPHER *fetched_kekcipher;
+ const char *kekcipher_name;
+ int keylen;
+ int ret;
- if (kekcipher) {
- if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_WRAP_MODE)
+ /* If a suitable wrap algorithm is already set nothing to do */
+ kekcipher = EVP_CIPHER_CTX_get0_cipher(ctx);
+ if (kekcipher != NULL) {
+ if (EVP_CIPHER_CTX_get_mode(ctx) != EVP_CIPH_WRAP_MODE)
return 0;
return 1;
}
+ if (cipher == NULL)
+ return 0;
+ keylen = EVP_CIPHER_get_key_length(cipher);
+ if ((EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_GET_WRAP_CIPHER) != 0) {
+ ret = EVP_CIPHER_meth_get_ctrl(cipher)(NULL, EVP_CTRL_GET_WRAP_CIPHER,
+ 0, &kekcipher);
+ if (ret <= 0)
+ return 0;
+
+ if (kekcipher != NULL) {
+ if (EVP_CIPHER_get_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
+ return 0;
+ kekcipher_name = EVP_CIPHER_get0_name(kekcipher);
+ goto enc;
+ }
+ }
+
/*
* Pick a cipher based on content encryption cipher. If it is DES3 use
* DES3 wrap otherwise use AES wrap similar to key size.
*/
#ifndef OPENSSL_NO_DES
- if (EVP_CIPHER_type(cipher) == NID_des_ede3_cbc)
- kekcipher = EVP_des_ede3_wrap();
+ if (EVP_CIPHER_get_type(cipher) == NID_des_ede3_cbc)
+ kekcipher_name = SN_id_smime_alg_CMS3DESwrap;
else
#endif
if (keylen <= 16)
- kekcipher = EVP_aes_128_wrap();
+ kekcipher_name = SN_id_aes128_wrap;
else if (keylen <= 24)
- kekcipher = EVP_aes_192_wrap();
+ kekcipher_name = SN_id_aes192_wrap;
else
- kekcipher = EVP_aes_256_wrap();
- return EVP_EncryptInit_ex(ctx, kekcipher, NULL, NULL, NULL);
+ kekcipher_name = SN_id_aes256_wrap;
+enc:
+ fetched_kekcipher = EVP_CIPHER_fetch(ossl_cms_ctx_get0_libctx(cms_ctx),
+ kekcipher_name,
+ ossl_cms_ctx_get0_propq(cms_ctx));
+ if (fetched_kekcipher == NULL)
+ return 0;
+ ret = EVP_EncryptInit_ex(ctx, fetched_kekcipher, NULL, NULL, NULL);
+ EVP_CIPHER_free(fetched_kekcipher);
+ return ret;
}
/* Encrypt content key in key agreement recipient info */
-int cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms,
- CMS_RecipientInfo *ri)
+int ossl_cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms,
+ CMS_RecipientInfo *ri)
{
CMS_KeyAgreeRecipientInfo *kari;
CMS_EncryptedContentInfo *ec;
@@ -373,12 +483,12 @@ int cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms,
int i;
if (ri->type != CMS_RECIPINFO_AGREE) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT, CMS_R_NOT_KEY_AGREEMENT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT);
return 0;
}
kari = ri->d.kari;
reks = kari->recipientEncryptedKeys;
- ec = cms->d.envelopedData->encryptedContentInfo;
+ ec = ossl_cms_get0_env_enc_content(cms);
/* Initialise wrap algorithm parameters */
if (!cms_wrap_init(kari, ec->cipher))
return 0;
@@ -394,7 +504,7 @@ int cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms,
return 0;
}
/* Initialise KDF algorithm */
- if (!cms_env_asn1_ctrl(ri, 0))
+ if (!ossl_cms_env_asn1_ctrl(ri, 0))
return 0;
/* For each rek, derive KEK, encrypt CEK */
for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
@@ -410,5 +520,4 @@ int cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms,
}
return 1;
-
}
diff --git a/crypto/cms/cms_lib.c b/crypto/cms/cms_lib.c
index be4c2c703f1a..1fd542d2375c 100644
--- a/crypto/cms/cms_lib.c
+++ b/crypto/cms/cms_lib.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -14,20 +14,119 @@
#include <openssl/bio.h>
#include <openssl/asn1.h>
#include <openssl/cms.h>
+#include <openssl/cms.h>
+#include "internal/sizes.h"
+#include "crypto/x509.h"
#include "cms_local.h"
-IMPLEMENT_ASN1_FUNCTIONS(CMS_ContentInfo)
+static STACK_OF(CMS_CertificateChoices)
+**cms_get0_certificate_choices(CMS_ContentInfo *cms);
+
IMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
+CMS_ContentInfo *d2i_CMS_ContentInfo(CMS_ContentInfo **a,
+ const unsigned char **in, long len)
+{
+ CMS_ContentInfo *ci;
+ const CMS_CTX *ctx = ossl_cms_get0_cmsctx(a == NULL ? NULL : *a);
+
+ ci = (CMS_ContentInfo *)ASN1_item_d2i_ex((ASN1_VALUE **)a, in, len,
+ (CMS_ContentInfo_it()),
+ ossl_cms_ctx_get0_libctx(ctx),
+ ossl_cms_ctx_get0_propq(ctx));
+ if (ci != NULL) {
+ ERR_set_mark();
+ ossl_cms_resolve_libctx(ci);
+ ERR_pop_to_mark();
+ }
+ return ci;
+}
+
+int i2d_CMS_ContentInfo(const CMS_ContentInfo *a, unsigned char **out)
+{
+ return ASN1_item_i2d((const ASN1_VALUE *)a, out, (CMS_ContentInfo_it()));
+}
+
+CMS_ContentInfo *CMS_ContentInfo_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
+{
+ CMS_ContentInfo *ci;
+
+ ci = (CMS_ContentInfo *)ASN1_item_new_ex(ASN1_ITEM_rptr(CMS_ContentInfo),
+ libctx, propq);
+ if (ci != NULL) {
+ ci->ctx.libctx = libctx;
+ ci->ctx.propq = NULL;
+ if (propq != NULL) {
+ ci->ctx.propq = OPENSSL_strdup(propq);
+ if (ci->ctx.propq == NULL) {
+ CMS_ContentInfo_free(ci);
+ ci = NULL;
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ }
+ }
+ }
+ return ci;
+}
+
+CMS_ContentInfo *CMS_ContentInfo_new(void)
+{
+ return CMS_ContentInfo_new_ex(NULL, NULL);
+}
+
+void CMS_ContentInfo_free(CMS_ContentInfo *cms)
+{
+ if (cms != NULL) {
+ OPENSSL_free(cms->ctx.propq);
+ ASN1_item_free((ASN1_VALUE *)cms, ASN1_ITEM_rptr(CMS_ContentInfo));
+ }
+}
+
+const CMS_CTX *ossl_cms_get0_cmsctx(const CMS_ContentInfo *cms)
+{
+ return cms != NULL ? &cms->ctx : NULL;
+}
+
+OSSL_LIB_CTX *ossl_cms_ctx_get0_libctx(const CMS_CTX *ctx)
+{
+ return ctx != NULL ? ctx->libctx : NULL;
+}
+
+const char *ossl_cms_ctx_get0_propq(const CMS_CTX *ctx)
+{
+ return ctx != NULL ? ctx->propq : NULL;
+}
+
+void ossl_cms_resolve_libctx(CMS_ContentInfo *ci)
+{
+ int i;
+ CMS_CertificateChoices *cch;
+ STACK_OF(CMS_CertificateChoices) **pcerts;
+ const CMS_CTX *ctx = ossl_cms_get0_cmsctx(ci);
+ OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(ctx);
+ const char *propq = ossl_cms_ctx_get0_propq(ctx);
+
+ ossl_cms_SignerInfos_set_cmsctx(ci);
+ ossl_cms_RecipientInfos_set_cmsctx(ci);
+
+ pcerts = cms_get0_certificate_choices(ci);
+ if (pcerts != NULL) {
+ for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
+ cch = sk_CMS_CertificateChoices_value(*pcerts, i);
+ if (cch->type == CMS_CERTCHOICE_CERT)
+ ossl_x509_set0_libctx(cch->d.certificate, libctx, propq);
+ }
+ }
+}
+
const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms)
{
return cms->contentType;
}
-CMS_ContentInfo *cms_Data_create(void)
+CMS_ContentInfo *ossl_cms_Data_create(OSSL_LIB_CTX *libctx, const char *propq)
{
- CMS_ContentInfo *cms;
- cms = CMS_ContentInfo_new();
+ CMS_ContentInfo *cms = CMS_ContentInfo_new_ex(libctx, propq);
+
if (cms != NULL) {
cms->contentType = OBJ_nid2obj(NID_pkcs7_data);
/* Never detached */
@@ -36,18 +135,19 @@ CMS_ContentInfo *cms_Data_create(void)
return cms;
}
-BIO *cms_content_bio(CMS_ContentInfo *cms)
+BIO *ossl_cms_content_bio(CMS_ContentInfo *cms)
{
ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
- if (!pos)
+
+ if (pos == NULL)
return NULL;
/* If content detached data goes nowhere: create NULL BIO */
- if (!*pos)
+ if (*pos == NULL)
return BIO_new(BIO_s_null());
/*
* If content not detached and created return memory BIO
*/
- if (!*pos || ((*pos)->flags == ASN1_STRING_FLAG_CONT))
+ if (*pos == NULL || ((*pos)->flags == ASN1_STRING_FLAG_CONT))
return BIO_new(BIO_s_mem());
/* Else content was read in: return read only BIO for it */
return BIO_new_mem_buf((*pos)->data, (*pos)->length);
@@ -59,9 +159,9 @@ BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont)
if (icont)
cont = icont;
else
- cont = cms_content_bio(cms);
+ cont = ossl_cms_content_bio(cms);
if (!cont) {
- CMSerr(CMS_F_CMS_DATAINIT, CMS_R_NO_CONTENT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_CONTENT);
return NULL;
}
switch (OBJ_obj2nid(cms->contentType)) {
@@ -70,34 +170,37 @@ BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont)
return cont;
case NID_pkcs7_signed:
- cmsbio = cms_SignedData_init_bio(cms);
+ cmsbio = ossl_cms_SignedData_init_bio(cms);
break;
case NID_pkcs7_digest:
- cmsbio = cms_DigestedData_init_bio(cms);
+ cmsbio = ossl_cms_DigestedData_init_bio(cms);
break;
#ifdef ZLIB
case NID_id_smime_ct_compressedData:
- cmsbio = cms_CompressedData_init_bio(cms);
+ cmsbio = ossl_cms_CompressedData_init_bio(cms);
break;
#endif
case NID_pkcs7_encrypted:
- cmsbio = cms_EncryptedData_init_bio(cms);
+ cmsbio = ossl_cms_EncryptedData_init_bio(cms);
break;
case NID_pkcs7_enveloped:
- cmsbio = cms_EnvelopedData_init_bio(cms);
+ cmsbio = ossl_cms_EnvelopedData_init_bio(cms);
+ break;
+
+ case NID_id_smime_ct_authEnvelopedData:
+ cmsbio = ossl_cms_AuthEnvelopedData_init_bio(cms);
break;
default:
- CMSerr(CMS_F_CMS_DATAINIT, CMS_R_UNSUPPORTED_TYPE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_TYPE);
goto err;
}
if (cmsbio)
return BIO_push(cmsbio, cont);
-
err:
if (!icont)
BIO_free(cont);
@@ -105,10 +208,12 @@ err:
}
+/* unfortunately cannot constify SMIME_write_ASN1() due to this function */
int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
{
ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
- if (!pos)
+
+ if (pos == NULL)
return 0;
/* If embedded content find memory BIO and set content */
if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) {
@@ -117,7 +222,7 @@ int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
long contlen;
mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM);
if (!mbio) {
- CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_CONTENT_NOT_FOUND);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_NOT_FOUND);
return 0;
}
contlen = BIO_get_mem_data(mbio, &cont);
@@ -131,20 +236,25 @@ int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
switch (OBJ_obj2nid(cms->contentType)) {
case NID_pkcs7_data:
- case NID_pkcs7_enveloped:
case NID_pkcs7_encrypted:
case NID_id_smime_ct_compressedData:
/* Nothing to do */
return 1;
+ case NID_pkcs7_enveloped:
+ return ossl_cms_EnvelopedData_final(cms, cmsbio);
+
+ case NID_id_smime_ct_authEnvelopedData:
+ return ossl_cms_AuthEnvelopedData_final(cms, cmsbio);
+
case NID_pkcs7_signed:
- return cms_SignedData_final(cms, cmsbio);
+ return ossl_cms_SignedData_final(cms, cmsbio);
case NID_pkcs7_digest:
- return cms_DigestedData_do_final(cms, cmsbio, 0);
+ return ossl_cms_DigestedData_do_final(cms, cmsbio, 0);
default:
- CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_UNSUPPORTED_TYPE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_TYPE);
return 0;
}
}
@@ -173,6 +283,10 @@ ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms)
case NID_pkcs7_encrypted:
return &cms->d.encryptedData->encryptedContentInfo->encryptedContent;
+ case NID_id_smime_ct_authEnvelopedData:
+ return &cms->d.authEnvelopedData->authEncryptedContentInfo
+ ->encryptedContent;
+
case NID_id_smime_ct_authData:
return &cms->d.authenticatedData->encapContentInfo->eContent;
@@ -182,7 +296,7 @@ ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms)
default:
if (cms->d.other->type == V_ASN1_OCTET_STRING)
return &cms->d.other->value.octet_string;
- CMSerr(CMS_F_CMS_GET0_CONTENT, CMS_R_UNSUPPORTED_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE);
return NULL;
}
@@ -209,6 +323,9 @@ static ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms)
case NID_pkcs7_encrypted:
return &cms->d.encryptedData->encryptedContentInfo->contentType;
+ case NID_id_smime_ct_authEnvelopedData:
+ return &cms->d.authEnvelopedData->authEncryptedContentInfo
+ ->contentType;
case NID_id_smime_ct_authData:
return &cms->d.authenticatedData->encapContentInfo->eContentType;
@@ -216,7 +333,7 @@ static ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms)
return &cms->d.compressedData->encapContentInfo->eContentType;
default:
- CMSerr(CMS_F_CMS_GET0_ECONTENT_TYPE, CMS_R_UNSUPPORTED_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE);
return NULL;
}
@@ -234,13 +351,14 @@ const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms)
int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid)
{
ASN1_OBJECT **petype, *etype;
+
petype = cms_get0_econtent_type(cms);
- if (!petype)
+ if (petype == NULL)
return 0;
- if (!oid)
+ if (oid == NULL)
return 1;
etype = OBJ_dup(oid);
- if (!etype)
+ if (etype == NULL)
return 0;
ASN1_OBJECT_free(*petype);
*petype = etype;
@@ -250,10 +368,11 @@ int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid)
int CMS_is_detached(CMS_ContentInfo *cms)
{
ASN1_OCTET_STRING **pos;
+
pos = CMS_get0_content(cms);
- if (!pos)
+ if (pos == NULL)
return -1;
- if (*pos)
+ if (*pos != NULL)
return 0;
return 1;
}
@@ -261,8 +380,9 @@ int CMS_is_detached(CMS_ContentInfo *cms)
int CMS_set_detached(CMS_ContentInfo *cms, int detached)
{
ASN1_OCTET_STRING **pos;
+
pos = CMS_get0_content(cms);
- if (!pos)
+ if (pos == NULL)
return 0;
if (detached) {
ASN1_OCTET_STRING_free(*pos);
@@ -278,39 +398,56 @@ int CMS_set_detached(CMS_ContentInfo *cms, int detached)
(*pos)->flags |= ASN1_STRING_FLAG_CONT;
return 1;
}
- CMSerr(CMS_F_CMS_SET_DETACHED, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return 0;
}
/* Create a digest BIO from an X509_ALGOR structure */
-BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm)
+BIO *ossl_cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm,
+ const CMS_CTX *ctx)
{
BIO *mdbio = NULL;
const ASN1_OBJECT *digestoid;
- const EVP_MD *digest;
+ const EVP_MD *digest = NULL;
+ EVP_MD *fetched_digest = NULL;
+ char alg[OSSL_MAX_NAME_SIZE];
+
X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm);
- digest = EVP_get_digestbyobj(digestoid);
- if (!digest) {
- CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO,
- CMS_R_UNKNOWN_DIGEST_ALGORITHM);
+ OBJ_obj2txt(alg, sizeof(alg), digestoid, 0);
+
+ (void)ERR_set_mark();
+ fetched_digest = EVP_MD_fetch(ossl_cms_ctx_get0_libctx(ctx), alg,
+ ossl_cms_ctx_get0_propq(ctx));
+
+ if (fetched_digest != NULL)
+ digest = fetched_digest;
+ else
+ digest = EVP_get_digestbyobj(digestoid);
+ if (digest == NULL) {
+ (void)ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_DIGEST_ALGORITHM);
goto err;
}
+ (void)ERR_pop_to_mark();
+
mdbio = BIO_new(BIO_f_md());
if (mdbio == NULL || !BIO_set_md(mdbio, digest)) {
- CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, CMS_R_MD_BIO_INIT_ERROR);
+ ERR_raise(ERR_LIB_CMS, CMS_R_MD_BIO_INIT_ERROR);
goto err;
}
+ EVP_MD_free(fetched_digest);
return mdbio;
err:
+ EVP_MD_free(fetched_digest);
BIO_free(mdbio);
return NULL;
}
/* Locate a message digest content from a BIO chain based on SignerInfo */
-int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
- X509_ALGOR *mdalg)
+int ossl_cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
+ X509_ALGOR *mdalg)
{
int nid;
const ASN1_OBJECT *mdoid;
@@ -321,17 +458,16 @@ int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
EVP_MD_CTX *mtmp;
chain = BIO_find_type(chain, BIO_TYPE_MD);
if (chain == NULL) {
- CMSerr(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX,
- CMS_R_NO_MATCHING_DIGEST);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_DIGEST);
return 0;
}
BIO_get_md_ctx(chain, &mtmp);
- if (EVP_MD_CTX_type(mtmp) == nid
+ if (EVP_MD_CTX_get_type(mtmp) == nid
/*
* Workaround for broken implementations that use signature
* algorithm OID instead of digest.
*/
- || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid)
+ || EVP_MD_get_pkey_type(EVP_MD_CTX_get0_md(mtmp)) == nid)
return EVP_MD_CTX_copy_ex(mctx, mtmp);
chain = BIO_next(chain);
}
@@ -350,9 +486,13 @@ static STACK_OF(CMS_CertificateChoices)
return NULL;
return &cms->d.envelopedData->originatorInfo->certificates;
+ case NID_id_smime_ct_authEnvelopedData:
+ if (cms->d.authEnvelopedData->originatorInfo == NULL)
+ return NULL;
+ return &cms->d.authEnvelopedData->originatorInfo->certificates;
+
default:
- CMSerr(CMS_F_CMS_GET0_CERTIFICATE_CHOICES,
- CMS_R_UNSUPPORTED_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE);
return NULL;
}
@@ -362,12 +502,13 @@ CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms)
{
STACK_OF(CMS_CertificateChoices) **pcerts;
CMS_CertificateChoices *cch;
+
pcerts = cms_get0_certificate_choices(cms);
- if (!pcerts)
+ if (pcerts == NULL)
return NULL;
- if (!*pcerts)
+ if (*pcerts == NULL)
*pcerts = sk_CMS_CertificateChoices_new_null();
- if (!*pcerts)
+ if (*pcerts == NULL)
return NULL;
cch = M_ASN1_new_of(CMS_CertificateChoices);
if (!cch)
@@ -384,15 +525,15 @@ int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert)
CMS_CertificateChoices *cch;
STACK_OF(CMS_CertificateChoices) **pcerts;
int i;
+
pcerts = cms_get0_certificate_choices(cms);
- if (!pcerts)
+ if (pcerts == NULL)
return 0;
for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
cch = sk_CMS_CertificateChoices_value(*pcerts, i);
if (cch->type == CMS_CERTCHOICE_CERT) {
if (!X509_cmp(cch->d.certificate, cert)) {
- CMSerr(CMS_F_CMS_ADD0_CERT,
- CMS_R_CERTIFICATE_ALREADY_PRESENT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CERTIFICATE_ALREADY_PRESENT);
return 0;
}
}
@@ -427,9 +568,13 @@ static STACK_OF(CMS_RevocationInfoChoice)
return NULL;
return &cms->d.envelopedData->originatorInfo->crls;
+ case NID_id_smime_ct_authEnvelopedData:
+ if (cms->d.authEnvelopedData->originatorInfo == NULL)
+ return NULL;
+ return &cms->d.authEnvelopedData->originatorInfo->crls;
+
default:
- CMSerr(CMS_F_CMS_GET0_REVOCATION_CHOICES,
- CMS_R_UNSUPPORTED_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE);
return NULL;
}
@@ -439,15 +584,16 @@ CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms)
{
STACK_OF(CMS_RevocationInfoChoice) **pcrls;
CMS_RevocationInfoChoice *rch;
+
pcrls = cms_get0_revocation_choices(cms);
- if (!pcrls)
+ if (pcrls == NULL)
return NULL;
- if (!*pcrls)
+ if (*pcrls == NULL)
*pcrls = sk_CMS_RevocationInfoChoice_new_null();
- if (!*pcrls)
+ if (*pcrls == NULL)
return NULL;
rch = M_ASN1_new_of(CMS_RevocationInfoChoice);
- if (!rch)
+ if (rch == NULL)
return NULL;
if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) {
M_ASN1_free_of(rch, CMS_RevocationInfoChoice);
@@ -482,22 +628,18 @@ STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms)
CMS_CertificateChoices *cch;
STACK_OF(CMS_CertificateChoices) **pcerts;
int i;
+
pcerts = cms_get0_certificate_choices(cms);
- if (!pcerts)
+ if (pcerts == NULL)
return NULL;
for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
cch = sk_CMS_CertificateChoices_value(*pcerts, i);
if (cch->type == 0) {
- if (!certs) {
- certs = sk_X509_new_null();
- if (!certs)
- return NULL;
- }
- if (!sk_X509_push(certs, cch->d.certificate)) {
+ if (!ossl_x509_add_cert_new(&certs, cch->d.certificate,
+ X509_ADD_FLAG_UP_REF)) {
sk_X509_pop_free(certs, X509_free);
return NULL;
}
- X509_up_ref(cch->d.certificate);
}
}
return certs;
@@ -510,8 +652,9 @@ STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms)
STACK_OF(CMS_RevocationInfoChoice) **pcrls;
CMS_RevocationInfoChoice *rch;
int i;
+
pcrls = cms_get0_revocation_choices(cms);
- if (!pcrls)
+ if (pcrls == NULL)
return NULL;
for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) {
rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i);
@@ -531,16 +674,16 @@ STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms)
return crls;
}
-int cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert)
+int ossl_cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert)
{
int ret;
ret = X509_NAME_cmp(ias->issuer, X509_get_issuer_name(cert));
if (ret)
return ret;
- return ASN1_INTEGER_cmp(ias->serialNumber, X509_get_serialNumber(cert));
+ return ASN1_INTEGER_cmp(ias->serialNumber, X509_get0_serialNumber(cert));
}
-int cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert)
+int ossl_cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert)
{
const ASN1_OCTET_STRING *cert_keyid = X509_get0_subject_key_id(cert);
@@ -549,7 +692,7 @@ int cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert)
return ASN1_OCTET_STRING_cmp(keyid, cert_keyid);
}
-int cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert)
+int ossl_cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert)
{
CMS_IssuerAndSerialNumber *ias;
ias = M_ASN1_new_of(CMS_IssuerAndSerialNumber);
@@ -557,29 +700,29 @@ int cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert)
goto err;
if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert)))
goto err;
- if (!ASN1_STRING_copy(ias->serialNumber, X509_get_serialNumber(cert)))
+ if (!ASN1_STRING_copy(ias->serialNumber, X509_get0_serialNumber(cert)))
goto err;
M_ASN1_free_of(*pias, CMS_IssuerAndSerialNumber);
*pias = ias;
return 1;
err:
M_ASN1_free_of(ias, CMS_IssuerAndSerialNumber);
- CMSerr(CMS_F_CMS_SET1_IAS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return 0;
}
-int cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert)
+int ossl_cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert)
{
ASN1_OCTET_STRING *keyid = NULL;
const ASN1_OCTET_STRING *cert_keyid;
cert_keyid = X509_get0_subject_key_id(cert);
if (cert_keyid == NULL) {
- CMSerr(CMS_F_CMS_SET1_KEYID, CMS_R_CERTIFICATE_HAS_NO_KEYID);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CERTIFICATE_HAS_NO_KEYID);
return 0;
}
keyid = ASN1_STRING_dup(cert_keyid);
if (!keyid) {
- CMSerr(CMS_F_CMS_SET1_KEYID, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return 0;
}
ASN1_OCTET_STRING_free(*pkeyid);
diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h
index a0ce4448f603..15b4a29ce03d 100644
--- a/crypto/cms/cms_local.h
+++ b/crypto/cms/cms_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2008-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -29,6 +29,7 @@ typedef struct CMS_EnvelopedData_st CMS_EnvelopedData;
typedef struct CMS_DigestedData_st CMS_DigestedData;
typedef struct CMS_EncryptedData_st CMS_EncryptedData;
typedef struct CMS_AuthenticatedData_st CMS_AuthenticatedData;
+typedef struct CMS_AuthEnvelopedData_st CMS_AuthEnvelopedData;
typedef struct CMS_CompressedData_st CMS_CompressedData;
typedef struct CMS_OtherCertificateFormat_st CMS_OtherCertificateFormat;
typedef struct CMS_KeyTransRecipientInfo_st CMS_KeyTransRecipientInfo;
@@ -43,6 +44,12 @@ typedef struct CMS_KEKRecipientInfo_st CMS_KEKRecipientInfo;
typedef struct CMS_PasswordRecipientInfo_st CMS_PasswordRecipientInfo;
typedef struct CMS_OtherRecipientInfo_st CMS_OtherRecipientInfo;
typedef struct CMS_ReceiptsFrom_st CMS_ReceiptsFrom;
+typedef struct CMS_CTX_st CMS_CTX;
+
+struct CMS_CTX_st {
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+};
struct CMS_ContentInfo_st {
ASN1_OBJECT *contentType;
@@ -52,12 +59,14 @@ struct CMS_ContentInfo_st {
CMS_EnvelopedData *envelopedData;
CMS_DigestedData *digestedData;
CMS_EncryptedData *encryptedData;
+ CMS_AuthEnvelopedData *authEnvelopedData;
CMS_AuthenticatedData *authenticatedData;
CMS_CompressedData *compressedData;
ASN1_TYPE *other;
/* Other types ... */
void *otherData;
} d;
+ CMS_CTX ctx;
};
DEFINE_STACK_OF(CMS_CertificateChoices)
@@ -92,6 +101,7 @@ struct CMS_SignerInfo_st {
/* Digest and public key context for alternative parameters */
EVP_MD_CTX *mctx;
EVP_PKEY_CTX *pctx;
+ const CMS_CTX *cms_ctx;
};
struct CMS_SignerIdentifier_st {
@@ -119,10 +129,12 @@ struct CMS_EncryptedContentInfo_st {
ASN1_OBJECT *contentType;
X509_ALGOR *contentEncryptionAlgorithm;
ASN1_OCTET_STRING *encryptedContent;
- /* Content encryption algorithm and key */
+ /* Content encryption algorithm, key and tag */
const EVP_CIPHER *cipher;
unsigned char *key;
size_t keylen;
+ unsigned char *tag;
+ size_t taglen;
/* Set to 1 if we are debugging decrypt and don't fake keys for MMA */
int debug;
/* Set to 1 if we have no cert and need extra safety measures for MMA */
@@ -152,6 +164,7 @@ struct CMS_KeyTransRecipientInfo_st {
EVP_PKEY *pkey;
/* Public key context for this operation */
EVP_PKEY_CTX *pctx;
+ const CMS_CTX *cms_ctx;
};
struct CMS_KeyAgreeRecipientInfo_st {
@@ -164,6 +177,7 @@ struct CMS_KeyAgreeRecipientInfo_st {
EVP_PKEY_CTX *pctx;
/* Cipher context for CEK wrapping */
EVP_CIPHER_CTX *ctx;
+ const CMS_CTX *cms_ctx;
};
struct CMS_OriginatorIdentifierOrKey_st {
@@ -209,6 +223,7 @@ struct CMS_KEKRecipientInfo_st {
/* Extra info: symmetric key to use */
unsigned char *key;
size_t keylen;
+ const CMS_CTX *cms_ctx;
};
struct CMS_KEKIdentifier_st {
@@ -225,6 +240,7 @@ struct CMS_PasswordRecipientInfo_st {
/* Extra info: password to use */
unsigned char *pass;
size_t passlen;
+ const CMS_CTX *cms_ctx;
};
struct CMS_OtherRecipientInfo_st {
@@ -257,6 +273,16 @@ struct CMS_AuthenticatedData_st {
STACK_OF(X509_ATTRIBUTE) *unauthAttrs;
};
+struct CMS_AuthEnvelopedData_st {
+ int32_t version;
+ CMS_OriginatorInfo *originatorInfo;
+ STACK_OF(CMS_RecipientInfo) *recipientInfos;
+ CMS_EncryptedContentInfo *authEncryptedContentInfo;
+ STACK_OF(X509_ATTRIBUTE) *authAttrs;
+ ASN1_OCTET_STRING *mac;
+ STACK_OF(X509_ATTRIBUTE) *unauthAttrs;
+};
+
struct CMS_CompressedData_st {
int32_t version;
X509_ALGOR *compressionAlgorithm;
@@ -362,66 +388,105 @@ DECLARE_ASN1_ALLOC_FUNCTIONS(CMS_IssuerAndSerialNumber)
# define CMS_OIK_KEYIDENTIFIER 1
# define CMS_OIK_PUBKEY 2
-BIO *cms_content_bio(CMS_ContentInfo *cms);
-
-CMS_ContentInfo *cms_Data_create(void);
-
-CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md);
-BIO *cms_DigestedData_init_bio(CMS_ContentInfo *cms);
-int cms_DigestedData_do_final(CMS_ContentInfo *cms, BIO *chain, int verify);
-
-BIO *cms_SignedData_init_bio(CMS_ContentInfo *cms);
-int cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain);
-int cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert,
- int type);
-int cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid,
- ASN1_OCTET_STRING **keyid,
- X509_NAME **issuer,
- ASN1_INTEGER **sno);
-int cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert);
-
-CMS_ContentInfo *cms_CompressedData_create(int comp_nid);
-BIO *cms_CompressedData_init_bio(CMS_ContentInfo *cms);
-
-BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm);
-int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
- X509_ALGOR *mdalg);
-
-int cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert);
-int cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert);
-int cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert);
-int cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert);
-
-BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec);
-BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms);
-int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
- const EVP_CIPHER *cipher,
- const unsigned char *key, size_t keylen);
-
-int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms);
-int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src);
-ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si);
-
-BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms);
-CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms);
-int cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd);
-int cms_pkey_get_ri_type(EVP_PKEY *pk);
+BIO *ossl_cms_content_bio(CMS_ContentInfo *cms);
+const CMS_CTX *ossl_cms_get0_cmsctx(const CMS_ContentInfo *cms);
+OSSL_LIB_CTX *ossl_cms_ctx_get0_libctx(const CMS_CTX *ctx);
+const char *ossl_cms_ctx_get0_propq(const CMS_CTX *ctx);
+void ossl_cms_resolve_libctx(CMS_ContentInfo *ci);
+
+CMS_ContentInfo *ossl_cms_Data_create(OSSL_LIB_CTX *ctx, const char *propq);
+
+CMS_ContentInfo *ossl_cms_DigestedData_create(const EVP_MD *md,
+ OSSL_LIB_CTX *libctx,
+ const char *propq);
+BIO *ossl_cms_DigestedData_init_bio(const CMS_ContentInfo *cms);
+int ossl_cms_DigestedData_do_final(const CMS_ContentInfo *cms,
+ BIO *chain, int verify);
+
+BIO *ossl_cms_SignedData_init_bio(CMS_ContentInfo *cms);
+int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain);
+int ossl_cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert,
+ int type, const CMS_CTX *ctx);
+int ossl_cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid,
+ ASN1_OCTET_STRING **keyid,
+ X509_NAME **issuer,
+ ASN1_INTEGER **sno);
+int ossl_cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert);
+
+CMS_ContentInfo *ossl_cms_CompressedData_create(int comp_nid,
+ OSSL_LIB_CTX *libctx,
+ const char *propq);
+BIO *ossl_cms_CompressedData_init_bio(const CMS_ContentInfo *cms);
+
+BIO *ossl_cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm,
+ const CMS_CTX *ctx);
+int ossl_cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
+ X509_ALGOR *mdalg);
+
+int ossl_cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert);
+int ossl_cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert);
+int ossl_cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert);
+int ossl_cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert);
+
+BIO *ossl_cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec,
+ const CMS_CTX *ctx);
+BIO *ossl_cms_EncryptedData_init_bio(const CMS_ContentInfo *cms);
+int ossl_cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
+ const EVP_CIPHER *cipher,
+ const unsigned char *key, size_t keylen,
+ const CMS_CTX *ctx);
+
+int ossl_cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms);
+int ossl_cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src);
+ASN1_OCTET_STRING *ossl_cms_encode_Receipt(CMS_SignerInfo *si);
+
+BIO *ossl_cms_EnvelopedData_init_bio(CMS_ContentInfo *cms);
+int ossl_cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain);
+BIO *ossl_cms_AuthEnvelopedData_init_bio(CMS_ContentInfo *cms);
+int ossl_cms_AuthEnvelopedData_final(CMS_ContentInfo *cms, BIO *cmsbio);
+CMS_EnvelopedData *ossl_cms_get0_enveloped(CMS_ContentInfo *cms);
+CMS_AuthEnvelopedData *ossl_cms_get0_auth_enveloped(CMS_ContentInfo *cms);
+CMS_EncryptedContentInfo *ossl_cms_get0_env_enc_content(const CMS_ContentInfo *cms);
+
+/* RecipientInfo routines */
+int ossl_cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd);
+int ossl_cms_pkey_get_ri_type(EVP_PKEY *pk);
+int ossl_cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type);
+
+void ossl_cms_RecipientInfos_set_cmsctx(CMS_ContentInfo *cms);
+
/* KARI routines */
-int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
- EVP_PKEY *pk, unsigned int flags);
-int cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms,
- CMS_RecipientInfo *ri);
+int ossl_cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
+ EVP_PKEY *recipPubKey, X509 *originator,
+ EVP_PKEY *originatorPrivKey,
+ unsigned int flags,
+ const CMS_CTX *ctx);
+int ossl_cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms,
+ CMS_RecipientInfo *ri);
/* PWRI routines */
-int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
- int en_de);
+int ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms,
+ CMS_RecipientInfo *ri, int en_de);
/* SignerInfo routines */
-int CMS_si_check_attributes(const CMS_SignerInfo *si);
+int ossl_cms_si_check_attributes(const CMS_SignerInfo *si);
+void ossl_cms_SignerInfos_set_cmsctx(CMS_ContentInfo *cms);
+
+
+/* ESS routines */
+int ossl_cms_check_signing_certs(const CMS_SignerInfo *si,
+ const STACK_OF(X509) *chain);
+
+int ossl_cms_dh_envelope(CMS_RecipientInfo *ri, int decrypt);
+int ossl_cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt);
+int ossl_cms_rsa_envelope(CMS_RecipientInfo *ri, int decrypt);
+int ossl_cms_ecdsa_dsa_sign(CMS_SignerInfo *si, int verify);
+int ossl_cms_rsa_sign(CMS_SignerInfo *si, int verify);
DECLARE_ASN1_ITEM(CMS_CertificateChoices)
DECLARE_ASN1_ITEM(CMS_DigestedData)
DECLARE_ASN1_ITEM(CMS_EncryptedData)
DECLARE_ASN1_ITEM(CMS_EnvelopedData)
+DECLARE_ASN1_ITEM(CMS_AuthEnvelopedData)
DECLARE_ASN1_ITEM(CMS_KEKRecipientInfo)
DECLARE_ASN1_ITEM(CMS_KeyAgreeRecipientInfo)
DECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo)
diff --git a/crypto/cms/cms_pwri.c b/crypto/cms/cms_pwri.c
index d7414883396c..2373092bed55 100644
--- a/crypto/cms/cms_pwri.c
+++ b/crypto/cms/cms_pwri.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2009-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2009-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -15,15 +15,16 @@
#include <openssl/cms.h>
#include <openssl/rand.h>
#include <openssl/aes.h>
-#include "cms_local.h"
+#include "internal/sizes.h"
#include "crypto/asn1.h"
+#include "cms_local.h"
int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri,
unsigned char *pass, ossl_ssize_t passlen)
{
CMS_PasswordRecipientInfo *pwri;
if (ri->type != CMS_RECIPINFO_PASS) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD, CMS_R_NOT_PWRI);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_PWRI);
return 0;
}
@@ -42,16 +43,21 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
ossl_ssize_t passlen,
const EVP_CIPHER *kekciph)
{
+ STACK_OF(CMS_RecipientInfo) *ris;
CMS_RecipientInfo *ri = NULL;
- CMS_EnvelopedData *env;
+ CMS_EncryptedContentInfo *ec;
CMS_PasswordRecipientInfo *pwri;
EVP_CIPHER_CTX *ctx = NULL;
X509_ALGOR *encalg = NULL;
unsigned char iv[EVP_MAX_IV_LENGTH];
int ivlen;
+ const CMS_CTX *cms_ctx = ossl_cms_get0_cmsctx(cms);
- env = cms_get0_enveloped(cms);
- if (!env)
+ ec = ossl_cms_get0_env_enc_content(cms);
+ if (ec == NULL)
+ return NULL;
+ ris = CMS_get0_RecipientInfos(cms);
+ if (ris == NULL)
return NULL;
if (wrap_nid <= 0)
@@ -62,15 +68,14 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
/* Get from enveloped data */
if (kekciph == NULL)
- kekciph = env->encryptedContentInfo->cipher;
+ kekciph = ec->cipher;
if (kekciph == NULL) {
- CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_NO_CIPHER);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_CIPHER);
return NULL;
}
if (wrap_nid != NID_id_alg_PWRI_KEK) {
- CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
- CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
return NULL;
}
@@ -80,34 +85,41 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
goto merr;
}
ctx = EVP_CIPHER_CTX_new();
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
if (EVP_EncryptInit_ex(ctx, kekciph, NULL, NULL, NULL) <= 0) {
- CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB);
goto err;
}
- ivlen = EVP_CIPHER_CTX_iv_length(ctx);
+ ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
+ if (ivlen < 0) {
+ ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB);
+ goto err;
+ }
if (ivlen > 0) {
- if (RAND_bytes(iv, ivlen) <= 0)
+ if (RAND_bytes_ex(ossl_cms_ctx_get0_libctx(cms_ctx), iv, ivlen, 0) <= 0)
goto err;
if (EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv) <= 0) {
- CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB);
goto err;
}
encalg->parameter = ASN1_TYPE_new();
if (!encalg->parameter) {
- CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_CIPHER_param_to_asn1(ctx, encalg->parameter) <= 0) {
- CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
- CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
goto err;
}
}
- encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
+ encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_get_type(ctx));
EVP_CIPHER_CTX_free(ctx);
ctx = NULL;
@@ -123,6 +135,7 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
ri->type = CMS_RECIPINFO_PASS;
pwri = ri->d.pwri;
+ pwri->cms_ctx = cms_ctx;
/* Since this is overwritten, free up empty structure already there */
X509_ALGOR_free(pwri->keyEncryptionAlgorithm);
pwri->keyEncryptionAlgorithm = X509_ALGOR_new();
@@ -146,19 +159,19 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1);
- if (!pwri->keyDerivationAlgorithm)
+ if (pwri->keyDerivationAlgorithm == NULL)
goto err;
CMS_RecipientInfo_set0_password(ri, pass, passlen);
pwri->version = 0;
- if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
+ if (!sk_CMS_RecipientInfo_push(ris, ri))
goto merr;
return ri;
merr:
- CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
err:
EVP_CIPHER_CTX_free(ctx);
if (ri)
@@ -177,7 +190,7 @@ static int kek_unwrap_key(unsigned char *out, size_t *outlen,
const unsigned char *in, size_t inlen,
EVP_CIPHER_CTX *ctx)
{
- size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
+ size_t blocklen = EVP_CIPHER_CTX_get_block_size(ctx);
unsigned char *tmp;
int outl, rv = 0;
if (inlen < 2 * blocklen) {
@@ -189,7 +202,7 @@ static int kek_unwrap_key(unsigned char *out, size_t *outlen,
return 0;
}
if ((tmp = OPENSSL_malloc(inlen)) == NULL) {
- CMSerr(CMS_F_KEK_UNWRAP_KEY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return 0;
}
/* setup IV by decrypting last two blocks */
@@ -230,9 +243,9 @@ static int kek_unwrap_key(unsigned char *out, size_t *outlen,
static int kek_wrap_key(unsigned char *out, size_t *outlen,
const unsigned char *in, size_t inlen,
- EVP_CIPHER_CTX *ctx)
+ EVP_CIPHER_CTX *ctx, const CMS_CTX *cms_ctx)
{
- size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
+ size_t blocklen = EVP_CIPHER_CTX_get_block_size(ctx);
size_t olen;
int dummy;
/*
@@ -258,7 +271,8 @@ static int kek_wrap_key(unsigned char *out, size_t *outlen,
memcpy(out + 4, in, inlen);
/* Add random padding to end */
if (olen > inlen + 4
- && RAND_bytes(out + 4 + inlen, olen - 4 - inlen) <= 0)
+ && RAND_bytes_ex(ossl_cms_ctx_get0_libctx(cms_ctx), out + 4 + inlen,
+ olen - 4 - inlen, 0) <= 0)
return 0;
/* Encrypt twice */
if (!EVP_EncryptUpdate(ctx, out, &dummy, out, olen)
@@ -273,31 +287,32 @@ static int kek_wrap_key(unsigned char *out, size_t *outlen,
/* Encrypt/Decrypt content key in PWRI recipient info */
-int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
- int en_de)
+int ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms,
+ CMS_RecipientInfo *ri, int en_de)
{
CMS_EncryptedContentInfo *ec;
CMS_PasswordRecipientInfo *pwri;
int r = 0;
X509_ALGOR *algtmp, *kekalg = NULL;
EVP_CIPHER_CTX *kekctx = NULL;
- const EVP_CIPHER *kekcipher;
+ char name[OSSL_MAX_NAME_SIZE];
+ EVP_CIPHER *kekcipher;
unsigned char *key = NULL;
size_t keylen;
+ const CMS_CTX *cms_ctx = ossl_cms_get0_cmsctx(cms);
- ec = cms->d.envelopedData->encryptedContentInfo;
+ ec = ossl_cms_get0_env_enc_content(cms);
pwri = ri->d.pwri;
- if (!pwri->pass) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_NO_PASSWORD);
+ if (pwri->pass == NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_PASSWORD);
return 0;
}
algtmp = pwri->keyEncryptionAlgorithm;
if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
- CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
return 0;
}
@@ -305,30 +320,30 @@ int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
algtmp->parameter);
if (kekalg == NULL) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
- CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER);
+ ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER);
return 0;
}
- kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
+ OBJ_obj2txt(name, sizeof(name), kekalg->algorithm, 0);
+ kekcipher = EVP_CIPHER_fetch(ossl_cms_ctx_get0_libctx(cms_ctx), name,
+ ossl_cms_ctx_get0_propq(cms_ctx));
- if (!kekcipher) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNKNOWN_CIPHER);
- return 0;
+ if (kekcipher == NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_CIPHER);
+ goto err;
}
kekctx = EVP_CIPHER_CTX_new();
if (kekctx == NULL) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_MALLOC_FAILURE);
- return 0;
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
+ goto err;
}
/* Fixup cipher based on AlgorithmIdentifier to set IV etc */
if (!EVP_CipherInit_ex(kekctx, kekcipher, NULL, NULL, NULL, en_de))
goto err;
EVP_CIPHER_CTX_set_padding(kekctx, 0);
if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
- CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
goto err;
}
@@ -339,7 +354,7 @@ int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
if (EVP_PBE_CipherInit(algtmp->algorithm,
(char *)pwri->pass, pwri->passlen,
algtmp->parameter, kekctx, en_de) < 0) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB);
goto err;
}
@@ -347,7 +362,7 @@ int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
if (en_de) {
- if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, kekctx))
+ if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, kekctx, cms_ctx))
goto err;
key = OPENSSL_malloc(keylen);
@@ -355,7 +370,7 @@ int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
if (key == NULL)
goto err;
- if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, kekctx))
+ if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, kekctx, cms_ctx))
goto err;
pwri->encryptedKey->data = key;
pwri->encryptedKey->length = keylen;
@@ -363,13 +378,13 @@ int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
key = OPENSSL_malloc(pwri->encryptedKey->length);
if (key == NULL) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!kek_unwrap_key(key, &keylen,
pwri->encryptedKey->data,
pwri->encryptedKey->length, kekctx)) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNWRAP_FAILURE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNWRAP_FAILURE);
goto err;
}
@@ -382,7 +397,7 @@ int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
r = 1;
err:
-
+ EVP_CIPHER_free(kekcipher);
EVP_CIPHER_CTX_free(kekctx);
if (!r)
diff --git a/crypto/cms/cms_rsa.c b/crypto/cms/cms_rsa.c
new file mode 100644
index 000000000000..997567fdbfac
--- /dev/null
+++ b/crypto/cms/cms_rsa.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <assert.h>
+#include <openssl/cms.h>
+#include <openssl/err.h>
+#include <openssl/core_names.h>
+#include "crypto/asn1.h"
+#include "crypto/rsa.h"
+#include "cms_local.h"
+
+static RSA_OAEP_PARAMS *rsa_oaep_decode(const X509_ALGOR *alg)
+{
+ RSA_OAEP_PARAMS *oaep;
+
+ oaep = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_OAEP_PARAMS),
+ alg->parameter);
+
+ if (oaep == NULL)
+ return NULL;
+
+ if (oaep->maskGenFunc != NULL) {
+ oaep->maskHash = ossl_x509_algor_mgf1_decode(oaep->maskGenFunc);
+ if (oaep->maskHash == NULL) {
+ RSA_OAEP_PARAMS_free(oaep);
+ return NULL;
+ }
+ }
+ return oaep;
+}
+
+static int rsa_cms_decrypt(CMS_RecipientInfo *ri)
+{
+ EVP_PKEY_CTX *pkctx;
+ X509_ALGOR *cmsalg;
+ int nid;
+ int rv = -1;
+ unsigned char *label = NULL;
+ int labellen = 0;
+ const EVP_MD *mgf1md = NULL, *md = NULL;
+ RSA_OAEP_PARAMS *oaep;
+
+ pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+ if (pkctx == NULL)
+ return 0;
+ if (!CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &cmsalg))
+ return -1;
+ nid = OBJ_obj2nid(cmsalg->algorithm);
+ if (nid == NID_rsaEncryption)
+ return 1;
+ if (nid != NID_rsaesOaep) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_ENCRYPTION_TYPE);
+ return -1;
+ }
+ /* Decode OAEP parameters */
+ oaep = rsa_oaep_decode(cmsalg);
+
+ if (oaep == NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_OAEP_PARAMETERS);
+ goto err;
+ }
+
+ mgf1md = ossl_x509_algor_get_md(oaep->maskHash);
+ if (mgf1md == NULL)
+ goto err;
+ md = ossl_x509_algor_get_md(oaep->hashFunc);
+ if (md == NULL)
+ goto err;
+
+ if (oaep->pSourceFunc != NULL) {
+ X509_ALGOR *plab = oaep->pSourceFunc;
+
+ if (OBJ_obj2nid(plab->algorithm) != NID_pSpecified) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_LABEL_SOURCE);
+ goto err;
+ }
+ if (plab->parameter->type != V_ASN1_OCTET_STRING) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_LABEL);
+ goto err;
+ }
+
+ label = plab->parameter->value.octet_string->data;
+ /* Stop label being freed when OAEP parameters are freed */
+ plab->parameter->value.octet_string->data = NULL;
+ labellen = plab->parameter->value.octet_string->length;
+ }
+
+ if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0)
+ goto err;
+ if (EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, md) <= 0)
+ goto err;
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0)
+ goto err;
+ if (label != NULL
+ && EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, label, labellen) <= 0)
+ goto err;
+ /* Carry on */
+ rv = 1;
+
+ err:
+ RSA_OAEP_PARAMS_free(oaep);
+ return rv;
+}
+
+static int rsa_cms_encrypt(CMS_RecipientInfo *ri)
+{
+ const EVP_MD *md, *mgf1md;
+ RSA_OAEP_PARAMS *oaep = NULL;
+ ASN1_STRING *os = NULL;
+ X509_ALGOR *alg;
+ EVP_PKEY_CTX *pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+ int pad_mode = RSA_PKCS1_PADDING, rv = 0, labellen;
+ unsigned char *label;
+
+ if (CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &alg) <= 0)
+ return 0;
+ if (pkctx != NULL) {
+ if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
+ return 0;
+ }
+ if (pad_mode == RSA_PKCS1_PADDING) {
+ X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
+ return 1;
+ }
+ /* Not supported */
+ if (pad_mode != RSA_PKCS1_OAEP_PADDING)
+ return 0;
+ if (EVP_PKEY_CTX_get_rsa_oaep_md(pkctx, &md) <= 0)
+ goto err;
+ if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0)
+ goto err;
+ labellen = EVP_PKEY_CTX_get0_rsa_oaep_label(pkctx, &label);
+ if (labellen < 0)
+ goto err;
+ oaep = RSA_OAEP_PARAMS_new();
+ if (oaep == NULL)
+ goto err;
+ if (!ossl_x509_algor_new_from_md(&oaep->hashFunc, md))
+ goto err;
+ if (!ossl_x509_algor_md_to_mgf1(&oaep->maskGenFunc, mgf1md))
+ goto err;
+ if (labellen > 0) {
+ ASN1_OCTET_STRING *los;
+
+ oaep->pSourceFunc = X509_ALGOR_new();
+ if (oaep->pSourceFunc == NULL)
+ goto err;
+ los = ASN1_OCTET_STRING_new();
+ if (los == NULL)
+ goto err;
+ if (!ASN1_OCTET_STRING_set(los, label, labellen)) {
+ ASN1_OCTET_STRING_free(los);
+ goto err;
+ }
+ X509_ALGOR_set0(oaep->pSourceFunc, OBJ_nid2obj(NID_pSpecified),
+ V_ASN1_OCTET_STRING, los);
+ }
+ /* create string with pss parameter encoding. */
+ if (!ASN1_item_pack(oaep, ASN1_ITEM_rptr(RSA_OAEP_PARAMS), &os))
+ goto err;
+ X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaesOaep), V_ASN1_SEQUENCE, os);
+ os = NULL;
+ rv = 1;
+ err:
+ RSA_OAEP_PARAMS_free(oaep);
+ ASN1_STRING_free(os);
+ return rv;
+}
+
+int ossl_cms_rsa_envelope(CMS_RecipientInfo *ri, int decrypt)
+{
+ assert(decrypt == 0 || decrypt == 1);
+
+ if (decrypt == 1)
+ return rsa_cms_decrypt(ri);
+
+ if (decrypt == 0)
+ return rsa_cms_encrypt(ri);
+
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+ return 0;
+}
+
+static int rsa_cms_sign(CMS_SignerInfo *si)
+{
+ int pad_mode = RSA_PKCS1_PADDING;
+ X509_ALGOR *alg;
+ EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
+ unsigned char aid[128];
+ const unsigned char *pp = aid;
+ size_t aid_len = 0;
+ OSSL_PARAM params[2];
+
+ CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
+ if (pkctx != NULL) {
+ if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
+ return 0;
+ }
+ if (pad_mode == RSA_PKCS1_PADDING) {
+ X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
+ return 1;
+ }
+ /* We don't support it */
+ if (pad_mode != RSA_PKCS1_PSS_PADDING)
+ return 0;
+
+ params[0] = OSSL_PARAM_construct_octet_string(
+ OSSL_SIGNATURE_PARAM_ALGORITHM_ID, aid, sizeof(aid));
+ params[1] = OSSL_PARAM_construct_end();
+
+ if (EVP_PKEY_CTX_get_params(pkctx, params) <= 0)
+ return 0;
+ if ((aid_len = params[0].return_size) == 0)
+ return 0;
+ if (d2i_X509_ALGOR(&alg, &pp, aid_len) == NULL)
+ return 0;
+ return 1;
+}
+
+static int rsa_cms_verify(CMS_SignerInfo *si)
+{
+ int nid, nid2;
+ X509_ALGOR *alg;
+ EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
+ EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pkctx);
+
+ CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
+ nid = OBJ_obj2nid(alg->algorithm);
+ if (nid == EVP_PKEY_RSA_PSS)
+ return ossl_rsa_pss_to_ctx(NULL, pkctx, alg, NULL) > 0;
+ /* Only PSS allowed for PSS keys */
+ if (EVP_PKEY_is_a(pkey, "RSA-PSS")) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
+ return 0;
+ }
+ if (nid == NID_rsaEncryption)
+ return 1;
+ /* Workaround for some implementation that use a signature OID */
+ if (OBJ_find_sigid_algs(nid, NULL, &nid2)) {
+ if (nid2 == NID_rsaEncryption)
+ return 1;
+ }
+ return 0;
+}
+
+int ossl_cms_rsa_sign(CMS_SignerInfo *si, int verify)
+{
+ assert(verify == 0 || verify == 1);
+
+ if (verify == 1)
+ return rsa_cms_verify(si);
+
+ if (verify == 0)
+ return rsa_cms_sign(si);
+
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+ return 0;
+}
diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c
index 3f2a782565a8..34c021bba64a 100644
--- a/crypto/cms/cms_sd.c
+++ b/crypto/cms/cms_sd.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -14,16 +14,20 @@
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/cms.h>
-#include "cms_local.h"
+#include <openssl/ess.h>
+#include "internal/sizes.h"
#include "crypto/asn1.h"
#include "crypto/evp.h"
+#include "crypto/ess.h"
+#include "crypto/x509.h" /* for ossl_x509_add_cert_new() */
+#include "cms_local.h"
/* CMS SignedData Utilities */
static CMS_SignedData *cms_get0_signed(CMS_ContentInfo *cms)
{
if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_signed) {
- CMSerr(CMS_F_CMS_GET0_SIGNED, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA);
return NULL;
}
return cms->d.signedData;
@@ -34,7 +38,7 @@ static CMS_SignedData *cms_signed_data_init(CMS_ContentInfo *cms)
if (cms->d.other == NULL) {
cms->d.signedData = M_ASN1_new_of(CMS_SignedData);
if (!cms->d.signedData) {
- CMSerr(CMS_F_CMS_SIGNED_DATA_INIT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return NULL;
}
cms->d.signedData->version = 1;
@@ -58,6 +62,7 @@ int CMS_SignedData_init(CMS_ContentInfo *cms)
return 0;
}
+
/* Check structures and fixup version numbers (if necessary) */
static void cms_sd_set_version(CMS_SignedData *sd)
@@ -137,9 +142,11 @@ static int cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si)
STACK_OF(CMS_SignerInfo) *sinfos;
CMS_SignerInfo *sitmp;
int i;
+
sinfos = CMS_get0_SignerInfos(cms);
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
ASN1_OCTET_STRING *messageDigest;
+
sitmp = sk_CMS_SignerInfo_value(sinfos, i);
if (sitmp == si)
continue;
@@ -153,8 +160,7 @@ static int cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si)
(NID_pkcs9_messageDigest),
-3, V_ASN1_OCTET_STRING);
if (!messageDigest) {
- CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST,
- CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
return 0;
}
@@ -165,25 +171,26 @@ static int cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si)
else
return 0;
}
- CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST, CMS_R_NO_MATCHING_DIGEST);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_DIGEST);
return 0;
}
-int cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type)
+int ossl_cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert,
+ int type, const CMS_CTX *ctx)
{
switch (type) {
case CMS_SIGNERINFO_ISSUER_SERIAL:
- if (!cms_set1_ias(&sid->d.issuerAndSerialNumber, cert))
+ if (!ossl_cms_set1_ias(&sid->d.issuerAndSerialNumber, cert))
return 0;
break;
case CMS_SIGNERINFO_KEYIDENTIFIER:
- if (!cms_set1_keyid(&sid->d.subjectKeyIdentifier, cert))
+ if (!ossl_cms_set1_keyid(&sid->d.subjectKeyIdentifier, cert))
return 0;
break;
default:
- CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, CMS_R_UNKNOWN_ID);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_ID);
return 0;
}
@@ -192,10 +199,10 @@ int cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type)
return 1;
}
-int cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid,
- ASN1_OCTET_STRING **keyid,
- X509_NAME **issuer,
- ASN1_INTEGER **sno)
+int ossl_cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid,
+ ASN1_OCTET_STRING **keyid,
+ X509_NAME **issuer,
+ ASN1_INTEGER **sno)
{
if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL) {
if (issuer)
@@ -210,12 +217,12 @@ int cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid,
return 1;
}
-int cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert)
+int ossl_cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert)
{
if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL)
- return cms_ias_cert_cmp(sid->d.issuerAndSerialNumber, cert);
+ return ossl_cms_ias_cert_cmp(sid->d.issuerAndSerialNumber, cert);
else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER)
- return cms_keyid_cert_cmp(sid->d.subjectKeyIdentifier, cert);
+ return ossl_cms_keyid_cert_cmp(sid->d.subjectKeyIdentifier, cert);
else
return -1;
}
@@ -224,20 +231,77 @@ static int cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd)
{
EVP_PKEY *pkey = si->pkey;
int i;
- if (!pkey->ameth || !pkey->ameth->pkey_ctrl)
+
+ if (EVP_PKEY_is_a(pkey, "DSA") || EVP_PKEY_is_a(pkey, "EC"))
+ return ossl_cms_ecdsa_dsa_sign(si, cmd);
+ else if (EVP_PKEY_is_a(pkey, "RSA") || EVP_PKEY_is_a(pkey, "RSA-PSS"))
+ return ossl_cms_rsa_sign(si, cmd);
+
+ /* Something else? We'll give engines etc a chance to handle this */
+ if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL)
return 1;
i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_SIGN, cmd, si);
if (i == -2) {
- CMSerr(CMS_F_CMS_SD_ASN1_CTRL, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
return 0;
}
if (i <= 0) {
- CMSerr(CMS_F_CMS_SD_ASN1_CTRL, CMS_R_CTRL_FAILURE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CTRL_FAILURE);
return 0;
}
return 1;
}
+/* Add SigningCertificate signed attribute to the signer info. */
+static int ossl_cms_add1_signing_cert(CMS_SignerInfo *si,
+ const ESS_SIGNING_CERT *sc)
+{
+ ASN1_STRING *seq = NULL;
+ unsigned char *p, *pp = NULL;
+ int ret, len = i2d_ESS_SIGNING_CERT(sc, NULL);
+
+ if (len <= 0 || (pp = OPENSSL_malloc(len)) == NULL)
+ return 0;
+
+ p = pp;
+ i2d_ESS_SIGNING_CERT(sc, &p);
+ if (!(seq = ASN1_STRING_new()) || !ASN1_STRING_set(seq, pp, len)) {
+ ASN1_STRING_free(seq);
+ OPENSSL_free(pp);
+ return 0;
+ }
+ OPENSSL_free(pp);
+ ret = CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_signingCertificate,
+ V_ASN1_SEQUENCE, seq, -1);
+ ASN1_STRING_free(seq);
+ return ret;
+}
+
+/* Add SigningCertificateV2 signed attribute to the signer info. */
+static int ossl_cms_add1_signing_cert_v2(CMS_SignerInfo *si,
+ const ESS_SIGNING_CERT_V2 *sc)
+{
+ ASN1_STRING *seq = NULL;
+ unsigned char *p, *pp = NULL;
+ int ret, len = i2d_ESS_SIGNING_CERT_V2(sc, NULL);
+
+ if (len <= 0 || (pp = OPENSSL_malloc(len)) == NULL)
+ return 0;
+
+ p = pp;
+ i2d_ESS_SIGNING_CERT_V2(sc, &p);
+ if (!(seq = ASN1_STRING_new()) || !ASN1_STRING_set(seq, pp, len)) {
+ ASN1_STRING_free(seq);
+ OPENSSL_free(pp);
+ return 0;
+ }
+ OPENSSL_free(pp);
+ ret = CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_signingCertificateV2,
+ V_ASN1_SEQUENCE, seq, -1);
+ ASN1_STRING_free(seq);
+ return ret;
+}
+
CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
unsigned int flags)
@@ -246,9 +310,10 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
CMS_SignerInfo *si = NULL;
X509_ALGOR *alg;
int i, type;
+ const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
+
if (!X509_check_private_key(signer, pk)) {
- CMSerr(CMS_F_CMS_ADD1_SIGNER,
- CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
return NULL;
}
sd = cms_signed_data_init(cms);
@@ -263,13 +328,14 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
X509_up_ref(signer);
EVP_PKEY_up_ref(pk);
+ si->cms_ctx = ctx;
si->pkey = pk;
si->signer = signer;
si->mctx = EVP_MD_CTX_new();
si->pctx = NULL;
if (si->mctx == NULL) {
- CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -283,7 +349,7 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
si->version = 1;
}
- if (!cms_set1_SignerIdentifier(si->sid, signer, type))
+ if (!ossl_cms_set1_SignerIdentifier(si->sid, signer, type, ctx))
goto err;
if (md == NULL) {
@@ -292,13 +358,18 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
goto err;
md = EVP_get_digestbynid(def_nid);
if (md == NULL) {
- CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DEFAULT_DIGEST);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_DEFAULT_DIGEST);
goto err;
}
}
if (!md) {
- CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DIGEST_SET);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_DIGEST_SET);
+ goto err;
+ }
+
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_DIGEST_SET);
goto err;
}
@@ -307,9 +378,12 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
/* See if digest is present in digestAlgorithms */
for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) {
const ASN1_OBJECT *aoid;
+ char name[OSSL_MAX_NAME_SIZE];
+
alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
X509_ALGOR_get0(&aoid, NULL, NULL, alg);
- if (OBJ_obj2nid(aoid) == EVP_MD_type(md))
+ OBJ_obj2txt(name, sizeof(name), aoid, 0);
+ if (EVP_MD_is_a(md, name))
break;
}
@@ -346,6 +420,27 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
if (!i)
goto merr;
}
+ if (flags & CMS_CADES) {
+ ESS_SIGNING_CERT *sc = NULL;
+ ESS_SIGNING_CERT_V2 *sc2 = NULL;
+ int add_sc;
+
+ if (md == NULL || EVP_MD_is_a(md, SN_sha1)) {
+ if ((sc = OSSL_ESS_signing_cert_new_init(signer,
+ NULL, 1)) == NULL)
+ goto err;
+ add_sc = ossl_cms_add1_signing_cert(si, sc);
+ ESS_SIGNING_CERT_free(sc);
+ } else {
+ if ((sc2 = OSSL_ESS_signing_cert_v2_new_init(md, signer,
+ NULL, 1)) == NULL)
+ goto err;
+ add_sc = ossl_cms_add1_signing_cert_v2(si, sc2);
+ ESS_SIGNING_CERT_V2_free(sc2);
+ }
+ if (!add_sc)
+ goto err;
+ }
if (flags & CMS_REUSE_DIGEST) {
if (!cms_copy_messageDigest(cms, si))
goto err;
@@ -365,16 +460,22 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
if (flags & CMS_KEY_PARAM) {
if (flags & CMS_NOATTR) {
- si->pctx = EVP_PKEY_CTX_new(si->pkey, NULL);
+ si->pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx),
+ si->pkey,
+ ossl_cms_ctx_get0_propq(ctx));
if (si->pctx == NULL)
goto err;
if (EVP_PKEY_sign_init(si->pctx) <= 0)
goto err;
if (EVP_PKEY_CTX_set_signature_md(si->pctx, md) <= 0)
goto err;
- } else if (EVP_DigestSignInit(si->mctx, &si->pctx, md, NULL, pk) <=
- 0)
+ } else if (EVP_DigestSignInit_ex(si->mctx, &si->pctx,
+ EVP_MD_get0_name(md),
+ ossl_cms_ctx_get0_libctx(ctx),
+ ossl_cms_ctx_get0_propq(ctx),
+ pk, NULL) <= 0) {
goto err;
+ }
}
if (!sd->signerInfos)
@@ -385,23 +486,42 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
return si;
merr:
- CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
err:
M_ASN1_free_of(si, CMS_SignerInfo);
return NULL;
}
+void ossl_cms_SignerInfos_set_cmsctx(CMS_ContentInfo *cms)
+{
+ int i;
+ CMS_SignerInfo *si;
+ STACK_OF(CMS_SignerInfo) *sinfos;
+ const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
+
+ ERR_set_mark();
+ sinfos = CMS_get0_SignerInfos(cms);
+ ERR_pop_to_mark(); /* removes error in case sinfos == NULL */
+
+ for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
+ si = sk_CMS_SignerInfo_value(sinfos, i);
+ if (si != NULL)
+ si->cms_ctx = ctx;
+ }
+}
+
static int cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t)
{
ASN1_TIME *tt;
int r = 0;
- if (t)
+
+ if (t != NULL)
tt = t;
else
tt = X509_gmtime_adj(NULL, 0);
- if (!tt)
+ if (tt == NULL)
goto merr;
if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_signingTime,
@@ -409,14 +529,12 @@ static int cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t)
goto merr;
r = 1;
-
merr:
-
- if (!t)
+ if (t == NULL)
ASN1_TIME_free(tt);
if (!r)
- CMSerr(CMS_F_CMS_ADD1_SIGNINGTIME, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return r;
@@ -434,11 +552,9 @@ EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si)
STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms)
{
- CMS_SignedData *sd;
- sd = cms_get0_signed(cms);
- if (!sd)
- return NULL;
- return sd->signerInfos;
+ CMS_SignedData *sd = cms_get0_signed(cms);
+
+ return sd != NULL ? sd->signerInfos : NULL;
}
STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms)
@@ -447,16 +563,13 @@ STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms)
STACK_OF(CMS_SignerInfo) *sinfos;
CMS_SignerInfo *si;
int i;
+
sinfos = CMS_get0_SignerInfos(cms);
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
si = sk_CMS_SignerInfo_value(sinfos, i);
- if (si->signer) {
- if (!signers) {
- signers = sk_X509_new_null();
- if (!signers)
- return NULL;
- }
- if (!sk_X509_push(signers, si->signer)) {
+ if (si->signer != NULL) {
+ if (!ossl_x509_add_cert_new(&signers, si->signer,
+ X509_ADD_FLAG_DEFAULT)) {
sk_X509_free(signers);
return NULL;
}
@@ -467,7 +580,7 @@ STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms)
void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer)
{
- if (signer) {
+ if (signer != NULL) {
X509_up_ref(signer);
EVP_PKEY_free(si->pkey);
si->pkey = X509_get_pubkey(signer);
@@ -480,12 +593,12 @@ int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si,
ASN1_OCTET_STRING **keyid,
X509_NAME **issuer, ASN1_INTEGER **sno)
{
- return cms_SignerIdentifier_get0_signer_id(si->sid, keyid, issuer, sno);
+ return ossl_cms_SignerIdentifier_get0_signer_id(si->sid, keyid, issuer, sno);
}
int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert)
{
- return cms_SignerIdentifier_cert_cmp(si->sid, cert);
+ return ossl_cms_SignerIdentifier_cert_cmp(si->sid, cert);
}
int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts,
@@ -498,13 +611,14 @@ int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts,
X509 *x;
int i, j;
int ret = 0;
+
sd = cms_get0_signed(cms);
- if (!sd)
+ if (sd == NULL)
return -1;
certs = sd->certificates;
for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) {
si = sk_CMS_SignerInfo_value(sd->signerInfos, i);
- if (si->signer)
+ if (si->signer != NULL)
continue;
for (j = 0; j < sk_X509_num(scerts); j++) {
@@ -516,7 +630,7 @@ int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts,
}
}
- if (si->signer || (flags & CMS_NOINTERN))
+ if (si->signer != NULL || (flags & CMS_NOINTERN))
continue;
for (j = 0; j < sk_CMS_CertificateChoices_num(certs); j++) {
@@ -538,13 +652,13 @@ void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk,
X509 **signer, X509_ALGOR **pdig,
X509_ALGOR **psig)
{
- if (pk)
+ if (pk != NULL)
*pk = si->pkey;
- if (signer)
+ if (signer != NULL)
*signer = si->signer;
- if (pdig)
+ if (pdig != NULL)
*pdig = si->digestAlgorithm;
- if (psig)
+ if (psig != NULL)
*psig = si->signatureAlgorithm;
}
@@ -559,18 +673,19 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
int r = 0;
EVP_PKEY_CTX *pctx = NULL;
+ const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
if (mctx == NULL) {
- CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
return 0;
}
- if (!si->pkey) {
- CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_NO_PRIVATE_KEY);
+ if (si->pkey == NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_PRIVATE_KEY);
goto err;
}
- if (!cms_DigestAlgorithm_find_ctx(mctx, chain, si->digestAlgorithm))
+ if (!ossl_cms_DigestAlgorithm_find_ctx(mctx, chain, si->digestAlgorithm))
goto err;
/* Set SignerInfo algorithm details if we used custom parameter */
if (si->pctx && !cms_sd_asn1_ctrl(si, 0))
@@ -583,6 +698,7 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
if (CMS_signed_get_attr_count(si) >= 0) {
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int mdlen;
+
if (!EVP_DigestFinal_ex(mctx, md, &mdlen))
goto err;
if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
@@ -599,13 +715,14 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
size_t siglen;
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int mdlen;
+
pctx = si->pctx;
if (!EVP_DigestFinal_ex(mctx, md, &mdlen))
goto err;
- siglen = EVP_PKEY_size(si->pkey);
+ siglen = EVP_PKEY_get_size(si->pkey);
sig = OPENSSL_malloc(siglen);
if (sig == NULL) {
- CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_PKEY_sign(pctx, sig, &siglen, md, mdlen) <= 0) {
@@ -616,13 +733,16 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
} else {
unsigned char *sig;
unsigned int siglen;
- sig = OPENSSL_malloc(EVP_PKEY_size(si->pkey));
+
+ sig = OPENSSL_malloc(EVP_PKEY_get_size(si->pkey));
if (sig == NULL) {
- CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (!EVP_SignFinal(mctx, sig, &siglen, si->pkey)) {
- CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_SIGNFINAL_ERROR);
+ if (!EVP_SignFinal_ex(mctx, sig, &siglen, si->pkey,
+ ossl_cms_ctx_get0_libctx(ctx),
+ ossl_cms_ctx_get0_propq(ctx))) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_SIGNFINAL_ERROR);
OPENSSL_free(sig);
goto err;
}
@@ -638,11 +758,12 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
}
-int cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain)
+int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain)
{
STACK_OF(CMS_SignerInfo) *sinfos;
CMS_SignerInfo *si;
int i;
+
sinfos = CMS_get0_SignerInfos(cms);
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
si = sk_CMS_SignerInfo_value(sinfos, i);
@@ -660,10 +781,11 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si)
unsigned char *abuf = NULL;
int alen;
size_t siglen;
- const EVP_MD *md = NULL;
+ const CMS_CTX *ctx = si->cms_ctx;
+ char md_name[OSSL_MAX_NAME_SIZE];
- md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
- if (md == NULL)
+ if (OBJ_obj2txt(md_name, sizeof(md_name),
+ si->digestAlgorithm->algorithm, 0) <= 0)
return 0;
if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) {
@@ -671,24 +793,21 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si)
goto err;
}
- if (!CMS_si_check_attributes(si))
+ if (!ossl_cms_si_check_attributes(si))
goto err;
if (si->pctx)
pctx = si->pctx;
else {
EVP_MD_CTX_reset(mctx);
- if (EVP_DigestSignInit(mctx, &pctx, md, NULL, si->pkey) <= 0)
+ if (EVP_DigestSignInit_ex(mctx, &pctx, md_name,
+ ossl_cms_ctx_get0_libctx(ctx),
+ ossl_cms_ctx_get0_propq(ctx), si->pkey,
+ NULL) <= 0)
goto err;
si->pctx = pctx;
}
- if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
- EVP_PKEY_CTRL_CMS_SIGN, 0, si) <= 0) {
- CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR);
- goto err;
- }
-
alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf,
ASN1_ITEM_rptr(CMS_Attributes_Sign));
if (!abuf)
@@ -704,12 +823,6 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si)
if (EVP_DigestSignFinal(mctx, abuf, &siglen) <= 0)
goto err;
- if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
- EVP_PKEY_CTRL_CMS_SIGN, 1, si) <= 0) {
- CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR);
- goto err;
- }
-
EVP_MD_CTX_reset(mctx);
ASN1_STRING_set0(si->signature, abuf, siglen);
@@ -727,25 +840,44 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si)
EVP_MD_CTX *mctx = NULL;
unsigned char *abuf = NULL;
int alen, r = -1;
- const EVP_MD *md = NULL;
-
- if (!si->pkey) {
- CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_NO_PUBLIC_KEY);
+ char name[OSSL_MAX_NAME_SIZE];
+ const EVP_MD *md;
+ EVP_MD *fetched_md = NULL;
+ const CMS_CTX *ctx = si->cms_ctx;
+ OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(ctx);
+ const char *propq = ossl_cms_ctx_get0_propq(ctx);
+
+ if (si->pkey == NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_PUBLIC_KEY);
return -1;
}
- if (!CMS_si_check_attributes(si))
+ if (!ossl_cms_si_check_attributes(si))
return -1;
- md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
- if (md == NULL)
+ OBJ_obj2txt(name, sizeof(name), si->digestAlgorithm->algorithm, 0);
+
+ (void)ERR_set_mark();
+ fetched_md = EVP_MD_fetch(libctx, name, propq);
+
+ if (fetched_md != NULL)
+ md = fetched_md;
+ else
+ md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
+ if (md == NULL) {
+ (void)ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_DIGEST_ALGORITHM);
return -1;
+ }
+ (void)ERR_pop_to_mark();
+
if (si->mctx == NULL && (si->mctx = EVP_MD_CTX_new()) == NULL) {
- CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, ERR_R_MALLOC_FAILURE);
- return -1;
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
+ goto err;
}
mctx = si->mctx;
- if (EVP_DigestVerifyInit(mctx, &si->pctx, md, NULL, si->pkey) <= 0)
+ if (EVP_DigestVerifyInit_ex(mctx, &si->pctx, EVP_MD_get0_name(md), libctx,
+ propq, si->pkey, NULL) <= 0)
goto err;
if (!cms_sd_asn1_ctrl(si, 1))
@@ -753,7 +885,7 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si)
alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf,
ASN1_ITEM_rptr(CMS_Attributes_Verify));
- if (!abuf)
+ if (abuf == NULL || alen < 0)
goto err;
r = EVP_DigestVerifyUpdate(mctx, abuf, alen);
OPENSSL_free(abuf);
@@ -764,32 +896,36 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si)
r = EVP_DigestVerifyFinal(mctx,
si->signature->data, si->signature->length);
if (r <= 0)
- CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_VERIFICATION_FAILURE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_VERIFICATION_FAILURE);
err:
+ EVP_MD_free(fetched_md);
EVP_MD_CTX_reset(mctx);
return r;
}
/* Create a chain of digest BIOs from a CMS ContentInfo */
-BIO *cms_SignedData_init_bio(CMS_ContentInfo *cms)
+BIO *ossl_cms_SignedData_init_bio(CMS_ContentInfo *cms)
{
int i;
CMS_SignedData *sd;
BIO *chain = NULL;
+
sd = cms_get0_signed(cms);
- if (!sd)
+ if (sd == NULL)
return NULL;
if (cms->d.signedData->encapContentInfo->partial)
cms_sd_set_version(sd);
for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) {
X509_ALGOR *digestAlgorithm;
BIO *mdbio;
+
digestAlgorithm = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
- mdbio = cms_DigestAlgorithm_init_bio(digestAlgorithm);
- if (!mdbio)
+ mdbio = ossl_cms_DigestAlgorithm_init_bio(digestAlgorithm,
+ ossl_cms_get0_cmsctx(cms));
+ if (mdbio == NULL)
goto err;
- if (chain)
+ if (chain != NULL)
BIO_push(chain, mdbio);
else
chain = mdbio;
@@ -810,7 +946,7 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain)
unsigned int mlen;
if (mctx == NULL) {
- CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
/* If we have any signed attributes look for messageDigest value */
@@ -818,40 +954,40 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain)
os = CMS_signed_get0_data_by_OBJ(si,
OBJ_nid2obj(NID_pkcs9_messageDigest),
-3, V_ASN1_OCTET_STRING);
- if (!os) {
- CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
- CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
+ if (os == NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
goto err;
}
}
- if (!cms_DigestAlgorithm_find_ctx(mctx, chain, si->digestAlgorithm))
+ if (!ossl_cms_DigestAlgorithm_find_ctx(mctx, chain, si->digestAlgorithm))
goto err;
if (EVP_DigestFinal_ex(mctx, mval, &mlen) <= 0) {
- CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
- CMS_R_UNABLE_TO_FINALIZE_CONTEXT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNABLE_TO_FINALIZE_CONTEXT);
goto err;
}
/* If messageDigest found compare it */
- if (os) {
+ if (os != NULL) {
if (mlen != (unsigned int)os->length) {
- CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
- CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH);
+ ERR_raise(ERR_LIB_CMS, CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH);
goto err;
}
if (memcmp(mval, os->data, mlen)) {
- CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
- CMS_R_VERIFICATION_FAILURE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_VERIFICATION_FAILURE);
r = 0;
} else
r = 1;
} else {
- const EVP_MD *md = EVP_MD_CTX_md(mctx);
- pkctx = EVP_PKEY_CTX_new(si->pkey, NULL);
+ const EVP_MD *md = EVP_MD_CTX_get0_md(mctx);
+ const CMS_CTX *ctx = si->cms_ctx;
+
+ pkctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx),
+ si->pkey,
+ ossl_cms_ctx_get0_propq(ctx));
if (pkctx == NULL)
goto err;
if (EVP_PKEY_verify_init(pkctx) <= 0)
@@ -864,8 +1000,7 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain)
r = EVP_PKEY_verify(pkctx, si->signature->data,
si->signature->length, mval, mlen);
if (r <= 0) {
- CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
- CMS_R_VERIFICATION_FAILURE);
+ ERR_raise(ERR_LIB_CMS, CMS_R_VERIFICATION_FAILURE);
r = 0;
}
}
@@ -881,6 +1016,7 @@ int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs)
{
unsigned char *smder = NULL;
int smderlen, r;
+
smderlen = i2d_X509_ALGORS(algs, &smder);
if (smderlen <= 0)
return 0;
@@ -895,6 +1031,7 @@ int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs,
{
X509_ALGOR *alg;
ASN1_INTEGER *key = NULL;
+
if (keysize > 0) {
key = ASN1_INTEGER_new();
if (key == NULL || !ASN1_INTEGER_set(key, keysize)) {
diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c
index 6e7dbc4da1fa..d17df31dd412 100644
--- a/crypto/cms/cms_smime.c
+++ b/crypto/cms/cms_smime.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -19,6 +19,7 @@
static BIO *cms_get_text_bio(BIO *out, unsigned int flags)
{
BIO *rbio;
+
if (out == NULL)
rbio = BIO_new(BIO_s_null());
else if (flags & CMS_TEXT) {
@@ -38,7 +39,7 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
tmpout = cms_get_text_bio(out, flags);
if (tmpout == NULL) {
- CMSerr(CMS_F_CMS_COPY_CONTENT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -47,7 +48,7 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
i = BIO_read(in, buf, sizeof(buf));
if (i <= 0) {
if (BIO_method_type(in) == BIO_TYPE_CIPHER) {
- if (!BIO_get_cipher_status(in))
+ if (BIO_get_cipher_status(in) <= 0)
goto err;
}
if (i < 0)
@@ -55,19 +56,18 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
break;
}
- if (tmpout && (BIO_write(tmpout, buf, i) != i))
+ if (tmpout != NULL && (BIO_write(tmpout, buf, i) != i))
goto err;
}
if (flags & CMS_TEXT) {
if (!SMIME_text(tmpout, out)) {
- CMSerr(CMS_F_CMS_COPY_CONTENT, CMS_R_SMIME_TEXT_ERROR);
+ ERR_raise(ERR_LIB_CMS, CMS_R_SMIME_TEXT_ERROR);
goto err;
}
}
r = 1;
-
err:
if (tmpout != out)
BIO_free(tmpout);
@@ -78,8 +78,9 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
static int check_content(CMS_ContentInfo *cms)
{
ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
- if (!pos || !*pos) {
- CMSerr(CMS_F_CHECK_CONTENT, CMS_R_NO_CONTENT);
+
+ if (pos == NULL || *pos == NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_CONTENT);
return 0;
}
return 1;
@@ -87,80 +88,95 @@ static int check_content(CMS_ContentInfo *cms)
static void do_free_upto(BIO *f, BIO *upto)
{
- if (upto) {
+ if (upto != NULL) {
BIO *tbio;
+
do {
tbio = BIO_pop(f);
BIO_free(f);
f = tbio;
- }
- while (f && f != upto);
- } else
+ } while (f != NULL && f != upto);
+ } else {
BIO_free_all(f);
+ }
}
int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags)
{
BIO *cont;
int r;
+
if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data) {
- CMSerr(CMS_F_CMS_DATA, CMS_R_TYPE_NOT_DATA);
+ ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_DATA);
return 0;
}
cont = CMS_dataInit(cms, NULL);
- if (!cont)
+ if (cont == NULL)
return 0;
r = cms_copy_content(out, cont, flags);
BIO_free_all(cont);
return r;
}
-CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags)
+CMS_ContentInfo *CMS_data_create_ex(BIO *in, unsigned int flags,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
- CMS_ContentInfo *cms;
- cms = cms_Data_create();
- if (!cms)
+ CMS_ContentInfo *cms = ossl_cms_Data_create(libctx, propq);
+
+ if (cms == NULL)
return NULL;
if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
return cms;
CMS_ContentInfo_free(cms);
-
return NULL;
}
+CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags)
+{
+ return CMS_data_create_ex(in, flags, NULL, NULL);
+}
+
int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
unsigned int flags)
{
BIO *cont;
int r;
+
if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest) {
- CMSerr(CMS_F_CMS_DIGEST_VERIFY, CMS_R_TYPE_NOT_DIGESTED_DATA);
+ ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_DIGESTED_DATA);
return 0;
}
- if (!dcont && !check_content(cms))
+ if (dcont == NULL && !check_content(cms))
return 0;
cont = CMS_dataInit(cms, dcont);
- if (!cont)
+ if (cont == NULL)
return 0;
+
r = cms_copy_content(out, cont, flags);
if (r)
- r = cms_DigestedData_do_final(cms, cont, 1);
+ r = ossl_cms_DigestedData_do_final(cms, cont, 1);
do_free_upto(cont, dcont);
return r;
}
-CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
- unsigned int flags)
+CMS_ContentInfo *CMS_digest_create_ex(BIO *in, const EVP_MD *md,
+ unsigned int flags, OSSL_LIB_CTX *ctx,
+ const char *propq)
{
CMS_ContentInfo *cms;
- if (!md)
+
+ /*
+ * Because the EVP_MD is cached and can be a legacy algorithm, we
+ * cannot fetch the algorithm if it isn't supplied.
+ */
+ if (md == NULL)
md = EVP_sha1();
- cms = cms_DigestedData_create(md);
- if (!cms)
+ cms = ossl_cms_DigestedData_create(md, ctx, propq);
+ if (cms == NULL)
return NULL;
if (!(flags & CMS_DETACHED))
@@ -173,41 +189,50 @@ CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
return NULL;
}
+CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
+ unsigned int flags)
+{
+ return CMS_digest_create_ex(in, md, flags, NULL, NULL);
+}
+
int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
const unsigned char *key, size_t keylen,
BIO *dcont, BIO *out, unsigned int flags)
{
BIO *cont;
int r;
+
if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted) {
- CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT,
- CMS_R_TYPE_NOT_ENCRYPTED_DATA);
+ ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_ENCRYPTED_DATA);
return 0;
}
- if (!dcont && !check_content(cms))
+ if (dcont == NULL && !check_content(cms))
return 0;
if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0)
return 0;
cont = CMS_dataInit(cms, dcont);
- if (!cont)
+ if (cont == NULL)
return 0;
r = cms_copy_content(out, cont, flags);
do_free_upto(cont, dcont);
return r;
}
-CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
- const unsigned char *key,
- size_t keylen, unsigned int flags)
+CMS_ContentInfo *CMS_EncryptedData_encrypt_ex(BIO *in, const EVP_CIPHER *cipher,
+ const unsigned char *key,
+ size_t keylen, unsigned int flags,
+ OSSL_LIB_CTX *libctx,
+ const char *propq)
{
CMS_ContentInfo *cms;
- if (!cipher) {
- CMSerr(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, CMS_R_NO_CIPHER);
+
+ if (cipher == NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_CIPHER);
return NULL;
}
- cms = CMS_ContentInfo_new();
+ cms = CMS_ContentInfo_new_ex(libctx, propq);
if (cms == NULL)
return NULL;
if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
@@ -224,38 +249,52 @@ CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
return NULL;
}
+CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
+ const unsigned char *key,
+ size_t keylen, unsigned int flags)
+{
+ return CMS_EncryptedData_encrypt_ex(in, cipher, key, keylen, flags, NULL,
+ NULL);
+}
+
static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
X509_STORE *store,
STACK_OF(X509) *certs,
- STACK_OF(X509_CRL) *crls)
+ STACK_OF(X509_CRL) *crls,
+ STACK_OF(X509) **chain,
+ const CMS_CTX *cms_ctx)
{
- X509_STORE_CTX *ctx = X509_STORE_CTX_new();
+ X509_STORE_CTX *ctx;
X509 *signer;
int i, j, r = 0;
+ ctx = X509_STORE_CTX_new_ex(ossl_cms_ctx_get0_libctx(cms_ctx),
+ ossl_cms_ctx_get0_propq(cms_ctx));
if (ctx == NULL) {
- CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
if (!X509_STORE_CTX_init(ctx, store, signer, certs)) {
- CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, CMS_R_STORE_INIT_ERROR);
+ ERR_raise(ERR_LIB_CMS, CMS_R_STORE_INIT_ERROR);
goto err;
}
X509_STORE_CTX_set_default(ctx, "smime_sign");
- if (crls)
+ if (crls != NULL)
X509_STORE_CTX_set0_crls(ctx, crls);
i = X509_verify_cert(ctx);
if (i <= 0) {
j = X509_STORE_CTX_get_error(ctx);
- CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT,
- CMS_R_CERTIFICATE_VERIFY_ERROR);
- ERR_add_error_data(2, "Verify error:",
- X509_verify_cert_error_string(j));
+ ERR_raise_data(ERR_LIB_CMS, CMS_R_CERTIFICATE_VERIFY_ERROR,
+ "Verify error: %s", X509_verify_cert_error_string(j));
goto err;
}
r = 1;
+
+ /* also send back the trust chain when required */
+ if (chain != NULL)
+ *chain = X509_STORE_CTX_get1_chain(ctx);
err:
X509_STORE_CTX_free(ctx);
return r;
@@ -269,14 +308,18 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
STACK_OF(CMS_SignerInfo) *sinfos;
STACK_OF(X509) *cms_certs = NULL;
STACK_OF(X509_CRL) *crls = NULL;
+ STACK_OF(X509) **si_chains = NULL;
X509 *signer;
int i, scount = 0, ret = 0;
BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL;
+ int cadesVerify = (flags & CMS_CADES) != 0;
+ const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
- if (!dcont && !check_content(cms))
+ if (dcont == NULL && !check_content(cms))
return 0;
- if (dcont && !(flags & CMS_BINARY)) {
+ if (dcont != NULL && !(flags & CMS_BINARY)) {
const ASN1_OBJECT *coid = CMS_get0_eContentType(cms);
+
if (OBJ_obj2nid(coid) == NID_id_ct_asciiTextWithCRLF)
flags |= CMS_ASCIICRLF;
}
@@ -286,7 +329,7 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
sinfos = CMS_get0_SignerInfos(cms);
if (sk_CMS_SignerInfo_num(sinfos) <= 0) {
- CMSerr(CMS_F_CMS_VERIFY, CMS_R_NO_SIGNERS);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_SIGNERS);
goto err;
}
@@ -301,32 +344,50 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
scount += CMS_set1_signers_certs(cms, certs, flags);
if (scount != sk_CMS_SignerInfo_num(sinfos)) {
- CMSerr(CMS_F_CMS_VERIFY, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
+ ERR_raise(ERR_LIB_CMS, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
goto err;
}
/* Attempt to verify all signers certs */
-
- if (!(flags & CMS_NO_SIGNER_CERT_VERIFY)) {
+ /* at this point scount == sk_CMS_SignerInfo_num(sinfos) */
+
+ if ((flags & CMS_NO_SIGNER_CERT_VERIFY) == 0 || cadesVerify) {
+ if (cadesVerify) {
+ /* Certificate trust chain is required to check CAdES signature */
+ si_chains = OPENSSL_zalloc(scount * sizeof(si_chains[0]));
+ if (si_chains == NULL) {
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
cms_certs = CMS_get1_certs(cms);
if (!(flags & CMS_NOCRL))
crls = CMS_get1_crls(cms);
- for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
+ for (i = 0; i < scount; i++) {
si = sk_CMS_SignerInfo_value(sinfos, i);
- if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls))
+
+ if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls,
+ si_chains ? &si_chains[i] : NULL,
+ ctx))
goto err;
}
}
/* Attempt to verify all SignerInfo signed attribute signatures */
- if (!(flags & CMS_NO_ATTR_VERIFY)) {
- for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
+ if ((flags & CMS_NO_ATTR_VERIFY) == 0 || cadesVerify) {
+ for (i = 0; i < scount; i++) {
si = sk_CMS_SignerInfo_value(sinfos, i);
if (CMS_signed_get_attr_count(si) < 0)
continue;
if (CMS_SignerInfo_verify(si) <= 0)
goto err;
+ if (cadesVerify) {
+ STACK_OF(X509) *si_chain = si_chains ? si_chains[i] : NULL;
+
+ if (ossl_cms_check_signing_certs(si, si_chain) <= 0)
+ goto err;
+ }
}
}
@@ -337,17 +398,19 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
* reading from a read write memory BIO when signatures are calculated.
*/
- if (dcont && (BIO_method_type(dcont) == BIO_TYPE_MEM)) {
+ if (dcont != NULL && (BIO_method_type(dcont) == BIO_TYPE_MEM)) {
char *ptr;
long len;
+
len = BIO_get_mem_data(dcont, &ptr);
tmpin = (len == 0) ? dcont : BIO_new_mem_buf(ptr, len);
if (tmpin == NULL) {
- CMSerr(CMS_F_CMS_VERIFY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err2;
}
- } else
+ } else {
tmpin = dcont;
+ }
/*
* If not binary mode and detached generate digests by *writing* through
* the BIO. That makes it possible to canonicalise the input.
@@ -358,28 +421,29 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
* included content doesn't override detached content.
*/
tmpout = cms_get_text_bio(out, flags);
- if (!tmpout) {
- CMSerr(CMS_F_CMS_VERIFY, ERR_R_MALLOC_FAILURE);
+ if (tmpout == NULL) {
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
goto err;
}
cmsbio = CMS_dataInit(cms, tmpout);
- if (!cmsbio)
+ if (cmsbio == NULL)
goto err;
/*
* Don't use SMIME_TEXT for verify: it adds headers and we want to
* remove them.
*/
- SMIME_crlf_copy(dcont, cmsbio, flags & ~SMIME_TEXT);
+ if (!SMIME_crlf_copy(dcont, cmsbio, flags & ~SMIME_TEXT))
+ goto err;
if (flags & CMS_TEXT) {
if (!SMIME_text(tmpout, out)) {
- CMSerr(CMS_F_CMS_VERIFY, CMS_R_SMIME_TEXT_ERROR);
+ ERR_raise(ERR_LIB_CMS, CMS_R_SMIME_TEXT_ERROR);
goto err;
}
}
} else {
cmsbio = CMS_dataInit(cms, tmpin);
- if (!cmsbio)
+ if (cmsbio == NULL)
goto err;
if (!cms_copy_content(out, cmsbio, flags))
@@ -390,14 +454,13 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
si = sk_CMS_SignerInfo_value(sinfos, i);
if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0) {
- CMSerr(CMS_F_CMS_VERIFY, CMS_R_CONTENT_VERIFY_ERROR);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_VERIFY_ERROR);
goto err;
}
}
}
ret = 1;
-
err:
if (!(flags & SMIME_BINARY) && dcont) {
do_free_upto(cmsbio, tmpout);
@@ -414,6 +477,11 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
BIO_free_all(tmpout);
err2:
+ if (si_chains != NULL) {
+ for (i = 0; i < scount; ++i)
+ sk_X509_pop_free(si_chains[i], X509_free);
+ OPENSSL_free(si_chains);
+ }
sk_X509_pop_free(cms_certs, X509_free);
sk_X509_CRL_pop_free(crls, X509_CRL_free);
@@ -425,21 +493,23 @@ int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
X509_STORE *store, unsigned int flags)
{
int r;
+
flags &= ~(CMS_DETACHED | CMS_TEXT);
r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
if (r <= 0)
return r;
- return cms_Receipt_verify(rcms, ocms);
+ return ossl_cms_Receipt_verify(rcms, ocms);
}
-CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
- STACK_OF(X509) *certs, BIO *data,
- unsigned int flags)
+CMS_ContentInfo *CMS_sign_ex(X509 *signcert, EVP_PKEY *pkey,
+ STACK_OF(X509) *certs, BIO *data,
+ unsigned int flags, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
CMS_ContentInfo *cms;
int i;
- cms = CMS_ContentInfo_new();
+ cms = CMS_ContentInfo_new_ex(libctx, propq);
if (cms == NULL || !CMS_SignedData_init(cms))
goto merr;
if (flags & CMS_ASCIICRLF
@@ -447,13 +517,14 @@ CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
OBJ_nid2obj(NID_id_ct_asciiTextWithCRLF)))
goto err;
- if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) {
- CMSerr(CMS_F_CMS_SIGN, CMS_R_ADD_SIGNER_ERROR);
+ if (pkey != NULL && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_ADD_SIGNER_ERROR);
goto err;
}
for (i = 0; i < sk_X509_num(certs); i++) {
X509 *x = sk_X509_value(certs, i);
+
if (!CMS_add1_cert(cms, x))
goto merr;
}
@@ -468,13 +539,19 @@ CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
goto err;
merr:
- CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
err:
CMS_ContentInfo_free(cms);
return NULL;
}
+CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+ BIO *data, unsigned int flags)
+{
+ return CMS_sign_ex(signcert, pkey, certs, data, flags, NULL, NULL);
+}
+
CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
X509 *signcert, EVP_PKEY *pkey,
STACK_OF(X509) *certs, unsigned int flags)
@@ -484,19 +561,22 @@ CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
ASN1_OCTET_STRING **pos, *os;
BIO *rct_cont = NULL;
int r = 0;
+ const CMS_CTX *ctx = si->cms_ctx;
flags &= ~(CMS_STREAM | CMS_TEXT);
/* Not really detached but avoids content being allocated */
flags |= CMS_PARTIAL | CMS_BINARY | CMS_DETACHED;
- if (!pkey || !signcert) {
- CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_NO_KEY_OR_CERT);
+ if (pkey == NULL || signcert == NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_KEY_OR_CERT);
return NULL;
}
/* Initialize signed data */
- cms = CMS_sign(NULL, NULL, certs, NULL, flags);
- if (!cms)
+ cms = CMS_sign_ex(NULL, NULL, certs, NULL, flags,
+ ossl_cms_ctx_get0_libctx(ctx),
+ ossl_cms_ctx_get0_propq(ctx));
+ if (cms == NULL)
goto err;
/* Set inner content type to signed receipt */
@@ -505,23 +585,22 @@ CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
if (!rct_si) {
- CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_ADD_SIGNER_ERROR);
+ ERR_raise(ERR_LIB_CMS, CMS_R_ADD_SIGNER_ERROR);
goto err;
}
- os = cms_encode_Receipt(si);
-
- if (!os)
+ os = ossl_cms_encode_Receipt(si);
+ if (os == NULL)
goto err;
/* Set content to digest */
rct_cont = BIO_new_mem_buf(os->data, os->length);
- if (!rct_cont)
+ if (rct_cont == NULL)
goto err;
/* Add msgSigDigest attribute */
- if (!cms_msgSigDigest_add1(rct_si, si))
+ if (!ossl_cms_msgSigDigest_add1(rct_si, si))
goto err;
/* Finalize structure */
@@ -530,6 +609,8 @@ CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
/* Set embedded content */
pos = CMS_get0_content(cms);
+ if (pos == NULL)
+ goto err;
*pos = os;
r = 1;
@@ -543,19 +624,24 @@ CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
}
-CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
- const EVP_CIPHER *cipher, unsigned int flags)
+CMS_ContentInfo *CMS_encrypt_ex(STACK_OF(X509) *certs, BIO *data,
+ const EVP_CIPHER *cipher, unsigned int flags,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
CMS_ContentInfo *cms;
int i;
X509 *recip;
- cms = CMS_EnvelopedData_create(cipher);
- if (!cms)
+
+
+ cms = (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)
+ ? CMS_AuthEnvelopedData_create_ex(cipher, libctx, propq)
+ : CMS_EnvelopedData_create_ex(cipher, libctx, propq);
+ if (cms == NULL)
goto merr;
for (i = 0; i < sk_X509_num(certs); i++) {
recip = sk_X509_value(certs, i);
if (!CMS_add1_recipient_cert(cms, recip, flags)) {
- CMSerr(CMS_F_CMS_ENCRYPT, CMS_R_RECIPIENT_ERROR);
+ ERR_raise(ERR_LIB_CMS, CMS_R_RECIPIENT_ERROR);
goto err;
}
}
@@ -570,25 +656,34 @@ CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
goto err;
merr:
- CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
err:
CMS_ContentInfo_free(cms);
return NULL;
}
-static int cms_kari_set1_pkey(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
- EVP_PKEY *pk, X509 *cert)
+CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
+ const EVP_CIPHER *cipher, unsigned int flags)
+{
+ return CMS_encrypt_ex(certs, data, cipher, flags, NULL, NULL);
+}
+
+static int cms_kari_set1_pkey_and_peer(CMS_ContentInfo *cms,
+ CMS_RecipientInfo *ri,
+ EVP_PKEY *pk, X509 *cert, X509 *peer)
{
int i;
STACK_OF(CMS_RecipientEncryptedKey) *reks;
CMS_RecipientEncryptedKey *rek;
+
reks = CMS_RecipientInfo_kari_get0_reks(ri);
for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
int rv;
+
rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
if (cert != NULL && CMS_RecipientEncryptedKey_cert_cmp(rek, cert))
continue;
- CMS_RecipientInfo_kari_set0_pkey(ri, pk);
+ CMS_RecipientInfo_kari_set0_pkey_and_peer(ri, pk, peer);
rv = CMS_RecipientInfo_kari_decrypt(cms, ri, rek);
CMS_RecipientInfo_kari_set0_pkey(ri, NULL);
if (rv > 0)
@@ -600,27 +695,37 @@ static int cms_kari_set1_pkey(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
{
+ return CMS_decrypt_set1_pkey_and_peer(cms, pk, cert, NULL);
+}
+
+int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk,
+ X509 *cert, X509 *peer)
+{
STACK_OF(CMS_RecipientInfo) *ris;
CMS_RecipientInfo *ri;
- int i, r, ri_type;
+ int i, r, cms_pkey_ri_type;
int debug = 0, match_ri = 0;
+
ris = CMS_get0_RecipientInfos(cms);
- if (ris)
- debug = cms->d.envelopedData->encryptedContentInfo->debug;
- ri_type = cms_pkey_get_ri_type(pk);
- if (ri_type == CMS_RECIPINFO_NONE) {
- CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
- CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
- return 0;
+ if (ris != NULL)
+ debug = ossl_cms_get0_env_enc_content(cms)->debug;
+
+ cms_pkey_ri_type = ossl_cms_pkey_get_ri_type(pk);
+ if (cms_pkey_ri_type == CMS_RECIPINFO_NONE) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+ return 0;
}
for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
+ int ri_type;
+
ri = sk_CMS_RecipientInfo_value(ris, i);
- if (CMS_RecipientInfo_type(ri) != ri_type)
+ ri_type = CMS_RecipientInfo_type(ri);
+ if (!ossl_cms_pkey_is_ri_type_supported(pk, ri_type))
continue;
match_ri = 1;
if (ri_type == CMS_RECIPINFO_AGREE) {
- r = cms_kari_set1_pkey(cms, ri, pk, cert);
+ r = cms_kari_set1_pkey_and_peer(cms, ri, pk, cert, peer);
if (r > 0)
return 1;
if (r < 0)
@@ -630,12 +735,12 @@ int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
* If we have a cert try matching RecipientInfo otherwise try them
* all.
*/
- else if (!cert || !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) {
+ else if (cert == NULL|| !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) {
EVP_PKEY_up_ref(pk);
CMS_RecipientInfo_set0_pkey(ri, pk);
r = CMS_RecipientInfo_decrypt(cms, ri);
CMS_RecipientInfo_set0_pkey(ri, NULL);
- if (cert) {
+ if (cert != NULL) {
/*
* If not debugging clear any error and return success to
* avoid leaking of information useful to MMA
@@ -646,7 +751,7 @@ int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
}
if (r > 0)
return 1;
- CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_DECRYPT_ERROR);
+ ERR_raise(ERR_LIB_CMS, CMS_R_DECRYPT_ERROR);
return 0;
}
/*
@@ -654,17 +759,20 @@ int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
* successful decrypt. Always attempt to decrypt all recipients
* to avoid leaking timing of a successful decrypt.
*/
- else if (r > 0 && debug)
+ else if (r > 0 && (debug || cms_pkey_ri_type != CMS_RECIPINFO_TRANS))
return 1;
}
}
/* If no cert, key transport and not debugging always return success */
- if (cert == NULL && ri_type == CMS_RECIPINFO_TRANS && match_ri && !debug) {
+ if (cert == NULL
+ && cms_pkey_ri_type == CMS_RECIPINFO_TRANS
+ && match_ri
+ && !debug) {
ERR_clear_error();
return 1;
}
- CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
return 0;
}
@@ -676,6 +784,7 @@ int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
STACK_OF(CMS_RecipientInfo) *ris;
CMS_RecipientInfo *ri;
int i, r;
+
ris = CMS_get0_RecipientInfos(cms);
for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
ri = sk_CMS_RecipientInfo_value(ris, i);
@@ -686,21 +795,21 @@ int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
* If we have an id try matching RecipientInfo otherwise try them
* all.
*/
- if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) {
+ if (id == NULL || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) {
CMS_RecipientInfo_set0_key(ri, key, keylen);
r = CMS_RecipientInfo_decrypt(cms, ri);
CMS_RecipientInfo_set0_key(ri, NULL, 0);
if (r > 0)
return 1;
- if (id) {
- CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_DECRYPT_ERROR);
+ if (id != NULL) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_DECRYPT_ERROR);
return 0;
}
ERR_clear_error();
}
}
- CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
return 0;
}
@@ -711,6 +820,7 @@ int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
STACK_OF(CMS_RecipientInfo) *ris;
CMS_RecipientInfo *ri;
int i, r;
+
ris = CMS_get0_RecipientInfos(cms);
for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
ri = sk_CMS_RecipientInfo_value(ris, i);
@@ -723,7 +833,7 @@ int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
return 1;
}
- CMSerr(CMS_F_CMS_DECRYPT_SET1_PASSWORD, CMS_R_NO_MATCHING_RECIPIENT);
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
return 0;
}
@@ -733,26 +843,30 @@ int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
{
int r;
BIO *cont;
- if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped) {
- CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA);
+
+ int nid = OBJ_obj2nid(CMS_get0_type(cms));
+
+ if (nid != NID_pkcs7_enveloped
+ && nid != NID_id_smime_ct_authEnvelopedData) {
+ ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_ENVELOPED_DATA);
return 0;
}
- if (!dcont && !check_content(cms))
+ if (dcont == NULL && !check_content(cms))
return 0;
if (flags & CMS_DEBUG_DECRYPT)
- cms->d.envelopedData->encryptedContentInfo->debug = 1;
+ ossl_cms_get0_env_enc_content(cms)->debug = 1;
else
- cms->d.envelopedData->encryptedContentInfo->debug = 0;
- if (!cert)
- cms->d.envelopedData->encryptedContentInfo->havenocert = 1;
+ ossl_cms_get0_env_enc_content(cms)->debug = 0;
+ if (cert == NULL)
+ ossl_cms_get0_env_enc_content(cms)->havenocert = 1;
else
- cms->d.envelopedData->encryptedContentInfo->havenocert = 0;
- if (!pk && !cert && !dcont && !out)
+ ossl_cms_get0_env_enc_content(cms)->havenocert = 0;
+ if (pk == NULL && cert == NULL && dcont == NULL && out == NULL)
return 1;
- if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
+ if (pk != NULL && !CMS_decrypt_set1_pkey(cms, pk, cert))
return 0;
cont = CMS_dataInit(cms, dcont);
- if (!cont)
+ if (cont == NULL)
return 0;
r = cms_copy_content(out, cont, flags);
do_free_upto(cont, dcont);
@@ -765,22 +879,24 @@ int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
int ret = 0;
if ((cmsbio = CMS_dataInit(cms, dcont)) == NULL) {
- CMSerr(CMS_F_CMS_FINAL, CMS_R_CMS_LIB);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CMS_LIB);
return 0;
}
- SMIME_crlf_copy(data, cmsbio, flags);
+ if (!SMIME_crlf_copy(data, cmsbio, flags)) {
+ goto err;
+ }
(void)BIO_flush(cmsbio);
if (!CMS_dataFinal(cms, cmsbio)) {
- CMSerr(CMS_F_CMS_FINAL, CMS_R_CMS_DATAFINAL_ERROR);
+ ERR_raise(ERR_LIB_CMS, CMS_R_CMS_DATAFINAL_ERROR);
goto err;
}
ret = 1;
- err:
+err:
do_free_upto(cmsbio, dcont);
return ret;
@@ -794,16 +910,17 @@ int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
{
BIO *cont;
int r;
+
if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData) {
- CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_TYPE_NOT_COMPRESSED_DATA);
+ ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_COMPRESSED_DATA);
return 0;
}
- if (!dcont && !check_content(cms))
+ if (dcont == NULL && !check_content(cms))
return 0;
cont = CMS_dataInit(cms, dcont);
- if (!cont)
+ if (cont == NULL)
return 0;
r = cms_copy_content(out, cont, flags);
do_free_upto(cont, dcont);
@@ -813,10 +930,11 @@ int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
{
CMS_ContentInfo *cms;
+
if (comp_nid <= 0)
comp_nid = NID_zlib_compression;
- cms = cms_CompressedData_create(comp_nid);
- if (!cms)
+ cms = ossl_cms_CompressedData_create(comp_nid, NULL, NULL);
+ if (cms == NULL)
return NULL;
if (!(flags & CMS_DETACHED))
@@ -834,13 +952,13 @@ CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
unsigned int flags)
{
- CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
return 0;
}
CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
{
- CMSerr(CMS_F_CMS_COMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+ ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
return NULL;
}
diff --git a/crypto/comp/c_zlib.c b/crypto/comp/c_zlib.c
index b81933791312..9a7087e44404 100644
--- a/crypto/comp/c_zlib.c
+++ b/crypto/comp/c_zlib.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -15,6 +15,7 @@
#include <openssl/err.h>
#include "crypto/cryptlib.h"
#include "internal/bio.h"
+#include "internal/thread_once.h"
#include "comp_local.h"
COMP_METHOD *COMP_zlib(void);
@@ -102,7 +103,6 @@ static deflate_ft p_deflate = NULL;
static deflateInit__ft p_deflateInit_ = NULL;
static zError__ft p_zError = NULL;
-static int zlib_loaded = 0; /* only attempt to init func pts once */
static DSO *zlib_dso = NULL;
# define compress p_compress
@@ -204,62 +204,59 @@ static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
return olen - state->istream.avail_out;
}
-#endif
-
-COMP_METHOD *COMP_zlib(void)
+static CRYPTO_ONCE zlib_once = CRYPTO_ONCE_STATIC_INIT;
+DEFINE_RUN_ONCE_STATIC(ossl_comp_zlib_init)
{
- COMP_METHOD *meth = &zlib_method_nozlib;
-
-#ifdef ZLIB_SHARED
+# ifdef ZLIB_SHARED
/* LIBZ may be externally defined, and we should respect that value */
-# ifndef LIBZ
-# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
-# define LIBZ "ZLIB1"
-# elif defined(OPENSSL_SYS_VMS)
-# define LIBZ "LIBZ"
-# else
-# define LIBZ "z"
+# ifndef LIBZ
+# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
+# define LIBZ "ZLIB1"
+# elif defined(OPENSSL_SYS_VMS)
+# define LIBZ "LIBZ"
+# else
+# define LIBZ "z"
+# endif
# endif
-# endif
- if (!zlib_loaded) {
- zlib_dso = DSO_load(NULL, LIBZ, NULL, 0);
- if (zlib_dso != NULL) {
- p_compress = (compress_ft) DSO_bind_func(zlib_dso, "compress");
- p_inflateEnd
- = (inflateEnd_ft) DSO_bind_func(zlib_dso, "inflateEnd");
- p_inflate = (inflate_ft) DSO_bind_func(zlib_dso, "inflate");
- p_inflateInit_
- = (inflateInit__ft) DSO_bind_func(zlib_dso, "inflateInit_");
- p_deflateEnd
- = (deflateEnd_ft) DSO_bind_func(zlib_dso, "deflateEnd");
- p_deflate = (deflate_ft) DSO_bind_func(zlib_dso, "deflate");
- p_deflateInit_
- = (deflateInit__ft) DSO_bind_func(zlib_dso, "deflateInit_");
- p_zError = (zError__ft) DSO_bind_func(zlib_dso, "zError");
-
- if (p_compress && p_inflateEnd && p_inflate
- && p_inflateInit_ && p_deflateEnd
- && p_deflate && p_deflateInit_ && p_zError)
- zlib_loaded++;
-
- if (!OPENSSL_init_crypto(OPENSSL_INIT_ZLIB, NULL)) {
- comp_zlib_cleanup_int();
- return meth;
- }
- if (zlib_loaded)
- meth = &zlib_stateful_method;
+ zlib_dso = DSO_load(NULL, LIBZ, NULL, 0);
+ if (zlib_dso != NULL) {
+ p_compress = (compress_ft) DSO_bind_func(zlib_dso, "compress");
+ p_inflateEnd = (inflateEnd_ft) DSO_bind_func(zlib_dso, "inflateEnd");
+ p_inflate = (inflate_ft) DSO_bind_func(zlib_dso, "inflate");
+ p_inflateInit_ = (inflateInit__ft) DSO_bind_func(zlib_dso, "inflateInit_");
+ p_deflateEnd = (deflateEnd_ft) DSO_bind_func(zlib_dso, "deflateEnd");
+ p_deflate = (deflate_ft) DSO_bind_func(zlib_dso, "deflate");
+ p_deflateInit_ = (deflateInit__ft) DSO_bind_func(zlib_dso, "deflateInit_");
+ p_zError = (zError__ft) DSO_bind_func(zlib_dso, "zError");
+
+ if (p_compress == NULL || p_inflateEnd == NULL
+ || p_inflate == NULL || p_inflateInit_ == NULL
+ || p_deflateEnd == NULL || p_deflate == NULL
+ || p_deflateInit_ == NULL || p_zError == NULL) {
+ ossl_comp_zlib_cleanup();
+ return 0;
}
}
+# endif
+ return 1;
+}
#endif
-#if defined(ZLIB)
- meth = &zlib_stateful_method;
+
+COMP_METHOD *COMP_zlib(void)
+{
+ COMP_METHOD *meth = &zlib_method_nozlib;
+
+#ifdef ZLIB
+ if (RUN_ONCE(&zlib_once, ossl_comp_zlib_init))
+ meth = &zlib_stateful_method;
#endif
return meth;
}
-void comp_zlib_cleanup_int(void)
+/* Also called from OPENSSL_cleanup() */
+void ossl_comp_zlib_cleanup(void)
{
#ifdef ZLIB_SHARED
DSO_free(zlib_dso);
@@ -296,10 +293,8 @@ static long bio_zlib_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp);
static const BIO_METHOD bio_meth_zlib = {
BIO_TYPE_COMP,
"zlib",
- /* TODO: Convert to new style write function */
bwrite_conv,
bio_zlib_write,
- /* TODO: Convert to new style read function */
bread_conv,
bio_zlib_read,
NULL, /* bio_zlib_puts, */
@@ -318,16 +313,16 @@ const BIO_METHOD *BIO_f_zlib(void)
static int bio_zlib_new(BIO *bi)
{
BIO_ZLIB_CTX *ctx;
+
# ifdef ZLIB_SHARED
- (void)COMP_zlib();
- if (!zlib_loaded) {
- COMPerr(COMP_F_BIO_ZLIB_NEW, COMP_R_ZLIB_NOT_SUPPORTED);
+ if (!RUN_ONCE(&zlib_once, ossl_comp_zlib_init)) {
+ ERR_raise(ERR_LIB_COMP, COMP_R_ZLIB_NOT_SUPPORTED);
return 0;
}
# endif
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL) {
- COMPerr(COMP_F_BIO_ZLIB_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_COMP, ERR_R_MALLOC_FAILURE);
return 0;
}
ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE;
@@ -346,6 +341,7 @@ static int bio_zlib_new(BIO *bi)
static int bio_zlib_free(BIO *bi)
{
BIO_ZLIB_CTX *ctx;
+
if (!bi)
return 0;
ctx = BIO_get_data(bi);
@@ -381,10 +377,14 @@ static int bio_zlib_read(BIO *b, char *out, int outl)
if (!ctx->ibuf) {
ctx->ibuf = OPENSSL_malloc(ctx->ibufsize);
if (ctx->ibuf == NULL) {
- COMPerr(COMP_F_BIO_ZLIB_READ, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_COMP, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if ((ret = inflateInit(zin)) != Z_OK) {
+ ERR_raise_data(ERR_LIB_COMP, COMP_R_ZLIB_INFLATE_ERROR,
+ "zlib error: %s", zError(ret));
return 0;
}
- inflateInit(zin);
zin->next_in = ctx->ibuf;
zin->avail_in = 0;
}
@@ -397,8 +397,8 @@ static int bio_zlib_read(BIO *b, char *out, int outl)
while (zin->avail_in) {
ret = inflate(zin, 0);
if ((ret != Z_OK) && (ret != Z_STREAM_END)) {
- COMPerr(COMP_F_BIO_ZLIB_READ, COMP_R_ZLIB_INFLATE_ERROR);
- ERR_add_error_data(2, "zlib error:", zError(ret));
+ ERR_raise_data(ERR_LIB_COMP, COMP_R_ZLIB_INFLATE_ERROR,
+ "zlib error: %s", zError(ret));
return 0;
}
/* If EOF or we've read everything then return */
@@ -442,12 +442,16 @@ static int bio_zlib_write(BIO *b, const char *in, int inl)
ctx->obuf = OPENSSL_malloc(ctx->obufsize);
/* Need error here */
if (ctx->obuf == NULL) {
- COMPerr(COMP_F_BIO_ZLIB_WRITE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_COMP, ERR_R_MALLOC_FAILURE);
return 0;
}
ctx->optr = ctx->obuf;
ctx->ocount = 0;
- deflateInit(zout, ctx->comp_level);
+ if ((ret = deflateInit(zout, ctx->comp_level)) != Z_OK) {
+ ERR_raise_data(ERR_LIB_COMP, COMP_R_ZLIB_DEFLATE_ERROR,
+ "zlib error: %s", zError(ret));
+ return 0;
+ }
zout->next_out = ctx->obuf;
zout->avail_out = ctx->obufsize;
}
@@ -483,8 +487,8 @@ static int bio_zlib_write(BIO *b, const char *in, int inl)
/* Compress some more */
ret = deflate(zout, 0);
if (ret != Z_OK) {
- COMPerr(COMP_F_BIO_ZLIB_WRITE, COMP_R_ZLIB_DEFLATE_ERROR);
- ERR_add_error_data(2, "zlib error:", zError(ret));
+ ERR_raise_data(ERR_LIB_COMP, COMP_R_ZLIB_DEFLATE_ERROR,
+ "zlib error: %s", zError(ret));
return 0;
}
ctx->ocount = ctx->obufsize - zout->avail_out;
@@ -532,8 +536,8 @@ static int bio_zlib_flush(BIO *b)
if (ret == Z_STREAM_END)
ctx->odone = 1;
else if (ret != Z_OK) {
- COMPerr(COMP_F_BIO_ZLIB_FLUSH, COMP_R_ZLIB_DEFLATE_ERROR);
- ERR_add_error_data(2, "zlib error:", zError(ret));
+ ERR_raise_data(ERR_LIB_COMP, COMP_R_ZLIB_DEFLATE_ERROR,
+ "zlib error: %s", zError(ret));
return 0;
}
ctx->ocount = ctx->obufsize - zout->avail_out;
@@ -632,6 +636,7 @@ static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr)
static long bio_zlib_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
BIO *next = BIO_next(b);
+
if (next == NULL)
return 0;
return BIO_callback_ctrl(next, cmd, fp);
diff --git a/crypto/comp/comp_err.c b/crypto/comp/comp_err.c
index 2dca315cf1d3..70a6eea0f052 100644
--- a/crypto/comp/comp_err.c
+++ b/crypto/comp/comp_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,17 +10,11 @@
#include <openssl/err.h>
#include <openssl/comperr.h>
+#include "crypto/comperr.h"
-#ifndef OPENSSL_NO_ERR
+#ifndef OPENSSL_NO_COMP
-static const ERR_STRING_DATA COMP_str_functs[] = {
- {ERR_PACK(ERR_LIB_COMP, COMP_F_BIO_ZLIB_FLUSH, 0), "bio_zlib_flush"},
- {ERR_PACK(ERR_LIB_COMP, COMP_F_BIO_ZLIB_NEW, 0), "bio_zlib_new"},
- {ERR_PACK(ERR_LIB_COMP, COMP_F_BIO_ZLIB_READ, 0), "bio_zlib_read"},
- {ERR_PACK(ERR_LIB_COMP, COMP_F_BIO_ZLIB_WRITE, 0), "bio_zlib_write"},
- {ERR_PACK(ERR_LIB_COMP, COMP_F_COMP_CTX_NEW, 0), "COMP_CTX_new"},
- {0, NULL}
-};
+# ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA COMP_str_reasons[] = {
{ERR_PACK(ERR_LIB_COMP, 0, COMP_R_ZLIB_DEFLATE_ERROR),
@@ -32,15 +26,16 @@ static const ERR_STRING_DATA COMP_str_reasons[] = {
{0, NULL}
};
-#endif
+# endif
-int ERR_load_COMP_strings(void)
+int ossl_err_load_COMP_strings(void)
{
-#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(COMP_str_functs[0].error) == NULL) {
- ERR_load_strings_const(COMP_str_functs);
+# ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(COMP_str_reasons[0].error) == NULL)
ERR_load_strings_const(COMP_str_reasons);
- }
-#endif
+# endif
return 1;
}
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/crypto/comp/comp_lib.c b/crypto/comp/comp_lib.c
index 56920e1cca51..bf9069d871a4 100644
--- a/crypto/comp/comp_lib.c
+++ b/crypto/comp/comp_lib.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -20,7 +20,7 @@ COMP_CTX *COMP_CTX_new(COMP_METHOD *meth)
COMP_CTX *ret;
if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
- COMPerr(COMP_F_COMP_CTX_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_COMP, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->meth = meth;
diff --git a/crypto/comp/comp_local.h b/crypto/comp/comp_local.h
index aa45fca238da..acf113e31cd0 100644
--- a/crypto/comp/comp_local.h
+++ b/crypto/comp/comp_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/conf/conf_api.c b/crypto/conf/conf_api.c
index 5e57d749ce5e..7a4efe6dbb2b 100644
--- a/crypto/conf/conf_api.c
+++ b/crypto/conf/conf_api.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -15,34 +15,31 @@
#include <string.h>
#include <openssl/conf.h>
#include <openssl/conf_api.h>
+#include "conf_local.h"
static void value_free_hash(const CONF_VALUE *a, LHASH_OF(CONF_VALUE) *conf);
static void value_free_stack_doall(CONF_VALUE *a);
-/* Up until OpenSSL 0.9.5a, this was get_section */
CONF_VALUE *_CONF_get_section(const CONF *conf, const char *section)
{
- CONF_VALUE *v, vv;
+ CONF_VALUE vv;
- if ((conf == NULL) || (section == NULL))
+ if (conf == NULL || section == NULL)
return NULL;
vv.name = NULL;
vv.section = (char *)section;
- v = lh_CONF_VALUE_retrieve(conf->data, &vv);
- return v;
+ return conf->data != NULL ? lh_CONF_VALUE_retrieve(conf->data, &vv) : NULL;
}
-/* Up until OpenSSL 0.9.5a, this was CONF_get_section */
STACK_OF(CONF_VALUE) *_CONF_get_section_values(const CONF *conf,
const char *section)
{
CONF_VALUE *v;
v = _CONF_get_section(conf, section);
- if (v != NULL)
- return ((STACK_OF(CONF_VALUE) *)v->value);
- else
+ if (v == NULL)
return NULL;
+ return ((STACK_OF(CONF_VALUE) *)v->value);
}
int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value)
@@ -53,9 +50,8 @@ int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value)
ts = (STACK_OF(CONF_VALUE) *)section->value;
value->section = section->section;
- if (!sk_CONF_VALUE_push(ts, value)) {
+ if (!sk_CONF_VALUE_push(ts, value))
return 0;
- }
v = lh_CONF_VALUE_insert(conf->data, value);
if (v != NULL) {
@@ -75,28 +71,28 @@ char *_CONF_get_string(const CONF *conf, const char *section,
if (name == NULL)
return NULL;
- if (conf != NULL) {
- if (section != NULL) {
- vv.name = (char *)name;
- vv.section = (char *)section;
- v = lh_CONF_VALUE_retrieve(conf->data, &vv);
- if (v != NULL)
- return v->value;
- if (strcmp(section, "ENV") == 0) {
- p = ossl_safe_getenv(name);
- if (p != NULL)
- return p;
- }
- }
- vv.section = "default";
+ if (conf == NULL)
+ return ossl_safe_getenv(name);
+ if (conf->data == NULL)
+ return NULL;
+ if (section != NULL) {
vv.name = (char *)name;
+ vv.section = (char *)section;
v = lh_CONF_VALUE_retrieve(conf->data, &vv);
if (v != NULL)
return v->value;
- else
- return NULL;
- } else
- return ossl_safe_getenv(name);
+ if (strcmp(section, "ENV") == 0) {
+ p = ossl_safe_getenv(name);
+ if (p != NULL)
+ return p;
+ }
+ }
+ vv.section = "default";
+ vv.name = (char *)name;
+ v = lh_CONF_VALUE_retrieve(conf->data, &vv);
+ if (v == NULL)
+ return NULL;
+ return v->value;
}
static unsigned long conf_value_hash(const CONF_VALUE *v)
@@ -110,24 +106,21 @@ static int conf_value_cmp(const CONF_VALUE *a, const CONF_VALUE *b)
if (a->section != b->section) {
i = strcmp(a->section, b->section);
- if (i)
+ if (i != 0)
return i;
}
- if ((a->name != NULL) && (b->name != NULL)) {
- i = strcmp(a->name, b->name);
- return i;
- } else if (a->name == b->name)
+ if (a->name != NULL && b->name != NULL)
+ return strcmp(a->name, b->name);
+ if (a->name == b->name)
return 0;
- else
- return ((a->name == NULL) ? -1 : 1);
+ return (a->name == NULL) ? -1 : 1;
}
int _CONF_new_data(CONF *conf)
{
- if (conf == NULL) {
+ if (conf == NULL)
return 0;
- }
if (conf->data == NULL) {
conf->data = lh_CONF_VALUE_new(conf_value_hash, conf_value_cmp);
if (conf->data == NULL)
@@ -142,7 +135,11 @@ IMPLEMENT_LHASH_DOALL_ARG_CONST(CONF_VALUE, LH_CONF_VALUE);
void _CONF_free_data(CONF *conf)
{
- if (conf == NULL || conf->data == NULL)
+ if (conf == NULL)
+ return;
+
+ OPENSSL_free(conf->includedir);
+ if (conf->data == NULL)
return;
/* evil thing to make sure the 'OPENSSL_free()' works as expected */
@@ -185,7 +182,6 @@ static void value_free_stack_doall(CONF_VALUE *a)
OPENSSL_free(a);
}
-/* Up until OpenSSL 0.9.5a, this was new_section */
CONF_VALUE *_CONF_new_section(CONF *conf, const char *section)
{
STACK_OF(CONF_VALUE) *sk = NULL;
diff --git a/crypto/conf/conf_def.c b/crypto/conf/conf_def.c
index 31c02cc49e22..b5d6668f4276 100644
--- a/crypto/conf/conf_def.c
+++ b/crypto/conf/conf_def.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,11 +11,17 @@
#include <stdio.h>
#include <string.h>
+#include "e_os.h" /* struct stat */
+#ifdef __TANDEM
+# include <sys/types.h> /* needed for stat.h */
+# include <sys/stat.h> /* struct stat */
+#endif
#include "internal/cryptlib.h"
#include "internal/o_dir.h"
#include <openssl/lhash.h>
#include <openssl/conf.h>
#include <openssl/conf_api.h>
+#include "conf_local.h"
#include "conf_def.h"
#include <openssl/buffer.h>
#include <openssl/err.h>
@@ -23,7 +29,6 @@
# include <sys/stat.h>
# ifdef _WIN32
# define stat _stat
-# define strcasecmp _stricmp
# endif
#endif
@@ -54,7 +59,9 @@ static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx);
static CONF *def_create(CONF_METHOD *meth);
static int def_init_default(CONF *conf);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
static int def_init_WIN32(CONF *conf);
+#endif
static int def_destroy(CONF *conf);
static int def_destroy_data(CONF *conf);
static int def_load(CONF *conf, const char *name, long *eline);
@@ -76,6 +83,12 @@ static CONF_METHOD default_method = {
def_load
};
+CONF_METHOD *NCONF_default(void)
+{
+ return &default_method;
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
static CONF_METHOD WIN32_method = {
"WIN32",
def_create,
@@ -89,15 +102,11 @@ static CONF_METHOD WIN32_method = {
def_load
};
-CONF_METHOD *NCONF_default(void)
-{
- return &default_method;
-}
-
CONF_METHOD *NCONF_WIN32(void)
{
return &WIN32_method;
}
+#endif
static CONF *def_create(CONF_METHOD *meth)
{
@@ -117,24 +126,26 @@ static int def_init_default(CONF *conf)
if (conf == NULL)
return 0;
+ memset(conf, 0, sizeof(*conf));
conf->meth = &default_method;
conf->meth_data = (void *)CONF_type_default;
- conf->data = NULL;
return 1;
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
static int def_init_WIN32(CONF *conf)
{
if (conf == NULL)
return 0;
+ memset(conf, 0, sizeof(*conf));
conf->meth = &WIN32_method;
conf->meth_data = (void *)CONF_type_win32;
- conf->data = NULL;
return 1;
}
+#endif
static int def_destroy(CONF *conf)
{
@@ -165,9 +176,9 @@ static int def_load(CONF *conf, const char *name, long *line)
#endif
if (in == NULL) {
if (ERR_GET_REASON(ERR_peek_last_error()) == BIO_R_NO_SUCH_FILE)
- CONFerr(CONF_F_DEF_LOAD, CONF_R_NO_SUCH_FILE);
+ ERR_raise(ERR_LIB_CONF, CONF_R_NO_SUCH_FILE);
else
- CONFerr(CONF_F_DEF_LOAD, ERR_R_SYS_LIB);
+ ERR_raise(ERR_LIB_CONF, ERR_R_SYS_LIB);
return 0;
}
@@ -177,6 +188,23 @@ static int def_load(CONF *conf, const char *name, long *line)
return ret;
}
+
+/* Parse a boolean value and fill in *flag. Return 0 on error. */
+static int parsebool(const char *pval, int *flag)
+{
+ if (OPENSSL_strcasecmp(pval, "on") == 0
+ || OPENSSL_strcasecmp(pval, "true") == 0) {
+ *flag = 1;
+ } else if (OPENSSL_strcasecmp(pval, "off") == 0
+ || OPENSSL_strcasecmp(pval, "false") == 0) {
+ *flag = 0;
+ } else {
+ ERR_raise(ERR_LIB_CONF, CONF_R_INVALID_PRAGMA);
+ return 0;
+ }
+ return 1;
+}
+
static int def_load_bio(CONF *conf, BIO *in, long *line)
{
/* The macro BUFSIZE conflicts with a system macro in VxWorks */
@@ -200,24 +228,24 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
#endif
if ((buff = BUF_MEM_new()) == NULL) {
- CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_CONF, ERR_R_BUF_LIB);
goto err;
}
section = OPENSSL_strdup("default");
if (section == NULL) {
- CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
if (_CONF_new_data(conf) == 0) {
- CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
sv = _CONF_new_section(conf, section);
if (sv == NULL) {
- CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
+ ERR_raise(ERR_LIB_CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
goto err;
}
@@ -225,13 +253,14 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
again = 0;
for (;;) {
if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) {
- CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_CONF, ERR_R_BUF_LIB);
goto err;
}
p = &(buff->data[bufnum]);
*p = '\0';
read_retry:
- BIO_gets(in, p, CONFBUFSIZE - 1);
+ if (in != NULL && BIO_gets(in, p, CONFBUFSIZE - 1) < 0)
+ goto err;
p[CONFBUFSIZE - 1] = '\0';
ii = i = strlen(p);
if (first_call) {
@@ -248,7 +277,7 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
first_call = 0;
}
if (i == 0 && !again) {
- /* the currently processed BIO is at EOF */
+ /* the currently processed BIO is NULL or at EOF */
BIO *parent;
#ifndef OPENSSL_NO_POSIX_IO
@@ -334,8 +363,7 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
ss = p;
goto again;
}
- CONFerr(CONF_F_DEF_LOAD_BIO,
- CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
+ ERR_raise(ERR_LIB_CONF, CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
goto err;
}
*end = '\0';
@@ -344,8 +372,7 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
if ((sv = _CONF_get_section(conf, section)) == NULL)
sv = _CONF_new_section(conf, section);
if (sv == NULL) {
- CONFerr(CONF_F_DEF_LOAD_BIO,
- CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
+ ERR_raise(ERR_LIB_CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
goto err;
}
continue;
@@ -362,10 +389,61 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
psection = section;
}
p = eat_ws(conf, end);
- if (strncmp(pname, ".include", 8) == 0
+ if (strncmp(pname, ".pragma", 7) == 0
+ && (p != pname + 7 || *p == '=')) {
+ char *pval;
+
+ if (*p == '=') {
+ p++;
+ p = eat_ws(conf, p);
+ }
+ trim_ws(conf, p);
+
+ /* Pragma values take the form keyword:value */
+ pval = strchr(p, ':');
+ if (pval == NULL || pval == p || pval[1] == '\0') {
+ ERR_raise(ERR_LIB_CONF, CONF_R_INVALID_PRAGMA);
+ goto err;
+ }
+
+ *pval++ = '\0';
+ trim_ws(conf, p);
+ pval = eat_ws(conf, pval);
+
+ /*
+ * Known pragmas:
+ *
+ * dollarid takes "on", "true or "off", "false"
+ * abspath takes "on", "true or "off", "false"
+ * includedir directory prefix
+ */
+ if (strcmp(p, "dollarid") == 0) {
+ if (!parsebool(pval, &conf->flag_dollarid))
+ goto err;
+ } else if (strcmp(p, "abspath") == 0) {
+ if (!parsebool(pval, &conf->flag_abspath))
+ goto err;
+ } else if (strcmp(p, "includedir") == 0) {
+ OPENSSL_free(conf->includedir);
+ if ((conf->includedir = OPENSSL_strdup(pval)) == NULL) {
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ /*
+ * We *ignore* any unknown pragma.
+ */
+ continue;
+ } else if (strncmp(pname, ".include", 8) == 0
&& (p != pname + 8 || *p == '=')) {
char *include = NULL;
BIO *next;
+ const char *include_dir = ossl_safe_getenv("OPENSSL_CONF_INCLUDE");
+ char *include_path = NULL;
+
+ if (include_dir == NULL)
+ include_dir = conf->includedir;
if (*p == '=') {
p++;
@@ -374,28 +452,56 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
trim_ws(conf, p);
if (!str_copy(conf, psection, &include, p))
goto err;
+
+ if (include_dir != NULL && !ossl_is_absolute_path(include)) {
+ size_t newlen = strlen(include_dir) + strlen(include) + 2;
+
+ include_path = OPENSSL_malloc(newlen);
+ if (include_path == NULL) {
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(include);
+ goto err;
+ }
+
+ OPENSSL_strlcpy(include_path, include_dir, newlen);
+ if (!ossl_ends_with_dirsep(include_path))
+ OPENSSL_strlcat(include_path, "/", newlen);
+ OPENSSL_strlcat(include_path, include, newlen);
+ OPENSSL_free(include);
+ } else {
+ include_path = include;
+ }
+
+ if (conf->flag_abspath
+ && !ossl_is_absolute_path(include_path)) {
+ ERR_raise(ERR_LIB_CONF, CONF_R_RELATIVE_PATH);
+ OPENSSL_free(include_path);
+ goto err;
+ }
+
/* get the BIO of the included file */
#ifndef OPENSSL_NO_POSIX_IO
- next = process_include(include, &dirctx, &dirpath);
- if (include != dirpath) {
+ next = process_include(include_path, &dirctx, &dirpath);
+ if (include_path != dirpath) {
/* dirpath will contain include in case of a directory */
- OPENSSL_free(include);
+ OPENSSL_free(include_path);
}
#else
- next = BIO_new_file(include, "r");
- OPENSSL_free(include);
+ next = BIO_new_file(include_path, "r");
+ OPENSSL_free(include_path);
#endif
+
if (next != NULL) {
/* push the currently processing BIO onto stack */
if (biosk == NULL) {
if ((biosk = sk_BIO_new_null()) == NULL) {
- CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
BIO_free(next);
goto err;
}
}
if (!sk_BIO_push(biosk, in)) {
- CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
BIO_free(next);
goto err;
}
@@ -404,7 +510,8 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
}
continue;
} else if (*p != '=') {
- CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_MISSING_EQUAL_SIGN);
+ ERR_raise_data(ERR_LIB_CONF, CONF_R_MISSING_EQUAL_SIGN,
+ "HERE-->%s", p);
goto err;
}
*end = '\0';
@@ -413,13 +520,13 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
trim_ws(conf, start);
if ((v = OPENSSL_malloc(sizeof(*v))) == NULL) {
- CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
v->name = OPENSSL_strdup(pname);
v->value = NULL;
if (v->name == NULL) {
- CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!str_copy(conf, psection, &(v->value), start))
@@ -430,14 +537,14 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
== NULL)
tv = _CONF_new_section(conf, psection);
if (tv == NULL) {
- CONFerr(CONF_F_DEF_LOAD_BIO,
- CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
+ ERR_raise(ERR_LIB_CONF,
+ CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
goto err;
}
} else
tv = sv;
if (_CONF_add_string(conf, tv, v) == 0) {
- CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
v = NULL;
@@ -451,6 +558,7 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
*/
sk_BIO_free(biosk);
return 1;
+
err:
BUF_MEM_free(buff);
OPENSSL_free(section);
@@ -581,7 +689,10 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from)
buf->data[to++] = v;
} else if (IS_EOF(conf, *from))
break;
- else if (*from == '$') {
+ else if (*from == '$'
+ && (!conf->flag_dollarid
+ || from[1] == '{'
+ || from[1] == '(')) {
size_t newsize;
/* try to expand it */
@@ -598,7 +709,8 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from)
s++;
cp = section;
e = np = s;
- while (IS_ALNUM(conf, *e))
+ while (IS_ALNUM(conf, *e)
+ || (conf->flag_dollarid && IS_DOLLAR(conf, *e)))
e++;
if ((e[0] == ':') && (e[1] == ':')) {
cp = np;
@@ -607,7 +719,8 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from)
*rrp = '\0';
e += 2;
np = e;
- while (IS_ALNUM(conf, *e))
+ while (IS_ALNUM(conf, *e)
+ || (conf->flag_dollarid && IS_DOLLAR(conf, *e)))
e++;
}
r = *e;
@@ -615,7 +728,7 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from)
rp = e;
if (q) {
if (r != q) {
- CONFerr(CONF_F_STR_COPY, CONF_R_NO_CLOSE_BRACE);
+ ERR_raise(ERR_LIB_CONF, CONF_R_NO_CLOSE_BRACE);
goto err;
}
e++;
@@ -635,16 +748,16 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from)
*rrp = rr;
*rp = r;
if (p == NULL) {
- CONFerr(CONF_F_STR_COPY, CONF_R_VARIABLE_HAS_NO_VALUE);
+ ERR_raise(ERR_LIB_CONF, CONF_R_VARIABLE_HAS_NO_VALUE);
goto err;
}
newsize = strlen(p) + buf->length - (e - from);
if (newsize > MAX_CONF_VALUE_LENGTH) {
- CONFerr(CONF_F_STR_COPY, CONF_R_VARIABLE_EXPANSION_TOO_LONG);
+ ERR_raise(ERR_LIB_CONF, CONF_R_VARIABLE_EXPANSION_TOO_LONG);
goto err;
}
if (!BUF_MEM_grow_clean(buf, newsize)) {
- CONFerr(CONF_F_STR_COPY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
while (*p)
@@ -685,21 +798,19 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from)
static BIO *process_include(char *include, OPENSSL_DIR_CTX **dirctx,
char **dirpath)
{
- struct stat st = { 0 };
+ struct stat st;
BIO *next;
if (stat(include, &st) < 0) {
- SYSerr(SYS_F_STAT, errno);
- ERR_add_error_data(1, include);
+ ERR_raise_data(ERR_LIB_SYS, errno, "calling stat(%s)", include);
/* missing include file is not fatal error */
return NULL;
}
if (S_ISDIR(st.st_mode)) {
if (*dirctx != NULL) {
- CONFerr(CONF_F_PROCESS_INCLUDE,
- CONF_R_RECURSIVE_DIRECTORY_INCLUDE);
- ERR_add_error_data(1, include);
+ ERR_raise_data(ERR_LIB_CONF, CONF_R_RECURSIVE_DIRECTORY_INCLUDE,
+ "%s", include);
return NULL;
}
/* a directory, load its contents */
@@ -728,8 +839,10 @@ static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx)
namelen = strlen(filename);
- if ((namelen > 5 && strcasecmp(filename + namelen - 5, ".conf") == 0)
- || (namelen > 4 && strcasecmp(filename + namelen - 4, ".cnf") == 0)) {
+ if ((namelen > 5
+ && OPENSSL_strcasecmp(filename + namelen - 5, ".conf") == 0)
+ || (namelen > 4
+ && OPENSSL_strcasecmp(filename + namelen - 4, ".cnf") == 0)) {
size_t newlen;
char *newpath;
BIO *bio;
@@ -737,7 +850,7 @@ static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx)
newlen = pathlen + namelen + 2;
newpath = OPENSSL_zalloc(newlen);
if (newpath == NULL) {
- CONFerr(CONF_F_GET_NEXT_FILE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
break;
}
#ifdef OPENSSL_SYS_VMS
@@ -822,7 +935,8 @@ static char *eat_alpha_numeric(CONF *conf, char *p)
p = scan_esc(conf, p);
continue;
}
- if (!IS_ALNUM_PUNCT(conf, *p))
+ if (!(IS_ALNUM_PUNCT(conf, *p)
+ || (conf->flag_dollarid && IS_DOLLAR(conf, *p))))
return p;
p++;
}
diff --git a/crypto/conf/conf_def.h b/crypto/conf/conf_def.h
index 0490236287ac..1f66a58e0923 100644
--- a/crypto/conf/conf_def.h
+++ b/crypto/conf/conf_def.h
@@ -2,8 +2,8 @@
* WARNING: do not edit!
* Generated by crypto/conf/keysets.pl
*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -20,6 +20,7 @@
#define CONF_DQUOTE 1024
#define CONF_COMMENT 128
#define CONF_FCOMMENT 2048
+#define CONF_DOLLAR 4096
#define CONF_EOF 8
#define CONF_ALPHA (CONF_UPPER|CONF_LOWER)
#define CONF_ALNUM (CONF_ALPHA|CONF_NUMBER|CONF_UNDER)
@@ -36,13 +37,14 @@
#define IS_ALNUM_PUNCT(conf,c) is_keytype(conf, c, CONF_ALNUM_PUNCT)
#define IS_QUOTE(conf,c) is_keytype(conf, c, CONF_QUOTE)
#define IS_DQUOTE(conf,c) is_keytype(conf, c, CONF_DQUOTE)
+#define IS_DOLLAR(conf,c) is_keytype(conf, c, CONF_DOLLAR)
static const unsigned short CONF_type_default[128] = {
0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0010, 0x0010, 0x0000, 0x0000, 0x0010, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0010, 0x0200, 0x0040, 0x0080, 0x0000, 0x0200, 0x0200, 0x0040,
+ 0x0010, 0x0200, 0x0040, 0x0080, 0x1000, 0x0200, 0x0200, 0x0040,
0x0000, 0x0000, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0000, 0x0200, 0x0000, 0x0000, 0x0000, 0x0200,
@@ -56,12 +58,13 @@ static const unsigned short CONF_type_default[128] = {
0x0004, 0x0004, 0x0004, 0x0000, 0x0200, 0x0000, 0x0200, 0x0000,
};
+#ifndef OPENSSL_NO_DEPRECATED_3_0
static const unsigned short CONF_type_win32[128] = {
0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0010, 0x0010, 0x0000, 0x0000, 0x0010, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0010, 0x0200, 0x0400, 0x0000, 0x0000, 0x0200, 0x0200, 0x0000,
+ 0x0010, 0x0200, 0x0400, 0x0000, 0x1000, 0x0200, 0x0200, 0x0000,
0x0000, 0x0000, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0000, 0x0A00, 0x0000, 0x0000, 0x0000, 0x0200,
@@ -74,3 +77,4 @@ static const unsigned short CONF_type_win32[128] = {
0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
0x0004, 0x0004, 0x0004, 0x0000, 0x0200, 0x0000, 0x0200, 0x0000,
};
+#endif
diff --git a/crypto/conf/conf_err.c b/crypto/conf/conf_err.c
index f7613584ec3e..68ee90b97055 100644
--- a/crypto/conf/conf_err.c
+++ b/crypto/conf/conf_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,41 +10,17 @@
#include <openssl/err.h>
#include <openssl/conferr.h>
+#include "crypto/conferr.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA CONF_str_functs[] = {
- {ERR_PACK(ERR_LIB_CONF, CONF_F_CONF_DUMP_FP, 0), "CONF_dump_fp"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_CONF_LOAD, 0), "CONF_load"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_CONF_LOAD_FP, 0), "CONF_load_fp"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_CONF_PARSE_LIST, 0), "CONF_parse_list"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_DEF_LOAD, 0), "def_load"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_DEF_LOAD_BIO, 0), "def_load_bio"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_GET_NEXT_FILE, 0), "get_next_file"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_MODULE_ADD, 0), "module_add"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_MODULE_INIT, 0), "module_init"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_MODULE_LOAD_DSO, 0), "module_load_dso"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_MODULE_RUN, 0), "module_run"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_DUMP_BIO, 0), "NCONF_dump_bio"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_DUMP_FP, 0), "NCONF_dump_fp"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_GET_NUMBER_E, 0),
- "NCONF_get_number_e"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_GET_SECTION, 0), "NCONF_get_section"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_GET_STRING, 0), "NCONF_get_string"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_LOAD, 0), "NCONF_load"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_LOAD_BIO, 0), "NCONF_load_bio"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_LOAD_FP, 0), "NCONF_load_fp"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_NEW, 0), "NCONF_new"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_PROCESS_INCLUDE, 0), "process_include"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_SSL_MODULE_INIT, 0), "ssl_module_init"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_STR_COPY, 0), "str_copy"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA CONF_str_reasons[] = {
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_ERROR_LOADING_DSO), "error loading dso"},
+ {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_INVALID_PRAGMA), "invalid pragma"},
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_LIST_CANNOT_BE_NULL),
"list cannot be null"},
+ {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_MANDATORY_BRACES_IN_VARIABLE_EXPANSION),
+ "mandatory braces in variable expansion"},
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_MISSING_CLOSE_SQUARE_BRACKET),
"missing close square bracket"},
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_MISSING_EQUAL_SIGN),
@@ -61,8 +37,11 @@ static const ERR_STRING_DATA CONF_str_reasons[] = {
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_SUCH_FILE), "no such file"},
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_VALUE), "no value"},
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NUMBER_TOO_LARGE), "number too large"},
+ {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_OPENSSL_CONF_REFERENCES_MISSING_SECTION),
+ "openssl conf references missing section"},
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_RECURSIVE_DIRECTORY_INCLUDE),
"recursive directory include"},
+ {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_RELATIVE_PATH), "relative path"},
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_SSL_COMMAND_SECTION_EMPTY),
"ssl command section empty"},
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_SSL_COMMAND_SECTION_NOT_FOUND),
@@ -83,13 +62,11 @@ static const ERR_STRING_DATA CONF_str_reasons[] = {
#endif
-int ERR_load_CONF_strings(void)
+int ossl_err_load_CONF_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(CONF_str_functs[0].error) == NULL) {
- ERR_load_strings_const(CONF_str_functs);
+ if (ERR_reason_error_string(CONF_str_reasons[0].error) == NULL)
ERR_load_strings_const(CONF_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/conf/conf_lib.c b/crypto/conf/conf_lib.c
index add1dfa1c181..a2360035257a 100644
--- a/crypto/conf/conf_lib.c
+++ b/crypto/conf/conf_lib.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -16,6 +16,7 @@
#include <openssl/err.h>
#include <openssl/conf.h>
#include <openssl/conf_api.h>
+#include "conf_local.h"
#include <openssl/lhash.h>
static CONF_METHOD *default_CONF_method = NULL;
@@ -54,7 +55,7 @@ LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file,
in = BIO_new_file(file, "rb");
#endif
if (in == NULL) {
- CONFerr(CONF_F_CONF_LOAD, ERR_R_SYS_LIB);
+ ERR_raise(ERR_LIB_CONF, ERR_R_SYS_LIB);
return NULL;
}
@@ -71,7 +72,7 @@ LHASH_OF(CONF_VALUE) *CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp,
BIO *btmp;
LHASH_OF(CONF_VALUE) *ltmp;
if ((btmp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
- CONFerr(CONF_F_CONF_LOAD_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_CONF, ERR_R_BUF_LIB);
return NULL;
}
ltmp = CONF_load_bio(conf, btmp, eline);
@@ -101,6 +102,7 @@ STACK_OF(CONF_VALUE) *CONF_get_section(LHASH_OF(CONF_VALUE) *conf,
return NULL;
} else {
CONF ctmp;
+
CONF_set_nconf(&ctmp, conf);
return NCONF_get_section(&ctmp, section);
}
@@ -113,6 +115,7 @@ char *CONF_get_string(LHASH_OF(CONF_VALUE) *conf, const char *group,
return NCONF_get_string(NULL, group, name);
} else {
CONF ctmp;
+
CONF_set_nconf(&ctmp, conf);
return NCONF_get_string(&ctmp, group, name);
}
@@ -129,6 +132,7 @@ long CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group,
status = NCONF_get_number_e(NULL, group, name, &result);
} else {
CONF ctmp;
+
CONF_set_nconf(&ctmp, conf);
status = NCONF_get_number_e(&ctmp, group, name, &result);
}
@@ -150,7 +154,7 @@ int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out)
int ret;
if ((btmp = BIO_new_fp(out, BIO_NOCLOSE)) == NULL) {
- CONFerr(CONF_F_CONF_DUMP_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_CONF, ERR_R_BUF_LIB);
return 0;
}
ret = CONF_dump_bio(conf, btmp);
@@ -162,6 +166,7 @@ int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out)
int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out)
{
CONF ctmp;
+
CONF_set_nconf(&ctmp, conf);
return NCONF_dump_bio(&ctmp, out);
}
@@ -174,7 +179,7 @@ int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out)
* the "CONF classic" functions, for consistency.
*/
-CONF *NCONF_new(CONF_METHOD *meth)
+CONF *NCONF_new_ex(OSSL_LIB_CTX *libctx, CONF_METHOD *meth)
{
CONF *ret;
@@ -183,13 +188,19 @@ CONF *NCONF_new(CONF_METHOD *meth)
ret = meth->create(meth);
if (ret == NULL) {
- CONFerr(CONF_F_NCONF_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
return NULL;
}
+ ret->libctx = libctx;
return ret;
}
+CONF *NCONF_new(CONF_METHOD *meth)
+{
+ return NCONF_new_ex(NULL, meth);
+}
+
void NCONF_free(CONF *conf)
{
if (conf == NULL)
@@ -204,10 +215,42 @@ void NCONF_free_data(CONF *conf)
conf->meth->destroy_data(conf);
}
+OSSL_LIB_CTX *NCONF_get0_libctx(const CONF *conf)
+{
+ return conf->libctx;
+}
+
+typedef STACK_OF(OPENSSL_CSTRING) SECTION_NAMES;
+
+IMPLEMENT_LHASH_DOALL_ARG_CONST(CONF_VALUE, SECTION_NAMES);
+
+static void collect_section_name(const CONF_VALUE *v, SECTION_NAMES *names)
+{
+ /* A section is a CONF_VALUE with name == NULL */
+ if (v->name == NULL)
+ sk_OPENSSL_CSTRING_push(names, v->section);
+}
+
+static int section_name_cmp(OPENSSL_CSTRING const *a, OPENSSL_CSTRING const *b)
+{
+ return strcmp(*a, *b);
+}
+
+STACK_OF(OPENSSL_CSTRING) *NCONF_get_section_names(const CONF *cnf)
+{
+ SECTION_NAMES *names;
+
+ if ((names = sk_OPENSSL_CSTRING_new(section_name_cmp)) == NULL)
+ return NULL;
+ lh_CONF_VALUE_doall_SECTION_NAMES(cnf->data, collect_section_name, names);
+ sk_OPENSSL_CSTRING_sort(names);
+ return names;
+}
+
int NCONF_load(CONF *conf, const char *file, long *eline)
{
if (conf == NULL) {
- CONFerr(CONF_F_NCONF_LOAD, CONF_R_NO_CONF);
+ ERR_raise(ERR_LIB_CONF, CONF_R_NO_CONF);
return 0;
}
@@ -220,7 +263,7 @@ int NCONF_load_fp(CONF *conf, FILE *fp, long *eline)
BIO *btmp;
int ret;
if ((btmp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
- CONFerr(CONF_F_NCONF_LOAD_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_CONF, ERR_R_BUF_LIB);
return 0;
}
ret = NCONF_load_bio(conf, btmp, eline);
@@ -232,7 +275,7 @@ int NCONF_load_fp(CONF *conf, FILE *fp, long *eline)
int NCONF_load_bio(CONF *conf, BIO *bp, long *eline)
{
if (conf == NULL) {
- CONFerr(CONF_F_NCONF_LOAD_BIO, CONF_R_NO_CONF);
+ ERR_raise(ERR_LIB_CONF, CONF_R_NO_CONF);
return 0;
}
@@ -242,12 +285,12 @@ int NCONF_load_bio(CONF *conf, BIO *bp, long *eline)
STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf, const char *section)
{
if (conf == NULL) {
- CONFerr(CONF_F_NCONF_GET_SECTION, CONF_R_NO_CONF);
+ ERR_raise(ERR_LIB_CONF, CONF_R_NO_CONF);
return NULL;
}
if (section == NULL) {
- CONFerr(CONF_F_NCONF_GET_SECTION, CONF_R_NO_SECTION);
+ ERR_raise(ERR_LIB_CONF, CONF_R_NO_SECTION);
return NULL;
}
@@ -266,12 +309,11 @@ char *NCONF_get_string(const CONF *conf, const char *group, const char *name)
return s;
if (conf == NULL) {
- CONFerr(CONF_F_NCONF_GET_STRING,
- CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE);
+ ERR_raise(ERR_LIB_CONF, CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE);
return NULL;
}
- CONFerr(CONF_F_NCONF_GET_STRING, CONF_R_NO_VALUE);
- ERR_add_error_data(4, "group=", group, " name=", name);
+ ERR_raise_data(ERR_LIB_CONF, CONF_R_NO_VALUE,
+ "group=%s name=%s", group, name);
return NULL;
}
@@ -294,7 +336,7 @@ int NCONF_get_number_e(const CONF *conf, const char *group, const char *name,
int (*to_int)(const CONF *, char) = &default_to_int;
if (result == NULL) {
- CONFerr(CONF_F_NCONF_GET_NUMBER_E, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_CONF, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
@@ -313,7 +355,7 @@ int NCONF_get_number_e(const CONF *conf, const char *group, const char *name,
const int d = to_int(conf, *str);
if (res > (LONG_MAX - d) / 10L) {
- CONFerr(CONF_F_NCONF_GET_NUMBER_E, CONF_R_NUMBER_TOO_LARGE);
+ ERR_raise(ERR_LIB_CONF, CONF_R_NUMBER_TOO_LARGE);
return 0;
}
res = res * 10 + d;
@@ -323,13 +365,25 @@ int NCONF_get_number_e(const CONF *conf, const char *group, const char *name,
return 1;
}
+long _CONF_get_number(const CONF *conf, const char *section,
+ const char *name)
+{
+ int status;
+ long result = 0;
+
+ ERR_set_mark();
+ status = NCONF_get_number_e(conf, section, name, &result);
+ ERR_pop_to_mark();
+ return status == 0 ? 0L : result;
+}
+
#ifndef OPENSSL_NO_STDIO
int NCONF_dump_fp(const CONF *conf, FILE *out)
{
BIO *btmp;
int ret;
if ((btmp = BIO_new_fp(out, BIO_NOCLOSE)) == NULL) {
- CONFerr(CONF_F_NCONF_DUMP_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_CONF, ERR_R_BUF_LIB);
return 0;
}
ret = NCONF_dump_bio(conf, btmp);
@@ -341,7 +395,7 @@ int NCONF_dump_fp(const CONF *conf, FILE *out)
int NCONF_dump_bio(const CONF *conf, BIO *out)
{
if (conf == NULL) {
- CONFerr(CONF_F_NCONF_DUMP_BIO, CONF_R_NO_CONF);
+ ERR_raise(ERR_LIB_CONF, CONF_R_NO_CONF);
return 0;
}
diff --git a/crypto/conf/conf_local.h b/crypto/conf/conf_local.h
index 6e1f7fe00d70..f3b16f113852 100644
--- a/crypto/conf/conf_local.h
+++ b/crypto/conf/conf_local.h
@@ -1,11 +1,11 @@
/*
- * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-void conf_add_ssl_module(void);
-
+#include <openssl/conftypes.h>
+void ossl_config_add_ssl_module(void);
diff --git a/crypto/conf/conf_mall.c b/crypto/conf/conf_mall.c
index d7eaa8509b2f..bad19c96cca0 100644
--- a/crypto/conf/conf_mall.c
+++ b/crypto/conf/conf_mall.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <stdio.h>
#include <openssl/crypto.h>
#include "internal/cryptlib.h"
@@ -14,6 +17,8 @@
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include <openssl/engine.h>
+#include "internal/provider.h"
+#include "crypto/rand.h"
#include "conf_local.h"
/* Load all OpenSSL builtin modules */
@@ -27,5 +32,7 @@ void OPENSSL_load_builtin_modules(void)
ENGINE_add_conf_module();
#endif
EVP_add_alg_module();
- conf_add_ssl_module();
+ ossl_config_add_ssl_module();
+ ossl_provider_add_conf_module();
+ ossl_random_add_conf_module();
}
diff --git a/crypto/conf/conf_mod.c b/crypto/conf/conf_mod.c
index e703d97f5451..17bbbf7a2747 100644
--- a/crypto/conf/conf_mod.c
+++ b/crypto/conf/conf_mod.c
@@ -1,19 +1,30 @@
/*
- * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "internal/cryptlib.h"
#include <stdio.h>
#include <ctype.h>
#include <openssl/crypto.h>
#include "internal/conf.h"
+#include <openssl/conf_api.h>
#include "internal/dso.h"
+#include "internal/thread_once.h"
#include <openssl/x509.h>
+#include <openssl/trace.h>
+#include <openssl/engine.h>
+#include "conf_local.h"
+
+DEFINE_STACK_OF(CONF_MODULE)
+DEFINE_STACK_OF(CONF_IMODULE)
#define DSO_mod_init_name "OPENSSL_init"
#define DSO_mod_finish_name "OPENSSL_finish"
@@ -51,8 +62,12 @@ struct conf_imodule_st {
void *usr_data;
};
-static STACK_OF(CONF_MODULE) *supported_modules = NULL;
-static STACK_OF(CONF_IMODULE) *initialized_modules = NULL;
+static CRYPTO_ONCE init_module_list_lock = CRYPTO_ONCE_STATIC_INIT;
+static CRYPTO_RWLOCK *module_list_lock = NULL;
+static STACK_OF(CONF_MODULE) *supported_modules = NULL; /* protected by lock */
+static STACK_OF(CONF_IMODULE) *initialized_modules = NULL; /* protected by lock */
+
+static CRYPTO_ONCE load_builtin_modules = CRYPTO_ONCE_STATIC_INIT;
static void module_free(CONF_MODULE *md);
static void module_finish(CONF_IMODULE *imod);
@@ -67,6 +82,36 @@ static int module_init(CONF_MODULE *pmod, const char *name, const char *value,
static CONF_MODULE *module_load_dso(const CONF *cnf, const char *name,
const char *value);
+static int conf_modules_finish_int(void);
+
+static void module_lists_free(void)
+{
+ CRYPTO_THREAD_lock_free(module_list_lock);
+ module_list_lock = NULL;
+
+ sk_CONF_MODULE_free(supported_modules);
+ supported_modules = NULL;
+
+ sk_CONF_IMODULE_free(initialized_modules);
+ initialized_modules = NULL;
+}
+
+DEFINE_RUN_ONCE_STATIC(do_init_module_list_lock)
+{
+ module_list_lock = CRYPTO_THREAD_lock_new();
+ if (module_list_lock == NULL) {
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int conf_diagnostics(const CONF *cnf)
+{
+ return _CONF_get_number(cnf, NULL, "config_diagnostics") != 0;
+}
+
/* Main function: load modules from a CONF structure */
int CONF_modules_load(const CONF *cnf, const char *appname,
@@ -75,12 +120,18 @@ int CONF_modules_load(const CONF *cnf, const char *appname,
STACK_OF(CONF_VALUE) *values;
CONF_VALUE *vl;
char *vsection = NULL;
-
int ret, i;
if (!cnf)
return 1;
+ if (conf_diagnostics(cnf))
+ flags &= ~(CONF_MFLAGS_IGNORE_ERRORS
+ | CONF_MFLAGS_IGNORE_RETURN_CODES
+ | CONF_MFLAGS_SILENT
+ | CONF_MFLAGS_IGNORE_MISSING_FILE);
+
+ ERR_set_mark();
if (appname)
vsection = NCONF_get_string(cnf, NULL, appname);
@@ -88,72 +139,116 @@ int CONF_modules_load(const CONF *cnf, const char *appname,
vsection = NCONF_get_string(cnf, NULL, "openssl_conf");
if (!vsection) {
- ERR_clear_error();
+ ERR_pop_to_mark();
return 1;
}
+ OSSL_TRACE1(CONF, "Configuration in section %s\n", vsection);
values = NCONF_get_section(cnf, vsection);
- if (!values)
+ if (values == NULL) {
+ if (!(flags & CONF_MFLAGS_SILENT)) {
+ ERR_clear_last_mark();
+ ERR_raise_data(ERR_LIB_CONF,
+ CONF_R_OPENSSL_CONF_REFERENCES_MISSING_SECTION,
+ "openssl_conf=%s", vsection);
+ } else {
+ ERR_pop_to_mark();
+ }
return 0;
+ }
+ ERR_pop_to_mark();
for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
vl = sk_CONF_VALUE_value(values, i);
+ ERR_set_mark();
ret = module_run(cnf, vl->name, vl->value, flags);
+ OSSL_TRACE3(CONF, "Running module %s (%s) returned %d\n",
+ vl->name, vl->value, ret);
if (ret <= 0)
- if (!(flags & CONF_MFLAGS_IGNORE_ERRORS))
+ if (!(flags & CONF_MFLAGS_IGNORE_ERRORS)) {
+ ERR_clear_last_mark();
return ret;
+ }
+ ERR_pop_to_mark();
}
return 1;
}
-int CONF_modules_load_file(const char *filename, const char *appname,
- unsigned long flags)
+int CONF_modules_load_file_ex(OSSL_LIB_CTX *libctx, const char *filename,
+ const char *appname, unsigned long flags)
{
char *file = NULL;
CONF *conf = NULL;
- int ret = 0;
- conf = NCONF_new(NULL);
- if (conf == NULL)
- goto err;
+ int ret = 0, diagnostics = 0;
if (filename == NULL) {
file = CONF_get1_default_config_file();
- if (!file)
+ if (file == NULL)
goto err;
- } else
+ } else {
file = (char *)filename;
+ }
+
+ ERR_set_mark();
+ conf = NCONF_new_ex(libctx, NULL);
+ if (conf == NULL)
+ goto err;
if (NCONF_load(conf, file, NULL) <= 0) {
if ((flags & CONF_MFLAGS_IGNORE_MISSING_FILE) &&
(ERR_GET_REASON(ERR_peek_last_error()) == CONF_R_NO_SUCH_FILE)) {
- ERR_clear_error();
ret = 1;
}
goto err;
}
ret = CONF_modules_load(conf, appname, flags);
+ diagnostics = conf_diagnostics(conf);
err:
if (filename == NULL)
OPENSSL_free(file);
NCONF_free(conf);
- if (flags & CONF_MFLAGS_IGNORE_RETURN_CODES)
- return 1;
+ if ((flags & CONF_MFLAGS_IGNORE_RETURN_CODES) != 0 && !diagnostics)
+ ret = 1;
+
+ if (ret > 0)
+ ERR_pop_to_mark();
+ else
+ ERR_clear_last_mark();
return ret;
}
+int CONF_modules_load_file(const char *filename,
+ const char *appname, unsigned long flags)
+{
+ return CONF_modules_load_file_ex(NULL, filename, appname, flags);
+}
+
+DEFINE_RUN_ONCE_STATIC(do_load_builtin_modules)
+{
+ OPENSSL_load_builtin_modules();
+#ifndef OPENSSL_NO_ENGINE
+ /* Need to load ENGINEs */
+ ENGINE_load_builtin_engines();
+#endif
+ return 1;
+}
+
static int module_run(const CONF *cnf, const char *name, const char *value,
unsigned long flags)
{
CONF_MODULE *md;
int ret;
+ if (!RUN_ONCE(&load_builtin_modules, do_load_builtin_modules))
+ return -1;
+
md = module_find(name);
/* Module not found: try to load DSO */
@@ -162,8 +257,8 @@ static int module_run(const CONF *cnf, const char *name, const char *value,
if (!md) {
if (!(flags & CONF_MFLAGS_SILENT)) {
- CONFerr(CONF_F_MODULE_RUN, CONF_R_UNKNOWN_MODULE_NAME);
- ERR_add_error_data(2, "module=", name);
+ ERR_raise_data(ERR_LIB_CONF, CONF_R_UNKNOWN_MODULE_NAME,
+ "module=%s", name);
}
return -1;
}
@@ -171,14 +266,10 @@ static int module_run(const CONF *cnf, const char *name, const char *value,
ret = module_init(md, name, value, cnf);
if (ret <= 0) {
- if (!(flags & CONF_MFLAGS_SILENT)) {
- char rcode[DECIMAL_SIZE(ret) + 1];
-
- CONFerr(CONF_F_MODULE_RUN, CONF_R_MODULE_INITIALIZATION_ERROR);
- BIO_snprintf(rcode, sizeof(rcode), "%-8d", ret);
- ERR_add_error_data(6, "module=", name, ", value=", value,
- ", retcode=", rcode);
- }
+ if (!(flags & CONF_MFLAGS_SILENT))
+ ERR_raise_data(ERR_LIB_CONF, CONF_R_MODULE_INITIALIZATION_ERROR,
+ "module=%s, value=%s retcode=%-8d",
+ name, value, ret);
}
return ret;
@@ -194,19 +285,19 @@ static CONF_MODULE *module_load_dso(const CONF *cnf,
const char *path = NULL;
int errcode = 0;
CONF_MODULE *md;
+
/* Look for alternative path in module section */
- path = NCONF_get_string(cnf, value, "path");
- if (!path) {
- ERR_clear_error();
+ path = _CONF_get_string(cnf, value, "path");
+ if (path == NULL) {
path = name;
}
dso = DSO_load(NULL, path, NULL, 0);
- if (!dso) {
+ if (dso == NULL) {
errcode = CONF_R_ERROR_LOADING_DSO;
goto err;
}
ifunc = (conf_init_func *)DSO_bind_func(dso, DSO_mod_init_name);
- if (!ifunc) {
+ if (ifunc == NULL) {
errcode = CONF_R_MISSING_INIT_FUNCTION;
goto err;
}
@@ -214,15 +305,14 @@ static CONF_MODULE *module_load_dso(const CONF *cnf,
/* All OK, add module */
md = module_add(dso, name, ifunc, ffunc);
- if (!md)
+ if (md == NULL)
goto err;
return md;
err:
DSO_free(dso);
- CONFerr(CONF_F_MODULE_LOAD_DSO, errcode);
- ERR_add_error_data(4, "module=", name, ", path=", path);
+ ERR_raise_data(ERR_LIB_CONF, errcode, "module=%s, path=%s", name, path);
return NULL;
}
@@ -231,31 +321,42 @@ static CONF_MODULE *module_add(DSO *dso, const char *name,
conf_init_func *ifunc, conf_finish_func *ffunc)
{
CONF_MODULE *tmod = NULL;
+
+ if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
+ return NULL;
+
+ if (!CRYPTO_THREAD_write_lock(module_list_lock))
+ return NULL;
+
if (supported_modules == NULL)
supported_modules = sk_CONF_MODULE_new_null();
if (supported_modules == NULL)
- return NULL;
+ goto err;
if ((tmod = OPENSSL_zalloc(sizeof(*tmod))) == NULL) {
- CONFerr(CONF_F_MODULE_ADD, ERR_R_MALLOC_FAILURE);
- return NULL;
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
+ goto err;
}
tmod->dso = dso;
tmod->name = OPENSSL_strdup(name);
tmod->init = ifunc;
tmod->finish = ffunc;
- if (tmod->name == NULL) {
- OPENSSL_free(tmod);
- return NULL;
- }
+ if (tmod->name == NULL)
+ goto err;
+
+ if (!sk_CONF_MODULE_push(supported_modules, tmod))
+ goto err;
- if (!sk_CONF_MODULE_push(supported_modules, tmod)) {
+ CRYPTO_THREAD_unlock(module_list_lock);
+ return tmod;
+
+ err:
+ CRYPTO_THREAD_unlock(module_list_lock);
+ if (tmod != NULL) {
OPENSSL_free(tmod->name);
OPENSSL_free(tmod);
- return NULL;
}
-
- return tmod;
+ return NULL;
}
/*
@@ -276,14 +377,22 @@ static CONF_MODULE *module_find(const char *name)
else
nchar = strlen(name);
+ if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
+ return NULL;
+
+ if (!CRYPTO_THREAD_read_lock(module_list_lock))
+ return NULL;
+
for (i = 0; i < sk_CONF_MODULE_num(supported_modules); i++) {
tmod = sk_CONF_MODULE_value(supported_modules, i);
- if (strncmp(tmod->name, name, nchar) == 0)
+ if (strncmp(tmod->name, name, nchar) == 0) {
+ CRYPTO_THREAD_unlock(module_list_lock);
return tmod;
+ }
}
+ CRYPTO_THREAD_unlock(module_list_lock);
return NULL;
-
}
/* initialize a module */
@@ -316,21 +425,30 @@ static int module_init(CONF_MODULE *pmod, const char *name, const char *value,
goto err;
}
+ if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
+ goto err;
+
+ if (!CRYPTO_THREAD_write_lock(module_list_lock))
+ goto err;
+
if (initialized_modules == NULL) {
initialized_modules = sk_CONF_IMODULE_new_null();
- if (!initialized_modules) {
- CONFerr(CONF_F_MODULE_INIT, ERR_R_MALLOC_FAILURE);
+ if (initialized_modules == NULL) {
+ CRYPTO_THREAD_unlock(module_list_lock);
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
}
if (!sk_CONF_IMODULE_push(initialized_modules, imod)) {
- CONFerr(CONF_F_MODULE_INIT, ERR_R_MALLOC_FAILURE);
+ CRYPTO_THREAD_unlock(module_list_lock);
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
pmod->links++;
+ CRYPTO_THREAD_unlock(module_list_lock);
return ret;
err:
@@ -360,7 +478,13 @@ void CONF_modules_unload(int all)
{
int i;
CONF_MODULE *md;
- CONF_modules_finish();
+
+ if (!conf_modules_finish_int()) /* also inits module list lock */
+ return;
+
+ if (!CRYPTO_THREAD_write_lock(module_list_lock))
+ return;
+
/* unload modules in reverse order */
for (i = sk_CONF_MODULE_num(supported_modules) - 1; i >= 0; i--) {
md = sk_CONF_MODULE_value(supported_modules, i);
@@ -371,10 +495,13 @@ void CONF_modules_unload(int all)
(void)sk_CONF_MODULE_delete(supported_modules, i);
module_free(md);
}
+
if (sk_CONF_MODULE_num(supported_modules) == 0) {
sk_CONF_MODULE_free(supported_modules);
supported_modules = NULL;
}
+
+ CRYPTO_THREAD_unlock(module_list_lock);
}
/* unload a single module */
@@ -387,15 +514,33 @@ static void module_free(CONF_MODULE *md)
/* finish and free up all modules instances */
-void CONF_modules_finish(void)
+static int conf_modules_finish_int(void)
{
CONF_IMODULE *imod;
+
+ if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
+ return 0;
+
+ /* If module_list_lock is NULL here it means we were already unloaded */
+ if (module_list_lock == NULL
+ || !CRYPTO_THREAD_write_lock(module_list_lock))
+ return 0;
+
while (sk_CONF_IMODULE_num(initialized_modules) > 0) {
imod = sk_CONF_IMODULE_pop(initialized_modules);
module_finish(imod);
}
sk_CONF_IMODULE_free(initialized_modules);
initialized_modules = NULL;
+
+ CRYPTO_THREAD_unlock(module_list_lock);
+
+ return 1;
+}
+
+void CONF_modules_finish(void)
+{
+ conf_modules_finish_int();
}
/* finish a module instance */
@@ -423,10 +568,10 @@ int CONF_module_add(const char *name, conf_init_func *ifunc,
return 0;
}
-void conf_modules_free_int(void)
+void ossl_config_modules_free(void)
{
- CONF_modules_finish();
- CONF_modules_unload(1);
+ CONF_modules_unload(1); /* calls CONF_modules_finish */
+ module_lists_free();
}
/* Utility functions */
@@ -477,28 +622,25 @@ void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data)
}
/* Return default config file name */
-
char *CONF_get1_default_config_file(void)
{
+ const char *t;
char *file, *sep = "";
- int len;
+ size_t size;
if ((file = ossl_safe_getenv("OPENSSL_CONF")) != NULL)
return OPENSSL_strdup(file);
- len = strlen(X509_get_default_cert_area());
+ t = X509_get_default_cert_area();
#ifndef OPENSSL_SYS_VMS
- len++;
sep = "/";
#endif
- len += strlen(OPENSSL_CONF);
-
- file = OPENSSL_malloc(len + 1);
+ size = strlen(t) + strlen(sep) + strlen(OPENSSL_CONF) + 1;
+ file = OPENSSL_malloc(size);
if (file == NULL)
return NULL;
- BIO_snprintf(file, len + 1, "%s%s%s", X509_get_default_cert_area(),
- sep, OPENSSL_CONF);
+ BIO_snprintf(file, size, "%s%s%s", t, sep, OPENSSL_CONF);
return file;
}
@@ -518,7 +660,7 @@ int CONF_parse_list(const char *list_, int sep, int nospc,
const char *lstart, *tmpend, *p;
if (list_ == NULL) {
- CONFerr(CONF_F_CONF_PARSE_LIST, CONF_R_LIST_CANNOT_BE_NULL);
+ ERR_raise(ERR_LIB_CONF, CONF_R_LIST_CANNOT_BE_NULL);
return 0;
}
@@ -529,7 +671,7 @@ int CONF_parse_list(const char *list_, int sep, int nospc,
lstart++;
}
p = strchr(lstart, sep);
- if (p == lstart || !*lstart)
+ if (p == lstart || *lstart == '\0')
ret = list_cb(NULL, 0, arg);
else {
if (p)
diff --git a/crypto/conf/conf_sap.c b/crypto/conf/conf_sap.c
index 82105de748ed..39efcdbf90fa 100644
--- a/crypto/conf/conf_sap.c
+++ b/crypto/conf/conf_sap.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,11 +11,12 @@
#include <openssl/crypto.h>
#include "internal/cryptlib.h"
#include "internal/conf.h"
+#include "conf_local.h"
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include <openssl/engine.h>
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__BORLANDC__)
# define strdup _strdup
#endif
@@ -27,7 +28,7 @@
static int openssl_configured = 0;
-#if OPENSSL_API_COMPAT < 0x10100000L
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
void OPENSSL_config(const char *appname)
{
OPENSSL_INIT_SETTINGS settings;
@@ -40,31 +41,29 @@ void OPENSSL_config(const char *appname)
}
#endif
-int openssl_config_int(const OPENSSL_INIT_SETTINGS *settings)
+int ossl_config_int(const OPENSSL_INIT_SETTINGS *settings)
{
int ret = 0;
+#if defined(OPENSSL_INIT_DEBUG) || !defined(OPENSSL_SYS_UEFI)
const char *filename;
const char *appname;
unsigned long flags;
+#endif
if (openssl_configured)
return 1;
+#if defined(OPENSSL_INIT_DEBUG) || !defined(OPENSSL_SYS_UEFI)
filename = settings ? settings->filename : NULL;
appname = settings ? settings->appname : NULL;
flags = settings ? settings->flags : DEFAULT_CONF_MFLAGS;
+#endif
#ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: openssl_config_int(%s, %s, %lu)\n",
+ fprintf(stderr, "OPENSSL_INIT: ossl_config_int(%s, %s, %lu)\n",
filename, appname, flags);
#endif
- OPENSSL_load_builtin_modules();
-#ifndef OPENSSL_NO_ENGINE
- /* Need to load ENGINEs */
- ENGINE_load_builtin_engines();
-#endif
- ERR_clear_error();
#ifndef OPENSSL_SYS_UEFI
ret = CONF_modules_load_file(filename, appname, flags);
#endif
@@ -72,7 +71,7 @@ int openssl_config_int(const OPENSSL_INIT_SETTINGS *settings)
return ret;
}
-void openssl_no_config_int(void)
+void ossl_no_config_int(void)
{
openssl_configured = 1;
}
diff --git a/crypto/conf/conf_ssl.c b/crypto/conf/conf_ssl.c
index 4bd8117d365c..84c5b2afe581 100644
--- a/crypto/conf/conf_ssl.c
+++ b/crypto/conf/conf_ssl.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -68,11 +68,12 @@ static int ssl_module_init(CONF_IMODULE *md, const CONF *cnf)
ssl_conf_section = CONF_imodule_get_value(md);
cmd_lists = NCONF_get_section(cnf, ssl_conf_section);
if (sk_CONF_VALUE_num(cmd_lists) <= 0) {
- if (cmd_lists == NULL)
- CONFerr(CONF_F_SSL_MODULE_INIT, CONF_R_SSL_SECTION_NOT_FOUND);
- else
- CONFerr(CONF_F_SSL_MODULE_INIT, CONF_R_SSL_SECTION_EMPTY);
- ERR_add_error_data(2, "section=", ssl_conf_section);
+ int rcode =
+ cmd_lists == NULL
+ ? CONF_R_SSL_SECTION_NOT_FOUND
+ : CONF_R_SSL_SECTION_EMPTY;
+
+ ERR_raise_data(ERR_LIB_CONF, rcode, "section=%s", ssl_conf_section);
goto err;
}
cnt = sk_CONF_VALUE_num(cmd_lists);
@@ -87,13 +88,13 @@ static int ssl_module_init(CONF_IMODULE *md, const CONF *cnf)
STACK_OF(CONF_VALUE) *cmds = NCONF_get_section(cnf, sect->value);
if (sk_CONF_VALUE_num(cmds) <= 0) {
- if (cmds == NULL)
- CONFerr(CONF_F_SSL_MODULE_INIT,
- CONF_R_SSL_COMMAND_SECTION_NOT_FOUND);
- else
- CONFerr(CONF_F_SSL_MODULE_INIT,
- CONF_R_SSL_COMMAND_SECTION_EMPTY);
- ERR_add_error_data(4, "name=", sect->name, ", value=", sect->value);
+ int rcode =
+ cmds == NULL
+ ? CONF_R_SSL_COMMAND_SECTION_NOT_FOUND
+ : CONF_R_SSL_COMMAND_SECTION_EMPTY;
+
+ ERR_raise_data(ERR_LIB_CONF, rcode,
+ "name=%s, value=%s", sect->name, sect->value);
goto err;
}
ssl_name->name = OPENSSL_strdup(sect->name);
@@ -175,7 +176,7 @@ void conf_ssl_get_cmd(const SSL_CONF_CMD *cmd, size_t idx, char **cmdstr,
*arg = cmd[idx].arg;
}
-void conf_add_ssl_module(void)
+void ossl_config_add_ssl_module(void)
{
CONF_module_add("ssl_conf", ssl_module_init, ssl_module_free);
}
diff --git a/crypto/conf/keysets.pl b/crypto/conf/keysets.pl
index 9c9a00dea8d7..7e83d800501b 100644
--- a/crypto/conf/keysets.pl
+++ b/crypto/conf/keysets.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -23,6 +23,7 @@ my $QUOTE = 0x0040;
my $DQUOTE = 0x0400;
my $COMMENT = 0x0080;
my $FCOMMENT = 0x0800;
+my $DOLLAR = 0x1000;
my $EOF = 0x0008;
my @V_def;
my @V_w32;
@@ -41,6 +42,7 @@ foreach (0 .. 127) {
$v |= $ESC if $c =~ /\\/;
$v |= $QUOTE if $c =~ /['`"]/; # for emacs: "`'
$v |= $COMMENT if $c =~ /\#/;
+ $v |= $DOLLAR if $c eq '$';
$v |= $EOF if $c =~ /\0/;
push(@V_def, $v);
@@ -53,6 +55,7 @@ foreach (0 .. 127) {
$v |= $WS if $c =~ /[ \t\r\n]/;
$v |= $DQUOTE if $c =~ /["]/; # for emacs: "
$v |= $FCOMMENT if $c =~ /;/;
+ $v |= $DOLLAR if $c eq '$';
$v |= $EOF if $c =~ /\0/;
push(@V_w32, $v);
}
@@ -65,7 +68,7 @@ print <<"EOF";
* Generated by crypto/conf/keysets.pl
*
* Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved.
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -82,6 +85,7 @@ print <<"EOF";
#define CONF_DQUOTE $DQUOTE
#define CONF_COMMENT $COMMENT
#define CONF_FCOMMENT $FCOMMENT
+#define CONF_DOLLAR $DOLLAR
#define CONF_EOF $EOF
#define CONF_ALPHA (CONF_UPPER|CONF_LOWER)
#define CONF_ALNUM (CONF_ALPHA|CONF_NUMBER|CONF_UNDER)
@@ -98,6 +102,7 @@ print <<"EOF";
#define IS_ALNUM_PUNCT(conf,c) is_keytype(conf, c, CONF_ALNUM_PUNCT)
#define IS_QUOTE(conf,c) is_keytype(conf, c, CONF_QUOTE)
#define IS_DQUOTE(conf,c) is_keytype(conf, c, CONF_DQUOTE)
+#define IS_DOLLAR(conf,c) is_keytype(conf, c, CONF_DOLLAR)
EOF
@@ -110,9 +115,11 @@ for ($i = 0; $i < 128; $i++) {
}
print "\n};\n\n";
+print "#ifndef OPENSSL_NO_DEPRECATED_3_0\n";
print "static const unsigned short CONF_type_win32[128] = {";
for ($i = 0; $i < 128; $i++) {
print "\n " if ($i % 8) == 0;
printf " 0x%04X,", $V_w32[$i];
}
print "\n};\n";
+print "#endif\n";
diff --git a/crypto/context.c b/crypto/context.c
new file mode 100644
index 000000000000..548665fba265
--- /dev/null
+++ b/crypto/context.c
@@ -0,0 +1,510 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "crypto/cryptlib.h"
+#include <openssl/conf.h>
+#include "internal/thread_once.h"
+#include "internal/property.h"
+#include "internal/core.h"
+#include "internal/bio.h"
+#include "internal/provider.h"
+#include "crypto/ctype.h"
+#include "crypto/rand.h"
+
+struct ossl_lib_ctx_onfree_list_st {
+ ossl_lib_ctx_onfree_fn *fn;
+ struct ossl_lib_ctx_onfree_list_st *next;
+};
+
+struct ossl_lib_ctx_st {
+ CRYPTO_RWLOCK *lock;
+ CRYPTO_EX_DATA data;
+
+ /*
+ * For most data in the OSSL_LIB_CTX we just use ex_data to store it. But
+ * that doesn't work for ex_data itself - so we store that directly.
+ */
+ OSSL_EX_DATA_GLOBAL global;
+
+ /* Map internal static indexes to dynamically created indexes */
+ int dyn_indexes[OSSL_LIB_CTX_MAX_INDEXES];
+
+ /* Keep a separate lock for each index */
+ CRYPTO_RWLOCK *index_locks[OSSL_LIB_CTX_MAX_INDEXES];
+
+ CRYPTO_RWLOCK *oncelock;
+ int run_once_done[OSSL_LIB_CTX_MAX_RUN_ONCE];
+ int run_once_ret[OSSL_LIB_CTX_MAX_RUN_ONCE];
+ struct ossl_lib_ctx_onfree_list_st *onfreelist;
+ unsigned int ischild:1;
+};
+
+int ossl_lib_ctx_write_lock(OSSL_LIB_CTX *ctx)
+{
+ return CRYPTO_THREAD_write_lock(ossl_lib_ctx_get_concrete(ctx)->lock);
+}
+
+int ossl_lib_ctx_read_lock(OSSL_LIB_CTX *ctx)
+{
+ return CRYPTO_THREAD_read_lock(ossl_lib_ctx_get_concrete(ctx)->lock);
+}
+
+int ossl_lib_ctx_unlock(OSSL_LIB_CTX *ctx)
+{
+ return CRYPTO_THREAD_unlock(ossl_lib_ctx_get_concrete(ctx)->lock);
+}
+
+int ossl_lib_ctx_is_child(OSSL_LIB_CTX *ctx)
+{
+ ctx = ossl_lib_ctx_get_concrete(ctx);
+
+ if (ctx == NULL)
+ return 0;
+ return ctx->ischild;
+}
+
+static int context_init(OSSL_LIB_CTX *ctx)
+{
+ size_t i;
+ int exdata_done = 0;
+
+ ctx->lock = CRYPTO_THREAD_lock_new();
+ if (ctx->lock == NULL)
+ return 0;
+
+ ctx->oncelock = CRYPTO_THREAD_lock_new();
+ if (ctx->oncelock == NULL)
+ goto err;
+
+ for (i = 0; i < OSSL_LIB_CTX_MAX_INDEXES; i++) {
+ ctx->index_locks[i] = CRYPTO_THREAD_lock_new();
+ ctx->dyn_indexes[i] = -1;
+ if (ctx->index_locks[i] == NULL)
+ goto err;
+ }
+
+ /* OSSL_LIB_CTX is built on top of ex_data so we initialise that directly */
+ if (!ossl_do_ex_data_init(ctx))
+ goto err;
+ exdata_done = 1;
+
+ if (!ossl_crypto_new_ex_data_ex(ctx, CRYPTO_EX_INDEX_OSSL_LIB_CTX, NULL,
+ &ctx->data))
+ goto err;
+
+ /* Everything depends on properties, so we also pre-initialise that */
+ if (!ossl_property_parse_init(ctx))
+ goto err;
+
+ return 1;
+ err:
+ if (exdata_done)
+ ossl_crypto_cleanup_all_ex_data_int(ctx);
+ for (i = 0; i < OSSL_LIB_CTX_MAX_INDEXES; i++)
+ CRYPTO_THREAD_lock_free(ctx->index_locks[i]);
+ CRYPTO_THREAD_lock_free(ctx->oncelock);
+ CRYPTO_THREAD_lock_free(ctx->lock);
+ memset(ctx, '\0', sizeof(*ctx));
+ return 0;
+}
+
+static int context_deinit(OSSL_LIB_CTX *ctx)
+{
+ struct ossl_lib_ctx_onfree_list_st *tmp, *onfree;
+ int i;
+
+ if (ctx == NULL)
+ return 1;
+
+ ossl_ctx_thread_stop(ctx);
+
+ onfree = ctx->onfreelist;
+ while (onfree != NULL) {
+ onfree->fn(ctx);
+ tmp = onfree;
+ onfree = onfree->next;
+ OPENSSL_free(tmp);
+ }
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_OSSL_LIB_CTX, NULL, &ctx->data);
+ ossl_crypto_cleanup_all_ex_data_int(ctx);
+ for (i = 0; i < OSSL_LIB_CTX_MAX_INDEXES; i++)
+ CRYPTO_THREAD_lock_free(ctx->index_locks[i]);
+
+ CRYPTO_THREAD_lock_free(ctx->oncelock);
+ CRYPTO_THREAD_lock_free(ctx->lock);
+ ctx->lock = NULL;
+ return 1;
+}
+
+#ifndef FIPS_MODULE
+/* The default default context */
+static OSSL_LIB_CTX default_context_int;
+
+static CRYPTO_ONCE default_context_init = CRYPTO_ONCE_STATIC_INIT;
+static CRYPTO_THREAD_LOCAL default_context_thread_local;
+
+DEFINE_RUN_ONCE_STATIC(default_context_do_init)
+{
+ return CRYPTO_THREAD_init_local(&default_context_thread_local, NULL)
+ && context_init(&default_context_int);
+}
+
+void ossl_lib_ctx_default_deinit(void)
+{
+ context_deinit(&default_context_int);
+ CRYPTO_THREAD_cleanup_local(&default_context_thread_local);
+}
+
+static OSSL_LIB_CTX *get_thread_default_context(void)
+{
+ if (!RUN_ONCE(&default_context_init, default_context_do_init))
+ return NULL;
+
+ return CRYPTO_THREAD_get_local(&default_context_thread_local);
+}
+
+static OSSL_LIB_CTX *get_default_context(void)
+{
+ OSSL_LIB_CTX *current_defctx = get_thread_default_context();
+
+ if (current_defctx == NULL)
+ current_defctx = &default_context_int;
+ return current_defctx;
+}
+
+static int set_default_context(OSSL_LIB_CTX *defctx)
+{
+ if (defctx == &default_context_int)
+ defctx = NULL;
+
+ return CRYPTO_THREAD_set_local(&default_context_thread_local, defctx);
+}
+#endif
+
+OSSL_LIB_CTX *OSSL_LIB_CTX_new(void)
+{
+ OSSL_LIB_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx != NULL && !context_init(ctx)) {
+ OPENSSL_free(ctx);
+ ctx = NULL;
+ }
+ return ctx;
+}
+
+#ifndef FIPS_MODULE
+OSSL_LIB_CTX *OSSL_LIB_CTX_new_from_dispatch(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in)
+{
+ OSSL_LIB_CTX *ctx = OSSL_LIB_CTX_new();
+
+ if (ctx == NULL)
+ return NULL;
+
+ if (!ossl_bio_init_core(ctx, in)) {
+ OSSL_LIB_CTX_free(ctx);
+ return NULL;
+ }
+
+ return ctx;
+}
+
+OSSL_LIB_CTX *OSSL_LIB_CTX_new_child(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in)
+{
+ OSSL_LIB_CTX *ctx = OSSL_LIB_CTX_new_from_dispatch(handle, in);
+
+ if (ctx == NULL)
+ return NULL;
+
+ if (!ossl_provider_init_as_child(ctx, handle, in)) {
+ OSSL_LIB_CTX_free(ctx);
+ return NULL;
+ }
+ ctx->ischild = 1;
+
+ return ctx;
+}
+
+int OSSL_LIB_CTX_load_config(OSSL_LIB_CTX *ctx, const char *config_file)
+{
+ return CONF_modules_load_file_ex(ctx, config_file, NULL, 0) > 0;
+}
+#endif
+
+void OSSL_LIB_CTX_free(OSSL_LIB_CTX *ctx)
+{
+ if (ossl_lib_ctx_is_default(ctx))
+ return;
+
+#ifndef FIPS_MODULE
+ if (ctx->ischild)
+ ossl_provider_deinit_child(ctx);
+#endif
+ context_deinit(ctx);
+ OPENSSL_free(ctx);
+}
+
+#ifndef FIPS_MODULE
+OSSL_LIB_CTX *OSSL_LIB_CTX_get0_global_default(void)
+{
+ if (!RUN_ONCE(&default_context_init, default_context_do_init))
+ return NULL;
+
+ return &default_context_int;
+}
+
+OSSL_LIB_CTX *OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX *libctx)
+{
+ OSSL_LIB_CTX *current_defctx;
+
+ if ((current_defctx = get_default_context()) != NULL) {
+ if (libctx != NULL)
+ set_default_context(libctx);
+ return current_defctx;
+ }
+
+ return NULL;
+}
+
+void ossl_release_default_drbg_ctx(void)
+{
+ int dynidx = default_context_int.dyn_indexes[OSSL_LIB_CTX_DRBG_INDEX];
+
+ /* early release of the DRBG in global default libctx, no locking */
+ if (dynidx != -1) {
+ void *data;
+
+ data = CRYPTO_get_ex_data(&default_context_int.data, dynidx);
+ ossl_rand_ctx_free(data);
+ CRYPTO_set_ex_data(&default_context_int.data, dynidx, NULL);
+ }
+}
+#endif
+
+OSSL_LIB_CTX *ossl_lib_ctx_get_concrete(OSSL_LIB_CTX *ctx)
+{
+#ifndef FIPS_MODULE
+ if (ctx == NULL)
+ return get_default_context();
+#endif
+ return ctx;
+}
+
+int ossl_lib_ctx_is_default(OSSL_LIB_CTX *ctx)
+{
+#ifndef FIPS_MODULE
+ if (ctx == NULL || ctx == get_default_context())
+ return 1;
+#endif
+ return 0;
+}
+
+int ossl_lib_ctx_is_global_default(OSSL_LIB_CTX *ctx)
+{
+#ifndef FIPS_MODULE
+ if (ossl_lib_ctx_get_concrete(ctx) == &default_context_int)
+ return 1;
+#endif
+ return 0;
+}
+
+static void ossl_lib_ctx_generic_new(void *parent_ign, void *ptr_ign,
+ CRYPTO_EX_DATA *ad, int index,
+ long argl_ign, void *argp)
+{
+ const OSSL_LIB_CTX_METHOD *meth = argp;
+ OSSL_LIB_CTX *ctx = ossl_crypto_ex_data_get_ossl_lib_ctx(ad);
+ void *ptr = meth->new_func(ctx);
+
+ if (ptr != NULL) {
+ if (!CRYPTO_THREAD_write_lock(ctx->lock))
+ /*
+ * Can't return something, so best to hope that something will
+ * fail later. :(
+ */
+ return;
+ CRYPTO_set_ex_data(ad, index, ptr);
+ CRYPTO_THREAD_unlock(ctx->lock);
+ }
+}
+static void ossl_lib_ctx_generic_free(void *parent_ign, void *ptr,
+ CRYPTO_EX_DATA *ad, int index,
+ long argl_ign, void *argp)
+{
+ const OSSL_LIB_CTX_METHOD *meth = argp;
+
+ meth->free_func(ptr);
+}
+
+static int ossl_lib_ctx_init_index(OSSL_LIB_CTX *ctx, int static_index,
+ const OSSL_LIB_CTX_METHOD *meth)
+{
+ int idx;
+
+ ctx = ossl_lib_ctx_get_concrete(ctx);
+ if (ctx == NULL)
+ return 0;
+
+ idx = ossl_crypto_get_ex_new_index_ex(ctx, CRYPTO_EX_INDEX_OSSL_LIB_CTX, 0,
+ (void *)meth,
+ ossl_lib_ctx_generic_new,
+ NULL, ossl_lib_ctx_generic_free,
+ meth->priority);
+ if (idx < 0)
+ return 0;
+
+ ctx->dyn_indexes[static_index] = idx;
+ return 1;
+}
+
+void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index,
+ const OSSL_LIB_CTX_METHOD *meth)
+{
+ void *data = NULL;
+ int dynidx;
+
+ ctx = ossl_lib_ctx_get_concrete(ctx);
+ if (ctx == NULL)
+ return NULL;
+
+ if (!CRYPTO_THREAD_read_lock(ctx->lock))
+ return NULL;
+ dynidx = ctx->dyn_indexes[index];
+ CRYPTO_THREAD_unlock(ctx->lock);
+
+ if (dynidx != -1) {
+ if (!CRYPTO_THREAD_read_lock(ctx->index_locks[index]))
+ return NULL;
+ if (!CRYPTO_THREAD_read_lock(ctx->lock)) {
+ CRYPTO_THREAD_unlock(ctx->index_locks[index]);
+ return NULL;
+ }
+ data = CRYPTO_get_ex_data(&ctx->data, dynidx);
+ CRYPTO_THREAD_unlock(ctx->lock);
+ CRYPTO_THREAD_unlock(ctx->index_locks[index]);
+ return data;
+ }
+
+ if (!CRYPTO_THREAD_write_lock(ctx->index_locks[index]))
+ return NULL;
+ if (!CRYPTO_THREAD_write_lock(ctx->lock)) {
+ CRYPTO_THREAD_unlock(ctx->index_locks[index]);
+ return NULL;
+ }
+
+ dynidx = ctx->dyn_indexes[index];
+ if (dynidx != -1) {
+ data = CRYPTO_get_ex_data(&ctx->data, dynidx);
+ CRYPTO_THREAD_unlock(ctx->lock);
+ CRYPTO_THREAD_unlock(ctx->index_locks[index]);
+ return data;
+ }
+
+ if (!ossl_lib_ctx_init_index(ctx, index, meth)) {
+ CRYPTO_THREAD_unlock(ctx->lock);
+ CRYPTO_THREAD_unlock(ctx->index_locks[index]);
+ return NULL;
+ }
+
+ CRYPTO_THREAD_unlock(ctx->lock);
+
+ /*
+ * The alloc call ensures there's a value there. We release the ctx->lock
+ * for this, because the allocation itself may recursively call
+ * ossl_lib_ctx_get_data for other indexes (never this one). The allocation
+ * will itself aquire the ctx->lock when it actually comes to store the
+ * allocated data (see ossl_lib_ctx_generic_new() above). We call
+ * ossl_crypto_alloc_ex_data_intern() here instead of CRYPTO_alloc_ex_data().
+ * They do the same thing except that the latter calls CRYPTO_get_ex_data()
+ * as well - which we must not do without holding the ctx->lock.
+ */
+ if (ossl_crypto_alloc_ex_data_intern(CRYPTO_EX_INDEX_OSSL_LIB_CTX, NULL,
+ &ctx->data, ctx->dyn_indexes[index])) {
+ if (!CRYPTO_THREAD_read_lock(ctx->lock))
+ goto end;
+ data = CRYPTO_get_ex_data(&ctx->data, ctx->dyn_indexes[index]);
+ CRYPTO_THREAD_unlock(ctx->lock);
+ }
+
+end:
+ CRYPTO_THREAD_unlock(ctx->index_locks[index]);
+ return data;
+}
+
+OSSL_EX_DATA_GLOBAL *ossl_lib_ctx_get_ex_data_global(OSSL_LIB_CTX *ctx)
+{
+ ctx = ossl_lib_ctx_get_concrete(ctx);
+ if (ctx == NULL)
+ return NULL;
+ return &ctx->global;
+}
+
+int ossl_lib_ctx_run_once(OSSL_LIB_CTX *ctx, unsigned int idx,
+ ossl_lib_ctx_run_once_fn run_once_fn)
+{
+ int done = 0, ret = 0;
+
+ ctx = ossl_lib_ctx_get_concrete(ctx);
+ if (ctx == NULL)
+ return 0;
+
+ if (!CRYPTO_THREAD_read_lock(ctx->oncelock))
+ return 0;
+ done = ctx->run_once_done[idx];
+ if (done)
+ ret = ctx->run_once_ret[idx];
+ CRYPTO_THREAD_unlock(ctx->oncelock);
+
+ if (done)
+ return ret;
+
+ if (!CRYPTO_THREAD_write_lock(ctx->oncelock))
+ return 0;
+ if (ctx->run_once_done[idx]) {
+ ret = ctx->run_once_ret[idx];
+ CRYPTO_THREAD_unlock(ctx->oncelock);
+ return ret;
+ }
+
+ ret = run_once_fn(ctx);
+ ctx->run_once_done[idx] = 1;
+ ctx->run_once_ret[idx] = ret;
+ CRYPTO_THREAD_unlock(ctx->oncelock);
+
+ return ret;
+}
+
+int ossl_lib_ctx_onfree(OSSL_LIB_CTX *ctx, ossl_lib_ctx_onfree_fn onfreefn)
+{
+ struct ossl_lib_ctx_onfree_list_st *newonfree
+ = OPENSSL_malloc(sizeof(*newonfree));
+
+ if (newonfree == NULL)
+ return 0;
+
+ newonfree->fn = onfreefn;
+ newonfree->next = ctx->onfreelist;
+ ctx->onfreelist = newonfree;
+
+ return 1;
+}
+
+const char *ossl_lib_ctx_get_descriptor(OSSL_LIB_CTX *libctx)
+{
+#ifdef FIPS_MODULE
+ return "FIPS internal library context";
+#else
+ if (ossl_lib_ctx_is_global_default(libctx))
+ return "Global default library context";
+ if (ossl_lib_ctx_is_default(libctx))
+ return "Thread-local default library context";
+ return "Non-default library context";
+#endif
+}
diff --git a/crypto/core_algorithm.c b/crypto/core_algorithm.c
new file mode 100644
index 000000000000..c245c814d98c
--- /dev/null
+++ b/crypto/core_algorithm.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include "internal/core.h"
+#include "internal/property.h"
+#include "internal/provider.h"
+
+struct algorithm_data_st {
+ OSSL_LIB_CTX *libctx;
+ int operation_id; /* May be zero for finding them all */
+ int (*pre)(OSSL_PROVIDER *, int operation_id, int no_store, void *data,
+ int *result);
+ int (*reserve_store)(int no_store, void *data);
+ void (*fn)(OSSL_PROVIDER *, const OSSL_ALGORITHM *, int no_store,
+ void *data);
+ int (*unreserve_store)(void *data);
+ int (*post)(OSSL_PROVIDER *, int operation_id, int no_store, void *data,
+ int *result);
+ void *data;
+};
+
+/*
+ * Process one OSSL_ALGORITHM array, for the operation |cur_operation|,
+ * by constructing methods for all its implementations and adding those
+ * to the appropriate method store.
+ * Which method store is appropriate is given by |no_store| ("permanent"
+ * if 0, temporary if 1) and other data in |data->data|.
+ *
+ * Returns:
+ * -1 to quit adding algorithm implementations immediately
+ * 0 if not successful, but adding should continue
+ * 1 if successful so far, and adding should continue
+ */
+static int algorithm_do_map(OSSL_PROVIDER *provider, const OSSL_ALGORITHM *map,
+ int cur_operation, int no_store, void *cbdata)
+{
+ struct algorithm_data_st *data = cbdata;
+ int ret = 0;
+
+ if (!data->reserve_store(no_store, data->data))
+ /* Error, bail out! */
+ return -1;
+
+ /* Do we fulfill pre-conditions? */
+ if (data->pre == NULL) {
+ /* If there is no pre-condition function, assume "yes" */
+ ret = 1;
+ } else if (!data->pre(provider, cur_operation, no_store, data->data,
+ &ret)) {
+ /* Error, bail out! */
+ ret = -1;
+ goto end;
+ }
+
+ /*
+ * If pre-condition not fulfilled don't add this set of implementations,
+ * but do continue with the next. This simply means that another thread
+ * got to it first.
+ */
+ if (ret == 0) {
+ ret = 1;
+ goto end;
+ }
+
+ if (map != NULL) {
+ const OSSL_ALGORITHM *thismap;
+
+ for (thismap = map; thismap->algorithm_names != NULL; thismap++)
+ data->fn(provider, thismap, no_store, data->data);
+ }
+
+ /* Do we fulfill post-conditions? */
+ if (data->post == NULL) {
+ /* If there is no post-condition function, assume "yes" */
+ ret = 1;
+ } else if (!data->post(provider, cur_operation, no_store, data->data,
+ &ret)) {
+ /* Error, bail out! */
+ ret = -1;
+ }
+
+ end:
+ data->unreserve_store(data->data);
+
+ return ret;
+}
+
+/*
+ * Given a provider, process one operation given by |data->operation_id|, or
+ * if that's zero, process all known operations.
+ * For each such operation, query the associated OSSL_ALGORITHM array from
+ * the provider, then process that array with |algorithm_do_map()|.
+ */
+static int algorithm_do_this(OSSL_PROVIDER *provider, void *cbdata)
+{
+ struct algorithm_data_st *data = cbdata;
+ int first_operation = 1;
+ int last_operation = OSSL_OP__HIGHEST;
+ int cur_operation;
+ int ok = 1;
+
+ if (data->operation_id != 0)
+ first_operation = last_operation = data->operation_id;
+
+ for (cur_operation = first_operation;
+ cur_operation <= last_operation;
+ cur_operation++) {
+ int no_store = 0; /* Assume caching is ok */
+ const OSSL_ALGORITHM *map = NULL;
+ int ret = 0;
+
+ map = ossl_provider_query_operation(provider, cur_operation,
+ &no_store);
+ ret = algorithm_do_map(provider, map, cur_operation, no_store, data);
+ ossl_provider_unquery_operation(provider, cur_operation, map);
+
+ if (ret < 0)
+ /* Hard error, bail out immediately! */
+ return 0;
+
+ /* If post-condition not fulfilled, set general failure */
+ if (!ret)
+ ok = 0;
+ }
+
+ return ok;
+}
+
+void ossl_algorithm_do_all(OSSL_LIB_CTX *libctx, int operation_id,
+ OSSL_PROVIDER *provider,
+ int (*pre)(OSSL_PROVIDER *, int operation_id,
+ int no_store, void *data, int *result),
+ int (*reserve_store)(int no_store, void *data),
+ void (*fn)(OSSL_PROVIDER *provider,
+ const OSSL_ALGORITHM *algo,
+ int no_store, void *data),
+ int (*unreserve_store)(void *data),
+ int (*post)(OSSL_PROVIDER *, int operation_id,
+ int no_store, void *data, int *result),
+ void *data)
+{
+ struct algorithm_data_st cbdata = { 0, };
+
+ cbdata.libctx = libctx;
+ cbdata.operation_id = operation_id;
+ cbdata.pre = pre;
+ cbdata.reserve_store = reserve_store;
+ cbdata.fn = fn;
+ cbdata.unreserve_store = unreserve_store;
+ cbdata.post = post;
+ cbdata.data = data;
+
+ if (provider == NULL) {
+ ossl_provider_doall_activated(libctx, algorithm_do_this, &cbdata);
+ } else {
+ OSSL_LIB_CTX *libctx2 = ossl_provider_libctx(provider);
+
+ /*
+ * If a provider is given, its library context MUST match the library
+ * context we're passed. If this turns out not to be true, there is
+ * a programming error in the functions up the call stack.
+ */
+ if (!ossl_assert(ossl_lib_ctx_get_concrete(libctx)
+ == ossl_lib_ctx_get_concrete(libctx2)))
+ return;
+
+ cbdata.libctx = libctx2;
+ algorithm_do_this(provider, &cbdata);
+ }
+}
+
+char *ossl_algorithm_get1_first_name(const OSSL_ALGORITHM *algo)
+{
+ const char *first_name_end = NULL;
+ size_t first_name_len = 0;
+ char *ret;
+
+ if (algo->algorithm_names == NULL)
+ return NULL;
+
+ first_name_end = strchr(algo->algorithm_names, ':');
+ if (first_name_end == NULL)
+ first_name_len = strlen(algo->algorithm_names);
+ else
+ first_name_len = first_name_end - algo->algorithm_names;
+
+ ret = OPENSSL_strndup(algo->algorithm_names, first_name_len);
+ if (ret == NULL)
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return ret;
+}
diff --git a/crypto/core_fetch.c b/crypto/core_fetch.c
new file mode 100644
index 000000000000..38db36ee1f75
--- /dev/null
+++ b/crypto/core_fetch.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stddef.h>
+
+#include <openssl/core.h>
+#include "internal/cryptlib.h"
+#include "internal/core.h"
+#include "internal/property.h"
+#include "internal/provider.h"
+
+struct construct_data_st {
+ OSSL_LIB_CTX *libctx;
+ OSSL_METHOD_STORE *store;
+ int operation_id;
+ int force_store;
+ OSSL_METHOD_CONSTRUCT_METHOD *mcm;
+ void *mcm_data;
+};
+
+static int is_temporary_method_store(int no_store, void *cbdata)
+{
+ struct construct_data_st *data = cbdata;
+
+ return no_store && !data->force_store;
+}
+
+static int ossl_method_construct_reserve_store(int no_store, void *cbdata)
+{
+ struct construct_data_st *data = cbdata;
+
+ if (is_temporary_method_store(no_store, data) && data->store == NULL) {
+ /*
+ * If we have been told not to store the method "permanently", we
+ * ask for a temporary store, and store the method there.
+ * The owner of |data->mcm| is completely responsible for managing
+ * that temporary store.
+ */
+ if ((data->store = data->mcm->get_tmp_store(data->mcm_data)) == NULL)
+ return 0;
+ }
+
+ return data->mcm->lock_store(data->store, data->mcm_data);
+}
+
+static int ossl_method_construct_unreserve_store(void *cbdata)
+{
+ struct construct_data_st *data = cbdata;
+
+ return data->mcm->unlock_store(data->store, data->mcm_data);
+}
+
+static int ossl_method_construct_precondition(OSSL_PROVIDER *provider,
+ int operation_id, int no_store,
+ void *cbdata, int *result)
+{
+ if (!ossl_assert(result != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ /* Assume that no bits are set */
+ *result = 0;
+
+ /* No flag bits for temporary stores */
+ if (!is_temporary_method_store(no_store, cbdata)
+ && !ossl_provider_test_operation_bit(provider, operation_id, result))
+ return 0;
+
+ /*
+ * The result we get tells if methods have already been constructed.
+ * However, we want to tell whether construction should happen (true)
+ * or not (false), which is the opposite of what we got.
+ */
+ *result = !*result;
+
+ return 1;
+}
+
+static int ossl_method_construct_postcondition(OSSL_PROVIDER *provider,
+ int operation_id, int no_store,
+ void *cbdata, int *result)
+{
+ if (!ossl_assert(result != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ *result = 1;
+
+ /* No flag bits for temporary stores */
+ return is_temporary_method_store(no_store, cbdata)
+ || ossl_provider_set_operation_bit(provider, operation_id);
+}
+
+static void ossl_method_construct_this(OSSL_PROVIDER *provider,
+ const OSSL_ALGORITHM *algo,
+ int no_store, void *cbdata)
+{
+ struct construct_data_st *data = cbdata;
+ void *method = NULL;
+
+ if ((method = data->mcm->construct(algo, provider, data->mcm_data))
+ == NULL)
+ return;
+
+ /*
+ * Note regarding putting the method in stores:
+ *
+ * we don't need to care if it actually got in or not here.
+ * If it didn't get in, it will simply not be available when
+ * ossl_method_construct() tries to get it from the store.
+ *
+ * It is *expected* that the put function increments the refcnt
+ * of the passed method.
+ */
+ data->mcm->put(data->store, method, provider, algo->algorithm_names,
+ algo->property_definition, data->mcm_data);
+
+ /* refcnt-- because we're dropping the reference */
+ data->mcm->destruct(method, data->mcm_data);
+}
+
+void *ossl_method_construct(OSSL_LIB_CTX *libctx, int operation_id,
+ OSSL_PROVIDER **provider_rw, int force_store,
+ OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data)
+{
+ void *method = NULL;
+ OSSL_PROVIDER *provider = provider_rw != NULL ? *provider_rw : NULL;
+ struct construct_data_st cbdata;
+
+ /*
+ * We might be tempted to try to look into the method store without
+ * constructing to see if we can find our method there already.
+ * Unfortunately that does not work well if the query contains
+ * optional properties as newly loaded providers can match them better.
+ * We trust that ossl_method_construct_precondition() and
+ * ossl_method_construct_postcondition() make sure that the
+ * ossl_algorithm_do_all() does very little when methods from
+ * a provider have already been constructed.
+ */
+
+ cbdata.store = NULL;
+ cbdata.force_store = force_store;
+ cbdata.mcm = mcm;
+ cbdata.mcm_data = mcm_data;
+ ossl_algorithm_do_all(libctx, operation_id, provider,
+ ossl_method_construct_precondition,
+ ossl_method_construct_reserve_store,
+ ossl_method_construct_this,
+ ossl_method_construct_unreserve_store,
+ ossl_method_construct_postcondition,
+ &cbdata);
+
+ /* If there is a temporary store, try there first */
+ if (cbdata.store != NULL)
+ method = mcm->get(cbdata.store, (const OSSL_PROVIDER **)provider_rw,
+ mcm_data);
+
+ /* If no method was found yet, try the global store */
+ if (method == NULL)
+ method = mcm->get(NULL, (const OSSL_PROVIDER **)provider_rw, mcm_data);
+
+ return method;
+}
diff --git a/crypto/core_namemap.c b/crypto/core_namemap.c
new file mode 100644
index 000000000000..7e11ab1c8845
--- /dev/null
+++ b/crypto/core_namemap.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/namemap.h"
+#include <openssl/lhash.h>
+#include "crypto/lhash.h" /* ossl_lh_strcasehash */
+#include "internal/tsan_assist.h"
+#include "internal/sizes.h"
+
+/*-
+ * The namenum entry
+ * =================
+ */
+typedef struct {
+ char *name;
+ int number;
+} NAMENUM_ENTRY;
+
+DEFINE_LHASH_OF(NAMENUM_ENTRY);
+
+/*-
+ * The namemap itself
+ * ==================
+ */
+
+struct ossl_namemap_st {
+ /* Flags */
+ unsigned int stored:1; /* If 1, it's stored in a library context */
+
+ CRYPTO_RWLOCK *lock;
+ LHASH_OF(NAMENUM_ENTRY) *namenum; /* Name->number mapping */
+
+ TSAN_QUALIFIER int max_number; /* Current max number */
+};
+
+/* LHASH callbacks */
+
+static unsigned long namenum_hash(const NAMENUM_ENTRY *n)
+{
+ return ossl_lh_strcasehash(n->name);
+}
+
+static int namenum_cmp(const NAMENUM_ENTRY *a, const NAMENUM_ENTRY *b)
+{
+ return OPENSSL_strcasecmp(a->name, b->name);
+}
+
+static void namenum_free(NAMENUM_ENTRY *n)
+{
+ if (n != NULL)
+ OPENSSL_free(n->name);
+ OPENSSL_free(n);
+}
+
+/* OSSL_LIB_CTX_METHOD functions for a namemap stored in a library context */
+
+static void *stored_namemap_new(OSSL_LIB_CTX *libctx)
+{
+ OSSL_NAMEMAP *namemap = ossl_namemap_new();
+
+ if (namemap != NULL)
+ namemap->stored = 1;
+
+ return namemap;
+}
+
+static void stored_namemap_free(void *vnamemap)
+{
+ OSSL_NAMEMAP *namemap = vnamemap;
+
+ if (namemap != NULL) {
+ /* Pretend it isn't stored, or ossl_namemap_free() will do nothing */
+ namemap->stored = 0;
+ ossl_namemap_free(namemap);
+ }
+}
+
+static const OSSL_LIB_CTX_METHOD stored_namemap_method = {
+ OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
+ stored_namemap_new,
+ stored_namemap_free,
+};
+
+/*-
+ * API functions
+ * =============
+ */
+
+int ossl_namemap_empty(OSSL_NAMEMAP *namemap)
+{
+#ifdef TSAN_REQUIRES_LOCKING
+ /* No TSAN support */
+ int rv;
+
+ if (namemap == NULL)
+ return 1;
+
+ if (!CRYPTO_THREAD_read_lock(namemap->lock))
+ return -1;
+ rv = namemap->max_number == 0;
+ CRYPTO_THREAD_unlock(namemap->lock);
+ return rv;
+#else
+ /* Have TSAN support */
+ return namemap == NULL || tsan_load(&namemap->max_number) == 0;
+#endif
+}
+
+typedef struct doall_names_data_st {
+ int number;
+ const char **names;
+ int found;
+} DOALL_NAMES_DATA;
+
+static void do_name(const NAMENUM_ENTRY *namenum, DOALL_NAMES_DATA *data)
+{
+ if (namenum->number == data->number)
+ data->names[data->found++] = namenum->name;
+}
+
+IMPLEMENT_LHASH_DOALL_ARG_CONST(NAMENUM_ENTRY, DOALL_NAMES_DATA);
+
+/*
+ * Call the callback for all names in the namemap with the given number.
+ * A return value 1 means that the callback was called for all names. A
+ * return value of 0 means that the callback was not called for any names.
+ */
+int ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ DOALL_NAMES_DATA cbdata;
+ size_t num_names;
+ int i;
+
+ cbdata.number = number;
+ cbdata.found = 0;
+
+ /*
+ * We collect all the names first under a read lock. Subsequently we call
+ * the user function, so that we're not holding the read lock when in user
+ * code. This could lead to deadlocks.
+ */
+ if (!CRYPTO_THREAD_read_lock(namemap->lock))
+ return 0;
+
+ num_names = lh_NAMENUM_ENTRY_num_items(namemap->namenum);
+ if (num_names == 0) {
+ CRYPTO_THREAD_unlock(namemap->lock);
+ return 0;
+ }
+ cbdata.names = OPENSSL_malloc(sizeof(*cbdata.names) * num_names);
+ if (cbdata.names == NULL) {
+ CRYPTO_THREAD_unlock(namemap->lock);
+ return 0;
+ }
+ lh_NAMENUM_ENTRY_doall_DOALL_NAMES_DATA(namemap->namenum, do_name,
+ &cbdata);
+ CRYPTO_THREAD_unlock(namemap->lock);
+
+ for (i = 0; i < cbdata.found; i++)
+ fn(cbdata.names[i], data);
+
+ OPENSSL_free(cbdata.names);
+ return 1;
+}
+
+static int namemap_name2num_n(const OSSL_NAMEMAP *namemap,
+ const char *name, size_t name_len)
+{
+ NAMENUM_ENTRY *namenum_entry, namenum_tmpl;
+
+ if ((namenum_tmpl.name = OPENSSL_strndup(name, name_len)) == NULL)
+ return 0;
+ namenum_tmpl.number = 0;
+ namenum_entry =
+ lh_NAMENUM_ENTRY_retrieve(namemap->namenum, &namenum_tmpl);
+ OPENSSL_free(namenum_tmpl.name);
+ return namenum_entry != NULL ? namenum_entry->number : 0;
+}
+
+int ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap,
+ const char *name, size_t name_len)
+{
+ int number;
+
+#ifndef FIPS_MODULE
+ if (namemap == NULL)
+ namemap = ossl_namemap_stored(NULL);
+#endif
+
+ if (namemap == NULL)
+ return 0;
+
+ if (!CRYPTO_THREAD_read_lock(namemap->lock))
+ return 0;
+ number = namemap_name2num_n(namemap, name, name_len);
+ CRYPTO_THREAD_unlock(namemap->lock);
+
+ return number;
+}
+
+int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name)
+{
+ if (name == NULL)
+ return 0;
+
+ return ossl_namemap_name2num_n(namemap, name, strlen(name));
+}
+
+struct num2name_data_st {
+ size_t idx; /* Countdown */
+ const char *name; /* Result */
+};
+
+static void do_num2name(const char *name, void *vdata)
+{
+ struct num2name_data_st *data = vdata;
+
+ if (data->idx > 0)
+ data->idx--;
+ else if (data->name == NULL)
+ data->name = name;
+}
+
+const char *ossl_namemap_num2name(const OSSL_NAMEMAP *namemap, int number,
+ size_t idx)
+{
+ struct num2name_data_st data;
+
+ data.idx = idx;
+ data.name = NULL;
+ if (!ossl_namemap_doall_names(namemap, number, do_num2name, &data))
+ return NULL;
+ return data.name;
+}
+
+static int namemap_add_name_n(OSSL_NAMEMAP *namemap, int number,
+ const char *name, size_t name_len)
+{
+ NAMENUM_ENTRY *namenum = NULL;
+ int tmp_number;
+
+ /* If it already exists, we don't add it */
+ if ((tmp_number = namemap_name2num_n(namemap, name, name_len)) != 0)
+ return tmp_number;
+
+ if ((namenum = OPENSSL_zalloc(sizeof(*namenum))) == NULL
+ || (namenum->name = OPENSSL_strndup(name, name_len)) == NULL)
+ goto err;
+
+ /* The tsan_counter use here is safe since we're under lock */
+ namenum->number =
+ number != 0 ? number : 1 + tsan_counter(&namemap->max_number);
+ (void)lh_NAMENUM_ENTRY_insert(namemap->namenum, namenum);
+
+ if (lh_NAMENUM_ENTRY_error(namemap->namenum))
+ goto err;
+ return namenum->number;
+
+ err:
+ namenum_free(namenum);
+ return 0;
+}
+
+int ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number,
+ const char *name, size_t name_len)
+{
+ int tmp_number;
+
+#ifndef FIPS_MODULE
+ if (namemap == NULL)
+ namemap = ossl_namemap_stored(NULL);
+#endif
+
+ if (name == NULL || name_len == 0 || namemap == NULL)
+ return 0;
+
+ if (!CRYPTO_THREAD_write_lock(namemap->lock))
+ return 0;
+ tmp_number = namemap_add_name_n(namemap, number, name, name_len);
+ CRYPTO_THREAD_unlock(namemap->lock);
+ return tmp_number;
+}
+
+int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number, const char *name)
+{
+ if (name == NULL)
+ return 0;
+
+ return ossl_namemap_add_name_n(namemap, number, name, strlen(name));
+}
+
+int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number,
+ const char *names, const char separator)
+{
+ const char *p, *q;
+ size_t l;
+
+ /* Check that we have a namemap */
+ if (!ossl_assert(namemap != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (!CRYPTO_THREAD_write_lock(namemap->lock))
+ return 0;
+ /*
+ * Check that no name is an empty string, and that all names have at
+ * most one numeric identity together.
+ */
+ for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) {
+ int this_number;
+
+ if ((q = strchr(p, separator)) == NULL)
+ l = strlen(p); /* offset to \0 */
+ else
+ l = q - p; /* offset to the next separator */
+
+ this_number = namemap_name2num_n(namemap, p, l);
+
+ if (*p == '\0' || *p == separator) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_BAD_ALGORITHM_NAME);
+ goto err;
+ }
+ if (number == 0) {
+ number = this_number;
+ } else if (this_number != 0 && this_number != number) {
+ ERR_raise_data(ERR_LIB_CRYPTO, CRYPTO_R_CONFLICTING_NAMES,
+ "\"%.*s\" has an existing different identity %d (from \"%s\")",
+ l, p, this_number, names);
+ goto err;
+ }
+ }
+
+ /* Now that we have checked, register all names */
+ for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) {
+ int this_number;
+
+ if ((q = strchr(p, separator)) == NULL)
+ l = strlen(p); /* offset to \0 */
+ else
+ l = q - p; /* offset to the next separator */
+
+ this_number = namemap_add_name_n(namemap, number, p, l);
+ if (number == 0) {
+ number = this_number;
+ } else if (this_number != number) {
+ ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR,
+ "Got number %d when expecting %d",
+ this_number, number);
+ goto err;
+ }
+ }
+
+ CRYPTO_THREAD_unlock(namemap->lock);
+ return number;
+
+ err:
+ CRYPTO_THREAD_unlock(namemap->lock);
+ return 0;
+}
+
+/*-
+ * Pre-population
+ * ==============
+ */
+
+#ifndef FIPS_MODULE
+#include <openssl/evp.h>
+
+/* Creates an initial namemap with names found in the legacy method db */
+static void get_legacy_evp_names(int base_nid, int nid, const char *pem_name,
+ void *arg)
+{
+ int num = 0;
+ ASN1_OBJECT *obj;
+
+ if (base_nid != NID_undef) {
+ num = ossl_namemap_add_name(arg, num, OBJ_nid2sn(base_nid));
+ num = ossl_namemap_add_name(arg, num, OBJ_nid2ln(base_nid));
+ }
+
+ if (nid != NID_undef) {
+ num = ossl_namemap_add_name(arg, num, OBJ_nid2sn(nid));
+ num = ossl_namemap_add_name(arg, num, OBJ_nid2ln(nid));
+ if ((obj = OBJ_nid2obj(nid)) != NULL) {
+ char txtoid[OSSL_MAX_NAME_SIZE];
+
+ if (OBJ_obj2txt(txtoid, sizeof(txtoid), obj, 1) > 0)
+ num = ossl_namemap_add_name(arg, num, txtoid);
+ }
+ }
+ if (pem_name != NULL)
+ num = ossl_namemap_add_name(arg, num, pem_name);
+}
+
+static void get_legacy_cipher_names(const OBJ_NAME *on, void *arg)
+{
+ const EVP_CIPHER *cipher = (void *)OBJ_NAME_get(on->name, on->type);
+
+ if (cipher != NULL)
+ get_legacy_evp_names(NID_undef, EVP_CIPHER_get_type(cipher), NULL, arg);
+}
+
+static void get_legacy_md_names(const OBJ_NAME *on, void *arg)
+{
+ const EVP_MD *md = (void *)OBJ_NAME_get(on->name, on->type);
+
+ if (md != NULL)
+ get_legacy_evp_names(0, EVP_MD_get_type(md), NULL, arg);
+}
+
+static void get_legacy_pkey_meth_names(const EVP_PKEY_ASN1_METHOD *ameth,
+ void *arg)
+{
+ int nid = 0, base_nid = 0, flags = 0;
+ const char *pem_name = NULL;
+
+ EVP_PKEY_asn1_get0_info(&nid, &base_nid, &flags, NULL, &pem_name, ameth);
+ if (nid != NID_undef) {
+ if ((flags & ASN1_PKEY_ALIAS) == 0) {
+ switch (nid) {
+ case EVP_PKEY_DHX:
+ /* We know that the name "DHX" is used too */
+ get_legacy_evp_names(0, nid, "DHX", arg);
+ /* FALLTHRU */
+ default:
+ get_legacy_evp_names(0, nid, pem_name, arg);
+ }
+ } else {
+ /*
+ * Treat aliases carefully, some of them are undesirable, or
+ * should not be treated as such for providers.
+ */
+
+ switch (nid) {
+ case EVP_PKEY_SM2:
+ /*
+ * SM2 is a separate keytype with providers, not an alias for
+ * EC.
+ */
+ get_legacy_evp_names(0, nid, pem_name, arg);
+ break;
+ default:
+ /* Use the short name of the base nid as the common reference */
+ get_legacy_evp_names(base_nid, nid, pem_name, arg);
+ }
+ }
+ }
+}
+#endif
+
+/*-
+ * Constructors / destructors
+ * ==========================
+ */
+
+OSSL_NAMEMAP *ossl_namemap_stored(OSSL_LIB_CTX *libctx)
+{
+#ifndef FIPS_MODULE
+ int nms;
+#endif
+ OSSL_NAMEMAP *namemap =
+ ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_NAMEMAP_INDEX,
+ &stored_namemap_method);
+
+ if (namemap == NULL)
+ return NULL;
+
+#ifndef FIPS_MODULE
+ nms = ossl_namemap_empty(namemap);
+ if (nms < 0) {
+ /*
+ * Could not get lock to make the count, so maybe internal objects
+ * weren't added. This seems safest.
+ */
+ return NULL;
+ }
+ if (nms == 1) {
+ int i, end;
+
+ /* Before pilfering, we make sure the legacy database is populated */
+ OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
+ | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
+
+ OBJ_NAME_do_all(OBJ_NAME_TYPE_CIPHER_METH,
+ get_legacy_cipher_names, namemap);
+ OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH,
+ get_legacy_md_names, namemap);
+
+ /* We also pilfer data from the legacy EVP_PKEY_ASN1_METHODs */
+ for (i = 0, end = EVP_PKEY_asn1_get_count(); i < end; i++)
+ get_legacy_pkey_meth_names(EVP_PKEY_asn1_get0(i), namemap);
+ }
+#endif
+
+ return namemap;
+}
+
+OSSL_NAMEMAP *ossl_namemap_new(void)
+{
+ OSSL_NAMEMAP *namemap;
+
+ if ((namemap = OPENSSL_zalloc(sizeof(*namemap))) != NULL
+ && (namemap->lock = CRYPTO_THREAD_lock_new()) != NULL
+ && (namemap->namenum =
+ lh_NAMENUM_ENTRY_new(namenum_hash, namenum_cmp)) != NULL)
+ return namemap;
+
+ ossl_namemap_free(namemap);
+ return NULL;
+}
+
+void ossl_namemap_free(OSSL_NAMEMAP *namemap)
+{
+ if (namemap == NULL || namemap->stored)
+ return;
+
+ lh_NAMENUM_ENTRY_doall(namemap->namenum, namenum_free);
+ lh_NAMENUM_ENTRY_free(namemap->namenum);
+
+ CRYPTO_THREAD_lock_free(namemap->lock);
+ OPENSSL_free(namemap);
+}
diff --git a/crypto/cpt_err.c b/crypto/cpt_err.c
index 4147b1cb9e23..8574f31a8124 100644
--- a/crypto/cpt_err.c
+++ b/crypto/cpt_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,68 +10,61 @@
#include <openssl/err.h>
#include <openssl/cryptoerr.h>
+#include "crypto/cryptoerr.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA CRYPTO_str_functs[] = {
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CMAC_CTX_NEW, 0), "CMAC_CTX_new"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_DUP_EX_DATA, 0),
- "CRYPTO_dup_ex_data"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_FREE_EX_DATA, 0),
- "CRYPTO_free_ex_data"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, 0),
- "CRYPTO_get_ex_new_index"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_MEMDUP, 0), "CRYPTO_memdup"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_NEW_EX_DATA, 0),
- "CRYPTO_new_ex_data"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_OCB128_COPY_CTX, 0),
- "CRYPTO_ocb128_copy_ctx"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_OCB128_INIT, 0),
- "CRYPTO_ocb128_init"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_SET_EX_DATA, 0),
- "CRYPTO_set_ex_data"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_FIPS_MODE_SET, 0), "FIPS_mode_set"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_GET_AND_LOCK, 0), "get_and_lock"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_ATEXIT, 0), "OPENSSL_atexit"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_BUF2HEXSTR, 0),
- "OPENSSL_buf2hexstr"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_FOPEN, 0), "openssl_fopen"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_HEXSTR2BUF, 0),
- "OPENSSL_hexstr2buf"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_INIT_CRYPTO, 0),
- "OPENSSL_init_crypto"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_LH_NEW, 0), "OPENSSL_LH_new"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_SK_DEEP_COPY, 0),
- "OPENSSL_sk_deep_copy"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_SK_DUP, 0), "OPENSSL_sk_dup"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PKEY_HMAC_INIT, 0), "pkey_hmac_init"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PKEY_POLY1305_INIT, 0),
- "pkey_poly1305_init"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PKEY_SIPHASH_INIT, 0),
- "pkey_siphash_init"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_SK_RESERVE, 0), "sk_reserve"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA CRYPTO_str_reasons[] = {
- {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_FIPS_MODE_NOT_SUPPORTED),
- "fips mode not supported"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_BAD_ALGORITHM_NAME),
+ "bad algorithm name"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_CONFLICTING_NAMES),
+ "conflicting names"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_HEX_STRING_TOO_SHORT),
+ "hex string too short"},
{ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_ILLEGAL_HEX_DIGIT),
"illegal hex digit"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_INSUFFICIENT_DATA_SPACE),
+ "insufficient data space"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_INSUFFICIENT_PARAM_SIZE),
+ "insufficient param size"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_INSUFFICIENT_SECURE_DATA_SPACE),
+ "insufficient secure data space"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_INVALID_NEGATIVE_VALUE),
+ "invalid negative value"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_INVALID_NULL_ARGUMENT),
+ "invalid null argument"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_INVALID_OSSL_PARAM_TYPE),
+ "invalid ossl param type"},
{ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_ODD_NUMBER_OF_DIGITS),
"odd number of digits"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_PROVIDER_ALREADY_EXISTS),
+ "provider already exists"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_PROVIDER_SECTION_ERROR),
+ "provider section error"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_RANDOM_SECTION_ERROR),
+ "random section error"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_SECURE_MALLOC_FAILURE),
+ "secure malloc failure"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_STRING_TOO_LONG), "string too long"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_TOO_MANY_BYTES), "too many bytes"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_TOO_MANY_RECORDS),
+ "too many records"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_TOO_SMALL_BUFFER),
+ "too small buffer"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION),
+ "unknown name in random section"},
+ {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_ZERO_LENGTH_NUMBER),
+ "zero length number"},
{0, NULL}
};
#endif
-int ERR_load_CRYPTO_strings(void)
+int ossl_err_load_CRYPTO_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(CRYPTO_str_functs[0].error) == NULL) {
- ERR_load_strings_const(CRYPTO_str_functs);
+ if (ERR_reason_error_string(CRYPTO_str_reasons[0].error) == NULL)
ERR_load_strings_const(CRYPTO_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/cpuid.c b/crypto/cpuid.c
new file mode 100644
index 000000000000..090f6fe03ecc
--- /dev/null
+++ b/crypto/cpuid.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "e_os.h"
+#include "crypto/cryptlib.h"
+
+#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
+ defined(__x86_64) || defined(__x86_64__) || \
+ defined(_M_AMD64) || defined(_M_X64)
+
+extern unsigned int OPENSSL_ia32cap_P[4];
+
+# if defined(OPENSSL_CPUID_OBJ)
+
+/*
+ * Purpose of these minimalistic and character-type-agnostic subroutines
+ * is to break dependency on MSVCRT (on Windows) and locale. This makes
+ * OPENSSL_cpuid_setup safe to use as "constructor". "Character-type-
+ * agnostic" means that they work with either wide or 8-bit characters,
+ * exploiting the fact that first 127 characters can be simply casted
+ * between the sets, while the rest would be simply rejected by ossl_is*
+ * subroutines.
+ */
+# ifdef _WIN32
+typedef WCHAR variant_char;
+
+static variant_char *ossl_getenv(const char *name)
+{
+ /*
+ * Since we pull only one environment variable, it's simpler to
+ * to just ignore |name| and use equivalent wide-char L-literal.
+ * As well as to ignore excessively long values...
+ */
+ static WCHAR value[48];
+ DWORD len = GetEnvironmentVariableW(L"OPENSSL_ia32cap", value, 48);
+
+ return (len > 0 && len < 48) ? value : NULL;
+}
+# else
+typedef char variant_char;
+# define ossl_getenv getenv
+# endif
+
+# include "crypto/ctype.h"
+
+static int todigit(variant_char c)
+{
+ if (ossl_isdigit(c))
+ return c - '0';
+ else if (ossl_isxdigit(c))
+ return ossl_tolower(c) - 'a' + 10;
+
+ /* return largest base value to make caller terminate the loop */
+ return 16;
+}
+
+static uint64_t ossl_strtouint64(const variant_char *str)
+{
+ uint64_t ret = 0;
+ unsigned int digit, base = 10;
+
+ if (*str == '0') {
+ base = 8, str++;
+ if (ossl_tolower(*str) == 'x')
+ base = 16, str++;
+ }
+
+ while((digit = todigit(*str++)) < base)
+ ret = ret * base + digit;
+
+ return ret;
+}
+
+static variant_char *ossl_strchr(const variant_char *str, char srch)
+{ variant_char c;
+
+ while((c = *str)) {
+ if (c == srch)
+ return (variant_char *)str;
+ str++;
+ }
+
+ return NULL;
+}
+
+# define OPENSSL_CPUID_SETUP
+typedef uint64_t IA32CAP;
+
+void OPENSSL_cpuid_setup(void)
+{
+ static int trigger = 0;
+ IA32CAP OPENSSL_ia32_cpuid(unsigned int *);
+ IA32CAP vec;
+ const variant_char *env;
+
+ if (trigger)
+ return;
+
+ trigger = 1;
+ if ((env = ossl_getenv("OPENSSL_ia32cap")) != NULL) {
+ int off = (env[0] == '~') ? 1 : 0;
+
+ vec = ossl_strtouint64(env + off);
+
+ if (off) {
+ IA32CAP mask = vec;
+ vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P) & ~mask;
+ if (mask & (1<<24)) {
+ /*
+ * User disables FXSR bit, mask even other capabilities
+ * that operate exclusively on XMM, so we don't have to
+ * double-check all the time. We mask PCLMULQDQ, AMD XOP,
+ * AES-NI and AVX. Formally speaking we don't have to
+ * do it in x86_64 case, but we can safely assume that
+ * x86_64 users won't actually flip this flag.
+ */
+ vec &= ~((IA32CAP)(1<<1|1<<11|1<<25|1<<28) << 32);
+ }
+ } else if (env[0] == ':') {
+ vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P);
+ }
+
+ if ((env = ossl_strchr(env, ':')) != NULL) {
+ IA32CAP vecx;
+
+ env++;
+ off = (env[0] == '~') ? 1 : 0;
+ vecx = ossl_strtouint64(env + off);
+ if (off) {
+ OPENSSL_ia32cap_P[2] &= ~(unsigned int)vecx;
+ OPENSSL_ia32cap_P[3] &= ~(unsigned int)(vecx >> 32);
+ } else {
+ OPENSSL_ia32cap_P[2] = (unsigned int)vecx;
+ OPENSSL_ia32cap_P[3] = (unsigned int)(vecx >> 32);
+ }
+ } else {
+ OPENSSL_ia32cap_P[2] = 0;
+ OPENSSL_ia32cap_P[3] = 0;
+ }
+ } else {
+ vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P);
+ }
+
+ /*
+ * |(1<<10) sets a reserved bit to signal that variable
+ * was initialized already... This is to avoid interference
+ * with cpuid snippets in ELF .init segment.
+ */
+ OPENSSL_ia32cap_P[0] = (unsigned int)vec | (1 << 10);
+ OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32);
+}
+# else
+unsigned int OPENSSL_ia32cap_P[4];
+# endif
+#endif
+
+#ifndef OPENSSL_CPUID_OBJ
+# ifndef OPENSSL_CPUID_SETUP
+void OPENSSL_cpuid_setup(void)
+{
+}
+# endif
+
+/*
+ * The rest are functions that are defined in the same assembler files as
+ * the CPUID functionality.
+ */
+
+/*
+ * The volatile is used to to ensure that the compiler generates code that reads
+ * all values from the array and doesn't try to optimize this away. The standard
+ * doesn't actually require this behavior if the original data pointed to is
+ * not volatile, but compilers do this in practice anyway.
+ *
+ * There are also assembler versions of this function.
+ */
+# undef CRYPTO_memcmp
+int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len)
+{
+ size_t i;
+ const volatile unsigned char *a = in_a;
+ const volatile unsigned char *b = in_b;
+ unsigned char x = 0;
+
+ for (i = 0; i < len; i++)
+ x |= a[i] ^ b[i];
+
+ return x;
+}
+
+/*
+ * For systems that don't provide an instruction counter register or equivalent.
+ */
+uint32_t OPENSSL_rdtsc(void)
+{
+ return 0;
+}
+
+size_t OPENSSL_instrument_bus(unsigned int *out, size_t cnt)
+{
+ return 0;
+}
+
+size_t OPENSSL_instrument_bus2(unsigned int *out, size_t cnt, size_t max)
+{
+ return 0;
+}
+#endif
diff --git a/crypto/crmf/build.info b/crypto/crmf/build.info
new file mode 100644
index 000000000000..7cfa8ec2b076
--- /dev/null
+++ b/crypto/crmf/build.info
@@ -0,0 +1,2 @@
+LIBS=../../libcrypto
+SOURCE[../../libcrypto]=crmf_asn.c crmf_err.c crmf_lib.c crmf_pbm.c
diff --git a/crypto/crmf/crmf_asn.c b/crypto/crmf/crmf_asn.c
new file mode 100644
index 000000000000..3354b89736e9
--- /dev/null
+++ b/crypto/crmf/crmf_asn.c
@@ -0,0 +1,235 @@
+/*-
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * CRMF implementation by Martin Peylo, Miikka Viljanen, and David von Oheimb.
+ */
+
+#include <openssl/asn1t.h>
+
+#include "crmf_local.h"
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <openssl/crmf.h>
+
+ASN1_SEQUENCE(OSSL_CRMF_PRIVATEKEYINFO) = {
+ ASN1_SIMPLE(OSSL_CRMF_PRIVATEKEYINFO, version, ASN1_INTEGER),
+ ASN1_SIMPLE(OSSL_CRMF_PRIVATEKEYINFO, privateKeyAlgorithm, X509_ALGOR),
+ ASN1_SIMPLE(OSSL_CRMF_PRIVATEKEYINFO, privateKey, ASN1_OCTET_STRING),
+ ASN1_IMP_SET_OF_OPT(OSSL_CRMF_PRIVATEKEYINFO, attributes, X509_ATTRIBUTE, 0)
+} ASN1_SEQUENCE_END(OSSL_CRMF_PRIVATEKEYINFO)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_PRIVATEKEYINFO)
+
+
+ASN1_CHOICE(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER) = {
+ ASN1_SIMPLE(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER, value.string, ASN1_UTF8STRING),
+ ASN1_SIMPLE(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER, value.generalName, GENERAL_NAME)
+} ASN1_CHOICE_END(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_ENCKEYWITHID) = {
+ ASN1_SIMPLE(OSSL_CRMF_ENCKEYWITHID, privateKey, OSSL_CRMF_PRIVATEKEYINFO),
+ ASN1_OPT(OSSL_CRMF_ENCKEYWITHID, identifier,
+ OSSL_CRMF_ENCKEYWITHID_IDENTIFIER)
+} ASN1_SEQUENCE_END(OSSL_CRMF_ENCKEYWITHID)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ENCKEYWITHID)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_CERTID) = {
+ ASN1_SIMPLE(OSSL_CRMF_CERTID, issuer, GENERAL_NAME),
+ ASN1_SIMPLE(OSSL_CRMF_CERTID, serialNumber, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(OSSL_CRMF_CERTID)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_CERTID)
+IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTID)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_ENCRYPTEDVALUE) = {
+ ASN1_IMP_OPT(OSSL_CRMF_ENCRYPTEDVALUE, intendedAlg, X509_ALGOR, 0),
+ ASN1_IMP_OPT(OSSL_CRMF_ENCRYPTEDVALUE, symmAlg, X509_ALGOR, 1),
+ ASN1_IMP_OPT(OSSL_CRMF_ENCRYPTEDVALUE, encSymmKey, ASN1_BIT_STRING, 2),
+ ASN1_IMP_OPT(OSSL_CRMF_ENCRYPTEDVALUE, keyAlg, X509_ALGOR, 3),
+ ASN1_IMP_OPT(OSSL_CRMF_ENCRYPTEDVALUE, valueHint, ASN1_OCTET_STRING, 4),
+ ASN1_SIMPLE(OSSL_CRMF_ENCRYPTEDVALUE, encValue, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(OSSL_CRMF_ENCRYPTEDVALUE)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ENCRYPTEDVALUE)
+
+ASN1_SEQUENCE(OSSL_CRMF_SINGLEPUBINFO) = {
+ ASN1_SIMPLE(OSSL_CRMF_SINGLEPUBINFO, pubMethod, ASN1_INTEGER),
+ ASN1_SIMPLE(OSSL_CRMF_SINGLEPUBINFO, pubLocation, GENERAL_NAME)
+} ASN1_SEQUENCE_END(OSSL_CRMF_SINGLEPUBINFO)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_SINGLEPUBINFO)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_PKIPUBLICATIONINFO) = {
+ ASN1_SIMPLE(OSSL_CRMF_PKIPUBLICATIONINFO, action, ASN1_INTEGER),
+ ASN1_SEQUENCE_OF_OPT(OSSL_CRMF_PKIPUBLICATIONINFO, pubInfos,
+ OSSL_CRMF_SINGLEPUBINFO)
+} ASN1_SEQUENCE_END(OSSL_CRMF_PKIPUBLICATIONINFO)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_PKIPUBLICATIONINFO)
+IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CRMF_PKIPUBLICATIONINFO)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_PKMACVALUE) = {
+ ASN1_SIMPLE(OSSL_CRMF_PKMACVALUE, algId, X509_ALGOR),
+ ASN1_SIMPLE(OSSL_CRMF_PKMACVALUE, value, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(OSSL_CRMF_PKMACVALUE)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_PKMACVALUE)
+
+
+ASN1_CHOICE(OSSL_CRMF_POPOPRIVKEY) = {
+ ASN1_IMP(OSSL_CRMF_POPOPRIVKEY, value.thisMessage, ASN1_BIT_STRING, 0),
+ ASN1_IMP(OSSL_CRMF_POPOPRIVKEY, value.subsequentMessage, ASN1_INTEGER, 1),
+ ASN1_IMP(OSSL_CRMF_POPOPRIVKEY, value.dhMAC, ASN1_BIT_STRING, 2),
+ ASN1_IMP(OSSL_CRMF_POPOPRIVKEY, value.agreeMAC, OSSL_CRMF_PKMACVALUE, 3),
+ ASN1_IMP(OSSL_CRMF_POPOPRIVKEY, value.encryptedKey, ASN1_NULL, 4),
+} ASN1_CHOICE_END(OSSL_CRMF_POPOPRIVKEY)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_POPOPRIVKEY)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_PBMPARAMETER) = {
+ ASN1_SIMPLE(OSSL_CRMF_PBMPARAMETER, salt, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(OSSL_CRMF_PBMPARAMETER, owf, X509_ALGOR),
+ ASN1_SIMPLE(OSSL_CRMF_PBMPARAMETER, iterationCount, ASN1_INTEGER),
+ ASN1_SIMPLE(OSSL_CRMF_PBMPARAMETER, mac, X509_ALGOR)
+} ASN1_SEQUENCE_END(OSSL_CRMF_PBMPARAMETER)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_PBMPARAMETER)
+
+
+ASN1_CHOICE(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO) = {
+ ASN1_EXP(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO, value.sender,
+ GENERAL_NAME, 0),
+ ASN1_SIMPLE(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO, value.publicKeyMAC,
+ OSSL_CRMF_PKMACVALUE)
+} ASN1_CHOICE_END(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_POPOSIGNINGKEYINPUT) = {
+ ASN1_SIMPLE(OSSL_CRMF_POPOSIGNINGKEYINPUT, authInfo,
+ OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO),
+ ASN1_SIMPLE(OSSL_CRMF_POPOSIGNINGKEYINPUT, publicKey, X509_PUBKEY)
+} ASN1_SEQUENCE_END(OSSL_CRMF_POPOSIGNINGKEYINPUT)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_POPOSIGNINGKEYINPUT)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_POPOSIGNINGKEY) = {
+ ASN1_IMP_OPT(OSSL_CRMF_POPOSIGNINGKEY, poposkInput,
+ OSSL_CRMF_POPOSIGNINGKEYINPUT, 0),
+ ASN1_SIMPLE(OSSL_CRMF_POPOSIGNINGKEY, algorithmIdentifier, X509_ALGOR),
+ ASN1_SIMPLE(OSSL_CRMF_POPOSIGNINGKEY, signature, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(OSSL_CRMF_POPOSIGNINGKEY)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_POPOSIGNINGKEY)
+
+
+ASN1_CHOICE(OSSL_CRMF_POPO) = {
+ ASN1_IMP(OSSL_CRMF_POPO, value.raVerified, ASN1_NULL, 0),
+ ASN1_IMP(OSSL_CRMF_POPO, value.signature, OSSL_CRMF_POPOSIGNINGKEY, 1),
+ ASN1_EXP(OSSL_CRMF_POPO, value.keyEncipherment, OSSL_CRMF_POPOPRIVKEY, 2),
+ ASN1_EXP(OSSL_CRMF_POPO, value.keyAgreement, OSSL_CRMF_POPOPRIVKEY, 3)
+} ASN1_CHOICE_END(OSSL_CRMF_POPO)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_POPO)
+
+
+ASN1_ADB_TEMPLATE(attributetypeandvalue_default) =
+ ASN1_OPT(OSSL_CRMF_ATTRIBUTETYPEANDVALUE, value.other, ASN1_ANY);
+ASN1_ADB(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) = {
+ ADB_ENTRY(NID_id_regCtrl_regToken,
+ ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
+ value.regToken, ASN1_UTF8STRING)),
+ ADB_ENTRY(NID_id_regCtrl_authenticator,
+ ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
+ value.authenticator, ASN1_UTF8STRING)),
+ ADB_ENTRY(NID_id_regCtrl_pkiPublicationInfo,
+ ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
+ value.pkiPublicationInfo,
+ OSSL_CRMF_PKIPUBLICATIONINFO)),
+ ADB_ENTRY(NID_id_regCtrl_oldCertID,
+ ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
+ value.oldCertID, OSSL_CRMF_CERTID)),
+ ADB_ENTRY(NID_id_regCtrl_protocolEncrKey,
+ ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
+ value.protocolEncrKey, X509_PUBKEY)),
+ ADB_ENTRY(NID_id_regInfo_utf8Pairs,
+ ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
+ value.utf8Pairs, ASN1_UTF8STRING)),
+ ADB_ENTRY(NID_id_regInfo_certReq,
+ ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
+ value.certReq, OSSL_CRMF_CERTREQUEST)),
+} ASN1_ADB_END(OSSL_CRMF_ATTRIBUTETYPEANDVALUE, 0, type, 0,
+ &attributetypeandvalue_default_tt, NULL);
+
+
+ASN1_SEQUENCE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) = {
+ ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE, type, ASN1_OBJECT),
+ ASN1_ADB_OBJECT(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+} ASN1_SEQUENCE_END(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_OPTIONALVALIDITY) = {
+ ASN1_EXP_OPT(OSSL_CRMF_OPTIONALVALIDITY, notBefore, ASN1_TIME, 0),
+ ASN1_EXP_OPT(OSSL_CRMF_OPTIONALVALIDITY, notAfter, ASN1_TIME, 1)
+} ASN1_SEQUENCE_END(OSSL_CRMF_OPTIONALVALIDITY)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_OPTIONALVALIDITY)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_CERTTEMPLATE) = {
+ ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, version, ASN1_INTEGER, 0),
+ /*
+ * serialNumber MUST be omitted. This field is assigned by the CA
+ * during certificate creation.
+ */
+ ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, serialNumber, ASN1_INTEGER, 1),
+ /*
+ * signingAlg MUST be omitted. This field is assigned by the CA
+ * during certificate creation.
+ */
+ ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, signingAlg, X509_ALGOR, 2),
+ ASN1_EXP_OPT(OSSL_CRMF_CERTTEMPLATE, issuer, X509_NAME, 3),
+ ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, validity,
+ OSSL_CRMF_OPTIONALVALIDITY, 4),
+ ASN1_EXP_OPT(OSSL_CRMF_CERTTEMPLATE, subject, X509_NAME, 5),
+ ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, publicKey, X509_PUBKEY, 6),
+ /* issuerUID is deprecated in version 2 */
+ ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, issuerUID, ASN1_BIT_STRING, 7),
+ /* subjectUID is deprecated in version 2 */
+ ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, subjectUID, ASN1_BIT_STRING, 8),
+ ASN1_IMP_SEQUENCE_OF_OPT(OSSL_CRMF_CERTTEMPLATE, extensions,
+ X509_EXTENSION, 9),
+} ASN1_SEQUENCE_END(OSSL_CRMF_CERTTEMPLATE)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_CERTTEMPLATE)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_CERTREQUEST) = {
+ ASN1_SIMPLE(OSSL_CRMF_CERTREQUEST, certReqId, ASN1_INTEGER),
+ ASN1_SIMPLE(OSSL_CRMF_CERTREQUEST, certTemplate, OSSL_CRMF_CERTTEMPLATE),
+ ASN1_SEQUENCE_OF_OPT(OSSL_CRMF_CERTREQUEST, controls,
+ OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+} ASN1_SEQUENCE_END(OSSL_CRMF_CERTREQUEST)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_CERTREQUEST)
+IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTREQUEST)
+
+
+ASN1_SEQUENCE(OSSL_CRMF_MSG) = {
+ ASN1_SIMPLE(OSSL_CRMF_MSG, certReq, OSSL_CRMF_CERTREQUEST),
+ ASN1_OPT(OSSL_CRMF_MSG, popo, OSSL_CRMF_POPO),
+ ASN1_SEQUENCE_OF_OPT(OSSL_CRMF_MSG, regInfo,
+ OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+} ASN1_SEQUENCE_END(OSSL_CRMF_MSG)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_MSG)
+IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CRMF_MSG)
+
+ASN1_ITEM_TEMPLATE(OSSL_CRMF_MSGS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0,
+ OSSL_CRMF_MSGS, OSSL_CRMF_MSG)
+ASN1_ITEM_TEMPLATE_END(OSSL_CRMF_MSGS)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_MSGS)
diff --git a/crypto/crmf/crmf_err.c b/crypto/crmf/crmf_err.c
new file mode 100644
index 000000000000..44b2f2757d2c
--- /dev/null
+++ b/crypto/crmf/crmf_err.c
@@ -0,0 +1,74 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/crmferr.h>
+#include "crypto/crmferr.h"
+
+#ifndef OPENSSL_NO_CRMF
+
+# ifndef OPENSSL_NO_ERR
+
+static const ERR_STRING_DATA CRMF_str_reasons[] = {
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_BAD_PBM_ITERATIONCOUNT),
+ "bad pbm iterationcount"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_CRMFERROR), "crmferror"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR), "error"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECODING_CERTIFICATE),
+ "error decoding certificate"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECRYPTING_CERTIFICATE),
+ "error decrypting certificate"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY),
+ "error decrypting symmetric key"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_FAILURE_OBTAINING_RANDOM),
+ "failure obtaining random"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ITERATIONCOUNT_BELOW_100),
+ "iterationcount below 100"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_MALFORMED_IV), "malformed iv"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_NULL_ARGUMENT), "null argument"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPOSKINPUT_NOT_SUPPORTED),
+ "poposkinput not supported"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY),
+ "popo inconsistent public key"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING), "popo missing"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING_PUBLIC_KEY),
+ "popo missing public key"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING_SUBJECT),
+ "popo missing subject"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED),
+ "popo raverified not accepted"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_SETTING_MAC_ALGOR_FAILURE),
+ "setting mac algor failure"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_SETTING_OWF_ALGOR_FAILURE),
+ "setting owf algor failure"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_ALGORITHM),
+ "unsupported algorithm"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_CIPHER),
+ "unsupported cipher"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO),
+ "unsupported method for creating popo"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_POPO_METHOD),
+ "unsupported popo method"},
+ {0, NULL}
+};
+
+# endif
+
+int ossl_err_load_CRMF_strings(void)
+{
+# ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(CRMF_str_reasons[0].error) == NULL)
+ ERR_load_strings_const(CRMF_str_reasons);
+# endif
+ return 1;
+}
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/crypto/crmf/crmf_lib.c b/crypto/crmf/crmf_lib.c
new file mode 100644
index 000000000000..3607fb0bf417
--- /dev/null
+++ b/crypto/crmf/crmf_lib.c
@@ -0,0 +1,715 @@
+/*-
+ * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2018
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * CRMF implementation by Martin Peylo, Miikka Viljanen, and David von Oheimb.
+ */
+
+/*
+ * This file contains the functions that handle the individual items inside
+ * the CRMF structures
+ */
+
+/*
+ * NAMING
+ *
+ * The 0 functions use the supplied structure pointer directly in the parent and
+ * it will be freed up when the parent is freed.
+ *
+ * The 1 functions use a copy of the supplied structure pointer (or in some
+ * cases increases its link count) in the parent and so both should be freed up.
+ */
+
+#include <openssl/asn1t.h>
+
+#include "crmf_local.h"
+#include "internal/constant_time.h"
+#include "internal/sizes.h"
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <openssl/crmf.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+/*-
+ * atyp = Attribute Type
+ * valt = Value Type
+ * ctrlinf = "regCtrl" or "regInfo"
+ */
+#define IMPLEMENT_CRMF_CTRL_FUNC(atyp, valt, ctrlinf) \
+valt *OSSL_CRMF_MSG_get0_##ctrlinf##_##atyp(const OSSL_CRMF_MSG *msg) \
+{ \
+ int i; \
+ STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) *controls; \
+ OSSL_CRMF_ATTRIBUTETYPEANDVALUE *atav = NULL; \
+ \
+ if (msg == NULL || msg->certReq == NULL) \
+ return NULL; \
+ controls = msg->certReq->controls; \
+ for (i = 0; i < sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_num(controls); i++) { \
+ atav = sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_value(controls, i); \
+ if (OBJ_obj2nid(atav->type) == NID_id_##ctrlinf##_##atyp) \
+ return atav->value.atyp; \
+ } \
+ return NULL; \
+} \
+ \
+int OSSL_CRMF_MSG_set1_##ctrlinf##_##atyp(OSSL_CRMF_MSG *msg, const valt *in) \
+{ \
+ OSSL_CRMF_ATTRIBUTETYPEANDVALUE *atav = NULL; \
+ \
+ if (msg == NULL || in == NULL) \
+ goto err; \
+ if ((atav = OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new()) == NULL) \
+ goto err; \
+ if ((atav->type = OBJ_nid2obj(NID_id_##ctrlinf##_##atyp)) == NULL) \
+ goto err; \
+ if ((atav->value.atyp = valt##_dup(in)) == NULL) \
+ goto err; \
+ if (!OSSL_CRMF_MSG_push0_##ctrlinf(msg, atav)) \
+ goto err; \
+ return 1; \
+ err: \
+ OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(atav); \
+ return 0; \
+}
+
+
+/*-
+ * Pushes the given control attribute into the controls stack of a CertRequest
+ * (section 6)
+ * returns 1 on success, 0 on error
+ */
+static int OSSL_CRMF_MSG_push0_regCtrl(OSSL_CRMF_MSG *crm,
+ OSSL_CRMF_ATTRIBUTETYPEANDVALUE *ctrl)
+{
+ int new = 0;
+
+ if (crm == NULL || crm->certReq == NULL || ctrl == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (crm->certReq->controls == NULL) {
+ crm->certReq->controls = sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new_null();
+ if (crm->certReq->controls == NULL)
+ goto err;
+ new = 1;
+ }
+ if (!sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_push(crm->certReq->controls, ctrl))
+ goto err;
+
+ return 1;
+ err:
+ if (new != 0) {
+ sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(crm->certReq->controls);
+ crm->certReq->controls = NULL;
+ }
+ return 0;
+}
+
+/* id-regCtrl-regToken Control (section 6.1) */
+IMPLEMENT_CRMF_CTRL_FUNC(regToken, ASN1_STRING, regCtrl)
+
+/* id-regCtrl-authenticator Control (section 6.2) */
+#define ASN1_UTF8STRING_dup ASN1_STRING_dup
+IMPLEMENT_CRMF_CTRL_FUNC(authenticator, ASN1_UTF8STRING, regCtrl)
+
+int OSSL_CRMF_MSG_set0_SinglePubInfo(OSSL_CRMF_SINGLEPUBINFO *spi,
+ int method, GENERAL_NAME *nm)
+{
+ if (spi == NULL
+ || method < OSSL_CRMF_PUB_METHOD_DONTCARE
+ || method > OSSL_CRMF_PUB_METHOD_LDAP) {
+ ERR_raise(ERR_LIB_CRMF, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ if (!ASN1_INTEGER_set(spi->pubMethod, method))
+ return 0;
+ GENERAL_NAME_free(spi->pubLocation);
+ spi->pubLocation = nm;
+ return 1;
+}
+
+int
+OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo(OSSL_CRMF_PKIPUBLICATIONINFO *pi,
+ OSSL_CRMF_SINGLEPUBINFO *spi)
+{
+ if (pi == NULL || spi == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (pi->pubInfos == NULL)
+ pi->pubInfos = sk_OSSL_CRMF_SINGLEPUBINFO_new_null();
+ if (pi->pubInfos == NULL)
+ return 0;
+
+ return sk_OSSL_CRMF_SINGLEPUBINFO_push(pi->pubInfos, spi);
+}
+
+int OSSL_CRMF_MSG_set_PKIPublicationInfo_action(OSSL_CRMF_PKIPUBLICATIONINFO *pi,
+ int action)
+{
+ if (pi == NULL
+ || action < OSSL_CRMF_PUB_ACTION_DONTPUBLISH
+ || action > OSSL_CRMF_PUB_ACTION_PLEASEPUBLISH) {
+ ERR_raise(ERR_LIB_CRMF, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ return ASN1_INTEGER_set(pi->action, action);
+}
+
+/* id-regCtrl-pkiPublicationInfo Control (section 6.3) */
+IMPLEMENT_CRMF_CTRL_FUNC(pkiPublicationInfo, OSSL_CRMF_PKIPUBLICATIONINFO,
+ regCtrl)
+
+/* id-regCtrl-oldCertID Control (section 6.5) from the given */
+IMPLEMENT_CRMF_CTRL_FUNC(oldCertID, OSSL_CRMF_CERTID, regCtrl)
+
+OSSL_CRMF_CERTID *OSSL_CRMF_CERTID_gen(const X509_NAME *issuer,
+ const ASN1_INTEGER *serial)
+{
+ OSSL_CRMF_CERTID *cid = NULL;
+
+ if (issuer == NULL || serial == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return NULL;
+ }
+
+ if ((cid = OSSL_CRMF_CERTID_new()) == NULL)
+ goto err;
+
+ if (!X509_NAME_set(&cid->issuer->d.directoryName, issuer))
+ goto err;
+ cid->issuer->type = GEN_DIRNAME;
+
+ ASN1_INTEGER_free(cid->serialNumber);
+ if ((cid->serialNumber = ASN1_INTEGER_dup(serial)) == NULL)
+ goto err;
+
+ return cid;
+
+ err:
+ OSSL_CRMF_CERTID_free(cid);
+ return NULL;
+}
+
+/*
+ * id-regCtrl-protocolEncrKey Control (section 6.6)
+ */
+IMPLEMENT_CRMF_CTRL_FUNC(protocolEncrKey, X509_PUBKEY, regCtrl)
+
+/*-
+ * Pushes the attribute given in regInfo in to the CertReqMsg->regInfo stack.
+ * (section 7)
+ * returns 1 on success, 0 on error
+ */
+static int OSSL_CRMF_MSG_push0_regInfo(OSSL_CRMF_MSG *crm,
+ OSSL_CRMF_ATTRIBUTETYPEANDVALUE *ri)
+{
+ STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) *info = NULL;
+
+ if (crm == NULL || ri == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (crm->regInfo == NULL)
+ crm->regInfo = info = sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new_null();
+ if (crm->regInfo == NULL)
+ goto err;
+ if (!sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_push(crm->regInfo, ri))
+ goto err;
+ return 1;
+
+ err:
+ if (info != NULL)
+ crm->regInfo = NULL;
+ sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(info);
+ return 0;
+}
+
+/* id-regInfo-utf8Pairs to regInfo (section 7.1) */
+IMPLEMENT_CRMF_CTRL_FUNC(utf8Pairs, ASN1_UTF8STRING, regInfo)
+
+/* id-regInfo-certReq to regInfo (section 7.2) */
+IMPLEMENT_CRMF_CTRL_FUNC(certReq, OSSL_CRMF_CERTREQUEST, regInfo)
+
+
+/* retrieves the certificate template of crm */
+OSSL_CRMF_CERTTEMPLATE *OSSL_CRMF_MSG_get0_tmpl(const OSSL_CRMF_MSG *crm)
+{
+ if (crm == NULL || crm->certReq == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return crm->certReq->certTemplate;
+}
+
+
+int OSSL_CRMF_MSG_set0_validity(OSSL_CRMF_MSG *crm,
+ ASN1_TIME *notBefore, ASN1_TIME *notAfter)
+{
+ OSSL_CRMF_OPTIONALVALIDITY *vld;
+ OSSL_CRMF_CERTTEMPLATE *tmpl = OSSL_CRMF_MSG_get0_tmpl(crm);
+
+ if (tmpl == NULL) { /* also crm == NULL implies this */
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if ((vld = OSSL_CRMF_OPTIONALVALIDITY_new()) == NULL)
+ return 0;
+ vld->notBefore = notBefore;
+ vld->notAfter = notAfter;
+ tmpl->validity = vld;
+ return 1;
+}
+
+
+int OSSL_CRMF_MSG_set_certReqId(OSSL_CRMF_MSG *crm, int rid)
+{
+ if (crm == NULL || crm->certReq == NULL || crm->certReq->certReqId == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ return ASN1_INTEGER_set(crm->certReq->certReqId, rid);
+}
+
+/* get ASN.1 encoded integer, return -1 on error */
+static int crmf_asn1_get_int(const ASN1_INTEGER *a)
+{
+ int64_t res;
+
+ if (!ASN1_INTEGER_get_int64(&res, a)) {
+ ERR_raise(ERR_LIB_CRMF, ASN1_R_INVALID_NUMBER);
+ return -1;
+ }
+ if (res < INT_MIN) {
+ ERR_raise(ERR_LIB_CRMF, ASN1_R_TOO_SMALL);
+ return -1;
+ }
+ if (res > INT_MAX) {
+ ERR_raise(ERR_LIB_CRMF, ASN1_R_TOO_LARGE);
+ return -1;
+ }
+ return (int)res;
+}
+
+int OSSL_CRMF_MSG_get_certReqId(const OSSL_CRMF_MSG *crm)
+{
+ if (crm == NULL || /* not really needed: */ crm->certReq == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return -1;
+ }
+ return crmf_asn1_get_int(crm->certReq->certReqId);
+}
+
+
+int OSSL_CRMF_MSG_set0_extensions(OSSL_CRMF_MSG *crm,
+ X509_EXTENSIONS *exts)
+{
+ OSSL_CRMF_CERTTEMPLATE *tmpl = OSSL_CRMF_MSG_get0_tmpl(crm);
+
+ if (tmpl == NULL) { /* also crm == NULL implies this */
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (sk_X509_EXTENSION_num(exts) == 0) {
+ sk_X509_EXTENSION_free(exts);
+ exts = NULL; /* do not include empty extensions list */
+ }
+
+ sk_X509_EXTENSION_pop_free(tmpl->extensions, X509_EXTENSION_free);
+ tmpl->extensions = exts;
+ return 1;
+}
+
+
+int OSSL_CRMF_MSG_push0_extension(OSSL_CRMF_MSG *crm,
+ X509_EXTENSION *ext)
+{
+ int new = 0;
+ OSSL_CRMF_CERTTEMPLATE *tmpl = OSSL_CRMF_MSG_get0_tmpl(crm);
+
+ if (tmpl == NULL || ext == NULL) { /* also crm == NULL implies this */
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (tmpl->extensions == NULL) {
+ if ((tmpl->extensions = sk_X509_EXTENSION_new_null()) == NULL)
+ goto err;
+ new = 1;
+ }
+
+ if (!sk_X509_EXTENSION_push(tmpl->extensions, ext))
+ goto err;
+ return 1;
+ err:
+ if (new != 0) {
+ sk_X509_EXTENSION_free(tmpl->extensions);
+ tmpl->extensions = NULL;
+ }
+ return 0;
+}
+
+static int create_popo_signature(OSSL_CRMF_POPOSIGNINGKEY *ps,
+ const OSSL_CRMF_CERTREQUEST *cr,
+ EVP_PKEY *pkey, const EVP_MD *digest,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ char name[80] = "";
+
+ if (ps == NULL || cr == NULL || pkey == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (ps->poposkInput != NULL) {
+ /* We do not support cases 1+2 defined in RFC 4211, section 4.1 */
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_POPOSKINPUT_NOT_SUPPORTED);
+ return 0;
+ }
+
+ if (EVP_PKEY_get_default_digest_name(pkey, name, sizeof(name)) > 0
+ && strcmp(name, "UNDEF") == 0) /* at least for Ed25519, Ed448 */
+ digest = NULL;
+
+ return ASN1_item_sign_ex(ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST),
+ ps->algorithmIdentifier, NULL, ps->signature, cr,
+ NULL, pkey, digest, libctx, propq);
+}
+
+
+int OSSL_CRMF_MSG_create_popo(int meth, OSSL_CRMF_MSG *crm,
+ EVP_PKEY *pkey, const EVP_MD *digest,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ OSSL_CRMF_POPO *pp = NULL;
+ ASN1_INTEGER *tag = NULL;
+
+ if (crm == NULL || (meth == OSSL_CRMF_POPO_SIGNATURE && pkey == NULL)) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (meth == OSSL_CRMF_POPO_NONE)
+ goto end;
+ if ((pp = OSSL_CRMF_POPO_new()) == NULL)
+ goto err;
+ pp->type = meth;
+
+ switch (meth) {
+ case OSSL_CRMF_POPO_RAVERIFIED:
+ if ((pp->value.raVerified = ASN1_NULL_new()) == NULL)
+ goto err;
+ break;
+
+ case OSSL_CRMF_POPO_SIGNATURE:
+ {
+ OSSL_CRMF_POPOSIGNINGKEY *ps = OSSL_CRMF_POPOSIGNINGKEY_new();
+
+ if (ps == NULL)
+ goto err;
+ if (!create_popo_signature(ps, crm->certReq, pkey, digest,
+ libctx, propq)) {
+ OSSL_CRMF_POPOSIGNINGKEY_free(ps);
+ goto err;
+ }
+ pp->value.signature = ps;
+ }
+ break;
+
+ case OSSL_CRMF_POPO_KEYENC:
+ if ((pp->value.keyEncipherment = OSSL_CRMF_POPOPRIVKEY_new()) == NULL)
+ goto err;
+ tag = ASN1_INTEGER_new();
+ pp->value.keyEncipherment->type =
+ OSSL_CRMF_POPOPRIVKEY_SUBSEQUENTMESSAGE;
+ pp->value.keyEncipherment->value.subsequentMessage = tag;
+ if (tag == NULL
+ || !ASN1_INTEGER_set(tag, OSSL_CRMF_SUBSEQUENTMESSAGE_ENCRCERT))
+ goto err;
+ break;
+
+ default:
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO);
+ goto err;
+ }
+
+ end:
+ OSSL_CRMF_POPO_free(crm->popo);
+ crm->popo = pp;
+
+ return 1;
+ err:
+ OSSL_CRMF_POPO_free(pp);
+ return 0;
+}
+
+/* verifies the Proof-of-Possession of the request with the given rid in reqs */
+int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs,
+ int rid, int acceptRAVerified,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ OSSL_CRMF_MSG *req = NULL;
+ X509_PUBKEY *pubkey = NULL;
+ OSSL_CRMF_POPOSIGNINGKEY *sig = NULL;
+ const ASN1_ITEM *it;
+ void *asn;
+
+ if (reqs == NULL || (req = sk_OSSL_CRMF_MSG_value(reqs, rid)) == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (req->popo == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_MISSING);
+ return 0;
+ }
+
+ switch (req->popo->type) {
+ case OSSL_CRMF_POPO_RAVERIFIED:
+ if (!acceptRAVerified) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED);
+ return 0;
+ }
+ break;
+ case OSSL_CRMF_POPO_SIGNATURE:
+ pubkey = req->certReq->certTemplate->publicKey;
+ if (pubkey == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_MISSING_PUBLIC_KEY);
+ return 0;
+ }
+ sig = req->popo->value.signature;
+ if (sig->poposkInput != NULL) {
+ /*
+ * According to RFC 4211: publicKey contains a copy of
+ * the public key from the certificate template. This MUST be
+ * exactly the same value as contained in the certificate template.
+ */
+ if (sig->poposkInput->publicKey == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_MISSING_PUBLIC_KEY);
+ return 0;
+ }
+ if (X509_PUBKEY_eq(pubkey, sig->poposkInput->publicKey) != 1) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY);
+ return 0;
+ }
+ it = ASN1_ITEM_rptr(OSSL_CRMF_POPOSIGNINGKEYINPUT);
+ asn = sig->poposkInput;
+ } else {
+ if (req->certReq->certTemplate->subject == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_MISSING_SUBJECT);
+ return 0;
+ }
+ it = ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST);
+ asn = req->certReq;
+ }
+ if (ASN1_item_verify_ex(it, sig->algorithmIdentifier, sig->signature,
+ asn, NULL, X509_PUBKEY_get0(pubkey), libctx,
+ propq) < 1)
+ return 0;
+ break;
+ case OSSL_CRMF_POPO_KEYENC:
+ case OSSL_CRMF_POPO_KEYAGREE:
+ default:
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_POPO_METHOD);
+ return 0;
+ }
+ return 1;
+}
+
+/* retrieves the serialNumber of the given cert template or NULL on error */
+const ASN1_INTEGER
+*OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(const OSSL_CRMF_CERTTEMPLATE *tmpl)
+{
+ return tmpl != NULL ? tmpl->serialNumber : NULL;
+}
+
+const X509_NAME
+ *OSSL_CRMF_CERTTEMPLATE_get0_subject(const OSSL_CRMF_CERTTEMPLATE *tmpl)
+{
+ return tmpl != NULL ? tmpl->subject : NULL;
+}
+
+/* retrieves the issuer name of the given cert template or NULL on error */
+const X509_NAME
+ *OSSL_CRMF_CERTTEMPLATE_get0_issuer(const OSSL_CRMF_CERTTEMPLATE *tmpl)
+{
+ return tmpl != NULL ? tmpl->issuer : NULL;
+}
+
+X509_EXTENSIONS
+ *OSSL_CRMF_CERTTEMPLATE_get0_extensions(const OSSL_CRMF_CERTTEMPLATE *tmpl)
+{
+ return tmpl != NULL ? tmpl->extensions : NULL;
+}
+
+/* retrieves the issuer name of the given CertId or NULL on error */
+const X509_NAME *OSSL_CRMF_CERTID_get0_issuer(const OSSL_CRMF_CERTID *cid)
+{
+ return cid != NULL && cid->issuer->type == GEN_DIRNAME ?
+ cid->issuer->d.directoryName : NULL;
+}
+
+/* retrieves the serialNumber of the given CertId or NULL on error */
+const ASN1_INTEGER *OSSL_CRMF_CERTID_get0_serialNumber(const OSSL_CRMF_CERTID *cid)
+{
+ return cid != NULL ? cid->serialNumber : NULL;
+}
+
+/*-
+ * fill in certificate template.
+ * Any value argument that is NULL will leave the respective field unchanged.
+ */
+int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl,
+ EVP_PKEY *pubkey,
+ const X509_NAME *subject,
+ const X509_NAME *issuer,
+ const ASN1_INTEGER *serial)
+{
+ if (tmpl == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (subject != NULL && !X509_NAME_set((X509_NAME **)&tmpl->subject, subject))
+ return 0;
+ if (issuer != NULL && !X509_NAME_set((X509_NAME **)&tmpl->issuer, issuer))
+ return 0;
+ if (serial != NULL) {
+ ASN1_INTEGER_free(tmpl->serialNumber);
+ if ((tmpl->serialNumber = ASN1_INTEGER_dup(serial)) == NULL)
+ return 0;
+ }
+ if (pubkey != NULL && !X509_PUBKEY_set(&tmpl->publicKey, pubkey))
+ return 0;
+ return 1;
+}
+
+
+/*-
+ * Decrypts the certificate in the given encryptedValue using private key pkey.
+ * This is needed for the indirect PoP method as in RFC 4210 section 5.2.8.2.
+ *
+ * returns a pointer to the decrypted certificate
+ * returns NULL on error or if no certificate available
+ */
+X509
+*OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(const OSSL_CRMF_ENCRYPTEDVALUE *ecert,
+ OSSL_LIB_CTX *libctx, const char *propq,
+ EVP_PKEY *pkey)
+{
+ X509 *cert = NULL; /* decrypted certificate */
+ EVP_CIPHER_CTX *evp_ctx = NULL; /* context for symmetric encryption */
+ unsigned char *ek = NULL; /* decrypted symmetric encryption key */
+ size_t eksize = 0; /* size of decrypted symmetric encryption key */
+ EVP_CIPHER *cipher = NULL; /* used cipher */
+ int cikeysize = 0; /* key size from cipher */
+ unsigned char *iv = NULL; /* initial vector for symmetric encryption */
+ unsigned char *outbuf = NULL; /* decryption output buffer */
+ const unsigned char *p = NULL; /* needed for decoding ASN1 */
+ int n, outlen = 0;
+ EVP_PKEY_CTX *pkctx = NULL; /* private key context */
+ char name[OSSL_MAX_NAME_SIZE];
+
+ if (ecert == NULL || ecert->symmAlg == NULL || ecert->encSymmKey == NULL
+ || ecert->encValue == NULL || pkey == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ return NULL;
+ }
+
+ /* select symmetric cipher based on algorithm given in message */
+ OBJ_obj2txt(name, sizeof(name), ecert->symmAlg->algorithm, 0);
+
+ (void)ERR_set_mark();
+ cipher = EVP_CIPHER_fetch(NULL, name, NULL);
+
+ if (cipher == NULL)
+ cipher = (EVP_CIPHER *)EVP_get_cipherbyname(name);
+
+ if (cipher == NULL) {
+ (void)ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_CIPHER);
+ goto end;
+ }
+ (void)ERR_pop_to_mark();
+
+ cikeysize = EVP_CIPHER_get_key_length(cipher);
+ /* first the symmetric key needs to be decrypted */
+ pkctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
+ if (pkctx != NULL && EVP_PKEY_decrypt_init(pkctx) > 0) {
+ ASN1_BIT_STRING *encKey = ecert->encSymmKey;
+ size_t failure;
+ int retval;
+
+ if (EVP_PKEY_decrypt(pkctx, NULL, &eksize,
+ encKey->data, encKey->length) <= 0
+ || (ek = OPENSSL_malloc(eksize)) == NULL)
+ goto end;
+ retval = EVP_PKEY_decrypt(pkctx, ek, &eksize,
+ encKey->data, encKey->length);
+ ERR_clear_error(); /* error state may have sensitive information */
+ failure = ~constant_time_is_zero_s(constant_time_msb(retval)
+ | constant_time_is_zero(retval));
+ failure |= ~constant_time_eq_s(eksize, (size_t)cikeysize);
+ if (failure) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY);
+ goto end;
+ }
+ } else {
+ goto end;
+ }
+ if ((iv = OPENSSL_malloc(EVP_CIPHER_get_iv_length(cipher))) == NULL)
+ goto end;
+ if (ASN1_TYPE_get_octetstring(ecert->symmAlg->parameter, iv,
+ EVP_CIPHER_get_iv_length(cipher))
+ != EVP_CIPHER_get_iv_length(cipher)) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_MALFORMED_IV);
+ goto end;
+ }
+
+ /*
+ * d2i_X509 changes the given pointer, so use p for decoding the message and
+ * keep the original pointer in outbuf so the memory can be freed later
+ */
+ if ((p = outbuf = OPENSSL_malloc(ecert->encValue->length +
+ EVP_CIPHER_get_block_size(cipher))) == NULL
+ || (evp_ctx = EVP_CIPHER_CTX_new()) == NULL)
+ goto end;
+ EVP_CIPHER_CTX_set_padding(evp_ctx, 0);
+
+ if (!EVP_DecryptInit(evp_ctx, cipher, ek, iv)
+ || !EVP_DecryptUpdate(evp_ctx, outbuf, &outlen,
+ ecert->encValue->data,
+ ecert->encValue->length)
+ || !EVP_DecryptFinal(evp_ctx, outbuf + outlen, &n)) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_CERTIFICATE);
+ goto end;
+ }
+ outlen += n;
+
+ /* convert decrypted certificate from DER to internal ASN.1 structure */
+ if ((cert = X509_new_ex(libctx, propq)) == NULL)
+ goto end;
+ if (d2i_X509(&cert, &p, outlen) == NULL)
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECODING_CERTIFICATE);
+ end:
+ EVP_PKEY_CTX_free(pkctx);
+ OPENSSL_free(outbuf);
+ EVP_CIPHER_CTX_free(evp_ctx);
+ EVP_CIPHER_free(cipher);
+ OPENSSL_clear_free(ek, eksize);
+ OPENSSL_free(iv);
+ return cert;
+}
diff --git a/crypto/crmf/crmf_local.h b/crypto/crmf/crmf_local.h
new file mode 100644
index 000000000000..3b8c3701b54d
--- /dev/null
+++ b/crypto/crmf/crmf_local.h
@@ -0,0 +1,385 @@
+/*-
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * CRMF implementation by Martin Peylo, Miikka Viljanen, and David von Oheimb.
+ */
+
+#ifndef OSSL_CRYPTO_CRMF_LOCAL_H
+# define OSSL_CRYPTO_CRMF_LOCAL_H
+
+# include <openssl/crmf.h>
+# include <openssl/err.h>
+
+/* explicit #includes not strictly needed since implied by the above: */
+# include <openssl/types.h>
+# include <openssl/safestack.h>
+# include <openssl/x509.h>
+# include <openssl/x509v3.h>
+
+/*-
+ * EncryptedValue ::= SEQUENCE {
+ * intendedAlg [0] AlgorithmIdentifier OPTIONAL,
+ * -- the intended algorithm for which the value will be used
+ * symmAlg [1] AlgorithmIdentifier OPTIONAL,
+ * -- the symmetric algorithm used to encrypt the value
+ * encSymmKey [2] BIT STRING OPTIONAL,
+ * -- the (encrypted) symmetric key used to encrypt the value
+ * keyAlg [3] AlgorithmIdentifier OPTIONAL,
+ * -- algorithm used to encrypt the symmetric key
+ * valueHint [4] OCTET STRING OPTIONAL,
+ * -- a brief description or identifier of the encValue content
+ * -- (may be meaningful only to the sending entity, and
+ * -- used only if EncryptedValue might be re-examined
+ * -- by the sending entity in the future)
+ * encValue BIT STRING
+ * -- the encrypted value itself
+ * }
+ */
+struct ossl_crmf_encryptedvalue_st {
+ X509_ALGOR *intendedAlg; /* 0 */
+ X509_ALGOR *symmAlg; /* 1 */
+ ASN1_BIT_STRING *encSymmKey; /* 2 */
+ X509_ALGOR *keyAlg; /* 3 */
+ ASN1_OCTET_STRING *valueHint; /* 4 */
+ ASN1_BIT_STRING *encValue;
+} /* OSSL_CRMF_ENCRYPTEDVALUE */;
+
+/*-
+ * Attributes ::= SET OF Attribute
+ * => X509_ATTRIBUTE
+ *
+ * PrivateKeyInfo ::= SEQUENCE {
+ * version INTEGER,
+ * privateKeyAlgorithm AlgorithmIdentifier,
+ * privateKey OCTET STRING,
+ * attributes [0] IMPLICIT Attributes OPTIONAL
+ * }
+ */
+typedef struct ossl_crmf_privatekeyinfo_st {
+ ASN1_INTEGER *version;
+ X509_ALGOR *privateKeyAlgorithm;
+ ASN1_OCTET_STRING *privateKey;
+ STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
+} OSSL_CRMF_PRIVATEKEYINFO;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_PRIVATEKEYINFO)
+
+/*-
+ * section 4.2.1 Private Key Info Content Type
+ * id-ct-encKeyWithID OBJECT IDENTIFIER ::= {id-ct 21}
+ *
+ * EncKeyWithID ::= SEQUENCE {
+ * privateKey PrivateKeyInfo,
+ * identifier CHOICE {
+ * string UTF8String,
+ * generalName GeneralName
+ * } OPTIONAL
+ * }
+ */
+typedef struct ossl_crmf_enckeywithid_identifier_st {
+ int type;
+ union {
+ ASN1_UTF8STRING *string;
+ GENERAL_NAME *generalName;
+ } value;
+} OSSL_CRMF_ENCKEYWITHID_IDENTIFIER;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER)
+
+typedef struct ossl_crmf_enckeywithid_st {
+ OSSL_CRMF_PRIVATEKEYINFO *privateKey;
+ /* [0] */
+ OSSL_CRMF_ENCKEYWITHID_IDENTIFIER *identifier;
+} OSSL_CRMF_ENCKEYWITHID;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_ENCKEYWITHID)
+
+/*-
+ * CertId ::= SEQUENCE {
+ * issuer GeneralName,
+ * serialNumber INTEGER
+ * }
+ */
+struct ossl_crmf_certid_st {
+ GENERAL_NAME *issuer;
+ ASN1_INTEGER *serialNumber;
+} /* OSSL_CRMF_CERTID */;
+
+/*-
+ * SinglePubInfo ::= SEQUENCE {
+ * pubMethod INTEGER {
+ * dontCare (0),
+ * x500 (1),
+ * web (2),
+ * ldap (3) },
+ * pubLocation GeneralName OPTIONAL
+ * }
+ */
+struct ossl_crmf_singlepubinfo_st {
+ ASN1_INTEGER *pubMethod;
+ GENERAL_NAME *pubLocation;
+} /* OSSL_CRMF_SINGLEPUBINFO */;
+DEFINE_STACK_OF(OSSL_CRMF_SINGLEPUBINFO)
+typedef STACK_OF(OSSL_CRMF_SINGLEPUBINFO) OSSL_CRMF_PUBINFOS;
+
+
+/*-
+ * PKIPublicationInfo ::= SEQUENCE {
+ * action INTEGER {
+ * dontPublish (0),
+ * pleasePublish (1) },
+ * pubInfos SEQUENCE SIZE (1..MAX) OF SinglePubInfo OPTIONAL
+ * -- pubInfos MUST NOT be present if action is "dontPublish"
+ * -- (if action is "pleasePublish" and pubInfos is omitted,
+ * -- "dontCare" is assumed)
+ * }
+ */
+struct ossl_crmf_pkipublicationinfo_st {
+ ASN1_INTEGER *action;
+ OSSL_CRMF_PUBINFOS *pubInfos;
+} /* OSSL_CRMF_PKIPUBLICATIONINFO */;
+DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_PKIPUBLICATIONINFO)
+
+/*-
+ * PKMACValue ::= SEQUENCE {
+ * algId AlgorithmIdentifier,
+ * -- algorithm value shall be PasswordBasedMac {1 2 840 113533 7 66 13}
+ * -- parameter value is PBMParameter
+ * value BIT STRING
+ * }
+ */
+typedef struct ossl_crmf_pkmacvalue_st {
+ X509_ALGOR *algId;
+ ASN1_BIT_STRING *value;
+} OSSL_CRMF_PKMACVALUE;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_PKMACVALUE)
+
+/*-
+ * SubsequentMessage ::= INTEGER {
+ * encrCert (0),
+ * -- requests that resulting certificate be encrypted for the
+ * -- end entity (following which, POP will be proven in a
+ * -- confirmation message)
+ * challengeResp (1)
+ * -- requests that CA engage in challenge-response exchange with
+ * -- end entity in order to prove private key possession
+ * }
+ *
+ * POPOPrivKey ::= CHOICE {
+ * thisMessage [0] BIT STRING, -- Deprecated
+ * -- possession is proven in this message (which contains the private
+ * -- key itself (encrypted for the CA))
+ * subsequentMessage [1] SubsequentMessage,
+ * -- possession will be proven in a subsequent message
+ * dhMAC [2] BIT STRING, -- Deprecated
+ * agreeMAC [3] PKMACValue,
+ * encryptedKey [4] EnvelopedData
+ * }
+ */
+
+typedef struct ossl_crmf_popoprivkey_st {
+ int type;
+ union {
+ ASN1_BIT_STRING *thisMessage; /* 0 */ /* Deprecated */
+ ASN1_INTEGER *subsequentMessage; /* 1 */
+ ASN1_BIT_STRING *dhMAC; /* 2 */ /* Deprecated */
+ OSSL_CRMF_PKMACVALUE *agreeMAC; /* 3 */
+ ASN1_NULL *encryptedKey; /* 4 */
+ } value;
+} OSSL_CRMF_POPOPRIVKEY;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_POPOPRIVKEY)
+
+/*-
+ * PBMParameter ::= SEQUENCE {
+ * salt OCTET STRING,
+ * owf AlgorithmIdentifier,
+ * -- AlgId for a One-Way Function (SHA-1 recommended)
+ * iterationCount INTEGER,
+ * -- number of times the OWF is applied
+ * mac AlgorithmIdentifier
+ * -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
+ * -- or HMAC [HMAC, RFC2202])
+ * }
+ */
+struct ossl_crmf_pbmparameter_st {
+ ASN1_OCTET_STRING *salt;
+ X509_ALGOR *owf;
+ ASN1_INTEGER *iterationCount;
+ X509_ALGOR *mac;
+} /* OSSL_CRMF_PBMPARAMETER */;
+# define OSSL_CRMF_PBM_MAX_ITERATION_COUNT 100000 /* if too large allows DoS */
+
+/*-
+ * POPOSigningKeyInput ::= SEQUENCE {
+ * authInfo CHOICE {
+ * sender [0] GeneralName,
+ * -- used only if an authenticated identity has been
+ * -- established for the sender (e.g., a DN from a
+ * -- previously-issued and currently-valid certificate)
+ * publicKeyMAC PKMACValue },
+ * -- used if no authenticated GeneralName currently exists for
+ * -- the sender; publicKeyMAC contains a password-based MAC
+ * -- on the DER-encoded value of publicKey
+ * publicKey SubjectPublicKeyInfo -- from CertTemplate
+ * }
+ */
+typedef struct ossl_crmf_poposigningkeyinput_authinfo_st {
+ int type;
+ union {
+ /* 0 */ GENERAL_NAME *sender;
+ /* 1 */ OSSL_CRMF_PKMACVALUE *publicKeyMAC;
+ } value;
+} OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO)
+
+typedef struct ossl_crmf_poposigningkeyinput_st {
+ OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO *authInfo;
+ X509_PUBKEY *publicKey;
+} OSSL_CRMF_POPOSIGNINGKEYINPUT;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_POPOSIGNINGKEYINPUT)
+
+/*-
+ * POPOSigningKey ::= SEQUENCE {
+ * poposkInput [0] POPOSigningKeyInput OPTIONAL,
+ * algorithmIdentifier AlgorithmIdentifier,
+ * signature BIT STRING
+ * }
+ */
+struct ossl_crmf_poposigningkey_st {
+ OSSL_CRMF_POPOSIGNINGKEYINPUT *poposkInput;
+ X509_ALGOR *algorithmIdentifier;
+ ASN1_BIT_STRING *signature;
+} /* OSSL_CRMF_POPOSIGNINGKEY */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_POPOSIGNINGKEY)
+
+/*-
+ * ProofOfPossession ::= CHOICE {
+ * raVerified [0] NULL,
+ * -- used if the RA has already verified that the requester is in
+ * -- possession of the private key
+ * signature [1] POPOSigningKey,
+ * keyEncipherment [2] POPOPrivKey,
+ * keyAgreement [3] POPOPrivKey
+ * }
+ */
+typedef struct ossl_crmf_popo_st {
+ int type;
+ union {
+ ASN1_NULL *raVerified; /* 0 */
+ OSSL_CRMF_POPOSIGNINGKEY *signature; /* 1 */
+ OSSL_CRMF_POPOPRIVKEY *keyEncipherment; /* 2 */
+ OSSL_CRMF_POPOPRIVKEY *keyAgreement; /* 3 */
+ } value;
+} OSSL_CRMF_POPO;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_POPO)
+
+/*-
+ * OptionalValidity ::= SEQUENCE {
+ * notBefore [0] Time OPTIONAL,
+ * notAfter [1] Time OPTIONAL -- at least one MUST be present
+ * }
+ */
+struct ossl_crmf_optionalvalidity_st {
+ /* 0 */ ASN1_TIME *notBefore;
+ /* 1 */ ASN1_TIME *notAfter;
+} /* OSSL_CRMF_OPTIONALVALIDITY */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_OPTIONALVALIDITY)
+
+/*-
+ * CertTemplate ::= SEQUENCE {
+ * version [0] Version OPTIONAL,
+ * serialNumber [1] INTEGER OPTIONAL,
+ * signingAlg [2] AlgorithmIdentifier OPTIONAL,
+ * issuer [3] Name OPTIONAL,
+ * validity [4] OptionalValidity OPTIONAL,
+ * subject [5] Name OPTIONAL,
+ * publicKey [6] SubjectPublicKeyInfo OPTIONAL,
+ * issuerUID [7] UniqueIdentifier OPTIONAL,
+ * subjectUID [8] UniqueIdentifier OPTIONAL,
+ * extensions [9] Extensions OPTIONAL
+ * }
+ */
+struct ossl_crmf_certtemplate_st {
+ ASN1_INTEGER *version;
+ ASN1_INTEGER *serialNumber; /* serialNumber MUST be omitted */
+ /* This field is assigned by the CA during certificate creation */
+ X509_ALGOR *signingAlg; /* signingAlg MUST be omitted */
+ /* This field is assigned by the CA during certificate creation */
+ const X509_NAME *issuer;
+ OSSL_CRMF_OPTIONALVALIDITY *validity;
+ const X509_NAME *subject;
+ X509_PUBKEY *publicKey;
+ ASN1_BIT_STRING *issuerUID; /* deprecated in version 2 */
+ /* According to rfc 3280: UniqueIdentifier ::= BIT STRING */
+ ASN1_BIT_STRING *subjectUID; /* deprecated in version 2 */
+ /* Could be X509_EXTENSION*S*, but that's only cosmetic */
+ STACK_OF(X509_EXTENSION) *extensions;
+} /* OSSL_CRMF_CERTTEMPLATE */;
+
+/*-
+ * CertRequest ::= SEQUENCE {
+ * certReqId INTEGER, -- ID for matching request and reply
+ * certTemplate CertTemplate, -- Selected fields of cert to be issued
+ * controls Controls OPTIONAL -- Attributes affecting issuance
+ * }
+ */
+struct ossl_crmf_certrequest_st {
+ ASN1_INTEGER *certReqId;
+ OSSL_CRMF_CERTTEMPLATE *certTemplate;
+ STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) *controls;
+} /* OSSL_CRMF_CERTREQUEST */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_CERTREQUEST)
+DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTREQUEST)
+
+struct ossl_crmf_attributetypeandvalue_st {
+ ASN1_OBJECT *type;
+ union {
+ /* NID_id_regCtrl_regToken */
+ ASN1_UTF8STRING *regToken;
+
+ /* NID_id_regCtrl_authenticator */
+ ASN1_UTF8STRING *authenticator;
+
+ /* NID_id_regCtrl_pkiPublicationInfo */
+ OSSL_CRMF_PKIPUBLICATIONINFO *pkiPublicationInfo;
+
+ /* NID_id_regCtrl_oldCertID */
+ OSSL_CRMF_CERTID *oldCertID;
+
+ /* NID_id_regCtrl_protocolEncrKey */
+ X509_PUBKEY *protocolEncrKey;
+
+ /* NID_id_regInfo_utf8Pairs */
+ ASN1_UTF8STRING *utf8Pairs;
+
+ /* NID_id_regInfo_certReq */
+ OSSL_CRMF_CERTREQUEST *certReq;
+
+ ASN1_TYPE *other;
+ } value;
+} /* OSSL_CRMF_ATTRIBUTETYPEANDVALUE */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+DEFINE_STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+
+/*-
+ * CertReqMessages ::= SEQUENCE SIZE (1..MAX) OF CertReqMsg
+ * CertReqMsg ::= SEQUENCE {
+ * certReq CertRequest,
+ * popo ProofOfPossession OPTIONAL,
+ * -- content depends upon key type
+ * regInfo SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue OPTIONAL
+ * }
+ */
+struct ossl_crmf_msg_st {
+ OSSL_CRMF_CERTREQUEST *certReq;
+ /* 0 */
+ OSSL_CRMF_POPO *popo;
+ /* 1 */
+ STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) *regInfo;
+} /* OSSL_CRMF_MSG */;
+#endif
diff --git a/crypto/crmf/crmf_pbm.c b/crypto/crmf/crmf_pbm.c
new file mode 100644
index 000000000000..88a8480cf73a
--- /dev/null
+++ b/crypto/crmf/crmf_pbm.c
@@ -0,0 +1,233 @@
+/*-
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * CRMF implementation by Martin Peylo, Miikka Viljanen, and David von Oheimb.
+ */
+
+
+#include <string.h>
+
+#include <openssl/rand.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <openssl/asn1t.h>
+#include <openssl/crmf.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
+
+#include "internal/sizes.h"
+
+#include "crmf_local.h"
+
+/*-
+ * creates and initializes OSSL_CRMF_PBMPARAMETER (section 4.4)
+ * |slen| SHOULD be at least 8 (16 is common)
+ * |owfnid| e.g., NID_sha256
+ * |itercnt| MUST be >= 100 (e.g., 500) and <= OSSL_CRMF_PBM_MAX_ITERATION_COUNT
+ * |macnid| e.g., NID_hmac_sha1
+ * returns pointer to OSSL_CRMF_PBMPARAMETER on success, NULL on error
+ */
+OSSL_CRMF_PBMPARAMETER *OSSL_CRMF_pbmp_new(OSSL_LIB_CTX *libctx, size_t slen,
+ int owfnid, size_t itercnt,
+ int macnid)
+{
+ OSSL_CRMF_PBMPARAMETER *pbm = NULL;
+ unsigned char *salt = NULL;
+
+ if ((pbm = OSSL_CRMF_PBMPARAMETER_new()) == NULL)
+ goto err;
+
+ /*
+ * salt contains a randomly generated value used in computing the key
+ * of the MAC process. The salt SHOULD be at least 8 octets (64
+ * bits) long.
+ */
+ if ((salt = OPENSSL_malloc(slen)) == NULL)
+ goto err;
+ if (RAND_bytes_ex(libctx, salt, slen, 0) <= 0) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_FAILURE_OBTAINING_RANDOM);
+ goto err;
+ }
+ if (!ASN1_OCTET_STRING_set(pbm->salt, salt, (int)slen))
+ goto err;
+
+ /*
+ * owf identifies the hash algorithm and associated parameters used to
+ * compute the key used in the MAC process. All implementations MUST
+ * support SHA-1.
+ */
+ if (!X509_ALGOR_set0(pbm->owf, OBJ_nid2obj(owfnid), V_ASN1_UNDEF, NULL)) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_SETTING_OWF_ALGOR_FAILURE);
+ goto err;
+ }
+
+ /*
+ * iterationCount identifies the number of times the hash is applied
+ * during the key computation process. The iterationCount MUST be a
+ * minimum of 100. Many people suggest using values as high as 1000
+ * iterations as the minimum value. The trade off here is between
+ * protection of the password from attacks and the time spent by the
+ * server processing all of the different iterations in deriving
+ * passwords. Hashing is generally considered a cheap operation but
+ * this may not be true with all hash functions in the future.
+ */
+ if (itercnt < 100) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_ITERATIONCOUNT_BELOW_100);
+ goto err;
+ }
+ if (itercnt > OSSL_CRMF_PBM_MAX_ITERATION_COUNT) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_BAD_PBM_ITERATIONCOUNT);
+ goto err;
+ }
+
+ if (!ASN1_INTEGER_set(pbm->iterationCount, itercnt)) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_CRMFERROR);
+ goto err;
+ }
+
+ /*
+ * mac identifies the algorithm and associated parameters of the MAC
+ * function to be used. All implementations MUST support HMAC-SHA1 [HMAC].
+ * All implementations SHOULD support DES-MAC and Triple-DES-MAC [PKCS11].
+ */
+ if (!X509_ALGOR_set0(pbm->mac, OBJ_nid2obj(macnid), V_ASN1_UNDEF, NULL)) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_SETTING_MAC_ALGOR_FAILURE);
+ goto err;
+ }
+
+ OPENSSL_free(salt);
+ return pbm;
+ err:
+ OPENSSL_free(salt);
+ OSSL_CRMF_PBMPARAMETER_free(pbm);
+ return NULL;
+}
+
+/*-
+ * calculates the PBM based on the settings of the given OSSL_CRMF_PBMPARAMETER
+ * |pbmp| identifies the algorithms, salt to use
+ * |msg| message to apply the PBM for
+ * |msglen| length of the message
+ * |sec| key to use
+ * |seclen| length of the key
+ * |out| pointer to the computed mac, will be set on success
+ * |outlen| if not NULL, will set variable to the length of the mac on success
+ * returns 1 on success, 0 on error
+ */
+int OSSL_CRMF_pbm_new(OSSL_LIB_CTX *libctx, const char *propq,
+ const OSSL_CRMF_PBMPARAMETER *pbmp,
+ const unsigned char *msg, size_t msglen,
+ const unsigned char *sec, size_t seclen,
+ unsigned char **out, size_t *outlen)
+{
+ int mac_nid, hmac_md_nid = NID_undef;
+ char mdname[OSSL_MAX_NAME_SIZE];
+ char hmac_mdname[OSSL_MAX_NAME_SIZE];
+ EVP_MD *owf = NULL;
+ EVP_MD_CTX *ctx = NULL;
+ unsigned char basekey[EVP_MAX_MD_SIZE];
+ unsigned int bklen = EVP_MAX_MD_SIZE;
+ int64_t iterations;
+ unsigned char *mac_res = 0;
+ int ok = 0;
+
+ if (out == NULL || pbmp == NULL || pbmp->mac == NULL
+ || pbmp->mac->algorithm == NULL || msg == NULL || sec == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+ goto err;
+ }
+ if ((mac_res = OPENSSL_malloc(EVP_MAX_MD_SIZE)) == NULL)
+ goto err;
+
+ /*
+ * owf identifies the hash algorithm and associated parameters used to
+ * compute the key used in the MAC process. All implementations MUST
+ * support SHA-1.
+ */
+ OBJ_obj2txt(mdname, sizeof(mdname), pbmp->owf->algorithm, 0);
+ if ((owf = EVP_MD_fetch(libctx, mdname, propq)) == NULL) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_ALGORITHM);
+ goto err;
+ }
+
+ if ((ctx = EVP_MD_CTX_new()) == NULL)
+ goto err;
+
+ /* compute the basekey of the salted secret */
+ if (!EVP_DigestInit_ex(ctx, owf, NULL))
+ goto err;
+ /* first the secret */
+ if (!EVP_DigestUpdate(ctx, sec, seclen))
+ goto err;
+ /* then the salt */
+ if (!EVP_DigestUpdate(ctx, pbmp->salt->data, pbmp->salt->length))
+ goto err;
+ if (!EVP_DigestFinal_ex(ctx, basekey, &bklen))
+ goto err;
+ if (!ASN1_INTEGER_get_int64(&iterations, pbmp->iterationCount)
+ || iterations < 100 /* min from RFC */
+ || iterations > OSSL_CRMF_PBM_MAX_ITERATION_COUNT) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_BAD_PBM_ITERATIONCOUNT);
+ goto err;
+ }
+
+ /* the first iteration was already done above */
+ while (--iterations > 0) {
+ if (!EVP_DigestInit_ex(ctx, owf, NULL))
+ goto err;
+ if (!EVP_DigestUpdate(ctx, basekey, bklen))
+ goto err;
+ if (!EVP_DigestFinal_ex(ctx, basekey, &bklen))
+ goto err;
+ }
+
+ /*
+ * mac identifies the algorithm and associated parameters of the MAC
+ * function to be used. All implementations MUST support HMAC-SHA1 [HMAC].
+ * All implementations SHOULD support DES-MAC and Triple-DES-MAC [PKCS11].
+ */
+ mac_nid = OBJ_obj2nid(pbmp->mac->algorithm);
+
+ if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, mac_nid, NULL, &hmac_md_nid, NULL)
+ || OBJ_obj2txt(hmac_mdname, sizeof(hmac_mdname),
+ OBJ_nid2obj(hmac_md_nid), 0) <= 0) {
+ ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_ALGORITHM);
+ goto err;
+ }
+ if (EVP_Q_mac(libctx, "HMAC", propq, hmac_mdname, NULL, basekey, bklen,
+ msg, msglen, mac_res, EVP_MAX_MD_SIZE, outlen) == NULL)
+ goto err;
+
+ ok = 1;
+
+ err:
+ OPENSSL_cleanse(basekey, bklen);
+ EVP_MD_free(owf);
+ EVP_MD_CTX_free(ctx);
+
+ if (ok == 1) {
+ *out = mac_res;
+ return 1;
+ }
+
+ OPENSSL_free(mac_res);
+
+ if (pbmp != NULL && pbmp->mac != NULL) {
+ char buf[128];
+
+ if (OBJ_obj2txt(buf, sizeof(buf), pbmp->mac->algorithm, 0))
+ ERR_add_error_data(1, buf);
+ }
+ return 0;
+}
diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c
index 1f36b20c86ed..6e73b8352cac 100644
--- a/crypto/cryptlib.c
+++ b/crypto/cryptlib.c
@@ -1,8 +1,8 @@
/*
- * Copyright 1998-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,161 +12,6 @@
#include "crypto/cryptlib.h"
#include <openssl/safestack.h>
-#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
- defined(__x86_64) || defined(__x86_64__) || \
- defined(_M_AMD64) || defined(_M_X64)
-
-extern unsigned int OPENSSL_ia32cap_P[4];
-
-# if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY)
-
-/*
- * Purpose of these minimalistic and character-type-agnostic subroutines
- * is to break dependency on MSVCRT (on Windows) and locale. This makes
- * OPENSSL_cpuid_setup safe to use as "constructor". "Character-type-
- * agnostic" means that they work with either wide or 8-bit characters,
- * exploiting the fact that first 127 characters can be simply casted
- * between the sets, while the rest would be simply rejected by ossl_is*
- * subroutines.
- */
-# ifdef _WIN32
-typedef WCHAR variant_char;
-
-static variant_char *ossl_getenv(const char *name)
-{
- /*
- * Since we pull only one environment variable, it's simpler to
- * to just ignore |name| and use equivalent wide-char L-literal.
- * As well as to ignore excessively long values...
- */
- static WCHAR value[48];
- DWORD len = GetEnvironmentVariableW(L"OPENSSL_ia32cap", value, 48);
-
- return (len > 0 && len < 48) ? value : NULL;
-}
-# else
-typedef char variant_char;
-# define ossl_getenv getenv
-# endif
-
-# include "crypto/ctype.h"
-
-static int todigit(variant_char c)
-{
- if (ossl_isdigit(c))
- return c - '0';
- else if (ossl_isxdigit(c))
- return ossl_tolower(c) - 'a' + 10;
-
- /* return largest base value to make caller terminate the loop */
- return 16;
-}
-
-static uint64_t ossl_strtouint64(const variant_char *str)
-{
- uint64_t ret = 0;
- unsigned int digit, base = 10;
-
- if (*str == '0') {
- base = 8, str++;
- if (ossl_tolower(*str) == 'x')
- base = 16, str++;
- }
-
- while((digit = todigit(*str++)) < base)
- ret = ret * base + digit;
-
- return ret;
-}
-
-static variant_char *ossl_strchr(const variant_char *str, char srch)
-{ variant_char c;
-
- while((c = *str)) {
- if (c == srch)
- return (variant_char *)str;
- str++;
- }
-
- return NULL;
-}
-
-# define OPENSSL_CPUID_SETUP
-typedef uint64_t IA32CAP;
-
-void OPENSSL_cpuid_setup(void)
-{
- static int trigger = 0;
- IA32CAP OPENSSL_ia32_cpuid(unsigned int *);
- IA32CAP vec;
- const variant_char *env;
-
- if (trigger)
- return;
-
- trigger = 1;
- if ((env = ossl_getenv("OPENSSL_ia32cap")) != NULL) {
- int off = (env[0] == '~') ? 1 : 0;
-
- vec = ossl_strtouint64(env + off);
-
- if (off) {
- IA32CAP mask = vec;
- vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P) & ~mask;
- if (mask & (1<<24)) {
- /*
- * User disables FXSR bit, mask even other capabilities
- * that operate exclusively on XMM, so we don't have to
- * double-check all the time. We mask PCLMULQDQ, AMD XOP,
- * AES-NI and AVX. Formally speaking we don't have to
- * do it in x86_64 case, but we can safely assume that
- * x86_64 users won't actually flip this flag.
- */
- vec &= ~((IA32CAP)(1<<1|1<<11|1<<25|1<<28) << 32);
- }
- } else if (env[0] == ':') {
- vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P);
- }
-
- if ((env = ossl_strchr(env, ':')) != NULL) {
- IA32CAP vecx;
-
- env++;
- off = (env[0] == '~') ? 1 : 0;
- vecx = ossl_strtouint64(env + off);
- if (off) {
- OPENSSL_ia32cap_P[2] &= ~(unsigned int)vecx;
- OPENSSL_ia32cap_P[3] &= ~(unsigned int)(vecx >> 32);
- } else {
- OPENSSL_ia32cap_P[2] = (unsigned int)vecx;
- OPENSSL_ia32cap_P[3] = (unsigned int)(vecx >> 32);
- }
- } else {
- OPENSSL_ia32cap_P[2] = 0;
- OPENSSL_ia32cap_P[3] = 0;
- }
- } else {
- vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P);
- }
-
- /*
- * |(1<<10) sets a reserved bit to signal that variable
- * was initialized already... This is to avoid interference
- * with cpuid snippets in ELF .init segment.
- */
- OPENSSL_ia32cap_P[0] = (unsigned int)vec | (1 << 10);
- OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32);
-}
-# else
-unsigned int OPENSSL_ia32cap_P[4];
-# endif
-#endif
-#if !defined(OPENSSL_CPUID_SETUP) && !defined(OPENSSL_CPUID_OBJ)
-void OPENSSL_cpuid_setup(void)
-{
-}
-#endif
-
#if defined(_WIN32)
# include <tchar.h>
# include <signal.h>
@@ -349,12 +194,6 @@ void OPENSSL_showfatal(const char *fmta, ...)
# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
# ifdef OPENSSL_SYS_WIN_CORE
/* ONECORE is always NONGUI and NT >= 0x0601 */
-
- /*
- * TODO: (For non GUI and no std error cases)
- * Add event logging feature here.
- */
-
# if !defined(NDEBUG)
/*
* We are in a situation where we tried to report a critical
@@ -430,44 +269,14 @@ void OPENSSL_die(const char *message, const char *file, int line)
#endif
}
-#if !defined(OPENSSL_CPUID_OBJ)
+#if defined(__TANDEM) && defined(OPENSSL_VPROC)
/*
- * The volatile is used to to ensure that the compiler generates code that reads
- * all values from the array and doesn't try to optimize this away. The standard
- * doesn't actually require this behavior if the original data pointed to is
- * not volatile, but compilers do this in practice anyway.
- *
- * There are also assembler versions of this function.
- */
-# undef CRYPTO_memcmp
-int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len)
-{
- size_t i;
- const volatile unsigned char *a = in_a;
- const volatile unsigned char *b = in_b;
- unsigned char x = 0;
-
- for (i = 0; i < len; i++)
- x |= a[i] ^ b[i];
-
- return x;
-}
-
-/*
- * For systems that don't provide an instruction counter register or equivalent.
+ * Define a VPROC function for HP NonStop build crypto library.
+ * This is used by platform version identification tools.
+ * Do not inline this procedure or make it static.
*/
-uint32_t OPENSSL_rdtsc(void)
-{
- return 0;
-}
-
-size_t OPENSSL_instrument_bus(unsigned int *out, size_t cnt)
-{
- return 0;
-}
-
-size_t OPENSSL_instrument_bus2(unsigned int *out, size_t cnt, size_t max)
-{
- return 0;
-}
-#endif
+# define OPENSSL_VPROC_STRING_(x) x##_CRYPTO
+# define OPENSSL_VPROC_STRING(x) OPENSSL_VPROC_STRING_(x)
+# define OPENSSL_VPROC_FUNC OPENSSL_VPROC_STRING(OPENSSL_VPROC)
+void OPENSSL_VPROC_FUNC(void) {}
+#endif /* __TANDEM */
diff --git a/crypto/ct/ct_b64.c b/crypto/ct/ct_b64.c
index 4abe11ca298b..d3f783962aec 100644
--- a/crypto/ct/ct_b64.c
+++ b/crypto/ct/ct_b64.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -35,13 +35,13 @@ static int ct_base64_decode(const char *in, unsigned char **out)
outlen = (inlen / 4) * 3;
outbuf = OPENSSL_malloc(outlen);
if (outbuf == NULL) {
- CTerr(CT_F_CT_BASE64_DECODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
goto err;
}
outlen = EVP_DecodeBlock(outbuf, (unsigned char *)in, inlen);
if (outlen < 0) {
- CTerr(CT_F_CT_BASE64_DECODE, CT_R_BASE64_DECODE_ERROR);
+ ERR_raise(ERR_LIB_CT, CT_R_BASE64_DECODE_ERROR);
goto err;
}
@@ -71,7 +71,7 @@ SCT *SCT_new_from_base64(unsigned char version, const char *logid_base64,
int declen;
if (sct == NULL) {
- CTerr(CT_F_SCT_NEW_FROM_BASE64, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -80,13 +80,13 @@ SCT *SCT_new_from_base64(unsigned char version, const char *logid_base64,
* can only construct SCT versions that have been defined.
*/
if (!SCT_set_version(sct, version)) {
- CTerr(CT_F_SCT_NEW_FROM_BASE64, CT_R_SCT_UNSUPPORTED_VERSION);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_UNSUPPORTED_VERSION);
goto err;
}
declen = ct_base64_decode(logid_base64, &dec);
if (declen < 0) {
- CTerr(CT_F_SCT_NEW_FROM_BASE64, X509_R_BASE64_DECODE_ERROR);
+ ERR_raise(ERR_LIB_CT, X509_R_BASE64_DECODE_ERROR);
goto err;
}
if (!SCT_set0_log_id(sct, dec, declen))
@@ -95,7 +95,7 @@ SCT *SCT_new_from_base64(unsigned char version, const char *logid_base64,
declen = ct_base64_decode(extensions_base64, &dec);
if (declen < 0) {
- CTerr(CT_F_SCT_NEW_FROM_BASE64, X509_R_BASE64_DECODE_ERROR);
+ ERR_raise(ERR_LIB_CT, X509_R_BASE64_DECODE_ERROR);
goto err;
}
SCT_set0_extensions(sct, dec, declen);
@@ -103,7 +103,7 @@ SCT *SCT_new_from_base64(unsigned char version, const char *logid_base64,
declen = ct_base64_decode(signature_base64, &dec);
if (declen < 0) {
- CTerr(CT_F_SCT_NEW_FROM_BASE64, X509_R_BASE64_DECODE_ERROR);
+ ERR_raise(ERR_LIB_CT, X509_R_BASE64_DECODE_ERROR);
goto err;
}
@@ -132,7 +132,9 @@ SCT *SCT_new_from_base64(unsigned char version, const char *logid_base64,
* 0 on decoding failure, or invalid parameter if any
* -1 on internal (malloc) failure
*/
-int CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, const char *name)
+int CTLOG_new_from_base64_ex(CTLOG **ct_log, const char *pkey_base64,
+ const char *name, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
unsigned char *pkey_der = NULL;
int pkey_der_len;
@@ -140,25 +142,25 @@ int CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, const char *n
EVP_PKEY *pkey = NULL;
if (ct_log == NULL) {
- CTerr(CT_F_CTLOG_NEW_FROM_BASE64, ERR_R_PASSED_INVALID_ARGUMENT);
+ ERR_raise(ERR_LIB_CT, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
pkey_der_len = ct_base64_decode(pkey_base64, &pkey_der);
if (pkey_der_len < 0) {
- CTerr(CT_F_CTLOG_NEW_FROM_BASE64, CT_R_LOG_CONF_INVALID_KEY);
+ ERR_raise(ERR_LIB_CT, CT_R_LOG_CONF_INVALID_KEY);
return 0;
}
p = pkey_der;
- pkey = d2i_PUBKEY(NULL, &p, pkey_der_len);
+ pkey = d2i_PUBKEY_ex(NULL, &p, pkey_der_len, libctx, propq);
OPENSSL_free(pkey_der);
if (pkey == NULL) {
- CTerr(CT_F_CTLOG_NEW_FROM_BASE64, CT_R_LOG_CONF_INVALID_KEY);
+ ERR_raise(ERR_LIB_CT, CT_R_LOG_CONF_INVALID_KEY);
return 0;
}
- *ct_log = CTLOG_new(pkey, name);
+ *ct_log = CTLOG_new_ex(pkey, name, libctx, propq);
if (*ct_log == NULL) {
EVP_PKEY_free(pkey);
return 0;
@@ -166,3 +168,9 @@ int CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, const char *n
return 1;
}
+
+int CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64,
+ const char *name)
+{
+ return CTLOG_new_from_base64_ex(ct_log, pkey_base64, name, NULL, NULL);
+}
diff --git a/crypto/ct/ct_err.c b/crypto/ct/ct_err.c
index c0c62fee6c6a..c4dd05119eba 100644
--- a/crypto/ct/ct_err.c
+++ b/crypto/ct/ct_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,47 +10,11 @@
#include <openssl/err.h>
#include <openssl/cterr.h>
+#include "crypto/cterr.h"
-#ifndef OPENSSL_NO_ERR
+#ifndef OPENSSL_NO_CT
-static const ERR_STRING_DATA CT_str_functs[] = {
- {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_NEW, 0), "CTLOG_new"},
- {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_NEW_FROM_BASE64, 0),
- "CTLOG_new_from_base64"},
- {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_NEW_FROM_CONF, 0), "ctlog_new_from_conf"},
- {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_LOAD_CTX_NEW, 0),
- "ctlog_store_load_ctx_new"},
- {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_LOAD_FILE, 0),
- "CTLOG_STORE_load_file"},
- {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_LOAD_LOG, 0),
- "ctlog_store_load_log"},
- {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_NEW, 0), "CTLOG_STORE_new"},
- {ERR_PACK(ERR_LIB_CT, CT_F_CT_BASE64_DECODE, 0), "ct_base64_decode"},
- {ERR_PACK(ERR_LIB_CT, CT_F_CT_POLICY_EVAL_CTX_NEW, 0),
- "CT_POLICY_EVAL_CTX_new"},
- {ERR_PACK(ERR_LIB_CT, CT_F_CT_V1_LOG_ID_FROM_PKEY, 0),
- "ct_v1_log_id_from_pkey"},
- {ERR_PACK(ERR_LIB_CT, CT_F_I2O_SCT, 0), "i2o_SCT"},
- {ERR_PACK(ERR_LIB_CT, CT_F_I2O_SCT_LIST, 0), "i2o_SCT_LIST"},
- {ERR_PACK(ERR_LIB_CT, CT_F_I2O_SCT_SIGNATURE, 0), "i2o_SCT_signature"},
- {ERR_PACK(ERR_LIB_CT, CT_F_O2I_SCT, 0), "o2i_SCT"},
- {ERR_PACK(ERR_LIB_CT, CT_F_O2I_SCT_LIST, 0), "o2i_SCT_LIST"},
- {ERR_PACK(ERR_LIB_CT, CT_F_O2I_SCT_SIGNATURE, 0), "o2i_SCT_signature"},
- {ERR_PACK(ERR_LIB_CT, CT_F_SCT_CTX_NEW, 0), "SCT_CTX_new"},
- {ERR_PACK(ERR_LIB_CT, CT_F_SCT_CTX_VERIFY, 0), "SCT_CTX_verify"},
- {ERR_PACK(ERR_LIB_CT, CT_F_SCT_NEW, 0), "SCT_new"},
- {ERR_PACK(ERR_LIB_CT, CT_F_SCT_NEW_FROM_BASE64, 0), "SCT_new_from_base64"},
- {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET0_LOG_ID, 0), "SCT_set0_log_id"},
- {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET1_EXTENSIONS, 0), "SCT_set1_extensions"},
- {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET1_LOG_ID, 0), "SCT_set1_log_id"},
- {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET1_SIGNATURE, 0), "SCT_set1_signature"},
- {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET_LOG_ENTRY_TYPE, 0),
- "SCT_set_log_entry_type"},
- {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET_SIGNATURE_NID, 0),
- "SCT_set_signature_nid"},
- {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET_VERSION, 0), "SCT_set_version"},
- {0, NULL}
-};
+# ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA CT_str_reasons[] = {
{ERR_PACK(ERR_LIB_CT, 0, CT_R_BASE64_DECODE_ERROR), "base64 decode error"},
@@ -82,15 +46,16 @@ static const ERR_STRING_DATA CT_str_reasons[] = {
{0, NULL}
};
-#endif
+# endif
-int ERR_load_CT_strings(void)
+int ossl_err_load_CT_strings(void)
{
-#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(CT_str_functs[0].error) == NULL) {
- ERR_load_strings_const(CT_str_functs);
+# ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(CT_str_reasons[0].error) == NULL)
ERR_load_strings_const(CT_str_reasons);
- }
-#endif
+# endif
return 1;
}
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/crypto/ct/ct_local.h b/crypto/ct/ct_local.h
index 9f983c91beae..e5614ddf5eb4 100644
--- a/crypto/ct/ct_local.h
+++ b/crypto/ct/ct_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -100,6 +100,9 @@ struct sct_ctx_st {
size_t prederlen;
/* milliseconds since epoch (to check that the SCT isn't from the future) */
uint64_t epoch_time_in_ms;
+
+ OSSL_LIB_CTX *libctx;
+ char *propq;
};
/* Context when evaluating whether a Certificate Transparency policy is met */
@@ -109,12 +112,15 @@ struct ct_policy_eval_ctx_st {
CTLOG_STORE *log_store;
/* milliseconds since epoch (to check that SCTs aren't from the future) */
uint64_t epoch_time_in_ms;
+
+ OSSL_LIB_CTX *libctx;
+ char *propq;
};
/*
* Creates a new context for verifying an SCT.
*/
-SCT_CTX *SCT_CTX_new(void);
+SCT_CTX *SCT_CTX_new(OSSL_LIB_CTX *ctx, const char *propq);
/*
* Deletes an SCT verification context.
*/
@@ -185,11 +191,6 @@ __owur int SCT_is_complete(const SCT *sct);
__owur int SCT_signature_is_complete(const SCT *sct);
/*
- * TODO(RJPercival): Create an SCT_signature struct and make i2o_SCT_signature
- * and o2i_SCT_signature conform to the i2d/d2i conventions.
- */
-
-/*
* Serialize (to TLS format) an |sct| signature and write it to |out|.
* If |out| is null, no signature will be output but the length will be returned.
* If |out| points to a null pointer, a string will be allocated to hold the
@@ -213,4 +214,4 @@ __owur int o2i_SCT_signature(SCT *sct, const unsigned char **in, size_t len);
/*
* Handlers for Certificate Transparency X509v3/OCSP extensions
*/
-extern const X509V3_EXT_METHOD v3_ct_scts[3];
+extern const X509V3_EXT_METHOD ossl_v3_ct_scts[3];
diff --git a/crypto/ct/ct_log.c b/crypto/ct/ct_log.c
index c1bca3e1415e..d19dda2cd2f2 100644
--- a/crypto/ct/ct_log.c
+++ b/crypto/ct/ct_log.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -22,6 +22,8 @@
* Information about a CT log server.
*/
struct ctlog_st {
+ OSSL_LIB_CTX *libctx;
+ char *propq;
char *name;
uint8_t log_id[CT_V1_HASHLEN];
EVP_PKEY *public_key;
@@ -32,6 +34,8 @@ struct ctlog_st {
* It takes ownership of any CTLOG instances added to it.
*/
struct ctlog_store_st {
+ OSSL_LIB_CTX *libctx;
+ char *propq;
STACK_OF(CTLOG) *logs;
};
@@ -59,7 +63,7 @@ static CTLOG_STORE_LOAD_CTX *ctlog_store_load_ctx_new(void)
CTLOG_STORE_LOAD_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL)
- CTerr(CT_F_CTLOG_STORE_LOAD_CTX_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
return ctx;
}
@@ -70,69 +74,95 @@ static void ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX* ctx)
}
/* Converts a log's public key into a SHA256 log ID */
-static int ct_v1_log_id_from_pkey(EVP_PKEY *pkey,
- unsigned char log_id[CT_V1_HASHLEN])
+static int ct_v1_log_id_from_pkey(CTLOG *log, EVP_PKEY *pkey)
{
int ret = 0;
unsigned char *pkey_der = NULL;
int pkey_der_len = i2d_PUBKEY(pkey, &pkey_der);
+ unsigned int len;
+ EVP_MD *sha256 = NULL;
if (pkey_der_len <= 0) {
- CTerr(CT_F_CT_V1_LOG_ID_FROM_PKEY, CT_R_LOG_KEY_INVALID);
+ ERR_raise(ERR_LIB_CT, CT_R_LOG_KEY_INVALID);
+ goto err;
+ }
+ sha256 = EVP_MD_fetch(log->libctx, "SHA2-256", log->propq);
+ if (sha256 == NULL) {
+ ERR_raise(ERR_LIB_CT, ERR_R_EVP_LIB);
goto err;
}
- SHA256(pkey_der, pkey_der_len, log_id);
- ret = 1;
+ ret = EVP_Digest(pkey_der, pkey_der_len, log->log_id, &len, sha256,
+ NULL);
err:
+ EVP_MD_free(sha256);
OPENSSL_free(pkey_der);
return ret;
}
-CTLOG_STORE *CTLOG_STORE_new(void)
+CTLOG_STORE *CTLOG_STORE_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
{
CTLOG_STORE *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- CTerr(CT_F_CTLOG_STORE_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
return NULL;
}
+ ret->libctx = libctx;
+ if (propq != NULL) {
+ ret->propq = OPENSSL_strdup(propq);
+ if (ret->propq == NULL) {
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
ret->logs = sk_CTLOG_new_null();
- if (ret->logs == NULL)
+ if (ret->logs == NULL) {
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
goto err;
+ }
return ret;
err:
- OPENSSL_free(ret);
+ CTLOG_STORE_free(ret);
return NULL;
}
+CTLOG_STORE *CTLOG_STORE_new(void)
+{
+ return CTLOG_STORE_new_ex(NULL, NULL);
+}
+
void CTLOG_STORE_free(CTLOG_STORE *store)
{
if (store != NULL) {
+ OPENSSL_free(store->propq);
sk_CTLOG_pop_free(store->logs, CTLOG_free);
OPENSSL_free(store);
}
}
-static int ctlog_new_from_conf(CTLOG **ct_log, const CONF *conf, const char *section)
+static int ctlog_new_from_conf(CTLOG_STORE *store, CTLOG **ct_log,
+ const CONF *conf, const char *section)
{
const char *description = NCONF_get_string(conf, section, "description");
char *pkey_base64;
if (description == NULL) {
- CTerr(CT_F_CTLOG_NEW_FROM_CONF, CT_R_LOG_CONF_MISSING_DESCRIPTION);
+ ERR_raise(ERR_LIB_CT, CT_R_LOG_CONF_MISSING_DESCRIPTION);
return 0;
}
pkey_base64 = NCONF_get_string(conf, section, "key");
if (pkey_base64 == NULL) {
- CTerr(CT_F_CTLOG_NEW_FROM_CONF, CT_R_LOG_CONF_MISSING_KEY);
+ ERR_raise(ERR_LIB_CT, CT_R_LOG_CONF_MISSING_KEY);
return 0;
}
- return CTLOG_new_from_base64(ct_log, pkey_base64, description);
+ return CTLOG_new_from_base64_ex(ct_log, pkey_base64, description,
+ store->libctx, store->propq);
}
int CTLOG_STORE_load_default_file(CTLOG_STORE *store)
@@ -168,7 +198,7 @@ static int ctlog_store_load_log(const char *log_name, int log_name_len,
if (tmp == NULL)
goto mem_err;
- ret = ctlog_new_from_conf(&ct_log, load_ctx->conf, tmp);
+ ret = ctlog_new_from_conf(load_ctx->log_store, &ct_log, load_ctx->conf, tmp);
OPENSSL_free(tmp);
if (ret < 0) {
@@ -188,7 +218,7 @@ static int ctlog_store_load_log(const char *log_name, int log_name_len,
mem_err:
CTLOG_free(ct_log);
- CTerr(CT_F_CTLOG_STORE_LOAD_LOG, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
return -1;
}
@@ -206,19 +236,19 @@ int CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file)
goto end;
if (NCONF_load(load_ctx->conf, file, NULL) <= 0) {
- CTerr(CT_F_CTLOG_STORE_LOAD_FILE, CT_R_LOG_CONF_INVALID);
+ ERR_raise(ERR_LIB_CT, CT_R_LOG_CONF_INVALID);
goto end;
}
enabled_logs = NCONF_get_string(load_ctx->conf, NULL, "enabled_logs");
if (enabled_logs == NULL) {
- CTerr(CT_F_CTLOG_STORE_LOAD_FILE, CT_R_LOG_CONF_INVALID);
+ ERR_raise(ERR_LIB_CT, CT_R_LOG_CONF_INVALID);
goto end;
}
if (!CONF_parse_list(enabled_logs, ',', 1, ctlog_store_load_log, load_ctx) ||
load_ctx->invalid_log_entries > 0) {
- CTerr(CT_F_CTLOG_STORE_LOAD_FILE, CT_R_LOG_CONF_INVALID);
+ ERR_raise(ERR_LIB_CT, CT_R_LOG_CONF_INVALID);
goto end;
}
@@ -234,22 +264,32 @@ end:
* Takes ownership of the public key.
* Copies the name.
*/
-CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name)
+CTLOG *CTLOG_new_ex(EVP_PKEY *public_key, const char *name, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
CTLOG *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- CTerr(CT_F_CTLOG_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
return NULL;
}
+ ret->libctx = libctx;
+ if (propq != NULL) {
+ ret->propq = OPENSSL_strdup(propq);
+ if (ret->propq == NULL) {
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
ret->name = OPENSSL_strdup(name);
if (ret->name == NULL) {
- CTerr(CT_F_CTLOG_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (ct_v1_log_id_from_pkey(public_key, ret->log_id) != 1)
+ if (ct_v1_log_id_from_pkey(ret, public_key) != 1)
goto err;
ret->public_key = public_key;
@@ -259,12 +299,18 @@ err:
return NULL;
}
+CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name)
+{
+ return CTLOG_new_ex(public_key, name, NULL, NULL);
+}
+
/* Frees CT log and associated structures */
void CTLOG_free(CTLOG *log)
{
if (log != NULL) {
OPENSSL_free(log->name);
EVP_PKEY_free(log->public_key);
+ OPENSSL_free(log->propq);
OPENSSL_free(log);
}
}
diff --git a/crypto/ct/ct_oct.c b/crypto/ct/ct_oct.c
index d4b6645af48d..72a43374797c 100644
--- a/crypto/ct/ct_oct.c
+++ b/crypto/ct/ct_oct.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -28,7 +28,7 @@ int o2i_SCT_signature(SCT *sct, const unsigned char **in, size_t len)
const unsigned char *p;
if (sct->version != SCT_VERSION_V1) {
- CTerr(CT_F_O2I_SCT_SIGNATURE, CT_R_UNSUPPORTED_VERSION);
+ ERR_raise(ERR_LIB_CT, CT_R_UNSUPPORTED_VERSION);
return -1;
}
/*
@@ -39,7 +39,7 @@ int o2i_SCT_signature(SCT *sct, const unsigned char **in, size_t len)
* all supported algorithms.
*/
if (len <= 4) {
- CTerr(CT_F_O2I_SCT_SIGNATURE, CT_R_SCT_INVALID_SIGNATURE);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID_SIGNATURE);
return -1;
}
@@ -48,14 +48,14 @@ int o2i_SCT_signature(SCT *sct, const unsigned char **in, size_t len)
sct->hash_alg = *p++;
sct->sig_alg = *p++;
if (SCT_get_signature_nid(sct) == NID_undef) {
- CTerr(CT_F_O2I_SCT_SIGNATURE, CT_R_SCT_INVALID_SIGNATURE);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID_SIGNATURE);
return -1;
}
/* Retrieve signature and check it is consistent with the buffer length */
n2s(p, siglen);
len_remaining -= (p - *in);
if (siglen > len_remaining) {
- CTerr(CT_F_O2I_SCT_SIGNATURE, CT_R_SCT_INVALID_SIGNATURE);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID_SIGNATURE);
return -1;
}
@@ -73,7 +73,7 @@ SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len)
const unsigned char *p;
if (len == 0 || len > MAX_SCT_SIZE) {
- CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID);
goto err;
}
@@ -96,12 +96,12 @@ SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len)
* }
*/
if (len < 43) {
- CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID);
goto err;
}
len -= 43;
p++;
- sct->log_id = BUF_memdup(p, CT_V1_HASHLEN);
+ sct->log_id = OPENSSL_memdup(p, CT_V1_HASHLEN);
if (sct->log_id == NULL)
goto err;
sct->log_id_len = CT_V1_HASHLEN;
@@ -111,11 +111,11 @@ SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len)
n2s(p, len2);
if (len < len2) {
- CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID);
goto err;
}
if (len2 > 0) {
- sct->ext = BUF_memdup(p, len2);
+ sct->ext = OPENSSL_memdup(p, len2);
if (sct->ext == NULL)
goto err;
}
@@ -125,14 +125,14 @@ SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len)
sig_len = o2i_SCT_signature(sct, &p, len);
if (sig_len <= 0) {
- CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID);
goto err;
}
len -= sig_len;
*in = p + len;
} else {
/* If not V1 just cache encoding */
- sct->sct = BUF_memdup(p, len);
+ sct->sct = OPENSSL_memdup(p, len);
if (sct->sct == NULL)
goto err;
sct->sct_len = len;
@@ -156,12 +156,12 @@ int i2o_SCT_signature(const SCT *sct, unsigned char **out)
unsigned char *p = NULL, *pstart = NULL;
if (!SCT_signature_is_complete(sct)) {
- CTerr(CT_F_I2O_SCT_SIGNATURE, CT_R_SCT_INVALID_SIGNATURE);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID_SIGNATURE);
goto err;
}
if (sct->version != SCT_VERSION_V1) {
- CTerr(CT_F_I2O_SCT_SIGNATURE, CT_R_UNSUPPORTED_VERSION);
+ ERR_raise(ERR_LIB_CT, CT_R_UNSUPPORTED_VERSION);
goto err;
}
@@ -179,7 +179,7 @@ int i2o_SCT_signature(const SCT *sct, unsigned char **out)
} else {
pstart = p = OPENSSL_malloc(len);
if (p == NULL) {
- CTerr(CT_F_I2O_SCT_SIGNATURE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
goto err;
}
*out = p;
@@ -203,7 +203,7 @@ int i2o_SCT(const SCT *sct, unsigned char **out)
unsigned char *p = NULL, *pstart = NULL;
if (!SCT_is_complete(sct)) {
- CTerr(CT_F_I2O_SCT, CT_R_SCT_NOT_SET);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_NOT_SET);
goto err;
}
/*
@@ -226,7 +226,7 @@ int i2o_SCT(const SCT *sct, unsigned char **out)
} else {
pstart = p = OPENSSL_malloc(len);
if (p == NULL) {
- CTerr(CT_F_I2O_SCT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
goto err;
}
*out = p;
@@ -261,13 +261,13 @@ STACK_OF(SCT) *o2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp,
size_t list_len, sct_len;
if (len < 2 || len > MAX_SCT_LIST_SIZE) {
- CTerr(CT_F_O2I_SCT_LIST, CT_R_SCT_LIST_INVALID);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_LIST_INVALID);
return NULL;
}
n2s(*pp, list_len);
if (list_len != len - 2) {
- CTerr(CT_F_O2I_SCT_LIST, CT_R_SCT_LIST_INVALID);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_LIST_INVALID);
return NULL;
}
@@ -288,14 +288,14 @@ STACK_OF(SCT) *o2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp,
SCT *sct;
if (list_len < 2) {
- CTerr(CT_F_O2I_SCT_LIST, CT_R_SCT_LIST_INVALID);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_LIST_INVALID);
goto err;
}
n2s(*pp, sct_len);
list_len -= 2;
if (sct_len == 0 || sct_len > list_len) {
- CTerr(CT_F_O2I_SCT_LIST, CT_R_SCT_LIST_INVALID);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_LIST_INVALID);
goto err;
}
list_len -= sct_len;
@@ -327,11 +327,11 @@ int i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp)
if (pp != NULL) {
if (*pp == NULL) {
if ((len = i2o_SCT_LIST(a, NULL)) == -1) {
- CTerr(CT_F_I2O_SCT_LIST, CT_R_SCT_LIST_INVALID);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_LIST_INVALID);
return -1;
}
if ((*pp = OPENSSL_malloc(len)) == NULL) {
- CTerr(CT_F_I2O_SCT_LIST, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
return -1;
}
is_pp_new = 1;
diff --git a/crypto/ct/ct_policy.c b/crypto/ct/ct_policy.c
index df66e8a494d0..80a8baabe163 100644
--- a/crypto/ct/ct_policy.c
+++ b/crypto/ct/ct_policy.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -25,15 +25,26 @@
*/
static const time_t SCT_CLOCK_DRIFT_TOLERANCE = 300;
-CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void)
+CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new_ex(OSSL_LIB_CTX *libctx,
+ const char *propq)
{
CT_POLICY_EVAL_CTX *ctx = OPENSSL_zalloc(sizeof(CT_POLICY_EVAL_CTX));
if (ctx == NULL) {
- CTerr(CT_F_CT_POLICY_EVAL_CTX_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
return NULL;
}
+ ctx->libctx = libctx;
+ if (propq != NULL) {
+ ctx->propq = OPENSSL_strdup(propq);
+ if (ctx->propq == NULL) {
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(ctx);
+ return NULL;
+ }
+ }
+
/* time(NULL) shouldn't ever fail, so don't bother checking for -1. */
ctx->epoch_time_in_ms = (uint64_t)(time(NULL) + SCT_CLOCK_DRIFT_TOLERANCE) *
1000;
@@ -41,12 +52,18 @@ CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void)
return ctx;
}
+CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void)
+{
+ return CT_POLICY_EVAL_CTX_new_ex(NULL, NULL);
+}
+
void CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx)
{
if (ctx == NULL)
return;
X509_free(ctx->cert);
X509_free(ctx->issuer);
+ OPENSSL_free(ctx->propq);
OPENSSL_free(ctx);
}
diff --git a/crypto/ct/ct_prn.c b/crypto/ct/ct_prn.c
index e6584b57f391..374235b7ec57 100644
--- a/crypto/ct/ct_prn.c
+++ b/crypto/ct/ct_prn.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/ct/ct_sct.c b/crypto/ct/ct_sct.c
index 4ff36e2fbd49..10a67ed6d68d 100644
--- a/crypto/ct/ct_sct.c
+++ b/crypto/ct/ct_sct.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -24,7 +24,7 @@ SCT *SCT_new(void)
SCT *sct = OPENSSL_zalloc(sizeof(*sct));
if (sct == NULL) {
- CTerr(CT_F_SCT_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -53,7 +53,7 @@ void SCT_LIST_free(STACK_OF(SCT) *a)
int SCT_set_version(SCT *sct, sct_version_t version)
{
if (version != SCT_VERSION_V1) {
- CTerr(CT_F_SCT_SET_VERSION, CT_R_UNSUPPORTED_VERSION);
+ ERR_raise(ERR_LIB_CT, CT_R_UNSUPPORTED_VERSION);
return 0;
}
sct->version = version;
@@ -73,14 +73,14 @@ int SCT_set_log_entry_type(SCT *sct, ct_log_entry_type_t entry_type)
case CT_LOG_ENTRY_TYPE_NOT_SET:
break;
}
- CTerr(CT_F_SCT_SET_LOG_ENTRY_TYPE, CT_R_UNSUPPORTED_ENTRY_TYPE);
+ ERR_raise(ERR_LIB_CT, CT_R_UNSUPPORTED_ENTRY_TYPE);
return 0;
}
int SCT_set0_log_id(SCT *sct, unsigned char *log_id, size_t log_id_len)
{
if (sct->version == SCT_VERSION_V1 && log_id_len != CT_V1_HASHLEN) {
- CTerr(CT_F_SCT_SET0_LOG_ID, CT_R_INVALID_LOG_ID_LENGTH);
+ ERR_raise(ERR_LIB_CT, CT_R_INVALID_LOG_ID_LENGTH);
return 0;
}
@@ -94,7 +94,7 @@ int SCT_set0_log_id(SCT *sct, unsigned char *log_id, size_t log_id_len)
int SCT_set1_log_id(SCT *sct, const unsigned char *log_id, size_t log_id_len)
{
if (sct->version == SCT_VERSION_V1 && log_id_len != CT_V1_HASHLEN) {
- CTerr(CT_F_SCT_SET1_LOG_ID, CT_R_INVALID_LOG_ID_LENGTH);
+ ERR_raise(ERR_LIB_CT, CT_R_INVALID_LOG_ID_LENGTH);
return 0;
}
@@ -106,7 +106,7 @@ int SCT_set1_log_id(SCT *sct, const unsigned char *log_id, size_t log_id_len)
if (log_id != NULL && log_id_len > 0) {
sct->log_id = OPENSSL_memdup(log_id, log_id_len);
if (sct->log_id == NULL) {
- CTerr(CT_F_SCT_SET1_LOG_ID, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
return 0;
}
sct->log_id_len = log_id_len;
@@ -135,7 +135,7 @@ int SCT_set_signature_nid(SCT *sct, int nid)
sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
return 1;
default:
- CTerr(CT_F_SCT_SET_SIGNATURE_NID, CT_R_UNRECOGNIZED_SIGNATURE_NID);
+ ERR_raise(ERR_LIB_CT, CT_R_UNRECOGNIZED_SIGNATURE_NID);
return 0;
}
}
@@ -158,7 +158,7 @@ int SCT_set1_extensions(SCT *sct, const unsigned char *ext, size_t ext_len)
if (ext != NULL && ext_len > 0) {
sct->ext = OPENSSL_memdup(ext, ext_len);
if (sct->ext == NULL) {
- CTerr(CT_F_SCT_SET1_EXTENSIONS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
return 0;
}
sct->ext_len = ext_len;
@@ -184,7 +184,7 @@ int SCT_set1_signature(SCT *sct, const unsigned char *sig, size_t sig_len)
if (sig != NULL && sig_len > 0) {
sct->sig = OPENSSL_memdup(sig, sig_len);
if (sct->sig == NULL) {
- CTerr(CT_F_SCT_SET1_SIGNATURE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
return 0;
}
sct->sig_len = sig_len;
@@ -312,7 +312,7 @@ int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx)
return 0;
}
- sctx = SCT_CTX_new();
+ sctx = SCT_CTX_new(ctx->libctx, ctx->propq);
if (sctx == NULL)
goto err;
@@ -343,7 +343,7 @@ int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx)
* XXX: Potential for optimization. This repeats some idempotent heavy
* lifting on the certificate for each candidate SCT, and appears to not
* use any information in the SCT itself, only the certificate is
- * processed. So it may make more sense to to do this just once, perhaps
+ * processed. So it may make more sense to do this just once, perhaps
* associated with the shared (by all SCTs) policy eval ctx.
*
* XXX: Failure here is global (SCT independent) and represents either an
diff --git a/crypto/ct/ct_sct_ctx.c b/crypto/ct/ct_sct_ctx.c
index 841e768033e5..8653684814ee 100644
--- a/crypto/ct/ct_sct_ctx.c
+++ b/crypto/ct/ct_sct_ctx.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -20,12 +20,24 @@
#include "ct_local.h"
-SCT_CTX *SCT_CTX_new(void)
+SCT_CTX *SCT_CTX_new(OSSL_LIB_CTX *libctx, const char *propq)
{
SCT_CTX *sctx = OPENSSL_zalloc(sizeof(*sctx));
- if (sctx == NULL)
- CTerr(CT_F_SCT_CTX_NEW, ERR_R_MALLOC_FAILURE);
+ if (sctx == NULL) {
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ sctx->libctx = libctx;
+ if (propq != NULL) {
+ sctx->propq = OPENSSL_strdup(propq);
+ if (sctx->propq == NULL) {
+ ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(sctx);
+ return NULL;
+ }
+ }
return sctx;
}
@@ -39,6 +51,7 @@ void SCT_CTX_free(SCT_CTX *sctx)
OPENSSL_free(sctx->ihash);
OPENSSL_free(sctx->certder);
OPENSSL_free(sctx->preder);
+ OPENSSL_free(sctx->propq);
OPENSSL_free(sctx);
}
@@ -155,15 +168,12 @@ int SCT_CTX_set1_cert(SCT_CTX *sctx, X509 *cert, X509 *presigner)
* SCT.
*/
if (idx >= 0) {
- X509_EXTENSION *ext;
-
/* Take a copy of certificate so we don't modify passed version */
pretmp = X509_dup(cert);
if (pretmp == NULL)
goto err;
- ext = X509_delete_ext(pretmp, idx);
- X509_EXTENSION_free(ext);
+ X509_EXTENSION_free(X509_delete_ext(pretmp, idx));
if (!ct_x509_cert_fixup(pretmp, presigner))
goto err;
@@ -191,13 +201,17 @@ err:
return 0;
}
-__owur static int ct_public_key_hash(X509_PUBKEY *pkey, unsigned char **hash,
- size_t *hash_len)
+__owur static int ct_public_key_hash(SCT_CTX *sctx, X509_PUBKEY *pkey,
+ unsigned char **hash, size_t *hash_len)
{
int ret = 0;
unsigned char *md = NULL, *der = NULL;
int der_len;
unsigned int md_len;
+ EVP_MD *sha256 = EVP_MD_fetch(sctx->libctx, "SHA2-256", sctx->propq);
+
+ if (sha256 == NULL)
+ goto err;
/* Reuse buffer if possible */
if (*hash != NULL && *hash_len >= SHA256_DIGEST_LENGTH) {
@@ -213,7 +227,7 @@ __owur static int ct_public_key_hash(X509_PUBKEY *pkey, unsigned char **hash,
if (der_len <= 0)
goto err;
- if (!EVP_Digest(der, der_len, md, &md_len, EVP_sha256(), NULL))
+ if (!EVP_Digest(der, der_len, md, &md_len, sha256, NULL))
goto err;
if (md != *hash) {
@@ -225,6 +239,7 @@ __owur static int ct_public_key_hash(X509_PUBKEY *pkey, unsigned char **hash,
md = NULL;
ret = 1;
err:
+ EVP_MD_free(sha256);
OPENSSL_free(md);
OPENSSL_free(der);
return ret;
@@ -237,7 +252,7 @@ int SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer)
int SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
{
- return ct_public_key_hash(pubkey, &sctx->ihash, &sctx->ihashlen);
+ return ct_public_key_hash(sctx, pubkey, &sctx->ihash, &sctx->ihashlen);
}
int SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
@@ -247,7 +262,7 @@ int SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
if (pkey == NULL)
return 0;
- if (!ct_public_key_hash(pubkey, &sctx->pkeyhash, &sctx->pkeyhashlen)) {
+ if (!ct_public_key_hash(sctx, pubkey, &sctx->pkeyhash, &sctx->pkeyhashlen)) {
EVP_PKEY_free(pkey);
return 0;
}
diff --git a/crypto/ct/ct_vfy.c b/crypto/ct/ct_vfy.c
index 74fd34f4154e..27fb79f40383 100644
--- a/crypto/ct/ct_vfy.c
+++ b/crypto/ct/ct_vfy.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -101,20 +101,20 @@ int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct)
if (!SCT_is_complete(sct) || sctx->pkey == NULL ||
sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET ||
(sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && sctx->ihash == NULL)) {
- CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_NOT_SET);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_NOT_SET);
return 0;
}
if (sct->version != SCT_VERSION_V1) {
- CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_UNSUPPORTED_VERSION);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_UNSUPPORTED_VERSION);
return 0;
}
if (sct->log_id_len != sctx->pkeyhashlen ||
memcmp(sct->log_id, sctx->pkeyhash, sctx->pkeyhashlen) != 0) {
- CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_LOG_ID_MISMATCH);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_LOG_ID_MISMATCH);
return 0;
}
if (sct->timestamp > sctx->epoch_time_in_ms) {
- CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_FUTURE_TIMESTAMP);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_FUTURE_TIMESTAMP);
return 0;
}
@@ -122,7 +122,8 @@ int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct)
if (ctx == NULL)
goto end;
- if (!EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, sctx->pkey))
+ if (!EVP_DigestVerifyInit_ex(ctx, NULL, "SHA2-256", sctx->libctx,
+ sctx->propq, sctx->pkey, NULL))
goto end;
if (!sct_ctx_update(ctx, sctx, sct))
@@ -132,7 +133,7 @@ int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct)
ret = EVP_DigestVerifyFinal(ctx, sct->sig, sct->sig_len);
/* If ret < 0 some other error: fall through without setting error */
if (ret == 0)
- CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_INVALID_SIGNATURE);
+ ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID_SIGNATURE);
end:
EVP_MD_CTX_free(ctx);
diff --git a/crypto/ct/ct_x509v3.c b/crypto/ct/ct_x509v3.c
index 19c2a852d24a..1284ec711db9 100644
--- a/crypto/ct/ct_x509v3.c
+++ b/crypto/ct/ct_x509v3.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -75,7 +75,7 @@ static STACK_OF(SCT) *ocsp_ext_d2i_SCT_LIST(STACK_OF(SCT) **a,
}
/* Handlers for X509v3/OCSP Certificate Transparency extensions */
-const X509V3_EXT_METHOD v3_ct_scts[3] = {
+const X509V3_EXT_METHOD ossl_v3_ct_scts[3] = {
/* X509v3 extension in certificates that contains SCTs */
{ NID_ct_precert_scts, 0, NULL,
NULL, (X509V3_EXT_FREE)SCT_LIST_free,
diff --git a/crypto/ctype.c b/crypto/ctype.c
index b7f1183f9ccf..de2e836ff783 100644
--- a/crypto/ctype.c
+++ b/crypto/ctype.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,7 +10,7 @@
#include <string.h>
#include <stdio.h>
#include "crypto/ctype.h"
-#include "openssl/ebcdic.h"
+#include <openssl/ebcdic.h>
/*
* Define the character classes for each character in the seven bit ASCII
@@ -257,6 +257,36 @@ int ossl_ctype_check(int c, unsigned int mask)
return a >= 0 && a < max && (ctype_char_map[a] & mask) != 0;
}
+/*
+ * Implement some of the simplier functions directly to avoid the overhead of
+ * accessing memory via ctype_char_map[].
+ */
+
+#define ASCII_IS_DIGIT(c) (c >= 0x30 && c <= 0x39)
+#define ASCII_IS_UPPER(c) (c >= 0x41 && c <= 0x5A)
+#define ASCII_IS_LOWER(c) (c >= 0x61 && c <= 0x7A)
+
+int ossl_isdigit(int c)
+{
+ int a = ossl_toascii(c);
+
+ return ASCII_IS_DIGIT(a);
+}
+
+int ossl_isupper(int c)
+{
+ int a = ossl_toascii(c);
+
+ return ASCII_IS_UPPER(a);
+}
+
+int ossl_islower(int c)
+{
+ int a = ossl_toascii(c);
+
+ return ASCII_IS_LOWER(a);
+}
+
#if defined(CHARSET_EBCDIC) && !defined(CHARSET_EBCDIC_TEST)
static const int case_change = 0x40;
#else
@@ -265,16 +295,19 @@ static const int case_change = 0x20;
int ossl_tolower(int c)
{
- return ossl_isupper(c) ? c ^ case_change : c;
+ int a = ossl_toascii(c);
+
+ return ASCII_IS_UPPER(a) ? c ^ case_change : c;
}
int ossl_toupper(int c)
{
- return ossl_islower(c) ? c ^ case_change : c;
+ int a = ossl_toascii(c);
+
+ return ASCII_IS_LOWER(a) ? c ^ case_change : c;
}
-int ascii_isdigit(const char inchar) {
- if (inchar > 0x2F && inchar < 0x3A)
- return 1;
- return 0;
+int ossl_ascii_isdigit(int c)
+{
+ return ASCII_IS_DIGIT(c);
}
diff --git a/crypto/cversion.c b/crypto/cversion.c
index 534e7eba55b3..530b0e805e8d 100644
--- a/crypto/cversion.c
+++ b/crypto/cversion.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -16,11 +16,42 @@ unsigned long OpenSSL_version_num(void)
return OPENSSL_VERSION_NUMBER;
}
+unsigned int OPENSSL_version_major(void)
+{
+ return OPENSSL_VERSION_MAJOR;
+}
+
+unsigned int OPENSSL_version_minor(void)
+{
+ return OPENSSL_VERSION_MINOR;
+}
+
+unsigned int OPENSSL_version_patch(void)
+{
+ return OPENSSL_VERSION_PATCH;
+}
+
+const char *OPENSSL_version_pre_release(void)
+{
+ return OPENSSL_VERSION_PRE_RELEASE;
+}
+
+const char *OPENSSL_version_build_metadata(void)
+{
+ return OPENSSL_VERSION_BUILD_METADATA;
+}
+
+extern char ossl_cpu_info_str[];
+
const char *OpenSSL_version(int t)
{
switch (t) {
case OPENSSL_VERSION:
return OPENSSL_VERSION_TEXT;
+ case OPENSSL_VERSION_STRING:
+ return OPENSSL_VERSION_STR;
+ case OPENSSL_FULL_VERSION_STRING:
+ return OPENSSL_FULL_VERSION_STR;
case OPENSSL_BUILT_ON:
return DATE;
case OPENSSL_CFLAGS:
@@ -39,6 +70,17 @@ const char *OpenSSL_version(int t)
#else
return "ENGINESDIR: N/A";
#endif
+ case OPENSSL_MODULES_DIR:
+#ifdef MODULESDIR
+ return "MODULESDIR: \"" MODULESDIR "\"";
+#else
+ return "MODULESDIR: N/A";
+#endif
+ case OPENSSL_CPU_INFO:
+ if (OPENSSL_info(OPENSSL_INFO_CPU_SETTINGS) != NULL)
+ return ossl_cpu_info_str;
+ else
+ return "CPUINFO: N/A";
}
return "not available";
}
diff --git a/crypto/der_writer.c b/crypto/der_writer.c
new file mode 100644
index 000000000000..2ab7480a6749
--- /dev/null
+++ b/crypto/der_writer.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "internal/cryptlib.h"
+#include "internal/der.h"
+#include "crypto/bn.h"
+
+static int int_start_context(WPACKET *pkt, int tag)
+{
+ if (tag < 0)
+ return 1;
+ if (!ossl_assert(tag <= 30))
+ return 0;
+ return WPACKET_start_sub_packet(pkt);
+}
+
+static int int_end_context(WPACKET *pkt, int tag)
+{
+ /*
+ * If someone set the flag WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH on this
+ * sub-packet and this sub-packet has nothing written to it, the DER length
+ * will not be written, and the total written size will be unchanged before
+ * and after WPACKET_close(). We use size1 and size2 to determine if
+ * anything was written, and only write our tag if it has.
+ *
+ */
+ size_t size1, size2;
+
+ if (tag < 0)
+ return 1;
+ if (!ossl_assert(tag <= 30))
+ return 0;
+
+ /* Context specific are normally (?) constructed */
+ tag |= DER_F_CONSTRUCTED | DER_C_CONTEXT;
+
+ return WPACKET_get_total_written(pkt, &size1)
+ && WPACKET_close(pkt)
+ && WPACKET_get_total_written(pkt, &size2)
+ && (size1 == size2 || WPACKET_put_bytes_u8(pkt, tag));
+}
+
+int ossl_DER_w_precompiled(WPACKET *pkt, int tag,
+ const unsigned char *precompiled,
+ size_t precompiled_n)
+{
+ return int_start_context(pkt, tag)
+ && WPACKET_memcpy(pkt, precompiled, precompiled_n)
+ && int_end_context(pkt, tag);
+}
+
+int ossl_DER_w_boolean(WPACKET *pkt, int tag, int b)
+{
+ return int_start_context(pkt, tag)
+ && WPACKET_start_sub_packet(pkt)
+ && (!b || WPACKET_put_bytes_u8(pkt, 0xFF))
+ && !WPACKET_close(pkt)
+ && !WPACKET_put_bytes_u8(pkt, DER_P_BOOLEAN)
+ && int_end_context(pkt, tag);
+}
+
+int ossl_DER_w_octet_string(WPACKET *pkt, int tag,
+ const unsigned char *data, size_t data_n)
+{
+ return int_start_context(pkt, tag)
+ && WPACKET_start_sub_packet(pkt)
+ && WPACKET_memcpy(pkt, data, data_n)
+ && WPACKET_close(pkt)
+ && WPACKET_put_bytes_u8(pkt, DER_P_OCTET_STRING)
+ && int_end_context(pkt, tag);
+}
+
+int ossl_DER_w_octet_string_uint32(WPACKET *pkt, int tag, uint32_t value)
+{
+ unsigned char tmp[4] = { 0, 0, 0, 0 };
+ unsigned char *pbuf = tmp + (sizeof(tmp) - 1);
+
+ while (value > 0) {
+ *pbuf-- = (value & 0xFF);
+ value >>= 8;
+ }
+ return ossl_DER_w_octet_string(pkt, tag, tmp, sizeof(tmp));
+}
+
+static int int_der_w_integer(WPACKET *pkt, int tag,
+ int (*put_bytes)(WPACKET *pkt, const void *v,
+ unsigned int *top_byte),
+ const void *v)
+{
+ unsigned int top_byte = 0;
+
+ return int_start_context(pkt, tag)
+ && WPACKET_start_sub_packet(pkt)
+ && put_bytes(pkt, v, &top_byte)
+ && ((top_byte & 0x80) == 0 || WPACKET_put_bytes_u8(pkt, 0))
+ && WPACKET_close(pkt)
+ && WPACKET_put_bytes_u8(pkt, DER_P_INTEGER)
+ && int_end_context(pkt, tag);
+}
+
+static int int_put_bytes_uint32(WPACKET *pkt, const void *v,
+ unsigned int *top_byte)
+{
+ const uint32_t *value = v;
+ uint32_t tmp = *value;
+ size_t n = 0;
+
+ while (tmp != 0) {
+ n++;
+ *top_byte = (tmp & 0xFF);
+ tmp >>= 8;
+ }
+ if (n == 0)
+ n = 1;
+
+ return WPACKET_put_bytes__(pkt, *value, n);
+}
+
+/* For integers, we only support unsigned values for now */
+int ossl_DER_w_uint32(WPACKET *pkt, int tag, uint32_t v)
+{
+ return int_der_w_integer(pkt, tag, int_put_bytes_uint32, &v);
+}
+
+static int int_put_bytes_bn(WPACKET *pkt, const void *v,
+ unsigned int *top_byte)
+{
+ unsigned char *p = NULL;
+ size_t n = BN_num_bytes(v);
+
+ /* The BIGNUM limbs are in LE order */
+ *top_byte =
+ ((bn_get_words(v) [(n - 1) / BN_BYTES]) >> (8 * ((n - 1) % BN_BYTES)))
+ & 0xFF;
+
+ if (!WPACKET_allocate_bytes(pkt, n, &p))
+ return 0;
+ if (p != NULL)
+ BN_bn2bin(v, p);
+ return 1;
+}
+
+int ossl_DER_w_bn(WPACKET *pkt, int tag, const BIGNUM *v)
+{
+ if (v == NULL || BN_is_negative(v))
+ return 0;
+ if (BN_is_zero(v))
+ return ossl_DER_w_uint32(pkt, tag, 0);
+
+ return int_der_w_integer(pkt, tag, int_put_bytes_bn, v);
+}
+
+int ossl_DER_w_null(WPACKET *pkt, int tag)
+{
+ return int_start_context(pkt, tag)
+ && WPACKET_start_sub_packet(pkt)
+ && WPACKET_close(pkt)
+ && WPACKET_put_bytes_u8(pkt, DER_P_NULL)
+ && int_end_context(pkt, tag);
+}
+
+/* Constructed things need a start and an end */
+int ossl_DER_w_begin_sequence(WPACKET *pkt, int tag)
+{
+ return int_start_context(pkt, tag)
+ && WPACKET_start_sub_packet(pkt);
+}
+
+int ossl_DER_w_end_sequence(WPACKET *pkt, int tag)
+{
+ /*
+ * If someone set the flag WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH on this
+ * sub-packet and this sub-packet has nothing written to it, the DER length
+ * will not be written, and the total written size will be unchanged before
+ * and after WPACKET_close(). We use size1 and size2 to determine if
+ * anything was written, and only write our tag if it has.
+ *
+ * Because we know that int_end_context() needs to do the same check,
+ * we reproduce this flag if the written length was unchanged, or we will
+ * have an erroneous context tag.
+ */
+ size_t size1, size2;
+
+ return WPACKET_get_total_written(pkt, &size1)
+ && WPACKET_close(pkt)
+ && WPACKET_get_total_written(pkt, &size2)
+ && (size1 == size2
+ ? WPACKET_set_flags(pkt, WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH)
+ : WPACKET_put_bytes_u8(pkt, DER_F_CONSTRUCTED | DER_P_SEQUENCE))
+ && int_end_context(pkt, tag);
+}
diff --git a/crypto/des/asm/crypt586.pl b/crypto/des/asm/crypt586.pl
index d14b9f89b6b6..e175b4f5515b 100644
--- a/crypto/des/asm/crypt586.pl
+++ b/crypto/des/asm/crypt586.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -13,8 +13,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
&asm_init($ARGV[0]);
diff --git a/crypto/des/asm/des-586.pl b/crypto/des/asm/des-586.pl
index 07d9d87ac735..fe51a227ca57 100644
--- a/crypto/des/asm/des-586.pl
+++ b/crypto/des/asm/des-586.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -20,8 +20,7 @@ require "desboth.pl";
# format.
#
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
&asm_init($ARGV[0]);
diff --git a/crypto/des/asm/des_enc.m4 b/crypto/des/asm/des_enc.m4
index ebb5e7cd1d75..c00ac6184d13 100644
--- a/crypto/des/asm/des_enc.m4
+++ b/crypto/des/asm/des_enc.m4
@@ -1,6 +1,6 @@
-! Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+! Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
!
-! Licensed under the OpenSSL license (the "License"). You may not use
+! Licensed under the Apache License 2.0 (the "License"). You may not use
! this file except in compliance with the License. You can obtain a copy
! in the file LICENSE in the source distribution or at
! https://www.openssl.org/source/license.html
@@ -29,8 +29,6 @@
.ident "des_enc.m4 2.1"
.file "des_enc-sparc.S"
-#include <openssl/opensslconf.h>
-
#if defined(__SUNPRO_C) && defined(__sparcv9)
# define ABI64 /* They've said -xarch=v9 at command line */
#elif defined(__GNUC__) && defined(__arch64__)
diff --git a/crypto/des/asm/desboth.pl b/crypto/des/asm/desboth.pl
index ef7054e27506..afffd20d84cd 100644
--- a/crypto/des/asm/desboth.pl
+++ b/crypto/des/asm/desboth.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
diff --git a/crypto/des/asm/dest4-sparcv9.pl b/crypto/des/asm/dest4-sparcv9.pl
index 5c92a52b7957..afa15860f0a0 100644
--- a/crypto/des/asm/dest4-sparcv9.pl
+++ b/crypto/des/asm/dest4-sparcv9.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -34,11 +34,13 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "sparcv9_modes.pl";
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
$code.=<<___;
-#include "sparc_arch.h"
+#ifndef __ASSEMBLER__
+# define __ASSEMBLER__ 1
+#endif
+#include "crypto/sparc_arch.h"
#ifdef __arch64__
.register %g2,#scratch
diff --git a/crypto/des/build.info b/crypto/des/build.info
index 05cb154cd462..5a13e4f9bebc 100644
--- a/crypto/des/build.info
+++ b/crypto/des/build.info
@@ -1,19 +1,47 @@
+$DESASM=des_enc.c fcrypt_b.c
+IF[{- !$disabled{asm} -}]
+ $DESASM_x86=des-586.S crypt586.S
+ $DESASM_sparcv9=des_enc-sparc.S fcrypt_b.c dest4-sparcv9.S
+ $DESASM_sparcv8=des_enc-sparc.S fcrypt_b.c
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one
+ IF[$DESASM_{- $target{asm_arch} -}]
+ $DESASM=$DESASM_{- $target{asm_arch} -}
+ $DESDEF=DES_ASM
+ ENDIF
+ENDIF
+
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- set_key.c ecb_enc.c cbc_enc.c \
- ecb3_enc.c cfb64enc.c cfb64ede.c cfb_enc.c \
- ofb64ede.c ofb64enc.c ofb_enc.c \
- str2key.c pcbc_enc.c qud_cksm.c rand_key.c \
- {- $target{des_asm_src} -} \
- fcrypt.c xcbc_enc.c cbc_cksm.c
+$COMMON=set_key.c ecb3_enc.c
+$ALL=$COMMON\
+ ecb_enc.c cbc_enc.c \
+ cfb64enc.c cfb64ede.c cfb_enc.c \
+ ofb64ede.c ofb64enc.c ofb_enc.c \
+ str2key.c pcbc_enc.c qud_cksm.c rand_key.c \
+ fcrypt.c xcbc_enc.c cbc_cksm.c
+
+SOURCE[../../libcrypto]=$ALL $DESASM
+SOURCE[../../providers/libfips.a]=$COMMON $DESASM
+IF[{- !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../../providers/liblegacy.a]=$DESASM
+ENDIF
+
+DEFINE[../../libcrypto]=$DESDEF
+DEFINE[../../providers/libfips.a]=$DESDEF
+
+# When all deprecated symbols are removed, libcrypto doesn't export the
+# DES functions, so we must include them directly in liblegacy.a
+IF[{- $disabled{'deprecated-3.0'} && !$disabled{des} -}]
+ SOURCE[../../providers/liblegacy.a]=$ALL
+ DEFINE[../../providers/liblegacy.a]=$DESDEF
+ENDIF
GENERATE[des_enc-sparc.S]=asm/des_enc.m4
-GENERATE[dest4-sparcv9.S]=asm/dest4-sparcv9.pl $(PERLASM_SCHEME)
+GENERATE[dest4-sparcv9.S]=asm/dest4-sparcv9.pl
INCLUDE[dest4-sparcv9.o]=..
-GENERATE[des-586.s]=asm/des-586.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS)
-DEPEND[des-586.s]=../perlasm/x86asm.pl ../perlasm/cbc.pl
-GENERATE[crypt586.s]=asm/crypt586.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS)
-DEPEND[crypt586.s]=../perlasm/x86asm.pl ../perlasm/cbc.pl
+GENERATE[des-586.S]=asm/des-586.pl
+DEPEND[des-586.S]=../perlasm/x86asm.pl ../perlasm/cbc.pl
+GENERATE[crypt586.S]=asm/crypt586.pl
+DEPEND[crypt586.S]=../perlasm/x86asm.pl ../perlasm/cbc.pl
diff --git a/crypto/des/cbc_cksm.c b/crypto/des/cbc_cksm.c
index c5e2e017b84e..d8ab38bf2377 100644
--- a/crypto/des/cbc_cksm.c
+++ b/crypto/des/cbc_cksm.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include "des_local.h"
DES_LONG DES_cbc_cksum(const unsigned char *in, DES_cblock *output,
diff --git a/crypto/des/cbc_enc.c b/crypto/des/cbc_enc.c
index 92e773f81f4a..aa8ac1a5c339 100644
--- a/crypto/des/cbc_enc.c
+++ b/crypto/des/cbc_enc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#define CBC_ENC_C__DONT_UPDATE_IV
#include "ncbc_enc.c" /* des_cbc_encrypt */
diff --git a/crypto/des/cfb64ede.c b/crypto/des/cfb64ede.c
index 490d925f46f4..c8e4e5cd2d93 100644
--- a/crypto/des/cfb64ede.c
+++ b/crypto/des/cfb64ede.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include "des_local.h"
/*
diff --git a/crypto/des/cfb64enc.c b/crypto/des/cfb64enc.c
index ca0e82164803..93ebf76825c9 100644
--- a/crypto/des/cfb64enc.c
+++ b/crypto/des/cfb64enc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include "des_local.h"
/*
diff --git a/crypto/des/cfb_enc.c b/crypto/des/cfb_enc.c
index 17018420e6cc..30458d50a12a 100644
--- a/crypto/des/cfb_enc.c
+++ b/crypto/des/cfb_enc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include "e_os.h"
#include "des_local.h"
#include <assert.h>
diff --git a/crypto/des/des_enc.c b/crypto/des/des_enc.c
index 45eec615d8b0..0041f21b8d3b 100644
--- a/crypto/des/des_enc.c
+++ b/crypto/des/des_enc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/crypto.h>
#include "des_local.h"
#include "spr.h"
diff --git a/crypto/des/des_local.h b/crypto/des/des_local.h
index 0f58a1c9ae2e..f888cb800169 100644
--- a/crypto/des/des_local.h
+++ b/crypto/des/des_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/des/ecb3_enc.c b/crypto/des/ecb3_enc.c
index 7afa8eaadde7..48e524dc3666 100644
--- a/crypto/des/ecb3_enc.c
+++ b/crypto/des/ecb3_enc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include "des_local.h"
void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output,
diff --git a/crypto/des/ecb_enc.c b/crypto/des/ecb_enc.c
index 513c65e116cd..c230a3737ce8 100644
--- a/crypto/des/ecb_enc.c
+++ b/crypto/des/ecb_enc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include "des_local.h"
#include <openssl/opensslv.h>
#include <openssl/bio.h>
diff --git a/crypto/des/fcrypt.c b/crypto/des/fcrypt.c
index e83cf76b615c..c3827a61c9bd 100644
--- a/crypto/des/fcrypt.c
+++ b/crypto/des/fcrypt.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
/* NOCW */
#include <stdio.h>
#ifdef _OSD_POSIX
@@ -25,7 +31,7 @@
* Added more values to handle illegal salt values the way normal crypt()
* implementations do.
*/
-static unsigned const char con_salt[128] = {
+static const unsigned char con_salt[128] = {
0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1,
0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9,
@@ -44,7 +50,7 @@ static unsigned const char con_salt[128] = {
0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44,
};
-static unsigned const char cov_2char[64] = {
+static const unsigned char cov_2char[64] = {
0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44,
0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
diff --git a/crypto/des/fcrypt_b.c b/crypto/des/fcrypt_b.c
index 22f967b8c6d3..e843e0e64397 100644
--- a/crypto/des/fcrypt_b.c
+++ b/crypto/des/fcrypt_b.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#define DES_FCRYPT
diff --git a/crypto/des/ncbc_enc.c b/crypto/des/ncbc_enc.c
index cd4b071a3d73..e8decf1fbee0 100644
--- a/crypto/des/ncbc_enc.c
+++ b/crypto/des/ncbc_enc.c
@@ -1,7 +1,7 @@
/*
* Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/des/ofb64ede.c b/crypto/des/ofb64ede.c
index 68cf2dc557c6..edcfac853011 100644
--- a/crypto/des/ofb64ede.c
+++ b/crypto/des/ofb64ede.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include "des_local.h"
/*
diff --git a/crypto/des/ofb64enc.c b/crypto/des/ofb64enc.c
index 5796980c1865..73d4e21d2f9b 100644
--- a/crypto/des/ofb64enc.c
+++ b/crypto/des/ofb64enc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include "des_local.h"
/*
diff --git a/crypto/des/ofb_enc.c b/crypto/des/ofb_enc.c
index 2b0498994b51..50c7f4c43213 100644
--- a/crypto/des/ofb_enc.c
+++ b/crypto/des/ofb_enc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include "des_local.h"
/*
diff --git a/crypto/des/pcbc_enc.c b/crypto/des/pcbc_enc.c
index 3490592741c6..dd9eb1a92774 100644
--- a/crypto/des/pcbc_enc.c
+++ b/crypto/des/pcbc_enc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include "des_local.h"
void DES_pcbc_encrypt(const unsigned char *input, unsigned char *output,
diff --git a/crypto/des/qud_cksm.c b/crypto/des/qud_cksm.c
index 10b6abf69ea5..9f6839907797 100644
--- a/crypto/des/qud_cksm.c
+++ b/crypto/des/qud_cksm.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,6 +13,13 @@
* only based on the code in this paper and is almost definitely not the same
* as the MIT implementation.
*/
+
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include "des_local.h"
#define Q_B0(a) (((DES_LONG)(a)))
diff --git a/crypto/des/rand_key.c b/crypto/des/rand_key.c
index fe8aefec370d..4c6588787126 100644
--- a/crypto/des/rand_key.c
+++ b/crypto/des/rand_key.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/des.h>
#include <openssl/rand.h>
diff --git a/crypto/des/set_key.c b/crypto/des/set_key.c
index cbcb616cb2ad..adcfb7f12451 100644
--- a/crypto/des/set_key.c
+++ b/crypto/des/set_key.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -15,12 +15,18 @@
* 1.1 added norm_expand_bits
* 1.0 First working version
*/
+
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/crypto.h>
+#include "internal/constant_time.h"
+#include "internal/nelem.h"
#include "des_local.h"
-/* defaults to false */
-OPENSSL_IMPLEMENT_GLOBAL(int, DES_check_key, 0)
-
static const unsigned char odd_parity[256] = {
1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14,
16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
@@ -58,15 +64,23 @@ void DES_set_odd_parity(DES_cblock *key)
(*key)[i] = odd_parity[(*key)[i]];
}
+/*
+ * Check that a key has the correct parity.
+ * Return 1 if parity is okay and 0 if not.
+ */
int DES_check_key_parity(const_DES_cblock *key)
{
unsigned int i;
+ unsigned char res = 0377, b;
for (i = 0; i < DES_KEY_SZ; i++) {
- if ((*key)[i] != odd_parity[(*key)[i]])
- return 0;
+ b = (*key)[i];
+ b ^= b >> 4;
+ b ^= b >> 2;
+ b ^= b >> 1;
+ res &= constant_time_eq_8(b & 1, 1);
}
- return 1;
+ return (int)(res & 1);
}
/*-
@@ -77,8 +91,7 @@ int DES_check_key_parity(const_DES_cblock *key)
* %I John Wiley & Sons
* %D 1984
*/
-#define NUM_WEAK_KEY 16
-static const DES_cblock weak_keys[NUM_WEAK_KEY] = {
+static const DES_cblock weak_keys[] = {
/* weak keys */
{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
{0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE},
@@ -99,14 +112,20 @@ static const DES_cblock weak_keys[NUM_WEAK_KEY] = {
{0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1}
};
+/*
+ * Check for weak keys.
+ * Return 1 if the key is weak and 0 otherwise.
+ */
int DES_is_weak_key(const_DES_cblock *key)
{
- int i;
+ unsigned int i, res = 0;
+ int j;
- for (i = 0; i < NUM_WEAK_KEY; i++)
- if (memcmp(weak_keys[i], key, sizeof(DES_cblock)) == 0)
- return 1;
- return 0;
+ for (i = 0; i < OSSL_NELEM(weak_keys); i++) {
+ j = CRYPTO_memcmp(weak_keys[i], key, sizeof(DES_cblock));
+ res |= constant_time_is_zero((unsigned int)j);
+ }
+ return (int)(res & 1);
}
/*-
@@ -275,14 +294,17 @@ static const DES_LONG des_skb[8][64] = {
}
};
+/* Return values as DES_set_key_checked() but always set the key */
int DES_set_key(const_DES_cblock *key, DES_key_schedule *schedule)
{
- if (DES_check_key) {
- return DES_set_key_checked(key, schedule);
- } else {
- DES_set_key_unchecked(key, schedule);
- return 0;
- }
+ int ret = 0;
+
+ if (!DES_check_key_parity(key))
+ ret = -1;
+ if (DES_is_weak_key(key))
+ ret = -2;
+ DES_set_key_unchecked(key, schedule);
+ return ret;
}
/*-
diff --git a/crypto/des/spr.h b/crypto/des/spr.h
index 2404e092d4ac..1fe3394ba0dc 100644
--- a/crypto/des/spr.h
+++ b/crypto/des/spr.h
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/des/str2key.c b/crypto/des/str2key.c
index 61db60512567..f6687fe524f0 100644
--- a/crypto/des/str2key.c
+++ b/crypto/des/str2key.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/crypto.h>
#include "des_local.h"
diff --git a/crypto/des/xcbc_enc.c b/crypto/des/xcbc_enc.c
index fb3fd5292cb6..8ad1f1db6dc3 100644
--- a/crypto/des/xcbc_enc.c
+++ b/crypto/des/xcbc_enc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include "des_local.h"
/* RSA's DESX */
diff --git a/crypto/dh/build.info b/crypto/dh/build.info
index b19ff6dbac19..b41356727185 100644
--- a/crypto/dh/build.info
+++ b/crypto/dh/build.info
@@ -1,5 +1,13 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- dh_asn1.c dh_gen.c dh_key.c dh_lib.c dh_check.c dh_err.c dh_depr.c \
- dh_ameth.c dh_pmeth.c dh_prn.c dh_rfc5114.c dh_kdf.c dh_meth.c \
- dh_rfc7919.c
+
+$COMMON=dh_lib.c dh_key.c dh_group_params.c dh_check.c dh_backend.c dh_gen.c \
+ dh_kdf.c
+
+SOURCE[../../libcrypto]=$COMMON\
+ dh_asn1.c dh_err.c \
+ dh_ameth.c dh_pmeth.c dh_prn.c dh_rfc5114.c dh_meth.c
+IF[{- !$disabled{'deprecated-0.9.8'} -}]
+ SOURCE[../../libcrypto]=dh_depr.c
+ENDIF
+
+SOURCE[../../providers/libfips.a]=$COMMON
diff --git a/crypto/dh/dh1024.pem b/crypto/dh/dh1024.pem
deleted file mode 100644
index 81d43f6a3eae..000000000000
--- a/crypto/dh/dh1024.pem
+++ /dev/null
@@ -1,5 +0,0 @@
------BEGIN DH PARAMETERS-----
-MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq
-/Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx
-/mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC
------END DH PARAMETERS-----
diff --git a/crypto/dh/dh192.pem b/crypto/dh/dh192.pem
deleted file mode 100644
index 521c07271d0d..000000000000
--- a/crypto/dh/dh192.pem
+++ /dev/null
@@ -1,3 +0,0 @@
------BEGIN DH PARAMETERS-----
-MB4CGQDUoLoCULb9LsYm5+/WN992xxbiLQlEuIsCAQM=
------END DH PARAMETERS-----
diff --git a/crypto/dh/dh2048.pem b/crypto/dh/dh2048.pem
deleted file mode 100644
index 295460f5081e..000000000000
--- a/crypto/dh/dh2048.pem
+++ /dev/null
@@ -1,16 +0,0 @@
------BEGIN DH PARAMETERS-----
-MIIBCAKCAQEA7ZKJNYJFVcs7+6J2WmkEYb8h86tT0s0h2v94GRFS8Q7B4lW9aG9o
-AFO5Imov5Jo0H2XMWTKKvbHbSe3fpxJmw/0hBHAY8H/W91hRGXKCeyKpNBgdL8sh
-z22SrkO2qCnHJ6PLAMXy5fsKpFmFor2tRfCzrfnggTXu2YOzzK7q62bmqVdmufEo
-pT8igNcLpvZxk5uBDvhakObMym9mX3rAEBoe8PwttggMYiiw7NuJKO4MqD1llGkW
-aVM8U2ATsCun1IKHrRxynkE1/MJ86VHeYYX8GZt2YA8z+GuzylIOKcMH6JAWzMwA
-Gbatw6QwizOhr9iMjZ0B26TE3X8LvW84wwIBAg==
------END DH PARAMETERS-----
------BEGIN DH PARAMETERS-----
-MIIBCAKCAQEArtA3w73zP6Lu3EOQtwogiXt3AXXpuS6yD4BhzNS1pZFyPHk0/an5
-8ydEkPhQZHKDW+BZJxxPLANaTudWo2YT8TgtvUdN6KSgMiEi6McwqDw+SADuvW+F
-SKUYFxG6VFIxyEP6xBdf+vhJxEDbRG2EYsHDRRtJ76gp9cSKTHusf2R+4AAVGqnt
-gRAbNqtcOar/7FSj+Pl8G3v0Bty0LcCSpbqgYlnv6z+rErQmmC6PPvSz97TDMCok
-yKpCE9hFA1zkqK3TH4FmFvGeIaXJUIBZf4mArWuBTjWFW3nmhESRUn1VK3K3x42N
-a5k6c2+EhrMFiLjxuH6JZoqL0/E93FF9SwIBAg==
------END DH PARAMETERS-----
diff --git a/crypto/dh/dh4096.pem b/crypto/dh/dh4096.pem
deleted file mode 100644
index 390943a21dc4..000000000000
--- a/crypto/dh/dh4096.pem
+++ /dev/null
@@ -1,14 +0,0 @@
------BEGIN DH PARAMETERS-----
-MIICCAKCAgEA/urRnb6vkPYc/KEGXWnbCIOaKitq7ySIq9dTH7s+Ri59zs77zty7
-vfVlSe6VFTBWgYjD2XKUFmtqq6CqXMhVX5ElUDoYDpAyTH85xqNFLzFC7nKrff/H
-TFKNttp22cZE9V0IPpzedPfnQkE7aUdmF9JnDyv21Z/818O93u1B4r0szdnmEvEF
-bKuIxEHX+bp0ZR7RqE1AeifXGJX3d6tsd2PMAObxwwsv55RGkn50vHO4QxtTARr1
-rRUV5j3B3oPMgC7Offxx+98Xn45B1/G0Prp11anDsR1PGwtaCYipqsvMwQUSJtyE
-EOQWk+yFkeMe4vWv367eEi0Sd/wnC+TSXBE3pYvpYerJ8n1MceI5GQTdarJ77OW9
-bGTHmxRsLSCM1jpLdPja5jjb4siAa6EHc4qN9c/iFKS3PQPJEnX7pXKBRs5f7AF3
-W3RIGt+G9IVNZfXaS7Z/iCpgzgvKCs0VeqN38QsJGtC1aIkwOeyjPNy2G6jJ4yqH
-ovXYt/0mc00vCWeSNS1wren0pR2EiLxX0ypjjgsU1mk/Z3b/+zVf7fZSIB+nDLjb
-NPtUlJCVGnAeBK1J1nG3TQicqowOXoM6ISkdaXj5GPJdXHab2+S7cqhKGv5qC7rR
-jT6sx7RUr0CNTxzLI7muV2/a4tGmj0PSdXQdsZ7tw7gbXlaWT1+MM2MCAQI=
------END DH PARAMETERS-----
-
diff --git a/crypto/dh/dh512.pem b/crypto/dh/dh512.pem
deleted file mode 100644
index 0a4d863ebe27..000000000000
--- a/crypto/dh/dh512.pem
+++ /dev/null
@@ -1,4 +0,0 @@
------BEGIN DH PARAMETERS-----
-MEYCQQDaWDwW2YUiidDkr3VvTMqS3UvlM7gE+w/tlO+cikQD7VdGUNNpmdsp13Yn
-a6LT1BLiGPTdHghM9tgAPnxHdOgzAgEC
------END DH PARAMETERS-----
diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c
index 576409ccb51b..8430872a9ab6 100644
--- a/crypto/dh/dh_ameth.c
+++ b/crypto/dh/dh_ameth.c
@@ -1,21 +1,30 @@
/*
- * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
-#include "internal/cryptlib.h"
#include <openssl/x509.h>
#include <openssl/asn1.h>
-#include "dh_local.h"
#include <openssl/bn.h>
+#include <openssl/core_names.h>
+#include <openssl/param_build.h>
+#include "internal/ffc.h"
+#include "internal/cryptlib.h"
#include "crypto/asn1.h"
+#include "crypto/dh.h"
#include "crypto/evp.h"
-#include <openssl/cms.h>
+#include "dh_local.h"
/*
* i2d/d2i like DH parameter functions which use the appropriate routine for
@@ -25,14 +34,20 @@
static DH *d2i_dhp(const EVP_PKEY *pkey, const unsigned char **pp,
long length)
{
- if (pkey->ameth == &dhx_asn1_meth)
- return d2i_DHxparams(NULL, pp, length);
- return d2i_DHparams(NULL, pp, length);
+ DH *dh = NULL;
+ int is_dhx = (pkey->ameth == &ossl_dhx_asn1_meth);
+
+ if (is_dhx)
+ dh = d2i_DHxparams(NULL, pp, length);
+ else
+ dh = d2i_DHparams(NULL, pp, length);
+
+ return dh;
}
static int i2d_dhp(const EVP_PKEY *pkey, const DH *a, unsigned char **pp)
{
- if (pkey->ameth == &dhx_asn1_meth)
+ if (pkey->ameth == &ossl_dhx_asn1_meth)
return i2d_DHxparams(a, pp);
return i2d_DHparams(a, pp);
}
@@ -42,7 +57,7 @@ static void int_dh_free(EVP_PKEY *pkey)
DH_free(pkey->pkey.dh);
}
-static int dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
+static int dh_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
{
const unsigned char *p, *pm;
int pklen, pmlen;
@@ -59,7 +74,7 @@ static int dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
X509_ALGOR_get0(NULL, &ptype, &pval, palg);
if (ptype != V_ASN1_SEQUENCE) {
- DHerr(DH_F_DH_PUB_DECODE, DH_R_PARAMETER_ENCODING_ERROR);
+ ERR_raise(ERR_LIB_DH, DH_R_PARAMETER_ENCODING_ERROR);
goto err;
}
@@ -68,18 +83,18 @@ static int dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
pmlen = pstr->length;
if ((dh = d2i_dhp(pkey, &pm, pmlen)) == NULL) {
- DHerr(DH_F_DH_PUB_DECODE, DH_R_DECODE_ERROR);
+ ERR_raise(ERR_LIB_DH, DH_R_DECODE_ERROR);
goto err;
}
if ((public_key = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL) {
- DHerr(DH_F_DH_PUB_DECODE, DH_R_DECODE_ERROR);
+ ERR_raise(ERR_LIB_DH, DH_R_DECODE_ERROR);
goto err;
}
/* We have parameters now set public key */
if ((dh->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)) == NULL) {
- DHerr(DH_F_DH_PUB_DECODE, DH_R_BN_DECODE_ERROR);
+ ERR_raise(ERR_LIB_DH, DH_R_BN_DECODE_ERROR);
goto err;
}
@@ -91,7 +106,6 @@ static int dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
ASN1_INTEGER_free(public_key);
DH_free(dh);
return 0;
-
}
static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
@@ -107,18 +121,18 @@ static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
str = ASN1_STRING_new();
if (str == NULL) {
- DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
goto err;
}
str->length = i2d_dhp(pkey, dh, &str->data);
if (str->length <= 0) {
- DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
goto err;
}
ptype = V_ASN1_SEQUENCE;
pub_key = BN_to_ASN1_INTEGER(dh->pub_key, NULL);
- if (!pub_key)
+ if (pub_key == NULL)
goto err;
penclen = i2d_ASN1_INTEGER(pub_key, &penc);
@@ -126,7 +140,7 @@ static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
ASN1_INTEGER_free(pub_key);
if (penclen <= 0) {
- DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -149,54 +163,15 @@ static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
static int dh_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
{
- const unsigned char *p, *pm;
- int pklen, pmlen;
- int ptype;
- const void *pval;
- const ASN1_STRING *pstr;
- const X509_ALGOR *palg;
- ASN1_INTEGER *privkey = NULL;
-
- DH *dh = NULL;
-
- if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
- return 0;
-
- X509_ALGOR_get0(NULL, &ptype, &pval, palg);
-
- if (ptype != V_ASN1_SEQUENCE)
- goto decerr;
- if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL)
- goto decerr;
+ int ret = 0;
+ DH *dh = ossl_dh_key_from_pkcs8(p8, NULL, NULL);
- pstr = pval;
- pm = pstr->data;
- pmlen = pstr->length;
- if ((dh = d2i_dhp(pkey, &pm, pmlen)) == NULL)
- goto decerr;
-
- /* We have parameters now set private key */
- if ((dh->priv_key = BN_secure_new()) == NULL
- || !ASN1_INTEGER_to_BN(privkey, dh->priv_key)) {
- DHerr(DH_F_DH_PRIV_DECODE, DH_R_BN_ERROR);
- goto dherr;
+ if (dh != NULL) {
+ ret = 1;
+ EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
}
- /* Calculate public key */
- if (!DH_generate_key(dh))
- goto dherr;
-
- EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
-
- ASN1_STRING_clear_free(privkey);
-
- return 1;
- decerr:
- DHerr(DH_F_DH_PRIV_DECODE, EVP_R_DECODE_ERROR);
- dherr:
- DH_free(dh);
- ASN1_STRING_clear_free(privkey);
- return 0;
+ return ret;
}
static int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
@@ -209,13 +184,13 @@ static int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
params = ASN1_STRING_new();
if (params == NULL) {
- DHerr(DH_F_DH_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
goto err;
}
params->length = i2d_dhp(pkey, pkey->pkey.dh, &params->data);
if (params->length <= 0) {
- DHerr(DH_F_DH_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
goto err;
}
params->type = V_ASN1_SEQUENCE;
@@ -223,26 +198,29 @@ static int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
/* Get private key into integer */
prkey = BN_to_ASN1_INTEGER(pkey->pkey.dh->priv_key, NULL);
- if (!prkey) {
- DHerr(DH_F_DH_PRIV_ENCODE, DH_R_BN_ERROR);
+ if (prkey == NULL) {
+ ERR_raise(ERR_LIB_DH, DH_R_BN_ERROR);
goto err;
}
dplen = i2d_ASN1_INTEGER(prkey, &dp);
ASN1_STRING_clear_free(prkey);
- prkey = NULL;
- if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
- V_ASN1_SEQUENCE, params, dp, dplen))
+ if (dplen <= 0) {
+ ERR_raise(ERR_LIB_DH, DH_R_BN_ERROR);
goto err;
+ }
+ if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
+ V_ASN1_SEQUENCE, params, dp, dplen)) {
+ OPENSSL_clear_free(dp, dplen);
+ goto err;
+ }
return 1;
err:
- OPENSSL_free(dp);
ASN1_STRING_free(params);
- ASN1_STRING_clear_free(prkey);
return 0;
}
@@ -251,10 +229,9 @@ static int dh_param_decode(EVP_PKEY *pkey,
{
DH *dh;
- if ((dh = d2i_dhp(pkey, pder, derlen)) == NULL) {
- DHerr(DH_F_DH_PARAM_DECODE, ERR_R_DH_LIB);
+ if ((dh = d2i_dhp(pkey, pder, derlen)) == NULL)
return 0;
- }
+ dh->dirty_cnt++;
EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
return 1;
}
@@ -280,7 +257,7 @@ static int do_dh_print(BIO *bp, const DH *x, int indent, int ptype)
else
pub_key = NULL;
- if (x->p == NULL || (ptype == 2 && priv_key == NULL)
+ if (x->params.p == NULL || (ptype == 2 && priv_key == NULL)
|| (ptype > 0 && pub_key == NULL)) {
reason = ERR_R_PASSED_NULL_PARAMETER;
goto err;
@@ -293,8 +270,8 @@ static int do_dh_print(BIO *bp, const DH *x, int indent, int ptype)
else
ktype = "DH Parameters";
- BIO_indent(bp, indent, 128);
- if (BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0)
+ if (!BIO_indent(bp, indent, 128)
+ || BIO_printf(bp, "%s: (%d bit)\n", ktype, DH_bits(x)) <= 0)
goto err;
indent += 4;
@@ -303,44 +280,20 @@ static int do_dh_print(BIO *bp, const DH *x, int indent, int ptype)
if (!ASN1_bn_print(bp, "public-key:", pub_key, NULL, indent))
goto err;
- if (!ASN1_bn_print(bp, "prime:", x->p, NULL, indent))
- goto err;
- if (!ASN1_bn_print(bp, "generator:", x->g, NULL, indent))
- goto err;
- if (x->q && !ASN1_bn_print(bp, "subgroup order:", x->q, NULL, indent))
- goto err;
- if (x->j && !ASN1_bn_print(bp, "subgroup factor:", x->j, NULL, indent))
- goto err;
- if (x->seed) {
- int i;
- BIO_indent(bp, indent, 128);
- BIO_puts(bp, "seed:");
- for (i = 0; i < x->seedlen; i++) {
- if ((i % 15) == 0) {
- if (BIO_puts(bp, "\n") <= 0
- || !BIO_indent(bp, indent + 4, 128))
- goto err;
- }
- if (BIO_printf(bp, "%02x%s", x->seed[i],
- ((i + 1) == x->seedlen) ? "" : ":") <= 0)
- goto err;
- }
- if (BIO_write(bp, "\n", 1) <= 0)
- return 0;
- }
- if (x->counter && !ASN1_bn_print(bp, "counter:", x->counter, NULL, indent))
+ if (!ossl_ffc_params_print(bp, &x->params, indent))
goto err;
+
if (x->length != 0) {
- BIO_indent(bp, indent, 128);
- if (BIO_printf(bp, "recommended-private-length: %d bits\n",
- (int)x->length) <= 0)
+ if (!BIO_indent(bp, indent, 128)
+ || BIO_printf(bp, "recommended-private-length: %d bits\n",
+ (int)x->length) <= 0)
goto err;
}
return 1;
err:
- DHerr(DH_F_DO_DH_PRINT, reason);
+ ERR_raise(ERR_LIB_DH, reason);
return 0;
}
@@ -351,7 +304,7 @@ static int int_dh_size(const EVP_PKEY *pkey)
static int dh_bits(const EVP_PKEY *pkey)
{
- return BN_num_bits(pkey->pkey.dh->p);
+ return DH_bits(pkey->pkey.dh);
}
static int dh_security_bits(const EVP_PKEY *pkey)
@@ -361,64 +314,23 @@ static int dh_security_bits(const EVP_PKEY *pkey)
static int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
{
- if (BN_cmp(a->pkey.dh->p, b->pkey.dh->p) ||
- BN_cmp(a->pkey.dh->g, b->pkey.dh->g))
- return 0;
- else if (a->ameth == &dhx_asn1_meth) {
- if (BN_cmp(a->pkey.dh->q, b->pkey.dh->q))
- return 0;
- }
- return 1;
-}
-
-static int int_dh_bn_cpy(BIGNUM **dst, const BIGNUM *src)
-{
- BIGNUM *a;
-
- /*
- * If source is read only just copy the pointer, so
- * we don't have to reallocate it.
- */
- if (src == NULL)
- a = NULL;
- else if (BN_get_flags(src, BN_FLG_STATIC_DATA)
- && !BN_get_flags(src, BN_FLG_MALLOCED))
- a = (BIGNUM *)src;
- else if ((a = BN_dup(src)) == NULL)
- return 0;
- BN_clear_free(*dst);
- *dst = a;
- return 1;
+ return ossl_ffc_params_cmp(&a->pkey.dh->params, &b->pkey.dh->params,
+ a->ameth != &ossl_dhx_asn1_meth);
}
static int int_dh_param_copy(DH *to, const DH *from, int is_x942)
{
if (is_x942 == -1)
- is_x942 = ! !from->q;
- if (!int_dh_bn_cpy(&to->p, from->p))
+ is_x942 = (from->params.q != NULL);
+ if (!ossl_ffc_params_copy(&to->params, &from->params))
return 0;
- if (!int_dh_bn_cpy(&to->g, from->g))
- return 0;
- if (is_x942) {
- if (!int_dh_bn_cpy(&to->q, from->q))
- return 0;
- if (!int_dh_bn_cpy(&to->j, from->j))
- return 0;
- OPENSSL_free(to->seed);
- to->seed = NULL;
- to->seedlen = 0;
- if (from->seed) {
- to->seed = OPENSSL_memdup(from->seed, from->seedlen);
- if (!to->seed)
- return 0;
- to->seedlen = from->seedlen;
- }
- } else
+ if (!is_x942)
to->length = from->length;
+ to->dirty_cnt++;
return 1;
}
-DH *DHparams_dup(DH *dh)
+DH *DHparams_dup(const DH *dh)
{
DH *ret;
ret = DH_new();
@@ -439,14 +351,14 @@ static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
return 0;
}
return int_dh_param_copy(to->pkey.dh, from->pkey.dh,
- from->ameth == &dhx_asn1_meth);
+ from->ameth == &ossl_dhx_asn1_meth);
}
static int dh_missing_parameters(const EVP_PKEY *a)
{
- if (a->pkey.dh == NULL || a->pkey.dh->p == NULL || a->pkey.dh->g == NULL)
- return 1;
- return 0;
+ return a->pkey.dh == NULL
+ || a->pkey.dh->params.p == NULL
+ || a->pkey.dh->params.g == NULL;
}
static int dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
@@ -482,27 +394,31 @@ int DHparams_print(BIO *bp, const DH *x)
return do_dh_print(bp, x, 4, 0);
}
-#ifndef OPENSSL_NO_CMS
-static int dh_cms_decrypt(CMS_RecipientInfo *ri);
-static int dh_cms_encrypt(CMS_RecipientInfo *ri);
-#endif
-
static int dh_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
{
+ DH *dh;
switch (op) {
-#ifndef OPENSSL_NO_CMS
-
- case ASN1_PKEY_CTRL_CMS_ENVELOPE:
- if (arg1 == 1)
- return dh_cms_decrypt(arg2);
- else if (arg1 == 0)
- return dh_cms_encrypt(arg2);
+ case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
+ /* We should only be here if we have a legacy key */
+ if (!ossl_assert(evp_pkey_is_legacy(pkey)))
+ return 0;
+ dh = (DH *) evp_pkey_get0_DH_int(pkey);
+ if (dh == NULL)
+ return 0;
+ return ossl_dh_buf2key(dh, arg2, arg1);
+ case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
+ dh = (DH *) EVP_PKEY_get0_DH(pkey);
+ if (dh == NULL)
+ return 0;
+ return ossl_dh_key2buf(dh, arg2, 0, 1);
+ default:
return -2;
+ }
+}
- case ASN1_PKEY_CTRL_CMS_RI_TYPE:
- *(int *)arg2 = CMS_RECIPINFO_AGREE;
- return 1;
-#endif
+static int dhx_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
+{
+ switch (op) {
default:
return -2;
}
@@ -514,7 +430,7 @@ static int dh_pkey_public_check(const EVP_PKEY *pkey)
DH *dh = pkey->pkey.dh;
if (dh->pub_key == NULL) {
- DHerr(DH_F_DH_PKEY_PUBLIC_CHECK, DH_R_MISSING_PUBKEY);
+ ERR_raise(ERR_LIB_DH, DH_R_MISSING_PUBKEY);
return 0;
}
@@ -528,7 +444,120 @@ static int dh_pkey_param_check(const EVP_PKEY *pkey)
return DH_check_ex(dh);
}
-const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
+static size_t dh_pkey_dirty_cnt(const EVP_PKEY *pkey)
+{
+ return pkey->pkey.dh->dirty_cnt;
+}
+
+static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
+ OSSL_FUNC_keymgmt_import_fn *importer,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ DH *dh = from->pkey.dh;
+ OSSL_PARAM_BLD *tmpl;
+ const BIGNUM *p = DH_get0_p(dh), *g = DH_get0_g(dh), *q = DH_get0_q(dh);
+ long l = DH_get_length(dh);
+ const BIGNUM *pub_key = DH_get0_pub_key(dh);
+ const BIGNUM *priv_key = DH_get0_priv_key(dh);
+ OSSL_PARAM *params = NULL;
+ int selection = 0;
+ int rv = 0;
+
+ if (p == NULL || g == NULL)
+ return 0;
+
+ tmpl = OSSL_PARAM_BLD_new();
+ if (tmpl == NULL)
+ return 0;
+ if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, p)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, g))
+ goto err;
+ if (q != NULL) {
+ if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, q))
+ goto err;
+ }
+ selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
+ if (l > 0) {
+ if (!OSSL_PARAM_BLD_push_long(tmpl, OSSL_PKEY_PARAM_DH_PRIV_LEN, l))
+ goto err;
+ selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS;
+ }
+ if (pub_key != NULL) {
+ if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
+ goto err;
+ selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+ }
+ if (priv_key != NULL) {
+ if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
+ priv_key))
+ goto err;
+ selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
+ }
+
+ if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
+ goto err;
+
+ /* We export, the provider imports */
+ rv = importer(to_keydata, selection, params);
+
+ OSSL_PARAM_free(params);
+err:
+ OSSL_PARAM_BLD_free(tmpl);
+ return rv;
+}
+
+static int dh_pkey_import_from_type(const OSSL_PARAM params[], void *vpctx,
+ int type)
+{
+ EVP_PKEY_CTX *pctx = vpctx;
+ EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
+ DH *dh = ossl_dh_new_ex(pctx->libctx);
+
+ if (dh == NULL) {
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
+ DH_set_flags(dh, type == EVP_PKEY_DH ? DH_FLAG_TYPE_DH : DH_FLAG_TYPE_DHX);
+
+ if (!ossl_dh_params_fromdata(dh, params)
+ || !ossl_dh_key_fromdata(dh, params, 1)
+ || !EVP_PKEY_assign(pkey, type, dh)) {
+ DH_free(dh);
+ return 0;
+ }
+ return 1;
+}
+
+static int dh_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
+{
+ return dh_pkey_import_from_type(params, vpctx, EVP_PKEY_DH);
+}
+
+static int dhx_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
+{
+ return dh_pkey_import_from_type(params, vpctx, EVP_PKEY_DHX);
+}
+
+static int dh_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
+{
+ DH *dh = from->pkey.dh;
+ DH *dupkey = NULL;
+ int ret;
+
+ if (dh != NULL) {
+ dupkey = ossl_dh_dup(dh, OSSL_KEYMGMT_SELECT_ALL);
+ if (dupkey == NULL)
+ return 0;
+ }
+
+ ret = EVP_PKEY_assign(to, from->type, dupkey);
+ if (!ret)
+ DH_free(dupkey);
+ return ret;
+}
+
+const EVP_PKEY_ASN1_METHOD ossl_dh_asn1_meth = {
EVP_PKEY_DH,
EVP_PKEY_DH,
0,
@@ -558,16 +587,23 @@ const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
0,
int_dh_free,
- 0,
+ dh_pkey_ctrl,
0, 0, 0, 0, 0,
0,
dh_pkey_public_check,
- dh_pkey_param_check
+ dh_pkey_param_check,
+
+ 0, 0, 0, 0,
+
+ dh_pkey_dirty_cnt,
+ dh_pkey_export_to,
+ dh_pkey_import_from,
+ dh_pkey_copy
};
-const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = {
+const EVP_PKEY_ASN1_METHOD ossl_dhx_asn1_meth = {
EVP_PKEY_DHX,
EVP_PKEY_DHX,
0,
@@ -597,315 +633,16 @@ const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = {
0,
int_dh_free,
- dh_pkey_ctrl,
+ dhx_pkey_ctrl,
0, 0, 0, 0, 0,
0,
dh_pkey_public_check,
- dh_pkey_param_check
+ dh_pkey_param_check,
+ 0, 0, 0, 0,
+ dh_pkey_dirty_cnt,
+ dh_pkey_export_to,
+ dhx_pkey_import_from,
+ dh_pkey_copy
};
-
-#ifndef OPENSSL_NO_CMS
-
-static int dh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
- X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
-{
- const ASN1_OBJECT *aoid;
- int atype;
- const void *aval;
- ASN1_INTEGER *public_key = NULL;
- int rv = 0;
- EVP_PKEY *pkpeer = NULL, *pk = NULL;
- DH *dhpeer = NULL;
- const unsigned char *p;
- int plen;
-
- X509_ALGOR_get0(&aoid, &atype, &aval, alg);
- if (OBJ_obj2nid(aoid) != NID_dhpublicnumber)
- goto err;
- /* Only absent parameters allowed in RFC XXXX */
- if (atype != V_ASN1_UNDEF && atype == V_ASN1_NULL)
- goto err;
-
- pk = EVP_PKEY_CTX_get0_pkey(pctx);
- if (pk == NULL || pk->type != EVP_PKEY_DHX)
- goto err;
-
- /* Get parameters from parent key */
- dhpeer = DHparams_dup(pk->pkey.dh);
- if (dhpeer == NULL)
- goto err;
-
- /* We have parameters now set public key */
- plen = ASN1_STRING_length(pubkey);
- p = ASN1_STRING_get0_data(pubkey);
- if (p == NULL || plen == 0)
- goto err;
-
- if ((public_key = d2i_ASN1_INTEGER(NULL, &p, plen)) == NULL) {
- DHerr(DH_F_DH_CMS_SET_PEERKEY, DH_R_DECODE_ERROR);
- goto err;
- }
-
- /* We have parameters now set public key */
- if ((dhpeer->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)) == NULL) {
- DHerr(DH_F_DH_CMS_SET_PEERKEY, DH_R_BN_DECODE_ERROR);
- goto err;
- }
-
- pkpeer = EVP_PKEY_new();
- if (pkpeer == NULL)
- goto err;
-
- EVP_PKEY_assign(pkpeer, pk->ameth->pkey_id, dhpeer);
- dhpeer = NULL;
- if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
- rv = 1;
- err:
- ASN1_INTEGER_free(public_key);
- EVP_PKEY_free(pkpeer);
- DH_free(dhpeer);
- return rv;
-}
-
-static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
-{
- int rv = 0;
-
- X509_ALGOR *alg, *kekalg = NULL;
- ASN1_OCTET_STRING *ukm;
- const unsigned char *p;
- unsigned char *dukm = NULL;
- size_t dukmlen = 0;
- int keylen, plen;
- const EVP_CIPHER *kekcipher;
- EVP_CIPHER_CTX *kekctx;
-
- if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
- goto err;
-
- /*
- * For DH we only have one OID permissible. If ever any more get defined
- * we will need something cleverer.
- */
- if (OBJ_obj2nid(alg->algorithm) != NID_id_smime_alg_ESDH) {
- DHerr(DH_F_DH_CMS_SET_SHARED_INFO, DH_R_KDF_PARAMETER_ERROR);
- goto err;
- }
-
- if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, EVP_PKEY_DH_KDF_X9_42) <= 0)
- goto err;
-
- if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, EVP_sha1()) <= 0)
- goto err;
-
- if (alg->parameter->type != V_ASN1_SEQUENCE)
- goto err;
-
- p = alg->parameter->value.sequence->data;
- plen = alg->parameter->value.sequence->length;
- kekalg = d2i_X509_ALGOR(NULL, &p, plen);
- if (!kekalg)
- goto err;
- kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
- if (!kekctx)
- goto err;
- kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
- if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
- goto err;
- if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
- goto err;
- if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
- goto err;
-
- keylen = EVP_CIPHER_CTX_key_length(kekctx);
- if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
- goto err;
- /* Use OBJ_nid2obj to ensure we use built in OID that isn't freed */
- if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx,
- OBJ_nid2obj(EVP_CIPHER_type(kekcipher)))
- <= 0)
- goto err;
-
- if (ukm) {
- dukmlen = ASN1_STRING_length(ukm);
- dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), dukmlen);
- if (!dukm)
- goto err;
- }
-
- if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
- goto err;
- dukm = NULL;
-
- rv = 1;
- err:
- X509_ALGOR_free(kekalg);
- OPENSSL_free(dukm);
- return rv;
-}
-
-static int dh_cms_decrypt(CMS_RecipientInfo *ri)
-{
- EVP_PKEY_CTX *pctx;
- pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
- if (!pctx)
- return 0;
- /* See if we need to set peer key */
- if (!EVP_PKEY_CTX_get0_peerkey(pctx)) {
- X509_ALGOR *alg;
- ASN1_BIT_STRING *pubkey;
- if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
- NULL, NULL, NULL))
- return 0;
- if (!alg || !pubkey)
- return 0;
- if (!dh_cms_set_peerkey(pctx, alg, pubkey)) {
- DHerr(DH_F_DH_CMS_DECRYPT, DH_R_PEER_KEY_ERROR);
- return 0;
- }
- }
- /* Set DH derivation parameters and initialise unwrap context */
- if (!dh_cms_set_shared_info(pctx, ri)) {
- DHerr(DH_F_DH_CMS_DECRYPT, DH_R_SHARED_INFO_ERROR);
- return 0;
- }
- return 1;
-}
-
-static int dh_cms_encrypt(CMS_RecipientInfo *ri)
-{
- EVP_PKEY_CTX *pctx;
- EVP_PKEY *pkey;
- EVP_CIPHER_CTX *ctx;
- int keylen;
- X509_ALGOR *talg, *wrap_alg = NULL;
- const ASN1_OBJECT *aoid;
- ASN1_BIT_STRING *pubkey;
- ASN1_STRING *wrap_str;
- ASN1_OCTET_STRING *ukm;
- unsigned char *penc = NULL, *dukm = NULL;
- int penclen;
- size_t dukmlen = 0;
- int rv = 0;
- int kdf_type, wrap_nid;
- const EVP_MD *kdf_md;
- pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
- if (!pctx)
- return 0;
- /* Get ephemeral key */
- pkey = EVP_PKEY_CTX_get0_pkey(pctx);
- if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
- NULL, NULL, NULL))
- goto err;
- X509_ALGOR_get0(&aoid, NULL, NULL, talg);
- /* Is everything uninitialised? */
- if (aoid == OBJ_nid2obj(NID_undef)) {
- ASN1_INTEGER *pubk = BN_to_ASN1_INTEGER(pkey->pkey.dh->pub_key, NULL);
- if (!pubk)
- goto err;
- /* Set the key */
-
- penclen = i2d_ASN1_INTEGER(pubk, &penc);
- ASN1_INTEGER_free(pubk);
- if (penclen <= 0)
- goto err;
- ASN1_STRING_set0(pubkey, penc, penclen);
- pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
- pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
-
- penc = NULL;
- X509_ALGOR_set0(talg, OBJ_nid2obj(NID_dhpublicnumber),
- V_ASN1_UNDEF, NULL);
- }
-
- /* See if custom parameters set */
- kdf_type = EVP_PKEY_CTX_get_dh_kdf_type(pctx);
- if (kdf_type <= 0)
- goto err;
- if (!EVP_PKEY_CTX_get_dh_kdf_md(pctx, &kdf_md))
- goto err;
-
- if (kdf_type == EVP_PKEY_DH_KDF_NONE) {
- kdf_type = EVP_PKEY_DH_KDF_X9_42;
- if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, kdf_type) <= 0)
- goto err;
- } else if (kdf_type != EVP_PKEY_DH_KDF_X9_42)
- /* Unknown KDF */
- goto err;
- if (kdf_md == NULL) {
- /* Only SHA1 supported */
- kdf_md = EVP_sha1();
- if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, kdf_md) <= 0)
- goto err;
- } else if (EVP_MD_type(kdf_md) != NID_sha1)
- /* Unsupported digest */
- goto err;
-
- if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
- goto err;
-
- /* Get wrap NID */
- ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
- wrap_nid = EVP_CIPHER_CTX_type(ctx);
- if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx, OBJ_nid2obj(wrap_nid)) <= 0)
- goto err;
- keylen = EVP_CIPHER_CTX_key_length(ctx);
-
- /* Package wrap algorithm in an AlgorithmIdentifier */
-
- wrap_alg = X509_ALGOR_new();
- if (wrap_alg == NULL)
- goto err;
- wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
- wrap_alg->parameter = ASN1_TYPE_new();
- if (wrap_alg->parameter == NULL)
- goto err;
- if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
- goto err;
- if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
- ASN1_TYPE_free(wrap_alg->parameter);
- wrap_alg->parameter = NULL;
- }
-
- if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
- goto err;
-
- if (ukm) {
- dukmlen = ASN1_STRING_length(ukm);
- dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), dukmlen);
- if (!dukm)
- goto err;
- }
-
- if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
- goto err;
- dukm = NULL;
-
- /*
- * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
- * of another AlgorithmIdentifier.
- */
- penc = NULL;
- penclen = i2d_X509_ALGOR(wrap_alg, &penc);
- if (!penc || !penclen)
- goto err;
- wrap_str = ASN1_STRING_new();
- if (wrap_str == NULL)
- goto err;
- ASN1_STRING_set0(wrap_str, penc, penclen);
- penc = NULL;
- X509_ALGOR_set0(talg, OBJ_nid2obj(NID_id_smime_alg_ESDH),
- V_ASN1_SEQUENCE, wrap_str);
-
- rv = 1;
-
- err:
- OPENSSL_free(penc);
- X509_ALGOR_free(wrap_alg);
- OPENSSL_free(dukm);
- return rv;
-}
-
-#endif
diff --git a/crypto/dh/dh_asn1.c b/crypto/dh/dh_asn1.c
index e37f0904e560..5fa91a8ec7dc 100644
--- a/crypto/dh/dh_asn1.c
+++ b/crypto/dh/dh_asn1.c
@@ -1,18 +1,25 @@
/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include "dh_local.h"
#include <openssl/objects.h>
#include <openssl/asn1t.h>
+#include "crypto/dh.h"
/* Override the default free and new methods */
static int dh_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
@@ -27,17 +34,24 @@ static int dh_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
DH_free((DH *)*pval);
*pval = NULL;
return 2;
+ } else if (operation == ASN1_OP_D2I_POST) {
+ DH *dh = (DH *)*pval;
+
+ DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
+ DH_set_flags(dh, DH_FLAG_TYPE_DH);
+ ossl_dh_cache_named_group(dh);
+ dh->dirty_cnt++;
}
return 1;
}
ASN1_SEQUENCE_cb(DHparams, dh_cb) = {
- ASN1_SIMPLE(DH, p, BIGNUM),
- ASN1_SIMPLE(DH, g, BIGNUM),
+ ASN1_SIMPLE(DH, params.p, BIGNUM),
+ ASN1_SIMPLE(DH, params.g, BIGNUM),
ASN1_OPT_EMBED(DH, length, ZINT32),
} ASN1_SEQUENCE_END_cb(DH, DHparams)
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DH, DHparams, DHparams)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(DH, DHparams, DHparams)
/*
* Internal only structures for handling X9.42 DH: this gets translated to or
@@ -74,14 +88,14 @@ int_dhx942_dh *d2i_int_dhx(int_dhx942_dh **a,
const unsigned char **pp, long length);
int i2d_int_dhx(const int_dhx942_dh *a, unsigned char **pp);
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(int_dhx942_dh, DHxparams, int_dhx)
-
-/* Application public function: read in X9.42 DH parameters into DH structure */
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(int_dhx942_dh, DHxparams, int_dhx)
DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length)
{
+ FFC_PARAMS *params;
int_dhx942_dh *dhx = NULL;
DH *dh = NULL;
+
dh = DH_new();
if (dh == NULL)
return NULL;
@@ -91,48 +105,63 @@ DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length)
return NULL;
}
- if (a) {
+ if (a != NULL) {
DH_free(*a);
*a = dh;
}
- dh->p = dhx->p;
- dh->q = dhx->q;
- dh->g = dhx->g;
- dh->j = dhx->j;
+ params = &dh->params;
+ DH_set0_pqg(dh, dhx->p, dhx->q, dhx->g);
+ ossl_ffc_params_set0_j(params, dhx->j);
- if (dhx->vparams) {
- dh->seed = dhx->vparams->seed->data;
- dh->seedlen = dhx->vparams->seed->length;
- dh->counter = dhx->vparams->counter;
- dhx->vparams->seed->data = NULL;
+ if (dhx->vparams != NULL) {
+ /* The counter has a maximum value of 4 * numbits(p) - 1 */
+ size_t counter = (size_t)BN_get_word(dhx->vparams->counter);
+ ossl_ffc_params_set_validate_params(params, dhx->vparams->seed->data,
+ dhx->vparams->seed->length,
+ counter);
ASN1_BIT_STRING_free(dhx->vparams->seed);
+ BN_free(dhx->vparams->counter);
OPENSSL_free(dhx->vparams);
dhx->vparams = NULL;
}
OPENSSL_free(dhx);
+ DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
+ DH_set_flags(dh, DH_FLAG_TYPE_DHX);
return dh;
}
int i2d_DHxparams(const DH *dh, unsigned char **pp)
{
+ int ret = 0;
int_dhx942_dh dhx;
- int_dhvparams dhv;
- ASN1_BIT_STRING bs;
- dhx.p = dh->p;
- dhx.g = dh->g;
- dhx.q = dh->q;
- dhx.j = dh->j;
- if (dh->counter && dh->seed && dh->seedlen > 0) {
- bs.flags = ASN1_STRING_FLAG_BITS_LEFT;
- bs.data = dh->seed;
- bs.length = dh->seedlen;
- dhv.seed = &bs;
- dhv.counter = dh->counter;
+ int_dhvparams dhv = { NULL, NULL };
+ ASN1_BIT_STRING seed;
+ size_t seedlen = 0;
+ const FFC_PARAMS *params = &dh->params;
+ int counter;
+
+ ossl_ffc_params_get0_pqg(params, (const BIGNUM **)&dhx.p,
+ (const BIGNUM **)&dhx.q, (const BIGNUM **)&dhx.g);
+ dhx.j = params->j;
+ ossl_ffc_params_get_validate_params(params, &seed.data, &seedlen, &counter);
+ seed.length = (int)seedlen;
+
+ if (counter != -1 && seed.data != NULL && seed.length > 0) {
+ seed.flags = ASN1_STRING_FLAG_BITS_LEFT;
+ dhv.seed = &seed;
+ dhv.counter = BN_new();
+ if (dhv.counter == NULL)
+ return 0;
+ if (!BN_set_word(dhv.counter, (BN_ULONG)counter))
+ goto err;
dhx.vparams = &dhv;
- } else
+ } else {
dhx.vparams = NULL;
-
- return i2d_int_dhx(&dhx, pp);
+ }
+ ret = i2d_int_dhx(&dhx, pp);
+err:
+ BN_free(dhv.counter);
+ return ret;
}
diff --git a/crypto/dh/dh_backend.c b/crypto/dh/dh_backend.c
new file mode 100644
index 000000000000..726843fd30cd
--- /dev/null
+++ b/crypto/dh/dh_backend.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/err.h>
+#include <openssl/core_names.h>
+#ifndef FIPS_MODULE
+# include <openssl/x509.h>
+#endif
+#include "internal/param_build_set.h"
+#include "crypto/dh.h"
+#include "dh_local.h"
+
+/*
+ * The intention with the "backend" source file is to offer backend functions
+ * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
+ * implementations alike.
+ */
+
+static int dh_ffc_params_fromdata(DH *dh, const OSSL_PARAM params[])
+{
+ int ret;
+ FFC_PARAMS *ffc;
+
+ if (dh == NULL)
+ return 0;
+ ffc = ossl_dh_get0_params(dh);
+ if (ffc == NULL)
+ return 0;
+
+ ret = ossl_ffc_params_fromdata(ffc, params);
+ if (ret)
+ ossl_dh_cache_named_group(dh); /* This increments dh->dirty_cnt */
+ return ret;
+}
+
+int ossl_dh_params_fromdata(DH *dh, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *param_priv_len;
+ long priv_len;
+
+ if (!dh_ffc_params_fromdata(dh, params))
+ return 0;
+
+ param_priv_len =
+ OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_LEN);
+ if (param_priv_len != NULL
+ && (!OSSL_PARAM_get_long(param_priv_len, &priv_len)
+ || !DH_set_length(dh, priv_len)))
+ return 0;
+
+ return 1;
+}
+
+int ossl_dh_key_fromdata(DH *dh, const OSSL_PARAM params[], int include_private)
+{
+ const OSSL_PARAM *param_priv_key, *param_pub_key;
+ BIGNUM *priv_key = NULL, *pub_key = NULL;
+
+ if (dh == NULL)
+ return 0;
+
+ param_priv_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
+ param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
+
+ if (include_private
+ && param_priv_key != NULL
+ && !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
+ goto err;
+
+ if (param_pub_key != NULL
+ && !OSSL_PARAM_get_BN(param_pub_key, &pub_key))
+ goto err;
+
+ if (!DH_set0_key(dh, pub_key, priv_key))
+ goto err;
+
+ return 1;
+
+ err:
+ BN_clear_free(priv_key);
+ BN_free(pub_key);
+ return 0;
+}
+
+int ossl_dh_params_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[])
+{
+ long l = DH_get_length(dh);
+
+ if (!ossl_ffc_params_todata(ossl_dh_get0_params(dh), bld, params))
+ return 0;
+ if (l > 0
+ && !ossl_param_build_set_long(bld, params, OSSL_PKEY_PARAM_DH_PRIV_LEN, l))
+ return 0;
+ return 1;
+}
+
+int ossl_dh_key_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[],
+ int include_private)
+{
+ const BIGNUM *priv = NULL, *pub = NULL;
+
+ if (dh == NULL)
+ return 0;
+
+ DH_get0_key(dh, &pub, &priv);
+ if (priv != NULL
+ && include_private
+ && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PRIV_KEY, priv))
+ return 0;
+ if (pub != NULL
+ && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PUB_KEY, pub))
+ return 0;
+
+ return 1;
+}
+
+int ossl_dh_is_foreign(const DH *dh)
+{
+#ifndef FIPS_MODULE
+ if (dh->engine != NULL || ossl_dh_get_method(dh) != DH_OpenSSL())
+ return 1;
+#endif
+ return 0;
+}
+
+static ossl_inline int dh_bn_dup_check(BIGNUM **out, const BIGNUM *f)
+{
+ if (f != NULL && (*out = BN_dup(f)) == NULL)
+ return 0;
+ return 1;
+}
+
+DH *ossl_dh_dup(const DH *dh, int selection)
+{
+ DH *dupkey = NULL;
+
+ /* Do not try to duplicate foreign DH keys */
+ if (ossl_dh_is_foreign(dh))
+ return NULL;
+
+ if ((dupkey = ossl_dh_new_ex(dh->libctx)) == NULL)
+ return NULL;
+
+ dupkey->length = DH_get_length(dh);
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0
+ && !ossl_ffc_params_copy(&dupkey->params, &dh->params))
+ goto err;
+
+ dupkey->flags = dh->flags;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0
+ && ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0
+ || !dh_bn_dup_check(&dupkey->pub_key, dh->pub_key)))
+ goto err;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
+ && ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0
+ || !dh_bn_dup_check(&dupkey->priv_key, dh->priv_key)))
+ goto err;
+
+#ifndef FIPS_MODULE
+ if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_DH,
+ &dupkey->ex_data, &dh->ex_data))
+ goto err;
+#endif
+
+ return dupkey;
+
+ err:
+ DH_free(dupkey);
+ return NULL;
+}
+
+#ifndef FIPS_MODULE
+DH *ossl_dh_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ const unsigned char *p, *pm;
+ int pklen, pmlen;
+ int ptype;
+ const void *pval;
+ const ASN1_STRING *pstr;
+ const X509_ALGOR *palg;
+ BIGNUM *privkey_bn = NULL;
+ ASN1_INTEGER *privkey = NULL;
+ DH *dh = NULL;
+
+ if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8inf))
+ return 0;
+
+ X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+
+ if (ptype != V_ASN1_SEQUENCE)
+ goto decerr;
+ if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL)
+ goto decerr;
+
+ pstr = pval;
+ pm = pstr->data;
+ pmlen = pstr->length;
+ switch (OBJ_obj2nid(palg->algorithm)) {
+ case NID_dhKeyAgreement:
+ dh = d2i_DHparams(NULL, &pm, pmlen);
+ break;
+ case NID_dhpublicnumber:
+ dh = d2i_DHxparams(NULL, &pm, pmlen);
+ break;
+ default:
+ goto decerr;
+ }
+ if (dh == NULL)
+ goto decerr;
+
+ /* We have parameters now set private key */
+ if ((privkey_bn = BN_secure_new()) == NULL
+ || !ASN1_INTEGER_to_BN(privkey, privkey_bn)) {
+ ERR_raise(ERR_LIB_DH, DH_R_BN_ERROR);
+ BN_clear_free(privkey_bn);
+ goto dherr;
+ }
+ if (!DH_set0_key(dh, NULL, privkey_bn))
+ goto dherr;
+ /* Calculate public key, increments dirty_cnt */
+ if (!DH_generate_key(dh))
+ goto dherr;
+
+ goto done;
+
+ decerr:
+ ERR_raise(ERR_LIB_DH, EVP_R_DECODE_ERROR);
+ dherr:
+ DH_free(dh);
+ dh = NULL;
+ done:
+ ASN1_STRING_clear_free(privkey);
+ return dh;
+}
+#endif
diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c
index 4ac169e75c23..0b391910d6b3 100644
--- a/crypto/dh/dh_check.c
+++ b/crypto/dh/dh_check.c
@@ -1,18 +1,23 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include "dh_local.h"
-
-# define DH_NUMBER_ITERATIONS_FOR_PRIME 64
+#include "crypto/dh.h"
/*-
* Check that p and g are suitable enough
@@ -28,13 +33,39 @@ int DH_check_params_ex(const DH *dh)
return 0;
if ((errflags & DH_CHECK_P_NOT_PRIME) != 0)
- DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_CHECK_P_NOT_PRIME);
+ ERR_raise(ERR_LIB_DH, DH_R_CHECK_P_NOT_PRIME);
if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0)
- DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_NOT_SUITABLE_GENERATOR);
+ ERR_raise(ERR_LIB_DH, DH_R_NOT_SUITABLE_GENERATOR);
+ if ((errflags & DH_MODULUS_TOO_SMALL) != 0)
+ ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_SMALL);
+ if ((errflags & DH_MODULUS_TOO_LARGE) != 0)
+ ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE);
return errflags == 0;
}
+#ifdef FIPS_MODULE
+int DH_check_params(const DH *dh, int *ret)
+{
+ int nid;
+
+ *ret = 0;
+ /*
+ * SP800-56A R3 Section 5.5.2 Assurances of Domain Parameter Validity
+ * (1a) The domain parameters correspond to any approved safe prime group.
+ */
+ nid = DH_get_nid((DH *)dh);
+ if (nid != NID_undef)
+ return 1;
+ /*
+ * OR
+ * (2b) FFC domain params conform to FIPS-186-4 explicit domain param
+ * validity tests.
+ */
+ return ossl_ffc_params_FIPS186_4_validate(dh->libctx, &dh->params,
+ FFC_PARAM_TYPE_DH, ret, NULL);
+}
+#else
int DH_check_params(const DH *dh, int *ret)
{
int ok = 0;
@@ -42,7 +73,7 @@ int DH_check_params(const DH *dh, int *ret)
BN_CTX *ctx = NULL;
*ret = 0;
- ctx = BN_CTX_new();
+ ctx = BN_CTX_new_ex(dh->libctx);
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
@@ -50,14 +81,20 @@ int DH_check_params(const DH *dh, int *ret)
if (tmp == NULL)
goto err;
- if (!BN_is_odd(dh->p))
+ if (!BN_is_odd(dh->params.p))
*ret |= DH_CHECK_P_NOT_PRIME;
- if (BN_is_negative(dh->g) || BN_is_zero(dh->g) || BN_is_one(dh->g))
+ if (BN_is_negative(dh->params.g)
+ || BN_is_zero(dh->params.g)
+ || BN_is_one(dh->params.g))
*ret |= DH_NOT_SUITABLE_GENERATOR;
- if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1))
+ if (BN_copy(tmp, dh->params.p) == NULL || !BN_sub_word(tmp, 1))
goto err;
- if (BN_cmp(dh->g, tmp) >= 0)
+ if (BN_cmp(dh->params.g, tmp) >= 0)
*ret |= DH_NOT_SUITABLE_GENERATOR;
+ if (BN_num_bits(dh->params.p) < DH_MIN_MODULUS_BITS)
+ *ret |= DH_MODULUS_TOO_SMALL;
+ if (BN_num_bits(dh->params.p) > OPENSSL_DH_MAX_MODULUS_BITS)
+ *ret |= DH_MODULUS_TOO_LARGE;
ok = 1;
err:
@@ -65,6 +102,7 @@ int DH_check_params(const DH *dh, int *ret)
BN_CTX_free(ctx);
return ok;
}
+#endif /* FIPS_MODULE */
/*-
* Check that p is a safe prime and
@@ -78,33 +116,46 @@ int DH_check_ex(const DH *dh)
return 0;
if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0)
- DHerr(DH_F_DH_CHECK_EX, DH_R_NOT_SUITABLE_GENERATOR);
+ ERR_raise(ERR_LIB_DH, DH_R_NOT_SUITABLE_GENERATOR);
if ((errflags & DH_CHECK_Q_NOT_PRIME) != 0)
- DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_Q_NOT_PRIME);
+ ERR_raise(ERR_LIB_DH, DH_R_CHECK_Q_NOT_PRIME);
if ((errflags & DH_CHECK_INVALID_Q_VALUE) != 0)
- DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_Q_VALUE);
+ ERR_raise(ERR_LIB_DH, DH_R_CHECK_INVALID_Q_VALUE);
if ((errflags & DH_CHECK_INVALID_J_VALUE) != 0)
- DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_J_VALUE);
+ ERR_raise(ERR_LIB_DH, DH_R_CHECK_INVALID_J_VALUE);
if ((errflags & DH_UNABLE_TO_CHECK_GENERATOR) != 0)
- DHerr(DH_F_DH_CHECK_EX, DH_R_UNABLE_TO_CHECK_GENERATOR);
+ ERR_raise(ERR_LIB_DH, DH_R_UNABLE_TO_CHECK_GENERATOR);
if ((errflags & DH_CHECK_P_NOT_PRIME) != 0)
- DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_PRIME);
+ ERR_raise(ERR_LIB_DH, DH_R_CHECK_P_NOT_PRIME);
if ((errflags & DH_CHECK_P_NOT_SAFE_PRIME) != 0)
- DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_SAFE_PRIME);
+ ERR_raise(ERR_LIB_DH, DH_R_CHECK_P_NOT_SAFE_PRIME);
+ if ((errflags & DH_MODULUS_TOO_SMALL) != 0)
+ ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_SMALL);
+ if ((errflags & DH_MODULUS_TOO_LARGE) != 0)
+ ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE);
return errflags == 0;
}
+/* Note: according to documentation - this only checks the params */
int DH_check(const DH *dh, int *ret)
{
+#ifdef FIPS_MODULE
+ return DH_check_params(dh, ret);
+#else
int ok = 0, r;
BN_CTX *ctx = NULL;
BIGNUM *t1 = NULL, *t2 = NULL;
+ int nid = DH_get_nid((DH *)dh);
+
+ *ret = 0;
+ if (nid != NID_undef)
+ return 1;
if (!DH_check_params(dh, ret))
return 0;
- ctx = BN_CTX_new();
+ ctx = BN_CTX_new_ex(dh->libctx);
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
@@ -113,41 +164,42 @@ int DH_check(const DH *dh, int *ret)
if (t2 == NULL)
goto err;
- if (dh->q) {
- if (BN_cmp(dh->g, BN_value_one()) <= 0)
+ if (dh->params.q != NULL) {
+ if (BN_cmp(dh->params.g, BN_value_one()) <= 0)
*ret |= DH_NOT_SUITABLE_GENERATOR;
- else if (BN_cmp(dh->g, dh->p) >= 0)
+ else if (BN_cmp(dh->params.g, dh->params.p) >= 0)
*ret |= DH_NOT_SUITABLE_GENERATOR;
else {
/* Check g^q == 1 mod p */
- if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx))
+ if (!BN_mod_exp(t1, dh->params.g, dh->params.q, dh->params.p, ctx))
goto err;
if (!BN_is_one(t1))
*ret |= DH_NOT_SUITABLE_GENERATOR;
}
- r = BN_is_prime_ex(dh->q, DH_NUMBER_ITERATIONS_FOR_PRIME, ctx, NULL);
+ r = BN_check_prime(dh->params.q, ctx, NULL);
if (r < 0)
goto err;
if (!r)
*ret |= DH_CHECK_Q_NOT_PRIME;
/* Check p == 1 mod q i.e. q divides p - 1 */
- if (!BN_div(t1, t2, dh->p, dh->q, ctx))
+ if (!BN_div(t1, t2, dh->params.p, dh->params.q, ctx))
goto err;
if (!BN_is_one(t2))
*ret |= DH_CHECK_INVALID_Q_VALUE;
- if (dh->j && BN_cmp(dh->j, t1))
+ if (dh->params.j != NULL
+ && BN_cmp(dh->params.j, t1))
*ret |= DH_CHECK_INVALID_J_VALUE;
}
- r = BN_is_prime_ex(dh->p, DH_NUMBER_ITERATIONS_FOR_PRIME, ctx, NULL);
+ r = BN_check_prime(dh->params.p, ctx, NULL);
if (r < 0)
goto err;
if (!r)
*ret |= DH_CHECK_P_NOT_PRIME;
- else if (!dh->q) {
- if (!BN_rshift1(t1, dh->p))
+ else if (dh->params.q == NULL) {
+ if (!BN_rshift1(t1, dh->params.p))
goto err;
- r = BN_is_prime_ex(t1, DH_NUMBER_ITERATIONS_FOR_PRIME, ctx, NULL);
+ r = BN_check_prime(t1, ctx, NULL);
if (r < 0)
goto err;
if (!r)
@@ -158,6 +210,7 @@ int DH_check(const DH *dh, int *ret)
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ok;
+#endif /* FIPS_MODULE */
}
int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key)
@@ -168,47 +221,113 @@ int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key)
return 0;
if ((errflags & DH_CHECK_PUBKEY_TOO_SMALL) != 0)
- DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_SMALL);
+ ERR_raise(ERR_LIB_DH, DH_R_CHECK_PUBKEY_TOO_SMALL);
if ((errflags & DH_CHECK_PUBKEY_TOO_LARGE) != 0)
- DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_LARGE);
+ ERR_raise(ERR_LIB_DH, DH_R_CHECK_PUBKEY_TOO_LARGE);
if ((errflags & DH_CHECK_PUBKEY_INVALID) != 0)
- DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_INVALID);
+ ERR_raise(ERR_LIB_DH, DH_R_CHECK_PUBKEY_INVALID);
return errflags == 0;
}
+/*
+ * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Full public key validation.
+ */
int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
{
+ return ossl_ffc_validate_public_key(&dh->params, pub_key, ret);
+}
+
+/*
+ * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Partial public key validation.
+ * To only be used with ephemeral FFC public keys generated using the approved
+ * safe-prime groups.
+ */
+int ossl_dh_check_pub_key_partial(const DH *dh, const BIGNUM *pub_key, int *ret)
+{
+ return ossl_ffc_validate_public_key_partial(&dh->params, pub_key, ret);
+}
+
+int ossl_dh_check_priv_key(const DH *dh, const BIGNUM *priv_key, int *ret)
+{
int ok = 0;
- BIGNUM *tmp = NULL;
- BN_CTX *ctx = NULL;
+ BIGNUM *two_powN = NULL, *upper;
*ret = 0;
- ctx = BN_CTX_new();
- if (ctx == NULL)
- goto err;
- BN_CTX_start(ctx);
- tmp = BN_CTX_get(ctx);
- if (tmp == NULL || !BN_set_word(tmp, 1))
- goto err;
- if (BN_cmp(pub_key, tmp) <= 0)
- *ret |= DH_CHECK_PUBKEY_TOO_SMALL;
- if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1))
- goto err;
- if (BN_cmp(pub_key, tmp) >= 0)
- *ret |= DH_CHECK_PUBKEY_TOO_LARGE;
+ two_powN = BN_new();
+ if (two_powN == NULL)
+ return 0;
- if (dh->q != NULL) {
- /* Check pub_key^q == 1 mod p */
- if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx))
- goto err;
- if (!BN_is_one(tmp))
- *ret |= DH_CHECK_PUBKEY_INVALID;
+ if (dh->params.q != NULL) {
+ upper = dh->params.q;
+#ifndef FIPS_MODULE
+ } else if (dh->params.p != NULL) {
+ /*
+ * We do not have q so we just check the key is within some
+ * reasonable range, or the number of bits is equal to dh->length.
+ */
+ int length = dh->length;
+
+ if (length == 0) {
+ length = BN_num_bits(dh->params.p) - 1;
+ if (BN_num_bits(priv_key) <= length
+ && BN_num_bits(priv_key) > 1)
+ ok = 1;
+ } else if (BN_num_bits(priv_key) == length) {
+ ok = 1;
+ }
+ goto end;
+#endif
+ } else {
+ goto end;
}
+ /* Is it from an approved Safe prime group ?*/
+ if (DH_get_nid((DH *)dh) != NID_undef && dh->length != 0) {
+ if (!BN_lshift(two_powN, BN_value_one(), dh->length))
+ goto end;
+ if (BN_cmp(two_powN, dh->params.q) < 0)
+ upper = two_powN;
+ }
+ if (!ossl_ffc_validate_private_key(upper, priv_key, ret))
+ goto end;
+
ok = 1;
- err:
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
+end:
+ BN_free(two_powN);
return ok;
}
+
+/*
+ * FFC pairwise check from SP800-56A R3.
+ * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency
+ */
+int ossl_dh_check_pairwise(const DH *dh)
+{
+ int ret = 0;
+ BN_CTX *ctx = NULL;
+ BIGNUM *pub_key = NULL;
+
+ if (dh->params.p == NULL
+ || dh->params.g == NULL
+ || dh->priv_key == NULL
+ || dh->pub_key == NULL)
+ return 0;
+
+ ctx = BN_CTX_new_ex(dh->libctx);
+ if (ctx == NULL)
+ goto err;
+ pub_key = BN_new();
+ if (pub_key == NULL)
+ goto err;
+
+ /* recalculate the public key = (g ^ priv) mod p */
+ if (!ossl_dh_generate_public_key(ctx, dh, dh->priv_key, pub_key))
+ goto err;
+ /* check it matches the existing pubic_key */
+ ret = BN_cmp(pub_key, dh->pub_key) == 0;
+err:
+ BN_free(pub_key);
+ BN_CTX_free(ctx);
+ return ret;
+}
diff --git a/crypto/dh/dh_depr.c b/crypto/dh/dh_depr.c
index f8ed1b7461ee..5822d511d958 100644
--- a/crypto/dh/dh_depr.c
+++ b/crypto/dh/dh_depr.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,15 +9,18 @@
/* This file contains deprecated functions as wrappers to the new ones */
+/*
+ * DH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/opensslconf.h>
-#if OPENSSL_API_COMPAT >= 0x00908000L
-NON_EMPTY_TRANSLATION_UNIT
-#else
-# include <stdio.h>
-# include "internal/cryptlib.h"
-# include <openssl/bn.h>
-# include <openssl/dh.h>
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/bn.h>
+#include <openssl/dh.h>
DH *DH_generate_parameters(int prime_len, int generator,
void (*callback) (int, int, void *), void *cb_arg)
@@ -43,4 +46,3 @@ DH *DH_generate_parameters(int prime_len, int generator,
DH_free(ret);
return NULL;
}
-#endif
diff --git a/crypto/dh/dh_err.c b/crypto/dh/dh_err.c
index 7285587b4ade..4152397426cc 100644
--- a/crypto/dh/dh_err.c
+++ b/crypto/dh/dh_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,43 +10,14 @@
#include <openssl/err.h>
#include <openssl/dherr.h>
+#include "crypto/dherr.h"
-#ifndef OPENSSL_NO_ERR
+#ifndef OPENSSL_NO_DH
-static const ERR_STRING_DATA DH_str_functs[] = {
- {ERR_PACK(ERR_LIB_DH, DH_F_COMPUTE_KEY, 0), "compute_key"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DHPARAMS_PRINT_FP, 0), "DHparams_print_fp"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_BUILTIN_GENPARAMS, 0),
- "dh_builtin_genparams"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK_EX, 0), "DH_check_ex"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK_PARAMS_EX, 0), "DH_check_params_ex"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK_PUB_KEY_EX, 0), "DH_check_pub_key_ex"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_CMS_DECRYPT, 0), "dh_cms_decrypt"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_CMS_SET_PEERKEY, 0), "dh_cms_set_peerkey"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_CMS_SET_SHARED_INFO, 0),
- "dh_cms_set_shared_info"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_METH_DUP, 0), "DH_meth_dup"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_METH_NEW, 0), "DH_meth_new"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_METH_SET1_NAME, 0), "DH_meth_set1_name"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_NEW_BY_NID, 0), "DH_new_by_nid"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_NEW_METHOD, 0), "DH_new_method"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_PARAM_DECODE, 0), "dh_param_decode"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_PKEY_PUBLIC_CHECK, 0),
- "dh_pkey_public_check"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_PRIV_DECODE, 0), "dh_priv_decode"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_PRIV_ENCODE, 0), "dh_priv_encode"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_PUB_DECODE, 0), "dh_pub_decode"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_PUB_ENCODE, 0), "dh_pub_encode"},
- {ERR_PACK(ERR_LIB_DH, DH_F_DO_DH_PRINT, 0), "do_dh_print"},
- {ERR_PACK(ERR_LIB_DH, DH_F_GENERATE_KEY, 0), "generate_key"},
- {ERR_PACK(ERR_LIB_DH, DH_F_PKEY_DH_CTRL_STR, 0), "pkey_dh_ctrl_str"},
- {ERR_PACK(ERR_LIB_DH, DH_F_PKEY_DH_DERIVE, 0), "pkey_dh_derive"},
- {ERR_PACK(ERR_LIB_DH, DH_F_PKEY_DH_INIT, 0), "pkey_dh_init"},
- {ERR_PACK(ERR_LIB_DH, DH_F_PKEY_DH_KEYGEN, 0), "pkey_dh_keygen"},
- {0, NULL}
-};
+# ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA DH_str_reasons[] = {
+ {ERR_PACK(ERR_LIB_DH, 0, DH_R_BAD_FFC_PARAMETERS), "bad ffc parameters"},
{ERR_PACK(ERR_LIB_DH, 0, DH_R_BAD_GENERATOR), "bad generator"},
{ERR_PACK(ERR_LIB_DH, 0, DH_R_BN_DECODE_ERROR), "bn decode error"},
{ERR_PACK(ERR_LIB_DH, 0, DH_R_BN_ERROR), "bn error"},
@@ -70,10 +41,12 @@ static const ERR_STRING_DATA DH_str_reasons[] = {
{ERR_PACK(ERR_LIB_DH, 0, DH_R_INVALID_PARAMETER_NID),
"invalid parameter nid"},
{ERR_PACK(ERR_LIB_DH, 0, DH_R_INVALID_PUBKEY), "invalid public key"},
+ {ERR_PACK(ERR_LIB_DH, 0, DH_R_INVALID_SECRET), "invalid secret"},
{ERR_PACK(ERR_LIB_DH, 0, DH_R_KDF_PARAMETER_ERROR), "kdf parameter error"},
{ERR_PACK(ERR_LIB_DH, 0, DH_R_KEYS_NOT_SET), "keys not set"},
{ERR_PACK(ERR_LIB_DH, 0, DH_R_MISSING_PUBKEY), "missing pubkey"},
{ERR_PACK(ERR_LIB_DH, 0, DH_R_MODULUS_TOO_LARGE), "modulus too large"},
+ {ERR_PACK(ERR_LIB_DH, 0, DH_R_MODULUS_TOO_SMALL), "modulus too small"},
{ERR_PACK(ERR_LIB_DH, 0, DH_R_NOT_SUITABLE_GENERATOR),
"not suitable generator"},
{ERR_PACK(ERR_LIB_DH, 0, DH_R_NO_PARAMETERS_SET), "no parameters set"},
@@ -87,15 +60,16 @@ static const ERR_STRING_DATA DH_str_reasons[] = {
{0, NULL}
};
-#endif
+# endif
-int ERR_load_DH_strings(void)
+int ossl_err_load_DH_strings(void)
{
-#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(DH_str_functs[0].error) == NULL) {
- ERR_load_strings_const(DH_str_functs);
+# ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(DH_str_reasons[0].error) == NULL)
ERR_load_strings_const(DH_str_reasons);
- }
-#endif
+# endif
return 1;
}
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/crypto/dh/dh_gen.c b/crypto/dh/dh_gen.c
index ab82ab58bd2a..aec6b853169a 100644
--- a/crypto/dh/dh_gen.c
+++ b/crypto/dh/dh_gen.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,22 +12,120 @@
* dh_depr.c as wrappers to these ones. - Geoff
*/
+/*
+ * DH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ *
+ * NOTE: When generating keys for key-agreement schemes - FIPS 140-2 IG 9.9
+ * states that no additional pairwise tests are required (apart from the tests
+ * specified in SP800-56A) when generating keys. Hence DH pairwise tests are
+ * omitted here.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
+#include <openssl/sha.h>
+#include "crypto/dh.h"
#include "dh_local.h"
+#ifndef FIPS_MODULE
static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
BN_GENCB *cb);
+#endif /* FIPS_MODULE */
+
+int ossl_dh_generate_ffc_parameters(DH *dh, int type, int pbits, int qbits,
+ BN_GENCB *cb)
+{
+ int ret, res;
+
+#ifndef FIPS_MODULE
+ if (type == DH_PARAMGEN_TYPE_FIPS_186_2)
+ ret = ossl_ffc_params_FIPS186_2_generate(dh->libctx, &dh->params,
+ FFC_PARAM_TYPE_DH,
+ pbits, qbits, &res, cb);
+ else
+#endif
+ ret = ossl_ffc_params_FIPS186_4_generate(dh->libctx, &dh->params,
+ FFC_PARAM_TYPE_DH,
+ pbits, qbits, &res, cb);
+ if (ret > 0)
+ dh->dirty_cnt++;
+ return ret;
+}
+
+int ossl_dh_get_named_group_uid_from_size(int pbits)
+{
+ /*
+ * Just choose an approved safe prime group.
+ * The alternative to this is to generate FIPS186-4 domain parameters i.e.
+ * return dh_generate_ffc_parameters(ret, prime_len, 0, NULL, cb);
+ * As the FIPS186-4 generated params are for backwards compatibility,
+ * the safe prime group should be used as the default.
+ */
+ int nid;
+
+ switch (pbits) {
+ case 2048:
+ nid = NID_ffdhe2048;
+ break;
+ case 3072:
+ nid = NID_ffdhe3072;
+ break;
+ case 4096:
+ nid = NID_ffdhe4096;
+ break;
+ case 6144:
+ nid = NID_ffdhe6144;
+ break;
+ case 8192:
+ nid = NID_ffdhe8192;
+ break;
+ /* unsupported prime_len */
+ default:
+ return NID_undef;
+ }
+ return nid;
+}
+
+#ifdef FIPS_MODULE
+
+static int dh_gen_named_group(OSSL_LIB_CTX *libctx, DH *ret, int prime_len)
+{
+ DH *dh;
+ int ok = 0;
+ int nid = ossl_dh_get_named_group_uid_from_size(prime_len);
+
+ if (nid == NID_undef)
+ return 0;
+
+ dh = ossl_dh_new_by_nid_ex(libctx, nid);
+ if (dh != NULL
+ && ossl_ffc_params_copy(&ret->params, &dh->params)) {
+ ok = 1;
+ ret->dirty_cnt++;
+ }
+ DH_free(dh);
+ return ok;
+}
+#endif /* FIPS_MODULE */
int DH_generate_parameters_ex(DH *ret, int prime_len, int generator,
BN_GENCB *cb)
{
+#ifdef FIPS_MODULE
+ if (generator != 2)
+ return 0;
+ return dh_gen_named_group(ret->libctx, ret, prime_len);
+#else
if (ret->meth->generate_params)
return ret->meth->generate_params(ret, prime_len, generator, cb);
return dh_builtin_genparams(ret, prime_len, generator, cb);
+#endif /* FIPS_MODULE */
}
+#ifndef FIPS_MODULE
/*-
* We generate DH parameters as follows
* find a prime p which is prime_len bits long,
@@ -53,10 +151,6 @@ int DH_generate_parameters_ex(DH *ret, int prime_len, int generator,
* for 2, p mod 24 == 23
* for 3, p mod 12 == 11
* for 5, p mod 60 == 59
- *
- * However for compatibility with previous versions we use:
- * for 2, p mod 24 == 11
- * for 5, p mod 60 == 23
*/
static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
BN_GENCB *cb)
@@ -65,7 +159,17 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
int g, ok = -1;
BN_CTX *ctx = NULL;
- ctx = BN_CTX_new();
+ if (prime_len > OPENSSL_DH_MAX_MODULUS_BITS) {
+ ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE);
+ return 0;
+ }
+
+ if (prime_len < DH_MIN_MODULUS_BITS) {
+ ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_SMALL);
+ return 0;
+ }
+
+ ctx = BN_CTX_new_ex(ret->libctx);
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
@@ -75,25 +179,25 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
goto err;
/* Make sure 'ret' has the necessary elements */
- if (!ret->p && ((ret->p = BN_new()) == NULL))
+ if (ret->params.p == NULL && ((ret->params.p = BN_new()) == NULL))
goto err;
- if (!ret->g && ((ret->g = BN_new()) == NULL))
+ if (ret->params.g == NULL && ((ret->params.g = BN_new()) == NULL))
goto err;
if (generator <= 1) {
- DHerr(DH_F_DH_BUILTIN_GENPARAMS, DH_R_BAD_GENERATOR);
+ ERR_raise(ERR_LIB_DH, DH_R_BAD_GENERATOR);
goto err;
}
if (generator == DH_GENERATOR_2) {
if (!BN_set_word(t1, 24))
goto err;
- if (!BN_set_word(t2, 11))
+ if (!BN_set_word(t2, 23))
goto err;
g = 2;
} else if (generator == DH_GENERATOR_5) {
if (!BN_set_word(t1, 60))
goto err;
- if (!BN_set_word(t2, 23))
+ if (!BN_set_word(t2, 59))
goto err;
g = 5;
} else {
@@ -109,16 +213,17 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
g = generator;
}
- if (!BN_generate_prime_ex(ret->p, prime_len, 1, t1, t2, cb))
+ if (!BN_generate_prime_ex2(ret->params.p, prime_len, 1, t1, t2, cb, ctx))
goto err;
if (!BN_GENCB_call(cb, 3, 0))
goto err;
- if (!BN_set_word(ret->g, g))
+ if (!BN_set_word(ret->params.g, g))
goto err;
+ ret->dirty_cnt++;
ok = 1;
err:
if (ok == -1) {
- DHerr(DH_F_DH_BUILTIN_GENPARAMS, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_DH, ERR_R_BN_LIB);
ok = 0;
}
@@ -126,3 +231,4 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
BN_CTX_free(ctx);
return ok;
}
+#endif /* FIPS_MODULE */
diff --git a/crypto/dh/dh_group_params.c b/crypto/dh/dh_group_params.c
new file mode 100644
index 000000000000..460bd8f00989
--- /dev/null
+++ b/crypto/dh/dh_group_params.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* DH parameters from RFC7919 and RFC3526 */
+
+/*
+ * DH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include "internal/ffc.h"
+#include "dh_local.h"
+#include <openssl/bn.h>
+#include <openssl/objects.h>
+#include "internal/nelem.h"
+#include "crypto/dh.h"
+
+static DH *dh_param_init(OSSL_LIB_CTX *libctx, const DH_NAMED_GROUP *group)
+{
+ DH *dh = ossl_dh_new_ex(libctx);
+
+ if (dh == NULL)
+ return NULL;
+
+ ossl_ffc_named_group_set(&dh->params, group);
+ dh->params.nid = ossl_ffc_named_group_get_uid(group);
+ dh->dirty_cnt++;
+ return dh;
+}
+
+DH *ossl_dh_new_by_nid_ex(OSSL_LIB_CTX *libctx, int nid)
+{
+ const DH_NAMED_GROUP *group;
+
+ if ((group = ossl_ffc_uid_to_dh_named_group(nid)) != NULL)
+ return dh_param_init(libctx, group);
+
+ ERR_raise(ERR_LIB_DH, DH_R_INVALID_PARAMETER_NID);
+ return NULL;
+}
+
+DH *DH_new_by_nid(int nid)
+{
+ return ossl_dh_new_by_nid_ex(NULL, nid);
+}
+
+void ossl_dh_cache_named_group(DH *dh)
+{
+ const DH_NAMED_GROUP *group;
+
+ if (dh == NULL)
+ return;
+
+ dh->params.nid = NID_undef; /* flush cached value */
+
+ /* Exit if p or g is not set */
+ if (dh->params.p == NULL
+ || dh->params.g == NULL)
+ return;
+
+ if ((group = ossl_ffc_numbers_to_dh_named_group(dh->params.p,
+ dh->params.q,
+ dh->params.g)) != NULL) {
+ if (dh->params.q == NULL)
+ dh->params.q = (BIGNUM *)ossl_ffc_named_group_get_q(group);
+ /* cache the nid and default key length */
+ dh->params.nid = ossl_ffc_named_group_get_uid(group);
+ dh->params.keylength = ossl_ffc_named_group_get_keylength(group);
+ dh->dirty_cnt++;
+ }
+}
+
+int ossl_dh_is_named_safe_prime_group(const DH *dh)
+{
+ int id = DH_get_nid(dh);
+
+ /*
+ * Exclude RFC5114 groups (id = 1..3) since they do not have
+ * q = (p - 1) / 2
+ */
+ return (id > 3);
+}
+
+int DH_get_nid(const DH *dh)
+{
+ if (dh == NULL)
+ return NID_undef;
+
+ return dh->params.nid;
+}
diff --git a/crypto/dh/dh_kdf.c b/crypto/dh/dh_kdf.c
index e17122bc82e3..6e99466e60b3 100644
--- a/crypto/dh/dh_kdf.c
+++ b/crypto/dh/dh_kdf.c
@@ -1,150 +1,81 @@
/*
- * Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2013-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include "e_os.h"
+/*
+ * DH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
-#ifndef OPENSSL_NO_CMS
+#include "e_os.h"
+#include "e_os.h"
#include <string.h>
+#include <openssl/core_names.h>
#include <openssl/dh.h>
#include <openssl/evp.h>
#include <openssl/asn1.h>
-#include <openssl/cms.h>
-
-
-/* Key derivation from X9.42/RFC2631 */
-/* Uses CMS functions, hence the #ifdef wrapper. */
+#include <openssl/kdf.h>
+#include "internal/provider.h"
+#include "crypto/dh.h"
-#define DH_KDF_MAX (1L << 30)
-
-/* Skip past an ASN1 structure: for OBJECT skip content octets too */
-
-static int skip_asn1(unsigned char **pp, long *plen, int exptag)
+/* Key derivation function from X9.63/SECG */
+int ossl_dh_kdf_X9_42_asn1(unsigned char *out, size_t outlen,
+ const unsigned char *Z, size_t Zlen,
+ const char *cek_alg,
+ const unsigned char *ukm, size_t ukmlen,
+ const EVP_MD *md,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
- const unsigned char *q = *pp;
- int i, tag, xclass;
- long tmplen;
- i = ASN1_get_object(&q, &tmplen, &tag, &xclass, *plen);
- if (i & 0x80)
- return 0;
- if (tag != exptag || xclass != V_ASN1_UNIVERSAL)
- return 0;
- if (tag == V_ASN1_OBJECT)
- q += tmplen;
- *plen -= q - *pp;
- *pp = (unsigned char *)q;
- return 1;
-}
-
-/*
- * Encode the DH shared info structure, return an offset to the counter value
- * so we can update the structure without reencoding it.
- */
+ int ret = 0;
+ EVP_KDF_CTX *kctx = NULL;
+ EVP_KDF *kdf = NULL;
+ OSSL_PARAM params[5], *p = params;
+ const char *mdname = EVP_MD_get0_name(md);
-static int dh_sharedinfo_encode(unsigned char **pder, unsigned char **pctr,
- ASN1_OBJECT *key_oid, size_t outlen,
- const unsigned char *ukm, size_t ukmlen)
-{
- unsigned char *p;
- int derlen;
- long tlen;
- /* "magic" value to check offset is sane */
- static unsigned char ctr[4] = { 0xF3, 0x17, 0x22, 0x53 };
- X509_ALGOR atmp;
- ASN1_OCTET_STRING ctr_oct, ukm_oct, *pukm_oct;
- ASN1_TYPE ctr_atype;
- if (ukmlen > DH_KDF_MAX || outlen > DH_KDF_MAX)
- return 0;
- ctr_oct.data = ctr;
- ctr_oct.length = 4;
- ctr_oct.flags = 0;
- ctr_oct.type = V_ASN1_OCTET_STRING;
- ctr_atype.type = V_ASN1_OCTET_STRING;
- ctr_atype.value.octet_string = &ctr_oct;
- atmp.algorithm = key_oid;
- atmp.parameter = &ctr_atype;
- if (ukm) {
- ukm_oct.type = V_ASN1_OCTET_STRING;
- ukm_oct.flags = 0;
- ukm_oct.data = (unsigned char *)ukm;
- ukm_oct.length = ukmlen;
- pukm_oct = &ukm_oct;
- } else
- pukm_oct = NULL;
- derlen = CMS_SharedInfo_encode(pder, &atmp, pukm_oct, outlen);
- if (derlen <= 0)
- return 0;
- p = *pder;
- tlen = derlen;
- if (!skip_asn1(&p, &tlen, V_ASN1_SEQUENCE))
- return 0;
- if (!skip_asn1(&p, &tlen, V_ASN1_SEQUENCE))
- return 0;
- if (!skip_asn1(&p, &tlen, V_ASN1_OBJECT))
- return 0;
- if (!skip_asn1(&p, &tlen, V_ASN1_OCTET_STRING))
+ kdf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_X942KDF_ASN1, propq);
+ if (kdf == NULL)
return 0;
- if (CRYPTO_memcmp(p, ctr, 4))
- return 0;
- *pctr = p;
- return derlen;
+ kctx = EVP_KDF_CTX_new(kdf);
+ if (kctx == NULL)
+ goto err;
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ (char *)mdname, 0);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ (unsigned char *)Z, Zlen);
+ if (ukm != NULL)
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_UKM,
+ (unsigned char *)ukm, ukmlen);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CEK_ALG,
+ (char *)cek_alg, 0);
+ *p = OSSL_PARAM_construct_end();
+ ret = EVP_KDF_derive(kctx, out, outlen, params) > 0;
+err:
+ EVP_KDF_CTX_free(kctx);
+ EVP_KDF_free(kdf);
+ return ret;
}
+#if !defined(FIPS_MODULE)
int DH_KDF_X9_42(unsigned char *out, size_t outlen,
const unsigned char *Z, size_t Zlen,
ASN1_OBJECT *key_oid,
const unsigned char *ukm, size_t ukmlen, const EVP_MD *md)
{
- EVP_MD_CTX *mctx = NULL;
- int rv = 0;
- unsigned int i;
- size_t mdlen;
- unsigned char *der = NULL, *ctr;
- int derlen;
- if (Zlen > DH_KDF_MAX)
- return 0;
- mctx = EVP_MD_CTX_new();
- if (mctx == NULL)
+ char key_alg[OSSL_MAX_NAME_SIZE];
+ const OSSL_PROVIDER *prov = EVP_MD_get0_provider(md);
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
+
+ if (OBJ_obj2txt(key_alg, sizeof(key_alg), key_oid, 0) <= 0)
return 0;
- mdlen = EVP_MD_size(md);
- derlen = dh_sharedinfo_encode(&der, &ctr, key_oid, outlen, ukm, ukmlen);
- if (derlen == 0)
- goto err;
- for (i = 1;; i++) {
- unsigned char mtmp[EVP_MAX_MD_SIZE];
- if (!EVP_DigestInit_ex(mctx, md, NULL)
- || !EVP_DigestUpdate(mctx, Z, Zlen))
- goto err;
- ctr[3] = i & 0xFF;
- ctr[2] = (i >> 8) & 0xFF;
- ctr[1] = (i >> 16) & 0xFF;
- ctr[0] = (i >> 24) & 0xFF;
- if (!EVP_DigestUpdate(mctx, der, derlen))
- goto err;
- if (outlen >= mdlen) {
- if (!EVP_DigestFinal(mctx, out, NULL))
- goto err;
- outlen -= mdlen;
- if (outlen == 0)
- break;
- out += mdlen;
- } else {
- if (!EVP_DigestFinal(mctx, mtmp, NULL))
- goto err;
- memcpy(out, mtmp, outlen);
- OPENSSL_cleanse(mtmp, mdlen);
- break;
- }
- }
- rv = 1;
- err:
- OPENSSL_free(der);
- EVP_MD_CTX_free(mctx);
- return rv;
+
+ return ossl_dh_kdf_X9_42_asn1(out, outlen, Z, Zlen, key_alg,
+ ukm, ukmlen, md, libctx, NULL);
}
-#endif
+#endif /* !defined(FIPS_MODULE) */
diff --git a/crypto/dh/dh_key.c b/crypto/dh/dh_key.c
index 117f2fa883ff..4e9705beef73 100644
--- a/crypto/dh/dh_key.c
+++ b/crypto/dh/dh_key.c
@@ -1,28 +1,104 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include "dh_local.h"
#include "crypto/bn.h"
+#include "crypto/dh.h"
+#include "crypto/security_bits.h"
+
+#ifdef FIPS_MODULE
+# define MIN_STRENGTH 112
+#else
+# define MIN_STRENGTH 80
+#endif
static int generate_key(DH *dh);
-static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh);
static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
static int dh_init(DH *dh);
static int dh_finish(DH *dh);
-int DH_generate_key(DH *dh)
+/*
+ * See SP800-56Ar3 Section 5.7.1.1
+ * Finite Field Cryptography Diffie-Hellman (FFC DH) Primitive
+ */
+int ossl_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
{
- return dh->meth->generate_key(dh);
+ BN_CTX *ctx = NULL;
+ BN_MONT_CTX *mont = NULL;
+ BIGNUM *z = NULL, *pminus1;
+ int ret = -1;
+
+ if (BN_num_bits(dh->params.p) > OPENSSL_DH_MAX_MODULUS_BITS) {
+ ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE);
+ goto err;
+ }
+
+ if (BN_num_bits(dh->params.p) < DH_MIN_MODULUS_BITS) {
+ ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_SMALL);
+ return 0;
+ }
+
+ ctx = BN_CTX_new_ex(dh->libctx);
+ if (ctx == NULL)
+ goto err;
+ BN_CTX_start(ctx);
+ pminus1 = BN_CTX_get(ctx);
+ z = BN_CTX_get(ctx);
+ if (z == NULL)
+ goto err;
+
+ if (dh->priv_key == NULL) {
+ ERR_raise(ERR_LIB_DH, DH_R_NO_PRIVATE_VALUE);
+ goto err;
+ }
+
+ if (dh->flags & DH_FLAG_CACHE_MONT_P) {
+ mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
+ dh->lock, dh->params.p, ctx);
+ BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME);
+ if (!mont)
+ goto err;
+ }
+
+ /* (Step 1) Z = pub_key^priv_key mod p */
+ if (!dh->meth->bn_mod_exp(dh, z, pub_key, dh->priv_key, dh->params.p, ctx,
+ mont)) {
+ ERR_raise(ERR_LIB_DH, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ /* (Step 2) Error if z <= 1 or z = p - 1 */
+ if (BN_copy(pminus1, dh->params.p) == NULL
+ || !BN_sub_word(pminus1, 1)
+ || BN_cmp(z, BN_value_one()) <= 0
+ || BN_cmp(z, pminus1) == 0) {
+ ERR_raise(ERR_LIB_DH, DH_R_INVALID_SECRET);
+ goto err;
+ }
+
+ /* return the padded key, i.e. same number of bytes as the modulus */
+ ret = BN_bn2binpad(z, key, BN_num_bytes(dh->params.p));
+ err:
+ BN_clear(z); /* (Step 2) destroy intermediate values */
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ return ret;
}
/*-
@@ -35,7 +111,12 @@ int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
volatile size_t npad = 0, mask = 1;
/* compute the key; ret is constant unless compute_key is external */
- if ((ret = dh->meth->compute_key(key, pub_key, dh)) <= 0)
+#ifdef FIPS_MODULE
+ ret = ossl_dh_compute_key(key, pub_key, dh);
+#else
+ ret = dh->meth->compute_key(key, pub_key, dh);
+#endif
+ if (ret <= 0)
return ret;
/* count leading zero bytes, yet still touch all bytes */
@@ -59,10 +140,14 @@ int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh)
int rv, pad;
/* rv is constant unless compute_key is external */
+#ifdef FIPS_MODULE
+ rv = ossl_dh_compute_key(key, pub_key, dh);
+#else
rv = dh->meth->compute_key(key, pub_key, dh);
+#endif
if (rv <= 0)
return rv;
- pad = BN_num_bytes(dh->p) - rv;
+ pad = BN_num_bytes(dh->params.p) - rv;
/* pad is constant (zero) unless compute_key is external */
if (pad > 0) {
memmove(key + pad, key, rv);
@@ -74,7 +159,7 @@ int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh)
static DH_METHOD dh_ossl = {
"OpenSSL DH Method",
generate_key,
- compute_key,
+ ossl_dh_compute_key,
dh_bn_mod_exp,
dh_init,
dh_finish,
@@ -90,31 +175,105 @@ const DH_METHOD *DH_OpenSSL(void)
return &dh_ossl;
}
+const DH_METHOD *DH_get_default_method(void)
+{
+ return default_DH_method;
+}
+
+static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
+ const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
+{
+ return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
+}
+
+static int dh_init(DH *dh)
+{
+ dh->flags |= DH_FLAG_CACHE_MONT_P;
+ ossl_ffc_params_init(&dh->params);
+ dh->dirty_cnt++;
+ return 1;
+}
+
+static int dh_finish(DH *dh)
+{
+ BN_MONT_CTX_free(dh->method_mont_p);
+ return 1;
+}
+
+#ifndef FIPS_MODULE
void DH_set_default_method(const DH_METHOD *meth)
{
default_DH_method = meth;
}
+#endif /* FIPS_MODULE */
-const DH_METHOD *DH_get_default_method(void)
+int DH_generate_key(DH *dh)
{
- return default_DH_method;
+#ifdef FIPS_MODULE
+ return generate_key(dh);
+#else
+ return dh->meth->generate_key(dh);
+#endif
+}
+
+int ossl_dh_generate_public_key(BN_CTX *ctx, const DH *dh,
+ const BIGNUM *priv_key, BIGNUM *pub_key)
+{
+ int ret = 0;
+ BIGNUM *prk = BN_new();
+ BN_MONT_CTX *mont = NULL;
+
+ if (prk == NULL)
+ return 0;
+
+ if (dh->flags & DH_FLAG_CACHE_MONT_P) {
+ /*
+ * We take the input DH as const, but we lie, because in some cases we
+ * want to get a hold of its Montgomery context.
+ *
+ * We cast to remove the const qualifier in this case, it should be
+ * fine...
+ */
+ BN_MONT_CTX **pmont = (BN_MONT_CTX **)&dh->method_mont_p;
+
+ mont = BN_MONT_CTX_set_locked(pmont, dh->lock, dh->params.p, ctx);
+ if (mont == NULL)
+ goto err;
+ }
+ BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
+
+ /* pub_key = g^priv_key mod p */
+ if (!dh->meth->bn_mod_exp(dh, pub_key, dh->params.g, prk, dh->params.p,
+ ctx, mont))
+ goto err;
+ ret = 1;
+err:
+ BN_clear_free(prk);
+ return ret;
}
static int generate_key(DH *dh)
{
int ok = 0;
int generate_new_key = 0;
+#ifndef FIPS_MODULE
unsigned l;
+#endif
BN_CTX *ctx = NULL;
- BN_MONT_CTX *mont = NULL;
BIGNUM *pub_key = NULL, *priv_key = NULL;
- if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
- DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_LARGE);
+ if (BN_num_bits(dh->params.p) > OPENSSL_DH_MAX_MODULUS_BITS) {
+ ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE);
return 0;
}
- ctx = BN_CTX_new();
+ if (BN_num_bits(dh->params.p) < DH_MIN_MODULUS_BITS) {
+ ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_SMALL);
+ return 0;
+ }
+
+ ctx = BN_CTX_new_ex(dh->libctx);
if (ctx == NULL)
goto err;
@@ -123,68 +282,85 @@ static int generate_key(DH *dh)
if (priv_key == NULL)
goto err;
generate_new_key = 1;
- } else
+ } else {
priv_key = dh->priv_key;
+ }
if (dh->pub_key == NULL) {
pub_key = BN_new();
if (pub_key == NULL)
goto err;
- } else
+ } else {
pub_key = dh->pub_key;
-
- if (dh->flags & DH_FLAG_CACHE_MONT_P) {
- mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
- dh->lock, dh->p, ctx);
- if (!mont)
- goto err;
}
-
if (generate_new_key) {
- if (dh->q) {
- do {
- if (!BN_priv_rand_range(priv_key, dh->q))
- goto err;
- }
- while (BN_is_zero(priv_key) || BN_is_one(priv_key));
+ /* Is it an approved safe prime ?*/
+ if (DH_get_nid(dh) != NID_undef) {
+ int max_strength =
+ ossl_ifc_ffc_compute_security_bits(BN_num_bits(dh->params.p));
+
+ if (dh->params.q == NULL
+ || dh->length > BN_num_bits(dh->params.q))
+ goto err;
+ /* dh->length = maximum bit length of generated private key */
+ if (!ossl_ffc_generate_private_key(ctx, &dh->params, dh->length,
+ max_strength, priv_key))
+ goto err;
} else {
- /* secret exponent length */
- l = dh->length ? dh->length : BN_num_bits(dh->p) - 1;
- if (!BN_priv_rand(priv_key, l, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
+#ifdef FIPS_MODULE
+ if (dh->params.q == NULL)
goto err;
- /*
- * We handle just one known case where g is a quadratic non-residue:
- * for g = 2: p % 8 == 3
- */
- if (BN_is_word(dh->g, DH_GENERATOR_2) && !BN_is_bit_set(dh->p, 2)) {
- /* clear bit 0, since it won't be a secret anyway */
- if (!BN_clear_bit(priv_key, 0))
+#else
+ if (dh->params.q == NULL) {
+ /* secret exponent length, must satisfy 2^(l-1) <= p */
+ if (dh->length != 0
+ && dh->length >= BN_num_bits(dh->params.p))
+ goto err;
+ l = dh->length ? dh->length : BN_num_bits(dh->params.p) - 1;
+ if (!BN_priv_rand_ex(priv_key, l, BN_RAND_TOP_ONE,
+ BN_RAND_BOTTOM_ANY, 0, ctx))
+ goto err;
+ /*
+ * We handle just one known case where g is a quadratic non-residue:
+ * for g = 2: p % 8 == 3
+ */
+ if (BN_is_word(dh->params.g, DH_GENERATOR_2)
+ && !BN_is_bit_set(dh->params.p, 2)) {
+ /* clear bit 0, since it won't be a secret anyway */
+ if (!BN_clear_bit(priv_key, 0))
+ goto err;
+ }
+ } else
+#endif
+ {
+ /* Do a partial check for invalid p, q, g */
+ if (!ossl_ffc_params_simple_validate(dh->libctx, &dh->params,
+ FFC_PARAM_TYPE_DH, NULL))
+ goto err;
+ /*
+ * For FFC FIPS 186-4 keygen
+ * security strength s = 112,
+ * Max Private key size N = len(q)
+ */
+ if (!ossl_ffc_generate_private_key(ctx, &dh->params,
+ BN_num_bits(dh->params.q),
+ MIN_STRENGTH,
+ priv_key))
goto err;
}
}
}
- {
- BIGNUM *prk = BN_new();
-
- if (prk == NULL)
- goto err;
- BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
-
- if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont)) {
- BN_clear_free(prk);
- goto err;
- }
- /* We MUST free prk before any further use of priv_key */
- BN_clear_free(prk);
- }
+ if (!ossl_dh_generate_public_key(ctx, dh, priv_key, pub_key))
+ goto err;
dh->pub_key = pub_key;
dh->priv_key = priv_key;
+ dh->dirty_cnt++;
ok = 1;
err:
if (ok != 1)
- DHerr(DH_F_GENERATE_KEY, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_DH, ERR_R_BN_LIB);
if (pub_key != dh->pub_key)
BN_free(pub_key);
@@ -194,73 +370,73 @@ static int generate_key(DH *dh)
return ok;
}
-static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
+int ossl_dh_buf2key(DH *dh, const unsigned char *buf, size_t len)
{
- BN_CTX *ctx = NULL;
- BN_MONT_CTX *mont = NULL;
- BIGNUM *tmp;
- int ret = -1;
- int check_result;
-
- if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
- DHerr(DH_F_COMPUTE_KEY, DH_R_MODULUS_TOO_LARGE);
- goto err;
- }
+ int err_reason = DH_R_BN_ERROR;
+ BIGNUM *pubkey = NULL;
+ const BIGNUM *p;
+ int ret;
- ctx = BN_CTX_new();
- if (ctx == NULL)
- goto err;
- BN_CTX_start(ctx);
- tmp = BN_CTX_get(ctx);
- if (tmp == NULL)
+ if ((pubkey = BN_bin2bn(buf, len, NULL)) == NULL)
goto err;
-
- if (dh->priv_key == NULL) {
- DHerr(DH_F_COMPUTE_KEY, DH_R_NO_PRIVATE_VALUE);
+ DH_get0_pqg(dh, &p, NULL, NULL);
+ if (p == NULL || BN_num_bytes(p) == 0) {
+ err_reason = DH_R_NO_PARAMETERS_SET;
goto err;
}
-
- if (dh->flags & DH_FLAG_CACHE_MONT_P) {
- mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
- dh->lock, dh->p, ctx);
- BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME);
- if (!mont)
- goto err;
- }
-
- if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result) {
- DHerr(DH_F_COMPUTE_KEY, DH_R_INVALID_PUBKEY);
+ /* Prevent small subgroup attacks per RFC 8446 Section 4.2.8.1 */
+ if (!ossl_dh_check_pub_key_partial(dh, pubkey, &ret)) {
+ err_reason = DH_R_INVALID_PUBKEY;
goto err;
}
-
- if (!dh->
- meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key, dh->p, ctx, mont)) {
- DHerr(DH_F_COMPUTE_KEY, ERR_R_BN_LIB);
+ if (DH_set0_key(dh, pubkey, NULL) != 1)
goto err;
- }
-
- ret = BN_bn2binpad(tmp, key, BN_num_bytes(dh->p));
- err:
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- return ret;
-}
-
-static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
- const BIGNUM *a, const BIGNUM *p,
- const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
-{
- return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
-}
-
-static int dh_init(DH *dh)
-{
- dh->flags |= DH_FLAG_CACHE_MONT_P;
return 1;
+err:
+ ERR_raise(ERR_LIB_DH, err_reason);
+ BN_free(pubkey);
+ return 0;
}
-static int dh_finish(DH *dh)
+size_t ossl_dh_key2buf(const DH *dh, unsigned char **pbuf_out, size_t size,
+ int alloc)
{
- BN_MONT_CTX_free(dh->method_mont_p);
- return 1;
+ const BIGNUM *pubkey;
+ unsigned char *pbuf = NULL;
+ const BIGNUM *p;
+ int p_size;
+
+ DH_get0_pqg(dh, &p, NULL, NULL);
+ DH_get0_key(dh, &pubkey, NULL);
+ if (p == NULL || pubkey == NULL
+ || (p_size = BN_num_bytes(p)) == 0
+ || BN_num_bytes(pubkey) == 0) {
+ ERR_raise(ERR_LIB_DH, DH_R_INVALID_PUBKEY);
+ return 0;
+ }
+ if (pbuf_out != NULL && (alloc || *pbuf_out != NULL)) {
+ if (!alloc) {
+ if (size >= (size_t)p_size)
+ pbuf = *pbuf_out;
+ } else {
+ pbuf = OPENSSL_malloc(p_size);
+ }
+
+ if (pbuf == NULL) {
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ /*
+ * As per Section 4.2.8.1 of RFC 8446 left pad public
+ * key with zeros to the size of p
+ */
+ if (BN_bn2binpad(pubkey, pbuf, p_size) < 0) {
+ if (alloc)
+ OPENSSL_free(pbuf);
+ ERR_raise(ERR_LIB_DH, DH_R_BN_ERROR);
+ return 0;
+ }
+ *pbuf_out = pbuf;
+ }
+ return p_size;
}
diff --git a/crypto/dh/dh_lib.c b/crypto/dh/dh_lib.c
index 04b79d355ca4..29cda5d7bfa8 100644
--- a/crypto/dh/dh_lib.c
+++ b/crypto/dh/dh_lib.c
@@ -1,19 +1,34 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
+#include <openssl/bn.h>
+#ifndef FIPS_MODULE
+# include <openssl/engine.h>
+#endif
+#include <openssl/obj_mac.h>
+#include <openssl/core_names.h>
#include "internal/cryptlib.h"
#include "internal/refcount.h"
-#include <openssl/bn.h>
+#include "crypto/evp.h"
+#include "crypto/dh.h"
#include "dh_local.h"
-#include <openssl/engine.h>
+static DH *dh_new_intern(ENGINE *engine, OSSL_LIB_CTX *libctx);
+
+#ifndef FIPS_MODULE
int DH_set_method(DH *dh, const DH_METHOD *meth)
{
/*
@@ -34,34 +49,52 @@ int DH_set_method(DH *dh, const DH_METHOD *meth)
return 1;
}
+const DH_METHOD *ossl_dh_get_method(const DH *dh)
+{
+ return dh->meth;
+}
+# ifndef OPENSSL_NO_DEPRECATED_3_0
DH *DH_new(void)
{
- return DH_new_method(NULL);
+ return dh_new_intern(NULL, NULL);
}
+# endif
DH *DH_new_method(ENGINE *engine)
{
+ return dh_new_intern(engine, NULL);
+}
+#endif /* !FIPS_MODULE */
+
+DH *ossl_dh_new_ex(OSSL_LIB_CTX *libctx)
+{
+ return dh_new_intern(NULL, libctx);
+}
+
+static DH *dh_new_intern(ENGINE *engine, OSSL_LIB_CTX *libctx)
+{
DH *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- DHerr(DH_F_DH_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->references = 1;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
- DHerr(DH_F_DH_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
+ ret->libctx = libctx;
ret->meth = DH_get_default_method();
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
ret->flags = ret->meth->flags; /* early default init */
if (engine) {
if (!ENGINE_init(engine)) {
- DHerr(DH_F_DH_NEW_METHOD, ERR_R_ENGINE_LIB);
+ ERR_raise(ERR_LIB_DH, ERR_R_ENGINE_LIB);
goto err;
}
ret->engine = engine;
@@ -70,7 +103,7 @@ DH *DH_new_method(ENGINE *engine)
if (ret->engine) {
ret->meth = ENGINE_get_DH(ret->engine);
if (ret->meth == NULL) {
- DHerr(DH_F_DH_NEW_METHOD, ERR_R_ENGINE_LIB);
+ ERR_raise(ERR_LIB_DH, ERR_R_ENGINE_LIB);
goto err;
}
}
@@ -78,11 +111,13 @@ DH *DH_new_method(ENGINE *engine)
ret->flags = ret->meth->flags;
+#ifndef FIPS_MODULE
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DH, ret, &ret->ex_data))
goto err;
+#endif /* FIPS_MODULE */
if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
- DHerr(DH_F_DH_NEW_METHOD, ERR_R_INIT_FAIL);
+ ERR_raise(ERR_LIB_DH, ERR_R_INIT_FAIL);
goto err;
}
@@ -108,20 +143,16 @@ void DH_free(DH *r)
if (r->meth != NULL && r->meth->finish != NULL)
r->meth->finish(r);
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(FIPS_MODULE)
+# if !defined(OPENSSL_NO_ENGINE)
ENGINE_finish(r->engine);
-#endif
-
+# endif
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, r, &r->ex_data);
+#endif
CRYPTO_THREAD_lock_free(r->lock);
- BN_clear_free(r->p);
- BN_clear_free(r->g);
- BN_clear_free(r->q);
- BN_clear_free(r->j);
- OPENSSL_free(r->seed);
- BN_clear_free(r->counter);
+ ossl_ffc_params_cleanup(&r->params);
BN_clear_free(r->pub_key);
BN_clear_free(r->priv_key);
OPENSSL_free(r);
@@ -139,76 +170,71 @@ int DH_up_ref(DH *r)
return ((i > 1) ? 1 : 0);
}
+void ossl_dh_set0_libctx(DH *d, OSSL_LIB_CTX *libctx)
+{
+ d->libctx = libctx;
+}
+
+#ifndef FIPS_MODULE
int DH_set_ex_data(DH *d, int idx, void *arg)
{
return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
}
-void *DH_get_ex_data(DH *d, int idx)
+void *DH_get_ex_data(const DH *d, int idx)
{
return CRYPTO_get_ex_data(&d->ex_data, idx);
}
+#endif
int DH_bits(const DH *dh)
{
- return BN_num_bits(dh->p);
+ if (dh->params.p != NULL)
+ return BN_num_bits(dh->params.p);
+ return -1;
}
int DH_size(const DH *dh)
{
- return BN_num_bytes(dh->p);
+ if (dh->params.p != NULL)
+ return BN_num_bytes(dh->params.p);
+ return -1;
}
int DH_security_bits(const DH *dh)
{
int N;
- if (dh->q)
- N = BN_num_bits(dh->q);
+
+ if (dh->params.q != NULL)
+ N = BN_num_bits(dh->params.q);
else if (dh->length)
N = dh->length;
else
N = -1;
- return BN_security_bits(BN_num_bits(dh->p), N);
+ if (dh->params.p != NULL)
+ return BN_security_bits(BN_num_bits(dh->params.p), N);
+ return -1;
}
-
void DH_get0_pqg(const DH *dh,
const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
{
- if (p != NULL)
- *p = dh->p;
- if (q != NULL)
- *q = dh->q;
- if (g != NULL)
- *g = dh->g;
+ ossl_ffc_params_get0_pqg(&dh->params, p, q, g);
}
int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
{
- /* If the fields p and g in d are NULL, the corresponding input
+ /*
+ * If the fields p and g in dh are NULL, the corresponding input
* parameters MUST be non-NULL. q may remain NULL.
*/
- if ((dh->p == NULL && p == NULL)
- || (dh->g == NULL && g == NULL))
+ if ((dh->params.p == NULL && p == NULL)
+ || (dh->params.g == NULL && g == NULL))
return 0;
- if (p != NULL) {
- BN_free(dh->p);
- dh->p = p;
- }
- if (q != NULL) {
- BN_free(dh->q);
- dh->q = q;
- }
- if (g != NULL) {
- BN_free(dh->g);
- dh->g = g;
- }
-
- if (q != NULL) {
- dh->length = BN_num_bits(q);
- }
-
+ ossl_ffc_params_set0_pqg(&dh->params, p, q, g);
+ ossl_dh_cache_named_group(dh);
+ dh->dirty_cnt++;
return 1;
}
@@ -220,6 +246,7 @@ long DH_get_length(const DH *dh)
int DH_set_length(DH *dh, long length)
{
dh->length = length;
+ dh->dirty_cnt++;
return 1;
}
@@ -242,22 +269,23 @@ int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
dh->priv_key = priv_key;
}
+ dh->dirty_cnt++;
return 1;
}
const BIGNUM *DH_get0_p(const DH *dh)
{
- return dh->p;
+ return dh->params.p;
}
const BIGNUM *DH_get0_q(const DH *dh)
{
- return dh->q;
+ return dh->params.q;
}
const BIGNUM *DH_get0_g(const DH *dh)
{
- return dh->g;
+ return dh->params.g;
}
const BIGNUM *DH_get0_priv_key(const DH *dh)
@@ -285,7 +313,18 @@ void DH_set_flags(DH *dh, int flags)
dh->flags |= flags;
}
+#ifndef FIPS_MODULE
ENGINE *DH_get0_engine(DH *dh)
{
return dh->engine;
}
+#endif /*FIPS_MODULE */
+
+FFC_PARAMS *ossl_dh_get0_params(DH *dh)
+{
+ return &dh->params;
+}
+int ossl_dh_get0_nid(const DH *dh)
+{
+ return dh->params.nid;
+}
diff --git a/crypto/dh/dh_local.h b/crypto/dh/dh_local.h
index 0a8391a6c004..1ff075e3dc1d 100644
--- a/crypto/dh/dh_local.h
+++ b/crypto/dh/dh_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,6 +9,9 @@
#include <openssl/dh.h>
#include "internal/refcount.h"
+#include "internal/ffc.h"
+
+#define DH_MIN_MODULUS_BITS 512
struct dh_st {
/*
@@ -17,24 +20,24 @@ struct dh_st {
*/
int pad;
int version;
- BIGNUM *p;
- BIGNUM *g;
- int32_t length; /* optional */
+ FFC_PARAMS params;
+ /* max generated private key length (can be less than len(q)) */
+ int32_t length;
BIGNUM *pub_key; /* g^x % p */
BIGNUM *priv_key; /* x */
int flags;
BN_MONT_CTX *method_mont_p;
- /* Place holders if we want to do X9.42 DH */
- BIGNUM *q;
- BIGNUM *j;
- unsigned char *seed;
- int seedlen;
- BIGNUM *counter;
CRYPTO_REF_COUNT references;
+#ifndef FIPS_MODULE
CRYPTO_EX_DATA ex_data;
- const DH_METHOD *meth;
ENGINE *engine;
+#endif
+ OSSL_LIB_CTX *libctx;
+ const DH_METHOD *meth;
CRYPTO_RWLOCK *lock;
+
+ /* Provider data */
+ size_t dirty_cnt; /* If any key material changes, increment this */
};
struct dh_method {
diff --git a/crypto/dh/dh_meth.c b/crypto/dh/dh_meth.c
index 8a54a8108fc3..5c15cd2b8cc2 100644
--- a/crypto/dh/dh_meth.c
+++ b/crypto/dh/dh_meth.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include "dh_local.h"
#include <string.h>
#include <openssl/err.h>
@@ -25,7 +31,7 @@ DH_METHOD *DH_meth_new(const char *name, int flags)
OPENSSL_free(dhm);
}
- DHerr(DH_F_DH_METH_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -51,7 +57,7 @@ DH_METHOD *DH_meth_dup(const DH_METHOD *dhm)
OPENSSL_free(ret);
}
- DHerr(DH_F_DH_METH_DUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -65,7 +71,7 @@ int DH_meth_set1_name(DH_METHOD *dhm, const char *name)
char *tmpname = OPENSSL_strdup(name);
if (tmpname == NULL) {
- DHerr(DH_F_DH_METH_SET1_NAME, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
return 0;
}
diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c
index 1fd94deb4731..f201eede0df4 100644
--- a/crypto/dh/dh_pmeth.c
+++ b/crypto/dh/dh_pmeth.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DH & DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
@@ -24,12 +30,11 @@ typedef struct {
/* Parameter gen parameters */
int prime_len;
int generator;
- int use_dsa;
+ int paramgen_type;
int subprime_len;
int pad;
/* message digest used for parameter generation */
const EVP_MD *md;
- int rfc5114_param;
int param_nid;
/* Keygen callback info */
int gentmp[2];
@@ -51,7 +56,7 @@ static int pkey_dh_init(EVP_PKEY_CTX *ctx)
DH_PKEY_CTX *dctx;
if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) {
- DHerr(DH_F_PKEY_DH_INIT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
return 0;
}
dctx->prime_len = 2048;
@@ -69,6 +74,7 @@ static int pkey_dh_init(EVP_PKEY_CTX *ctx)
static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
{
DH_PKEY_CTX *dctx = ctx->data;
+
if (dctx != NULL) {
OPENSSL_free(dctx->kdf_ukm);
ASN1_OBJECT_free(dctx->kdf_oid);
@@ -77,9 +83,10 @@ static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
}
-static int pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+static int pkey_dh_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
{
DH_PKEY_CTX *dctx, *sctx;
+
if (!pkey_dh_init(dst))
return 0;
sctx = src->data;
@@ -87,10 +94,9 @@ static int pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
dctx->prime_len = sctx->prime_len;
dctx->subprime_len = sctx->subprime_len;
dctx->generator = sctx->generator;
- dctx->use_dsa = sctx->use_dsa;
+ dctx->paramgen_type = sctx->paramgen_type;
dctx->pad = sctx->pad;
dctx->md = sctx->md;
- dctx->rfc5114_param = sctx->rfc5114_param;
dctx->param_nid = sctx->param_nid;
dctx->kdf_type = sctx->kdf_type;
@@ -119,7 +125,7 @@ static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return 1;
case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN:
- if (dctx->use_dsa == 0)
+ if (dctx->paramgen_type == DH_PARAMGEN_TYPE_GENERATOR)
return -2;
dctx->subprime_len = p1;
return 1;
@@ -129,30 +135,30 @@ static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return 1;
case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
- if (dctx->use_dsa)
+ if (dctx->paramgen_type != DH_PARAMGEN_TYPE_GENERATOR)
return -2;
dctx->generator = p1;
return 1;
case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE:
#ifdef OPENSSL_NO_DSA
- if (p1 != 0)
+ if (p1 != DH_PARAMGEN_TYPE_GENERATOR)
return -2;
#else
if (p1 < 0 || p1 > 2)
return -2;
#endif
- dctx->use_dsa = p1;
+ dctx->paramgen_type = p1;
return 1;
case EVP_PKEY_CTRL_DH_RFC5114:
if (p1 < 1 || p1 > 3 || dctx->param_nid != NID_undef)
return -2;
- dctx->rfc5114_param = p1;
+ dctx->param_nid = p1;
return 1;
case EVP_PKEY_CTRL_DH_NID:
- if (p1 <= 0 || dctx->rfc5114_param != 0)
+ if (p1 <= 0 || dctx->param_nid != NID_undef)
return -2;
dctx->param_nid = p1;
return 1;
@@ -164,11 +170,7 @@ static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_DH_KDF_TYPE:
if (p1 == -2)
return dctx->kdf_type;
-#ifdef OPENSSL_NO_CMS
- if (p1 != EVP_PKEY_DH_KDF_NONE)
-#else
if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42)
-#endif
return -2;
dctx->kdf_type = p1;
return 1;
@@ -229,11 +231,12 @@ static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
}
if (strcmp(type, "dh_rfc5114") == 0) {
DH_PKEY_CTX *dctx = ctx->data;
- int len;
- len = atoi(value);
- if (len < 0 || len > 3)
+ int id;
+
+ id = atoi(value);
+ if (id < 0 || id > 3)
return -2;
- dctx->rfc5114_param = len;
+ dctx->param_nid = id;
return 1;
}
if (strcmp(type, "dh_param") == 0) {
@@ -241,7 +244,7 @@ static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
int nid = OBJ_sn2nid(value);
if (nid == NID_undef) {
- DHerr(DH_F_PKEY_DH_CTRL_STR, DH_R_INVALID_PARAMETER_NAME);
+ ERR_raise(ERR_LIB_DH, DH_R_INVALID_PARAMETER_NAME);
return -2;
}
dctx->param_nid = nid;
@@ -270,116 +273,91 @@ static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
return -2;
}
-#ifndef OPENSSL_NO_DSA
-
-extern int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
- const EVP_MD *evpmd,
- const unsigned char *seed_in, size_t seed_len,
- unsigned char *seed_out, int *counter_ret,
- unsigned long *h_ret, BN_GENCB *cb);
-
-extern int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
- const EVP_MD *evpmd,
- const unsigned char *seed_in,
- size_t seed_len, int idx,
- unsigned char *seed_out, int *counter_ret,
- unsigned long *h_ret, BN_GENCB *cb);
-
-static DSA *dsa_dh_generate(DH_PKEY_CTX *dctx, BN_GENCB *pcb)
+static DH *ffc_params_generate(OSSL_LIB_CTX *libctx, DH_PKEY_CTX *dctx,
+ BN_GENCB *pcb)
{
- DSA *ret;
+ DH *ret;
int rv = 0;
+ int res;
int prime_len = dctx->prime_len;
int subprime_len = dctx->subprime_len;
- const EVP_MD *md = dctx->md;
- if (dctx->use_dsa > 2)
+
+ if (dctx->paramgen_type > DH_PARAMGEN_TYPE_FIPS_186_4)
return NULL;
- ret = DSA_new();
+ ret = DH_new();
if (ret == NULL)
return NULL;
+
if (subprime_len == -1) {
if (prime_len >= 2048)
subprime_len = 256;
else
subprime_len = 160;
}
- if (md == NULL) {
- if (prime_len >= 2048)
- md = EVP_sha256();
- else
- md = EVP_sha1();
- }
- if (dctx->use_dsa == 1)
- rv = dsa_builtin_paramgen(ret, prime_len, subprime_len, md,
- NULL, 0, NULL, NULL, NULL, pcb);
- else if (dctx->use_dsa == 2)
- rv = dsa_builtin_paramgen2(ret, prime_len, subprime_len, md,
- NULL, 0, -1, NULL, NULL, NULL, pcb);
+
+ if (dctx->md != NULL)
+ ossl_ffc_set_digest(&ret->params, EVP_MD_get0_name(dctx->md), NULL);
+
+# ifndef FIPS_MODULE
+ if (dctx->paramgen_type == DH_PARAMGEN_TYPE_FIPS_186_2)
+ rv = ossl_ffc_params_FIPS186_2_generate(libctx, &ret->params,
+ FFC_PARAM_TYPE_DH,
+ prime_len, subprime_len, &res,
+ pcb);
+ else
+# endif
+ /* For FIPS we always use the DH_PARAMGEN_TYPE_FIPS_186_4 generator */
+ if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2)
+ rv = ossl_ffc_params_FIPS186_4_generate(libctx, &ret->params,
+ FFC_PARAM_TYPE_DH,
+ prime_len, subprime_len, &res,
+ pcb);
if (rv <= 0) {
- DSA_free(ret);
+ DH_free(ret);
return NULL;
}
return ret;
}
-#endif
-
-static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx,
+ EVP_PKEY *pkey)
{
DH *dh = NULL;
DH_PKEY_CTX *dctx = ctx->data;
- BN_GENCB *pcb;
+ BN_GENCB *pcb = NULL;
int ret;
- if (dctx->rfc5114_param) {
- switch (dctx->rfc5114_param) {
- case 1:
- dh = DH_get_1024_160();
- break;
- case 2:
- dh = DH_get_2048_224();
- break;
+ /*
+ * Look for a safe prime group for key establishment. Which uses
+ * either RFC_3526 (modp_XXXX) or RFC_7919 (ffdheXXXX).
+ * RFC_5114 is also handled here for param_nid = (1..3)
+ */
+ if (dctx->param_nid != NID_undef) {
+ int type = dctx->param_nid <= 3 ? EVP_PKEY_DHX : EVP_PKEY_DH;
- case 3:
- dh = DH_get_2048_256();
- break;
-
- default:
- return -2;
- }
- EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
- return 1;
- }
-
- if (dctx->param_nid != 0) {
if ((dh = DH_new_by_nid(dctx->param_nid)) == NULL)
return 0;
- EVP_PKEY_assign(pkey, EVP_PKEY_DH, dh);
+ EVP_PKEY_assign(pkey, type, dh);
return 1;
}
- if (ctx->pkey_gencb) {
+ if (ctx->pkey_gencb != NULL) {
pcb = BN_GENCB_new();
if (pcb == NULL)
return 0;
evp_pkey_set_cb_translate(pcb, ctx);
- } else
- pcb = NULL;
-#ifndef OPENSSL_NO_DSA
- if (dctx->use_dsa) {
- DSA *dsa_dh;
- dsa_dh = dsa_dh_generate(dctx, pcb);
+ }
+# ifdef FIPS_MODULE
+ dctx->paramgen_type = DH_PARAMGEN_TYPE_FIPS_186_4;
+# endif /* FIPS_MODULE */
+ if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2) {
+ dh = ffc_params_generate(NULL, dctx, pcb);
BN_GENCB_free(pcb);
- if (dsa_dh == NULL)
- return 0;
- dh = DSA_dup_DH(dsa_dh);
- DSA_free(dsa_dh);
- if (!dh)
+ if (dh == NULL)
return 0;
EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
return 1;
}
-#endif
dh = DH_new();
if (dh == NULL) {
BN_GENCB_free(pcb);
@@ -400,11 +378,11 @@ static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
DH_PKEY_CTX *dctx = ctx->data;
DH *dh = NULL;
- if (ctx->pkey == NULL && dctx->param_nid == 0) {
- DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET);
+ if (ctx->pkey == NULL && dctx->param_nid == NID_undef) {
+ ERR_raise(ERR_LIB_DH, DH_R_NO_PARAMETERS_SET);
return 0;
}
- if (dctx->param_nid != 0)
+ if (dctx->param_nid != NID_undef)
dh = DH_new_by_nid(dctx->param_nid);
else
dh = DH_new();
@@ -414,7 +392,7 @@ static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
/* Note: if error return, pkey is freed by parent routine */
if (ctx->pkey != NULL && !EVP_PKEY_copy_parameters(pkey, ctx->pkey))
return 0;
- return DH_generate_key(pkey->pkey.dh);
+ return DH_generate_key((DH *)EVP_PKEY_get0_DH(pkey));
}
static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
@@ -422,33 +400,40 @@ static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
{
int ret;
DH *dh;
+ const DH *dhpub;
DH_PKEY_CTX *dctx = ctx->data;
- BIGNUM *dhpub;
- if (!ctx->pkey || !ctx->peerkey) {
- DHerr(DH_F_PKEY_DH_DERIVE, DH_R_KEYS_NOT_SET);
+ BIGNUM *dhpubbn;
+
+ if (ctx->pkey == NULL || ctx->peerkey == NULL) {
+ ERR_raise(ERR_LIB_DH, DH_R_KEYS_NOT_SET);
+ return 0;
+ }
+ dh = (DH *)EVP_PKEY_get0_DH(ctx->pkey);
+ dhpub = EVP_PKEY_get0_DH(ctx->peerkey);
+ if (dhpub == NULL) {
+ ERR_raise(ERR_LIB_DH, DH_R_KEYS_NOT_SET);
return 0;
}
- dh = ctx->pkey->pkey.dh;
- dhpub = ctx->peerkey->pkey.dh->pub_key;
+ dhpubbn = dhpub->pub_key;
if (dctx->kdf_type == EVP_PKEY_DH_KDF_NONE) {
if (key == NULL) {
*keylen = DH_size(dh);
return 1;
}
if (dctx->pad)
- ret = DH_compute_key_padded(key, dhpub, dh);
+ ret = DH_compute_key_padded(key, dhpubbn, dh);
else
- ret = DH_compute_key(key, dhpub, dh);
+ ret = DH_compute_key(key, dhpubbn, dh);
if (ret < 0)
return ret;
*keylen = ret;
return 1;
}
-#ifndef OPENSSL_NO_CMS
else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) {
unsigned char *Z = NULL;
- size_t Zlen = 0;
+ int Zlen = 0;
+
if (!dctx->kdf_outlen || !dctx->kdf_oid)
return 0;
if (key == NULL) {
@@ -458,12 +443,13 @@ static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
if (*keylen != dctx->kdf_outlen)
return 0;
ret = 0;
- Zlen = DH_size(dh);
- Z = OPENSSL_malloc(Zlen);
- if (Z == NULL) {
- goto err;
+ if ((Zlen = DH_size(dh)) <= 0)
+ return 0;
+ if ((Z = OPENSSL_malloc(Zlen)) == NULL) {
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
+ return 0;
}
- if (DH_compute_key_padded(Z, dhpub, dh) <= 0)
+ if (DH_compute_key_padded(Z, dhpubbn, dh) <= 0)
goto err;
if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid,
dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
@@ -474,11 +460,10 @@ static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
OPENSSL_clear_free(Z, Zlen);
return ret;
}
-#endif
return 0;
}
-const EVP_PKEY_METHOD dh_pkey_meth = {
+static const EVP_PKEY_METHOD dh_pkey_meth = {
EVP_PKEY_DH,
0,
pkey_dh_init,
@@ -512,7 +497,12 @@ const EVP_PKEY_METHOD dh_pkey_meth = {
pkey_dh_ctrl_str
};
-const EVP_PKEY_METHOD dhx_pkey_meth = {
+const EVP_PKEY_METHOD *ossl_dh_pkey_method(void)
+{
+ return &dh_pkey_meth;
+}
+
+static const EVP_PKEY_METHOD dhx_pkey_meth = {
EVP_PKEY_DHX,
0,
pkey_dh_init,
@@ -545,3 +535,8 @@ const EVP_PKEY_METHOD dhx_pkey_meth = {
pkey_dh_ctrl,
pkey_dh_ctrl_str
};
+
+const EVP_PKEY_METHOD *ossl_dhx_pkey_method(void)
+{
+ return &dhx_pkey_meth;
+}
diff --git a/crypto/dh/dh_prn.c b/crypto/dh/dh_prn.c
index aab1733db3b3..5d31254dcbc6 100644
--- a/crypto/dh/dh_prn.c
+++ b/crypto/dh/dh_prn.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
@@ -19,7 +25,7 @@ int DHparams_print_fp(FILE *fp, const DH *x)
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- DHerr(DH_F_DHPARAMS_PRINT_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_DH, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
diff --git a/crypto/dh/dh_rfc5114.c b/crypto/dh/dh_rfc5114.c
index e3603a05a322..7b1e0610bd71 100644
--- a/crypto/dh/dh_rfc5114.c
+++ b/crypto/dh/dh_rfc5114.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include "dh_local.h"
@@ -26,10 +32,10 @@ DH *DH_get_##x(void) \
\
if (dh == NULL) \
return NULL; \
- dh->p = BN_dup(&_bignum_dh##x##_p); \
- dh->g = BN_dup(&_bignum_dh##x##_g); \
- dh->q = BN_dup(&_bignum_dh##x##_q); \
- if (dh->p == NULL || dh->q == NULL || dh->g == NULL) {\
+ dh->params.p = BN_dup(&ossl_bignum_dh##x##_p); \
+ dh->params.g = BN_dup(&ossl_bignum_dh##x##_g); \
+ dh->params.q = BN_dup(&ossl_bignum_dh##x##_q); \
+ if (dh->params.p == NULL || dh->params.q == NULL || dh->params.g == NULL) {\
DH_free(dh); \
return NULL; \
} \
diff --git a/crypto/dh/dh_rfc7919.c b/crypto/dh/dh_rfc7919.c
deleted file mode 100644
index 03d30a1f5d59..000000000000
--- a/crypto/dh/dh_rfc7919.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include "dh_local.h"
-#include <openssl/bn.h>
-#include <openssl/objects.h>
-#include "crypto/bn_dh.h"
-
-static DH *dh_param_init(const BIGNUM *p, int32_t nbits)
-{
- DH *dh = DH_new();
- if (dh == NULL)
- return NULL;
- dh->p = (BIGNUM *)p;
- dh->g = (BIGNUM *)&_bignum_const_2;
- dh->length = nbits;
- return dh;
-}
-
-DH *DH_new_by_nid(int nid)
-{
- switch (nid) {
- case NID_ffdhe2048:
- return dh_param_init(&_bignum_ffdhe2048_p, 225);
- case NID_ffdhe3072:
- return dh_param_init(&_bignum_ffdhe3072_p, 275);
- case NID_ffdhe4096:
- return dh_param_init(&_bignum_ffdhe4096_p, 325);
- case NID_ffdhe6144:
- return dh_param_init(&_bignum_ffdhe6144_p, 375);
- case NID_ffdhe8192:
- return dh_param_init(&_bignum_ffdhe8192_p, 400);
- default:
- DHerr(DH_F_DH_NEW_BY_NID, DH_R_INVALID_PARAMETER_NID);
- return NULL;
- }
-}
-
-int DH_get_nid(const DH *dh)
-{
- int nid;
-
- if (BN_get_word(dh->g) != 2)
- return NID_undef;
- if (!BN_cmp(dh->p, &_bignum_ffdhe2048_p))
- nid = NID_ffdhe2048;
- else if (!BN_cmp(dh->p, &_bignum_ffdhe3072_p))
- nid = NID_ffdhe3072;
- else if (!BN_cmp(dh->p, &_bignum_ffdhe4096_p))
- nid = NID_ffdhe4096;
- else if (!BN_cmp(dh->p, &_bignum_ffdhe6144_p))
- nid = NID_ffdhe6144;
- else if (!BN_cmp(dh->p, &_bignum_ffdhe8192_p))
- nid = NID_ffdhe8192;
- else
- return NID_undef;
- if (dh->q != NULL) {
- BIGNUM *q = BN_dup(dh->p);
-
- /* Check q = p * 2 + 1 we already know q is odd, so just shift right */
- if (q == NULL || !BN_rshift1(q, q) || !BN_cmp(dh->q, q))
- nid = NID_undef;
- BN_free(q);
- }
- return nid;
-}
diff --git a/crypto/dllmain.c b/crypto/dllmain.c
index e8217893b9ed..48c0cd31227a 100644
--- a/crypto/dllmain.c
+++ b/crypto/dllmain.c
@@ -1,7 +1,7 @@
/*
* Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/dsa/build.info b/crypto/dsa/build.info
index 2e759853a2a2..9a7d275c3500 100644
--- a/crypto/dsa/build.info
+++ b/crypto/dsa/build.info
@@ -1,5 +1,12 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- dsa_gen.c dsa_key.c dsa_lib.c dsa_asn1.c dsa_vrf.c dsa_sign.c \
- dsa_err.c dsa_ossl.c dsa_depr.c dsa_ameth.c dsa_pmeth.c dsa_prn.c \
+
+$COMMON=dsa_sign.c dsa_vrf.c dsa_lib.c dsa_ossl.c dsa_check.c \
+ dsa_key.c dsa_backend.c dsa_gen.c
+
+SOURCE[../../libcrypto]=$COMMON\
+ dsa_asn1.c dsa_err.c dsa_ameth.c dsa_pmeth.c dsa_prn.c \
dsa_meth.c
+IF[{- !$disabled{'deprecated-0.9.8'} -}]
+ SOURCE[../../libcrypto]=dsa_depr.c
+ENDIF
+SOURCE[../../providers/libfips.a]=$COMMON
diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c
index 2dcaa0815fd6..482b9e1e0aa7 100644
--- a/crypto/dsa/dsa_ameth.c
+++ b/crypto/dsa/dsa_ameth.c
@@ -1,23 +1,32 @@
/*
- * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
-#include "internal/cryptlib.h"
#include <openssl/x509.h>
#include <openssl/asn1.h>
-#include "dsa_local.h"
#include <openssl/bn.h>
-#include <openssl/cms.h>
+#include <openssl/core_names.h>
+#include <openssl/param_build.h>
+#include "internal/cryptlib.h"
#include "crypto/asn1.h"
+#include "crypto/dsa.h"
#include "crypto/evp.h"
+#include "internal/ffc.h"
+#include "dsa_local.h"
-static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
+static int dsa_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
{
const unsigned char *p, *pm;
int pklen, pmlen;
@@ -39,30 +48,31 @@ static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
pmlen = pstr->length;
if ((dsa = d2i_DSAparams(NULL, &pm, pmlen)) == NULL) {
- DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_DECODE_ERROR);
+ ERR_raise(ERR_LIB_DSA, DSA_R_DECODE_ERROR);
goto err;
}
} else if ((ptype == V_ASN1_NULL) || (ptype == V_ASN1_UNDEF)) {
if ((dsa = DSA_new()) == NULL) {
- DSAerr(DSA_F_DSA_PUB_DECODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
goto err;
}
} else {
- DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_PARAMETER_ENCODING_ERROR);
+ ERR_raise(ERR_LIB_DSA, DSA_R_PARAMETER_ENCODING_ERROR);
goto err;
}
if ((public_key = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL) {
- DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_DECODE_ERROR);
+ ERR_raise(ERR_LIB_DSA, DSA_R_DECODE_ERROR);
goto err;
}
if ((dsa->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)) == NULL) {
- DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_BN_DECODE_ERROR);
+ ERR_raise(ERR_LIB_DSA, DSA_R_BN_DECODE_ERROR);
goto err;
}
+ dsa->dirty_cnt++;
ASN1_INTEGER_free(public_key);
EVP_PKEY_assign_DSA(pkey, dsa);
return 1;
@@ -85,15 +95,18 @@ static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
ASN1_OBJECT *aobj;
dsa = pkey->pkey.dsa;
- if (pkey->save_parameters && dsa->p && dsa->q && dsa->g) {
+ if (pkey->save_parameters
+ && dsa->params.p != NULL
+ && dsa->params.q != NULL
+ && dsa->params.g != NULL) {
str = ASN1_STRING_new();
if (str == NULL) {
- DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
goto err;
}
str->length = i2d_DSAparams(dsa, &str->data);
if (str->length <= 0) {
- DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
goto err;
}
ptype = V_ASN1_SEQUENCE;
@@ -103,7 +116,7 @@ static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
pubint = BN_to_ASN1_INTEGER(dsa->pub_key, NULL);
if (pubint == NULL) {
- DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -111,7 +124,7 @@ static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
ASN1_INTEGER_free(pubint);
if (penclen <= 0) {
- DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -136,67 +149,14 @@ static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
static int dsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
{
- const unsigned char *p, *pm;
- int pklen, pmlen;
- int ptype;
- const void *pval;
- const ASN1_STRING *pstr;
- const X509_ALGOR *palg;
- ASN1_INTEGER *privkey = NULL;
- BN_CTX *ctx = NULL;
-
- DSA *dsa = NULL;
-
int ret = 0;
+ DSA *dsa = ossl_dsa_key_from_pkcs8(p8, NULL, NULL);
- if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
- return 0;
- X509_ALGOR_get0(NULL, &ptype, &pval, palg);
-
- if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL)
- goto decerr;
- if (privkey->type == V_ASN1_NEG_INTEGER || ptype != V_ASN1_SEQUENCE)
- goto decerr;
-
- pstr = pval;
- pm = pstr->data;
- pmlen = pstr->length;
- if ((dsa = d2i_DSAparams(NULL, &pm, pmlen)) == NULL)
- goto decerr;
- /* We have parameters now set private key */
- if ((dsa->priv_key = BN_secure_new()) == NULL
- || !ASN1_INTEGER_to_BN(privkey, dsa->priv_key)) {
- DSAerr(DSA_F_DSA_PRIV_DECODE, DSA_R_BN_ERROR);
- goto dsaerr;
- }
- /* Calculate public key */
- if ((dsa->pub_key = BN_new()) == NULL) {
- DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_MALLOC_FAILURE);
- goto dsaerr;
- }
- if ((ctx = BN_CTX_new()) == NULL) {
- DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_MALLOC_FAILURE);
- goto dsaerr;
- }
-
- BN_set_flags(dsa->priv_key, BN_FLG_CONSTTIME);
- if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) {
- DSAerr(DSA_F_DSA_PRIV_DECODE, DSA_R_BN_ERROR);
- goto dsaerr;
+ if (dsa != NULL) {
+ ret = 1;
+ EVP_PKEY_assign_DSA(pkey, dsa);
}
- EVP_PKEY_assign_DSA(pkey, dsa);
-
- ret = 1;
- goto done;
-
- decerr:
- DSAerr(DSA_F_DSA_PRIV_DECODE, DSA_R_DECODE_ERROR);
- dsaerr:
- DSA_free(dsa);
- done:
- BN_CTX_free(ctx);
- ASN1_STRING_clear_free(privkey);
return ret;
}
@@ -207,21 +167,21 @@ static int dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
unsigned char *dp = NULL;
int dplen;
- if (!pkey->pkey.dsa || !pkey->pkey.dsa->priv_key) {
- DSAerr(DSA_F_DSA_PRIV_ENCODE, DSA_R_MISSING_PARAMETERS);
+ if (pkey->pkey.dsa == NULL|| pkey->pkey.dsa->priv_key == NULL) {
+ ERR_raise(ERR_LIB_DSA, DSA_R_MISSING_PARAMETERS);
goto err;
}
params = ASN1_STRING_new();
if (params == NULL) {
- DSAerr(DSA_F_DSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
goto err;
}
params->length = i2d_DSAparams(pkey->pkey.dsa, &params->data);
if (params->length <= 0) {
- DSAerr(DSA_F_DSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
goto err;
}
params->type = V_ASN1_SEQUENCE;
@@ -229,26 +189,29 @@ static int dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
/* Get private key into integer */
prkey = BN_to_ASN1_INTEGER(pkey->pkey.dsa->priv_key, NULL);
- if (!prkey) {
- DSAerr(DSA_F_DSA_PRIV_ENCODE, DSA_R_BN_ERROR);
+ if (prkey == NULL) {
+ ERR_raise(ERR_LIB_DSA, DSA_R_BN_ERROR);
goto err;
}
dplen = i2d_ASN1_INTEGER(prkey, &dp);
ASN1_STRING_clear_free(prkey);
- prkey = NULL;
- if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_dsa), 0,
- V_ASN1_SEQUENCE, params, dp, dplen))
+ if (dplen <= 0) {
+ ERR_raise(ERR_LIB_DSA, DSA_R_BN_ERROR);
goto err;
+ }
+ if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_dsa), 0,
+ V_ASN1_SEQUENCE, params, dp, dplen)) {
+ OPENSSL_clear_free(dp, dplen);
+ goto err;
+ }
return 1;
err:
- OPENSSL_free(dp);
ASN1_STRING_free(params);
- ASN1_STRING_clear_free(prkey);
return 0;
}
@@ -271,54 +234,34 @@ static int dsa_missing_parameters(const EVP_PKEY *pkey)
{
DSA *dsa;
dsa = pkey->pkey.dsa;
- if (dsa == NULL || dsa->p == NULL || dsa->q == NULL || dsa->g == NULL)
- return 1;
- return 0;
+ return dsa == NULL
+ || dsa->params.p == NULL
+ || dsa->params.q == NULL
+ || dsa->params.g == NULL;
}
static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
{
- BIGNUM *a;
-
if (to->pkey.dsa == NULL) {
to->pkey.dsa = DSA_new();
if (to->pkey.dsa == NULL)
return 0;
}
-
- if ((a = BN_dup(from->pkey.dsa->p)) == NULL)
+ if (!ossl_ffc_params_copy(&to->pkey.dsa->params, &from->pkey.dsa->params))
return 0;
- BN_free(to->pkey.dsa->p);
- to->pkey.dsa->p = a;
- if ((a = BN_dup(from->pkey.dsa->q)) == NULL)
- return 0;
- BN_free(to->pkey.dsa->q);
- to->pkey.dsa->q = a;
-
- if ((a = BN_dup(from->pkey.dsa->g)) == NULL)
- return 0;
- BN_free(to->pkey.dsa->g);
- to->pkey.dsa->g = a;
+ to->pkey.dsa->dirty_cnt++;
return 1;
}
static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
{
- if (BN_cmp(a->pkey.dsa->p, b->pkey.dsa->p) ||
- BN_cmp(a->pkey.dsa->q, b->pkey.dsa->q) ||
- BN_cmp(a->pkey.dsa->g, b->pkey.dsa->g))
- return 0;
- else
- return 1;
+ return ossl_ffc_params_cmp(&a->pkey.dsa->params, &b->pkey.dsa->params, 1);
}
static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
{
- if (BN_cmp(b->pkey.dsa->pub_key, a->pkey.dsa->pub_key) != 0)
- return 0;
- else
- return 1;
+ return BN_cmp(b->pkey.dsa->pub_key, a->pkey.dsa->pub_key) == 0;
}
static void int_dsa_free(EVP_PKEY *pkey)
@@ -331,6 +274,10 @@ static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype)
int ret = 0;
const char *ktype = NULL;
const BIGNUM *priv_key, *pub_key;
+ int mod_len = 0;
+
+ if (x->params.p != NULL)
+ mod_len = DSA_bits(x);
if (ptype == 2)
priv_key = x->priv_key;
@@ -349,11 +296,13 @@ static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype)
else
ktype = "DSA-Parameters";
- if (priv_key) {
+ if (priv_key != NULL) {
if (!BIO_indent(bp, off, 128))
goto err;
- if (BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p))
- <= 0)
+ if (BIO_printf(bp, "%s: (%d bit)\n", ktype, mod_len) <= 0)
+ goto err;
+ } else {
+ if (BIO_printf(bp, "Public-Key: (%d bit)\n", mod_len) <= 0)
goto err;
}
@@ -361,11 +310,7 @@ static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype)
goto err;
if (!ASN1_bn_print(bp, "pub: ", pub_key, NULL, off))
goto err;
- if (!ASN1_bn_print(bp, "P: ", x->p, NULL, off))
- goto err;
- if (!ASN1_bn_print(bp, "Q: ", x->q, NULL, off))
- goto err;
- if (!ASN1_bn_print(bp, "G: ", x->g, NULL, off))
+ if (!ossl_ffc_params_print(bp, &x->params, off))
goto err;
ret = 1;
err:
@@ -377,10 +322,10 @@ static int dsa_param_decode(EVP_PKEY *pkey,
{
DSA *dsa;
- if ((dsa = d2i_DSAparams(NULL, pder, derlen)) == NULL) {
- DSAerr(DSA_F_DSA_PARAM_DECODE, ERR_R_DSA_LIB);
+ if ((dsa = d2i_DSAparams(NULL, pder, derlen)) == NULL)
return 0;
- }
+
+ dsa->dirty_cnt++;
EVP_PKEY_assign_DSA(pkey, dsa);
return 1;
}
@@ -414,9 +359,10 @@ static int old_dsa_priv_decode(EVP_PKEY *pkey,
DSA *dsa;
if ((dsa = d2i_DSAPrivateKey(NULL, pder, derlen)) == NULL) {
- DSAerr(DSA_F_OLD_DSA_PRIV_DECODE, ERR_R_DSA_LIB);
+ ERR_raise(ERR_LIB_DSA, ERR_R_DSA_LIB);
return 0;
}
+ dsa->dirty_cnt++;
EVP_PKEY_assign_DSA(pkey, dsa);
return 1;
}
@@ -432,7 +378,7 @@ static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
DSA_SIG *dsa_sig;
const unsigned char *p;
- if (!sig) {
+ if (sig == NULL) {
if (BIO_puts(bp, "\n") <= 0)
return 0;
else
@@ -440,7 +386,7 @@ static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
}
p = sig->data;
dsa_sig = d2i_DSA_SIG(NULL, &p, sig->length);
- if (dsa_sig) {
+ if (dsa_sig != NULL) {
int rv = 0;
const BIGNUM *r, *s;
@@ -458,63 +404,119 @@ static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
DSA_SIG_free(dsa_sig);
return rv;
}
+ if (BIO_puts(bp, "\n") <= 0)
+ return 0;
return X509_signature_dump(bp, sig, indent);
}
static int dsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
{
switch (op) {
- case ASN1_PKEY_CTRL_PKCS7_SIGN:
- if (arg1 == 0) {
- int snid, hnid;
- X509_ALGOR *alg1, *alg2;
- PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
- if (alg1 == NULL || alg1->algorithm == NULL)
- return -1;
- hnid = OBJ_obj2nid(alg1->algorithm);
- if (hnid == NID_undef)
- return -1;
- if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
- return -1;
- X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
- }
- return 1;
-#ifndef OPENSSL_NO_CMS
- case ASN1_PKEY_CTRL_CMS_SIGN:
- if (arg1 == 0) {
- int snid, hnid;
- X509_ALGOR *alg1, *alg2;
- CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
- if (alg1 == NULL || alg1->algorithm == NULL)
- return -1;
- hnid = OBJ_obj2nid(alg1->algorithm);
- if (hnid == NID_undef)
- return -1;
- if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
- return -1;
- X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
- }
- return 1;
-
- case ASN1_PKEY_CTRL_CMS_RI_TYPE:
- *(int *)arg2 = CMS_RECIPINFO_NONE;
- return 1;
-#endif
-
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
*(int *)arg2 = NID_sha256;
return 1;
default:
return -2;
+ }
+}
+
+static size_t dsa_pkey_dirty_cnt(const EVP_PKEY *pkey)
+{
+ return pkey->pkey.dsa->dirty_cnt;
+}
+
+static int dsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
+ OSSL_FUNC_keymgmt_import_fn *importer,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ DSA *dsa = from->pkey.dsa;
+ OSSL_PARAM_BLD *tmpl;
+ const BIGNUM *p = DSA_get0_p(dsa), *g = DSA_get0_g(dsa);
+ const BIGNUM *q = DSA_get0_q(dsa), *pub_key = DSA_get0_pub_key(dsa);
+ const BIGNUM *priv_key = DSA_get0_priv_key(dsa);
+ OSSL_PARAM *params;
+ int selection = 0;
+ int rv = 0;
+
+ if (p == NULL || q == NULL || g == NULL)
+ return 0;
+
+ tmpl = OSSL_PARAM_BLD_new();
+ if (tmpl == NULL)
+ return 0;
+
+ if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, p)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, q)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, g))
+ goto err;
+ selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
+ if (pub_key != NULL) {
+ if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
+ pub_key))
+ goto err;
+ selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+ }
+ if (priv_key != NULL) {
+ if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
+ priv_key))
+ goto err;
+ selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
+ }
+
+ if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
+ goto err;
+ /* We export, the provider imports */
+ rv = importer(to_keydata, selection, params);
+
+ OSSL_PARAM_free(params);
+ err:
+ OSSL_PARAM_BLD_free(tmpl);
+ return rv;
+}
+
+static int dsa_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
+{
+ EVP_PKEY_CTX *pctx = vpctx;
+ EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
+ DSA *dsa = ossl_dsa_new(pctx->libctx);
+
+ if (dsa == NULL) {
+ ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
+ return 0;
}
+ if (!ossl_dsa_ffc_params_fromdata(dsa, params)
+ || !ossl_dsa_key_fromdata(dsa, params, 1)
+ || !EVP_PKEY_assign_DSA(pkey, dsa)) {
+ DSA_free(dsa);
+ return 0;
+ }
+ return 1;
+}
+
+static int dsa_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
+{
+ DSA *dsa = from->pkey.dsa;
+ DSA *dupkey = NULL;
+ int ret;
+
+ if (dsa != NULL) {
+ dupkey = ossl_dsa_dup(dsa, OSSL_KEYMGMT_SELECT_ALL);
+ if (dupkey == NULL)
+ return 0;
+ }
+
+ ret = EVP_PKEY_assign_DSA(to, dupkey);
+ if (!ret)
+ DSA_free(dupkey);
+ return ret;
}
/* NB these are sorted in pkey_id order, lowest first */
-const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[5] = {
+const EVP_PKEY_ASN1_METHOD ossl_dsa_asn1_meths[5] = {
{
EVP_PKEY_DSA2,
@@ -568,5 +570,15 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[5] = {
int_dsa_free,
dsa_pkey_ctrl,
old_dsa_priv_decode,
- old_dsa_priv_encode}
+ old_dsa_priv_encode,
+
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+
+ dsa_pkey_dirty_cnt,
+ dsa_pkey_export_to,
+ dsa_pkey_import_from,
+ dsa_pkey_copy
+ }
};
diff --git a/crypto/dsa/dsa_asn1.c b/crypto/dsa/dsa_asn1.c
index 9cafd5ca8a90..300ce6806df5 100644
--- a/crypto/dsa/dsa_asn1.c
+++ b/crypto/dsa/dsa_asn1.c
@@ -1,61 +1,25 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include "dsa_local.h"
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/rand.h>
-
-ASN1_SEQUENCE(DSA_SIG) = {
- ASN1_SIMPLE(DSA_SIG, r, CBIGNUM),
- ASN1_SIMPLE(DSA_SIG, s, CBIGNUM)
-} static_ASN1_SEQUENCE_END(DSA_SIG)
-
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA_SIG, DSA_SIG, DSA_SIG)
-
-DSA_SIG *DSA_SIG_new(void)
-{
- DSA_SIG *sig = OPENSSL_zalloc(sizeof(*sig));
- if (sig == NULL)
- DSAerr(DSA_F_DSA_SIG_NEW, ERR_R_MALLOC_FAILURE);
- return sig;
-}
-
-void DSA_SIG_free(DSA_SIG *sig)
-{
- if (sig == NULL)
- return;
- BN_clear_free(sig->r);
- BN_clear_free(sig->s);
- OPENSSL_free(sig);
-}
-
-void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
-{
- if (pr != NULL)
- *pr = sig->r;
- if (ps != NULL)
- *ps = sig->s;
-}
-
-int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
-{
- if (r == NULL || s == NULL)
- return 0;
- BN_clear_free(sig->r);
- BN_clear_free(sig->s);
- sig->r = r;
- sig->s = s;
- return 1;
-}
+#include "crypto/asn1_dsa.h"
/* Override the default free and new methods */
static int dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
@@ -76,80 +40,33 @@ static int dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
ASN1_SEQUENCE_cb(DSAPrivateKey, dsa_cb) = {
ASN1_EMBED(DSA, version, INT32),
- ASN1_SIMPLE(DSA, p, BIGNUM),
- ASN1_SIMPLE(DSA, q, BIGNUM),
- ASN1_SIMPLE(DSA, g, BIGNUM),
+ ASN1_SIMPLE(DSA, params.p, BIGNUM),
+ ASN1_SIMPLE(DSA, params.q, BIGNUM),
+ ASN1_SIMPLE(DSA, params.g, BIGNUM),
ASN1_SIMPLE(DSA, pub_key, BIGNUM),
ASN1_SIMPLE(DSA, priv_key, CBIGNUM)
} static_ASN1_SEQUENCE_END_cb(DSA, DSAPrivateKey)
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPrivateKey, DSAPrivateKey)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(DSA, DSAPrivateKey, DSAPrivateKey)
ASN1_SEQUENCE_cb(DSAparams, dsa_cb) = {
- ASN1_SIMPLE(DSA, p, BIGNUM),
- ASN1_SIMPLE(DSA, q, BIGNUM),
- ASN1_SIMPLE(DSA, g, BIGNUM),
+ ASN1_SIMPLE(DSA, params.p, BIGNUM),
+ ASN1_SIMPLE(DSA, params.q, BIGNUM),
+ ASN1_SIMPLE(DSA, params.g, BIGNUM),
} static_ASN1_SEQUENCE_END_cb(DSA, DSAparams)
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAparams, DSAparams)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(DSA, DSAparams, DSAparams)
ASN1_SEQUENCE_cb(DSAPublicKey, dsa_cb) = {
ASN1_SIMPLE(DSA, pub_key, BIGNUM),
- ASN1_SIMPLE(DSA, p, BIGNUM),
- ASN1_SIMPLE(DSA, q, BIGNUM),
- ASN1_SIMPLE(DSA, g, BIGNUM)
+ ASN1_SIMPLE(DSA, params.p, BIGNUM),
+ ASN1_SIMPLE(DSA, params.q, BIGNUM),
+ ASN1_SIMPLE(DSA, params.g, BIGNUM)
} static_ASN1_SEQUENCE_END_cb(DSA, DSAPublicKey)
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPublicKey, DSAPublicKey)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(DSA, DSAPublicKey, DSAPublicKey)
-DSA *DSAparams_dup(DSA *dsa)
+DSA *DSAparams_dup(const DSA *dsa)
{
return ASN1_item_dup(ASN1_ITEM_rptr(DSAparams), dsa);
}
-
-int DSA_sign(int type, const unsigned char *dgst, int dlen,
- unsigned char *sig, unsigned int *siglen, DSA *dsa)
-{
- DSA_SIG *s;
-
- s = DSA_do_sign(dgst, dlen, dsa);
- if (s == NULL) {
- *siglen = 0;
- return 0;
- }
- *siglen = i2d_DSA_SIG(s, &sig);
- DSA_SIG_free(s);
- return 1;
-}
-
-/* data has already been hashed (probably with SHA or SHA-1). */
-/*-
- * returns
- * 1: correct signature
- * 0: incorrect signature
- * -1: error
- */
-int DSA_verify(int type, const unsigned char *dgst, int dgst_len,
- const unsigned char *sigbuf, int siglen, DSA *dsa)
-{
- DSA_SIG *s;
- const unsigned char *p = sigbuf;
- unsigned char *der = NULL;
- int derlen = -1;
- int ret = -1;
-
- s = DSA_SIG_new();
- if (s == NULL)
- return ret;
- if (d2i_DSA_SIG(&s, &p, siglen) == NULL)
- goto err;
- /* Ensure signature uses DER and doesn't have trailing garbage */
- derlen = i2d_DSA_SIG(s, &der);
- if (derlen != siglen || memcmp(sigbuf, der, derlen))
- goto err;
- ret = DSA_do_verify(dgst, dgst_len, s, dsa);
- err:
- OPENSSL_clear_free(der, derlen);
- DSA_SIG_free(s);
- return ret;
-}
diff --git a/crypto/dsa/dsa_backend.c b/crypto/dsa/dsa_backend.c
new file mode 100644
index 000000000000..f9a71bdc9e0b
--- /dev/null
+++ b/crypto/dsa/dsa_backend.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/core_names.h>
+#include <openssl/err.h>
+#ifndef FIPS_MODULE
+# include <openssl/x509.h>
+#endif
+#include "crypto/dsa.h"
+#include "dsa_local.h"
+
+/*
+ * The intention with the "backend" source file is to offer backend support
+ * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
+ * implementations alike.
+ */
+
+int ossl_dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[],
+ int include_private)
+{
+ const OSSL_PARAM *param_priv_key = NULL, *param_pub_key;
+ BIGNUM *priv_key = NULL, *pub_key = NULL;
+
+ if (dsa == NULL)
+ return 0;
+
+ if (include_private) {
+ param_priv_key =
+ OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
+ }
+ param_pub_key =
+ OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
+
+ /* It's ok if neither half is present */
+ if (param_priv_key == NULL && param_pub_key == NULL)
+ return 1;
+
+ if (param_pub_key != NULL && !OSSL_PARAM_get_BN(param_pub_key, &pub_key))
+ goto err;
+ if (param_priv_key != NULL && !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
+ goto err;
+
+ if (!DSA_set0_key(dsa, pub_key, priv_key))
+ goto err;
+
+ return 1;
+
+ err:
+ BN_clear_free(priv_key);
+ BN_free(pub_key);
+ return 0;
+}
+
+int ossl_dsa_is_foreign(const DSA *dsa)
+{
+#ifndef FIPS_MODULE
+ if (dsa->engine != NULL || DSA_get_method((DSA *)dsa) != DSA_OpenSSL())
+ return 1;
+#endif
+ return 0;
+}
+
+static ossl_inline int dsa_bn_dup_check(BIGNUM **out, const BIGNUM *f)
+{
+ if (f != NULL && (*out = BN_dup(f)) == NULL)
+ return 0;
+ return 1;
+}
+
+DSA *ossl_dsa_dup(const DSA *dsa, int selection)
+{
+ DSA *dupkey = NULL;
+
+ /* Do not try to duplicate foreign DSA keys */
+ if (ossl_dsa_is_foreign(dsa))
+ return NULL;
+
+ if ((dupkey = ossl_dsa_new(dsa->libctx)) == NULL)
+ return NULL;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0
+ && !ossl_ffc_params_copy(&dupkey->params, &dsa->params))
+ goto err;
+
+ dupkey->flags = dsa->flags;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0
+ && ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0
+ || !dsa_bn_dup_check(&dupkey->pub_key, dsa->pub_key)))
+ goto err;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
+ && ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0
+ || !dsa_bn_dup_check(&dupkey->priv_key, dsa->priv_key)))
+ goto err;
+
+#ifndef FIPS_MODULE
+ if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_DSA,
+ &dupkey->ex_data, &dsa->ex_data))
+ goto err;
+#endif
+
+ return dupkey;
+
+ err:
+ DSA_free(dupkey);
+ return NULL;
+}
+
+#ifndef FIPS_MODULE
+DSA *ossl_dsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ const unsigned char *p, *pm;
+ int pklen, pmlen;
+ int ptype;
+ const void *pval;
+ const ASN1_STRING *pstr;
+ const X509_ALGOR *palg;
+ ASN1_INTEGER *privkey = NULL;
+ const BIGNUM *dsa_p, *dsa_g;
+ BIGNUM *dsa_pubkey = NULL, *dsa_privkey = NULL;
+ BN_CTX *ctx = NULL;
+
+ DSA *dsa = NULL;
+
+ if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8inf))
+ return 0;
+ X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+
+ if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL)
+ goto decerr;
+ if (privkey->type == V_ASN1_NEG_INTEGER || ptype != V_ASN1_SEQUENCE)
+ goto decerr;
+
+ pstr = pval;
+ pm = pstr->data;
+ pmlen = pstr->length;
+ if ((dsa = d2i_DSAparams(NULL, &pm, pmlen)) == NULL)
+ goto decerr;
+ /* We have parameters now set private key */
+ if ((dsa_privkey = BN_secure_new()) == NULL
+ || !ASN1_INTEGER_to_BN(privkey, dsa_privkey)) {
+ ERR_raise(ERR_LIB_DSA, DSA_R_BN_ERROR);
+ goto dsaerr;
+ }
+ /* Calculate public key */
+ if ((dsa_pubkey = BN_new()) == NULL) {
+ ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
+ goto dsaerr;
+ }
+ if ((ctx = BN_CTX_new()) == NULL) {
+ ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
+ goto dsaerr;
+ }
+
+ dsa_p = DSA_get0_p(dsa);
+ dsa_g = DSA_get0_g(dsa);
+ BN_set_flags(dsa_privkey, BN_FLG_CONSTTIME);
+ if (!BN_mod_exp(dsa_pubkey, dsa_g, dsa_privkey, dsa_p, ctx)) {
+ ERR_raise(ERR_LIB_DSA, DSA_R_BN_ERROR);
+ goto dsaerr;
+ }
+ DSA_set0_key(dsa, dsa_pubkey, dsa_privkey);
+
+ goto done;
+
+ decerr:
+ ERR_raise(ERR_LIB_DSA, DSA_R_DECODE_ERROR);
+ dsaerr:
+ BN_free(dsa_privkey);
+ BN_free(dsa_pubkey);
+ DSA_free(dsa);
+ dsa = NULL;
+ done:
+ BN_CTX_free(ctx);
+ ASN1_STRING_clear_free(privkey);
+ return dsa;
+}
+#endif
diff --git a/crypto/dsa/dsa_check.c b/crypto/dsa/dsa_check.c
new file mode 100644
index 000000000000..7ee914a477ec
--- /dev/null
+++ b/crypto/dsa/dsa_check.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/bn.h>
+#include "dsa_local.h"
+#include "crypto/dsa.h"
+
+int ossl_dsa_check_params(const DSA *dsa, int checktype, int *ret)
+{
+ if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)
+ return ossl_ffc_params_simple_validate(dsa->libctx, &dsa->params,
+ FFC_PARAM_TYPE_DSA, ret);
+ else
+ /*
+ * Do full FFC domain params validation according to FIPS-186-4
+ * - always in FIPS_MODULE
+ * - only if possible (i.e., seed is set) in default provider
+ */
+ return ossl_ffc_params_full_validate(dsa->libctx, &dsa->params,
+ FFC_PARAM_TYPE_DSA, ret);
+}
+
+/*
+ * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Full public key validation.
+ */
+int ossl_dsa_check_pub_key(const DSA *dsa, const BIGNUM *pub_key, int *ret)
+{
+ return ossl_ffc_validate_public_key(&dsa->params, pub_key, ret);
+}
+
+/*
+ * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Partial public key validation.
+ * To only be used with ephemeral FFC public keys generated using the approved
+ * safe-prime groups.
+ */
+int ossl_dsa_check_pub_key_partial(const DSA *dsa, const BIGNUM *pub_key, int *ret)
+{
+ return ossl_ffc_validate_public_key_partial(&dsa->params, pub_key, ret);
+}
+
+int ossl_dsa_check_priv_key(const DSA *dsa, const BIGNUM *priv_key, int *ret)
+{
+ *ret = 0;
+
+ return (dsa->params.q != NULL
+ && ossl_ffc_validate_private_key(dsa->params.q, priv_key, ret));
+}
+
+/*
+ * FFC pairwise check from SP800-56A R3.
+ * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency
+ */
+int ossl_dsa_check_pairwise(const DSA *dsa)
+{
+ int ret = 0;
+ BN_CTX *ctx = NULL;
+ BIGNUM *pub_key = NULL;
+
+ if (dsa->params.p == NULL
+ || dsa->params.g == NULL
+ || dsa->priv_key == NULL
+ || dsa->pub_key == NULL)
+ return 0;
+
+ ctx = BN_CTX_new_ex(dsa->libctx);
+ if (ctx == NULL)
+ goto err;
+ pub_key = BN_new();
+ if (pub_key == NULL)
+ goto err;
+
+ /* recalculate the public key = (g ^ priv) mod p */
+ if (!ossl_dsa_generate_public_key(ctx, dsa, dsa->priv_key, pub_key))
+ goto err;
+ /* check it matches the existing pubic_key */
+ ret = BN_cmp(pub_key, dsa->pub_key) == 0;
+err:
+ BN_free(pub_key);
+ BN_CTX_free(ctx);
+ return ret;
+}
diff --git a/crypto/dsa/dsa_depr.c b/crypto/dsa/dsa_depr.c
index f51aea74978a..95f8d1f3a9cb 100644
--- a/crypto/dsa/dsa_depr.c
+++ b/crypto/dsa/dsa_depr.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,24 +13,20 @@
*/
/*
- * Parameter generation follows the updated Appendix 2.2 for FIPS PUB 186,
- * also Appendix 2.2 of FIPS PUB 186-1 (i.e. use SHA as defined in FIPS PUB
- * 180-1)
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
*/
-#define xxxHASH EVP_sha1()
+#include "internal/deprecated.h"
#include <openssl/opensslconf.h>
-#if OPENSSL_API_COMPAT >= 0x00908000L
-NON_EMPTY_TRANSLATION_UNIT
-#else
-
-# include <stdio.h>
-# include <time.h>
-# include "internal/cryptlib.h"
-# include <openssl/evp.h>
-# include <openssl/bn.h>
-# include <openssl/dsa.h>
-# include <openssl/sha.h>
+
+#include <stdio.h>
+#include <time.h>
+#include "internal/cryptlib.h"
+#include <openssl/evp.h>
+#include <openssl/bn.h>
+#include <openssl/dsa.h>
+#include <openssl/sha.h>
DSA *DSA_generate_parameters(int bits,
unsigned char *seed_in, int seed_len,
@@ -59,4 +55,3 @@ err:
DSA_free(ret);
return NULL;
}
-#endif
diff --git a/crypto/dsa/dsa_err.c b/crypto/dsa/dsa_err.c
index 8dcf0548ac76..5685d5e83eb3 100644
--- a/crypto/dsa/dsa_err.c
+++ b/crypto/dsa/dsa_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,40 +10,14 @@
#include <openssl/err.h>
#include <openssl/dsaerr.h>
+#include "crypto/dsaerr.h"
-#ifndef OPENSSL_NO_ERR
+#ifndef OPENSSL_NO_DSA
-static const ERR_STRING_DATA DSA_str_functs[] = {
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSAPARAMS_PRINT, 0), "DSAparams_print"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSAPARAMS_PRINT_FP, 0), "DSAparams_print_fp"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_BUILTIN_PARAMGEN, 0),
- "dsa_builtin_paramgen"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_BUILTIN_PARAMGEN2, 0),
- "dsa_builtin_paramgen2"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_DO_SIGN, 0), "DSA_do_sign"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_DO_VERIFY, 0), "DSA_do_verify"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_METH_DUP, 0), "DSA_meth_dup"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_METH_NEW, 0), "DSA_meth_new"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_METH_SET1_NAME, 0), "DSA_meth_set1_name"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_NEW_METHOD, 0), "DSA_new_method"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_PARAM_DECODE, 0), "dsa_param_decode"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_PRINT_FP, 0), "DSA_print_fp"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_PRIV_DECODE, 0), "dsa_priv_decode"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_PRIV_ENCODE, 0), "dsa_priv_encode"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_PUB_DECODE, 0), "dsa_pub_decode"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_PUB_ENCODE, 0), "dsa_pub_encode"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_SIGN, 0), "DSA_sign"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_SIGN_SETUP, 0), "DSA_sign_setup"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_SIG_NEW, 0), "DSA_SIG_new"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_OLD_DSA_PRIV_DECODE, 0),
- "old_dsa_priv_decode"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_PKEY_DSA_CTRL, 0), "pkey_dsa_ctrl"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_PKEY_DSA_CTRL_STR, 0), "pkey_dsa_ctrl_str"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_PKEY_DSA_KEYGEN, 0), "pkey_dsa_keygen"},
- {0, NULL}
-};
+# ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA DSA_str_reasons[] = {
+ {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_BAD_FFC_PARAMETERS), "bad ffc parameters"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_BAD_Q_VALUE), "bad q value"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_BN_DECODE_ERROR), "bn decode error"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_BN_ERROR), "bn error"},
@@ -58,21 +32,23 @@ static const ERR_STRING_DATA DSA_str_reasons[] = {
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_NO_PARAMETERS_SET), "no parameters set"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_PARAMETER_ENCODING_ERROR),
"parameter encoding error"},
+ {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_P_NOT_PRIME), "p not prime"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_Q_NOT_PRIME), "q not prime"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_SEED_LEN_SMALL),
"seed_len is less than the length of q"},
{0, NULL}
};
-#endif
+# endif
-int ERR_load_DSA_strings(void)
+int ossl_err_load_DSA_strings(void)
{
-#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(DSA_str_functs[0].error) == NULL) {
- ERR_load_strings_const(DSA_str_functs);
+# ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(DSA_str_reasons[0].error) == NULL)
ERR_load_strings_const(DSA_str_reasons);
- }
-#endif
+# endif
return 1;
}
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c
index 5d066a06c546..a45092141281 100644
--- a/crypto/dsa/dsa_gen.c
+++ b/crypto/dsa/dsa_gen.c
@@ -1,18 +1,17 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
- * Parameter generation follows the updated Appendix 2.2 for FIPS PUB 186,
- * also Appendix 2.2 of FIPS PUB 186-1 (i.e. use SHA as defined in FIPS PUB
- * 180-1)
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
*/
-#define xxxHASH EVP_sha1()
+#include "internal/deprecated.h"
#include <openssl/opensslconf.h>
#include <stdio.h>
@@ -21,594 +20,58 @@
#include <openssl/bn.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
+#include "crypto/dsa.h"
#include "dsa_local.h"
-int DSA_generate_parameters_ex(DSA *ret, int bits,
+int ossl_dsa_generate_ffc_parameters(DSA *dsa, int type, int pbits, int qbits,
+ BN_GENCB *cb)
+{
+ int ret = 0, res;
+
+#ifndef FIPS_MODULE
+ if (type == DSA_PARAMGEN_TYPE_FIPS_186_2)
+ ret = ossl_ffc_params_FIPS186_2_generate(dsa->libctx, &dsa->params,
+ FFC_PARAM_TYPE_DSA,
+ pbits, qbits, &res, cb);
+ else
+#endif
+ ret = ossl_ffc_params_FIPS186_4_generate(dsa->libctx, &dsa->params,
+ FFC_PARAM_TYPE_DSA,
+ pbits, qbits, &res, cb);
+ if (ret > 0)
+ dsa->dirty_cnt++;
+ return ret;
+}
+
+#ifndef FIPS_MODULE
+int DSA_generate_parameters_ex(DSA *dsa, int bits,
const unsigned char *seed_in, int seed_len,
int *counter_ret, unsigned long *h_ret,
BN_GENCB *cb)
{
- if (ret->meth->dsa_paramgen)
- return ret->meth->dsa_paramgen(ret, bits, seed_in, seed_len,
+ if (dsa->meth->dsa_paramgen)
+ return dsa->meth->dsa_paramgen(dsa, bits, seed_in, seed_len,
counter_ret, h_ret, cb);
- else {
- const EVP_MD *evpmd = bits >= 2048 ? EVP_sha256() : EVP_sha1();
- size_t qbits = EVP_MD_size(evpmd) * 8;
-
- return dsa_builtin_paramgen(ret, bits, qbits, evpmd,
- seed_in, seed_len, NULL, counter_ret,
- h_ret, cb);
- }
-}
-
-int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
- const EVP_MD *evpmd, const unsigned char *seed_in,
- size_t seed_len, unsigned char *seed_out,
- int *counter_ret, unsigned long *h_ret, BN_GENCB *cb)
-{
- int ok = 0;
- unsigned char seed[SHA256_DIGEST_LENGTH];
- unsigned char md[SHA256_DIGEST_LENGTH];
- unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH];
- BIGNUM *r0, *W, *X, *c, *test;
- BIGNUM *g = NULL, *q = NULL, *p = NULL;
- BN_MONT_CTX *mont = NULL;
- int i, k, n = 0, m = 0, qsize = qbits >> 3;
- int counter = 0;
- int r = 0;
- BN_CTX *ctx = NULL;
- unsigned int h = 2;
-
- if (qsize != SHA_DIGEST_LENGTH && qsize != SHA224_DIGEST_LENGTH &&
- qsize != SHA256_DIGEST_LENGTH)
- /* invalid q size */
+ if (seed_in != NULL
+ && !ossl_ffc_params_set_validate_params(&dsa->params, seed_in, seed_len,
+ -1))
return 0;
- if (evpmd == NULL) {
- if (qsize == SHA_DIGEST_LENGTH)
- evpmd = EVP_sha1();
- else if (qsize == SHA224_DIGEST_LENGTH)
- evpmd = EVP_sha224();
- else
- evpmd = EVP_sha256();
- } else {
- qsize = EVP_MD_size(evpmd);
- }
-
- if (bits < 512)
- bits = 512;
-
- bits = (bits + 63) / 64 * 64;
-
- if (seed_in != NULL) {
- if (seed_len < (size_t)qsize) {
- DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN, DSA_R_SEED_LEN_SMALL);
+ /* The old code used FIPS 186-2 DSA Parameter generation */
+ if (bits < 2048 && seed_len <= 20) {
+ if (!ossl_dsa_generate_ffc_parameters(dsa, DSA_PARAMGEN_TYPE_FIPS_186_2,
+ bits, 160, cb))
return 0;
- }
- if (seed_len > (size_t)qsize) {
- /* Only consume as much seed as is expected. */
- seed_len = qsize;
- }
- memcpy(seed, seed_in, seed_len);
- }
-
- if ((mont = BN_MONT_CTX_new()) == NULL)
- goto err;
-
- if ((ctx = BN_CTX_new()) == NULL)
- goto err;
-
- BN_CTX_start(ctx);
-
- r0 = BN_CTX_get(ctx);
- g = BN_CTX_get(ctx);
- W = BN_CTX_get(ctx);
- q = BN_CTX_get(ctx);
- X = BN_CTX_get(ctx);
- c = BN_CTX_get(ctx);
- p = BN_CTX_get(ctx);
- test = BN_CTX_get(ctx);
-
- if (test == NULL)
- goto err;
-
- if (!BN_lshift(test, BN_value_one(), bits - 1))
- goto err;
-
- for (;;) {
- for (;;) { /* find q */
- int use_random_seed = (seed_in == NULL);
-
- /* step 1 */
- if (!BN_GENCB_call(cb, 0, m++))
- goto err;
-
- if (use_random_seed) {
- if (RAND_bytes(seed, qsize) <= 0)
- goto err;
- } else {
- /* If we come back through, use random seed next time. */
- seed_in = NULL;
- }
- memcpy(buf, seed, qsize);
- memcpy(buf2, seed, qsize);
- /* precompute "SEED + 1" for step 7: */
- for (i = qsize - 1; i >= 0; i--) {
- buf[i]++;
- if (buf[i] != 0)
- break;
- }
-
- /* step 2 */
- if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL))
- goto err;
- if (!EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL))
- goto err;
- for (i = 0; i < qsize; i++)
- md[i] ^= buf2[i];
-
- /* step 3 */
- md[0] |= 0x80;
- md[qsize - 1] |= 0x01;
- if (!BN_bin2bn(md, qsize, q))
- goto err;
-
- /* step 4 */
- r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx,
- use_random_seed, cb);
- if (r > 0)
- break;
- if (r != 0)
- goto err;
-
- /* do a callback call */
- /* step 5 */
- }
-
- if (!BN_GENCB_call(cb, 2, 0))
- goto err;
- if (!BN_GENCB_call(cb, 3, 0))
- goto err;
-
- /* step 6 */
- counter = 0;
- /* "offset = 2" */
-
- n = (bits - 1) / 160;
-
- for (;;) {
- if ((counter != 0) && !BN_GENCB_call(cb, 0, counter))
- goto err;
-
- /* step 7 */
- BN_zero(W);
- /* now 'buf' contains "SEED + offset - 1" */
- for (k = 0; k <= n; k++) {
- /*
- * obtain "SEED + offset + k" by incrementing:
- */
- for (i = qsize - 1; i >= 0; i--) {
- buf[i]++;
- if (buf[i] != 0)
- break;
- }
-
- if (!EVP_Digest(buf, qsize, md, NULL, evpmd, NULL))
- goto err;
-
- /* step 8 */
- if (!BN_bin2bn(md, qsize, r0))
- goto err;
- if (!BN_lshift(r0, r0, (qsize << 3) * k))
- goto err;
- if (!BN_add(W, W, r0))
- goto err;
- }
-
- /* more of step 8 */
- if (!BN_mask_bits(W, bits - 1))
- goto err;
- if (!BN_copy(X, W))
- goto err;
- if (!BN_add(X, X, test))
- goto err;
-
- /* step 9 */
- if (!BN_lshift1(r0, q))
- goto err;
- if (!BN_mod(c, X, r0, ctx))
- goto err;
- if (!BN_sub(r0, c, BN_value_one()))
- goto err;
- if (!BN_sub(p, X, r0))
- goto err;
-
- /* step 10 */
- if (BN_cmp(p, test) >= 0) {
- /* step 11 */
- r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb);
- if (r > 0)
- goto end; /* found it */
- if (r != 0)
- goto err;
- }
-
- /* step 13 */
- counter++;
- /* "offset = offset + n + 1" */
-
- /* step 14 */
- if (counter >= 4096)
- break;
- }
- }
- end:
- if (!BN_GENCB_call(cb, 2, 1))
- goto err;
-
- /* We now need to generate g */
- /* Set r0=(p-1)/q */
- if (!BN_sub(test, p, BN_value_one()))
- goto err;
- if (!BN_div(r0, NULL, test, q, ctx))
- goto err;
-
- if (!BN_set_word(test, h))
- goto err;
- if (!BN_MONT_CTX_set(mont, p, ctx))
- goto err;
-
- for (;;) {
- /* g=test^r0%p */
- if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont))
- goto err;
- if (!BN_is_one(g))
- break;
- if (!BN_add(test, test, BN_value_one()))
- goto err;
- h++;
- }
-
- if (!BN_GENCB_call(cb, 3, 1))
- goto err;
-
- ok = 1;
- err:
- if (ok) {
- BN_free(ret->p);
- BN_free(ret->q);
- BN_free(ret->g);
- ret->p = BN_dup(p);
- ret->q = BN_dup(q);
- ret->g = BN_dup(g);
- if (ret->p == NULL || ret->q == NULL || ret->g == NULL) {
- ok = 0;
- goto err;
- }
- if (counter_ret != NULL)
- *counter_ret = counter;
- if (h_ret != NULL)
- *h_ret = h;
- if (seed_out)
- memcpy(seed_out, seed, qsize);
- }
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- BN_MONT_CTX_free(mont);
- return ok;
-}
-
-/*
- * This is a parameter generation algorithm for the DSA2 algorithm as
- * described in FIPS 186-3.
- */
-
-int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
- const EVP_MD *evpmd, const unsigned char *seed_in,
- size_t seed_len, int idx, unsigned char *seed_out,
- int *counter_ret, unsigned long *h_ret,
- BN_GENCB *cb)
-{
- int ok = -1;
- unsigned char *seed = NULL, *seed_tmp = NULL;
- unsigned char md[EVP_MAX_MD_SIZE];
- int mdsize;
- BIGNUM *r0, *W, *X, *c, *test;
- BIGNUM *g = NULL, *q = NULL, *p = NULL;
- BN_MONT_CTX *mont = NULL;
- int i, k, n = 0, m = 0, qsize = N >> 3;
- int counter = 0;
- int r = 0;
- BN_CTX *ctx = NULL;
- EVP_MD_CTX *mctx = EVP_MD_CTX_new();
- unsigned int h = 2;
-
- if (mctx == NULL)
- goto err;
-
- /* make sure L > N, otherwise we'll get trapped in an infinite loop */
- if (L <= N) {
- DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_INVALID_PARAMETERS);
- goto err;
- }
-
- if (evpmd == NULL) {
- if (N == 160)
- evpmd = EVP_sha1();
- else if (N == 224)
- evpmd = EVP_sha224();
- else
- evpmd = EVP_sha256();
- }
-
- mdsize = EVP_MD_size(evpmd);
- /* If unverifiable g generation only don't need seed */
- if (!ret->p || !ret->q || idx >= 0) {
- if (seed_len == 0)
- seed_len = mdsize;
-
- seed = OPENSSL_malloc(seed_len);
-
- if (seed_out)
- seed_tmp = seed_out;
- else
- seed_tmp = OPENSSL_malloc(seed_len);
-
- if (seed == NULL || seed_tmp == NULL)
- goto err;
-
- if (seed_in)
- memcpy(seed, seed_in, seed_len);
-
- }
-
- if ((ctx = BN_CTX_new()) == NULL)
- goto err;
-
- if ((mont = BN_MONT_CTX_new()) == NULL)
- goto err;
-
- BN_CTX_start(ctx);
- r0 = BN_CTX_get(ctx);
- g = BN_CTX_get(ctx);
- W = BN_CTX_get(ctx);
- X = BN_CTX_get(ctx);
- c = BN_CTX_get(ctx);
- test = BN_CTX_get(ctx);
- if (test == NULL)
- goto err;
-
- /* if p, q already supplied generate g only */
- if (ret->p && ret->q) {
- p = ret->p;
- q = ret->q;
- if (idx >= 0)
- memcpy(seed_tmp, seed, seed_len);
- goto g_only;
} else {
- p = BN_CTX_get(ctx);
- q = BN_CTX_get(ctx);
- if (q == NULL)
- goto err;
- }
-
- if (!BN_lshift(test, BN_value_one(), L - 1))
- goto err;
- for (;;) {
- for (;;) { /* find q */
- unsigned char *pmd;
- /* step 1 */
- if (!BN_GENCB_call(cb, 0, m++))
- goto err;
-
- if (!seed_in) {
- if (RAND_bytes(seed, seed_len) <= 0)
- goto err;
- }
- /* step 2 */
- if (!EVP_Digest(seed, seed_len, md, NULL, evpmd, NULL))
- goto err;
- /* Take least significant bits of md */
- if (mdsize > qsize)
- pmd = md + mdsize - qsize;
- else
- pmd = md;
-
- if (mdsize < qsize)
- memset(md + mdsize, 0, qsize - mdsize);
-
- /* step 3 */
- pmd[0] |= 0x80;
- pmd[qsize - 1] |= 0x01;
- if (!BN_bin2bn(pmd, qsize, q))
- goto err;
-
- /* step 4 */
- r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx,
- seed_in ? 1 : 0, cb);
- if (r > 0)
- break;
- if (r != 0)
- goto err;
- /* Provided seed didn't produce a prime: error */
- if (seed_in) {
- ok = 0;
- DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_Q_NOT_PRIME);
- goto err;
- }
-
- /* do a callback call */
- /* step 5 */
- }
- /* Copy seed to seed_out before we mess with it */
- if (seed_out)
- memcpy(seed_out, seed, seed_len);
-
- if (!BN_GENCB_call(cb, 2, 0))
- goto err;
- if (!BN_GENCB_call(cb, 3, 0))
- goto err;
-
- /* step 6 */
- counter = 0;
- /* "offset = 1" */
-
- n = (L - 1) / (mdsize << 3);
-
- for (;;) {
- if ((counter != 0) && !BN_GENCB_call(cb, 0, counter))
- goto err;
-
- /* step 7 */
- BN_zero(W);
- /* now 'buf' contains "SEED + offset - 1" */
- for (k = 0; k <= n; k++) {
- /*
- * obtain "SEED + offset + k" by incrementing:
- */
- for (i = seed_len - 1; i >= 0; i--) {
- seed[i]++;
- if (seed[i] != 0)
- break;
- }
-
- if (!EVP_Digest(seed, seed_len, md, NULL, evpmd, NULL))
- goto err;
-
- /* step 8 */
- if (!BN_bin2bn(md, mdsize, r0))
- goto err;
- if (!BN_lshift(r0, r0, (mdsize << 3) * k))
- goto err;
- if (!BN_add(W, W, r0))
- goto err;
- }
-
- /* more of step 8 */
- if (!BN_mask_bits(W, L - 1))
- goto err;
- if (!BN_copy(X, W))
- goto err;
- if (!BN_add(X, X, test))
- goto err;
-
- /* step 9 */
- if (!BN_lshift1(r0, q))
- goto err;
- if (!BN_mod(c, X, r0, ctx))
- goto err;
- if (!BN_sub(r0, c, BN_value_one()))
- goto err;
- if (!BN_sub(p, X, r0))
- goto err;
-
- /* step 10 */
- if (BN_cmp(p, test) >= 0) {
- /* step 11 */
- r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb);
- if (r > 0)
- goto end; /* found it */
- if (r != 0)
- goto err;
- }
-
- /* step 13 */
- counter++;
- /* "offset = offset + n + 1" */
-
- /* step 14 */
- if (counter >= (int)(4 * L))
- break;
- }
- if (seed_in) {
- ok = 0;
- DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_INVALID_PARAMETERS);
- goto err;
- }
- }
- end:
- if (!BN_GENCB_call(cb, 2, 1))
- goto err;
-
- g_only:
-
- /* We now need to generate g */
- /* Set r0=(p-1)/q */
- if (!BN_sub(test, p, BN_value_one()))
- goto err;
- if (!BN_div(r0, NULL, test, q, ctx))
- goto err;
-
- if (idx < 0) {
- if (!BN_set_word(test, h))
- goto err;
- } else
- h = 1;
- if (!BN_MONT_CTX_set(mont, p, ctx))
- goto err;
-
- for (;;) {
- static const unsigned char ggen[4] = { 0x67, 0x67, 0x65, 0x6e };
- if (idx >= 0) {
- md[0] = idx & 0xff;
- md[1] = (h >> 8) & 0xff;
- md[2] = h & 0xff;
- if (!EVP_DigestInit_ex(mctx, evpmd, NULL))
- goto err;
- if (!EVP_DigestUpdate(mctx, seed_tmp, seed_len))
- goto err;
- if (!EVP_DigestUpdate(mctx, ggen, sizeof(ggen)))
- goto err;
- if (!EVP_DigestUpdate(mctx, md, 3))
- goto err;
- if (!EVP_DigestFinal_ex(mctx, md, NULL))
- goto err;
- if (!BN_bin2bn(md, mdsize, test))
- goto err;
- }
- /* g=test^r0%p */
- if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont))
- goto err;
- if (!BN_is_one(g))
- break;
- if (idx < 0 && !BN_add(test, test, BN_value_one()))
- goto err;
- h++;
- if (idx >= 0 && h > 0xffff)
- goto err;
+ if (!ossl_dsa_generate_ffc_parameters(dsa, DSA_PARAMGEN_TYPE_FIPS_186_4,
+ bits, 0, cb))
+ return 0;
}
- if (!BN_GENCB_call(cb, 3, 1))
- goto err;
-
- ok = 1;
- err:
- if (ok == 1) {
- if (p != ret->p) {
- BN_free(ret->p);
- ret->p = BN_dup(p);
- }
- if (q != ret->q) {
- BN_free(ret->q);
- ret->q = BN_dup(q);
- }
- BN_free(ret->g);
- ret->g = BN_dup(g);
- if (ret->p == NULL || ret->q == NULL || ret->g == NULL) {
- ok = -1;
- goto err;
- }
- if (counter_ret != NULL)
- *counter_ret = counter;
- if (h_ret != NULL)
- *h_ret = h;
- }
- OPENSSL_free(seed);
- if (seed_out != seed_tmp)
- OPENSSL_free(seed_tmp);
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- BN_MONT_CTX_free(mont);
- EVP_MD_CTX_free(mctx);
- return ok;
+ if (counter_ret != NULL)
+ *counter_ret = dsa->params.pcounter;
+ if (h_ret != NULL)
+ *h_ret = dsa->params.h;
+ return 1;
}
+#endif
diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c
index bdeddd4f61df..1f951a9d36a9 100644
--- a/crypto/dsa/dsa_key.c
+++ b/crypto/dsa/dsa_key.c
@@ -1,71 +1,130 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <time.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
+#include <openssl/self_test.h>
+#include "prov/providercommon.h"
+#include "crypto/dsa.h"
#include "dsa_local.h"
-static int dsa_builtin_keygen(DSA *dsa);
+#ifdef FIPS_MODULE
+# define MIN_STRENGTH 112
+#else
+# define MIN_STRENGTH 80
+#endif
+
+static int dsa_keygen(DSA *dsa, int pairwise_test);
+static int dsa_keygen_pairwise_test(DSA *dsa, OSSL_CALLBACK *cb, void *cbarg);
int DSA_generate_key(DSA *dsa)
{
- if (dsa->meth->dsa_keygen)
+#ifndef FIPS_MODULE
+ if (dsa->meth->dsa_keygen != NULL)
return dsa->meth->dsa_keygen(dsa);
- return dsa_builtin_keygen(dsa);
+#endif
+ return dsa_keygen(dsa, 0);
}
-static int dsa_builtin_keygen(DSA *dsa)
+int ossl_dsa_generate_public_key(BN_CTX *ctx, const DSA *dsa,
+ const BIGNUM *priv_key, BIGNUM *pub_key)
+{
+ int ret = 0;
+ BIGNUM *prk = BN_new();
+
+ if (prk == NULL)
+ return 0;
+ BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
+
+ /* pub_key = g ^ priv_key mod p */
+ if (!BN_mod_exp(pub_key, dsa->params.g, prk, dsa->params.p, ctx))
+ goto err;
+ ret = 1;
+err:
+ BN_clear_free(prk);
+ return ret;
+}
+
+static int dsa_keygen(DSA *dsa, int pairwise_test)
{
int ok = 0;
BN_CTX *ctx = NULL;
BIGNUM *pub_key = NULL, *priv_key = NULL;
- if ((ctx = BN_CTX_new()) == NULL)
+ if ((ctx = BN_CTX_new_ex(dsa->libctx)) == NULL)
goto err;
if (dsa->priv_key == NULL) {
if ((priv_key = BN_secure_new()) == NULL)
goto err;
- } else
+ } else {
priv_key = dsa->priv_key;
+ }
- do
- if (!BN_priv_rand_range(priv_key, dsa->q))
- goto err;
- while (BN_is_zero(priv_key)) ;
+ /* Do a partial check for invalid p, q, g */
+ if (!ossl_ffc_params_simple_validate(dsa->libctx, &dsa->params,
+ FFC_PARAM_TYPE_DSA, NULL))
+ goto err;
+
+ /*
+ * For FFC FIPS 186-4 keygen
+ * security strength s = 112,
+ * Max Private key size N = len(q)
+ */
+ if (!ossl_ffc_generate_private_key(ctx, &dsa->params,
+ BN_num_bits(dsa->params.q),
+ MIN_STRENGTH, priv_key))
+ goto err;
if (dsa->pub_key == NULL) {
if ((pub_key = BN_new()) == NULL)
goto err;
- } else
+ } else {
pub_key = dsa->pub_key;
-
- {
- BIGNUM *prk = BN_new();
-
- if (prk == NULL)
- goto err;
- BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
-
- if (!BN_mod_exp(pub_key, dsa->g, prk, dsa->p, ctx)) {
- BN_free(prk);
- goto err;
- }
- /* We MUST free prk before any further use of priv_key */
- BN_free(prk);
}
+ if (!ossl_dsa_generate_public_key(ctx, dsa, priv_key, pub_key))
+ goto err;
+
dsa->priv_key = priv_key;
dsa->pub_key = pub_key;
+
+#ifdef FIPS_MODULE
+ pairwise_test = 1;
+#endif /* FIPS_MODULE */
+
ok = 1;
+ if (pairwise_test) {
+ OSSL_CALLBACK *cb = NULL;
+ void *cbarg = NULL;
+
+ OSSL_SELF_TEST_get_callback(dsa->libctx, &cb, &cbarg);
+ ok = dsa_keygen_pairwise_test(dsa, cb, cbarg);
+ if (!ok) {
+ ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
+ BN_free(dsa->pub_key);
+ BN_clear_free(dsa->priv_key);
+ dsa->pub_key = NULL;
+ dsa->priv_key = NULL;
+ BN_CTX_free(ctx);
+ return ok;
+ }
+ }
+ dsa->dirty_cnt++;
err:
if (pub_key != dsa->pub_key)
@@ -73,5 +132,42 @@ static int dsa_builtin_keygen(DSA *dsa)
if (priv_key != dsa->priv_key)
BN_free(priv_key);
BN_CTX_free(ctx);
+
return ok;
}
+
+/*
+ * FIPS 140-2 IG 9.9 AS09.33
+ * Perform a sign/verify operation.
+ */
+static int dsa_keygen_pairwise_test(DSA *dsa, OSSL_CALLBACK *cb, void *cbarg)
+{
+ int ret = 0;
+ unsigned char dgst[16] = {0};
+ unsigned int dgst_len = (unsigned int)sizeof(dgst);
+ DSA_SIG *sig = NULL;
+ OSSL_SELF_TEST *st = NULL;
+
+ st = OSSL_SELF_TEST_new(cb, cbarg);
+ if (st == NULL)
+ goto err;
+
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
+ OSSL_SELF_TEST_DESC_PCT_DSA);
+
+ sig = DSA_do_sign(dgst, (int)dgst_len, dsa);
+ if (sig == NULL)
+ goto err;
+
+ OSSL_SELF_TEST_oncorrupt_byte(st, dgst);
+
+ if (DSA_do_verify(dgst, dgst_len, sig, dsa) != 1)
+ goto err;
+
+ ret = 1;
+err:
+ OSSL_SELF_TEST_onend(st, ret);
+ OSSL_SELF_TEST_free(st);
+ DSA_SIG_free(sig);
+ return ret;
+}
diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c
index f98af5853dc1..ccc701659217 100644
--- a/crypto/dsa/dsa_lib.c
+++ b/crypto/dsa/dsa_lib.c
@@ -1,24 +1,106 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <stdio.h>
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/bn.h>
+#ifndef FIPS_MODULE
+# include <openssl/engine.h>
+#endif
#include "internal/cryptlib.h"
#include "internal/refcount.h"
-#include <openssl/bn.h>
+#include "crypto/dsa.h"
+#include "crypto/dh.h" /* required by DSA_dup_DH() */
#include "dsa_local.h"
-#include <openssl/asn1.h>
-#include <openssl/engine.h>
-#include <openssl/dh.h>
-DSA *DSA_new(void)
+static DSA *dsa_new_intern(ENGINE *engine, OSSL_LIB_CTX *libctx);
+
+#ifndef FIPS_MODULE
+
+int DSA_set_ex_data(DSA *d, int idx, void *arg)
+{
+ return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
+}
+
+void *DSA_get_ex_data(const DSA *d, int idx)
+{
+ return CRYPTO_get_ex_data(&d->ex_data, idx);
+}
+
+# ifndef OPENSSL_NO_DH
+DH *DSA_dup_DH(const DSA *r)
+{
+ /*
+ * DSA has p, q, g, optional pub_key, optional priv_key.
+ * DH has p, optional length, g, optional pub_key,
+ * optional priv_key, optional q.
+ */
+ DH *ret = NULL;
+ BIGNUM *pub_key = NULL, *priv_key = NULL;
+
+ if (r == NULL)
+ goto err;
+ ret = DH_new();
+ if (ret == NULL)
+ goto err;
+
+ if (!ossl_ffc_params_copy(ossl_dh_get0_params(ret), &r->params))
+ goto err;
+
+ if (r->pub_key != NULL) {
+ pub_key = BN_dup(r->pub_key);
+ if (pub_key == NULL)
+ goto err;
+ if (r->priv_key != NULL) {
+ priv_key = BN_dup(r->priv_key);
+ if (priv_key == NULL)
+ goto err;
+ }
+ if (!DH_set0_key(ret, pub_key, priv_key))
+ goto err;
+ } else if (r->priv_key != NULL) {
+ /* Shouldn't happen */
+ goto err;
+ }
+
+ return ret;
+
+ err:
+ BN_free(pub_key);
+ BN_free(priv_key);
+ DH_free(ret);
+ return NULL;
+}
+# endif /* OPENSSL_NO_DH */
+
+void DSA_clear_flags(DSA *d, int flags)
+{
+ d->flags &= ~flags;
+}
+
+int DSA_test_flags(const DSA *d, int flags)
{
- return DSA_new_method(NULL);
+ return d->flags & flags;
+}
+
+void DSA_set_flags(DSA *d, int flags)
+{
+ d->flags |= flags;
+}
+
+ENGINE *DSA_get0_engine(DSA *d)
+{
+ return d->engine;
}
int DSA_set_method(DSA *dsa, const DSA_METHOD *meth)
@@ -40,35 +122,38 @@ int DSA_set_method(DSA *dsa, const DSA_METHOD *meth)
meth->init(dsa);
return 1;
}
+#endif /* FIPS_MODULE */
+
const DSA_METHOD *DSA_get_method(DSA *d)
{
return d->meth;
}
-DSA *DSA_new_method(ENGINE *engine)
+static DSA *dsa_new_intern(ENGINE *engine, OSSL_LIB_CTX *libctx)
{
DSA *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->references = 1;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
- DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
+ ret->libctx = libctx;
ret->meth = DSA_get_default_method();
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
ret->flags = ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW; /* early default init */
if (engine) {
if (!ENGINE_init(engine)) {
- DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_ENGINE_LIB);
+ ERR_raise(ERR_LIB_DSA, ERR_R_ENGINE_LIB);
goto err;
}
ret->engine = engine;
@@ -77,7 +162,7 @@ DSA *DSA_new_method(ENGINE *engine)
if (ret->engine) {
ret->meth = ENGINE_get_DSA(ret->engine);
if (ret->meth == NULL) {
- DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_ENGINE_LIB);
+ ERR_raise(ERR_LIB_DSA, ERR_R_ENGINE_LIB);
goto err;
}
}
@@ -85,11 +170,14 @@ DSA *DSA_new_method(ENGINE *engine)
ret->flags = ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW;
- if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data))
+#ifndef FIPS_MODULE
+ if (!ossl_crypto_new_ex_data_ex(libctx, CRYPTO_EX_INDEX_DSA, ret,
+ &ret->ex_data))
goto err;
+#endif
if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
- DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_INIT_FAIL);
+ ERR_raise(ERR_LIB_DSA, ERR_R_INIT_FAIL);
goto err;
}
@@ -100,6 +188,23 @@ DSA *DSA_new_method(ENGINE *engine)
return NULL;
}
+DSA *DSA_new_method(ENGINE *engine)
+{
+ return dsa_new_intern(engine, NULL);
+}
+
+DSA *ossl_dsa_new(OSSL_LIB_CTX *libctx)
+{
+ return dsa_new_intern(NULL, libctx);
+}
+
+#ifndef FIPS_MODULE
+DSA *DSA_new(void)
+{
+ return dsa_new_intern(NULL, NULL);
+}
+#endif
+
void DSA_free(DSA *r)
{
int i;
@@ -115,17 +220,17 @@ void DSA_free(DSA *r)
if (r->meth != NULL && r->meth->finish != NULL)
r->meth->finish(r);
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
ENGINE_finish(r->engine);
#endif
+#ifndef FIPS_MODULE
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, r, &r->ex_data);
+#endif
CRYPTO_THREAD_lock_free(r->lock);
- BN_clear_free(r->p);
- BN_clear_free(r->q);
- BN_clear_free(r->g);
+ ossl_ffc_params_cleanup(&r->params);
BN_clear_free(r->pub_key);
BN_clear_free(r->priv_key);
OPENSSL_free(r);
@@ -143,138 +248,56 @@ int DSA_up_ref(DSA *r)
return ((i > 1) ? 1 : 0);
}
-int DSA_size(const DSA *r)
+void ossl_dsa_set0_libctx(DSA *d, OSSL_LIB_CTX *libctx)
{
- int ret, i;
- ASN1_INTEGER bs;
- unsigned char buf[4]; /* 4 bytes looks really small. However,
- * i2d_ASN1_INTEGER() will not look beyond
- * the first byte, as long as the second
- * parameter is NULL. */
-
- i = BN_num_bits(r->q);
- bs.length = (i + 7) / 8;
- bs.data = buf;
- bs.type = V_ASN1_INTEGER;
- /* If the top bit is set the asn1 encoding is 1 larger. */
- buf[0] = 0xff;
-
- i = i2d_ASN1_INTEGER(&bs, NULL);
- i += i; /* r and s */
- ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE);
- return ret;
+ d->libctx = libctx;
}
-int DSA_set_ex_data(DSA *d, int idx, void *arg)
+void DSA_get0_pqg(const DSA *d,
+ const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
{
- return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
+ ossl_ffc_params_get0_pqg(&d->params, p, q, g);
}
-void *DSA_get_ex_data(DSA *d, int idx)
+int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
{
- return CRYPTO_get_ex_data(&d->ex_data, idx);
+ /* If the fields p, q and g in d are NULL, the corresponding input
+ * parameters MUST be non-NULL.
+ */
+ if ((d->params.p == NULL && p == NULL)
+ || (d->params.q == NULL && q == NULL)
+ || (d->params.g == NULL && g == NULL))
+ return 0;
+
+ ossl_ffc_params_set0_pqg(&d->params, p, q, g);
+ d->dirty_cnt++;
+
+ return 1;
}
-int DSA_security_bits(const DSA *d)
+const BIGNUM *DSA_get0_p(const DSA *d)
{
- if (d->p && d->q)
- return BN_security_bits(BN_num_bits(d->p), BN_num_bits(d->q));
- return -1;
+ return d->params.p;
}
-#ifndef OPENSSL_NO_DH
-DH *DSA_dup_DH(const DSA *r)
+const BIGNUM *DSA_get0_q(const DSA *d)
{
- /*
- * DSA has p, q, g, optional pub_key, optional priv_key. DH has p,
- * optional length, g, optional pub_key, optional priv_key, optional q.
- */
-
- DH *ret = NULL;
- BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL;
-
- if (r == NULL)
- goto err;
- ret = DH_new();
- if (ret == NULL)
- goto err;
- if (r->p != NULL || r->g != NULL || r->q != NULL) {
- if (r->p == NULL || r->g == NULL || r->q == NULL) {
- /* Shouldn't happen */
- goto err;
- }
- p = BN_dup(r->p);
- g = BN_dup(r->g);
- q = BN_dup(r->q);
- if (p == NULL || g == NULL || q == NULL || !DH_set0_pqg(ret, p, q, g))
- goto err;
- p = g = q = NULL;
- }
-
- if (r->pub_key != NULL) {
- pub_key = BN_dup(r->pub_key);
- if (pub_key == NULL)
- goto err;
- if (r->priv_key != NULL) {
- priv_key = BN_dup(r->priv_key);
- if (priv_key == NULL)
- goto err;
- }
- if (!DH_set0_key(ret, pub_key, priv_key))
- goto err;
- } else if (r->priv_key != NULL) {
- /* Shouldn't happen */
- goto err;
- }
-
- return ret;
-
- err:
- BN_free(p);
- BN_free(g);
- BN_free(q);
- BN_free(pub_key);
- BN_free(priv_key);
- DH_free(ret);
- return NULL;
+ return d->params.q;
}
-#endif
-void DSA_get0_pqg(const DSA *d,
- const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
+const BIGNUM *DSA_get0_g(const DSA *d)
{
- if (p != NULL)
- *p = d->p;
- if (q != NULL)
- *q = d->q;
- if (g != NULL)
- *g = d->g;
+ return d->params.g;
}
-int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+const BIGNUM *DSA_get0_pub_key(const DSA *d)
{
- /* If the fields p, q and g in d are NULL, the corresponding input
- * parameters MUST be non-NULL.
- */
- if ((d->p == NULL && p == NULL)
- || (d->q == NULL && q == NULL)
- || (d->g == NULL && g == NULL))
- return 0;
-
- if (p != NULL) {
- BN_free(d->p);
- d->p = p;
- }
- if (q != NULL) {
- BN_free(d->q);
- d->q = q;
- }
- if (g != NULL) {
- BN_free(d->g);
- d->g = g;
- }
+ return d->pub_key;
+}
- return 1;
+const BIGNUM *DSA_get0_priv_key(const DSA *d)
+{
+ return d->priv_key;
}
void DSA_get0_key(const DSA *d,
@@ -288,13 +311,6 @@ void DSA_get0_key(const DSA *d,
int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
{
- /* If the field pub_key in d is NULL, the corresponding input
- * parameters MUST be non-NULL. The priv_key field may
- * be left NULL.
- */
- if (d->pub_key == NULL && pub_key == NULL)
- return 0;
-
if (pub_key != NULL) {
BN_free(d->pub_key);
d->pub_key = pub_key;
@@ -303,56 +319,44 @@ int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
BN_free(d->priv_key);
d->priv_key = priv_key;
}
+ d->dirty_cnt++;
return 1;
}
-const BIGNUM *DSA_get0_p(const DSA *d)
-{
- return d->p;
-}
-
-const BIGNUM *DSA_get0_q(const DSA *d)
-{
- return d->q;
-}
-
-const BIGNUM *DSA_get0_g(const DSA *d)
-{
- return d->g;
-}
-
-const BIGNUM *DSA_get0_pub_key(const DSA *d)
-{
- return d->pub_key;
-}
-
-const BIGNUM *DSA_get0_priv_key(const DSA *d)
+int DSA_security_bits(const DSA *d)
{
- return d->priv_key;
+ if (d->params.p != NULL && d->params.q != NULL)
+ return BN_security_bits(BN_num_bits(d->params.p),
+ BN_num_bits(d->params.q));
+ return -1;
}
-void DSA_clear_flags(DSA *d, int flags)
+int DSA_bits(const DSA *dsa)
{
- d->flags &= ~flags;
+ if (dsa->params.p != NULL)
+ return BN_num_bits(dsa->params.p);
+ return -1;
}
-int DSA_test_flags(const DSA *d, int flags)
+FFC_PARAMS *ossl_dsa_get0_params(DSA *dsa)
{
- return d->flags & flags;
+ return &dsa->params;
}
-void DSA_set_flags(DSA *d, int flags)
+int ossl_dsa_ffc_params_fromdata(DSA *dsa, const OSSL_PARAM params[])
{
- d->flags |= flags;
-}
+ int ret;
+ FFC_PARAMS *ffc;
-ENGINE *DSA_get0_engine(DSA *d)
-{
- return d->engine;
-}
+ if (dsa == NULL)
+ return 0;
+ ffc = ossl_dsa_get0_params(dsa);
+ if (ffc == NULL)
+ return 0;
-int DSA_bits(const DSA *dsa)
-{
- return BN_num_bits(dsa->p);
+ ret = ossl_ffc_params_fromdata(ffc, params);
+ if (ret)
+ dsa->dirty_cnt++;
+ return ret;
}
diff --git a/crypto/dsa/dsa_local.h b/crypto/dsa/dsa_local.h
index a81a4b49788d..9e33fae131ea 100644
--- a/crypto/dsa/dsa_local.h
+++ b/crypto/dsa/dsa_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,6 +9,7 @@
#include <openssl/dsa.h>
#include "internal/refcount.h"
+#include "internal/ffc.h"
struct dsa_st {
/*
@@ -17,20 +18,24 @@ struct dsa_st {
*/
int pad;
int32_t version;
- BIGNUM *p;
- BIGNUM *q; /* == 20 */
- BIGNUM *g;
+ FFC_PARAMS params;
BIGNUM *pub_key; /* y public key */
BIGNUM *priv_key; /* x private key */
int flags;
/* Normally used to cache montgomery values */
BN_MONT_CTX *method_mont_p;
CRYPTO_REF_COUNT references;
+#ifndef FIPS_MODULE
CRYPTO_EX_DATA ex_data;
+#endif
const DSA_METHOD *meth;
/* functional reference if 'meth' is ENGINE-provided */
ENGINE *engine;
CRYPTO_RWLOCK *lock;
+ OSSL_LIB_CTX *libctx;
+
+ /* Provider data */
+ size_t dirty_cnt; /* If any key material changes, increment this */
};
struct DSA_SIG_st {
@@ -64,14 +69,4 @@ struct dsa_method {
int (*dsa_keygen) (DSA *dsa);
};
-int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
- const EVP_MD *evpmd, const unsigned char *seed_in,
- size_t seed_len, unsigned char *seed_out,
- int *counter_ret, unsigned long *h_ret,
- BN_GENCB *cb);
-
-int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
- const EVP_MD *evpmd, const unsigned char *seed_in,
- size_t seed_len, int idx, unsigned char *seed_out,
- int *counter_ret, unsigned long *h_ret,
- BN_GENCB *cb);
+DSA_SIG *ossl_dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa);
diff --git a/crypto/dsa/dsa_meth.c b/crypto/dsa/dsa_meth.c
index 1e6ee2f4ed3b..2f0a0bf4608e 100644
--- a/crypto/dsa/dsa_meth.c
+++ b/crypto/dsa/dsa_meth.c
@@ -1,24 +1,23 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
- * Licensed under the OpenSSL licenses, (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * https://www.openssl.org/source/license.html
- * or in the file LICENSE in the source distribution.
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
*/
+#include "internal/deprecated.h"
#include "dsa_local.h"
#include <string.h>
#include <openssl/err.h>
+#ifndef OPENSSL_NO_DEPRECATED_3_0
DSA_METHOD *DSA_meth_new(const char *name, int flags)
{
DSA_METHOD *dsam = OPENSSL_zalloc(sizeof(*dsam));
@@ -33,7 +32,7 @@ DSA_METHOD *DSA_meth_new(const char *name, int flags)
OPENSSL_free(dsam);
}
- DSAerr(DSA_F_DSA_METH_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -59,7 +58,7 @@ DSA_METHOD *DSA_meth_dup(const DSA_METHOD *dsam)
OPENSSL_free(ret);
}
- DSAerr(DSA_F_DSA_METH_DUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -73,7 +72,7 @@ int DSA_meth_set1_name(DSA_METHOD *dsam, const char *name)
char *tmpname = OPENSSL_strdup(name);
if (tmpname == NULL) {
- DSAerr(DSA_F_DSA_METH_SET1_NAME, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -222,3 +221,4 @@ int DSA_meth_set_keygen(DSA_METHOD *dsam, int (*keygen) (DSA *))
dsam->dsa_keygen = keygen;
return 1;
}
+#endif
diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c
index a983def64e76..86d89f4c724f 100644
--- a/crypto/dsa/dsa_ossl.c
+++ b/crypto/dsa/dsa_ossl.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include "crypto/bn.h"
@@ -44,10 +50,12 @@ static DSA_METHOD openssl_dsa_meth = {
static const DSA_METHOD *default_DSA_method = &openssl_dsa_meth;
+#ifndef FIPS_MODULE
void DSA_set_default_method(const DSA_METHOD *meth)
{
default_DSA_method = meth;
}
+#endif /* FIPS_MODULE */
const DSA_METHOD *DSA_get_default_method(void)
{
@@ -59,7 +67,7 @@ const DSA_METHOD *DSA_OpenSSL(void)
return &openssl_dsa_meth;
}
-static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
+DSA_SIG *ossl_dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa)
{
BIGNUM *kinv = NULL;
BIGNUM *m, *blind, *blindm, *tmp;
@@ -68,7 +76,9 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
DSA_SIG *ret = NULL;
int rv = 0;
- if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
+ if (dsa->params.p == NULL
+ || dsa->params.q == NULL
+ || dsa->params.g == NULL) {
reason = DSA_R_MISSING_PARAMETERS;
goto err;
}
@@ -85,7 +95,7 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
if (ret->r == NULL || ret->s == NULL)
goto err;
- ctx = BN_CTX_new();
+ ctx = BN_CTX_new_ex(dsa->libctx);
if (ctx == NULL)
goto err;
m = BN_CTX_get(ctx);
@@ -99,13 +109,13 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
if (!dsa_sign_setup(dsa, ctx, &kinv, &ret->r, dgst, dlen))
goto err;
- if (dlen > BN_num_bytes(dsa->q))
+ if (dlen > BN_num_bytes(dsa->params.q))
/*
* if the digest length is greater than the size of q use the
* BN_num_bits(dsa->q) leftmost bits of the digest, see fips 186-3,
* 4.2
*/
- dlen = BN_num_bytes(dsa->q);
+ dlen = BN_num_bytes(dsa->params.q);
if (BN_bin2bn(dgst, dlen, m) == NULL)
goto err;
@@ -121,8 +131,8 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
/* Generate a blinding value */
do {
- if (!BN_priv_rand(blind, BN_num_bits(dsa->q) - 1,
- BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
+ if (!BN_priv_rand_ex(blind, BN_num_bits(dsa->params.q) - 1,
+ BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0, ctx))
goto err;
} while (BN_is_zero(blind));
BN_set_flags(blind, BN_FLG_CONSTTIME);
@@ -130,27 +140,27 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
BN_set_flags(tmp, BN_FLG_CONSTTIME);
/* tmp := blind * priv_key * r mod q */
- if (!BN_mod_mul(tmp, blind, dsa->priv_key, dsa->q, ctx))
+ if (!BN_mod_mul(tmp, blind, dsa->priv_key, dsa->params.q, ctx))
goto err;
- if (!BN_mod_mul(tmp, tmp, ret->r, dsa->q, ctx))
+ if (!BN_mod_mul(tmp, tmp, ret->r, dsa->params.q, ctx))
goto err;
/* blindm := blind * m mod q */
- if (!BN_mod_mul(blindm, blind, m, dsa->q, ctx))
+ if (!BN_mod_mul(blindm, blind, m, dsa->params.q, ctx))
goto err;
/* s : = (blind * priv_key * r) + (blind * m) mod q */
- if (!BN_mod_add_quick(ret->s, tmp, blindm, dsa->q))
+ if (!BN_mod_add_quick(ret->s, tmp, blindm, dsa->params.q))
goto err;
/* s := s * k^-1 mod q */
- if (!BN_mod_mul(ret->s, ret->s, kinv, dsa->q, ctx))
+ if (!BN_mod_mul(ret->s, ret->s, kinv, dsa->params.q, ctx))
goto err;
/* s:= s * blind^-1 mod q */
- if (BN_mod_inverse(blind, blind, dsa->q, ctx) == NULL)
+ if (BN_mod_inverse(blind, blind, dsa->params.q, ctx) == NULL)
goto err;
- if (!BN_mod_mul(ret->s, ret->s, blind, dsa->q, ctx))
+ if (!BN_mod_mul(ret->s, ret->s, blind, dsa->params.q, ctx))
goto err;
/*
@@ -164,7 +174,7 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
err:
if (rv == 0) {
- DSAerr(DSA_F_DSA_DO_SIGN, reason);
+ ERR_raise(ERR_LIB_DSA, reason);
DSA_SIG_free(ret);
ret = NULL;
}
@@ -173,6 +183,11 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
return ret;
}
+static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
+{
+ return ossl_dsa_do_sign_int(dgst, dlen, dsa);
+}
+
static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in,
BIGNUM **kinvp, BIGNUM **rp)
{
@@ -189,18 +204,20 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
int ret = 0;
int q_bits, q_words;
- if (!dsa->p || !dsa->q || !dsa->g) {
- DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_MISSING_PARAMETERS);
+ if (!dsa->params.p || !dsa->params.q || !dsa->params.g) {
+ ERR_raise(ERR_LIB_DSA, DSA_R_MISSING_PARAMETERS);
return 0;
}
/* Reject obviously invalid parameters */
- if (BN_is_zero(dsa->p) || BN_is_zero(dsa->q) || BN_is_zero(dsa->g)) {
- DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_INVALID_PARAMETERS);
+ if (BN_is_zero(dsa->params.p)
+ || BN_is_zero(dsa->params.q)
+ || BN_is_zero(dsa->params.g)) {
+ ERR_raise(ERR_LIB_DSA, DSA_R_INVALID_PARAMETERS);
return 0;
}
if (dsa->priv_key == NULL) {
- DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_MISSING_PRIVATE_KEY);
+ ERR_raise(ERR_LIB_DSA, DSA_R_MISSING_PRIVATE_KEY);
return 0;
}
@@ -210,14 +227,15 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
goto err;
if (ctx_in == NULL) {
- if ((ctx = BN_CTX_new()) == NULL)
+ /* if you don't pass in ctx_in you get a default libctx */
+ if ((ctx = BN_CTX_new_ex(NULL)) == NULL)
goto err;
} else
ctx = ctx_in;
/* Preallocate space */
- q_bits = BN_num_bits(dsa->q);
- q_words = bn_get_top(dsa->q);
+ q_bits = BN_num_bits(dsa->params.q);
+ q_words = bn_get_top(dsa->params.q);
if (!bn_wexpand(k, q_words + 2)
|| !bn_wexpand(l, q_words + 2))
goto err;
@@ -229,10 +247,10 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
* We calculate k from SHA512(private_key + H(message) + random).
* This protects the private key from a weak PRNG.
*/
- if (!BN_generate_dsa_nonce(k, dsa->q, dsa->priv_key, dgst,
+ if (!BN_generate_dsa_nonce(k, dsa->params.q, dsa->priv_key, dgst,
dlen, ctx))
goto err;
- } else if (!BN_priv_rand_range(k, dsa->q))
+ } else if (!BN_priv_rand_range_ex(k, dsa->params.q, 0, ctx))
goto err;
} while (BN_is_zero(k));
@@ -241,7 +259,7 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p,
- dsa->lock, dsa->p, ctx))
+ dsa->lock, dsa->params.p, ctx))
goto err;
}
@@ -260,26 +278,27 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
* https://github.com/openssl/openssl/pull/7486#discussion_r228323705
* The fix is to rework BN so these gymnastics aren't required.
*/
- if (!BN_add(l, k, dsa->q)
- || !BN_add(k, l, dsa->q))
+ if (!BN_add(l, k, dsa->params.q)
+ || !BN_add(k, l, dsa->params.q))
goto err;
BN_consttime_swap(BN_is_bit_set(l, q_bits), k, l, q_words + 2);
if ((dsa)->meth->bn_mod_exp != NULL) {
- if (!dsa->meth->bn_mod_exp(dsa, r, dsa->g, k, dsa->p, ctx,
- dsa->method_mont_p))
+ if (!dsa->meth->bn_mod_exp(dsa, r, dsa->params.g, k, dsa->params.p,
+ ctx, dsa->method_mont_p))
goto err;
} else {
- if (!BN_mod_exp_mont(r, dsa->g, k, dsa->p, ctx, dsa->method_mont_p))
+ if (!BN_mod_exp_mont(r, dsa->params.g, k, dsa->params.p, ctx,
+ dsa->method_mont_p))
goto err;
}
- if (!BN_mod(r, r, dsa->q, ctx))
+ if (!BN_mod(r, r, dsa->params.q, ctx))
goto err;
/* Compute part of 's = inv(k) (m + xr) mod q' */
- if ((kinv = dsa_mod_inverse_fermat(k, dsa->q, ctx)) == NULL)
+ if ((kinv = dsa_mod_inverse_fermat(k, dsa->params.q, ctx)) == NULL)
goto err;
BN_clear_free(*kinvp);
@@ -288,7 +307,7 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
ret = 1;
err:
if (!ret)
- DSAerr(DSA_F_DSA_SIGN_SETUP, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_DSA, ERR_R_BN_LIB);
if (ctx != ctx_in)
BN_CTX_free(ctx);
BN_clear_free(k);
@@ -304,38 +323,41 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
BN_MONT_CTX *mont = NULL;
const BIGNUM *r, *s;
int ret = -1, i;
- if (!dsa->p || !dsa->q || !dsa->g) {
- DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_MISSING_PARAMETERS);
+
+ if (dsa->params.p == NULL
+ || dsa->params.q == NULL
+ || dsa->params.g == NULL) {
+ ERR_raise(ERR_LIB_DSA, DSA_R_MISSING_PARAMETERS);
return -1;
}
- i = BN_num_bits(dsa->q);
+ i = BN_num_bits(dsa->params.q);
/* fips 186-3 allows only different sizes for q */
if (i != 160 && i != 224 && i != 256) {
- DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_BAD_Q_VALUE);
+ ERR_raise(ERR_LIB_DSA, DSA_R_BAD_Q_VALUE);
return -1;
}
- if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) {
- DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_MODULUS_TOO_LARGE);
+ if (BN_num_bits(dsa->params.p) > OPENSSL_DSA_MAX_MODULUS_BITS) {
+ ERR_raise(ERR_LIB_DSA, DSA_R_MODULUS_TOO_LARGE);
return -1;
}
u1 = BN_new();
u2 = BN_new();
t1 = BN_new();
- ctx = BN_CTX_new();
+ ctx = BN_CTX_new_ex(NULL); /* verify does not need a libctx */
if (u1 == NULL || u2 == NULL || t1 == NULL || ctx == NULL)
goto err;
DSA_SIG_get0(sig, &r, &s);
if (BN_is_zero(r) || BN_is_negative(r) ||
- BN_ucmp(r, dsa->q) >= 0) {
+ BN_ucmp(r, dsa->params.q) >= 0) {
ret = 0;
goto err;
}
if (BN_is_zero(s) || BN_is_negative(s) ||
- BN_ucmp(s, dsa->q) >= 0) {
+ BN_ucmp(s, dsa->params.q) >= 0) {
ret = 0;
goto err;
}
@@ -343,7 +365,7 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
/*
* Calculate W = inv(S) mod Q save W in u2
*/
- if ((BN_mod_inverse(u2, s, dsa->q, ctx)) == NULL)
+ if ((BN_mod_inverse(u2, s, dsa->params.q, ctx)) == NULL)
goto err;
/* save M in u1 */
@@ -358,32 +380,32 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
goto err;
/* u1 = M * w mod q */
- if (!BN_mod_mul(u1, u1, u2, dsa->q, ctx))
+ if (!BN_mod_mul(u1, u1, u2, dsa->params.q, ctx))
goto err;
/* u2 = r * w mod q */
- if (!BN_mod_mul(u2, r, u2, dsa->q, ctx))
+ if (!BN_mod_mul(u2, r, u2, dsa->params.q, ctx))
goto err;
if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
mont = BN_MONT_CTX_set_locked(&dsa->method_mont_p,
- dsa->lock, dsa->p, ctx);
+ dsa->lock, dsa->params.p, ctx);
if (!mont)
goto err;
}
if (dsa->meth->dsa_mod_exp != NULL) {
- if (!dsa->meth->dsa_mod_exp(dsa, t1, dsa->g, u1, dsa->pub_key, u2,
- dsa->p, ctx, mont))
+ if (!dsa->meth->dsa_mod_exp(dsa, t1, dsa->params.g, u1, dsa->pub_key, u2,
+ dsa->params.p, ctx, mont))
goto err;
} else {
- if (!BN_mod_exp2_mont(t1, dsa->g, u1, dsa->pub_key, u2, dsa->p, ctx,
- mont))
+ if (!BN_mod_exp2_mont(t1, dsa->params.g, u1, dsa->pub_key, u2,
+ dsa->params.p, ctx, mont))
goto err;
}
/* let u1 = u1 mod q */
- if (!BN_mod(u1, t1, dsa->q, ctx))
+ if (!BN_mod(u1, t1, dsa->params.q, ctx))
goto err;
/*
@@ -393,7 +415,7 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
err:
if (ret < 0)
- DSAerr(DSA_F_DSA_DO_VERIFY, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_DSA, ERR_R_BN_LIB);
BN_CTX_free(ctx);
BN_free(u1);
BN_free(u2);
@@ -404,6 +426,8 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
static int dsa_init(DSA *dsa)
{
dsa->flags |= DSA_FLAG_CACHE_MONT_P;
+ ossl_ffc_params_init(&dsa->params);
+ dsa->dirty_cnt++;
return 1;
}
diff --git a/crypto/dsa/dsa_pmeth.c b/crypto/dsa/dsa_pmeth.c
index 4ca3747a4646..ba6be720a296 100644
--- a/crypto/dsa/dsa_pmeth.c
+++ b/crypto/dsa/dsa_pmeth.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
@@ -47,7 +53,7 @@ static int pkey_dsa_init(EVP_PKEY_CTX *ctx)
return 1;
}
-static int pkey_dsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+static int pkey_dsa_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
{
DSA_PKEY_CTX *dctx, *sctx;
@@ -75,9 +81,14 @@ static int pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig,
int ret;
unsigned int sltmp;
DSA_PKEY_CTX *dctx = ctx->data;
- DSA *dsa = ctx->pkey->pkey.dsa;
-
- if (dctx->md != NULL && tbslen != (size_t)EVP_MD_size(dctx->md))
+ /*
+ * Discard const. Its marked as const because this may be a cached copy of
+ * the "real" key. These calls don't make any modifications that need to
+ * be reflected back in the "original" key.
+ */
+ DSA *dsa = (DSA *)EVP_PKEY_get0_DSA(ctx->pkey);
+
+ if (dctx->md != NULL && tbslen != (size_t)EVP_MD_get_size(dctx->md))
return 0;
ret = DSA_sign(0, tbs, tbslen, sig, &sltmp, dsa);
@@ -94,9 +105,14 @@ static int pkey_dsa_verify(EVP_PKEY_CTX *ctx,
{
int ret;
DSA_PKEY_CTX *dctx = ctx->data;
- DSA *dsa = ctx->pkey->pkey.dsa;
-
- if (dctx->md != NULL && tbslen != (size_t)EVP_MD_size(dctx->md))
+ /*
+ * Discard const. Its marked as const because this may be a cached copy of
+ * the "real" key. These calls don't make any modifications that need to
+ * be reflected back in the "original" key.
+ */
+ DSA *dsa = (DSA *)EVP_PKEY_get0_DSA(ctx->pkey);
+
+ if (dctx->md != NULL && tbslen != (size_t)EVP_MD_get_size(dctx->md))
return 0;
ret = DSA_verify(0, tbs, tbslen, sig, siglen, dsa);
@@ -122,28 +138,28 @@ static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return 1;
case EVP_PKEY_CTRL_DSA_PARAMGEN_MD:
- if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha256) {
- DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE);
+ if (EVP_MD_get_type((const EVP_MD *)p2) != NID_sha1 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha224 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha256) {
+ ERR_raise(ERR_LIB_DSA, DSA_R_INVALID_DIGEST_TYPE);
return 0;
}
dctx->pmd = p2;
return 1;
case EVP_PKEY_CTRL_MD:
- if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_dsa &&
- EVP_MD_type((const EVP_MD *)p2) != NID_dsaWithSHA &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha512 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512) {
- DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE);
+ if (EVP_MD_get_type((const EVP_MD *)p2) != NID_sha1 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_dsa &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_dsaWithSHA &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha224 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha256 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha384 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha512 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_224 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_256 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_384 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_512) {
+ ERR_raise(ERR_LIB_DSA, DSA_R_INVALID_DIGEST_TYPE);
return 0;
}
dctx->md = p2;
@@ -159,8 +175,7 @@ static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return 1;
case EVP_PKEY_CTRL_PEER_KEY:
- DSAerr(DSA_F_PKEY_DSA_CTRL,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ ERR_raise(ERR_LIB_DSA, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
default:
return -2;
@@ -184,7 +199,7 @@ static int pkey_dsa_ctrl_str(EVP_PKEY_CTX *ctx,
const EVP_MD *md = EVP_get_digestbyname(value);
if (md == NULL) {
- DSAerr(DSA_F_PKEY_DSA_CTRL_STR, DSA_R_INVALID_DIGEST_TYPE);
+ ERR_raise(ERR_LIB_DSA, DSA_R_INVALID_DIGEST_TYPE);
return 0;
}
return EVP_PKEY_CTX_set_dsa_paramgen_md(ctx, md);
@@ -197,7 +212,7 @@ static int pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
DSA *dsa = NULL;
DSA_PKEY_CTX *dctx = ctx->data;
BN_GENCB *pcb;
- int ret;
+ int ret, res;
if (ctx->pkey_gencb) {
pcb = BN_GENCB_new();
@@ -211,10 +226,14 @@ static int pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
BN_GENCB_free(pcb);
return 0;
}
- ret = dsa_builtin_paramgen(dsa, dctx->nbits, dctx->qbits, dctx->pmd,
- NULL, 0, NULL, NULL, NULL, pcb);
+ if (dctx->md != NULL)
+ ossl_ffc_set_digest(&dsa->params, EVP_MD_get0_name(dctx->md), NULL);
+
+ ret = ossl_ffc_params_FIPS186_4_generate(NULL, &dsa->params,
+ FFC_PARAM_TYPE_DSA, dctx->nbits,
+ dctx->qbits, &res, pcb);
BN_GENCB_free(pcb);
- if (ret)
+ if (ret > 0)
EVP_PKEY_assign_DSA(pkey, dsa);
else
DSA_free(dsa);
@@ -226,7 +245,7 @@ static int pkey_dsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
DSA *dsa = NULL;
if (ctx->pkey == NULL) {
- DSAerr(DSA_F_PKEY_DSA_KEYGEN, DSA_R_NO_PARAMETERS_SET);
+ ERR_raise(ERR_LIB_DSA, DSA_R_NO_PARAMETERS_SET);
return 0;
}
dsa = DSA_new();
@@ -236,10 +255,10 @@ static int pkey_dsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
/* Note: if error return, pkey is freed by parent routine */
if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
return 0;
- return DSA_generate_key(pkey->pkey.dsa);
+ return DSA_generate_key((DSA *)EVP_PKEY_get0_DSA(pkey));
}
-const EVP_PKEY_METHOD dsa_pkey_meth = {
+static const EVP_PKEY_METHOD dsa_pkey_meth = {
EVP_PKEY_DSA,
EVP_PKEY_FLAG_AUTOARGLEN,
pkey_dsa_init,
@@ -271,3 +290,8 @@ const EVP_PKEY_METHOD dsa_pkey_meth = {
pkey_dsa_ctrl,
pkey_dsa_ctrl_str
};
+
+const EVP_PKEY_METHOD *ossl_dsa_pkey_method(void)
+{
+ return &dsa_pkey_meth;
+}
diff --git a/crypto/dsa/dsa_prn.c b/crypto/dsa/dsa_prn.c
index 070b881e1fae..1164e0f5cbff 100644
--- a/crypto/dsa/dsa_prn.c
+++ b/crypto/dsa/dsa_prn.c
@@ -1,12 +1,18 @@
/*
* Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
@@ -19,7 +25,7 @@ int DSA_print_fp(FILE *fp, const DSA *x, int off)
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- DSAerr(DSA_F_DSA_PRINT_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_DSA, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
@@ -34,7 +40,7 @@ int DSAparams_print_fp(FILE *fp, const DSA *x)
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- DSAerr(DSA_F_DSAPARAMS_PRINT_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_DSA, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
diff --git a/crypto/dsa/dsa_sign.c b/crypto/dsa/dsa_sign.c
index 51c7754b93e4..21b0cbd5fbef 100644
--- a/crypto/dsa/dsa_sign.c
+++ b/crypto/dsa/dsa_sign.c
@@ -1,24 +1,209 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/bn.h>
#include "internal/cryptlib.h"
#include "dsa_local.h"
-#include <openssl/bn.h>
+#include "crypto/asn1_dsa.h"
+#include "crypto/dsa.h"
DSA_SIG *DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
{
return dsa->meth->dsa_do_sign(dgst, dlen, dsa);
}
-#if OPENSSL_API_COMPAT < 0x10200000L
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
{
return dsa->meth->dsa_sign_setup(dsa, ctx_in, kinvp, rp);
}
#endif
+
+DSA_SIG *DSA_SIG_new(void)
+{
+ DSA_SIG *sig = OPENSSL_zalloc(sizeof(*sig));
+ if (sig == NULL)
+ ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
+ return sig;
+}
+
+void DSA_SIG_free(DSA_SIG *sig)
+{
+ if (sig == NULL)
+ return;
+ BN_clear_free(sig->r);
+ BN_clear_free(sig->s);
+ OPENSSL_free(sig);
+}
+
+DSA_SIG *d2i_DSA_SIG(DSA_SIG **psig, const unsigned char **ppin, long len)
+{
+ DSA_SIG *sig;
+
+ if (len < 0)
+ return NULL;
+ if (psig != NULL && *psig != NULL) {
+ sig = *psig;
+ } else {
+ sig = DSA_SIG_new();
+ if (sig == NULL)
+ return NULL;
+ }
+ if (sig->r == NULL)
+ sig->r = BN_new();
+ if (sig->s == NULL)
+ sig->s = BN_new();
+ if (sig->r == NULL || sig->s == NULL
+ || ossl_decode_der_dsa_sig(sig->r, sig->s, ppin, (size_t)len) == 0) {
+ if (psig == NULL || *psig == NULL)
+ DSA_SIG_free(sig);
+ return NULL;
+ }
+ if (psig != NULL && *psig == NULL)
+ *psig = sig;
+ return sig;
+}
+
+int i2d_DSA_SIG(const DSA_SIG *sig, unsigned char **ppout)
+{
+ BUF_MEM *buf = NULL;
+ size_t encoded_len;
+ WPACKET pkt;
+
+ if (ppout == NULL) {
+ if (!WPACKET_init_null(&pkt, 0))
+ return -1;
+ } else if (*ppout == NULL) {
+ if ((buf = BUF_MEM_new()) == NULL
+ || !WPACKET_init_len(&pkt, buf, 0)) {
+ BUF_MEM_free(buf);
+ return -1;
+ }
+ } else {
+ if (!WPACKET_init_static_len(&pkt, *ppout, SIZE_MAX, 0))
+ return -1;
+ }
+
+ if (!ossl_encode_der_dsa_sig(&pkt, sig->r, sig->s)
+ || !WPACKET_get_total_written(&pkt, &encoded_len)
+ || !WPACKET_finish(&pkt)) {
+ BUF_MEM_free(buf);
+ WPACKET_cleanup(&pkt);
+ return -1;
+ }
+
+ if (ppout != NULL) {
+ if (*ppout == NULL) {
+ *ppout = (unsigned char *)buf->data;
+ buf->data = NULL;
+ BUF_MEM_free(buf);
+ } else {
+ *ppout += encoded_len;
+ }
+ }
+
+ return (int)encoded_len;
+}
+
+int DSA_size(const DSA *dsa)
+{
+ int ret = -1;
+ DSA_SIG sig;
+
+ if (dsa->params.q != NULL) {
+ sig.r = sig.s = dsa->params.q;
+ ret = i2d_DSA_SIG(&sig, NULL);
+
+ if (ret < 0)
+ ret = 0;
+ }
+ return ret;
+}
+
+void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
+{
+ if (pr != NULL)
+ *pr = sig->r;
+ if (ps != NULL)
+ *ps = sig->s;
+}
+
+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+ if (r == NULL || s == NULL)
+ return 0;
+ BN_clear_free(sig->r);
+ BN_clear_free(sig->s);
+ sig->r = r;
+ sig->s = s;
+ return 1;
+}
+
+int ossl_dsa_sign_int(int type, const unsigned char *dgst, int dlen,
+ unsigned char *sig, unsigned int *siglen, DSA *dsa)
+{
+ DSA_SIG *s;
+
+ /* legacy case uses the method table */
+ if (dsa->libctx == NULL || dsa->meth != DSA_get_default_method())
+ s = DSA_do_sign(dgst, dlen, dsa);
+ else
+ s = ossl_dsa_do_sign_int(dgst, dlen, dsa);
+ if (s == NULL) {
+ *siglen = 0;
+ return 0;
+ }
+ *siglen = i2d_DSA_SIG(s, &sig);
+ DSA_SIG_free(s);
+ return 1;
+}
+
+int DSA_sign(int type, const unsigned char *dgst, int dlen,
+ unsigned char *sig, unsigned int *siglen, DSA *dsa)
+{
+ return ossl_dsa_sign_int(type, dgst, dlen, sig, siglen, dsa);
+}
+
+/* data has already been hashed (probably with SHA or SHA-1). */
+/*-
+ * returns
+ * 1: correct signature
+ * 0: incorrect signature
+ * -1: error
+ */
+int DSA_verify(int type, const unsigned char *dgst, int dgst_len,
+ const unsigned char *sigbuf, int siglen, DSA *dsa)
+{
+ DSA_SIG *s;
+ const unsigned char *p = sigbuf;
+ unsigned char *der = NULL;
+ int derlen = -1;
+ int ret = -1;
+
+ s = DSA_SIG_new();
+ if (s == NULL)
+ return ret;
+ if (d2i_DSA_SIG(&s, &p, siglen) == NULL)
+ goto err;
+ /* Ensure signature uses DER and doesn't have trailing garbage */
+ derlen = i2d_DSA_SIG(s, &der);
+ if (derlen != siglen || memcmp(sigbuf, der, derlen))
+ goto err;
+ ret = DSA_do_verify(dgst, dgst_len, s, dsa);
+ err:
+ OPENSSL_clear_free(der, derlen);
+ DSA_SIG_free(s);
+ return ret;
+}
diff --git a/crypto/dsa/dsa_vrf.c b/crypto/dsa/dsa_vrf.c
index 6f80a4aab7a5..b0a9d965d959 100644
--- a/crypto/dsa/dsa_vrf.c
+++ b/crypto/dsa/dsa_vrf.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include "internal/cryptlib.h"
#include "dsa_local.h"
diff --git a/crypto/dso/dso_dl.c b/crypto/dso/dso_dl.c
index 3bbb10e5ca98..f4e6e5f4573f 100644
--- a/crypto/dso/dso_dl.c
+++ b/crypto/dso/dso_dl.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -61,7 +61,7 @@ static int dl_load(DSO *dso)
char *filename = DSO_convert_filename(dso, NULL);
if (filename == NULL) {
- DSOerr(DSO_F_DL_LOAD, DSO_R_NO_FILENAME);
+ ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
goto err;
}
ptr = shl_load(filename, BIND_IMMEDIATE |
@@ -69,13 +69,17 @@ static int dl_load(DSO *dso)
DYNAMIC_PATH), 0L);
if (ptr == NULL) {
char errbuf[160];
- DSOerr(DSO_F_DL_LOAD, DSO_R_LOAD_FAILED);
+
if (openssl_strerror_r(errno, errbuf, sizeof(errbuf)))
- ERR_add_error_data(4, "filename(", filename, "): ", errbuf);
+ ERR_raise_data(ERR_LIB_DSO, DSO_R_LOAD_FAILED,
+ "filename(%s): %s", filename, errbuf);
+ else
+ ERR_raise_data(ERR_LIB_DSO, DSO_R_LOAD_FAILED,
+ "filename(%s): errno %d", filename, errno);
goto err;
}
if (!sk_push(dso->meth_data, (char *)ptr)) {
- DSOerr(DSO_F_DL_LOAD, DSO_R_STACK_ERROR);
+ ERR_raise(ERR_LIB_DSO, DSO_R_STACK_ERROR);
goto err;
}
/*
@@ -96,7 +100,7 @@ static int dl_unload(DSO *dso)
{
shl_t ptr;
if (dso == NULL) {
- DSOerr(DSO_F_DL_UNLOAD, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (sk_num(dso->meth_data) < 1)
@@ -104,7 +108,7 @@ static int dl_unload(DSO *dso)
/* Is this statement legal? */
ptr = (shl_t) sk_pop(dso->meth_data);
if (ptr == NULL) {
- DSOerr(DSO_F_DL_UNLOAD, DSO_R_NULL_HANDLE);
+ ERR_raise(ERR_LIB_DSO, DSO_R_NULL_HANDLE);
/*
* Should push the value back onto the stack in case of a retry.
*/
@@ -121,23 +125,27 @@ static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname)
void *sym;
if ((dso == NULL) || (symname == NULL)) {
- DSOerr(DSO_F_DL_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (sk_num(dso->meth_data) < 1) {
- DSOerr(DSO_F_DL_BIND_FUNC, DSO_R_STACK_ERROR);
+ ERR_raise(ERR_LIB_DSO, DSO_R_STACK_ERROR);
return NULL;
}
ptr = (shl_t) sk_value(dso->meth_data, sk_num(dso->meth_data) - 1);
if (ptr == NULL) {
- DSOerr(DSO_F_DL_BIND_FUNC, DSO_R_NULL_HANDLE);
+ ERR_raise(ERR_LIB_DSO, DSO_R_NULL_HANDLE);
return NULL;
}
if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0) {
char errbuf[160];
- DSOerr(DSO_F_DL_BIND_FUNC, DSO_R_SYM_FAILURE);
+
if (openssl_strerror_r(errno, errbuf, sizeof(errbuf)))
- ERR_add_error_data(4, "symname(", symname, "): ", errbuf);
+ ERR_raise_data(ERR_LIB_DSO, DSO_R_SYM_FAILURE,
+ "symname(%s): %s", symname, errbuf);
+ else
+ ERR_raise_data(ERR_LIB_DSO, DSO_R_SYM_FAILURE,
+ "symname(%s): errno %d", symname, errno);
return NULL;
}
return (DSO_FUNC_TYPE)sym;
@@ -148,7 +156,7 @@ static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2)
char *merged;
if (!filespec1 && !filespec2) {
- DSOerr(DSO_F_DL_MERGER, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
/*
@@ -158,7 +166,7 @@ static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2)
if (!filespec2 || filespec1[0] == '/') {
merged = OPENSSL_strdup(filespec1);
if (merged == NULL) {
- DSOerr(DSO_F_DL_MERGER, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
}
@@ -168,7 +176,7 @@ static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2)
else if (!filespec1) {
merged = OPENSSL_strdup(filespec2);
if (merged == NULL) {
- DSOerr(DSO_F_DL_MERGER, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else
@@ -191,7 +199,7 @@ static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2)
}
merged = OPENSSL_malloc(len + 2);
if (merged == NULL) {
- DSOerr(DSO_F_DL_MERGER, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
strcpy(merged, filespec2);
@@ -216,7 +224,7 @@ static char *dl_name_converter(DSO *dso, const char *filename)
len = strlen(filename);
rsize = len + 1;
transform = (strstr(filename, "/") == NULL);
- {
+ if (transform) {
/* We will convert this to "%s.s?" or "lib%s.s?" */
rsize += strlen(DSO_EXTENSION); /* The length of ".s?" */
if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
@@ -224,7 +232,7 @@ static char *dl_name_converter(DSO *dso, const char *filename)
}
translated = OPENSSL_malloc(rsize);
if (translated == NULL) {
- DSOerr(DSO_F_DL_NAME_CONVERTER, DSO_R_NAME_TRANSLATION_FAILED);
+ ERR_raise(ERR_LIB_DSO, DSO_R_NAME_TRANSLATION_FAILED);
return NULL;
}
if (transform) {
diff --git a/crypto/dso/dso_dlfcn.c b/crypto/dso/dso_dlfcn.c
index 4719e8f4f337..6a988cc72791 100644
--- a/crypto/dso/dso_dlfcn.c
+++ b/crypto/dso/dso_dlfcn.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -30,7 +30,7 @@
# if defined(__SCO_VERSION__) || defined(_SCO_ELF) || \
(defined(__osf__) && !defined(RTLD_NEXT)) || \
(defined(__OpenBSD__) && !defined(RTLD_SELF)) || \
- defined(__ANDROID__)
+ defined(__ANDROID__) || defined(__TANDEM)
# undef HAVE_DLINFO
# endif
# endif
@@ -102,7 +102,7 @@ static int dlfcn_load(DSO *dso)
int saveerrno = get_last_sys_error();
if (filename == NULL) {
- DSOerr(DSO_F_DLFCN_LOAD, DSO_R_NO_FILENAME);
+ ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
goto err;
}
# ifdef RTLD_GLOBAL
@@ -115,8 +115,8 @@ static int dlfcn_load(DSO *dso)
# endif
ptr = dlopen(filename, flags);
if (ptr == NULL) {
- DSOerr(DSO_F_DLFCN_LOAD, DSO_R_LOAD_FAILED);
- ERR_add_error_data(4, "filename(", filename, "): ", dlerror());
+ ERR_raise_data(ERR_LIB_DSO, DSO_R_LOAD_FAILED,
+ "filename(%s): %s", filename, dlerror());
goto err;
}
/*
@@ -125,7 +125,7 @@ static int dlfcn_load(DSO *dso)
*/
set_sys_error(saveerrno);
if (!sk_void_push(dso->meth_data, (char *)ptr)) {
- DSOerr(DSO_F_DLFCN_LOAD, DSO_R_STACK_ERROR);
+ ERR_raise(ERR_LIB_DSO, DSO_R_STACK_ERROR);
goto err;
}
/* Success */
@@ -143,14 +143,14 @@ static int dlfcn_unload(DSO *dso)
{
void *ptr;
if (dso == NULL) {
- DSOerr(DSO_F_DLFCN_UNLOAD, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (sk_void_num(dso->meth_data) < 1)
return 1;
ptr = sk_void_pop(dso->meth_data);
if (ptr == NULL) {
- DSOerr(DSO_F_DLFCN_UNLOAD, DSO_R_NULL_HANDLE);
+ ERR_raise(ERR_LIB_DSO, DSO_R_NULL_HANDLE);
/*
* Should push the value back onto the stack in case of a retry.
*/
@@ -171,22 +171,22 @@ static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname)
} u;
if ((dso == NULL) || (symname == NULL)) {
- DSOerr(DSO_F_DLFCN_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (sk_void_num(dso->meth_data) < 1) {
- DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_STACK_ERROR);
+ ERR_raise(ERR_LIB_DSO, DSO_R_STACK_ERROR);
return NULL;
}
ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
if (ptr == NULL) {
- DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_NULL_HANDLE);
+ ERR_raise(ERR_LIB_DSO, DSO_R_NULL_HANDLE);
return NULL;
}
u.dlret = dlsym(ptr, symname);
if (u.dlret == NULL) {
- DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_SYM_FAILURE);
- ERR_add_error_data(4, "symname(", symname, "): ", dlerror());
+ ERR_raise_data(ERR_LIB_DSO, DSO_R_SYM_FAILURE,
+ "symname(%s): %s", symname, dlerror());
return NULL;
}
return u.sym;
@@ -198,7 +198,7 @@ static char *dlfcn_merger(DSO *dso, const char *filespec1,
char *merged;
if (!filespec1 && !filespec2) {
- DSOerr(DSO_F_DLFCN_MERGER, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
/*
@@ -208,7 +208,7 @@ static char *dlfcn_merger(DSO *dso, const char *filespec1,
if (!filespec2 || (filespec1 != NULL && filespec1[0] == '/')) {
merged = OPENSSL_strdup(filespec1);
if (merged == NULL) {
- DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
}
@@ -218,7 +218,7 @@ static char *dlfcn_merger(DSO *dso, const char *filespec1,
else if (!filespec1) {
merged = OPENSSL_strdup(filespec2);
if (merged == NULL) {
- DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else {
@@ -240,7 +240,7 @@ static char *dlfcn_merger(DSO *dso, const char *filespec1,
}
merged = OPENSSL_malloc(len + 2);
if (merged == NULL) {
- DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
strcpy(merged, filespec2);
@@ -266,7 +266,7 @@ static char *dlfcn_name_converter(DSO *dso, const char *filename)
}
translated = OPENSSL_malloc(rsize);
if (translated == NULL) {
- DSOerr(DSO_F_DLFCN_NAME_CONVERTER, DSO_R_NAME_TRANSLATION_FAILED);
+ ERR_raise(ERR_LIB_DSO, DSO_R_NAME_TRANSLATION_FAILED);
return NULL;
}
if (transform) {
diff --git a/crypto/dso/dso_err.c b/crypto/dso/dso_err.c
index 613072a8d6ec..6934a1b364bc 100644
--- a/crypto/dso/dso_err.c
+++ b/crypto/dso/dso_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,48 +13,6 @@
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA DSO_str_functs[] = {
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DLFCN_BIND_FUNC, 0), "dlfcn_bind_func"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DLFCN_LOAD, 0), "dlfcn_load"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DLFCN_MERGER, 0), "dlfcn_merger"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DLFCN_NAME_CONVERTER, 0),
- "dlfcn_name_converter"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DLFCN_UNLOAD, 0), "dlfcn_unload"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DL_BIND_FUNC, 0), "dl_bind_func"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DL_LOAD, 0), "dl_load"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DL_MERGER, 0), "dl_merger"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DL_NAME_CONVERTER, 0), "dl_name_converter"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DL_UNLOAD, 0), "dl_unload"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_BIND_FUNC, 0), "DSO_bind_func"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_CONVERT_FILENAME, 0),
- "DSO_convert_filename"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_CTRL, 0), "DSO_ctrl"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_FREE, 0), "DSO_free"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_GET_FILENAME, 0), "DSO_get_filename"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_GLOBAL_LOOKUP, 0), "DSO_global_lookup"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_LOAD, 0), "DSO_load"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_MERGE, 0), "DSO_merge"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_NEW_METHOD, 0), "DSO_new_method"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_PATHBYADDR, 0), "DSO_pathbyaddr"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_SET_FILENAME, 0), "DSO_set_filename"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_UP_REF, 0), "DSO_up_ref"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_VMS_BIND_SYM, 0), "vms_bind_sym"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_VMS_LOAD, 0), "vms_load"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_VMS_MERGER, 0), "vms_merger"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_VMS_UNLOAD, 0), "vms_unload"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_BIND_FUNC, 0), "win32_bind_func"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_GLOBALLOOKUP, 0), "win32_globallookup"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_JOINER, 0), "win32_joiner"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_LOAD, 0), "win32_load"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_MERGER, 0), "win32_merger"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_NAME_CONVERTER, 0),
- "win32_name_converter"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_PATHBYADDR, 0), ""},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_SPLITTER, 0), "win32_splitter"},
- {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_UNLOAD, 0), "win32_unload"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA DSO_str_reasons[] = {
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_CTRL_FAILED), "control command failed"},
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_DSO_ALREADY_LOADED), "dso already loaded"},
@@ -88,13 +46,11 @@ static const ERR_STRING_DATA DSO_str_reasons[] = {
#endif
-int ERR_load_DSO_strings(void)
+int ossl_err_load_DSO_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(DSO_str_functs[0].error) == NULL) {
- ERR_load_strings_const(DSO_str_functs);
+ if (ERR_reason_error_string(DSO_str_reasons[0].error) == NULL)
ERR_load_strings_const(DSO_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/dso/dso_lib.c b/crypto/dso/dso_lib.c
index 50a39bb7d5d8..9d755986d755 100644
--- a/crypto/dso/dso_lib.c
+++ b/crypto/dso/dso_lib.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,37 +10,27 @@
#include "dso_local.h"
#include "internal/refcount.h"
-static DSO_METHOD *default_DSO_meth = NULL;
-
static DSO *DSO_new_method(DSO_METHOD *meth)
{
DSO *ret;
- if (default_DSO_meth == NULL) {
- /*
- * We default to DSO_METH_openssl() which in turn defaults to
- * stealing the "best available" method. Will fallback to
- * DSO_METH_null() in the worst case.
- */
- default_DSO_meth = DSO_METHOD_openssl();
- }
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->meth_data = sk_void_new_null();
if (ret->meth_data == NULL) {
/* sk_new doesn't generate any errors so we do */
- DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
- ret->meth = default_DSO_meth;
+ ret->meth = DSO_METHOD_openssl();
ret->references = 1;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
- DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
sk_void_free(ret->meth_data);
OPENSSL_free(ret);
return NULL;
@@ -76,13 +66,13 @@ int DSO_free(DSO *dso)
if ((dso->flags & DSO_FLAG_NO_UNLOAD_ON_FREE) == 0) {
if ((dso->meth->dso_unload != NULL) && !dso->meth->dso_unload(dso)) {
- DSOerr(DSO_F_DSO_FREE, DSO_R_UNLOAD_FAILED);
+ ERR_raise(ERR_LIB_DSO, DSO_R_UNLOAD_FAILED);
return 0;
}
}
if ((dso->meth->finish != NULL) && !dso->meth->finish(dso)) {
- DSOerr(DSO_F_DSO_FREE, DSO_R_FINISH_FAILED);
+ ERR_raise(ERR_LIB_DSO, DSO_R_FINISH_FAILED);
return 0;
}
@@ -104,14 +94,14 @@ int DSO_up_ref(DSO *dso)
int i;
if (dso == NULL) {
- DSOerr(DSO_F_DSO_UP_REF, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (CRYPTO_UP_REF(&dso->references, &i, dso->lock) <= 0)
return 0;
- REF_PRINT_COUNT("DSO", r);
+ REF_PRINT_COUNT("DSO", dso);
REF_ASSERT_ISNT(i < 2);
return ((i > 1) ? 1 : 0);
}
@@ -124,20 +114,20 @@ DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags)
if (dso == NULL) {
ret = DSO_new_method(meth);
if (ret == NULL) {
- DSOerr(DSO_F_DSO_LOAD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
goto err;
}
allocated = 1;
/* Pass the provided flags to the new DSO object */
if (DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) {
- DSOerr(DSO_F_DSO_LOAD, DSO_R_CTRL_FAILED);
+ ERR_raise(ERR_LIB_DSO, DSO_R_CTRL_FAILED);
goto err;
}
} else
ret = dso;
/* Don't load if we're currently already loaded */
if (ret->filename != NULL) {
- DSOerr(DSO_F_DSO_LOAD, DSO_R_DSO_ALREADY_LOADED);
+ ERR_raise(ERR_LIB_DSO, DSO_R_DSO_ALREADY_LOADED);
goto err;
}
/*
@@ -146,20 +136,20 @@ DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags)
*/
if (filename != NULL)
if (!DSO_set_filename(ret, filename)) {
- DSOerr(DSO_F_DSO_LOAD, DSO_R_SET_FILENAME_FAILED);
+ ERR_raise(ERR_LIB_DSO, DSO_R_SET_FILENAME_FAILED);
goto err;
}
filename = ret->filename;
if (filename == NULL) {
- DSOerr(DSO_F_DSO_LOAD, DSO_R_NO_FILENAME);
+ ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
goto err;
}
if (ret->meth->dso_load == NULL) {
- DSOerr(DSO_F_DSO_LOAD, DSO_R_UNSUPPORTED);
+ ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
goto err;
}
if (!ret->meth->dso_load(ret)) {
- DSOerr(DSO_F_DSO_LOAD, DSO_R_LOAD_FAILED);
+ ERR_raise(ERR_LIB_DSO, DSO_R_LOAD_FAILED);
goto err;
}
/* Load succeeded */
@@ -175,15 +165,15 @@ DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname)
DSO_FUNC_TYPE ret = NULL;
if ((dso == NULL) || (symname == NULL)) {
- DSOerr(DSO_F_DSO_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (dso->meth->dso_bind_func == NULL) {
- DSOerr(DSO_F_DSO_BIND_FUNC, DSO_R_UNSUPPORTED);
+ ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
return NULL;
}
if ((ret = dso->meth->dso_bind_func(dso, symname)) == NULL) {
- DSOerr(DSO_F_DSO_BIND_FUNC, DSO_R_SYM_FAILURE);
+ ERR_raise(ERR_LIB_DSO, DSO_R_SYM_FAILURE);
return NULL;
}
/* Success */
@@ -202,7 +192,7 @@ DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname)
long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg)
{
if (dso == NULL) {
- DSOerr(DSO_F_DSO_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
/*
@@ -222,7 +212,7 @@ long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg)
break;
}
if ((dso->meth == NULL) || (dso->meth->dso_ctrl == NULL)) {
- DSOerr(DSO_F_DSO_CTRL, DSO_R_UNSUPPORTED);
+ ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
return -1;
}
return dso->meth->dso_ctrl(dso, cmd, larg, parg);
@@ -231,7 +221,7 @@ long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg)
const char *DSO_get_filename(DSO *dso)
{
if (dso == NULL) {
- DSOerr(DSO_F_DSO_GET_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
return dso->filename;
@@ -242,17 +232,17 @@ int DSO_set_filename(DSO *dso, const char *filename)
char *copied;
if ((dso == NULL) || (filename == NULL)) {
- DSOerr(DSO_F_DSO_SET_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (dso->loaded_filename) {
- DSOerr(DSO_F_DSO_SET_FILENAME, DSO_R_DSO_ALREADY_LOADED);
+ ERR_raise(ERR_LIB_DSO, DSO_R_DSO_ALREADY_LOADED);
return 0;
}
/* We'll duplicate filename */
copied = OPENSSL_strdup(filename);
if (copied == NULL) {
- DSOerr(DSO_F_DSO_SET_FILENAME, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return 0;
}
OPENSSL_free(dso->filename);
@@ -265,7 +255,7 @@ char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2)
char *result = NULL;
if (dso == NULL || filespec1 == NULL) {
- DSOerr(DSO_F_DSO_MERGE, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
@@ -282,13 +272,13 @@ char *DSO_convert_filename(DSO *dso, const char *filename)
char *result = NULL;
if (dso == NULL) {
- DSOerr(DSO_F_DSO_CONVERT_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (filename == NULL)
filename = dso->filename;
if (filename == NULL) {
- DSOerr(DSO_F_DSO_CONVERT_FILENAME, DSO_R_NO_FILENAME);
+ ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
return NULL;
}
if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
@@ -300,7 +290,7 @@ char *DSO_convert_filename(DSO *dso, const char *filename)
if (result == NULL) {
result = OPENSSL_strdup(filename);
if (result == NULL) {
- DSOerr(DSO_F_DSO_CONVERT_FILENAME, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
return NULL;
}
}
@@ -309,11 +299,10 @@ char *DSO_convert_filename(DSO *dso, const char *filename)
int DSO_pathbyaddr(void *addr, char *path, int sz)
{
- DSO_METHOD *meth = default_DSO_meth;
- if (meth == NULL)
- meth = DSO_METHOD_openssl();
+ DSO_METHOD *meth = DSO_METHOD_openssl();
+
if (meth->pathbyaddr == NULL) {
- DSOerr(DSO_F_DSO_PATHBYADDR, DSO_R_UNSUPPORTED);
+ ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
return -1;
}
return (*meth->pathbyaddr) (addr, path, sz);
@@ -339,11 +328,10 @@ DSO *DSO_dsobyaddr(void *addr, int flags)
void *DSO_global_lookup(const char *name)
{
- DSO_METHOD *meth = default_DSO_meth;
- if (meth == NULL)
- meth = DSO_METHOD_openssl();
+ DSO_METHOD *meth = DSO_METHOD_openssl();
+
if (meth->globallookup == NULL) {
- DSOerr(DSO_F_DSO_GLOBAL_LOOKUP, DSO_R_UNSUPPORTED);
+ ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
return NULL;
}
return (*meth->globallookup) (name);
diff --git a/crypto/dso/dso_local.h b/crypto/dso/dso_local.h
index 43b7df9d7832..8aa29c1826fe 100644
--- a/crypto/dso/dso_local.h
+++ b/crypto/dso/dso_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/dso/dso_openssl.c b/crypto/dso/dso_openssl.c
index c76a04db23f9..3f264a6c658b 100644
--- a/crypto/dso/dso_openssl.c
+++ b/crypto/dso/dso_openssl.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/ebcdic.c b/crypto/ebcdic.c
index 2a8ca6101067..970ffc015c9d 100644
--- a/crypto/ebcdic.c
+++ b/crypto/ebcdic.c
@@ -1,7 +1,7 @@
/*
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/ec/asm/ecp_nistp521-ppc64.pl b/crypto/ec/asm/ecp_nistp521-ppc64.pl
new file mode 100755
index 000000000000..4260e24a1f57
--- /dev/null
+++ b/crypto/ec/asm/ecp_nistp521-ppc64.pl
@@ -0,0 +1,435 @@
+#! /usr/bin/env perl
+# Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+#
+# ====================================================================
+# Written by Amitay Isaacs <amitay@ozlabs.org> and Martin Schwenke
+# <martin@meltin.net> for the OpenSSL project.
+# ====================================================================
+#
+# p521 lower-level primitives for PPC64 using vector instructions.
+#
+
+use strict;
+use warnings;
+
+my $flavour = shift;
+my $output = "";
+while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
+if (!$output) {
+ $output = "-";
+}
+
+my ($xlate, $dir);
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
+die "can't locate ppc-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+my $code = "";
+
+my ($sp, $outp, $savelr, $savesp) = ("r1", "r3", "r10", "r12");
+
+my $vzero = "v32";
+
+sub startproc($)
+{
+ my ($name) = @_;
+
+ $code.=<<___;
+ .globl ${name}
+ .align 5
+${name}:
+
+___
+}
+
+sub endproc($)
+{
+ my ($name) = @_;
+
+ $code.=<<___;
+ blr
+ .size ${name},.-${name}
+
+___
+}
+
+
+sub push_vrs($$)
+{
+ my ($min, $max) = @_;
+
+ my $count = $max - $min + 1;
+
+ $code.=<<___;
+ mr $savesp,$sp
+ stdu $sp,-16*`$count+1`($sp)
+
+___
+ for (my $i = $min; $i <= $max; $i++) {
+ my $mult = $max - $i + 1;
+ $code.=<<___;
+ stxv $i,-16*$mult($savesp)
+___
+
+ }
+
+ $code.=<<___;
+
+___
+}
+
+sub pop_vrs($$)
+{
+ my ($min, $max) = @_;
+
+ $code.=<<___;
+ ld $savesp,0($sp)
+___
+ for (my $i = $min; $i <= $max; $i++) {
+ my $mult = $max - $i + 1;
+ $code.=<<___;
+ lxv $i,-16*$mult($savesp)
+___
+ }
+
+ $code.=<<___;
+ mr $sp,$savesp
+
+___
+}
+
+sub load_vrs($$)
+{
+ my ($pointer, $reg_list) = @_;
+
+ for (my $i = 0; $i <= 8; $i++) {
+ my $offset = $i * 8;
+ $code.=<<___;
+ lxsd $reg_list->[$i],$offset($pointer)
+___
+ }
+
+ $code.=<<___;
+
+___
+}
+
+sub store_vrs($$)
+{
+ my ($pointer, $reg_list) = @_;
+
+ for (my $i = 0; $i <= 8; $i++) {
+ my $offset = $i * 16;
+ $code.=<<___;
+ stxv $reg_list->[$i],$offset($pointer)
+___
+ }
+
+ $code.=<<___;
+
+___
+}
+
+$code.=<<___;
+.text
+
+___
+
+{
+ # mul/square common
+ my ($t1, $t2, $t3, $t4) = ("v33", "v34", "v44", "v54");
+ my ($zero, $one) = ("r8", "r9");
+ my @out = map("v$_",(55..63));
+
+ {
+ #
+ # p521_felem_mul
+ #
+
+ my ($in1p, $in2p) = ("r4", "r5");
+ my @in1 = map("v$_",(45..53));
+ my @in2 = map("v$_",(35..43));
+
+ startproc("p521_felem_mul");
+
+ push_vrs(52, 63);
+
+ $code.=<<___;
+ vspltisw $vzero,0
+
+___
+
+ load_vrs($in1p, \@in1);
+ load_vrs($in2p, \@in2);
+
+ $code.=<<___;
+ vmsumudm $out[0],$in1[0],$in2[0],$vzero
+
+ xxpermdi $t1,$in1[0],$in1[1],0b00
+ xxpermdi $t2,$in2[1],$in2[0],0b00
+ vmsumudm $out[1],$t1,$t2,$vzero
+
+ xxpermdi $t2,$in2[2],$in2[1],0b00
+ vmsumudm $out[2],$t1,$t2,$vzero
+ vmsumudm $out[2],$in1[2],$in2[0],$out[2]
+
+ xxpermdi $t2,$in2[3],$in2[2],0b00
+ vmsumudm $out[3],$t1,$t2,$vzero
+ xxpermdi $t3,$in1[2],$in1[3],0b00
+ xxpermdi $t4,$in2[1],$in2[0],0b00
+ vmsumudm $out[3],$t3,$t4,$out[3]
+
+ xxpermdi $t2,$in2[4],$in2[3],0b00
+ vmsumudm $out[4],$t1,$t2,$vzero
+ xxpermdi $t4,$in2[2],$in2[1],0b00
+ vmsumudm $out[4],$t3,$t4,$out[4]
+ vmsumudm $out[4],$in1[4],$in2[0],$out[4]
+
+ xxpermdi $t2,$in2[5],$in2[4],0b00
+ vmsumudm $out[5],$t1,$t2,$vzero
+ xxpermdi $t4,$in2[3],$in2[2],0b00
+ vmsumudm $out[5],$t3,$t4,$out[5]
+
+ xxpermdi $t2,$in2[6],$in2[5],0b00
+ vmsumudm $out[6],$t1,$t2,$vzero
+ xxpermdi $t4,$in2[4],$in2[3],0b00
+ vmsumudm $out[6],$t3,$t4,$out[6]
+
+ xxpermdi $t2,$in2[7],$in2[6],0b00
+ vmsumudm $out[7],$t1,$t2,$vzero
+ xxpermdi $t4,$in2[5],$in2[4],0b00
+ vmsumudm $out[7],$t3,$t4,$out[7]
+
+ xxpermdi $t2,$in2[8],$in2[7],0b00
+ vmsumudm $out[8],$t1,$t2,$vzero
+ xxpermdi $t4,$in2[6],$in2[5],0b00
+ vmsumudm $out[8],$t3,$t4,$out[8]
+
+ xxpermdi $t1,$in1[4],$in1[5],0b00
+ xxpermdi $t2,$in2[1],$in2[0],0b00
+ vmsumudm $out[5],$t1,$t2,$out[5]
+
+ xxpermdi $t2,$in2[2],$in2[1],0b00
+ vmsumudm $out[6],$t1,$t2,$out[6]
+ vmsumudm $out[6],$in1[6],$in2[0],$out[6]
+
+ xxpermdi $t2,$in2[3],$in2[2],0b00
+ vmsumudm $out[7],$t1,$t2,$out[7]
+ xxpermdi $t3,$in1[6],$in1[7],0b00
+ xxpermdi $t4,$in2[1],$in2[0],0b00
+ vmsumudm $out[7],$t3,$t4,$out[7]
+
+ xxpermdi $t2,$in2[4],$in2[3],0b00
+ vmsumudm $out[8],$t1,$t2,$out[8]
+ xxpermdi $t4,$in2[2],$in2[1],0b00
+ vmsumudm $out[8],$t3,$t4,$out[8]
+ vmsumudm $out[8],$in1[8],$in2[0],$out[8]
+
+ li $zero,0
+ li $one,1
+ mtvsrdd $t1,$one,$zero
+___
+
+ for (my $i = 0; $i <= 8; $i++) {
+ $code.=<<___;
+ vsld $in2[$i],$in2[$i],$t1
+___
+ }
+
+ $code.=<<___;
+
+ vmsumudm $out[7],$in1[8],$in2[8],$out[7]
+
+ xxpermdi $t2,$in2[8],$in2[7],0b00
+ xxpermdi $t1,$in1[7],$in1[8],0b00
+ vmsumudm $out[6],$t1,$t2,$out[6]
+
+ xxpermdi $t1,$in1[6],$in1[7],0b00
+ vmsumudm $out[5],$t1,$t2,$out[5]
+ vmsumudm $out[5],$in1[8],$in2[6],$out[5]
+
+ xxpermdi $t1,$in1[5],$in1[6],0b00
+ vmsumudm $out[4],$t1,$t2,$out[4]
+ xxpermdi $t4,$in2[6],$in2[5],0b00
+ xxpermdi $t3,$in1[7],$in1[8],0b00
+ vmsumudm $out[4],$t3,$t4,$out[4]
+
+ xxpermdi $t1,$in1[4],$in1[5],0b00
+ vmsumudm $out[3],$t1,$t2,$out[3]
+ xxpermdi $t3,$in1[6],$in1[7],0b00
+ vmsumudm $out[3],$t3,$t4,$out[3]
+ vmsumudm $out[3],$in1[8],$in2[4],$out[3]
+
+ xxpermdi $t1,$in1[3],$in1[4],0b00
+ vmsumudm $out[2],$t1,$t2,$out[2]
+ xxpermdi $t3,$in1[5],$in1[6],0b00
+ vmsumudm $out[2],$t3,$t4,$out[2]
+
+ xxpermdi $t1,$in1[2],$in1[3],0b00
+ vmsumudm $out[1],$t1,$t2,$out[1]
+ xxpermdi $t3,$in1[4],$in1[5],0b00
+ vmsumudm $out[1],$t3,$t4,$out[1]
+
+ xxpermdi $t1,$in1[1],$in1[2],0b00
+ vmsumudm $out[0],$t1,$t2,$out[0]
+ xxpermdi $t3,$in1[3],$in1[4],0b00
+ vmsumudm $out[0],$t3,$t4,$out[0]
+
+ xxpermdi $t2,$in2[4],$in2[3],0b00
+ xxpermdi $t1,$in1[7],$in1[8],0b00
+ vmsumudm $out[2],$t1,$t2,$out[2]
+
+ xxpermdi $t1,$in1[6],$in1[7],0b00
+ vmsumudm $out[1],$t1,$t2,$out[1]
+ vmsumudm $out[1],$in1[8],$in2[2],$out[1]
+
+ xxpermdi $t1,$in1[5],$in1[6],0b00
+ vmsumudm $out[0],$t1,$t2,$out[0]
+ xxpermdi $t4,$in2[2],$in2[1],0b00
+ xxpermdi $t3,$in1[7],$in1[8],0b00
+ vmsumudm $out[0],$t3,$t4,$out[0]
+
+___
+
+ store_vrs($outp, \@out);
+
+ pop_vrs(52, 63);
+
+ endproc("p521_felem_mul");
+ }
+
+ {
+ #
+ # p51_felem_square
+ #
+
+ my ($inp) = ("r4");
+ my @in = map("v$_",(45..53));
+ my @inx2 = map("v$_",(35..43));
+
+ startproc("p521_felem_square");
+
+ push_vrs(52, 63);
+
+ $code.=<<___;
+ vspltisw $vzero,0
+
+___
+
+ load_vrs($inp, \@in);
+
+ $code.=<<___;
+ li $zero,0
+ li $one,1
+ mtvsrdd $t1,$one,$zero
+___
+
+ for (my $i = 0; $i <= 8; $i++) {
+ $code.=<<___;
+ vsld $inx2[$i],$in[$i],$t1
+___
+ }
+
+ $code.=<<___;
+ vmsumudm $out[0],$in[0],$in[0],$vzero
+
+ vmsumudm $out[1],$in[0],$inx2[1],$vzero
+
+ xxpermdi $t1,$in[0],$in[1],0b00
+ xxpermdi $t2,$inx2[2],$in[1],0b00
+ vmsumudm $out[2],$t1,$t2,$vzero
+
+ xxpermdi $t2,$inx2[3],$inx2[2],0b00
+ vmsumudm $out[3],$t1,$t2,$vzero
+
+ xxpermdi $t2,$inx2[4],$inx2[3],0b00
+ vmsumudm $out[4],$t1,$t2,$vzero
+ vmsumudm $out[4],$in[2],$in[2],$out[4]
+
+ xxpermdi $t2,$inx2[5],$inx2[4],0b00
+ vmsumudm $out[5],$t1,$t2,$vzero
+ vmsumudm $out[5],$in[2],$inx2[3],$out[5]
+
+ xxpermdi $t2,$inx2[6],$inx2[5],0b00
+ vmsumudm $out[6],$t1,$t2,$vzero
+ xxpermdi $t3,$in[2],$in[3],0b00
+ xxpermdi $t4,$inx2[4],$in[3],0b00
+ vmsumudm $out[6],$t3,$t4,$out[6]
+
+ xxpermdi $t2,$inx2[7],$inx2[6],0b00
+ vmsumudm $out[7],$t1,$t2,$vzero
+ xxpermdi $t4,$inx2[5],$inx2[4],0b00
+ vmsumudm $out[7],$t3,$t4,$out[7]
+
+ xxpermdi $t2,$inx2[8],$inx2[7],0b00
+ vmsumudm $out[8],$t1,$t2,$vzero
+ xxpermdi $t4,$inx2[6],$inx2[5],0b00
+ vmsumudm $out[8],$t3,$t4,$out[8]
+ vmsumudm $out[8],$in[4],$in[4],$out[8]
+
+ vmsumudm $out[1],$in[5],$inx2[5],$out[1]
+
+ vmsumudm $out[3],$in[6],$inx2[6],$out[3]
+
+ vmsumudm $out[5],$in[7],$inx2[7],$out[5]
+
+ vmsumudm $out[7],$in[8],$inx2[8],$out[7]
+
+ mtvsrdd $t1,$one,$zero
+___
+
+ for (my $i = 5; $i <= 8; $i++) {
+ $code.=<<___;
+ vsld $inx2[$i],$inx2[$i],$t1
+___
+ }
+
+ $code.=<<___;
+
+ vmsumudm $out[6],$in[7],$inx2[8],$out[6]
+
+ vmsumudm $out[5],$in[6],$inx2[8],$out[5]
+
+ xxpermdi $t2,$inx2[8],$inx2[7],0b00
+ xxpermdi $t1,$in[5],$in[6],0b00
+ vmsumudm $out[4],$t1,$t2,$out[4]
+
+ xxpermdi $t1,$in[4],$in[5],0b00
+ vmsumudm $out[3],$t1,$t2,$out[3]
+
+ xxpermdi $t1,$in[3],$in[4],0b00
+ vmsumudm $out[2],$t1,$t2,$out[2]
+ vmsumudm $out[2],$in[5],$inx2[6],$out[2]
+
+ xxpermdi $t1,$in[2],$in[3],0b00
+ vmsumudm $out[1],$t1,$t2,$out[1]
+ vmsumudm $out[1],$in[4],$inx2[6],$out[1]
+
+ xxpermdi $t1,$in[1],$in[2],0b00
+ vmsumudm $out[0],$t1,$t2,$out[0]
+ xxpermdi $t2,$inx2[6],$inx2[5],0b00
+ xxpermdi $t1,$in[3],$in[4],0b00
+ vmsumudm $out[0],$t1,$t2,$out[0]
+
+___
+
+ store_vrs($outp, \@out);
+
+ pop_vrs(52, 63);
+
+ endproc("p521_felem_square");
+ }
+}
+
+$code =~ s/\`([^\`]*)\`/eval $1/gem;
+print $code;
+close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/ec/asm/ecp_nistz256-armv4.pl b/crypto/ec/asm/ecp_nistz256-armv4.pl
index fa833ce6aaf3..0adad26cb11f 100755
--- a/crypto/ec/asm/ecp_nistz256-armv4.pl
+++ b/crypto/ec/asm/ecp_nistz256-armv4.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -33,9 +33,10 @@
# on benchmark. Lower coefficients are for ECDSA sign, server-side
# operation. Keep in mind that +200% means 3x improvement.
-$flavour = shift;
-if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour && $flavour ne "void") {
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -43,15 +44,15 @@ if ($flavour && $flavour ne "void") {
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
- open STDOUT,"| \"$^X\" $xlate $flavour $output";
+ open STDOUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
} else {
- open STDOUT,">$output";
+ $output and open STDOUT,">$output";
}
$code.=<<___;
#include "arm_arch.h"
-.text
#if defined(__thumb2__)
.syntax unified
.thumb
@@ -80,6 +81,7 @@ close TABLE;
die "insane number of elements" if ($#arr != 64*16*37-1);
$code.=<<___;
+.rodata
.globl ecp_nistz256_precomputed
.type ecp_nistz256_precomputed,%object
.align 12
@@ -104,6 +106,8 @@ for(1..37) {
}
$code.=<<___;
.size ecp_nistz256_precomputed,.-ecp_nistz256_precomputed
+
+.text
.align 5
.LRR: @ 2^512 mod P precomputed for NIST P256 polynomial
.long 0x00000003, 0x00000000, 0xffffffff, 0xfffffffb
diff --git a/crypto/ec/asm/ecp_nistz256-armv8.pl b/crypto/ec/asm/ecp_nistz256-armv8.pl
index e93e18f29f19..81ee3947d7e4 100644
--- a/crypto/ec/asm/ecp_nistz256-armv8.pl
+++ b/crypto/ec/asm/ecp_nistz256-armv8.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -31,15 +31,18 @@
# on benchmark. Lower coefficients are for ECDSA sign, server-side
# operation. Keep in mind that +400% means 5x improvement.
-$flavour = shift;
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
{
@@ -1479,7 +1482,7 @@ $code.=<<___;
////////////////////////////////////////////////////////////////////////
// void ecp_nistz256_ord_sqr_mont(uint64_t res[4], uint64_t a[4],
-// int rep);
+// uint64_t rep);
.globl ecp_nistz256_ord_sqr_mont
.type ecp_nistz256_ord_sqr_mont,%function
.align 4
@@ -1645,7 +1648,7 @@ ecp_nistz256_scatter_w5:
ldp x4,x5,[$inp] // X
ldp x6,x7,[$inp,#16]
- str w4,[$out,#64*0-4]
+ stur w4,[$out,#64*0-4]
lsr x4,x4,#32
str w5,[$out,#64*1-4]
lsr x5,x5,#32
@@ -1661,7 +1664,7 @@ ecp_nistz256_scatter_w5:
ldp x4,x5,[$inp,#32] // Y
ldp x6,x7,[$inp,#48]
- str w4,[$out,#64*0-4]
+ stur w4,[$out,#64*0-4]
lsr x4,x4,#32
str w5,[$out,#64*1-4]
lsr x5,x5,#32
@@ -1677,7 +1680,7 @@ ecp_nistz256_scatter_w5:
ldp x4,x5,[$inp,#64] // Z
ldp x6,x7,[$inp,#80]
- str w4,[$out,#64*0-4]
+ stur w4,[$out,#64*0-4]
lsr x4,x4,#32
str w5,[$out,#64*1-4]
lsr x5,x5,#32
diff --git a/crypto/ec/asm/ecp_nistz256-ppc64.pl b/crypto/ec/asm/ecp_nistz256-ppc64.pl
index 2bf54e2aa544..7f600cece9d7 100755
--- a/crypto/ec/asm/ecp_nistz256-ppc64.pl
+++ b/crypto/ec/asm/ecp_nistz256-ppc64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -25,15 +25,18 @@
# POWER7 +260-530%
# POWER8 +220-340%
-$flavour = shift;
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
my $sp="r1";
@@ -1919,7 +1922,7 @@ $code.=<<___;
################################################################################
# void ecp_nistz256_ord_sqr_mont(uint64_t res[4], uint64_t a[4],
-# int rep);
+# uint64_t rep);
.globl ecp_nistz256_ord_sqr_mont
.align 5
ecp_nistz256_ord_sqr_mont:
diff --git a/crypto/ec/asm/ecp_nistz256-sparcv9.pl b/crypto/ec/asm/ecp_nistz256-sparcv9.pl
index 042e122718b7..986e002cc94d 100755
--- a/crypto/ec/asm/ecp_nistz256-sparcv9.pl
+++ b/crypto/ec/asm/ecp_nistz256-sparcv9.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -31,11 +31,13 @@
# on benchmark. Lower coefficients are for ECDSA sign, server-side
# operation. Keep in mind that +200% means 3x improvement.
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
$code.=<<___;
-#include "sparc_arch.h"
+#ifndef __ASSEMBLER__
+# define __ASSEMBLER__ 1
+#endif
+#include "crypto/sparc_arch.h"
#define LOCALS (STACK_BIAS+STACK_FRAME)
#ifdef __arch64__
diff --git a/crypto/ec/asm/ecp_nistz256-x86.pl b/crypto/ec/asm/ecp_nistz256-x86.pl
index e926d69b020b..e78f0cd7266d 100755
--- a/crypto/ec/asm/ecp_nistz256-x86.pl
+++ b/crypto/ec/asm/ecp_nistz256-x86.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -42,8 +42,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386");
diff --git a/crypto/ec/asm/ecp_nistz256-x86_64.pl b/crypto/ec/asm/ecp_nistz256-x86_64.pl
index b50ee70191b2..430b14c86d8d 100755
--- a/crypto/ec/asm/ecp_nistz256-x86_64.pl
+++ b/crypto/ec/asm/ecp_nistz256-x86_64.pl
@@ -3,7 +3,7 @@
# Copyright (c) 2014, Intel Corporation. All Rights Reserved.
# Copyright (c) 2015 CloudFlare, Inc.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -40,9 +40,10 @@
# higher - for ECDSA sign, relatively fastest server-side operation.
# Keep in mind that +100% means 2x improvement.
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -51,7 +52,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
@@ -826,7 +828,7 @@ $code.=<<___;
# void ecp_nistz256_ord_sqr_mont(
# uint64_t res[4],
# uint64_t a[4],
-# int rep);
+# uint64_t rep);
.globl ecp_nistz256_ord_sqr_mont
.type ecp_nistz256_ord_sqr_mont,\@function,3
diff --git a/crypto/ec/asm/x25519-ppc64.pl b/crypto/ec/asm/x25519-ppc64.pl
index f4b523bf8a08..c1d9650c6bfa 100755
--- a/crypto/ec/asm/x25519-ppc64.pl
+++ b/crypto/ec/asm/x25519-ppc64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -27,15 +27,18 @@
# this module delivers more than 2x improvement, and when it does,
# from 12% to 30% improvement was measured...
-$flavour = shift;
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
my $sp = "r1";
diff --git a/crypto/ec/asm/x25519-x86_64.pl b/crypto/ec/asm/x25519-x86_64.pl
index 62599dacaccd..d2285269a308 100755
--- a/crypto/ec/asm/x25519-x86_64.pl
+++ b/crypto/ec/asm/x25519-x86_64.pl
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
# Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -61,9 +61,10 @@
# C implementation, so that comparison is always against
# 2^51 radix;
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -72,7 +73,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
diff --git a/crypto/ec/build.info b/crypto/ec/build.info
index a1e673e347d0..a511e887a9ba 100644
--- a/crypto/ec/build.info
+++ b/crypto/ec/build.info
@@ -1,42 +1,105 @@
-LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \
- ec_err.c ec_curve.c ec_check.c ec_print.c ec_asn1.c ec_key.c \
- ec2_smpl.c ec_ameth.c ec_pmeth.c eck_prn.c \
- ecp_nistp224.c ecp_nistp256.c ecp_nistp521.c ecp_nistputil.c \
- ecp_oct.c ec2_oct.c ec_oct.c ec_kmeth.c ecdh_ossl.c ecdh_kdf.c \
- ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c curve25519.c ecx_meth.c \
- curve448/arch_32/f_impl.c curve448/f_generic.c curve448/scalar.c \
+$ECASM=
+IF[{- !$disabled{asm} -}]
+ $ECASM_x86=ecp_nistz256.c ecp_nistz256-x86.S
+ $ECDEF_x86=ECP_NISTZ256_ASM
+
+ $ECASM_x86_64=ecp_nistz256.c ecp_nistz256-x86_64.s x25519-x86_64.s
+ $ECDEF_x86_64=ECP_NISTZ256_ASM X25519_ASM
+
+ $ECASM_ia64=
+
+ $ECASM_sparcv9=ecp_nistz256.c ecp_nistz256-sparcv9.S
+ $ECDEF_sparcv9=ECP_NISTZ256_ASM
+
+ $ECASM_sparcv8=
+
+ $ECASM_alpha=
+
+ $ECASM_mips32=
+ $ECASM_mips64=
+
+ $ECASM_s390x=ecp_s390x_nistp.c ecx_s390x.c
+ $ECDEF_s390x=S390X_EC_ASM
+
+ $ECASM_armv4=ecp_nistz256.c ecp_nistz256-armv4.S
+ $ECDEF_armv4=ECP_NISTZ256_ASM
+ $ECASM_aarch64=ecp_nistz256.c ecp_nistz256-armv8.S
+ $ECDEF_aarch64=ECP_NISTZ256_ASM
+
+ $ECASM_parisc11=
+ $ECASM_parisc20_64=
+
+ $ECASM_ppc32=
+ $ECASM_ppc64=ecp_nistz256.c ecp_ppc.c ecp_nistz256-ppc64.s x25519-ppc64.s
+ $ECDEF_ppc64=ECP_NISTZ256_ASM X25519_ASM
+ IF[{- !$disabled{'ec_nistp_64_gcc_128'} -}]
+ $ECASM_ppc64=$ECASM_ppc64 ecp_nistp521-ppc64.s
+ $ECDEF_ppc64=$ECDEF_ppc64 ECP_NISTP521_ASM
+ INCLUDE[ecp_nistp521.o]=..
+ ENDIF
+
+ $ECASM_c64xplus=
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+ IF[$ECASM_{- $target{asm_arch} -}]
+ $ECASM=$ECASM_{- $target{asm_arch} -}
+ $ECDEF=$ECDEF_{- $target{asm_arch} -}
+ ENDIF
+ENDIF
+
+$COMMON=ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \
+ ec_curve.c ec_check.c ec_key.c ec_kmeth.c ecx_key.c ec_asn1.c \
+ ec2_smpl.c \
+ ecp_oct.c ec2_oct.c ec_oct.c ecdh_ossl.c \
+ ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c curve25519.c \
+ curve448/f_generic.c curve448/scalar.c \
curve448/curve448_tables.c curve448/eddsa.c curve448/curve448.c \
- {- $target{ec_asm_src} -}
+ $ECASM ec_backend.c ecx_backend.c ecdh_kdf.c curve448/arch_64/f_impl64.c \
+ curve448/arch_32/f_impl32.c
+
+IF[{- !$disabled{'ec_nistp_64_gcc_128'} -}]
+ $COMMON=$COMMON ecp_nistp224.c ecp_nistp256.c ecp_nistp521.c ecp_nistputil.c
+ENDIF
+
+SOURCE[../../libcrypto]=$COMMON ec_ameth.c ec_pmeth.c ecx_meth.c \
+ ec_err.c eck_prn.c \
+ ec_deprecated.c ec_print.c
+SOURCE[../../providers/libfips.a]=$COMMON
-GENERATE[ecp_nistz256-x86.s]=asm/ecp_nistz256-x86.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
+# Implementations are now spread across several libraries, so the defines
+# need to be applied to all affected libraries and modules.
+DEFINE[../../libcrypto]=$ECDEF
+DEFINE[../../providers/libfips.a]=$ECDEF
+DEFINE[../../providers/libdefault.a]=$ECDEF
+# We only need to include the ECDEF stuff in the legacy provider when
+# it's a separate module and it's dynamically linked with libcrypto.
+# Otherwise, it already gets everything that the static libcrypto.a
+# has, and doesn't need it added again.
+IF[{- !$disabled{module} && !$disabled{shared} -}]
+ DEFINE[../providers/liblegacy.a]=$ECDEF
+ENDIF
-GENERATE[ecp_nistz256-x86_64.s]=asm/ecp_nistz256-x86_64.pl $(PERLASM_SCHEME)
+GENERATE[ecp_nistz256-x86.S]=asm/ecp_nistz256-x86.pl
-GENERATE[ecp_nistz256-avx2.s]=asm/ecp_nistz256-avx2.pl $(PERLASM_SCHEME)
+GENERATE[ecp_nistz256-x86_64.s]=asm/ecp_nistz256-x86_64.pl
-GENERATE[ecp_nistz256-sparcv9.S]=asm/ecp_nistz256-sparcv9.pl $(PERLASM_SCHEME)
+GENERATE[ecp_nistz256-avx2.s]=asm/ecp_nistz256-avx2.pl
+
+GENERATE[ecp_nistz256-sparcv9.S]=asm/ecp_nistz256-sparcv9.pl
INCLUDE[ecp_nistz256-sparcv9.o]=..
-GENERATE[ecp_nistz256-armv4.S]=asm/ecp_nistz256-armv4.pl $(PERLASM_SCHEME)
+INCLUDE[ecp_s390x_nistp.o]=..
+INCLUDE[ecx_s390x.o]=..
+INCLUDE[ecx_meth.o]=..
+
+GENERATE[ecp_nistz256-armv4.S]=asm/ecp_nistz256-armv4.pl
INCLUDE[ecp_nistz256-armv4.o]=..
-GENERATE[ecp_nistz256-armv8.S]=asm/ecp_nistz256-armv8.pl $(PERLASM_SCHEME)
+GENERATE[ecp_nistz256-armv8.S]=asm/ecp_nistz256-armv8.pl
INCLUDE[ecp_nistz256-armv8.o]=..
-GENERATE[ecp_nistz256-ppc64.s]=asm/ecp_nistz256-ppc64.pl $(PERLASM_SCHEME)
-
-GENERATE[x25519-x86_64.s]=asm/x25519-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[x25519-ppc64.s]=asm/x25519-ppc64.pl $(PERLASM_SCHEME)
-
-BEGINRAW[Makefile]
-{- $builddir -}/ecp_nistz256-%.S: {- $sourcedir -}/asm/ecp_nistz256-%.pl
- CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@
-ENDRAW[Makefile]
-
-INCLUDE[curve448/arch_32/f_impl.o]=curve448/arch_32 curve448
-INCLUDE[curve448/f_generic.o]=curve448/arch_32 curve448
-INCLUDE[curve448/scalar.o]=curve448/arch_32 curve448
-INCLUDE[curve448/curve448_tables.o]=curve448/arch_32 curve448
-INCLUDE[curve448/eddsa.o]=curve448/arch_32 curve448
-INCLUDE[curve448/curve448.o]=curve448/arch_32 curve448
+GENERATE[ecp_nistz256-ppc64.s]=asm/ecp_nistz256-ppc64.pl
+
+GENERATE[ecp_nistp521-ppc64.s]=asm/ecp_nistp521-ppc64.pl
+
+GENERATE[x25519-x86_64.s]=asm/x25519-x86_64.pl
+GENERATE[x25519-ppc64.s]=asm/x25519-ppc64.pl
diff --git a/crypto/ec/curve25519.c b/crypto/ec/curve25519.c
index 952da0e65385..50a8e6b169d2 100644
--- a/crypto/ec/curve25519.c
+++ b/crypto/ec/curve25519.c
@@ -1,16 +1,26 @@
/*
- * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <string.h>
+#include "crypto/ecx.h"
#include "ec_local.h"
+#include <openssl/evp.h>
#include <openssl/sha.h>
+#include "internal/numbers.h"
+
#if defined(X25519_ASM) && (defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64))
@@ -252,7 +262,7 @@ static void x25519_scalar_mulx(uint8_t out[32], const uint8_t scalar[32],
#endif
#if defined(X25519_ASM) \
- || ( (defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16) \
+ || ( defined(INT128_MAX) \
&& !defined(__sparc__) \
&& (!defined(__SIZEOF_LONG__) || (__SIZEOF_LONG__ == 8)) \
&& !(defined(__ANDROID__) && !defined(__clang__)) )
@@ -385,7 +395,7 @@ void x25519_fe51_mul121666(fe51 h, fe51 f);
# define fe51_mul121666 x25519_fe51_mul121666
# else
-typedef __uint128_t u128;
+typedef uint128_t u128;
static void fe51_mul(fe51 h, const fe51 f, const fe51 g)
{
@@ -5429,57 +5439,75 @@ static void sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b,
s[31] = (uint8_t) (s11 >> 17);
}
-int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
- const uint8_t public_key[32], const uint8_t private_key[32])
+int
+ossl_ed25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
+ const uint8_t public_key[32], const uint8_t private_key[32],
+ OSSL_LIB_CTX *libctx, const char *propq)
{
uint8_t az[SHA512_DIGEST_LENGTH];
uint8_t nonce[SHA512_DIGEST_LENGTH];
ge_p3 R;
uint8_t hram[SHA512_DIGEST_LENGTH];
- SHA512_CTX hash_ctx;
+ EVP_MD *sha512 = EVP_MD_fetch(libctx, SN_sha512, propq);
+ EVP_MD_CTX *hash_ctx = EVP_MD_CTX_new();
+ unsigned int sz;
+ int res = 0;
- SHA512_Init(&hash_ctx);
- SHA512_Update(&hash_ctx, private_key, 32);
- SHA512_Final(az, &hash_ctx);
+ if (sha512 == NULL || hash_ctx == NULL)
+ goto err;
+
+ if (!EVP_DigestInit_ex(hash_ctx, sha512, NULL)
+ || !EVP_DigestUpdate(hash_ctx, private_key, 32)
+ || !EVP_DigestFinal_ex(hash_ctx, az, &sz))
+ goto err;
az[0] &= 248;
az[31] &= 63;
az[31] |= 64;
- SHA512_Init(&hash_ctx);
- SHA512_Update(&hash_ctx, az + 32, 32);
- SHA512_Update(&hash_ctx, message, message_len);
- SHA512_Final(nonce, &hash_ctx);
+ if (!EVP_DigestInit_ex(hash_ctx, sha512, NULL)
+ || !EVP_DigestUpdate(hash_ctx, az + 32, 32)
+ || !EVP_DigestUpdate(hash_ctx, message, message_len)
+ || !EVP_DigestFinal_ex(hash_ctx, nonce, &sz))
+ goto err;
x25519_sc_reduce(nonce);
ge_scalarmult_base(&R, nonce);
ge_p3_tobytes(out_sig, &R);
- SHA512_Init(&hash_ctx);
- SHA512_Update(&hash_ctx, out_sig, 32);
- SHA512_Update(&hash_ctx, public_key, 32);
- SHA512_Update(&hash_ctx, message, message_len);
- SHA512_Final(hram, &hash_ctx);
+ if (!EVP_DigestInit_ex(hash_ctx, sha512, NULL)
+ || !EVP_DigestUpdate(hash_ctx, out_sig, 32)
+ || !EVP_DigestUpdate(hash_ctx, public_key, 32)
+ || !EVP_DigestUpdate(hash_ctx, message, message_len)
+ || !EVP_DigestFinal_ex(hash_ctx, hram, &sz))
+ goto err;
x25519_sc_reduce(hram);
sc_muladd(out_sig + 32, hram, az, nonce);
- OPENSSL_cleanse(&hash_ctx, sizeof(hash_ctx));
+ res = 1;
+err:
OPENSSL_cleanse(nonce, sizeof(nonce));
OPENSSL_cleanse(az, sizeof(az));
-
- return 1;
+ EVP_MD_free(sha512);
+ EVP_MD_CTX_free(hash_ctx);
+ return res;
}
static const char allzeroes[15];
-int ED25519_verify(const uint8_t *message, size_t message_len,
- const uint8_t signature[64], const uint8_t public_key[32])
+int
+ossl_ed25519_verify(const uint8_t *message, size_t message_len,
+ const uint8_t signature[64], const uint8_t public_key[32],
+ OSSL_LIB_CTX *libctx, const char *propq)
{
int i;
ge_p3 A;
const uint8_t *r, *s;
- SHA512_CTX hash_ctx;
+ EVP_MD *sha512;
+ EVP_MD_CTX *hash_ctx = NULL;
+ unsigned int sz;
+ int res = 0;
ge_p2 R;
uint8_t rcheck[32];
uint8_t h[SHA512_DIGEST_LENGTH];
@@ -5526,11 +5554,19 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
fe_neg(A.X, A.X);
fe_neg(A.T, A.T);
- SHA512_Init(&hash_ctx);
- SHA512_Update(&hash_ctx, r, 32);
- SHA512_Update(&hash_ctx, public_key, 32);
- SHA512_Update(&hash_ctx, message, message_len);
- SHA512_Final(h, &hash_ctx);
+ sha512 = EVP_MD_fetch(libctx, SN_sha512, propq);
+ if (sha512 == NULL)
+ return 0;
+ hash_ctx = EVP_MD_CTX_new();
+ if (hash_ctx == NULL)
+ goto err;
+
+ if (!EVP_DigestInit_ex(hash_ctx, sha512, NULL)
+ || !EVP_DigestUpdate(hash_ctx, r, 32)
+ || !EVP_DigestUpdate(hash_ctx, public_key, 32)
+ || !EVP_DigestUpdate(hash_ctx, message, message_len)
+ || !EVP_DigestFinal_ex(hash_ctx, h, &sz))
+ goto err;
x25519_sc_reduce(h);
@@ -5538,16 +5574,32 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
ge_tobytes(rcheck, &R);
- return CRYPTO_memcmp(rcheck, r, sizeof(rcheck)) == 0;
+ res = CRYPTO_memcmp(rcheck, r, sizeof(rcheck)) == 0;
+err:
+ EVP_MD_free(sha512);
+ EVP_MD_CTX_free(hash_ctx);
+ return res;
}
-void ED25519_public_from_private(uint8_t out_public_key[32],
- const uint8_t private_key[32])
+int
+ossl_ed25519_public_from_private(OSSL_LIB_CTX *ctx, uint8_t out_public_key[32],
+ const uint8_t private_key[32],
+ const char *propq)
{
uint8_t az[SHA512_DIGEST_LENGTH];
ge_p3 A;
+ int r;
+ EVP_MD *sha512 = NULL;
- SHA512(private_key, 32, az);
+ sha512 = EVP_MD_fetch(ctx, SN_sha512, propq);
+ if (sha512 == NULL)
+ return 0;
+ r = EVP_Digest(private_key, 32, az, NULL, sha512, NULL);
+ EVP_MD_free(sha512);
+ if (!r) {
+ OPENSSL_cleanse(az, sizeof(az));
+ return 0;
+ }
az[0] &= 248;
az[31] &= 63;
@@ -5557,10 +5609,12 @@ void ED25519_public_from_private(uint8_t out_public_key[32],
ge_p3_tobytes(out_public_key, &A);
OPENSSL_cleanse(az, sizeof(az));
+ return 1;
}
-int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
- const uint8_t peer_public_value[32])
+int
+ossl_x25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
+ const uint8_t peer_public_value[32])
{
static const uint8_t kZeros[32] = {0};
x25519_scalar_mult(out_shared_key, private_key, peer_public_value);
@@ -5568,7 +5622,8 @@ int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
return CRYPTO_memcmp(kZeros, out_shared_key, 32) != 0;
}
-void X25519_public_from_private(uint8_t out_public_value[32],
+void
+ossl_x25519_public_from_private(uint8_t out_public_value[32],
const uint8_t private_key[32])
{
uint8_t e[32];
diff --git a/crypto/ec/curve448/arch_32/arch_intrinsics.h b/crypto/ec/curve448/arch_32/arch_intrinsics.h
index 5f6389863d15..7a54903ac95a 100644
--- a/crypto/ec/curve448/arch_32/arch_intrinsics.h
+++ b/crypto/ec/curve448/arch_32/arch_intrinsics.h
@@ -2,7 +2,7 @@
* Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2016 Cryptography Research, Inc.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/ec/curve448/arch_32/f_impl.c b/crypto/ec/curve448/arch_32/f_impl.c
deleted file mode 100644
index 8a89d276edb6..000000000000
--- a/crypto/ec/curve448/arch_32/f_impl.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright 2014 Cryptography Research, Inc.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- *
- * Originally written by Mike Hamburg
- */
-
-#include "field.h"
-
-void gf_mul(gf_s * RESTRICT cs, const gf as, const gf bs)
-{
- const uint32_t *a = as->limb, *b = bs->limb;
- uint32_t *c = cs->limb;
- uint64_t accum0 = 0, accum1 = 0, accum2 = 0;
- uint32_t mask = (1 << 28) - 1;
- uint32_t aa[8], bb[8];
- int i, j;
-
- for (i = 0; i < 8; i++) {
- aa[i] = a[i] + a[i + 8];
- bb[i] = b[i] + b[i + 8];
- }
-
- for (j = 0; j < 8; j++) {
- accum2 = 0;
- for (i = 0; i < j + 1; i++) {
- accum2 += widemul(a[j - i], b[i]);
- accum1 += widemul(aa[j - i], bb[i]);
- accum0 += widemul(a[8 + j - i], b[8 + i]);
- }
- accum1 -= accum2;
- accum0 += accum2;
- accum2 = 0;
- for (i = j + 1; i < 8; i++) {
- accum0 -= widemul(a[8 + j - i], b[i]);
- accum2 += widemul(aa[8 + j - i], bb[i]);
- accum1 += widemul(a[16 + j - i], b[8 + i]);
- }
- accum1 += accum2;
- accum0 += accum2;
- c[j] = ((uint32_t)(accum0)) & mask;
- c[j + 8] = ((uint32_t)(accum1)) & mask;
- accum0 >>= 28;
- accum1 >>= 28;
- }
-
- accum0 += accum1;
- accum0 += c[8];
- accum1 += c[0];
- c[8] = ((uint32_t)(accum0)) & mask;
- c[0] = ((uint32_t)(accum1)) & mask;
-
- accum0 >>= 28;
- accum1 >>= 28;
- c[9] += ((uint32_t)(accum0));
- c[1] += ((uint32_t)(accum1));
-}
-
-void gf_mulw_unsigned(gf_s * RESTRICT cs, const gf as, uint32_t b)
-{
- const uint32_t *a = as->limb;
- uint32_t *c = cs->limb;
- uint64_t accum0 = 0, accum8 = 0;
- uint32_t mask = (1 << 28) - 1;
- int i;
-
- assert(b <= mask);
-
- for (i = 0; i < 8; i++) {
- accum0 += widemul(b, a[i]);
- accum8 += widemul(b, a[i + 8]);
- c[i] = accum0 & mask;
- accum0 >>= 28;
- c[i + 8] = accum8 & mask;
- accum8 >>= 28;
- }
-
- accum0 += accum8 + c[8];
- c[8] = ((uint32_t)accum0) & mask;
- c[9] += (uint32_t)(accum0 >> 28);
-
- accum8 += c[0];
- c[0] = ((uint32_t)accum8) & mask;
- c[1] += (uint32_t)(accum8 >> 28);
-}
-
-void gf_sqr(gf_s * RESTRICT cs, const gf as)
-{
- gf_mul(cs, as, as); /* Performs better with a dedicated square */
-}
diff --git a/crypto/ec/curve448/arch_32/f_impl.h b/crypto/ec/curve448/arch_32/f_impl.h
index e1ddddaee08d..5cd25c04e123 100644
--- a/crypto/ec/curve448/arch_32/f_impl.h
+++ b/crypto/ec/curve448/arch_32/f_impl.h
@@ -2,7 +2,7 @@
* Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2014-2016 Cryptography Research, Inc.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/ec/curve448/arch_32/f_impl32.c b/crypto/ec/curve448/arch_32/f_impl32.c
new file mode 100644
index 000000000000..8714a5142216
--- /dev/null
+++ b/crypto/ec/curve448/arch_32/f_impl32.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014 Cryptography Research, Inc.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+
+#include "e_os.h"
+#include <openssl/macros.h>
+#include "internal/numbers.h"
+
+#ifdef UINT128_MAX
+/* We have support for 128 bit ints, so do nothing here */
+NON_EMPTY_TRANSLATION_UNIT
+#else
+
+# include "../field.h"
+
+void gf_mul(gf_s * RESTRICT cs, const gf as, const gf bs)
+{
+ const uint32_t *a = as->limb, *b = bs->limb;
+ uint32_t *c = cs->limb;
+ uint64_t accum0 = 0, accum1 = 0, accum2 = 0;
+ uint32_t mask = (1 << 28) - 1;
+ uint32_t aa[8], bb[8];
+ int i, j;
+
+ for (i = 0; i < 8; i++) {
+ aa[i] = a[i] + a[i + 8];
+ bb[i] = b[i] + b[i + 8];
+ }
+
+ for (j = 0; j < 8; j++) {
+ accum2 = 0;
+ for (i = 0; i < j + 1; i++) {
+ accum2 += widemul(a[j - i], b[i]);
+ accum1 += widemul(aa[j - i], bb[i]);
+ accum0 += widemul(a[8 + j - i], b[8 + i]);
+ }
+ accum1 -= accum2;
+ accum0 += accum2;
+ accum2 = 0;
+ for (i = j + 1; i < 8; i++) {
+ accum0 -= widemul(a[8 + j - i], b[i]);
+ accum2 += widemul(aa[8 + j - i], bb[i]);
+ accum1 += widemul(a[16 + j - i], b[8 + i]);
+ }
+ accum1 += accum2;
+ accum0 += accum2;
+ c[j] = ((uint32_t)(accum0)) & mask;
+ c[j + 8] = ((uint32_t)(accum1)) & mask;
+ accum0 >>= 28;
+ accum1 >>= 28;
+ }
+
+ accum0 += accum1;
+ accum0 += c[8];
+ accum1 += c[0];
+ c[8] = ((uint32_t)(accum0)) & mask;
+ c[0] = ((uint32_t)(accum1)) & mask;
+
+ accum0 >>= 28;
+ accum1 >>= 28;
+ c[9] += ((uint32_t)(accum0));
+ c[1] += ((uint32_t)(accum1));
+}
+
+void gf_mulw_unsigned(gf_s * RESTRICT cs, const gf as, uint32_t b)
+{
+ const uint32_t *a = as->limb;
+ uint32_t *c = cs->limb;
+ uint64_t accum0 = 0, accum8 = 0;
+ uint32_t mask = (1 << 28) - 1;
+ int i;
+
+ assert(b <= mask);
+
+ for (i = 0; i < 8; i++) {
+ accum0 += widemul(b, a[i]);
+ accum8 += widemul(b, a[i + 8]);
+ c[i] = accum0 & mask;
+ accum0 >>= 28;
+ c[i + 8] = accum8 & mask;
+ accum8 >>= 28;
+ }
+
+ accum0 += accum8 + c[8];
+ c[8] = ((uint32_t)accum0) & mask;
+ c[9] += (uint32_t)(accum0 >> 28);
+
+ accum8 += c[0];
+ c[0] = ((uint32_t)accum8) & mask;
+ c[1] += (uint32_t)(accum8 >> 28);
+}
+
+void gf_sqr(gf_s * RESTRICT cs, const gf as)
+{
+ gf_mul(cs, as, as); /* Performs better with a dedicated square */
+}
+#endif
diff --git a/crypto/ec/curve448/arch_64/arch_intrinsics.h b/crypto/ec/curve448/arch_64/arch_intrinsics.h
new file mode 100644
index 000000000000..e12b8cf22624
--- /dev/null
+++ b/crypto/ec/curve448/arch_64/arch_intrinsics.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016 Cryptography Research, Inc.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+
+#ifndef OSSL_CRYPTO_EC_CURVE448_ARCH_64_INTRINSICS_H
+# define OSSL_CRYPTO_EC_CURVE448_ARCH_64_INTRINSICS_H
+
+# include "internal/constant_time.h"
+
+# define ARCH_WORD_BITS 64
+
+# define word_is_zero(a) constant_time_is_zero_64(a)
+
+static ossl_inline uint128_t widemul(uint64_t a, uint64_t b)
+{
+ return ((uint128_t) a) * b;
+}
+
+#endif /* OSSL_CRYPTO_EC_CURVE448_ARCH_64_INTRINSICS_H */
diff --git a/crypto/ec/curve448/arch_64/f_impl.h b/crypto/ec/curve448/arch_64/f_impl.h
new file mode 100644
index 000000000000..faaeb8d9944b
--- /dev/null
+++ b/crypto/ec/curve448/arch_64/f_impl.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014-2016 Cryptography Research, Inc.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+
+#ifndef OSSL_CRYPTO_EC_CURVE448_ARCH_64_F_IMPL_H
+# define OSSL_CRYPTO_EC_CURVE448_ARCH_64_F_IMPL_H
+
+# define GF_HEADROOM 9999 /* Everything is reduced anyway */
+# define FIELD_LITERAL(a,b,c,d,e,f,g,h) {{a,b,c,d,e,f,g,h}}
+
+# define LIMB_PLACE_VALUE(i) 56
+
+void gf_add_RAW(gf out, const gf a, const gf b)
+{
+ unsigned int i;
+
+ for (i = 0; i < NLIMBS; i++)
+ out->limb[i] = a->limb[i] + b->limb[i];
+
+ gf_weak_reduce(out);
+}
+
+void gf_sub_RAW(gf out, const gf a, const gf b)
+{
+ uint64_t co1 = ((1ULL << 56) - 1) * 2, co2 = co1 - 2;
+ unsigned int i;
+
+ for (i = 0; i < NLIMBS; i++)
+ out->limb[i] = a->limb[i] - b->limb[i] + ((i == NLIMBS / 2) ? co2 : co1);
+
+ gf_weak_reduce(out);
+}
+
+void gf_bias(gf a, int amt)
+{
+}
+
+void gf_weak_reduce(gf a)
+{
+ uint64_t mask = (1ULL << 56) - 1;
+ uint64_t tmp = a->limb[NLIMBS - 1] >> 56;
+ unsigned int i;
+
+ a->limb[NLIMBS / 2] += tmp;
+ for (i = NLIMBS - 1; i > 0; i--)
+ a->limb[i] = (a->limb[i] & mask) + (a->limb[i - 1] >> 56);
+ a->limb[0] = (a->limb[0] & mask) + tmp;
+}
+
+#endif /* OSSL_CRYPTO_EC_CURVE448_ARCH_64_F_IMPL_H */
diff --git a/crypto/ec/curve448/arch_64/f_impl64.c b/crypto/ec/curve448/arch_64/f_impl64.c
new file mode 100644
index 000000000000..8f7a7dd391bd
--- /dev/null
+++ b/crypto/ec/curve448/arch_64/f_impl64.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014 Cryptography Research, Inc.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+
+#include "e_os.h"
+#include <openssl/macros.h>
+#include "internal/numbers.h"
+
+#ifndef UINT128_MAX
+/* No support for 128 bit ints, so do nothing here */
+NON_EMPTY_TRANSLATION_UNIT
+#else
+
+# include "../field.h"
+
+void gf_mul(gf_s * RESTRICT cs, const gf as, const gf bs)
+{
+ const uint64_t *a = as->limb, *b = bs->limb;
+ uint64_t *c = cs->limb;
+ uint128_t accum0 = 0, accum1 = 0, accum2;
+ uint64_t mask = (1ULL << 56) - 1;
+ uint64_t aa[4], bb[4], bbb[4];
+ unsigned int i, j;
+
+ for (i = 0; i < 4; i++) {
+ aa[i] = a[i] + a[i + 4];
+ bb[i] = b[i] + b[i + 4];
+ bbb[i] = bb[i] + b[i + 4];
+ }
+
+ for (i = 0; i < 4; i++) {
+ accum2 = 0;
+
+ for (j = 0; j <= i; j++) {
+ accum2 += widemul(a[j], b[i - j]);
+ accum1 += widemul(aa[j], bb[i - j]);
+ accum0 += widemul(a[j + 4], b[i - j + 4]);
+ }
+ for (; j < 4; j++) {
+ accum2 += widemul(a[j], b[i - j + 8]);
+ accum1 += widemul(aa[j], bbb[i - j + 4]);
+ accum0 += widemul(a[j + 4], bb[i - j + 4]);
+ }
+
+ accum1 -= accum2;
+ accum0 += accum2;
+
+ c[i] = ((uint64_t)(accum0)) & mask;
+ c[i + 4] = ((uint64_t)(accum1)) & mask;
+
+ accum0 >>= 56;
+ accum1 >>= 56;
+ }
+
+ accum0 += accum1;
+ accum0 += c[4];
+ accum1 += c[0];
+ c[4] = ((uint64_t)(accum0)) & mask;
+ c[0] = ((uint64_t)(accum1)) & mask;
+
+ accum0 >>= 56;
+ accum1 >>= 56;
+
+ c[5] += ((uint64_t)(accum0));
+ c[1] += ((uint64_t)(accum1));
+}
+
+void gf_mulw_unsigned(gf_s * RESTRICT cs, const gf as, uint32_t b)
+{
+ const uint64_t *a = as->limb;
+ uint64_t *c = cs->limb;
+ uint128_t accum0 = 0, accum4 = 0;
+ uint64_t mask = (1ULL << 56) - 1;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ accum0 += widemul(b, a[i]);
+ accum4 += widemul(b, a[i + 4]);
+ c[i] = accum0 & mask;
+ accum0 >>= 56;
+ c[i + 4] = accum4 & mask;
+ accum4 >>= 56;
+ }
+
+ accum0 += accum4 + c[4];
+ c[4] = accum0 & mask;
+ c[5] += accum0 >> 56;
+
+ accum4 += c[0];
+ c[0] = accum4 & mask;
+ c[1] += accum4 >> 56;
+}
+
+void gf_sqr(gf_s * RESTRICT cs, const gf as)
+{
+ const uint64_t *a = as->limb;
+ uint64_t *c = cs->limb;
+ uint128_t accum0 = 0, accum1 = 0, accum2;
+ uint64_t mask = (1ULL << 56) - 1;
+ uint64_t aa[4];
+ unsigned int i;
+
+ /* For some reason clang doesn't vectorize this without prompting? */
+ for (i = 0; i < 4; i++)
+ aa[i] = a[i] + a[i + 4];
+
+ accum2 = widemul(a[0], a[3]);
+ accum0 = widemul(aa[0], aa[3]);
+ accum1 = widemul(a[4], a[7]);
+
+ accum2 += widemul(a[1], a[2]);
+ accum0 += widemul(aa[1], aa[2]);
+ accum1 += widemul(a[5], a[6]);
+
+ accum0 -= accum2;
+ accum1 += accum2;
+
+ c[3] = ((uint64_t)(accum1)) << 1 & mask;
+ c[7] = ((uint64_t)(accum0)) << 1 & mask;
+
+ accum0 >>= 55;
+ accum1 >>= 55;
+
+ accum0 += widemul(2 * aa[1], aa[3]);
+ accum1 += widemul(2 * a[5], a[7]);
+ accum0 += widemul(aa[2], aa[2]);
+ accum1 += accum0;
+
+ accum0 -= widemul(2 * a[1], a[3]);
+ accum1 += widemul(a[6], a[6]);
+
+ accum2 = widemul(a[0], a[0]);
+ accum1 -= accum2;
+ accum0 += accum2;
+
+ accum0 -= widemul(a[2], a[2]);
+ accum1 += widemul(aa[0], aa[0]);
+ accum0 += widemul(a[4], a[4]);
+
+ c[0] = ((uint64_t)(accum0)) & mask;
+ c[4] = ((uint64_t)(accum1)) & mask;
+
+ accum0 >>= 56;
+ accum1 >>= 56;
+
+ accum2 = widemul(2 * aa[2], aa[3]);
+ accum0 -= widemul(2 * a[2], a[3]);
+ accum1 += widemul(2 * a[6], a[7]);
+
+ accum1 += accum2;
+ accum0 += accum2;
+
+ accum2 = widemul(2 * a[0], a[1]);
+ accum1 += widemul(2 * aa[0], aa[1]);
+ accum0 += widemul(2 * a[4], a[5]);
+
+ accum1 -= accum2;
+ accum0 += accum2;
+
+ c[1] = ((uint64_t)(accum0)) & mask;
+ c[5] = ((uint64_t)(accum1)) & mask;
+
+ accum0 >>= 56;
+ accum1 >>= 56;
+
+ accum2 = widemul(aa[3], aa[3]);
+ accum0 -= widemul(a[3], a[3]);
+ accum1 += widemul(a[7], a[7]);
+
+ accum1 += accum2;
+ accum0 += accum2;
+
+ accum2 = widemul(2 * a[0], a[2]);
+ accum1 += widemul(2 * aa[0], aa[2]);
+ accum0 += widemul(2 * a[4], a[6]);
+
+ accum2 += widemul(a[1], a[1]);
+ accum1 += widemul(aa[1], aa[1]);
+ accum0 += widemul(a[5], a[5]);
+
+ accum1 -= accum2;
+ accum0 += accum2;
+
+ c[2] = ((uint64_t)(accum0)) & mask;
+ c[6] = ((uint64_t)(accum1)) & mask;
+
+ accum0 >>= 56;
+ accum1 >>= 56;
+
+ accum0 += c[3];
+ accum1 += c[7];
+ c[3] = ((uint64_t)(accum0)) & mask;
+ c[7] = ((uint64_t)(accum1)) & mask;
+
+ /* we could almost stop here, but it wouldn't be stable, so... */
+
+ accum0 >>= 56;
+ accum1 >>= 56;
+ c[4] += ((uint64_t)(accum0)) + ((uint64_t)(accum1));
+ c[0] += ((uint64_t)(accum1));
+}
+#endif
diff --git a/crypto/ec/curve448/curve448.c b/crypto/ec/curve448/curve448.c
index 3d4db44564e9..6928d9693ca5 100644
--- a/crypto/ec/curve448/curve448.c
+++ b/crypto/ec/curve448/curve448.c
@@ -2,7 +2,7 @@
* Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2016 Cryptography Research, Inc.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -15,6 +15,7 @@
#include "point_448.h"
#include "ed448.h"
+#include "crypto/ecx.h"
#include "curve448_local.h"
#define COFACTOR 4
@@ -54,7 +55,7 @@ static void gf_invert(gf y, const gf x, int assert_nonzero)
}
/** identity = (0,1) */
-const curve448_point_t curve448_point_identity =
+const curve448_point_t ossl_curve448_point_identity =
{ {{{{0}}}, {{{1}}}, {{{1}}}, {{{0}}}} };
static void point_double_internal(curve448_point_t p, const curve448_point_t q,
@@ -81,7 +82,7 @@ static void point_double_internal(curve448_point_t p, const curve448_point_t q,
gf_mul(p->t, b, d);
}
-void curve448_point_double(curve448_point_t p, const curve448_point_t q)
+void ossl_curve448_point_double(curve448_point_t p, const curve448_point_t q)
{
point_double_internal(p, q, 0);
}
@@ -183,8 +184,9 @@ static void sub_pniels_from_pt(curve448_point_t p, const pniels_t pn,
sub_niels_from_pt(p, pn->n, before_double);
}
-c448_bool_t curve448_point_eq(const curve448_point_t p,
- const curve448_point_t q)
+c448_bool_t
+ossl_curve448_point_eq(const curve448_point_t p,
+ const curve448_point_t q)
{
mask_t succ;
gf a, b;
@@ -197,7 +199,8 @@ c448_bool_t curve448_point_eq(const curve448_point_t p,
return mask_to_bool(succ);
}
-c448_bool_t curve448_point_valid(const curve448_point_t p)
+c448_bool_t
+ossl_curve448_point_valid(const curve448_point_t p)
{
mask_t out;
gf a, b, c;
@@ -224,7 +227,8 @@ static ossl_inline void constant_time_lookup_niels(niels_s * RESTRICT ni,
constant_time_lookup(ni, table, sizeof(niels_s), nelts, idx);
}
-void curve448_precomputed_scalarmul(curve448_point_t out,
+void
+ossl_curve448_precomputed_scalarmul(curve448_point_t out,
const curve448_precomputed_s * table,
const curve448_scalar_t scalar)
{
@@ -233,8 +237,8 @@ void curve448_precomputed_scalarmul(curve448_point_t out,
niels_t ni;
curve448_scalar_t scalar1x;
- curve448_scalar_add(scalar1x, scalar, precomputed_scalarmul_adjustment);
- curve448_scalar_halve(scalar1x, scalar1x);
+ ossl_curve448_scalar_add(scalar1x, scalar, precomputed_scalarmul_adjustment);
+ ossl_curve448_scalar_halve(scalar1x, scalar1x);
for (i = s; i > 0; i--) {
if (i != s)
@@ -271,7 +275,8 @@ void curve448_precomputed_scalarmul(curve448_point_t out,
OPENSSL_cleanse(scalar1x, sizeof(scalar1x));
}
-void curve448_point_mul_by_ratio_and_encode_like_eddsa(
+void
+ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa(
uint8_t enc[EDDSA_448_PUBLIC_BYTES],
const curve448_point_t p)
{
@@ -315,10 +320,11 @@ void curve448_point_mul_by_ratio_and_encode_like_eddsa(
OPENSSL_cleanse(y, sizeof(y));
OPENSSL_cleanse(z, sizeof(z));
OPENSSL_cleanse(t, sizeof(t));
- curve448_point_destroy(q);
+ ossl_curve448_point_destroy(q);
}
-c448_error_t curve448_point_decode_like_eddsa_and_mul_by_ratio(
+c448_error_t
+ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(
curve448_point_t p,
const uint8_t enc[EDDSA_448_PUBLIC_BYTES])
{
@@ -371,14 +377,15 @@ c448_error_t curve448_point_decode_like_eddsa_and_mul_by_ratio(
}
OPENSSL_cleanse(enc2, sizeof(enc2));
- assert(curve448_point_valid(p) || ~succ);
+ assert(ossl_curve448_point_valid(p) || ~succ);
return c448_succeed_if(mask_to_bool(succ));
}
-c448_error_t x448_int(uint8_t out[X_PUBLIC_BYTES],
- const uint8_t base[X_PUBLIC_BYTES],
- const uint8_t scalar[X_PRIVATE_BYTES])
+c448_error_t
+ossl_x448_int(uint8_t out[X_PUBLIC_BYTES],
+ const uint8_t base[X_PUBLIC_BYTES],
+ const uint8_t scalar[X_PRIVATE_BYTES])
{
gf x1, x2, z2, x3, z3, t1, t2;
int t;
@@ -455,7 +462,8 @@ c448_error_t x448_int(uint8_t out[X_PUBLIC_BYTES],
return c448_succeed_if(mask_to_bool(nz));
}
-void curve448_point_mul_by_ratio_and_encode_like_x448(uint8_t
+void
+ossl_curve448_point_mul_by_ratio_and_encode_like_x448(uint8_t
out[X_PUBLIC_BYTES],
const curve448_point_t p)
{
@@ -466,11 +474,11 @@ void curve448_point_mul_by_ratio_and_encode_like_x448(uint8_t
gf_mul(q->z, q->t, q->y); /* y/x */
gf_sqr(q->y, q->z); /* (y/x)^2 */
gf_serialize(out, q->y, 1);
- curve448_point_destroy(q);
+ ossl_curve448_point_destroy(q);
}
-void x448_derive_public_key(uint8_t out[X_PUBLIC_BYTES],
- const uint8_t scalar[X_PRIVATE_BYTES])
+void ossl_x448_derive_public_key(uint8_t out[X_PUBLIC_BYTES],
+ const uint8_t scalar[X_PRIVATE_BYTES])
{
/* Scalar conditioning */
uint8_t scalar2[X_PRIVATE_BYTES];
@@ -484,15 +492,16 @@ void x448_derive_public_key(uint8_t out[X_PUBLIC_BYTES],
scalar2[X_PRIVATE_BYTES - 1] &= ~((0u - 1u) << ((X_PRIVATE_BITS + 7) % 8));
scalar2[X_PRIVATE_BYTES - 1] |= 1 << ((X_PRIVATE_BITS + 7) % 8);
- curve448_scalar_decode_long(the_scalar, scalar2, sizeof(scalar2));
+ ossl_curve448_scalar_decode_long(the_scalar, scalar2, sizeof(scalar2));
/* Compensate for the encoding ratio */
for (i = 1; i < X448_ENCODE_RATIO; i <<= 1)
- curve448_scalar_halve(the_scalar, the_scalar);
+ ossl_curve448_scalar_halve(the_scalar, the_scalar);
- curve448_precomputed_scalarmul(p, curve448_precomputed_base, the_scalar);
- curve448_point_mul_by_ratio_and_encode_like_x448(out, p);
- curve448_point_destroy(p);
+ ossl_curve448_precomputed_scalarmul(p, ossl_curve448_precomputed_base,
+ the_scalar);
+ ossl_curve448_point_mul_by_ratio_and_encode_like_x448(out, p);
+ ossl_curve448_point_destroy(p);
}
/* Control for variable-time scalar multiply algorithms. */
@@ -501,9 +510,9 @@ struct smvt_control {
};
#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3))
-# define NUMTRAILINGZEROS __builtin_ctz
+# define NUMTRAILINGZEROS __builtin_ctz
#else
-# define NUMTRAILINGZEROS numtrailingzeros
+# define NUMTRAILINGZEROS numtrailingzeros
static uint32_t numtrailingzeros(uint32_t i)
{
uint32_t tmp;
@@ -610,7 +619,7 @@ static void prepare_wnaf_table(pniels_t * output,
if (tbits == 0)
return;
- curve448_point_double(tmp, working);
+ ossl_curve448_point_double(tmp, working);
pt_to_pniels(twop, tmp);
add_pniels_to_pt(tmp, output[0], 0);
@@ -621,11 +630,12 @@ static void prepare_wnaf_table(pniels_t * output,
pt_to_pniels(output[i], tmp);
}
- curve448_point_destroy(tmp);
+ ossl_curve448_point_destroy(tmp);
OPENSSL_cleanse(twop, sizeof(twop));
}
-void curve448_base_double_scalarmul_non_secret(curve448_point_t combo,
+void
+ossl_curve448_base_double_scalarmul_non_secret(curve448_point_t combo,
const curve448_scalar_t scalar1,
const curve448_point_t base2,
const curve448_scalar_t scalar2)
@@ -645,7 +655,7 @@ void curve448_base_double_scalarmul_non_secret(curve448_point_t combo,
i = control_var[0].power;
if (i < 0) {
- curve448_point_copy(combo, curve448_point_identity);
+ curve448_point_copy(combo, ossl_curve448_point_identity);
return;
}
if (i > control_pre[0].power) {
@@ -653,13 +663,14 @@ void curve448_base_double_scalarmul_non_secret(curve448_point_t combo,
contv++;
} else if (i == control_pre[0].power && i >= 0) {
pniels_to_pt(combo, precmp_var[control_var[0].addend >> 1]);
- add_niels_to_pt(combo, curve448_wnaf_base[control_pre[0].addend >> 1],
+ add_niels_to_pt(combo,
+ ossl_curve448_wnaf_base[control_pre[0].addend >> 1],
i);
contv++;
contp++;
} else {
i = control_pre[0].power;
- niels_to_pt(combo, curve448_wnaf_base[control_pre[0].addend >> 1]);
+ niels_to_pt(combo, ossl_curve448_wnaf_base[control_pre[0].addend >> 1]);
contp++;
}
@@ -688,11 +699,11 @@ void curve448_base_double_scalarmul_non_secret(curve448_point_t combo,
if (control_pre[contp].addend > 0)
add_niels_to_pt(combo,
- curve448_wnaf_base[control_pre[contp].addend
+ ossl_curve448_wnaf_base[control_pre[contp].addend
>> 1], i);
else
sub_niels_from_pt(combo,
- curve448_wnaf_base[(-control_pre
+ ossl_curve448_wnaf_base[(-control_pre
[contp].addend) >> 1], i);
contp++;
}
@@ -709,20 +720,20 @@ void curve448_base_double_scalarmul_non_secret(curve448_point_t combo,
(void)ncb_pre;
}
-void curve448_point_destroy(curve448_point_t point)
+void ossl_curve448_point_destroy(curve448_point_t point)
{
OPENSSL_cleanse(point, sizeof(curve448_point_t));
}
-int X448(uint8_t out_shared_key[56], const uint8_t private_key[56],
- const uint8_t peer_public_value[56])
+int ossl_x448(uint8_t out_shared_key[56], const uint8_t private_key[56],
+ const uint8_t peer_public_value[56])
{
- return x448_int(out_shared_key, peer_public_value, private_key)
+ return ossl_x448_int(out_shared_key, peer_public_value, private_key)
== C448_SUCCESS;
}
-void X448_public_from_private(uint8_t out_public_value[56],
- const uint8_t private_key[56])
+void ossl_x448_public_from_private(uint8_t out_public_value[56],
+ const uint8_t private_key[56])
{
- x448_derive_public_key(out_public_value, private_key);
+ ossl_x448_derive_public_key(out_public_value, private_key);
}
diff --git a/crypto/ec/curve448/curve448_local.h b/crypto/ec/curve448/curve448_local.h
index b27770661f89..3410f091a655 100644
--- a/crypto/ec/curve448/curve448_local.h
+++ b/crypto/ec/curve448/curve448_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,29 +10,15 @@
# define OSSL_CRYPTO_EC_CURVE448_LOCAL_H
# include "curve448utils.h"
-int X448(uint8_t out_shared_key[56], const uint8_t private_key[56],
- const uint8_t peer_public_value[56]);
+int
+ossl_ed448ph_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig, const uint8_t hash[64],
+ const uint8_t public_key[57], const uint8_t private_key[57],
+ const uint8_t *context, size_t context_len, const char *propq);
-void X448_public_from_private(uint8_t out_public_value[56],
- const uint8_t private_key[56]);
-
-int ED448_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
- const uint8_t public_key[57], const uint8_t private_key[57],
- const uint8_t *context, size_t context_len);
-
-int ED448_verify(const uint8_t *message, size_t message_len,
- const uint8_t signature[114], const uint8_t public_key[57],
- const uint8_t *context, size_t context_len);
-
-int ED448ph_sign(uint8_t *out_sig, const uint8_t hash[64],
- const uint8_t public_key[57], const uint8_t private_key[57],
- const uint8_t *context, size_t context_len);
-
-int ED448ph_verify(const uint8_t hash[64], const uint8_t signature[114],
- const uint8_t public_key[57], const uint8_t *context,
- size_t context_len);
-
-int ED448_public_from_private(uint8_t out_public_key[57],
- const uint8_t private_key[57]);
+int
+ossl_ed448ph_verify(OSSL_LIB_CTX *ctx, const uint8_t hash[64],
+ const uint8_t signature[114], const uint8_t public_key[57],
+ const uint8_t *context, size_t context_len,
+ const char *propq);
#endif /* OSSL_CRYPTO_EC_CURVE448_LOCAL_H */
diff --git a/crypto/ec/curve448/curve448_tables.c b/crypto/ec/curve448/curve448_tables.c
index 9ef29769e3b3..0c6f626b3e6e 100644
--- a/crypto/ec/curve448/curve448_tables.c
+++ b/crypto/ec/curve448/curve448_tables.c
@@ -1,8 +1,8 @@
/*
- * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2016 Cryptography Research, Inc.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -1058,7 +1058,7 @@ static const curve448_precomputed_s curve448_precomputed_base_table = {
}}
}
};
-const struct curve448_precomputed_s *curve448_precomputed_base
+const struct curve448_precomputed_s *ossl_curve448_precomputed_base
= &curve448_precomputed_base_table;
static const niels_t curve448_wnaf_base_table[32] = {
@@ -1480,4 +1480,4 @@ static const niels_t curve448_wnaf_base_table[32] = {
0x001979c0df237316ULL, 0x00501e953a919b87ULL)},
}}
};
-const niels_t *curve448_wnaf_base = curve448_wnaf_base_table;
+const niels_t *ossl_curve448_wnaf_base = curve448_wnaf_base_table;
diff --git a/crypto/ec/curve448/curve448utils.h b/crypto/ec/curve448/curve448utils.h
index 86c258e745e4..664c6e6ff306 100644
--- a/crypto/ec/curve448/curve448utils.h
+++ b/crypto/ec/curve448/curve448utils.h
@@ -1,8 +1,8 @@
/*
- * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015 Cryptography Research, Inc.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -15,6 +15,8 @@
# include <openssl/e_os2.h>
+# include "internal/numbers.h"
+
/*
* Internal word types. Somewhat tricky. This could be decided separately per
* platform. However, the structs do need to be all the same size and
@@ -41,9 +43,9 @@ typedef int64_t c448_sword_t;
/* "Boolean" type, will be set to all-zero or all-one (i.e. -1u) */
typedef uint64_t c448_bool_t;
/* Double-word size for internal computations */
-typedef __uint128_t c448_dword_t;
+typedef uint128_t c448_dword_t;
/* Signed double-word size for internal computations */
-typedef __int128_t c448_dsword_t;
+typedef int128_t c448_dsword_t;
# elif C448_WORD_BITS == 32
/* Word size for internal computations */
typedef uint32_t c448_word_t;
diff --git a/crypto/ec/curve448/ed448.h b/crypto/ec/curve448/ed448.h
index c1e5c2832f9b..00b2bae580ba 100644
--- a/crypto/ec/curve448/ed448.h
+++ b/crypto/ec/curve448/ed448.h
@@ -1,8 +1,8 @@
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2016 Cryptography Research, Inc.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -37,9 +37,12 @@
* pubkey (out): The public key.
* privkey (in): The private key.
*/
-c448_error_t c448_ed448_derive_public_key(
- uint8_t pubkey [EDDSA_448_PUBLIC_BYTES],
- const uint8_t privkey [EDDSA_448_PRIVATE_BYTES]);
+c448_error_t
+ossl_c448_ed448_derive_public_key(
+ OSSL_LIB_CTX *ctx,
+ uint8_t pubkey [EDDSA_448_PUBLIC_BYTES],
+ const uint8_t privkey [EDDSA_448_PRIVATE_BYTES],
+ const char *propq);
/*
* EdDSA signing.
@@ -58,13 +61,15 @@ c448_error_t c448_ed448_derive_public_key(
* non-prehashed messages, at least without some very careful protocol-level
* disambiguation. For Ed448 it is safe.
*/
-c448_error_t c448_ed448_sign(
- uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
- const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
- const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
- const uint8_t *message, size_t message_len,
- uint8_t prehashed, const uint8_t *context,
- size_t context_len);
+c448_error_t
+ossl_c448_ed448_sign(OSSL_LIB_CTX *ctx,
+ uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
+ const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
+ const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
+ const uint8_t *message, size_t message_len,
+ uint8_t prehashed, const uint8_t *context,
+ size_t context_len,
+ const char *propq);
/*
* EdDSA signing with prehash.
@@ -82,13 +87,15 @@ c448_error_t c448_ed448_sign(
* non-prehashed messages, at least without some very careful protocol-level
* disambiguation. For Ed448 it is safe.
*/
-c448_error_t c448_ed448_sign_prehash(
- uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
- const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
- const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
- const uint8_t hash[64],
- const uint8_t *context,
- size_t context_len);
+c448_error_t
+ossl_c448_ed448_sign_prehash(OSSL_LIB_CTX *ctx,
+ uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
+ const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
+ const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
+ const uint8_t hash[64],
+ const uint8_t *context,
+ size_t context_len,
+ const char *propq);
/*
* EdDSA signature verification.
@@ -108,13 +115,16 @@ c448_error_t c448_ed448_sign_prehash(
* non-prehashed messages, at least without some very careful protocol-level
* disambiguation. For Ed448 it is safe.
*/
-c448_error_t c448_ed448_verify(const uint8_t
- signature[EDDSA_448_SIGNATURE_BYTES],
- const uint8_t
- pubkey[EDDSA_448_PUBLIC_BYTES],
- const uint8_t *message, size_t message_len,
- uint8_t prehashed, const uint8_t *context,
- uint8_t context_len);
+c448_error_t
+ossl_c448_ed448_verify(OSSL_LIB_CTX *ctx,
+ const uint8_t
+ signature[EDDSA_448_SIGNATURE_BYTES],
+ const uint8_t
+ pubkey[EDDSA_448_PUBLIC_BYTES],
+ const uint8_t *message, size_t message_len,
+ uint8_t prehashed, const uint8_t *context,
+ uint8_t context_len,
+ const char *propq);
/*
* EdDSA signature verification.
@@ -133,12 +143,15 @@ c448_error_t c448_ed448_verify(const uint8_t
* non-prehashed messages, at least without some very careful protocol-level
* disambiguation. For Ed448 it is safe.
*/
-c448_error_t c448_ed448_verify_prehash(
- const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
- const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
- const uint8_t hash[64],
- const uint8_t *context,
- uint8_t context_len);
+c448_error_t
+ossl_c448_ed448_verify_prehash(
+ OSSL_LIB_CTX *ctx,
+ const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
+ const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
+ const uint8_t hash[64],
+ const uint8_t *context,
+ uint8_t context_len,
+ const char *propq);
/*
* EdDSA point encoding. Used internally, exposed externally.
@@ -163,7 +176,8 @@ c448_error_t c448_ed448_verify_prehash(
* enc (out): The encoded point.
* p (in): The point.
*/
-void curve448_point_mul_by_ratio_and_encode_like_eddsa(
+void
+ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa(
uint8_t enc [EDDSA_448_PUBLIC_BYTES],
const curve448_point_t p);
@@ -176,7 +190,8 @@ void curve448_point_mul_by_ratio_and_encode_like_eddsa(
* enc (out): The encoded point.
* p (in): The point.
*/
-c448_error_t curve448_point_decode_like_eddsa_and_mul_by_ratio(
+c448_error_t
+ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(
curve448_point_t p,
const uint8_t enc[EDDSA_448_PUBLIC_BYTES]);
@@ -188,8 +203,11 @@ c448_error_t curve448_point_decode_like_eddsa_and_mul_by_ratio(
* x (out): The ECDH private key as in RFC7748
* ed (in): The EdDSA private key
*/
-c448_error_t c448_ed448_convert_private_key_to_x448(
- uint8_t x[X448_PRIVATE_BYTES],
- const uint8_t ed[EDDSA_448_PRIVATE_BYTES]);
+c448_error_t
+ossl_c448_ed448_convert_private_key_to_x448(
+ OSSL_LIB_CTX *ctx,
+ uint8_t x[X448_PRIVATE_BYTES],
+ const uint8_t ed[EDDSA_448_PRIVATE_BYTES],
+ const char *propq);
#endif /* OSSL_CRYPTO_EC_CURVE448_ED448_H */
diff --git a/crypto/ec/curve448/eddsa.c b/crypto/ec/curve448/eddsa.c
index 82741f543549..6648692ff395 100644
--- a/crypto/ec/curve448/eddsa.c
+++ b/crypto/ec/curve448/eddsa.c
@@ -1,8 +1,8 @@
/*
- * Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2016 Cryptography Research, Inc.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,6 +12,7 @@
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
+#include "crypto/ecx.h"
#include "curve448_local.h"
#include "word.h"
#include "ed448.h"
@@ -19,23 +20,31 @@
#define COFACTOR 4
-static c448_error_t oneshot_hash(uint8_t *out, size_t outlen,
- const uint8_t *in, size_t inlen)
+static c448_error_t oneshot_hash(OSSL_LIB_CTX *ctx, uint8_t *out, size_t outlen,
+ const uint8_t *in, size_t inlen,
+ const char *propq)
{
EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
+ EVP_MD *shake256 = NULL;
+ c448_error_t ret = C448_FAILURE;
if (hashctx == NULL)
return C448_FAILURE;
- if (!EVP_DigestInit_ex(hashctx, EVP_shake256(), NULL)
+ shake256 = EVP_MD_fetch(ctx, "SHAKE256", propq);
+ if (shake256 == NULL)
+ goto err;
+
+ if (!EVP_DigestInit_ex(hashctx, shake256, NULL)
|| !EVP_DigestUpdate(hashctx, in, inlen)
- || !EVP_DigestFinalXOF(hashctx, out, outlen)) {
- EVP_MD_CTX_free(hashctx);
- return C448_FAILURE;
- }
+ || !EVP_DigestFinalXOF(hashctx, out, outlen))
+ goto err;
+ ret = C448_SUCCESS;
+ err:
EVP_MD_CTX_free(hashctx);
- return C448_SUCCESS;
+ EVP_MD_free(shake256);
+ return ret;
}
static void clamp(uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES])
@@ -45,10 +54,12 @@ static void clamp(uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES])
secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 2] |= 0x80;
}
-static c448_error_t hash_init_with_dom(EVP_MD_CTX *hashctx, uint8_t prehashed,
+static c448_error_t hash_init_with_dom(OSSL_LIB_CTX *ctx, EVP_MD_CTX *hashctx,
+ uint8_t prehashed,
uint8_t for_prehash,
const uint8_t *context,
- size_t context_len)
+ size_t context_len,
+ const char *propq)
{
#ifdef CHARSET_EBCDIC
const char dom_s[] = {0x53, 0x69, 0x67, 0x45,
@@ -57,6 +68,7 @@ static c448_error_t hash_init_with_dom(EVP_MD_CTX *hashctx, uint8_t prehashed,
const char dom_s[] = "SigEd448";
#endif
uint8_t dom[2];
+ EVP_MD *shake256 = NULL;
if (context_len > UINT8_MAX)
return C448_FAILURE;
@@ -65,29 +77,42 @@ static c448_error_t hash_init_with_dom(EVP_MD_CTX *hashctx, uint8_t prehashed,
- (for_prehash == 0 ? 1 : 0));
dom[1] = (uint8_t)context_len;
- if (!EVP_DigestInit_ex(hashctx, EVP_shake256(), NULL)
+ shake256 = EVP_MD_fetch(ctx, "SHAKE256", propq);
+ if (shake256 == NULL)
+ return C448_FAILURE;
+
+ if (!EVP_DigestInit_ex(hashctx, shake256, NULL)
|| !EVP_DigestUpdate(hashctx, dom_s, strlen(dom_s))
|| !EVP_DigestUpdate(hashctx, dom, sizeof(dom))
- || !EVP_DigestUpdate(hashctx, context, context_len))
+ || !EVP_DigestUpdate(hashctx, context, context_len)) {
+ EVP_MD_free(shake256);
return C448_FAILURE;
+ }
+ EVP_MD_free(shake256);
return C448_SUCCESS;
}
/* In this file because it uses the hash */
-c448_error_t c448_ed448_convert_private_key_to_x448(
+c448_error_t
+ossl_c448_ed448_convert_private_key_to_x448(
+ OSSL_LIB_CTX *ctx,
uint8_t x[X448_PRIVATE_BYTES],
- const uint8_t ed [EDDSA_448_PRIVATE_BYTES])
+ const uint8_t ed [EDDSA_448_PRIVATE_BYTES],
+ const char *propq)
{
/* pass the private key through oneshot_hash function */
/* and keep the first X448_PRIVATE_BYTES bytes */
- return oneshot_hash(x, X448_PRIVATE_BYTES, ed,
- EDDSA_448_PRIVATE_BYTES);
+ return oneshot_hash(ctx, x, X448_PRIVATE_BYTES, ed,
+ EDDSA_448_PRIVATE_BYTES, propq);
}
-c448_error_t c448_ed448_derive_public_key(
+c448_error_t
+ossl_c448_ed448_derive_public_key(
+ OSSL_LIB_CTX *ctx,
uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
- const uint8_t privkey[EDDSA_448_PRIVATE_BYTES])
+ const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
+ const char *propq)
{
/* only this much used for keygen */
uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES];
@@ -95,14 +120,16 @@ c448_error_t c448_ed448_derive_public_key(
unsigned int c;
curve448_point_t p;
- if (!oneshot_hash(secret_scalar_ser, sizeof(secret_scalar_ser), privkey,
- EDDSA_448_PRIVATE_BYTES))
+ if (!oneshot_hash(ctx, secret_scalar_ser, sizeof(secret_scalar_ser),
+ privkey,
+ EDDSA_448_PRIVATE_BYTES,
+ propq))
return C448_FAILURE;
clamp(secret_scalar_ser);
- curve448_scalar_decode_long(secret_scalar, secret_scalar_ser,
- sizeof(secret_scalar_ser));
+ ossl_curve448_scalar_decode_long(secret_scalar, secret_scalar_ser,
+ sizeof(secret_scalar_ser));
/*
* Since we are going to mul_by_cofactor during encoding, divide by it
@@ -113,27 +140,29 @@ c448_error_t c448_ed448_derive_public_key(
* we might start at 2 instead of 1.
*/
for (c = 1; c < C448_EDDSA_ENCODE_RATIO; c <<= 1)
- curve448_scalar_halve(secret_scalar, secret_scalar);
+ ossl_curve448_scalar_halve(secret_scalar, secret_scalar);
- curve448_precomputed_scalarmul(p, curve448_precomputed_base, secret_scalar);
+ ossl_curve448_precomputed_scalarmul(p, ossl_curve448_precomputed_base,
+ secret_scalar);
- curve448_point_mul_by_ratio_and_encode_like_eddsa(pubkey, p);
+ ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa(pubkey, p);
/* Cleanup */
- curve448_scalar_destroy(secret_scalar);
- curve448_point_destroy(p);
+ ossl_curve448_scalar_destroy(secret_scalar);
+ ossl_curve448_point_destroy(p);
OPENSSL_cleanse(secret_scalar_ser, sizeof(secret_scalar_ser));
return C448_SUCCESS;
}
-c448_error_t c448_ed448_sign(
- uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
- const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
- const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
- const uint8_t *message, size_t message_len,
- uint8_t prehashed, const uint8_t *context,
- size_t context_len)
+c448_error_t
+ossl_c448_ed448_sign(OSSL_LIB_CTX *ctx,
+ uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
+ const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
+ const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
+ const uint8_t *message, size_t message_len,
+ uint8_t prehashed, const uint8_t *context,
+ size_t context_len, const char *propq)
{
curve448_scalar_t secret_scalar;
EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
@@ -148,20 +177,21 @@ c448_error_t c448_ed448_sign(
{
/*
- * Schedule the secret key, First EDDSA_448_PRIVATE_BYTES is serialised
+ * Schedule the secret key, First EDDSA_448_PRIVATE_BYTES is serialized
* secret scalar,next EDDSA_448_PRIVATE_BYTES bytes is the seed.
*/
uint8_t expanded[EDDSA_448_PRIVATE_BYTES * 2];
- if (!oneshot_hash(expanded, sizeof(expanded), privkey,
- EDDSA_448_PRIVATE_BYTES))
+ if (!oneshot_hash(ctx, expanded, sizeof(expanded), privkey,
+ EDDSA_448_PRIVATE_BYTES, propq))
goto err;
clamp(expanded);
- curve448_scalar_decode_long(secret_scalar, expanded,
- EDDSA_448_PRIVATE_BYTES);
+ ossl_curve448_scalar_decode_long(secret_scalar, expanded,
+ EDDSA_448_PRIVATE_BYTES);
/* Hash to create the nonce */
- if (!hash_init_with_dom(hashctx, prehashed, 0, context, context_len)
+ if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context,
+ context_len, propq)
|| !EVP_DigestUpdate(hashctx,
expanded + EDDSA_448_PRIVATE_BYTES,
EDDSA_448_PRIVATE_BYTES)
@@ -178,7 +208,7 @@ c448_error_t c448_ed448_sign(
if (!EVP_DigestFinalXOF(hashctx, nonce, sizeof(nonce)))
goto err;
- curve448_scalar_decode_long(nonce_scalar, nonce, sizeof(nonce));
+ ossl_curve448_scalar_decode_long(nonce_scalar, nonce, sizeof(nonce));
OPENSSL_cleanse(nonce, sizeof(nonce));
}
@@ -187,44 +217,45 @@ c448_error_t c448_ed448_sign(
curve448_scalar_t nonce_scalar_2;
curve448_point_t p;
- curve448_scalar_halve(nonce_scalar_2, nonce_scalar);
+ ossl_curve448_scalar_halve(nonce_scalar_2, nonce_scalar);
for (c = 2; c < C448_EDDSA_ENCODE_RATIO; c <<= 1)
- curve448_scalar_halve(nonce_scalar_2, nonce_scalar_2);
+ ossl_curve448_scalar_halve(nonce_scalar_2, nonce_scalar_2);
- curve448_precomputed_scalarmul(p, curve448_precomputed_base,
- nonce_scalar_2);
- curve448_point_mul_by_ratio_and_encode_like_eddsa(nonce_point, p);
- curve448_point_destroy(p);
- curve448_scalar_destroy(nonce_scalar_2);
+ ossl_curve448_precomputed_scalarmul(p, ossl_curve448_precomputed_base,
+ nonce_scalar_2);
+ ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa(nonce_point, p);
+ ossl_curve448_point_destroy(p);
+ ossl_curve448_scalar_destroy(nonce_scalar_2);
}
{
uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES];
/* Compute the challenge */
- if (!hash_init_with_dom(hashctx, prehashed, 0, context, context_len)
+ if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context, context_len,
+ propq)
|| !EVP_DigestUpdate(hashctx, nonce_point, sizeof(nonce_point))
|| !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES)
|| !EVP_DigestUpdate(hashctx, message, message_len)
|| !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge)))
goto err;
- curve448_scalar_decode_long(challenge_scalar, challenge,
- sizeof(challenge));
+ ossl_curve448_scalar_decode_long(challenge_scalar, challenge,
+ sizeof(challenge));
OPENSSL_cleanse(challenge, sizeof(challenge));
}
- curve448_scalar_mul(challenge_scalar, challenge_scalar, secret_scalar);
- curve448_scalar_add(challenge_scalar, challenge_scalar, nonce_scalar);
+ ossl_curve448_scalar_mul(challenge_scalar, challenge_scalar, secret_scalar);
+ ossl_curve448_scalar_add(challenge_scalar, challenge_scalar, nonce_scalar);
OPENSSL_cleanse(signature, EDDSA_448_SIGNATURE_BYTES);
memcpy(signature, nonce_point, sizeof(nonce_point));
- curve448_scalar_encode(&signature[EDDSA_448_PUBLIC_BYTES],
- challenge_scalar);
+ ossl_curve448_scalar_encode(&signature[EDDSA_448_PUBLIC_BYTES],
+ challenge_scalar);
- curve448_scalar_destroy(secret_scalar);
- curve448_scalar_destroy(nonce_scalar);
- curve448_scalar_destroy(challenge_scalar);
+ ossl_curve448_scalar_destroy(secret_scalar);
+ ossl_curve448_scalar_destroy(nonce_scalar);
+ ossl_curve448_scalar_destroy(challenge_scalar);
ret = C448_SUCCESS;
err:
@@ -232,23 +263,27 @@ c448_error_t c448_ed448_sign(
return ret;
}
-c448_error_t c448_ed448_sign_prehash(
+c448_error_t
+ossl_c448_ed448_sign_prehash(
+ OSSL_LIB_CTX *ctx,
uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
const uint8_t hash[64], const uint8_t *context,
- size_t context_len)
+ size_t context_len, const char *propq)
{
- return c448_ed448_sign(signature, privkey, pubkey, hash, 64, 1, context,
- context_len);
+ return ossl_c448_ed448_sign(ctx, signature, privkey, pubkey, hash, 64, 1,
+ context, context_len, propq);
}
-c448_error_t c448_ed448_verify(
+c448_error_t
+ossl_c448_ed448_verify(
+ OSSL_LIB_CTX *ctx,
const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
const uint8_t *message, size_t message_len,
uint8_t prehashed, const uint8_t *context,
- uint8_t context_len)
+ uint8_t context_len, const char *propq)
{
curve448_point_t pk_point, r_point;
c448_error_t error;
@@ -280,13 +315,13 @@ c448_error_t c448_ed448_verify(
return C448_FAILURE;
error =
- curve448_point_decode_like_eddsa_and_mul_by_ratio(pk_point, pubkey);
+ ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(pk_point, pubkey);
if (C448_SUCCESS != error)
return error;
error =
- curve448_point_decode_like_eddsa_and_mul_by_ratio(r_point, signature);
+ ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(r_point, signature);
if (C448_SUCCESS != error)
return error;
@@ -296,8 +331,8 @@ c448_error_t c448_ed448_verify(
uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES];
if (hashctx == NULL
- || !hash_init_with_dom(hashctx, prehashed, 0, context,
- context_len)
+ || !hash_init_with_dom(ctx, hashctx, prehashed, 0, context,
+ context_len, propq)
|| !EVP_DigestUpdate(hashctx, signature, EDDSA_448_PUBLIC_BYTES)
|| !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES)
|| !EVP_DigestUpdate(hashctx, message, message_len)
@@ -307,71 +342,82 @@ c448_error_t c448_ed448_verify(
}
EVP_MD_CTX_free(hashctx);
- curve448_scalar_decode_long(challenge_scalar, challenge,
- sizeof(challenge));
+ ossl_curve448_scalar_decode_long(challenge_scalar, challenge,
+ sizeof(challenge));
OPENSSL_cleanse(challenge, sizeof(challenge));
}
- curve448_scalar_sub(challenge_scalar, curve448_scalar_zero,
- challenge_scalar);
+ ossl_curve448_scalar_sub(challenge_scalar, ossl_curve448_scalar_zero,
+ challenge_scalar);
- curve448_scalar_decode_long(response_scalar,
- &signature[EDDSA_448_PUBLIC_BYTES],
- EDDSA_448_PRIVATE_BYTES);
+ ossl_curve448_scalar_decode_long(response_scalar,
+ &signature[EDDSA_448_PUBLIC_BYTES],
+ EDDSA_448_PRIVATE_BYTES);
/* pk_point = -c(x(P)) + (cx + k)G = kG */
- curve448_base_double_scalarmul_non_secret(pk_point,
- response_scalar,
- pk_point, challenge_scalar);
- return c448_succeed_if(curve448_point_eq(pk_point, r_point));
+ ossl_curve448_base_double_scalarmul_non_secret(pk_point,
+ response_scalar,
+ pk_point, challenge_scalar);
+ return c448_succeed_if(ossl_curve448_point_eq(pk_point, r_point));
}
-c448_error_t c448_ed448_verify_prehash(
+c448_error_t
+ossl_c448_ed448_verify_prehash(
+ OSSL_LIB_CTX *ctx,
const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
const uint8_t hash[64], const uint8_t *context,
- uint8_t context_len)
+ uint8_t context_len, const char *propq)
{
- return c448_ed448_verify(signature, pubkey, hash, 64, 1, context,
- context_len);
+ return ossl_c448_ed448_verify(ctx, signature, pubkey, hash, 64, 1, context,
+ context_len, propq);
}
-int ED448_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
- const uint8_t public_key[57], const uint8_t private_key[57],
- const uint8_t *context, size_t context_len)
+int
+ossl_ed448_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig, const uint8_t *message,
+ size_t message_len, const uint8_t public_key[57],
+ const uint8_t private_key[57], const uint8_t *context,
+ size_t context_len, const char *propq)
{
- return c448_ed448_sign(out_sig, private_key, public_key, message,
- message_len, 0, context, context_len)
- == C448_SUCCESS;
+ return ossl_c448_ed448_sign(ctx, out_sig, private_key, public_key, message,
+ message_len, 0, context, context_len,
+ propq) == C448_SUCCESS;
}
-int ED448_verify(const uint8_t *message, size_t message_len,
- const uint8_t signature[114], const uint8_t public_key[57],
- const uint8_t *context, size_t context_len)
+int
+ossl_ed448_verify(OSSL_LIB_CTX *ctx, const uint8_t *message, size_t message_len,
+ const uint8_t signature[114], const uint8_t public_key[57],
+ const uint8_t *context, size_t context_len, const char *propq)
{
- return c448_ed448_verify(signature, public_key, message, message_len, 0,
- context, (uint8_t)context_len) == C448_SUCCESS;
+ return ossl_c448_ed448_verify(ctx, signature, public_key, message,
+ message_len, 0, context, (uint8_t)context_len,
+ propq) == C448_SUCCESS;
}
-int ED448ph_sign(uint8_t *out_sig, const uint8_t hash[64],
- const uint8_t public_key[57], const uint8_t private_key[57],
- const uint8_t *context, size_t context_len)
+int
+ossl_ed448ph_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig, const uint8_t hash[64],
+ const uint8_t public_key[57], const uint8_t private_key[57],
+ const uint8_t *context, size_t context_len, const char *propq)
{
- return c448_ed448_sign_prehash(out_sig, private_key, public_key, hash,
- context, context_len) == C448_SUCCESS;
-
+ return ossl_c448_ed448_sign_prehash(ctx, out_sig, private_key, public_key,
+ hash, context, context_len,
+ propq) == C448_SUCCESS;
}
-int ED448ph_verify(const uint8_t hash[64], const uint8_t signature[114],
- const uint8_t public_key[57], const uint8_t *context,
- size_t context_len)
+int
+ossl_ed448ph_verify(OSSL_LIB_CTX *ctx, const uint8_t hash[64],
+ const uint8_t signature[114], const uint8_t public_key[57],
+ const uint8_t *context, size_t context_len,
+ const char *propq)
{
- return c448_ed448_verify_prehash(signature, public_key, hash, context,
- (uint8_t)context_len) == C448_SUCCESS;
+ return ossl_c448_ed448_verify_prehash(ctx, signature, public_key, hash,
+ context, (uint8_t)context_len,
+ propq) == C448_SUCCESS;
}
-int ED448_public_from_private(uint8_t out_public_key[57],
- const uint8_t private_key[57])
+int
+ossl_ed448_public_from_private(OSSL_LIB_CTX *ctx, uint8_t out_public_key[57],
+ const uint8_t private_key[57], const char *propq)
{
- return c448_ed448_derive_public_key(out_public_key, private_key)
- == C448_SUCCESS;
+ return ossl_c448_ed448_derive_public_key(ctx, out_public_key, private_key,
+ propq) == C448_SUCCESS;
}
diff --git a/crypto/ec/curve448/f_generic.c b/crypto/ec/curve448/f_generic.c
index 09d08165e250..4c571810d3af 100644
--- a/crypto/ec/curve448/f_generic.c
+++ b/crypto/ec/curve448/f_generic.c
@@ -1,8 +1,8 @@
/*
- * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2016 Cryptography Research, Inc.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -18,7 +18,7 @@ static const gf MODULUS = {
};
/* Serialize to wire format. */
-void gf_serialize(uint8_t serial[SER_BYTES], const gf x, int with_hibit)
+void gf_serialize(uint8_t *serial, const gf x, int with_hibit)
{
unsigned int j = 0, fill = 0;
dword_t buffer = 0;
diff --git a/crypto/ec/curve448/field.h b/crypto/ec/curve448/field.h
index 4e4eda664f78..e1c633378950 100644
--- a/crypto/ec/curve448/field.h
+++ b/crypto/ec/curve448/field.h
@@ -2,7 +2,7 @@
* Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2014 Cryptography Research, Inc.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -62,14 +62,19 @@ mask_t gf_eq(const gf x, const gf y);
mask_t gf_lobit(const gf x);
mask_t gf_hibit(const gf x);
-void gf_serialize(uint8_t serial[SER_BYTES], const gf x, int with_highbit);
+void gf_serialize(uint8_t *serial, const gf x, int with_highbit);
mask_t gf_deserialize(gf x, const uint8_t serial[SER_BYTES], int with_hibit,
uint8_t hi_nmask);
-# include "f_impl.h" /* Bring in the inline implementations */
# define LIMBPERM(i) (i)
-# define LIMB_MASK(i) (((1)<<LIMB_PLACE_VALUE(i))-1)
+# if (ARCH_WORD_BITS == 32)
+# include "arch_32/f_impl.h" /* Bring in the inline implementations */
+# define LIMB_MASK(i) (((1)<<LIMB_PLACE_VALUE(i))-1)
+# elif (ARCH_WORD_BITS == 64)
+# include "arch_64/f_impl.h" /* Bring in the inline implementations */
+# define LIMB_MASK(i) (((1ULL)<<LIMB_PLACE_VALUE(i))-1)
+# endif
static const gf ZERO = {{{0}}}, ONE = {{{1}}};
diff --git a/crypto/ec/curve448/point_448.h b/crypto/ec/curve448/point_448.h
index 93e715fd9c8d..e67ea68044eb 100644
--- a/crypto/ec/curve448/point_448.h
+++ b/crypto/ec/curve448/point_448.h
@@ -1,8 +1,8 @@
/*
- * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2016 Cryptography Research, Inc.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -69,17 +69,17 @@ typedef struct curve448_scalar_s {
} curve448_scalar_t[1];
/* A scalar equal to 1. */
-extern const curve448_scalar_t curve448_scalar_one;
+extern const curve448_scalar_t ossl_curve448_scalar_one;
/* A scalar equal to 0. */
-extern const curve448_scalar_t curve448_scalar_zero;
+extern const curve448_scalar_t ossl_curve448_scalar_zero;
/* The identity point on the curve. */
-extern const curve448_point_t curve448_point_identity;
+extern const curve448_point_t ossl_curve448_point_identity;
/* Precomputed table for the base point on the curve. */
-extern const struct curve448_precomputed_s *curve448_precomputed_base;
-extern const niels_t *curve448_wnaf_base;
+extern const struct curve448_precomputed_s *ossl_curve448_precomputed_base;
+extern const niels_t *ossl_curve448_wnaf_base;
/*
* Read a scalar from wire format or from bytes.
@@ -92,8 +92,9 @@ extern const niels_t *curve448_wnaf_base;
* C448_FAILURE: The scalar was greater than the modulus, and has been reduced
* modulo that modulus.
*/
-c448_error_t curve448_scalar_decode(curve448_scalar_t out,
- const unsigned char ser[C448_SCALAR_BYTES]);
+c448_error_t
+ossl_curve448_scalar_decode(curve448_scalar_t out,
+ const unsigned char ser[C448_SCALAR_BYTES]);
/*
* Read a scalar from wire format or from bytes. Reduces mod scalar prime.
@@ -102,7 +103,8 @@ c448_error_t curve448_scalar_decode(curve448_scalar_t out,
* ser_len (in): Length of serialized form.
* out (out): Deserialized form.
*/
-void curve448_scalar_decode_long(curve448_scalar_t out,
+void
+ossl_curve448_scalar_decode_long(curve448_scalar_t out,
const unsigned char *ser, size_t ser_len);
/*
@@ -111,7 +113,8 @@ void curve448_scalar_decode_long(curve448_scalar_t out,
* ser (out): Serialized form of a scalar.
* s (in): Deserialized scalar.
*/
-void curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES],
+void
+ossl_curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES],
const curve448_scalar_t s);
/*
@@ -121,7 +124,8 @@ void curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES],
* b (in): Another scalar.
* out (out): a+b.
*/
-void curve448_scalar_add(curve448_scalar_t out,
+void
+ossl_curve448_scalar_add(curve448_scalar_t out,
const curve448_scalar_t a, const curve448_scalar_t b);
/*
@@ -130,7 +134,8 @@ void curve448_scalar_add(curve448_scalar_t out,
* b (in): Another scalar.
* out (out): a-b.
*/
-void curve448_scalar_sub(curve448_scalar_t out,
+void
+ossl_curve448_scalar_sub(curve448_scalar_t out,
const curve448_scalar_t a, const curve448_scalar_t b);
/*
@@ -140,7 +145,8 @@ void curve448_scalar_sub(curve448_scalar_t out,
* b (in): Another scalar.
* out (out): a*b.
*/
-void curve448_scalar_mul(curve448_scalar_t out,
+void
+ossl_curve448_scalar_mul(curve448_scalar_t out,
const curve448_scalar_t a, const curve448_scalar_t b);
/*
@@ -149,7 +155,8 @@ void curve448_scalar_mul(curve448_scalar_t out,
* a (in): A scalar.
* out (out): a/2.
*/
-void curve448_scalar_halve(curve448_scalar_t out, const curve448_scalar_t a);
+void
+ossl_curve448_scalar_halve(curve448_scalar_t out, const curve448_scalar_t a);
/*
* Copy a scalar. The scalars may alias each other, in which case this
@@ -188,8 +195,9 @@ static ossl_inline void curve448_point_copy(curve448_point_t a,
* C448_TRUE: The points are equal.
* C448_FALSE: The points are not equal.
*/
-__owur c448_bool_t curve448_point_eq(const curve448_point_t a,
- const curve448_point_t b);
+__owur c448_bool_t
+ossl_curve448_point_eq(const curve448_point_t a,
+ const curve448_point_t b);
/*
* Double a point. Equivalent to curve448_point_add(two_a,a,a), but potentially
@@ -198,7 +206,8 @@ __owur c448_bool_t curve448_point_eq(const curve448_point_t a,
* two_a (out): The sum a+a.
* a (in): A point.
*/
-void curve448_point_double(curve448_point_t two_a, const curve448_point_t a);
+void
+ossl_curve448_point_double(curve448_point_t two_a, const curve448_point_t a);
/*
* RFC 7748 Diffie-Hellman scalarmul. This function uses a different
@@ -213,9 +222,10 @@ void curve448_point_double(curve448_point_t two_a, const curve448_point_t a);
* C448_FAILURE: The scalarmul didn't succeed, because the base point is in a
* small subgroup.
*/
-__owur c448_error_t x448_int(uint8_t out[X448_PUBLIC_BYTES],
- const uint8_t base[X448_PUBLIC_BYTES],
- const uint8_t scalar[X448_PRIVATE_BYTES]);
+__owur c448_error_t
+ossl_x448_int(uint8_t out[X448_PUBLIC_BYTES],
+ const uint8_t base[X448_PUBLIC_BYTES],
+ const uint8_t scalar[X448_PRIVATE_BYTES]);
/*
* Multiply a point by X448_ENCODE_RATIO, then encode it like RFC 7748.
@@ -236,7 +246,8 @@ __owur c448_error_t x448_int(uint8_t out[X448_PUBLIC_BYTES],
* out (out): The scaled and encoded point.
* p (in): The point to be scaled and encoded.
*/
-void curve448_point_mul_by_ratio_and_encode_like_x448(
+void
+ossl_curve448_point_mul_by_ratio_and_encode_like_x448(
uint8_t out[X448_PUBLIC_BYTES],
const curve448_point_t p);
@@ -247,7 +258,8 @@ void curve448_point_mul_by_ratio_and_encode_like_x448(
* out (out): The scaled point base*scalar
* scalar (in): The scalar to multiply by.
*/
-void x448_derive_public_key(uint8_t out[X448_PUBLIC_BYTES],
+void
+ossl_x448_derive_public_key(uint8_t out[X448_PUBLIC_BYTES],
const uint8_t scalar[X448_PRIVATE_BYTES]);
/*
@@ -257,7 +269,8 @@ void x448_derive_public_key(uint8_t out[X448_PUBLIC_BYTES],
* base (in): The point to be scaled.
* scalar (in): The scalar to multiply by.
*/
-void curve448_precomputed_scalarmul(curve448_point_t scaled,
+void
+ossl_curve448_precomputed_scalarmul(curve448_point_t scaled,
const curve448_precomputed_s * base,
const curve448_scalar_t scalar);
@@ -276,7 +289,8 @@ void curve448_precomputed_scalarmul(curve448_point_t scaled,
* Warning: This function takes variable time, and may leak the scalars used.
* It is designed for signature verification.
*/
-void curve448_base_double_scalarmul_non_secret(curve448_point_t combo,
+void
+ossl_curve448_base_double_scalarmul_non_secret(curve448_point_t combo,
const curve448_scalar_t scalar1,
const curve448_point_t base2,
const curve448_scalar_t scalar2);
@@ -290,12 +304,13 @@ void curve448_base_double_scalarmul_non_secret(curve448_point_t combo,
* C448_TRUE The point is valid.
* C448_FALSE The point is invalid.
*/
-__owur c448_bool_t curve448_point_valid(const curve448_point_t to_test);
+__owur c448_bool_t
+ossl_curve448_point_valid(const curve448_point_t to_test);
/* Overwrite scalar with zeros. */
-void curve448_scalar_destroy(curve448_scalar_t scalar);
+void ossl_curve448_scalar_destroy(curve448_scalar_t scalar);
/* Overwrite point with zeros. */
-void curve448_point_destroy(curve448_point_t point);
+void ossl_curve448_point_destroy(curve448_point_t point);
#endif /* OSSL_CRYPTO_EC_CURVE448_POINT_448_H */
diff --git a/crypto/ec/curve448/scalar.c b/crypto/ec/curve448/scalar.c
index 347794bbac38..99c0d83db13b 100644
--- a/crypto/ec/curve448/scalar.c
+++ b/crypto/ec/curve448/scalar.c
@@ -1,8 +1,8 @@
/*
- * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2016 Cryptography Research, Inc.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -38,8 +38,8 @@ static const curve448_scalar_t sc_p = {
#define WBITS C448_WORD_BITS /* NB this may be different from ARCH_WORD_BITS */
-const curve448_scalar_t curve448_scalar_one = {{{1}}};
-const curve448_scalar_t curve448_scalar_zero = {{{0}}};
+const curve448_scalar_t ossl_curve448_scalar_one = {{{1}}};
+const curve448_scalar_t ossl_curve448_scalar_zero = {{{0}}};
/*
* {extra,accum} - sub +? p
@@ -106,20 +106,22 @@ static void sc_montmul(curve448_scalar_t out, const curve448_scalar_t a,
sc_subx(out, accum, sc_p, sc_p, hi_carry);
}
-void curve448_scalar_mul(curve448_scalar_t out, const curve448_scalar_t a,
- const curve448_scalar_t b)
+void ossl_curve448_scalar_mul(curve448_scalar_t out, const curve448_scalar_t a,
+ const curve448_scalar_t b)
{
sc_montmul(out, a, b);
sc_montmul(out, out, sc_r2);
}
-void curve448_scalar_sub(curve448_scalar_t out, const curve448_scalar_t a,
+void
+ossl_curve448_scalar_sub(curve448_scalar_t out, const curve448_scalar_t a,
const curve448_scalar_t b)
{
sc_subx(out, a->limb, b, sc_p, 0);
}
-void curve448_scalar_add(curve448_scalar_t out, const curve448_scalar_t a,
+void
+ossl_curve448_scalar_add(curve448_scalar_t out, const curve448_scalar_t a,
const curve448_scalar_t b)
{
c448_dword_t chain = 0;
@@ -148,9 +150,9 @@ static ossl_inline void scalar_decode_short(curve448_scalar_t s,
}
}
-c448_error_t curve448_scalar_decode(
- curve448_scalar_t s,
- const unsigned char ser[C448_SCALAR_BYTES])
+c448_error_t
+ossl_curve448_scalar_decode(curve448_scalar_t s,
+ const unsigned char ser[C448_SCALAR_BYTES])
{
unsigned int i;
c448_dsword_t accum = 0;
@@ -160,24 +162,25 @@ c448_error_t curve448_scalar_decode(
accum = (accum + s->limb[i] - sc_p->limb[i]) >> WBITS;
/* Here accum == 0 or -1 */
- curve448_scalar_mul(s, s, curve448_scalar_one); /* ham-handed reduce */
+ ossl_curve448_scalar_mul(s, s, ossl_curve448_scalar_one); /* ham-handed reduce */
return c448_succeed_if(~word_is_zero((uint32_t)accum));
}
-void curve448_scalar_destroy(curve448_scalar_t scalar)
+void ossl_curve448_scalar_destroy(curve448_scalar_t scalar)
{
OPENSSL_cleanse(scalar, sizeof(curve448_scalar_t));
}
-void curve448_scalar_decode_long(curve448_scalar_t s,
+void
+ossl_curve448_scalar_decode_long(curve448_scalar_t s,
const unsigned char *ser, size_t ser_len)
{
size_t i;
curve448_scalar_t t1, t2;
if (ser_len == 0) {
- curve448_scalar_copy(s, curve448_scalar_zero);
+ curve448_scalar_copy(s, ossl_curve448_scalar_zero);
return;
}
@@ -190,24 +193,25 @@ void curve448_scalar_decode_long(curve448_scalar_t s,
if (ser_len == sizeof(curve448_scalar_t)) {
assert(i == 0);
/* ham-handed reduce */
- curve448_scalar_mul(s, t1, curve448_scalar_one);
- curve448_scalar_destroy(t1);
+ ossl_curve448_scalar_mul(s, t1, ossl_curve448_scalar_one);
+ ossl_curve448_scalar_destroy(t1);
return;
}
while (i) {
i -= C448_SCALAR_BYTES;
sc_montmul(t1, t1, sc_r2);
- (void)curve448_scalar_decode(t2, ser + i);
- curve448_scalar_add(t1, t1, t2);
+ (void)ossl_curve448_scalar_decode(t2, ser + i);
+ ossl_curve448_scalar_add(t1, t1, t2);
}
curve448_scalar_copy(s, t1);
- curve448_scalar_destroy(t1);
- curve448_scalar_destroy(t2);
+ ossl_curve448_scalar_destroy(t1);
+ ossl_curve448_scalar_destroy(t2);
}
-void curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES],
+void
+ossl_curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES],
const curve448_scalar_t s)
{
unsigned int i, j, k = 0;
@@ -218,7 +222,8 @@ void curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES],
}
}
-void curve448_scalar_halve(curve448_scalar_t out, const curve448_scalar_t a)
+void
+ossl_curve448_scalar_halve(curve448_scalar_t out, const curve448_scalar_t a)
{
c448_word_t mask = 0 - (a->limb[0] & 1);
c448_dword_t chain = 0;
diff --git a/crypto/ec/curve448/word.h b/crypto/ec/curve448/word.h
index 237cc9b63139..f8292eef88f2 100644
--- a/crypto/ec/curve448/word.h
+++ b/crypto/ec/curve448/word.h
@@ -1,8 +1,8 @@
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2014 Cryptography Research, Inc.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -17,15 +17,20 @@
# include <assert.h>
# include <stdlib.h>
# include <openssl/e_os2.h>
-# include "arch_intrinsics.h"
# include "curve448utils.h"
+# ifdef INT128_MAX
+# include "arch_64/arch_intrinsics.h"
+# else
+# include "arch_32/arch_intrinsics.h"
+# endif
+
# if (ARCH_WORD_BITS == 64)
typedef uint64_t word_t, mask_t;
-typedef __uint128_t dword_t;
+typedef uint128_t dword_t;
typedef int32_t hsword_t;
typedef int64_t sword_t;
-typedef __int128_t dsword_t;
+typedef int128_t dsword_t;
# elif (ARCH_WORD_BITS == 32)
typedef uint32_t word_t, mask_t;
typedef uint64_t dword_t;
diff --git a/crypto/ec/ec2_oct.c b/crypto/ec/ec2_oct.c
index 788e6501fbcd..10a4932591d6 100644
--- a/crypto/ec/ec2_oct.c
+++ b/crypto/ec/ec2_oct.c
@@ -2,12 +2,18 @@
* Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/err.h>
#include "ec_local.h"
@@ -30,23 +36,22 @@
* the same method, but claim no priority date earlier than July 29, 1994
* (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
*/
-int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group,
- EC_POINT *point,
- const BIGNUM *x_, int y_bit,
- BN_CTX *ctx)
+int ossl_ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group,
+ EC_POINT *point,
+ const BIGNUM *x_, int y_bit,
+ BN_CTX *ctx)
{
- BN_CTX *new_ctx = NULL;
BIGNUM *tmp, *x, *y, *z;
int ret = 0, z0;
-
- /* clear error queue */
- ERR_clear_error();
+#ifndef FIPS_MODULE
+ BN_CTX *new_ctx = NULL;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
+#endif
y_bit = (y_bit != 0) ? 1 : 0;
@@ -72,19 +77,24 @@ int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group,
goto err;
if (!BN_GF2m_add(tmp, x, tmp))
goto err;
+ ERR_set_mark();
if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx)) {
+#ifndef FIPS_MODULE
unsigned long err = ERR_peek_last_error();
if (ERR_GET_LIB(err) == ERR_LIB_BN
&& ERR_GET_REASON(err) == BN_R_NO_SOLUTION) {
- ERR_clear_error();
- ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES,
- EC_R_INVALID_COMPRESSED_POINT);
+ ERR_pop_to_mark();
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_COMPRESSED_POINT);
} else
- ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES,
- ERR_R_BN_LIB);
+#endif
+ {
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
+ }
goto err;
}
+ ERR_clear_last_mark();
z0 = (BN_is_odd(z)) ? 1 : 0;
if (!group->meth->field_mul(group, y, x, z, ctx))
goto err;
@@ -101,7 +111,9 @@ int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group,
err:
BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
return ret;
}
@@ -110,20 +122,23 @@ int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group,
* length will be returned. If the length len of buf is smaller than required
* an error will be returned.
*/
-size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
- point_conversion_form_t form,
- unsigned char *buf, size_t len, BN_CTX *ctx)
+size_t ossl_ec_GF2m_simple_point2oct(const EC_GROUP *group,
+ const EC_POINT *point,
+ point_conversion_form_t form,
+ unsigned char *buf, size_t len, BN_CTX *ctx)
{
size_t ret;
- BN_CTX *new_ctx = NULL;
int used_ctx = 0;
BIGNUM *x, *y, *yxi;
size_t field_len, i, skip;
+#ifndef FIPS_MODULE
+ BN_CTX *new_ctx = NULL;
+#endif
if ((form != POINT_CONVERSION_COMPRESSED)
&& (form != POINT_CONVERSION_UNCOMPRESSED)
&& (form != POINT_CONVERSION_HYBRID)) {
- ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_FORM);
goto err;
}
@@ -131,7 +146,7 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
/* encodes to a single 0 octet */
if (buf != NULL) {
if (len < 1) {
- ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
+ ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
return 0;
}
buf[0] = 0;
@@ -148,15 +163,17 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
/* if 'buf' is NULL, just return required length */
if (buf != NULL) {
if (len < ret) {
- ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
+ ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
goto err;
}
+#ifndef FIPS_MODULE
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
+#endif
BN_CTX_start(ctx);
used_ctx = 1;
@@ -181,7 +198,7 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
skip = field_len - BN_num_bytes(x);
if (skip > field_len) {
- ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
goto err;
}
while (skip > 0) {
@@ -191,7 +208,7 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
skip = BN_bn2bin(x, buf + i);
i += skip;
if (i != 1 + field_len) {
- ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -199,7 +216,7 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
|| form == POINT_CONVERSION_HYBRID) {
skip = field_len - BN_num_bytes(y);
if (skip > field_len) {
- ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
goto err;
}
while (skip > 0) {
@@ -211,20 +228,24 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
}
if (i != ret) {
- ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (used_ctx)
BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
return ret;
err:
if (used_ctx)
BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
return 0;
}
@@ -232,19 +253,21 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
* Converts an octet string representation to an EC_POINT. Note that the
* simple implementation only uses affine coordinates.
*/
-int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
- const unsigned char *buf, size_t len,
- BN_CTX *ctx)
+int ossl_ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
+ const unsigned char *buf, size_t len,
+ BN_CTX *ctx)
{
point_conversion_form_t form;
int y_bit, m;
- BN_CTX *new_ctx = NULL;
BIGNUM *x, *y, *yxi;
size_t field_len, enc_len;
int ret = 0;
+#ifndef FIPS_MODULE
+ BN_CTX *new_ctx = NULL;
+#endif
if (len == 0) {
- ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
+ ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
return 0;
}
@@ -265,18 +288,18 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
&& (form != POINT_CONVERSION_UNCOMPRESSED)
&& (form != POINT_CONVERSION_HYBRID)) {
- ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
return 0;
}
if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) {
- ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
return 0;
}
/* The point at infinity is represented by a single zero octet. */
if (form == 0) {
if (len != 1) {
- ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
return 0;
}
@@ -290,15 +313,17 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
if (len != enc_len) {
- ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
return 0;
}
+#ifndef FIPS_MODULE
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
+#endif
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
@@ -310,7 +335,7 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
if (!BN_bin2bn(buf + 1, field_len, x))
goto err;
if (BN_num_bits(x) > m) {
- ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
goto err;
}
@@ -321,7 +346,7 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
if (!BN_bin2bn(buf + 1 + field_len, field_len, y))
goto err;
if (BN_num_bits(y) > m) {
- ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
goto err;
}
if (form == POINT_CONVERSION_HYBRID) {
@@ -332,14 +357,14 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
*/
if (BN_is_zero(x)) {
if (y_bit != 0) {
- ECerr(ERR_LIB_EC, EC_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
goto err;
}
} else {
if (!group->meth->field_div(group, yxi, y, x, ctx))
goto err;
if (y_bit != BN_is_odd(yxi)) {
- ECerr(ERR_LIB_EC, EC_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
goto err;
}
}
@@ -357,7 +382,9 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
err:
BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
return ret;
}
#endif
diff --git a/crypto/ec/ec2_smpl.c b/crypto/ec/ec2_smpl.c
index 84e5537a034a..3a59544c8b2f 100644
--- a/crypto/ec/ec2_smpl.c
+++ b/crypto/ec/ec2_smpl.c
@@ -1,13 +1,19 @@
/*
- * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/err.h>
#include "crypto/bn.h"
@@ -19,7 +25,7 @@
* Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members
* are handled by EC_GROUP_new.
*/
-int ec_GF2m_simple_group_init(EC_GROUP *group)
+int ossl_ec_GF2m_simple_group_init(EC_GROUP *group)
{
group->field = BN_new();
group->a = BN_new();
@@ -38,7 +44,7 @@ int ec_GF2m_simple_group_init(EC_GROUP *group)
* Free a GF(2^m)-based EC_GROUP structure. Note that all other members are
* handled by EC_GROUP_free.
*/
-void ec_GF2m_simple_group_finish(EC_GROUP *group)
+void ossl_ec_GF2m_simple_group_finish(EC_GROUP *group)
{
BN_free(group->field);
BN_free(group->a);
@@ -49,7 +55,7 @@ void ec_GF2m_simple_group_finish(EC_GROUP *group)
* Clear and free a GF(2^m)-based EC_GROUP structure. Note that all other
* members are handled by EC_GROUP_clear_free.
*/
-void ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
+void ossl_ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
{
BN_clear_free(group->field);
BN_clear_free(group->a);
@@ -66,7 +72,7 @@ void ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
* Copy a GF(2^m)-based EC_GROUP structure. Note that all other members are
* handled by EC_GROUP_copy.
*/
-int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
+int ossl_ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
{
if (!BN_copy(dest->field, src->field))
return 0;
@@ -92,9 +98,9 @@ int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
}
/* Set the curve parameters of an EC_GROUP structure. */
-int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
- const BIGNUM *p, const BIGNUM *a,
- const BIGNUM *b, BN_CTX *ctx)
+int ossl_ec_GF2m_simple_group_set_curve(EC_GROUP *group,
+ const BIGNUM *p, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *ctx)
{
int ret = 0, i;
@@ -103,7 +109,7 @@ int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
goto err;
i = BN_GF2m_poly2arr(group->field, group->poly, 6) - 1;
if ((i != 5) && (i != 3)) {
- ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
+ ERR_raise(ERR_LIB_EC, EC_R_UNSUPPORTED_FIELD);
goto err;
}
@@ -132,8 +138,8 @@ int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
* Get the curve parameters of an EC_GROUP structure. If p, a, or b are NULL
* then there values will not be set but the method will return with success.
*/
-int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p,
- BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
+int ossl_ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p,
+ BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
{
int ret = 0;
@@ -162,7 +168,7 @@ int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p,
* Gets the degree of the field. For a curve over GF(2^m) this is the value
* m.
*/
-int ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
+int ossl_ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
{
return BN_num_bits(group->field) - 1;
}
@@ -171,21 +177,22 @@ int ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
* Checks the discriminant of the curve. y^2 + x*y = x^3 + a*x^2 + b is an
* elliptic curve <=> b != 0 (mod p)
*/
-int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group,
- BN_CTX *ctx)
+int ossl_ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group,
+ BN_CTX *ctx)
{
int ret = 0;
BIGNUM *b;
+#ifndef FIPS_MODULE
BN_CTX *new_ctx = NULL;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL) {
- ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
}
+#endif
BN_CTX_start(ctx);
b = BN_CTX_get(ctx);
if (b == NULL)
@@ -205,12 +212,14 @@ int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group,
err:
BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
return ret;
}
/* Initializes an EC_POINT. */
-int ec_GF2m_simple_point_init(EC_POINT *point)
+int ossl_ec_GF2m_simple_point_init(EC_POINT *point)
{
point->X = BN_new();
point->Y = BN_new();
@@ -226,7 +235,7 @@ int ec_GF2m_simple_point_init(EC_POINT *point)
}
/* Frees an EC_POINT. */
-void ec_GF2m_simple_point_finish(EC_POINT *point)
+void ossl_ec_GF2m_simple_point_finish(EC_POINT *point)
{
BN_free(point->X);
BN_free(point->Y);
@@ -234,7 +243,7 @@ void ec_GF2m_simple_point_finish(EC_POINT *point)
}
/* Clears and frees an EC_POINT. */
-void ec_GF2m_simple_point_clear_finish(EC_POINT *point)
+void ossl_ec_GF2m_simple_point_clear_finish(EC_POINT *point)
{
BN_clear_free(point->X);
BN_clear_free(point->Y);
@@ -246,7 +255,7 @@ void ec_GF2m_simple_point_clear_finish(EC_POINT *point)
* Copy the contents of one EC_POINT into another. Assumes dest is
* initialized.
*/
-int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
+int ossl_ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
{
if (!BN_copy(dest->X, src->X))
return 0;
@@ -264,8 +273,8 @@ int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
* Set an EC_POINT to the point at infinity. A point at infinity is
* represented by having Z=0.
*/
-int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group,
- EC_POINT *point)
+int ossl_ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group,
+ EC_POINT *point)
{
point->Z_is_one = 0;
BN_zero(point->Z);
@@ -276,15 +285,15 @@ int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group,
* Set the coordinates of an EC_POINT using affine coordinates. Note that
* the simple implementation only uses affine coordinates.
*/
-int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group,
- EC_POINT *point,
- const BIGNUM *x,
- const BIGNUM *y, BN_CTX *ctx)
+int ossl_ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group,
+ EC_POINT *point,
+ const BIGNUM *x,
+ const BIGNUM *y,
+ BN_CTX *ctx)
{
int ret = 0;
if (x == NULL || y == NULL) {
- ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES,
- ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
@@ -308,22 +317,20 @@ int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group,
* Gets the affine coordinates of an EC_POINT. Note that the simple
* implementation only uses affine coordinates.
*/
-int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group,
- const EC_POINT *point,
- BIGNUM *x, BIGNUM *y,
- BN_CTX *ctx)
+int ossl_ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx)
{
int ret = 0;
if (EC_POINT_is_at_infinity(group, point)) {
- ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES,
- EC_R_POINT_AT_INFINITY);
+ ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY);
return 0;
}
if (BN_cmp(point->Z, BN_value_one())) {
- ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (x != NULL) {
@@ -346,12 +353,14 @@ int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group,
* Computes a + b and stores the result in r. r could be a or b, a could be
* b. Uses algorithm A.10.2 of IEEE P1363.
*/
-int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
- const EC_POINT *b, BN_CTX *ctx)
+int ossl_ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r,
+ const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
{
- BN_CTX *new_ctx = NULL;
BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
int ret = 0;
+#ifndef FIPS_MODULE
+ BN_CTX *new_ctx = NULL;
+#endif
if (EC_POINT_is_at_infinity(group, a)) {
if (!EC_POINT_copy(r, b))
@@ -365,11 +374,13 @@ int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
return 1;
}
+#ifndef FIPS_MODULE
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
+#endif
BN_CTX_start(ctx);
x0 = BN_CTX_get(ctx);
@@ -453,7 +464,9 @@ int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
err:
BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
return ret;
}
@@ -461,26 +474,28 @@ int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
* Computes 2 * a and stores the result in r. r could be a. Uses algorithm
* A.10.2 of IEEE P1363.
*/
-int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
- BN_CTX *ctx)
+int ossl_ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r,
+ const EC_POINT *a, BN_CTX *ctx)
{
- return ec_GF2m_simple_add(group, r, a, a, ctx);
+ return ossl_ec_GF2m_simple_add(group, r, a, a, ctx);
}
-int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
+int ossl_ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point,
+ BN_CTX *ctx)
{
if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y))
/* point is its own inverse */
return 1;
- if (!EC_POINT_make_affine(group, point, ctx))
+ if (group->meth->make_affine == NULL
+ || !group->meth->make_affine(group, point, ctx))
return 0;
return BN_GF2m_add(point->Y, point->X, point->Y);
}
/* Indicates whether the given point is the point at infinity. */
-int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group,
- const EC_POINT *point)
+int ossl_ec_GF2m_simple_is_at_infinity(const EC_GROUP *group,
+ const EC_POINT *point)
{
return BN_is_zero(point->Z);
}
@@ -490,15 +505,17 @@ int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group,
* in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation:
* y^2 + x*y = x^3 + a*x^2 + b.
*/
-int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
- BN_CTX *ctx)
+int ossl_ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
+ BN_CTX *ctx)
{
int ret = -1;
- BN_CTX *new_ctx = NULL;
BIGNUM *lh, *y2;
int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
const BIGNUM *, BN_CTX *);
int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
+#ifndef FIPS_MODULE
+ BN_CTX *new_ctx = NULL;
+#endif
if (EC_POINT_is_at_infinity(group, point))
return 1;
@@ -510,11 +527,13 @@ int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
if (!point->Z_is_one)
return -1;
+#ifndef FIPS_MODULE
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return -1;
}
+#endif
BN_CTX_start(ctx);
y2 = BN_CTX_get(ctx);
@@ -546,7 +565,9 @@ int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
err:
BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
return ret;
}
@@ -557,12 +578,14 @@ int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
* 0 equal (in affine coordinates)
* 1 not equal
*/
-int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
- const EC_POINT *b, BN_CTX *ctx)
+int ossl_ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
+ const EC_POINT *b, BN_CTX *ctx)
{
BIGNUM *aX, *aY, *bX, *bY;
- BN_CTX *new_ctx = NULL;
int ret = -1;
+#ifndef FIPS_MODULE
+ BN_CTX *new_ctx = NULL;
+#endif
if (EC_POINT_is_at_infinity(group, a)) {
return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
@@ -575,11 +598,13 @@ int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
return ((BN_cmp(a->X, b->X) == 0) && BN_cmp(a->Y, b->Y) == 0) ? 0 : 1;
}
+#ifndef FIPS_MODULE
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return -1;
}
+#endif
BN_CTX_start(ctx);
aX = BN_CTX_get(ctx);
@@ -597,26 +622,32 @@ int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
err:
BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
return ret;
}
/* Forces the given EC_POINT to internally use affine coordinates. */
-int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
- BN_CTX *ctx)
+int ossl_ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
+ BN_CTX *ctx)
{
- BN_CTX *new_ctx = NULL;
BIGNUM *x, *y;
int ret = 0;
+#ifndef FIPS_MODULE
+ BN_CTX *new_ctx = NULL;
+#endif
if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
return 1;
+#ifndef FIPS_MODULE
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
+#endif
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
@@ -638,15 +669,17 @@ int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
err:
BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
return ret;
}
/*
* Forces each of the EC_POINTs in the given array to use affine coordinates.
*/
-int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num,
- EC_POINT *points[], BN_CTX *ctx)
+int ossl_ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num,
+ EC_POINT *points[], BN_CTX *ctx)
{
size_t i;
@@ -659,22 +692,22 @@ int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num,
}
/* Wrapper to simple binary polynomial field multiplication implementation. */
-int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r,
- const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+int ossl_ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r,
+ const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
{
return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
}
/* Wrapper to simple binary polynomial field squaring implementation. */
-int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r,
- const BIGNUM *a, BN_CTX *ctx)
+int ossl_ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r,
+ const BIGNUM *a, BN_CTX *ctx)
{
return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
}
/* Wrapper to simple binary polynomial field division implementation. */
-int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r,
- const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+int ossl_ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r,
+ const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
{
return BN_GF2m_mod_div(r, a, b, group->field, ctx);
}
@@ -696,9 +729,9 @@ int ec_GF2m_simple_ladder_pre(const EC_GROUP *group,
/* s blinding: make sure lambda (s->Z here) is not zero */
do {
- if (!BN_priv_rand(s->Z, BN_num_bits(group->field) - 1,
- BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
- ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_PRE, ERR_R_BN_LIB);
+ if (!BN_priv_rand_ex(s->Z, BN_num_bits(group->field) - 1,
+ BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0, ctx)) {
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
return 0;
}
} while (BN_is_zero(s->Z));
@@ -711,9 +744,9 @@ int ec_GF2m_simple_ladder_pre(const EC_GROUP *group,
/* r blinding: make sure lambda (r->Y here for storage) is not zero */
do {
- if (!BN_priv_rand(r->Y, BN_num_bits(group->field) - 1,
- BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
- ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_PRE, ERR_R_BN_LIB);
+ if (!BN_priv_rand_ex(r->Y, BN_num_bits(group->field) - 1,
+ BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0, ctx)) {
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
return 0;
}
} while (BN_is_zero(r->Y));
@@ -782,7 +815,7 @@ int ec_GF2m_simple_ladder_post(const EC_GROUP *group,
if (BN_is_zero(s->Z)) {
if (!EC_POINT_copy(r, p)
|| !EC_POINT_invert(group, r, ctx)) {
- ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_POST, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
return 0;
}
return 1;
@@ -793,7 +826,7 @@ int ec_GF2m_simple_ladder_post(const EC_GROUP *group,
t1 = BN_CTX_get(ctx);
t2 = BN_CTX_get(ctx);
if (t2 == NULL) {
- ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_POST, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -856,15 +889,15 @@ int ec_GF2m_simple_points_mul(const EC_GROUP *group, EC_POINT *r,
* order or cofactor set to 0.
*/
if (num > 1 || BN_is_zero(group->order) || BN_is_zero(group->cofactor))
- return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
+ return ossl_ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
if (scalar != NULL && num == 0)
/* Fixed point multiplication */
- return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);
+ return ossl_ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);
if (scalar == NULL && num == 1)
/* Variable point multiplication */
- return ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx);
+ return ossl_ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx);
/*-
* Double point multiplication:
@@ -872,12 +905,12 @@ int ec_GF2m_simple_points_mul(const EC_GROUP *group, EC_POINT *r,
*/
if ((t = EC_POINT_new(group)) == NULL) {
- ECerr(EC_F_EC_GF2M_SIMPLE_POINTS_MUL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
- if (!ec_scalar_mul_ladder(group, t, scalar, NULL, ctx)
- || !ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx)
+ if (!ossl_ec_scalar_mul_ladder(group, t, scalar, NULL, ctx)
+ || !ossl_ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx)
|| !EC_POINT_add(group, r, t, r, ctx))
goto err;
@@ -899,7 +932,7 @@ static int ec_GF2m_simple_field_inv(const EC_GROUP *group, BIGNUM *r,
int ret;
if (!(ret = BN_GF2m_mod_inv(r, a, group->field, ctx)))
- ECerr(EC_F_EC_GF2M_SIMPLE_FIELD_INV, EC_R_CANNOT_INVERT);
+ ERR_raise(ERR_LIB_EC, EC_R_CANNOT_INVERT);
return ret;
}
@@ -908,54 +941,55 @@ const EC_METHOD *EC_GF2m_simple_method(void)
static const EC_METHOD ret = {
EC_FLAGS_DEFAULT_OCT,
NID_X9_62_characteristic_two_field,
- ec_GF2m_simple_group_init,
- ec_GF2m_simple_group_finish,
- ec_GF2m_simple_group_clear_finish,
- ec_GF2m_simple_group_copy,
- ec_GF2m_simple_group_set_curve,
- ec_GF2m_simple_group_get_curve,
- ec_GF2m_simple_group_get_degree,
- ec_group_simple_order_bits,
- ec_GF2m_simple_group_check_discriminant,
- ec_GF2m_simple_point_init,
- ec_GF2m_simple_point_finish,
- ec_GF2m_simple_point_clear_finish,
- ec_GF2m_simple_point_copy,
- ec_GF2m_simple_point_set_to_infinity,
- 0, /* set_Jprojective_coordinates_GFp */
- 0, /* get_Jprojective_coordinates_GFp */
- ec_GF2m_simple_point_set_affine_coordinates,
- ec_GF2m_simple_point_get_affine_coordinates,
+ ossl_ec_GF2m_simple_group_init,
+ ossl_ec_GF2m_simple_group_finish,
+ ossl_ec_GF2m_simple_group_clear_finish,
+ ossl_ec_GF2m_simple_group_copy,
+ ossl_ec_GF2m_simple_group_set_curve,
+ ossl_ec_GF2m_simple_group_get_curve,
+ ossl_ec_GF2m_simple_group_get_degree,
+ ossl_ec_group_simple_order_bits,
+ ossl_ec_GF2m_simple_group_check_discriminant,
+ ossl_ec_GF2m_simple_point_init,
+ ossl_ec_GF2m_simple_point_finish,
+ ossl_ec_GF2m_simple_point_clear_finish,
+ ossl_ec_GF2m_simple_point_copy,
+ ossl_ec_GF2m_simple_point_set_to_infinity,
+ ossl_ec_GF2m_simple_point_set_affine_coordinates,
+ ossl_ec_GF2m_simple_point_get_affine_coordinates,
0, /* point_set_compressed_coordinates */
0, /* point2oct */
0, /* oct2point */
- ec_GF2m_simple_add,
- ec_GF2m_simple_dbl,
- ec_GF2m_simple_invert,
- ec_GF2m_simple_is_at_infinity,
- ec_GF2m_simple_is_on_curve,
- ec_GF2m_simple_cmp,
- ec_GF2m_simple_make_affine,
- ec_GF2m_simple_points_make_affine,
+ ossl_ec_GF2m_simple_add,
+ ossl_ec_GF2m_simple_dbl,
+ ossl_ec_GF2m_simple_invert,
+ ossl_ec_GF2m_simple_is_at_infinity,
+ ossl_ec_GF2m_simple_is_on_curve,
+ ossl_ec_GF2m_simple_cmp,
+ ossl_ec_GF2m_simple_make_affine,
+ ossl_ec_GF2m_simple_points_make_affine,
ec_GF2m_simple_points_mul,
0, /* precompute_mult */
0, /* have_precompute_mult */
- ec_GF2m_simple_field_mul,
- ec_GF2m_simple_field_sqr,
- ec_GF2m_simple_field_div,
+ ossl_ec_GF2m_simple_field_mul,
+ ossl_ec_GF2m_simple_field_sqr,
+ ossl_ec_GF2m_simple_field_div,
ec_GF2m_simple_field_inv,
0, /* field_encode */
0, /* field_decode */
0, /* field_set_to_one */
- ec_key_simple_priv2oct,
- ec_key_simple_oct2priv,
+ ossl_ec_key_simple_priv2oct,
+ ossl_ec_key_simple_oct2priv,
0, /* set private */
- ec_key_simple_generate_key,
- ec_key_simple_check_key,
- ec_key_simple_generate_public_key,
+ ossl_ec_key_simple_generate_key,
+ ossl_ec_key_simple_check_key,
+ ossl_ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
- ecdh_simple_compute_key,
+ ossl_ecdh_simple_compute_key,
+ ossl_ecdsa_simple_sign_setup,
+ ossl_ecdsa_simple_sign_sig,
+ ossl_ecdsa_simple_verify_sig,
0, /* field_inverse_mod_ord */
0, /* blind_coordinates */
ec_GF2m_simple_ladder_pre,
diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c
index 5098bd7a6602..d4348ff244c7 100644
--- a/crypto/ec/ec_ameth.c
+++ b/crypto/ec/ec_ameth.c
@@ -1,34 +1,38 @@
/*
- * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDH and ECDSA low level APIs are deprecated for public use, but still ok
+ * for internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/x509.h>
#include <openssl/ec.h>
#include <openssl/bn.h>
-#include <openssl/cms.h>
#include <openssl/asn1t.h>
#include "crypto/asn1.h"
#include "crypto/evp.h"
+#include "crypto/x509.h"
+#include <openssl/core_names.h>
+#include <openssl/param_build.h>
#include "ec_local.h"
-#ifndef OPENSSL_NO_CMS
-static int ecdh_cms_decrypt(CMS_RecipientInfo *ri);
-static int ecdh_cms_encrypt(CMS_RecipientInfo *ri);
-#endif
-
static int eckey_param2type(int *pptype, void **ppval, const EC_KEY *ec_key)
{
const EC_GROUP *group;
int nid;
+
if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) {
- ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS);
+ ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS);
return 0;
}
if (EC_GROUP_get_asn1_flag(group)
@@ -38,8 +42,7 @@ static int eckey_param2type(int *pptype, void **ppval, const EC_KEY *ec_key)
ASN1_OBJECT *asn1obj = OBJ_nid2obj(nid);
if (asn1obj == NULL || OBJ_length(asn1obj) == 0) {
- ASN1_OBJECT_free(asn1obj);
- ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_OID);
+ ERR_raise(ERR_LIB_EC, EC_R_MISSING_OID);
return 0;
}
*ppval = asn1obj;
@@ -50,20 +53,10 @@ static int eckey_param2type(int *pptype, void **ppval, const EC_KEY *ec_key)
pstr = ASN1_STRING_new();
if (pstr == NULL)
return 0;
-
- /*
- * The cast in the following line is intentional as the
- * `i2d_ECParameters` signature can't be constified (see discussion at
- * https://github.com/openssl/openssl/pull/9347 where related and
- * required constification backports were rejected).
- *
- * This cast should be safe anyway, because we can expect
- * `i2d_ECParameters()` to treat the first argument as if it was const.
- */
- pstr->length = i2d_ECParameters((EC_KEY *)ec_key, &pstr->data);
+ pstr->length = i2d_ECParameters(ec_key, &pstr->data);
if (pstr->length <= 0) {
ASN1_STRING_free(pstr);
- ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
return 0;
}
*ppval = pstr;
@@ -81,7 +74,7 @@ static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
int penclen;
if (!eckey_param2type(&ptype, &pval, ec_key)) {
- ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
return 0;
}
penclen = i2o_ECPublicKey(ec_key, NULL);
@@ -98,80 +91,32 @@ static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
ptype, pval, penc, penclen))
return 1;
err:
- if (ptype == V_ASN1_OBJECT)
- ASN1_OBJECT_free(pval);
- else
+ if (ptype == V_ASN1_SEQUENCE)
ASN1_STRING_free(pval);
OPENSSL_free(penc);
return 0;
}
-static EC_KEY *eckey_type2param(int ptype, const void *pval)
-{
- EC_KEY *eckey = NULL;
- EC_GROUP *group = NULL;
-
- if (ptype == V_ASN1_SEQUENCE) {
- const ASN1_STRING *pstr = pval;
- const unsigned char *pm = pstr->data;
- int pmlen = pstr->length;
-
- if ((eckey = d2i_ECParameters(NULL, &pm, pmlen)) == NULL) {
- ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
- goto ecerr;
- }
- } else if (ptype == V_ASN1_OBJECT) {
- const ASN1_OBJECT *poid = pval;
-
- /*
- * type == V_ASN1_OBJECT => the parameters are given by an asn1 OID
- */
- if ((eckey = EC_KEY_new()) == NULL) {
- ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE);
- goto ecerr;
- }
- group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid));
- if (group == NULL)
- goto ecerr;
- EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
- if (EC_KEY_set_group(eckey, group) == 0)
- goto ecerr;
- EC_GROUP_free(group);
- } else {
- ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
- goto ecerr;
- }
-
- return eckey;
-
- ecerr:
- EC_KEY_free(eckey);
- EC_GROUP_free(group);
- return NULL;
-}
-
-static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
+static int eckey_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
{
const unsigned char *p = NULL;
- const void *pval;
- int ptype, pklen;
+ int pklen;
EC_KEY *eckey = NULL;
X509_ALGOR *palg;
+ OSSL_LIB_CTX *libctx = NULL;
+ const char *propq = NULL;
- if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
+ if (!ossl_x509_PUBKEY_get0_libctx(&libctx, &propq, pubkey)
+ || !X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
return 0;
- X509_ALGOR_get0(NULL, &ptype, &pval, palg);
-
- eckey = eckey_type2param(ptype, pval);
+ eckey = ossl_ec_key_param_from_x509_algor(palg, libctx, propq);
- if (!eckey) {
- ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB);
+ if (!eckey)
return 0;
- }
/* We have parameters now set public key */
if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
- ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR);
+ ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
goto ecerr;
}
@@ -189,6 +134,7 @@ static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec),
*pb = EC_KEY_get0_public_key(b->pkey.ec);
+
if (group == NULL || pa == NULL || pb == NULL)
return -2;
r = EC_POINT_cmp(group, pa, pb, NULL);
@@ -199,49 +145,30 @@ static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
return -2;
}
-static int eckey_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
+static int eckey_priv_decode_ex(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
- const unsigned char *p = NULL;
- const void *pval;
- int ptype, pklen;
- EC_KEY *eckey = NULL;
- const X509_ALGOR *palg;
-
- if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
- return 0;
- X509_ALGOR_get0(NULL, &ptype, &pval, palg);
-
- eckey = eckey_type2param(ptype, pval);
-
- if (!eckey)
- goto ecliberr;
+ int ret = 0;
+ EC_KEY *eckey = ossl_ec_key_from_pkcs8(p8, libctx, propq);
- /* We have parameters now set private key */
- if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
- ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR);
- goto ecerr;
+ if (eckey != NULL) {
+ ret = 1;
+ EVP_PKEY_assign_EC_KEY(pkey, eckey);
}
- EVP_PKEY_assign_EC_KEY(pkey, eckey);
- return 1;
-
- ecliberr:
- ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
- ecerr:
- EC_KEY_free(eckey);
- return 0;
+ return ret;
}
static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
{
EC_KEY ec_key = *(pkey->pkey.ec);
- unsigned char *ep, *p;
+ unsigned char *ep = NULL;
int eplen, ptype;
void *pval;
unsigned int old_flags;
if (!eckey_param2type(&ptype, &pval, &ec_key)) {
- ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR);
+ ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
return 0;
}
@@ -254,30 +181,25 @@ static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
old_flags = EC_KEY_get_enc_flags(&ec_key);
EC_KEY_set_enc_flags(&ec_key, old_flags | EC_PKEY_NO_PARAMETERS);
- eplen = i2d_ECPrivateKey(&ec_key, NULL);
- if (!eplen) {
- ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
- return 0;
- }
- ep = OPENSSL_malloc(eplen);
- if (ep == NULL) {
- ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- p = ep;
- if (!i2d_ECPrivateKey(&ec_key, &p)) {
- OPENSSL_free(ep);
- ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
- return 0;
+ eplen = i2d_ECPrivateKey(&ec_key, &ep);
+ if (eplen <= 0) {
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
+ goto err;
}
if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0,
ptype, pval, ep, eplen)) {
- OPENSSL_free(ep);
- return 0;
+ ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
+ OPENSSL_clear_free(ep, eplen);
+ goto err;
}
return 1;
+
+ err:
+ if (ptype == V_ASN1_SEQUENCE)
+ ASN1_STRING_free(pval);
+ return 0;
}
static int int_ec_size(const EVP_PKEY *pkey)
@@ -293,6 +215,7 @@ static int ec_bits(const EVP_PKEY *pkey)
static int ec_security_bits(const EVP_PKEY *pkey)
{
int ecbits = ec_bits(pkey);
+
if (ecbits >= 512)
return 256;
if (ecbits >= 384)
@@ -337,6 +260,7 @@ static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
{
const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec),
*group_b = EC_KEY_get0_group(b->pkey.ec);
+
if (group_a == NULL || group_b == NULL)
return -2;
if (EC_GROUP_cmp(group_a, group_b, NULL))
@@ -365,7 +289,7 @@ static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype)
const EC_GROUP *group;
if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
- ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
@@ -413,7 +337,7 @@ static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype)
ret = 1;
err:
if (!ret)
- ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
OPENSSL_clear_free(priv, privlen);
OPENSSL_free(pub);
return ret;
@@ -424,10 +348,8 @@ static int eckey_param_decode(EVP_PKEY *pkey,
{
EC_KEY *eckey;
- if ((eckey = d2i_ECParameters(NULL, pder, derlen)) == NULL) {
- ECerr(EC_F_ECKEY_PARAM_DECODE, ERR_R_EC_LIB);
+ if ((eckey = d2i_ECParameters(NULL, pder, derlen)) == NULL)
return 0;
- }
EVP_PKEY_assign_EC_KEY(pkey, eckey);
return 1;
}
@@ -460,10 +382,8 @@ static int old_ec_priv_decode(EVP_PKEY *pkey,
{
EC_KEY *ec;
- if ((ec = d2i_ECPrivateKey(NULL, pder, derlen)) == NULL) {
- ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR);
+ if ((ec = d2i_ECPrivateKey(NULL, pder, derlen)) == NULL)
return 0;
- }
EVP_PKEY_assign_EC_KEY(pkey, ec);
return 1;
}
@@ -476,61 +396,20 @@ static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
{
switch (op) {
- case ASN1_PKEY_CTRL_PKCS7_SIGN:
- if (arg1 == 0) {
- int snid, hnid;
- X509_ALGOR *alg1, *alg2;
- PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
- if (alg1 == NULL || alg1->algorithm == NULL)
- return -1;
- hnid = OBJ_obj2nid(alg1->algorithm);
- if (hnid == NID_undef)
- return -1;
- if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
- return -1;
- X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
- }
- return 1;
-#ifndef OPENSSL_NO_CMS
- case ASN1_PKEY_CTRL_CMS_SIGN:
- if (arg1 == 0) {
- int snid, hnid;
- X509_ALGOR *alg1, *alg2;
- CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
- if (alg1 == NULL || alg1->algorithm == NULL)
- return -1;
- hnid = OBJ_obj2nid(alg1->algorithm);
- if (hnid == NID_undef)
- return -1;
- if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
- return -1;
- X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
- }
- return 1;
-
- case ASN1_PKEY_CTRL_CMS_ENVELOPE:
- if (arg1 == 1)
- return ecdh_cms_decrypt(arg2);
- else if (arg1 == 0)
- return ecdh_cms_encrypt(arg2);
- return -2;
-
- case ASN1_PKEY_CTRL_CMS_RI_TYPE:
- *(int *)arg2 = CMS_RECIPINFO_AGREE;
- return 1;
-#endif
-
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
- if (EVP_PKEY_id(pkey) == EVP_PKEY_SM2) {
+ if (EVP_PKEY_get_id(pkey) == EVP_PKEY_SM2) {
/* For SM2, the only valid digest-alg is SM3 */
*(int *)arg2 = NID_sm3;
- } else {
- *(int *)arg2 = NID_sha256;
+ return 2; /* Make it mandatory */
}
+ *(int *)arg2 = NID_sha256;
return 1;
case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
- return EC_KEY_oct2key(EVP_PKEY_get0_EC_KEY(pkey), arg2, arg1, NULL);
+ /* We should only be here if we have a legacy key */
+ if (!ossl_assert(evp_pkey_is_legacy(pkey)))
+ return 0;
+ return EC_KEY_oct2key(evp_pkey_get0_EC_KEY_int(pkey), arg2, arg1, NULL);
case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
return EC_KEY_key2buf(EVP_PKEY_get0_EC_KEY(pkey),
@@ -538,9 +417,7 @@ static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
default:
return -2;
-
}
-
}
static int ec_pkey_check(const EVP_PKEY *pkey)
@@ -549,7 +426,7 @@ static int ec_pkey_check(const EVP_PKEY *pkey)
/* stay consistent to what EVP_PKEY_check demands */
if (eckey->priv_key == NULL) {
- ECerr(EC_F_EC_PKEY_CHECK, EC_R_MISSING_PRIVATE_KEY);
+ ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY);
return 0;
}
@@ -578,14 +455,200 @@ static int ec_pkey_param_check(const EVP_PKEY *pkey)
/* stay consistent to what EVP_PKEY_check demands */
if (eckey->group == NULL) {
- ECerr(EC_F_EC_PKEY_PARAM_CHECK, EC_R_MISSING_PARAMETERS);
+ ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS);
return 0;
}
return EC_GROUP_check(eckey->group, NULL);
}
-const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
+static
+size_t ec_pkey_dirty_cnt(const EVP_PKEY *pkey)
+{
+ return pkey->pkey.ec->dirty_cnt;
+}
+
+static
+int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
+ OSSL_FUNC_keymgmt_import_fn *importer,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ const EC_KEY *eckey = NULL;
+ const EC_GROUP *ecg = NULL;
+ unsigned char *pub_key_buf = NULL, *gen_buf = NULL;
+ size_t pub_key_buflen;
+ OSSL_PARAM_BLD *tmpl;
+ OSSL_PARAM *params = NULL;
+ const BIGNUM *priv_key = NULL;
+ const EC_POINT *pub_point = NULL;
+ int selection = 0;
+ int rv = 0;
+ BN_CTX *bnctx = NULL;
+
+ if (from == NULL
+ || (eckey = from->pkey.ec) == NULL
+ || (ecg = EC_KEY_get0_group(eckey)) == NULL)
+ return 0;
+
+ tmpl = OSSL_PARAM_BLD_new();
+ if (tmpl == NULL)
+ return 0;
+
+ /*
+ * EC_POINT_point2buf() can generate random numbers in some
+ * implementations so we need to ensure we use the correct libctx.
+ */
+ bnctx = BN_CTX_new_ex(libctx);
+ if (bnctx == NULL)
+ goto err;
+ BN_CTX_start(bnctx);
+
+ /* export the domain parameters */
+ if (!ossl_ec_group_todata(ecg, tmpl, NULL, libctx, propq, bnctx, &gen_buf))
+ goto err;
+ selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
+
+ priv_key = EC_KEY_get0_private_key(eckey);
+ pub_point = EC_KEY_get0_public_key(eckey);
+
+ if (pub_point != NULL) {
+ /* convert pub_point to a octet string according to the SECG standard */
+ point_conversion_form_t format = EC_KEY_get_conv_form(eckey);
+
+ if ((pub_key_buflen = EC_POINT_point2buf(ecg, pub_point,
+ format,
+ &pub_key_buf, bnctx)) == 0
+ || !OSSL_PARAM_BLD_push_octet_string(tmpl,
+ OSSL_PKEY_PARAM_PUB_KEY,
+ pub_key_buf,
+ pub_key_buflen))
+ goto err;
+ selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+ }
+
+ if (priv_key != NULL) {
+ size_t sz;
+ int ecbits;
+ int ecdh_cofactor_mode;
+
+ /*
+ * Key import/export should never leak the bit length of the secret
+ * scalar in the key.
+ *
+ * For this reason, on export we use padded BIGNUMs with fixed length.
+ *
+ * When importing we also should make sure that, even if short lived,
+ * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
+ * soon as possible, so that any processing of this BIGNUM might opt for
+ * constant time implementations in the backend.
+ *
+ * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
+ * to preallocate the BIGNUM internal buffer to a fixed public size big
+ * enough that operations performed during the processing never trigger
+ * a realloc which would leak the size of the scalar through memory
+ * accesses.
+ *
+ * Fixed Length
+ * ------------
+ *
+ * The order of the large prime subgroup of the curve is our choice for
+ * a fixed public size, as that is generally the upper bound for
+ * generating a private key in EC cryptosystems and should fit all valid
+ * secret scalars.
+ *
+ * For padding on export we just use the bit length of the order
+ * converted to bytes (rounding up).
+ *
+ * For preallocating the BIGNUM storage we look at the number of "words"
+ * required for the internal representation of the order, and we
+ * preallocate 2 extra "words" in case any of the subsequent processing
+ * might temporarily overflow the order length.
+ */
+ ecbits = EC_GROUP_order_bits(ecg);
+ if (ecbits <= 0)
+ goto err;
+
+ sz = (ecbits + 7 ) / 8;
+ if (!OSSL_PARAM_BLD_push_BN_pad(tmpl,
+ OSSL_PKEY_PARAM_PRIV_KEY,
+ priv_key, sz))
+ goto err;
+ selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
+
+ /*
+ * The ECDH Cofactor Mode is defined only if the EC_KEY actually
+ * contains a private key, so we check for the flag and export it only
+ * in this case.
+ */
+ ecdh_cofactor_mode =
+ (EC_KEY_get_flags(eckey) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
+
+ /* Export the ECDH_COFACTOR_MODE parameter */
+ if (!OSSL_PARAM_BLD_push_int(tmpl,
+ OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
+ ecdh_cofactor_mode))
+ goto err;
+ selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS;
+ }
+
+ params = OSSL_PARAM_BLD_to_param(tmpl);
+
+ /* We export, the provider imports */
+ rv = importer(to_keydata, selection, params);
+
+ err:
+ OSSL_PARAM_BLD_free(tmpl);
+ OSSL_PARAM_free(params);
+ OPENSSL_free(pub_key_buf);
+ OPENSSL_free(gen_buf);
+ BN_CTX_end(bnctx);
+ BN_CTX_free(bnctx);
+ return rv;
+}
+
+static int ec_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
+{
+ EVP_PKEY_CTX *pctx = vpctx;
+ EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
+ EC_KEY *ec = EC_KEY_new_ex(pctx->libctx, pctx->propquery);
+
+ if (ec == NULL) {
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (!ossl_ec_group_fromdata(ec, params)
+ || !ossl_ec_key_otherparams_fromdata(ec, params)
+ || !ossl_ec_key_fromdata(ec, params, 1)
+ || !EVP_PKEY_assign_EC_KEY(pkey, ec)) {
+ EC_KEY_free(ec);
+ return 0;
+ }
+ return 1;
+}
+
+static int ec_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
+{
+ EC_KEY *eckey = from->pkey.ec;
+ EC_KEY *dupkey = NULL;
+ int ret;
+
+ if (eckey != NULL) {
+ dupkey = EC_KEY_dup(eckey);
+ if (dupkey == NULL)
+ return 0;
+ } else {
+ /* necessary to properly copy empty SM2 keys */
+ return EVP_PKEY_set_type(to, from->type);
+ }
+
+ ret = EVP_PKEY_assign_EC_KEY(to, dupkey);
+ if (!ret)
+ EC_KEY_free(dupkey);
+ return ret;
+}
+
+const EVP_PKEY_ASN1_METHOD ossl_eckey_asn1_meth = {
EVP_PKEY_EC,
EVP_PKEY_EC,
0,
@@ -597,7 +660,7 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
eckey_pub_cmp,
eckey_pub_print,
- eckey_priv_decode,
+ NULL,
eckey_priv_encode,
eckey_priv_print,
@@ -622,11 +685,22 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
ec_pkey_check,
ec_pkey_public_check,
- ec_pkey_param_check
+ ec_pkey_param_check,
+
+ 0, /* set_priv_key */
+ 0, /* set_pub_key */
+ 0, /* get_priv_key */
+ 0, /* get_pub_key */
+
+ ec_pkey_dirty_cnt,
+ ec_pkey_export_to,
+ ec_pkey_import_from,
+ ec_pkey_copy,
+ eckey_priv_decode_ex
};
#if !defined(OPENSSL_NO_SM2)
-const EVP_PKEY_ASN1_METHOD sm2_asn1_meth = {
+const EVP_PKEY_ASN1_METHOD ossl_sm2_asn1_meth = {
EVP_PKEY_SM2,
EVP_PKEY_EC,
ASN1_PKEY_ALIAS
@@ -645,320 +719,3 @@ int ECParameters_print(BIO *bp, const EC_KEY *x)
{
return do_EC_KEY_print(bp, x, 4, EC_KEY_PRINT_PARAM);
}
-
-#ifndef OPENSSL_NO_CMS
-
-static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
- X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
-{
- const ASN1_OBJECT *aoid;
- int atype;
- const void *aval;
- int rv = 0;
- EVP_PKEY *pkpeer = NULL;
- EC_KEY *ecpeer = NULL;
- const unsigned char *p;
- int plen;
- X509_ALGOR_get0(&aoid, &atype, &aval, alg);
- if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey)
- goto err;
- /* If absent parameters get group from main key */
- if (atype == V_ASN1_UNDEF || atype == V_ASN1_NULL) {
- const EC_GROUP *grp;
- EVP_PKEY *pk;
- pk = EVP_PKEY_CTX_get0_pkey(pctx);
- if (!pk)
- goto err;
- grp = EC_KEY_get0_group(pk->pkey.ec);
- ecpeer = EC_KEY_new();
- if (ecpeer == NULL)
- goto err;
- if (!EC_KEY_set_group(ecpeer, grp))
- goto err;
- } else {
- ecpeer = eckey_type2param(atype, aval);
- if (!ecpeer)
- goto err;
- }
- /* We have parameters now set public key */
- plen = ASN1_STRING_length(pubkey);
- p = ASN1_STRING_get0_data(pubkey);
- if (!p || !plen)
- goto err;
- if (!o2i_ECPublicKey(&ecpeer, &p, plen))
- goto err;
- pkpeer = EVP_PKEY_new();
- if (pkpeer == NULL)
- goto err;
- EVP_PKEY_set1_EC_KEY(pkpeer, ecpeer);
- if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
- rv = 1;
- err:
- EC_KEY_free(ecpeer);
- EVP_PKEY_free(pkpeer);
- return rv;
-}
-
-/* Set KDF parameters based on KDF NID */
-static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid)
-{
- int kdf_nid, kdfmd_nid, cofactor;
- const EVP_MD *kdf_md;
- if (eckdf_nid == NID_undef)
- return 0;
-
- /* Lookup KDF type, cofactor mode and digest */
- if (!OBJ_find_sigid_algs(eckdf_nid, &kdfmd_nid, &kdf_nid))
- return 0;
-
- if (kdf_nid == NID_dh_std_kdf)
- cofactor = 0;
- else if (kdf_nid == NID_dh_cofactor_kdf)
- cofactor = 1;
- else
- return 0;
-
- if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0)
- return 0;
-
- if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0)
- return 0;
-
- kdf_md = EVP_get_digestbynid(kdfmd_nid);
- if (!kdf_md)
- return 0;
-
- if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
- return 0;
- return 1;
-}
-
-static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
-{
- int rv = 0;
-
- X509_ALGOR *alg, *kekalg = NULL;
- ASN1_OCTET_STRING *ukm;
- const unsigned char *p;
- unsigned char *der = NULL;
- int plen, keylen;
- const EVP_CIPHER *kekcipher;
- EVP_CIPHER_CTX *kekctx;
-
- if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
- return 0;
-
- if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) {
- ECerr(EC_F_ECDH_CMS_SET_SHARED_INFO, EC_R_KDF_PARAMETER_ERROR);
- return 0;
- }
-
- if (alg->parameter->type != V_ASN1_SEQUENCE)
- return 0;
-
- p = alg->parameter->value.sequence->data;
- plen = alg->parameter->value.sequence->length;
- kekalg = d2i_X509_ALGOR(NULL, &p, plen);
- if (!kekalg)
- goto err;
- kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
- if (!kekctx)
- goto err;
- kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
- if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
- goto err;
- if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
- goto err;
- if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
- goto err;
-
- keylen = EVP_CIPHER_CTX_key_length(kekctx);
- if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
- goto err;
-
- plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen);
-
- if (!plen)
- goto err;
-
- if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0)
- goto err;
- der = NULL;
-
- rv = 1;
- err:
- X509_ALGOR_free(kekalg);
- OPENSSL_free(der);
- return rv;
-}
-
-static int ecdh_cms_decrypt(CMS_RecipientInfo *ri)
-{
- EVP_PKEY_CTX *pctx;
- pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
- if (!pctx)
- return 0;
- /* See if we need to set peer key */
- if (!EVP_PKEY_CTX_get0_peerkey(pctx)) {
- X509_ALGOR *alg;
- ASN1_BIT_STRING *pubkey;
- if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
- NULL, NULL, NULL))
- return 0;
- if (!alg || !pubkey)
- return 0;
- if (!ecdh_cms_set_peerkey(pctx, alg, pubkey)) {
- ECerr(EC_F_ECDH_CMS_DECRYPT, EC_R_PEER_KEY_ERROR);
- return 0;
- }
- }
- /* Set ECDH derivation parameters and initialise unwrap context */
- if (!ecdh_cms_set_shared_info(pctx, ri)) {
- ECerr(EC_F_ECDH_CMS_DECRYPT, EC_R_SHARED_INFO_ERROR);
- return 0;
- }
- return 1;
-}
-
-static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
-{
- EVP_PKEY_CTX *pctx;
- EVP_PKEY *pkey;
- EVP_CIPHER_CTX *ctx;
- int keylen;
- X509_ALGOR *talg, *wrap_alg = NULL;
- const ASN1_OBJECT *aoid;
- ASN1_BIT_STRING *pubkey;
- ASN1_STRING *wrap_str;
- ASN1_OCTET_STRING *ukm;
- unsigned char *penc = NULL;
- int penclen;
- int rv = 0;
- int ecdh_nid, kdf_type, kdf_nid, wrap_nid;
- const EVP_MD *kdf_md;
- pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
- if (!pctx)
- return 0;
- /* Get ephemeral key */
- pkey = EVP_PKEY_CTX_get0_pkey(pctx);
- if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
- NULL, NULL, NULL))
- goto err;
- X509_ALGOR_get0(&aoid, NULL, NULL, talg);
- /* Is everything uninitialised? */
- if (aoid == OBJ_nid2obj(NID_undef)) {
-
- EC_KEY *eckey = pkey->pkey.ec;
- /* Set the key */
- unsigned char *p;
-
- penclen = i2o_ECPublicKey(eckey, NULL);
- if (penclen <= 0)
- goto err;
- penc = OPENSSL_malloc(penclen);
- if (penc == NULL)
- goto err;
- p = penc;
- penclen = i2o_ECPublicKey(eckey, &p);
- if (penclen <= 0)
- goto err;
- ASN1_STRING_set0(pubkey, penc, penclen);
- pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
- pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
-
- penc = NULL;
- X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
- V_ASN1_UNDEF, NULL);
- }
-
- /* See if custom parameters set */
- kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx);
- if (kdf_type <= 0)
- goto err;
- if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md))
- goto err;
- ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx);
- if (ecdh_nid < 0)
- goto err;
- else if (ecdh_nid == 0)
- ecdh_nid = NID_dh_std_kdf;
- else if (ecdh_nid == 1)
- ecdh_nid = NID_dh_cofactor_kdf;
-
- if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) {
- kdf_type = EVP_PKEY_ECDH_KDF_X9_63;
- if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0)
- goto err;
- } else
- /* Unknown KDF */
- goto err;
- if (kdf_md == NULL) {
- /* Fixme later for better MD */
- kdf_md = EVP_sha1();
- if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
- goto err;
- }
-
- if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
- goto err;
-
- /* Lookup NID for KDF+cofactor+digest */
-
- if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid))
- goto err;
- /* Get wrap NID */
- ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
- wrap_nid = EVP_CIPHER_CTX_type(ctx);
- keylen = EVP_CIPHER_CTX_key_length(ctx);
-
- /* Package wrap algorithm in an AlgorithmIdentifier */
-
- wrap_alg = X509_ALGOR_new();
- if (wrap_alg == NULL)
- goto err;
- wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
- wrap_alg->parameter = ASN1_TYPE_new();
- if (wrap_alg->parameter == NULL)
- goto err;
- if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
- goto err;
- if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
- ASN1_TYPE_free(wrap_alg->parameter);
- wrap_alg->parameter = NULL;
- }
-
- if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
- goto err;
-
- penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen);
-
- if (!penclen)
- goto err;
-
- if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0)
- goto err;
- penc = NULL;
-
- /*
- * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
- * of another AlgorithmIdentifier.
- */
- penclen = i2d_X509_ALGOR(wrap_alg, &penc);
- if (!penc || !penclen)
- goto err;
- wrap_str = ASN1_STRING_new();
- if (wrap_str == NULL)
- goto err;
- ASN1_STRING_set0(wrap_str, penc, penclen);
- penc = NULL;
- X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str);
-
- rv = 1;
-
- err:
- OPENSSL_free(penc);
- X509_ALGOR_free(wrap_alg);
- return rv;
-}
-
-#endif
diff --git a/crypto/ec/ec_asn1.c b/crypto/ec/ec_asn1.c
index 1acbbde3d37b..7a0b35a59431 100644
--- a/crypto/ec/ec_asn1.c
+++ b/crypto/ec/ec_asn1.c
@@ -1,90 +1,27 @@
/*
* Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <string.h>
#include "ec_local.h"
#include <openssl/err.h>
#include <openssl/asn1t.h>
#include <openssl/objects.h>
#include "internal/nelem.h"
+#include "crypto/asn1_dsa.h"
-int EC_GROUP_get_basis_type(const EC_GROUP *group)
-{
- int i;
-
- if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
- NID_X9_62_characteristic_two_field)
- /* everything else is currently not supported */
- return 0;
-
- /* Find the last non-zero element of group->poly[] */
- for (i = 0;
- i < (int)OSSL_NELEM(group->poly) && group->poly[i] != 0;
- i++)
- continue;
-
- if (i == 4)
- return NID_X9_62_ppBasis;
- else if (i == 2)
- return NID_X9_62_tpBasis;
- else
- /* everything else is currently not supported */
- return 0;
-}
-
-#ifndef OPENSSL_NO_EC2M
-int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k)
-{
- if (group == NULL)
- return 0;
-
- if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
- NID_X9_62_characteristic_two_field
- || !((group->poly[0] != 0) && (group->poly[1] != 0)
- && (group->poly[2] == 0))) {
- ECerr(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- return 0;
- }
-
- if (k)
- *k = group->poly[1];
-
- return 1;
-}
-
-int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,
- unsigned int *k2, unsigned int *k3)
-{
- if (group == NULL)
- return 0;
-
- if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
- NID_X9_62_characteristic_two_field
- || !((group->poly[0] != 0) && (group->poly[1] != 0)
- && (group->poly[2] != 0) && (group->poly[3] != 0)
- && (group->poly[4] == 0))) {
- ECerr(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- return 0;
- }
-
- if (k1)
- *k1 = group->poly[3];
- if (k2)
- *k2 = group->poly[2];
- if (k3)
- *k3 = group->poly[1];
-
- return 1;
-}
-#endif
+#ifndef FIPS_MODULE
/* some structures needed for the asn1 encoding */
typedef struct x9_62_pentanomial_st {
@@ -223,9 +160,9 @@ ASN1_CHOICE(ECPKPARAMETERS) = {
ASN1_SIMPLE(ECPKPARAMETERS, value.implicitlyCA, ASN1_NULL)
} ASN1_CHOICE_END(ECPKPARAMETERS)
-DECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS)
-DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS)
-IMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS)
+DECLARE_ASN1_FUNCTIONS(ECPKPARAMETERS)
+DECLARE_ASN1_ENCODE_FUNCTIONS_name(ECPKPARAMETERS, ECPKPARAMETERS)
+IMPLEMENT_ASN1_FUNCTIONS(ECPKPARAMETERS)
ASN1_SEQUENCE(EC_PRIVATEKEY) = {
ASN1_EMBED(EC_PRIVATEKEY, version, INT32),
@@ -234,9 +171,9 @@ ASN1_SEQUENCE(EC_PRIVATEKEY) = {
ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1)
} static_ASN1_SEQUENCE_END(EC_PRIVATEKEY)
-DECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY)
-DECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY)
-IMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY)
+DECLARE_ASN1_FUNCTIONS(EC_PRIVATEKEY)
+DECLARE_ASN1_ENCODE_FUNCTIONS_name(EC_PRIVATEKEY, EC_PRIVATEKEY)
+IMPLEMENT_ASN1_FUNCTIONS(EC_PRIVATEKEY)
/* some declarations of internal function */
@@ -259,33 +196,33 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
ASN1_OBJECT_free(field->fieldType);
ASN1_TYPE_free(field->p.other);
- nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
+ nid = EC_GROUP_get_field_type(group);
/* set OID for the field */
if ((field->fieldType = OBJ_nid2obj(nid)) == NULL) {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_OBJ_LIB);
goto err;
}
if (nid == NID_X9_62_prime_field) {
if ((tmp = BN_new()) == NULL) {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
/* the parameters are specified by the prime number p */
if (!EC_GROUP_get_curve(group, tmp, NULL, NULL, NULL)) {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
/* set the prime number */
field->p.prime = BN_to_ASN1_INTEGER(tmp, NULL);
if (field->p.prime == NULL) {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
} else if (nid == NID_X9_62_characteristic_two_field)
#ifdef OPENSSL_NO_EC2M
{
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_GF2M_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
goto err;
}
#else
@@ -297,7 +234,7 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
char_two = field->p.char_two;
if (char_two == NULL) {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -306,12 +243,12 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
field_type = EC_GROUP_get_basis_type(group);
if (field_type == 0) {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
/* set base type OID */
if ((char_two->type = OBJ_nid2obj(field_type)) == NULL) {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_OBJ_LIB);
goto err;
}
@@ -323,11 +260,11 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
char_two->p.tpBasis = ASN1_INTEGER_new();
if (char_two->p.tpBasis == NULL) {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k)) {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
} else if (field_type == NID_X9_62_ppBasis) {
@@ -338,7 +275,7 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
char_two->p.ppBasis = X9_62_PENTANOMIAL_new();
if (char_two->p.ppBasis == NULL) {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -351,14 +288,14 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
/* for ONB the parameters are (asn1) NULL */
char_two->p.onBasis = ASN1_NULL_new();
if (char_two->p.onBasis == NULL) {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
}
}
#endif
else {
- ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_UNSUPPORTED_FIELD);
+ ERR_raise(ERR_LIB_EC, EC_R_UNSUPPORTED_FIELD);
goto err;
}
@@ -380,13 +317,13 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
return 0;
if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
/* get a and b */
if (!EC_GROUP_get_curve(group, NULL, tmp_1, tmp_2, NULL)) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
@@ -398,19 +335,19 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
len = ((size_t)EC_GROUP_get_degree(group) + 7) / 8;
if ((a_buf = OPENSSL_malloc(len)) == NULL
|| (b_buf = OPENSSL_malloc(len)) == NULL) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
if (BN_bn2binpad(tmp_1, a_buf, len) < 0
|| BN_bn2binpad(tmp_2, b_buf, len) < 0) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* set a and b */
if (!ASN1_OCTET_STRING_set(curve->a, a_buf, len)
|| !ASN1_OCTET_STRING_set(curve->b, b_buf, len)) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
@@ -418,14 +355,14 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
if (group->seed) {
if (!curve->seed)
if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
curve->seed->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
curve->seed->flags |= ASN1_STRING_FLAG_BITS_LEFT;
if (!ASN1_BIT_STRING_set(curve->seed, group->seed,
(int)group->seed_len)) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
} else {
@@ -444,7 +381,7 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
}
ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group,
- ECPARAMETERS *params)
+ ECPARAMETERS *params)
{
size_t len = 0;
ECPARAMETERS *ret = NULL;
@@ -456,7 +393,7 @@ ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group,
if (params == NULL) {
if ((ret = ECPARAMETERS_new()) == NULL) {
- ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
} else
@@ -467,19 +404,19 @@ ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group,
/* set the fieldID */
if (!ec_asn1_group2fieldid(group, ret->fieldID)) {
- ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
/* set the curve */
if (!ec_asn1_group2curve(group, ret->curve)) {
- ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
/* set the base point */
if ((point = EC_GROUP_get0_generator(group)) == NULL) {
- ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, EC_R_UNDEFINED_GENERATOR);
+ ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR);
goto err;
}
@@ -487,12 +424,12 @@ ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group,
len = EC_POINT_point2buf(group, point, form, &buffer, NULL);
if (len == 0) {
- ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) {
OPENSSL_free(buffer);
- ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
ASN1_STRING_set0(ret->base, buffer, len);
@@ -500,13 +437,13 @@ ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group,
/* set the order */
tmp = EC_GROUP_get0_order(group);
if (tmp == NULL) {
- ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
ret->order = BN_to_ASN1_INTEGER(tmp, orig = ret->order);
if (ret->order == NULL) {
ret->order = orig;
- ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
@@ -516,7 +453,7 @@ ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group,
ret->cofactor = BN_to_ASN1_INTEGER(tmp, orig = ret->cofactor);
if (ret->cofactor == NULL) {
ret->cofactor = orig;
- ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
}
@@ -537,7 +474,7 @@ ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group,
if (ret == NULL) {
if ((ret = ECPKPARAMETERS_new()) == NULL) {
- ECerr(EC_F_EC_GROUP_GET_ECPKPARAMETERS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else {
@@ -558,7 +495,7 @@ ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group,
if (asn1obj == NULL || OBJ_length(asn1obj) == 0) {
ASN1_OBJECT_free(asn1obj);
- ECerr(EC_F_EC_GROUP_GET_ECPKPARAMETERS, EC_R_MISSING_OID);
+ ERR_raise(ERR_LIB_EC, EC_R_MISSING_OID);
ok = 0;
} else {
ret->type = ECPKPARAMETERS_TYPE_NAMED;
@@ -592,9 +529,10 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
int curve_name = NID_undef;
BN_CTX *ctx = NULL;
- if (!params->fieldID || !params->fieldID->fieldType ||
- !params->fieldID->p.ptr) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR);
+ if (params->fieldID == NULL
+ || params->fieldID->fieldType == NULL
+ || params->fieldID->p.ptr == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
goto err;
}
@@ -604,20 +542,20 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
* encoded them incorrectly, so we must accept any length for backwards
* compatibility.
*/
- if (!params->curve || !params->curve->a ||
- !params->curve->a->data || !params->curve->b ||
- !params->curve->b->data) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR);
+ if (params->curve == NULL
+ || params->curve->a == NULL || params->curve->a->data == NULL
+ || params->curve->b == NULL || params->curve->b->data == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
goto err;
}
a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL);
if (a == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL);
if (b == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
@@ -626,7 +564,7 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
if (tmp == NID_X9_62_characteristic_two_field)
#ifdef OPENSSL_NO_EC2M
{
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_GF2M_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
goto err;
}
#else
@@ -637,12 +575,12 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
field_bits = char_two->m;
if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_FIELD_TOO_LARGE);
+ ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE);
goto err;
}
if ((p = BN_new()) == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -653,15 +591,14 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
long tmp_long;
if (!char_two->p.tpBasis) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR);
+ ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
goto err;
}
tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis);
if (!(char_two->m > tmp_long && tmp_long > 0)) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS,
- EC_R_INVALID_TRINOMIAL_BASIS);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_TRINOMIAL_BASIS);
goto err;
}
@@ -676,16 +613,15 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
X9_62_PENTANOMIAL *penta;
penta = char_two->p.ppBasis;
- if (!penta) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR);
+ if (penta == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
goto err;
}
if (!
(char_two->m > penta->k3 && penta->k3 > penta->k2
&& penta->k2 > penta->k1 && penta->k1 > 0)) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS,
- EC_R_INVALID_PENTANOMIAL_BASIS);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_PENTANOMIAL_BASIS);
goto err;
}
@@ -701,11 +637,11 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
if (!BN_set_bit(p, 0))
goto err;
} else if (tmp == NID_X9_62_onBasis) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_NOT_IMPLEMENTED);
+ ERR_raise(ERR_LIB_EC, EC_R_NOT_IMPLEMENTED);
goto err;
} else { /* error */
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR);
+ ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
goto err;
}
@@ -716,36 +652,36 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
else if (tmp == NID_X9_62_prime_field) {
/* we have a curve over a prime field */
/* extract the prime number */
- if (!params->fieldID->p.prime) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR);
+ if (params->fieldID->p.prime == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
goto err;
}
p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL);
if (p == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
if (BN_is_negative(p) || BN_is_zero(p)) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_FIELD);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
goto err;
}
field_bits = BN_num_bits(p);
if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_FIELD_TOO_LARGE);
+ ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE);
goto err;
}
/* create the EC_GROUP structure */
ret = EC_GROUP_new_curve_GFp(p, a, b, NULL);
} else {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_FIELD);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
goto err;
}
if (ret == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
@@ -758,12 +694,12 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
* zero length allocation request.
*/
if (params->curve->seed->length == 0) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR);
+ ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
goto err;
}
OPENSSL_free(ret->seed);
if ((ret->seed = OPENSSL_malloc(params->curve->seed->length)) == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
memcpy(ret->seed, params->curve->seed->data,
@@ -775,7 +711,7 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
|| params->base == NULL
|| params->base->data == NULL
|| params->base->length == 0) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR);
+ ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
goto err;
}
@@ -789,21 +725,21 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
/* extract the ec point */
if (!EC_POINT_oct2point(ret, point, params->base->data,
params->base->length, NULL)) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
/* extract the order */
if (ASN1_INTEGER_to_BN(params->order, a) == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
if (BN_is_negative(a) || BN_is_zero(a)) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_GROUP_ORDER);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
goto err;
}
if (BN_num_bits(a) > (int)field_bits + 1) { /* Hasse bound */
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_GROUP_ORDER);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
goto err;
}
@@ -812,12 +748,12 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
BN_free(b);
b = NULL;
} else if (ASN1_INTEGER_to_BN(params->cofactor, b) == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
goto err;
}
/* set the generator, order and cofactor (if present) */
if (!EC_GROUP_set_generator(ret, point, a, b)) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
@@ -834,16 +770,16 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
* mathematically wrong anyway and should not be used.
*/
if ((ctx = BN_CTX_new()) == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
if ((dup = EC_GROUP_dup(ret)) == NULL
|| EC_GROUP_set_seed(dup, NULL, 0) != 1
|| !EC_GROUP_set_generator(dup, point, a, NULL)) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
- if ((curve_name = ec_curve_nid_from_params(dup, ctx)) != NID_undef) {
+ if ((curve_name = ossl_ec_curve_nid_from_params(dup, ctx)) != NID_undef) {
/*
* The input explicit parameters successfully matched one of the
* built-in curves: often for built-in curves we have specialized
@@ -865,7 +801,7 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
#endif /* !def(OPENSSL_NO_EC_NISTP_64_GCC_128) */
if ((named_group = EC_GROUP_new_by_curve_name(curve_name)) == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
EC_GROUP_free(ret);
@@ -917,7 +853,7 @@ EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params)
int tmp = 0;
if (params == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, EC_R_MISSING_PARAMETERS);
+ ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS);
return NULL;
}
@@ -925,8 +861,7 @@ EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params)
/* the curve is given by an OID */
tmp = OBJ_obj2nid(params->value.named_curve);
if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS,
- EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
+ ERR_raise(ERR_LIB_EC, EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
return NULL;
}
EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE);
@@ -934,7 +869,7 @@ EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params)
/* the parameters are given by an ECPARAMETERS structure */
ret = EC_GROUP_new_from_ecparameters(params->value.parameters);
if (!ret) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
return NULL;
}
EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_EXPLICIT_CURVE);
@@ -942,7 +877,7 @@ EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params)
/* implicit parameters inherited from CA - unsupported */
return NULL;
} else {
- ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, EC_R_ASN1_ERROR);
+ ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
return NULL;
}
@@ -958,13 +893,11 @@ EC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len)
const unsigned char *p = *in;
if ((params = d2i_ECPKPARAMETERS(NULL, &p, len)) == NULL) {
- ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE);
ECPKPARAMETERS_free(params);
return NULL;
}
if ((group = EC_GROUP_new_from_ecpkparameters(params)) == NULL) {
- ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE);
ECPKPARAMETERS_free(params);
return NULL;
}
@@ -987,11 +920,11 @@ int i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out)
int ret = 0;
ECPKPARAMETERS *tmp = EC_GROUP_get_ecpkparameters(a, NULL);
if (tmp == NULL) {
- ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE);
+ ERR_raise(ERR_LIB_EC, EC_R_GROUP2PKPARAMETERS_FAILURE);
return 0;
}
if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0) {
- ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE);
+ ERR_raise(ERR_LIB_EC, EC_R_I2D_ECPKPARAMETERS_FAILURE);
ECPKPARAMETERS_free(tmp);
return 0;
}
@@ -1007,14 +940,12 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
EC_PRIVATEKEY *priv_key = NULL;
const unsigned char *p = *in;
- if ((priv_key = d2i_EC_PRIVATEKEY(NULL, &p, len)) == NULL) {
- ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
+ if ((priv_key = d2i_EC_PRIVATEKEY(NULL, &p, len)) == NULL)
return NULL;
- }
if (a == NULL || *a == NULL) {
if ((ret = EC_KEY_new()) == NULL) {
- ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
} else
@@ -1029,7 +960,7 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
}
if (ret->group == NULL) {
- ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
@@ -1041,14 +972,17 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
ASN1_STRING_length(pkey)) == 0)
goto err;
} else {
- ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_MISSING_PRIVATE_KEY);
+ ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY);
goto err;
}
+ if (EC_GROUP_get_curve_name(ret->group) == NID_sm2)
+ EC_KEY_set_flags(ret, EC_FLAG_SM2_RANGE);
+
EC_POINT_clear_free(ret->pub_key);
ret->pub_key = EC_POINT_new(ret->group);
if (ret->pub_key == NULL) {
- ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
@@ -1059,7 +993,7 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
pub_oct = ASN1_STRING_get0_data(priv_key->publicKey);
pub_oct_len = ASN1_STRING_length(priv_key->publicKey);
if (!EC_KEY_oct2key(ret, pub_oct, pub_oct_len, NULL)) {
- ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
} else {
@@ -1074,6 +1008,7 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
*a = ret;
EC_PRIVATEKEY_free(priv_key);
*in = p;
+ ret->dirty_cnt++;
return ret;
err:
@@ -1083,7 +1018,7 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
return NULL;
}
-int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
+int i2d_ECPrivateKey(const EC_KEY *a, unsigned char **out)
{
int ret = 0, ok = 0;
unsigned char *priv= NULL, *pub= NULL;
@@ -1093,12 +1028,12 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
if (a == NULL || a->group == NULL ||
(!(a->enc_flag & EC_PKEY_NO_PUBKEY) && a->pub_key == NULL)) {
- ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
goto err;
}
if ((priv_key = EC_PRIVATEKEY_new()) == NULL) {
- ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -1107,7 +1042,7 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
privlen = EC_KEY_priv2buf(a, &priv);
if (privlen == 0) {
- ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
@@ -1118,7 +1053,7 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
if ((priv_key->parameters =
EC_GROUP_get_ecpkparameters(a->group,
priv_key->parameters)) == NULL) {
- ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
}
@@ -1126,14 +1061,14 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
if (!(a->enc_flag & EC_PKEY_NO_PUBKEY)) {
priv_key->publicKey = ASN1_BIT_STRING_new();
if (priv_key->publicKey == NULL) {
- ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
publen = EC_KEY_key2buf(a, a->conv_form, &pub, NULL);
if (publen == 0) {
- ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
@@ -1144,7 +1079,7 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
}
if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) {
- ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
ok = 1;
@@ -1155,10 +1090,10 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
return (ok ? ret : 0);
}
-int i2d_ECParameters(EC_KEY *a, unsigned char **out)
+int i2d_ECParameters(const EC_KEY *a, unsigned char **out)
{
if (a == NULL) {
- ECerr(EC_F_I2D_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
return i2d_ECPKParameters(a->group, out);
@@ -1169,25 +1104,31 @@ EC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len)
EC_KEY *ret;
if (in == NULL || *in == NULL) {
- ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (a == NULL || *a == NULL) {
if ((ret = EC_KEY_new()) == NULL) {
- ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else
ret = *a;
if (!d2i_ECPKParameters(&ret->group, in, len)) {
- ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB);
if (a == NULL || *a != ret)
EC_KEY_free(ret);
+ else
+ ret->dirty_cnt++;
return NULL;
}
+ if (EC_GROUP_get_curve_name(ret->group) == NID_sm2)
+ EC_KEY_set_flags(ret, EC_FLAG_SM2_RANGE);
+
+ ret->dirty_cnt++;
+
if (a)
*a = ret;
@@ -1202,12 +1143,13 @@ EC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len)
/*
* sorry, but a EC_GROUP-structure is necessary to set the public key
*/
- ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
ret = *a;
+ /* EC_KEY_opt2key updates dirty_cnt */
if (!EC_KEY_oct2key(ret, *in, len, NULL)) {
- ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
return 0;
}
*in += len;
@@ -1220,7 +1162,7 @@ int i2o_ECPublicKey(const EC_KEY *a, unsigned char **out)
int new_buffer = 0;
if (a == NULL) {
- ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
@@ -1233,14 +1175,14 @@ int i2o_ECPublicKey(const EC_KEY *a, unsigned char **out)
if (*out == NULL) {
if ((*out = OPENSSL_malloc(buf_len)) == NULL) {
- ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
new_buffer = 1;
}
if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form,
*out, buf_len, NULL)) {
- ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
if (new_buffer) {
OPENSSL_free(*out);
*out = NULL;
@@ -1252,20 +1194,16 @@ int i2o_ECPublicKey(const EC_KEY *a, unsigned char **out)
return buf_len;
}
-ASN1_SEQUENCE(ECDSA_SIG) = {
- ASN1_SIMPLE(ECDSA_SIG, r, CBIGNUM),
- ASN1_SIMPLE(ECDSA_SIG, s, CBIGNUM)
-} static_ASN1_SEQUENCE_END(ECDSA_SIG)
+DECLARE_ASN1_FUNCTIONS(ECDSA_SIG)
+DECLARE_ASN1_ENCODE_FUNCTIONS_name(ECDSA_SIG, ECDSA_SIG)
-DECLARE_ASN1_FUNCTIONS_const(ECDSA_SIG)
-DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECDSA_SIG, ECDSA_SIG)
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ECDSA_SIG, ECDSA_SIG, ECDSA_SIG)
+#endif /* FIPS_MODULE */
ECDSA_SIG *ECDSA_SIG_new(void)
{
ECDSA_SIG *sig = OPENSSL_zalloc(sizeof(*sig));
if (sig == NULL)
- ECerr(EC_F_ECDSA_SIG_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return sig;
}
@@ -1278,6 +1216,75 @@ void ECDSA_SIG_free(ECDSA_SIG *sig)
OPENSSL_free(sig);
}
+ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **psig, const unsigned char **ppin, long len)
+{
+ ECDSA_SIG *sig;
+
+ if (len < 0)
+ return NULL;
+ if (psig != NULL && *psig != NULL) {
+ sig = *psig;
+ } else {
+ sig = ECDSA_SIG_new();
+ if (sig == NULL)
+ return NULL;
+ }
+ if (sig->r == NULL)
+ sig->r = BN_new();
+ if (sig->s == NULL)
+ sig->s = BN_new();
+ if (sig->r == NULL || sig->s == NULL
+ || ossl_decode_der_dsa_sig(sig->r, sig->s, ppin, (size_t)len) == 0) {
+ if (psig == NULL || *psig == NULL)
+ ECDSA_SIG_free(sig);
+ return NULL;
+ }
+ if (psig != NULL && *psig == NULL)
+ *psig = sig;
+ return sig;
+}
+
+int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **ppout)
+{
+ BUF_MEM *buf = NULL;
+ size_t encoded_len;
+ WPACKET pkt;
+
+ if (ppout == NULL) {
+ if (!WPACKET_init_null(&pkt, 0))
+ return -1;
+ } else if (*ppout == NULL) {
+ if ((buf = BUF_MEM_new()) == NULL
+ || !WPACKET_init_len(&pkt, buf, 0)) {
+ BUF_MEM_free(buf);
+ return -1;
+ }
+ } else {
+ if (!WPACKET_init_static_len(&pkt, *ppout, SIZE_MAX, 0))
+ return -1;
+ }
+
+ if (!ossl_encode_der_dsa_sig(&pkt, sig->r, sig->s)
+ || !WPACKET_get_total_written(&pkt, &encoded_len)
+ || !WPACKET_finish(&pkt)) {
+ BUF_MEM_free(buf);
+ WPACKET_cleanup(&pkt);
+ return -1;
+ }
+
+ if (ppout != NULL) {
+ if (*ppout == NULL) {
+ *ppout = (unsigned char *)buf->data;
+ buf->data = NULL;
+ BUF_MEM_free(buf);
+ } else {
+ *ppout += encoded_len;
+ }
+ }
+
+ return (int)encoded_len;
+}
+
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
{
if (pr != NULL)
@@ -1307,32 +1314,27 @@ int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
return 1;
}
-int ECDSA_size(const EC_KEY *r)
+int ECDSA_size(const EC_KEY *ec)
{
- int ret, i;
- ASN1_INTEGER bs;
- unsigned char buf[4];
+ int ret;
+ ECDSA_SIG sig;
const EC_GROUP *group;
+ const BIGNUM *bn;
- if (r == NULL)
+ if (ec == NULL)
return 0;
- group = EC_KEY_get0_group(r);
+ group = EC_KEY_get0_group(ec);
if (group == NULL)
return 0;
- i = EC_GROUP_order_bits(group);
- if (i == 0)
+ bn = EC_GROUP_get0_order(group);
+ if (bn == NULL)
return 0;
- bs.length = (i + 7) / 8;
- bs.data = buf;
- bs.type = V_ASN1_INTEGER;
- /* If the top bit is set the asn1 encoding is 1 larger. */
- buf[0] = 0xff;
-
- i = i2d_ASN1_INTEGER(&bs, NULL);
- i += i; /* r and s */
- ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE);
+
+ sig.r = sig.s = (BIGNUM *)bn;
+ ret = i2d_ECDSA_SIG(&sig, NULL);
+
if (ret < 0)
- return 0;
+ ret = 0;
return ret;
}
diff --git a/crypto/ec/ec_backend.c b/crypto/ec/ec_backend.c
new file mode 100644
index 000000000000..98e2c418e416
--- /dev/null
+++ b/crypto/ec/ec_backend.c
@@ -0,0 +1,842 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Low level APIs related to EC_KEY are deprecated for public use,
+ * but still ok for internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/core_names.h>
+#include <openssl/objects.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#ifndef FIPS_MODULE
+# include <openssl/engine.h>
+# include <openssl/x509.h>
+#endif
+#include "crypto/bn.h"
+#include "crypto/ec.h"
+#include "ec_local.h"
+#include "e_os.h"
+#include "internal/param_build_set.h"
+
+/* Mapping between a flag and a name */
+static const OSSL_ITEM encoding_nameid_map[] = {
+ { OPENSSL_EC_EXPLICIT_CURVE, OSSL_PKEY_EC_ENCODING_EXPLICIT },
+ { OPENSSL_EC_NAMED_CURVE, OSSL_PKEY_EC_ENCODING_GROUP },
+};
+
+static const OSSL_ITEM check_group_type_nameid_map[] = {
+ { 0, OSSL_PKEY_EC_GROUP_CHECK_DEFAULT },
+ { EC_FLAG_CHECK_NAMED_GROUP, OSSL_PKEY_EC_GROUP_CHECK_NAMED },
+ { EC_FLAG_CHECK_NAMED_GROUP_NIST, OSSL_PKEY_EC_GROUP_CHECK_NAMED_NIST },
+};
+
+static const OSSL_ITEM format_nameid_map[] = {
+ { (int)POINT_CONVERSION_UNCOMPRESSED, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_UNCOMPRESSED },
+ { (int)POINT_CONVERSION_COMPRESSED, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED },
+ { (int)POINT_CONVERSION_HYBRID, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_HYBRID },
+};
+
+int ossl_ec_encoding_name2id(const char *name)
+{
+ size_t i, sz;
+
+ /* Return the default value if there is no name */
+ if (name == NULL)
+ return OPENSSL_EC_NAMED_CURVE;
+
+ for (i = 0, sz = OSSL_NELEM(encoding_nameid_map); i < sz; i++) {
+ if (OPENSSL_strcasecmp(name, encoding_nameid_map[i].ptr) == 0)
+ return encoding_nameid_map[i].id;
+ }
+ return -1;
+}
+
+static char *ec_param_encoding_id2name(int id)
+{
+ size_t i, sz;
+
+ for (i = 0, sz = OSSL_NELEM(encoding_nameid_map); i < sz; i++) {
+ if (id == (int)encoding_nameid_map[i].id)
+ return encoding_nameid_map[i].ptr;
+ }
+ return NULL;
+}
+
+char *ossl_ec_check_group_type_id2name(int id)
+{
+ size_t i, sz;
+
+ for (i = 0, sz = OSSL_NELEM(check_group_type_nameid_map); i < sz; i++) {
+ if (id == (int)check_group_type_nameid_map[i].id)
+ return check_group_type_nameid_map[i].ptr;
+ }
+ return NULL;
+}
+
+static int ec_check_group_type_name2id(const char *name)
+{
+ size_t i, sz;
+
+ /* Return the default value if there is no name */
+ if (name == NULL)
+ return 0;
+
+ for (i = 0, sz = OSSL_NELEM(check_group_type_nameid_map); i < sz; i++) {
+ if (OPENSSL_strcasecmp(name, check_group_type_nameid_map[i].ptr) == 0)
+ return check_group_type_nameid_map[i].id;
+ }
+ return -1;
+}
+
+int ossl_ec_set_check_group_type_from_name(EC_KEY *ec, const char *name)
+{
+ int flags = ec_check_group_type_name2id(name);
+
+ if (flags == -1)
+ return 0;
+ EC_KEY_clear_flags(ec, EC_FLAG_CHECK_NAMED_GROUP_MASK);
+ EC_KEY_set_flags(ec, flags);
+ return 1;
+}
+
+static int ec_set_check_group_type_from_param(EC_KEY *ec, const OSSL_PARAM *p)
+{
+ const char *name = NULL;
+ int status = 0;
+
+ switch (p->data_type) {
+ case OSSL_PARAM_UTF8_STRING:
+ name = p->data;
+ status = (name != NULL);
+ break;
+ case OSSL_PARAM_UTF8_PTR:
+ status = OSSL_PARAM_get_utf8_ptr(p, &name);
+ break;
+ }
+ if (status)
+ return ossl_ec_set_check_group_type_from_name(ec, name);
+ return 0;
+}
+
+int ossl_ec_pt_format_name2id(const char *name)
+{
+ size_t i, sz;
+
+ /* Return the default value if there is no name */
+ if (name == NULL)
+ return (int)POINT_CONVERSION_UNCOMPRESSED;
+
+ for (i = 0, sz = OSSL_NELEM(format_nameid_map); i < sz; i++) {
+ if (OPENSSL_strcasecmp(name, format_nameid_map[i].ptr) == 0)
+ return format_nameid_map[i].id;
+ }
+ return -1;
+}
+
+char *ossl_ec_pt_format_id2name(int id)
+{
+ size_t i, sz;
+
+ for (i = 0, sz = OSSL_NELEM(format_nameid_map); i < sz; i++) {
+ if (id == (int)format_nameid_map[i].id)
+ return format_nameid_map[i].ptr;
+ }
+ return NULL;
+}
+
+static int ec_group_explicit_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl,
+ OSSL_PARAM params[], BN_CTX *bnctx,
+ unsigned char **genbuf)
+{
+ int ret = 0, fid;
+ const char *field_type;
+ const OSSL_PARAM *param = NULL;
+ const OSSL_PARAM *param_p = NULL;
+ const OSSL_PARAM *param_a = NULL;
+ const OSSL_PARAM *param_b = NULL;
+
+ fid = EC_GROUP_get_field_type(group);
+
+ if (fid == NID_X9_62_prime_field) {
+ field_type = SN_X9_62_prime_field;
+ } else if (fid == NID_X9_62_characteristic_two_field) {
+#ifdef OPENSSL_NO_EC2M
+ ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
+ goto err;
+#else
+ field_type = SN_X9_62_characteristic_two_field;
+#endif
+ } else {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
+ return 0;
+ }
+
+ param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_P);
+ param_a = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_A);
+ param_b = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_B);
+ if (tmpl != NULL || param_p != NULL || param_a != NULL || param_b != NULL)
+ {
+ BIGNUM *p = BN_CTX_get(bnctx);
+ BIGNUM *a = BN_CTX_get(bnctx);
+ BIGNUM *b = BN_CTX_get(bnctx);
+
+ if (b == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EC_GROUP_get_curve(group, p, a, b, bnctx)) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE);
+ goto err;
+ }
+ if (!ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_P, p)
+ || !ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_A, a)
+ || !ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_B, b)) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ORDER);
+ if (tmpl != NULL || param != NULL) {
+ const BIGNUM *order = EC_GROUP_get0_order(group);
+
+ if (order == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
+ goto err;
+ }
+ if (!ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_ORDER,
+ order)) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE);
+ if (tmpl != NULL || param != NULL) {
+ if (!ossl_param_build_set_utf8_string(tmpl, params,
+ OSSL_PKEY_PARAM_EC_FIELD_TYPE,
+ field_type)) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_GENERATOR);
+ if (tmpl != NULL || param != NULL) {
+ size_t genbuf_len;
+ const EC_POINT *genpt = EC_GROUP_get0_generator(group);
+ point_conversion_form_t genform = EC_GROUP_get_point_conversion_form(group);
+
+ if (genpt == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
+ goto err;
+ }
+ genbuf_len = EC_POINT_point2buf(group, genpt, genform, genbuf, bnctx);
+ if (genbuf_len == 0) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
+ goto err;
+ }
+ if (!ossl_param_build_set_octet_string(tmpl, params,
+ OSSL_PKEY_PARAM_EC_GENERATOR,
+ *genbuf, genbuf_len)) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_COFACTOR);
+ if (tmpl != NULL || param != NULL) {
+ const BIGNUM *cofactor = EC_GROUP_get0_cofactor(group);
+
+ if (cofactor != NULL
+ && !ossl_param_build_set_bn(tmpl, params,
+ OSSL_PKEY_PARAM_EC_COFACTOR, cofactor)) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED);
+ if (tmpl != NULL || param != NULL) {
+ unsigned char *seed = EC_GROUP_get0_seed(group);
+ size_t seed_len = EC_GROUP_get_seed_len(group);
+
+ if (seed != NULL
+ && seed_len > 0
+ && !ossl_param_build_set_octet_string(tmpl, params,
+ OSSL_PKEY_PARAM_EC_SEED,
+ seed, seed_len)) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ ret = 1;
+err:
+ return ret;
+}
+
+int ossl_ec_group_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl,
+ OSSL_PARAM params[], OSSL_LIB_CTX *libctx,
+ const char *propq,
+ BN_CTX *bnctx, unsigned char **genbuf)
+{
+ int ret = 0, curve_nid, encoding_flag;
+ const char *encoding_name, *pt_form_name;
+ point_conversion_form_t genform;
+
+ if (group == NULL) {
+ ERR_raise(ERR_LIB_EC,EC_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ genform = EC_GROUP_get_point_conversion_form(group);
+ pt_form_name = ossl_ec_pt_format_id2name(genform);
+ if (pt_form_name == NULL
+ || !ossl_param_build_set_utf8_string(
+ tmpl, params,
+ OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, pt_form_name)) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_FORM);
+ return 0;
+ }
+ encoding_flag = EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE;
+ encoding_name = ec_param_encoding_id2name(encoding_flag);
+ if (encoding_name == NULL
+ || !ossl_param_build_set_utf8_string(tmpl, params,
+ OSSL_PKEY_PARAM_EC_ENCODING,
+ encoding_name)) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
+ return 0;
+ }
+
+ if (!ossl_param_build_set_int(tmpl, params,
+ OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS,
+ group->decoded_from_explicit_params))
+ return 0;
+
+ curve_nid = EC_GROUP_get_curve_name(group);
+
+ /*
+ * Get the explicit parameters in these two cases:
+ * - We do not have a template, i.e. specific parameters are requested
+ * - The curve is not a named curve
+ */
+ if (tmpl == NULL || curve_nid == NID_undef)
+ if (!ec_group_explicit_todata(group, tmpl, params, bnctx, genbuf))
+ goto err;
+
+ if (curve_nid != NID_undef) {
+ /* Named curve */
+ const char *curve_name = OSSL_EC_curve_nid2name(curve_nid);
+
+ if (curve_name == NULL
+ || !ossl_param_build_set_utf8_string(tmpl, params,
+ OSSL_PKEY_PARAM_GROUP_NAME,
+ curve_name)) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE);
+ goto err;
+ }
+ }
+ ret = 1;
+err:
+ return ret;
+}
+
+/*
+ * The intention with the "backend" source file is to offer backend support
+ * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
+ * implementations alike.
+ */
+int ossl_ec_set_ecdh_cofactor_mode(EC_KEY *ec, int mode)
+{
+ const EC_GROUP *ecg = EC_KEY_get0_group(ec);
+ const BIGNUM *cofactor;
+ /*
+ * mode can be only 0 for disable, or 1 for enable here.
+ *
+ * This is in contrast with the same parameter on an ECDH EVP_PKEY_CTX that
+ * also supports mode == -1 with the meaning of "reset to the default for
+ * the associated key".
+ */
+ if (mode < 0 || mode > 1)
+ return 0;
+
+ if ((cofactor = EC_GROUP_get0_cofactor(ecg)) == NULL )
+ return 0;
+
+ /* ECDH cofactor mode has no effect if cofactor is 1 */
+ if (BN_is_one(cofactor))
+ return 1;
+
+ if (mode == 1)
+ EC_KEY_set_flags(ec, EC_FLAG_COFACTOR_ECDH);
+ else if (mode == 0)
+ EC_KEY_clear_flags(ec, EC_FLAG_COFACTOR_ECDH);
+
+ return 1;
+}
+
+/*
+ * Callers of ossl_ec_key_fromdata MUST make sure that ec_key_params_fromdata has
+ * been called before!
+ *
+ * This function only gets the bare keypair, domain parameters and other
+ * parameters are treated separately, and domain parameters are required to
+ * define a keypair.
+ */
+int ossl_ec_key_fromdata(EC_KEY *ec, const OSSL_PARAM params[], int include_private)
+{
+ const OSSL_PARAM *param_priv_key = NULL, *param_pub_key = NULL;
+ BN_CTX *ctx = NULL;
+ BIGNUM *priv_key = NULL;
+ unsigned char *pub_key = NULL;
+ size_t pub_key_len;
+ const EC_GROUP *ecg = NULL;
+ EC_POINT *pub_point = NULL;
+ int ok = 0;
+
+ ecg = EC_KEY_get0_group(ec);
+ if (ecg == NULL)
+ return 0;
+
+ param_pub_key =
+ OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
+ if (include_private)
+ param_priv_key =
+ OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
+
+ ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec));
+ if (ctx == NULL)
+ goto err;
+
+ if (param_pub_key != NULL)
+ if (!OSSL_PARAM_get_octet_string(param_pub_key,
+ (void **)&pub_key, 0, &pub_key_len)
+ || (pub_point = EC_POINT_new(ecg)) == NULL
+ || !EC_POINT_oct2point(ecg, pub_point, pub_key, pub_key_len, ctx))
+ goto err;
+
+ if (param_priv_key != NULL && include_private) {
+ int fixed_words;
+ const BIGNUM *order;
+
+ /*
+ * Key import/export should never leak the bit length of the secret
+ * scalar in the key.
+ *
+ * For this reason, on export we use padded BIGNUMs with fixed length.
+ *
+ * When importing we also should make sure that, even if short lived,
+ * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
+ * soon as possible, so that any processing of this BIGNUM might opt for
+ * constant time implementations in the backend.
+ *
+ * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
+ * to preallocate the BIGNUM internal buffer to a fixed public size big
+ * enough that operations performed during the processing never trigger
+ * a realloc which would leak the size of the scalar through memory
+ * accesses.
+ *
+ * Fixed Length
+ * ------------
+ *
+ * The order of the large prime subgroup of the curve is our choice for
+ * a fixed public size, as that is generally the upper bound for
+ * generating a private key in EC cryptosystems and should fit all valid
+ * secret scalars.
+ *
+ * For padding on export we just use the bit length of the order
+ * converted to bytes (rounding up).
+ *
+ * For preallocating the BIGNUM storage we look at the number of "words"
+ * required for the internal representation of the order, and we
+ * preallocate 2 extra "words" in case any of the subsequent processing
+ * might temporarily overflow the order length.
+ */
+ order = EC_GROUP_get0_order(ecg);
+ if (order == NULL || BN_is_zero(order))
+ goto err;
+
+ fixed_words = bn_get_top(order) + 2;
+
+ if ((priv_key = BN_secure_new()) == NULL)
+ goto err;
+ if (bn_wexpand(priv_key, fixed_words) == NULL)
+ goto err;
+ BN_set_flags(priv_key, BN_FLG_CONSTTIME);
+
+ if (!OSSL_PARAM_get_BN(param_priv_key, &priv_key))
+ goto err;
+ }
+
+ if (priv_key != NULL
+ && !EC_KEY_set_private_key(ec, priv_key))
+ goto err;
+
+ if (pub_point != NULL
+ && !EC_KEY_set_public_key(ec, pub_point))
+ goto err;
+
+ ok = 1;
+
+ err:
+ BN_CTX_free(ctx);
+ BN_clear_free(priv_key);
+ OPENSSL_free(pub_key);
+ EC_POINT_free(pub_point);
+ return ok;
+}
+
+int ossl_ec_group_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
+{
+ int ok = 0;
+ EC_GROUP *group = NULL;
+
+ if (ec == NULL)
+ return 0;
+
+ group = EC_GROUP_new_from_params(params, ossl_ec_key_get_libctx(ec),
+ ossl_ec_key_get0_propq(ec));
+
+ if (!EC_KEY_set_group(ec, group))
+ goto err;
+ ok = 1;
+err:
+ EC_GROUP_free(group);
+ return ok;
+}
+
+static int ec_key_point_format_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ int format = -1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT);
+ if (p != NULL) {
+ if (!ossl_ec_pt_format_param2id(p, &format)) {
+ ECerr(0, EC_R_INVALID_FORM);
+ return 0;
+ }
+ EC_KEY_set_conv_form(ec, format);
+ }
+ return 1;
+}
+
+static int ec_key_group_check_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE);
+ if (p != NULL)
+ return ec_set_check_group_type_from_param(ec, p);
+ return 1;
+}
+
+static int ec_set_include_public(EC_KEY *ec, int include)
+{
+ int flags = EC_KEY_get_enc_flags(ec);
+
+ if (!include)
+ flags |= EC_PKEY_NO_PUBKEY;
+ else
+ flags &= ~EC_PKEY_NO_PUBKEY;
+ EC_KEY_set_enc_flags(ec, flags);
+ return 1;
+}
+
+int ossl_ec_key_otherparams_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+
+ if (ec == NULL)
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
+ if (p != NULL) {
+ int mode;
+
+ if (!OSSL_PARAM_get_int(p, &mode)
+ || !ossl_ec_set_ecdh_cofactor_mode(ec, mode))
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC);
+ if (p != NULL) {
+ int include = 1;
+
+ if (!OSSL_PARAM_get_int(p, &include)
+ || !ec_set_include_public(ec, include))
+ return 0;
+ }
+ if (!ec_key_point_format_fromdata(ec, params))
+ return 0;
+ if (!ec_key_group_check_fromdata(ec, params))
+ return 0;
+ return 1;
+}
+
+int ossl_ec_key_is_foreign(const EC_KEY *ec)
+{
+#ifndef FIPS_MODULE
+ if (ec->engine != NULL || EC_KEY_get_method(ec) != EC_KEY_OpenSSL())
+ return 1;
+#endif
+ return 0;
+
+}
+
+EC_KEY *ossl_ec_key_dup(const EC_KEY *src, int selection)
+{
+ EC_KEY *ret;
+
+ if (src == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+
+ if ((ret = ossl_ec_key_new_method_int(src->libctx, src->propq,
+ src->engine)) == NULL)
+ return NULL;
+
+ /* copy the parameters */
+ if (src->group != NULL
+ && (selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
+ ret->group = ossl_ec_group_new_ex(src->libctx, src->propq,
+ src->group->meth);
+ if (ret->group == NULL
+ || !EC_GROUP_copy(ret->group, src->group))
+ goto err;
+
+ if (src->meth != NULL) {
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
+ if (src->engine != NULL && ENGINE_init(src->engine) == 0)
+ goto err;
+ ret->engine = src->engine;
+#endif
+ ret->meth = src->meth;
+ }
+ }
+
+ /* copy the public key */
+ if (src->pub_key != NULL
+ && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ if (ret->group == NULL)
+ /* no parameter-less keys allowed */
+ goto err;
+ ret->pub_key = EC_POINT_new(ret->group);
+ if (ret->pub_key == NULL
+ || !EC_POINT_copy(ret->pub_key, src->pub_key))
+ goto err;
+ }
+
+ /* copy the private key */
+ if (src->priv_key != NULL
+ && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ if (ret->group == NULL)
+ /* no parameter-less keys allowed */
+ goto err;
+ ret->priv_key = BN_new();
+ if (ret->priv_key == NULL || !BN_copy(ret->priv_key, src->priv_key))
+ goto err;
+ if (ret->group->meth->keycopy
+ && ret->group->meth->keycopy(ret, src) == 0)
+ goto err;
+ }
+
+ /* copy the rest */
+ if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0) {
+ ret->enc_flag = src->enc_flag;
+ ret->conv_form = src->conv_form;
+ }
+
+ ret->version = src->version;
+ ret->flags = src->flags;
+
+#ifndef FIPS_MODULE
+ if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY,
+ &ret->ex_data, &src->ex_data))
+ goto err;
+#endif
+
+ if (ret->meth != NULL && ret->meth->copy != NULL) {
+ if ((selection
+ & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR)
+ goto err;
+ if (ret->meth->copy(ret, src) == 0)
+ goto err;
+ }
+
+ return ret;
+ err:
+ EC_KEY_free(ret);
+ return NULL;
+}
+
+int ossl_ec_encoding_param2id(const OSSL_PARAM *p, int *id)
+{
+ const char *name = NULL;
+ int status = 0;
+
+ switch (p->data_type) {
+ case OSSL_PARAM_UTF8_STRING:
+ /* The OSSL_PARAM functions have no support for this */
+ name = p->data;
+ status = (name != NULL);
+ break;
+ case OSSL_PARAM_UTF8_PTR:
+ status = OSSL_PARAM_get_utf8_ptr(p, &name);
+ break;
+ }
+ if (status) {
+ int i = ossl_ec_encoding_name2id(name);
+
+ if (i >= 0) {
+ *id = i;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int ossl_ec_pt_format_param2id(const OSSL_PARAM *p, int *id)
+{
+ const char *name = NULL;
+ int status = 0;
+
+ switch (p->data_type) {
+ case OSSL_PARAM_UTF8_STRING:
+ /* The OSSL_PARAM functions have no support for this */
+ name = p->data;
+ status = (name != NULL);
+ break;
+ case OSSL_PARAM_UTF8_PTR:
+ status = OSSL_PARAM_get_utf8_ptr(p, &name);
+ break;
+ }
+ if (status) {
+ int i = ossl_ec_pt_format_name2id(name);
+
+ if (i >= 0) {
+ *id = i;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#ifndef FIPS_MODULE
+int ossl_x509_algor_is_sm2(const X509_ALGOR *palg)
+{
+ int ptype = 0;
+ const void *pval = NULL;
+
+ X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+
+ if (ptype == V_ASN1_OBJECT)
+ return OBJ_obj2nid((ASN1_OBJECT *)pval) == NID_sm2;
+
+ if (ptype == V_ASN1_SEQUENCE) {
+ const ASN1_STRING *str = pval;
+ const unsigned char *der = str->data;
+ int derlen = str->length;
+ EC_GROUP *group;
+ int ret;
+
+ if ((group = d2i_ECPKParameters(NULL, &der, derlen)) == NULL)
+ ret = 0;
+ else
+ ret = (EC_GROUP_get_curve_name(group) == NID_sm2);
+
+ EC_GROUP_free(group);
+ return ret;
+ }
+
+ return 0;
+}
+
+EC_KEY *ossl_ec_key_param_from_x509_algor(const X509_ALGOR *palg,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ int ptype = 0;
+ const void *pval = NULL;
+ EC_KEY *eckey = NULL;
+ EC_GROUP *group = NULL;
+
+ X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+ if ((eckey = EC_KEY_new_ex(libctx, propq)) == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto ecerr;
+ }
+
+ if (ptype == V_ASN1_SEQUENCE) {
+ const ASN1_STRING *pstr = pval;
+ const unsigned char *pm = pstr->data;
+ int pmlen = pstr->length;
+
+
+ if (d2i_ECParameters(&eckey, &pm, pmlen) == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
+ goto ecerr;
+ }
+ } else if (ptype == V_ASN1_OBJECT) {
+ const ASN1_OBJECT *poid = pval;
+
+ /*
+ * type == V_ASN1_OBJECT => the parameters are given by an asn1 OID
+ */
+
+ group = EC_GROUP_new_by_curve_name_ex(libctx, propq, OBJ_obj2nid(poid));
+ if (group == NULL)
+ goto ecerr;
+ EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
+ if (EC_KEY_set_group(eckey, group) == 0)
+ goto ecerr;
+ EC_GROUP_free(group);
+ } else {
+ ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
+ goto ecerr;
+ }
+
+ return eckey;
+
+ ecerr:
+ EC_KEY_free(eckey);
+ EC_GROUP_free(group);
+ return NULL;
+}
+
+EC_KEY *ossl_ec_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ const unsigned char *p = NULL;
+ int pklen;
+ EC_KEY *eckey = NULL;
+ const X509_ALGOR *palg;
+
+ if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8inf))
+ return 0;
+ eckey = ossl_ec_key_param_from_x509_algor(palg, libctx, propq);
+ if (eckey == NULL)
+ goto err;
+
+ /* We have parameters now set private key */
+ if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
+ ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
+ goto err;
+ }
+
+ return eckey;
+ err:
+ EC_KEY_free(eckey);
+ return NULL;
+}
+#endif
diff --git a/crypto/ec/ec_check.c b/crypto/ec/ec_check.c
index d0706d2857e6..484124915dc6 100644
--- a/crypto/ec/ec_check.c
+++ b/crypto/ec/ec_check.c
@@ -1,22 +1,67 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include "ec_local.h"
#include <openssl/err.h>
+int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only,
+ BN_CTX *ctx)
+{
+ int nid;
+ BN_CTX *new_ctx = NULL;
+
+ if (group == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
+ return NID_undef;
+ }
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new_ex(NULL);
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ return NID_undef;
+ }
+ }
+
+ nid = ossl_ec_curve_nid_from_params(group, ctx);
+ if (nid > 0 && nist_only && EC_curve_nid2nist(nid) == NULL)
+ nid = NID_undef;
+
+ BN_CTX_free(new_ctx);
+ return nid;
+}
+
int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)
{
+#ifdef FIPS_MODULE
+ /*
+ * ECC domain parameter validation.
+ * See SP800-56A R3 5.5.2 "Assurances of Domain-Parameter Validity" Part 1b.
+ */
+ return EC_GROUP_check_named_curve(group, 1, ctx) >= 0 ? 1 : 0;
+#else
int ret = 0;
const BIGNUM *order;
BN_CTX *new_ctx = NULL;
EC_POINT *point = NULL;
+ if (group == NULL || group->meth == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
/* Custom curves assumed to be correct */
if ((group->meth->flags & EC_FLAGS_CUSTOM_CURVE) != 0)
return 1;
@@ -24,24 +69,24 @@ int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL) {
- ECerr(EC_F_EC_GROUP_CHECK, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
}
/* check the discriminant */
if (!EC_GROUP_check_discriminant(group, ctx)) {
- ECerr(EC_F_EC_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO);
+ ERR_raise(ERR_LIB_EC, EC_R_DISCRIMINANT_IS_ZERO);
goto err;
}
/* check the generator */
if (group->generator == NULL) {
- ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR);
+ ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR);
goto err;
}
if (EC_POINT_is_on_curve(group, group->generator, ctx) <= 0) {
- ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE);
+ ERR_raise(ERR_LIB_EC, EC_R_POINT_IS_NOT_ON_CURVE);
goto err;
}
@@ -52,14 +97,14 @@ int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)
if (order == NULL)
goto err;
if (BN_is_zero(order)) {
- ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_ORDER);
+ ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_ORDER);
goto err;
}
if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx))
goto err;
if (!EC_POINT_is_at_infinity(group, point)) {
- ECerr(EC_F_EC_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
goto err;
}
@@ -69,4 +114,5 @@ int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)
BN_CTX_free(new_ctx);
EC_POINT_free(point);
return ret;
+#endif /* FIPS_MODULE */
}
diff --git a/crypto/ec/ec_curve.c b/crypto/ec/ec_curve.c
index b4c14e91e175..b5b2f3342dfb 100644
--- a/crypto/ec/ec_curve.c
+++ b/crypto/ec/ec_curve.c
@@ -2,12 +2,18 @@
* Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <string.h>
#include "ec_local.h"
#include <openssl/err.h>
@@ -194,6 +200,7 @@ static const struct {
}
};
+# ifndef FIPS_MODULE
/* the x9.62 prime curves (minus the nist prime curves) */
static const struct {
EC_CURVE_DATA h;
@@ -372,6 +379,7 @@ static const struct {
0x43, 0x21, 0x46, 0x52, 0x65, 0x51
}
};
+#endif /* FIPS_MODULE */
static const struct {
EC_CURVE_DATA h;
@@ -411,6 +419,7 @@ static const struct {
}
};
+#ifndef FIPS_MODULE
/* the secg prime curves (minus the nist and x9.62 prime curves) */
static const struct {
EC_CURVE_DATA h;
@@ -832,10 +841,13 @@ static const struct {
0x5C, 0x5C, 0x2A, 0x3D
}
};
+#endif /* FIPS_MODULE */
#ifndef OPENSSL_NO_EC2M
/* characteristic two curves */
+
+# ifndef FIPS_MODULE
static const struct {
EC_CURVE_DATA h;
unsigned char data[20 + 15 * 6];
@@ -963,6 +975,7 @@ static const struct {
0x33, 0x04, 0x9B, 0xA9, 0x8F
}
};
+# endif /* FIPS_MODULE */
static const struct {
EC_CURVE_DATA h;
@@ -994,6 +1007,7 @@ static const struct {
}
};
+# ifndef FIPS_MODULE
static const struct {
EC_CURVE_DATA h;
unsigned char data[0 + 21 * 6];
@@ -1022,6 +1036,7 @@ static const struct {
0xAA, 0xB6, 0x89, 0xC2, 0x9C, 0xA7, 0x10, 0x27, 0x9B
}
};
+# endif /* FIPS_MODULE */
static const struct {
EC_CURVE_DATA h;
@@ -1052,6 +1067,7 @@ static const struct {
}
};
+# ifndef FIPS_MODULE
static const struct {
EC_CURVE_DATA h;
unsigned char data[20 + 25 * 6];
@@ -1127,6 +1143,7 @@ static const struct {
0xD5
}
};
+# endif /* FIPS_MODULE */
static const struct {
EC_CURVE_DATA h;
@@ -1137,6 +1154,7 @@ static const struct {
},
{
/* no seed */
+ /* p */
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
@@ -1201,6 +1219,7 @@ static const struct {
}
};
+#ifndef FIPS_MODULE
static const struct {
EC_CURVE_DATA h;
unsigned char data[0 + 30 * 6];
@@ -1210,6 +1229,7 @@ static const struct {
},
{
/* no seed */
+ /* p */
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
@@ -1235,6 +1255,7 @@ static const struct {
0x1D, 0xA8, 0x00, 0xE4, 0x78, 0xA5
}
};
+# endif /* FIPS_MODULE */
static const struct {
EC_CURVE_DATA h;
@@ -1245,6 +1266,7 @@ static const struct {
},
{
/* no seed */
+ /* p */
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA1,
@@ -1279,7 +1301,7 @@ static const struct {
NID_X9_62_characteristic_two_field, 20, 36, 2
},
{
- /* no seed */
+ /* seed */
0x77, 0xE2, 0xB0, 0x73, 0x70, 0xEB, 0x0F, 0x83, 0x2A, 0x6D, 0xD5, 0xB6,
0x2D, 0xFC, 0x88, 0xCD, 0x06, 0xBB, 0x84, 0xBE,
/* p */
@@ -1517,6 +1539,7 @@ static const struct {
}
};
+# ifndef FIPS_MODULE
static const struct {
EC_CURVE_DATA h;
unsigned char data[20 + 21 * 6];
@@ -2201,8 +2224,8 @@ static const struct {
0xED, 0xF9, 0x7C, 0x44, 0xDB, 0x9F, 0x24, 0x20, 0xBA, 0xFC, 0xA7, 0x5E
}
};
-
-#endif
+# endif /* FIPS_MODULE */
+#endif /* OPENSSL_NO_EC2M */
/*
* These curves were added by Annie Yousar.
@@ -2212,6 +2235,7 @@ static const struct {
* generation mechanism is different from those defined in ANSI X9.62.
*/
+#ifndef FIPS_MODULE
static const struct {
EC_CURVE_DATA h;
unsigned char data[0 + 20 * 6];
@@ -2751,8 +2775,9 @@ static const struct {
0x9C, 0xA9, 0x00, 0x69
}
};
+#endif /* FIPS_MODULE */
-#ifndef OPENSSL_NO_SM2
+#if !defined(OPENSSL_NO_SM2) && !defined(FIPS_MODULE)
static const struct {
EC_CURVE_DATA h;
unsigned char data[0 + 32 * 6];
@@ -2798,6 +2823,79 @@ typedef struct _ec_list_element_st {
const char *comment;
} ec_list_element;
+#ifdef FIPS_MODULE
+static const ec_list_element curve_list[] = {
+ /* prime field curves */
+ /* secg curves */
+ {NID_secp224r1, &_EC_NIST_PRIME_224.h,
+# if !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
+ EC_GFp_nistp224_method,
+# else
+ 0,
+# endif
+ "NIST/SECG curve over a 224 bit prime field"},
+ /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
+ {NID_secp384r1, &_EC_NIST_PRIME_384.h,
+# if defined(S390X_EC_ASM)
+ EC_GFp_s390x_nistp384_method,
+# else
+ 0,
+# endif
+ "NIST/SECG curve over a 384 bit prime field"},
+
+ {NID_secp521r1, &_EC_NIST_PRIME_521.h,
+# if defined(S390X_EC_ASM)
+ EC_GFp_s390x_nistp521_method,
+# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
+ EC_GFp_nistp521_method,
+# else
+ 0,
+# endif
+ "NIST/SECG curve over a 521 bit prime field"},
+
+ /* X9.62 curves */
+ {NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0,
+ "NIST/X9.62/SECG curve over a 192 bit prime field"},
+ {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
+# if defined(ECP_NISTZ256_ASM)
+ EC_GFp_nistz256_method,
+# elif defined(S390X_EC_ASM)
+ EC_GFp_s390x_nistp256_method,
+# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
+ EC_GFp_nistp256_method,
+# else
+ 0,
+# endif
+ "X9.62/SECG curve over a 256 bit prime field"},
+
+# ifndef OPENSSL_NO_EC2M
+ /* characteristic two field curves */
+ /* NIST/SECG curves */
+ {NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0,
+ "NIST/SECG/WTLS curve over a 163 bit binary field"},
+ {NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0,
+ "NIST/SECG curve over a 163 bit binary field"},
+ {NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0,
+ "NIST/SECG/WTLS curve over a 233 bit binary field"},
+ {NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0,
+ "NIST/SECG/WTLS curve over a 233 bit binary field"},
+ {NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0,
+ "NIST/SECG curve over a 283 bit binary field"},
+ {NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0,
+ "NIST/SECG curve over a 283 bit binary field"},
+ {NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0,
+ "NIST/SECG curve over a 409 bit binary field"},
+ {NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0,
+ "NIST/SECG curve over a 409 bit binary field"},
+ {NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0,
+ "NIST/SECG curve over a 571 bit binary field"},
+ {NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0,
+ "NIST/SECG curve over a 571 bit binary field"},
+# endif
+};
+
+#else
+
static const ec_list_element curve_list[] = {
/* prime field curves */
/* secg curves */
@@ -2820,25 +2918,32 @@ static const ec_list_element curve_list[] = {
"SECG curve over a 192 bit prime field"},
{NID_secp224k1, &_EC_SECG_PRIME_224K1.h, 0,
"SECG curve over a 224 bit prime field"},
-#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
+# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
{NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method,
"NIST/SECG curve over a 224 bit prime field"},
-#else
+# else
{NID_secp224r1, &_EC_NIST_PRIME_224.h, 0,
"NIST/SECG curve over a 224 bit prime field"},
-#endif
+# endif
{NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0,
"SECG curve over a 256 bit prime field"},
/* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
- {NID_secp384r1, &_EC_NIST_PRIME_384.h, 0,
+ {NID_secp384r1, &_EC_NIST_PRIME_384.h,
+# if defined(S390X_EC_ASM)
+ EC_GFp_s390x_nistp384_method,
+# else
+ 0,
+# endif
"NIST/SECG curve over a 384 bit prime field"},
-#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
- {NID_secp521r1, &_EC_NIST_PRIME_521.h, EC_GFp_nistp521_method,
- "NIST/SECG curve over a 521 bit prime field"},
-#else
- {NID_secp521r1, &_EC_NIST_PRIME_521.h, 0,
+ {NID_secp521r1, &_EC_NIST_PRIME_521.h,
+# if defined(S390X_EC_ASM)
+ EC_GFp_s390x_nistp521_method,
+# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
+ EC_GFp_nistp521_method,
+# else
+ 0,
+# endif
"NIST/SECG curve over a 521 bit prime field"},
-#endif
/* X9.62 curves */
{NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0,
"NIST/X9.62/SECG curve over a 192 bit prime field"},
@@ -2853,15 +2958,17 @@ static const ec_list_element curve_list[] = {
{NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, 0,
"X9.62 curve over a 239 bit prime field"},
{NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
-#if defined(ECP_NISTZ256_ASM)
+# if defined(ECP_NISTZ256_ASM)
EC_GFp_nistz256_method,
-#elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
+# elif defined(S390X_EC_ASM)
+ EC_GFp_s390x_nistp256_method,
+# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
EC_GFp_nistp256_method,
-#else
+# else
0,
-#endif
+# endif
"X9.62/SECG curve over a 256 bit prime field"},
-#ifndef OPENSSL_NO_EC2M
+# ifndef OPENSSL_NO_EC2M
/* characteristic two field curves */
/* NIST/SECG curves */
{NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, 0,
@@ -2945,7 +3052,7 @@ static const ec_list_element curve_list[] = {
"SECG curve over a 113 bit binary field"},
{NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0,
"X9.62 curve over a 163 bit binary field"},
-#endif
+# endif
{NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0,
"SECG/WTLS curve over a 112 bit prime field"},
{NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, 0,
@@ -2954,15 +3061,15 @@ static const ec_list_element curve_list[] = {
"WTLS curve over a 112 bit prime field"},
{NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0,
"WTLS curve over a 160 bit prime field"},
-#ifndef OPENSSL_NO_EC2M
+# ifndef OPENSSL_NO_EC2M
{NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, 0,
"NIST/SECG/WTLS curve over a 233 bit binary field"},
{NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0,
"NIST/SECG/WTLS curve over a 233 bit binary field"},
-#endif
+# endif
{NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0,
"WTLS curve over a 224 bit prime field"},
-#ifndef OPENSSL_NO_EC2M
+# ifndef OPENSSL_NO_EC2M
/* IPSec curves */
{NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0,
"\n\tIPSec/IKE/Oakley curve #3 over a 155 bit binary field.\n"
@@ -2970,7 +3077,7 @@ static const ec_list_element curve_list[] = {
{NID_ipsec4, &_EC_IPSEC_185_ID4.h, 0,
"\n\tIPSec/IKE/Oakley curve #4 over a 185 bit binary field.\n"
"\tNot suitable for ECDSA.\n\tQuestionable extension field!"},
-#endif
+# endif
/* brainpool curves */
{NID_brainpoolP160r1, &_EC_brainpoolP160r1.h, 0,
"RFC 5639 curve over a 160 bit prime field"},
@@ -3000,15 +3107,32 @@ static const ec_list_element curve_list[] = {
"RFC 5639 curve over a 512 bit prime field"},
{NID_brainpoolP512t1, &_EC_brainpoolP512t1.h, 0,
"RFC 5639 curve over a 512 bit prime field"},
-#ifndef OPENSSL_NO_SM2
+# ifndef OPENSSL_NO_SM2
{NID_sm2, &_EC_sm2p256v1.h, 0,
"SM2 curve over a 256 bit prime field"},
-#endif
+# endif
};
+#endif /* FIPS_MODULE */
#define curve_list_length OSSL_NELEM(curve_list)
-static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
+static const ec_list_element *ec_curve_nid2curve(int nid)
+{
+ size_t i;
+
+ if (nid <= 0)
+ return NULL;
+
+ for (i = 0; i < curve_list_length; i++) {
+ if (curve_list[i].nid == nid)
+ return &curve_list[i];
+ }
+ return NULL;
+}
+
+static EC_GROUP *ec_group_new_from_data(OSSL_LIB_CTX *libctx,
+ const char *propq,
+ const ec_list_element curve)
{
EC_GROUP *group = NULL;
EC_POINT *P = NULL;
@@ -3023,10 +3147,11 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
/* If no curve data curve method must handle everything */
if (curve.data == NULL)
- return EC_GROUP_new(curve.meth != NULL ? curve.meth() : NULL);
+ return ossl_ec_group_new_ex(libctx, propq,
+ curve.meth != NULL ? curve.meth() : NULL);
- if ((ctx = BN_CTX_new()) == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_MALLOC_FAILURE);
+ if ((ctx = BN_CTX_new_ex(libctx)) == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -3039,20 +3164,20 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
if ((p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) == NULL
|| (a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) == NULL
|| (b = BN_bin2bn(params + 2 * param_len, param_len, NULL)) == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
if (curve.meth != 0) {
meth = curve.meth();
- if (((group = EC_GROUP_new(meth)) == NULL) ||
+ if (((group = ossl_ec_group_new_ex(libctx, propq, meth)) == NULL) ||
(!(group->meth->group_set_curve(group, p, a, b, ctx)))) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
} else if (data->field_type == NID_X9_62_prime_field) {
if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
}
@@ -3061,7 +3186,7 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
* NID_X9_62_characteristic_two_field */
if ((group = EC_GROUP_new_curve_GF2m(p, a, b, ctx)) == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
}
@@ -3070,35 +3195,36 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
EC_GROUP_set_curve_name(group, curve.nid);
if ((P = EC_POINT_new(group)) == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if ((x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) == NULL
|| (y = BN_bin2bn(params + 4 * param_len, param_len, NULL)) == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
if (!EC_POINT_set_affine_coordinates(group, P, x, y, ctx)) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if ((order = BN_bin2bn(params + 5 * param_len, param_len, NULL)) == NULL
|| !BN_set_word(x, (BN_ULONG)data->cofactor)) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
if (!EC_GROUP_set_generator(group, P, order, x)) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if (seed_len) {
if (!EC_GROUP_set_seed(group, params - seed_len, seed_len)) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
}
+#ifndef FIPS_MODULE
if (EC_GROUP_get_asn1_flag(group) == OPENSSL_EC_NAMED_CURVE) {
/*
* Some curves don't have an associated OID: for those we should not
@@ -3115,7 +3241,7 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
ASN1_OBJECT *asn1obj = OBJ_nid2obj(curve.nid);
if (asn1obj == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_OBJ_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_OBJ_LIB);
goto err;
}
if (OBJ_length(asn1obj) == 0)
@@ -3123,6 +3249,16 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
ASN1_OBJECT_free(asn1obj);
}
+#else
+ /*
+ * Inside the FIPS module we do not support explicit curves anyway
+ * so the above check is not necessary.
+ *
+ * Skipping it is also necessary because `OBJ_length()` and
+ * `ASN1_OBJECT_free()` are not available within the FIPS module
+ * boundaries.
+ */
+#endif
ok = 1;
err:
@@ -3141,28 +3277,33 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
return group;
}
-EC_GROUP *EC_GROUP_new_by_curve_name(int nid)
+EC_GROUP *EC_GROUP_new_by_curve_name_ex(OSSL_LIB_CTX *libctx, const char *propq,
+ int nid)
{
- size_t i;
EC_GROUP *ret = NULL;
+ const ec_list_element *curve;
- if (nid <= 0)
- return NULL;
-
- for (i = 0; i < curve_list_length; i++)
- if (curve_list[i].nid == nid) {
- ret = ec_group_new_from_data(curve_list[i]);
- break;
- }
-
- if (ret == NULL) {
- ECerr(EC_F_EC_GROUP_NEW_BY_CURVE_NAME, EC_R_UNKNOWN_GROUP);
+ if ((curve = ec_curve_nid2curve(nid)) == NULL
+ || (ret = ec_group_new_from_data(libctx, propq, *curve)) == NULL) {
+#ifndef FIPS_MODULE
+ ERR_raise_data(ERR_LIB_EC, EC_R_UNKNOWN_GROUP,
+ "name=%s", OBJ_nid2sn(nid));
+#else
+ ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_GROUP);
+#endif
return NULL;
}
return ret;
}
+#ifndef FIPS_MODULE
+EC_GROUP *EC_GROUP_new_by_curve_name(int nid)
+{
+ return EC_GROUP_new_by_curve_name_ex(NULL, NULL, nid);
+}
+#endif
+
size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems)
{
size_t i, min;
@@ -3180,49 +3321,14 @@ size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems)
return curve_list_length;
}
-/* Functions to translate between common NIST curve names and NIDs */
-
-typedef struct {
- const char *name; /* NIST Name of curve */
- int nid; /* Curve NID */
-} EC_NIST_NAME;
-
-static EC_NIST_NAME nist_curves[] = {
- {"B-163", NID_sect163r2},
- {"B-233", NID_sect233r1},
- {"B-283", NID_sect283r1},
- {"B-409", NID_sect409r1},
- {"B-571", NID_sect571r1},
- {"K-163", NID_sect163k1},
- {"K-233", NID_sect233k1},
- {"K-283", NID_sect283k1},
- {"K-409", NID_sect409k1},
- {"K-571", NID_sect571k1},
- {"P-192", NID_X9_62_prime192v1},
- {"P-224", NID_secp224r1},
- {"P-256", NID_X9_62_prime256v1},
- {"P-384", NID_secp384r1},
- {"P-521", NID_secp521r1}
-};
-
const char *EC_curve_nid2nist(int nid)
{
- size_t i;
- for (i = 0; i < OSSL_NELEM(nist_curves); i++) {
- if (nist_curves[i].nid == nid)
- return nist_curves[i].name;
- }
- return NULL;
+ return ossl_ec_curve_nid2nist_int(nid);
}
int EC_curve_nist2nid(const char *name)
{
- size_t i;
- for (i = 0; i < OSSL_NELEM(nist_curves); i++) {
- if (strcmp(nist_curves[i].name, name) == 0)
- return nist_curves[i].nid;
- }
- return NID_undef;
+ return ossl_ec_curve_nist2nid_int(name);
}
#define NUM_BN_FIELDS 6
@@ -3234,7 +3340,7 @@ int EC_curve_nist2nid(const char *name)
* Returns: The nid associated with the found named curve, or NID_undef
* if not found. If there was an error it returns -1.
*/
-int ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx)
+int ossl_ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx)
{
int ret = -1, nid, len, field_type, param_len;
size_t i, seed_len;
@@ -3242,17 +3348,13 @@ int ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx)
unsigned char *param_bytes = NULL;
const EC_CURVE_DATA *data;
const EC_POINT *generator = NULL;
- const EC_METHOD *meth;
const BIGNUM *cofactor = NULL;
/* An array of BIGNUMs for (p, a, b, x, y, order) */
BIGNUM *bn[NUM_BN_FIELDS] = {NULL, NULL, NULL, NULL, NULL, NULL};
- meth = EC_GROUP_method_of(group);
- if (meth == NULL)
- return -1;
/* Use the optional named curve nid as a search field */
nid = EC_GROUP_get_curve_name(group);
- field_type = EC_METHOD_get_field_type(meth);
+ field_type = EC_GROUP_get_field_type(group);
seed_len = EC_GROUP_get_seed_len(group);
seed = EC_GROUP_get0_seed(group);
cofactor = EC_GROUP_get0_cofactor(group);
diff --git a/crypto/ec/ec_cvt.c b/crypto/ec/ec_cvt.c
index 944e317d9d14..1145bfb68f90 100644
--- a/crypto/ec/ec_cvt.c
+++ b/crypto/ec/ec_cvt.c
@@ -1,14 +1,21 @@
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/err.h>
+#include "crypto/bn.h"
#include "ec_local.h"
EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
@@ -47,12 +54,12 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
meth = EC_GFp_mont_method();
#endif
- ret = EC_GROUP_new(meth);
+ ret = ossl_ec_group_new_ex(ossl_bn_get_libctx(ctx), NULL, meth);
if (ret == NULL)
return NULL;
if (!EC_GROUP_set_curve(ret, p, a, b, ctx)) {
- EC_GROUP_clear_free(ret);
+ EC_GROUP_free(ret);
return NULL;
}
@@ -68,12 +75,12 @@ EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a,
meth = EC_GF2m_simple_method();
- ret = EC_GROUP_new(meth);
+ ret = ossl_ec_group_new_ex(ossl_bn_get_libctx(ctx), NULL, meth);
if (ret == NULL)
return NULL;
if (!EC_GROUP_set_curve(ret, p, a, b, ctx)) {
- EC_GROUP_clear_free(ret);
+ EC_GROUP_free(ret);
return NULL;
}
diff --git a/crypto/ec/ec_deprecated.c b/crypto/ec/ec_deprecated.c
new file mode 100644
index 000000000000..765894c32977
--- /dev/null
+++ b/crypto/ec/ec_deprecated.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Suppress deprecation warnings for EC low level implementations that are
+ * kept until removal.
+ */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/ec.h>
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+BIGNUM *EC_POINT_point2bn(const EC_GROUP *group,
+ const EC_POINT *point,
+ point_conversion_form_t form,
+ BIGNUM *ret, BN_CTX *ctx)
+{
+ size_t buf_len = 0;
+ unsigned char *buf;
+
+ buf_len = EC_POINT_point2buf(group, point, form, &buf, ctx);
+
+ if (buf_len == 0)
+ return NULL;
+
+ ret = BN_bin2bn(buf, buf_len, ret);
+
+ OPENSSL_free(buf);
+
+ return ret;
+}
+
+EC_POINT *EC_POINT_bn2point(const EC_GROUP *group,
+ const BIGNUM *bn, EC_POINT *point, BN_CTX *ctx)
+{
+ size_t buf_len = 0;
+ unsigned char *buf;
+ EC_POINT *ret;
+
+ if ((buf_len = BN_num_bytes(bn)) == 0)
+ buf_len = 1;
+ if ((buf = OPENSSL_malloc(buf_len)) == NULL) {
+ ECerr(EC_F_EC_POINT_BN2POINT, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (BN_bn2binpad(bn, buf, buf_len) < 0) {
+ OPENSSL_free(buf);
+ return NULL;
+ }
+
+ if (point == NULL) {
+ if ((ret = EC_POINT_new(group)) == NULL) {
+ OPENSSL_free(buf);
+ return NULL;
+ }
+ } else
+ ret = point;
+
+ if (!EC_POINT_oct2point(group, ret, buf, buf_len, ctx)) {
+ if (ret != point)
+ EC_POINT_clear_free(ret);
+ OPENSSL_free(buf);
+ return NULL;
+ }
+
+ OPENSSL_free(buf);
+ return ret;
+}
+#endif /* OPENSSL_NO_DEPRECATED_3_0 */
diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c
index bfe74226503e..4d6f2a76ad20 100644
--- a/crypto/ec/ec_err.c
+++ b/crypto/ec/ec_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,283 +10,11 @@
#include <openssl/err.h>
#include <openssl/ecerr.h>
+#include "crypto/ecerr.h"
-#ifndef OPENSSL_NO_ERR
+#ifndef OPENSSL_NO_EC
-static const ERR_STRING_DATA EC_str_functs[] = {
- {ERR_PACK(ERR_LIB_EC, EC_F_BN_TO_FELEM, 0), "BN_to_felem"},
- {ERR_PACK(ERR_LIB_EC, EC_F_D2I_ECPARAMETERS, 0), "d2i_ECParameters"},
- {ERR_PACK(ERR_LIB_EC, EC_F_D2I_ECPKPARAMETERS, 0), "d2i_ECPKParameters"},
- {ERR_PACK(ERR_LIB_EC, EC_F_D2I_ECPRIVATEKEY, 0), "d2i_ECPrivateKey"},
- {ERR_PACK(ERR_LIB_EC, EC_F_DO_EC_KEY_PRINT, 0), "do_EC_KEY_print"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECDH_CMS_DECRYPT, 0), "ecdh_cms_decrypt"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECDH_CMS_SET_SHARED_INFO, 0),
- "ecdh_cms_set_shared_info"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECDH_COMPUTE_KEY, 0), "ECDH_compute_key"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECDH_SIMPLE_COMPUTE_KEY, 0),
- "ecdh_simple_compute_key"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_DO_SIGN_EX, 0), "ECDSA_do_sign_ex"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_DO_VERIFY, 0), "ECDSA_do_verify"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_SIGN_EX, 0), "ECDSA_sign_ex"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_SIGN_SETUP, 0), "ECDSA_sign_setup"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_SIG_NEW, 0), "ECDSA_SIG_new"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_VERIFY, 0), "ECDSA_verify"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECD_ITEM_VERIFY, 0), "ecd_item_verify"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PARAM2TYPE, 0), "eckey_param2type"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PARAM_DECODE, 0), "eckey_param_decode"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PRIV_DECODE, 0), "eckey_priv_decode"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PRIV_ENCODE, 0), "eckey_priv_encode"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PUB_DECODE, 0), "eckey_pub_decode"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PUB_ENCODE, 0), "eckey_pub_encode"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_TYPE2PARAM, 0), "eckey_type2param"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECPARAMETERS_PRINT, 0), "ECParameters_print"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECPARAMETERS_PRINT_FP, 0),
- "ECParameters_print_fp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECPKPARAMETERS_PRINT, 0),
- "ECPKParameters_print"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECPKPARAMETERS_PRINT_FP, 0),
- "ECPKParameters_print_fp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_GET_AFFINE, 0),
- "ecp_nistz256_get_affine"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_INV_MOD_ORD, 0),
- "ecp_nistz256_inv_mod_ord"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, 0),
- "ecp_nistz256_mult_precompute"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_POINTS_MUL, 0),
- "ecp_nistz256_points_mul"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_PRE_COMP_NEW, 0),
- "ecp_nistz256_pre_comp_new"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_WINDOWED_MUL, 0),
- "ecp_nistz256_windowed_mul"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECX_KEY_OP, 0), "ecx_key_op"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECX_PRIV_ENCODE, 0), "ecx_priv_encode"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ECX_PUB_ENCODE, 0), "ecx_pub_encode"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_ASN1_GROUP2CURVE, 0), "ec_asn1_group2curve"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_ASN1_GROUP2FIELDID, 0),
- "ec_asn1_group2fieldid"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, 0),
- "ec_GF2m_montgomery_point_multiply"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_FIELD_INV, 0),
- "ec_GF2m_simple_field_inv"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, 0),
- "ec_GF2m_simple_group_check_discriminant"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, 0),
- "ec_GF2m_simple_group_set_curve"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_LADDER_POST, 0),
- "ec_GF2m_simple_ladder_post"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_LADDER_PRE, 0),
- "ec_GF2m_simple_ladder_pre"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_OCT2POINT, 0),
- "ec_GF2m_simple_oct2point"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINT2OCT, 0),
- "ec_GF2m_simple_point2oct"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINTS_MUL, 0),
- "ec_GF2m_simple_points_mul"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, 0),
- "ec_GF2m_simple_point_get_affine_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, 0),
- "ec_GF2m_simple_point_set_affine_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, 0),
- "ec_GF2m_simple_set_compressed_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_DECODE, 0),
- "ec_GFp_mont_field_decode"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_ENCODE, 0),
- "ec_GFp_mont_field_encode"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_INV, 0),
- "ec_GFp_mont_field_inv"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_MUL, 0),
- "ec_GFp_mont_field_mul"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, 0),
- "ec_GFp_mont_field_set_to_one"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_SQR, 0),
- "ec_GFp_mont_field_sqr"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_GROUP_SET_CURVE, 0),
- "ec_GFp_mont_group_set_curve"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE, 0),
- "ec_GFp_nistp224_group_set_curve"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP224_POINTS_MUL, 0),
- "ec_GFp_nistp224_points_mul"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES, 0),
- "ec_GFp_nistp224_point_get_affine_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE, 0),
- "ec_GFp_nistp256_group_set_curve"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP256_POINTS_MUL, 0),
- "ec_GFp_nistp256_points_mul"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES, 0),
- "ec_GFp_nistp256_point_get_affine_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE, 0),
- "ec_GFp_nistp521_group_set_curve"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP521_POINTS_MUL, 0),
- "ec_GFp_nistp521_points_mul"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, 0),
- "ec_GFp_nistp521_point_get_affine_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NIST_FIELD_MUL, 0),
- "ec_GFp_nist_field_mul"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NIST_FIELD_SQR, 0),
- "ec_GFp_nist_field_sqr"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NIST_GROUP_SET_CURVE, 0),
- "ec_GFp_nist_group_set_curve"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, 0),
- "ec_GFp_simple_blind_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_FIELD_INV, 0),
- "ec_GFp_simple_field_inv"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, 0),
- "ec_GFp_simple_group_check_discriminant"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, 0),
- "ec_GFp_simple_group_set_curve"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, 0),
- "ec_GFp_simple_make_affine"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_OCT2POINT, 0),
- "ec_GFp_simple_oct2point"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_POINT2OCT, 0),
- "ec_GFp_simple_point2oct"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, 0),
- "ec_GFp_simple_points_make_affine"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, 0),
- "ec_GFp_simple_point_get_affine_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, 0),
- "ec_GFp_simple_point_set_affine_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, 0),
- "ec_GFp_simple_set_compressed_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_CHECK, 0), "EC_GROUP_check"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_CHECK_DISCRIMINANT, 0),
- "EC_GROUP_check_discriminant"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_COPY, 0), "EC_GROUP_copy"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_CURVE, 0), "EC_GROUP_get_curve"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_CURVE_GF2M, 0),
- "EC_GROUP_get_curve_GF2m"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_CURVE_GFP, 0),
- "EC_GROUP_get_curve_GFp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_DEGREE, 0), "EC_GROUP_get_degree"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_ECPARAMETERS, 0),
- "EC_GROUP_get_ecparameters"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_ECPKPARAMETERS, 0),
- "EC_GROUP_get_ecpkparameters"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS, 0),
- "EC_GROUP_get_pentanomial_basis"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_TRINOMIAL_BASIS, 0),
- "EC_GROUP_get_trinomial_basis"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_NEW, 0), "EC_GROUP_new"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_NEW_BY_CURVE_NAME, 0),
- "EC_GROUP_new_by_curve_name"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_NEW_FROM_DATA, 0),
- "ec_group_new_from_data"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, 0),
- "EC_GROUP_new_from_ecparameters"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, 0),
- "EC_GROUP_new_from_ecpkparameters"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_CURVE, 0), "EC_GROUP_set_curve"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_CURVE_GF2M, 0),
- "EC_GROUP_set_curve_GF2m"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_CURVE_GFP, 0),
- "EC_GROUP_set_curve_GFp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_GENERATOR, 0),
- "EC_GROUP_set_generator"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_SEED, 0), "EC_GROUP_set_seed"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_CHECK_KEY, 0), "EC_KEY_check_key"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_COPY, 0), "EC_KEY_copy"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_GENERATE_KEY, 0), "EC_KEY_generate_key"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_NEW, 0), "EC_KEY_new"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_NEW_METHOD, 0), "EC_KEY_new_method"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_OCT2PRIV, 0), "EC_KEY_oct2priv"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_PRINT, 0), "EC_KEY_print"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_PRINT_FP, 0), "EC_KEY_print_fp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_PRIV2BUF, 0), "EC_KEY_priv2buf"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_PRIV2OCT, 0), "EC_KEY_priv2oct"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, 0),
- "EC_KEY_set_public_key_affine_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SIMPLE_CHECK_KEY, 0),
- "ec_key_simple_check_key"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SIMPLE_OCT2PRIV, 0),
- "ec_key_simple_oct2priv"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SIMPLE_PRIV2OCT, 0),
- "ec_key_simple_priv2oct"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_PKEY_CHECK, 0), "ec_pkey_check"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_PKEY_PARAM_CHECK, 0), "ec_pkey_param_check"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINTS_MAKE_AFFINE, 0),
- "EC_POINTs_make_affine"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINTS_MUL, 0), "EC_POINTs_mul"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_ADD, 0), "EC_POINT_add"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_BN2POINT, 0), "EC_POINT_bn2point"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_CMP, 0), "EC_POINT_cmp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_COPY, 0), "EC_POINT_copy"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_DBL, 0), "EC_POINT_dbl"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_GET_AFFINE_COORDINATES, 0),
- "EC_POINT_get_affine_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, 0),
- "EC_POINT_get_affine_coordinates_GF2m"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, 0),
- "EC_POINT_get_affine_coordinates_GFp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, 0),
- "EC_POINT_get_Jprojective_coordinates_GFp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_INVERT, 0), "EC_POINT_invert"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_IS_AT_INFINITY, 0),
- "EC_POINT_is_at_infinity"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_IS_ON_CURVE, 0),
- "EC_POINT_is_on_curve"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_MAKE_AFFINE, 0),
- "EC_POINT_make_affine"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_NEW, 0), "EC_POINT_new"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_OCT2POINT, 0), "EC_POINT_oct2point"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_POINT2BUF, 0), "EC_POINT_point2buf"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_POINT2OCT, 0), "EC_POINT_point2oct"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_AFFINE_COORDINATES, 0),
- "EC_POINT_set_affine_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, 0),
- "EC_POINT_set_affine_coordinates_GF2m"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, 0),
- "EC_POINT_set_affine_coordinates_GFp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_COMPRESSED_COORDINATES, 0),
- "EC_POINT_set_compressed_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, 0),
- "EC_POINT_set_compressed_coordinates_GF2m"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, 0),
- "EC_POINT_set_compressed_coordinates_GFp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, 0),
- "EC_POINT_set_Jprojective_coordinates_GFp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_TO_INFINITY, 0),
- "EC_POINT_set_to_infinity"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_PRE_COMP_NEW, 0), "ec_pre_comp_new"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_SCALAR_MUL_LADDER, 0),
- "ec_scalar_mul_ladder"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_WNAF_MUL, 0), "ec_wNAF_mul"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_WNAF_PRECOMPUTE_MULT, 0),
- "ec_wNAF_precompute_mult"},
- {ERR_PACK(ERR_LIB_EC, EC_F_I2D_ECPARAMETERS, 0), "i2d_ECParameters"},
- {ERR_PACK(ERR_LIB_EC, EC_F_I2D_ECPKPARAMETERS, 0), "i2d_ECPKParameters"},
- {ERR_PACK(ERR_LIB_EC, EC_F_I2D_ECPRIVATEKEY, 0), "i2d_ECPrivateKey"},
- {ERR_PACK(ERR_LIB_EC, EC_F_I2O_ECPUBLICKEY, 0), "i2o_ECPublicKey"},
- {ERR_PACK(ERR_LIB_EC, EC_F_NISTP224_PRE_COMP_NEW, 0),
- "nistp224_pre_comp_new"},
- {ERR_PACK(ERR_LIB_EC, EC_F_NISTP256_PRE_COMP_NEW, 0),
- "nistp256_pre_comp_new"},
- {ERR_PACK(ERR_LIB_EC, EC_F_NISTP521_PRE_COMP_NEW, 0),
- "nistp521_pre_comp_new"},
- {ERR_PACK(ERR_LIB_EC, EC_F_O2I_ECPUBLICKEY, 0), "o2i_ECPublicKey"},
- {ERR_PACK(ERR_LIB_EC, EC_F_OLD_EC_PRIV_DECODE, 0), "old_ec_priv_decode"},
- {ERR_PACK(ERR_LIB_EC, EC_F_OSSL_ECDH_COMPUTE_KEY, 0),
- "ossl_ecdh_compute_key"},
- {ERR_PACK(ERR_LIB_EC, EC_F_OSSL_ECDSA_SIGN_SIG, 0), "ossl_ecdsa_sign_sig"},
- {ERR_PACK(ERR_LIB_EC, EC_F_OSSL_ECDSA_VERIFY_SIG, 0),
- "ossl_ecdsa_verify_sig"},
- {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECD_CTRL, 0), "pkey_ecd_ctrl"},
- {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECD_DIGESTSIGN, 0), "pkey_ecd_digestsign"},
- {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECD_DIGESTSIGN25519, 0),
- "pkey_ecd_digestsign25519"},
- {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECD_DIGESTSIGN448, 0),
- "pkey_ecd_digestsign448"},
- {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECX_DERIVE, 0), "pkey_ecx_derive"},
- {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_CTRL, 0), "pkey_ec_ctrl"},
- {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_CTRL_STR, 0), "pkey_ec_ctrl_str"},
- {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_DERIVE, 0), "pkey_ec_derive"},
- {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_INIT, 0), "pkey_ec_init"},
- {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_KDF_DERIVE, 0), "pkey_ec_kdf_derive"},
- {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_KEYGEN, 0), "pkey_ec_keygen"},
- {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_PARAMGEN, 0), "pkey_ec_paramgen"},
- {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_SIGN, 0), "pkey_ec_sign"},
- {ERR_PACK(ERR_LIB_EC, EC_F_VALIDATE_ECX_DERIVE, 0), "validate_ecx_derive"},
- {0, NULL}
-};
+# ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA EC_str_reasons[] = {
{ERR_PACK(ERR_LIB_EC, 0, EC_R_ASN1_ERROR), "asn1 error"},
@@ -298,15 +26,19 @@ static const ERR_STRING_DATA EC_str_reasons[] = {
"coordinates out of range"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_CURVE_DOES_NOT_SUPPORT_ECDH),
"curve does not support ecdh"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA),
+ "curve does not support ecdsa"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING),
"curve does not support signing"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_D2I_ECPKPARAMETERS_FAILURE),
- "d2i ecpkparameters failure"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_DECODE_ERROR), "decode error"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_DISCRIMINANT_IS_ZERO),
"discriminant is zero"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_EC_GROUP_NEW_BY_NAME_FAILURE),
"ec group new by name failure"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_EXPLICIT_PARAMS_NOT_SUPPORTED),
+ "explicit params not supported"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_FAILED_MAKING_PUBLIC_KEY),
+ "failed making public key"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_FIELD_TOO_LARGE), "field too large"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_GF2M_NOT_SUPPORTED), "gf2m not supported"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_GROUP2PKPARAMETERS_FAILURE),
@@ -315,7 +47,10 @@ static const ERR_STRING_DATA EC_str_reasons[] = {
"i2d ecpkparameters failure"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INCOMPATIBLE_OBJECTS),
"incompatible objects"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_A), "invalid a"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_ARGUMENT), "invalid argument"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_B), "invalid b"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_COFACTOR), "invalid cofactor"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_COMPRESSED_POINT),
"invalid compressed point"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_COMPRESSION_BIT),
@@ -326,14 +61,20 @@ static const ERR_STRING_DATA EC_str_reasons[] = {
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_ENCODING), "invalid encoding"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_FIELD), "invalid field"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_FORM), "invalid form"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_GENERATOR), "invalid generator"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_GROUP_ORDER), "invalid group order"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_KEY), "invalid key"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_LENGTH), "invalid length"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_NAMED_GROUP_CONVERSION),
+ "invalid named group conversion"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_OUTPUT_LENGTH),
"invalid output length"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_P), "invalid p"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_PEER_KEY), "invalid peer key"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_PENTANOMIAL_BASIS),
"invalid pentanomial basis"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_PRIVATE_KEY), "invalid private key"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_SEED), "invalid seed"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_TRINOMIAL_BASIS),
"invalid trinomial basis"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_KDF_PARAMETER_ERROR), "kdf parameter error"},
@@ -356,8 +97,6 @@ static const ERR_STRING_DATA EC_str_reasons[] = {
{ERR_PACK(ERR_LIB_EC, 0, EC_R_PASSED_NULL_PARAMETER),
"passed null parameter"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_PEER_KEY_ERROR), "peer key error"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_PKPARAMETERS2GROUP_FAILURE),
- "pkparameters2group failure"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_ARITHMETIC_FAILURE),
"point arithmetic failure"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_AT_INFINITY), "point at infinity"},
@@ -381,15 +120,16 @@ static const ERR_STRING_DATA EC_str_reasons[] = {
{0, NULL}
};
-#endif
+# endif
-int ERR_load_EC_strings(void)
+int ossl_err_load_EC_strings(void)
{
-#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(EC_str_functs[0].error) == NULL) {
- ERR_load_strings_const(EC_str_functs);
+# ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(EC_str_reasons[0].error) == NULL)
ERR_load_strings_const(EC_str_reasons);
- }
-#endif
+# endif
return 1;
}
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c
index 63799002bc98..729d338b3379 100644
--- a/crypto/ec/ec_key.c
+++ b/crypto/ec/ec_key.c
@@ -2,31 +2,52 @@
* Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * EC_KEY low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include "internal/cryptlib.h"
#include <string.h>
#include "ec_local.h"
#include "internal/refcount.h"
#include <openssl/err.h>
-#include <openssl/engine.h>
+#ifndef FIPS_MODULE
+# include <openssl/engine.h>
+#endif
+#include <openssl/self_test.h>
+#include "prov/providercommon.h"
#include "crypto/bn.h"
+static int ecdsa_keygen_pairwise_test(EC_KEY *eckey, OSSL_CALLBACK *cb,
+ void *cbarg);
+
+#ifndef FIPS_MODULE
EC_KEY *EC_KEY_new(void)
{
- return EC_KEY_new_method(NULL);
+ return ossl_ec_key_new_method_int(NULL, NULL, NULL);
}
+#endif
-EC_KEY *EC_KEY_new_by_curve_name(int nid)
+EC_KEY *EC_KEY_new_ex(OSSL_LIB_CTX *ctx, const char *propq)
{
- EC_KEY *ret = EC_KEY_new();
+ return ossl_ec_key_new_method_int(ctx, propq, NULL);
+}
+
+EC_KEY *EC_KEY_new_by_curve_name_ex(OSSL_LIB_CTX *ctx, const char *propq,
+ int nid)
+{
+ EC_KEY *ret = EC_KEY_new_ex(ctx, propq);
if (ret == NULL)
return NULL;
- ret->group = EC_GROUP_new_by_curve_name(nid);
+ ret->group = EC_GROUP_new_by_curve_name_ex(ctx, propq, nid);
if (ret->group == NULL) {
EC_KEY_free(ret);
return NULL;
@@ -39,6 +60,13 @@ EC_KEY *EC_KEY_new_by_curve_name(int nid)
return ret;
}
+#ifndef FIPS_MODULE
+EC_KEY *EC_KEY_new_by_curve_name(int nid)
+{
+ return EC_KEY_new_by_curve_name_ex(NULL, NULL, nid);
+}
+#endif
+
void EC_KEY_free(EC_KEY *r)
{
int i;
@@ -55,18 +83,21 @@ void EC_KEY_free(EC_KEY *r)
if (r->meth != NULL && r->meth->finish != NULL)
r->meth->finish(r);
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
ENGINE_finish(r->engine);
#endif
if (r->group && r->group->meth->keyfinish)
r->group->meth->keyfinish(r);
+#ifndef FIPS_MODULE
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data);
+#endif
CRYPTO_THREAD_lock_free(r->lock);
EC_GROUP_free(r->group);
EC_POINT_free(r->pub_key);
BN_clear_free(r->priv_key);
+ OPENSSL_free(r->propq);
OPENSSL_clear_free((void *)r, sizeof(EC_KEY));
}
@@ -74,7 +105,7 @@ void EC_KEY_free(EC_KEY *r)
EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
{
if (dest == NULL || src == NULL) {
- ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (src->meth != dest->meth) {
@@ -82,18 +113,19 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
dest->meth->finish(dest);
if (dest->group && dest->group->meth->keyfinish)
dest->group->meth->keyfinish(dest);
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
if (ENGINE_finish(dest->engine) == 0)
return 0;
dest->engine = NULL;
#endif
}
+ dest->libctx = src->libctx;
/* copy the parameters */
if (src->group != NULL) {
- const EC_METHOD *meth = EC_GROUP_method_of(src->group);
/* clear the old group */
EC_GROUP_free(dest->group);
- dest->group = EC_GROUP_new(meth);
+ dest->group = ossl_ec_group_new_ex(src->libctx, src->propq,
+ src->group->meth);
if (dest->group == NULL)
return NULL;
if (!EC_GROUP_copy(dest->group, src->group))
@@ -129,12 +161,14 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
dest->conv_form = src->conv_form;
dest->version = src->version;
dest->flags = src->flags;
+#ifndef FIPS_MODULE
if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY,
&dest->ex_data, &src->ex_data))
return NULL;
+#endif
if (src->meth != dest->meth) {
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
if (src->engine != NULL && ENGINE_init(src->engine) == 0)
return NULL;
dest->engine = src->engine;
@@ -145,21 +179,14 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
if (src->meth->copy != NULL && src->meth->copy(dest, src) == 0)
return NULL;
+ dest->dirty_cnt++;
+
return dest;
}
EC_KEY *EC_KEY_dup(const EC_KEY *ec_key)
{
- EC_KEY *ret = EC_KEY_new_method(ec_key->engine);
-
- if (ret == NULL)
- return NULL;
-
- if (EC_KEY_copy(ret, ec_key) == NULL) {
- EC_KEY_free(ret);
- return NULL;
- }
- return ret;
+ return ossl_ec_key_dup(ec_key, OSSL_KEYMGMT_SELECT_ALL);
}
int EC_KEY_up_ref(EC_KEY *r)
@@ -182,156 +209,389 @@ ENGINE *EC_KEY_get0_engine(const EC_KEY *eckey)
int EC_KEY_generate_key(EC_KEY *eckey)
{
if (eckey == NULL || eckey->group == NULL) {
- ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
- if (eckey->meth->keygen != NULL)
- return eckey->meth->keygen(eckey);
- ECerr(EC_F_EC_KEY_GENERATE_KEY, EC_R_OPERATION_NOT_SUPPORTED);
+ if (eckey->meth->keygen != NULL) {
+ int ret;
+
+ ret = eckey->meth->keygen(eckey);
+ if (ret == 1)
+ eckey->dirty_cnt++;
+
+ return ret;
+ }
+ ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED);
return 0;
}
int ossl_ec_key_gen(EC_KEY *eckey)
{
- return eckey->group->meth->keygen(eckey);
+ int ret;
+
+ ret = eckey->group->meth->keygen(eckey);
+
+ if (ret == 1)
+ eckey->dirty_cnt++;
+ return ret;
}
-int ec_key_simple_generate_key(EC_KEY *eckey)
+/*
+ * ECC Key generation.
+ * See SP800-56AR3 5.6.1.2.2 "Key Pair Generation by Testing Candidates"
+ *
+ * Params:
+ * libctx A context containing an optional self test callback.
+ * eckey An EC key object that contains domain params. The generated keypair
+ * is stored in this object.
+ * pairwise_test Set to non zero to perform a pairwise test. If the test
+ * fails then the keypair is not generated,
+ * Returns 1 if the keypair was generated or 0 otherwise.
+ */
+static int ec_generate_key(EC_KEY *eckey, int pairwise_test)
{
int ok = 0;
- BN_CTX *ctx = NULL;
BIGNUM *priv_key = NULL;
- const BIGNUM *order = NULL;
+ const BIGNUM *tmp = NULL;
+ BIGNUM *order = NULL;
EC_POINT *pub_key = NULL;
+ const EC_GROUP *group = eckey->group;
+ BN_CTX *ctx = BN_CTX_secure_new_ex(eckey->libctx);
+ int sm2 = EC_KEY_get_flags(eckey) & EC_FLAG_SM2_RANGE ? 1 : 0;
- if ((ctx = BN_CTX_new()) == NULL)
+ if (ctx == NULL)
goto err;
if (eckey->priv_key == NULL) {
- priv_key = BN_new();
+ priv_key = BN_secure_new();
if (priv_key == NULL)
goto err;
} else
priv_key = eckey->priv_key;
- order = EC_GROUP_get0_order(eckey->group);
- if (order == NULL)
+ /*
+ * Steps (1-2): Check domain parameters and security strength.
+ * These steps must be done by the user. This would need to be
+ * stated in the security policy.
+ */
+
+ tmp = EC_GROUP_get0_order(group);
+ if (tmp == NULL)
goto err;
+ /*
+ * Steps (3-7): priv_key = DRBG_RAND(order_n_bits) (range [1, n-1]).
+ * Although this is slightly different from the standard, it is effectively
+ * equivalent as it gives an unbiased result ranging from 1..n-1. It is also
+ * faster as the standard needs to retry more often. Also doing
+ * 1 + rand[0..n-2] would effect the way that tests feed dummy entropy into
+ * rand so the simpler backward compatible method has been used here.
+ */
+
+ /* range of SM2 private key is [1, n-1) */
+ if (sm2) {
+ order = BN_new();
+ if (order == NULL || !BN_sub(order, tmp, BN_value_one()))
+ goto err;
+ } else {
+ order = BN_dup(tmp);
+ if (order == NULL)
+ goto err;
+ }
+
do
- if (!BN_priv_rand_range(priv_key, order))
+ if (!BN_priv_rand_range_ex(priv_key, order, 0, ctx))
goto err;
while (BN_is_zero(priv_key)) ;
if (eckey->pub_key == NULL) {
- pub_key = EC_POINT_new(eckey->group);
+ pub_key = EC_POINT_new(group);
if (pub_key == NULL)
goto err;
} else
pub_key = eckey->pub_key;
- if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx))
+ /* Step (8) : pub_key = priv_key * G (where G is a point on the curve) */
+ if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
goto err;
eckey->priv_key = priv_key;
eckey->pub_key = pub_key;
+ priv_key = NULL;
+ pub_key = NULL;
+
+ eckey->dirty_cnt++;
+
+#ifdef FIPS_MODULE
+ pairwise_test = 1;
+#endif /* FIPS_MODULE */
ok = 1;
+ if (pairwise_test) {
+ OSSL_CALLBACK *cb = NULL;
+ void *cbarg = NULL;
- err:
- if (eckey->pub_key == NULL)
- EC_POINT_free(pub_key);
- if (eckey->priv_key != priv_key)
- BN_free(priv_key);
+ OSSL_SELF_TEST_get_callback(eckey->libctx, &cb, &cbarg);
+ ok = ecdsa_keygen_pairwise_test(eckey, cb, cbarg);
+ }
+err:
+ /* Step (9): If there is an error return an invalid keypair. */
+ if (!ok) {
+ ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
+ BN_clear(eckey->priv_key);
+ if (eckey->pub_key != NULL)
+ EC_POINT_set_to_infinity(group, eckey->pub_key);
+ }
+
+ EC_POINT_free(pub_key);
+ BN_clear_free(priv_key);
BN_CTX_free(ctx);
+ BN_free(order);
return ok;
}
-int ec_key_simple_generate_public_key(EC_KEY *eckey)
+int ossl_ec_key_simple_generate_key(EC_KEY *eckey)
{
- return EC_POINT_mul(eckey->group, eckey->pub_key, eckey->priv_key, NULL,
- NULL, NULL);
+ return ec_generate_key(eckey, 0);
+}
+
+int ossl_ec_key_simple_generate_public_key(EC_KEY *eckey)
+{
+ int ret;
+ BN_CTX *ctx = BN_CTX_new_ex(eckey->libctx);
+
+ if (ctx == NULL)
+ return 0;
+
+ /*
+ * See SP800-56AR3 5.6.1.2.2: Step (8)
+ * pub_key = priv_key * G (where G is a point on the curve)
+ */
+ ret = EC_POINT_mul(eckey->group, eckey->pub_key, eckey->priv_key, NULL,
+ NULL, ctx);
+
+ BN_CTX_free(ctx);
+ if (ret == 1)
+ eckey->dirty_cnt++;
+
+ return ret;
}
int EC_KEY_check_key(const EC_KEY *eckey)
{
if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) {
- ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (eckey->group->meth->keycheck == NULL) {
- ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return eckey->group->meth->keycheck(eckey);
}
-int ec_key_simple_check_key(const EC_KEY *eckey)
+/*
+ * Check the range of the EC public key.
+ * See SP800-56A R3 Section 5.6.2.3.3 (Part 2)
+ * i.e.
+ * - If q = odd prime p: Verify that xQ and yQ are integers in the
+ * interval[0, p - 1], OR
+ * - If q = 2m: Verify that xQ and yQ are bit strings of length m bits.
+ * Returns 1 if the public key has a valid range, otherwise it returns 0.
+ */
+static int ec_key_public_range_check(BN_CTX *ctx, const EC_KEY *key)
{
- int ok = 0;
- BN_CTX *ctx = NULL;
- const BIGNUM *order = NULL;
- EC_POINT *point = NULL;
+ int ret = 0;
+ BIGNUM *x, *y;
+ BN_CTX_start(ctx);
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+ if (y == NULL)
+ goto err;
+
+ if (!EC_POINT_get_affine_coordinates(key->group, key->pub_key, x, y, ctx))
+ goto err;
+
+ if (EC_GROUP_get_field_type(key->group) == NID_X9_62_prime_field) {
+ if (BN_is_negative(x)
+ || BN_cmp(x, key->group->field) >= 0
+ || BN_is_negative(y)
+ || BN_cmp(y, key->group->field) >= 0) {
+ goto err;
+ }
+ } else {
+ int m = EC_GROUP_get_degree(key->group);
+ if (BN_num_bits(x) > m || BN_num_bits(y) > m) {
+ goto err;
+ }
+ }
+ ret = 1;
+err:
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+/*
+ * ECC Partial Public-Key Validation as specified in SP800-56A R3
+ * Section 5.6.2.3.4 ECC Partial Public-Key Validation Routine.
+ */
+int ossl_ec_key_public_check_quick(const EC_KEY *eckey, BN_CTX *ctx)
+{
if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) {
- ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
+ /* 5.6.2.3.3 (Step 1): Q != infinity */
if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) {
- ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_AT_INFINITY);
- goto err;
+ ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY);
+ return 0;
}
- if ((ctx = BN_CTX_new()) == NULL)
- goto err;
- if ((point = EC_POINT_new(eckey->group)) == NULL)
- goto err;
+ /* 5.6.2.3.3 (Step 2) Test if the public key is in range */
+ if (!ec_key_public_range_check(ctx, eckey)) {
+ ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE);
+ return 0;
+ }
- /* testing whether the pub_key is on the elliptic curve */
+ /* 5.6.2.3.3 (Step 3) is the pub_key on the elliptic curve */
if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) {
- ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE);
- goto err;
+ ERR_raise(ERR_LIB_EC, EC_R_POINT_IS_NOT_ON_CURVE);
+ return 0;
}
- /* testing whether pub_key * order is the point at infinity */
+ return 1;
+}
+
+/*
+ * ECC Key validation as specified in SP800-56A R3.
+ * Section 5.6.2.3.3 ECC Full Public-Key Validation Routine.
+ */
+int ossl_ec_key_public_check(const EC_KEY *eckey, BN_CTX *ctx)
+{
+ int ret = 0;
+ EC_POINT *point = NULL;
+ const BIGNUM *order = NULL;
+
+ if (!ossl_ec_key_public_check_quick(eckey, ctx))
+ return 0;
+
+ point = EC_POINT_new(eckey->group);
+ if (point == NULL)
+ return 0;
+
order = eckey->group->order;
if (BN_is_zero(order)) {
- ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_GROUP_ORDER);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
goto err;
}
+ /* 5.6.2.3.3 (Step 4) : pub_key * order is the point at infinity. */
if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) {
- ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if (!EC_POINT_is_at_infinity(eckey->group, point)) {
- ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER);
+ ERR_raise(ERR_LIB_EC, EC_R_WRONG_ORDER);
goto err;
}
- /*
- * in case the priv_key is present : check if generator * priv_key ==
- * pub_key
- */
+ ret = 1;
+err:
+ EC_POINT_free(point);
+ return ret;
+}
+
+/*
+ * ECC Key validation as specified in SP800-56A R3.
+ * Section 5.6.2.1.2 Owner Assurance of Private-Key Validity
+ * The private key is in the range [1, order-1]
+ */
+int ossl_ec_key_private_check(const EC_KEY *eckey)
+{
+ if (eckey == NULL || eckey->group == NULL || eckey->priv_key == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (BN_cmp(eckey->priv_key, BN_value_one()) < 0
+ || BN_cmp(eckey->priv_key, eckey->group->order) >= 0) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * ECC Key validation as specified in SP800-56A R3.
+ * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency (b)
+ * Check if generator * priv_key = pub_key
+ */
+int ossl_ec_key_pairwise_check(const EC_KEY *eckey, BN_CTX *ctx)
+{
+ int ret = 0;
+ EC_POINT *point = NULL;
+
+ if (eckey == NULL
+ || eckey->group == NULL
+ || eckey->pub_key == NULL
+ || eckey->priv_key == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ point = EC_POINT_new(eckey->group);
+ if (point == NULL)
+ goto err;
+
+
+ if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, NULL, ctx)) {
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
+ goto err;
+ }
+ if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
+ goto err;
+ }
+ ret = 1;
+err:
+ EC_POINT_free(point);
+ return ret;
+}
+
+
+/*
+ * ECC Key validation as specified in SP800-56A R3.
+ * Section 5.6.2.3.3 ECC Full Public-Key Validation
+ * Section 5.6.2.1.2 Owner Assurance of Private-Key Validity
+ * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency
+ * NOTES:
+ * Before calling this method in fips mode, there should be an assurance that
+ * an approved elliptic-curve group is used.
+ * Returns 1 if the key is valid, otherwise it returns 0.
+ */
+int ossl_ec_key_simple_check_key(const EC_KEY *eckey)
+{
+ int ok = 0;
+ BN_CTX *ctx = NULL;
+
+ if (eckey == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL)
+ return 0;
+
+ if (!ossl_ec_key_public_check(eckey, ctx))
+ goto err;
+
if (eckey->priv_key != NULL) {
- if (BN_cmp(eckey->priv_key, order) >= 0) {
- ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER);
- goto err;
- }
- if (!EC_POINT_mul(eckey->group, point, eckey->priv_key,
- NULL, NULL, ctx)) {
- ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB);
+ if (!ossl_ec_key_private_check(eckey)
+ || !ossl_ec_key_pairwise_check(eckey, ctx))
goto err;
- }
- if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) {
- ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY);
- goto err;
- }
}
ok = 1;
- err:
+err:
BN_CTX_free(ctx);
- EC_POINT_free(point);
return ok;
}
@@ -344,11 +604,10 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
int ok = 0;
if (key == NULL || key->group == NULL || x == NULL || y == NULL) {
- ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
- ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
- ctx = BN_CTX_new();
+ ctx = BN_CTX_new_ex(key->libctx);
if (ctx == NULL)
return 0;
@@ -369,17 +628,15 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
goto err;
/*
- * Check if retrieved coordinates match originals and are less than field
- * order: if not values are out of range.
+ * Check if retrieved coordinates match originals. The range check is done
+ * inside EC_KEY_check_key().
*/
- if (BN_cmp(x, tx) || BN_cmp(y, ty)
- || (BN_cmp(x, key->group->field) >= 0)
- || (BN_cmp(y, key->group->field) >= 0)) {
- ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
- EC_R_COORDINATES_OUT_OF_RANGE);
+ if (BN_cmp(x, tx) || BN_cmp(y, ty)) {
+ ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE);
goto err;
}
+ /* EC_KEY_set_public_key updates dirty_cnt */
if (!EC_KEY_set_public_key(key, point))
goto err;
@@ -396,6 +653,22 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
}
+OSSL_LIB_CTX *ossl_ec_key_get_libctx(const EC_KEY *key)
+{
+ return key->libctx;
+}
+
+const char *ossl_ec_key_get0_propq(const EC_KEY *key)
+{
+ return key->propq;
+}
+
+void ossl_ec_key_set0_libctx(EC_KEY *key, OSSL_LIB_CTX *libctx)
+{
+ key->libctx = libctx;
+ /* Do we need to propagate this to the group? */
+}
+
const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key)
{
return key->group;
@@ -407,6 +680,10 @@ int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group)
return 0;
EC_GROUP_free(key->group);
key->group = EC_GROUP_dup(group);
+ if (key->group != NULL && EC_GROUP_get_curve_name(key->group) == NID_sm2)
+ EC_KEY_set_flags(key, EC_FLAG_SM2_RANGE);
+
+ key->dirty_cnt++;
return (key->group == NULL) ? 0 : 1;
}
@@ -505,6 +782,7 @@ int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key)
BN_clear_free(key->priv_key);
key->priv_key = tmp_key;
+ key->dirty_cnt++;
return 1;
}
@@ -521,6 +799,7 @@ int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key)
return 0;
EC_POINT_free(key->pub_key);
key->pub_key = EC_POINT_dup(pub_key, key->group);
+ key->dirty_cnt++;
return (key->pub_key == NULL) ? 0 : 1;
}
@@ -552,12 +831,14 @@ void EC_KEY_set_asn1_flag(EC_KEY *key, int flag)
EC_GROUP_set_asn1_flag(key->group, flag);
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx)
{
if (key->group == NULL)
return 0;
return EC_GROUP_precompute_mult(key->group, ctx);
}
+#endif
int EC_KEY_get_flags(const EC_KEY *key)
{
@@ -567,11 +848,13 @@ int EC_KEY_get_flags(const EC_KEY *key)
void EC_KEY_set_flags(EC_KEY *key, int flags)
{
key->flags |= flags;
+ key->dirty_cnt++;
}
void EC_KEY_clear_flags(EC_KEY *key, int flags)
{
key->flags &= ~flags;
+ key->dirty_cnt++;
}
int EC_KEY_decoded_from_explicit_params(const EC_KEY *key)
@@ -600,6 +883,7 @@ int EC_KEY_oct2key(EC_KEY *key, const unsigned char *buf, size_t len,
return 0;
if (EC_POINT_oct2point(key->group, key->pub_key, buf, len, ctx) == 0)
return 0;
+ key->dirty_cnt++;
/*
* Save the point conversion form.
* For non-custom curves the first octet of the buffer (excluding
@@ -618,15 +902,15 @@ size_t EC_KEY_priv2oct(const EC_KEY *eckey,
if (eckey->group == NULL || eckey->group->meth == NULL)
return 0;
if (eckey->group->meth->priv2oct == NULL) {
- ECerr(EC_F_EC_KEY_PRIV2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return eckey->group->meth->priv2oct(eckey, buf, len);
}
-size_t ec_key_simple_priv2oct(const EC_KEY *eckey,
- unsigned char *buf, size_t len)
+size_t ossl_ec_key_simple_priv2oct(const EC_KEY *eckey,
+ unsigned char *buf, size_t len)
{
size_t buf_len;
@@ -641,7 +925,7 @@ size_t ec_key_simple_priv2oct(const EC_KEY *eckey,
/* Octetstring may need leading zeros if BN is to short */
if (BN_bn2binpad(eckey->priv_key, buf, buf_len) == -1) {
- ECerr(EC_F_EC_KEY_SIMPLE_PRIV2OCT, EC_R_BUFFER_TOO_SMALL);
+ ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
return 0;
}
@@ -650,27 +934,34 @@ size_t ec_key_simple_priv2oct(const EC_KEY *eckey,
int EC_KEY_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len)
{
+ int ret;
+
if (eckey->group == NULL || eckey->group->meth == NULL)
return 0;
if (eckey->group->meth->oct2priv == NULL) {
- ECerr(EC_F_EC_KEY_OCT2PRIV, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
- return eckey->group->meth->oct2priv(eckey, buf, len);
+ ret = eckey->group->meth->oct2priv(eckey, buf, len);
+ if (ret == 1)
+ eckey->dirty_cnt++;
+ return ret;
}
-int ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len)
+int ossl_ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf,
+ size_t len)
{
if (eckey->priv_key == NULL)
eckey->priv_key = BN_secure_new();
if (eckey->priv_key == NULL) {
- ECerr(EC_F_EC_KEY_SIMPLE_OCT2PRIV, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
if (BN_bin2bn(buf, len, eckey->priv_key) == NULL) {
- ECerr(EC_F_EC_KEY_SIMPLE_OCT2PRIV, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
return 0;
}
+ eckey->dirty_cnt++;
return 1;
}
@@ -683,7 +974,7 @@ size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf)
if (len == 0)
return 0;
if ((buf = OPENSSL_malloc(len)) == NULL) {
- ECerr(EC_F_EC_KEY_PRIV2BUF, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
len = EC_KEY_priv2oct(eckey, buf, len);
@@ -702,3 +993,45 @@ int EC_KEY_can_sign(const EC_KEY *eckey)
return 0;
return 1;
}
+
+/*
+ * FIPS 140-2 IG 9.9 AS09.33
+ * Perform a sign/verify operation.
+ *
+ * NOTE: When generating keys for key-agreement schemes - FIPS 140-2 IG 9.9
+ * states that no additional pairwise tests are required (apart from the tests
+ * specified in SP800-56A) when generating keys. Hence pairwise ECDH tests are
+ * omitted here.
+ */
+static int ecdsa_keygen_pairwise_test(EC_KEY *eckey, OSSL_CALLBACK *cb,
+ void *cbarg)
+{
+ int ret = 0;
+ unsigned char dgst[16] = {0};
+ int dgst_len = (int)sizeof(dgst);
+ ECDSA_SIG *sig = NULL;
+ OSSL_SELF_TEST *st = NULL;
+
+ st = OSSL_SELF_TEST_new(cb, cbarg);
+ if (st == NULL)
+ return 0;
+
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
+ OSSL_SELF_TEST_DESC_PCT_ECDSA);
+
+ sig = ECDSA_do_sign(dgst, dgst_len, eckey);
+ if (sig == NULL)
+ goto err;
+
+ OSSL_SELF_TEST_oncorrupt_byte(st, dgst);
+
+ if (ECDSA_do_verify(dgst, dgst_len, sig, eckey) != 1)
+ goto err;
+
+ ret = 1;
+err:
+ OSSL_SELF_TEST_onend(st, ret);
+ OSSL_SELF_TEST_free(st);
+ ECDSA_SIG_free(sig);
+ return ret;
+}
diff --git a/crypto/ec/ec_kmeth.c b/crypto/ec/ec_kmeth.c
index 53a4a9295201..8c011635cb42 100644
--- a/crypto/ec/ec_kmeth.c
+++ b/crypto/ec/ec_kmeth.c
@@ -1,15 +1,23 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDH and ECDSA low level APIs are deprecated for public use, but still ok
+ * for internal use.
+ */
+#include "internal/deprecated.h"
+
#include <string.h>
#include <openssl/ec.h>
-#include <openssl/engine.h>
+#ifndef FIPS_MODULE
+# include <openssl/engine.h>
+#endif
#include <openssl/err.h>
#include "ec_local.h"
@@ -59,7 +67,7 @@ int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth)
if (finish != NULL)
finish(key);
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
ENGINE_finish(key->engine);
key->engine = NULL;
#endif
@@ -70,28 +78,37 @@ int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth)
return 1;
}
-EC_KEY *EC_KEY_new_method(ENGINE *engine)
+EC_KEY *ossl_ec_key_new_method_int(OSSL_LIB_CTX *libctx, const char *propq,
+ ENGINE *engine)
{
EC_KEY *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return NULL;
}
+ ret->libctx = libctx;
+ if (propq != NULL) {
+ ret->propq = OPENSSL_strdup(propq);
+ if (ret->propq == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
ret->references = 1;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
- ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_MALLOC_FAILURE);
- OPENSSL_free(ret);
- return NULL;
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
}
ret->meth = EC_KEY_get_default_method();
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
if (engine != NULL) {
if (!ENGINE_init(engine)) {
- ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_ENGINE_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_ENGINE_LIB);
goto err;
}
ret->engine = engine;
@@ -100,7 +117,7 @@ EC_KEY *EC_KEY_new_method(ENGINE *engine)
if (ret->engine != NULL) {
ret->meth = ENGINE_get_EC(ret->engine);
if (ret->meth == NULL) {
- ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_ENGINE_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_ENGINE_LIB);
goto err;
}
}
@@ -109,12 +126,15 @@ EC_KEY *EC_KEY_new_method(ENGINE *engine)
ret->version = 1;
ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
+/* No ex_data inside the FIPS provider */
+#ifndef FIPS_MODULE
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EC_KEY, ret, &ret->ex_data)) {
goto err;
}
+#endif
if (ret->meth->init != NULL && ret->meth->init(ret) == 0) {
- ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_INIT_FAIL);
+ ERR_raise(ERR_LIB_EC, ERR_R_INIT_FAIL);
goto err;
}
return ret;
@@ -124,6 +144,13 @@ EC_KEY *EC_KEY_new_method(ENGINE *engine)
return NULL;
}
+#ifndef FIPS_MODULE
+EC_KEY *EC_KEY_new_method(ENGINE *engine)
+{
+ return ossl_ec_key_new_method_int(NULL, NULL, engine);
+}
+#endif
+
int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
const EC_KEY *eckey,
void *(*KDF) (const void *in, size_t inlen, void *out,
@@ -132,11 +159,11 @@ int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
unsigned char *sec = NULL;
size_t seclen;
if (eckey->meth->compute_key == NULL) {
- ECerr(EC_F_ECDH_COMPUTE_KEY, EC_R_OPERATION_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED);
return 0;
}
if (outlen > INT_MAX) {
- ECerr(EC_F_ECDH_COMPUTE_KEY, EC_R_INVALID_OUTPUT_LENGTH);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_OUTPUT_LENGTH);
return 0;
}
if (!eckey->meth->compute_key(&sec, &seclen, pub_key, eckey))
diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c
index 08db89fceeb5..b1696d93bd6d 100644
--- a/crypto/ec/ec_lib.c
+++ b/crypto/ec/ec_lib.c
@@ -1,41 +1,58 @@
/*
- * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <string.h>
+/*
+ * EC_GROUP low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+#include <string.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
#include <openssl/err.h>
#include <openssl/opensslv.h>
-
+#include "crypto/ec.h"
+#include "internal/nelem.h"
#include "ec_local.h"
/* functions for EC_GROUP objects */
-EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
+EC_GROUP *ossl_ec_group_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
+ const EC_METHOD *meth)
{
EC_GROUP *ret;
if (meth == NULL) {
- ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL);
+ ERR_raise(ERR_LIB_EC, EC_R_SLOT_FULL);
return NULL;
}
if (meth->group_init == 0) {
- ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return NULL;
}
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return NULL;
}
+ ret->libctx = libctx;
+ if (propq != NULL) {
+ ret->propq = OPENSSL_strdup(propq);
+ if (ret->propq == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
ret->meth = meth;
if ((ret->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
ret->order = BN_new();
@@ -45,7 +62,7 @@ EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
if (ret->cofactor == NULL)
goto err;
}
- ret->asn1_flag = OPENSSL_EC_NAMED_CURVE;
+ ret->asn1_flag = OPENSSL_EC_EXPLICIT_CURVE;
ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
if (!meth->group_init(ret))
goto err;
@@ -54,10 +71,20 @@ EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
err:
BN_free(ret->order);
BN_free(ret->cofactor);
+ OPENSSL_free(ret->propq);
OPENSSL_free(ret);
return NULL;
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef FIPS_MODULE
+EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
+{
+ return ossl_ec_group_new_ex(NULL, NULL, meth);
+}
+# endif
+#endif
+
void EC_pre_comp_free(EC_GROUP *group)
{
switch (group->pre_comp_type) {
@@ -105,9 +132,11 @@ void EC_GROUP_free(EC_GROUP *group)
BN_free(group->order);
BN_free(group->cofactor);
OPENSSL_free(group->seed);
+ OPENSSL_free(group->propq);
OPENSSL_free(group);
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
void EC_GROUP_clear_free(EC_GROUP *group)
{
if (!group)
@@ -126,20 +155,22 @@ void EC_GROUP_clear_free(EC_GROUP *group)
OPENSSL_clear_free(group->seed, group->seed_len);
OPENSSL_clear_free(group, sizeof(*group));
}
+#endif
int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
{
if (dest->meth->group_copy == 0) {
- ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (dest->meth != src->meth) {
- ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (dest == src)
return 1;
+ dest->libctx = src->libctx;
dest->curve_name = src->curve_name;
/* Copy precomputed */
@@ -216,7 +247,7 @@ int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
if (src->seed) {
OPENSSL_free(dest->seed);
if ((dest->seed = OPENSSL_malloc(src->seed_len)) == NULL) {
- ECerr(EC_F_EC_GROUP_COPY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!memcpy(dest->seed, src->seed, src->seed_len))
@@ -239,7 +270,7 @@ EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
if (a == NULL)
return NULL;
- if ((t = EC_GROUP_new(a->meth)) == NULL)
+ if ((t = ossl_ec_group_new_ex(a->libctx, a->propq, a->meth)) == NULL)
return NULL;
if (!EC_GROUP_copy(t, a))
goto err;
@@ -254,6 +285,7 @@ EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
return t;
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
{
return group->meth;
@@ -263,6 +295,7 @@ int EC_METHOD_get_field_type(const EC_METHOD *meth)
{
return meth->field_type;
}
+#endif
static int ec_precompute_mont_data(EC_GROUP *);
@@ -295,7 +328,7 @@ static int ec_guess_cofactor(EC_GROUP *group) {
return 1;
}
- if ((ctx = BN_CTX_new()) == NULL)
+ if ((ctx = BN_CTX_new_ex(group->libctx)) == NULL)
return 0;
BN_CTX_start(ctx);
@@ -331,14 +364,14 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
const BIGNUM *order, const BIGNUM *cofactor)
{
if (generator == NULL) {
- ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
/* require group->field >= 1 */
if (group->field == NULL || BN_is_zero(group->field)
|| BN_is_negative(group->field)) {
- ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_INVALID_FIELD);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
return 0;
}
@@ -349,7 +382,7 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
*/
if (order == NULL || BN_is_zero(order) || BN_is_negative(order)
|| BN_num_bits(order) > BN_num_bits(group->field) + 1) {
- ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_INVALID_GROUP_ORDER);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
return 0;
}
@@ -359,7 +392,7 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
* So accept cofactor == NULL or cofactor >= 0.
*/
if (cofactor != NULL && BN_is_negative(cofactor)) {
- ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_UNKNOWN_COFACTOR);
+ ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_COFACTOR);
return 0;
}
@@ -447,6 +480,10 @@ const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group)
void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
{
group->curve_name = nid;
+ group->asn1_flag =
+ (nid != NID_undef)
+ ? OPENSSL_EC_NAMED_CURVE
+ : OPENSSL_EC_EXPLICIT_CURVE;
}
int EC_GROUP_get_curve_name(const EC_GROUP *group)
@@ -454,6 +491,16 @@ int EC_GROUP_get_curve_name(const EC_GROUP *group)
return group->curve_name;
}
+const BIGNUM *EC_GROUP_get0_field(const EC_GROUP *group)
+{
+ return group->field;
+}
+
+int EC_GROUP_get_field_type(const EC_GROUP *group)
+{
+ return group->meth->field_type;
+}
+
void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
{
group->asn1_flag = flag;
@@ -486,7 +533,7 @@ size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
return 1;
if ((group->seed = OPENSSL_malloc(len)) == NULL) {
- ECerr(EC_F_EC_GROUP_SET_SEED, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(group->seed, p, len);
@@ -509,7 +556,7 @@ int EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx)
{
if (group->meth->group_set_curve == 0) {
- ECerr(EC_F_EC_GROUP_SET_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->group_set_curve(group, p, a, b, ctx);
@@ -519,13 +566,13 @@ int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b,
BN_CTX *ctx)
{
if (group->meth->group_get_curve == NULL) {
- ECerr(EC_F_EC_GROUP_GET_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->group_get_curve(group, p, a, b, ctx);
}
-#if OPENSSL_API_COMPAT < 0x10200000L
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx)
{
@@ -556,7 +603,7 @@ int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
int EC_GROUP_get_degree(const EC_GROUP *group)
{
if (group->meth->group_get_degree == 0) {
- ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->group_get_degree(group);
@@ -565,8 +612,7 @@ int EC_GROUP_get_degree(const EC_GROUP *group)
int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
{
if (group->meth->group_check_discriminant == 0) {
- ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->group_check_discriminant(group, ctx);
@@ -576,11 +622,12 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
{
int r = 0;
BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
+#ifndef FIPS_MODULE
BN_CTX *ctx_new = NULL;
+#endif
/* compare the field types */
- if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
- EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
+ if (EC_GROUP_get_field_type(a) != EC_GROUP_get_field_type(b))
return 1;
/* compare the curve name (if present in both) */
if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
@@ -589,8 +636,10 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
if (a->meth->flags & EC_FLAGS_CUSTOM_CURVE)
return 0;
+#ifndef FIPS_MODULE
if (ctx == NULL)
ctx_new = ctx = BN_CTX_new();
+#endif
if (ctx == NULL)
return -1;
@@ -603,7 +652,9 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
b3 = BN_CTX_get(ctx);
if (b3 == NULL) {
BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(ctx_new);
+#endif
return -1;
}
@@ -615,33 +666,47 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
!b->meth->group_get_curve(b, b1, b2, b3, ctx))
r = 1;
- if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
+ /* return 1 if the curve parameters are different */
+ if (r || BN_cmp(a1, b1) != 0 || BN_cmp(a2, b2) != 0 || BN_cmp(a3, b3) != 0)
r = 1;
/* XXX EC_POINT_cmp() assumes that the methods are equal */
+ /* return 1 if the generators are different */
if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
- EC_GROUP_get0_generator(b), ctx))
+ EC_GROUP_get0_generator(b), ctx) != 0)
r = 1;
if (!r) {
const BIGNUM *ao, *bo, *ac, *bc;
- /* compare the order and cofactor */
+ /* compare the orders */
ao = EC_GROUP_get0_order(a);
bo = EC_GROUP_get0_order(b);
- ac = EC_GROUP_get0_cofactor(a);
- bc = EC_GROUP_get0_cofactor(b);
if (ao == NULL || bo == NULL) {
- BN_CTX_end(ctx);
- BN_CTX_free(ctx_new);
- return -1;
+ /* return an error if either order is NULL */
+ r = -1;
+ goto end;
}
- if (BN_cmp(ao, bo) || BN_cmp(ac, bc))
+ if (BN_cmp(ao, bo) != 0) {
+ /* return 1 if orders are different */
r = 1;
+ goto end;
+ }
+ /*
+ * It gets here if the curve parameters and generator matched.
+ * Now check the optional cofactors (if both are present).
+ */
+ ac = EC_GROUP_get0_cofactor(a);
+ bc = EC_GROUP_get0_cofactor(b);
+ /* Returns 1 (mismatch) if both cofactors are specified and different */
+ if (!BN_is_zero(ac) && !BN_is_zero(bc) && BN_cmp(ac, bc) != 0)
+ r = 1;
+ /* Returns 0 if the parameters matched */
}
-
+end:
BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(ctx_new);
-
+#endif
return r;
}
@@ -652,17 +717,17 @@ EC_POINT *EC_POINT_new(const EC_GROUP *group)
EC_POINT *ret;
if (group == NULL) {
- ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (group->meth->point_init == NULL) {
- ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return NULL;
}
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -679,7 +744,7 @@ EC_POINT *EC_POINT_new(const EC_GROUP *group)
void EC_POINT_free(EC_POINT *point)
{
- if (!point)
+ if (point == NULL)
return;
if (point->meth->point_finish != 0)
@@ -689,7 +754,7 @@ void EC_POINT_free(EC_POINT *point)
void EC_POINT_clear_free(EC_POINT *point)
{
- if (!point)
+ if (point == NULL)
return;
if (point->meth->point_clear_finish != 0)
@@ -702,14 +767,14 @@ void EC_POINT_clear_free(EC_POINT *point)
int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
{
if (dest->meth->point_copy == 0) {
- ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (dest->meth != src->meth
|| (dest->curve_name != src->curve_name
- && dest->curve_name != 0
- && src->curve_name != 0)) {
- ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
+ && dest->curve_name != 0
+ && src->curve_name != 0)) {
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (dest == src)
@@ -736,42 +801,42 @@ EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
return t;
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
{
return point->meth;
}
+#endif
int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
{
if (group->meth->point_set_to_infinity == 0) {
- ECerr(EC_F_EC_POINT_SET_TO_INFINITY,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (group->meth != point->meth) {
- ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->point_set_to_infinity(group, point);
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
EC_POINT *point, const BIGNUM *x,
const BIGNUM *y, const BIGNUM *z,
BN_CTX *ctx)
{
- if (group->meth->point_set_Jprojective_coordinates_GFp == 0) {
- ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ if (group->meth->field_type != NID_X9_62_prime_field) {
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
- ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
- EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
- return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x,
- y, z, ctx);
+ return ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, point,
+ x, y, z, ctx);
}
int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
@@ -779,44 +844,42 @@ int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
BIGNUM *y, BIGNUM *z,
BN_CTX *ctx)
{
- if (group->meth->point_get_Jprojective_coordinates_GFp == 0) {
- ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ if (group->meth->field_type != NID_X9_62_prime_field) {
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
- ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
- EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
- return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x,
- y, z, ctx);
+ return ossl_ec_GFp_simple_get_Jprojective_coordinates_GFp(group, point,
+ x, y, z, ctx);
}
+#endif
int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
const BIGNUM *x, const BIGNUM *y,
BN_CTX *ctx)
{
if (group->meth->point_set_affine_coordinates == NULL) {
- ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
- ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES, EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx))
return 0;
if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
- ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES, EC_R_POINT_IS_NOT_ON_CURVE);
+ ERR_raise(ERR_LIB_EC, EC_R_POINT_IS_NOT_ON_CURVE);
return 0;
}
return 1;
}
-#if OPENSSL_API_COMPAT < 0x10200000L
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
EC_POINT *point, const BIGNUM *x,
const BIGNUM *y, BN_CTX *ctx)
@@ -839,22 +902,21 @@ int EC_POINT_get_affine_coordinates(const EC_GROUP *group,
BN_CTX *ctx)
{
if (group->meth->point_get_affine_coordinates == NULL) {
- ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
- ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES, EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (EC_POINT_is_at_infinity(group, point)) {
- ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
+ ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY);
return 0;
}
return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
}
-#if OPENSSL_API_COMPAT < 0x10200000L
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
const EC_POINT *point, BIGNUM *x,
BIGNUM *y, BN_CTX *ctx)
@@ -876,12 +938,12 @@ int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
const EC_POINT *b, BN_CTX *ctx)
{
if (group->meth->add == 0) {
- ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group)
|| !ec_point_is_compat(b, group)) {
- ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->add(group, r, a, b, ctx);
@@ -891,11 +953,11 @@ int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
BN_CTX *ctx)
{
if (group->meth->dbl == 0) {
- ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group)) {
- ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->dbl(group, r, a, ctx);
@@ -904,11 +966,11 @@ int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
{
if (group->meth->invert == 0) {
- ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(a, group)) {
- ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->invert(group, a, ctx);
@@ -917,12 +979,11 @@ int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
{
if (group->meth->is_at_infinity == 0) {
- ECerr(EC_F_EC_POINT_IS_AT_INFINITY,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
- ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->is_at_infinity(group, point);
@@ -939,11 +1000,11 @@ int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
BN_CTX *ctx)
{
if (group->meth->is_on_curve == 0) {
- ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
- ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->is_on_curve(group, point, ctx);
@@ -953,24 +1014,25 @@ int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
BN_CTX *ctx)
{
if (group->meth->point_cmp == 0) {
- ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return -1;
}
if (!ec_point_is_compat(a, group) || !ec_point_is_compat(b, group)) {
- ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return -1;
}
return group->meth->point_cmp(group, a, b, ctx);
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
{
if (group->meth->make_affine == 0) {
- ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
- ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->make_affine(group, point, ctx);
@@ -982,17 +1044,18 @@ int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
size_t i;
if (group->meth->points_make_affine == 0) {
- ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
for (i = 0; i < num; i++) {
if (!ec_point_is_compat(points[i], group)) {
- ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
}
return group->meth->points_make_affine(group, num, points, ctx);
}
+#endif
/*
* Functions for point multiplication. If group->meth->mul is 0, we use the
@@ -1000,16 +1063,19 @@ int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
* methods.
*/
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
size_t num, const EC_POINT *points[],
const BIGNUM *scalars[], BN_CTX *ctx)
{
int ret = 0;
size_t i = 0;
+#ifndef FIPS_MODULE
BN_CTX *new_ctx = NULL;
+#endif
if (!ec_point_is_compat(r, group)) {
- ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
@@ -1018,13 +1084,17 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
for (i = 0; i < num; i++) {
if (!ec_point_is_compat(points[i], group)) {
- ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
}
- if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL) {
- ECerr(EC_F_EC_POINTS_MUL, ERR_R_INTERNAL_ERROR);
+#ifndef FIPS_MODULE
+ if (ctx == NULL)
+ ctx = new_ctx = BN_CTX_secure_new();
+#endif
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -1032,33 +1102,61 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
ret = group->meth->mul(group, r, scalar, num, points, scalars, ctx);
else
/* use default */
- ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
+ ret = ossl_ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
return ret;
}
+#endif
int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
{
- /* just a convenient interface to EC_POINTs_mul() */
+ int ret = 0;
+ size_t num;
+#ifndef FIPS_MODULE
+ BN_CTX *new_ctx = NULL;
+#endif
+
+ if (!ec_point_is_compat(r, group)
+ || (point != NULL && !ec_point_is_compat(point, group))) {
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
- const EC_POINT *points[1];
- const BIGNUM *scalars[1];
+ if (g_scalar == NULL && p_scalar == NULL)
+ return EC_POINT_set_to_infinity(group, r);
- points[0] = point;
- scalars[0] = p_scalar;
+#ifndef FIPS_MODULE
+ if (ctx == NULL)
+ ctx = new_ctx = BN_CTX_secure_new();
+#endif
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ num = (point != NULL && p_scalar != NULL) ? 1 : 0;
+ if (group->meth->mul != NULL)
+ ret = group->meth->mul(group, r, g_scalar, num, &point, &p_scalar, ctx);
+ else
+ /* use default */
+ ret = ossl_ec_wNAF_mul(group, r, g_scalar, num, &point, &p_scalar, ctx);
- return EC_POINTs_mul(group, r, g_scalar,
- (point != NULL
- && p_scalar != NULL), points, scalars, ctx);
+#ifndef FIPS_MODULE
+ BN_CTX_free(new_ctx);
+#endif
+ return ret;
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
{
if (group->meth->mul == 0)
/* use default */
- return ec_wNAF_precompute_mult(group, ctx);
+ return ossl_ec_wNAF_precompute_mult(group, ctx);
if (group->meth->precompute_mult != 0)
return group->meth->precompute_mult(group, ctx);
@@ -1070,7 +1168,7 @@ int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
{
if (group->meth->mul == 0)
/* use default */
- return ec_wNAF_have_precompute_mult(group);
+ return ossl_ec_wNAF_have_precompute_mult(group);
if (group->meth->have_precompute_mult != 0)
return group->meth->have_precompute_mult(group);
@@ -1078,6 +1176,7 @@ int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
return 0; /* cannot tell whether precomputation has
* been performed */
}
+#endif
/*
* ec_precompute_mont_data sets |group->mont_data| from |group->order| and
@@ -1085,7 +1184,7 @@ int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
*/
static int ec_precompute_mont_data(EC_GROUP *group)
{
- BN_CTX *ctx = BN_CTX_new();
+ BN_CTX *ctx = BN_CTX_new_ex(group->libctx);
int ret = 0;
BN_MONT_CTX_free(group->mont_data);
@@ -1112,6 +1211,7 @@ static int ec_precompute_mont_data(EC_GROUP *group)
return ret;
}
+#ifndef FIPS_MODULE
int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg)
{
return CRYPTO_set_ex_data(&key->ex_data, idx, arg);
@@ -1121,8 +1221,9 @@ void *EC_KEY_get_ex_data(const EC_KEY *key, int idx)
{
return CRYPTO_get_ex_data(&key->ex_data, idx);
}
+#endif
-int ec_group_simple_order_bits(const EC_GROUP *group)
+int ossl_ec_group_simple_order_bits(const EC_GROUP *group)
{
if (group->order == NULL)
return 0;
@@ -1133,13 +1234,19 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
const BIGNUM *x, BN_CTX *ctx)
{
BIGNUM *e = NULL;
- BN_CTX *new_ctx = NULL;
int ret = 0;
+#ifndef FIPS_MODULE
+ BN_CTX *new_ctx = NULL;
+#endif
if (group->mont_data == NULL)
return 0;
- if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL)
+#ifndef FIPS_MODULE
+ if (ctx == NULL)
+ ctx = new_ctx = BN_CTX_secure_new();
+#endif
+ if (ctx == NULL)
return 0;
BN_CTX_start(ctx);
@@ -1165,7 +1272,9 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
err:
BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
return ret;
}
@@ -1182,8 +1291,8 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
* EC_METHODs must implement their own field_inverse_mod_ord for
* other functionality.
*/
-int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
- const BIGNUM *x, BN_CTX *ctx)
+int ossl_ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
+ const BIGNUM *x, BN_CTX *ctx)
{
if (group->meth->field_inverse_mod_ord != NULL)
return group->meth->field_inverse_mod_ord(group, res, x, ctx);
@@ -1201,10 +1310,451 @@ int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
* This wrapper returns 1 in case the underlying EC_METHOD does not
* support coordinate blinding.
*/
-int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx)
+int ossl_ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
+ BN_CTX *ctx)
{
if (group->meth->blind_coordinates == NULL)
return 1; /* ignore if not implemented */
return group->meth->blind_coordinates(group, p, ctx);
}
+
+int EC_GROUP_get_basis_type(const EC_GROUP *group)
+{
+ int i;
+
+ if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field)
+ /* everything else is currently not supported */
+ return 0;
+
+ /* Find the last non-zero element of group->poly[] */
+ for (i = 0;
+ i < (int)OSSL_NELEM(group->poly) && group->poly[i] != 0;
+ i++)
+ continue;
+
+ if (i == 4)
+ return NID_X9_62_ppBasis;
+ else if (i == 2)
+ return NID_X9_62_tpBasis;
+ else
+ /* everything else is currently not supported */
+ return 0;
+}
+
+#ifndef OPENSSL_NO_EC2M
+int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k)
+{
+ if (group == NULL)
+ return 0;
+
+ if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field
+ || !((group->poly[0] != 0) && (group->poly[1] != 0)
+ && (group->poly[2] == 0))) {
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ if (k)
+ *k = group->poly[1];
+
+ return 1;
+}
+
+int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,
+ unsigned int *k2, unsigned int *k3)
+{
+ if (group == NULL)
+ return 0;
+
+ if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field
+ || !((group->poly[0] != 0) && (group->poly[1] != 0)
+ && (group->poly[2] != 0) && (group->poly[3] != 0)
+ && (group->poly[4] == 0))) {
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ if (k1)
+ *k1 = group->poly[3];
+ if (k2)
+ *k2 = group->poly[2];
+ if (k3)
+ *k3 = group->poly[1];
+
+ return 1;
+}
+#endif
+
+#ifndef FIPS_MODULE
+/*
+ * Check if the explicit parameters group matches any built-in curves.
+ *
+ * We create a copy of the group just built, so that we can remove optional
+ * fields for the lookup: we do this to avoid the possibility that one of
+ * the optional parameters is used to force the library into using a less
+ * performant and less secure EC_METHOD instead of the specialized one.
+ * In any case, `seed` is not really used in any computation, while a
+ * cofactor different from the one in the built-in table is just
+ * mathematically wrong anyway and should not be used.
+ */
+static EC_GROUP *ec_group_explicit_to_named(const EC_GROUP *group,
+ OSSL_LIB_CTX *libctx,
+ const char *propq,
+ BN_CTX *ctx)
+{
+ EC_GROUP *ret_group = NULL, *dup = NULL;
+ int curve_name_nid;
+
+ const EC_POINT *point = EC_GROUP_get0_generator(group);
+ const BIGNUM *order = EC_GROUP_get0_order(group);
+ int no_seed = (EC_GROUP_get0_seed(group) == NULL);
+
+ if ((dup = EC_GROUP_dup(group)) == NULL
+ || EC_GROUP_set_seed(dup, NULL, 0) != 1
+ || !EC_GROUP_set_generator(dup, point, order, NULL))
+ goto err;
+ if ((curve_name_nid = ossl_ec_curve_nid_from_params(dup, ctx)) != NID_undef) {
+ /*
+ * The input explicit parameters successfully matched one of the
+ * built-in curves: often for built-in curves we have specialized
+ * methods with better performance and hardening.
+ *
+ * In this case we replace the `EC_GROUP` created through explicit
+ * parameters with one created from a named group.
+ */
+
+# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
+ /*
+ * NID_wap_wsg_idm_ecid_wtls12 and NID_secp224r1 are both aliases for
+ * the same curve, we prefer the SECP nid when matching explicit
+ * parameters as that is associated with a specialized EC_METHOD.
+ */
+ if (curve_name_nid == NID_wap_wsg_idm_ecid_wtls12)
+ curve_name_nid = NID_secp224r1;
+# endif /* !def(OPENSSL_NO_EC_NISTP_64_GCC_128) */
+
+ ret_group = EC_GROUP_new_by_curve_name_ex(libctx, propq, curve_name_nid);
+ if (ret_group == NULL)
+ goto err;
+
+ /*
+ * Set the flag so that EC_GROUPs created from explicit parameters are
+ * serialized using explicit parameters by default.
+ */
+ EC_GROUP_set_asn1_flag(ret_group, OPENSSL_EC_EXPLICIT_CURVE);
+
+ /*
+ * If the input params do not contain the optional seed field we make
+ * sure it is not added to the returned group.
+ *
+ * The seed field is not really used inside libcrypto anyway, and
+ * adding it to parsed explicit parameter keys would alter their DER
+ * encoding output (because of the extra field) which could impact
+ * applications fingerprinting keys by their DER encoding.
+ */
+ if (no_seed) {
+ if (EC_GROUP_set_seed(ret_group, NULL, 0) != 1)
+ goto err;
+ }
+ } else {
+ ret_group = (EC_GROUP *)group;
+ }
+ EC_GROUP_free(dup);
+ return ret_group;
+err:
+ EC_GROUP_free(dup);
+ EC_GROUP_free(ret_group);
+ return NULL;
+}
+#endif /* FIPS_MODULE */
+
+static EC_GROUP *group_new_from_name(const OSSL_PARAM *p,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ int ok = 0, nid;
+ const char *curve_name = NULL;
+
+ switch (p->data_type) {
+ case OSSL_PARAM_UTF8_STRING:
+ /* The OSSL_PARAM functions have no support for this */
+ curve_name = p->data;
+ ok = (curve_name != NULL);
+ break;
+ case OSSL_PARAM_UTF8_PTR:
+ ok = OSSL_PARAM_get_utf8_ptr(p, &curve_name);
+ break;
+ }
+
+ if (ok) {
+ nid = ossl_ec_curve_name2nid(curve_name);
+ if (nid == NID_undef) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE);
+ return NULL;
+ } else {
+ return EC_GROUP_new_by_curve_name_ex(libctx, propq, nid);
+ }
+ }
+ return NULL;
+}
+
+/* These parameters can be set directly into an EC_GROUP */
+int ossl_ec_group_set_params(EC_GROUP *group, const OSSL_PARAM params[])
+{
+ int encoding_flag = -1, format = -1;
+ const OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT);
+ if (p != NULL) {
+ if (!ossl_ec_pt_format_param2id(p, &format)) {
+ ECerr(0, EC_R_INVALID_FORM);
+ return 0;
+ }
+ EC_GROUP_set_point_conversion_form(group, format);
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ENCODING);
+ if (p != NULL) {
+ if (!ossl_ec_encoding_param2id(p, &encoding_flag)) {
+ ECerr(0, EC_R_INVALID_FORM);
+ return 0;
+ }
+ EC_GROUP_set_asn1_flag(group, encoding_flag);
+ }
+ /* Optional seed */
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED);
+ if (p != NULL) {
+ /* The seed is allowed to be NULL */
+ if (p->data_type != OSSL_PARAM_OCTET_STRING
+ || !EC_GROUP_set_seed(group, p->data, p->data_size)) {
+ ECerr(0, EC_R_INVALID_SEED);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[],
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ const OSSL_PARAM *ptmp;
+ EC_GROUP *group = NULL;
+
+#ifndef FIPS_MODULE
+ const OSSL_PARAM *pa, *pb;
+ int ok = 0;
+ EC_GROUP *named_group = NULL;
+ BIGNUM *p = NULL, *a = NULL, *b = NULL, *order = NULL, *cofactor = NULL;
+ EC_POINT *point = NULL;
+ int field_bits = 0;
+ int is_prime_field = 1;
+ BN_CTX *bnctx = NULL;
+ const unsigned char *buf = NULL;
+ int encoding_flag = -1;
+#endif
+
+ /* This is the simple named group case */
+ ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
+ if (ptmp != NULL) {
+ int decoded = 0;
+
+ if ((group = group_new_from_name(ptmp, libctx, propq)) == NULL)
+ return NULL;
+ if (!ossl_ec_group_set_params(group, params)) {
+ EC_GROUP_free(group);
+ return NULL;
+ }
+
+ ptmp = OSSL_PARAM_locate_const(params,
+ OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS);
+ if (ptmp != NULL && !OSSL_PARAM_get_int(ptmp, &decoded)) {
+ ERR_raise(ERR_LIB_EC, EC_R_WRONG_CURVE_PARAMETERS);
+ EC_GROUP_free(group);
+ return NULL;
+ }
+ group->decoded_from_explicit_params = decoded > 0;
+ return group;
+ }
+#ifdef FIPS_MODULE
+ ERR_raise(ERR_LIB_EC, EC_R_EXPLICIT_PARAMS_NOT_SUPPORTED);
+ return NULL;
+#else
+ /* If it gets here then we are trying explicit parameters */
+ bnctx = BN_CTX_new_ex(libctx);
+ if (bnctx == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ BN_CTX_start(bnctx);
+
+ p = BN_CTX_get(bnctx);
+ a = BN_CTX_get(bnctx);
+ b = BN_CTX_get(bnctx);
+ order = BN_CTX_get(bnctx);
+ if (order == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE);
+ if (ptmp == NULL || ptmp->data_type != OSSL_PARAM_UTF8_STRING) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
+ goto err;
+ }
+ if (OPENSSL_strcasecmp(ptmp->data, SN_X9_62_prime_field) == 0) {
+ is_prime_field = 1;
+ } else if (OPENSSL_strcasecmp(ptmp->data,
+ SN_X9_62_characteristic_two_field) == 0) {
+ is_prime_field = 0;
+ } else {
+ /* Invalid field */
+ ERR_raise(ERR_LIB_EC, EC_R_UNSUPPORTED_FIELD);
+ goto err;
+ }
+
+ pa = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_A);
+ if (!OSSL_PARAM_get_BN(pa, &a)) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_A);
+ goto err;
+ }
+ pb = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_B);
+ if (!OSSL_PARAM_get_BN(pb, &b)) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_B);
+ goto err;
+ }
+
+ /* extract the prime number or irreducible polynomial */
+ ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_P);
+ if (!OSSL_PARAM_get_BN(ptmp, &p)) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_P);
+ goto err;
+ }
+
+ if (is_prime_field) {
+ if (BN_is_negative(p) || BN_is_zero(p)) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_P);
+ goto err;
+ }
+ field_bits = BN_num_bits(p);
+ if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
+ ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE);
+ goto err;
+ }
+
+ /* create the EC_GROUP structure */
+ group = EC_GROUP_new_curve_GFp(p, a, b, bnctx);
+ } else {
+# ifdef OPENSSL_NO_EC2M
+ ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
+ goto err;
+# else
+ /* create the EC_GROUP structure */
+ group = EC_GROUP_new_curve_GF2m(p, a, b, NULL);
+ if (group != NULL) {
+ field_bits = EC_GROUP_get_degree(group);
+ if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
+ ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE);
+ goto err;
+ }
+ }
+# endif /* OPENSSL_NO_EC2M */
+ }
+
+ if (group == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ /* Optional seed */
+ ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED);
+ if (ptmp != NULL) {
+ if (ptmp->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_SEED);
+ goto err;
+ }
+ if (!EC_GROUP_set_seed(group, ptmp->data, ptmp->data_size))
+ goto err;
+ }
+
+ /* generator base point */
+ ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_GENERATOR);
+ if (ptmp == NULL
+ || ptmp->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
+ goto err;
+ }
+ buf = (const unsigned char *)(ptmp->data);
+ if ((point = EC_POINT_new(group)) == NULL)
+ goto err;
+ EC_GROUP_set_point_conversion_form(group,
+ (point_conversion_form_t)buf[0] & ~0x01);
+ if (!EC_POINT_oct2point(group, point, buf, ptmp->data_size, bnctx)) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
+ goto err;
+ }
+
+ /* order */
+ ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ORDER);
+ if (!OSSL_PARAM_get_BN(ptmp, &order)
+ || (BN_is_negative(order) || BN_is_zero(order))
+ || (BN_num_bits(order) > (int)field_bits + 1)) { /* Hasse bound */
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
+ goto err;
+ }
+
+ /* Optional cofactor */
+ ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_COFACTOR);
+ if (ptmp != NULL) {
+ cofactor = BN_CTX_get(bnctx);
+ if (cofactor == NULL || !OSSL_PARAM_get_BN(ptmp, &cofactor)) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_COFACTOR);
+ goto err;
+ }
+ }
+
+ /* set the generator, order and cofactor (if present) */
+ if (!EC_GROUP_set_generator(group, point, order, cofactor)) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
+ goto err;
+ }
+
+ named_group = ec_group_explicit_to_named(group, libctx, propq, bnctx);
+ if (named_group == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_NAMED_GROUP_CONVERSION);
+ goto err;
+ }
+ if (named_group == group) {
+ /*
+ * If we did not find a named group then the encoding should be explicit
+ * if it was specified
+ */
+ ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ENCODING);
+ if (ptmp != NULL
+ && !ossl_ec_encoding_param2id(ptmp, &encoding_flag)) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
+ goto err;
+ }
+ if (encoding_flag == OPENSSL_EC_NAMED_CURVE) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
+ goto err;
+ }
+ EC_GROUP_set_asn1_flag(group, OPENSSL_EC_EXPLICIT_CURVE);
+ } else {
+ EC_GROUP_free(group);
+ group = named_group;
+ }
+ /* We've imported the group from explicit parameters, set it so. */
+ group->decoded_from_explicit_params = 1;
+ ok = 1;
+ err:
+ if (!ok) {
+ EC_GROUP_free(group);
+ group = NULL;
+ }
+ EC_POINT_free(point);
+ BN_CTX_end(bnctx);
+ BN_CTX_free(bnctx);
+
+ return group;
+#endif /* FIPS_MODULE */
+}
diff --git a/crypto/ec/ec_local.h b/crypto/ec/ec_local.h
index 64725a9c92f4..f34e06aea89a 100644
--- a/crypto/ec/ec_local.h
+++ b/crypto/ec/ec_local.h
@@ -1,8 +1,8 @@
/*
- * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -31,6 +31,10 @@
/* Curve does not support signing operations */
#define EC_FLAGS_NO_SIGN 0x4
+#ifdef OPENSSL_NO_DEPRECATED_3_0
+typedef struct ec_method_st EC_METHOD;
+#endif
+
/*
* Structure details are not part of the exported interface, so all this may
* change in future versions.
@@ -76,14 +80,6 @@ struct ec_method_st {
* EC_POINT_set_compressed_coordinates:
*/
int (*point_set_to_infinity) (const EC_GROUP *, EC_POINT *);
- int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
- EC_POINT *, const BIGNUM *x,
- const BIGNUM *y,
- const BIGNUM *z, BN_CTX *);
- int (*point_get_Jprojective_coordinates_GFp) (const EC_GROUP *,
- const EC_POINT *, BIGNUM *x,
- BIGNUM *y, BIGNUM *z,
- BN_CTX *);
int (*point_set_affine_coordinates) (const EC_GROUP *, EC_POINT *,
const BIGNUM *x, const BIGNUM *y,
BN_CTX *);
@@ -179,6 +175,14 @@ struct ec_method_st {
/* custom ECDH operation */
int (*ecdh_compute_key)(unsigned char **pout, size_t *poutlen,
const EC_POINT *pub_key, const EC_KEY *ecdh);
+ /* custom ECDSA */
+ int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinvp,
+ BIGNUM **rp);
+ ECDSA_SIG *(*ecdsa_sign_sig)(const unsigned char *dgst, int dgstlen,
+ const BIGNUM *kinv, const BIGNUM *r,
+ EC_KEY *eckey);
+ int (*ecdsa_verify_sig)(const unsigned char *dgst, int dgstlen,
+ const ECDSA_SIG *sig, EC_KEY *eckey);
/* Inverse modulo order */
int (*field_inverse_mod_ord)(const EC_GROUP *, BIGNUM *r,
const BIGNUM *x, BN_CTX *);
@@ -270,6 +274,9 @@ struct ec_group_st {
NISTZ256_PRE_COMP *nistz256;
EC_PRE_COMP *ec;
} pre_comp;
+
+ OSSL_LIB_CTX *libctx;
+ char *propq;
};
#define SETPRECOMP(g, type, pre) \
@@ -288,8 +295,15 @@ struct ec_key_st {
point_conversion_form_t conv_form;
CRYPTO_REF_COUNT references;
int flags;
+#ifndef FIPS_MODULE
CRYPTO_EX_DATA ex_data;
+#endif
CRYPTO_RWLOCK *lock;
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+
+ /* Provider data */
+ size_t dirty_cnt; /* If any key material changes, increment this */
};
struct ec_point_st {
@@ -311,13 +325,10 @@ struct ec_point_st {
static ossl_inline int ec_point_is_compat(const EC_POINT *point,
const EC_GROUP *group)
{
- if (group->meth != point->meth
- || (group->curve_name != 0
- && point->curve_name != 0
- && group->curve_name != point->curve_name))
- return 0;
-
- return 1;
+ return group->meth == point->meth
+ && (group->curve_name == 0
+ || point->curve_name == 0
+ || group->curve_name == point->curve_name);
}
NISTP224_PRE_COMP *EC_nistp224_pre_comp_dup(NISTP224_PRE_COMP *);
@@ -338,249 +349,264 @@ void EC_ec_pre_comp_free(EC_PRE_COMP *);
* method functions in ec_mult.c (ec_lib.c uses these as defaults if
* group->method->mul is 0)
*/
-int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
- size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
- BN_CTX *);
-int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *);
-int ec_wNAF_have_precompute_mult(const EC_GROUP *group);
+int ossl_ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
+ size_t num, const EC_POINT *points[],
+ const BIGNUM *scalars[], BN_CTX *);
+int ossl_ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *);
+int ossl_ec_wNAF_have_precompute_mult(const EC_GROUP *group);
/* method functions in ecp_smpl.c */
-int ec_GFp_simple_group_init(EC_GROUP *);
-void ec_GFp_simple_group_finish(EC_GROUP *);
-void ec_GFp_simple_group_clear_finish(EC_GROUP *);
-int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *);
-int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p,
- const BIGNUM *a, const BIGNUM *b, BN_CTX *);
-int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a,
- BIGNUM *b, BN_CTX *);
-int ec_GFp_simple_group_get_degree(const EC_GROUP *);
-int ec_GFp_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);
-int ec_GFp_simple_point_init(EC_POINT *);
-void ec_GFp_simple_point_finish(EC_POINT *);
-void ec_GFp_simple_point_clear_finish(EC_POINT *);
-int ec_GFp_simple_point_copy(EC_POINT *, const EC_POINT *);
-int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *);
-int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *,
- EC_POINT *, const BIGNUM *x,
- const BIGNUM *y,
- const BIGNUM *z, BN_CTX *);
-int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *,
- const EC_POINT *, BIGNUM *x,
- BIGNUM *y, BIGNUM *z,
+int ossl_ec_GFp_simple_group_init(EC_GROUP *);
+void ossl_ec_GFp_simple_group_finish(EC_GROUP *);
+void ossl_ec_GFp_simple_group_clear_finish(EC_GROUP *);
+int ossl_ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *);
+int ossl_ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p,
+ const BIGNUM *a, const BIGNUM *b,
+ BN_CTX *);
+int ossl_ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a,
+ BIGNUM *b, BN_CTX *);
+int ossl_ec_GFp_simple_group_get_degree(const EC_GROUP *);
+int ossl_ec_GFp_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);
+int ossl_ec_GFp_simple_point_init(EC_POINT *);
+void ossl_ec_GFp_simple_point_finish(EC_POINT *);
+void ossl_ec_GFp_simple_point_clear_finish(EC_POINT *);
+int ossl_ec_GFp_simple_point_copy(EC_POINT *, const EC_POINT *);
+int ossl_ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *);
+int ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *,
+ EC_POINT *,
+ const BIGNUM *x,
+ const BIGNUM *y,
+ const BIGNUM *z,
+ BN_CTX *);
+int ossl_ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *,
+ const EC_POINT *,
+ BIGNUM *x,
+ BIGNUM *y, BIGNUM *z,
+ BN_CTX *);
+int ossl_ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,
+ const BIGNUM *x,
+ const BIGNUM *y, BN_CTX *);
+int ossl_ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *,
+ const EC_POINT *, BIGNUM *x,
+ BIGNUM *y, BN_CTX *);
+int ossl_ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,
+ const BIGNUM *x, int y_bit,
BN_CTX *);
-int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,
- const BIGNUM *x,
- const BIGNUM *y, BN_CTX *);
-int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *,
- const EC_POINT *, BIGNUM *x,
- BIGNUM *y, BN_CTX *);
-int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,
- const BIGNUM *x, int y_bit,
- BN_CTX *);
-size_t ec_GFp_simple_point2oct(const EC_GROUP *, const EC_POINT *,
- point_conversion_form_t form,
- unsigned char *buf, size_t len, BN_CTX *);
-int ec_GFp_simple_oct2point(const EC_GROUP *, EC_POINT *,
- const unsigned char *buf, size_t len, BN_CTX *);
-int ec_GFp_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,
- const EC_POINT *b, BN_CTX *);
-int ec_GFp_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,
- BN_CTX *);
-int ec_GFp_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);
-int ec_GFp_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *);
-int ec_GFp_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);
-int ec_GFp_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b,
- BN_CTX *);
-int ec_GFp_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
-int ec_GFp_simple_points_make_affine(const EC_GROUP *, size_t num,
- EC_POINT *[], BN_CTX *);
-int ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
- const BIGNUM *b, BN_CTX *);
-int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
- BN_CTX *);
-int ec_GFp_simple_field_inv(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
- BN_CTX *);
-int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
- BN_CTX *ctx);
-int ec_GFp_simple_ladder_pre(const EC_GROUP *group,
- EC_POINT *r, EC_POINT *s,
- EC_POINT *p, BN_CTX *ctx);
-int ec_GFp_simple_ladder_step(const EC_GROUP *group,
- EC_POINT *r, EC_POINT *s,
- EC_POINT *p, BN_CTX *ctx);
-int ec_GFp_simple_ladder_post(const EC_GROUP *group,
- EC_POINT *r, EC_POINT *s,
- EC_POINT *p, BN_CTX *ctx);
+size_t ossl_ec_GFp_simple_point2oct(const EC_GROUP *, const EC_POINT *,
+ point_conversion_form_t form,
+ unsigned char *buf, size_t len, BN_CTX *);
+int ossl_ec_GFp_simple_oct2point(const EC_GROUP *, EC_POINT *,
+ const unsigned char *buf, size_t len, BN_CTX *);
+int ossl_ec_GFp_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,
+ const EC_POINT *b, BN_CTX *);
+int ossl_ec_GFp_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,
+ BN_CTX *);
+int ossl_ec_GFp_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);
+int ossl_ec_GFp_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *);
+int ossl_ec_GFp_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);
+int ossl_ec_GFp_simple_cmp(const EC_GROUP *, const EC_POINT *a,
+ const EC_POINT *b, BN_CTX *);
+int ossl_ec_GFp_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
+int ossl_ec_GFp_simple_points_make_affine(const EC_GROUP *, size_t num,
+ EC_POINT *[], BN_CTX *);
+int ossl_ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *);
+int ossl_ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *);
+int ossl_ec_GFp_simple_field_inv(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *);
+int ossl_ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
+ BN_CTX *ctx);
+int ossl_ec_GFp_simple_ladder_pre(const EC_GROUP *group,
+ EC_POINT *r, EC_POINT *s,
+ EC_POINT *p, BN_CTX *ctx);
+int ossl_ec_GFp_simple_ladder_step(const EC_GROUP *group,
+ EC_POINT *r, EC_POINT *s,
+ EC_POINT *p, BN_CTX *ctx);
+int ossl_ec_GFp_simple_ladder_post(const EC_GROUP *group,
+ EC_POINT *r, EC_POINT *s,
+ EC_POINT *p, BN_CTX *ctx);
/* method functions in ecp_mont.c */
-int ec_GFp_mont_group_init(EC_GROUP *);
-int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
- const BIGNUM *b, BN_CTX *);
-void ec_GFp_mont_group_finish(EC_GROUP *);
-void ec_GFp_mont_group_clear_finish(EC_GROUP *);
-int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *);
-int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
- const BIGNUM *b, BN_CTX *);
-int ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
- BN_CTX *);
-int ec_GFp_mont_field_inv(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
- BN_CTX *);
-int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
- BN_CTX *);
-int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
- BN_CTX *);
-int ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *);
+int ossl_ec_GFp_mont_group_init(EC_GROUP *);
+int ossl_ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p,
+ const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *);
+void ossl_ec_GFp_mont_group_finish(EC_GROUP *);
+void ossl_ec_GFp_mont_group_clear_finish(EC_GROUP *);
+int ossl_ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *);
+int ossl_ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *);
+int ossl_ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *);
+int ossl_ec_GFp_mont_field_inv(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *);
+int ossl_ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *);
+int ossl_ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *);
+int ossl_ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *);
/* method functions in ecp_nist.c */
-int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src);
-int ec_GFp_nist_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
- const BIGNUM *b, BN_CTX *);
-int ec_GFp_nist_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
- const BIGNUM *b, BN_CTX *);
-int ec_GFp_nist_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
- BN_CTX *);
+int ossl_ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src);
+int ossl_ec_GFp_nist_group_set_curve(EC_GROUP *, const BIGNUM *p,
+ const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+int ossl_ec_GFp_nist_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *);
+int ossl_ec_GFp_nist_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *);
/* method functions in ec2_smpl.c */
-int ec_GF2m_simple_group_init(EC_GROUP *);
-void ec_GF2m_simple_group_finish(EC_GROUP *);
-void ec_GF2m_simple_group_clear_finish(EC_GROUP *);
-int ec_GF2m_simple_group_copy(EC_GROUP *, const EC_GROUP *);
-int ec_GF2m_simple_group_set_curve(EC_GROUP *, const BIGNUM *p,
- const BIGNUM *a, const BIGNUM *b,
- BN_CTX *);
-int ec_GF2m_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a,
- BIGNUM *b, BN_CTX *);
-int ec_GF2m_simple_group_get_degree(const EC_GROUP *);
-int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);
-int ec_GF2m_simple_point_init(EC_POINT *);
-void ec_GF2m_simple_point_finish(EC_POINT *);
-void ec_GF2m_simple_point_clear_finish(EC_POINT *);
-int ec_GF2m_simple_point_copy(EC_POINT *, const EC_POINT *);
-int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *);
-int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,
- const BIGNUM *x,
- const BIGNUM *y, BN_CTX *);
-int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *,
- const EC_POINT *, BIGNUM *x,
- BIGNUM *y, BN_CTX *);
-int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,
- const BIGNUM *x, int y_bit,
- BN_CTX *);
-size_t ec_GF2m_simple_point2oct(const EC_GROUP *, const EC_POINT *,
- point_conversion_form_t form,
- unsigned char *buf, size_t len, BN_CTX *);
-int ec_GF2m_simple_oct2point(const EC_GROUP *, EC_POINT *,
- const unsigned char *buf, size_t len, BN_CTX *);
-int ec_GF2m_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,
- const EC_POINT *b, BN_CTX *);
-int ec_GF2m_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,
- BN_CTX *);
-int ec_GF2m_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);
-int ec_GF2m_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *);
-int ec_GF2m_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);
-int ec_GF2m_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b,
- BN_CTX *);
-int ec_GF2m_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
-int ec_GF2m_simple_points_make_affine(const EC_GROUP *, size_t num,
- EC_POINT *[], BN_CTX *);
-int ec_GF2m_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
- const BIGNUM *b, BN_CTX *);
-int ec_GF2m_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
- BN_CTX *);
-int ec_GF2m_simple_field_div(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
- const BIGNUM *b, BN_CTX *);
+int ossl_ec_GF2m_simple_group_init(EC_GROUP *);
+void ossl_ec_GF2m_simple_group_finish(EC_GROUP *);
+void ossl_ec_GF2m_simple_group_clear_finish(EC_GROUP *);
+int ossl_ec_GF2m_simple_group_copy(EC_GROUP *, const EC_GROUP *);
+int ossl_ec_GF2m_simple_group_set_curve(EC_GROUP *, const BIGNUM *p,
+ const BIGNUM *a, const BIGNUM *b,
+ BN_CTX *);
+int ossl_ec_GF2m_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a,
+ BIGNUM *b, BN_CTX *);
+int ossl_ec_GF2m_simple_group_get_degree(const EC_GROUP *);
+int ossl_ec_GF2m_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);
+int ossl_ec_GF2m_simple_point_init(EC_POINT *);
+void ossl_ec_GF2m_simple_point_finish(EC_POINT *);
+void ossl_ec_GF2m_simple_point_clear_finish(EC_POINT *);
+int ossl_ec_GF2m_simple_point_copy(EC_POINT *, const EC_POINT *);
+int ossl_ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *);
+int ossl_ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *,
+ EC_POINT *,
+ const BIGNUM *x,
+ const BIGNUM *y, BN_CTX *);
+int ossl_ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *,
+ const EC_POINT *, BIGNUM *x,
+ BIGNUM *y, BN_CTX *);
+int ossl_ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,
+ const BIGNUM *x, int y_bit,
+ BN_CTX *);
+size_t ossl_ec_GF2m_simple_point2oct(const EC_GROUP *, const EC_POINT *,
+ point_conversion_form_t form,
+ unsigned char *buf, size_t len, BN_CTX *);
+int ossl_ec_GF2m_simple_oct2point(const EC_GROUP *, EC_POINT *,
+ const unsigned char *buf, size_t len, BN_CTX *);
+int ossl_ec_GF2m_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,
+ const EC_POINT *b, BN_CTX *);
+int ossl_ec_GF2m_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,
+ BN_CTX *);
+int ossl_ec_GF2m_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);
+int ossl_ec_GF2m_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *);
+int ossl_ec_GF2m_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);
+int ossl_ec_GF2m_simple_cmp(const EC_GROUP *, const EC_POINT *a,
+ const EC_POINT *b, BN_CTX *);
+int ossl_ec_GF2m_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
+int ossl_ec_GF2m_simple_points_make_affine(const EC_GROUP *, size_t num,
+ EC_POINT *[], BN_CTX *);
+int ossl_ec_GF2m_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *);
+int ossl_ec_GF2m_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *);
+int ossl_ec_GF2m_simple_field_div(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *);
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
+# ifdef B_ENDIAN
+# error "Can not enable ec_nistp_64_gcc_128 on big-endian systems"
+# endif
+
/* method functions in ecp_nistp224.c */
-int ec_GFp_nistp224_group_init(EC_GROUP *group);
-int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p,
- const BIGNUM *a, const BIGNUM *n,
- BN_CTX *);
-int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
- const EC_POINT *point,
- BIGNUM *x, BIGNUM *y,
- BN_CTX *ctx);
-int ec_GFp_nistp224_mul(const EC_GROUP *group, EC_POINT *r,
- const BIGNUM *scalar, size_t num,
- const EC_POINT *points[], const BIGNUM *scalars[],
- BN_CTX *);
-int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
- const BIGNUM *scalar, size_t num,
- const EC_POINT *points[],
- const BIGNUM *scalars[], BN_CTX *ctx);
-int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
-int ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group);
+int ossl_ec_GFp_nistp224_group_init(EC_GROUP *group);
+int ossl_ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p,
+ const BIGNUM *a, const BIGNUM *n,
+ BN_CTX *);
+int ossl_ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx);
+int ossl_ec_GFp_nistp224_mul(const EC_GROUP *group, EC_POINT *r,
+ const BIGNUM *scalar, size_t num,
+ const EC_POINT *points[], const BIGNUM *scalars[],
+ BN_CTX *);
+int ossl_ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
+ const BIGNUM *scalar, size_t num,
+ const EC_POINT *points[],
+ const BIGNUM *scalars[], BN_CTX *ctx);
+int ossl_ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
+int ossl_ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group);
/* method functions in ecp_nistp256.c */
-int ec_GFp_nistp256_group_init(EC_GROUP *group);
-int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,
- const BIGNUM *a, const BIGNUM *n,
- BN_CTX *);
-int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
- const EC_POINT *point,
- BIGNUM *x, BIGNUM *y,
- BN_CTX *ctx);
-int ec_GFp_nistp256_mul(const EC_GROUP *group, EC_POINT *r,
- const BIGNUM *scalar, size_t num,
- const EC_POINT *points[], const BIGNUM *scalars[],
- BN_CTX *);
-int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
- const BIGNUM *scalar, size_t num,
- const EC_POINT *points[],
- const BIGNUM *scalars[], BN_CTX *ctx);
-int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
-int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group);
+int ossl_ec_GFp_nistp256_group_init(EC_GROUP *group);
+int ossl_ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,
+ const BIGNUM *a, const BIGNUM *n,
+ BN_CTX *);
+int ossl_ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx);
+int ossl_ec_GFp_nistp256_mul(const EC_GROUP *group, EC_POINT *r,
+ const BIGNUM *scalar, size_t num,
+ const EC_POINT *points[], const BIGNUM *scalars[],
+ BN_CTX *);
+int ossl_ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
+ const BIGNUM *scalar, size_t num,
+ const EC_POINT *points[],
+ const BIGNUM *scalars[], BN_CTX *ctx);
+int ossl_ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
+int ossl_ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group);
/* method functions in ecp_nistp521.c */
-int ec_GFp_nistp521_group_init(EC_GROUP *group);
-int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p,
- const BIGNUM *a, const BIGNUM *n,
- BN_CTX *);
-int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group,
- const EC_POINT *point,
- BIGNUM *x, BIGNUM *y,
- BN_CTX *ctx);
-int ec_GFp_nistp521_mul(const EC_GROUP *group, EC_POINT *r,
- const BIGNUM *scalar, size_t num,
- const EC_POINT *points[], const BIGNUM *scalars[],
- BN_CTX *);
-int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
- const BIGNUM *scalar, size_t num,
- const EC_POINT *points[],
- const BIGNUM *scalars[], BN_CTX *ctx);
-int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
-int ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group);
+int ossl_ec_GFp_nistp521_group_init(EC_GROUP *group);
+int ossl_ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p,
+ const BIGNUM *a, const BIGNUM *n,
+ BN_CTX *);
+int ossl_ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx);
+int ossl_ec_GFp_nistp521_mul(const EC_GROUP *group, EC_POINT *r,
+ const BIGNUM *scalar, size_t num,
+ const EC_POINT *points[], const BIGNUM *scalars[],
+ BN_CTX *);
+int ossl_ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
+ const BIGNUM *scalar, size_t num,
+ const EC_POINT *points[],
+ const BIGNUM *scalars[], BN_CTX *ctx);
+int ossl_ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
+int ossl_ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group);
/* utility functions in ecp_nistputil.c */
-void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,
- size_t felem_size,
- void *tmp_felems,
- void (*felem_one) (void *out),
- int (*felem_is_zero) (const void
- *in),
- void (*felem_assign) (void *out,
- const void
- *in),
- void (*felem_square) (void *out,
- const void
- *in),
- void (*felem_mul) (void *out,
- const void
- *in1,
- const void
- *in2),
- void (*felem_inv) (void *out,
- const void
- *in),
- void (*felem_contract) (void
- *out,
- const
- void
- *in));
-void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign,
- unsigned char *digit, unsigned char in);
+void ossl_ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,
+ size_t felem_size,
+ void *tmp_felems,
+ void (*felem_one) (void *out),
+ int (*felem_is_zero)
+ (const void *in),
+ void (*felem_assign)
+ (void *out, const void *in),
+ void (*felem_square)
+ (void *out, const void *in),
+ void (*felem_mul)
+ (void *out,
+ const void *in1,
+ const void *in2),
+ void (*felem_inv)
+ (void *out, const void *in),
+ void (*felem_contract)
+ (void *out, const void *in));
+void ossl_ec_GFp_nistp_recode_scalar_bits(unsigned char *sign,
+ unsigned char *digit,
+ unsigned char in);
#endif
-int ec_group_simple_order_bits(const EC_GROUP *group);
+int ossl_ec_group_simple_order_bits(const EC_GROUP *group);
+
+/**
+ * Creates a new EC_GROUP object
+ * \param libctx The associated library context or NULL for the default
+ * library context
+ * \param propq Any property query string
+ * \param meth EC_METHOD to use
+ * \return newly created EC_GROUP object or NULL in case of an error.
+ */
+EC_GROUP *ossl_ec_group_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
+ const EC_METHOD *meth);
#ifdef ECP_NISTZ256_ASM
/** Returns GFp methods using montgomery multiplication, with x86-64 optimized
@@ -589,15 +615,21 @@ int ec_group_simple_order_bits(const EC_GROUP *group);
*/
const EC_METHOD *EC_GFp_nistz256_method(void);
#endif
+#ifdef S390X_EC_ASM
+const EC_METHOD *EC_GFp_s390x_nistp256_method(void);
+const EC_METHOD *EC_GFp_s390x_nistp384_method(void);
+const EC_METHOD *EC_GFp_s390x_nistp521_method(void);
+#endif
-size_t ec_key_simple_priv2oct(const EC_KEY *eckey,
- unsigned char *buf, size_t len);
-int ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len);
-int ec_key_simple_generate_key(EC_KEY *eckey);
-int ec_key_simple_generate_public_key(EC_KEY *eckey);
-int ec_key_simple_check_key(const EC_KEY *eckey);
+size_t ossl_ec_key_simple_priv2oct(const EC_KEY *eckey,
+ unsigned char *buf, size_t len);
+int ossl_ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf,
+ size_t len);
+int ossl_ec_key_simple_generate_key(EC_KEY *eckey);
+int ossl_ec_key_simple_generate_public_key(EC_KEY *eckey);
+int ossl_ec_key_simple_check_key(const EC_KEY *eckey);
-int ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx);
+int ossl_ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx);
/* EC_METHOD definitions */
@@ -630,11 +662,14 @@ struct ec_key_method_st {
#define EC_KEY_METHOD_DYNAMIC 1
+EC_KEY *ossl_ec_key_new_method_int(OSSL_LIB_CTX *libctx, const char *propq,
+ ENGINE *engine);
+
int ossl_ec_key_gen(EC_KEY *eckey);
int ossl_ecdh_compute_key(unsigned char **pout, size_t *poutlen,
const EC_POINT *pub_key, const EC_KEY *ecdh);
-int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen,
- const EC_POINT *pub_key, const EC_KEY *ecdh);
+int ossl_ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen,
+ const EC_POINT *pub_key, const EC_KEY *ecdh);
struct ECDSA_SIG_st {
BIGNUM *r;
@@ -653,18 +688,14 @@ int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len,
const unsigned char *sigbuf, int sig_len, EC_KEY *eckey);
int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY *eckey);
+int ossl_ecdsa_simple_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
+ BIGNUM **rp);
+ECDSA_SIG *ossl_ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len,
+ const BIGNUM *in_kinv, const BIGNUM *in_r,
+ EC_KEY *eckey);
+int ossl_ecdsa_simple_verify_sig(const unsigned char *dgst, int dgst_len,
+ const ECDSA_SIG *sig, EC_KEY *eckey);
-int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
- const uint8_t public_key[32], const uint8_t private_key[32]);
-int ED25519_verify(const uint8_t *message, size_t message_len,
- const uint8_t signature[64], const uint8_t public_key[32]);
-void ED25519_public_from_private(uint8_t out_public_key[32],
- const uint8_t private_key[32]);
-
-int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
- const uint8_t peer_public_value[32]);
-void X25519_public_from_private(uint8_t out_public_value[32],
- const uint8_t private_key[32]);
/*-
* This functions computes a single point multiplication over the EC group,
@@ -695,11 +726,12 @@ void X25519_public_from_private(uint8_t out_public_value[32],
*
* Returns 1 on success, 0 otherwise.
*/
-int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
- const BIGNUM *scalar, const EC_POINT *point,
- BN_CTX *ctx);
+int ossl_ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
+ const BIGNUM *scalar, const EC_POINT *point,
+ BN_CTX *ctx);
-int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx);
+int ossl_ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
+ BN_CTX *ctx);
static ossl_inline int ec_point_ladder_pre(const EC_GROUP *group,
EC_POINT *r, EC_POINT *s,
diff --git a/crypto/ec/ec_mult.c b/crypto/ec/ec_mult.c
index 9a1e3974ed9e..c6ec2964b7c4 100644
--- a/crypto/ec/ec_mult.c
+++ b/crypto/ec/ec_mult.c
@@ -1,13 +1,19 @@
/*
- * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <string.h>
#include <openssl/err.h>
@@ -51,7 +57,7 @@ static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group)
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return ret;
}
@@ -62,7 +68,7 @@ static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group)
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
- ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
@@ -136,9 +142,9 @@ void EC_ec_pre_comp_free(EC_PRE_COMP *pre)
*
* Returns 1 on success, 0 otherwise.
*/
-int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
- const BIGNUM *scalar, const EC_POINT *point,
- BN_CTX *ctx)
+int ossl_ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
+ const BIGNUM *scalar, const EC_POINT *point,
+ BN_CTX *ctx)
{
int i, cardinality_bits, group_top, kbit, pbit, Z_is_one;
EC_POINT *p = NULL;
@@ -153,11 +159,11 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
return EC_POINT_set_to_infinity(group, r);
if (BN_is_zero(group->order)) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_UNKNOWN_ORDER);
+ ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_ORDER);
return 0;
}
if (BN_is_zero(group->cofactor)) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_UNKNOWN_COFACTOR);
+ ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_COFACTOR);
return 0;
}
@@ -165,18 +171,18 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
if (((p = EC_POINT_new(group)) == NULL)
|| ((s = EC_POINT_new(group)) == NULL)) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
if (point == NULL) {
if (!EC_POINT_copy(p, group->generator)) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
} else {
if (!EC_POINT_copy(p, point)) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
}
@@ -189,12 +195,12 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
lambda = BN_CTX_get(ctx);
k = BN_CTX_get(ctx);
if (k == NULL) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!BN_mul(cardinality, group->order, group->cofactor, ctx)) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
@@ -208,12 +214,12 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
group_top = bn_get_top(cardinality);
if ((bn_wexpand(k, group_top + 2) == NULL)
|| (bn_wexpand(lambda, group_top + 2) == NULL)) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
if (!BN_copy(k, scalar)) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
@@ -225,18 +231,18 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
* constant-timeness
*/
if (!BN_nnmod(k, k, cardinality, ctx)) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
}
if (!BN_add(lambda, k, cardinality)) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
BN_set_flags(lambda, BN_FLG_CONSTTIME);
if (!BN_add(k, lambda, cardinality)) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/*
@@ -256,19 +262,20 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
|| (bn_wexpand(p->X, group_top) == NULL)
|| (bn_wexpand(p->Y, group_top) == NULL)
|| (bn_wexpand(p->Z, group_top) == NULL)) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* ensure input point is in affine coords for ladder step efficiency */
- if (!p->Z_is_one && !EC_POINT_make_affine(group, p, ctx)) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_EC_LIB);
+ if (!p->Z_is_one && (group->meth->make_affine == NULL
+ || !group->meth->make_affine(group, p, ctx))) {
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
/* Initialize the Montgomery ladder */
if (!ec_point_ladder_pre(group, r, s, p, ctx)) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_PRE_FAILURE);
+ ERR_raise(ERR_LIB_EC, EC_R_LADDER_PRE_FAILURE);
goto err;
}
@@ -348,7 +355,7 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
/* Perform a single step of the Montgomery ladder */
if (!ec_point_ladder_step(group, r, s, p, ctx)) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_STEP_FAILURE);
+ ERR_raise(ERR_LIB_EC, EC_R_LADDER_STEP_FAILURE);
goto err;
}
/*
@@ -363,7 +370,7 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
/* Finalize ladder (and recover full point coordinates) */
if (!ec_point_ladder_post(group, r, s, p, ctx)) {
- ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_POST_FAILURE);
+ ERR_raise(ERR_LIB_EC, EC_R_LADDER_POST_FAILURE);
goto err;
}
@@ -380,7 +387,7 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
#undef EC_POINT_BN_set_flags
/*
- * TODO: table should be optimised for the wNAF-based implementation,
+ * Table could be optimised for the wNAF-based implementation,
* sometimes smaller windows will give better performance (thus the
* boundaries should be increased)
*/
@@ -400,9 +407,9 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
* scalar*generator
* in the addition if scalar != NULL
*/
-int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
- size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
- BN_CTX *ctx)
+int ossl_ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
+ size_t num, const EC_POINT *points[],
+ const BIGNUM *scalars[], BN_CTX *ctx)
{
const EC_POINT *generator = NULL;
EC_POINT *tmp = NULL;
@@ -443,7 +450,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
* is why we ignore if BN_FLG_CONSTTIME is actually set and we
* always call the ladder version.
*/
- return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);
+ return ossl_ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);
}
if ((scalar == NULL) && (num == 1) && (scalars[0] != group->order)) {
/*-
@@ -453,14 +460,15 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
* To protect the secret scalar, we ignore if BN_FLG_CONSTTIME is
* actually set and we always call the ladder version.
*/
- return ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx);
+ return ossl_ec_scalar_mul_ladder(group, r, scalars[0], points[0],
+ ctx);
}
}
if (scalar != NULL) {
generator = EC_GROUP_get0_generator(group);
if (generator == NULL) {
- ECerr(EC_F_EC_WNAF_MUL, EC_R_UNDEFINED_GENERATOR);
+ ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR);
goto err;
}
@@ -488,7 +496,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
/* check that pre_comp looks sane */
if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block)) {
- ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
goto err;
}
} else {
@@ -513,7 +521,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
wNAF[0] = NULL; /* preliminary pivot */
if (wsize == NULL || wNAF_len == NULL || wNAF == NULL || val_sub == NULL) {
- ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -543,7 +551,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
if (pre_comp == NULL) {
if (num_scalar != 1) {
- ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
goto err;
}
/* we have already generated a wNAF for 'scalar' */
@@ -552,7 +560,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
size_t tmp_len = 0;
if (num_scalar != 0) {
- ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -595,7 +603,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
*/
numblocks = (tmp_len + blocksize - 1) / blocksize;
if (numblocks > pre_comp->numblocks) {
- ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
OPENSSL_free(tmp_wNAF);
goto err;
}
@@ -610,7 +618,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
if (i < totalnum - 1) {
wNAF_len[i] = blocksize;
if (tmp_len < blocksize) {
- ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
OPENSSL_free(tmp_wNAF);
goto err;
}
@@ -625,7 +633,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
wNAF[i + 1] = NULL;
wNAF[i] = OPENSSL_malloc(wNAF_len[i]);
if (wNAF[i] == NULL) {
- ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
OPENSSL_free(tmp_wNAF);
goto err;
}
@@ -634,7 +642,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
max_len = wNAF_len[i];
if (*tmp_points == NULL) {
- ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
OPENSSL_free(tmp_wNAF);
goto err;
}
@@ -654,7 +662,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
*/
val = OPENSSL_malloc((num_val + 1) * sizeof(val[0]));
if (val == NULL) {
- ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
val[num_val] = NULL; /* pivot element */
@@ -671,7 +679,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
}
}
if (!(v == val + num_val)) {
- ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -705,7 +713,8 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
}
}
- if (!EC_POINTs_make_affine(group, num_val, val, ctx))
+ if (group->meth->points_make_affine == NULL
+ || !group->meth->points_make_affine(group, num_val, val, ctx))
goto err;
r_is_at_infinity = 1;
@@ -745,12 +754,12 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
* Apply coordinate blinding for EC_POINT.
*
* The underlying EC_METHOD can optionally implement this function:
- * ec_point_blind_coordinates() returns 0 in case of errors or 1 on
+ * ossl_ec_point_blind_coordinates() returns 0 in case of errors or 1 on
* success or if coordinate blinding is not implemented for this
* group.
*/
- if (!ec_point_blind_coordinates(group, r, ctx)) {
- ECerr(EC_F_EC_WNAF_MUL, EC_R_POINT_COORDINATES_BLIND_FAILURE);
+ if (!ossl_ec_point_blind_coordinates(group, r, ctx)) {
+ ERR_raise(ERR_LIB_EC, EC_R_POINT_COORDINATES_BLIND_FAILURE);
goto err;
}
@@ -799,9 +808,9 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
}
/*-
- * ec_wNAF_precompute_mult()
+ * ossl_ec_wNAF_precompute_mult()
* creates an EC_PRE_COMP object with preprecomputed multiples of the generator
- * for use with wNAF splitting as implemented in ec_wNAF_mul().
+ * for use with wNAF splitting as implemented in ossl_ec_wNAF_mul().
*
* 'pre_comp->points' is an array of multiples of the generator
* of the following form:
@@ -818,16 +827,19 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
* points[2^(w-1)*numblocks-1] = (2^(w-1)) * 2^(blocksize*(numblocks-1)) * generator
* points[2^(w-1)*numblocks] = NULL
*/
-int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
+int ossl_ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
{
const EC_POINT *generator;
EC_POINT *tmp_point = NULL, *base = NULL, **var;
- BN_CTX *new_ctx = NULL;
const BIGNUM *order;
size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num;
EC_POINT **points = NULL;
EC_PRE_COMP *pre_comp;
int ret = 0;
+ int used_ctx = 0;
+#ifndef FIPS_MODULE
+ BN_CTX *new_ctx = NULL;
+#endif
/* if there is an old EC_PRE_COMP object, throw it away */
EC_pre_comp_free(group);
@@ -836,23 +848,25 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
generator = EC_GROUP_get0_generator(group);
if (generator == NULL) {
- ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNDEFINED_GENERATOR);
+ ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR);
goto err;
}
- if (ctx == NULL) {
+#ifndef FIPS_MODULE
+ if (ctx == NULL)
ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL)
- goto err;
- }
+#endif
+ if (ctx == NULL)
+ goto err;
BN_CTX_start(ctx);
+ used_ctx = 1;
order = EC_GROUP_get0_order(group);
if (order == NULL)
goto err;
if (BN_is_zero(order)) {
- ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER);
+ ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_ORDER);
goto err;
}
@@ -880,7 +894,7 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
points = OPENSSL_malloc(sizeof(*points) * (num + 1));
if (points == NULL) {
- ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -888,14 +902,14 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
var[num] = NULL; /* pivot */
for (i = 0; i < num; i++) {
if ((var[i] = EC_POINT_new(group)) == NULL) {
- ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
}
if ((tmp_point = EC_POINT_new(group)) == NULL
|| (base = EC_POINT_new(group)) == NULL) {
- ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -927,7 +941,7 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
size_t k;
if (blocksize <= 2) {
- ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -940,7 +954,8 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
}
}
- if (!EC_POINTs_make_affine(group, num, points, ctx))
+ if (group->meth->points_make_affine == NULL
+ || !group->meth->points_make_affine(group, num, points, ctx))
goto err;
pre_comp->group = group;
@@ -955,8 +970,11 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
ret = 1;
err:
- BN_CTX_end(ctx);
+ if (used_ctx)
+ BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
EC_ec_pre_comp_free(pre_comp);
if (points) {
EC_POINT **p;
@@ -970,7 +988,7 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
return ret;
}
-int ec_wNAF_have_precompute_mult(const EC_GROUP *group)
+int ossl_ec_wNAF_have_precompute_mult(const EC_GROUP *group)
{
return HAVEPRECOMP(group, ec);
}
diff --git a/crypto/ec/ec_oct.c b/crypto/ec/ec_oct.c
index 7ddc86b047ca..790a0b290771 100644
--- a/crypto/ec/ec_oct.c
+++ b/crypto/ec/ec_oct.c
@@ -1,13 +1,19 @@
/*
- * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <string.h>
#include <openssl/err.h>
@@ -20,36 +26,33 @@ int EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
{
if (group->meth->point_set_compressed_coordinates == NULL
&& !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
- ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
- ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES,
- EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
if (group->meth->field_type == NID_X9_62_prime_field)
- return ec_GFp_simple_set_compressed_coordinates(group, point, x,
- y_bit, ctx);
+ return ossl_ec_GFp_simple_set_compressed_coordinates(group, point, x,
+ y_bit, ctx);
else
#ifdef OPENSSL_NO_EC2M
{
- ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES,
- EC_R_GF2M_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
return 0;
}
#else
- return ec_GF2m_simple_set_compressed_coordinates(group, point, x,
- y_bit, ctx);
+ return ossl_ec_GF2m_simple_set_compressed_coordinates(group, point,
+ x, y_bit, ctx);
#endif
}
return group->meth->point_set_compressed_coordinates(group, point, x,
y_bit, ctx);
}
-#if OPENSSL_API_COMPAT < 0x10200000L
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
EC_POINT *point, const BIGNUM *x,
int y_bit, BN_CTX *ctx)
@@ -73,25 +76,26 @@ size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
{
if (group->meth->point2oct == 0
&& !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
- ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
- ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
if (group->meth->field_type == NID_X9_62_prime_field)
- return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx);
+ return ossl_ec_GFp_simple_point2oct(group, point, form, buf, len,
+ ctx);
else
#ifdef OPENSSL_NO_EC2M
{
- ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_GF2M_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
return 0;
}
#else
- return ec_GF2m_simple_point2oct(group, point,
- form, buf, len, ctx);
+ return ossl_ec_GF2m_simple_point2oct(group, point,
+ form, buf, len, ctx);
#endif
}
@@ -103,24 +107,24 @@ int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
{
if (group->meth->oct2point == 0
&& !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
- ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
- ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
+ ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
if (group->meth->field_type == NID_X9_62_prime_field)
- return ec_GFp_simple_oct2point(group, point, buf, len, ctx);
+ return ossl_ec_GFp_simple_oct2point(group, point, buf, len, ctx);
else
#ifdef OPENSSL_NO_EC2M
{
- ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_GF2M_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
return 0;
}
#else
- return ec_GF2m_simple_oct2point(group, point, buf, len, ctx);
+ return ossl_ec_GF2m_simple_oct2point(group, point, buf, len, ctx);
#endif
}
return group->meth->oct2point(group, point, buf, len, ctx);
@@ -137,7 +141,7 @@ size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point,
if (len == 0)
return 0;
if ((buf = OPENSSL_malloc(len)) == NULL) {
- ECerr(EC_F_EC_POINT_POINT2BUF, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
len = EC_POINT_point2oct(group, point, form, buf, len, ctx);
diff --git a/crypto/ec/ec_pmeth.c b/crypto/ec/ec_pmeth.c
index 64d2cc93a620..19e2f0d0c04d 100644
--- a/crypto/ec/ec_pmeth.c
+++ b/crypto/ec/ec_pmeth.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDH and ECDSA low level APIs are deprecated for public use, but still ok
+ * for internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
@@ -43,7 +49,7 @@ static int pkey_ec_init(EVP_PKEY_CTX *ctx)
EC_PKEY_CTX *dctx;
if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) {
- ECerr(EC_F_PKEY_EC_INIT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -53,7 +59,7 @@ static int pkey_ec_init(EVP_PKEY_CTX *ctx)
return 1;
}
-static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+static int pkey_ec_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
{
EC_PKEY_CTX *dctx, *sctx;
if (!pkey_ec_init(dst))
@@ -103,7 +109,12 @@ static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
int ret, type;
unsigned int sltmp;
EC_PKEY_CTX *dctx = ctx->data;
- EC_KEY *ec = ctx->pkey->pkey.ec;
+ /*
+ * Discard const. Its marked as const because this may be a cached copy of
+ * the "real" key. These calls don't make any modifications that need to
+ * be reflected back in the "original" key.
+ */
+ EC_KEY *ec = (EC_KEY *)EVP_PKEY_get0_EC_KEY(ctx->pkey);
const int sig_sz = ECDSA_size(ec);
/* ensure cast to size_t is safe */
@@ -116,11 +127,11 @@ static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
}
if (*siglen < (size_t)sig_sz) {
- ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL);
+ ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
return 0;
}
- type = (dctx->md != NULL) ? EVP_MD_type(dctx->md) : NID_sha1;
+ type = (dctx->md != NULL) ? EVP_MD_get_type(dctx->md) : NID_sha1;
ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
@@ -136,10 +147,15 @@ static int pkey_ec_verify(EVP_PKEY_CTX *ctx,
{
int ret, type;
EC_PKEY_CTX *dctx = ctx->data;
- EC_KEY *ec = ctx->pkey->pkey.ec;
+ /*
+ * Discard const. Its marked as const because this may be a cached copy of
+ * the "real" key. These calls don't make any modifications that need to
+ * be reflected back in the "original" key.
+ */
+ EC_KEY *ec = (EC_KEY *)EVP_PKEY_get0_EC_KEY(ctx->pkey);
if (dctx->md)
- type = EVP_MD_type(dctx->md);
+ type = EVP_MD_get_type(dctx->md);
else
type = NID_sha1;
@@ -155,21 +171,32 @@ static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
size_t outlen;
const EC_POINT *pubkey = NULL;
EC_KEY *eckey;
+ const EC_KEY *eckeypub;
EC_PKEY_CTX *dctx = ctx->data;
- if (!ctx->pkey || !ctx->peerkey) {
- ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET);
+
+ if (ctx->pkey == NULL || ctx->peerkey == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
+ return 0;
+ }
+ eckeypub = EVP_PKEY_get0_EC_KEY(ctx->peerkey);
+ if (eckeypub == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
return 0;
}
- eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec;
+ eckey = dctx->co_key ? dctx->co_key
+ : (EC_KEY *)EVP_PKEY_get0_EC_KEY(ctx->pkey);
if (!key) {
const EC_GROUP *group;
group = EC_KEY_get0_group(eckey);
+
+ if (group == NULL)
+ return 0;
*keylen = (EC_GROUP_get_degree(group) + 7) / 8;
return 1;
}
- pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec);
+ pubkey = EC_KEY_get0_public_key(eckeypub);
/*
* NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is not
@@ -203,14 +230,15 @@ static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx,
if (!pkey_ec_derive(ctx, NULL, &ktmplen))
return 0;
if ((ktmp = OPENSSL_malloc(ktmplen)) == NULL) {
- ECerr(EC_F_PKEY_EC_KDF_DERIVE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!pkey_ec_derive(ctx, ktmp, &ktmplen))
goto err;
/* Do KDF stuff */
- if (!ecdh_KDF_X9_63(key, *keylen, ktmp, ktmplen,
- dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
+ if (!ossl_ecdh_kdf_X9_63(key, *keylen, ktmp, ktmplen,
+ dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md,
+ ctx->libctx, ctx->propquery))
goto err;
rv = 1;
@@ -228,7 +256,7 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
group = EC_GROUP_new_by_curve_name(p1);
if (group == NULL) {
- ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE);
return 0;
}
EC_GROUP_free(dctx->gen_group);
@@ -237,7 +265,7 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_EC_PARAM_ENC:
if (!dctx->gen_group) {
- ECerr(EC_F_PKEY_EC_CTRL, EC_R_NO_PARAMETERS_SET);
+ ERR_raise(ERR_LIB_EC, EC_R_NO_PARAMETERS_SET);
return 0;
}
EC_GROUP_set_asn1_flag(dctx->gen_group, p1);
@@ -249,14 +277,23 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
if (dctx->cofactor_mode != -1)
return dctx->cofactor_mode;
else {
- EC_KEY *ec_key = ctx->pkey->pkey.ec;
+ const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(ctx->pkey);
return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : 0;
}
} else if (p1 < -1 || p1 > 1)
return -2;
dctx->cofactor_mode = p1;
if (p1 != -1) {
- EC_KEY *ec_key = ctx->pkey->pkey.ec;
+ EC_KEY *ec_key = (EC_KEY *)EVP_PKEY_get0_EC_KEY(ctx->pkey);
+
+ /*
+ * We discarded the "const" above. This will only work if the key is
+ * a "real" legacy key, and not a cached copy of a provided key
+ */
+ if (evp_pkey_is_provided(ctx->pkey)) {
+ ERR_raise(ERR_LIB_EC, ERR_R_UNSUPPORTED);
+ return 0;
+ }
if (!ec_key->group)
return -2;
/* If cofactor is 1 cofactor mode does nothing */
@@ -318,17 +355,18 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return dctx->kdf_ukmlen;
case EVP_PKEY_CTRL_MD:
- if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha512 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512) {
- ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE);
+ if (EVP_MD_get_type((const EVP_MD *)p2) != NID_sha1 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha224 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha256 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha384 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha512 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_224 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_256 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_384 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_512 &&
+ EVP_MD_get_type((const EVP_MD *)p2) != NID_sm3) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
return 0;
}
dctx->md = p2;
@@ -362,7 +400,7 @@ static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx,
if (nid == NID_undef)
nid = OBJ_ln2nid(value);
if (nid == NID_undef) {
- ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE);
return 0;
}
return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
@@ -378,7 +416,7 @@ static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx,
} else if (strcmp(type, "ecdh_kdf_md") == 0) {
const EVP_MD *md;
if ((md = EVP_get_digestbyname(value)) == NULL) {
- ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_DIGEST);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST);
return 0;
}
return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md);
@@ -398,7 +436,7 @@ static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
int ret;
if (dctx->gen_group == NULL) {
- ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET);
+ ERR_raise(ERR_LIB_EC, EC_R_NO_PARAMETERS_SET);
return 0;
}
ec = EC_KEY_new();
@@ -417,7 +455,7 @@ static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
int ret;
if (ctx->pkey == NULL && dctx->gen_group == NULL) {
- ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET);
+ ERR_raise(ERR_LIB_EC, EC_R_NO_PARAMETERS_SET);
return 0;
}
ec = EC_KEY_new();
@@ -436,7 +474,7 @@ static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
return ret ? EC_KEY_generate_key(ec) : 0;
}
-const EVP_PKEY_METHOD ec_pkey_meth = {
+static const EVP_PKEY_METHOD ec_pkey_meth = {
EVP_PKEY_EC,
0,
pkey_ec_init,
@@ -474,3 +512,8 @@ const EVP_PKEY_METHOD ec_pkey_meth = {
pkey_ec_ctrl,
pkey_ec_ctrl_str
};
+
+const EVP_PKEY_METHOD *ossl_ec_pkey_method(void)
+{
+ return &ec_pkey_meth;
+}
diff --git a/crypto/ec/ec_print.c b/crypto/ec/ec_print.c
index 660fc400fb75..ffe112052fbd 100644
--- a/crypto/ec/ec_print.c
+++ b/crypto/ec/ec_print.c
@@ -1,74 +1,16 @@
/*
- * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#include <string.h> /* strlen */
#include <openssl/crypto.h>
-#include <openssl/err.h>
#include "ec_local.h"
-BIGNUM *EC_POINT_point2bn(const EC_GROUP *group,
- const EC_POINT *point,
- point_conversion_form_t form,
- BIGNUM *ret, BN_CTX *ctx)
-{
- size_t buf_len = 0;
- unsigned char *buf;
-
- buf_len = EC_POINT_point2buf(group, point, form, &buf, ctx);
-
- if (buf_len == 0)
- return NULL;
-
- ret = BN_bin2bn(buf, buf_len, ret);
-
- OPENSSL_free(buf);
-
- return ret;
-}
-
-EC_POINT *EC_POINT_bn2point(const EC_GROUP *group,
- const BIGNUM *bn, EC_POINT *point, BN_CTX *ctx)
-{
- size_t buf_len = 0;
- unsigned char *buf;
- EC_POINT *ret;
-
- if ((buf_len = BN_num_bytes(bn)) == 0)
- buf_len = 1;
- if ((buf = OPENSSL_malloc(buf_len)) == NULL) {
- ECerr(EC_F_EC_POINT_BN2POINT, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- if (!BN_bn2binpad(bn, buf, buf_len)) {
- OPENSSL_free(buf);
- return NULL;
- }
-
- if (point == NULL) {
- if ((ret = EC_POINT_new(group)) == NULL) {
- OPENSSL_free(buf);
- return NULL;
- }
- } else
- ret = point;
-
- if (!EC_POINT_oct2point(group, ret, buf, buf_len, ctx)) {
- if (ret != point)
- EC_POINT_clear_free(ret);
- OPENSSL_free(buf);
- return NULL;
- }
-
- OPENSSL_free(buf);
- return ret;
-}
-
static const char *HEX_DIGITS = "0123456789ABCDEF";
/* the return value must be freed (using OPENSSL_free()) */
@@ -105,17 +47,39 @@ char *EC_POINT_point2hex(const EC_GROUP *group,
}
EC_POINT *EC_POINT_hex2point(const EC_GROUP *group,
- const char *buf, EC_POINT *point, BN_CTX *ctx)
+ const char *hex, EC_POINT *point, BN_CTX *ctx)
{
- EC_POINT *ret = NULL;
- BIGNUM *tmp_bn = NULL;
+ int ok = 0;
+ unsigned char *oct_buf = NULL;
+ size_t len, oct_buf_len = 0;
+ EC_POINT *pt = NULL;
- if (!BN_hex2bn(&tmp_bn, buf))
+ if (group == NULL || hex == NULL)
return NULL;
- ret = EC_POINT_bn2point(group, tmp_bn, point, ctx);
-
- BN_clear_free(tmp_bn);
+ if (point == NULL) {
+ pt = EC_POINT_new(group);
+ if (pt == NULL)
+ goto err;
+ } else {
+ pt = point;
+ }
- return ret;
+ len = strlen(hex) / 2;
+ oct_buf = OPENSSL_malloc(len);
+ if (oct_buf == NULL)
+ goto err;
+
+ if (!OPENSSL_hexstr2buf_ex(oct_buf, len, &oct_buf_len, hex, '\0')
+ || !EC_POINT_oct2point(group, pt, oct_buf, oct_buf_len, ctx))
+ goto err;
+ ok = 1;
+err:
+ OPENSSL_clear_free(oct_buf, oct_buf_len);
+ if (!ok) {
+ if (pt != point)
+ EC_POINT_clear_free(pt);
+ pt = NULL;
+ }
+ return pt;
}
diff --git a/crypto/ec/ecdh_kdf.c b/crypto/ec/ecdh_kdf.c
index 96efac62f66f..de63bf8500b4 100644
--- a/crypto/ec/ecdh_kdf.c
+++ b/crypto/ec/ecdh_kdf.c
@@ -1,81 +1,65 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <string.h>
+#include <openssl/core_names.h>
#include <openssl/ec.h>
#include <openssl/evp.h>
+#include <openssl/kdf.h>
#include "ec_local.h"
/* Key derivation function from X9.63/SECG */
-/* Way more than we will ever need */
-#define ECDH_KDF_MAX (1 << 30)
-
-int ecdh_KDF_X9_63(unsigned char *out, size_t outlen,
- const unsigned char *Z, size_t Zlen,
- const unsigned char *sinfo, size_t sinfolen,
- const EVP_MD *md)
+int ossl_ecdh_kdf_X9_63(unsigned char *out, size_t outlen,
+ const unsigned char *Z, size_t Zlen,
+ const unsigned char *sinfo, size_t sinfolen,
+ const EVP_MD *md,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
- EVP_MD_CTX *mctx = NULL;
- int rv = 0;
- unsigned int i;
- size_t mdlen;
- unsigned char ctr[4];
- if (sinfolen > ECDH_KDF_MAX || outlen > ECDH_KDF_MAX
- || Zlen > ECDH_KDF_MAX)
- return 0;
- mctx = EVP_MD_CTX_new();
- if (mctx == NULL)
- return 0;
- mdlen = EVP_MD_size(md);
- for (i = 1;; i++) {
- unsigned char mtmp[EVP_MAX_MD_SIZE];
- if (!EVP_DigestInit_ex(mctx, md, NULL))
- goto err;
- ctr[3] = i & 0xFF;
- ctr[2] = (i >> 8) & 0xFF;
- ctr[1] = (i >> 16) & 0xFF;
- ctr[0] = (i >> 24) & 0xFF;
- if (!EVP_DigestUpdate(mctx, Z, Zlen))
- goto err;
- if (!EVP_DigestUpdate(mctx, ctr, sizeof(ctr)))
- goto err;
- if (!EVP_DigestUpdate(mctx, sinfo, sinfolen))
- goto err;
- if (outlen >= mdlen) {
- if (!EVP_DigestFinal(mctx, out, NULL))
- goto err;
- outlen -= mdlen;
- if (outlen == 0)
- break;
- out += mdlen;
- } else {
- if (!EVP_DigestFinal(mctx, mtmp, NULL))
- goto err;
- memcpy(out, mtmp, outlen);
- OPENSSL_cleanse(mtmp, mdlen);
- break;
- }
+ int ret = 0;
+ EVP_KDF_CTX *kctx = NULL;
+ OSSL_PARAM params[4], *p = params;
+ const char *mdname = EVP_MD_get0_name(md);
+ EVP_KDF *kdf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_X963KDF, propq);
+
+ if ((kctx = EVP_KDF_CTX_new(kdf)) != NULL) {
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ (char *)mdname, 0);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ (void *)Z, Zlen);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
+ (void *)sinfo, sinfolen);
+ *p = OSSL_PARAM_construct_end();
+
+ ret = EVP_KDF_derive(kctx, out, outlen, params) > 0;
+ EVP_KDF_CTX_free(kctx);
}
- rv = 1;
- err:
- EVP_MD_CTX_free(mctx);
- return rv;
+ EVP_KDF_free(kdf);
+ return ret;
}
/*-
* The old name for ecdh_KDF_X9_63
* Retained for ABI compatibility
*/
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
const unsigned char *Z, size_t Zlen,
const unsigned char *sinfo, size_t sinfolen,
const EVP_MD *md)
{
- return ecdh_KDF_X9_63(out, outlen, Z, Zlen, sinfo, sinfolen, md);
+ return ossl_ecdh_kdf_X9_63(out, outlen, Z, Zlen, sinfo, sinfolen, md, NULL,
+ NULL);
}
+#endif
diff --git a/crypto/ec/ecdh_ossl.c b/crypto/ec/ecdh_ossl.c
index 0be00d43da4e..8016c6d7ad73 100644
--- a/crypto/ec/ecdh_ossl.c
+++ b/crypto/ec/ecdh_ossl.c
@@ -1,13 +1,19 @@
/*
- * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <string.h>
#include <limits.h>
@@ -23,7 +29,7 @@ int ossl_ecdh_compute_key(unsigned char **psec, size_t *pseclen,
const EC_POINT *pub_key, const EC_KEY *ecdh)
{
if (ecdh->group->meth->ecdh_compute_key == NULL) {
- ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_CURVE_DOES_NOT_SUPPORT_ECDH);
+ ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDH);
return 0;
}
@@ -31,12 +37,17 @@ int ossl_ecdh_compute_key(unsigned char **psec, size_t *pseclen,
}
/*-
- * This implementation is based on the following primitives in the IEEE 1363 standard:
+ * This implementation is based on the following primitives in the
+ * IEEE 1363 standard:
* - ECKAS-DH1
* - ECSVDP-DH
+ *
+ * It also conforms to SP800-56A r3
+ * See Section 5.7.1.2 "Elliptic Curve Cryptography Cofactor Diffie-Hellman
+ * (ECC CDH) Primitive:". The steps listed below refer to SP800-56A.
*/
-int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen,
- const EC_POINT *pub_key, const EC_KEY *ecdh)
+int ossl_ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen,
+ const EC_POINT *pub_key, const EC_KEY *ecdh)
{
BN_CTX *ctx;
EC_POINT *tmp = NULL;
@@ -47,61 +58,74 @@ int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen,
size_t buflen, len;
unsigned char *buf = NULL;
- if ((ctx = BN_CTX_new()) == NULL)
+ if ((ctx = BN_CTX_new_ex(ecdh->libctx)) == NULL)
goto err;
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
if (x == NULL) {
- ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
priv_key = EC_KEY_get0_private_key(ecdh);
if (priv_key == NULL) {
- ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_MISSING_PRIVATE_KEY);
+ ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY);
goto err;
}
group = EC_KEY_get0_group(ecdh);
+ /*
+ * Step(1) - Compute the point tmp = cofactor * owners_private_key
+ * * peer_public_key.
+ */
if (EC_KEY_get_flags(ecdh) & EC_FLAG_COFACTOR_ECDH) {
if (!EC_GROUP_get_cofactor(group, x, NULL) ||
!BN_mul(x, x, priv_key, ctx)) {
- ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
priv_key = x;
}
if ((tmp = EC_POINT_new(group)) == NULL) {
- ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) {
- ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE);
+ ERR_raise(ERR_LIB_EC, EC_R_POINT_ARITHMETIC_FAILURE);
goto err;
}
+ /*
+ * Step(2) : If point tmp is at infinity then clear intermediate values and
+ * exit. Note: getting affine coordinates returns 0 if point is at infinity.
+ * Step(3a) : Get x-coordinate of point x = tmp.x
+ */
if (!EC_POINT_get_affine_coordinates(group, tmp, x, NULL, ctx)) {
- ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE);
+ ERR_raise(ERR_LIB_EC, EC_R_POINT_ARITHMETIC_FAILURE);
goto err;
}
+ /*
+ * Step(3b) : convert x to a byte string, using the field-element-to-byte
+ * string conversion routine defined in Appendix C.2
+ */
buflen = (EC_GROUP_get_degree(group) + 7) / 8;
len = BN_num_bytes(x);
if (len > buflen) {
- ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
goto err;
}
if ((buf = OPENSSL_malloc(buflen)) == NULL) {
- ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
memset(buf, 0, buflen - len);
if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) {
- ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
@@ -112,6 +136,8 @@ int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen,
ret = 1;
err:
+ /* Step(4) : Destroy all intermediate calculations */
+ BN_clear(x);
EC_POINT_clear_free(tmp);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
diff --git a/crypto/ec/ecdsa_ossl.c b/crypto/ec/ecdsa_ossl.c
index 1da87bfb5e39..fe9b3cf59363 100644
--- a/crypto/ec/ecdsa_ossl.c
+++ b/crypto/ec/ecdsa_ossl.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <string.h>
#include <openssl/err.h>
#include <openssl/obj_mac.h>
@@ -14,6 +20,41 @@
#include "crypto/bn.h"
#include "ec_local.h"
+int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
+ BIGNUM **rp)
+{
+ if (eckey->group->meth->ecdsa_sign_setup == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA);
+ return 0;
+ }
+
+ return eckey->group->meth->ecdsa_sign_setup(eckey, ctx_in, kinvp, rp);
+}
+
+ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
+ const BIGNUM *in_kinv, const BIGNUM *in_r,
+ EC_KEY *eckey)
+{
+ if (eckey->group->meth->ecdsa_sign_sig == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA);
+ return NULL;
+ }
+
+ return eckey->group->meth->ecdsa_sign_sig(dgst, dgst_len,
+ in_kinv, in_r, eckey);
+}
+
+int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
+ const ECDSA_SIG *sig, EC_KEY *eckey)
+{
+ if (eckey->group->meth->ecdsa_verify_sig == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA);
+ return 0;
+ }
+
+ return eckey->group->meth->ecdsa_verify_sig(dgst, dgst_len, sig, eckey);
+}
+
int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen,
unsigned char *sig, unsigned int *siglen,
const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey)
@@ -44,35 +85,35 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
const BIGNUM *priv_key;
if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) {
- ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if ((priv_key = EC_KEY_get0_private_key(eckey)) == NULL) {
- ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_MISSING_PRIVATE_KEY);
+ ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY);
return 0;
}
if (!EC_KEY_can_sign(eckey)) {
- ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
+ ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
return 0;
}
if ((ctx = ctx_in) == NULL) {
- if ((ctx = BN_CTX_new()) == NULL) {
- ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE);
+ if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
}
- k = BN_new(); /* this value is later returned in *kinvp */
+ k = BN_secure_new(); /* this value is later returned in *kinvp */
r = BN_new(); /* this value is later returned in *rp */
X = BN_new();
if (k == NULL || r == NULL || X == NULL) {
- ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
if ((tmp_point = EC_POINT_new(group)) == NULL) {
- ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
order = EC_GROUP_get0_order(group);
@@ -90,14 +131,12 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
if (dgst != NULL) {
if (!BN_generate_dsa_nonce(k, order, priv_key,
dgst, dlen, ctx)) {
- ECerr(EC_F_ECDSA_SIGN_SETUP,
- EC_R_RANDOM_NUMBER_GENERATION_FAILED);
+ ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED);
goto err;
}
} else {
- if (!BN_priv_rand_range(k, order)) {
- ECerr(EC_F_ECDSA_SIGN_SETUP,
- EC_R_RANDOM_NUMBER_GENERATION_FAILED);
+ if (!BN_priv_rand_range_ex(k, order, 0, ctx)) {
+ ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED);
goto err;
}
}
@@ -105,24 +144,24 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
/* compute r the x-coordinate of generator * k */
if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) {
- ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if (!EC_POINT_get_affine_coordinates(group, tmp_point, X, NULL, ctx)) {
- ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if (!BN_nnmod(r, X, order, ctx)) {
- ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
} while (BN_is_zero(r));
/* compute the inverse of k */
- if (!ec_group_do_inverse_ord(group, k, k, ctx)) {
- ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
+ if (!ossl_ec_group_do_inverse_ord(group, k, k, ctx)) {
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
@@ -145,15 +184,15 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
return ret;
}
-int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
- BIGNUM **rp)
+int ossl_ecdsa_simple_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
+ BIGNUM **rp)
{
return ecdsa_sign_setup(eckey, ctx_in, kinvp, rp, NULL, 0);
}
-ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
- const BIGNUM *in_kinv, const BIGNUM *in_r,
- EC_KEY *eckey)
+ECDSA_SIG *ossl_ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len,
+ const BIGNUM *in_kinv, const BIGNUM *in_r,
+ EC_KEY *eckey)
{
int ok = 0, i;
BIGNUM *kinv = NULL, *s, *m = NULL;
@@ -167,35 +206,35 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
priv_key = EC_KEY_get0_private_key(eckey);
if (group == NULL) {
- ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (priv_key == NULL) {
- ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_MISSING_PRIVATE_KEY);
+ ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY);
return NULL;
}
if (!EC_KEY_can_sign(eckey)) {
- ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
+ ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
return NULL;
}
ret = ECDSA_SIG_new();
if (ret == NULL) {
- ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->r = BN_new();
ret->s = BN_new();
if (ret->r == NULL || ret->s == NULL) {
- ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
s = ret->s;
- if ((ctx = BN_CTX_new()) == NULL
+ if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL
|| (m = BN_new()) == NULL) {
- ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -207,25 +246,25 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
if (8 * dgst_len > i)
dgst_len = (i + 7) / 8;
if (!BN_bin2bn(dgst, dgst_len, m)) {
- ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* If still too long, truncate remaining bits with a shift */
if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
- ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
do {
if (in_kinv == NULL || in_r == NULL) {
if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len)) {
- ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_ECDSA_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_ECDSA_LIB);
goto err;
}
ckinv = kinv;
} else {
ckinv = in_kinv;
if (BN_copy(ret->r, in_r) == NULL) {
- ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -239,11 +278,11 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
*/
if (!bn_to_mont_fixed_top(s, ret->r, group->mont_data, ctx)
|| !bn_mul_mont_fixed_top(s, s, priv_key, group->mont_data, ctx)) {
- ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
if (!bn_mod_add_fixed_top(s, s, m, order)) {
- ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/*
@@ -252,7 +291,7 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
*/
if (!bn_to_mont_fixed_top(s, s, group->mont_data, ctx)
|| !BN_mod_mul_montgomery(s, s, ckinv, group->mont_data, ctx)) {
- ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
@@ -262,7 +301,7 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
* generate new kinv and r values
*/
if (in_kinv != NULL && in_r != NULL) {
- ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_NEED_NEW_SETUP_VALUES);
+ ERR_raise(ERR_LIB_EC, EC_R_NEED_NEW_SETUP_VALUES);
goto err;
}
} else {
@@ -314,8 +353,8 @@ int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len,
return ret;
}
-int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
- const ECDSA_SIG *sig, EC_KEY *eckey)
+int ossl_ecdsa_simple_verify_sig(const unsigned char *dgst, int dgst_len,
+ const ECDSA_SIG *sig, EC_KEY *eckey)
{
int ret = -1, i;
BN_CTX *ctx;
@@ -328,18 +367,18 @@ int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
/* check input values */
if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL ||
(pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_MISSING_PARAMETERS);
+ ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS);
return -1;
}
if (!EC_KEY_can_sign(eckey)) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
+ ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
return -1;
}
- ctx = BN_CTX_new();
+ ctx = BN_CTX_new_ex(eckey->libctx);
if (ctx == NULL) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return -1;
}
BN_CTX_start(ctx);
@@ -348,26 +387,26 @@ int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
m = BN_CTX_get(ctx);
X = BN_CTX_get(ctx);
if (X == NULL) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
order = EC_GROUP_get0_order(group);
if (order == NULL) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) ||
BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_BAD_SIGNATURE);
+ ERR_raise(ERR_LIB_EC, EC_R_BAD_SIGNATURE);
ret = 0; /* signature is invalid */
goto err;
}
/* calculate tmp1 = inv(S) mod order */
- if (!ec_group_do_inverse_ord(group, u2, sig->s, ctx)) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
+ if (!ossl_ec_group_do_inverse_ord(group, u2, sig->s, ctx)) {
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* digest -> m */
@@ -378,41 +417,41 @@ int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
if (8 * dgst_len > i)
dgst_len = (i + 7) / 8;
if (!BN_bin2bn(dgst, dgst_len, m)) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* If still too long truncate remaining bits with a shift */
if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* u1 = m * tmp mod order */
if (!BN_mod_mul(u1, m, u2, order, ctx)) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* u2 = r * w mod q */
if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
if ((point = EC_POINT_new(group)) == NULL) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if (!EC_POINT_get_affine_coordinates(group, point, X, NULL, ctx)) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if (!BN_nnmod(u1, X, order, ctx)) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* if the signature is correct u1 is equal to sig->r */
diff --git a/crypto/ec/ecdsa_sign.c b/crypto/ec/ecdsa_sign.c
index dc79c8c8e3df..0c0748c84f87 100644
--- a/crypto/ec/ecdsa_sign.c
+++ b/crypto/ec/ecdsa_sign.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/ec.h>
#include "ec_local.h"
#include <openssl/err.h>
@@ -22,7 +28,7 @@ ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dlen,
{
if (eckey->meth->sign_sig != NULL)
return eckey->meth->sign_sig(dgst, dlen, kinv, rp, eckey);
- ECerr(EC_F_ECDSA_DO_SIGN_EX, EC_R_OPERATION_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED);
return NULL;
}
@@ -38,7 +44,7 @@ int ECDSA_sign_ex(int type, const unsigned char *dgst, int dlen,
{
if (eckey->meth->sign != NULL)
return eckey->meth->sign(type, dgst, dlen, sig, siglen, kinv, r, eckey);
- ECerr(EC_F_ECDSA_SIGN_EX, EC_R_OPERATION_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED);
return 0;
}
@@ -47,6 +53,6 @@ int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
{
if (eckey->meth->sign_setup != NULL)
return eckey->meth->sign_setup(eckey, ctx_in, kinvp, rp);
- ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_OPERATION_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED);
return 0;
}
diff --git a/crypto/ec/ecdsa_vrf.c b/crypto/ec/ecdsa_vrf.c
index ff597bdc143c..c148ecdb7cf6 100644
--- a/crypto/ec/ecdsa_vrf.c
+++ b/crypto/ec/ecdsa_vrf.c
@@ -1,12 +1,18 @@
/*
* Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/ec.h>
#include "ec_local.h"
#include <openssl/err.h>
@@ -22,7 +28,7 @@ int ECDSA_do_verify(const unsigned char *dgst, int dgst_len,
{
if (eckey->meth->verify_sig != NULL)
return eckey->meth->verify_sig(dgst, dgst_len, sig, eckey);
- ECerr(EC_F_ECDSA_DO_VERIFY, EC_R_OPERATION_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED);
return -1;
}
@@ -38,6 +44,6 @@ int ECDSA_verify(int type, const unsigned char *dgst, int dgst_len,
if (eckey->meth->verify != NULL)
return eckey->meth->verify(type, dgst, dgst_len, sigbuf, sig_len,
eckey);
- ECerr(EC_F_ECDSA_VERIFY, EC_R_OPERATION_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED);
return -1;
}
diff --git a/crypto/ec/eck_prn.c b/crypto/ec/eck_prn.c
index b538fadcb10c..96ced7c8be0d 100644
--- a/crypto/ec/eck_prn.c
+++ b/crypto/ec/eck_prn.c
@@ -1,27 +1,30 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/bn.h>
-#ifndef OPENSSL_NO_STDIO
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef OPENSSL_NO_STDIO
int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- ECerr(EC_F_ECPKPARAMETERS_PRINT_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
@@ -36,7 +39,7 @@ int EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off)
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- ECerr(EC_F_EC_KEY_PRINT_FP, ERR_R_BIO_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BIO_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
@@ -51,7 +54,7 @@ int ECParameters_print_fp(FILE *fp, const EC_KEY *x)
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- ECerr(EC_F_ECPARAMETERS_PRINT_FP, ERR_R_BIO_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BIO_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
@@ -59,7 +62,7 @@ int ECParameters_print_fp(FILE *fp, const EC_KEY *x)
BIO_free(b);
return ret;
}
-#endif
+#endif /* OPENSSL_NO_STDIO */
static int print_bin(BIO *fp, const char *str, const unsigned char *num,
size_t len, int off);
@@ -69,10 +72,11 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off)
int ret = 0, reason = ERR_R_BIO_LIB;
BN_CTX *ctx = NULL;
const EC_POINT *point = NULL;
- BIGNUM *p = NULL, *a = NULL, *b = NULL, *gen = NULL;
+ BIGNUM *p = NULL, *a = NULL, *b = NULL;
+ unsigned char *gen_buf = NULL;
const BIGNUM *order = NULL, *cofactor = NULL;
const unsigned char *seed;
- size_t seed_len = 0;
+ size_t seed_len = 0, gen_buf_len = 0;
static const char *gen_compressed = "Generator (compressed):";
static const char *gen_uncompressed = "Generator (uncompressed):";
@@ -112,10 +116,11 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off)
goto err;
}
} else {
+ const char *form_str;
/* explicit parameters */
int is_char_two = 0;
point_conversion_form_t form;
- int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(x));
+ int tmp_nid = EC_GROUP_get_field_type(x);
if (tmp_nid == NID_X9_62_characteristic_two_field)
is_char_two = 1;
@@ -144,7 +149,8 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off)
form = EC_GROUP_get_point_conversion_form(x);
- if ((gen = EC_POINT_point2bn(x, point, form, NULL, ctx)) == NULL) {
+ gen_buf_len = EC_POINT_point2buf(x, point, form, &gen_buf, ctx);
+ if (gen_buf_len == 0) {
reason = ERR_R_EC_LIB;
goto err;
}
@@ -185,22 +191,18 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off)
goto err;
if ((b != NULL) && !ASN1_bn_print(bp, "B: ", b, NULL, off))
goto err;
- if (form == POINT_CONVERSION_COMPRESSED) {
- if ((gen != NULL) && !ASN1_bn_print(bp, gen_compressed, gen,
- NULL, off))
- goto err;
- } else if (form == POINT_CONVERSION_UNCOMPRESSED) {
- if ((gen != NULL) && !ASN1_bn_print(bp, gen_uncompressed, gen,
- NULL, off))
- goto err;
- } else { /* form == POINT_CONVERSION_HYBRID */
- if ((gen != NULL) && !ASN1_bn_print(bp, gen_hybrid, gen,
- NULL, off))
- goto err;
- }
- if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order,
- NULL, off))
+ if (form == POINT_CONVERSION_COMPRESSED)
+ form_str = gen_compressed;
+ else if (form == POINT_CONVERSION_UNCOMPRESSED)
+ form_str = gen_uncompressed;
+ else
+ form_str = gen_hybrid;
+ if (gen_buf != NULL
+ && !print_bin(bp, form_str, gen_buf, gen_buf_len, off))
+ goto err;
+
+ if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order, NULL, off))
goto err;
if ((cofactor != NULL) && !ASN1_bn_print(bp, "Cofactor: ", cofactor,
NULL, off))
@@ -211,11 +213,11 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off)
ret = 1;
err:
if (!ret)
- ECerr(EC_F_ECPKPARAMETERS_PRINT, reason);
+ ERR_raise(ERR_LIB_EC, reason);
BN_free(p);
BN_free(a);
BN_free(b);
- BN_free(gen);
+ OPENSSL_clear_free(gen_buf, gen_buf_len);
BN_CTX_free(ctx);
return ret;
}
@@ -257,3 +259,4 @@ static int print_bin(BIO *fp, const char *name, const unsigned char *buf,
return 1;
}
+#endif /* OPENSSL_NO_DEPRECATED_3_0 */
diff --git a/crypto/ec/ecp_mont.c b/crypto/ec/ecp_mont.c
index bdc39d5efb0e..35b492453f57 100644
--- a/crypto/ec/ecp_mont.c
+++ b/crypto/ec/ecp_mont.c
@@ -1,13 +1,19 @@
/*
- * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/err.h>
#include "ec_local.h"
@@ -17,98 +23,99 @@ const EC_METHOD *EC_GFp_mont_method(void)
static const EC_METHOD ret = {
EC_FLAGS_DEFAULT_OCT,
NID_X9_62_prime_field,
- ec_GFp_mont_group_init,
- ec_GFp_mont_group_finish,
- ec_GFp_mont_group_clear_finish,
- ec_GFp_mont_group_copy,
- ec_GFp_mont_group_set_curve,
- ec_GFp_simple_group_get_curve,
- ec_GFp_simple_group_get_degree,
- ec_group_simple_order_bits,
- ec_GFp_simple_group_check_discriminant,
- ec_GFp_simple_point_init,
- ec_GFp_simple_point_finish,
- ec_GFp_simple_point_clear_finish,
- ec_GFp_simple_point_copy,
- ec_GFp_simple_point_set_to_infinity,
- ec_GFp_simple_set_Jprojective_coordinates_GFp,
- ec_GFp_simple_get_Jprojective_coordinates_GFp,
- ec_GFp_simple_point_set_affine_coordinates,
- ec_GFp_simple_point_get_affine_coordinates,
+ ossl_ec_GFp_mont_group_init,
+ ossl_ec_GFp_mont_group_finish,
+ ossl_ec_GFp_mont_group_clear_finish,
+ ossl_ec_GFp_mont_group_copy,
+ ossl_ec_GFp_mont_group_set_curve,
+ ossl_ec_GFp_simple_group_get_curve,
+ ossl_ec_GFp_simple_group_get_degree,
+ ossl_ec_group_simple_order_bits,
+ ossl_ec_GFp_simple_group_check_discriminant,
+ ossl_ec_GFp_simple_point_init,
+ ossl_ec_GFp_simple_point_finish,
+ ossl_ec_GFp_simple_point_clear_finish,
+ ossl_ec_GFp_simple_point_copy,
+ ossl_ec_GFp_simple_point_set_to_infinity,
+ ossl_ec_GFp_simple_point_set_affine_coordinates,
+ ossl_ec_GFp_simple_point_get_affine_coordinates,
0, 0, 0,
- ec_GFp_simple_add,
- ec_GFp_simple_dbl,
- ec_GFp_simple_invert,
- ec_GFp_simple_is_at_infinity,
- ec_GFp_simple_is_on_curve,
- ec_GFp_simple_cmp,
- ec_GFp_simple_make_affine,
- ec_GFp_simple_points_make_affine,
+ ossl_ec_GFp_simple_add,
+ ossl_ec_GFp_simple_dbl,
+ ossl_ec_GFp_simple_invert,
+ ossl_ec_GFp_simple_is_at_infinity,
+ ossl_ec_GFp_simple_is_on_curve,
+ ossl_ec_GFp_simple_cmp,
+ ossl_ec_GFp_simple_make_affine,
+ ossl_ec_GFp_simple_points_make_affine,
0 /* mul */ ,
0 /* precompute_mult */ ,
0 /* have_precompute_mult */ ,
- ec_GFp_mont_field_mul,
- ec_GFp_mont_field_sqr,
+ ossl_ec_GFp_mont_field_mul,
+ ossl_ec_GFp_mont_field_sqr,
0 /* field_div */ ,
- ec_GFp_mont_field_inv,
- ec_GFp_mont_field_encode,
- ec_GFp_mont_field_decode,
- ec_GFp_mont_field_set_to_one,
- ec_key_simple_priv2oct,
- ec_key_simple_oct2priv,
+ ossl_ec_GFp_mont_field_inv,
+ ossl_ec_GFp_mont_field_encode,
+ ossl_ec_GFp_mont_field_decode,
+ ossl_ec_GFp_mont_field_set_to_one,
+ ossl_ec_key_simple_priv2oct,
+ ossl_ec_key_simple_oct2priv,
0, /* set private */
- ec_key_simple_generate_key,
- ec_key_simple_check_key,
- ec_key_simple_generate_public_key,
+ ossl_ec_key_simple_generate_key,
+ ossl_ec_key_simple_check_key,
+ ossl_ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
- ecdh_simple_compute_key,
+ ossl_ecdh_simple_compute_key,
+ ossl_ecdsa_simple_sign_setup,
+ ossl_ecdsa_simple_sign_sig,
+ ossl_ecdsa_simple_verify_sig,
0, /* field_inverse_mod_ord */
- ec_GFp_simple_blind_coordinates,
- ec_GFp_simple_ladder_pre,
- ec_GFp_simple_ladder_step,
- ec_GFp_simple_ladder_post
+ ossl_ec_GFp_simple_blind_coordinates,
+ ossl_ec_GFp_simple_ladder_pre,
+ ossl_ec_GFp_simple_ladder_step,
+ ossl_ec_GFp_simple_ladder_post
};
return &ret;
}
-int ec_GFp_mont_group_init(EC_GROUP *group)
+int ossl_ec_GFp_mont_group_init(EC_GROUP *group)
{
int ok;
- ok = ec_GFp_simple_group_init(group);
+ ok = ossl_ec_GFp_simple_group_init(group);
group->field_data1 = NULL;
group->field_data2 = NULL;
return ok;
}
-void ec_GFp_mont_group_finish(EC_GROUP *group)
+void ossl_ec_GFp_mont_group_finish(EC_GROUP *group)
{
BN_MONT_CTX_free(group->field_data1);
group->field_data1 = NULL;
BN_free(group->field_data2);
group->field_data2 = NULL;
- ec_GFp_simple_group_finish(group);
+ ossl_ec_GFp_simple_group_finish(group);
}
-void ec_GFp_mont_group_clear_finish(EC_GROUP *group)
+void ossl_ec_GFp_mont_group_clear_finish(EC_GROUP *group)
{
BN_MONT_CTX_free(group->field_data1);
group->field_data1 = NULL;
BN_clear_free(group->field_data2);
group->field_data2 = NULL;
- ec_GFp_simple_group_clear_finish(group);
+ ossl_ec_GFp_simple_group_clear_finish(group);
}
-int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src)
+int ossl_ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src)
{
BN_MONT_CTX_free(dest->field_data1);
dest->field_data1 = NULL;
BN_clear_free(dest->field_data2);
dest->field_data2 = NULL;
- if (!ec_GFp_simple_group_copy(dest, src))
+ if (!ossl_ec_GFp_simple_group_copy(dest, src))
return 0;
if (src->field_data1 != NULL) {
@@ -132,8 +139,9 @@ int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src)
return 0;
}
-int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
- const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+int ossl_ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
+ const BIGNUM *a, const BIGNUM *b,
+ BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
BN_MONT_CTX *mont = NULL;
@@ -146,7 +154,7 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
group->field_data2 = NULL;
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
return 0;
}
@@ -155,7 +163,7 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
if (mont == NULL)
goto err;
if (!BN_MONT_CTX_set(mont, p, ctx)) {
- ECerr(EC_F_EC_GFP_MONT_GROUP_SET_CURVE, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
one = BN_new();
@@ -169,7 +177,7 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
group->field_data2 = one;
one = NULL;
- ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
+ ret = ossl_ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
if (!ret) {
BN_MONT_CTX_free(group->field_data1);
@@ -185,22 +193,22 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
return ret;
}
-int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
- const BIGNUM *b, BN_CTX *ctx)
+int ossl_ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *ctx)
{
if (group->field_data1 == NULL) {
- ECerr(EC_F_EC_GFP_MONT_FIELD_MUL, EC_R_NOT_INITIALIZED);
+ ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED);
return 0;
}
return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx);
}
-int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
- BN_CTX *ctx)
+int ossl_ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *ctx)
{
if (group->field_data1 == NULL) {
- ECerr(EC_F_EC_GFP_MONT_FIELD_SQR, EC_R_NOT_INITIALIZED);
+ ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED);
return 0;
}
@@ -212,8 +220,8 @@ int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
* If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error.
* We have a Mont structure, so SCA hardening is FLT inversion.
*/
-int ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
- BN_CTX *ctx)
+int ossl_ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *ctx)
{
BIGNUM *e = NULL;
BN_CTX *new_ctx = NULL;
@@ -222,7 +230,8 @@ int ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
if (group->field_data1 == NULL)
return 0;
- if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL)
+ if (ctx == NULL
+ && (ctx = new_ctx = BN_CTX_secure_new_ex(group->libctx)) == NULL)
return 0;
BN_CTX_start(ctx);
@@ -243,7 +252,7 @@ int ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
/* throw an error on zero */
if (BN_is_zero(r)) {
- ECerr(EC_F_EC_GFP_MONT_FIELD_INV, EC_R_CANNOT_INVERT);
+ ERR_raise(ERR_LIB_EC, EC_R_CANNOT_INVERT);
goto err;
}
@@ -255,33 +264,33 @@ int ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
return ret;
}
-int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r,
- const BIGNUM *a, BN_CTX *ctx)
+int ossl_ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r,
+ const BIGNUM *a, BN_CTX *ctx)
{
if (group->field_data1 == NULL) {
- ECerr(EC_F_EC_GFP_MONT_FIELD_ENCODE, EC_R_NOT_INITIALIZED);
+ ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED);
return 0;
}
return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx);
}
-int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r,
- const BIGNUM *a, BN_CTX *ctx)
+int ossl_ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r,
+ const BIGNUM *a, BN_CTX *ctx)
{
if (group->field_data1 == NULL) {
- ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED);
+ ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED);
return 0;
}
return BN_from_montgomery(r, a, group->field_data1, ctx);
}
-int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r,
- BN_CTX *ctx)
+int ossl_ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r,
+ BN_CTX *ctx)
{
if (group->field_data2 == NULL) {
- ECerr(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, EC_R_NOT_INITIALIZED);
+ ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED);
return 0;
}
diff --git a/crypto/ec/ecp_nist.c b/crypto/ec/ecp_nist.c
index 9fd01279a891..3efd43e64c75 100644
--- a/crypto/ec/ecp_nist.c
+++ b/crypto/ec/ecp_nist.c
@@ -1,13 +1,19 @@
/*
- * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <limits.h>
#include <openssl/err.h>
@@ -19,77 +25,79 @@ const EC_METHOD *EC_GFp_nist_method(void)
static const EC_METHOD ret = {
EC_FLAGS_DEFAULT_OCT,
NID_X9_62_prime_field,
- ec_GFp_simple_group_init,
- ec_GFp_simple_group_finish,
- ec_GFp_simple_group_clear_finish,
- ec_GFp_nist_group_copy,
- ec_GFp_nist_group_set_curve,
- ec_GFp_simple_group_get_curve,
- ec_GFp_simple_group_get_degree,
- ec_group_simple_order_bits,
- ec_GFp_simple_group_check_discriminant,
- ec_GFp_simple_point_init,
- ec_GFp_simple_point_finish,
- ec_GFp_simple_point_clear_finish,
- ec_GFp_simple_point_copy,
- ec_GFp_simple_point_set_to_infinity,
- ec_GFp_simple_set_Jprojective_coordinates_GFp,
- ec_GFp_simple_get_Jprojective_coordinates_GFp,
- ec_GFp_simple_point_set_affine_coordinates,
- ec_GFp_simple_point_get_affine_coordinates,
+ ossl_ec_GFp_simple_group_init,
+ ossl_ec_GFp_simple_group_finish,
+ ossl_ec_GFp_simple_group_clear_finish,
+ ossl_ec_GFp_nist_group_copy,
+ ossl_ec_GFp_nist_group_set_curve,
+ ossl_ec_GFp_simple_group_get_curve,
+ ossl_ec_GFp_simple_group_get_degree,
+ ossl_ec_group_simple_order_bits,
+ ossl_ec_GFp_simple_group_check_discriminant,
+ ossl_ec_GFp_simple_point_init,
+ ossl_ec_GFp_simple_point_finish,
+ ossl_ec_GFp_simple_point_clear_finish,
+ ossl_ec_GFp_simple_point_copy,
+ ossl_ec_GFp_simple_point_set_to_infinity,
+ ossl_ec_GFp_simple_point_set_affine_coordinates,
+ ossl_ec_GFp_simple_point_get_affine_coordinates,
0, 0, 0,
- ec_GFp_simple_add,
- ec_GFp_simple_dbl,
- ec_GFp_simple_invert,
- ec_GFp_simple_is_at_infinity,
- ec_GFp_simple_is_on_curve,
- ec_GFp_simple_cmp,
- ec_GFp_simple_make_affine,
- ec_GFp_simple_points_make_affine,
+ ossl_ec_GFp_simple_add,
+ ossl_ec_GFp_simple_dbl,
+ ossl_ec_GFp_simple_invert,
+ ossl_ec_GFp_simple_is_at_infinity,
+ ossl_ec_GFp_simple_is_on_curve,
+ ossl_ec_GFp_simple_cmp,
+ ossl_ec_GFp_simple_make_affine,
+ ossl_ec_GFp_simple_points_make_affine,
0 /* mul */ ,
0 /* precompute_mult */ ,
0 /* have_precompute_mult */ ,
- ec_GFp_nist_field_mul,
- ec_GFp_nist_field_sqr,
+ ossl_ec_GFp_nist_field_mul,
+ ossl_ec_GFp_nist_field_sqr,
0 /* field_div */ ,
- ec_GFp_simple_field_inv,
+ ossl_ec_GFp_simple_field_inv,
0 /* field_encode */ ,
0 /* field_decode */ ,
0, /* field_set_to_one */
- ec_key_simple_priv2oct,
- ec_key_simple_oct2priv,
+ ossl_ec_key_simple_priv2oct,
+ ossl_ec_key_simple_oct2priv,
0, /* set private */
- ec_key_simple_generate_key,
- ec_key_simple_check_key,
- ec_key_simple_generate_public_key,
+ ossl_ec_key_simple_generate_key,
+ ossl_ec_key_simple_check_key,
+ ossl_ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
- ecdh_simple_compute_key,
+ ossl_ecdh_simple_compute_key,
+ ossl_ecdsa_simple_sign_setup,
+ ossl_ecdsa_simple_sign_sig,
+ ossl_ecdsa_simple_verify_sig,
0, /* field_inverse_mod_ord */
- ec_GFp_simple_blind_coordinates,
- ec_GFp_simple_ladder_pre,
- ec_GFp_simple_ladder_step,
- ec_GFp_simple_ladder_post
+ ossl_ec_GFp_simple_blind_coordinates,
+ ossl_ec_GFp_simple_ladder_pre,
+ ossl_ec_GFp_simple_ladder_step,
+ ossl_ec_GFp_simple_ladder_post
};
return &ret;
}
-int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src)
+int ossl_ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src)
{
dest->field_mod_func = src->field_mod_func;
- return ec_GFp_simple_group_copy(dest, src);
+ return ossl_ec_GFp_simple_group_copy(dest, src);
}
-int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p,
- const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+int ossl_ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p,
+ const BIGNUM *a, const BIGNUM *b,
+ BN_CTX *ctx)
{
int ret = 0;
BN_CTX *new_ctx = NULL;
if (ctx == NULL)
- if ((ctx = new_ctx = BN_CTX_new()) == NULL)
+ if ((ctx = new_ctx = BN_CTX_new_ex(group->libctx)) == NULL)
return 0;
BN_CTX_start(ctx);
@@ -105,11 +113,11 @@ int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p,
else if (BN_ucmp(BN_get0_nist_prime_521(), p) == 0)
group->field_mod_func = BN_nist_mod_521;
else {
- ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE, EC_R_NOT_A_NIST_PRIME);
+ ERR_raise(ERR_LIB_EC, EC_R_NOT_A_NIST_PRIME);
goto err;
}
- ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
+ ret = ossl_ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
err:
BN_CTX_end(ctx);
@@ -117,18 +125,18 @@ int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p,
return ret;
}
-int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
- const BIGNUM *b, BN_CTX *ctx)
+int ossl_ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *ctx)
{
int ret = 0;
BN_CTX *ctx_new = NULL;
if (!group || !r || !a || !b) {
- ECerr(EC_F_EC_GFP_NIST_FIELD_MUL, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
goto err;
}
if (!ctx)
- if ((ctx_new = ctx = BN_CTX_new()) == NULL)
+ if ((ctx_new = ctx = BN_CTX_new_ex(group->libctx)) == NULL)
goto err;
if (!BN_mul(r, a, b, ctx))
@@ -142,18 +150,18 @@ int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
return ret;
}
-int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
- BN_CTX *ctx)
+int ossl_ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *ctx)
{
int ret = 0;
BN_CTX *ctx_new = NULL;
if (!group || !r || !a) {
- ECerr(EC_F_EC_GFP_NIST_FIELD_SQR, EC_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, EC_R_PASSED_NULL_PARAMETER);
goto err;
}
if (!ctx)
- if ((ctx_new = ctx = BN_CTX_new()) == NULL)
+ if ((ctx_new = ctx = BN_CTX_new_ex(group->libctx)) == NULL)
goto err;
if (!BN_sqr(r, a, ctx))
diff --git a/crypto/ec/ecp_nistp224.c b/crypto/ec/ecp_nistp224.c
index 6f7d66c8bea4..5ab0dd7bef4f 100644
--- a/crypto/ec/ecp_nistp224.c
+++ b/crypto/ec/ecp_nistp224.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2010-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -24,6 +24,12 @@
*/
/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+/*
* A 64-bit implementation of the NIST P-224 elliptic curve point multiplication
*
* Inspired by Daniel J. Bernstein's public domain nistp224 implementation
@@ -31,22 +37,17 @@
*/
#include <openssl/opensslconf.h>
-#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128
-NON_EMPTY_TRANSLATION_UNIT
-#else
-
-# include <stdint.h>
-# include <string.h>
-# include <openssl/err.h>
-# include "ec_local.h"
-
-# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16
- /* even with gcc, the typedef won't work for 32-bit platforms */
-typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit
- * platforms */
-# else
-# error "Your compiler doesn't appear to support 128-bit integer types"
-# endif
+
+#include <stdint.h>
+#include <string.h>
+#include <openssl/err.h>
+#include "ec_local.h"
+
+#include "internal/numbers.h"
+
+#ifndef INT128_MAX
+# error "Your compiler doesn't appear to support 128-bit integer types"
+#endif
typedef uint8_t u8;
typedef uint64_t u64;
@@ -245,54 +246,55 @@ const EC_METHOD *EC_GFp_nistp224_method(void)
static const EC_METHOD ret = {
EC_FLAGS_DEFAULT_OCT,
NID_X9_62_prime_field,
- ec_GFp_nistp224_group_init,
- ec_GFp_simple_group_finish,
- ec_GFp_simple_group_clear_finish,
- ec_GFp_nist_group_copy,
- ec_GFp_nistp224_group_set_curve,
- ec_GFp_simple_group_get_curve,
- ec_GFp_simple_group_get_degree,
- ec_group_simple_order_bits,
- ec_GFp_simple_group_check_discriminant,
- ec_GFp_simple_point_init,
- ec_GFp_simple_point_finish,
- ec_GFp_simple_point_clear_finish,
- ec_GFp_simple_point_copy,
- ec_GFp_simple_point_set_to_infinity,
- ec_GFp_simple_set_Jprojective_coordinates_GFp,
- ec_GFp_simple_get_Jprojective_coordinates_GFp,
- ec_GFp_simple_point_set_affine_coordinates,
- ec_GFp_nistp224_point_get_affine_coordinates,
+ ossl_ec_GFp_nistp224_group_init,
+ ossl_ec_GFp_simple_group_finish,
+ ossl_ec_GFp_simple_group_clear_finish,
+ ossl_ec_GFp_nist_group_copy,
+ ossl_ec_GFp_nistp224_group_set_curve,
+ ossl_ec_GFp_simple_group_get_curve,
+ ossl_ec_GFp_simple_group_get_degree,
+ ossl_ec_group_simple_order_bits,
+ ossl_ec_GFp_simple_group_check_discriminant,
+ ossl_ec_GFp_simple_point_init,
+ ossl_ec_GFp_simple_point_finish,
+ ossl_ec_GFp_simple_point_clear_finish,
+ ossl_ec_GFp_simple_point_copy,
+ ossl_ec_GFp_simple_point_set_to_infinity,
+ ossl_ec_GFp_simple_point_set_affine_coordinates,
+ ossl_ec_GFp_nistp224_point_get_affine_coordinates,
0 /* point_set_compressed_coordinates */ ,
0 /* point2oct */ ,
0 /* oct2point */ ,
- ec_GFp_simple_add,
- ec_GFp_simple_dbl,
- ec_GFp_simple_invert,
- ec_GFp_simple_is_at_infinity,
- ec_GFp_simple_is_on_curve,
- ec_GFp_simple_cmp,
- ec_GFp_simple_make_affine,
- ec_GFp_simple_points_make_affine,
- ec_GFp_nistp224_points_mul,
- ec_GFp_nistp224_precompute_mult,
- ec_GFp_nistp224_have_precompute_mult,
- ec_GFp_nist_field_mul,
- ec_GFp_nist_field_sqr,
+ ossl_ec_GFp_simple_add,
+ ossl_ec_GFp_simple_dbl,
+ ossl_ec_GFp_simple_invert,
+ ossl_ec_GFp_simple_is_at_infinity,
+ ossl_ec_GFp_simple_is_on_curve,
+ ossl_ec_GFp_simple_cmp,
+ ossl_ec_GFp_simple_make_affine,
+ ossl_ec_GFp_simple_points_make_affine,
+ ossl_ec_GFp_nistp224_points_mul,
+ ossl_ec_GFp_nistp224_precompute_mult,
+ ossl_ec_GFp_nistp224_have_precompute_mult,
+ ossl_ec_GFp_nist_field_mul,
+ ossl_ec_GFp_nist_field_sqr,
0 /* field_div */ ,
- ec_GFp_simple_field_inv,
+ ossl_ec_GFp_simple_field_inv,
0 /* field_encode */ ,
0 /* field_decode */ ,
0, /* field_set_to_one */
- ec_key_simple_priv2oct,
- ec_key_simple_oct2priv,
+ ossl_ec_key_simple_priv2oct,
+ ossl_ec_key_simple_oct2priv,
0, /* set private */
- ec_key_simple_generate_key,
- ec_key_simple_check_key,
- ec_key_simple_generate_public_key,
+ ossl_ec_key_simple_generate_key,
+ ossl_ec_key_simple_check_key,
+ ossl_ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
- ecdh_simple_compute_key,
+ ossl_ecdh_simple_compute_key,
+ ossl_ecdsa_simple_sign_setup,
+ ossl_ecdsa_simple_sign_sig,
+ ossl_ecdsa_simple_verify_sig,
0, /* field_inverse_mod_ord */
0, /* blind_coordinates */
0, /* ladder_pre */
@@ -332,12 +334,12 @@ static int BN_to_felem(felem out, const BIGNUM *bn)
int num_bytes;
if (BN_is_negative(bn)) {
- ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
+ ERR_raise(ERR_LIB_EC, EC_R_BIGNUM_OUT_OF_RANGE);
return 0;
}
num_bytes = BN_bn2lebinpad(bn, b_out, sizeof(b_out));
if (num_bytes < 0) {
- ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
+ ERR_raise(ERR_LIB_EC, EC_R_BIGNUM_OUT_OF_RANGE);
return 0;
}
bin28_to_felem(out, b_out);
@@ -663,7 +665,9 @@ static void felem_contract(felem out, const felem in)
*/
static void felem_neg(felem out, const felem in)
{
- widefelem tmp = {0};
+ widefelem tmp;
+
+ memset(tmp, 0, sizeof(tmp));
felem_diff_128_64(tmp, in);
felem_reduce(out, tmp);
}
@@ -1201,7 +1205,7 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
bits |= get_bit(scalars[num], i + 1) << 2;
bits |= get_bit(scalars[num], i) << 1;
bits |= get_bit(scalars[num], i - 1);
- ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
+ ossl_ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
/* select the point to add or subtract */
select_point(digit, 17, pre_comp[num], tmp);
@@ -1235,7 +1239,7 @@ static NISTP224_PRE_COMP *nistp224_pre_comp_new(void)
NISTP224_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret));
if (!ret) {
- ECerr(EC_F_NISTP224_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return ret;
}
@@ -1243,7 +1247,7 @@ static NISTP224_PRE_COMP *nistp224_pre_comp_new(void)
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
- ECerr(EC_F_NISTP224_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
@@ -1266,7 +1270,7 @@ void EC_nistp224_pre_comp_free(NISTP224_PRE_COMP *p)
return;
CRYPTO_DOWN_REF(&p->references, &i, p->lock);
- REF_PRINT_COUNT("EC_nistp224", x);
+ REF_PRINT_COUNT("EC_nistp224", p);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
@@ -1280,25 +1284,29 @@ void EC_nistp224_pre_comp_free(NISTP224_PRE_COMP *p)
* OPENSSL EC_METHOD FUNCTIONS
*/
-int ec_GFp_nistp224_group_init(EC_GROUP *group)
+int ossl_ec_GFp_nistp224_group_init(EC_GROUP *group)
{
int ret;
- ret = ec_GFp_simple_group_init(group);
+ ret = ossl_ec_GFp_simple_group_init(group);
group->a_is_minus3 = 1;
return ret;
}
-int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p,
- const BIGNUM *a, const BIGNUM *b,
- BN_CTX *ctx)
+int ossl_ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p,
+ const BIGNUM *a, const BIGNUM *b,
+ BN_CTX *ctx)
{
int ret = 0;
- BN_CTX *new_ctx = NULL;
BIGNUM *curve_p, *curve_a, *curve_b;
+#ifndef FIPS_MODULE
+ BN_CTX *new_ctx = NULL;
if (ctx == NULL)
- if ((ctx = new_ctx = BN_CTX_new()) == NULL)
- return 0;
+ ctx = new_ctx = BN_CTX_new();
+#endif
+ if (ctx == NULL)
+ return 0;
+
BN_CTX_start(ctx);
curve_p = BN_CTX_get(ctx);
curve_a = BN_CTX_get(ctx);
@@ -1309,15 +1317,16 @@ int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p,
BN_bin2bn(nistp224_curve_params[1], sizeof(felem_bytearray), curve_a);
BN_bin2bn(nistp224_curve_params[2], sizeof(felem_bytearray), curve_b);
if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || (BN_cmp(curve_b, b))) {
- ECerr(EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE,
- EC_R_WRONG_CURVE_PARAMETERS);
+ ERR_raise(ERR_LIB_EC, EC_R_WRONG_CURVE_PARAMETERS);
goto err;
}
group->field_mod_func = BN_nist_mod_224;
- ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
+ ret = ossl_ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
err:
BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
return ret;
}
@@ -1325,17 +1334,16 @@ int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p,
* Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') =
* (X/Z^2, Y/Z^3)
*/
-int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
- const EC_POINT *point,
- BIGNUM *x, BIGNUM *y,
- BN_CTX *ctx)
+int ossl_ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx)
{
felem z1, z2, x_in, y_in, x_out, y_out;
widefelem tmp;
if (EC_POINT_is_at_infinity(group, point)) {
- ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES,
- EC_R_POINT_AT_INFINITY);
+ ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY);
return 0;
}
if ((!BN_to_felem(x_in, point->X)) || (!BN_to_felem(y_in, point->Y)) ||
@@ -1349,8 +1357,7 @@ int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
felem_contract(x_out, x_in);
if (x != NULL) {
if (!felem_to_BN(x, x_out)) {
- ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES,
- ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
return 0;
}
}
@@ -1361,8 +1368,7 @@ int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
felem_contract(y_out, y_in);
if (y != NULL) {
if (!felem_to_BN(y, y_out)) {
- ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES,
- ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
return 0;
}
}
@@ -1376,36 +1382,36 @@ static void make_points_affine(size_t num, felem points[ /* num */ ][3],
* Runs in constant time, unless an input is the point at infinity (which
* normally shouldn't happen).
*/
- ec_GFp_nistp_points_make_affine_internal(num,
- points,
- sizeof(felem),
- tmp_felems,
- (void (*)(void *))felem_one,
- felem_is_zero_int,
- (void (*)(void *, const void *))
- felem_assign,
- (void (*)(void *, const void *))
- felem_square_reduce, (void (*)
- (void *,
- const void
- *,
- const void
- *))
- felem_mul_reduce,
- (void (*)(void *, const void *))
- felem_inv,
- (void (*)(void *, const void *))
- felem_contract);
+ ossl_ec_GFp_nistp_points_make_affine_internal(num,
+ points,
+ sizeof(felem),
+ tmp_felems,
+ (void (*)(void *))felem_one,
+ felem_is_zero_int,
+ (void (*)(void *, const void *))
+ felem_assign,
+ (void (*)(void *, const void *))
+ felem_square_reduce, (void (*)
+ (void *,
+ const void
+ *,
+ const void
+ *))
+ felem_mul_reduce,
+ (void (*)(void *, const void *))
+ felem_inv,
+ (void (*)(void *, const void *))
+ felem_contract);
}
/*
* Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL
* values Result is stored in r (r can equal one of the inputs).
*/
-int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
- const BIGNUM *scalar, size_t num,
- const EC_POINT *points[],
- const BIGNUM *scalars[], BN_CTX *ctx)
+int ossl_ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
+ const BIGNUM *scalar, size_t num,
+ const EC_POINT *points[],
+ const BIGNUM *scalars[], BN_CTX *ctx)
{
int ret = 0;
int j;
@@ -1449,12 +1455,12 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
if (!felem_to_BN(x, g_pre_comp[0][1][0]) ||
!felem_to_BN(y, g_pre_comp[0][1][1]) ||
!felem_to_BN(z, g_pre_comp[0][1][2])) {
- ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
- if (!EC_POINT_set_Jprojective_coordinates_GFp(group,
- generator, x, y, z,
- ctx))
+ if (!ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group,
+ generator,
+ x, y, z, ctx))
goto err;
if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
/* precomputation matches generator */
@@ -1482,7 +1488,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
OPENSSL_malloc(sizeof(felem) * (num_points * 17 + 1));
if ((secrets == NULL) || (pre_comp == NULL)
|| (mixed && (tmp_felems == NULL))) {
- ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -1509,7 +1515,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
* constant-timeness
*/
if (!BN_nnmod(tmp_scalar, p_scalar, group->order, ctx)) {
- ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
num_bytes = BN_bn2lebinpad(tmp_scalar,
@@ -1519,7 +1525,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
secrets[i], sizeof(secrets[i]));
}
if (num_bytes < 0) {
- ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* precompute multiples */
@@ -1561,7 +1567,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
* constant-timeness
*/
if (!BN_nnmod(tmp_scalar, scalar, group->order, ctx)) {
- ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
num_bytes = BN_bn2lebinpad(tmp_scalar, g_secret, sizeof(g_secret));
@@ -1585,10 +1591,11 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
felem_contract(z_in, z_out);
if ((!felem_to_BN(x, x_in)) || (!felem_to_BN(y, y_in)) ||
(!felem_to_BN(z, z_in))) {
- ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
- ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx);
+ ret = ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, r, x, y, z,
+ ctx);
err:
BN_CTX_end(ctx);
@@ -1599,21 +1606,28 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
return ret;
}
-int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
+int ossl_ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
{
int ret = 0;
NISTP224_PRE_COMP *pre = NULL;
int i, j;
- BN_CTX *new_ctx = NULL;
BIGNUM *x, *y;
EC_POINT *generator = NULL;
felem tmp_felems[32];
+#ifndef FIPS_MODULE
+ BN_CTX *new_ctx = NULL;
+#endif
/* throw away old precomputation */
EC_pre_comp_free(group);
+
+#ifndef FIPS_MODULE
if (ctx == NULL)
- if ((ctx = new_ctx = BN_CTX_new()) == NULL)
- return 0;
+ ctx = new_ctx = BN_CTX_new();
+#endif
+ if (ctx == NULL)
+ return 0;
+
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
@@ -1721,14 +1735,14 @@ int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
err:
BN_CTX_end(ctx);
EC_POINT_free(generator);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
EC_nistp224_pre_comp_free(pre);
return ret;
}
-int ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group)
+int ossl_ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group)
{
return HAVEPRECOMP(group, nistp224);
}
-
-#endif
diff --git a/crypto/ec/ecp_nistp256.c b/crypto/ec/ecp_nistp256.c
index e23e9d2a0b34..4a55f925c465 100644
--- a/crypto/ec/ecp_nistp256.c
+++ b/crypto/ec/ecp_nistp256.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -24,6 +24,12 @@
*/
/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+/*
* A 64-bit implementation of the NIST P-256 elliptic curve point multiplication
*
* OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c.
@@ -32,23 +38,17 @@
*/
#include <openssl/opensslconf.h>
-#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128
-NON_EMPTY_TRANSLATION_UNIT
-#else
-
-# include <stdint.h>
-# include <string.h>
-# include <openssl/err.h>
-# include "ec_local.h"
-
-# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16
- /* even with gcc, the typedef won't work for 32-bit platforms */
-typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit
- * platforms */
-typedef __int128_t int128_t;
-# else
-# error "Your compiler doesn't appear to support 128-bit integer types"
-# endif
+
+#include <stdint.h>
+#include <string.h>
+#include <openssl/err.h>
+#include "ec_local.h"
+
+#include "internal/numbers.h"
+
+#ifndef INT128_MAX
+# error "Your compiler doesn't appear to support 128-bit integer types"
+#endif
typedef uint8_t u8;
typedef uint32_t u32;
@@ -56,7 +56,7 @@ typedef uint64_t u64;
/*
* The underlying field. P256 operates over GF(2^256-2^224+2^192+2^96-1). We
- * can serialise an element of this field into 32 bytes. We call this an
+ * can serialize an element of this field into 32 bytes. We call this an
* felem_bytearray.
*/
@@ -110,7 +110,7 @@ static const felem_bytearray nistp256_curve_params[5] = {
* values are used as intermediate values before multiplication.
*/
-# define NLIMBS 4
+#define NLIMBS 4
typedef uint128_t limb;
typedef limb felem[NLIMBS];
@@ -135,7 +135,7 @@ static void bin32_to_felem(felem out, const u8 in[32])
}
/*
- * smallfelem_to_bin32 takes a smallfelem and serialises into a little
+ * smallfelem_to_bin32 takes a smallfelem and serializes into a little
* endian, 32 byte array. This assumes that the CPU is little-endian.
*/
static void smallfelem_to_bin32(u8 out[32], const smallfelem in)
@@ -153,12 +153,12 @@ static int BN_to_felem(felem out, const BIGNUM *bn)
int num_bytes;
if (BN_is_negative(bn)) {
- ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
+ ERR_raise(ERR_LIB_EC, EC_R_BIGNUM_OUT_OF_RANGE);
return 0;
}
num_bytes = BN_bn2lebinpad(bn, b_out, sizeof(b_out));
if (num_bytes < 0) {
- ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
+ ERR_raise(ERR_LIB_EC, EC_R_BIGNUM_OUT_OF_RANGE);
return 0;
}
bin32_to_felem(out, b_out);
@@ -242,9 +242,9 @@ static void longfelem_scalar(longfelem out, const u64 scalar)
out[7] *= scalar;
}
-# define two105m41m9 (((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9)
-# define two105 (((limb)1) << 105)
-# define two105m41p9 (((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9)
+#define two105m41m9 (((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9)
+#define two105 (((limb)1) << 105)
+#define two105m41p9 (((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9)
/* zero105 is 0 mod p */
static const felem zero105 =
@@ -287,9 +287,9 @@ static void felem_diff(felem out, const felem in)
out[3] -= in[3];
}
-# define two107m43m11 (((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11)
-# define two107 (((limb)1) << 107)
-# define two107m43p11 (((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11)
+#define two107m43m11 (((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11)
+#define two107 (((limb)1) << 107)
+#define two107m43p11 (((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11)
/* zero107 is 0 mod p */
static const felem zero107 =
@@ -358,10 +358,10 @@ static void longfelem_diff(longfelem out, const longfelem in)
out[7] -= in[7];
}
-# define two64m0 (((limb)1) << 64) - 1
-# define two110p32m0 (((limb)1) << 110) + (((limb)1) << 32) - 1
-# define two64m46 (((limb)1) << 64) - (((limb)1) << 46)
-# define two64m32 (((limb)1) << 64) - (((limb)1) << 32)
+#define two64m0 (((limb)1) << 64) - 1
+#define two110p32m0 (((limb)1) << 110) + (((limb)1) << 32) - 1
+#define two64m46 (((limb)1) << 64) - (((limb)1) << 46)
+#define two64m32 (((limb)1) << 64) - (((limb)1) << 32)
/* zero110 is 0 mod p */
static const felem zero110 = { two64m0, two110p32m0, two64m46, two64m32 };
@@ -711,9 +711,9 @@ static void felem_small_mul(longfelem out, const smallfelem small1,
smallfelem_mul(out, small1, small2);
}
-# define two100m36m4 (((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4)
-# define two100 (((limb)1) << 100)
-# define two100m36p4 (((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4)
+#define two100m36m4 (((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4)
+#define two100 (((limb)1) << 100)
+#define two100m36p4 (((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4)
/* zero100 is 0 mod p */
static const felem zero100 =
{ two100m36m4, two100, two100m36p4, two100m36p4 };
@@ -1740,7 +1740,7 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
bits |= get_bit(scalars[num], i + 1) << 2;
bits |= get_bit(scalars[num], i) << 1;
bits |= get_bit(scalars[num], i - 1);
- ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
+ ossl_ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
/*
* select the point to add or subtract, in constant time
@@ -1781,54 +1781,55 @@ const EC_METHOD *EC_GFp_nistp256_method(void)
static const EC_METHOD ret = {
EC_FLAGS_DEFAULT_OCT,
NID_X9_62_prime_field,
- ec_GFp_nistp256_group_init,
- ec_GFp_simple_group_finish,
- ec_GFp_simple_group_clear_finish,
- ec_GFp_nist_group_copy,
- ec_GFp_nistp256_group_set_curve,
- ec_GFp_simple_group_get_curve,
- ec_GFp_simple_group_get_degree,
- ec_group_simple_order_bits,
- ec_GFp_simple_group_check_discriminant,
- ec_GFp_simple_point_init,
- ec_GFp_simple_point_finish,
- ec_GFp_simple_point_clear_finish,
- ec_GFp_simple_point_copy,
- ec_GFp_simple_point_set_to_infinity,
- ec_GFp_simple_set_Jprojective_coordinates_GFp,
- ec_GFp_simple_get_Jprojective_coordinates_GFp,
- ec_GFp_simple_point_set_affine_coordinates,
- ec_GFp_nistp256_point_get_affine_coordinates,
+ ossl_ec_GFp_nistp256_group_init,
+ ossl_ec_GFp_simple_group_finish,
+ ossl_ec_GFp_simple_group_clear_finish,
+ ossl_ec_GFp_nist_group_copy,
+ ossl_ec_GFp_nistp256_group_set_curve,
+ ossl_ec_GFp_simple_group_get_curve,
+ ossl_ec_GFp_simple_group_get_degree,
+ ossl_ec_group_simple_order_bits,
+ ossl_ec_GFp_simple_group_check_discriminant,
+ ossl_ec_GFp_simple_point_init,
+ ossl_ec_GFp_simple_point_finish,
+ ossl_ec_GFp_simple_point_clear_finish,
+ ossl_ec_GFp_simple_point_copy,
+ ossl_ec_GFp_simple_point_set_to_infinity,
+ ossl_ec_GFp_simple_point_set_affine_coordinates,
+ ossl_ec_GFp_nistp256_point_get_affine_coordinates,
0 /* point_set_compressed_coordinates */ ,
0 /* point2oct */ ,
0 /* oct2point */ ,
- ec_GFp_simple_add,
- ec_GFp_simple_dbl,
- ec_GFp_simple_invert,
- ec_GFp_simple_is_at_infinity,
- ec_GFp_simple_is_on_curve,
- ec_GFp_simple_cmp,
- ec_GFp_simple_make_affine,
- ec_GFp_simple_points_make_affine,
- ec_GFp_nistp256_points_mul,
- ec_GFp_nistp256_precompute_mult,
- ec_GFp_nistp256_have_precompute_mult,
- ec_GFp_nist_field_mul,
- ec_GFp_nist_field_sqr,
+ ossl_ec_GFp_simple_add,
+ ossl_ec_GFp_simple_dbl,
+ ossl_ec_GFp_simple_invert,
+ ossl_ec_GFp_simple_is_at_infinity,
+ ossl_ec_GFp_simple_is_on_curve,
+ ossl_ec_GFp_simple_cmp,
+ ossl_ec_GFp_simple_make_affine,
+ ossl_ec_GFp_simple_points_make_affine,
+ ossl_ec_GFp_nistp256_points_mul,
+ ossl_ec_GFp_nistp256_precompute_mult,
+ ossl_ec_GFp_nistp256_have_precompute_mult,
+ ossl_ec_GFp_nist_field_mul,
+ ossl_ec_GFp_nist_field_sqr,
0 /* field_div */ ,
- ec_GFp_simple_field_inv,
+ ossl_ec_GFp_simple_field_inv,
0 /* field_encode */ ,
0 /* field_decode */ ,
0, /* field_set_to_one */
- ec_key_simple_priv2oct,
- ec_key_simple_oct2priv,
+ ossl_ec_key_simple_priv2oct,
+ ossl_ec_key_simple_oct2priv,
0, /* set private */
- ec_key_simple_generate_key,
- ec_key_simple_check_key,
- ec_key_simple_generate_public_key,
+ ossl_ec_key_simple_generate_key,
+ ossl_ec_key_simple_check_key,
+ ossl_ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
- ecdh_simple_compute_key,
+ ossl_ecdh_simple_compute_key,
+ ossl_ecdsa_simple_sign_setup,
+ ossl_ecdsa_simple_sign_sig,
+ ossl_ecdsa_simple_verify_sig,
0, /* field_inverse_mod_ord */
0, /* blind_coordinates */
0, /* ladder_pre */
@@ -1849,7 +1850,7 @@ static NISTP256_PRE_COMP *nistp256_pre_comp_new(void)
NISTP256_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- ECerr(EC_F_NISTP256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return ret;
}
@@ -1857,7 +1858,7 @@ static NISTP256_PRE_COMP *nistp256_pre_comp_new(void)
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
- ECerr(EC_F_NISTP256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
@@ -1880,7 +1881,7 @@ void EC_nistp256_pre_comp_free(NISTP256_PRE_COMP *pre)
return;
CRYPTO_DOWN_REF(&pre->references, &i, pre->lock);
- REF_PRINT_COUNT("EC_nistp256", x);
+ REF_PRINT_COUNT("EC_nistp256", pre);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
@@ -1894,25 +1895,29 @@ void EC_nistp256_pre_comp_free(NISTP256_PRE_COMP *pre)
* OPENSSL EC_METHOD FUNCTIONS
*/
-int ec_GFp_nistp256_group_init(EC_GROUP *group)
+int ossl_ec_GFp_nistp256_group_init(EC_GROUP *group)
{
int ret;
- ret = ec_GFp_simple_group_init(group);
+ ret = ossl_ec_GFp_simple_group_init(group);
group->a_is_minus3 = 1;
return ret;
}
-int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,
- const BIGNUM *a, const BIGNUM *b,
- BN_CTX *ctx)
+int ossl_ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,
+ const BIGNUM *a, const BIGNUM *b,
+ BN_CTX *ctx)
{
int ret = 0;
- BN_CTX *new_ctx = NULL;
BIGNUM *curve_p, *curve_a, *curve_b;
+#ifndef FIPS_MODULE
+ BN_CTX *new_ctx = NULL;
if (ctx == NULL)
- if ((ctx = new_ctx = BN_CTX_new()) == NULL)
- return 0;
+ ctx = new_ctx = BN_CTX_new();
+#endif
+ if (ctx == NULL)
+ return 0;
+
BN_CTX_start(ctx);
curve_p = BN_CTX_get(ctx);
curve_a = BN_CTX_get(ctx);
@@ -1923,15 +1928,16 @@ int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,
BN_bin2bn(nistp256_curve_params[1], sizeof(felem_bytearray), curve_a);
BN_bin2bn(nistp256_curve_params[2], sizeof(felem_bytearray), curve_b);
if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || (BN_cmp(curve_b, b))) {
- ECerr(EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE,
- EC_R_WRONG_CURVE_PARAMETERS);
+ ERR_raise(ERR_LIB_EC, EC_R_WRONG_CURVE_PARAMETERS);
goto err;
}
group->field_mod_func = BN_nist_mod_256;
- ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
+ ret = ossl_ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
err:
BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
return ret;
}
@@ -1939,18 +1945,17 @@ int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,
* Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') =
* (X/Z^2, Y/Z^3)
*/
-int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
- const EC_POINT *point,
- BIGNUM *x, BIGNUM *y,
- BN_CTX *ctx)
+int ossl_ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx)
{
felem z1, z2, x_in, y_in;
smallfelem x_out, y_out;
longfelem tmp;
if (EC_POINT_is_at_infinity(group, point)) {
- ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES,
- EC_R_POINT_AT_INFINITY);
+ ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY);
return 0;
}
if ((!BN_to_felem(x_in, point->X)) || (!BN_to_felem(y_in, point->Y)) ||
@@ -1964,8 +1969,7 @@ int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
felem_contract(x_out, x_in);
if (x != NULL) {
if (!smallfelem_to_BN(x, x_out)) {
- ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES,
- ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
return 0;
}
}
@@ -1976,8 +1980,7 @@ int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
felem_contract(y_out, y_in);
if (y != NULL) {
if (!smallfelem_to_BN(y, y_out)) {
- ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES,
- ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
return 0;
}
}
@@ -1992,35 +1995,35 @@ static void make_points_affine(size_t num, smallfelem points[][3],
* Runs in constant time, unless an input is the point at infinity (which
* normally shouldn't happen).
*/
- ec_GFp_nistp_points_make_affine_internal(num,
- points,
- sizeof(smallfelem),
- tmp_smallfelems,
- (void (*)(void *))smallfelem_one,
- smallfelem_is_zero_int,
- (void (*)(void *, const void *))
- smallfelem_assign,
- (void (*)(void *, const void *))
- smallfelem_square_contract,
- (void (*)
- (void *, const void *,
- const void *))
- smallfelem_mul_contract,
- (void (*)(void *, const void *))
- smallfelem_inv_contract,
- /* nothing to contract */
- (void (*)(void *, const void *))
- smallfelem_assign);
+ ossl_ec_GFp_nistp_points_make_affine_internal(num,
+ points,
+ sizeof(smallfelem),
+ tmp_smallfelems,
+ (void (*)(void *))smallfelem_one,
+ smallfelem_is_zero_int,
+ (void (*)(void *, const void *))
+ smallfelem_assign,
+ (void (*)(void *, const void *))
+ smallfelem_square_contract,
+ (void (*)
+ (void *, const void *,
+ const void *))
+ smallfelem_mul_contract,
+ (void (*)(void *, const void *))
+ smallfelem_inv_contract,
+ /* nothing to contract */
+ (void (*)(void *, const void *))
+ smallfelem_assign);
}
/*
* Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL
* values Result is stored in r (r can equal one of the inputs).
*/
-int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
- const BIGNUM *scalar, size_t num,
- const EC_POINT *points[],
- const BIGNUM *scalars[], BN_CTX *ctx)
+int ossl_ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
+ const BIGNUM *scalar, size_t num,
+ const EC_POINT *points[],
+ const BIGNUM *scalars[], BN_CTX *ctx)
{
int ret = 0;
int j;
@@ -2065,12 +2068,12 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
if (!smallfelem_to_BN(x, g_pre_comp[0][1][0]) ||
!smallfelem_to_BN(y, g_pre_comp[0][1][1]) ||
!smallfelem_to_BN(z, g_pre_comp[0][1][2])) {
- ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
- if (!EC_POINT_set_Jprojective_coordinates_GFp(group,
- generator, x, y, z,
- ctx))
+ if (!ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group,
+ generator,
+ x, y, z, ctx))
goto err;
if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
/* precomputation matches generator */
@@ -2097,7 +2100,7 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
OPENSSL_malloc(sizeof(*tmp_smallfelems) * (num_points * 17 + 1));
if ((secrets == NULL) || (pre_comp == NULL)
|| (mixed && (tmp_smallfelems == NULL))) {
- ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -2129,7 +2132,7 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
* constant-timeness
*/
if (!BN_nnmod(tmp_scalar, p_scalar, group->order, ctx)) {
- ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
num_bytes = BN_bn2lebinpad(tmp_scalar,
@@ -2139,7 +2142,7 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
secrets[i], sizeof(secrets[i]));
}
if (num_bytes < 0) {
- ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* precompute multiples */
@@ -2183,7 +2186,7 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
* constant-timeness
*/
if (!BN_nnmod(tmp_scalar, scalar, group->order, ctx)) {
- ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
num_bytes = BN_bn2lebinpad(tmp_scalar, g_secret, sizeof(g_secret));
@@ -2207,10 +2210,11 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
felem_contract(z_in, z_out);
if ((!smallfelem_to_BN(x, x_in)) || (!smallfelem_to_BN(y, y_in)) ||
(!smallfelem_to_BN(z, z_in))) {
- ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
- ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx);
+ ret = ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, r, x, y, z,
+ ctx);
err:
BN_CTX_end(ctx);
@@ -2221,22 +2225,29 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
return ret;
}
-int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
+int ossl_ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
{
int ret = 0;
NISTP256_PRE_COMP *pre = NULL;
int i, j;
- BN_CTX *new_ctx = NULL;
BIGNUM *x, *y;
EC_POINT *generator = NULL;
smallfelem tmp_smallfelems[32];
felem x_tmp, y_tmp, z_tmp;
+#ifndef FIPS_MODULE
+ BN_CTX *new_ctx = NULL;
+#endif
/* throw away old precomputation */
EC_pre_comp_free(group);
+
+#ifndef FIPS_MODULE
if (ctx == NULL)
- if ((ctx = new_ctx = BN_CTX_new()) == NULL)
- return 0;
+ ctx = new_ctx = BN_CTX_new();
+#endif
+ if (ctx == NULL)
+ return 0;
+
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
@@ -2354,13 +2365,14 @@ int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
err:
BN_CTX_end(ctx);
EC_POINT_free(generator);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
EC_nistp256_pre_comp_free(pre);
return ret;
}
-int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group)
+int ossl_ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group)
{
return HAVEPRECOMP(group, nistp256);
}
-#endif
diff --git a/crypto/ec/ecp_nistp521.c b/crypto/ec/ecp_nistp521.c
index 08b32787293b..31a97d793742 100644
--- a/crypto/ec/ecp_nistp521.c
+++ b/crypto/ec/ecp_nistp521.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -24,6 +24,12 @@
*/
/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+/*
* A 64-bit implementation of the NIST P-521 elliptic curve point multiplication
*
* OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c.
@@ -32,27 +38,22 @@
*/
#include <openssl/e_os2.h>
-#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128
-NON_EMPTY_TRANSLATION_UNIT
-#else
-# include <string.h>
-# include <openssl/err.h>
-# include "ec_local.h"
+#include <string.h>
+#include <openssl/err.h>
+#include "ec_local.h"
-# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16
- /* even with gcc, the typedef won't work for 32-bit platforms */
-typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit
- * platforms */
-# else
-# error "Your compiler doesn't appear to support 128-bit integer types"
-# endif
+#include "internal/numbers.h"
+
+#ifndef INT128_MAX
+# error "Your compiler doesn't appear to support 128-bit integer types"
+#endif
typedef uint8_t u8;
typedef uint64_t u64;
/*
- * The underlying field. P521 operates over GF(2^521-1). We can serialise an
+ * The underlying field. P521 operates over GF(2^521-1). We can serialize an
* element of this field into 66 bytes where the most significant byte
* contains only a single bit. We call this an felem_bytearray.
*/
@@ -125,7 +126,7 @@ static const felem_bytearray nistp521_curve_params[5] = {
* A field element with 64-bit limbs is an 'felem'. One with 128-bit limbs is a
* 'largefelem' */
-# define NLIMBS 9
+#define NLIMBS 9
typedef uint64_t limb;
typedef limb limb_aX __attribute((__aligned__(1)));
@@ -153,7 +154,7 @@ static void bin66_to_felem(felem out, const u8 in[66])
}
/*
- * felem_to_bin66 takes an felem and serialises into a little endian, 66 byte
+ * felem_to_bin66 takes an felem and serializes into a little endian, 66 byte
* array. This assumes that the CPU is little-endian.
*/
static void felem_to_bin66(u8 out[66], const felem in)
@@ -177,12 +178,12 @@ static int BN_to_felem(felem out, const BIGNUM *bn)
int num_bytes;
if (BN_is_negative(bn)) {
- ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
+ ERR_raise(ERR_LIB_EC, EC_R_BIGNUM_OUT_OF_RANGE);
return 0;
}
num_bytes = BN_bn2lebinpad(bn, b_out, sizeof(b_out));
if (num_bytes < 0) {
- ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
+ ERR_raise(ERR_LIB_EC, EC_R_BIGNUM_OUT_OF_RANGE);
return 0;
}
bin66_to_felem(out, b_out);
@@ -400,7 +401,7 @@ static void felem_diff128(largefelem out, const largefelem in)
* On exit:
* out[i] < 17 * max(in[i]) * max(in[i])
*/
-static void felem_square(largefelem out, const felem in)
+static void felem_square_ref(largefelem out, const felem in)
{
felem inx2, inx4;
felem_scalar(inx2, in, 2);
@@ -484,7 +485,7 @@ static void felem_square(largefelem out, const felem in)
* On exit:
* out[i] < 17 * max(in1[i]) * max(in2[i])
*/
-static void felem_mul(largefelem out, const felem in1, const felem in2)
+static void felem_mul_ref(largefelem out, const felem in1, const felem in2)
{
felem in2x2;
felem_scalar(in2x2, in2, 2);
@@ -674,6 +675,57 @@ static void felem_reduce(felem out, const largefelem in)
*/
}
+#if defined(ECP_NISTP521_ASM)
+void felem_square_wrapper(largefelem out, const felem in);
+void felem_mul_wrapper(largefelem out, const felem in1, const felem in2);
+
+static void (*felem_square_p)(largefelem out, const felem in) =
+ felem_square_wrapper;
+static void (*felem_mul_p)(largefelem out, const felem in1, const felem in2) =
+ felem_mul_wrapper;
+
+void p521_felem_square(largefelem out, const felem in);
+void p521_felem_mul(largefelem out, const felem in1, const felem in2);
+
+# if defined(_ARCH_PPC64)
+# include "crypto/ppc_arch.h"
+# endif
+
+void felem_select(void)
+{
+# if defined(_ARCH_PPC64)
+ if ((OPENSSL_ppccap_P & PPC_MADD300) && (OPENSSL_ppccap_P & PPC_ALTIVEC)) {
+ felem_square_p = p521_felem_square;
+ felem_mul_p = p521_felem_mul;
+
+ return;
+ }
+# endif
+
+ /* Default */
+ felem_square_p = felem_square_ref;
+ felem_mul_p = felem_mul_ref;
+}
+
+void felem_square_wrapper(largefelem out, const felem in)
+{
+ felem_select();
+ felem_square_p(out, in);
+}
+
+void felem_mul_wrapper(largefelem out, const felem in1, const felem in2)
+{
+ felem_select();
+ felem_mul_p(out, in1, in2);
+}
+
+# define felem_square felem_square_p
+# define felem_mul felem_mul_p
+#else
+# define felem_square felem_square_ref
+# define felem_mul felem_mul_ref
+#endif
+
static void felem_square_reduce(felem out, const felem in)
{
largefelem tmp;
@@ -1266,8 +1318,8 @@ static void point_add(felem x3, felem y3, felem z3,
* This is obviously not constant-time but it will almost-never happen
* for ECDH / ECDSA. The case where it can happen is during scalar-mult
* where the intermediate value gets very close to the group order.
- * Since |ec_GFp_nistp_recode_scalar_bits| produces signed digits for
- * the scalar, it's possible for the intermediate value to be a small
+ * Since |ossl_ec_GFp_nistp_recode_scalar_bits| produces signed digits
+ * for the scalar, it's possible for the intermediate value to be a small
* negative multiple of the base point, and for the final signed digit
* to be the same value. We believe that this only occurs for the scalar
* 1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
@@ -1584,7 +1636,7 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
bits |= get_bit(scalars[num], i + 1) << 2;
bits |= get_bit(scalars[num], i) << 1;
bits |= get_bit(scalars[num], i - 1);
- ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
+ ossl_ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
/*
* select the point to add or subtract, in constant time
@@ -1622,54 +1674,55 @@ const EC_METHOD *EC_GFp_nistp521_method(void)
static const EC_METHOD ret = {
EC_FLAGS_DEFAULT_OCT,
NID_X9_62_prime_field,
- ec_GFp_nistp521_group_init,
- ec_GFp_simple_group_finish,
- ec_GFp_simple_group_clear_finish,
- ec_GFp_nist_group_copy,
- ec_GFp_nistp521_group_set_curve,
- ec_GFp_simple_group_get_curve,
- ec_GFp_simple_group_get_degree,
- ec_group_simple_order_bits,
- ec_GFp_simple_group_check_discriminant,
- ec_GFp_simple_point_init,
- ec_GFp_simple_point_finish,
- ec_GFp_simple_point_clear_finish,
- ec_GFp_simple_point_copy,
- ec_GFp_simple_point_set_to_infinity,
- ec_GFp_simple_set_Jprojective_coordinates_GFp,
- ec_GFp_simple_get_Jprojective_coordinates_GFp,
- ec_GFp_simple_point_set_affine_coordinates,
- ec_GFp_nistp521_point_get_affine_coordinates,
+ ossl_ec_GFp_nistp521_group_init,
+ ossl_ec_GFp_simple_group_finish,
+ ossl_ec_GFp_simple_group_clear_finish,
+ ossl_ec_GFp_nist_group_copy,
+ ossl_ec_GFp_nistp521_group_set_curve,
+ ossl_ec_GFp_simple_group_get_curve,
+ ossl_ec_GFp_simple_group_get_degree,
+ ossl_ec_group_simple_order_bits,
+ ossl_ec_GFp_simple_group_check_discriminant,
+ ossl_ec_GFp_simple_point_init,
+ ossl_ec_GFp_simple_point_finish,
+ ossl_ec_GFp_simple_point_clear_finish,
+ ossl_ec_GFp_simple_point_copy,
+ ossl_ec_GFp_simple_point_set_to_infinity,
+ ossl_ec_GFp_simple_point_set_affine_coordinates,
+ ossl_ec_GFp_nistp521_point_get_affine_coordinates,
0 /* point_set_compressed_coordinates */ ,
0 /* point2oct */ ,
0 /* oct2point */ ,
- ec_GFp_simple_add,
- ec_GFp_simple_dbl,
- ec_GFp_simple_invert,
- ec_GFp_simple_is_at_infinity,
- ec_GFp_simple_is_on_curve,
- ec_GFp_simple_cmp,
- ec_GFp_simple_make_affine,
- ec_GFp_simple_points_make_affine,
- ec_GFp_nistp521_points_mul,
- ec_GFp_nistp521_precompute_mult,
- ec_GFp_nistp521_have_precompute_mult,
- ec_GFp_nist_field_mul,
- ec_GFp_nist_field_sqr,
+ ossl_ec_GFp_simple_add,
+ ossl_ec_GFp_simple_dbl,
+ ossl_ec_GFp_simple_invert,
+ ossl_ec_GFp_simple_is_at_infinity,
+ ossl_ec_GFp_simple_is_on_curve,
+ ossl_ec_GFp_simple_cmp,
+ ossl_ec_GFp_simple_make_affine,
+ ossl_ec_GFp_simple_points_make_affine,
+ ossl_ec_GFp_nistp521_points_mul,
+ ossl_ec_GFp_nistp521_precompute_mult,
+ ossl_ec_GFp_nistp521_have_precompute_mult,
+ ossl_ec_GFp_nist_field_mul,
+ ossl_ec_GFp_nist_field_sqr,
0 /* field_div */ ,
- ec_GFp_simple_field_inv,
+ ossl_ec_GFp_simple_field_inv,
0 /* field_encode */ ,
0 /* field_decode */ ,
0, /* field_set_to_one */
- ec_key_simple_priv2oct,
- ec_key_simple_oct2priv,
+ ossl_ec_key_simple_priv2oct,
+ ossl_ec_key_simple_oct2priv,
0, /* set private */
- ec_key_simple_generate_key,
- ec_key_simple_check_key,
- ec_key_simple_generate_public_key,
+ ossl_ec_key_simple_generate_key,
+ ossl_ec_key_simple_check_key,
+ ossl_ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
- ecdh_simple_compute_key,
+ ossl_ecdh_simple_compute_key,
+ ossl_ecdsa_simple_sign_setup,
+ ossl_ecdsa_simple_sign_sig,
+ ossl_ecdsa_simple_verify_sig,
0, /* field_inverse_mod_ord */
0, /* blind_coordinates */
0, /* ladder_pre */
@@ -1690,7 +1743,7 @@ static NISTP521_PRE_COMP *nistp521_pre_comp_new(void)
NISTP521_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- ECerr(EC_F_NISTP521_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return ret;
}
@@ -1698,7 +1751,7 @@ static NISTP521_PRE_COMP *nistp521_pre_comp_new(void)
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
- ECerr(EC_F_NISTP521_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
@@ -1721,7 +1774,7 @@ void EC_nistp521_pre_comp_free(NISTP521_PRE_COMP *p)
return;
CRYPTO_DOWN_REF(&p->references, &i, p->lock);
- REF_PRINT_COUNT("EC_nistp521", x);
+ REF_PRINT_COUNT("EC_nistp521", p);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
@@ -1735,25 +1788,29 @@ void EC_nistp521_pre_comp_free(NISTP521_PRE_COMP *p)
* OPENSSL EC_METHOD FUNCTIONS
*/
-int ec_GFp_nistp521_group_init(EC_GROUP *group)
+int ossl_ec_GFp_nistp521_group_init(EC_GROUP *group)
{
int ret;
- ret = ec_GFp_simple_group_init(group);
+ ret = ossl_ec_GFp_simple_group_init(group);
group->a_is_minus3 = 1;
return ret;
}
-int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p,
- const BIGNUM *a, const BIGNUM *b,
- BN_CTX *ctx)
+int ossl_ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p,
+ const BIGNUM *a, const BIGNUM *b,
+ BN_CTX *ctx)
{
int ret = 0;
- BN_CTX *new_ctx = NULL;
BIGNUM *curve_p, *curve_a, *curve_b;
+#ifndef FIPS_MODULE
+ BN_CTX *new_ctx = NULL;
if (ctx == NULL)
- if ((ctx = new_ctx = BN_CTX_new()) == NULL)
- return 0;
+ ctx = new_ctx = BN_CTX_new();
+#endif
+ if (ctx == NULL)
+ return 0;
+
BN_CTX_start(ctx);
curve_p = BN_CTX_get(ctx);
curve_a = BN_CTX_get(ctx);
@@ -1764,15 +1821,16 @@ int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p,
BN_bin2bn(nistp521_curve_params[1], sizeof(felem_bytearray), curve_a);
BN_bin2bn(nistp521_curve_params[2], sizeof(felem_bytearray), curve_b);
if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || (BN_cmp(curve_b, b))) {
- ECerr(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE,
- EC_R_WRONG_CURVE_PARAMETERS);
+ ERR_raise(ERR_LIB_EC, EC_R_WRONG_CURVE_PARAMETERS);
goto err;
}
group->field_mod_func = BN_nist_mod_521;
- ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
+ ret = ossl_ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
err:
BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
return ret;
}
@@ -1780,17 +1838,16 @@ int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p,
* Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') =
* (X/Z^2, Y/Z^3)
*/
-int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group,
- const EC_POINT *point,
- BIGNUM *x, BIGNUM *y,
- BN_CTX *ctx)
+int ossl_ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx)
{
felem z1, z2, x_in, y_in, x_out, y_out;
largefelem tmp;
if (EC_POINT_is_at_infinity(group, point)) {
- ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES,
- EC_R_POINT_AT_INFINITY);
+ ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY);
return 0;
}
if ((!BN_to_felem(x_in, point->X)) || (!BN_to_felem(y_in, point->Y)) ||
@@ -1804,8 +1861,7 @@ int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group,
felem_contract(x_out, x_in);
if (x != NULL) {
if (!felem_to_BN(x, x_out)) {
- ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES,
- ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
return 0;
}
}
@@ -1816,8 +1872,7 @@ int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group,
felem_contract(y_out, y_in);
if (y != NULL) {
if (!felem_to_BN(y, y_out)) {
- ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES,
- ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
return 0;
}
}
@@ -1832,36 +1887,36 @@ static void make_points_affine(size_t num, felem points[][3],
* Runs in constant time, unless an input is the point at infinity (which
* normally shouldn't happen).
*/
- ec_GFp_nistp_points_make_affine_internal(num,
- points,
- sizeof(felem),
- tmp_felems,
- (void (*)(void *))felem_one,
- felem_is_zero_int,
- (void (*)(void *, const void *))
- felem_assign,
- (void (*)(void *, const void *))
- felem_square_reduce, (void (*)
- (void *,
- const void
- *,
- const void
- *))
- felem_mul_reduce,
- (void (*)(void *, const void *))
- felem_inv,
- (void (*)(void *, const void *))
- felem_contract);
+ ossl_ec_GFp_nistp_points_make_affine_internal(num,
+ points,
+ sizeof(felem),
+ tmp_felems,
+ (void (*)(void *))felem_one,
+ felem_is_zero_int,
+ (void (*)(void *, const void *))
+ felem_assign,
+ (void (*)(void *, const void *))
+ felem_square_reduce, (void (*)
+ (void *,
+ const void
+ *,
+ const void
+ *))
+ felem_mul_reduce,
+ (void (*)(void *, const void *))
+ felem_inv,
+ (void (*)(void *, const void *))
+ felem_contract);
}
/*
* Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL
* values Result is stored in r (r can equal one of the inputs).
*/
-int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
- const BIGNUM *scalar, size_t num,
- const EC_POINT *points[],
- const BIGNUM *scalars[], BN_CTX *ctx)
+int ossl_ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
+ const BIGNUM *scalar, size_t num,
+ const EC_POINT *points[],
+ const BIGNUM *scalars[], BN_CTX *ctx)
{
int ret = 0;
int j;
@@ -1905,12 +1960,12 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
if (!felem_to_BN(x, g_pre_comp[1][0]) ||
!felem_to_BN(y, g_pre_comp[1][1]) ||
!felem_to_BN(z, g_pre_comp[1][2])) {
- ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
- if (!EC_POINT_set_Jprojective_coordinates_GFp(group,
- generator, x, y, z,
- ctx))
+ if (!ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group,
+ generator,
+ x, y, z, ctx))
goto err;
if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
/* precomputation matches generator */
@@ -1938,7 +1993,7 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
OPENSSL_malloc(sizeof(*tmp_felems) * (num_points * 17 + 1));
if ((secrets == NULL) || (pre_comp == NULL)
|| (mixed && (tmp_felems == NULL))) {
- ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -1968,7 +2023,7 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
* constant-timeness
*/
if (!BN_nnmod(tmp_scalar, p_scalar, group->order, ctx)) {
- ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
num_bytes = BN_bn2lebinpad(tmp_scalar,
@@ -1978,7 +2033,7 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
secrets[i], sizeof(secrets[i]));
}
if (num_bytes < 0) {
- ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* precompute multiples */
@@ -2020,7 +2075,7 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
* constant-timeness
*/
if (!BN_nnmod(tmp_scalar, scalar, group->order, ctx)) {
- ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
num_bytes = BN_bn2lebinpad(tmp_scalar, g_secret, sizeof(g_secret));
@@ -2045,10 +2100,11 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
felem_contract(z_in, z_out);
if ((!felem_to_BN(x, x_in)) || (!felem_to_BN(y, y_in)) ||
(!felem_to_BN(z, z_in))) {
- ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
- ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx);
+ ret = ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, r, x, y, z,
+ ctx);
err:
BN_CTX_end(ctx);
@@ -2059,21 +2115,28 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
return ret;
}
-int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
+int ossl_ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
{
int ret = 0;
NISTP521_PRE_COMP *pre = NULL;
int i, j;
- BN_CTX *new_ctx = NULL;
BIGNUM *x, *y;
EC_POINT *generator = NULL;
felem tmp_felems[16];
+#ifndef FIPS_MODULE
+ BN_CTX *new_ctx = NULL;
+#endif
/* throw away old precomputation */
EC_pre_comp_free(group);
+
+#ifndef FIPS_MODULE
if (ctx == NULL)
- if ((ctx = new_ctx = BN_CTX_new()) == NULL)
- return 0;
+ ctx = new_ctx = BN_CTX_new();
+#endif
+ if (ctx == NULL)
+ return 0;
+
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
@@ -2161,14 +2224,14 @@ int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
err:
BN_CTX_end(ctx);
EC_POINT_free(generator);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
EC_nistp521_pre_comp_free(pre);
return ret;
}
-int ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group)
+int ossl_ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group)
{
return HAVEPRECOMP(group, nistp521);
}
-
-#endif
diff --git a/crypto/ec/ecp_nistputil.c b/crypto/ec/ecp_nistputil.c
index 60e1325c340f..4e8c0e276769 100644
--- a/crypto/ec/ecp_nistputil.c
+++ b/crypto/ec/ecp_nistputil.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -23,17 +23,20 @@
* limitations under the License.
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/opensslconf.h>
-#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128
-NON_EMPTY_TRANSLATION_UNIT
-#else
/*
* Common utility functions for ecp_nistp224.c, ecp_nistp256.c, ecp_nistp521.c.
*/
-# include <stddef.h>
-# include "ec_local.h"
+#include <stddef.h>
+#include "ec_local.h"
/*
* Convert an array of points into affine coordinates. (If the point at
@@ -46,7 +49,8 @@ NON_EMPTY_TRANSLATION_UNIT
* of size 'felem_size'. tmp_felems needs to point to a temporary array of
* 'num'+1 field elements for storage of intermediate values.
*/
-void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,
+void
+ossl_ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,
size_t felem_size,
void *tmp_felems,
void (*felem_one) (void *out),
@@ -74,10 +78,10 @@ void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,
{
int i = 0;
-# define tmp_felem(I) (&((char *)tmp_felems)[(I) * felem_size])
-# define X(I) (&((char *)point_array)[3*(I) * felem_size])
-# define Y(I) (&((char *)point_array)[(3*(I) + 1) * felem_size])
-# define Z(I) (&((char *)point_array)[(3*(I) + 2) * felem_size])
+#define tmp_felem(I) (&((char *)tmp_felems)[(I) * felem_size])
+#define X(I) (&((char *)point_array)[3*(I) * felem_size])
+#define Y(I) (&((char *)point_array)[(3*(I) + 1) * felem_size])
+#define Z(I) (&((char *)point_array)[(3*(I) + 2) * felem_size])
if (!felem_is_zero(Z(0)))
felem_assign(tmp_felem(0), Z(0));
@@ -206,8 +210,8 @@ void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,
* b_-1, has to be b_4 b_3 b_2 b_1 b_0 0.
*
*/
-void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign,
- unsigned char *digit, unsigned char in)
+void ossl_ec_GFp_nistp_recode_scalar_bits(unsigned char *sign,
+ unsigned char *digit, unsigned char in)
{
unsigned char s, d;
@@ -220,4 +224,3 @@ void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign,
*sign = s & 1;
*digit = d;
}
-#endif
diff --git a/crypto/ec/ecp_nistz256.c b/crypto/ec/ecp_nistz256.c
index cfad3e15b0bf..d65f6984ded3 100644
--- a/crypto/ec/ecp_nistz256.c
+++ b/crypto/ec/ecp_nistz256.c
@@ -3,7 +3,7 @@
* Copyright (c) 2014, Intel Corporation. All Rights Reserved.
* Copyright (c) 2015, CloudFlare, Inc.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -18,6 +18,12 @@
* 256 Bit Primes"
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <string.h>
#include "internal/cryptlib.h"
@@ -631,7 +637,7 @@ __owur static int ecp_nistz256_windowed_mul(const EC_GROUP *group,
|| (p_str =
OPENSSL_malloc(num * 33 * sizeof(unsigned char))) == NULL
|| (scalars = OPENSSL_malloc(num * sizeof(BIGNUM *))) == NULL) {
- ECerr(EC_F_ECP_NISTZ256_WINDOWED_MUL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -648,7 +654,7 @@ __owur static int ecp_nistz256_windowed_mul(const EC_GROUP *group,
if ((mod = BN_CTX_get(ctx)) == NULL)
goto err;
if (!BN_nnmod(mod, scalar[i], group->order, ctx)) {
- ECerr(EC_F_ECP_NISTZ256_WINDOWED_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
scalars[i] = mod;
@@ -676,8 +682,7 @@ __owur static int ecp_nistz256_windowed_mul(const EC_GROUP *group,
if (!ecp_nistz256_bignum_to_field_elem(temp[0].X, point[i]->X)
|| !ecp_nistz256_bignum_to_field_elem(temp[0].Y, point[i]->Y)
|| !ecp_nistz256_bignum_to_field_elem(temp[0].Z, point[i]->Z)) {
- ECerr(EC_F_ECP_NISTZ256_WINDOWED_MUL,
- EC_R_COORDINATES_OUT_OF_RANGE);
+ ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE);
goto err;
}
@@ -828,7 +833,7 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
EC_pre_comp_free(group);
generator = EC_GROUP_get0_generator(group);
if (generator == NULL) {
- ECerr(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, EC_R_UNDEFINED_GENERATOR);
+ ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR);
return 0;
}
@@ -844,7 +849,7 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
return 0;
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
goto err;
}
@@ -856,7 +861,7 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
goto err;
if (BN_is_zero(order)) {
- ECerr(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, EC_R_UNKNOWN_ORDER);
+ ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_ORDER);
goto err;
}
@@ -864,7 +869,7 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
if ((precomp_storage =
OPENSSL_malloc(37 * 64 * sizeof(P256_POINT_AFFINE) + 64)) == NULL) {
- ECerr(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -891,12 +896,12 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
* It would be faster to use EC_POINTs_make_affine and
* make multiple points affine at the same time.
*/
- if (!EC_POINT_make_affine(group, P, ctx))
+ if (group->meth->make_affine == NULL
+ || !group->meth->make_affine(group, P, ctx))
goto err;
if (!ecp_nistz256_bignum_to_field_elem(temp.X, P->X) ||
!ecp_nistz256_bignum_to_field_elem(temp.Y, P->Y)) {
- ECerr(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE,
- EC_R_COORDINATES_OUT_OF_RANGE);
+ ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE);
goto err;
}
ecp_nistz256_scatter_w7(preComputedTable[j], &temp, k);
@@ -969,7 +974,7 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group,
BIGNUM *tmp_scalar;
if ((num + 1) == 0 || (num + 1) > OPENSSL_MALLOC_MAX_NELEMS(void *)) {
- ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -979,7 +984,7 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group,
if (scalar) {
generator = EC_GROUP_get0_generator(group);
if (generator == NULL) {
- ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, EC_R_UNDEFINED_GENERATOR);
+ ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR);
goto err;
}
@@ -1027,7 +1032,7 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group,
goto err;
if (!BN_nnmod(tmp_scalar, scalar, group->order, ctx)) {
- ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
scalar = tmp_scalar;
@@ -1119,13 +1124,13 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group,
*/
new_scalars = OPENSSL_malloc((num + 1) * sizeof(BIGNUM *));
if (new_scalars == NULL) {
- ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
new_points = OPENSSL_malloc((num + 1) * sizeof(EC_POINT *));
if (new_points == NULL) {
- ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -1180,14 +1185,14 @@ __owur static int ecp_nistz256_get_affine(const EC_GROUP *group,
BN_ULONG x_ret[P256_LIMBS], y_ret[P256_LIMBS];
if (EC_POINT_is_at_infinity(group, point)) {
- ECerr(EC_F_ECP_NISTZ256_GET_AFFINE, EC_R_POINT_AT_INFINITY);
+ ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY);
return 0;
}
if (!ecp_nistz256_bignum_to_field_elem(point_x, point->X) ||
!ecp_nistz256_bignum_to_field_elem(point_y, point->Y) ||
!ecp_nistz256_bignum_to_field_elem(point_z, point->Z)) {
- ECerr(EC_F_ECP_NISTZ256_GET_AFFINE, EC_R_COORDINATES_OUT_OF_RANGE);
+ ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE);
return 0;
}
@@ -1222,7 +1227,7 @@ static NISTZ256_PRE_COMP *ecp_nistz256_pre_comp_new(const EC_GROUP *group)
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- ECerr(EC_F_ECP_NISTZ256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return ret;
}
@@ -1232,7 +1237,7 @@ static NISTZ256_PRE_COMP *ecp_nistz256_pre_comp_new(const EC_GROUP *group)
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
- ECerr(EC_F_ECP_NISTZ256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
@@ -1255,7 +1260,7 @@ void EC_nistz256_pre_comp_free(NISTZ256_PRE_COMP *pre)
return;
CRYPTO_DOWN_REF(&pre->references, &i, pre->lock);
- REF_PRINT_COUNT("EC_nistz256", x);
+ REF_PRINT_COUNT("EC_nistz256", pre);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
@@ -1291,7 +1296,7 @@ void ecp_nistz256_ord_mul_mont(BN_ULONG res[P256_LIMBS],
const BN_ULONG b[P256_LIMBS]);
void ecp_nistz256_ord_sqr_mont(BN_ULONG res[P256_LIMBS],
const BN_ULONG a[P256_LIMBS],
- int rep);
+ BN_ULONG rep);
static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r,
const BIGNUM *x, BN_CTX *ctx)
@@ -1321,7 +1326,7 @@ static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r,
* Catch allocation failure early.
*/
if (bn_wexpand(r, P256_LIMBS) == NULL) {
- ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
@@ -1330,14 +1335,14 @@ static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r,
if ((tmp = BN_CTX_get(ctx)) == NULL
|| !BN_nnmod(tmp, x, group->order, ctx)) {
- ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
x = tmp;
}
if (!ecp_nistz256_bignum_to_field_elem(t, x)) {
- ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, EC_R_COORDINATES_OUT_OF_RANGE);
+ ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE);
goto err;
}
@@ -1467,52 +1472,53 @@ const EC_METHOD *EC_GFp_nistz256_method(void)
static const EC_METHOD ret = {
EC_FLAGS_DEFAULT_OCT,
NID_X9_62_prime_field,
- ec_GFp_mont_group_init,
- ec_GFp_mont_group_finish,
- ec_GFp_mont_group_clear_finish,
- ec_GFp_mont_group_copy,
- ec_GFp_mont_group_set_curve,
- ec_GFp_simple_group_get_curve,
- ec_GFp_simple_group_get_degree,
- ec_group_simple_order_bits,
- ec_GFp_simple_group_check_discriminant,
- ec_GFp_simple_point_init,
- ec_GFp_simple_point_finish,
- ec_GFp_simple_point_clear_finish,
- ec_GFp_simple_point_copy,
- ec_GFp_simple_point_set_to_infinity,
- ec_GFp_simple_set_Jprojective_coordinates_GFp,
- ec_GFp_simple_get_Jprojective_coordinates_GFp,
- ec_GFp_simple_point_set_affine_coordinates,
+ ossl_ec_GFp_mont_group_init,
+ ossl_ec_GFp_mont_group_finish,
+ ossl_ec_GFp_mont_group_clear_finish,
+ ossl_ec_GFp_mont_group_copy,
+ ossl_ec_GFp_mont_group_set_curve,
+ ossl_ec_GFp_simple_group_get_curve,
+ ossl_ec_GFp_simple_group_get_degree,
+ ossl_ec_group_simple_order_bits,
+ ossl_ec_GFp_simple_group_check_discriminant,
+ ossl_ec_GFp_simple_point_init,
+ ossl_ec_GFp_simple_point_finish,
+ ossl_ec_GFp_simple_point_clear_finish,
+ ossl_ec_GFp_simple_point_copy,
+ ossl_ec_GFp_simple_point_set_to_infinity,
+ ossl_ec_GFp_simple_point_set_affine_coordinates,
ecp_nistz256_get_affine,
0, 0, 0,
- ec_GFp_simple_add,
- ec_GFp_simple_dbl,
- ec_GFp_simple_invert,
- ec_GFp_simple_is_at_infinity,
- ec_GFp_simple_is_on_curve,
- ec_GFp_simple_cmp,
- ec_GFp_simple_make_affine,
- ec_GFp_simple_points_make_affine,
+ ossl_ec_GFp_simple_add,
+ ossl_ec_GFp_simple_dbl,
+ ossl_ec_GFp_simple_invert,
+ ossl_ec_GFp_simple_is_at_infinity,
+ ossl_ec_GFp_simple_is_on_curve,
+ ossl_ec_GFp_simple_cmp,
+ ossl_ec_GFp_simple_make_affine,
+ ossl_ec_GFp_simple_points_make_affine,
ecp_nistz256_points_mul, /* mul */
ecp_nistz256_mult_precompute, /* precompute_mult */
ecp_nistz256_window_have_precompute_mult, /* have_precompute_mult */
- ec_GFp_mont_field_mul,
- ec_GFp_mont_field_sqr,
+ ossl_ec_GFp_mont_field_mul,
+ ossl_ec_GFp_mont_field_sqr,
0, /* field_div */
- ec_GFp_mont_field_inv,
- ec_GFp_mont_field_encode,
- ec_GFp_mont_field_decode,
- ec_GFp_mont_field_set_to_one,
- ec_key_simple_priv2oct,
- ec_key_simple_oct2priv,
+ ossl_ec_GFp_mont_field_inv,
+ ossl_ec_GFp_mont_field_encode,
+ ossl_ec_GFp_mont_field_decode,
+ ossl_ec_GFp_mont_field_set_to_one,
+ ossl_ec_key_simple_priv2oct,
+ ossl_ec_key_simple_oct2priv,
0, /* set private */
- ec_key_simple_generate_key,
- ec_key_simple_check_key,
- ec_key_simple_generate_public_key,
+ ossl_ec_key_simple_generate_key,
+ ossl_ec_key_simple_check_key,
+ ossl_ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
- ecdh_simple_compute_key,
+ ossl_ecdh_simple_compute_key,
+ ossl_ecdsa_simple_sign_setup,
+ ossl_ecdsa_simple_sign_sig,
+ ossl_ecdsa_simple_verify_sig,
ecp_nistz256_inv_mod_ord, /* can be #define-d NULL */
0, /* blind_coordinates */
0, /* ladder_pre */
diff --git a/crypto/ec/ecp_nistz256_table.c b/crypto/ec/ecp_nistz256_table.c
index 3f5625c6c5eb..71430d4b8142 100644
--- a/crypto/ec/ecp_nistz256_table.c
+++ b/crypto/ec/ecp_nistz256_table.c
@@ -1,7 +1,7 @@
/*
* Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/ec/ecp_oct.c b/crypto/ec/ecp_oct.c
index 9460763256fd..68943e521e8a 100644
--- a/crypto/ec/ecp_oct.c
+++ b/crypto/ec/ecp_oct.c
@@ -1,32 +1,35 @@
/*
- * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/err.h>
#include <openssl/symhacks.h>
#include "ec_local.h"
-int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
- EC_POINT *point,
- const BIGNUM *x_, int y_bit,
- BN_CTX *ctx)
+int ossl_ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
+ EC_POINT *point,
+ const BIGNUM *x_, int y_bit,
+ BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
BIGNUM *tmp1, *tmp2, *x, *y;
int ret = 0;
- /* clear error queue */
- ERR_clear_error();
-
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
return 0;
}
@@ -98,19 +101,24 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
goto err;
}
+ ERR_set_mark();
if (!BN_mod_sqrt(y, tmp1, group->field, ctx)) {
+#ifndef FIPS_MODULE
unsigned long err = ERR_peek_last_error();
if (ERR_GET_LIB(err) == ERR_LIB_BN
&& ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) {
- ERR_clear_error();
- ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
- EC_R_INVALID_COMPRESSED_POINT);
+ ERR_pop_to_mark();
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_COMPRESSED_POINT);
} else
- ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
- ERR_R_BN_LIB);
+#endif
+ {
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
+ }
goto err;
}
+ ERR_clear_last_mark();
if (y_bit != BN_is_odd(y)) {
if (BN_is_zero(y)) {
@@ -121,22 +129,19 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
goto err;
if (kron == 1)
- ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
- EC_R_INVALID_COMPRESSION_BIT);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_COMPRESSION_BIT);
else
/*
* BN_mod_sqrt() should have caught this error (not a square)
*/
- ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
- EC_R_INVALID_COMPRESSED_POINT);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_COMPRESSED_POINT);
goto err;
}
if (!BN_usub(y, group->field, y))
goto err;
}
if (y_bit != BN_is_odd(y)) {
- ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
- ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -151,9 +156,9 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
return ret;
}
-size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
- point_conversion_form_t form,
- unsigned char *buf, size_t len, BN_CTX *ctx)
+size_t ossl_ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
+ point_conversion_form_t form,
+ unsigned char *buf, size_t len, BN_CTX *ctx)
{
size_t ret;
BN_CTX *new_ctx = NULL;
@@ -164,7 +169,7 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
if ((form != POINT_CONVERSION_COMPRESSED)
&& (form != POINT_CONVERSION_UNCOMPRESSED)
&& (form != POINT_CONVERSION_HYBRID)) {
- ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_FORM);
goto err;
}
@@ -172,7 +177,7 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
/* encodes to a single 0 octet */
if (buf != NULL) {
if (len < 1) {
- ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
+ ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
return 0;
}
buf[0] = 0;
@@ -189,12 +194,12 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
/* if 'buf' is NULL, just return required length */
if (buf != NULL) {
if (len < ret) {
- ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
+ ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
goto err;
}
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
return 0;
}
@@ -219,7 +224,7 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
skip = field_len - BN_num_bytes(x);
if (skip > field_len) {
- ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
goto err;
}
while (skip > 0) {
@@ -229,7 +234,7 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
skip = BN_bn2bin(x, buf + i);
i += skip;
if (i != 1 + field_len) {
- ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -237,7 +242,7 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
|| form == POINT_CONVERSION_HYBRID) {
skip = field_len - BN_num_bytes(y);
if (skip > field_len) {
- ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
goto err;
}
while (skip > 0) {
@@ -249,7 +254,7 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
}
if (i != ret) {
- ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
goto err;
}
}
@@ -266,8 +271,9 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
return 0;
}
-int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
- const unsigned char *buf, size_t len, BN_CTX *ctx)
+int ossl_ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
+ const unsigned char *buf, size_t len,
+ BN_CTX *ctx)
{
point_conversion_form_t form;
int y_bit;
@@ -277,7 +283,7 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
int ret = 0;
if (len == 0) {
- ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
+ ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
return 0;
}
form = buf[0];
@@ -286,17 +292,17 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
&& (form != POINT_CONVERSION_UNCOMPRESSED)
&& (form != POINT_CONVERSION_HYBRID)) {
- ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
return 0;
}
if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) {
- ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
return 0;
}
if (form == 0) {
if (len != 1) {
- ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
return 0;
}
@@ -309,12 +315,12 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
if (len != enc_len) {
- ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
return 0;
}
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
return 0;
}
@@ -328,7 +334,7 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
if (!BN_bin2bn(buf + 1, field_len, x))
goto err;
if (BN_ucmp(x, group->field) >= 0) {
- ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
goto err;
}
@@ -339,12 +345,12 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
if (!BN_bin2bn(buf + 1 + field_len, field_len, y))
goto err;
if (BN_ucmp(y, group->field) >= 0) {
- ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
goto err;
}
if (form == POINT_CONVERSION_HYBRID) {
if (y_bit != BN_is_odd(y)) {
- ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
goto err;
}
}
diff --git a/crypto/ec/ecp_ppc.c b/crypto/ec/ecp_ppc.c
new file mode 100644
index 000000000000..b2b9f772b87b
--- /dev/null
+++ b/crypto/ec/ecp_ppc.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2009-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/cryptlib.h"
+#include "crypto/ppc_arch.h"
+#include "ec_local.h"
+
+void ecp_nistz256_mul_mont(unsigned long res[4], const unsigned long a[4],
+ const unsigned long b[4]);
+
+void ecp_nistz256_to_mont(unsigned long res[4], const unsigned long in[4]);
+void ecp_nistz256_to_mont(unsigned long res[4], const unsigned long in[4])
+{
+ static const unsigned long RR[] = { 0x0000000000000003U,
+ 0xfffffffbffffffffU,
+ 0xfffffffffffffffeU,
+ 0x00000004fffffffdU };
+
+ ecp_nistz256_mul_mont(res, in, RR);
+}
+
+void ecp_nistz256_from_mont(unsigned long res[4], const unsigned long in[4]);
+void ecp_nistz256_from_mont(unsigned long res[4], const unsigned long in[4])
+{
+ static const unsigned long one[] = { 1, 0, 0, 0 };
+
+ ecp_nistz256_mul_mont(res, in, one);
+}
diff --git a/crypto/ec/ecp_s390x_nistp.c b/crypto/ec/ecp_s390x_nistp.c
new file mode 100644
index 000000000000..0c10196ea34e
--- /dev/null
+++ b/crypto/ec/ecp_s390x_nistp.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * EC_METHOD low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include "ec_local.h"
+#include "s390x_arch.h"
+
+/* Size of parameter blocks */
+#define S390X_SIZE_PARAM 4096
+
+/* Size of fields in parameter blocks */
+#define S390X_SIZE_P256 32
+#define S390X_SIZE_P384 48
+#define S390X_SIZE_P521 80
+
+/* Offsets of fields in PCC parameter blocks */
+#define S390X_OFF_RES_X(n) (0 * n)
+#define S390X_OFF_RES_Y(n) (1 * n)
+#define S390X_OFF_SRC_X(n) (2 * n)
+#define S390X_OFF_SRC_Y(n) (3 * n)
+#define S390X_OFF_SCALAR(n) (4 * n)
+
+/* Offsets of fields in KDSA parameter blocks */
+#define S390X_OFF_R(n) (0 * n)
+#define S390X_OFF_S(n) (1 * n)
+#define S390X_OFF_H(n) (2 * n)
+#define S390X_OFF_K(n) (3 * n)
+#define S390X_OFF_X(n) (3 * n)
+#define S390X_OFF_RN(n) (4 * n)
+#define S390X_OFF_Y(n) (4 * n)
+
+static int ec_GFp_s390x_nistp_mul(const EC_GROUP *group, EC_POINT *r,
+ const BIGNUM *scalar,
+ size_t num, const EC_POINT *points[],
+ const BIGNUM *scalars[],
+ BN_CTX *ctx, unsigned int fc, int len)
+{
+ unsigned char param[S390X_SIZE_PARAM];
+ BIGNUM *x, *y;
+ const EC_POINT *point_ptr = NULL;
+ const BIGNUM *scalar_ptr = NULL;
+ BN_CTX *new_ctx = NULL;
+ int rc = -1;
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
+ if (ctx == NULL)
+ return 0;
+ }
+
+ BN_CTX_start(ctx);
+
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+ if (x == NULL || y == NULL) {
+ rc = 0;
+ goto ret;
+ }
+
+ /*
+ * Use PCC for EC keygen and ECDH key derivation:
+ * scalar * generator and scalar * peer public key,
+ * scalar in [0,order).
+ */
+ if ((scalar != NULL && num == 0 && BN_is_negative(scalar) == 0)
+ || (scalar == NULL && num == 1 && BN_is_negative(scalars[0]) == 0)) {
+
+ if (num == 0) {
+ point_ptr = EC_GROUP_get0_generator(group);
+ scalar_ptr = scalar;
+ } else {
+ point_ptr = points[0];
+ scalar_ptr = scalars[0];
+ }
+
+ if (EC_POINT_is_at_infinity(group, point_ptr) == 1
+ || BN_is_zero(scalar_ptr)) {
+ rc = EC_POINT_set_to_infinity(group, r);
+ goto ret;
+ }
+
+ memset(&param, 0, sizeof(param));
+
+ if (group->meth->point_get_affine_coordinates(group, point_ptr,
+ x, y, ctx) != 1
+ || BN_bn2binpad(x, param + S390X_OFF_SRC_X(len), len) == -1
+ || BN_bn2binpad(y, param + S390X_OFF_SRC_Y(len), len) == -1
+ || BN_bn2binpad(scalar_ptr,
+ param + S390X_OFF_SCALAR(len), len) == -1
+ || s390x_pcc(fc, param) != 0
+ || BN_bin2bn(param + S390X_OFF_RES_X(len), len, x) == NULL
+ || BN_bin2bn(param + S390X_OFF_RES_Y(len), len, y) == NULL
+ || group->meth->point_set_affine_coordinates(group, r,
+ x, y, ctx) != 1)
+ goto ret;
+
+ rc = 1;
+ }
+
+ret:
+ /* Otherwise use default. */
+ if (rc == -1)
+ rc = ossl_ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
+ OPENSSL_cleanse(param, sizeof(param));
+ BN_CTX_end(ctx);
+ BN_CTX_free(new_ctx);
+ return rc;
+}
+
+static ECDSA_SIG *ecdsa_s390x_nistp_sign_sig(const unsigned char *dgst,
+ int dgstlen,
+ const BIGNUM *kinv,
+ const BIGNUM *r,
+ EC_KEY *eckey,
+ unsigned int fc, int len)
+{
+ unsigned char param[S390X_SIZE_PARAM];
+ int ok = 0;
+ BIGNUM *k;
+ ECDSA_SIG *sig;
+ const EC_GROUP *group;
+ const BIGNUM *privkey;
+ int off;
+
+ group = EC_KEY_get0_group(eckey);
+ privkey = EC_KEY_get0_private_key(eckey);
+ if (group == NULL || privkey == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS);
+ return NULL;
+ }
+
+ if (!EC_KEY_can_sign(eckey)) {
+ ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
+ return NULL;
+ }
+
+ k = BN_secure_new();
+ sig = ECDSA_SIG_new();
+ if (k == NULL || sig == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto ret;
+ }
+
+ sig->r = BN_new();
+ sig->s = BN_new();
+ if (sig->r == NULL || sig->s == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto ret;
+ }
+
+ memset(param, 0, sizeof(param));
+ off = len - (dgstlen > len ? len : dgstlen);
+ memcpy(param + S390X_OFF_H(len) + off, dgst, len - off);
+
+ if (BN_bn2binpad(privkey, param + S390X_OFF_K(len), len) == -1) {
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
+ goto ret;
+ }
+
+ if (r == NULL || kinv == NULL) {
+ if (len < 0) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_LENGTH);
+ goto ret;
+ }
+ /*
+ * Generate random k and copy to param param block. RAND_priv_bytes_ex
+ * is used instead of BN_priv_rand_range or BN_generate_dsa_nonce
+ * because kdsa instruction constructs an in-range, invertible nonce
+ * internally implementing counter-measures for RNG weakness.
+ */
+ if (RAND_priv_bytes_ex(eckey->libctx, param + S390X_OFF_RN(len),
+ (size_t)len, 0) != 1) {
+ ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED);
+ goto ret;
+ }
+ } else {
+ /* Reconstruct k = (k^-1)^-1. */
+ if (ossl_ec_group_do_inverse_ord(group, k, kinv, NULL) == 0
+ || BN_bn2binpad(k, param + S390X_OFF_RN(len), len) == -1) {
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
+ goto ret;
+ }
+ /* Turns KDSA internal nonce-generation off. */
+ fc |= S390X_KDSA_D;
+ }
+
+ if (s390x_kdsa(fc, param, NULL, 0) != 0) {
+ ERR_raise(ERR_LIB_EC, ERR_R_ECDSA_LIB);
+ goto ret;
+ }
+
+ if (BN_bin2bn(param + S390X_OFF_R(len), len, sig->r) == NULL
+ || BN_bin2bn(param + S390X_OFF_S(len), len, sig->s) == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
+ goto ret;
+ }
+
+ ok = 1;
+ret:
+ OPENSSL_cleanse(param, sizeof(param));
+ if (ok != 1) {
+ ECDSA_SIG_free(sig);
+ sig = NULL;
+ }
+ BN_clear_free(k);
+ return sig;
+}
+
+static int ecdsa_s390x_nistp_verify_sig(const unsigned char *dgst, int dgstlen,
+ const ECDSA_SIG *sig, EC_KEY *eckey,
+ unsigned int fc, int len)
+{
+ unsigned char param[S390X_SIZE_PARAM];
+ int rc = -1;
+ BN_CTX *ctx;
+ BIGNUM *x, *y;
+ const EC_GROUP *group;
+ const EC_POINT *pubkey;
+ int off;
+
+ group = EC_KEY_get0_group(eckey);
+ pubkey = EC_KEY_get0_public_key(eckey);
+ if (eckey == NULL || group == NULL || pubkey == NULL || sig == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS);
+ return -1;
+ }
+
+ if (!EC_KEY_can_sign(eckey)) {
+ ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
+ return -1;
+ }
+
+ ctx = BN_CTX_new_ex(group->libctx);
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+
+ BN_CTX_start(ctx);
+
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+ if (x == NULL || y == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto ret;
+ }
+
+ memset(param, 0, sizeof(param));
+ off = len - (dgstlen > len ? len : dgstlen);
+ memcpy(param + S390X_OFF_H(len) + off, dgst, len - off);
+
+ if (group->meth->point_get_affine_coordinates(group, pubkey,
+ x, y, ctx) != 1
+ || BN_bn2binpad(sig->r, param + S390X_OFF_R(len), len) == -1
+ || BN_bn2binpad(sig->s, param + S390X_OFF_S(len), len) == -1
+ || BN_bn2binpad(x, param + S390X_OFF_X(len), len) == -1
+ || BN_bn2binpad(y, param + S390X_OFF_Y(len), len) == -1) {
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
+ goto ret;
+ }
+
+ rc = s390x_kdsa(fc, param, NULL, 0) == 0 ? 1 : 0;
+ret:
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ return rc;
+}
+
+#define EC_GFP_S390X_NISTP_METHOD(bits) \
+ \
+static int ec_GFp_s390x_nistp##bits##_mul(const EC_GROUP *group, \
+ EC_POINT *r, \
+ const BIGNUM *scalar, \
+ size_t num, \
+ const EC_POINT *points[], \
+ const BIGNUM *scalars[], \
+ BN_CTX *ctx) \
+{ \
+ return ec_GFp_s390x_nistp_mul(group, r, scalar, num, points, \
+ scalars, ctx, \
+ S390X_SCALAR_MULTIPLY_P##bits, \
+ S390X_SIZE_P##bits); \
+} \
+ \
+static ECDSA_SIG *ecdsa_s390x_nistp##bits##_sign_sig(const unsigned \
+ char *dgst, \
+ int dgstlen, \
+ const BIGNUM *kinv,\
+ const BIGNUM *r, \
+ EC_KEY *eckey) \
+{ \
+ return ecdsa_s390x_nistp_sign_sig(dgst, dgstlen, kinv, r, eckey, \
+ S390X_ECDSA_SIGN_P##bits, \
+ S390X_SIZE_P##bits); \
+} \
+ \
+static int ecdsa_s390x_nistp##bits##_verify_sig(const \
+ unsigned char *dgst, \
+ int dgstlen, \
+ const ECDSA_SIG *sig, \
+ EC_KEY *eckey) \
+{ \
+ return ecdsa_s390x_nistp_verify_sig(dgst, dgstlen, sig, eckey, \
+ S390X_ECDSA_VERIFY_P##bits, \
+ S390X_SIZE_P##bits); \
+} \
+ \
+const EC_METHOD *EC_GFp_s390x_nistp##bits##_method(void) \
+{ \
+ static const EC_METHOD EC_GFp_s390x_nistp##bits##_meth = { \
+ EC_FLAGS_DEFAULT_OCT, \
+ NID_X9_62_prime_field, \
+ ossl_ec_GFp_simple_group_init, \
+ ossl_ec_GFp_simple_group_finish, \
+ ossl_ec_GFp_simple_group_clear_finish, \
+ ossl_ec_GFp_simple_group_copy, \
+ ossl_ec_GFp_simple_group_set_curve, \
+ ossl_ec_GFp_simple_group_get_curve, \
+ ossl_ec_GFp_simple_group_get_degree, \
+ ossl_ec_group_simple_order_bits, \
+ ossl_ec_GFp_simple_group_check_discriminant, \
+ ossl_ec_GFp_simple_point_init, \
+ ossl_ec_GFp_simple_point_finish, \
+ ossl_ec_GFp_simple_point_clear_finish, \
+ ossl_ec_GFp_simple_point_copy, \
+ ossl_ec_GFp_simple_point_set_to_infinity, \
+ ossl_ec_GFp_simple_point_set_affine_coordinates, \
+ ossl_ec_GFp_simple_point_get_affine_coordinates, \
+ NULL, /* point_set_compressed_coordinates */ \
+ NULL, /* point2oct */ \
+ NULL, /* oct2point */ \
+ ossl_ec_GFp_simple_add, \
+ ossl_ec_GFp_simple_dbl, \
+ ossl_ec_GFp_simple_invert, \
+ ossl_ec_GFp_simple_is_at_infinity, \
+ ossl_ec_GFp_simple_is_on_curve, \
+ ossl_ec_GFp_simple_cmp, \
+ ossl_ec_GFp_simple_make_affine, \
+ ossl_ec_GFp_simple_points_make_affine, \
+ ec_GFp_s390x_nistp##bits##_mul, \
+ NULL, /* precompute_mult */ \
+ NULL, /* have_precompute_mult */ \
+ ossl_ec_GFp_simple_field_mul, \
+ ossl_ec_GFp_simple_field_sqr, \
+ NULL, /* field_div */ \
+ ossl_ec_GFp_simple_field_inv, \
+ NULL, /* field_encode */ \
+ NULL, /* field_decode */ \
+ NULL, /* field_set_to_one */ \
+ ossl_ec_key_simple_priv2oct, \
+ ossl_ec_key_simple_oct2priv, \
+ NULL, /* set_private */ \
+ ossl_ec_key_simple_generate_key, \
+ ossl_ec_key_simple_check_key, \
+ ossl_ec_key_simple_generate_public_key, \
+ NULL, /* keycopy */ \
+ NULL, /* keyfinish */ \
+ ossl_ecdh_simple_compute_key, \
+ ossl_ecdsa_simple_sign_setup, \
+ ecdsa_s390x_nistp##bits##_sign_sig, \
+ ecdsa_s390x_nistp##bits##_verify_sig, \
+ NULL, /* field_inverse_mod_ord */ \
+ ossl_ec_GFp_simple_blind_coordinates, \
+ ossl_ec_GFp_simple_ladder_pre, \
+ ossl_ec_GFp_simple_ladder_step, \
+ ossl_ec_GFp_simple_ladder_post \
+ }; \
+ static const EC_METHOD *ret; \
+ \
+ if ((OPENSSL_s390xcap_P.pcc[1] \
+ & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P##bits)) \
+ && (OPENSSL_s390xcap_P.kdsa[0] \
+ & S390X_CAPBIT(S390X_ECDSA_VERIFY_P##bits)) \
+ && (OPENSSL_s390xcap_P.kdsa[0] \
+ & S390X_CAPBIT(S390X_ECDSA_SIGN_P##bits))) \
+ ret = &EC_GFp_s390x_nistp##bits##_meth; \
+ else \
+ ret = EC_GFp_mont_method(); \
+ \
+ return ret; \
+}
+
+EC_GFP_S390X_NISTP_METHOD(256)
+EC_GFP_S390X_NISTP_METHOD(384)
+EC_GFP_S390X_NISTP_METHOD(521)
diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c
index b3110ec89dbe..bde8cad34641 100644
--- a/crypto/ec/ecp_smpl.c
+++ b/crypto/ec/ecp_smpl.c
@@ -1,13 +1,19 @@
/*
- * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/err.h>
#include <openssl/symhacks.h>
@@ -18,57 +24,58 @@ const EC_METHOD *EC_GFp_simple_method(void)
static const EC_METHOD ret = {
EC_FLAGS_DEFAULT_OCT,
NID_X9_62_prime_field,
- ec_GFp_simple_group_init,
- ec_GFp_simple_group_finish,
- ec_GFp_simple_group_clear_finish,
- ec_GFp_simple_group_copy,
- ec_GFp_simple_group_set_curve,
- ec_GFp_simple_group_get_curve,
- ec_GFp_simple_group_get_degree,
- ec_group_simple_order_bits,
- ec_GFp_simple_group_check_discriminant,
- ec_GFp_simple_point_init,
- ec_GFp_simple_point_finish,
- ec_GFp_simple_point_clear_finish,
- ec_GFp_simple_point_copy,
- ec_GFp_simple_point_set_to_infinity,
- ec_GFp_simple_set_Jprojective_coordinates_GFp,
- ec_GFp_simple_get_Jprojective_coordinates_GFp,
- ec_GFp_simple_point_set_affine_coordinates,
- ec_GFp_simple_point_get_affine_coordinates,
+ ossl_ec_GFp_simple_group_init,
+ ossl_ec_GFp_simple_group_finish,
+ ossl_ec_GFp_simple_group_clear_finish,
+ ossl_ec_GFp_simple_group_copy,
+ ossl_ec_GFp_simple_group_set_curve,
+ ossl_ec_GFp_simple_group_get_curve,
+ ossl_ec_GFp_simple_group_get_degree,
+ ossl_ec_group_simple_order_bits,
+ ossl_ec_GFp_simple_group_check_discriminant,
+ ossl_ec_GFp_simple_point_init,
+ ossl_ec_GFp_simple_point_finish,
+ ossl_ec_GFp_simple_point_clear_finish,
+ ossl_ec_GFp_simple_point_copy,
+ ossl_ec_GFp_simple_point_set_to_infinity,
+ ossl_ec_GFp_simple_point_set_affine_coordinates,
+ ossl_ec_GFp_simple_point_get_affine_coordinates,
0, 0, 0,
- ec_GFp_simple_add,
- ec_GFp_simple_dbl,
- ec_GFp_simple_invert,
- ec_GFp_simple_is_at_infinity,
- ec_GFp_simple_is_on_curve,
- ec_GFp_simple_cmp,
- ec_GFp_simple_make_affine,
- ec_GFp_simple_points_make_affine,
+ ossl_ec_GFp_simple_add,
+ ossl_ec_GFp_simple_dbl,
+ ossl_ec_GFp_simple_invert,
+ ossl_ec_GFp_simple_is_at_infinity,
+ ossl_ec_GFp_simple_is_on_curve,
+ ossl_ec_GFp_simple_cmp,
+ ossl_ec_GFp_simple_make_affine,
+ ossl_ec_GFp_simple_points_make_affine,
0 /* mul */ ,
0 /* precompute_mult */ ,
0 /* have_precompute_mult */ ,
- ec_GFp_simple_field_mul,
- ec_GFp_simple_field_sqr,
+ ossl_ec_GFp_simple_field_mul,
+ ossl_ec_GFp_simple_field_sqr,
0 /* field_div */ ,
- ec_GFp_simple_field_inv,
+ ossl_ec_GFp_simple_field_inv,
0 /* field_encode */ ,
0 /* field_decode */ ,
0, /* field_set_to_one */
- ec_key_simple_priv2oct,
- ec_key_simple_oct2priv,
+ ossl_ec_key_simple_priv2oct,
+ ossl_ec_key_simple_oct2priv,
0, /* set private */
- ec_key_simple_generate_key,
- ec_key_simple_check_key,
- ec_key_simple_generate_public_key,
+ ossl_ec_key_simple_generate_key,
+ ossl_ec_key_simple_check_key,
+ ossl_ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
- ecdh_simple_compute_key,
+ ossl_ecdh_simple_compute_key,
+ ossl_ecdsa_simple_sign_setup,
+ ossl_ecdsa_simple_sign_sig,
+ ossl_ecdsa_simple_verify_sig,
0, /* field_inverse_mod_ord */
- ec_GFp_simple_blind_coordinates,
- ec_GFp_simple_ladder_pre,
- ec_GFp_simple_ladder_step,
- ec_GFp_simple_ladder_post
+ ossl_ec_GFp_simple_blind_coordinates,
+ ossl_ec_GFp_simple_ladder_pre,
+ ossl_ec_GFp_simple_ladder_step,
+ ossl_ec_GFp_simple_ladder_post
};
return &ret;
@@ -88,7 +95,7 @@ const EC_METHOD *EC_GFp_simple_method(void)
* representation (i.e. 'encoding' means multiplying by some factor R).
*/
-int ec_GFp_simple_group_init(EC_GROUP *group)
+int ossl_ec_GFp_simple_group_init(EC_GROUP *group)
{
group->field = BN_new();
group->a = BN_new();
@@ -103,21 +110,21 @@ int ec_GFp_simple_group_init(EC_GROUP *group)
return 1;
}
-void ec_GFp_simple_group_finish(EC_GROUP *group)
+void ossl_ec_GFp_simple_group_finish(EC_GROUP *group)
{
BN_free(group->field);
BN_free(group->a);
BN_free(group->b);
}
-void ec_GFp_simple_group_clear_finish(EC_GROUP *group)
+void ossl_ec_GFp_simple_group_clear_finish(EC_GROUP *group)
{
BN_clear_free(group->field);
BN_clear_free(group->a);
BN_clear_free(group->b);
}
-int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
+int ossl_ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
{
if (!BN_copy(dest->field, src->field))
return 0;
@@ -131,9 +138,9 @@ int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
return 1;
}
-int ec_GFp_simple_group_set_curve(EC_GROUP *group,
- const BIGNUM *p, const BIGNUM *a,
- const BIGNUM *b, BN_CTX *ctx)
+int ossl_ec_GFp_simple_group_set_curve(EC_GROUP *group,
+ const BIGNUM *p, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *ctx)
{
int ret = 0;
BN_CTX *new_ctx = NULL;
@@ -141,12 +148,12 @@ int ec_GFp_simple_group_set_curve(EC_GROUP *group,
/* p must be a prime > 3 */
if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) {
- ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
return 0;
}
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
return 0;
}
@@ -190,8 +197,8 @@ int ec_GFp_simple_group_set_curve(EC_GROUP *group,
return ret;
}
-int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
- BIGNUM *b, BN_CTX *ctx)
+int ossl_ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p,
+ BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
{
int ret = 0;
BN_CTX *new_ctx = NULL;
@@ -204,7 +211,7 @@ int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
if (a != NULL || b != NULL) {
if (group->meth->field_decode) {
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
return 0;
}
@@ -235,12 +242,13 @@ int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
return ret;
}
-int ec_GFp_simple_group_get_degree(const EC_GROUP *group)
+int ossl_ec_GFp_simple_group_get_degree(const EC_GROUP *group)
{
return BN_num_bits(group->field);
}
-int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
+int ossl_ec_GFp_simple_group_check_discriminant(const EC_GROUP *group,
+ BN_CTX *ctx)
{
int ret = 0;
BIGNUM *a, *b, *order, *tmp_1, *tmp_2;
@@ -248,10 +256,9 @@ int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
BN_CTX *new_ctx = NULL;
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL) {
- ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -312,7 +319,7 @@ int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
return ret;
}
-int ec_GFp_simple_point_init(EC_POINT *point)
+int ossl_ec_GFp_simple_point_init(EC_POINT *point)
{
point->X = BN_new();
point->Y = BN_new();
@@ -328,14 +335,14 @@ int ec_GFp_simple_point_init(EC_POINT *point)
return 1;
}
-void ec_GFp_simple_point_finish(EC_POINT *point)
+void ossl_ec_GFp_simple_point_finish(EC_POINT *point)
{
BN_free(point->X);
BN_free(point->Y);
BN_free(point->Z);
}
-void ec_GFp_simple_point_clear_finish(EC_POINT *point)
+void ossl_ec_GFp_simple_point_clear_finish(EC_POINT *point)
{
BN_clear_free(point->X);
BN_clear_free(point->Y);
@@ -343,7 +350,7 @@ void ec_GFp_simple_point_clear_finish(EC_POINT *point)
point->Z_is_one = 0;
}
-int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
+int ossl_ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
{
if (!BN_copy(dest->X, src->X))
return 0;
@@ -357,26 +364,26 @@ int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
return 1;
}
-int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group,
- EC_POINT *point)
+int ossl_ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group,
+ EC_POINT *point)
{
point->Z_is_one = 0;
BN_zero(point->Z);
return 1;
}
-int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
- EC_POINT *point,
- const BIGNUM *x,
- const BIGNUM *y,
- const BIGNUM *z,
- BN_CTX *ctx)
+int ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
+ EC_POINT *point,
+ const BIGNUM *x,
+ const BIGNUM *y,
+ const BIGNUM *z,
+ BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
int ret = 0;
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
return 0;
}
@@ -425,17 +432,17 @@ int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
return ret;
}
-int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
- const EC_POINT *point,
- BIGNUM *x, BIGNUM *y,
- BIGNUM *z, BN_CTX *ctx)
+int ossl_ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BIGNUM *z, BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
int ret = 0;
if (group->meth->field_decode != 0) {
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
return 0;
}
@@ -474,17 +481,16 @@ int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
return ret;
}
-int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group,
- EC_POINT *point,
- const BIGNUM *x,
- const BIGNUM *y, BN_CTX *ctx)
+int ossl_ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group,
+ EC_POINT *point,
+ const BIGNUM *x,
+ const BIGNUM *y, BN_CTX *ctx)
{
if (x == NULL || y == NULL) {
/*
* unlike for projective coordinates, we do not tolerate this
*/
- ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES,
- ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
@@ -492,10 +498,10 @@ int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group,
BN_value_one(), ctx);
}
-int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
- const EC_POINT *point,
- BIGNUM *x, BIGNUM *y,
- BN_CTX *ctx)
+int ossl_ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
BIGNUM *Z, *Z_1, *Z_2, *Z_3;
@@ -503,13 +509,12 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
int ret = 0;
if (EC_POINT_is_at_infinity(group, point)) {
- ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES,
- EC_R_POINT_AT_INFINITY);
+ ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY);
return 0;
}
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
return 0;
}
@@ -554,8 +559,7 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
}
} else {
if (!group->meth->field_inv(group, Z_1, Z_, ctx)) {
- ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES,
- ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
@@ -606,8 +610,8 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
return ret;
}
-int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
- const EC_POINT *b, BN_CTX *ctx)
+int ossl_ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
+ const EC_POINT *b, BN_CTX *ctx)
{
int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
const BIGNUM *, BN_CTX *);
@@ -629,7 +633,7 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
p = group->field;
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
return 0;
}
@@ -791,8 +795,8 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
return ret;
}
-int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
- BN_CTX *ctx)
+int ossl_ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
+ BN_CTX *ctx)
{
int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
const BIGNUM *, BN_CTX *);
@@ -813,7 +817,7 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
p = group->field;
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
return 0;
}
@@ -933,7 +937,8 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
return ret;
}
-int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
+int ossl_ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point,
+ BN_CTX *ctx)
{
if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y))
/* point is its own inverse */
@@ -942,13 +947,14 @@ int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
return BN_usub(point->Y, group->field, point->Y);
}
-int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
+int ossl_ec_GFp_simple_is_at_infinity(const EC_GROUP *group,
+ const EC_POINT *point)
{
return BN_is_zero(point->Z);
}
-int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
- BN_CTX *ctx)
+int ossl_ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
+ BN_CTX *ctx)
{
int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
const BIGNUM *, BN_CTX *);
@@ -966,7 +972,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
p = group->field;
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
return -1;
}
@@ -1050,8 +1056,8 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
return ret;
}
-int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
- const EC_POINT *b, BN_CTX *ctx)
+int ossl_ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
+ const EC_POINT *b, BN_CTX *ctx)
{
/*-
* return values:
@@ -1083,7 +1089,7 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
field_sqr = group->meth->field_sqr;
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
return -1;
}
@@ -1158,8 +1164,8 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
return ret;
}
-int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
- BN_CTX *ctx)
+int ossl_ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
+ BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
BIGNUM *x, *y;
@@ -1169,7 +1175,7 @@ int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
return 1;
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
return 0;
}
@@ -1185,7 +1191,7 @@ int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
goto err;
if (!point->Z_is_one) {
- ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -1197,8 +1203,8 @@ int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
return ret;
}
-int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
- EC_POINT *points[], BN_CTX *ctx)
+int ossl_ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
+ EC_POINT *points[], BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
BIGNUM *tmp, *tmp_Z;
@@ -1210,7 +1216,7 @@ int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
return 1;
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
return 0;
}
@@ -1266,7 +1272,7 @@ int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
*/
if (!group->meth->field_inv(group, tmp, prod_Z[num - 1], ctx)) {
- ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
if (group->meth->field_encode != 0) {
@@ -1356,14 +1362,14 @@ int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
return ret;
}
-int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
- const BIGNUM *b, BN_CTX *ctx)
+int ossl_ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *ctx)
{
return BN_mod_mul(r, a, b, group->field, ctx);
}
-int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
- BN_CTX *ctx)
+int ossl_ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *ctx)
{
return BN_mod_sqr(r, a, group->field, ctx);
}
@@ -1374,14 +1380,15 @@ int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
* Since we don't have a Mont structure here, SCA hardening is with blinding.
* NB: "a" must be in _decoded_ form. (i.e. field_decode must precede.)
*/
-int ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
- BN_CTX *ctx)
+int ossl_ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r,
+ const BIGNUM *a, BN_CTX *ctx)
{
BIGNUM *e = NULL;
BN_CTX *new_ctx = NULL;
int ret = 0;
- if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL)
+ if (ctx == NULL
+ && (ctx = new_ctx = BN_CTX_secure_new_ex(group->libctx)) == NULL)
return 0;
BN_CTX_start(ctx);
@@ -1389,7 +1396,7 @@ int ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
goto err;
do {
- if (!BN_priv_rand_range(e, group->field))
+ if (!BN_priv_rand_range_ex(e, group->field, 0, ctx))
goto err;
} while (BN_is_zero(e));
@@ -1398,7 +1405,7 @@ int ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
goto err;
/* r := 1/(a * e) */
if (!BN_mod_inverse(r, r, group->field, ctx)) {
- ECerr(EC_F_EC_GFP_SIMPLE_FIELD_INV, EC_R_CANNOT_INVERT);
+ ERR_raise(ERR_LIB_EC, EC_R_CANNOT_INVERT);
goto err;
}
/* r := e/(a * e) = 1/a */
@@ -1420,8 +1427,8 @@ int ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
* lambda = [1,group->field)
*
*/
-int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
- BN_CTX *ctx)
+int ossl_ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
+ BN_CTX *ctx)
{
int ret = 0;
BIGNUM *lambda = NULL;
@@ -1431,7 +1438,7 @@ int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
lambda = BN_CTX_get(ctx);
temp = BN_CTX_get(ctx);
if (temp == NULL) {
- ECerr(EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto end;
}
@@ -1442,7 +1449,7 @@ int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
*/
do {
ERR_set_mark();
- ret = BN_priv_rand_range(lambda, group->field);
+ ret = BN_priv_rand_range_ex(lambda, group->field, 0, ctx);
ERR_pop_to_mark();
if (ret == 0) {
ret = 1;
@@ -1483,9 +1490,9 @@ int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
* Blinding uses the equivalence relation (\lambda X, \lambda Y, \lambda Z)
* for any non-zero \lambda that holds for projective (homogeneous) coords.
*/
-int ec_GFp_simple_ladder_pre(const EC_GROUP *group,
- EC_POINT *r, EC_POINT *s,
- EC_POINT *p, BN_CTX *ctx)
+int ossl_ec_GFp_simple_ladder_pre(const EC_GROUP *group,
+ EC_POINT *r, EC_POINT *s,
+ EC_POINT *p, BN_CTX *ctx)
{
BIGNUM *t1, *t2, *t3, *t4, *t5 = NULL;
@@ -1512,13 +1519,13 @@ int ec_GFp_simple_ladder_pre(const EC_GROUP *group,
/* make sure lambda (r->Y here for storage) is not zero */
do {
- if (!BN_priv_rand_range(r->Y, group->field))
+ if (!BN_priv_rand_range_ex(r->Y, group->field, 0, ctx))
return 0;
} while (BN_is_zero(r->Y));
/* make sure lambda (s->Z here for storage) is not zero */
do {
- if (!BN_priv_rand_range(s->Z, group->field))
+ if (!BN_priv_rand_range_ex(s->Z, group->field, 0, ctx))
return 0;
} while (BN_is_zero(s->Z));
@@ -1553,9 +1560,9 @@ int ec_GFp_simple_ladder_pre(const EC_GROUP *group,
* attacks", as described at
* https://hyperelliptic.org/EFD/g1p/auto-shortw-xz.html#ladder-mladd-2002-it-4
*/
-int ec_GFp_simple_ladder_step(const EC_GROUP *group,
- EC_POINT *r, EC_POINT *s,
- EC_POINT *p, BN_CTX *ctx)
+int ossl_ec_GFp_simple_ladder_step(const EC_GROUP *group,
+ EC_POINT *r, EC_POINT *s,
+ EC_POINT *p, BN_CTX *ctx)
{
int ret = 0;
BIGNUM *t0, *t1, *t2, *t3, *t4, *t5, *t6 = NULL;
@@ -1641,9 +1648,9 @@ int ec_GFp_simple_ladder_step(const EC_GROUP *group,
* - Y1==0 implies p has order 2, so either r or s are infinity and handled by
* one of the BN_is_zero(...) branches.
*/
-int ec_GFp_simple_ladder_post(const EC_GROUP *group,
- EC_POINT *r, EC_POINT *s,
- EC_POINT *p, BN_CTX *ctx)
+int ossl_ec_GFp_simple_ladder_post(const EC_GROUP *group,
+ EC_POINT *r, EC_POINT *s,
+ EC_POINT *p, BN_CTX *ctx)
{
int ret = 0;
BIGNUM *t0, *t1, *t2, *t3, *t4, *t5, *t6 = NULL;
diff --git a/crypto/ec/ecx_backend.c b/crypto/ec/ecx_backend.c
new file mode 100644
index 000000000000..2ab7611be9af
--- /dev/null
+++ b/crypto/ec/ecx_backend.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/ec.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#ifndef FIPS_MODULE
+# include <openssl/x509.h>
+#endif
+#include "crypto/ecx.h"
+#include "ecx_backend.h"
+
+/*
+ * The intention with the "backend" source file is to offer backend support
+ * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
+ * implementations alike.
+ */
+
+int ossl_ecx_public_from_private(ECX_KEY *key)
+{
+ switch (key->type) {
+ case ECX_KEY_TYPE_X25519:
+ ossl_x25519_public_from_private(key->pubkey, key->privkey);
+ break;
+ case ECX_KEY_TYPE_ED25519:
+ if (!ossl_ed25519_public_from_private(key->libctx, key->pubkey,
+ key->privkey, key->propq)) {
+ ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY);
+ return 0;
+ }
+ break;
+ case ECX_KEY_TYPE_X448:
+ ossl_x448_public_from_private(key->pubkey, key->privkey);
+ break;
+ case ECX_KEY_TYPE_ED448:
+ if (!ossl_ed448_public_from_private(key->libctx, key->pubkey,
+ key->privkey, key->propq)) {
+ ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY);
+ return 0;
+ }
+ break;
+ }
+ return 1;
+}
+
+int ossl_ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
+ int include_private)
+{
+ size_t privkeylen = 0, pubkeylen = 0;
+ const OSSL_PARAM *param_priv_key = NULL, *param_pub_key;
+ unsigned char *pubkey;
+
+ if (ecx == NULL)
+ return 0;
+
+ param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
+ if (include_private)
+ param_priv_key =
+ OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
+
+ if (param_pub_key == NULL && param_priv_key == NULL)
+ return 0;
+
+ if (param_priv_key != NULL) {
+ if (!OSSL_PARAM_get_octet_string(param_priv_key,
+ (void **)&ecx->privkey, ecx->keylen,
+ &privkeylen))
+ return 0;
+ if (privkeylen != ecx->keylen) {
+ /*
+ * Invalid key length. We will clear what we've received now. We
+ * can't leave it to ossl_ecx_key_free() because that will call
+ * OPENSSL_secure_clear_free() and assume the correct key length
+ */
+ OPENSSL_secure_clear_free(ecx->privkey, privkeylen);
+ ecx->privkey = NULL;
+ return 0;
+ }
+ }
+
+
+ pubkey = ecx->pubkey;
+ if (param_pub_key != NULL
+ && !OSSL_PARAM_get_octet_string(param_pub_key,
+ (void **)&pubkey,
+ sizeof(ecx->pubkey), &pubkeylen))
+ return 0;
+
+ if ((param_pub_key != NULL && pubkeylen != ecx->keylen))
+ return 0;
+
+ if (param_pub_key == NULL && !ossl_ecx_public_from_private(ecx))
+ return 0;
+
+ ecx->haspubkey = 1;
+
+ return 1;
+}
+
+ECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key, int selection)
+{
+ ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret));
+
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ ret->lock = CRYPTO_THREAD_lock_new();
+ if (ret->lock == NULL) {
+ OPENSSL_free(ret);
+ return NULL;
+ }
+
+ ret->libctx = key->libctx;
+ ret->haspubkey = key->haspubkey;
+ ret->keylen = key->keylen;
+ ret->type = key->type;
+ ret->references = 1;
+
+ if (key->propq != NULL) {
+ ret->propq = OPENSSL_strdup(key->propq);
+ if (ret->propq == NULL)
+ goto err;
+ }
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ memcpy(ret->pubkey, key->pubkey, sizeof(ret->pubkey));
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
+ && key->privkey != NULL) {
+ if (ossl_ecx_key_allocate_privkey(ret) == NULL)
+ goto err;
+ memcpy(ret->privkey, key->privkey, ret->keylen);
+ }
+
+ return ret;
+
+err:
+ ossl_ecx_key_free(ret);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ return NULL;
+}
+
+#ifndef FIPS_MODULE
+ECX_KEY *ossl_ecx_key_op(const X509_ALGOR *palg,
+ const unsigned char *p, int plen,
+ int id, ecx_key_op_t op,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ ECX_KEY *key = NULL;
+ unsigned char *privkey, *pubkey;
+
+ if (op != KEY_OP_KEYGEN) {
+ if (palg != NULL) {
+ int ptype;
+
+ /* Algorithm parameters must be absent */
+ X509_ALGOR_get0(NULL, &ptype, NULL, palg);
+ if (ptype != V_ASN1_UNDEF) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
+ return 0;
+ }
+ if (id == EVP_PKEY_NONE)
+ id = OBJ_obj2nid(palg->algorithm);
+ else if (id != OBJ_obj2nid(palg->algorithm)) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
+ return 0;
+ }
+ }
+
+ if (p == NULL || id == EVP_PKEY_NONE || plen != KEYLENID(id)) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
+ return 0;
+ }
+ }
+
+ key = ossl_ecx_key_new(libctx, KEYNID2TYPE(id), 1, propq);
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ pubkey = key->pubkey;
+
+ if (op == KEY_OP_PUBLIC) {
+ memcpy(pubkey, p, plen);
+ } else {
+ privkey = ossl_ecx_key_allocate_privkey(key);
+ if (privkey == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (op == KEY_OP_KEYGEN) {
+ if (id != EVP_PKEY_NONE) {
+ if (RAND_priv_bytes_ex(libctx, privkey, KEYLENID(id), 0) <= 0)
+ goto err;
+ if (id == EVP_PKEY_X25519) {
+ privkey[0] &= 248;
+ privkey[X25519_KEYLEN - 1] &= 127;
+ privkey[X25519_KEYLEN - 1] |= 64;
+ } else if (id == EVP_PKEY_X448) {
+ privkey[0] &= 252;
+ privkey[X448_KEYLEN - 1] |= 128;
+ }
+ }
+ } else {
+ memcpy(privkey, p, KEYLENID(id));
+ }
+ if (!ossl_ecx_public_from_private(key)) {
+ ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY);
+ goto err;
+ }
+ }
+
+ return key;
+ err:
+ ossl_ecx_key_free(key);
+ return NULL;
+}
+
+ECX_KEY *ossl_ecx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ ECX_KEY *ecx = NULL;
+ const unsigned char *p;
+ int plen;
+ ASN1_OCTET_STRING *oct = NULL;
+ const X509_ALGOR *palg;
+
+ if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8inf))
+ return 0;
+
+ oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen);
+ if (oct == NULL) {
+ p = NULL;
+ plen = 0;
+ } else {
+ p = ASN1_STRING_get0_data(oct);
+ plen = ASN1_STRING_length(oct);
+ }
+
+ /*
+ * EVP_PKEY_NONE means that ecx_key_op() has to figure out the key type
+ * on its own.
+ */
+ ecx = ossl_ecx_key_op(palg, p, plen, EVP_PKEY_NONE, KEY_OP_PRIVATE,
+ libctx, propq);
+ ASN1_OCTET_STRING_free(oct);
+ return ecx;
+}
+#endif
diff --git a/crypto/ec/ecx_backend.h b/crypto/ec/ecx_backend.h
new file mode 100644
index 000000000000..2c01294789b3
--- /dev/null
+++ b/crypto/ec/ecx_backend.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#define ISX448(id) ((id) == EVP_PKEY_X448)
+#define IS25519(id) ((id) == EVP_PKEY_X25519 || (id) == EVP_PKEY_ED25519)
+#define KEYLENID(id) (IS25519(id) ? X25519_KEYLEN \
+ : ((id) == EVP_PKEY_X448 ? X448_KEYLEN \
+ : ED448_KEYLEN))
+#define KEYNID2TYPE(id) \
+ (IS25519(id) ? ((id) == EVP_PKEY_X25519 ? ECX_KEY_TYPE_X25519 \
+ : ECX_KEY_TYPE_ED25519) \
+ : ((id) == EVP_PKEY_X448 ? ECX_KEY_TYPE_X448 \
+ : ECX_KEY_TYPE_ED448))
+#define KEYLEN(p) KEYLENID((p)->ameth->pkey_id)
diff --git a/crypto/ec/ecx_key.c b/crypto/ec/ecx_key.c
new file mode 100644
index 000000000000..dcec26c2e9b3
--- /dev/null
+++ b/crypto/ec/ecx_key.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/err.h>
+#include "crypto/ecx.h"
+
+ECX_KEY *ossl_ecx_key_new(OSSL_LIB_CTX *libctx, ECX_KEY_TYPE type, int haspubkey,
+ const char *propq)
+{
+ ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret));
+
+ if (ret == NULL)
+ return NULL;
+
+ ret->libctx = libctx;
+ ret->haspubkey = haspubkey;
+ switch (type) {
+ case ECX_KEY_TYPE_X25519:
+ ret->keylen = X25519_KEYLEN;
+ break;
+ case ECX_KEY_TYPE_X448:
+ ret->keylen = X448_KEYLEN;
+ break;
+ case ECX_KEY_TYPE_ED25519:
+ ret->keylen = ED25519_KEYLEN;
+ break;
+ case ECX_KEY_TYPE_ED448:
+ ret->keylen = ED448_KEYLEN;
+ break;
+ }
+ ret->type = type;
+ ret->references = 1;
+
+ if (propq != NULL) {
+ ret->propq = OPENSSL_strdup(propq);
+ if (ret->propq == NULL)
+ goto err;
+ }
+
+ ret->lock = CRYPTO_THREAD_lock_new();
+ if (ret->lock == NULL)
+ goto err;
+ return ret;
+err:
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(ret);
+ return NULL;
+}
+
+void ossl_ecx_key_free(ECX_KEY *key)
+{
+ int i;
+
+ if (key == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&key->references, &i, key->lock);
+ REF_PRINT_COUNT("ECX_KEY", key);
+ if (i > 0)
+ return;
+ REF_ASSERT_ISNT(i < 0);
+
+ OPENSSL_free(key->propq);
+ OPENSSL_secure_clear_free(key->privkey, key->keylen);
+ CRYPTO_THREAD_lock_free(key->lock);
+ OPENSSL_free(key);
+}
+
+void ossl_ecx_key_set0_libctx(ECX_KEY *key, OSSL_LIB_CTX *libctx)
+{
+ key->libctx = libctx;
+}
+
+int ossl_ecx_key_up_ref(ECX_KEY *key)
+{
+ int i;
+
+ if (CRYPTO_UP_REF(&key->references, &i, key->lock) <= 0)
+ return 0;
+
+ REF_PRINT_COUNT("ECX_KEY", key);
+ REF_ASSERT_ISNT(i < 2);
+ return ((i > 1) ? 1 : 0);
+}
+
+unsigned char *ossl_ecx_key_allocate_privkey(ECX_KEY *key)
+{
+ key->privkey = OPENSSL_secure_zalloc(key->keylen);
+
+ return key->privkey;
+}
diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c
index 9dc5259e4afc..4e32210bf436 100644
--- a/crypto/ec/ecx_meth.c
+++ b/crypto/ec/ecx_meth.c
@@ -1,126 +1,32 @@
/*
- * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
-#include "internal/cryptlib.h"
#include <openssl/x509.h>
#include <openssl/ec.h>
+#include <openssl/core_names.h>
+#include <openssl/param_build.h>
#include <openssl/rand.h>
+#include "internal/cryptlib.h"
+#include "internal/provider.h"
#include "crypto/asn1.h"
#include "crypto/evp.h"
+#include "crypto/ecx.h"
#include "ec_local.h"
#include "curve448/curve448_local.h"
-
-#define X25519_BITS 253
-#define X25519_SECURITY_BITS 128
-
-#define ED25519_SIGSIZE 64
-
-#define X448_BITS 448
-#define ED448_BITS 456
-#define X448_SECURITY_BITS 224
-
-#define ED448_SIGSIZE 114
-
-#define ISX448(id) ((id) == EVP_PKEY_X448)
-#define IS25519(id) ((id) == EVP_PKEY_X25519 || (id) == EVP_PKEY_ED25519)
-#define KEYLENID(id) (IS25519(id) ? X25519_KEYLEN \
- : ((id) == EVP_PKEY_X448 ? X448_KEYLEN \
- : ED448_KEYLEN))
-#define KEYLEN(p) KEYLENID((p)->ameth->pkey_id)
-
-
-typedef enum {
- KEY_OP_PUBLIC,
- KEY_OP_PRIVATE,
- KEY_OP_KEYGEN
-} ecx_key_op_t;
-
-/* Setup EVP_PKEY using public, private or generation */
-static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg,
- const unsigned char *p, int plen, ecx_key_op_t op)
-{
- ECX_KEY *key = NULL;
- unsigned char *privkey, *pubkey;
-
- if (op != KEY_OP_KEYGEN) {
- if (palg != NULL) {
- int ptype;
-
- /* Algorithm parameters must be absent */
- X509_ALGOR_get0(NULL, &ptype, NULL, palg);
- if (ptype != V_ASN1_UNDEF) {
- ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING);
- return 0;
- }
- }
-
- if (p == NULL || plen != KEYLENID(id)) {
- ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING);
- return 0;
- }
- }
-
- key = OPENSSL_zalloc(sizeof(*key));
- if (key == NULL) {
- ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- pubkey = key->pubkey;
-
- if (op == KEY_OP_PUBLIC) {
- memcpy(pubkey, p, plen);
- } else {
- privkey = key->privkey = OPENSSL_secure_malloc(KEYLENID(id));
- if (privkey == NULL) {
- ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if (op == KEY_OP_KEYGEN) {
- if (RAND_priv_bytes(privkey, KEYLENID(id)) <= 0) {
- OPENSSL_secure_free(privkey);
- key->privkey = NULL;
- goto err;
- }
- if (id == EVP_PKEY_X25519) {
- privkey[0] &= 248;
- privkey[X25519_KEYLEN - 1] &= 127;
- privkey[X25519_KEYLEN - 1] |= 64;
- } else if (id == EVP_PKEY_X448) {
- privkey[0] &= 252;
- privkey[X448_KEYLEN - 1] |= 128;
- }
- } else {
- memcpy(privkey, p, KEYLENID(id));
- }
- switch (id) {
- case EVP_PKEY_X25519:
- X25519_public_from_private(pubkey, privkey);
- break;
- case EVP_PKEY_ED25519:
- ED25519_public_from_private(pubkey, privkey);
- break;
- case EVP_PKEY_X448:
- X448_public_from_private(pubkey, privkey);
- break;
- case EVP_PKEY_ED448:
- ED448_public_from_private(pubkey, privkey);
- break;
- }
- }
-
- EVP_PKEY_assign(pkey, id, key);
- return 1;
- err:
- OPENSSL_free(key);
- return 0;
-}
+#include "ecx_backend.h"
static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
{
@@ -128,35 +34,42 @@ static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
unsigned char *penc;
if (ecxkey == NULL) {
- ECerr(EC_F_ECX_PUB_ENCODE, EC_R_INVALID_KEY);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
return 0;
}
penc = OPENSSL_memdup(ecxkey->pubkey, KEYLEN(pkey));
if (penc == NULL) {
- ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
V_ASN1_UNDEF, NULL, penc, KEYLEN(pkey))) {
OPENSSL_free(penc);
- ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
}
-static int ecx_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
+static int ecx_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
{
const unsigned char *p;
int pklen;
X509_ALGOR *palg;
+ ECX_KEY *ecx;
+ int ret = 0;
if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
return 0;
- return ecx_key_op(pkey, pkey->ameth->pkey_id, palg, p, pklen,
- KEY_OP_PUBLIC);
+ ecx = ossl_ecx_key_op(palg, p, pklen, pkey->ameth->pkey_id,
+ KEY_OP_PUBLIC, NULL, NULL);
+ if (ecx != NULL) {
+ ret = 1;
+ EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
+ }
+ return ret;
}
static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
@@ -170,29 +83,18 @@ static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
return CRYPTO_memcmp(akey->pubkey, bkey->pubkey, KEYLEN(a)) == 0;
}
-static int ecx_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
+static int ecx_priv_decode_ex(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
- const unsigned char *p;
- int plen;
- ASN1_OCTET_STRING *oct = NULL;
- const X509_ALGOR *palg;
- int rv;
+ int ret = 0;
+ ECX_KEY *ecx = ossl_ecx_key_from_pkcs8(p8, libctx, propq);
- if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8))
- return 0;
-
- oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen);
- if (oct == NULL) {
- p = NULL;
- plen = 0;
- } else {
- p = ASN1_STRING_get0_data(oct);
- plen = ASN1_STRING_length(oct);
+ if (ecx != NULL) {
+ ret = 1;
+ EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
}
- rv = ecx_key_op(pkey, pkey->ameth->pkey_id, palg, p, plen, KEY_OP_PRIVATE);
- ASN1_STRING_clear_free(oct);
- return rv;
+ return ret;
}
static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
@@ -203,7 +105,7 @@ static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
int penclen;
if (ecxkey == NULL || ecxkey->privkey == NULL) {
- ECerr(EC_F_ECX_PRIV_ENCODE, EC_R_INVALID_PRIVATE_KEY);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
return 0;
}
@@ -213,14 +115,14 @@ static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
penclen = i2d_ASN1_OCTET_STRING(&oct, &penc);
if (penclen < 0) {
- ECerr(EC_F_ECX_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
V_ASN1_UNDEF, NULL, penc, penclen)) {
OPENSSL_clear_free(penc, penclen);
- ECerr(EC_F_ECX_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -254,9 +156,7 @@ static int ecx_security_bits(const EVP_PKEY *pkey)
static void ecx_free(EVP_PKEY *pkey)
{
- if (pkey->pkey.ecx != NULL)
- OPENSSL_secure_clear_free(pkey->pkey.ecx->privkey, KEYLEN(pkey));
- OPENSSL_free(pkey->pkey.ecx);
+ ossl_ecx_key_free(pkey->pkey.ecx);
}
/* "parameters" are always equal */
@@ -318,10 +218,16 @@ static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
{
switch (op) {
- case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
- return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, arg2, arg1,
- KEY_OP_PUBLIC);
+ case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: {
+ ECX_KEY *ecx = ossl_ecx_key_op(NULL, arg2, arg1, pkey->ameth->pkey_id,
+ KEY_OP_PUBLIC, NULL, NULL);
+ if (ecx != NULL) {
+ EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
+ return 1;
+ }
+ return 0;
+ }
case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
if (pkey->pkey.ecx != NULL) {
unsigned char **ppt = arg2;
@@ -355,14 +261,38 @@ static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
static int ecx_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
size_t len)
{
- return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, priv, len,
- KEY_OP_PRIVATE);
+ OSSL_LIB_CTX *libctx = NULL;
+ ECX_KEY *ecx = NULL;
+
+ if (pkey->keymgmt != NULL)
+ libctx = ossl_provider_libctx(EVP_KEYMGMT_get0_provider(pkey->keymgmt));
+
+ ecx = ossl_ecx_key_op(NULL, priv, len, pkey->ameth->pkey_id,
+ KEY_OP_PRIVATE, libctx, NULL);
+
+ if (ecx != NULL) {
+ EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
+ return 1;
+ }
+ return 0;
}
static int ecx_set_pub_key(EVP_PKEY *pkey, const unsigned char *pub, size_t len)
{
- return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, pub, len,
- KEY_OP_PUBLIC);
+ OSSL_LIB_CTX *libctx = NULL;
+ ECX_KEY *ecx = NULL;
+
+ if (pkey->keymgmt != NULL)
+ libctx = ossl_provider_libctx(EVP_KEYMGMT_get0_provider(pkey->keymgmt));
+
+ ecx = ossl_ecx_key_op(NULL, pub, len, pkey->ameth->pkey_id,
+ KEY_OP_PUBLIC, libctx, NULL);
+
+ if (ecx != NULL) {
+ EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
+ return 1;
+ }
+ return 0;
}
static int ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
@@ -406,7 +336,97 @@ static int ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *pub,
return 1;
}
-const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = {
+static size_t ecx_pkey_dirty_cnt(const EVP_PKEY *pkey)
+{
+ /*
+ * We provide no mechanism to "update" an ECX key once it has been set,
+ * therefore we do not have to maintain a dirty count.
+ */
+ return 1;
+}
+
+static int ecx_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
+ OSSL_FUNC_keymgmt_import_fn *importer,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ const ECX_KEY *key = from->pkey.ecx;
+ OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new();
+ OSSL_PARAM *params = NULL;
+ int selection = 0;
+ int rv = 0;
+
+ if (tmpl == NULL)
+ return 0;
+
+ /* A key must at least have a public part */
+ if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
+ key->pubkey, key->keylen))
+ goto err;
+ selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+
+ if (key->privkey != NULL) {
+ if (!OSSL_PARAM_BLD_push_octet_string(tmpl,
+ OSSL_PKEY_PARAM_PRIV_KEY,
+ key->privkey, key->keylen))
+ goto err;
+ selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
+ }
+
+ params = OSSL_PARAM_BLD_to_param(tmpl);
+
+ /* We export, the provider imports */
+ rv = importer(to_keydata, selection, params);
+
+ err:
+ OSSL_PARAM_BLD_free(tmpl);
+ OSSL_PARAM_free(params);
+ return rv;
+}
+
+static int ecx_generic_import_from(const OSSL_PARAM params[], void *vpctx,
+ int keytype)
+{
+ EVP_PKEY_CTX *pctx = vpctx;
+ EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
+ ECX_KEY *ecx = ossl_ecx_key_new(pctx->libctx, KEYNID2TYPE(keytype), 0,
+ pctx->propquery);
+
+ if (ecx == NULL) {
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (!ossl_ecx_key_fromdata(ecx, params, 1)
+ || !EVP_PKEY_assign(pkey, keytype, ecx)) {
+ ossl_ecx_key_free(ecx);
+ return 0;
+ }
+ return 1;
+}
+
+static int ecx_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
+{
+ ECX_KEY *ecx = from->pkey.ecx, *dupkey = NULL;
+ int ret;
+
+ if (ecx != NULL) {
+ dupkey = ossl_ecx_key_dup(ecx, OSSL_KEYMGMT_SELECT_ALL);
+ if (dupkey == NULL)
+ return 0;
+ }
+
+ ret = EVP_PKEY_assign(to, from->type, dupkey);
+ if (!ret)
+ ossl_ecx_key_free(dupkey);
+ return ret;
+}
+
+static int x25519_import_from(const OSSL_PARAM params[], void *vpctx)
+{
+ return ecx_generic_import_from(params, vpctx, EVP_PKEY_X25519);
+}
+
+const EVP_PKEY_ASN1_METHOD ossl_ecx25519_asn1_meth = {
EVP_PKEY_X25519,
EVP_PKEY_X25519,
0,
@@ -418,7 +438,7 @@ const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = {
ecx_pub_cmp,
ecx_pub_print,
- ecx_priv_decode,
+ NULL,
ecx_priv_encode,
ecx_priv_print,
@@ -447,9 +467,20 @@ const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = {
ecx_set_pub_key,
ecx_get_priv_key,
ecx_get_pub_key,
+ ecx_pkey_dirty_cnt,
+ ecx_pkey_export_to,
+ x25519_import_from,
+ ecx_pkey_copy,
+
+ ecx_priv_decode_ex
};
-const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = {
+static int x448_import_from(const OSSL_PARAM params[], void *vpctx)
+{
+ return ecx_generic_import_from(params, vpctx, EVP_PKEY_X448);
+}
+
+const EVP_PKEY_ASN1_METHOD ossl_ecx448_asn1_meth = {
EVP_PKEY_X448,
EVP_PKEY_X448,
0,
@@ -461,7 +492,7 @@ const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = {
ecx_pub_cmp,
ecx_pub_print,
- ecx_priv_decode,
+ NULL,
ecx_priv_encode,
ecx_priv_print,
@@ -490,6 +521,12 @@ const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = {
ecx_set_pub_key,
ecx_get_priv_key,
ecx_get_pub_key,
+ ecx_pkey_dirty_cnt,
+ ecx_pkey_export_to,
+ x448_import_from,
+ ecx_pkey_copy,
+
+ ecx_priv_decode_ex
};
static int ecd_size25519(const EVP_PKEY *pkey)
@@ -502,9 +539,9 @@ static int ecd_size448(const EVP_PKEY *pkey)
return ED448_SIGSIZE;
}
-static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
- X509_ALGOR *sigalg, ASN1_BIT_STRING *str,
- EVP_PKEY *pkey)
+static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
+ const void *asn, const X509_ALGOR *sigalg,
+ const ASN1_BIT_STRING *str, EVP_PKEY *pkey)
{
const ASN1_OBJECT *obj;
int ptype;
@@ -514,7 +551,7 @@ static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
X509_ALGOR_get0(&obj, &ptype, NULL, sigalg);
nid = OBJ_obj2nid(obj);
if ((nid != NID_ED25519 && nid != NID_ED448) || ptype != V_ASN1_UNDEF) {
- ECerr(EC_F_ECD_ITEM_VERIFY, EC_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
return 0;
}
@@ -524,7 +561,8 @@ static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
return 2;
}
-static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
+static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
+ const void *asn,
X509_ALGOR *alg1, X509_ALGOR *alg2,
ASN1_BIT_STRING *str)
{
@@ -544,7 +582,8 @@ static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
return 1;
}
-static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
+static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
+ const void *asn,
X509_ALGOR *alg1, X509_ALGOR *alg2,
ASN1_BIT_STRING *str)
{
@@ -564,8 +603,12 @@ static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
return 1;
}
+static int ed25519_import_from(const OSSL_PARAM params[], void *vpctx)
+{
+ return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED25519);
+}
-const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
+const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth = {
EVP_PKEY_ED25519,
EVP_PKEY_ED25519,
0,
@@ -577,7 +620,7 @@ const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
ecx_pub_cmp,
ecx_pub_print,
- ecx_priv_decode,
+ NULL,
ecx_priv_encode,
ecx_priv_print,
@@ -605,9 +648,20 @@ const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
ecx_set_pub_key,
ecx_get_priv_key,
ecx_get_pub_key,
+ ecx_pkey_dirty_cnt,
+ ecx_pkey_export_to,
+ ed25519_import_from,
+ ecx_pkey_copy,
+
+ ecx_priv_decode_ex
};
-const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = {
+static int ed448_import_from(const OSSL_PARAM params[], void *vpctx)
+{
+ return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED448);
+}
+
+const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth = {
EVP_PKEY_ED448,
EVP_PKEY_ED448,
0,
@@ -619,7 +673,7 @@ const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = {
ecx_pub_cmp,
ecx_pub_print,
- ecx_priv_decode,
+ NULL,
ecx_priv_encode,
ecx_priv_print,
@@ -647,11 +701,24 @@ const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = {
ecx_set_pub_key,
ecx_get_priv_key,
ecx_get_pub_key,
+ ecx_pkey_dirty_cnt,
+ ecx_pkey_export_to,
+ ed448_import_from,
+ ecx_pkey_copy,
+
+ ecx_priv_decode_ex
};
static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
- return ecx_key_op(pkey, ctx->pmeth->pkey_id, NULL, NULL, 0, KEY_OP_KEYGEN);
+ ECX_KEY *ecx = ossl_ecx_key_op(NULL, NULL, 0, ctx->pmeth->pkey_id,
+ KEY_OP_PUBLIC, NULL, NULL);
+
+ if (ecx != NULL) {
+ EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, ecx);
+ return 1;
+ }
+ return 0;
}
static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
@@ -662,17 +729,17 @@ static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
const ECX_KEY *ecxkey, *peerkey;
if (ctx->pkey == NULL || ctx->peerkey == NULL) {
- ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_KEYS_NOT_SET);
+ ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
return 0;
}
- ecxkey = ctx->pkey->pkey.ecx;
- peerkey = ctx->peerkey->pkey.ecx;
+ ecxkey = evp_pkey_get_legacy(ctx->pkey);
+ peerkey = evp_pkey_get_legacy(ctx->peerkey);
if (ecxkey == NULL || ecxkey->privkey == NULL) {
- ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_INVALID_PRIVATE_KEY);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
return 0;
}
if (peerkey == NULL) {
- ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_INVALID_PEER_KEY);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_PEER_KEY);
return 0;
}
*privkey = ecxkey->privkey;
@@ -688,7 +755,7 @@ static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
|| (key != NULL
- && X25519(key, privkey, pubkey) == 0))
+ && ossl_x25519(key, privkey, pubkey) == 0))
return 0;
*keylen = X25519_KEYLEN;
return 1;
@@ -701,7 +768,7 @@ static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
|| (key != NULL
- && X448(key, privkey, pubkey) == 0))
+ && ossl_x448(key, privkey, pubkey) == 0))
return 0;
*keylen = X448_KEYLEN;
return 1;
@@ -715,7 +782,7 @@ static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return -2;
}
-const EVP_PKEY_METHOD ecx25519_pkey_meth = {
+static const EVP_PKEY_METHOD ecx25519_pkey_meth = {
EVP_PKEY_X25519,
0, 0, 0, 0, 0, 0, 0,
pkey_ecx_keygen,
@@ -725,7 +792,7 @@ const EVP_PKEY_METHOD ecx25519_pkey_meth = {
0
};
-const EVP_PKEY_METHOD ecx448_pkey_meth = {
+static const EVP_PKEY_METHOD ecx448_pkey_meth = {
EVP_PKEY_X448,
0, 0, 0, 0, 0, 0, 0,
pkey_ecx_keygen,
@@ -739,18 +806,24 @@ static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig,
size_t *siglen, const unsigned char *tbs,
size_t tbslen)
{
- const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
+ const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
+
+ if (edkey == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
+ return 0;
+ }
if (sig == NULL) {
*siglen = ED25519_SIGSIZE;
return 1;
}
if (*siglen < ED25519_SIGSIZE) {
- ECerr(EC_F_PKEY_ECD_DIGESTSIGN25519, EC_R_BUFFER_TOO_SMALL);
+ ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
return 0;
}
- if (ED25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey) == 0)
+ if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
+ NULL) == 0)
return 0;
*siglen = ED25519_SIGSIZE;
return 1;
@@ -760,19 +833,24 @@ static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
size_t *siglen, const unsigned char *tbs,
size_t tbslen)
{
- const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
+ const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
+
+ if (edkey == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
+ return 0;
+ }
if (sig == NULL) {
*siglen = ED448_SIGSIZE;
return 1;
}
if (*siglen < ED448_SIGSIZE) {
- ECerr(EC_F_PKEY_ECD_DIGESTSIGN448, EC_R_BUFFER_TOO_SMALL);
+ ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
return 0;
}
- if (ED448_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
- 0) == 0)
+ if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
+ edkey->privkey, NULL, 0, edkey->propq) == 0)
return 0;
*siglen = ED448_SIGSIZE;
return 1;
@@ -782,24 +860,36 @@ static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
size_t siglen, const unsigned char *tbs,
size_t tbslen)
{
- const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
+ const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
+
+ if (edkey == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
+ return 0;
+ }
if (siglen != ED25519_SIGSIZE)
return 0;
- return ED25519_verify(tbs, tbslen, sig, edkey->pubkey);
+ return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
+ edkey->libctx, edkey->propq);
}
static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
size_t siglen, const unsigned char *tbs,
size_t tbslen)
{
- const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
+ const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
+
+ if (edkey == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
+ return 0;
+ }
if (siglen != ED448_SIGSIZE)
return 0;
- return ED448_verify(tbs, tbslen, sig, edkey->pubkey, NULL, 0);
+ return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
+ NULL, 0, edkey->propq);
}
static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
@@ -809,7 +899,7 @@ static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
/* Only NULL allowed as digest */
if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
return 1;
- ECerr(EC_F_PKEY_ECD_CTRL, EC_R_INVALID_DIGEST_TYPE);
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
return 0;
case EVP_PKEY_CTRL_DIGESTINIT:
@@ -818,7 +908,7 @@ static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return -2;
}
-const EVP_PKEY_METHOD ed25519_pkey_meth = {
+static const EVP_PKEY_METHOD ed25519_pkey_meth = {
EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
0, 0, 0, 0, 0, 0,
pkey_ecx_keygen,
@@ -829,7 +919,7 @@ const EVP_PKEY_METHOD ed25519_pkey_meth = {
pkey_ecd_digestverify25519
};
-const EVP_PKEY_METHOD ed448_pkey_meth = {
+static const EVP_PKEY_METHOD ed448_pkey_meth = {
EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
0, 0, 0, 0, 0, 0,
pkey_ecx_keygen,
@@ -839,3 +929,496 @@ const EVP_PKEY_METHOD ed448_pkey_meth = {
pkey_ecd_digestsign448,
pkey_ecd_digestverify448
};
+
+#ifdef S390X_EC_ASM
+# include "s390x_arch.h"
+
+static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+ static const unsigned char generator[] = {
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
+ ctx->propquery);
+ unsigned char *privkey = NULL, *pubkey;
+
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ pubkey = key->pubkey;
+
+ privkey = ossl_ecx_key_allocate_privkey(key);
+ if (privkey == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
+ goto err;
+
+ privkey[0] &= 248;
+ privkey[31] &= 127;
+ privkey[31] |= 64;
+
+ if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
+ goto err;
+
+ EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
+ return 1;
+ err:
+ ossl_ecx_key_free(key);
+ return 0;
+}
+
+static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+ static const unsigned char generator[] = {
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
+ ctx->propquery);
+ unsigned char *privkey = NULL, *pubkey;
+
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ pubkey = key->pubkey;
+
+ privkey = ossl_ecx_key_allocate_privkey(key);
+ if (privkey == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
+ goto err;
+
+ privkey[0] &= 252;
+ privkey[55] |= 128;
+
+ if (s390x_x448_mul(pubkey, generator, privkey) != 1)
+ goto err;
+
+ EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
+ return 1;
+ err:
+ ossl_ecx_key_free(key);
+ return 0;
+}
+
+static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+ static const unsigned char generator_x[] = {
+ 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
+ 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
+ 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
+ };
+ static const unsigned char generator_y[] = {
+ 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ };
+ unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
+ ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
+ ctx->propquery);
+ unsigned char *privkey = NULL, *pubkey;
+ unsigned int sz;
+ EVP_MD *md = NULL;
+ int rv;
+
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ pubkey = key->pubkey;
+
+ privkey = ossl_ecx_key_allocate_privkey(key);
+ if (privkey == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
+ goto err;
+
+ md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
+ if (md == NULL)
+ goto err;
+
+ rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
+ EVP_MD_free(md);
+ if (!rv)
+ goto err;
+
+ buff[0] &= 248;
+ buff[31] &= 63;
+ buff[31] |= 64;
+
+ if (s390x_ed25519_mul(x_dst, pubkey,
+ generator_x, generator_y, buff) != 1)
+ goto err;
+
+ pubkey[31] |= ((x_dst[0] & 0x01) << 7);
+
+ EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
+ return 1;
+ err:
+ ossl_ecx_key_free(key);
+ return 0;
+}
+
+static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+ static const unsigned char generator_x[] = {
+ 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
+ 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
+ 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
+ 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
+ 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
+ };
+ static const unsigned char generator_y[] = {
+ 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
+ 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
+ 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
+ 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
+ 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
+ };
+ unsigned char x_dst[57], buff[114];
+ ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
+ ctx->propquery);
+ unsigned char *privkey = NULL, *pubkey;
+ EVP_MD_CTX *hashctx = NULL;
+ EVP_MD *md = NULL;
+ int rv;
+
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ pubkey = key->pubkey;
+
+ privkey = ossl_ecx_key_allocate_privkey(key);
+ if (privkey == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
+ goto err;
+
+ hashctx = EVP_MD_CTX_new();
+ if (hashctx == NULL)
+ goto err;
+
+ md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
+ if (md == NULL)
+ goto err;
+
+ rv = EVP_DigestInit_ex(hashctx, md, NULL);
+ EVP_MD_free(md);
+ if (rv != 1)
+ goto err;
+
+ if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
+ goto err;
+ if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
+ goto err;
+
+ buff[0] &= -4;
+ buff[55] |= 0x80;
+ buff[56] = 0;
+
+ if (s390x_ed448_mul(x_dst, pubkey,
+ generator_x, generator_y, buff) != 1)
+ goto err;
+
+ pubkey[56] |= ((x_dst[0] & 0x01) << 7);
+
+ EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
+ EVP_MD_CTX_free(hashctx);
+ return 1;
+ err:
+ ossl_ecx_key_free(key);
+ EVP_MD_CTX_free(hashctx);
+ return 0;
+}
+
+static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
+ size_t *keylen)
+{
+ const unsigned char *privkey, *pubkey;
+
+ if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
+ || (key != NULL
+ && s390x_x25519_mul(key, privkey, pubkey) == 0))
+ return 0;
+ *keylen = X25519_KEYLEN;
+ return 1;
+}
+
+static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
+ size_t *keylen)
+{
+ const unsigned char *privkey, *pubkey;
+
+ if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
+ || (key != NULL
+ && s390x_x448_mul(key, pubkey, privkey) == 0))
+ return 0;
+ *keylen = X448_KEYLEN;
+ return 1;
+}
+
+static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
+ unsigned char *sig, size_t *siglen,
+ const unsigned char *tbs,
+ size_t tbslen)
+{
+ union {
+ struct {
+ unsigned char sig[64];
+ unsigned char priv[32];
+ } ed25519;
+ unsigned long long buff[512];
+ } param;
+ const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
+ int rc;
+
+ if (edkey == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
+ return 0;
+ }
+
+ if (sig == NULL) {
+ *siglen = ED25519_SIGSIZE;
+ return 1;
+ }
+
+ if (*siglen < ED25519_SIGSIZE) {
+ ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ memset(&param, 0, sizeof(param));
+ memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
+
+ rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
+ OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
+ if (rc != 0)
+ return 0;
+
+ s390x_flip_endian32(sig, param.ed25519.sig);
+ s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
+
+ *siglen = ED25519_SIGSIZE;
+ return 1;
+}
+
+static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
+ unsigned char *sig, size_t *siglen,
+ const unsigned char *tbs,
+ size_t tbslen)
+{
+ union {
+ struct {
+ unsigned char sig[128];
+ unsigned char priv[64];
+ } ed448;
+ unsigned long long buff[512];
+ } param;
+ const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
+ int rc;
+
+ if (edkey == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
+ return 0;
+ }
+
+ if (sig == NULL) {
+ *siglen = ED448_SIGSIZE;
+ return 1;
+ }
+
+ if (*siglen < ED448_SIGSIZE) {
+ ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ memset(&param, 0, sizeof(param));
+ memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
+
+ rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
+ OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
+ if (rc != 0)
+ return 0;
+
+ s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
+ s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
+ memcpy(sig, param.ed448.sig, 57);
+ memcpy(sig + 57, param.ed448.sig + 64, 57);
+
+ *siglen = ED448_SIGSIZE;
+ return 1;
+}
+
+static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
+ const unsigned char *sig,
+ size_t siglen,
+ const unsigned char *tbs,
+ size_t tbslen)
+{
+ union {
+ struct {
+ unsigned char sig[64];
+ unsigned char pub[32];
+ } ed25519;
+ unsigned long long buff[512];
+ } param;
+ const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
+
+ if (edkey == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
+ return 0;
+ }
+
+ if (siglen != ED25519_SIGSIZE)
+ return 0;
+
+ memset(&param, 0, sizeof(param));
+ s390x_flip_endian32(param.ed25519.sig, sig);
+ s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
+ s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
+
+ return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
+ &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
+}
+
+static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
+ const unsigned char *sig,
+ size_t siglen,
+ const unsigned char *tbs,
+ size_t tbslen)
+{
+ union {
+ struct {
+ unsigned char sig[128];
+ unsigned char pub[64];
+ } ed448;
+ unsigned long long buff[512];
+ } param;
+ const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
+
+ if (edkey == NULL) {
+ ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
+ return 0;
+ }
+
+ if (siglen != ED448_SIGSIZE)
+ return 0;
+
+ memset(&param, 0, sizeof(param));
+ memcpy(param.ed448.sig, sig, 57);
+ s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
+ memcpy(param.ed448.sig + 64, sig + 57, 57);
+ s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
+ memcpy(param.ed448.pub, edkey->pubkey, 57);
+ s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
+
+ return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
+ &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
+}
+
+static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
+ EVP_PKEY_X25519,
+ 0, 0, 0, 0, 0, 0, 0,
+ s390x_pkey_ecx_keygen25519,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ s390x_pkey_ecx_derive25519,
+ pkey_ecx_ctrl,
+ 0
+};
+
+static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
+ EVP_PKEY_X448,
+ 0, 0, 0, 0, 0, 0, 0,
+ s390x_pkey_ecx_keygen448,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ s390x_pkey_ecx_derive448,
+ pkey_ecx_ctrl,
+ 0
+};
+static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
+ EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
+ 0, 0, 0, 0, 0, 0,
+ s390x_pkey_ecd_keygen25519,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pkey_ecd_ctrl,
+ 0,
+ s390x_pkey_ecd_digestsign25519,
+ s390x_pkey_ecd_digestverify25519
+};
+
+static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
+ EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
+ 0, 0, 0, 0, 0, 0,
+ s390x_pkey_ecd_keygen448,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pkey_ecd_ctrl,
+ 0,
+ s390x_pkey_ecd_digestsign448,
+ s390x_pkey_ecd_digestverify448
+};
+#endif
+
+const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
+{
+#ifdef S390X_EC_ASM
+ if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
+ return &ecx25519_s390x_pkey_meth;
+#endif
+ return &ecx25519_pkey_meth;
+}
+
+const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
+{
+#ifdef S390X_EC_ASM
+ if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
+ return &ecx448_s390x_pkey_meth;
+#endif
+ return &ecx448_pkey_meth;
+}
+
+const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
+{
+#ifdef S390X_EC_ASM
+ if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
+ && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
+ && OPENSSL_s390xcap_P.kdsa[0]
+ & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
+ return &ed25519_s390x_pkey_meth;
+#endif
+ return &ed25519_pkey_meth;
+}
+
+const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
+{
+#ifdef S390X_EC_ASM
+ if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
+ && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
+ && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
+ return &ed448_s390x_pkey_meth;
+#endif
+ return &ed448_pkey_meth;
+}
diff --git a/crypto/ec/ecx_s390x.c b/crypto/ec/ecx_s390x.c
new file mode 100644
index 000000000000..d424d6252dcf
--- /dev/null
+++ b/crypto/ec/ecx_s390x.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/ec.h>
+#include <openssl/rand.h>
+#include "crypto/ecx.h"
+#include "ec_local.h"
+#include "curve448/curve448_local.h"
+#include "ecx_backend.h"
+#include "s390x_arch.h"
+#include "internal/constant_time.h"
+
+static void s390x_x25519_mod_p(unsigned char u[32])
+{
+ unsigned char u_red[32];
+ unsigned int c = 0;
+ int i;
+
+ memcpy(u_red, u, sizeof(u_red));
+
+ c += (unsigned int)u_red[31] + 19;
+ u_red[31] = (unsigned char)c;
+ c >>= 8;
+
+ for (i = 30; i >= 0; i--) {
+ c += (unsigned int)u_red[i];
+ u_red[i] = (unsigned char)c;
+ c >>= 8;
+ }
+
+ c = (u_red[0] & 0x80) >> 7;
+ u_red[0] &= 0x7f;
+ constant_time_cond_swap_buff(0 - (unsigned char)c,
+ u, u_red, sizeof(u_red));
+}
+
+static void s390x_x448_mod_p(unsigned char u[56])
+{
+ unsigned char u_red[56];
+ unsigned int c = 0;
+ int i;
+
+ memcpy(u_red, u, sizeof(u_red));
+
+ c += (unsigned int)u_red[55] + 1;
+ u_red[55] = (unsigned char)c;
+ c >>= 8;
+
+ for (i = 54; i >= 28; i--) {
+ c += (unsigned int)u_red[i];
+ u_red[i] = (unsigned char)c;
+ c >>= 8;
+ }
+
+ c += (unsigned int)u_red[27] + 1;
+ u_red[27] = (unsigned char)c;
+ c >>= 8;
+
+ for (i = 26; i >= 0; i--) {
+ c += (unsigned int)u_red[i];
+ u_red[i] = (unsigned char)c;
+ c >>= 8;
+ }
+
+ constant_time_cond_swap_buff(0 - (unsigned char)c,
+ u, u_red, sizeof(u_red));
+}
+
+int s390x_x25519_mul(unsigned char u_dst[32],
+ const unsigned char u_src[32],
+ const unsigned char d_src[32])
+{
+ union {
+ struct {
+ unsigned char u_dst[32];
+ unsigned char u_src[32];
+ unsigned char d_src[32];
+ } x25519;
+ unsigned long long buff[512];
+ } param;
+ int rc;
+
+ memset(&param, 0, sizeof(param));
+
+ s390x_flip_endian32(param.x25519.u_src, u_src);
+ param.x25519.u_src[0] &= 0x7f;
+ s390x_x25519_mod_p(param.x25519.u_src);
+
+ s390x_flip_endian32(param.x25519.d_src, d_src);
+ param.x25519.d_src[31] &= 248;
+ param.x25519.d_src[0] &= 127;
+ param.x25519.d_src[0] |= 64;
+
+ rc = s390x_pcc(S390X_SCALAR_MULTIPLY_X25519, &param.x25519) ? 0 : 1;
+ if (rc == 1)
+ s390x_flip_endian32(u_dst, param.x25519.u_dst);
+
+ OPENSSL_cleanse(param.x25519.d_src, sizeof(param.x25519.d_src));
+ return rc;
+}
+
+int s390x_x448_mul(unsigned char u_dst[56],
+ const unsigned char u_src[56],
+ const unsigned char d_src[56])
+{
+ union {
+ struct {
+ unsigned char u_dst[64];
+ unsigned char u_src[64];
+ unsigned char d_src[64];
+ } x448;
+ unsigned long long buff[512];
+ } param;
+ int rc;
+
+ memset(&param, 0, sizeof(param));
+
+ memcpy(param.x448.u_src, u_src, 56);
+ memcpy(param.x448.d_src, d_src, 56);
+
+ s390x_flip_endian64(param.x448.u_src, param.x448.u_src);
+ s390x_x448_mod_p(param.x448.u_src + 8);
+
+ s390x_flip_endian64(param.x448.d_src, param.x448.d_src);
+ param.x448.d_src[63] &= 252;
+ param.x448.d_src[8] |= 128;
+
+ rc = s390x_pcc(S390X_SCALAR_MULTIPLY_X448, &param.x448) ? 0 : 1;
+ if (rc == 1) {
+ s390x_flip_endian64(param.x448.u_dst, param.x448.u_dst);
+ memcpy(u_dst, param.x448.u_dst, 56);
+ }
+
+ OPENSSL_cleanse(param.x448.d_src, sizeof(param.x448.d_src));
+ return rc;
+}
+
+int s390x_ed25519_mul(unsigned char x_dst[32],
+ unsigned char y_dst[32],
+ const unsigned char x_src[32],
+ const unsigned char y_src[32],
+ const unsigned char d_src[32])
+{
+ union {
+ struct {
+ unsigned char x_dst[32];
+ unsigned char y_dst[32];
+ unsigned char x_src[32];
+ unsigned char y_src[32];
+ unsigned char d_src[32];
+ } ed25519;
+ unsigned long long buff[512];
+ } param;
+ int rc;
+
+ memset(&param, 0, sizeof(param));
+
+ s390x_flip_endian32(param.ed25519.x_src, x_src);
+ s390x_flip_endian32(param.ed25519.y_src, y_src);
+ s390x_flip_endian32(param.ed25519.d_src, d_src);
+
+ rc = s390x_pcc(S390X_SCALAR_MULTIPLY_ED25519, &param.ed25519) ? 0 : 1;
+ if (rc == 1) {
+ s390x_flip_endian32(x_dst, param.ed25519.x_dst);
+ s390x_flip_endian32(y_dst, param.ed25519.y_dst);
+ }
+
+ OPENSSL_cleanse(param.ed25519.d_src, sizeof(param.ed25519.d_src));
+ return rc;
+}
+
+int s390x_ed448_mul(unsigned char x_dst[57],
+ unsigned char y_dst[57],
+ const unsigned char x_src[57],
+ const unsigned char y_src[57],
+ const unsigned char d_src[57])
+{
+ union {
+ struct {
+ unsigned char x_dst[64];
+ unsigned char y_dst[64];
+ unsigned char x_src[64];
+ unsigned char y_src[64];
+ unsigned char d_src[64];
+ } ed448;
+ unsigned long long buff[512];
+ } param;
+ int rc;
+
+ memset(&param, 0, sizeof(param));
+
+ memcpy(param.ed448.x_src, x_src, 57);
+ memcpy(param.ed448.y_src, y_src, 57);
+ memcpy(param.ed448.d_src, d_src, 57);
+ s390x_flip_endian64(param.ed448.x_src, param.ed448.x_src);
+ s390x_flip_endian64(param.ed448.y_src, param.ed448.y_src);
+ s390x_flip_endian64(param.ed448.d_src, param.ed448.d_src);
+
+ rc = s390x_pcc(S390X_SCALAR_MULTIPLY_ED448, &param.ed448) ? 0 : 1;
+ if (rc == 1) {
+ s390x_flip_endian64(param.ed448.x_dst, param.ed448.x_dst);
+ s390x_flip_endian64(param.ed448.y_dst, param.ed448.y_dst);
+ memcpy(x_dst, param.ed448.x_dst, 57);
+ memcpy(y_dst, param.ed448.y_dst, 57);
+ }
+
+ OPENSSL_cleanse(param.ed448.d_src, sizeof(param.ed448.d_src));
+ return rc;
+}
diff --git a/crypto/encode_decode/build.info b/crypto/encode_decode/build.info
new file mode 100644
index 000000000000..e2cd84667338
--- /dev/null
+++ b/crypto/encode_decode/build.info
@@ -0,0 +1,5 @@
+SOURCE[../../libcrypto]=encoder_meth.c encoder_lib.c encoder_pkey.c
+SOURCE[../../libcrypto]=decoder_meth.c decoder_lib.c decoder_pkey.c
+
+SOURCE[../../libcrypto]=encoder_err.c
+SOURCE[../../libcrypto]=decoder_err.c
diff --git a/crypto/encode_decode/decoder_err.c b/crypto/encode_decode/decoder_err.c
new file mode 100644
index 000000000000..88324a1d5078
--- /dev/null
+++ b/crypto/encode_decode/decoder_err.c
@@ -0,0 +1,36 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/decodererr.h>
+#include "crypto/decodererr.h"
+
+#ifndef OPENSSL_NO_ERR
+
+static const ERR_STRING_DATA OSSL_DECODER_str_reasons[] = {
+ {ERR_PACK(ERR_LIB_OSSL_DECODER, 0, OSSL_DECODER_R_COULD_NOT_DECODE_OBJECT),
+ "could not decode object"},
+ {ERR_PACK(ERR_LIB_OSSL_DECODER, 0, OSSL_DECODER_R_DECODER_NOT_FOUND),
+ "decoder not found"},
+ {ERR_PACK(ERR_LIB_OSSL_DECODER, 0, OSSL_DECODER_R_MISSING_GET_PARAMS),
+ "missing get params"},
+ {0, NULL}
+};
+
+#endif
+
+int ossl_err_load_OSSL_DECODER_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(OSSL_DECODER_str_reasons[0].error) == NULL)
+ ERR_load_strings_const(OSSL_DECODER_str_reasons);
+#endif
+ return 1;
+}
diff --git a/crypto/encode_decode/decoder_lib.c b/crypto/encode_decode/decoder_lib.c
new file mode 100644
index 000000000000..e24d2c6cd588
--- /dev/null
+++ b/crypto/encode_decode/decoder_lib.c
@@ -0,0 +1,999 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_names.h>
+#include <openssl/bio.h>
+#include <openssl/params.h>
+#include <openssl/provider.h>
+#include <openssl/evperr.h>
+#include <openssl/ecerr.h>
+#include <openssl/pkcs12err.h>
+#include <openssl/x509err.h>
+#include <openssl/trace.h>
+#include "internal/bio.h"
+#include "internal/provider.h"
+#include "crypto/decoder.h"
+#include "encoder_local.h"
+#include "e_os.h"
+
+struct decoder_process_data_st {
+ OSSL_DECODER_CTX *ctx;
+
+ /* Current BIO */
+ BIO *bio;
+
+ /* Index of the current decoder instance to be processed */
+ size_t current_decoder_inst_index;
+ /* For tracing, count recursion level */
+ size_t recursion;
+
+ /*-
+ * Flags
+ */
+ unsigned int flag_next_level_called : 1;
+ unsigned int flag_construct_called : 1;
+ unsigned int flag_input_structure_checked : 1;
+};
+
+static int decoder_process(const OSSL_PARAM params[], void *arg);
+
+int OSSL_DECODER_from_bio(OSSL_DECODER_CTX *ctx, BIO *in)
+{
+ struct decoder_process_data_st data;
+ int ok = 0;
+ BIO *new_bio = NULL;
+ unsigned long lasterr;
+
+ if (in == NULL) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (OSSL_DECODER_CTX_get_num_decoders(ctx) == 0) {
+ ERR_raise_data(ERR_LIB_OSSL_DECODER, OSSL_DECODER_R_DECODER_NOT_FOUND,
+ "No decoders were found. For standard decoders you need "
+ "at least one of the default or base providers "
+ "available. Did you forget to load them?");
+ return 0;
+ }
+
+ lasterr = ERR_peek_last_error();
+
+ if (BIO_tell(in) < 0) {
+ new_bio = BIO_new(BIO_f_readbuffer());
+ if (new_bio == NULL)
+ return 0;
+ in = BIO_push(new_bio, in);
+ }
+ memset(&data, 0, sizeof(data));
+ data.ctx = ctx;
+ data.bio = in;
+
+ /* Enable passphrase caching */
+ (void)ossl_pw_enable_passphrase_caching(&ctx->pwdata);
+
+ ok = decoder_process(NULL, &data);
+
+ if (!data.flag_construct_called) {
+ const char *spaces
+ = ctx->start_input_type != NULL && ctx->input_structure != NULL
+ ? " " : "";
+ const char *input_type_label
+ = ctx->start_input_type != NULL ? "Input type: " : "";
+ const char *input_structure_label
+ = ctx->input_structure != NULL ? "Input structure: " : "";
+ const char *comma
+ = ctx->start_input_type != NULL && ctx->input_structure != NULL
+ ? ", " : "";
+ const char *input_type
+ = ctx->start_input_type != NULL ? ctx->start_input_type : "";
+ const char *input_structure
+ = ctx->input_structure != NULL ? ctx->input_structure : "";
+
+ if (ERR_peek_last_error() == lasterr || ERR_peek_error() == 0)
+ /* Prevent spurious decoding error but add at least something */
+ ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_UNSUPPORTED,
+ "No supported data to decode. %s%s%s%s%s%s",
+ spaces, input_type_label, input_type, comma,
+ input_structure_label, input_structure);
+ ok = 0;
+ }
+
+ /* Clear any internally cached passphrase */
+ (void)ossl_pw_clear_passphrase_cache(&ctx->pwdata);
+
+ if (new_bio != NULL) {
+ BIO_pop(new_bio);
+ BIO_free(new_bio);
+ }
+ return ok;
+}
+
+#ifndef OPENSSL_NO_STDIO
+static BIO *bio_from_file(FILE *fp)
+{
+ BIO *b;
+
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_BIO_LIB);
+ return NULL;
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ return b;
+}
+
+int OSSL_DECODER_from_fp(OSSL_DECODER_CTX *ctx, FILE *fp)
+{
+ BIO *b = bio_from_file(fp);
+ int ret = 0;
+
+ if (b != NULL)
+ ret = OSSL_DECODER_from_bio(ctx, b);
+
+ BIO_free(b);
+ return ret;
+}
+#endif
+
+int OSSL_DECODER_from_data(OSSL_DECODER_CTX *ctx, const unsigned char **pdata,
+ size_t *pdata_len)
+{
+ BIO *membio;
+ int ret = 0;
+
+ if (pdata == NULL || *pdata == NULL || pdata_len == NULL) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ membio = BIO_new_mem_buf(*pdata, (int)*pdata_len);
+ if (OSSL_DECODER_from_bio(ctx, membio)) {
+ *pdata_len = (size_t)BIO_get_mem_data(membio, pdata);
+ ret = 1;
+ }
+ BIO_free(membio);
+
+ return ret;
+}
+
+int OSSL_DECODER_CTX_set_selection(OSSL_DECODER_CTX *ctx, int selection)
+{
+ if (!ossl_assert(ctx != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ /*
+ * 0 is a valid selection, and means that the caller leaves
+ * it to code to discover what the selection is.
+ */
+ ctx->selection = selection;
+ return 1;
+}
+
+int OSSL_DECODER_CTX_set_input_type(OSSL_DECODER_CTX *ctx,
+ const char *input_type)
+{
+ if (!ossl_assert(ctx != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ /*
+ * NULL is a valid starting input type, and means that the caller leaves
+ * it to code to discover what the starting input type is.
+ */
+ ctx->start_input_type = input_type;
+ return 1;
+}
+
+int OSSL_DECODER_CTX_set_input_structure(OSSL_DECODER_CTX *ctx,
+ const char *input_structure)
+{
+ if (!ossl_assert(ctx != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ /*
+ * NULL is a valid starting input structure, and means that the caller
+ * leaves it to code to discover what the starting input structure is.
+ */
+ ctx->input_structure = input_structure;
+ return 1;
+}
+
+OSSL_DECODER_INSTANCE *ossl_decoder_instance_new(OSSL_DECODER *decoder,
+ void *decoderctx)
+{
+ OSSL_DECODER_INSTANCE *decoder_inst = NULL;
+ const OSSL_PROVIDER *prov;
+ OSSL_LIB_CTX *libctx;
+ const OSSL_PROPERTY_LIST *props;
+ const OSSL_PROPERTY_DEFINITION *prop;
+
+ if (!ossl_assert(decoder != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if ((decoder_inst = OPENSSL_zalloc(sizeof(*decoder_inst))) == NULL) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ prov = OSSL_DECODER_get0_provider(decoder);
+ libctx = ossl_provider_libctx(prov);
+ props = ossl_decoder_parsed_properties(decoder);
+ if (props == NULL) {
+ ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION,
+ "there are no property definitions with decoder %s",
+ OSSL_DECODER_get0_name(decoder));
+ goto err;
+ }
+
+ /* The "input" property is mandatory */
+ prop = ossl_property_find_property(props, libctx, "input");
+ decoder_inst->input_type = ossl_property_get_string_value(libctx, prop);
+ if (decoder_inst->input_type == NULL) {
+ ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION,
+ "the mandatory 'input' property is missing "
+ "for decoder %s (properties: %s)",
+ OSSL_DECODER_get0_name(decoder),
+ OSSL_DECODER_get0_properties(decoder));
+ goto err;
+ }
+
+ /* The "structure" property is optional */
+ prop = ossl_property_find_property(props, libctx, "structure");
+ if (prop != NULL) {
+ decoder_inst->input_structure
+ = ossl_property_get_string_value(libctx, prop);
+ }
+
+ if (!OSSL_DECODER_up_ref(decoder)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ decoder_inst->decoder = decoder;
+ decoder_inst->decoderctx = decoderctx;
+ return decoder_inst;
+ err:
+ ossl_decoder_instance_free(decoder_inst);
+ return NULL;
+}
+
+void ossl_decoder_instance_free(OSSL_DECODER_INSTANCE *decoder_inst)
+{
+ if (decoder_inst != NULL) {
+ if (decoder_inst->decoder != NULL)
+ decoder_inst->decoder->freectx(decoder_inst->decoderctx);
+ decoder_inst->decoderctx = NULL;
+ OSSL_DECODER_free(decoder_inst->decoder);
+ decoder_inst->decoder = NULL;
+ OPENSSL_free(decoder_inst);
+ }
+}
+
+int ossl_decoder_ctx_add_decoder_inst(OSSL_DECODER_CTX *ctx,
+ OSSL_DECODER_INSTANCE *di)
+{
+ int ok;
+
+ if (ctx->decoder_insts == NULL
+ && (ctx->decoder_insts =
+ sk_OSSL_DECODER_INSTANCE_new_null()) == NULL) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ ok = (sk_OSSL_DECODER_INSTANCE_push(ctx->decoder_insts, di) > 0);
+ if (ok) {
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) Added decoder instance %p for decoder %p\n"
+ " %s with %s\n",
+ (void *)ctx, (void *)di, (void *)di->decoder,
+ OSSL_DECODER_get0_name(di->decoder),
+ OSSL_DECODER_get0_properties(di->decoder));
+ } OSSL_TRACE_END(DECODER);
+ }
+ return ok;
+}
+
+int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder)
+{
+ OSSL_DECODER_INSTANCE *decoder_inst = NULL;
+ const OSSL_PROVIDER *prov = NULL;
+ void *decoderctx = NULL;
+ void *provctx = NULL;
+
+ if (!ossl_assert(ctx != NULL) || !ossl_assert(decoder != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ prov = OSSL_DECODER_get0_provider(decoder);
+ provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
+
+ if ((decoderctx = decoder->newctx(provctx)) == NULL
+ || (decoder_inst =
+ ossl_decoder_instance_new(decoder, decoderctx)) == NULL)
+ goto err;
+ /* Avoid double free of decoderctx on further errors */
+ decoderctx = NULL;
+
+ if (!ossl_decoder_ctx_add_decoder_inst(ctx, decoder_inst))
+ goto err;
+
+ return 1;
+ err:
+ ossl_decoder_instance_free(decoder_inst);
+ if (decoderctx != NULL)
+ decoder->freectx(decoderctx);
+ return 0;
+}
+
+struct collect_extra_decoder_data_st {
+ OSSL_DECODER_CTX *ctx;
+ const char *output_type;
+ /*
+ * 0 to check that the decoder's input type is the same as the decoder name
+ * 1 to check that the decoder's input type differs from the decoder name
+ */
+ enum { IS_SAME = 0, IS_DIFFERENT = 1 } type_check;
+ size_t w_prev_start, w_prev_end; /* "previous" decoders */
+ size_t w_new_start, w_new_end; /* "new" decoders */
+};
+
+DEFINE_STACK_OF(OSSL_DECODER)
+
+static void collect_all_decoders(OSSL_DECODER *decoder, void *arg)
+{
+ STACK_OF(OSSL_DECODER) *skdecoders = arg;
+
+ if (OSSL_DECODER_up_ref(decoder)
+ && !sk_OSSL_DECODER_push(skdecoders, decoder))
+ OSSL_DECODER_free(decoder);
+}
+
+static void collect_extra_decoder(OSSL_DECODER *decoder, void *arg)
+{
+ struct collect_extra_decoder_data_st *data = arg;
+ size_t j;
+ const OSSL_PROVIDER *prov = OSSL_DECODER_get0_provider(decoder);
+ void *provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
+
+ if (OSSL_DECODER_is_a(decoder, data->output_type)) {
+ void *decoderctx = NULL;
+ OSSL_DECODER_INSTANCE *di = NULL;
+
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) [%d] Checking out decoder %p:\n"
+ " %s with %s\n",
+ (void *)data->ctx, data->type_check, (void *)decoder,
+ OSSL_DECODER_get0_name(decoder),
+ OSSL_DECODER_get0_properties(decoder));
+ } OSSL_TRACE_END(DECODER);
+
+ /*
+ * Check that we don't already have this decoder in our stack,
+ * starting with the previous windows but also looking at what
+ * we have added in the current window.
+ */
+ for (j = data->w_prev_start; j < data->w_new_end; j++) {
+ OSSL_DECODER_INSTANCE *check_inst =
+ sk_OSSL_DECODER_INSTANCE_value(data->ctx->decoder_insts, j);
+
+ if (decoder->base.algodef == check_inst->decoder->base.algodef) {
+ /* We found it, so don't do anything more */
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ " REJECTED: already exists in the chain\n");
+ } OSSL_TRACE_END(DECODER);
+ return;
+ }
+ }
+
+ if ((decoderctx = decoder->newctx(provctx)) == NULL)
+ return;
+
+ if ((di = ossl_decoder_instance_new(decoder, decoderctx)) == NULL) {
+ decoder->freectx(decoderctx);
+ return;
+ }
+
+ switch (data->type_check) {
+ case IS_SAME:
+ /* If it differs, this is not a decoder to add for now. */
+ if (!OSSL_DECODER_is_a(decoder,
+ OSSL_DECODER_INSTANCE_get_input_type(di))) {
+ ossl_decoder_instance_free(di);
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ " REJECTED: input type doesn't match output type\n");
+ } OSSL_TRACE_END(DECODER);
+ return;
+ }
+ break;
+ case IS_DIFFERENT:
+ /* If it's the same, this is not a decoder to add for now. */
+ if (OSSL_DECODER_is_a(decoder,
+ OSSL_DECODER_INSTANCE_get_input_type(di))) {
+ ossl_decoder_instance_free(di);
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ " REJECTED: input type matches output type\n");
+ } OSSL_TRACE_END(DECODER);
+ return;
+ }
+ break;
+ }
+
+ /*
+ * Apart from keeping w_new_end up to date, We don't care about
+ * errors here. If it doesn't collect, then it doesn't...
+ */
+ if (!ossl_decoder_ctx_add_decoder_inst(data->ctx, di)) {
+ ossl_decoder_instance_free(di);
+ return;
+ }
+
+ data->w_new_end++;
+ }
+}
+
+int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ /*
+ * This function goes through existing decoder methods in
+ * |ctx->decoder_insts|, and tries to fetch new decoders that produce
+ * what the existing ones want as input, and push those newly fetched
+ * decoders on top of the same stack.
+ * Then it does the same again, but looping over the newly fetched
+ * decoders, until there are no more decoders to be fetched, or
+ * when we have done this 10 times.
+ *
+ * we do this with sliding windows on the stack by keeping track of indexes
+ * and of the end.
+ *
+ * +----------------+
+ * | DER to RSA | <--- w_prev_start
+ * +----------------+
+ * | DER to DSA |
+ * +----------------+
+ * | DER to DH |
+ * +----------------+
+ * | PEM to DER | <--- w_prev_end, w_new_start
+ * +----------------+
+ * <--- w_new_end
+ */
+ struct collect_extra_decoder_data_st data;
+ size_t depth = 0; /* Counts the number of iterations */
+ size_t count; /* Calculates how many were added in each iteration */
+ size_t numdecoders;
+ STACK_OF(OSSL_DECODER) *skdecoders;
+
+ if (!ossl_assert(ctx != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ /*
+ * If there is no stack of OSSL_DECODER_INSTANCE, we have nothing
+ * more to add. That's fine.
+ */
+ if (ctx->decoder_insts == NULL)
+ return 1;
+
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out, "(ctx %p) Looking for extra decoders\n",
+ (void *)ctx);
+ } OSSL_TRACE_END(DECODER);
+
+
+ skdecoders = sk_OSSL_DECODER_new_null();
+ if (skdecoders == NULL) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ OSSL_DECODER_do_all_provided(libctx, collect_all_decoders, skdecoders);
+ numdecoders = sk_OSSL_DECODER_num(skdecoders);
+
+ memset(&data, 0, sizeof(data));
+ data.ctx = ctx;
+ data.w_prev_start = 0;
+ data.w_prev_end = sk_OSSL_DECODER_INSTANCE_num(ctx->decoder_insts);
+ do {
+ size_t i, j;
+
+ data.w_new_start = data.w_new_end = data.w_prev_end;
+
+ /*
+ * Two iterations:
+ * 0. All decoders that have the same name as their input type.
+ * This allows for decoders that unwrap some data in a specific
+ * encoding, and pass the result on with the same encoding.
+ * 1. All decoders that a different name than their input type.
+ */
+ for (data.type_check = IS_SAME;
+ data.type_check <= IS_DIFFERENT;
+ data.type_check++) {
+ for (i = data.w_prev_start; i < data.w_prev_end; i++) {
+ OSSL_DECODER_INSTANCE *decoder_inst =
+ sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, i);
+
+ data.output_type
+ = OSSL_DECODER_INSTANCE_get_input_type(decoder_inst);
+
+
+ for (j = 0; j < numdecoders; j++)
+ collect_extra_decoder(sk_OSSL_DECODER_value(skdecoders, j),
+ &data);
+ }
+ }
+ /* How many were added in this iteration */
+ count = data.w_new_end - data.w_new_start;
+
+ /* Slide the "previous decoder" windows */
+ data.w_prev_start = data.w_new_start;
+ data.w_prev_end = data.w_new_end;
+
+ depth++;
+ } while (count != 0 && depth <= 10);
+
+ sk_OSSL_DECODER_pop_free(skdecoders, OSSL_DECODER_free);
+ return 1;
+}
+
+int OSSL_DECODER_CTX_get_num_decoders(OSSL_DECODER_CTX *ctx)
+{
+ if (ctx == NULL || ctx->decoder_insts == NULL)
+ return 0;
+ return sk_OSSL_DECODER_INSTANCE_num(ctx->decoder_insts);
+}
+
+int OSSL_DECODER_CTX_set_construct(OSSL_DECODER_CTX *ctx,
+ OSSL_DECODER_CONSTRUCT *construct)
+{
+ if (!ossl_assert(ctx != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ ctx->construct = construct;
+ return 1;
+}
+
+int OSSL_DECODER_CTX_set_construct_data(OSSL_DECODER_CTX *ctx,
+ void *construct_data)
+{
+ if (!ossl_assert(ctx != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ ctx->construct_data = construct_data;
+ return 1;
+}
+
+int OSSL_DECODER_CTX_set_cleanup(OSSL_DECODER_CTX *ctx,
+ OSSL_DECODER_CLEANUP *cleanup)
+{
+ if (!ossl_assert(ctx != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ ctx->cleanup = cleanup;
+ return 1;
+}
+
+OSSL_DECODER_CONSTRUCT *
+OSSL_DECODER_CTX_get_construct(OSSL_DECODER_CTX *ctx)
+{
+ if (ctx == NULL)
+ return NULL;
+ return ctx->construct;
+}
+
+void *OSSL_DECODER_CTX_get_construct_data(OSSL_DECODER_CTX *ctx)
+{
+ if (ctx == NULL)
+ return NULL;
+ return ctx->construct_data;
+}
+
+OSSL_DECODER_CLEANUP *
+OSSL_DECODER_CTX_get_cleanup(OSSL_DECODER_CTX *ctx)
+{
+ if (ctx == NULL)
+ return NULL;
+ return ctx->cleanup;
+}
+
+int OSSL_DECODER_export(OSSL_DECODER_INSTANCE *decoder_inst,
+ void *reference, size_t reference_sz,
+ OSSL_CALLBACK *export_cb, void *export_cbarg)
+{
+ OSSL_DECODER *decoder = NULL;
+ void *decoderctx = NULL;
+
+ if (!(ossl_assert(decoder_inst != NULL)
+ && ossl_assert(reference != NULL)
+ && ossl_assert(export_cb != NULL)
+ && ossl_assert(export_cbarg != NULL))) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ decoder = OSSL_DECODER_INSTANCE_get_decoder(decoder_inst);
+ decoderctx = OSSL_DECODER_INSTANCE_get_decoder_ctx(decoder_inst);
+ return decoder->export_object(decoderctx, reference, reference_sz,
+ export_cb, export_cbarg);
+}
+
+OSSL_DECODER *
+OSSL_DECODER_INSTANCE_get_decoder(OSSL_DECODER_INSTANCE *decoder_inst)
+{
+ if (decoder_inst == NULL)
+ return NULL;
+ return decoder_inst->decoder;
+}
+
+void *
+OSSL_DECODER_INSTANCE_get_decoder_ctx(OSSL_DECODER_INSTANCE *decoder_inst)
+{
+ if (decoder_inst == NULL)
+ return NULL;
+ return decoder_inst->decoderctx;
+}
+
+const char *
+OSSL_DECODER_INSTANCE_get_input_type(OSSL_DECODER_INSTANCE *decoder_inst)
+{
+ if (decoder_inst == NULL)
+ return NULL;
+ return decoder_inst->input_type;
+}
+
+const char *
+OSSL_DECODER_INSTANCE_get_input_structure(OSSL_DECODER_INSTANCE *decoder_inst,
+ int *was_set)
+{
+ if (decoder_inst == NULL)
+ return NULL;
+ *was_set = decoder_inst->flag_input_structure_was_set;
+ return decoder_inst->input_structure;
+}
+
+static int decoder_process(const OSSL_PARAM params[], void *arg)
+{
+ struct decoder_process_data_st *data = arg;
+ OSSL_DECODER_CTX *ctx = data->ctx;
+ OSSL_DECODER_INSTANCE *decoder_inst = NULL;
+ OSSL_DECODER *decoder = NULL;
+ OSSL_CORE_BIO *cbio = NULL;
+ BIO *bio = data->bio;
+ long loc;
+ size_t i;
+ int ok = 0;
+ /* For recursions */
+ struct decoder_process_data_st new_data;
+ const char *data_type = NULL;
+ const char *data_structure = NULL;
+
+ /*
+ * This is an indicator up the call stack that something was indeed
+ * decoded, leading to a recursive call of this function.
+ */
+ data->flag_next_level_called = 1;
+
+ memset(&new_data, 0, sizeof(new_data));
+ new_data.ctx = data->ctx;
+ new_data.recursion = data->recursion + 1;
+
+#define LEVEL_STR ">>>>>>>>>>>>>>>>"
+#define LEVEL (new_data.recursion < sizeof(LEVEL_STR) \
+ ? &LEVEL_STR[sizeof(LEVEL_STR) - new_data.recursion - 1] \
+ : LEVEL_STR "...")
+
+ if (params == NULL) {
+ /* First iteration, where we prepare for what is to come */
+
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) starting to walk the decoder chain\n",
+ (void *)new_data.ctx);
+ } OSSL_TRACE_END(DECODER);
+
+ data->current_decoder_inst_index =
+ OSSL_DECODER_CTX_get_num_decoders(ctx);
+
+ bio = data->bio;
+ } else {
+ const OSSL_PARAM *p;
+ const char *trace_data_structure;
+
+ decoder_inst =
+ sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts,
+ data->current_decoder_inst_index);
+ decoder = OSSL_DECODER_INSTANCE_get_decoder(decoder_inst);
+
+ data->flag_construct_called = 0;
+ if (ctx->construct != NULL) {
+ int rv;
+
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) %s Running constructor\n",
+ (void *)new_data.ctx, LEVEL);
+ } OSSL_TRACE_END(DECODER);
+
+ rv = ctx->construct(decoder_inst, params, ctx->construct_data);
+
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) %s Running constructor => %d\n",
+ (void *)new_data.ctx, LEVEL, rv);
+ } OSSL_TRACE_END(DECODER);
+
+ data->flag_construct_called = 1;
+ ok = (rv > 0);
+ if (ok)
+ goto end;
+ }
+
+ /* The constructor didn't return success */
+
+ /*
+ * so we try to use the object we got and feed it to any next
+ * decoder that will take it. Object references are not
+ * allowed for this.
+ * If this data isn't present, decoding has failed.
+ */
+
+ p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA);
+ if (p == NULL || p->data_type != OSSL_PARAM_OCTET_STRING)
+ goto end;
+ new_data.bio = BIO_new_mem_buf(p->data, (int)p->data_size);
+ if (new_data.bio == NULL)
+ goto end;
+ bio = new_data.bio;
+
+ /* Get the data type if there is one */
+ p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA_TYPE);
+ if (p != NULL && !OSSL_PARAM_get_utf8_string_ptr(p, &data_type))
+ goto end;
+
+ /* Get the data structure if there is one */
+ p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA_STRUCTURE);
+ if (p != NULL && !OSSL_PARAM_get_utf8_string_ptr(p, &data_structure))
+ goto end;
+
+ /*
+ * If the data structure is "type-specific" and the data type is
+ * given, we drop the data structure. The reasoning is that the
+ * data type is already enough to find the applicable next decoder,
+ * so an additional "type-specific" data structure is extraneous.
+ *
+ * Furthermore, if the OSSL_DECODER caller asked for a type specific
+ * structure under another name, such as "DH", we get a mismatch
+ * if the data structure we just received is "type-specific".
+ * There's only so much you can do without infusing this code with
+ * too special knowledge.
+ */
+ trace_data_structure = data_structure;
+ if (data_type != NULL && data_structure != NULL
+ && OPENSSL_strcasecmp(data_structure, "type-specific") == 0)
+ data_structure = NULL;
+
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) %s incoming from previous decoder (%p):\n"
+ " data type: %s, data structure: %s%s\n",
+ (void *)new_data.ctx, LEVEL, (void *)decoder,
+ data_type, trace_data_structure,
+ (trace_data_structure == data_structure
+ ? "" : " (dropped)"));
+ } OSSL_TRACE_END(DECODER);
+ }
+
+ /*
+ * If we have no more decoders to look through at this point,
+ * we failed
+ */
+ if (data->current_decoder_inst_index == 0)
+ goto end;
+
+ if ((loc = BIO_tell(bio)) < 0) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_BIO_LIB);
+ goto end;
+ }
+
+ if ((cbio = ossl_core_bio_new_from_bio(bio)) == NULL) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+
+ for (i = data->current_decoder_inst_index; i-- > 0;) {
+ OSSL_DECODER_INSTANCE *new_decoder_inst =
+ sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, i);
+ OSSL_DECODER *new_decoder =
+ OSSL_DECODER_INSTANCE_get_decoder(new_decoder_inst);
+ void *new_decoderctx =
+ OSSL_DECODER_INSTANCE_get_decoder_ctx(new_decoder_inst);
+ const char *new_input_type =
+ OSSL_DECODER_INSTANCE_get_input_type(new_decoder_inst);
+ int n_i_s_was_set = 0; /* We don't care here */
+ const char *new_input_structure =
+ OSSL_DECODER_INSTANCE_get_input_structure(new_decoder_inst,
+ &n_i_s_was_set);
+
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) %s [%u] Considering decoder instance %p (decoder %p):\n"
+ " %s with %s\n",
+ (void *)new_data.ctx, LEVEL, (unsigned int)i,
+ (void *)new_decoder_inst, (void *)new_decoder,
+ OSSL_DECODER_get0_name(new_decoder),
+ OSSL_DECODER_get0_properties(new_decoder));
+ } OSSL_TRACE_END(DECODER);
+
+ /*
+ * If |decoder| is NULL, it means we've just started, and the caller
+ * may have specified what it expects the initial input to be. If
+ * that's the case, we do this extra check.
+ */
+ if (decoder == NULL && ctx->start_input_type != NULL
+ && OPENSSL_strcasecmp(ctx->start_input_type, new_input_type) != 0) {
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) %s [%u] the start input type '%s' doesn't match the input type of the considered decoder, skipping...\n",
+ (void *)new_data.ctx, LEVEL, (unsigned int)i,
+ ctx->start_input_type);
+ } OSSL_TRACE_END(DECODER);
+ continue;
+ }
+
+ /*
+ * If we have a previous decoder, we check that the input type
+ * of the next to be used matches the type of this previous one.
+ * |new_input_type| holds the value of the "input-type" parameter
+ * for the decoder we're currently considering.
+ */
+ if (decoder != NULL && !OSSL_DECODER_is_a(decoder, new_input_type)) {
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) %s [%u] the input type doesn't match the name of the previous decoder (%p), skipping...\n",
+ (void *)new_data.ctx, LEVEL, (unsigned int)i,
+ (void *)decoder);
+ } OSSL_TRACE_END(DECODER);
+ continue;
+ }
+
+ /*
+ * If the previous decoder gave us a data type, we check to see
+ * if that matches the decoder we're currently considering.
+ */
+ if (data_type != NULL && !OSSL_DECODER_is_a(new_decoder, data_type)) {
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) %s [%u] the previous decoder's data type doesn't match the name of the considered decoder, skipping...\n",
+ (void *)new_data.ctx, LEVEL, (unsigned int)i);
+ } OSSL_TRACE_END(DECODER);
+ continue;
+ }
+
+ /*
+ * If the previous decoder gave us a data structure name, we check
+ * to see that it matches the input data structure of the decoder
+ * we're currently considering.
+ */
+ if (data_structure != NULL
+ && (new_input_structure == NULL
+ || OPENSSL_strcasecmp(data_structure,
+ new_input_structure) != 0)) {
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) %s [%u] the previous decoder's data structure doesn't match the input structure of the considered decoder, skipping...\n",
+ (void *)new_data.ctx, LEVEL, (unsigned int)i);
+ } OSSL_TRACE_END(DECODER);
+ continue;
+ }
+
+ /*
+ * If the decoder we're currently considering specifies a structure,
+ * and this check hasn't already been done earlier in this chain of
+ * decoder_process() calls, check that it matches the user provided
+ * input structure, if one is given.
+ */
+ if (!data->flag_input_structure_checked
+ && ctx->input_structure != NULL
+ && new_input_structure != NULL) {
+ data->flag_input_structure_checked = 1;
+ if (OPENSSL_strcasecmp(new_input_structure,
+ ctx->input_structure) != 0) {
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) %s [%u] the previous decoder's data structure doesn't match the input structure given by the user, skipping...\n",
+ (void *)new_data.ctx, LEVEL, (unsigned int)i);
+ } OSSL_TRACE_END(DECODER);
+ continue;
+ }
+ }
+
+ /*
+ * Checking the return value of BIO_reset() or BIO_seek() is unsafe.
+ * Furthermore, BIO_reset() is unsafe to use if the source BIO happens
+ * to be a BIO_s_mem(), because the earlier BIO_tell() gives us zero
+ * no matter where we are in the underlying buffer we're reading from.
+ *
+ * So, we simply do a BIO_seek(), and use BIO_tell() that we're back
+ * at the same position. This is a best effort attempt, but BIO_seek()
+ * and BIO_tell() should come as a pair...
+ */
+ (void)BIO_seek(bio, loc);
+ if (BIO_tell(bio) != loc)
+ goto end;
+
+ /* Recurse */
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) %s [%u] Running decoder instance %p\n",
+ (void *)new_data.ctx, LEVEL, (unsigned int)i,
+ (void *)new_decoder_inst);
+ } OSSL_TRACE_END(DECODER);
+
+ /*
+ * We only care about errors reported from decoder implementations
+ * if it returns false (i.e. there was a fatal error).
+ */
+ ERR_set_mark();
+
+ new_data.current_decoder_inst_index = i;
+ new_data.flag_input_structure_checked
+ = data->flag_input_structure_checked;
+ ok = new_decoder->decode(new_decoderctx, cbio,
+ new_data.ctx->selection,
+ decoder_process, &new_data,
+ ossl_pw_passphrase_callback_dec,
+ &new_data.ctx->pwdata);
+
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) %s [%u] Running decoder instance %p => %d"
+ " (recursed further: %s, construct called: %s)\n",
+ (void *)new_data.ctx, LEVEL, (unsigned int)i,
+ (void *)new_decoder_inst, ok,
+ new_data.flag_next_level_called ? "yes" : "no",
+ new_data.flag_construct_called ? "yes" : "no");
+ } OSSL_TRACE_END(DECODER);
+
+ data->flag_construct_called = new_data.flag_construct_called;
+
+ /* Break on error or if we tried to construct an object already */
+ if (!ok || data->flag_construct_called) {
+ ERR_clear_last_mark();
+ break;
+ }
+ ERR_pop_to_mark();
+
+ /*
+ * Break if the decoder implementation that we called recursed, since
+ * that indicates that it successfully decoded something.
+ */
+ if (new_data.flag_next_level_called)
+ break;
+ }
+
+ end:
+ ossl_core_bio_free(cbio);
+ BIO_free(new_data.bio);
+ return ok;
+}
diff --git a/crypto/encode_decode/decoder_meth.c b/crypto/encode_decode/decoder_meth.c
new file mode 100644
index 000000000000..56899a926981
--- /dev/null
+++ b/crypto/encode_decode/decoder_meth.c
@@ -0,0 +1,701 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/decoder.h>
+#include <openssl/ui.h>
+#include "internal/core.h"
+#include "internal/namemap.h"
+#include "internal/property.h"
+#include "internal/provider.h"
+#include "crypto/decoder.h"
+#include "encoder_local.h"
+
+/*
+ * Decoder can have multiple names, separated with colons in a name string
+ */
+#define NAME_SEPARATOR ':'
+
+/* Simple method structure constructor and destructor */
+static OSSL_DECODER *ossl_decoder_new(void)
+{
+ OSSL_DECODER *decoder = NULL;
+
+ if ((decoder = OPENSSL_zalloc(sizeof(*decoder))) == NULL
+ || (decoder->base.lock = CRYPTO_THREAD_lock_new()) == NULL) {
+ OSSL_DECODER_free(decoder);
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ decoder->base.refcnt = 1;
+
+ return decoder;
+}
+
+int OSSL_DECODER_up_ref(OSSL_DECODER *decoder)
+{
+ int ref = 0;
+
+ CRYPTO_UP_REF(&decoder->base.refcnt, &ref, decoder->base.lock);
+ return 1;
+}
+
+void OSSL_DECODER_free(OSSL_DECODER *decoder)
+{
+ int ref = 0;
+
+ if (decoder == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&decoder->base.refcnt, &ref, decoder->base.lock);
+ if (ref > 0)
+ return;
+ OPENSSL_free(decoder->base.name);
+ ossl_property_free(decoder->base.parsed_propdef);
+ ossl_provider_free(decoder->base.prov);
+ CRYPTO_THREAD_lock_free(decoder->base.lock);
+ OPENSSL_free(decoder);
+}
+
+/* Permanent decoder method store, constructor and destructor */
+static void decoder_store_free(void *vstore)
+{
+ ossl_method_store_free(vstore);
+}
+
+static void *decoder_store_new(OSSL_LIB_CTX *ctx)
+{
+ return ossl_method_store_new(ctx);
+}
+
+
+static const OSSL_LIB_CTX_METHOD decoder_store_method = {
+ /* We want decoder_store to be cleaned up before the provider store */
+ OSSL_LIB_CTX_METHOD_PRIORITY_2,
+ decoder_store_new,
+ decoder_store_free,
+};
+
+/* Data to be passed through ossl_method_construct() */
+struct decoder_data_st {
+ OSSL_LIB_CTX *libctx;
+ int id; /* For get_decoder_from_store() */
+ const char *names; /* For get_decoder_from_store() */
+ const char *propquery; /* For get_decoder_from_store() */
+
+ OSSL_METHOD_STORE *tmp_store; /* For get_tmp_decoder_store() */
+
+ unsigned int flag_construct_error_occurred : 1;
+};
+
+/*
+ * Generic routines to fetch / create DECODER methods with
+ * ossl_method_construct()
+ */
+
+/* Temporary decoder method store, constructor and destructor */
+static void *get_tmp_decoder_store(void *data)
+{
+ struct decoder_data_st *methdata = data;
+
+ if (methdata->tmp_store == NULL)
+ methdata->tmp_store = ossl_method_store_new(methdata->libctx);
+ return methdata->tmp_store;
+}
+
+static void dealloc_tmp_decoder_store(void *store)
+{
+ if (store != NULL)
+ ossl_method_store_free(store);
+}
+
+/* Get the permanent decoder store */
+static OSSL_METHOD_STORE *get_decoder_store(OSSL_LIB_CTX *libctx)
+{
+ return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DECODER_STORE_INDEX,
+ &decoder_store_method);
+}
+
+static int reserve_decoder_store(void *store, void *data)
+{
+ struct decoder_data_st *methdata = data;
+
+ if (store == NULL
+ && (store = get_decoder_store(methdata->libctx)) == NULL)
+ return 0;
+
+ return ossl_method_lock_store(store);
+}
+
+static int unreserve_decoder_store(void *store, void *data)
+{
+ struct decoder_data_st *methdata = data;
+
+ if (store == NULL
+ && (store = get_decoder_store(methdata->libctx)) == NULL)
+ return 0;
+
+ return ossl_method_unlock_store(store);
+}
+
+/* Get decoder methods from a store, or put one in */
+static void *get_decoder_from_store(void *store, const OSSL_PROVIDER **prov,
+ void *data)
+{
+ struct decoder_data_st *methdata = data;
+ void *method = NULL;
+ int id;
+
+ /*
+ * get_decoder_from_store() is only called to try and get the method
+ * that OSSL_DECODER_fetch() is asking for, and the name or name id are
+ * passed via methdata.
+ */
+ if ((id = methdata->id) == 0 && methdata->names != NULL) {
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
+ const char *names = methdata->names;
+ const char *q = strchr(names, NAME_SEPARATOR);
+ size_t l = (q == NULL ? strlen(names) : (size_t)(q - names));
+
+ if (namemap == 0)
+ return NULL;
+ id = ossl_namemap_name2num_n(namemap, names, l);
+ }
+
+ if (id == 0)
+ return NULL;
+
+ if (store == NULL
+ && (store = get_decoder_store(methdata->libctx)) == NULL)
+ return NULL;
+
+ if (!ossl_method_store_fetch(store, id, methdata->propquery, prov, &method))
+ return NULL;
+ return method;
+}
+
+static int put_decoder_in_store(void *store, void *method,
+ const OSSL_PROVIDER *prov,
+ const char *names, const char *propdef,
+ void *data)
+{
+ struct decoder_data_st *methdata = data;
+ OSSL_NAMEMAP *namemap;
+ int id;
+ size_t l = 0;
+
+ /*
+ * put_decoder_in_store() is only called with an OSSL_DECODER method that
+ * was successfully created by construct_decoder() below, which means that
+ * all the names should already be stored in the namemap with the same
+ * numeric identity, so just use the first to get that identity.
+ */
+ if (names != NULL) {
+ const char *q = strchr(names, NAME_SEPARATOR);
+
+ l = (q == NULL ? strlen(names) : (size_t)(q - names));
+ }
+
+ if ((namemap = ossl_namemap_stored(methdata->libctx)) == NULL
+ || (id = ossl_namemap_name2num_n(namemap, names, l)) == 0)
+ return 0;
+
+ if (store == NULL && (store = get_decoder_store(methdata->libctx)) == NULL)
+ return 0;
+
+ return ossl_method_store_add(store, prov, id, propdef, method,
+ (int (*)(void *))OSSL_DECODER_up_ref,
+ (void (*)(void *))OSSL_DECODER_free);
+}
+
+/* Create and populate a decoder method */
+void *ossl_decoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
+{
+ OSSL_DECODER *decoder = NULL;
+ const OSSL_DISPATCH *fns = algodef->implementation;
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
+
+ if ((decoder = ossl_decoder_new()) == NULL)
+ return NULL;
+ decoder->base.id = id;
+ if ((decoder->base.name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
+ OSSL_DECODER_free(decoder);
+ return NULL;
+ }
+ decoder->base.algodef = algodef;
+ if ((decoder->base.parsed_propdef
+ = ossl_parse_property(libctx, algodef->property_definition)) == NULL) {
+ OSSL_DECODER_free(decoder);
+ return NULL;
+ }
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_DECODER_NEWCTX:
+ if (decoder->newctx == NULL)
+ decoder->newctx = OSSL_FUNC_decoder_newctx(fns);
+ break;
+ case OSSL_FUNC_DECODER_FREECTX:
+ if (decoder->freectx == NULL)
+ decoder->freectx = OSSL_FUNC_decoder_freectx(fns);
+ break;
+ case OSSL_FUNC_DECODER_GET_PARAMS:
+ if (decoder->get_params == NULL)
+ decoder->get_params =
+ OSSL_FUNC_decoder_get_params(fns);
+ break;
+ case OSSL_FUNC_DECODER_GETTABLE_PARAMS:
+ if (decoder->gettable_params == NULL)
+ decoder->gettable_params =
+ OSSL_FUNC_decoder_gettable_params(fns);
+ break;
+ case OSSL_FUNC_DECODER_SET_CTX_PARAMS:
+ if (decoder->set_ctx_params == NULL)
+ decoder->set_ctx_params =
+ OSSL_FUNC_decoder_set_ctx_params(fns);
+ break;
+ case OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS:
+ if (decoder->settable_ctx_params == NULL)
+ decoder->settable_ctx_params =
+ OSSL_FUNC_decoder_settable_ctx_params(fns);
+ break;
+ case OSSL_FUNC_DECODER_DOES_SELECTION:
+ if (decoder->does_selection == NULL)
+ decoder->does_selection =
+ OSSL_FUNC_decoder_does_selection(fns);
+ break;
+ case OSSL_FUNC_DECODER_DECODE:
+ if (decoder->decode == NULL)
+ decoder->decode = OSSL_FUNC_decoder_decode(fns);
+ break;
+ case OSSL_FUNC_DECODER_EXPORT_OBJECT:
+ if (decoder->export_object == NULL)
+ decoder->export_object = OSSL_FUNC_decoder_export_object(fns);
+ break;
+ }
+ }
+ /*
+ * Try to check that the method is sensible.
+ * If you have a constructor, you must have a destructor and vice versa.
+ * You must have at least one of the encoding driver functions.
+ */
+ if (!((decoder->newctx == NULL && decoder->freectx == NULL)
+ || (decoder->newctx != NULL && decoder->freectx != NULL))
+ || decoder->decode == NULL) {
+ OSSL_DECODER_free(decoder);
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROVIDER_FUNCTIONS);
+ return NULL;
+ }
+
+ if (prov != NULL && !ossl_provider_up_ref(prov)) {
+ OSSL_DECODER_free(decoder);
+ return NULL;
+ }
+
+ decoder->base.prov = prov;
+ return decoder;
+}
+
+
+/*
+ * The core fetching functionality passes the names of the implementation.
+ * This function is responsible to getting an identity number for them,
+ * then call ossl_decoder_from_algorithm() with that identity number.
+ */
+static void *construct_decoder(const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov, void *data)
+{
+ /*
+ * This function is only called if get_decoder_from_store() returned
+ * NULL, so it's safe to say that of all the spots to create a new
+ * namemap entry, this is it. Should the name already exist there, we
+ * know that ossl_namemap_add() will return its corresponding number.
+ */
+ struct decoder_data_st *methdata = data;
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+ const char *names = algodef->algorithm_names;
+ int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR);
+ void *method = NULL;
+
+ if (id != 0)
+ method = ossl_decoder_from_algorithm(id, algodef, prov);
+
+ /*
+ * Flag to indicate that there was actual construction errors. This
+ * helps inner_evp_generic_fetch() determine what error it should
+ * record on inaccessible algorithms.
+ */
+ if (method == NULL)
+ methdata->flag_construct_error_occurred = 1;
+
+ return method;
+}
+
+/* Intermediary function to avoid ugly casts, used below */
+static void destruct_decoder(void *method, void *data)
+{
+ OSSL_DECODER_free(method);
+}
+
+static int up_ref_decoder(void *method)
+{
+ return OSSL_DECODER_up_ref(method);
+}
+
+static void free_decoder(void *method)
+{
+ OSSL_DECODER_free(method);
+}
+
+/* Fetching support. Can fetch by numeric identity or by name */
+static OSSL_DECODER *
+inner_ossl_decoder_fetch(struct decoder_data_st *methdata, int id,
+ const char *name, const char *properties)
+{
+ OSSL_METHOD_STORE *store = get_decoder_store(methdata->libctx);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
+ const char *const propq = properties != NULL ? properties : "";
+ void *method = NULL;
+ int unsupported = 0;
+
+ if (store == NULL || namemap == NULL) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_INVALID_ARGUMENT);
+ return NULL;
+ }
+
+ /*
+ * If we have been passed both an id and a name, we have an
+ * internal programming error.
+ */
+ if (!ossl_assert(id == 0 || name == NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ if (id == 0 && name != NULL)
+ id = ossl_namemap_name2num(namemap, name);
+
+ /*
+ * If we haven't found the name yet, chances are that the algorithm to
+ * be fetched is unsupported.
+ */
+ if (id == 0)
+ unsupported = 1;
+
+ if (id == 0
+ || !ossl_method_store_cache_get(store, NULL, id, propq, &method)) {
+ OSSL_METHOD_CONSTRUCT_METHOD mcm = {
+ get_tmp_decoder_store,
+ reserve_decoder_store,
+ unreserve_decoder_store,
+ get_decoder_from_store,
+ put_decoder_in_store,
+ construct_decoder,
+ destruct_decoder
+ };
+ OSSL_PROVIDER *prov = NULL;
+
+ methdata->id = id;
+ methdata->names = name;
+ methdata->propquery = propq;
+ methdata->flag_construct_error_occurred = 0;
+ if ((method = ossl_method_construct(methdata->libctx, OSSL_OP_DECODER,
+ &prov, 0 /* !force_cache */,
+ &mcm, methdata)) != NULL) {
+ /*
+ * If construction did create a method for us, we know that
+ * there is a correct name_id and meth_id, since those have
+ * already been calculated in get_decoder_from_store() and
+ * put_decoder_in_store() above.
+ */
+ if (id == 0 && name != NULL)
+ id = ossl_namemap_name2num(namemap, name);
+ if (id != 0)
+ ossl_method_store_cache_set(store, prov, id, propq, method,
+ up_ref_decoder, free_decoder);
+ }
+
+ /*
+ * If we never were in the constructor, the algorithm to be fetched
+ * is unsupported.
+ */
+ unsupported = !methdata->flag_construct_error_occurred;
+ }
+
+ if ((id != 0 || name != NULL) && method == NULL) {
+ int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED;
+
+ if (name == NULL)
+ name = ossl_namemap_num2name(namemap, id, 0);
+ ERR_raise_data(ERR_LIB_OSSL_DECODER, code,
+ "%s, Name (%s : %d), Properties (%s)",
+ ossl_lib_ctx_get_descriptor(methdata->libctx),
+ name == NULL ? "<null>" : name, id,
+ properties == NULL ? "<null>" : properties);
+ }
+
+ return method;
+}
+
+OSSL_DECODER *OSSL_DECODER_fetch(OSSL_LIB_CTX *libctx, const char *name,
+ const char *properties)
+{
+ struct decoder_data_st methdata;
+ void *method;
+
+ methdata.libctx = libctx;
+ methdata.tmp_store = NULL;
+ method = inner_ossl_decoder_fetch(&methdata, 0, name, properties);
+ dealloc_tmp_decoder_store(methdata.tmp_store);
+ return method;
+}
+
+OSSL_DECODER *ossl_decoder_fetch_by_number(OSSL_LIB_CTX *libctx, int id,
+ const char *properties)
+{
+ struct decoder_data_st methdata;
+ void *method;
+
+ methdata.libctx = libctx;
+ methdata.tmp_store = NULL;
+ method = inner_ossl_decoder_fetch(&methdata, id, NULL, properties);
+ dealloc_tmp_decoder_store(methdata.tmp_store);
+ return method;
+}
+
+int ossl_decoder_store_cache_flush(OSSL_LIB_CTX *libctx)
+{
+ OSSL_METHOD_STORE *store = get_decoder_store(libctx);
+
+ if (store != NULL)
+ return ossl_method_store_cache_flush_all(store);
+ return 1;
+}
+
+int ossl_decoder_store_remove_all_provided(const OSSL_PROVIDER *prov)
+{
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
+ OSSL_METHOD_STORE *store = get_decoder_store(libctx);
+
+ if (store != NULL)
+ return ossl_method_store_remove_all_provided(store, prov);
+ return 1;
+}
+
+/*
+ * Library of basic method functions
+ */
+
+const OSSL_PROVIDER *OSSL_DECODER_get0_provider(const OSSL_DECODER *decoder)
+{
+ if (!ossl_assert(decoder != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ return decoder->base.prov;
+}
+
+const char *OSSL_DECODER_get0_properties(const OSSL_DECODER *decoder)
+{
+ if (!ossl_assert(decoder != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ return decoder->base.algodef->property_definition;
+}
+
+const OSSL_PROPERTY_LIST *
+ossl_decoder_parsed_properties(const OSSL_DECODER *decoder)
+{
+ if (!ossl_assert(decoder != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ return decoder->base.parsed_propdef;
+}
+
+int ossl_decoder_get_number(const OSSL_DECODER *decoder)
+{
+ if (!ossl_assert(decoder != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ return decoder->base.id;
+}
+
+const char *OSSL_DECODER_get0_name(const OSSL_DECODER *decoder)
+{
+ return decoder->base.name;
+}
+
+const char *OSSL_DECODER_get0_description(const OSSL_DECODER *decoder)
+{
+ return decoder->base.algodef->algorithm_description;
+}
+
+int OSSL_DECODER_is_a(const OSSL_DECODER *decoder, const char *name)
+{
+ if (decoder->base.prov != NULL) {
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(decoder->base.prov);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+
+ return ossl_namemap_name2num(namemap, name) == decoder->base.id;
+ }
+ return 0;
+}
+
+struct do_one_data_st {
+ void (*user_fn)(OSSL_DECODER *decoder, void *arg);
+ void *user_arg;
+};
+
+static void do_one(ossl_unused int id, void *method, void *arg)
+{
+ struct do_one_data_st *data = arg;
+
+ data->user_fn(method, data->user_arg);
+}
+
+void OSSL_DECODER_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*user_fn)(OSSL_DECODER *decoder,
+ void *arg),
+ void *user_arg)
+{
+ struct decoder_data_st methdata;
+ struct do_one_data_st data;
+
+ methdata.libctx = libctx;
+ methdata.tmp_store = NULL;
+ (void)inner_ossl_decoder_fetch(&methdata, 0, NULL, NULL /* properties */);
+
+ data.user_fn = user_fn;
+ data.user_arg = user_arg;
+ if (methdata.tmp_store != NULL)
+ ossl_method_store_do_all(methdata.tmp_store, &do_one, &data);
+ ossl_method_store_do_all(get_decoder_store(libctx), &do_one, &data);
+ dealloc_tmp_decoder_store(methdata.tmp_store);
+}
+
+int OSSL_DECODER_names_do_all(const OSSL_DECODER *decoder,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (decoder == NULL)
+ return 0;
+
+ if (decoder->base.prov != NULL) {
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(decoder->base.prov);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+
+ return ossl_namemap_doall_names(namemap, decoder->base.id, fn, data);
+ }
+
+ return 1;
+}
+
+const OSSL_PARAM *
+OSSL_DECODER_gettable_params(OSSL_DECODER *decoder)
+{
+ if (decoder != NULL && decoder->gettable_params != NULL) {
+ void *provctx = ossl_provider_ctx(OSSL_DECODER_get0_provider(decoder));
+
+ return decoder->gettable_params(provctx);
+ }
+ return NULL;
+}
+
+int OSSL_DECODER_get_params(OSSL_DECODER *decoder, OSSL_PARAM params[])
+{
+ if (decoder != NULL && decoder->get_params != NULL)
+ return decoder->get_params(params);
+ return 0;
+}
+
+const OSSL_PARAM *
+OSSL_DECODER_settable_ctx_params(OSSL_DECODER *decoder)
+{
+ if (decoder != NULL && decoder->settable_ctx_params != NULL) {
+ void *provctx = ossl_provider_ctx(OSSL_DECODER_get0_provider(decoder));
+
+ return decoder->settable_ctx_params(provctx);
+ }
+ return NULL;
+}
+
+/*
+ * Decoder context support
+ */
+
+/*
+ * |encoder| value NULL is valid, and signifies that there is no decoder.
+ * This is useful to provide fallback mechanisms.
+ * Functions that want to verify if there is a decoder can do so with
+ * OSSL_DECODER_CTX_get_decoder()
+ */
+OSSL_DECODER_CTX *OSSL_DECODER_CTX_new(void)
+{
+ OSSL_DECODER_CTX *ctx;
+
+ if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL)
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
+
+ return ctx;
+}
+
+int OSSL_DECODER_CTX_set_params(OSSL_DECODER_CTX *ctx,
+ const OSSL_PARAM params[])
+{
+ int ok = 1;
+ size_t i;
+ size_t l;
+
+ if (!ossl_assert(ctx != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (ctx->decoder_insts == NULL)
+ return 1;
+
+ l = OSSL_DECODER_CTX_get_num_decoders(ctx);
+ for (i = 0; i < l; i++) {
+ OSSL_DECODER_INSTANCE *decoder_inst =
+ sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, i);
+ OSSL_DECODER *decoder =
+ OSSL_DECODER_INSTANCE_get_decoder(decoder_inst);
+ OSSL_DECODER *decoderctx =
+ OSSL_DECODER_INSTANCE_get_decoder_ctx(decoder_inst);
+
+ if (decoderctx == NULL || decoder->set_ctx_params == NULL)
+ continue;
+ if (!decoder->set_ctx_params(decoderctx, params))
+ ok = 0;
+ }
+ return ok;
+}
+
+void OSSL_DECODER_CTX_free(OSSL_DECODER_CTX *ctx)
+{
+ if (ctx != NULL) {
+ if (ctx->cleanup != NULL)
+ ctx->cleanup(ctx->construct_data);
+ sk_OSSL_DECODER_INSTANCE_pop_free(ctx->decoder_insts,
+ ossl_decoder_instance_free);
+ ossl_pw_clear_passphrase_data(&ctx->pwdata);
+ OPENSSL_free(ctx);
+ }
+}
diff --git a/crypto/encode_decode/decoder_pkey.c b/crypto/encode_decode/decoder_pkey.c
new file mode 100644
index 000000000000..ed10bb1cee03
--- /dev/null
+++ b/crypto/encode_decode/decoder_pkey.c
@@ -0,0 +1,462 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_names.h>
+#include <openssl/core_object.h>
+#include <openssl/provider.h>
+#include <openssl/evp.h>
+#include <openssl/ui.h>
+#include <openssl/decoder.h>
+#include <openssl/safestack.h>
+#include <openssl/trace.h>
+#include "crypto/evp.h"
+#include "crypto/decoder.h"
+#include "encoder_local.h"
+
+int OSSL_DECODER_CTX_set_passphrase(OSSL_DECODER_CTX *ctx,
+ const unsigned char *kstr,
+ size_t klen)
+{
+ return ossl_pw_set_passphrase(&ctx->pwdata, kstr, klen);
+}
+
+int OSSL_DECODER_CTX_set_passphrase_ui(OSSL_DECODER_CTX *ctx,
+ const UI_METHOD *ui_method,
+ void *ui_data)
+{
+ return ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data);
+}
+
+int OSSL_DECODER_CTX_set_pem_password_cb(OSSL_DECODER_CTX *ctx,
+ pem_password_cb *cb, void *cbarg)
+{
+ return ossl_pw_set_pem_password_cb(&ctx->pwdata, cb, cbarg);
+}
+
+int OSSL_DECODER_CTX_set_passphrase_cb(OSSL_DECODER_CTX *ctx,
+ OSSL_PASSPHRASE_CALLBACK *cb,
+ void *cbarg)
+{
+ return ossl_pw_set_ossl_passphrase_cb(&ctx->pwdata, cb, cbarg);
+}
+
+/*
+ * Support for OSSL_DECODER_CTX_new_for_pkey:
+ * The construct data, and collecting keymgmt information for it
+ */
+
+DEFINE_STACK_OF(EVP_KEYMGMT)
+
+struct decoder_pkey_data_st {
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+ int selection;
+
+ STACK_OF(EVP_KEYMGMT) *keymgmts;
+ char *object_type; /* recorded object data type, may be NULL */
+ void **object; /* Where the result should end up */
+};
+
+static int decoder_construct_pkey(OSSL_DECODER_INSTANCE *decoder_inst,
+ const OSSL_PARAM *params,
+ void *construct_data)
+{
+ struct decoder_pkey_data_st *data = construct_data;
+ OSSL_DECODER *decoder = OSSL_DECODER_INSTANCE_get_decoder(decoder_inst);
+ void *decoderctx = OSSL_DECODER_INSTANCE_get_decoder_ctx(decoder_inst);
+ const OSSL_PROVIDER *decoder_prov = OSSL_DECODER_get0_provider(decoder);
+ EVP_KEYMGMT *keymgmt = NULL;
+ const OSSL_PROVIDER *keymgmt_prov = NULL;
+ int i, end;
+ /*
+ * |object_ref| points to a provider reference to an object, its exact
+ * contents entirely opaque to us, but may be passed to any provider
+ * function that expects this (such as OSSL_FUNC_keymgmt_load().
+ *
+ * This pointer is considered volatile, i.e. whatever it points at
+ * is assumed to be freed as soon as this function returns.
+ */
+ void *object_ref = NULL;
+ size_t object_ref_sz = 0;
+ const OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA_TYPE);
+ if (p != NULL) {
+ char *object_type = NULL;
+
+ if (!OSSL_PARAM_get_utf8_string(p, &object_type, 0))
+ return 0;
+ OPENSSL_free(data->object_type);
+ data->object_type = object_type;
+ }
+
+ /*
+ * For stuff that should end up in an EVP_PKEY, we only accept an object
+ * reference for the moment. This enforces that the key data itself
+ * remains with the provider.
+ */
+ p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_REFERENCE);
+ if (p == NULL || p->data_type != OSSL_PARAM_OCTET_STRING)
+ return 0;
+ object_ref = p->data;
+ object_ref_sz = p->data_size;
+
+ /*
+ * First, we try to find a keymgmt that comes from the same provider as
+ * the decoder that passed the params.
+ */
+ end = sk_EVP_KEYMGMT_num(data->keymgmts);
+ for (i = 0; i < end; i++) {
+ keymgmt = sk_EVP_KEYMGMT_value(data->keymgmts, i);
+ keymgmt_prov = EVP_KEYMGMT_get0_provider(keymgmt);
+
+ if (keymgmt_prov == decoder_prov
+ && evp_keymgmt_has_load(keymgmt)
+ && EVP_KEYMGMT_is_a(keymgmt, data->object_type))
+ break;
+ }
+ if (i < end) {
+ /* To allow it to be freed further down */
+ if (!EVP_KEYMGMT_up_ref(keymgmt))
+ return 0;
+ } else if ((keymgmt = EVP_KEYMGMT_fetch(data->libctx,
+ data->object_type,
+ data->propq)) != NULL) {
+ keymgmt_prov = EVP_KEYMGMT_get0_provider(keymgmt);
+ }
+
+ if (keymgmt != NULL) {
+ EVP_PKEY *pkey = NULL;
+ void *keydata = NULL;
+
+ /*
+ * If the EVP_KEYMGMT and the OSSL_DECODER are from the
+ * same provider, we assume that the KEYMGMT has a key loading
+ * function that can handle the provider reference we hold.
+ *
+ * Otherwise, we export from the decoder and import the
+ * result in the keymgmt.
+ */
+ if (keymgmt_prov == decoder_prov) {
+ keydata = evp_keymgmt_load(keymgmt, object_ref, object_ref_sz);
+ } else {
+ struct evp_keymgmt_util_try_import_data_st import_data;
+
+ import_data.keymgmt = keymgmt;
+ import_data.keydata = NULL;
+ import_data.selection = data->selection;
+
+ /*
+ * No need to check for errors here, the value of
+ * |import_data.keydata| is as much an indicator.
+ */
+ (void)decoder->export_object(decoderctx,
+ object_ref, object_ref_sz,
+ &evp_keymgmt_util_try_import,
+ &import_data);
+ keydata = import_data.keydata;
+ import_data.keydata = NULL;
+ }
+
+ if (keydata != NULL
+ && (pkey = evp_keymgmt_util_make_pkey(keymgmt, keydata)) == NULL)
+ evp_keymgmt_freedata(keymgmt, keydata);
+
+ *data->object = pkey;
+
+ /*
+ * evp_keymgmt_util_make_pkey() increments the reference count when
+ * assigning the EVP_PKEY, so we can free the keymgmt here.
+ */
+ EVP_KEYMGMT_free(keymgmt);
+ }
+ /*
+ * We successfully looked through, |*ctx->object| determines if we
+ * actually found something.
+ */
+ return (*data->object != NULL);
+}
+
+static void decoder_clean_pkey_construct_arg(void *construct_data)
+{
+ struct decoder_pkey_data_st *data = construct_data;
+
+ if (data != NULL) {
+ sk_EVP_KEYMGMT_pop_free(data->keymgmts, EVP_KEYMGMT_free);
+ OPENSSL_free(data->propq);
+ OPENSSL_free(data->object_type);
+ OPENSSL_free(data);
+ }
+}
+
+static void collect_name(const char *name, void *arg)
+{
+ STACK_OF(OPENSSL_CSTRING) *names = arg;
+
+ sk_OPENSSL_CSTRING_push(names, name);
+}
+
+static void collect_keymgmt(EVP_KEYMGMT *keymgmt, void *arg)
+{
+ STACK_OF(EVP_KEYMGMT) *keymgmts = arg;
+
+ if (!EVP_KEYMGMT_up_ref(keymgmt) /* ref++ */)
+ return;
+ if (sk_EVP_KEYMGMT_push(keymgmts, keymgmt) <= 0) {
+ EVP_KEYMGMT_free(keymgmt); /* ref-- */
+ return;
+ }
+}
+
+struct collect_decoder_data_st {
+ STACK_OF(OPENSSL_CSTRING) *names;
+ OSSL_DECODER_CTX *ctx;
+
+ int total;
+ unsigned int error_occurred:1;
+};
+
+static void collect_decoder(OSSL_DECODER *decoder, void *arg)
+{
+ struct collect_decoder_data_st *data = arg;
+ size_t i, end_i;
+ const OSSL_PROVIDER *prov = OSSL_DECODER_get0_provider(decoder);
+ void *provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
+
+ if (data->error_occurred)
+ return;
+
+ if (data->names == NULL) {
+ data->error_occurred = 1;
+ return;
+ }
+
+ /*
+ * Either the caller didn't give a selection, or if they did,
+ * the decoder must tell us if it supports that selection to
+ * be accepted. If the decoder doesn't have |does_selection|,
+ * it's seen as taking anything.
+ */
+ if (decoder->does_selection != NULL
+ && !decoder->does_selection(provctx, data->ctx->selection))
+ return;
+
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) Checking out decoder %p:\n"
+ " %s with %s\n",
+ (void *)data->ctx, (void *)decoder,
+ OSSL_DECODER_get0_name(decoder),
+ OSSL_DECODER_get0_properties(decoder));
+ } OSSL_TRACE_END(DECODER);
+
+ end_i = sk_OPENSSL_CSTRING_num(data->names);
+ for (i = 0; i < end_i; i++) {
+ const char *name = sk_OPENSSL_CSTRING_value(data->names, i);
+
+ if (OSSL_DECODER_is_a(decoder, name)) {
+ void *decoderctx = NULL;
+ OSSL_DECODER_INSTANCE *di = NULL;
+
+ if ((decoderctx = decoder->newctx(provctx)) == NULL) {
+ data->error_occurred = 1;
+ return;
+ }
+ if ((di = ossl_decoder_instance_new(decoder, decoderctx)) == NULL) {
+ decoder->freectx(decoderctx);
+ data->error_occurred = 1;
+ return;
+ }
+
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) Checking out decoder %p:\n"
+ " %s with %s\n",
+ (void *)data->ctx, (void *)decoder,
+ OSSL_DECODER_get0_name(decoder),
+ OSSL_DECODER_get0_properties(decoder));
+ } OSSL_TRACE_END(DECODER);
+
+ if (!ossl_decoder_ctx_add_decoder_inst(data->ctx, di)) {
+ ossl_decoder_instance_free(di);
+ data->error_occurred = 1;
+ return;
+ }
+ data->total++;
+
+ /* Success */
+ return;
+ }
+ }
+
+ /* Decoder not suitable - but not a fatal error */
+ data->error_occurred = 0;
+}
+
+int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
+ EVP_PKEY **pkey, const char *keytype,
+ OSSL_LIB_CTX *libctx,
+ const char *propquery)
+{
+ struct decoder_pkey_data_st *process_data = NULL;
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+ const char *input_type = ctx->start_input_type;
+ const char *input_structure = ctx->input_structure;
+ int ok = 0;
+ int isecoid = 0;
+ int i, end;
+
+ if (keytype != NULL
+ && (strcmp(keytype, "id-ecPublicKey") == 0
+ || strcmp(keytype, "1.2.840.10045.2.1") == 0))
+ isecoid = 1;
+
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) Looking for decoders producing %s%s%s%s%s%s\n",
+ (void *)ctx,
+ keytype != NULL ? keytype : "",
+ keytype != NULL ? " keys" : "keys of any type",
+ input_type != NULL ? " from " : "",
+ input_type != NULL ? input_type : "",
+ input_structure != NULL ? " with " : "",
+ input_structure != NULL ? input_structure : "");
+ } OSSL_TRACE_END(DECODER);
+
+ if ((process_data = OPENSSL_zalloc(sizeof(*process_data))) == NULL
+ || (propquery != NULL
+ && (process_data->propq = OPENSSL_strdup(propquery)) == NULL)
+ || (process_data->keymgmts = sk_EVP_KEYMGMT_new_null()) == NULL
+ || (names = sk_OPENSSL_CSTRING_new_null()) == NULL) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ process_data->object = (void **)pkey;
+ process_data->libctx = libctx;
+ process_data->selection = ctx->selection;
+
+ /* First, find all keymgmts to form goals */
+ EVP_KEYMGMT_do_all_provided(libctx, collect_keymgmt,
+ process_data->keymgmts);
+
+ /* Then, we collect all the keymgmt names */
+ end = sk_EVP_KEYMGMT_num(process_data->keymgmts);
+ for (i = 0; i < end; i++) {
+ EVP_KEYMGMT *keymgmt = sk_EVP_KEYMGMT_value(process_data->keymgmts, i);
+
+ /*
+ * If the key type is given by the caller, we only use the matching
+ * KEYMGMTs, otherwise we use them all.
+ * We have to special case SM2 here because of its abuse of the EC OID.
+ * The EC OID can be used to identify an EC key or an SM2 key - so if
+ * we have seen that OID we try both key types
+ */
+ if (keytype == NULL
+ || EVP_KEYMGMT_is_a(keymgmt, keytype)
+ || (isecoid && EVP_KEYMGMT_is_a(keymgmt, "SM2"))) {
+ if (!EVP_KEYMGMT_names_do_all(keymgmt, collect_name, names)) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+ }
+
+ OSSL_TRACE_BEGIN(DECODER) {
+ end = sk_OPENSSL_CSTRING_num(names);
+ BIO_printf(trc_out,
+ " Found %d keytypes (possibly with duplicates)",
+ end);
+ for (i = 0; i < end; i++)
+ BIO_printf(trc_out, "%s%s",
+ i == 0 ? ": " : ", ",
+ sk_OPENSSL_CSTRING_value(names, i));
+ BIO_printf(trc_out, "\n");
+ } OSSL_TRACE_END(DECODER);
+
+ /*
+ * Finally, find all decoders that have any keymgmt of the collected
+ * keymgmt names
+ */
+ {
+ struct collect_decoder_data_st collect_decoder_data = { NULL, };
+
+ collect_decoder_data.names = names;
+ collect_decoder_data.ctx = ctx;
+ OSSL_DECODER_do_all_provided(libctx,
+ collect_decoder, &collect_decoder_data);
+ sk_OPENSSL_CSTRING_free(names);
+ names = NULL;
+
+ if (collect_decoder_data.error_occurred)
+ goto err;
+
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) Got %d decoders producing keys\n",
+ (void *)ctx, collect_decoder_data.total);
+ } OSSL_TRACE_END(DECODER);
+ }
+
+ if (OSSL_DECODER_CTX_get_num_decoders(ctx) != 0) {
+ if (!OSSL_DECODER_CTX_set_construct(ctx, decoder_construct_pkey)
+ || !OSSL_DECODER_CTX_set_construct_data(ctx, process_data)
+ || !OSSL_DECODER_CTX_set_cleanup(ctx,
+ decoder_clean_pkey_construct_arg))
+ goto err;
+
+ process_data = NULL; /* Avoid it being freed */
+ }
+
+ ok = 1;
+ err:
+ decoder_clean_pkey_construct_arg(process_data);
+ sk_OPENSSL_CSTRING_free(names);
+
+ return ok;
+}
+
+OSSL_DECODER_CTX *
+OSSL_DECODER_CTX_new_for_pkey(EVP_PKEY **pkey,
+ const char *input_type,
+ const char *input_structure,
+ const char *keytype, int selection,
+ OSSL_LIB_CTX *libctx, const char *propquery)
+{
+ OSSL_DECODER_CTX *ctx = NULL;
+
+ if ((ctx = OSSL_DECODER_CTX_new()) == NULL) {
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) Looking for %s decoders with selection %d\n",
+ (void *)ctx, keytype, selection);
+ BIO_printf(trc_out, " input type: %s, input structure: %s\n",
+ input_type, input_structure);
+ } OSSL_TRACE_END(DECODER);
+
+ if (OSSL_DECODER_CTX_set_input_type(ctx, input_type)
+ && OSSL_DECODER_CTX_set_input_structure(ctx, input_structure)
+ && OSSL_DECODER_CTX_set_selection(ctx, selection)
+ && ossl_decoder_ctx_setup_for_pkey(ctx, pkey, keytype,
+ libctx, propquery)
+ && OSSL_DECODER_CTX_add_extra(ctx, libctx, propquery)) {
+ OSSL_TRACE_BEGIN(DECODER) {
+ BIO_printf(trc_out, "(ctx %p) Got %d decoders\n",
+ (void *)ctx, OSSL_DECODER_CTX_get_num_decoders(ctx));
+ } OSSL_TRACE_END(DECODER);
+ return ctx;
+ }
+
+ OSSL_DECODER_CTX_free(ctx);
+ return NULL;
+}
diff --git a/crypto/encode_decode/encoder_err.c b/crypto/encode_decode/encoder_err.c
new file mode 100644
index 000000000000..a904e87ef2e7
--- /dev/null
+++ b/crypto/encode_decode/encoder_err.c
@@ -0,0 +1,36 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/encodererr.h>
+#include "crypto/encodererr.h"
+
+#ifndef OPENSSL_NO_ERR
+
+static const ERR_STRING_DATA OSSL_ENCODER_str_reasons[] = {
+ {ERR_PACK(ERR_LIB_OSSL_ENCODER, 0, OSSL_ENCODER_R_ENCODER_NOT_FOUND),
+ "encoder not found"},
+ {ERR_PACK(ERR_LIB_OSSL_ENCODER, 0, OSSL_ENCODER_R_INCORRECT_PROPERTY_QUERY),
+ "incorrect property query"},
+ {ERR_PACK(ERR_LIB_OSSL_ENCODER, 0, OSSL_ENCODER_R_MISSING_GET_PARAMS),
+ "missing get params"},
+ {0, NULL}
+};
+
+#endif
+
+int ossl_err_load_OSSL_ENCODER_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(OSSL_ENCODER_str_reasons[0].error) == NULL)
+ ERR_load_strings_const(OSSL_ENCODER_str_reasons);
+#endif
+ return 1;
+}
diff --git a/crypto/encode_decode/encoder_lib.c b/crypto/encode_decode/encoder_lib.c
new file mode 100644
index 000000000000..7a55c7ab9a27
--- /dev/null
+++ b/crypto/encode_decode/encoder_lib.c
@@ -0,0 +1,674 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_names.h>
+#include <openssl/bio.h>
+#include <openssl/encoder.h>
+#include <openssl/buffer.h>
+#include <openssl/params.h>
+#include <openssl/provider.h>
+#include <openssl/trace.h>
+#include "internal/bio.h"
+#include "internal/provider.h"
+#include "encoder_local.h"
+
+struct encoder_process_data_st {
+ OSSL_ENCODER_CTX *ctx;
+
+ /* Current BIO */
+ BIO *bio;
+
+ /* Index of the current encoder instance to be processed */
+ int current_encoder_inst_index;
+
+ /* Processing data passed down through recursion */
+ int level; /* Recursion level */
+ OSSL_ENCODER_INSTANCE *next_encoder_inst;
+ int count_output_structure;
+
+ /* Processing data passed up through recursion */
+ OSSL_ENCODER_INSTANCE *prev_encoder_inst;
+ unsigned char *running_output;
+ size_t running_output_length;
+ /* Data type = the name of the first succeeding encoder implementation */
+ const char *data_type;
+};
+
+static int encoder_process(struct encoder_process_data_st *data);
+
+int OSSL_ENCODER_to_bio(OSSL_ENCODER_CTX *ctx, BIO *out)
+{
+ struct encoder_process_data_st data;
+
+ memset(&data, 0, sizeof(data));
+ data.ctx = ctx;
+ data.bio = out;
+ data.current_encoder_inst_index = OSSL_ENCODER_CTX_get_num_encoders(ctx);
+
+ if (data.current_encoder_inst_index == 0) {
+ ERR_raise_data(ERR_LIB_OSSL_ENCODER, OSSL_ENCODER_R_ENCODER_NOT_FOUND,
+ "No encoders were found. For standard encoders you need "
+ "at least one of the default or base providers "
+ "available. Did you forget to load them?");
+ return 0;
+ }
+
+ return encoder_process(&data) > 0;
+}
+
+#ifndef OPENSSL_NO_STDIO
+static BIO *bio_from_file(FILE *fp)
+{
+ BIO *b;
+
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_BUF_LIB);
+ return NULL;
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ return b;
+}
+
+int OSSL_ENCODER_to_fp(OSSL_ENCODER_CTX *ctx, FILE *fp)
+{
+ BIO *b = bio_from_file(fp);
+ int ret = 0;
+
+ if (b != NULL)
+ ret = OSSL_ENCODER_to_bio(ctx, b);
+
+ BIO_free(b);
+ return ret;
+}
+#endif
+
+int OSSL_ENCODER_to_data(OSSL_ENCODER_CTX *ctx, unsigned char **pdata,
+ size_t *pdata_len)
+{
+ BIO *out;
+ BUF_MEM *buf = NULL;
+ int ret = 0;
+
+ if (pdata_len == NULL) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ out = BIO_new(BIO_s_mem());
+
+ if (out != NULL
+ && OSSL_ENCODER_to_bio(ctx, out)
+ && BIO_get_mem_ptr(out, &buf) > 0) {
+ ret = 1; /* Hope for the best. A too small buffer will clear this */
+
+ if (pdata != NULL && *pdata != NULL) {
+ if (*pdata_len < buf->length)
+ /*
+ * It's tempting to do |*pdata_len = (size_t)buf->length|
+ * However, it's believed to be confusing more than helpful,
+ * so we don't.
+ */
+ ret = 0;
+ else
+ *pdata_len -= buf->length;
+ } else {
+ /* The buffer with the right size is already allocated for us */
+ *pdata_len = (size_t)buf->length;
+ }
+
+ if (ret) {
+ if (pdata != NULL) {
+ if (*pdata != NULL) {
+ memcpy(*pdata, buf->data, buf->length);
+ *pdata += buf->length;
+ } else {
+ /* In this case, we steal the data from BIO_s_mem() */
+ *pdata = (unsigned char *)buf->data;
+ buf->data = NULL;
+ }
+ }
+ }
+ }
+ BIO_free(out);
+ return ret;
+}
+
+int OSSL_ENCODER_CTX_set_selection(OSSL_ENCODER_CTX *ctx, int selection)
+{
+ if (!ossl_assert(ctx != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (!ossl_assert(selection != 0)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ ctx->selection = selection;
+ return 1;
+}
+
+int OSSL_ENCODER_CTX_set_output_type(OSSL_ENCODER_CTX *ctx,
+ const char *output_type)
+{
+ if (!ossl_assert(ctx != NULL) || !ossl_assert(output_type != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ ctx->output_type = output_type;
+ return 1;
+}
+
+int OSSL_ENCODER_CTX_set_output_structure(OSSL_ENCODER_CTX *ctx,
+ const char *output_structure)
+{
+ if (!ossl_assert(ctx != NULL) || !ossl_assert(output_structure != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ ctx->output_structure = output_structure;
+ return 1;
+}
+
+static OSSL_ENCODER_INSTANCE *ossl_encoder_instance_new(OSSL_ENCODER *encoder,
+ void *encoderctx)
+{
+ OSSL_ENCODER_INSTANCE *encoder_inst = NULL;
+ const OSSL_PROVIDER *prov;
+ OSSL_LIB_CTX *libctx;
+ const OSSL_PROPERTY_LIST *props;
+ const OSSL_PROPERTY_DEFINITION *prop;
+
+ if (!ossl_assert(encoder != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if ((encoder_inst = OPENSSL_zalloc(sizeof(*encoder_inst))) == NULL) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (!OSSL_ENCODER_up_ref(encoder)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ prov = OSSL_ENCODER_get0_provider(encoder);
+ libctx = ossl_provider_libctx(prov);
+ props = ossl_encoder_parsed_properties(encoder);
+ if (props == NULL) {
+ ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION,
+ "there are no property definitions with encoder %s",
+ OSSL_ENCODER_get0_name(encoder));
+ goto err;
+ }
+
+ /* The "output" property is mandatory */
+ prop = ossl_property_find_property(props, libctx, "output");
+ encoder_inst->output_type = ossl_property_get_string_value(libctx, prop);
+ if (encoder_inst->output_type == NULL) {
+ ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION,
+ "the mandatory 'output' property is missing "
+ "for encoder %s (properties: %s)",
+ OSSL_ENCODER_get0_name(encoder),
+ OSSL_ENCODER_get0_properties(encoder));
+ goto err;
+ }
+
+ /* The "structure" property is optional */
+ prop = ossl_property_find_property(props, libctx, "structure");
+ if (prop != NULL)
+ encoder_inst->output_structure
+ = ossl_property_get_string_value(libctx, prop);
+
+ encoder_inst->encoder = encoder;
+ encoder_inst->encoderctx = encoderctx;
+ return encoder_inst;
+ err:
+ ossl_encoder_instance_free(encoder_inst);
+ return NULL;
+}
+
+void ossl_encoder_instance_free(OSSL_ENCODER_INSTANCE *encoder_inst)
+{
+ if (encoder_inst != NULL) {
+ if (encoder_inst->encoder != NULL)
+ encoder_inst->encoder->freectx(encoder_inst->encoderctx);
+ encoder_inst->encoderctx = NULL;
+ OSSL_ENCODER_free(encoder_inst->encoder);
+ encoder_inst->encoder = NULL;
+ OPENSSL_free(encoder_inst);
+ }
+}
+
+static int ossl_encoder_ctx_add_encoder_inst(OSSL_ENCODER_CTX *ctx,
+ OSSL_ENCODER_INSTANCE *ei)
+{
+ int ok;
+
+ if (ctx->encoder_insts == NULL
+ && (ctx->encoder_insts =
+ sk_OSSL_ENCODER_INSTANCE_new_null()) == NULL) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ ok = (sk_OSSL_ENCODER_INSTANCE_push(ctx->encoder_insts, ei) > 0);
+ if (ok) {
+ OSSL_TRACE_BEGIN(ENCODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) Added encoder instance %p (encoder %p):\n"
+ " %s with %s\n",
+ (void *)ctx, (void *)ei, (void *)ei->encoder,
+ OSSL_ENCODER_get0_name(ei->encoder),
+ OSSL_ENCODER_get0_properties(ei->encoder));
+ } OSSL_TRACE_END(ENCODER);
+ }
+ return ok;
+}
+
+int OSSL_ENCODER_CTX_add_encoder(OSSL_ENCODER_CTX *ctx, OSSL_ENCODER *encoder)
+{
+ OSSL_ENCODER_INSTANCE *encoder_inst = NULL;
+ const OSSL_PROVIDER *prov = NULL;
+ void *encoderctx = NULL;
+ void *provctx = NULL;
+
+ if (!ossl_assert(ctx != NULL) || !ossl_assert(encoder != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ prov = OSSL_ENCODER_get0_provider(encoder);
+ provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
+
+ if ((encoderctx = encoder->newctx(provctx)) == NULL
+ || (encoder_inst =
+ ossl_encoder_instance_new(encoder, encoderctx)) == NULL)
+ goto err;
+ /* Avoid double free of encoderctx on further errors */
+ encoderctx = NULL;
+
+ if (!ossl_encoder_ctx_add_encoder_inst(ctx, encoder_inst))
+ goto err;
+
+ return 1;
+ err:
+ ossl_encoder_instance_free(encoder_inst);
+ if (encoderctx != NULL)
+ encoder->freectx(encoderctx);
+ return 0;
+}
+
+int OSSL_ENCODER_CTX_add_extra(OSSL_ENCODER_CTX *ctx,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ return 1;
+}
+
+int OSSL_ENCODER_CTX_get_num_encoders(OSSL_ENCODER_CTX *ctx)
+{
+ if (ctx == NULL || ctx->encoder_insts == NULL)
+ return 0;
+ return sk_OSSL_ENCODER_INSTANCE_num(ctx->encoder_insts);
+}
+
+int OSSL_ENCODER_CTX_set_construct(OSSL_ENCODER_CTX *ctx,
+ OSSL_ENCODER_CONSTRUCT *construct)
+{
+ if (!ossl_assert(ctx != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ ctx->construct = construct;
+ return 1;
+}
+
+int OSSL_ENCODER_CTX_set_construct_data(OSSL_ENCODER_CTX *ctx,
+ void *construct_data)
+{
+ if (!ossl_assert(ctx != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ ctx->construct_data = construct_data;
+ return 1;
+}
+
+int OSSL_ENCODER_CTX_set_cleanup(OSSL_ENCODER_CTX *ctx,
+ OSSL_ENCODER_CLEANUP *cleanup)
+{
+ if (!ossl_assert(ctx != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ ctx->cleanup = cleanup;
+ return 1;
+}
+
+OSSL_ENCODER *
+OSSL_ENCODER_INSTANCE_get_encoder(OSSL_ENCODER_INSTANCE *encoder_inst)
+{
+ if (encoder_inst == NULL)
+ return NULL;
+ return encoder_inst->encoder;
+}
+
+void *
+OSSL_ENCODER_INSTANCE_get_encoder_ctx(OSSL_ENCODER_INSTANCE *encoder_inst)
+{
+ if (encoder_inst == NULL)
+ return NULL;
+ return encoder_inst->encoderctx;
+}
+
+const char *
+OSSL_ENCODER_INSTANCE_get_output_type(OSSL_ENCODER_INSTANCE *encoder_inst)
+{
+ if (encoder_inst == NULL)
+ return NULL;
+ return encoder_inst->output_type;
+}
+
+const char *
+OSSL_ENCODER_INSTANCE_get_output_structure(OSSL_ENCODER_INSTANCE *encoder_inst)
+{
+ if (encoder_inst == NULL)
+ return NULL;
+ return encoder_inst->output_structure;
+}
+
+static int encoder_process(struct encoder_process_data_st *data)
+{
+ OSSL_ENCODER_INSTANCE *current_encoder_inst = NULL;
+ OSSL_ENCODER *current_encoder = NULL;
+ OSSL_ENCODER_CTX *current_encoder_ctx = NULL;
+ BIO *allocated_out = NULL;
+ const void *original_data = NULL;
+ OSSL_PARAM abstract[10];
+ const OSSL_PARAM *current_abstract = NULL;
+ int i;
+ int ok = -1; /* -1 signifies that the lookup loop gave nothing */
+ int top = 0;
+
+ if (data->next_encoder_inst == NULL) {
+ /* First iteration, where we prepare for what is to come */
+
+ data->count_output_structure =
+ data->ctx->output_structure == NULL ? -1 : 0;
+ top = 1;
+ }
+
+ for (i = data->current_encoder_inst_index; i-- > 0;) {
+ OSSL_ENCODER *next_encoder = NULL;
+ const char *current_output_type;
+ const char *current_output_structure;
+ struct encoder_process_data_st new_data;
+
+ if (!top)
+ next_encoder =
+ OSSL_ENCODER_INSTANCE_get_encoder(data->next_encoder_inst);
+
+ current_encoder_inst =
+ sk_OSSL_ENCODER_INSTANCE_value(data->ctx->encoder_insts, i);
+ current_encoder =
+ OSSL_ENCODER_INSTANCE_get_encoder(current_encoder_inst);
+ current_encoder_ctx =
+ OSSL_ENCODER_INSTANCE_get_encoder_ctx(current_encoder_inst);
+ current_output_type =
+ OSSL_ENCODER_INSTANCE_get_output_type(current_encoder_inst);
+ current_output_structure =
+ OSSL_ENCODER_INSTANCE_get_output_structure(current_encoder_inst);
+ memset(&new_data, 0, sizeof(new_data));
+ new_data.ctx = data->ctx;
+ new_data.current_encoder_inst_index = i;
+ new_data.next_encoder_inst = current_encoder_inst;
+ new_data.count_output_structure = data->count_output_structure;
+ new_data.level = data->level + 1;
+
+ OSSL_TRACE_BEGIN(ENCODER) {
+ BIO_printf(trc_out,
+ "[%d] (ctx %p) Considering encoder instance %p (encoder %p)\n",
+ data->level, (void *)data->ctx,
+ (void *)current_encoder_inst, (void *)current_encoder);
+ } OSSL_TRACE_END(ENCODER);
+
+ /*
+ * If this is the top call, we check if the output type of the current
+ * encoder matches the desired output type.
+ * If this isn't the top call, i.e. this is deeper in the recursion,
+ * we instead check if the output type of the current encoder matches
+ * the name of the next encoder (the one found by the parent call).
+ */
+ if (top) {
+ if (data->ctx->output_type != NULL
+ && OPENSSL_strcasecmp(current_output_type,
+ data->ctx->output_type) != 0) {
+ OSSL_TRACE_BEGIN(ENCODER) {
+ BIO_printf(trc_out,
+ "[%d] Skipping because current encoder output type (%s) != desired output type (%s)\n",
+ data->level,
+ current_output_type, data->ctx->output_type);
+ } OSSL_TRACE_END(ENCODER);
+ continue;
+ }
+ } else {
+ if (!OSSL_ENCODER_is_a(next_encoder, current_output_type)) {
+ OSSL_TRACE_BEGIN(ENCODER) {
+ BIO_printf(trc_out,
+ "[%d] Skipping because current encoder output type (%s) != name of encoder %p\n",
+ data->level,
+ current_output_type, (void *)next_encoder);
+ } OSSL_TRACE_END(ENCODER);
+ continue;
+ }
+ }
+
+ /*
+ * If the caller and the current encoder specify an output structure,
+ * Check if they match. If they do, count the match, otherwise skip
+ * the current encoder.
+ */
+ if (data->ctx->output_structure != NULL
+ && current_output_structure != NULL) {
+ if (OPENSSL_strcasecmp(data->ctx->output_structure,
+ current_output_structure) != 0) {
+ OSSL_TRACE_BEGIN(ENCODER) {
+ BIO_printf(trc_out,
+ "[%d] Skipping because current encoder output structure (%s) != ctx output structure (%s)\n",
+ data->level,
+ current_output_structure,
+ data->ctx->output_structure);
+ } OSSL_TRACE_END(ENCODER);
+ continue;
+ }
+
+ data->count_output_structure++;
+ }
+
+ /*
+ * Recurse to process the encoder implementations before the current
+ * one.
+ */
+ ok = encoder_process(&new_data);
+
+ data->prev_encoder_inst = new_data.prev_encoder_inst;
+ data->running_output = new_data.running_output;
+ data->running_output_length = new_data.running_output_length;
+
+ /*
+ * ok == -1 means that the recursion call above gave no further
+ * encoders, and that the one we're currently at should
+ * be tried.
+ * ok == 0 means that something failed in the recursion call
+ * above, making the result unsuitable for a chain.
+ * In this case, we simply continue to try finding a
+ * suitable encoder at this recursion level.
+ * ok == 1 means that the recursion call was successful, and we
+ * try to use the result at this recursion level.
+ */
+ if (ok != 0)
+ break;
+
+ OSSL_TRACE_BEGIN(ENCODER) {
+ BIO_printf(trc_out,
+ "[%d] Skipping because recusion level %d failed\n",
+ data->level, new_data.level);
+ } OSSL_TRACE_END(ENCODER);
+ }
+
+ /*
+ * If |i < 0|, we didn't find any useful encoder in this recursion, so
+ * we do the rest of the process only if |i >= 0|.
+ */
+ if (i < 0) {
+ ok = -1;
+
+ OSSL_TRACE_BEGIN(ENCODER) {
+ BIO_printf(trc_out,
+ "[%d] (ctx %p) No suitable encoder found\n",
+ data->level, (void *)data->ctx);
+ } OSSL_TRACE_END(ENCODER);
+ } else {
+ /* Preparations */
+
+ switch (ok) {
+ case 0:
+ break;
+ case -1:
+ /*
+ * We have reached the beginning of the encoder instance sequence,
+ * so we prepare the object to be encoded.
+ */
+
+ /*
+ * |data->count_output_structure| is one of these values:
+ *
+ * -1 There is no desired output structure
+ * 0 There is a desired output structure, and it wasn't
+ * matched by any of the encoder instances that were
+ * considered
+ * >0 There is a desired output structure, and at least one
+ * of the encoder instances matched it
+ */
+ if (data->count_output_structure == 0)
+ return 0;
+
+ original_data =
+ data->ctx->construct(current_encoder_inst,
+ data->ctx->construct_data);
+
+ /* Also set the data type, using the encoder implementation name */
+ data->data_type = OSSL_ENCODER_get0_name(current_encoder);
+
+ /* Assume that the constructor recorded an error */
+ if (original_data != NULL)
+ ok = 1;
+ else
+ ok = 0;
+ break;
+ case 1:
+ if (!ossl_assert(data->running_output != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INTERNAL_ERROR);
+ ok = 0;
+ break;
+ }
+
+ {
+ /*
+ * Create an object abstraction from the latest output, which
+ * was stolen from the previous round.
+ */
+
+ OSSL_PARAM *abstract_p = abstract;
+ const char *prev_output_structure =
+ OSSL_ENCODER_INSTANCE_get_output_structure(data->prev_encoder_inst);
+
+ *abstract_p++ =
+ OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
+ (char *)data->data_type, 0);
+ if (prev_output_structure != NULL)
+ *abstract_p++ =
+ OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE,
+ (char *)prev_output_structure,
+ 0);
+ *abstract_p++ =
+ OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA,
+ data->running_output,
+ data->running_output_length);
+ *abstract_p = OSSL_PARAM_construct_end();
+ current_abstract = abstract;
+ }
+ break;
+ }
+
+ /* Calling the encoder implementation */
+
+ if (ok) {
+ OSSL_CORE_BIO *cbio = NULL;
+ BIO *current_out = NULL;
+
+ /*
+ * If we're at the last encoder instance to use, we're setting up
+ * final output. Otherwise, set up an intermediary memory output.
+ */
+ if (top)
+ current_out = data->bio;
+ else if ((current_out = allocated_out = BIO_new(BIO_s_mem()))
+ == NULL)
+ ok = 0; /* Assume BIO_new() recorded an error */
+
+ if (ok)
+ ok = (cbio = ossl_core_bio_new_from_bio(current_out)) != NULL;
+ if (ok) {
+ ok = current_encoder->encode(current_encoder_ctx, cbio,
+ original_data, current_abstract,
+ data->ctx->selection,
+ ossl_pw_passphrase_callback_enc,
+ &data->ctx->pwdata);
+ OSSL_TRACE_BEGIN(ENCODER) {
+ BIO_printf(trc_out,
+ "[%d] (ctx %p) Running encoder instance %p => %d\n",
+ data->level, (void *)data->ctx,
+ (void *)current_encoder_inst, ok);
+ } OSSL_TRACE_END(ENCODER);
+ }
+
+ ossl_core_bio_free(cbio);
+ data->prev_encoder_inst = current_encoder_inst;
+ }
+ }
+
+ /* Cleanup and collecting the result */
+
+ OPENSSL_free(data->running_output);
+ data->running_output = NULL;
+
+ /*
+ * Steal the output from the BIO_s_mem, if we did allocate one.
+ * That'll be the data for an object abstraction in the next round.
+ */
+ if (allocated_out != NULL) {
+ BUF_MEM *buf;
+
+ BIO_get_mem_ptr(allocated_out, &buf);
+ data->running_output = (unsigned char *)buf->data;
+ data->running_output_length = buf->length;
+ memset(buf, 0, sizeof(*buf));
+ }
+
+ BIO_free(allocated_out);
+ if (original_data != NULL)
+ data->ctx->cleanup(data->ctx->construct_data);
+ return ok;
+}
diff --git a/crypto/encode_decode/encoder_local.h b/crypto/encode_decode/encoder_local.h
new file mode 100644
index 000000000000..c1885ffc771f
--- /dev/null
+++ b/crypto/encode_decode/encoder_local.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_dispatch.h>
+#include <openssl/types.h>
+#include <openssl/safestack.h>
+#include <openssl/encoder.h>
+#include <openssl/decoder.h>
+#include "internal/cryptlib.h"
+#include "internal/passphrase.h"
+#include "internal/property.h"
+#include "internal/refcount.h"
+
+struct ossl_endecode_base_st {
+ OSSL_PROVIDER *prov;
+ int id;
+ char *name;
+ const OSSL_ALGORITHM *algodef;
+ OSSL_PROPERTY_LIST *parsed_propdef;
+
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+};
+
+struct ossl_encoder_st {
+ struct ossl_endecode_base_st base;
+ OSSL_FUNC_encoder_newctx_fn *newctx;
+ OSSL_FUNC_encoder_freectx_fn *freectx;
+ OSSL_FUNC_encoder_get_params_fn *get_params;
+ OSSL_FUNC_encoder_gettable_params_fn *gettable_params;
+ OSSL_FUNC_encoder_set_ctx_params_fn *set_ctx_params;
+ OSSL_FUNC_encoder_settable_ctx_params_fn *settable_ctx_params;
+ OSSL_FUNC_encoder_does_selection_fn *does_selection;
+ OSSL_FUNC_encoder_encode_fn *encode;
+ OSSL_FUNC_encoder_import_object_fn *import_object;
+ OSSL_FUNC_encoder_free_object_fn *free_object;
+};
+
+struct ossl_decoder_st {
+ struct ossl_endecode_base_st base;
+ OSSL_FUNC_decoder_newctx_fn *newctx;
+ OSSL_FUNC_decoder_freectx_fn *freectx;
+ OSSL_FUNC_decoder_get_params_fn *get_params;
+ OSSL_FUNC_decoder_gettable_params_fn *gettable_params;
+ OSSL_FUNC_decoder_set_ctx_params_fn *set_ctx_params;
+ OSSL_FUNC_decoder_settable_ctx_params_fn *settable_ctx_params;
+ OSSL_FUNC_decoder_does_selection_fn *does_selection;
+ OSSL_FUNC_decoder_decode_fn *decode;
+ OSSL_FUNC_decoder_export_object_fn *export_object;
+};
+
+struct ossl_encoder_instance_st {
+ OSSL_ENCODER *encoder; /* Never NULL */
+ void *encoderctx; /* Never NULL */
+ const char *output_type; /* Never NULL */
+ const char *output_structure; /* May be NULL */
+};
+
+DEFINE_STACK_OF(OSSL_ENCODER_INSTANCE)
+
+void ossl_encoder_instance_free(OSSL_ENCODER_INSTANCE *encoder_inst);
+
+struct ossl_encoder_ctx_st {
+ /*
+ * Select what parts of an object will be encoded. This selection is
+ * bit encoded, and the bits correspond to selection bits available with
+ * the provider side operation. For example, when encoding an EVP_PKEY,
+ * the OSSL_KEYMGMT_SELECT_ macros are used for this.
+ */
+ int selection;
+ /*
+ * The desired output type. The encoder implementation must have a
+ * gettable "output-type" parameter that this will match against.
+ */
+ const char *output_type;
+ /*
+ * The desired output structure, if that's relevant for the type of
+ * object being encoded. It may be used for selection of the starting
+ * encoder implementations in a chain.
+ */
+ const char *output_structure;
+
+ /*
+ * Decoders that are components of any current decoding path.
+ */
+ STACK_OF(OSSL_ENCODER_INSTANCE) *encoder_insts;
+
+ /*
+ * The constructor and destructor of an object to pass to the first
+ * encoder in a chain.
+ */
+ OSSL_ENCODER_CONSTRUCT *construct;
+ OSSL_ENCODER_CLEANUP *cleanup;
+ void *construct_data;
+
+ /* For any function that needs a passphrase reader */
+ struct ossl_passphrase_data_st pwdata;
+};
+
+struct ossl_decoder_instance_st {
+ OSSL_DECODER *decoder; /* Never NULL */
+ void *decoderctx; /* Never NULL */
+ const char *input_type; /* Never NULL */
+ const char *input_structure; /* May be NULL */
+
+ unsigned int flag_input_structure_was_set : 1;
+};
+
+DEFINE_STACK_OF(OSSL_DECODER_INSTANCE)
+
+struct ossl_decoder_ctx_st {
+ /*
+ * The caller may know the input type of the data they pass. If not,
+ * this will remain NULL and the decoding functionality will start
+ * with trying to decode with any desencoder in |decoder_insts|,
+ * regardless of their respective input type.
+ */
+ const char *start_input_type;
+ /*
+ * The desired input structure, if that's relevant for the type of
+ * object being encoded. It may be used for selection of the ending
+ * decoder implementations in a chain, i.e. those chosen using the
+ * expected output data type.
+ */
+ const char *input_structure;
+ /*
+ * Select what parts of an object are expected. This may affect what
+ * decoder implementations are selected, because there are structures
+ * that look different depending on this selection; for example, EVP_PKEY
+ * objects often have different encoding structures for private keys,
+ * public keys and key parameters.
+ * This selection is bit encoded, and the bits correspond to selection
+ * bits available with the provider side operation. For example, when
+ * encoding an EVP_PKEY, the OSSL_KEYMGMT_SELECT_ macros are used for
+ * this.
+ */
+ int selection;
+
+ /*
+ * Decoders that are components of any current decoding path.
+ */
+ STACK_OF(OSSL_DECODER_INSTANCE) *decoder_insts;
+
+ /*
+ * The constructors of a decoding, and its caller argument.
+ */
+ OSSL_DECODER_CONSTRUCT *construct;
+ OSSL_DECODER_CLEANUP *cleanup;
+ void *construct_data;
+
+ /* For any function that needs a passphrase reader */
+ struct ossl_passphrase_data_st pwdata;
+};
+
+const OSSL_PROPERTY_LIST *
+ossl_decoder_parsed_properties(const OSSL_DECODER *decoder);
+const OSSL_PROPERTY_LIST *
+ossl_encoder_parsed_properties(const OSSL_ENCODER *encoder);
diff --git a/crypto/encode_decode/encoder_meth.c b/crypto/encode_decode/encoder_meth.c
new file mode 100644
index 000000000000..89e7b6abf855
--- /dev/null
+++ b/crypto/encode_decode/encoder_meth.c
@@ -0,0 +1,700 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/encoder.h>
+#include <openssl/ui.h>
+#include "internal/core.h"
+#include "internal/namemap.h"
+#include "internal/property.h"
+#include "internal/provider.h"
+#include "crypto/encoder.h"
+#include "encoder_local.h"
+
+/*
+ * Encoder can have multiple names, separated with colons in a name string
+ */
+#define NAME_SEPARATOR ':'
+
+/* Simple method structure constructor and destructor */
+static OSSL_ENCODER *ossl_encoder_new(void)
+{
+ OSSL_ENCODER *encoder = NULL;
+
+ if ((encoder = OPENSSL_zalloc(sizeof(*encoder))) == NULL
+ || (encoder->base.lock = CRYPTO_THREAD_lock_new()) == NULL) {
+ OSSL_ENCODER_free(encoder);
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ encoder->base.refcnt = 1;
+
+ return encoder;
+}
+
+int OSSL_ENCODER_up_ref(OSSL_ENCODER *encoder)
+{
+ int ref = 0;
+
+ CRYPTO_UP_REF(&encoder->base.refcnt, &ref, encoder->base.lock);
+ return 1;
+}
+
+void OSSL_ENCODER_free(OSSL_ENCODER *encoder)
+{
+ int ref = 0;
+
+ if (encoder == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&encoder->base.refcnt, &ref, encoder->base.lock);
+ if (ref > 0)
+ return;
+ OPENSSL_free(encoder->base.name);
+ ossl_property_free(encoder->base.parsed_propdef);
+ ossl_provider_free(encoder->base.prov);
+ CRYPTO_THREAD_lock_free(encoder->base.lock);
+ OPENSSL_free(encoder);
+}
+
+/* Permanent encoder method store, constructor and destructor */
+static void encoder_store_free(void *vstore)
+{
+ ossl_method_store_free(vstore);
+}
+
+static void *encoder_store_new(OSSL_LIB_CTX *ctx)
+{
+ return ossl_method_store_new(ctx);
+}
+
+
+static const OSSL_LIB_CTX_METHOD encoder_store_method = {
+ /* We want encoder_store to be cleaned up before the provider store */
+ OSSL_LIB_CTX_METHOD_PRIORITY_2,
+ encoder_store_new,
+ encoder_store_free,
+};
+
+/* Data to be passed through ossl_method_construct() */
+struct encoder_data_st {
+ OSSL_LIB_CTX *libctx;
+ int id; /* For get_encoder_from_store() */
+ const char *names; /* For get_encoder_from_store() */
+ const char *propquery; /* For get_encoder_from_store() */
+
+ OSSL_METHOD_STORE *tmp_store; /* For get_tmp_encoder_store() */
+
+ unsigned int flag_construct_error_occurred : 1;
+};
+
+/*
+ * Generic routines to fetch / create ENCODER methods with
+ * ossl_method_construct()
+ */
+
+/* Temporary encoder method store, constructor and destructor */
+static void *get_tmp_encoder_store(void *data)
+{
+ struct encoder_data_st *methdata = data;
+
+ if (methdata->tmp_store == NULL)
+ methdata->tmp_store = ossl_method_store_new(methdata->libctx);
+ return methdata->tmp_store;
+}
+
+static void dealloc_tmp_encoder_store(void *store)
+{
+ if (store != NULL)
+ ossl_method_store_free(store);
+}
+
+/* Get the permanent encoder store */
+static OSSL_METHOD_STORE *get_encoder_store(OSSL_LIB_CTX *libctx)
+{
+ return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_ENCODER_STORE_INDEX,
+ &encoder_store_method);
+}
+
+static int reserve_encoder_store(void *store, void *data)
+{
+ struct encoder_data_st *methdata = data;
+
+ if (store == NULL
+ && (store = get_encoder_store(methdata->libctx)) == NULL)
+ return 0;
+
+ return ossl_method_lock_store(store);
+}
+
+static int unreserve_encoder_store(void *store, void *data)
+{
+ struct encoder_data_st *methdata = data;
+
+ if (store == NULL
+ && (store = get_encoder_store(methdata->libctx)) == NULL)
+ return 0;
+
+ return ossl_method_unlock_store(store);
+}
+
+/* Get encoder methods from a store, or put one in */
+static void *get_encoder_from_store(void *store, const OSSL_PROVIDER **prov,
+ void *data)
+{
+ struct encoder_data_st *methdata = data;
+ void *method = NULL;
+ int id;
+
+ /*
+ * get_encoder_from_store() is only called to try and get the method
+ * that OSSL_ENCODER_fetch() is asking for, and the name or name id are
+ * passed via methdata.
+ */
+ if ((id = methdata->id) == 0 && methdata->names != NULL) {
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
+ const char *names = methdata->names;
+ const char *q = strchr(names, NAME_SEPARATOR);
+ size_t l = (q == NULL ? strlen(names) : (size_t)(q - names));
+
+ if (namemap == 0)
+ return NULL;
+ id = ossl_namemap_name2num_n(namemap, methdata->names, l);
+ }
+
+ if (id == 0)
+ return NULL;
+
+ if (store == NULL
+ && (store = get_encoder_store(methdata->libctx)) == NULL)
+ return NULL;
+
+ if (!ossl_method_store_fetch(store, id, methdata->propquery, prov, &method))
+ return NULL;
+ return method;
+}
+
+static int put_encoder_in_store(void *store, void *method,
+ const OSSL_PROVIDER *prov,
+ const char *names, const char *propdef,
+ void *data)
+{
+ struct encoder_data_st *methdata = data;
+ OSSL_NAMEMAP *namemap;
+ int id;
+ size_t l = 0;
+
+ /*
+ * put_encoder_in_store() is only called with an OSSL_ENCODER method that
+ * was successfully created by construct_encoder() below, which means that
+ * all the names should already be stored in the namemap with the same
+ * numeric identity, so just use the first to get that identity.
+ */
+ if (names != NULL) {
+ const char *q = strchr(names, NAME_SEPARATOR);
+
+ l = (q == NULL ? strlen(names) : (size_t)(q - names));
+ }
+
+ if ((namemap = ossl_namemap_stored(methdata->libctx)) == NULL
+ || (id = ossl_namemap_name2num_n(namemap, names, l)) == 0)
+ return 0;
+
+ if (store == NULL && (store = get_encoder_store(methdata->libctx)) == NULL)
+ return 0;
+
+ return ossl_method_store_add(store, prov, id, propdef, method,
+ (int (*)(void *))OSSL_ENCODER_up_ref,
+ (void (*)(void *))OSSL_ENCODER_free);
+}
+
+/* Create and populate a encoder method */
+static void *encoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
+{
+ OSSL_ENCODER *encoder = NULL;
+ const OSSL_DISPATCH *fns = algodef->implementation;
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
+
+ if ((encoder = ossl_encoder_new()) == NULL)
+ return NULL;
+ encoder->base.id = id;
+ if ((encoder->base.name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
+ OSSL_ENCODER_free(encoder);
+ return NULL;
+ }
+ encoder->base.algodef = algodef;
+ if ((encoder->base.parsed_propdef
+ = ossl_parse_property(libctx, algodef->property_definition)) == NULL) {
+ OSSL_ENCODER_free(encoder);
+ return NULL;
+ }
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_ENCODER_NEWCTX:
+ if (encoder->newctx == NULL)
+ encoder->newctx =
+ OSSL_FUNC_encoder_newctx(fns);
+ break;
+ case OSSL_FUNC_ENCODER_FREECTX:
+ if (encoder->freectx == NULL)
+ encoder->freectx =
+ OSSL_FUNC_encoder_freectx(fns);
+ break;
+ case OSSL_FUNC_ENCODER_GET_PARAMS:
+ if (encoder->get_params == NULL)
+ encoder->get_params =
+ OSSL_FUNC_encoder_get_params(fns);
+ break;
+ case OSSL_FUNC_ENCODER_GETTABLE_PARAMS:
+ if (encoder->gettable_params == NULL)
+ encoder->gettable_params =
+ OSSL_FUNC_encoder_gettable_params(fns);
+ break;
+ case OSSL_FUNC_ENCODER_SET_CTX_PARAMS:
+ if (encoder->set_ctx_params == NULL)
+ encoder->set_ctx_params =
+ OSSL_FUNC_encoder_set_ctx_params(fns);
+ break;
+ case OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS:
+ if (encoder->settable_ctx_params == NULL)
+ encoder->settable_ctx_params =
+ OSSL_FUNC_encoder_settable_ctx_params(fns);
+ break;
+ case OSSL_FUNC_ENCODER_DOES_SELECTION:
+ if (encoder->does_selection == NULL)
+ encoder->does_selection =
+ OSSL_FUNC_encoder_does_selection(fns);
+ break;
+ case OSSL_FUNC_ENCODER_ENCODE:
+ if (encoder->encode == NULL)
+ encoder->encode = OSSL_FUNC_encoder_encode(fns);
+ break;
+ case OSSL_FUNC_ENCODER_IMPORT_OBJECT:
+ if (encoder->import_object == NULL)
+ encoder->import_object =
+ OSSL_FUNC_encoder_import_object(fns);
+ break;
+ case OSSL_FUNC_ENCODER_FREE_OBJECT:
+ if (encoder->free_object == NULL)
+ encoder->free_object =
+ OSSL_FUNC_encoder_free_object(fns);
+ break;
+ }
+ }
+ /*
+ * Try to check that the method is sensible.
+ * If you have a constructor, you must have a destructor and vice versa.
+ * You must have the encoding driver functions.
+ */
+ if (!((encoder->newctx == NULL && encoder->freectx == NULL)
+ || (encoder->newctx != NULL && encoder->freectx != NULL)
+ || (encoder->import_object != NULL && encoder->free_object != NULL)
+ || (encoder->import_object == NULL && encoder->free_object == NULL))
+ || encoder->encode == NULL) {
+ OSSL_ENCODER_free(encoder);
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INVALID_PROVIDER_FUNCTIONS);
+ return NULL;
+ }
+
+ if (prov != NULL && !ossl_provider_up_ref(prov)) {
+ OSSL_ENCODER_free(encoder);
+ return NULL;
+ }
+
+ encoder->base.prov = prov;
+ return encoder;
+}
+
+
+/*
+ * The core fetching functionality passes the names of the implementation.
+ * This function is responsible to getting an identity number for them,
+ * then call encoder_from_algorithm() with that identity number.
+ */
+static void *construct_encoder(const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov, void *data)
+{
+ /*
+ * This function is only called if get_encoder_from_store() returned
+ * NULL, so it's safe to say that of all the spots to create a new
+ * namemap entry, this is it. Should the name already exist there, we
+ * know that ossl_namemap_add() will return its corresponding number.
+ */
+ struct encoder_data_st *methdata = data;
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+ const char *names = algodef->algorithm_names;
+ int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR);
+ void *method = NULL;
+
+ if (id != 0)
+ method = encoder_from_algorithm(id, algodef, prov);
+
+ /*
+ * Flag to indicate that there was actual construction errors. This
+ * helps inner_evp_generic_fetch() determine what error it should
+ * record on inaccessible algorithms.
+ */
+ if (method == NULL)
+ methdata->flag_construct_error_occurred = 1;
+
+ return method;
+}
+
+/* Intermediary function to avoid ugly casts, used below */
+static void destruct_encoder(void *method, void *data)
+{
+ OSSL_ENCODER_free(method);
+}
+
+static int up_ref_encoder(void *method)
+{
+ return OSSL_ENCODER_up_ref(method);
+}
+
+static void free_encoder(void *method)
+{
+ OSSL_ENCODER_free(method);
+}
+
+/* Fetching support. Can fetch by numeric identity or by name */
+static OSSL_ENCODER *
+inner_ossl_encoder_fetch(struct encoder_data_st *methdata, int id,
+ const char *name, const char *properties)
+{
+ OSSL_METHOD_STORE *store = get_encoder_store(methdata->libctx);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
+ const char *const propq = properties != NULL ? properties : "";
+ void *method = NULL;
+ int unsupported = 0;
+
+ if (store == NULL || namemap == NULL) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_INVALID_ARGUMENT);
+ return NULL;
+ }
+
+ /*
+ * If we have been passed both an id and a name, we have an
+ * internal programming error.
+ */
+ if (!ossl_assert(id == 0 || name == NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ if (id == 0)
+ id = ossl_namemap_name2num(namemap, name);
+
+ /*
+ * If we haven't found the name yet, chances are that the algorithm to
+ * be fetched is unsupported.
+ */
+ if (id == 0)
+ unsupported = 1;
+
+ if (id == 0
+ || !ossl_method_store_cache_get(store, NULL, id, propq, &method)) {
+ OSSL_METHOD_CONSTRUCT_METHOD mcm = {
+ get_tmp_encoder_store,
+ reserve_encoder_store,
+ unreserve_encoder_store,
+ get_encoder_from_store,
+ put_encoder_in_store,
+ construct_encoder,
+ destruct_encoder
+ };
+ OSSL_PROVIDER *prov = NULL;
+
+ methdata->id = id;
+ methdata->names = name;
+ methdata->propquery = propq;
+ methdata->flag_construct_error_occurred = 0;
+ if ((method = ossl_method_construct(methdata->libctx, OSSL_OP_ENCODER,
+ &prov, 0 /* !force_cache */,
+ &mcm, methdata)) != NULL) {
+ /*
+ * If construction did create a method for us, we know that
+ * there is a correct name_id and meth_id, since those have
+ * already been calculated in get_encoder_from_store() and
+ * put_encoder_in_store() above.
+ */
+ if (id == 0)
+ id = ossl_namemap_name2num(namemap, name);
+ ossl_method_store_cache_set(store, prov, id, propq, method,
+ up_ref_encoder, free_encoder);
+ }
+
+ /*
+ * If we never were in the constructor, the algorithm to be fetched
+ * is unsupported.
+ */
+ unsupported = !methdata->flag_construct_error_occurred;
+ }
+
+ if ((id != 0 || name != NULL) && method == NULL) {
+ int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED;
+
+ if (name == NULL)
+ name = ossl_namemap_num2name(namemap, id, 0);
+ ERR_raise_data(ERR_LIB_OSSL_ENCODER, code,
+ "%s, Name (%s : %d), Properties (%s)",
+ ossl_lib_ctx_get_descriptor(methdata->libctx),
+ name == NULL ? "<null>" : name, id,
+ properties == NULL ? "<null>" : properties);
+ }
+
+ return method;
+}
+
+OSSL_ENCODER *OSSL_ENCODER_fetch(OSSL_LIB_CTX *libctx, const char *name,
+ const char *properties)
+{
+ struct encoder_data_st methdata;
+ void *method;
+
+ methdata.libctx = libctx;
+ methdata.tmp_store = NULL;
+ method = inner_ossl_encoder_fetch(&methdata, 0, name, properties);
+ dealloc_tmp_encoder_store(methdata.tmp_store);
+ return method;
+}
+
+OSSL_ENCODER *ossl_encoder_fetch_by_number(OSSL_LIB_CTX *libctx, int id,
+ const char *properties)
+{
+ struct encoder_data_st methdata;
+ void *method;
+
+ methdata.libctx = libctx;
+ methdata.tmp_store = NULL;
+ method = inner_ossl_encoder_fetch(&methdata, id, NULL, properties);
+ dealloc_tmp_encoder_store(methdata.tmp_store);
+ return method;
+}
+
+int ossl_encoder_store_cache_flush(OSSL_LIB_CTX *libctx)
+{
+ OSSL_METHOD_STORE *store = get_encoder_store(libctx);
+
+ if (store != NULL)
+ return ossl_method_store_cache_flush_all(store);
+ return 1;
+}
+
+int ossl_encoder_store_remove_all_provided(const OSSL_PROVIDER *prov)
+{
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
+ OSSL_METHOD_STORE *store = get_encoder_store(libctx);
+
+ if (store != NULL)
+ return ossl_method_store_remove_all_provided(store, prov);
+ return 1;
+}
+
+/*
+ * Library of basic method functions
+ */
+
+const OSSL_PROVIDER *OSSL_ENCODER_get0_provider(const OSSL_ENCODER *encoder)
+{
+ if (!ossl_assert(encoder != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ return encoder->base.prov;
+}
+
+const char *OSSL_ENCODER_get0_properties(const OSSL_ENCODER *encoder)
+{
+ if (!ossl_assert(encoder != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ return encoder->base.algodef->property_definition;
+}
+
+const OSSL_PROPERTY_LIST *
+ossl_encoder_parsed_properties(const OSSL_ENCODER *encoder)
+{
+ if (!ossl_assert(encoder != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ return encoder->base.parsed_propdef;
+}
+
+int ossl_encoder_get_number(const OSSL_ENCODER *encoder)
+{
+ if (!ossl_assert(encoder != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ return encoder->base.id;
+}
+
+const char *OSSL_ENCODER_get0_name(const OSSL_ENCODER *encoder)
+{
+ return encoder->base.name;
+}
+
+const char *OSSL_ENCODER_get0_description(const OSSL_ENCODER *encoder)
+{
+ return encoder->base.algodef->algorithm_description;
+}
+
+int OSSL_ENCODER_is_a(const OSSL_ENCODER *encoder, const char *name)
+{
+ if (encoder->base.prov != NULL) {
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(encoder->base.prov);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+
+ return ossl_namemap_name2num(namemap, name) == encoder->base.id;
+ }
+ return 0;
+}
+
+struct do_one_data_st {
+ void (*user_fn)(OSSL_ENCODER *encoder, void *arg);
+ void *user_arg;
+};
+
+static void do_one(ossl_unused int id, void *method, void *arg)
+{
+ struct do_one_data_st *data = arg;
+
+ data->user_fn(method, data->user_arg);
+}
+
+void OSSL_ENCODER_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*user_fn)(OSSL_ENCODER *encoder,
+ void *arg),
+ void *user_arg)
+{
+ struct encoder_data_st methdata;
+ struct do_one_data_st data;
+
+ methdata.libctx = libctx;
+ methdata.tmp_store = NULL;
+ (void)inner_ossl_encoder_fetch(&methdata, 0, NULL, NULL /* properties */);
+
+ data.user_fn = user_fn;
+ data.user_arg = user_arg;
+ if (methdata.tmp_store != NULL)
+ ossl_method_store_do_all(methdata.tmp_store, &do_one, &data);
+ ossl_method_store_do_all(get_encoder_store(libctx), &do_one, &data);
+ dealloc_tmp_encoder_store(methdata.tmp_store);
+}
+
+int OSSL_ENCODER_names_do_all(const OSSL_ENCODER *encoder,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (encoder == NULL)
+ return 0;
+
+ if (encoder->base.prov != NULL) {
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(encoder->base.prov);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+
+ return ossl_namemap_doall_names(namemap, encoder->base.id, fn, data);
+ }
+
+ return 1;
+}
+
+const OSSL_PARAM *
+OSSL_ENCODER_gettable_params(OSSL_ENCODER *encoder)
+{
+ if (encoder != NULL && encoder->gettable_params != NULL) {
+ void *provctx = ossl_provider_ctx(OSSL_ENCODER_get0_provider(encoder));
+
+ return encoder->gettable_params(provctx);
+ }
+ return NULL;
+}
+
+int OSSL_ENCODER_get_params(OSSL_ENCODER *encoder, OSSL_PARAM params[])
+{
+ if (encoder != NULL && encoder->get_params != NULL)
+ return encoder->get_params(params);
+ return 0;
+}
+
+const OSSL_PARAM *OSSL_ENCODER_settable_ctx_params(OSSL_ENCODER *encoder)
+{
+ if (encoder != NULL && encoder->settable_ctx_params != NULL) {
+ void *provctx = ossl_provider_ctx(OSSL_ENCODER_get0_provider(encoder));
+
+ return encoder->settable_ctx_params(provctx);
+ }
+ return NULL;
+}
+
+/*
+ * Encoder context support
+ */
+
+OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new(void)
+{
+ OSSL_ENCODER_CTX *ctx;
+
+ if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL)
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
+
+ return ctx;
+}
+
+int OSSL_ENCODER_CTX_set_params(OSSL_ENCODER_CTX *ctx,
+ const OSSL_PARAM params[])
+{
+ int ok = 1;
+ size_t i;
+ size_t l;
+
+ if (!ossl_assert(ctx != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (ctx->encoder_insts == NULL)
+ return 1;
+
+ l = OSSL_ENCODER_CTX_get_num_encoders(ctx);
+ for (i = 0; i < l; i++) {
+ OSSL_ENCODER_INSTANCE *encoder_inst =
+ sk_OSSL_ENCODER_INSTANCE_value(ctx->encoder_insts, i);
+ OSSL_ENCODER *encoder = OSSL_ENCODER_INSTANCE_get_encoder(encoder_inst);
+ void *encoderctx = OSSL_ENCODER_INSTANCE_get_encoder_ctx(encoder_inst);
+
+ if (encoderctx == NULL || encoder->set_ctx_params == NULL)
+ continue;
+ if (!encoder->set_ctx_params(encoderctx, params))
+ ok = 0;
+ }
+ return ok;
+}
+
+void OSSL_ENCODER_CTX_free(OSSL_ENCODER_CTX *ctx)
+{
+ if (ctx != NULL) {
+ sk_OSSL_ENCODER_INSTANCE_pop_free(ctx->encoder_insts,
+ ossl_encoder_instance_free);
+ OPENSSL_free(ctx->construct_data);
+ ossl_pw_clear_passphrase_data(&ctx->pwdata);
+ OPENSSL_free(ctx);
+ }
+}
diff --git a/crypto/encode_decode/encoder_pkey.c b/crypto/encode_decode/encoder_pkey.c
new file mode 100644
index 000000000000..3a24317cf4d6
--- /dev/null
+++ b/crypto/encode_decode/encoder_pkey.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/ui.h>
+#include <openssl/params.h>
+#include <openssl/encoder.h>
+#include <openssl/core_names.h>
+#include <openssl/provider.h>
+#include <openssl/safestack.h>
+#include <openssl/trace.h>
+#include "internal/provider.h"
+#include "internal/property.h"
+#include "crypto/evp.h"
+#include "encoder_local.h"
+
+DEFINE_STACK_OF(OSSL_ENCODER)
+
+int OSSL_ENCODER_CTX_set_cipher(OSSL_ENCODER_CTX *ctx,
+ const char *cipher_name,
+ const char *propquery)
+{
+ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] =
+ OSSL_PARAM_construct_utf8_string(OSSL_ENCODER_PARAM_CIPHER,
+ (void *)cipher_name, 0);
+ params[1] =
+ OSSL_PARAM_construct_utf8_string(OSSL_ENCODER_PARAM_PROPERTIES,
+ (void *)propquery, 0);
+
+ return OSSL_ENCODER_CTX_set_params(ctx, params);
+}
+
+int OSSL_ENCODER_CTX_set_passphrase(OSSL_ENCODER_CTX *ctx,
+ const unsigned char *kstr,
+ size_t klen)
+{
+ return ossl_pw_set_passphrase(&ctx->pwdata, kstr, klen);
+}
+
+int OSSL_ENCODER_CTX_set_passphrase_ui(OSSL_ENCODER_CTX *ctx,
+ const UI_METHOD *ui_method,
+ void *ui_data)
+{
+ return ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data);
+}
+
+int OSSL_ENCODER_CTX_set_pem_password_cb(OSSL_ENCODER_CTX *ctx,
+ pem_password_cb *cb, void *cbarg)
+{
+ return ossl_pw_set_pem_password_cb(&ctx->pwdata, cb, cbarg);
+}
+
+int OSSL_ENCODER_CTX_set_passphrase_cb(OSSL_ENCODER_CTX *ctx,
+ OSSL_PASSPHRASE_CALLBACK *cb,
+ void *cbarg)
+{
+ return ossl_pw_set_ossl_passphrase_cb(&ctx->pwdata, cb, cbarg);
+}
+
+/*
+ * Support for OSSL_ENCODER_CTX_new_for_type:
+ * finding a suitable encoder
+ */
+
+struct collected_encoder_st {
+ STACK_OF(OPENSSL_CSTRING) *names;
+ const char *output_structure;
+ const char *output_type;
+
+ const OSSL_PROVIDER *keymgmt_prov;
+ OSSL_ENCODER_CTX *ctx;
+ unsigned int flag_find_same_provider:1;
+
+ int error_occurred;
+};
+
+static void collect_encoder(OSSL_ENCODER *encoder, void *arg)
+{
+ struct collected_encoder_st *data = arg;
+ size_t i, end_i;
+
+ if (data->error_occurred)
+ return;
+
+ data->error_occurred = 1; /* Assume the worst */
+
+ if (data->names == NULL)
+ return;
+
+ end_i = sk_OPENSSL_CSTRING_num(data->names);
+ for (i = 0; i < end_i; i++) {
+ const char *name = sk_OPENSSL_CSTRING_value(data->names, i);
+ const OSSL_PROVIDER *prov = OSSL_ENCODER_get0_provider(encoder);
+ void *provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
+
+ /*
+ * collect_encoder() is called in two passes, one where the encoders
+ * from the same provider as the keymgmt are looked up, and one where
+ * the other encoders are looked up. |data->flag_find_same_provider|
+ * tells us which pass we're in.
+ */
+ if ((data->keymgmt_prov == prov) != data->flag_find_same_provider)
+ continue;
+
+ if (!OSSL_ENCODER_is_a(encoder, name)
+ || (encoder->does_selection != NULL
+ && !encoder->does_selection(provctx, data->ctx->selection))
+ || (data->keymgmt_prov != prov
+ && encoder->import_object == NULL))
+ continue;
+
+ /* Only add each encoder implementation once */
+ if (OSSL_ENCODER_CTX_add_encoder(data->ctx, encoder))
+ break;
+ }
+
+ data->error_occurred = 0; /* All is good now */
+}
+
+struct collected_names_st {
+ STACK_OF(OPENSSL_CSTRING) *names;
+ unsigned int error_occurred:1;
+};
+
+static void collect_name(const char *name, void *arg)
+{
+ struct collected_names_st *data = arg;
+
+ if (data->error_occurred)
+ return;
+
+ data->error_occurred = 1; /* Assume the worst */
+
+ if (sk_OPENSSL_CSTRING_push(data->names, name) <= 0)
+ return;
+
+ data->error_occurred = 0; /* All is good now */
+}
+
+/*
+ * Support for OSSL_ENCODER_to_bio:
+ * writing callback for the OSSL_PARAM (the implementation doesn't have
+ * intimate knowledge of the provider side object)
+ */
+
+struct construct_data_st {
+ const EVP_PKEY *pk;
+ int selection;
+
+ OSSL_ENCODER_INSTANCE *encoder_inst;
+ const void *obj;
+ void *constructed_obj;
+};
+
+static int encoder_import_cb(const OSSL_PARAM params[], void *arg)
+{
+ struct construct_data_st *construct_data = arg;
+ OSSL_ENCODER_INSTANCE *encoder_inst = construct_data->encoder_inst;
+ OSSL_ENCODER *encoder = OSSL_ENCODER_INSTANCE_get_encoder(encoder_inst);
+ void *encoderctx = OSSL_ENCODER_INSTANCE_get_encoder_ctx(encoder_inst);
+
+ construct_data->constructed_obj =
+ encoder->import_object(encoderctx, construct_data->selection, params);
+
+ return (construct_data->constructed_obj != NULL);
+}
+
+static const void *
+encoder_construct_pkey(OSSL_ENCODER_INSTANCE *encoder_inst, void *arg)
+{
+ struct construct_data_st *data = arg;
+
+ if (data->obj == NULL) {
+ OSSL_ENCODER *encoder =
+ OSSL_ENCODER_INSTANCE_get_encoder(encoder_inst);
+ const EVP_PKEY *pk = data->pk;
+ const OSSL_PROVIDER *k_prov = EVP_KEYMGMT_get0_provider(pk->keymgmt);
+ const OSSL_PROVIDER *e_prov = OSSL_ENCODER_get0_provider(encoder);
+
+ if (k_prov != e_prov) {
+ data->encoder_inst = encoder_inst;
+
+ if (!evp_keymgmt_export(pk->keymgmt, pk->keydata, data->selection,
+ &encoder_import_cb, data))
+ return NULL;
+ data->obj = data->constructed_obj;
+ } else {
+ data->obj = pk->keydata;
+ }
+ }
+
+ return data->obj;
+}
+
+static void encoder_destruct_pkey(void *arg)
+{
+ struct construct_data_st *data = arg;
+
+ if (data->encoder_inst != NULL) {
+ OSSL_ENCODER *encoder =
+ OSSL_ENCODER_INSTANCE_get_encoder(data->encoder_inst);
+
+ encoder->free_object(data->constructed_obj);
+ }
+ data->constructed_obj = NULL;
+}
+
+/*
+ * OSSL_ENCODER_CTX_new_for_pkey() returns a ctx with no encoder if
+ * it couldn't find a suitable encoder. This allows a caller to detect if
+ * a suitable encoder was found, with OSSL_ENCODER_CTX_get_num_encoder(),
+ * and to use fallback methods if the result is NULL.
+ */
+static int ossl_encoder_ctx_setup_for_pkey(OSSL_ENCODER_CTX *ctx,
+ const EVP_PKEY *pkey,
+ int selection,
+ const char *propquery)
+{
+ struct construct_data_st *data = NULL;
+ const OSSL_PROVIDER *prov = NULL;
+ OSSL_LIB_CTX *libctx = NULL;
+ int ok = 0;
+
+ if (!ossl_assert(ctx != NULL) || !ossl_assert(pkey != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (evp_pkey_is_provided(pkey)) {
+ prov = EVP_KEYMGMT_get0_provider(pkey->keymgmt);
+ libctx = ossl_provider_libctx(prov);
+ }
+
+ if (pkey->keymgmt != NULL) {
+ struct collected_encoder_st encoder_data;
+ struct collected_names_st keymgmt_data;
+
+ if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /*
+ * Select the first encoder implementations in two steps.
+ * First, collect the keymgmt names, then the encoders that match.
+ */
+ keymgmt_data.names = sk_OPENSSL_CSTRING_new_null();
+ if (keymgmt_data.names == NULL) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ keymgmt_data.error_occurred = 0;
+ EVP_KEYMGMT_names_do_all(pkey->keymgmt, collect_name, &keymgmt_data);
+ if (keymgmt_data.error_occurred) {
+ sk_OPENSSL_CSTRING_free(keymgmt_data.names);
+ goto err;
+ }
+
+ encoder_data.names = keymgmt_data.names;
+ encoder_data.output_type = ctx->output_type;
+ encoder_data.output_structure = ctx->output_structure;
+ encoder_data.error_occurred = 0;
+ encoder_data.keymgmt_prov = prov;
+ encoder_data.ctx = ctx;
+
+ /*
+ * Place the encoders with the a different provider as the keymgmt
+ * last (the chain is processed in reverse order)
+ */
+ encoder_data.flag_find_same_provider = 0;
+ OSSL_ENCODER_do_all_provided(libctx, collect_encoder, &encoder_data);
+
+ /*
+ * Place the encoders with the same provider as the keymgmt first
+ * (the chain is processed in reverse order)
+ */
+ encoder_data.flag_find_same_provider = 1;
+ OSSL_ENCODER_do_all_provided(libctx, collect_encoder, &encoder_data);
+
+ sk_OPENSSL_CSTRING_free(keymgmt_data.names);
+ if (encoder_data.error_occurred) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (data != NULL && OSSL_ENCODER_CTX_get_num_encoders(ctx) != 0) {
+ if (!OSSL_ENCODER_CTX_set_construct(ctx, encoder_construct_pkey)
+ || !OSSL_ENCODER_CTX_set_construct_data(ctx, data)
+ || !OSSL_ENCODER_CTX_set_cleanup(ctx, encoder_destruct_pkey))
+ goto err;
+
+ data->pk = pkey;
+ data->selection = selection;
+
+ data = NULL; /* Avoid it being freed */
+ }
+
+ ok = 1;
+ err:
+ if (data != NULL) {
+ OSSL_ENCODER_CTX_set_construct_data(ctx, NULL);
+ OPENSSL_free(data);
+ }
+ return ok;
+}
+
+OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new_for_pkey(const EVP_PKEY *pkey,
+ int selection,
+ const char *output_type,
+ const char *output_struct,
+ const char *propquery)
+{
+ OSSL_ENCODER_CTX *ctx = NULL;
+ OSSL_LIB_CTX *libctx = NULL;
+
+ if (pkey == NULL) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+
+ if (!evp_pkey_is_assigned(pkey)) {
+ ERR_raise_data(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_INVALID_ARGUMENT,
+ "The passed EVP_PKEY must be assigned a key");
+ return NULL;
+ }
+
+ if ((ctx = OSSL_ENCODER_CTX_new()) == NULL) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (evp_pkey_is_provided(pkey)) {
+ const OSSL_PROVIDER *prov = EVP_KEYMGMT_get0_provider(pkey->keymgmt);
+
+ libctx = ossl_provider_libctx(prov);
+ }
+
+ OSSL_TRACE_BEGIN(ENCODER) {
+ BIO_printf(trc_out,
+ "(ctx %p) Looking for %s encoders with selection %d\n",
+ (void *)ctx, EVP_PKEY_get0_type_name(pkey), selection);
+ BIO_printf(trc_out, " output type: %s, output structure: %s\n",
+ output_type, output_struct);
+ } OSSL_TRACE_END(ENCODER);
+
+ if (OSSL_ENCODER_CTX_set_output_type(ctx, output_type)
+ && (output_struct == NULL
+ || OSSL_ENCODER_CTX_set_output_structure(ctx, output_struct))
+ && OSSL_ENCODER_CTX_set_selection(ctx, selection)
+ && ossl_encoder_ctx_setup_for_pkey(ctx, pkey, selection, propquery)
+ && OSSL_ENCODER_CTX_add_extra(ctx, libctx, propquery)) {
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ int save_parameters = pkey->save_parameters;
+
+ params[0] = OSSL_PARAM_construct_int(OSSL_ENCODER_PARAM_SAVE_PARAMETERS,
+ &save_parameters);
+ /* ignoring error as this is only auxiliary parameter */
+ (void)OSSL_ENCODER_CTX_set_params(ctx, params);
+
+ OSSL_TRACE_BEGIN(ENCODER) {
+ BIO_printf(trc_out, "(ctx %p) Got %d encoders\n",
+ (void *)ctx, OSSL_ENCODER_CTX_get_num_encoders(ctx));
+ } OSSL_TRACE_END(ENCODER);
+ return ctx;
+ }
+
+ OSSL_ENCODER_CTX_free(ctx);
+ return NULL;
+}
diff --git a/crypto/engine/README b/crypto/engine/README
deleted file mode 100644
index 0f8a8fbde410..000000000000
--- a/crypto/engine/README
+++ /dev/null
@@ -1,211 +0,0 @@
-Notes: 2001-09-24
------------------
-
-This "description" (if one chooses to call it that) needed some major updating
-so here goes. This update addresses a change being made at the same time to
-OpenSSL, and it pretty much completely restructures the underlying mechanics of
-the "ENGINE" code. So it serves a double purpose of being a "ENGINE internals
-for masochists" document *and* a rather extensive commit log message. (I'd get
-lynched for sticking all this in CHANGES or the commit mails :-).
-
-ENGINE_TABLE underlies this restructuring, as described in the internal header
-"eng_local.h", implemented in eng_table.c, and used in each of the "class" files;
-tb_rsa.c, tb_dsa.c, etc.
-
-However, "EVP_CIPHER" underlies the motivation and design of ENGINE_TABLE so
-I'll mention a bit about that first. EVP_CIPHER (and most of this applies
-equally to EVP_MD for digests) is both a "method" and a algorithm/mode
-identifier that, in the current API, "lingers". These cipher description +
-implementation structures can be defined or obtained directly by applications,
-or can be loaded "en masse" into EVP storage so that they can be catalogued and
-searched in various ways, ie. two ways of encrypting with the "des_cbc"
-algorithm/mode pair are;
-
-(i) directly;
- const EVP_CIPHER *cipher = EVP_des_cbc();
- EVP_EncryptInit(&ctx, cipher, key, iv);
- [ ... use EVP_EncryptUpdate() and EVP_EncryptFinal() ...]
-
-(ii) indirectly;
- OpenSSL_add_all_ciphers();
- cipher = EVP_get_cipherbyname("des_cbc");
- EVP_EncryptInit(&ctx, cipher, key, iv);
- [ ... etc ... ]
-
-The latter is more generally used because it also allows ciphers/digests to be
-looked up based on other identifiers which can be useful for automatic cipher
-selection, eg. in SSL/TLS, or by user-controllable configuration.
-
-The important point about this is that EVP_CIPHER definitions and structures are
-passed around with impunity and there is no safe way, without requiring massive
-rewrites of many applications, to assume that EVP_CIPHERs can be reference
-counted. One an EVP_CIPHER is exposed to the caller, neither it nor anything it
-comes from can "safely" be destroyed. Unless of course the way of getting to
-such ciphers is via entirely distinct API calls that didn't exist before.
-However existing API usage cannot be made to understand when an EVP_CIPHER
-pointer, that has been passed to the caller, is no longer being used.
-
-The other problem with the existing API w.r.t. to hooking EVP_CIPHER support
-into ENGINE is storage - the OBJ_NAME-based storage used by EVP to register
-ciphers simultaneously registers cipher *types* and cipher *implementations* -
-they are effectively the same thing, an "EVP_CIPHER" pointer. The problem with
-hooking in ENGINEs is that multiple ENGINEs may implement the same ciphers. The
-solution is necessarily that ENGINE-provided ciphers simply are not registered,
-stored, or exposed to the caller in the same manner as existing ciphers. This is
-especially necessary considering the fact ENGINE uses reference counts to allow
-for cleanup, modularity, and DSO support - yet EVP_CIPHERs, as exposed to
-callers in the current API, support no such controls.
-
-Another sticking point for integrating cipher support into ENGINE is linkage.
-Already there is a problem with the way ENGINE supports RSA, DSA, etc whereby
-they are available *because* they're part of a giant ENGINE called "openssl".
-Ie. all implementations *have* to come from an ENGINE, but we get round that by
-having a giant ENGINE with all the software support encapsulated. This creates
-linker hassles if nothing else - linking a 1-line application that calls 2 basic
-RSA functions (eg. "RSA_free(RSA_new());") will result in large quantities of
-ENGINE code being linked in *and* because of that DSA, DH, and RAND also. If we
-continue with this approach for EVP_CIPHER support (even if it *was* possible)
-we would lose our ability to link selectively by selectively loading certain
-implementations of certain functionality. Touching any part of any kind of
-crypto would result in massive static linkage of everything else. So the
-solution is to change the way ENGINE feeds existing "classes", ie. how the
-hooking to ENGINE works from RSA, DSA, DH, RAND, as well as adding new hooking
-for EVP_CIPHER, and EVP_MD.
-
-The way this is now being done is by mostly reverting back to how things used to
-work prior to ENGINE :-). Ie. RSA now has a "RSA_METHOD" pointer again - this
-was previously replaced by an "ENGINE" pointer and all RSA code that required
-the RSA_METHOD would call ENGINE_get_RSA() each time on its ENGINE handle to
-temporarily get and use the ENGINE's RSA implementation. Apart from being more
-efficient, switching back to each RSA having an RSA_METHOD pointer also allows
-us to conceivably operate with *no* ENGINE. As we'll see, this removes any need
-for a fallback ENGINE that encapsulates default implementations - we can simply
-have our RSA structure pointing its RSA_METHOD pointer to the software
-implementation and have its ENGINE pointer set to NULL.
-
-A look at the EVP_CIPHER hooking is most explanatory, the RSA, DSA (etc) cases
-turn out to be degenerate forms of the same thing. The EVP storage of ciphers,
-and the existing EVP API functions that return "software" implementations and
-descriptions remain untouched. However, the storage takes more meaning in terms
-of "cipher description" and less meaning in terms of "implementation". When an
-EVP_CIPHER_CTX is actually initialised with an EVP_CIPHER method and is about to
-begin en/decryption, the hooking to ENGINE comes into play. What happens is that
-cipher-specific ENGINE code is asked for an ENGINE pointer (a functional
-reference) for any ENGINE that is registered to perform the algo/mode that the
-provided EVP_CIPHER structure represents. Under normal circumstances, that
-ENGINE code will return NULL because no ENGINEs will have had any cipher
-implementations *registered*. As such, a NULL ENGINE pointer is stored in the
-EVP_CIPHER_CTX context, and the EVP_CIPHER structure is left hooked into the
-context and so is used as the implementation. Pretty much how things work now
-except we'd have a redundant ENGINE pointer set to NULL and doing nothing.
-
-Conversely, if an ENGINE *has* been registered to perform the algorithm/mode
-combination represented by the provided EVP_CIPHER, then a functional reference
-to that ENGINE will be returned to the EVP_CIPHER_CTX during initialisation.
-That functional reference will be stored in the context (and released on
-cleanup) - and having that reference provides a *safe* way to use an EVP_CIPHER
-definition that is private to the ENGINE. Ie. the EVP_CIPHER provided by the
-application will actually be replaced by an EVP_CIPHER from the registered
-ENGINE - it will support the same algorithm/mode as the original but will be a
-completely different implementation. Because this EVP_CIPHER isn't stored in the
-EVP storage, nor is it returned to applications from traditional API functions,
-there is no associated problem with it not having reference counts. And of
-course, when one of these "private" cipher implementations is hooked into
-EVP_CIPHER_CTX, it is done whilst the EVP_CIPHER_CTX holds a functional
-reference to the ENGINE that owns it, thus the use of the ENGINE's EVP_CIPHER is
-safe.
-
-The "cipher-specific ENGINE code" I mentioned is implemented in tb_cipher.c but
-in essence it is simply an instantiation of "ENGINE_TABLE" code for use by
-EVP_CIPHER code. tb_digest.c is virtually identical but, of course, it is for
-use by EVP_MD code. Ditto for tb_rsa.c, tb_dsa.c, etc. These instantiations of
-ENGINE_TABLE essentially provide linker-separation of the classes so that even
-if ENGINEs implement *all* possible algorithms, an application using only
-EVP_CIPHER code will link at most code relating to EVP_CIPHER, tb_cipher.c, core
-ENGINE code that is independent of class, and of course the ENGINE
-implementation that the application loaded. It will *not* however link any
-class-specific ENGINE code for digests, RSA, etc nor will it bleed over into
-other APIs, such as the RSA/DSA/etc library code.
-
-ENGINE_TABLE is a little more complicated than may seem necessary but this is
-mostly to avoid a lot of "init()"-thrashing on ENGINEs (that may have to load
-DSOs, and other expensive setup that shouldn't be thrashed unnecessarily) *and*
-to duplicate "default" behaviour. Basically an ENGINE_TABLE instantiation, for
-example tb_cipher.c, implements a hash-table keyed by integer "nid" values.
-These nids provide the uniquenness of an algorithm/mode - and each nid will hash
-to a potentially NULL "ENGINE_PILE". An ENGINE_PILE is essentially a list of
-pointers to ENGINEs that implement that particular 'nid'. Each "pile" uses some
-caching tricks such that requests on that 'nid' will be cached and all future
-requests will return immediately (well, at least with minimal operation) unless
-a change is made to the pile, eg. perhaps an ENGINE was unloaded. The reason is
-that an application could have support for 10 ENGINEs statically linked
-in, and the machine in question may not have any of the hardware those 10
-ENGINEs support. If each of those ENGINEs has a "des_cbc" implementation, we
-want to avoid every EVP_CIPHER_CTX setup from trying (and failing) to initialise
-each of those 10 ENGINEs. Instead, the first such request will try to do that
-and will either return (and cache) a NULL ENGINE pointer or will return a
-functional reference to the first that successfully initialised. In the latter
-case it will also cache an extra functional reference to the ENGINE as a
-"default" for that 'nid'. The caching is acknowledged by a 'uptodate' variable
-that is unset only if un/registration takes place on that pile. Ie. if
-implementations of "des_cbc" are added or removed. This behaviour can be
-tweaked; the ENGINE_TABLE_FLAG_NOINIT value can be passed to
-ENGINE_set_table_flags(), in which case the only ENGINEs that tb_cipher.c will
-try to initialise from the "pile" will be those that are already initialised
-(ie. it's simply an increment of the functional reference count, and no real
-"initialisation" will take place).
-
-RSA, DSA, DH, and RAND all have their own ENGINE_TABLE code as well, and the
-difference is that they all use an implicit 'nid' of 1. Whereas EVP_CIPHERs are
-actually qualitatively different depending on 'nid' (the "des_cbc" EVP_CIPHER is
-not an interoperable implementation of "aes_256_cbc"), RSA_METHODs are
-necessarily interoperable and don't have different flavours, only different
-implementations. In other words, the ENGINE_TABLE for RSA will either be empty,
-or will have a single ENGINE_PILE hashed to by the 'nid' 1 and that pile
-represents ENGINEs that implement the single "type" of RSA there is.
-
-Cleanup - the registration and unregistration may pose questions about how
-cleanup works with the ENGINE_PILE doing all this caching nonsense (ie. when the
-application or EVP_CIPHER code releases its last reference to an ENGINE, the
-ENGINE_PILE code may still have references and thus those ENGINEs will stay
-hooked in forever). The way this is handled is via "unregistration". With these
-new ENGINE changes, an abstract ENGINE can be loaded and initialised, but that
-is an algorithm-agnostic process. Even if initialised, it will not have
-registered any of its implementations (to do so would link all class "table"
-code despite the fact the application may use only ciphers, for example). This
-is deliberately a distinct step. Moreover, registration and unregistration has
-nothing to do with whether an ENGINE is *functional* or not (ie. you can even
-register an ENGINE and its implementations without it being operational, you may
-not even have the drivers to make it operate). What actually happens with
-respect to cleanup is managed inside eng_lib.c with the "engine_cleanup_***"
-functions. These functions are internal-only and each part of ENGINE code that
-could require cleanup will, upon performing its first allocation, register a
-callback with the "engine_cleanup" code. The other part of this that makes it
-tick is that the ENGINE_TABLE instantiations (tb_***.c) use NULL as their
-initialised state. So if RSA code asks for an ENGINE and no ENGINE has
-registered an implementation, the code will simply return NULL and the tb_rsa.c
-state will be unchanged. Thus, no cleanup is required unless registration takes
-place. ENGINE_cleanup() will simply iterate across a list of registered cleanup
-callbacks calling each in turn, and will then internally delete its own storage
-(a STACK). When a cleanup callback is next registered (eg. if the cleanup() is
-part of a graceful restart and the application wants to cleanup all state then
-start again), the internal STACK storage will be freshly allocated. This is much
-the same as the situation in the ENGINE_TABLE instantiations ... NULL is the
-initialised state, so only modification operations (not queries) will cause that
-code to have to register a cleanup.
-
-What else? The bignum callbacks and associated ENGINE functions have been
-removed for two obvious reasons; (i) there was no way to generalise them to the
-mechanism now used by RSA/DSA/..., because there's no such thing as a BIGNUM
-method, and (ii) because of (i), there was no meaningful way for library or
-application code to automatically hook and use ENGINE supplied bignum functions
-anyway. Also, ENGINE_cpy() has been removed (although an internal-only version
-exists) - the idea of providing an ENGINE_cpy() function probably wasn't a good
-one and now certainly doesn't make sense in any generalised way. Some of the
-RSA, DSA, DH, and RAND functions that were fiddled during the original ENGINE
-changes have now, as a consequence, been reverted back. This is because the
-hooking of ENGINE is now automatic (and passive, it can internally use a NULL
-ENGINE pointer to simply ignore ENGINE from then on).
-
-Hell, that should be enough for now ... comments welcome.
-
diff --git a/crypto/engine/README.md b/crypto/engine/README.md
new file mode 100644
index 000000000000..b45115ca2481
--- /dev/null
+++ b/crypto/engine/README.md
@@ -0,0 +1,210 @@
+Notes on engines of 2001-09-24
+==============================
+
+This "description" (if one chooses to call it that) needed some major updating
+so here goes. This update addresses a change being made at the same time to
+OpenSSL, and it pretty much completely restructures the underlying mechanics of
+the "ENGINE" code. So it serves a double purpose of being a "ENGINE internals
+for masochists" document *and* a rather extensive commit log message. (I'd get
+lynched for sticking all this in CHANGES.md or the commit mails :-).
+
+ENGINE_TABLE underlies this restructuring, as described in the internal header
+"eng_local.h", implemented in eng_table.c, and used in each of the "class" files;
+tb_rsa.c, tb_dsa.c, etc.
+
+However, "EVP_CIPHER" underlies the motivation and design of ENGINE_TABLE so
+I'll mention a bit about that first. EVP_CIPHER (and most of this applies
+equally to EVP_MD for digests) is both a "method" and a algorithm/mode
+identifier that, in the current API, "lingers". These cipher description +
+implementation structures can be defined or obtained directly by applications,
+or can be loaded "en masse" into EVP storage so that they can be catalogued and
+searched in various ways, ie. two ways of encrypting with the "des_cbc"
+algorithm/mode pair are;
+
+ (i) directly;
+ const EVP_CIPHER *cipher = EVP_des_cbc();
+ EVP_EncryptInit(&ctx, cipher, key, iv);
+ [ ... use EVP_EncryptUpdate() and EVP_EncryptFinal() ...]
+
+ (ii) indirectly;
+ OpenSSL_add_all_ciphers();
+ cipher = EVP_get_cipherbyname("des_cbc");
+ EVP_EncryptInit(&ctx, cipher, key, iv);
+ [ ... etc ... ]
+
+The latter is more generally used because it also allows ciphers/digests to be
+looked up based on other identifiers which can be useful for automatic cipher
+selection, eg. in SSL/TLS, or by user-controllable configuration.
+
+The important point about this is that EVP_CIPHER definitions and structures are
+passed around with impunity and there is no safe way, without requiring massive
+rewrites of many applications, to assume that EVP_CIPHERs can be reference
+counted. One an EVP_CIPHER is exposed to the caller, neither it nor anything it
+comes from can "safely" be destroyed. Unless of course the way of getting to
+such ciphers is via entirely distinct API calls that didn't exist before.
+However existing API usage cannot be made to understand when an EVP_CIPHER
+pointer, that has been passed to the caller, is no longer being used.
+
+The other problem with the existing API w.r.t. to hooking EVP_CIPHER support
+into ENGINE is storage - the OBJ_NAME-based storage used by EVP to register
+ciphers simultaneously registers cipher *types* and cipher *implementations* -
+they are effectively the same thing, an "EVP_CIPHER" pointer. The problem with
+hooking in ENGINEs is that multiple ENGINEs may implement the same ciphers. The
+solution is necessarily that ENGINE-provided ciphers simply are not registered,
+stored, or exposed to the caller in the same manner as existing ciphers. This is
+especially necessary considering the fact ENGINE uses reference counts to allow
+for cleanup, modularity, and DSO support - yet EVP_CIPHERs, as exposed to
+callers in the current API, support no such controls.
+
+Another sticking point for integrating cipher support into ENGINE is linkage.
+Already there is a problem with the way ENGINE supports RSA, DSA, etc whereby
+they are available *because* they're part of a giant ENGINE called "openssl".
+Ie. all implementations *have* to come from an ENGINE, but we get round that by
+having a giant ENGINE with all the software support encapsulated. This creates
+linker hassles if nothing else - linking a 1-line application that calls 2 basic
+RSA functions (eg. "RSA_free(RSA_new());") will result in large quantities of
+ENGINE code being linked in *and* because of that DSA, DH, and RAND also. If we
+continue with this approach for EVP_CIPHER support (even if it *was* possible)
+we would lose our ability to link selectively by selectively loading certain
+implementations of certain functionality. Touching any part of any kind of
+crypto would result in massive static linkage of everything else. So the
+solution is to change the way ENGINE feeds existing "classes", ie. how the
+hooking to ENGINE works from RSA, DSA, DH, RAND, as well as adding new hooking
+for EVP_CIPHER, and EVP_MD.
+
+The way this is now being done is by mostly reverting back to how things used to
+work prior to ENGINE :-). Ie. RSA now has a "RSA_METHOD" pointer again - this
+was previously replaced by an "ENGINE" pointer and all RSA code that required
+the RSA_METHOD would call ENGINE_get_RSA() each time on its ENGINE handle to
+temporarily get and use the ENGINE's RSA implementation. Apart from being more
+efficient, switching back to each RSA having an RSA_METHOD pointer also allows
+us to conceivably operate with *no* ENGINE. As we'll see, this removes any need
+for a fallback ENGINE that encapsulates default implementations - we can simply
+have our RSA structure pointing its RSA_METHOD pointer to the software
+implementation and have its ENGINE pointer set to NULL.
+
+A look at the EVP_CIPHER hooking is most explanatory, the RSA, DSA (etc) cases
+turn out to be degenerate forms of the same thing. The EVP storage of ciphers,
+and the existing EVP API functions that return "software" implementations and
+descriptions remain untouched. However, the storage takes more meaning in terms
+of "cipher description" and less meaning in terms of "implementation". When an
+EVP_CIPHER_CTX is actually initialised with an EVP_CIPHER method and is about to
+begin en/decryption, the hooking to ENGINE comes into play. What happens is that
+cipher-specific ENGINE code is asked for an ENGINE pointer (a functional
+reference) for any ENGINE that is registered to perform the algo/mode that the
+provided EVP_CIPHER structure represents. Under normal circumstances, that
+ENGINE code will return NULL because no ENGINEs will have had any cipher
+implementations *registered*. As such, a NULL ENGINE pointer is stored in the
+EVP_CIPHER_CTX context, and the EVP_CIPHER structure is left hooked into the
+context and so is used as the implementation. Pretty much how things work now
+except we'd have a redundant ENGINE pointer set to NULL and doing nothing.
+
+Conversely, if an ENGINE *has* been registered to perform the algorithm/mode
+combination represented by the provided EVP_CIPHER, then a functional reference
+to that ENGINE will be returned to the EVP_CIPHER_CTX during initialisation.
+That functional reference will be stored in the context (and released on
+cleanup) - and having that reference provides a *safe* way to use an EVP_CIPHER
+definition that is private to the ENGINE. Ie. the EVP_CIPHER provided by the
+application will actually be replaced by an EVP_CIPHER from the registered
+ENGINE - it will support the same algorithm/mode as the original but will be a
+completely different implementation. Because this EVP_CIPHER isn't stored in the
+EVP storage, nor is it returned to applications from traditional API functions,
+there is no associated problem with it not having reference counts. And of
+course, when one of these "private" cipher implementations is hooked into
+EVP_CIPHER_CTX, it is done whilst the EVP_CIPHER_CTX holds a functional
+reference to the ENGINE that owns it, thus the use of the ENGINE's EVP_CIPHER is
+safe.
+
+The "cipher-specific ENGINE code" I mentioned is implemented in tb_cipher.c but
+in essence it is simply an instantiation of "ENGINE_TABLE" code for use by
+EVP_CIPHER code. tb_digest.c is virtually identical but, of course, it is for
+use by EVP_MD code. Ditto for tb_rsa.c, tb_dsa.c, etc. These instantiations of
+ENGINE_TABLE essentially provide linker-separation of the classes so that even
+if ENGINEs implement *all* possible algorithms, an application using only
+EVP_CIPHER code will link at most code relating to EVP_CIPHER, tb_cipher.c, core
+ENGINE code that is independent of class, and of course the ENGINE
+implementation that the application loaded. It will *not* however link any
+class-specific ENGINE code for digests, RSA, etc nor will it bleed over into
+other APIs, such as the RSA/DSA/etc library code.
+
+ENGINE_TABLE is a little more complicated than may seem necessary but this is
+mostly to avoid a lot of "init()"-thrashing on ENGINEs (that may have to load
+DSOs, and other expensive setup that shouldn't be thrashed unnecessarily) *and*
+to duplicate "default" behaviour. Basically an ENGINE_TABLE instantiation, for
+example tb_cipher.c, implements a hash-table keyed by integer "nid" values.
+These nids provide the uniquenness of an algorithm/mode - and each nid will hash
+to a potentially NULL "ENGINE_PILE". An ENGINE_PILE is essentially a list of
+pointers to ENGINEs that implement that particular 'nid'. Each "pile" uses some
+caching tricks such that requests on that 'nid' will be cached and all future
+requests will return immediately (well, at least with minimal operation) unless
+a change is made to the pile, eg. perhaps an ENGINE was unloaded. The reason is
+that an application could have support for 10 ENGINEs statically linked
+in, and the machine in question may not have any of the hardware those 10
+ENGINEs support. If each of those ENGINEs has a "des_cbc" implementation, we
+want to avoid every EVP_CIPHER_CTX setup from trying (and failing) to initialise
+each of those 10 ENGINEs. Instead, the first such request will try to do that
+and will either return (and cache) a NULL ENGINE pointer or will return a
+functional reference to the first that successfully initialised. In the latter
+case it will also cache an extra functional reference to the ENGINE as a
+"default" for that 'nid'. The caching is acknowledged by a 'uptodate' variable
+that is unset only if un/registration takes place on that pile. Ie. if
+implementations of "des_cbc" are added or removed. This behaviour can be
+tweaked; the ENGINE_TABLE_FLAG_NOINIT value can be passed to
+ENGINE_set_table_flags(), in which case the only ENGINEs that tb_cipher.c will
+try to initialise from the "pile" will be those that are already initialised
+(ie. it's simply an increment of the functional reference count, and no real
+"initialisation" will take place).
+
+RSA, DSA, DH, and RAND all have their own ENGINE_TABLE code as well, and the
+difference is that they all use an implicit 'nid' of 1. Whereas EVP_CIPHERs are
+actually qualitatively different depending on 'nid' (the "des_cbc" EVP_CIPHER is
+not an interoperable implementation of "aes_256_cbc"), RSA_METHODs are
+necessarily interoperable and don't have different flavours, only different
+implementations. In other words, the ENGINE_TABLE for RSA will either be empty,
+or will have a single ENGINE_PILE hashed to by the 'nid' 1 and that pile
+represents ENGINEs that implement the single "type" of RSA there is.
+
+Cleanup - the registration and unregistration may pose questions about how
+cleanup works with the ENGINE_PILE doing all this caching nonsense (ie. when the
+application or EVP_CIPHER code releases its last reference to an ENGINE, the
+ENGINE_PILE code may still have references and thus those ENGINEs will stay
+hooked in forever). The way this is handled is via "unregistration". With these
+new ENGINE changes, an abstract ENGINE can be loaded and initialised, but that
+is an algorithm-agnostic process. Even if initialised, it will not have
+registered any of its implementations (to do so would link all class "table"
+code despite the fact the application may use only ciphers, for example). This
+is deliberately a distinct step. Moreover, registration and unregistration has
+nothing to do with whether an ENGINE is *functional* or not (ie. you can even
+register an ENGINE and its implementations without it being operational, you may
+not even have the drivers to make it operate). What actually happens with
+respect to cleanup is managed inside eng_lib.c with the `engine_cleanup_***`
+functions. These functions are internal-only and each part of ENGINE code that
+could require cleanup will, upon performing its first allocation, register a
+callback with the "engine_cleanup" code. The other part of this that makes it
+tick is that the ENGINE_TABLE instantiations (tb_***.c) use NULL as their
+initialised state. So if RSA code asks for an ENGINE and no ENGINE has
+registered an implementation, the code will simply return NULL and the tb_rsa.c
+state will be unchanged. Thus, no cleanup is required unless registration takes
+place. ENGINE_cleanup() will simply iterate across a list of registered cleanup
+callbacks calling each in turn, and will then internally delete its own storage
+(a STACK). When a cleanup callback is next registered (eg. if the cleanup() is
+part of a graceful restart and the application wants to cleanup all state then
+start again), the internal STACK storage will be freshly allocated. This is much
+the same as the situation in the ENGINE_TABLE instantiations ... NULL is the
+initialised state, so only modification operations (not queries) will cause that
+code to have to register a cleanup.
+
+What else? The bignum callbacks and associated ENGINE functions have been
+removed for two obvious reasons; (i) there was no way to generalise them to the
+mechanism now used by RSA/DSA/..., because there's no such thing as a BIGNUM
+method, and (ii) because of (i), there was no meaningful way for library or
+application code to automatically hook and use ENGINE supplied bignum functions
+anyway. Also, ENGINE_cpy() has been removed (although an internal-only version
+exists) - the idea of providing an ENGINE_cpy() function probably wasn't a good
+one and now certainly doesn't make sense in any generalised way. Some of the
+RSA, DSA, DH, and RAND functions that were fiddled during the original ENGINE
+changes have now, as a consequence, been reverted back. This is because the
+hooking of ENGINE is now automatic (and passive, it can internally use a NULL
+ENGINE pointer to simply ignore ENGINE from then on).
+
+Hell, that should be enough for now ... comments welcome.
diff --git a/crypto/engine/build.info b/crypto/engine/build.info
index e00802a3fd55..47fe948966ea 100644
--- a/crypto/engine/build.info
+++ b/crypto/engine/build.info
@@ -6,6 +6,3 @@ SOURCE[../../libcrypto]=\
tb_cipher.c tb_digest.c tb_pkmeth.c tb_asnmth.c tb_eckey.c \
eng_openssl.c eng_cnf.c eng_dyn.c \
eng_rdrand.c
-IF[{- !$disabled{devcryptoeng} -}]
- SOURCE[../../libcrypto]=eng_devcrypto.c
-ENDIF
diff --git a/crypto/engine/eng_all.c b/crypto/engine/eng_all.c
index 474a60c9bf13..2f83b2ec182f 100644
--- a/crypto/engine/eng_all.c
+++ b/crypto/engine/eng_all.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -15,8 +15,10 @@ void ENGINE_load_builtin_engines(void)
OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_ALL_BUILTIN, NULL);
}
-#if (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)) && OPENSSL_API_COMPAT < 0x10100000L
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# if (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__))
void ENGINE_setup_bsd_cryptodev(void)
{
}
+# endif
#endif
diff --git a/crypto/engine/eng_cnf.c b/crypto/engine/eng_cnf.c
index df00df6acd61..14744bb7f55b 100644
--- a/crypto/engine/eng_cnf.c
+++ b/crypto/engine/eng_cnf.c
@@ -1,16 +1,18 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "eng_local.h"
#include <openssl/conf.h>
-
-/* #define ENGINE_CONF_DEBUG */
+#include <openssl/trace.h>
/* ENGINE config module */
@@ -50,15 +52,12 @@ static int int_engine_configure(const char *name, const char *value, const CONF
int soft = 0;
name = skip_dot(name);
-#ifdef ENGINE_CONF_DEBUG
- fprintf(stderr, "Configuring engine %s\n", name);
-#endif
+ OSSL_TRACE1(CONF, "Configuring engine %s\n", name);
/* Value is a section containing ENGINE commands */
ecmds = NCONF_get_section(cnf, value);
if (!ecmds) {
- ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE,
- ENGINE_R_ENGINE_SECTION_ERROR);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ENGINE_SECTION_ERROR);
return 0;
}
@@ -66,10 +65,8 @@ static int int_engine_configure(const char *name, const char *value, const CONF
ecmd = sk_CONF_VALUE_value(ecmds, i);
ctrlname = skip_dot(ecmd->name);
ctrlvalue = ecmd->value;
-#ifdef ENGINE_CONF_DEBUG
- fprintf(stderr, "ENGINE conf: doing ctrl(%s,%s)\n", ctrlname,
- ctrlvalue);
-#endif
+ OSSL_TRACE2(CONF, "ENGINE: doing ctrl(%s,%s)\n",
+ ctrlname, ctrlvalue);
/* First handle some special pseudo ctrls */
@@ -118,8 +115,7 @@ static int int_engine_configure(const char *name, const char *value, const CONF
if (!int_engine_init(e))
goto err;
} else if (do_init != 0) {
- ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE,
- ENGINE_R_INVALID_INIT_VALUE);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INVALID_INIT_VALUE);
goto err;
}
} else if (strcmp(ctrlname, "default_algorithms") == 0) {
@@ -137,12 +133,12 @@ static int int_engine_configure(const char *name, const char *value, const CONF
ret = 1;
err:
if (ret != 1) {
- ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE,
- ENGINE_R_ENGINE_CONFIGURATION_ERROR);
- if (ecmd)
- ERR_add_error_data(6, "section=", ecmd->section,
- ", name=", ecmd->name,
- ", value=", ecmd->value);
+ if (ecmd == NULL)
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ENGINE_CONFIGURATION_ERROR);
+ else
+ ERR_raise_data(ERR_LIB_ENGINE, ENGINE_R_ENGINE_CONFIGURATION_ERROR,
+ "section=%s, name=%s, value=%s",
+ ecmd->section, ecmd->name, ecmd->value);
}
ENGINE_free(e);
return ret;
@@ -153,16 +149,13 @@ static int int_engine_module_init(CONF_IMODULE *md, const CONF *cnf)
STACK_OF(CONF_VALUE) *elist;
CONF_VALUE *cval;
int i;
-#ifdef ENGINE_CONF_DEBUG
- fprintf(stderr, "Called engine module: name %s, value %s\n",
- CONF_imodule_get_name(md), CONF_imodule_get_value(md));
-#endif
+ OSSL_TRACE2(CONF, "Called engine module: name %s, value %s\n",
+ CONF_imodule_get_name(md), CONF_imodule_get_value(md));
/* Value is a section containing ENGINEs to configure */
elist = NCONF_get_section(cnf, CONF_imodule_get_value(md));
if (!elist) {
- ENGINEerr(ENGINE_F_INT_ENGINE_MODULE_INIT,
- ENGINE_R_ENGINES_SECTION_ERROR);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ENGINES_SECTION_ERROR);
return 0;
}
diff --git a/crypto/engine/eng_ctrl.c b/crypto/engine/eng_ctrl.c
index e65e78447b43..5d7e15634e6e 100644
--- a/crypto/engine/eng_ctrl.c
+++ b/crypto/engine/eng_ctrl.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "eng_local.h"
/*
@@ -76,7 +79,7 @@ static int int_ctrl_helper(ENGINE *e, int cmd, long i, void *p,
(cmd == ENGINE_CTRL_GET_NAME_FROM_CMD) ||
(cmd == ENGINE_CTRL_GET_DESC_FROM_CMD)) {
if (s == NULL) {
- ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
}
@@ -84,7 +87,7 @@ static int int_ctrl_helper(ENGINE *e, int cmd, long i, void *p,
if (cmd == ENGINE_CTRL_GET_CMD_FROM_NAME) {
if ((e->cmd_defns == NULL)
|| ((idx = int_ctrl_cmd_by_name(e->cmd_defns, s)) < 0)) {
- ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ENGINE_R_INVALID_CMD_NAME);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INVALID_CMD_NAME);
return -1;
}
return e->cmd_defns[idx].cmd_num;
@@ -95,7 +98,7 @@ static int int_ctrl_helper(ENGINE *e, int cmd, long i, void *p,
*/
if ((e->cmd_defns == NULL)
|| ((idx = int_ctrl_cmd_by_num(e->cmd_defns, (unsigned int)i)) < 0)) {
- ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ENGINE_R_INVALID_CMD_NUMBER);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INVALID_CMD_NUMBER);
return -1;
}
/* Now the logic splits depending on command type */
@@ -118,7 +121,7 @@ static int int_ctrl_helper(ENGINE *e, int cmd, long i, void *p,
return cdp->cmd_flags;
}
/* Shouldn't really be here ... */
- ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ENGINE_R_INTERNAL_LIST_ERROR);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
return -1;
}
@@ -126,15 +129,16 @@ int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
{
int ctrl_exists, ref_exists;
if (e == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return 0;
ref_exists = ((e->struct_ref > 0) ? 1 : 0);
CRYPTO_THREAD_unlock(global_engine_lock);
ctrl_exists = ((e->ctrl == NULL) ? 0 : 1);
if (!ref_exists) {
- ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_NO_REFERENCE);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NO_REFERENCE);
return 0;
}
/*
@@ -155,7 +159,7 @@ int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
if (ctrl_exists && !(e->flags & ENGINE_FLAGS_MANUAL_CMD_CTRL))
return int_ctrl_helper(e, cmd, i, p, f);
if (!ctrl_exists) {
- ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_NO_CONTROL_FUNCTION);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NO_CONTROL_FUNCTION);
/*
* For these cmd-related functions, failure is indicated by a -1
* return value (because 0 is used as a valid return in some
@@ -168,7 +172,7 @@ int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
}
/* Anything else requires a ctrl() handler to exist. */
if (!ctrl_exists) {
- ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_NO_CONTROL_FUNCTION);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NO_CONTROL_FUNCTION);
return 0;
}
return e->ctrl(e, cmd, i, p, f);
@@ -179,8 +183,7 @@ int ENGINE_cmd_is_executable(ENGINE *e, int cmd)
int flags;
if ((flags =
ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, cmd, NULL, NULL)) < 0) {
- ENGINEerr(ENGINE_F_ENGINE_CMD_IS_EXECUTABLE,
- ENGINE_R_INVALID_CMD_NUMBER);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INVALID_CMD_NUMBER);
return 0;
}
if (!(flags & ENGINE_CMD_FLAG_NO_INPUT) &&
@@ -196,7 +199,7 @@ int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name,
int num;
if (e == NULL || cmd_name == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (e->ctrl == NULL
@@ -214,7 +217,7 @@ int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name,
ERR_clear_error();
return 1;
}
- ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD, ENGINE_R_INVALID_CMD_NAME);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INVALID_CMD_NAME);
return 0;
}
/*
@@ -234,7 +237,7 @@ int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
char *ptr;
if (e == NULL || cmd_name == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (e->ctrl == NULL
@@ -252,12 +255,11 @@ int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
ERR_clear_error();
return 1;
}
- ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, ENGINE_R_INVALID_CMD_NAME);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INVALID_CMD_NAME);
return 0;
}
if (!ENGINE_cmd_is_executable(e, num)) {
- ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
- ENGINE_R_CMD_NOT_EXECUTABLE);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_CMD_NOT_EXECUTABLE);
return 0;
}
@@ -267,8 +269,7 @@ int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
* Shouldn't happen, given that ENGINE_cmd_is_executable() returned
* success.
*/
- ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
- ENGINE_R_INTERNAL_LIST_ERROR);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
return 0;
}
/*
@@ -276,8 +277,7 @@ int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
*/
if (flags & ENGINE_CMD_FLAG_NO_INPUT) {
if (arg != NULL) {
- ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
- ENGINE_R_COMMAND_TAKES_NO_INPUT);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_COMMAND_TAKES_NO_INPUT);
return 0;
}
/*
@@ -292,8 +292,7 @@ int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
}
/* So, we require input */
if (arg == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
- ENGINE_R_COMMAND_TAKES_INPUT);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_COMMAND_TAKES_INPUT);
return 0;
}
/* If it takes string input, that's easy */
@@ -310,14 +309,12 @@ int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
* used.
*/
if (!(flags & ENGINE_CMD_FLAG_NUMERIC)) {
- ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
- ENGINE_R_INTERNAL_LIST_ERROR);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
return 0;
}
l = strtol(arg, &ptr, 10);
if ((arg == ptr) || (*ptr != '\0')) {
- ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
- ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER);
return 0;
}
/*
diff --git a/crypto/engine/eng_devcrypto.c b/crypto/engine/eng_devcrypto.c
deleted file mode 100644
index 84a3b7dbec75..000000000000
--- a/crypto/engine/eng_devcrypto.c
+++ /dev/null
@@ -1,849 +0,0 @@
-/*
- * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "e_os.h"
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <assert.h>
-
-#include <openssl/evp.h>
-#include <openssl/err.h>
-#include <openssl/engine.h>
-#include <openssl/objects.h>
-#include <crypto/cryptodev.h>
-
-#include "crypto/engine.h"
-
-/* #define ENGINE_DEVCRYPTO_DEBUG */
-
-#if CRYPTO_ALGORITHM_MIN < CRYPTO_ALGORITHM_MAX
-# define CHECK_BSD_STYLE_MACROS
-#endif
-
-/*
- * ONE global file descriptor for all sessions. This allows operations
- * such as digest session data copying (see digest_copy()), but is also
- * saner... why re-open /dev/crypto for every session?
- */
-static int cfd;
-
-static int clean_devcrypto_session(struct session_op *sess) {
- if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) {
- SYSerr(SYS_F_IOCTL, errno);
- return 0;
- }
- memset(sess, 0, sizeof(struct session_op));
- return 1;
-}
-
-/******************************************************************************
- *
- * Ciphers
- *
- * Because they all do the same basic operation, we have only one set of
- * method functions for them all to share, and a mapping table between
- * NIDs and cryptodev IDs, with all the necessary size data.
- *
- *****/
-
-struct cipher_ctx {
- struct session_op sess;
- int op; /* COP_ENCRYPT or COP_DECRYPT */
- unsigned long mode; /* EVP_CIPH_*_MODE */
-
- /* to handle ctr mode being a stream cipher */
- unsigned char partial[EVP_MAX_BLOCK_LENGTH];
- unsigned int blocksize, num;
-};
-
-static const struct cipher_data_st {
- int nid;
- int blocksize;
- int keylen;
- int ivlen;
- int flags;
- int devcryptoid;
-} cipher_data[] = {
-#ifndef OPENSSL_NO_DES
- { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC },
- { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC },
-#endif
-#ifndef OPENSSL_NO_BF
- { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC },
-#endif
-#ifndef OPENSSL_NO_CAST
- { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC },
-#endif
- { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
- { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
- { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
-#ifndef OPENSSL_NO_RC4
- { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 },
-#endif
-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR)
- { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
- { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
- { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
-#endif
-#if 0 /* Not yet supported */
- { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
- { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
-#endif
-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB)
- { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
- { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
- { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
-#endif
-#if 0 /* Not yet supported */
- { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
- { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
- { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
-#endif
-#ifndef OPENSSL_NO_CAMELLIA
- { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE,
- CRYPTO_CAMELLIA_CBC },
- { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE,
- CRYPTO_CAMELLIA_CBC },
- { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE,
- CRYPTO_CAMELLIA_CBC },
-#endif
-};
-
-static size_t get_cipher_data_index(int nid)
-{
- size_t i;
-
- for (i = 0; i < OSSL_NELEM(cipher_data); i++)
- if (nid == cipher_data[i].nid)
- return i;
-
- /*
- * Code further down must make sure that only NIDs in the table above
- * are used. If any other NID reaches this function, there's a grave
- * coding error further down.
- */
- assert("Code that never should be reached" == NULL);
- return -1;
-}
-
-static const struct cipher_data_st *get_cipher_data(int nid)
-{
- return &cipher_data[get_cipher_data_index(nid)];
-}
-
-/*
- * Following are the three necessary functions to map OpenSSL functionality
- * with cryptodev.
- */
-
-static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
- const unsigned char *iv, int enc)
-{
- struct cipher_ctx *cipher_ctx =
- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
- const struct cipher_data_st *cipher_d =
- get_cipher_data(EVP_CIPHER_CTX_nid(ctx));
-
- /* cleanup a previous session */
- if (cipher_ctx->sess.ses != 0 &&
- clean_devcrypto_session(&cipher_ctx->sess) == 0)
- return 0;
-
- cipher_ctx->sess.cipher = cipher_d->devcryptoid;
- cipher_ctx->sess.keylen = cipher_d->keylen;
- cipher_ctx->sess.key = (void *)key;
- cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT;
- cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE;
- cipher_ctx->blocksize = cipher_d->blocksize;
- if (ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) {
- SYSerr(SYS_F_IOCTL, errno);
- return 0;
- }
-
- return 1;
-}
-
-static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
-{
- struct cipher_ctx *cipher_ctx =
- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
- struct crypt_op cryp;
- unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
-#if !defined(COP_FLAG_WRITE_IV)
- unsigned char saved_iv[EVP_MAX_IV_LENGTH];
- const unsigned char *ivptr;
- size_t nblocks, ivlen;
-#endif
-
- memset(&cryp, 0, sizeof(cryp));
- cryp.ses = cipher_ctx->sess.ses;
- cryp.len = inl;
- cryp.src = (void *)in;
- cryp.dst = (void *)out;
- cryp.iv = (void *)iv;
- cryp.op = cipher_ctx->op;
-#if !defined(COP_FLAG_WRITE_IV)
- cryp.flags = 0;
-
- ivlen = EVP_CIPHER_CTX_iv_length(ctx);
- if (ivlen > 0)
- switch (cipher_ctx->mode) {
- case EVP_CIPH_CBC_MODE:
- assert(inl >= ivlen);
- if (!EVP_CIPHER_CTX_encrypting(ctx)) {
- ivptr = in + inl - ivlen;
- memcpy(saved_iv, ivptr, ivlen);
- }
- break;
-
- case EVP_CIPH_CTR_MODE:
- break;
-
- default: /* should not happen */
- return 0;
- }
-#else
- cryp.flags = COP_FLAG_WRITE_IV;
-#endif
-
- if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) {
- SYSerr(SYS_F_IOCTL, errno);
- return 0;
- }
-
-#if !defined(COP_FLAG_WRITE_IV)
- if (ivlen > 0)
- switch (cipher_ctx->mode) {
- case EVP_CIPH_CBC_MODE:
- assert(inl >= ivlen);
- if (EVP_CIPHER_CTX_encrypting(ctx))
- ivptr = out + inl - ivlen;
- else
- ivptr = saved_iv;
-
- memcpy(iv, ivptr, ivlen);
- break;
-
- case EVP_CIPH_CTR_MODE:
- nblocks = (inl + cipher_ctx->blocksize - 1)
- / cipher_ctx->blocksize;
- do {
- ivlen--;
- nblocks += iv[ivlen];
- iv[ivlen] = (uint8_t) nblocks;
- nblocks >>= 8;
- } while (ivlen);
- break;
-
- default: /* should not happen */
- return 0;
- }
-#endif
-
- return 1;
-}
-
-static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
-{
- struct cipher_ctx *cipher_ctx =
- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
- size_t nblocks, len;
-
- /* initial partial block */
- while (cipher_ctx->num && inl) {
- (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num];
- --inl;
- cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize;
- }
-
- /* full blocks */
- if (inl > (unsigned int) cipher_ctx->blocksize) {
- nblocks = inl/cipher_ctx->blocksize;
- len = nblocks * cipher_ctx->blocksize;
- if (cipher_do_cipher(ctx, out, in, len) < 1)
- return 0;
- inl -= len;
- out += len;
- in += len;
- }
-
- /* final partial block */
- if (inl) {
- memset(cipher_ctx->partial, 0, cipher_ctx->blocksize);
- if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial,
- cipher_ctx->blocksize) < 1)
- return 0;
- while (inl--) {
- out[cipher_ctx->num] = in[cipher_ctx->num]
- ^ cipher_ctx->partial[cipher_ctx->num];
- cipher_ctx->num++;
- }
- }
-
- return 1;
-}
-
-static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2)
-{
- struct cipher_ctx *cipher_ctx =
- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
- EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2;
- struct cipher_ctx *to_cipher_ctx;
-
- switch (type) {
- case EVP_CTRL_COPY:
- if (cipher_ctx == NULL)
- return 1;
- /* when copying the context, a new session needs to be initialized */
- to_cipher_ctx =
- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx);
- memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess));
- return cipher_init(to_ctx, cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx),
- (cipher_ctx->op == COP_ENCRYPT));
-
- case EVP_CTRL_INIT:
- memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess));
- return 1;
-
- default:
- break;
- }
-
- return -1;
-}
-
-static int cipher_cleanup(EVP_CIPHER_CTX *ctx)
-{
- struct cipher_ctx *cipher_ctx =
- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
-
- return clean_devcrypto_session(&cipher_ctx->sess);
-}
-
-/*
- * Keep a table of known nids and associated methods.
- * Note that known_cipher_nids[] isn't necessarily indexed the same way as
- * cipher_data[] above, which known_cipher_methods[] is.
- */
-static int known_cipher_nids[OSSL_NELEM(cipher_data)];
-static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */
-static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, };
-
-static void prepare_cipher_methods(void)
-{
- size_t i;
- struct session_op sess;
- unsigned long cipher_mode;
-
- memset(&sess, 0, sizeof(sess));
- sess.key = (void *)"01234567890123456789012345678901234567890123456789";
-
- for (i = 0, known_cipher_nids_amount = 0;
- i < OSSL_NELEM(cipher_data); i++) {
-
- /*
- * Check that the algo is really availably by trying to open and close
- * a session.
- */
- sess.cipher = cipher_data[i].devcryptoid;
- sess.keylen = cipher_data[i].keylen;
- if (ioctl(cfd, CIOCGSESSION, &sess) < 0
- || ioctl(cfd, CIOCFSESSION, &sess.ses) < 0)
- continue;
-
- cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE;
-
- if ((known_cipher_methods[i] =
- EVP_CIPHER_meth_new(cipher_data[i].nid,
- cipher_mode == EVP_CIPH_CTR_MODE ? 1 :
- cipher_data[i].blocksize,
- cipher_data[i].keylen)) == NULL
- || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i],
- cipher_data[i].ivlen)
- || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i],
- cipher_data[i].flags
- | EVP_CIPH_CUSTOM_COPY
- | EVP_CIPH_CTRL_INIT
- | EVP_CIPH_FLAG_DEFAULT_ASN1)
- || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init)
- || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i],
- cipher_mode == EVP_CIPH_CTR_MODE ?
- ctr_do_cipher :
- cipher_do_cipher)
- || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl)
- || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i],
- cipher_cleanup)
- || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
- sizeof(struct cipher_ctx))) {
- EVP_CIPHER_meth_free(known_cipher_methods[i]);
- known_cipher_methods[i] = NULL;
- } else {
- known_cipher_nids[known_cipher_nids_amount++] =
- cipher_data[i].nid;
- }
- }
-}
-
-static const EVP_CIPHER *get_cipher_method(int nid)
-{
- size_t i = get_cipher_data_index(nid);
-
- if (i == (size_t)-1)
- return NULL;
- return known_cipher_methods[i];
-}
-
-static int get_cipher_nids(const int **nids)
-{
- *nids = known_cipher_nids;
- return known_cipher_nids_amount;
-}
-
-static void destroy_cipher_method(int nid)
-{
- size_t i = get_cipher_data_index(nid);
-
- EVP_CIPHER_meth_free(known_cipher_methods[i]);
- known_cipher_methods[i] = NULL;
-}
-
-static void destroy_all_cipher_methods(void)
-{
- size_t i;
-
- for (i = 0; i < OSSL_NELEM(cipher_data); i++)
- destroy_cipher_method(cipher_data[i].nid);
-}
-
-static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
- const int **nids, int nid)
-{
- if (cipher == NULL)
- return get_cipher_nids(nids);
-
- *cipher = get_cipher_method(nid);
-
- return *cipher != NULL;
-}
-
-/*
- * We only support digests if the cryptodev implementation supports multiple
- * data updates and session copying. Otherwise, we would be forced to maintain
- * a cache, which is perilous if there's a lot of data coming in (if someone
- * wants to checksum an OpenSSL tarball, for example).
- */
-#if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
-#define IMPLEMENT_DIGEST
-
-/******************************************************************************
- *
- * Digests
- *
- * Because they all do the same basic operation, we have only one set of
- * method functions for them all to share, and a mapping table between
- * NIDs and cryptodev IDs, with all the necessary size data.
- *
- *****/
-
-struct digest_ctx {
- struct session_op sess;
- /* This signals that the init function was called, not that it succeeded. */
- int init_called;
-};
-
-static const struct digest_data_st {
- int nid;
- int blocksize;
- int digestlen;
- int devcryptoid;
-} digest_data[] = {
-#ifndef OPENSSL_NO_MD5
- { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 },
-#endif
- { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 },
-#ifndef OPENSSL_NO_RMD160
-# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160)
- { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 },
-# endif
-#endif
-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224)
- { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 },
-#endif
-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256)
- { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 },
-#endif
-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384)
- { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 },
-#endif
-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512)
- { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 },
-#endif
-};
-
-static size_t get_digest_data_index(int nid)
-{
- size_t i;
-
- for (i = 0; i < OSSL_NELEM(digest_data); i++)
- if (nid == digest_data[i].nid)
- return i;
-
- /*
- * Code further down must make sure that only NIDs in the table above
- * are used. If any other NID reaches this function, there's a grave
- * coding error further down.
- */
- assert("Code that never should be reached" == NULL);
- return -1;
-}
-
-static const struct digest_data_st *get_digest_data(int nid)
-{
- return &digest_data[get_digest_data_index(nid)];
-}
-
-/*
- * Following are the four necessary functions to map OpenSSL functionality
- * with cryptodev.
- */
-
-static int digest_init(EVP_MD_CTX *ctx)
-{
- struct digest_ctx *digest_ctx =
- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
- const struct digest_data_st *digest_d =
- get_digest_data(EVP_MD_CTX_type(ctx));
-
- digest_ctx->init_called = 1;
-
- memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess));
- digest_ctx->sess.mac = digest_d->devcryptoid;
- if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) {
- SYSerr(SYS_F_IOCTL, errno);
- return 0;
- }
-
- return 1;
-}
-
-static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen,
- void *res, unsigned int flags)
-{
- struct crypt_op cryp;
-
- memset(&cryp, 0, sizeof(cryp));
- cryp.ses = ctx->sess.ses;
- cryp.len = srclen;
- cryp.src = (void *)src;
- cryp.dst = NULL;
- cryp.mac = res;
- cryp.flags = flags;
- return ioctl(cfd, CIOCCRYPT, &cryp);
-}
-
-static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- struct digest_ctx *digest_ctx =
- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
-
- if (count == 0)
- return 1;
-
- if (digest_ctx == NULL)
- return 0;
-
- if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) < 0) {
- SYSerr(SYS_F_IOCTL, errno);
- return 0;
- }
-
- return 1;
-}
-
-static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
-{
- struct digest_ctx *digest_ctx =
- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
-
- if (md == NULL || digest_ctx == NULL)
- return 0;
- if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) {
- SYSerr(SYS_F_IOCTL, errno);
- return 0;
- }
-
- return 1;
-}
-
-static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
-{
- struct digest_ctx *digest_from =
- (struct digest_ctx *)EVP_MD_CTX_md_data(from);
- struct digest_ctx *digest_to =
- (struct digest_ctx *)EVP_MD_CTX_md_data(to);
- struct cphash_op cphash;
-
- if (digest_from == NULL || digest_from->init_called != 1)
- return 1;
-
- if (!digest_init(to)) {
- SYSerr(SYS_F_IOCTL, errno);
- return 0;
- }
-
- cphash.src_ses = digest_from->sess.ses;
- cphash.dst_ses = digest_to->sess.ses;
- if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
- SYSerr(SYS_F_IOCTL, errno);
- return 0;
- }
- return 1;
-}
-
-static int digest_cleanup(EVP_MD_CTX *ctx)
-{
- struct digest_ctx *digest_ctx =
- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
-
- if (digest_ctx == NULL)
- return 1;
-
- return clean_devcrypto_session(&digest_ctx->sess);
-}
-
-static int devcrypto_test_digest(size_t digest_data_index)
-{
- struct session_op sess1, sess2;
- struct cphash_op cphash;
- int ret=0;
-
- memset(&sess1, 0, sizeof(sess1));
- memset(&sess2, 0, sizeof(sess2));
- sess1.mac = digest_data[digest_data_index].devcryptoid;
- if (ioctl(cfd, CIOCGSESSION, &sess1) < 0)
- return 0;
- /* Make sure the driver is capable of hash state copy */
- sess2.mac = sess1.mac;
- if (ioctl(cfd, CIOCGSESSION, &sess2) >= 0) {
- cphash.src_ses = sess1.ses;
- cphash.dst_ses = sess2.ses;
- if (ioctl(cfd, CIOCCPHASH, &cphash) >= 0)
- ret = 1;
- ioctl(cfd, CIOCFSESSION, &sess2.ses);
- }
- ioctl(cfd, CIOCFSESSION, &sess1.ses);
- return ret;
-}
-
-/*
- * Keep a table of known nids and associated methods.
- * Note that known_digest_nids[] isn't necessarily indexed the same way as
- * digest_data[] above, which known_digest_methods[] is.
- */
-static int known_digest_nids[OSSL_NELEM(digest_data)];
-static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */
-static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, };
-
-static void prepare_digest_methods(void)
-{
- size_t i;
-
- for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data);
- i++) {
-
- /*
- * Check that the algo is usable
- */
- if (!devcrypto_test_digest(i))
- continue;
-
- if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid,
- NID_undef)) == NULL
- || !EVP_MD_meth_set_input_blocksize(known_digest_methods[i],
- digest_data[i].blocksize)
- || !EVP_MD_meth_set_result_size(known_digest_methods[i],
- digest_data[i].digestlen)
- || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init)
- || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update)
- || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final)
- || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy)
- || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
- || !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
- sizeof(struct digest_ctx))) {
- EVP_MD_meth_free(known_digest_methods[i]);
- known_digest_methods[i] = NULL;
- } else {
- known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
- }
- }
-}
-
-static const EVP_MD *get_digest_method(int nid)
-{
- size_t i = get_digest_data_index(nid);
-
- if (i == (size_t)-1)
- return NULL;
- return known_digest_methods[i];
-}
-
-static int get_digest_nids(const int **nids)
-{
- *nids = known_digest_nids;
- return known_digest_nids_amount;
-}
-
-static void destroy_digest_method(int nid)
-{
- size_t i = get_digest_data_index(nid);
-
- EVP_MD_meth_free(known_digest_methods[i]);
- known_digest_methods[i] = NULL;
-}
-
-static void destroy_all_digest_methods(void)
-{
- size_t i;
-
- for (i = 0; i < OSSL_NELEM(digest_data); i++)
- destroy_digest_method(digest_data[i].nid);
-}
-
-static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
- const int **nids, int nid)
-{
- if (digest == NULL)
- return get_digest_nids(nids);
-
- *digest = get_digest_method(nid);
-
- return *digest != NULL;
-}
-
-#endif
-
-/******************************************************************************
- *
- * LOAD / UNLOAD
- *
- *****/
-
-static int devcrypto_unload(ENGINE *e)
-{
- destroy_all_cipher_methods();
-#ifdef IMPLEMENT_DIGEST
- destroy_all_digest_methods();
-#endif
-
- close(cfd);
-
- return 1;
-}
-/*
- * This engine is always built into libcrypto, so it doesn't offer any
- * ability to be dynamically loadable.
- */
-void engine_load_devcrypto_int()
-{
- ENGINE *e = NULL;
- int fd;
-
- if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
-#ifndef ENGINE_DEVCRYPTO_DEBUG
- if (errno != ENOENT)
-#endif
- fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
- return;
- }
-
-#ifdef CRIOGET
- if (ioctl(fd, CRIOGET, &cfd) < 0) {
- fprintf(stderr, "Could not create crypto fd: %s\n", strerror(errno));
- close(fd);
- cfd = -1;
- return;
- }
- close(fd);
-#else
- cfd = fd;
-#endif
-
- if ((e = ENGINE_new()) == NULL
- || !ENGINE_set_destroy_function(e, devcrypto_unload)) {
- ENGINE_free(e);
- /*
- * We know that devcrypto_unload() won't be called when one of the
- * above two calls have failed, so we close cfd explicitly here to
- * avoid leaking resources.
- */
- close(cfd);
- return;
- }
-
- prepare_cipher_methods();
-#ifdef IMPLEMENT_DIGEST
- prepare_digest_methods();
-#endif
-
- if (!ENGINE_set_id(e, "devcrypto")
- || !ENGINE_set_name(e, "/dev/crypto engine")
-
-/*
- * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD
- * implementations, it seems to only exist in FreeBSD, and regarding the
- * parameters in its crypt_kop, the manual crypto(4) has this to say:
- *
- * The semantics of these arguments are currently undocumented.
- *
- * Reading through the FreeBSD source code doesn't give much more than
- * their CRK_MOD_EXP implementation for ubsec.
- *
- * It doesn't look much better with cryptodev-linux. They have the crypt_kop
- * structure as well as the command (CRK_*) in cryptodev.h, but no support
- * seems to be implemented at all for the moment.
- *
- * At the time of writing, it seems impossible to write proper support for
- * FreeBSD's asym features without some very deep knowledge and access to
- * specific kernel modules.
- *
- * /Richard Levitte, 2017-05-11
- */
-#if 0
-# ifndef OPENSSL_NO_RSA
- || !ENGINE_set_RSA(e, devcrypto_rsa)
-# endif
-# ifndef OPENSSL_NO_DSA
- || !ENGINE_set_DSA(e, devcrypto_dsa)
-# endif
-# ifndef OPENSSL_NO_DH
- || !ENGINE_set_DH(e, devcrypto_dh)
-# endif
-# ifndef OPENSSL_NO_EC
- || !ENGINE_set_EC(e, devcrypto_ec)
-# endif
-#endif
- || !ENGINE_set_ciphers(e, devcrypto_ciphers)
-#ifdef IMPLEMENT_DIGEST
- || !ENGINE_set_digests(e, devcrypto_digests)
-#endif
- ) {
- ENGINE_free(e);
- return;
- }
-
- ENGINE_add(e);
- ENGINE_free(e); /* Loose our local reference */
- ERR_clear_error();
-}
diff --git a/crypto/engine/eng_dyn.c b/crypto/engine/eng_dyn.c
index 27d7b893cdad..6d402927c546 100644
--- a/crypto/engine/eng_dyn.c
+++ b/crypto/engine/eng_dyn.c
@@ -1,12 +1,15 @@
/*
* Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "eng_local.h"
#include "internal/dso.h"
#include <openssl/crypto.h>
@@ -154,22 +157,22 @@ static void dynamic_data_ctx_free_func(void *parent, void *ptr,
static int dynamic_set_data_ctx(ENGINE *e, dynamic_data_ctx **ctx)
{
dynamic_data_ctx *c = OPENSSL_zalloc(sizeof(*c));
- int ret = 1;
+ int ret = 0;
if (c == NULL) {
- ENGINEerr(ENGINE_F_DYNAMIC_SET_DATA_CTX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
return 0;
}
c->dirs = sk_OPENSSL_STRING_new_null();
if (c->dirs == NULL) {
- ENGINEerr(ENGINE_F_DYNAMIC_SET_DATA_CTX, ERR_R_MALLOC_FAILURE);
- OPENSSL_free(c);
- return 0;
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
+ goto end;
}
c->DYNAMIC_F1 = "v_check";
c->DYNAMIC_F2 = "bind_engine";
c->dir_load = 1;
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ goto end;
if ((*ctx = (dynamic_data_ctx *)ENGINE_get_ex_data(e,
dynamic_ex_data_idx))
== NULL) {
@@ -181,11 +184,13 @@ static int dynamic_set_data_ctx(ENGINE *e, dynamic_data_ctx **ctx)
}
}
CRYPTO_THREAD_unlock(global_engine_lock);
+ ret = 1;
/*
* If we lost the race to set the context, c is non-NULL and *ctx is the
* context of the thread that won.
*/
- if (c)
+end:
+ if (c != NULL)
sk_OPENSSL_STRING_free(c->dirs);
OPENSSL_free(c);
return ret;
@@ -207,10 +212,11 @@ static dynamic_data_ctx *dynamic_get_data_ctx(ENGINE *e)
int new_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL,
dynamic_data_ctx_free_func);
if (new_idx == -1) {
- ENGINEerr(ENGINE_F_DYNAMIC_GET_DATA_CTX, ENGINE_R_NO_INDEX);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NO_INDEX);
return NULL;
}
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return NULL;
/* Avoid a race by checking again inside this lock */
if (dynamic_ex_data_idx < 0) {
/* Good, someone didn't beat us to it */
@@ -254,6 +260,8 @@ void engine_load_dynamic_int(void)
ENGINE *toadd = engine_dynamic();
if (!toadd)
return;
+
+ ERR_set_mark();
ENGINE_add(toadd);
/*
* If the "add" worked, it gets a structural reference. So either way, we
@@ -265,7 +273,7 @@ void engine_load_dynamic_int(void)
* already added (eg. someone calling ENGINE_load_blah then calling
* ENGINE_load_builtin_engines() perhaps).
*/
- ERR_clear_error();
+ ERR_pop_to_mark();
}
static int dynamic_init(ENGINE *e)
@@ -292,13 +300,13 @@ static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
int initialised;
if (!ctx) {
- ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_NOT_LOADED);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NOT_LOADED);
return 0;
}
initialised = ((ctx->dynamic_dso == NULL) ? 0 : 1);
/* All our control commands require the ENGINE to be uninitialised */
if (initialised) {
- ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_ALREADY_LOADED);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ALREADY_LOADED);
return 0;
}
switch (cmd) {
@@ -327,7 +335,7 @@ static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
return (ctx->engine_id ? 1 : 0);
case DYNAMIC_CMD_LIST_ADD:
if ((i < 0) || (i > 2)) {
- ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INVALID_ARGUMENT);
return 0;
}
ctx->list_add_value = (int)i;
@@ -336,26 +344,26 @@ static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
return dynamic_load(e, ctx);
case DYNAMIC_CMD_DIR_LOAD:
if ((i < 0) || (i > 2)) {
- ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INVALID_ARGUMENT);
return 0;
}
ctx->dir_load = (int)i;
return 1;
case DYNAMIC_CMD_DIR_ADD:
/* a NULL 'p' or a string of zero-length is the same thing */
- if (!p || (strlen((const char *)p) < 1)) {
- ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT);
+ if (p == NULL || (strlen((const char *)p) < 1)) {
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INVALID_ARGUMENT);
return 0;
}
{
char *tmp_str = OPENSSL_strdup(p);
if (tmp_str == NULL) {
- ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!sk_OPENSSL_STRING_push(ctx->dirs, tmp_str)) {
OPENSSL_free(tmp_str);
- ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
return 0;
}
}
@@ -363,7 +371,7 @@ static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
default:
break;
}
- ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
return 0;
}
@@ -396,18 +404,18 @@ static int int_load(dynamic_data_ctx *ctx)
/*
* Unfortunately the version checker does not distinguish between
* engines built for openssl 1.1.x and openssl 3.x, but loading
- * an engine that is built for openssl 3.x will cause a fatal
- * error. Detect such engines, since EVP_PKEY_get_base_id is exported
- * as a function in openssl 3.x, while it is named EVP_PKEY_base_id
- * in openssl 1.1.x. Therefore we take the presence of that symbol
+ * an engine that is built for openssl 1.1.x will cause a fatal
+ * error. Detect such engines, since EVP_PKEY_base_id is exported
+ * as a function in openssl 1.1.x, while it is named EVP_PKEY_get_base_id
+ * in openssl 3.x. Therefore we take the presence of that symbol
* as an indication that the engine will be incompatible.
*/
-static int using_libcrypto_3(dynamic_data_ctx *ctx)
+static int using_libcrypto_11(dynamic_data_ctx *ctx)
{
int ret;
ERR_set_mark();
- ret = DSO_bind_func(ctx->dynamic_dso, "EVP_PKEY_get_base_id") != NULL;
+ ret = DSO_bind_func(ctx->dynamic_dso, "EVP_PKEY_base_id") != NULL;
ERR_pop_to_mark();
return ret;
@@ -431,7 +439,7 @@ static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx)
DSO_convert_filename(ctx->dynamic_dso, ctx->engine_id);
}
if (!int_load(ctx)) {
- ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_DSO_NOT_FOUND);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_DSO_NOT_FOUND);
DSO_free(ctx->dynamic_dso);
ctx->dynamic_dso = NULL;
return 0;
@@ -444,7 +452,7 @@ static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx)
ctx->bind_engine = NULL;
DSO_free(ctx->dynamic_dso);
ctx->dynamic_dso = NULL;
- ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_DSO_FAILURE);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_DSO_FAILURE);
return 0;
}
/* Do we perform version checking? */
@@ -462,16 +470,15 @@ static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx)
/*
* We fail if the version checker veto'd the load *or* if it is
* deferring to us (by returning its version) and we think it is too
- * old. Also fail if this is engine for openssl 3.x.
+ * old. Also fail if this is engine for openssl 1.1.x.
*/
- if (vcheck_res < OSSL_DYNAMIC_OLDEST || using_libcrypto_3(ctx)) {
+ if (vcheck_res < OSSL_DYNAMIC_OLDEST || using_libcrypto_11(ctx)) {
/* Fail */
ctx->bind_engine = NULL;
ctx->v_check = NULL;
DSO_free(ctx->dynamic_dso);
ctx->dynamic_dso = NULL;
- ENGINEerr(ENGINE_F_DYNAMIC_LOAD,
- ENGINE_R_VERSION_INCOMPATIBILITY);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_VERSION_INCOMPATIBILITY);
return 0;
}
}
@@ -504,7 +511,7 @@ static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx)
ctx->v_check = NULL;
DSO_free(ctx->dynamic_dso);
ctx->dynamic_dso = NULL;
- ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_INIT_FAILED);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INIT_FAILED);
/* Copy the original ENGINE structure back */
memcpy(e, &cpy, sizeof(ENGINE));
return 0;
@@ -520,8 +527,7 @@ static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx)
* created leaks. We just have to fail where we are, after
* the ENGINE has changed.
*/
- ENGINEerr(ENGINE_F_DYNAMIC_LOAD,
- ENGINE_R_CONFLICTING_ENGINE_ID);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_CONFLICTING_ENGINE_ID);
return 0;
}
/* Tolerate */
diff --git a/crypto/engine/eng_err.c b/crypto/engine/eng_err.c
index bd1aefa185ec..17c1b7d008ee 100644
--- a/crypto/engine/eng_err.c
+++ b/crypto/engine/eng_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,72 +10,11 @@
#include <openssl/err.h>
#include <openssl/engineerr.h>
+#include "crypto/engineerr.h"
-#ifndef OPENSSL_NO_ERR
+#ifndef OPENSSL_NO_ENGINE
-static const ERR_STRING_DATA ENGINE_str_functs[] = {
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_DIGEST_UPDATE, 0), "digest_update"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_DYNAMIC_CTRL, 0), "dynamic_ctrl"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_DYNAMIC_GET_DATA_CTX, 0),
- "dynamic_get_data_ctx"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_DYNAMIC_LOAD, 0), "dynamic_load"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_DYNAMIC_SET_DATA_CTX, 0),
- "dynamic_set_data_ctx"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_ADD, 0), "ENGINE_add"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_BY_ID, 0), "ENGINE_by_id"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_CMD_IS_EXECUTABLE, 0),
- "ENGINE_cmd_is_executable"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_CTRL, 0), "ENGINE_ctrl"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_CTRL_CMD, 0), "ENGINE_ctrl_cmd"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_CTRL_CMD_STRING, 0),
- "ENGINE_ctrl_cmd_string"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_FINISH, 0), "ENGINE_finish"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_GET_CIPHER, 0),
- "ENGINE_get_cipher"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_GET_DIGEST, 0),
- "ENGINE_get_digest"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_GET_FIRST, 0),
- "ENGINE_get_first"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_GET_LAST, 0), "ENGINE_get_last"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_GET_NEXT, 0), "ENGINE_get_next"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_GET_PKEY_ASN1_METH, 0),
- "ENGINE_get_pkey_asn1_meth"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_GET_PKEY_METH, 0),
- "ENGINE_get_pkey_meth"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_GET_PREV, 0), "ENGINE_get_prev"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_INIT, 0), "ENGINE_init"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_LIST_ADD, 0), "engine_list_add"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_LIST_REMOVE, 0),
- "engine_list_remove"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_LOAD_PRIVATE_KEY, 0),
- "ENGINE_load_private_key"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, 0),
- "ENGINE_load_public_key"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT, 0),
- "ENGINE_load_ssl_client_cert"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_NEW, 0), "ENGINE_new"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_PKEY_ASN1_FIND_STR, 0),
- "ENGINE_pkey_asn1_find_str"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_REMOVE, 0), "ENGINE_remove"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_SET_DEFAULT_STRING, 0),
- "ENGINE_set_default_string"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_SET_ID, 0), "ENGINE_set_id"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_SET_NAME, 0), "ENGINE_set_name"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_TABLE_REGISTER, 0),
- "engine_table_register"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_UNLOCKED_FINISH, 0),
- "engine_unlocked_finish"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_UP_REF, 0), "ENGINE_up_ref"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_INT_CLEANUP_ITEM, 0),
- "int_cleanup_item"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_INT_CTRL_HELPER, 0), "int_ctrl_helper"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_INT_ENGINE_CONFIGURE, 0),
- "int_engine_configure"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_INT_ENGINE_MODULE_INIT, 0),
- "int_engine_module_init"},
- {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_OSSL_HMAC_INIT, 0), "ossl_hmac_init"},
- {0, NULL}
-};
+# ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA ENGINE_str_reasons[] = {
{ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_ALREADY_LOADED), "already loaded"},
@@ -140,15 +79,16 @@ static const ERR_STRING_DATA ENGINE_str_reasons[] = {
{0, NULL}
};
-#endif
+# endif
-int ERR_load_ENGINE_strings(void)
+int ossl_err_load_ENGINE_strings(void)
{
-#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(ENGINE_str_functs[0].error) == NULL) {
- ERR_load_strings_const(ENGINE_str_functs);
+# ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(ENGINE_str_reasons[0].error) == NULL)
ERR_load_strings_const(ENGINE_str_reasons);
- }
-#endif
+# endif
return 1;
}
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/crypto/engine/eng_fat.c b/crypto/engine/eng_fat.c
index fe231a65f658..0cf27715c5cc 100644
--- a/crypto/engine/eng_fat.c
+++ b/crypto/engine/eng_fat.c
@@ -1,13 +1,16 @@
/*
- * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "eng_local.h"
#include <openssl/conf.h>
@@ -17,10 +20,8 @@ int ENGINE_set_default(ENGINE *e, unsigned int flags)
return 0;
if ((flags & ENGINE_METHOD_DIGESTS) && !ENGINE_set_default_digests(e))
return 0;
-#ifndef OPENSSL_NO_RSA
if ((flags & ENGINE_METHOD_RSA) && !ENGINE_set_default_RSA(e))
return 0;
-#endif
#ifndef OPENSSL_NO_DSA
if ((flags & ENGINE_METHOD_DSA) && !ENGINE_set_default_DSA(e))
return 0;
@@ -82,9 +83,8 @@ int ENGINE_set_default_string(ENGINE *e, const char *def_list)
{
unsigned int flags = 0;
if (!CONF_parse_list(def_list, ',', 1, int_def_cb, &flags)) {
- ENGINEerr(ENGINE_F_ENGINE_SET_DEFAULT_STRING,
- ENGINE_R_INVALID_STRING);
- ERR_add_error_data(2, "str=", def_list);
+ ERR_raise_data(ERR_LIB_ENGINE, ENGINE_R_INVALID_STRING,
+ "str=%s", def_list);
return 0;
}
return ENGINE_set_default(e, flags);
@@ -94,9 +94,7 @@ int ENGINE_register_complete(ENGINE *e)
{
ENGINE_register_ciphers(e);
ENGINE_register_digests(e);
-#ifndef OPENSSL_NO_RSA
ENGINE_register_RSA(e);
-#endif
#ifndef OPENSSL_NO_DSA
ENGINE_register_DSA(e);
#endif
diff --git a/crypto/engine/eng_init.c b/crypto/engine/eng_init.c
index 6c9063f8f681..c204eb189986 100644
--- a/crypto/engine/eng_init.c
+++ b/crypto/engine/eng_init.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "e_os.h"
#include "eng_local.h"
@@ -31,8 +34,8 @@ int engine_unlocked_init(ENGINE *e)
*/
e->struct_ref++;
e->funct_ref++;
- engine_ref_debug(e, 0, 1);
- engine_ref_debug(e, 1, 1);
+ ENGINE_REF_PRINT(e, 0, 1);
+ ENGINE_REF_PRINT(e, 1, 1);
}
return to_return;
}
@@ -54,20 +57,21 @@ int engine_unlocked_finish(ENGINE *e, int unlock_for_handlers)
* to 0 without either calling finish().
*/
e->funct_ref--;
- engine_ref_debug(e, 1, -1);
+ ENGINE_REF_PRINT(e, 1, -1);
if ((e->funct_ref == 0) && e->finish) {
if (unlock_for_handlers)
CRYPTO_THREAD_unlock(global_engine_lock);
to_return = e->finish(e);
if (unlock_for_handlers)
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return 0;
if (!to_return)
return 0;
}
REF_ASSERT_ISNT(e->funct_ref < 0);
/* Release the structural reference too */
if (!engine_free_util(e, 0)) {
- ENGINEerr(ENGINE_F_ENGINE_UNLOCKED_FINISH, ENGINE_R_FINISH_FAILED);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_FINISH_FAILED);
return 0;
}
return to_return;
@@ -78,14 +82,15 @@ int ENGINE_init(ENGINE *e)
{
int ret;
if (e == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_INIT, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
- ENGINEerr(ENGINE_F_ENGINE_INIT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
return 0;
}
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return 0;
ret = engine_unlocked_init(e);
CRYPTO_THREAD_unlock(global_engine_lock);
return ret;
@@ -98,11 +103,12 @@ int ENGINE_finish(ENGINE *e)
if (e == NULL)
return 1;
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return 0;
to_return = engine_unlocked_finish(e, 1);
CRYPTO_THREAD_unlock(global_engine_lock);
if (!to_return) {
- ENGINEerr(ENGINE_F_ENGINE_FINISH, ENGINE_R_FINISH_FAILED);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_FINISH_FAILED);
return 0;
}
return to_return;
diff --git a/crypto/engine/eng_lib.c b/crypto/engine/eng_lib.c
index fb727b787747..05c6a67c1e1b 100644
--- a/crypto/engine/eng_lib.c
+++ b/crypto/engine/eng_lib.c
@@ -1,7 +1,7 @@
/*
* Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -20,8 +20,6 @@ CRYPTO_ONCE engine_lock_init = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE(do_engine_lock_init)
{
- if (!OPENSSL_init_crypto(0, NULL))
- return 0;
global_engine_lock = CRYPTO_THREAD_lock_new();
return global_engine_lock != NULL;
}
@@ -32,11 +30,11 @@ ENGINE *ENGINE_new(void)
if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)
|| (ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->struct_ref = 1;
- engine_ref_debug(ret, 0, 1);
+ ENGINE_REF_PRINT(ret, 0, 1);
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ENGINE, ret, &ret->ex_data)) {
OPENSSL_free(ret);
return NULL;
@@ -80,7 +78,7 @@ int engine_free_util(ENGINE *e, int not_locked)
CRYPTO_DOWN_REF(&e->struct_ref, &i, global_engine_lock);
else
i = --e->struct_ref;
- engine_ref_debug(e, 0, -1);
+ ENGINE_REF_PRINT(e, 0, -1);
if (i > 0)
return 1;
REF_ASSERT_ISNT(i < 0);
@@ -128,7 +126,7 @@ static ENGINE_CLEANUP_ITEM *int_cleanup_item(ENGINE_CLEANUP_CB *cb)
ENGINE_CLEANUP_ITEM *item;
if ((item = OPENSSL_malloc(sizeof(*item))) == NULL) {
- ENGINEerr(ENGINE_F_INT_CLEANUP_ITEM, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
return NULL;
}
item->cb = cb;
@@ -196,7 +194,7 @@ void *ENGINE_get_ex_data(const ENGINE *e, int idx)
int ENGINE_set_id(ENGINE *e, const char *id)
{
if (id == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_SET_ID, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
e->id = id;
@@ -206,7 +204,7 @@ int ENGINE_set_id(ENGINE *e, const char *id)
int ENGINE_set_name(ENGINE *e, const char *name)
{
if (name == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_SET_NAME, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
e->name = name;
diff --git a/crypto/engine/eng_list.c b/crypto/engine/eng_list.c
index e2e91d297bd6..04c73c762864 100644
--- a/crypto/engine/eng_list.c
+++ b/crypto/engine/eng_list.c
@@ -2,12 +2,15 @@
* Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "eng_local.h"
/*
@@ -57,7 +60,7 @@ static int engine_list_add(ENGINE *e)
ENGINE *iterator = NULL;
if (e == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
iterator = engine_list_head;
@@ -66,13 +69,13 @@ static int engine_list_add(ENGINE *e)
iterator = iterator->next;
}
if (conflict) {
- ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_CONFLICTING_ENGINE_ID);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_CONFLICTING_ENGINE_ID);
return 0;
}
if (engine_list_head == NULL) {
/* We are adding to an empty list. */
if (engine_list_tail) {
- ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_INTERNAL_LIST_ERROR);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
return 0;
}
engine_list_head = e;
@@ -84,7 +87,7 @@ static int engine_list_add(ENGINE *e)
} else {
/* We are adding to the tail of an existing list. */
if ((engine_list_tail == NULL) || (engine_list_tail->next != NULL)) {
- ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_INTERNAL_LIST_ERROR);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
return 0;
}
engine_list_tail->next = e;
@@ -94,7 +97,7 @@ static int engine_list_add(ENGINE *e)
* Having the engine in the list assumes a structural reference.
*/
e->struct_ref++;
- engine_ref_debug(e, 0, 1);
+ ENGINE_REF_PRINT(e, 0, 1);
/* However it came to be, e is the last item in the list. */
engine_list_tail = e;
e->next = NULL;
@@ -106,7 +109,7 @@ static int engine_list_remove(ENGINE *e)
ENGINE *iterator;
if (e == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_LIST_REMOVE, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
/* We need to check that e is in our linked list! */
@@ -114,8 +117,7 @@ static int engine_list_remove(ENGINE *e)
while (iterator && (iterator != e))
iterator = iterator->next;
if (iterator == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_LIST_REMOVE,
- ENGINE_R_ENGINE_IS_NOT_IN_LIST);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ENGINE_IS_NOT_IN_LIST);
return 0;
}
/* un-link e from the chain. */
@@ -217,15 +219,16 @@ ENGINE *ENGINE_get_first(void)
ENGINE *ret;
if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
- ENGINEerr(ENGINE_F_ENGINE_GET_FIRST, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
return NULL;
}
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return NULL;
ret = engine_list_head;
if (ret) {
ret->struct_ref++;
- engine_ref_debug(ret, 0, 1);
+ ENGINE_REF_PRINT(ret, 0, 1);
}
CRYPTO_THREAD_unlock(global_engine_lock);
return ret;
@@ -236,15 +239,16 @@ ENGINE *ENGINE_get_last(void)
ENGINE *ret;
if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
- ENGINEerr(ENGINE_F_ENGINE_GET_LAST, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
return NULL;
}
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return NULL;
ret = engine_list_tail;
if (ret) {
ret->struct_ref++;
- engine_ref_debug(ret, 0, 1);
+ ENGINE_REF_PRINT(ret, 0, 1);
}
CRYPTO_THREAD_unlock(global_engine_lock);
return ret;
@@ -255,15 +259,16 @@ ENGINE *ENGINE_get_next(ENGINE *e)
{
ENGINE *ret = NULL;
if (e == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_GET_NEXT, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
}
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return NULL;
ret = e->next;
if (ret) {
/* Return a valid structural reference to the next ENGINE */
ret->struct_ref++;
- engine_ref_debug(ret, 0, 1);
+ ENGINE_REF_PRINT(ret, 0, 1);
}
CRYPTO_THREAD_unlock(global_engine_lock);
/* Release the structural reference to the previous ENGINE */
@@ -275,15 +280,16 @@ ENGINE *ENGINE_get_prev(ENGINE *e)
{
ENGINE *ret = NULL;
if (e == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_GET_PREV, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
}
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return NULL;
ret = e->prev;
if (ret) {
/* Return a valid structural reference to the next ENGINE */
ret->struct_ref++;
- engine_ref_debug(ret, 0, 1);
+ ENGINE_REF_PRINT(ret, 0, 1);
}
CRYPTO_THREAD_unlock(global_engine_lock);
/* Release the structural reference to the previous ENGINE */
@@ -296,16 +302,17 @@ int ENGINE_add(ENGINE *e)
{
int to_return = 1;
if (e == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_ADD, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if ((e->id == NULL) || (e->name == NULL)) {
- ENGINEerr(ENGINE_F_ENGINE_ADD, ENGINE_R_ID_OR_NAME_MISSING);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ID_OR_NAME_MISSING);
return 0;
}
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return 0;
if (!engine_list_add(e)) {
- ENGINEerr(ENGINE_F_ENGINE_ADD, ENGINE_R_INTERNAL_LIST_ERROR);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
to_return = 0;
}
CRYPTO_THREAD_unlock(global_engine_lock);
@@ -317,12 +324,13 @@ int ENGINE_remove(ENGINE *e)
{
int to_return = 1;
if (e == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_REMOVE, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return 0;
if (!engine_list_remove(e)) {
- ENGINEerr(ENGINE_F_ENGINE_REMOVE, ENGINE_R_INTERNAL_LIST_ERROR);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
to_return = 0;
}
CRYPTO_THREAD_unlock(global_engine_lock);
@@ -333,9 +341,7 @@ static void engine_cpy(ENGINE *dest, const ENGINE *src)
{
dest->id = src->id;
dest->name = src->name;
-#ifndef OPENSSL_NO_RSA
dest->rsa_meth = src->rsa_meth;
-#endif
#ifndef OPENSSL_NO_DSA
dest->dsa_meth = src->dsa_meth;
#endif
@@ -366,15 +372,18 @@ ENGINE *ENGINE_by_id(const char *id)
ENGINE *iterator;
char *load_dir = NULL;
if (id == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
+ ENGINE_load_builtin_engines();
+
if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
- ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
return NULL;
}
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return NULL;
iterator = engine_list_head;
while (iterator && (strcmp(id, iterator->id) != 0))
iterator = iterator->next;
@@ -394,7 +403,7 @@ ENGINE *ENGINE_by_id(const char *id)
}
} else {
iterator->struct_ref++;
- engine_ref_debug(iterator, 0, 1);
+ ENGINE_REF_PRINT(iterator, 0, 1);
}
}
CRYPTO_THREAD_unlock(global_engine_lock);
@@ -418,8 +427,7 @@ ENGINE *ENGINE_by_id(const char *id)
}
notfound:
ENGINE_free(iterator);
- ENGINEerr(ENGINE_F_ENGINE_BY_ID, ENGINE_R_NO_SUCH_ENGINE);
- ERR_add_error_data(2, "id=", id);
+ ERR_raise_data(ERR_LIB_ENGINE, ENGINE_R_NO_SUCH_ENGINE, "id=%s", id);
return NULL;
/* EEK! Experimental code ends */
}
@@ -428,7 +436,7 @@ int ENGINE_up_ref(ENGINE *e)
{
int i;
if (e == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_UP_REF, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
CRYPTO_UP_REF(&e->struct_ref, &i, global_engine_lock);
diff --git a/crypto/engine/eng_local.h b/crypto/engine/eng_local.h
index e271222d76a8..03a86299cf88 100644
--- a/crypto/engine/eng_local.h
+++ b/crypto/engine/eng_local.h
@@ -2,7 +2,7 @@
* Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,6 +11,7 @@
#ifndef OSSL_CRYPTO_ENGINE_ENG_LOCAL_H
# define OSSL_CRYPTO_ENGINE_ENG_LOCAL_H
+# include <openssl/trace.h>
# include "internal/cryptlib.h"
# include "crypto/engine.h"
# include "internal/thread_once.h"
@@ -19,27 +20,20 @@
extern CRYPTO_RWLOCK *global_engine_lock;
/*
- * If we compile with this symbol defined, then both reference counts in the
- * ENGINE structure will be monitored with a line of output on stderr for
- * each change. This prints the engine's pointer address (truncated to
- * unsigned int), "struct" or "funct" to indicate the reference type, the
- * before and after reference count, and the file:line-number pair. The
- * "engine_ref_debug" statements must come *after* the change.
+ * This prints the engine's pointer address, "struct" or "funct" to
+ * indicate the reference type, the before and after reference count, and
+ * the file:line-number pair. The "ENGINE_REF_PRINT" statements must come
+ * *after* the change.
*/
-# ifdef ENGINE_REF_COUNT_DEBUG
-
-# define engine_ref_debug(e, isfunct, diff) \
- fprintf(stderr, "engine: %08x %s from %d to %d (%s:%d)\n", \
- (unsigned int)(e), (isfunct ? "funct" : "struct"), \
- ((isfunct) ? ((e)->funct_ref - (diff)) : ((e)->struct_ref - (diff))), \
- ((isfunct) ? (e)->funct_ref : (e)->struct_ref), \
- (OPENSSL_FILE), (OPENSSL_LINE))
-
-# else
-
-# define engine_ref_debug(e, isfunct, diff)
-
-# endif
+# define ENGINE_REF_PRINT(e, isfunct, diff) \
+ OSSL_TRACE6(ENGINE_REF_COUNT, \
+ "engine: %p %s from %d to %d (%s:%d)\n", \
+ (void *)(e), (isfunct ? "funct" : "struct"), \
+ ((isfunct) \
+ ? ((e)->funct_ref - (diff)) \
+ : ((e)->struct_ref - (diff))), \
+ ((isfunct) ? (e)->funct_ref : (e)->struct_ref), \
+ (OPENSSL_FILE), (OPENSSL_LINE))
/*
* Any code that will need cleanup operations should use these functions to
@@ -59,14 +53,6 @@ void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb);
DEFINE_STACK_OF(ENGINE)
/*
- * If this symbol is defined then engine_table_select(), the function that is
- * used by RSA, DSA (etc) code to select registered ENGINEs, cache defaults
- * and functional references (etc), will display debugging summaries to
- * stderr.
- */
-/* #define ENGINE_TABLE_DEBUG */
-
-/*
* This represents an implementation table. Dependent code should instantiate
* it as a (ENGINE_TABLE *) pointer value set initially to NULL.
*/
@@ -76,13 +62,8 @@ int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup,
int setdefault);
void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e);
void engine_table_cleanup(ENGINE_TABLE **table);
-# ifndef ENGINE_TABLE_DEBUG
-ENGINE *engine_table_select(ENGINE_TABLE **table, int nid);
-# else
-ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f,
- int l);
-# define engine_table_select(t,n) engine_table_select_tmp(t,n,OPENSSL_FILE,OPENSSL_LINE)
-# endif
+ENGINE *ossl_engine_table_select(ENGINE_TABLE **table, int nid,
+ const char *f, int l);
typedef void (engine_table_doall_cb) (int nid, STACK_OF(ENGINE) *sk,
ENGINE *def, void *arg);
void engine_table_doall(ENGINE_TABLE *table, engine_table_doall_cb *cb,
diff --git a/crypto/engine/eng_openssl.c b/crypto/engine/eng_openssl.c
index 25631fb879ee..91656e6b8084 100644
--- a/crypto/engine/eng_openssl.c
+++ b/crypto/engine/eng_openssl.c
@@ -1,13 +1,22 @@
/*
- * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+/*
+ * RC4 and SHA-1 low level APIs and EVP _meth_ APISs are deprecated for public
+ * use, but still ok for internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <openssl/crypto.h>
#include "internal/cryptlib.h"
@@ -89,9 +98,7 @@ static int bind_helper(ENGINE *e)
|| !ENGINE_set_name(e, engine_openssl_name)
|| !ENGINE_set_destroy_function(e, openssl_destroy)
#ifndef TEST_ENG_OPENSSL_NO_ALGORITHMS
-# ifndef OPENSSL_NO_RSA
|| !ENGINE_set_RSA(e, RSA_get_default_method())
-# endif
# ifndef OPENSSL_NO_DSA
|| !ENGINE_set_DSA(e, DSA_get_default_method())
# endif
@@ -143,13 +150,20 @@ void engine_load_openssl_int(void)
ENGINE *toadd = engine_openssl();
if (!toadd)
return;
+
+ ERR_set_mark();
ENGINE_add(toadd);
/*
* If the "add" worked, it gets a structural reference. So either way, we
* release our just-created reference.
*/
ENGINE_free(toadd);
- ERR_clear_error();
+ /*
+ * If the "add" didn't work, it was probably a conflict because it was
+ * already added (eg. someone calling ENGINE_load_blah then calling
+ * ENGINE_load_builtin_engines() perhaps).
+ */
+ ERR_pop_to_mark();
}
/*
@@ -167,7 +181,7 @@ static int bind_fn(ENGINE *e, const char *id)
}
IMPLEMENT_DYNAMIC_CHECK_FN()
-IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
+ IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
#endif /* ENGINE_DYNAMIC_SUPPORT */
#ifdef TEST_ENG_OPENSSL_RC4
/*-
@@ -191,12 +205,15 @@ typedef struct {
static int test_rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
+ const int n = EVP_CIPHER_CTX_get_key_length(ctx);
+
# ifdef TEST_ENG_OPENSSL_RC4_P_INIT
fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_init_key() called\n");
# endif
- memcpy(&test(ctx)->key[0], key, EVP_CIPHER_CTX_key_length(ctx));
- RC4_set_key(&test(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx),
- test(ctx)->key);
+ if (n <= 0)
+ return n;
+ memcpy(&test(ctx)->key[0], key, n);
+ RC4_set_key(&test(ctx)->ks, n, test(ctx)->key);
return 1;
}
@@ -268,9 +285,9 @@ static int test_cipher_nids(const int **nids)
if (!init) {
const EVP_CIPHER *cipher;
if ((cipher = test_r4_cipher()) != NULL)
- cipher_nids[pos++] = EVP_CIPHER_nid(cipher);
+ cipher_nids[pos++] = EVP_CIPHER_get_nid(cipher);
if ((cipher = test_r4_40_cipher()) != NULL)
- cipher_nids[pos++] = EVP_CIPHER_nid(cipher);
+ cipher_nids[pos++] = EVP_CIPHER_get_nid(cipher);
cipher_nids[pos] = 0;
init = 1;
}
@@ -311,7 +328,7 @@ static int test_sha1_init(EVP_MD_CTX *ctx)
# ifdef TEST_ENG_OPENSSL_SHA_P_INIT
fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_init() called\n");
# endif
- return SHA1_Init(EVP_MD_CTX_md_data(ctx));
+ return SHA1_Init(EVP_MD_CTX_get0_md_data(ctx));
}
static int test_sha1_update(EVP_MD_CTX *ctx, const void *data, size_t count)
@@ -319,7 +336,7 @@ static int test_sha1_update(EVP_MD_CTX *ctx, const void *data, size_t count)
# ifdef TEST_ENG_OPENSSL_SHA_P_UPDATE
fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_update() called\n");
# endif
- return SHA1_Update(EVP_MD_CTX_md_data(ctx), data, count);
+ return SHA1_Update(EVP_MD_CTX_get0_md_data(ctx), data, count);
}
static int test_sha1_final(EVP_MD_CTX *ctx, unsigned char *md)
@@ -327,7 +344,7 @@ static int test_sha1_final(EVP_MD_CTX *ctx, unsigned char *md)
# ifdef TEST_ENG_OPENSSL_SHA_P_FINAL
fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_final() called\n");
# endif
- return SHA1_Final(md, EVP_MD_CTX_md_data(ctx));
+ return SHA1_Final(md, EVP_MD_CTX_get0_md_data(ctx));
}
static EVP_MD *sha1_md = NULL;
@@ -366,7 +383,7 @@ static int test_digest_nids(const int **nids)
if (!init) {
const EVP_MD *md;
if ((md = test_sha_md()) != NULL)
- digest_nids[pos++] = EVP_MD_type(md);
+ digest_nids[pos++] = EVP_MD_get_type(md);
digest_nids[pos] = 0;
init = 1;
}
@@ -434,7 +451,7 @@ static int ossl_hmac_init(EVP_PKEY_CTX *ctx)
OSSL_HMAC_PKEY_CTX *hctx;
if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) {
- ENGINEerr(ENGINE_F_OSSL_HMAC_INIT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
return 0;
}
hctx->ktmp.type = V_ASN1_OCTET_STRING;
@@ -505,7 +522,7 @@ static int ossl_hmac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
static int ossl_int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
{
- OSSL_HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx));
+ OSSL_HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_get_pkey_ctx(ctx));
if (!HMAC_Update(hctx->ctx, data, count))
return 0;
return 1;
@@ -523,7 +540,7 @@ static int ossl_hmac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
{
unsigned int hlen;
OSSL_HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
- int l = EVP_MD_CTX_size(mctx);
+ int l = EVP_MD_CTX_get_size(mctx);
if (l < 0)
return 0;
@@ -622,7 +639,8 @@ static int ossl_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
EVP_PKEY_HMAC,
0
};
- if (!pmeth) {
+
+ if (pmeth == NULL) {
*nids = ossl_pkey_nids;
return 1;
}
diff --git a/crypto/engine/eng_pkey.c b/crypto/engine/eng_pkey.c
index e813bc6db0e6..6e6d6df35b2b 100644
--- a/crypto/engine/eng_pkey.c
+++ b/crypto/engine/eng_pkey.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "eng_local.h"
/* Basic get/set stuff */
@@ -56,27 +59,25 @@ EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id,
EVP_PKEY *pkey;
if (e == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY,
- ERR_R_PASSED_NULL_PARAMETER);
- return 0;
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
}
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return NULL;
if (e->funct_ref == 0) {
CRYPTO_THREAD_unlock(global_engine_lock);
- ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY, ENGINE_R_NOT_INITIALISED);
- return 0;
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NOT_INITIALISED);
+ return NULL;
}
CRYPTO_THREAD_unlock(global_engine_lock);
if (!e->load_privkey) {
- ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY,
- ENGINE_R_NO_LOAD_FUNCTION);
- return 0;
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NO_LOAD_FUNCTION);
+ return NULL;
}
pkey = e->load_privkey(e, key_id, ui_method, callback_data);
- if (!pkey) {
- ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY,
- ENGINE_R_FAILED_LOADING_PRIVATE_KEY);
- return 0;
+ if (pkey == NULL) {
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_FAILED_LOADING_PRIVATE_KEY);
+ return NULL;
}
return pkey;
}
@@ -87,26 +88,25 @@ EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id,
EVP_PKEY *pkey;
if (e == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY,
- ERR_R_PASSED_NULL_PARAMETER);
- return 0;
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
}
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return NULL;
if (e->funct_ref == 0) {
CRYPTO_THREAD_unlock(global_engine_lock);
- ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, ENGINE_R_NOT_INITIALISED);
- return 0;
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NOT_INITIALISED);
+ return NULL;
}
CRYPTO_THREAD_unlock(global_engine_lock);
if (!e->load_pubkey) {
- ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, ENGINE_R_NO_LOAD_FUNCTION);
- return 0;
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NO_LOAD_FUNCTION);
+ return NULL;
}
pkey = e->load_pubkey(e, key_id, ui_method, callback_data);
- if (!pkey) {
- ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY,
- ENGINE_R_FAILED_LOADING_PUBLIC_KEY);
- return 0;
+ if (pkey == NULL) {
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_FAILED_LOADING_PUBLIC_KEY);
+ return NULL;
}
return pkey;
}
@@ -118,21 +118,19 @@ int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s,
{
if (e == NULL) {
- ENGINEerr(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT,
- ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return 0;
if (e->funct_ref == 0) {
CRYPTO_THREAD_unlock(global_engine_lock);
- ENGINEerr(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT,
- ENGINE_R_NOT_INITIALISED);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NOT_INITIALISED);
return 0;
}
CRYPTO_THREAD_unlock(global_engine_lock);
if (!e->load_ssl_client_cert) {
- ENGINEerr(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT,
- ENGINE_R_NO_LOAD_FUNCTION);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NO_LOAD_FUNCTION);
return 0;
}
return e->load_ssl_client_cert(e, s, ca_dn, pcert, ppkey, pother,
diff --git a/crypto/engine/eng_rdrand.c b/crypto/engine/eng_rdrand.c
index 9dceb1671099..f46a5145974e 100644
--- a/crypto/engine/eng_rdrand.c
+++ b/crypto/engine/eng_rdrand.c
@@ -1,17 +1,21 @@
/*
- * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <openssl/opensslconf.h>
#include <stdio.h>
#include <string.h>
#include "crypto/engine.h"
+#include "internal/cryptlib.h"
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/crypto.h>
@@ -79,15 +83,23 @@ static ENGINE *ENGINE_rdrand(void)
void engine_load_rdrand_int(void)
{
- extern unsigned int OPENSSL_ia32cap_P[];
-
if (OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) {
ENGINE *toadd = ENGINE_rdrand();
if (!toadd)
return;
+ ERR_set_mark();
ENGINE_add(toadd);
+ /*
+ * If the "add" worked, it gets a structural reference. So either way, we
+ * release our just-created reference.
+ */
ENGINE_free(toadd);
- ERR_clear_error();
+ /*
+ * If the "add" didn't work, it was probably a conflict because it was
+ * already added (eg. someone calling ENGINE_load_blah then calling
+ * ENGINE_load_builtin_engines() perhaps).
+ */
+ ERR_pop_to_mark();
}
}
#else
diff --git a/crypto/engine/eng_table.c b/crypto/engine/eng_table.c
index 72f393dbe143..a8209d9e7176 100644
--- a/crypto/engine/eng_table.c
+++ b/crypto/engine/eng_table.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,6 +10,7 @@
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/lhash.h>
+#include <openssl/trace.h>
#include "eng_local.h"
/* The type of the items in the table */
@@ -85,7 +86,9 @@ int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup,
{
int ret = 0, added = 0;
ENGINE_PILE tmplate, *fnd;
- CRYPTO_THREAD_write_lock(global_engine_lock);
+
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return 0;
if (!(*table))
added = 1;
if (!int_table_check(table, 1))
@@ -126,8 +129,7 @@ int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup,
fnd->uptodate = 0;
if (setdefault) {
if (!engine_unlocked_init(e)) {
- ENGINEerr(ENGINE_F_ENGINE_TABLE_REGISTER,
- ENGINE_R_INIT_FAILED);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INIT_FAILED);
goto end;
}
if (fnd->funct)
@@ -161,7 +163,9 @@ IMPLEMENT_LHASH_DOALL_ARG(ENGINE_PILE, ENGINE);
void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e)
{
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ /* Can't return a value. :( */
+ return;
if (int_table_check(table, 0))
lh_ENGINE_PILE_doall_ENGINE(&(*table)->piles, int_unregister_cb, e);
CRYPTO_THREAD_unlock(global_engine_lock);
@@ -169,7 +173,7 @@ void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e)
static void int_cleanup_cb_doall(ENGINE_PILE *p)
{
- if (!p)
+ if (p == NULL)
return;
sk_ENGINE_free(p->sk);
if (p->funct)
@@ -179,7 +183,8 @@ static void int_cleanup_cb_doall(ENGINE_PILE *p)
void engine_table_cleanup(ENGINE_TABLE **table)
{
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return;
if (*table) {
lh_ENGINE_PILE_doall(&(*table)->piles, int_cleanup_cb_doall);
lh_ENGINE_PILE_free(&(*table)->piles);
@@ -189,29 +194,28 @@ void engine_table_cleanup(ENGINE_TABLE **table)
}
/* return a functional reference for a given 'nid' */
-#ifndef ENGINE_TABLE_DEBUG
-ENGINE *engine_table_select(ENGINE_TABLE **table, int nid)
-#else
-ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f,
- int l)
-#endif
+ENGINE *ossl_engine_table_select(ENGINE_TABLE **table, int nid,
+ const char *f, int l)
{
ENGINE *ret = NULL;
ENGINE_PILE tmplate, *fnd = NULL;
int initres, loop = 0;
+ /* Load the config before trying to check if engines are available */
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+
if (!(*table)) {
-#ifdef ENGINE_TABLE_DEBUG
- fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, nothing "
- "registered!\n", f, l, nid);
-#endif
+ OSSL_TRACE3(ENGINE_TABLE,
+ "%s:%d, nid=%d, nothing registered!\n",
+ f, l, nid);
return NULL;
}
ERR_set_mark();
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ goto end;
/*
* Check again inside the lock otherwise we could race against cleanup
- * operations. But don't worry about a fprintf(stderr).
+ * operations. But don't worry about a debug printout
*/
if (!int_table_check(table, 0))
goto end;
@@ -220,10 +224,9 @@ ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f,
if (!fnd)
goto end;
if (fnd->funct && engine_unlocked_init(fnd->funct)) {
-#ifdef ENGINE_TABLE_DEBUG
- fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using "
- "ENGINE '%s' cached\n", f, l, nid, fnd->funct->id);
-#endif
+ OSSL_TRACE4(ENGINE_TABLE,
+ "%s:%d, nid=%d, using ENGINE '%s' cached\n",
+ f, l, nid, fnd->funct->id);
ret = fnd->funct;
goto end;
}
@@ -234,10 +237,10 @@ ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f,
trynext:
ret = sk_ENGINE_value(fnd->sk, loop++);
if (!ret) {
-#ifdef ENGINE_TABLE_DEBUG
- fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, no "
- "registered implementations would initialise\n", f, l, nid);
-#endif
+ OSSL_TRACE3(ENGINE_TABLE,
+ "%s:%d, nid=%d, "
+ "no registered implementations would initialise\n",
+ f, l, nid);
goto end;
}
/* Try to initialise the ENGINE? */
@@ -252,15 +255,13 @@ ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f,
if (fnd->funct)
engine_unlocked_finish(fnd->funct, 0);
fnd->funct = ret;
-#ifdef ENGINE_TABLE_DEBUG
- fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, "
- "setting default to '%s'\n", f, l, nid, ret->id);
-#endif
+ OSSL_TRACE4(ENGINE_TABLE,
+ "%s:%d, nid=%d, setting default to '%s'\n",
+ f, l, nid, ret->id);
}
-#ifdef ENGINE_TABLE_DEBUG
- fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using "
- "newly initialised '%s'\n", f, l, nid, ret->id);
-#endif
+ OSSL_TRACE4(ENGINE_TABLE,
+ "%s:%d, nid=%d, using newly initialised '%s'\n",
+ f, l, nid, ret->id);
goto end;
}
goto trynext;
@@ -271,14 +272,14 @@ ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f,
*/
if (fnd)
fnd->uptodate = 1;
-#ifdef ENGINE_TABLE_DEBUG
if (ret)
- fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching "
- "ENGINE '%s'\n", f, l, nid, ret->id);
+ OSSL_TRACE4(ENGINE_TABLE,
+ "%s:%d, nid=%d, caching ENGINE '%s'\n",
+ f, l, nid, ret->id);
else
- fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching "
- "'no matching ENGINE'\n", f, l, nid);
-#endif
+ OSSL_TRACE3(ENGINE_TABLE,
+ "%s:%d, nid=%d, caching 'no matching ENGINE'\n",
+ f, l, nid);
CRYPTO_THREAD_unlock(global_engine_lock);
/*
* Whatever happened, any failed init()s are not failures in this
diff --git a/crypto/engine/tb_asnmth.c b/crypto/engine/tb_asnmth.c
index 72850b9398e3..81f8e7add0e7 100644
--- a/crypto/engine/tb_asnmth.c
+++ b/crypto/engine/tb_asnmth.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "e_os.h"
#include "eng_local.h"
#include <openssl/evp.h>
@@ -73,7 +76,8 @@ int ENGINE_set_default_pkey_asn1_meths(ENGINE *e)
*/
ENGINE *ENGINE_get_pkey_asn1_meth_engine(int nid)
{
- return engine_table_select(&pkey_asn1_meth_table, nid);
+ return ossl_engine_table_select(&pkey_asn1_meth_table, nid,
+ OPENSSL_FILE, OPENSSL_LINE);
}
/*
@@ -85,8 +89,7 @@ const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid)
EVP_PKEY_ASN1_METHOD *ret;
ENGINE_PKEY_ASN1_METHS_PTR fn = ENGINE_get_pkey_asn1_meths(e);
if (!fn || !fn(e, &ret, NULL, nid)) {
- ENGINEerr(ENGINE_F_ENGINE_GET_PKEY_ASN1_METH,
- ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD);
return NULL;
}
return ret;
@@ -149,7 +152,7 @@ const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e,
e->pkey_asn1_meths(e, &ameth, NULL, nids[i]);
if (ameth != NULL
&& ((int)strlen(ameth->pem_str) == len)
- && strncasecmp(ameth->pem_str, str, len) == 0)
+ && OPENSSL_strncasecmp(ameth->pem_str, str, len) == 0)
return ameth;
}
return NULL;
@@ -174,7 +177,7 @@ static void look_str_cb(int nid, STACK_OF(ENGINE) *sk, ENGINE *def, void *arg)
e->pkey_asn1_meths(e, &ameth, NULL, nid);
if (ameth != NULL
&& ((int)strlen(ameth->pem_str) == lk->len)
- && strncasecmp(ameth->pem_str, lk->str, lk->len) == 0) {
+ && OPENSSL_strncasecmp(ameth->pem_str, lk->str, lk->len) == 0) {
lk->e = e;
lk->ameth = ameth;
return;
@@ -193,16 +196,17 @@ const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe,
fstr.len = len;
if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
- ENGINEerr(ENGINE_F_ENGINE_PKEY_ASN1_FIND_STR, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
return NULL;
}
- CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return NULL;
engine_table_doall(pkey_asn1_meth_table, look_str_cb, &fstr);
/* If found obtain a structural reference to engine */
if (fstr.e) {
fstr.e->struct_ref++;
- engine_ref_debug(fstr.e, 0, 1);
+ ENGINE_REF_PRINT(fstr.e, 0, 1);
}
*pe = fstr.e;
CRYPTO_THREAD_unlock(global_engine_lock);
diff --git a/crypto/engine/tb_cipher.c b/crypto/engine/tb_cipher.c
index 236da346cd4c..037f5687524f 100644
--- a/crypto/engine/tb_cipher.c
+++ b/crypto/engine/tb_cipher.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "eng_local.h"
static ENGINE_TABLE *cipher_table = NULL;
@@ -62,7 +65,8 @@ int ENGINE_set_default_ciphers(ENGINE *e)
*/
ENGINE *ENGINE_get_cipher_engine(int nid)
{
- return engine_table_select(&cipher_table, nid);
+ return ossl_engine_table_select(&cipher_table, nid,
+ OPENSSL_FILE, OPENSSL_LINE);
}
/* Obtains a cipher implementation from an ENGINE functional reference */
@@ -71,7 +75,7 @@ const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid)
const EVP_CIPHER *ret;
ENGINE_CIPHERS_PTR fn = ENGINE_get_ciphers(e);
if (!fn || !fn(e, &ret, NULL, nid)) {
- ENGINEerr(ENGINE_F_ENGINE_GET_CIPHER, ENGINE_R_UNIMPLEMENTED_CIPHER);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_UNIMPLEMENTED_CIPHER);
return NULL;
}
return ret;
diff --git a/crypto/engine/tb_dh.c b/crypto/engine/tb_dh.c
index a13a13950083..e1fa45685b11 100644
--- a/crypto/engine/tb_dh.c
+++ b/crypto/engine/tb_dh.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "eng_local.h"
static ENGINE_TABLE *dh_table = NULL;
@@ -55,7 +58,8 @@ int ENGINE_set_default_DH(ENGINE *e)
*/
ENGINE *ENGINE_get_default_DH(void)
{
- return engine_table_select(&dh_table, dummy_nid);
+ return ossl_engine_table_select(&dh_table, dummy_nid,
+ OPENSSL_FILE, OPENSSL_LINE);
}
/* Obtains an DH implementation from an ENGINE functional reference */
diff --git a/crypto/engine/tb_digest.c b/crypto/engine/tb_digest.c
index a6e6337a01d9..dcc70eca4587 100644
--- a/crypto/engine/tb_digest.c
+++ b/crypto/engine/tb_digest.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "eng_local.h"
static ENGINE_TABLE *digest_table = NULL;
@@ -62,7 +65,8 @@ int ENGINE_set_default_digests(ENGINE *e)
*/
ENGINE *ENGINE_get_digest_engine(int nid)
{
- return engine_table_select(&digest_table, nid);
+ return ossl_engine_table_select(&digest_table, nid,
+ OPENSSL_FILE, OPENSSL_LINE);
}
/* Obtains a digest implementation from an ENGINE functional reference */
@@ -71,7 +75,7 @@ const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid)
const EVP_MD *ret;
ENGINE_DIGESTS_PTR fn = ENGINE_get_digests(e);
if (!fn || !fn(e, &ret, NULL, nid)) {
- ENGINEerr(ENGINE_F_ENGINE_GET_DIGEST, ENGINE_R_UNIMPLEMENTED_DIGEST);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_UNIMPLEMENTED_DIGEST);
return NULL;
}
return ret;
diff --git a/crypto/engine/tb_dsa.c b/crypto/engine/tb_dsa.c
index 2c77f0f3e151..6de314b7fcbe 100644
--- a/crypto/engine/tb_dsa.c
+++ b/crypto/engine/tb_dsa.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "eng_local.h"
static ENGINE_TABLE *dsa_table = NULL;
@@ -55,7 +58,8 @@ int ENGINE_set_default_DSA(ENGINE *e)
*/
ENGINE *ENGINE_get_default_DSA(void)
{
- return engine_table_select(&dsa_table, dummy_nid);
+ return ossl_engine_table_select(&dsa_table, dummy_nid,
+ OPENSSL_FILE, OPENSSL_LINE);
}
/* Obtains an DSA implementation from an ENGINE functional reference */
diff --git a/crypto/engine/tb_eckey.c b/crypto/engine/tb_eckey.c
index 907d55ae8c44..0394a5bc220a 100644
--- a/crypto/engine/tb_eckey.c
+++ b/crypto/engine/tb_eckey.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "eng_local.h"
static ENGINE_TABLE *dh_table = NULL;
@@ -55,7 +58,8 @@ int ENGINE_set_default_EC(ENGINE *e)
*/
ENGINE *ENGINE_get_default_EC(void)
{
- return engine_table_select(&dh_table, dummy_nid);
+ return ossl_engine_table_select(&dh_table, dummy_nid,
+ OPENSSL_FILE, OPENSSL_LINE);
}
/* Obtains an EC_KEY implementation from an ENGINE functional reference */
diff --git a/crypto/engine/tb_pkmeth.c b/crypto/engine/tb_pkmeth.c
index c5c001c5cbec..5c3da1136d2b 100644
--- a/crypto/engine/tb_pkmeth.c
+++ b/crypto/engine/tb_pkmeth.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some deprecated APIs */
+#include "internal/deprecated.h"
+
#include "eng_local.h"
#include <openssl/evp.h>
@@ -63,7 +66,8 @@ int ENGINE_set_default_pkey_meths(ENGINE *e)
*/
ENGINE *ENGINE_get_pkey_meth_engine(int nid)
{
- return engine_table_select(&pkey_meth_table, nid);
+ return ossl_engine_table_select(&pkey_meth_table, nid,
+ OPENSSL_FILE, OPENSSL_LINE);
}
/* Obtains a pkey_meth implementation from an ENGINE functional reference */
@@ -72,8 +76,7 @@ const EVP_PKEY_METHOD *ENGINE_get_pkey_meth(ENGINE *e, int nid)
EVP_PKEY_METHOD *ret;
ENGINE_PKEY_METHS_PTR fn = ENGINE_get_pkey_meths(e);
if (!fn || !fn(e, &ret, NULL, nid)) {
- ENGINEerr(ENGINE_F_ENGINE_GET_PKEY_METH,
- ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD);
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD);
return NULL;
}
return ret;
diff --git a/crypto/engine/tb_rand.c b/crypto/engine/tb_rand.c
index 92f61c5a8840..991a4914eafe 100644
--- a/crypto/engine/tb_rand.c
+++ b/crypto/engine/tb_rand.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "eng_local.h"
static ENGINE_TABLE *rand_table = NULL;
@@ -55,7 +58,8 @@ int ENGINE_set_default_RAND(ENGINE *e)
*/
ENGINE *ENGINE_get_default_RAND(void)
{
- return engine_table_select(&rand_table, dummy_nid);
+ return ossl_engine_table_select(&rand_table, dummy_nid,
+ OPENSSL_FILE, OPENSSL_LINE);
}
/* Obtains an RAND implementation from an ENGINE functional reference */
diff --git a/crypto/engine/tb_rsa.c b/crypto/engine/tb_rsa.c
index 43e865e6d6d1..b68b8f0ca74e 100644
--- a/crypto/engine/tb_rsa.c
+++ b/crypto/engine/tb_rsa.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "eng_local.h"
static ENGINE_TABLE *rsa_table = NULL;
@@ -55,7 +58,8 @@ int ENGINE_set_default_RSA(ENGINE *e)
*/
ENGINE *ENGINE_get_default_RSA(void)
{
- return engine_table_select(&rsa_table, dummy_nid);
+ return ossl_engine_table_select(&rsa_table, dummy_nid,
+ OPENSSL_FILE, OPENSSL_LINE);
}
/* Obtains an RSA implementation from an ENGINE functional reference */
diff --git a/crypto/err/README b/crypto/err/README
deleted file mode 100644
index 6d2ce0cd0ee8..000000000000
--- a/crypto/err/README
+++ /dev/null
@@ -1,44 +0,0 @@
-Adding new libraries
---------------------
-
-When adding a new sub-library to OpenSSL, assign it a library number
-ERR_LIB_XXX, define a macro XXXerr() (both in err.h), add its
-name to ERR_str_libraries[] (in crypto/err/err.c), and add
-ERR_load_XXX_strings() to the ERR_load_crypto_strings() function
-(in crypto/err/err_all.c). Finally, add an entry:
-
- L XXX xxx.h xxx_err.c
-
-to crypto/err/openssl.ec, and add xxx_err.c to the Makefile.
-Running make errors will then generate a file xxx_err.c, and
-add all error codes used in the library to xxx.h.
-
-Additionally the library include file must have a certain form.
-Typically it will initially look like this:
-
- #ifndef HEADER_XXX_H
- #define HEADER_XXX_H
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- /* Include files */
-
- #include <openssl/bio.h>
- #include <openssl/x509.h>
-
- /* Macros, structures and function prototypes */
-
-
- /* BEGIN ERROR CODES */
-
-The BEGIN ERROR CODES sequence is used by the error code
-generation script as the point to place new error codes, any text
-after this point will be overwritten when make errors is run.
-The closing #endif etc will be automatically added by the script.
-
-The generated C error code file xxx_err.c will load the header
-files stdio.h, openssl/err.h and openssl/xxx.h so the
-header file must load any additional header files containing any
-definitions it uses.
diff --git a/crypto/err/README.md b/crypto/err/README.md
new file mode 100644
index 000000000000..477dffa2ad32
--- /dev/null
+++ b/crypto/err/README.md
@@ -0,0 +1,55 @@
+Adding new libraries
+====================
+
+When adding a new sub-library to OpenSSL, assign it a library number
+`ERR_LIB_XXX`, define a macro `XXXerr()` (both in `err.h`), add its
+name to `ERR_str_libraries[]` (in `crypto/err/err.c`), and add
+`ERR_load_XXX_strings()` to the `ERR_load_crypto_strings()` function
+(in `crypto/err/err_all.c`). Finally, add an entry:
+
+ L XXX xxx.h xxx_err.c
+
+to `crypto/err/openssl.ec`, and add `xxx_err.c` to the `Makefile`.
+Running make errors will then generate a file `xxx_err.c`, and
+add all error codes used in the library to `xxx.h`.
+
+Additionally the library include file must have a certain form.
+Typically it will initially look like this:
+
+ #ifndef HEADER_XXX_H
+ #define HEADER_XXX_H
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ /* Include files */
+
+ #include <openssl/bio.h>
+ #include <openssl/x509.h>
+
+ /* Macros, structures and function prototypes */
+
+
+ /* BEGIN ERROR CODES */
+
+The `BEGIN ERROR CODES` sequence is used by the error code
+generation script as the point to place new error codes, any text
+after this point will be overwritten when make errors is run.
+The closing `#endif` etc will be automatically added by the script.
+
+The generated C error code file `xxx_err.c` will load the header
+files `stdio.h`, `openssl/err.h` and `openssl/xxx.h` so the
+header file must load any additional header files containing any
+definitions it uses.
+
+Adding new error codes
+======================
+
+Instead of manually adding error codes into `crypto/err/openssl.txt`,
+it is recommended to leverage `make update` for error code generation.
+The target will process relevant sources and generate error codes for
+any *used* error codes.
+
+If an error code is added manually into `crypto/err/openssl.txt`,
+subsequent `make update` has no effect.
diff --git a/crypto/err/build.info b/crypto/err/build.info
index 6163d95b74f3..98f8801e34a6 100644
--- a/crypto/err/build.info
+++ b/crypto/err/build.info
@@ -1,3 +1,3 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
- err.c err_all.c err_prn.c
+ err_blocks.c err.c err_all.c err_all_legacy.c err_prn.c
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 239a3cea9cc2..ec55642308c4 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -1,12 +1,14 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#define OSSL_FORCE_ERR_STATE
+
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
@@ -22,6 +24,10 @@
#include "crypto/ctype.h"
#include "internal/constant_time.h"
#include "e_os.h"
+#include "err_local.h"
+
+/* Forward declaration in case it's not published because of configuration */
+ERR_STATE *ERR_get_state(void);
#ifndef OPENSSL_NO_ERR
static int err_load_strings(const ERR_STRING_DATA *str);
@@ -60,45 +66,26 @@ static ERR_STRING_DATA ERR_str_libraries[] = {
{ERR_PACK(ERR_LIB_UI, 0, 0), "UI routines"},
{ERR_PACK(ERR_LIB_FIPS, 0, 0), "FIPS routines"},
{ERR_PACK(ERR_LIB_CMS, 0, 0), "CMS routines"},
+ {ERR_PACK(ERR_LIB_CRMF, 0, 0), "CRMF routines"},
+ {ERR_PACK(ERR_LIB_CMP, 0, 0), "CMP routines"},
{ERR_PACK(ERR_LIB_HMAC, 0, 0), "HMAC routines"},
{ERR_PACK(ERR_LIB_CT, 0, 0), "CT routines"},
{ERR_PACK(ERR_LIB_ASYNC, 0, 0), "ASYNC routines"},
{ERR_PACK(ERR_LIB_KDF, 0, 0), "KDF routines"},
{ERR_PACK(ERR_LIB_OSSL_STORE, 0, 0), "STORE routines"},
{ERR_PACK(ERR_LIB_SM2, 0, 0), "SM2 routines"},
+ {ERR_PACK(ERR_LIB_ESS, 0, 0), "ESS routines"},
+ {ERR_PACK(ERR_LIB_PROV, 0, 0), "Provider routines"},
+ {ERR_PACK(ERR_LIB_OSSL_ENCODER, 0, 0), "ENCODER routines"},
+ {ERR_PACK(ERR_LIB_OSSL_DECODER, 0, 0), "DECODER routines"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, 0), "HTTP routines"},
{0, NULL},
};
-static ERR_STRING_DATA ERR_str_functs[] = {
- {ERR_PACK(0, SYS_F_FOPEN, 0), "fopen"},
- {ERR_PACK(0, SYS_F_CONNECT, 0), "connect"},
- {ERR_PACK(0, SYS_F_GETSERVBYNAME, 0), "getservbyname"},
- {ERR_PACK(0, SYS_F_SOCKET, 0), "socket"},
- {ERR_PACK(0, SYS_F_IOCTLSOCKET, 0), "ioctlsocket"},
- {ERR_PACK(0, SYS_F_BIND, 0), "bind"},
- {ERR_PACK(0, SYS_F_LISTEN, 0), "listen"},
- {ERR_PACK(0, SYS_F_ACCEPT, 0), "accept"},
-#ifdef OPENSSL_SYS_WINDOWS
- {ERR_PACK(0, SYS_F_WSASTARTUP, 0), "WSAstartup"},
-#endif
- {ERR_PACK(0, SYS_F_OPENDIR, 0), "opendir"},
- {ERR_PACK(0, SYS_F_FREAD, 0), "fread"},
- {ERR_PACK(0, SYS_F_GETADDRINFO, 0), "getaddrinfo"},
- {ERR_PACK(0, SYS_F_GETNAMEINFO, 0), "getnameinfo"},
- {ERR_PACK(0, SYS_F_SETSOCKOPT, 0), "setsockopt"},
- {ERR_PACK(0, SYS_F_GETSOCKOPT, 0), "getsockopt"},
- {ERR_PACK(0, SYS_F_GETSOCKNAME, 0), "getsockname"},
- {ERR_PACK(0, SYS_F_GETHOSTBYNAME, 0), "gethostbyname"},
- {ERR_PACK(0, SYS_F_FFLUSH, 0), "fflush"},
- {ERR_PACK(0, SYS_F_OPEN, 0), "open"},
- {ERR_PACK(0, SYS_F_CLOSE, 0), "close"},
- {ERR_PACK(0, SYS_F_IOCTL, 0), "ioctl"},
- {ERR_PACK(0, SYS_F_STAT, 0), "stat"},
- {ERR_PACK(0, SYS_F_FCNTL, 0), "fcntl"},
- {ERR_PACK(0, SYS_F_FSTAT, 0), "fstat"},
- {0, NULL},
-};
-
+/*
+ * Should make sure that all ERR_R_ reasons defined in include/openssl/err.h.in
+ * are listed. For maintainability, please keep all reasons in the same order.
+ */
static ERR_STRING_DATA ERR_str_reasons[] = {
{ERR_R_SYS_LIB, "system lib"},
{ERR_R_BN_LIB, "BN lib"},
@@ -111,17 +98,16 @@ static ERR_STRING_DATA ERR_str_reasons[] = {
{ERR_R_DSA_LIB, "DSA lib"},
{ERR_R_X509_LIB, "X509 lib"},
{ERR_R_ASN1_LIB, "ASN1 lib"},
+ {ERR_R_CRYPTO_LIB, "CRYPTO lib"},
{ERR_R_EC_LIB, "EC lib"},
{ERR_R_BIO_LIB, "BIO lib"},
{ERR_R_PKCS7_LIB, "PKCS7 lib"},
{ERR_R_X509V3_LIB, "X509V3 lib"},
{ERR_R_ENGINE_LIB, "ENGINE lib"},
{ERR_R_UI_LIB, "UI lib"},
- {ERR_R_OSSL_STORE_LIB, "STORE lib"},
{ERR_R_ECDSA_LIB, "ECDSA lib"},
-
- {ERR_R_NESTED_ASN1_ERROR, "nested asn1 error"},
- {ERR_R_MISSING_ASN1_EOS, "missing asn1 eos"},
+ {ERR_R_OSSL_STORE_LIB, "OSSL_STORE lib"},
+ {ERR_R_OSSL_DECODER_LIB, "OSSL_DECODER lib"},
{ERR_R_FATAL, "fatal"},
{ERR_R_MALLOC_FAILURE, "malloc failure"},
@@ -133,7 +119,22 @@ static ERR_STRING_DATA ERR_str_reasons[] = {
{ERR_R_INIT_FAIL, "init fail"},
{ERR_R_PASSED_INVALID_ARGUMENT, "passed invalid argument"},
{ERR_R_OPERATION_FAIL, "operation fail"},
-
+ {ERR_R_INVALID_PROVIDER_FUNCTIONS, "invalid provider functions"},
+ {ERR_R_INTERRUPTED_OR_CANCELLED, "interrupted or cancelled"},
+ {ERR_R_NESTED_ASN1_ERROR, "nested asn1 error"},
+ {ERR_R_MISSING_ASN1_EOS, "missing asn1 eos"},
+ /*
+ * Something is unsupported, exactly what is expressed with additional data
+ */
+ {ERR_R_UNSUPPORTED, "unsupported"},
+ /*
+ * A fetch failed for other reasons than the name to be fetched being
+ * unsupported.
+ */
+ {ERR_R_FETCH_FAILED, "fetch failed"},
+ {ERR_R_INVALID_PROPERTY_DEFINITION, "invalid property definition"},
+ {ERR_R_UNABLE_TO_GET_READ_LOCK, "unable to get read lock"},
+ {ERR_R_UNABLE_TO_GET_WRITE_LOCK, "unable to get write lock"},
{0, NULL},
};
#endif
@@ -158,8 +159,13 @@ static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL;
#endif
static int int_err_library_number = ERR_LIB_USER;
-static unsigned long get_error_values(int inc, int top, const char **file,
- int *line, const char **data,
+typedef enum ERR_GET_ACTION_e {
+ EV_POP, EV_PEEK, EV_PEEK_LAST
+} ERR_GET_ACTION;
+
+static unsigned long get_error_values(ERR_GET_ACTION g,
+ const char **file, int *line,
+ const char **func, const char **data,
int *flags);
#ifndef OPENSSL_NO_ERR
@@ -168,7 +174,7 @@ static unsigned long err_string_data_hash(const ERR_STRING_DATA *a)
unsigned long ret, l;
l = a->error;
- ret = l ^ ERR_GET_LIB(l) ^ ERR_GET_FUNC(l);
+ ret = l ^ ERR_GET_LIB(l);
return (ret ^ ret % 19 * 13);
}
@@ -184,108 +190,15 @@ static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d)
{
ERR_STRING_DATA *p = NULL;
- CRYPTO_THREAD_read_lock(err_string_lock);
+ if (!CRYPTO_THREAD_read_lock(err_string_lock))
+ return NULL;
p = lh_ERR_STRING_DATA_retrieve(int_error_hash, d);
CRYPTO_THREAD_unlock(err_string_lock);
return p;
}
-
-/* 2019-05-21: Russian and Ukrainian locales on Linux require more than 6,5 kB */
-# define SPACE_SYS_STR_REASONS 8 * 1024
-# define NUM_SYS_STR_REASONS 127
-
-static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1];
-/*
- * SYS_str_reasons is filled with copies of strerror() results at
- * initialization. 'errno' values up to 127 should cover all usual errors,
- * others will be displayed numerically by ERR_error_string. It is crucial
- * that we have something for each reason code that occurs in
- * ERR_str_reasons, or bogus reason strings will be returned for SYSerr(),
- * which always gets an errno value and never one of those 'standard' reason
- * codes.
- */
-
-static void build_SYS_str_reasons(void)
-{
- /* OPENSSL_malloc cannot be used here, use static storage instead */
- static char strerror_pool[SPACE_SYS_STR_REASONS];
- char *cur = strerror_pool;
- size_t cnt = 0;
- static int init = 1;
- int i;
- int saveerrno = get_last_sys_error();
-
- CRYPTO_THREAD_write_lock(err_string_lock);
- if (!init) {
- CRYPTO_THREAD_unlock(err_string_lock);
- return;
- }
-
- for (i = 1; i <= NUM_SYS_STR_REASONS; i++) {
- ERR_STRING_DATA *str = &SYS_str_reasons[i - 1];
-
- str->error = ERR_PACK(ERR_LIB_SYS, 0, i);
- /*
- * If we have used up all the space in strerror_pool,
- * there's no point in calling openssl_strerror_r()
- */
- if (str->string == NULL && cnt < sizeof(strerror_pool)) {
- if (openssl_strerror_r(i, cur, sizeof(strerror_pool) - cnt)) {
- size_t l = strlen(cur);
-
- str->string = cur;
- cnt += l;
- cur += l;
-
- /*
- * VMS has an unusual quirk of adding spaces at the end of
- * some (most? all?) messages. Lets trim them off.
- */
- while (cur > strerror_pool && ossl_isspace(cur[-1])) {
- cur--;
- cnt--;
- }
- *cur++ = '\0';
- cnt++;
- }
- }
- if (str->string == NULL)
- str->string = "unknown";
- }
-
- /*
- * Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL}, as
- * required by ERR_load_strings.
- */
-
- init = 0;
-
- CRYPTO_THREAD_unlock(err_string_lock);
- /* openssl_strerror_r could change errno, but we want to preserve it */
- set_sys_error(saveerrno);
- err_load_strings(SYS_str_reasons);
-}
#endif
-#define err_clear_data(p, i) \
- do { \
- if ((p)->err_data_flags[i] & ERR_TXT_MALLOCED) {\
- OPENSSL_free((p)->err_data[i]); \
- (p)->err_data[i] = NULL; \
- } \
- (p)->err_data_flags[i] = 0; \
- } while (0)
-
-#define err_clear(p, i) \
- do { \
- err_clear_data(p, i); \
- (p)->err_flags[i] = 0; \
- (p)->err_buffer[i] = 0; \
- (p)->err_file[i] = NULL; \
- (p)->err_line[i] = -1; \
- } while (0)
-
static void ERR_STATE_free(ERR_STATE *s)
{
int i;
@@ -293,14 +206,14 @@ static void ERR_STATE_free(ERR_STATE *s)
if (s == NULL)
return;
for (i = 0; i < ERR_NUM_ERRORS; i++) {
- err_clear_data(s, i);
+ err_clear(s, i, 1);
}
OPENSSL_free(s);
}
DEFINE_RUN_ONCE_STATIC(do_err_strings_init)
{
- if (!OPENSSL_init_crypto(0, NULL))
+ if (!OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL))
return 0;
err_string_lock = CRYPTO_THREAD_lock_new();
if (err_string_lock == NULL)
@@ -342,11 +255,12 @@ static void err_patch(int lib, ERR_STRING_DATA *str)
}
/*
- * Hash in |str| error strings. Assumes the URN_ONCE was done.
+ * Hash in |str| error strings. Assumes the RUN_ONCE was done.
*/
static int err_load_strings(const ERR_STRING_DATA *str)
{
- CRYPTO_THREAD_write_lock(err_string_lock);
+ if (!CRYPTO_THREAD_write_lock(err_string_lock))
+ return 0;
for (; str->error; str++)
(void)lh_ERR_STRING_DATA_insert(int_error_hash,
(ERR_STRING_DATA *)str);
@@ -355,7 +269,7 @@ static int err_load_strings(const ERR_STRING_DATA *str)
}
#endif
-int ERR_load_ERR_strings(void)
+int ossl_err_load_ERR_strings(void)
{
#ifndef OPENSSL_NO_ERR
if (!RUN_ONCE(&err_string_init, do_err_strings_init))
@@ -363,9 +277,6 @@ int ERR_load_ERR_strings(void)
err_load_strings(ERR_str_libraries);
err_load_strings(ERR_str_reasons);
- err_patch(ERR_LIB_SYS, ERR_str_functs);
- err_load_strings(ERR_str_functs);
- build_SYS_str_reasons();
#endif
return 1;
}
@@ -373,7 +284,7 @@ int ERR_load_ERR_strings(void)
int ERR_load_strings(int lib, ERR_STRING_DATA *str)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_load_ERR_strings() == 0)
+ if (ossl_err_load_ERR_strings() == 0)
return 0;
err_patch(lib, str);
@@ -386,7 +297,7 @@ int ERR_load_strings(int lib, ERR_STRING_DATA *str)
int ERR_load_strings_const(const ERR_STRING_DATA *str)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_load_ERR_strings() == 0)
+ if (ossl_err_load_ERR_strings() == 0)
return 0;
err_load_strings(str);
#endif
@@ -400,7 +311,8 @@ int ERR_unload_strings(int lib, ERR_STRING_DATA *str)
if (!RUN_ONCE(&err_string_init, do_err_strings_init))
return 0;
- CRYPTO_THREAD_write_lock(err_string_lock);
+ if (!CRYPTO_THREAD_write_lock(err_string_lock))
+ return 0;
/*
* We don't need to ERR_PACK the lib, since that was done (to
* the table) when it was loaded.
@@ -420,193 +332,199 @@ void err_free_strings_int(void)
/********************************************************/
-void ERR_put_error(int lib, int func, int reason, const char *file, int line)
-{
- ERR_STATE *es;
-
-#ifdef _OSD_POSIX
- /*
- * In the BS2000-OSD POSIX subsystem, the compiler generates path names
- * in the form "*POSIX(/etc/passwd)". This dirty hack strips them to
- * something sensible. @@@ We shouldn't modify a const string, though.
- */
- if (strncmp(file, "*POSIX(", sizeof("*POSIX(") - 1) == 0) {
- char *end;
-
- /* Skip the "*POSIX(" prefix */
- file += sizeof("*POSIX(") - 1;
- end = &file[strlen(file) - 1];
- if (*end == ')')
- *end = '\0';
- /* Optional: use the basename of the path only. */
- if ((end = strrchr(file, '/')) != NULL)
- file = &end[1];
- }
-#endif
- es = ERR_get_state();
- if (es == NULL)
- return;
-
- es->top = (es->top + 1) % ERR_NUM_ERRORS;
- if (es->top == es->bottom)
- es->bottom = (es->bottom + 1) % ERR_NUM_ERRORS;
- es->err_flags[es->top] = 0;
- es->err_buffer[es->top] = ERR_PACK(lib, func, reason);
- es->err_file[es->top] = file;
- es->err_line[es->top] = line;
- err_clear_data(es, es->top);
-}
-
void ERR_clear_error(void)
{
int i;
ERR_STATE *es;
- es = ERR_get_state();
+ es = ossl_err_get_state_int();
if (es == NULL)
return;
for (i = 0; i < ERR_NUM_ERRORS; i++) {
- err_clear(es, i);
+ err_clear(es, i, 0);
}
es->top = es->bottom = 0;
}
unsigned long ERR_get_error(void)
{
- return get_error_values(1, 0, NULL, NULL, NULL, NULL);
+ return get_error_values(EV_POP, NULL, NULL, NULL, NULL, NULL);
+}
+
+unsigned long ERR_get_error_all(const char **file, int *line,
+ const char **func,
+ const char **data, int *flags)
+{
+ return get_error_values(EV_POP, file, line, func, data, flags);
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
unsigned long ERR_get_error_line(const char **file, int *line)
{
- return get_error_values(1, 0, file, line, NULL, NULL);
+ return get_error_values(EV_POP, file, line, NULL, NULL, NULL);
}
unsigned long ERR_get_error_line_data(const char **file, int *line,
const char **data, int *flags)
{
- return get_error_values(1, 0, file, line, data, flags);
+ return get_error_values(EV_POP, file, line, NULL, data, flags);
}
+#endif
unsigned long ERR_peek_error(void)
{
- return get_error_values(0, 0, NULL, NULL, NULL, NULL);
+ return get_error_values(EV_PEEK, NULL, NULL, NULL, NULL, NULL);
}
unsigned long ERR_peek_error_line(const char **file, int *line)
{
- return get_error_values(0, 0, file, line, NULL, NULL);
+ return get_error_values(EV_PEEK, file, line, NULL, NULL, NULL);
}
+unsigned long ERR_peek_error_func(const char **func)
+{
+ return get_error_values(EV_PEEK, NULL, NULL, func, NULL, NULL);
+}
+
+unsigned long ERR_peek_error_data(const char **data, int *flags)
+{
+ return get_error_values(EV_PEEK, NULL, NULL, NULL, data, flags);
+}
+
+unsigned long ERR_peek_error_all(const char **file, int *line,
+ const char **func,
+ const char **data, int *flags)
+{
+ return get_error_values(EV_PEEK, file, line, func, data, flags);
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
unsigned long ERR_peek_error_line_data(const char **file, int *line,
const char **data, int *flags)
{
- return get_error_values(0, 0, file, line, data, flags);
+ return get_error_values(EV_PEEK, file, line, NULL, data, flags);
}
+#endif
unsigned long ERR_peek_last_error(void)
{
- return get_error_values(0, 1, NULL, NULL, NULL, NULL);
+ return get_error_values(EV_PEEK_LAST, NULL, NULL, NULL, NULL, NULL);
}
unsigned long ERR_peek_last_error_line(const char **file, int *line)
{
- return get_error_values(0, 1, file, line, NULL, NULL);
+ return get_error_values(EV_PEEK_LAST, file, line, NULL, NULL, NULL);
+}
+
+unsigned long ERR_peek_last_error_func(const char **func)
+{
+ return get_error_values(EV_PEEK_LAST, NULL, NULL, func, NULL, NULL);
}
+unsigned long ERR_peek_last_error_data(const char **data, int *flags)
+{
+ return get_error_values(EV_PEEK_LAST, NULL, NULL, NULL, data, flags);
+}
+
+unsigned long ERR_peek_last_error_all(const char **file, int *line,
+ const char **func,
+ const char **data, int *flags)
+{
+ return get_error_values(EV_PEEK_LAST, file, line, func, data, flags);
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
const char **data, int *flags)
{
- return get_error_values(0, 1, file, line, data, flags);
+ return get_error_values(EV_PEEK_LAST, file, line, NULL, data, flags);
}
+#endif
-static unsigned long get_error_values(int inc, int top, const char **file,
- int *line, const char **data,
- int *flags)
+static unsigned long get_error_values(ERR_GET_ACTION g,
+ const char **file, int *line,
+ const char **func,
+ const char **data, int *flags)
{
int i = 0;
ERR_STATE *es;
unsigned long ret;
- es = ERR_get_state();
+ es = ossl_err_get_state_int();
if (es == NULL)
return 0;
- if (inc && top) {
- if (file)
- *file = "";
- if (line)
- *line = 0;
- if (data)
- *data = "";
- if (flags)
- *flags = 0;
-
- return ERR_R_INTERNAL_ERROR;
- }
-
+ /*
+ * Clear anything that should have been cleared earlier. We do this
+ * here because this doesn't have constant-time issues.
+ */
while (es->bottom != es->top) {
if (es->err_flags[es->top] & ERR_FLAG_CLEAR) {
- err_clear(es, es->top);
+ err_clear(es, es->top, 0);
es->top = es->top > 0 ? es->top - 1 : ERR_NUM_ERRORS - 1;
continue;
}
i = (es->bottom + 1) % ERR_NUM_ERRORS;
if (es->err_flags[i] & ERR_FLAG_CLEAR) {
es->bottom = i;
- err_clear(es, es->bottom);
+ err_clear(es, es->bottom, 0);
continue;
}
break;
}
+ /* If everything has been cleared, the stack is empty. */
if (es->bottom == es->top)
return 0;
- if (top)
- i = es->top; /* last error */
+ /* Which error, the top of stack (latest one) or the first one? */
+ if (g == EV_PEEK_LAST)
+ i = es->top;
else
- i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */
+ i = (es->bottom + 1) % ERR_NUM_ERRORS;
ret = es->err_buffer[i];
- if (inc) {
+ if (g == EV_POP) {
es->bottom = i;
es->err_buffer[i] = 0;
}
- if (file != NULL && line != NULL) {
- if (es->err_file[i] == NULL) {
- *file = "NA";
- *line = 0;
- } else {
- *file = es->err_file[i];
- *line = es->err_line[i];
- }
+ if (file != NULL) {
+ *file = es->err_file[i];
+ if (*file == NULL)
+ *file = "";
}
-
+ if (line != NULL)
+ *line = es->err_line[i];
+ if (func != NULL) {
+ *func = es->err_func[i];
+ if (*func == NULL)
+ *func = "";
+ }
+ if (flags != NULL)
+ *flags = es->err_data_flags[i];
if (data == NULL) {
- if (inc) {
- err_clear_data(es, i);
+ if (g == EV_POP) {
+ err_clear_data(es, i, 0);
}
} else {
- if (es->err_data[i] == NULL) {
+ *data = es->err_data[i];
+ if (*data == NULL) {
*data = "";
if (flags != NULL)
*flags = 0;
- } else {
- *data = es->err_data[i];
- if (flags != NULL)
- *flags = es->err_data_flags[i];
}
}
return ret;
}
-void ERR_error_string_n(unsigned long e, char *buf, size_t len)
+void ossl_err_string_int(unsigned long e, const char *func,
+ char *buf, size_t len)
{
- char lsbuf[64], fsbuf[64], rsbuf[64];
- const char *ls, *fs, *rs;
- unsigned long l, f, r;
+ char lsbuf[64], rsbuf[256];
+ const char *ls, *rs = NULL;
+ unsigned long l, r;
if (len == 0)
return;
@@ -618,27 +536,39 @@ void ERR_error_string_n(unsigned long e, char *buf, size_t len)
ls = lsbuf;
}
- fs = ERR_func_error_string(e);
- f = ERR_GET_FUNC(e);
- if (fs == NULL) {
- BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f);
- fs = fsbuf;
- }
-
- rs = ERR_reason_error_string(e);
+ /*
+ * ERR_reason_error_string() can't safely return system error strings,
+ * since it would call openssl_strerror_r(), which needs a buffer for
+ * thread safety. So for system errors, we call openssl_strerror_r()
+ * directly instead.
+ */
r = ERR_GET_REASON(e);
+#ifndef OPENSSL_NO_ERR
+ if (ERR_SYSTEM_ERROR(e)) {
+ if (openssl_strerror_r(r, rsbuf, sizeof(rsbuf)))
+ rs = rsbuf;
+ } else {
+ rs = ERR_reason_error_string(e);
+ }
+#endif
if (rs == NULL) {
BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", r);
rs = rsbuf;
}
- BIO_snprintf(buf, len, "error:%08lX:%s:%s:%s", e, ls, fs, rs);
+ BIO_snprintf(buf, len, "error:%08lX:%s:%s:%s", e, ls, func, rs);
if (strlen(buf) == len - 1) {
/* Didn't fit; use a minimal format. */
- BIO_snprintf(buf, len, "err:%lx:%lx:%lx:%lx", e, l, f, r);
+ BIO_snprintf(buf, len, "err:%lx:%lx:%lx:%lx", e, l, 0L, r);
}
}
+
+void ERR_error_string_n(unsigned long e, char *buf, size_t len)
+{
+ ossl_err_string_int(e, "", buf, len);
+}
+
/*
* ERR_error_string_n should be used instead for ret != NULL as
* ERR_error_string cannot know how large the buffer is
@@ -672,25 +602,12 @@ const char *ERR_lib_error_string(unsigned long e)
#endif
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
const char *ERR_func_error_string(unsigned long e)
{
-#ifndef OPENSSL_NO_ERR
- ERR_STRING_DATA d, *p;
- unsigned long l, f;
-
- if (!RUN_ONCE(&err_string_init, do_err_strings_init)) {
- return NULL;
- }
-
- l = ERR_GET_LIB(e);
- f = ERR_GET_FUNC(e);
- d.error = ERR_PACK(l, f, 0);
- p = int_err_get_item(&d);
- return ((p == NULL) ? NULL : p->string);
-#else
return NULL;
-#endif
}
+#endif
const char *ERR_reason_error_string(unsigned long e)
{
@@ -702,11 +619,19 @@ const char *ERR_reason_error_string(unsigned long e)
return NULL;
}
+ /*
+ * ERR_reason_error_string() can't safely return system error strings,
+ * since openssl_strerror_r() needs a buffer for thread safety, and we
+ * haven't got one that would serve any sensible purpose.
+ */
+ if (ERR_SYSTEM_ERROR(e))
+ return NULL;
+
l = ERR_GET_LIB(e);
r = ERR_GET_REASON(e);
d.error = ERR_PACK(l, 0, r);
p = int_err_get_item(&d);
- if (!p) {
+ if (p == NULL) {
d.error = ERR_PACK(0, 0, r);
p = int_err_get_item(&d);
}
@@ -716,7 +641,7 @@ const char *ERR_reason_error_string(unsigned long e)
#endif
}
-void err_delete_thread_state(void)
+static void err_delete_thread_state(void *unused)
{
ERR_STATE *state = CRYPTO_THREAD_get_local(&err_thread_local);
if (state == NULL)
@@ -726,13 +651,13 @@ void err_delete_thread_state(void)
ERR_STATE_free(state);
}
-#if OPENSSL_API_COMPAT < 0x10100000L
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
void ERR_remove_thread_state(void *dummy)
{
}
#endif
-#if OPENSSL_API_COMPAT < 0x10000000L
+#ifndef OPENSSL_NO_DEPRECATED_1_0_0
void ERR_remove_state(unsigned long pid)
{
}
@@ -744,7 +669,7 @@ DEFINE_RUN_ONCE_STATIC(err_do_init)
return CRYPTO_THREAD_init_local(&err_thread_local, NULL);
}
-ERR_STATE *ERR_get_state(void)
+ERR_STATE *ossl_err_get_state_int(void)
{
ERR_STATE *state;
int saveerrno = get_last_sys_error();
@@ -768,7 +693,7 @@ ERR_STATE *ERR_get_state(void)
return NULL;
}
- if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_ERR_STATE)
+ if (!ossl_init_thread_start(NULL, NULL, err_delete_thread_state)
|| !CRYPTO_THREAD_set_local(&err_thread_local, state)) {
ERR_STATE_free(state);
CRYPTO_THREAD_set_local(&err_thread_local, NULL);
@@ -783,6 +708,14 @@ ERR_STATE *ERR_get_state(void)
return state;
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ERR_STATE *ERR_get_state(void)
+{
+ return ossl_err_get_state_int();
+}
+#endif
+
+
/*
* err_shelve_state returns the current thread local error state
* and freezes the error module until err_unshelve_state is called.
@@ -834,26 +767,24 @@ int ERR_get_next_error_library(void)
if (!RUN_ONCE(&err_string_init, do_err_strings_init))
return 0;
- CRYPTO_THREAD_write_lock(err_string_lock);
+ if (!CRYPTO_THREAD_write_lock(err_string_lock))
+ return 0;
ret = int_err_library_number++;
CRYPTO_THREAD_unlock(err_string_lock);
return ret;
}
-static int err_set_error_data_int(char *data, int flags)
+static int err_set_error_data_int(char *data, size_t size, int flags,
+ int deallocate)
{
ERR_STATE *es;
- int i;
- es = ERR_get_state();
+ es = ossl_err_get_state_int();
if (es == NULL)
return 0;
- i = es->top;
-
- err_clear_data(es, i);
- es->err_data[i] = data;
- es->err_data_flags[i] = flags;
+ err_clear_data(es, es->top, deallocate);
+ err_set_data(es, es->top, data, size, flags);
return 1;
}
@@ -863,8 +794,18 @@ void ERR_set_error_data(char *data, int flags)
/*
* This function is void so we cannot propagate the error return. Since it
* is also in the public API we can't change the return type.
+ *
+ * We estimate the size of the data. If it's not flagged as allocated,
+ * then this is safe, and if it is flagged as allocated, then our size
+ * may be smaller than the actual allocation, but that doesn't matter
+ * too much, the buffer will remain untouched or will eventually be
+ * reallocated to a new size.
+ *
+ * callers should be advised that this function takes over ownership of
+ * the allocated memory, i.e. they can't count on the pointer to remain
+ * valid.
*/
- err_set_error_data_int(data, flags);
+ err_set_error_data_int(data, strlen(data) + 1, flags, 1);
}
void ERR_add_error_data(int num, ...)
@@ -877,34 +818,60 @@ void ERR_add_error_data(int num, ...)
void ERR_add_error_vdata(int num, va_list args)
{
- int i, n, s;
- char *str, *p, *a;
+ int i, len, size;
+ int flags = ERR_TXT_MALLOCED | ERR_TXT_STRING;
+ char *str, *arg;
+ ERR_STATE *es;
- s = 80;
- if ((str = OPENSSL_malloc(s + 1)) == NULL) {
- /* ERRerr(ERR_F_ERR_ADD_ERROR_VDATA, ERR_R_MALLOC_FAILURE); */
+ /* Get the current error data; if an allocated string get it. */
+ es = ossl_err_get_state_int();
+ if (es == NULL)
return;
+ i = es->top;
+
+ /*
+ * If err_data is allocated already, re-use the space.
+ * Otherwise, allocate a small new buffer.
+ */
+ if ((es->err_data_flags[i] & flags) == flags) {
+ str = es->err_data[i];
+ size = es->err_data_size[i];
+
+ /*
+ * To protect the string we just grabbed from tampering by other
+ * functions we may call, or to protect them from freeing a pointer
+ * that may no longer be valid at that point, we clear away the
+ * data pointer and the flags. We will set them again at the end
+ * of this function.
+ */
+ es->err_data[i] = NULL;
+ es->err_data_flags[i] = 0;
+ } else if ((str = OPENSSL_malloc(size = 81)) == NULL) {
+ return;
+ } else {
+ str[0] = '\0';
}
- str[0] = '\0';
-
- n = 0;
- for (i = 0; i < num; i++) {
- a = va_arg(args, char *);
- if (a == NULL)
- a = "<NULL>";
- n += strlen(a);
- if (n > s) {
- s = n + 20;
- p = OPENSSL_realloc(str, s + 1);
+ len = strlen(str);
+
+ while (--num >= 0) {
+ arg = va_arg(args, char *);
+ if (arg == NULL)
+ arg = "<NULL>";
+ len += strlen(arg);
+ if (len >= size) {
+ char *p;
+
+ size = len + 20;
+ p = OPENSSL_realloc(str, size);
if (p == NULL) {
OPENSSL_free(str);
return;
}
str = p;
}
- OPENSSL_strlcat(str, a, (size_t)s + 1);
+ OPENSSL_strlcat(str, arg, (size_t)size);
}
- if (!err_set_error_data_int(str, ERR_TXT_MALLOCED | ERR_TXT_STRING))
+ if (!err_set_error_data_int(str, size, flags, 0))
OPENSSL_free(str);
}
@@ -912,13 +879,13 @@ int ERR_set_mark(void)
{
ERR_STATE *es;
- es = ERR_get_state();
+ es = ossl_err_get_state_int();
if (es == NULL)
return 0;
if (es->bottom == es->top)
return 0;
- es->err_flags[es->top] |= ERR_FLAG_MARK;
+ es->err_marks[es->top]++;
return 1;
}
@@ -926,19 +893,19 @@ int ERR_pop_to_mark(void)
{
ERR_STATE *es;
- es = ERR_get_state();
+ es = ossl_err_get_state_int();
if (es == NULL)
return 0;
while (es->bottom != es->top
- && (es->err_flags[es->top] & ERR_FLAG_MARK) == 0) {
- err_clear(es, es->top);
+ && es->err_marks[es->top] == 0) {
+ err_clear(es, es->top, 0);
es->top = es->top > 0 ? es->top - 1 : ERR_NUM_ERRORS - 1;
}
if (es->bottom == es->top)
return 0;
- es->err_flags[es->top] &= ~ERR_FLAG_MARK;
+ es->err_marks[es->top]--;
return 1;
}
@@ -947,19 +914,19 @@ int ERR_clear_last_mark(void)
ERR_STATE *es;
int top;
- es = ERR_get_state();
+ es = ossl_err_get_state_int();
if (es == NULL)
return 0;
top = es->top;
while (es->bottom != top
- && (es->err_flags[top] & ERR_FLAG_MARK) == 0) {
+ && es->err_marks[top] == 0) {
top = top > 0 ? top - 1 : ERR_NUM_ERRORS - 1;
}
if (es->bottom == top)
return 0;
- es->err_flags[top] &= ~ERR_FLAG_MARK;
+ es->err_marks[top]--;
return 1;
}
@@ -968,7 +935,7 @@ void err_clear_last_constant_time(int clear)
ERR_STATE *es;
int top;
- es = ERR_get_state();
+ es = ossl_err_get_state_int();
if (es == NULL)
return;
diff --git a/crypto/err/err_all.c b/crypto/err/err_all.c
index 7c0a5f0b9c5f..55aa2b8dbd56 100644
--- a/crypto/err/err_all.c
+++ b/crypto/err/err_all.c
@@ -1,100 +1,112 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
-#include "crypto/err.h"
-#include <openssl/asn1err.h>
-#include <openssl/bnerr.h>
-#include <openssl/ecerr.h>
-#include <openssl/buffererr.h>
-#include <openssl/bioerr.h>
-#include <openssl/comperr.h>
-#include <openssl/rsaerr.h>
-#include <openssl/dherr.h>
-#include <openssl/dsaerr.h>
-#include <openssl/evperr.h>
-#include <openssl/objectserr.h>
-#include <openssl/pemerr.h>
-#include <openssl/pkcs7err.h>
-#include <openssl/x509err.h>
-#include <openssl/x509v3err.h>
-#include <openssl/conferr.h>
-#include <openssl/pkcs12err.h>
-#include <openssl/randerr.h>
-#include "internal/dso.h"
-#include <openssl/engineerr.h>
-#include <openssl/uierr.h>
-#include <openssl/ocsperr.h>
#include <openssl/err.h>
-#include <openssl/tserr.h>
-#include <openssl/cmserr.h>
-#include <openssl/cterr.h>
-#include <openssl/asyncerr.h>
-#include <openssl/kdferr.h>
-#include <openssl/storeerr.h>
+#include "crypto/err.h"
+#include "crypto/cryptoerr.h"
+#include "crypto/asn1err.h"
+#include "crypto/bnerr.h"
+#include "crypto/ecerr.h"
+#include "crypto/buffererr.h"
+#include "crypto/bioerr.h"
+#include "crypto/comperr.h"
+#include "crypto/rsaerr.h"
+#include "crypto/dherr.h"
+#include "crypto/dsaerr.h"
+#include "crypto/evperr.h"
+#include "crypto/objectserr.h"
+#include "crypto/pemerr.h"
+#include "crypto/pkcs7err.h"
+#include "crypto/x509err.h"
+#include "crypto/x509v3err.h"
+#include "crypto/conferr.h"
+#include "crypto/pkcs12err.h"
+#include "crypto/randerr.h"
+#include "internal/dsoerr.h"
+#include "crypto/engineerr.h"
+#include "crypto/uierr.h"
+#include "crypto/httperr.h"
+#include "crypto/ocsperr.h"
+#include "crypto/tserr.h"
+#include "crypto/cmserr.h"
+#include "crypto/crmferr.h"
+#include "crypto/cmperr.h"
+#include "crypto/cterr.h"
+#include "crypto/asyncerr.h"
+#include "crypto/storeerr.h"
+#include "crypto/esserr.h"
+#include "internal/propertyerr.h"
+#include "prov/proverr.h"
-int err_load_crypto_strings_int(void)
+int ossl_err_load_crypto_strings(void)
{
- if (
+ if (0
#ifndef OPENSSL_NO_ERR
- ERR_load_ERR_strings() == 0 || /* include error strings for SYSerr */
- ERR_load_BN_strings() == 0 ||
-# ifndef OPENSSL_NO_RSA
- ERR_load_RSA_strings() == 0 ||
-# endif
+ || ossl_err_load_ERR_strings() == 0 /* include error strings for SYSerr */
+ || ossl_err_load_BN_strings() == 0
+ || ossl_err_load_RSA_strings() == 0
# ifndef OPENSSL_NO_DH
- ERR_load_DH_strings() == 0 ||
+ || ossl_err_load_DH_strings() == 0
# endif
- ERR_load_EVP_strings() == 0 ||
- ERR_load_BUF_strings() == 0 ||
- ERR_load_OBJ_strings() == 0 ||
- ERR_load_PEM_strings() == 0 ||
+ || ossl_err_load_EVP_strings() == 0
+ || ossl_err_load_BUF_strings() == 0
+ || ossl_err_load_OBJ_strings() == 0
+ || ossl_err_load_PEM_strings() == 0
# ifndef OPENSSL_NO_DSA
- ERR_load_DSA_strings() == 0 ||
+ || ossl_err_load_DSA_strings() == 0
# endif
- ERR_load_X509_strings() == 0 ||
- ERR_load_ASN1_strings() == 0 ||
- ERR_load_CONF_strings() == 0 ||
- ERR_load_CRYPTO_strings() == 0 ||
+ || ossl_err_load_X509_strings() == 0
+ || ossl_err_load_ASN1_strings() == 0
+ || ossl_err_load_CONF_strings() == 0
+ || ossl_err_load_CRYPTO_strings() == 0
# ifndef OPENSSL_NO_COMP
- ERR_load_COMP_strings() == 0 ||
+ || ossl_err_load_COMP_strings() == 0
# endif
# ifndef OPENSSL_NO_EC
- ERR_load_EC_strings() == 0 ||
+ || ossl_err_load_EC_strings() == 0
# endif
- /* skip ERR_load_SSL_strings() because it is not in this library */
- ERR_load_BIO_strings() == 0 ||
- ERR_load_PKCS7_strings() == 0 ||
- ERR_load_X509V3_strings() == 0 ||
- ERR_load_PKCS12_strings() == 0 ||
- ERR_load_RAND_strings() == 0 ||
- ERR_load_DSO_strings() == 0 ||
+ /* skip ossl_err_load_SSL_strings() because it is not in this library */
+ || ossl_err_load_BIO_strings() == 0
+ || ossl_err_load_PKCS7_strings() == 0
+ || ossl_err_load_X509V3_strings() == 0
+ || ossl_err_load_PKCS12_strings() == 0
+ || ossl_err_load_RAND_strings() == 0
+ || ossl_err_load_DSO_strings() == 0
# ifndef OPENSSL_NO_TS
- ERR_load_TS_strings() == 0 ||
+ || ossl_err_load_TS_strings() == 0
# endif
# ifndef OPENSSL_NO_ENGINE
- ERR_load_ENGINE_strings() == 0 ||
+ || ossl_err_load_ENGINE_strings() == 0
# endif
+ || ossl_err_load_HTTP_strings() == 0
# ifndef OPENSSL_NO_OCSP
- ERR_load_OCSP_strings() == 0 ||
+ || ossl_err_load_OCSP_strings() == 0
# endif
- ERR_load_UI_strings() == 0 ||
+ || ossl_err_load_UI_strings() == 0
# ifndef OPENSSL_NO_CMS
- ERR_load_CMS_strings() == 0 ||
+ || ossl_err_load_CMS_strings() == 0
+# endif
+# ifndef OPENSSL_NO_CRMF
+ || ossl_err_load_CRMF_strings() == 0
+ || ossl_err_load_CMP_strings() == 0
# endif
# ifndef OPENSSL_NO_CT
- ERR_load_CT_strings() == 0 ||
+ || ossl_err_load_CT_strings() == 0
# endif
- ERR_load_ASYNC_strings() == 0 ||
+ || ossl_err_load_ESS_strings() == 0
+ || ossl_err_load_ASYNC_strings() == 0
+ || ossl_err_load_OSSL_STORE_strings() == 0
+ || ossl_err_load_PROP_strings() == 0
+ || ossl_err_load_PROV_strings() == 0
#endif
- ERR_load_KDF_strings() == 0 ||
- ERR_load_OSSL_STORE_strings() == 0)
+ )
return 0;
return 1;
diff --git a/crypto/err/err_all_legacy.c b/crypto/err/err_all_legacy.c
new file mode 100644
index 000000000000..64dd61867d6d
--- /dev/null
+++ b/crypto/err/err_all_legacy.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* This is the C source file where we include this header directly */
+#include <openssl/cryptoerr_legacy.h>
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+
+# include "crypto/err.h"
+# include "crypto/asn1err.h"
+# include "crypto/asyncerr.h"
+# include "crypto/bnerr.h"
+# include "crypto/buffererr.h"
+# include "crypto/bioerr.h"
+# include "crypto/cmserr.h"
+# include "crypto/comperr.h"
+# include "crypto/conferr.h"
+# include "crypto/cryptoerr.h"
+# include "crypto/cterr.h"
+# include "crypto/dherr.h"
+# include "crypto/dsaerr.h"
+# include "internal/dsoerr.h"
+# include "crypto/ecerr.h"
+# include "crypto/engineerr.h"
+# include "crypto/evperr.h"
+# include "crypto/httperr.h"
+# include "crypto/objectserr.h"
+# include "crypto/ocsperr.h"
+# include "crypto/pemerr.h"
+# include "crypto/pkcs12err.h"
+# include "crypto/pkcs7err.h"
+# include "crypto/randerr.h"
+# include "crypto/rsaerr.h"
+# include "crypto/storeerr.h"
+# include "crypto/tserr.h"
+# include "crypto/uierr.h"
+# include "crypto/x509err.h"
+# include "crypto/x509v3err.h"
+
+# ifdef OPENSSL_NO_ERR
+# define IMPLEMENT_LEGACY_ERR_LOAD(lib) \
+ int ERR_load_##lib##_strings(void) \
+ { \
+ return 1; \
+ }
+# else
+# define IMPLEMENT_LEGACY_ERR_LOAD(lib) \
+ int ERR_load_##lib##_strings(void) \
+ { \
+ return ossl_err_load_##lib##_strings(); \
+ }
+# endif
+
+IMPLEMENT_LEGACY_ERR_LOAD(ASN1)
+IMPLEMENT_LEGACY_ERR_LOAD(ASYNC)
+IMPLEMENT_LEGACY_ERR_LOAD(BIO)
+IMPLEMENT_LEGACY_ERR_LOAD(BN)
+IMPLEMENT_LEGACY_ERR_LOAD(BUF)
+# ifndef OPENSSL_NO_CMS
+IMPLEMENT_LEGACY_ERR_LOAD(CMS)
+# endif
+# ifndef OPENSSL_NO_COMP
+IMPLEMENT_LEGACY_ERR_LOAD(COMP)
+# endif
+IMPLEMENT_LEGACY_ERR_LOAD(CONF)
+IMPLEMENT_LEGACY_ERR_LOAD(CRYPTO)
+# ifndef OPENSSL_NO_CT
+IMPLEMENT_LEGACY_ERR_LOAD(CT)
+# endif
+# ifndef OPENSSL_NO_DH
+IMPLEMENT_LEGACY_ERR_LOAD(DH)
+# endif
+# ifndef OPENSSL_NO_DSA
+IMPLEMENT_LEGACY_ERR_LOAD(DSA)
+# endif
+# ifndef OPENSSL_NO_EC
+IMPLEMENT_LEGACY_ERR_LOAD(EC)
+# endif
+# ifndef OPENSSL_NO_ENGINE
+IMPLEMENT_LEGACY_ERR_LOAD(ENGINE)
+# endif
+IMPLEMENT_LEGACY_ERR_LOAD(ERR)
+IMPLEMENT_LEGACY_ERR_LOAD(EVP)
+IMPLEMENT_LEGACY_ERR_LOAD(OBJ)
+# ifndef OPENSSL_NO_OCSP
+IMPLEMENT_LEGACY_ERR_LOAD(OCSP)
+# endif
+IMPLEMENT_LEGACY_ERR_LOAD(PEM)
+IMPLEMENT_LEGACY_ERR_LOAD(PKCS12)
+IMPLEMENT_LEGACY_ERR_LOAD(PKCS7)
+IMPLEMENT_LEGACY_ERR_LOAD(RAND)
+IMPLEMENT_LEGACY_ERR_LOAD(RSA)
+IMPLEMENT_LEGACY_ERR_LOAD(OSSL_STORE)
+# ifndef OPENSSL_NO_TS
+IMPLEMENT_LEGACY_ERR_LOAD(TS)
+# endif
+IMPLEMENT_LEGACY_ERR_LOAD(UI)
+IMPLEMENT_LEGACY_ERR_LOAD(X509)
+IMPLEMENT_LEGACY_ERR_LOAD(X509V3)
+#endif /* OPENSSL_NO_DEPRECATED_3_0 */
diff --git a/crypto/err/err_blocks.c b/crypto/err/err_blocks.c
new file mode 100644
index 000000000000..a658df05766d
--- /dev/null
+++ b/crypto/err/err_blocks.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#define OSSL_FORCE_ERR_STATE
+
+#include <string.h>
+#include <openssl/err.h>
+#include "err_local.h"
+
+void ERR_new(void)
+{
+ ERR_STATE *es;
+
+ es = ossl_err_get_state_int();
+ if (es == NULL)
+ return;
+
+ /* Allocate a slot */
+ err_get_slot(es);
+ err_clear(es, es->top, 0);
+}
+
+void ERR_set_debug(const char *file, int line, const char *func)
+{
+ ERR_STATE *es;
+
+ es = ossl_err_get_state_int();
+ if (es == NULL)
+ return;
+
+ err_set_debug(es, es->top, file, line, func);
+}
+
+void ERR_set_error(int lib, int reason, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ ERR_vset_error(lib, reason, fmt, args);
+ va_end(args);
+}
+
+void ERR_vset_error(int lib, int reason, const char *fmt, va_list args)
+{
+ ERR_STATE *es;
+ char *buf = NULL;
+ size_t buf_size = 0;
+ unsigned long flags = 0;
+ size_t i;
+
+ es = ossl_err_get_state_int();
+ if (es == NULL)
+ return;
+ i = es->top;
+
+ if (fmt != NULL) {
+ int printed_len = 0;
+ char *rbuf = NULL;
+
+ buf = es->err_data[i];
+ buf_size = es->err_data_size[i];
+
+ /*
+ * To protect the string we just grabbed from tampering by other
+ * functions we may call, or to protect them from freeing a pointer
+ * that may no longer be valid at that point, we clear away the
+ * data pointer and the flags. We will set them again at the end
+ * of this function.
+ */
+ es->err_data[i] = NULL;
+ es->err_data_flags[i] = 0;
+
+ /*
+ * Try to maximize the space available. If that fails, we use what
+ * we have.
+ */
+ if (buf_size < ERR_MAX_DATA_SIZE
+ && (rbuf = OPENSSL_realloc(buf, ERR_MAX_DATA_SIZE)) != NULL) {
+ buf = rbuf;
+ buf_size = ERR_MAX_DATA_SIZE;
+ }
+
+ if (buf != NULL) {
+ printed_len = BIO_vsnprintf(buf, buf_size, fmt, args);
+ }
+ if (printed_len < 0)
+ printed_len = 0;
+ if (buf != NULL)
+ buf[printed_len] = '\0';
+
+ /*
+ * Try to reduce the size, but only if we maximized above. If that
+ * fails, we keep what we have.
+ * (According to documentation, realloc leaves the old buffer untouched
+ * if it fails)
+ */
+ if ((rbuf = OPENSSL_realloc(buf, printed_len + 1)) != NULL) {
+ buf = rbuf;
+ buf_size = printed_len + 1;
+ buf[printed_len] = '\0';
+ }
+
+ if (buf != NULL)
+ flags = ERR_TXT_MALLOCED | ERR_TXT_STRING;
+ }
+
+ err_clear_data(es, es->top, 0);
+ err_set_error(es, es->top, lib, reason);
+ if (fmt != NULL)
+ err_set_data(es, es->top, buf, buf_size, flags);
+}
diff --git a/crypto/err/err_local.h b/crypto/err/err_local.h
new file mode 100644
index 000000000000..d4e19dff241b
--- /dev/null
+++ b/crypto/err/err_local.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/e_os2.h>
+
+static ossl_inline void err_get_slot(ERR_STATE *es)
+{
+ es->top = (es->top + 1) % ERR_NUM_ERRORS;
+ if (es->top == es->bottom)
+ es->bottom = (es->bottom + 1) % ERR_NUM_ERRORS;
+}
+
+static ossl_inline void err_clear_data(ERR_STATE *es, size_t i, int deall)
+{
+ if (es->err_data_flags[i] & ERR_TXT_MALLOCED) {
+ if (deall) {
+ OPENSSL_free(es->err_data[i]);
+ es->err_data[i] = NULL;
+ es->err_data_size[i] = 0;
+ es->err_data_flags[i] = 0;
+ } else if (es->err_data[i] != NULL) {
+ es->err_data[i][0] = '\0';
+ es->err_data_flags[i] = ERR_TXT_MALLOCED;
+ }
+ } else {
+ es->err_data[i] = NULL;
+ es->err_data_size[i] = 0;
+ es->err_data_flags[i] = 0;
+ }
+}
+
+static ossl_inline void err_set_error(ERR_STATE *es, size_t i,
+ int lib, int reason)
+{
+ es->err_buffer[i] =
+ lib == ERR_LIB_SYS
+ ? (unsigned int)(ERR_SYSTEM_FLAG | reason)
+ : ERR_PACK(lib, 0, reason);
+}
+
+static ossl_inline void err_set_debug(ERR_STATE *es, size_t i,
+ const char *file, int line,
+ const char *fn)
+{
+ /*
+ * We dup the file and fn strings because they may be provider owned. If the
+ * provider gets unloaded, they may not be valid anymore.
+ */
+ OPENSSL_free(es->err_file[i]);
+ if (file == NULL || file[0] == '\0')
+ es->err_file[i] = NULL;
+ else
+ es->err_file[i] = OPENSSL_strdup(file);
+ es->err_line[i] = line;
+ OPENSSL_free(es->err_func[i]);
+ if (fn == NULL || fn[0] == '\0')
+ es->err_func[i] = NULL;
+ else
+ es->err_func[i] = OPENSSL_strdup(fn);
+}
+
+static ossl_inline void err_set_data(ERR_STATE *es, size_t i,
+ void *data, size_t datasz, int flags)
+{
+ if ((es->err_data_flags[i] & ERR_TXT_MALLOCED) != 0)
+ OPENSSL_free(es->err_data[i]);
+ es->err_data[i] = data;
+ es->err_data_size[i] = datasz;
+ es->err_data_flags[i] = flags;
+}
+
+static ossl_inline void err_clear(ERR_STATE *es, size_t i, int deall)
+{
+ err_clear_data(es, i, (deall));
+ es->err_marks[i] = 0;
+ es->err_flags[i] = 0;
+ es->err_buffer[i] = 0;
+ es->err_line[i] = -1;
+ OPENSSL_free(es->err_file[i]);
+ es->err_file[i] = NULL;
+ OPENSSL_free(es->err_func[i]);
+ es->err_func[i] = NULL;
+}
+
+ERR_STATE *ossl_err_get_state_int(void);
+void ossl_err_string_int(unsigned long e, const char *func,
+ char *buf, size_t len);
diff --git a/crypto/err/err_prn.c b/crypto/err/err_prn.c
index c82e62947ed3..028811eedeee 100644
--- a/crypto/err/err_prn.c
+++ b/crypto/err/err_prn.c
@@ -1,47 +1,168 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#define OSSL_FORCE_ERR_STATE
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/crypto.h>
#include <openssl/buffer.h>
#include <openssl/err.h>
+#include "err_local.h"
+#define ERR_PRINT_BUF_SIZE 4096
void ERR_print_errors_cb(int (*cb) (const char *str, size_t len, void *u),
void *u)
{
+ CRYPTO_THREAD_ID tid = CRYPTO_THREAD_get_current_id();
unsigned long l;
- char buf[256];
- char buf2[4096];
- const char *file, *data;
+ const char *file, *data, *func;
int line, flags;
- /*
- * We don't know what kind of thing CRYPTO_THREAD_ID is. Here is our best
- * attempt to convert it into something we can print.
- */
- union {
- CRYPTO_THREAD_ID tid;
- unsigned long ltid;
- } tid;
-
- tid.ltid = 0;
- tid.tid = CRYPTO_THREAD_get_current_id();
-
- while ((l = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) {
- ERR_error_string_n(l, buf, sizeof(buf));
- BIO_snprintf(buf2, sizeof(buf2), "%lu:%s:%s:%d:%s\n", tid.ltid, buf,
- file, line, (flags & ERR_TXT_STRING) ? data : "");
- if (cb(buf2, strlen(buf2), u) <= 0)
+
+ while ((l = ERR_get_error_all(&file, &line, &func, &data, &flags)) != 0) {
+ char buf[ERR_PRINT_BUF_SIZE] = "";
+ char *hex = NULL;
+ int offset;
+
+ if ((flags & ERR_TXT_STRING) == 0)
+ data = "";
+
+ hex = ossl_buf2hexstr_sep((const unsigned char *)&tid, sizeof(tid), '\0');
+ BIO_snprintf(buf, sizeof(buf), "%s:", hex == NULL ? "<null>" : hex);
+ offset = strlen(buf);
+ ossl_err_string_int(l, func, buf + offset, sizeof(buf) - offset);
+ offset += strlen(buf + offset);
+ BIO_snprintf(buf + offset, sizeof(buf) - offset, ":%s:%d:%s\n",
+ file, line, data);
+ OPENSSL_free(hex);
+ if (cb(buf, strlen(buf), u) <= 0)
break; /* abort outputting the error report */
}
}
+/* auxiliary function for incrementally reporting texts via the error queue */
+static void put_error(int lib, const char *func, int reason,
+ const char *file, int line)
+{
+ ERR_new();
+ ERR_set_debug(file, line, func);
+ ERR_set_error(lib, reason, NULL /* no data here, so fmt is NULL */);
+}
+
+#define TYPICAL_MAX_OUTPUT_BEFORE_DATA 100
+#define MAX_DATA_LEN (ERR_PRINT_BUF_SIZE - TYPICAL_MAX_OUTPUT_BEFORE_DATA)
+void ERR_add_error_txt(const char *separator, const char *txt)
+{
+ const char *file = NULL;
+ int line;
+ const char *func = NULL;
+ const char *data = NULL;
+ int flags;
+ unsigned long err = ERR_peek_last_error();
+
+ if (separator == NULL)
+ separator = "";
+ if (err == 0)
+ put_error(ERR_LIB_NONE, NULL, 0, "", 0);
+
+ do {
+ size_t available_len, data_len;
+ const char *curr = txt, *next = txt;
+ const char *leading_separator = separator;
+ int trailing_separator = 0;
+ char *tmp;
+
+ ERR_peek_last_error_all(&file, &line, &func, &data, &flags);
+ if ((flags & ERR_TXT_STRING) == 0) {
+ data = "";
+ leading_separator = "";
+ }
+ data_len = strlen(data);
+
+ /* workaround for limit of ERR_print_errors_cb() */
+ if (data_len >= MAX_DATA_LEN
+ || strlen(separator) >= (size_t)(MAX_DATA_LEN - data_len))
+ available_len = 0;
+ else
+ available_len = MAX_DATA_LEN - data_len - strlen(separator) - 1;
+ /* MAX_DATA_LEN > available_len >= 0 */
+
+ if (*separator == '\0') {
+ const size_t len_next = strlen(next);
+
+ if (len_next <= available_len) {
+ next += len_next;
+ curr = NULL; /* no need to split */
+ } else {
+ next += available_len;
+ curr = next; /* will split at this point */
+ }
+ } else {
+ while (*next != '\0' && (size_t)(next - txt) <= available_len) {
+ curr = next;
+ next = strstr(curr, separator);
+ if (next != NULL) {
+ next += strlen(separator);
+ trailing_separator = *next == '\0';
+ } else {
+ next = curr + strlen(curr);
+ }
+ }
+ if ((size_t)(next - txt) <= available_len)
+ curr = NULL; /* the above loop implies *next == '\0' */
+ }
+ if (curr != NULL) {
+ /* split error msg at curr since error data would get too long */
+ if (curr != txt) {
+ tmp = OPENSSL_strndup(txt, curr - txt);
+ if (tmp == NULL)
+ return;
+ ERR_add_error_data(2, separator, tmp);
+ OPENSSL_free(tmp);
+ }
+ put_error(ERR_GET_LIB(err), func, err, file, line);
+ txt = curr;
+ } else {
+ if (trailing_separator) {
+ tmp = OPENSSL_strndup(txt, next - strlen(separator) - txt);
+ if (tmp == NULL)
+ return;
+ /* output txt without the trailing separator */
+ ERR_add_error_data(2, leading_separator, tmp);
+ OPENSSL_free(tmp);
+ } else {
+ ERR_add_error_data(2, leading_separator, txt);
+ }
+ txt = next; /* finished */
+ }
+ } while (*txt != '\0');
+}
+
+void ERR_add_error_mem_bio(const char *separator, BIO *bio)
+{
+ if (bio != NULL) {
+ char *str;
+ long len = BIO_get_mem_data(bio, &str);
+
+ if (len > 0) {
+ if (str[len - 1] != '\0') {
+ if (BIO_write(bio, "", 1) <= 0)
+ return;
+
+ len = BIO_get_mem_data(bio, &str);
+ }
+ if (len > 1)
+ ERR_add_error_txt(separator, str);
+ }
+ }
+}
+
static int print_bio(const char *str, size_t len, void *bp)
{
return BIO_write((BIO *)bp, str, len);
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index ba3a46d5b988..49e42550db1a 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -1,1775 +1,10 @@
-# Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
-# Function codes
-ASN1_F_A2D_ASN1_OBJECT:100:a2d_ASN1_OBJECT
-ASN1_F_A2I_ASN1_INTEGER:102:a2i_ASN1_INTEGER
-ASN1_F_A2I_ASN1_STRING:103:a2i_ASN1_STRING
-ASN1_F_APPEND_EXP:176:append_exp
-ASN1_F_ASN1_BIO_INIT:113:asn1_bio_init
-ASN1_F_ASN1_BIT_STRING_SET_BIT:183:ASN1_BIT_STRING_set_bit
-ASN1_F_ASN1_CB:177:asn1_cb
-ASN1_F_ASN1_CHECK_TLEN:104:asn1_check_tlen
-ASN1_F_ASN1_COLLECT:106:asn1_collect
-ASN1_F_ASN1_D2I_EX_PRIMITIVE:108:asn1_d2i_ex_primitive
-ASN1_F_ASN1_D2I_FP:109:ASN1_d2i_fp
-ASN1_F_ASN1_D2I_READ_BIO:107:asn1_d2i_read_bio
-ASN1_F_ASN1_DIGEST:184:ASN1_digest
-ASN1_F_ASN1_DO_ADB:110:asn1_do_adb
-ASN1_F_ASN1_DO_LOCK:233:asn1_do_lock
-ASN1_F_ASN1_DUP:111:ASN1_dup
-ASN1_F_ASN1_ENC_SAVE:115:asn1_enc_save
-ASN1_F_ASN1_EX_C2I:204:asn1_ex_c2i
-ASN1_F_ASN1_FIND_END:190:asn1_find_end
-ASN1_F_ASN1_GENERALIZEDTIME_ADJ:216:ASN1_GENERALIZEDTIME_adj
-ASN1_F_ASN1_GENERATE_V3:178:ASN1_generate_v3
-ASN1_F_ASN1_GET_INT64:224:asn1_get_int64
-ASN1_F_ASN1_GET_OBJECT:114:ASN1_get_object
-ASN1_F_ASN1_GET_UINT64:225:asn1_get_uint64
-ASN1_F_ASN1_I2D_BIO:116:ASN1_i2d_bio
-ASN1_F_ASN1_I2D_FP:117:ASN1_i2d_fp
-ASN1_F_ASN1_ITEM_D2I_FP:206:ASN1_item_d2i_fp
-ASN1_F_ASN1_ITEM_DUP:191:ASN1_item_dup
-ASN1_F_ASN1_ITEM_EMBED_D2I:120:asn1_item_embed_d2i
-ASN1_F_ASN1_ITEM_EMBED_NEW:121:asn1_item_embed_new
-ASN1_F_ASN1_ITEM_EX_I2D:144:ASN1_item_ex_i2d
-ASN1_F_ASN1_ITEM_FLAGS_I2D:118:asn1_item_flags_i2d
-ASN1_F_ASN1_ITEM_I2D_BIO:192:ASN1_item_i2d_bio
-ASN1_F_ASN1_ITEM_I2D_FP:193:ASN1_item_i2d_fp
-ASN1_F_ASN1_ITEM_PACK:198:ASN1_item_pack
-ASN1_F_ASN1_ITEM_SIGN:195:ASN1_item_sign
-ASN1_F_ASN1_ITEM_SIGN_CTX:220:ASN1_item_sign_ctx
-ASN1_F_ASN1_ITEM_UNPACK:199:ASN1_item_unpack
-ASN1_F_ASN1_ITEM_VERIFY:197:ASN1_item_verify
-ASN1_F_ASN1_MBSTRING_NCOPY:122:ASN1_mbstring_ncopy
-ASN1_F_ASN1_OBJECT_NEW:123:ASN1_OBJECT_new
-ASN1_F_ASN1_OUTPUT_DATA:214:asn1_output_data
-ASN1_F_ASN1_PCTX_NEW:205:ASN1_PCTX_new
-ASN1_F_ASN1_PRIMITIVE_NEW:119:asn1_primitive_new
-ASN1_F_ASN1_SCTX_NEW:221:ASN1_SCTX_new
-ASN1_F_ASN1_SIGN:128:ASN1_sign
-ASN1_F_ASN1_STR2TYPE:179:asn1_str2type
-ASN1_F_ASN1_STRING_GET_INT64:227:asn1_string_get_int64
-ASN1_F_ASN1_STRING_GET_UINT64:230:asn1_string_get_uint64
-ASN1_F_ASN1_STRING_SET:186:ASN1_STRING_set
-ASN1_F_ASN1_STRING_TABLE_ADD:129:ASN1_STRING_TABLE_add
-ASN1_F_ASN1_STRING_TO_BN:228:asn1_string_to_bn
-ASN1_F_ASN1_STRING_TYPE_NEW:130:ASN1_STRING_type_new
-ASN1_F_ASN1_TEMPLATE_EX_D2I:132:asn1_template_ex_d2i
-ASN1_F_ASN1_TEMPLATE_NEW:133:asn1_template_new
-ASN1_F_ASN1_TEMPLATE_NOEXP_D2I:131:asn1_template_noexp_d2i
-ASN1_F_ASN1_TIME_ADJ:217:ASN1_TIME_adj
-ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING:134:ASN1_TYPE_get_int_octetstring
-ASN1_F_ASN1_TYPE_GET_OCTETSTRING:135:ASN1_TYPE_get_octetstring
-ASN1_F_ASN1_UTCTIME_ADJ:218:ASN1_UTCTIME_adj
-ASN1_F_ASN1_VERIFY:137:ASN1_verify
-ASN1_F_B64_READ_ASN1:209:b64_read_asn1
-ASN1_F_B64_WRITE_ASN1:210:B64_write_ASN1
-ASN1_F_BIO_NEW_NDEF:208:BIO_new_NDEF
-ASN1_F_BITSTR_CB:180:bitstr_cb
-ASN1_F_BN_TO_ASN1_STRING:229:bn_to_asn1_string
-ASN1_F_C2I_ASN1_BIT_STRING:189:c2i_ASN1_BIT_STRING
-ASN1_F_C2I_ASN1_INTEGER:194:c2i_ASN1_INTEGER
-ASN1_F_C2I_ASN1_OBJECT:196:c2i_ASN1_OBJECT
-ASN1_F_C2I_IBUF:226:c2i_ibuf
-ASN1_F_C2I_UINT64_INT:101:c2i_uint64_int
-ASN1_F_COLLECT_DATA:140:collect_data
-ASN1_F_D2I_ASN1_OBJECT:147:d2i_ASN1_OBJECT
-ASN1_F_D2I_ASN1_UINTEGER:150:d2i_ASN1_UINTEGER
-ASN1_F_D2I_AUTOPRIVATEKEY:207:d2i_AutoPrivateKey
-ASN1_F_D2I_PRIVATEKEY:154:d2i_PrivateKey
-ASN1_F_D2I_PUBLICKEY:155:d2i_PublicKey
-ASN1_F_DO_BUF:142:do_buf
-ASN1_F_DO_CREATE:124:do_create
-ASN1_F_DO_DUMP:125:do_dump
-ASN1_F_DO_TCREATE:222:do_tcreate
-ASN1_F_I2A_ASN1_OBJECT:126:i2a_ASN1_OBJECT
-ASN1_F_I2D_ASN1_BIO_STREAM:211:i2d_ASN1_bio_stream
-ASN1_F_I2D_ASN1_OBJECT:143:i2d_ASN1_OBJECT
-ASN1_F_I2D_DSA_PUBKEY:161:i2d_DSA_PUBKEY
-ASN1_F_I2D_EC_PUBKEY:181:i2d_EC_PUBKEY
-ASN1_F_I2D_PRIVATEKEY:163:i2d_PrivateKey
-ASN1_F_I2D_PUBLICKEY:164:i2d_PublicKey
-ASN1_F_I2D_RSA_PUBKEY:165:i2d_RSA_PUBKEY
-ASN1_F_LONG_C2I:166:long_c2i
-ASN1_F_NDEF_PREFIX:127:ndef_prefix
-ASN1_F_NDEF_SUFFIX:136:ndef_suffix
-ASN1_F_OID_MODULE_INIT:174:oid_module_init
-ASN1_F_PARSE_TAGGING:182:parse_tagging
-ASN1_F_PKCS5_PBE2_SET_IV:167:PKCS5_pbe2_set_iv
-ASN1_F_PKCS5_PBE2_SET_SCRYPT:231:PKCS5_pbe2_set_scrypt
-ASN1_F_PKCS5_PBE_SET:202:PKCS5_pbe_set
-ASN1_F_PKCS5_PBE_SET0_ALGOR:215:PKCS5_pbe_set0_algor
-ASN1_F_PKCS5_PBKDF2_SET:219:PKCS5_pbkdf2_set
-ASN1_F_PKCS5_SCRYPT_SET:232:pkcs5_scrypt_set
-ASN1_F_SMIME_READ_ASN1:212:SMIME_read_ASN1
-ASN1_F_SMIME_TEXT:213:SMIME_text
-ASN1_F_STABLE_GET:138:stable_get
-ASN1_F_STBL_MODULE_INIT:223:stbl_module_init
-ASN1_F_UINT32_C2I:105:uint32_c2i
-ASN1_F_UINT32_NEW:139:uint32_new
-ASN1_F_UINT64_C2I:112:uint64_c2i
-ASN1_F_UINT64_NEW:141:uint64_new
-ASN1_F_X509_CRL_ADD0_REVOKED:169:X509_CRL_add0_revoked
-ASN1_F_X509_INFO_NEW:170:X509_INFO_new
-ASN1_F_X509_NAME_ENCODE:203:x509_name_encode
-ASN1_F_X509_NAME_EX_D2I:158:x509_name_ex_d2i
-ASN1_F_X509_NAME_EX_NEW:171:x509_name_ex_new
-ASN1_F_X509_PKEY_NEW:173:X509_PKEY_new
-ASYNC_F_ASYNC_CTX_NEW:100:async_ctx_new
-ASYNC_F_ASYNC_INIT_THREAD:101:ASYNC_init_thread
-ASYNC_F_ASYNC_JOB_NEW:102:async_job_new
-ASYNC_F_ASYNC_PAUSE_JOB:103:ASYNC_pause_job
-ASYNC_F_ASYNC_START_FUNC:104:async_start_func
-ASYNC_F_ASYNC_START_JOB:105:ASYNC_start_job
-ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD:106:ASYNC_WAIT_CTX_set_wait_fd
-BIO_F_ACPT_STATE:100:acpt_state
-BIO_F_ADDRINFO_WRAP:148:addrinfo_wrap
-BIO_F_ADDR_STRINGS:134:addr_strings
-BIO_F_BIO_ACCEPT:101:BIO_accept
-BIO_F_BIO_ACCEPT_EX:137:BIO_accept_ex
-BIO_F_BIO_ACCEPT_NEW:152:BIO_ACCEPT_new
-BIO_F_BIO_ADDR_NEW:144:BIO_ADDR_new
-BIO_F_BIO_BIND:147:BIO_bind
-BIO_F_BIO_CALLBACK_CTRL:131:BIO_callback_ctrl
-BIO_F_BIO_CONNECT:138:BIO_connect
-BIO_F_BIO_CONNECT_NEW:153:BIO_CONNECT_new
-BIO_F_BIO_CTRL:103:BIO_ctrl
-BIO_F_BIO_GETS:104:BIO_gets
-BIO_F_BIO_GET_HOST_IP:106:BIO_get_host_ip
-BIO_F_BIO_GET_NEW_INDEX:102:BIO_get_new_index
-BIO_F_BIO_GET_PORT:107:BIO_get_port
-BIO_F_BIO_LISTEN:139:BIO_listen
-BIO_F_BIO_LOOKUP:135:BIO_lookup
-BIO_F_BIO_LOOKUP_EX:143:BIO_lookup_ex
-BIO_F_BIO_MAKE_PAIR:121:bio_make_pair
-BIO_F_BIO_METH_NEW:146:BIO_meth_new
-BIO_F_BIO_NEW:108:BIO_new
-BIO_F_BIO_NEW_DGRAM_SCTP:145:BIO_new_dgram_sctp
-BIO_F_BIO_NEW_FILE:109:BIO_new_file
-BIO_F_BIO_NEW_MEM_BUF:126:BIO_new_mem_buf
-BIO_F_BIO_NREAD:123:BIO_nread
-BIO_F_BIO_NREAD0:124:BIO_nread0
-BIO_F_BIO_NWRITE:125:BIO_nwrite
-BIO_F_BIO_NWRITE0:122:BIO_nwrite0
-BIO_F_BIO_PARSE_HOSTSERV:136:BIO_parse_hostserv
-BIO_F_BIO_PUTS:110:BIO_puts
-BIO_F_BIO_READ:111:BIO_read
-BIO_F_BIO_READ_EX:105:BIO_read_ex
-BIO_F_BIO_READ_INTERN:120:bio_read_intern
-BIO_F_BIO_SOCKET:140:BIO_socket
-BIO_F_BIO_SOCKET_NBIO:142:BIO_socket_nbio
-BIO_F_BIO_SOCK_INFO:141:BIO_sock_info
-BIO_F_BIO_SOCK_INIT:112:BIO_sock_init
-BIO_F_BIO_WRITE:113:BIO_write
-BIO_F_BIO_WRITE_EX:119:BIO_write_ex
-BIO_F_BIO_WRITE_INTERN:128:bio_write_intern
-BIO_F_BUFFER_CTRL:114:buffer_ctrl
-BIO_F_CONN_CTRL:127:conn_ctrl
-BIO_F_CONN_STATE:115:conn_state
-BIO_F_DGRAM_SCTP_NEW:149:dgram_sctp_new
-BIO_F_DGRAM_SCTP_READ:132:dgram_sctp_read
-BIO_F_DGRAM_SCTP_WRITE:133:dgram_sctp_write
-BIO_F_DOAPR_OUTCH:150:doapr_outch
-BIO_F_FILE_CTRL:116:file_ctrl
-BIO_F_FILE_READ:130:file_read
-BIO_F_LINEBUFFER_CTRL:129:linebuffer_ctrl
-BIO_F_LINEBUFFER_NEW:151:linebuffer_new
-BIO_F_MEM_WRITE:117:mem_write
-BIO_F_NBIOF_NEW:154:nbiof_new
-BIO_F_SLG_WRITE:155:slg_write
-BIO_F_SSL_NEW:118:SSL_new
-BN_F_BNRAND:127:bnrand
-BN_F_BNRAND_RANGE:138:bnrand_range
-BN_F_BN_BLINDING_CONVERT_EX:100:BN_BLINDING_convert_ex
-BN_F_BN_BLINDING_CREATE_PARAM:128:BN_BLINDING_create_param
-BN_F_BN_BLINDING_INVERT_EX:101:BN_BLINDING_invert_ex
-BN_F_BN_BLINDING_NEW:102:BN_BLINDING_new
-BN_F_BN_BLINDING_UPDATE:103:BN_BLINDING_update
-BN_F_BN_BN2DEC:104:BN_bn2dec
-BN_F_BN_BN2HEX:105:BN_bn2hex
-BN_F_BN_COMPUTE_WNAF:142:bn_compute_wNAF
-BN_F_BN_CTX_GET:116:BN_CTX_get
-BN_F_BN_CTX_NEW:106:BN_CTX_new
-BN_F_BN_CTX_START:129:BN_CTX_start
-BN_F_BN_DIV:107:BN_div
-BN_F_BN_DIV_RECP:130:BN_div_recp
-BN_F_BN_EXP:123:BN_exp
-BN_F_BN_EXPAND_INTERNAL:120:bn_expand_internal
-BN_F_BN_GENCB_NEW:143:BN_GENCB_new
-BN_F_BN_GENERATE_DSA_NONCE:140:BN_generate_dsa_nonce
-BN_F_BN_GENERATE_PRIME_EX:141:BN_generate_prime_ex
-BN_F_BN_GF2M_MOD:131:BN_GF2m_mod
-BN_F_BN_GF2M_MOD_EXP:132:BN_GF2m_mod_exp
-BN_F_BN_GF2M_MOD_MUL:133:BN_GF2m_mod_mul
-BN_F_BN_GF2M_MOD_SOLVE_QUAD:134:BN_GF2m_mod_solve_quad
-BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR:135:BN_GF2m_mod_solve_quad_arr
-BN_F_BN_GF2M_MOD_SQR:136:BN_GF2m_mod_sqr
-BN_F_BN_GF2M_MOD_SQRT:137:BN_GF2m_mod_sqrt
-BN_F_BN_LSHIFT:145:BN_lshift
-BN_F_BN_MOD_EXP2_MONT:118:BN_mod_exp2_mont
-BN_F_BN_MOD_EXP_MONT:109:BN_mod_exp_mont
-BN_F_BN_MOD_EXP_MONT_CONSTTIME:124:BN_mod_exp_mont_consttime
-BN_F_BN_MOD_EXP_MONT_WORD:117:BN_mod_exp_mont_word
-BN_F_BN_MOD_EXP_RECP:125:BN_mod_exp_recp
-BN_F_BN_MOD_EXP_SIMPLE:126:BN_mod_exp_simple
-BN_F_BN_MOD_INVERSE:110:BN_mod_inverse
-BN_F_BN_MOD_INVERSE_NO_BRANCH:139:BN_mod_inverse_no_branch
-BN_F_BN_MOD_LSHIFT_QUICK:119:BN_mod_lshift_quick
-BN_F_BN_MOD_SQRT:121:BN_mod_sqrt
-BN_F_BN_MONT_CTX_NEW:149:BN_MONT_CTX_new
-BN_F_BN_MPI2BN:112:BN_mpi2bn
-BN_F_BN_NEW:113:BN_new
-BN_F_BN_POOL_GET:147:BN_POOL_get
-BN_F_BN_RAND:114:BN_rand
-BN_F_BN_RAND_RANGE:122:BN_rand_range
-BN_F_BN_RECP_CTX_NEW:150:BN_RECP_CTX_new
-BN_F_BN_RSHIFT:146:BN_rshift
-BN_F_BN_SET_WORDS:144:bn_set_words
-BN_F_BN_STACK_PUSH:148:BN_STACK_push
-BN_F_BN_USUB:115:BN_usub
-BN_F_OSSL_BN_RSA_DO_UNBLIND:151:ossl_bn_rsa_do_unblind
-BUF_F_BUF_MEM_GROW:100:BUF_MEM_grow
-BUF_F_BUF_MEM_GROW_CLEAN:105:BUF_MEM_grow_clean
-BUF_F_BUF_MEM_NEW:101:BUF_MEM_new
-CMS_F_CHECK_CONTENT:99:check_content
-CMS_F_CMS_ADD0_CERT:164:CMS_add0_cert
-CMS_F_CMS_ADD0_RECIPIENT_KEY:100:CMS_add0_recipient_key
-CMS_F_CMS_ADD0_RECIPIENT_PASSWORD:165:CMS_add0_recipient_password
-CMS_F_CMS_ADD1_RECEIPTREQUEST:158:CMS_add1_ReceiptRequest
-CMS_F_CMS_ADD1_RECIPIENT_CERT:101:CMS_add1_recipient_cert
-CMS_F_CMS_ADD1_SIGNER:102:CMS_add1_signer
-CMS_F_CMS_ADD1_SIGNINGTIME:103:cms_add1_signingTime
-CMS_F_CMS_COMPRESS:104:CMS_compress
-CMS_F_CMS_COMPRESSEDDATA_CREATE:105:cms_CompressedData_create
-CMS_F_CMS_COMPRESSEDDATA_INIT_BIO:106:cms_CompressedData_init_bio
-CMS_F_CMS_COPY_CONTENT:107:cms_copy_content
-CMS_F_CMS_COPY_MESSAGEDIGEST:108:cms_copy_messageDigest
-CMS_F_CMS_DATA:109:CMS_data
-CMS_F_CMS_DATAFINAL:110:CMS_dataFinal
-CMS_F_CMS_DATAINIT:111:CMS_dataInit
-CMS_F_CMS_DECRYPT:112:CMS_decrypt
-CMS_F_CMS_DECRYPT_SET1_KEY:113:CMS_decrypt_set1_key
-CMS_F_CMS_DECRYPT_SET1_PASSWORD:166:CMS_decrypt_set1_password
-CMS_F_CMS_DECRYPT_SET1_PKEY:114:CMS_decrypt_set1_pkey
-CMS_F_CMS_DIGESTALGORITHM_FIND_CTX:115:cms_DigestAlgorithm_find_ctx
-CMS_F_CMS_DIGESTALGORITHM_INIT_BIO:116:cms_DigestAlgorithm_init_bio
-CMS_F_CMS_DIGESTEDDATA_DO_FINAL:117:cms_DigestedData_do_final
-CMS_F_CMS_DIGEST_VERIFY:118:CMS_digest_verify
-CMS_F_CMS_ENCODE_RECEIPT:161:cms_encode_Receipt
-CMS_F_CMS_ENCRYPT:119:CMS_encrypt
-CMS_F_CMS_ENCRYPTEDCONTENT_INIT:179:cms_EncryptedContent_init
-CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO:120:cms_EncryptedContent_init_bio
-CMS_F_CMS_ENCRYPTEDDATA_DECRYPT:121:CMS_EncryptedData_decrypt
-CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT:122:CMS_EncryptedData_encrypt
-CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY:123:CMS_EncryptedData_set1_key
-CMS_F_CMS_ENVELOPEDDATA_CREATE:124:CMS_EnvelopedData_create
-CMS_F_CMS_ENVELOPEDDATA_INIT_BIO:125:cms_EnvelopedData_init_bio
-CMS_F_CMS_ENVELOPED_DATA_INIT:126:cms_enveloped_data_init
-CMS_F_CMS_ENV_ASN1_CTRL:171:cms_env_asn1_ctrl
-CMS_F_CMS_FINAL:127:CMS_final
-CMS_F_CMS_GET0_CERTIFICATE_CHOICES:128:cms_get0_certificate_choices
-CMS_F_CMS_GET0_CONTENT:129:CMS_get0_content
-CMS_F_CMS_GET0_ECONTENT_TYPE:130:cms_get0_econtent_type
-CMS_F_CMS_GET0_ENVELOPED:131:cms_get0_enveloped
-CMS_F_CMS_GET0_REVOCATION_CHOICES:132:cms_get0_revocation_choices
-CMS_F_CMS_GET0_SIGNED:133:cms_get0_signed
-CMS_F_CMS_MSGSIGDIGEST_ADD1:162:cms_msgSigDigest_add1
-CMS_F_CMS_RECEIPTREQUEST_CREATE0:159:CMS_ReceiptRequest_create0
-CMS_F_CMS_RECEIPT_VERIFY:160:cms_Receipt_verify
-CMS_F_CMS_RECIPIENTINFO_DECRYPT:134:CMS_RecipientInfo_decrypt
-CMS_F_CMS_RECIPIENTINFO_ENCRYPT:169:CMS_RecipientInfo_encrypt
-CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT:178:cms_RecipientInfo_kari_encrypt
-CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG:175:CMS_RecipientInfo_kari_get0_alg
-CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID:173:\
- CMS_RecipientInfo_kari_get0_orig_id
-CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS:172:CMS_RecipientInfo_kari_get0_reks
-CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP:174:CMS_RecipientInfo_kari_orig_id_cmp
-CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT:135:cms_RecipientInfo_kekri_decrypt
-CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT:136:cms_RecipientInfo_kekri_encrypt
-CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID:137:CMS_RecipientInfo_kekri_get0_id
-CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP:138:CMS_RecipientInfo_kekri_id_cmp
-CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP:139:CMS_RecipientInfo_ktri_cert_cmp
-CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT:140:cms_RecipientInfo_ktri_decrypt
-CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT:141:cms_RecipientInfo_ktri_encrypt
-CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS:142:CMS_RecipientInfo_ktri_get0_algs
-CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID:143:\
- CMS_RecipientInfo_ktri_get0_signer_id
-CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT:167:cms_RecipientInfo_pwri_crypt
-CMS_F_CMS_RECIPIENTINFO_SET0_KEY:144:CMS_RecipientInfo_set0_key
-CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD:168:CMS_RecipientInfo_set0_password
-CMS_F_CMS_RECIPIENTINFO_SET0_PKEY:145:CMS_RecipientInfo_set0_pkey
-CMS_F_CMS_SD_ASN1_CTRL:170:cms_sd_asn1_ctrl
-CMS_F_CMS_SET1_IAS:176:cms_set1_ias
-CMS_F_CMS_SET1_KEYID:177:cms_set1_keyid
-CMS_F_CMS_SET1_SIGNERIDENTIFIER:146:cms_set1_SignerIdentifier
-CMS_F_CMS_SET_DETACHED:147:CMS_set_detached
-CMS_F_CMS_SIGN:148:CMS_sign
-CMS_F_CMS_SIGNED_DATA_INIT:149:cms_signed_data_init
-CMS_F_CMS_SIGNERINFO_CONTENT_SIGN:150:cms_SignerInfo_content_sign
-CMS_F_CMS_SIGNERINFO_SIGN:151:CMS_SignerInfo_sign
-CMS_F_CMS_SIGNERINFO_VERIFY:152:CMS_SignerInfo_verify
-CMS_F_CMS_SIGNERINFO_VERIFY_CERT:153:cms_signerinfo_verify_cert
-CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT:154:CMS_SignerInfo_verify_content
-CMS_F_CMS_SIGN_RECEIPT:163:CMS_sign_receipt
-CMS_F_CMS_SI_CHECK_ATTRIBUTES:183:CMS_si_check_attributes
-CMS_F_CMS_STREAM:155:CMS_stream
-CMS_F_CMS_UNCOMPRESS:156:CMS_uncompress
-CMS_F_CMS_VERIFY:157:CMS_verify
-CMS_F_KEK_UNWRAP_KEY:180:kek_unwrap_key
-COMP_F_BIO_ZLIB_FLUSH:99:bio_zlib_flush
-COMP_F_BIO_ZLIB_NEW:100:bio_zlib_new
-COMP_F_BIO_ZLIB_READ:101:bio_zlib_read
-COMP_F_BIO_ZLIB_WRITE:102:bio_zlib_write
-COMP_F_COMP_CTX_NEW:103:COMP_CTX_new
-CONF_F_CONF_DUMP_FP:104:CONF_dump_fp
-CONF_F_CONF_LOAD:100:CONF_load
-CONF_F_CONF_LOAD_FP:103:CONF_load_fp
-CONF_F_CONF_PARSE_LIST:119:CONF_parse_list
-CONF_F_DEF_LOAD:120:def_load
-CONF_F_DEF_LOAD_BIO:121:def_load_bio
-CONF_F_GET_NEXT_FILE:107:get_next_file
-CONF_F_MODULE_ADD:122:module_add
-CONF_F_MODULE_INIT:115:module_init
-CONF_F_MODULE_LOAD_DSO:117:module_load_dso
-CONF_F_MODULE_RUN:118:module_run
-CONF_F_NCONF_DUMP_BIO:105:NCONF_dump_bio
-CONF_F_NCONF_DUMP_FP:106:NCONF_dump_fp
-CONF_F_NCONF_GET_NUMBER_E:112:NCONF_get_number_e
-CONF_F_NCONF_GET_SECTION:108:NCONF_get_section
-CONF_F_NCONF_GET_STRING:109:NCONF_get_string
-CONF_F_NCONF_LOAD:113:NCONF_load
-CONF_F_NCONF_LOAD_BIO:110:NCONF_load_bio
-CONF_F_NCONF_LOAD_FP:114:NCONF_load_fp
-CONF_F_NCONF_NEW:111:NCONF_new
-CONF_F_PROCESS_INCLUDE:116:process_include
-CONF_F_SSL_MODULE_INIT:123:ssl_module_init
-CONF_F_STR_COPY:101:str_copy
-CRYPTO_F_CMAC_CTX_NEW:120:CMAC_CTX_new
-CRYPTO_F_CRYPTO_DUP_EX_DATA:110:CRYPTO_dup_ex_data
-CRYPTO_F_CRYPTO_FREE_EX_DATA:111:CRYPTO_free_ex_data
-CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX:100:CRYPTO_get_ex_new_index
-CRYPTO_F_CRYPTO_MEMDUP:115:CRYPTO_memdup
-CRYPTO_F_CRYPTO_NEW_EX_DATA:112:CRYPTO_new_ex_data
-CRYPTO_F_CRYPTO_OCB128_COPY_CTX:121:CRYPTO_ocb128_copy_ctx
-CRYPTO_F_CRYPTO_OCB128_INIT:122:CRYPTO_ocb128_init
-CRYPTO_F_CRYPTO_SET_EX_DATA:102:CRYPTO_set_ex_data
-CRYPTO_F_FIPS_MODE_SET:109:FIPS_mode_set
-CRYPTO_F_GET_AND_LOCK:113:get_and_lock
-CRYPTO_F_OPENSSL_ATEXIT:114:OPENSSL_atexit
-CRYPTO_F_OPENSSL_BUF2HEXSTR:117:OPENSSL_buf2hexstr
-CRYPTO_F_OPENSSL_FOPEN:119:openssl_fopen
-CRYPTO_F_OPENSSL_HEXSTR2BUF:118:OPENSSL_hexstr2buf
-CRYPTO_F_OPENSSL_INIT_CRYPTO:116:OPENSSL_init_crypto
-CRYPTO_F_OPENSSL_LH_NEW:126:OPENSSL_LH_new
-CRYPTO_F_OPENSSL_SK_DEEP_COPY:127:OPENSSL_sk_deep_copy
-CRYPTO_F_OPENSSL_SK_DUP:128:OPENSSL_sk_dup
-CRYPTO_F_PKEY_HMAC_INIT:123:pkey_hmac_init
-CRYPTO_F_PKEY_POLY1305_INIT:124:pkey_poly1305_init
-CRYPTO_F_PKEY_SIPHASH_INIT:125:pkey_siphash_init
-CRYPTO_F_SK_RESERVE:129:sk_reserve
-CT_F_CTLOG_NEW:117:CTLOG_new
-CT_F_CTLOG_NEW_FROM_BASE64:118:CTLOG_new_from_base64
-CT_F_CTLOG_NEW_FROM_CONF:119:ctlog_new_from_conf
-CT_F_CTLOG_STORE_LOAD_CTX_NEW:122:ctlog_store_load_ctx_new
-CT_F_CTLOG_STORE_LOAD_FILE:123:CTLOG_STORE_load_file
-CT_F_CTLOG_STORE_LOAD_LOG:130:ctlog_store_load_log
-CT_F_CTLOG_STORE_NEW:131:CTLOG_STORE_new
-CT_F_CT_BASE64_DECODE:124:ct_base64_decode
-CT_F_CT_POLICY_EVAL_CTX_NEW:133:CT_POLICY_EVAL_CTX_new
-CT_F_CT_V1_LOG_ID_FROM_PKEY:125:ct_v1_log_id_from_pkey
-CT_F_I2O_SCT:107:i2o_SCT
-CT_F_I2O_SCT_LIST:108:i2o_SCT_LIST
-CT_F_I2O_SCT_SIGNATURE:109:i2o_SCT_signature
-CT_F_O2I_SCT:110:o2i_SCT
-CT_F_O2I_SCT_LIST:111:o2i_SCT_LIST
-CT_F_O2I_SCT_SIGNATURE:112:o2i_SCT_signature
-CT_F_SCT_CTX_NEW:126:SCT_CTX_new
-CT_F_SCT_CTX_VERIFY:128:SCT_CTX_verify
-CT_F_SCT_NEW:100:SCT_new
-CT_F_SCT_NEW_FROM_BASE64:127:SCT_new_from_base64
-CT_F_SCT_SET0_LOG_ID:101:SCT_set0_log_id
-CT_F_SCT_SET1_EXTENSIONS:114:SCT_set1_extensions
-CT_F_SCT_SET1_LOG_ID:115:SCT_set1_log_id
-CT_F_SCT_SET1_SIGNATURE:116:SCT_set1_signature
-CT_F_SCT_SET_LOG_ENTRY_TYPE:102:SCT_set_log_entry_type
-CT_F_SCT_SET_SIGNATURE_NID:103:SCT_set_signature_nid
-CT_F_SCT_SET_VERSION:104:SCT_set_version
-DH_F_COMPUTE_KEY:102:compute_key
-DH_F_DHPARAMS_PRINT_FP:101:DHparams_print_fp
-DH_F_DH_BUILTIN_GENPARAMS:106:dh_builtin_genparams
-DH_F_DH_CHECK_EX:121:DH_check_ex
-DH_F_DH_CHECK_PARAMS_EX:122:DH_check_params_ex
-DH_F_DH_CHECK_PUB_KEY_EX:123:DH_check_pub_key_ex
-DH_F_DH_CMS_DECRYPT:114:dh_cms_decrypt
-DH_F_DH_CMS_SET_PEERKEY:115:dh_cms_set_peerkey
-DH_F_DH_CMS_SET_SHARED_INFO:116:dh_cms_set_shared_info
-DH_F_DH_METH_DUP:117:DH_meth_dup
-DH_F_DH_METH_NEW:118:DH_meth_new
-DH_F_DH_METH_SET1_NAME:119:DH_meth_set1_name
-DH_F_DH_NEW_BY_NID:104:DH_new_by_nid
-DH_F_DH_NEW_METHOD:105:DH_new_method
-DH_F_DH_PARAM_DECODE:107:dh_param_decode
-DH_F_DH_PKEY_PUBLIC_CHECK:124:dh_pkey_public_check
-DH_F_DH_PRIV_DECODE:110:dh_priv_decode
-DH_F_DH_PRIV_ENCODE:111:dh_priv_encode
-DH_F_DH_PUB_DECODE:108:dh_pub_decode
-DH_F_DH_PUB_ENCODE:109:dh_pub_encode
-DH_F_DO_DH_PRINT:100:do_dh_print
-DH_F_GENERATE_KEY:103:generate_key
-DH_F_PKEY_DH_CTRL_STR:120:pkey_dh_ctrl_str
-DH_F_PKEY_DH_DERIVE:112:pkey_dh_derive
-DH_F_PKEY_DH_INIT:125:pkey_dh_init
-DH_F_PKEY_DH_KEYGEN:113:pkey_dh_keygen
-DSA_F_DSAPARAMS_PRINT:100:DSAparams_print
-DSA_F_DSAPARAMS_PRINT_FP:101:DSAparams_print_fp
-DSA_F_DSA_BUILTIN_PARAMGEN:125:dsa_builtin_paramgen
-DSA_F_DSA_BUILTIN_PARAMGEN2:126:dsa_builtin_paramgen2
-DSA_F_DSA_DO_SIGN:112:DSA_do_sign
-DSA_F_DSA_DO_VERIFY:113:DSA_do_verify
-DSA_F_DSA_METH_DUP:127:DSA_meth_dup
-DSA_F_DSA_METH_NEW:128:DSA_meth_new
-DSA_F_DSA_METH_SET1_NAME:129:DSA_meth_set1_name
-DSA_F_DSA_NEW_METHOD:103:DSA_new_method
-DSA_F_DSA_PARAM_DECODE:119:dsa_param_decode
-DSA_F_DSA_PRINT_FP:105:DSA_print_fp
-DSA_F_DSA_PRIV_DECODE:115:dsa_priv_decode
-DSA_F_DSA_PRIV_ENCODE:116:dsa_priv_encode
-DSA_F_DSA_PUB_DECODE:117:dsa_pub_decode
-DSA_F_DSA_PUB_ENCODE:118:dsa_pub_encode
-DSA_F_DSA_SIGN:106:DSA_sign
-DSA_F_DSA_SIGN_SETUP:107:DSA_sign_setup
-DSA_F_DSA_SIG_NEW:102:DSA_SIG_new
-DSA_F_OLD_DSA_PRIV_DECODE:122:old_dsa_priv_decode
-DSA_F_PKEY_DSA_CTRL:120:pkey_dsa_ctrl
-DSA_F_PKEY_DSA_CTRL_STR:104:pkey_dsa_ctrl_str
-DSA_F_PKEY_DSA_KEYGEN:121:pkey_dsa_keygen
-DSO_F_DLFCN_BIND_FUNC:100:dlfcn_bind_func
-DSO_F_DLFCN_LOAD:102:dlfcn_load
-DSO_F_DLFCN_MERGER:130:dlfcn_merger
-DSO_F_DLFCN_NAME_CONVERTER:123:dlfcn_name_converter
-DSO_F_DLFCN_UNLOAD:103:dlfcn_unload
-DSO_F_DL_BIND_FUNC:104:dl_bind_func
-DSO_F_DL_LOAD:106:dl_load
-DSO_F_DL_MERGER:131:dl_merger
-DSO_F_DL_NAME_CONVERTER:124:dl_name_converter
-DSO_F_DL_UNLOAD:107:dl_unload
-DSO_F_DSO_BIND_FUNC:108:DSO_bind_func
-DSO_F_DSO_CONVERT_FILENAME:126:DSO_convert_filename
-DSO_F_DSO_CTRL:110:DSO_ctrl
-DSO_F_DSO_FREE:111:DSO_free
-DSO_F_DSO_GET_FILENAME:127:DSO_get_filename
-DSO_F_DSO_GLOBAL_LOOKUP:139:DSO_global_lookup
-DSO_F_DSO_LOAD:112:DSO_load
-DSO_F_DSO_MERGE:132:DSO_merge
-DSO_F_DSO_NEW_METHOD:113:DSO_new_method
-DSO_F_DSO_PATHBYADDR:105:DSO_pathbyaddr
-DSO_F_DSO_SET_FILENAME:129:DSO_set_filename
-DSO_F_DSO_UP_REF:114:DSO_up_ref
-DSO_F_VMS_BIND_SYM:115:vms_bind_sym
-DSO_F_VMS_LOAD:116:vms_load
-DSO_F_VMS_MERGER:133:vms_merger
-DSO_F_VMS_UNLOAD:117:vms_unload
-DSO_F_WIN32_BIND_FUNC:101:win32_bind_func
-DSO_F_WIN32_GLOBALLOOKUP:142:win32_globallookup
-DSO_F_WIN32_JOINER:135:win32_joiner
-DSO_F_WIN32_LOAD:120:win32_load
-DSO_F_WIN32_MERGER:134:win32_merger
-DSO_F_WIN32_NAME_CONVERTER:125:win32_name_converter
-DSO_F_WIN32_PATHBYADDR:109:*
-DSO_F_WIN32_SPLITTER:136:win32_splitter
-DSO_F_WIN32_UNLOAD:121:win32_unload
-EC_F_BN_TO_FELEM:224:BN_to_felem
-EC_F_D2I_ECPARAMETERS:144:d2i_ECParameters
-EC_F_D2I_ECPKPARAMETERS:145:d2i_ECPKParameters
-EC_F_D2I_ECPRIVATEKEY:146:d2i_ECPrivateKey
-EC_F_DO_EC_KEY_PRINT:221:do_EC_KEY_print
-EC_F_ECDH_CMS_DECRYPT:238:ecdh_cms_decrypt
-EC_F_ECDH_CMS_SET_SHARED_INFO:239:ecdh_cms_set_shared_info
-EC_F_ECDH_COMPUTE_KEY:246:ECDH_compute_key
-EC_F_ECDH_SIMPLE_COMPUTE_KEY:257:ecdh_simple_compute_key
-EC_F_ECDSA_DO_SIGN_EX:251:ECDSA_do_sign_ex
-EC_F_ECDSA_DO_VERIFY:252:ECDSA_do_verify
-EC_F_ECDSA_SIGN_EX:254:ECDSA_sign_ex
-EC_F_ECDSA_SIGN_SETUP:248:ECDSA_sign_setup
-EC_F_ECDSA_SIG_NEW:265:ECDSA_SIG_new
-EC_F_ECDSA_VERIFY:253:ECDSA_verify
-EC_F_ECD_ITEM_VERIFY:270:ecd_item_verify
-EC_F_ECKEY_PARAM2TYPE:223:eckey_param2type
-EC_F_ECKEY_PARAM_DECODE:212:eckey_param_decode
-EC_F_ECKEY_PRIV_DECODE:213:eckey_priv_decode
-EC_F_ECKEY_PRIV_ENCODE:214:eckey_priv_encode
-EC_F_ECKEY_PUB_DECODE:215:eckey_pub_decode
-EC_F_ECKEY_PUB_ENCODE:216:eckey_pub_encode
-EC_F_ECKEY_TYPE2PARAM:220:eckey_type2param
-EC_F_ECPARAMETERS_PRINT:147:ECParameters_print
-EC_F_ECPARAMETERS_PRINT_FP:148:ECParameters_print_fp
-EC_F_ECPKPARAMETERS_PRINT:149:ECPKParameters_print
-EC_F_ECPKPARAMETERS_PRINT_FP:150:ECPKParameters_print_fp
-EC_F_ECP_NISTZ256_GET_AFFINE:240:ecp_nistz256_get_affine
-EC_F_ECP_NISTZ256_INV_MOD_ORD:275:ecp_nistz256_inv_mod_ord
-EC_F_ECP_NISTZ256_MULT_PRECOMPUTE:243:ecp_nistz256_mult_precompute
-EC_F_ECP_NISTZ256_POINTS_MUL:241:ecp_nistz256_points_mul
-EC_F_ECP_NISTZ256_PRE_COMP_NEW:244:ecp_nistz256_pre_comp_new
-EC_F_ECP_NISTZ256_WINDOWED_MUL:242:ecp_nistz256_windowed_mul
-EC_F_ECX_KEY_OP:266:ecx_key_op
-EC_F_ECX_PRIV_ENCODE:267:ecx_priv_encode
-EC_F_ECX_PUB_ENCODE:268:ecx_pub_encode
-EC_F_EC_ASN1_GROUP2CURVE:153:ec_asn1_group2curve
-EC_F_EC_ASN1_GROUP2FIELDID:154:ec_asn1_group2fieldid
-EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY:208:ec_GF2m_montgomery_point_multiply
-EC_F_EC_GF2M_SIMPLE_FIELD_INV:296:ec_GF2m_simple_field_inv
-EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT:159:\
- ec_GF2m_simple_group_check_discriminant
-EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE:195:ec_GF2m_simple_group_set_curve
-EC_F_EC_GF2M_SIMPLE_LADDER_POST:285:ec_GF2m_simple_ladder_post
-EC_F_EC_GF2M_SIMPLE_LADDER_PRE:288:ec_GF2m_simple_ladder_pre
-EC_F_EC_GF2M_SIMPLE_OCT2POINT:160:ec_GF2m_simple_oct2point
-EC_F_EC_GF2M_SIMPLE_POINT2OCT:161:ec_GF2m_simple_point2oct
-EC_F_EC_GF2M_SIMPLE_POINTS_MUL:289:ec_GF2m_simple_points_mul
-EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES:162:\
- ec_GF2m_simple_point_get_affine_coordinates
-EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES:163:\
- ec_GF2m_simple_point_set_affine_coordinates
-EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES:164:\
- ec_GF2m_simple_set_compressed_coordinates
-EC_F_EC_GFP_MONT_FIELD_DECODE:133:ec_GFp_mont_field_decode
-EC_F_EC_GFP_MONT_FIELD_ENCODE:134:ec_GFp_mont_field_encode
-EC_F_EC_GFP_MONT_FIELD_INV:297:ec_GFp_mont_field_inv
-EC_F_EC_GFP_MONT_FIELD_MUL:131:ec_GFp_mont_field_mul
-EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE:209:ec_GFp_mont_field_set_to_one
-EC_F_EC_GFP_MONT_FIELD_SQR:132:ec_GFp_mont_field_sqr
-EC_F_EC_GFP_MONT_GROUP_SET_CURVE:189:ec_GFp_mont_group_set_curve
-EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE:225:ec_GFp_nistp224_group_set_curve
-EC_F_EC_GFP_NISTP224_POINTS_MUL:228:ec_GFp_nistp224_points_mul
-EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES:226:\
- ec_GFp_nistp224_point_get_affine_coordinates
-EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE:230:ec_GFp_nistp256_group_set_curve
-EC_F_EC_GFP_NISTP256_POINTS_MUL:231:ec_GFp_nistp256_points_mul
-EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES:232:\
- ec_GFp_nistp256_point_get_affine_coordinates
-EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE:233:ec_GFp_nistp521_group_set_curve
-EC_F_EC_GFP_NISTP521_POINTS_MUL:234:ec_GFp_nistp521_points_mul
-EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES:235:\
- ec_GFp_nistp521_point_get_affine_coordinates
-EC_F_EC_GFP_NIST_FIELD_MUL:200:ec_GFp_nist_field_mul
-EC_F_EC_GFP_NIST_FIELD_SQR:201:ec_GFp_nist_field_sqr
-EC_F_EC_GFP_NIST_GROUP_SET_CURVE:202:ec_GFp_nist_group_set_curve
-EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES:287:ec_GFp_simple_blind_coordinates
-EC_F_EC_GFP_SIMPLE_FIELD_INV:298:ec_GFp_simple_field_inv
-EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT:165:\
- ec_GFp_simple_group_check_discriminant
-EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE:166:ec_GFp_simple_group_set_curve
-EC_F_EC_GFP_SIMPLE_MAKE_AFFINE:102:ec_GFp_simple_make_affine
-EC_F_EC_GFP_SIMPLE_OCT2POINT:103:ec_GFp_simple_oct2point
-EC_F_EC_GFP_SIMPLE_POINT2OCT:104:ec_GFp_simple_point2oct
-EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE:137:ec_GFp_simple_points_make_affine
-EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES:167:\
- ec_GFp_simple_point_get_affine_coordinates
-EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES:168:\
- ec_GFp_simple_point_set_affine_coordinates
-EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES:169:\
- ec_GFp_simple_set_compressed_coordinates
-EC_F_EC_GROUP_CHECK:170:EC_GROUP_check
-EC_F_EC_GROUP_CHECK_DISCRIMINANT:171:EC_GROUP_check_discriminant
-EC_F_EC_GROUP_COPY:106:EC_GROUP_copy
-EC_F_EC_GROUP_GET_CURVE:291:EC_GROUP_get_curve
-EC_F_EC_GROUP_GET_CURVE_GF2M:172:EC_GROUP_get_curve_GF2m
-EC_F_EC_GROUP_GET_CURVE_GFP:130:EC_GROUP_get_curve_GFp
-EC_F_EC_GROUP_GET_DEGREE:173:EC_GROUP_get_degree
-EC_F_EC_GROUP_GET_ECPARAMETERS:261:EC_GROUP_get_ecparameters
-EC_F_EC_GROUP_GET_ECPKPARAMETERS:262:EC_GROUP_get_ecpkparameters
-EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS:193:EC_GROUP_get_pentanomial_basis
-EC_F_EC_GROUP_GET_TRINOMIAL_BASIS:194:EC_GROUP_get_trinomial_basis
-EC_F_EC_GROUP_NEW:108:EC_GROUP_new
-EC_F_EC_GROUP_NEW_BY_CURVE_NAME:174:EC_GROUP_new_by_curve_name
-EC_F_EC_GROUP_NEW_FROM_DATA:175:ec_group_new_from_data
-EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS:263:EC_GROUP_new_from_ecparameters
-EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS:264:EC_GROUP_new_from_ecpkparameters
-EC_F_EC_GROUP_SET_CURVE:292:EC_GROUP_set_curve
-EC_F_EC_GROUP_SET_CURVE_GF2M:176:EC_GROUP_set_curve_GF2m
-EC_F_EC_GROUP_SET_CURVE_GFP:109:EC_GROUP_set_curve_GFp
-EC_F_EC_GROUP_SET_GENERATOR:111:EC_GROUP_set_generator
-EC_F_EC_GROUP_SET_SEED:286:EC_GROUP_set_seed
-EC_F_EC_KEY_CHECK_KEY:177:EC_KEY_check_key
-EC_F_EC_KEY_COPY:178:EC_KEY_copy
-EC_F_EC_KEY_GENERATE_KEY:179:EC_KEY_generate_key
-EC_F_EC_KEY_NEW:182:EC_KEY_new
-EC_F_EC_KEY_NEW_METHOD:245:EC_KEY_new_method
-EC_F_EC_KEY_OCT2PRIV:255:EC_KEY_oct2priv
-EC_F_EC_KEY_PRINT:180:EC_KEY_print
-EC_F_EC_KEY_PRINT_FP:181:EC_KEY_print_fp
-EC_F_EC_KEY_PRIV2BUF:279:EC_KEY_priv2buf
-EC_F_EC_KEY_PRIV2OCT:256:EC_KEY_priv2oct
-EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES:229:\
- EC_KEY_set_public_key_affine_coordinates
-EC_F_EC_KEY_SIMPLE_CHECK_KEY:258:ec_key_simple_check_key
-EC_F_EC_KEY_SIMPLE_OCT2PRIV:259:ec_key_simple_oct2priv
-EC_F_EC_KEY_SIMPLE_PRIV2OCT:260:ec_key_simple_priv2oct
-EC_F_EC_PKEY_CHECK:273:ec_pkey_check
-EC_F_EC_PKEY_PARAM_CHECK:274:ec_pkey_param_check
-EC_F_EC_POINTS_MAKE_AFFINE:136:EC_POINTs_make_affine
-EC_F_EC_POINTS_MUL:290:EC_POINTs_mul
-EC_F_EC_POINT_ADD:112:EC_POINT_add
-EC_F_EC_POINT_BN2POINT:280:EC_POINT_bn2point
-EC_F_EC_POINT_CMP:113:EC_POINT_cmp
-EC_F_EC_POINT_COPY:114:EC_POINT_copy
-EC_F_EC_POINT_DBL:115:EC_POINT_dbl
-EC_F_EC_POINT_GET_AFFINE_COORDINATES:293:EC_POINT_get_affine_coordinates
-EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M:183:\
- EC_POINT_get_affine_coordinates_GF2m
-EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP:116:EC_POINT_get_affine_coordinates_GFp
-EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP:117:\
- EC_POINT_get_Jprojective_coordinates_GFp
-EC_F_EC_POINT_INVERT:210:EC_POINT_invert
-EC_F_EC_POINT_IS_AT_INFINITY:118:EC_POINT_is_at_infinity
-EC_F_EC_POINT_IS_ON_CURVE:119:EC_POINT_is_on_curve
-EC_F_EC_POINT_MAKE_AFFINE:120:EC_POINT_make_affine
-EC_F_EC_POINT_NEW:121:EC_POINT_new
-EC_F_EC_POINT_OCT2POINT:122:EC_POINT_oct2point
-EC_F_EC_POINT_POINT2BUF:281:EC_POINT_point2buf
-EC_F_EC_POINT_POINT2OCT:123:EC_POINT_point2oct
-EC_F_EC_POINT_SET_AFFINE_COORDINATES:294:EC_POINT_set_affine_coordinates
-EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M:185:\
- EC_POINT_set_affine_coordinates_GF2m
-EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP:124:EC_POINT_set_affine_coordinates_GFp
-EC_F_EC_POINT_SET_COMPRESSED_COORDINATES:295:EC_POINT_set_compressed_coordinates
-EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M:186:\
- EC_POINT_set_compressed_coordinates_GF2m
-EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP:125:\
- EC_POINT_set_compressed_coordinates_GFp
-EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP:126:\
- EC_POINT_set_Jprojective_coordinates_GFp
-EC_F_EC_POINT_SET_TO_INFINITY:127:EC_POINT_set_to_infinity
-EC_F_EC_PRE_COMP_NEW:196:ec_pre_comp_new
-EC_F_EC_SCALAR_MUL_LADDER:284:ec_scalar_mul_ladder
-EC_F_EC_WNAF_MUL:187:ec_wNAF_mul
-EC_F_EC_WNAF_PRECOMPUTE_MULT:188:ec_wNAF_precompute_mult
-EC_F_I2D_ECPARAMETERS:190:i2d_ECParameters
-EC_F_I2D_ECPKPARAMETERS:191:i2d_ECPKParameters
-EC_F_I2D_ECPRIVATEKEY:192:i2d_ECPrivateKey
-EC_F_I2O_ECPUBLICKEY:151:i2o_ECPublicKey
-EC_F_NISTP224_PRE_COMP_NEW:227:nistp224_pre_comp_new
-EC_F_NISTP256_PRE_COMP_NEW:236:nistp256_pre_comp_new
-EC_F_NISTP521_PRE_COMP_NEW:237:nistp521_pre_comp_new
-EC_F_O2I_ECPUBLICKEY:152:o2i_ECPublicKey
-EC_F_OLD_EC_PRIV_DECODE:222:old_ec_priv_decode
-EC_F_OSSL_ECDH_COMPUTE_KEY:247:ossl_ecdh_compute_key
-EC_F_OSSL_ECDSA_SIGN_SIG:249:ossl_ecdsa_sign_sig
-EC_F_OSSL_ECDSA_VERIFY_SIG:250:ossl_ecdsa_verify_sig
-EC_F_PKEY_ECD_CTRL:271:pkey_ecd_ctrl
-EC_F_PKEY_ECD_DIGESTSIGN:272:pkey_ecd_digestsign
-EC_F_PKEY_ECD_DIGESTSIGN25519:276:pkey_ecd_digestsign25519
-EC_F_PKEY_ECD_DIGESTSIGN448:277:pkey_ecd_digestsign448
-EC_F_PKEY_ECX_DERIVE:269:pkey_ecx_derive
-EC_F_PKEY_EC_CTRL:197:pkey_ec_ctrl
-EC_F_PKEY_EC_CTRL_STR:198:pkey_ec_ctrl_str
-EC_F_PKEY_EC_DERIVE:217:pkey_ec_derive
-EC_F_PKEY_EC_INIT:282:pkey_ec_init
-EC_F_PKEY_EC_KDF_DERIVE:283:pkey_ec_kdf_derive
-EC_F_PKEY_EC_KEYGEN:199:pkey_ec_keygen
-EC_F_PKEY_EC_PARAMGEN:219:pkey_ec_paramgen
-EC_F_PKEY_EC_SIGN:218:pkey_ec_sign
-EC_F_VALIDATE_ECX_DERIVE:278:validate_ecx_derive
-ENGINE_F_DIGEST_UPDATE:198:digest_update
-ENGINE_F_DYNAMIC_CTRL:180:dynamic_ctrl
-ENGINE_F_DYNAMIC_GET_DATA_CTX:181:dynamic_get_data_ctx
-ENGINE_F_DYNAMIC_LOAD:182:dynamic_load
-ENGINE_F_DYNAMIC_SET_DATA_CTX:183:dynamic_set_data_ctx
-ENGINE_F_ENGINE_ADD:105:ENGINE_add
-ENGINE_F_ENGINE_BY_ID:106:ENGINE_by_id
-ENGINE_F_ENGINE_CMD_IS_EXECUTABLE:170:ENGINE_cmd_is_executable
-ENGINE_F_ENGINE_CTRL:142:ENGINE_ctrl
-ENGINE_F_ENGINE_CTRL_CMD:178:ENGINE_ctrl_cmd
-ENGINE_F_ENGINE_CTRL_CMD_STRING:171:ENGINE_ctrl_cmd_string
-ENGINE_F_ENGINE_FINISH:107:ENGINE_finish
-ENGINE_F_ENGINE_GET_CIPHER:185:ENGINE_get_cipher
-ENGINE_F_ENGINE_GET_DIGEST:186:ENGINE_get_digest
-ENGINE_F_ENGINE_GET_FIRST:195:ENGINE_get_first
-ENGINE_F_ENGINE_GET_LAST:196:ENGINE_get_last
-ENGINE_F_ENGINE_GET_NEXT:115:ENGINE_get_next
-ENGINE_F_ENGINE_GET_PKEY_ASN1_METH:193:ENGINE_get_pkey_asn1_meth
-ENGINE_F_ENGINE_GET_PKEY_METH:192:ENGINE_get_pkey_meth
-ENGINE_F_ENGINE_GET_PREV:116:ENGINE_get_prev
-ENGINE_F_ENGINE_INIT:119:ENGINE_init
-ENGINE_F_ENGINE_LIST_ADD:120:engine_list_add
-ENGINE_F_ENGINE_LIST_REMOVE:121:engine_list_remove
-ENGINE_F_ENGINE_LOAD_PRIVATE_KEY:150:ENGINE_load_private_key
-ENGINE_F_ENGINE_LOAD_PUBLIC_KEY:151:ENGINE_load_public_key
-ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT:194:ENGINE_load_ssl_client_cert
-ENGINE_F_ENGINE_NEW:122:ENGINE_new
-ENGINE_F_ENGINE_PKEY_ASN1_FIND_STR:197:ENGINE_pkey_asn1_find_str
-ENGINE_F_ENGINE_REMOVE:123:ENGINE_remove
-ENGINE_F_ENGINE_SET_DEFAULT_STRING:189:ENGINE_set_default_string
-ENGINE_F_ENGINE_SET_ID:129:ENGINE_set_id
-ENGINE_F_ENGINE_SET_NAME:130:ENGINE_set_name
-ENGINE_F_ENGINE_TABLE_REGISTER:184:engine_table_register
-ENGINE_F_ENGINE_UNLOCKED_FINISH:191:engine_unlocked_finish
-ENGINE_F_ENGINE_UP_REF:190:ENGINE_up_ref
-ENGINE_F_INT_CLEANUP_ITEM:199:int_cleanup_item
-ENGINE_F_INT_CTRL_HELPER:172:int_ctrl_helper
-ENGINE_F_INT_ENGINE_CONFIGURE:188:int_engine_configure
-ENGINE_F_INT_ENGINE_MODULE_INIT:187:int_engine_module_init
-ENGINE_F_OSSL_HMAC_INIT:200:ossl_hmac_init
-EVP_F_AESNI_INIT_KEY:165:aesni_init_key
-EVP_F_AESNI_XTS_INIT_KEY:207:aesni_xts_init_key
-EVP_F_AES_GCM_CTRL:196:aes_gcm_ctrl
-EVP_F_AES_INIT_KEY:133:aes_init_key
-EVP_F_AES_OCB_CIPHER:169:aes_ocb_cipher
-EVP_F_AES_T4_INIT_KEY:178:aes_t4_init_key
-EVP_F_AES_T4_XTS_INIT_KEY:208:aes_t4_xts_init_key
-EVP_F_AES_WRAP_CIPHER:170:aes_wrap_cipher
-EVP_F_AES_XTS_INIT_KEY:209:aes_xts_init_key
-EVP_F_ALG_MODULE_INIT:177:alg_module_init
-EVP_F_ARIA_CCM_INIT_KEY:175:aria_ccm_init_key
-EVP_F_ARIA_GCM_CTRL:197:aria_gcm_ctrl
-EVP_F_ARIA_GCM_INIT_KEY:176:aria_gcm_init_key
-EVP_F_ARIA_INIT_KEY:185:aria_init_key
-EVP_F_B64_NEW:198:b64_new
-EVP_F_CAMELLIA_INIT_KEY:159:camellia_init_key
-EVP_F_CHACHA20_POLY1305_CTRL:182:chacha20_poly1305_ctrl
-EVP_F_CMLL_T4_INIT_KEY:179:cmll_t4_init_key
-EVP_F_DES_EDE3_WRAP_CIPHER:171:des_ede3_wrap_cipher
-EVP_F_DO_SIGVER_INIT:161:do_sigver_init
-EVP_F_ENC_NEW:199:enc_new
-EVP_F_EVP_CIPHERINIT_EX:123:EVP_CipherInit_ex
-EVP_F_EVP_CIPHER_ASN1_TO_PARAM:204:EVP_CIPHER_asn1_to_param
-EVP_F_EVP_CIPHER_CTX_COPY:163:EVP_CIPHER_CTX_copy
-EVP_F_EVP_CIPHER_CTX_CTRL:124:EVP_CIPHER_CTX_ctrl
-EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH:122:EVP_CIPHER_CTX_set_key_length
-EVP_F_EVP_CIPHER_PARAM_TO_ASN1:205:EVP_CIPHER_param_to_asn1
-EVP_F_EVP_DECRYPTFINAL_EX:101:EVP_DecryptFinal_ex
-EVP_F_EVP_DECRYPTUPDATE:166:EVP_DecryptUpdate
-EVP_F_EVP_DIGESTFINALXOF:174:EVP_DigestFinalXOF
-EVP_F_EVP_DIGESTINIT_EX:128:EVP_DigestInit_ex
-EVP_F_EVP_ENCRYPTDECRYPTUPDATE:219:evp_EncryptDecryptUpdate
-EVP_F_EVP_ENCRYPTFINAL_EX:127:EVP_EncryptFinal_ex
-EVP_F_EVP_ENCRYPTUPDATE:167:EVP_EncryptUpdate
-EVP_F_EVP_MD_CTX_COPY_EX:110:EVP_MD_CTX_copy_ex
-EVP_F_EVP_MD_SIZE:162:EVP_MD_size
-EVP_F_EVP_OPENINIT:102:EVP_OpenInit
-EVP_F_EVP_PBE_ALG_ADD:115:EVP_PBE_alg_add
-EVP_F_EVP_PBE_ALG_ADD_TYPE:160:EVP_PBE_alg_add_type
-EVP_F_EVP_PBE_CIPHERINIT:116:EVP_PBE_CipherInit
-EVP_F_EVP_PBE_SCRYPT:181:EVP_PBE_scrypt
-EVP_F_EVP_PKCS82PKEY:111:EVP_PKCS82PKEY
-EVP_F_EVP_PKEY2PKCS8:113:EVP_PKEY2PKCS8
-EVP_F_EVP_PKEY_ASN1_ADD0:188:EVP_PKEY_asn1_add0
-EVP_F_EVP_PKEY_CHECK:186:EVP_PKEY_check
-EVP_F_EVP_PKEY_COPY_PARAMETERS:103:EVP_PKEY_copy_parameters
-EVP_F_EVP_PKEY_CTX_CTRL:137:EVP_PKEY_CTX_ctrl
-EVP_F_EVP_PKEY_CTX_CTRL_STR:150:EVP_PKEY_CTX_ctrl_str
-EVP_F_EVP_PKEY_CTX_DUP:156:EVP_PKEY_CTX_dup
-EVP_F_EVP_PKEY_CTX_MD:168:EVP_PKEY_CTX_md
-EVP_F_EVP_PKEY_DECRYPT:104:EVP_PKEY_decrypt
-EVP_F_EVP_PKEY_DECRYPT_INIT:138:EVP_PKEY_decrypt_init
-EVP_F_EVP_PKEY_DECRYPT_OLD:151:EVP_PKEY_decrypt_old
-EVP_F_EVP_PKEY_DERIVE:153:EVP_PKEY_derive
-EVP_F_EVP_PKEY_DERIVE_INIT:154:EVP_PKEY_derive_init
-EVP_F_EVP_PKEY_DERIVE_SET_PEER:155:EVP_PKEY_derive_set_peer
-EVP_F_EVP_PKEY_ENCRYPT:105:EVP_PKEY_encrypt
-EVP_F_EVP_PKEY_ENCRYPT_INIT:139:EVP_PKEY_encrypt_init
-EVP_F_EVP_PKEY_ENCRYPT_OLD:152:EVP_PKEY_encrypt_old
-EVP_F_EVP_PKEY_GET0_DH:119:EVP_PKEY_get0_DH
-EVP_F_EVP_PKEY_GET0_DSA:120:EVP_PKEY_get0_DSA
-EVP_F_EVP_PKEY_GET0_EC_KEY:131:EVP_PKEY_get0_EC_KEY
-EVP_F_EVP_PKEY_GET0_HMAC:183:EVP_PKEY_get0_hmac
-EVP_F_EVP_PKEY_GET0_POLY1305:184:EVP_PKEY_get0_poly1305
-EVP_F_EVP_PKEY_GET0_RSA:121:EVP_PKEY_get0_RSA
-EVP_F_EVP_PKEY_GET0_SIPHASH:172:EVP_PKEY_get0_siphash
-EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY:202:EVP_PKEY_get_raw_private_key
-EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY:203:EVP_PKEY_get_raw_public_key
-EVP_F_EVP_PKEY_KEYGEN:146:EVP_PKEY_keygen
-EVP_F_EVP_PKEY_KEYGEN_INIT:147:EVP_PKEY_keygen_init
-EVP_F_EVP_PKEY_METH_ADD0:194:EVP_PKEY_meth_add0
-EVP_F_EVP_PKEY_METH_NEW:195:EVP_PKEY_meth_new
-EVP_F_EVP_PKEY_NEW:106:EVP_PKEY_new
-EVP_F_EVP_PKEY_NEW_CMAC_KEY:193:EVP_PKEY_new_CMAC_key
-EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY:191:EVP_PKEY_new_raw_private_key
-EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY:192:EVP_PKEY_new_raw_public_key
-EVP_F_EVP_PKEY_PARAMGEN:148:EVP_PKEY_paramgen
-EVP_F_EVP_PKEY_PARAMGEN_INIT:149:EVP_PKEY_paramgen_init
-EVP_F_EVP_PKEY_PARAM_CHECK:189:EVP_PKEY_param_check
-EVP_F_EVP_PKEY_PUBLIC_CHECK:190:EVP_PKEY_public_check
-EVP_F_EVP_PKEY_SET1_ENGINE:187:EVP_PKEY_set1_engine
-EVP_F_EVP_PKEY_SET_ALIAS_TYPE:206:EVP_PKEY_set_alias_type
-EVP_F_EVP_PKEY_SIGN:140:EVP_PKEY_sign
-EVP_F_EVP_PKEY_SIGN_INIT:141:EVP_PKEY_sign_init
-EVP_F_EVP_PKEY_VERIFY:142:EVP_PKEY_verify
-EVP_F_EVP_PKEY_VERIFY_INIT:143:EVP_PKEY_verify_init
-EVP_F_EVP_PKEY_VERIFY_RECOVER:144:EVP_PKEY_verify_recover
-EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT:145:EVP_PKEY_verify_recover_init
-EVP_F_EVP_SIGNFINAL:107:EVP_SignFinal
-EVP_F_EVP_VERIFYFINAL:108:EVP_VerifyFinal
-EVP_F_INT_CTX_NEW:157:int_ctx_new
-EVP_F_OK_NEW:200:ok_new
-EVP_F_PKCS5_PBE_KEYIVGEN:117:PKCS5_PBE_keyivgen
-EVP_F_PKCS5_V2_PBE_KEYIVGEN:118:PKCS5_v2_PBE_keyivgen
-EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN:164:PKCS5_v2_PBKDF2_keyivgen
-EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN:180:PKCS5_v2_scrypt_keyivgen
-EVP_F_PKEY_SET_TYPE:158:pkey_set_type
-EVP_F_RC2_MAGIC_TO_METH:109:rc2_magic_to_meth
-EVP_F_RC5_CTRL:125:rc5_ctrl
-EVP_F_R_32_12_16_INIT_KEY:242:r_32_12_16_init_key
-EVP_F_S390X_AES_GCM_CTRL:201:s390x_aes_gcm_ctrl
-EVP_F_UPDATE:173:update
-KDF_F_PKEY_HKDF_CTRL_STR:103:pkey_hkdf_ctrl_str
-KDF_F_PKEY_HKDF_DERIVE:102:pkey_hkdf_derive
-KDF_F_PKEY_HKDF_INIT:108:pkey_hkdf_init
-KDF_F_PKEY_SCRYPT_CTRL_STR:104:pkey_scrypt_ctrl_str
-KDF_F_PKEY_SCRYPT_CTRL_UINT64:105:pkey_scrypt_ctrl_uint64
-KDF_F_PKEY_SCRYPT_DERIVE:109:pkey_scrypt_derive
-KDF_F_PKEY_SCRYPT_INIT:106:pkey_scrypt_init
-KDF_F_PKEY_SCRYPT_SET_MEMBUF:107:pkey_scrypt_set_membuf
-KDF_F_PKEY_TLS1_PRF_CTRL_STR:100:pkey_tls1_prf_ctrl_str
-KDF_F_PKEY_TLS1_PRF_DERIVE:101:pkey_tls1_prf_derive
-KDF_F_PKEY_TLS1_PRF_INIT:110:pkey_tls1_prf_init
-KDF_F_TLS1_PRF_ALG:111:tls1_prf_alg
-OBJ_F_OBJ_ADD_OBJECT:105:OBJ_add_object
-OBJ_F_OBJ_ADD_SIGID:107:OBJ_add_sigid
-OBJ_F_OBJ_CREATE:100:OBJ_create
-OBJ_F_OBJ_DUP:101:OBJ_dup
-OBJ_F_OBJ_NAME_NEW_INDEX:106:OBJ_NAME_new_index
-OBJ_F_OBJ_NID2LN:102:OBJ_nid2ln
-OBJ_F_OBJ_NID2OBJ:103:OBJ_nid2obj
-OBJ_F_OBJ_NID2SN:104:OBJ_nid2sn
-OBJ_F_OBJ_TXT2OBJ:108:OBJ_txt2obj
-OCSP_F_D2I_OCSP_NONCE:102:d2i_ocsp_nonce
-OCSP_F_OCSP_BASIC_ADD1_STATUS:103:OCSP_basic_add1_status
-OCSP_F_OCSP_BASIC_SIGN:104:OCSP_basic_sign
-OCSP_F_OCSP_BASIC_SIGN_CTX:119:OCSP_basic_sign_ctx
-OCSP_F_OCSP_BASIC_VERIFY:105:OCSP_basic_verify
-OCSP_F_OCSP_CERT_ID_NEW:101:OCSP_cert_id_new
-OCSP_F_OCSP_CHECK_DELEGATED:106:ocsp_check_delegated
-OCSP_F_OCSP_CHECK_IDS:107:ocsp_check_ids
-OCSP_F_OCSP_CHECK_ISSUER:108:ocsp_check_issuer
-OCSP_F_OCSP_CHECK_VALIDITY:115:OCSP_check_validity
-OCSP_F_OCSP_MATCH_ISSUERID:109:ocsp_match_issuerid
-OCSP_F_OCSP_PARSE_URL:114:OCSP_parse_url
-OCSP_F_OCSP_REQUEST_SIGN:110:OCSP_request_sign
-OCSP_F_OCSP_REQUEST_VERIFY:116:OCSP_request_verify
-OCSP_F_OCSP_RESPONSE_GET1_BASIC:111:OCSP_response_get1_basic
-OCSP_F_PARSE_HTTP_LINE1:118:parse_http_line1
-OSSL_STORE_F_FILE_CTRL:129:file_ctrl
-OSSL_STORE_F_FILE_FIND:138:file_find
-OSSL_STORE_F_FILE_GET_PASS:118:file_get_pass
-OSSL_STORE_F_FILE_LOAD:119:file_load
-OSSL_STORE_F_FILE_LOAD_TRY_DECODE:124:file_load_try_decode
-OSSL_STORE_F_FILE_NAME_TO_URI:126:file_name_to_uri
-OSSL_STORE_F_FILE_OPEN:120:file_open
-OSSL_STORE_F_OSSL_STORE_ATTACH_PEM_BIO:127:ossl_store_attach_pem_bio
-OSSL_STORE_F_OSSL_STORE_EXPECT:130:OSSL_STORE_expect
-OSSL_STORE_F_OSSL_STORE_FILE_ATTACH_PEM_BIO_INT:128:\
- ossl_store_file_attach_pem_bio_int
-OSSL_STORE_F_OSSL_STORE_FIND:131:OSSL_STORE_find
-OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT:100:ossl_store_get0_loader_int
-OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT:101:OSSL_STORE_INFO_get1_CERT
-OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL:102:OSSL_STORE_INFO_get1_CRL
-OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME:103:OSSL_STORE_INFO_get1_NAME
-OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION:135:\
- OSSL_STORE_INFO_get1_NAME_description
-OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS:104:OSSL_STORE_INFO_get1_PARAMS
-OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY:105:OSSL_STORE_INFO_get1_PKEY
-OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT:106:OSSL_STORE_INFO_new_CERT
-OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL:107:OSSL_STORE_INFO_new_CRL
-OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED:123:ossl_store_info_new_EMBEDDED
-OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME:109:OSSL_STORE_INFO_new_NAME
-OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS:110:OSSL_STORE_INFO_new_PARAMS
-OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY:111:OSSL_STORE_INFO_new_PKEY
-OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION:134:\
- OSSL_STORE_INFO_set0_NAME_description
-OSSL_STORE_F_OSSL_STORE_INIT_ONCE:112:ossl_store_init_once
-OSSL_STORE_F_OSSL_STORE_LOADER_NEW:113:OSSL_STORE_LOADER_new
-OSSL_STORE_F_OSSL_STORE_OPEN:114:OSSL_STORE_open
-OSSL_STORE_F_OSSL_STORE_OPEN_INT:115:*
-OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT:117:ossl_store_register_loader_int
-OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ALIAS:132:OSSL_STORE_SEARCH_by_alias
-OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ISSUER_SERIAL:133:\
- OSSL_STORE_SEARCH_by_issuer_serial
-OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:136:\
- OSSL_STORE_SEARCH_by_key_fingerprint
-OSSL_STORE_F_OSSL_STORE_SEARCH_BY_NAME:137:OSSL_STORE_SEARCH_by_name
-OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT:116:\
- ossl_store_unregister_loader_int
-OSSL_STORE_F_TRY_DECODE_PARAMS:121:try_decode_params
-OSSL_STORE_F_TRY_DECODE_PKCS12:122:try_decode_PKCS12
-OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED:125:try_decode_PKCS8Encrypted
-PEM_F_B2I_DSS:127:b2i_dss
-PEM_F_B2I_PVK_BIO:128:b2i_PVK_bio
-PEM_F_B2I_RSA:129:b2i_rsa
-PEM_F_CHECK_BITLEN_DSA:130:check_bitlen_dsa
-PEM_F_CHECK_BITLEN_RSA:131:check_bitlen_rsa
-PEM_F_D2I_PKCS8PRIVATEKEY_BIO:120:d2i_PKCS8PrivateKey_bio
-PEM_F_D2I_PKCS8PRIVATEKEY_FP:121:d2i_PKCS8PrivateKey_fp
-PEM_F_DO_B2I:132:do_b2i
-PEM_F_DO_B2I_BIO:133:do_b2i_bio
-PEM_F_DO_BLOB_HEADER:134:do_blob_header
-PEM_F_DO_I2B:146:do_i2b
-PEM_F_DO_PK8PKEY:126:do_pk8pkey
-PEM_F_DO_PK8PKEY_FP:125:do_pk8pkey_fp
-PEM_F_DO_PVK_BODY:135:do_PVK_body
-PEM_F_DO_PVK_HEADER:136:do_PVK_header
-PEM_F_GET_HEADER_AND_DATA:143:get_header_and_data
-PEM_F_GET_NAME:144:get_name
-PEM_F_I2B_PVK:137:i2b_PVK
-PEM_F_I2B_PVK_BIO:138:i2b_PVK_bio
-PEM_F_LOAD_IV:101:load_iv
-PEM_F_PEM_ASN1_READ:102:PEM_ASN1_read
-PEM_F_PEM_ASN1_READ_BIO:103:PEM_ASN1_read_bio
-PEM_F_PEM_ASN1_WRITE:104:PEM_ASN1_write
-PEM_F_PEM_ASN1_WRITE_BIO:105:PEM_ASN1_write_bio
-PEM_F_PEM_DEF_CALLBACK:100:PEM_def_callback
-PEM_F_PEM_DO_HEADER:106:PEM_do_header
-PEM_F_PEM_GET_EVP_CIPHER_INFO:107:PEM_get_EVP_CIPHER_INFO
-PEM_F_PEM_READ:108:PEM_read
-PEM_F_PEM_READ_BIO:109:PEM_read_bio
-PEM_F_PEM_READ_BIO_DHPARAMS:141:PEM_read_bio_DHparams
-PEM_F_PEM_READ_BIO_EX:145:PEM_read_bio_ex
-PEM_F_PEM_READ_BIO_PARAMETERS:140:PEM_read_bio_Parameters
-PEM_F_PEM_READ_BIO_PRIVATEKEY:123:PEM_read_bio_PrivateKey
-PEM_F_PEM_READ_DHPARAMS:142:PEM_read_DHparams
-PEM_F_PEM_READ_PRIVATEKEY:124:PEM_read_PrivateKey
-PEM_F_PEM_SIGNFINAL:112:PEM_SignFinal
-PEM_F_PEM_WRITE:113:PEM_write
-PEM_F_PEM_WRITE_BIO:114:PEM_write_bio
-PEM_F_PEM_WRITE_BIO_PRIVATEKEY_TRADITIONAL:147:\
- PEM_write_bio_PrivateKey_traditional
-PEM_F_PEM_WRITE_PRIVATEKEY:139:PEM_write_PrivateKey
-PEM_F_PEM_X509_INFO_READ:115:PEM_X509_INFO_read
-PEM_F_PEM_X509_INFO_READ_BIO:116:PEM_X509_INFO_read_bio
-PEM_F_PEM_X509_INFO_WRITE_BIO:117:PEM_X509_INFO_write_bio
-PKCS12_F_OPENSSL_ASC2UNI:121:OPENSSL_asc2uni
-PKCS12_F_OPENSSL_UNI2ASC:124:OPENSSL_uni2asc
-PKCS12_F_OPENSSL_UNI2UTF8:127:OPENSSL_uni2utf8
-PKCS12_F_OPENSSL_UTF82UNI:129:OPENSSL_utf82uni
-PKCS12_F_PKCS12_CREATE:105:PKCS12_create
-PKCS12_F_PKCS12_GEN_MAC:107:PKCS12_gen_mac
-PKCS12_F_PKCS12_INIT:109:PKCS12_init
-PKCS12_F_PKCS12_ITEM_DECRYPT_D2I:106:PKCS12_item_decrypt_d2i
-PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT:108:PKCS12_item_i2d_encrypt
-PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG:117:PKCS12_item_pack_safebag
-PKCS12_F_PKCS12_KEY_GEN_ASC:110:PKCS12_key_gen_asc
-PKCS12_F_PKCS12_KEY_GEN_UNI:111:PKCS12_key_gen_uni
-PKCS12_F_PKCS12_KEY_GEN_UTF8:116:PKCS12_key_gen_utf8
-PKCS12_F_PKCS12_NEWPASS:128:PKCS12_newpass
-PKCS12_F_PKCS12_PACK_P7DATA:114:PKCS12_pack_p7data
-PKCS12_F_PKCS12_PACK_P7ENCDATA:115:PKCS12_pack_p7encdata
-PKCS12_F_PKCS12_PARSE:118:PKCS12_parse
-PKCS12_F_PKCS12_PBE_CRYPT:119:PKCS12_pbe_crypt
-PKCS12_F_PKCS12_PBE_KEYIVGEN:120:PKCS12_PBE_keyivgen
-PKCS12_F_PKCS12_SAFEBAG_CREATE0_P8INF:112:PKCS12_SAFEBAG_create0_p8inf
-PKCS12_F_PKCS12_SAFEBAG_CREATE0_PKCS8:113:PKCS12_SAFEBAG_create0_pkcs8
-PKCS12_F_PKCS12_SAFEBAG_CREATE_PKCS8_ENCRYPT:133:\
- PKCS12_SAFEBAG_create_pkcs8_encrypt
-PKCS12_F_PKCS12_SETUP_MAC:122:PKCS12_setup_mac
-PKCS12_F_PKCS12_SET_MAC:123:PKCS12_set_mac
-PKCS12_F_PKCS12_UNPACK_AUTHSAFES:130:PKCS12_unpack_authsafes
-PKCS12_F_PKCS12_UNPACK_P7DATA:131:PKCS12_unpack_p7data
-PKCS12_F_PKCS12_VERIFY_MAC:126:PKCS12_verify_mac
-PKCS12_F_PKCS8_ENCRYPT:125:PKCS8_encrypt
-PKCS12_F_PKCS8_SET0_PBE:132:PKCS8_set0_pbe
-PKCS7_F_DO_PKCS7_SIGNED_ATTRIB:136:do_pkcs7_signed_attrib
-PKCS7_F_PKCS7_ADD0_ATTRIB_SIGNING_TIME:135:PKCS7_add0_attrib_signing_time
-PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP:118:PKCS7_add_attrib_smimecap
-PKCS7_F_PKCS7_ADD_CERTIFICATE:100:PKCS7_add_certificate
-PKCS7_F_PKCS7_ADD_CRL:101:PKCS7_add_crl
-PKCS7_F_PKCS7_ADD_RECIPIENT_INFO:102:PKCS7_add_recipient_info
-PKCS7_F_PKCS7_ADD_SIGNATURE:131:PKCS7_add_signature
-PKCS7_F_PKCS7_ADD_SIGNER:103:PKCS7_add_signer
-PKCS7_F_PKCS7_BIO_ADD_DIGEST:125:PKCS7_bio_add_digest
-PKCS7_F_PKCS7_COPY_EXISTING_DIGEST:138:pkcs7_copy_existing_digest
-PKCS7_F_PKCS7_CTRL:104:PKCS7_ctrl
-PKCS7_F_PKCS7_DATADECODE:112:PKCS7_dataDecode
-PKCS7_F_PKCS7_DATAFINAL:128:PKCS7_dataFinal
-PKCS7_F_PKCS7_DATAINIT:105:PKCS7_dataInit
-PKCS7_F_PKCS7_DATAVERIFY:107:PKCS7_dataVerify
-PKCS7_F_PKCS7_DECRYPT:114:PKCS7_decrypt
-PKCS7_F_PKCS7_DECRYPT_RINFO:133:pkcs7_decrypt_rinfo
-PKCS7_F_PKCS7_ENCODE_RINFO:132:pkcs7_encode_rinfo
-PKCS7_F_PKCS7_ENCRYPT:115:PKCS7_encrypt
-PKCS7_F_PKCS7_FINAL:134:PKCS7_final
-PKCS7_F_PKCS7_FIND_DIGEST:127:PKCS7_find_digest
-PKCS7_F_PKCS7_GET0_SIGNERS:124:PKCS7_get0_signers
-PKCS7_F_PKCS7_RECIP_INFO_SET:130:PKCS7_RECIP_INFO_set
-PKCS7_F_PKCS7_SET_CIPHER:108:PKCS7_set_cipher
-PKCS7_F_PKCS7_SET_CONTENT:109:PKCS7_set_content
-PKCS7_F_PKCS7_SET_DIGEST:126:PKCS7_set_digest
-PKCS7_F_PKCS7_SET_TYPE:110:PKCS7_set_type
-PKCS7_F_PKCS7_SIGN:116:PKCS7_sign
-PKCS7_F_PKCS7_SIGNATUREVERIFY:113:PKCS7_signatureVerify
-PKCS7_F_PKCS7_SIGNER_INFO_SET:129:PKCS7_SIGNER_INFO_set
-PKCS7_F_PKCS7_SIGNER_INFO_SIGN:139:PKCS7_SIGNER_INFO_sign
-PKCS7_F_PKCS7_SIGN_ADD_SIGNER:137:PKCS7_sign_add_signer
-PKCS7_F_PKCS7_SIMPLE_SMIMECAP:119:PKCS7_simple_smimecap
-PKCS7_F_PKCS7_VERIFY:117:PKCS7_verify
-RAND_F_DATA_COLLECT_METHOD:127:data_collect_method
-RAND_F_DRBG_BYTES:101:drbg_bytes
-RAND_F_DRBG_GET_ENTROPY:105:drbg_get_entropy
-RAND_F_DRBG_SETUP:117:drbg_setup
-RAND_F_GET_ENTROPY:106:get_entropy
-RAND_F_RAND_BYTES:100:RAND_bytes
-RAND_F_RAND_DRBG_ENABLE_LOCKING:119:rand_drbg_enable_locking
-RAND_F_RAND_DRBG_GENERATE:107:RAND_DRBG_generate
-RAND_F_RAND_DRBG_GET_ENTROPY:120:rand_drbg_get_entropy
-RAND_F_RAND_DRBG_GET_NONCE:123:rand_drbg_get_nonce
-RAND_F_RAND_DRBG_INSTANTIATE:108:RAND_DRBG_instantiate
-RAND_F_RAND_DRBG_NEW:109:RAND_DRBG_new
-RAND_F_RAND_DRBG_RESEED:110:RAND_DRBG_reseed
-RAND_F_RAND_DRBG_RESTART:102:rand_drbg_restart
-RAND_F_RAND_DRBG_SET:104:RAND_DRBG_set
-RAND_F_RAND_DRBG_SET_DEFAULTS:121:RAND_DRBG_set_defaults
-RAND_F_RAND_DRBG_UNINSTANTIATE:118:RAND_DRBG_uninstantiate
-RAND_F_RAND_LOAD_FILE:111:RAND_load_file
-RAND_F_RAND_POOL_ACQUIRE_ENTROPY:122:rand_pool_acquire_entropy
-RAND_F_RAND_POOL_ADD:103:rand_pool_add
-RAND_F_RAND_POOL_ADD_BEGIN:113:rand_pool_add_begin
-RAND_F_RAND_POOL_ADD_END:114:rand_pool_add_end
-RAND_F_RAND_POOL_ATTACH:124:rand_pool_attach
-RAND_F_RAND_POOL_BYTES_NEEDED:115:rand_pool_bytes_needed
-RAND_F_RAND_POOL_GROW:125:rand_pool_grow
-RAND_F_RAND_POOL_NEW:116:rand_pool_new
-RAND_F_RAND_PSEUDO_BYTES:126:RAND_pseudo_bytes
-RAND_F_RAND_WRITE_FILE:112:RAND_write_file
-RSA_F_CHECK_PADDING_MD:140:check_padding_md
-RSA_F_ENCODE_PKCS1:146:encode_pkcs1
-RSA_F_INT_RSA_VERIFY:145:int_rsa_verify
-RSA_F_OLD_RSA_PRIV_DECODE:147:old_rsa_priv_decode
-RSA_F_PKEY_PSS_INIT:165:pkey_pss_init
-RSA_F_PKEY_RSA_CTRL:143:pkey_rsa_ctrl
-RSA_F_PKEY_RSA_CTRL_STR:144:pkey_rsa_ctrl_str
-RSA_F_PKEY_RSA_SIGN:142:pkey_rsa_sign
-RSA_F_PKEY_RSA_VERIFY:149:pkey_rsa_verify
-RSA_F_PKEY_RSA_VERIFYRECOVER:141:pkey_rsa_verifyrecover
-RSA_F_RSA_ALGOR_TO_MD:156:rsa_algor_to_md
-RSA_F_RSA_BUILTIN_KEYGEN:129:rsa_builtin_keygen
-RSA_F_RSA_CHECK_KEY:123:RSA_check_key
-RSA_F_RSA_CHECK_KEY_EX:160:RSA_check_key_ex
-RSA_F_RSA_CMS_DECRYPT:159:rsa_cms_decrypt
-RSA_F_RSA_CMS_VERIFY:158:rsa_cms_verify
-RSA_F_RSA_ITEM_VERIFY:148:rsa_item_verify
-RSA_F_RSA_METH_DUP:161:RSA_meth_dup
-RSA_F_RSA_METH_NEW:162:RSA_meth_new
-RSA_F_RSA_METH_SET1_NAME:163:RSA_meth_set1_name
-RSA_F_RSA_MGF1_TO_MD:157:*
-RSA_F_RSA_MULTIP_INFO_NEW:166:rsa_multip_info_new
-RSA_F_RSA_NEW_METHOD:106:RSA_new_method
-RSA_F_RSA_NULL:124:*
-RSA_F_RSA_NULL_PRIVATE_DECRYPT:132:*
-RSA_F_RSA_NULL_PRIVATE_ENCRYPT:133:*
-RSA_F_RSA_NULL_PUBLIC_DECRYPT:134:*
-RSA_F_RSA_NULL_PUBLIC_ENCRYPT:135:*
-RSA_F_RSA_OSSL_PRIVATE_DECRYPT:101:rsa_ossl_private_decrypt
-RSA_F_RSA_OSSL_PRIVATE_ENCRYPT:102:rsa_ossl_private_encrypt
-RSA_F_RSA_OSSL_PUBLIC_DECRYPT:103:rsa_ossl_public_decrypt
-RSA_F_RSA_OSSL_PUBLIC_ENCRYPT:104:rsa_ossl_public_encrypt
-RSA_F_RSA_PADDING_ADD_NONE:107:RSA_padding_add_none
-RSA_F_RSA_PADDING_ADD_PKCS1_OAEP:121:RSA_padding_add_PKCS1_OAEP
-RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1:154:RSA_padding_add_PKCS1_OAEP_mgf1
-RSA_F_RSA_PADDING_ADD_PKCS1_PSS:125:RSA_padding_add_PKCS1_PSS
-RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1:152:RSA_padding_add_PKCS1_PSS_mgf1
-RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1:108:RSA_padding_add_PKCS1_type_1
-RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2:109:RSA_padding_add_PKCS1_type_2
-RSA_F_RSA_PADDING_ADD_SSLV23:110:RSA_padding_add_SSLv23
-RSA_F_RSA_PADDING_ADD_X931:127:RSA_padding_add_X931
-RSA_F_RSA_PADDING_CHECK_NONE:111:RSA_padding_check_none
-RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP:122:RSA_padding_check_PKCS1_OAEP
-RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1:153:RSA_padding_check_PKCS1_OAEP_mgf1
-RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1:112:RSA_padding_check_PKCS1_type_1
-RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2:113:RSA_padding_check_PKCS1_type_2
-RSA_F_RSA_PADDING_CHECK_SSLV23:114:RSA_padding_check_SSLv23
-RSA_F_RSA_PADDING_CHECK_X931:128:RSA_padding_check_X931
-RSA_F_RSA_PARAM_DECODE:164:rsa_param_decode
-RSA_F_RSA_PRINT:115:RSA_print
-RSA_F_RSA_PRINT_FP:116:RSA_print_fp
-RSA_F_RSA_PRIV_DECODE:150:rsa_priv_decode
-RSA_F_RSA_PRIV_ENCODE:138:rsa_priv_encode
-RSA_F_RSA_PSS_GET_PARAM:151:rsa_pss_get_param
-RSA_F_RSA_PSS_TO_CTX:155:rsa_pss_to_ctx
-RSA_F_RSA_PUB_DECODE:139:rsa_pub_decode
-RSA_F_RSA_SETUP_BLINDING:136:RSA_setup_blinding
-RSA_F_RSA_SIGN:117:RSA_sign
-RSA_F_RSA_SIGN_ASN1_OCTET_STRING:118:RSA_sign_ASN1_OCTET_STRING
-RSA_F_RSA_VERIFY:119:RSA_verify
-RSA_F_RSA_VERIFY_ASN1_OCTET_STRING:120:RSA_verify_ASN1_OCTET_STRING
-RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1:126:RSA_verify_PKCS1_PSS_mgf1
-RSA_F_SETUP_TBUF:167:setup_tbuf
-SM2_F_PKEY_SM2_COPY:115:pkey_sm2_copy
-SM2_F_PKEY_SM2_CTRL:109:pkey_sm2_ctrl
-SM2_F_PKEY_SM2_CTRL_STR:110:pkey_sm2_ctrl_str
-SM2_F_PKEY_SM2_DIGEST_CUSTOM:114:pkey_sm2_digest_custom
-SM2_F_PKEY_SM2_INIT:111:pkey_sm2_init
-SM2_F_PKEY_SM2_SIGN:112:pkey_sm2_sign
-SM2_F_SM2_COMPUTE_MSG_HASH:100:sm2_compute_msg_hash
-SM2_F_SM2_COMPUTE_USERID_DIGEST:101:sm2_compute_userid_digest
-SM2_F_SM2_COMPUTE_Z_DIGEST:113:sm2_compute_z_digest
-SM2_F_SM2_DECRYPT:102:sm2_decrypt
-SM2_F_SM2_ENCRYPT:103:sm2_encrypt
-SM2_F_SM2_PLAINTEXT_SIZE:104:sm2_plaintext_size
-SM2_F_SM2_SIGN:105:sm2_sign
-SM2_F_SM2_SIG_GEN:106:sm2_sig_gen
-SM2_F_SM2_SIG_VERIFY:107:sm2_sig_verify
-SM2_F_SM2_VERIFY:108:sm2_verify
-SSL_F_ADD_CLIENT_KEY_SHARE_EXT:438:*
-SSL_F_ADD_KEY_SHARE:512:add_key_share
-SSL_F_BYTES_TO_CIPHER_LIST:519:bytes_to_cipher_list
-SSL_F_CHECK_SUITEB_CIPHER_LIST:331:check_suiteb_cipher_list
-SSL_F_CIPHERSUITE_CB:622:ciphersuite_cb
-SSL_F_CONSTRUCT_CA_NAMES:552:construct_ca_names
-SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS:553:construct_key_exchange_tbs
-SSL_F_CONSTRUCT_STATEFUL_TICKET:636:construct_stateful_ticket
-SSL_F_CONSTRUCT_STATELESS_TICKET:637:construct_stateless_ticket
-SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH:539:create_synthetic_message_hash
-SSL_F_CREATE_TICKET_PREQUEL:638:create_ticket_prequel
-SSL_F_CT_MOVE_SCTS:345:ct_move_scts
-SSL_F_CT_STRICT:349:ct_strict
-SSL_F_CUSTOM_EXT_ADD:554:custom_ext_add
-SSL_F_CUSTOM_EXT_PARSE:555:custom_ext_parse
-SSL_F_D2I_SSL_SESSION:103:d2i_SSL_SESSION
-SSL_F_DANE_CTX_ENABLE:347:dane_ctx_enable
-SSL_F_DANE_MTYPE_SET:393:dane_mtype_set
-SSL_F_DANE_TLSA_ADD:394:dane_tlsa_add
-SSL_F_DERIVE_SECRET_KEY_AND_IV:514:derive_secret_key_and_iv
-SSL_F_DO_DTLS1_WRITE:245:do_dtls1_write
-SSL_F_DO_SSL3_WRITE:104:do_ssl3_write
-SSL_F_DTLS1_BUFFER_RECORD:247:dtls1_buffer_record
-SSL_F_DTLS1_CHECK_TIMEOUT_NUM:318:dtls1_check_timeout_num
-SSL_F_DTLS1_HEARTBEAT:305:*
-SSL_F_DTLS1_HM_FRAGMENT_NEW:623:dtls1_hm_fragment_new
-SSL_F_DTLS1_PREPROCESS_FRAGMENT:288:dtls1_preprocess_fragment
-SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS:424:dtls1_process_buffered_records
-SSL_F_DTLS1_PROCESS_RECORD:257:dtls1_process_record
-SSL_F_DTLS1_READ_BYTES:258:dtls1_read_bytes
-SSL_F_DTLS1_READ_FAILED:339:dtls1_read_failed
-SSL_F_DTLS1_RETRANSMIT_MESSAGE:390:dtls1_retransmit_message
-SSL_F_DTLS1_WRITE_APP_DATA_BYTES:268:dtls1_write_app_data_bytes
-SSL_F_DTLS1_WRITE_BYTES:545:dtls1_write_bytes
-SSL_F_DTLSV1_LISTEN:350:DTLSv1_listen
-SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC:371:dtls_construct_change_cipher_spec
-SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST:385:\
- dtls_construct_hello_verify_request
-SSL_F_DTLS_GET_REASSEMBLED_MESSAGE:370:dtls_get_reassembled_message
-SSL_F_DTLS_PROCESS_HELLO_VERIFY:386:dtls_process_hello_verify
-SSL_F_DTLS_RECORD_LAYER_NEW:635:DTLS_RECORD_LAYER_new
-SSL_F_DTLS_WAIT_FOR_DRY:592:dtls_wait_for_dry
-SSL_F_EARLY_DATA_COUNT_OK:532:early_data_count_ok
-SSL_F_FINAL_EARLY_DATA:556:final_early_data
-SSL_F_FINAL_EC_PT_FORMATS:485:final_ec_pt_formats
-SSL_F_FINAL_EMS:486:final_ems
-SSL_F_FINAL_KEY_SHARE:503:final_key_share
-SSL_F_FINAL_MAXFRAGMENTLEN:557:final_maxfragmentlen
-SSL_F_FINAL_PSK:639:final_psk
-SSL_F_FINAL_RENEGOTIATE:483:final_renegotiate
-SSL_F_FINAL_SERVER_NAME:558:final_server_name
-SSL_F_FINAL_SIG_ALGS:497:final_sig_algs
-SSL_F_GET_CERT_VERIFY_TBS_DATA:588:get_cert_verify_tbs_data
-SSL_F_NSS_KEYLOG_INT:500:nss_keylog_int
-SSL_F_OPENSSL_INIT_SSL:342:OPENSSL_init_ssl
-SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION:436:*
-SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION:598:\
- ossl_statem_client13_write_transition
-SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE:430:*
-SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE:593:\
- ossl_statem_client_post_process_message
-SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE:594:ossl_statem_client_process_message
-SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION:417:ossl_statem_client_read_transition
-SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION:599:\
- ossl_statem_client_write_transition
-SSL_F_OSSL_STATEM_SERVER13_READ_TRANSITION:437:*
-SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION:600:\
- ossl_statem_server13_write_transition
-SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE:431:*
-SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE:601:\
- ossl_statem_server_post_process_message
-SSL_F_OSSL_STATEM_SERVER_POST_WORK:602:ossl_statem_server_post_work
-SSL_F_OSSL_STATEM_SERVER_PRE_WORK:640:
-SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE:603:ossl_statem_server_process_message
-SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION:418:ossl_statem_server_read_transition
-SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION:604:\
- ossl_statem_server_write_transition
-SSL_F_PARSE_CA_NAMES:541:parse_ca_names
-SSL_F_PITEM_NEW:624:pitem_new
-SSL_F_PQUEUE_NEW:625:pqueue_new
-SSL_F_PROCESS_KEY_SHARE_EXT:439:*
-SSL_F_READ_STATE_MACHINE:352:read_state_machine
-SSL_F_SET_CLIENT_CIPHERSUITE:540:set_client_ciphersuite
-SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET:595:srp_generate_client_master_secret
-SSL_F_SRP_GENERATE_SERVER_MASTER_SECRET:589:srp_generate_server_master_secret
-SSL_F_SRP_VERIFY_SERVER_PARAM:596:srp_verify_server_param
-SSL_F_SSL3_CHANGE_CIPHER_STATE:129:ssl3_change_cipher_state
-SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM:130:ssl3_check_cert_and_algorithm
-SSL_F_SSL3_CTRL:213:ssl3_ctrl
-SSL_F_SSL3_CTX_CTRL:133:ssl3_ctx_ctrl
-SSL_F_SSL3_DIGEST_CACHED_RECORDS:293:ssl3_digest_cached_records
-SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC:292:ssl3_do_change_cipher_spec
-SSL_F_SSL3_ENC:608:ssl3_enc
-SSL_F_SSL3_FINAL_FINISH_MAC:285:ssl3_final_finish_mac
-SSL_F_SSL3_FINISH_MAC:587:ssl3_finish_mac
-SSL_F_SSL3_GENERATE_KEY_BLOCK:238:ssl3_generate_key_block
-SSL_F_SSL3_GENERATE_MASTER_SECRET:388:ssl3_generate_master_secret
-SSL_F_SSL3_GET_RECORD:143:ssl3_get_record
-SSL_F_SSL3_INIT_FINISHED_MAC:397:ssl3_init_finished_mac
-SSL_F_SSL3_OUTPUT_CERT_CHAIN:147:ssl3_output_cert_chain
-SSL_F_SSL3_READ_BYTES:148:ssl3_read_bytes
-SSL_F_SSL3_READ_N:149:ssl3_read_n
-SSL_F_SSL3_SETUP_KEY_BLOCK:157:ssl3_setup_key_block
-SSL_F_SSL3_SETUP_READ_BUFFER:156:ssl3_setup_read_buffer
-SSL_F_SSL3_SETUP_WRITE_BUFFER:291:ssl3_setup_write_buffer
-SSL_F_SSL3_WRITE_BYTES:158:ssl3_write_bytes
-SSL_F_SSL3_WRITE_PENDING:159:ssl3_write_pending
-SSL_F_SSL_ADD_CERT_CHAIN:316:ssl_add_cert_chain
-SSL_F_SSL_ADD_CERT_TO_BUF:319:*
-SSL_F_SSL_ADD_CERT_TO_WPACKET:493:ssl_add_cert_to_wpacket
-SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT:298:*
-SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT:277:*
-SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT:307:*
-SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK:215:SSL_add_dir_cert_subjects_to_stack
-SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK:216:\
- SSL_add_file_cert_subjects_to_stack
-SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT:299:*
-SSL_F_SSL_ADD_SERVERHELLO_TLSEXT:278:*
-SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT:308:*
-SSL_F_SSL_BAD_METHOD:160:ssl_bad_method
-SSL_F_SSL_BUILD_CERT_CHAIN:332:ssl_build_cert_chain
-SSL_F_SSL_BYTES_TO_CIPHER_LIST:161:SSL_bytes_to_cipher_list
-SSL_F_SSL_CACHE_CIPHERLIST:520:ssl_cache_cipherlist
-SSL_F_SSL_CERT_ADD0_CHAIN_CERT:346:ssl_cert_add0_chain_cert
-SSL_F_SSL_CERT_DUP:221:ssl_cert_dup
-SSL_F_SSL_CERT_NEW:162:ssl_cert_new
-SSL_F_SSL_CERT_SET0_CHAIN:340:ssl_cert_set0_chain
-SSL_F_SSL_CHECK_PRIVATE_KEY:163:SSL_check_private_key
-SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT:280:*
-SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO:606:ssl_check_srp_ext_ClientHello
-SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG:279:ssl_check_srvr_ecc_cert_and_alg
-SSL_F_SSL_CHOOSE_CLIENT_VERSION:607:ssl_choose_client_version
-SSL_F_SSL_CIPHER_DESCRIPTION:626:SSL_CIPHER_description
-SSL_F_SSL_CIPHER_LIST_TO_BYTES:425:ssl_cipher_list_to_bytes
-SSL_F_SSL_CIPHER_PROCESS_RULESTR:230:ssl_cipher_process_rulestr
-SSL_F_SSL_CIPHER_STRENGTH_SORT:231:ssl_cipher_strength_sort
-SSL_F_SSL_CLEAR:164:SSL_clear
-SSL_F_SSL_CLIENT_HELLO_GET1_EXTENSIONS_PRESENT:627:\
- SSL_client_hello_get1_extensions_present
-SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD:165:SSL_COMP_add_compression_method
-SSL_F_SSL_CONF_CMD:334:SSL_CONF_cmd
-SSL_F_SSL_CREATE_CIPHER_LIST:166:ssl_create_cipher_list
-SSL_F_SSL_CTRL:232:SSL_ctrl
-SSL_F_SSL_CTX_CHECK_PRIVATE_KEY:168:SSL_CTX_check_private_key
-SSL_F_SSL_CTX_ENABLE_CT:398:SSL_CTX_enable_ct
-SSL_F_SSL_CTX_MAKE_PROFILES:309:ssl_ctx_make_profiles
-SSL_F_SSL_CTX_NEW:169:SSL_CTX_new
-SSL_F_SSL_CTX_SET_ALPN_PROTOS:343:SSL_CTX_set_alpn_protos
-SSL_F_SSL_CTX_SET_CIPHER_LIST:269:SSL_CTX_set_cipher_list
-SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE:290:SSL_CTX_set_client_cert_engine
-SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK:396:SSL_CTX_set_ct_validation_callback
-SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT:219:SSL_CTX_set_session_id_context
-SSL_F_SSL_CTX_SET_SSL_VERSION:170:SSL_CTX_set_ssl_version
-SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH:551:\
- SSL_CTX_set_tlsext_max_fragment_length
-SSL_F_SSL_CTX_USE_CERTIFICATE:171:SSL_CTX_use_certificate
-SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1:172:SSL_CTX_use_certificate_ASN1
-SSL_F_SSL_CTX_USE_CERTIFICATE_FILE:173:SSL_CTX_use_certificate_file
-SSL_F_SSL_CTX_USE_PRIVATEKEY:174:SSL_CTX_use_PrivateKey
-SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1:175:SSL_CTX_use_PrivateKey_ASN1
-SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE:176:SSL_CTX_use_PrivateKey_file
-SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT:272:SSL_CTX_use_psk_identity_hint
-SSL_F_SSL_CTX_USE_RSAPRIVATEKEY:177:SSL_CTX_use_RSAPrivateKey
-SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1:178:SSL_CTX_use_RSAPrivateKey_ASN1
-SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE:179:SSL_CTX_use_RSAPrivateKey_file
-SSL_F_SSL_CTX_USE_SERVERINFO:336:SSL_CTX_use_serverinfo
-SSL_F_SSL_CTX_USE_SERVERINFO_EX:543:SSL_CTX_use_serverinfo_ex
-SSL_F_SSL_CTX_USE_SERVERINFO_FILE:337:SSL_CTX_use_serverinfo_file
-SSL_F_SSL_DANE_DUP:403:ssl_dane_dup
-SSL_F_SSL_DANE_ENABLE:395:SSL_dane_enable
-SSL_F_SSL_DERIVE:590:ssl_derive
-SSL_F_SSL_DO_CONFIG:391:ssl_do_config
-SSL_F_SSL_DO_HANDSHAKE:180:SSL_do_handshake
-SSL_F_SSL_DUP_CA_LIST:408:SSL_dup_CA_list
-SSL_F_SSL_ENABLE_CT:402:SSL_enable_ct
-SSL_F_SSL_GENERATE_PKEY_GROUP:559:ssl_generate_pkey_group
-SSL_F_SSL_GENERATE_SESSION_ID:547:ssl_generate_session_id
-SSL_F_SSL_GET_NEW_SESSION:181:ssl_get_new_session
-SSL_F_SSL_GET_PREV_SESSION:217:ssl_get_prev_session
-SSL_F_SSL_GET_SERVER_CERT_INDEX:322:*
-SSL_F_SSL_GET_SIGN_PKEY:183:*
-SSL_F_SSL_HANDSHAKE_HASH:560:ssl_handshake_hash
-SSL_F_SSL_INIT_WBIO_BUFFER:184:ssl_init_wbio_buffer
-SSL_F_SSL_KEY_UPDATE:515:SSL_key_update
-SSL_F_SSL_LOAD_CLIENT_CA_FILE:185:SSL_load_client_CA_file
-SSL_F_SSL_LOG_MASTER_SECRET:498:*
-SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE:499:ssl_log_rsa_client_key_exchange
-SSL_F_SSL_MODULE_INIT:392:ssl_module_init
-SSL_F_SSL_NEW:186:SSL_new
-SSL_F_SSL_NEXT_PROTO_VALIDATE:565:ssl_next_proto_validate
-SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT:300:*
-SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT:302:*
-SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT:310:*
-SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT:301:*
-SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT:303:*
-SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT:311:*
-SSL_F_SSL_PEEK:270:SSL_peek
-SSL_F_SSL_PEEK_EX:432:SSL_peek_ex
-SSL_F_SSL_PEEK_INTERNAL:522:ssl_peek_internal
-SSL_F_SSL_READ:223:SSL_read
-SSL_F_SSL_READ_EARLY_DATA:529:SSL_read_early_data
-SSL_F_SSL_READ_EX:434:SSL_read_ex
-SSL_F_SSL_READ_INTERNAL:523:ssl_read_internal
-SSL_F_SSL_RENEGOTIATE:516:SSL_renegotiate
-SSL_F_SSL_RENEGOTIATE_ABBREVIATED:546:SSL_renegotiate_abbreviated
-SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT:320:*
-SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT:321:*
-SSL_F_SSL_SESSION_DUP:348:ssl_session_dup
-SSL_F_SSL_SESSION_NEW:189:SSL_SESSION_new
-SSL_F_SSL_SESSION_PRINT_FP:190:SSL_SESSION_print_fp
-SSL_F_SSL_SESSION_SET1_ID:423:SSL_SESSION_set1_id
-SSL_F_SSL_SESSION_SET1_ID_CONTEXT:312:SSL_SESSION_set1_id_context
-SSL_F_SSL_SET_ALPN_PROTOS:344:SSL_set_alpn_protos
-SSL_F_SSL_SET_CERT:191:ssl_set_cert
-SSL_F_SSL_SET_CERT_AND_KEY:621:ssl_set_cert_and_key
-SSL_F_SSL_SET_CIPHER_LIST:271:SSL_set_cipher_list
-SSL_F_SSL_SET_CT_VALIDATION_CALLBACK:399:SSL_set_ct_validation_callback
-SSL_F_SSL_SET_FD:192:SSL_set_fd
-SSL_F_SSL_SET_PKEY:193:ssl_set_pkey
-SSL_F_SSL_SET_RFD:194:SSL_set_rfd
-SSL_F_SSL_SET_SESSION:195:SSL_set_session
-SSL_F_SSL_SET_SESSION_ID_CONTEXT:218:SSL_set_session_id_context
-SSL_F_SSL_SET_SESSION_TICKET_EXT:294:SSL_set_session_ticket_ext
-SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH:550:SSL_set_tlsext_max_fragment_length
-SSL_F_SSL_SET_WFD:196:SSL_set_wfd
-SSL_F_SSL_SHUTDOWN:224:SSL_shutdown
-SSL_F_SSL_SRP_CTX_INIT:313:SSL_SRP_CTX_init
-SSL_F_SSL_START_ASYNC_JOB:389:ssl_start_async_job
-SSL_F_SSL_UNDEFINED_FUNCTION:197:ssl_undefined_function
-SSL_F_SSL_UNDEFINED_VOID_FUNCTION:244:ssl_undefined_void_function
-SSL_F_SSL_USE_CERTIFICATE:198:SSL_use_certificate
-SSL_F_SSL_USE_CERTIFICATE_ASN1:199:SSL_use_certificate_ASN1
-SSL_F_SSL_USE_CERTIFICATE_FILE:200:SSL_use_certificate_file
-SSL_F_SSL_USE_PRIVATEKEY:201:SSL_use_PrivateKey
-SSL_F_SSL_USE_PRIVATEKEY_ASN1:202:SSL_use_PrivateKey_ASN1
-SSL_F_SSL_USE_PRIVATEKEY_FILE:203:SSL_use_PrivateKey_file
-SSL_F_SSL_USE_PSK_IDENTITY_HINT:273:SSL_use_psk_identity_hint
-SSL_F_SSL_USE_RSAPRIVATEKEY:204:SSL_use_RSAPrivateKey
-SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1:205:SSL_use_RSAPrivateKey_ASN1
-SSL_F_SSL_USE_RSAPRIVATEKEY_FILE:206:SSL_use_RSAPrivateKey_file
-SSL_F_SSL_VALIDATE_CT:400:ssl_validate_ct
-SSL_F_SSL_VERIFY_CERT_CHAIN:207:ssl_verify_cert_chain
-SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE:616:SSL_verify_client_post_handshake
-SSL_F_SSL_WRITE:208:SSL_write
-SSL_F_SSL_WRITE_EARLY_DATA:526:SSL_write_early_data
-SSL_F_SSL_WRITE_EARLY_FINISH:527:*
-SSL_F_SSL_WRITE_EX:433:SSL_write_ex
-SSL_F_SSL_WRITE_INTERNAL:524:ssl_write_internal
-SSL_F_STATE_MACHINE:353:state_machine
-SSL_F_TLS12_CHECK_PEER_SIGALG:333:tls12_check_peer_sigalg
-SSL_F_TLS12_COPY_SIGALGS:533:tls12_copy_sigalgs
-SSL_F_TLS13_CHANGE_CIPHER_STATE:440:tls13_change_cipher_state
-SSL_F_TLS13_ENC:609:tls13_enc
-SSL_F_TLS13_FINAL_FINISH_MAC:605:tls13_final_finish_mac
-SSL_F_TLS13_GENERATE_SECRET:591:tls13_generate_secret
-SSL_F_TLS13_HKDF_EXPAND:561:tls13_hkdf_expand
-SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA:617:\
- tls13_restore_handshake_digest_for_pha
-SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA:618:\
- tls13_save_handshake_digest_for_pha
-SSL_F_TLS13_SETUP_KEY_BLOCK:441:tls13_setup_key_block
-SSL_F_TLS1_CHANGE_CIPHER_STATE:209:tls1_change_cipher_state
-SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS:341:*
-SSL_F_TLS1_ENC:401:tls1_enc
-SSL_F_TLS1_EXPORT_KEYING_MATERIAL:314:tls1_export_keying_material
-SSL_F_TLS1_GET_CURVELIST:338:tls1_get_curvelist
-SSL_F_TLS1_PRF:284:tls1_PRF
-SSL_F_TLS1_SAVE_U16:628:tls1_save_u16
-SSL_F_TLS1_SETUP_KEY_BLOCK:211:tls1_setup_key_block
-SSL_F_TLS1_SET_GROUPS:629:tls1_set_groups
-SSL_F_TLS1_SET_RAW_SIGALGS:630:tls1_set_raw_sigalgs
-SSL_F_TLS1_SET_SERVER_SIGALGS:335:tls1_set_server_sigalgs
-SSL_F_TLS1_SET_SHARED_SIGALGS:631:tls1_set_shared_sigalgs
-SSL_F_TLS1_SET_SIGALGS:632:tls1_set_sigalgs
-SSL_F_TLS_CHOOSE_SIGALG:513:tls_choose_sigalg
-SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK:354:tls_client_key_exchange_post_work
-SSL_F_TLS_COLLECT_EXTENSIONS:435:tls_collect_extensions
-SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES:542:\
- tls_construct_certificate_authorities
-SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST:372:tls_construct_certificate_request
-SSL_F_TLS_CONSTRUCT_CERT_STATUS:429:*
-SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY:494:tls_construct_cert_status_body
-SSL_F_TLS_CONSTRUCT_CERT_VERIFY:496:tls_construct_cert_verify
-SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC:427:tls_construct_change_cipher_spec
-SSL_F_TLS_CONSTRUCT_CKE_DHE:404:tls_construct_cke_dhe
-SSL_F_TLS_CONSTRUCT_CKE_ECDHE:405:tls_construct_cke_ecdhe
-SSL_F_TLS_CONSTRUCT_CKE_GOST:406:tls_construct_cke_gost
-SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE:407:tls_construct_cke_psk_preamble
-SSL_F_TLS_CONSTRUCT_CKE_RSA:409:tls_construct_cke_rsa
-SSL_F_TLS_CONSTRUCT_CKE_SRP:410:tls_construct_cke_srp
-SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE:484:tls_construct_client_certificate
-SSL_F_TLS_CONSTRUCT_CLIENT_HELLO:487:tls_construct_client_hello
-SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE:488:tls_construct_client_key_exchange
-SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY:489:*
-SSL_F_TLS_CONSTRUCT_CTOS_ALPN:466:tls_construct_ctos_alpn
-SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE:355:*
-SSL_F_TLS_CONSTRUCT_CTOS_COOKIE:535:tls_construct_ctos_cookie
-SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA:530:tls_construct_ctos_early_data
-SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS:467:tls_construct_ctos_ec_pt_formats
-SSL_F_TLS_CONSTRUCT_CTOS_EMS:468:tls_construct_ctos_ems
-SSL_F_TLS_CONSTRUCT_CTOS_ETM:469:tls_construct_ctos_etm
-SSL_F_TLS_CONSTRUCT_CTOS_HELLO:356:*
-SSL_F_TLS_CONSTRUCT_CTOS_KEY_EXCHANGE:357:*
-SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE:470:tls_construct_ctos_key_share
-SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN:549:tls_construct_ctos_maxfragmentlen
-SSL_F_TLS_CONSTRUCT_CTOS_NPN:471:tls_construct_ctos_npn
-SSL_F_TLS_CONSTRUCT_CTOS_PADDING:472:tls_construct_ctos_padding
-SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH:619:\
- tls_construct_ctos_post_handshake_auth
-SSL_F_TLS_CONSTRUCT_CTOS_PSK:501:tls_construct_ctos_psk
-SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES:509:tls_construct_ctos_psk_kex_modes
-SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE:473:tls_construct_ctos_renegotiate
-SSL_F_TLS_CONSTRUCT_CTOS_SCT:474:tls_construct_ctos_sct
-SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME:475:tls_construct_ctos_server_name
-SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET:476:tls_construct_ctos_session_ticket
-SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS:477:tls_construct_ctos_sig_algs
-SSL_F_TLS_CONSTRUCT_CTOS_SRP:478:tls_construct_ctos_srp
-SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST:479:tls_construct_ctos_status_request
-SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS:480:\
- tls_construct_ctos_supported_groups
-SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS:481:\
- tls_construct_ctos_supported_versions
-SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP:482:tls_construct_ctos_use_srtp
-SSL_F_TLS_CONSTRUCT_CTOS_VERIFY:358:*
-SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS:443:tls_construct_encrypted_extensions
-SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA:536:tls_construct_end_of_early_data
-SSL_F_TLS_CONSTRUCT_EXTENSIONS:447:tls_construct_extensions
-SSL_F_TLS_CONSTRUCT_FINISHED:359:tls_construct_finished
-SSL_F_TLS_CONSTRUCT_HELLO_REQUEST:373:*
-SSL_F_TLS_CONSTRUCT_HELLO_RETRY_REQUEST:510:tls_construct_hello_retry_request
-SSL_F_TLS_CONSTRUCT_KEY_UPDATE:517:tls_construct_key_update
-SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET:428:tls_construct_new_session_ticket
-SSL_F_TLS_CONSTRUCT_NEXT_PROTO:426:tls_construct_next_proto
-SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE:490:tls_construct_server_certificate
-SSL_F_TLS_CONSTRUCT_SERVER_HELLO:491:tls_construct_server_hello
-SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE:492:tls_construct_server_key_exchange
-SSL_F_TLS_CONSTRUCT_STOC_ALPN:451:tls_construct_stoc_alpn
-SSL_F_TLS_CONSTRUCT_STOC_CERTIFICATE:374:*
-SSL_F_TLS_CONSTRUCT_STOC_COOKIE:613:tls_construct_stoc_cookie
-SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG:452:tls_construct_stoc_cryptopro_bug
-SSL_F_TLS_CONSTRUCT_STOC_DONE:375:*
-SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA:531:tls_construct_stoc_early_data
-SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_INFO:525:*
-SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS:453:tls_construct_stoc_ec_pt_formats
-SSL_F_TLS_CONSTRUCT_STOC_EMS:454:tls_construct_stoc_ems
-SSL_F_TLS_CONSTRUCT_STOC_ETM:455:tls_construct_stoc_etm
-SSL_F_TLS_CONSTRUCT_STOC_HELLO:376:*
-SSL_F_TLS_CONSTRUCT_STOC_KEY_EXCHANGE:377:*
-SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE:456:tls_construct_stoc_key_share
-SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN:548:tls_construct_stoc_maxfragmentlen
-SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG:457:tls_construct_stoc_next_proto_neg
-SSL_F_TLS_CONSTRUCT_STOC_PSK:504:tls_construct_stoc_psk
-SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE:458:tls_construct_stoc_renegotiate
-SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME:459:tls_construct_stoc_server_name
-SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET:460:tls_construct_stoc_session_ticket
-SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST:461:tls_construct_stoc_status_request
-SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS:544:\
- tls_construct_stoc_supported_groups
-SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS:611:\
- tls_construct_stoc_supported_versions
-SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP:462:tls_construct_stoc_use_srtp
-SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO:521:\
- tls_early_post_process_client_hello
-SSL_F_TLS_FINISH_HANDSHAKE:597:tls_finish_handshake
-SSL_F_TLS_GET_MESSAGE_BODY:351:tls_get_message_body
-SSL_F_TLS_GET_MESSAGE_HEADER:387:tls_get_message_header
-SSL_F_TLS_HANDLE_ALPN:562:tls_handle_alpn
-SSL_F_TLS_HANDLE_STATUS_REQUEST:563:tls_handle_status_request
-SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES:566:tls_parse_certificate_authorities
-SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT:449:*
-SSL_F_TLS_PARSE_CTOS_ALPN:567:tls_parse_ctos_alpn
-SSL_F_TLS_PARSE_CTOS_COOKIE:614:tls_parse_ctos_cookie
-SSL_F_TLS_PARSE_CTOS_EARLY_DATA:568:tls_parse_ctos_early_data
-SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS:569:tls_parse_ctos_ec_pt_formats
-SSL_F_TLS_PARSE_CTOS_EMS:570:tls_parse_ctos_ems
-SSL_F_TLS_PARSE_CTOS_KEY_SHARE:463:tls_parse_ctos_key_share
-SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN:571:tls_parse_ctos_maxfragmentlen
-SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH:620:tls_parse_ctos_post_handshake_auth
-SSL_F_TLS_PARSE_CTOS_PSK:505:tls_parse_ctos_psk
-SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES:572:tls_parse_ctos_psk_kex_modes
-SSL_F_TLS_PARSE_CTOS_RENEGOTIATE:464:tls_parse_ctos_renegotiate
-SSL_F_TLS_PARSE_CTOS_SERVER_NAME:573:tls_parse_ctos_server_name
-SSL_F_TLS_PARSE_CTOS_SESSION_TICKET:574:tls_parse_ctos_session_ticket
-SSL_F_TLS_PARSE_CTOS_SIG_ALGS:575:tls_parse_ctos_sig_algs
-SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT:615:tls_parse_ctos_sig_algs_cert
-SSL_F_TLS_PARSE_CTOS_SRP:576:tls_parse_ctos_srp
-SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST:577:tls_parse_ctos_status_request
-SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS:578:tls_parse_ctos_supported_groups
-SSL_F_TLS_PARSE_CTOS_USE_SRTP:465:tls_parse_ctos_use_srtp
-SSL_F_TLS_PARSE_STOC_ALPN:579:tls_parse_stoc_alpn
-SSL_F_TLS_PARSE_STOC_COOKIE:534:tls_parse_stoc_cookie
-SSL_F_TLS_PARSE_STOC_EARLY_DATA:538:tls_parse_stoc_early_data
-SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO:528:*
-SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS:580:tls_parse_stoc_ec_pt_formats
-SSL_F_TLS_PARSE_STOC_KEY_SHARE:445:tls_parse_stoc_key_share
-SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN:581:tls_parse_stoc_maxfragmentlen
-SSL_F_TLS_PARSE_STOC_NPN:582:tls_parse_stoc_npn
-SSL_F_TLS_PARSE_STOC_PSK:502:tls_parse_stoc_psk
-SSL_F_TLS_PARSE_STOC_RENEGOTIATE:448:tls_parse_stoc_renegotiate
-SSL_F_TLS_PARSE_STOC_SCT:564:tls_parse_stoc_sct
-SSL_F_TLS_PARSE_STOC_SERVER_NAME:583:tls_parse_stoc_server_name
-SSL_F_TLS_PARSE_STOC_SESSION_TICKET:584:tls_parse_stoc_session_ticket
-SSL_F_TLS_PARSE_STOC_STATUS_REQUEST:585:tls_parse_stoc_status_request
-SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS:612:tls_parse_stoc_supported_versions
-SSL_F_TLS_PARSE_STOC_USE_SRTP:446:tls_parse_stoc_use_srtp
-SSL_F_TLS_POST_PROCESS_CLIENT_HELLO:378:tls_post_process_client_hello
-SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE:384:\
- tls_post_process_client_key_exchange
-SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE:360:tls_prepare_client_certificate
-SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST:610:tls_process_as_hello_retry_request
-SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST:361:tls_process_certificate_request
-SSL_F_TLS_PROCESS_CERT_STATUS:362:*
-SSL_F_TLS_PROCESS_CERT_STATUS_BODY:495:tls_process_cert_status_body
-SSL_F_TLS_PROCESS_CERT_VERIFY:379:tls_process_cert_verify
-SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC:363:tls_process_change_cipher_spec
-SSL_F_TLS_PROCESS_CKE_DHE:411:tls_process_cke_dhe
-SSL_F_TLS_PROCESS_CKE_ECDHE:412:tls_process_cke_ecdhe
-SSL_F_TLS_PROCESS_CKE_GOST:413:tls_process_cke_gost
-SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE:414:tls_process_cke_psk_preamble
-SSL_F_TLS_PROCESS_CKE_RSA:415:tls_process_cke_rsa
-SSL_F_TLS_PROCESS_CKE_SRP:416:tls_process_cke_srp
-SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE:380:tls_process_client_certificate
-SSL_F_TLS_PROCESS_CLIENT_HELLO:381:tls_process_client_hello
-SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE:382:tls_process_client_key_exchange
-SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS:444:tls_process_encrypted_extensions
-SSL_F_TLS_PROCESS_END_OF_EARLY_DATA:537:tls_process_end_of_early_data
-SSL_F_TLS_PROCESS_FINISHED:364:tls_process_finished
-SSL_F_TLS_PROCESS_HELLO_REQ:507:tls_process_hello_req
-SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST:511:tls_process_hello_retry_request
-SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT:442:tls_process_initial_server_flight
-SSL_F_TLS_PROCESS_KEY_EXCHANGE:365:tls_process_key_exchange
-SSL_F_TLS_PROCESS_KEY_UPDATE:518:tls_process_key_update
-SSL_F_TLS_PROCESS_NEW_SESSION_TICKET:366:tls_process_new_session_ticket
-SSL_F_TLS_PROCESS_NEXT_PROTO:383:tls_process_next_proto
-SSL_F_TLS_PROCESS_SERVER_CERTIFICATE:367:tls_process_server_certificate
-SSL_F_TLS_PROCESS_SERVER_DONE:368:tls_process_server_done
-SSL_F_TLS_PROCESS_SERVER_HELLO:369:tls_process_server_hello
-SSL_F_TLS_PROCESS_SKE_DHE:419:tls_process_ske_dhe
-SSL_F_TLS_PROCESS_SKE_ECDHE:420:tls_process_ske_ecdhe
-SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE:421:tls_process_ske_psk_preamble
-SSL_F_TLS_PROCESS_SKE_SRP:422:tls_process_ske_srp
-SSL_F_TLS_PSK_DO_BINDER:506:tls_psk_do_binder
-SSL_F_TLS_SCAN_CLIENTHELLO_TLSEXT:450:*
-SSL_F_TLS_SETUP_HANDSHAKE:508:tls_setup_handshake
-SSL_F_USE_CERTIFICATE_CHAIN_FILE:220:use_certificate_chain_file
-SSL_F_WPACKET_INTERN_INIT_LEN:633:wpacket_intern_init_len
-SSL_F_WPACKET_START_SUB_PACKET_LEN__:634:WPACKET_start_sub_packet_len__
-SSL_F_WRITE_STATE_MACHINE:586:write_state_machine
-TS_F_DEF_SERIAL_CB:110:def_serial_cb
-TS_F_DEF_TIME_CB:111:def_time_cb
-TS_F_ESS_ADD_SIGNING_CERT:112:ess_add_signing_cert
-TS_F_ESS_ADD_SIGNING_CERT_V2:147:ess_add_signing_cert_v2
-TS_F_ESS_CERT_ID_NEW_INIT:113:ess_CERT_ID_new_init
-TS_F_ESS_CERT_ID_V2_NEW_INIT:156:ess_cert_id_v2_new_init
-TS_F_ESS_SIGNING_CERT_NEW_INIT:114:ess_SIGNING_CERT_new_init
-TS_F_ESS_SIGNING_CERT_V2_NEW_INIT:157:ess_signing_cert_v2_new_init
-TS_F_INT_TS_RESP_VERIFY_TOKEN:149:int_ts_RESP_verify_token
-TS_F_PKCS7_TO_TS_TST_INFO:148:PKCS7_to_TS_TST_INFO
-TS_F_TS_ACCURACY_SET_MICROS:115:TS_ACCURACY_set_micros
-TS_F_TS_ACCURACY_SET_MILLIS:116:TS_ACCURACY_set_millis
-TS_F_TS_ACCURACY_SET_SECONDS:117:TS_ACCURACY_set_seconds
-TS_F_TS_CHECK_IMPRINTS:100:ts_check_imprints
-TS_F_TS_CHECK_NONCES:101:ts_check_nonces
-TS_F_TS_CHECK_POLICY:102:ts_check_policy
-TS_F_TS_CHECK_SIGNING_CERTS:103:ts_check_signing_certs
-TS_F_TS_CHECK_STATUS_INFO:104:ts_check_status_info
-TS_F_TS_COMPUTE_IMPRINT:145:ts_compute_imprint
-TS_F_TS_CONF_INVALID:151:ts_CONF_invalid
-TS_F_TS_CONF_LOAD_CERT:153:TS_CONF_load_cert
-TS_F_TS_CONF_LOAD_CERTS:154:TS_CONF_load_certs
-TS_F_TS_CONF_LOAD_KEY:155:TS_CONF_load_key
-TS_F_TS_CONF_LOOKUP_FAIL:152:ts_CONF_lookup_fail
-TS_F_TS_CONF_SET_DEFAULT_ENGINE:146:TS_CONF_set_default_engine
-TS_F_TS_GET_STATUS_TEXT:105:ts_get_status_text
-TS_F_TS_MSG_IMPRINT_SET_ALGO:118:TS_MSG_IMPRINT_set_algo
-TS_F_TS_REQ_SET_MSG_IMPRINT:119:TS_REQ_set_msg_imprint
-TS_F_TS_REQ_SET_NONCE:120:TS_REQ_set_nonce
-TS_F_TS_REQ_SET_POLICY_ID:121:TS_REQ_set_policy_id
-TS_F_TS_RESP_CREATE_RESPONSE:122:TS_RESP_create_response
-TS_F_TS_RESP_CREATE_TST_INFO:123:ts_RESP_create_tst_info
-TS_F_TS_RESP_CTX_ADD_FAILURE_INFO:124:TS_RESP_CTX_add_failure_info
-TS_F_TS_RESP_CTX_ADD_MD:125:TS_RESP_CTX_add_md
-TS_F_TS_RESP_CTX_ADD_POLICY:126:TS_RESP_CTX_add_policy
-TS_F_TS_RESP_CTX_NEW:127:TS_RESP_CTX_new
-TS_F_TS_RESP_CTX_SET_ACCURACY:128:TS_RESP_CTX_set_accuracy
-TS_F_TS_RESP_CTX_SET_CERTS:129:TS_RESP_CTX_set_certs
-TS_F_TS_RESP_CTX_SET_DEF_POLICY:130:TS_RESP_CTX_set_def_policy
-TS_F_TS_RESP_CTX_SET_SIGNER_CERT:131:TS_RESP_CTX_set_signer_cert
-TS_F_TS_RESP_CTX_SET_STATUS_INFO:132:TS_RESP_CTX_set_status_info
-TS_F_TS_RESP_GET_POLICY:133:ts_RESP_get_policy
-TS_F_TS_RESP_SET_GENTIME_WITH_PRECISION:134:TS_RESP_set_genTime_with_precision
-TS_F_TS_RESP_SET_STATUS_INFO:135:TS_RESP_set_status_info
-TS_F_TS_RESP_SET_TST_INFO:150:TS_RESP_set_tst_info
-TS_F_TS_RESP_SIGN:136:ts_RESP_sign
-TS_F_TS_RESP_VERIFY_SIGNATURE:106:TS_RESP_verify_signature
-TS_F_TS_TST_INFO_SET_ACCURACY:137:TS_TST_INFO_set_accuracy
-TS_F_TS_TST_INFO_SET_MSG_IMPRINT:138:TS_TST_INFO_set_msg_imprint
-TS_F_TS_TST_INFO_SET_NONCE:139:TS_TST_INFO_set_nonce
-TS_F_TS_TST_INFO_SET_POLICY_ID:140:TS_TST_INFO_set_policy_id
-TS_F_TS_TST_INFO_SET_SERIAL:141:TS_TST_INFO_set_serial
-TS_F_TS_TST_INFO_SET_TIME:142:TS_TST_INFO_set_time
-TS_F_TS_TST_INFO_SET_TSA:143:TS_TST_INFO_set_tsa
-TS_F_TS_VERIFY:108:*
-TS_F_TS_VERIFY_CERT:109:ts_verify_cert
-TS_F_TS_VERIFY_CTX_NEW:144:TS_VERIFY_CTX_new
-UI_F_CLOSE_CONSOLE:115:close_console
-UI_F_ECHO_CONSOLE:116:echo_console
-UI_F_GENERAL_ALLOCATE_BOOLEAN:108:general_allocate_boolean
-UI_F_GENERAL_ALLOCATE_PROMPT:109:general_allocate_prompt
-UI_F_NOECHO_CONSOLE:117:noecho_console
-UI_F_OPEN_CONSOLE:114:open_console
-UI_F_UI_CONSTRUCT_PROMPT:121:UI_construct_prompt
-UI_F_UI_CREATE_METHOD:112:UI_create_method
-UI_F_UI_CTRL:111:UI_ctrl
-UI_F_UI_DUP_ERROR_STRING:101:UI_dup_error_string
-UI_F_UI_DUP_INFO_STRING:102:UI_dup_info_string
-UI_F_UI_DUP_INPUT_BOOLEAN:110:UI_dup_input_boolean
-UI_F_UI_DUP_INPUT_STRING:103:UI_dup_input_string
-UI_F_UI_DUP_USER_DATA:118:UI_dup_user_data
-UI_F_UI_DUP_VERIFY_STRING:106:UI_dup_verify_string
-UI_F_UI_GET0_RESULT:107:UI_get0_result
-UI_F_UI_GET_RESULT_LENGTH:119:UI_get_result_length
-UI_F_UI_NEW_METHOD:104:UI_new_method
-UI_F_UI_PROCESS:113:UI_process
-UI_F_UI_SET_RESULT:105:UI_set_result
-UI_F_UI_SET_RESULT_EX:120:UI_set_result_ex
-X509V3_F_A2I_GENERAL_NAME:164:a2i_GENERAL_NAME
-X509V3_F_ADDR_VALIDATE_PATH_INTERNAL:166:addr_validate_path_internal
-X509V3_F_ASIDENTIFIERCHOICE_CANONIZE:161:ASIdentifierChoice_canonize
-X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL:162:ASIdentifierChoice_is_canonical
-X509V3_F_BIGNUM_TO_STRING:167:bignum_to_string
-X509V3_F_COPY_EMAIL:122:copy_email
-X509V3_F_COPY_ISSUER:123:copy_issuer
-X509V3_F_DO_DIRNAME:144:do_dirname
-X509V3_F_DO_EXT_I2D:135:do_ext_i2d
-X509V3_F_DO_EXT_NCONF:151:do_ext_nconf
-X509V3_F_GNAMES_FROM_SECTNAME:156:gnames_from_sectname
-X509V3_F_I2S_ASN1_ENUMERATED:121:i2s_ASN1_ENUMERATED
-X509V3_F_I2S_ASN1_IA5STRING:149:i2s_ASN1_IA5STRING
-X509V3_F_I2S_ASN1_INTEGER:120:i2s_ASN1_INTEGER
-X509V3_F_I2V_AUTHORITY_INFO_ACCESS:138:i2v_AUTHORITY_INFO_ACCESS
-X509V3_F_I2V_AUTHORITY_KEYID:173:i2v_AUTHORITY_KEYID
-X509V3_F_LEVEL_ADD_NODE:168:level_add_node
-X509V3_F_NOTICE_SECTION:132:notice_section
-X509V3_F_NREF_NOS:133:nref_nos
-X509V3_F_POLICY_CACHE_CREATE:169:policy_cache_create
-X509V3_F_POLICY_CACHE_NEW:170:policy_cache_new
-X509V3_F_POLICY_DATA_NEW:171:policy_data_new
-X509V3_F_POLICY_SECTION:131:policy_section
-X509V3_F_PROCESS_PCI_VALUE:150:process_pci_value
-X509V3_F_R2I_CERTPOL:130:r2i_certpol
-X509V3_F_R2I_PCI:155:r2i_pci
-X509V3_F_S2I_ASN1_IA5STRING:100:s2i_ASN1_IA5STRING
-X509V3_F_S2I_ASN1_INTEGER:108:s2i_ASN1_INTEGER
-X509V3_F_S2I_ASN1_OCTET_STRING:112:s2i_ASN1_OCTET_STRING
-X509V3_F_S2I_SKEY_ID:115:s2i_skey_id
-X509V3_F_SET_DIST_POINT_NAME:158:set_dist_point_name
-X509V3_F_SXNET_ADD_ID_ASC:125:SXNET_add_id_asc
-X509V3_F_SXNET_ADD_ID_INTEGER:126:SXNET_add_id_INTEGER
-X509V3_F_SXNET_ADD_ID_ULONG:127:SXNET_add_id_ulong
-X509V3_F_SXNET_GET_ID_ASC:128:SXNET_get_id_asc
-X509V3_F_SXNET_GET_ID_ULONG:129:SXNET_get_id_ulong
-X509V3_F_TREE_INIT:172:tree_init
-X509V3_F_V2I_ASIDENTIFIERS:163:v2i_ASIdentifiers
-X509V3_F_V2I_ASN1_BIT_STRING:101:v2i_ASN1_BIT_STRING
-X509V3_F_V2I_AUTHORITY_INFO_ACCESS:139:v2i_AUTHORITY_INFO_ACCESS
-X509V3_F_V2I_AUTHORITY_KEYID:119:v2i_AUTHORITY_KEYID
-X509V3_F_V2I_BASIC_CONSTRAINTS:102:v2i_BASIC_CONSTRAINTS
-X509V3_F_V2I_CRLD:134:v2i_crld
-X509V3_F_V2I_EXTENDED_KEY_USAGE:103:v2i_EXTENDED_KEY_USAGE
-X509V3_F_V2I_GENERAL_NAMES:118:v2i_GENERAL_NAMES
-X509V3_F_V2I_GENERAL_NAME_EX:117:v2i_GENERAL_NAME_ex
-X509V3_F_V2I_IDP:157:v2i_idp
-X509V3_F_V2I_IPADDRBLOCKS:159:v2i_IPAddrBlocks
-X509V3_F_V2I_ISSUER_ALT:153:v2i_issuer_alt
-X509V3_F_V2I_NAME_CONSTRAINTS:147:v2i_NAME_CONSTRAINTS
-X509V3_F_V2I_POLICY_CONSTRAINTS:146:v2i_POLICY_CONSTRAINTS
-X509V3_F_V2I_POLICY_MAPPINGS:145:v2i_POLICY_MAPPINGS
-X509V3_F_V2I_SUBJECT_ALT:154:v2i_subject_alt
-X509V3_F_V2I_TLS_FEATURE:165:v2i_TLS_FEATURE
-X509V3_F_V3_GENERIC_EXTENSION:116:v3_generic_extension
-X509V3_F_X509V3_ADD1_I2D:140:X509V3_add1_i2d
-X509V3_F_X509V3_ADD_LEN_VALUE:174:x509v3_add_len_value
-X509V3_F_X509V3_ADD_VALUE:105:X509V3_add_value
-X509V3_F_X509V3_EXT_ADD:104:X509V3_EXT_add
-X509V3_F_X509V3_EXT_ADD_ALIAS:106:X509V3_EXT_add_alias
-X509V3_F_X509V3_EXT_I2D:136:X509V3_EXT_i2d
-X509V3_F_X509V3_EXT_NCONF:152:X509V3_EXT_nconf
-X509V3_F_X509V3_GET_SECTION:142:X509V3_get_section
-X509V3_F_X509V3_GET_STRING:143:X509V3_get_string
-X509V3_F_X509V3_GET_VALUE_BOOL:110:X509V3_get_value_bool
-X509V3_F_X509V3_PARSE_LIST:109:X509V3_parse_list
-X509V3_F_X509_PURPOSE_ADD:137:X509_PURPOSE_add
-X509V3_F_X509_PURPOSE_SET:141:X509_PURPOSE_set
-X509_F_ADD_CERT_DIR:100:add_cert_dir
-X509_F_BUILD_CHAIN:106:build_chain
-X509_F_BY_FILE_CTRL:101:by_file_ctrl
-X509_F_CHECK_NAME_CONSTRAINTS:149:check_name_constraints
-X509_F_CHECK_POLICY:145:check_policy
-X509_F_DANE_I2D:107:dane_i2d
-X509_F_DIR_CTRL:102:dir_ctrl
-X509_F_GET_CERT_BY_SUBJECT:103:get_cert_by_subject
-X509_F_I2D_X509_AUX:151:i2d_X509_AUX
-X509_F_LOOKUP_CERTS_SK:152:lookup_certs_sk
-X509_F_NETSCAPE_SPKI_B64_DECODE:129:NETSCAPE_SPKI_b64_decode
-X509_F_NETSCAPE_SPKI_B64_ENCODE:130:NETSCAPE_SPKI_b64_encode
-X509_F_NEW_DIR:153:new_dir
-X509_F_X509AT_ADD1_ATTR:135:X509at_add1_attr
-X509_F_X509V3_ADD_EXT:104:X509v3_add_ext
-X509_F_X509_ATTRIBUTE_CREATE_BY_NID:136:X509_ATTRIBUTE_create_by_NID
-X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ:137:X509_ATTRIBUTE_create_by_OBJ
-X509_F_X509_ATTRIBUTE_CREATE_BY_TXT:140:X509_ATTRIBUTE_create_by_txt
-X509_F_X509_ATTRIBUTE_GET0_DATA:139:X509_ATTRIBUTE_get0_data
-X509_F_X509_ATTRIBUTE_SET1_DATA:138:X509_ATTRIBUTE_set1_data
-X509_F_X509_CHECK_PRIVATE_KEY:128:X509_check_private_key
-X509_F_X509_CRL_DIFF:105:X509_CRL_diff
-X509_F_X509_CRL_METHOD_NEW:154:X509_CRL_METHOD_new
-X509_F_X509_CRL_PRINT_FP:147:X509_CRL_print_fp
-X509_F_X509_EXTENSION_CREATE_BY_NID:108:X509_EXTENSION_create_by_NID
-X509_F_X509_EXTENSION_CREATE_BY_OBJ:109:X509_EXTENSION_create_by_OBJ
-X509_F_X509_GET_PUBKEY_PARAMETERS:110:X509_get_pubkey_parameters
-X509_F_X509_LOAD_CERT_CRL_FILE:132:X509_load_cert_crl_file
-X509_F_X509_LOAD_CERT_FILE:111:X509_load_cert_file
-X509_F_X509_LOAD_CRL_FILE:112:X509_load_crl_file
-X509_F_X509_LOOKUP_METH_NEW:160:X509_LOOKUP_meth_new
-X509_F_X509_LOOKUP_NEW:155:X509_LOOKUP_new
-X509_F_X509_NAME_ADD_ENTRY:113:X509_NAME_add_entry
-X509_F_X509_NAME_CANON:156:x509_name_canon
-X509_F_X509_NAME_ENTRY_CREATE_BY_NID:114:X509_NAME_ENTRY_create_by_NID
-X509_F_X509_NAME_ENTRY_CREATE_BY_TXT:131:X509_NAME_ENTRY_create_by_txt
-X509_F_X509_NAME_ENTRY_SET_OBJECT:115:X509_NAME_ENTRY_set_object
-X509_F_X509_NAME_ONELINE:116:X509_NAME_oneline
-X509_F_X509_NAME_PRINT:117:X509_NAME_print
-X509_F_X509_OBJECT_NEW:150:X509_OBJECT_new
-X509_F_X509_PRINT_EX_FP:118:X509_print_ex_fp
-X509_F_X509_PUBKEY_DECODE:148:x509_pubkey_decode
-X509_F_X509_PUBKEY_GET:161:X509_PUBKEY_get
-X509_F_X509_PUBKEY_GET0:119:X509_PUBKEY_get0
-X509_F_X509_PUBKEY_SET:120:X509_PUBKEY_set
-X509_F_X509_REQ_CHECK_PRIVATE_KEY:144:X509_REQ_check_private_key
-X509_F_X509_REQ_PRINT_EX:121:X509_REQ_print_ex
-X509_F_X509_REQ_PRINT_FP:122:X509_REQ_print_fp
-X509_F_X509_REQ_TO_X509:123:X509_REQ_to_X509
-X509_F_X509_STORE_ADD_CERT:124:X509_STORE_add_cert
-X509_F_X509_STORE_ADD_CRL:125:X509_STORE_add_crl
-X509_F_X509_STORE_ADD_LOOKUP:157:X509_STORE_add_lookup
-X509_F_X509_STORE_CTX_GET1_ISSUER:146:X509_STORE_CTX_get1_issuer
-X509_F_X509_STORE_CTX_INIT:143:X509_STORE_CTX_init
-X509_F_X509_STORE_CTX_NEW:142:X509_STORE_CTX_new
-X509_F_X509_STORE_CTX_PURPOSE_INHERIT:134:X509_STORE_CTX_purpose_inherit
-X509_F_X509_STORE_NEW:158:X509_STORE_new
-X509_F_X509_TO_X509_REQ:126:X509_to_X509_REQ
-X509_F_X509_TRUST_ADD:133:X509_TRUST_add
-X509_F_X509_TRUST_SET:141:X509_TRUST_set
-X509_F_X509_VERIFY_CERT:127:X509_verify_cert
-X509_F_X509_VERIFY_PARAM_NEW:159:X509_VERIFY_PARAM_new
-
#Reason codes
ASN1_R_ADDING_OBJECT:171:adding object
ASN1_R_ASN1_PARSE_ERROR:203:asn1 parse error
@@ -1831,6 +66,7 @@ ASN1_R_INVALID_STRING_TABLE_VALUE:218:invalid string table value
ASN1_R_INVALID_UNIVERSALSTRING_LENGTH:133:invalid universalstring length
ASN1_R_INVALID_UTF8STRING:134:invalid utf8string
ASN1_R_INVALID_VALUE:219:invalid value
+ASN1_R_LENGTH_TOO_LONG:231:length too long
ASN1_R_LIST_ERROR:188:list error
ASN1_R_MIME_NO_CONTENT_TYPE:206:mime no content type
ASN1_R_MIME_PARSE_ERROR:207:mime parse error
@@ -1872,6 +108,7 @@ ASN1_R_TYPE_NOT_CONSTRUCTED:156:type not constructed
ASN1_R_TYPE_NOT_PRIMITIVE:195:type not primitive
ASN1_R_UNEXPECTED_EOC:159:unexpected eoc
ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH:215:universalstring is wrong length
+ASN1_R_UNKNOWN_DIGEST:229:unknown digest
ASN1_R_UNKNOWN_FORMAT:160:unknown format
ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM:161:unknown message digest algorithm
ASN1_R_UNKNOWN_OBJECT_TYPE:162:unknown object type
@@ -1895,6 +132,7 @@ BIO_R_AMBIGUOUS_HOST_OR_SERVICE:129:ambiguous host or service
BIO_R_BAD_FOPEN_MODE:101:bad fopen mode
BIO_R_BROKEN_PIPE:124:broken pipe
BIO_R_CONNECT_ERROR:103:connect error
+BIO_R_CONNECT_TIMEOUT:147:connect timeout
BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET:107:gethostbyname addr is not af inet
BIO_R_GETSOCKNAME_ERROR:132:getsockname error
BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS:133:getsockname truncated address
@@ -1912,7 +150,8 @@ BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED:143:\
BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED:144:no hostname or service specified
BIO_R_NO_PORT_DEFINED:113:no port defined
BIO_R_NO_SUCH_FILE:128:no such file
-BIO_R_NULL_PARAMETER:115:null parameter
+BIO_R_TRANSFER_ERROR:104:transfer error
+BIO_R_TRANSFER_TIMEOUT:105:transfer timeout
BIO_R_UNABLE_TO_BIND_SOCKET:117:unable to bind socket
BIO_R_UNABLE_TO_CREATE_SOCKET:118:unable to create socket
BIO_R_UNABLE_TO_KEEPALIVE:137:unable to keepalive
@@ -1942,16 +181,109 @@ BN_R_INVALID_SHIFT:119:invalid shift
BN_R_NOT_A_SQUARE:111:not a square
BN_R_NOT_INITIALIZED:107:not initialized
BN_R_NO_INVERSE:108:no inverse
+BN_R_NO_PRIME_CANDIDATE:121:no prime candidate
BN_R_NO_SOLUTION:116:no solution
+BN_R_NO_SUITABLE_DIGEST:120:no suitable digest
BN_R_PRIVATE_KEY_TOO_LARGE:117:private key too large
BN_R_P_IS_NOT_PRIME:112:p is not prime
BN_R_TOO_MANY_ITERATIONS:113:too many iterations
BN_R_TOO_MANY_TEMPORARY_VARIABLES:109:too many temporary variables
+CMP_R_ALGORITHM_NOT_SUPPORTED:139:algorithm not supported
+CMP_R_BAD_CHECKAFTER_IN_POLLREP:167:bad checkafter in pollrep
+CMP_R_BAD_REQUEST_ID:108:bad request id
+CMP_R_CERTHASH_UNMATCHED:156:certhash unmatched
+CMP_R_CERTID_NOT_FOUND:109:certid not found
+CMP_R_CERTIFICATE_NOT_ACCEPTED:169:certificate not accepted
+CMP_R_CERTIFICATE_NOT_FOUND:112:certificate not found
+CMP_R_CERTREQMSG_NOT_FOUND:157:certreqmsg not found
+CMP_R_CERTRESPONSE_NOT_FOUND:113:certresponse not found
+CMP_R_CERT_AND_KEY_DO_NOT_MATCH:114:cert and key do not match
+CMP_R_CHECKAFTER_OUT_OF_RANGE:181:checkafter out of range
+CMP_R_ENCOUNTERED_KEYUPDATEWARNING:176:encountered keyupdatewarning
+CMP_R_ENCOUNTERED_WAITING:162:encountered waiting
+CMP_R_ERROR_CALCULATING_PROTECTION:115:error calculating protection
+CMP_R_ERROR_CREATING_CERTCONF:116:error creating certconf
+CMP_R_ERROR_CREATING_CERTREP:117:error creating certrep
+CMP_R_ERROR_CREATING_CERTREQ:163:error creating certreq
+CMP_R_ERROR_CREATING_ERROR:118:error creating error
+CMP_R_ERROR_CREATING_GENM:119:error creating genm
+CMP_R_ERROR_CREATING_GENP:120:error creating genp
+CMP_R_ERROR_CREATING_PKICONF:122:error creating pkiconf
+CMP_R_ERROR_CREATING_POLLREP:123:error creating pollrep
+CMP_R_ERROR_CREATING_POLLREQ:124:error creating pollreq
+CMP_R_ERROR_CREATING_RP:125:error creating rp
+CMP_R_ERROR_CREATING_RR:126:error creating rr
+CMP_R_ERROR_PARSING_PKISTATUS:107:error parsing pkistatus
+CMP_R_ERROR_PROCESSING_MESSAGE:158:error processing message
+CMP_R_ERROR_PROTECTING_MESSAGE:127:error protecting message
+CMP_R_ERROR_SETTING_CERTHASH:128:error setting certhash
+CMP_R_ERROR_UNEXPECTED_CERTCONF:160:error unexpected certconf
+CMP_R_ERROR_VALIDATING_PROTECTION:140:error validating protection
+CMP_R_ERROR_VALIDATING_SIGNATURE:171:error validating signature
+CMP_R_FAILED_BUILDING_OWN_CHAIN:164:failed building own chain
+CMP_R_FAILED_EXTRACTING_PUBKEY:141:failed extracting pubkey
+CMP_R_FAILURE_OBTAINING_RANDOM:110:failure obtaining random
+CMP_R_FAIL_INFO_OUT_OF_RANGE:129:fail info out of range
+CMP_R_INVALID_ARGS:100:invalid args
+CMP_R_INVALID_OPTION:174:invalid option
+CMP_R_MISSING_CERTID:165:missing certid
+CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION:130:\
+ missing key input for creating protection
+CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE:142:missing key usage digitalsignature
+CMP_R_MISSING_P10CSR:121:missing p10csr
+CMP_R_MISSING_PBM_SECRET:166:missing pbm secret
+CMP_R_MISSING_PRIVATE_KEY:131:missing private key
+CMP_R_MISSING_PROTECTION:143:missing protection
+CMP_R_MISSING_REFERENCE_CERT:168:missing reference cert
+CMP_R_MISSING_SECRET:178:missing secret
+CMP_R_MISSING_SENDER_IDENTIFICATION:111:missing sender identification
+CMP_R_MISSING_TRUST_ANCHOR:179:missing trust anchor
+CMP_R_MISSING_TRUST_STORE:144:missing trust store
+CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED:161:multiple requests not supported
+CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED:170:multiple responses not supported
+CMP_R_MULTIPLE_SAN_SOURCES:102:multiple san sources
+CMP_R_NO_STDIO:194:no stdio
+CMP_R_NO_SUITABLE_SENDER_CERT:145:no suitable sender cert
+CMP_R_NULL_ARGUMENT:103:null argument
+CMP_R_PKIBODY_ERROR:146:pkibody error
+CMP_R_PKISTATUSINFO_NOT_FOUND:132:pkistatusinfo not found
+CMP_R_POLLING_FAILED:172:polling failed
+CMP_R_POTENTIALLY_INVALID_CERTIFICATE:147:potentially invalid certificate
+CMP_R_RECEIVED_ERROR:180:received error
+CMP_R_RECIPNONCE_UNMATCHED:148:recipnonce unmatched
+CMP_R_REQUEST_NOT_ACCEPTED:149:request not accepted
+CMP_R_REQUEST_REJECTED_BY_SERVER:182:request rejected by server
+CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED:150:\
+ sender generalname type not supported
+CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG:151:srvcert does not validate msg
+CMP_R_TOTAL_TIMEOUT:184:total timeout
+CMP_R_TRANSACTIONID_UNMATCHED:152:transactionid unmatched
+CMP_R_TRANSFER_ERROR:159:transfer error
+CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody
+CMP_R_UNEXPECTED_PKISTATUS:185:unexpected pkistatus
+CMP_R_UNEXPECTED_PVNO:153:unexpected pvno
+CMP_R_UNKNOWN_ALGORITHM_ID:134:unknown algorithm id
+CMP_R_UNKNOWN_CERT_TYPE:135:unknown cert type
+CMP_R_UNKNOWN_PKISTATUS:186:unknown pkistatus
+CMP_R_UNSUPPORTED_ALGORITHM:136:unsupported algorithm
+CMP_R_UNSUPPORTED_KEY_TYPE:137:unsupported key type
+CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC:154:\
+ unsupported protection alg dhbasedmac
+CMP_R_VALUE_TOO_LARGE:175:value too large
+CMP_R_VALUE_TOO_SMALL:177:value too small
+CMP_R_WRONG_ALGORITHM_OID:138:wrong algorithm oid
+CMP_R_WRONG_CERTID:189:wrong certid
+CMP_R_WRONG_CERTID_IN_RP:187:wrong certid in rp
+CMP_R_WRONG_PBM_VALUE:155:wrong pbm value
+CMP_R_WRONG_RP_COMPONENT_COUNT:188:wrong rp component count
+CMP_R_WRONG_SERIAL_IN_RP:173:wrong serial in rp
CMS_R_ADD_SIGNER_ERROR:99:add signer error
CMS_R_ATTRIBUTE_ERROR:161:attribute error
CMS_R_CERTIFICATE_ALREADY_PRESENT:175:certificate already present
CMS_R_CERTIFICATE_HAS_NO_KEYID:160:certificate has no keyid
CMS_R_CERTIFICATE_VERIFY_ERROR:100:certificate verify error
+CMS_R_CIPHER_AEAD_SET_TAG_ERROR:184:cipher aead set tag error
+CMS_R_CIPHER_GET_TAG:185:cipher get tag
CMS_R_CIPHER_INITIALISATION_ERROR:101:cipher initialisation error
CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR:102:\
cipher parameter initialisation error
@@ -1966,15 +298,20 @@ CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA:108:content type not signed data
CMS_R_CONTENT_VERIFY_ERROR:109:content verify error
CMS_R_CTRL_ERROR:110:ctrl error
CMS_R_CTRL_FAILURE:111:ctrl failure
+CMS_R_DECODE_ERROR:187:decode error
CMS_R_DECRYPT_ERROR:112:decrypt error
CMS_R_ERROR_GETTING_PUBLIC_KEY:113:error getting public key
CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE:114:\
error reading messagedigest attribute
CMS_R_ERROR_SETTING_KEY:115:error setting key
CMS_R_ERROR_SETTING_RECIPIENTINFO:116:error setting recipientinfo
+CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR:183:ess signing certid mismatch error
CMS_R_INVALID_ENCRYPTED_KEY_LENGTH:117:invalid encrypted key length
CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER:176:invalid key encryption parameter
CMS_R_INVALID_KEY_LENGTH:118:invalid key length
+CMS_R_INVALID_LABEL:190:invalid label
+CMS_R_INVALID_OAEP_PARAMETERS:191:invalid oaep parameters
+CMS_R_KDF_PARAMETER_ERROR:186:kdf parameter error
CMS_R_MD_BIO_INIT_ERROR:119:md bio init error
CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH:120:\
messagedigest attribute wrong length
@@ -2006,10 +343,12 @@ CMS_R_NO_PRIVATE_KEY:133:no private key
CMS_R_NO_PUBLIC_KEY:134:no public key
CMS_R_NO_RECEIPT_REQUEST:168:no receipt request
CMS_R_NO_SIGNERS:135:no signers
+CMS_R_PEER_KEY_ERROR:188:peer key error
CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:136:\
private key does not match certificate
CMS_R_RECEIPT_DECODE_ERROR:169:receipt decode error
CMS_R_RECIPIENT_ERROR:137:recipient error
+CMS_R_SHARED_INFO_ERROR:189:shared info error
CMS_R_SIGNER_CERTIFICATE_NOT_FOUND:138:signer certificate not found
CMS_R_SIGNFINAL_ERROR:139:signfinal error
CMS_R_SMIME_TEXT_ERROR:140:smime text error
@@ -2027,9 +366,11 @@ CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM:151:unsupported compression algorithm
CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM:194:\
unsupported content encryption algorithm
CMS_R_UNSUPPORTED_CONTENT_TYPE:152:unsupported content type
+CMS_R_UNSUPPORTED_ENCRYPTION_TYPE:192:unsupported encryption type
CMS_R_UNSUPPORTED_KEK_ALGORITHM:153:unsupported kek algorithm
CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM:179:\
unsupported key encryption algorithm
+CMS_R_UNSUPPORTED_LABEL_SOURCE:193:unsupported label source
CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE:155:unsupported recipientinfo type
CMS_R_UNSUPPORTED_RECIPIENT_TYPE:154:unsupported recipient type
CMS_R_UNSUPPORTED_TYPE:156:unsupported type
@@ -2041,7 +382,10 @@ COMP_R_ZLIB_DEFLATE_ERROR:99:zlib deflate error
COMP_R_ZLIB_INFLATE_ERROR:100:zlib inflate error
COMP_R_ZLIB_NOT_SUPPORTED:101:zlib not supported
CONF_R_ERROR_LOADING_DSO:110:error loading dso
+CONF_R_INVALID_PRAGMA:122:invalid pragma
CONF_R_LIST_CANNOT_BE_NULL:115:list cannot be null
+CONF_R_MANDATORY_BRACES_IN_VARIABLE_EXPANSION:123:\
+ mandatory braces in variable expansion
CONF_R_MISSING_CLOSE_SQUARE_BRACKET:100:missing close square bracket
CONF_R_MISSING_EQUAL_SIGN:101:missing equal sign
CONF_R_MISSING_INIT_FUNCTION:112:missing init function
@@ -2053,7 +397,10 @@ CONF_R_NO_SECTION:107:no section
CONF_R_NO_SUCH_FILE:114:no such file
CONF_R_NO_VALUE:108:no value
CONF_R_NUMBER_TOO_LARGE:121:number too large
+CONF_R_OPENSSL_CONF_REFERENCES_MISSING_SECTION:124:\
+ openssl conf references missing section
CONF_R_RECURSIVE_DIRECTORY_INCLUDE:111:recursive directory include
+CONF_R_RELATIVE_PATH:125:relative path
CONF_R_SSL_COMMAND_SECTION_EMPTY:117:ssl command section empty
CONF_R_SSL_COMMAND_SECTION_NOT_FOUND:118:ssl command section not found
CONF_R_SSL_SECTION_EMPTY:119:ssl section empty
@@ -2062,9 +409,50 @@ CONF_R_UNABLE_TO_CREATE_NEW_SECTION:103:unable to create new section
CONF_R_UNKNOWN_MODULE_NAME:113:unknown module name
CONF_R_VARIABLE_EXPANSION_TOO_LONG:116:variable expansion too long
CONF_R_VARIABLE_HAS_NO_VALUE:104:variable has no value
-CRYPTO_R_FIPS_MODE_NOT_SUPPORTED:101:fips mode not supported
+CRMF_R_BAD_PBM_ITERATIONCOUNT:100:bad pbm iterationcount
+CRMF_R_CRMFERROR:102:crmferror
+CRMF_R_ERROR:103:error
+CRMF_R_ERROR_DECODING_CERTIFICATE:104:error decoding certificate
+CRMF_R_ERROR_DECRYPTING_CERTIFICATE:105:error decrypting certificate
+CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY:106:error decrypting symmetric key
+CRMF_R_FAILURE_OBTAINING_RANDOM:107:failure obtaining random
+CRMF_R_ITERATIONCOUNT_BELOW_100:108:iterationcount below 100
+CRMF_R_MALFORMED_IV:101:malformed iv
+CRMF_R_NULL_ARGUMENT:109:null argument
+CRMF_R_POPOSKINPUT_NOT_SUPPORTED:113:poposkinput not supported
+CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY:117:popo inconsistent public key
+CRMF_R_POPO_MISSING:121:popo missing
+CRMF_R_POPO_MISSING_PUBLIC_KEY:118:popo missing public key
+CRMF_R_POPO_MISSING_SUBJECT:119:popo missing subject
+CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED:120:popo raverified not accepted
+CRMF_R_SETTING_MAC_ALGOR_FAILURE:110:setting mac algor failure
+CRMF_R_SETTING_OWF_ALGOR_FAILURE:111:setting owf algor failure
+CRMF_R_UNSUPPORTED_ALGORITHM:112:unsupported algorithm
+CRMF_R_UNSUPPORTED_CIPHER:114:unsupported cipher
+CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO:115:\
+ unsupported method for creating popo
+CRMF_R_UNSUPPORTED_POPO_METHOD:116:unsupported popo method
+CRYPTO_R_BAD_ALGORITHM_NAME:117:bad algorithm name
+CRYPTO_R_CONFLICTING_NAMES:118:conflicting names
+CRYPTO_R_HEX_STRING_TOO_SHORT:121:hex string too short
CRYPTO_R_ILLEGAL_HEX_DIGIT:102:illegal hex digit
+CRYPTO_R_INSUFFICIENT_DATA_SPACE:106:insufficient data space
+CRYPTO_R_INSUFFICIENT_PARAM_SIZE:107:insufficient param size
+CRYPTO_R_INSUFFICIENT_SECURE_DATA_SPACE:108:insufficient secure data space
+CRYPTO_R_INVALID_NEGATIVE_VALUE:122:invalid negative value
+CRYPTO_R_INVALID_NULL_ARGUMENT:109:invalid null argument
+CRYPTO_R_INVALID_OSSL_PARAM_TYPE:110:invalid ossl param type
CRYPTO_R_ODD_NUMBER_OF_DIGITS:103:odd number of digits
+CRYPTO_R_PROVIDER_ALREADY_EXISTS:104:provider already exists
+CRYPTO_R_PROVIDER_SECTION_ERROR:105:provider section error
+CRYPTO_R_RANDOM_SECTION_ERROR:119:random section error
+CRYPTO_R_SECURE_MALLOC_FAILURE:111:secure malloc failure
+CRYPTO_R_STRING_TOO_LONG:112:string too long
+CRYPTO_R_TOO_MANY_BYTES:113:too many bytes
+CRYPTO_R_TOO_MANY_RECORDS:114:too many records
+CRYPTO_R_TOO_SMALL_BUFFER:116:too small buffer
+CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION:120:unknown name in random section
+CRYPTO_R_ZERO_LENGTH_NUMBER:115:zero length number
CT_R_BASE64_DECODE_ERROR:108:base64 decode error
CT_R_INVALID_LOG_ID_LENGTH:100:invalid log id length
CT_R_LOG_CONF_INVALID:109:log conf invalid
@@ -2082,6 +470,7 @@ CT_R_SCT_UNSUPPORTED_VERSION:115:sct unsupported version
CT_R_UNRECOGNIZED_SIGNATURE_NID:101:unrecognized signature nid
CT_R_UNSUPPORTED_ENTRY_TYPE:102:unsupported entry type
CT_R_UNSUPPORTED_VERSION:103:unsupported version
+DH_R_BAD_FFC_PARAMETERS:127:bad ffc parameters
DH_R_BAD_GENERATOR:101:bad generator
DH_R_BN_DECODE_ERROR:109:bn decode error
DH_R_BN_ERROR:106:bn error
@@ -2097,10 +486,12 @@ DH_R_DECODE_ERROR:104:decode error
DH_R_INVALID_PARAMETER_NAME:110:invalid parameter name
DH_R_INVALID_PARAMETER_NID:114:invalid parameter nid
DH_R_INVALID_PUBKEY:102:invalid public key
+DH_R_INVALID_SECRET:128:invalid secret
DH_R_KDF_PARAMETER_ERROR:112:kdf parameter error
DH_R_KEYS_NOT_SET:108:keys not set
DH_R_MISSING_PUBKEY:125:missing pubkey
DH_R_MODULUS_TOO_LARGE:103:modulus too large
+DH_R_MODULUS_TOO_SMALL:126:modulus too small
DH_R_NOT_SUITABLE_GENERATOR:120:not suitable generator
DH_R_NO_PARAMETERS_SET:107:no parameters set
DH_R_NO_PRIVATE_VALUE:100:no private value
@@ -2108,6 +499,7 @@ DH_R_PARAMETER_ENCODING_ERROR:105:parameter encoding error
DH_R_PEER_KEY_ERROR:111:peer key error
DH_R_SHARED_INFO_ERROR:113:shared info error
DH_R_UNABLE_TO_CHECK_GENERATOR:121:unable to check generator
+DSA_R_BAD_FFC_PARAMETERS:114:bad ffc parameters
DSA_R_BAD_Q_VALUE:102:bad q value
DSA_R_BN_DECODE_ERROR:108:bn decode error
DSA_R_BN_ERROR:109:bn error
@@ -2119,6 +511,7 @@ DSA_R_MISSING_PRIVATE_KEY:111:missing private key
DSA_R_MODULUS_TOO_LARGE:103:modulus too large
DSA_R_NO_PARAMETERS_SET:107:no parameters set
DSA_R_PARAMETER_ENCODING_ERROR:105:parameter encoding error
+DSA_R_P_NOT_PRIME:115:p not prime
DSA_R_Q_NOT_PRIME:113:q not prime
DSA_R_SEED_LEN_SMALL:110:seed_len is less than the length of q
DSO_R_CTRL_FAILED:100:control command failed
@@ -2144,17 +537,22 @@ EC_R_BUFFER_TOO_SMALL:100:buffer too small
EC_R_CANNOT_INVERT:165:cannot invert
EC_R_COORDINATES_OUT_OF_RANGE:146:coordinates out of range
EC_R_CURVE_DOES_NOT_SUPPORT_ECDH:160:curve does not support ecdh
+EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA:170:curve does not support ecdsa
EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING:159:curve does not support signing
-EC_R_D2I_ECPKPARAMETERS_FAILURE:117:d2i ecpkparameters failure
EC_R_DECODE_ERROR:142:decode error
EC_R_DISCRIMINANT_IS_ZERO:118:discriminant is zero
EC_R_EC_GROUP_NEW_BY_NAME_FAILURE:119:ec group new by name failure
+EC_R_EXPLICIT_PARAMS_NOT_SUPPORTED:127:explicit params not supported
+EC_R_FAILED_MAKING_PUBLIC_KEY:166:failed making public key
EC_R_FIELD_TOO_LARGE:143:field too large
EC_R_GF2M_NOT_SUPPORTED:147:gf2m not supported
EC_R_GROUP2PKPARAMETERS_FAILURE:120:group2pkparameters failure
EC_R_I2D_ECPKPARAMETERS_FAILURE:121:i2d ecpkparameters failure
EC_R_INCOMPATIBLE_OBJECTS:101:incompatible objects
+EC_R_INVALID_A:168:invalid a
EC_R_INVALID_ARGUMENT:112:invalid argument
+EC_R_INVALID_B:169:invalid b
+EC_R_INVALID_COFACTOR:171:invalid cofactor
EC_R_INVALID_COMPRESSED_POINT:110:invalid compressed point
EC_R_INVALID_COMPRESSION_BIT:109:invalid compression bit
EC_R_INVALID_CURVE:141:invalid curve
@@ -2163,12 +561,17 @@ EC_R_INVALID_DIGEST_TYPE:138:invalid digest type
EC_R_INVALID_ENCODING:102:invalid encoding
EC_R_INVALID_FIELD:103:invalid field
EC_R_INVALID_FORM:104:invalid form
+EC_R_INVALID_GENERATOR:173:invalid generator
EC_R_INVALID_GROUP_ORDER:122:invalid group order
EC_R_INVALID_KEY:116:invalid key
+EC_R_INVALID_LENGTH:117:invalid length
+EC_R_INVALID_NAMED_GROUP_CONVERSION:174:invalid named group conversion
EC_R_INVALID_OUTPUT_LENGTH:161:invalid output length
+EC_R_INVALID_P:172:invalid p
EC_R_INVALID_PEER_KEY:133:invalid peer key
EC_R_INVALID_PENTANOMIAL_BASIS:132:invalid pentanomial basis
EC_R_INVALID_PRIVATE_KEY:123:invalid private key
+EC_R_INVALID_SEED:175:invalid seed
EC_R_INVALID_TRINOMIAL_BASIS:137:invalid trinomial basis
EC_R_KDF_PARAMETER_ERROR:148:kdf parameter error
EC_R_KEYS_NOT_SET:140:keys not set
@@ -2187,7 +590,6 @@ EC_R_NO_PRIVATE_VALUE:154:no private value
EC_R_OPERATION_NOT_SUPPORTED:152:operation not supported
EC_R_PASSED_NULL_PARAMETER:134:passed null parameter
EC_R_PEER_KEY_ERROR:149:peer key error
-EC_R_PKPARAMETERS2GROUP_FAILURE:127:pkparameters2group failure
EC_R_POINT_ARITHMETIC_FAILURE:155:point arithmetic failure
EC_R_POINT_AT_INFINITY:106:point at infinity
EC_R_POINT_COORDINATES_BLIND_FAILURE:163:point coordinates blind failure
@@ -2238,58 +640,92 @@ ENGINE_R_UNIMPLEMENTED_CIPHER:146:unimplemented cipher
ENGINE_R_UNIMPLEMENTED_DIGEST:147:unimplemented digest
ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD:101:unimplemented public key method
ENGINE_R_VERSION_INCOMPATIBILITY:145:version incompatibility
+ESS_R_EMPTY_ESS_CERT_ID_LIST:107:empty ess cert id list
+ESS_R_ESS_CERT_DIGEST_ERROR:103:ess cert digest error
+ESS_R_ESS_CERT_ID_NOT_FOUND:104:ess cert id not found
+ESS_R_ESS_CERT_ID_WRONG_ORDER:105:ess cert id wrong order
+ESS_R_ESS_DIGEST_ALG_UNKNOWN:106:ess digest alg unknown
+ESS_R_ESS_SIGNING_CERTIFICATE_ERROR:102:ess signing certificate error
+ESS_R_ESS_SIGNING_CERT_ADD_ERROR:100:ess signing cert add error
+ESS_R_ESS_SIGNING_CERT_V2_ADD_ERROR:101:ess signing cert v2 add error
+ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE:108:\
+ missing signing certificate attribute
EVP_R_AES_KEY_SETUP_FAILED:143:aes key setup failed
EVP_R_ARIA_KEY_SETUP_FAILED:176:aria key setup failed
+EVP_R_BAD_ALGORITHM_NAME:200:bad algorithm name
EVP_R_BAD_DECRYPT:100:bad decrypt
EVP_R_BAD_KEY_LENGTH:195:bad key length
EVP_R_BUFFER_TOO_SMALL:155:buffer too small
+EVP_R_CACHE_CONSTANTS_FAILED:225:cache constants failed
EVP_R_CAMELLIA_KEY_SETUP_FAILED:157:camellia key setup failed
+EVP_R_CANNOT_GET_PARAMETERS:197:cannot get parameters
+EVP_R_CANNOT_SET_PARAMETERS:198:cannot set parameters
+EVP_R_CIPHER_NOT_GCM_MODE:184:cipher not gcm mode
EVP_R_CIPHER_PARAMETER_ERROR:122:cipher parameter error
EVP_R_COMMAND_NOT_SUPPORTED:147:command not supported
+EVP_R_CONFLICTING_ALGORITHM_NAME:201:conflicting algorithm name
EVP_R_COPY_ERROR:173:copy error
EVP_R_CTRL_NOT_IMPLEMENTED:132:ctrl not implemented
EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED:133:ctrl operation not implemented
EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH:138:data not multiple of block length
EVP_R_DECODE_ERROR:114:decode error
+EVP_R_DEFAULT_QUERY_PARSE_ERROR:210:default query parse error
EVP_R_DIFFERENT_KEY_TYPES:101:different key types
EVP_R_DIFFERENT_PARAMETERS:153:different parameters
EVP_R_ERROR_LOADING_SECTION:165:error loading section
-EVP_R_ERROR_SETTING_FIPS_MODE:166:error setting fips mode
EVP_R_EXPECTING_AN_HMAC_KEY:174:expecting an hmac key
EVP_R_EXPECTING_AN_RSA_KEY:127:expecting an rsa key
EVP_R_EXPECTING_A_DH_KEY:128:expecting a dh key
EVP_R_EXPECTING_A_DSA_KEY:129:expecting a dsa key
-EVP_R_EXPECTING_A_EC_KEY:142:expecting a ec key
+EVP_R_EXPECTING_A_ECX_KEY:219:expecting an ecx key
+EVP_R_EXPECTING_A_EC_KEY:142:expecting an ec key
EVP_R_EXPECTING_A_POLY1305_KEY:164:expecting a poly1305 key
EVP_R_EXPECTING_A_SIPHASH_KEY:175:expecting a siphash key
-EVP_R_FIPS_MODE_NOT_SUPPORTED:167:fips mode not supported
+EVP_R_FINAL_ERROR:188:final error
+EVP_R_GENERATE_ERROR:214:generate error
EVP_R_GET_RAW_KEY_FAILED:182:get raw key failed
EVP_R_ILLEGAL_SCRYPT_PARAMETERS:171:illegal scrypt parameters
+EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS:204:inaccessible domain parameters
+EVP_R_INACCESSIBLE_KEY:203:inaccessible key
EVP_R_INITIALIZATION_ERROR:134:initialization error
EVP_R_INPUT_NOT_INITIALIZED:111:input not initialized
+EVP_R_INVALID_CUSTOM_LENGTH:185:invalid custom length
EVP_R_INVALID_DIGEST:152:invalid digest
-EVP_R_INVALID_FIPS_MODE:168:invalid fips mode
EVP_R_INVALID_IV_LENGTH:194:invalid iv length
EVP_R_INVALID_KEY:163:invalid key
EVP_R_INVALID_KEY_LENGTH:130:invalid key length
+EVP_R_INVALID_LENGTH:221:invalid length
+EVP_R_INVALID_NULL_ALGORITHM:218:invalid null algorithm
EVP_R_INVALID_OPERATION:148:invalid operation
-EVP_R_KEYGEN_FAILURE:120:keygen failure
+EVP_R_INVALID_PROVIDER_FUNCTIONS:193:invalid provider functions
+EVP_R_INVALID_SALT_LENGTH:186:invalid salt length
+EVP_R_INVALID_SECRET_LENGTH:223:invalid secret length
+EVP_R_INVALID_SEED_LENGTH:220:invalid seed length
+EVP_R_INVALID_VALUE:222:invalid value
+EVP_R_KEYMGMT_EXPORT_FAILURE:205:keymgmt export failure
EVP_R_KEY_SETUP_FAILED:180:key setup failed
+EVP_R_LOCKING_NOT_SUPPORTED:213:locking not supported
EVP_R_MEMORY_LIMIT_EXCEEDED:172:memory limit exceeded
EVP_R_MESSAGE_DIGEST_IS_NULL:159:message digest is null
EVP_R_METHOD_NOT_SUPPORTED:144:method not supported
EVP_R_MISSING_PARAMETERS:103:missing parameters
+EVP_R_NOT_ABLE_TO_COPY_CTX:190:not able to copy ctx
EVP_R_NOT_XOF_OR_INVALID_LENGTH:178:not XOF or invalid length
EVP_R_NO_CIPHER_SET:131:no cipher set
EVP_R_NO_DEFAULT_DIGEST:158:no default digest
EVP_R_NO_DIGEST_SET:139:no digest set
+EVP_R_NO_IMPORT_FUNCTION:206:no import function
+EVP_R_NO_KEYMGMT_AVAILABLE:199:no keymgmt available
+EVP_R_NO_KEYMGMT_PRESENT:196:no keymgmt present
EVP_R_NO_KEY_SET:154:no key set
EVP_R_NO_OPERATION_SET:149:no operation set
+EVP_R_NULL_MAC_PKEY_CTX:208:null mac pkey ctx
EVP_R_ONLY_ONESHOT_SUPPORTED:177:only oneshot supported
+EVP_R_OPERATION_NOT_INITIALIZED:151:operation not initialized
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:150:\
operation not supported for this keytype
-EVP_R_OPERATON_NOT_INITIALIZED:151:operaton not initialized
-EVP_R_OUTPUT_WOULD_OVERFLOW:184:output would overflow
+EVP_R_OUTPUT_WOULD_OVERFLOW:202:output would overflow
+EVP_R_PARAMETER_TOO_LARGE:187:parameter too large
EVP_R_PARTIALLY_OVERLAPPING:162:partially overlapping buffers
EVP_R_PBKDF2_ERROR:181:pbkdf2 error
EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED:179:\
@@ -2297,8 +733,17 @@ EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED:179:\
EVP_R_PRIVATE_KEY_DECODE_ERROR:145:private key decode error
EVP_R_PRIVATE_KEY_ENCODE_ERROR:146:private key encode error
EVP_R_PUBLIC_KEY_NOT_RSA:106:public key not rsa
+EVP_R_SETTING_XOF_FAILED:227:setting xof failed
+EVP_R_SET_DEFAULT_PROPERTY_FAILURE:209:set default property failure
+EVP_R_TOO_MANY_RECORDS:183:too many records
+EVP_R_UNABLE_TO_ENABLE_LOCKING:212:unable to enable locking
+EVP_R_UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE:215:unable to get maximum request size
+EVP_R_UNABLE_TO_GET_RANDOM_STRENGTH:216:unable to get random strength
+EVP_R_UNABLE_TO_LOCK_CONTEXT:211:unable to lock context
+EVP_R_UNABLE_TO_SET_CALLBACKS:217:unable to set callbacks
EVP_R_UNKNOWN_CIPHER:160:unknown cipher
EVP_R_UNKNOWN_DIGEST:161:unknown digest
+EVP_R_UNKNOWN_KEY_TYPE:207:unknown key type
EVP_R_UNKNOWN_OPTION:169:unknown option
EVP_R_UNKNOWN_PBE_ALGORITHM:121:unknown pbe algorithm
EVP_R_UNSUPPORTED_ALGORITHM:156:unsupported algorithm
@@ -2307,32 +752,55 @@ EVP_R_UNSUPPORTED_KEYLENGTH:123:unsupported keylength
EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION:124:\
unsupported key derivation function
EVP_R_UNSUPPORTED_KEY_SIZE:108:unsupported key size
+EVP_R_UNSUPPORTED_KEY_TYPE:224:unsupported key type
EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS:135:unsupported number of rounds
EVP_R_UNSUPPORTED_PRF:125:unsupported prf
EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM:118:unsupported private key algorithm
EVP_R_UNSUPPORTED_SALT_TYPE:126:unsupported salt type
+EVP_R_UPDATE_ERROR:189:update error
EVP_R_WRAP_MODE_NOT_ALLOWED:170:wrap mode not allowed
EVP_R_WRONG_FINAL_BLOCK_LENGTH:109:wrong final block length
-EVP_R_XTS_DUPLICATED_KEYS:183:xts duplicated keys
-KDF_R_INVALID_DIGEST:100:invalid digest
-KDF_R_MISSING_ITERATION_COUNT:109:missing iteration count
-KDF_R_MISSING_KEY:104:missing key
-KDF_R_MISSING_MESSAGE_DIGEST:105:missing message digest
-KDF_R_MISSING_PARAMETER:101:missing parameter
-KDF_R_MISSING_PASS:110:missing pass
-KDF_R_MISSING_SALT:111:missing salt
-KDF_R_MISSING_SECRET:107:missing secret
-KDF_R_MISSING_SEED:106:missing seed
-KDF_R_UNKNOWN_PARAMETER_TYPE:103:unknown parameter type
-KDF_R_VALUE_ERROR:108:value error
-KDF_R_VALUE_MISSING:102:value missing
+EVP_R_XTS_DATA_UNIT_IS_TOO_LARGE:191:xts data unit is too large
+EVP_R_XTS_DUPLICATED_KEYS:192:xts duplicated keys
+HTTP_R_ASN1_LEN_EXCEEDS_MAX_RESP_LEN:108:asn1 len exceeds max resp len
+HTTP_R_CONNECT_FAILURE:100:connect failure
+HTTP_R_ERROR_PARSING_ASN1_LENGTH:109:error parsing asn1 length
+HTTP_R_ERROR_PARSING_CONTENT_LENGTH:119:error parsing content length
+HTTP_R_ERROR_PARSING_URL:101:error parsing url
+HTTP_R_ERROR_RECEIVING:103:error receiving
+HTTP_R_ERROR_SENDING:102:error sending
+HTTP_R_FAILED_READING_DATA:128:failed reading data
+HTTP_R_HEADER_PARSE_ERROR:126:header parse error
+HTTP_R_INCONSISTENT_CONTENT_LENGTH:120:inconsistent content length
+HTTP_R_INVALID_PORT_NUMBER:123:invalid port number
+HTTP_R_INVALID_URL_PATH:125:invalid url path
+HTTP_R_INVALID_URL_SCHEME:124:invalid url scheme
+HTTP_R_MAX_RESP_LEN_EXCEEDED:117:max resp len exceeded
+HTTP_R_MISSING_ASN1_ENCODING:110:missing asn1 encoding
+HTTP_R_MISSING_CONTENT_TYPE:121:missing content type
+HTTP_R_MISSING_REDIRECT_LOCATION:111:missing redirect location
+HTTP_R_RECEIVED_ERROR:105:received error
+HTTP_R_RECEIVED_WRONG_HTTP_VERSION:106:received wrong http version
+HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP:112:redirection from https to http
+HTTP_R_REDIRECTION_NOT_ENABLED:116:redirection not enabled
+HTTP_R_RESPONSE_LINE_TOO_LONG:113:response line too long
+HTTP_R_RESPONSE_PARSE_ERROR:104:response parse error
+HTTP_R_RETRY_TIMEOUT:129:retry timeout
+HTTP_R_SERVER_CANCELED_CONNECTION:127:server canceled connection
+HTTP_R_SOCK_NOT_SUPPORTED:122:sock not supported
+HTTP_R_STATUS_CODE_UNSUPPORTED:114:status code unsupported
+HTTP_R_TLS_NOT_ENABLED:107:tls not enabled
+HTTP_R_TOO_MANY_REDIRECTIONS:115:too many redirections
+HTTP_R_UNEXPECTED_CONTENT_TYPE:118:unexpected content type
OBJ_R_OID_EXISTS:102:oid exists
OBJ_R_UNKNOWN_NID:101:unknown nid
+OBJ_R_UNKNOWN_OBJECT_NAME:103:unknown object name
OCSP_R_CERTIFICATE_VERIFY_ERROR:101:certificate verify error
OCSP_R_DIGEST_ERR:102:digest err
+OCSP_R_DIGEST_NAME_ERR:106:digest name err
+OCSP_R_DIGEST_SIZE_ERR:107:digest size err
OCSP_R_ERROR_IN_NEXTUPDATE_FIELD:122:error in nextupdate field
OCSP_R_ERROR_IN_THISUPDATE_FIELD:123:error in thisupdate field
-OCSP_R_ERROR_PARSING_URL:121:error parsing url
OCSP_R_MISSING_OCSPSIGNING_USAGE:103:missing ocspsigning usage
OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE:124:nextupdate before thisupdate
OCSP_R_NOT_BASIC_RESPONSE:104:not basic response
@@ -2346,8 +814,6 @@ OCSP_R_REQUEST_NOT_SIGNED:128:request not signed
OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA:111:\
response contains no revocation data
OCSP_R_ROOT_CA_NOT_TRUSTED:112:root ca not trusted
-OCSP_R_SERVER_RESPONSE_ERROR:114:server response error
-OCSP_R_SERVER_RESPONSE_PARSE_ERROR:115:server response parse error
OCSP_R_SIGNATURE_FAILURE:117:signature failure
OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND:118:signer certificate not found
OCSP_R_STATUS_EXPIRED:125:status expired
@@ -2356,6 +822,12 @@ OCSP_R_STATUS_TOO_OLD:127:status too old
OCSP_R_UNKNOWN_MESSAGE_DIGEST:119:unknown message digest
OCSP_R_UNKNOWN_NID:120:unknown nid
OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE:129:unsupported requestorname type
+OSSL_DECODER_R_COULD_NOT_DECODE_OBJECT:101:could not decode object
+OSSL_DECODER_R_DECODER_NOT_FOUND:102:decoder not found
+OSSL_DECODER_R_MISSING_GET_PARAMS:100:missing get params
+OSSL_ENCODER_R_ENCODER_NOT_FOUND:101:encoder not found
+OSSL_ENCODER_R_INCORRECT_PROPERTY_QUERY:100:incorrect property query
+OSSL_ENCODER_R_MISSING_GET_PARAMS:102:missing get params
OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE:107:ambiguous content type
OSSL_STORE_R_BAD_PASSWORD_READ:115:bad password read
OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC:113:error verifying pkcs12 mac
@@ -2367,9 +839,11 @@ OSSL_STORE_R_LOADER_INCOMPLETE:116:loader incomplete
OSSL_STORE_R_LOADING_STARTED:117:loading started
OSSL_STORE_R_NOT_A_CERTIFICATE:100:not a certificate
OSSL_STORE_R_NOT_A_CRL:101:not a crl
-OSSL_STORE_R_NOT_A_KEY:102:not a key
OSSL_STORE_R_NOT_A_NAME:103:not a name
+OSSL_STORE_R_NOT_A_PRIVATE_KEY:102:not a private key
+OSSL_STORE_R_NOT_A_PUBLIC_KEY:122:not a public key
OSSL_STORE_R_NOT_PARAMETERS:104:not parameters
+OSSL_STORE_R_NO_LOADERS_FOUND:123:no loaders found
OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR:114:passphrase callback error
OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE:108:path must be absolute
OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES:119:\
@@ -2391,8 +865,10 @@ PEM_R_BAD_VERSION_NUMBER:117:bad version number
PEM_R_BIO_WRITE_FAILURE:118:bio write failure
PEM_R_CIPHER_IS_NULL:127:cipher is null
PEM_R_ERROR_CONVERTING_PRIVATE_KEY:115:error converting private key
+PEM_R_EXPECTING_DSS_KEY_BLOB:131:expecting dss key blob
PEM_R_EXPECTING_PRIVATE_KEY_BLOB:119:expecting private key blob
PEM_R_EXPECTING_PUBLIC_KEY_BLOB:120:expecting public key blob
+PEM_R_EXPECTING_RSA_KEY_BLOB:132:expecting rsa key blob
PEM_R_HEADER_TOO_LONG:128:header too long
PEM_R_INCONSISTENT_HEADER:121:inconsistent header
PEM_R_KEYBLOB_HEADER_PARSE_ERROR:122:keyblob header parse error
@@ -2420,6 +896,7 @@ PKCS12_R_ENCRYPT_ERROR:103:encrypt error
PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE:120:error setting encrypted data type
PKCS12_R_INVALID_NULL_ARGUMENT:104:invalid null argument
PKCS12_R_INVALID_NULL_PKCS12_POINTER:105:invalid null pkcs12 pointer
+PKCS12_R_INVALID_TYPE:112:invalid type
PKCS12_R_IV_GEN_ERROR:106:iv gen error
PKCS12_R_KEY_GEN_ERROR:107:key gen error
PKCS12_R_MAC_ABSENT:108:mac absent
@@ -2428,9 +905,7 @@ PKCS12_R_MAC_SETUP_ERROR:110:mac setup error
PKCS12_R_MAC_STRING_SET_ERROR:111:mac string set error
PKCS12_R_MAC_VERIFY_FAILURE:113:mac verify failure
PKCS12_R_PARSE_ERROR:114:parse error
-PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR:115:pkcs12 algor cipherinit error
PKCS12_R_PKCS12_CIPHERFINAL_ERROR:116:pkcs12 cipherfinal error
-PKCS12_R_PKCS12_PBE_CRYPT_ERROR:117:pkcs12 pbe crypt error
PKCS12_R_UNKNOWN_DIGEST_ALGORITHM:118:unknown digest algorithm
PKCS12_R_UNSUPPORTED_PKCS12_MODE:119:unsupported pkcs12 mode
PKCS7_R_CERTIFICATE_VERIFY_ERROR:117:certificate verify error
@@ -2475,6 +950,145 @@ PKCS7_R_UNSUPPORTED_CIPHER_TYPE:111:unsupported cipher type
PKCS7_R_UNSUPPORTED_CONTENT_TYPE:112:unsupported content type
PKCS7_R_WRONG_CONTENT_TYPE:113:wrong content type
PKCS7_R_WRONG_PKCS7_TYPE:114:wrong pkcs7 type
+PROP_R_NAME_TOO_LONG:100:name too long
+PROP_R_NOT_AN_ASCII_CHARACTER:101:not an ascii character
+PROP_R_NOT_AN_HEXADECIMAL_DIGIT:102:not an hexadecimal digit
+PROP_R_NOT_AN_IDENTIFIER:103:not an identifier
+PROP_R_NOT_AN_OCTAL_DIGIT:104:not an octal digit
+PROP_R_NOT_A_DECIMAL_DIGIT:105:not a decimal digit
+PROP_R_NO_MATCHING_STRING_DELIMITER:106:no matching string delimiter
+PROP_R_NO_VALUE:107:no value
+PROP_R_PARSE_FAILED:108:parse failed
+PROP_R_STRING_TOO_LONG:109:string too long
+PROP_R_TRAILING_CHARACTERS:110:trailing characters
+PROV_R_ADDITIONAL_INPUT_TOO_LONG:184:additional input too long
+PROV_R_ALGORITHM_MISMATCH:173:algorithm mismatch
+PROV_R_ALREADY_INSTANTIATED:185:already instantiated
+PROV_R_BAD_DECRYPT:100:bad decrypt
+PROV_R_BAD_ENCODING:141:bad encoding
+PROV_R_BAD_LENGTH:142:bad length
+PROV_R_BAD_TLS_CLIENT_VERSION:161:bad tls client version
+PROV_R_BN_ERROR:160:bn error
+PROV_R_CIPHER_OPERATION_FAILED:102:cipher operation failed
+PROV_R_DERIVATION_FUNCTION_INIT_FAILED:205:derivation function init failed
+PROV_R_DIGEST_NOT_ALLOWED:174:digest not allowed
+PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK:186:entropy source strength too weak
+PROV_R_ERROR_INSTANTIATING_DRBG:188:error instantiating drbg
+PROV_R_ERROR_RETRIEVING_ENTROPY:189:error retrieving entropy
+PROV_R_ERROR_RETRIEVING_NONCE:190:error retrieving nonce
+PROV_R_FAILED_DURING_DERIVATION:164:failed during derivation
+PROV_R_FAILED_TO_CREATE_LOCK:180:failed to create lock
+PROV_R_FAILED_TO_DECRYPT:162:failed to decrypt
+PROV_R_FAILED_TO_GENERATE_KEY:121:failed to generate key
+PROV_R_FAILED_TO_GET_PARAMETER:103:failed to get parameter
+PROV_R_FAILED_TO_SET_PARAMETER:104:failed to set parameter
+PROV_R_FAILED_TO_SIGN:175:failed to sign
+PROV_R_FIPS_MODULE_CONDITIONAL_ERROR:227:fips module conditional error
+PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE:224:fips module entering error state
+PROV_R_FIPS_MODULE_IN_ERROR_STATE:225:fips module in error state
+PROV_R_GENERATE_ERROR:191:generate error
+PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:165:\
+ illegal or unsupported padding mode
+PROV_R_INDICATOR_INTEGRITY_FAILURE:210:indicator integrity failure
+PROV_R_INSUFFICIENT_DRBG_STRENGTH:181:insufficient drbg strength
+PROV_R_INVALID_AAD:108:invalid aad
+PROV_R_INVALID_CONFIG_DATA:211:invalid config data
+PROV_R_INVALID_CONSTANT_LENGTH:157:invalid constant length
+PROV_R_INVALID_CURVE:176:invalid curve
+PROV_R_INVALID_CUSTOM_LENGTH:111:invalid custom length
+PROV_R_INVALID_DATA:115:invalid data
+PROV_R_INVALID_DIGEST:122:invalid digest
+PROV_R_INVALID_DIGEST_LENGTH:166:invalid digest length
+PROV_R_INVALID_DIGEST_SIZE:218:invalid digest size
+PROV_R_INVALID_INPUT_LENGTH:230:invalid input length
+PROV_R_INVALID_ITERATION_COUNT:123:invalid iteration count
+PROV_R_INVALID_IV_LENGTH:109:invalid iv length
+PROV_R_INVALID_KEY:158:invalid key
+PROV_R_INVALID_KEY_LENGTH:105:invalid key length
+PROV_R_INVALID_MAC:151:invalid mac
+PROV_R_INVALID_MGF1_MD:167:invalid mgf1 md
+PROV_R_INVALID_MODE:125:invalid mode
+PROV_R_INVALID_OUTPUT_LENGTH:217:invalid output length
+PROV_R_INVALID_PADDING_MODE:168:invalid padding mode
+PROV_R_INVALID_PUBINFO:198:invalid pubinfo
+PROV_R_INVALID_SALT_LENGTH:112:invalid salt length
+PROV_R_INVALID_SEED_LENGTH:154:invalid seed length
+PROV_R_INVALID_SIGNATURE_SIZE:179:invalid signature size
+PROV_R_INVALID_STATE:212:invalid state
+PROV_R_INVALID_TAG:110:invalid tag
+PROV_R_INVALID_TAG_LENGTH:118:invalid tag length
+PROV_R_INVALID_UKM_LENGTH:200:invalid ukm length
+PROV_R_INVALID_X931_DIGEST:170:invalid x931 digest
+PROV_R_IN_ERROR_STATE:192:in error state
+PROV_R_KEY_SETUP_FAILED:101:key setup failed
+PROV_R_KEY_SIZE_TOO_SMALL:171:key size too small
+PROV_R_LENGTH_TOO_LARGE:202:length too large
+PROV_R_MISMATCHING_DOMAIN_PARAMETERS:203:mismatching domain parameters
+PROV_R_MISSING_CEK_ALG:144:missing cek alg
+PROV_R_MISSING_CIPHER:155:missing cipher
+PROV_R_MISSING_CONFIG_DATA:213:missing config data
+PROV_R_MISSING_CONSTANT:156:missing constant
+PROV_R_MISSING_KEY:128:missing key
+PROV_R_MISSING_MAC:150:missing mac
+PROV_R_MISSING_MESSAGE_DIGEST:129:missing message digest
+PROV_R_MISSING_OID:209:missing OID
+PROV_R_MISSING_PASS:130:missing pass
+PROV_R_MISSING_SALT:131:missing salt
+PROV_R_MISSING_SECRET:132:missing secret
+PROV_R_MISSING_SEED:140:missing seed
+PROV_R_MISSING_SESSION_ID:133:missing session id
+PROV_R_MISSING_TYPE:134:missing type
+PROV_R_MISSING_XCGHASH:135:missing xcghash
+PROV_R_MODULE_INTEGRITY_FAILURE:214:module integrity failure
+PROV_R_NOT_A_PRIVATE_KEY:221:not a private key
+PROV_R_NOT_A_PUBLIC_KEY:220:not a public key
+PROV_R_NOT_INSTANTIATED:193:not instantiated
+PROV_R_NOT_PARAMETERS:226:not parameters
+PROV_R_NOT_SUPPORTED:136:not supported
+PROV_R_NOT_XOF_OR_INVALID_LENGTH:113:not xof or invalid length
+PROV_R_NO_KEY_SET:114:no key set
+PROV_R_NO_PARAMETERS_SET:177:no parameters set
+PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:178:\
+ operation not supported for this keytype
+PROV_R_OUTPUT_BUFFER_TOO_SMALL:106:output buffer too small
+PROV_R_PARENT_CANNOT_GENERATE_RANDOM_NUMBERS:228:\
+ parent cannot generate random numbers
+PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED:187:parent cannot supply entropy seed
+PROV_R_PARENT_LOCKING_NOT_ENABLED:182:parent locking not enabled
+PROV_R_PARENT_STRENGTH_TOO_WEAK:194:parent strength too weak
+PROV_R_PATH_MUST_BE_ABSOLUTE:219:path must be absolute
+PROV_R_PERSONALISATION_STRING_TOO_LONG:195:personalisation string too long
+PROV_R_PSS_SALTLEN_TOO_SMALL:172:pss saltlen too small
+PROV_R_REQUEST_TOO_LARGE_FOR_DRBG:196:request too large for drbg
+PROV_R_REQUIRE_CTR_MODE_CIPHER:206:require ctr mode cipher
+PROV_R_RESEED_ERROR:197:reseed error
+PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES:222:\
+ search only supported for directories
+PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT:229:\
+ seed sources must not have a parent
+PROV_R_SELF_TEST_KAT_FAILURE:215:self test kat failure
+PROV_R_SELF_TEST_POST_FAILURE:216:self test post failure
+PROV_R_TAG_NOT_NEEDED:120:tag not needed
+PROV_R_TAG_NOT_SET:119:tag not set
+PROV_R_TOO_MANY_RECORDS:126:too many records
+PROV_R_UNABLE_TO_FIND_CIPHERS:207:unable to find ciphers
+PROV_R_UNABLE_TO_GET_PARENT_STRENGTH:199:unable to get parent strength
+PROV_R_UNABLE_TO_GET_PASSPHRASE:159:unable to get passphrase
+PROV_R_UNABLE_TO_INITIALISE_CIPHERS:208:unable to initialise ciphers
+PROV_R_UNABLE_TO_LOAD_SHA256:147:unable to load sha256
+PROV_R_UNABLE_TO_LOCK_PARENT:201:unable to lock parent
+PROV_R_UNABLE_TO_RESEED:204:unable to reseed
+PROV_R_UNSUPPORTED_CEK_ALG:145:unsupported cek alg
+PROV_R_UNSUPPORTED_KEY_SIZE:153:unsupported key size
+PROV_R_UNSUPPORTED_MAC_TYPE:137:unsupported mac type
+PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS:152:unsupported number of rounds
+PROV_R_URI_AUTHORITY_UNSUPPORTED:223:uri authority unsupported
+PROV_R_VALUE_ERROR:138:value error
+PROV_R_WRONG_FINAL_BLOCK_LENGTH:107:wrong final block length
+PROV_R_WRONG_OUTPUT_BUFFER_SIZE:139:wrong output buffer size
+PROV_R_XOF_DIGESTS_NOT_ALLOWED:183:xof digests not allowed
+PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE:148:xts data unit is too large
+PROV_R_XTS_DUPLICATED_KEYS:149:xts duplicated keys
RAND_R_ADDITIONAL_INPUT_TOO_LONG:102:additional input too long
RAND_R_ALREADY_INSTANTIATED:103:already instantiated
RAND_R_ARGUMENT_OUT_OF_RANGE:105:argument out of range
@@ -2493,6 +1107,7 @@ RAND_R_FAILED_TO_CREATE_LOCK:126:failed to create lock
RAND_R_FUNC_NOT_IMPLEMENTED:101:Function not implemented
RAND_R_FWRITE_ERROR:123:Error writing file
RAND_R_GENERATE_ERROR:112:generate error
+RAND_R_INSUFFICIENT_DRBG_STRENGTH:139:insufficient drbg strength
RAND_R_INTERNAL_ERROR:113:internal error
RAND_R_IN_ERROR_STATE:114:in error state
RAND_R_NOT_A_REGULAR_FILE:122:Not a regular file
@@ -2511,6 +1126,12 @@ RAND_R_RESEED_ERROR:118:reseed error
RAND_R_SELFTEST_FAILURE:119:selftest failure
RAND_R_TOO_LITTLE_NONCE_REQUESTED:135:too little nonce requested
RAND_R_TOO_MUCH_NONCE_REQUESTED:136:too much nonce requested
+RAND_R_UNABLE_TO_CREATE_DRBG:143:unable to create drbg
+RAND_R_UNABLE_TO_FETCH_DRBG:144:unable to fetch drbg
+RAND_R_UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER:141:\
+ unable to get parent reseed prop counter
+RAND_R_UNABLE_TO_GET_PARENT_STRENGTH:138:unable to get parent strength
+RAND_R_UNABLE_TO_LOCK_PARENT:140:unable to lock parent
RAND_R_UNSUPPORTED_DRBG_FLAGS:132:unsupported drbg flags
RAND_R_UNSUPPORTED_DRBG_TYPE:120:unsupported drbg type
RSA_R_ALGORITHM_MISMATCH:100:algorithm mismatch
@@ -2538,16 +1159,22 @@ RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:144:\
RSA_R_INVALID_DIGEST:157:invalid digest
RSA_R_INVALID_DIGEST_LENGTH:143:invalid digest length
RSA_R_INVALID_HEADER:137:invalid header
+RSA_R_INVALID_KEYPAIR:171:invalid keypair
+RSA_R_INVALID_KEY_LENGTH:173:invalid key length
RSA_R_INVALID_LABEL:160:invalid label
+RSA_R_INVALID_LENGTH:181:invalid length
RSA_R_INVALID_MESSAGE_LENGTH:131:invalid message length
RSA_R_INVALID_MGF1_MD:156:invalid mgf1 md
+RSA_R_INVALID_MODULUS:174:invalid modulus
RSA_R_INVALID_MULTI_PRIME_KEY:167:invalid multi prime key
RSA_R_INVALID_OAEP_PARAMETERS:161:invalid oaep parameters
RSA_R_INVALID_PADDING:138:invalid padding
RSA_R_INVALID_PADDING_MODE:141:invalid padding mode
RSA_R_INVALID_PSS_PARAMETERS:149:invalid pss parameters
RSA_R_INVALID_PSS_SALTLEN:146:invalid pss saltlen
+RSA_R_INVALID_REQUEST:175:invalid request
RSA_R_INVALID_SALT_LENGTH:150:invalid salt length
+RSA_R_INVALID_STRENGTH:176:invalid strength
RSA_R_INVALID_TRAILER:139:invalid trailer
RSA_R_INVALID_X931_DIGEST:142:invalid x931 digest
RSA_R_IQMP_NOT_INVERSE_OF_Q:126:iqmp not inverse of q
@@ -2568,10 +1195,14 @@ RSA_R_OAEP_DECODING_ERROR:121:oaep decoding error
RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:148:\
operation not supported for this keytype
RSA_R_PADDING_CHECK_FAILED:114:padding check failed
+RSA_R_PAIRWISE_TEST_FAILURE:177:pairwise test failure
RSA_R_PKCS_DECODING_ERROR:159:pkcs decoding error
RSA_R_PSS_SALTLEN_TOO_SMALL:164:pss saltlen too small
+RSA_R_PUB_EXPONENT_OUT_OF_RANGE:178:pub exponent out of range
RSA_R_P_NOT_PRIME:128:p not prime
RSA_R_Q_NOT_PRIME:129:q not prime
+RSA_R_RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT:180:\
+ randomness source strength insufficient
RSA_R_RSA_OPERATIONS_NOT_SUPPORTED:130:rsa operations not supported
RSA_R_SLEN_CHECK_FAILED:136:salt length check failed
RSA_R_SLEN_RECOVERY_FAILED:135:salt length recovery failed
@@ -2600,6 +1231,7 @@ SM2_R_INVALID_DIGEST:102:invalid digest
SM2_R_INVALID_DIGEST_TYPE:103:invalid digest type
SM2_R_INVALID_ENCODING:104:invalid encoding
SM2_R_INVALID_FIELD:105:invalid field
+SM2_R_INVALID_PRIVATE_KEY:113:invalid private key
SM2_R_NO_PARAMETERS_SET:109:no parameters set
SM2_R_USER_ID_TOO_LARGE:106:user id too large
SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY:291:\
@@ -2607,8 +1239,6 @@ SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY:291:\
SSL_R_APP_DATA_IN_HANDSHAKE:100:app data in handshake
SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT:272:\
attempt to reuse session in different context
-SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE:143:\
- at least TLS 1.0 needed in FIPS mode
SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE:158:\
at least (D)TLS 1.2 needed in Suite B mode
SSL_R_BAD_CHANGE_CIPHER_SPEC:103:bad change cipher spec
@@ -2651,6 +1281,7 @@ SSL_R_BLOCK_CIPHER_PAD_IS_WRONG:129:block cipher pad is wrong
SSL_R_BN_LIB:130:bn lib
SSL_R_CALLBACK_FAILED:234:callback failed
SSL_R_CANNOT_CHANGE_CIPHER:109:cannot change cipher
+SSL_R_CANNOT_GET_GROUP_NAME:299:cannot get group name
SSL_R_CA_DN_LENGTH_MISMATCH:131:ca dn length mismatch
SSL_R_CA_KEY_TOO_SMALL:397:ca key too small
SSL_R_CA_MD_TOO_WEAK:398:ca md too weak
@@ -2660,7 +1291,6 @@ SSL_R_CERT_CB_ERROR:377:cert cb error
SSL_R_CERT_LENGTH_MISMATCH:135:cert length mismatch
SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED:218:ciphersuite digest has changed
SSL_R_CIPHER_CODE_WRONG_LENGTH:137:cipher code wrong length
-SSL_R_CIPHER_OR_HASH_UNAVAILABLE:138:cipher or hash unavailable
SSL_R_CLIENTHELLO_TLSEXT:226:clienthello tlsext
SSL_R_COMPRESSED_LENGTH_TOO_LONG:140:compressed length too long
SSL_R_COMPRESSION_DISABLED:343:compression disabled
@@ -2672,6 +1302,7 @@ SSL_R_CONNECTION_TYPE_NOT_SET:144:connection type not set
SSL_R_CONTEXT_NOT_DANE_ENABLED:167:context not dane enabled
SSL_R_COOKIE_GEN_CALLBACK_FAILURE:400:cookie gen callback failure
SSL_R_COOKIE_MISMATCH:308:cookie mismatch
+SSL_R_COPY_PARAMETERS_FAILED:296:copy parameters failed
SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED:206:\
custom ext handler already installed
SSL_R_DANE_ALREADY_ENABLED:172:dane already enabled
@@ -2738,6 +1369,8 @@ SSL_R_INVALID_SESSION_ID:999:invalid session id
SSL_R_INVALID_SRP_USERNAME:357:invalid srp username
SSL_R_INVALID_STATUS_RESPONSE:328:invalid status response
SSL_R_INVALID_TICKET_KEYS_LENGTH:325:invalid ticket keys length
+SSL_R_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED:333:\
+ legacy sigalg disallowed or unsupported
SSL_R_LENGTH_MISMATCH:159:length mismatch
SSL_R_LENGTH_TOO_LONG:404:length too long
SSL_R_LENGTH_TOO_SHORT:160:length too short
@@ -2785,13 +1418,15 @@ SSL_R_NO_SHARED_CIPHER:193:no shared cipher
SSL_R_NO_SHARED_GROUPS:410:no shared groups
SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS:376:no shared signature algorithms
SSL_R_NO_SRTP_PROFILES:359:no srtp profiles
+SSL_R_NO_SUITABLE_DIGEST_ALGORITHM:297:no suitable digest algorithm
+SSL_R_NO_SUITABLE_GROUPS:295:no suitable groups
SSL_R_NO_SUITABLE_KEY_SHARE:101:no suitable key share
SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM:118:no suitable signature algorithm
SSL_R_NO_VALID_SCTS:216:no valid scts
SSL_R_NO_VERIFY_COOKIE_CALLBACK:403:no verify cookie callback
SSL_R_NULL_SSL_CTX:195:null ssl ctx
SSL_R_NULL_SSL_METHOD_PASSED:196:null ssl method passed
-SSL_R_OCSP_CALLBACK_FAILURE:294:ocsp callback failure
+SSL_R_OCSP_CALLBACK_FAILURE:305:ocsp callback failure
SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED:197:old session cipher not returned
SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED:344:\
old session compression algorithm not returned
@@ -2854,8 +1489,6 @@ SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH:303:ssl session id has bad length
SSL_R_SSL_SESSION_ID_TOO_LONG:408:ssl session id too long
SSL_R_SSL_SESSION_VERSION_MISMATCH:210:ssl session version mismatch
SSL_R_STILL_IN_INIT:121:still in init
-SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT:365:peer does not accept heartbeats
-SSL_R_TLS_HEARTBEAT_PENDING:366:heartbeat request already pending
SSL_R_TLS_ILLEGAL_EXPORTER_LABEL:367:tls illegal exporter label
SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST:157:tls invalid ecpointformat list
SSL_R_TOO_MANY_KEY_UPDATES:132:too many key updates
@@ -2868,6 +1501,7 @@ SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES:242:unable to load ssl3 md5 routines
SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES:243:unable to load ssl3 sha1 routines
SSL_R_UNEXPECTED_CCS_MESSAGE:262:unexpected ccs message
SSL_R_UNEXPECTED_END_OF_EARLY_DATA:178:unexpected end of early data
+SSL_R_UNEXPECTED_EOF_WHILE_READING:294:unexpected eof while reading
SSL_R_UNEXPECTED_MESSAGE:244:unexpected message
SSL_R_UNEXPECTED_RECORD:245:unexpected record
SSL_R_UNINITIALIZED:276:uninitialized
@@ -2964,6 +1598,7 @@ X509V3_R_BN_TO_ASN1_INTEGER_ERROR:101:bn to asn1 integer error
X509V3_R_DIRNAME_ERROR:149:dirname error
X509V3_R_DISTPOINT_ALREADY_SET:160:distpoint already set
X509V3_R_DUPLICATE_ZONE_ID:133:duplicate zone id
+X509V3_R_EMPTY_KEY_USAGE:169:empty key usage
X509V3_R_ERROR_CONVERTING_ZONE:131:error converting zone
X509V3_R_ERROR_CREATING_EXTENSION:144:error creating extension
X509V3_R_ERROR_IN_EXTENSION:128:error in extension
@@ -2978,13 +1613,14 @@ X509V3_R_INCORRECT_POLICY_SYNTAX_TAG:152:incorrect policy syntax tag
X509V3_R_INVALID_ASNUMBER:162:invalid asnumber
X509V3_R_INVALID_ASRANGE:163:invalid asrange
X509V3_R_INVALID_BOOLEAN_STRING:104:invalid boolean string
+X509V3_R_INVALID_CERTIFICATE:158:invalid certificate
+X509V3_R_INVALID_EMPTY_NAME:108:invalid empty name
X509V3_R_INVALID_EXTENSION_STRING:105:invalid extension string
X509V3_R_INVALID_INHERITANCE:165:invalid inheritance
X509V3_R_INVALID_IPADDRESS:166:invalid ipaddress
X509V3_R_INVALID_MULTIPLE_RDNS:161:invalid multiple rdns
X509V3_R_INVALID_NAME:106:invalid name
X509V3_R_INVALID_NULL_ARGUMENT:107:invalid null argument
-X509V3_R_INVALID_NULL_NAME:108:invalid null name
X509V3_R_INVALID_NULL_VALUE:109:invalid null value
X509V3_R_INVALID_NUMBER:140:invalid number
X509V3_R_INVALID_NUMBERS:141:invalid numbers
@@ -2999,6 +1635,7 @@ X509V3_R_INVALID_SYNTAX:143:invalid syntax
X509V3_R_ISSUER_DECODE_ERROR:126:issuer decode error
X509V3_R_MISSING_VALUE:124:missing value
X509V3_R_NEED_ORGANIZATION_AND_NUMBERS:142:need organization and numbers
+X509V3_R_NEGATIVE_PATHLEN:168:negative pathlen
X509V3_R_NO_CONFIG_DATABASE:136:no config database
X509V3_R_NO_ISSUER_CERTIFICATE:121:no issuer certificate
X509V3_R_NO_ISSUER_DETAILS:127:no issuer details
@@ -3030,12 +1667,16 @@ X509_R_BAD_SELECTOR:133:bad selector
X509_R_BAD_X509_FILETYPE:100:bad x509 filetype
X509_R_BASE64_DECODE_ERROR:118:base64 decode error
X509_R_CANT_CHECK_DH_KEY:114:cant check dh key
+X509_R_CERTIFICATE_VERIFICATION_FAILED:139:certificate verification failed
X509_R_CERT_ALREADY_IN_HASH_TABLE:101:cert already in hash table
X509_R_CRL_ALREADY_DELTA:127:crl already delta
X509_R_CRL_VERIFY_FAILURE:131:crl verify failure
+X509_R_ERROR_GETTING_MD_BY_NID:141:error getting md by nid
+X509_R_ERROR_USING_SIGINF_SET:142:error using siginf set
X509_R_IDP_MISMATCH:128:idp mismatch
X509_R_INVALID_ATTRIBUTES:138:invalid attributes
X509_R_INVALID_DIRECTORY:113:invalid directory
+X509_R_INVALID_DISTPOINT:143:invalid distpoint
X509_R_INVALID_FIELD_NAME:119:invalid field name
X509_R_INVALID_TRUST:123:invalid trust
X509_R_ISSUER_MISMATCH:129:issuer mismatch
@@ -3059,6 +1700,7 @@ X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY:108:unable to get certs public key
X509_R_UNKNOWN_KEY_TYPE:117:unknown key type
X509_R_UNKNOWN_NID:109:unknown nid
X509_R_UNKNOWN_PURPOSE_ID:121:unknown purpose id
+X509_R_UNKNOWN_SIGID_ALGS:144:unknown sigid algs
X509_R_UNKNOWN_TRUST_ID:120:unknown trust id
X509_R_UNSUPPORTED_ALGORITHM:111:unsupported algorithm
X509_R_WRONG_LOOKUP_TYPE:112:wrong lookup type
diff --git a/crypto/ess/build.info b/crypto/ess/build.info
new file mode 100644
index 000000000000..f25c1271fb2f
--- /dev/null
+++ b/crypto/ess/build.info
@@ -0,0 +1,3 @@
+LIBS=../../libcrypto
+
+SOURCE[../../libcrypto]= ess_asn1.c ess_err.c ess_lib.c
diff --git a/crypto/ess/ess_asn1.c b/crypto/ess/ess_asn1.c
new file mode 100644
index 000000000000..68bc854c99bb
--- /dev/null
+++ b/crypto/ess/ess_asn1.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/asn1t.h>
+#include <openssl/cms.h>
+#include <openssl/ess.h>
+#include <openssl/x509v3.h>
+#include "crypto/ess.h"
+
+/* ASN1 stuff for ESS Structure */
+
+ASN1_SEQUENCE(ESS_ISSUER_SERIAL) = {
+ ASN1_SEQUENCE_OF(ESS_ISSUER_SERIAL, issuer, GENERAL_NAME),
+ ASN1_SIMPLE(ESS_ISSUER_SERIAL, serial, ASN1_INTEGER)
+} static_ASN1_SEQUENCE_END(ESS_ISSUER_SERIAL)
+
+IMPLEMENT_ASN1_FUNCTIONS(ESS_ISSUER_SERIAL)
+IMPLEMENT_ASN1_DUP_FUNCTION(ESS_ISSUER_SERIAL)
+
+ASN1_SEQUENCE(ESS_CERT_ID) = {
+ ASN1_SIMPLE(ESS_CERT_ID, hash, ASN1_OCTET_STRING),
+ ASN1_OPT(ESS_CERT_ID, issuer_serial, ESS_ISSUER_SERIAL)
+} static_ASN1_SEQUENCE_END(ESS_CERT_ID)
+
+IMPLEMENT_ASN1_FUNCTIONS(ESS_CERT_ID)
+IMPLEMENT_ASN1_DUP_FUNCTION(ESS_CERT_ID)
+
+ASN1_SEQUENCE(ESS_SIGNING_CERT) = {
+ ASN1_SEQUENCE_OF(ESS_SIGNING_CERT, cert_ids, ESS_CERT_ID),
+ ASN1_SEQUENCE_OF_OPT(ESS_SIGNING_CERT, policy_info, POLICYINFO)
+} ASN1_SEQUENCE_END(ESS_SIGNING_CERT)
+
+IMPLEMENT_ASN1_FUNCTIONS(ESS_SIGNING_CERT)
+IMPLEMENT_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT)
+
+ASN1_SEQUENCE(ESS_CERT_ID_V2) = {
+ ASN1_OPT(ESS_CERT_ID_V2, hash_alg, X509_ALGOR),
+ ASN1_SIMPLE(ESS_CERT_ID_V2, hash, ASN1_OCTET_STRING),
+ ASN1_OPT(ESS_CERT_ID_V2, issuer_serial, ESS_ISSUER_SERIAL)
+} static_ASN1_SEQUENCE_END(ESS_CERT_ID_V2)
+
+IMPLEMENT_ASN1_FUNCTIONS(ESS_CERT_ID_V2)
+IMPLEMENT_ASN1_DUP_FUNCTION(ESS_CERT_ID_V2)
+
+ASN1_SEQUENCE(ESS_SIGNING_CERT_V2) = {
+ ASN1_SEQUENCE_OF(ESS_SIGNING_CERT_V2, cert_ids, ESS_CERT_ID_V2),
+ ASN1_SEQUENCE_OF_OPT(ESS_SIGNING_CERT_V2, policy_info, POLICYINFO)
+} ASN1_SEQUENCE_END(ESS_SIGNING_CERT_V2)
+
+IMPLEMENT_ASN1_FUNCTIONS(ESS_SIGNING_CERT_V2)
+IMPLEMENT_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT_V2)
diff --git a/crypto/ess/ess_err.c b/crypto/ess/ess_err.c
new file mode 100644
index 000000000000..eb76dfe7cc8f
--- /dev/null
+++ b/crypto/ess/ess_err.c
@@ -0,0 +1,48 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/esserr.h>
+#include "crypto/esserr.h"
+
+#ifndef OPENSSL_NO_ERR
+
+static const ERR_STRING_DATA ESS_str_reasons[] = {
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_EMPTY_ESS_CERT_ID_LIST),
+ "empty ess cert id list"},
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_CERT_DIGEST_ERROR),
+ "ess cert digest error"},
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_CERT_ID_NOT_FOUND),
+ "ess cert id not found"},
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_CERT_ID_WRONG_ORDER),
+ "ess cert id wrong order"},
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_DIGEST_ALG_UNKNOWN),
+ "ess digest alg unknown"},
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_SIGNING_CERTIFICATE_ERROR),
+ "ess signing certificate error"},
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_SIGNING_CERT_ADD_ERROR),
+ "ess signing cert add error"},
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_SIGNING_CERT_V2_ADD_ERROR),
+ "ess signing cert v2 add error"},
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE),
+ "missing signing certificate attribute"},
+ {0, NULL}
+};
+
+#endif
+
+int ossl_err_load_ESS_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(ESS_str_reasons[0].error) == NULL)
+ ERR_load_strings_const(ESS_str_reasons);
+#endif
+ return 1;
+}
diff --git a/crypto/ess/ess_lib.c b/crypto/ess/ess_lib.c
new file mode 100644
index 000000000000..65444d383ff4
--- /dev/null
+++ b/crypto/ess/ess_lib.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+#include <openssl/ess.h>
+#include "internal/sizes.h"
+#include "crypto/ess.h"
+#include "crypto/x509.h"
+
+static ESS_CERT_ID *ESS_CERT_ID_new_init(const X509 *cert,
+ int set_issuer_serial);
+static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg,
+ const X509 *cert,
+ int set_issuer_serial);
+
+ESS_SIGNING_CERT *OSSL_ESS_signing_cert_new_init(const X509 *signcert,
+ const STACK_OF(X509) *certs,
+ int set_issuer_serial)
+{
+ ESS_CERT_ID *cid = NULL;
+ ESS_SIGNING_CERT *sc;
+ int i;
+
+ if ((sc = ESS_SIGNING_CERT_new()) == NULL)
+ goto err;
+ if (sc->cert_ids == NULL
+ && (sc->cert_ids = sk_ESS_CERT_ID_new_null()) == NULL)
+ goto err;
+
+ if ((cid = ESS_CERT_ID_new_init(signcert, set_issuer_serial)) == NULL
+ || !sk_ESS_CERT_ID_push(sc->cert_ids, cid))
+ goto err;
+ for (i = 0; i < sk_X509_num(certs); ++i) {
+ X509 *cert = sk_X509_value(certs, i);
+
+ if ((cid = ESS_CERT_ID_new_init(cert, 1)) == NULL
+ || !sk_ESS_CERT_ID_push(sc->cert_ids, cid))
+ goto err;
+ }
+
+ return sc;
+ err:
+ ESS_SIGNING_CERT_free(sc);
+ ESS_CERT_ID_free(cid);
+ ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
+ return NULL;
+}
+
+static ESS_CERT_ID *ESS_CERT_ID_new_init(const X509 *cert,
+ int set_issuer_serial)
+{
+ ESS_CERT_ID *cid = NULL;
+ GENERAL_NAME *name = NULL;
+ unsigned char cert_sha1[SHA_DIGEST_LENGTH];
+
+ if ((cid = ESS_CERT_ID_new()) == NULL)
+ goto err;
+ if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL))
+ goto err;
+ if (!ASN1_OCTET_STRING_set(cid->hash, cert_sha1, SHA_DIGEST_LENGTH))
+ goto err;
+
+ /* Setting the issuer/serial if requested. */
+ if (!set_issuer_serial)
+ return cid;
+
+ if (cid->issuer_serial == NULL
+ && (cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL)
+ goto err;
+ if ((name = GENERAL_NAME_new()) == NULL)
+ goto err;
+ name->type = GEN_DIRNAME;
+ if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL)
+ goto err;
+ if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name))
+ goto err;
+ name = NULL; /* Ownership is lost. */
+ ASN1_INTEGER_free(cid->issuer_serial->serial);
+ if ((cid->issuer_serial->serial =
+ ASN1_INTEGER_dup(X509_get0_serialNumber(cert))) == NULL)
+ goto err;
+
+ return cid;
+ err:
+ GENERAL_NAME_free(name);
+ ESS_CERT_ID_free(cid);
+ ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
+ return NULL;
+}
+
+ESS_SIGNING_CERT_V2 *OSSL_ESS_signing_cert_v2_new_init(const EVP_MD *hash_alg,
+ const X509 *signcert,
+ const
+ STACK_OF(X509) *certs,
+ int set_issuer_serial)
+{
+ ESS_CERT_ID_V2 *cid = NULL;
+ ESS_SIGNING_CERT_V2 *sc;
+ int i;
+
+ if ((sc = ESS_SIGNING_CERT_V2_new()) == NULL)
+ goto err;
+ cid = ESS_CERT_ID_V2_new_init(hash_alg, signcert, set_issuer_serial);
+ if (cid == NULL)
+ goto err;
+ if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid))
+ goto err;
+ cid = NULL;
+
+ for (i = 0; i < sk_X509_num(certs); ++i) {
+ X509 *cert = sk_X509_value(certs, i);
+
+ if ((cid = ESS_CERT_ID_V2_new_init(hash_alg, cert, 1)) == NULL)
+ goto err;
+ if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid))
+ goto err;
+ cid = NULL;
+ }
+
+ return sc;
+ err:
+ ESS_SIGNING_CERT_V2_free(sc);
+ ESS_CERT_ID_V2_free(cid);
+ ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
+ return NULL;
+}
+
+static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg,
+ const X509 *cert,
+ int set_issuer_serial)
+{
+ ESS_CERT_ID_V2 *cid;
+ GENERAL_NAME *name = NULL;
+ unsigned char hash[EVP_MAX_MD_SIZE];
+ unsigned int hash_len = sizeof(hash);
+ X509_ALGOR *alg = NULL;
+
+ memset(hash, 0, sizeof(hash));
+
+ if ((cid = ESS_CERT_ID_V2_new()) == NULL)
+ goto err;
+
+ if (!EVP_MD_is_a(hash_alg, SN_sha256)) {
+ alg = X509_ALGOR_new();
+ if (alg == NULL)
+ goto err;
+ X509_ALGOR_set_md(alg, hash_alg);
+ if (alg->algorithm == NULL)
+ goto err;
+ cid->hash_alg = alg;
+ alg = NULL;
+ } else {
+ cid->hash_alg = NULL;
+ }
+
+ if (!X509_digest(cert, hash_alg, hash, &hash_len))
+ goto err;
+
+ if (!ASN1_OCTET_STRING_set(cid->hash, hash, hash_len))
+ goto err;
+
+ if (!set_issuer_serial)
+ return cid;
+
+ if ((cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL)
+ goto err;
+ if ((name = GENERAL_NAME_new()) == NULL)
+ goto err;
+ name->type = GEN_DIRNAME;
+ if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL)
+ goto err;
+ if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name))
+ goto err;
+ name = NULL; /* Ownership is lost. */
+ ASN1_INTEGER_free(cid->issuer_serial->serial);
+ cid->issuer_serial->serial = ASN1_INTEGER_dup(X509_get0_serialNumber(cert));
+ if (cid->issuer_serial->serial == NULL)
+ goto err;
+
+ return cid;
+ err:
+ X509_ALGOR_free(alg);
+ GENERAL_NAME_free(name);
+ ESS_CERT_ID_V2_free(cid);
+ ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
+ return NULL;
+}
+
+static int ess_issuer_serial_cmp(const ESS_ISSUER_SERIAL *is, const X509 *cert)
+{
+ GENERAL_NAME *issuer;
+
+ if (is == NULL || cert == NULL || sk_GENERAL_NAME_num(is->issuer) != 1)
+ return -1;
+
+ issuer = sk_GENERAL_NAME_value(is->issuer, 0);
+ if (issuer->type != GEN_DIRNAME
+ || X509_NAME_cmp(issuer->d.dirn, X509_get_issuer_name(cert)) != 0)
+ return -1;
+
+ return ASN1_INTEGER_cmp(is->serial, X509_get0_serialNumber(cert));
+}
+
+/*
+ * Find the cert in |certs| referenced by |cid| if not NULL, else by |cid_v2|.
+ * The cert must be the first one in |certs| if and only if |index| is 0.
+ * Return 0 on not found, -1 on error, else 1 + the position in |certs|.
+ */
+static int find(const ESS_CERT_ID *cid, const ESS_CERT_ID_V2 *cid_v2,
+ int index, const STACK_OF(X509) *certs)
+{
+ const X509 *cert;
+ EVP_MD *md = NULL;
+ char name[OSSL_MAX_NAME_SIZE];
+ unsigned char cert_digest[EVP_MAX_MD_SIZE];
+ unsigned int len, cid_hash_len;
+ const ESS_ISSUER_SERIAL *is;
+ int i;
+ int ret = -1;
+
+ if (cid == NULL && cid_v2 == NULL) {
+ ERR_raise(ERR_LIB_ESS, ERR_R_PASSED_INVALID_ARGUMENT);
+ return -1;
+ }
+
+ if (cid != NULL)
+ strcpy(name, "SHA1");
+ else if (cid_v2->hash_alg == NULL)
+ strcpy(name, "SHA256");
+ else
+ OBJ_obj2txt(name, sizeof(name), cid_v2->hash_alg->algorithm, 0);
+
+ (void)ERR_set_mark();
+ md = EVP_MD_fetch(NULL, name, NULL);
+
+ if (md == NULL)
+ md = (EVP_MD *)EVP_get_digestbyname(name);
+
+ if (md == NULL) {
+ (void)ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_ESS, ESS_R_ESS_DIGEST_ALG_UNKNOWN);
+ goto end;
+ }
+ (void)ERR_pop_to_mark();
+
+ for (i = 0; i < sk_X509_num(certs); ++i) {
+ cert = sk_X509_value(certs, i);
+
+ cid_hash_len = cid != NULL ? cid->hash->length : cid_v2->hash->length;
+ if (!X509_digest(cert, md, cert_digest, &len)
+ || cid_hash_len != len) {
+ ERR_raise(ERR_LIB_ESS, ESS_R_ESS_CERT_DIGEST_ERROR);
+ goto end;
+ }
+
+ if (memcmp(cid != NULL ? cid->hash->data : cid_v2->hash->data,
+ cert_digest, len) == 0) {
+ is = cid != NULL ? cid->issuer_serial : cid_v2->issuer_serial;
+ /* Well, it's not really required to match the serial numbers. */
+ if (is == NULL || ess_issuer_serial_cmp(is, cert) == 0) {
+ if ((i == 0) == (index == 0)) {
+ ret = i + 1;
+ goto end;
+ }
+ ERR_raise(ERR_LIB_ESS, ESS_R_ESS_CERT_ID_WRONG_ORDER);
+ goto end;
+ }
+ }
+ }
+
+ ret = 0;
+ ERR_raise(ERR_LIB_ESS, ESS_R_ESS_CERT_ID_NOT_FOUND);
+end:
+ EVP_MD_free(md);
+ return ret;
+}
+
+int OSSL_ESS_check_signing_certs(const ESS_SIGNING_CERT *ss,
+ const ESS_SIGNING_CERT_V2 *ssv2,
+ const STACK_OF(X509) *chain,
+ int require_signing_cert)
+{
+ int n_v1 = ss == NULL ? -1 : sk_ESS_CERT_ID_num(ss->cert_ids);
+ int n_v2 = ssv2 == NULL ? -1 : sk_ESS_CERT_ID_V2_num(ssv2->cert_ids);
+ int i, ret;
+
+ if (require_signing_cert && ss == NULL && ssv2 == NULL) {
+ ERR_raise(ERR_LIB_CMS, ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE);
+ return -1;
+ }
+ if (n_v1 == 0 || n_v2 == 0) {
+ ERR_raise(ERR_LIB_ESS, ESS_R_EMPTY_ESS_CERT_ID_LIST);
+ return -1;
+ }
+ /* If both ss and ssv2 exist, as required evaluate them independently. */
+ for (i = 0; i < n_v1; i++) {
+ ret = find(sk_ESS_CERT_ID_value(ss->cert_ids, i), NULL, i, chain);
+ if (ret <= 0)
+ return ret;
+ }
+ for (i = 0; i < n_v2; i++) {
+ ret = find(NULL, sk_ESS_CERT_ID_V2_value(ssv2->cert_ids, i), i, chain);
+ if (ret <= 0)
+ return ret;
+ }
+ return 1;
+}
diff --git a/crypto/evp/asymcipher.c b/crypto/evp/asymcipher.c
new file mode 100644
index 000000000000..b7784c899457
--- /dev/null
+++ b/crypto/evp/asymcipher.c
@@ -0,0 +1,552 @@
+/*
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include "internal/cryptlib.h"
+#include "internal/provider.h"
+#include "internal/core.h"
+#include "crypto/evp.h"
+#include "evp_local.h"
+
+static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation,
+ const OSSL_PARAM params[])
+{
+ int ret = 0;
+ void *provkey = NULL;
+ EVP_ASYM_CIPHER *cipher = NULL;
+ EVP_KEYMGMT *tmp_keymgmt = NULL;
+ const OSSL_PROVIDER *tmp_prov = NULL;
+ const char *supported_ciph = NULL;
+ int iter;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ evp_pkey_ctx_free_old_ops(ctx);
+ ctx->operation = operation;
+
+ ERR_set_mark();
+
+ if (evp_pkey_ctx_is_legacy(ctx))
+ goto legacy;
+
+ if (ctx->pkey == NULL) {
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET);
+ goto err;
+ }
+
+ /*
+ * Try to derive the supported asym cipher from |ctx->keymgmt|.
+ */
+ if (!ossl_assert(ctx->pkey->keymgmt == NULL
+ || ctx->pkey->keymgmt == ctx->keymgmt)) {
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ supported_ciph
+ = evp_keymgmt_util_query_operation_name(ctx->keymgmt,
+ OSSL_OP_ASYM_CIPHER);
+ if (supported_ciph == NULL) {
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+
+ /*
+ * We perform two iterations:
+ *
+ * 1. Do the normal asym cipher fetch, using the fetching data given by
+ * the EVP_PKEY_CTX.
+ * 2. Do the provider specific asym cipher fetch, from the same provider
+ * as |ctx->keymgmt|
+ *
+ * We then try to fetch the keymgmt from the same provider as the
+ * asym cipher, and try to export |ctx->pkey| to that keymgmt (when
+ * this keymgmt happens to be the same as |ctx->keymgmt|, the export
+ * is a no-op, but we call it anyway to not complicate the code even
+ * more).
+ * If the export call succeeds (returns a non-NULL provider key pointer),
+ * we're done and can perform the operation itself. If not, we perform
+ * the second iteration, or jump to legacy.
+ */
+ for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) {
+ EVP_KEYMGMT *tmp_keymgmt_tofree;
+
+ /*
+ * If we're on the second iteration, free the results from the first.
+ * They are NULL on the first iteration, so no need to check what
+ * iteration we're on.
+ */
+ EVP_ASYM_CIPHER_free(cipher);
+ EVP_KEYMGMT_free(tmp_keymgmt);
+
+ switch (iter) {
+ case 1:
+ cipher = EVP_ASYM_CIPHER_fetch(ctx->libctx, supported_ciph,
+ ctx->propquery);
+ if (cipher != NULL)
+ tmp_prov = EVP_ASYM_CIPHER_get0_provider(cipher);
+ break;
+ case 2:
+ tmp_prov = EVP_KEYMGMT_get0_provider(ctx->keymgmt);
+ cipher =
+ evp_asym_cipher_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
+ supported_ciph, ctx->propquery);
+ if (cipher == NULL)
+ goto legacy;
+ break;
+ }
+ if (cipher == NULL)
+ continue;
+
+ /*
+ * Ensure that the key is provided, either natively, or as a cached
+ * export. We start by fetching the keymgmt with the same name as
+ * |ctx->pkey|, but from the provider of the asym cipher method, using
+ * the same property query as when fetching the asym cipher method.
+ * With the keymgmt we found (if we did), we try to export |ctx->pkey|
+ * to it (evp_pkey_export_to_provider() is smart enough to only actually
+ * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt)
+ */
+ tmp_keymgmt_tofree = tmp_keymgmt
+ = evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
+ EVP_KEYMGMT_get0_name(ctx->keymgmt),
+ ctx->propquery);
+ if (tmp_keymgmt != NULL)
+ provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
+ &tmp_keymgmt, ctx->propquery);
+ if (tmp_keymgmt == NULL)
+ EVP_KEYMGMT_free(tmp_keymgmt_tofree);
+ }
+
+ if (provkey == NULL) {
+ EVP_ASYM_CIPHER_free(cipher);
+ goto legacy;
+ }
+
+ ERR_pop_to_mark();
+
+ /* No more legacy from here down to legacy: */
+
+ ctx->op.ciph.cipher = cipher;
+ ctx->op.ciph.algctx = cipher->newctx(ossl_provider_ctx(cipher->prov));
+ if (ctx->op.ciph.algctx == NULL) {
+ /* The provider key can stay in the cache */
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+
+ switch (operation) {
+ case EVP_PKEY_OP_ENCRYPT:
+ if (cipher->encrypt_init == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ ret = -2;
+ goto err;
+ }
+ ret = cipher->encrypt_init(ctx->op.ciph.algctx, provkey, params);
+ break;
+ case EVP_PKEY_OP_DECRYPT:
+ if (cipher->decrypt_init == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ ret = -2;
+ goto err;
+ }
+ ret = cipher->decrypt_init(ctx->op.ciph.algctx, provkey, params);
+ break;
+ default:
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+
+ if (ret <= 0)
+ goto err;
+ EVP_KEYMGMT_free(tmp_keymgmt);
+ return 1;
+
+ legacy:
+ /*
+ * If we don't have the full support we need with provided methods,
+ * let's go see if legacy does.
+ */
+ ERR_pop_to_mark();
+ EVP_KEYMGMT_free(tmp_keymgmt);
+ tmp_keymgmt = NULL;
+
+ if (ctx->pmeth == NULL || ctx->pmeth->encrypt == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+ switch(ctx->operation) {
+ case EVP_PKEY_OP_ENCRYPT:
+ if (ctx->pmeth->encrypt_init == NULL)
+ return 1;
+ ret = ctx->pmeth->encrypt_init(ctx);
+ break;
+ case EVP_PKEY_OP_DECRYPT:
+ if (ctx->pmeth->decrypt_init == NULL)
+ return 1;
+ ret = ctx->pmeth->decrypt_init(ctx);
+ break;
+ default:
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ ret = -1;
+ }
+
+ err:
+ if (ret <= 0) {
+ evp_pkey_ctx_free_old_ops(ctx);
+ ctx->operation = EVP_PKEY_OP_UNDEFINED;
+ }
+ EVP_KEYMGMT_free(tmp_keymgmt);
+ return ret;
+}
+
+int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx)
+{
+ return evp_pkey_asym_cipher_init(ctx, EVP_PKEY_OP_ENCRYPT, NULL);
+}
+
+int EVP_PKEY_encrypt_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
+{
+ return evp_pkey_asym_cipher_init(ctx, EVP_PKEY_OP_ENCRYPT, params);
+}
+
+int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
+ unsigned char *out, size_t *outlen,
+ const unsigned char *in, size_t inlen)
+{
+ int ret;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ if (ctx->operation != EVP_PKEY_OP_ENCRYPT) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
+ return -1;
+ }
+
+ if (ctx->op.ciph.algctx == NULL)
+ goto legacy;
+
+ ret = ctx->op.ciph.cipher->encrypt(ctx->op.ciph.algctx, out, outlen,
+ (out == NULL ? 0 : *outlen), in, inlen);
+ return ret;
+
+ legacy:
+ if (ctx->pmeth == NULL || ctx->pmeth->encrypt == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+ M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_ENCRYPT)
+ return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen);
+}
+
+int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx)
+{
+ return evp_pkey_asym_cipher_init(ctx, EVP_PKEY_OP_DECRYPT, NULL);
+}
+
+int EVP_PKEY_decrypt_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
+{
+ return evp_pkey_asym_cipher_init(ctx, EVP_PKEY_OP_DECRYPT, params);
+}
+
+int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
+ unsigned char *out, size_t *outlen,
+ const unsigned char *in, size_t inlen)
+{
+ int ret;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ if (ctx->operation != EVP_PKEY_OP_DECRYPT) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
+ return -1;
+ }
+
+ if (ctx->op.ciph.algctx == NULL)
+ goto legacy;
+
+ ret = ctx->op.ciph.cipher->decrypt(ctx->op.ciph.algctx, out, outlen,
+ (out == NULL ? 0 : *outlen), in, inlen);
+ return ret;
+
+ legacy:
+ if (ctx->pmeth == NULL || ctx->pmeth->decrypt == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+ M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_DECRYPT)
+ return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen);
+}
+
+
+static EVP_ASYM_CIPHER *evp_asym_cipher_new(OSSL_PROVIDER *prov)
+{
+ EVP_ASYM_CIPHER *cipher = OPENSSL_zalloc(sizeof(EVP_ASYM_CIPHER));
+
+ if (cipher == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ cipher->lock = CRYPTO_THREAD_lock_new();
+ if (cipher->lock == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(cipher);
+ return NULL;
+ }
+ cipher->prov = prov;
+ ossl_provider_up_ref(prov);
+ cipher->refcnt = 1;
+
+ return cipher;
+}
+
+static void *evp_asym_cipher_from_algorithm(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
+{
+ const OSSL_DISPATCH *fns = algodef->implementation;
+ EVP_ASYM_CIPHER *cipher = NULL;
+ int ctxfncnt = 0, encfncnt = 0, decfncnt = 0;
+ int gparamfncnt = 0, sparamfncnt = 0;
+
+ if ((cipher = evp_asym_cipher_new(prov)) == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ cipher->name_id = name_id;
+ if ((cipher->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL)
+ goto err;
+ cipher->description = algodef->algorithm_description;
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_ASYM_CIPHER_NEWCTX:
+ if (cipher->newctx != NULL)
+ break;
+ cipher->newctx = OSSL_FUNC_asym_cipher_newctx(fns);
+ ctxfncnt++;
+ break;
+ case OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT:
+ if (cipher->encrypt_init != NULL)
+ break;
+ cipher->encrypt_init = OSSL_FUNC_asym_cipher_encrypt_init(fns);
+ encfncnt++;
+ break;
+ case OSSL_FUNC_ASYM_CIPHER_ENCRYPT:
+ if (cipher->encrypt != NULL)
+ break;
+ cipher->encrypt = OSSL_FUNC_asym_cipher_encrypt(fns);
+ encfncnt++;
+ break;
+ case OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT:
+ if (cipher->decrypt_init != NULL)
+ break;
+ cipher->decrypt_init = OSSL_FUNC_asym_cipher_decrypt_init(fns);
+ decfncnt++;
+ break;
+ case OSSL_FUNC_ASYM_CIPHER_DECRYPT:
+ if (cipher->decrypt != NULL)
+ break;
+ cipher->decrypt = OSSL_FUNC_asym_cipher_decrypt(fns);
+ decfncnt++;
+ break;
+ case OSSL_FUNC_ASYM_CIPHER_FREECTX:
+ if (cipher->freectx != NULL)
+ break;
+ cipher->freectx = OSSL_FUNC_asym_cipher_freectx(fns);
+ ctxfncnt++;
+ break;
+ case OSSL_FUNC_ASYM_CIPHER_DUPCTX:
+ if (cipher->dupctx != NULL)
+ break;
+ cipher->dupctx = OSSL_FUNC_asym_cipher_dupctx(fns);
+ break;
+ case OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS:
+ if (cipher->get_ctx_params != NULL)
+ break;
+ cipher->get_ctx_params
+ = OSSL_FUNC_asym_cipher_get_ctx_params(fns);
+ gparamfncnt++;
+ break;
+ case OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS:
+ if (cipher->gettable_ctx_params != NULL)
+ break;
+ cipher->gettable_ctx_params
+ = OSSL_FUNC_asym_cipher_gettable_ctx_params(fns);
+ gparamfncnt++;
+ break;
+ case OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS:
+ if (cipher->set_ctx_params != NULL)
+ break;
+ cipher->set_ctx_params
+ = OSSL_FUNC_asym_cipher_set_ctx_params(fns);
+ sparamfncnt++;
+ break;
+ case OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS:
+ if (cipher->settable_ctx_params != NULL)
+ break;
+ cipher->settable_ctx_params
+ = OSSL_FUNC_asym_cipher_settable_ctx_params(fns);
+ sparamfncnt++;
+ break;
+ }
+ }
+ if (ctxfncnt != 2
+ || (encfncnt != 0 && encfncnt != 2)
+ || (decfncnt != 0 && decfncnt != 2)
+ || (encfncnt != 2 && decfncnt != 2)
+ || (gparamfncnt != 0 && gparamfncnt != 2)
+ || (sparamfncnt != 0 && sparamfncnt != 2)) {
+ /*
+ * In order to be a consistent set of functions we must have at least
+ * a set of context functions (newctx and freectx) as well as a pair of
+ * "cipher" functions: (encrypt_init, encrypt) or
+ * (decrypt_init decrypt). set_ctx_params and settable_ctx_params are
+ * optional, but if one of them is present then the other one must also
+ * be present. The same applies to get_ctx_params and
+ * gettable_ctx_params. The dupctx function is optional.
+ */
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+ goto err;
+ }
+
+ return cipher;
+ err:
+ EVP_ASYM_CIPHER_free(cipher);
+ return NULL;
+}
+
+void EVP_ASYM_CIPHER_free(EVP_ASYM_CIPHER *cipher)
+{
+ int i;
+
+ if (cipher == NULL)
+ return;
+ CRYPTO_DOWN_REF(&cipher->refcnt, &i, cipher->lock);
+ if (i > 0)
+ return;
+ OPENSSL_free(cipher->type_name);
+ ossl_provider_free(cipher->prov);
+ CRYPTO_THREAD_lock_free(cipher->lock);
+ OPENSSL_free(cipher);
+}
+
+int EVP_ASYM_CIPHER_up_ref(EVP_ASYM_CIPHER *cipher)
+{
+ int ref = 0;
+
+ CRYPTO_UP_REF(&cipher->refcnt, &ref, cipher->lock);
+ return 1;
+}
+
+OSSL_PROVIDER *EVP_ASYM_CIPHER_get0_provider(const EVP_ASYM_CIPHER *cipher)
+{
+ return cipher->prov;
+}
+
+EVP_ASYM_CIPHER *EVP_ASYM_CIPHER_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties)
+{
+ return evp_generic_fetch(ctx, OSSL_OP_ASYM_CIPHER, algorithm, properties,
+ evp_asym_cipher_from_algorithm,
+ (int (*)(void *))EVP_ASYM_CIPHER_up_ref,
+ (void (*)(void *))EVP_ASYM_CIPHER_free);
+}
+
+EVP_ASYM_CIPHER *evp_asym_cipher_fetch_from_prov(OSSL_PROVIDER *prov,
+ const char *algorithm,
+ const char *properties)
+{
+ return evp_generic_fetch_from_prov(prov, OSSL_OP_ASYM_CIPHER,
+ algorithm, properties,
+ evp_asym_cipher_from_algorithm,
+ (int (*)(void *))EVP_ASYM_CIPHER_up_ref,
+ (void (*)(void *))EVP_ASYM_CIPHER_free);
+}
+
+int EVP_ASYM_CIPHER_is_a(const EVP_ASYM_CIPHER *cipher, const char *name)
+{
+ return evp_is_a(cipher->prov, cipher->name_id, NULL, name);
+}
+
+int evp_asym_cipher_get_number(const EVP_ASYM_CIPHER *cipher)
+{
+ return cipher->name_id;
+}
+
+const char *EVP_ASYM_CIPHER_get0_name(const EVP_ASYM_CIPHER *cipher)
+{
+ return cipher->type_name;
+}
+
+const char *EVP_ASYM_CIPHER_get0_description(const EVP_ASYM_CIPHER *cipher)
+{
+ return cipher->description;
+}
+
+void EVP_ASYM_CIPHER_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_ASYM_CIPHER *cipher,
+ void *arg),
+ void *arg)
+{
+ evp_generic_do_all(libctx, OSSL_OP_ASYM_CIPHER,
+ (void (*)(void *, void *))fn, arg,
+ evp_asym_cipher_from_algorithm,
+ (int (*)(void *))EVP_ASYM_CIPHER_up_ref,
+ (void (*)(void *))EVP_ASYM_CIPHER_free);
+}
+
+
+int EVP_ASYM_CIPHER_names_do_all(const EVP_ASYM_CIPHER *cipher,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (cipher->prov != NULL)
+ return evp_names_do_all(cipher->prov, cipher->name_id, fn, data);
+
+ return 1;
+}
+
+const OSSL_PARAM *EVP_ASYM_CIPHER_gettable_ctx_params(const EVP_ASYM_CIPHER *cip)
+{
+ void *provctx;
+
+ if (cip == NULL || cip->gettable_ctx_params == NULL)
+ return NULL;
+
+ provctx = ossl_provider_ctx(EVP_ASYM_CIPHER_get0_provider(cip));
+ return cip->gettable_ctx_params(NULL, provctx);
+}
+
+const OSSL_PARAM *EVP_ASYM_CIPHER_settable_ctx_params(const EVP_ASYM_CIPHER *cip)
+{
+ void *provctx;
+
+ if (cip == NULL || cip->settable_ctx_params == NULL)
+ return NULL;
+
+ provctx = ossl_provider_ctx(EVP_ASYM_CIPHER_get0_provider(cip));
+ return cip->settable_ctx_params(NULL, provctx);
+}
diff --git a/crypto/evp/bio_b64.c b/crypto/evp/bio_b64.c
index 9f891f7626a6..81d2609c302b 100644
--- a/crypto/evp/bio_b64.c
+++ b/crypto/evp/bio_b64.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -46,10 +46,8 @@ typedef struct b64_struct {
static const BIO_METHOD methods_b64 = {
BIO_TYPE_BASE64,
"base64 encoding",
- /* TODO: Convert to new style write function */
bwrite_conv,
b64_write,
- /* TODO: Convert to new style read function */
bread_conv,
b64_read,
b64_puts,
@@ -71,7 +69,7 @@ static int b64_new(BIO *bi)
BIO_B64_CTX *ctx;
if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
- EVPerr(EVP_F_B64_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -534,17 +532,12 @@ static long b64_ctrl(BIO *b, int cmd, long num, void *ptr)
static long b64_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
- long ret = 1;
BIO *next = BIO_next(b);
if (next == NULL)
return 0;
- switch (cmd) {
- default:
- ret = BIO_callback_ctrl(next, cmd, fp);
- break;
- }
- return ret;
+
+ return BIO_callback_ctrl(next, cmd, fp);
}
static int b64_puts(BIO *b, const char *str)
diff --git a/crypto/evp/bio_enc.c b/crypto/evp/bio_enc.c
index 9afce7c08409..304030bcb3b5 100644
--- a/crypto/evp/bio_enc.c
+++ b/crypto/evp/bio_enc.c
@@ -1,12 +1,14 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#define OPENSSL_SUPPRESS_DEPRECATED /* for BIO_get_callback */
+
#include <stdio.h>
#include <errno.h>
#include "internal/cryptlib.h"
@@ -42,10 +44,8 @@ typedef struct enc_struct {
static const BIO_METHOD methods_enc = {
BIO_TYPE_CIPHER,
"cipher",
- /* TODO: Convert to new style write function */
bwrite_conv,
enc_write,
- /* TODO: Convert to new style read function */
bread_conv,
enc_read,
NULL, /* enc_puts, */
@@ -66,7 +66,7 @@ static int enc_new(BIO *bi)
BIO_ENC_CTX *ctx;
if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
- EVPerr(EVP_F_ENC_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -133,7 +133,7 @@ static int enc_read(BIO *b, char *out, int outl)
}
}
- blocksize = EVP_CIPHER_CTX_block_size(ctx->cipher);
+ blocksize = EVP_CIPHER_CTX_get_block_size(ctx->cipher);
if (blocksize == 1)
blocksize = 0;
@@ -311,7 +311,7 @@ static long enc_ctrl(BIO *b, int cmd, long num, void *ptr)
ctx->ok = 1;
ctx->finished = 0;
if (!EVP_CipherInit_ex(ctx->cipher, NULL, NULL, NULL, NULL,
- EVP_CIPHER_CTX_encrypting(ctx->cipher)))
+ EVP_CIPHER_CTX_is_encrypting(ctx->cipher)))
return 0;
ret = BIO_ctrl(next, cmd, num, ptr);
break;
@@ -395,42 +395,54 @@ static long enc_ctrl(BIO *b, int cmd, long num, void *ptr)
static long enc_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
- long ret = 1;
BIO *next = BIO_next(b);
if (next == NULL)
return 0;
- switch (cmd) {
- default:
- ret = BIO_callback_ctrl(next, cmd, fp);
- break;
- }
- return ret;
+
+ return BIO_callback_ctrl(next, cmd, fp);
}
int BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k,
const unsigned char *i, int e)
{
BIO_ENC_CTX *ctx;
- long (*callback) (struct bio_st *, int, const char *, int, long, long);
+ BIO_callback_fn_ex callback_ex;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ long (*callback) (struct bio_st *, int, const char *, int, long, long) = NULL;
+#endif
ctx = BIO_get_data(b);
if (ctx == NULL)
return 0;
- callback = BIO_get_callback(b);
+ if ((callback_ex = BIO_get_callback_ex(b)) != NULL) {
+ if (callback_ex(b, BIO_CB_CTRL, (const char *)c, 0, BIO_CTRL_SET,
+ e, 1, NULL) <= 0)
+ return 0;
+ }
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ else {
+ callback = BIO_get_callback(b);
- if ((callback != NULL) &&
+ if ((callback != NULL) &&
(callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e,
0L) <= 0))
- return 0;
+ return 0;
+ }
+#endif
BIO_set_init(b, 1);
if (!EVP_CipherInit_ex(ctx->cipher, c, NULL, k, i, e))
return 0;
- if (callback != NULL)
+ if (callback_ex != NULL)
+ return callback_ex(b, BIO_CB_CTRL | BIO_CB_RETURN, (const char *)c, 0,
+ BIO_CTRL_SET, e, 1, NULL);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ else if (callback != NULL)
return callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 1L);
+#endif
return 1;
}
diff --git a/crypto/evp/bio_md.c b/crypto/evp/bio_md.c
index fed4cf1eb1ff..1a85be18118b 100644
--- a/crypto/evp/bio_md.c
+++ b/crypto/evp/bio_md.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,11 +9,8 @@
#include <stdio.h>
#include <errno.h>
-#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/evp.h>
-#include "crypto/evp.h"
-#include "evp_local.h"
#include "internal/bio.h"
/*
@@ -31,10 +28,8 @@ static long md_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
static const BIO_METHOD methods_md = {
BIO_TYPE_MD,
"message digest",
- /* TODO: Convert to new style write function */
bwrite_conv,
md_write,
- /* TODO: Convert to new style read function */
bread_conv,
md_read,
NULL, /* md_puts, */
@@ -148,7 +143,7 @@ static long md_ctrl(BIO *b, int cmd, long num, void *ptr)
switch (cmd) {
case BIO_CTRL_RESET:
if (BIO_get_init(b))
- ret = EVP_DigestInit_ex(ctx, ctx->digest, NULL);
+ ret = EVP_DigestInit_ex(ctx, EVP_MD_CTX_get0_md(ctx), NULL);
else
ret = 0;
if (ret > 0)
@@ -157,7 +152,7 @@ static long md_ctrl(BIO *b, int cmd, long num, void *ptr)
case BIO_C_GET_MD:
if (BIO_get_init(b)) {
ppmd = ptr;
- *ppmd = ctx->digest;
+ *ppmd = EVP_MD_CTX_get0_md(ctx);
} else
ret = 0;
break;
@@ -200,7 +195,6 @@ static long md_ctrl(BIO *b, int cmd, long num, void *ptr)
static long md_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
- long ret = 1;
BIO *next;
next = BIO_next(b);
@@ -208,12 +202,7 @@ static long md_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
if (next == NULL)
return 0;
- switch (cmd) {
- default:
- ret = BIO_callback_ctrl(next, cmd, fp);
- break;
- }
- return ret;
+ return BIO_callback_ctrl(next, cmd, fp);
}
static int md_gets(BIO *bp, char *buf, int size)
@@ -223,7 +212,7 @@ static int md_gets(BIO *bp, char *buf, int size)
ctx = BIO_get_data(bp);
- if (size < ctx->digest->md_size)
+ if (size < EVP_MD_CTX_get_size(ctx))
return 0;
if (EVP_DigestFinal_ex(ctx, (unsigned char *)buf, &ret) <= 0)
diff --git a/crypto/evp/bio_ok.c b/crypto/evp/bio_ok.c
index 9610f3c1efeb..97e67fcb6814 100644
--- a/crypto/evp/bio_ok.c
+++ b/crypto/evp/bio_ok.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -76,6 +76,7 @@
#include "internal/bio.h"
#include <openssl/evp.h>
#include <openssl/rand.h>
+#include "internal/endian.h"
#include "crypto/evp.h"
static int ok_write(BIO *h, const char *buf, int num);
@@ -110,10 +111,8 @@ typedef struct ok_struct {
static const BIO_METHOD methods_ok = {
BIO_TYPE_CIPHER,
"reliable",
- /* TODO: Convert to new style write function */
bwrite_conv,
ok_write,
- /* TODO: Convert to new style read function */
bread_conv,
ok_read,
NULL, /* ok_puts, */
@@ -134,7 +133,7 @@ static int ok_new(BIO *bi)
BIO_OK_CTX *ctx;
if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
- EVPerr(EVP_F_OK_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -393,7 +392,7 @@ static long ok_ctrl(BIO *b, int cmd, long num, void *ptr)
case BIO_C_GET_MD:
if (BIO_get_init(b)) {
ppmd = ptr;
- *ppmd = EVP_MD_CTX_md(ctx->md);
+ *ppmd = EVP_MD_CTX_get0_md(ctx->md);
} else
ret = 0;
break;
@@ -406,7 +405,6 @@ static long ok_ctrl(BIO *b, int cmd, long num, void *ptr)
static long ok_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
- long ret = 1;
BIO *next;
next = BIO_next(b);
@@ -414,25 +412,14 @@ static long ok_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
if (next == NULL)
return 0;
- switch (cmd) {
- default:
- ret = BIO_callback_ctrl(next, cmd, fp);
- break;
- }
-
- return ret;
+ return BIO_callback_ctrl(next, cmd, fp);
}
static void longswap(void *_ptr, size_t len)
{
- const union {
- long one;
- char little;
- } is_endian = {
- 1
- };
-
- if (is_endian.little) {
+ DECLARE_IS_ENDIAN;
+
+ if (IS_LITTLE_ENDIAN) {
size_t i;
unsigned char *p = _ptr, c;
@@ -453,9 +440,9 @@ static int sig_out(BIO *b)
ctx = BIO_get_data(b);
md = ctx->md;
- digest = EVP_MD_CTX_md(md);
- md_size = EVP_MD_size(digest);
- md_data = EVP_MD_CTX_md_data(md);
+ digest = EVP_MD_CTX_get0_md(md);
+ md_size = EVP_MD_get_size(digest);
+ md_data = EVP_MD_CTX_get0_md_data(md);
if (ctx->buf_len + 2 * md_size > OK_BLOCK_SIZE)
return 1;
@@ -496,10 +483,12 @@ static int sig_in(BIO *b)
void *md_data;
ctx = BIO_get_data(b);
- md = ctx->md;
- digest = EVP_MD_CTX_md(md);
- md_size = EVP_MD_size(digest);
- md_data = EVP_MD_CTX_md_data(md);
+ if ((md = ctx->md) == NULL)
+ goto berr;
+ digest = EVP_MD_CTX_get0_md(md);
+ if ((md_size = EVP_MD_get_size(digest)) < 0)
+ goto berr;
+ md_data = EVP_MD_CTX_get0_md_data(md);
if ((int)(ctx->buf_len - ctx->buf_off) < 2 * md_size)
return 1;
@@ -543,8 +532,8 @@ static int block_out(BIO *b)
ctx = BIO_get_data(b);
md = ctx->md;
- digest = EVP_MD_CTX_md(md);
- md_size = EVP_MD_size(digest);
+ digest = EVP_MD_CTX_get0_md(md);
+ md_size = EVP_MD_get_size(digest);
tl = ctx->buf_len - OK_BLOCK_BLOCK;
ctx->buf[0] = (unsigned char)(tl >> 24);
@@ -574,7 +563,9 @@ static int block_in(BIO *b)
ctx = BIO_get_data(b);
md = ctx->md;
- md_size = EVP_MD_size(EVP_MD_CTX_md(md));
+ md_size = EVP_MD_get_size(EVP_MD_CTX_get0_md(md));
+ if (md_size < 0)
+ goto berr;
assert(sizeof(tl) >= OK_BLOCK_BLOCK); /* always true */
tl = ctx->buf[0];
diff --git a/crypto/evp/build.info b/crypto/evp/build.info
index cc33ac3c4942..95fea31226b0 100644
--- a/crypto/evp/build.info
+++ b/crypto/evp/build.info
@@ -1,25 +1,71 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \
- e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\
- e_rc4.c e_aes.c names.c e_seed.c e_aria.c e_sm4.c \
- e_xcbc_d.c e_rc2.c e_cast.c e_rc5.c \
- m_null.c m_md2.c m_md4.c m_md5.c m_sha1.c m_wp.c \
- m_md5_sha1.c m_mdc2.c m_ripemd.c m_sha3.c \
- p_open.c p_seal.c p_sign.c p_verify.c p_lib.c p_enc.c p_dec.c \
+$COMMON=digest.c evp_enc.c evp_lib.c evp_fetch.c evp_utils.c \
+ mac_lib.c mac_meth.c keymgmt_meth.c keymgmt_lib.c kdf_lib.c kdf_meth.c \
+ m_sigver.c pmeth_lib.c signature.c p_lib.c pmeth_gn.c exchange.c \
+ evp_rand.c asymcipher.c kem.c dh_support.c ec_support.c pmeth_check.c
+
+SOURCE[../../libcrypto]=$COMMON\
+ encode.c evp_key.c evp_cnf.c \
+ e_des.c e_bf.c e_idea.c e_des3.c \
+ e_rc4.c e_aes.c names.c e_aria.c e_sm4.c \
+ e_xcbc_d.c e_rc2.c e_cast.c e_rc5.c m_null.c \
+ p_seal.c p_sign.c p_verify.c p_legacy.c \
bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \
- c_allc.c c_alld.c evp_lib.c bio_ok.c \
+ c_allc.c c_alld.c bio_ok.c \
evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \
- e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \
e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \
- e_chacha20_poly1305.c cmeth_lib.c
+ e_chacha20_poly1305.c \
+ legacy_sha.c ctrl_params_translate.c \
+ cmeth_lib.c
+
+# Diverse type specific ctrl functions. They are kinda sorta legacy, kinda
+# sorta not.
+SOURCE[../../libcrypto]=dh_ctrl.c dsa_ctrl.c ec_ctrl.c
+
+IF[{- !$disabled{'deprecated-3.0'} -}]
+ SOURCE[../../libcrypto]=p_enc.c p_dec.c
+ENDIF
+IF[{- !$disabled{'deprecated-0.9.8'} -}]
+ SOURCE[../../libcrypto]=e_old.c
+ENDIF
+IF[{- !$disabled{'rsa'} -}]
+ SOURCE[../../libcrypto]=p_open.c
+ENDIF
+IF[{- !$disabled{md2} -}]
+ SOURCE[../../libcrypto]=legacy_md2.c
+ENDIF
+IF[{- !$disabled{md4} -}]
+ SOURCE[../../libcrypto]=legacy_md4.c
+ENDIF
+IF[{- !$disabled{md5} -}]
+ SOURCE[../../libcrypto]=legacy_md5.c legacy_md5_sha1.c
+ENDIF
+IF[{- !$disabled{mdc2} -}]
+ SOURCE[../../libcrypto]=legacy_mdc2.c
+ENDIF
+IF[{- !$disabled{blake2} -}]
+ SOURCE[../../libcrypto]=legacy_blake2.c
+ENDIF
+IF[{- !$disabled{whirlpool} -}]
+ SOURCE[../../libcrypto]=legacy_wp.c
+ENDIF
+IF[{- !$disabled{rmd160} -}]
+ SOURCE[../../libcrypto]=legacy_ripemd.c
+ENDIF
+IF[{- !$disabled{seed} -}]
+ SOURCE[../../libcrypto]=e_seed.c
+ENDIF
+IF[{- !$disabled{camellia} -}]
+ SOURCE[../../libcrypto]=e_camellia.c
+ INCLUDE[e_camellia.o]=.. ../modes
+ENDIF
+
+SOURCE[../../providers/libfips.a]=$COMMON
INCLUDE[e_aes.o]=.. ../modes
INCLUDE[e_aes_cbc_hmac_sha1.o]=../modes
INCLUDE[e_aes_cbc_hmac_sha256.o]=../modes
INCLUDE[e_aria.o]=.. ../modes
-INCLUDE[e_camellia.o]=.. ../modes
INCLUDE[e_sm4.o]=.. ../modes
INCLUDE[e_des.o]=..
INCLUDE[e_des3.o]=..
-INCLUDE[m_sha3.o]=..
diff --git a/crypto/evp/c_allc.c b/crypto/evp/c_allc.c
index 22fdcc409c16..d556b5ab280a 100644
--- a/crypto/evp/c_allc.c
+++ b/crypto/evp/c_allc.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -190,7 +190,6 @@ void openssl_add_all_ciphers_int(void)
EVP_add_cipher(EVP_aes_256_cbc_hmac_sha1());
EVP_add_cipher(EVP_aes_128_cbc_hmac_sha256());
EVP_add_cipher(EVP_aes_256_cbc_hmac_sha256());
-
#ifndef OPENSSL_NO_ARIA
EVP_add_cipher(EVP_aria_128_ecb());
EVP_add_cipher(EVP_aria_128_cbc());
diff --git a/crypto/evp/c_alld.c b/crypto/evp/c_alld.c
index 16ac1b67f465..f7d62bd2ecff 100644
--- a/crypto/evp/c_alld.c
+++ b/crypto/evp/c_alld.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/evp/cmeth_lib.c b/crypto/evp/cmeth_lib.c
index 272e48249e42..a806ec5f9e22 100644
--- a/crypto/evp/cmeth_lib.c
+++ b/crypto/evp/cmeth_lib.c
@@ -1,59 +1,91 @@
/*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * EVP _meth_ APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <string.h>
#include <openssl/evp.h>
#include "crypto/evp.h"
+#include "internal/provider.h"
#include "evp_local.h"
EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len)
{
- EVP_CIPHER *cipher = OPENSSL_zalloc(sizeof(EVP_CIPHER));
+ EVP_CIPHER *cipher = evp_cipher_new();
if (cipher != NULL) {
cipher->nid = cipher_type;
cipher->block_size = block_size;
cipher->key_len = key_len;
+ cipher->origin = EVP_ORIG_METH;
}
return cipher;
}
EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher)
{
- EVP_CIPHER *to = EVP_CIPHER_meth_new(cipher->nid, cipher->block_size,
- cipher->key_len);
+ EVP_CIPHER *to = NULL;
+
+ /*
+ * Non-legacy EVP_CIPHERs can't be duplicated like this.
+ * Use EVP_CIPHER_up_ref() instead.
+ */
+ if (cipher->prov != NULL)
+ return NULL;
+
+ if ((to = EVP_CIPHER_meth_new(cipher->nid, cipher->block_size,
+ cipher->key_len)) != NULL) {
+ CRYPTO_RWLOCK *lock = to->lock;
- if (to != NULL)
memcpy(to, cipher, sizeof(*to));
+ to->lock = lock;
+ to->origin = EVP_ORIG_METH;
+ }
return to;
}
void EVP_CIPHER_meth_free(EVP_CIPHER *cipher)
{
- OPENSSL_free(cipher);
+ if (cipher == NULL || cipher->origin != EVP_ORIG_METH)
+ return;
+
+ evp_cipher_free_int(cipher);
}
int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len)
{
+ if (cipher->iv_len != 0)
+ return 0;
+
cipher->iv_len = iv_len;
return 1;
}
int EVP_CIPHER_meth_set_flags(EVP_CIPHER *cipher, unsigned long flags)
{
+ if (cipher->flags != 0)
+ return 0;
+
cipher->flags = flags;
return 1;
}
int EVP_CIPHER_meth_set_impl_ctx_size(EVP_CIPHER *cipher, int ctx_size)
{
+ if (cipher->ctx_size != 0)
+ return 0;
+
cipher->ctx_size = ctx_size;
return 1;
}
@@ -64,6 +96,9 @@ int EVP_CIPHER_meth_set_init(EVP_CIPHER *cipher,
const unsigned char *iv,
int enc))
{
+ if (cipher->init != NULL)
+ return 0;
+
cipher->init = init;
return 1;
}
@@ -74,6 +109,9 @@ int EVP_CIPHER_meth_set_do_cipher(EVP_CIPHER *cipher,
const unsigned char *in,
size_t inl))
{
+ if (cipher->do_cipher != NULL)
+ return 0;
+
cipher->do_cipher = do_cipher;
return 1;
}
@@ -81,6 +119,9 @@ int EVP_CIPHER_meth_set_do_cipher(EVP_CIPHER *cipher,
int EVP_CIPHER_meth_set_cleanup(EVP_CIPHER *cipher,
int (*cleanup) (EVP_CIPHER_CTX *))
{
+ if (cipher->cleanup != NULL)
+ return 0;
+
cipher->cleanup = cleanup;
return 1;
}
@@ -89,6 +130,9 @@ int EVP_CIPHER_meth_set_set_asn1_params(EVP_CIPHER *cipher,
int (*set_asn1_parameters) (EVP_CIPHER_CTX *,
ASN1_TYPE *))
{
+ if (cipher->set_asn1_parameters != NULL)
+ return 0;
+
cipher->set_asn1_parameters = set_asn1_parameters;
return 1;
}
@@ -97,6 +141,9 @@ int EVP_CIPHER_meth_set_get_asn1_params(EVP_CIPHER *cipher,
int (*get_asn1_parameters) (EVP_CIPHER_CTX *,
ASN1_TYPE *))
{
+ if (cipher->get_asn1_parameters != NULL)
+ return 0;
+
cipher->get_asn1_parameters = get_asn1_parameters;
return 1;
}
@@ -105,6 +152,9 @@ int EVP_CIPHER_meth_set_ctrl(EVP_CIPHER *cipher,
int (*ctrl) (EVP_CIPHER_CTX *, int type,
int arg, void *ptr))
{
+ if (cipher->ctrl != NULL)
+ return 0;
+
cipher->ctrl = ctrl;
return 1;
}
diff --git a/crypto/evp/ctrl_params_translate.c b/crypto/evp/ctrl_params_translate.c
new file mode 100644
index 000000000000..c767c316439d
--- /dev/null
+++ b/crypto/evp/ctrl_params_translate.c
@@ -0,0 +1,2808 @@
+/*
+ * Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Some ctrls depend on deprecated functionality. We trust that this is
+ * functionality that remains internally even when 'no-deprecated' is
+ * configured. When we drop #legacy EVP_PKEYs, this source should be
+ * possible to drop as well.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h>
+
+/* The following includes get us all the EVP_PKEY_CTRL macros */
+#include <openssl/dh.h>
+#include <openssl/dsa.h>
+#include <openssl/ec.h>
+#include <openssl/rsa.h>
+#include <openssl/kdf.h>
+
+/* This include gets us all the OSSL_PARAM key string macros */
+#include <openssl/core_names.h>
+
+#include <openssl/err.h>
+#include <openssl/evperr.h>
+#include <openssl/params.h>
+#include "internal/nelem.h"
+#include "internal/cryptlib.h"
+#include "internal/ffc.h"
+#include "crypto/evp.h"
+#include "crypto/dh.h"
+#include "crypto/ec.h"
+
+struct translation_ctx_st; /* Forwarding */
+struct translation_st; /* Forwarding */
+
+/*
+ * The fixup_args functions are called with the following parameters:
+ *
+ * |state| The state we're called in, explained further at the
+ * end of this comment.
+ * |translation| The translation item, to be pilfered for data as
+ * necessary.
+ * |ctx| The translation context, which contains copies of
+ * the following arguments, applicable according to
+ * the caller. All of the attributes in this context
+ * may be freely modified by the fixup_args function.
+ * For cleanup, call cleanup_translation_ctx().
+ *
+ * The |state| tells the fixup_args function something about the caller and
+ * what they may expect:
+ *
+ * PKEY The fixup_args function has been called
+ * from an EVP_PKEY payload getter / setter,
+ * and is fully responsible for getting or
+ * setting the requested data. With this
+ * state, the fixup_args function is expected
+ * to use or modify |*params|, depending on
+ * |action_type|.
+ *
+ * PRE_CTRL_TO_PARAMS The fixup_args function has been called
+ * POST_CTRL_TO_PARAMS from EVP_PKEY_CTX_ctrl(), to help with
+ * translating the ctrl data to an OSSL_PARAM
+ * element or back. The calling sequence is
+ * as follows:
+ *
+ * 1. fixup_args(PRE_CTRL_TO_PARAMS, ...)
+ * 2. EVP_PKEY_CTX_set_params() or
+ * EVP_PKEY_CTX_get_params()
+ * 3. fixup_args(POST_CTRL_TO_PARAMS, ...)
+ *
+ * With the PRE_CTRL_TO_PARAMS state, the
+ * fixup_args function is expected to modify
+ * the passed |*params| in whatever way
+ * necessary, when |action_type == SET|.
+ * With the POST_CTRL_TO_PARAMS state, the
+ * fixup_args function is expected to modify
+ * the passed |p2| in whatever way necessary,
+ * when |action_type == GET|.
+ *
+ * The return value from the fixup_args call
+ * with the POST_CTRL_TO_PARAMS state becomes
+ * the return value back to EVP_PKEY_CTX_ctrl().
+ *
+ * CLEANUP_CTRL_TO_PARAMS The cleanup_args functions has been called
+ * from EVP_PKEY_CTX_ctrl(), to clean up what
+ * the fixup_args function has done, if needed.
+ *
+ *
+ * PRE_CTRL_STR_TO_PARAMS The fixup_args function has been called
+ * POST_CTRL_STR_TO_PARAMS from EVP_PKEY_CTX_ctrl_str(), to help with
+ * translating the ctrl_str data to an
+ * OSSL_PARAM element or back. The calling
+ * sequence is as follows:
+ *
+ * 1. fixup_args(PRE_CTRL_STR_TO_PARAMS, ...)
+ * 2. EVP_PKEY_CTX_set_params() or
+ * EVP_PKEY_CTX_get_params()
+ * 3. fixup_args(POST_CTRL_STR_TO_PARAMS, ...)
+ *
+ * With the PRE_CTRL_STR_TO_PARAMS state,
+ * the fixup_args function is expected to
+ * modify the passed |*params| in whatever
+ * way necessary, when |action_type == SET|.
+ * With the POST_CTRL_STR_TO_PARAMS state,
+ * the fixup_args function is only expected
+ * to return a value.
+ *
+ * CLEANUP_CTRL_STR_TO_PARAMS The cleanup_args functions has been called
+ * from EVP_PKEY_CTX_ctrl_str(), to clean up
+ * what the fixup_args function has done, if
+ * needed.
+ *
+ * PRE_PARAMS_TO_CTRL The fixup_args function has been called
+ * POST_PARAMS_TO_CTRL from EVP_PKEY_CTX_get_params() or
+ * EVP_PKEY_CTX_set_params(), to help with
+ * translating the OSSL_PARAM data to the
+ * corresponding EVP_PKEY_CTX_ctrl() arguments
+ * or the other way around. The calling
+ * sequence is as follows:
+ *
+ * 1. fixup_args(PRE_PARAMS_TO_CTRL, ...)
+ * 2. EVP_PKEY_CTX_ctrl()
+ * 3. fixup_args(POST_PARAMS_TO_CTRL, ...)
+ *
+ * With the PRE_PARAMS_TO_CTRL state, the
+ * fixup_args function is expected to modify
+ * the passed |p1| and |p2| in whatever way
+ * necessary, when |action_type == SET|.
+ * With the POST_PARAMS_TO_CTRL state, the
+ * fixup_args function is expected to
+ * modify the passed |*params| in whatever
+ * way necessary, when |action_type == GET|.
+ *
+ * CLEANUP_PARAMS_TO_CTRL The cleanup_args functions has been called
+ * from EVP_PKEY_CTX_get_params() or
+ * EVP_PKEY_CTX_set_params(), to clean up what
+ * the fixup_args function has done, if needed.
+ */
+enum state {
+ PKEY,
+ PRE_CTRL_TO_PARAMS, POST_CTRL_TO_PARAMS, CLEANUP_CTRL_TO_PARAMS,
+ PRE_CTRL_STR_TO_PARAMS, POST_CTRL_STR_TO_PARAMS, CLEANUP_CTRL_STR_TO_PARAMS,
+ PRE_PARAMS_TO_CTRL, POST_PARAMS_TO_CTRL, CLEANUP_PARAMS_TO_CTRL
+};
+enum action {
+ NONE = 0, GET = 1, SET = 2
+};
+typedef int fixup_args_fn(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx);
+typedef int cleanup_args_fn(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx);
+
+struct translation_ctx_st {
+ /*
+ * The EVP_PKEY_CTX, for calls on that structure, to be pilfered for data
+ * as necessary.
+ */
+ EVP_PKEY_CTX *pctx;
+ /*
+ * The action type (GET or SET). This may be 0 in some cases, and should
+ * be modified by the fixup_args function in the PRE states. It should
+ * otherwise remain untouched once set.
+ */
+ enum action action_type;
+ /*
+ * For ctrl to params translation, the actual ctrl command number used.
+ * For params to ctrl translation, 0.
+ */
+ int ctrl_cmd;
+ /*
+ * For ctrl_str to params translation, the actual ctrl command string
+ * used. In this case, the (string) value is always passed as |p2|.
+ * For params to ctrl translation, this is NULL. Along with it is also
+ * and indicator whether it matched |ctrl_str| or |ctrl_hexstr| in the
+ * translation item.
+ */
+ const char *ctrl_str;
+ int ishex;
+ /* the ctrl-style int argument. */
+ int p1;
+ /* the ctrl-style void* argument. */
+ void *p2;
+ /* a size, for passing back the |p2| size where applicable */
+ size_t sz;
+ /* pointer to the OSSL_PARAM-style params array. */
+ OSSL_PARAM *params;
+
+ /*-
+ * The following are used entirely internally by the fixup_args functions
+ * and should not be touched by the callers, at all.
+ */
+
+ /*
+ * Copy of the ctrl-style void* argument, if the fixup_args function
+ * needs to manipulate |p2| but wants to remember original.
+ */
+ void *orig_p2;
+ /* Diverse types of storage for the needy. */
+ char name_buf[OSSL_MAX_NAME_SIZE];
+ void *allocated_buf;
+ void *bufp;
+ size_t buflen;
+};
+
+struct translation_st {
+ /*-
+ * What this table item does.
+ *
+ * If the item has this set to 0, it means that both GET and SET are
+ * supported, and |fixup_args| will determine which it is. This is to
+ * support translations of ctrls where the action type depends on the
+ * value of |p1| or |p2| (ctrls are really bi-directional, but are
+ * seldom used that way).
+ *
+ * This can be also used in the lookup template when it looks up by
+ * OSSL_PARAM key, to indicate if a setter or a getter called.
+ */
+ enum action action_type;
+
+ /*-
+ * Conditions, for params->ctrl translations.
+ *
+ * In table item, |keytype1| and |keytype2| can be set to -1 to indicate
+ * that this item supports all key types (or rather, that |fixup_args|
+ * will check and return an error if it's not supported).
+ * Any of these may be set to 0 to indicate that they are unset.
+ */
+ int keytype1; /* The EVP_PKEY_XXX type, i.e. NIDs. #legacy */
+ int keytype2; /* Another EVP_PKEY_XXX type, used for aliases */
+ int optype; /* The operation type */
+
+ /*
+ * Lookup and translation attributes
+ *
+ * |ctrl_num|, |ctrl_str|, |ctrl_hexstr| and |param_key| are lookup
+ * attributes.
+ *
+ * |ctrl_num| may be 0 or that |param_key| may be NULL in the table item,
+ * but not at the same time. If they are, they are simply not used for
+ * lookup.
+ * When |ctrl_num| == 0, no ctrl will be called. Likewise, when
+ * |param_key| == NULL, no OSSL_PARAM setter/getter will be called.
+ * In that case the treatment of the translation item relies entirely on
+ * |fixup_args|, which is then assumed to have side effects.
+ *
+ * As a special case, it's possible to set |ctrl_hexstr| and assign NULL
+ * to |ctrl_str|. That will signal to default_fixup_args() that the
+ * value must always be interpreted as hex.
+ */
+ int ctrl_num; /* EVP_PKEY_CTRL_xxx */
+ const char *ctrl_str; /* The corresponding ctrl string */
+ const char *ctrl_hexstr; /* The alternative "hex{str}" ctrl string */
+ const char *param_key; /* The corresponding OSSL_PARAM key */
+ /*
+ * The appropriate OSSL_PARAM data type. This may be 0 to indicate that
+ * this OSSL_PARAM may have more than one data type, depending on input
+ * material. In this case, |fixup_args| is expected to check and handle
+ * it.
+ */
+ unsigned int param_data_type;
+
+ /*
+ * Fixer functions
+ *
+ * |fixup_args| is always called before (for SET) or after (for GET)
+ * the actual ctrl / OSSL_PARAM function.
+ */
+ fixup_args_fn *fixup_args;
+};
+
+/*-
+ * Fixer function implementations
+ * ==============================
+ */
+
+/*
+ * default_check isn't a fixer per se, but rather a helper function to
+ * perform certain standard checks.
+ */
+static int default_check(enum state state,
+ const struct translation_st *translation,
+ const struct translation_ctx_st *ctx)
+{
+ switch (state) {
+ default:
+ break;
+ case PRE_CTRL_TO_PARAMS:
+ if (!ossl_assert(translation != NULL)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return -2;
+ }
+ if (!ossl_assert(translation->param_key != 0)
+ || !ossl_assert(translation->param_data_type != 0)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ break;
+ case PRE_CTRL_STR_TO_PARAMS:
+ /*
+ * For ctrl_str to params translation, we allow direct use of
+ * OSSL_PARAM keys as ctrl_str keys. Therefore, it's possible that
+ * we end up with |translation == NULL|, which is fine. The fixup
+ * function will have to deal with it carefully.
+ */
+ if (translation != NULL) {
+ if (!ossl_assert(translation->action_type != GET)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return -2;
+ }
+ if (!ossl_assert(translation->param_key != NULL)
+ || !ossl_assert(translation->param_data_type != 0)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ break;
+ case PRE_PARAMS_TO_CTRL:
+ case POST_PARAMS_TO_CTRL:
+ if (!ossl_assert(translation != NULL)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return -2;
+ }
+ if (!ossl_assert(translation->ctrl_num != 0)
+ || !ossl_assert(translation->param_data_type != 0)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ }
+
+ /* Nothing else to check */
+ return 1;
+}
+
+/*-
+ * default_fixup_args fixes up all sorts of arguments, governed by the
+ * diverse attributes in the translation item. It covers all "standard"
+ * base ctrl functionality, meaning it can handle basic conversion of
+ * data between p1+p2 (SET) or return value+p2 (GET) as long as the values
+ * don't have extra semantics (such as NIDs, OIDs, that sort of stuff).
+ * Extra semantics must be handled via specific fixup_args functions.
+ *
+ * The following states and action type combinations have standard handling
+ * done in this function:
+ *
+ * PRE_CTRL_TO_PARAMS, 0 - ERROR. action type must be
+ * determined by a fixup function.
+ * PRE_CTRL_TO_PARAMS, SET | GET - |p1| and |p2| are converted to an
+ * OSSL_PARAM according to the data
+ * type given in |translattion|.
+ * For OSSL_PARAM_UNSIGNED_INTEGER,
+ * a BIGNUM passed as |p2| is accepted.
+ * POST_CTRL_TO_PARAMS, GET - If the OSSL_PARAM data type is a
+ * STRING or PTR type, |p1| is set
+ * to the OSSL_PARAM return size, and
+ * |p2| is set to the string.
+ * PRE_CTRL_STR_TO_PARAMS, !SET - ERROR. That combination is not
+ * supported.
+ * PRE_CTRL_STR_TO_PARAMS, SET - |p2| is taken as a string, and is
+ * converted to an OSSL_PARAM in a
+ * standard manner, guided by the
+ * param key and data type from
+ * |translation|.
+ * PRE_PARAMS_TO_CTRL, SET - the OSSL_PARAM is converted to
+ * |p1| and |p2| according to the
+ * data type given in |translation|
+ * For OSSL_PARAM_UNSIGNED_INTEGER,
+ * if |p2| is non-NULL, then |*p2|
+ * is assigned a BIGNUM, otherwise
+ * |p1| is assigned an unsigned int.
+ * POST_PARAMS_TO_CTRL, GET - |p1| and |p2| are converted to
+ * an OSSL_PARAM, in the same manner
+ * as for the combination of
+ * PRE_CTRL_TO_PARAMS, SET.
+ */
+static int default_fixup_args(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ int ret;
+
+ if ((ret = default_check(state, translation, ctx)) < 0)
+ return ret;
+
+ switch (state) {
+ default:
+ /* For states this function should never have been called with */
+ ERR_raise_data(ERR_LIB_EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,
+ "[action:%d, state:%d]", ctx->action_type, state);
+ return 0;
+
+ /*
+ * PRE_CTRL_TO_PARAMS and POST_CTRL_TO_PARAMS handle ctrl to params
+ * translations. PRE_CTRL_TO_PARAMS is responsible for preparing
+ * |*params|, and POST_CTRL_TO_PARAMS is responsible for bringing the
+ * result back to |*p2| and the return value.
+ */
+ case PRE_CTRL_TO_PARAMS:
+ /* This is ctrl to params translation, so we need an OSSL_PARAM key */
+ if (ctx->action_type == NONE) {
+ /*
+ * No action type is an error here. That's a case for a
+ * special fixup function.
+ */
+ ERR_raise_data(ERR_LIB_EVP, ERR_R_UNSUPPORTED,
+ "[action:%d, state:%d]", ctx->action_type, state);
+ return 0;
+ }
+
+ if (translation->optype != 0) {
+ if ((EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx->pctx)
+ && ctx->pctx->op.sig.algctx == NULL)
+ || (EVP_PKEY_CTX_IS_DERIVE_OP(ctx->pctx)
+ && ctx->pctx->op.kex.algctx == NULL)
+ || (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx->pctx)
+ && ctx->pctx->op.ciph.algctx == NULL)
+ || (EVP_PKEY_CTX_IS_KEM_OP(ctx->pctx)
+ && ctx->pctx->op.encap.algctx == NULL)
+ /*
+ * The following may be unnecessary, but we have them
+ * for good measure...
+ */
+ || (EVP_PKEY_CTX_IS_GEN_OP(ctx->pctx)
+ && ctx->pctx->op.keymgmt.genctx == NULL)
+ || (EVP_PKEY_CTX_IS_FROMDATA_OP(ctx->pctx)
+ && ctx->pctx->op.keymgmt.genctx == NULL)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+ }
+
+ /*
+ * OSSL_PARAM_construct_TYPE() works equally well for both SET and GET.
+ */
+ switch (translation->param_data_type) {
+ case OSSL_PARAM_INTEGER:
+ *ctx->params = OSSL_PARAM_construct_int(translation->param_key,
+ &ctx->p1);
+ break;
+ case OSSL_PARAM_UNSIGNED_INTEGER:
+ /*
+ * BIGNUMs are passed via |p2|. For all ctrl's that just want
+ * to pass a simple integer via |p1|, |p2| is expected to be
+ * NULL.
+ *
+ * Note that this allocates a buffer, which the cleanup function
+ * must deallocate.
+ */
+ if (ctx->p2 != NULL) {
+ if (ctx->action_type == SET) {
+ ctx->buflen = BN_num_bytes(ctx->p2);
+ if ((ctx->allocated_buf =
+ OPENSSL_malloc(ctx->buflen)) == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (BN_bn2nativepad(ctx->p2,
+ ctx->allocated_buf, ctx->buflen) < 0) {
+ OPENSSL_free(ctx->allocated_buf);
+ ctx->allocated_buf = NULL;
+ return 0;
+ }
+ *ctx->params =
+ OSSL_PARAM_construct_BN(translation->param_key,
+ ctx->allocated_buf,
+ ctx->buflen);
+ } else {
+ /*
+ * No support for getting a BIGNUM by ctrl, this needs
+ * fixup_args function support.
+ */
+ ERR_raise_data(ERR_LIB_EVP, ERR_R_UNSUPPORTED,
+ "[action:%d, state:%d] trying to get a "
+ "BIGNUM via ctrl call",
+ ctx->action_type, state);
+ return 0;
+ }
+ } else {
+ *ctx->params =
+ OSSL_PARAM_construct_uint(translation->param_key,
+ (unsigned int *)&ctx->p1);
+ }
+ break;
+ case OSSL_PARAM_UTF8_STRING:
+ *ctx->params =
+ OSSL_PARAM_construct_utf8_string(translation->param_key,
+ ctx->p2, (size_t)ctx->p1);
+ break;
+ case OSSL_PARAM_UTF8_PTR:
+ *ctx->params =
+ OSSL_PARAM_construct_utf8_ptr(translation->param_key,
+ ctx->p2, (size_t)ctx->p1);
+ break;
+ case OSSL_PARAM_OCTET_STRING:
+ *ctx->params =
+ OSSL_PARAM_construct_octet_string(translation->param_key,
+ ctx->p2, (size_t)ctx->p1);
+ break;
+ case OSSL_PARAM_OCTET_PTR:
+ *ctx->params =
+ OSSL_PARAM_construct_octet_ptr(translation->param_key,
+ ctx->p2, (size_t)ctx->p1);
+ break;
+ }
+ break;
+ case POST_CTRL_TO_PARAMS:
+ /*
+ * Because EVP_PKEY_CTX_ctrl() returns the length of certain objects
+ * as its return value, we need to ensure that we do it here as well,
+ * for the OSSL_PARAM data types where this makes sense.
+ */
+ if (ctx->action_type == GET) {
+ switch (translation->param_data_type) {
+ case OSSL_PARAM_UTF8_STRING:
+ case OSSL_PARAM_UTF8_PTR:
+ case OSSL_PARAM_OCTET_STRING:
+ case OSSL_PARAM_OCTET_PTR:
+ ctx->p1 = (int)ctx->params[0].return_size;
+ break;
+ }
+ }
+ break;
+
+ /*
+ * PRE_CTRL_STR_TO_PARAMS and POST_CTRL_STR_TO_PARAMS handle ctrl_str to
+ * params translations. PRE_CTRL_TO_PARAMS is responsible for preparing
+ * |*params|, and POST_CTRL_TO_PARAMS currently has nothing to do, since
+ * there's no support for getting data via ctrl_str calls.
+ */
+ case PRE_CTRL_STR_TO_PARAMS:
+ {
+ /* This is ctrl_str to params translation */
+ const char *tmp_ctrl_str = ctx->ctrl_str;
+ const char *orig_ctrl_str = ctx->ctrl_str;
+ const char *orig_value = ctx->p2;
+ const OSSL_PARAM *settable = NULL;
+ int exists = 0;
+
+ /* Only setting is supported here */
+ if (ctx->action_type != SET) {
+ ERR_raise_data(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED,
+ "[action:%d, state:%d] only setting allowed",
+ ctx->action_type, state);
+ return 0;
+ }
+
+ /*
+ * If no translation exists, we simply pass the control string
+ * unmodified.
+ */
+ if (translation != NULL) {
+ tmp_ctrl_str = ctx->ctrl_str = translation->param_key;
+
+ if (ctx->ishex) {
+ strcpy(ctx->name_buf, "hex");
+ if (OPENSSL_strlcat(ctx->name_buf, tmp_ctrl_str,
+ sizeof(ctx->name_buf)) <= 3) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ tmp_ctrl_str = ctx->name_buf;
+ }
+ }
+
+ settable = EVP_PKEY_CTX_settable_params(ctx->pctx);
+ if (!OSSL_PARAM_allocate_from_text(ctx->params, settable,
+ tmp_ctrl_str,
+ ctx->p2, strlen(ctx->p2),
+ &exists)) {
+ if (!exists) {
+ ERR_raise_data(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED,
+ "[action:%d, state:%d] name=%s, value=%s",
+ ctx->action_type, state,
+ orig_ctrl_str, orig_value);
+ return -2;
+ }
+ return 0;
+ }
+ ctx->allocated_buf = ctx->params->data;
+ ctx->buflen = ctx->params->data_size;
+ }
+ break;
+ case POST_CTRL_STR_TO_PARAMS:
+ /* Nothing to be done */
+ break;
+
+ /*
+ * PRE_PARAMS_TO_CTRL and POST_PARAMS_TO_CTRL handle params to ctrl
+ * translations. PRE_PARAMS_TO_CTRL is responsible for preparing
+ * |p1| and |p2|, and POST_PARAMS_TO_CTRL is responsible for bringing
+ * the EVP_PKEY_CTX_ctrl() return value (passed as |p1|) and |p2| back
+ * to |*params|.
+ *
+ * PKEY is treated just like POST_PARAMS_TO_CTRL, making it easy
+ * for the related fixup_args functions to just set |p1| and |p2|
+ * appropriately and leave it to this section of code to fix up
+ * |ctx->params| accordingly.
+ */
+ case PKEY:
+ case POST_PARAMS_TO_CTRL:
+ ret = ctx->p1;
+ /* FALLTHRU */
+ case PRE_PARAMS_TO_CTRL:
+ {
+ /* This is params to ctrl translation */
+ if (state == PRE_PARAMS_TO_CTRL && ctx->action_type == SET) {
+ /* For the PRE state, only setting needs some work to be done */
+
+ /* When setting, we populate |p1| and |p2| from |*params| */
+ switch (translation->param_data_type) {
+ case OSSL_PARAM_INTEGER:
+ return OSSL_PARAM_get_int(ctx->params, &ctx->p1);
+ case OSSL_PARAM_UNSIGNED_INTEGER:
+ if (ctx->p2 != NULL) {
+ /* BIGNUM passed down with p2 */
+ if (!OSSL_PARAM_get_BN(ctx->params, ctx->p2))
+ return 0;
+ } else {
+ /* Normal C unsigned int passed down */
+ if (!OSSL_PARAM_get_uint(ctx->params,
+ (unsigned int *)&ctx->p1))
+ return 0;
+ }
+ return 1;
+ case OSSL_PARAM_UTF8_STRING:
+ return OSSL_PARAM_get_utf8_string(ctx->params,
+ ctx->p2, ctx->sz);
+ case OSSL_PARAM_OCTET_STRING:
+ return OSSL_PARAM_get_octet_string(ctx->params,
+ ctx->p2, ctx->sz,
+ &ctx->sz);
+ case OSSL_PARAM_OCTET_PTR:
+ return OSSL_PARAM_get_octet_ptr(ctx->params,
+ ctx->p2, &ctx->sz);
+ default:
+ ERR_raise_data(ERR_LIB_EVP, ERR_R_UNSUPPORTED,
+ "[action:%d, state:%d] "
+ "unknown OSSL_PARAM data type %d",
+ ctx->action_type, state,
+ translation->param_data_type);
+ return 0;
+ }
+ } else if ((state == POST_PARAMS_TO_CTRL || state == PKEY)
+ && ctx->action_type == GET) {
+ /* For the POST state, only getting needs some work to be done */
+ unsigned int param_data_type = translation->param_data_type;
+ size_t size = (size_t)ctx->p1;
+
+ if (state == PKEY)
+ size = ctx->sz;
+ if (param_data_type == 0) {
+ /* we must have a fixup_args function to work */
+ if (!ossl_assert(translation->fixup_args != NULL)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ param_data_type = ctx->params->data_type;
+ }
+ /* When getting, we populate |*params| from |p1| and |p2| */
+ switch (param_data_type) {
+ case OSSL_PARAM_INTEGER:
+ return OSSL_PARAM_set_int(ctx->params, ctx->p1);
+ case OSSL_PARAM_UNSIGNED_INTEGER:
+ if (ctx->p2 != NULL) {
+ /* BIGNUM passed back */
+ return OSSL_PARAM_set_BN(ctx->params, ctx->p2);
+ } else {
+ /* Normal C unsigned int passed back */
+ return OSSL_PARAM_set_uint(ctx->params,
+ (unsigned int)ctx->p1);
+ }
+ return 0;
+ case OSSL_PARAM_UTF8_STRING:
+ return OSSL_PARAM_set_utf8_string(ctx->params, ctx->p2);
+ case OSSL_PARAM_OCTET_STRING:
+ return OSSL_PARAM_set_octet_string(ctx->params, ctx->p2,
+ size);
+ case OSSL_PARAM_OCTET_PTR:
+ return OSSL_PARAM_set_octet_ptr(ctx->params, ctx->p2,
+ size);
+ default:
+ ERR_raise_data(ERR_LIB_EVP, ERR_R_UNSUPPORTED,
+ "[action:%d, state:%d] "
+ "unsupported OSSL_PARAM data type %d",
+ ctx->action_type, state,
+ translation->param_data_type);
+ return 0;
+ }
+ }
+ }
+ /* Any other combination is simply pass-through */
+ break;
+ }
+ return ret;
+}
+
+static int
+cleanup_translation_ctx(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ if (ctx->allocated_buf != NULL)
+ OPENSSL_free(ctx->allocated_buf);
+ ctx->allocated_buf = NULL;
+ return 1;
+}
+
+/*
+ * fix_cipher_md fixes up an EVP_CIPHER / EVP_MD to its name on SET,
+ * and cipher / md name to EVP_MD on GET.
+ */
+static const char *get_cipher_name(void *cipher)
+{
+ return EVP_CIPHER_get0_name(cipher);
+}
+
+static const char *get_md_name(void *md)
+{
+ return EVP_MD_get0_name(md);
+}
+
+static const void *get_cipher_by_name(OSSL_LIB_CTX *libctx, const char *name)
+{
+ return evp_get_cipherbyname_ex(libctx, name);
+}
+
+static const void *get_md_by_name(OSSL_LIB_CTX *libctx, const char *name)
+{
+ return evp_get_digestbyname_ex(libctx, name);
+}
+
+static int fix_cipher_md(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx,
+ const char *(*get_name)(void *algo),
+ const void *(*get_algo_by_name)(OSSL_LIB_CTX *libctx,
+ const char *name))
+{
+ int ret = 1;
+
+ if ((ret = default_check(state, translation, ctx)) <= 0)
+ return ret;
+
+ if (state == PRE_CTRL_TO_PARAMS && ctx->action_type == GET) {
+ /*
+ * |ctx->p2| contains the address to an EVP_CIPHER or EVP_MD pointer
+ * to be filled in. We need to remember it, then make |ctx->p2|
+ * point at a buffer to be filled in with the name, and |ctx->p1|
+ * with its size. default_fixup_args() will take care of the rest
+ * for us.
+ */
+ ctx->orig_p2 = ctx->p2;
+ ctx->p2 = ctx->name_buf;
+ ctx->p1 = sizeof(ctx->name_buf);
+ } else if (state == PRE_CTRL_TO_PARAMS && ctx->action_type == SET) {
+ /*
+ * In different parts of OpenSSL, this ctrl command is used
+ * differently. Some calls pass a NID as p1, others pass an
+ * EVP_CIPHER pointer as p2...
+ */
+ ctx->p2 = (char *)(ctx->p2 == NULL
+ ? OBJ_nid2sn(ctx->p1)
+ : get_name(ctx->p2));
+ ctx->p1 = strlen(ctx->p2);
+ } else if (state == POST_PARAMS_TO_CTRL && ctx->action_type == GET) {
+ ctx->p2 = (ctx->p2 == NULL ? "" : (char *)get_name(ctx->p2));
+ ctx->p1 = strlen(ctx->p2);
+ }
+
+ if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
+ return ret;
+
+ if (state == POST_CTRL_TO_PARAMS && ctx->action_type == GET) {
+ /*
+ * Here's how we re-use |ctx->orig_p2| that was set in the
+ * PRE_CTRL_TO_PARAMS state above.
+ */
+ *(void **)ctx->orig_p2 =
+ (void *)get_algo_by_name(ctx->pctx->libctx, ctx->p2);
+ ctx->p1 = 1;
+ } else if (state == PRE_PARAMS_TO_CTRL && ctx->action_type == SET) {
+ ctx->p2 = (void *)get_algo_by_name(ctx->pctx->libctx, ctx->p2);
+ ctx->p1 = 0;
+ }
+
+ return ret;
+}
+
+static int fix_cipher(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ return fix_cipher_md(state, translation, ctx,
+ get_cipher_name, get_cipher_by_name);
+}
+
+static int fix_md(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ return fix_cipher_md(state, translation, ctx,
+ get_md_name, get_md_by_name);
+}
+
+static int fix_distid_len(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ int ret = default_fixup_args(state, translation, ctx);
+
+ if (ret > 0) {
+ ret = 0;
+ if ((state == POST_CTRL_TO_PARAMS
+ || state == POST_CTRL_STR_TO_PARAMS) && ctx->action_type == GET) {
+ *(size_t *)ctx->p2 = ctx->sz;
+ ret = 1;
+ }
+ }
+ return ret;
+}
+
+struct kdf_type_map_st {
+ int kdf_type_num;
+ const char *kdf_type_str;
+};
+
+static int fix_kdf_type(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx,
+ const struct kdf_type_map_st *kdf_type_map)
+{
+ /*
+ * The EVP_PKEY_CTRL_DH_KDF_TYPE ctrl command is a bit special, in
+ * that it's used both for setting a value, and for getting it, all
+ * depending on the value if |p1|; if |p1| is -2, the backend is
+ * supposed to place the current kdf type in |p2|, and if not, |p1|
+ * is interpreted as the new kdf type.
+ */
+ int ret = 0;
+
+ if ((ret = default_check(state, translation, ctx)) <= 0)
+ return ret;
+
+ if (state == PRE_CTRL_TO_PARAMS) {
+ /*
+ * In |translations|, the initial value for |ctx->action_type| must
+ * be NONE.
+ */
+ if (!ossl_assert(ctx->action_type == NONE))
+ return 0;
+
+ /* The action type depends on the value of *p1 */
+ if (ctx->p1 == -2) {
+ /*
+ * The OSSL_PARAMS getter needs space to store a copy of the kdf
+ * type string. We use |ctx->name_buf|, which has enough space
+ * allocated.
+ *
+ * (this wouldn't be needed if the OSSL_xxx_PARAM_KDF_TYPE
+ * had the data type OSSL_PARAM_UTF8_PTR)
+ */
+ ctx->p2 = ctx->name_buf;
+ ctx->p1 = sizeof(ctx->name_buf);
+ ctx->action_type = GET;
+ } else {
+ ctx->action_type = SET;
+ }
+ }
+
+ if ((ret = default_check(state, translation, ctx)) <= 0)
+ return ret;
+
+ if ((state == PRE_CTRL_TO_PARAMS && ctx->action_type == SET)
+ || (state == POST_PARAMS_TO_CTRL && ctx->action_type == GET)) {
+ ret = -2;
+ /* Convert KDF type numbers to strings */
+ for (; kdf_type_map->kdf_type_str != NULL; kdf_type_map++)
+ if (ctx->p1 == kdf_type_map->kdf_type_num) {
+ ctx->p2 = (char *)kdf_type_map->kdf_type_str;
+ ret = 1;
+ break;
+ }
+ if (ret <= 0)
+ goto end;
+ ctx->p1 = strlen(ctx->p2);
+ }
+
+ if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
+ return ret;
+
+ if ((state == POST_CTRL_TO_PARAMS && ctx->action_type == GET)
+ || (state == PRE_PARAMS_TO_CTRL && ctx->action_type == SET)) {
+ ctx->p1 = ret = -1;
+
+ /* Convert KDF type strings to numbers */
+ for (; kdf_type_map->kdf_type_str != NULL; kdf_type_map++)
+ if (OPENSSL_strcasecmp(ctx->p2, kdf_type_map->kdf_type_str) == 0) {
+ ctx->p1 = kdf_type_map->kdf_type_num;
+ ret = 1;
+ break;
+ }
+ ctx->p2 = NULL;
+ } else if (state == PRE_PARAMS_TO_CTRL && ctx->action_type == GET) {
+ ctx->p1 = -2;
+ }
+ end:
+ return ret;
+}
+
+/* EVP_PKEY_CTRL_DH_KDF_TYPE */
+static int fix_dh_kdf_type(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ static const struct kdf_type_map_st kdf_type_map[] = {
+ { EVP_PKEY_DH_KDF_NONE, "" },
+ { EVP_PKEY_DH_KDF_X9_42, OSSL_KDF_NAME_X942KDF_ASN1 },
+ { 0, NULL }
+ };
+
+ return fix_kdf_type(state, translation, ctx, kdf_type_map);
+}
+
+/* EVP_PKEY_CTRL_EC_KDF_TYPE */
+static int fix_ec_kdf_type(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ static const struct kdf_type_map_st kdf_type_map[] = {
+ { EVP_PKEY_ECDH_KDF_NONE, "" },
+ { EVP_PKEY_ECDH_KDF_X9_63, OSSL_KDF_NAME_X963KDF },
+ { 0, NULL }
+ };
+
+ return fix_kdf_type(state, translation, ctx, kdf_type_map);
+}
+
+/* EVP_PKEY_CTRL_DH_KDF_OID, EVP_PKEY_CTRL_GET_DH_KDF_OID, ...??? */
+static int fix_oid(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ int ret;
+
+ if ((ret = default_check(state, translation, ctx)) <= 0)
+ return ret;
+
+ if ((state == PRE_CTRL_TO_PARAMS && ctx->action_type == SET)
+ || (state == POST_PARAMS_TO_CTRL && ctx->action_type == GET)) {
+ /*
+ * We're translating from ctrl to params and setting the OID, or
+ * we're translating from params to ctrl and getting the OID.
+ * Either way, |ctx->p2| points at an ASN1_OBJECT, and needs to have
+ * that replaced with the corresponding name.
+ * default_fixup_args() will then be able to convert that to the
+ * corresponding OSSL_PARAM.
+ */
+ OBJ_obj2txt(ctx->name_buf, sizeof(ctx->name_buf), ctx->p2, 0);
+ ctx->p2 = (char *)ctx->name_buf;
+ ctx->p1 = 0; /* let default_fixup_args() figure out the length */
+ }
+
+ if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
+ return ret;
+
+ if ((state == PRE_PARAMS_TO_CTRL && ctx->action_type == SET)
+ || (state == POST_CTRL_TO_PARAMS && ctx->action_type == GET)) {
+ /*
+ * We're translating from ctrl to params and setting the OID name,
+ * or we're translating from params to ctrl and getting the OID
+ * name. Either way, default_fixup_args() has placed the OID name
+ * in |ctx->p2|, all we need to do now is to replace that with the
+ * corresponding ASN1_OBJECT.
+ */
+ ctx->p2 = (ASN1_OBJECT *)OBJ_txt2obj(ctx->p2, 0);
+ }
+
+ return ret;
+}
+
+/* EVP_PKEY_CTRL_DH_NID */
+static int fix_dh_nid(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ int ret;
+
+ if ((ret = default_check(state, translation, ctx)) <= 0)
+ return ret;
+
+ /* This is only settable */
+ if (ctx->action_type != SET)
+ return 0;
+
+ if (state == PRE_CTRL_TO_PARAMS) {
+ if ((ctx->p2 = (char *)ossl_ffc_named_group_get_name
+ (ossl_ffc_uid_to_dh_named_group(ctx->p1))) == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
+ return 0;
+ }
+ ctx->p1 = 0;
+ }
+
+ return default_fixup_args(state, translation, ctx);
+}
+
+/* EVP_PKEY_CTRL_DH_RFC5114 */
+static int fix_dh_nid5114(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ int ret;
+
+ if ((ret = default_check(state, translation, ctx)) <= 0)
+ return ret;
+
+ /* This is only settable */
+ if (ctx->action_type != SET)
+ return 0;
+
+ switch (state) {
+ case PRE_CTRL_TO_PARAMS:
+ if ((ctx->p2 = (char *)ossl_ffc_named_group_get_name
+ (ossl_ffc_uid_to_dh_named_group(ctx->p1))) == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
+ return 0;
+ }
+
+ ctx->p1 = 0;
+ break;
+
+ case PRE_CTRL_STR_TO_PARAMS:
+ if (ctx->p2 == NULL)
+ return 0;
+ if ((ctx->p2 = (char *)ossl_ffc_named_group_get_name
+ (ossl_ffc_uid_to_dh_named_group(atoi(ctx->p2)))) == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
+ return 0;
+ }
+
+ ctx->p1 = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ return default_fixup_args(state, translation, ctx);
+}
+
+/* EVP_PKEY_CTRL_DH_PARAMGEN_TYPE */
+static int fix_dh_paramgen_type(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ int ret;
+
+ if ((ret = default_check(state, translation, ctx)) <= 0)
+ return ret;
+
+ /* This is only settable */
+ if (ctx->action_type != SET)
+ return 0;
+
+ if (state == PRE_CTRL_STR_TO_PARAMS) {
+ if ((ctx->p2 = (char *)ossl_dh_gen_type_id2name(atoi(ctx->p2)))
+ == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
+ return 0;
+ }
+ ctx->p1 = strlen(ctx->p2);
+ }
+
+ return default_fixup_args(state, translation, ctx);
+}
+
+/* EVP_PKEY_CTRL_EC_PARAM_ENC */
+static int fix_ec_param_enc(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ int ret;
+
+ if ((ret = default_check(state, translation, ctx)) <= 0)
+ return ret;
+
+ /* This is currently only settable */
+ if (ctx->action_type != SET)
+ return 0;
+
+ if (state == PRE_CTRL_TO_PARAMS) {
+ switch (ctx->p1) {
+ case OPENSSL_EC_EXPLICIT_CURVE:
+ ctx->p2 = OSSL_PKEY_EC_ENCODING_EXPLICIT;
+ break;
+ case OPENSSL_EC_NAMED_CURVE:
+ ctx->p2 = OSSL_PKEY_EC_ENCODING_GROUP;
+ break;
+ default:
+ ret = -2;
+ goto end;
+ }
+ ctx->p1 = 0;
+ }
+
+ if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
+ return ret;
+
+ if (state == PRE_PARAMS_TO_CTRL) {
+ if (strcmp(ctx->p2, OSSL_PKEY_EC_ENCODING_EXPLICIT) == 0)
+ ctx->p1 = OPENSSL_EC_EXPLICIT_CURVE;
+ else if (strcmp(ctx->p2, OSSL_PKEY_EC_ENCODING_GROUP) == 0)
+ ctx->p1 = OPENSSL_EC_NAMED_CURVE;
+ else
+ ctx->p1 = ret = -2;
+ ctx->p2 = NULL;
+ }
+
+ end:
+ if (ret == -2)
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return ret;
+}
+
+/* EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID */
+static int fix_ec_paramgen_curve_nid(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ int ret;
+
+ if ((ret = default_check(state, translation, ctx)) <= 0)
+ return ret;
+
+ /* This is currently only settable */
+ if (ctx->action_type != SET)
+ return 0;
+
+ if (state == PRE_CTRL_TO_PARAMS) {
+ ctx->p2 = (char *)OBJ_nid2sn(ctx->p1);
+ ctx->p1 = 0;
+ }
+
+ if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
+ return ret;
+
+ if (state == PRE_PARAMS_TO_CTRL) {
+ ctx->p1 = OBJ_sn2nid(ctx->p2);
+ ctx->p2 = NULL;
+ }
+
+ return ret;
+}
+
+/* EVP_PKEY_CTRL_EC_ECDH_COFACTOR */
+static int fix_ecdh_cofactor(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ /*
+ * The EVP_PKEY_CTRL_EC_ECDH_COFACTOR ctrl command is a bit special, in
+ * that it's used both for setting a value, and for getting it, all
+ * depending on the value if |ctx->p1|; if |ctx->p1| is -2, the backend is
+ * supposed to place the current cofactor mode in |ctx->p2|, and if not,
+ * |ctx->p1| is interpreted as the new cofactor mode.
+ */
+ int ret = 0;
+
+ if (state == PRE_CTRL_TO_PARAMS) {
+ /*
+ * The initial value for |ctx->action_type| must be zero.
+ * evp_pkey_ctrl_to_params() takes it from the translation item.
+ */
+ if (!ossl_assert(ctx->action_type == NONE))
+ return 0;
+
+ /* The action type depends on the value of ctx->p1 */
+ if (ctx->p1 == -2)
+ ctx->action_type = GET;
+ else
+ ctx->action_type = SET;
+ } else if (state == PRE_CTRL_STR_TO_PARAMS) {
+ ctx->action_type = SET;
+ } else if (state == PRE_PARAMS_TO_CTRL) {
+ /* The initial value for |ctx->action_type| must not be zero. */
+ if (!ossl_assert(ctx->action_type != NONE))
+ return 0;
+ }
+
+ if ((ret = default_check(state, translation, ctx)) <= 0)
+ return ret;
+
+ if (state == PRE_CTRL_TO_PARAMS && ctx->action_type == SET) {
+ if (ctx->p1 < -1 || ctx->p1 > 1) {
+ /* Uses the same return value of pkey_ec_ctrl() */
+ return -2;
+ }
+ }
+
+ if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
+ return ret;
+
+ if (state == POST_CTRL_TO_PARAMS && ctx->action_type == GET) {
+ if (ctx->p1 < 0 || ctx->p1 > 1) {
+ /*
+ * The provider should return either 0 or 1, any other value is a
+ * provider error.
+ */
+ ctx->p1 = ret = -1;
+ }
+ } else if (state == PRE_PARAMS_TO_CTRL && ctx->action_type == GET) {
+ ctx->p1 = -2;
+ }
+
+ return ret;
+}
+
+/* EVP_PKEY_CTRL_RSA_PADDING, EVP_PKEY_CTRL_GET_RSA_PADDING */
+static int fix_rsa_padding_mode(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ static const OSSL_ITEM str_value_map[] = {
+ { RSA_PKCS1_PADDING, "pkcs1" },
+ { RSA_NO_PADDING, "none" },
+ { RSA_PKCS1_OAEP_PADDING, "oaep" },
+ { RSA_PKCS1_OAEP_PADDING, "oeap" },
+ { RSA_X931_PADDING, "x931" },
+ { RSA_PKCS1_PSS_PADDING, "pss" },
+ /* Special case, will pass directly as an integer */
+ { RSA_PKCS1_WITH_TLS_PADDING, NULL }
+ };
+ int ret;
+
+ if ((ret = default_check(state, translation, ctx)) <= 0)
+ return ret;
+
+ if (state == PRE_CTRL_TO_PARAMS && ctx->action_type == GET) {
+ /*
+ * EVP_PKEY_CTRL_GET_RSA_PADDING returns the padding mode in the
+ * weirdest way for a ctrl. Instead of doing like all other ctrls
+ * that return a simple, i.e. just have that as a return value,
+ * this particular ctrl treats p2 as the address for the int to be
+ * returned. We must therefore remember |ctx->p2|, then make
+ * |ctx->p2| point at a buffer to be filled in with the name, and
+ * |ctx->p1| with its size. default_fixup_args() will take care
+ * of the rest for us, along with the POST_CTRL_TO_PARAMS && GET
+ * code section further down.
+ */
+ ctx->orig_p2 = ctx->p2;
+ ctx->p2 = ctx->name_buf;
+ ctx->p1 = sizeof(ctx->name_buf);
+ } else if (state == PRE_CTRL_TO_PARAMS && ctx->action_type == SET) {
+ /*
+ * Ideally, we should use utf8 strings for the diverse padding modes.
+ * We only came here because someone called EVP_PKEY_CTX_ctrl(),
+ * though, and since that can reasonably be seen as legacy code
+ * that uses the diverse RSA macros for the padding mode, and we
+ * know that at least our providers can handle the numeric modes,
+ * we take the cheap route for now.
+ *
+ * The other solution would be to match |ctx->p1| against entries
+ * in str_value_map and pass the corresponding string. However,
+ * since we don't have a string for RSA_PKCS1_WITH_TLS_PADDING,
+ * we have to do this same hack at least for that one.
+ *
+ * Since the "official" data type for the RSA padding mode is utf8
+ * string, we cannot count on default_fixup_args(). Instead, we
+ * build the OSSL_PARAM item ourselves and return immediately.
+ */
+ ctx->params[0] = OSSL_PARAM_construct_int(translation->param_key,
+ &ctx->p1);
+ return 1;
+ } else if (state == POST_PARAMS_TO_CTRL && ctx->action_type == GET) {
+ size_t i;
+
+ /*
+ * The EVP_PKEY_CTX_get_params() caller may have asked for a utf8
+ * string, or may have asked for an integer of some sort. If they
+ * ask for an integer, we respond directly. If not, we translate
+ * the response from the ctrl function into a string.
+ */
+ switch (ctx->params->data_type) {
+ case OSSL_PARAM_INTEGER:
+ return OSSL_PARAM_get_int(ctx->params, &ctx->p1);
+ case OSSL_PARAM_UNSIGNED_INTEGER:
+ return OSSL_PARAM_get_uint(ctx->params, (unsigned int *)&ctx->p1);
+ default:
+ break;
+ }
+
+ for (i = 0; i < OSSL_NELEM(str_value_map); i++) {
+ if (ctx->p1 == (int)str_value_map[i].id)
+ break;
+ }
+ if (i == OSSL_NELEM(str_value_map)) {
+ ERR_raise_data(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE,
+ "[action:%d, state:%d] padding number %d",
+ ctx->action_type, state, ctx->p1);
+ return -2;
+ }
+ /*
+ * If we don't have a string, we can't do anything. The caller
+ * should have asked for a number...
+ */
+ if (str_value_map[i].ptr == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return -2;
+ }
+ ctx->p2 = str_value_map[i].ptr;
+ ctx->p1 = strlen(ctx->p2);
+ }
+
+ if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
+ return ret;
+
+ if ((ctx->action_type == SET && state == PRE_PARAMS_TO_CTRL)
+ || (ctx->action_type == GET && state == POST_CTRL_TO_PARAMS)) {
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(str_value_map); i++) {
+ if (strcmp(ctx->p2, str_value_map[i].ptr) == 0)
+ break;
+ }
+
+ if (i == OSSL_NELEM(str_value_map)) {
+ ERR_raise_data(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE,
+ "[action:%d, state:%d] padding name %s",
+ ctx->action_type, state, ctx->p1);
+ ctx->p1 = ret = -2;
+ } else if (state == POST_CTRL_TO_PARAMS) {
+ /* EVP_PKEY_CTRL_GET_RSA_PADDING weirdness explained further up */
+ *(int *)ctx->orig_p2 = str_value_map[i].id;
+ } else {
+ ctx->p1 = str_value_map[i].id;
+ }
+ ctx->p2 = NULL;
+ }
+
+ return ret;
+}
+
+/* EVP_PKEY_CTRL_RSA_PSS_SALTLEN, EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN */
+static int fix_rsa_pss_saltlen(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ static const OSSL_ITEM str_value_map[] = {
+ { (unsigned int)RSA_PSS_SALTLEN_DIGEST, "digest" },
+ { (unsigned int)RSA_PSS_SALTLEN_MAX, "max" },
+ { (unsigned int)RSA_PSS_SALTLEN_AUTO, "auto" }
+ };
+ int ret;
+
+ if ((ret = default_check(state, translation, ctx)) <= 0)
+ return ret;
+
+ if (state == PRE_CTRL_TO_PARAMS && ctx->action_type == GET) {
+ /*
+ * EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN returns the saltlen by filling
+ * in the int pointed at by p2. This is potentially as weird as
+ * the way EVP_PKEY_CTRL_GET_RSA_PADDING works, except that saltlen
+ * might be a negative value, so it wouldn't work as a legitimate
+ * return value.
+ * In any case, we must therefore remember |ctx->p2|, then make
+ * |ctx->p2| point at a buffer to be filled in with the name, and
+ * |ctx->p1| with its size. default_fixup_args() will take care
+ * of the rest for us, along with the POST_CTRL_TO_PARAMS && GET
+ * code section further down.
+ */
+ ctx->orig_p2 = ctx->p2;
+ ctx->p2 = ctx->name_buf;
+ ctx->p1 = sizeof(ctx->name_buf);
+ } else if ((ctx->action_type == SET && state == PRE_CTRL_TO_PARAMS)
+ || (ctx->action_type == GET && state == POST_PARAMS_TO_CTRL)) {
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(str_value_map); i++) {
+ if (ctx->p1 == (int)str_value_map[i].id)
+ break;
+ }
+ if (i == OSSL_NELEM(str_value_map)) {
+ BIO_snprintf(ctx->name_buf, sizeof(ctx->name_buf), "%d", ctx->p1);
+ } else {
+ /* This won't truncate but it will quiet static analysers */
+ strncpy(ctx->name_buf, str_value_map[i].ptr, sizeof(ctx->name_buf) - 1);
+ ctx->name_buf[sizeof(ctx->name_buf) - 1] = '\0';
+ }
+ ctx->p2 = ctx->name_buf;
+ ctx->p1 = strlen(ctx->p2);
+ }
+
+ if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
+ return ret;
+
+ if ((ctx->action_type == SET && state == PRE_PARAMS_TO_CTRL)
+ || (ctx->action_type == GET && state == POST_CTRL_TO_PARAMS)) {
+ size_t i;
+ int val;
+
+ for (i = 0; i < OSSL_NELEM(str_value_map); i++) {
+ if (strcmp(ctx->p2, str_value_map[i].ptr) == 0)
+ break;
+ }
+
+ val = i == OSSL_NELEM(str_value_map) ? atoi(ctx->p2)
+ : (int)str_value_map[i].id;
+ if (state == POST_CTRL_TO_PARAMS) {
+ /*
+ * EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN weirdness explained further
+ * up
+ */
+ *(int *)ctx->orig_p2 = val;
+ } else {
+ ctx->p1 = val;
+ }
+ ctx->p2 = NULL;
+ }
+
+ return ret;
+}
+
+/* EVP_PKEY_CTRL_HKDF_MODE */
+static int fix_hkdf_mode(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ static const OSSL_ITEM str_value_map[] = {
+ { EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND, "EXTRACT_AND_EXPAND" },
+ { EVP_KDF_HKDF_MODE_EXTRACT_ONLY, "EXTRACT_ONLY" },
+ { EVP_KDF_HKDF_MODE_EXPAND_ONLY, "EXPAND_ONLY" }
+ };
+ int ret;
+
+ if ((ret = default_check(state, translation, ctx)) <= 0)
+ return ret;
+
+ if ((ctx->action_type == SET && state == PRE_CTRL_TO_PARAMS)
+ || (ctx->action_type == GET && state == POST_PARAMS_TO_CTRL)) {
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(str_value_map); i++) {
+ if (ctx->p1 == (int)str_value_map[i].id)
+ break;
+ }
+ if (i == OSSL_NELEM(str_value_map))
+ return 0;
+ ctx->p2 = str_value_map[i].ptr;
+ ctx->p1 = strlen(ctx->p2);
+ }
+
+ if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
+ return ret;
+
+ if ((ctx->action_type == SET && state == PRE_PARAMS_TO_CTRL)
+ || (ctx->action_type == GET && state == POST_CTRL_TO_PARAMS)) {
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(str_value_map); i++) {
+ if (strcmp(ctx->p2, str_value_map[i].ptr) == 0)
+ break;
+ }
+ if (i == OSSL_NELEM(str_value_map))
+ return 0;
+ if (state == POST_CTRL_TO_PARAMS)
+ ret = str_value_map[i].id;
+ else
+ ctx->p1 = str_value_map[i].id;
+ ctx->p2 = NULL;
+ }
+
+ return 1;
+}
+
+/*-
+ * Payload getters
+ * ===============
+ *
+ * These all get the data they want, then call default_fixup_args() as
+ * a post-ctrl GET fixup. They all get NULL ctx, ctrl_cmd, ctrl_str,
+ * p1, sz
+ */
+
+/* Pilfering DH, DSA and EC_KEY */
+static int get_payload_group_name(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ EVP_PKEY *pkey = ctx->p2;
+
+ ctx->p2 = NULL;
+ switch (EVP_PKEY_get_base_id(pkey)) {
+#ifndef OPENSSL_NO_DH
+ case EVP_PKEY_DH:
+ {
+ const DH *dh = EVP_PKEY_get0_DH(pkey);
+ int uid = DH_get_nid(dh);
+
+ if (uid != NID_undef) {
+ const DH_NAMED_GROUP *dh_group =
+ ossl_ffc_uid_to_dh_named_group(uid);
+
+ ctx->p2 = (char *)ossl_ffc_named_group_get_name(dh_group);
+ }
+ }
+ break;
+#endif
+#ifndef OPENSSL_NO_EC
+ case EVP_PKEY_EC:
+ {
+ const EC_GROUP *grp =
+ EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey));
+ int nid = NID_undef;
+
+ if (grp != NULL)
+ nid = EC_GROUP_get_curve_name(grp);
+ if (nid != NID_undef)
+ ctx->p2 = (char *)OSSL_EC_curve_nid2name(nid);
+ }
+ break;
+#endif
+ default:
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE);
+ return 0;
+ }
+
+ /*
+ * Quietly ignoring unknown groups matches the behaviour on the provider
+ * side.
+ */
+ if (ctx->p2 == NULL)
+ return 1;
+
+ ctx->p1 = strlen(ctx->p2);
+ return default_fixup_args(state, translation, ctx);
+}
+
+static int get_payload_private_key(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ EVP_PKEY *pkey = ctx->p2;
+
+ ctx->p2 = NULL;
+ if (ctx->params->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
+ return 0;
+
+ switch (EVP_PKEY_get_base_id(pkey)) {
+#ifndef OPENSSL_NO_DH
+ case EVP_PKEY_DH:
+ {
+ const DH *dh = EVP_PKEY_get0_DH(pkey);
+
+ ctx->p2 = (BIGNUM *)DH_get0_priv_key(dh);
+ }
+ break;
+#endif
+#ifndef OPENSSL_NO_EC
+ case EVP_PKEY_EC:
+ {
+ const EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
+
+ ctx->p2 = (BIGNUM *)EC_KEY_get0_private_key(ec);
+ }
+ break;
+#endif
+ default:
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE);
+ return 0;
+ }
+
+ return default_fixup_args(state, translation, ctx);
+}
+
+static int get_payload_public_key(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ EVP_PKEY *pkey = ctx->p2;
+ unsigned char *buf = NULL;
+ int ret;
+
+ ctx->p2 = NULL;
+ switch (EVP_PKEY_get_base_id(pkey)) {
+#ifndef OPENSSL_NO_DH
+ case EVP_PKEY_DHX:
+ case EVP_PKEY_DH:
+ switch (ctx->params->data_type) {
+ case OSSL_PARAM_OCTET_STRING:
+ ctx->sz = ossl_dh_key2buf(EVP_PKEY_get0_DH(pkey), &buf, 0, 1);
+ ctx->p2 = buf;
+ break;
+ case OSSL_PARAM_UNSIGNED_INTEGER:
+ ctx->p2 = (void *)DH_get0_pub_key(EVP_PKEY_get0_DH(pkey));
+ break;
+ default:
+ return 0;
+ }
+ break;
+#endif
+#ifndef OPENSSL_NO_DSA
+ case EVP_PKEY_DSA:
+ if (ctx->params->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
+ ctx->p2 = (void *)DSA_get0_pub_key(EVP_PKEY_get0_DSA(pkey));
+ break;
+ }
+ return 0;
+#endif
+#ifndef OPENSSL_NO_EC
+ case EVP_PKEY_EC:
+ if (ctx->params->data_type == OSSL_PARAM_OCTET_STRING) {
+ const EC_KEY *eckey = EVP_PKEY_get0_EC_KEY(pkey);
+ BN_CTX *bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eckey));
+ const EC_GROUP *ecg = EC_KEY_get0_group(eckey);
+ const EC_POINT *point = EC_KEY_get0_public_key(eckey);
+
+ if (bnctx == NULL)
+ return 0;
+ ctx->sz = EC_POINT_point2buf(ecg, point,
+ POINT_CONVERSION_COMPRESSED,
+ &buf, bnctx);
+ ctx->p2 = buf;
+ BN_CTX_free(bnctx);
+ break;
+ }
+ return 0;
+#endif
+ default:
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE);
+ return 0;
+ }
+
+ ret = default_fixup_args(state, translation, ctx);
+ OPENSSL_free(buf);
+ return ret;
+}
+
+static int get_payload_bn(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx, const BIGNUM *bn)
+{
+ if (bn == NULL)
+ return 0;
+ if (ctx->params->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
+ return 0;
+ ctx->p2 = (BIGNUM *)bn;
+
+ return default_fixup_args(state, translation, ctx);
+}
+
+static int get_dh_dsa_payload_p(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ const BIGNUM *bn = NULL;
+ EVP_PKEY *pkey = ctx->p2;
+
+ switch (EVP_PKEY_get_base_id(pkey)) {
+#ifndef OPENSSL_NO_DH
+ case EVP_PKEY_DH:
+ bn = DH_get0_p(EVP_PKEY_get0_DH(pkey));
+ break;
+#endif
+#ifndef OPENSSL_NO_DSA
+ case EVP_PKEY_DSA:
+ bn = DSA_get0_p(EVP_PKEY_get0_DSA(pkey));
+ break;
+#endif
+ default:
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE);
+ }
+
+ return get_payload_bn(state, translation, ctx, bn);
+}
+
+static int get_dh_dsa_payload_q(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ const BIGNUM *bn = NULL;
+
+ switch (EVP_PKEY_get_base_id(ctx->p2)) {
+#ifndef OPENSSL_NO_DH
+ case EVP_PKEY_DH:
+ bn = DH_get0_q(EVP_PKEY_get0_DH(ctx->p2));
+ break;
+#endif
+#ifndef OPENSSL_NO_DSA
+ case EVP_PKEY_DSA:
+ bn = DSA_get0_q(EVP_PKEY_get0_DSA(ctx->p2));
+ break;
+#endif
+ }
+
+ return get_payload_bn(state, translation, ctx, bn);
+}
+
+static int get_dh_dsa_payload_g(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ const BIGNUM *bn = NULL;
+
+ switch (EVP_PKEY_get_base_id(ctx->p2)) {
+#ifndef OPENSSL_NO_DH
+ case EVP_PKEY_DH:
+ bn = DH_get0_g(EVP_PKEY_get0_DH(ctx->p2));
+ break;
+#endif
+#ifndef OPENSSL_NO_DSA
+ case EVP_PKEY_DSA:
+ bn = DSA_get0_g(EVP_PKEY_get0_DSA(ctx->p2));
+ break;
+#endif
+ }
+
+ return get_payload_bn(state, translation, ctx, bn);
+}
+
+static int get_payload_int(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx,
+ const int val)
+{
+ if (ctx->params->data_type != OSSL_PARAM_INTEGER)
+ return 0;
+ ctx->p1 = val;
+ ctx->p2 = NULL;
+
+ return default_fixup_args(state, translation, ctx);
+}
+
+static int get_ec_decoded_from_explicit_params(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ int val = 0;
+ EVP_PKEY *pkey = ctx->p2;
+
+ switch (EVP_PKEY_base_id(pkey)) {
+#ifndef OPENSSL_NO_EC
+ case EVP_PKEY_EC:
+ val = EC_KEY_decoded_from_explicit_params(EVP_PKEY_get0_EC_KEY(pkey));
+ if (val < 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY);
+ return 0;
+ }
+ break;
+#endif
+ default:
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE);
+ return 0;
+ }
+
+ return get_payload_int(state, translation, ctx, val);
+}
+
+static int get_rsa_payload_n(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ const BIGNUM *bn = NULL;
+
+ if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA)
+ return 0;
+ bn = RSA_get0_n(EVP_PKEY_get0_RSA(ctx->p2));
+
+ return get_payload_bn(state, translation, ctx, bn);
+}
+
+static int get_rsa_payload_e(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ const BIGNUM *bn = NULL;
+
+ if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA)
+ return 0;
+ bn = RSA_get0_e(EVP_PKEY_get0_RSA(ctx->p2));
+
+ return get_payload_bn(state, translation, ctx, bn);
+}
+
+static int get_rsa_payload_d(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ const BIGNUM *bn = NULL;
+
+ if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA)
+ return 0;
+ bn = RSA_get0_d(EVP_PKEY_get0_RSA(ctx->p2));
+
+ return get_payload_bn(state, translation, ctx, bn);
+}
+
+static int get_rsa_payload_factor(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx,
+ size_t factornum)
+{
+ const RSA *r = EVP_PKEY_get0_RSA(ctx->p2);
+ const BIGNUM *bn = NULL;
+
+ switch (factornum) {
+ case 0:
+ bn = RSA_get0_p(r);
+ break;
+ case 1:
+ bn = RSA_get0_q(r);
+ break;
+ default:
+ {
+ size_t pnum = RSA_get_multi_prime_extra_count(r);
+ const BIGNUM *factors[10];
+
+ if (factornum - 2 < pnum
+ && RSA_get0_multi_prime_factors(r, factors))
+ bn = factors[factornum - 2];
+ }
+ break;
+ }
+
+ return get_payload_bn(state, translation, ctx, bn);
+}
+
+static int get_rsa_payload_exponent(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx,
+ size_t exponentnum)
+{
+ const RSA *r = EVP_PKEY_get0_RSA(ctx->p2);
+ const BIGNUM *bn = NULL;
+
+ switch (exponentnum) {
+ case 0:
+ bn = RSA_get0_dmp1(r);
+ break;
+ case 1:
+ bn = RSA_get0_dmq1(r);
+ break;
+ default:
+ {
+ size_t pnum = RSA_get_multi_prime_extra_count(r);
+ const BIGNUM *exps[10], *coeffs[10];
+
+ if (exponentnum - 2 < pnum
+ && RSA_get0_multi_prime_crt_params(r, exps, coeffs))
+ bn = exps[exponentnum - 2];
+ }
+ break;
+ }
+
+ return get_payload_bn(state, translation, ctx, bn);
+}
+
+static int get_rsa_payload_coefficient(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx,
+ size_t coefficientnum)
+{
+ const RSA *r = EVP_PKEY_get0_RSA(ctx->p2);
+ const BIGNUM *bn = NULL;
+
+ switch (coefficientnum) {
+ case 0:
+ bn = RSA_get0_iqmp(r);
+ break;
+ default:
+ {
+ size_t pnum = RSA_get_multi_prime_extra_count(r);
+ const BIGNUM *exps[10], *coeffs[10];
+
+ if (coefficientnum - 1 < pnum
+ && RSA_get0_multi_prime_crt_params(r, exps, coeffs))
+ bn = coeffs[coefficientnum - 1];
+ }
+ break;
+ }
+
+ return get_payload_bn(state, translation, ctx, bn);
+}
+
+#define IMPL_GET_RSA_PAYLOAD_FACTOR(n) \
+ static int \
+ get_rsa_payload_f##n(enum state state, \
+ const struct translation_st *translation, \
+ struct translation_ctx_st *ctx) \
+ { \
+ if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA) \
+ return 0; \
+ return get_rsa_payload_factor(state, translation, ctx, n - 1); \
+ }
+
+#define IMPL_GET_RSA_PAYLOAD_EXPONENT(n) \
+ static int \
+ get_rsa_payload_e##n(enum state state, \
+ const struct translation_st *translation, \
+ struct translation_ctx_st *ctx) \
+ { \
+ if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA) \
+ return 0; \
+ return get_rsa_payload_exponent(state, translation, ctx, \
+ n - 1); \
+ }
+
+#define IMPL_GET_RSA_PAYLOAD_COEFFICIENT(n) \
+ static int \
+ get_rsa_payload_c##n(enum state state, \
+ const struct translation_st *translation, \
+ struct translation_ctx_st *ctx) \
+ { \
+ if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA) \
+ return 0; \
+ return get_rsa_payload_coefficient(state, translation, ctx, \
+ n - 1); \
+ }
+
+IMPL_GET_RSA_PAYLOAD_FACTOR(1)
+IMPL_GET_RSA_PAYLOAD_FACTOR(2)
+IMPL_GET_RSA_PAYLOAD_FACTOR(3)
+IMPL_GET_RSA_PAYLOAD_FACTOR(4)
+IMPL_GET_RSA_PAYLOAD_FACTOR(5)
+IMPL_GET_RSA_PAYLOAD_FACTOR(6)
+IMPL_GET_RSA_PAYLOAD_FACTOR(7)
+IMPL_GET_RSA_PAYLOAD_FACTOR(8)
+IMPL_GET_RSA_PAYLOAD_FACTOR(9)
+IMPL_GET_RSA_PAYLOAD_FACTOR(10)
+IMPL_GET_RSA_PAYLOAD_EXPONENT(1)
+IMPL_GET_RSA_PAYLOAD_EXPONENT(2)
+IMPL_GET_RSA_PAYLOAD_EXPONENT(3)
+IMPL_GET_RSA_PAYLOAD_EXPONENT(4)
+IMPL_GET_RSA_PAYLOAD_EXPONENT(5)
+IMPL_GET_RSA_PAYLOAD_EXPONENT(6)
+IMPL_GET_RSA_PAYLOAD_EXPONENT(7)
+IMPL_GET_RSA_PAYLOAD_EXPONENT(8)
+IMPL_GET_RSA_PAYLOAD_EXPONENT(9)
+IMPL_GET_RSA_PAYLOAD_EXPONENT(10)
+IMPL_GET_RSA_PAYLOAD_COEFFICIENT(1)
+IMPL_GET_RSA_PAYLOAD_COEFFICIENT(2)
+IMPL_GET_RSA_PAYLOAD_COEFFICIENT(3)
+IMPL_GET_RSA_PAYLOAD_COEFFICIENT(4)
+IMPL_GET_RSA_PAYLOAD_COEFFICIENT(5)
+IMPL_GET_RSA_PAYLOAD_COEFFICIENT(6)
+IMPL_GET_RSA_PAYLOAD_COEFFICIENT(7)
+IMPL_GET_RSA_PAYLOAD_COEFFICIENT(8)
+IMPL_GET_RSA_PAYLOAD_COEFFICIENT(9)
+
+static int fix_group_ecx(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ const char *value = NULL;
+
+ switch (state) {
+ case PRE_PARAMS_TO_CTRL:
+ if (!EVP_PKEY_CTX_IS_GEN_OP(ctx->pctx))
+ return 0;
+ ctx->action_type = NONE;
+ return 1;
+ case POST_PARAMS_TO_CTRL:
+ if (OSSL_PARAM_get_utf8_string_ptr(ctx->params, &value) == 0 ||
+ OPENSSL_strcasecmp(ctx->pctx->keytype, value) != 0) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
+ ctx->p1 = 0;
+ return 0;
+ }
+ ctx->p1 = 1;
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/*-
+ * The translation table itself
+ * ============================
+ */
+
+static const struct translation_st evp_pkey_ctx_translations[] = {
+ /*
+ * DistID: we pass it to the backend as an octet string,
+ * but get it back as a pointer to an octet string.
+ *
+ * Note that the EVP_PKEY_CTRL_GET1_ID_LEN is purely for legacy purposes
+ * that has no separate counterpart in OSSL_PARAM terms, since we get
+ * the length of the DistID automatically when getting the DistID itself.
+ */
+ { SET, -1, -1, EVP_PKEY_OP_TYPE_SIG,
+ EVP_PKEY_CTRL_SET1_ID, "distid", "hexdistid",
+ OSSL_PKEY_PARAM_DIST_ID, OSSL_PARAM_OCTET_STRING, NULL },
+ { GET, -1, -1, -1,
+ EVP_PKEY_CTRL_GET1_ID, "distid", "hexdistid",
+ OSSL_PKEY_PARAM_DIST_ID, OSSL_PARAM_OCTET_PTR, NULL },
+ { GET, -1, -1, -1,
+ EVP_PKEY_CTRL_GET1_ID_LEN, NULL, NULL,
+ OSSL_PKEY_PARAM_DIST_ID, OSSL_PARAM_OCTET_PTR, fix_distid_len },
+
+ /*-
+ * DH & DHX
+ * ========
+ */
+
+ /*
+ * EVP_PKEY_CTRL_DH_KDF_TYPE is used both for setting and getting. The
+ * fixup function has to handle this...
+ */
+ { NONE, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_DH_KDF_TYPE, NULL, NULL,
+ OSSL_EXCHANGE_PARAM_KDF_TYPE, OSSL_PARAM_UTF8_STRING,
+ fix_dh_kdf_type },
+ { SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_DH_KDF_MD, NULL, NULL,
+ OSSL_EXCHANGE_PARAM_KDF_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
+ { GET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_GET_DH_KDF_MD, NULL, NULL,
+ OSSL_EXCHANGE_PARAM_KDF_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
+ { SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_DH_KDF_OUTLEN, NULL, NULL,
+ OSSL_EXCHANGE_PARAM_KDF_OUTLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+ { GET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN, NULL, NULL,
+ OSSL_EXCHANGE_PARAM_KDF_OUTLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+ { SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_DH_KDF_UKM, NULL, NULL,
+ OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_STRING, NULL },
+ { GET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_GET_DH_KDF_UKM, NULL, NULL,
+ OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR, NULL },
+ { SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_DH_KDF_OID, NULL, NULL,
+ OSSL_KDF_PARAM_CEK_ALG, OSSL_PARAM_UTF8_STRING, fix_oid },
+ { GET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_GET_DH_KDF_OID, NULL, NULL,
+ OSSL_KDF_PARAM_CEK_ALG, OSSL_PARAM_UTF8_STRING, fix_oid },
+
+ /* DHX Keygen Parameters that are shared with DH */
+ { SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, "dh_paramgen_type", NULL,
+ OSSL_PKEY_PARAM_FFC_TYPE, OSSL_PARAM_UTF8_STRING, fix_dh_paramgen_type },
+ { SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN, "dh_paramgen_prime_len", NULL,
+ OSSL_PKEY_PARAM_FFC_PBITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+ { SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_DH_NID, "dh_param", NULL,
+ OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, NULL },
+ { SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_DH_RFC5114, "dh_rfc5114", NULL,
+ OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, fix_dh_nid5114 },
+
+ /* DH Keygen Parameters that are shared with DHX */
+ { SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, "dh_paramgen_type", NULL,
+ OSSL_PKEY_PARAM_FFC_TYPE, OSSL_PARAM_UTF8_STRING, fix_dh_paramgen_type },
+ { SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN, "dh_paramgen_prime_len", NULL,
+ OSSL_PKEY_PARAM_FFC_PBITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+ { SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_DH_NID, "dh_param", NULL,
+ OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, fix_dh_nid },
+ { SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_DH_RFC5114, "dh_rfc5114", NULL,
+ OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, fix_dh_nid5114 },
+
+ /* DH specific Keygen Parameters */
+ { SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR, "dh_paramgen_generator", NULL,
+ OSSL_PKEY_PARAM_DH_GENERATOR, OSSL_PARAM_INTEGER, NULL },
+
+ /* DHX specific Keygen Parameters */
+ { SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN, "dh_paramgen_subprime_len", NULL,
+ OSSL_PKEY_PARAM_FFC_QBITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+
+ { SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_DH_PAD, "dh_pad", NULL,
+ OSSL_EXCHANGE_PARAM_PAD, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+
+ /*-
+ * DSA
+ * ===
+ */
+ { SET, EVP_PKEY_DSA, 0, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DSA_PARAMGEN_BITS, "dsa_paramgen_bits", NULL,
+ OSSL_PKEY_PARAM_FFC_PBITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+ { SET, EVP_PKEY_DSA, 0, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, "dsa_paramgen_q_bits", NULL,
+ OSSL_PKEY_PARAM_FFC_QBITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+ { SET, EVP_PKEY_DSA, 0, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DSA_PARAMGEN_MD, "dsa_paramgen_md", NULL,
+ OSSL_PKEY_PARAM_FFC_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
+
+ /*-
+ * EC
+ * ==
+ */
+ { SET, EVP_PKEY_EC, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_EC_PARAM_ENC, "ec_param_enc", NULL,
+ OSSL_PKEY_PARAM_EC_ENCODING, OSSL_PARAM_UTF8_STRING, fix_ec_param_enc },
+ { SET, EVP_PKEY_EC, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, "ec_paramgen_curve", NULL,
+ OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING,
+ fix_ec_paramgen_curve_nid },
+ /*
+ * EVP_PKEY_CTRL_EC_ECDH_COFACTOR and EVP_PKEY_CTRL_EC_KDF_TYPE are used
+ * both for setting and getting. The fixup function has to handle this...
+ */
+ { NONE, EVP_PKEY_EC, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_EC_ECDH_COFACTOR, "ecdh_cofactor_mode", NULL,
+ OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, OSSL_PARAM_INTEGER,
+ fix_ecdh_cofactor },
+ { NONE, EVP_PKEY_EC, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_EC_KDF_TYPE, NULL, NULL,
+ OSSL_EXCHANGE_PARAM_KDF_TYPE, OSSL_PARAM_UTF8_STRING, fix_ec_kdf_type },
+ { SET, EVP_PKEY_EC, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_EC_KDF_MD, "ecdh_kdf_md", NULL,
+ OSSL_EXCHANGE_PARAM_KDF_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
+ { GET, EVP_PKEY_EC, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_GET_EC_KDF_MD, NULL, NULL,
+ OSSL_EXCHANGE_PARAM_KDF_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
+ { SET, EVP_PKEY_EC, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_EC_KDF_OUTLEN, NULL, NULL,
+ OSSL_EXCHANGE_PARAM_KDF_OUTLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+ { GET, EVP_PKEY_EC, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, NULL, NULL,
+ OSSL_EXCHANGE_PARAM_KDF_OUTLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+ { SET, EVP_PKEY_EC, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_EC_KDF_UKM, NULL, NULL,
+ OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_STRING, NULL },
+ { GET, EVP_PKEY_EC, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_GET_EC_KDF_UKM, NULL, NULL,
+ OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR, NULL },
+
+ /*-
+ * RSA
+ * ===
+ */
+
+ /*
+ * RSA padding modes are numeric with ctrls, strings with ctrl_strs,
+ * and can be both with OSSL_PARAM. We standardise on strings here,
+ * fix_rsa_padding_mode() does the work when the caller has a different
+ * idea.
+ */
+ { SET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS,
+ EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_TYPE_SIG,
+ EVP_PKEY_CTRL_RSA_PADDING, "rsa_padding_mode", NULL,
+ OSSL_PKEY_PARAM_PAD_MODE, OSSL_PARAM_UTF8_STRING, fix_rsa_padding_mode },
+ { GET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS,
+ EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_TYPE_SIG,
+ EVP_PKEY_CTRL_GET_RSA_PADDING, NULL, NULL,
+ OSSL_PKEY_PARAM_PAD_MODE, OSSL_PARAM_UTF8_STRING, fix_rsa_padding_mode },
+
+ { SET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS,
+ EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_TYPE_SIG,
+ EVP_PKEY_CTRL_RSA_MGF1_MD, "rsa_mgf1_md", NULL,
+ OSSL_PKEY_PARAM_MGF1_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
+ { GET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS,
+ EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_TYPE_SIG,
+ EVP_PKEY_CTRL_GET_RSA_MGF1_MD, NULL, NULL,
+ OSSL_PKEY_PARAM_MGF1_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
+
+ /*
+ * RSA-PSS saltlen is essentially numeric, but certain values can be
+ * expressed as keywords (strings) with ctrl_str. The corresponding
+ * OSSL_PARAM allows both forms.
+ * fix_rsa_pss_saltlen() takes care of the distinction.
+ */
+ { SET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_TYPE_SIG,
+ EVP_PKEY_CTRL_RSA_PSS_SALTLEN, "rsa_pss_saltlen", NULL,
+ OSSL_PKEY_PARAM_RSA_PSS_SALTLEN, OSSL_PARAM_UTF8_STRING,
+ fix_rsa_pss_saltlen },
+ { GET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_TYPE_SIG,
+ EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_PSS_SALTLEN, OSSL_PARAM_UTF8_STRING,
+ fix_rsa_pss_saltlen },
+
+ { SET, EVP_PKEY_RSA, 0, EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_RSA_OAEP_MD, "rsa_oaep_md", NULL,
+ OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
+ { GET, EVP_PKEY_RSA, 0, EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_GET_RSA_OAEP_MD, NULL, NULL,
+ OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
+ /*
+ * The "rsa_oaep_label" ctrl_str expects the value to always be hex.
+ * This is accomodated by default_fixup_args() above, which mimics that
+ * expectation for any translation item where |ctrl_str| is NULL and
+ * |ctrl_hexstr| is non-NULL.
+ */
+ { SET, EVP_PKEY_RSA, 0, EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_RSA_OAEP_LABEL, NULL, "rsa_oaep_label",
+ OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, OSSL_PARAM_OCTET_STRING, NULL },
+ { GET, EVP_PKEY_RSA, 0, EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, NULL, NULL,
+ OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, OSSL_PARAM_OCTET_STRING, NULL },
+
+ { SET, EVP_PKEY_RSA_PSS, 0, EVP_PKEY_OP_TYPE_GEN,
+ EVP_PKEY_CTRL_MD, "rsa_pss_keygen_md", NULL,
+ OSSL_ALG_PARAM_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
+ { SET, EVP_PKEY_RSA_PSS, 0, EVP_PKEY_OP_TYPE_GEN,
+ EVP_PKEY_CTRL_RSA_MGF1_MD, "rsa_pss_keygen_mgf1_md", NULL,
+ OSSL_PKEY_PARAM_MGF1_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
+ { SET, EVP_PKEY_RSA_PSS, 0, EVP_PKEY_OP_TYPE_GEN,
+ EVP_PKEY_CTRL_RSA_PSS_SALTLEN, "rsa_pss_keygen_saltlen", NULL,
+ OSSL_SIGNATURE_PARAM_PSS_SALTLEN, OSSL_PARAM_INTEGER, NULL },
+ { SET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_RSA_KEYGEN_BITS, "rsa_keygen_bits", NULL,
+ OSSL_PKEY_PARAM_RSA_BITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+ { SET, EVP_PKEY_RSA, 0, EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, "rsa_keygen_pubexp", NULL,
+ OSSL_PKEY_PARAM_RSA_E, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+ { SET, EVP_PKEY_RSA, 0, EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES, "rsa_keygen_primes", NULL,
+ OSSL_PKEY_PARAM_RSA_PRIMES, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+
+ /*-
+ * SipHash
+ * ======
+ */
+ { SET, -1, -1, EVP_PKEY_OP_TYPE_SIG,
+ EVP_PKEY_CTRL_SET_DIGEST_SIZE, "digestsize", NULL,
+ OSSL_MAC_PARAM_SIZE, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+
+ /*-
+ * TLS1-PRF
+ * ========
+ */
+ { SET, -1, -1, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_TLS_MD, "md", NULL,
+ OSSL_KDF_PARAM_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
+ { SET, -1, -1, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_TLS_SECRET, "secret", "hexsecret",
+ OSSL_KDF_PARAM_SECRET, OSSL_PARAM_OCTET_STRING, NULL },
+ { SET, -1, -1, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_TLS_SEED, "seed", "hexseed",
+ OSSL_KDF_PARAM_SEED, OSSL_PARAM_OCTET_STRING, NULL },
+
+ /*-
+ * HKDF
+ * ====
+ */
+ { SET, -1, -1, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_HKDF_MD, "md", NULL,
+ OSSL_KDF_PARAM_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
+ { SET, -1, -1, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_HKDF_SALT, "salt", "hexsalt",
+ OSSL_KDF_PARAM_SALT, OSSL_PARAM_OCTET_STRING, NULL },
+ { SET, -1, -1, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_HKDF_KEY, "key", "hexkey",
+ OSSL_KDF_PARAM_KEY, OSSL_PARAM_OCTET_STRING, NULL },
+ { SET, -1, -1, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_HKDF_INFO, "info", "hexinfo",
+ OSSL_KDF_PARAM_INFO, OSSL_PARAM_OCTET_STRING, NULL },
+ { SET, -1, -1, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_HKDF_MODE, "mode", NULL,
+ OSSL_KDF_PARAM_MODE, OSSL_PARAM_INTEGER, fix_hkdf_mode },
+
+ /*-
+ * Scrypt
+ * ======
+ */
+ { SET, -1, -1, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_PASS, "pass", "hexpass",
+ OSSL_KDF_PARAM_PASSWORD, OSSL_PARAM_OCTET_STRING, NULL },
+ { SET, -1, -1, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_SCRYPT_SALT, "salt", "hexsalt",
+ OSSL_KDF_PARAM_SALT, OSSL_PARAM_OCTET_STRING, NULL },
+ { SET, -1, -1, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_SCRYPT_N, "N", NULL,
+ OSSL_KDF_PARAM_SCRYPT_N, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+ { SET, -1, -1, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_SCRYPT_R, "r", NULL,
+ OSSL_KDF_PARAM_SCRYPT_R, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+ { SET, -1, -1, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_SCRYPT_P, "p", NULL,
+ OSSL_KDF_PARAM_SCRYPT_P, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+ { SET, -1, -1, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES, "maxmem_bytes", NULL,
+ OSSL_KDF_PARAM_SCRYPT_MAXMEM, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+
+ { SET, -1, -1, EVP_PKEY_OP_KEYGEN | EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_CIPHER, NULL, NULL,
+ OSSL_PKEY_PARAM_CIPHER, OSSL_PARAM_UTF8_STRING, fix_cipher },
+ { SET, -1, -1, EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_SET_MAC_KEY, "key", "hexkey",
+ OSSL_PKEY_PARAM_PRIV_KEY, OSSL_PARAM_OCTET_STRING, NULL },
+
+ { SET, -1, -1, EVP_PKEY_OP_TYPE_SIG,
+ EVP_PKEY_CTRL_MD, NULL, NULL,
+ OSSL_SIGNATURE_PARAM_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
+ { GET, -1, -1, EVP_PKEY_OP_TYPE_SIG,
+ EVP_PKEY_CTRL_GET_MD, NULL, NULL,
+ OSSL_SIGNATURE_PARAM_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
+
+ /*-
+ * ECX
+ * ===
+ */
+ { SET, EVP_PKEY_X25519, EVP_PKEY_X25519, EVP_PKEY_OP_KEYGEN, -1, NULL, NULL,
+ OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, fix_group_ecx },
+ { SET, EVP_PKEY_X448, EVP_PKEY_X448, EVP_PKEY_OP_KEYGEN, -1, NULL, NULL,
+ OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, fix_group_ecx },
+};
+
+static const struct translation_st evp_pkey_translations[] = {
+ /*
+ * The following contain no ctrls, they are exclusively here to extract
+ * key payloads from legacy keys, using OSSL_PARAMs, and rely entirely
+ * on |fixup_args| to pass the actual data. The |fixup_args| should
+ * expect to get the EVP_PKEY pointer through |ctx->p2|.
+ */
+
+ /* DH, DSA & EC */
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING,
+ get_payload_group_name },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_PRIV_KEY, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_payload_private_key },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_PUB_KEY,
+ 0 /* no data type, let get_payload_public_key() handle that */,
+ get_payload_public_key },
+
+ /* DH and DSA */
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_FFC_P, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_dh_dsa_payload_p },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_FFC_G, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_dh_dsa_payload_g },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_FFC_Q, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_dh_dsa_payload_q },
+
+ /* RSA */
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_N, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_n },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_E, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_e },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_D, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_d },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_FACTOR1, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_f1 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_FACTOR2, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_f2 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_FACTOR3, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_f3 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_FACTOR4, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_f4 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_FACTOR5, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_f5 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_FACTOR6, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_f6 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_FACTOR7, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_f7 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_FACTOR8, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_f8 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_FACTOR9, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_f9 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_FACTOR10, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_f10 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_EXPONENT1, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_e1 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_EXPONENT2, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_e2 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_EXPONENT3, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_e3 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_EXPONENT4, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_e4 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_EXPONENT5, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_e5 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_EXPONENT6, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_e6 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_EXPONENT7, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_e7 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_EXPONENT8, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_e8 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_EXPONENT9, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_e9 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_EXPONENT10, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_e10 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT1, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_c1 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT2, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_c2 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT3, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_c3 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT4, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_c4 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT5, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_c5 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT6, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_c6 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT7, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_c7 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT8, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_c8 },
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT9, OSSL_PARAM_UNSIGNED_INTEGER,
+ get_rsa_payload_c9 },
+
+ /* EC */
+ { GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, OSSL_PARAM_INTEGER,
+ get_ec_decoded_from_explicit_params },
+};
+
+static const struct translation_st *
+lookup_translation(struct translation_st *tmpl,
+ const struct translation_st *translations,
+ size_t translations_num)
+{
+ size_t i;
+
+ for (i = 0; i < translations_num; i++) {
+ const struct translation_st *item = &translations[i];
+
+ /*
+ * Sanity check the translation table item.
+ *
+ * 1. Either both keytypes are -1, or neither of them are.
+ * 2. TBA...
+ */
+ if (!ossl_assert((item->keytype1 == -1) == (item->keytype2 == -1)))
+ continue;
+
+
+ /*
+ * Base search criteria: check that the optype and keytypes match,
+ * if relevant. All callers must synthesise these bits somehow.
+ */
+ if (item->optype != -1 && (tmpl->optype & item->optype) == 0)
+ continue;
+ /*
+ * This expression is stunningly simple thanks to the sanity check
+ * above.
+ */
+ if (item->keytype1 != -1
+ && tmpl->keytype1 != item->keytype1
+ && tmpl->keytype2 != item->keytype2)
+ continue;
+
+ /*
+ * Done with the base search criteria, now we check the criteria for
+ * the individual types of translations:
+ * ctrl->params, ctrl_str->params, and params->ctrl
+ */
+ if (tmpl->ctrl_num != 0) {
+ if (tmpl->ctrl_num != item->ctrl_num)
+ continue;
+ } else if (tmpl->ctrl_str != NULL) {
+ const char *ctrl_str = NULL;
+ const char *ctrl_hexstr = NULL;
+
+ /*
+ * Search criteria that originates from a ctrl_str is only used
+ * for setting, never for getting. Therefore, we only look at
+ * the setter items.
+ */
+ if (item->action_type != NONE
+ && item->action_type != SET)
+ continue;
+ /*
+ * At least one of the ctrl cmd names must be match the ctrl
+ * cmd name in the template.
+ */
+ if (item->ctrl_str != NULL
+ && OPENSSL_strcasecmp(tmpl->ctrl_str, item->ctrl_str) == 0)
+ ctrl_str = tmpl->ctrl_str;
+ else if (item->ctrl_hexstr != NULL
+ && OPENSSL_strcasecmp(tmpl->ctrl_hexstr,
+ item->ctrl_hexstr) == 0)
+ ctrl_hexstr = tmpl->ctrl_hexstr;
+ else
+ continue;
+
+ /* Modify the template to signal which string matched */
+ tmpl->ctrl_str = ctrl_str;
+ tmpl->ctrl_hexstr = ctrl_hexstr;
+ } else if (tmpl->param_key != NULL) {
+ /*
+ * Search criteria that originates from a OSSL_PARAM setter or
+ * getter.
+ *
+ * Ctrls were fundamentally bidirectional, with only the ctrl
+ * command macro name implying direction (if you're lucky).
+ * A few ctrl commands were even taking advantage of the
+ * bidirectional nature, making the direction depend in the
+ * value of the numeric argument.
+ *
+ * OSSL_PARAM functions are fundamentally different, in that
+ * setters and getters are separated, so the data direction is
+ * implied by the function that's used. The same OSSL_PARAM
+ * key name can therefore be used in both directions. We must
+ * therefore take the action type into account in this case.
+ */
+ if ((item->action_type != NONE
+ && tmpl->action_type != item->action_type)
+ || (item->param_key != NULL
+ && OPENSSL_strcasecmp(tmpl->param_key,
+ item->param_key) != 0))
+ continue;
+ } else {
+ return NULL;
+ }
+
+ return item;
+ }
+
+ return NULL;
+}
+
+static const struct translation_st *
+lookup_evp_pkey_ctx_translation(struct translation_st *tmpl)
+{
+ return lookup_translation(tmpl, evp_pkey_ctx_translations,
+ OSSL_NELEM(evp_pkey_ctx_translations));
+}
+
+static const struct translation_st *
+lookup_evp_pkey_translation(struct translation_st *tmpl)
+{
+ return lookup_translation(tmpl, evp_pkey_translations,
+ OSSL_NELEM(evp_pkey_translations));
+}
+
+/* This must ONLY be called for provider side operations */
+int evp_pkey_ctx_ctrl_to_param(EVP_PKEY_CTX *pctx,
+ int keytype, int optype,
+ int cmd, int p1, void *p2)
+{
+ struct translation_ctx_st ctx = { 0, };
+ struct translation_st tmpl = { 0, };
+ const struct translation_st *translation = NULL;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ int ret;
+ fixup_args_fn *fixup = default_fixup_args;
+
+ if (keytype == -1)
+ keytype = pctx->legacy_keytype;
+ tmpl.ctrl_num = cmd;
+ tmpl.keytype1 = tmpl.keytype2 = keytype;
+ tmpl.optype = optype;
+ translation = lookup_evp_pkey_ctx_translation(&tmpl);
+
+ if (translation == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return -2;
+ }
+
+ if (pctx->pmeth != NULL
+ && pctx->pmeth->pkey_id != translation->keytype1
+ && pctx->pmeth->pkey_id != translation->keytype2)
+ return -1;
+
+ if (translation->fixup_args != NULL)
+ fixup = translation->fixup_args;
+ ctx.action_type = translation->action_type;
+ ctx.ctrl_cmd = cmd;
+ ctx.p1 = p1;
+ ctx.p2 = p2;
+ ctx.pctx = pctx;
+ ctx.params = params;
+
+ ret = fixup(PRE_CTRL_TO_PARAMS, translation, &ctx);
+
+ if (ret > 0) {
+ switch (ctx.action_type) {
+ default:
+ /* fixup_args is expected to make sure this is dead code */
+ break;
+ case GET:
+ ret = evp_pkey_ctx_get_params_strict(pctx, ctx.params);
+ break;
+ case SET:
+ ret = evp_pkey_ctx_set_params_strict(pctx, ctx.params);
+ break;
+ }
+ }
+
+ /*
+ * In POST, we pass the return value as p1, allowing the fixup_args
+ * function to affect it by changing its value.
+ */
+ if (ret > 0) {
+ ctx.p1 = ret;
+ fixup(POST_CTRL_TO_PARAMS, translation, &ctx);
+ ret = ctx.p1;
+ }
+
+ cleanup_translation_ctx(POST_CTRL_TO_PARAMS, translation, &ctx);
+
+ return ret;
+}
+
+/* This must ONLY be called for provider side operations */
+int evp_pkey_ctx_ctrl_str_to_param(EVP_PKEY_CTX *pctx,
+ const char *name, const char *value)
+{
+ struct translation_ctx_st ctx = { 0, };
+ struct translation_st tmpl = { 0, };
+ const struct translation_st *translation = NULL;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ int keytype = pctx->legacy_keytype;
+ int optype = pctx->operation == 0 ? -1 : pctx->operation;
+ int ret;
+ fixup_args_fn *fixup = default_fixup_args;
+
+ tmpl.action_type = SET;
+ tmpl.keytype1 = tmpl.keytype2 = keytype;
+ tmpl.optype = optype;
+ tmpl.ctrl_str = name;
+ tmpl.ctrl_hexstr = name;
+ translation = lookup_evp_pkey_ctx_translation(&tmpl);
+
+ if (translation != NULL) {
+ if (translation->fixup_args != NULL)
+ fixup = translation->fixup_args;
+ ctx.action_type = translation->action_type;
+ ctx.ishex = (tmpl.ctrl_hexstr != NULL);
+ } else {
+ /* String controls really only support setting */
+ ctx.action_type = SET;
+ }
+ ctx.ctrl_str = name;
+ ctx.p1 = (int)strlen(value);
+ ctx.p2 = (char *)value;
+ ctx.pctx = pctx;
+ ctx.params = params;
+
+ ret = fixup(PRE_CTRL_STR_TO_PARAMS, translation, &ctx);
+
+ if (ret > 0) {
+ switch (ctx.action_type) {
+ default:
+ /* fixup_args is expected to make sure this is dead code */
+ break;
+ case GET:
+ /*
+ * this is dead code, but must be present, or some compilers
+ * will complain
+ */
+ break;
+ case SET:
+ ret = evp_pkey_ctx_set_params_strict(pctx, ctx.params);
+ break;
+ }
+ }
+
+ if (ret > 0)
+ ret = fixup(POST_CTRL_STR_TO_PARAMS, translation, &ctx);
+
+ cleanup_translation_ctx(CLEANUP_CTRL_STR_TO_PARAMS, translation, &ctx);
+
+ return ret;
+}
+
+/* This must ONLY be called for legacy operations */
+static int evp_pkey_ctx_setget_params_to_ctrl(EVP_PKEY_CTX *pctx,
+ enum action action_type,
+ OSSL_PARAM *params)
+{
+ int keytype = pctx->legacy_keytype;
+ int optype = pctx->operation == 0 ? -1 : pctx->operation;
+
+ for (; params != NULL && params->key != NULL; params++) {
+ struct translation_ctx_st ctx = { 0, };
+ struct translation_st tmpl = { 0, };
+ const struct translation_st *translation = NULL;
+ fixup_args_fn *fixup = default_fixup_args;
+ int ret;
+
+ tmpl.action_type = action_type;
+ tmpl.keytype1 = tmpl.keytype2 = keytype;
+ tmpl.optype = optype;
+ tmpl.param_key = params->key;
+ translation = lookup_evp_pkey_ctx_translation(&tmpl);
+
+ if (translation != NULL) {
+ if (translation->fixup_args != NULL)
+ fixup = translation->fixup_args;
+ ctx.action_type = translation->action_type;
+ }
+ ctx.pctx = pctx;
+ ctx.params = params;
+
+ ret = fixup(PRE_PARAMS_TO_CTRL, translation, &ctx);
+
+ if (ret > 0 && ctx.action_type != NONE)
+ ret = EVP_PKEY_CTX_ctrl(pctx, keytype, optype,
+ ctx.ctrl_cmd, ctx.p1, ctx.p2);
+
+ /*
+ * In POST, we pass the return value as p1, allowing the fixup_args
+ * function to put it to good use, or maybe affect it.
+ */
+ if (ret > 0) {
+ ctx.p1 = ret;
+ fixup(POST_PARAMS_TO_CTRL, translation, &ctx);
+ ret = ctx.p1;
+ }
+
+ cleanup_translation_ctx(CLEANUP_PARAMS_TO_CTRL, translation, &ctx);
+
+ if (ret <= 0)
+ return 0;
+ }
+ return 1;
+}
+
+int evp_pkey_ctx_set_params_to_ctrl(EVP_PKEY_CTX *ctx, const OSSL_PARAM *params)
+{
+ return evp_pkey_ctx_setget_params_to_ctrl(ctx, SET, (OSSL_PARAM *)params);
+}
+
+int evp_pkey_ctx_get_params_to_ctrl(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
+{
+ return evp_pkey_ctx_setget_params_to_ctrl(ctx, GET, params);
+}
+
+/* This must ONLY be called for legacy EVP_PKEYs */
+static int evp_pkey_setget_params_to_ctrl(const EVP_PKEY *pkey,
+ enum action action_type,
+ OSSL_PARAM *params)
+{
+ int ret = 1;
+
+ for (; params != NULL && params->key != NULL; params++) {
+ struct translation_ctx_st ctx = { 0, };
+ struct translation_st tmpl = { 0, };
+ const struct translation_st *translation = NULL;
+ fixup_args_fn *fixup = default_fixup_args;
+
+ tmpl.action_type = action_type;
+ tmpl.param_key = params->key;
+ translation = lookup_evp_pkey_translation(&tmpl);
+
+ if (translation != NULL) {
+ if (translation->fixup_args != NULL)
+ fixup = translation->fixup_args;
+ ctx.action_type = translation->action_type;
+ }
+ ctx.p2 = (void *)pkey;
+ ctx.params = params;
+
+ /*
+ * EVP_PKEY doesn't have any ctrl function, so we rely completely
+ * on fixup_args to do the whole work. Also, we currently only
+ * support getting.
+ */
+ if (!ossl_assert(translation != NULL)
+ || !ossl_assert(translation->action_type == GET)
+ || !ossl_assert(translation->fixup_args != NULL)) {
+ return -2;
+ }
+
+ ret = fixup(PKEY, translation, &ctx);
+
+ cleanup_translation_ctx(PKEY, translation, &ctx);
+ }
+ return ret;
+}
+
+int evp_pkey_get_params_to_ctrl(const EVP_PKEY *pkey, OSSL_PARAM *params)
+{
+ return evp_pkey_setget_params_to_ctrl(pkey, GET, params);
+}
diff --git a/crypto/evp/dh_ctrl.c b/crypto/evp/dh_ctrl.c
new file mode 100644
index 000000000000..fee7757d9aee
--- /dev/null
+++ b/crypto/evp/dh_ctrl.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/deprecated.h"
+
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#include <openssl/dh.h>
+#include "crypto/dh.h"
+#include "crypto/evp.h"
+
+static int dh_paramgen_check(EVP_PKEY_CTX *ctx)
+{
+ if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+ /* If key type not DH return error */
+ if (evp_pkey_ctx_is_legacy(ctx)
+ && ctx->pmeth->pkey_id != EVP_PKEY_DH
+ && ctx->pmeth->pkey_id != EVP_PKEY_DHX)
+ return -1;
+ return 1;
+}
+
+static int dh_param_derive_check(EVP_PKEY_CTX *ctx)
+{
+ if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+ /* If key type not DH return error */
+ if (evp_pkey_ctx_is_legacy(ctx)
+ && ctx->pmeth->pkey_id != EVP_PKEY_DH
+ && ctx->pmeth->pkey_id != EVP_PKEY_DHX)
+ return -1;
+ return 1;
+}
+
+int EVP_PKEY_CTX_set_dh_paramgen_gindex(EVP_PKEY_CTX *ctx, int gindex)
+{
+ int ret;
+ OSSL_PARAM params[2], *p = params;
+
+ if ((ret = dh_paramgen_check(ctx)) <= 0)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_FFC_GINDEX, &gindex);
+ *p = OSSL_PARAM_construct_end();
+
+ return evp_pkey_ctx_set_params_strict(ctx, params);
+}
+
+int EVP_PKEY_CTX_set_dh_paramgen_seed(EVP_PKEY_CTX *ctx,
+ const unsigned char *seed,
+ size_t seedlen)
+{
+ int ret;
+ OSSL_PARAM params[2], *p = params;
+
+ if ((ret = dh_paramgen_check(ctx)) <= 0)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_FFC_SEED,
+ (void *)seed, seedlen);
+ *p = OSSL_PARAM_construct_end();
+
+ return evp_pkey_ctx_set_params_strict(ctx, params);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_set_dh_paramgen_type(EVP_PKEY_CTX *ctx, int typ)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, typ, NULL);
+}
+
+int EVP_PKEY_CTX_set_dh_paramgen_prime_len(EVP_PKEY_CTX *ctx, int pbits)
+{
+ int ret;
+ OSSL_PARAM params[2], *p = params;
+ size_t bits = pbits;
+
+ if ((ret = dh_paramgen_check(ctx)) <= 0)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_FFC_PBITS, &bits);
+ *p = OSSL_PARAM_construct_end();
+ return evp_pkey_ctx_set_params_strict(ctx, params);
+}
+
+int EVP_PKEY_CTX_set_dh_paramgen_subprime_len(EVP_PKEY_CTX *ctx, int qbits)
+{
+ int ret;
+ OSSL_PARAM params[2], *p = params;
+ size_t bits2 = qbits;
+
+ if ((ret = dh_paramgen_check(ctx)) <= 0)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_FFC_QBITS, &bits2);
+ *p = OSSL_PARAM_construct_end();
+
+ return evp_pkey_ctx_set_params_strict(ctx, params);
+}
+
+int EVP_PKEY_CTX_set_dh_paramgen_generator(EVP_PKEY_CTX *ctx, int gen)
+{
+ int ret;
+ OSSL_PARAM params[2], *p = params;
+
+ if ((ret = dh_paramgen_check(ctx)) <= 0)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_DH_GENERATOR, &gen);
+ *p = OSSL_PARAM_construct_end();
+
+ return evp_pkey_ctx_set_params_strict(ctx, params);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_set_dh_rfc5114(EVP_PKEY_CTX *ctx, int gen)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DH_RFC5114, gen, NULL);
+}
+
+int EVP_PKEY_CTX_set_dhx_rfc5114(EVP_PKEY_CTX *ctx, int gen)
+{
+ return EVP_PKEY_CTX_set_dh_rfc5114(ctx, gen);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_set_dh_nid(EVP_PKEY_CTX *ctx, int nid)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH,
+ EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_DH_NID, nid, NULL);
+}
+
+int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad)
+{
+ OSSL_PARAM dh_pad_params[2];
+ unsigned int upad = pad;
+
+ /* We use EVP_PKEY_CTX_ctrl return values */
+ if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return -2;
+ }
+
+ dh_pad_params[0] = OSSL_PARAM_construct_uint(OSSL_EXCHANGE_PARAM_PAD, &upad);
+ dh_pad_params[1] = OSSL_PARAM_construct_end();
+
+ return evp_pkey_ctx_set_params_strict(ctx, dh_pad_params);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_set_dh_kdf_type(EVP_PKEY_CTX *ctx, int kdf)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_DH_KDF_TYPE, kdf, NULL);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_get_dh_kdf_type(EVP_PKEY_CTX *ctx)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_DH_KDF_TYPE, -2, NULL);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_set0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT *oid)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_DH_KDF_OID, 0, (void *)(oid));
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_get0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT **oid)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_GET_DH_KDF_OID, 0, (void *)(oid));
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_set_dh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_DH_KDF_MD, 0, (void *)(md));
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_get_dh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_GET_DH_KDF_MD, 0, (void *)(pmd));
+}
+
+int EVP_PKEY_CTX_set_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int outlen)
+{
+ int ret;
+ size_t len = outlen;
+ OSSL_PARAM params[2], *p = params;
+
+ ret = dh_param_derive_check(ctx);
+ if (ret != 1)
+ return ret;
+
+ if (outlen <= 0) {
+ /*
+ * This would ideally be -1 or 0, but we have to retain compatibility
+ * with legacy behaviour of EVP_PKEY_CTX_ctrl() which returned -2 if
+ * inlen <= 0
+ */
+ return -2;
+ }
+
+ *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
+ &len);
+ *p = OSSL_PARAM_construct_end();
+
+ ret = evp_pkey_ctx_set_params_strict(ctx, params);
+ if (ret == -2)
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return ret;
+}
+
+int EVP_PKEY_CTX_get_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int *plen)
+{
+ int ret;
+ size_t len = UINT_MAX;
+ OSSL_PARAM params[2], *p = params;
+
+ ret = dh_param_derive_check(ctx);
+ if (ret != 1)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
+ &len);
+ *p = OSSL_PARAM_construct_end();
+
+ ret = evp_pkey_ctx_get_params_strict(ctx, params);
+ if (ret == -2)
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ if (ret != 1 || len > INT_MAX)
+ return -1;
+
+ *plen = (int)len;
+
+ return 1;
+}
+
+int EVP_PKEY_CTX_set0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len)
+{
+ int ret;
+ OSSL_PARAM params[2], *p = params;
+
+ if (len < 0)
+ return -1;
+
+ ret = dh_param_derive_check(ctx);
+ if (ret != 1)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM,
+ /*
+ * Cast away the const. This is read
+ * only so should be safe
+ */
+ (void *)ukm,
+ (size_t)len);
+ *p = OSSL_PARAM_construct_end();
+
+ ret = evp_pkey_ctx_set_params_strict(ctx, params);
+ if (ret == -2)
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ if (ret == 1)
+ OPENSSL_free(ukm);
+ return ret;
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+int EVP_PKEY_CTX_get0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm)
+{
+ int ret;
+ size_t ukmlen;
+ OSSL_PARAM params[2], *p = params;
+
+ ret = dh_param_derive_check(ctx);
+ if (ret != 1)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_EXCHANGE_PARAM_KDF_UKM,
+ (void **)pukm, 0);
+ *p = OSSL_PARAM_construct_end();
+
+ ret = evp_pkey_ctx_get_params_strict(ctx, params);
+ if (ret == -2)
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ if (ret != 1)
+ return -1;
+
+ ukmlen = params[0].return_size;
+ if (ukmlen > INT_MAX)
+ return -1;
+
+ return (int)ukmlen;
+}
+#endif
diff --git a/crypto/evp/dh_support.c b/crypto/evp/dh_support.c
new file mode 100644
index 000000000000..87296ffbee2b
--- /dev/null
+++ b/crypto/evp/dh_support.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h> /* strcmp */
+#include <openssl/dh.h>
+#include "internal/nelem.h"
+#include "crypto/dh.h"
+
+typedef struct dh_name2id_st{
+ const char *name;
+ int id;
+ int type;
+} DH_GENTYPE_NAME2ID;
+
+/* Indicates that the paramgen_type can be used for either DH or DHX */
+#define TYPE_ANY -1
+#ifndef OPENSSL_NO_DH
+# define TYPE_DH DH_FLAG_TYPE_DH
+# define TYPE_DHX DH_FLAG_TYPE_DHX
+#else
+# define TYPE_DH 0
+# define TYPE_DHX 0
+#endif
+
+static const DH_GENTYPE_NAME2ID dhtype2id[] =
+{
+ { "group", DH_PARAMGEN_TYPE_GROUP, TYPE_ANY },
+ { "generator", DH_PARAMGEN_TYPE_GENERATOR, TYPE_DH },
+ { "fips186_4", DH_PARAMGEN_TYPE_FIPS_186_4, TYPE_DHX },
+ { "fips186_2", DH_PARAMGEN_TYPE_FIPS_186_2, TYPE_DHX },
+};
+
+const char *ossl_dh_gen_type_id2name(int id)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(dhtype2id); ++i) {
+ if (dhtype2id[i].id == id)
+ return dhtype2id[i].name;
+ }
+ return NULL;
+}
+
+#ifndef OPENSSL_NO_DH
+int ossl_dh_gen_type_name2id(const char *name, int type)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(dhtype2id); ++i) {
+ if ((dhtype2id[i].type == TYPE_ANY
+ || type == dhtype2id[i].type)
+ && strcmp(dhtype2id[i].name, name) == 0)
+ return dhtype2id[i].id;
+ }
+ return -1;
+}
+#endif
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index 01a6f251f56e..e6e03eaf34a5 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -1,21 +1,30 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <stdio.h>
-#include "internal/cryptlib.h"
#include <openssl/objects.h>
#include <openssl/evp.h>
-#include <openssl/engine.h>
+#include <openssl/ec.h>
+#ifndef FIPS_MODULE
+# include <openssl/engine.h>
+#endif
+#include <openssl/params.h>
+#include <openssl/core_names.h>
+#include "internal/cryptlib.h"
+#include "internal/provider.h"
+#include "internal/core.h"
#include "crypto/evp.h"
#include "evp_local.h"
-
static void cleanup_old_md_data(EVP_MD_CTX *ctx, int force)
{
if (ctx->digest != NULL) {
@@ -31,32 +40,93 @@ static void cleanup_old_md_data(EVP_MD_CTX *ctx, int force)
}
}
-/* This call frees resources associated with the context */
-int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
+void evp_md_ctx_clear_digest(EVP_MD_CTX *ctx, int force, int keep_fetched)
{
- if (ctx == NULL)
- return 1;
+ if (ctx->algctx != NULL) {
+ if (ctx->digest != NULL && ctx->digest->freectx != NULL)
+ ctx->digest->freectx(ctx->algctx);
+ ctx->algctx = NULL;
+ EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
+ }
+
+ /* Code below to be removed when legacy support is dropped. */
/*
* Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because
* sometimes only copies of the context are ever finalised.
*/
- cleanup_old_md_data(ctx, 0);
+ cleanup_old_md_data(ctx, force);
+ if (force)
+ ctx->digest = NULL;
+
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
+ ENGINE_finish(ctx->engine);
+ ctx->engine = NULL;
+#endif
+
+ /* Non legacy code, this has to be later than the ctx->digest cleaning */
+ if (!keep_fetched) {
+ EVP_MD_free(ctx->fetched_digest);
+ ctx->fetched_digest = NULL;
+ ctx->reqdigest = NULL;
+ }
+}
+
+static int evp_md_ctx_reset_ex(EVP_MD_CTX *ctx, int keep_fetched)
+{
+ if (ctx == NULL)
+ return 1;
+#ifndef FIPS_MODULE
/*
* pctx should be freed by the user of EVP_MD_CTX
* if EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set
*/
- if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX))
+ if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX)) {
EVP_PKEY_CTX_free(ctx->pctx);
-#ifndef OPENSSL_NO_ENGINE
- ENGINE_finish(ctx->engine);
+ ctx->pctx = NULL;
+ }
#endif
- OPENSSL_cleanse(ctx, sizeof(*ctx));
+
+ evp_md_ctx_clear_digest(ctx, 0, keep_fetched);
+ if (!keep_fetched)
+ OPENSSL_cleanse(ctx, sizeof(*ctx));
return 1;
}
+/* This call frees resources associated with the context */
+int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
+{
+ return evp_md_ctx_reset_ex(ctx, 0);
+}
+
+#ifndef FIPS_MODULE
+EVP_MD_CTX *evp_md_ctx_new_ex(EVP_PKEY *pkey, const ASN1_OCTET_STRING *id,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ EVP_MD_CTX *ctx;
+ EVP_PKEY_CTX *pctx = NULL;
+
+ if ((ctx = EVP_MD_CTX_new()) == NULL
+ || (pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq)) == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (id != NULL && EVP_PKEY_CTX_set1_id(pctx, id->data, id->length) <= 0)
+ goto err;
+
+ EVP_MD_CTX_set_pkey_ctx(ctx, pctx);
+ return ctx;
+
+ err:
+ EVP_PKEY_CTX_free(pctx);
+ EVP_MD_CTX_free(ctx);
+ return NULL;
+}
+#endif
+
EVP_MD_CTX *EVP_MD_CTX_new(void)
{
return OPENSSL_zalloc(sizeof(EVP_MD_CTX));
@@ -64,20 +134,63 @@ EVP_MD_CTX *EVP_MD_CTX_new(void)
void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
{
+ if (ctx == NULL)
+ return;
+
EVP_MD_CTX_reset(ctx);
OPENSSL_free(ctx);
}
-int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
+static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type,
+ const OSSL_PARAM params[], ENGINE *impl)
{
- EVP_MD_CTX_reset(ctx);
- return EVP_DigestInit_ex(ctx, type, NULL);
-}
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
+ ENGINE *tmpimpl = NULL;
+#endif
+
+#if !defined(FIPS_MODULE)
+ if (ctx->pctx != NULL
+ && EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx->pctx)
+ && ctx->pctx->op.sig.algctx != NULL) {
+ /*
+ * Prior to OpenSSL 3.0 calling EVP_DigestInit_ex() on an mdctx
+ * previously initialised with EVP_DigestSignInit() would retain
+ * information about the key, and re-initialise for another sign
+ * operation. So in that case we redirect to EVP_DigestSignInit()
+ */
+ if (ctx->pctx->operation == EVP_PKEY_OP_SIGNCTX)
+ return EVP_DigestSignInit(ctx, NULL, type, impl, NULL);
+ if (ctx->pctx->operation == EVP_PKEY_OP_VERIFYCTX)
+ return EVP_DigestVerifyInit(ctx, NULL, type, impl, NULL);
+ ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
+ return 0;
+ }
+#endif
-int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
-{
EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
-#ifndef OPENSSL_NO_ENGINE
+
+ if (ctx->algctx != NULL) {
+ if (!ossl_assert(ctx->digest != NULL)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+ if (ctx->digest->freectx != NULL)
+ ctx->digest->freectx(ctx->algctx);
+ ctx->algctx = NULL;
+ }
+
+ if (type != NULL) {
+ ctx->reqdigest = type;
+ } else {
+ if (ctx->digest == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_DIGEST_SET);
+ return 0;
+ }
+ type = ctx->digest;
+ }
+
+ /* Code below to be removed when legacy support is dropped. */
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
/*
* Whether it's nice or not, "Inits" can be used on "Final"'d contexts so
* this context may already have an ENGINE! Try to avoid releasing the
@@ -88,28 +201,114 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
(type == NULL || (type->type == ctx->digest->type)))
goto skip_to_init;
- if (type) {
+ if (type != NULL) {
/*
* Ensure an ENGINE left lying around from last time is cleared (the
* previous check attempted to avoid this if the same ENGINE and
* EVP_MD could be used).
*/
ENGINE_finish(ctx->engine);
+ ctx->engine = NULL;
+ }
+
+ if (type != NULL && impl == NULL)
+ tmpimpl = ENGINE_get_digest_engine(type->type);
+#endif
+
+ /*
+ * If there are engines involved or EVP_MD_CTX_FLAG_NO_INIT is set then we
+ * should use legacy handling for now.
+ */
+ if (ctx->engine != NULL
+ || impl != NULL
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
+ || tmpimpl != NULL
+#endif
+ || (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) != 0
+ || (type != NULL && type->origin == EVP_ORIG_METH)
+ || (type == NULL && ctx->digest != NULL
+ && ctx->digest->origin == EVP_ORIG_METH)) {
+ if (ctx->digest == ctx->fetched_digest)
+ ctx->digest = NULL;
+ EVP_MD_free(ctx->fetched_digest);
+ ctx->fetched_digest = NULL;
+ goto legacy;
+ }
+
+ cleanup_old_md_data(ctx, 1);
+
+ /* Start of non-legacy code below */
+
+ if (type->prov == NULL) {
+#ifdef FIPS_MODULE
+ /* We only do explicit fetches inside the FIPS module */
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+#else
+ /* The NULL digest is a special case */
+ EVP_MD *provmd = EVP_MD_fetch(NULL,
+ type->type != NID_undef ? OBJ_nid2sn(type->type)
+ : "NULL", "");
+
+ if (provmd == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+ type = provmd;
+ EVP_MD_free(ctx->fetched_digest);
+ ctx->fetched_digest = provmd;
+#endif
+ }
+
+ if (ctx->algctx != NULL && ctx->digest != NULL && ctx->digest != type) {
+ if (ctx->digest->freectx != NULL)
+ ctx->digest->freectx(ctx->algctx);
+ ctx->algctx = NULL;
+ }
+ if (type->prov != NULL && ctx->fetched_digest != type) {
+ if (!EVP_MD_up_ref((EVP_MD *)type)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+ EVP_MD_free(ctx->fetched_digest);
+ ctx->fetched_digest = (EVP_MD *)type;
+ }
+ ctx->digest = type;
+ if (ctx->algctx == NULL) {
+ ctx->algctx = ctx->digest->newctx(ossl_provider_ctx(type->prov));
+ if (ctx->algctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+ }
+
+ if (ctx->digest->dinit == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+
+ return ctx->digest->dinit(ctx->algctx, params);
+
+ /* Code below to be removed when legacy support is dropped. */
+ legacy:
+
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
+ if (type) {
if (impl != NULL) {
if (!ENGINE_init(impl)) {
- EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
} else {
/* Ask if an ENGINE is reserved for this job */
- impl = ENGINE_get_digest_engine(type->type);
+ impl = tmpimpl;
}
if (impl != NULL) {
/* There's an ENGINE for this job ... (apparently) */
const EVP_MD *d = ENGINE_get_digest(impl, type->type);
if (d == NULL) {
- EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
ENGINE_finish(impl);
return 0;
}
@@ -122,12 +321,6 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
ctx->engine = impl;
} else
ctx->engine = NULL;
- } else {
- if (!ctx->digest) {
- EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_NO_DIGEST_SET);
- return 0;
- }
- type = ctx->digest;
}
#endif
if (ctx->digest != type) {
@@ -138,31 +331,84 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
ctx->update = type->update;
ctx->md_data = OPENSSL_zalloc(type->ctx_size);
if (ctx->md_data == NULL) {
- EVPerr(EVP_F_EVP_DIGESTINIT_EX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
}
}
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
skip_to_init:
#endif
- if (ctx->pctx) {
+#ifndef FIPS_MODULE
+ if (ctx->pctx != NULL
+ && (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx->pctx)
+ || ctx->pctx->op.sig.signature == NULL)) {
int r;
r = EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG,
EVP_PKEY_CTRL_DIGESTINIT, 0, ctx);
if (r <= 0 && (r != -2))
return 0;
}
+#endif
if (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT)
return 1;
return ctx->digest->init(ctx);
}
+int EVP_DigestInit_ex2(EVP_MD_CTX *ctx, const EVP_MD *type,
+ const OSSL_PARAM params[])
+{
+ return evp_md_init_internal(ctx, type, params, NULL);
+}
+
+int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
+{
+ EVP_MD_CTX_reset(ctx);
+ return evp_md_init_internal(ctx, type, NULL, NULL);
+}
+
+int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
+{
+ return evp_md_init_internal(ctx, type, NULL, impl);
+}
+
int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count)
{
if (count == 0)
return 1;
+ if (ctx->pctx != NULL
+ && EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx->pctx)
+ && ctx->pctx->op.sig.algctx != NULL) {
+ /*
+ * Prior to OpenSSL 3.0 EVP_DigestSignUpdate() and
+ * EVP_DigestVerifyUpdate() were just macros for EVP_DigestUpdate().
+ * Some code calls EVP_DigestUpdate() directly even when initialised
+ * with EVP_DigestSignInit_ex() or
+ * EVP_DigestVerifyInit_ex(), so we detect that and redirect to
+ * the correct EVP_Digest*Update() function
+ */
+ if (ctx->pctx->operation == EVP_PKEY_OP_SIGNCTX)
+ return EVP_DigestSignUpdate(ctx, data, count);
+ if (ctx->pctx->operation == EVP_PKEY_OP_VERIFYCTX)
+ return EVP_DigestVerifyUpdate(ctx, data, count);
+ ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
+ return 0;
+ }
+
+ if (ctx->digest == NULL
+ || ctx->digest->prov == NULL
+ || (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) != 0)
+ goto legacy;
+
+ if (ctx->digest->dupdate == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
+ return 0;
+ }
+ return ctx->digest->dupdate(ctx->algctx, data, count);
+
+ /* Code below to be removed when legacy support is dropped. */
+ legacy:
return ctx->update(ctx, data, count);
}
@@ -176,14 +422,46 @@ int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
}
/* The caller can assume that this removes any secret data from the context */
-int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
+int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize)
{
- int ret;
+ int ret, sz;
+ size_t size = 0;
+ size_t mdsize = 0;
+
+ if (ctx->digest == NULL)
+ return 0;
+
+ sz = EVP_MD_get_size(ctx->digest);
+ if (sz < 0)
+ return 0;
+ mdsize = sz;
+ if (ctx->digest->prov == NULL)
+ goto legacy;
+
+ if (ctx->digest->dfinal == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
+ return 0;
+ }
+
+ ret = ctx->digest->dfinal(ctx->algctx, md, &size, mdsize);
+
+ if (isize != NULL) {
+ if (size <= UINT_MAX) {
+ *isize = (int)size;
+ } else {
+ ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
+ ret = 0;
+ }
+ }
- OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE);
+ return ret;
+
+ /* Code below to be removed when legacy support is dropped. */
+ legacy:
+ OPENSSL_assert(mdsize <= EVP_MAX_MD_SIZE);
ret = ctx->digest->final(ctx, md);
- if (size != NULL)
- *size = ctx->digest->md_size;
+ if (isize != NULL)
+ *isize = mdsize;
if (ctx->digest->cleanup) {
ctx->digest->cleanup(ctx);
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
@@ -195,19 +473,42 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t size)
{
int ret = 0;
+ OSSL_PARAM params[2];
+ size_t i = 0;
+ if (ctx->digest == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_NULL_ALGORITHM);
+ return 0;
+ }
+
+ if (ctx->digest->prov == NULL)
+ goto legacy;
+
+ if (ctx->digest->dfinal == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
+ return 0;
+ }
+
+ params[i++] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_XOFLEN, &size);
+ params[i++] = OSSL_PARAM_construct_end();
+
+ if (EVP_MD_CTX_set_params(ctx, params) > 0)
+ ret = ctx->digest->dfinal(ctx->algctx, md, &size, size);
+
+ return ret;
+
+legacy:
if (ctx->digest->flags & EVP_MD_FLAG_XOF
&& size <= INT_MAX
&& ctx->digest->md_ctrl(ctx, EVP_MD_CTRL_XOF_LEN, (int)size, NULL)) {
ret = ctx->digest->final(ctx, md);
-
if (ctx->digest->cleanup != NULL) {
ctx->digest->cleanup(ctx);
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
}
OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size);
} else {
- EVPerr(EVP_F_EVP_DIGESTFINALXOF, EVP_R_NOT_XOF_OR_INVALID_LENGTH);
+ ERR_raise(ERR_LIB_EVP, EVP_R_NOT_XOF_OR_INVALID_LENGTH);
}
return ret;
@@ -221,15 +522,74 @@ int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in)
int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
{
+ int digest_change = 0;
unsigned char *tmp_buf;
- if ((in == NULL) || (in->digest == NULL)) {
- EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, EVP_R_INPUT_NOT_INITIALIZED);
+
+ if (in == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
-#ifndef OPENSSL_NO_ENGINE
+
+ if (in->digest == NULL) {
+ /* copying uninitialized digest context */
+ EVP_MD_CTX_reset(out);
+ if (out->fetched_digest != NULL)
+ EVP_MD_free(out->fetched_digest);
+ *out = *in;
+ goto clone_pkey;
+ }
+
+ if (in->digest->prov == NULL
+ || (in->flags & EVP_MD_CTX_FLAG_NO_INIT) != 0)
+ goto legacy;
+
+ if (in->digest->dupctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NOT_ABLE_TO_COPY_CTX);
+ return 0;
+ }
+
+ evp_md_ctx_reset_ex(out, 1);
+ digest_change = (out->fetched_digest != in->fetched_digest);
+ if (digest_change && out->fetched_digest != NULL)
+ EVP_MD_free(out->fetched_digest);
+ *out = *in;
+ /* NULL out pointers in case of error */
+ out->pctx = NULL;
+ out->algctx = NULL;
+
+ if (digest_change && in->fetched_digest != NULL)
+ EVP_MD_up_ref(in->fetched_digest);
+
+ if (in->algctx != NULL) {
+ out->algctx = in->digest->dupctx(in->algctx);
+ if (out->algctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NOT_ABLE_TO_COPY_CTX);
+ return 0;
+ }
+ }
+
+ clone_pkey:
+ /* copied EVP_MD_CTX should free the copied EVP_PKEY_CTX */
+ EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
+#ifndef FIPS_MODULE
+ if (in->pctx != NULL) {
+ out->pctx = EVP_PKEY_CTX_dup(in->pctx);
+ if (out->pctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NOT_ABLE_TO_COPY_CTX);
+ EVP_MD_CTX_reset(out);
+ return 0;
+ }
+ }
+#endif
+
+ return 1;
+
+ /* Code below to be removed when legacy support is dropped. */
+ legacy:
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
/* Make sure it's safe to copy a digest context using an ENGINE */
if (in->engine && !ENGINE_init(in->engine)) {
- EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, ERR_R_ENGINE_LIB);
+ ERR_raise(ERR_LIB_EVP, ERR_R_ENGINE_LIB);
return 0;
}
#endif
@@ -258,7 +618,7 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
else {
out->md_data = OPENSSL_malloc(out->digest->ctx_size);
if (out->md_data == NULL) {
- EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
}
@@ -267,6 +627,7 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
out->update = in->update;
+#ifndef FIPS_MODULE
if (in->pctx) {
out->pctx = EVP_PKEY_CTX_dup(in->pctx);
if (!out->pctx) {
@@ -274,6 +635,7 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
return 0;
}
}
+#endif
if (out->digest->copy)
return out->digest->copy(out, in);
@@ -299,13 +661,448 @@ int EVP_Digest(const void *data, size_t count,
return ret;
}
-int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)
+int EVP_Q_digest(OSSL_LIB_CTX *libctx, const char *name, const char *propq,
+ const void *data, size_t datalen,
+ unsigned char *md, size_t *mdlen)
{
- if (ctx->digest && ctx->digest->md_ctrl) {
- int ret = ctx->digest->md_ctrl(ctx, cmd, p1, p2);
- if (ret <= 0)
- return 0;
- return 1;
+ EVP_MD *digest = EVP_MD_fetch(libctx, name, propq);
+ unsigned int temp = 0;
+ int ret = 0;
+
+ if (digest != NULL) {
+ ret = EVP_Digest(data, datalen, md, &temp, digest, NULL);
+ EVP_MD_free(digest);
+ }
+ if (mdlen != NULL)
+ *mdlen = temp;
+ return ret;
+}
+
+int EVP_MD_get_params(const EVP_MD *digest, OSSL_PARAM params[])
+{
+ if (digest != NULL && digest->get_params != NULL)
+ return digest->get_params(params);
+ return 0;
+}
+
+const OSSL_PARAM *EVP_MD_gettable_params(const EVP_MD *digest)
+{
+ if (digest != NULL && digest->gettable_params != NULL)
+ return digest->gettable_params(
+ ossl_provider_ctx(EVP_MD_get0_provider(digest)));
+ return NULL;
+}
+
+int EVP_MD_CTX_set_params(EVP_MD_CTX *ctx, const OSSL_PARAM params[])
+{
+ EVP_PKEY_CTX *pctx = ctx->pctx;
+
+ /* If we have a pctx then we should try that first */
+ if (pctx != NULL
+ && (pctx->operation == EVP_PKEY_OP_VERIFYCTX
+ || pctx->operation == EVP_PKEY_OP_SIGNCTX)
+ && pctx->op.sig.algctx != NULL
+ && pctx->op.sig.signature->set_ctx_md_params != NULL)
+ return pctx->op.sig.signature->set_ctx_md_params(pctx->op.sig.algctx,
+ params);
+
+ if (ctx->digest != NULL && ctx->digest->set_ctx_params != NULL)
+ return ctx->digest->set_ctx_params(ctx->algctx, params);
+
+ return 0;
+}
+
+const OSSL_PARAM *EVP_MD_settable_ctx_params(const EVP_MD *md)
+{
+ void *provctx;
+
+ if (md != NULL && md->settable_ctx_params != NULL) {
+ provctx = ossl_provider_ctx(EVP_MD_get0_provider(md));
+ return md->settable_ctx_params(NULL, provctx);
+ }
+ return NULL;
+}
+
+const OSSL_PARAM *EVP_MD_CTX_settable_params(EVP_MD_CTX *ctx)
+{
+ EVP_PKEY_CTX *pctx;
+ void *alg;
+
+ if (ctx == NULL)
+ return NULL;
+
+ /* If we have a pctx then we should try that first */
+ pctx = ctx->pctx;
+ if (pctx != NULL
+ && (pctx->operation == EVP_PKEY_OP_VERIFYCTX
+ || pctx->operation == EVP_PKEY_OP_SIGNCTX)
+ && pctx->op.sig.algctx != NULL
+ && pctx->op.sig.signature->settable_ctx_md_params != NULL)
+ return pctx->op.sig.signature->settable_ctx_md_params(
+ pctx->op.sig.algctx);
+
+ if (ctx->digest != NULL && ctx->digest->settable_ctx_params != NULL) {
+ alg = ossl_provider_ctx(EVP_MD_get0_provider(ctx->digest));
+ return ctx->digest->settable_ctx_params(ctx->algctx, alg);
}
+
+ return NULL;
+}
+
+int EVP_MD_CTX_get_params(EVP_MD_CTX *ctx, OSSL_PARAM params[])
+{
+ EVP_PKEY_CTX *pctx = ctx->pctx;
+
+ /* If we have a pctx then we should try that first */
+ if (pctx != NULL
+ && (pctx->operation == EVP_PKEY_OP_VERIFYCTX
+ || pctx->operation == EVP_PKEY_OP_SIGNCTX)
+ && pctx->op.sig.algctx != NULL
+ && pctx->op.sig.signature->get_ctx_md_params != NULL)
+ return pctx->op.sig.signature->get_ctx_md_params(pctx->op.sig.algctx,
+ params);
+
+ if (ctx->digest != NULL && ctx->digest->get_params != NULL)
+ return ctx->digest->get_ctx_params(ctx->algctx, params);
+
return 0;
}
+
+const OSSL_PARAM *EVP_MD_gettable_ctx_params(const EVP_MD *md)
+{
+ void *provctx;
+
+ if (md != NULL && md->gettable_ctx_params != NULL) {
+ provctx = ossl_provider_ctx(EVP_MD_get0_provider(md));
+ return md->gettable_ctx_params(NULL, provctx);
+ }
+ return NULL;
+}
+
+const OSSL_PARAM *EVP_MD_CTX_gettable_params(EVP_MD_CTX *ctx)
+{
+ EVP_PKEY_CTX *pctx;
+ void *provctx;
+
+ if (ctx == NULL)
+ return NULL;
+
+ /* If we have a pctx then we should try that first */
+ pctx = ctx->pctx;
+ if (pctx != NULL
+ && (pctx->operation == EVP_PKEY_OP_VERIFYCTX
+ || pctx->operation == EVP_PKEY_OP_SIGNCTX)
+ && pctx->op.sig.algctx != NULL
+ && pctx->op.sig.signature->gettable_ctx_md_params != NULL)
+ return pctx->op.sig.signature->gettable_ctx_md_params(
+ pctx->op.sig.algctx);
+
+ if (ctx->digest != NULL && ctx->digest->gettable_ctx_params != NULL) {
+ provctx = ossl_provider_ctx(EVP_MD_get0_provider(ctx->digest));
+ return ctx->digest->gettable_ctx_params(ctx->algctx, provctx);
+ }
+ return NULL;
+}
+
+int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)
+{
+ int ret = EVP_CTRL_RET_UNSUPPORTED;
+ int set_params = 1;
+ size_t sz;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (ctx->digest != NULL && ctx->digest->prov == NULL)
+ goto legacy;
+
+ switch (cmd) {
+ case EVP_MD_CTRL_XOF_LEN:
+ sz = (size_t)p1;
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_XOFLEN, &sz);
+ break;
+ case EVP_MD_CTRL_MICALG:
+ set_params = 0;
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_DIGEST_PARAM_MICALG,
+ p2, p1 ? p1 : 9999);
+ break;
+ case EVP_CTRL_SSL3_MASTER_SECRET:
+ params[0] = OSSL_PARAM_construct_octet_string(OSSL_DIGEST_PARAM_SSL3_MS,
+ p2, p1);
+ break;
+ default:
+ goto conclude;
+ }
+
+ if (set_params)
+ ret = EVP_MD_CTX_set_params(ctx, params);
+ else
+ ret = EVP_MD_CTX_get_params(ctx, params);
+ goto conclude;
+
+
+ /* Code below to be removed when legacy support is dropped. */
+ legacy:
+ if (ctx->digest->md_ctrl == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_CTRL_NOT_IMPLEMENTED);
+ return 0;
+ }
+
+ ret = ctx->digest->md_ctrl(ctx, cmd, p1, p2);
+ conclude:
+ if (ret <= 0)
+ return 0;
+ return ret;
+}
+
+EVP_MD *evp_md_new(void)
+{
+ EVP_MD *md = OPENSSL_zalloc(sizeof(*md));
+
+ if (md != NULL) {
+ md->lock = CRYPTO_THREAD_lock_new();
+ if (md->lock == NULL) {
+ OPENSSL_free(md);
+ return NULL;
+ }
+ md->refcnt = 1;
+ }
+ return md;
+}
+
+/*
+ * FIPS module note: since internal fetches will be entirely
+ * provider based, we know that none of its code depends on legacy
+ * NIDs or any functionality that use them.
+ */
+#ifndef FIPS_MODULE
+static void set_legacy_nid(const char *name, void *vlegacy_nid)
+{
+ int nid;
+ int *legacy_nid = vlegacy_nid;
+ /*
+ * We use lowest level function to get the associated method, because
+ * higher level functions such as EVP_get_digestbyname() have changed
+ * to look at providers too.
+ */
+ const void *legacy_method = OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH);
+
+ if (*legacy_nid == -1) /* We found a clash already */
+ return;
+
+ if (legacy_method == NULL)
+ return;
+ nid = EVP_MD_nid(legacy_method);
+ if (*legacy_nid != NID_undef && *legacy_nid != nid) {
+ *legacy_nid = -1;
+ return;
+ }
+ *legacy_nid = nid;
+}
+#endif
+
+static int evp_md_cache_constants(EVP_MD *md)
+{
+ int ok, xof = 0, algid_absent = 0;
+ size_t blksz = 0;
+ size_t mdsize = 0;
+ OSSL_PARAM params[5];
+
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_BLOCK_SIZE, &blksz);
+ params[1] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &mdsize);
+ params[2] = OSSL_PARAM_construct_int(OSSL_DIGEST_PARAM_XOF, &xof);
+ params[3] = OSSL_PARAM_construct_int(OSSL_DIGEST_PARAM_ALGID_ABSENT,
+ &algid_absent);
+ params[4] = OSSL_PARAM_construct_end();
+ ok = evp_do_md_getparams(md, params) > 0;
+ if (mdsize > INT_MAX || blksz > INT_MAX)
+ ok = 0;
+ if (ok) {
+ md->block_size = (int)blksz;
+ md->md_size = (int)mdsize;
+ if (xof)
+ md->flags |= EVP_MD_FLAG_XOF;
+ if (algid_absent)
+ md->flags |= EVP_MD_FLAG_DIGALGID_ABSENT;
+ }
+ return ok;
+}
+
+static void *evp_md_from_algorithm(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
+{
+ const OSSL_DISPATCH *fns = algodef->implementation;
+ EVP_MD *md = NULL;
+ int fncnt = 0;
+
+ /* EVP_MD_fetch() will set the legacy NID if available */
+ if ((md = evp_md_new()) == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+#ifndef FIPS_MODULE
+ md->type = NID_undef;
+ if (!evp_names_do_all(prov, name_id, set_legacy_nid, &md->type)
+ || md->type == -1) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ EVP_MD_free(md);
+ return NULL;
+ }
+#endif
+
+ md->name_id = name_id;
+ if ((md->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
+ EVP_MD_free(md);
+ return NULL;
+ }
+ md->description = algodef->algorithm_description;
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_DIGEST_NEWCTX:
+ if (md->newctx == NULL) {
+ md->newctx = OSSL_FUNC_digest_newctx(fns);
+ fncnt++;
+ }
+ break;
+ case OSSL_FUNC_DIGEST_INIT:
+ if (md->dinit == NULL) {
+ md->dinit = OSSL_FUNC_digest_init(fns);
+ fncnt++;
+ }
+ break;
+ case OSSL_FUNC_DIGEST_UPDATE:
+ if (md->dupdate == NULL) {
+ md->dupdate = OSSL_FUNC_digest_update(fns);
+ fncnt++;
+ }
+ break;
+ case OSSL_FUNC_DIGEST_FINAL:
+ if (md->dfinal == NULL) {
+ md->dfinal = OSSL_FUNC_digest_final(fns);
+ fncnt++;
+ }
+ break;
+ case OSSL_FUNC_DIGEST_DIGEST:
+ if (md->digest == NULL)
+ md->digest = OSSL_FUNC_digest_digest(fns);
+ /* We don't increment fnct for this as it is stand alone */
+ break;
+ case OSSL_FUNC_DIGEST_FREECTX:
+ if (md->freectx == NULL) {
+ md->freectx = OSSL_FUNC_digest_freectx(fns);
+ fncnt++;
+ }
+ break;
+ case OSSL_FUNC_DIGEST_DUPCTX:
+ if (md->dupctx == NULL)
+ md->dupctx = OSSL_FUNC_digest_dupctx(fns);
+ break;
+ case OSSL_FUNC_DIGEST_GET_PARAMS:
+ if (md->get_params == NULL)
+ md->get_params = OSSL_FUNC_digest_get_params(fns);
+ break;
+ case OSSL_FUNC_DIGEST_SET_CTX_PARAMS:
+ if (md->set_ctx_params == NULL)
+ md->set_ctx_params = OSSL_FUNC_digest_set_ctx_params(fns);
+ break;
+ case OSSL_FUNC_DIGEST_GET_CTX_PARAMS:
+ if (md->get_ctx_params == NULL)
+ md->get_ctx_params = OSSL_FUNC_digest_get_ctx_params(fns);
+ break;
+ case OSSL_FUNC_DIGEST_GETTABLE_PARAMS:
+ if (md->gettable_params == NULL)
+ md->gettable_params = OSSL_FUNC_digest_gettable_params(fns);
+ break;
+ case OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS:
+ if (md->settable_ctx_params == NULL)
+ md->settable_ctx_params =
+ OSSL_FUNC_digest_settable_ctx_params(fns);
+ break;
+ case OSSL_FUNC_DIGEST_GETTABLE_CTX_PARAMS:
+ if (md->gettable_ctx_params == NULL)
+ md->gettable_ctx_params =
+ OSSL_FUNC_digest_gettable_ctx_params(fns);
+ break;
+ }
+ }
+ if ((fncnt != 0 && fncnt != 5)
+ || (fncnt == 0 && md->digest == NULL)) {
+ /*
+ * In order to be a consistent set of functions we either need the
+ * whole set of init/update/final etc functions or none of them.
+ * The "digest" function can standalone. We at least need one way to
+ * generate digests.
+ */
+ EVP_MD_free(md);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+ return NULL;
+ }
+ md->prov = prov;
+ if (prov != NULL)
+ ossl_provider_up_ref(prov);
+
+ if (!evp_md_cache_constants(md)) {
+ EVP_MD_free(md);
+ ERR_raise(ERR_LIB_EVP, EVP_R_CACHE_CONSTANTS_FAILED);
+ md = NULL;
+ }
+
+ return md;
+}
+
+static int evp_md_up_ref(void *md)
+{
+ return EVP_MD_up_ref(md);
+}
+
+static void evp_md_free(void *md)
+{
+ EVP_MD_free(md);
+}
+
+EVP_MD *EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties)
+{
+ EVP_MD *md =
+ evp_generic_fetch(ctx, OSSL_OP_DIGEST, algorithm, properties,
+ evp_md_from_algorithm, evp_md_up_ref, evp_md_free);
+
+ return md;
+}
+
+int EVP_MD_up_ref(EVP_MD *md)
+{
+ int ref = 0;
+
+ if (md->origin == EVP_ORIG_DYNAMIC)
+ CRYPTO_UP_REF(&md->refcnt, &ref, md->lock);
+ return 1;
+}
+
+void EVP_MD_free(EVP_MD *md)
+{
+ int i;
+
+ if (md == NULL || md->origin != EVP_ORIG_DYNAMIC)
+ return;
+
+ CRYPTO_DOWN_REF(&md->refcnt, &i, md->lock);
+ if (i > 0)
+ return;
+ evp_md_free_int(md);
+}
+
+void EVP_MD_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_MD *mac, void *arg),
+ void *arg)
+{
+ evp_generic_do_all(libctx, OSSL_OP_DIGEST,
+ (void (*)(void *, void *))fn, arg,
+ evp_md_from_algorithm, evp_md_up_ref, evp_md_free);
+}
diff --git a/crypto/evp/dsa_ctrl.c b/crypto/evp/dsa_ctrl.c
new file mode 100644
index 000000000000..531a21fa8d4d
--- /dev/null
+++ b/crypto/evp/dsa_ctrl.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include <openssl/core_names.h>
+#include <openssl/err.h>
+#include <openssl/dsa.h>
+#include <openssl/evp.h>
+#include "crypto/evp.h"
+
+static int dsa_paramgen_check(EVP_PKEY_CTX *ctx)
+{
+ if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+ /* If key type not DSA return error */
+ if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_DSA)
+ return -1;
+ return 1;
+}
+
+int EVP_PKEY_CTX_set_dsa_paramgen_type(EVP_PKEY_CTX *ctx, const char *name)
+{
+ int ret;
+ OSSL_PARAM params[2], *p = params;
+
+ if ((ret = dsa_paramgen_check(ctx)) <= 0)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE,
+ (char *)name, 0);
+ *p++ = OSSL_PARAM_construct_end();
+
+ return EVP_PKEY_CTX_set_params(ctx, params);
+}
+
+int EVP_PKEY_CTX_set_dsa_paramgen_gindex(EVP_PKEY_CTX *ctx, int gindex)
+{
+ int ret;
+ OSSL_PARAM params[2], *p = params;
+
+ if ((ret = dsa_paramgen_check(ctx)) <= 0)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_FFC_GINDEX, &gindex);
+ *p++ = OSSL_PARAM_construct_end();
+
+ return EVP_PKEY_CTX_set_params(ctx, params);
+}
+
+int EVP_PKEY_CTX_set_dsa_paramgen_seed(EVP_PKEY_CTX *ctx,
+ const unsigned char *seed,
+ size_t seedlen)
+{
+ int ret;
+ OSSL_PARAM params[2], *p = params;
+
+ if ((ret = dsa_paramgen_check(ctx)) <= 0)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_FFC_SEED,
+ (void *)seed, seedlen);
+ *p++ = OSSL_PARAM_construct_end();
+
+ return EVP_PKEY_CTX_set_params(ctx, params);
+}
+
+int EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX *ctx, int nbits)
+{
+ int ret;
+ OSSL_PARAM params[2], *p = params;
+ size_t bits = nbits;
+
+ if ((ret = dsa_paramgen_check(ctx)) <= 0)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_FFC_PBITS, &bits);
+ *p++ = OSSL_PARAM_construct_end();
+
+ return EVP_PKEY_CTX_set_params(ctx, params);
+}
+
+int EVP_PKEY_CTX_set_dsa_paramgen_q_bits(EVP_PKEY_CTX *ctx, int qbits)
+{
+ int ret;
+ OSSL_PARAM params[2], *p = params;
+ size_t bits2 = qbits;
+
+ if ((ret = dsa_paramgen_check(ctx)) <= 0)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_FFC_QBITS, &bits2);
+ *p++ = OSSL_PARAM_construct_end();
+
+ return EVP_PKEY_CTX_set_params(ctx, params);
+}
+
+int EVP_PKEY_CTX_set_dsa_paramgen_md_props(EVP_PKEY_CTX *ctx,
+ const char *md_name,
+ const char *md_properties)
+{
+ int ret;
+ OSSL_PARAM params[3], *p = params;
+
+ if ((ret = dsa_paramgen_check(ctx)) <= 0)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST,
+ (char *)md_name, 0);
+ if (md_properties != NULL)
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST_PROPS,
+ (char *)md_properties, 0);
+ *p++ = OSSL_PARAM_construct_end();
+
+ return EVP_PKEY_CTX_set_params(ctx, params);
+}
+
+#if !defined(FIPS_MODULE)
+int EVP_PKEY_CTX_set_dsa_paramgen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0, (void *)(md));
+}
+#endif
diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c
index a1d3ab90fa61..52b9e87c1e2b 100644
--- a/crypto/evp/e_aes.c
+++ b/crypto/evp/e_aes.c
@@ -1,27 +1,37 @@
/*
* Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * This file uses the low level AES functions (which are deprecated for
+ * non-internal use) in order to implement the EVP AES ciphers.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h>
+#include <assert.h>
#include <openssl/opensslconf.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/err.h>
-#include <string.h>
-#include <assert.h>
#include <openssl/aes.h>
-#include "crypto/evp.h"
-#include "modes_local.h"
#include <openssl/rand.h>
+#include <openssl/cmac.h>
+#include "crypto/evp.h"
+#include "internal/cryptlib.h"
+#include "crypto/modes.h"
+#include "crypto/siv.h"
+#include "crypto/aes_platform.h"
#include "evp_local.h"
typedef struct {
union {
- double align;
+ OSSL_UNION_ALIGN;
AES_KEY ks;
} ks;
block128_f block;
@@ -33,7 +43,7 @@ typedef struct {
typedef struct {
union {
- double align;
+ OSSL_UNION_ALIGN;
AES_KEY ks;
} ks; /* AES key schedule to use */
int key_set; /* Set if key initialised */
@@ -43,13 +53,15 @@ typedef struct {
int ivlen; /* IV length */
int taglen;
int iv_gen; /* It is OK to generate IVs */
+ int iv_gen_rand; /* No IV was specified, so generate a rand IV */
int tls_aad_len; /* TLS AAD length */
+ uint64_t tls_enc_records; /* Number of TLS records encrypted */
ctr128_f ctr;
} EVP_AES_GCM_CTX;
typedef struct {
union {
- double align;
+ OSSL_UNION_ALIGN;
AES_KEY ks;
} ks1, ks2; /* AES key schedules to use */
XTS128_CONTEXT xts;
@@ -59,9 +71,15 @@ typedef struct {
const unsigned char iv[16]);
} EVP_AES_XTS_CTX;
+#ifdef FIPS_MODULE
+static const int allow_insecure_decrypt = 0;
+#else
+static const int allow_insecure_decrypt = 1;
+#endif
+
typedef struct {
union {
- double align;
+ OSSL_UNION_ALIGN;
AES_KEY ks;
} ks; /* AES key schedule to use */
int key_set; /* Set if key initialised */
@@ -77,11 +95,11 @@ typedef struct {
#ifndef OPENSSL_NO_OCB
typedef struct {
union {
- double align;
+ OSSL_UNION_ALIGN;
AES_KEY ks;
} ksenc; /* AES key schedule to use for encryption */
union {
- double align;
+ OSSL_UNION_ALIGN;
AES_KEY ks;
} ksdec; /* AES key schedule to use for decryption */
int key_set; /* Set if key initialised */
@@ -100,50 +118,6 @@ typedef struct {
#define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4))
-#ifdef VPAES_ASM
-int vpaes_set_encrypt_key(const unsigned char *userKey, int bits,
- AES_KEY *key);
-int vpaes_set_decrypt_key(const unsigned char *userKey, int bits,
- AES_KEY *key);
-
-void vpaes_encrypt(const unsigned char *in, unsigned char *out,
- const AES_KEY *key);
-void vpaes_decrypt(const unsigned char *in, unsigned char *out,
- const AES_KEY *key);
-
-void vpaes_cbc_encrypt(const unsigned char *in,
- unsigned char *out,
- size_t length,
- const AES_KEY *key, unsigned char *ivec, int enc);
-#endif
-#ifdef BSAES_ASM
-void bsaes_cbc_encrypt(const unsigned char *in, unsigned char *out,
- size_t length, const AES_KEY *key,
- unsigned char ivec[16], int enc);
-void bsaes_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
- size_t len, const AES_KEY *key,
- const unsigned char ivec[16]);
-void bsaes_xts_encrypt(const unsigned char *inp, unsigned char *out,
- size_t len, const AES_KEY *key1,
- const AES_KEY *key2, const unsigned char iv[16]);
-void bsaes_xts_decrypt(const unsigned char *inp, unsigned char *out,
- size_t len, const AES_KEY *key1,
- const AES_KEY *key2, const unsigned char iv[16]);
-#endif
-#ifdef AES_CTR_ASM
-void AES_ctr32_encrypt(const unsigned char *in, unsigned char *out,
- size_t blocks, const AES_KEY *key,
- const unsigned char ivec[AES_BLOCK_SIZE]);
-#endif
-#ifdef AES_XTS_ASM
-void AES_xts_encrypt(const unsigned char *inp, unsigned char *out, size_t len,
- const AES_KEY *key1, const AES_KEY *key2,
- const unsigned char iv[16]);
-void AES_xts_decrypt(const unsigned char *inp, unsigned char *out, size_t len,
- const AES_KEY *key1, const AES_KEY *key2,
- const unsigned char iv[16]);
-#endif
-
/* increment counter (64-bit int) by 1 */
static void ctr64_inc(unsigned char *counter)
{
@@ -160,105 +134,8 @@ static void ctr64_inc(unsigned char *counter)
} while (n);
}
-#if defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC))
-# include "ppc_arch.h"
-# ifdef VPAES_ASM
-# define VPAES_CAPABLE (OPENSSL_ppccap_P & PPC_ALTIVEC)
-# endif
-# define HWAES_CAPABLE (OPENSSL_ppccap_P & PPC_CRYPTO207)
-# define HWAES_set_encrypt_key aes_p8_set_encrypt_key
-# define HWAES_set_decrypt_key aes_p8_set_decrypt_key
-# define HWAES_encrypt aes_p8_encrypt
-# define HWAES_decrypt aes_p8_decrypt
-# define HWAES_cbc_encrypt aes_p8_cbc_encrypt
-# define HWAES_ctr32_encrypt_blocks aes_p8_ctr32_encrypt_blocks
-# define HWAES_xts_encrypt aes_p8_xts_encrypt
-# define HWAES_xts_decrypt aes_p8_xts_decrypt
-#endif
-
-#if defined(OPENSSL_CPUID_OBJ) && ( \
- ((defined(__i386) || defined(__i386__) || \
- defined(_M_IX86)) && defined(OPENSSL_IA32_SSE2))|| \
- defined(__x86_64) || defined(__x86_64__) || \
- defined(_M_AMD64) || defined(_M_X64) )
-
-extern unsigned int OPENSSL_ia32cap_P[];
-
-# ifdef VPAES_ASM
-# define VPAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
-# endif
-# ifdef BSAES_ASM
-# define BSAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
-# endif
-/*
- * AES-NI section
- */
-# define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32)))
-
-int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
- AES_KEY *key);
-int aesni_set_decrypt_key(const unsigned char *userKey, int bits,
- AES_KEY *key);
-
-void aesni_encrypt(const unsigned char *in, unsigned char *out,
- const AES_KEY *key);
-void aesni_decrypt(const unsigned char *in, unsigned char *out,
- const AES_KEY *key);
-
-void aesni_ecb_encrypt(const unsigned char *in,
- unsigned char *out,
- size_t length, const AES_KEY *key, int enc);
-void aesni_cbc_encrypt(const unsigned char *in,
- unsigned char *out,
- size_t length,
- const AES_KEY *key, unsigned char *ivec, int enc);
-
-void aesni_ctr32_encrypt_blocks(const unsigned char *in,
- unsigned char *out,
- size_t blocks,
- const void *key, const unsigned char *ivec);
-
-void aesni_xts_encrypt(const unsigned char *in,
- unsigned char *out,
- size_t length,
- const AES_KEY *key1, const AES_KEY *key2,
- const unsigned char iv[16]);
-
-void aesni_xts_decrypt(const unsigned char *in,
- unsigned char *out,
- size_t length,
- const AES_KEY *key1, const AES_KEY *key2,
- const unsigned char iv[16]);
-
-void aesni_ccm64_encrypt_blocks(const unsigned char *in,
- unsigned char *out,
- size_t blocks,
- const void *key,
- const unsigned char ivec[16],
- unsigned char cmac[16]);
-
-void aesni_ccm64_decrypt_blocks(const unsigned char *in,
- unsigned char *out,
- size_t blocks,
- const void *key,
- const unsigned char ivec[16],
- unsigned char cmac[16]);
-
+#if defined(AESNI_CAPABLE)
# if defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
-size_t aesni_gcm_encrypt(const unsigned char *in,
- unsigned char *out,
- size_t len,
- const void *key, unsigned char ivec[16], u64 *Xi);
-# define AES_gcm_encrypt aesni_gcm_encrypt
-size_t aesni_gcm_decrypt(const unsigned char *in,
- unsigned char *out,
- size_t len,
- const void *key, unsigned char ivec[16], u64 *Xi);
-# define AES_gcm_decrypt aesni_gcm_decrypt
-void gcm_ghash_avx(u64 Xi[2], const u128 Htable[16], const u8 *in,
- size_t len);
-# define AES_GCM_ASM(gctx) (gctx->ctr==aesni_ctr32_encrypt_blocks && \
- gctx->gcm.ghash==gcm_ghash_avx)
# define AES_GCM_ASM2(gctx) (gctx->gcm.block==(block128_f)aesni_encrypt && \
gctx->gcm.ghash==gcm_ghash_avx)
# undef AES_GCM_ASM2 /* minor size optimization */
@@ -270,16 +147,18 @@ static int aesni_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
int ret, mode;
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
- mode = EVP_CIPHER_CTX_mode(ctx);
+ mode = EVP_CIPHER_CTX_get_mode(ctx);
if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
&& !enc) {
- ret = aesni_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ ret = aesni_set_decrypt_key(key,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) aesni_decrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) aesni_cbc_encrypt : NULL;
} else {
- ret = aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ ret = aesni_set_encrypt_key(key,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) aesni_encrypt;
if (mode == EVP_CIPH_CBC_MODE)
@@ -291,7 +170,7 @@ static int aesni_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
}
if (ret < 0) {
- EVPerr(EVP_F_AESNI_INIT_KEY, EVP_R_AES_KEY_SETUP_FAILED);
+ ERR_raise(ERR_LIB_EVP, EVP_R_AES_KEY_SETUP_FAILED);
return 0;
}
@@ -302,8 +181,7 @@ static int aesni_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
aesni_cbc_encrypt(in, out, len, &EVP_C_DATA(EVP_AES_KEY,ctx)->ks.ks,
- EVP_CIPHER_CTX_iv_noconst(ctx),
- EVP_CIPHER_CTX_encrypting(ctx));
+ ctx->iv, EVP_CIPHER_CTX_is_encrypting(ctx));
return 1;
}
@@ -311,13 +189,13 @@ static int aesni_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int aesni_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
- size_t bl = EVP_CIPHER_CTX_block_size(ctx);
+ size_t bl = EVP_CIPHER_CTX_get_block_size(ctx);
if (len < bl)
return 1;
aesni_ecb_encrypt(in, out, len, &EVP_C_DATA(EVP_AES_KEY,ctx)->ks.ks,
- EVP_CIPHER_CTX_encrypting(ctx));
+ EVP_CIPHER_CTX_is_encrypting(ctx));
return 1;
}
@@ -349,7 +227,7 @@ static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
if (!iv && !key)
return 1;
if (key) {
- aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) aesni_encrypt);
gctx->ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
@@ -389,35 +267,33 @@ static int aesni_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
if (key) {
/* The key is two half length keys in reality */
- const int bytes = EVP_CIPHER_CTX_key_length(ctx) / 2;
+ const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2;
+ const int bits = bytes * 8;
/*
* Verify that the two keys are different.
- *
+ *
* This addresses Rogaway's vulnerability.
* See comment in aes_xts_init_key() below.
*/
- if (enc && CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
- EVPerr(EVP_F_AESNI_XTS_INIT_KEY, EVP_R_XTS_DUPLICATED_KEYS);
+ if ((!allow_insecure_decrypt || enc)
+ && CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_XTS_DUPLICATED_KEYS);
return 0;
}
/* key_len is two AES keys */
if (enc) {
- aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4,
- &xctx->ks1.ks);
+ aesni_set_encrypt_key(key, bits, &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) aesni_encrypt;
xctx->stream = aesni_xts_encrypt;
} else {
- aesni_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4,
- &xctx->ks1.ks);
+ aesni_set_decrypt_key(key, bits, &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) aesni_decrypt;
xctx->stream = aesni_xts_decrypt;
}
- aesni_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2,
- EVP_CIPHER_CTX_key_length(ctx) * 4,
- &xctx->ks2.ks);
+ aesni_set_encrypt_key(key + bytes, bits, &xctx->ks2.ks);
xctx->xts.block2 = (block128_f) aesni_encrypt;
xctx->xts.key1 = &xctx->ks1;
@@ -425,7 +301,7 @@ static int aesni_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
if (iv) {
xctx->xts.key2 = &xctx->ks2;
- memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 16);
+ memcpy(ctx->iv, iv, 16);
}
return 1;
@@ -442,7 +318,7 @@ static int aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
if (!iv && !key)
return 1;
if (key) {
- aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
&cctx->ks, (block128_f) aesni_encrypt);
@@ -451,7 +327,7 @@ static int aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
cctx->key_set = 1;
}
if (iv) {
- memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L);
+ memcpy(ctx->iv, iv, 15 - cctx->L);
cctx->iv_set = 1;
}
return 1;
@@ -462,19 +338,6 @@ static int aesni_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# ifndef OPENSSL_NO_OCB
-void aesni_ocb_encrypt(const unsigned char *in, unsigned char *out,
- size_t blocks, const void *key,
- size_t start_block_num,
- unsigned char offset_i[16],
- const unsigned char L_[][16],
- unsigned char checksum[16]);
-void aesni_ocb_decrypt(const unsigned char *in, unsigned char *out,
- size_t blocks, const void *key,
- size_t start_block_num,
- unsigned char offset_i[16],
- const unsigned char L_[][16],
- unsigned char checksum[16]);
-
static int aesni_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
@@ -488,9 +351,9 @@ static int aesni_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
* needs both. We could possibly optimise to remove setting the
* decrypt for an encryption operation.
*/
- aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&octx->ksenc.ks);
- aesni_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ aesni_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&octx->ksdec.ks);
if (!CRYPTO_ocb128_init(&octx->ocb,
&octx->ksenc.ks, &octx->ksdec.ks,
@@ -534,6 +397,7 @@ static int aesni_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static const EVP_CIPHER aesni_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
aesni_init_key, \
aesni_##mode##_cipher, \
NULL, \
@@ -541,8 +405,9 @@ static const EVP_CIPHER aesni_##keylen##_##mode = { \
NULL,NULL,NULL,NULL }; \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize, \
- keylen/8,ivlen, \
+ keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
aes_init_key, \
aes_##mode##_cipher, \
NULL, \
@@ -554,8 +419,10 @@ const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
static const EVP_CIPHER aesni_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
- (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
+ (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
+ ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
aesni_##mode##_init_key, \
aesni_##mode##_cipher, \
aes_##mode##_cleanup, \
@@ -563,8 +430,10 @@ static const EVP_CIPHER aesni_##keylen##_##mode = { \
NULL,NULL,aes_##mode##_ctrl,NULL }; \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
- (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
+ (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
+ ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
aes_##mode##_init_key, \
aes_##mode##_cipher, \
aes_##mode##_cleanup, \
@@ -573,81 +442,7 @@ static const EVP_CIPHER aes_##keylen##_##mode = { \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; }
-#elif defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
-
-# include "sparc_arch.h"
-
-extern unsigned int OPENSSL_sparcv9cap_P[];
-
-/*
- * Initial Fujitsu SPARC64 X support
- */
-# define HWAES_CAPABLE (OPENSSL_sparcv9cap_P[0] & SPARCV9_FJAESX)
-# define HWAES_set_encrypt_key aes_fx_set_encrypt_key
-# define HWAES_set_decrypt_key aes_fx_set_decrypt_key
-# define HWAES_encrypt aes_fx_encrypt
-# define HWAES_decrypt aes_fx_decrypt
-# define HWAES_cbc_encrypt aes_fx_cbc_encrypt
-# define HWAES_ctr32_encrypt_blocks aes_fx_ctr32_encrypt_blocks
-
-# define SPARC_AES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_AES)
-
-void aes_t4_set_encrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
-void aes_t4_set_decrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
-void aes_t4_encrypt(const unsigned char *in, unsigned char *out,
- const AES_KEY *key);
-void aes_t4_decrypt(const unsigned char *in, unsigned char *out,
- const AES_KEY *key);
-/*
- * Key-length specific subroutines were chosen for following reason.
- * Each SPARC T4 core can execute up to 8 threads which share core's
- * resources. Loading as much key material to registers allows to
- * minimize references to shared memory interface, as well as amount
- * of instructions in inner loops [much needed on T4]. But then having
- * non-key-length specific routines would require conditional branches
- * either in inner loops or on subroutines' entries. Former is hardly
- * acceptable, while latter means code size increase to size occupied
- * by multiple key-length specific subroutines, so why fight?
- */
-void aes128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
- size_t len, const AES_KEY *key,
- unsigned char *ivec, int /*unused*/);
-void aes128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
- size_t len, const AES_KEY *key,
- unsigned char *ivec, int /*unused*/);
-void aes192_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
- size_t len, const AES_KEY *key,
- unsigned char *ivec, int /*unused*/);
-void aes192_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
- size_t len, const AES_KEY *key,
- unsigned char *ivec, int /*unused*/);
-void aes256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
- size_t len, const AES_KEY *key,
- unsigned char *ivec, int /*unused*/);
-void aes256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
- size_t len, const AES_KEY *key,
- unsigned char *ivec, int /*unused*/);
-void aes128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
- size_t blocks, const AES_KEY *key,
- unsigned char *ivec);
-void aes192_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
- size_t blocks, const AES_KEY *key,
- unsigned char *ivec);
-void aes256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
- size_t blocks, const AES_KEY *key,
- unsigned char *ivec);
-void aes128_t4_xts_encrypt(const unsigned char *in, unsigned char *out,
- size_t blocks, const AES_KEY *key1,
- const AES_KEY *key2, const unsigned char *ivec);
-void aes128_t4_xts_decrypt(const unsigned char *in, unsigned char *out,
- size_t blocks, const AES_KEY *key1,
- const AES_KEY *key2, const unsigned char *ivec);
-void aes256_t4_xts_encrypt(const unsigned char *in, unsigned char *out,
- size_t blocks, const AES_KEY *key1,
- const AES_KEY *key2, const unsigned char *ivec);
-void aes256_t4_xts_decrypt(const unsigned char *in, unsigned char *out,
- size_t blocks, const AES_KEY *key1,
- const AES_KEY *key2, const unsigned char *ivec);
+#elif defined(SPARC_AES_CAPABLE)
static int aes_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
@@ -655,8 +450,8 @@ static int aes_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
int ret, mode, bits;
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
- mode = EVP_CIPHER_CTX_mode(ctx);
- bits = EVP_CIPHER_CTX_key_length(ctx) * 8;
+ mode = EVP_CIPHER_CTX_get_mode(ctx);
+ bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8;
if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
&& !enc) {
ret = 0;
@@ -713,7 +508,7 @@ static int aes_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
}
if (ret < 0) {
- EVPerr(EVP_F_AES_T4_INIT_KEY, EVP_R_AES_KEY_SETUP_FAILED);
+ ERR_raise(ERR_LIB_EVP, EVP_R_AES_KEY_SETUP_FAILED);
return 0;
}
@@ -755,7 +550,7 @@ static int aes_t4_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
if (!iv && !key)
return 1;
if (key) {
- int bits = EVP_CIPHER_CTX_key_length(ctx) * 8;
+ int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8;
aes_t4_set_encrypt_key(key, bits, &gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
(block128_f) aes_t4_encrypt);
@@ -808,17 +603,18 @@ static int aes_t4_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
if (key) {
/* The key is two half length keys in reality */
- const int bytes = EVP_CIPHER_CTX_key_length(ctx) / 2;
+ const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2;
const int bits = bytes * 8;
/*
* Verify that the two keys are different.
- *
+ *
* This addresses Rogaway's vulnerability.
* See comment in aes_xts_init_key() below.
*/
- if (enc && CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
- EVPerr(EVP_F_AES_T4_XTS_INIT_KEY, EVP_R_XTS_DUPLICATED_KEYS);
+ if ((!allow_insecure_decrypt || enc)
+ && CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_XTS_DUPLICATED_KEYS);
return 0;
}
@@ -838,8 +634,7 @@ static int aes_t4_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
return 0;
}
} else {
- aes_t4_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4,
- &xctx->ks1.ks);
+ aes_t4_set_decrypt_key(key, bits, &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) aes_t4_decrypt;
switch (bits) {
case 128:
@@ -853,9 +648,7 @@ static int aes_t4_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
}
}
- aes_t4_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2,
- EVP_CIPHER_CTX_key_length(ctx) * 4,
- &xctx->ks2.ks);
+ aes_t4_set_encrypt_key(key + bytes, bits, &xctx->ks2.ks);
xctx->xts.block2 = (block128_f) aes_t4_encrypt;
xctx->xts.key1 = &xctx->ks1;
@@ -863,7 +656,7 @@ static int aes_t4_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
if (iv) {
xctx->xts.key2 = &xctx->ks2;
- memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 16);
+ memcpy(ctx->iv, iv, 16);
}
return 1;
@@ -880,7 +673,7 @@ static int aes_t4_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
if (!iv && !key)
return 1;
if (key) {
- int bits = EVP_CIPHER_CTX_key_length(ctx) * 8;
+ int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8;
aes_t4_set_encrypt_key(key, bits, &cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
&cctx->ks, (block128_f) aes_t4_encrypt);
@@ -888,7 +681,7 @@ static int aes_t4_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
cctx->key_set = 1;
}
if (iv) {
- memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L);
+ memcpy(ctx->iv, iv, 15 - cctx->L);
cctx->iv_set = 1;
}
return 1;
@@ -912,9 +705,9 @@ static int aes_t4_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
* needs both. We could possibly optimise to remove setting the
* decrypt for an encryption operation.
*/
- aes_t4_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ aes_t4_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&octx->ksenc.ks);
- aes_t4_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ aes_t4_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&octx->ksdec.ks);
if (!CRYPTO_ocb128_init(&octx->ocb,
&octx->ksenc.ks, &octx->ksdec.ks,
@@ -953,10 +746,16 @@ static int aes_t4_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# endif /* OPENSSL_NO_OCB */
+# ifndef OPENSSL_NO_SIV
+# define aes_t4_siv_init_key aes_siv_init_key
+# define aes_t4_siv_cipher aes_siv_cipher
+# endif /* OPENSSL_NO_SIV */
+
# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
static const EVP_CIPHER aes_t4_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
aes_t4_init_key, \
aes_t4_##mode##_cipher, \
NULL, \
@@ -966,6 +765,7 @@ static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize, \
keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
aes_init_key, \
aes_##mode##_cipher, \
NULL, \
@@ -977,8 +777,10 @@ const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
static const EVP_CIPHER aes_t4_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
- (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
+ (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
+ ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
aes_t4_##mode##_init_key, \
aes_t4_##mode##_cipher, \
aes_##mode##_cleanup, \
@@ -986,8 +788,10 @@ static const EVP_CIPHER aes_t4_##keylen##_##mode = { \
NULL,NULL,aes_##mode##_ctrl,NULL }; \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
- (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
+ (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
+ ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
aes_##mode##_init_key, \
aes_##mode##_cipher, \
aes_##mode##_cleanup, \
@@ -996,15 +800,11 @@ static const EVP_CIPHER aes_##keylen##_##mode = { \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return SPARC_AES_CAPABLE?&aes_t4_##keylen##_##mode:&aes_##keylen##_##mode; }
-#elif defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
-/*
- * IBM S390X support
- */
-# include "s390x_arch.h"
-
+#elif defined(S390X_aes_128_CAPABLE)
+/* IBM S390X support */
typedef struct {
union {
- double align;
+ OSSL_UNION_ALIGN;
/*-
* KM-AES parameter block - begin
* (see z/Architecture Principles of Operation >= SA22-7832-06)
@@ -1019,7 +819,7 @@ typedef struct {
typedef struct {
union {
- double align;
+ OSSL_UNION_ALIGN;
/*-
* KMO-AES parameter block - begin
* (see z/Architecture Principles of Operation >= SA22-7832-08)
@@ -1037,7 +837,7 @@ typedef struct {
typedef struct {
union {
- double align;
+ OSSL_UNION_ALIGN;
/*-
* KMF-AES parameter block - begin
* (see z/Architecture Principles of Operation >= SA22-7832-08)
@@ -1055,7 +855,7 @@ typedef struct {
typedef struct {
union {
- double align;
+ OSSL_UNION_ALIGN;
/*-
* KMA-GCM-AES parameter block - begin
* (see z/Architecture Principles of Operation >= SA22-7832-11)
@@ -1099,11 +899,12 @@ typedef struct {
int kreslen;
int tls_aad_len;
+ uint64_t tls_enc_records; /* Number of TLS records encrypted */
} S390X_AES_GCM_CTX;
typedef struct {
union {
- double align;
+ OSSL_UNION_ALIGN;
/*-
* Padding is chosen so that ccm.kmac_param.k overlaps with key.k and
* ccm.fc with key.k.rounds. Remember that on s390x, an AES_KEY's
@@ -1153,25 +954,11 @@ typedef struct {
} aes;
} S390X_AES_CCM_CTX;
-/* Convert key size to function code: [16,24,32] -> [18,19,20]. */
-# define S390X_AES_FC(keylen) (S390X_AES_128 + ((((keylen) << 3) - 128) >> 6))
-
-/* Most modes of operation need km for partial block processing. */
-# define S390X_aes_128_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
- S390X_CAPBIT(S390X_AES_128))
-# define S390X_aes_192_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
- S390X_CAPBIT(S390X_AES_192))
-# define S390X_aes_256_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
- S390X_CAPBIT(S390X_AES_256))
-
# define s390x_aes_init_key aes_init_key
static int s390x_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
-# define S390X_aes_128_cbc_CAPABLE 0 /* checked by callee */
-# define S390X_aes_192_cbc_CAPABLE 0
-# define S390X_aes_256_cbc_CAPABLE 0
-# define S390X_AES_CBC_CTX EVP_AES_KEY
+# define S390X_AES_CBC_CTX EVP_AES_KEY
# define s390x_aes_cbc_init_key aes_init_key
@@ -1179,22 +966,18 @@ static int s390x_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
static int s390x_aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
-# define S390X_aes_128_ecb_CAPABLE S390X_aes_128_CAPABLE
-# define S390X_aes_192_ecb_CAPABLE S390X_aes_192_CAPABLE
-# define S390X_aes_256_ecb_CAPABLE S390X_aes_256_CAPABLE
-
static int s390x_aes_ecb_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv, int enc)
{
S390X_AES_ECB_CTX *cctx = EVP_C_DATA(S390X_AES_ECB_CTX, ctx);
- const int keylen = EVP_CIPHER_CTX_key_length(ctx);
-
- cctx->fc = S390X_AES_FC(keylen) | (enc ? 0 : S390X_DECRYPT);
+ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
- if (key != NULL)
- memcpy(cctx->km.param.k, key, keylen);
+ cctx->fc = S390X_AES_FC(keylen);
+ if (!enc)
+ cctx->fc |= S390X_DECRYPT;
+ memcpy(cctx->km.param.k, key, keylen);
return 1;
}
@@ -1207,32 +990,19 @@ static int s390x_aes_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return 1;
}
-# define S390X_aes_128_ofb_CAPABLE (S390X_aes_128_CAPABLE && \
- (OPENSSL_s390xcap_P.kmo[0] & \
- S390X_CAPBIT(S390X_AES_128)))
-# define S390X_aes_192_ofb_CAPABLE (S390X_aes_192_CAPABLE && \
- (OPENSSL_s390xcap_P.kmo[0] & \
- S390X_CAPBIT(S390X_AES_192)))
-# define S390X_aes_256_ofb_CAPABLE (S390X_aes_256_CAPABLE && \
- (OPENSSL_s390xcap_P.kmo[0] & \
- S390X_CAPBIT(S390X_AES_256)))
-
static int s390x_aes_ofb_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *ivec, int enc)
{
S390X_AES_OFB_CTX *cctx = EVP_C_DATA(S390X_AES_OFB_CTX, ctx);
- const unsigned char *oiv = EVP_CIPHER_CTX_original_iv(ctx);
- const int keylen = EVP_CIPHER_CTX_key_length(ctx);
- const int ivlen = EVP_CIPHER_CTX_iv_length(ctx);
+ const unsigned char *iv = ctx->oiv;
+ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
+ const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
+ memcpy(cctx->kmo.param.cv, iv, ivlen);
+ memcpy(cctx->kmo.param.k, key, keylen);
cctx->fc = S390X_AES_FC(keylen);
-
- if (key != NULL)
- memcpy(cctx->kmo.param.k, key, keylen);
-
cctx->res = 0;
- memcpy(cctx->kmo.param.cv, oiv, ivlen);
return 1;
}
@@ -1240,7 +1010,7 @@ static int s390x_aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
S390X_AES_OFB_CTX *cctx = EVP_C_DATA(S390X_AES_OFB_CTX, ctx);
- const int ivlen = EVP_CIPHER_CTX_iv_length(ctx);
+ const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
int n = cctx->res;
int rem;
@@ -1279,33 +1049,23 @@ static int s390x_aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return 1;
}
-# define S390X_aes_128_cfb_CAPABLE (S390X_aes_128_CAPABLE && \
- (OPENSSL_s390xcap_P.kmf[0] & \
- S390X_CAPBIT(S390X_AES_128)))
-# define S390X_aes_192_cfb_CAPABLE (S390X_aes_192_CAPABLE && \
- (OPENSSL_s390xcap_P.kmf[0] & \
- S390X_CAPBIT(S390X_AES_192)))
-# define S390X_aes_256_cfb_CAPABLE (S390X_aes_256_CAPABLE && \
- (OPENSSL_s390xcap_P.kmf[0] & \
- S390X_CAPBIT(S390X_AES_256)))
-
static int s390x_aes_cfb_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *ivec, int enc)
{
S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
- const unsigned char *oiv = EVP_CIPHER_CTX_original_iv(ctx);
- const int keylen = EVP_CIPHER_CTX_key_length(ctx);
- const int ivlen = EVP_CIPHER_CTX_iv_length(ctx);
-
- cctx->fc = S390X_AES_FC(keylen) | (enc ? 0 : S390X_DECRYPT)
- | (16 << 24); /* 16 bytes cipher feedback */
+ const unsigned char *iv = ctx->oiv;
+ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
+ const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
- if (key != NULL)
- memcpy(cctx->kmf.param.k, key, keylen);
+ cctx->fc = S390X_AES_FC(keylen);
+ cctx->fc |= 16 << 24; /* 16 bytes cipher feedback */
+ if (!enc)
+ cctx->fc |= S390X_DECRYPT;
cctx->res = 0;
- memcpy(cctx->kmf.param.cv, oiv, ivlen);
+ memcpy(cctx->kmf.param.cv, iv, ivlen);
+ memcpy(cctx->kmf.param.k, key, keylen);
return 1;
}
@@ -1313,9 +1073,9 @@ static int s390x_aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
- const int keylen = EVP_CIPHER_CTX_key_length(ctx);
- const int enc = EVP_CIPHER_CTX_encrypting(ctx);
- const int ivlen = EVP_CIPHER_CTX_iv_length(ctx);
+ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
+ const int enc = EVP_CIPHER_CTX_is_encrypting(ctx);
+ const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
int n = cctx->res;
int rem;
@@ -1359,30 +1119,22 @@ static int s390x_aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return 1;
}
-# define S390X_aes_128_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
- S390X_CAPBIT(S390X_AES_128))
-# define S390X_aes_192_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
- S390X_CAPBIT(S390X_AES_192))
-# define S390X_aes_256_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
- S390X_CAPBIT(S390X_AES_256))
-
static int s390x_aes_cfb8_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *ivec, int enc)
{
S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
- const unsigned char *oiv = EVP_CIPHER_CTX_original_iv(ctx);
- const int keylen = EVP_CIPHER_CTX_key_length(ctx);
- const int ivlen = EVP_CIPHER_CTX_iv_length(ctx);
+ const unsigned char *iv = ctx->oiv;
+ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
+ const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
- cctx->fc = S390X_AES_FC(keylen) | (enc ? 0 : S390X_DECRYPT)
- | (1 << 24); /* 1 byte cipher feedback flag */
-
- if (key != NULL)
- memcpy(cctx->kmf.param.k, key, keylen);
+ cctx->fc = S390X_AES_FC(keylen);
+ cctx->fc |= 1 << 24; /* 1 byte cipher feedback */
+ if (!enc)
+ cctx->fc |= S390X_DECRYPT;
- cctx->res = 0;
- memcpy(cctx->kmf.param.cv, oiv, ivlen);
+ memcpy(cctx->kmf.param.cv, iv, ivlen);
+ memcpy(cctx->kmf.param.k, key, keylen);
return 1;
}
@@ -1390,7 +1142,7 @@ static int s390x_aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
- const int ivlen = EVP_CIPHER_CTX_iv_length(ctx);
+ const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
memcpy(cctx->kmf.param.cv, iv, ivlen);
@@ -1399,20 +1151,13 @@ static int s390x_aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return 1;
}
-# define S390X_aes_128_cfb1_CAPABLE 0
-# define S390X_aes_192_cfb1_CAPABLE 0
-# define S390X_aes_256_cfb1_CAPABLE 0
-
# define s390x_aes_cfb1_init_key aes_init_key
# define s390x_aes_cfb1_cipher aes_cfb1_cipher
static int s390x_aes_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
-# define S390X_aes_128_ctr_CAPABLE 0 /* checked by callee */
-# define S390X_aes_192_ctr_CAPABLE 0
-# define S390X_aes_256_ctr_CAPABLE 0
-# define S390X_AES_CTR_CTX EVP_AES_KEY
+# define S390X_AES_CTR_CTX EVP_AES_KEY
# define s390x_aes_ctr_init_key aes_init_key
@@ -1420,18 +1165,8 @@ static int s390x_aes_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int s390x_aes_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
-# define S390X_aes_128_gcm_CAPABLE (S390X_aes_128_CAPABLE && \
- (OPENSSL_s390xcap_P.kma[0] & \
- S390X_CAPBIT(S390X_AES_128)))
-# define S390X_aes_192_gcm_CAPABLE (S390X_aes_192_CAPABLE && \
- (OPENSSL_s390xcap_P.kma[0] & \
- S390X_CAPBIT(S390X_AES_192)))
-# define S390X_aes_256_gcm_CAPABLE (S390X_aes_256_CAPABLE && \
- (OPENSSL_s390xcap_P.kma[0] & \
- S390X_CAPBIT(S390X_AES_256)))
-
/* iv + padding length for iv lengths != 12 */
-# define S390X_gcm_ivpadlen(i) ((((i) + 15) >> 4 << 4) + 16)
+# define S390X_gcm_ivpadlen(i) ((((i) + 15) >> 4 << 4) + 16)
/*-
* Process additional authenticated data. Returns 0 on success. Code is
@@ -1579,7 +1314,8 @@ static int s390x_aes_gcm(S390X_AES_GCM_CTX *ctx, const unsigned char *in,
/*-
* Initialize context structure. Code is big-endian.
*/
-static void s390x_aes_gcm_setiv(S390X_AES_GCM_CTX *ctx)
+static void s390x_aes_gcm_setiv(S390X_AES_GCM_CTX *ctx,
+ const unsigned char *iv)
{
ctx->kma.param.t.g[0] = 0;
ctx->kma.param.t.g[1] = 0;
@@ -1590,11 +1326,12 @@ static void s390x_aes_gcm_setiv(S390X_AES_GCM_CTX *ctx)
ctx->kreslen = 0;
if (ctx->ivlen == 12) {
- memcpy(&ctx->kma.param.j0, ctx->iv, ctx->ivlen);
+ memcpy(&ctx->kma.param.j0, iv, ctx->ivlen);
ctx->kma.param.j0.w[3] = 1;
ctx->kma.param.cv.w = 1;
} else {
/* ctx->iv has the right size and is already padded. */
+ memcpy(ctx->iv, iv, ctx->ivlen);
s390x_kma(ctx->iv, S390X_gcm_ivpadlen(ctx->ivlen), NULL, 0, NULL,
ctx->fc, &ctx->kma.param);
ctx->fc |= S390X_KMA_HS;
@@ -1617,17 +1354,16 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, c);
S390X_AES_GCM_CTX *gctx_out;
EVP_CIPHER_CTX *out;
- unsigned char *buf, *iv;
+ unsigned char *buf;
int ivlen, enc, len;
switch (type) {
case EVP_CTRL_INIT:
- ivlen = EVP_CIPHER_iv_length(c->cipher);
- iv = EVP_CIPHER_CTX_iv_noconst(c);
+ ivlen = EVP_CIPHER_get_iv_length(c->cipher);
gctx->key_set = 0;
gctx->iv_set = 0;
gctx->ivlen = ivlen;
- gctx->iv = iv;
+ gctx->iv = c->iv;
gctx->taglen = -1;
gctx->iv_gen = 0;
gctx->tls_aad_len = -1;
@@ -1642,16 +1378,15 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
return 0;
if (arg != 12) {
- iv = EVP_CIPHER_CTX_iv_noconst(c);
len = S390X_gcm_ivpadlen(arg);
/* Allocate memory for iv if needed. */
if (gctx->ivlen == 12 || len > S390X_gcm_ivpadlen(gctx->ivlen)) {
- if (gctx->iv != iv)
+ if (gctx->iv != c->iv)
OPENSSL_free(gctx->iv);
if ((gctx->iv = OPENSSL_malloc(len)) == NULL) {
- EVPerr(EVP_F_S390X_AES_GCM_CTRL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
}
@@ -1664,7 +1399,7 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
case EVP_CTRL_AEAD_SET_TAG:
buf = EVP_CIPHER_CTX_buf_noconst(c);
- enc = EVP_CIPHER_CTX_encrypting(c);
+ enc = EVP_CIPHER_CTX_is_encrypting(c);
if (arg <= 0 || arg > 16 || enc)
return 0;
@@ -1673,7 +1408,7 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
return 1;
case EVP_CTRL_AEAD_GET_TAG:
- enc = EVP_CIPHER_CTX_encrypting(c);
+ enc = EVP_CIPHER_CTX_is_encrypting(c);
if (arg <= 0 || arg > 16 || !enc || gctx->taglen < 0)
return 0;
@@ -1697,7 +1432,7 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
if (arg)
memcpy(gctx->iv, ptr, arg);
- enc = EVP_CIPHER_CTX_encrypting(c);
+ enc = EVP_CIPHER_CTX_is_encrypting(c);
if (enc && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
return 0;
@@ -1708,7 +1443,7 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
if (gctx->iv_gen == 0 || gctx->key_set == 0)
return 0;
- s390x_aes_gcm_setiv(gctx);
+ s390x_aes_gcm_setiv(gctx, gctx->iv);
if (arg <= 0 || arg > gctx->ivlen)
arg = gctx->ivlen;
@@ -1723,12 +1458,12 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
return 1;
case EVP_CTRL_GCM_SET_IV_INV:
- enc = EVP_CIPHER_CTX_encrypting(c);
+ enc = EVP_CIPHER_CTX_is_encrypting(c);
if (gctx->iv_gen == 0 || gctx->key_set == 0 || enc)
return 0;
memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
- s390x_aes_gcm_setiv(gctx);
+ s390x_aes_gcm_setiv(gctx, gctx->iv);
gctx->iv_set = 1;
return 1;
@@ -1740,6 +1475,7 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
buf = EVP_CIPHER_CTX_buf_noconst(c);
memcpy(buf, ptr, arg);
gctx->tls_aad_len = arg;
+ gctx->tls_enc_records = 0;
len = buf[arg - 2] << 8 | buf[arg - 1];
/* Correct length for explicit iv. */
@@ -1748,7 +1484,7 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
/* If decrypting correct for tag too. */
- enc = EVP_CIPHER_CTX_encrypting(c);
+ enc = EVP_CIPHER_CTX_is_encrypting(c);
if (!enc) {
if (len < EVP_GCM_TLS_TAG_LEN)
return 0;
@@ -1762,15 +1498,14 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
case EVP_CTRL_COPY:
out = ptr;
gctx_out = EVP_C_DATA(S390X_AES_GCM_CTX, out);
- iv = EVP_CIPHER_CTX_iv_noconst(c);
- if (gctx->iv == iv) {
- gctx_out->iv = EVP_CIPHER_CTX_iv_noconst(out);
+ if (gctx->iv == c->iv) {
+ gctx_out->iv = out->iv;
} else {
len = S390X_gcm_ivpadlen(gctx->ivlen);
if ((gctx_out->iv = OPENSSL_malloc(len)) == NULL) {
- EVPerr(EVP_F_S390X_AES_GCM_CTRL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -1784,36 +1519,43 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
}
/*-
- * Set key or iv or enc/dec. Returns 1 on success. Otherwise 0 is returned.
+ * Set key and/or iv. Returns 1 on success. Otherwise 0 is returned.
*/
static int s390x_aes_gcm_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv, int enc)
{
S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, ctx);
- const int keylen = EVP_CIPHER_CTX_key_length(ctx);
+ int keylen;
- gctx->fc = S390X_AES_FC(keylen) | (enc ? 0 : S390X_DECRYPT);
+ if (iv == NULL && key == NULL)
+ return 1;
if (key != NULL) {
- gctx->fc &= ~S390X_KMA_HS;
+ keylen = EVP_CIPHER_CTX_get_key_length(ctx);
memcpy(&gctx->kma.param.k, key, keylen);
+
+ gctx->fc = S390X_AES_FC(keylen);
+ if (!enc)
+ gctx->fc |= S390X_DECRYPT;
+
+ if (iv == NULL && gctx->iv_set)
+ iv = gctx->iv;
+
+ if (iv != NULL) {
+ s390x_aes_gcm_setiv(gctx, iv);
+ gctx->iv_set = 1;
+ }
gctx->key_set = 1;
- }
+ } else {
+ if (gctx->key_set)
+ s390x_aes_gcm_setiv(gctx, iv);
+ else
+ memcpy(gctx->iv, iv, gctx->ivlen);
- if (iv != NULL) {
- memcpy(gctx->iv, iv, gctx->ivlen);
- gctx->iv_gen = 0;
gctx->iv_set = 1;
+ gctx->iv_gen = 0;
}
-
- if (gctx->key_set && gctx->iv_set)
- s390x_aes_gcm_setiv(gctx);
-
- gctx->fc &= ~(S390X_KMA_LPC | S390X_KMA_LAAD);
- gctx->areslen = 0;
- gctx->mreslen = 0;
- gctx->kreslen = 0;
return 1;
}
@@ -1826,12 +1568,23 @@ static int s390x_aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
{
S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, ctx);
const unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
- const int enc = EVP_CIPHER_CTX_encrypting(ctx);
+ const int enc = EVP_CIPHER_CTX_is_encrypting(ctx);
int rv = -1;
if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
return -1;
+ /*
+ * Check for too many keys as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness
+ * Requirements from SP 800-38D". The requirements is for one party to the
+ * communication to fail after 2^64 - 1 keys. We do this on the encrypting
+ * side only.
+ */
+ if (ctx->encrypt && ++gctx->tls_enc_records == 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_TOO_MANY_RECORDS);
+ goto err;
+ }
+
if (EVP_CIPHER_CTX_ctrl(ctx, enc ? EVP_CTRL_GCM_IV_GEN
: EVP_CTRL_GCM_SET_IV_INV,
EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0)
@@ -1902,8 +1655,9 @@ static int s390x_aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
/* recall that we already did en-/decrypt gctx->mres
* and returned it to caller... */
OPENSSL_cleanse(tmp, gctx->mreslen);
+ gctx->iv_set = 0;
- enc = EVP_CIPHER_CTX_encrypting(ctx);
+ enc = EVP_CIPHER_CTX_is_encrypting(ctx);
if (enc) {
gctx->taglen = 16;
} else {
@@ -1921,22 +1675,18 @@ static int s390x_aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int s390x_aes_gcm_cleanup(EVP_CIPHER_CTX *c)
{
S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, c);
- const unsigned char *iv;
if (gctx == NULL)
return 0;
- iv = EVP_CIPHER_CTX_iv(c);
- if (iv != gctx->iv)
+ if (gctx->iv != c->iv)
OPENSSL_free(gctx->iv);
OPENSSL_cleanse(gctx, sizeof(*gctx));
return 1;
}
-# define S390X_AES_XTS_CTX EVP_AES_XTS_CTX
-# define S390X_aes_128_xts_CAPABLE 0 /* checked by callee */
-# define S390X_aes_256_xts_CAPABLE 0
+# define S390X_AES_XTS_CTX EVP_AES_XTS_CTX
# define s390x_aes_xts_init_key aes_xts_init_key
static int s390x_aes_xts_init_key(EVP_CIPHER_CTX *ctx,
@@ -1949,18 +1699,6 @@ static int s390x_aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int s390x_aes_xts_ctrl(EVP_CIPHER_CTX *, int type, int arg, void *ptr);
# define s390x_aes_xts_cleanup aes_xts_cleanup
-# define S390X_aes_128_ccm_CAPABLE (S390X_aes_128_CAPABLE && \
- (OPENSSL_s390xcap_P.kmac[0] & \
- S390X_CAPBIT(S390X_AES_128)))
-# define S390X_aes_192_ccm_CAPABLE (S390X_aes_192_CAPABLE && \
- (OPENSSL_s390xcap_P.kmac[0] & \
- S390X_CAPBIT(S390X_AES_192)))
-# define S390X_aes_256_ccm_CAPABLE (S390X_aes_256_CAPABLE && \
- (OPENSSL_s390xcap_P.kmac[0] & \
- S390X_CAPBIT(S390X_AES_256)))
-
-# define S390X_CCM_AAD_FLAG 0x40
-
/*-
* Set nonce and length fields. Code is big-endian.
*/
@@ -2073,13 +1811,13 @@ static int s390x_aes_ccm(S390X_AES_CCM_CTX *ctx, const unsigned char *in,
ctx->aes.ccm.nonce.b[15] = 1;
if (n != len)
- return -1; /* length mismatch */
+ return -1; /* length mismatch */
if (enc) {
/* Two operations per block plus one for tag encryption */
ctx->aes.ccm.blocks += (((len + 15) >> 4) << 1) + 1;
if (ctx->aes.ccm.blocks > (1ULL << 61))
- return -2; /* too much data */
+ return -2; /* too much data */
}
num = 0;
@@ -2128,7 +1866,7 @@ static int s390x_aes_ccm(S390X_AES_CCM_CTX *ctx, const unsigned char *in,
ctx->aes.ccm.kmac_param.icv.g[0] ^= ctx->aes.ccm.buf.g[0];
ctx->aes.ccm.kmac_param.icv.g[1] ^= ctx->aes.ccm.buf.g[1];
- ctx->aes.ccm.nonce.b[0] = flags; /* restore flags field */
+ ctx->aes.ccm.nonce.b[0] = flags; /* restore flags field */
return 0;
}
@@ -2140,10 +1878,9 @@ static int s390x_aes_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, ctx);
- const unsigned char *ivec = EVP_CIPHER_CTX_iv(ctx);
+ unsigned char *ivec = ctx->iv;
unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
- const int enc = EVP_CIPHER_CTX_encrypting(ctx);
- unsigned char iv[EVP_MAX_IV_LENGTH];
+ const int enc = EVP_CIPHER_CTX_is_encrypting(ctx);
if (out != in
|| len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)cctx->aes.ccm.m))
@@ -2159,9 +1896,8 @@ static int s390x_aes_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
* Get explicit iv (sequence number). We already have fixed iv
* (server/client_write_iv) here.
*/
- memcpy(iv, ivec, sizeof(iv));
- memcpy(iv + EVP_CCM_TLS_FIXED_IV_LEN, in, EVP_CCM_TLS_EXPLICIT_IV_LEN);
- s390x_aes_ccm_setiv(cctx, iv, len);
+ memcpy(ivec + EVP_CCM_TLS_FIXED_IV_LEN, in, EVP_CCM_TLS_EXPLICIT_IV_LEN);
+ s390x_aes_ccm_setiv(cctx, ivec, len);
/* Process aad (sequence number|type|version|length) */
s390x_aes_ccm_aad(cctx, buf, cctx->aes.ccm.tls_aad_len);
@@ -2188,35 +1924,40 @@ static int s390x_aes_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
}
/*-
- * Set key or iv or enc/dec. Returns 1 if successful.
- * Otherwise 0 is returned.
+ * Set key and flag field and/or iv. Returns 1 if successful. Otherwise 0 is
+ * returned.
*/
static int s390x_aes_ccm_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv, int enc)
{
S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, ctx);
- const int keylen = EVP_CIPHER_CTX_key_length(ctx);
- unsigned char *ivec = EVP_CIPHER_CTX_iv_noconst(ctx);
+ int keylen;
- cctx->aes.ccm.fc = S390X_AES_FC(keylen);
+ if (iv == NULL && key == NULL)
+ return 1;
if (key != NULL) {
+ keylen = EVP_CIPHER_CTX_get_key_length(ctx);
+ cctx->aes.ccm.fc = S390X_AES_FC(keylen);
memcpy(cctx->aes.ccm.kmac_param.k, key, keylen);
+
+ /* Store encoded m and l. */
+ cctx->aes.ccm.nonce.b[0] = ((cctx->aes.ccm.l - 1) & 0x7)
+ | (((cctx->aes.ccm.m - 2) >> 1) & 0x7) << 3;
+ memset(cctx->aes.ccm.nonce.b + 1, 0,
+ sizeof(cctx->aes.ccm.nonce.b));
+ cctx->aes.ccm.blocks = 0;
+
cctx->aes.ccm.key_set = 1;
}
+
if (iv != NULL) {
- memcpy(ivec, iv, 15 - cctx->aes.ccm.l);
+ memcpy(ctx->iv, iv, 15 - cctx->aes.ccm.l);
+
cctx->aes.ccm.iv_set = 1;
}
- /* Store encoded m and l. */
- cctx->aes.ccm.nonce.b[0] = ((cctx->aes.ccm.l - 1) & 0x7)
- | (((cctx->aes.ccm.m - 2) >> 1) & 0x7) << 3;
- memset(cctx->aes.ccm.nonce.b + 1, 0, sizeof(cctx->aes.ccm.nonce.b) - 1);
-
- cctx->aes.ccm.blocks = 0;
- cctx->aes.ccm.len_set = 0;
return 1;
}
@@ -2230,10 +1971,9 @@ static int s390x_aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, ctx);
- const int enc = EVP_CIPHER_CTX_encrypting(ctx);
- const unsigned char *ivec = EVP_CIPHER_CTX_iv(ctx);
- unsigned char *buf;
+ const int enc = EVP_CIPHER_CTX_is_encrypting(ctx);
int rv;
+ unsigned char *buf;
if (!cctx->aes.ccm.key_set)
return -1;
@@ -2255,7 +1995,7 @@ static int s390x_aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (out == NULL) {
/* Update(): Pass message length. */
if (in == NULL) {
- s390x_aes_ccm_setiv(cctx, ivec, len);
+ s390x_aes_ccm_setiv(cctx, ctx->iv, len);
cctx->aes.ccm.len_set = 1;
return len;
@@ -2280,7 +2020,7 @@ static int s390x_aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
* In case message length was not previously set explicitly via
* Update(), set it now.
*/
- s390x_aes_ccm_setiv(cctx, ivec, len);
+ s390x_aes_ccm_setiv(cctx, ctx->iv, len);
cctx->aes.ccm.len_set = 1;
}
@@ -2304,6 +2044,9 @@ static int s390x_aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (rv == -1)
OPENSSL_cleanse(out, len);
+ cctx->aes.ccm.iv_set = 0;
+ cctx->aes.ccm.tag_set = 0;
+ cctx->aes.ccm.len_set = 0;
return rv;
}
}
@@ -2316,7 +2059,7 @@ static int s390x_aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int s390x_aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
{
S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, c);
- unsigned char *buf, *iv;
+ unsigned char *buf;
int enc, len;
switch (type) {
@@ -2350,7 +2093,7 @@ static int s390x_aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
/* Correct length for explicit iv. */
len -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
- enc = EVP_CIPHER_CTX_encrypting(c);
+ enc = EVP_CIPHER_CTX_is_encrypting(c);
if (!enc) {
if (len < cctx->aes.ccm.m)
return 0;
@@ -2370,8 +2113,7 @@ static int s390x_aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
return 0;
/* Copy to first part of the iv. */
- iv = EVP_CIPHER_CTX_iv_noconst(c);
- memcpy(iv, ptr, arg);
+ memcpy(c->iv, ptr, arg);
return 1;
case EVP_CTRL_AEAD_SET_IVLEN:
@@ -2389,7 +2131,7 @@ static int s390x_aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
if ((arg & 1) || arg < 4 || arg > 16)
return 0;
- enc = EVP_CIPHER_CTX_encrypting(c);
+ enc = EVP_CIPHER_CTX_is_encrypting(c);
if (enc && ptr)
return 0;
@@ -2403,7 +2145,7 @@ static int s390x_aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
return 1;
case EVP_CTRL_AEAD_GET_TAG:
- enc = EVP_CIPHER_CTX_encrypting(c);
+ enc = EVP_CIPHER_CTX_is_encrypting(c);
if (!enc || !cctx->aes.ccm.tag_set)
return 0;
@@ -2411,6 +2153,9 @@ static int s390x_aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
return 0;
memcpy(ptr, cctx->aes.ccm.kmac_param.icv.b, cctx->aes.ccm.m);
+ cctx->aes.ccm.tag_set = 0;
+ cctx->aes.ccm.iv_set = 0;
+ cctx->aes.ccm.len_set = 0;
return 1;
case EVP_CTRL_COPY:
@@ -2424,10 +2169,7 @@ static int s390x_aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
# define s390x_aes_ccm_cleanup aes_ccm_cleanup
# ifndef OPENSSL_NO_OCB
-# define S390X_AES_OCB_CTX EVP_AES_OCB_CTX
-# define S390X_aes_128_ocb_CAPABLE 0
-# define S390X_aes_192_ocb_CAPABLE 0
-# define S390X_aes_256_ocb_CAPABLE 0
+# define S390X_AES_OCB_CTX EVP_AES_OCB_CTX
# define s390x_aes_ocb_init_key aes_ocb_init_key
static int s390x_aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
@@ -2441,77 +2183,90 @@ static int s390x_aes_ocb_cleanup(EVP_CIPHER_CTX *);
static int s390x_aes_ocb_ctrl(EVP_CIPHER_CTX *, int type, int arg, void *ptr);
# endif
-# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode, \
- MODE,flags) \
-static const EVP_CIPHER s390x_aes_##keylen##_##mode = { \
- nid##_##keylen##_##nmode,blocksize, \
- keylen / 8, \
- ivlen, \
- flags | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_##MODE##_MODE, \
- s390x_aes_##mode##_init_key, \
- s390x_aes_##mode##_cipher, \
- NULL, \
- sizeof(S390X_AES_##MODE##_CTX), \
- NULL, \
- NULL, \
- NULL, \
- NULL \
-}; \
-static const EVP_CIPHER aes_##keylen##_##mode = { \
- nid##_##keylen##_##nmode, \
- blocksize, \
- keylen / 8, \
- ivlen, \
- flags | EVP_CIPH_##MODE##_MODE, \
- aes_init_key, \
- aes_##mode##_cipher, \
- NULL, \
- sizeof(EVP_AES_KEY), \
- NULL, \
- NULL, \
- NULL, \
- NULL \
-}; \
-const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
-{ \
- return S390X_aes_##keylen##_##mode##_CAPABLE ? \
- &s390x_aes_##keylen##_##mode : &aes_##keylen##_##mode; \
+# ifndef OPENSSL_NO_SIV
+# define S390X_AES_SIV_CTX EVP_AES_SIV_CTX
+
+# define s390x_aes_siv_init_key aes_siv_init_key
+# define s390x_aes_siv_cipher aes_siv_cipher
+# define s390x_aes_siv_cleanup aes_siv_cleanup
+# define s390x_aes_siv_ctrl aes_siv_ctrl
+# endif
+
+# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode, \
+ MODE,flags) \
+static const EVP_CIPHER s390x_aes_##keylen##_##mode = { \
+ nid##_##keylen##_##nmode,blocksize, \
+ keylen / 8, \
+ ivlen, \
+ flags | EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
+ s390x_aes_##mode##_init_key, \
+ s390x_aes_##mode##_cipher, \
+ NULL, \
+ sizeof(S390X_AES_##MODE##_CTX), \
+ NULL, \
+ NULL, \
+ NULL, \
+ NULL \
+}; \
+static const EVP_CIPHER aes_##keylen##_##mode = { \
+ nid##_##keylen##_##nmode, \
+ blocksize, \
+ keylen / 8, \
+ ivlen, \
+ flags | EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
+ aes_init_key, \
+ aes_##mode##_cipher, \
+ NULL, \
+ sizeof(EVP_AES_KEY), \
+ NULL, \
+ NULL, \
+ NULL, \
+ NULL \
+}; \
+const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
+{ \
+ return S390X_aes_##keylen##_##mode##_CAPABLE ? \
+ &s390x_aes_##keylen##_##mode : &aes_##keylen##_##mode; \
}
# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags)\
-static const EVP_CIPHER s390x_aes_##keylen##_##mode = { \
- nid##_##keylen##_##mode, \
- blocksize, \
- (EVP_CIPH_##MODE##_MODE == EVP_CIPH_XTS_MODE ? 2 : 1) * keylen / 8, \
- ivlen, \
- flags | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_##MODE##_MODE, \
- s390x_aes_##mode##_init_key, \
- s390x_aes_##mode##_cipher, \
- s390x_aes_##mode##_cleanup, \
- sizeof(S390X_AES_##MODE##_CTX), \
- NULL, \
- NULL, \
- s390x_aes_##mode##_ctrl, \
- NULL \
-}; \
-static const EVP_CIPHER aes_##keylen##_##mode = { \
- nid##_##keylen##_##mode,blocksize, \
- (EVP_CIPH_##MODE##_MODE == EVP_CIPH_XTS_MODE ? 2 : 1) * keylen / 8, \
- ivlen, \
- flags | EVP_CIPH_##MODE##_MODE, \
- aes_##mode##_init_key, \
- aes_##mode##_cipher, \
- aes_##mode##_cleanup, \
- sizeof(EVP_AES_##MODE##_CTX), \
- NULL, \
- NULL, \
- aes_##mode##_ctrl, \
- NULL \
-}; \
-const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
-{ \
- return S390X_aes_##keylen##_##mode##_CAPABLE ? \
- &s390x_aes_##keylen##_##mode : &aes_##keylen##_##mode; \
+static const EVP_CIPHER s390x_aes_##keylen##_##mode = { \
+ nid##_##keylen##_##mode, \
+ blocksize, \
+ (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE ? 2 : 1) * keylen / 8, \
+ ivlen, \
+ flags | EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
+ s390x_aes_##mode##_init_key, \
+ s390x_aes_##mode##_cipher, \
+ s390x_aes_##mode##_cleanup, \
+ sizeof(S390X_AES_##MODE##_CTX), \
+ NULL, \
+ NULL, \
+ s390x_aes_##mode##_ctrl, \
+ NULL \
+}; \
+static const EVP_CIPHER aes_##keylen##_##mode = { \
+ nid##_##keylen##_##mode,blocksize, \
+ (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE ? 2 : 1) * keylen / 8, \
+ ivlen, \
+ flags | EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
+ aes_##mode##_init_key, \
+ aes_##mode##_cipher, \
+ aes_##mode##_cleanup, \
+ sizeof(EVP_AES_##MODE##_CTX), \
+ NULL, \
+ NULL, \
+ aes_##mode##_ctrl, \
+ NULL \
+}; \
+const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
+{ \
+ return S390X_aes_##keylen##_##mode##_CAPABLE ? \
+ &s390x_aes_##keylen##_##mode : &aes_##keylen##_##mode; \
}
#else
@@ -2520,6 +2275,7 @@ const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
aes_init_key, \
aes_##mode##_cipher, \
NULL, \
@@ -2531,8 +2287,10 @@ const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
- (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
+ (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
+ ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
aes_##mode##_init_key, \
aes_##mode##_cipher, \
aes_##mode##_cleanup, \
@@ -2543,48 +2301,6 @@ const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
#endif
-#if defined(OPENSSL_CPUID_OBJ) && (defined(__arm__) || defined(__arm) || defined(__aarch64__))
-# include "arm_arch.h"
-# if __ARM_MAX_ARCH__>=7
-# if defined(BSAES_ASM)
-# define BSAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
-# endif
-# if defined(VPAES_ASM)
-# define VPAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
-# endif
-# define HWAES_CAPABLE (OPENSSL_armcap_P & ARMV8_AES)
-# define HWAES_set_encrypt_key aes_v8_set_encrypt_key
-# define HWAES_set_decrypt_key aes_v8_set_decrypt_key
-# define HWAES_encrypt aes_v8_encrypt
-# define HWAES_decrypt aes_v8_decrypt
-# define HWAES_cbc_encrypt aes_v8_cbc_encrypt
-# define HWAES_ctr32_encrypt_blocks aes_v8_ctr32_encrypt_blocks
-# endif
-#endif
-
-#if defined(HWAES_CAPABLE)
-int HWAES_set_encrypt_key(const unsigned char *userKey, const int bits,
- AES_KEY *key);
-int HWAES_set_decrypt_key(const unsigned char *userKey, const int bits,
- AES_KEY *key);
-void HWAES_encrypt(const unsigned char *in, unsigned char *out,
- const AES_KEY *key);
-void HWAES_decrypt(const unsigned char *in, unsigned char *out,
- const AES_KEY *key);
-void HWAES_cbc_encrypt(const unsigned char *in, unsigned char *out,
- size_t length, const AES_KEY *key,
- unsigned char *ivec, const int enc);
-void HWAES_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
- size_t len, const AES_KEY *key,
- const unsigned char ivec[16]);
-void HWAES_xts_encrypt(const unsigned char *inp, unsigned char *out,
- size_t len, const AES_KEY *key1,
- const AES_KEY *key2, const unsigned char iv[16]);
-void HWAES_xts_decrypt(const unsigned char *inp, unsigned char *out,
- size_t len, const AES_KEY *key1,
- const AES_KEY *key2, const unsigned char iv[16]);
-#endif
-
#define BLOCK_CIPHER_generic_pack(nid,keylen,flags) \
BLOCK_CIPHER_generic(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
BLOCK_CIPHER_generic(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
@@ -2600,13 +2316,13 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
int ret, mode;
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
- mode = EVP_CIPHER_CTX_mode(ctx);
+ mode = EVP_CIPHER_CTX_get_mode(ctx);
if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
&& !enc) {
#ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
ret = HWAES_set_decrypt_key(key,
- EVP_CIPHER_CTX_key_length(ctx) * 8,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) HWAES_decrypt;
dat->stream.cbc = NULL;
@@ -2618,16 +2334,17 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
#endif
#ifdef BSAES_CAPABLE
if (BSAES_CAPABLE && mode == EVP_CIPH_CBC_MODE) {
- ret = AES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ ret = AES_set_decrypt_key(key,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) AES_decrypt;
- dat->stream.cbc = (cbc128_f) bsaes_cbc_encrypt;
+ dat->stream.cbc = (cbc128_f) ossl_bsaes_cbc_encrypt;
} else
#endif
#ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
ret = vpaes_set_decrypt_key(key,
- EVP_CIPHER_CTX_key_length(ctx) * 8,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) vpaes_decrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
@@ -2636,7 +2353,7 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
#endif
{
ret = AES_set_decrypt_key(key,
- EVP_CIPHER_CTX_key_length(ctx) * 8,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) AES_decrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
@@ -2645,7 +2362,8 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
} else
#ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
- ret = HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ ret = HWAES_set_encrypt_key(key,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) HWAES_encrypt;
dat->stream.cbc = NULL;
@@ -2664,15 +2382,16 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
#endif
#ifdef BSAES_CAPABLE
if (BSAES_CAPABLE && mode == EVP_CIPH_CTR_MODE) {
- ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) AES_encrypt;
- dat->stream.ctr = (ctr128_f) bsaes_ctr32_encrypt_blocks;
+ dat->stream.ctr = (ctr128_f) ossl_bsaes_ctr32_encrypt_blocks;
} else
#endif
#ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
- ret = vpaes_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ ret = vpaes_set_encrypt_key(key,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) vpaes_encrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
@@ -2680,7 +2399,7 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
} else
#endif
{
- ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) AES_encrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
@@ -2692,7 +2411,7 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
}
if (ret < 0) {
- EVPerr(EVP_F_AES_INIT_KEY, EVP_R_AES_KEY_SETUP_FAILED);
+ ERR_raise(ERR_LIB_EVP, EVP_R_AES_KEY_SETUP_FAILED);
return 0;
}
@@ -2705,15 +2424,14 @@ static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
if (dat->stream.cbc)
- (*dat->stream.cbc) (in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx),
- EVP_CIPHER_CTX_encrypting(ctx));
- else if (EVP_CIPHER_CTX_encrypting(ctx))
- CRYPTO_cbc128_encrypt(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), dat->block);
+ (*dat->stream.cbc) (in, out, len, &dat->ks, ctx->iv,
+ EVP_CIPHER_CTX_is_encrypting(ctx));
+ else if (EVP_CIPHER_CTX_is_encrypting(ctx))
+ CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv,
+ dat->block);
else
CRYPTO_cbc128_decrypt(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), dat->block);
+ ctx->iv, dat->block);
return 1;
}
@@ -2721,7 +2439,7 @@ static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
- size_t bl = EVP_CIPHER_CTX_block_size(ctx);
+ size_t bl = EVP_CIPHER_CTX_get_block_size(ctx);
size_t i;
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
@@ -2739,9 +2457,9 @@ static int aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
{
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
- int num = EVP_CIPHER_CTX_num(ctx);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
CRYPTO_ofb128_encrypt(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), &num, dat->block);
+ ctx->iv, &num, dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
return 1;
}
@@ -2751,10 +2469,10 @@ static int aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
{
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
- int num = EVP_CIPHER_CTX_num(ctx);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
CRYPTO_cfb128_encrypt(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), &num,
- EVP_CIPHER_CTX_encrypting(ctx), dat->block);
+ ctx->iv, &num,
+ EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
return 1;
}
@@ -2764,10 +2482,10 @@ static int aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
{
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
- int num = EVP_CIPHER_CTX_num(ctx);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), &num,
- EVP_CIPHER_CTX_encrypting(ctx), dat->block);
+ ctx->iv, &num,
+ EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
return 1;
}
@@ -2778,29 +2496,29 @@ static int aes_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) {
- int num = EVP_CIPHER_CTX_num(ctx);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), &num,
- EVP_CIPHER_CTX_encrypting(ctx), dat->block);
+ ctx->iv, &num,
+ EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
return 1;
}
while (len >= MAXBITCHUNK) {
- int num = EVP_CIPHER_CTX_num(ctx);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), &num,
- EVP_CIPHER_CTX_encrypting(ctx), dat->block);
+ ctx->iv, &num,
+ EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
len -= MAXBITCHUNK;
out += MAXBITCHUNK;
in += MAXBITCHUNK;
}
if (len) {
- int num = EVP_CIPHER_CTX_num(ctx);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
CRYPTO_cfb128_1_encrypt(in, out, len * 8, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), &num,
- EVP_CIPHER_CTX_encrypting(ctx), dat->block);
+ ctx->iv, &num,
+ EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
}
@@ -2810,17 +2528,22 @@ static int aes_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
- unsigned int num = EVP_CIPHER_CTX_num(ctx);
+ int n = EVP_CIPHER_CTX_get_num(ctx);
+ unsigned int num;
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
+ if (n < 0)
+ return 0;
+ num = (unsigned int)n;
+
if (dat->stream.ctr)
CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx),
+ ctx->iv,
EVP_CIPHER_CTX_buf_noconst(ctx),
&num, dat->stream.ctr);
else
CRYPTO_ctr128_encrypt(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx),
+ ctx->iv,
EVP_CIPHER_CTX_buf_noconst(ctx), &num,
dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
@@ -2837,7 +2560,7 @@ static int aes_gcm_cleanup(EVP_CIPHER_CTX *c)
if (gctx == NULL)
return 0;
OPENSSL_cleanse(&gctx->gcm, sizeof(gctx->gcm));
- if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(c))
+ if (gctx->iv != c->iv)
OPENSSL_free(gctx->iv);
return 1;
}
@@ -2849,7 +2572,7 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
case EVP_CTRL_INIT:
gctx->key_set = 0;
gctx->iv_set = 0;
- gctx->ivlen = EVP_CIPHER_iv_length(c->cipher);
+ gctx->ivlen = EVP_CIPHER_get_iv_length(c->cipher);
gctx->iv = c->iv;
gctx->taglen = -1;
gctx->iv_gen = 0;
@@ -2868,7 +2591,7 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
if (gctx->iv != c->iv)
OPENSSL_free(gctx->iv);
if ((gctx->iv = OPENSSL_malloc(arg)) == NULL) {
- EVPerr(EVP_F_AES_GCM_CTRL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
}
@@ -2938,6 +2661,7 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
return 0;
memcpy(c->buf, ptr, arg);
gctx->tls_aad_len = arg;
+ gctx->tls_enc_records = 0;
{
unsigned int len = c->buf[arg - 2] << 8 | c->buf[arg - 1];
/* Correct length for explicit IV */
@@ -2969,7 +2693,7 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
gctx_out->iv = out->iv;
else {
if ((gctx_out->iv = OPENSSL_malloc(gctx->ivlen)) == NULL) {
- EVPerr(EVP_F_AES_GCM_CTRL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
@@ -3009,7 +2733,7 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
(block128_f) AES_encrypt);
- gctx->ctr = (ctr128_f) bsaes_ctr32_encrypt_blocks;
+ gctx->ctr = (ctr128_f) ossl_bsaes_ctr32_encrypt_blocks;
break;
} else
#endif
@@ -3072,6 +2796,18 @@ static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (out != in
|| len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
return -1;
+
+ /*
+ * Check for too many keys as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness
+ * Requirements from SP 800-38D". The requirements is for one party to the
+ * communication to fail after 2^64 - 1 keys. We do this on the encrypting
+ * side only.
+ */
+ if (ctx->encrypt && ++gctx->tls_enc_records == 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_TOO_MANY_RECORDS);
+ goto err;
+ }
+
/*
* Set IV from start of buffer or generate IV and write to start of
* buffer.
@@ -3181,10 +2917,35 @@ static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return rv;
}
+#ifdef FIPS_MODULE
+/*
+ * See SP800-38D (GCM) Section 8 "Uniqueness requirement on IVS and keys"
+ *
+ * See also 8.2.2 RBG-based construction.
+ * Random construction consists of a free field (which can be NULL) and a
+ * random field which will use a DRBG that can return at least 96 bits of
+ * entropy strength. (The DRBG must be seeded by the FIPS module).
+ */
+static int aes_gcm_iv_generate(EVP_AES_GCM_CTX *gctx, int offset)
+{
+ int sz = gctx->ivlen - offset;
+
+ /* Must be at least 96 bits */
+ if (sz <= 0 || gctx->ivlen < 12)
+ return 0;
+
+ /* Use DRBG to generate random iv */
+ if (RAND_bytes(gctx->iv + offset, sz) <= 0)
+ return 0;
+ return 1;
+}
+#endif /* FIPS_MODULE */
+
static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
+
/* If not set up, return error */
if (!gctx->key_set)
return -1;
@@ -3192,8 +2953,25 @@ static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (gctx->tls_aad_len >= 0)
return aes_gcm_tls_cipher(ctx, out, in, len);
+#ifdef FIPS_MODULE
+ /*
+ * FIPS requires generation of AES-GCM IV's inside the FIPS module.
+ * The IV can still be set externally (the security policy will state that
+ * this is not FIPS compliant). There are some applications
+ * where setting the IV externally is the only option available.
+ */
+ if (!gctx->iv_set) {
+ if (!ctx->encrypt || !aes_gcm_iv_generate(gctx, 0))
+ return -1;
+ CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
+ gctx->iv_set = 1;
+ gctx->iv_gen_rand = 1;
+ }
+#else
if (!gctx->iv_set)
return -1;
+#endif /* FIPS_MODULE */
+
if (in) {
if (out == NULL) {
if (CRYPTO_gcm128_aad(&gctx->gcm, in, len))
@@ -3353,10 +3131,11 @@ static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
if (!iv && !key)
return 1;
- if (key)
+ if (key) {
do {
/* The key is two half length keys in reality */
- const int bytes = EVP_CIPHER_CTX_key_length(ctx) / 2;
+ const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2;
+ const int bits = bytes * 8;
/*
* Verify that the two keys are different.
@@ -3374,8 +3153,9 @@ static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
* BEFORE using the keys in the XTS-AES algorithm to process
* data with them."
*/
- if (enc && CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
- EVPerr(EVP_F_AES_XTS_INIT_KEY, EVP_R_XTS_DUPLICATED_KEYS);
+ if ((!allow_insecure_decrypt || enc)
+ && CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_XTS_DUPLICATED_KEYS);
return 0;
}
@@ -3388,26 +3168,20 @@ static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
#ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
if (enc) {
- HWAES_set_encrypt_key(key,
- EVP_CIPHER_CTX_key_length(ctx) * 4,
- &xctx->ks1.ks);
+ HWAES_set_encrypt_key(key, bits, &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) HWAES_encrypt;
# ifdef HWAES_xts_encrypt
xctx->stream = HWAES_xts_encrypt;
# endif
} else {
- HWAES_set_decrypt_key(key,
- EVP_CIPHER_CTX_key_length(ctx) * 4,
- &xctx->ks1.ks);
+ HWAES_set_decrypt_key(key, bits, &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) HWAES_decrypt;
# ifdef HWAES_xts_decrypt
xctx->stream = HWAES_xts_decrypt;
#endif
}
- HWAES_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2,
- EVP_CIPHER_CTX_key_length(ctx) * 4,
- &xctx->ks2.ks);
+ HWAES_set_encrypt_key(key + bytes, bits, &xctx->ks2.ks);
xctx->xts.block2 = (block128_f) HWAES_encrypt;
xctx->xts.key1 = &xctx->ks1;
@@ -3416,26 +3190,20 @@ static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
#endif
#ifdef BSAES_CAPABLE
if (BSAES_CAPABLE)
- xctx->stream = enc ? bsaes_xts_encrypt : bsaes_xts_decrypt;
+ xctx->stream = enc ? ossl_bsaes_xts_encrypt : ossl_bsaes_xts_decrypt;
else
#endif
#ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
if (enc) {
- vpaes_set_encrypt_key(key,
- EVP_CIPHER_CTX_key_length(ctx) * 4,
- &xctx->ks1.ks);
+ vpaes_set_encrypt_key(key, bits, &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) vpaes_encrypt;
} else {
- vpaes_set_decrypt_key(key,
- EVP_CIPHER_CTX_key_length(ctx) * 4,
- &xctx->ks1.ks);
+ vpaes_set_decrypt_key(key, bits, &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) vpaes_decrypt;
}
- vpaes_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2,
- EVP_CIPHER_CTX_key_length(ctx) * 4,
- &xctx->ks2.ks);
+ vpaes_set_encrypt_key(key + bytes, bits, &xctx->ks2.ks);
xctx->xts.block2 = (block128_f) vpaes_encrypt;
xctx->xts.key1 = &xctx->ks1;
@@ -3445,26 +3213,23 @@ static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
(void)0; /* terminate potentially open 'else' */
if (enc) {
- AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4,
- &xctx->ks1.ks);
+ AES_set_encrypt_key(key, bits, &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) AES_encrypt;
} else {
- AES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4,
- &xctx->ks1.ks);
+ AES_set_decrypt_key(key, bits, &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) AES_decrypt;
}
- AES_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2,
- EVP_CIPHER_CTX_key_length(ctx) * 4,
- &xctx->ks2.ks);
+ AES_set_encrypt_key(key + bytes, bits, &xctx->ks2.ks);
xctx->xts.block2 = (block128_f) AES_encrypt;
xctx->xts.key1 = &xctx->ks1;
} while (0);
+ }
if (iv) {
xctx->xts.key2 = &xctx->ks2;
- memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 16);
+ memcpy(ctx->iv, iv, 16);
}
return 1;
@@ -3474,17 +3239,31 @@ static int aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx);
- if (!xctx->xts.key1 || !xctx->xts.key2)
+
+ if (xctx->xts.key1 == NULL
+ || xctx->xts.key2 == NULL
+ || out == NULL
+ || in == NULL
+ || len < AES_BLOCK_SIZE)
return 0;
- if (!out || !in || len < AES_BLOCK_SIZE)
+
+ /*
+ * Impose a limit of 2^20 blocks per data unit as specified by
+ * IEEE Std 1619-2018. The earlier and obsolete IEEE Std 1619-2007
+ * indicated that this was a SHOULD NOT rather than a MUST NOT.
+ * NIST SP 800-38E mandates the same limit.
+ */
+ if (len > XTS_MAX_BLOCKS_PER_DATA_UNIT * AES_BLOCK_SIZE) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_XTS_DATA_UNIT_IS_TOO_LARGE);
return 0;
+ }
+
if (xctx->stream)
(*xctx->stream) (in, out, len,
xctx->xts.key1, xctx->xts.key2,
- EVP_CIPHER_CTX_iv_noconst(ctx));
- else if (CRYPTO_xts128_encrypt(&xctx->xts, EVP_CIPHER_CTX_iv_noconst(ctx),
- in, out, len,
- EVP_CIPHER_CTX_encrypting(ctx)))
+ ctx->iv);
+ else if (CRYPTO_xts128_encrypt(&xctx->xts, ctx->iv, in, out, len,
+ EVP_CIPHER_CTX_is_encrypting(ctx)))
return 0;
return 1;
}
@@ -3511,9 +3290,11 @@ static int aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
cctx->len_set = 0;
cctx->tls_aad_len = -1;
return 1;
+
case EVP_CTRL_GET_IVLEN:
*(int *)ptr = 15 - cctx->L;
return 1;
+
case EVP_CTRL_AEAD_TLS1_AAD:
/* Save the AAD for later use */
if (arg != EVP_AEAD_TLS1_AAD_LEN)
@@ -3529,7 +3310,7 @@ static int aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
return 0;
len -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
/* If decrypting correct for tag too */
- if (!EVP_CIPHER_CTX_encrypting(c)) {
+ if (!EVP_CIPHER_CTX_is_encrypting(c)) {
if (len < cctx->M)
return 0;
len -= cctx->M;
@@ -3545,7 +3326,7 @@ static int aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
if (arg != EVP_CCM_TLS_FIXED_IV_LEN)
return 0;
/* Just copy to first part of IV */
- memcpy(EVP_CIPHER_CTX_iv_noconst(c), ptr, arg);
+ memcpy(c->iv, ptr, arg);
return 1;
case EVP_CTRL_AEAD_SET_IVLEN:
@@ -3560,7 +3341,7 @@ static int aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
case EVP_CTRL_AEAD_SET_TAG:
if ((arg & 1) || arg < 4 || arg > 16)
return 0;
- if (EVP_CIPHER_CTX_encrypting(c) && ptr)
+ if (EVP_CIPHER_CTX_is_encrypting(c) && ptr)
return 0;
if (ptr) {
cctx->tag_set = 1;
@@ -3570,7 +3351,7 @@ static int aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
return 1;
case EVP_CTRL_AEAD_GET_TAG:
- if (!EVP_CIPHER_CTX_encrypting(c) || !cctx->tag_set)
+ if (!EVP_CIPHER_CTX_is_encrypting(c) || !cctx->tag_set)
return 0;
if (!CRYPTO_ccm128_tag(&cctx->ccm, ptr, (size_t)arg))
return 0;
@@ -3607,7 +3388,8 @@ static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
do {
#ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
- HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ HWAES_set_encrypt_key(key,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
@@ -3619,7 +3401,8 @@ static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
#endif
#ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
- vpaes_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ vpaes_set_encrypt_key(key,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
&cctx->ks, (block128_f) vpaes_encrypt);
@@ -3628,7 +3411,7 @@ static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
break;
}
#endif
- AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
&cctx->ks, (block128_f) AES_encrypt);
@@ -3636,7 +3419,7 @@ static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
cctx->key_set = 1;
} while (0);
if (iv) {
- memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L);
+ memcpy(ctx->iv, iv, 15 - cctx->L);
cctx->iv_set = 1;
}
return 1;
@@ -3651,23 +3434,24 @@ static int aes_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (out != in || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)cctx->M))
return -1;
/* If encrypting set explicit IV from sequence number (start of AAD) */
- if (EVP_CIPHER_CTX_encrypting(ctx))
+ if (EVP_CIPHER_CTX_is_encrypting(ctx))
memcpy(out, EVP_CIPHER_CTX_buf_noconst(ctx),
EVP_CCM_TLS_EXPLICIT_IV_LEN);
/* Get rest of IV from explicit IV */
- memcpy(EVP_CIPHER_CTX_iv_noconst(ctx) + EVP_CCM_TLS_FIXED_IV_LEN, in,
+ memcpy(ctx->iv + EVP_CCM_TLS_FIXED_IV_LEN, in,
EVP_CCM_TLS_EXPLICIT_IV_LEN);
/* Correct length value */
len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M;
- if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), 15 - cctx->L,
+ if (CRYPTO_ccm128_setiv(ccm, ctx->iv, 15 - cctx->L,
len))
return -1;
/* Use saved AAD */
- CRYPTO_ccm128_aad(ccm, EVP_CIPHER_CTX_buf_noconst(ctx), cctx->tls_aad_len);
+ CRYPTO_ccm128_aad(ccm, EVP_CIPHER_CTX_buf_noconst(ctx),
+ cctx->tls_aad_len);
/* Fix buffer to point to payload */
in += EVP_CCM_TLS_EXPLICIT_IV_LEN;
out += EVP_CCM_TLS_EXPLICIT_IV_LEN;
- if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len,
cctx->str) :
CRYPTO_ccm128_encrypt(ccm, in, out, len))
@@ -3711,7 +3495,7 @@ static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (!out) {
if (!in) {
- if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx),
+ if (CRYPTO_ccm128_setiv(ccm, ctx->iv,
15 - cctx->L, len))
return -1;
cctx->len_set = 1;
@@ -3725,17 +3509,16 @@ static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
}
/* The tag must be set before actually decrypting data */
- if (!EVP_CIPHER_CTX_encrypting(ctx) && !cctx->tag_set)
+ if (!EVP_CIPHER_CTX_is_encrypting(ctx) && !cctx->tag_set)
return -1;
/* If not set length yet do it */
if (!cctx->len_set) {
- if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx),
- 15 - cctx->L, len))
+ if (CRYPTO_ccm128_setiv(ccm, ctx->iv, 15 - cctx->L, len))
return -1;
cctx->len_set = 1;
}
- if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len,
cctx->str) :
CRYPTO_ccm128_encrypt(ccm, in, out, len))
@@ -3767,14 +3550,14 @@ static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
BLOCK_CIPHER_custom(NID_aes, 128, 1, 12, ccm, CCM,
EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
- BLOCK_CIPHER_custom(NID_aes, 192, 1, 12, ccm, CCM,
- EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
- BLOCK_CIPHER_custom(NID_aes, 256, 1, 12, ccm, CCM,
- EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
+BLOCK_CIPHER_custom(NID_aes, 192, 1, 12, ccm, CCM,
+ EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
+BLOCK_CIPHER_custom(NID_aes, 256, 1, 12, ccm, CCM,
+ EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
typedef struct {
union {
- double align;
+ OSSL_UNION_ALIGN;
AES_KEY ks;
} ks;
/* Indicates if IV has been set */
@@ -3784,22 +3567,26 @@ typedef struct {
static int aes_wrap_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
+ int len;
EVP_AES_WRAP_CTX *wctx = EVP_C_DATA(EVP_AES_WRAP_CTX,ctx);
- if (!iv && !key)
+
+ if (iv == NULL && key == NULL)
return 1;
- if (key) {
- if (EVP_CIPHER_CTX_encrypting(ctx))
- AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ if (key != NULL) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx))
+ AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&wctx->ks.ks);
else
- AES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ AES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&wctx->ks.ks);
- if (!iv)
+ if (iv == NULL)
wctx->iv = NULL;
}
- if (iv) {
- memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, EVP_CIPHER_CTX_iv_length(ctx));
- wctx->iv = EVP_CIPHER_CTX_iv_noconst(ctx);
+ if (iv != NULL) {
+ if ((len = EVP_CIPHER_CTX_get_iv_length(ctx)) < 0)
+ return 0;
+ memcpy(ctx->iv, iv, len);
+ wctx->iv = ctx->iv;
}
return 1;
}
@@ -3810,7 +3597,7 @@ static int aes_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
EVP_AES_WRAP_CTX *wctx = EVP_C_DATA(EVP_AES_WRAP_CTX,ctx);
size_t rv;
/* AES wrap with padding has IV length of 4, without padding 8 */
- int pad = EVP_CIPHER_CTX_iv_length(ctx) == 4;
+ int pad = EVP_CIPHER_CTX_get_iv_length(ctx) == 4;
/* No final operation so always return zero length */
if (!in)
return 0;
@@ -3818,17 +3605,17 @@ static int aes_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (!inlen)
return -1;
/* If decrypting need at least 16 bytes and multiple of 8 */
- if (!EVP_CIPHER_CTX_encrypting(ctx) && (inlen < 16 || inlen & 0x7))
+ if (!EVP_CIPHER_CTX_is_encrypting(ctx) && (inlen < 16 || inlen & 0x7))
return -1;
/* If not padding input must be multiple of 8 */
if (!pad && inlen & 0x7)
return -1;
- if (is_partially_overlapping(out, in, inlen)) {
- EVPerr(EVP_F_AES_WRAP_CIPHER, EVP_R_PARTIALLY_OVERLAPPING);
+ if (ossl_is_partially_overlapping(out, in, inlen)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING);
return 0;
}
if (!out) {
- if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
/* If padding round up to multiple of 8 */
if (pad)
inlen = (inlen + 7) / 8 * 8;
@@ -3844,7 +3631,7 @@ static int aes_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
}
}
if (pad) {
- if (EVP_CIPHER_CTX_encrypting(ctx))
+ if (EVP_CIPHER_CTX_is_encrypting(ctx))
rv = CRYPTO_128_wrap_pad(&wctx->ks.ks, wctx->iv,
out, in, inlen,
(block128_f) AES_encrypt);
@@ -3853,7 +3640,7 @@ static int aes_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
out, in, inlen,
(block128_f) AES_decrypt);
} else {
- if (EVP_CIPHER_CTX_encrypting(ctx))
+ if (EVP_CIPHER_CTX_is_encrypting(ctx))
rv = CRYPTO_128_wrap(&wctx->ks.ks, wctx->iv,
out, in, inlen, (block128_f) AES_encrypt);
else
@@ -3869,7 +3656,7 @@ static int aes_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static const EVP_CIPHER aes_128_wrap = {
NID_id_aes128_wrap,
- 8, 16, 8, WRAP_FLAGS,
+ 8, 16, 8, WRAP_FLAGS, EVP_ORIG_GLOBAL,
aes_wrap_init_key, aes_wrap_cipher,
NULL,
sizeof(EVP_AES_WRAP_CTX),
@@ -3883,7 +3670,7 @@ const EVP_CIPHER *EVP_aes_128_wrap(void)
static const EVP_CIPHER aes_192_wrap = {
NID_id_aes192_wrap,
- 8, 24, 8, WRAP_FLAGS,
+ 8, 24, 8, WRAP_FLAGS, EVP_ORIG_GLOBAL,
aes_wrap_init_key, aes_wrap_cipher,
NULL,
sizeof(EVP_AES_WRAP_CTX),
@@ -3897,7 +3684,7 @@ const EVP_CIPHER *EVP_aes_192_wrap(void)
static const EVP_CIPHER aes_256_wrap = {
NID_id_aes256_wrap,
- 8, 32, 8, WRAP_FLAGS,
+ 8, 32, 8, WRAP_FLAGS, EVP_ORIG_GLOBAL,
aes_wrap_init_key, aes_wrap_cipher,
NULL,
sizeof(EVP_AES_WRAP_CTX),
@@ -3911,7 +3698,7 @@ const EVP_CIPHER *EVP_aes_256_wrap(void)
static const EVP_CIPHER aes_128_wrap_pad = {
NID_id_aes128_wrap_pad,
- 8, 16, 4, WRAP_FLAGS,
+ 8, 16, 4, WRAP_FLAGS, EVP_ORIG_GLOBAL,
aes_wrap_init_key, aes_wrap_cipher,
NULL,
sizeof(EVP_AES_WRAP_CTX),
@@ -3925,7 +3712,7 @@ const EVP_CIPHER *EVP_aes_128_wrap_pad(void)
static const EVP_CIPHER aes_192_wrap_pad = {
NID_id_aes192_wrap_pad,
- 8, 24, 4, WRAP_FLAGS,
+ 8, 24, 4, WRAP_FLAGS, EVP_ORIG_GLOBAL,
aes_wrap_init_key, aes_wrap_cipher,
NULL,
sizeof(EVP_AES_WRAP_CTX),
@@ -3939,7 +3726,7 @@ const EVP_CIPHER *EVP_aes_192_wrap_pad(void)
static const EVP_CIPHER aes_256_wrap_pad = {
NID_id_aes256_wrap_pad,
- 8, 32, 4, WRAP_FLAGS,
+ 8, 32, 4, WRAP_FLAGS, EVP_ORIG_GLOBAL,
aes_wrap_init_key, aes_wrap_cipher,
NULL,
sizeof(EVP_AES_WRAP_CTX),
@@ -3962,8 +3749,8 @@ static int aes_ocb_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
case EVP_CTRL_INIT:
octx->key_set = 0;
octx->iv_set = 0;
- octx->ivlen = EVP_CIPHER_iv_length(c->cipher);
- octx->iv = EVP_CIPHER_CTX_iv_noconst(c);
+ octx->ivlen = EVP_CIPHER_get_iv_length(c->cipher);
+ octx->iv = c->iv;
octx->taglen = 16;
octx->data_buf_len = 0;
octx->aad_buf_len = 0;
@@ -3982,7 +3769,7 @@ static int aes_ocb_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
return 1;
case EVP_CTRL_AEAD_SET_TAG:
- if (!ptr) {
+ if (ptr == NULL) {
/* Tag len must be 0 to 16 */
if (arg < 0 || arg > 16)
return 0;
@@ -3990,13 +3777,13 @@ static int aes_ocb_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
octx->taglen = arg;
return 1;
}
- if (arg != octx->taglen || EVP_CIPHER_CTX_encrypting(c))
+ if (arg != octx->taglen || EVP_CIPHER_CTX_is_encrypting(c))
return 0;
memcpy(octx->tag, ptr, arg);
return 1;
case EVP_CTRL_AEAD_GET_TAG:
- if (arg != octx->taglen || !EVP_CIPHER_CTX_encrypting(c))
+ if (arg != octx->taglen || !EVP_CIPHER_CTX_is_encrypting(c))
return 0;
memcpy(ptr, octx->tag, arg);
@@ -4015,29 +3802,6 @@ static int aes_ocb_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
}
}
-# ifdef HWAES_CAPABLE
-# ifdef HWAES_ocb_encrypt
-void HWAES_ocb_encrypt(const unsigned char *in, unsigned char *out,
- size_t blocks, const void *key,
- size_t start_block_num,
- unsigned char offset_i[16],
- const unsigned char L_[][16],
- unsigned char checksum[16]);
-# else
-# define HWAES_ocb_encrypt ((ocb128_f)NULL)
-# endif
-# ifdef HWAES_ocb_decrypt
-void HWAES_ocb_decrypt(const unsigned char *in, unsigned char *out,
- size_t blocks, const void *key,
- size_t start_block_num,
- unsigned char offset_i[16],
- const unsigned char L_[][16],
- unsigned char checksum[16]);
-# else
-# define HWAES_ocb_decrypt ((ocb128_f)NULL)
-# endif
-# endif
-
static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
@@ -4053,9 +3817,9 @@ static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
*/
# ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
- HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&octx->ksenc.ks);
- HWAES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ HWAES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&octx->ksdec.ks);
if (!CRYPTO_ocb128_init(&octx->ocb,
&octx->ksenc.ks, &octx->ksdec.ks,
@@ -4069,9 +3833,11 @@ static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
# endif
# ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
- vpaes_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ vpaes_set_encrypt_key(key,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&octx->ksenc.ks);
- vpaes_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ vpaes_set_decrypt_key(key,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&octx->ksdec.ks);
if (!CRYPTO_ocb128_init(&octx->ocb,
&octx->ksenc.ks, &octx->ksdec.ks,
@@ -4082,9 +3848,9 @@ static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
break;
}
# endif
- AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&octx->ksenc.ks);
- AES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ AES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&octx->ksdec.ks);
if (!CRYPTO_ocb128_init(&octx->ocb,
&octx->ksenc.ks, &octx->ksdec.ks,
@@ -4150,8 +3916,8 @@ static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
buf = octx->data_buf;
buf_len = &(octx->data_buf_len);
- if (is_partially_overlapping(out + *buf_len, in, len)) {
- EVPerr(EVP_F_AES_OCB_CIPHER, EVP_R_PARTIALLY_OVERLAPPING);
+ if (ossl_is_partially_overlapping(out + *buf_len, in, len)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING);
return 0;
}
}
@@ -4179,7 +3945,7 @@ static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (out == NULL) {
if (!CRYPTO_ocb128_aad(&octx->ocb, buf, AES_BLOCK_SIZE))
return -1;
- } else if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ } else if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
if (!CRYPTO_ocb128_encrypt(&octx->ocb, buf, out,
AES_BLOCK_SIZE))
return -1;
@@ -4204,7 +3970,7 @@ static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (out == NULL) {
if (!CRYPTO_ocb128_aad(&octx->ocb, in, len - trailing_len))
return -1;
- } else if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ } else if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
if (!CRYPTO_ocb128_encrypt
(&octx->ocb, in, out, len - trailing_len))
return -1;
@@ -4230,7 +3996,7 @@ static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
* have been provided - both for data and AAD
*/
if (octx->data_buf_len > 0) {
- if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
if (!CRYPTO_ocb128_encrypt(&octx->ocb, octx->data_buf, out,
octx->data_buf_len))
return -1;
@@ -4249,7 +4015,7 @@ static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
octx->aad_buf_len = 0;
}
/* If decrypting then verify */
- if (!EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (!EVP_CIPHER_CTX_is_encrypting(ctx)) {
if (octx->taglen < 0)
return -1;
if (CRYPTO_ocb128_finish(&octx->ocb,
diff --git a/crypto/evp/e_aes_cbc_hmac_sha1.c b/crypto/evp/e_aes_cbc_hmac_sha1.c
index 27c36b46e7a4..4941f98e6483 100644
--- a/crypto/evp/e_aes_cbc_hmac_sha1.c
+++ b/crypto/evp/e_aes_cbc_hmac_sha1.c
@@ -1,25 +1,32 @@
/*
- * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/opensslconf.h>
+/*
+ * AES low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
#include <stdio.h>
#include <string.h>
-
+#include <openssl/opensslconf.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/aes.h>
#include <openssl/sha.h>
#include <openssl/rand.h>
-#include "modes_local.h"
+#include "internal/cryptlib.h"
+#include "crypto/modes.h"
#include "crypto/evp.h"
#include "internal/constant_time.h"
+#include "evp_local.h"
typedef struct {
AES_KEY ks;
@@ -33,11 +40,10 @@ typedef struct {
#define NO_PAYLOAD_LENGTH ((size_t)-1)
-#if defined(AESNI_ASM) && ( \
+#if defined(AES_ASM) && ( \
defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64) )
-extern unsigned int OPENSSL_ia32cap_P[];
# define AESNI_CAPABLE (1<<(57-32))
int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
@@ -69,11 +75,11 @@ static int aesni_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx,
if (enc)
ret = aesni_set_encrypt_key(inkey,
- EVP_CIPHER_CTX_key_length(ctx) * 8,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&key->ks);
else
ret = aesni_set_decrypt_key(inkey,
- EVP_CIPHER_CTX_key_length(ctx) * 8,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&key->ks);
SHA1_Init(&key->head); /* handy when benchmarking */
@@ -418,7 +424,7 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (len % AES_BLOCK_SIZE)
return 0;
- if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
if (plen == NO_PAYLOAD_LENGTH)
plen = len;
else if (len !=
@@ -433,8 +439,7 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
&& (blocks = (plen - (sha_off + iv)) / SHA_CBLOCK)) {
SHA1_Update(&key->md, in + iv, sha_off);
- aesni_cbc_sha1_enc(in, out, blocks, &key->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx),
+ aesni_cbc_sha1_enc(in, out, blocks, &key->ks, ctx->iv,
&key->md, in + iv + sha_off);
blocks *= SHA_CBLOCK;
aes_off += blocks;
@@ -466,10 +471,10 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
out[plen] = l;
/* encrypt HMAC|padding at once */
aesni_cbc_encrypt(out + aes_off, out + aes_off, len - aes_off,
- &key->ks, EVP_CIPHER_CTX_iv_noconst(ctx), 1);
+ &key->ks, ctx->iv, 1);
} else {
aesni_cbc_encrypt(in + aes_off, out + aes_off, len - aes_off,
- &key->ks, EVP_CIPHER_CTX_iv_noconst(ctx), 1);
+ &key->ks, ctx->iv, 1);
}
} else {
union {
@@ -499,7 +504,7 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return 0;
/* omit explicit iv */
- memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), in, AES_BLOCK_SIZE);
+ memcpy(ctx->iv, in, AES_BLOCK_SIZE);
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
@@ -520,7 +525,7 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
# endif
/* decrypt HMAC|padding at once */
aesni_cbc_encrypt(in, out, len, &key->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), 0);
+ ctx->iv, 0);
/* figure out payload length */
pad = out[len - 1];
@@ -697,8 +702,7 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
size_t off = out - p;
unsigned int c, cmask;
- maxpad += SHA_DIGEST_LENGTH;
- for (res = 0, i = 0, j = 0; j < maxpad; j++) {
+ for (res = 0, i = 0, j = 0; j < maxpad + SHA_DIGEST_LENGTH; j++) {
c = p[j];
cmask =
((int)(j - off - SHA_DIGEST_LENGTH)) >> (sizeof(int) *
@@ -708,7 +712,6 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
res |= (c ^ pmac->c[i]) & cmask;
i += 1 & cmask;
}
- maxpad -= SHA_DIGEST_LENGTH;
res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1));
ret &= (int)~res;
@@ -756,7 +759,7 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
# endif
/* decrypt HMAC|padding at once */
aesni_cbc_encrypt(in, out, len, &key->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), 0);
+ ctx->iv, 0);
SHA1_Update(&key->md, out, len);
}
@@ -810,7 +813,7 @@ static int aesni_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
len = p[arg - 2] << 8 | p[arg - 1];
- if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
key->payload_length = len;
if ((key->aux.tls_ver =
p[arg - 4] << 8 | p[arg - 3]) >= TLS1_1_VERSION) {
@@ -848,7 +851,7 @@ static int aesni_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
inp_len = param->inp[11] << 8 | param->inp[12];
- if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
if ((param->inp[9] << 8 | param->inp[10]) < TLS1_1_VERSION)
return -1;
@@ -911,6 +914,7 @@ static EVP_CIPHER aesni_128_cbc_hmac_sha1_cipher = {
AES_BLOCK_SIZE, 16, AES_BLOCK_SIZE,
EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 |
EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK,
+ EVP_ORIG_GLOBAL,
aesni_cbc_hmac_sha1_init_key,
aesni_cbc_hmac_sha1_cipher,
NULL,
@@ -930,6 +934,7 @@ static EVP_CIPHER aesni_256_cbc_hmac_sha1_cipher = {
AES_BLOCK_SIZE, 32, AES_BLOCK_SIZE,
EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 |
EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK,
+ EVP_ORIG_GLOBAL,
aesni_cbc_hmac_sha1_init_key,
aesni_cbc_hmac_sha1_cipher,
NULL,
diff --git a/crypto/evp/e_aes_cbc_hmac_sha256.c b/crypto/evp/e_aes_cbc_hmac_sha256.c
index cc622b6faa8c..3a5f757dbff3 100644
--- a/crypto/evp/e_aes_cbc_hmac_sha256.c
+++ b/crypto/evp/e_aes_cbc_hmac_sha256.c
@@ -1,26 +1,32 @@
/*
- * Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/opensslconf.h>
+/*
+ * AES low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
#include <stdio.h>
#include <string.h>
-
-
+#include <openssl/opensslconf.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/aes.h>
#include <openssl/sha.h>
#include <openssl/rand.h>
-#include "modes_local.h"
+#include "internal/cryptlib.h"
+#include "crypto/modes.h"
#include "internal/constant_time.h"
#include "crypto/evp.h"
+#include "evp_local.h"
typedef struct {
AES_KEY ks;
@@ -34,11 +40,10 @@ typedef struct {
# define NO_PAYLOAD_LENGTH ((size_t)-1)
-#if defined(AESNI_ASM) && ( \
+#if defined(AES_ASM) && ( \
defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64) )
-extern unsigned int OPENSSL_ia32cap_P[];
# define AESNI_CAPABLE (1<<(57-32))
int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
@@ -66,11 +71,11 @@ static int aesni_cbc_hmac_sha256_init_key(EVP_CIPHER_CTX *ctx,
if (enc)
ret = aesni_set_encrypt_key(inkey,
- EVP_CIPHER_CTX_key_length(ctx) * 8,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&key->ks);
else
ret = aesni_set_decrypt_key(inkey,
- EVP_CIPHER_CTX_key_length(ctx) * 8,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
&key->ks);
SHA256_Init(&key->head); /* handy when benchmarking */
@@ -434,7 +439,7 @@ static int aesni_cbc_hmac_sha256_cipher(EVP_CIPHER_CTX *ctx,
if (len % AES_BLOCK_SIZE)
return 0;
- if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
if (plen == NO_PAYLOAD_LENGTH)
plen = len;
else if (len !=
@@ -464,8 +469,7 @@ static int aesni_cbc_hmac_sha256_cipher(EVP_CIPHER_CTX *ctx,
SHA256_Update(&key->md, in + iv, sha_off);
(void)aesni_cbc_sha256_enc(in, out, blocks, &key->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx),
- &key->md, in + iv + sha_off);
+ ctx->iv, &key->md, in + iv + sha_off);
blocks *= SHA256_CBLOCK;
aes_off += blocks;
sha_off += blocks;
@@ -496,10 +500,10 @@ static int aesni_cbc_hmac_sha256_cipher(EVP_CIPHER_CTX *ctx,
out[plen] = l;
/* encrypt HMAC|padding at once */
aesni_cbc_encrypt(out + aes_off, out + aes_off, len - aes_off,
- &key->ks, EVP_CIPHER_CTX_iv_noconst(ctx), 1);
+ &key->ks, ctx->iv, 1);
} else {
aesni_cbc_encrypt(in + aes_off, out + aes_off, len - aes_off,
- &key->ks, EVP_CIPHER_CTX_iv_noconst(ctx), 1);
+ &key->ks, ctx->iv, 1);
}
} else {
union {
@@ -512,7 +516,7 @@ static int aesni_cbc_hmac_sha256_cipher(EVP_CIPHER_CTX *ctx,
/* decrypt HMAC|padding at once */
aesni_cbc_encrypt(in, out, len, &key->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), 0);
+ ctx->iv, 0);
if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */
size_t inp_len, mask, j, i;
@@ -702,8 +706,8 @@ static int aesni_cbc_hmac_sha256_cipher(EVP_CIPHER_CTX *ctx,
size_t off = out - p;
unsigned int c, cmask;
- maxpad += SHA256_DIGEST_LENGTH;
- for (res = 0, i = 0, j = 0; j < maxpad; j++) {
+ for (res = 0, i = 0, j = 0; j < maxpad + SHA256_DIGEST_LENGTH;
+ j++) {
c = p[j];
cmask =
((int)(j - off - SHA256_DIGEST_LENGTH)) >>
@@ -713,7 +717,6 @@ static int aesni_cbc_hmac_sha256_cipher(EVP_CIPHER_CTX *ctx,
res |= (c ^ pmac->c[i]) & cmask;
i += 1 & cmask;
}
- maxpad -= SHA256_DIGEST_LENGTH;
res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1));
ret &= (int)~res;
@@ -791,7 +794,7 @@ static int aesni_cbc_hmac_sha256_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
len = p[arg - 2] << 8 | p[arg - 1];
- if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
key->payload_length = len;
if ((key->aux.tls_ver =
p[arg - 4] << 8 | p[arg - 3]) >= TLS1_1_VERSION) {
@@ -832,7 +835,7 @@ static int aesni_cbc_hmac_sha256_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
inp_len = param->inp[11] << 8 | param->inp[12];
- if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
if ((param->inp[9] << 8 | param->inp[10]) < TLS1_1_VERSION)
return -1;
@@ -895,6 +898,7 @@ static EVP_CIPHER aesni_128_cbc_hmac_sha256_cipher = {
AES_BLOCK_SIZE, 16, AES_BLOCK_SIZE,
EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 |
EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK,
+ EVP_ORIG_GLOBAL,
aesni_cbc_hmac_sha256_init_key,
aesni_cbc_hmac_sha256_cipher,
NULL,
@@ -914,6 +918,7 @@ static EVP_CIPHER aesni_256_cbc_hmac_sha256_cipher = {
AES_BLOCK_SIZE, 32, AES_BLOCK_SIZE,
EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 |
EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK,
+ EVP_ORIG_GLOBAL,
aesni_cbc_hmac_sha256_init_key,
aesni_cbc_hmac_sha256_cipher,
NULL,
@@ -947,4 +952,4 @@ const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha256(void)
{
return NULL;
}
-#endif /* AESNI_ASM */
+#endif
diff --git a/crypto/evp/e_aria.c b/crypto/evp/e_aria.c
index 1cc6dd91a95a..7e1fda33e121 100644
--- a/crypto/evp/e_aria.c
+++ b/crypto/evp/e_aria.c
@@ -1,22 +1,23 @@
/*
- * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#include "internal/deprecated.h"
+
#include "internal/cryptlib.h"
#ifndef OPENSSL_NO_ARIA
# include <openssl/evp.h>
# include <openssl/modes.h>
# include <openssl/rand.h>
-# include <openssl/rand_drbg.h>
# include "crypto/aria.h"
# include "crypto/evp.h"
-# include "modes_local.h"
+# include "crypto/modes.h"
# include "evp_local.h"
/* ARIA subkey Structure */
@@ -27,7 +28,7 @@ typedef struct {
/* ARIA GCM context */
typedef struct {
union {
- double align;
+ OSSL_UNION_ALIGN;
ARIA_KEY ks;
} ks; /* ARIA subkey to use */
int key_set; /* Set if key initialised */
@@ -43,7 +44,7 @@ typedef struct {
/* ARIA CCM context */
typedef struct {
union {
- double align;
+ OSSL_UNION_ALIGN;
ARIA_KEY ks;
} ks; /* ARIA key schedule to use */
int key_set; /* Set if key initialised */
@@ -61,16 +62,18 @@ static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
int ret;
- int mode = EVP_CIPHER_CTX_mode(ctx);
+ int mode = EVP_CIPHER_CTX_get_mode(ctx);
if (enc || (mode != EVP_CIPH_ECB_MODE && mode != EVP_CIPH_CBC_MODE))
- ret = aria_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ ret = ossl_aria_set_encrypt_key(key,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
EVP_CIPHER_CTX_get_cipher_data(ctx));
else
- ret = aria_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
+ ret = ossl_aria_set_decrypt_key(key,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
EVP_CIPHER_CTX_get_cipher_data(ctx));
if (ret < 0) {
- EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);
+ ERR_raise(ERR_LIB_EVP,EVP_R_ARIA_KEY_SETUP_FAILED);
return 0;
}
return 1;
@@ -83,10 +86,10 @@ static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,
if (enc)
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,
- (block128_f) aria_encrypt);
+ (block128_f) ossl_aria_encrypt);
else
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,
- (block128_f) aria_encrypt);
+ (block128_f) ossl_aria_encrypt);
}
static void aria_cfb128_encrypt(const unsigned char *in, unsigned char *out,
@@ -95,7 +98,7 @@ static void aria_cfb128_encrypt(const unsigned char *in, unsigned char *out,
{
CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc,
- (block128_f) aria_encrypt);
+ (block128_f) ossl_aria_encrypt);
}
static void aria_cfb1_encrypt(const unsigned char *in, unsigned char *out,
@@ -103,7 +106,7 @@ static void aria_cfb1_encrypt(const unsigned char *in, unsigned char *out,
unsigned char *ivec, int *num, const int enc)
{
CRYPTO_cfb128_1_encrypt(in, out, length, key, ivec, num, enc,
- (block128_f) aria_encrypt);
+ (block128_f) ossl_aria_encrypt);
}
static void aria_cfb8_encrypt(const unsigned char *in, unsigned char *out,
@@ -111,13 +114,13 @@ static void aria_cfb8_encrypt(const unsigned char *in, unsigned char *out,
unsigned char *ivec, int *num, const int enc)
{
CRYPTO_cfb128_8_encrypt(in, out, length, key, ivec, num, enc,
- (block128_f) aria_encrypt);
+ (block128_f) ossl_aria_encrypt);
}
static void aria_ecb_encrypt(const unsigned char *in, unsigned char *out,
const ARIA_KEY *key, const int enc)
{
- aria_encrypt(in, out, key);
+ ossl_aria_encrypt(in, out, key);
}
static void aria_ofb128_encrypt(const unsigned char *in, unsigned char *out,
@@ -125,7 +128,7 @@ static void aria_ofb128_encrypt(const unsigned char *in, unsigned char *out,
unsigned char *ivec, int *num)
{
CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num,
- (block128_f) aria_encrypt);
+ (block128_f) ossl_aria_encrypt);
}
IMPLEMENT_BLOCK_CIPHER(aria_128, ks, aria, EVP_ARIA_KEY,
@@ -160,6 +163,7 @@ IMPLEMENT_ARIA_CFBR(256,8)
static const EVP_CIPHER aria_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
aria_init_key, \
aria_##mode##_cipher, \
NULL, \
@@ -171,13 +175,17 @@ const EVP_CIPHER *EVP_aria_##keylen##_##mode(void) \
static int aria_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
- unsigned int num = EVP_CIPHER_CTX_num(ctx);
- EVP_ARIA_KEY *dat = EVP_C_DATA(EVP_ARIA_KEY,ctx);
+ int n = EVP_CIPHER_CTX_get_num(ctx);
+ unsigned int num;
+ EVP_ARIA_KEY *dat = EVP_C_DATA(EVP_ARIA_KEY, ctx);
+
+ if (n < 0)
+ return 0;
+ num = (unsigned int)n;
- CRYPTO_ctr128_encrypt(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx),
+ CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv,
EVP_CIPHER_CTX_buf_noconst(ctx), &num,
- (block128_f) aria_encrypt);
+ (block128_f) ossl_aria_encrypt);
EVP_CIPHER_CTX_set_num(ctx, num);
return 1;
}
@@ -213,12 +221,13 @@ static int aria_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
if (!iv && !key)
return 1;
if (key) {
- ret = aria_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
- &gctx->ks.ks);
+ ret = ossl_aria_set_encrypt_key(key,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
+ &gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
- (block128_f) aria_encrypt);
+ (block128_f) ossl_aria_encrypt);
if (ret < 0) {
- EVPerr(EVP_F_ARIA_GCM_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);
+ ERR_raise(ERR_LIB_EVP,EVP_R_ARIA_KEY_SETUP_FAILED);
return 0;
}
@@ -252,41 +261,41 @@ static int aria_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
case EVP_CTRL_INIT:
gctx->key_set = 0;
gctx->iv_set = 0;
- gctx->ivlen = EVP_CIPHER_iv_length(c->cipher);
- gctx->iv = EVP_CIPHER_CTX_iv_noconst(c);
+ gctx->ivlen = EVP_CIPHER_get_iv_length(c->cipher);
+ gctx->iv = c->iv;
gctx->taglen = -1;
gctx->iv_gen = 0;
gctx->tls_aad_len = -1;
return 1;
+ case EVP_CTRL_GET_IVLEN:
+ *(int *)ptr = gctx->ivlen;
+ return 1;
+
case EVP_CTRL_AEAD_SET_IVLEN:
if (arg <= 0)
return 0;
/* Allocate memory for IV if needed */
if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen)) {
- if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(c))
+ if (gctx->iv != c->iv)
OPENSSL_free(gctx->iv);
if ((gctx->iv = OPENSSL_malloc(arg)) == NULL) {
- EVPerr(EVP_F_ARIA_GCM_CTRL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
}
gctx->ivlen = arg;
return 1;
- case EVP_CTRL_GET_IVLEN:
- *(int *)ptr = gctx->ivlen;
- return 1;
-
case EVP_CTRL_AEAD_SET_TAG:
- if (arg <= 0 || arg > 16 || EVP_CIPHER_CTX_encrypting(c))
+ if (arg <= 0 || arg > 16 || EVP_CIPHER_CTX_is_encrypting(c))
return 0;
memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg);
gctx->taglen = arg;
return 1;
case EVP_CTRL_AEAD_GET_TAG:
- if (arg <= 0 || arg > 16 || !EVP_CIPHER_CTX_encrypting(c)
+ if (arg <= 0 || arg > 16 || !EVP_CIPHER_CTX_is_encrypting(c)
|| gctx->taglen < 0)
return 0;
memcpy(ptr, EVP_CIPHER_CTX_buf_noconst(c), arg);
@@ -307,7 +316,7 @@ static int aria_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
return 0;
if (arg)
memcpy(gctx->iv, ptr, arg);
- if (EVP_CIPHER_CTX_encrypting(c)
+ if (EVP_CIPHER_CTX_is_encrypting(c)
&& RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
return 0;
gctx->iv_gen = 1;
@@ -330,7 +339,7 @@ static int aria_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
case EVP_CTRL_GCM_SET_IV_INV:
if (gctx->iv_gen == 0 || gctx->key_set == 0
- || EVP_CIPHER_CTX_encrypting(c))
+ || EVP_CIPHER_CTX_is_encrypting(c))
return 0;
memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
@@ -352,7 +361,7 @@ static int aria_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
return 0;
len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
/* If decrypting correct for tag too */
- if (!EVP_CIPHER_CTX_encrypting(c)) {
+ if (!EVP_CIPHER_CTX_is_encrypting(c)) {
if (len < EVP_GCM_TLS_TAG_LEN)
return 0;
len -= EVP_GCM_TLS_TAG_LEN;
@@ -372,11 +381,11 @@ static int aria_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
return 0;
gctx_out->gcm.key = &gctx_out->ks;
}
- if (gctx->iv == EVP_CIPHER_CTX_iv_noconst(c))
- gctx_out->iv = EVP_CIPHER_CTX_iv_noconst(out);
+ if (gctx->iv == c->iv)
+ gctx_out->iv = out->iv;
else {
if ((gctx_out->iv = OPENSSL_malloc(gctx->ivlen)) == NULL) {
- EVPerr(EVP_F_ARIA_GCM_CTRL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
@@ -404,7 +413,7 @@ static int aria_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
* Set IV from start of buffer or generate IV and write to start of
* buffer.
*/
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CIPHER_CTX_encrypting(ctx) ?
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CIPHER_CTX_is_encrypting(ctx) ?
EVP_CTRL_GCM_IV_GEN : EVP_CTRL_GCM_SET_IV_INV,
EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0)
goto err;
@@ -416,7 +425,7 @@ static int aria_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
- if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
/* Encrypt payload */
if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
goto err;
@@ -464,7 +473,7 @@ static int aria_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (out == NULL) {
if (CRYPTO_gcm128_aad(&gctx->gcm, in, len))
return -1;
- } else if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ } else if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
return -1;
} else {
@@ -473,7 +482,7 @@ static int aria_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
}
return len;
}
- if (!EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (!EVP_CIPHER_CTX_is_encrypting(ctx)) {
if (gctx->taglen < 0)
return -1;
if (CRYPTO_gcm128_finish(&gctx->gcm,
@@ -494,7 +503,7 @@ static int aria_gcm_cleanup(EVP_CIPHER_CTX *ctx)
{
EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX, ctx);
- if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(ctx))
+ if (gctx->iv != ctx->iv)
OPENSSL_free(gctx->iv);
return 1;
@@ -510,19 +519,20 @@ static int aria_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
return 1;
if (key) {
- ret = aria_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
- &cctx->ks.ks);
+ ret = ossl_aria_set_encrypt_key(key,
+ EVP_CIPHER_CTX_get_key_length(ctx) * 8,
+ &cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
- &cctx->ks, (block128_f) aria_encrypt);
+ &cctx->ks, (block128_f) ossl_aria_encrypt);
if (ret < 0) {
- EVPerr(EVP_F_ARIA_CCM_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);
+ ERR_raise(ERR_LIB_EVP,EVP_R_ARIA_KEY_SETUP_FAILED);
return 0;
}
cctx->str = NULL;
cctx->key_set = 1;
}
if (iv) {
- memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L);
+ memcpy(ctx->iv, iv, 15 - cctx->L);
cctx->iv_set = 1;
}
return 1;
@@ -543,6 +553,10 @@ static int aria_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
cctx->tls_aad_len = -1;
return 1;
+ case EVP_CTRL_GET_IVLEN:
+ *(int *)ptr = 15 - cctx->L;
+ return 1;
+
case EVP_CTRL_AEAD_TLS1_AAD:
/* Save the AAD for later use */
if (arg != EVP_AEAD_TLS1_AAD_LEN)
@@ -558,7 +572,7 @@ static int aria_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
return 0;
len -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
/* If decrypting correct for tag too */
- if (!EVP_CIPHER_CTX_encrypting(c)) {
+ if (!EVP_CIPHER_CTX_is_encrypting(c)) {
if (len < cctx->M)
return 0;
len -= cctx->M;
@@ -574,11 +588,7 @@ static int aria_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
if (arg != EVP_CCM_TLS_FIXED_IV_LEN)
return 0;
/* Just copy to first part of IV */
- memcpy(EVP_CIPHER_CTX_iv_noconst(c), ptr, arg);
- return 1;
-
- case EVP_CTRL_GET_IVLEN:
- *(int *)ptr = 15 - cctx->L;
+ memcpy(c->iv, ptr, arg);
return 1;
case EVP_CTRL_AEAD_SET_IVLEN:
@@ -592,7 +602,7 @@ static int aria_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
case EVP_CTRL_AEAD_SET_TAG:
if ((arg & 1) || arg < 4 || arg > 16)
return 0;
- if (EVP_CIPHER_CTX_encrypting(c) && ptr)
+ if (EVP_CIPHER_CTX_is_encrypting(c) && ptr)
return 0;
if (ptr) {
cctx->tag_set = 1;
@@ -602,7 +612,7 @@ static int aria_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
return 1;
case EVP_CTRL_AEAD_GET_TAG:
- if (!EVP_CIPHER_CTX_encrypting(c) || !cctx->tag_set)
+ if (!EVP_CIPHER_CTX_is_encrypting(c) || !cctx->tag_set)
return 0;
if (!CRYPTO_ccm128_tag(&cctx->ccm, ptr, (size_t)arg))
return 0;
@@ -638,23 +648,24 @@ static int aria_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (out != in || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)cctx->M))
return -1;
/* If encrypting set explicit IV from sequence number (start of AAD) */
- if (EVP_CIPHER_CTX_encrypting(ctx))
+ if (EVP_CIPHER_CTX_is_encrypting(ctx))
memcpy(out, EVP_CIPHER_CTX_buf_noconst(ctx),
EVP_CCM_TLS_EXPLICIT_IV_LEN);
/* Get rest of IV from explicit IV */
- memcpy(EVP_CIPHER_CTX_iv_noconst(ctx) + EVP_CCM_TLS_FIXED_IV_LEN, in,
+ memcpy(ctx->iv + EVP_CCM_TLS_FIXED_IV_LEN, in,
EVP_CCM_TLS_EXPLICIT_IV_LEN);
/* Correct length value */
len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M;
- if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), 15 - cctx->L,
+ if (CRYPTO_ccm128_setiv(ccm, ctx->iv, 15 - cctx->L,
len))
return -1;
/* Use saved AAD */
- CRYPTO_ccm128_aad(ccm, EVP_CIPHER_CTX_buf_noconst(ctx), cctx->tls_aad_len);
+ CRYPTO_ccm128_aad(ccm, EVP_CIPHER_CTX_buf_noconst(ctx),
+ cctx->tls_aad_len);
/* Fix buffer to point to payload */
in += EVP_CCM_TLS_EXPLICIT_IV_LEN;
out += EVP_CCM_TLS_EXPLICIT_IV_LEN;
- if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len, cctx->str)
: CRYPTO_ccm128_encrypt(ccm, in, out, len))
return -1;
@@ -697,8 +708,7 @@ static int aria_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (!out) {
if (!in) {
- if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx),
- 15 - cctx->L, len))
+ if (CRYPTO_ccm128_setiv(ccm, ctx->iv, 15 - cctx->L, len))
return -1;
cctx->len_set = 1;
return len;
@@ -711,17 +721,16 @@ static int aria_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
}
/* The tag must be set before actually decrypting data */
- if (!EVP_CIPHER_CTX_encrypting(ctx) && !cctx->tag_set)
+ if (!EVP_CIPHER_CTX_is_encrypting(ctx) && !cctx->tag_set)
return -1;
/* If not set length yet do it */
if (!cctx->len_set) {
- if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx),
- 15 - cctx->L, len))
+ if (CRYPTO_ccm128_setiv(ccm, ctx->iv, 15 - cctx->L, len))
return -1;
cctx->len_set = 1;
}
- if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len, cctx->str)
: CRYPTO_ccm128_encrypt(ccm, in, out, len))
return -1;
@@ -761,6 +770,7 @@ static const EVP_CIPHER aria_##keylen##_##mode = { \
nid##_##keylen##_##nmode, \
blocksize, keylen/8, ivlen, \
ARIA_AUTH_FLAGS|EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
aria_##mode##_init_key, \
aria_##mode##_cipher, \
aria_##mode##_cleanup, \
diff --git a/crypto/evp/e_bf.c b/crypto/evp/e_bf.c
index 9a065582c6c8..2aeda2ecf07a 100644
--- a/crypto/evp/e_bf.c
+++ b/crypto/evp/e_bf.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * BF low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#ifndef OPENSSL_NO_BF
@@ -14,6 +20,7 @@
# include "crypto/evp.h"
# include <openssl/objects.h>
# include <openssl/blowfish.h>
+# include "evp_local.h"
static int bf_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
@@ -31,7 +38,11 @@ IMPLEMENT_BLOCK_CIPHER(bf, ks, BF, EVP_BF_KEY, NID_bf, 8, 16, 8, 64,
static int bf_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
- BF_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), key);
+ int len = EVP_CIPHER_CTX_get_key_length(ctx);
+
+ if (len < 0)
+ return 0;
+ BF_set_key(&data(ctx)->ks, len, key);
return 1;
}
diff --git a/crypto/evp/e_camellia.c b/crypto/evp/e_camellia.c
index f8c019801267..4f1f4822dc92 100644
--- a/crypto/evp/e_camellia.c
+++ b/crypto/evp/e_camellia.c
@@ -1,24 +1,29 @@
/*
* Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * Camellia low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/opensslconf.h>
-#ifdef OPENSSL_NO_CAMELLIA
-NON_EMPTY_TRANSLATION_UNIT
-#else
-# include <openssl/evp.h>
-# include <openssl/err.h>
-# include <string.h>
-# include <assert.h>
-# include <openssl/camellia.h>
-# include "crypto/evp.h"
-# include "modes_local.h"
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <string.h>
+#include <assert.h>
+#include <openssl/camellia.h>
+#include "crypto/evp.h"
+#include "crypto/modes.h"
+#include "crypto/cmll_platform.h"
+#include "evp_local.h"
static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
@@ -33,44 +38,15 @@ typedef struct {
} stream;
} EVP_CAMELLIA_KEY;
-# define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4))
+#define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4))
/* Attribute operation for Camellia */
-# define data(ctx) EVP_C_DATA(EVP_CAMELLIA_KEY,ctx)
+#define data(ctx) EVP_C_DATA(EVP_CAMELLIA_KEY,ctx)
-# if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
+#if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
/* ---------^^^ this is not a typo, just a way to detect that
* assembler support was in general requested... */
-# include "sparc_arch.h"
-
-extern unsigned int OPENSSL_sparcv9cap_P[];
-
-# define SPARC_CMLL_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_CAMELLIA)
-
-void cmll_t4_set_key(const unsigned char *key, int bits, CAMELLIA_KEY *ks);
-void cmll_t4_encrypt(const unsigned char *in, unsigned char *out,
- const CAMELLIA_KEY *key);
-void cmll_t4_decrypt(const unsigned char *in, unsigned char *out,
- const CAMELLIA_KEY *key);
-
-void cmll128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
- size_t len, const CAMELLIA_KEY *key,
- unsigned char *ivec, int /*unused*/);
-void cmll128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
- size_t len, const CAMELLIA_KEY *key,
- unsigned char *ivec, int /*unused*/);
-void cmll256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
- size_t len, const CAMELLIA_KEY *key,
- unsigned char *ivec, int /*unused*/);
-void cmll256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
- size_t len, const CAMELLIA_KEY *key,
- unsigned char *ivec, int /*unused*/);
-void cmll128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
- size_t blocks, const CAMELLIA_KEY *key,
- unsigned char *ivec);
-void cmll256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
- size_t blocks, const CAMELLIA_KEY *key,
- unsigned char *ivec);
+# include "crypto/sparc_arch.h"
static int cmll_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
@@ -79,8 +55,8 @@ static int cmll_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
EVP_CAMELLIA_KEY *dat =
(EVP_CAMELLIA_KEY *)EVP_CIPHER_CTX_get_cipher_data(ctx);
- mode = EVP_CIPHER_CTX_mode(ctx);
- bits = EVP_CIPHER_CTX_key_length(ctx) * 8;
+ mode = EVP_CIPHER_CTX_get_mode(ctx);
+ bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8;
cmll_t4_set_key(key, bits, &dat->ks);
@@ -128,45 +104,46 @@ static int cmll_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
}
if (ret < 0) {
- EVPerr(EVP_F_CMLL_T4_INIT_KEY, EVP_R_CAMELLIA_KEY_SETUP_FAILED);
+ ERR_raise(ERR_LIB_EVP, EVP_R_CAMELLIA_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
-# define cmll_t4_cbc_cipher camellia_cbc_cipher
+# define cmll_t4_cbc_cipher camellia_cbc_cipher
static int cmll_t4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
-# define cmll_t4_ecb_cipher camellia_ecb_cipher
+# define cmll_t4_ecb_cipher camellia_ecb_cipher
static int cmll_t4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
-# define cmll_t4_ofb_cipher camellia_ofb_cipher
+# define cmll_t4_ofb_cipher camellia_ofb_cipher
static int cmll_t4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
-# define cmll_t4_cfb_cipher camellia_cfb_cipher
+# define cmll_t4_cfb_cipher camellia_cfb_cipher
static int cmll_t4_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
-# define cmll_t4_cfb8_cipher camellia_cfb8_cipher
+# define cmll_t4_cfb8_cipher camellia_cfb8_cipher
static int cmll_t4_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
-# define cmll_t4_cfb1_cipher camellia_cfb1_cipher
+# define cmll_t4_cfb1_cipher camellia_cfb1_cipher
static int cmll_t4_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
-# define cmll_t4_ctr_cipher camellia_ctr_cipher
+# define cmll_t4_ctr_cipher camellia_ctr_cipher
static int cmll_t4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
-# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
+# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
static const EVP_CIPHER cmll_t4_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
cmll_t4_init_key, \
cmll_t4_##mode##_cipher, \
NULL, \
@@ -176,6 +153,7 @@ static const EVP_CIPHER camellia_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize, \
keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
camellia_init_key, \
camellia_##mode##_cipher, \
NULL, \
@@ -184,12 +162,13 @@ static const EVP_CIPHER camellia_##keylen##_##mode = { \
const EVP_CIPHER *EVP_camellia_##keylen##_##mode(void) \
{ return SPARC_CMLL_CAPABLE?&cmll_t4_##keylen##_##mode:&camellia_##keylen##_##mode; }
-# else
+#else
-# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
+# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
static const EVP_CIPHER camellia_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
camellia_init_key, \
camellia_##mode##_cipher, \
NULL, \
@@ -198,9 +177,9 @@ static const EVP_CIPHER camellia_##keylen##_##mode = { \
const EVP_CIPHER *EVP_camellia_##keylen##_##mode(void) \
{ return &camellia_##keylen##_##mode; }
-# endif
+#endif
-# define BLOCK_CIPHER_generic_pack(nid,keylen,flags) \
+#define BLOCK_CIPHER_generic_pack(nid,keylen,flags) \
BLOCK_CIPHER_generic(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
BLOCK_CIPHER_generic(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
BLOCK_CIPHER_generic(nid,keylen,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
@@ -216,13 +195,14 @@ static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
int ret, mode;
EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx);
- ret = Camellia_set_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, &dat->ks);
+ ret = Camellia_set_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
+ &dat->ks);
if (ret < 0) {
- EVPerr(EVP_F_CAMELLIA_INIT_KEY, EVP_R_CAMELLIA_KEY_SETUP_FAILED);
+ ERR_raise(ERR_LIB_EVP, EVP_R_CAMELLIA_KEY_SETUP_FAILED);
return 0;
}
- mode = EVP_CIPHER_CTX_mode(ctx);
+ mode = EVP_CIPHER_CTX_get_mode(ctx);
if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
&& !enc) {
dat->block = (block128_f) Camellia_decrypt;
@@ -243,15 +223,12 @@ static int camellia_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx);
if (dat->stream.cbc)
- (*dat->stream.cbc) (in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx),
- EVP_CIPHER_CTX_encrypting(ctx));
- else if (EVP_CIPHER_CTX_encrypting(ctx))
- CRYPTO_cbc128_encrypt(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), dat->block);
+ (*dat->stream.cbc) (in, out, len, &dat->ks, ctx->iv,
+ EVP_CIPHER_CTX_is_encrypting(ctx));
+ else if (EVP_CIPHER_CTX_is_encrypting(ctx))
+ CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv, dat->block);
else
- CRYPTO_cbc128_decrypt(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), dat->block);
+ CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, ctx->iv, dat->block);
return 1;
}
@@ -259,7 +236,7 @@ static int camellia_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int camellia_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
- size_t bl = EVP_CIPHER_CTX_block_size(ctx);
+ size_t bl = EVP_CIPHER_CTX_get_block_size(ctx);
size_t i;
EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx);
@@ -277,9 +254,8 @@ static int camellia_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
{
EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx);
- int num = EVP_CIPHER_CTX_num(ctx);
- CRYPTO_ofb128_encrypt(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), &num, dat->block);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
+ CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, ctx->iv, &num, dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
return 1;
}
@@ -289,9 +265,9 @@ static int camellia_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
{
EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx);
- int num = EVP_CIPHER_CTX_num(ctx);
- CRYPTO_cfb128_encrypt(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), &num, EVP_CIPHER_CTX_encrypting(ctx), dat->block);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
+ CRYPTO_cfb128_encrypt(in, out, len, &dat->ks, ctx->iv, &num,
+ EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
return 1;
}
@@ -301,9 +277,9 @@ static int camellia_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
{
EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx);
- int num = EVP_CIPHER_CTX_num(ctx);
- CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), &num, EVP_CIPHER_CTX_encrypting(ctx), dat->block);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
+ CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks, ctx->iv, &num,
+ EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
return 1;
}
@@ -314,26 +290,31 @@ static int camellia_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx);
if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) {
- int num = EVP_CIPHER_CTX_num(ctx);
- CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), &num, EVP_CIPHER_CTX_encrypting(ctx), dat->block);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
+ CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks, ctx->iv, &num,
+ EVP_CIPHER_CTX_is_encrypting(ctx),
+ dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
return 1;
}
while (len >= MAXBITCHUNK) {
- int num = EVP_CIPHER_CTX_num(ctx);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), &num, EVP_CIPHER_CTX_encrypting(ctx), dat->block);
+ ctx->iv, &num,
+ EVP_CIPHER_CTX_is_encrypting(ctx),
+ dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
len -= MAXBITCHUNK;
out += MAXBITCHUNK;
in += MAXBITCHUNK;
}
if (len) {
- int num = EVP_CIPHER_CTX_num(ctx);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
CRYPTO_cfb128_1_encrypt(in, out, len * 8, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx), &num, EVP_CIPHER_CTX_encrypting(ctx), dat->block);
+ ctx->iv, &num,
+ EVP_CIPHER_CTX_is_encrypting(ctx),
+ dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
}
@@ -343,17 +324,20 @@ static int camellia_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int camellia_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
- unsigned int num = EVP_CIPHER_CTX_num(ctx);
+ int snum = EVP_CIPHER_CTX_get_num(ctx);
+ unsigned int num;
EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx);
+ if (snum < 0)
+ return 0;
+ num = snum;
if (dat->stream.ctr)
- CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx),
- EVP_CIPHER_CTX_buf_noconst(ctx), &num,
+ CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, ctx->iv,
+ EVP_CIPHER_CTX_buf_noconst(ctx),
+ &num,
dat->stream.ctr);
else
- CRYPTO_ctr128_encrypt(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx),
+ CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv,
EVP_CIPHER_CTX_buf_noconst(ctx), &num,
dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
@@ -363,4 +347,3 @@ static int camellia_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
BLOCK_CIPHER_generic_pack(NID_camellia, 128, 0)
BLOCK_CIPHER_generic_pack(NID_camellia, 192, 0)
BLOCK_CIPHER_generic_pack(NID_camellia, 256, 0)
-#endif
diff --git a/crypto/evp/e_cast.c b/crypto/evp/e_cast.c
index df9f445bd0a2..5e9be2dc7dd5 100644
--- a/crypto/evp/e_cast.c
+++ b/crypto/evp/e_cast.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * CAST low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
@@ -15,6 +21,7 @@
# include <openssl/objects.h>
# include "crypto/evp.h"
# include <openssl/cast.h>
+# include "evp_local.h"
static int cast_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
@@ -33,7 +40,11 @@ IMPLEMENT_BLOCK_CIPHER(cast5, ks, CAST, EVP_CAST_KEY,
static int cast_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
- CAST_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), key);
+ int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
+
+ if (keylen <= 0)
+ return 0;
+ CAST_set_key(&data(ctx)->ks, keylen, key);
return 1;
}
diff --git a/crypto/evp/e_chacha20_poly1305.c b/crypto/evp/e_chacha20_poly1305.c
index bdc406bb69dc..18e1c0b5ac06 100644
--- a/crypto/evp/e_chacha20_poly1305.c
+++ b/crypto/evp/e_chacha20_poly1305.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,18 +9,19 @@
#include <stdio.h>
#include "internal/cryptlib.h"
+#include "internal/endian.h"
#ifndef OPENSSL_NO_CHACHA
# include <openssl/evp.h>
# include <openssl/objects.h>
-# include "evp_local.h"
# include "crypto/evp.h"
+# include "evp_local.h"
# include "crypto/chacha.h"
typedef struct {
union {
- double align; /* this ensures even sizeof(EVP_CHACHA_KEY)%8==0 */
+ OSSL_UNION_ALIGN; /* this ensures even sizeof(EVP_CHACHA_KEY)%8==0 */
unsigned int d[CHACHA_KEY_SIZE / 4];
} key;
unsigned int counter[CHACHA_CTR_SIZE / 4];
@@ -130,6 +131,7 @@ static const EVP_CIPHER chacha20 = {
CHACHA_KEY_SIZE, /* key_len */
CHACHA_CTR_SIZE, /* iv_len, 128-bit counter in the context */
EVP_CIPH_CUSTOM_IV | EVP_CIPH_ALWAYS_CALL_INIT,
+ EVP_ORIG_GLOBAL,
chacha_init_key,
chacha_cipher,
NULL,
@@ -310,12 +312,9 @@ static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
}
{
- const union {
- long one;
- char little;
- } is_endian = { 1 };
+ DECLARE_IS_ENDIAN;
- if (is_endian.little) {
+ if (IS_LITTLE_ENDIAN) {
memcpy(ctr, (unsigned char *)&actx->len, POLY1305_BLOCK_SIZE);
} else {
ctr[0] = (unsigned char)(actx->len.aad);
@@ -426,10 +425,7 @@ static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
}
if (in == NULL /* explicit final */
|| plen != len) { /* or tls mode */
- const union {
- long one;
- char little;
- } is_endian = { 1 };
+ DECLARE_IS_ENDIAN;
unsigned char temp[POLY1305_BLOCK_SIZE];
if (actx->aad) { /* wrap up aad */
@@ -443,7 +439,7 @@ static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
Poly1305_Update(POLY1305_ctx(actx), zero,
POLY1305_BLOCK_SIZE - rem);
- if (is_endian.little) {
+ if (IS_LITTLE_ENDIAN) {
Poly1305_Update(POLY1305_ctx(actx),
(unsigned char *)&actx->len, POLY1305_BLOCK_SIZE);
} else {
@@ -508,7 +504,7 @@ static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
actx = ctx->cipher_data
= OPENSSL_zalloc(sizeof(*actx) + Poly1305_ctx_size());
if (actx == NULL) {
- EVPerr(EVP_F_CHACHA20_POLY1305_CTRL, EVP_R_INITIALIZATION_ERROR);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
actx->len.aad = 0;
@@ -528,7 +524,7 @@ static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
dst->cipher_data =
OPENSSL_memdup(actx, sizeof(*actx) + Poly1305_ctx_size());
if (dst->cipher_data == NULL) {
- EVPerr(EVP_F_CHACHA20_POLY1305_CTRL, EVP_R_COPY_ERROR);
+ ERR_raise(ERR_LIB_EVP, EVP_R_COPY_ERROR);
return 0;
}
}
@@ -619,6 +615,7 @@ static EVP_CIPHER chacha20_poly1305 = {
EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER |
EVP_CIPH_CUSTOM_IV_LENGTH,
+ EVP_ORIG_GLOBAL,
chacha20_poly1305_init_key,
chacha20_poly1305_cipher,
chacha20_poly1305_cleanup,
diff --git a/crypto/evp/e_des.c b/crypto/evp/e_des.c
index 6d6e919af696..cd6e5af8d0e4 100644
--- a/crypto/evp/e_des.c
+++ b/crypto/evp/e_des.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#ifndef OPENSSL_NO_DES
@@ -15,10 +21,11 @@
# include "crypto/evp.h"
# include <openssl/des.h>
# include <openssl/rand.h>
+# include "evp_local.h"
typedef struct {
union {
- double align;
+ OSSL_UNION_ALIGN;
DES_key_schedule ks;
} ks;
union {
@@ -30,9 +37,7 @@ typedef struct {
# if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
/* ----------^^^ this is not a typo, just a way to detect that
* assembler support was in general requested... */
-# include "sparc_arch.h"
-
-extern unsigned int OPENSSL_sparcv9cap_P[];
+# include "crypto/sparc_arch.h"
# define SPARC_DES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_DES)
@@ -58,7 +63,7 @@ static int des_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
BLOCK_CIPHER_ecb_loop()
DES_ecb_encrypt((DES_cblock *)(in + i), (DES_cblock *)(out + i),
EVP_CIPHER_CTX_get_cipher_data(ctx),
- EVP_CIPHER_CTX_encrypting(ctx));
+ EVP_CIPHER_CTX_is_encrypting(ctx));
return 1;
}
@@ -66,20 +71,20 @@ static int des_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
while (inl >= EVP_MAXCHUNK) {
- int num = EVP_CIPHER_CTX_num(ctx);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
DES_ofb64_encrypt(in, out, (long)EVP_MAXCHUNK,
EVP_CIPHER_CTX_get_cipher_data(ctx),
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), &num);
+ (DES_cblock *)ctx->iv, &num);
EVP_CIPHER_CTX_set_num(ctx, num);
inl -= EVP_MAXCHUNK;
in += EVP_MAXCHUNK;
out += EVP_MAXCHUNK;
}
if (inl) {
- int num = EVP_CIPHER_CTX_num(ctx);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
DES_ofb64_encrypt(in, out, (long)inl,
EVP_CIPHER_CTX_get_cipher_data(ctx),
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), &num);
+ (DES_cblock *)ctx->iv, &num);
EVP_CIPHER_CTX_set_num(ctx, num);
}
return 1;
@@ -91,15 +96,14 @@ static int des_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
EVP_DES_KEY *dat = (EVP_DES_KEY *) EVP_CIPHER_CTX_get_cipher_data(ctx);
if (dat->stream.cbc != NULL) {
- (*dat->stream.cbc) (in, out, inl, &dat->ks.ks,
- EVP_CIPHER_CTX_iv_noconst(ctx));
+ (*dat->stream.cbc) (in, out, inl, &dat->ks.ks, ctx->iv);
return 1;
}
while (inl >= EVP_MAXCHUNK) {
DES_ncbc_encrypt(in, out, (long)EVP_MAXCHUNK,
EVP_CIPHER_CTX_get_cipher_data(ctx),
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx),
- EVP_CIPHER_CTX_encrypting(ctx));
+ (DES_cblock *)ctx->iv,
+ EVP_CIPHER_CTX_is_encrypting(ctx));
inl -= EVP_MAXCHUNK;
in += EVP_MAXCHUNK;
out += EVP_MAXCHUNK;
@@ -107,8 +111,8 @@ static int des_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (inl)
DES_ncbc_encrypt(in, out, (long)inl,
EVP_CIPHER_CTX_get_cipher_data(ctx),
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx),
- EVP_CIPHER_CTX_encrypting(ctx));
+ (DES_cblock *)ctx->iv,
+ EVP_CIPHER_CTX_is_encrypting(ctx));
return 1;
}
@@ -116,22 +120,22 @@ static int des_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
while (inl >= EVP_MAXCHUNK) {
- int num = EVP_CIPHER_CTX_num(ctx);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
DES_cfb64_encrypt(in, out, (long)EVP_MAXCHUNK,
EVP_CIPHER_CTX_get_cipher_data(ctx),
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), &num,
- EVP_CIPHER_CTX_encrypting(ctx));
+ (DES_cblock *)ctx->iv, &num,
+ EVP_CIPHER_CTX_is_encrypting(ctx));
EVP_CIPHER_CTX_set_num(ctx, num);
inl -= EVP_MAXCHUNK;
in += EVP_MAXCHUNK;
out += EVP_MAXCHUNK;
}
if (inl) {
- int num = EVP_CIPHER_CTX_num(ctx);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
DES_cfb64_encrypt(in, out, (long)inl,
EVP_CIPHER_CTX_get_cipher_data(ctx),
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), &num,
- EVP_CIPHER_CTX_encrypting(ctx));
+ (DES_cblock *)ctx->iv, &num,
+ EVP_CIPHER_CTX_is_encrypting(ctx));
EVP_CIPHER_CTX_set_num(ctx, num);
}
return 1;
@@ -154,8 +158,8 @@ static int des_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
for (n = 0; n < chunk * 8; ++n) {
c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0;
DES_cfb_encrypt(c, d, 1, 1, EVP_CIPHER_CTX_get_cipher_data(ctx),
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx),
- EVP_CIPHER_CTX_encrypting(ctx));
+ (DES_cblock *)ctx->iv,
+ EVP_CIPHER_CTX_is_encrypting(ctx));
out[n / 8] =
(out[n / 8] & ~(0x80 >> (unsigned int)(n % 8))) |
((d[0] & 0x80) >> (unsigned int)(n % 8));
@@ -176,8 +180,8 @@ static int des_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
while (inl >= EVP_MAXCHUNK) {
DES_cfb_encrypt(in, out, 8, (long)EVP_MAXCHUNK,
EVP_CIPHER_CTX_get_cipher_data(ctx),
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx),
- EVP_CIPHER_CTX_encrypting(ctx));
+ (DES_cblock *)ctx->iv,
+ EVP_CIPHER_CTX_is_encrypting(ctx));
inl -= EVP_MAXCHUNK;
in += EVP_MAXCHUNK;
out += EVP_MAXCHUNK;
@@ -185,8 +189,8 @@ static int des_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (inl)
DES_cfb_encrypt(in, out, 8, (long)inl,
EVP_CIPHER_CTX_get_cipher_data(ctx),
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx),
- EVP_CIPHER_CTX_encrypting(ctx));
+ (DES_cblock *)ctx->iv,
+ EVP_CIPHER_CTX_is_encrypting(ctx));
return 1;
}
@@ -211,7 +215,7 @@ static int des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
dat->stream.cbc = NULL;
# if defined(SPARC_DES_CAPABLE)
if (SPARC_DES_CAPABLE) {
- int mode = EVP_CIPHER_CTX_mode(ctx);
+ int mode = EVP_CIPHER_CTX_get_mode(ctx);
if (mode == EVP_CIPH_CBC_MODE) {
des_t4_key_expand(key, &dat->ks.ks);
diff --git a/crypto/evp/e_des3.c b/crypto/evp/e_des3.c
index 2a5597fee527..1e1591834402 100644
--- a/crypto/evp/e_des3.c
+++ b/crypto/evp/e_des3.c
@@ -1,25 +1,31 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#ifndef OPENSSL_NO_DES
-# include <openssl/evp.h>
# include <openssl/objects.h>
# include "crypto/evp.h"
+# include "crypto/sha.h"
# include <openssl/des.h>
# include <openssl/rand.h>
# include "evp_local.h"
typedef struct {
union {
- double align;
+ OSSL_UNION_ALIGN;
DES_key_schedule ks[3];
} ks;
union {
@@ -34,9 +40,7 @@ typedef struct {
# if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
/* ---------^^^ this is not a typo, just a way to detect that
* assembler support was in general requested... */
-# include "sparc_arch.h"
-
-extern unsigned int OPENSSL_sparcv9cap_P[];
+# include "crypto/sparc_arch.h"
# define SPARC_DES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_DES)
@@ -69,7 +73,7 @@ static int des_ede_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
DES_ecb3_encrypt((const_DES_cblock *)(in + i),
(DES_cblock *)(out + i),
&data(ctx)->ks1, &data(ctx)->ks2,
- &data(ctx)->ks3, EVP_CIPHER_CTX_encrypting(ctx));
+ &data(ctx)->ks3, EVP_CIPHER_CTX_is_encrypting(ctx));
return 1;
}
@@ -77,11 +81,11 @@ static int des_ede_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
while (inl >= EVP_MAXCHUNK) {
- int num = EVP_CIPHER_CTX_num(ctx);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
DES_ede3_ofb64_encrypt(in, out, (long)EVP_MAXCHUNK,
&data(ctx)->ks1, &data(ctx)->ks2,
&data(ctx)->ks3,
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx),
+ (DES_cblock *)ctx->iv,
&num);
EVP_CIPHER_CTX_set_num(ctx, num);
inl -= EVP_MAXCHUNK;
@@ -89,11 +93,11 @@ static int des_ede_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
out += EVP_MAXCHUNK;
}
if (inl) {
- int num = EVP_CIPHER_CTX_num(ctx);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
DES_ede3_ofb64_encrypt(in, out, (long)inl,
&data(ctx)->ks1, &data(ctx)->ks2,
&data(ctx)->ks3,
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx),
+ (DES_cblock *)ctx->iv,
&num);
EVP_CIPHER_CTX_set_num(ctx, num);
}
@@ -107,15 +111,15 @@ static int des_ede_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (dat->stream.cbc != NULL) {
(*dat->stream.cbc) (in, out, inl, dat->ks.ks,
- EVP_CIPHER_CTX_iv_noconst(ctx));
+ ctx->iv);
return 1;
}
while (inl >= EVP_MAXCHUNK) {
DES_ede3_cbc_encrypt(in, out, (long)EVP_MAXCHUNK,
&dat->ks1, &dat->ks2, &dat->ks3,
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx),
- EVP_CIPHER_CTX_encrypting(ctx));
+ (DES_cblock *)ctx->iv,
+ EVP_CIPHER_CTX_is_encrypting(ctx));
inl -= EVP_MAXCHUNK;
in += EVP_MAXCHUNK;
out += EVP_MAXCHUNK;
@@ -123,8 +127,8 @@ static int des_ede_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (inl)
DES_ede3_cbc_encrypt(in, out, (long)inl,
&dat->ks1, &dat->ks2, &dat->ks3,
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx),
- EVP_CIPHER_CTX_encrypting(ctx));
+ (DES_cblock *)ctx->iv,
+ EVP_CIPHER_CTX_is_encrypting(ctx));
return 1;
}
@@ -132,24 +136,22 @@ static int des_ede_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
while (inl >= EVP_MAXCHUNK) {
- int num = EVP_CIPHER_CTX_num(ctx);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
DES_ede3_cfb64_encrypt(in, out, (long)EVP_MAXCHUNK,
&data(ctx)->ks1, &data(ctx)->ks2,
- &data(ctx)->ks3,
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx),
- &num, EVP_CIPHER_CTX_encrypting(ctx));
+ &data(ctx)->ks3, (DES_cblock *)ctx->iv,
+ &num, EVP_CIPHER_CTX_is_encrypting(ctx));
EVP_CIPHER_CTX_set_num(ctx, num);
inl -= EVP_MAXCHUNK;
in += EVP_MAXCHUNK;
out += EVP_MAXCHUNK;
}
if (inl) {
- int num = EVP_CIPHER_CTX_num(ctx);
+ int num = EVP_CIPHER_CTX_get_num(ctx);
DES_ede3_cfb64_encrypt(in, out, (long)inl,
&data(ctx)->ks1, &data(ctx)->ks2,
- &data(ctx)->ks3,
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx),
- &num, EVP_CIPHER_CTX_encrypting(ctx));
+ &data(ctx)->ks3, (DES_cblock *)ctx->iv,
+ &num, EVP_CIPHER_CTX_is_encrypting(ctx));
EVP_CIPHER_CTX_set_num(ctx, num);
}
return 1;
@@ -171,9 +173,8 @@ static int des_ede3_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0;
DES_ede3_cfb_encrypt(c, d, 1, 1,
&data(ctx)->ks1, &data(ctx)->ks2,
- &data(ctx)->ks3,
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx),
- EVP_CIPHER_CTX_encrypting(ctx));
+ &data(ctx)->ks3, (DES_cblock *)ctx->iv,
+ EVP_CIPHER_CTX_is_encrypting(ctx));
out[n / 8] = (out[n / 8] & ~(0x80 >> (unsigned int)(n % 8)))
| ((d[0] & 0x80) >> (unsigned int)(n % 8));
}
@@ -187,9 +188,8 @@ static int des_ede3_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
while (inl >= EVP_MAXCHUNK) {
DES_ede3_cfb_encrypt(in, out, 8, (long)EVP_MAXCHUNK,
&data(ctx)->ks1, &data(ctx)->ks2,
- &data(ctx)->ks3,
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx),
- EVP_CIPHER_CTX_encrypting(ctx));
+ &data(ctx)->ks3, (DES_cblock *)ctx->iv,
+ EVP_CIPHER_CTX_is_encrypting(ctx));
inl -= EVP_MAXCHUNK;
in += EVP_MAXCHUNK;
out += EVP_MAXCHUNK;
@@ -197,9 +197,8 @@ static int des_ede3_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (inl)
DES_ede3_cfb_encrypt(in, out, 8, (long)inl,
&data(ctx)->ks1, &data(ctx)->ks2,
- &data(ctx)->ks3,
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx),
- EVP_CIPHER_CTX_encrypting(ctx));
+ &data(ctx)->ks3, (DES_cblock *)ctx->iv,
+ EVP_CIPHER_CTX_is_encrypting(ctx));
return 1;
}
@@ -231,7 +230,7 @@ static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
dat->stream.cbc = NULL;
# if defined(SPARC_DES_CAPABLE)
if (SPARC_DES_CAPABLE) {
- int mode = EVP_CIPHER_CTX_mode(ctx);
+ int mode = EVP_CIPHER_CTX_get_mode(ctx);
if (mode == EVP_CIPH_CBC_MODE) {
des_t4_key_expand(&deskey[0], &dat->ks1);
@@ -258,7 +257,7 @@ static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
dat->stream.cbc = NULL;
# if defined(SPARC_DES_CAPABLE)
if (SPARC_DES_CAPABLE) {
- int mode = EVP_CIPHER_CTX_mode(ctx);
+ int mode = EVP_CIPHER_CTX_get_mode(ctx);
if (mode == EVP_CIPH_CBC_MODE) {
des_t4_key_expand(&deskey[0], &dat->ks1);
@@ -280,15 +279,17 @@ static int des3_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
{
DES_cblock *deskey = ptr;
+ int kl;
switch (type) {
case EVP_CTRL_RAND_KEY:
- if (RAND_priv_bytes(ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0)
+ kl = EVP_CIPHER_CTX_get_key_length(ctx);
+ if (kl < 0 || RAND_priv_bytes(ptr, kl) <= 0)
return 0;
DES_set_odd_parity(deskey);
- if (EVP_CIPHER_CTX_key_length(ctx) >= 16)
+ if (kl >= 16)
DES_set_odd_parity(deskey + 1);
- if (EVP_CIPHER_CTX_key_length(ctx) >= 24)
+ if (kl >= 24)
DES_set_odd_parity(deskey + 2);
return 1;
@@ -322,7 +323,7 @@ static int des_ede3_unwrap(EVP_CIPHER_CTX *ctx, unsigned char *out,
return -1;
if (out == NULL)
return inl - 16;
- memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), wrap_iv, 8);
+ memcpy(ctx->iv, wrap_iv, 8);
/* Decrypt first block which will end up as icv */
des_ede_cbc_cipher(ctx, icv, in, 8);
/* Decrypt central blocks */
@@ -340,19 +341,17 @@ static int des_ede3_unwrap(EVP_CIPHER_CTX *ctx, unsigned char *out,
/* Reverse order of everything */
BUF_reverse(icv, NULL, 8);
BUF_reverse(out, NULL, inl - 16);
- BUF_reverse(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 8);
+ BUF_reverse(ctx->iv, iv, 8);
/* Decrypt again using new IV */
des_ede_cbc_cipher(ctx, out, out, inl - 16);
des_ede_cbc_cipher(ctx, icv, icv, 8);
- /* Work out SHA1 hash of first portion */
- SHA1(out, inl - 16, sha1tmp);
-
- if (!CRYPTO_memcmp(sha1tmp, icv, 8))
+ if (ossl_sha1(out, inl - 16, sha1tmp) /* Work out hash of first portion */
+ && CRYPTO_memcmp(sha1tmp, icv, 8) == 0)
rv = inl - 16;
OPENSSL_cleanse(icv, 8);
OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH);
OPENSSL_cleanse(iv, 8);
- OPENSSL_cleanse(EVP_CIPHER_CTX_iv_noconst(ctx), 8);
+ OPENSSL_cleanse(ctx->iv, 8);
if (rv == -1)
OPENSSL_cleanse(out, inl - 16);
@@ -368,17 +367,18 @@ static int des_ede3_wrap(EVP_CIPHER_CTX *ctx, unsigned char *out,
/* Copy input to output buffer + 8 so we have space for IV */
memmove(out + 8, in, inl);
/* Work out ICV */
- SHA1(in, inl, sha1tmp);
+ if (!ossl_sha1(in, inl, sha1tmp))
+ return -1;
memcpy(out + inl + 8, sha1tmp, 8);
OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH);
/* Generate random IV */
- if (RAND_bytes(EVP_CIPHER_CTX_iv_noconst(ctx), 8) <= 0)
+ if (RAND_bytes(ctx->iv, 8) <= 0)
return -1;
- memcpy(out, EVP_CIPHER_CTX_iv_noconst(ctx), 8);
+ memcpy(out, ctx->iv, 8);
/* Encrypt everything after IV in place */
des_ede_cbc_cipher(ctx, out + 8, out + 8, inl + 8);
BUF_reverse(out, NULL, inl + 16);
- memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), wrap_iv, 8);
+ memcpy(ctx->iv, wrap_iv, 8);
des_ede_cbc_cipher(ctx, out, out, inl + 16);
return inl + 16;
}
@@ -394,12 +394,12 @@ static int des_ede3_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (inl >= EVP_MAXCHUNK || inl % 8)
return -1;
- if (is_partially_overlapping(out, in, inl)) {
- EVPerr(EVP_F_DES_EDE3_WRAP_CIPHER, EVP_R_PARTIALLY_OVERLAPPING);
+ if (ossl_is_partially_overlapping(out, in, inl)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING);
return 0;
}
- if (EVP_CIPHER_CTX_encrypting(ctx))
+ if (EVP_CIPHER_CTX_is_encrypting(ctx))
return des_ede3_wrap(ctx, out, in, inl);
else
return des_ede3_unwrap(ctx, out, in, inl);
@@ -410,6 +410,7 @@ static const EVP_CIPHER des3_wrap = {
8, 24, 0,
EVP_CIPH_WRAP_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER
| EVP_CIPH_FLAG_DEFAULT_ASN1,
+ EVP_ORIG_GLOBAL,
des_ede3_init_key, des_ede3_wrap_cipher,
NULL,
sizeof(DES_EDE_KEY),
diff --git a/crypto/evp/e_idea.c b/crypto/evp/e_idea.c
index 1068378ddc75..4a4df4b92510 100644
--- a/crypto/evp/e_idea.c
+++ b/crypto/evp/e_idea.c
@@ -1,12 +1,19 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * IDEA low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
@@ -15,6 +22,7 @@
# include <openssl/objects.h>
# include "crypto/evp.h"
# include <openssl/idea.h>
+# include "evp_local.h"
/* Can't use IMPLEMENT_BLOCK_CIPHER because IDEA_ecb_encrypt is different */
@@ -50,9 +58,9 @@ static int idea_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
if (!enc) {
- if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE)
+ if (EVP_CIPHER_CTX_get_mode(ctx) == EVP_CIPH_OFB_MODE)
enc = 1;
- else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE)
+ else if (EVP_CIPHER_CTX_get_mode(ctx) == EVP_CIPH_CFB_MODE)
enc = 1;
}
if (enc)
diff --git a/crypto/evp/e_null.c b/crypto/evp/e_null.c
index 0725454a3a4a..af900c52989f 100644
--- a/crypto/evp/e_null.c
+++ b/crypto/evp/e_null.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -20,6 +20,7 @@ static int null_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static const EVP_CIPHER n_cipher = {
NID_undef,
1, 0, 0, 0,
+ EVP_ORIG_GLOBAL,
null_init_key,
null_cipher,
NULL,
diff --git a/crypto/evp/e_old.c b/crypto/evp/e_old.c
index 927908f87176..e9c9f22119bf 100644
--- a/crypto/evp/e_old.c
+++ b/crypto/evp/e_old.c
@@ -1,18 +1,15 @@
/*
- * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/opensslconf.h>
-#if OPENSSL_API_COMPAT >= 0x00908000L
-NON_EMPTY_TRANSLATION_UNIT
-#else
-# include <openssl/evp.h>
+#include <openssl/evp.h>
/*
* Define some deprecated functions, so older programs don't crash and burn
@@ -21,93 +18,91 @@ NON_EMPTY_TRANSLATION_UNIT
* location, not by name.
*/
-# ifndef OPENSSL_NO_BF
-# undef EVP_bf_cfb
+#ifndef OPENSSL_NO_BF
+# undef EVP_bf_cfb
const EVP_CIPHER *EVP_bf_cfb(void);
const EVP_CIPHER *EVP_bf_cfb(void)
{
return EVP_bf_cfb64();
}
-# endif
+#endif
-# ifndef OPENSSL_NO_DES
-# undef EVP_des_cfb
+#ifndef OPENSSL_NO_DES
+# undef EVP_des_cfb
const EVP_CIPHER *EVP_des_cfb(void);
const EVP_CIPHER *EVP_des_cfb(void)
{
return EVP_des_cfb64();
}
-# undef EVP_des_ede3_cfb
+# undef EVP_des_ede3_cfb
const EVP_CIPHER *EVP_des_ede3_cfb(void);
const EVP_CIPHER *EVP_des_ede3_cfb(void)
{
return EVP_des_ede3_cfb64();
}
-# undef EVP_des_ede_cfb
+# undef EVP_des_ede_cfb
const EVP_CIPHER *EVP_des_ede_cfb(void);
const EVP_CIPHER *EVP_des_ede_cfb(void)
{
return EVP_des_ede_cfb64();
}
-# endif
+#endif
-# ifndef OPENSSL_NO_IDEA
-# undef EVP_idea_cfb
+#ifndef OPENSSL_NO_IDEA
+# undef EVP_idea_cfb
const EVP_CIPHER *EVP_idea_cfb(void);
const EVP_CIPHER *EVP_idea_cfb(void)
{
return EVP_idea_cfb64();
}
-# endif
+#endif
-# ifndef OPENSSL_NO_RC2
-# undef EVP_rc2_cfb
+#ifndef OPENSSL_NO_RC2
+# undef EVP_rc2_cfb
const EVP_CIPHER *EVP_rc2_cfb(void);
const EVP_CIPHER *EVP_rc2_cfb(void)
{
return EVP_rc2_cfb64();
}
-# endif
+#endif
-# ifndef OPENSSL_NO_CAST
-# undef EVP_cast5_cfb
+#ifndef OPENSSL_NO_CAST
+# undef EVP_cast5_cfb
const EVP_CIPHER *EVP_cast5_cfb(void);
const EVP_CIPHER *EVP_cast5_cfb(void)
{
return EVP_cast5_cfb64();
}
-# endif
+#endif
-# ifndef OPENSSL_NO_RC5
-# undef EVP_rc5_32_12_16_cfb
+#ifndef OPENSSL_NO_RC5
+# undef EVP_rc5_32_12_16_cfb
const EVP_CIPHER *EVP_rc5_32_12_16_cfb(void);
const EVP_CIPHER *EVP_rc5_32_12_16_cfb(void)
{
return EVP_rc5_32_12_16_cfb64();
}
-# endif
+#endif
-# undef EVP_aes_128_cfb
+#undef EVP_aes_128_cfb
const EVP_CIPHER *EVP_aes_128_cfb(void);
const EVP_CIPHER *EVP_aes_128_cfb(void)
{
return EVP_aes_128_cfb128();
}
-# undef EVP_aes_192_cfb
+#undef EVP_aes_192_cfb
const EVP_CIPHER *EVP_aes_192_cfb(void);
const EVP_CIPHER *EVP_aes_192_cfb(void)
{
return EVP_aes_192_cfb128();
}
-# undef EVP_aes_256_cfb
+#undef EVP_aes_256_cfb
const EVP_CIPHER *EVP_aes_256_cfb(void);
const EVP_CIPHER *EVP_aes_256_cfb(void)
{
return EVP_aes_256_cfb128();
}
-
-#endif
diff --git a/crypto/evp/e_rc2.c b/crypto/evp/e_rc2.c
index 4d8a0ee4b015..ffeb17fb1e5a 100644
--- a/crypto/evp/e_rc2.c
+++ b/crypto/evp/e_rc2.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RC2 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
@@ -16,6 +22,7 @@
# include <openssl/objects.h>
# include "crypto/evp.h"
# include <openssl/rc2.h>
+# include "evp_local.h"
static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
@@ -46,6 +53,7 @@ static const EVP_CIPHER r2_64_cbc_cipher = {
NID_rc2_64_cbc,
8, 8 /* 64 bit */ , 8,
EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
+ EVP_ORIG_GLOBAL,
rc2_init_key,
rc2_cbc_cipher,
NULL,
@@ -60,6 +68,7 @@ static const EVP_CIPHER r2_40_cbc_cipher = {
NID_rc2_40_cbc,
8, 5 /* 40 bit */ , 8,
EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
+ EVP_ORIG_GLOBAL,
rc2_init_key,
rc2_cbc_cipher,
NULL,
@@ -83,7 +92,7 @@ const EVP_CIPHER *EVP_rc2_40_cbc(void)
static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
- RC2_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx),
+ RC2_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_get_key_length(ctx),
key, data(ctx)->key_bits);
return 1;
}
@@ -113,7 +122,7 @@ static int rc2_magic_to_meth(int i)
else if (i == RC2_40_MAGIC)
return 40;
else {
- EVPerr(EVP_F_RC2_MAGIC_TO_METH, EVP_R_UNSUPPORTED_KEY_SIZE);
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_SIZE);
return 0;
}
}
@@ -127,7 +136,7 @@ static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
unsigned char iv[EVP_MAX_IV_LENGTH];
if (type != NULL) {
- l = EVP_CIPHER_CTX_iv_length(c);
+ l = EVP_CIPHER_CTX_get_iv_length(c);
OPENSSL_assert(l <= sizeof(iv));
i = ASN1_TYPE_get_int_octetstring(type, &num, iv, l);
if (i != (int)l)
@@ -152,10 +161,8 @@ static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
if (type != NULL) {
num = rc2_meth_to_magic(c);
- j = EVP_CIPHER_CTX_iv_length(c);
- i = ASN1_TYPE_set_int_octetstring(type, num,
- (unsigned char *)EVP_CIPHER_CTX_original_iv(c),
- j);
+ j = EVP_CIPHER_CTX_get_iv_length(c);
+ i = ASN1_TYPE_set_int_octetstring(type, num, c->oiv, j);
}
return i;
}
@@ -164,7 +171,7 @@ static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
{
switch (type) {
case EVP_CTRL_INIT:
- data(c)->key_bits = EVP_CIPHER_CTX_key_length(c) * 8;
+ data(c)->key_bits = EVP_CIPHER_CTX_get_key_length(c) * 8;
return 1;
case EVP_CTRL_GET_RC2_KEY_BITS:
diff --git a/crypto/evp/e_rc4.c b/crypto/evp/e_rc4.c
index c24bc8fe5982..e22e81d46752 100644
--- a/crypto/evp/e_rc4.c
+++ b/crypto/evp/e_rc4.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RC4 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
@@ -32,6 +38,7 @@ static const EVP_CIPHER r4_cipher = {
NID_rc4,
1, EVP_RC4_KEY_SIZE, 0,
EVP_CIPH_VARIABLE_LENGTH,
+ EVP_ORIG_GLOBAL,
rc4_init_key,
rc4_cipher,
NULL,
@@ -46,6 +53,7 @@ static const EVP_CIPHER r4_40_cipher = {
NID_rc4_40,
1, 5 /* 40 bit */ , 0,
EVP_CIPH_VARIABLE_LENGTH,
+ EVP_ORIG_GLOBAL,
rc4_init_key,
rc4_cipher,
NULL,
@@ -69,7 +77,11 @@ const EVP_CIPHER *EVP_rc4_40(void)
static int rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
- RC4_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), key);
+ int keylen;
+
+ if ((keylen = EVP_CIPHER_CTX_get_key_length(ctx)) <= 0)
+ return 0;
+ RC4_set_key(&data(ctx)->ks, keylen, key);
return 1;
}
diff --git a/crypto/evp/e_rc4_hmac_md5.c b/crypto/evp/e_rc4_hmac_md5.c
index 201ce443435c..183ecefcec65 100644
--- a/crypto/evp/e_rc4_hmac_md5.c
+++ b/crypto/evp/e_rc4_hmac_md5.c
@@ -1,12 +1,19 @@
/*
- * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * MD5 and RC4 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include "internal/cryptlib.h"
#include <openssl/opensslconf.h>
#include <stdio.h>
@@ -39,8 +46,12 @@ static int rc4_hmac_md5_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char *iv, int enc)
{
EVP_RC4_HMAC_MD5 *key = data(ctx);
+ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
+
+ if (keylen <= 0)
+ return 0;
- RC4_set_key(&key->ks, EVP_CIPHER_CTX_key_length(ctx), inkey);
+ RC4_set_key(&key->ks, keylen, inkey);
MD5_Init(&key->head); /* handy when benchmarking */
key->tail = key->head;
@@ -51,7 +62,7 @@ static int rc4_hmac_md5_init_key(EVP_CIPHER_CTX *ctx,
return 1;
}
-# if defined(RC4_ASM) && defined(MD5_ASM) && ( \
+# if defined(RC4_ASM) && defined(MD5_ASM) && ( \
defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64) )
# define STITCHED_CALL
@@ -71,14 +82,13 @@ static int rc4_hmac_md5_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
* rc4_md5-x86_64.pl */
md5_off = MD5_CBLOCK - key->md.num, blocks;
unsigned int l;
- extern unsigned int OPENSSL_ia32cap_P[];
# endif
size_t plen = key->payload_length;
if (plen != NO_PAYLOAD_LENGTH && len != (plen + MD5_DIGEST_LENGTH))
return 0;
- if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
if (plen == NO_PAYLOAD_LENGTH)
plen = len;
# if defined(STITCHED_CALL)
@@ -218,7 +228,7 @@ static int rc4_hmac_md5_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
len = p[arg - 2] << 8 | p[arg - 1];
- if (!EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (!EVP_CIPHER_CTX_is_encrypting(ctx)) {
if (len < MD5_DIGEST_LENGTH)
return -1;
len -= MD5_DIGEST_LENGTH;
@@ -245,6 +255,7 @@ static EVP_CIPHER r4_hmac_md5_cipher = {
1, EVP_RC4_KEY_SIZE, 0,
EVP_CIPH_STREAM_CIPHER | EVP_CIPH_VARIABLE_LENGTH |
EVP_CIPH_FLAG_AEAD_CIPHER,
+ EVP_ORIG_GLOBAL,
rc4_hmac_md5_init_key,
rc4_hmac_md5_cipher,
NULL,
diff --git a/crypto/evp/e_rc5.c b/crypto/evp/e_rc5.c
index c86e87b65ab4..3496a701931c 100644
--- a/crypto/evp/e_rc5.c
+++ b/crypto/evp/e_rc5.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RC5 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
@@ -54,7 +60,7 @@ static int rc5_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
return 1;
default:
- EVPerr(EVP_F_RC5_CTRL, EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS);
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS);
return 0;
}
@@ -66,13 +72,13 @@ static int rc5_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
static int r_32_12_16_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
- if (EVP_CIPHER_CTX_key_length(ctx) > 255) {
- EVPerr(EVP_F_R_32_12_16_INIT_KEY, EVP_R_BAD_KEY_LENGTH);
+ const int key_len = EVP_CIPHER_CTX_get_key_length(ctx);
+
+ if (key_len > 255 || key_len < 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_BAD_KEY_LENGTH);
return 0;
}
- RC5_32_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx),
- key, data(ctx)->rounds);
- return 1;
+ return RC5_32_set_key(&data(ctx)->ks, key_len, key, data(ctx)->rounds);
}
#endif
diff --git a/crypto/evp/e_seed.c b/crypto/evp/e_seed.c
index aeb2363beade..98c7385f61da 100644
--- a/crypto/evp/e_seed.c
+++ b/crypto/evp/e_seed.c
@@ -1,22 +1,26 @@
/*
- * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * SEED low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/opensslconf.h>
-#ifdef OPENSSL_NO_SEED
-NON_EMPTY_TRANSLATION_UNIT
-#else
-# include <openssl/evp.h>
-# include <openssl/err.h>
-# include <string.h>
-# include <assert.h>
-# include <openssl/seed.h>
-# include "crypto/evp.h"
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <string.h>
+#include <assert.h>
+#include <openssl/seed.h>
+#include "crypto/evp.h"
+#include "evp_local.h"
static int seed_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
@@ -35,5 +39,3 @@ static int seed_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
SEED_set_key(key, &EVP_C_DATA(EVP_SEED_KEY,ctx)->ks);
return 1;
}
-
-#endif
diff --git a/crypto/evp/e_sm4.c b/crypto/evp/e_sm4.c
index fce32794fc51..abd603015c71 100644
--- a/crypto/evp/e_sm4.c
+++ b/crypto/evp/e_sm4.c
@@ -1,20 +1,23 @@
/*
- * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2017 Ribose Inc. All Rights Reserved.
* Ported from Ribose contributions from Botan.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#include "internal/deprecated.h"
+
#include "internal/cryptlib.h"
#ifndef OPENSSL_NO_SM4
# include <openssl/evp.h>
# include <openssl/modes.h>
# include "crypto/sm4.h"
# include "crypto/evp.h"
+# include "evp_local.h"
typedef struct {
SM4_KEY ks;
@@ -23,7 +26,7 @@ typedef struct {
static int sm4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
- SM4_set_key(key, EVP_CIPHER_CTX_get_cipher_data(ctx));
+ ossl_sm4_set_key(key, EVP_CIPHER_CTX_get_cipher_data(ctx));
return 1;
}
@@ -33,10 +36,10 @@ static void sm4_cbc_encrypt(const unsigned char *in, unsigned char *out,
{
if (enc)
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,
- (block128_f)SM4_encrypt);
+ (block128_f)ossl_sm4_encrypt);
else
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,
- (block128_f)SM4_decrypt);
+ (block128_f)ossl_sm4_decrypt);
}
static void sm4_cfb128_encrypt(const unsigned char *in, unsigned char *out,
@@ -44,16 +47,16 @@ static void sm4_cfb128_encrypt(const unsigned char *in, unsigned char *out,
unsigned char *ivec, int *num, const int enc)
{
CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc,
- (block128_f)SM4_encrypt);
+ (block128_f)ossl_sm4_encrypt);
}
static void sm4_ecb_encrypt(const unsigned char *in, unsigned char *out,
const SM4_KEY *key, const int enc)
{
if (enc)
- SM4_encrypt(in, out, key);
+ ossl_sm4_encrypt(in, out, key);
else
- SM4_decrypt(in, out, key);
+ ossl_sm4_decrypt(in, out, key);
}
static void sm4_ofb128_encrypt(const unsigned char *in, unsigned char *out,
@@ -61,7 +64,7 @@ static void sm4_ofb128_encrypt(const unsigned char *in, unsigned char *out,
unsigned char *ivec, int *num)
{
CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num,
- (block128_f)SM4_encrypt);
+ (block128_f)ossl_sm4_encrypt);
}
IMPLEMENT_BLOCK_CIPHER(sm4, ks, sm4, EVP_SM4_KEY, NID_sm4,
@@ -71,13 +74,17 @@ IMPLEMENT_BLOCK_CIPHER(sm4, ks, sm4, EVP_SM4_KEY, NID_sm4,
static int sm4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
- unsigned int num = EVP_CIPHER_CTX_num(ctx);
+ int n = EVP_CIPHER_CTX_get_num(ctx);
+ unsigned int num;
EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY, ctx);
- CRYPTO_ctr128_encrypt(in, out, len, &dat->ks,
- EVP_CIPHER_CTX_iv_noconst(ctx),
+ if (n < 0)
+ return 0;
+ num = (unsigned int)n;
+
+ CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv,
EVP_CIPHER_CTX_buf_noconst(ctx), &num,
- (block128_f)SM4_encrypt);
+ (block128_f)ossl_sm4_encrypt);
EVP_CIPHER_CTX_set_num(ctx, num);
return 1;
}
@@ -85,6 +92,7 @@ static int sm4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static const EVP_CIPHER sm4_ctr_mode = {
NID_sm4_ctr, 1, 16, 16,
EVP_CIPH_CTR_MODE,
+ EVP_ORIG_GLOBAL,
sm4_init_key,
sm4_ctr_cipher,
NULL,
diff --git a/crypto/evp/e_xcbc_d.c b/crypto/evp/e_xcbc_d.c
index b73077542264..f930941887a3 100644
--- a/crypto/evp/e_xcbc_d.c
+++ b/crypto/evp/e_xcbc_d.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
@@ -16,6 +22,7 @@
# include <openssl/objects.h>
# include "crypto/evp.h"
# include <openssl/des.h>
+# include "evp_local.h"
static int desx_cbc_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
@@ -34,6 +41,7 @@ static const EVP_CIPHER d_xcbc_cipher = {
NID_desx_cbc,
8, 24, 8,
EVP_CIPH_CBC_MODE,
+ EVP_ORIG_GLOBAL,
desx_cbc_init_key,
desx_cbc_cipher,
NULL,
@@ -66,18 +74,18 @@ static int desx_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
{
while (inl >= EVP_MAXCHUNK) {
DES_xcbc_encrypt(in, out, (long)EVP_MAXCHUNK, &data(ctx)->ks,
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx),
+ (DES_cblock *)ctx->iv,
&data(ctx)->inw, &data(ctx)->outw,
- EVP_CIPHER_CTX_encrypting(ctx));
+ EVP_CIPHER_CTX_is_encrypting(ctx));
inl -= EVP_MAXCHUNK;
in += EVP_MAXCHUNK;
out += EVP_MAXCHUNK;
}
if (inl)
DES_xcbc_encrypt(in, out, (long)inl, &data(ctx)->ks,
- (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx),
+ (DES_cblock *)ctx->iv,
&data(ctx)->inw, &data(ctx)->outw,
- EVP_CIPHER_CTX_encrypting(ctx));
+ EVP_CIPHER_CTX_is_encrypting(ctx));
return 1;
}
#endif
diff --git a/crypto/evp/ec_ctrl.c b/crypto/evp/ec_ctrl.c
new file mode 100644
index 000000000000..404358ab97f1
--- /dev/null
+++ b/crypto/evp/ec_ctrl.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/deprecated.h"
+
+#include <openssl/core_names.h>
+#include <openssl/err.h>
+#include <openssl/ec.h>
+#include "crypto/evp.h"
+#include "crypto/ec.h"
+
+/*
+ * This file is meant to contain functions to provide EVP_PKEY support for EC
+ * keys.
+ */
+
+static ossl_inline
+int evp_pkey_ctx_getset_ecdh_param_checks(const EVP_PKEY_CTX *ctx)
+{
+ if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+
+ /* If key type not EC return error */
+ if (evp_pkey_ctx_is_legacy(ctx)
+ && ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_EC)
+ return -1;
+
+ return 1;
+}
+
+int EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode)
+{
+ int ret;
+ OSSL_PARAM params[2], *p = params;
+
+ ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
+ if (ret != 1)
+ return ret;
+
+ /*
+ * Valid input values are:
+ * * 0 for disable
+ * * 1 for enable
+ * * -1 for reset to default for associated priv key
+ */
+ if (cofactor_mode < -1 || cofactor_mode > 1) {
+ /* Uses the same return value of pkey_ec_ctrl() */
+ return -2;
+ }
+
+ *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
+ &cofactor_mode);
+ *p++ = OSSL_PARAM_construct_end();
+
+ ret = evp_pkey_ctx_set_params_strict(ctx, params);
+ if (ret == -2)
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return ret;
+}
+
+int EVP_PKEY_CTX_get_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx)
+{
+ int ret, mode;
+ OSSL_PARAM params[2], *p = params;
+
+ ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
+ if (ret != 1)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
+ &mode);
+ *p++ = OSSL_PARAM_construct_end();
+
+ ret = evp_pkey_ctx_get_params_strict(ctx, params);
+
+ switch (ret) {
+ case -2:
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ break;
+ case 1:
+ ret = mode;
+ if (mode < 0 || mode > 1) {
+ /*
+ * The provider should return either 0 or 1, any other value is a
+ * provider error.
+ */
+ ret = -1;
+ }
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_set_ecdh_kdf_type(EVP_PKEY_CTX *ctx, int kdf)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_get_ecdh_kdf_type(EVP_PKEY_CTX *ctx)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_set_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md));
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_get_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd));
+}
+
+int EVP_PKEY_CTX_set_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int outlen)
+{
+ int ret;
+ size_t len = outlen;
+ OSSL_PARAM params[2], *p = params;
+
+ ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
+ if (ret != 1)
+ return ret;
+
+ if (outlen <= 0) {
+ /*
+ * This would ideally be -1 or 0, but we have to retain compatibility
+ * with legacy behaviour of EVP_PKEY_CTX_ctrl() which returned -2 if
+ * in <= 0
+ */
+ return -2;
+ }
+
+ *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
+ &len);
+ *p++ = OSSL_PARAM_construct_end();
+
+ ret = evp_pkey_ctx_set_params_strict(ctx, params);
+ if (ret == -2)
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return ret;
+}
+
+int EVP_PKEY_CTX_get_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int *plen)
+{
+ size_t len = UINT_MAX;
+ int ret;
+ OSSL_PARAM params[2], *p = params;
+
+ ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
+ if (ret != 1)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
+ &len);
+ *p++ = OSSL_PARAM_construct_end();
+
+ ret = evp_pkey_ctx_get_params_strict(ctx, params);
+
+ switch (ret) {
+ case -2:
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ break;
+ case 1:
+ if (len <= INT_MAX)
+ *plen = (int)len;
+ else
+ ret = -1;
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+
+int EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len)
+{
+ int ret;
+ OSSL_PARAM params[2], *p = params;
+
+ ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
+ if (ret != 1)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM,
+ /*
+ * Cast away the const. This is read
+ * only so should be safe
+ */
+ (void *)ukm,
+ (size_t)len);
+ *p++ = OSSL_PARAM_construct_end();
+
+ ret = evp_pkey_ctx_set_params_strict(ctx, params);
+
+ switch (ret) {
+ case -2:
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ break;
+ case 1:
+ OPENSSL_free(ukm);
+ break;
+ }
+
+ return ret;
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm)
+{
+ size_t ukmlen;
+ int ret;
+ OSSL_PARAM params[2], *p = params;
+
+ ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
+ if (ret != 1)
+ return ret;
+
+ *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_EXCHANGE_PARAM_KDF_UKM,
+ (void **)pukm, 0);
+ *p++ = OSSL_PARAM_construct_end();
+
+ ret = evp_pkey_ctx_get_params_strict(ctx, params);
+
+ switch (ret) {
+ case -2:
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ break;
+ case 1:
+ ret = -1;
+ ukmlen = params[0].return_size;
+ if (ukmlen <= INT_MAX)
+ ret = (int)ukmlen;
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+#endif
+
+#ifndef FIPS_MODULE
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ * ASN1_OBJECT (which would be converted to text internally)?
+ */
+int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_TYPE_GEN,
+ EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID,
+ nid, NULL);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int param_enc)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_TYPE_GEN,
+ EVP_PKEY_CTRL_EC_PARAM_ENC, param_enc, NULL);
+}
+#endif
diff --git a/crypto/evp/ec_support.c b/crypto/evp/ec_support.c
new file mode 100644
index 000000000000..1ec10143d2de
--- /dev/null
+++ b/crypto/evp/ec_support.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/ec.h>
+#include "crypto/ec.h"
+#include "internal/nelem.h"
+
+typedef struct ec_name2nid_st {
+ const char *name;
+ int nid;
+} EC_NAME2NID;
+
+static const EC_NAME2NID curve_list[] = {
+ /* prime field curves */
+ /* secg curves */
+ {"secp112r1", NID_secp112r1 },
+ {"secp112r2", NID_secp112r2 },
+ {"secp128r1", NID_secp128r1 },
+ {"secp128r2", NID_secp128r2 },
+ {"secp160k1", NID_secp160k1 },
+ {"secp160r1", NID_secp160r1 },
+ {"secp160r2", NID_secp160r2 },
+ {"secp192k1", NID_secp192k1 },
+ {"secp224k1", NID_secp224k1 },
+ {"secp224r1", NID_secp224r1 },
+ {"secp256k1", NID_secp256k1 },
+ {"secp384r1", NID_secp384r1 },
+ {"secp521r1", NID_secp521r1 },
+ /* X9.62 curves */
+ {"prime192v1", NID_X9_62_prime192v1 },
+ {"prime192v2", NID_X9_62_prime192v2 },
+ {"prime192v3", NID_X9_62_prime192v3 },
+ {"prime239v1", NID_X9_62_prime239v1 },
+ {"prime239v2", NID_X9_62_prime239v2 },
+ {"prime239v3", NID_X9_62_prime239v3 },
+ {"prime256v1", NID_X9_62_prime256v1 },
+ /* characteristic two field curves */
+ /* NIST/SECG curves */
+ {"sect113r1", NID_sect113r1 },
+ {"sect113r2", NID_sect113r2 },
+ {"sect131r1", NID_sect131r1 },
+ {"sect131r2", NID_sect131r2 },
+ {"sect163k1", NID_sect163k1 },
+ {"sect163r1", NID_sect163r1 },
+ {"sect163r2", NID_sect163r2 },
+ {"sect193r1", NID_sect193r1 },
+ {"sect193r2", NID_sect193r2 },
+ {"sect233k1", NID_sect233k1 },
+ {"sect233r1", NID_sect233r1 },
+ {"sect239k1", NID_sect239k1 },
+ {"sect283k1", NID_sect283k1 },
+ {"sect283r1", NID_sect283r1 },
+ {"sect409k1", NID_sect409k1 },
+ {"sect409r1", NID_sect409r1 },
+ {"sect571k1", NID_sect571k1 },
+ {"sect571r1", NID_sect571r1 },
+ /* X9.62 curves */
+ {"c2pnb163v1", NID_X9_62_c2pnb163v1 },
+ {"c2pnb163v2", NID_X9_62_c2pnb163v2 },
+ {"c2pnb163v3", NID_X9_62_c2pnb163v3 },
+ {"c2pnb176v1", NID_X9_62_c2pnb176v1 },
+ {"c2tnb191v1", NID_X9_62_c2tnb191v1 },
+ {"c2tnb191v2", NID_X9_62_c2tnb191v2 },
+ {"c2tnb191v3", NID_X9_62_c2tnb191v3 },
+ {"c2pnb208w1", NID_X9_62_c2pnb208w1 },
+ {"c2tnb239v1", NID_X9_62_c2tnb239v1 },
+ {"c2tnb239v2", NID_X9_62_c2tnb239v2 },
+ {"c2tnb239v3", NID_X9_62_c2tnb239v3 },
+ {"c2pnb272w1", NID_X9_62_c2pnb272w1 },
+ {"c2pnb304w1", NID_X9_62_c2pnb304w1 },
+ {"c2tnb359v1", NID_X9_62_c2tnb359v1 },
+ {"c2pnb368w1", NID_X9_62_c2pnb368w1 },
+ {"c2tnb431r1", NID_X9_62_c2tnb431r1 },
+ /*
+ * the WAP/WTLS curves [unlike SECG, spec has its own OIDs for curves
+ * from X9.62]
+ */
+ {"wap-wsg-idm-ecid-wtls1", NID_wap_wsg_idm_ecid_wtls1 },
+ {"wap-wsg-idm-ecid-wtls3", NID_wap_wsg_idm_ecid_wtls3 },
+ {"wap-wsg-idm-ecid-wtls4", NID_wap_wsg_idm_ecid_wtls4 },
+ {"wap-wsg-idm-ecid-wtls5", NID_wap_wsg_idm_ecid_wtls5 },
+ {"wap-wsg-idm-ecid-wtls6", NID_wap_wsg_idm_ecid_wtls6 },
+ {"wap-wsg-idm-ecid-wtls7", NID_wap_wsg_idm_ecid_wtls7 },
+ {"wap-wsg-idm-ecid-wtls8", NID_wap_wsg_idm_ecid_wtls8 },
+ {"wap-wsg-idm-ecid-wtls9", NID_wap_wsg_idm_ecid_wtls9 },
+ {"wap-wsg-idm-ecid-wtls10", NID_wap_wsg_idm_ecid_wtls10 },
+ {"wap-wsg-idm-ecid-wtls11", NID_wap_wsg_idm_ecid_wtls11 },
+ {"wap-wsg-idm-ecid-wtls12", NID_wap_wsg_idm_ecid_wtls12 },
+ /* IPSec curves */
+ {"Oakley-EC2N-3", NID_ipsec3 },
+ {"Oakley-EC2N-4", NID_ipsec4 },
+ /* brainpool curves */
+ {"brainpoolP160r1", NID_brainpoolP160r1 },
+ {"brainpoolP160t1", NID_brainpoolP160t1 },
+ {"brainpoolP192r1", NID_brainpoolP192r1 },
+ {"brainpoolP192t1", NID_brainpoolP192t1 },
+ {"brainpoolP224r1", NID_brainpoolP224r1 },
+ {"brainpoolP224t1", NID_brainpoolP224t1 },
+ {"brainpoolP256r1", NID_brainpoolP256r1 },
+ {"brainpoolP256t1", NID_brainpoolP256t1 },
+ {"brainpoolP320r1", NID_brainpoolP320r1 },
+ {"brainpoolP320t1", NID_brainpoolP320t1 },
+ {"brainpoolP384r1", NID_brainpoolP384r1 },
+ {"brainpoolP384t1", NID_brainpoolP384t1 },
+ {"brainpoolP512r1", NID_brainpoolP512r1 },
+ {"brainpoolP512t1", NID_brainpoolP512t1 },
+ /* SM2 curve */
+ {"SM2", NID_sm2 },
+};
+
+const char *OSSL_EC_curve_nid2name(int nid)
+{
+ size_t i;
+
+ if (nid <= 0)
+ return NULL;
+
+ for (i = 0; i < OSSL_NELEM(curve_list); i++) {
+ if (curve_list[i].nid == nid)
+ return curve_list[i].name;
+ }
+ return NULL;
+}
+
+int ossl_ec_curve_name2nid(const char *name)
+{
+ size_t i;
+ int nid;
+
+ if (name != NULL) {
+ if ((nid = ossl_ec_curve_nist2nid_int(name)) != NID_undef)
+ return nid;
+
+ for (i = 0; i < OSSL_NELEM(curve_list); i++) {
+ if (OPENSSL_strcasecmp(curve_list[i].name, name) == 0)
+ return curve_list[i].nid;
+ }
+ }
+
+ return NID_undef;
+}
+
+/* Functions to translate between common NIST curve names and NIDs */
+
+static const EC_NAME2NID nist_curves[] = {
+ {"B-163", NID_sect163r2},
+ {"B-233", NID_sect233r1},
+ {"B-283", NID_sect283r1},
+ {"B-409", NID_sect409r1},
+ {"B-571", NID_sect571r1},
+ {"K-163", NID_sect163k1},
+ {"K-233", NID_sect233k1},
+ {"K-283", NID_sect283k1},
+ {"K-409", NID_sect409k1},
+ {"K-571", NID_sect571k1},
+ {"P-192", NID_X9_62_prime192v1},
+ {"P-224", NID_secp224r1},
+ {"P-256", NID_X9_62_prime256v1},
+ {"P-384", NID_secp384r1},
+ {"P-521", NID_secp521r1}
+};
+
+const char *ossl_ec_curve_nid2nist_int(int nid)
+{
+ size_t i;
+ for (i = 0; i < OSSL_NELEM(nist_curves); i++) {
+ if (nist_curves[i].nid == nid)
+ return nist_curves[i].name;
+ }
+ return NULL;
+}
+
+int ossl_ec_curve_nist2nid_int(const char *name)
+{
+ size_t i;
+ for (i = 0; i < OSSL_NELEM(nist_curves); i++) {
+ if (strcmp(nist_curves[i].name, name) == 0)
+ return nist_curves[i].nid;
+ }
+ return NID_undef;
+}
diff --git a/crypto/evp/encode.c b/crypto/evp/encode.c
index 85926434c300..2c047fa039ae 100644
--- a/crypto/evp/encode.c
+++ b/crypto/evp/encode.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,8 +11,8 @@
#include <limits.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
-#include "evp_local.h"
#include "crypto/evp.h"
+#include "evp_local.h"
static unsigned char conv_ascii2bin(unsigned char a,
const unsigned char *table);
@@ -134,7 +134,7 @@ void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
OPENSSL_free(ctx);
}
-int EVP_ENCODE_CTX_copy(EVP_ENCODE_CTX *dctx, EVP_ENCODE_CTX *sctx)
+int EVP_ENCODE_CTX_copy(EVP_ENCODE_CTX *dctx, const EVP_ENCODE_CTX *sctx)
{
memcpy(dctx, sctx, sizeof(EVP_ENCODE_CTX));
@@ -422,7 +422,7 @@ static int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
else
table = data_ascii2bin;
- /* trim white space from the start of the line. */
+ /* trim whitespace from the start of the line. */
while ((n > 0) && (conv_ascii2bin(*f, table) == B64_WS)) {
f++;
n--;
diff --git a/crypto/evp/evp_cnf.c b/crypto/evp/evp_cnf.c
index 8df2c06e1f52..0e7fe64cf92e 100644
--- a/crypto/evp/evp_cnf.c
+++ b/crypto/evp/evp_cnf.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2012-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,6 +13,8 @@
#include <openssl/conf.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
+#include <openssl/trace.h>
+#include "crypto/evp.h"
/* Algorithm configuration module. */
@@ -23,27 +25,42 @@ static int alg_module_init(CONF_IMODULE *md, const CONF *cnf)
STACK_OF(CONF_VALUE) *sktmp;
CONF_VALUE *oval;
+ OSSL_TRACE2(CONF, "Loading EVP module: name %s, value %s\n",
+ CONF_imodule_get_name(md), CONF_imodule_get_value(md));
+
oid_section = CONF_imodule_get_value(md);
if ((sktmp = NCONF_get_section(cnf, oid_section)) == NULL) {
- EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_ERROR_LOADING_SECTION);
+ ERR_raise(ERR_LIB_EVP, EVP_R_ERROR_LOADING_SECTION);
return 0;
}
for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
oval = sk_CONF_VALUE_value(sktmp, i);
if (strcmp(oval->name, "fips_mode") == 0) {
int m;
- if (!X509V3_get_value_bool(oval, &m)) {
- EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_INVALID_FIPS_MODE);
+
+ /* Detailed error already reported. */
+ if (!X509V3_get_value_bool(oval, &m))
+ return 0;
+
+ /*
+ * fips_mode is deprecated and should not be used in new
+ * configurations.
+ */
+ if (!evp_default_properties_enable_fips_int(
+ NCONF_get0_libctx((CONF *)cnf), m > 0, 0)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_SET_DEFAULT_PROPERTY_FAILURE);
return 0;
}
- if (m > 0) {
- EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_FIPS_MODE_NOT_SUPPORTED);
+ } else if (strcmp(oval->name, "default_properties") == 0) {
+ if (!evp_set_default_properties_int(NCONF_get0_libctx((CONF *)cnf),
+ oval->value, 0, 0)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_SET_DEFAULT_PROPERTY_FAILURE);
return 0;
}
} else {
- EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_UNKNOWN_OPTION);
- ERR_add_error_data(4, "name=", oval->name,
- ", value=", oval->value);
+ ERR_raise_data(ERR_LIB_EVP, EVP_R_UNKNOWN_OPTION,
+ "name=%s, value=%s", oval->name, oval->value);
+ return 0;
}
}
@@ -52,5 +69,6 @@ static int alg_module_init(CONF_IMODULE *md, const CONF *cnf)
void EVP_add_alg_module(void)
{
+ OSSL_TRACE(CONF, "Adding config module 'alg_section'\n");
CONF_module_add("alg_section", alg_module_init, 0);
}
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index e756624b2cdf..b178d1086473 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -1,40 +1,68 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <stdio.h>
#include <limits.h>
#include <assert.h>
-#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/rand.h>
-#include <openssl/rand_drbg.h>
-#include <openssl/engine.h>
+#ifndef FIPS_MODULE
+# include <openssl/engine.h>
+#endif
+#include <openssl/params.h>
+#include <openssl/core_names.h>
+#include "internal/cryptlib.h"
+#include "internal/provider.h"
+#include "internal/core.h"
#include "crypto/evp.h"
#include "evp_local.h"
-int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c)
+int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx)
{
- if (c == NULL)
+ if (ctx == NULL)
return 1;
- if (c->cipher != NULL) {
- if (c->cipher->cleanup && !c->cipher->cleanup(c))
+
+ if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
+ goto legacy;
+
+ if (ctx->algctx != NULL) {
+ if (ctx->cipher->freectx != NULL)
+ ctx->cipher->freectx(ctx->algctx);
+ ctx->algctx = NULL;
+ }
+ if (ctx->fetched_cipher != NULL)
+ EVP_CIPHER_free(ctx->fetched_cipher);
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->iv_len = -1;
+
+ return 1;
+
+ /* Remove legacy code below when legacy support is removed. */
+ legacy:
+
+ if (ctx->cipher != NULL) {
+ if (ctx->cipher->cleanup && !ctx->cipher->cleanup(ctx))
return 0;
/* Cleanse cipher context data */
- if (c->cipher_data && c->cipher->ctx_size)
- OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size);
+ if (ctx->cipher_data && ctx->cipher->ctx_size)
+ OPENSSL_cleanse(ctx->cipher_data, ctx->cipher->ctx_size);
}
- OPENSSL_free(c->cipher_data);
-#ifndef OPENSSL_NO_ENGINE
- ENGINE_finish(c->engine);
+ OPENSSL_free(ctx->cipher_data);
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
+ ENGINE_finish(ctx->engine);
#endif
- memset(c, 0, sizeof(*c));
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->iv_len = -1;
return 1;
}
@@ -45,30 +73,46 @@ EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void)
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
{
+ if (ctx == NULL)
+ return;
EVP_CIPHER_CTX_reset(ctx);
OPENSSL_free(ctx);
}
-int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
- const unsigned char *key, const unsigned char *iv, int enc)
+static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx,
+ const EVP_CIPHER *cipher,
+ ENGINE *impl, const unsigned char *key,
+ const unsigned char *iv, int enc,
+ const OSSL_PARAM params[])
{
- if (cipher != NULL)
- EVP_CIPHER_CTX_reset(ctx);
- return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc);
-}
+ int n;
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
+ ENGINE *tmpimpl = NULL;
+#endif
-int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
- ENGINE *impl, const unsigned char *key,
- const unsigned char *iv, int enc)
-{
- if (enc == -1)
+ ctx->iv_len = -1;
+
+ /*
+ * enc == 1 means we are encrypting.
+ * enc == 0 means we are decrypting.
+ * enc == -1 means, use the previously initialised value for encrypt/decrypt
+ */
+ if (enc == -1) {
enc = ctx->encrypt;
- else {
+ } else {
if (enc)
enc = 1;
ctx->encrypt = enc;
}
-#ifndef OPENSSL_NO_ENGINE
+
+ if (cipher == NULL && ctx->cipher == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
+ return 0;
+ }
+
+ /* Code below to be removed when legacy support is dropped. */
+
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
/*
* Whether it's nice or not, "Inits" can be used on "Final"'d contexts so
* this context may already have an ENGINE! Try to avoid releasing the
@@ -78,39 +122,168 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
if (ctx->engine && ctx->cipher
&& (cipher == NULL || cipher->nid == ctx->cipher->nid))
goto skip_to_init;
+
+ if (cipher != NULL && impl == NULL) {
+ /* Ask if an ENGINE is reserved for this job */
+ tmpimpl = ENGINE_get_cipher_engine(cipher->nid);
+ }
#endif
- if (cipher) {
+
+ /*
+ * If there are engines involved then we should use legacy handling for now.
+ */
+ if (ctx->engine != NULL
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
+ || tmpimpl != NULL
+#endif
+ || impl != NULL
+ || (cipher != NULL && cipher->origin == EVP_ORIG_METH)
+ || (cipher == NULL && ctx->cipher != NULL
+ && ctx->cipher->origin == EVP_ORIG_METH)) {
+ if (ctx->cipher == ctx->fetched_cipher)
+ ctx->cipher = NULL;
+ EVP_CIPHER_free(ctx->fetched_cipher);
+ ctx->fetched_cipher = NULL;
+ goto legacy;
+ }
+ /*
+ * Ensure a context left lying around from last time is cleared
+ * (legacy code)
+ */
+ if (cipher != NULL && ctx->cipher != NULL) {
+ if (ctx->cipher->cleanup != NULL && !ctx->cipher->cleanup(ctx))
+ return 0;
+ OPENSSL_clear_free(ctx->cipher_data, ctx->cipher->ctx_size);
+ ctx->cipher_data = NULL;
+ }
+
+ /* Start of non-legacy code below */
+
+ /* Ensure a context left lying around from last time is cleared */
+ if (cipher != NULL && ctx->cipher != NULL) {
+ unsigned long flags = ctx->flags;
+
+ EVP_CIPHER_CTX_reset(ctx);
+ /* Restore encrypt and flags */
+ ctx->encrypt = enc;
+ ctx->flags = flags;
+ }
+
+ if (cipher == NULL)
+ cipher = ctx->cipher;
+
+ if (cipher->prov == NULL) {
+#ifdef FIPS_MODULE
+ /* We only do explicit fetches inside the FIPS module */
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+#else
+ EVP_CIPHER *provciph =
+ EVP_CIPHER_fetch(NULL,
+ cipher->nid == NID_undef ? "NULL"
+ : OBJ_nid2sn(cipher->nid),
+ "");
+
+ if (provciph == NULL)
+ return 0;
+ cipher = provciph;
+ EVP_CIPHER_free(ctx->fetched_cipher);
+ ctx->fetched_cipher = provciph;
+#endif
+ }
+
+ if (cipher->prov != NULL) {
+ if (!EVP_CIPHER_up_ref((EVP_CIPHER *)cipher)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+ EVP_CIPHER_free(ctx->fetched_cipher);
+ ctx->fetched_cipher = (EVP_CIPHER *)cipher;
+ }
+ ctx->cipher = cipher;
+ if (ctx->algctx == NULL) {
+ ctx->algctx = ctx->cipher->newctx(ossl_provider_ctx(cipher->prov));
+ if (ctx->algctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+ }
+
+ if ((ctx->flags & EVP_CIPH_NO_PADDING) != 0) {
/*
- * Ensure a context left lying around from last time is cleared (the
- * previous check attempted to avoid this if the same ENGINE and
+ * If this ctx was already set up for no padding then we need to tell
+ * the new cipher about it.
+ */
+ if (!EVP_CIPHER_CTX_set_padding(ctx, 0))
+ return 0;
+ }
+
+ if (enc) {
+ if (ctx->cipher->einit == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+
+ return ctx->cipher->einit(ctx->algctx,
+ key,
+ key == NULL ? 0
+ : EVP_CIPHER_CTX_get_key_length(ctx),
+ iv,
+ iv == NULL ? 0
+ : EVP_CIPHER_CTX_get_iv_length(ctx),
+ params);
+ }
+
+ if (ctx->cipher->dinit == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+
+ return ctx->cipher->dinit(ctx->algctx,
+ key,
+ key == NULL ? 0
+ : EVP_CIPHER_CTX_get_key_length(ctx),
+ iv,
+ iv == NULL ? 0
+ : EVP_CIPHER_CTX_get_iv_length(ctx),
+ params);
+
+ /* Code below to be removed when legacy support is dropped. */
+ legacy:
+
+ if (cipher != NULL) {
+ /*
+ * Ensure a context left lying around from last time is cleared (we
+ * previously attempted to avoid this if the same ENGINE and
* EVP_CIPHER could be used).
*/
- if (ctx->cipher
-#ifndef OPENSSL_NO_ENGINE
- || ctx->engine
-#endif
- || ctx->cipher_data) {
+ if (ctx->cipher) {
unsigned long flags = ctx->flags;
EVP_CIPHER_CTX_reset(ctx);
/* Restore encrypt and flags */
ctx->encrypt = enc;
ctx->flags = flags;
}
-#ifndef OPENSSL_NO_ENGINE
- if (impl) {
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
+ if (impl != NULL) {
if (!ENGINE_init(impl)) {
- EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
- } else
- /* Ask if an ENGINE is reserved for this job */
- impl = ENGINE_get_cipher_engine(cipher->nid);
- if (impl) {
+ } else {
+ impl = tmpimpl;
+ }
+ if (impl != NULL) {
/* There's an ENGINE for this job ... (apparently) */
const EVP_CIPHER *c = ENGINE_get_cipher(impl, cipher->nid);
- if (!c) {
- ENGINE_finish(impl);
- EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
+
+ if (c == NULL) {
+ /*
+ * One positive side-effect of US's export control history,
+ * is that we should at least be able to avoid using US
+ * misspellings of "initialisation"?
+ */
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
/* We'll use the ENGINE's private cipher definition */
@@ -120,8 +293,9 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
* from an ENGINE and we need to release it when done.
*/
ctx->engine = impl;
- } else
+ } else {
ctx->engine = NULL;
+ }
#endif
ctx->cipher = cipher;
@@ -129,7 +303,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
ctx->cipher_data = OPENSSL_zalloc(ctx->cipher->ctx_size);
if (ctx->cipher_data == NULL) {
ctx->cipher = NULL;
- EVPerr(EVP_F_EVP_CIPHERINIT_EX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
} else {
@@ -139,32 +313,33 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
/* Preserve wrap enable flag, zero everything else */
ctx->flags &= EVP_CIPHER_CTX_FLAG_WRAP_ALLOW;
if (ctx->cipher->flags & EVP_CIPH_CTRL_INIT) {
- if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) {
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL) <= 0) {
ctx->cipher = NULL;
- EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
}
- } else if (!ctx->cipher) {
- EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_NO_CIPHER_SET);
- return 0;
}
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
skip_to_init:
#endif
+ if (ctx->cipher == NULL)
+ return 0;
+
/* we assume block size is a power of 2 in *cryptUpdate */
OPENSSL_assert(ctx->cipher->block_size == 1
|| ctx->cipher->block_size == 8
|| ctx->cipher->block_size == 16);
if (!(ctx->flags & EVP_CIPHER_CTX_FLAG_WRAP_ALLOW)
- && EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_WRAP_MODE) {
- EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_WRAP_MODE_NOT_ALLOWED);
+ && EVP_CIPHER_CTX_get_mode(ctx) == EVP_CIPH_WRAP_MODE) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_WRAP_MODE_NOT_ALLOWED);
return 0;
}
- if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_CUSTOM_IV)) {
- switch (EVP_CIPHER_CTX_mode(ctx)) {
+ if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx))
+ & EVP_CIPH_CUSTOM_IV) == 0) {
+ switch (EVP_CIPHER_CTX_get_mode(ctx)) {
case EVP_CIPH_STREAM_CIPHER:
case EVP_CIPH_ECB_MODE:
@@ -177,19 +352,27 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
/* fall-through */
case EVP_CIPH_CBC_MODE:
-
- OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) <=
- (int)sizeof(ctx->iv));
- if (iv)
- memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
- memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
+ n = EVP_CIPHER_CTX_get_iv_length(ctx);
+ if (n < 0 || n > (int)sizeof(ctx->iv)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ if (iv != NULL)
+ memcpy(ctx->oiv, iv, n);
+ memcpy(ctx->iv, ctx->oiv, n);
break;
case EVP_CIPH_CTR_MODE:
ctx->num = 0;
/* Don't reuse IV for CTR mode */
- if (iv)
- memcpy(ctx->iv, iv, EVP_CIPHER_CTX_iv_length(ctx));
+ if (iv != NULL) {
+ n = EVP_CIPHER_CTX_get_iv_length(ctx);
+ if (n <= 0 || n > (int)sizeof(ctx->iv)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ memcpy(ctx->iv, iv, n);
+ }
break;
default:
@@ -197,7 +380,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
}
}
- if (key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) {
+ if (key != NULL || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) {
if (!ctx->cipher->init(ctx, key, iv, enc))
return 0;
}
@@ -207,6 +390,28 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
return 1;
}
+int EVP_CipherInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ const unsigned char *key, const unsigned char *iv,
+ int enc, const OSSL_PARAM params[])
+{
+ return evp_cipher_init_internal(ctx, cipher, NULL, key, iv, enc, params);
+}
+
+int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ const unsigned char *key, const unsigned char *iv, int enc)
+{
+ if (cipher != NULL)
+ EVP_CIPHER_CTX_reset(ctx);
+ return evp_cipher_init_internal(ctx, cipher, NULL, key, iv, enc, NULL);
+}
+
+int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ ENGINE *impl, const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ return evp_cipher_init_internal(ctx, cipher, impl, key, iv, enc, NULL);
+}
+
int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
const unsigned char *in, int inl)
{
@@ -245,6 +450,13 @@ int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 1);
}
+int EVP_EncryptInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ const unsigned char *key, const unsigned char *iv,
+ const OSSL_PARAM params[])
+{
+ return EVP_CipherInit_ex2(ctx, cipher, key, iv, 1, params);
+}
+
int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const unsigned char *key, const unsigned char *iv)
{
@@ -258,6 +470,13 @@ int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 0);
}
+int EVP_DecryptInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ const unsigned char *key, const unsigned char *iv,
+ const OSSL_PARAM params[])
+{
+ return EVP_CipherInit_ex2(ctx, cipher, key, iv, 0, params);
+}
+
/*
* According to the letter of standard difference between pointers
* is specified to be valid only within same object. This makes
@@ -281,7 +500,7 @@ int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
# define PTRDIFF_T size_t
#endif
-int is_partially_overlapping(const void *ptr1, const void *ptr2, size_t len)
+int ossl_is_partially_overlapping(const void *ptr1, const void *ptr2, int len)
{
PTRDIFF_T diff = (PTRDIFF_T)ptr1-(PTRDIFF_T)ptr2;
/*
@@ -299,29 +518,17 @@ static int evp_EncryptDecryptUpdate(EVP_CIPHER_CTX *ctx,
unsigned char *out, int *outl,
const unsigned char *in, int inl)
{
- int i, j, bl;
- size_t cmpl = (size_t)inl;
+ int i, j, bl, cmpl = inl;
if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS))
cmpl = (cmpl + 7) / 8;
bl = ctx->cipher->block_size;
- /*
- * CCM mode needs to know about the case where inl == 0 && in == NULL - it
- * means the plaintext/ciphertext length is 0
- */
- if (inl < 0
- || (inl == 0
- && EVP_CIPHER_mode(ctx->cipher) != EVP_CIPH_CCM_MODE)) {
- *outl = 0;
- return inl == 0;
- }
-
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
/* If block size > 1 then the cipher will have to do this check */
- if (bl == 1 && is_partially_overlapping(out, in, cmpl)) {
- EVPerr(EVP_F_EVP_ENCRYPTDECRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING);
+ if (bl == 1 && ossl_is_partially_overlapping(out, in, cmpl)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING);
return 0;
}
@@ -333,8 +540,12 @@ static int evp_EncryptDecryptUpdate(EVP_CIPHER_CTX *ctx,
return 1;
}
- if (is_partially_overlapping(out + ctx->buf_len, in, cmpl)) {
- EVPerr(EVP_F_EVP_ENCRYPTDECRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING);
+ if (inl <= 0) {
+ *outl = 0;
+ return inl == 0;
+ }
+ if (ossl_is_partially_overlapping(out + ctx->buf_len, in, cmpl)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING);
return 0;
}
@@ -366,8 +577,7 @@ static int evp_EncryptDecryptUpdate(EVP_CIPHER_CTX *ctx,
* we process from ctx->buf does not exceed INT_MAX
*/
if (((inl - j) & ~(bl - 1)) > INT_MAX - bl) {
- EVPerr(EVP_F_EVP_ENCRYPTDECRYPTUPDATE,
- EVP_R_OUTPUT_WOULD_OVERFLOW);
+ ERR_raise(ERR_LIB_EVP, EVP_R_OUTPUT_WOULD_OVERFLOW);
return 0;
}
memcpy(&(ctx->buf[i]), in, j);
@@ -398,12 +608,55 @@ static int evp_EncryptDecryptUpdate(EVP_CIPHER_CTX *ctx,
int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
const unsigned char *in, int inl)
{
+ int ret;
+ size_t soutl, inl_ = (size_t)inl;
+ int blocksize;
+
+ if (outl != NULL) {
+ *outl = 0;
+ } else {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
/* Prevent accidental use of decryption context when encrypting */
if (!ctx->encrypt) {
- EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_INVALID_OPERATION);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
+ return 0;
+ }
+
+ if (ctx->cipher == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
+ return 0;
+ }
+
+ if (ctx->cipher->prov == NULL)
+ goto legacy;
+
+ blocksize = ctx->cipher->block_size;
+
+ if (ctx->cipher->cupdate == NULL || blocksize < 1) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
return 0;
}
+ ret = ctx->cipher->cupdate(ctx->algctx, out, &soutl,
+ inl_ + (size_t)(blocksize == 1 ? 0 : blocksize),
+ in, inl_);
+
+ if (ret) {
+ if (soutl > INT_MAX) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
+ return 0;
+ }
+ *outl = soutl;
+ }
+
+ return ret;
+
+ /* Code below to be removed when legacy support is dropped. */
+ legacy:
+
return evp_EncryptDecryptUpdate(ctx, out, outl, in, inl);
}
@@ -418,13 +671,52 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
{
int n, ret;
unsigned int i, b, bl;
+ size_t soutl;
+ int blocksize;
+
+ if (outl != NULL) {
+ *outl = 0;
+ } else {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
/* Prevent accidental use of decryption context when encrypting */
if (!ctx->encrypt) {
- EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_INVALID_OPERATION);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
return 0;
}
+ if (ctx->cipher == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
+ return 0;
+ }
+ if (ctx->cipher->prov == NULL)
+ goto legacy;
+
+ blocksize = EVP_CIPHER_CTX_get_block_size(ctx);
+
+ if (blocksize < 1 || ctx->cipher->cfinal == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
+ return 0;
+ }
+
+ ret = ctx->cipher->cfinal(ctx->algctx, out, &soutl,
+ blocksize == 1 ? 0 : blocksize);
+
+ if (ret) {
+ if (soutl > INT_MAX) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
+ return 0;
+ }
+ *outl = soutl;
+ }
+
+ return ret;
+
+ /* Code below to be removed when legacy support is dropped. */
+ legacy:
+
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
ret = ctx->cipher->do_cipher(ctx, out, NULL, 0);
if (ret < 0)
@@ -443,8 +735,7 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
bl = ctx->buf_len;
if (ctx->flags & EVP_CIPH_NO_PADDING) {
if (bl) {
- EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX,
- EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
+ ERR_raise(ERR_LIB_EVP, EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
return 0;
}
*outl = 0;
@@ -465,35 +756,62 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
const unsigned char *in, int inl)
{
- int fix_len;
+ int fix_len, cmpl = inl, ret;
unsigned int b;
- size_t cmpl = (size_t)inl;
+ size_t soutl, inl_ = (size_t)inl;
+ int blocksize;
+
+ if (outl != NULL) {
+ *outl = 0;
+ } else {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
/* Prevent accidental use of encryption context when decrypting */
if (ctx->encrypt) {
- EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_INVALID_OPERATION);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
return 0;
}
+ if (ctx->cipher == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
+ return 0;
+ }
+ if (ctx->cipher->prov == NULL)
+ goto legacy;
+
+ blocksize = EVP_CIPHER_CTX_get_block_size(ctx);
+
+ if (ctx->cipher->cupdate == NULL || blocksize < 1) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
+ return 0;
+ }
+ ret = ctx->cipher->cupdate(ctx->algctx, out, &soutl,
+ inl_ + (size_t)(blocksize == 1 ? 0 : blocksize),
+ in, inl_);
+
+ if (ret) {
+ if (soutl > INT_MAX) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
+ return 0;
+ }
+ *outl = soutl;
+ }
+
+ return ret;
+
+ /* Code below to be removed when legacy support is dropped. */
+ legacy:
+
b = ctx->cipher->block_size;
if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS))
cmpl = (cmpl + 7) / 8;
- /*
- * CCM mode needs to know about the case where inl == 0 - it means the
- * plaintext/ciphertext length is 0
- */
- if (inl < 0
- || (inl == 0
- && EVP_CIPHER_mode(ctx->cipher) != EVP_CIPH_CCM_MODE)) {
- *outl = 0;
- return inl == 0;
- }
-
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
- if (b == 1 && is_partially_overlapping(out, in, cmpl)) {
- EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING);
+ if (b == 1 && ossl_is_partially_overlapping(out, in, cmpl)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING);
return 0;
}
@@ -506,6 +824,11 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
return 1;
}
+ if (inl <= 0) {
+ *outl = 0;
+ return inl == 0;
+ }
+
if (ctx->flags & EVP_CIPH_NO_PADDING)
return evp_EncryptDecryptUpdate(ctx, out, outl, in, inl);
@@ -514,8 +837,8 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
if (ctx->final_used) {
/* see comment about PTRDIFF_T comparison above */
if (((PTRDIFF_T)out == (PTRDIFF_T)in)
- || is_partially_overlapping(out, in, b)) {
- EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING);
+ || ossl_is_partially_overlapping(out, in, b)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING);
return 0;
}
/*
@@ -528,7 +851,7 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
* This must never exceed INT_MAX
*/
if ((inl & ~(b - 1)) > INT_MAX - b) {
- EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_OUTPUT_WOULD_OVERFLOW);
+ ERR_raise(ERR_LIB_EVP, EVP_R_OUTPUT_WOULD_OVERFLOW);
return 0;
}
memcpy(out, ctx->final, b);
@@ -568,15 +891,55 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
{
int i, n;
unsigned int b;
+ size_t soutl;
+ int ret;
+ int blocksize;
+
+ if (outl != NULL) {
+ *outl = 0;
+ } else {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
/* Prevent accidental use of encryption context when decrypting */
if (ctx->encrypt) {
- EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_INVALID_OPERATION);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
return 0;
}
- *outl = 0;
+ if (ctx->cipher == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
+ return 0;
+ }
+
+ if (ctx->cipher->prov == NULL)
+ goto legacy;
+
+ blocksize = EVP_CIPHER_CTX_get_block_size(ctx);
+
+ if (blocksize < 1 || ctx->cipher->cfinal == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
+ return 0;
+ }
+ ret = ctx->cipher->cfinal(ctx->algctx, out, &soutl,
+ blocksize == 1 ? 0 : blocksize);
+
+ if (ret) {
+ if (soutl > INT_MAX) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
+ return 0;
+ }
+ *outl = soutl;
+ }
+
+ return ret;
+
+ /* Code below to be removed when legacy support is dropped. */
+ legacy:
+
+ *outl = 0;
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
i = ctx->cipher->do_cipher(ctx, out, NULL, 0);
if (i < 0)
@@ -589,8 +952,7 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
b = ctx->cipher->block_size;
if (ctx->flags & EVP_CIPH_NO_PADDING) {
if (ctx->buf_len) {
- EVPerr(EVP_F_EVP_DECRYPTFINAL_EX,
- EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
+ ERR_raise(ERR_LIB_EVP, EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
return 0;
}
*outl = 0;
@@ -598,7 +960,7 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
}
if (b > 1) {
if (ctx->buf_len || !ctx->final_used) {
- EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_WRONG_FINAL_BLOCK_LENGTH);
+ ERR_raise(ERR_LIB_EVP, EVP_R_WRONG_FINAL_BLOCK_LENGTH);
return 0;
}
OPENSSL_assert(b <= sizeof(ctx->final));
@@ -609,12 +971,12 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
*/
n = ctx->final[b - 1];
if (n == 0 || n > (int)b) {
- EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_BAD_DECRYPT);
+ ERR_raise(ERR_LIB_EVP, EVP_R_BAD_DECRYPT);
return 0;
}
for (i = 0; i < n; i++) {
if (ctx->final[--b] != n) {
- EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_BAD_DECRYPT);
+ ERR_raise(ERR_LIB_EVP, EVP_R_BAD_DECRYPT);
return 0;
}
}
@@ -629,69 +991,420 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
{
+ if (c->cipher->prov != NULL) {
+ int ok;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ size_t len = keylen;
+
+ if (EVP_CIPHER_CTX_get_key_length(c) == keylen)
+ return 1;
+
+ /* Check the cipher actually understands this parameter */
+ if (OSSL_PARAM_locate_const(EVP_CIPHER_settable_ctx_params(c->cipher),
+ OSSL_CIPHER_PARAM_KEYLEN) == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &len);
+ ok = evp_do_ciph_ctx_setparams(c->cipher, c->algctx, params);
+
+ return ok > 0 ? 1 : 0;
+ }
+
+ /* Code below to be removed when legacy support is dropped. */
+
+ /*
+ * Note there have never been any built-in ciphers that define this flag
+ * since it was first introduced.
+ */
if (c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH)
return EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_KEY_LENGTH, keylen, NULL);
- if (c->key_len == keylen)
+ if (EVP_CIPHER_CTX_get_key_length(c) == keylen)
return 1;
if ((keylen > 0) && (c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH)) {
c->key_len = keylen;
return 1;
}
- EVPerr(EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH, EVP_R_INVALID_KEY_LENGTH);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH);
return 0;
}
int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad)
{
+ int ok;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ unsigned int pd = pad;
+
if (pad)
ctx->flags &= ~EVP_CIPH_NO_PADDING;
else
ctx->flags |= EVP_CIPH_NO_PADDING;
- return 1;
+
+ if (ctx->cipher != NULL && ctx->cipher->prov == NULL)
+ return 1;
+ params[0] = OSSL_PARAM_construct_uint(OSSL_CIPHER_PARAM_PADDING, &pd);
+ ok = evp_do_ciph_ctx_setparams(ctx->cipher, ctx->algctx, params);
+
+ return ok != 0;
}
int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
{
- int ret;
-
- if (!ctx->cipher) {
- EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_NO_CIPHER_SET);
+ int ret = EVP_CTRL_RET_UNSUPPORTED;
+ int set_params = 1;
+ size_t sz = arg;
+ unsigned int i;
+ OSSL_PARAM params[4] = {
+ OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END
+ };
+
+ if (ctx == NULL || ctx->cipher == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
return 0;
}
- if (!ctx->cipher->ctrl) {
- EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_NOT_IMPLEMENTED);
+ if (ctx->cipher->prov == NULL)
+ goto legacy;
+
+ switch (type) {
+ case EVP_CTRL_SET_KEY_LENGTH:
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &sz);
+ break;
+ case EVP_CTRL_RAND_KEY: /* Used by DES */
+ set_params = 0;
+ params[0] =
+ OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_RANDOM_KEY,
+ ptr, sz);
+ break;
+
+ case EVP_CTRL_INIT:
+ /*
+ * EVP_CTRL_INIT is purely legacy, no provider counterpart.
+ * As a matter of fact, this should be dead code, but some caller
+ * might still do a direct control call with this command, so...
+ * Legacy methods return 1 except for exceptional circumstances, so
+ * we do the same here to not be disruptive.
+ */
+ return 1;
+ case EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS: /* Used by DASYNC */
+ default:
+ goto end;
+ case EVP_CTRL_AEAD_SET_IVLEN:
+ if (arg < 0)
+ return 0;
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN, &sz);
+ ctx->iv_len = -1;
+ break;
+ case EVP_CTRL_CCM_SET_L:
+ if (arg < 2 || arg > 8)
+ return 0;
+ sz = 15 - arg;
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN, &sz);
+ ctx->iv_len = -1;
+ break;
+ case EVP_CTRL_AEAD_SET_IV_FIXED:
+ params[0] = OSSL_PARAM_construct_octet_string(
+ OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED, ptr, sz);
+ break;
+ case EVP_CTRL_GCM_IV_GEN:
+ set_params = 0;
+ if (arg < 0)
+ sz = 0; /* special case that uses the iv length */
+ params[0] = OSSL_PARAM_construct_octet_string(
+ OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN, ptr, sz);
+ break;
+ case EVP_CTRL_GCM_SET_IV_INV:
+ if (arg < 0)
+ return 0;
+ params[0] = OSSL_PARAM_construct_octet_string(
+ OSSL_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV, ptr, sz);
+ break;
+ case EVP_CTRL_GET_RC5_ROUNDS:
+ set_params = 0; /* Fall thru */
+ case EVP_CTRL_SET_RC5_ROUNDS:
+ if (arg < 0)
+ return 0;
+ i = (unsigned int)arg;
+ params[0] = OSSL_PARAM_construct_uint(OSSL_CIPHER_PARAM_ROUNDS, &i);
+ break;
+ case EVP_CTRL_SET_SPEED:
+ if (arg < 0)
+ return 0;
+ i = (unsigned int)arg;
+ params[0] = OSSL_PARAM_construct_uint(OSSL_CIPHER_PARAM_SPEED, &i);
+ break;
+ case EVP_CTRL_AEAD_GET_TAG:
+ set_params = 0; /* Fall thru */
+ case EVP_CTRL_AEAD_SET_TAG:
+ params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
+ ptr, sz);
+ break;
+ case EVP_CTRL_AEAD_TLS1_AAD:
+ /* This one does a set and a get - since it returns a size */
+ params[0] =
+ OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD,
+ ptr, sz);
+ ret = evp_do_ciph_ctx_setparams(ctx->cipher, ctx->algctx, params);
+ if (ret <= 0)
+ goto end;
+ params[0] =
+ OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, &sz);
+ ret = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params);
+ if (ret <= 0)
+ goto end;
+ return sz;
+#ifndef OPENSSL_NO_RC2
+ case EVP_CTRL_GET_RC2_KEY_BITS:
+ set_params = 0; /* Fall thru */
+ case EVP_CTRL_SET_RC2_KEY_BITS:
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_RC2_KEYBITS, &sz);
+ break;
+#endif /* OPENSSL_NO_RC2 */
+#if !defined(OPENSSL_NO_MULTIBLOCK)
+ case EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE:
+ params[0] = OSSL_PARAM_construct_size_t(
+ OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT, &sz);
+ ret = evp_do_ciph_ctx_setparams(ctx->cipher, ctx->algctx, params);
+ if (ret <= 0)
+ return 0;
+
+ params[0] = OSSL_PARAM_construct_size_t(
+ OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE, &sz);
+ params[1] = OSSL_PARAM_construct_end();
+ ret = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params);
+ if (ret <= 0)
+ return 0;
+ return sz;
+ case EVP_CTRL_TLS1_1_MULTIBLOCK_AAD: {
+ EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *p =
+ (EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *)ptr;
+
+ if (arg < (int)sizeof(EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM))
+ return 0;
+
+ params[0] = OSSL_PARAM_construct_octet_string(
+ OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD, (void*)p->inp, p->len);
+ params[1] = OSSL_PARAM_construct_uint(
+ OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE, &p->interleave);
+ ret = evp_do_ciph_ctx_setparams(ctx->cipher, ctx->algctx, params);
+ if (ret <= 0)
+ return ret;
+ /* Retrieve the return values changed by the set */
+ params[0] = OSSL_PARAM_construct_size_t(
+ OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN, &sz);
+ params[1] = OSSL_PARAM_construct_uint(
+ OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE, &p->interleave);
+ params[2] = OSSL_PARAM_construct_end();
+ ret = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params);
+ if (ret <= 0)
+ return 0;
+ return sz;
+ }
+ case EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT: {
+ EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *p =
+ (EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *)ptr;
+
+ params[0] = OSSL_PARAM_construct_octet_string(
+ OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC, p->out, p->len);
+
+ params[1] = OSSL_PARAM_construct_octet_string(
+ OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN, (void*)p->inp,
+ p->len);
+ params[2] = OSSL_PARAM_construct_uint(
+ OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE, &p->interleave);
+ ret = evp_do_ciph_ctx_setparams(ctx->cipher, ctx->algctx, params);
+ if (ret <= 0)
+ return ret;
+ params[0] = OSSL_PARAM_construct_size_t(
+ OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN, &sz);
+ params[1] = OSSL_PARAM_construct_end();
+ ret = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params);
+ if (ret <= 0)
+ return 0;
+ return sz;
+ }
+#endif /* OPENSSL_NO_MULTIBLOCK */
+ case EVP_CTRL_AEAD_SET_MAC_KEY:
+ if (arg < 0)
+ return -1;
+ params[0] = OSSL_PARAM_construct_octet_string(
+ OSSL_CIPHER_PARAM_AEAD_MAC_KEY, ptr, sz);
+ break;
+ }
+
+ if (set_params)
+ ret = evp_do_ciph_ctx_setparams(ctx->cipher, ctx->algctx, params);
+ else
+ ret = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params);
+ goto end;
+
+ /* Code below to be removed when legacy support is dropped. */
+legacy:
+ if (ctx->cipher->ctrl == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_CTRL_NOT_IMPLEMENTED);
return 0;
}
ret = ctx->cipher->ctrl(ctx, type, arg, ptr);
- if (ret == -1) {
- EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL,
- EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED);
+
+ end:
+ if (ret == EVP_CTRL_RET_UNSUPPORTED) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED);
return 0;
}
return ret;
}
+int EVP_CIPHER_get_params(EVP_CIPHER *cipher, OSSL_PARAM params[])
+{
+ if (cipher != NULL && cipher->get_params != NULL)
+ return cipher->get_params(params);
+ return 0;
+}
+
+int EVP_CIPHER_CTX_set_params(EVP_CIPHER_CTX *ctx, const OSSL_PARAM params[])
+{
+ if (ctx->cipher != NULL && ctx->cipher->set_ctx_params != NULL) {
+ ctx->iv_len = -1;
+ return ctx->cipher->set_ctx_params(ctx->algctx, params);
+ }
+ return 0;
+}
+
+int EVP_CIPHER_CTX_get_params(EVP_CIPHER_CTX *ctx, OSSL_PARAM params[])
+{
+ if (ctx->cipher != NULL && ctx->cipher->get_ctx_params != NULL)
+ return ctx->cipher->get_ctx_params(ctx->algctx, params);
+ return 0;
+}
+
+const OSSL_PARAM *EVP_CIPHER_gettable_params(const EVP_CIPHER *cipher)
+{
+ if (cipher != NULL && cipher->gettable_params != NULL)
+ return cipher->gettable_params(
+ ossl_provider_ctx(EVP_CIPHER_get0_provider(cipher)));
+ return NULL;
+}
+
+const OSSL_PARAM *EVP_CIPHER_settable_ctx_params(const EVP_CIPHER *cipher)
+{
+ void *provctx;
+
+ if (cipher != NULL && cipher->settable_ctx_params != NULL) {
+ provctx = ossl_provider_ctx(EVP_CIPHER_get0_provider(cipher));
+ return cipher->settable_ctx_params(NULL, provctx);
+ }
+ return NULL;
+}
+
+const OSSL_PARAM *EVP_CIPHER_gettable_ctx_params(const EVP_CIPHER *cipher)
+{
+ void *provctx;
+
+ if (cipher != NULL && cipher->gettable_ctx_params != NULL) {
+ provctx = ossl_provider_ctx(EVP_CIPHER_get0_provider(cipher));
+ return cipher->gettable_ctx_params(NULL, provctx);
+ }
+ return NULL;
+}
+
+const OSSL_PARAM *EVP_CIPHER_CTX_settable_params(EVP_CIPHER_CTX *cctx)
+{
+ void *alg;
+
+ if (cctx != NULL && cctx->cipher->settable_ctx_params != NULL) {
+ alg = ossl_provider_ctx(EVP_CIPHER_get0_provider(cctx->cipher));
+ return cctx->cipher->settable_ctx_params(cctx->algctx, alg);
+ }
+ return NULL;
+}
+
+const OSSL_PARAM *EVP_CIPHER_CTX_gettable_params(EVP_CIPHER_CTX *cctx)
+{
+ void *provctx;
+
+ if (cctx != NULL && cctx->cipher->gettable_ctx_params != NULL) {
+ provctx = ossl_provider_ctx(EVP_CIPHER_get0_provider(cctx->cipher));
+ return cctx->cipher->gettable_ctx_params(cctx->algctx, provctx);
+ }
+ return NULL;
+}
+
+#ifndef FIPS_MODULE
+static OSSL_LIB_CTX *EVP_CIPHER_CTX_get_libctx(EVP_CIPHER_CTX *ctx)
+{
+ const EVP_CIPHER *cipher = ctx->cipher;
+ const OSSL_PROVIDER *prov;
+
+ if (cipher == NULL)
+ return NULL;
+
+ prov = EVP_CIPHER_get0_provider(cipher);
+ return ossl_provider_libctx(prov);
+}
+#endif
+
int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key)
{
if (ctx->cipher->flags & EVP_CIPH_RAND_KEY)
return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, key);
- if (RAND_priv_bytes(key, ctx->key_len) <= 0)
- return 0;
- return 1;
+
+#ifdef FIPS_MODULE
+ return 0;
+#else
+ {
+ int kl;
+ OSSL_LIB_CTX *libctx = EVP_CIPHER_CTX_get_libctx(ctx);
+
+ kl = EVP_CIPHER_CTX_get_key_length(ctx);
+ if (kl <= 0 || RAND_priv_bytes_ex(libctx, key, kl, 0) <= 0)
+ return 0;
+ return 1;
+ }
+#endif /* FIPS_MODULE */
}
int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
{
if ((in == NULL) || (in->cipher == NULL)) {
- EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, EVP_R_INPUT_NOT_INITIALIZED);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INPUT_NOT_INITIALIZED);
return 0;
}
-#ifndef OPENSSL_NO_ENGINE
+
+ if (in->cipher->prov == NULL)
+ goto legacy;
+
+ if (in->cipher->dupctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NOT_ABLE_TO_COPY_CTX);
+ return 0;
+ }
+
+ EVP_CIPHER_CTX_reset(out);
+
+ *out = *in;
+ out->algctx = NULL;
+
+ if (in->fetched_cipher != NULL && !EVP_CIPHER_up_ref(in->fetched_cipher)) {
+ out->fetched_cipher = NULL;
+ return 0;
+ }
+
+ out->algctx = in->cipher->dupctx(in->algctx);
+ if (out->algctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NOT_ABLE_TO_COPY_CTX);
+ return 0;
+ }
+
+ return 1;
+
+ /* Code below to be removed when legacy support is dropped. */
+ legacy:
+
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
/* Make sure it's safe to copy a cipher context using an ENGINE */
if (in->engine && !ENGINE_init(in->engine)) {
- EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, ERR_R_ENGINE_LIB);
+ ERR_raise(ERR_LIB_EVP, ERR_R_ENGINE_LIB);
return 0;
}
#endif
@@ -703,7 +1416,7 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size);
if (out->cipher_data == NULL) {
out->cipher = NULL;
- EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size);
@@ -712,8 +1425,253 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
if (in->cipher->flags & EVP_CIPH_CUSTOM_COPY)
if (!in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out)) {
out->cipher = NULL;
- EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, EVP_R_INITIALIZATION_ERROR);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
return 1;
}
+
+EVP_CIPHER *evp_cipher_new(void)
+{
+ EVP_CIPHER *cipher = OPENSSL_zalloc(sizeof(EVP_CIPHER));
+
+ if (cipher != NULL) {
+ cipher->lock = CRYPTO_THREAD_lock_new();
+ if (cipher->lock == NULL) {
+ OPENSSL_free(cipher);
+ return NULL;
+ }
+ cipher->refcnt = 1;
+ }
+ return cipher;
+}
+
+/*
+ * FIPS module note: since internal fetches will be entirely
+ * provider based, we know that none of its code depends on legacy
+ * NIDs or any functionality that use them.
+ */
+#ifndef FIPS_MODULE
+/* After removal of legacy support get rid of the need for legacy NIDs */
+static void set_legacy_nid(const char *name, void *vlegacy_nid)
+{
+ int nid;
+ int *legacy_nid = vlegacy_nid;
+ /*
+ * We use lowest level function to get the associated method, because
+ * higher level functions such as EVP_get_cipherbyname() have changed
+ * to look at providers too.
+ */
+ const void *legacy_method = OBJ_NAME_get(name, OBJ_NAME_TYPE_CIPHER_METH);
+
+ if (*legacy_nid == -1) /* We found a clash already */
+ return;
+ if (legacy_method == NULL)
+ return;
+ nid = EVP_CIPHER_get_nid(legacy_method);
+ if (*legacy_nid != NID_undef && *legacy_nid != nid) {
+ *legacy_nid = -1;
+ return;
+ }
+ *legacy_nid = nid;
+}
+#endif
+
+static void *evp_cipher_from_algorithm(const int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
+{
+ const OSSL_DISPATCH *fns = algodef->implementation;
+ EVP_CIPHER *cipher = NULL;
+ int fnciphcnt = 0, fnctxcnt = 0;
+
+ if ((cipher = evp_cipher_new()) == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+#ifndef FIPS_MODULE
+ cipher->nid = NID_undef;
+ if (!evp_names_do_all(prov, name_id, set_legacy_nid, &cipher->nid)
+ || cipher->nid == -1) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ EVP_CIPHER_free(cipher);
+ return NULL;
+ }
+#endif
+
+ cipher->name_id = name_id;
+ if ((cipher->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
+ EVP_CIPHER_free(cipher);
+ return NULL;
+ }
+ cipher->description = algodef->algorithm_description;
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_CIPHER_NEWCTX:
+ if (cipher->newctx != NULL)
+ break;
+ cipher->newctx = OSSL_FUNC_cipher_newctx(fns);
+ fnctxcnt++;
+ break;
+ case OSSL_FUNC_CIPHER_ENCRYPT_INIT:
+ if (cipher->einit != NULL)
+ break;
+ cipher->einit = OSSL_FUNC_cipher_encrypt_init(fns);
+ fnciphcnt++;
+ break;
+ case OSSL_FUNC_CIPHER_DECRYPT_INIT:
+ if (cipher->dinit != NULL)
+ break;
+ cipher->dinit = OSSL_FUNC_cipher_decrypt_init(fns);
+ fnciphcnt++;
+ break;
+ case OSSL_FUNC_CIPHER_UPDATE:
+ if (cipher->cupdate != NULL)
+ break;
+ cipher->cupdate = OSSL_FUNC_cipher_update(fns);
+ fnciphcnt++;
+ break;
+ case OSSL_FUNC_CIPHER_FINAL:
+ if (cipher->cfinal != NULL)
+ break;
+ cipher->cfinal = OSSL_FUNC_cipher_final(fns);
+ fnciphcnt++;
+ break;
+ case OSSL_FUNC_CIPHER_CIPHER:
+ if (cipher->ccipher != NULL)
+ break;
+ cipher->ccipher = OSSL_FUNC_cipher_cipher(fns);
+ break;
+ case OSSL_FUNC_CIPHER_FREECTX:
+ if (cipher->freectx != NULL)
+ break;
+ cipher->freectx = OSSL_FUNC_cipher_freectx(fns);
+ fnctxcnt++;
+ break;
+ case OSSL_FUNC_CIPHER_DUPCTX:
+ if (cipher->dupctx != NULL)
+ break;
+ cipher->dupctx = OSSL_FUNC_cipher_dupctx(fns);
+ break;
+ case OSSL_FUNC_CIPHER_GET_PARAMS:
+ if (cipher->get_params != NULL)
+ break;
+ cipher->get_params = OSSL_FUNC_cipher_get_params(fns);
+ break;
+ case OSSL_FUNC_CIPHER_GET_CTX_PARAMS:
+ if (cipher->get_ctx_params != NULL)
+ break;
+ cipher->get_ctx_params = OSSL_FUNC_cipher_get_ctx_params(fns);
+ break;
+ case OSSL_FUNC_CIPHER_SET_CTX_PARAMS:
+ if (cipher->set_ctx_params != NULL)
+ break;
+ cipher->set_ctx_params = OSSL_FUNC_cipher_set_ctx_params(fns);
+ break;
+ case OSSL_FUNC_CIPHER_GETTABLE_PARAMS:
+ if (cipher->gettable_params != NULL)
+ break;
+ cipher->gettable_params = OSSL_FUNC_cipher_gettable_params(fns);
+ break;
+ case OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS:
+ if (cipher->gettable_ctx_params != NULL)
+ break;
+ cipher->gettable_ctx_params =
+ OSSL_FUNC_cipher_gettable_ctx_params(fns);
+ break;
+ case OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS:
+ if (cipher->settable_ctx_params != NULL)
+ break;
+ cipher->settable_ctx_params =
+ OSSL_FUNC_cipher_settable_ctx_params(fns);
+ break;
+ }
+ }
+ if ((fnciphcnt != 0 && fnciphcnt != 3 && fnciphcnt != 4)
+ || (fnciphcnt == 0 && cipher->ccipher == NULL)
+ || fnctxcnt != 2) {
+ /*
+ * In order to be a consistent set of functions we must have at least
+ * a complete set of "encrypt" functions, or a complete set of "decrypt"
+ * functions, or a single "cipher" function. In all cases we need both
+ * the "newctx" and "freectx" functions.
+ */
+ EVP_CIPHER_free(cipher);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+ return NULL;
+ }
+ cipher->prov = prov;
+ if (prov != NULL)
+ ossl_provider_up_ref(prov);
+
+ if (!evp_cipher_cache_constants(cipher)) {
+ EVP_CIPHER_free(cipher);
+ ERR_raise(ERR_LIB_EVP, EVP_R_CACHE_CONSTANTS_FAILED);
+ cipher = NULL;
+ }
+
+ return cipher;
+}
+
+static int evp_cipher_up_ref(void *cipher)
+{
+ return EVP_CIPHER_up_ref(cipher);
+}
+
+static void evp_cipher_free(void *cipher)
+{
+ EVP_CIPHER_free(cipher);
+}
+
+EVP_CIPHER *EVP_CIPHER_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties)
+{
+ EVP_CIPHER *cipher =
+ evp_generic_fetch(ctx, OSSL_OP_CIPHER, algorithm, properties,
+ evp_cipher_from_algorithm, evp_cipher_up_ref,
+ evp_cipher_free);
+
+ return cipher;
+}
+
+int EVP_CIPHER_up_ref(EVP_CIPHER *cipher)
+{
+ int ref = 0;
+
+ if (cipher->origin == EVP_ORIG_DYNAMIC)
+ CRYPTO_UP_REF(&cipher->refcnt, &ref, cipher->lock);
+ return 1;
+}
+
+void evp_cipher_free_int(EVP_CIPHER *cipher)
+{
+ OPENSSL_free(cipher->type_name);
+ ossl_provider_free(cipher->prov);
+ CRYPTO_THREAD_lock_free(cipher->lock);
+ OPENSSL_free(cipher);
+}
+
+void EVP_CIPHER_free(EVP_CIPHER *cipher)
+{
+ int i;
+
+ if (cipher == NULL || cipher->origin != EVP_ORIG_DYNAMIC)
+ return;
+
+ CRYPTO_DOWN_REF(&cipher->refcnt, &i, cipher->lock);
+ if (i > 0)
+ return;
+ evp_cipher_free_int(cipher);
+}
+
+void EVP_CIPHER_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_CIPHER *mac, void *arg),
+ void *arg)
+{
+ evp_generic_do_all(libctx, OSSL_OP_CIPHER,
+ (void (*)(void *, void *))fn, arg,
+ evp_cipher_from_algorithm, evp_cipher_up_ref,
+ evp_cipher_free);
+}
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index 32ac0125de24..c0d92321032f 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -2,7 +2,7 @@
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,170 +10,35 @@
#include <openssl/err.h>
#include <openssl/evperr.h>
+#include "crypto/evperr.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA EVP_str_functs[] = {
- {ERR_PACK(ERR_LIB_EVP, EVP_F_AESNI_INIT_KEY, 0), "aesni_init_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_AESNI_XTS_INIT_KEY, 0), "aesni_xts_init_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_AES_GCM_CTRL, 0), "aes_gcm_ctrl"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_AES_INIT_KEY, 0), "aes_init_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_AES_OCB_CIPHER, 0), "aes_ocb_cipher"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_AES_T4_INIT_KEY, 0), "aes_t4_init_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_AES_T4_XTS_INIT_KEY, 0),
- "aes_t4_xts_init_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_AES_WRAP_CIPHER, 0), "aes_wrap_cipher"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_AES_XTS_INIT_KEY, 0), "aes_xts_init_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_ALG_MODULE_INIT, 0), "alg_module_init"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_ARIA_CCM_INIT_KEY, 0), "aria_ccm_init_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_ARIA_GCM_CTRL, 0), "aria_gcm_ctrl"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_ARIA_GCM_INIT_KEY, 0), "aria_gcm_init_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_ARIA_INIT_KEY, 0), "aria_init_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_B64_NEW, 0), "b64_new"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_CAMELLIA_INIT_KEY, 0), "camellia_init_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_CHACHA20_POLY1305_CTRL, 0),
- "chacha20_poly1305_ctrl"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_CMLL_T4_INIT_KEY, 0), "cmll_t4_init_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_DES_EDE3_WRAP_CIPHER, 0),
- "des_ede3_wrap_cipher"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_DO_SIGVER_INIT, 0), "do_sigver_init"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_ENC_NEW, 0), "enc_new"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHERINIT_EX, 0), "EVP_CipherInit_ex"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_ASN1_TO_PARAM, 0),
- "EVP_CIPHER_asn1_to_param"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_CTX_COPY, 0),
- "EVP_CIPHER_CTX_copy"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_CTX_CTRL, 0),
- "EVP_CIPHER_CTX_ctrl"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH, 0),
- "EVP_CIPHER_CTX_set_key_length"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_PARAM_TO_ASN1, 0),
- "EVP_CIPHER_param_to_asn1"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTFINAL_EX, 0),
- "EVP_DecryptFinal_ex"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTUPDATE, 0), "EVP_DecryptUpdate"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DIGESTFINALXOF, 0), "EVP_DigestFinalXOF"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DIGESTINIT_EX, 0), "EVP_DigestInit_ex"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTDECRYPTUPDATE, 0),
- "evp_EncryptDecryptUpdate"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTFINAL_EX, 0),
- "EVP_EncryptFinal_ex"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTUPDATE, 0), "EVP_EncryptUpdate"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MD_CTX_COPY_EX, 0), "EVP_MD_CTX_copy_ex"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MD_SIZE, 0), "EVP_MD_size"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_OPENINIT, 0), "EVP_OpenInit"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PBE_ALG_ADD, 0), "EVP_PBE_alg_add"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PBE_ALG_ADD_TYPE, 0),
- "EVP_PBE_alg_add_type"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PBE_CIPHERINIT, 0), "EVP_PBE_CipherInit"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PBE_SCRYPT, 0), "EVP_PBE_scrypt"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKCS82PKEY, 0), "EVP_PKCS82PKEY"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY2PKCS8, 0), "EVP_PKEY2PKCS8"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_ASN1_ADD0, 0), "EVP_PKEY_asn1_add0"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CHECK, 0), "EVP_PKEY_check"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_COPY_PARAMETERS, 0),
- "EVP_PKEY_copy_parameters"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_CTRL, 0), "EVP_PKEY_CTX_ctrl"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_CTRL_STR, 0),
- "EVP_PKEY_CTX_ctrl_str"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_DUP, 0), "EVP_PKEY_CTX_dup"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_MD, 0), "EVP_PKEY_CTX_md"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_DECRYPT, 0), "EVP_PKEY_decrypt"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_DECRYPT_INIT, 0),
- "EVP_PKEY_decrypt_init"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_DECRYPT_OLD, 0),
- "EVP_PKEY_decrypt_old"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_DERIVE, 0), "EVP_PKEY_derive"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_DERIVE_INIT, 0),
- "EVP_PKEY_derive_init"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_DERIVE_SET_PEER, 0),
- "EVP_PKEY_derive_set_peer"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_ENCRYPT, 0), "EVP_PKEY_encrypt"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_ENCRYPT_INIT, 0),
- "EVP_PKEY_encrypt_init"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_ENCRYPT_OLD, 0),
- "EVP_PKEY_encrypt_old"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET0_DH, 0), "EVP_PKEY_get0_DH"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET0_DSA, 0), "EVP_PKEY_get0_DSA"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET0_EC_KEY, 0),
- "EVP_PKEY_get0_EC_KEY"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET0_HMAC, 0), "EVP_PKEY_get0_hmac"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET0_POLY1305, 0),
- "EVP_PKEY_get0_poly1305"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET0_RSA, 0), "EVP_PKEY_get0_RSA"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET0_SIPHASH, 0),
- "EVP_PKEY_get0_siphash"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY, 0),
- "EVP_PKEY_get_raw_private_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY, 0),
- "EVP_PKEY_get_raw_public_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_KEYGEN, 0), "EVP_PKEY_keygen"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_KEYGEN_INIT, 0),
- "EVP_PKEY_keygen_init"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_METH_ADD0, 0), "EVP_PKEY_meth_add0"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_METH_NEW, 0), "EVP_PKEY_meth_new"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_NEW, 0), "EVP_PKEY_new"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_NEW_CMAC_KEY, 0),
- "EVP_PKEY_new_CMAC_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY, 0),
- "EVP_PKEY_new_raw_private_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY, 0),
- "EVP_PKEY_new_raw_public_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_PARAMGEN, 0), "EVP_PKEY_paramgen"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_PARAMGEN_INIT, 0),
- "EVP_PKEY_paramgen_init"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_PARAM_CHECK, 0),
- "EVP_PKEY_param_check"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_PUBLIC_CHECK, 0),
- "EVP_PKEY_public_check"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_SET1_ENGINE, 0),
- "EVP_PKEY_set1_engine"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_SET_ALIAS_TYPE, 0),
- "EVP_PKEY_set_alias_type"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_SIGN, 0), "EVP_PKEY_sign"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_SIGN_INIT, 0), "EVP_PKEY_sign_init"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_VERIFY, 0), "EVP_PKEY_verify"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_VERIFY_INIT, 0),
- "EVP_PKEY_verify_init"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_VERIFY_RECOVER, 0),
- "EVP_PKEY_verify_recover"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT, 0),
- "EVP_PKEY_verify_recover_init"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_SIGNFINAL, 0), "EVP_SignFinal"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_VERIFYFINAL, 0), "EVP_VerifyFinal"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_INT_CTX_NEW, 0), "int_ctx_new"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_OK_NEW, 0), "ok_new"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_PBE_KEYIVGEN, 0), "PKCS5_PBE_keyivgen"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_V2_PBE_KEYIVGEN, 0),
- "PKCS5_v2_PBE_keyivgen"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, 0),
- "PKCS5_v2_PBKDF2_keyivgen"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, 0),
- "PKCS5_v2_scrypt_keyivgen"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_SET_TYPE, 0), "pkey_set_type"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_RC2_MAGIC_TO_METH, 0), "rc2_magic_to_meth"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_RC5_CTRL, 0), "rc5_ctrl"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_R_32_12_16_INIT_KEY, 0),
- "r_32_12_16_init_key"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_S390X_AES_GCM_CTRL, 0), "s390x_aes_gcm_ctrl"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_UPDATE, 0), "update"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA EVP_str_reasons[] = {
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_AES_KEY_SETUP_FAILED),
"aes key setup failed"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ARIA_KEY_SETUP_FAILED),
"aria key setup failed"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BAD_ALGORITHM_NAME), "bad algorithm name"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BAD_DECRYPT), "bad decrypt"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BAD_KEY_LENGTH), "bad key length"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BUFFER_TOO_SMALL), "buffer too small"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CACHE_CONSTANTS_FAILED),
+ "cache constants failed"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CAMELLIA_KEY_SETUP_FAILED),
"camellia key setup failed"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CANNOT_GET_PARAMETERS),
+ "cannot get parameters"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CANNOT_SET_PARAMETERS),
+ "cannot set parameters"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CIPHER_NOT_GCM_MODE),
+ "cipher not gcm mode"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CIPHER_PARAMETER_ERROR),
"cipher parameter error"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_COMMAND_NOT_SUPPORTED),
"command not supported"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CONFLICTING_ALGORITHM_NAME),
+ "conflicting algorithm name"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_COPY_ERROR), "copy error"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CTRL_NOT_IMPLEMENTED),
"ctrl not implemented"},
@@ -182,14 +47,14 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH),
"data not multiple of block length"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DECODE_ERROR), "decode error"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DEFAULT_QUERY_PARSE_ERROR),
+ "default query parse error"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIFFERENT_KEY_TYPES),
"different key types"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIFFERENT_PARAMETERS),
"different parameters"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ERROR_LOADING_SECTION),
"error loading section"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ERROR_SETTING_FIPS_MODE),
- "error setting fips mode"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_HMAC_KEY),
"expecting an hmac key"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_RSA_KEY),
@@ -197,28 +62,49 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_DH_KEY), "expecting a dh key"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_DSA_KEY),
"expecting a dsa key"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_EC_KEY), "expecting a ec key"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_ECX_KEY),
+ "expecting an ecx key"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_EC_KEY), "expecting an ec key"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_POLY1305_KEY),
"expecting a poly1305 key"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_SIPHASH_KEY),
"expecting a siphash key"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FIPS_MODE_NOT_SUPPORTED),
- "fips mode not supported"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FINAL_ERROR), "final error"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GENERATE_ERROR), "generate error"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GET_RAW_KEY_FAILED), "get raw key failed"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ILLEGAL_SCRYPT_PARAMETERS),
"illegal scrypt parameters"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS),
+ "inaccessible domain parameters"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INACCESSIBLE_KEY), "inaccessible key"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INITIALIZATION_ERROR),
"initialization error"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INPUT_NOT_INITIALIZED),
"input not initialized"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_CUSTOM_LENGTH),
+ "invalid custom length"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_DIGEST), "invalid digest"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_FIPS_MODE), "invalid fips mode"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_IV_LENGTH), "invalid iv length"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY), "invalid key"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY_LENGTH), "invalid key length"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_LENGTH), "invalid length"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_NULL_ALGORITHM),
+ "invalid null algorithm"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_OPERATION), "invalid operation"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYGEN_FAILURE), "keygen failure"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_PROVIDER_FUNCTIONS),
+ "invalid provider functions"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SALT_LENGTH),
+ "invalid salt length"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SECRET_LENGTH),
+ "invalid secret length"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SEED_LENGTH),
+ "invalid seed length"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_VALUE), "invalid value"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYMGMT_EXPORT_FAILURE),
+ "keymgmt export failure"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEY_SETUP_FAILED), "key setup failed"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_LOCKING_NOT_SUPPORTED),
+ "locking not supported"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MEMORY_LIMIT_EXCEEDED),
"memory limit exceeded"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MESSAGE_DIGEST_IS_NULL),
@@ -226,21 +112,30 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_METHOD_NOT_SUPPORTED),
"method not supported"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MISSING_PARAMETERS), "missing parameters"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NOT_ABLE_TO_COPY_CTX),
+ "not able to copy ctx"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NOT_XOF_OR_INVALID_LENGTH),
"not XOF or invalid length"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_CIPHER_SET), "no cipher set"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_DEFAULT_DIGEST), "no default digest"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_DIGEST_SET), "no digest set"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_IMPORT_FUNCTION), "no import function"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEYMGMT_AVAILABLE),
+ "no keymgmt available"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEYMGMT_PRESENT), "no keymgmt present"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEY_SET), "no key set"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_OPERATION_SET), "no operation set"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NULL_MAC_PKEY_CTX), "null mac pkey ctx"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ONLY_ONESHOT_SUPPORTED),
"only oneshot supported"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OPERATION_NOT_INITIALIZED),
+ "operation not initialized"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE),
"operation not supported for this keytype"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OPERATON_NOT_INITIALIZED),
- "operaton not initialized"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OUTPUT_WOULD_OVERFLOW),
"output would overflow"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PARAMETER_TOO_LARGE),
+ "parameter too large"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PARTIALLY_OVERLAPPING),
"partially overlapping buffers"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PBKDF2_ERROR), "pbkdf2 error"},
@@ -251,8 +146,23 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PRIVATE_KEY_ENCODE_ERROR),
"private key encode error"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PUBLIC_KEY_NOT_RSA), "public key not rsa"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_SETTING_XOF_FAILED), "setting xof failed"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_SET_DEFAULT_PROPERTY_FAILURE),
+ "set default property failure"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_TOO_MANY_RECORDS), "too many records"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNABLE_TO_ENABLE_LOCKING),
+ "unable to enable locking"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE),
+ "unable to get maximum request size"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNABLE_TO_GET_RANDOM_STRENGTH),
+ "unable to get random strength"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNABLE_TO_LOCK_CONTEXT),
+ "unable to lock context"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNABLE_TO_SET_CALLBACKS),
+ "unable to set callbacks"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_CIPHER), "unknown cipher"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_DIGEST), "unknown digest"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_KEY_TYPE), "unknown key type"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_OPTION), "unknown option"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_PBE_ALGORITHM),
"unknown pbe algorithm"},
@@ -265,6 +175,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
"unsupported key derivation function"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_KEY_SIZE),
"unsupported key size"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_KEY_TYPE),
+ "unsupported key type"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS),
"unsupported number of rounds"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_PRF), "unsupported prf"},
@@ -272,10 +184,13 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
"unsupported private key algorithm"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_SALT_TYPE),
"unsupported salt type"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UPDATE_ERROR), "update error"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_WRAP_MODE_NOT_ALLOWED),
"wrap mode not allowed"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_WRONG_FINAL_BLOCK_LENGTH),
"wrong final block length"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_XTS_DATA_UNIT_IS_TOO_LARGE),
+ "xts data unit is too large"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_XTS_DUPLICATED_KEYS),
"xts duplicated keys"},
{0, NULL}
@@ -283,13 +198,11 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
#endif
-int ERR_load_EVP_strings(void)
+int ossl_err_load_EVP_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(EVP_str_functs[0].error) == NULL) {
- ERR_load_strings_const(EVP_str_functs);
+ if (ERR_reason_error_string(EVP_str_reasons[0].error) == NULL)
ERR_load_strings_const(EVP_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c
new file mode 100644
index 000000000000..aafd927e63f9
--- /dev/null
+++ b/crypto/evp/evp_fetch.c
@@ -0,0 +1,690 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stddef.h>
+#include <openssl/types.h>
+#include <openssl/evp.h>
+#include <openssl/core.h>
+#include "internal/cryptlib.h"
+#include "internal/thread_once.h"
+#include "internal/property.h"
+#include "internal/core.h"
+#include "internal/provider.h"
+#include "internal/namemap.h"
+#include "internal/property.h"
+#include "crypto/evp.h" /* evp_local.h needs it */
+#include "evp_local.h"
+
+#define NAME_SEPARATOR ':'
+
+static void evp_method_store_free(void *vstore)
+{
+ ossl_method_store_free(vstore);
+}
+
+static void *evp_method_store_new(OSSL_LIB_CTX *ctx)
+{
+ return ossl_method_store_new(ctx);
+}
+
+
+static const OSSL_LIB_CTX_METHOD evp_method_store_method = {
+ /* We want evp_method_store to be cleaned up before the provider store */
+ OSSL_LIB_CTX_METHOD_PRIORITY_2,
+ evp_method_store_new,
+ evp_method_store_free,
+};
+
+/* Data to be passed through ossl_method_construct() */
+struct evp_method_data_st {
+ OSSL_LIB_CTX *libctx;
+ int operation_id; /* For get_evp_method_from_store() */
+ int name_id; /* For get_evp_method_from_store() */
+ const char *names; /* For get_evp_method_from_store() */
+ const char *propquery; /* For get_evp_method_from_store() */
+
+ OSSL_METHOD_STORE *tmp_store; /* For get_tmp_evp_method_store() */
+
+ unsigned int flag_construct_error_occurred : 1;
+
+ void *(*method_from_algorithm)(int name_id, const OSSL_ALGORITHM *,
+ OSSL_PROVIDER *);
+ int (*refcnt_up_method)(void *method);
+ void (*destruct_method)(void *method);
+};
+
+/*
+ * Generic routines to fetch / create EVP methods with ossl_method_construct()
+ */
+static void *get_tmp_evp_method_store(void *data)
+{
+ struct evp_method_data_st *methdata = data;
+
+ if (methdata->tmp_store == NULL)
+ methdata->tmp_store = ossl_method_store_new(methdata->libctx);
+ return methdata->tmp_store;
+}
+
+ static void dealloc_tmp_evp_method_store(void *store)
+{
+ if (store != NULL)
+ ossl_method_store_free(store);
+}
+
+static OSSL_METHOD_STORE *get_evp_method_store(OSSL_LIB_CTX *libctx)
+{
+ return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_EVP_METHOD_STORE_INDEX,
+ &evp_method_store_method);
+}
+
+static int reserve_evp_method_store(void *store, void *data)
+{
+ struct evp_method_data_st *methdata = data;
+
+ if (store == NULL
+ && (store = get_evp_method_store(methdata->libctx)) == NULL)
+ return 0;
+
+ return ossl_method_lock_store(store);
+}
+
+static int unreserve_evp_method_store(void *store, void *data)
+{
+ struct evp_method_data_st *methdata = data;
+
+ if (store == NULL
+ && (store = get_evp_method_store(methdata->libctx)) == NULL)
+ return 0;
+
+ return ossl_method_unlock_store(store);
+}
+
+/*
+ * To identify the method in the EVP method store, we mix the name identity
+ * with the operation identity, under the assumption that we don't have more
+ * than 2^23 names or more than 2^8 operation types.
+ *
+ * The resulting identity is a 31-bit integer, composed like this:
+ *
+ * +---------23 bits--------+-8 bits-+
+ * | name identity | op id |
+ * +------------------------+--------+
+ *
+ * We limit this composite number to 31 bits, thus leaving the top uint32_t
+ * bit always zero, to avoid negative sign extension when downshifting after
+ * this number happens to be passed to an int (which happens as soon as it's
+ * passed to ossl_method_store_cache_set(), and it's in that form that it
+ * gets passed along to filter_on_operation_id(), defined further down.
+ */
+#define METHOD_ID_OPERATION_MASK 0x000000FF
+#define METHOD_ID_OPERATION_MAX ((1 << 8) - 1)
+#define METHOD_ID_NAME_MASK 0x7FFFFF00
+#define METHOD_ID_NAME_OFFSET 8
+#define METHOD_ID_NAME_MAX ((1 << 23) - 1)
+static uint32_t evp_method_id(int name_id, unsigned int operation_id)
+{
+ if (!ossl_assert(name_id > 0 && name_id <= METHOD_ID_NAME_MAX)
+ || !ossl_assert(operation_id > 0
+ && operation_id <= METHOD_ID_OPERATION_MAX))
+ return 0;
+ return (((name_id << METHOD_ID_NAME_OFFSET) & METHOD_ID_NAME_MASK)
+ | (operation_id & METHOD_ID_OPERATION_MASK));
+}
+
+static void *get_evp_method_from_store(void *store, const OSSL_PROVIDER **prov,
+ void *data)
+{
+ struct evp_method_data_st *methdata = data;
+ void *method = NULL;
+ int name_id = 0;
+ uint32_t meth_id;
+
+ /*
+ * get_evp_method_from_store() is only called to try and get the method
+ * that evp_generic_fetch() is asking for, and the operation id as well
+ * as the name or name id are passed via methdata.
+ */
+ if ((name_id = methdata->name_id) == 0 && methdata->names != NULL) {
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
+ const char *names = methdata->names;
+ const char *q = strchr(names, NAME_SEPARATOR);
+ size_t l = (q == NULL ? strlen(names) : (size_t)(q - names));
+
+ if (namemap == 0)
+ return NULL;
+ name_id = ossl_namemap_name2num_n(namemap, names, l);
+ }
+
+ if (name_id == 0
+ || (meth_id = evp_method_id(name_id, methdata->operation_id)) == 0)
+ return NULL;
+
+ if (store == NULL
+ && (store = get_evp_method_store(methdata->libctx)) == NULL)
+ return NULL;
+
+ if (!ossl_method_store_fetch(store, meth_id, methdata->propquery, prov,
+ &method))
+ return NULL;
+ return method;
+}
+
+static int put_evp_method_in_store(void *store, void *method,
+ const OSSL_PROVIDER *prov,
+ const char *names, const char *propdef,
+ void *data)
+{
+ struct evp_method_data_st *methdata = data;
+ OSSL_NAMEMAP *namemap;
+ int name_id;
+ uint32_t meth_id;
+ size_t l = 0;
+
+ /*
+ * put_evp_method_in_store() is only called with an EVP method that was
+ * successfully created by construct_method() below, which means that
+ * all the names should already be stored in the namemap with the same
+ * numeric identity, so just use the first to get that identity.
+ */
+ if (names != NULL) {
+ const char *q = strchr(names, NAME_SEPARATOR);
+
+ l = (q == NULL ? strlen(names) : (size_t)(q - names));
+ }
+
+ if ((namemap = ossl_namemap_stored(methdata->libctx)) == NULL
+ || (name_id = ossl_namemap_name2num_n(namemap, names, l)) == 0
+ || (meth_id = evp_method_id(name_id, methdata->operation_id)) == 0)
+ return 0;
+
+ if (store == NULL
+ && (store = get_evp_method_store(methdata->libctx)) == NULL)
+ return 0;
+
+ return ossl_method_store_add(store, prov, meth_id, propdef, method,
+ methdata->refcnt_up_method,
+ methdata->destruct_method);
+}
+
+/*
+ * The core fetching functionality passes the name of the implementation.
+ * This function is responsible to getting an identity number for it.
+ */
+static void *construct_evp_method(const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov, void *data)
+{
+ /*
+ * This function is only called if get_evp_method_from_store() returned
+ * NULL, so it's safe to say that of all the spots to create a new
+ * namemap entry, this is it. Should the name already exist there, we
+ * know that ossl_namemap_add_name() will return its corresponding
+ * number.
+ */
+ struct evp_method_data_st *methdata = data;
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+ const char *names = algodef->algorithm_names;
+ int name_id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR);
+ void *method;
+
+ if (name_id == 0)
+ return NULL;
+
+ method = methdata->method_from_algorithm(name_id, algodef, prov);
+
+ /*
+ * Flag to indicate that there was actual construction errors. This
+ * helps inner_evp_generic_fetch() determine what error it should
+ * record on inaccessible algorithms.
+ */
+ if (method == NULL)
+ methdata->flag_construct_error_occurred = 1;
+
+ return method;
+}
+
+static void destruct_evp_method(void *method, void *data)
+{
+ struct evp_method_data_st *methdata = data;
+
+ methdata->destruct_method(method);
+}
+
+static void *
+inner_evp_generic_fetch(struct evp_method_data_st *methdata,
+ OSSL_PROVIDER *prov, int operation_id,
+ int name_id, const char *name,
+ const char *properties,
+ void *(*new_method)(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov),
+ int (*up_ref_method)(void *),
+ void (*free_method)(void *))
+{
+ OSSL_METHOD_STORE *store = get_evp_method_store(methdata->libctx);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
+ const char *const propq = properties != NULL ? properties : "";
+ uint32_t meth_id = 0;
+ void *method = NULL;
+ int unsupported = 0;
+
+ if (store == NULL || namemap == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return NULL;
+ }
+
+ /*
+ * If there's ever an operation_id == 0 passed, we have an internal
+ * programming error.
+ */
+ if (!ossl_assert(operation_id > 0)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ /*
+ * If we have been passed both a name_id and a name, we have an
+ * internal programming error.
+ */
+ if (!ossl_assert(name_id == 0 || name == NULL)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ /* If we haven't received a name id yet, try to get one for the name */
+ if (name_id == 0 && name != NULL)
+ name_id = ossl_namemap_name2num(namemap, name);
+
+ /*
+ * If we have a name id, calculate a method id with evp_method_id().
+ *
+ * evp_method_id returns 0 if we have too many operations (more than
+ * about 2^8) or too many names (more than about 2^24). In that case,
+ * we can't create any new method.
+ * For all intents and purposes, this is an internal error.
+ */
+ if (name_id != 0 && (meth_id = evp_method_id(name_id, operation_id)) == 0) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ /*
+ * If we haven't found the name yet, chances are that the algorithm to
+ * be fetched is unsupported.
+ */
+ if (name_id == 0)
+ unsupported = 1;
+
+ if (meth_id == 0
+ || !ossl_method_store_cache_get(store, prov, meth_id, propq, &method)) {
+ OSSL_METHOD_CONSTRUCT_METHOD mcm = {
+ get_tmp_evp_method_store,
+ reserve_evp_method_store,
+ unreserve_evp_method_store,
+ get_evp_method_from_store,
+ put_evp_method_in_store,
+ construct_evp_method,
+ destruct_evp_method
+ };
+
+ methdata->operation_id = operation_id;
+ methdata->name_id = name_id;
+ methdata->names = name;
+ methdata->propquery = propq;
+ methdata->method_from_algorithm = new_method;
+ methdata->refcnt_up_method = up_ref_method;
+ methdata->destruct_method = free_method;
+ methdata->flag_construct_error_occurred = 0;
+ if ((method = ossl_method_construct(methdata->libctx, operation_id,
+ &prov, 0 /* !force_cache */,
+ &mcm, methdata)) != NULL) {
+ /*
+ * If construction did create a method for us, we know that
+ * there is a correct name_id and meth_id, since those have
+ * already been calculated in get_evp_method_from_store() and
+ * put_evp_method_in_store() above.
+ */
+ if (name_id == 0)
+ name_id = ossl_namemap_name2num(namemap, name);
+ meth_id = evp_method_id(name_id, operation_id);
+ if (name_id != 0)
+ ossl_method_store_cache_set(store, prov, meth_id, propq,
+ method, up_ref_method, free_method);
+ }
+
+ /*
+ * If we never were in the constructor, the algorithm to be fetched
+ * is unsupported.
+ */
+ unsupported = !methdata->flag_construct_error_occurred;
+ }
+
+ if ((name_id != 0 || name != NULL) && method == NULL) {
+ int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED;
+
+ if (name == NULL)
+ name = ossl_namemap_num2name(namemap, name_id, 0);
+ ERR_raise_data(ERR_LIB_EVP, code,
+ "%s, Algorithm (%s : %d), Properties (%s)",
+ ossl_lib_ctx_get_descriptor(methdata->libctx),
+ name == NULL ? "<null>" : name, name_id,
+ properties == NULL ? "<null>" : properties);
+ }
+
+ return method;
+}
+
+void *evp_generic_fetch(OSSL_LIB_CTX *libctx, int operation_id,
+ const char *name, const char *properties,
+ void *(*new_method)(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov),
+ int (*up_ref_method)(void *),
+ void (*free_method)(void *))
+{
+ struct evp_method_data_st methdata;
+ void *method;
+
+ methdata.libctx = libctx;
+ methdata.tmp_store = NULL;
+ method = inner_evp_generic_fetch(&methdata, NULL, operation_id,
+ 0, name, properties,
+ new_method, up_ref_method, free_method);
+ dealloc_tmp_evp_method_store(methdata.tmp_store);
+ return method;
+}
+
+/*
+ * evp_generic_fetch_by_number() is special, and only returns methods for
+ * already known names, i.e. it refuses to work if no name_id can be found
+ * (it's considered an internal programming error).
+ * This is meant to be used when one method needs to fetch an associated
+ * method.
+ */
+void *evp_generic_fetch_by_number(OSSL_LIB_CTX *libctx, int operation_id,
+ int name_id, const char *properties,
+ void *(*new_method)(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov),
+ int (*up_ref_method)(void *),
+ void (*free_method)(void *))
+{
+ struct evp_method_data_st methdata;
+ void *method;
+
+ methdata.libctx = libctx;
+ methdata.tmp_store = NULL;
+ method = inner_evp_generic_fetch(&methdata, NULL, operation_id,
+ name_id, NULL, properties,
+ new_method, up_ref_method, free_method);
+ dealloc_tmp_evp_method_store(methdata.tmp_store);
+ return method;
+}
+
+/*
+ * evp_generic_fetch_from_prov() is special, and only returns methods from
+ * the given provider.
+ * This is meant to be used when one method needs to fetch an associated
+ * method.
+ */
+void *evp_generic_fetch_from_prov(OSSL_PROVIDER *prov, int operation_id,
+ const char *name, const char *properties,
+ void *(*new_method)(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov),
+ int (*up_ref_method)(void *),
+ void (*free_method)(void *))
+{
+ struct evp_method_data_st methdata;
+ void *method;
+
+ methdata.libctx = ossl_provider_libctx(prov);
+ methdata.tmp_store = NULL;
+ method = inner_evp_generic_fetch(&methdata, prov, operation_id,
+ 0, name, properties,
+ new_method, up_ref_method, free_method);
+ dealloc_tmp_evp_method_store(methdata.tmp_store);
+ return method;
+}
+
+int evp_method_store_cache_flush(OSSL_LIB_CTX *libctx)
+{
+ OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
+
+ if (store != NULL)
+ return ossl_method_store_cache_flush_all(store);
+ return 1;
+}
+
+int evp_method_store_remove_all_provided(const OSSL_PROVIDER *prov)
+{
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
+ OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
+
+ if (store != NULL)
+ return ossl_method_store_remove_all_provided(store, prov);
+ return 1;
+}
+
+static int evp_set_parsed_default_properties(OSSL_LIB_CTX *libctx,
+ OSSL_PROPERTY_LIST *def_prop,
+ int loadconfig,
+ int mirrored)
+{
+ OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
+ OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, loadconfig);
+
+ if (plp != NULL && store != NULL) {
+#ifndef FIPS_MODULE
+ char *propstr = NULL;
+ size_t strsz;
+
+ if (mirrored) {
+ if (ossl_global_properties_no_mirrored(libctx))
+ return 0;
+ } else {
+ /*
+ * These properties have been explicitly set on this libctx, so
+ * don't allow any mirroring from a parent libctx.
+ */
+ ossl_global_properties_stop_mirroring(libctx);
+ }
+
+ strsz = ossl_property_list_to_string(libctx, def_prop, NULL, 0);
+ if (strsz > 0)
+ propstr = OPENSSL_malloc(strsz);
+ if (propstr == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ if (ossl_property_list_to_string(libctx, def_prop, propstr,
+ strsz) == 0) {
+ OPENSSL_free(propstr);
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ ossl_provider_default_props_update(libctx, propstr);
+ OPENSSL_free(propstr);
+#endif
+ ossl_property_free(*plp);
+ *plp = def_prop;
+ if (store != NULL)
+ return ossl_method_store_cache_flush_all(store);
+ }
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return 0;
+}
+
+int evp_set_default_properties_int(OSSL_LIB_CTX *libctx, const char *propq,
+ int loadconfig, int mirrored)
+{
+ OSSL_PROPERTY_LIST *pl = NULL;
+
+ if (propq != NULL && (pl = ossl_parse_query(libctx, propq, 1)) == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_DEFAULT_QUERY_PARSE_ERROR);
+ return 0;
+ }
+ if (!evp_set_parsed_default_properties(libctx, pl, loadconfig, mirrored)) {
+ ossl_property_free(pl);
+ return 0;
+ }
+ return 1;
+}
+
+int EVP_set_default_properties(OSSL_LIB_CTX *libctx, const char *propq)
+{
+ return evp_set_default_properties_int(libctx, propq, 1, 0);
+}
+
+static int evp_default_properties_merge(OSSL_LIB_CTX *libctx, const char *propq,
+ int loadconfig)
+{
+ OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, loadconfig);
+ OSSL_PROPERTY_LIST *pl1, *pl2;
+
+ if (propq == NULL)
+ return 1;
+ if (plp == NULL || *plp == NULL)
+ return evp_set_default_properties_int(libctx, propq, 0, 0);
+ if ((pl1 = ossl_parse_query(libctx, propq, 1)) == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_DEFAULT_QUERY_PARSE_ERROR);
+ return 0;
+ }
+ pl2 = ossl_property_merge(pl1, *plp);
+ ossl_property_free(pl1);
+ if (pl2 == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (!evp_set_parsed_default_properties(libctx, pl2, 0, 0)) {
+ ossl_property_free(pl2);
+ return 0;
+ }
+ return 1;
+}
+
+static int evp_default_property_is_enabled(OSSL_LIB_CTX *libctx,
+ const char *prop_name)
+{
+ OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, 1);
+
+ return plp != NULL && ossl_property_is_enabled(libctx, prop_name, *plp);
+}
+
+int EVP_default_properties_is_fips_enabled(OSSL_LIB_CTX *libctx)
+{
+ return evp_default_property_is_enabled(libctx, "fips");
+}
+
+int evp_default_properties_enable_fips_int(OSSL_LIB_CTX *libctx, int enable,
+ int loadconfig)
+{
+ const char *query = (enable != 0) ? "fips=yes" : "-fips";
+
+ return evp_default_properties_merge(libctx, query, loadconfig);
+}
+
+int EVP_default_properties_enable_fips(OSSL_LIB_CTX *libctx, int enable)
+{
+ return evp_default_properties_enable_fips_int(libctx, enable, 1);
+}
+
+char *evp_get_global_properties_str(OSSL_LIB_CTX *libctx, int loadconfig)
+{
+ OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, loadconfig);
+ char *propstr = NULL;
+ size_t sz;
+
+ if (plp == NULL)
+ return OPENSSL_strdup("");
+
+ sz = ossl_property_list_to_string(libctx, *plp, NULL, 0);
+ if (sz == 0) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ propstr = OPENSSL_malloc(sz);
+ if (propstr == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ if (ossl_property_list_to_string(libctx, *plp, propstr, sz) == 0) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ OPENSSL_free(propstr);
+ return NULL;
+ }
+ return propstr;
+}
+
+struct filter_data_st {
+ int operation_id;
+ void (*user_fn)(void *method, void *arg);
+ void *user_arg;
+};
+
+static void filter_on_operation_id(int id, void *method, void *arg)
+{
+ struct filter_data_st *data = arg;
+
+ if ((id & METHOD_ID_OPERATION_MASK) == data->operation_id)
+ data->user_fn(method, data->user_arg);
+}
+
+void evp_generic_do_all(OSSL_LIB_CTX *libctx, int operation_id,
+ void (*user_fn)(void *method, void *arg),
+ void *user_arg,
+ void *(*new_method)(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov),
+ int (*up_ref_method)(void *),
+ void (*free_method)(void *))
+{
+ struct evp_method_data_st methdata;
+ struct filter_data_st data;
+
+ methdata.libctx = libctx;
+ methdata.tmp_store = NULL;
+ (void)inner_evp_generic_fetch(&methdata, NULL, operation_id, 0, NULL, NULL,
+ new_method, up_ref_method, free_method);
+
+ data.operation_id = operation_id;
+ data.user_fn = user_fn;
+ data.user_arg = user_arg;
+ if (methdata.tmp_store != NULL)
+ ossl_method_store_do_all(methdata.tmp_store, &filter_on_operation_id,
+ &data);
+ ossl_method_store_do_all(get_evp_method_store(libctx),
+ &filter_on_operation_id, &data);
+ dealloc_tmp_evp_method_store(methdata.tmp_store);
+}
+
+int evp_is_a(OSSL_PROVIDER *prov, int number,
+ const char *legacy_name, const char *name)
+{
+ /*
+ * For a |prov| that is NULL, the library context will be NULL
+ */
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+
+ if (prov == NULL)
+ number = ossl_namemap_name2num(namemap, legacy_name);
+ return ossl_namemap_name2num(namemap, name) == number;
+}
+
+int evp_names_do_all(OSSL_PROVIDER *prov, int number,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+
+ return ossl_namemap_doall_names(namemap, number, fn, data);
+}
diff --git a/crypto/evp/evp_key.c b/crypto/evp/evp_key.c
index e5ac107c385c..607d45ee2340 100644
--- a/crypto/evp/evp_key.c
+++ b/crypto/evp/evp_key.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -14,6 +14,10 @@
#include <openssl/evp.h>
#include <openssl/ui.h>
+#ifndef BUFSIZ
+# define BUFSIZ 256
+#endif
+
/* should be init to zeros. */
static char prompt_string[80];
@@ -81,8 +85,8 @@ int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
int niv, nkey, addmd = 0;
unsigned int mds = 0, i;
int rv = 0;
- nkey = EVP_CIPHER_key_length(type);
- niv = EVP_CIPHER_iv_length(type);
+ nkey = EVP_CIPHER_get_key_length(type);
+ niv = EVP_CIPHER_get_iv_length(type);
OPENSSL_assert(nkey <= EVP_MAX_KEY_LENGTH);
OPENSSL_assert(niv <= EVP_MAX_IV_LENGTH);
@@ -142,7 +146,7 @@ int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
if ((nkey == 0) && (niv == 0))
break;
}
- rv = EVP_CIPHER_key_length(type);
+ rv = EVP_CIPHER_get_key_length(type);
err:
EVP_MD_CTX_free(c);
OPENSSL_cleanse(md_buf, sizeof(md_buf));
diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c
index 45cde0da8bfc..4f3d901eba5d 100644
--- a/crypto/evp/evp_lib.c
+++ b/crypto/evp/evp_lib.c
@@ -1,34 +1,118 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * EVP _meth_ APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
+#include <string.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/objects.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
+#include <openssl/rsa.h>
+#include <openssl/dh.h>
+#include <openssl/ec.h>
#include "crypto/evp.h"
+#include "crypto/cryptlib.h"
+#include "internal/provider.h"
#include "evp_local.h"
+#if !defined(FIPS_MODULE)
+# include "crypto/asn1.h"
+
int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
{
- int ret;
+ return evp_cipher_param_to_asn1_ex(c, type, NULL);
+}
+
+int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
+{
+ return evp_cipher_asn1_to_param_ex(c, type, NULL);
+}
+
+int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *ctx, ASN1_TYPE *type)
+{
+ int i = 0;
+ unsigned int l;
+
+ if (type != NULL) {
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+
+ l = EVP_CIPHER_CTX_get_iv_length(ctx);
+ if (!ossl_assert(l <= sizeof(iv)))
+ return -1;
+ i = ASN1_TYPE_get_octetstring(type, iv, l);
+ if (i != (int)l)
+ return -1;
+
+ if (!EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1))
+ return -1;
+ }
+ return i;
+}
+
+int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
+{
+ int i = 0;
+ unsigned int j;
+ unsigned char *oiv = NULL;
- if (c->cipher->set_asn1_parameters != NULL)
- ret = c->cipher->set_asn1_parameters(c, type);
- else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) {
- switch (EVP_CIPHER_CTX_mode(c)) {
+ if (type != NULL) {
+ oiv = (unsigned char *)EVP_CIPHER_CTX_original_iv(c);
+ j = EVP_CIPHER_CTX_get_iv_length(c);
+ OPENSSL_assert(j <= sizeof(c->iv));
+ i = ASN1_TYPE_set_octetstring(type, oiv, j);
+ }
+ return i;
+}
+
+int evp_cipher_param_to_asn1_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
+ evp_cipher_aead_asn1_params *asn1_params)
+{
+ int ret = -1; /* Assume the worst */
+ const EVP_CIPHER *cipher = c->cipher;
+
+ /*
+ * For legacy implementations, we detect custom AlgorithmIdentifier
+ * parameter handling by checking if the function pointer
+ * cipher->set_asn1_parameters is set. We know that this pointer
+ * is NULL for provided implementations.
+ *
+ * Otherwise, for any implementation, we check the flag
+ * EVP_CIPH_FLAG_CUSTOM_ASN1. If it isn't set, we apply
+ * default AI parameter extraction.
+ *
+ * Otherwise, for provided implementations, we convert |type| to
+ * a DER encoded blob and pass to the implementation in OSSL_PARAM
+ * form.
+ *
+ * If none of the above applies, this operation is unsupported.
+ */
+ if (cipher->set_asn1_parameters != NULL) {
+ ret = cipher->set_asn1_parameters(c, type);
+ } else if ((EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_CUSTOM_ASN1) == 0) {
+ switch (EVP_CIPHER_get_mode(cipher)) {
case EVP_CIPH_WRAP_MODE:
- if (EVP_CIPHER_CTX_nid(c) == NID_id_smime_alg_CMS3DESwrap)
+ if (EVP_CIPHER_is_a(cipher, SN_id_smime_alg_CMS3DESwrap))
ASN1_TYPE_set(type, V_ASN1_NULL, NULL);
ret = 1;
break;
case EVP_CIPH_GCM_MODE:
+ ret = evp_cipher_set_asn1_aead_params(c, type, asn1_params);
+ break;
+
case EVP_CIPH_CCM_MODE:
case EVP_CIPH_XTS_MODE:
case EVP_CIPH_OCB_MODE:
@@ -38,31 +122,86 @@ int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
default:
ret = EVP_CIPHER_set_asn1_iv(c, type);
}
- } else
- ret = -1;
- if (ret <= 0)
- EVPerr(EVP_F_EVP_CIPHER_PARAM_TO_ASN1, ret == -2 ?
- ASN1_R_UNSUPPORTED_CIPHER :
- EVP_R_CIPHER_PARAMETER_ERROR);
+ } else if (cipher->prov != NULL) {
+ OSSL_PARAM params[3], *p = params;
+ unsigned char *der = NULL, *derp;
+
+ /*
+ * We make two passes, the first to get the appropriate buffer size,
+ * and the second to get the actual value.
+ */
+ *p++ = OSSL_PARAM_construct_octet_string(
+ OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS,
+ NULL, 0);
+ *p = OSSL_PARAM_construct_end();
+
+ if (!EVP_CIPHER_CTX_get_params(c, params))
+ goto err;
+
+ /* ... but, we should get a return size too! */
+ if (OSSL_PARAM_modified(params)
+ && params[0].return_size != 0
+ && (der = OPENSSL_malloc(params[0].return_size)) != NULL) {
+ params[0].data = der;
+ params[0].data_size = params[0].return_size;
+ OSSL_PARAM_set_all_unmodified(params);
+ derp = der;
+ if (EVP_CIPHER_CTX_get_params(c, params)
+ && OSSL_PARAM_modified(params)
+ && d2i_ASN1_TYPE(&type, (const unsigned char **)&derp,
+ params[0].return_size) != NULL) {
+ ret = 1;
+ }
+ OPENSSL_free(der);
+ }
+ } else {
+ ret = -2;
+ }
+
+ err:
+ if (ret == -2)
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_CIPHER);
+ else if (ret <= 0)
+ ERR_raise(ERR_LIB_EVP, EVP_R_CIPHER_PARAMETER_ERROR);
if (ret < -1)
ret = -1;
return ret;
}
-int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
+int evp_cipher_asn1_to_param_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
+ evp_cipher_aead_asn1_params *asn1_params)
{
- int ret;
-
- if (c->cipher->get_asn1_parameters != NULL)
- ret = c->cipher->get_asn1_parameters(c, type);
- else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) {
- switch (EVP_CIPHER_CTX_mode(c)) {
+ int ret = -1; /* Assume the worst */
+ const EVP_CIPHER *cipher = c->cipher;
+ /*
+ * For legacy implementations, we detect custom AlgorithmIdentifier
+ * parameter handling by checking if there the function pointer
+ * cipher->get_asn1_parameters is set. We know that this pointer
+ * is NULL for provided implementations.
+ *
+ * Otherwise, for any implementation, we check the flag
+ * EVP_CIPH_FLAG_CUSTOM_ASN1. If it isn't set, we apply
+ * default AI parameter creation.
+ *
+ * Otherwise, for provided implementations, we get the AI parameter
+ * in DER encoded form from the implementation by requesting the
+ * appropriate OSSL_PARAM and converting the result to a ASN1_TYPE.
+ *
+ * If none of the above applies, this operation is unsupported.
+ */
+ if (cipher->get_asn1_parameters != NULL) {
+ ret = cipher->get_asn1_parameters(c, type);
+ } else if ((EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_CUSTOM_ASN1) == 0) {
+ switch (EVP_CIPHER_get_mode(cipher)) {
case EVP_CIPH_WRAP_MODE:
ret = 1;
break;
case EVP_CIPH_GCM_MODE:
+ ret = evp_cipher_get_asn1_aead_params(c, type, asn1_params);
+ break;
+
case EVP_CIPH_CCM_MODE:
case EVP_CIPH_XTS_MODE:
case EVP_CIPH_OCB_MODE:
@@ -70,56 +209,74 @@ int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
break;
default:
- ret = EVP_CIPHER_get_asn1_iv(c, type);
- break;
+ ret = EVP_CIPHER_get_asn1_iv(c, type) >= 0 ? 1 : -1;
}
- } else
- ret = -1;
- if (ret <= 0)
- EVPerr(EVP_F_EVP_CIPHER_ASN1_TO_PARAM, ret == -2 ?
- EVP_R_UNSUPPORTED_CIPHER :
- EVP_R_CIPHER_PARAMETER_ERROR);
+ } else if (cipher->prov != NULL) {
+ OSSL_PARAM params[3], *p = params;
+ unsigned char *der = NULL;
+ int derl = -1;
+
+ if ((derl = i2d_ASN1_TYPE(type, &der)) >= 0) {
+ *p++ =
+ OSSL_PARAM_construct_octet_string(
+ OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS,
+ der, (size_t)derl);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_CIPHER_CTX_set_params(c, params))
+ ret = 1;
+ OPENSSL_free(der);
+ }
+ } else {
+ ret = -2;
+ }
+
+ if (ret == -2)
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_CIPHER);
+ else if (ret <= 0)
+ ERR_raise(ERR_LIB_EVP, EVP_R_CIPHER_PARAMETER_ERROR);
if (ret < -1)
ret = -1;
return ret;
}
-int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
+int evp_cipher_get_asn1_aead_params(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
+ evp_cipher_aead_asn1_params *asn1_params)
{
int i = 0;
- unsigned int l;
+ long tl;
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+
+ if (type == NULL || asn1_params == NULL)
+ return 0;
+
+ i = ossl_asn1_type_get_octetstring_int(type, &tl, NULL, EVP_MAX_IV_LENGTH);
+ if (i <= 0)
+ return -1;
+ ossl_asn1_type_get_octetstring_int(type, &tl, iv, i);
+
+ memcpy(asn1_params->iv, iv, i);
+ asn1_params->iv_len = i;
- if (type != NULL) {
- l = EVP_CIPHER_CTX_iv_length(c);
- OPENSSL_assert(l <= sizeof(c->iv));
- i = ASN1_TYPE_get_octetstring(type, c->oiv, l);
- if (i != (int)l)
- return -1;
- else if (i > 0)
- memcpy(c->iv, c->oiv, l);
- }
return i;
}
-int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
+int evp_cipher_set_asn1_aead_params(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
+ evp_cipher_aead_asn1_params *asn1_params)
{
- int i = 0;
- unsigned int j;
+ if (type == NULL || asn1_params == NULL)
+ return 0;
- if (type != NULL) {
- j = EVP_CIPHER_CTX_iv_length(c);
- OPENSSL_assert(j <= sizeof(c->iv));
- i = ASN1_TYPE_set_octetstring(type, c->oiv, j);
- }
- return i;
+ return ossl_asn1_type_set_octetstring_int(type, asn1_params->tag_len,
+ asn1_params->iv,
+ asn1_params->iv_len);
}
+#endif /* !defined(FIPS_MODULE) */
/* Convert the various cipher NIDs and dummies to a proper OID NID */
-int EVP_CIPHER_type(const EVP_CIPHER *ctx)
+int EVP_CIPHER_get_type(const EVP_CIPHER *cipher)
{
int nid;
- ASN1_OBJECT *otmp;
- nid = EVP_CIPHER_nid(ctx);
+ nid = EVP_CIPHER_get_nid(cipher);
switch (nid) {
@@ -165,23 +322,77 @@ int EVP_CIPHER_type(const EVP_CIPHER *ctx)
return NID_des_cfb64;
default:
- /* Check it has an OID and it is valid */
- otmp = OBJ_nid2obj(nid);
- if (OBJ_get0_data(otmp) == NULL)
- nid = NID_undef;
- ASN1_OBJECT_free(otmp);
- return nid;
+#ifdef FIPS_MODULE
+ return NID_undef;
+#else
+ {
+ /* Check it has an OID and it is valid */
+ ASN1_OBJECT *otmp = OBJ_nid2obj(nid);
+
+ if (OBJ_get0_data(otmp) == NULL)
+ nid = NID_undef;
+ ASN1_OBJECT_free(otmp);
+ return nid;
+ }
+#endif
+ }
+}
+
+int evp_cipher_cache_constants(EVP_CIPHER *cipher)
+{
+ int ok, aead = 0, custom_iv = 0, cts = 0, multiblock = 0, randkey = 0;
+ size_t ivlen = 0;
+ size_t blksz = 0;
+ size_t keylen = 0;
+ unsigned int mode = 0;
+ OSSL_PARAM params[10];
+
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_BLOCK_SIZE, &blksz);
+ params[1] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN, &ivlen);
+ params[2] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &keylen);
+ params[3] = OSSL_PARAM_construct_uint(OSSL_CIPHER_PARAM_MODE, &mode);
+ params[4] = OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_AEAD, &aead);
+ params[5] = OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_CUSTOM_IV,
+ &custom_iv);
+ params[6] = OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_CTS, &cts);
+ params[7] = OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK,
+ &multiblock);
+ params[8] = OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_HAS_RAND_KEY,
+ &randkey);
+ params[9] = OSSL_PARAM_construct_end();
+ ok = evp_do_ciph_getparams(cipher, params) > 0;
+ if (ok) {
+ cipher->block_size = blksz;
+ cipher->iv_len = ivlen;
+ cipher->key_len = keylen;
+ cipher->flags = mode;
+ if (aead)
+ cipher->flags |= EVP_CIPH_FLAG_AEAD_CIPHER;
+ if (custom_iv)
+ cipher->flags |= EVP_CIPH_CUSTOM_IV;
+ if (cts)
+ cipher->flags |= EVP_CIPH_FLAG_CTS;
+ if (multiblock)
+ cipher->flags |= EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK;
+ if (cipher->ccipher != NULL)
+ cipher->flags |= EVP_CIPH_FLAG_CUSTOM_CIPHER;
+ if (randkey)
+ cipher->flags |= EVP_CIPH_RAND_KEY;
+ if (OSSL_PARAM_locate_const(EVP_CIPHER_gettable_ctx_params(cipher),
+ OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS))
+ cipher->flags |= EVP_CIPH_FLAG_CUSTOM_ASN1;
}
+ return ok;
}
-int EVP_CIPHER_block_size(const EVP_CIPHER *e)
+int EVP_CIPHER_get_block_size(const EVP_CIPHER *cipher)
{
- return e->block_size;
+ return cipher->block_size;
}
-int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx)
+int EVP_CIPHER_CTX_get_block_size(const EVP_CIPHER_CTX *ctx)
{
- return ctx->cipher->block_size;
+ return EVP_CIPHER_get_block_size(ctx->cipher);
}
int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *e)
@@ -192,20 +403,71 @@ int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *e)
int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, unsigned int inl)
{
+ if (ctx->cipher->prov != NULL) {
+ /*
+ * If the provided implementation has a ccipher function, we use it,
+ * and translate its return value like this: 0 => -1, 1 => outlen
+ *
+ * Otherwise, we call the cupdate function if in != NULL, or cfinal
+ * if in == NULL. Regardless of which, we return what we got.
+ */
+ int ret = -1;
+ size_t outl = 0;
+ size_t blocksize = EVP_CIPHER_CTX_get_block_size(ctx);
+
+ if (ctx->cipher->ccipher != NULL)
+ ret = ctx->cipher->ccipher(ctx->algctx, out, &outl,
+ inl + (blocksize == 1 ? 0 : blocksize),
+ in, (size_t)inl)
+ ? (int)outl : -1;
+ else if (in != NULL)
+ ret = ctx->cipher->cupdate(ctx->algctx, out, &outl,
+ inl + (blocksize == 1 ? 0 : blocksize),
+ in, (size_t)inl);
+ else
+ ret = ctx->cipher->cfinal(ctx->algctx, out, &outl,
+ blocksize == 1 ? 0 : blocksize);
+
+ return ret;
+ }
+
return ctx->cipher->do_cipher(ctx, out, in, inl);
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx)
{
+ if (ctx == NULL)
+ return NULL;
return ctx->cipher;
}
+#endif
+
+const EVP_CIPHER *EVP_CIPHER_CTX_get0_cipher(const EVP_CIPHER_CTX *ctx)
+{
+ if (ctx == NULL)
+ return NULL;
+ return ctx->cipher;
+}
+
+EVP_CIPHER *EVP_CIPHER_CTX_get1_cipher(EVP_CIPHER_CTX *ctx)
+{
+ EVP_CIPHER *cipher;
+
+ if (ctx == NULL)
+ return NULL;
+ cipher = (EVP_CIPHER *)ctx->cipher;
+ if (!EVP_CIPHER_up_ref(cipher))
+ return NULL;
+ return cipher;
+}
-int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx)
+int EVP_CIPHER_CTX_is_encrypting(const EVP_CIPHER_CTX *ctx)
{
return ctx->encrypt;
}
-unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher)
+unsigned long EVP_CIPHER_get_flags(const EVP_CIPHER *cipher)
{
return cipher->flags;
}
@@ -235,36 +497,121 @@ void *EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data)
return old_cipher_data;
}
-int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher)
+int EVP_CIPHER_get_iv_length(const EVP_CIPHER *cipher)
{
return cipher->iv_len;
}
-int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx)
+int EVP_CIPHER_CTX_get_iv_length(const EVP_CIPHER_CTX *ctx)
+{
+ if (ctx->iv_len < 0) {
+ int rv, len = EVP_CIPHER_get_iv_length(ctx->cipher);
+ size_t v = len;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ if (ctx->cipher->get_ctx_params != NULL) {
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN,
+ &v);
+ rv = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params);
+ if (rv > 0) {
+ if (OSSL_PARAM_modified(params)
+ && !OSSL_PARAM_get_int(params, &len))
+ return -1;
+ } else if (rv != EVP_CTRL_RET_UNSUPPORTED) {
+ return -1;
+ }
+ }
+ /* Code below to be removed when legacy support is dropped. */
+ else if ((EVP_CIPHER_get_flags(ctx->cipher)
+ & EVP_CIPH_CUSTOM_IV_LENGTH) != 0) {
+ rv = EVP_CIPHER_CTX_ctrl((EVP_CIPHER_CTX *)ctx, EVP_CTRL_GET_IVLEN,
+ 0, &len);
+ if (rv <= 0)
+ return -1;
+ }
+ /*-
+ * Casting away the const is annoying but required here. We need to
+ * cache the result for performance reasons.
+ */
+ ((EVP_CIPHER_CTX *)ctx)->iv_len = len;
+ }
+ return ctx->iv_len;
+}
+
+int EVP_CIPHER_CTX_get_tag_length(const EVP_CIPHER_CTX *ctx)
{
- int i, rv;
+ int ret;
+ size_t v = 0;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
- if ((EVP_CIPHER_flags(ctx->cipher) & EVP_CIPH_CUSTOM_IV_LENGTH) != 0) {
- rv = EVP_CIPHER_CTX_ctrl((EVP_CIPHER_CTX *)ctx, EVP_CTRL_GET_IVLEN,
- 0, &i);
- return (rv == 1) ? i : -1;
- }
- return ctx->cipher->iv_len;
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, &v);
+ ret = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params);
+ return ret == 1 ? (int)v : 0;
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
const unsigned char *EVP_CIPHER_CTX_original_iv(const EVP_CIPHER_CTX *ctx)
{
- return ctx->oiv;
+ int ok;
+ const unsigned char *v = ctx->oiv;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] =
+ OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_IV,
+ (void **)&v, sizeof(ctx->oiv));
+ ok = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params);
+
+ return ok != 0 ? v : NULL;
}
+/*
+ * OSSL_PARAM_OCTET_PTR gets us the pointer to the running IV in the provider
+ */
const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx)
{
- return ctx->iv;
+ int ok;
+ const unsigned char *v = ctx->iv;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] =
+ OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_UPDATED_IV,
+ (void **)&v, sizeof(ctx->iv));
+ ok = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params);
+
+ return ok != 0 ? v : NULL;
}
unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx)
{
- return ctx->iv;
+ int ok;
+ unsigned char *v = ctx->iv;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] =
+ OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_UPDATED_IV,
+ (void **)&v, sizeof(ctx->iv));
+ ok = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params);
+
+ return ok != 0 ? v : NULL;
+}
+#endif /* OPENSSL_NO_DEPRECATED_3_0_0 */
+
+int EVP_CIPHER_CTX_get_updated_iv(EVP_CIPHER_CTX *ctx, void *buf, size_t len)
+{
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] =
+ OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_UPDATED_IV, buf, len);
+ return evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params) > 0;
+}
+
+int EVP_CIPHER_CTX_get_original_iv(EVP_CIPHER_CTX *ctx, void *buf, size_t len)
+{
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] =
+ OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_IV, buf, len);
+ return evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params) > 0;
}
unsigned char *EVP_CIPHER_CTX_buf_noconst(EVP_CIPHER_CTX *ctx)
@@ -272,109 +619,287 @@ unsigned char *EVP_CIPHER_CTX_buf_noconst(EVP_CIPHER_CTX *ctx)
return ctx->buf;
}
-int EVP_CIPHER_CTX_num(const EVP_CIPHER_CTX *ctx)
+int EVP_CIPHER_CTX_get_num(const EVP_CIPHER_CTX *ctx)
{
- return ctx->num;
+ int ok;
+ unsigned int v = (unsigned int)ctx->num;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] = OSSL_PARAM_construct_uint(OSSL_CIPHER_PARAM_NUM, &v);
+ ok = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params);
+
+ return ok != 0 ? (int)v : EVP_CTRL_RET_UNSUPPORTED;
}
-void EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num)
+int EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num)
{
- ctx->num = num;
+ int ok;
+ unsigned int n = (unsigned int)num;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] = OSSL_PARAM_construct_uint(OSSL_CIPHER_PARAM_NUM, &n);
+ ok = evp_do_ciph_ctx_setparams(ctx->cipher, ctx->algctx, params);
+
+ if (ok != 0)
+ ctx->num = (int)n;
+ return ok != 0;
}
-int EVP_CIPHER_key_length(const EVP_CIPHER *cipher)
+int EVP_CIPHER_get_key_length(const EVP_CIPHER *cipher)
{
return cipher->key_len;
}
-int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx)
+int EVP_CIPHER_CTX_get_key_length(const EVP_CIPHER_CTX *ctx)
{
- return ctx->key_len;
+ int ok;
+ size_t v = ctx->key_len;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &v);
+ ok = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params);
+
+ return ok != 0 ? (int)v : EVP_CTRL_RET_UNSUPPORTED;
}
-int EVP_CIPHER_nid(const EVP_CIPHER *cipher)
+int EVP_CIPHER_get_nid(const EVP_CIPHER *cipher)
{
return cipher->nid;
}
-int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx)
+int EVP_CIPHER_CTX_get_nid(const EVP_CIPHER_CTX *ctx)
{
return ctx->cipher->nid;
}
-int EVP_MD_block_size(const EVP_MD *md)
+int EVP_CIPHER_is_a(const EVP_CIPHER *cipher, const char *name)
{
- return md->block_size;
+ if (cipher == NULL)
+ return 0;
+ if (cipher->prov != NULL)
+ return evp_is_a(cipher->prov, cipher->name_id, NULL, name);
+ return evp_is_a(NULL, 0, EVP_CIPHER_get0_name(cipher), name);
+}
+
+int evp_cipher_get_number(const EVP_CIPHER *cipher)
+{
+ return cipher->name_id;
+}
+
+const char *EVP_CIPHER_get0_name(const EVP_CIPHER *cipher)
+{
+ if (cipher->type_name != NULL)
+ return cipher->type_name;
+#ifndef FIPS_MODULE
+ return OBJ_nid2sn(EVP_CIPHER_get_nid(cipher));
+#else
+ return NULL;
+#endif
+}
+
+const char *EVP_CIPHER_get0_description(const EVP_CIPHER *cipher)
+{
+ if (cipher->description != NULL)
+ return cipher->description;
+#ifndef FIPS_MODULE
+ return OBJ_nid2ln(EVP_CIPHER_get_nid(cipher));
+#else
+ return NULL;
+#endif
+}
+
+int EVP_CIPHER_names_do_all(const EVP_CIPHER *cipher,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (cipher->prov != NULL)
+ return evp_names_do_all(cipher->prov, cipher->name_id, fn, data);
+
+ return 1;
+}
+
+const OSSL_PROVIDER *EVP_CIPHER_get0_provider(const EVP_CIPHER *cipher)
+{
+ return cipher->prov;
+}
+
+int EVP_CIPHER_get_mode(const EVP_CIPHER *cipher)
+{
+ return EVP_CIPHER_get_flags(cipher) & EVP_CIPH_MODE;
+}
+
+int EVP_MD_is_a(const EVP_MD *md, const char *name)
+{
+ if (md == NULL)
+ return 0;
+ if (md->prov != NULL)
+ return evp_is_a(md->prov, md->name_id, NULL, name);
+ return evp_is_a(NULL, 0, EVP_MD_get0_name(md), name);
+}
+
+int evp_md_get_number(const EVP_MD *md)
+{
+ return md->name_id;
}
-int EVP_MD_type(const EVP_MD *md)
+const char *EVP_MD_get0_description(const EVP_MD *md)
+{
+ if (md->description != NULL)
+ return md->description;
+#ifndef FIPS_MODULE
+ return OBJ_nid2ln(EVP_MD_nid(md));
+#else
+ return NULL;
+#endif
+}
+
+const char *EVP_MD_get0_name(const EVP_MD *md)
+{
+ if (md == NULL)
+ return NULL;
+ if (md->type_name != NULL)
+ return md->type_name;
+#ifndef FIPS_MODULE
+ return OBJ_nid2sn(EVP_MD_nid(md));
+#else
+ return NULL;
+#endif
+}
+
+int EVP_MD_names_do_all(const EVP_MD *md,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (md->prov != NULL)
+ return evp_names_do_all(md->prov, md->name_id, fn, data);
+
+ return 1;
+}
+
+const OSSL_PROVIDER *EVP_MD_get0_provider(const EVP_MD *md)
+{
+ return md->prov;
+}
+
+int EVP_MD_get_type(const EVP_MD *md)
{
return md->type;
}
-int EVP_MD_pkey_type(const EVP_MD *md)
+int EVP_MD_get_pkey_type(const EVP_MD *md)
{
return md->pkey_type;
}
-int EVP_MD_size(const EVP_MD *md)
+int EVP_MD_get_block_size(const EVP_MD *md)
{
- if (!md) {
- EVPerr(EVP_F_EVP_MD_SIZE, EVP_R_MESSAGE_DIGEST_IS_NULL);
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_MESSAGE_DIGEST_IS_NULL);
+ return -1;
+ }
+ return md->block_size;
+}
+
+int EVP_MD_get_size(const EVP_MD *md)
+{
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_MESSAGE_DIGEST_IS_NULL);
return -1;
}
return md->md_size;
}
-unsigned long EVP_MD_flags(const EVP_MD *md)
+unsigned long EVP_MD_get_flags(const EVP_MD *md)
{
return md->flags;
}
EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type)
{
- EVP_MD *md = OPENSSL_zalloc(sizeof(*md));
+ EVP_MD *md = evp_md_new();
if (md != NULL) {
md->type = md_type;
md->pkey_type = pkey_type;
+ md->origin = EVP_ORIG_METH;
}
return md;
}
+
EVP_MD *EVP_MD_meth_dup(const EVP_MD *md)
{
- EVP_MD *to = EVP_MD_meth_new(md->type, md->pkey_type);
+ EVP_MD *to = NULL;
+
+ /*
+ * Non-legacy EVP_MDs can't be duplicated like this.
+ * Use EVP_MD_up_ref() instead.
+ */
+ if (md->prov != NULL)
+ return NULL;
+
+ if ((to = EVP_MD_meth_new(md->type, md->pkey_type)) != NULL) {
+ CRYPTO_RWLOCK *lock = to->lock;
- if (to != NULL)
memcpy(to, md, sizeof(*to));
+ to->lock = lock;
+ to->origin = EVP_ORIG_METH;
+ }
return to;
}
-void EVP_MD_meth_free(EVP_MD *md)
+
+void evp_md_free_int(EVP_MD *md)
{
+ OPENSSL_free(md->type_name);
+ ossl_provider_free(md->prov);
+ CRYPTO_THREAD_lock_free(md->lock);
OPENSSL_free(md);
}
+
+void EVP_MD_meth_free(EVP_MD *md)
+{
+ if (md == NULL || md->origin != EVP_ORIG_METH)
+ return;
+
+ evp_md_free_int(md);
+}
+
int EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize)
{
+ if (md->block_size != 0)
+ return 0;
+
md->block_size = blocksize;
return 1;
}
int EVP_MD_meth_set_result_size(EVP_MD *md, int resultsize)
{
+ if (md->md_size != 0)
+ return 0;
+
md->md_size = resultsize;
return 1;
}
int EVP_MD_meth_set_app_datasize(EVP_MD *md, int datasize)
{
+ if (md->ctx_size != 0)
+ return 0;
+
md->ctx_size = datasize;
return 1;
}
int EVP_MD_meth_set_flags(EVP_MD *md, unsigned long flags)
{
+ if (md->flags != 0)
+ return 0;
+
md->flags = flags;
return 1;
}
int EVP_MD_meth_set_init(EVP_MD *md, int (*init)(EVP_MD_CTX *ctx))
{
+ if (md->init != NULL)
+ return 0;
+
md->init = init;
return 1;
}
@@ -382,29 +907,44 @@ int EVP_MD_meth_set_update(EVP_MD *md, int (*update)(EVP_MD_CTX *ctx,
const void *data,
size_t count))
{
+ if (md->update != NULL)
+ return 0;
+
md->update = update;
return 1;
}
int EVP_MD_meth_set_final(EVP_MD *md, int (*final)(EVP_MD_CTX *ctx,
unsigned char *md))
{
+ if (md->final != NULL)
+ return 0;
+
md->final = final;
return 1;
}
int EVP_MD_meth_set_copy(EVP_MD *md, int (*copy)(EVP_MD_CTX *to,
const EVP_MD_CTX *from))
{
+ if (md->copy != NULL)
+ return 0;
+
md->copy = copy;
return 1;
}
int EVP_MD_meth_set_cleanup(EVP_MD *md, int (*cleanup)(EVP_MD_CTX *ctx))
{
+ if (md->cleanup != NULL)
+ return 0;
+
md->cleanup = cleanup;
return 1;
}
int EVP_MD_meth_set_ctrl(EVP_MD *md, int (*ctrl)(EVP_MD_CTX *ctx, int cmd,
int p1, void *p2))
{
+ if (md->md_ctrl != NULL)
+ return 0;
+
md->md_ctrl = ctrl;
return 1;
}
@@ -455,18 +995,40 @@ int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd,
return md->md_ctrl;
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx)
{
- if (!ctx)
+ if (ctx == NULL)
+ return NULL;
+ return ctx->reqdigest;
+}
+#endif
+
+const EVP_MD *EVP_MD_CTX_get0_md(const EVP_MD_CTX *ctx)
+{
+ if (ctx == NULL)
return NULL;
- return ctx->digest;
+ return ctx->reqdigest;
}
-EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx)
+EVP_MD *EVP_MD_CTX_get1_md(EVP_MD_CTX *ctx)
+{
+ EVP_MD *md;
+
+ if (ctx == NULL)
+ return NULL;
+ md = (EVP_MD *)ctx->reqdigest;
+ if (md == NULL || !EVP_MD_up_ref(md))
+ return NULL;
+ return md;
+}
+
+EVP_PKEY_CTX *EVP_MD_CTX_get_pkey_ctx(const EVP_MD_CTX *ctx)
{
return ctx->pctx;
}
+#if !defined(FIPS_MODULE)
void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx)
{
/*
@@ -485,8 +1047,9 @@ void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx)
EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
}
}
+#endif /* !defined(FIPS_MODULE) */
-void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx)
+void *EVP_MD_CTX_get0_md_data(const EVP_MD_CTX *ctx)
{
return ctx->md_data;
}
@@ -519,17 +1082,135 @@ int EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, int flags)
return (ctx->flags & flags);
}
+static int evp_cipher_ctx_enable_use_bits(EVP_CIPHER_CTX *ctx,
+ unsigned int enable)
+{
+ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] = OSSL_PARAM_construct_uint(OSSL_CIPHER_PARAM_USE_BITS, &enable);
+ return EVP_CIPHER_CTX_set_params(ctx, params);
+}
+
void EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags)
{
+ int oldflags = ctx->flags;
+
ctx->flags |= flags;
+ if (((oldflags ^ ctx->flags) & EVP_CIPH_FLAG_LENGTH_BITS) != 0)
+ evp_cipher_ctx_enable_use_bits(ctx, 1);
}
void EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags)
{
+ int oldflags = ctx->flags;
+
ctx->flags &= ~flags;
+ if (((oldflags ^ ctx->flags) & EVP_CIPH_FLAG_LENGTH_BITS) != 0)
+ evp_cipher_ctx_enable_use_bits(ctx, 0);
}
int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags)
{
return (ctx->flags & flags);
}
+
+#if !defined(FIPS_MODULE)
+
+int EVP_PKEY_CTX_set_group_name(EVP_PKEY_CTX *ctx, const char *name)
+{
+ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+
+ if (name == NULL)
+ return -1;
+
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
+ (char *)name, 0);
+ return EVP_PKEY_CTX_set_params(ctx, params);
+}
+
+int EVP_PKEY_CTX_get_group_name(EVP_PKEY_CTX *ctx, char *name, size_t namelen)
+{
+ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ OSSL_PARAM *p = params;
+
+ if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
+ /* There is no legacy support for this */
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+
+ if (name == NULL)
+ return -1;
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
+ name, namelen);
+ if (!EVP_PKEY_CTX_get_params(ctx, params))
+ return -1;
+ return 1;
+}
+
+/*
+ * evp_pkey_keygen() abstracts from the explicit use of B<EVP_PKEY_CTX>
+ * while providing a generic way of generating a new asymmetric key pair
+ * of algorithm type I<name> (e.g., C<RSA> or C<EC>).
+ * The library context I<libctx> and property query I<propq>
+ * are used when fetching algorithms from providers.
+ * The I<params> specify algorithm-specific parameters
+ * such as the RSA modulus size or the name of an EC curve.
+ */
+static EVP_PKEY *evp_pkey_keygen(OSSL_LIB_CTX *libctx, const char *name,
+ const char *propq, const OSSL_PARAM *params)
+{
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(libctx, name, propq);
+
+ if (ctx != NULL
+ && EVP_PKEY_keygen_init(ctx) > 0
+ && EVP_PKEY_CTX_set_params(ctx, params))
+ (void)EVP_PKEY_generate(ctx, &pkey);
+
+ EVP_PKEY_CTX_free(ctx);
+ return pkey;
+}
+
+EVP_PKEY *EVP_PKEY_Q_keygen(OSSL_LIB_CTX *libctx, const char *propq,
+ const char *type, ...)
+{
+ va_list args;
+ size_t bits;
+ char *name;
+ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ EVP_PKEY *ret = NULL;
+
+ va_start(args, type);
+
+ if (OPENSSL_strcasecmp(type, "RSA") == 0) {
+ bits = va_arg(args, size_t);
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_RSA_BITS, &bits);
+ } else if (OPENSSL_strcasecmp(type, "EC") == 0) {
+ name = va_arg(args, char *);
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
+ name, 0);
+ } else if (OPENSSL_strcasecmp(type, "ED25519") != 0
+ && OPENSSL_strcasecmp(type, "X25519") != 0
+ && OPENSSL_strcasecmp(type, "ED448") != 0
+ && OPENSSL_strcasecmp(type, "X448") != 0
+ && OPENSSL_strcasecmp(type, "SM2") != 0) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
+ goto end;
+ }
+ ret = evp_pkey_keygen(libctx, type, propq, params);
+
+ end:
+ va_end(args);
+ return ret;
+}
+
+#endif /* !defined(FIPS_MODULE) */
diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h
index b59beee49fa8..3ccfaeb37cd9 100644
--- a/crypto/evp/evp_local.h
+++ b/crypto/evp/evp_local.h
@@ -1,15 +1,20 @@
/*
* Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-/* EVP_MD_CTX related stuff */
+#include <openssl/core_dispatch.h>
+#include "internal/refcount.h"
+
+#define EVP_CTRL_RET_UNSUPPORTED -1
+
struct evp_md_ctx_st {
+ const EVP_MD *reqdigest; /* The original requested digest */
const EVP_MD *digest;
ENGINE *engine; /* functional reference if 'digest' is
* ENGINE-provided */
@@ -19,6 +24,13 @@ struct evp_md_ctx_st {
EVP_PKEY_CTX *pctx;
/* Update function: usually copied from EVP_MD */
int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count);
+
+ /*
+ * Opaque ctx returned from a providers digest algorithm implementation
+ * OSSL_FUNC_digest_newctx()
+ */
+ void *algctx;
+ EVP_MD *fetched_digest;
} /* EVP_MD_CTX */ ;
struct evp_cipher_ctx_st {
@@ -34,17 +46,198 @@ struct evp_cipher_ctx_st {
/* FIXME: Should this even exist? It appears unused */
void *app_data; /* application stuff */
int key_len; /* May change for variable length cipher */
+ int iv_len; /* IV length */
unsigned long flags; /* Various flags */
void *cipher_data; /* per EVP data */
int final_used;
int block_mask;
unsigned char final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */
+
+ /*
+ * Opaque ctx returned from a providers cipher algorithm implementation
+ * OSSL_FUNC_cipher_newctx()
+ */
+ void *algctx;
+ EVP_CIPHER *fetched_cipher;
} /* EVP_CIPHER_CTX */ ;
+struct evp_mac_ctx_st {
+ EVP_MAC *meth; /* Method structure */
+ /*
+ * Opaque ctx returned from a providers MAC algorithm implementation
+ * OSSL_FUNC_mac_newctx()
+ */
+ void *algctx;
+} /* EVP_MAC_CTX */;
+
+struct evp_kdf_ctx_st {
+ EVP_KDF *meth; /* Method structure */
+ /*
+ * Opaque ctx returned from a providers KDF algorithm implementation
+ * OSSL_FUNC_kdf_newctx()
+ */
+ void *algctx;
+} /* EVP_KDF_CTX */ ;
+
+struct evp_rand_ctx_st {
+ EVP_RAND *meth; /* Method structure */
+ /*
+ * Opaque ctx returned from a providers rand algorithm implementation
+ * OSSL_FUNC_rand_newctx()
+ */
+ void *algctx;
+ EVP_RAND_CTX *parent; /* Parent EVP_RAND or NULL if none */
+ CRYPTO_REF_COUNT refcnt; /* Context reference count */
+ CRYPTO_RWLOCK *refcnt_lock;
+} /* EVP_RAND_CTX */ ;
+
+struct evp_keymgmt_st {
+ int id; /* libcrypto internal */
+
+ int name_id;
+ char *type_name;
+ const char *description;
+ OSSL_PROVIDER *prov;
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+
+ /* Constructor(s), destructor, information */
+ OSSL_FUNC_keymgmt_new_fn *new;
+ OSSL_FUNC_keymgmt_free_fn *free;
+ OSSL_FUNC_keymgmt_get_params_fn *get_params;
+ OSSL_FUNC_keymgmt_gettable_params_fn *gettable_params;
+ OSSL_FUNC_keymgmt_set_params_fn *set_params;
+ OSSL_FUNC_keymgmt_settable_params_fn *settable_params;
+
+ /* Generation, a complex constructor */
+ OSSL_FUNC_keymgmt_gen_init_fn *gen_init;
+ OSSL_FUNC_keymgmt_gen_set_template_fn *gen_set_template;
+ OSSL_FUNC_keymgmt_gen_set_params_fn *gen_set_params;
+ OSSL_FUNC_keymgmt_gen_settable_params_fn *gen_settable_params;
+ OSSL_FUNC_keymgmt_gen_fn *gen;
+ OSSL_FUNC_keymgmt_gen_cleanup_fn *gen_cleanup;
+
+ OSSL_FUNC_keymgmt_load_fn *load;
+
+ /* Key object checking */
+ OSSL_FUNC_keymgmt_query_operation_name_fn *query_operation_name;
+ OSSL_FUNC_keymgmt_has_fn *has;
+ OSSL_FUNC_keymgmt_validate_fn *validate;
+ OSSL_FUNC_keymgmt_match_fn *match;
+
+ /* Import and export routines */
+ OSSL_FUNC_keymgmt_import_fn *import;
+ OSSL_FUNC_keymgmt_import_types_fn *import_types;
+ OSSL_FUNC_keymgmt_export_fn *export;
+ OSSL_FUNC_keymgmt_export_types_fn *export_types;
+ OSSL_FUNC_keymgmt_dup_fn *dup;
+} /* EVP_KEYMGMT */ ;
+
+struct evp_keyexch_st {
+ int name_id;
+ char *type_name;
+ const char *description;
+ OSSL_PROVIDER *prov;
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+
+ OSSL_FUNC_keyexch_newctx_fn *newctx;
+ OSSL_FUNC_keyexch_init_fn *init;
+ OSSL_FUNC_keyexch_set_peer_fn *set_peer;
+ OSSL_FUNC_keyexch_derive_fn *derive;
+ OSSL_FUNC_keyexch_freectx_fn *freectx;
+ OSSL_FUNC_keyexch_dupctx_fn *dupctx;
+ OSSL_FUNC_keyexch_set_ctx_params_fn *set_ctx_params;
+ OSSL_FUNC_keyexch_settable_ctx_params_fn *settable_ctx_params;
+ OSSL_FUNC_keyexch_get_ctx_params_fn *get_ctx_params;
+ OSSL_FUNC_keyexch_gettable_ctx_params_fn *gettable_ctx_params;
+} /* EVP_KEYEXCH */;
+
+struct evp_signature_st {
+ int name_id;
+ char *type_name;
+ const char *description;
+ OSSL_PROVIDER *prov;
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+
+ OSSL_FUNC_signature_newctx_fn *newctx;
+ OSSL_FUNC_signature_sign_init_fn *sign_init;
+ OSSL_FUNC_signature_sign_fn *sign;
+ OSSL_FUNC_signature_verify_init_fn *verify_init;
+ OSSL_FUNC_signature_verify_fn *verify;
+ OSSL_FUNC_signature_verify_recover_init_fn *verify_recover_init;
+ OSSL_FUNC_signature_verify_recover_fn *verify_recover;
+ OSSL_FUNC_signature_digest_sign_init_fn *digest_sign_init;
+ OSSL_FUNC_signature_digest_sign_update_fn *digest_sign_update;
+ OSSL_FUNC_signature_digest_sign_final_fn *digest_sign_final;
+ OSSL_FUNC_signature_digest_sign_fn *digest_sign;
+ OSSL_FUNC_signature_digest_verify_init_fn *digest_verify_init;
+ OSSL_FUNC_signature_digest_verify_update_fn *digest_verify_update;
+ OSSL_FUNC_signature_digest_verify_final_fn *digest_verify_final;
+ OSSL_FUNC_signature_digest_verify_fn *digest_verify;
+ OSSL_FUNC_signature_freectx_fn *freectx;
+ OSSL_FUNC_signature_dupctx_fn *dupctx;
+ OSSL_FUNC_signature_get_ctx_params_fn *get_ctx_params;
+ OSSL_FUNC_signature_gettable_ctx_params_fn *gettable_ctx_params;
+ OSSL_FUNC_signature_set_ctx_params_fn *set_ctx_params;
+ OSSL_FUNC_signature_settable_ctx_params_fn *settable_ctx_params;
+ OSSL_FUNC_signature_get_ctx_md_params_fn *get_ctx_md_params;
+ OSSL_FUNC_signature_gettable_ctx_md_params_fn *gettable_ctx_md_params;
+ OSSL_FUNC_signature_set_ctx_md_params_fn *set_ctx_md_params;
+ OSSL_FUNC_signature_settable_ctx_md_params_fn *settable_ctx_md_params;
+} /* EVP_SIGNATURE */;
+
+struct evp_asym_cipher_st {
+ int name_id;
+ char *type_name;
+ const char *description;
+ OSSL_PROVIDER *prov;
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+
+ OSSL_FUNC_asym_cipher_newctx_fn *newctx;
+ OSSL_FUNC_asym_cipher_encrypt_init_fn *encrypt_init;
+ OSSL_FUNC_asym_cipher_encrypt_fn *encrypt;
+ OSSL_FUNC_asym_cipher_decrypt_init_fn *decrypt_init;
+ OSSL_FUNC_asym_cipher_decrypt_fn *decrypt;
+ OSSL_FUNC_asym_cipher_freectx_fn *freectx;
+ OSSL_FUNC_asym_cipher_dupctx_fn *dupctx;
+ OSSL_FUNC_asym_cipher_get_ctx_params_fn *get_ctx_params;
+ OSSL_FUNC_asym_cipher_gettable_ctx_params_fn *gettable_ctx_params;
+ OSSL_FUNC_asym_cipher_set_ctx_params_fn *set_ctx_params;
+ OSSL_FUNC_asym_cipher_settable_ctx_params_fn *settable_ctx_params;
+} /* EVP_ASYM_CIPHER */;
+
+struct evp_kem_st {
+ int name_id;
+ char *type_name;
+ const char *description;
+ OSSL_PROVIDER *prov;
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+
+ OSSL_FUNC_kem_newctx_fn *newctx;
+ OSSL_FUNC_kem_encapsulate_init_fn *encapsulate_init;
+ OSSL_FUNC_kem_encapsulate_fn *encapsulate;
+ OSSL_FUNC_kem_decapsulate_init_fn *decapsulate_init;
+ OSSL_FUNC_kem_decapsulate_fn *decapsulate;
+ OSSL_FUNC_kem_freectx_fn *freectx;
+ OSSL_FUNC_kem_dupctx_fn *dupctx;
+ OSSL_FUNC_kem_get_ctx_params_fn *get_ctx_params;
+ OSSL_FUNC_kem_gettable_ctx_params_fn *gettable_ctx_params;
+ OSSL_FUNC_kem_set_ctx_params_fn *set_ctx_params;
+ OSSL_FUNC_kem_settable_ctx_params_fn *settable_ctx_params;
+} /* EVP_KEM */;
+
int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
int passlen, ASN1_TYPE *param,
const EVP_CIPHER *c, const EVP_MD *md,
int en_de);
+int PKCS5_v2_PBKDF2_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass,
+ int passlen, ASN1_TYPE *param,
+ const EVP_CIPHER *c, const EVP_MD *md,
+ int en_de, OSSL_LIB_CTX *libctx, const char *propq);
struct evp_Encode_Ctx_st {
/* number saved in a partial encode/decode */
@@ -65,4 +258,121 @@ struct evp_Encode_Ctx_st {
typedef struct evp_pbe_st EVP_PBE_CTL;
DEFINE_STACK_OF(EVP_PBE_CTL)
-int is_partially_overlapping(const void *ptr1, const void *ptr2, size_t len);
+int ossl_is_partially_overlapping(const void *ptr1, const void *ptr2, int len);
+
+#include <openssl/types.h>
+#include <openssl/core.h>
+
+void *evp_generic_fetch(OSSL_LIB_CTX *ctx, int operation_id,
+ const char *name, const char *properties,
+ void *(*new_method)(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov),
+ int (*up_ref_method)(void *),
+ void (*free_method)(void *));
+void *evp_generic_fetch_by_number(OSSL_LIB_CTX *ctx, int operation_id,
+ int name_id, const char *properties,
+ void *(*new_method)(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov),
+ int (*up_ref_method)(void *),
+ void (*free_method)(void *));
+void *evp_generic_fetch_from_prov(OSSL_PROVIDER *prov, int operation_id,
+ const char *name, const char *properties,
+ void *(*new_method)(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov),
+ int (*up_ref_method)(void *),
+ void (*free_method)(void *));
+void evp_generic_do_all_prefetched(OSSL_LIB_CTX *libctx, int operation_id,
+ void (*user_fn)(void *method, void *arg),
+ void *user_arg);
+void evp_generic_do_all(OSSL_LIB_CTX *libctx, int operation_id,
+ void (*user_fn)(void *method, void *arg),
+ void *user_arg,
+ void *(*new_method)(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov),
+ int (*up_ref_method)(void *),
+ void (*free_method)(void *));
+
+/* Internal fetchers for method types that are to be combined with others */
+EVP_KEYMGMT *evp_keymgmt_fetch_by_number(OSSL_LIB_CTX *ctx, int name_id,
+ const char *properties);
+EVP_SIGNATURE *evp_signature_fetch_from_prov(OSSL_PROVIDER *prov,
+ const char *name,
+ const char *properties);
+EVP_ASYM_CIPHER *evp_asym_cipher_fetch_from_prov(OSSL_PROVIDER *prov,
+ const char *name,
+ const char *properties);
+EVP_KEYEXCH *evp_keyexch_fetch_from_prov(OSSL_PROVIDER *prov,
+ const char *name,
+ const char *properties);
+EVP_KEM *evp_kem_fetch_from_prov(OSSL_PROVIDER *prov,
+ const char *name,
+ const char *properties);
+
+/* Internal structure constructors for fetched methods */
+EVP_MD *evp_md_new(void);
+EVP_CIPHER *evp_cipher_new(void);
+
+int evp_cipher_get_asn1_aead_params(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
+ evp_cipher_aead_asn1_params *asn1_params);
+int evp_cipher_set_asn1_aead_params(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
+ evp_cipher_aead_asn1_params *asn1_params);
+
+/* Helper functions to avoid duplicating code */
+
+/*
+ * These methods implement different ways to pass a params array to the
+ * provider. They will return one of these values:
+ *
+ * -2 if the method doesn't come from a provider
+ * (evp_do_param will return this to the called)
+ * -1 if the provider doesn't offer the desired function
+ * (evp_do_param will raise an error and return 0)
+ * or the return value from the desired function
+ * (evp_do_param will return it to the caller)
+ */
+int evp_do_ciph_getparams(const EVP_CIPHER *ciph, OSSL_PARAM params[]);
+int evp_do_ciph_ctx_getparams(const EVP_CIPHER *ciph, void *provctx,
+ OSSL_PARAM params[]);
+int evp_do_ciph_ctx_setparams(const EVP_CIPHER *ciph, void *provctx,
+ OSSL_PARAM params[]);
+int evp_do_md_getparams(const EVP_MD *md, OSSL_PARAM params[]);
+int evp_do_md_ctx_getparams(const EVP_MD *md, void *provctx,
+ OSSL_PARAM params[]);
+int evp_do_md_ctx_setparams(const EVP_MD *md, void *provctx,
+ OSSL_PARAM params[]);
+
+OSSL_PARAM *evp_pkey_to_param(EVP_PKEY *pkey, size_t *sz);
+
+#define M_check_autoarg(ctx, arg, arglen, err) \
+ if (ctx->pmeth->flags & EVP_PKEY_FLAG_AUTOARGLEN) { \
+ size_t pksize = (size_t)EVP_PKEY_get_size(ctx->pkey); \
+ \
+ if (pksize == 0) { \
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY); /*ckerr_ignore*/ \
+ return 0; \
+ } \
+ if (arg == NULL) { \
+ *arglen = pksize; \
+ return 1; \
+ } \
+ if (*arglen < pksize) { \
+ ERR_raise(ERR_LIB_EVP, EVP_R_BUFFER_TOO_SMALL); /*ckerr_ignore*/ \
+ return 0; \
+ } \
+ }
+
+void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx);
+void evp_cipher_free_int(EVP_CIPHER *md);
+void evp_md_free_int(EVP_MD *md);
+
+/* OSSL_PROVIDER * is only used to get the library context */
+int evp_is_a(OSSL_PROVIDER *prov, int number,
+ const char *legacy_name, const char *name);
+int evp_names_do_all(OSSL_PROVIDER *prov, int number,
+ void (*fn)(const char *name, void *data),
+ void *data);
+int evp_cipher_cache_constants(EVP_CIPHER *cipher);
diff --git a/crypto/evp/evp_pbe.c b/crypto/evp/evp_pbe.c
index 967203f373c9..5f6720d2c3f3 100644
--- a/crypto/evp/evp_pbe.c
+++ b/crypto/evp/evp_pbe.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,8 +10,11 @@
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
+#include <openssl/core.h>
+#include <openssl/core_names.h>
#include <openssl/pkcs12.h>
#include <openssl/x509.h>
+#include "crypto/evp.h"
#include "evp_local.h"
/* Password based encryption (PBE) functions */
@@ -24,41 +27,42 @@ struct evp_pbe_st {
int cipher_nid;
int md_nid;
EVP_PBE_KEYGEN *keygen;
+ EVP_PBE_KEYGEN_EX *keygen_ex;
};
static STACK_OF(EVP_PBE_CTL) *pbe_algs;
static const EVP_PBE_CTL builtin_pbe[] = {
{EVP_PBE_TYPE_OUTER, NID_pbeWithMD2AndDES_CBC,
- NID_des_cbc, NID_md2, PKCS5_PBE_keyivgen},
+ NID_des_cbc, NID_md2, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbeWithMD5AndDES_CBC,
- NID_des_cbc, NID_md5, PKCS5_PBE_keyivgen},
+ NID_des_cbc, NID_md5, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbeWithSHA1AndRC2_CBC,
- NID_rc2_64_cbc, NID_sha1, PKCS5_PBE_keyivgen},
+ NID_rc2_64_cbc, NID_sha1, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen},
{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And128BitRC4,
- NID_rc4, NID_sha1, PKCS12_PBE_keyivgen},
+ NID_rc4, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And40BitRC4,
- NID_rc4_40, NID_sha1, PKCS12_PBE_keyivgen},
+ NID_rc4_40, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
- NID_des_ede3_cbc, NID_sha1, PKCS12_PBE_keyivgen},
+ NID_des_ede3_cbc, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And2_Key_TripleDES_CBC,
- NID_des_ede_cbc, NID_sha1, PKCS12_PBE_keyivgen},
+ NID_des_ede_cbc, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And128BitRC2_CBC,
- NID_rc2_cbc, NID_sha1, PKCS12_PBE_keyivgen},
+ NID_rc2_cbc, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And40BitRC2_CBC,
- NID_rc2_40_cbc, NID_sha1, PKCS12_PBE_keyivgen},
+ NID_rc2_40_cbc, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
- {EVP_PBE_TYPE_OUTER, NID_pbes2, -1, -1, PKCS5_v2_PBE_keyivgen},
+ {EVP_PBE_TYPE_OUTER, NID_pbes2, -1, -1, PKCS5_v2_PBE_keyivgen, &PKCS5_v2_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbeWithMD2AndRC2_CBC,
- NID_rc2_64_cbc, NID_md2, PKCS5_PBE_keyivgen},
+ NID_rc2_64_cbc, NID_md2, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbeWithMD5AndRC2_CBC,
- NID_rc2_64_cbc, NID_md5, PKCS5_PBE_keyivgen},
+ NID_rc2_64_cbc, NID_md5, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbeWithSHA1AndDES_CBC,
- NID_des_cbc, NID_sha1, PKCS5_PBE_keyivgen},
+ NID_des_cbc, NID_sha1, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_PRF, NID_hmacWithSHA1, -1, NID_sha1, 0},
{EVP_PBE_TYPE_PRF, NID_hmac_md5, -1, NID_md5, 0},
@@ -75,62 +79,90 @@ static const EVP_PBE_CTL builtin_pbe[] = {
NID_id_GostR3411_2012_512, 0},
{EVP_PBE_TYPE_PRF, NID_hmacWithSHA512_224, -1, NID_sha512_224, 0},
{EVP_PBE_TYPE_PRF, NID_hmacWithSHA512_256, -1, NID_sha512_256, 0},
- {EVP_PBE_TYPE_KDF, NID_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen},
+ {EVP_PBE_TYPE_KDF, NID_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen, &PKCS5_v2_PBKDF2_keyivgen_ex},
#ifndef OPENSSL_NO_SCRYPT
- {EVP_PBE_TYPE_KDF, NID_id_scrypt, -1, -1, PKCS5_v2_scrypt_keyivgen}
+ {EVP_PBE_TYPE_KDF, NID_id_scrypt, -1, -1, PKCS5_v2_scrypt_keyivgen, &PKCS5_v2_scrypt_keyivgen_ex}
#endif
};
-int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
- ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de)
+
+int EVP_PBE_CipherInit_ex(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
+ ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
- const EVP_CIPHER *cipher;
- const EVP_MD *md;
- int cipher_nid, md_nid;
+ const EVP_CIPHER *cipher = NULL;
+ EVP_CIPHER *cipher_fetch = NULL;
+ const EVP_MD *md = NULL;
+ EVP_MD *md_fetch = NULL;
+ int ret = 0, cipher_nid, md_nid;
+ EVP_PBE_KEYGEN_EX *keygen_ex;
EVP_PBE_KEYGEN *keygen;
- if (!EVP_PBE_find(EVP_PBE_TYPE_OUTER, OBJ_obj2nid(pbe_obj),
- &cipher_nid, &md_nid, &keygen)) {
+ if (!EVP_PBE_find_ex(EVP_PBE_TYPE_OUTER, OBJ_obj2nid(pbe_obj),
+ &cipher_nid, &md_nid, &keygen, &keygen_ex)) {
char obj_tmp[80];
- EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_PBE_ALGORITHM);
- if (!pbe_obj)
+
+ if (pbe_obj == NULL)
OPENSSL_strlcpy(obj_tmp, "NULL", sizeof(obj_tmp));
else
i2t_ASN1_OBJECT(obj_tmp, sizeof(obj_tmp), pbe_obj);
- ERR_add_error_data(2, "TYPE=", obj_tmp);
- return 0;
+ ERR_raise_data(ERR_LIB_EVP, EVP_R_UNKNOWN_PBE_ALGORITHM,
+ "TYPE=%s", obj_tmp);
+ goto err;
}
- if (!pass)
+ if (pass == NULL)
passlen = 0;
else if (passlen == -1)
passlen = strlen(pass);
- if (cipher_nid == -1)
- cipher = NULL;
- else {
- cipher = EVP_get_cipherbynid(cipher_nid);
- if (!cipher) {
- EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_CIPHER);
- return 0;
+ if (cipher_nid != -1) {
+ (void)ERR_set_mark();
+ cipher = cipher_fetch = EVP_CIPHER_fetch(libctx, OBJ_nid2sn(cipher_nid), propq);
+ /* Fallback to legacy method */
+ if (cipher == NULL)
+ cipher = EVP_get_cipherbynid(cipher_nid);
+ if (cipher == NULL) {
+ (void)ERR_clear_last_mark();
+ ERR_raise_data(ERR_LIB_EVP, EVP_R_UNKNOWN_CIPHER,
+ OBJ_nid2sn(cipher_nid));
+ goto err;
}
+ (void)ERR_pop_to_mark();
}
- if (md_nid == -1)
- md = NULL;
- else {
- md = EVP_get_digestbynid(md_nid);
- if (!md) {
- EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_DIGEST);
- return 0;
+ if (md_nid != -1) {
+ (void)ERR_set_mark();
+ md = md_fetch = EVP_MD_fetch(libctx, OBJ_nid2sn(md_nid), propq);
+ /* Fallback to legacy method */
+ if (md == NULL)
+ EVP_get_digestbynid(md_nid);
+
+ if (md == NULL) {
+ (void)ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNKNOWN_DIGEST);
+ goto err;
}
+ (void)ERR_pop_to_mark();
}
- if (!keygen(ctx, pass, passlen, param, cipher, md, en_de)) {
- EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_KEYGEN_FAILURE);
- return 0;
- }
- return 1;
+ /* Try extended keygen with libctx/propq first, fall back to legacy keygen */
+ if (keygen_ex != NULL)
+ ret = keygen_ex(ctx, pass, passlen, param, cipher, md, en_de, libctx, propq);
+ else
+ ret = keygen(ctx, pass, passlen, param, cipher, md, en_de);
+
+err:
+ EVP_CIPHER_free(cipher_fetch);
+ EVP_MD_free(md_fetch);
+
+ return ret;
+}
+
+int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
+ ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de)
+{
+ return EVP_PBE_CipherInit_ex(pbe_obj, pass, passlen, param, ctx, en_de, NULL, NULL);
}
DECLARE_OBJ_BSEARCH_CMP_FN(EVP_PBE_CTL, EVP_PBE_CTL, pbe2);
@@ -168,7 +200,7 @@ int EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid,
goto err;
}
- if ((pbe_tmp = OPENSSL_malloc(sizeof(*pbe_tmp))) == NULL)
+ if ((pbe_tmp = OPENSSL_zalloc(sizeof(*pbe_tmp))) == NULL)
goto err;
pbe_tmp->pbe_type = pbe_type;
@@ -184,7 +216,7 @@ int EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid,
return 1;
err:
- EVPerr(EVP_F_EVP_PBE_ALG_ADD_TYPE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -194,11 +226,11 @@ int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
int cipher_nid, md_nid;
if (cipher)
- cipher_nid = EVP_CIPHER_nid(cipher);
+ cipher_nid = EVP_CIPHER_get_nid(cipher);
else
cipher_nid = -1;
if (md)
- md_nid = EVP_MD_type(md);
+ md_nid = EVP_MD_get_type(md);
else
md_nid = -1;
@@ -206,8 +238,8 @@ int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
cipher_nid, md_nid, keygen);
}
-int EVP_PBE_find(int type, int pbe_nid,
- int *pcnid, int *pmnid, EVP_PBE_KEYGEN **pkeygen)
+int EVP_PBE_find_ex(int type, int pbe_nid, int *pcnid, int *pmnid,
+ EVP_PBE_KEYGEN **pkeygen, EVP_PBE_KEYGEN_EX **pkeygen_ex)
{
EVP_PBE_CTL *pbetmp = NULL, pbelu;
int i;
@@ -226,15 +258,23 @@ int EVP_PBE_find(int type, int pbe_nid,
}
if (pbetmp == NULL)
return 0;
- if (pcnid)
+ if (pcnid != NULL)
*pcnid = pbetmp->cipher_nid;
- if (pmnid)
+ if (pmnid != NULL)
*pmnid = pbetmp->md_nid;
- if (pkeygen)
+ if (pkeygen != NULL)
*pkeygen = pbetmp->keygen;
+ if (pkeygen_ex != NULL)
+ *pkeygen_ex = pbetmp->keygen_ex;
return 1;
}
+int EVP_PBE_find(int type, int pbe_nid,
+ int *pcnid, int *pmnid, EVP_PBE_KEYGEN **pkeygen)
+{
+ return EVP_PBE_find_ex(type, pbe_nid, pcnid, pmnid, pkeygen, NULL);
+}
+
static void free_evp_pbe_ctl(EVP_PBE_CTL *pbe)
{
OPENSSL_free(pbe);
diff --git a/crypto/evp/evp_pkey.c b/crypto/evp/evp_pkey.c
index 586b74605cbd..8f3f1503756c 100644
--- a/crypto/evp/evp_pkey.c
+++ b/crypto/evp/evp_pkey.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,13 +12,17 @@
#include "internal/cryptlib.h"
#include <openssl/x509.h>
#include <openssl/rand.h>
+#include <openssl/encoder.h>
+#include <openssl/decoder.h>
+#include "internal/provider.h"
#include "crypto/asn1.h"
#include "crypto/evp.h"
#include "crypto/x509.h"
/* Extract a private key from a PKCS8 structure */
-EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8)
+EVP_PKEY *evp_pkcs82pkey_legacy(const PKCS8_PRIV_KEY_INFO *p8, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
EVP_PKEY *pkey = NULL;
const ASN1_OBJECT *algoid;
@@ -28,24 +32,27 @@ EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8)
return NULL;
if ((pkey = EVP_PKEY_new()) == NULL) {
- EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) {
- EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
i2t_ASN1_OBJECT(obj_tmp, 80, algoid);
- ERR_add_error_data(2, "TYPE=", obj_tmp);
+ ERR_raise_data(ERR_LIB_EVP, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM,
+ "TYPE=%s", obj_tmp);
goto error;
}
- if (pkey->ameth->priv_decode) {
+ if (pkey->ameth->priv_decode_ex != NULL) {
+ if (!pkey->ameth->priv_decode_ex(pkey, p8, libctx, propq))
+ goto error;
+ } else if (pkey->ameth->priv_decode != NULL) {
if (!pkey->ameth->priv_decode(pkey, p8)) {
- EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_PRIVATE_KEY_DECODE_ERROR);
+ ERR_raise(ERR_LIB_EVP, EVP_R_PRIVATE_KEY_DECODE_ERROR);
goto error;
}
} else {
- EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_METHOD_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_EVP, EVP_R_METHOD_NOT_SUPPORTED);
goto error;
}
@@ -56,34 +63,100 @@ EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8)
return NULL;
}
+EVP_PKEY *EVP_PKCS82PKEY_ex(const PKCS8_PRIV_KEY_INFO *p8, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ EVP_PKEY *pkey = NULL;
+ const unsigned char *p8_data = NULL;
+ unsigned char *encoded_data = NULL;
+ int encoded_len;
+ int selection;
+ size_t len;
+ OSSL_DECODER_CTX *dctx = NULL;
+
+ if ((encoded_len = i2d_PKCS8_PRIV_KEY_INFO(p8, &encoded_data)) <= 0
+ || encoded_data == NULL)
+ return NULL;
+
+ p8_data = encoded_data;
+ len = encoded_len;
+ selection = EVP_PKEY_KEYPAIR | EVP_PKEY_KEY_PARAMETERS;
+ dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", "PrivateKeyInfo",
+ NULL, selection, libctx, propq);
+ if (dctx == NULL
+ || !OSSL_DECODER_from_data(dctx, &p8_data, &len))
+ /* try legacy */
+ pkey = evp_pkcs82pkey_legacy(p8, libctx, propq);
+
+ OPENSSL_clear_free(encoded_data, encoded_len);
+ OSSL_DECODER_CTX_free(dctx);
+ return pkey;
+}
+
+EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8)
+{
+ return EVP_PKCS82PKEY_ex(p8, NULL, NULL);
+}
+
/* Turn a private key into a PKCS8 structure */
-PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey)
+PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(const EVP_PKEY *pkey)
{
- PKCS8_PRIV_KEY_INFO *p8 = PKCS8_PRIV_KEY_INFO_new();
- if (p8 == NULL) {
- EVPerr(EVP_F_EVP_PKEY2PKCS8, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
+ PKCS8_PRIV_KEY_INFO *p8 = NULL;
+ OSSL_ENCODER_CTX *ctx = NULL;
+
+ /*
+ * The implementation for provider-native keys is to encode the
+ * key to a DER encoded PKCS#8 structure, then convert it to a
+ * PKCS8_PRIV_KEY_INFO with good old d2i functions.
+ */
+ if (evp_pkey_is_provided(pkey)) {
+ int selection = OSSL_KEYMGMT_SELECT_ALL;
+ unsigned char *der = NULL;
+ size_t derlen = 0;
+ const unsigned char *pp;
+
+ if ((ctx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection,
+ "DER", "PrivateKeyInfo",
+ NULL)) == NULL
+ || !OSSL_ENCODER_to_data(ctx, &der, &derlen))
+ goto error;
+
+ pp = der;
+ p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &pp, (long)derlen);
+ OPENSSL_free(der);
+ if (p8 == NULL)
+ goto error;
+ } else {
+ p8 = PKCS8_PRIV_KEY_INFO_new();
+ if (p8 == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
- if (pkey->ameth) {
- if (pkey->ameth->priv_encode) {
- if (!pkey->ameth->priv_encode(p8, pkey)) {
- EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_PRIVATE_KEY_ENCODE_ERROR);
+ if (pkey->ameth != NULL) {
+ if (pkey->ameth->priv_encode != NULL) {
+ if (!pkey->ameth->priv_encode(p8, pkey)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_PRIVATE_KEY_ENCODE_ERROR);
+ goto error;
+ }
+ } else {
+ ERR_raise(ERR_LIB_EVP, EVP_R_METHOD_NOT_SUPPORTED);
goto error;
}
} else {
- EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_METHOD_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
goto error;
}
- } else {
- EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
- goto error;
}
- return p8;
+ goto end;
error:
PKCS8_PRIV_KEY_INFO_free(p8);
- return NULL;
+ p8 = NULL;
+ end:
+ OSSL_ENCODER_CTX_free(ctx);
+ return p8;
+
}
/* EVP_PKEY attribute functions */
@@ -147,3 +220,27 @@ int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key,
return 1;
return 0;
}
+
+const char *EVP_PKEY_get0_type_name(const EVP_PKEY *key)
+{
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ const char *name = NULL;
+
+ if (key->keymgmt != NULL)
+ return EVP_KEYMGMT_get0_name(key->keymgmt);
+
+ /* Otherwise fallback to legacy */
+ ameth = EVP_PKEY_get0_asn1(key);
+ if (ameth != NULL)
+ EVP_PKEY_asn1_get0_info(NULL, NULL,
+ NULL, NULL, &name, ameth);
+
+ return name;
+}
+
+const OSSL_PROVIDER *EVP_PKEY_get0_provider(const EVP_PKEY *key)
+{
+ if (evp_pkey_is_provided(key))
+ return EVP_KEYMGMT_get0_provider(key->keymgmt);
+ return NULL;
+}
diff --git a/crypto/evp/evp_rand.c b/crypto/evp/evp_rand.c
new file mode 100644
index 000000000000..c36dbdc56c77
--- /dev/null
+++ b/crypto/evp/evp_rand.c
@@ -0,0 +1,682 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/core.h>
+#include <openssl/core_names.h>
+#include <openssl/crypto.h>
+#include "internal/cryptlib.h"
+#include "internal/numbers.h"
+#include "internal/provider.h"
+#include "internal/core.h"
+#include "crypto/evp.h"
+#include "evp_local.h"
+
+struct evp_rand_st {
+ OSSL_PROVIDER *prov;
+ int name_id;
+ char *type_name;
+ const char *description;
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *refcnt_lock;
+
+ const OSSL_DISPATCH *dispatch;
+ OSSL_FUNC_rand_newctx_fn *newctx;
+ OSSL_FUNC_rand_freectx_fn *freectx;
+ OSSL_FUNC_rand_instantiate_fn *instantiate;
+ OSSL_FUNC_rand_uninstantiate_fn *uninstantiate;
+ OSSL_FUNC_rand_generate_fn *generate;
+ OSSL_FUNC_rand_reseed_fn *reseed;
+ OSSL_FUNC_rand_nonce_fn *nonce;
+ OSSL_FUNC_rand_enable_locking_fn *enable_locking;
+ OSSL_FUNC_rand_lock_fn *lock;
+ OSSL_FUNC_rand_unlock_fn *unlock;
+ OSSL_FUNC_rand_gettable_params_fn *gettable_params;
+ OSSL_FUNC_rand_gettable_ctx_params_fn *gettable_ctx_params;
+ OSSL_FUNC_rand_settable_ctx_params_fn *settable_ctx_params;
+ OSSL_FUNC_rand_get_params_fn *get_params;
+ OSSL_FUNC_rand_get_ctx_params_fn *get_ctx_params;
+ OSSL_FUNC_rand_set_ctx_params_fn *set_ctx_params;
+ OSSL_FUNC_rand_verify_zeroization_fn *verify_zeroization;
+} /* EVP_RAND */ ;
+
+static int evp_rand_up_ref(void *vrand)
+{
+ EVP_RAND *rand = (EVP_RAND *)vrand;
+ int ref = 0;
+
+ if (rand != NULL)
+ return CRYPTO_UP_REF(&rand->refcnt, &ref, rand->refcnt_lock);
+ return 1;
+}
+
+static void evp_rand_free(void *vrand)
+{
+ EVP_RAND *rand = (EVP_RAND *)vrand;
+ int ref = 0;
+
+ if (rand == NULL)
+ return;
+ CRYPTO_DOWN_REF(&rand->refcnt, &ref, rand->refcnt_lock);
+ if (ref > 0)
+ return;
+ OPENSSL_free(rand->type_name);
+ ossl_provider_free(rand->prov);
+ CRYPTO_THREAD_lock_free(rand->refcnt_lock);
+ OPENSSL_free(rand);
+}
+
+static void *evp_rand_new(void)
+{
+ EVP_RAND *rand = OPENSSL_zalloc(sizeof(*rand));
+
+ if (rand == NULL
+ || (rand->refcnt_lock = CRYPTO_THREAD_lock_new()) == NULL) {
+ OPENSSL_free(rand);
+ return NULL;
+ }
+ rand->refcnt = 1;
+ return rand;
+}
+
+/* Enable locking of the underlying DRBG/RAND if available */
+int EVP_RAND_enable_locking(EVP_RAND_CTX *rand)
+{
+ if (rand->meth->enable_locking != NULL)
+ return rand->meth->enable_locking(rand->algctx);
+ ERR_raise(ERR_LIB_EVP, EVP_R_LOCKING_NOT_SUPPORTED);
+ return 0;
+}
+
+/* Lock the underlying DRBG/RAND if available */
+static int evp_rand_lock(EVP_RAND_CTX *rand)
+{
+ if (rand->meth->lock != NULL)
+ return rand->meth->lock(rand->algctx);
+ return 1;
+}
+
+/* Unlock the underlying DRBG/RAND if available */
+static void evp_rand_unlock(EVP_RAND_CTX *rand)
+{
+ if (rand->meth->unlock != NULL)
+ rand->meth->unlock(rand->algctx);
+}
+
+static void *evp_rand_from_algorithm(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
+{
+ const OSSL_DISPATCH *fns = algodef->implementation;
+ EVP_RAND *rand = NULL;
+ int fnrandcnt = 0, fnctxcnt = 0, fnlockcnt = 0, fnenablelockcnt = 0;
+#ifdef FIPS_MODULE
+ int fnzeroizecnt = 0;
+#endif
+
+ if ((rand = evp_rand_new()) == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ rand->name_id = name_id;
+ if ((rand->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
+ evp_rand_free(rand);
+ return NULL;
+ }
+ rand->description = algodef->algorithm_description;
+ rand->dispatch = fns;
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_RAND_NEWCTX:
+ if (rand->newctx != NULL)
+ break;
+ rand->newctx = OSSL_FUNC_rand_newctx(fns);
+ fnctxcnt++;
+ break;
+ case OSSL_FUNC_RAND_FREECTX:
+ if (rand->freectx != NULL)
+ break;
+ rand->freectx = OSSL_FUNC_rand_freectx(fns);
+ fnctxcnt++;
+ break;
+ case OSSL_FUNC_RAND_INSTANTIATE:
+ if (rand->instantiate != NULL)
+ break;
+ rand->instantiate = OSSL_FUNC_rand_instantiate(fns);
+ fnrandcnt++;
+ break;
+ case OSSL_FUNC_RAND_UNINSTANTIATE:
+ if (rand->uninstantiate != NULL)
+ break;
+ rand->uninstantiate = OSSL_FUNC_rand_uninstantiate(fns);
+ fnrandcnt++;
+ break;
+ case OSSL_FUNC_RAND_GENERATE:
+ if (rand->generate != NULL)
+ break;
+ rand->generate = OSSL_FUNC_rand_generate(fns);
+ fnrandcnt++;
+ break;
+ case OSSL_FUNC_RAND_RESEED:
+ if (rand->reseed != NULL)
+ break;
+ rand->reseed = OSSL_FUNC_rand_reseed(fns);
+ break;
+ case OSSL_FUNC_RAND_NONCE:
+ if (rand->nonce != NULL)
+ break;
+ rand->nonce = OSSL_FUNC_rand_nonce(fns);
+ break;
+ case OSSL_FUNC_RAND_ENABLE_LOCKING:
+ if (rand->enable_locking != NULL)
+ break;
+ rand->enable_locking = OSSL_FUNC_rand_enable_locking(fns);
+ fnenablelockcnt++;
+ break;
+ case OSSL_FUNC_RAND_LOCK:
+ if (rand->lock != NULL)
+ break;
+ rand->lock = OSSL_FUNC_rand_lock(fns);
+ fnlockcnt++;
+ break;
+ case OSSL_FUNC_RAND_UNLOCK:
+ if (rand->unlock != NULL)
+ break;
+ rand->unlock = OSSL_FUNC_rand_unlock(fns);
+ fnlockcnt++;
+ break;
+ case OSSL_FUNC_RAND_GETTABLE_PARAMS:
+ if (rand->gettable_params != NULL)
+ break;
+ rand->gettable_params =
+ OSSL_FUNC_rand_gettable_params(fns);
+ break;
+ case OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS:
+ if (rand->gettable_ctx_params != NULL)
+ break;
+ rand->gettable_ctx_params =
+ OSSL_FUNC_rand_gettable_ctx_params(fns);
+ break;
+ case OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS:
+ if (rand->settable_ctx_params != NULL)
+ break;
+ rand->settable_ctx_params =
+ OSSL_FUNC_rand_settable_ctx_params(fns);
+ break;
+ case OSSL_FUNC_RAND_GET_PARAMS:
+ if (rand->get_params != NULL)
+ break;
+ rand->get_params = OSSL_FUNC_rand_get_params(fns);
+ break;
+ case OSSL_FUNC_RAND_GET_CTX_PARAMS:
+ if (rand->get_ctx_params != NULL)
+ break;
+ rand->get_ctx_params = OSSL_FUNC_rand_get_ctx_params(fns);
+ fnctxcnt++;
+ break;
+ case OSSL_FUNC_RAND_SET_CTX_PARAMS:
+ if (rand->set_ctx_params != NULL)
+ break;
+ rand->set_ctx_params = OSSL_FUNC_rand_set_ctx_params(fns);
+ break;
+ case OSSL_FUNC_RAND_VERIFY_ZEROIZATION:
+ if (rand->verify_zeroization != NULL)
+ break;
+ rand->verify_zeroization = OSSL_FUNC_rand_verify_zeroization(fns);
+#ifdef FIPS_MODULE
+ fnzeroizecnt++;
+#endif
+ break;
+ }
+ }
+ /*
+ * In order to be a consistent set of functions we must have at least
+ * a complete set of "rand" functions and a complete set of context
+ * management functions. In FIPS mode, we also require the zeroization
+ * verification function.
+ *
+ * In addition, if locking can be enabled, we need a complete set of
+ * locking functions.
+ */
+ if (fnrandcnt != 3
+ || fnctxcnt != 3
+ || (fnenablelockcnt != 0 && fnenablelockcnt != 1)
+ || (fnlockcnt != 0 && fnlockcnt != 2)
+#ifdef FIPS_MODULE
+ || fnzeroizecnt != 1
+#endif
+ ) {
+ evp_rand_free(rand);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+ return NULL;
+ }
+
+ if (prov != NULL && !ossl_provider_up_ref(prov)) {
+ evp_rand_free(rand);
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+ rand->prov = prov;
+
+ return rand;
+}
+
+EVP_RAND *EVP_RAND_fetch(OSSL_LIB_CTX *libctx, const char *algorithm,
+ const char *properties)
+{
+ return evp_generic_fetch(libctx, OSSL_OP_RAND, algorithm, properties,
+ evp_rand_from_algorithm, evp_rand_up_ref,
+ evp_rand_free);
+}
+
+int EVP_RAND_up_ref(EVP_RAND *rand)
+{
+ return evp_rand_up_ref(rand);
+}
+
+void EVP_RAND_free(EVP_RAND *rand)
+{
+ evp_rand_free(rand);
+}
+
+int evp_rand_get_number(const EVP_RAND *rand)
+{
+ return rand->name_id;
+}
+
+const char *EVP_RAND_get0_name(const EVP_RAND *rand)
+{
+ return rand->type_name;
+}
+
+const char *EVP_RAND_get0_description(const EVP_RAND *rand)
+{
+ return rand->description;
+}
+
+int EVP_RAND_is_a(const EVP_RAND *rand, const char *name)
+{
+ return rand != NULL && evp_is_a(rand->prov, rand->name_id, NULL, name);
+}
+
+const OSSL_PROVIDER *EVP_RAND_get0_provider(const EVP_RAND *rand)
+{
+ return rand->prov;
+}
+
+int EVP_RAND_get_params(EVP_RAND *rand, OSSL_PARAM params[])
+{
+ if (rand->get_params != NULL)
+ return rand->get_params(params);
+ return 1;
+}
+
+static int evp_rand_ctx_up_ref(EVP_RAND_CTX *ctx)
+{
+ int ref = 0;
+
+ return CRYPTO_UP_REF(&ctx->refcnt, &ref, ctx->refcnt_lock);
+}
+
+EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, EVP_RAND_CTX *parent)
+{
+ EVP_RAND_CTX *ctx;
+ void *parent_ctx = NULL;
+ const OSSL_DISPATCH *parent_dispatch = NULL;
+
+ if (rand == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_NULL_ALGORITHM);
+ return NULL;
+ }
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx == NULL || (ctx->refcnt_lock = CRYPTO_THREAD_lock_new()) == NULL) {
+ OPENSSL_free(ctx);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ if (parent != NULL) {
+ if (!evp_rand_ctx_up_ref(parent)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ CRYPTO_THREAD_lock_free(ctx->refcnt_lock);
+ OPENSSL_free(ctx);
+ return NULL;
+ }
+ parent_ctx = parent->algctx;
+ parent_dispatch = parent->meth->dispatch;
+ }
+ if ((ctx->algctx = rand->newctx(ossl_provider_ctx(rand->prov), parent_ctx,
+ parent_dispatch)) == NULL
+ || !EVP_RAND_up_ref(rand)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ rand->freectx(ctx->algctx);
+ CRYPTO_THREAD_lock_free(ctx->refcnt_lock);
+ OPENSSL_free(ctx);
+ EVP_RAND_CTX_free(parent);
+ return NULL;
+ }
+ ctx->meth = rand;
+ ctx->parent = parent;
+ ctx->refcnt = 1;
+ return ctx;
+}
+
+void EVP_RAND_CTX_free(EVP_RAND_CTX *ctx)
+{
+ int ref = 0;
+ EVP_RAND_CTX *parent;
+
+ if (ctx == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&ctx->refcnt, &ref, ctx->refcnt_lock);
+ if (ref > 0)
+ return;
+ parent = ctx->parent;
+ ctx->meth->freectx(ctx->algctx);
+ ctx->algctx = NULL;
+ EVP_RAND_free(ctx->meth);
+ CRYPTO_THREAD_lock_free(ctx->refcnt_lock);
+ OPENSSL_free(ctx);
+ EVP_RAND_CTX_free(parent);
+}
+
+EVP_RAND *EVP_RAND_CTX_get0_rand(EVP_RAND_CTX *ctx)
+{
+ return ctx->meth;
+}
+
+static int evp_rand_get_ctx_params_locked(EVP_RAND_CTX *ctx,
+ OSSL_PARAM params[])
+{
+ return ctx->meth->get_ctx_params(ctx->algctx, params);
+}
+
+int EVP_RAND_CTX_get_params(EVP_RAND_CTX *ctx, OSSL_PARAM params[])
+{
+ int res;
+
+ if (!evp_rand_lock(ctx))
+ return 0;
+ res = evp_rand_get_ctx_params_locked(ctx, params);
+ evp_rand_unlock(ctx);
+ return res;
+}
+
+static int evp_rand_set_ctx_params_locked(EVP_RAND_CTX *ctx,
+ const OSSL_PARAM params[])
+{
+ if (ctx->meth->set_ctx_params != NULL)
+ return ctx->meth->set_ctx_params(ctx->algctx, params);
+ return 1;
+}
+
+int EVP_RAND_CTX_set_params(EVP_RAND_CTX *ctx, const OSSL_PARAM params[])
+{
+ int res;
+
+ if (!evp_rand_lock(ctx))
+ return 0;
+ res = evp_rand_set_ctx_params_locked(ctx, params);
+ evp_rand_unlock(ctx);
+ return res;
+}
+
+const OSSL_PARAM *EVP_RAND_gettable_params(const EVP_RAND *rand)
+{
+ if (rand->gettable_params == NULL)
+ return NULL;
+ return rand->gettable_params(ossl_provider_ctx(EVP_RAND_get0_provider(rand)));
+}
+
+const OSSL_PARAM *EVP_RAND_gettable_ctx_params(const EVP_RAND *rand)
+{
+ void *provctx;
+
+ if (rand->gettable_ctx_params == NULL)
+ return NULL;
+ provctx = ossl_provider_ctx(EVP_RAND_get0_provider(rand));
+ return rand->gettable_ctx_params(NULL, provctx);
+}
+
+const OSSL_PARAM *EVP_RAND_settable_ctx_params(const EVP_RAND *rand)
+{
+ void *provctx;
+
+ if (rand->settable_ctx_params == NULL)
+ return NULL;
+ provctx = ossl_provider_ctx(EVP_RAND_get0_provider(rand));
+ return rand->settable_ctx_params(NULL, provctx);
+}
+
+const OSSL_PARAM *EVP_RAND_CTX_gettable_params(EVP_RAND_CTX *ctx)
+{
+ void *provctx;
+
+ if (ctx->meth->gettable_ctx_params == NULL)
+ return NULL;
+ provctx = ossl_provider_ctx(EVP_RAND_get0_provider(ctx->meth));
+ return ctx->meth->gettable_ctx_params(ctx->algctx, provctx);
+}
+
+const OSSL_PARAM *EVP_RAND_CTX_settable_params(EVP_RAND_CTX *ctx)
+{
+ void *provctx;
+
+ if (ctx->meth->settable_ctx_params == NULL)
+ return NULL;
+ provctx = ossl_provider_ctx(EVP_RAND_get0_provider(ctx->meth));
+ return ctx->meth->settable_ctx_params(ctx->algctx, provctx);
+}
+
+void EVP_RAND_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_RAND *rand, void *arg),
+ void *arg)
+{
+ evp_generic_do_all(libctx, OSSL_OP_RAND,
+ (void (*)(void *, void *))fn, arg,
+ evp_rand_from_algorithm, evp_rand_up_ref,
+ evp_rand_free);
+}
+
+int EVP_RAND_names_do_all(const EVP_RAND *rand,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (rand->prov != NULL)
+ return evp_names_do_all(rand->prov, rand->name_id, fn, data);
+
+ return 1;
+}
+
+static int evp_rand_instantiate_locked
+ (EVP_RAND_CTX *ctx, unsigned int strength, int prediction_resistance,
+ const unsigned char *pstr, size_t pstr_len, const OSSL_PARAM params[])
+{
+ return ctx->meth->instantiate(ctx->algctx, strength, prediction_resistance,
+ pstr, pstr_len, params);
+}
+
+int EVP_RAND_instantiate(EVP_RAND_CTX *ctx, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *pstr, size_t pstr_len,
+ const OSSL_PARAM params[])
+{
+ int res;
+
+ if (!evp_rand_lock(ctx))
+ return 0;
+ res = evp_rand_instantiate_locked(ctx, strength, prediction_resistance,
+ pstr, pstr_len, params);
+ evp_rand_unlock(ctx);
+ return res;
+}
+
+static int evp_rand_uninstantiate_locked(EVP_RAND_CTX *ctx)
+{
+ return ctx->meth->uninstantiate(ctx->algctx);
+}
+
+int EVP_RAND_uninstantiate(EVP_RAND_CTX *ctx)
+{
+ int res;
+
+ if (!evp_rand_lock(ctx))
+ return 0;
+ res = evp_rand_uninstantiate_locked(ctx);
+ evp_rand_unlock(ctx);
+ return res;
+}
+
+static int evp_rand_generate_locked(EVP_RAND_CTX *ctx, unsigned char *out,
+ size_t outlen, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *addin,
+ size_t addin_len)
+{
+ size_t chunk, max_request = 0;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_RAND_PARAM_MAX_REQUEST,
+ &max_request);
+ if (!evp_rand_get_ctx_params_locked(ctx, params)
+ || max_request == 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE);
+ return 0;
+ }
+ for (; outlen > 0; outlen -= chunk, out += chunk) {
+ chunk = outlen > max_request ? max_request : outlen;
+ if (!ctx->meth->generate(ctx->algctx, out, chunk, strength,
+ prediction_resistance, addin, addin_len)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_GENERATE_ERROR);
+ return 0;
+ }
+ /*
+ * Prediction resistance is only relevant the first time around,
+ * subsequently, the DRBG has already been properly reseeded.
+ */
+ prediction_resistance = 0;
+ }
+ return 1;
+}
+
+int EVP_RAND_generate(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen,
+ unsigned int strength, int prediction_resistance,
+ const unsigned char *addin, size_t addin_len)
+{
+ int res;
+
+ if (!evp_rand_lock(ctx))
+ return 0;
+ res = evp_rand_generate_locked(ctx, out, outlen, strength,
+ prediction_resistance, addin, addin_len);
+ evp_rand_unlock(ctx);
+ return res;
+}
+
+static int evp_rand_reseed_locked(EVP_RAND_CTX *ctx, int prediction_resistance,
+ const unsigned char *ent, size_t ent_len,
+ const unsigned char *addin, size_t addin_len)
+{
+ if (ctx->meth->reseed != NULL)
+ return ctx->meth->reseed(ctx->algctx, prediction_resistance,
+ ent, ent_len, addin, addin_len);
+ return 1;
+}
+
+int EVP_RAND_reseed(EVP_RAND_CTX *ctx, int prediction_resistance,
+ const unsigned char *ent, size_t ent_len,
+ const unsigned char *addin, size_t addin_len)
+{
+ int res;
+
+ if (!evp_rand_lock(ctx))
+ return 0;
+ res = evp_rand_reseed_locked(ctx, prediction_resistance,
+ ent, ent_len, addin, addin_len);
+ evp_rand_unlock(ctx);
+ return res;
+}
+
+static unsigned int evp_rand_strength_locked(EVP_RAND_CTX *ctx)
+{
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ unsigned int strength = 0;
+
+ params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, &strength);
+ if (!evp_rand_get_ctx_params_locked(ctx, params))
+ return 0;
+ return strength;
+}
+
+unsigned int EVP_RAND_get_strength(EVP_RAND_CTX *ctx)
+{
+ unsigned int res;
+
+ if (!evp_rand_lock(ctx))
+ return 0;
+ res = evp_rand_strength_locked(ctx);
+ evp_rand_unlock(ctx);
+ return res;
+}
+
+static int evp_rand_nonce_locked(EVP_RAND_CTX *ctx, unsigned char *out,
+ size_t outlen)
+{
+ unsigned int str = evp_rand_strength_locked(ctx);
+
+ if (ctx->meth->nonce == NULL)
+ return 0;
+ if (ctx->meth->nonce(ctx->algctx, out, str, outlen, outlen))
+ return 1;
+ return evp_rand_generate_locked(ctx, out, outlen, str, 0, NULL, 0);
+}
+
+int EVP_RAND_nonce(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen)
+{
+ int res;
+
+ if (!evp_rand_lock(ctx))
+ return 0;
+ res = evp_rand_nonce_locked(ctx, out, outlen);
+ evp_rand_unlock(ctx);
+ return res;
+}
+
+int EVP_RAND_get_state(EVP_RAND_CTX *ctx)
+{
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ int state;
+
+ params[0] = OSSL_PARAM_construct_int(OSSL_RAND_PARAM_STATE, &state);
+ if (!EVP_RAND_CTX_get_params(ctx, params))
+ state = EVP_RAND_STATE_ERROR;
+ return state;
+}
+
+static int evp_rand_verify_zeroization_locked(EVP_RAND_CTX *ctx)
+{
+ if (ctx->meth->verify_zeroization != NULL)
+ return ctx->meth->verify_zeroization(ctx->algctx);
+ return 0;
+}
+
+int EVP_RAND_verify_zeroization(EVP_RAND_CTX *ctx)
+{
+ int res;
+
+ if (!evp_rand_lock(ctx))
+ return 0;
+ res = evp_rand_verify_zeroization_locked(ctx);
+ evp_rand_unlock(ctx);
+ return res;
+}
diff --git a/crypto/evp/evp_utils.c b/crypto/evp/evp_utils.c
new file mode 100644
index 000000000000..3cc17921f8f4
--- /dev/null
+++ b/crypto/evp/evp_utils.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Internal EVP utility functions */
+
+#include <openssl/core.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/asn1.h> /* evp_local.h needs it */
+#include <openssl/safestack.h> /* evp_local.h needs it */
+#include "crypto/evp.h" /* evp_local.h needs it */
+#include "evp_local.h"
+
+/*
+ * EVP_CTRL_RET_UNSUPPORTED = -1 is the returned value from any ctrl function
+ * where the control command isn't supported, and an alternative code path
+ * may be chosen.
+ * Since these functions are used to implement ctrl functionality, we
+ * use the same value, and other callers will have to compensate.
+ */
+#define PARAM_CHECK(obj, func, errfunc) \
+ if (obj == NULL) \
+ return 0; \
+ if (obj->prov == NULL) \
+ return EVP_CTRL_RET_UNSUPPORTED; \
+ if (obj->func == NULL) { \
+ errfunc(); \
+ return 0; \
+ }
+
+#define PARAM_FUNC(name, func, type, err) \
+int name (const type *obj, OSSL_PARAM params[]) \
+{ \
+ PARAM_CHECK(obj, func, err) \
+ return obj->func(params); \
+}
+
+#define PARAM_CTX_FUNC(name, func, type, err) \
+int name (const type *obj, void *algctx, OSSL_PARAM params[]) \
+{ \
+ PARAM_CHECK(obj, func, err) \
+ return obj->func(algctx, params); \
+}
+
+#define PARAM_FUNCTIONS(type, \
+ getname, getfunc, \
+ getctxname, getctxfunc, \
+ setctxname, setctxfunc) \
+ PARAM_FUNC(getname, getfunc, type, geterr) \
+ PARAM_CTX_FUNC(getctxname, getctxfunc, type, geterr) \
+ PARAM_CTX_FUNC(setctxname, setctxfunc, type, seterr)
+
+/*
+ * These error functions are a workaround for the error scripts, which
+ * currently require that XXXerr method appears inside a function (not a macro).
+ */
+static void geterr(void)
+{
+ ERR_raise(ERR_LIB_EVP, EVP_R_CANNOT_GET_PARAMETERS);
+}
+
+static void seterr(void)
+{
+ ERR_raise(ERR_LIB_EVP, EVP_R_CANNOT_SET_PARAMETERS);
+}
+
+PARAM_FUNCTIONS(EVP_CIPHER,
+ evp_do_ciph_getparams, get_params,
+ evp_do_ciph_ctx_getparams, get_ctx_params,
+ evp_do_ciph_ctx_setparams, set_ctx_params)
+
+PARAM_FUNCTIONS(EVP_MD,
+ evp_do_md_getparams, get_params,
+ evp_do_md_ctx_getparams, get_ctx_params,
+ evp_do_md_ctx_setparams, set_ctx_params)
diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c
new file mode 100644
index 000000000000..d7a4ad142aa7
--- /dev/null
+++ b/crypto/evp/exchange.c
@@ -0,0 +1,597 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include "internal/cryptlib.h"
+#include "internal/refcount.h"
+#include "internal/provider.h"
+#include "internal/core.h"
+#include "internal/numbers.h" /* includes SIZE_MAX */
+#include "crypto/evp.h"
+#include "evp_local.h"
+
+static EVP_KEYEXCH *evp_keyexch_new(OSSL_PROVIDER *prov)
+{
+ EVP_KEYEXCH *exchange = OPENSSL_zalloc(sizeof(EVP_KEYEXCH));
+
+ if (exchange == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ exchange->lock = CRYPTO_THREAD_lock_new();
+ if (exchange->lock == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(exchange);
+ return NULL;
+ }
+ exchange->prov = prov;
+ ossl_provider_up_ref(prov);
+ exchange->refcnt = 1;
+
+ return exchange;
+}
+
+static void *evp_keyexch_from_algorithm(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
+{
+ const OSSL_DISPATCH *fns = algodef->implementation;
+ EVP_KEYEXCH *exchange = NULL;
+ int fncnt = 0, sparamfncnt = 0, gparamfncnt = 0;
+
+ if ((exchange = evp_keyexch_new(prov)) == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ exchange->name_id = name_id;
+ if ((exchange->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL)
+ goto err;
+ exchange->description = algodef->algorithm_description;
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_KEYEXCH_NEWCTX:
+ if (exchange->newctx != NULL)
+ break;
+ exchange->newctx = OSSL_FUNC_keyexch_newctx(fns);
+ fncnt++;
+ break;
+ case OSSL_FUNC_KEYEXCH_INIT:
+ if (exchange->init != NULL)
+ break;
+ exchange->init = OSSL_FUNC_keyexch_init(fns);
+ fncnt++;
+ break;
+ case OSSL_FUNC_KEYEXCH_SET_PEER:
+ if (exchange->set_peer != NULL)
+ break;
+ exchange->set_peer = OSSL_FUNC_keyexch_set_peer(fns);
+ break;
+ case OSSL_FUNC_KEYEXCH_DERIVE:
+ if (exchange->derive != NULL)
+ break;
+ exchange->derive = OSSL_FUNC_keyexch_derive(fns);
+ fncnt++;
+ break;
+ case OSSL_FUNC_KEYEXCH_FREECTX:
+ if (exchange->freectx != NULL)
+ break;
+ exchange->freectx = OSSL_FUNC_keyexch_freectx(fns);
+ fncnt++;
+ break;
+ case OSSL_FUNC_KEYEXCH_DUPCTX:
+ if (exchange->dupctx != NULL)
+ break;
+ exchange->dupctx = OSSL_FUNC_keyexch_dupctx(fns);
+ break;
+ case OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS:
+ if (exchange->get_ctx_params != NULL)
+ break;
+ exchange->get_ctx_params = OSSL_FUNC_keyexch_get_ctx_params(fns);
+ gparamfncnt++;
+ break;
+ case OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS:
+ if (exchange->gettable_ctx_params != NULL)
+ break;
+ exchange->gettable_ctx_params
+ = OSSL_FUNC_keyexch_gettable_ctx_params(fns);
+ gparamfncnt++;
+ break;
+ case OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS:
+ if (exchange->set_ctx_params != NULL)
+ break;
+ exchange->set_ctx_params = OSSL_FUNC_keyexch_set_ctx_params(fns);
+ sparamfncnt++;
+ break;
+ case OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS:
+ if (exchange->settable_ctx_params != NULL)
+ break;
+ exchange->settable_ctx_params
+ = OSSL_FUNC_keyexch_settable_ctx_params(fns);
+ sparamfncnt++;
+ break;
+ }
+ }
+ if (fncnt != 4
+ || (gparamfncnt != 0 && gparamfncnt != 2)
+ || (sparamfncnt != 0 && sparamfncnt != 2)) {
+ /*
+ * In order to be a consistent set of functions we must have at least
+ * a complete set of "exchange" functions: init, derive, newctx,
+ * and freectx. The set_ctx_params and settable_ctx_params functions are
+ * optional, but if one of them is present then the other one must also
+ * be present. Same goes for get_ctx_params and gettable_ctx_params.
+ * The dupctx and set_peer functions are optional.
+ */
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+ goto err;
+ }
+
+ return exchange;
+
+ err:
+ EVP_KEYEXCH_free(exchange);
+ return NULL;
+}
+
+void EVP_KEYEXCH_free(EVP_KEYEXCH *exchange)
+{
+ int i;
+
+ if (exchange == NULL)
+ return;
+ CRYPTO_DOWN_REF(&exchange->refcnt, &i, exchange->lock);
+ if (i > 0)
+ return;
+ OPENSSL_free(exchange->type_name);
+ ossl_provider_free(exchange->prov);
+ CRYPTO_THREAD_lock_free(exchange->lock);
+ OPENSSL_free(exchange);
+}
+
+int EVP_KEYEXCH_up_ref(EVP_KEYEXCH *exchange)
+{
+ int ref = 0;
+
+ CRYPTO_UP_REF(&exchange->refcnt, &ref, exchange->lock);
+ return 1;
+}
+
+OSSL_PROVIDER *EVP_KEYEXCH_get0_provider(const EVP_KEYEXCH *exchange)
+{
+ return exchange->prov;
+}
+
+EVP_KEYEXCH *EVP_KEYEXCH_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties)
+{
+ return evp_generic_fetch(ctx, OSSL_OP_KEYEXCH, algorithm, properties,
+ evp_keyexch_from_algorithm,
+ (int (*)(void *))EVP_KEYEXCH_up_ref,
+ (void (*)(void *))EVP_KEYEXCH_free);
+}
+
+EVP_KEYEXCH *evp_keyexch_fetch_from_prov(OSSL_PROVIDER *prov,
+ const char *algorithm,
+ const char *properties)
+{
+ return evp_generic_fetch_from_prov(prov, OSSL_OP_KEYEXCH,
+ algorithm, properties,
+ evp_keyexch_from_algorithm,
+ (int (*)(void *))EVP_KEYEXCH_up_ref,
+ (void (*)(void *))EVP_KEYEXCH_free);
+}
+
+int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
+{
+ return EVP_PKEY_derive_init_ex(ctx, NULL);
+}
+
+int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
+{
+ int ret;
+ void *provkey = NULL;
+ EVP_KEYEXCH *exchange = NULL;
+ EVP_KEYMGMT *tmp_keymgmt = NULL;
+ const OSSL_PROVIDER *tmp_prov = NULL;
+ const char *supported_exch = NULL;
+ int iter;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
+ return -2;
+ }
+
+ evp_pkey_ctx_free_old_ops(ctx);
+ ctx->operation = EVP_PKEY_OP_DERIVE;
+
+ ERR_set_mark();
+
+ if (evp_pkey_ctx_is_legacy(ctx))
+ goto legacy;
+
+ /*
+ * Some algorithms (e.g. legacy KDFs) don't have a pkey - so we create
+ * a blank one.
+ */
+ if (ctx->pkey == NULL) {
+ EVP_PKEY *pkey = EVP_PKEY_new();
+
+ if (pkey == NULL
+ || !EVP_PKEY_set_type_by_keymgmt(pkey, ctx->keymgmt)
+ || (pkey->keydata = evp_keymgmt_newdata(ctx->keymgmt)) == NULL) {
+ ERR_clear_last_mark();
+ EVP_PKEY_free(pkey);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+ ctx->pkey = pkey;
+ }
+
+ /*
+ * Try to derive the supported exch from |ctx->keymgmt|.
+ */
+ if (!ossl_assert(ctx->pkey->keymgmt == NULL
+ || ctx->pkey->keymgmt == ctx->keymgmt)) {
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ supported_exch = evp_keymgmt_util_query_operation_name(ctx->keymgmt,
+ OSSL_OP_KEYEXCH);
+ if (supported_exch == NULL) {
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+
+
+ /*
+ * We perform two iterations:
+ *
+ * 1. Do the normal exchange fetch, using the fetching data given by
+ * the EVP_PKEY_CTX.
+ * 2. Do the provider specific exchange fetch, from the same provider
+ * as |ctx->keymgmt|
+ *
+ * We then try to fetch the keymgmt from the same provider as the
+ * exchange, and try to export |ctx->pkey| to that keymgmt (when
+ * this keymgmt happens to be the same as |ctx->keymgmt|, the export
+ * is a no-op, but we call it anyway to not complicate the code even
+ * more).
+ * If the export call succeeds (returns a non-NULL provider key pointer),
+ * we're done and can perform the operation itself. If not, we perform
+ * the second iteration, or jump to legacy.
+ */
+ for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) {
+ EVP_KEYMGMT *tmp_keymgmt_tofree = NULL;
+
+ /*
+ * If we're on the second iteration, free the results from the first.
+ * They are NULL on the first iteration, so no need to check what
+ * iteration we're on.
+ */
+ EVP_KEYEXCH_free(exchange);
+ EVP_KEYMGMT_free(tmp_keymgmt);
+
+ switch (iter) {
+ case 1:
+ exchange =
+ EVP_KEYEXCH_fetch(ctx->libctx, supported_exch, ctx->propquery);
+ if (exchange != NULL)
+ tmp_prov = EVP_KEYEXCH_get0_provider(exchange);
+ break;
+ case 2:
+ tmp_prov = EVP_KEYMGMT_get0_provider(ctx->keymgmt);
+ exchange =
+ evp_keyexch_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
+ supported_exch, ctx->propquery);
+ if (exchange == NULL)
+ goto legacy;
+ break;
+ }
+ if (exchange == NULL)
+ continue;
+
+ /*
+ * Ensure that the key is provided, either natively, or as a cached
+ * export. We start by fetching the keymgmt with the same name as
+ * |ctx->keymgmt|, but from the provider of the exchange method, using
+ * the same property query as when fetching the exchange method.
+ * With the keymgmt we found (if we did), we try to export |ctx->pkey|
+ * to it (evp_pkey_export_to_provider() is smart enough to only actually
+ * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt)
+ */
+ tmp_keymgmt_tofree = tmp_keymgmt =
+ evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
+ EVP_KEYMGMT_get0_name(ctx->keymgmt),
+ ctx->propquery);
+ if (tmp_keymgmt != NULL)
+ provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
+ &tmp_keymgmt, ctx->propquery);
+ if (tmp_keymgmt == NULL)
+ EVP_KEYMGMT_free(tmp_keymgmt_tofree);
+ }
+
+ if (provkey == NULL) {
+ EVP_KEYEXCH_free(exchange);
+ goto legacy;
+ }
+
+ ERR_pop_to_mark();
+
+ /* No more legacy from here down to legacy: */
+
+ ctx->op.kex.exchange = exchange;
+ ctx->op.kex.algctx = exchange->newctx(ossl_provider_ctx(exchange->prov));
+ if (ctx->op.kex.algctx == NULL) {
+ /* The provider key can stay in the cache */
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+ ret = exchange->init(ctx->op.kex.algctx, provkey, params);
+
+ EVP_KEYMGMT_free(tmp_keymgmt);
+ return ret ? 1 : 0;
+ err:
+ evp_pkey_ctx_free_old_ops(ctx);
+ ctx->operation = EVP_PKEY_OP_UNDEFINED;
+ EVP_KEYMGMT_free(tmp_keymgmt);
+ return 0;
+
+ legacy:
+ /*
+ * If we don't have the full support we need with provided methods,
+ * let's go see if legacy does.
+ */
+ ERR_pop_to_mark();
+
+#ifdef FIPS_MODULE
+ return 0;
+#else
+ if (ctx->pmeth == NULL || ctx->pmeth->derive == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ if (ctx->pmeth->derive_init == NULL)
+ return 1;
+ ret = ctx->pmeth->derive_init(ctx);
+ if (ret <= 0)
+ ctx->operation = EVP_PKEY_OP_UNDEFINED;
+ EVP_KEYMGMT_free(tmp_keymgmt);
+ return ret;
+#endif
+}
+
+int EVP_PKEY_derive_set_peer_ex(EVP_PKEY_CTX *ctx, EVP_PKEY *peer,
+ int validate_peer)
+{
+ int ret = 0, check;
+ void *provkey = NULL;
+ EVP_PKEY_CTX *check_ctx = NULL;
+ EVP_KEYMGMT *tmp_keymgmt = NULL, *tmp_keymgmt_tofree = NULL;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+
+ if (!EVP_PKEY_CTX_IS_DERIVE_OP(ctx) || ctx->op.kex.algctx == NULL)
+ goto legacy;
+
+ if (ctx->op.kex.exchange->set_peer == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ if (validate_peer) {
+ check_ctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, peer, ctx->propquery);
+ if (check_ctx == NULL)
+ return -1;
+ check = EVP_PKEY_public_check(check_ctx);
+ EVP_PKEY_CTX_free(check_ctx);
+ if (check <= 0)
+ return -1;
+ }
+
+ /*
+ * Ensure that the |peer| is provided, either natively, or as a cached
+ * export. We start by fetching the keymgmt with the same name as
+ * |ctx->keymgmt|, but from the provider of the exchange method, using
+ * the same property query as when fetching the exchange method.
+ * With the keymgmt we found (if we did), we try to export |peer|
+ * to it (evp_pkey_export_to_provider() is smart enough to only actually
+ * export it if |tmp_keymgmt| is different from |peer|'s keymgmt)
+ */
+ tmp_keymgmt_tofree = tmp_keymgmt =
+ evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)
+ EVP_KEYEXCH_get0_provider(ctx->op.kex.exchange),
+ EVP_KEYMGMT_get0_name(ctx->keymgmt),
+ ctx->propquery);
+ if (tmp_keymgmt != NULL)
+ provkey = evp_pkey_export_to_provider(peer, ctx->libctx,
+ &tmp_keymgmt, ctx->propquery);
+ EVP_KEYMGMT_free(tmp_keymgmt_tofree);
+
+ /*
+ * If making the key provided wasn't possible, legacy may be able to pick
+ * it up
+ */
+ if (provkey == NULL)
+ goto legacy;
+ return ctx->op.kex.exchange->set_peer(ctx->op.kex.algctx, provkey);
+
+ legacy:
+#ifdef FIPS_MODULE
+ return ret;
+#else
+ if (ctx->pmeth == NULL
+ || !(ctx->pmeth->derive != NULL
+ || ctx->pmeth->encrypt != NULL
+ || ctx->pmeth->decrypt != NULL)
+ || ctx->pmeth->ctrl == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+ if (ctx->operation != EVP_PKEY_OP_DERIVE
+ && ctx->operation != EVP_PKEY_OP_ENCRYPT
+ && ctx->operation != EVP_PKEY_OP_DECRYPT) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
+ return -1;
+ }
+
+ ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer);
+
+ if (ret <= 0)
+ return ret;
+
+ if (ret == 2)
+ return 1;
+
+ if (ctx->pkey == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET);
+ return -1;
+ }
+
+ if (ctx->pkey->type != peer->type) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
+ return -1;
+ }
+
+ /*
+ * For clarity. The error is if parameters in peer are
+ * present (!missing) but don't match. EVP_PKEY_parameters_eq may return
+ * 1 (match), 0 (don't match) and -2 (comparison is not defined). -1
+ * (different key types) is impossible here because it is checked earlier.
+ * -2 is OK for us here, as well as 1, so we can check for 0 only.
+ */
+ if (!EVP_PKEY_missing_parameters(peer) &&
+ !EVP_PKEY_parameters_eq(ctx->pkey, peer)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_PARAMETERS);
+ return -1;
+ }
+
+ EVP_PKEY_free(ctx->peerkey);
+ ctx->peerkey = peer;
+
+ ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer);
+
+ if (ret <= 0) {
+ ctx->peerkey = NULL;
+ return ret;
+ }
+
+ EVP_PKEY_up_ref(peer);
+ return 1;
+#endif
+}
+
+int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
+{
+ return EVP_PKEY_derive_set_peer_ex(ctx, peer, 1);
+}
+
+int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen)
+{
+ int ret;
+
+ if (ctx == NULL || pkeylen == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+
+ if (!EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
+ return -1;
+ }
+
+ if (ctx->op.kex.algctx == NULL)
+ goto legacy;
+
+ ret = ctx->op.kex.exchange->derive(ctx->op.kex.algctx, key, pkeylen,
+ key != NULL ? *pkeylen : 0);
+
+ return ret;
+ legacy:
+ if (ctx->pmeth == NULL || ctx->pmeth->derive == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ M_check_autoarg(ctx, key, pkeylen, EVP_F_EVP_PKEY_DERIVE)
+ return ctx->pmeth->derive(ctx, key, pkeylen);
+}
+
+int evp_keyexch_get_number(const EVP_KEYEXCH *keyexch)
+{
+ return keyexch->name_id;
+}
+
+const char *EVP_KEYEXCH_get0_name(const EVP_KEYEXCH *keyexch)
+{
+ return keyexch->type_name;
+}
+
+const char *EVP_KEYEXCH_get0_description(const EVP_KEYEXCH *keyexch)
+{
+ return keyexch->description;
+}
+
+int EVP_KEYEXCH_is_a(const EVP_KEYEXCH *keyexch, const char *name)
+{
+ return keyexch != NULL
+ && evp_is_a(keyexch->prov, keyexch->name_id, NULL, name);
+}
+
+void EVP_KEYEXCH_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_KEYEXCH *keyexch, void *arg),
+ void *arg)
+{
+ evp_generic_do_all(libctx, OSSL_OP_KEYEXCH,
+ (void (*)(void *, void *))fn, arg,
+ evp_keyexch_from_algorithm,
+ (int (*)(void *))EVP_KEYEXCH_up_ref,
+ (void (*)(void *))EVP_KEYEXCH_free);
+}
+
+int EVP_KEYEXCH_names_do_all(const EVP_KEYEXCH *keyexch,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (keyexch->prov != NULL)
+ return evp_names_do_all(keyexch->prov, keyexch->name_id, fn, data);
+
+ return 1;
+}
+
+const OSSL_PARAM *EVP_KEYEXCH_gettable_ctx_params(const EVP_KEYEXCH *keyexch)
+{
+ void *provctx;
+
+ if (keyexch == NULL || keyexch->gettable_ctx_params == NULL)
+ return NULL;
+
+ provctx = ossl_provider_ctx(EVP_KEYEXCH_get0_provider(keyexch));
+ return keyexch->gettable_ctx_params(NULL, provctx);
+}
+
+const OSSL_PARAM *EVP_KEYEXCH_settable_ctx_params(const EVP_KEYEXCH *keyexch)
+{
+ void *provctx;
+
+ if (keyexch == NULL || keyexch->settable_ctx_params == NULL)
+ return NULL;
+ provctx = ossl_provider_ctx(EVP_KEYEXCH_get0_provider(keyexch));
+ return keyexch->settable_ctx_params(NULL, provctx);
+}
diff --git a/crypto/evp/kdf_lib.c b/crypto/evp/kdf_lib.c
new file mode 100644
index 000000000000..6a6bb31e6372
--- /dev/null
+++ b/crypto/evp/kdf_lib.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2018-2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "internal/cryptlib.h"
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/core.h>
+#include <openssl/core_names.h>
+#include "crypto/evp.h"
+#include "internal/numbers.h"
+#include "internal/provider.h"
+#include "evp_local.h"
+
+EVP_KDF_CTX *EVP_KDF_CTX_new(EVP_KDF *kdf)
+{
+ EVP_KDF_CTX *ctx = NULL;
+
+ if (kdf == NULL)
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(EVP_KDF_CTX));
+ if (ctx == NULL
+ || (ctx->algctx = kdf->newctx(ossl_provider_ctx(kdf->prov))) == NULL
+ || !EVP_KDF_up_ref(kdf)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ if (ctx != NULL)
+ kdf->freectx(ctx->algctx);
+ OPENSSL_free(ctx);
+ ctx = NULL;
+ } else {
+ ctx->meth = kdf;
+ }
+ return ctx;
+}
+
+void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx)
+{
+ if (ctx == NULL)
+ return;
+ ctx->meth->freectx(ctx->algctx);
+ ctx->algctx = NULL;
+ EVP_KDF_free(ctx->meth);
+ OPENSSL_free(ctx);
+}
+
+EVP_KDF_CTX *EVP_KDF_CTX_dup(const EVP_KDF_CTX *src)
+{
+ EVP_KDF_CTX *dst;
+
+ if (src == NULL || src->algctx == NULL || src->meth->dupctx == NULL)
+ return NULL;
+
+ dst = OPENSSL_malloc(sizeof(*dst));
+ if (dst == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ memcpy(dst, src, sizeof(*dst));
+ if (!EVP_KDF_up_ref(dst->meth)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(dst);
+ return NULL;
+ }
+
+ dst->algctx = src->meth->dupctx(src->algctx);
+ if (dst->algctx == NULL) {
+ EVP_KDF_CTX_free(dst);
+ return NULL;
+ }
+ return dst;
+}
+
+int evp_kdf_get_number(const EVP_KDF *kdf)
+{
+ return kdf->name_id;
+}
+
+const char *EVP_KDF_get0_name(const EVP_KDF *kdf)
+{
+ return kdf->type_name;
+}
+
+const char *EVP_KDF_get0_description(const EVP_KDF *kdf)
+{
+ return kdf->description;
+}
+
+int EVP_KDF_is_a(const EVP_KDF *kdf, const char *name)
+{
+ return kdf != NULL && evp_is_a(kdf->prov, kdf->name_id, NULL, name);
+}
+
+const OSSL_PROVIDER *EVP_KDF_get0_provider(const EVP_KDF *kdf)
+{
+ return kdf->prov;
+}
+
+const EVP_KDF *EVP_KDF_CTX_kdf(EVP_KDF_CTX *ctx)
+{
+ return ctx->meth;
+}
+
+void EVP_KDF_CTX_reset(EVP_KDF_CTX *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ if (ctx->meth->reset != NULL)
+ ctx->meth->reset(ctx->algctx);
+}
+
+size_t EVP_KDF_CTX_get_kdf_size(EVP_KDF_CTX *ctx)
+{
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ size_t s = 0;
+
+ if (ctx == NULL)
+ return 0;
+
+ *params = OSSL_PARAM_construct_size_t(OSSL_KDF_PARAM_SIZE, &s);
+ if (ctx->meth->get_ctx_params != NULL
+ && ctx->meth->get_ctx_params(ctx->algctx, params))
+ return s;
+ if (ctx->meth->get_params != NULL
+ && ctx->meth->get_params(params))
+ return s;
+ return 0;
+}
+
+int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ if (ctx == NULL)
+ return 0;
+
+ return ctx->meth->derive(ctx->algctx, key, keylen, params);
+}
+
+/*
+ * The {get,set}_params functions return 1 if there is no corresponding
+ * function in the implementation. This is the same as if there was one,
+ * but it didn't recognise any of the given params, i.e. nothing in the
+ * bag of parameters was useful.
+ */
+int EVP_KDF_get_params(EVP_KDF *kdf, OSSL_PARAM params[])
+{
+ if (kdf->get_params != NULL)
+ return kdf->get_params(params);
+ return 1;
+}
+
+int EVP_KDF_CTX_get_params(EVP_KDF_CTX *ctx, OSSL_PARAM params[])
+{
+ if (ctx->meth->get_ctx_params != NULL)
+ return ctx->meth->get_ctx_params(ctx->algctx, params);
+ return 1;
+}
+
+int EVP_KDF_CTX_set_params(EVP_KDF_CTX *ctx, const OSSL_PARAM params[])
+{
+ if (ctx->meth->set_ctx_params != NULL)
+ return ctx->meth->set_ctx_params(ctx->algctx, params);
+ return 1;
+}
+
+int EVP_KDF_names_do_all(const EVP_KDF *kdf,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (kdf->prov != NULL)
+ return evp_names_do_all(kdf->prov, kdf->name_id, fn, data);
+
+ return 1;
+}
diff --git a/crypto/evp/kdf_meth.c b/crypto/evp/kdf_meth.c
new file mode 100644
index 000000000000..94af5d40a091
--- /dev/null
+++ b/crypto/evp/kdf_meth.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/kdf.h>
+#include "internal/provider.h"
+#include "internal/core.h"
+#include "crypto/evp.h"
+#include "evp_local.h"
+
+static int evp_kdf_up_ref(void *vkdf)
+{
+ EVP_KDF *kdf = (EVP_KDF *)vkdf;
+ int ref = 0;
+
+ CRYPTO_UP_REF(&kdf->refcnt, &ref, kdf->lock);
+ return 1;
+}
+
+static void evp_kdf_free(void *vkdf)
+{
+ EVP_KDF *kdf = (EVP_KDF *)vkdf;
+ int ref = 0;
+
+ if (kdf == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&kdf->refcnt, &ref, kdf->lock);
+ if (ref > 0)
+ return;
+ OPENSSL_free(kdf->type_name);
+ ossl_provider_free(kdf->prov);
+ CRYPTO_THREAD_lock_free(kdf->lock);
+ OPENSSL_free(kdf);
+}
+
+static void *evp_kdf_new(void)
+{
+ EVP_KDF *kdf = NULL;
+
+ if ((kdf = OPENSSL_zalloc(sizeof(*kdf))) == NULL
+ || (kdf->lock = CRYPTO_THREAD_lock_new()) == NULL) {
+ OPENSSL_free(kdf);
+ return NULL;
+ }
+ kdf->refcnt = 1;
+ return kdf;
+}
+
+static void *evp_kdf_from_algorithm(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
+{
+ const OSSL_DISPATCH *fns = algodef->implementation;
+ EVP_KDF *kdf = NULL;
+ int fnkdfcnt = 0, fnctxcnt = 0;
+
+ if ((kdf = evp_kdf_new()) == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ kdf->name_id = name_id;
+ if ((kdf->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
+ evp_kdf_free(kdf);
+ return NULL;
+ }
+ kdf->description = algodef->algorithm_description;
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_KDF_NEWCTX:
+ if (kdf->newctx != NULL)
+ break;
+ kdf->newctx = OSSL_FUNC_kdf_newctx(fns);
+ fnctxcnt++;
+ break;
+ case OSSL_FUNC_KDF_DUPCTX:
+ if (kdf->dupctx != NULL)
+ break;
+ kdf->dupctx = OSSL_FUNC_kdf_dupctx(fns);
+ break;
+ case OSSL_FUNC_KDF_FREECTX:
+ if (kdf->freectx != NULL)
+ break;
+ kdf->freectx = OSSL_FUNC_kdf_freectx(fns);
+ fnctxcnt++;
+ break;
+ case OSSL_FUNC_KDF_RESET:
+ if (kdf->reset != NULL)
+ break;
+ kdf->reset = OSSL_FUNC_kdf_reset(fns);
+ break;
+ case OSSL_FUNC_KDF_DERIVE:
+ if (kdf->derive != NULL)
+ break;
+ kdf->derive = OSSL_FUNC_kdf_derive(fns);
+ fnkdfcnt++;
+ break;
+ case OSSL_FUNC_KDF_GETTABLE_PARAMS:
+ if (kdf->gettable_params != NULL)
+ break;
+ kdf->gettable_params =
+ OSSL_FUNC_kdf_gettable_params(fns);
+ break;
+ case OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS:
+ if (kdf->gettable_ctx_params != NULL)
+ break;
+ kdf->gettable_ctx_params =
+ OSSL_FUNC_kdf_gettable_ctx_params(fns);
+ break;
+ case OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS:
+ if (kdf->settable_ctx_params != NULL)
+ break;
+ kdf->settable_ctx_params =
+ OSSL_FUNC_kdf_settable_ctx_params(fns);
+ break;
+ case OSSL_FUNC_KDF_GET_PARAMS:
+ if (kdf->get_params != NULL)
+ break;
+ kdf->get_params = OSSL_FUNC_kdf_get_params(fns);
+ break;
+ case OSSL_FUNC_KDF_GET_CTX_PARAMS:
+ if (kdf->get_ctx_params != NULL)
+ break;
+ kdf->get_ctx_params = OSSL_FUNC_kdf_get_ctx_params(fns);
+ break;
+ case OSSL_FUNC_KDF_SET_CTX_PARAMS:
+ if (kdf->set_ctx_params != NULL)
+ break;
+ kdf->set_ctx_params = OSSL_FUNC_kdf_set_ctx_params(fns);
+ break;
+ }
+ }
+ if (fnkdfcnt != 1 || fnctxcnt != 2) {
+ /*
+ * In order to be a consistent set of functions we must have at least
+ * a derive function, and a complete set of context management
+ * functions.
+ */
+ evp_kdf_free(kdf);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+ return NULL;
+ }
+ kdf->prov = prov;
+ if (prov != NULL)
+ ossl_provider_up_ref(prov);
+
+ return kdf;
+}
+
+EVP_KDF *EVP_KDF_fetch(OSSL_LIB_CTX *libctx, const char *algorithm,
+ const char *properties)
+{
+ return evp_generic_fetch(libctx, OSSL_OP_KDF, algorithm, properties,
+ evp_kdf_from_algorithm, evp_kdf_up_ref,
+ evp_kdf_free);
+}
+
+int EVP_KDF_up_ref(EVP_KDF *kdf)
+{
+ return evp_kdf_up_ref(kdf);
+}
+
+void EVP_KDF_free(EVP_KDF *kdf)
+{
+ evp_kdf_free(kdf);
+}
+
+const OSSL_PARAM *EVP_KDF_gettable_params(const EVP_KDF *kdf)
+{
+ if (kdf->gettable_params == NULL)
+ return NULL;
+ return kdf->gettable_params(ossl_provider_ctx(EVP_KDF_get0_provider(kdf)));
+}
+
+const OSSL_PARAM *EVP_KDF_gettable_ctx_params(const EVP_KDF *kdf)
+{
+ void *alg;
+
+ if (kdf->gettable_ctx_params == NULL)
+ return NULL;
+ alg = ossl_provider_ctx(EVP_KDF_get0_provider(kdf));
+ return kdf->gettable_ctx_params(NULL, alg);
+}
+
+const OSSL_PARAM *EVP_KDF_settable_ctx_params(const EVP_KDF *kdf)
+{
+ void *alg;
+
+ if (kdf->settable_ctx_params == NULL)
+ return NULL;
+ alg = ossl_provider_ctx(EVP_KDF_get0_provider(kdf));
+ return kdf->settable_ctx_params(NULL, alg);
+}
+
+const OSSL_PARAM *EVP_KDF_CTX_gettable_params(EVP_KDF_CTX *ctx)
+{
+ void *alg;
+
+ if (ctx->meth->gettable_ctx_params == NULL)
+ return NULL;
+ alg = ossl_provider_ctx(EVP_KDF_get0_provider(ctx->meth));
+ return ctx->meth->gettable_ctx_params(ctx->algctx, alg);
+}
+
+const OSSL_PARAM *EVP_KDF_CTX_settable_params(EVP_KDF_CTX *ctx)
+{
+ void *alg;
+
+ if (ctx->meth->settable_ctx_params == NULL)
+ return NULL;
+ alg = ossl_provider_ctx(EVP_KDF_get0_provider(ctx->meth));
+ return ctx->meth->settable_ctx_params(ctx->algctx, alg);
+}
+
+void EVP_KDF_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_KDF *kdf, void *arg),
+ void *arg)
+{
+ evp_generic_do_all(libctx, OSSL_OP_KDF,
+ (void (*)(void *, void *))fn, arg,
+ evp_kdf_from_algorithm, evp_kdf_up_ref, evp_kdf_free);
+}
diff --git a/crypto/evp/kem.c b/crypto/evp/kem.c
new file mode 100644
index 000000000000..1786ae6553bf
--- /dev/null
+++ b/crypto/evp/kem.c
@@ -0,0 +1,482 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include "internal/cryptlib.h"
+#include "internal/provider.h"
+#include "internal/core.h"
+#include "crypto/evp.h"
+#include "evp_local.h"
+
+static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation,
+ const OSSL_PARAM params[])
+{
+ int ret = 0;
+ EVP_KEM *kem = NULL;
+ EVP_KEYMGMT *tmp_keymgmt = NULL;
+ const OSSL_PROVIDER *tmp_prov = NULL;
+ void *provkey = NULL;
+ const char *supported_kem = NULL;
+ int iter;
+
+ if (ctx == NULL || ctx->keytype == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+
+ evp_pkey_ctx_free_old_ops(ctx);
+ ctx->operation = operation;
+
+ if (ctx->pkey == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET);
+ goto err;
+ }
+
+ /*
+ * Try to derive the supported kem from |ctx->keymgmt|.
+ */
+ if (!ossl_assert(ctx->pkey->keymgmt == NULL
+ || ctx->pkey->keymgmt == ctx->keymgmt)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ supported_kem = evp_keymgmt_util_query_operation_name(ctx->keymgmt,
+ OSSL_OP_KEM);
+ if (supported_kem == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+
+ /*
+ * Because we cleared out old ops, we shouldn't need to worry about
+ * checking if kem is already there.
+ * We perform two iterations:
+ *
+ * 1. Do the normal kem fetch, using the fetching data given by
+ * the EVP_PKEY_CTX.
+ * 2. Do the provider specific kem fetch, from the same provider
+ * as |ctx->keymgmt|
+ *
+ * We then try to fetch the keymgmt from the same provider as the
+ * kem, and try to export |ctx->pkey| to that keymgmt (when this
+ * keymgmt happens to be the same as |ctx->keymgmt|, the export is
+ * a no-op, but we call it anyway to not complicate the code even
+ * more).
+ * If the export call succeeds (returns a non-NULL provider key pointer),
+ * we're done and can perform the operation itself. If not, we perform
+ * the second iteration, or jump to legacy.
+ */
+ for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) {
+ EVP_KEYMGMT *tmp_keymgmt_tofree = NULL;
+
+ /*
+ * If we're on the second iteration, free the results from the first.
+ * They are NULL on the first iteration, so no need to check what
+ * iteration we're on.
+ */
+ EVP_KEM_free(kem);
+ EVP_KEYMGMT_free(tmp_keymgmt);
+
+ switch (iter) {
+ case 1:
+ kem = EVP_KEM_fetch(ctx->libctx, supported_kem, ctx->propquery);
+ if (kem != NULL)
+ tmp_prov = EVP_KEM_get0_provider(kem);
+ break;
+ case 2:
+ tmp_prov = EVP_KEYMGMT_get0_provider(ctx->keymgmt);
+ kem = evp_kem_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
+ supported_kem, ctx->propquery);
+
+ if (kem == NULL) {
+ ERR_raise(ERR_LIB_EVP,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ ret = -2;
+ goto err;
+ }
+ }
+ if (kem == NULL)
+ continue;
+
+ /*
+ * Ensure that the key is provided, either natively, or as a cached
+ * export. We start by fetching the keymgmt with the same name as
+ * |ctx->pkey|, but from the provider of the kem method, using the
+ * same property query as when fetching the kem method.
+ * With the keymgmt we found (if we did), we try to export |ctx->pkey|
+ * to it (evp_pkey_export_to_provider() is smart enough to only actually
+
+ * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt)
+ */
+ tmp_keymgmt_tofree = tmp_keymgmt =
+ evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
+ EVP_KEYMGMT_get0_name(ctx->keymgmt),
+ ctx->propquery);
+ if (tmp_keymgmt != NULL)
+ provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
+ &tmp_keymgmt, ctx->propquery);
+ if (tmp_keymgmt == NULL)
+ EVP_KEYMGMT_free(tmp_keymgmt_tofree);
+ }
+
+ if (provkey == NULL) {
+ EVP_KEM_free(kem);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+
+ ctx->op.encap.kem = kem;
+ ctx->op.encap.algctx = kem->newctx(ossl_provider_ctx(kem->prov));
+ if (ctx->op.encap.algctx == NULL) {
+ /* The provider key can stay in the cache */
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+
+ switch (operation) {
+ case EVP_PKEY_OP_ENCAPSULATE:
+ if (kem->encapsulate_init == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ ret = -2;
+ goto err;
+ }
+ ret = kem->encapsulate_init(ctx->op.encap.algctx, provkey, params);
+ break;
+ case EVP_PKEY_OP_DECAPSULATE:
+ if (kem->decapsulate_init == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ ret = -2;
+ goto err;
+ }
+ ret = kem->decapsulate_init(ctx->op.encap.algctx, provkey, params);
+ break;
+ default:
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+
+ EVP_KEYMGMT_free(tmp_keymgmt);
+ tmp_keymgmt = NULL;
+
+ if (ret > 0)
+ return 1;
+ err:
+ if (ret <= 0) {
+ evp_pkey_ctx_free_old_ops(ctx);
+ ctx->operation = EVP_PKEY_OP_UNDEFINED;
+ }
+ EVP_KEYMGMT_free(tmp_keymgmt);
+ return ret;
+}
+
+int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
+{
+ return evp_kem_init(ctx, EVP_PKEY_OP_ENCAPSULATE, params);
+}
+
+int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx,
+ unsigned char *out, size_t *outlen,
+ unsigned char *secret, size_t *secretlen)
+{
+ if (ctx == NULL)
+ return 0;
+
+ if (ctx->operation != EVP_PKEY_OP_ENCAPSULATE) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
+ return -1;
+ }
+
+ if (ctx->op.encap.algctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ if (out != NULL && secret == NULL)
+ return 0;
+
+ return ctx->op.encap.kem->encapsulate(ctx->op.encap.algctx,
+ out, outlen, secret, secretlen);
+}
+
+int EVP_PKEY_decapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
+{
+ return evp_kem_init(ctx, EVP_PKEY_OP_DECAPSULATE, params);
+}
+
+int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx,
+ unsigned char *secret, size_t *secretlen,
+ const unsigned char *in, size_t inlen)
+{
+ if (ctx == NULL
+ || (in == NULL || inlen == 0)
+ || (secret == NULL && secretlen == NULL))
+ return 0;
+
+ if (ctx->operation != EVP_PKEY_OP_DECAPSULATE) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
+ return -1;
+ }
+
+ if (ctx->op.encap.algctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+ return ctx->op.encap.kem->decapsulate(ctx->op.encap.algctx,
+ secret, secretlen, in, inlen);
+}
+
+static EVP_KEM *evp_kem_new(OSSL_PROVIDER *prov)
+{
+ EVP_KEM *kem = OPENSSL_zalloc(sizeof(EVP_KEM));
+
+ if (kem == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ kem->lock = CRYPTO_THREAD_lock_new();
+ if (kem->lock == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(kem);
+ return NULL;
+ }
+ kem->prov = prov;
+ ossl_provider_up_ref(prov);
+ kem->refcnt = 1;
+
+ return kem;
+}
+
+static void *evp_kem_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
+{
+ const OSSL_DISPATCH *fns = algodef->implementation;
+ EVP_KEM *kem = NULL;
+ int ctxfncnt = 0, encfncnt = 0, decfncnt = 0;
+ int gparamfncnt = 0, sparamfncnt = 0;
+
+ if ((kem = evp_kem_new(prov)) == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ kem->name_id = name_id;
+ if ((kem->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL)
+ goto err;
+ kem->description = algodef->algorithm_description;
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_KEM_NEWCTX:
+ if (kem->newctx != NULL)
+ break;
+ kem->newctx = OSSL_FUNC_kem_newctx(fns);
+ ctxfncnt++;
+ break;
+ case OSSL_FUNC_KEM_ENCAPSULATE_INIT:
+ if (kem->encapsulate_init != NULL)
+ break;
+ kem->encapsulate_init = OSSL_FUNC_kem_encapsulate_init(fns);
+ encfncnt++;
+ break;
+ case OSSL_FUNC_KEM_ENCAPSULATE:
+ if (kem->encapsulate != NULL)
+ break;
+ kem->encapsulate = OSSL_FUNC_kem_encapsulate(fns);
+ encfncnt++;
+ break;
+ case OSSL_FUNC_KEM_DECAPSULATE_INIT:
+ if (kem->decapsulate_init != NULL)
+ break;
+ kem->decapsulate_init = OSSL_FUNC_kem_decapsulate_init(fns);
+ decfncnt++;
+ break;
+ case OSSL_FUNC_KEM_DECAPSULATE:
+ if (kem->decapsulate != NULL)
+ break;
+ kem->decapsulate = OSSL_FUNC_kem_decapsulate(fns);
+ decfncnt++;
+ break;
+ case OSSL_FUNC_KEM_FREECTX:
+ if (kem->freectx != NULL)
+ break;
+ kem->freectx = OSSL_FUNC_kem_freectx(fns);
+ ctxfncnt++;
+ break;
+ case OSSL_FUNC_KEM_DUPCTX:
+ if (kem->dupctx != NULL)
+ break;
+ kem->dupctx = OSSL_FUNC_kem_dupctx(fns);
+ break;
+ case OSSL_FUNC_KEM_GET_CTX_PARAMS:
+ if (kem->get_ctx_params != NULL)
+ break;
+ kem->get_ctx_params
+ = OSSL_FUNC_kem_get_ctx_params(fns);
+ gparamfncnt++;
+ break;
+ case OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS:
+ if (kem->gettable_ctx_params != NULL)
+ break;
+ kem->gettable_ctx_params
+ = OSSL_FUNC_kem_gettable_ctx_params(fns);
+ gparamfncnt++;
+ break;
+ case OSSL_FUNC_KEM_SET_CTX_PARAMS:
+ if (kem->set_ctx_params != NULL)
+ break;
+ kem->set_ctx_params
+ = OSSL_FUNC_kem_set_ctx_params(fns);
+ sparamfncnt++;
+ break;
+ case OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS:
+ if (kem->settable_ctx_params != NULL)
+ break;
+ kem->settable_ctx_params
+ = OSSL_FUNC_kem_settable_ctx_params(fns);
+ sparamfncnt++;
+ break;
+ }
+ }
+ if (ctxfncnt != 2
+ || (encfncnt != 0 && encfncnt != 2)
+ || (decfncnt != 0 && decfncnt != 2)
+ || (encfncnt != 2 && decfncnt != 2)
+ || (gparamfncnt != 0 && gparamfncnt != 2)
+ || (sparamfncnt != 0 && sparamfncnt != 2)) {
+ /*
+ * In order to be a consistent set of functions we must have at least
+ * a set of context functions (newctx and freectx) as well as a pair of
+ * "kem" functions: (encapsulate_init, encapsulate) or
+ * (decapsulate_init, decapsulate). set_ctx_params and settable_ctx_params are
+ * optional, but if one of them is present then the other one must also
+ * be present. The same applies to get_ctx_params and
+ * gettable_ctx_params. The dupctx function is optional.
+ */
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+ goto err;
+ }
+
+ return kem;
+ err:
+ EVP_KEM_free(kem);
+ return NULL;
+}
+
+void EVP_KEM_free(EVP_KEM *kem)
+{
+ int i;
+
+ if (kem == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&kem->refcnt, &i, kem->lock);
+ if (i > 0)
+ return;
+ OPENSSL_free(kem->type_name);
+ ossl_provider_free(kem->prov);
+ CRYPTO_THREAD_lock_free(kem->lock);
+ OPENSSL_free(kem);
+}
+
+int EVP_KEM_up_ref(EVP_KEM *kem)
+{
+ int ref = 0;
+
+ CRYPTO_UP_REF(&kem->refcnt, &ref, kem->lock);
+ return 1;
+}
+
+OSSL_PROVIDER *EVP_KEM_get0_provider(const EVP_KEM *kem)
+{
+ return kem->prov;
+}
+
+EVP_KEM *EVP_KEM_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties)
+{
+ return evp_generic_fetch(ctx, OSSL_OP_KEM, algorithm, properties,
+ evp_kem_from_algorithm,
+ (int (*)(void *))EVP_KEM_up_ref,
+ (void (*)(void *))EVP_KEM_free);
+}
+
+EVP_KEM *evp_kem_fetch_from_prov(OSSL_PROVIDER *prov, const char *algorithm,
+ const char *properties)
+{
+ return evp_generic_fetch_from_prov(prov, OSSL_OP_KEM, algorithm, properties,
+ evp_kem_from_algorithm,
+ (int (*)(void *))EVP_KEM_up_ref,
+ (void (*)(void *))EVP_KEM_free);
+}
+
+int EVP_KEM_is_a(const EVP_KEM *kem, const char *name)
+{
+ return kem != NULL && evp_is_a(kem->prov, kem->name_id, NULL, name);
+}
+
+int evp_kem_get_number(const EVP_KEM *kem)
+{
+ return kem->name_id;
+}
+
+const char *EVP_KEM_get0_name(const EVP_KEM *kem)
+{
+ return kem->type_name;
+}
+
+const char *EVP_KEM_get0_description(const EVP_KEM *kem)
+{
+ return kem->description;
+}
+
+void EVP_KEM_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_KEM *kem, void *arg),
+ void *arg)
+{
+ evp_generic_do_all(libctx, OSSL_OP_KEM, (void (*)(void *, void *))fn, arg,
+ evp_kem_from_algorithm,
+ (int (*)(void *))EVP_KEM_up_ref,
+ (void (*)(void *))EVP_KEM_free);
+}
+
+int EVP_KEM_names_do_all(const EVP_KEM *kem,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (kem->prov != NULL)
+ return evp_names_do_all(kem->prov, kem->name_id, fn, data);
+
+ return 1;
+}
+
+const OSSL_PARAM *EVP_KEM_gettable_ctx_params(const EVP_KEM *kem)
+{
+ void *provctx;
+
+ if (kem == NULL || kem->gettable_ctx_params == NULL)
+ return NULL;
+
+ provctx = ossl_provider_ctx(EVP_KEM_get0_provider(kem));
+ return kem->gettable_ctx_params(NULL, provctx);
+}
+
+const OSSL_PARAM *EVP_KEM_settable_ctx_params(const EVP_KEM *kem)
+{
+ void *provctx;
+
+ if (kem == NULL || kem->settable_ctx_params == NULL)
+ return NULL;
+
+ provctx = ossl_provider_ctx(EVP_KEM_get0_provider(kem));
+ return kem->settable_ctx_params(NULL, provctx);
+}
diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c
new file mode 100644
index 000000000000..8369d9578cbd
--- /dev/null
+++ b/crypto/evp/keymgmt_lib.c
@@ -0,0 +1,589 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_names.h>
+#include "internal/cryptlib.h"
+#include "internal/nelem.h"
+#include "crypto/evp.h"
+#include "internal/core.h"
+#include "internal/provider.h"
+#include "evp_local.h"
+
+/*
+ * match_type() checks if two EVP_KEYMGMT are matching key types. This
+ * function assumes that the caller has made all the necessary NULL checks.
+ */
+static int match_type(const EVP_KEYMGMT *keymgmt1, const EVP_KEYMGMT *keymgmt2)
+{
+ const char *name2 = EVP_KEYMGMT_get0_name(keymgmt2);
+
+ return EVP_KEYMGMT_is_a(keymgmt1, name2);
+}
+
+int evp_keymgmt_util_try_import(const OSSL_PARAM params[], void *arg)
+{
+ struct evp_keymgmt_util_try_import_data_st *data = arg;
+ int delete_on_error = 0;
+
+ /* Just in time creation of keydata */
+ if (data->keydata == NULL) {
+ if ((data->keydata = evp_keymgmt_newdata(data->keymgmt)) == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ delete_on_error = 1;
+ }
+
+ /*
+ * It's fine if there was no data to transfer, we just end up with an
+ * empty destination key.
+ */
+ if (params[0].key == NULL)
+ return 1;
+
+ if (evp_keymgmt_import(data->keymgmt, data->keydata, data->selection,
+ params))
+ return 1;
+ if (delete_on_error) {
+ evp_keymgmt_freedata(data->keymgmt, data->keydata);
+ data->keydata = NULL;
+ }
+ return 0;
+}
+
+int evp_keymgmt_util_assign_pkey(EVP_PKEY *pkey, EVP_KEYMGMT *keymgmt,
+ void *keydata)
+{
+ if (pkey == NULL || keymgmt == NULL || keydata == NULL
+ || !EVP_PKEY_set_type_by_keymgmt(pkey, keymgmt)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ pkey->keydata = keydata;
+ evp_keymgmt_util_cache_keyinfo(pkey);
+ return 1;
+}
+
+EVP_PKEY *evp_keymgmt_util_make_pkey(EVP_KEYMGMT *keymgmt, void *keydata)
+{
+ EVP_PKEY *pkey = NULL;
+
+ if (keymgmt == NULL
+ || keydata == NULL
+ || (pkey = EVP_PKEY_new()) == NULL
+ || !evp_keymgmt_util_assign_pkey(pkey, keymgmt, keydata)) {
+ EVP_PKEY_free(pkey);
+ return NULL;
+ }
+ return pkey;
+}
+
+int evp_keymgmt_util_export(const EVP_PKEY *pk, int selection,
+ OSSL_CALLBACK *export_cb, void *export_cbarg)
+{
+ if (pk == NULL || export_cb == NULL)
+ return 0;
+ return evp_keymgmt_export(pk->keymgmt, pk->keydata, selection,
+ export_cb, export_cbarg);
+}
+
+void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
+ int selection)
+{
+ struct evp_keymgmt_util_try_import_data_st import_data;
+ OP_CACHE_ELEM *op;
+
+ /* Export to where? */
+ if (keymgmt == NULL)
+ return NULL;
+
+ /* If we have an unassigned key, give up */
+ if (pk->keydata == NULL)
+ return NULL;
+
+ /*
+ * If |keymgmt| matches the "origin" |keymgmt|, there is no more to do.
+ * The "origin" is determined by the |keymgmt| pointers being identical
+ * or when the provider and the name ID match. The latter case handles the
+ * situation where the fetch cache is flushed and a "new" key manager is
+ * created.
+ */
+ if (pk->keymgmt == keymgmt
+ || (pk->keymgmt->name_id == keymgmt->name_id
+ && pk->keymgmt->prov == keymgmt->prov))
+ return pk->keydata;
+
+ if (!CRYPTO_THREAD_read_lock(pk->lock))
+ return NULL;
+ /*
+ * If the provider native "origin" hasn't changed since last time, we
+ * try to find our keymgmt in the operation cache. If it has changed
+ * and our keymgmt isn't found, we will clear the cache further down.
+ */
+ if (pk->dirty_cnt == pk->dirty_cnt_copy) {
+ /* If this key is already exported to |keymgmt|, no more to do */
+ op = evp_keymgmt_util_find_operation_cache(pk, keymgmt, selection);
+ if (op != NULL && op->keymgmt != NULL) {
+ void *ret = op->keydata;
+
+ CRYPTO_THREAD_unlock(pk->lock);
+ return ret;
+ }
+ }
+ CRYPTO_THREAD_unlock(pk->lock);
+
+ /* If the "origin" |keymgmt| doesn't support exporting, give up */
+ if (pk->keymgmt->export == NULL)
+ return NULL;
+
+ /*
+ * Make sure that the type of the keymgmt to export to matches the type
+ * of the "origin"
+ */
+ if (!ossl_assert(match_type(pk->keymgmt, keymgmt)))
+ return NULL;
+
+ /*
+ * We look at the already cached provider keys, and import from the
+ * first that supports it (i.e. use its export function), and export
+ * the imported data to the new provider.
+ */
+
+ /* Setup for the export callback */
+ import_data.keydata = NULL; /* evp_keymgmt_util_try_import will create it */
+ import_data.keymgmt = keymgmt;
+ import_data.selection = selection;
+
+ /*
+ * The export function calls the callback (evp_keymgmt_util_try_import),
+ * which does the import for us. If successful, we're done.
+ */
+ if (!evp_keymgmt_util_export(pk, selection,
+ &evp_keymgmt_util_try_import, &import_data))
+ /* If there was an error, bail out */
+ return NULL;
+
+ if (!CRYPTO_THREAD_write_lock(pk->lock)) {
+ evp_keymgmt_freedata(keymgmt, import_data.keydata);
+ return NULL;
+ }
+ /* Check to make sure some other thread didn't get there first */
+ op = evp_keymgmt_util_find_operation_cache(pk, keymgmt, selection);
+ if (op != NULL && op->keydata != NULL) {
+ void *ret = op->keydata;
+
+ CRYPTO_THREAD_unlock(pk->lock);
+
+ /*
+ * Another thread seemms to have already exported this so we abandon
+ * all the work we just did.
+ */
+ evp_keymgmt_freedata(keymgmt, import_data.keydata);
+
+ return ret;
+ }
+
+ /*
+ * If the dirty counter changed since last time, then clear the
+ * operation cache. In that case, we know that |i| is zero.
+ */
+ if (pk->dirty_cnt != pk->dirty_cnt_copy)
+ evp_keymgmt_util_clear_operation_cache(pk, 0);
+
+ /* Add the new export to the operation cache */
+ if (!evp_keymgmt_util_cache_keydata(pk, keymgmt, import_data.keydata,
+ selection)) {
+ CRYPTO_THREAD_unlock(pk->lock);
+ evp_keymgmt_freedata(keymgmt, import_data.keydata);
+ return NULL;
+ }
+
+ /* Synchronize the dirty count */
+ pk->dirty_cnt_copy = pk->dirty_cnt;
+
+ CRYPTO_THREAD_unlock(pk->lock);
+
+ return import_data.keydata;
+}
+
+static void op_cache_free(OP_CACHE_ELEM *e)
+{
+ evp_keymgmt_freedata(e->keymgmt, e->keydata);
+ EVP_KEYMGMT_free(e->keymgmt);
+ OPENSSL_free(e);
+}
+
+int evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk, int locking)
+{
+ if (pk != NULL) {
+ if (locking && pk->lock != NULL && !CRYPTO_THREAD_write_lock(pk->lock))
+ return 0;
+ sk_OP_CACHE_ELEM_pop_free(pk->operation_cache, op_cache_free);
+ pk->operation_cache = NULL;
+ if (locking && pk->lock != NULL)
+ CRYPTO_THREAD_unlock(pk->lock);
+ }
+
+ return 1;
+}
+
+OP_CACHE_ELEM *evp_keymgmt_util_find_operation_cache(EVP_PKEY *pk,
+ EVP_KEYMGMT *keymgmt,
+ int selection)
+{
+ int i, end = sk_OP_CACHE_ELEM_num(pk->operation_cache);
+ OP_CACHE_ELEM *p;
+
+ /*
+ * A comparison and sk_P_CACHE_ELEM_find() are avoided to not cause
+ * problems when we've only a read lock.
+ */
+ for (i = 0; i < end; i++) {
+ p = sk_OP_CACHE_ELEM_value(pk->operation_cache, i);
+ if (keymgmt == p->keymgmt && (p->selection & selection) == selection)
+ return p;
+ }
+ return NULL;
+}
+
+int evp_keymgmt_util_cache_keydata(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
+ void *keydata, int selection)
+{
+ OP_CACHE_ELEM *p = NULL;
+
+ if (keydata != NULL) {
+ if (pk->operation_cache == NULL) {
+ pk->operation_cache = sk_OP_CACHE_ELEM_new_null();
+ if (pk->operation_cache == NULL)
+ return 0;
+ }
+
+ p = OPENSSL_malloc(sizeof(*p));
+ if (p == NULL)
+ return 0;
+ p->keydata = keydata;
+ p->keymgmt = keymgmt;
+ p->selection = selection;
+
+ if (!EVP_KEYMGMT_up_ref(keymgmt)) {
+ OPENSSL_free(p);
+ return 0;
+ }
+
+ if (!sk_OP_CACHE_ELEM_push(pk->operation_cache, p)) {
+ EVP_KEYMGMT_free(keymgmt);
+ OPENSSL_free(p);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk)
+{
+ /*
+ * Cache information about the provider "origin" key.
+ *
+ * This services functions like EVP_PKEY_get_size, EVP_PKEY_get_bits, etc
+ */
+ if (pk->keydata != NULL) {
+ int bits = 0;
+ int security_bits = 0;
+ int size = 0;
+ OSSL_PARAM params[4];
+
+ params[0] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_BITS, &bits);
+ params[1] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_SECURITY_BITS,
+ &security_bits);
+ params[2] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_MAX_SIZE, &size);
+ params[3] = OSSL_PARAM_construct_end();
+ if (evp_keymgmt_get_params(pk->keymgmt, pk->keydata, params)) {
+ pk->cache.size = size;
+ pk->cache.bits = bits;
+ pk->cache.security_bits = security_bits;
+ }
+ }
+}
+
+void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
+ int selection, const OSSL_PARAM params[])
+{
+ void *keydata = NULL;
+
+ if ((keydata = evp_keymgmt_newdata(keymgmt)) == NULL
+ || !evp_keymgmt_import(keymgmt, keydata, selection, params)
+ || !evp_keymgmt_util_assign_pkey(target, keymgmt, keydata)) {
+ evp_keymgmt_freedata(keymgmt, keydata);
+ keydata = NULL;
+ }
+ return keydata;
+}
+
+int evp_keymgmt_util_has(EVP_PKEY *pk, int selection)
+{
+ /* Check if key is even assigned */
+ if (pk->keymgmt == NULL)
+ return 0;
+
+ return evp_keymgmt_has(pk->keymgmt, pk->keydata, selection);
+}
+
+/*
+ * evp_keymgmt_util_match() doesn't just look at the provider side "origin",
+ * but also in the operation cache to see if there's any common keymgmt that
+ * supplies OP_keymgmt_match.
+ *
+ * evp_keymgmt_util_match() adheres to the return values that EVP_PKEY_eq()
+ * and EVP_PKEY_parameters_eq() return, i.e.:
+ *
+ * 1 same key
+ * 0 not same key
+ * -1 not same key type
+ * -2 unsupported operation
+ */
+int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection)
+{
+ EVP_KEYMGMT *keymgmt1 = NULL, *keymgmt2 = NULL;
+ void *keydata1 = NULL, *keydata2 = NULL;
+
+ if (pk1 == NULL || pk2 == NULL) {
+ if (pk1 == NULL && pk2 == NULL)
+ return 1;
+ return 0;
+ }
+
+ keymgmt1 = pk1->keymgmt;
+ keydata1 = pk1->keydata;
+ keymgmt2 = pk2->keymgmt;
+ keydata2 = pk2->keydata;
+
+ if (keymgmt1 != keymgmt2) {
+ /*
+ * The condition for a successful cross export is that the
+ * keydata to be exported is NULL (typed, but otherwise empty
+ * EVP_PKEY), or that it was possible to export it with
+ * evp_keymgmt_util_export_to_provider().
+ *
+ * We use |ok| to determine if it's ok to cross export one way,
+ * but also to determine if we should attempt a cross export
+ * the other way. There's no point doing it both ways.
+ */
+ int ok = 0;
+
+ /* Complex case, where the keymgmt differ */
+ if (keymgmt1 != NULL
+ && keymgmt2 != NULL
+ && !match_type(keymgmt1, keymgmt2)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
+ return -1; /* Not the same type */
+ }
+
+ /*
+ * The key types are determined to match, so we try cross export,
+ * but only to keymgmt's that supply a matching function.
+ */
+ if (keymgmt2 != NULL
+ && keymgmt2->match != NULL) {
+ void *tmp_keydata = NULL;
+
+ ok = 1;
+ if (keydata1 != NULL) {
+ tmp_keydata =
+ evp_keymgmt_util_export_to_provider(pk1, keymgmt2,
+ selection);
+ ok = (tmp_keydata != NULL);
+ }
+ if (ok) {
+ keymgmt1 = keymgmt2;
+ keydata1 = tmp_keydata;
+ }
+ }
+ /*
+ * If we've successfully cross exported one way, there's no point
+ * doing it the other way, hence the |!ok| check.
+ */
+ if (!ok
+ && keymgmt1 != NULL
+ && keymgmt1->match != NULL) {
+ void *tmp_keydata = NULL;
+
+ ok = 1;
+ if (keydata2 != NULL) {
+ tmp_keydata =
+ evp_keymgmt_util_export_to_provider(pk2, keymgmt1,
+ selection);
+ ok = (tmp_keydata != NULL);
+ }
+ if (ok) {
+ keymgmt2 = keymgmt1;
+ keydata2 = tmp_keydata;
+ }
+ }
+ }
+
+ /* If we still don't have matching keymgmt implementations, we give up */
+ if (keymgmt1 != keymgmt2)
+ return -2;
+
+ /* If both keydata are NULL, then they're the same key */
+ if (keydata1 == NULL && keydata2 == NULL)
+ return 1;
+ /* If only one of the keydata is NULL, then they're different keys */
+ if (keydata1 == NULL || keydata2 == NULL)
+ return 0;
+ /* If both keydata are non-NULL, we let the backend decide */
+ return evp_keymgmt_match(keymgmt1, keydata1, keydata2, selection);
+}
+
+int evp_keymgmt_util_copy(EVP_PKEY *to, EVP_PKEY *from, int selection)
+{
+ /* Save copies of pointers we want to play with without affecting |to| */
+ EVP_KEYMGMT *to_keymgmt = to->keymgmt;
+ void *to_keydata = to->keydata, *alloc_keydata = NULL;
+
+ /* An unassigned key can't be copied */
+ if (from == NULL || from->keydata == NULL)
+ return 0;
+
+ /*
+ * If |to| is unassigned, ensure it gets the same KEYMGMT as |from|,
+ * Note that the final setting of KEYMGMT is done further down, with
+ * EVP_PKEY_set_type_by_keymgmt(); we don't want to do that prematurely.
+ */
+ if (to_keymgmt == NULL)
+ to_keymgmt = from->keymgmt;
+
+ if (to_keymgmt == from->keymgmt && to_keymgmt->dup != NULL
+ && to_keydata == NULL) {
+ to_keydata = alloc_keydata = evp_keymgmt_dup(to_keymgmt,
+ from->keydata,
+ selection);
+ if (to_keydata == NULL)
+ return 0;
+ } else if (match_type(to_keymgmt, from->keymgmt)) {
+ struct evp_keymgmt_util_try_import_data_st import_data;
+
+ import_data.keymgmt = to_keymgmt;
+ import_data.keydata = to_keydata;
+ import_data.selection = selection;
+
+ if (!evp_keymgmt_util_export(from, selection,
+ &evp_keymgmt_util_try_import,
+ &import_data))
+ return 0;
+
+ /*
+ * In case to_keydata was previously unallocated,
+ * evp_keymgmt_util_try_import() may have created it for us.
+ */
+ if (to_keydata == NULL)
+ to_keydata = alloc_keydata = import_data.keydata;
+ } else {
+ ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
+ return 0;
+ }
+
+ /*
+ * We only need to set the |to| type when its |keymgmt| isn't set.
+ * We can then just set its |keydata| to what we have, which might
+ * be exactly what it had when entering this function.
+ * This is a bit different from using evp_keymgmt_util_assign_pkey(),
+ * which isn't as careful with |to|'s original |keymgmt|, since it's
+ * meant to forcibly reassign an EVP_PKEY no matter what, which is
+ * why we don't use that one here.
+ */
+ if (to->keymgmt == NULL
+ && !EVP_PKEY_set_type_by_keymgmt(to, to_keymgmt)) {
+ evp_keymgmt_freedata(to_keymgmt, alloc_keydata);
+ return 0;
+ }
+ to->keydata = to_keydata;
+ evp_keymgmt_util_cache_keyinfo(to);
+
+ return 1;
+}
+
+void *evp_keymgmt_util_gen(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
+ void *genctx, OSSL_CALLBACK *cb, void *cbarg)
+{
+ void *keydata = NULL;
+
+ if ((keydata = evp_keymgmt_gen(keymgmt, genctx, cb, cbarg)) == NULL
+ || !evp_keymgmt_util_assign_pkey(target, keymgmt, keydata)) {
+ evp_keymgmt_freedata(keymgmt, keydata);
+ keydata = NULL;
+ }
+
+ return keydata;
+}
+
+/*
+ * Returns the same numbers as EVP_PKEY_get_default_digest_name()
+ * When the string from the EVP_KEYMGMT implementation is "", we use
+ * SN_undef, since that corresponds to what EVP_PKEY_get_default_nid()
+ * returns for no digest.
+ */
+int evp_keymgmt_util_get_deflt_digest_name(EVP_KEYMGMT *keymgmt,
+ void *keydata,
+ char *mdname, size_t mdname_sz)
+{
+ OSSL_PARAM params[3];
+ char mddefault[100] = "";
+ char mdmandatory[100] = "";
+ char *result = NULL;
+ int rv = -2;
+
+ params[0] =
+ OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST,
+ mddefault, sizeof(mddefault));
+ params[1] =
+ OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST,
+ mdmandatory,
+ sizeof(mdmandatory));
+ params[2] = OSSL_PARAM_construct_end();
+
+ if (!evp_keymgmt_get_params(keymgmt, keydata, params))
+ return 0;
+
+ if (OSSL_PARAM_modified(params + 1)) {
+ if (params[1].return_size <= 1) /* Only a NUL byte */
+ result = SN_undef;
+ else
+ result = mdmandatory;
+ rv = 2;
+ } else if (OSSL_PARAM_modified(params)) {
+ if (params[0].return_size <= 1) /* Only a NUL byte */
+ result = SN_undef;
+ else
+ result = mddefault;
+ rv = 1;
+ }
+ if (rv > 0)
+ OPENSSL_strlcpy(mdname, result, mdname_sz);
+ return rv;
+}
+
+/*
+ * If |keymgmt| has the method function |query_operation_name|, use it to get
+ * the name of a supported operation identity. Otherwise, return the keytype,
+ * assuming that it works as a default operation name.
+ */
+const char *evp_keymgmt_util_query_operation_name(EVP_KEYMGMT *keymgmt,
+ int op_id)
+{
+ const char *name = NULL;
+
+ if (keymgmt != NULL) {
+ if (keymgmt->query_operation_name != NULL)
+ name = keymgmt->query_operation_name(op_id);
+ if (name == NULL)
+ name = EVP_KEYMGMT_get0_name(keymgmt);
+ }
+ return name;
+}
diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c
new file mode 100644
index 000000000000..90fd8068dc42
--- /dev/null
+++ b/crypto/evp/keymgmt_meth.c
@@ -0,0 +1,496 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include "internal/provider.h"
+#include "internal/refcount.h"
+#include "internal/core.h"
+#include "crypto/evp.h"
+#include "evp_local.h"
+
+static void *keymgmt_new(void)
+{
+ EVP_KEYMGMT *keymgmt = NULL;
+
+ if ((keymgmt = OPENSSL_zalloc(sizeof(*keymgmt))) == NULL
+ || (keymgmt->lock = CRYPTO_THREAD_lock_new()) == NULL) {
+ EVP_KEYMGMT_free(keymgmt);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ keymgmt->refcnt = 1;
+
+ return keymgmt;
+}
+
+static void *keymgmt_from_algorithm(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
+{
+ const OSSL_DISPATCH *fns = algodef->implementation;
+ EVP_KEYMGMT *keymgmt = NULL;
+ int setparamfncnt = 0, getparamfncnt = 0;
+ int setgenparamfncnt = 0;
+ int importfncnt = 0, exportfncnt = 0;
+
+ if ((keymgmt = keymgmt_new()) == NULL)
+ return NULL;
+
+ keymgmt->name_id = name_id;
+ if ((keymgmt->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
+ EVP_KEYMGMT_free(keymgmt);
+ return NULL;
+ }
+ keymgmt->description = algodef->algorithm_description;
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_KEYMGMT_NEW:
+ if (keymgmt->new == NULL)
+ keymgmt->new = OSSL_FUNC_keymgmt_new(fns);
+ break;
+ case OSSL_FUNC_KEYMGMT_GEN_INIT:
+ if (keymgmt->gen_init == NULL)
+ keymgmt->gen_init = OSSL_FUNC_keymgmt_gen_init(fns);
+ break;
+ case OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE:
+ if (keymgmt->gen_set_template == NULL)
+ keymgmt->gen_set_template =
+ OSSL_FUNC_keymgmt_gen_set_template(fns);
+ break;
+ case OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS:
+ if (keymgmt->gen_set_params == NULL) {
+ setgenparamfncnt++;
+ keymgmt->gen_set_params =
+ OSSL_FUNC_keymgmt_gen_set_params(fns);
+ }
+ break;
+ case OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS:
+ if (keymgmt->gen_settable_params == NULL) {
+ setgenparamfncnt++;
+ keymgmt->gen_settable_params =
+ OSSL_FUNC_keymgmt_gen_settable_params(fns);
+ }
+ break;
+ case OSSL_FUNC_KEYMGMT_GEN:
+ if (keymgmt->gen == NULL)
+ keymgmt->gen = OSSL_FUNC_keymgmt_gen(fns);
+ break;
+ case OSSL_FUNC_KEYMGMT_GEN_CLEANUP:
+ if (keymgmt->gen_cleanup == NULL)
+ keymgmt->gen_cleanup = OSSL_FUNC_keymgmt_gen_cleanup(fns);
+ break;
+ case OSSL_FUNC_KEYMGMT_FREE:
+ if (keymgmt->free == NULL)
+ keymgmt->free = OSSL_FUNC_keymgmt_free(fns);
+ break;
+ case OSSL_FUNC_KEYMGMT_LOAD:
+ if (keymgmt->load == NULL)
+ keymgmt->load = OSSL_FUNC_keymgmt_load(fns);
+ break;
+ case OSSL_FUNC_KEYMGMT_GET_PARAMS:
+ if (keymgmt->get_params == NULL) {
+ getparamfncnt++;
+ keymgmt->get_params = OSSL_FUNC_keymgmt_get_params(fns);
+ }
+ break;
+ case OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS:
+ if (keymgmt->gettable_params == NULL) {
+ getparamfncnt++;
+ keymgmt->gettable_params =
+ OSSL_FUNC_keymgmt_gettable_params(fns);
+ }
+ break;
+ case OSSL_FUNC_KEYMGMT_SET_PARAMS:
+ if (keymgmt->set_params == NULL) {
+ setparamfncnt++;
+ keymgmt->set_params = OSSL_FUNC_keymgmt_set_params(fns);
+ }
+ break;
+ case OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS:
+ if (keymgmt->settable_params == NULL) {
+ setparamfncnt++;
+ keymgmt->settable_params =
+ OSSL_FUNC_keymgmt_settable_params(fns);
+ }
+ break;
+ case OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME:
+ if (keymgmt->query_operation_name == NULL)
+ keymgmt->query_operation_name =
+ OSSL_FUNC_keymgmt_query_operation_name(fns);
+ break;
+ case OSSL_FUNC_KEYMGMT_HAS:
+ if (keymgmt->has == NULL)
+ keymgmt->has = OSSL_FUNC_keymgmt_has(fns);
+ break;
+ case OSSL_FUNC_KEYMGMT_DUP:
+ if (keymgmt->dup == NULL)
+ keymgmt->dup = OSSL_FUNC_keymgmt_dup(fns);
+ break;
+ case OSSL_FUNC_KEYMGMT_VALIDATE:
+ if (keymgmt->validate == NULL)
+ keymgmt->validate = OSSL_FUNC_keymgmt_validate(fns);
+ break;
+ case OSSL_FUNC_KEYMGMT_MATCH:
+ if (keymgmt->match == NULL)
+ keymgmt->match = OSSL_FUNC_keymgmt_match(fns);
+ break;
+ case OSSL_FUNC_KEYMGMT_IMPORT:
+ if (keymgmt->import == NULL) {
+ importfncnt++;
+ keymgmt->import = OSSL_FUNC_keymgmt_import(fns);
+ }
+ break;
+ case OSSL_FUNC_KEYMGMT_IMPORT_TYPES:
+ if (keymgmt->import_types == NULL) {
+ importfncnt++;
+ keymgmt->import_types = OSSL_FUNC_keymgmt_import_types(fns);
+ }
+ break;
+ case OSSL_FUNC_KEYMGMT_EXPORT:
+ if (keymgmt->export == NULL) {
+ exportfncnt++;
+ keymgmt->export = OSSL_FUNC_keymgmt_export(fns);
+ }
+ break;
+ case OSSL_FUNC_KEYMGMT_EXPORT_TYPES:
+ if (keymgmt->export_types == NULL) {
+ exportfncnt++;
+ keymgmt->export_types = OSSL_FUNC_keymgmt_export_types(fns);
+ }
+ break;
+ }
+ }
+ /*
+ * Try to check that the method is sensible.
+ * At least one constructor and the destructor are MANDATORY
+ * The functions 'has' is MANDATORY
+ * It makes no sense being able to free stuff if you can't create it.
+ * It makes no sense providing OSSL_PARAM descriptors for import and
+ * export if you can't import or export.
+ */
+ if (keymgmt->free == NULL
+ || (keymgmt->new == NULL
+ && keymgmt->gen == NULL
+ && keymgmt->load == NULL)
+ || keymgmt->has == NULL
+ || (getparamfncnt != 0 && getparamfncnt != 2)
+ || (setparamfncnt != 0 && setparamfncnt != 2)
+ || (setgenparamfncnt != 0 && setgenparamfncnt != 2)
+ || (importfncnt != 0 && importfncnt != 2)
+ || (exportfncnt != 0 && exportfncnt != 2)
+ || (keymgmt->gen != NULL
+ && (keymgmt->gen_init == NULL
+ || keymgmt->gen_cleanup == NULL))) {
+ EVP_KEYMGMT_free(keymgmt);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+ return NULL;
+ }
+ keymgmt->prov = prov;
+ if (prov != NULL)
+ ossl_provider_up_ref(prov);
+
+ return keymgmt;
+}
+
+EVP_KEYMGMT *evp_keymgmt_fetch_by_number(OSSL_LIB_CTX *ctx, int name_id,
+ const char *properties)
+{
+ return evp_generic_fetch_by_number(ctx,
+ OSSL_OP_KEYMGMT, name_id, properties,
+ keymgmt_from_algorithm,
+ (int (*)(void *))EVP_KEYMGMT_up_ref,
+ (void (*)(void *))EVP_KEYMGMT_free);
+}
+
+EVP_KEYMGMT *evp_keymgmt_fetch_from_prov(OSSL_PROVIDER *prov,
+ const char *name,
+ const char *properties)
+{
+ return evp_generic_fetch_from_prov(prov, OSSL_OP_KEYMGMT,
+ name, properties,
+ keymgmt_from_algorithm,
+ (int (*)(void *))EVP_KEYMGMT_up_ref,
+ (void (*)(void *))EVP_KEYMGMT_free);
+}
+
+EVP_KEYMGMT *EVP_KEYMGMT_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties)
+{
+ return evp_generic_fetch(ctx, OSSL_OP_KEYMGMT, algorithm, properties,
+ keymgmt_from_algorithm,
+ (int (*)(void *))EVP_KEYMGMT_up_ref,
+ (void (*)(void *))EVP_KEYMGMT_free);
+}
+
+int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt)
+{
+ int ref = 0;
+
+ CRYPTO_UP_REF(&keymgmt->refcnt, &ref, keymgmt->lock);
+ return 1;
+}
+
+void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt)
+{
+ int ref = 0;
+
+ if (keymgmt == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&keymgmt->refcnt, &ref, keymgmt->lock);
+ if (ref > 0)
+ return;
+ OPENSSL_free(keymgmt->type_name);
+ ossl_provider_free(keymgmt->prov);
+ CRYPTO_THREAD_lock_free(keymgmt->lock);
+ OPENSSL_free(keymgmt);
+}
+
+const OSSL_PROVIDER *EVP_KEYMGMT_get0_provider(const EVP_KEYMGMT *keymgmt)
+{
+ return keymgmt->prov;
+}
+
+int evp_keymgmt_get_number(const EVP_KEYMGMT *keymgmt)
+{
+ return keymgmt->name_id;
+}
+
+const char *EVP_KEYMGMT_get0_description(const EVP_KEYMGMT *keymgmt)
+{
+ return keymgmt->description;
+}
+
+const char *EVP_KEYMGMT_get0_name(const EVP_KEYMGMT *keymgmt)
+{
+ return keymgmt->type_name;
+}
+
+int EVP_KEYMGMT_is_a(const EVP_KEYMGMT *keymgmt, const char *name)
+{
+ return keymgmt != NULL
+ && evp_is_a(keymgmt->prov, keymgmt->name_id, NULL, name);
+}
+
+void EVP_KEYMGMT_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_KEYMGMT *keymgmt, void *arg),
+ void *arg)
+{
+ evp_generic_do_all(libctx, OSSL_OP_KEYMGMT,
+ (void (*)(void *, void *))fn, arg,
+ keymgmt_from_algorithm,
+ (int (*)(void *))EVP_KEYMGMT_up_ref,
+ (void (*)(void *))EVP_KEYMGMT_free);
+}
+
+int EVP_KEYMGMT_names_do_all(const EVP_KEYMGMT *keymgmt,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (keymgmt->prov != NULL)
+ return evp_names_do_all(keymgmt->prov, keymgmt->name_id, fn, data);
+
+ return 1;
+}
+
+/*
+ * Internal API that interfaces with the method function pointers
+ */
+void *evp_keymgmt_newdata(const EVP_KEYMGMT *keymgmt)
+{
+ void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
+
+ /*
+ * 'new' is currently mandatory on its own, but when new
+ * constructors appear, it won't be quite as mandatory,
+ * so we have a check for future cases.
+ */
+ if (keymgmt->new == NULL)
+ return NULL;
+ return keymgmt->new(provctx);
+}
+
+void evp_keymgmt_freedata(const EVP_KEYMGMT *keymgmt, void *keydata)
+{
+ /* This is mandatory, no need to check for its presence */
+ keymgmt->free(keydata);
+}
+
+void *evp_keymgmt_gen_init(const EVP_KEYMGMT *keymgmt, int selection,
+ const OSSL_PARAM params[])
+{
+ void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
+
+ if (keymgmt->gen_init == NULL)
+ return NULL;
+ return keymgmt->gen_init(provctx, selection, params);
+}
+
+int evp_keymgmt_gen_set_template(const EVP_KEYMGMT *keymgmt, void *genctx,
+ void *template)
+{
+ /*
+ * It's arguable if we actually should return success in this case, as
+ * it allows the caller to set a template key, which is then ignored.
+ * However, this is how the legacy methods (EVP_PKEY_METHOD) operate,
+ * so we do this in the interest of backward compatibility.
+ */
+ if (keymgmt->gen_set_template == NULL)
+ return 1;
+ return keymgmt->gen_set_template(genctx, template);
+}
+
+int evp_keymgmt_gen_set_params(const EVP_KEYMGMT *keymgmt, void *genctx,
+ const OSSL_PARAM params[])
+{
+ if (keymgmt->gen_set_params == NULL)
+ return 0;
+ return keymgmt->gen_set_params(genctx, params);
+}
+
+const OSSL_PARAM *EVP_KEYMGMT_gen_settable_params(const EVP_KEYMGMT *keymgmt)
+{
+ void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
+
+ if (keymgmt->gen_settable_params == NULL)
+ return NULL;
+ return keymgmt->gen_settable_params(NULL, provctx);
+}
+
+void *evp_keymgmt_gen(const EVP_KEYMGMT *keymgmt, void *genctx,
+ OSSL_CALLBACK *cb, void *cbarg)
+{
+ if (keymgmt->gen == NULL)
+ return NULL;
+ return keymgmt->gen(genctx, cb, cbarg);
+}
+
+void evp_keymgmt_gen_cleanup(const EVP_KEYMGMT *keymgmt, void *genctx)
+{
+ if (keymgmt->gen != NULL)
+ keymgmt->gen_cleanup(genctx);
+}
+
+int evp_keymgmt_has_load(const EVP_KEYMGMT *keymgmt)
+{
+ return keymgmt != NULL && keymgmt->load != NULL;
+}
+
+void *evp_keymgmt_load(const EVP_KEYMGMT *keymgmt,
+ const void *objref, size_t objref_sz)
+{
+ if (evp_keymgmt_has_load(keymgmt))
+ return keymgmt->load(objref, objref_sz);
+ return NULL;
+}
+
+int evp_keymgmt_get_params(const EVP_KEYMGMT *keymgmt, void *keydata,
+ OSSL_PARAM params[])
+{
+ if (keymgmt->get_params == NULL)
+ return 1;
+ return keymgmt->get_params(keydata, params);
+}
+
+const OSSL_PARAM *EVP_KEYMGMT_gettable_params(const EVP_KEYMGMT *keymgmt)
+{
+ void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
+
+ if (keymgmt->gettable_params == NULL)
+ return NULL;
+ return keymgmt->gettable_params(provctx);
+}
+
+int evp_keymgmt_set_params(const EVP_KEYMGMT *keymgmt, void *keydata,
+ const OSSL_PARAM params[])
+{
+ if (keymgmt->set_params == NULL)
+ return 1;
+ return keymgmt->set_params(keydata, params);
+}
+
+const OSSL_PARAM *EVP_KEYMGMT_settable_params(const EVP_KEYMGMT *keymgmt)
+{
+ void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
+
+ if (keymgmt->settable_params == NULL)
+ return NULL;
+ return keymgmt->settable_params(provctx);
+}
+
+int evp_keymgmt_has(const EVP_KEYMGMT *keymgmt, void *keydata, int selection)
+{
+ /* This is mandatory, no need to check for its presence */
+ return keymgmt->has(keydata, selection);
+}
+
+int evp_keymgmt_validate(const EVP_KEYMGMT *keymgmt, void *keydata,
+ int selection, int checktype)
+{
+ /* We assume valid if the implementation doesn't have a function */
+ if (keymgmt->validate == NULL)
+ return 1;
+ return keymgmt->validate(keydata, selection, checktype);
+}
+
+int evp_keymgmt_match(const EVP_KEYMGMT *keymgmt,
+ const void *keydata1, const void *keydata2,
+ int selection)
+{
+ /* We assume no match if the implementation doesn't have a function */
+ if (keymgmt->match == NULL)
+ return 0;
+ return keymgmt->match(keydata1, keydata2, selection);
+}
+
+int evp_keymgmt_import(const EVP_KEYMGMT *keymgmt, void *keydata,
+ int selection, const OSSL_PARAM params[])
+{
+ if (keymgmt->import == NULL)
+ return 0;
+ return keymgmt->import(keydata, selection, params);
+}
+
+const OSSL_PARAM *evp_keymgmt_import_types(const EVP_KEYMGMT *keymgmt,
+ int selection)
+{
+ if (keymgmt->import_types == NULL)
+ return NULL;
+ return keymgmt->import_types(selection);
+}
+
+int evp_keymgmt_export(const EVP_KEYMGMT *keymgmt, void *keydata,
+ int selection, OSSL_CALLBACK *param_cb, void *cbarg)
+{
+ if (keymgmt->export == NULL)
+ return 0;
+ return keymgmt->export(keydata, selection, param_cb, cbarg);
+}
+
+const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt,
+ int selection)
+{
+ if (keymgmt->export_types == NULL)
+ return NULL;
+ return keymgmt->export_types(selection);
+}
+
+void *evp_keymgmt_dup(const EVP_KEYMGMT *keymgmt, const void *keydata_from,
+ int selection)
+{
+ /* We assume no dup if the implementation doesn't have a function */
+ if (keymgmt->dup == NULL)
+ return NULL;
+ return keymgmt->dup(keydata_from, selection);
+}
diff --git a/crypto/evp/legacy_blake2.c b/crypto/evp/legacy_blake2.c
new file mode 100644
index 000000000000..6a18e5fe01b6
--- /dev/null
+++ b/crypto/evp/legacy_blake2.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "crypto/evp.h"
+#include "prov/blake2.h" /* diverse BLAKE2 macros */
+#include "legacy_meth.h"
+
+#define ossl_blake2b_init ossl_blake2b512_init
+#define ossl_blake2s_init ossl_blake2s256_init
+
+IMPLEMENT_LEGACY_EVP_MD_METH_LC(blake2s_int, ossl_blake2s)
+IMPLEMENT_LEGACY_EVP_MD_METH_LC(blake2b_int, ossl_blake2b)
+
+static const EVP_MD blake2b_md = {
+ NID_blake2b512,
+ 0,
+ BLAKE2B_DIGEST_LENGTH,
+ 0,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(blake2b_int_init, blake2b_int_update,
+ blake2b_int_final, NULL, BLAKE2B_BLOCKBYTES),
+};
+
+const EVP_MD *EVP_blake2b512(void)
+{
+ return &blake2b_md;
+}
+
+static const EVP_MD blake2s_md = {
+ NID_blake2s256,
+ 0,
+ BLAKE2S_DIGEST_LENGTH,
+ 0,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(blake2s_int_init, blake2s_int_update,
+ blake2s_int_final, NULL, BLAKE2S_BLOCKBYTES),
+};
+
+const EVP_MD *EVP_blake2s256(void)
+{
+ return &blake2s_md;
+}
diff --git a/crypto/evp/legacy_md2.c b/crypto/evp/legacy_md2.c
new file mode 100644
index 000000000000..72cc99ad7044
--- /dev/null
+++ b/crypto/evp/legacy_md2.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * MD2 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/md2.h>
+#include "crypto/evp.h"
+#include "legacy_meth.h"
+
+IMPLEMENT_LEGACY_EVP_MD_METH(md2, MD2)
+
+static const EVP_MD md2_md = {
+ NID_md2,
+ NID_md2WithRSAEncryption,
+ MD2_DIGEST_LENGTH,
+ 0,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(md2_init, md2_update, md2_final, NULL, MD2_BLOCK)
+};
+
+const EVP_MD *EVP_md2(void)
+{
+ return &md2_md;
+}
diff --git a/crypto/evp/legacy_md4.c b/crypto/evp/legacy_md4.c
new file mode 100644
index 000000000000..4bc852b5209a
--- /dev/null
+++ b/crypto/evp/legacy_md4.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * MD4 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/md4.h>
+#include "crypto/evp.h"
+#include "legacy_meth.h"
+
+IMPLEMENT_LEGACY_EVP_MD_METH(md4, MD4)
+
+static const EVP_MD md4_md = {
+ NID_md4,
+ NID_md4WithRSAEncryption,
+ MD4_DIGEST_LENGTH,
+ 0,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(md4_init, md4_update, md4_final, NULL, MD4_CBLOCK),
+};
+
+const EVP_MD *EVP_md4(void)
+{
+ return &md4_md;
+}
diff --git a/crypto/evp/legacy_md5.c b/crypto/evp/legacy_md5.c
new file mode 100644
index 000000000000..a67be9fef74b
--- /dev/null
+++ b/crypto/evp/legacy_md5.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * MD5 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/md5.h>
+#include "crypto/evp.h"
+#include "legacy_meth.h"
+
+IMPLEMENT_LEGACY_EVP_MD_METH(md5, MD5)
+
+static const EVP_MD md5_md = {
+ NID_md5,
+ NID_md5WithRSAEncryption,
+ MD5_DIGEST_LENGTH,
+ 0,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(md5_init, md5_update, md5_final, NULL, MD5_CBLOCK)
+};
+
+const EVP_MD *EVP_md5(void)
+{
+ return &md5_md;
+}
diff --git a/crypto/evp/legacy_md5_sha1.c b/crypto/evp/legacy_md5_sha1.c
new file mode 100644
index 000000000000..b84bf3deaaf4
--- /dev/null
+++ b/crypto/evp/legacy_md5_sha1.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * MD5 and SHA-1 low level APIs are deprecated for public use, but still ok for
+ * internal use. The prov/md5_sha1.h include requires this, but this must
+ * be the first include loaded.
+ */
+#include "internal/deprecated.h"
+
+#include "crypto/evp.h"
+#include "prov/md5_sha1.h" /* diverse MD5_SHA1 macros */
+#include "legacy_meth.h"
+
+IMPLEMENT_LEGACY_EVP_MD_METH_LC(md5_sha1_int, ossl_md5_sha1)
+static int md5_sha1_int_ctrl(EVP_MD_CTX *ctx, int cmd, int mslen, void *ms)
+{
+ return ossl_md5_sha1_ctrl(EVP_MD_CTX_get0_md_data(ctx), cmd, mslen, ms);
+}
+
+static const EVP_MD md5_sha1_md = {
+ NID_md5_sha1,
+ NID_md5_sha1,
+ MD5_SHA1_DIGEST_LENGTH,
+ 0,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(md5_sha1_int_init, md5_sha1_int_update,
+ md5_sha1_int_final, md5_sha1_int_ctrl,
+ MD5_SHA1_CBLOCK),
+};
+
+const EVP_MD *EVP_md5_sha1(void)
+{
+ return &md5_sha1_md;
+}
diff --git a/crypto/evp/legacy_mdc2.c b/crypto/evp/legacy_mdc2.c
new file mode 100644
index 000000000000..317d87c61b14
--- /dev/null
+++ b/crypto/evp/legacy_mdc2.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * MDC2 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/mdc2.h>
+#include "crypto/evp.h"
+#include "legacy_meth.h"
+
+IMPLEMENT_LEGACY_EVP_MD_METH(mdc2, MDC2)
+
+static const EVP_MD mdc2_md = {
+ NID_mdc2,
+ NID_mdc2WithRSA,
+ MDC2_DIGEST_LENGTH,
+ 0,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(mdc2_init, mdc2_update, mdc2_final, NULL,
+ MDC2_BLOCK),
+};
+
+const EVP_MD *EVP_mdc2(void)
+{
+ return &mdc2_md;
+}
diff --git a/crypto/evp/legacy_meth.h b/crypto/evp/legacy_meth.h
new file mode 100644
index 000000000000..a6e58bc824e2
--- /dev/null
+++ b/crypto/evp/legacy_meth.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#define IMPLEMENT_LEGACY_EVP_MD_METH(nm, fn) \
+static int nm##_init(EVP_MD_CTX *ctx) \
+{ \
+ return fn##_Init(EVP_MD_CTX_get0_md_data(ctx)); \
+} \
+static int nm##_update(EVP_MD_CTX *ctx, const void *data, size_t count) \
+{ \
+ return fn##_Update(EVP_MD_CTX_get0_md_data(ctx), data, count); \
+} \
+static int nm##_final(EVP_MD_CTX *ctx, unsigned char *md) \
+{ \
+ return fn##_Final(md, EVP_MD_CTX_get0_md_data(ctx)); \
+}
+
+#define IMPLEMENT_LEGACY_EVP_MD_METH_LC(nm, fn) \
+static int nm##_init(EVP_MD_CTX *ctx) \
+{ \
+ return fn##_init(EVP_MD_CTX_get0_md_data(ctx)); \
+} \
+static int nm##_update(EVP_MD_CTX *ctx, const void *data, size_t count) \
+{ \
+ return fn##_update(EVP_MD_CTX_get0_md_data(ctx), data, count); \
+} \
+static int nm##_final(EVP_MD_CTX *ctx, unsigned char *md) \
+{ \
+ return fn##_final(md, EVP_MD_CTX_get0_md_data(ctx)); \
+}
+
+
+#define LEGACY_EVP_MD_METH_TABLE(init, update, final, ctrl, blksz) \
+ init, update, final, NULL, NULL, blksz, 0, ctrl
diff --git a/crypto/evp/legacy_ripemd.c b/crypto/evp/legacy_ripemd.c
new file mode 100644
index 000000000000..1fa1ebc04998
--- /dev/null
+++ b/crypto/evp/legacy_ripemd.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * RIPEMD160 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/ripemd.h>
+#include "crypto/evp.h"
+#include "legacy_meth.h"
+
+IMPLEMENT_LEGACY_EVP_MD_METH(ripe, RIPEMD160)
+
+static const EVP_MD ripemd160_md = {
+ NID_ripemd160,
+ NID_ripemd160WithRSA,
+ RIPEMD160_DIGEST_LENGTH,
+ 0,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(ripe_init, ripe_update, ripe_final, NULL,
+ RIPEMD160_CBLOCK),
+};
+
+const EVP_MD *EVP_ripemd160(void)
+{
+ return &ripemd160_md;
+}
diff --git a/crypto/evp/legacy_sha.c b/crypto/evp/legacy_sha.c
new file mode 100644
index 000000000000..3859286eeb20
--- /dev/null
+++ b/crypto/evp/legacy_sha.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * All SHA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/sha.h> /* diverse SHA macros */
+#include "internal/sha3.h" /* KECCAK1600_WIDTH */
+#include "crypto/evp.h"
+/* Used by legacy methods */
+#include "crypto/sha.h"
+#include "legacy_meth.h"
+#include "evp_local.h"
+
+/*-
+ * LEGACY methods for SHA.
+ * These only remain to support engines that can get these methods.
+ * Hardware support for SHA3 has been removed from these legacy cases.
+ */
+#define IMPLEMENT_LEGACY_EVP_MD_METH_SHA3(nm, fn, tag) \
+static int nm##_init(EVP_MD_CTX *ctx) \
+{ \
+ return fn##_init(EVP_MD_CTX_get0_md_data(ctx), tag, ctx->digest->md_size * 8); \
+} \
+static int nm##_update(EVP_MD_CTX *ctx, const void *data, size_t count) \
+{ \
+ return fn##_update(EVP_MD_CTX_get0_md_data(ctx), data, count); \
+} \
+static int nm##_final(EVP_MD_CTX *ctx, unsigned char *md) \
+{ \
+ return fn##_final(md, EVP_MD_CTX_get0_md_data(ctx)); \
+}
+#define IMPLEMENT_LEGACY_EVP_MD_METH_SHAKE(nm, fn, tag) \
+static int nm##_init(EVP_MD_CTX *ctx) \
+{ \
+ return fn##_init(EVP_MD_CTX_get0_md_data(ctx), tag, ctx->digest->md_size * 8); \
+} \
+
+#define sha512_224_Init sha512_224_init
+#define sha512_256_Init sha512_256_init
+
+#define sha512_224_Update SHA512_Update
+#define sha512_224_Final SHA512_Final
+#define sha512_256_Update SHA512_Update
+#define sha512_256_Final SHA512_Final
+
+IMPLEMENT_LEGACY_EVP_MD_METH(sha1, SHA1)
+IMPLEMENT_LEGACY_EVP_MD_METH(sha224, SHA224)
+IMPLEMENT_LEGACY_EVP_MD_METH(sha256, SHA256)
+IMPLEMENT_LEGACY_EVP_MD_METH(sha384, SHA384)
+IMPLEMENT_LEGACY_EVP_MD_METH(sha512, SHA512)
+IMPLEMENT_LEGACY_EVP_MD_METH(sha512_224_int, sha512_224)
+IMPLEMENT_LEGACY_EVP_MD_METH(sha512_256_int, sha512_256)
+IMPLEMENT_LEGACY_EVP_MD_METH_SHA3(sha3_int, ossl_sha3, '\x06')
+IMPLEMENT_LEGACY_EVP_MD_METH_SHAKE(shake, ossl_sha3, '\x1f')
+
+static int sha1_int_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)
+{
+ return ossl_sha1_ctrl(ctx != NULL ? EVP_MD_CTX_get0_md_data(ctx) : NULL,
+ cmd, p1, p2);
+}
+
+static int shake_ctrl(EVP_MD_CTX *evp_ctx, int cmd, int p1, void *p2)
+{
+ KECCAK1600_CTX *ctx = evp_ctx->md_data;
+
+ switch (cmd) {
+ case EVP_MD_CTRL_XOF_LEN:
+ ctx->md_size = p1;
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+
+
+static const EVP_MD sha1_md = {
+ NID_sha1,
+ NID_sha1WithRSAEncryption,
+ SHA_DIGEST_LENGTH,
+ EVP_MD_FLAG_DIGALGID_ABSENT,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(sha1_init, sha1_update, sha1_final, sha1_int_ctrl,
+ SHA_CBLOCK),
+};
+
+const EVP_MD *EVP_sha1(void)
+{
+ return &sha1_md;
+}
+
+static const EVP_MD sha224_md = {
+ NID_sha224,
+ NID_sha224WithRSAEncryption,
+ SHA224_DIGEST_LENGTH,
+ EVP_MD_FLAG_DIGALGID_ABSENT,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(sha224_init, sha224_update, sha224_final, NULL,
+ SHA256_CBLOCK),
+};
+
+const EVP_MD *EVP_sha224(void)
+{
+ return &sha224_md;
+}
+
+static const EVP_MD sha256_md = {
+ NID_sha256,
+ NID_sha256WithRSAEncryption,
+ SHA256_DIGEST_LENGTH,
+ EVP_MD_FLAG_DIGALGID_ABSENT,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(sha256_init, sha256_update, sha256_final, NULL,
+ SHA256_CBLOCK),
+};
+
+const EVP_MD *EVP_sha256(void)
+{
+ return &sha256_md;
+}
+
+static const EVP_MD sha512_224_md = {
+ NID_sha512_224,
+ NID_sha512_224WithRSAEncryption,
+ SHA224_DIGEST_LENGTH,
+ EVP_MD_FLAG_DIGALGID_ABSENT,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(sha512_224_int_init, sha512_224_int_update,
+ sha512_224_int_final, NULL, SHA512_CBLOCK),
+};
+
+const EVP_MD *EVP_sha512_224(void)
+{
+ return &sha512_224_md;
+}
+
+static const EVP_MD sha512_256_md = {
+ NID_sha512_256,
+ NID_sha512_256WithRSAEncryption,
+ SHA256_DIGEST_LENGTH,
+ EVP_MD_FLAG_DIGALGID_ABSENT,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(sha512_256_int_init, sha512_256_int_update,
+ sha512_256_int_final, NULL, SHA512_CBLOCK),
+};
+
+const EVP_MD *EVP_sha512_256(void)
+{
+ return &sha512_256_md;
+}
+
+static const EVP_MD sha384_md = {
+ NID_sha384,
+ NID_sha384WithRSAEncryption,
+ SHA384_DIGEST_LENGTH,
+ EVP_MD_FLAG_DIGALGID_ABSENT,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(sha384_init, sha384_update, sha384_final, NULL,
+ SHA512_CBLOCK),
+};
+
+const EVP_MD *EVP_sha384(void)
+{
+ return &sha384_md;
+}
+
+static const EVP_MD sha512_md = {
+ NID_sha512,
+ NID_sha512WithRSAEncryption,
+ SHA512_DIGEST_LENGTH,
+ EVP_MD_FLAG_DIGALGID_ABSENT,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(sha512_init, sha512_update, sha512_final, NULL,
+ SHA512_CBLOCK),
+};
+
+const EVP_MD *EVP_sha512(void)
+{
+ return &sha512_md;
+}
+
+#define EVP_MD_SHA3(bitlen) \
+const EVP_MD *EVP_sha3_##bitlen(void) \
+{ \
+ static const EVP_MD sha3_##bitlen##_md = { \
+ NID_sha3_##bitlen, \
+ NID_RSA_SHA3_##bitlen, \
+ bitlen / 8, \
+ EVP_MD_FLAG_DIGALGID_ABSENT, \
+ EVP_ORIG_GLOBAL, \
+ LEGACY_EVP_MD_METH_TABLE(sha3_int_init, sha3_int_update, \
+ sha3_int_final, NULL, \
+ (KECCAK1600_WIDTH - bitlen * 2) / 8), \
+ }; \
+ return &sha3_##bitlen##_md; \
+}
+#define EVP_MD_SHAKE(bitlen) \
+const EVP_MD *EVP_shake##bitlen(void) \
+{ \
+ static const EVP_MD shake##bitlen##_md = { \
+ NID_shake##bitlen, \
+ 0, \
+ bitlen / 8, \
+ EVP_MD_FLAG_XOF, \
+ EVP_ORIG_GLOBAL, \
+ LEGACY_EVP_MD_METH_TABLE(shake_init, sha3_int_update, sha3_int_final, \
+ shake_ctrl, (KECCAK1600_WIDTH - bitlen * 2) / 8), \
+ }; \
+ return &shake##bitlen##_md; \
+}
+
+EVP_MD_SHA3(224)
+EVP_MD_SHA3(256)
+EVP_MD_SHA3(384)
+EVP_MD_SHA3(512)
+
+EVP_MD_SHAKE(128)
+EVP_MD_SHAKE(256)
diff --git a/crypto/evp/legacy_wp.c b/crypto/evp/legacy_wp.c
new file mode 100644
index 000000000000..3976ff73fb2d
--- /dev/null
+++ b/crypto/evp/legacy_wp.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Whirlpool low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/whrlpool.h>
+#include "crypto/evp.h"
+#include "legacy_meth.h"
+
+IMPLEMENT_LEGACY_EVP_MD_METH(wp, WHIRLPOOL)
+
+static const EVP_MD whirlpool_md = {
+ NID_whirlpool,
+ 0,
+ WHIRLPOOL_DIGEST_LENGTH,
+ 0,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(wp_init, wp_update, wp_final, NULL,
+ WHIRLPOOL_BBLOCK / 8),
+};
+
+const EVP_MD *EVP_whirlpool(void)
+{
+ return &whirlpool_md;
+}
diff --git a/crypto/evp/m_md2.c b/crypto/evp/m_md2.c
deleted file mode 100644
index 1aec5185239d..000000000000
--- a/crypto/evp/m_md2.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-
-#ifndef OPENSSL_NO_MD2
-
-# include <openssl/evp.h>
-# include <openssl/objects.h>
-# include <openssl/x509.h>
-# include <openssl/md2.h>
-# include <openssl/rsa.h>
-
-#include "crypto/evp.h"
-
-static int init(EVP_MD_CTX *ctx)
-{
- return MD2_Init(EVP_MD_CTX_md_data(ctx));
-}
-
-static int update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- return MD2_Update(EVP_MD_CTX_md_data(ctx), data, count);
-}
-
-static int final(EVP_MD_CTX *ctx, unsigned char *md)
-{
- return MD2_Final(md, EVP_MD_CTX_md_data(ctx));
-}
-
-static const EVP_MD md2_md = {
- NID_md2,
- NID_md2WithRSAEncryption,
- MD2_DIGEST_LENGTH,
- 0,
- init,
- update,
- final,
- NULL,
- NULL,
- MD2_BLOCK,
- sizeof(EVP_MD *) + sizeof(MD2_CTX),
-};
-
-const EVP_MD *EVP_md2(void)
-{
- return &md2_md;
-}
-#endif
diff --git a/crypto/evp/m_md4.c b/crypto/evp/m_md4.c
deleted file mode 100644
index 45d2cafee101..000000000000
--- a/crypto/evp/m_md4.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-
-#ifndef OPENSSL_NO_MD4
-
-# include <openssl/evp.h>
-# include <openssl/objects.h>
-# include <openssl/x509.h>
-# include <openssl/md4.h>
-# include <openssl/rsa.h>
-# include "crypto/evp.h"
-
-static int init(EVP_MD_CTX *ctx)
-{
- return MD4_Init(EVP_MD_CTX_md_data(ctx));
-}
-
-static int update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- return MD4_Update(EVP_MD_CTX_md_data(ctx), data, count);
-}
-
-static int final(EVP_MD_CTX *ctx, unsigned char *md)
-{
- return MD4_Final(md, EVP_MD_CTX_md_data(ctx));
-}
-
-static const EVP_MD md4_md = {
- NID_md4,
- NID_md4WithRSAEncryption,
- MD4_DIGEST_LENGTH,
- 0,
- init,
- update,
- final,
- NULL,
- NULL,
- MD4_CBLOCK,
- sizeof(EVP_MD *) + sizeof(MD4_CTX),
-};
-
-const EVP_MD *EVP_md4(void)
-{
- return &md4_md;
-}
-#endif
diff --git a/crypto/evp/m_md5.c b/crypto/evp/m_md5.c
deleted file mode 100644
index d26b5a4d31dc..000000000000
--- a/crypto/evp/m_md5.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-
-#ifndef OPENSSL_NO_MD5
-
-# include <openssl/evp.h>
-# include <openssl/objects.h>
-# include <openssl/x509.h>
-# include <openssl/md5.h>
-# include <openssl/rsa.h>
-# include "crypto/evp.h"
-
-static int init(EVP_MD_CTX *ctx)
-{
- return MD5_Init(EVP_MD_CTX_md_data(ctx));
-}
-
-static int update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- return MD5_Update(EVP_MD_CTX_md_data(ctx), data, count);
-}
-
-static int final(EVP_MD_CTX *ctx, unsigned char *md)
-{
- return MD5_Final(md, EVP_MD_CTX_md_data(ctx));
-}
-
-static const EVP_MD md5_md = {
- NID_md5,
- NID_md5WithRSAEncryption,
- MD5_DIGEST_LENGTH,
- 0,
- init,
- update,
- final,
- NULL,
- NULL,
- MD5_CBLOCK,
- sizeof(EVP_MD *) + sizeof(MD5_CTX),
-};
-
-const EVP_MD *EVP_md5(void)
-{
- return &md5_md;
-}
-#endif
diff --git a/crypto/evp/m_md5_sha1.c b/crypto/evp/m_md5_sha1.c
deleted file mode 100644
index eeec2b13e9ed..000000000000
--- a/crypto/evp/m_md5_sha1.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#if !defined(OPENSSL_NO_MD5)
-
-# include <openssl/evp.h>
-# include <openssl/objects.h>
-# include <openssl/x509.h>
-# include <openssl/md5.h>
-# include <openssl/sha.h>
-# include "internal/cryptlib.h"
-# include "crypto/evp.h"
-# include <openssl/rsa.h>
-
-struct md5_sha1_ctx {
- MD5_CTX md5;
- SHA_CTX sha1;
-};
-
-static int init(EVP_MD_CTX *ctx)
-{
- struct md5_sha1_ctx *mctx = EVP_MD_CTX_md_data(ctx);
- if (!MD5_Init(&mctx->md5))
- return 0;
- return SHA1_Init(&mctx->sha1);
-}
-
-static int update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- struct md5_sha1_ctx *mctx = EVP_MD_CTX_md_data(ctx);
- if (!MD5_Update(&mctx->md5, data, count))
- return 0;
- return SHA1_Update(&mctx->sha1, data, count);
-}
-
-static int final(EVP_MD_CTX *ctx, unsigned char *md)
-{
- struct md5_sha1_ctx *mctx = EVP_MD_CTX_md_data(ctx);
- if (!MD5_Final(md, &mctx->md5))
- return 0;
- return SHA1_Final(md + MD5_DIGEST_LENGTH, &mctx->sha1);
-}
-
-static int ctrl(EVP_MD_CTX *ctx, int cmd, int mslen, void *ms)
-{
- unsigned char padtmp[48];
- unsigned char md5tmp[MD5_DIGEST_LENGTH];
- unsigned char sha1tmp[SHA_DIGEST_LENGTH];
- struct md5_sha1_ctx *mctx;
-
- if (cmd != EVP_CTRL_SSL3_MASTER_SECRET)
- return -2;
-
- if (ctx == NULL)
- return 0;
-
- mctx = EVP_MD_CTX_md_data(ctx);
-
- /* SSLv3 client auth handling: see RFC-6101 5.6.8 */
- if (mslen != 48)
- return 0;
-
- /* At this point hash contains all handshake messages, update
- * with master secret and pad_1.
- */
-
- if (update(ctx, ms, mslen) <= 0)
- return 0;
-
- /* Set padtmp to pad_1 value */
- memset(padtmp, 0x36, sizeof(padtmp));
-
- if (!MD5_Update(&mctx->md5, padtmp, sizeof(padtmp)))
- return 0;
-
- if (!MD5_Final(md5tmp, &mctx->md5))
- return 0;
-
- if (!SHA1_Update(&mctx->sha1, padtmp, 40))
- return 0;
-
- if (!SHA1_Final(sha1tmp, &mctx->sha1))
- return 0;
-
- /* Reinitialise context */
-
- if (!init(ctx))
- return 0;
-
- if (update(ctx, ms, mslen) <= 0)
- return 0;
-
- /* Set padtmp to pad_2 value */
- memset(padtmp, 0x5c, sizeof(padtmp));
-
- if (!MD5_Update(&mctx->md5, padtmp, sizeof(padtmp)))
- return 0;
-
- if (!MD5_Update(&mctx->md5, md5tmp, sizeof(md5tmp)))
- return 0;
-
- if (!SHA1_Update(&mctx->sha1, padtmp, 40))
- return 0;
-
- if (!SHA1_Update(&mctx->sha1, sha1tmp, sizeof(sha1tmp)))
- return 0;
-
- /* Now when ctx is finalised it will return the SSL v3 hash value */
-
- OPENSSL_cleanse(md5tmp, sizeof(md5tmp));
- OPENSSL_cleanse(sha1tmp, sizeof(sha1tmp));
-
- return 1;
-
-}
-
-static const EVP_MD md5_sha1_md = {
- NID_md5_sha1,
- NID_md5_sha1,
- MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH,
- 0,
- init,
- update,
- final,
- NULL,
- NULL,
- MD5_CBLOCK,
- sizeof(EVP_MD *) + sizeof(struct md5_sha1_ctx),
- ctrl
-};
-
-const EVP_MD *EVP_md5_sha1(void)
-{
- return &md5_sha1_md;
-}
-#endif
diff --git a/crypto/evp/m_mdc2.c b/crypto/evp/m_mdc2.c
deleted file mode 100644
index fffa751efd18..000000000000
--- a/crypto/evp/m_mdc2.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-
-#ifndef OPENSSL_NO_MDC2
-
-# include <openssl/evp.h>
-# include <openssl/objects.h>
-# include <openssl/x509.h>
-# include <openssl/mdc2.h>
-# include <openssl/rsa.h>
-# include "crypto/evp.h"
-
-static int init(EVP_MD_CTX *ctx)
-{
- return MDC2_Init(EVP_MD_CTX_md_data(ctx));
-}
-
-static int update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- return MDC2_Update(EVP_MD_CTX_md_data(ctx), data, count);
-}
-
-static int final(EVP_MD_CTX *ctx, unsigned char *md)
-{
- return MDC2_Final(md, EVP_MD_CTX_md_data(ctx));
-}
-
-static const EVP_MD mdc2_md = {
- NID_mdc2,
- NID_mdc2WithRSA,
- MDC2_DIGEST_LENGTH,
- 0,
- init,
- update,
- final,
- NULL,
- NULL,
- MDC2_BLOCK,
- sizeof(EVP_MD *) + sizeof(MDC2_CTX),
-};
-
-const EVP_MD *EVP_mdc2(void)
-{
- return &mdc2_md;
-}
-#endif
diff --git a/crypto/evp/m_null.c b/crypto/evp/m_null.c
index 0847139df17b..7b310d70477e 100644
--- a/crypto/evp/m_null.c
+++ b/crypto/evp/m_null.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -34,6 +34,7 @@ static const EVP_MD null_md = {
NID_undef,
0,
0,
+ EVP_ORIG_GLOBAL,
init,
update,
final,
diff --git a/crypto/evp/m_ripemd.c b/crypto/evp/m_ripemd.c
deleted file mode 100644
index d93ad24fe58a..000000000000
--- a/crypto/evp/m_ripemd.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-
-#ifndef OPENSSL_NO_RMD160
-
-# include <openssl/ripemd.h>
-# include <openssl/evp.h>
-# include <openssl/objects.h>
-# include <openssl/x509.h>
-# include <openssl/rsa.h>
-# include "crypto/evp.h"
-
-static int init(EVP_MD_CTX *ctx)
-{
- return RIPEMD160_Init(EVP_MD_CTX_md_data(ctx));
-}
-
-static int update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- return RIPEMD160_Update(EVP_MD_CTX_md_data(ctx), data, count);
-}
-
-static int final(EVP_MD_CTX *ctx, unsigned char *md)
-{
- return RIPEMD160_Final(md, EVP_MD_CTX_md_data(ctx));
-}
-
-static const EVP_MD ripemd160_md = {
- NID_ripemd160,
- NID_ripemd160WithRSA,
- RIPEMD160_DIGEST_LENGTH,
- 0,
- init,
- update,
- final,
- NULL,
- NULL,
- RIPEMD160_CBLOCK,
- sizeof(EVP_MD *) + sizeof(RIPEMD160_CTX),
-};
-
-const EVP_MD *EVP_ripemd160(void)
-{
- return &ripemd160_md;
-}
-#endif
diff --git a/crypto/evp/m_sha1.c b/crypto/evp/m_sha1.c
deleted file mode 100644
index 22b9bbc7d861..000000000000
--- a/crypto/evp/m_sha1.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-
-#include <openssl/evp.h>
-#include <openssl/objects.h>
-#include <openssl/sha.h>
-#include <openssl/rsa.h>
-#include "crypto/evp.h"
-#include "crypto/sha.h"
-
-static int init(EVP_MD_CTX *ctx)
-{
- return SHA1_Init(EVP_MD_CTX_md_data(ctx));
-}
-
-static int update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- return SHA1_Update(EVP_MD_CTX_md_data(ctx), data, count);
-}
-
-static int final(EVP_MD_CTX *ctx, unsigned char *md)
-{
- return SHA1_Final(md, EVP_MD_CTX_md_data(ctx));
-}
-
-static int ctrl(EVP_MD_CTX *ctx, int cmd, int mslen, void *ms)
-{
- unsigned char padtmp[40];
- unsigned char sha1tmp[SHA_DIGEST_LENGTH];
-
- SHA_CTX *sha1;
-
- if (cmd != EVP_CTRL_SSL3_MASTER_SECRET)
- return -2;
-
- if (ctx == NULL)
- return 0;
-
- sha1 = EVP_MD_CTX_md_data(ctx);
-
- /* SSLv3 client auth handling: see RFC-6101 5.6.8 */
- if (mslen != 48)
- return 0;
-
- /* At this point hash contains all handshake messages, update
- * with master secret and pad_1.
- */
-
- if (SHA1_Update(sha1, ms, mslen) <= 0)
- return 0;
-
- /* Set padtmp to pad_1 value */
- memset(padtmp, 0x36, sizeof(padtmp));
-
- if (!SHA1_Update(sha1, padtmp, sizeof(padtmp)))
- return 0;
-
- if (!SHA1_Final(sha1tmp, sha1))
- return 0;
-
- /* Reinitialise context */
-
- if (!SHA1_Init(sha1))
- return 0;
-
- if (SHA1_Update(sha1, ms, mslen) <= 0)
- return 0;
-
- /* Set padtmp to pad_2 value */
- memset(padtmp, 0x5c, sizeof(padtmp));
-
- if (!SHA1_Update(sha1, padtmp, sizeof(padtmp)))
- return 0;
-
- if (!SHA1_Update(sha1, sha1tmp, sizeof(sha1tmp)))
- return 0;
-
- /* Now when ctx is finalised it will return the SSL v3 hash value */
- OPENSSL_cleanse(sha1tmp, sizeof(sha1tmp));
-
- return 1;
-
-}
-
-static const EVP_MD sha1_md = {
- NID_sha1,
- NID_sha1WithRSAEncryption,
- SHA_DIGEST_LENGTH,
- EVP_MD_FLAG_DIGALGID_ABSENT,
- init,
- update,
- final,
- NULL,
- NULL,
- SHA_CBLOCK,
- sizeof(EVP_MD *) + sizeof(SHA_CTX),
- ctrl
-};
-
-const EVP_MD *EVP_sha1(void)
-{
- return &sha1_md;
-}
-
-static int init224(EVP_MD_CTX *ctx)
-{
- return SHA224_Init(EVP_MD_CTX_md_data(ctx));
-}
-
-static int update224(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- return SHA224_Update(EVP_MD_CTX_md_data(ctx), data, count);
-}
-
-static int final224(EVP_MD_CTX *ctx, unsigned char *md)
-{
- return SHA224_Final(md, EVP_MD_CTX_md_data(ctx));
-}
-
-static int init256(EVP_MD_CTX *ctx)
-{
- return SHA256_Init(EVP_MD_CTX_md_data(ctx));
-}
-
-static int update256(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- return SHA256_Update(EVP_MD_CTX_md_data(ctx), data, count);
-}
-
-static int final256(EVP_MD_CTX *ctx, unsigned char *md)
-{
- return SHA256_Final(md, EVP_MD_CTX_md_data(ctx));
-}
-
-static const EVP_MD sha224_md = {
- NID_sha224,
- NID_sha224WithRSAEncryption,
- SHA224_DIGEST_LENGTH,
- EVP_MD_FLAG_DIGALGID_ABSENT,
- init224,
- update224,
- final224,
- NULL,
- NULL,
- SHA256_CBLOCK,
- sizeof(EVP_MD *) + sizeof(SHA256_CTX),
-};
-
-const EVP_MD *EVP_sha224(void)
-{
- return &sha224_md;
-}
-
-static const EVP_MD sha256_md = {
- NID_sha256,
- NID_sha256WithRSAEncryption,
- SHA256_DIGEST_LENGTH,
- EVP_MD_FLAG_DIGALGID_ABSENT,
- init256,
- update256,
- final256,
- NULL,
- NULL,
- SHA256_CBLOCK,
- sizeof(EVP_MD *) + sizeof(SHA256_CTX),
-};
-
-const EVP_MD *EVP_sha256(void)
-{
- return &sha256_md;
-}
-
-static int init512_224(EVP_MD_CTX *ctx)
-{
- return sha512_224_init(EVP_MD_CTX_md_data(ctx));
-}
-
-static int init512_256(EVP_MD_CTX *ctx)
-{
- return sha512_256_init(EVP_MD_CTX_md_data(ctx));
-}
-
-static int init384(EVP_MD_CTX *ctx)
-{
- return SHA384_Init(EVP_MD_CTX_md_data(ctx));
-}
-
-static int update384(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- return SHA384_Update(EVP_MD_CTX_md_data(ctx), data, count);
-}
-
-static int final384(EVP_MD_CTX *ctx, unsigned char *md)
-{
- return SHA384_Final(md, EVP_MD_CTX_md_data(ctx));
-}
-
-static int init512(EVP_MD_CTX *ctx)
-{
- return SHA512_Init(EVP_MD_CTX_md_data(ctx));
-}
-
-/* See comment in SHA224/256 section */
-static int update512(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- return SHA512_Update(EVP_MD_CTX_md_data(ctx), data, count);
-}
-
-static int final512(EVP_MD_CTX *ctx, unsigned char *md)
-{
- return SHA512_Final(md, EVP_MD_CTX_md_data(ctx));
-}
-
-static const EVP_MD sha512_224_md = {
- NID_sha512_224,
- NID_sha512_224WithRSAEncryption,
- SHA224_DIGEST_LENGTH,
- EVP_MD_FLAG_DIGALGID_ABSENT,
- init512_224,
- update512,
- final512,
- NULL,
- NULL,
- SHA512_CBLOCK,
- sizeof(EVP_MD *) + sizeof(SHA512_CTX),
-};
-
-const EVP_MD *EVP_sha512_224(void)
-{
- return &sha512_224_md;
-}
-
-static const EVP_MD sha512_256_md = {
- NID_sha512_256,
- NID_sha512_256WithRSAEncryption,
- SHA256_DIGEST_LENGTH,
- EVP_MD_FLAG_DIGALGID_ABSENT,
- init512_256,
- update512,
- final512,
- NULL,
- NULL,
- SHA512_CBLOCK,
- sizeof(EVP_MD *) + sizeof(SHA512_CTX),
-};
-
-const EVP_MD *EVP_sha512_256(void)
-{
- return &sha512_256_md;
-}
-
-static const EVP_MD sha384_md = {
- NID_sha384,
- NID_sha384WithRSAEncryption,
- SHA384_DIGEST_LENGTH,
- EVP_MD_FLAG_DIGALGID_ABSENT,
- init384,
- update384,
- final384,
- NULL,
- NULL,
- SHA512_CBLOCK,
- sizeof(EVP_MD *) + sizeof(SHA512_CTX),
-};
-
-const EVP_MD *EVP_sha384(void)
-{
- return &sha384_md;
-}
-
-static const EVP_MD sha512_md = {
- NID_sha512,
- NID_sha512WithRSAEncryption,
- SHA512_DIGEST_LENGTH,
- EVP_MD_FLAG_DIGALGID_ABSENT,
- init512,
- update512,
- final512,
- NULL,
- NULL,
- SHA512_CBLOCK,
- sizeof(EVP_MD *) + sizeof(SHA512_CTX),
-};
-
-const EVP_MD *EVP_sha512(void)
-{
- return &sha512_md;
-}
diff --git a/crypto/evp/m_sha3.c b/crypto/evp/m_sha3.c
deleted file mode 100644
index 54c592a3cce2..000000000000
--- a/crypto/evp/m_sha3.c
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include <openssl/evp.h>
-#include <openssl/objects.h>
-#include "crypto/evp.h"
-#include "evp_local.h"
-
-size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len,
- size_t r);
-void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r);
-
-#define KECCAK1600_WIDTH 1600
-
-typedef struct {
- uint64_t A[5][5];
- size_t block_size; /* cached ctx->digest->block_size */
- size_t md_size; /* output length, variable in XOF */
- size_t num; /* used bytes in below buffer */
- unsigned char buf[KECCAK1600_WIDTH / 8 - 32];
- unsigned char pad;
-} KECCAK1600_CTX;
-
-static int init(EVP_MD_CTX *evp_ctx, unsigned char pad)
-{
- KECCAK1600_CTX *ctx = evp_ctx->md_data;
- size_t bsz = evp_ctx->digest->block_size;
-
- if (bsz <= sizeof(ctx->buf)) {
- memset(ctx->A, 0, sizeof(ctx->A));
-
- ctx->num = 0;
- ctx->block_size = bsz;
- ctx->md_size = evp_ctx->digest->md_size;
- ctx->pad = pad;
-
- return 1;
- }
-
- return 0;
-}
-
-static int sha3_init(EVP_MD_CTX *evp_ctx)
-{
- return init(evp_ctx, '\x06');
-}
-
-static int shake_init(EVP_MD_CTX *evp_ctx)
-{
- return init(evp_ctx, '\x1f');
-}
-
-static int sha3_update(EVP_MD_CTX *evp_ctx, const void *_inp, size_t len)
-{
- KECCAK1600_CTX *ctx = evp_ctx->md_data;
- const unsigned char *inp = _inp;
- size_t bsz = ctx->block_size;
- size_t num, rem;
-
- if (len == 0)
- return 1;
-
- if ((num = ctx->num) != 0) { /* process intermediate buffer? */
- rem = bsz - num;
-
- if (len < rem) {
- memcpy(ctx->buf + num, inp, len);
- ctx->num += len;
- return 1;
- }
- /*
- * We have enough data to fill or overflow the intermediate
- * buffer. So we append |rem| bytes and process the block,
- * leaving the rest for later processing...
- */
- memcpy(ctx->buf + num, inp, rem);
- inp += rem, len -= rem;
- (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
- ctx->num = 0;
- /* ctx->buf is processed, ctx->num is guaranteed to be zero */
- }
-
- if (len >= bsz)
- rem = SHA3_absorb(ctx->A, inp, len, bsz);
- else
- rem = len;
-
- if (rem) {
- memcpy(ctx->buf, inp + len - rem, rem);
- ctx->num = rem;
- }
-
- return 1;
-}
-
-static int sha3_final(EVP_MD_CTX *evp_ctx, unsigned char *md)
-{
- KECCAK1600_CTX *ctx = evp_ctx->md_data;
- size_t bsz = ctx->block_size;
- size_t num = ctx->num;
-
- if (ctx->md_size == 0)
- return 1;
-
- /*
- * Pad the data with 10*1. Note that |num| can be |bsz - 1|
- * in which case both byte operations below are performed on
- * same byte...
- */
- memset(ctx->buf + num, 0, bsz - num);
- ctx->buf[num] = ctx->pad;
- ctx->buf[bsz - 1] |= 0x80;
-
- (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
-
- SHA3_squeeze(ctx->A, md, ctx->md_size, bsz);
-
- return 1;
-}
-
-static int shake_ctrl(EVP_MD_CTX *evp_ctx, int cmd, int p1, void *p2)
-{
- KECCAK1600_CTX *ctx = evp_ctx->md_data;
-
- switch (cmd) {
- case EVP_MD_CTRL_XOF_LEN:
- ctx->md_size = p1;
- return 1;
- default:
- return 0;
- }
-}
-
-#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) && defined(KECCAK1600_ASM)
-/*
- * IBM S390X support
- */
-# include "s390x_arch.h"
-
-# define S390X_SHA3_FC(ctx) ((ctx)->pad)
-
-# define S390X_sha3_224_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \
- S390X_CAPBIT(S390X_SHA3_224)) && \
- (OPENSSL_s390xcap_P.klmd[0] & \
- S390X_CAPBIT(S390X_SHA3_224)))
-# define S390X_sha3_256_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \
- S390X_CAPBIT(S390X_SHA3_256)) && \
- (OPENSSL_s390xcap_P.klmd[0] & \
- S390X_CAPBIT(S390X_SHA3_256)))
-# define S390X_sha3_384_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \
- S390X_CAPBIT(S390X_SHA3_384)) && \
- (OPENSSL_s390xcap_P.klmd[0] & \
- S390X_CAPBIT(S390X_SHA3_384)))
-# define S390X_sha3_512_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \
- S390X_CAPBIT(S390X_SHA3_512)) && \
- (OPENSSL_s390xcap_P.klmd[0] & \
- S390X_CAPBIT(S390X_SHA3_512)))
-# define S390X_shake128_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \
- S390X_CAPBIT(S390X_SHAKE_128)) && \
- (OPENSSL_s390xcap_P.klmd[0] & \
- S390X_CAPBIT(S390X_SHAKE_128)))
-# define S390X_shake256_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \
- S390X_CAPBIT(S390X_SHAKE_256)) && \
- (OPENSSL_s390xcap_P.klmd[0] & \
- S390X_CAPBIT(S390X_SHAKE_256)))
-
-/* Convert md-size to block-size. */
-# define S390X_KECCAK1600_BSZ(n) ((KECCAK1600_WIDTH - ((n) << 1)) >> 3)
-
-static int s390x_sha3_init(EVP_MD_CTX *evp_ctx)
-{
- KECCAK1600_CTX *ctx = evp_ctx->md_data;
- const size_t bsz = evp_ctx->digest->block_size;
-
- /*-
- * KECCAK1600_CTX structure's pad field is used to store the KIMD/KLMD
- * function code.
- */
- switch (bsz) {
- case S390X_KECCAK1600_BSZ(224):
- ctx->pad = S390X_SHA3_224;
- break;
- case S390X_KECCAK1600_BSZ(256):
- ctx->pad = S390X_SHA3_256;
- break;
- case S390X_KECCAK1600_BSZ(384):
- ctx->pad = S390X_SHA3_384;
- break;
- case S390X_KECCAK1600_BSZ(512):
- ctx->pad = S390X_SHA3_512;
- break;
- default:
- return 0;
- }
-
- memset(ctx->A, 0, sizeof(ctx->A));
- ctx->num = 0;
- ctx->block_size = bsz;
- ctx->md_size = evp_ctx->digest->md_size;
- return 1;
-}
-
-static int s390x_shake_init(EVP_MD_CTX *evp_ctx)
-{
- KECCAK1600_CTX *ctx = evp_ctx->md_data;
- const size_t bsz = evp_ctx->digest->block_size;
-
- /*-
- * KECCAK1600_CTX structure's pad field is used to store the KIMD/KLMD
- * function code.
- */
- switch (bsz) {
- case S390X_KECCAK1600_BSZ(128):
- ctx->pad = S390X_SHAKE_128;
- break;
- case S390X_KECCAK1600_BSZ(256):
- ctx->pad = S390X_SHAKE_256;
- break;
- default:
- return 0;
- }
-
- memset(ctx->A, 0, sizeof(ctx->A));
- ctx->num = 0;
- ctx->block_size = bsz;
- ctx->md_size = evp_ctx->digest->md_size;
- return 1;
-}
-
-static int s390x_sha3_update(EVP_MD_CTX *evp_ctx, const void *_inp, size_t len)
-{
- KECCAK1600_CTX *ctx = evp_ctx->md_data;
- const unsigned char *inp = _inp;
- const size_t bsz = ctx->block_size;
- size_t num, rem;
-
- if (len == 0)
- return 1;
-
- if ((num = ctx->num) != 0) {
- rem = bsz - num;
-
- if (len < rem) {
- memcpy(ctx->buf + num, inp, len);
- ctx->num += len;
- return 1;
- }
- memcpy(ctx->buf + num, inp, rem);
- inp += rem;
- len -= rem;
- s390x_kimd(ctx->buf, bsz, ctx->pad, ctx->A);
- ctx->num = 0;
- }
- rem = len % bsz;
-
- s390x_kimd(inp, len - rem, ctx->pad, ctx->A);
-
- if (rem) {
- memcpy(ctx->buf, inp + len - rem, rem);
- ctx->num = rem;
- }
- return 1;
-}
-
-static int s390x_sha3_final(EVP_MD_CTX *evp_ctx, unsigned char *md)
-{
- KECCAK1600_CTX *ctx = evp_ctx->md_data;
-
- s390x_klmd(ctx->buf, ctx->num, NULL, 0, ctx->pad, ctx->A);
- memcpy(md, ctx->A, ctx->md_size);
- return 1;
-}
-
-static int s390x_shake_final(EVP_MD_CTX *evp_ctx, unsigned char *md)
-{
- KECCAK1600_CTX *ctx = evp_ctx->md_data;
-
- s390x_klmd(ctx->buf, ctx->num, md, ctx->md_size, ctx->pad, ctx->A);
- return 1;
-}
-
-# define EVP_MD_SHA3(bitlen) \
-const EVP_MD *EVP_sha3_##bitlen(void) \
-{ \
- static const EVP_MD s390x_sha3_##bitlen##_md = { \
- NID_sha3_##bitlen, \
- NID_RSA_SHA3_##bitlen, \
- bitlen / 8, \
- EVP_MD_FLAG_DIGALGID_ABSENT, \
- s390x_sha3_init, \
- s390x_sha3_update, \
- s390x_sha3_final, \
- NULL, \
- NULL, \
- (KECCAK1600_WIDTH - bitlen * 2) / 8, \
- sizeof(KECCAK1600_CTX), \
- }; \
- static const EVP_MD sha3_##bitlen##_md = { \
- NID_sha3_##bitlen, \
- NID_RSA_SHA3_##bitlen, \
- bitlen / 8, \
- EVP_MD_FLAG_DIGALGID_ABSENT, \
- sha3_init, \
- sha3_update, \
- sha3_final, \
- NULL, \
- NULL, \
- (KECCAK1600_WIDTH - bitlen * 2) / 8, \
- sizeof(KECCAK1600_CTX), \
- }; \
- return S390X_sha3_##bitlen##_CAPABLE ? \
- &s390x_sha3_##bitlen##_md : \
- &sha3_##bitlen##_md; \
-}
-
-# define EVP_MD_SHAKE(bitlen) \
-const EVP_MD *EVP_shake##bitlen(void) \
-{ \
- static const EVP_MD s390x_shake##bitlen##_md = { \
- NID_shake##bitlen, \
- 0, \
- bitlen / 8, \
- EVP_MD_FLAG_XOF, \
- s390x_shake_init, \
- s390x_sha3_update, \
- s390x_shake_final, \
- NULL, \
- NULL, \
- (KECCAK1600_WIDTH - bitlen * 2) / 8, \
- sizeof(KECCAK1600_CTX), \
- shake_ctrl \
- }; \
- static const EVP_MD shake##bitlen##_md = { \
- NID_shake##bitlen, \
- 0, \
- bitlen / 8, \
- EVP_MD_FLAG_XOF, \
- shake_init, \
- sha3_update, \
- sha3_final, \
- NULL, \
- NULL, \
- (KECCAK1600_WIDTH - bitlen * 2) / 8, \
- sizeof(KECCAK1600_CTX), \
- shake_ctrl \
- }; \
- return S390X_shake##bitlen##_CAPABLE ? \
- &s390x_shake##bitlen##_md : \
- &shake##bitlen##_md; \
-}
-
-#else
-
-# define EVP_MD_SHA3(bitlen) \
-const EVP_MD *EVP_sha3_##bitlen(void) \
-{ \
- static const EVP_MD sha3_##bitlen##_md = { \
- NID_sha3_##bitlen, \
- NID_RSA_SHA3_##bitlen, \
- bitlen / 8, \
- EVP_MD_FLAG_DIGALGID_ABSENT, \
- sha3_init, \
- sha3_update, \
- sha3_final, \
- NULL, \
- NULL, \
- (KECCAK1600_WIDTH - bitlen * 2) / 8, \
- sizeof(KECCAK1600_CTX), \
- }; \
- return &sha3_##bitlen##_md; \
-}
-
-# define EVP_MD_SHAKE(bitlen) \
-const EVP_MD *EVP_shake##bitlen(void) \
-{ \
- static const EVP_MD shake##bitlen##_md = { \
- NID_shake##bitlen, \
- 0, \
- bitlen / 8, \
- EVP_MD_FLAG_XOF, \
- shake_init, \
- sha3_update, \
- sha3_final, \
- NULL, \
- NULL, \
- (KECCAK1600_WIDTH - bitlen * 2) / 8, \
- sizeof(KECCAK1600_CTX), \
- shake_ctrl \
- }; \
- return &shake##bitlen##_md; \
-}
-#endif
-
-EVP_MD_SHA3(224)
-EVP_MD_SHA3(256)
-EVP_MD_SHA3(384)
-EVP_MD_SHA3(512)
-
-EVP_MD_SHAKE(128)
-EVP_MD_SHAKE(256)
diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c
index 04643acc8837..76a6814b424b 100644
--- a/crypto/evp/m_sigver.c
+++ b/crypto/evp/m_sigver.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,25 +11,301 @@
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/objects.h>
-#include <openssl/x509.h>
#include "crypto/evp.h"
+#include "internal/provider.h"
+#include "internal/numbers.h" /* includes SIZE_MAX */
#include "evp_local.h"
+#ifndef FIPS_MODULE
+
static int update(EVP_MD_CTX *ctx, const void *data, size_t datalen)
{
- EVPerr(EVP_F_UPDATE, EVP_R_ONLY_ONESHOT_SUPPORTED);
+ ERR_raise(ERR_LIB_EVP, EVP_R_ONLY_ONESHOT_SUPPORTED);
return 0;
}
+/*
+ * If we get the "NULL" md then the name comes back as "UNDEF". We want to use
+ * NULL for this.
+ */
+static const char *canon_mdname(const char *mdname)
+{
+ if (mdname != NULL && strcmp(mdname, "UNDEF") == 0)
+ return NULL;
+
+ return mdname;
+}
+
static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
- const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey,
- int ver)
+ const EVP_MD *type, const char *mdname,
+ OSSL_LIB_CTX *libctx, const char *props,
+ ENGINE *e, EVP_PKEY *pkey, int ver,
+ const OSSL_PARAM params[])
{
+ EVP_PKEY_CTX *locpctx = NULL;
+ EVP_SIGNATURE *signature = NULL;
+ EVP_KEYMGMT *tmp_keymgmt = NULL;
+ const OSSL_PROVIDER *tmp_prov = NULL;
+ const char *supported_sig = NULL;
+ char locmdname[80] = ""; /* 80 chars should be enough */
+ void *provkey = NULL;
+ int ret, iter, reinit = 1;
+
+ if (ctx->algctx != NULL) {
+ if (!ossl_assert(ctx->digest != NULL)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+ if (ctx->digest->freectx != NULL)
+ ctx->digest->freectx(ctx->algctx);
+ ctx->algctx = NULL;
+ }
+
+ if (ctx->pctx == NULL) {
+ reinit = 0;
+ if (e == NULL)
+ ctx->pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, props);
+ else
+ ctx->pctx = EVP_PKEY_CTX_new(pkey, e);
+ }
if (ctx->pctx == NULL)
- ctx->pctx = EVP_PKEY_CTX_new(pkey, e);
- if (ctx->pctx == NULL)
return 0;
+ locpctx = ctx->pctx;
+ ERR_set_mark();
+
+ if (evp_pkey_ctx_is_legacy(locpctx))
+ goto legacy;
+
+ /* do not reinitialize if pkey is set or operation is different */
+ if (reinit
+ && (pkey != NULL
+ || locpctx->operation != (ver ? EVP_PKEY_OP_VERIFYCTX
+ : EVP_PKEY_OP_SIGNCTX)
+ || (signature = locpctx->op.sig.signature) == NULL
+ || locpctx->op.sig.algctx == NULL))
+ reinit = 0;
+
+ if (props == NULL)
+ props = locpctx->propquery;
+
+ if (locpctx->pkey == NULL) {
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET);
+ goto err;
+ }
+
+ if (!reinit) {
+ evp_pkey_ctx_free_old_ops(locpctx);
+ } else {
+ if (mdname == NULL && type == NULL)
+ mdname = canon_mdname(EVP_MD_get0_name(ctx->reqdigest));
+ goto reinitialize;
+ }
+
+ /*
+ * Try to derive the supported signature from |locpctx->keymgmt|.
+ */
+ if (!ossl_assert(locpctx->pkey->keymgmt == NULL
+ || locpctx->pkey->keymgmt == locpctx->keymgmt)) {
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ supported_sig = evp_keymgmt_util_query_operation_name(locpctx->keymgmt,
+ OSSL_OP_SIGNATURE);
+ if (supported_sig == NULL) {
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+
+ /*
+ * We perform two iterations:
+ *
+ * 1. Do the normal signature fetch, using the fetching data given by
+ * the EVP_PKEY_CTX.
+ * 2. Do the provider specific signature fetch, from the same provider
+ * as |ctx->keymgmt|
+ *
+ * We then try to fetch the keymgmt from the same provider as the
+ * signature, and try to export |ctx->pkey| to that keymgmt (when
+ * this keymgmt happens to be the same as |ctx->keymgmt|, the export
+ * is a no-op, but we call it anyway to not complicate the code even
+ * more).
+ * If the export call succeeds (returns a non-NULL provider key pointer),
+ * we're done and can perform the operation itself. If not, we perform
+ * the second iteration, or jump to legacy.
+ */
+ for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) {
+ EVP_KEYMGMT *tmp_keymgmt_tofree = NULL;
+
+ /*
+ * If we're on the second iteration, free the results from the first.
+ * They are NULL on the first iteration, so no need to check what
+ * iteration we're on.
+ */
+ EVP_SIGNATURE_free(signature);
+ EVP_KEYMGMT_free(tmp_keymgmt);
+
+ switch (iter) {
+ case 1:
+ signature = EVP_SIGNATURE_fetch(locpctx->libctx, supported_sig,
+ locpctx->propquery);
+ if (signature != NULL)
+ tmp_prov = EVP_SIGNATURE_get0_provider(signature);
+ break;
+ case 2:
+ tmp_prov = EVP_KEYMGMT_get0_provider(locpctx->keymgmt);
+ signature =
+ evp_signature_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
+ supported_sig, locpctx->propquery);
+ if (signature == NULL)
+ goto legacy;
+ break;
+ }
+ if (signature == NULL)
+ continue;
+
+ /*
+ * Ensure that the key is provided, either natively, or as a cached
+ * export. We start by fetching the keymgmt with the same name as
+ * |locpctx->pkey|, but from the provider of the signature method, using
+ * the same property query as when fetching the signature method.
+ * With the keymgmt we found (if we did), we try to export |locpctx->pkey|
+ * to it (evp_pkey_export_to_provider() is smart enough to only actually
+
+ * export it if |tmp_keymgmt| is different from |locpctx->pkey|'s keymgmt)
+ */
+ tmp_keymgmt_tofree = tmp_keymgmt =
+ evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
+ EVP_KEYMGMT_get0_name(locpctx->keymgmt),
+ locpctx->propquery);
+ if (tmp_keymgmt != NULL)
+ provkey = evp_pkey_export_to_provider(locpctx->pkey, locpctx->libctx,
+ &tmp_keymgmt, locpctx->propquery);
+ if (tmp_keymgmt == NULL)
+ EVP_KEYMGMT_free(tmp_keymgmt_tofree);
+ }
+
+ if (provkey == NULL) {
+ EVP_SIGNATURE_free(signature);
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+
+ ERR_pop_to_mark();
+
+ /* No more legacy from here down to legacy: */
+
+ locpctx->op.sig.signature = signature;
+ locpctx->operation = ver ? EVP_PKEY_OP_VERIFYCTX
+ : EVP_PKEY_OP_SIGNCTX;
+ locpctx->op.sig.algctx
+ = signature->newctx(ossl_provider_ctx(signature->prov), props);
+ if (locpctx->op.sig.algctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+
+ reinitialize:
+ if (pctx != NULL)
+ *pctx = locpctx;
+
+ if (type != NULL) {
+ ctx->reqdigest = type;
+ if (mdname == NULL)
+ mdname = canon_mdname(EVP_MD_get0_name(type));
+ } else {
+ if (mdname == NULL && !reinit) {
+ if (evp_keymgmt_util_get_deflt_digest_name(tmp_keymgmt, provkey,
+ locmdname,
+ sizeof(locmdname)) > 0) {
+ mdname = canon_mdname(locmdname);
+ }
+ }
+
+ if (mdname != NULL) {
+ /*
+ * We're about to get a new digest so clear anything associated with
+ * an old digest.
+ */
+ evp_md_ctx_clear_digest(ctx, 1, 0);
+
+ /* legacy code support for engines */
+ ERR_set_mark();
+ /*
+ * This might be requested by a later call to EVP_MD_CTX_get0_md().
+ * In that case the "explicit fetch" rules apply for that
+ * function (as per man pages), i.e. the ref count is not updated
+ * so the EVP_MD should not be used beyound the lifetime of the
+ * EVP_MD_CTX.
+ */
+ ctx->fetched_digest = EVP_MD_fetch(locpctx->libctx, mdname, props);
+ if (ctx->fetched_digest != NULL) {
+ ctx->digest = ctx->reqdigest = ctx->fetched_digest;
+ } else {
+ /* legacy engine support : remove the mark when this is deleted */
+ ctx->reqdigest = ctx->digest = EVP_get_digestbyname(mdname);
+ if (ctx->digest == NULL) {
+ (void)ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+ }
+ (void)ERR_pop_to_mark();
+ }
+ }
+
+ if (ver) {
+ if (signature->digest_verify_init == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+ ret = signature->digest_verify_init(locpctx->op.sig.algctx,
+ mdname, provkey, params);
+ } else {
+ if (signature->digest_sign_init == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+ ret = signature->digest_sign_init(locpctx->op.sig.algctx,
+ mdname, provkey, params);
+ }
+
+ /*
+ * If the operation was not a success and no digest was found, an error
+ * needs to be raised.
+ */
+ if (ret > 0 || mdname != NULL)
+ goto end;
+ if (type == NULL) /* This check is redundant but clarifies matters */
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_DEFAULT_DIGEST);
+
+ err:
+ evp_pkey_ctx_free_old_ops(locpctx);
+ locpctx->operation = EVP_PKEY_OP_UNDEFINED;
+ EVP_KEYMGMT_free(tmp_keymgmt);
+ return 0;
+
+ legacy:
+ /*
+ * If we don't have the full support we need with provided methods,
+ * let's go see if legacy does.
+ */
+ ERR_pop_to_mark();
+ EVP_KEYMGMT_free(tmp_keymgmt);
+ tmp_keymgmt = NULL;
+
+ if (type == NULL && mdname != NULL)
+ type = evp_get_digestbyname_ex(locpctx->libctx, mdname);
+
+ if (ctx->pctx->pmeth == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+
if (!(ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM)) {
if (type == NULL) {
@@ -39,7 +315,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
}
if (type == NULL) {
- EVPerr(EVP_F_DO_SIGVER_INIT, EVP_R_NO_DEFAULT_DIGEST);
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_DEFAULT_DIGEST);
return 0;
}
}
@@ -79,57 +355,184 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
* This indicates the current algorithm requires
* special treatment before hashing the tbs-message.
*/
+ ctx->pctx->flag_call_digest_custom = 0;
if (ctx->pctx->pmeth->digest_custom != NULL)
- return ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx);
+ ctx->pctx->flag_call_digest_custom = 1;
- return 1;
+ ret = 1;
+
+ end:
+#ifndef FIPS_MODULE
+ if (ret > 0)
+ ret = evp_pkey_ctx_use_cached_data(locpctx);
+#endif
+
+ EVP_KEYMGMT_free(tmp_keymgmt);
+ return ret > 0 ? 1 : 0;
+}
+
+int EVP_DigestSignInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+ const char *mdname, OSSL_LIB_CTX *libctx,
+ const char *props, EVP_PKEY *pkey,
+ const OSSL_PARAM params[])
+{
+ return do_sigver_init(ctx, pctx, NULL, mdname, libctx, props, NULL, pkey, 0,
+ params);
}
int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey)
{
- return do_sigver_init(ctx, pctx, type, e, pkey, 0);
+ return do_sigver_init(ctx, pctx, type, NULL, NULL, NULL, e, pkey, 0,
+ NULL);
+}
+
+int EVP_DigestVerifyInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+ const char *mdname, OSSL_LIB_CTX *libctx,
+ const char *props, EVP_PKEY *pkey,
+ const OSSL_PARAM params[])
+{
+ return do_sigver_init(ctx, pctx, NULL, mdname, libctx, props, NULL, pkey, 1,
+ params);
}
int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey)
{
- return do_sigver_init(ctx, pctx, type, e, pkey, 1);
+ return do_sigver_init(ctx, pctx, type, NULL, NULL, NULL, e, pkey, 1,
+ NULL);
+}
+#endif /* FIPS_MDOE */
+
+int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
+{
+ EVP_PKEY_CTX *pctx = ctx->pctx;
+
+ if (pctx == NULL
+ || pctx->operation != EVP_PKEY_OP_SIGNCTX
+ || pctx->op.sig.algctx == NULL
+ || pctx->op.sig.signature == NULL)
+ goto legacy;
+
+ if (pctx->op.sig.signature->digest_sign_update == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ return pctx->op.sig.signature->digest_sign_update(pctx->op.sig.algctx,
+ data, dsize);
+
+ legacy:
+ if (pctx != NULL) {
+ /* do_sigver_init() checked that |digest_custom| is non-NULL */
+ if (pctx->flag_call_digest_custom
+ && !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx))
+ return 0;
+ pctx->flag_call_digest_custom = 0;
+ }
+
+ return EVP_DigestUpdate(ctx, data, dsize);
+}
+
+int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
+{
+ EVP_PKEY_CTX *pctx = ctx->pctx;
+
+ if (pctx == NULL
+ || pctx->operation != EVP_PKEY_OP_VERIFYCTX
+ || pctx->op.sig.algctx == NULL
+ || pctx->op.sig.signature == NULL)
+ goto legacy;
+
+ if (pctx->op.sig.signature->digest_verify_update == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ return pctx->op.sig.signature->digest_verify_update(pctx->op.sig.algctx,
+ data, dsize);
+
+ legacy:
+ if (pctx != NULL) {
+ /* do_sigver_init() checked that |digest_custom| is non-NULL */
+ if (pctx->flag_call_digest_custom
+ && !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx))
+ return 0;
+ pctx->flag_call_digest_custom = 0;
+ }
+
+ return EVP_DigestUpdate(ctx, data, dsize);
}
+#ifndef FIPS_MODULE
int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
size_t *siglen)
{
int sctx = 0, r = 0;
- EVP_PKEY_CTX *pctx = ctx->pctx;
+ EVP_PKEY_CTX *dctx, *pctx = ctx->pctx;
+
+ if (pctx == NULL
+ || pctx->operation != EVP_PKEY_OP_SIGNCTX
+ || pctx->op.sig.algctx == NULL
+ || pctx->op.sig.signature == NULL)
+ goto legacy;
+
+ if (sigret == NULL || (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) != 0)
+ return pctx->op.sig.signature->digest_sign_final(pctx->op.sig.algctx,
+ sigret, siglen,
+ sigret == NULL ? 0 : *siglen);
+ dctx = EVP_PKEY_CTX_dup(pctx);
+ if (dctx == NULL)
+ return 0;
+
+ r = dctx->op.sig.signature->digest_sign_final(dctx->op.sig.algctx,
+ sigret, siglen,
+ *siglen);
+ EVP_PKEY_CTX_free(dctx);
+ return r;
+
+ legacy:
+ if (pctx == NULL || pctx->pmeth == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+
+ /* do_sigver_init() checked that |digest_custom| is non-NULL */
+ if (pctx->flag_call_digest_custom
+ && !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx))
+ return 0;
+ pctx->flag_call_digest_custom = 0;
+
if (pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) {
- if (!sigret)
+ if (sigret == NULL)
return pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE)
r = pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
else {
- EVP_PKEY_CTX *dctx = EVP_PKEY_CTX_dup(ctx->pctx);
- if (!dctx)
+ dctx = EVP_PKEY_CTX_dup(pctx);
+ if (dctx == NULL)
return 0;
r = dctx->pmeth->signctx(dctx, sigret, siglen, ctx);
EVP_PKEY_CTX_free(dctx);
}
return r;
}
- if (pctx->pmeth->signctx)
+ if (pctx->pmeth->signctx != NULL)
sctx = 1;
else
sctx = 0;
- if (sigret) {
+ if (sigret != NULL) {
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int mdlen = 0;
+
if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) {
if (sctx)
- r = ctx->pctx->pmeth->signctx(ctx->pctx, sigret, siglen, ctx);
+ r = pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
else
r = EVP_DigestFinal_ex(ctx, md, &mdlen);
} else {
EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new();
+
if (tmp_ctx == NULL)
return 0;
if (!EVP_MD_CTX_copy_ex(tmp_ctx, ctx)) {
@@ -145,14 +548,15 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
}
if (sctx || !r)
return r;
- if (EVP_PKEY_sign(ctx->pctx, sigret, siglen, md, mdlen) <= 0)
+ if (EVP_PKEY_sign(pctx, sigret, siglen, md, mdlen) <= 0)
return 0;
} else {
if (sctx) {
if (pctx->pmeth->signctx(pctx, sigret, siglen, ctx) <= 0)
return 0;
} else {
- int s = EVP_MD_size(ctx->digest);
+ int s = EVP_MD_get_size(ctx->digest);
+
if (s < 0 || EVP_PKEY_sign(pctx, sigret, siglen, NULL, s) <= 0)
return 0;
}
@@ -163,8 +567,23 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen,
const unsigned char *tbs, size_t tbslen)
{
- if (ctx->pctx->pmeth->digestsign != NULL)
- return ctx->pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen);
+ EVP_PKEY_CTX *pctx = ctx->pctx;
+
+ if (pctx != NULL
+ && pctx->operation == EVP_PKEY_OP_SIGNCTX
+ && pctx->op.sig.algctx != NULL
+ && pctx->op.sig.signature != NULL) {
+ if (pctx->op.sig.signature->digest_sign != NULL)
+ return pctx->op.sig.signature->digest_sign(pctx->op.sig.algctx,
+ sigret, siglen,
+ sigret == NULL ? 0 : *siglen,
+ tbs, tbslen);
+ } else {
+ /* legacy */
+ if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestsign != NULL)
+ return ctx->pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen);
+ }
+
if (sigret != NULL && EVP_DigestSignUpdate(ctx, tbs, tbslen) <= 0)
return 0;
return EVP_DigestSignFinal(ctx, sigret, siglen);
@@ -177,14 +596,45 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
int r = 0;
unsigned int mdlen = 0;
int vctx = 0;
+ EVP_PKEY_CTX *dctx, *pctx = ctx->pctx;
- if (ctx->pctx->pmeth->verifyctx)
+ if (pctx == NULL
+ || pctx->operation != EVP_PKEY_OP_VERIFYCTX
+ || pctx->op.sig.algctx == NULL
+ || pctx->op.sig.signature == NULL)
+ goto legacy;
+
+ if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISE) != 0)
+ return pctx->op.sig.signature->digest_verify_final(pctx->op.sig.algctx,
+ sig, siglen);
+ dctx = EVP_PKEY_CTX_dup(pctx);
+ if (dctx == NULL)
+ return 0;
+
+ r = dctx->op.sig.signature->digest_verify_final(dctx->op.sig.algctx,
+ sig, siglen);
+ EVP_PKEY_CTX_free(dctx);
+ return r;
+
+ legacy:
+ if (pctx == NULL || pctx->pmeth == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+
+ /* do_sigver_init() checked that |digest_custom| is non-NULL */
+ if (pctx->flag_call_digest_custom
+ && !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx))
+ return 0;
+ pctx->flag_call_digest_custom = 0;
+
+ if (pctx->pmeth->verifyctx != NULL)
vctx = 1;
else
vctx = 0;
if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) {
if (vctx)
- r = ctx->pctx->pmeth->verifyctx(ctx->pctx, sig, siglen, ctx);
+ r = pctx->pmeth->verifyctx(pctx, sig, siglen, ctx);
else
r = EVP_DigestFinal_ex(ctx, md, &mdlen);
} else {
@@ -204,15 +654,30 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
}
if (vctx || !r)
return r;
- return EVP_PKEY_verify(ctx->pctx, sig, siglen, md, mdlen);
+ return EVP_PKEY_verify(pctx, sig, siglen, md, mdlen);
}
int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
size_t siglen, const unsigned char *tbs, size_t tbslen)
{
- if (ctx->pctx->pmeth->digestverify != NULL)
- return ctx->pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen);
+ EVP_PKEY_CTX *pctx = ctx->pctx;
+
+ if (pctx != NULL
+ && pctx->operation == EVP_PKEY_OP_VERIFYCTX
+ && pctx->op.sig.algctx != NULL
+ && pctx->op.sig.signature != NULL) {
+ if (pctx->op.sig.signature->digest_verify != NULL)
+ return pctx->op.sig.signature->digest_verify(pctx->op.sig.algctx,
+ sigret, siglen,
+ tbs, tbslen);
+ } else {
+ /* legacy */
+ if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestverify != NULL)
+ return ctx->pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen);
+ }
+
if (EVP_DigestVerifyUpdate(ctx, tbs, tbslen) <= 0)
return -1;
return EVP_DigestVerifyFinal(ctx, sigret, siglen);
}
+#endif /* FIPS_MODULE */
diff --git a/crypto/evp/m_wp.c b/crypto/evp/m_wp.c
deleted file mode 100644
index 5ce15d2d5e57..000000000000
--- a/crypto/evp/m_wp.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-
-#ifndef OPENSSL_NO_WHIRLPOOL
-
-# include <openssl/evp.h>
-# include <openssl/objects.h>
-# include <openssl/x509.h>
-# include <openssl/whrlpool.h>
-# include "crypto/evp.h"
-
-static int init(EVP_MD_CTX *ctx)
-{
- return WHIRLPOOL_Init(EVP_MD_CTX_md_data(ctx));
-}
-
-static int update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- return WHIRLPOOL_Update(EVP_MD_CTX_md_data(ctx), data, count);
-}
-
-static int final(EVP_MD_CTX *ctx, unsigned char *md)
-{
- return WHIRLPOOL_Final(md, EVP_MD_CTX_md_data(ctx));
-}
-
-static const EVP_MD whirlpool_md = {
- NID_whirlpool,
- 0,
- WHIRLPOOL_DIGEST_LENGTH,
- 0,
- init,
- update,
- final,
- NULL,
- NULL,
- WHIRLPOOL_BBLOCK / 8,
- sizeof(EVP_MD *) + sizeof(WHIRLPOOL_CTX),
-};
-
-const EVP_MD *EVP_whirlpool(void)
-{
- return &whirlpool_md;
-}
-#endif
diff --git a/crypto/evp/mac_lib.c b/crypto/evp/mac_lib.c
new file mode 100644
index 000000000000..90c79715d757
--- /dev/null
+++ b/crypto/evp/mac_lib.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <stdarg.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/core.h>
+#include <openssl/core_names.h>
+#include <openssl/types.h>
+#include "internal/nelem.h"
+#include "crypto/evp.h"
+#include "internal/provider.h"
+#include "evp_local.h"
+
+EVP_MAC_CTX *EVP_MAC_CTX_new(EVP_MAC *mac)
+{
+ EVP_MAC_CTX *ctx = OPENSSL_zalloc(sizeof(EVP_MAC_CTX));
+
+ if (ctx == NULL
+ || (ctx->algctx = mac->newctx(ossl_provider_ctx(mac->prov))) == NULL
+ || !EVP_MAC_up_ref(mac)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ if (ctx != NULL)
+ mac->freectx(ctx->algctx);
+ OPENSSL_free(ctx);
+ ctx = NULL;
+ } else {
+ ctx->meth = mac;
+ }
+ return ctx;
+}
+
+void EVP_MAC_CTX_free(EVP_MAC_CTX *ctx)
+{
+ if (ctx == NULL)
+ return;
+ ctx->meth->freectx(ctx->algctx);
+ ctx->algctx = NULL;
+ /* refcnt-- */
+ EVP_MAC_free(ctx->meth);
+ OPENSSL_free(ctx);
+}
+
+EVP_MAC_CTX *EVP_MAC_CTX_dup(const EVP_MAC_CTX *src)
+{
+ EVP_MAC_CTX *dst;
+
+ if (src->algctx == NULL)
+ return NULL;
+
+ dst = OPENSSL_malloc(sizeof(*dst));
+ if (dst == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ *dst = *src;
+ if (!EVP_MAC_up_ref(dst->meth)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(dst);
+ return NULL;
+ }
+
+ dst->algctx = src->meth->dupctx(src->algctx);
+ if (dst->algctx == NULL) {
+ EVP_MAC_CTX_free(dst);
+ return NULL;
+ }
+
+ return dst;
+}
+
+EVP_MAC *EVP_MAC_CTX_get0_mac(EVP_MAC_CTX *ctx)
+{
+ return ctx->meth;
+}
+
+static size_t get_size_t_ctx_param(EVP_MAC_CTX *ctx, const char *name)
+{
+ size_t sz = 0;
+
+ if (ctx->algctx != NULL) {
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] = OSSL_PARAM_construct_size_t(name, &sz);
+ if (ctx->meth->get_ctx_params != NULL) {
+ if (ctx->meth->get_ctx_params(ctx->algctx, params))
+ return sz;
+ } else if (ctx->meth->get_params != NULL) {
+ if (ctx->meth->get_params(params))
+ return sz;
+ }
+ }
+ /*
+ * If the MAC hasn't been initialized yet, or there is no size to get,
+ * we return zero
+ */
+ return 0;
+}
+
+size_t EVP_MAC_CTX_get_mac_size(EVP_MAC_CTX *ctx)
+{
+ return get_size_t_ctx_param(ctx, OSSL_MAC_PARAM_SIZE);
+}
+
+size_t EVP_MAC_CTX_get_block_size(EVP_MAC_CTX *ctx)
+{
+ return get_size_t_ctx_param(ctx, OSSL_MAC_PARAM_BLOCK_SIZE);
+}
+
+int EVP_MAC_init(EVP_MAC_CTX *ctx, const unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ return ctx->meth->init(ctx->algctx, key, keylen, params);
+}
+
+int EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen)
+{
+ return ctx->meth->update(ctx->algctx, data, datalen);
+}
+
+static int evp_mac_final(EVP_MAC_CTX *ctx, int xof,
+ unsigned char *out, size_t *outl, size_t outsize)
+{
+ size_t l;
+ int res;
+ OSSL_PARAM params[2];
+ size_t macsize;
+
+ if (ctx == NULL || ctx->meth == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_NULL_ALGORITHM);
+ return 0;
+ }
+ if (ctx->meth->final == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
+ return 0;
+ }
+
+ macsize = EVP_MAC_CTX_get_mac_size(ctx);
+ if (out == NULL) {
+ if (outl == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ *outl = macsize;
+ return 1;
+ }
+ if (outsize < macsize) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+ if (xof) {
+ params[0] = OSSL_PARAM_construct_int(OSSL_MAC_PARAM_XOF, &xof);
+ params[1] = OSSL_PARAM_construct_end();
+
+ if (EVP_MAC_CTX_set_params(ctx, params) <= 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_SETTING_XOF_FAILED);
+ return 0;
+ }
+ }
+ res = ctx->meth->final(ctx->algctx, out, &l, outsize);
+ if (outl != NULL)
+ *outl = l;
+ return res;
+}
+
+int EVP_MAC_final(EVP_MAC_CTX *ctx,
+ unsigned char *out, size_t *outl, size_t outsize)
+{
+ return evp_mac_final(ctx, 0, out, outl, outsize);
+}
+
+int EVP_MAC_finalXOF(EVP_MAC_CTX *ctx, unsigned char *out, size_t outsize)
+{
+ return evp_mac_final(ctx, 1, out, NULL, outsize);
+}
+
+/*
+ * The {get,set}_params functions return 1 if there is no corresponding
+ * function in the implementation. This is the same as if there was one,
+ * but it didn't recognise any of the given params, i.e. nothing in the
+ * bag of parameters was useful.
+ */
+int EVP_MAC_get_params(EVP_MAC *mac, OSSL_PARAM params[])
+{
+ if (mac->get_params != NULL)
+ return mac->get_params(params);
+ return 1;
+}
+
+int EVP_MAC_CTX_get_params(EVP_MAC_CTX *ctx, OSSL_PARAM params[])
+{
+ if (ctx->meth->get_ctx_params != NULL)
+ return ctx->meth->get_ctx_params(ctx->algctx, params);
+ return 1;
+}
+
+int EVP_MAC_CTX_set_params(EVP_MAC_CTX *ctx, const OSSL_PARAM params[])
+{
+ if (ctx->meth->set_ctx_params != NULL)
+ return ctx->meth->set_ctx_params(ctx->algctx, params);
+ return 1;
+}
+
+int evp_mac_get_number(const EVP_MAC *mac)
+{
+ return mac->name_id;
+}
+
+const char *EVP_MAC_get0_name(const EVP_MAC *mac)
+{
+ return mac->type_name;
+}
+
+const char *EVP_MAC_get0_description(const EVP_MAC *mac)
+{
+ return mac->description;
+}
+
+int EVP_MAC_is_a(const EVP_MAC *mac, const char *name)
+{
+ return mac != NULL && evp_is_a(mac->prov, mac->name_id, NULL, name);
+}
+
+int EVP_MAC_names_do_all(const EVP_MAC *mac,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (mac->prov != NULL)
+ return evp_names_do_all(mac->prov, mac->name_id, fn, data);
+
+ return 1;
+}
+
+unsigned char *EVP_Q_mac(OSSL_LIB_CTX *libctx,
+ const char *name, const char *propq,
+ const char *subalg, const OSSL_PARAM *params,
+ const void *key, size_t keylen,
+ const unsigned char *data, size_t datalen,
+ unsigned char *out, size_t outsize, size_t *outlen)
+{
+ EVP_MAC *mac = EVP_MAC_fetch(libctx, name, propq);
+ OSSL_PARAM subalg_param[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ EVP_MAC_CTX *ctx = NULL;
+ size_t len = 0;
+ unsigned char *res = NULL;
+
+ if (outlen != NULL)
+ *outlen = 0;
+ if (mac == NULL)
+ return NULL;
+ if (subalg != NULL) {
+ const OSSL_PARAM *defined_params = EVP_MAC_settable_ctx_params(mac);
+ const char *param_name = OSSL_MAC_PARAM_DIGEST;
+
+ /*
+ * The underlying algorithm may be a cipher or a digest.
+ * We don't know which it is, but we can ask the MAC what it
+ * should be and bet on that.
+ */
+ if (OSSL_PARAM_locate_const(defined_params, param_name) == NULL) {
+ param_name = OSSL_MAC_PARAM_CIPHER;
+ if (OSSL_PARAM_locate_const(defined_params, param_name) == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
+ goto err;
+ }
+ }
+ subalg_param[0] =
+ OSSL_PARAM_construct_utf8_string(param_name, (char *)subalg, 0);
+ }
+ /* Single-shot - on NULL key input, set dummy key value for EVP_MAC_Init. */
+ if (key == NULL && keylen == 0)
+ key = data;
+ if ((ctx = EVP_MAC_CTX_new(mac)) != NULL
+ && EVP_MAC_CTX_set_params(ctx, subalg_param)
+ && EVP_MAC_CTX_set_params(ctx, params)
+ && EVP_MAC_init(ctx, key, keylen, params)
+ && EVP_MAC_update(ctx, data, datalen)
+ && EVP_MAC_final(ctx, out, &len, outsize)) {
+ if (out == NULL) {
+ out = OPENSSL_malloc(len);
+ if (out != NULL && !EVP_MAC_final(ctx, out, NULL, len)) {
+ OPENSSL_free(out);
+ out = NULL;
+ }
+ }
+ res = out;
+ if (res != NULL && outlen != NULL)
+ *outlen = len;
+ }
+
+ err:
+ EVP_MAC_CTX_free(ctx);
+ EVP_MAC_free(mac);
+ return res;
+}
diff --git a/crypto/evp/mac_meth.c b/crypto/evp/mac_meth.c
new file mode 100644
index 000000000000..85fe7704fde2
--- /dev/null
+++ b/crypto/evp/mac_meth.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include "internal/provider.h"
+#include "internal/core.h"
+#include "crypto/evp.h"
+#include "evp_local.h"
+
+static int evp_mac_up_ref(void *vmac)
+{
+ EVP_MAC *mac = vmac;
+ int ref = 0;
+
+ CRYPTO_UP_REF(&mac->refcnt, &ref, mac->lock);
+ return 1;
+}
+
+static void evp_mac_free(void *vmac)
+{
+ EVP_MAC *mac = vmac;
+ int ref = 0;
+
+ if (mac == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&mac->refcnt, &ref, mac->lock);
+ if (ref > 0)
+ return;
+ OPENSSL_free(mac->type_name);
+ ossl_provider_free(mac->prov);
+ CRYPTO_THREAD_lock_free(mac->lock);
+ OPENSSL_free(mac);
+}
+
+static void *evp_mac_new(void)
+{
+ EVP_MAC *mac = NULL;
+
+ if ((mac = OPENSSL_zalloc(sizeof(*mac))) == NULL
+ || (mac->lock = CRYPTO_THREAD_lock_new()) == NULL) {
+ evp_mac_free(mac);
+ return NULL;
+ }
+
+ mac->refcnt = 1;
+
+ return mac;
+}
+
+static void *evp_mac_from_algorithm(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
+{
+ const OSSL_DISPATCH *fns = algodef->implementation;
+ EVP_MAC *mac = NULL;
+ int fnmaccnt = 0, fnctxcnt = 0;
+
+ if ((mac = evp_mac_new()) == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ mac->name_id = name_id;
+ if ((mac->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
+ evp_mac_free(mac);
+ return NULL;
+ }
+ mac->description = algodef->algorithm_description;
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_MAC_NEWCTX:
+ if (mac->newctx != NULL)
+ break;
+ mac->newctx = OSSL_FUNC_mac_newctx(fns);
+ fnctxcnt++;
+ break;
+ case OSSL_FUNC_MAC_DUPCTX:
+ if (mac->dupctx != NULL)
+ break;
+ mac->dupctx = OSSL_FUNC_mac_dupctx(fns);
+ break;
+ case OSSL_FUNC_MAC_FREECTX:
+ if (mac->freectx != NULL)
+ break;
+ mac->freectx = OSSL_FUNC_mac_freectx(fns);
+ fnctxcnt++;
+ break;
+ case OSSL_FUNC_MAC_INIT:
+ if (mac->init != NULL)
+ break;
+ mac->init = OSSL_FUNC_mac_init(fns);
+ fnmaccnt++;
+ break;
+ case OSSL_FUNC_MAC_UPDATE:
+ if (mac->update != NULL)
+ break;
+ mac->update = OSSL_FUNC_mac_update(fns);
+ fnmaccnt++;
+ break;
+ case OSSL_FUNC_MAC_FINAL:
+ if (mac->final != NULL)
+ break;
+ mac->final = OSSL_FUNC_mac_final(fns);
+ fnmaccnt++;
+ break;
+ case OSSL_FUNC_MAC_GETTABLE_PARAMS:
+ if (mac->gettable_params != NULL)
+ break;
+ mac->gettable_params =
+ OSSL_FUNC_mac_gettable_params(fns);
+ break;
+ case OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS:
+ if (mac->gettable_ctx_params != NULL)
+ break;
+ mac->gettable_ctx_params =
+ OSSL_FUNC_mac_gettable_ctx_params(fns);
+ break;
+ case OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS:
+ if (mac->settable_ctx_params != NULL)
+ break;
+ mac->settable_ctx_params =
+ OSSL_FUNC_mac_settable_ctx_params(fns);
+ break;
+ case OSSL_FUNC_MAC_GET_PARAMS:
+ if (mac->get_params != NULL)
+ break;
+ mac->get_params = OSSL_FUNC_mac_get_params(fns);
+ break;
+ case OSSL_FUNC_MAC_GET_CTX_PARAMS:
+ if (mac->get_ctx_params != NULL)
+ break;
+ mac->get_ctx_params = OSSL_FUNC_mac_get_ctx_params(fns);
+ break;
+ case OSSL_FUNC_MAC_SET_CTX_PARAMS:
+ if (mac->set_ctx_params != NULL)
+ break;
+ mac->set_ctx_params = OSSL_FUNC_mac_set_ctx_params(fns);
+ break;
+ }
+ }
+ if (fnmaccnt != 3
+ || fnctxcnt != 2) {
+ /*
+ * In order to be a consistent set of functions we must have at least
+ * a complete set of "mac" functions, and a complete set of context
+ * management functions, as well as the size function.
+ */
+ evp_mac_free(mac);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+ return NULL;
+ }
+ mac->prov = prov;
+ if (prov != NULL)
+ ossl_provider_up_ref(prov);
+
+ return mac;
+}
+
+EVP_MAC *EVP_MAC_fetch(OSSL_LIB_CTX *libctx, const char *algorithm,
+ const char *properties)
+{
+ return evp_generic_fetch(libctx, OSSL_OP_MAC, algorithm, properties,
+ evp_mac_from_algorithm, evp_mac_up_ref,
+ evp_mac_free);
+}
+
+int EVP_MAC_up_ref(EVP_MAC *mac)
+{
+ return evp_mac_up_ref(mac);
+}
+
+void EVP_MAC_free(EVP_MAC *mac)
+{
+ evp_mac_free(mac);
+}
+
+const OSSL_PROVIDER *EVP_MAC_get0_provider(const EVP_MAC *mac)
+{
+ return mac->prov;
+}
+
+const OSSL_PARAM *EVP_MAC_gettable_params(const EVP_MAC *mac)
+{
+ if (mac->gettable_params == NULL)
+ return NULL;
+ return mac->gettable_params(ossl_provider_ctx(EVP_MAC_get0_provider(mac)));
+}
+
+const OSSL_PARAM *EVP_MAC_gettable_ctx_params(const EVP_MAC *mac)
+{
+ void *alg;
+
+ if (mac->gettable_ctx_params == NULL)
+ return NULL;
+ alg = ossl_provider_ctx(EVP_MAC_get0_provider(mac));
+ return mac->gettable_ctx_params(NULL, alg);
+}
+
+const OSSL_PARAM *EVP_MAC_settable_ctx_params(const EVP_MAC *mac)
+{
+ void *alg;
+
+ if (mac->settable_ctx_params == NULL)
+ return NULL;
+ alg = ossl_provider_ctx(EVP_MAC_get0_provider(mac));
+ return mac->settable_ctx_params(NULL, alg);
+}
+
+const OSSL_PARAM *EVP_MAC_CTX_gettable_params(EVP_MAC_CTX *ctx)
+{
+ void *alg;
+
+ if (ctx->meth->gettable_ctx_params == NULL)
+ return NULL;
+ alg = ossl_provider_ctx(EVP_MAC_get0_provider(ctx->meth));
+ return ctx->meth->gettable_ctx_params(ctx->algctx, alg);
+}
+
+const OSSL_PARAM *EVP_MAC_CTX_settable_params(EVP_MAC_CTX *ctx)
+{
+ void *alg;
+
+ if (ctx->meth->settable_ctx_params == NULL)
+ return NULL;
+ alg = ossl_provider_ctx(EVP_MAC_get0_provider(ctx->meth));
+ return ctx->meth->settable_ctx_params(ctx->algctx, alg);
+}
+
+void EVP_MAC_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_MAC *mac, void *arg),
+ void *arg)
+{
+ evp_generic_do_all(libctx, OSSL_OP_MAC,
+ (void (*)(void *, void *))fn, arg,
+ evp_mac_from_algorithm, evp_mac_up_ref, evp_mac_free);
+}
diff --git a/crypto/evp/names.c b/crypto/evp/names.c
index 90c7b73b7a49..19c03a3085e8 100644
--- a/crypto/evp/names.c
+++ b/crypto/evp/names.c
@@ -1,17 +1,19 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
-#include "internal/cryptlib.h"
#include <openssl/evp.h>
-#include "crypto/objects.h"
+#include <openssl/kdf.h>
#include <openssl/x509.h>
+#include "internal/cryptlib.h"
+#include "internal/namemap.h"
+#include "crypto/objects.h"
#include "crypto/evp.h"
int EVP_add_cipher(const EVP_CIPHER *c)
@@ -55,30 +57,102 @@ int EVP_add_digest(const EVP_MD *md)
return r;
}
+static void cipher_from_name(const char *name, void *data)
+{
+ const EVP_CIPHER **cipher = data;
+
+ if (*cipher != NULL)
+ return;
+
+ *cipher = (const EVP_CIPHER *)OBJ_NAME_get(name, OBJ_NAME_TYPE_CIPHER_METH);
+}
+
const EVP_CIPHER *EVP_get_cipherbyname(const char *name)
{
+ return evp_get_cipherbyname_ex(NULL, name);
+}
+
+const EVP_CIPHER *evp_get_cipherbyname_ex(OSSL_LIB_CTX *libctx,
+ const char *name)
+{
const EVP_CIPHER *cp;
+ OSSL_NAMEMAP *namemap;
+ int id;
if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL))
return NULL;
cp = (const EVP_CIPHER *)OBJ_NAME_get(name, OBJ_NAME_TYPE_CIPHER_METH);
+
+ if (cp != NULL)
+ return cp;
+
+ /*
+ * It's not in the method database, but it might be there under a different
+ * name. So we check for aliases in the EVP namemap and try all of those
+ * in turn.
+ */
+
+ namemap = ossl_namemap_stored(libctx);
+ id = ossl_namemap_name2num(namemap, name);
+ if (id == 0)
+ return NULL;
+
+ if (!ossl_namemap_doall_names(namemap, id, cipher_from_name, &cp))
+ return NULL;
+
return cp;
}
+static void digest_from_name(const char *name, void *data)
+{
+ const EVP_MD **md = data;
+
+ if (*md != NULL)
+ return;
+
+ *md = (const EVP_MD *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH);
+}
+
const EVP_MD *EVP_get_digestbyname(const char *name)
{
- const EVP_MD *cp;
+ return evp_get_digestbyname_ex(NULL, name);
+}
+
+const EVP_MD *evp_get_digestbyname_ex(OSSL_LIB_CTX *libctx, const char *name)
+{
+ const EVP_MD *dp;
+ OSSL_NAMEMAP *namemap;
+ int id;
if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL))
return NULL;
- cp = (const EVP_MD *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH);
- return cp;
+ dp = (const EVP_MD *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH);
+
+ if (dp != NULL)
+ return dp;
+
+ /*
+ * It's not in the method database, but it might be there under a different
+ * name. So we check for aliases in the EVP namemap and try all of those
+ * in turn.
+ */
+
+ namemap = ossl_namemap_stored(libctx);
+ id = ossl_namemap_name2num(namemap, name);
+ if (id == 0)
+ return NULL;
+
+ if (!ossl_namemap_doall_names(namemap, id, digest_from_name, &dp))
+ return NULL;
+
+ return dp;
}
void evp_cleanup_int(void)
{
+ OBJ_NAME_cleanup(OBJ_NAME_TYPE_KDF_METH);
OBJ_NAME_cleanup(OBJ_NAME_TYPE_CIPHER_METH);
OBJ_NAME_cleanup(OBJ_NAME_TYPE_MD_METH);
/*
diff --git a/crypto/evp/p5_crpt.c b/crypto/evp/p5_crpt.c
index 6c5f45f73368..f3ac675ff2e3 100644
--- a/crypto/evp/p5_crpt.c
+++ b/crypto/evp/p5_crpt.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,6 +12,8 @@
#include "internal/cryptlib.h"
#include <openssl/x509.h>
#include <openssl/evp.h>
+#include <openssl/core_names.h>
+#include <openssl/kdf.h>
/*
* Doesn't do anything now: Builtin PBE algorithms in static table.
@@ -21,85 +23,79 @@ void PKCS5_PBE_add(void)
{
}
-int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
- ASN1_TYPE *param, const EVP_CIPHER *cipher,
- const EVP_MD *md, int en_de)
+int PKCS5_PBE_keyivgen_ex(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md, int en_de, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
- EVP_MD_CTX *ctx;
unsigned char md_tmp[EVP_MAX_MD_SIZE];
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
- int i, ivl, kl;
- PBEPARAM *pbe;
+ int ivl, kl;
+ PBEPARAM *pbe = NULL;
int saltlen, iter;
unsigned char *salt;
int mdsize;
int rv = 0;
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx = NULL;
+ OSSL_PARAM params[5], *p = params;
+ const char *mdname = EVP_MD_name(md);
/* Extract useful info from parameter */
if (param == NULL || param->type != V_ASN1_SEQUENCE ||
param->value.sequence == NULL) {
- EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN, EVP_R_DECODE_ERROR);
+ ERR_raise(ERR_LIB_EVP, EVP_R_DECODE_ERROR);
return 0;
}
pbe = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBEPARAM), param);
if (pbe == NULL) {
- EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN, EVP_R_DECODE_ERROR);
+ ERR_raise(ERR_LIB_EVP, EVP_R_DECODE_ERROR);
return 0;
}
- ivl = EVP_CIPHER_iv_length(cipher);
+ ivl = EVP_CIPHER_get_iv_length(cipher);
if (ivl < 0 || ivl > 16) {
- EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN, EVP_R_INVALID_IV_LENGTH);
- PBEPARAM_free(pbe);
- return 0;
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH);
+ goto err;
}
- kl = EVP_CIPHER_key_length(cipher);
+ kl = EVP_CIPHER_get_key_length(cipher);
if (kl < 0 || kl > (int)sizeof(md_tmp)) {
- EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN, EVP_R_INVALID_KEY_LENGTH);
- PBEPARAM_free(pbe);
- return 0;
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH);
+ goto err;
}
- if (!pbe->iter)
+ if (pbe->iter == NULL)
iter = 1;
else
iter = ASN1_INTEGER_get(pbe->iter);
salt = pbe->salt->data;
saltlen = pbe->salt->length;
- if (!pass)
+ if (pass == NULL)
passlen = 0;
else if (passlen == -1)
passlen = strlen(pass);
- ctx = EVP_MD_CTX_new();
- if (ctx == NULL) {
- EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN, ERR_R_MALLOC_FAILURE);
+ mdsize = EVP_MD_get_size(md);
+ if (mdsize < 0)
goto err;
- }
- if (!EVP_DigestInit_ex(ctx, md, NULL))
- goto err;
- if (!EVP_DigestUpdate(ctx, pass, passlen))
- goto err;
- if (!EVP_DigestUpdate(ctx, salt, saltlen))
+ kdf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_PBKDF1, propq);
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+ if (kctx == NULL)
goto err;
- PBEPARAM_free(pbe);
- pbe = NULL;
- if (!EVP_DigestFinal_ex(ctx, md_tmp, NULL))
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
+ (char *)pass, (size_t)passlen);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ salt, saltlen);
+ *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_ITER, &iter);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ (char *)mdname, 0);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, md_tmp, mdsize, params) != 1)
goto err;
- mdsize = EVP_MD_size(md);
- if (mdsize < 0)
- return 0;
- for (i = 1; i < iter; i++) {
- if (!EVP_DigestInit_ex(ctx, md, NULL))
- goto err;
- if (!EVP_DigestUpdate(ctx, md_tmp, mdsize))
- goto err;
- if (!EVP_DigestFinal_ex(ctx, md_tmp, NULL))
- goto err;
- }
memcpy(key, md_tmp, kl);
memcpy(iv, md_tmp + (16 - ivl), ivl);
if (!EVP_CipherInit_ex(cctx, cipher, NULL, key, iv, en_de))
@@ -109,7 +105,16 @@ int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH);
rv = 1;
err:
+ EVP_KDF_CTX_free(kctx);
PBEPARAM_free(pbe);
- EVP_MD_CTX_free(ctx);
return rv;
}
+
+int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md, int en_de)
+{
+ return PKCS5_PBE_keyivgen_ex(cctx, pass, passlen, param, cipher, md, en_de,
+ NULL, NULL);
+}
+
diff --git a/crypto/evp/p5_crpt2.c b/crypto/evp/p5_crpt2.c
index 7f625b3d57f3..b7455be1cf0a 100644
--- a/crypto/evp/p5_crpt2.c
+++ b/crypto/evp/p5_crpt2.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,123 +10,97 @@
#include <stdio.h>
#include <stdlib.h>
#include "internal/cryptlib.h"
-# include <openssl/x509.h>
-# include <openssl/evp.h>
-# include <openssl/hmac.h>
-# include "evp_local.h"
+#include <openssl/x509.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/hmac.h>
+#include <openssl/trace.h>
+#include <openssl/core_names.h>
+#include "crypto/evp.h"
+#include "evp_local.h"
-/* set this to print out info about the keygen algorithm */
-/* #define OPENSSL_DEBUG_PKCS5V2 */
-
-# ifdef OPENSSL_DEBUG_PKCS5V2
-static void h__dump(const unsigned char *p, int len);
-# endif
-
-/*
- * This is an implementation of PKCS#5 v2.0 password based encryption key
- * derivation function PBKDF2. SHA1 version verified against test vectors
- * posted by Peter Gutmann to the PKCS-TNG mailing list.
- */
-
-int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
- const unsigned char *salt, int saltlen, int iter,
- const EVP_MD *digest, int keylen, unsigned char *out)
+int ossl_pkcs5_pbkdf2_hmac_ex(const char *pass, int passlen,
+ const unsigned char *salt, int saltlen, int iter,
+ const EVP_MD *digest, int keylen, unsigned char *out,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
const char *empty = "";
- unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
- int cplen, j, k, tkeylen, mdlen;
- unsigned long i = 1;
- HMAC_CTX *hctx_tpl = NULL, *hctx = NULL;
+ int rv = 1, mode = 1;
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx;
+ const char *mdname = EVP_MD_get0_name(digest);
+ OSSL_PARAM params[6], *p = params;
- mdlen = EVP_MD_size(digest);
- if (mdlen < 0)
- return 0;
-
- hctx_tpl = HMAC_CTX_new();
- if (hctx_tpl == NULL)
- return 0;
- p = out;
- tkeylen = keylen;
+ /* Keep documented behaviour. */
if (pass == NULL) {
pass = empty;
passlen = 0;
} else if (passlen == -1) {
passlen = strlen(pass);
}
- if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL)) {
- HMAC_CTX_free(hctx_tpl);
- return 0;
- }
- hctx = HMAC_CTX_new();
- if (hctx == NULL) {
- HMAC_CTX_free(hctx_tpl);
+ if (salt == NULL && saltlen == 0)
+ salt = (unsigned char *)empty;
+
+ kdf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_PBKDF2, propq);
+ if (kdf == NULL)
+ return 0;
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+ if (kctx == NULL)
return 0;
- }
- while (tkeylen) {
- if (tkeylen > mdlen)
- cplen = mdlen;
- else
- cplen = tkeylen;
- /*
- * We are unlikely to ever use more than 256 blocks (5120 bits!) but
- * just in case...
- */
- itmp[0] = (unsigned char)((i >> 24) & 0xff);
- itmp[1] = (unsigned char)((i >> 16) & 0xff);
- itmp[2] = (unsigned char)((i >> 8) & 0xff);
- itmp[3] = (unsigned char)(i & 0xff);
- if (!HMAC_CTX_copy(hctx, hctx_tpl)) {
- HMAC_CTX_free(hctx);
- HMAC_CTX_free(hctx_tpl);
- return 0;
- }
- if (!HMAC_Update(hctx, salt, saltlen)
- || !HMAC_Update(hctx, itmp, 4)
- || !HMAC_Final(hctx, digtmp, NULL)) {
- HMAC_CTX_free(hctx);
- HMAC_CTX_free(hctx_tpl);
- return 0;
- }
- memcpy(p, digtmp, cplen);
- for (j = 1; j < iter; j++) {
- if (!HMAC_CTX_copy(hctx, hctx_tpl)) {
- HMAC_CTX_free(hctx);
- HMAC_CTX_free(hctx_tpl);
- return 0;
- }
- if (!HMAC_Update(hctx, digtmp, mdlen)
- || !HMAC_Final(hctx, digtmp, NULL)) {
- HMAC_CTX_free(hctx);
- HMAC_CTX_free(hctx_tpl);
- return 0;
- }
- for (k = 0; k < cplen; k++)
- p[k] ^= digtmp[k];
- }
- tkeylen -= cplen;
- i++;
- p += cplen;
- }
- HMAC_CTX_free(hctx);
- HMAC_CTX_free(hctx_tpl);
-# ifdef OPENSSL_DEBUG_PKCS5V2
- fprintf(stderr, "Password:\n");
- h__dump(pass, passlen);
- fprintf(stderr, "Salt:\n");
- h__dump(salt, saltlen);
- fprintf(stderr, "Iteration count %d\n", iter);
- fprintf(stderr, "Key:\n");
- h__dump(out, keylen);
-# endif
- return 1;
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
+ (char *)pass, (size_t)passlen);
+ *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_PKCS5, &mode);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ (unsigned char *)salt, saltlen);
+ *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_ITER, &iter);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ (char *)mdname, 0);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, out, keylen, params) != 1)
+ rv = 0;
+
+ EVP_KDF_CTX_free(kctx);
+
+ OSSL_TRACE_BEGIN(PKCS5V2) {
+ BIO_printf(trc_out, "Password:\n");
+ BIO_hex_string(trc_out,
+ 0, passlen, pass, passlen);
+ BIO_printf(trc_out, "\n");
+ BIO_printf(trc_out, "Salt:\n");
+ BIO_hex_string(trc_out,
+ 0, saltlen, salt, saltlen);
+ BIO_printf(trc_out, "\n");
+ BIO_printf(trc_out, "Iteration count %d\n", iter);
+ BIO_printf(trc_out, "Key:\n");
+ BIO_hex_string(trc_out,
+ 0, keylen, out, keylen);
+ BIO_printf(trc_out, "\n");
+ } OSSL_TRACE_END(PKCS5V2);
+ return rv;
}
+int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, const unsigned char *salt,
+ int saltlen, int iter, const EVP_MD *digest, int keylen,
+ unsigned char *out)
+{
+ return ossl_pkcs5_pbkdf2_hmac_ex(pass, passlen, salt, saltlen, iter, digest,
+ keylen, out, NULL, NULL);
+}
+
+
int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
const unsigned char *salt, int saltlen, int iter,
int keylen, unsigned char *out)
{
- return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, EVP_sha1(),
- keylen, out);
+ EVP_MD *digest;
+ int r = 0;
+
+ if ((digest = EVP_MD_fetch(NULL, SN_sha1, NULL)) != NULL)
+ r = ossl_pkcs5_pbkdf2_hmac_ex(pass, passlen, salt, saltlen, iter,
+ digest, keylen, out, NULL, NULL);
+ EVP_MD_free(digest);
+ return r;
}
/*
@@ -135,71 +109,93 @@ int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
* them...
*/
-int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
- ASN1_TYPE *param, const EVP_CIPHER *c,
- const EVP_MD *md, int en_de)
+int PKCS5_v2_PBE_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *c,
+ const EVP_MD *md, int en_de,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
PBE2PARAM *pbe2 = NULL;
- const EVP_CIPHER *cipher;
- EVP_PBE_KEYGEN *kdf;
+ char ciph_name[80];
+ const EVP_CIPHER *cipher = NULL;
+ EVP_CIPHER *cipher_fetch = NULL;
+ EVP_PBE_KEYGEN_EX *kdf;
int rv = 0;
pbe2 = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBE2PARAM), param);
if (pbe2 == NULL) {
- EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_DECODE_ERROR);
+ ERR_raise(ERR_LIB_EVP, EVP_R_DECODE_ERROR);
goto err;
}
/* See if we recognise the key derivation function */
- if (!EVP_PBE_find(EVP_PBE_TYPE_KDF, OBJ_obj2nid(pbe2->keyfunc->algorithm),
- NULL, NULL, &kdf)) {
- EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,
- EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION);
+ if (!EVP_PBE_find_ex(EVP_PBE_TYPE_KDF, OBJ_obj2nid(pbe2->keyfunc->algorithm),
+ NULL, NULL, NULL, &kdf)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION);
goto err;
}
/*
* lets see if we recognise the encryption algorithm.
*/
+ if (OBJ_obj2txt(ciph_name, sizeof(ciph_name), pbe2->encryption->algorithm, 0) <= 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_CIPHER);
+ goto err;
+ }
- cipher = EVP_get_cipherbyobj(pbe2->encryption->algorithm);
+ (void)ERR_set_mark();
+ cipher = cipher_fetch = EVP_CIPHER_fetch(libctx, ciph_name, propq);
+ /* Fallback to legacy method */
+ if (cipher == NULL)
+ cipher = EVP_get_cipherbyname(ciph_name);
- if (!cipher) {
- EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_UNSUPPORTED_CIPHER);
+ if (cipher == NULL) {
+ (void)ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_CIPHER);
goto err;
}
+ (void)ERR_pop_to_mark();
/* Fixup cipher based on AlgorithmIdentifier */
if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, en_de))
goto err;
- if (EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) < 0) {
- EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_CIPHER_PARAMETER_ERROR);
+ if (EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) <= 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_CIPHER_PARAMETER_ERROR);
goto err;
}
- rv = kdf(ctx, pass, passlen, pbe2->keyfunc->parameter, NULL, NULL, en_de);
+ rv = kdf(ctx, pass, passlen, pbe2->keyfunc->parameter, NULL, NULL, en_de, libctx, propq);
err:
+ EVP_CIPHER_free(cipher_fetch);
PBE2PARAM_free(pbe2);
return rv;
}
-int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
- int passlen, ASN1_TYPE *param,
- const EVP_CIPHER *c, const EVP_MD *md, int en_de)
+int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *c,
+ const EVP_MD *md, int en_de)
+{
+ return PKCS5_v2_PBE_keyivgen_ex(ctx, pass, passlen, param, c, md, en_de, NULL, NULL);
+}
+
+int PKCS5_v2_PBKDF2_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass,
+ int passlen, ASN1_TYPE *param,
+ const EVP_CIPHER *c, const EVP_MD *md, int en_de,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
unsigned char *salt, key[EVP_MAX_KEY_LENGTH];
- int saltlen, iter;
+ int saltlen, iter, t;
int rv = 0;
unsigned int keylen = 0;
int prf_nid, hmac_md_nid;
PBKDF2PARAM *kdf = NULL;
- const EVP_MD *prfmd;
+ const EVP_MD *prfmd = NULL;
+ EVP_MD *prfmd_fetch = NULL;
- if (EVP_CIPHER_CTX_cipher(ctx) == NULL) {
- EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_NO_CIPHER_SET);
+ if (EVP_CIPHER_CTX_get0_cipher(ctx) == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
goto err;
}
- keylen = EVP_CIPHER_CTX_key_length(ctx);
+ keylen = EVP_CIPHER_CTX_get_key_length(ctx);
OPENSSL_assert(keylen <= sizeof(key));
/* Decode parameter */
@@ -207,16 +203,21 @@ int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
kdf = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBKDF2PARAM), param);
if (kdf == NULL) {
- EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_DECODE_ERROR);
+ ERR_raise(ERR_LIB_EVP, EVP_R_DECODE_ERROR);
goto err;
}
- keylen = EVP_CIPHER_CTX_key_length(ctx);
+ t = EVP_CIPHER_CTX_get_key_length(ctx);
+ if (t < 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH);
+ goto err;
+ }
+ keylen = t;
/* Now check the parameters of the kdf */
if (kdf->keylength && (ASN1_INTEGER_get(kdf->keylength) != (int)keylen)) {
- EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_KEYLENGTH);
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEYLENGTH);
goto err;
}
@@ -226,18 +227,20 @@ int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
prf_nid = NID_hmacWithSHA1;
if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, prf_nid, NULL, &hmac_md_nid, 0)) {
- EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF);
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_PRF);
goto err;
}
- prfmd = EVP_get_digestbynid(hmac_md_nid);
+ prfmd = prfmd_fetch = EVP_MD_fetch(libctx, OBJ_nid2sn(hmac_md_nid), propq);
+ if (prfmd == NULL)
+ prfmd = EVP_get_digestbynid(hmac_md_nid);
if (prfmd == NULL) {
- EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF);
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_PRF);
goto err;
}
if (kdf->salt->type != V_ASN1_OCTET_STRING) {
- EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_SALT_TYPE);
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_SALT_TYPE);
goto err;
}
@@ -245,21 +248,21 @@ int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
salt = kdf->salt->value.octet_string->data;
saltlen = kdf->salt->value.octet_string->length;
iter = ASN1_INTEGER_get(kdf->iter);
- if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, prfmd,
- keylen, key))
+ if (!ossl_pkcs5_pbkdf2_hmac_ex(pass, passlen, salt, saltlen, iter, prfmd,
+ keylen, key, libctx, propq))
goto err;
rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de);
err:
OPENSSL_cleanse(key, keylen);
PBKDF2PARAM_free(kdf);
+ EVP_MD_free(prfmd_fetch);
return rv;
}
-# ifdef OPENSSL_DEBUG_PKCS5V2
-static void h__dump(const unsigned char *p, int len)
+int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
+ int passlen, ASN1_TYPE *param,
+ const EVP_CIPHER *c, const EVP_MD *md, int en_de)
{
- for (; len--; p++)
- fprintf(stderr, "%02X ", *p);
- fprintf(stderr, "\n");
+ return PKCS5_v2_PBKDF2_keyivgen_ex(ctx, pass, passlen, param, c, md, en_de,
+ NULL, NULL);
}
-# endif
diff --git a/crypto/evp/p_dec.c b/crypto/evp/p_dec.c
index a150a26e092c..d77eed14284f 100644
--- a/crypto/evp/p_dec.c
+++ b/crypto/evp/p_dec.c
@@ -1,36 +1,40 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use the deprecated RSA low level calls */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
+#include "crypto/evp.h"
int EVP_PKEY_decrypt_old(unsigned char *key, const unsigned char *ek, int ekl,
EVP_PKEY *priv)
{
int ret = -1;
+ RSA *rsa = NULL;
-#ifndef OPENSSL_NO_RSA
- if (EVP_PKEY_id(priv) != EVP_PKEY_RSA) {
-#endif
- EVPerr(EVP_F_EVP_PKEY_DECRYPT_OLD, EVP_R_PUBLIC_KEY_NOT_RSA);
-#ifndef OPENSSL_NO_RSA
+ if (EVP_PKEY_get_id(priv) != EVP_PKEY_RSA) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_PUBLIC_KEY_NOT_RSA);
goto err;
}
+ rsa = evp_pkey_get0_RSA_int(priv);
+ if (rsa == NULL)
+ goto err;
+
ret =
- RSA_private_decrypt(ekl, ek, key, EVP_PKEY_get0_RSA(priv),
- RSA_PKCS1_PADDING);
+ RSA_private_decrypt(ekl, ek, key, rsa, RSA_PKCS1_PADDING);
err:
-#endif
return ret;
}
diff --git a/crypto/evp/p_enc.c b/crypto/evp/p_enc.c
index 04d67cb50f24..433c1a9e1710 100644
--- a/crypto/evp/p_enc.c
+++ b/crypto/evp/p_enc.c
@@ -1,35 +1,40 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use the deprecated RSA low level calls */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
+#include "crypto/evp.h"
int EVP_PKEY_encrypt_old(unsigned char *ek, const unsigned char *key,
int key_len, EVP_PKEY *pubk)
{
int ret = 0;
+ RSA *rsa = NULL;
-#ifndef OPENSSL_NO_RSA
- if (EVP_PKEY_id(pubk) != EVP_PKEY_RSA) {
-#endif
- EVPerr(EVP_F_EVP_PKEY_ENCRYPT_OLD, EVP_R_PUBLIC_KEY_NOT_RSA);
-#ifndef OPENSSL_NO_RSA
+ if (EVP_PKEY_get_id(pubk) != EVP_PKEY_RSA) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_PUBLIC_KEY_NOT_RSA);
goto err;
}
+
+ rsa = evp_pkey_get0_RSA_int(pubk);
+ if (rsa == NULL)
+ goto err;
+
ret =
- RSA_public_encrypt(key_len, key, ek, EVP_PKEY_get0_RSA(pubk),
- RSA_PKCS1_PADDING);
+ RSA_public_encrypt(key_len, key, ek, rsa, RSA_PKCS1_PADDING);
err:
-#endif
return ret;
}
diff --git a/crypto/evp/p_legacy.c b/crypto/evp/p_legacy.c
new file mode 100644
index 000000000000..6c65e7e1947a
--- /dev/null
+++ b/crypto/evp/p_legacy.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Legacy EVP_PKEY assign/set/get APIs are deprecated for public use, but
+ * still ok for internal use, particularly in providers.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/types.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+#include <openssl/ec.h>
+#include "crypto/types.h"
+#include "crypto/evp.h"
+#include "evp_local.h"
+
+int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key)
+{
+ int ret = EVP_PKEY_assign_RSA(pkey, key);
+
+ if (ret)
+ RSA_up_ref(key);
+ return ret;
+}
+
+RSA *evp_pkey_get0_RSA_int(const EVP_PKEY *pkey)
+{
+ if (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_RSA_PSS) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_AN_RSA_KEY);
+ return NULL;
+ }
+ return evp_pkey_get_legacy((EVP_PKEY *)pkey);
+}
+
+const RSA *EVP_PKEY_get0_RSA(const EVP_PKEY *pkey)
+{
+ return evp_pkey_get0_RSA_int(pkey);
+}
+
+RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey)
+{
+ RSA *ret = evp_pkey_get0_RSA_int(pkey);
+
+ if (ret != NULL)
+ RSA_up_ref(ret);
+ return ret;
+}
+
+#ifndef OPENSSL_NO_EC
+int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key)
+{
+ if (!EC_KEY_up_ref(key))
+ return 0;
+ if (!EVP_PKEY_assign_EC_KEY(pkey, key)) {
+ EC_KEY_free(key);
+ return 0;
+ }
+ return 1;
+}
+
+EC_KEY *evp_pkey_get0_EC_KEY_int(const EVP_PKEY *pkey)
+{
+ if (EVP_PKEY_get_base_id(pkey) != EVP_PKEY_EC) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_EC_KEY);
+ return NULL;
+ }
+ return evp_pkey_get_legacy((EVP_PKEY *)pkey);
+}
+
+const EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey)
+{
+ return evp_pkey_get0_EC_KEY_int(pkey);
+}
+
+EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey)
+{
+ EC_KEY *ret = evp_pkey_get0_EC_KEY_int(pkey);
+
+ if (ret != NULL && !EC_KEY_up_ref(ret))
+ ret = NULL;
+ return ret;
+}
+#endif /* OPENSSL_NO_EC */
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index 1f36cb2164fc..5803974c3221 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -1,57 +1,91 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <assert.h>
#include <stdio.h>
#include "internal/cryptlib.h"
#include "internal/refcount.h"
+#include "internal/namemap.h"
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
-#include <openssl/x509.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/dh.h>
+#include <openssl/ec.h>
#include <openssl/cmac.h>
-#include <openssl/engine.h>
+#ifndef FIPS_MODULE
+# include <openssl/engine.h>
+#endif
+#include <openssl/params.h>
+#include <openssl/param_build.h>
+#include <openssl/encoder.h>
+#include <openssl/core_names.h>
-#include "crypto/asn1.h"
+#include "internal/numbers.h" /* includes SIZE_MAX */
+#include "internal/ffc.h"
#include "crypto/evp.h"
+#include "crypto/dh.h"
+#include "crypto/dsa.h"
+#include "crypto/ec.h"
+#include "crypto/ecx.h"
+#include "crypto/rsa.h"
+#ifndef FIPS_MODULE
+# include "crypto/asn1.h"
+# include "crypto/x509.h"
+#endif
+#include "internal/provider.h"
+#include "evp_local.h"
-static void EVP_PKEY_free_it(EVP_PKEY *x);
+static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str,
+ int len, EVP_KEYMGMT *keymgmt);
+static void evp_pkey_free_it(EVP_PKEY *key);
-int EVP_PKEY_bits(const EVP_PKEY *pkey)
-{
- if (pkey && pkey->ameth && pkey->ameth->pkey_bits)
- return pkey->ameth->pkey_bits(pkey);
- return 0;
-}
+#ifndef FIPS_MODULE
+
+/* The type of parameters selected in key parameter functions */
+# define SELECT_PARAMETERS OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
-int EVP_PKEY_security_bits(const EVP_PKEY *pkey)
+int EVP_PKEY_get_bits(const EVP_PKEY *pkey)
{
- if (pkey == NULL)
- return 0;
- if (!pkey->ameth || !pkey->ameth->pkey_security_bits)
- return -2;
- return pkey->ameth->pkey_security_bits(pkey);
+ int size = 0;
+
+ if (pkey != NULL) {
+ size = pkey->cache.bits;
+ if (pkey->ameth != NULL && pkey->ameth->pkey_bits != NULL)
+ size = pkey->ameth->pkey_bits(pkey);
+ }
+ return size < 0 ? 0 : size;
}
-int EVP_PKEY_size(const EVP_PKEY *pkey)
+int EVP_PKEY_get_security_bits(const EVP_PKEY *pkey)
{
- if (pkey && pkey->ameth && pkey->ameth->pkey_size)
- return pkey->ameth->pkey_size(pkey);
- return 0;
+ int size = 0;
+
+ if (pkey != NULL) {
+ size = pkey->cache.security_bits;
+ if (pkey->ameth != NULL && pkey->ameth->pkey_security_bits != NULL)
+ size = pkey->ameth->pkey_security_bits(pkey);
+ }
+ return size < 0 ? 0 : size;
}
int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode)
{
-#ifndef OPENSSL_NO_DSA
+# ifndef OPENSSL_NO_DSA
if (pkey->type == EVP_PKEY_DSA) {
int ret = pkey->save_parameters;
@@ -59,8 +93,8 @@ int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode)
pkey->save_parameters = mode;
return ret;
}
-#endif
-#ifndef OPENSSL_NO_EC
+# endif
+# ifndef OPENSSL_NO_EC
if (pkey->type == EVP_PKEY_EC) {
int ret = pkey->save_parameters;
@@ -68,234 +102,477 @@ int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode)
pkey->save_parameters = mode;
return ret;
}
-#endif
+# endif
return 0;
}
+int EVP_PKEY_set_ex_data(EVP_PKEY *key, int idx, void *arg)
+{
+ return CRYPTO_set_ex_data(&key->ex_data, idx, arg);
+}
+
+void *EVP_PKEY_get_ex_data(const EVP_PKEY *key, int idx)
+{
+ return CRYPTO_get_ex_data(&key->ex_data, idx);
+}
+
int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
{
- if (to->type == EVP_PKEY_NONE) {
- if (EVP_PKEY_set_type(to, from->type) == 0)
- return 0;
- } else if (to->type != from->type) {
- EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_KEY_TYPES);
- goto err;
+ /*
+ * Clean up legacy stuff from this function when legacy support is gone.
+ */
+
+ EVP_PKEY *downgraded_from = NULL;
+ int ok = 0;
+
+ /*
+ * If |to| is a legacy key and |from| isn't, we must make a downgraded
+ * copy of |from|. If that fails, this function fails.
+ */
+ if (evp_pkey_is_legacy(to) && evp_pkey_is_provided(from)) {
+ if (!evp_pkey_copy_downgraded(&downgraded_from, from))
+ goto end;
+ from = downgraded_from;
+ }
+
+ /*
+ * Make sure |to| is typed. Content is less important at this early
+ * stage.
+ *
+ * 1. If |to| is untyped, assign |from|'s key type to it.
+ * 2. If |to| contains a legacy key, compare its |type| to |from|'s.
+ * (|from| was already downgraded above)
+ *
+ * If |to| is a provided key, there's nothing more to do here, functions
+ * like evp_keymgmt_util_copy() and evp_pkey_export_to_provider() called
+ * further down help us find out if they are the same or not.
+ */
+ if (evp_pkey_is_blank(to)) {
+ if (evp_pkey_is_legacy(from)) {
+ if (EVP_PKEY_set_type(to, from->type) == 0)
+ goto end;
+ } else {
+ if (EVP_PKEY_set_type_by_keymgmt(to, from->keymgmt) == 0)
+ goto end;
+ }
+ } else if (evp_pkey_is_legacy(to)) {
+ if (to->type != from->type) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
+ goto end;
+ }
}
if (EVP_PKEY_missing_parameters(from)) {
- EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_MISSING_PARAMETERS);
- goto err;
+ ERR_raise(ERR_LIB_EVP, EVP_R_MISSING_PARAMETERS);
+ goto end;
}
if (!EVP_PKEY_missing_parameters(to)) {
- if (EVP_PKEY_cmp_parameters(to, from) == 1)
- return 1;
- EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_PARAMETERS);
- return 0;
+ if (EVP_PKEY_parameters_eq(to, from) == 1)
+ ok = 1;
+ else
+ ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_PARAMETERS);
+ goto end;
}
- if (from->ameth && from->ameth->param_copy)
- return from->ameth->param_copy(to, from);
- err:
- return 0;
+ /* For purely provided keys, we just call the keymgmt utility */
+ if (to->keymgmt != NULL && from->keymgmt != NULL) {
+ ok = evp_keymgmt_util_copy(to, (EVP_PKEY *)from, SELECT_PARAMETERS);
+ goto end;
+ }
+
+ /*
+ * If |to| is provided, we know that |from| is legacy at this point.
+ * Try exporting |from| to |to|'s keymgmt, then use evp_keymgmt_dup()
+ * to copy the appropriate data to |to|'s keydata.
+ * We cannot override existing data so do it only if there is no keydata
+ * in |to| yet.
+ */
+ if (to->keymgmt != NULL && to->keydata == NULL) {
+ EVP_KEYMGMT *to_keymgmt = to->keymgmt;
+ void *from_keydata =
+ evp_pkey_export_to_provider((EVP_PKEY *)from, NULL, &to_keymgmt,
+ NULL);
+
+ /*
+ * If we get a NULL, it could be an internal error, or it could be
+ * that there's a key mismatch. We're pretending the latter...
+ */
+ if (from_keydata == NULL)
+ ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
+ else
+ ok = (to->keydata = evp_keymgmt_dup(to->keymgmt,
+ from_keydata,
+ SELECT_PARAMETERS)) != NULL;
+ goto end;
+ }
+
+ /* Both keys are legacy */
+ if (from->ameth != NULL && from->ameth->param_copy != NULL)
+ ok = from->ameth->param_copy(to, from);
+ end:
+ EVP_PKEY_free(downgraded_from);
+ return ok;
}
int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey)
{
- if (pkey != NULL && pkey->ameth && pkey->ameth->param_missing)
- return pkey->ameth->param_missing(pkey);
+ if (pkey != NULL) {
+ if (pkey->keymgmt != NULL)
+ return !evp_keymgmt_util_has((EVP_PKEY *)pkey, SELECT_PARAMETERS);
+ else if (pkey->ameth != NULL && pkey->ameth->param_missing != NULL)
+ return pkey->ameth->param_missing(pkey);
+ }
return 0;
}
+/*
+ * This function is called for any mixture of keys except pure legacy pair.
+ * When legacy keys are gone, we replace a call to this functions with
+ * a call to evp_keymgmt_util_match().
+ */
+static int evp_pkey_cmp_any(const EVP_PKEY *a, const EVP_PKEY *b,
+ int selection)
+{
+ EVP_KEYMGMT *keymgmt1 = NULL, *keymgmt2 = NULL;
+ void *keydata1 = NULL, *keydata2 = NULL, *tmp_keydata = NULL;
+
+ /* If none of them are provided, this function shouldn't have been called */
+ if (!ossl_assert(evp_pkey_is_provided(a) || evp_pkey_is_provided(b)))
+ return -2;
+
+ /* For purely provided keys, we just call the keymgmt utility */
+ if (evp_pkey_is_provided(a) && evp_pkey_is_provided(b))
+ return evp_keymgmt_util_match((EVP_PKEY *)a, (EVP_PKEY *)b, selection);
+
+ /*
+ * At this point, one of them is provided, the other not. This allows
+ * us to compare types using legacy NIDs.
+ */
+ if (evp_pkey_is_legacy(a)
+ && !EVP_KEYMGMT_is_a(b->keymgmt, OBJ_nid2sn(a->type)))
+ return -1; /* not the same key type */
+ if (evp_pkey_is_legacy(b)
+ && !EVP_KEYMGMT_is_a(a->keymgmt, OBJ_nid2sn(b->type)))
+ return -1; /* not the same key type */
+
+ /*
+ * We've determined that they both are the same keytype, so the next
+ * step is to do a bit of cross export to ensure we have keydata for
+ * both keys in the same keymgmt.
+ */
+ keymgmt1 = a->keymgmt;
+ keydata1 = a->keydata;
+ keymgmt2 = b->keymgmt;
+ keydata2 = b->keydata;
+
+ if (keymgmt2 != NULL && keymgmt2->match != NULL) {
+ tmp_keydata =
+ evp_pkey_export_to_provider((EVP_PKEY *)a, NULL, &keymgmt2, NULL);
+ if (tmp_keydata != NULL) {
+ keymgmt1 = keymgmt2;
+ keydata1 = tmp_keydata;
+ }
+ }
+ if (tmp_keydata == NULL && keymgmt1 != NULL && keymgmt1->match != NULL) {
+ tmp_keydata =
+ evp_pkey_export_to_provider((EVP_PKEY *)b, NULL, &keymgmt1, NULL);
+ if (tmp_keydata != NULL) {
+ keymgmt2 = keymgmt1;
+ keydata2 = tmp_keydata;
+ }
+ }
+
+ /* If we still don't have matching keymgmt implementations, we give up */
+ if (keymgmt1 != keymgmt2)
+ return -2;
+
+ /* If the keymgmt implementations are NULL, the export failed */
+ if (keymgmt1 == NULL)
+ return -2;
+
+ return evp_keymgmt_match(keymgmt1, keydata1, keydata2, selection);
+}
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
{
+ return EVP_PKEY_parameters_eq(a, b);
+}
+#endif
+
+int EVP_PKEY_parameters_eq(const EVP_PKEY *a, const EVP_PKEY *b)
+{
+ /*
+ * This will just call evp_keymgmt_util_match when legacy support
+ * is gone.
+ */
+
+ if (a->keymgmt != NULL || b->keymgmt != NULL)
+ return evp_pkey_cmp_any(a, b, SELECT_PARAMETERS);
+
+ /* All legacy keys */
if (a->type != b->type)
return -1;
- if (a->ameth && a->ameth->param_cmp)
+ if (a->ameth != NULL && a->ameth->param_cmp != NULL)
return a->ameth->param_cmp(a, b);
return -2;
}
+# ifndef OPENSSL_NO_DEPRECATED_3_0
int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
{
+ return EVP_PKEY_eq(a, b);
+}
+#endif
+
+int EVP_PKEY_eq(const EVP_PKEY *a, const EVP_PKEY *b)
+{
+ /*
+ * This will just call evp_keymgmt_util_match when legacy support
+ * is gone.
+ */
+
+ /* Trivial shortcuts */
+ if (a == b)
+ return 1;
+ if (a == NULL || b == NULL)
+ return 0;
+
+ if (a->keymgmt != NULL || b->keymgmt != NULL) {
+ int selection = SELECT_PARAMETERS;
+
+ if (evp_keymgmt_util_has((EVP_PKEY *)a, OSSL_KEYMGMT_SELECT_PUBLIC_KEY)
+ && evp_keymgmt_util_has((EVP_PKEY *)b, OSSL_KEYMGMT_SELECT_PUBLIC_KEY))
+ selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+ else
+ selection |= OSSL_KEYMGMT_SELECT_KEYPAIR;
+ return evp_pkey_cmp_any(a, b, selection);
+ }
+
+ /* All legacy keys */
if (a->type != b->type)
return -1;
- if (a->ameth) {
+ if (a->ameth != NULL) {
int ret;
/* Compare parameters if the algorithm has them */
- if (a->ameth->param_cmp) {
+ if (a->ameth->param_cmp != NULL) {
ret = a->ameth->param_cmp(a, b);
if (ret <= 0)
return ret;
}
- if (a->ameth->pub_cmp)
+ if (a->ameth->pub_cmp != NULL)
return a->ameth->pub_cmp(a, b);
}
return -2;
}
-EVP_PKEY *EVP_PKEY_new(void)
-{
- EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret));
- if (ret == NULL) {
- EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- ret->type = EVP_PKEY_NONE;
- ret->save_type = EVP_PKEY_NONE;
- ret->references = 1;
- ret->save_parameters = 1;
- ret->lock = CRYPTO_THREAD_lock_new();
- if (ret->lock == NULL) {
- EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
- OPENSSL_free(ret);
- return NULL;
- }
- return ret;
-}
-
-int EVP_PKEY_up_ref(EVP_PKEY *pkey)
+static EVP_PKEY *new_raw_key_int(OSSL_LIB_CTX *libctx,
+ const char *strtype,
+ const char *propq,
+ int nidtype,
+ ENGINE *e,
+ const unsigned char *key,
+ size_t len,
+ int key_is_priv)
{
- int i;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ const EVP_PKEY_ASN1_METHOD *ameth = NULL;
+ int result = 0;
- if (CRYPTO_UP_REF(&pkey->references, &i, pkey->lock) <= 0)
- return 0;
+# ifndef OPENSSL_NO_ENGINE
+ /* Check if there is an Engine for this type */
+ if (e == NULL) {
+ ENGINE *tmpe = NULL;
- REF_PRINT_COUNT("EVP_PKEY", pkey);
- REF_ASSERT_ISNT(i < 2);
- return ((i > 1) ? 1 : 0);
-}
+ if (strtype != NULL)
+ ameth = EVP_PKEY_asn1_find_str(&tmpe, strtype, -1);
+ else if (nidtype != EVP_PKEY_NONE)
+ ameth = EVP_PKEY_asn1_find(&tmpe, nidtype);
-/*
- * Setup a public key ASN1 method and ENGINE from a NID or a string. If pkey
- * is NULL just return 1 or 0 if the algorithm exists.
- */
+ /* If tmpe is NULL then no engine is claiming to support this type */
+ if (tmpe == NULL)
+ ameth = NULL;
-static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str,
- int len)
-{
- const EVP_PKEY_ASN1_METHOD *ameth;
- ENGINE **eptr = (e == NULL) ? &e : NULL;
+ ENGINE_finish(tmpe);
+ }
+# endif
- if (pkey) {
- if (pkey->pkey.ptr)
- EVP_PKEY_free_it(pkey);
+ if (e == NULL && ameth == NULL) {
/*
- * If key type matches and a method exists then this lookup has
- * succeeded once so just indicate success.
+ * No engine is claiming to support this type, so lets see if we have
+ * a provider.
*/
- if ((type == pkey->save_type) && pkey->ameth)
- return 1;
-#ifndef OPENSSL_NO_ENGINE
- /* If we have ENGINEs release them */
- ENGINE_finish(pkey->engine);
- pkey->engine = NULL;
- ENGINE_finish(pkey->pmeth_engine);
- pkey->pmeth_engine = NULL;
-#endif
- }
- if (str)
- ameth = EVP_PKEY_asn1_find_str(eptr, str, len);
- else
- ameth = EVP_PKEY_asn1_find(eptr, type);
-#ifndef OPENSSL_NO_ENGINE
- if (pkey == NULL && eptr != NULL)
- ENGINE_finish(e);
-#endif
- if (ameth == NULL) {
- EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM);
- return 0;
- }
- if (pkey) {
- pkey->ameth = ameth;
- pkey->type = pkey->ameth->pkey_id;
- pkey->save_type = type;
-# ifndef OPENSSL_NO_ENGINE
- if (eptr == NULL && e != NULL && !ENGINE_init(e)) {
- EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_INITIALIZATION_ERROR);
- return 0;
+ ctx = EVP_PKEY_CTX_new_from_name(libctx,
+ strtype != NULL ? strtype
+ : OBJ_nid2sn(nidtype),
+ propq);
+ if (ctx == NULL)
+ goto err;
+ /* May fail if no provider available */
+ ERR_set_mark();
+ if (EVP_PKEY_fromdata_init(ctx) == 1) {
+ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ ERR_clear_last_mark();
+ params[0] = OSSL_PARAM_construct_octet_string(
+ key_is_priv ? OSSL_PKEY_PARAM_PRIV_KEY
+ : OSSL_PKEY_PARAM_PUB_KEY,
+ (void *)key, len);
+
+ if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) != 1) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
+ goto err;
+ }
+
+ EVP_PKEY_CTX_free(ctx);
+
+ return pkey;
}
-# endif
- pkey->engine = e;
+ ERR_pop_to_mark();
+ /* else not supported so fallback to legacy */
}
- return 1;
-}
-EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
- const unsigned char *priv,
- size_t len)
-{
- EVP_PKEY *ret = EVP_PKEY_new();
+ /* Legacy code path */
- if (ret == NULL
- || !pkey_set_type(ret, e, type, NULL, -1)) {
- /* EVPerr already called */
+ pkey = EVP_PKEY_new();
+ if (pkey == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (ret->ameth->set_priv_key == NULL) {
- EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ if (!pkey_set_type(pkey, e, nidtype, strtype, -1, NULL)) {
+ /* EVPerr already called */
goto err;
}
- if (!ret->ameth->set_priv_key(ret, priv, len)) {
- EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY, EVP_R_KEY_SETUP_FAILED);
+ if (!ossl_assert(pkey->ameth != NULL))
goto err;
- }
- return ret;
+ if (key_is_priv) {
+ if (pkey->ameth->set_priv_key == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ goto err;
+ }
+ if (!pkey->ameth->set_priv_key(pkey, key, len)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
+ goto err;
+ }
+ } else {
+ if (pkey->ameth->set_pub_key == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ goto err;
+ }
+
+ if (!pkey->ameth->set_pub_key(pkey, key, len)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
+ goto err;
+ }
+ }
+
+ result = 1;
err:
- EVP_PKEY_free(ret);
- return NULL;
+ if (!result) {
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ }
+ EVP_PKEY_CTX_free(ctx);
+ return pkey;
+}
+
+EVP_PKEY *EVP_PKEY_new_raw_private_key_ex(OSSL_LIB_CTX *libctx,
+ const char *keytype,
+ const char *propq,
+ const unsigned char *priv, size_t len)
+{
+ return new_raw_key_int(libctx, keytype, propq, EVP_PKEY_NONE, NULL, priv,
+ len, 1);
+}
+
+EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
+ const unsigned char *priv,
+ size_t len)
+{
+ return new_raw_key_int(NULL, NULL, NULL, type, e, priv, len, 1);
+}
+
+EVP_PKEY *EVP_PKEY_new_raw_public_key_ex(OSSL_LIB_CTX *libctx,
+ const char *keytype, const char *propq,
+ const unsigned char *pub, size_t len)
+{
+ return new_raw_key_int(libctx, keytype, propq, EVP_PKEY_NONE, NULL, pub,
+ len, 0);
}
EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
const unsigned char *pub,
size_t len)
{
- EVP_PKEY *ret = EVP_PKEY_new();
-
- if (ret == NULL
- || !pkey_set_type(ret, e, type, NULL, -1)) {
- /* EVPerr already called */
- goto err;
- }
+ return new_raw_key_int(NULL, NULL, NULL, type, e, pub, len, 0);
+}
- if (ret->ameth->set_pub_key == NULL) {
- EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- goto err;
- }
+struct raw_key_details_st
+{
+ unsigned char **key;
+ size_t *len;
+ int selection;
+};
- if (!ret->ameth->set_pub_key(ret, pub, len)) {
- EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY, EVP_R_KEY_SETUP_FAILED);
- goto err;
+static OSSL_CALLBACK get_raw_key_details;
+static int get_raw_key_details(const OSSL_PARAM params[], void *arg)
+{
+ const OSSL_PARAM *p = NULL;
+ struct raw_key_details_st *raw_key = arg;
+
+ if (raw_key->selection == OSSL_KEYMGMT_SELECT_PRIVATE_KEY) {
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY))
+ != NULL)
+ return OSSL_PARAM_get_octet_string(p, (void **)raw_key->key,
+ raw_key->key == NULL ? 0 : *raw_key->len,
+ raw_key->len);
+ } else if (raw_key->selection == OSSL_KEYMGMT_SELECT_PUBLIC_KEY) {
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY))
+ != NULL)
+ return OSSL_PARAM_get_octet_string(p, (void **)raw_key->key,
+ raw_key->key == NULL ? 0 : *raw_key->len,
+ raw_key->len);
}
- return ret;
-
- err:
- EVP_PKEY_free(ret);
- return NULL;
+ return 0;
}
int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv,
size_t *len)
{
- if (pkey->ameth->get_priv_key == NULL) {
- EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ if (pkey->keymgmt != NULL) {
+ struct raw_key_details_st raw_key;
+
+ raw_key.key = priv == NULL ? NULL : &priv;
+ raw_key.len = len;
+ raw_key.selection = OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
+
+ return evp_keymgmt_util_export(pkey, OSSL_KEYMGMT_SELECT_PRIVATE_KEY,
+ get_raw_key_details, &raw_key);
+ }
+
+ if (pkey->ameth == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+
+ if (pkey->ameth->get_priv_key == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (!pkey->ameth->get_priv_key(pkey, priv, len)) {
- EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY, EVP_R_GET_RAW_KEY_FAILED);
+ ERR_raise(ERR_LIB_EVP, EVP_R_GET_RAW_KEY_FAILED);
return 0;
}
@@ -305,93 +582,122 @@ int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv,
int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub,
size_t *len)
{
+ if (pkey->keymgmt != NULL) {
+ struct raw_key_details_st raw_key;
+
+ raw_key.key = pub == NULL ? NULL : &pub;
+ raw_key.len = len;
+ raw_key.selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+
+ return evp_keymgmt_util_export(pkey, OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
+ get_raw_key_details, &raw_key);
+ }
+
+ if (pkey->ameth == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+
if (pkey->ameth->get_pub_key == NULL) {
- EVPerr(EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (!pkey->ameth->get_pub_key(pkey, pub, len)) {
- EVPerr(EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY, EVP_R_GET_RAW_KEY_FAILED);
+ ERR_raise(ERR_LIB_EVP, EVP_R_GET_RAW_KEY_FAILED);
return 0;
}
return 1;
}
-EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
- size_t len, const EVP_CIPHER *cipher)
+static EVP_PKEY *new_cmac_key_int(const unsigned char *priv, size_t len,
+ const char *cipher_name,
+ const EVP_CIPHER *cipher,
+ OSSL_LIB_CTX *libctx,
+ const char *propq, ENGINE *e)
{
-#ifndef OPENSSL_NO_CMAC
- EVP_PKEY *ret = EVP_PKEY_new();
- CMAC_CTX *cmctx = CMAC_CTX_new();
+# ifndef OPENSSL_NO_CMAC
+# ifndef OPENSSL_NO_ENGINE
+ const char *engine_id = e != NULL ? ENGINE_get_id(e) : NULL;
+# endif
+ OSSL_PARAM params[5], *p = params;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx;
+
+ if (cipher != NULL)
+ cipher_name = EVP_CIPHER_get0_name(cipher);
+
+ if (cipher_name == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
+ return NULL;
+ }
- if (ret == NULL
- || cmctx == NULL
- || !pkey_set_type(ret, e, EVP_PKEY_CMAC, NULL, -1)) {
- /* EVPerr already called */
+ ctx = EVP_PKEY_CTX_new_from_name(libctx, "CMAC", propq);
+ if (ctx == NULL)
goto err;
- }
- if (!CMAC_Init(cmctx, priv, len, cipher, e)) {
- EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY, EVP_R_KEY_SETUP_FAILED);
+ if (EVP_PKEY_fromdata_init(ctx) <= 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
goto err;
}
- ret->pkey.ptr = cmctx;
- return ret;
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
+ (void *)priv, len);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_CIPHER,
+ (char *)cipher_name, 0);
+ if (propq != NULL)
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_PROPERTIES,
+ (char *)propq, 0);
+# ifndef OPENSSL_NO_ENGINE
+ if (engine_id != NULL)
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_ENGINE,
+ (char *)engine_id, 0);
+# endif
+ *p = OSSL_PARAM_construct_end();
+
+ if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
+ goto err;
+ }
err:
- EVP_PKEY_free(ret);
- CMAC_CTX_free(cmctx);
- return NULL;
-#else
- EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ EVP_PKEY_CTX_free(ctx);
+
+ return pkey;
+# else
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return NULL;
-#endif
+# endif
}
-int EVP_PKEY_set_type(EVP_PKEY *pkey, int type)
+EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
+ size_t len, const EVP_CIPHER *cipher)
{
- return pkey_set_type(pkey, NULL, type, NULL, -1);
+ return new_cmac_key_int(priv, len, NULL, cipher, NULL, NULL, e);
}
-int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len)
+int EVP_PKEY_set_type(EVP_PKEY *pkey, int type)
{
- return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len);
+ return pkey_set_type(pkey, NULL, type, NULL, -1, NULL);
}
-int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type)
+int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len)
{
- if (pkey->type == type) {
- return 1; /* it already is that type */
- }
-
- /*
- * The application is requesting to alias this to a different pkey type,
- * but not one that resolves to the base type.
- */
- if (EVP_PKEY_type(type) != EVP_PKEY_base_id(pkey)) {
- EVPerr(EVP_F_EVP_PKEY_SET_ALIAS_TYPE, EVP_R_UNSUPPORTED_ALGORITHM);
- return 0;
- }
-
- pkey->type = type;
- return 1;
+ return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len, NULL);
}
-#ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_ENGINE
int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e)
{
if (e != NULL) {
if (!ENGINE_init(e)) {
- EVPerr(EVP_F_EVP_PKEY_SET1_ENGINE, ERR_R_ENGINE_LIB);
+ ERR_raise(ERR_LIB_EVP, ERR_R_ENGINE_LIB);
return 0;
}
if (ENGINE_get_pkey_meth(e, pkey->type) == NULL) {
ENGINE_finish(e);
- EVPerr(EVP_F_EVP_PKEY_SET1_ENGINE, EVP_R_UNSUPPORTED_ALGORITHM);
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_ALGORITHM);
return 0;
}
}
@@ -404,89 +710,151 @@ ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey)
{
return pkey->engine;
}
+# endif
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+static void detect_foreign_key(EVP_PKEY *pkey)
+{
+ switch (pkey->type) {
+ case EVP_PKEY_RSA:
+ pkey->foreign = pkey->pkey.rsa != NULL
+ && ossl_rsa_is_foreign(pkey->pkey.rsa);
+ break;
+# ifndef OPENSSL_NO_EC
+ case EVP_PKEY_SM2:
+ case EVP_PKEY_EC:
+ pkey->foreign = pkey->pkey.ec != NULL
+ && ossl_ec_key_is_foreign(pkey->pkey.ec);
+ break;
+# endif
+# ifndef OPENSSL_NO_DSA
+ case EVP_PKEY_DSA:
+ pkey->foreign = pkey->pkey.dsa != NULL
+ && ossl_dsa_is_foreign(pkey->pkey.dsa);
+ break;
+#endif
+# ifndef OPENSSL_NO_DH
+ case EVP_PKEY_DH:
+ pkey->foreign = pkey->pkey.dh != NULL
+ && ossl_dh_is_foreign(pkey->pkey.dh);
+ break;
#endif
+ default:
+ pkey->foreign = 0;
+ break;
+ }
+}
+
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
{
+# ifndef OPENSSL_NO_EC
+ int pktype;
+
+ pktype = EVP_PKEY_type(type);
+ if ((key != NULL) && (pktype == EVP_PKEY_EC || pktype == EVP_PKEY_SM2)) {
+ const EC_GROUP *group = EC_KEY_get0_group(key);
+
+ if (group != NULL) {
+ int curve = EC_GROUP_get_curve_name(group);
+
+ /*
+ * Regardless of what is requested the SM2 curve must be SM2 type,
+ * and non SM2 curves are EC type.
+ */
+ if (curve == NID_sm2 && pktype == EVP_PKEY_EC)
+ type = EVP_PKEY_SM2;
+ else if(curve != NID_sm2 && pktype == EVP_PKEY_SM2)
+ type = EVP_PKEY_EC;
+ }
+ }
+# endif
+
if (pkey == NULL || !EVP_PKEY_set_type(pkey, type))
return 0;
+
pkey->pkey.ptr = key;
+ detect_foreign_key(pkey);
+
return (key != NULL);
}
+# endif
void *EVP_PKEY_get0(const EVP_PKEY *pkey)
{
- return pkey->pkey.ptr;
+ if (pkey == NULL)
+ return NULL;
+
+ if (!evp_pkey_is_provided(pkey))
+ return pkey->pkey.ptr;
+
+ return NULL;
}
const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len)
{
- ASN1_OCTET_STRING *os = NULL;
+ const ASN1_OCTET_STRING *os = NULL;
if (pkey->type != EVP_PKEY_HMAC) {
- EVPerr(EVP_F_EVP_PKEY_GET0_HMAC, EVP_R_EXPECTING_AN_HMAC_KEY);
+ ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_AN_HMAC_KEY);
return NULL;
}
- os = EVP_PKEY_get0(pkey);
- *len = os->length;
- return os->data;
+ os = evp_pkey_get_legacy((EVP_PKEY *)pkey);
+ if (os != NULL) {
+ *len = os->length;
+ return os->data;
+ }
+ return NULL;
}
-#ifndef OPENSSL_NO_POLY1305
+# ifndef OPENSSL_NO_POLY1305
const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len)
{
- ASN1_OCTET_STRING *os = NULL;
+ const ASN1_OCTET_STRING *os = NULL;
if (pkey->type != EVP_PKEY_POLY1305) {
- EVPerr(EVP_F_EVP_PKEY_GET0_POLY1305, EVP_R_EXPECTING_A_POLY1305_KEY);
+ ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_POLY1305_KEY);
return NULL;
}
- os = EVP_PKEY_get0(pkey);
- *len = os->length;
- return os->data;
+ os = evp_pkey_get_legacy((EVP_PKEY *)pkey);
+ if (os != NULL) {
+ *len = os->length;
+ return os->data;
+ }
+ return NULL;
}
-#endif
+# endif
-#ifndef OPENSSL_NO_SIPHASH
+# ifndef OPENSSL_NO_SIPHASH
const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len)
{
- ASN1_OCTET_STRING *os = NULL;
+ const ASN1_OCTET_STRING *os = NULL;
if (pkey->type != EVP_PKEY_SIPHASH) {
- EVPerr(EVP_F_EVP_PKEY_GET0_SIPHASH, EVP_R_EXPECTING_A_SIPHASH_KEY);
+ ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_SIPHASH_KEY);
return NULL;
}
- os = EVP_PKEY_get0(pkey);
- *len = os->length;
- return os->data;
-}
-#endif
-
-#ifndef OPENSSL_NO_RSA
-int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key)
-{
- int ret = EVP_PKEY_assign_RSA(pkey, key);
- if (ret)
- RSA_up_ref(key);
- return ret;
+ os = evp_pkey_get_legacy((EVP_PKEY *)pkey);
+ if (os != NULL) {
+ *len = os->length;
+ return os->data;
+ }
+ return NULL;
}
+# endif
-RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey)
+# ifndef OPENSSL_NO_DSA
+static DSA *evp_pkey_get0_DSA_int(const EVP_PKEY *pkey)
{
- if (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_RSA_PSS) {
- EVPerr(EVP_F_EVP_PKEY_GET0_RSA, EVP_R_EXPECTING_AN_RSA_KEY);
+ if (pkey->type != EVP_PKEY_DSA) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_DSA_KEY);
return NULL;
}
- return pkey->pkey.rsa;
+ return evp_pkey_get_legacy((EVP_PKEY *)pkey);
}
-RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey)
+const DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey)
{
- RSA *ret = EVP_PKEY_get0_RSA(pkey);
- if (ret != NULL)
- RSA_up_ref(ret);
- return ret;
+ return evp_pkey_get0_DSA_int(pkey);
}
-#endif
-#ifndef OPENSSL_NO_DSA
int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key)
{
int ret = EVP_PKEY_assign_DSA(pkey, key);
@@ -494,82 +862,107 @@ int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key)
DSA_up_ref(key);
return ret;
}
-
-DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey)
-{
- if (pkey->type != EVP_PKEY_DSA) {
- EVPerr(EVP_F_EVP_PKEY_GET0_DSA, EVP_R_EXPECTING_A_DSA_KEY);
- return NULL;
- }
- return pkey->pkey.dsa;
-}
-
DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey)
{
- DSA *ret = EVP_PKEY_get0_DSA(pkey);
+ DSA *ret = evp_pkey_get0_DSA_int(pkey);
+
if (ret != NULL)
DSA_up_ref(ret);
return ret;
}
-#endif
-
-#ifndef OPENSSL_NO_EC
-
-int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key)
-{
- int ret = EVP_PKEY_assign_EC_KEY(pkey, key);
- if (ret)
- EC_KEY_up_ref(key);
- return ret;
-}
+# endif /* OPENSSL_NO_DSA */
-EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
+# ifndef OPENSSL_NO_EC
+static const ECX_KEY *evp_pkey_get0_ECX_KEY(const EVP_PKEY *pkey, int type)
{
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) {
- EVPerr(EVP_F_EVP_PKEY_GET0_EC_KEY, EVP_R_EXPECTING_A_EC_KEY);
+ if (EVP_PKEY_get_base_id(pkey) != type) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_ECX_KEY);
return NULL;
}
- return pkey->pkey.ec;
+ return evp_pkey_get_legacy((EVP_PKEY *)pkey);
}
-EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey)
+static ECX_KEY *evp_pkey_get1_ECX_KEY(EVP_PKEY *pkey, int type)
{
- EC_KEY *ret = EVP_PKEY_get0_EC_KEY(pkey);
- if (ret != NULL)
- EC_KEY_up_ref(ret);
+ ECX_KEY *ret = (ECX_KEY *)evp_pkey_get0_ECX_KEY(pkey, type);
+
+ if (ret != NULL && !ossl_ecx_key_up_ref(ret))
+ ret = NULL;
return ret;
}
-#endif
-#ifndef OPENSSL_NO_DH
+# define IMPLEMENT_ECX_VARIANT(NAME) \
+ ECX_KEY *ossl_evp_pkey_get1_##NAME(EVP_PKEY *pkey) \
+ { \
+ return evp_pkey_get1_ECX_KEY(pkey, EVP_PKEY_##NAME); \
+ }
+IMPLEMENT_ECX_VARIANT(X25519)
+IMPLEMENT_ECX_VARIANT(X448)
+IMPLEMENT_ECX_VARIANT(ED25519)
+IMPLEMENT_ECX_VARIANT(ED448)
+
+# endif
+
+# if !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_DEPRECATED_3_0)
-int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key)
+int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *dhkey)
{
- int type = DH_get0_q(key) == NULL ? EVP_PKEY_DH : EVP_PKEY_DHX;
- int ret = EVP_PKEY_assign(pkey, type, key);
+ int ret, type;
+
+ /*
+ * ossl_dh_is_named_safe_prime_group() returns 1 for named safe prime groups
+ * related to ffdhe and modp (which cache q = (p - 1) / 2),
+ * and returns 0 for all other dh parameter generation types including
+ * RFC5114 named groups.
+ *
+ * The EVP_PKEY_DH type is used for dh parameter generation types:
+ * - named safe prime groups related to ffdhe and modp
+ * - safe prime generator
+ *
+ * The type EVP_PKEY_DHX is used for dh parameter generation types
+ * - fips186-4 and fips186-2
+ * - rfc5114 named groups.
+ *
+ * The EVP_PKEY_DH type is used to save PKCS#3 data than can be stored
+ * without a q value.
+ * The EVP_PKEY_DHX type is used to save X9.42 data that requires the
+ * q value to be stored.
+ */
+ if (ossl_dh_is_named_safe_prime_group(dhkey))
+ type = EVP_PKEY_DH;
+ else
+ type = DH_get0_q(dhkey) == NULL ? EVP_PKEY_DH : EVP_PKEY_DHX;
+
+ ret = EVP_PKEY_assign(pkey, type, dhkey);
if (ret)
- DH_up_ref(key);
+ DH_up_ref(dhkey);
return ret;
}
-DH *EVP_PKEY_get0_DH(EVP_PKEY *pkey)
+DH *evp_pkey_get0_DH_int(const EVP_PKEY *pkey)
{
if (pkey->type != EVP_PKEY_DH && pkey->type != EVP_PKEY_DHX) {
- EVPerr(EVP_F_EVP_PKEY_GET0_DH, EVP_R_EXPECTING_A_DH_KEY);
+ ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_DH_KEY);
return NULL;
}
- return pkey->pkey.dh;
+ return evp_pkey_get_legacy((EVP_PKEY *)pkey);
+}
+
+const DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey)
+{
+ return evp_pkey_get0_DH_int(pkey);
}
DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey)
{
- DH *ret = EVP_PKEY_get0_DH(pkey);
+ DH *ret = evp_pkey_get0_DH_int(pkey);
+
if (ret != NULL)
DH_up_ref(ret);
return ret;
}
-#endif
+# endif
int EVP_PKEY_type(int type)
{
@@ -581,93 +974,350 @@ int EVP_PKEY_type(int type)
ret = ameth->pkey_id;
else
ret = NID_undef;
-#ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_ENGINE
ENGINE_finish(e);
-#endif
+# endif
return ret;
}
-int EVP_PKEY_id(const EVP_PKEY *pkey)
+int EVP_PKEY_get_id(const EVP_PKEY *pkey)
{
return pkey->type;
}
-int EVP_PKEY_base_id(const EVP_PKEY *pkey)
+int EVP_PKEY_get_base_id(const EVP_PKEY *pkey)
{
return EVP_PKEY_type(pkey->type);
}
-void EVP_PKEY_free(EVP_PKEY *x)
+/*
+ * These hard coded cases are pure hackery to get around the fact
+ * that names in crypto/objects/objects.txt are a mess. There is
+ * no "EC", and "RSA" leads to the NID for 2.5.8.1.1, an OID that's
+ * fallen out in favor of { pkcs-1 1 }, i.e. 1.2.840.113549.1.1.1,
+ * the NID of which is used for EVP_PKEY_RSA. Strangely enough,
+ * "DSA" is accurate... but still, better be safe and hard-code
+ * names that we know.
+ * On a similar topic, EVP_PKEY_type(EVP_PKEY_SM2) will result in
+ * EVP_PKEY_EC, because of aliasing.
+ * This should be cleaned away along with all other #legacy support.
+ */
+static const OSSL_ITEM standard_name2type[] = {
+ { EVP_PKEY_RSA, "RSA" },
+ { EVP_PKEY_RSA_PSS, "RSA-PSS" },
+ { EVP_PKEY_EC, "EC" },
+ { EVP_PKEY_ED25519, "ED25519" },
+ { EVP_PKEY_ED448, "ED448" },
+ { EVP_PKEY_X25519, "X25519" },
+ { EVP_PKEY_X448, "X448" },
+ { EVP_PKEY_SM2, "SM2" },
+ { EVP_PKEY_DH, "DH" },
+ { EVP_PKEY_DHX, "X9.42 DH" },
+ { EVP_PKEY_DHX, "DHX" },
+ { EVP_PKEY_DSA, "DSA" },
+};
+
+int evp_pkey_name2type(const char *name)
{
- int i;
+ int type;
+ size_t i;
- if (x == NULL)
- return;
+ for (i = 0; i < OSSL_NELEM(standard_name2type); i++) {
+ if (OPENSSL_strcasecmp(name, standard_name2type[i].ptr) == 0)
+ return (int)standard_name2type[i].id;
+ }
- CRYPTO_DOWN_REF(&x->references, &i, x->lock);
- REF_PRINT_COUNT("EVP_PKEY", x);
- if (i > 0)
- return;
- REF_ASSERT_ISNT(i < 0);
- EVP_PKEY_free_it(x);
- CRYPTO_THREAD_lock_free(x->lock);
- sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
- OPENSSL_free(x);
+ if ((type = EVP_PKEY_type(OBJ_sn2nid(name))) != NID_undef)
+ return type;
+ return EVP_PKEY_type(OBJ_ln2nid(name));
}
-static void EVP_PKEY_free_it(EVP_PKEY *x)
+const char *evp_pkey_type2name(int type)
{
- /* internal function; x is never NULL */
- if (x->ameth && x->ameth->pkey_free) {
- x->ameth->pkey_free(x);
- x->pkey.ptr = NULL;
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(standard_name2type); i++) {
+ if (type == (int)standard_name2type[i].id)
+ return standard_name2type[i].ptr;
}
-#ifndef OPENSSL_NO_ENGINE
- ENGINE_finish(x->engine);
- x->engine = NULL;
- ENGINE_finish(x->pmeth_engine);
- x->pmeth_engine = NULL;
-#endif
+
+ return OBJ_nid2sn(type);
+}
+
+int EVP_PKEY_is_a(const EVP_PKEY *pkey, const char *name)
+{
+ if (pkey == NULL)
+ return 0;
+ if (pkey->keymgmt == NULL)
+ return pkey->type == evp_pkey_name2type(name);
+ return EVP_KEYMGMT_is_a(pkey->keymgmt, name);
+}
+
+int EVP_PKEY_type_names_do_all(const EVP_PKEY *pkey,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (!evp_pkey_is_typed(pkey))
+ return 0;
+
+ if (!evp_pkey_is_provided(pkey)) {
+ const char *name = OBJ_nid2sn(EVP_PKEY_get_id(pkey));
+
+ fn(name, data);
+ return 1;
+ }
+ return EVP_KEYMGMT_names_do_all(pkey->keymgmt, fn, data);
+}
+
+int EVP_PKEY_can_sign(const EVP_PKEY *pkey)
+{
+ if (pkey->keymgmt == NULL) {
+ switch (EVP_PKEY_get_base_id(pkey)) {
+ case EVP_PKEY_RSA:
+ return 1;
+# ifndef OPENSSL_NO_DSA
+ case EVP_PKEY_DSA:
+ return 1;
+# endif
+# ifndef OPENSSL_NO_EC
+ case EVP_PKEY_ED25519:
+ case EVP_PKEY_ED448:
+ return 1;
+ case EVP_PKEY_EC: /* Including SM2 */
+ return EC_KEY_can_sign(pkey->pkey.ec);
+# endif
+ default:
+ break;
+ }
+ } else {
+ const OSSL_PROVIDER *prov = EVP_KEYMGMT_get0_provider(pkey->keymgmt);
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
+ const char *supported_sig =
+ pkey->keymgmt->query_operation_name != NULL
+ ? pkey->keymgmt->query_operation_name(OSSL_OP_SIGNATURE)
+ : EVP_KEYMGMT_get0_name(pkey->keymgmt);
+ EVP_SIGNATURE *signature = NULL;
+
+ signature = EVP_SIGNATURE_fetch(libctx, supported_sig, NULL);
+ if (signature != NULL) {
+ EVP_SIGNATURE_free(signature);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int print_reset_indent(BIO **out, int pop_f_prefix, long saved_indent)
+{
+ BIO_set_indent(*out, saved_indent);
+ if (pop_f_prefix) {
+ BIO *next = BIO_pop(*out);
+
+ BIO_free(*out);
+ *out = next;
+ }
+ return 1;
+}
+
+static int print_set_indent(BIO **out, int *pop_f_prefix, long *saved_indent,
+ long indent)
+{
+ *pop_f_prefix = 0;
+ *saved_indent = 0;
+ if (indent > 0) {
+ long i = BIO_get_indent(*out);
+
+ *saved_indent = (i < 0 ? 0 : i);
+ if (BIO_set_indent(*out, indent) <= 0) {
+ BIO *prefbio = BIO_new(BIO_f_prefix());
+
+ if (prefbio == NULL)
+ return 0;
+ *out = BIO_push(prefbio, *out);
+ *pop_f_prefix = 1;
+ }
+ if (BIO_set_indent(*out, indent) <= 0) {
+ print_reset_indent(out, *pop_f_prefix, *saved_indent);
+ return 0;
+ }
+ }
+ return 1;
}
static int unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent,
const char *kstr)
{
- BIO_indent(out, indent, 128);
- BIO_printf(out, "%s algorithm \"%s\" unsupported\n",
- kstr, OBJ_nid2ln(pkey->type));
- return 1;
+ return BIO_indent(out, indent, 128)
+ && BIO_printf(out, "%s algorithm \"%s\" unsupported\n",
+ kstr, OBJ_nid2ln(pkey->type)) > 0;
+}
+
+static int print_pkey(const EVP_PKEY *pkey, BIO *out, int indent,
+ int selection /* For provided encoding */,
+ const char *propquery /* For provided encoding */,
+ int (*legacy_print)(BIO *out, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx),
+ ASN1_PCTX *legacy_pctx /* For legacy print */)
+{
+ int pop_f_prefix;
+ long saved_indent;
+ OSSL_ENCODER_CTX *ctx = NULL;
+ int ret = -2; /* default to unsupported */
+
+ if (!print_set_indent(&out, &pop_f_prefix, &saved_indent, indent))
+ return 0;
+
+ ctx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, "TEXT", NULL,
+ propquery);
+ if (OSSL_ENCODER_CTX_get_num_encoders(ctx) != 0)
+ ret = OSSL_ENCODER_to_bio(ctx, out);
+ OSSL_ENCODER_CTX_free(ctx);
+
+ if (ret != -2)
+ goto end;
+
+ /* legacy fallback */
+ if (legacy_print != NULL)
+ ret = legacy_print(out, pkey, 0, legacy_pctx);
+ else
+ ret = unsup_alg(out, pkey, 0, "Public Key");
+
+ end:
+ print_reset_indent(&out, pop_f_prefix, saved_indent);
+ return ret;
}
int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx)
{
- if (pkey->ameth && pkey->ameth->pub_print)
- return pkey->ameth->pub_print(out, pkey, indent, pctx);
-
- return unsup_alg(out, pkey, indent, "Public Key");
+ return print_pkey(pkey, out, indent, EVP_PKEY_PUBLIC_KEY, NULL,
+ (pkey->ameth != NULL ? pkey->ameth->pub_print : NULL),
+ pctx);
}
int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx)
{
- if (pkey->ameth && pkey->ameth->priv_print)
- return pkey->ameth->priv_print(out, pkey, indent, pctx);
-
- return unsup_alg(out, pkey, indent, "Private Key");
+ return print_pkey(pkey, out, indent, EVP_PKEY_KEYPAIR, NULL,
+ (pkey->ameth != NULL ? pkey->ameth->priv_print : NULL),
+ pctx);
}
int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx)
{
- if (pkey->ameth && pkey->ameth->param_print)
- return pkey->ameth->param_print(out, pkey, indent, pctx);
- return unsup_alg(out, pkey, indent, "Parameters");
+ return print_pkey(pkey, out, indent, EVP_PKEY_KEY_PARAMETERS, NULL,
+ (pkey->ameth != NULL ? pkey->ameth->param_print : NULL),
+ pctx);
+}
+
+# ifndef OPENSSL_NO_STDIO
+int EVP_PKEY_print_public_fp(FILE *fp, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx)
+{
+ int ret;
+ BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
+
+ if (b == NULL)
+ return 0;
+ ret = EVP_PKEY_print_public(b, pkey, indent, pctx);
+ BIO_free(b);
+ return ret;
+}
+
+int EVP_PKEY_print_private_fp(FILE *fp, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx)
+{
+ int ret;
+ BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
+
+ if (b == NULL)
+ return 0;
+ ret = EVP_PKEY_print_private(b, pkey, indent, pctx);
+ BIO_free(b);
+ return ret;
+}
+
+int EVP_PKEY_print_params_fp(FILE *fp, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx)
+{
+ int ret;
+ BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
+
+ if (b == NULL)
+ return 0;
+ ret = EVP_PKEY_print_params(b, pkey, indent, pctx);
+ BIO_free(b);
+ return ret;
+}
+# endif
+
+static void mdname2nid(const char *mdname, void *data)
+{
+ int *nid = (int *)data;
+
+ if (*nid != NID_undef)
+ return;
+
+ *nid = OBJ_sn2nid(mdname);
+ if (*nid == NID_undef)
+ *nid = OBJ_ln2nid(mdname);
+}
+
+static int legacy_asn1_ctrl_to_param(EVP_PKEY *pkey, int op,
+ int arg1, void *arg2)
+{
+ if (pkey->keymgmt == NULL)
+ return 0;
+ switch (op) {
+ case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
+ {
+ char mdname[80] = "";
+ int rv = EVP_PKEY_get_default_digest_name(pkey, mdname,
+ sizeof(mdname));
+
+ if (rv > 0) {
+ int mdnum;
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(pkey->keymgmt->prov);
+ /* Make sure the MD is in the namemap if available */
+ EVP_MD *md;
+ OSSL_NAMEMAP *namemap;
+ int nid = NID_undef;
+
+ (void)ERR_set_mark();
+ md = EVP_MD_fetch(libctx, mdname, NULL);
+ (void)ERR_pop_to_mark();
+ namemap = ossl_namemap_stored(libctx);
+
+ /*
+ * The only reason to fetch the MD was to make sure it is in the
+ * namemap. We can immediately free it.
+ */
+ EVP_MD_free(md);
+ mdnum = ossl_namemap_name2num(namemap, mdname);
+ if (mdnum == 0)
+ return 0;
+
+ /*
+ * We have the namemap number - now we need to find the
+ * associated nid
+ */
+ if (!ossl_namemap_doall_names(namemap, mdnum, mdname2nid, &nid))
+ return 0;
+ *(int *)arg2 = nid;
+ }
+ return rv;
+ }
+ default:
+ return -2;
+ }
}
static int evp_pkey_asn1_ctrl(EVP_PKEY *pkey, int op, int arg1, void *arg2)
{
- if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL)
+ if (pkey->ameth == NULL)
+ return legacy_asn1_ctrl_to_param(pkey, op, arg1, arg2);
+ if (pkey->ameth->pkey_ctrl == NULL)
return -2;
return pkey->ameth->pkey_ctrl(pkey, op, arg1, arg2);
}
@@ -677,22 +1327,1134 @@ int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid)
return evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_DEFAULT_MD_NID, 0, pnid);
}
-int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey,
- const unsigned char *pt, size_t ptlen)
+int EVP_PKEY_get_default_digest_name(EVP_PKEY *pkey,
+ char *mdname, size_t mdname_sz)
+{
+ if (pkey->ameth == NULL)
+ return evp_keymgmt_util_get_deflt_digest_name(pkey->keymgmt,
+ pkey->keydata,
+ mdname, mdname_sz);
+
+ {
+ int nid = NID_undef;
+ int rv = EVP_PKEY_get_default_digest_nid(pkey, &nid);
+ const char *name = rv > 0 ? OBJ_nid2sn(nid) : NULL;
+
+ if (rv > 0)
+ OPENSSL_strlcpy(mdname, name, mdname_sz);
+ return rv;
+ }
+}
+
+int EVP_PKEY_get_group_name(const EVP_PKEY *pkey, char *gname, size_t gname_sz,
+ size_t *gname_len)
{
- if (ptlen > INT_MAX)
+ return EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME,
+ gname, gname_sz, gname_len);
+}
+
+int EVP_PKEY_digestsign_supports_digest(EVP_PKEY *pkey, OSSL_LIB_CTX *libctx,
+ const char *name, const char *propq)
+{
+ int rv;
+ EVP_MD_CTX *ctx = NULL;
+
+ if ((ctx = EVP_MD_CTX_new()) == NULL)
+ return -1;
+
+ ERR_set_mark();
+ rv = EVP_DigestSignInit_ex(ctx, NULL, name, libctx,
+ propq, pkey, NULL);
+ ERR_pop_to_mark();
+
+ EVP_MD_CTX_free(ctx);
+ return rv;
+}
+
+int EVP_PKEY_set1_encoded_public_key(EVP_PKEY *pkey, const unsigned char *pub,
+ size_t publen)
+{
+ if (pkey != NULL && evp_pkey_is_provided(pkey))
+ return
+ EVP_PKEY_set_octet_string_param(pkey,
+ OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
+ (unsigned char *)pub, publen);
+
+ if (publen > INT_MAX)
return 0;
- if (evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_SET1_TLS_ENCPT, ptlen,
- (void *)pt) <= 0)
+ /* Historically this function was EVP_PKEY_set1_tls_encodedpoint */
+ if (evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_SET1_TLS_ENCPT, publen,
+ (void *)pub) <= 0)
return 0;
return 1;
}
-size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *pkey, unsigned char **ppt)
+size_t EVP_PKEY_get1_encoded_public_key(EVP_PKEY *pkey, unsigned char **ppub)
{
int rv;
- rv = evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_GET1_TLS_ENCPT, 0, ppt);
+
+ if (pkey != NULL && evp_pkey_is_provided(pkey)) {
+ size_t return_size = OSSL_PARAM_UNMODIFIED;
+ unsigned char *buf;
+
+ /*
+ * We know that this is going to fail, but it will give us a size
+ * to allocate.
+ */
+ EVP_PKEY_get_octet_string_param(pkey,
+ OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
+ NULL, 0, &return_size);
+ if (return_size == OSSL_PARAM_UNMODIFIED)
+ return 0;
+
+ *ppub = NULL;
+ buf = OPENSSL_malloc(return_size);
+ if (buf == NULL)
+ return 0;
+
+ if (!EVP_PKEY_get_octet_string_param(pkey,
+ OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
+ buf, return_size, NULL)) {
+ OPENSSL_free(buf);
+ return 0;
+ }
+ *ppub = buf;
+ return return_size;
+ }
+
+
+ rv = evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_GET1_TLS_ENCPT, 0, ppub);
if (rv <= 0)
return 0;
return rv;
}
+
+#endif /* FIPS_MODULE */
+
+/*- All methods below can also be used in FIPS_MODULE */
+
+EVP_PKEY *EVP_PKEY_new(void)
+{
+ EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret));
+
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ ret->type = EVP_PKEY_NONE;
+ ret->save_type = EVP_PKEY_NONE;
+ ret->references = 1;
+
+ ret->lock = CRYPTO_THREAD_lock_new();
+ if (ret->lock == NULL) {
+ EVPerr(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+#ifndef FIPS_MODULE
+ ret->save_parameters = 1;
+ if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EVP_PKEY, ret, &ret->ex_data)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+#endif
+ return ret;
+
+ err:
+ CRYPTO_THREAD_lock_free(ret->lock);
+ OPENSSL_free(ret);
+ return NULL;
+}
+
+/*
+ * Setup a public key management method.
+ *
+ * For legacy keys, either |type| or |str| is expected to have the type
+ * information. In this case, the setup consists of finding an ASN1 method
+ * and potentially an ENGINE, and setting those fields in |pkey|.
+ *
+ * For provider side keys, |keymgmt| is expected to be non-NULL. In this
+ * case, the setup consists of setting the |keymgmt| field in |pkey|.
+ *
+ * If pkey is NULL just return 1 or 0 if the key management method exists.
+ */
+
+static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str,
+ int len, EVP_KEYMGMT *keymgmt)
+{
+#ifndef FIPS_MODULE
+ const EVP_PKEY_ASN1_METHOD *ameth = NULL;
+ ENGINE **eptr = (e == NULL) ? &e : NULL;
+#endif
+
+ /*
+ * The setups can't set both legacy and provider side methods.
+ * It is forbidden
+ */
+ if (!ossl_assert(type == EVP_PKEY_NONE || keymgmt == NULL)
+ || !ossl_assert(e == NULL || keymgmt == NULL)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (pkey != NULL) {
+ int free_it = 0;
+
+#ifndef FIPS_MODULE
+ free_it = free_it || pkey->pkey.ptr != NULL;
+#endif
+ free_it = free_it || pkey->keydata != NULL;
+ if (free_it)
+ evp_pkey_free_it(pkey);
+#ifndef FIPS_MODULE
+ /*
+ * If key type matches and a method exists then this lookup has
+ * succeeded once so just indicate success.
+ */
+ if (pkey->type != EVP_PKEY_NONE
+ && type == pkey->save_type
+ && pkey->ameth != NULL)
+ return 1;
+# ifndef OPENSSL_NO_ENGINE
+ /* If we have ENGINEs release them */
+ ENGINE_finish(pkey->engine);
+ pkey->engine = NULL;
+ ENGINE_finish(pkey->pmeth_engine);
+ pkey->pmeth_engine = NULL;
+# endif
+#endif
+ }
+#ifndef FIPS_MODULE
+ if (str != NULL)
+ ameth = EVP_PKEY_asn1_find_str(eptr, str, len);
+ else if (type != EVP_PKEY_NONE)
+ ameth = EVP_PKEY_asn1_find(eptr, type);
+# ifndef OPENSSL_NO_ENGINE
+ if (pkey == NULL && eptr != NULL)
+ ENGINE_finish(e);
+# endif
+#endif
+
+
+ {
+ int check = 1;
+
+#ifndef FIPS_MODULE
+ check = check && ameth == NULL;
+#endif
+ check = check && keymgmt == NULL;
+ if (check) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_ALGORITHM);
+ return 0;
+ }
+ }
+ if (pkey != NULL) {
+ if (keymgmt != NULL && !EVP_KEYMGMT_up_ref(keymgmt)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ pkey->keymgmt = keymgmt;
+
+ pkey->save_type = type;
+ pkey->type = type;
+
+#ifndef FIPS_MODULE
+ /*
+ * If the internal "origin" key is provider side, don't save |ameth|.
+ * The main reason is that |ameth| is one factor to detect that the
+ * internal "origin" key is a legacy one.
+ */
+ if (keymgmt == NULL)
+ pkey->ameth = ameth;
+
+ /*
+ * The EVP_PKEY_ASN1_METHOD |pkey_id| retains its legacy key purpose
+ * for any key type that has a legacy implementation, regardless of
+ * if the internal key is a legacy or a provider side one. When
+ * there is no legacy implementation for the key, the type becomes
+ * EVP_PKEY_KEYMGMT, which indicates that one should be cautious
+ * with functions that expect legacy internal keys.
+ */
+ if (ameth != NULL) {
+ if (type == EVP_PKEY_NONE)
+ pkey->type = ameth->pkey_id;
+ } else {
+ pkey->type = EVP_PKEY_KEYMGMT;
+ }
+# ifndef OPENSSL_NO_ENGINE
+ if (eptr == NULL && e != NULL && !ENGINE_init(e)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+# endif
+ pkey->engine = e;
+#endif
+ }
+ return 1;
+}
+
+#ifndef FIPS_MODULE
+static void find_ameth(const char *name, void *data)
+{
+ const char **str = data;
+
+ /*
+ * The error messages from pkey_set_type() are uninteresting here,
+ * and misleading.
+ */
+ ERR_set_mark();
+
+ if (pkey_set_type(NULL, NULL, EVP_PKEY_NONE, name, strlen(name),
+ NULL)) {
+ if (str[0] == NULL)
+ str[0] = name;
+ else if (str[1] == NULL)
+ str[1] = name;
+ }
+
+ ERR_pop_to_mark();
+}
+#endif
+
+int EVP_PKEY_set_type_by_keymgmt(EVP_PKEY *pkey, EVP_KEYMGMT *keymgmt)
+{
+#ifndef FIPS_MODULE
+# define EVP_PKEY_TYPE_STR str[0]
+# define EVP_PKEY_TYPE_STRLEN (str[0] == NULL ? -1 : (int)strlen(str[0]))
+ /*
+ * Find at most two strings that have an associated EVP_PKEY_ASN1_METHOD
+ * Ideally, only one should be found. If two (or more) are found, the
+ * match is ambiguous. This should never happen, but...
+ */
+ const char *str[2] = { NULL, NULL };
+
+ if (!EVP_KEYMGMT_names_do_all(keymgmt, find_ameth, &str)
+ || str[1] != NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+#else
+# define EVP_PKEY_TYPE_STR NULL
+# define EVP_PKEY_TYPE_STRLEN -1
+#endif
+ return pkey_set_type(pkey, NULL, EVP_PKEY_NONE,
+ EVP_PKEY_TYPE_STR, EVP_PKEY_TYPE_STRLEN,
+ keymgmt);
+
+#undef EVP_PKEY_TYPE_STR
+#undef EVP_PKEY_TYPE_STRLEN
+}
+
+int EVP_PKEY_up_ref(EVP_PKEY *pkey)
+{
+ int i;
+
+ if (CRYPTO_UP_REF(&pkey->references, &i, pkey->lock) <= 0)
+ return 0;
+
+ REF_PRINT_COUNT("EVP_PKEY", pkey);
+ REF_ASSERT_ISNT(i < 2);
+ return ((i > 1) ? 1 : 0);
+}
+
+#ifndef FIPS_MODULE
+EVP_PKEY *EVP_PKEY_dup(EVP_PKEY *pkey)
+{
+ EVP_PKEY *dup_pk;
+
+ if (pkey == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+
+ if ((dup_pk = EVP_PKEY_new()) == NULL)
+ return NULL;
+
+ if (evp_pkey_is_blank(pkey))
+ goto done;
+
+ if (evp_pkey_is_provided(pkey)) {
+ if (!evp_keymgmt_util_copy(dup_pk, pkey,
+ OSSL_KEYMGMT_SELECT_ALL))
+ goto err;
+ goto done;
+ }
+
+ if (evp_pkey_is_legacy(pkey)) {
+ const EVP_PKEY_ASN1_METHOD *ameth = pkey->ameth;
+
+ if (ameth == NULL || ameth->copy == NULL) {
+ if (pkey->pkey.ptr == NULL /* empty key, just set type */
+ && EVP_PKEY_set_type(dup_pk, pkey->type) != 0)
+ goto done;
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE);
+ goto err;
+ }
+ if (!ameth->copy(dup_pk, pkey))
+ goto err;
+ goto done;
+ }
+
+ goto err;
+done:
+ /* copy auxiliary data */
+ if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EVP_PKEY,
+ &dup_pk->ex_data, &pkey->ex_data))
+ goto err;
+
+ if (pkey->attributes != NULL) {
+ if ((dup_pk->attributes = ossl_x509at_dup(pkey->attributes)) == NULL)
+ goto err;
+ }
+ return dup_pk;
+err:
+ EVP_PKEY_free(dup_pk);
+ return NULL;
+}
+
+void evp_pkey_free_legacy(EVP_PKEY *x)
+{
+ const EVP_PKEY_ASN1_METHOD *ameth = x->ameth;
+ ENGINE *tmpe = NULL;
+
+ if (ameth == NULL && x->legacy_cache_pkey.ptr != NULL)
+ ameth = EVP_PKEY_asn1_find(&tmpe, x->type);
+
+ if (ameth != NULL) {
+ if (x->legacy_cache_pkey.ptr != NULL) {
+ /*
+ * We should never have both a legacy origin key, and a key in the
+ * legacy cache.
+ */
+ assert(x->pkey.ptr == NULL);
+ /*
+ * For the purposes of freeing we make the legacy cache look like
+ * a legacy origin key.
+ */
+ x->pkey = x->legacy_cache_pkey;
+ x->legacy_cache_pkey.ptr = NULL;
+ }
+ if (ameth->pkey_free != NULL)
+ ameth->pkey_free(x);
+ x->pkey.ptr = NULL;
+ }
+# ifndef OPENSSL_NO_ENGINE
+ ENGINE_finish(tmpe);
+ ENGINE_finish(x->engine);
+ x->engine = NULL;
+ ENGINE_finish(x->pmeth_engine);
+ x->pmeth_engine = NULL;
+# endif
+}
+#endif /* FIPS_MODULE */
+
+static void evp_pkey_free_it(EVP_PKEY *x)
+{
+ /* internal function; x is never NULL */
+ evp_keymgmt_util_clear_operation_cache(x, 1);
+#ifndef FIPS_MODULE
+ evp_pkey_free_legacy(x);
+#endif
+
+ if (x->keymgmt != NULL) {
+ evp_keymgmt_freedata(x->keymgmt, x->keydata);
+ EVP_KEYMGMT_free(x->keymgmt);
+ x->keymgmt = NULL;
+ x->keydata = NULL;
+ }
+ x->type = EVP_PKEY_NONE;
+}
+
+void EVP_PKEY_free(EVP_PKEY *x)
+{
+ int i;
+
+ if (x == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&x->references, &i, x->lock);
+ REF_PRINT_COUNT("EVP_PKEY", x);
+ if (i > 0)
+ return;
+ REF_ASSERT_ISNT(i < 0);
+ evp_pkey_free_it(x);
+#ifndef FIPS_MODULE
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EVP_PKEY, x, &x->ex_data);
+#endif
+ CRYPTO_THREAD_lock_free(x->lock);
+#ifndef FIPS_MODULE
+ sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
+#endif
+ OPENSSL_free(x);
+}
+
+int EVP_PKEY_get_size(const EVP_PKEY *pkey)
+{
+ int size = 0;
+
+ if (pkey != NULL) {
+ size = pkey->cache.size;
+#ifndef FIPS_MODULE
+ if (pkey->ameth != NULL && pkey->ameth->pkey_size != NULL)
+ size = pkey->ameth->pkey_size(pkey);
+#endif
+ }
+ return size < 0 ? 0 : size;
+}
+
+const char *EVP_PKEY_get0_description(const EVP_PKEY *pkey)
+{
+ if (!evp_pkey_is_assigned(pkey))
+ return NULL;
+
+ if (evp_pkey_is_provided(pkey) && pkey->keymgmt->description != NULL)
+ return pkey->keymgmt->description;
+#ifndef FIPS_MODULE
+ if (pkey->ameth != NULL)
+ return pkey->ameth->info;
+#endif
+ return NULL;
+}
+
+void *evp_pkey_export_to_provider(EVP_PKEY *pk, OSSL_LIB_CTX *libctx,
+ EVP_KEYMGMT **keymgmt,
+ const char *propquery)
+{
+ EVP_KEYMGMT *allocated_keymgmt = NULL;
+ EVP_KEYMGMT *tmp_keymgmt = NULL;
+ int selection = OSSL_KEYMGMT_SELECT_ALL;
+ void *keydata = NULL;
+ int check;
+
+ if (pk == NULL)
+ return NULL;
+
+ /* No key data => nothing to export */
+ check = 1;
+#ifndef FIPS_MODULE
+ check = check && pk->pkey.ptr == NULL;
+#endif
+ check = check && pk->keydata == NULL;
+ if (check)
+ return NULL;
+
+#ifndef FIPS_MODULE
+ if (pk->pkey.ptr != NULL) {
+ /*
+ * If the legacy key doesn't have an dirty counter or export function,
+ * give up
+ */
+ if (pk->ameth->dirty_cnt == NULL || pk->ameth->export_to == NULL)
+ return NULL;
+ }
+#endif
+
+ if (keymgmt != NULL) {
+ tmp_keymgmt = *keymgmt;
+ *keymgmt = NULL;
+ }
+
+ /*
+ * If no keymgmt was given or found, get a default keymgmt. We do so by
+ * letting EVP_PKEY_CTX_new_from_pkey() do it for us, then we steal it.
+ */
+ if (tmp_keymgmt == NULL) {
+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pk, propquery);
+
+ if (ctx == NULL)
+ goto end;
+ allocated_keymgmt = tmp_keymgmt = ctx->keymgmt;
+ ctx->keymgmt = NULL;
+ EVP_PKEY_CTX_free(ctx);
+ }
+
+ /* If there's still no keymgmt to be had, give up */
+ if (tmp_keymgmt == NULL)
+ goto end;
+
+#ifndef FIPS_MODULE
+ if (pk->pkey.ptr != NULL) {
+ OP_CACHE_ELEM *op;
+
+ /*
+ * If the legacy "origin" hasn't changed since last time, we try
+ * to find our keymgmt in the operation cache. If it has changed,
+ * |i| remains zero, and we will clear the cache further down.
+ */
+ if (pk->ameth->dirty_cnt(pk) == pk->dirty_cnt_copy) {
+ if (!CRYPTO_THREAD_read_lock(pk->lock))
+ goto end;
+ op = evp_keymgmt_util_find_operation_cache(pk, tmp_keymgmt,
+ selection);
+
+ /*
+ * If |tmp_keymgmt| is present in the operation cache, it means
+ * that export doesn't need to be redone. In that case, we take
+ * token copies of the cached pointers, to have token success
+ * values to return.
+ */
+ if (op != NULL && op->keymgmt != NULL) {
+ keydata = op->keydata;
+ CRYPTO_THREAD_unlock(pk->lock);
+ goto end;
+ }
+ CRYPTO_THREAD_unlock(pk->lock);
+ }
+
+ /* Make sure that the keymgmt key type matches the legacy NID */
+ if (!EVP_KEYMGMT_is_a(tmp_keymgmt, OBJ_nid2sn(pk->type)))
+ goto end;
+
+ if ((keydata = evp_keymgmt_newdata(tmp_keymgmt)) == NULL)
+ goto end;
+
+ if (!pk->ameth->export_to(pk, keydata, tmp_keymgmt->import,
+ libctx, propquery)) {
+ evp_keymgmt_freedata(tmp_keymgmt, keydata);
+ keydata = NULL;
+ goto end;
+ }
+
+ /*
+ * If the dirty counter changed since last time, then clear the
+ * operation cache. In that case, we know that |i| is zero. Just
+ * in case this is a re-export, we increment then decrement the
+ * keymgmt reference counter.
+ */
+ if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) { /* refcnt++ */
+ evp_keymgmt_freedata(tmp_keymgmt, keydata);
+ keydata = NULL;
+ goto end;
+ }
+
+ if (!CRYPTO_THREAD_write_lock(pk->lock))
+ goto end;
+ if (pk->ameth->dirty_cnt(pk) != pk->dirty_cnt_copy
+ && !evp_keymgmt_util_clear_operation_cache(pk, 0)) {
+ CRYPTO_THREAD_unlock(pk->lock);
+ evp_keymgmt_freedata(tmp_keymgmt, keydata);
+ keydata = NULL;
+ EVP_KEYMGMT_free(tmp_keymgmt);
+ goto end;
+ }
+ EVP_KEYMGMT_free(tmp_keymgmt); /* refcnt-- */
+
+ /* Check to make sure some other thread didn't get there first */
+ op = evp_keymgmt_util_find_operation_cache(pk, tmp_keymgmt, selection);
+ if (op != NULL && op->keymgmt != NULL) {
+ void *tmp_keydata = op->keydata;
+
+ CRYPTO_THREAD_unlock(pk->lock);
+ evp_keymgmt_freedata(tmp_keymgmt, keydata);
+ keydata = tmp_keydata;
+ goto end;
+ }
+
+ /* Add the new export to the operation cache */
+ if (!evp_keymgmt_util_cache_keydata(pk, tmp_keymgmt, keydata,
+ selection)) {
+ CRYPTO_THREAD_unlock(pk->lock);
+ evp_keymgmt_freedata(tmp_keymgmt, keydata);
+ keydata = NULL;
+ goto end;
+ }
+
+ /* Synchronize the dirty count */
+ pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk);
+
+ CRYPTO_THREAD_unlock(pk->lock);
+ goto end;
+ }
+#endif /* FIPS_MODULE */
+
+ keydata = evp_keymgmt_util_export_to_provider(pk, tmp_keymgmt, selection);
+
+ end:
+ /*
+ * If nothing was exported, |tmp_keymgmt| might point at a freed
+ * EVP_KEYMGMT, so we clear it to be safe. It shouldn't be useful for
+ * the caller either way in that case.
+ */
+ if (keydata == NULL)
+ tmp_keymgmt = NULL;
+
+ if (keymgmt != NULL && tmp_keymgmt != NULL) {
+ *keymgmt = tmp_keymgmt;
+ allocated_keymgmt = NULL;
+ }
+
+ EVP_KEYMGMT_free(allocated_keymgmt);
+ return keydata;
+}
+
+#ifndef FIPS_MODULE
+int evp_pkey_copy_downgraded(EVP_PKEY **dest, const EVP_PKEY *src)
+{
+ EVP_PKEY *allocpkey = NULL;
+
+ if (!ossl_assert(dest != NULL))
+ return 0;
+
+ if (evp_pkey_is_assigned(src) && evp_pkey_is_provided(src)) {
+ EVP_KEYMGMT *keymgmt = src->keymgmt;
+ void *keydata = src->keydata;
+ int type = src->type;
+ const char *keytype = NULL;
+
+ keytype = EVP_KEYMGMT_get0_name(keymgmt);
+
+ /*
+ * If the type is EVP_PKEY_NONE, then we have a problem somewhere
+ * else in our code. If it's not one of the well known EVP_PKEY_xxx
+ * values, it should at least be EVP_PKEY_KEYMGMT at this point.
+ * The check is kept as a safety measure.
+ */
+ if (!ossl_assert(type != EVP_PKEY_NONE)) {
+ ERR_raise_data(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR,
+ "keymgmt key type = %s but legacy type = EVP_PKEY_NONE",
+ keytype);
+ return 0;
+ }
+
+ /* Prefer the legacy key type name for error reporting */
+ if (type != EVP_PKEY_KEYMGMT)
+ keytype = OBJ_nid2sn(type);
+
+ /* Make sure we have a clean slate to copy into */
+ if (*dest == NULL) {
+ allocpkey = *dest = EVP_PKEY_new();
+ if (*dest == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else {
+ evp_pkey_free_it(*dest);
+ }
+
+ if (EVP_PKEY_set_type(*dest, type)) {
+ /* If the key is typed but empty, we're done */
+ if (keydata == NULL)
+ return 1;
+
+ if ((*dest)->ameth->import_from == NULL) {
+ ERR_raise_data(ERR_LIB_EVP, EVP_R_NO_IMPORT_FUNCTION,
+ "key type = %s", keytype);
+ } else {
+ /*
+ * We perform the export in the same libctx as the keymgmt
+ * that we are using.
+ */
+ OSSL_LIB_CTX *libctx =
+ ossl_provider_libctx(keymgmt->prov);
+ EVP_PKEY_CTX *pctx =
+ EVP_PKEY_CTX_new_from_pkey(libctx, *dest, NULL);
+
+ if (pctx == NULL)
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+
+ if (pctx != NULL
+ && evp_keymgmt_export(keymgmt, keydata,
+ OSSL_KEYMGMT_SELECT_ALL,
+ (*dest)->ameth->import_from,
+ pctx)) {
+ /* Synchronize the dirty count */
+ (*dest)->dirty_cnt_copy = (*dest)->ameth->dirty_cnt(*dest);
+
+ EVP_PKEY_CTX_free(pctx);
+ return 1;
+ }
+ EVP_PKEY_CTX_free(pctx);
+ }
+
+ ERR_raise_data(ERR_LIB_EVP, EVP_R_KEYMGMT_EXPORT_FAILURE,
+ "key type = %s", keytype);
+ }
+ }
+
+ if (allocpkey != NULL) {
+ EVP_PKEY_free(allocpkey);
+ *dest = NULL;
+ }
+ return 0;
+}
+
+void *evp_pkey_get_legacy(EVP_PKEY *pk)
+{
+ EVP_PKEY *tmp_copy = NULL;
+ void *ret = NULL;
+
+ if (!ossl_assert(pk != NULL))
+ return NULL;
+
+ /*
+ * If this isn't an assigned provider side key, we just use any existing
+ * origin legacy key.
+ */
+ if (!evp_pkey_is_assigned(pk))
+ return NULL;
+ if (!evp_pkey_is_provided(pk))
+ return pk->pkey.ptr;
+
+ if (!CRYPTO_THREAD_read_lock(pk->lock))
+ return NULL;
+
+ ret = pk->legacy_cache_pkey.ptr;
+
+ if (!CRYPTO_THREAD_unlock(pk->lock))
+ return NULL;
+
+ if (ret != NULL)
+ return ret;
+
+ if (!evp_pkey_copy_downgraded(&tmp_copy, pk))
+ goto err;
+
+ if (!CRYPTO_THREAD_write_lock(pk->lock))
+ goto err;
+
+ /* Check again in case some other thread has updated it in the meantime */
+ ret = pk->legacy_cache_pkey.ptr;
+ if (ret == NULL) {
+ /* Steal the legacy key reference from the temporary copy */
+ ret = pk->legacy_cache_pkey.ptr = tmp_copy->pkey.ptr;
+ tmp_copy->pkey.ptr = NULL;
+ }
+
+ if (!CRYPTO_THREAD_unlock(pk->lock)) {
+ ret = NULL;
+ goto err;
+ }
+
+ err:
+ EVP_PKEY_free(tmp_copy);
+
+ return ret;
+}
+#endif /* FIPS_MODULE */
+
+int EVP_PKEY_get_bn_param(const EVP_PKEY *pkey, const char *key_name,
+ BIGNUM **bn)
+{
+ int ret = 0;
+ OSSL_PARAM params[2];
+ unsigned char buffer[2048];
+ unsigned char *buf = NULL;
+ size_t buf_sz = 0;
+
+ if (key_name == NULL
+ || bn == NULL)
+ return 0;
+
+ memset(buffer, 0, sizeof(buffer));
+ params[0] = OSSL_PARAM_construct_BN(key_name, buffer, sizeof(buffer));
+ params[1] = OSSL_PARAM_construct_end();
+ if (!EVP_PKEY_get_params(pkey, params)) {
+ if (!OSSL_PARAM_modified(params) || params[0].return_size == 0)
+ return 0;
+ buf_sz = params[0].return_size;
+ /*
+ * If it failed because the buffer was too small then allocate the
+ * required buffer size and retry.
+ */
+ buf = OPENSSL_zalloc(buf_sz);
+ if (buf == NULL)
+ return 0;
+ params[0].data = buf;
+ params[0].data_size = buf_sz;
+
+ if (!EVP_PKEY_get_params(pkey, params))
+ goto err;
+ }
+ /* Fail if the param was not found */
+ if (!OSSL_PARAM_modified(params))
+ goto err;
+ ret = OSSL_PARAM_get_BN(params, bn);
+err:
+ OPENSSL_free(buf);
+ return ret;
+}
+
+int EVP_PKEY_get_octet_string_param(const EVP_PKEY *pkey, const char *key_name,
+ unsigned char *buf, size_t max_buf_sz,
+ size_t *out_len)
+{
+ OSSL_PARAM params[2];
+ int ret1 = 0, ret2 = 0;
+
+ if (key_name == NULL)
+ return 0;
+
+ params[0] = OSSL_PARAM_construct_octet_string(key_name, buf, max_buf_sz);
+ params[1] = OSSL_PARAM_construct_end();
+ if ((ret1 = EVP_PKEY_get_params(pkey, params)))
+ ret2 = OSSL_PARAM_modified(params);
+ if (ret2 && out_len != NULL)
+ *out_len = params[0].return_size;
+ return ret1 && ret2;
+}
+
+int EVP_PKEY_get_utf8_string_param(const EVP_PKEY *pkey, const char *key_name,
+ char *str, size_t max_buf_sz,
+ size_t *out_len)
+{
+ OSSL_PARAM params[2];
+ int ret1 = 0, ret2 = 0;
+
+ if (key_name == NULL)
+ return 0;
+
+ params[0] = OSSL_PARAM_construct_utf8_string(key_name, str, max_buf_sz);
+ params[1] = OSSL_PARAM_construct_end();
+ if ((ret1 = EVP_PKEY_get_params(pkey, params)))
+ ret2 = OSSL_PARAM_modified(params);
+ if (ret2 && out_len != NULL)
+ *out_len = params[0].return_size;
+
+ if (ret2 && params[0].return_size == max_buf_sz)
+ /* There was no space for a NUL byte */
+ return 0;
+ /* Add a terminating NUL byte for good measure */
+ if (ret2 && str != NULL)
+ str[params[0].return_size] = '\0';
+
+ return ret1 && ret2;
+}
+
+int EVP_PKEY_get_int_param(const EVP_PKEY *pkey, const char *key_name,
+ int *out)
+{
+ OSSL_PARAM params[2];
+
+ if (key_name == NULL)
+ return 0;
+
+ params[0] = OSSL_PARAM_construct_int(key_name, out);
+ params[1] = OSSL_PARAM_construct_end();
+ return EVP_PKEY_get_params(pkey, params)
+ && OSSL_PARAM_modified(params);
+}
+
+int EVP_PKEY_get_size_t_param(const EVP_PKEY *pkey, const char *key_name,
+ size_t *out)
+{
+ OSSL_PARAM params[2];
+
+ if (key_name == NULL)
+ return 0;
+
+ params[0] = OSSL_PARAM_construct_size_t(key_name, out);
+ params[1] = OSSL_PARAM_construct_end();
+ return EVP_PKEY_get_params(pkey, params)
+ && OSSL_PARAM_modified(params);
+}
+
+int EVP_PKEY_set_int_param(EVP_PKEY *pkey, const char *key_name, int in)
+{
+ OSSL_PARAM params[2];
+
+ if (key_name == NULL)
+ return 0;
+
+ params[0] = OSSL_PARAM_construct_int(key_name, &in);
+ params[1] = OSSL_PARAM_construct_end();
+ return EVP_PKEY_set_params(pkey, params);
+}
+
+int EVP_PKEY_set_size_t_param(EVP_PKEY *pkey, const char *key_name, size_t in)
+{
+ OSSL_PARAM params[2];
+
+ if (key_name == NULL)
+ return 0;
+
+ params[0] = OSSL_PARAM_construct_size_t(key_name, &in);
+ params[1] = OSSL_PARAM_construct_end();
+ return EVP_PKEY_set_params(pkey, params);
+}
+
+int EVP_PKEY_set_bn_param(EVP_PKEY *pkey, const char *key_name,
+ const BIGNUM *bn)
+{
+ OSSL_PARAM params[2];
+ unsigned char buffer[2048];
+ int bsize = 0;
+
+ if (key_name == NULL
+ || bn == NULL
+ || pkey == NULL
+ || !evp_pkey_is_assigned(pkey))
+ return 0;
+
+ bsize = BN_num_bytes(bn);
+ if (!ossl_assert(bsize <= (int)sizeof(buffer)))
+ return 0;
+
+ if (BN_bn2nativepad(bn, buffer, bsize) < 0)
+ return 0;
+ params[0] = OSSL_PARAM_construct_BN(key_name, buffer, bsize);
+ params[1] = OSSL_PARAM_construct_end();
+ return EVP_PKEY_set_params(pkey, params);
+}
+
+int EVP_PKEY_set_utf8_string_param(EVP_PKEY *pkey, const char *key_name,
+ const char *str)
+{
+ OSSL_PARAM params[2];
+
+ if (key_name == NULL)
+ return 0;
+
+ params[0] = OSSL_PARAM_construct_utf8_string(key_name, (char *)str, 0);
+ params[1] = OSSL_PARAM_construct_end();
+ return EVP_PKEY_set_params(pkey, params);
+}
+
+int EVP_PKEY_set_octet_string_param(EVP_PKEY *pkey, const char *key_name,
+ const unsigned char *buf, size_t bsize)
+{
+ OSSL_PARAM params[2];
+
+ if (key_name == NULL)
+ return 0;
+
+ params[0] = OSSL_PARAM_construct_octet_string(key_name,
+ (unsigned char *)buf, bsize);
+ params[1] = OSSL_PARAM_construct_end();
+ return EVP_PKEY_set_params(pkey, params);
+}
+
+const OSSL_PARAM *EVP_PKEY_settable_params(const EVP_PKEY *pkey)
+{
+ return (pkey != NULL && evp_pkey_is_provided(pkey))
+ ? EVP_KEYMGMT_settable_params(pkey->keymgmt)
+ : NULL;
+}
+
+int EVP_PKEY_set_params(EVP_PKEY *pkey, OSSL_PARAM params[])
+{
+ if (pkey != NULL) {
+ if (evp_pkey_is_provided(pkey)) {
+ pkey->dirty_cnt++;
+ return evp_keymgmt_set_params(pkey->keymgmt, pkey->keydata, params);
+ }
+#ifndef FIPS_MODULE
+ /*
+ * We will hopefully never find the need to set individual data in
+ * EVP_PKEYs with a legacy internal key, but we can't be entirely
+ * sure. This bit of code can be enabled if we find the need. If
+ * not, it can safely be removed when #legacy support is removed.
+ */
+# if 0
+ else if (evp_pkey_is_legacy(pkey)) {
+ return evp_pkey_set_params_to_ctrl(pkey, params);
+ }
+# endif
+#endif
+ }
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY);
+ return 0;
+}
+
+const OSSL_PARAM *EVP_PKEY_gettable_params(const EVP_PKEY *pkey)
+{
+ return (pkey != NULL && evp_pkey_is_provided(pkey))
+ ? EVP_KEYMGMT_gettable_params(pkey->keymgmt)
+ : NULL;
+}
+
+int EVP_PKEY_get_params(const EVP_PKEY *pkey, OSSL_PARAM params[])
+{
+ if (pkey != NULL) {
+ if (evp_pkey_is_provided(pkey))
+ return evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params) > 0;
+#ifndef FIPS_MODULE
+ else if (evp_pkey_is_legacy(pkey))
+ return evp_pkey_get_params_to_ctrl(pkey, params) > 0;
+#endif
+ }
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY);
+ return 0;
+}
+
+#ifndef FIPS_MODULE
+int EVP_PKEY_get_ec_point_conv_form(const EVP_PKEY *pkey)
+{
+ char name[80];
+ size_t name_len;
+
+ if (pkey == NULL)
+ return 0;
+
+ if (pkey->keymgmt == NULL
+ || pkey->keydata == NULL) {
+# ifndef OPENSSL_NO_EC
+ /* Might work through the legacy route */
+ const EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
+
+ if (ec == NULL)
+ return 0;
+
+ return EC_KEY_get_conv_form(ec);
+# else
+ return 0;
+# endif
+ }
+
+ if (!EVP_PKEY_get_utf8_string_param(pkey,
+ OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
+ name, sizeof(name), &name_len))
+ return 0;
+
+ if (strcmp(name, "uncompressed") == 0)
+ return POINT_CONVERSION_UNCOMPRESSED;
+
+ if (strcmp(name, "compressed") == 0)
+ return POINT_CONVERSION_COMPRESSED;
+
+ if (strcmp(name, "hybrid") == 0)
+ return POINT_CONVERSION_HYBRID;
+
+ return 0;
+}
+
+int EVP_PKEY_get_field_type(const EVP_PKEY *pkey)
+{
+ char fstr[80];
+ size_t fstrlen;
+
+ if (pkey == NULL)
+ return 0;
+
+ if (pkey->keymgmt == NULL
+ || pkey->keydata == NULL) {
+# ifndef OPENSSL_NO_EC
+ /* Might work through the legacy route */
+ const EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
+ const EC_GROUP *grp;
+
+ if (ec == NULL)
+ return 0;
+ grp = EC_KEY_get0_group(ec);
+ if (grp == NULL)
+ return 0;
+
+ return EC_GROUP_get_field_type(grp);
+# else
+ return 0;
+# endif
+ }
+
+ if (!EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_EC_FIELD_TYPE,
+ fstr, sizeof(fstr), &fstrlen))
+ return 0;
+
+ if (strcmp(fstr, SN_X9_62_prime_field) == 0)
+ return NID_X9_62_prime_field;
+ else if (strcmp(fstr, SN_X9_62_characteristic_two_field))
+ return NID_X9_62_characteristic_two_field;
+
+ return 0;
+}
+#endif
diff --git a/crypto/evp/p_open.c b/crypto/evp/p_open.c
index 1ce87454bdec..8ee8b7a0276b 100644
--- a/crypto/evp/p_open.c
+++ b/crypto/evp/p_open.c
@@ -1,63 +1,63 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "internal/cryptlib.h"
-#ifdef OPENSSL_NO_RSA
-NON_EMPTY_TRANSLATION_UNIT
-#else
-# include <stdio.h>
-# include <openssl/evp.h>
-# include <openssl/objects.h>
-# include <openssl/x509.h>
-# include <openssl/rsa.h>
+#include <stdio.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/x509.h>
+#include <openssl/rsa.h>
int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
const unsigned char *ek, int ekl, const unsigned char *iv,
EVP_PKEY *priv)
{
unsigned char *key = NULL;
- int i, size = 0, ret = 0;
+ size_t keylen = 0;
+ int ret = 0;
+ EVP_PKEY_CTX *pctx = NULL;
if (type) {
EVP_CIPHER_CTX_reset(ctx);
if (!EVP_DecryptInit_ex(ctx, type, NULL, NULL, NULL))
- return 0;
+ goto err;
}
- if (!priv)
+ if (priv == NULL)
return 1;
- if (EVP_PKEY_id(priv) != EVP_PKEY_RSA) {
- EVPerr(EVP_F_EVP_OPENINIT, EVP_R_PUBLIC_KEY_NOT_RSA);
+ if ((pctx = EVP_PKEY_CTX_new(priv, NULL)) == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
goto err;
}
- size = EVP_PKEY_size(priv);
- key = OPENSSL_malloc(size);
- if (key == NULL) {
- /* ERROR */
- EVPerr(EVP_F_EVP_OPENINIT, ERR_R_MALLOC_FAILURE);
+ if (EVP_PKEY_decrypt_init(pctx) <= 0
+ || EVP_PKEY_decrypt(pctx, NULL, &keylen, ek, ekl) <= 0)
goto err;
- }
- i = EVP_PKEY_decrypt_old(key, ek, ekl, priv);
- if ((i <= 0) || !EVP_CIPHER_CTX_set_key_length(ctx, i)) {
- /* ERROR */
+ if ((key = OPENSSL_malloc(keylen)) == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))
+
+ if (EVP_PKEY_decrypt(pctx, key, &keylen, ek, ekl) <= 0)
+ goto err;
+
+ if (EVP_CIPHER_CTX_set_key_length(ctx, keylen) <= 0
+ || !EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))
goto err;
ret = 1;
err:
- OPENSSL_clear_free(key, size);
+ EVP_PKEY_CTX_free(pctx);
+ OPENSSL_clear_free(key, keylen);
return ret;
}
@@ -70,4 +70,3 @@ int EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
i = EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL);
return i;
}
-#endif
diff --git a/crypto/evp/p_seal.c b/crypto/evp/p_seal.c
index e851d7ab8b56..475082d43116 100644
--- a/crypto/evp/p_seal.c
+++ b/crypto/evp/p_seal.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,48 +9,70 @@
#include <stdio.h>
#include "internal/cryptlib.h"
+#include "internal/provider.h"
#include <openssl/rand.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
+#include <openssl/evp.h>
int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
unsigned char **ek, int *ekl, unsigned char *iv,
EVP_PKEY **pubk, int npubk)
{
unsigned char key[EVP_MAX_KEY_LENGTH];
- int i;
+ const OSSL_PROVIDER *prov;
+ OSSL_LIB_CTX *libctx = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ const EVP_CIPHER *cipher;
+ int i, len;
int rv = 0;
- if (type) {
+ if (type != NULL) {
EVP_CIPHER_CTX_reset(ctx);
if (!EVP_EncryptInit_ex(ctx, type, NULL, NULL, NULL))
return 0;
}
+ if ((cipher = EVP_CIPHER_CTX_get0_cipher(ctx)) != NULL
+ && (prov = EVP_CIPHER_get0_provider(cipher)) != NULL)
+ libctx = ossl_provider_libctx(prov);
if ((npubk <= 0) || !pubk)
return 1;
+
if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
return 0;
- if (EVP_CIPHER_CTX_iv_length(ctx)
- && RAND_bytes(iv, EVP_CIPHER_CTX_iv_length(ctx)) <= 0)
+ len = EVP_CIPHER_CTX_get_iv_length(ctx);
+ if (len < 0 || RAND_priv_bytes_ex(libctx, iv, len, 0) <= 0)
+ goto err;
+
+ len = EVP_CIPHER_CTX_get_key_length(ctx);
+ if (len < 0)
goto err;
if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))
goto err;
for (i = 0; i < npubk; i++) {
- ekl[i] =
- EVP_PKEY_encrypt_old(ek[i], key, EVP_CIPHER_CTX_key_length(ctx),
- pubk[i]);
- if (ekl[i] <= 0) {
- rv = -1;
+ size_t keylen = len;
+
+ pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pubk[i], NULL);
+ if (pctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
goto err;
}
+
+ if (EVP_PKEY_encrypt_init(pctx) <= 0
+ || EVP_PKEY_encrypt(pctx, ek[i], &keylen, key, keylen) <= 0)
+ goto err;
+ ekl[i] = (int)keylen;
+ EVP_PKEY_CTX_free(pctx);
}
+ pctx = NULL;
rv = npubk;
err:
+ EVP_PKEY_CTX_free(pctx);
OPENSSL_cleanse(key, sizeof(key));
return rv;
}
diff --git a/crypto/evp/p_sign.c b/crypto/evp/p_sign.c
index 0383294a87c8..8e430f4704b2 100644
--- a/crypto/evp/p_sign.c
+++ b/crypto/evp/p_sign.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -14,8 +14,9 @@
#include <openssl/x509.h>
#include "crypto/evp.h"
-int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
- unsigned int *siglen, EVP_PKEY *pkey)
+int EVP_SignFinal_ex(EVP_MD_CTX *ctx, unsigned char *sigret,
+ unsigned int *siglen, EVP_PKEY *pkey, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
unsigned char m[EVP_MAX_MD_SIZE];
unsigned int m_len = 0;
@@ -30,8 +31,9 @@ int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
} else {
int rv = 0;
EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new();
+
if (tmp_ctx == NULL) {
- EVPerr(EVP_F_EVP_SIGNFINAL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
rv = EVP_MD_CTX_copy_ex(tmp_ctx, ctx);
@@ -42,14 +44,14 @@ int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
return 0;
}
- sltmp = (size_t)EVP_PKEY_size(pkey);
+ sltmp = (size_t)EVP_PKEY_get_size(pkey);
i = 0;
- pkctx = EVP_PKEY_CTX_new(pkey, NULL);
+ pkctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
if (pkctx == NULL)
goto err;
if (EVP_PKEY_sign_init(pkctx) <= 0)
goto err;
- if (EVP_PKEY_CTX_set_signature_md(pkctx, EVP_MD_CTX_md(ctx)) <= 0)
+ if (EVP_PKEY_CTX_set_signature_md(pkctx, EVP_MD_CTX_get0_md(ctx)) <= 0)
goto err;
if (EVP_PKEY_sign(pkctx, sigret, &sltmp, m, m_len) <= 0)
goto err;
@@ -59,3 +61,9 @@ int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
EVP_PKEY_CTX_free(pkctx);
return i;
}
+
+int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
+ unsigned int *siglen, EVP_PKEY *pkey)
+{
+ return EVP_SignFinal_ex(ctx, sigret, siglen, pkey, NULL, NULL);
+}
diff --git a/crypto/evp/p_verify.c b/crypto/evp/p_verify.c
index e27196f7c2e6..e5667afb7cca 100644
--- a/crypto/evp/p_verify.c
+++ b/crypto/evp/p_verify.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -14,8 +14,9 @@
#include <openssl/x509.h>
#include "crypto/evp.h"
-int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
- unsigned int siglen, EVP_PKEY *pkey)
+int EVP_VerifyFinal_ex(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
+ unsigned int siglen, EVP_PKEY *pkey, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
unsigned char m[EVP_MAX_MD_SIZE];
unsigned int m_len = 0;
@@ -28,8 +29,9 @@ int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
} else {
int rv = 0;
EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new();
+
if (tmp_ctx == NULL) {
- EVPerr(EVP_F_EVP_VERIFYFINAL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
rv = EVP_MD_CTX_copy_ex(tmp_ctx, ctx);
@@ -41,15 +43,21 @@ int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
}
i = -1;
- pkctx = EVP_PKEY_CTX_new(pkey, NULL);
+ pkctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
if (pkctx == NULL)
goto err;
if (EVP_PKEY_verify_init(pkctx) <= 0)
goto err;
- if (EVP_PKEY_CTX_set_signature_md(pkctx, EVP_MD_CTX_md(ctx)) <= 0)
+ if (EVP_PKEY_CTX_set_signature_md(pkctx, EVP_MD_CTX_get0_md(ctx)) <= 0)
goto err;
i = EVP_PKEY_verify(pkctx, sigbuf, siglen, m, m_len);
err:
EVP_PKEY_CTX_free(pkctx);
return i;
}
+
+int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
+ unsigned int siglen, EVP_PKEY *pkey)
+{
+ return EVP_VerifyFinal_ex(ctx, sigbuf, siglen, pkey, NULL, NULL);
+}
diff --git a/crypto/evp/pbe_scrypt.c b/crypto/evp/pbe_scrypt.c
index 57da82f3fe4c..78b2d13ec9e1 100644
--- a/crypto/evp/pbe_scrypt.c
+++ b/crypto/evp/pbe_scrypt.c
@@ -1,141 +1,20 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
#include <openssl/evp.h>
#include <openssl/err.h>
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
#include "internal/numbers.h"
#ifndef OPENSSL_NO_SCRYPT
-#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
-static void salsa208_word_specification(uint32_t inout[16])
-{
- int i;
- uint32_t x[16];
- memcpy(x, inout, sizeof(x));
- for (i = 8; i > 0; i -= 2) {
- x[4] ^= R(x[0] + x[12], 7);
- x[8] ^= R(x[4] + x[0], 9);
- x[12] ^= R(x[8] + x[4], 13);
- x[0] ^= R(x[12] + x[8], 18);
- x[9] ^= R(x[5] + x[1], 7);
- x[13] ^= R(x[9] + x[5], 9);
- x[1] ^= R(x[13] + x[9], 13);
- x[5] ^= R(x[1] + x[13], 18);
- x[14] ^= R(x[10] + x[6], 7);
- x[2] ^= R(x[14] + x[10], 9);
- x[6] ^= R(x[2] + x[14], 13);
- x[10] ^= R(x[6] + x[2], 18);
- x[3] ^= R(x[15] + x[11], 7);
- x[7] ^= R(x[3] + x[15], 9);
- x[11] ^= R(x[7] + x[3], 13);
- x[15] ^= R(x[11] + x[7], 18);
- x[1] ^= R(x[0] + x[3], 7);
- x[2] ^= R(x[1] + x[0], 9);
- x[3] ^= R(x[2] + x[1], 13);
- x[0] ^= R(x[3] + x[2], 18);
- x[6] ^= R(x[5] + x[4], 7);
- x[7] ^= R(x[6] + x[5], 9);
- x[4] ^= R(x[7] + x[6], 13);
- x[5] ^= R(x[4] + x[7], 18);
- x[11] ^= R(x[10] + x[9], 7);
- x[8] ^= R(x[11] + x[10], 9);
- x[9] ^= R(x[8] + x[11], 13);
- x[10] ^= R(x[9] + x[8], 18);
- x[12] ^= R(x[15] + x[14], 7);
- x[13] ^= R(x[12] + x[15], 9);
- x[14] ^= R(x[13] + x[12], 13);
- x[15] ^= R(x[14] + x[13], 18);
- }
- for (i = 0; i < 16; ++i)
- inout[i] += x[i];
- OPENSSL_cleanse(x, sizeof(x));
-}
-
-static void scryptBlockMix(uint32_t *B_, uint32_t *B, uint64_t r)
-{
- uint64_t i, j;
- uint32_t X[16], *pB;
-
- memcpy(X, B + (r * 2 - 1) * 16, sizeof(X));
- pB = B;
- for (i = 0; i < r * 2; i++) {
- for (j = 0; j < 16; j++)
- X[j] ^= *pB++;
- salsa208_word_specification(X);
- memcpy(B_ + (i / 2 + (i & 1) * r) * 16, X, sizeof(X));
- }
- OPENSSL_cleanse(X, sizeof(X));
-}
-
-static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N,
- uint32_t *X, uint32_t *T, uint32_t *V)
-{
- unsigned char *pB;
- uint32_t *pV;
- uint64_t i, k;
-
- /* Convert from little endian input */
- for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) {
- *pV = *pB++;
- *pV |= *pB++ << 8;
- *pV |= *pB++ << 16;
- *pV |= (uint32_t)*pB++ << 24;
- }
-
- for (i = 1; i < N; i++, pV += 32 * r)
- scryptBlockMix(pV, pV - 32 * r, r);
-
- scryptBlockMix(X, V + (N - 1) * 32 * r, r);
-
- for (i = 0; i < N; i++) {
- uint32_t j;
- j = X[16 * (2 * r - 1)] % N;
- pV = V + 32 * r * j;
- for (k = 0; k < 32 * r; k++)
- T[k] = X[k] ^ *pV++;
- scryptBlockMix(X, T, r);
- }
- /* Convert output to little endian */
- for (i = 0, pB = B; i < 32 * r; i++) {
- uint32_t xtmp = X[i];
- *pB++ = xtmp & 0xff;
- *pB++ = (xtmp >> 8) & 0xff;
- *pB++ = (xtmp >> 16) & 0xff;
- *pB++ = (xtmp >> 24) & 0xff;
- }
-}
-
-#ifndef SIZE_MAX
-# define SIZE_MAX ((size_t)-1)
-#endif
-
-/*
- * Maximum power of two that will fit in uint64_t: this should work on
- * most (all?) platforms.
- */
-
-#define LOG2_UINT64_MAX (sizeof(uint64_t) * 8 - 1)
-
-/*
- * Maximum value of p * r:
- * p <= ((2^32-1) * hLen) / MFLen =>
- * p <= ((2^32-1) * 32) / (128 * r) =>
- * p * r <= (2^30-1)
- *
- */
-
-#define SCRYPT_PR_MAX ((1 << 30) - 1)
-
/*
* Maximum permitted memory allow this to be overridden with Configuration
* option: e.g. -DSCRYPT_MAX_MEM=0 for maximum possible.
@@ -155,112 +34,66 @@ static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N,
# define SCRYPT_MAX_MEM (1024 * 1024 * 32)
#endif
-int EVP_PBE_scrypt(const char *pass, size_t passlen,
- const unsigned char *salt, size_t saltlen,
- uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
- unsigned char *key, size_t keylen)
+int EVP_PBE_scrypt_ex(const char *pass, size_t passlen,
+ const unsigned char *salt, size_t saltlen,
+ uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
+ unsigned char *key, size_t keylen,
+ OSSL_LIB_CTX *ctx, const char *propq)
{
- int rv = 0;
- unsigned char *B;
- uint32_t *X, *V, *T;
- uint64_t i, Blen, Vlen;
-
- /* Sanity check parameters */
- /* initial check, r,p must be non zero, N >= 2 and a power of 2 */
- if (r == 0 || p == 0 || N < 2 || (N & (N - 1)))
- return 0;
- /* Check p * r < SCRYPT_PR_MAX avoiding overflow */
- if (p > SCRYPT_PR_MAX / r) {
- EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
- return 0;
- }
-
- /*
- * Need to check N: if 2^(128 * r / 8) overflows limit this is
- * automatically satisfied since N <= UINT64_MAX.
- */
-
- if (16 * r <= LOG2_UINT64_MAX) {
- if (N >= (((uint64_t)1) << (16 * r))) {
- EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
- return 0;
- }
- }
-
- /* Memory checks: check total allocated buffer size fits in uint64_t */
-
- /*
- * B size in section 5 step 1.S
- * Note: we know p * 128 * r < UINT64_MAX because we already checked
- * p * r < SCRYPT_PR_MAX
- */
- Blen = p * 128 * r;
- /*
- * Yet we pass it as integer to PKCS5_PBKDF2_HMAC... [This would
- * have to be revised when/if PKCS5_PBKDF2_HMAC accepts size_t.]
- */
- if (Blen > INT_MAX) {
- EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
+ const char *empty = "";
+ int rv = 1;
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx;
+ OSSL_PARAM params[7], *z = params;
+
+ if (r > UINT32_MAX || p > UINT32_MAX) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_PARAMETER_TOO_LARGE);
return 0;
}
- /*
- * Check 32 * r * (N + 2) * sizeof(uint32_t) fits in uint64_t
- * This is combined size V, X and T (section 4)
- */
- i = UINT64_MAX / (32 * sizeof(uint32_t));
- if (N + 2 > i / r) {
- EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
- return 0;
+ /* Maintain existing behaviour. */
+ if (pass == NULL) {
+ pass = empty;
+ passlen = 0;
}
- Vlen = 32 * r * (N + 2) * sizeof(uint32_t);
-
- /* check total allocated size fits in uint64_t */
- if (Blen > UINT64_MAX - Vlen) {
- EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
- return 0;
+ if (salt == NULL) {
+ salt = (const unsigned char *)empty;
+ saltlen = 0;
}
-
if (maxmem == 0)
maxmem = SCRYPT_MAX_MEM;
- /* Check that the maximum memory doesn't exceed a size_t limits */
- if (maxmem > SIZE_MAX)
- maxmem = SIZE_MAX;
-
- if (Blen + Vlen > maxmem) {
- EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
+ /* Use OSSL_LIB_CTX_set0_default() if you need a library context */
+ kdf = EVP_KDF_fetch(ctx, OSSL_KDF_NAME_SCRYPT, propq);
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+ if (kctx == NULL)
return 0;
- }
-
- /* If no key return to indicate parameters are OK */
- if (key == NULL)
- return 1;
-
- B = OPENSSL_malloc((size_t)(Blen + Vlen));
- if (B == NULL) {
- EVPerr(EVP_F_EVP_PBE_SCRYPT, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- X = (uint32_t *)(B + Blen);
- T = X + 32 * r;
- V = T + 32 * r;
- if (PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, 1, EVP_sha256(),
- (int)Blen, B) == 0)
- goto err;
-
- for (i = 0; i < p; i++)
- scryptROMix(B + 128 * r * i, r, N, X, T, V);
- if (PKCS5_PBKDF2_HMAC(pass, passlen, B, (int)Blen, 1, EVP_sha256(),
- keylen, key) == 0)
- goto err;
- rv = 1;
- err:
- if (rv == 0)
- EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_PBKDF2_ERROR);
-
- OPENSSL_clear_free(B, (size_t)(Blen + Vlen));
+ *z++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
+ (unsigned char *)pass,
+ passlen);
+ *z++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ (unsigned char *)salt, saltlen);
+ *z++ = OSSL_PARAM_construct_uint64(OSSL_KDF_PARAM_SCRYPT_N, &N);
+ *z++ = OSSL_PARAM_construct_uint64(OSSL_KDF_PARAM_SCRYPT_R, &r);
+ *z++ = OSSL_PARAM_construct_uint64(OSSL_KDF_PARAM_SCRYPT_P, &p);
+ *z++ = OSSL_PARAM_construct_uint64(OSSL_KDF_PARAM_SCRYPT_MAXMEM, &maxmem);
+ *z = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, key, keylen, params) != 1)
+ rv = 0;
+
+ EVP_KDF_CTX_free(kctx);
return rv;
}
+
+int EVP_PBE_scrypt(const char *pass, size_t passlen,
+ const unsigned char *salt, size_t saltlen,
+ uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
+ unsigned char *key, size_t keylen)
+{
+ return EVP_PBE_scrypt_ex(pass, passlen, salt, saltlen, N, r, p, maxmem,
+ key, keylen, NULL, NULL);
+}
+
#endif
diff --git a/crypto/evp/pmeth_check.c b/crypto/evp/pmeth_check.c
new file mode 100644
index 000000000000..7f3a2e3a1c80
--- /dev/null
+++ b/crypto/evp/pmeth_check.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "internal/cryptlib.h"
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include "crypto/bn.h"
+#ifndef FIPS_MODULE
+# include "crypto/asn1.h"
+#endif
+#include "crypto/evp.h"
+#include "evp_local.h"
+
+/*
+ * Returns:
+ * 1 True
+ * 0 False
+ * -1 Unsupported (use legacy path)
+ */
+static int try_provided_check(EVP_PKEY_CTX *ctx, int selection, int checktype)
+{
+ EVP_KEYMGMT *keymgmt;
+ void *keydata;
+
+ if (evp_pkey_ctx_is_legacy(ctx))
+ return -1;
+
+ keymgmt = ctx->keymgmt;
+ keydata = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
+ &keymgmt, ctx->propquery);
+ if (keydata == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+
+ return evp_keymgmt_validate(keymgmt, keydata, selection, checktype);
+}
+
+static int evp_pkey_public_check_combined(EVP_PKEY_CTX *ctx, int checktype)
+{
+ EVP_PKEY *pkey = ctx->pkey;
+ int ok;
+
+ if (pkey == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET);
+ return 0;
+ }
+
+ if ((ok = try_provided_check(ctx, OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
+ checktype)) != -1)
+ return ok;
+
+ if (pkey->type == EVP_PKEY_NONE)
+ goto not_supported;
+
+#ifndef FIPS_MODULE
+ /* legacy */
+ /* call customized public key check function first */
+ if (ctx->pmeth->public_check != NULL)
+ return ctx->pmeth->public_check(pkey);
+
+ /* use default public key check function in ameth */
+ if (pkey->ameth == NULL || pkey->ameth->pkey_public_check == NULL)
+ goto not_supported;
+
+ return pkey->ameth->pkey_public_check(pkey);
+#endif
+ not_supported:
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+}
+
+int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx)
+{
+ return evp_pkey_public_check_combined(ctx, OSSL_KEYMGMT_VALIDATE_FULL_CHECK);
+}
+
+int EVP_PKEY_public_check_quick(EVP_PKEY_CTX *ctx)
+{
+ return evp_pkey_public_check_combined(ctx, OSSL_KEYMGMT_VALIDATE_QUICK_CHECK);
+}
+
+static int evp_pkey_param_check_combined(EVP_PKEY_CTX *ctx, int checktype)
+{
+ EVP_PKEY *pkey = ctx->pkey;
+ int ok;
+
+ if (pkey == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET);
+ return 0;
+ }
+
+ if ((ok = try_provided_check(ctx,
+ OSSL_KEYMGMT_SELECT_ALL_PARAMETERS,
+ checktype)) != -1)
+ return ok;
+
+ if (pkey->type == EVP_PKEY_NONE)
+ goto not_supported;
+
+#ifndef FIPS_MODULE
+ /* legacy */
+ /* call customized param check function first */
+ if (ctx->pmeth->param_check != NULL)
+ return ctx->pmeth->param_check(pkey);
+
+ /* use default param check function in ameth */
+ if (pkey->ameth == NULL || pkey->ameth->pkey_param_check == NULL)
+ goto not_supported;
+
+ return pkey->ameth->pkey_param_check(pkey);
+#endif
+ not_supported:
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+}
+
+int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx)
+{
+ return evp_pkey_param_check_combined(ctx, OSSL_KEYMGMT_VALIDATE_FULL_CHECK);
+}
+
+int EVP_PKEY_param_check_quick(EVP_PKEY_CTX *ctx)
+{
+ return evp_pkey_param_check_combined(ctx, OSSL_KEYMGMT_VALIDATE_QUICK_CHECK);
+}
+
+int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx)
+{
+ EVP_PKEY *pkey = ctx->pkey;
+ int ok;
+
+ if (pkey == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET);
+ return 0;
+ }
+
+ if ((ok = try_provided_check(ctx, OSSL_KEYMGMT_SELECT_PRIVATE_KEY,
+ OSSL_KEYMGMT_VALIDATE_FULL_CHECK)) != -1)
+ return ok;
+
+ /* not supported for legacy keys */
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+}
+
+int EVP_PKEY_check(EVP_PKEY_CTX *ctx)
+{
+ return EVP_PKEY_pairwise_check(ctx);
+}
+
+int EVP_PKEY_pairwise_check(EVP_PKEY_CTX *ctx)
+{
+ EVP_PKEY *pkey = ctx->pkey;
+ int ok;
+
+ if (pkey == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET);
+ return 0;
+ }
+
+ if ((ok = try_provided_check(ctx, OSSL_KEYMGMT_SELECT_KEYPAIR,
+ OSSL_KEYMGMT_VALIDATE_FULL_CHECK)) != -1)
+ return ok;
+
+ if (pkey->type == EVP_PKEY_NONE)
+ goto not_supported;
+
+#ifndef FIPS_MODULE
+ /* legacy */
+ /* call customized check function first */
+ if (ctx->pmeth->check != NULL)
+ return ctx->pmeth->check(pkey);
+
+ /* use default check function in ameth */
+ if (pkey->ameth == NULL || pkey->ameth->pkey_check == NULL)
+ goto not_supported;
+
+ return pkey->ameth->pkey_check(pkey);
+#endif
+ not_supported:
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+}
+
diff --git a/crypto/evp/pmeth_fn.c b/crypto/evp/pmeth_fn.c
deleted file mode 100644
index 02f4093461d8..000000000000
--- a/crypto/evp/pmeth_fn.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "internal/cryptlib.h"
-#include <openssl/objects.h>
-#include <openssl/evp.h>
-#include "crypto/evp.h"
-
-#define M_check_autoarg(ctx, arg, arglen, err) \
- if (ctx->pmeth->flags & EVP_PKEY_FLAG_AUTOARGLEN) { \
- size_t pksize = (size_t)EVP_PKEY_size(ctx->pkey); \
- \
- if (pksize == 0) { \
- EVPerr(err, EVP_R_INVALID_KEY); /*ckerr_ignore*/ \
- return 0; \
- } \
- if (!arg) { \
- *arglen = pksize; \
- return 1; \
- } \
- if (*arglen < pksize) { \
- EVPerr(err, EVP_R_BUFFER_TOO_SMALL); /*ckerr_ignore*/ \
- return 0; \
- } \
- }
-
-int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx)
-{
- int ret;
- if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) {
- EVPerr(EVP_F_EVP_PKEY_SIGN_INIT,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
- ctx->operation = EVP_PKEY_OP_SIGN;
- if (!ctx->pmeth->sign_init)
- return 1;
- ret = ctx->pmeth->sign_init(ctx);
- if (ret <= 0)
- ctx->operation = EVP_PKEY_OP_UNDEFINED;
- return ret;
-}
-
-int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
- unsigned char *sig, size_t *siglen,
- const unsigned char *tbs, size_t tbslen)
-{
- if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) {
- EVPerr(EVP_F_EVP_PKEY_SIGN,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
- if (ctx->operation != EVP_PKEY_OP_SIGN) {
- EVPerr(EVP_F_EVP_PKEY_SIGN, EVP_R_OPERATON_NOT_INITIALIZED);
- return -1;
- }
- M_check_autoarg(ctx, sig, siglen, EVP_F_EVP_PKEY_SIGN)
- return ctx->pmeth->sign(ctx, sig, siglen, tbs, tbslen);
-}
-
-int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx)
-{
- int ret;
- if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) {
- EVPerr(EVP_F_EVP_PKEY_VERIFY_INIT,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
- ctx->operation = EVP_PKEY_OP_VERIFY;
- if (!ctx->pmeth->verify_init)
- return 1;
- ret = ctx->pmeth->verify_init(ctx);
- if (ret <= 0)
- ctx->operation = EVP_PKEY_OP_UNDEFINED;
- return ret;
-}
-
-int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
- const unsigned char *sig, size_t siglen,
- const unsigned char *tbs, size_t tbslen)
-{
- if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) {
- EVPerr(EVP_F_EVP_PKEY_VERIFY,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
- if (ctx->operation != EVP_PKEY_OP_VERIFY) {
- EVPerr(EVP_F_EVP_PKEY_VERIFY, EVP_R_OPERATON_NOT_INITIALIZED);
- return -1;
- }
- return ctx->pmeth->verify(ctx, sig, siglen, tbs, tbslen);
-}
-
-int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx)
-{
- int ret;
- if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) {
- EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
- ctx->operation = EVP_PKEY_OP_VERIFYRECOVER;
- if (!ctx->pmeth->verify_recover_init)
- return 1;
- ret = ctx->pmeth->verify_recover_init(ctx);
- if (ret <= 0)
- ctx->operation = EVP_PKEY_OP_UNDEFINED;
- return ret;
-}
-
-int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx,
- unsigned char *rout, size_t *routlen,
- const unsigned char *sig, size_t siglen)
-{
- if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) {
- EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
- if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) {
- EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER, EVP_R_OPERATON_NOT_INITIALIZED);
- return -1;
- }
- M_check_autoarg(ctx, rout, routlen, EVP_F_EVP_PKEY_VERIFY_RECOVER)
- return ctx->pmeth->verify_recover(ctx, rout, routlen, sig, siglen);
-}
-
-int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx)
-{
- int ret;
- if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) {
- EVPerr(EVP_F_EVP_PKEY_ENCRYPT_INIT,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
- ctx->operation = EVP_PKEY_OP_ENCRYPT;
- if (!ctx->pmeth->encrypt_init)
- return 1;
- ret = ctx->pmeth->encrypt_init(ctx);
- if (ret <= 0)
- ctx->operation = EVP_PKEY_OP_UNDEFINED;
- return ret;
-}
-
-int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
- unsigned char *out, size_t *outlen,
- const unsigned char *in, size_t inlen)
-{
- if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) {
- EVPerr(EVP_F_EVP_PKEY_ENCRYPT,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
- if (ctx->operation != EVP_PKEY_OP_ENCRYPT) {
- EVPerr(EVP_F_EVP_PKEY_ENCRYPT, EVP_R_OPERATON_NOT_INITIALIZED);
- return -1;
- }
- M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_ENCRYPT)
- return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen);
-}
-
-int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx)
-{
- int ret;
- if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) {
- EVPerr(EVP_F_EVP_PKEY_DECRYPT_INIT,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
- ctx->operation = EVP_PKEY_OP_DECRYPT;
- if (!ctx->pmeth->decrypt_init)
- return 1;
- ret = ctx->pmeth->decrypt_init(ctx);
- if (ret <= 0)
- ctx->operation = EVP_PKEY_OP_UNDEFINED;
- return ret;
-}
-
-int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
- unsigned char *out, size_t *outlen,
- const unsigned char *in, size_t inlen)
-{
- if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) {
- EVPerr(EVP_F_EVP_PKEY_DECRYPT,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
- if (ctx->operation != EVP_PKEY_OP_DECRYPT) {
- EVPerr(EVP_F_EVP_PKEY_DECRYPT, EVP_R_OPERATON_NOT_INITIALIZED);
- return -1;
- }
- M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_DECRYPT)
- return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen);
-}
-
-int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
-{
- int ret;
- if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) {
- EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
- ctx->operation = EVP_PKEY_OP_DERIVE;
- if (!ctx->pmeth->derive_init)
- return 1;
- ret = ctx->pmeth->derive_init(ctx);
- if (ret <= 0)
- ctx->operation = EVP_PKEY_OP_UNDEFINED;
- return ret;
-}
-
-int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
-{
- int ret;
- if (!ctx || !ctx->pmeth
- || !(ctx->pmeth->derive || ctx->pmeth->encrypt || ctx->pmeth->decrypt)
- || !ctx->pmeth->ctrl) {
- EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
- if (ctx->operation != EVP_PKEY_OP_DERIVE
- && ctx->operation != EVP_PKEY_OP_ENCRYPT
- && ctx->operation != EVP_PKEY_OP_DECRYPT) {
- EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
- EVP_R_OPERATON_NOT_INITIALIZED);
- return -1;
- }
-
- ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer);
-
- if (ret <= 0)
- return ret;
-
- if (ret == 2)
- return 1;
-
- if (!ctx->pkey) {
- EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_NO_KEY_SET);
- return -1;
- }
-
- if (ctx->pkey->type != peer->type) {
- EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_KEY_TYPES);
- return -1;
- }
-
- /*
- * For clarity. The error is if parameters in peer are
- * present (!missing) but don't match. EVP_PKEY_cmp_parameters may return
- * 1 (match), 0 (don't match) and -2 (comparison is not defined). -1
- * (different key types) is impossible here because it is checked earlier.
- * -2 is OK for us here, as well as 1, so we can check for 0 only.
- */
- if (!EVP_PKEY_missing_parameters(peer) &&
- !EVP_PKEY_cmp_parameters(ctx->pkey, peer)) {
- EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_PARAMETERS);
- return -1;
- }
-
- EVP_PKEY_free(ctx->peerkey);
- ctx->peerkey = peer;
-
- ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer);
-
- if (ret <= 0) {
- ctx->peerkey = NULL;
- return ret;
- }
-
- EVP_PKEY_up_ref(peer);
- return 1;
-}
-
-int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen)
-{
- if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) {
- EVPerr(EVP_F_EVP_PKEY_DERIVE,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
- if (ctx->operation != EVP_PKEY_OP_DERIVE) {
- EVPerr(EVP_F_EVP_PKEY_DERIVE, EVP_R_OPERATON_NOT_INITIALIZED);
- return -1;
- }
- M_check_autoarg(ctx, key, pkeylen, EVP_F_EVP_PKEY_DERIVE)
- return ctx->pmeth->derive(ctx, key, pkeylen);
-}
diff --git a/crypto/evp/pmeth_gn.c b/crypto/evp/pmeth_gn.c
index 3ad6d5c7c7a0..8e4940ed5956 100644
--- a/crypto/evp/pmeth_gn.c
+++ b/crypto/evp/pmeth_gn.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,108 +9,269 @@
#include <stdio.h>
#include <stdlib.h>
+#include <openssl/core.h>
+#include <openssl/core_names.h>
#include "internal/cryptlib.h"
+#include "internal/core.h"
#include <openssl/objects.h>
#include <openssl/evp.h>
#include "crypto/bn.h"
-#include "crypto/asn1.h"
+#ifndef FIPS_MODULE
+# include "crypto/asn1.h"
+#endif
#include "crypto/evp.h"
+#include "evp_local.h"
-int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx)
+static int gen_init(EVP_PKEY_CTX *ctx, int operation)
{
- int ret;
- if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) {
- EVPerr(EVP_F_EVP_PKEY_PARAMGEN_INIT,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
+ int ret = 0;
+
+ if (ctx == NULL)
+ goto not_supported;
+
+ evp_pkey_ctx_free_old_ops(ctx);
+ ctx->operation = operation;
+
+ if (ctx->keymgmt == NULL || ctx->keymgmt->gen_init == NULL)
+ goto legacy;
+
+ switch (operation) {
+ case EVP_PKEY_OP_PARAMGEN:
+ ctx->op.keymgmt.genctx =
+ evp_keymgmt_gen_init(ctx->keymgmt,
+ OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, NULL);
+ break;
+ case EVP_PKEY_OP_KEYGEN:
+ ctx->op.keymgmt.genctx =
+ evp_keymgmt_gen_init(ctx->keymgmt, OSSL_KEYMGMT_SELECT_KEYPAIR,
+ NULL);
+ break;
+ }
+
+ if (ctx->op.keymgmt.genctx == NULL)
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ else
+ ret = 1;
+ goto end;
+
+ legacy:
+#ifdef FIPS_MODULE
+ goto not_supported;
+#else
+ if (ctx->pmeth == NULL
+ || (operation == EVP_PKEY_OP_PARAMGEN
+ && ctx->pmeth->paramgen == NULL)
+ || (operation == EVP_PKEY_OP_KEYGEN
+ && ctx->pmeth->keygen == NULL))
+ goto not_supported;
+
+ ret = 1;
+ switch (operation) {
+ case EVP_PKEY_OP_PARAMGEN:
+ if (ctx->pmeth->paramgen_init != NULL)
+ ret = ctx->pmeth->paramgen_init(ctx);
+ break;
+ case EVP_PKEY_OP_KEYGEN:
+ if (ctx->pmeth->keygen_init != NULL)
+ ret = ctx->pmeth->keygen_init(ctx);
+ break;
}
- ctx->operation = EVP_PKEY_OP_PARAMGEN;
- if (!ctx->pmeth->paramgen_init)
- return 1;
- ret = ctx->pmeth->paramgen_init(ctx);
- if (ret <= 0)
+#endif
+
+ end:
+ if (ret <= 0 && ctx != NULL) {
+ evp_pkey_ctx_free_old_ops(ctx);
ctx->operation = EVP_PKEY_OP_UNDEFINED;
+ }
return ret;
+
+ not_supported:
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ ret = -2;
+ goto end;
}
-int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
+int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx)
{
- int ret;
- if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) {
- EVPerr(EVP_F_EVP_PKEY_PARAMGEN,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
+ return gen_init(ctx, EVP_PKEY_OP_PARAMGEN);
+}
- if (ctx->operation != EVP_PKEY_OP_PARAMGEN) {
- EVPerr(EVP_F_EVP_PKEY_PARAMGEN, EVP_R_OPERATON_NOT_INITIALIZED);
- return -1;
- }
+int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx)
+{
+ return gen_init(ctx, EVP_PKEY_OP_KEYGEN);
+}
+
+static int ossl_callback_to_pkey_gencb(const OSSL_PARAM params[], void *arg)
+{
+ EVP_PKEY_CTX *ctx = arg;
+ const OSSL_PARAM *param = NULL;
+ int p = -1, n = -1;
+
+ if (ctx->pkey_gencb == NULL)
+ return 1; /* No callback? That's fine */
+
+ if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_POTENTIAL))
+ == NULL
+ || !OSSL_PARAM_get_int(param, &p))
+ return 0;
+ if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_ITERATION))
+ == NULL
+ || !OSSL_PARAM_get_int(param, &n))
+ return 0;
+
+ ctx->keygen_info[0] = p;
+ ctx->keygen_info[1] = n;
+
+ return ctx->pkey_gencb(ctx);
+}
+
+int EVP_PKEY_generate(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
+{
+ int ret = 0;
+ EVP_PKEY *allocated_pkey = NULL;
+ /* Legacy compatible keygen callback info, only used with provider impls */
+ int gentmp[2];
if (ppkey == NULL)
return -1;
+ if (ctx == NULL)
+ goto not_supported;
+
+ if ((ctx->operation & EVP_PKEY_OP_TYPE_GEN) == 0)
+ goto not_initialized;
+
if (*ppkey == NULL)
- *ppkey = EVP_PKEY_new();
+ *ppkey = allocated_pkey = EVP_PKEY_new();
if (*ppkey == NULL) {
- EVPerr(EVP_F_EVP_PKEY_PARAMGEN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return -1;
}
- ret = ctx->pmeth->paramgen(ctx, *ppkey);
+ if (ctx->op.keymgmt.genctx == NULL)
+ goto legacy;
+
+ /*
+ * Asssigning gentmp to ctx->keygen_info is something our legacy
+ * implementations do. Because the provider implementations aren't
+ * allowed to reach into our EVP_PKEY_CTX, we need to provide similar
+ * space for backward compatibility. It's ok that we attach a local
+ * variable, as it should only be useful in the calls down from here.
+ * This is cleared as soon as it isn't useful any more, i.e. directly
+ * after the evp_keymgmt_util_gen() call.
+ */
+ ctx->keygen_info = gentmp;
+ ctx->keygen_info_count = 2;
+
+ ret = 1;
+ if (ctx->pkey != NULL) {
+ EVP_KEYMGMT *tmp_keymgmt = ctx->keymgmt;
+ void *keydata =
+ evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
+ &tmp_keymgmt, ctx->propquery);
+
+ if (tmp_keymgmt == NULL)
+ goto not_supported;
+ /*
+ * It's ok if keydata is NULL here. The backend is expected to deal
+ * with that as it sees fit.
+ */
+ ret = evp_keymgmt_gen_set_template(ctx->keymgmt,
+ ctx->op.keymgmt.genctx, keydata);
+ }
+
+ /*
+ * the returned value from evp_keymgmt_util_gen() is cached in *ppkey,
+ * so we do not need to save it, just check it.
+ */
+ ret = ret
+ && (evp_keymgmt_util_gen(*ppkey, ctx->keymgmt, ctx->op.keymgmt.genctx,
+ ossl_callback_to_pkey_gencb, ctx)
+ != NULL);
+
+ ctx->keygen_info = NULL;
+
+#ifndef FIPS_MODULE
+ /* In case |*ppkey| was originally a legacy key */
+ if (ret)
+ evp_pkey_free_legacy(*ppkey);
+#endif
+
+ /*
+ * Because we still have legacy keys
+ */
+ (*ppkey)->type = ctx->legacy_keytype;
+
+ goto end;
+
+ legacy:
+#ifdef FIPS_MODULE
+ goto not_supported;
+#else
+ /*
+ * If we get here then we're using legacy paramgen/keygen. In that case
+ * the pkey in ctx (if there is one) had better not be provided (because the
+ * legacy methods may not know how to handle it). However we can only get
+ * here if ctx->op.keymgmt.genctx == NULL, but that should never be the case
+ * if ctx->pkey is provided because we don't allow this when we initialise
+ * the ctx.
+ */
+ if (ctx->pkey != NULL && !ossl_assert(!evp_pkey_is_provided(ctx->pkey)))
+ goto not_accessible;
+
+ switch (ctx->operation) {
+ case EVP_PKEY_OP_PARAMGEN:
+ ret = ctx->pmeth->paramgen(ctx, *ppkey);
+ break;
+ case EVP_PKEY_OP_KEYGEN:
+ ret = ctx->pmeth->keygen(ctx, *ppkey);
+ break;
+ default:
+ goto not_supported;
+ }
+#endif
+
+ end:
if (ret <= 0) {
- EVP_PKEY_free(*ppkey);
- *ppkey = NULL;
+ if (allocated_pkey != NULL)
+ *ppkey = NULL;
+ EVP_PKEY_free(allocated_pkey);
}
return ret;
+
+ not_supported:
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ ret = -2;
+ goto end;
+ not_initialized:
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
+ ret = -1;
+ goto end;
+#ifndef FIPS_MODULE
+ not_accessible:
+ ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS);
+ ret = -1;
+ goto end;
+#endif
}
-int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx)
+int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
{
- int ret;
- if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) {
- EVPerr(EVP_F_EVP_PKEY_KEYGEN_INIT,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
+ if (ctx->operation != EVP_PKEY_OP_PARAMGEN) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
+ return -1;
}
- ctx->operation = EVP_PKEY_OP_KEYGEN;
- if (!ctx->pmeth->keygen_init)
- return 1;
- ret = ctx->pmeth->keygen_init(ctx);
- if (ret <= 0)
- ctx->operation = EVP_PKEY_OP_UNDEFINED;
- return ret;
+ return EVP_PKEY_generate(ctx, ppkey);
}
int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
{
- int ret;
-
- if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) {
- EVPerr(EVP_F_EVP_PKEY_KEYGEN,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
if (ctx->operation != EVP_PKEY_OP_KEYGEN) {
- EVPerr(EVP_F_EVP_PKEY_KEYGEN, EVP_R_OPERATON_NOT_INITIALIZED);
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
return -1;
}
-
- if (ppkey == NULL)
- return -1;
-
- if (*ppkey == NULL)
- *ppkey = EVP_PKEY_new();
- if (*ppkey == NULL)
- return -1;
-
- ret = ctx->pmeth->keygen(ctx, *ppkey);
- if (ret <= 0) {
- EVP_PKEY_free(*ppkey);
- *ppkey = NULL;
- }
- return ret;
+ return EVP_PKEY_generate(ctx, ppkey);
}
void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb)
@@ -150,6 +311,8 @@ int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx)
return ctx->keygen_info[idx];
}
+#ifndef FIPS_MODULE
+
EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
const unsigned char *key, int keylen)
{
@@ -169,71 +332,130 @@ EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
return mac_key;
}
-int EVP_PKEY_check(EVP_PKEY_CTX *ctx)
+#endif /* FIPS_MODULE */
+
+/*- All methods below can also be used in FIPS_MODULE */
+
+static int fromdata_init(EVP_PKEY_CTX *ctx, int operation)
{
- EVP_PKEY *pkey = ctx->pkey;
+ if (ctx == NULL || ctx->keytype == NULL)
+ goto not_supported;
- if (pkey == NULL) {
- EVPerr(EVP_F_EVP_PKEY_CHECK, EVP_R_NO_KEY_SET);
- return 0;
- }
+ evp_pkey_ctx_free_old_ops(ctx);
+ if (ctx->keymgmt == NULL)
+ goto not_supported;
- /* call customized check function first */
- if (ctx->pmeth->check != NULL)
- return ctx->pmeth->check(pkey);
+ ctx->operation = operation;
+ return 1;
- /* use default check function in ameth */
- if (pkey->ameth == NULL || pkey->ameth->pkey_check == NULL) {
- EVPerr(EVP_F_EVP_PKEY_CHECK,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
+ not_supported:
+ if (ctx != NULL)
+ ctx->operation = EVP_PKEY_OP_UNDEFINED;
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+}
- return pkey->ameth->pkey_check(pkey);
+int EVP_PKEY_fromdata_init(EVP_PKEY_CTX *ctx)
+{
+ return fromdata_init(ctx, EVP_PKEY_OP_FROMDATA);
}
-int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx)
+int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, int selection,
+ OSSL_PARAM params[])
{
- EVP_PKEY *pkey = ctx->pkey;
+ void *keydata = NULL;
+ EVP_PKEY *allocated_pkey = NULL;
- if (pkey == NULL) {
- EVPerr(EVP_F_EVP_PKEY_PUBLIC_CHECK, EVP_R_NO_KEY_SET);
- return 0;
+ if (ctx == NULL || (ctx->operation & EVP_PKEY_OP_FROMDATA) == 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
}
- /* call customized public key check function first */
- if (ctx->pmeth->public_check != NULL)
- return ctx->pmeth->public_check(pkey);
+ if (ppkey == NULL)
+ return -1;
- /* use default public key check function in ameth */
- if (pkey->ameth == NULL || pkey->ameth->pkey_public_check == NULL) {
- EVPerr(EVP_F_EVP_PKEY_PUBLIC_CHECK,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
+ if (*ppkey == NULL)
+ allocated_pkey = *ppkey = EVP_PKEY_new();
+
+ if (*ppkey == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return -1;
}
- return pkey->ameth->pkey_public_check(pkey);
+ keydata = evp_keymgmt_util_fromdata(*ppkey, ctx->keymgmt, selection, params);
+ if (keydata == NULL) {
+ if (allocated_pkey != NULL) {
+ *ppkey = NULL;
+ EVP_PKEY_free(allocated_pkey);
+ }
+ return 0;
+ }
+ /* keydata is cached in *ppkey, so we need not bother with it further */
+ return 1;
}
-int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx)
+const OSSL_PARAM *EVP_PKEY_fromdata_settable(EVP_PKEY_CTX *ctx, int selection)
{
- EVP_PKEY *pkey = ctx->pkey;
+ /* We call fromdata_init to get ctx->keymgmt populated */
+ if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED) == 1)
+ return evp_keymgmt_import_types(ctx->keymgmt, selection);
+ return NULL;
+}
- if (pkey == NULL) {
- EVPerr(EVP_F_EVP_PKEY_PARAM_CHECK, EVP_R_NO_KEY_SET);
+static OSSL_CALLBACK ossl_pkey_todata_cb;
+
+static int ossl_pkey_todata_cb(const OSSL_PARAM params[], void *arg)
+{
+ OSSL_PARAM **ret = arg;
+
+ *ret = OSSL_PARAM_dup(params);
+ return 1;
+}
+
+int EVP_PKEY_todata(const EVP_PKEY *pkey, int selection, OSSL_PARAM **params)
+{
+ if (params == NULL)
return 0;
- }
+ return EVP_PKEY_export(pkey, selection, ossl_pkey_todata_cb, params);
+}
- /* call customized param check function first */
- if (ctx->pmeth->param_check != NULL)
- return ctx->pmeth->param_check(pkey);
+#ifndef FIPS_MODULE
+struct fake_import_data_st {
+ OSSL_CALLBACK *export_cb;
+ void *export_cbarg;
+};
- /* use default param check function in ameth */
- if (pkey->ameth == NULL || pkey->ameth->pkey_param_check == NULL) {
- EVPerr(EVP_F_EVP_PKEY_PARAM_CHECK,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- return -2;
- }
+static OSSL_FUNC_keymgmt_import_fn pkey_fake_import;
+static int pkey_fake_import(void *fake_keydata, int ignored_selection,
+ const OSSL_PARAM params[])
+{
+ struct fake_import_data_st *data = fake_keydata;
+
+ return data->export_cb(params, data->export_cbarg);
+}
+#endif
- return pkey->ameth->pkey_param_check(pkey);
+int EVP_PKEY_export(const EVP_PKEY *pkey, int selection,
+ OSSL_CALLBACK *export_cb, void *export_cbarg)
+{
+ if (pkey == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+#ifndef FIPS_MODULE
+ if (evp_pkey_is_legacy(pkey)) {
+ struct fake_import_data_st data;
+
+ data.export_cb = export_cb;
+ data.export_cbarg = export_cbarg;
+
+ /*
+ * We don't need to care about libctx or propq here, as we're only
+ * interested in the resulting OSSL_PARAM array.
+ */
+ return pkey->ameth->export_to(pkey, &data, pkey_fake_import,
+ NULL, NULL);
+ }
+#endif
+ return evp_keymgmt_util_export(pkey, selection, export_cb, export_cbarg);
}
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index 603ccd835219..da367ed05fbe 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -1,76 +1,89 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * Low level key APIs (DH etc) are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <stdlib.h>
-#include "internal/cryptlib.h"
-#include <openssl/engine.h>
+#ifndef FIPS_MODULE
+# include <openssl/engine.h>
+#endif
#include <openssl/evp.h>
-#include <openssl/x509v3.h>
-#include "crypto/asn1.h"
+#include <openssl/core_names.h>
+#include <openssl/dh.h>
+#include <openssl/rsa.h>
+#include <openssl/kdf.h>
+#include "internal/cryptlib.h"
+#ifndef FIPS_MODULE
+# include "crypto/asn1.h"
+#endif
#include "crypto/evp.h"
+#include "crypto/dh.h"
+#include "crypto/ec.h"
+#include "internal/ffc.h"
#include "internal/numbers.h"
+#include "internal/provider.h"
+#include "evp_local.h"
+
+#ifndef FIPS_MODULE
+static int evp_pkey_ctx_store_cached_data(EVP_PKEY_CTX *ctx,
+ int keytype, int optype,
+ int cmd, const char *name,
+ const void *data, size_t data_len);
+static void evp_pkey_ctx_free_cached_data(EVP_PKEY_CTX *ctx,
+ int cmd, const char *name);
+static void evp_pkey_ctx_free_all_cached_data(EVP_PKEY_CTX *ctx);
+
+typedef const EVP_PKEY_METHOD *(*pmeth_fn)(void);
typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
static STACK_OF(EVP_PKEY_METHOD) *app_pkey_methods = NULL;
/* This array needs to be in order of NIDs */
-static const EVP_PKEY_METHOD *standard_methods[] = {
-#ifndef OPENSSL_NO_RSA
- &rsa_pkey_meth,
-#endif
-#ifndef OPENSSL_NO_DH
- &dh_pkey_meth,
-#endif
-#ifndef OPENSSL_NO_DSA
- &dsa_pkey_meth,
-#endif
-#ifndef OPENSSL_NO_EC
- &ec_pkey_meth,
-#endif
- &hmac_pkey_meth,
-#ifndef OPENSSL_NO_CMAC
- &cmac_pkey_meth,
-#endif
-#ifndef OPENSSL_NO_RSA
- &rsa_pss_pkey_meth,
-#endif
-#ifndef OPENSSL_NO_DH
- &dhx_pkey_meth,
-#endif
-#ifndef OPENSSL_NO_SCRYPT
- &scrypt_pkey_meth,
-#endif
- &tls1_prf_pkey_meth,
-#ifndef OPENSSL_NO_EC
- &ecx25519_pkey_meth,
- &ecx448_pkey_meth,
-#endif
- &hkdf_pkey_meth,
-#ifndef OPENSSL_NO_POLY1305
- &poly1305_pkey_meth,
-#endif
-#ifndef OPENSSL_NO_SIPHASH
- &siphash_pkey_meth,
-#endif
-#ifndef OPENSSL_NO_EC
- &ed25519_pkey_meth,
- &ed448_pkey_meth,
-#endif
-#ifndef OPENSSL_NO_SM2
- &sm2_pkey_meth,
-#endif
+static pmeth_fn standard_methods[] = {
+ ossl_rsa_pkey_method,
+# ifndef OPENSSL_NO_DH
+ ossl_dh_pkey_method,
+# endif
+# ifndef OPENSSL_NO_DSA
+ ossl_dsa_pkey_method,
+# endif
+# ifndef OPENSSL_NO_EC
+ ossl_ec_pkey_method,
+# endif
+ ossl_rsa_pss_pkey_method,
+# ifndef OPENSSL_NO_DH
+ ossl_dhx_pkey_method,
+# endif
+# ifndef OPENSSL_NO_EC
+ ossl_ecx25519_pkey_method,
+ ossl_ecx448_pkey_method,
+# endif
+# ifndef OPENSSL_NO_EC
+ ossl_ed25519_pkey_method,
+ ossl_ed448_pkey_method,
+# endif
};
-DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *,
- pmeth);
+DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, pmeth_fn, pmeth_func);
+
+static int pmeth_func_cmp(const EVP_PKEY_METHOD *const *a, pmeth_fn const *b)
+{
+ return ((*a)->pkey_id - ((**b)())->pkey_id);
+}
+
+IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, pmeth_fn, pmeth_func);
static int pmeth_cmp(const EVP_PKEY_METHOD *const *a,
const EVP_PKEY_METHOD *const *b)
@@ -78,45 +91,154 @@ static int pmeth_cmp(const EVP_PKEY_METHOD *const *a,
return ((*a)->pkey_id - (*b)->pkey_id);
}
-IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *,
- pmeth);
-
-const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type)
+static const EVP_PKEY_METHOD *evp_pkey_meth_find_added_by_application(int type)
{
- EVP_PKEY_METHOD tmp;
- const EVP_PKEY_METHOD *t = &tmp, **ret;
- tmp.pkey_id = type;
- if (app_pkey_methods) {
+ if (app_pkey_methods != NULL) {
int idx;
+ EVP_PKEY_METHOD tmp;
+
+ tmp.pkey_id = type;
idx = sk_EVP_PKEY_METHOD_find(app_pkey_methods, &tmp);
if (idx >= 0)
return sk_EVP_PKEY_METHOD_value(app_pkey_methods, idx);
}
- ret = OBJ_bsearch_pmeth(&t, standard_methods,
- sizeof(standard_methods) /
- sizeof(EVP_PKEY_METHOD *));
- if (!ret || !*ret)
+ return NULL;
+}
+
+const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type)
+{
+ pmeth_fn *ret;
+ EVP_PKEY_METHOD tmp;
+ const EVP_PKEY_METHOD *t;
+
+ if ((t = evp_pkey_meth_find_added_by_application(type)) != NULL)
+ return t;
+
+ tmp.pkey_id = type;
+ t = &tmp;
+ ret = OBJ_bsearch_pmeth_func(&t, standard_methods,
+ OSSL_NELEM(standard_methods));
+ if (ret == NULL || *ret == NULL)
return NULL;
- return *ret;
+ return (**ret)();
+}
+
+EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags)
+{
+ EVP_PKEY_METHOD *pmeth;
+
+ pmeth = OPENSSL_zalloc(sizeof(*pmeth));
+ if (pmeth == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ pmeth->pkey_id = id;
+ pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC;
+ return pmeth;
+}
+
+static void help_get_legacy_alg_type_from_keymgmt(const char *keytype,
+ void *arg)
+{
+ int *type = arg;
+
+ if (*type == NID_undef)
+ *type = evp_pkey_name2type(keytype);
}
-static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
+static int get_legacy_alg_type_from_keymgmt(const EVP_KEYMGMT *keymgmt)
{
- EVP_PKEY_CTX *ret;
- const EVP_PKEY_METHOD *pmeth;
+ int type = NID_undef;
+ EVP_KEYMGMT_names_do_all(keymgmt, help_get_legacy_alg_type_from_keymgmt,
+ &type);
+ return type;
+}
+#endif /* FIPS_MODULE */
+
+int evp_pkey_ctx_state(const EVP_PKEY_CTX *ctx)
+{
+ if (ctx->operation == EVP_PKEY_OP_UNDEFINED)
+ return EVP_PKEY_STATE_UNKNOWN;
+
+ if ((EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
+ && ctx->op.kex.algctx != NULL)
+ || (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
+ && ctx->op.sig.algctx != NULL)
+ || (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
+ && ctx->op.ciph.algctx != NULL)
+ || (EVP_PKEY_CTX_IS_GEN_OP(ctx)
+ && ctx->op.keymgmt.genctx != NULL)
+ || (EVP_PKEY_CTX_IS_KEM_OP(ctx)
+ && ctx->op.encap.algctx != NULL))
+ return EVP_PKEY_STATE_PROVIDER;
+
+ return EVP_PKEY_STATE_LEGACY;
+}
+
+static EVP_PKEY_CTX *int_ctx_new(OSSL_LIB_CTX *libctx,
+ EVP_PKEY *pkey, ENGINE *e,
+ const char *keytype, const char *propquery,
+ int id)
+
+{
+ EVP_PKEY_CTX *ret = NULL;
+ const EVP_PKEY_METHOD *pmeth = NULL, *app_pmeth = NULL;
+ EVP_KEYMGMT *keymgmt = NULL;
+
+ /* Code below to be removed when legacy support is dropped. */
+ /* BEGIN legacy */
if (id == -1) {
- if (pkey == NULL)
- return 0;
- id = pkey->type;
+ if (pkey != NULL && !evp_pkey_is_provided(pkey)) {
+ id = pkey->type;
+ } else {
+ if (pkey != NULL) {
+ /* Must be provided if we get here */
+ keytype = EVP_KEYMGMT_get0_name(pkey->keymgmt);
+ }
+#ifndef FIPS_MODULE
+ if (keytype != NULL) {
+ id = evp_pkey_name2type(keytype);
+ if (id == NID_undef)
+ id = -1;
+ }
+#endif
+ }
}
-#ifndef OPENSSL_NO_ENGINE
+ /* If no ID was found here, we can only resort to find a keymgmt */
+ if (id == -1) {
+#ifndef FIPS_MODULE
+ /* Using engine with a key without id will not work */
+ if (e != NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_ALGORITHM);
+ return NULL;
+ }
+#endif
+ goto common;
+ }
+
+#ifndef FIPS_MODULE
+ /*
+ * Here, we extract what information we can for the purpose of
+ * supporting usage with implementations from providers, to make
+ * for a smooth transition from legacy stuff to provider based stuff.
+ *
+ * If an engine is given, this is entirely legacy, and we should not
+ * pretend anything else, so we clear the name.
+ */
+ if (e != NULL)
+ keytype = NULL;
+ if (e == NULL && (pkey == NULL || pkey->foreign == 0))
+ keytype = OBJ_nid2sn(id);
+
+# ifndef OPENSSL_NO_ENGINE
if (e == NULL && pkey != NULL)
e = pkey->pmeth_engine != NULL ? pkey->pmeth_engine : pkey->engine;
/* Try to find an ENGINE which implements this method */
- if (e) {
+ if (e != NULL) {
if (!ENGINE_init(e)) {
- EVPerr(EVP_F_INT_CTX_NEW, ERR_R_ENGINE_LIB);
+ ERR_raise(ERR_LIB_EVP, ERR_R_ENGINE_LIB);
return NULL;
}
} else {
@@ -127,28 +249,98 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
* If an ENGINE handled this method look it up. Otherwise use internal
* tables.
*/
- if (e)
+ if (e != NULL)
pmeth = ENGINE_get_pkey_meth(e, id);
- else
-#endif
+ else if (pkey != NULL && pkey->foreign)
pmeth = EVP_PKEY_meth_find(id);
+ else
+# endif
+ app_pmeth = pmeth = evp_pkey_meth_find_added_by_application(id);
- if (pmeth == NULL) {
-#ifndef OPENSSL_NO_ENGINE
- ENGINE_finish(e);
+ /* END legacy */
+#endif /* FIPS_MODULE */
+ common:
+ /*
+ * If there's no engine and no app supplied pmeth and there's a name, we try
+ * fetching a provider implementation.
+ */
+ if (e == NULL && app_pmeth == NULL && keytype != NULL) {
+ /*
+ * If |pkey| is given and is provided, we take a reference to its
+ * keymgmt. Otherwise, we fetch one for the keytype we got. This
+ * is to ensure that operation init functions can access what they
+ * need through this single pointer.
+ */
+ if (pkey != NULL && pkey->keymgmt != NULL) {
+ if (!EVP_KEYMGMT_up_ref(pkey->keymgmt))
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ else
+ keymgmt = pkey->keymgmt;
+ } else {
+ keymgmt = EVP_KEYMGMT_fetch(libctx, keytype, propquery);
+ }
+ if (keymgmt == NULL)
+ return NULL; /* EVP_KEYMGMT_fetch() recorded an error */
+
+#ifndef FIPS_MODULE
+ /*
+ * Chase down the legacy NID, as that might be needed for diverse
+ * purposes, such as ensure that EVP_PKEY_type() can return sensible
+ * values. We go through all keymgmt names, because the keytype
+ * that's passed to this function doesn't necessarily translate
+ * directly.
+ */
+ if (keymgmt != NULL) {
+ int tmp_id = get_legacy_alg_type_from_keymgmt(keymgmt);
+
+ if (tmp_id != NID_undef) {
+ if (id == -1) {
+ id = tmp_id;
+ } else {
+ /*
+ * It really really shouldn't differ. If it still does,
+ * something is very wrong.
+ */
+ if (!ossl_assert(id == tmp_id)) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ EVP_KEYMGMT_free(keymgmt);
+ return NULL;
+ }
+ }
+ }
+ }
#endif
- EVPerr(EVP_F_INT_CTX_NEW, EVP_R_UNSUPPORTED_ALGORITHM);
- return NULL;
}
- ret = OPENSSL_zalloc(sizeof(*ret));
- if (ret == NULL) {
-#ifndef OPENSSL_NO_ENGINE
+ if (pmeth == NULL && keymgmt == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_ALGORITHM);
+ } else {
+ ret = OPENSSL_zalloc(sizeof(*ret));
+ if (ret == NULL)
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ }
+
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
+ if ((ret == NULL || pmeth == NULL) && e != NULL)
ENGINE_finish(e);
#endif
- EVPerr(EVP_F_INT_CTX_NEW, ERR_R_MALLOC_FAILURE);
+
+ if (ret == NULL) {
+ EVP_KEYMGMT_free(keymgmt);
return NULL;
}
+ if (propquery != NULL) {
+ ret->propquery = OPENSSL_strdup(propquery);
+ if (ret->propquery == NULL) {
+ OPENSSL_free(ret);
+ EVP_KEYMGMT_free(keymgmt);
+ return NULL;
+ }
+ }
+ ret->libctx = libctx;
+ ret->keytype = keytype;
+ ret->keymgmt = keymgmt;
+ ret->legacy_keytype = id;
ret->engine = e;
ret->pmeth = pmeth;
ret->operation = EVP_PKEY_OP_UNDEFINED;
@@ -156,7 +348,7 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
if (pkey != NULL)
EVP_PKEY_up_ref(pkey);
- if (pmeth->init) {
+ if (pmeth != NULL && pmeth->init != NULL) {
if (pmeth->init(ret) <= 0) {
ret->pmeth = NULL;
EVP_PKEY_CTX_free(ret);
@@ -167,21 +359,79 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
return ret;
}
-EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags)
+/*- All methods below can also be used in FIPS_MODULE */
+
+EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name(OSSL_LIB_CTX *libctx,
+ const char *name,
+ const char *propquery)
{
- EVP_PKEY_METHOD *pmeth;
+ return int_ctx_new(libctx, NULL, NULL, name, propquery, -1);
+}
- pmeth = OPENSSL_zalloc(sizeof(*pmeth));
- if (pmeth == NULL) {
- EVPerr(EVP_F_EVP_PKEY_METH_NEW, ERR_R_MALLOC_FAILURE);
- return NULL;
+EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OSSL_LIB_CTX *libctx, EVP_PKEY *pkey,
+ const char *propquery)
+{
+ return int_ctx_new(libctx, pkey, NULL, NULL, propquery, -1);
+}
+
+void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx)
+{
+ if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
+ if (ctx->op.sig.algctx != NULL && ctx->op.sig.signature != NULL)
+ ctx->op.sig.signature->freectx(ctx->op.sig.algctx);
+ EVP_SIGNATURE_free(ctx->op.sig.signature);
+ ctx->op.sig.algctx = NULL;
+ ctx->op.sig.signature = NULL;
+ } else if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
+ if (ctx->op.kex.algctx != NULL && ctx->op.kex.exchange != NULL)
+ ctx->op.kex.exchange->freectx(ctx->op.kex.algctx);
+ EVP_KEYEXCH_free(ctx->op.kex.exchange);
+ ctx->op.kex.algctx = NULL;
+ ctx->op.kex.exchange = NULL;
+ } else if (EVP_PKEY_CTX_IS_KEM_OP(ctx)) {
+ if (ctx->op.encap.algctx != NULL && ctx->op.encap.kem != NULL)
+ ctx->op.encap.kem->freectx(ctx->op.encap.algctx);
+ EVP_KEM_free(ctx->op.encap.kem);
+ ctx->op.encap.algctx = NULL;
+ ctx->op.encap.kem = NULL;
+ }
+ else if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)) {
+ if (ctx->op.ciph.algctx != NULL && ctx->op.ciph.cipher != NULL)
+ ctx->op.ciph.cipher->freectx(ctx->op.ciph.algctx);
+ EVP_ASYM_CIPHER_free(ctx->op.ciph.cipher);
+ ctx->op.ciph.algctx = NULL;
+ ctx->op.ciph.cipher = NULL;
+ } else if (EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
+ if (ctx->op.keymgmt.genctx != NULL && ctx->keymgmt != NULL)
+ evp_keymgmt_gen_cleanup(ctx->keymgmt, ctx->op.keymgmt.genctx);
}
+}
- pmeth->pkey_id = id;
- pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC;
- return pmeth;
+void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx)
+{
+ if (ctx == NULL)
+ return;
+ if (ctx->pmeth && ctx->pmeth->cleanup)
+ ctx->pmeth->cleanup(ctx);
+
+ evp_pkey_ctx_free_old_ops(ctx);
+#ifndef FIPS_MODULE
+ evp_pkey_ctx_free_all_cached_data(ctx);
+#endif
+ EVP_KEYMGMT_free(ctx->keymgmt);
+
+ OPENSSL_free(ctx->propquery);
+ EVP_PKEY_free(ctx->pkey);
+ EVP_PKEY_free(ctx->peerkey);
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
+ ENGINE_finish(ctx->engine);
+#endif
+ BN_free(ctx->rsa_pubexp);
+ OPENSSL_free(ctx);
}
+#ifndef FIPS_MODULE
+
void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags,
const EVP_PKEY_METHOD *meth)
{
@@ -193,45 +443,14 @@ void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags,
void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src)
{
+ int pkey_id = dst->pkey_id;
+ int flags = dst->flags;
- dst->init = src->init;
- dst->copy = src->copy;
- dst->cleanup = src->cleanup;
-
- dst->paramgen_init = src->paramgen_init;
- dst->paramgen = src->paramgen;
+ *dst = *src;
- dst->keygen_init = src->keygen_init;
- dst->keygen = src->keygen;
-
- dst->sign_init = src->sign_init;
- dst->sign = src->sign;
-
- dst->verify_init = src->verify_init;
- dst->verify = src->verify;
-
- dst->verify_recover_init = src->verify_recover_init;
- dst->verify_recover = src->verify_recover;
-
- dst->signctx_init = src->signctx_init;
- dst->signctx = src->signctx;
-
- dst->verifyctx_init = src->verifyctx_init;
- dst->verifyctx = src->verifyctx;
-
- dst->encrypt_init = src->encrypt_init;
- dst->encrypt = src->encrypt;
-
- dst->decrypt_init = src->decrypt_init;
- dst->decrypt = src->decrypt;
-
- dst->derive_init = src->derive_init;
- dst->derive = src->derive;
-
- dst->ctrl = src->ctrl;
- dst->ctrl_str = src->ctrl_str;
-
- dst->check = src->check;
+ /* We only copy the function pointers so restore the other values */
+ dst->pkey_id = pkey_id;
+ dst->flags = flags;
}
void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth)
@@ -242,58 +461,153 @@ void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth)
EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e)
{
- return int_ctx_new(pkey, e, -1);
+ return int_ctx_new(NULL, pkey, e, NULL, NULL, -1);
}
EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e)
{
- return int_ctx_new(NULL, e, id);
+ return int_ctx_new(NULL, NULL, e, NULL, NULL, id);
}
-EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx)
+EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx)
{
EVP_PKEY_CTX *rctx;
- if (!pctx->pmeth || !pctx->pmeth->copy)
- return NULL;
-#ifndef OPENSSL_NO_ENGINE
+
+# ifndef OPENSSL_NO_ENGINE
/* Make sure it's safe to copy a pkey context using an ENGINE */
if (pctx->engine && !ENGINE_init(pctx->engine)) {
- EVPerr(EVP_F_EVP_PKEY_CTX_DUP, ERR_R_ENGINE_LIB);
+ ERR_raise(ERR_LIB_EVP, ERR_R_ENGINE_LIB);
return 0;
}
-#endif
- rctx = OPENSSL_malloc(sizeof(*rctx));
+# endif
+ rctx = OPENSSL_zalloc(sizeof(*rctx));
if (rctx == NULL) {
- EVPerr(EVP_F_EVP_PKEY_CTX_DUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return NULL;
}
- rctx->pmeth = pctx->pmeth;
-#ifndef OPENSSL_NO_ENGINE
- rctx->engine = pctx->engine;
-#endif
-
- if (pctx->pkey)
+ if (pctx->pkey != NULL)
EVP_PKEY_up_ref(pctx->pkey);
-
rctx->pkey = pctx->pkey;
+ rctx->operation = pctx->operation;
+ rctx->libctx = pctx->libctx;
+ rctx->keytype = pctx->keytype;
+ rctx->propquery = NULL;
+ if (pctx->propquery != NULL) {
+ rctx->propquery = OPENSSL_strdup(pctx->propquery);
+ if (rctx->propquery == NULL)
+ goto err;
+ }
+ rctx->legacy_keytype = pctx->legacy_keytype;
- if (pctx->peerkey)
- EVP_PKEY_up_ref(pctx->peerkey);
+ if (EVP_PKEY_CTX_IS_DERIVE_OP(pctx)) {
+ if (pctx->op.kex.exchange != NULL) {
+ rctx->op.kex.exchange = pctx->op.kex.exchange;
+ if (!EVP_KEYEXCH_up_ref(rctx->op.kex.exchange))
+ goto err;
+ }
+ if (pctx->op.kex.algctx != NULL) {
+ if (!ossl_assert(pctx->op.kex.exchange != NULL))
+ goto err;
+ rctx->op.kex.algctx
+ = pctx->op.kex.exchange->dupctx(pctx->op.kex.algctx);
+ if (rctx->op.kex.algctx == NULL) {
+ EVP_KEYEXCH_free(rctx->op.kex.exchange);
+ rctx->op.kex.exchange = NULL;
+ goto err;
+ }
+ return rctx;
+ }
+ } else if (EVP_PKEY_CTX_IS_SIGNATURE_OP(pctx)) {
+ if (pctx->op.sig.signature != NULL) {
+ rctx->op.sig.signature = pctx->op.sig.signature;
+ if (!EVP_SIGNATURE_up_ref(rctx->op.sig.signature))
+ goto err;
+ }
+ if (pctx->op.sig.algctx != NULL) {
+ if (!ossl_assert(pctx->op.sig.signature != NULL))
+ goto err;
+ rctx->op.sig.algctx
+ = pctx->op.sig.signature->dupctx(pctx->op.sig.algctx);
+ if (rctx->op.sig.algctx == NULL) {
+ EVP_SIGNATURE_free(rctx->op.sig.signature);
+ rctx->op.sig.signature = NULL;
+ goto err;
+ }
+ return rctx;
+ }
+ } else if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(pctx)) {
+ if (pctx->op.ciph.cipher != NULL) {
+ rctx->op.ciph.cipher = pctx->op.ciph.cipher;
+ if (!EVP_ASYM_CIPHER_up_ref(rctx->op.ciph.cipher))
+ goto err;
+ }
+ if (pctx->op.ciph.algctx != NULL) {
+ if (!ossl_assert(pctx->op.ciph.cipher != NULL))
+ goto err;
+ rctx->op.ciph.algctx
+ = pctx->op.ciph.cipher->dupctx(pctx->op.ciph.algctx);
+ if (rctx->op.ciph.algctx == NULL) {
+ EVP_ASYM_CIPHER_free(rctx->op.ciph.cipher);
+ rctx->op.ciph.cipher = NULL;
+ goto err;
+ }
+ return rctx;
+ }
+ } else if (EVP_PKEY_CTX_IS_KEM_OP(pctx)) {
+ if (pctx->op.encap.kem != NULL) {
+ rctx->op.encap.kem = pctx->op.encap.kem;
+ if (!EVP_KEM_up_ref(rctx->op.encap.kem))
+ goto err;
+ }
+ if (pctx->op.encap.algctx != NULL) {
+ if (!ossl_assert(pctx->op.encap.kem != NULL))
+ goto err;
+ rctx->op.encap.algctx
+ = pctx->op.encap.kem->dupctx(pctx->op.encap.algctx);
+ if (rctx->op.encap.algctx == NULL) {
+ EVP_KEM_free(rctx->op.encap.kem);
+ rctx->op.encap.kem = NULL;
+ goto err;
+ }
+ return rctx;
+ }
+ } else if (EVP_PKEY_CTX_IS_GEN_OP(pctx)) {
+ /* Not supported - This would need a gen_dupctx() to work */
+ goto err;
+ }
- rctx->peerkey = pctx->peerkey;
+ rctx->pmeth = pctx->pmeth;
+# ifndef OPENSSL_NO_ENGINE
+ rctx->engine = pctx->engine;
+# endif
- rctx->data = NULL;
- rctx->app_data = NULL;
- rctx->operation = pctx->operation;
+ if (pctx->peerkey != NULL)
+ EVP_PKEY_up_ref(pctx->peerkey);
+ rctx->peerkey = pctx->peerkey;
- if (pctx->pmeth->copy(rctx, pctx) > 0)
+ if (pctx->pmeth == NULL) {
+ if (rctx->operation == EVP_PKEY_OP_UNDEFINED) {
+ EVP_KEYMGMT *tmp_keymgmt = pctx->keymgmt;
+ void *provkey;
+
+ provkey = evp_pkey_export_to_provider(pctx->pkey, pctx->libctx,
+ &tmp_keymgmt, pctx->propquery);
+ if (provkey == NULL)
+ goto err;
+ if (!EVP_KEYMGMT_up_ref(tmp_keymgmt))
+ goto err;
+ EVP_KEYMGMT_free(rctx->keymgmt);
+ rctx->keymgmt = tmp_keymgmt;
+ return rctx;
+ }
+ } else if (pctx->pmeth->copy(rctx, pctx) > 0) {
return rctx;
-
+ }
+err:
rctx->pmeth = NULL;
EVP_PKEY_CTX_free(rctx);
return NULL;
-
}
int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth)
@@ -301,12 +615,12 @@ int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth)
if (app_pkey_methods == NULL) {
app_pkey_methods = sk_EVP_PKEY_METHOD_new(pmeth_cmp);
if (app_pkey_methods == NULL){
- EVPerr(EVP_F_EVP_PKEY_METH_ADD0, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
}
if (!sk_EVP_PKEY_METHOD_push(app_pkey_methods, pmeth)) {
- EVPerr(EVP_F_EVP_PKEY_METH_ADD0, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
sk_EVP_PKEY_METHOD_sort(app_pkey_methods);
@@ -340,7 +654,7 @@ size_t EVP_PKEY_meth_get_count(void)
const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx)
{
if (idx < OSSL_NELEM(standard_methods))
- return standard_methods[idx];
+ return (standard_methods[idx])();
if (app_pkey_methods == NULL)
return NULL;
idx -= OSSL_NELEM(standard_methods);
@@ -348,73 +662,917 @@ const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx)
return NULL;
return sk_EVP_PKEY_METHOD_value(app_pkey_methods, idx);
}
+#endif
-void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx)
+int EVP_PKEY_CTX_is_a(EVP_PKEY_CTX *ctx, const char *keytype)
{
- if (ctx == NULL)
- return;
- if (ctx->pmeth && ctx->pmeth->cleanup)
- ctx->pmeth->cleanup(ctx);
- EVP_PKEY_free(ctx->pkey);
- EVP_PKEY_free(ctx->peerkey);
-#ifndef OPENSSL_NO_ENGINE
- ENGINE_finish(ctx->engine);
+#ifndef FIPS_MODULE
+ if (evp_pkey_ctx_is_legacy(ctx))
+ return (ctx->pmeth->pkey_id == evp_pkey_name2type(keytype));
#endif
- OPENSSL_free(ctx);
+ return EVP_KEYMGMT_is_a(ctx->keymgmt, keytype);
+}
+
+int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, const OSSL_PARAM *params)
+{
+ switch (evp_pkey_ctx_state(ctx)) {
+ case EVP_PKEY_STATE_PROVIDER:
+ if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
+ && ctx->op.kex.exchange != NULL
+ && ctx->op.kex.exchange->set_ctx_params != NULL)
+ return
+ ctx->op.kex.exchange->set_ctx_params(ctx->op.kex.algctx,
+ params);
+ if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
+ && ctx->op.sig.signature != NULL
+ && ctx->op.sig.signature->set_ctx_params != NULL)
+ return
+ ctx->op.sig.signature->set_ctx_params(ctx->op.sig.algctx,
+ params);
+ if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
+ && ctx->op.ciph.cipher != NULL
+ && ctx->op.ciph.cipher->set_ctx_params != NULL)
+ return
+ ctx->op.ciph.cipher->set_ctx_params(ctx->op.ciph.algctx,
+ params);
+ if (EVP_PKEY_CTX_IS_GEN_OP(ctx)
+ && ctx->keymgmt != NULL
+ && ctx->keymgmt->gen_set_params != NULL)
+ return
+ evp_keymgmt_gen_set_params(ctx->keymgmt, ctx->op.keymgmt.genctx,
+ params);
+ if (EVP_PKEY_CTX_IS_KEM_OP(ctx)
+ && ctx->op.encap.kem != NULL
+ && ctx->op.encap.kem->set_ctx_params != NULL)
+ return
+ ctx->op.encap.kem->set_ctx_params(ctx->op.encap.algctx,
+ params);
+ break;
+#ifndef FIPS_MODULE
+ case EVP_PKEY_STATE_UNKNOWN:
+ case EVP_PKEY_STATE_LEGACY:
+ return evp_pkey_ctx_set_params_to_ctrl(ctx, params);
+#endif
+ }
+ return 0;
+}
+
+int EVP_PKEY_CTX_get_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
+{
+ switch (evp_pkey_ctx_state(ctx)) {
+ case EVP_PKEY_STATE_PROVIDER:
+ if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
+ && ctx->op.kex.exchange != NULL
+ && ctx->op.kex.exchange->get_ctx_params != NULL)
+ return
+ ctx->op.kex.exchange->get_ctx_params(ctx->op.kex.algctx,
+ params);
+ if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
+ && ctx->op.sig.signature != NULL
+ && ctx->op.sig.signature->get_ctx_params != NULL)
+ return
+ ctx->op.sig.signature->get_ctx_params(ctx->op.sig.algctx,
+ params);
+ if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
+ && ctx->op.ciph.cipher != NULL
+ && ctx->op.ciph.cipher->get_ctx_params != NULL)
+ return
+ ctx->op.ciph.cipher->get_ctx_params(ctx->op.ciph.algctx,
+ params);
+ if (EVP_PKEY_CTX_IS_KEM_OP(ctx)
+ && ctx->op.encap.kem != NULL
+ && ctx->op.encap.kem->get_ctx_params != NULL)
+ return
+ ctx->op.encap.kem->get_ctx_params(ctx->op.encap.algctx,
+ params);
+ break;
+#ifndef FIPS_MODULE
+ case EVP_PKEY_STATE_UNKNOWN:
+ case EVP_PKEY_STATE_LEGACY:
+ return evp_pkey_ctx_get_params_to_ctrl(ctx, params);
+#endif
+ }
+ return 0;
}
-int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
- int cmd, int p1, void *p2)
+#ifndef FIPS_MODULE
+const OSSL_PARAM *EVP_PKEY_CTX_gettable_params(const EVP_PKEY_CTX *ctx)
{
- int ret;
+ void *provctx;
+
+ if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
+ && ctx->op.kex.exchange != NULL
+ && ctx->op.kex.exchange->gettable_ctx_params != NULL) {
+ provctx = ossl_provider_ctx(EVP_KEYEXCH_get0_provider(ctx->op.kex.exchange));
+ return ctx->op.kex.exchange->gettable_ctx_params(ctx->op.kex.algctx,
+ provctx);
+ }
+ if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
+ && ctx->op.sig.signature != NULL
+ && ctx->op.sig.signature->gettable_ctx_params != NULL) {
+ provctx = ossl_provider_ctx(
+ EVP_SIGNATURE_get0_provider(ctx->op.sig.signature));
+ return ctx->op.sig.signature->gettable_ctx_params(ctx->op.sig.algctx,
+ provctx);
+ }
+ if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
+ && ctx->op.ciph.cipher != NULL
+ && ctx->op.ciph.cipher->gettable_ctx_params != NULL) {
+ provctx = ossl_provider_ctx(
+ EVP_ASYM_CIPHER_get0_provider(ctx->op.ciph.cipher));
+ return ctx->op.ciph.cipher->gettable_ctx_params(ctx->op.ciph.algctx,
+ provctx);
+ }
+ if (EVP_PKEY_CTX_IS_KEM_OP(ctx)
+ && ctx->op.encap.kem != NULL
+ && ctx->op.encap.kem->gettable_ctx_params != NULL) {
+ provctx = ossl_provider_ctx(EVP_KEM_get0_provider(ctx->op.encap.kem));
+ return ctx->op.encap.kem->gettable_ctx_params(ctx->op.encap.algctx,
+ provctx);
+ }
+ return NULL;
+}
+
+const OSSL_PARAM *EVP_PKEY_CTX_settable_params(const EVP_PKEY_CTX *ctx)
+{
+ void *provctx;
+
+ if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
+ && ctx->op.kex.exchange != NULL
+ && ctx->op.kex.exchange->settable_ctx_params != NULL) {
+ provctx = ossl_provider_ctx(EVP_KEYEXCH_get0_provider(ctx->op.kex.exchange));
+ return ctx->op.kex.exchange->settable_ctx_params(ctx->op.kex.algctx,
+ provctx);
+ }
+ if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
+ && ctx->op.sig.signature != NULL
+ && ctx->op.sig.signature->settable_ctx_params != NULL) {
+ provctx = ossl_provider_ctx(
+ EVP_SIGNATURE_get0_provider(ctx->op.sig.signature));
+ return ctx->op.sig.signature->settable_ctx_params(ctx->op.sig.algctx,
+ provctx);
+ }
+ if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
+ && ctx->op.ciph.cipher != NULL
+ && ctx->op.ciph.cipher->settable_ctx_params != NULL) {
+ provctx = ossl_provider_ctx(
+ EVP_ASYM_CIPHER_get0_provider(ctx->op.ciph.cipher));
+ return ctx->op.ciph.cipher->settable_ctx_params(ctx->op.ciph.algctx,
+ provctx);
+ }
+ if (EVP_PKEY_CTX_IS_GEN_OP(ctx)
+ && ctx->keymgmt != NULL
+ && ctx->keymgmt->gen_settable_params != NULL) {
+ provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(ctx->keymgmt));
+ return ctx->keymgmt->gen_settable_params(ctx->op.keymgmt.genctx,
+ provctx);
+ }
+ if (EVP_PKEY_CTX_IS_KEM_OP(ctx)
+ && ctx->op.encap.kem != NULL
+ && ctx->op.encap.kem->settable_ctx_params != NULL) {
+ provctx = ossl_provider_ctx(EVP_KEM_get0_provider(ctx->op.encap.kem));
+ return ctx->op.encap.kem->settable_ctx_params(ctx->op.encap.algctx,
+ provctx);
+ }
+ return NULL;
+}
+
+/*
+ * Internal helpers for stricter EVP_PKEY_CTX_{set,get}_params().
+ *
+ * Return 1 on success, 0 or negative for errors.
+ *
+ * In particular they return -2 if any of the params is not supported.
+ *
+ * They are not available in FIPS_MODULE as they depend on
+ * - EVP_PKEY_CTX_{get,set}_params()
+ * - EVP_PKEY_CTX_{gettable,settable}_params()
+ *
+ */
+int evp_pkey_ctx_set_params_strict(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
+{
+ if (ctx == NULL || params == NULL)
+ return 0;
+
+ /*
+ * We only check for provider side EVP_PKEY_CTX. For #legacy, we
+ * depend on the translation that happens in EVP_PKEY_CTX_set_params()
+ * call, and that the resulting ctrl call will return -2 if it doesn't
+ * known the ctrl command number.
+ */
+ if (evp_pkey_ctx_is_provided(ctx)) {
+ const OSSL_PARAM *settable = EVP_PKEY_CTX_settable_params(ctx);
+ const OSSL_PARAM *p;
+
+ for (p = params; p->key != NULL; p++) {
+ /* Check the ctx actually understands this parameter */
+ if (OSSL_PARAM_locate_const(settable, p->key) == NULL )
+ return -2;
+ }
+ }
+
+ return EVP_PKEY_CTX_set_params(ctx, params);
+}
+
+int evp_pkey_ctx_get_params_strict(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
+{
+ if (ctx == NULL || params == NULL)
+ return 0;
+
+ /*
+ * We only check for provider side EVP_PKEY_CTX. For #legacy, we
+ * depend on the translation that happens in EVP_PKEY_CTX_get_params()
+ * call, and that the resulting ctrl call will return -2 if it doesn't
+ * known the ctrl command number.
+ */
+ if (evp_pkey_ctx_is_provided(ctx)) {
+ const OSSL_PARAM *gettable = EVP_PKEY_CTX_gettable_params(ctx);
+ const OSSL_PARAM *p;
+
+ for (p = params; p->key != NULL; p++ ) {
+ /* Check the ctx actually understands this parameter */
+ if (OSSL_PARAM_locate_const(gettable, p->key) == NULL )
+ return -2;
+ }
+ }
+
+ return EVP_PKEY_CTX_get_params(ctx, params);
+}
- if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) {
- EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
+int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **md)
+{
+ OSSL_PARAM sig_md_params[2], *p = sig_md_params;
+ /* 80 should be big enough */
+ char name[80] = "";
+ const EVP_MD *tmp;
+
+ if (ctx == NULL || !EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
return -2;
}
- if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype))
- return -1;
- /* Skip the operation checks since this is called in a very early stage */
- if (ctx->pmeth->digest_custom != NULL)
- goto doit;
+ if (ctx->op.sig.algctx == NULL)
+ return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG,
+ EVP_PKEY_CTRL_GET_MD, 0, (void *)(md));
- if (ctx->operation == EVP_PKEY_OP_UNDEFINED) {
- EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_NO_OPERATION_SET);
- return -1;
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST,
+ name,
+ sizeof(name));
+ *p = OSSL_PARAM_construct_end();
+
+ if (!EVP_PKEY_CTX_get_params(ctx, sig_md_params))
+ return 0;
+
+ tmp = evp_get_digestbyname_ex(ctx->libctx, name);
+ if (tmp == NULL)
+ return 0;
+
+ *md = tmp;
+
+ return 1;
+}
+
+static int evp_pkey_ctx_set_md(EVP_PKEY_CTX *ctx, const EVP_MD *md,
+ int fallback, const char *param, int op,
+ int ctrl)
+{
+ OSSL_PARAM md_params[2], *p = md_params;
+ const char *name;
+
+ if (ctx == NULL || (ctx->operation & op) == 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
}
- if ((optype != -1) && !(ctx->operation & optype)) {
- EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_INVALID_OPERATION);
- return -1;
+ if (fallback)
+ return EVP_PKEY_CTX_ctrl(ctx, -1, op, ctrl, 0, (void *)(md));
+
+ if (md == NULL) {
+ name = "";
+ } else {
+ name = EVP_MD_get0_name(md);
+ }
+
+ *p++ = OSSL_PARAM_construct_utf8_string(param,
+ /*
+ * Cast away the const. This is read
+ * only so should be safe
+ */
+ (char *)name, 0);
+ *p = OSSL_PARAM_construct_end();
+
+ return EVP_PKEY_CTX_set_params(ctx, md_params);
+}
+
+int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
+{
+ return evp_pkey_ctx_set_md(ctx, md, ctx->op.sig.algctx == NULL,
+ OSSL_SIGNATURE_PARAM_DIGEST,
+ EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD);
+}
+
+int EVP_PKEY_CTX_set_tls1_prf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
+{
+ return evp_pkey_ctx_set_md(ctx, md, ctx->op.kex.algctx == NULL,
+ OSSL_KDF_PARAM_DIGEST,
+ EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_TLS_MD);
+}
+
+static int evp_pkey_ctx_set1_octet_string(EVP_PKEY_CTX *ctx, int fallback,
+ const char *param, int op, int ctrl,
+ const unsigned char *data,
+ int datalen)
+{
+ OSSL_PARAM octet_string_params[2], *p = octet_string_params;
+
+ if (ctx == NULL || (ctx->operation & op) == 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+
+ /* Code below to be removed when legacy support is dropped. */
+ if (fallback)
+ return EVP_PKEY_CTX_ctrl(ctx, -1, op, ctrl, datalen, (void *)(data));
+ /* end of legacy support */
+
+ if (datalen < 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_LENGTH);
+ return 0;
}
- doit:
- ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2);
+ *p++ = OSSL_PARAM_construct_octet_string(param,
+ /*
+ * Cast away the const. This is read
+ * only so should be safe
+ */
+ (unsigned char *)data,
+ (size_t)datalen);
+ *p = OSSL_PARAM_construct_end();
+ return EVP_PKEY_CTX_set_params(ctx, octet_string_params);
+}
+
+int EVP_PKEY_CTX_set1_tls1_prf_secret(EVP_PKEY_CTX *ctx,
+ const unsigned char *sec, int seclen)
+{
+ return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.algctx == NULL,
+ OSSL_KDF_PARAM_SECRET,
+ EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_TLS_SECRET,
+ sec, seclen);
+}
+
+int EVP_PKEY_CTX_add1_tls1_prf_seed(EVP_PKEY_CTX *ctx,
+ const unsigned char *seed, int seedlen)
+{
+ return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.algctx == NULL,
+ OSSL_KDF_PARAM_SEED,
+ EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_TLS_SEED,
+ seed, seedlen);
+}
+
+int EVP_PKEY_CTX_set_hkdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
+{
+ return evp_pkey_ctx_set_md(ctx, md, ctx->op.kex.algctx == NULL,
+ OSSL_KDF_PARAM_DIGEST,
+ EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_HKDF_MD);
+}
+
+int EVP_PKEY_CTX_set1_hkdf_salt(EVP_PKEY_CTX *ctx,
+ const unsigned char *salt, int saltlen)
+{
+ return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.algctx == NULL,
+ OSSL_KDF_PARAM_SALT,
+ EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_HKDF_SALT,
+ salt, saltlen);
+}
+
+int EVP_PKEY_CTX_set1_hkdf_key(EVP_PKEY_CTX *ctx,
+ const unsigned char *key, int keylen)
+{
+ return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.algctx == NULL,
+ OSSL_KDF_PARAM_KEY,
+ EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_HKDF_KEY,
+ key, keylen);
+}
+
+int EVP_PKEY_CTX_add1_hkdf_info(EVP_PKEY_CTX *ctx,
+ const unsigned char *info, int infolen)
+{
+ return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.algctx == NULL,
+ OSSL_KDF_PARAM_INFO,
+ EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_HKDF_INFO,
+ info, infolen);
+}
+
+int EVP_PKEY_CTX_set_hkdf_mode(EVP_PKEY_CTX *ctx, int mode)
+{
+ OSSL_PARAM int_params[2], *p = int_params;
+
+ if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+
+ /* Code below to be removed when legacy support is dropped. */
+ if (ctx->op.kex.algctx == NULL)
+ return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_HKDF_MODE, mode, NULL);
+ /* end of legacy support */
+
+ if (mode < 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
+ return 0;
+ }
+
+ *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode);
+ *p = OSSL_PARAM_construct_end();
+
+ return EVP_PKEY_CTX_set_params(ctx, int_params);
+}
+
+int EVP_PKEY_CTX_set1_pbe_pass(EVP_PKEY_CTX *ctx, const char *pass,
+ int passlen)
+{
+ return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.algctx == NULL,
+ OSSL_KDF_PARAM_PASSWORD,
+ EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_PASS,
+ (const unsigned char *)pass, passlen);
+}
+
+int EVP_PKEY_CTX_set1_scrypt_salt(EVP_PKEY_CTX *ctx,
+ const unsigned char *salt, int saltlen)
+{
+ return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.algctx == NULL,
+ OSSL_KDF_PARAM_SALT,
+ EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_SCRYPT_SALT,
+ salt, saltlen);
+}
+
+static int evp_pkey_ctx_set_uint64(EVP_PKEY_CTX *ctx, const char *param,
+ int op, int ctrl, uint64_t val)
+{
+ OSSL_PARAM uint64_params[2], *p = uint64_params;
+
+ if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+
+ /* Code below to be removed when legacy support is dropped. */
+ if (ctx->op.kex.algctx == NULL)
+ return EVP_PKEY_CTX_ctrl_uint64(ctx, -1, op, ctrl, val);
+ /* end of legacy support */
+
+ *p++ = OSSL_PARAM_construct_uint64(param, &val);
+ *p = OSSL_PARAM_construct_end();
+
+ return EVP_PKEY_CTX_set_params(ctx, uint64_params);
+}
+
+int EVP_PKEY_CTX_set_scrypt_N(EVP_PKEY_CTX *ctx, uint64_t n)
+{
+ return evp_pkey_ctx_set_uint64(ctx, OSSL_KDF_PARAM_SCRYPT_N,
+ EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_SCRYPT_N,
+ n);
+}
+
+int EVP_PKEY_CTX_set_scrypt_r(EVP_PKEY_CTX *ctx, uint64_t r)
+{
+ return evp_pkey_ctx_set_uint64(ctx, OSSL_KDF_PARAM_SCRYPT_R,
+ EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_SCRYPT_R,
+ r);
+}
+
+int EVP_PKEY_CTX_set_scrypt_p(EVP_PKEY_CTX *ctx, uint64_t p)
+{
+ return evp_pkey_ctx_set_uint64(ctx, OSSL_KDF_PARAM_SCRYPT_P,
+ EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_SCRYPT_P,
+ p);
+}
+
+int EVP_PKEY_CTX_set_scrypt_maxmem_bytes(EVP_PKEY_CTX *ctx,
+ uint64_t maxmem_bytes)
+{
+ return evp_pkey_ctx_set_uint64(ctx, OSSL_KDF_PARAM_SCRYPT_MAXMEM,
+ EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES,
+ maxmem_bytes);
+}
+
+int EVP_PKEY_CTX_set_mac_key(EVP_PKEY_CTX *ctx, const unsigned char *key,
+ int keylen)
+{
+ return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.keymgmt.genctx == NULL,
+ OSSL_PKEY_PARAM_PRIV_KEY,
+ EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_SET_MAC_KEY,
+ key, keylen);
+}
+
+int EVP_PKEY_CTX_set_kem_op(EVP_PKEY_CTX *ctx, const char *op)
+{
+ OSSL_PARAM params[2], *p = params;
+
+ if (ctx == NULL || op == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
+ return 0;
+ }
+ if (!EVP_PKEY_CTX_IS_KEM_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return -2;
+ }
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
+ (char *)op, 0);
+ *p = OSSL_PARAM_construct_end();
+ return EVP_PKEY_CTX_set_params(ctx, params);
+}
+
+int evp_pkey_ctx_set1_id_prov(EVP_PKEY_CTX *ctx, const void *id, int len)
+{
+ OSSL_PARAM params[2], *p = params;
+ int ret;
+
+ if (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DIST_ID,
+ /*
+ * Cast away the const. This is
+ * read only so should be safe
+ */
+ (void *)id, (size_t)len);
+ *p++ = OSSL_PARAM_construct_end();
+
+ ret = evp_pkey_ctx_set_params_strict(ctx, params);
if (ret == -2)
- EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return ret;
+}
+
+int EVP_PKEY_CTX_set1_id(EVP_PKEY_CTX *ctx, const void *id, int len)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, -1, -1,
+ EVP_PKEY_CTRL_SET1_ID, (int)len, (void*)(id));
+}
+
+static int get1_id_data(EVP_PKEY_CTX *ctx, void *id, size_t *id_len)
+{
+ int ret;
+ void *tmp_id = NULL;
+ OSSL_PARAM params[2], *p = params;
+
+ if (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+
+ *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_PKEY_PARAM_DIST_ID,
+ &tmp_id, 0);
+ *p++ = OSSL_PARAM_construct_end();
+
+ ret = evp_pkey_ctx_get_params_strict(ctx, params);
+ if (ret == -2) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ } else if (ret > 0) {
+ size_t tmp_id_len = params[0].return_size;
+
+ if (id != NULL)
+ memcpy(id, tmp_id, tmp_id_len);
+ if (id_len != NULL)
+ *id_len = tmp_id_len;
+ }
+ return ret;
+}
+
+int evp_pkey_ctx_get1_id_prov(EVP_PKEY_CTX *ctx, void *id)
+{
+ return get1_id_data(ctx, id, NULL);
+}
+
+int evp_pkey_ctx_get1_id_len_prov(EVP_PKEY_CTX *ctx, size_t *id_len)
+{
+ return get1_id_data(ctx, NULL, id_len);
+}
+
+int EVP_PKEY_CTX_get1_id(EVP_PKEY_CTX *ctx, void *id)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_GET1_ID, 0, (void*)id);
+}
+
+int EVP_PKEY_CTX_get1_id_len(EVP_PKEY_CTX *ctx, size_t *id_len)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, -1, -1,
+ EVP_PKEY_CTRL_GET1_ID_LEN, 0, (void*)id_len);
+}
+
+static int evp_pkey_ctx_ctrl_int(EVP_PKEY_CTX *ctx, int keytype, int optype,
+ int cmd, int p1, void *p2)
+{
+ int ret = 0;
+
+ /*
+ * If the method has a |digest_custom| function, we can relax the
+ * operation type check, since this can be called before the operation
+ * is initialized.
+ */
+ if (ctx->pmeth == NULL || ctx->pmeth->digest_custom == NULL) {
+ if (ctx->operation == EVP_PKEY_OP_UNDEFINED) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_OPERATION_SET);
+ return -1;
+ }
+
+ if ((optype != -1) && !(ctx->operation & optype)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
+ return -1;
+ }
+ }
+ switch (evp_pkey_ctx_state(ctx)) {
+ case EVP_PKEY_STATE_PROVIDER:
+ return evp_pkey_ctx_ctrl_to_param(ctx, keytype, optype, cmd, p1, p2);
+ case EVP_PKEY_STATE_UNKNOWN:
+ case EVP_PKEY_STATE_LEGACY:
+ if (ctx->pmeth == NULL || ctx->pmeth->ctrl == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return -2;
+ }
+ if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype))
+ return -1;
+
+ ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2);
+
+ if (ret == -2)
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ break;
+ }
return ret;
}
+int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
+ int cmd, int p1, void *p2)
+{
+ int ret = 0;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return -2;
+ }
+ /* If unsupported, we don't want that reported here */
+ ERR_set_mark();
+ ret = evp_pkey_ctx_store_cached_data(ctx, keytype, optype,
+ cmd, NULL, p2, p1);
+ if (ret == -2) {
+ ERR_pop_to_mark();
+ } else {
+ ERR_clear_last_mark();
+ /*
+ * If there was an error, there was an error.
+ * If the operation isn't initialized yet, we also return, as
+ * the saved values will be used then anyway.
+ */
+ if (ret < 1 || ctx->operation == EVP_PKEY_OP_UNDEFINED)
+ return ret;
+ }
+ return evp_pkey_ctx_ctrl_int(ctx, keytype, optype, cmd, p1, p2);
+}
+
int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype,
int cmd, uint64_t value)
{
return EVP_PKEY_CTX_ctrl(ctx, keytype, optype, cmd, 0, &value);
}
+
+static int evp_pkey_ctx_ctrl_str_int(EVP_PKEY_CTX *ctx,
+ const char *name, const char *value)
+{
+ int ret = 0;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return -2;
+ }
+
+ switch (evp_pkey_ctx_state(ctx)) {
+ case EVP_PKEY_STATE_PROVIDER:
+ return evp_pkey_ctx_ctrl_str_to_param(ctx, name, value);
+ case EVP_PKEY_STATE_UNKNOWN:
+ case EVP_PKEY_STATE_LEGACY:
+ if (ctx == NULL || ctx->pmeth == NULL || ctx->pmeth->ctrl_str == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return -2;
+ }
+ if (strcmp(name, "digest") == 0)
+ ret = EVP_PKEY_CTX_md(ctx,
+ EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_MD, value);
+ else
+ ret = ctx->pmeth->ctrl_str(ctx, name, value);
+ break;
+ }
+
+ return ret;
+}
+
int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx,
const char *name, const char *value)
{
- if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) {
- EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
+ int ret = 0;
+
+ /* If unsupported, we don't want that reported here */
+ ERR_set_mark();
+ ret = evp_pkey_ctx_store_cached_data(ctx, -1, -1, -1,
+ name, value, strlen(value) + 1);
+ if (ret == -2) {
+ ERR_pop_to_mark();
+ } else {
+ ERR_clear_last_mark();
+ /*
+ * If there was an error, there was an error.
+ * If the operation isn't initialized yet, we also return, as
+ * the saved values will be used then anyway.
+ */
+ if (ret < 1 || ctx->operation == EVP_PKEY_OP_UNDEFINED)
+ return ret;
+ }
+
+ return evp_pkey_ctx_ctrl_str_int(ctx, name, value);
+}
+
+static int decode_cmd(int cmd, const char *name)
+{
+ if (cmd == -1) {
+ /*
+ * The consequence of the assertion not being true is that this
+ * function will return -1, which will cause the calling functions
+ * to signal that the command is unsupported... in non-debug mode.
+ */
+ if (ossl_assert(name != NULL))
+ if (strcmp(name, "distid") == 0 || strcmp(name, "hexdistid") == 0)
+ cmd = EVP_PKEY_CTRL_SET1_ID;
+ }
+
+ return cmd;
+}
+
+static int evp_pkey_ctx_store_cached_data(EVP_PKEY_CTX *ctx,
+ int keytype, int optype,
+ int cmd, const char *name,
+ const void *data, size_t data_len)
+{
+ /*
+ * Check that it's one of the supported commands. The ctrl commands
+ * number cases here must correspond to the cases in the bottom switch
+ * in this function.
+ */
+ switch (cmd = decode_cmd(cmd, name)) {
+ case EVP_PKEY_CTRL_SET1_ID:
+ break;
+ default:
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
- if (strcmp(name, "digest") == 0)
- return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD,
- value);
- return ctx->pmeth->ctrl_str(ctx, name, value);
+
+ if (keytype != -1) {
+ switch (evp_pkey_ctx_state(ctx)) {
+ case EVP_PKEY_STATE_PROVIDER:
+ if (ctx->keymgmt == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return -2;
+ }
+ if (!EVP_KEYMGMT_is_a(ctx->keymgmt,
+ evp_pkey_type2name(keytype))) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
+ return -1;
+ }
+ break;
+ case EVP_PKEY_STATE_UNKNOWN:
+ case EVP_PKEY_STATE_LEGACY:
+ if (ctx->pmeth == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return -2;
+ }
+ if (EVP_PKEY_type(ctx->pmeth->pkey_id) != EVP_PKEY_type(keytype)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
+ return -1;
+ }
+ break;
+ }
+ }
+ if (optype != -1 && (ctx->operation & optype) == 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
+ return -1;
+ }
+
+ switch (cmd) {
+ case EVP_PKEY_CTRL_SET1_ID:
+ evp_pkey_ctx_free_cached_data(ctx, cmd, name);
+ if (name != NULL) {
+ ctx->cached_parameters.dist_id_name = OPENSSL_strdup(name);
+ if (ctx->cached_parameters.dist_id_name == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ if (data_len > 0) {
+ ctx->cached_parameters.dist_id = OPENSSL_memdup(data, data_len);
+ if (ctx->cached_parameters.dist_id == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ ctx->cached_parameters.dist_id_set = 1;
+ ctx->cached_parameters.dist_id_len = data_len;
+ break;
+ }
+ return 1;
+}
+
+static void evp_pkey_ctx_free_cached_data(EVP_PKEY_CTX *ctx,
+ int cmd, const char *name)
+{
+ cmd = decode_cmd(cmd, name);
+ switch (cmd) {
+ case EVP_PKEY_CTRL_SET1_ID:
+ OPENSSL_free(ctx->cached_parameters.dist_id);
+ OPENSSL_free(ctx->cached_parameters.dist_id_name);
+ ctx->cached_parameters.dist_id = NULL;
+ ctx->cached_parameters.dist_id_name = NULL;
+ break;
+ }
+}
+
+static void evp_pkey_ctx_free_all_cached_data(EVP_PKEY_CTX *ctx)
+{
+ evp_pkey_ctx_free_cached_data(ctx, EVP_PKEY_CTRL_SET1_ID, NULL);
+}
+
+int evp_pkey_ctx_use_cached_data(EVP_PKEY_CTX *ctx)
+{
+ int ret = 1;
+
+ if (ret && ctx->cached_parameters.dist_id_set) {
+ const char *name = ctx->cached_parameters.dist_id_name;
+ const void *val = ctx->cached_parameters.dist_id;
+ size_t len = ctx->cached_parameters.dist_id_len;
+
+ if (name != NULL)
+ ret = evp_pkey_ctx_ctrl_str_int(ctx, name, val);
+ else
+ ret = evp_pkey_ctx_ctrl_int(ctx, -1, ctx->operation,
+ EVP_PKEY_CTRL_SET1_ID,
+ (int)len, (void *)val);
+ }
+
+ return ret;
+}
+
+OSSL_LIB_CTX *EVP_PKEY_CTX_get0_libctx(EVP_PKEY_CTX *ctx)
+{
+ return ctx->libctx;
+}
+
+const char *EVP_PKEY_CTX_get0_propq(const EVP_PKEY_CTX *ctx)
+{
+ return ctx->propquery;
+}
+
+const OSSL_PROVIDER *EVP_PKEY_CTX_get0_provider(const EVP_PKEY_CTX *ctx)
+{
+ if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
+ if (ctx->op.sig.signature != NULL)
+ return EVP_SIGNATURE_get0_provider(ctx->op.sig.signature);
+ } else if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
+ if (ctx->op.kex.exchange != NULL)
+ return EVP_KEYEXCH_get0_provider(ctx->op.kex.exchange);
+ } else if (EVP_PKEY_CTX_IS_KEM_OP(ctx)) {
+ if (ctx->op.encap.kem != NULL)
+ return EVP_KEM_get0_provider(ctx->op.encap.kem);
+ } else if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)) {
+ if (ctx->op.ciph.cipher != NULL)
+ return EVP_ASYM_CIPHER_get0_provider(ctx->op.ciph.cipher);
+ } else if (EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
+ if (ctx->keymgmt != NULL)
+ return EVP_KEYMGMT_get0_provider(ctx->keymgmt);
+ }
+
+ return NULL;
}
/* Utility functions to send a string of hex string to a ctrl */
@@ -450,7 +1608,7 @@ int EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md)
const EVP_MD *m;
if (md == NULL || (m = EVP_get_digestbyname(md)) == NULL) {
- EVPerr(EVP_F_EVP_PKEY_CTX_MD, EVP_R_INVALID_DIGEST);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_DIGEST);
return 0;
}
return EVP_PKEY_CTX_ctrl(ctx, -1, optype, cmd, 0, (void *)m);
@@ -472,7 +1630,7 @@ void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data)
ctx->data = data;
}
-void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx)
+void *EVP_PKEY_CTX_get_data(const EVP_PKEY_CTX *ctx)
{
return ctx->data;
}
@@ -505,7 +1663,7 @@ void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth,
void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth,
int (*copy) (EVP_PKEY_CTX *dst,
- EVP_PKEY_CTX *src))
+ const EVP_PKEY_CTX *src))
{
pmeth->copy = copy;
}
@@ -690,7 +1848,7 @@ void EVP_PKEY_meth_get_init(const EVP_PKEY_METHOD *pmeth,
void EVP_PKEY_meth_get_copy(const EVP_PKEY_METHOD *pmeth,
int (**pcopy) (EVP_PKEY_CTX *dst,
- EVP_PKEY_CTX *src))
+ const EVP_PKEY_CTX *src))
{
*pcopy = pmeth->copy;
}
@@ -849,7 +2007,7 @@ void EVP_PKEY_meth_get_ctrl(const EVP_PKEY_METHOD *pmeth,
*pctrl_str = pmeth->ctrl_str;
}
-void EVP_PKEY_meth_get_digestsign(EVP_PKEY_METHOD *pmeth,
+void EVP_PKEY_meth_get_digestsign(const EVP_PKEY_METHOD *pmeth,
int (**digestsign) (EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen))
{
@@ -857,7 +2015,7 @@ void EVP_PKEY_meth_get_digestsign(EVP_PKEY_METHOD *pmeth,
*digestsign = pmeth->digestsign;
}
-void EVP_PKEY_meth_get_digestverify(EVP_PKEY_METHOD *pmeth,
+void EVP_PKEY_meth_get_digestverify(const EVP_PKEY_METHOD *pmeth,
int (**digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig,
size_t siglen, const unsigned char *tbs,
size_t tbslen))
@@ -887,10 +2045,12 @@ void EVP_PKEY_meth_get_param_check(const EVP_PKEY_METHOD *pmeth,
*pcheck = pmeth->param_check;
}
-void EVP_PKEY_meth_get_digest_custom(EVP_PKEY_METHOD *pmeth,
+void EVP_PKEY_meth_get_digest_custom(const EVP_PKEY_METHOD *pmeth,
int (**pdigest_custom) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx))
{
if (pdigest_custom != NULL)
*pdigest_custom = pmeth->digest_custom;
}
+
+#endif /* FIPS_MODULE */
diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c
new file mode 100644
index 000000000000..fb269b3bfd07
--- /dev/null
+++ b/crypto/evp/signature.c
@@ -0,0 +1,748 @@
+/*
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include "internal/numbers.h" /* includes SIZE_MAX */
+#include "internal/cryptlib.h"
+#include "internal/provider.h"
+#include "internal/core.h"
+#include "crypto/evp.h"
+#include "evp_local.h"
+
+static EVP_SIGNATURE *evp_signature_new(OSSL_PROVIDER *prov)
+{
+ EVP_SIGNATURE *signature = OPENSSL_zalloc(sizeof(EVP_SIGNATURE));
+
+ if (signature == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ signature->lock = CRYPTO_THREAD_lock_new();
+ if (signature->lock == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(signature);
+ return NULL;
+ }
+ signature->prov = prov;
+ ossl_provider_up_ref(prov);
+ signature->refcnt = 1;
+
+ return signature;
+}
+
+static void *evp_signature_from_algorithm(int name_id,
+ const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
+{
+ const OSSL_DISPATCH *fns = algodef->implementation;
+ EVP_SIGNATURE *signature = NULL;
+ int ctxfncnt = 0, signfncnt = 0, verifyfncnt = 0, verifyrecfncnt = 0;
+ int digsignfncnt = 0, digverifyfncnt = 0;
+ int gparamfncnt = 0, sparamfncnt = 0, gmdparamfncnt = 0, smdparamfncnt = 0;
+
+ if ((signature = evp_signature_new(prov)) == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ signature->name_id = name_id;
+ if ((signature->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL)
+ goto err;
+ signature->description = algodef->algorithm_description;
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_SIGNATURE_NEWCTX:
+ if (signature->newctx != NULL)
+ break;
+ signature->newctx = OSSL_FUNC_signature_newctx(fns);
+ ctxfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_SIGN_INIT:
+ if (signature->sign_init != NULL)
+ break;
+ signature->sign_init = OSSL_FUNC_signature_sign_init(fns);
+ signfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_SIGN:
+ if (signature->sign != NULL)
+ break;
+ signature->sign = OSSL_FUNC_signature_sign(fns);
+ signfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_VERIFY_INIT:
+ if (signature->verify_init != NULL)
+ break;
+ signature->verify_init = OSSL_FUNC_signature_verify_init(fns);
+ verifyfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_VERIFY:
+ if (signature->verify != NULL)
+ break;
+ signature->verify = OSSL_FUNC_signature_verify(fns);
+ verifyfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT:
+ if (signature->verify_recover_init != NULL)
+ break;
+ signature->verify_recover_init
+ = OSSL_FUNC_signature_verify_recover_init(fns);
+ verifyrecfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_VERIFY_RECOVER:
+ if (signature->verify_recover != NULL)
+ break;
+ signature->verify_recover
+ = OSSL_FUNC_signature_verify_recover(fns);
+ verifyrecfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT:
+ if (signature->digest_sign_init != NULL)
+ break;
+ signature->digest_sign_init
+ = OSSL_FUNC_signature_digest_sign_init(fns);
+ break;
+ case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE:
+ if (signature->digest_sign_update != NULL)
+ break;
+ signature->digest_sign_update
+ = OSSL_FUNC_signature_digest_sign_update(fns);
+ digsignfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL:
+ if (signature->digest_sign_final != NULL)
+ break;
+ signature->digest_sign_final
+ = OSSL_FUNC_signature_digest_sign_final(fns);
+ digsignfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_DIGEST_SIGN:
+ if (signature->digest_sign != NULL)
+ break;
+ signature->digest_sign
+ = OSSL_FUNC_signature_digest_sign(fns);
+ break;
+ case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT:
+ if (signature->digest_verify_init != NULL)
+ break;
+ signature->digest_verify_init
+ = OSSL_FUNC_signature_digest_verify_init(fns);
+ break;
+ case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE:
+ if (signature->digest_verify_update != NULL)
+ break;
+ signature->digest_verify_update
+ = OSSL_FUNC_signature_digest_verify_update(fns);
+ digverifyfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL:
+ if (signature->digest_verify_final != NULL)
+ break;
+ signature->digest_verify_final
+ = OSSL_FUNC_signature_digest_verify_final(fns);
+ digverifyfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY:
+ if (signature->digest_verify != NULL)
+ break;
+ signature->digest_verify
+ = OSSL_FUNC_signature_digest_verify(fns);
+ break;
+ case OSSL_FUNC_SIGNATURE_FREECTX:
+ if (signature->freectx != NULL)
+ break;
+ signature->freectx = OSSL_FUNC_signature_freectx(fns);
+ ctxfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_DUPCTX:
+ if (signature->dupctx != NULL)
+ break;
+ signature->dupctx = OSSL_FUNC_signature_dupctx(fns);
+ break;
+ case OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS:
+ if (signature->get_ctx_params != NULL)
+ break;
+ signature->get_ctx_params
+ = OSSL_FUNC_signature_get_ctx_params(fns);
+ gparamfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS:
+ if (signature->gettable_ctx_params != NULL)
+ break;
+ signature->gettable_ctx_params
+ = OSSL_FUNC_signature_gettable_ctx_params(fns);
+ gparamfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS:
+ if (signature->set_ctx_params != NULL)
+ break;
+ signature->set_ctx_params
+ = OSSL_FUNC_signature_set_ctx_params(fns);
+ sparamfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS:
+ if (signature->settable_ctx_params != NULL)
+ break;
+ signature->settable_ctx_params
+ = OSSL_FUNC_signature_settable_ctx_params(fns);
+ sparamfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS:
+ if (signature->get_ctx_md_params != NULL)
+ break;
+ signature->get_ctx_md_params
+ = OSSL_FUNC_signature_get_ctx_md_params(fns);
+ gmdparamfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS:
+ if (signature->gettable_ctx_md_params != NULL)
+ break;
+ signature->gettable_ctx_md_params
+ = OSSL_FUNC_signature_gettable_ctx_md_params(fns);
+ gmdparamfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS:
+ if (signature->set_ctx_md_params != NULL)
+ break;
+ signature->set_ctx_md_params
+ = OSSL_FUNC_signature_set_ctx_md_params(fns);
+ smdparamfncnt++;
+ break;
+ case OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS:
+ if (signature->settable_ctx_md_params != NULL)
+ break;
+ signature->settable_ctx_md_params
+ = OSSL_FUNC_signature_settable_ctx_md_params(fns);
+ smdparamfncnt++;
+ break;
+ }
+ }
+ if (ctxfncnt != 2
+ || (signfncnt == 0
+ && verifyfncnt == 0
+ && verifyrecfncnt == 0
+ && digsignfncnt == 0
+ && digverifyfncnt == 0
+ && signature->digest_sign == NULL
+ && signature->digest_verify == NULL)
+ || (signfncnt != 0 && signfncnt != 2)
+ || (verifyfncnt != 0 && verifyfncnt != 2)
+ || (verifyrecfncnt != 0 && verifyrecfncnt != 2)
+ || (digsignfncnt != 0 && digsignfncnt != 2)
+ || (digsignfncnt == 2 && signature->digest_sign_init == NULL)
+ || (digverifyfncnt != 0 && digverifyfncnt != 2)
+ || (digverifyfncnt == 2 && signature->digest_verify_init == NULL)
+ || (signature->digest_sign != NULL
+ && signature->digest_sign_init == NULL)
+ || (signature->digest_verify != NULL
+ && signature->digest_verify_init == NULL)
+ || (gparamfncnt != 0 && gparamfncnt != 2)
+ || (sparamfncnt != 0 && sparamfncnt != 2)
+ || (gmdparamfncnt != 0 && gmdparamfncnt != 2)
+ || (smdparamfncnt != 0 && smdparamfncnt != 2)) {
+ /*
+ * In order to be a consistent set of functions we must have at least
+ * a set of context functions (newctx and freectx) as well as a set of
+ * "signature" functions:
+ * (sign_init, sign) or
+ * (verify_init verify) or
+ * (verify_recover_init, verify_recover) or
+ * (digest_sign_init, digest_sign_update, digest_sign_final) or
+ * (digest_verify_init, digest_verify_update, digest_verify_final) or
+ * (digest_sign_init, digest_sign) or
+ * (digest_verify_init, digest_verify).
+ *
+ * set_ctx_params and settable_ctx_params are optional, but if one of
+ * them is present then the other one must also be present. The same
+ * applies to get_ctx_params and gettable_ctx_params. The same rules
+ * apply to the "md_params" functions. The dupctx function is optional.
+ */
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+ goto err;
+ }
+
+ return signature;
+ err:
+ EVP_SIGNATURE_free(signature);
+ return NULL;
+}
+
+void EVP_SIGNATURE_free(EVP_SIGNATURE *signature)
+{
+ int i;
+
+ if (signature == NULL)
+ return;
+ CRYPTO_DOWN_REF(&signature->refcnt, &i, signature->lock);
+ if (i > 0)
+ return;
+ OPENSSL_free(signature->type_name);
+ ossl_provider_free(signature->prov);
+ CRYPTO_THREAD_lock_free(signature->lock);
+ OPENSSL_free(signature);
+}
+
+int EVP_SIGNATURE_up_ref(EVP_SIGNATURE *signature)
+{
+ int ref = 0;
+
+ CRYPTO_UP_REF(&signature->refcnt, &ref, signature->lock);
+ return 1;
+}
+
+OSSL_PROVIDER *EVP_SIGNATURE_get0_provider(const EVP_SIGNATURE *signature)
+{
+ return signature->prov;
+}
+
+EVP_SIGNATURE *EVP_SIGNATURE_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties)
+{
+ return evp_generic_fetch(ctx, OSSL_OP_SIGNATURE, algorithm, properties,
+ evp_signature_from_algorithm,
+ (int (*)(void *))EVP_SIGNATURE_up_ref,
+ (void (*)(void *))EVP_SIGNATURE_free);
+}
+
+EVP_SIGNATURE *evp_signature_fetch_from_prov(OSSL_PROVIDER *prov,
+ const char *algorithm,
+ const char *properties)
+{
+ return evp_generic_fetch_from_prov(prov, OSSL_OP_SIGNATURE,
+ algorithm, properties,
+ evp_signature_from_algorithm,
+ (int (*)(void *))EVP_SIGNATURE_up_ref,
+ (void (*)(void *))EVP_SIGNATURE_free);
+}
+
+int EVP_SIGNATURE_is_a(const EVP_SIGNATURE *signature, const char *name)
+{
+ return signature != NULL
+ && evp_is_a(signature->prov, signature->name_id, NULL, name);
+}
+
+int evp_signature_get_number(const EVP_SIGNATURE *signature)
+{
+ return signature->name_id;
+}
+
+const char *EVP_SIGNATURE_get0_name(const EVP_SIGNATURE *signature)
+{
+ return signature->type_name;
+}
+
+const char *EVP_SIGNATURE_get0_description(const EVP_SIGNATURE *signature)
+{
+ return signature->description;
+}
+
+void EVP_SIGNATURE_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_SIGNATURE *signature,
+ void *arg),
+ void *arg)
+{
+ evp_generic_do_all(libctx, OSSL_OP_SIGNATURE,
+ (void (*)(void *, void *))fn, arg,
+ evp_signature_from_algorithm,
+ (int (*)(void *))EVP_SIGNATURE_up_ref,
+ (void (*)(void *))EVP_SIGNATURE_free);
+}
+
+
+int EVP_SIGNATURE_names_do_all(const EVP_SIGNATURE *signature,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (signature->prov != NULL)
+ return evp_names_do_all(signature->prov, signature->name_id, fn, data);
+
+ return 1;
+}
+
+const OSSL_PARAM *EVP_SIGNATURE_gettable_ctx_params(const EVP_SIGNATURE *sig)
+{
+ void *provctx;
+
+ if (sig == NULL || sig->gettable_ctx_params == NULL)
+ return NULL;
+
+ provctx = ossl_provider_ctx(EVP_SIGNATURE_get0_provider(sig));
+ return sig->gettable_ctx_params(NULL, provctx);
+}
+
+const OSSL_PARAM *EVP_SIGNATURE_settable_ctx_params(const EVP_SIGNATURE *sig)
+{
+ void *provctx;
+
+ if (sig == NULL || sig->settable_ctx_params == NULL)
+ return NULL;
+
+ provctx = ossl_provider_ctx(EVP_SIGNATURE_get0_provider(sig));
+ return sig->settable_ctx_params(NULL, provctx);
+}
+
+static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation,
+ const OSSL_PARAM params[])
+{
+ int ret = 0;
+ void *provkey = NULL;
+ EVP_SIGNATURE *signature = NULL;
+ EVP_KEYMGMT *tmp_keymgmt = NULL;
+ const OSSL_PROVIDER *tmp_prov = NULL;
+ const char *supported_sig = NULL;
+ int iter;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ evp_pkey_ctx_free_old_ops(ctx);
+ ctx->operation = operation;
+
+ ERR_set_mark();
+
+ if (evp_pkey_ctx_is_legacy(ctx))
+ goto legacy;
+
+ if (ctx->pkey == NULL) {
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET);
+ goto err;
+ }
+
+ /*
+ * Try to derive the supported signature from |ctx->keymgmt|.
+ */
+ if (!ossl_assert(ctx->pkey->keymgmt == NULL
+ || ctx->pkey->keymgmt == ctx->keymgmt)) {
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ supported_sig = evp_keymgmt_util_query_operation_name(ctx->keymgmt,
+ OSSL_OP_SIGNATURE);
+ if (supported_sig == NULL) {
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+
+ /*
+ * We perform two iterations:
+ *
+ * 1. Do the normal signature fetch, using the fetching data given by
+ * the EVP_PKEY_CTX.
+ * 2. Do the provider specific signature fetch, from the same provider
+ * as |ctx->keymgmt|
+ *
+ * We then try to fetch the keymgmt from the same provider as the
+ * signature, and try to export |ctx->pkey| to that keymgmt (when
+ * this keymgmt happens to be the same as |ctx->keymgmt|, the export
+ * is a no-op, but we call it anyway to not complicate the code even
+ * more).
+ * If the export call succeeds (returns a non-NULL provider key pointer),
+ * we're done and can perform the operation itself. If not, we perform
+ * the second iteration, or jump to legacy.
+ */
+ for (iter = 1; iter < 3 && provkey == NULL; iter++) {
+ EVP_KEYMGMT *tmp_keymgmt_tofree = NULL;
+
+ /*
+ * If we're on the second iteration, free the results from the first.
+ * They are NULL on the first iteration, so no need to check what
+ * iteration we're on.
+ */
+ EVP_SIGNATURE_free(signature);
+ EVP_KEYMGMT_free(tmp_keymgmt);
+
+ switch (iter) {
+ case 1:
+ signature =
+ EVP_SIGNATURE_fetch(ctx->libctx, supported_sig, ctx->propquery);
+ if (signature != NULL)
+ tmp_prov = EVP_SIGNATURE_get0_provider(signature);
+ break;
+ case 2:
+ tmp_prov = EVP_KEYMGMT_get0_provider(ctx->keymgmt);
+ signature =
+ evp_signature_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
+ supported_sig, ctx->propquery);
+ if (signature == NULL)
+ goto legacy;
+ break;
+ }
+ if (signature == NULL)
+ continue;
+
+ /*
+ * Ensure that the key is provided, either natively, or as a cached
+ * export. We start by fetching the keymgmt with the same name as
+ * |ctx->pkey|, but from the provider of the signature method, using
+ * the same property query as when fetching the signature method.
+ * With the keymgmt we found (if we did), we try to export |ctx->pkey|
+ * to it (evp_pkey_export_to_provider() is smart enough to only actually
+
+ * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt)
+ */
+ tmp_keymgmt_tofree = tmp_keymgmt =
+ evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
+ EVP_KEYMGMT_get0_name(ctx->keymgmt),
+ ctx->propquery);
+ if (tmp_keymgmt != NULL)
+ provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
+ &tmp_keymgmt, ctx->propquery);
+ if (tmp_keymgmt == NULL)
+ EVP_KEYMGMT_free(tmp_keymgmt_tofree);
+ }
+
+ if (provkey == NULL) {
+ EVP_SIGNATURE_free(signature);
+ goto legacy;
+ }
+
+ ERR_pop_to_mark();
+
+ /* No more legacy from here down to legacy: */
+
+ ctx->op.sig.signature = signature;
+ ctx->op.sig.algctx =
+ signature->newctx(ossl_provider_ctx(signature->prov), ctx->propquery);
+ if (ctx->op.sig.algctx == NULL) {
+ /* The provider key can stay in the cache */
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+
+ switch (operation) {
+ case EVP_PKEY_OP_SIGN:
+ if (signature->sign_init == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ ret = -2;
+ goto err;
+ }
+ ret = signature->sign_init(ctx->op.sig.algctx, provkey, params);
+ break;
+ case EVP_PKEY_OP_VERIFY:
+ if (signature->verify_init == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ ret = -2;
+ goto err;
+ }
+ ret = signature->verify_init(ctx->op.sig.algctx, provkey, params);
+ break;
+ case EVP_PKEY_OP_VERIFYRECOVER:
+ if (signature->verify_recover_init == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ ret = -2;
+ goto err;
+ }
+ ret = signature->verify_recover_init(ctx->op.sig.algctx, provkey,
+ params);
+ break;
+ default:
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+
+ if (ret <= 0) {
+ signature->freectx(ctx->op.sig.algctx);
+ ctx->op.sig.algctx = NULL;
+ goto err;
+ }
+ goto end;
+
+ legacy:
+ /*
+ * If we don't have the full support we need with provided methods,
+ * let's go see if legacy does.
+ */
+ ERR_pop_to_mark();
+ EVP_KEYMGMT_free(tmp_keymgmt);
+ tmp_keymgmt = NULL;
+
+ if (ctx->pmeth == NULL
+ || (operation == EVP_PKEY_OP_SIGN && ctx->pmeth->sign == NULL)
+ || (operation == EVP_PKEY_OP_VERIFY && ctx->pmeth->verify == NULL)
+ || (operation == EVP_PKEY_OP_VERIFYRECOVER
+ && ctx->pmeth->verify_recover == NULL)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ switch (operation) {
+ case EVP_PKEY_OP_SIGN:
+ if (ctx->pmeth->sign_init == NULL)
+ return 1;
+ ret = ctx->pmeth->sign_init(ctx);
+ break;
+ case EVP_PKEY_OP_VERIFY:
+ if (ctx->pmeth->verify_init == NULL)
+ return 1;
+ ret = ctx->pmeth->verify_init(ctx);
+ break;
+ case EVP_PKEY_OP_VERIFYRECOVER:
+ if (ctx->pmeth->verify_recover_init == NULL)
+ return 1;
+ ret = ctx->pmeth->verify_recover_init(ctx);
+ break;
+ default:
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+ if (ret <= 0)
+ goto err;
+ end:
+#ifndef FIPS_MODULE
+ if (ret > 0)
+ ret = evp_pkey_ctx_use_cached_data(ctx);
+#endif
+
+ EVP_KEYMGMT_free(tmp_keymgmt);
+ return ret;
+ err:
+ evp_pkey_ctx_free_old_ops(ctx);
+ ctx->operation = EVP_PKEY_OP_UNDEFINED;
+ EVP_KEYMGMT_free(tmp_keymgmt);
+ return ret;
+}
+
+int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx)
+{
+ return evp_pkey_signature_init(ctx, EVP_PKEY_OP_SIGN, NULL);
+}
+
+int EVP_PKEY_sign_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
+{
+ return evp_pkey_signature_init(ctx, EVP_PKEY_OP_SIGN, params);
+}
+
+int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
+ unsigned char *sig, size_t *siglen,
+ const unsigned char *tbs, size_t tbslen)
+{
+ int ret;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ if (ctx->operation != EVP_PKEY_OP_SIGN) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
+ return -1;
+ }
+
+ if (ctx->op.sig.algctx == NULL)
+ goto legacy;
+
+ ret = ctx->op.sig.signature->sign(ctx->op.sig.algctx, sig, siglen,
+ (sig == NULL) ? 0 : *siglen, tbs, tbslen);
+
+ return ret;
+ legacy:
+
+ if (ctx->pmeth == NULL || ctx->pmeth->sign == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ M_check_autoarg(ctx, sig, siglen, EVP_F_EVP_PKEY_SIGN)
+ return ctx->pmeth->sign(ctx, sig, siglen, tbs, tbslen);
+}
+
+int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx)
+{
+ return evp_pkey_signature_init(ctx, EVP_PKEY_OP_VERIFY, NULL);
+}
+
+int EVP_PKEY_verify_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
+{
+ return evp_pkey_signature_init(ctx, EVP_PKEY_OP_VERIFY, params);
+}
+
+int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
+ const unsigned char *sig, size_t siglen,
+ const unsigned char *tbs, size_t tbslen)
+{
+ int ret;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ if (ctx->operation != EVP_PKEY_OP_VERIFY) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
+ return -1;
+ }
+
+ if (ctx->op.sig.algctx == NULL)
+ goto legacy;
+
+ ret = ctx->op.sig.signature->verify(ctx->op.sig.algctx, sig, siglen,
+ tbs, tbslen);
+
+ return ret;
+ legacy:
+ if (ctx->pmeth == NULL || ctx->pmeth->verify == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ return ctx->pmeth->verify(ctx, sig, siglen, tbs, tbslen);
+}
+
+int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx)
+{
+ return evp_pkey_signature_init(ctx, EVP_PKEY_OP_VERIFYRECOVER, NULL);
+}
+
+int EVP_PKEY_verify_recover_init_ex(EVP_PKEY_CTX *ctx,
+ const OSSL_PARAM params[])
+{
+ return evp_pkey_signature_init(ctx, EVP_PKEY_OP_VERIFYRECOVER, params);
+}
+
+int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx,
+ unsigned char *rout, size_t *routlen,
+ const unsigned char *sig, size_t siglen)
+{
+ int ret;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
+ return -1;
+ }
+
+ if (ctx->op.sig.algctx == NULL)
+ goto legacy;
+
+ ret = ctx->op.sig.signature->verify_recover(ctx->op.sig.algctx, rout,
+ routlen,
+ (rout == NULL ? 0 : *routlen),
+ sig, siglen);
+ return ret;
+ legacy:
+ if (ctx->pmeth == NULL || ctx->pmeth->verify_recover == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+ M_check_autoarg(ctx, rout, routlen, EVP_F_EVP_PKEY_VERIFY_RECOVER)
+ return ctx->pmeth->verify_recover(ctx, rout, routlen, sig, siglen);
+}
diff --git a/crypto/ex_data.c b/crypto/ex_data.c
index 0f5a9295056a..40223f06e4ec 100644
--- a/crypto/ex_data.c
+++ b/crypto/ex_data.c
@@ -1,81 +1,52 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#include <stdlib.h>
#include "crypto/cryptlib.h"
#include "internal/thread_once.h"
-/*
- * Each structure type (sometimes called a class), that supports
- * exdata has a stack of callbacks for each instance.
- */
-struct ex_callback_st {
- long argl; /* Arbitrary long */
- void *argp; /* Arbitrary void * */
- CRYPTO_EX_new *new_func;
- CRYPTO_EX_free *free_func;
- CRYPTO_EX_dup *dup_func;
-};
-
-/*
- * The state for each class. This could just be a typedef, but
- * a structure allows future changes.
- */
-typedef struct ex_callbacks_st {
- STACK_OF(EX_CALLBACK) *meth;
-} EX_CALLBACKS;
-
-static EX_CALLBACKS ex_data[CRYPTO_EX_INDEX__COUNT];
-
-static CRYPTO_RWLOCK *ex_data_lock = NULL;
-static CRYPTO_ONCE ex_data_init = CRYPTO_ONCE_STATIC_INIT;
-
-DEFINE_RUN_ONCE_STATIC(do_ex_data_init)
+int ossl_do_ex_data_init(OSSL_LIB_CTX *ctx)
{
- if (!OPENSSL_init_crypto(0, NULL))
+ OSSL_EX_DATA_GLOBAL *global = ossl_lib_ctx_get_ex_data_global(ctx);
+
+ if (global == NULL)
return 0;
- ex_data_lock = CRYPTO_THREAD_lock_new();
- return ex_data_lock != NULL;
+
+ global->ex_data_lock = CRYPTO_THREAD_lock_new();
+ return global->ex_data_lock != NULL;
}
/*
* Return the EX_CALLBACKS from the |ex_data| array that corresponds to
* a given class. On success, *holds the lock.*
+ * The |global| parameter is assumed to be non null (checked by the caller).
*/
-static EX_CALLBACKS *get_and_lock(int class_index)
+static EX_CALLBACKS *get_and_lock(OSSL_EX_DATA_GLOBAL *global, int class_index)
{
EX_CALLBACKS *ip;
if (class_index < 0 || class_index >= CRYPTO_EX_INDEX__COUNT) {
- CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_PASSED_INVALID_ARGUMENT);
- return NULL;
- }
-
- if (!RUN_ONCE(&ex_data_init, do_ex_data_init)) {
- CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
return NULL;
}
- if (ex_data_lock == NULL) {
+ if (global->ex_data_lock == NULL) {
/*
- * This can happen in normal operation when using CRYPTO_mem_leaks().
- * The CRYPTO_mem_leaks() function calls OPENSSL_cleanup() which cleans
- * up the locks. Subsequently the BIO that CRYPTO_mem_leaks() uses gets
- * freed, which also attempts to free the ex_data. However
- * CRYPTO_mem_leaks() ensures that the ex_data is freed early (i.e.
- * before OPENSSL_cleanup() is called), so if we get here we can safely
- * ignore this operation. We just treat it as an error.
+ * If we get here, someone (who?) cleaned up the lock, so just
+ * treat it as an error.
*/
return NULL;
}
- ip = &ex_data[class_index];
- CRYPTO_THREAD_write_lock(ex_data_lock);
+ if (!CRYPTO_THREAD_write_lock(global->ex_data_lock))
+ return NULL;
+ ip = &global->ex_data[class_index];
return ip;
}
@@ -90,19 +61,23 @@ static void cleanup_cb(EX_CALLBACK *funcs)
* called under potential race-conditions anyway (it's for program shutdown
* after all).
*/
-void crypto_cleanup_all_ex_data_int(void)
+void ossl_crypto_cleanup_all_ex_data_int(OSSL_LIB_CTX *ctx)
{
int i;
+ OSSL_EX_DATA_GLOBAL *global = ossl_lib_ctx_get_ex_data_global(ctx);
+
+ if (global == NULL)
+ return;
for (i = 0; i < CRYPTO_EX_INDEX__COUNT; ++i) {
- EX_CALLBACKS *ip = &ex_data[i];
+ EX_CALLBACKS *ip = &global->ex_data[i];
sk_EX_CALLBACK_pop_free(ip->meth, cleanup_cb);
ip->meth = NULL;
}
- CRYPTO_THREAD_lock_free(ex_data_lock);
- ex_data_lock = NULL;
+ CRYPTO_THREAD_lock_free(global->ex_data_lock);
+ global->ex_data_lock = NULL;
}
@@ -121,20 +96,26 @@ static void dummy_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx,
}
static int dummy_dup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from,
- void *from_d, int idx,
+ void **from_d, int idx,
long argl, void *argp)
{
return 1;
}
-int CRYPTO_free_ex_index(int class_index, int idx)
+int ossl_crypto_free_ex_index_ex(OSSL_LIB_CTX *ctx, int class_index, int idx)
{
- EX_CALLBACKS *ip = get_and_lock(class_index);
+ EX_CALLBACKS *ip;
EX_CALLBACK *a;
int toret = 0;
+ OSSL_EX_DATA_GLOBAL *global = ossl_lib_ctx_get_ex_data_global(ctx);
+
+ if (global == NULL)
+ return 0;
+ ip = get_and_lock(global, class_index);
if (ip == NULL)
return 0;
+
if (idx < 0 || idx >= sk_EX_CALLBACK_num(ip->meth))
goto err;
a = sk_EX_CALLBACK_value(ip->meth, idx);
@@ -145,21 +126,34 @@ int CRYPTO_free_ex_index(int class_index, int idx)
a->free_func = dummy_free;
toret = 1;
err:
- CRYPTO_THREAD_unlock(ex_data_lock);
+ CRYPTO_THREAD_unlock(global->ex_data_lock);
return toret;
}
+int CRYPTO_free_ex_index(int class_index, int idx)
+{
+ return ossl_crypto_free_ex_index_ex(NULL, class_index, idx);
+}
+
/*
* Register a new index.
*/
-int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
- CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
- CRYPTO_EX_free *free_func)
+int ossl_crypto_get_ex_new_index_ex(OSSL_LIB_CTX *ctx, int class_index,
+ long argl, void *argp,
+ CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func,
+ CRYPTO_EX_free *free_func,
+ int priority)
{
int toret = -1;
EX_CALLBACK *a;
- EX_CALLBACKS *ip = get_and_lock(class_index);
+ EX_CALLBACKS *ip;
+ OSSL_EX_DATA_GLOBAL *global = ossl_lib_ctx_get_ex_data_global(ctx);
+ if (global == NULL)
+ return -1;
+
+ ip = get_and_lock(global, class_index);
if (ip == NULL)
return -1;
@@ -169,14 +163,14 @@ int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
* "app_data" routines use ex_data index zero. See RT 3710. */
if (ip->meth == NULL
|| !sk_EX_CALLBACK_push(ip->meth, NULL)) {
- CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
goto err;
}
}
a = (EX_CALLBACK *)OPENSSL_malloc(sizeof(*a));
if (a == NULL) {
- CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
goto err;
}
a->argl = argl;
@@ -184,9 +178,10 @@ int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
a->new_func = new_func;
a->dup_func = dup_func;
a->free_func = free_func;
+ a->priority = priority;
if (!sk_EX_CALLBACK_push(ip->meth, NULL)) {
- CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
OPENSSL_free(a);
goto err;
}
@@ -194,10 +189,18 @@ int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
(void)sk_EX_CALLBACK_set(ip->meth, toret, a);
err:
- CRYPTO_THREAD_unlock(ex_data_lock);
+ CRYPTO_THREAD_unlock(global->ex_data_lock);
return toret;
}
+int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
+ CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
+ CRYPTO_EX_free *free_func)
+{
+ return ossl_crypto_get_ex_new_index_ex(NULL, class_index, argl, argp,
+ new_func, dup_func, free_func, 0);
+}
+
/*
* Initialise a new CRYPTO_EX_DATA for use in a particular class - including
* calling new() callbacks for each index in the class used by this variable
@@ -205,19 +208,25 @@ int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
* in the lock, then using them outside the lock. Note this only applies
* to the global "ex_data" state (ie. class definitions), not 'ad' itself.
*/
-int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
+int ossl_crypto_new_ex_data_ex(OSSL_LIB_CTX *ctx, int class_index, void *obj,
+ CRYPTO_EX_DATA *ad)
{
int mx, i;
void *ptr;
EX_CALLBACK **storage = NULL;
EX_CALLBACK *stack[10];
- EX_CALLBACKS *ip = get_and_lock(class_index);
+ EX_CALLBACKS *ip;
+ OSSL_EX_DATA_GLOBAL *global = ossl_lib_ctx_get_ex_data_global(ctx);
+ if (global == NULL)
+ return 0;
+
+ ip = get_and_lock(global, class_index);
if (ip == NULL)
return 0;
+ ad->ctx = ctx;
ad->sk = NULL;
-
mx = sk_EX_CALLBACK_num(ip->meth);
if (mx > 0) {
if (mx < (int)OSSL_NELEM(stack))
@@ -228,10 +237,10 @@ int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
for (i = 0; i < mx; i++)
storage[i] = sk_EX_CALLBACK_value(ip->meth, i);
}
- CRYPTO_THREAD_unlock(ex_data_lock);
+ CRYPTO_THREAD_unlock(global->ex_data_lock);
if (mx > 0 && storage == NULL) {
- CRYPTOerr(CRYPTO_F_CRYPTO_NEW_EX_DATA, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return 0;
}
for (i = 0; i < mx; i++) {
@@ -246,6 +255,11 @@ int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
return 1;
}
+int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
+{
+ return ossl_crypto_new_ex_data_ex(NULL, class_index, obj, ad);
+}
+
/*
* Duplicate a CRYPTO_EX_DATA variable - including calling dup() callbacks
* for each index in the class used by this variable
@@ -259,11 +273,19 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
EX_CALLBACK **storage = NULL;
EX_CALLBACKS *ip;
int toret = 0;
+ OSSL_EX_DATA_GLOBAL *global;
+ to->ctx = from->ctx;
if (from->sk == NULL)
/* Nothing to copy over */
return 1;
- if ((ip = get_and_lock(class_index)) == NULL)
+
+ global = ossl_lib_ctx_get_ex_data_global(from->ctx);
+ if (global == NULL)
+ return 0;
+
+ ip = get_and_lock(global, class_index);
+ if (ip == NULL)
return 0;
mx = sk_EX_CALLBACK_num(ip->meth);
@@ -279,12 +301,12 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
for (i = 0; i < mx; i++)
storage[i] = sk_EX_CALLBACK_value(ip->meth, i);
}
- CRYPTO_THREAD_unlock(ex_data_lock);
+ CRYPTO_THREAD_unlock(global->ex_data_lock);
if (mx == 0)
return 1;
if (storage == NULL) {
- CRYPTOerr(CRYPTO_F_CRYPTO_DUP_EX_DATA, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return 0;
}
/*
@@ -312,6 +334,27 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
return toret;
}
+struct ex_callback_entry {
+ const EX_CALLBACK *excb;
+ int index;
+};
+
+static int ex_callback_compare(const void *a, const void *b)
+{
+ const struct ex_callback_entry *ap = (const struct ex_callback_entry *)a;
+ const struct ex_callback_entry *bp = (const struct ex_callback_entry *)b;
+
+ if (ap->excb == bp->excb)
+ return 0;
+
+ if (ap->excb == NULL)
+ return 1;
+ if (bp->excb == NULL)
+ return -1;
+ if (ap->excb->priority == bp->excb->priority)
+ return 0;
+ return ap->excb->priority > bp->excb->priority ? -1 : 1;
+}
/*
* Cleanup a CRYPTO_EX_DATA variable - including calling free() callbacks for
@@ -322,11 +365,16 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
int mx, i;
EX_CALLBACKS *ip;
void *ptr;
- EX_CALLBACK *f;
- EX_CALLBACK *stack[10];
- EX_CALLBACK **storage = NULL;
+ const EX_CALLBACK *f;
+ struct ex_callback_entry stack[10];
+ struct ex_callback_entry *storage = NULL;
+ OSSL_EX_DATA_GLOBAL *global = ossl_lib_ctx_get_ex_data_global(ad->ctx);
+
+ if (global == NULL)
+ goto err;
- if ((ip = get_and_lock(class_index)) == NULL)
+ ip = get_and_lock(global, class_index);
+ if (ip == NULL)
goto err;
mx = sk_EX_CALLBACK_num(ip->meth);
@@ -336,22 +384,23 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
else
storage = OPENSSL_malloc(sizeof(*storage) * mx);
if (storage != NULL)
- for (i = 0; i < mx; i++)
- storage[i] = sk_EX_CALLBACK_value(ip->meth, i);
+ for (i = 0; i < mx; i++) {
+ storage[i].excb = sk_EX_CALLBACK_value(ip->meth, i);
+ storage[i].index = i;
+ }
}
- CRYPTO_THREAD_unlock(ex_data_lock);
-
- for (i = 0; i < mx; i++) {
- if (storage != NULL)
- f = storage[i];
- else {
- CRYPTO_THREAD_write_lock(ex_data_lock);
- f = sk_EX_CALLBACK_value(ip->meth, i);
- CRYPTO_THREAD_unlock(ex_data_lock);
- }
- if (f != NULL && f->free_func != NULL) {
- ptr = CRYPTO_get_ex_data(ad, i);
- f->free_func(obj, ptr, ad, i, f->argl, f->argp);
+ CRYPTO_THREAD_unlock(global->ex_data_lock);
+
+ if (storage != NULL) {
+ /* Sort according to priority. High priority first */
+ qsort(storage, mx, sizeof(*storage), ex_callback_compare);
+ for (i = 0; i < mx; i++) {
+ f = storage[i].excb;
+
+ if (f != NULL && f->free_func != NULL) {
+ ptr = CRYPTO_get_ex_data(ad, storage[i].index);
+ f->free_func(obj, ptr, ad, storage[i].index, f->argl, f->argp);
+ }
}
}
@@ -360,6 +409,53 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
err:
sk_void_free(ad->sk);
ad->sk = NULL;
+ ad->ctx = NULL;
+}
+
+/*
+ * Allocate a given CRYPTO_EX_DATA item using the class specific allocation
+ * function
+ */
+int CRYPTO_alloc_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad,
+ int idx)
+{
+ void *curval;
+
+ curval = CRYPTO_get_ex_data(ad, idx);
+ /* Already there, no need to allocate */
+ if (curval != NULL)
+ return 1;
+
+ return ossl_crypto_alloc_ex_data_intern(class_index, obj, ad, idx);
+}
+
+int ossl_crypto_alloc_ex_data_intern(int class_index, void *obj,
+ CRYPTO_EX_DATA *ad, int idx)
+{
+ EX_CALLBACK *f;
+ EX_CALLBACKS *ip;
+ OSSL_EX_DATA_GLOBAL *global;
+
+ global = ossl_lib_ctx_get_ex_data_global(ad->ctx);
+ if (global == NULL)
+ return 0;
+
+ ip = get_and_lock(global, class_index);
+ if (ip == NULL)
+ return 0;
+ f = sk_EX_CALLBACK_value(ip->meth, idx);
+ CRYPTO_THREAD_unlock(global->ex_data_lock);
+
+ /*
+ * This should end up calling CRYPTO_set_ex_data(), which allocates
+ * everything necessary to support placing the new data in the right spot.
+ */
+ if (f->new_func == NULL)
+ return 0;
+
+ f->new_func(obj, NULL, ad, idx, f->argl, f->argp);
+
+ return 1;
}
/*
@@ -372,18 +468,22 @@ int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val)
if (ad->sk == NULL) {
if ((ad->sk = sk_void_new_null()) == NULL) {
- CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return 0;
}
}
for (i = sk_void_num(ad->sk); i <= idx; ++i) {
if (!sk_void_push(ad->sk, NULL)) {
- CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return 0;
}
}
- sk_void_set(ad->sk, idx, val);
+ if (sk_void_set(ad->sk, idx, val) != val) {
+ /* Probably the index is out of bounds */
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
return 1;
}
@@ -397,3 +497,8 @@ void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx)
return NULL;
return sk_void_value(ad->sk, idx);
}
+
+OSSL_LIB_CTX *ossl_crypto_ex_data_get_ossl_lib_ctx(const CRYPTO_EX_DATA *ad)
+{
+ return ad->ctx;
+}
diff --git a/crypto/ffc/build.info b/crypto/ffc/build.info
new file mode 100644
index 000000000000..61cca17c5fe8
--- /dev/null
+++ b/crypto/ffc/build.info
@@ -0,0 +1,8 @@
+LIBS=../../libcrypto
+
+$COMMON=ffc_params.c ffc_params_generate.c ffc_key_generate.c \
+ ffc_params_validate.c ffc_key_validate.c ffc_backend.c \
+ ffc_dh.c
+
+SOURCE[../../libcrypto]=$COMMON
+SOURCE[../../providers/libfips.a]=$COMMON
diff --git a/crypto/ffc/ffc_backend.c b/crypto/ffc/ffc_backend.c
new file mode 100644
index 000000000000..dbd28b0e66bd
--- /dev/null
+++ b/crypto/ffc/ffc_backend.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_names.h>
+#include "internal/ffc.h"
+#include "internal/sizes.h"
+
+/*
+ * The intention with the "backend" source file is to offer backend support
+ * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
+ * implementations alike.
+ */
+
+int ossl_ffc_params_fromdata(FFC_PARAMS *ffc, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *prm;
+ const OSSL_PARAM *param_p, *param_q, *param_g;
+ BIGNUM *p = NULL, *q = NULL, *g = NULL, *j = NULL;
+ int i;
+
+ if (ffc == NULL)
+ return 0;
+
+ prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
+ if (prm != NULL) {
+ /*
+ * In a no-dh build we just go straight to err because we have no
+ * support for this.
+ */
+#ifndef OPENSSL_NO_DH
+ const DH_NAMED_GROUP *group = NULL;
+
+ if (prm->data_type != OSSL_PARAM_UTF8_STRING
+ || prm->data == NULL
+ || (group = ossl_ffc_name_to_dh_named_group(prm->data)) == NULL
+ || !ossl_ffc_named_group_set(ffc, group))
+#endif
+ goto err;
+ }
+
+ param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P);
+ param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G);
+ param_q = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_Q);
+
+ if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p))
+ || (param_q != NULL && !OSSL_PARAM_get_BN(param_q, &q))
+ || (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g)))
+ goto err;
+
+ prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GINDEX);
+ if (prm != NULL) {
+ if (!OSSL_PARAM_get_int(prm, &i))
+ goto err;
+ ffc->gindex = i;
+ }
+ prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PCOUNTER);
+ if (prm != NULL) {
+ if (!OSSL_PARAM_get_int(prm, &i))
+ goto err;
+ ffc->pcounter = i;
+ }
+ prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_COFACTOR);
+ if (prm != NULL && !OSSL_PARAM_get_BN(prm, &j))
+ goto err;
+ prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_H);
+ if (prm != NULL) {
+ if (!OSSL_PARAM_get_int(prm, &i))
+ goto err;
+ ffc->h = i;
+ }
+ prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_SEED);
+ if (prm != NULL) {
+ if (prm->data_type != OSSL_PARAM_OCTET_STRING)
+ goto err;
+ if (!ossl_ffc_params_set_seed(ffc, prm->data, prm->data_size))
+ goto err;
+ }
+ prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_VALIDATE_PQ);
+ if (prm != NULL) {
+ if (!OSSL_PARAM_get_int(prm, &i))
+ goto err;
+ ossl_ffc_params_enable_flags(ffc, FFC_PARAM_FLAG_VALIDATE_PQ, i);
+ }
+ prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_VALIDATE_G);
+ if (prm != NULL) {
+ if (!OSSL_PARAM_get_int(prm, &i))
+ goto err;
+ ossl_ffc_params_enable_flags(ffc, FFC_PARAM_FLAG_VALIDATE_G, i);
+ }
+ prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_VALIDATE_LEGACY);
+ if (prm != NULL) {
+ if (!OSSL_PARAM_get_int(prm, &i))
+ goto err;
+ ossl_ffc_params_enable_flags(ffc, FFC_PARAM_FLAG_VALIDATE_LEGACY, i);
+ }
+
+ prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST);
+ if (prm != NULL) {
+ const OSSL_PARAM *p1;
+ const char *props = NULL;
+
+ if (prm->data_type != OSSL_PARAM_UTF8_STRING)
+ goto err;
+ p1 = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS);
+ if (p1 != NULL) {
+ if (p1->data_type != OSSL_PARAM_UTF8_STRING)
+ goto err;
+ }
+ if (!ossl_ffc_set_digest(ffc, prm->data, props))
+ goto err;
+ }
+
+ ossl_ffc_params_set0_pqg(ffc, p, q, g);
+ ossl_ffc_params_set0_j(ffc, j);
+ return 1;
+
+ err:
+ BN_free(j);
+ BN_free(p);
+ BN_free(q);
+ BN_free(g);
+ return 0;
+}
diff --git a/crypto/ffc/ffc_dh.c b/crypto/ffc/ffc_dh.c
new file mode 100644
index 000000000000..df07e173bcb8
--- /dev/null
+++ b/crypto/ffc/ffc_dh.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/ffc.h"
+#include "internal/nelem.h"
+#include "crypto/bn_dh.h"
+
+#ifndef OPENSSL_NO_DH
+
+# define FFDHE(sz, keylength) { \
+ SN_ffdhe##sz, NID_ffdhe##sz, \
+ sz, \
+ keylength, \
+ &ossl_bignum_ffdhe##sz##_p, &ossl_bignum_ffdhe##sz##_q, \
+ &ossl_bignum_const_2, \
+ }
+
+# define MODP(sz, keylength) { \
+ SN_modp_##sz, NID_modp_##sz, \
+ sz, \
+ keylength, \
+ &ossl_bignum_modp_##sz##_p, &ossl_bignum_modp_##sz##_q, \
+ &ossl_bignum_const_2 \
+ }
+
+# define RFC5114(name, uid, sz, tag) { \
+ name, uid, \
+ sz, \
+ 0, \
+ &ossl_bignum_dh##tag##_p, &ossl_bignum_dh##tag##_q, \
+ &ossl_bignum_dh##tag##_g \
+ }
+
+#else
+
+# define FFDHE(sz, keylength) { SN_ffdhe##sz, NID_ffdhe##sz }
+# define MODP(sz, keylength) { SN_modp_##sz, NID_modp_##sz }
+# define RFC5114(name, uid, sz, tag) { name, uid }
+
+#endif
+
+struct dh_named_group_st {
+ const char *name;
+ int uid;
+#ifndef OPENSSL_NO_DH
+ int32_t nbits;
+ int keylength;
+ const BIGNUM *p;
+ const BIGNUM *q;
+ const BIGNUM *g;
+#endif
+};
+
+/*
+ * The private key length values are taken from RFC7919 with the values for
+ * MODP primes given the same lengths as the equivalent FFDHE.
+ * The MODP 1536 value is approximated.
+ */
+static const DH_NAMED_GROUP dh_named_groups[] = {
+ FFDHE(2048, 225),
+ FFDHE(3072, 275),
+ FFDHE(4096, 325),
+ FFDHE(6144, 375),
+ FFDHE(8192, 400),
+#ifndef FIPS_MODULE
+ MODP(1536, 200),
+#endif
+ MODP(2048, 225),
+ MODP(3072, 275),
+ MODP(4096, 325),
+ MODP(6144, 375),
+ MODP(8192, 400),
+ /*
+ * Additional dh named groups from RFC 5114 that have a different g.
+ * The uid can be any unique identifier.
+ */
+#ifndef FIPS_MODULE
+ RFC5114("dh_1024_160", 1, 1024, 1024_160),
+ RFC5114("dh_2048_224", 2, 2048, 2048_224),
+ RFC5114("dh_2048_256", 3, 2048, 2048_256),
+#endif
+};
+
+const DH_NAMED_GROUP *ossl_ffc_name_to_dh_named_group(const char *name)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) {
+ if (OPENSSL_strcasecmp(dh_named_groups[i].name, name) == 0)
+ return &dh_named_groups[i];
+ }
+ return NULL;
+}
+
+const DH_NAMED_GROUP *ossl_ffc_uid_to_dh_named_group(int uid)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) {
+ if (dh_named_groups[i].uid == uid)
+ return &dh_named_groups[i];
+ }
+ return NULL;
+}
+
+#ifndef OPENSSL_NO_DH
+const DH_NAMED_GROUP *ossl_ffc_numbers_to_dh_named_group(const BIGNUM *p,
+ const BIGNUM *q,
+ const BIGNUM *g)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) {
+ /* Keep searching until a matching p and g is found */
+ if (BN_cmp(p, dh_named_groups[i].p) == 0
+ && BN_cmp(g, dh_named_groups[i].g) == 0
+ /* Verify q is correct if it exists */
+ && (q == NULL || BN_cmp(q, dh_named_groups[i].q) == 0))
+ return &dh_named_groups[i];
+ }
+ return NULL;
+}
+#endif
+
+int ossl_ffc_named_group_get_uid(const DH_NAMED_GROUP *group)
+{
+ if (group == NULL)
+ return NID_undef;
+ return group->uid;
+}
+
+const char *ossl_ffc_named_group_get_name(const DH_NAMED_GROUP *group)
+{
+ if (group == NULL)
+ return NULL;
+ return group->name;
+}
+
+#ifndef OPENSSL_NO_DH
+int ossl_ffc_named_group_get_keylength(const DH_NAMED_GROUP *group)
+{
+ if (group == NULL)
+ return 0;
+ return group->keylength;
+}
+
+const BIGNUM *ossl_ffc_named_group_get_q(const DH_NAMED_GROUP *group)
+{
+ if (group == NULL)
+ return NULL;
+ return group->q;
+}
+
+int ossl_ffc_named_group_set(FFC_PARAMS *ffc, const DH_NAMED_GROUP *group)
+{
+ if (ffc == NULL || group == NULL)
+ return 0;
+
+ ossl_ffc_params_set0_pqg(ffc, (BIGNUM *)group->p, (BIGNUM *)group->q,
+ (BIGNUM *)group->g);
+ ffc->keylength = group->keylength;
+
+ /* flush the cached nid, The DH layer is responsible for caching */
+ ffc->nid = NID_undef;
+ return 1;
+}
+#endif
diff --git a/crypto/ffc/ffc_key_generate.c b/crypto/ffc/ffc_key_generate.c
new file mode 100644
index 000000000000..d02c6575274d
--- /dev/null
+++ b/crypto/ffc/ffc_key_generate.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/ffc.h"
+
+/*
+ * SP800-56Ar3 5.6.1.1.4 Key pair generation by testing candidates.
+ * Generates a private key in the interval [1, min(2 ^ N - 1, q - 1)].
+ *
+ * ctx must be set up with a libctx (for fips mode).
+ * params contains the FFC domain parameters p, q and g (for DH or DSA).
+ * N is the maximum bit length of the generated private key,
+ * s is the security strength.
+ * priv_key is the returned private key,
+ */
+int ossl_ffc_generate_private_key(BN_CTX *ctx, const FFC_PARAMS *params,
+ int N, int s, BIGNUM *priv)
+{
+ int ret = 0, qbits = BN_num_bits(params->q);
+ BIGNUM *m, *two_powN = NULL;
+
+ /* Deal with the edge cases where the value of N and/or s is not set */
+ if (s == 0)
+ goto err;
+ if (N == 0)
+ N = params->keylength ? params->keylength : 2 * s;
+
+ /* Step (2) : check range of N */
+ if (N < 2 * s || N > qbits)
+ return 0;
+
+ two_powN = BN_new();
+ /* 2^N */
+ if (two_powN == NULL || !BN_lshift(two_powN, BN_value_one(), N))
+ goto err;
+
+ /* Step (5) : M = min(2 ^ N, q) */
+ m = (BN_cmp(two_powN, params->q) > 0) ? params->q : two_powN;
+
+ do {
+ /* Steps (3, 4 & 7) : c + 1 = 1 + random[0..2^N - 1] */
+ if (!BN_priv_rand_range_ex(priv, two_powN, 0, ctx)
+ || !BN_add_word(priv, 1))
+ goto err;
+ /* Step (6) : loop if c > M - 2 (i.e. c + 1 >= M) */
+ if (BN_cmp(priv, m) < 0)
+ break;
+ } while (1);
+
+ ret = 1;
+err:
+ BN_free(two_powN);
+ return ret;
+}
diff --git a/crypto/ffc/ffc_key_validate.c b/crypto/ffc/ffc_key_validate.c
new file mode 100644
index 000000000000..342789621d6d
--- /dev/null
+++ b/crypto/ffc/ffc_key_validate.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/ffc.h"
+
+/*
+ * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Partial public key validation.
+ * To only be used with ephemeral FFC public keys generated using the approved
+ * safe-prime groups. (Checks that the public key is in the range [2, p - 1]
+ *
+ * ret contains 0 on success, or error flags (see FFC_ERROR_PUBKEY_TOO_SMALL)
+ */
+int ossl_ffc_validate_public_key_partial(const FFC_PARAMS *params,
+ const BIGNUM *pub_key, int *ret)
+{
+ int ok = 0;
+ BIGNUM *tmp = NULL;
+ BN_CTX *ctx = NULL;
+
+ *ret = 0;
+ if (params == NULL || pub_key == NULL || params->p == NULL) {
+ *ret = FFC_ERROR_PASSED_NULL_PARAM;
+ return 0;
+ }
+
+ ctx = BN_CTX_new_ex(NULL);
+ if (ctx == NULL)
+ goto err;
+
+ BN_CTX_start(ctx);
+ tmp = BN_CTX_get(ctx);
+ /* Step(1): Verify pub_key >= 2 */
+ if (tmp == NULL
+ || !BN_set_word(tmp, 1))
+ goto err;
+ if (BN_cmp(pub_key, tmp) <= 0) {
+ *ret |= FFC_ERROR_PUBKEY_TOO_SMALL;
+ goto err;
+ }
+ /* Step(1): Verify pub_key <= p-2 */
+ if (BN_copy(tmp, params->p) == NULL
+ || !BN_sub_word(tmp, 1))
+ goto err;
+ if (BN_cmp(pub_key, tmp) >= 0) {
+ *ret |= FFC_ERROR_PUBKEY_TOO_LARGE;
+ goto err;
+ }
+ ok = 1;
+ err:
+ if (ctx != NULL) {
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ }
+ return ok;
+}
+
+/*
+ * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Full public key validation.
+ */
+int ossl_ffc_validate_public_key(const FFC_PARAMS *params,
+ const BIGNUM *pub_key, int *ret)
+{
+ int ok = 0;
+ BIGNUM *tmp = NULL;
+ BN_CTX *ctx = NULL;
+
+ if (!ossl_ffc_validate_public_key_partial(params, pub_key, ret))
+ return 0;
+
+ if (params->q != NULL) {
+ ctx = BN_CTX_new_ex(NULL);
+ if (ctx == NULL)
+ goto err;
+ BN_CTX_start(ctx);
+ tmp = BN_CTX_get(ctx);
+
+ /* Check pub_key^q == 1 mod p */
+ if (tmp == NULL
+ || !BN_mod_exp(tmp, pub_key, params->q, params->p, ctx))
+ goto err;
+ if (!BN_is_one(tmp)) {
+ *ret |= FFC_ERROR_PUBKEY_INVALID;
+ goto err;
+ }
+ }
+
+ ok = 1;
+ err:
+ if (ctx != NULL) {
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ }
+ return ok;
+}
+
+/*
+ * See SP800-56Ar3 Section 5.6.2.1.2: Owner assurance of Private key validity.
+ * Verifies priv_key is in the range [1..upper-1]. The passed in value of upper
+ * is normally params->q but can be 2^N for approved safe prime groups.
+ * Note: This assumes that the domain parameters are valid.
+ */
+int ossl_ffc_validate_private_key(const BIGNUM *upper, const BIGNUM *priv,
+ int *ret)
+{
+ int ok = 0;
+
+ *ret = 0;
+
+ if (priv == NULL || upper == NULL) {
+ *ret = FFC_ERROR_PASSED_NULL_PARAM;
+ goto err;
+ }
+ if (BN_cmp(priv, BN_value_one()) < 0) {
+ *ret |= FFC_ERROR_PRIVKEY_TOO_SMALL;
+ goto err;
+ }
+ if (BN_cmp(priv, upper) >= 0) {
+ *ret |= FFC_ERROR_PRIVKEY_TOO_LARGE;
+ goto err;
+ }
+ ok = 1;
+err:
+ return ok;
+}
diff --git a/crypto/ffc/ffc_params.c b/crypto/ffc/ffc_params.c
new file mode 100644
index 000000000000..fb558f8221f6
--- /dev/null
+++ b/crypto/ffc/ffc_params.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h> /* memset */
+#include <openssl/core_names.h>
+#include "internal/ffc.h"
+#include "internal/param_build_set.h"
+#include "internal/nelem.h"
+
+#ifndef FIPS_MODULE
+# include <openssl/asn1.h> /* ossl_ffc_params_print */
+#endif
+
+void ossl_ffc_params_init(FFC_PARAMS *params)
+{
+ memset(params, 0, sizeof(*params));
+ params->pcounter = -1;
+ params->gindex = FFC_UNVERIFIABLE_GINDEX;
+ params->flags = FFC_PARAM_FLAG_VALIDATE_PQG;
+}
+
+void ossl_ffc_params_cleanup(FFC_PARAMS *params)
+{
+ BN_free(params->p);
+ BN_free(params->q);
+ BN_free(params->g);
+ BN_free(params->j);
+ OPENSSL_free(params->seed);
+ ossl_ffc_params_init(params);
+}
+
+void ossl_ffc_params_set0_pqg(FFC_PARAMS *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+ if (p != NULL && p != d->p) {
+ BN_free(d->p);
+ d->p = p;
+ }
+ if (q != NULL && q != d->q) {
+ BN_free(d->q);
+ d->q = q;
+ }
+ if (g != NULL && g != d->g) {
+ BN_free(d->g);
+ d->g = g;
+ }
+}
+
+void ossl_ffc_params_get0_pqg(const FFC_PARAMS *d, const BIGNUM **p,
+ const BIGNUM **q, const BIGNUM **g)
+{
+ if (p != NULL)
+ *p = d->p;
+ if (q != NULL)
+ *q = d->q;
+ if (g != NULL)
+ *g = d->g;
+}
+
+
+/* j is the 'cofactor' that is optionally output for ASN1. */
+void ossl_ffc_params_set0_j(FFC_PARAMS *d, BIGNUM *j)
+{
+ BN_free(d->j);
+ d->j = NULL;
+ if (j != NULL)
+ d->j = j;
+}
+
+int ossl_ffc_params_set_seed(FFC_PARAMS *params,
+ const unsigned char *seed, size_t seedlen)
+{
+ if (params == NULL)
+ return 0;
+
+ if (params->seed != NULL) {
+ if (params->seed == seed)
+ return 1;
+ OPENSSL_free(params->seed);
+ }
+
+ if (seed != NULL && seedlen > 0) {
+ params->seed = OPENSSL_memdup(seed, seedlen);
+ if (params->seed == NULL)
+ return 0;
+ params->seedlen = seedlen;
+ } else {
+ params->seed = NULL;
+ params->seedlen = 0;
+ }
+ return 1;
+}
+
+void ossl_ffc_params_set_gindex(FFC_PARAMS *params, int index)
+{
+ params->gindex = index;
+}
+
+void ossl_ffc_params_set_pcounter(FFC_PARAMS *params, int index)
+{
+ params->pcounter = index;
+}
+
+void ossl_ffc_params_set_h(FFC_PARAMS *params, int index)
+{
+ params->h = index;
+}
+
+void ossl_ffc_params_set_flags(FFC_PARAMS *params, unsigned int flags)
+{
+ params->flags = flags;
+}
+
+void ossl_ffc_params_enable_flags(FFC_PARAMS *params, unsigned int flags,
+ int enable)
+{
+ if (enable)
+ params->flags |= flags;
+ else
+ params->flags &= ~flags;
+}
+
+int ossl_ffc_set_digest(FFC_PARAMS *params, const char *alg, const char *props)
+{
+ params->mdname = alg;
+ params->mdprops = props;
+ return 1;
+}
+
+int ossl_ffc_params_set_validate_params(FFC_PARAMS *params,
+ const unsigned char *seed,
+ size_t seedlen, int counter)
+{
+ if (!ossl_ffc_params_set_seed(params, seed, seedlen))
+ return 0;
+ params->pcounter = counter;
+ return 1;
+}
+
+void ossl_ffc_params_get_validate_params(const FFC_PARAMS *params,
+ unsigned char **seed, size_t *seedlen,
+ int *pcounter)
+{
+ if (seed != NULL)
+ *seed = params->seed;
+ if (seedlen != NULL)
+ *seedlen = params->seedlen;
+ if (pcounter != NULL)
+ *pcounter = params->pcounter;
+}
+
+static int ffc_bn_cpy(BIGNUM **dst, const BIGNUM *src)
+{
+ BIGNUM *a;
+
+ /*
+ * If source is read only just copy the pointer, so
+ * we don't have to reallocate it.
+ */
+ if (src == NULL)
+ a = NULL;
+ else if (BN_get_flags(src, BN_FLG_STATIC_DATA)
+ && !BN_get_flags(src, BN_FLG_MALLOCED))
+ a = (BIGNUM *)src;
+ else if ((a = BN_dup(src)) == NULL)
+ return 0;
+ BN_clear_free(*dst);
+ *dst = a;
+ return 1;
+}
+
+int ossl_ffc_params_copy(FFC_PARAMS *dst, const FFC_PARAMS *src)
+{
+ if (!ffc_bn_cpy(&dst->p, src->p)
+ || !ffc_bn_cpy(&dst->g, src->g)
+ || !ffc_bn_cpy(&dst->q, src->q)
+ || !ffc_bn_cpy(&dst->j, src->j))
+ return 0;
+
+ OPENSSL_free(dst->seed);
+ dst->seedlen = src->seedlen;
+ if (src->seed != NULL) {
+ dst->seed = OPENSSL_memdup(src->seed, src->seedlen);
+ if (dst->seed == NULL)
+ return 0;
+ } else {
+ dst->seed = NULL;
+ }
+ dst->nid = src->nid;
+ dst->pcounter = src->pcounter;
+ dst->h = src->h;
+ dst->gindex = src->gindex;
+ dst->flags = src->flags;
+ dst->keylength = src->keylength;
+ return 1;
+}
+
+int ossl_ffc_params_cmp(const FFC_PARAMS *a, const FFC_PARAMS *b, int ignore_q)
+{
+ return BN_cmp(a->p, b->p) == 0
+ && BN_cmp(a->g, b->g) == 0
+ && (ignore_q || BN_cmp(a->q, b->q) == 0); /* Note: q may be NULL */
+}
+
+int ossl_ffc_params_todata(const FFC_PARAMS *ffc, OSSL_PARAM_BLD *bld,
+ OSSL_PARAM params[])
+{
+ int test_flags;
+
+ if (ffc == NULL)
+ return 0;
+
+ if (ffc->p != NULL
+ && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_P, ffc->p))
+ return 0;
+ if (ffc->q != NULL
+ && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_Q, ffc->q))
+ return 0;
+ if (ffc->g != NULL
+ && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_G, ffc->g))
+ return 0;
+ if (ffc->j != NULL
+ && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_COFACTOR,
+ ffc->j))
+ return 0;
+ if (!ossl_param_build_set_int(bld, params, OSSL_PKEY_PARAM_FFC_GINDEX,
+ ffc->gindex))
+ return 0;
+ if (!ossl_param_build_set_int(bld, params, OSSL_PKEY_PARAM_FFC_PCOUNTER,
+ ffc->pcounter))
+ return 0;
+ if (!ossl_param_build_set_int(bld, params, OSSL_PKEY_PARAM_FFC_H, ffc->h))
+ return 0;
+ if (ffc->seed != NULL
+ && !ossl_param_build_set_octet_string(bld, params,
+ OSSL_PKEY_PARAM_FFC_SEED,
+ ffc->seed, ffc->seedlen))
+ return 0;
+ if (ffc->nid != NID_undef) {
+ const DH_NAMED_GROUP *group = ossl_ffc_uid_to_dh_named_group(ffc->nid);
+ const char *name = ossl_ffc_named_group_get_name(group);
+
+ if (name == NULL
+ || !ossl_param_build_set_utf8_string(bld, params,
+ OSSL_PKEY_PARAM_GROUP_NAME,
+ name))
+ return 0;
+ }
+ test_flags = ((ffc->flags & FFC_PARAM_FLAG_VALIDATE_PQ) != 0);
+ if (!ossl_param_build_set_int(bld, params,
+ OSSL_PKEY_PARAM_FFC_VALIDATE_PQ, test_flags))
+ return 0;
+ test_flags = ((ffc->flags & FFC_PARAM_FLAG_VALIDATE_G) != 0);
+ if (!ossl_param_build_set_int(bld, params,
+ OSSL_PKEY_PARAM_FFC_VALIDATE_G, test_flags))
+ return 0;
+ test_flags = ((ffc->flags & FFC_PARAM_FLAG_VALIDATE_LEGACY) != 0);
+ if (!ossl_param_build_set_int(bld, params,
+ OSSL_PKEY_PARAM_FFC_VALIDATE_LEGACY,
+ test_flags))
+ return 0;
+
+ if (ffc->mdname != NULL
+ && !ossl_param_build_set_utf8_string(bld, params,
+ OSSL_PKEY_PARAM_FFC_DIGEST,
+ ffc->mdname))
+ return 0;
+ if (ffc->mdprops != NULL
+ && !ossl_param_build_set_utf8_string(bld, params,
+ OSSL_PKEY_PARAM_FFC_DIGEST_PROPS,
+ ffc->mdprops))
+ return 0;
+ return 1;
+}
+
+#ifndef FIPS_MODULE
+int ossl_ffc_params_print(BIO *bp, const FFC_PARAMS *ffc, int indent)
+{
+ if (!ASN1_bn_print(bp, "prime P:", ffc->p, NULL, indent))
+ goto err;
+ if (!ASN1_bn_print(bp, "generator G:", ffc->g, NULL, indent))
+ goto err;
+ if (ffc->q != NULL
+ && !ASN1_bn_print(bp, "subgroup order Q:", ffc->q, NULL, indent))
+ goto err;
+ if (ffc->j != NULL
+ && !ASN1_bn_print(bp, "subgroup factor:", ffc->j, NULL, indent))
+ goto err;
+ if (ffc->seed != NULL) {
+ size_t i;
+
+ if (!BIO_indent(bp, indent, 128)
+ || BIO_puts(bp, "seed:") <= 0)
+ goto err;
+ for (i = 0; i < ffc->seedlen; i++) {
+ if ((i % 15) == 0) {
+ if (BIO_puts(bp, "\n") <= 0
+ || !BIO_indent(bp, indent + 4, 128))
+ goto err;
+ }
+ if (BIO_printf(bp, "%02x%s", ffc->seed[i],
+ ((i + 1) == ffc->seedlen) ? "" : ":") <= 0)
+ goto err;
+ }
+ if (BIO_write(bp, "\n", 1) <= 0)
+ return 0;
+ }
+ if (ffc->pcounter != -1) {
+ if (!BIO_indent(bp, indent, 128)
+ || BIO_printf(bp, "counter: %d\n", ffc->pcounter) <= 0)
+ goto err;
+ }
+ return 1;
+err:
+ return 0;
+}
+#endif /* FIPS_MODULE */
diff --git a/crypto/ffc/ffc_params_generate.c b/crypto/ffc/ffc_params_generate.c
new file mode 100644
index 000000000000..6b018edfffce
--- /dev/null
+++ b/crypto/ffc/ffc_params_generate.c
@@ -0,0 +1,1057 @@
+/*
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * For the prime check..
+ * FIPS 186-4 Section C.3 Table C.1
+ * Returns the minimum number of Miller Rabin iterations for a L,N pair
+ * (where L = len(p), N = len(q))
+ * L N Min
+ * 1024 160 40
+ * 2048 224 56
+ * 2048 256 56
+ * 3072 256 64
+ *
+ * BN_check_prime() uses:
+ * 64 iterations for L <= 2048 OR
+ * 128 iterations for L > 2048
+ * So this satisfies the requirement.
+ */
+
+#include <string.h> /* memset */
+#include <openssl/sha.h> /* SHA_DIGEST_LENGTH */
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/dherr.h>
+#include <openssl/dsaerr.h>
+#include "crypto/bn.h"
+#include "internal/ffc.h"
+
+/*
+ * Verify that the passed in L, N pair for DH or DSA is valid.
+ * Returns 0 if invalid, otherwise it returns the security strength.
+ */
+
+#ifdef FIPS_MODULE
+static int ffc_validate_LN(size_t L, size_t N, int type, int verify)
+{
+ if (type == FFC_PARAM_TYPE_DH) {
+ /* Valid DH L,N parameters from SP800-56Ar3 5.5.1 Table 1 */
+ if (L == 2048 && (N == 224 || N == 256))
+ return 112;
+# ifndef OPENSSL_NO_DH
+ ERR_raise(ERR_LIB_DH, DH_R_BAD_FFC_PARAMETERS);
+# endif
+ } else if (type == FFC_PARAM_TYPE_DSA) {
+ /* Valid DSA L,N parameters from FIPS 186-4 Section 4.2 */
+ /* In fips mode 1024/160 can only be used for verification */
+ if (verify && L == 1024 && N == 160)
+ return 80;
+ if (L == 2048 && (N == 224 || N == 256))
+ return 112;
+ if (L == 3072 && N == 256)
+ return 128;
+# ifndef OPENSSL_NO_DSA
+ ERR_raise(ERR_LIB_DSA, DSA_R_BAD_FFC_PARAMETERS);
+# endif
+ }
+ return 0;
+}
+#else
+static int ffc_validate_LN(size_t L, size_t N, int type, int verify)
+{
+ if (type == FFC_PARAM_TYPE_DH) {
+ /* Allow legacy 1024/160 in non fips mode */
+ if (L == 1024 && N == 160)
+ return 80;
+ /* Valid DH L,N parameters from SP800-56Ar3 5.5.1 Table 1 */
+ if (L == 2048 && (N == 224 || N == 256))
+ return 112;
+# ifndef OPENSSL_NO_DH
+ ERR_raise(ERR_LIB_DH, DH_R_BAD_FFC_PARAMETERS);
+# endif
+ } else if (type == FFC_PARAM_TYPE_DSA) {
+ if (L >= 3072 && N >= 256)
+ return 128;
+ if (L >= 2048 && N >= 224)
+ return 112;
+ if (L >= 1024 && N >= 160)
+ return 80;
+# ifndef OPENSSL_NO_DSA
+ ERR_raise(ERR_LIB_DSA, DSA_R_BAD_FFC_PARAMETERS);
+# endif
+ }
+ return 0;
+}
+#endif /* FIPS_MODULE */
+
+/* FIPS186-4 A.2.1 Unverifiable Generation of Generator g */
+static int generate_unverifiable_g(BN_CTX *ctx, BN_MONT_CTX *mont, BIGNUM *g,
+ BIGNUM *hbn, const BIGNUM *p,
+ const BIGNUM *e,const BIGNUM *pm1,
+ int *hret)
+{
+ int h = 2;
+
+ /* Step (2): choose h (where 1 < h)*/
+ if (!BN_set_word(hbn, h))
+ return 0;
+
+ for (;;) {
+ /* Step (3): g = h^e % p */
+ if (!BN_mod_exp_mont(g, hbn, e, p, ctx, mont))
+ return 0;
+ /* Step (4): Finish if g > 1 */
+ if (BN_cmp(g, BN_value_one()) > 0)
+ break;
+
+ /* Step (2) Choose any h in the range 1 < h < (p-1) */
+ if (!BN_add_word(hbn, 1) || BN_cmp(hbn, pm1) >= 0)
+ return 0;
+ ++h;
+ }
+ *hret = h;
+ return 1;
+}
+
+/*
+ * FIPS186-4 A.2 Generation of canonical generator g.
+ *
+ * It requires the following values as input:
+ * 'evpmd' digest, 'p' prime, 'e' cofactor, gindex and seed.
+ * tmp is a passed in temporary BIGNUM.
+ * mont is used in a BN_mod_exp_mont() with a modulus of p.
+ * Returns a value in g.
+ */
+static int generate_canonical_g(BN_CTX *ctx, BN_MONT_CTX *mont,
+ const EVP_MD *evpmd, BIGNUM *g, BIGNUM *tmp,
+ const BIGNUM *p, const BIGNUM *e,
+ int gindex, unsigned char *seed, size_t seedlen)
+{
+ int ret = 0;
+ int counter = 1;
+ unsigned char md[EVP_MAX_MD_SIZE];
+ EVP_MD_CTX *mctx = NULL;
+ int mdsize;
+
+ mdsize = EVP_MD_get_size(evpmd);
+ if (mdsize <= 0)
+ return 0;
+
+ mctx = EVP_MD_CTX_new();
+ if (mctx == NULL)
+ return 0;
+
+ /*
+ * A.2.3 Step (4) & (5)
+ * A.2.4 Step (6) & (7)
+ * counter = 0; counter += 1
+ */
+ for (counter = 1; counter <= 0xFFFF; ++counter) {
+ /*
+ * A.2.3 Step (7) & (8) & (9)
+ * A.2.4 Step (9) & (10) & (11)
+ * W = Hash(seed || "ggen" || index || counter)
+ * g = W^e % p
+ */
+ static const unsigned char ggen[4] = { 0x67, 0x67, 0x65, 0x6e };
+
+ md[0] = (unsigned char)(gindex & 0xff);
+ md[1] = (unsigned char)((counter >> 8) & 0xff);
+ md[2] = (unsigned char)(counter & 0xff);
+ if (!EVP_DigestInit_ex(mctx, evpmd, NULL)
+ || !EVP_DigestUpdate(mctx, seed, seedlen)
+ || !EVP_DigestUpdate(mctx, ggen, sizeof(ggen))
+ || !EVP_DigestUpdate(mctx, md, 3)
+ || !EVP_DigestFinal_ex(mctx, md, NULL)
+ || (BN_bin2bn(md, mdsize, tmp) == NULL)
+ || !BN_mod_exp_mont(g, tmp, e, p, ctx, mont))
+ break; /* exit on failure */
+ /*
+ * A.2.3 Step (10)
+ * A.2.4 Step (12)
+ * Found a value for g if (g >= 2)
+ */
+ if (BN_cmp(g, BN_value_one()) > 0) {
+ ret = 1;
+ break; /* found g */
+ }
+ }
+ EVP_MD_CTX_free(mctx);
+ return ret;
+}
+
+/* Generation of p is the same for FIPS 186-4 & FIPS 186-2 */
+static int generate_p(BN_CTX *ctx, const EVP_MD *evpmd, int max_counter, int n,
+ unsigned char *buf, size_t buf_len, const BIGNUM *q,
+ BIGNUM *p, int L, BN_GENCB *cb, int *counter,
+ int *res)
+{
+ int ret = -1;
+ int i, j, k, r;
+ unsigned char md[EVP_MAX_MD_SIZE];
+ int mdsize;
+ BIGNUM *W, *X, *tmp, *c, *test;
+
+ BN_CTX_start(ctx);
+ W = BN_CTX_get(ctx);
+ X = BN_CTX_get(ctx);
+ c = BN_CTX_get(ctx);
+ test = BN_CTX_get(ctx);
+ tmp = BN_CTX_get(ctx);
+ if (tmp == NULL)
+ goto err;
+
+ if (!BN_lshift(test, BN_value_one(), L - 1))
+ goto err;
+
+ mdsize = EVP_MD_get_size(evpmd);
+ if (mdsize <= 0)
+ goto err;
+
+ /* A.1.1.2 Step (10) AND
+ * A.1.1.2 Step (12)
+ * offset = 1 (this is handled below)
+ */
+ /*
+ * A.1.1.2 Step (11) AND
+ * A.1.1.3 Step (13)
+ */
+ for (i = 0; i <= max_counter; i++) {
+ if ((i != 0) && !BN_GENCB_call(cb, 0, i))
+ goto err;
+
+ BN_zero(W);
+ /* seed_tmp buffer contains "seed + offset - 1" */
+ for (j = 0; j <= n; j++) {
+ /* obtain "seed + offset + j" by incrementing by 1: */
+ for (k = (int)buf_len - 1; k >= 0; k--) {
+ buf[k]++;
+ if (buf[k] != 0)
+ break;
+ }
+ /*
+ * A.1.1.2 Step (11.1) AND
+ * A.1.1.3 Step (13.1)
+ * tmp = V(j) = Hash((seed + offset + j) % 2^seedlen)
+ */
+ if (!EVP_Digest(buf, buf_len, md, NULL, evpmd, NULL)
+ || (BN_bin2bn(md, mdsize, tmp) == NULL)
+ /*
+ * A.1.1.2 Step (11.2)
+ * A.1.1.3 Step (13.2)
+ * W += V(j) * 2^(outlen * j)
+ */
+ || !BN_lshift(tmp, tmp, (mdsize << 3) * j)
+ || !BN_add(W, W, tmp))
+ goto err;
+ }
+
+ /*
+ * A.1.1.2 Step (11.3) AND
+ * A.1.1.3 Step (13.3)
+ * X = W + 2^(L-1) where W < 2^(L-1)
+ */
+ if (!BN_mask_bits(W, L - 1)
+ || !BN_copy(X, W)
+ || !BN_add(X, X, test)
+ /*
+ * A.1.1.2 Step (11.4) AND
+ * A.1.1.3 Step (13.4)
+ * c = X mod 2q
+ */
+ || !BN_lshift1(tmp, q)
+ || !BN_mod(c, X, tmp, ctx)
+ /*
+ * A.1.1.2 Step (11.5) AND
+ * A.1.1.3 Step (13.5)
+ * p = X - (c - 1)
+ */
+ || !BN_sub(tmp, c, BN_value_one())
+ || !BN_sub(p, X, tmp))
+ goto err;
+
+ /*
+ * A.1.1.2 Step (11.6) AND
+ * A.1.1.3 Step (13.6)
+ * if (p < 2 ^ (L-1)) continue
+ * This makes sure the top bit is set.
+ */
+ if (BN_cmp(p, test) >= 0) {
+ /*
+ * A.1.1.2 Step (11.7) AND
+ * A.1.1.3 Step (13.7)
+ * Test if p is prime
+ * (This also makes sure the bottom bit is set)
+ */
+ r = BN_check_prime(p, ctx, cb);
+ /* A.1.1.2 Step (11.8) : Return if p is prime */
+ if (r > 0) {
+ *counter = i;
+ ret = 1; /* return success */
+ goto err;
+ }
+ if (r != 0)
+ goto err;
+ }
+ /* Step (11.9) : offset = offset + n + 1 is done auto-magically */
+ }
+ /* No prime P found */
+ ret = 0;
+ *res |= FFC_CHECK_P_NOT_PRIME;
+err:
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+static int generate_q_fips186_4(BN_CTX *ctx, BIGNUM *q, const EVP_MD *evpmd,
+ int qsize, unsigned char *seed, size_t seedlen,
+ int generate_seed, int *retm, int *res,
+ BN_GENCB *cb)
+{
+ int ret = 0, r;
+ int m = *retm;
+ unsigned char md[EVP_MAX_MD_SIZE];
+ int mdsize = EVP_MD_get_size(evpmd);
+ unsigned char *pmd;
+ OSSL_LIB_CTX *libctx = ossl_bn_get_libctx(ctx);
+
+ /* find q */
+ for (;;) {
+ if(!BN_GENCB_call(cb, 0, m++))
+ goto err;
+
+ /* A.1.1.2 Step (5) : generate seed with size seed_len */
+ if (generate_seed
+ && RAND_bytes_ex(libctx, seed, seedlen, 0) <= 0)
+ goto err;
+ /*
+ * A.1.1.2 Step (6) AND
+ * A.1.1.3 Step (7)
+ * U = Hash(seed) % (2^(N-1))
+ */
+ if (!EVP_Digest(seed, seedlen, md, NULL, evpmd, NULL))
+ goto err;
+ /* Take least significant bits of md */
+ if (mdsize > qsize)
+ pmd = md + mdsize - qsize;
+ else
+ pmd = md;
+ if (mdsize < qsize)
+ memset(md + mdsize, 0, qsize - mdsize);
+
+ /*
+ * A.1.1.2 Step (7) AND
+ * A.1.1.3 Step (8)
+ * q = U + 2^(N-1) + (1 - U %2) (This sets top and bottom bits)
+ */
+ pmd[0] |= 0x80;
+ pmd[qsize-1] |= 0x01;
+ if (!BN_bin2bn(pmd, qsize, q))
+ goto err;
+
+ /*
+ * A.1.1.2 Step (8) AND
+ * A.1.1.3 Step (9)
+ * Test if q is prime
+ */
+ r = BN_check_prime(q, ctx, cb);
+ if (r > 0) {
+ ret = 1;
+ goto err;
+ }
+ /*
+ * A.1.1.3 Step (9) : If the provided seed didn't produce a prime q
+ * return an error.
+ */
+ if (!generate_seed) {
+ *res |= FFC_CHECK_Q_NOT_PRIME;
+ goto err;
+ }
+ if (r != 0)
+ goto err;
+ /* A.1.1.2 Step (9) : if q is not prime, try another q */
+ }
+err:
+ *retm = m;
+ return ret;
+}
+
+static int generate_q_fips186_2(BN_CTX *ctx, BIGNUM *q, const EVP_MD *evpmd,
+ unsigned char *buf, unsigned char *seed,
+ size_t qsize, int generate_seed, int *retm,
+ int *res, BN_GENCB *cb)
+{
+ unsigned char buf2[EVP_MAX_MD_SIZE];
+ unsigned char md[EVP_MAX_MD_SIZE];
+ int i, r, ret = 0, m = *retm;
+ OSSL_LIB_CTX *libctx = ossl_bn_get_libctx(ctx);
+
+ /* find q */
+ for (;;) {
+ /* step 1 */
+ if (!BN_GENCB_call(cb, 0, m++))
+ goto err;
+
+ if (generate_seed && RAND_bytes_ex(libctx, seed, qsize, 0) <= 0)
+ goto err;
+
+ memcpy(buf, seed, qsize);
+ memcpy(buf2, seed, qsize);
+
+ /* precompute "SEED + 1" for step 7: */
+ for (i = (int)qsize - 1; i >= 0; i--) {
+ buf[i]++;
+ if (buf[i] != 0)
+ break;
+ }
+
+ /* step 2 */
+ if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL))
+ goto err;
+ if (!EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL))
+ goto err;
+ for (i = 0; i < (int)qsize; i++)
+ md[i] ^= buf2[i];
+
+ /* step 3 */
+ md[0] |= 0x80;
+ md[qsize - 1] |= 0x01;
+ if (!BN_bin2bn(md, (int)qsize, q))
+ goto err;
+
+ /* step 4 */
+ r = BN_check_prime(q, ctx, cb);
+ if (r > 0) {
+ /* Found a prime */
+ ret = 1;
+ goto err;
+ }
+ if (r != 0)
+ goto err; /* Exit if error */
+ /* Try another iteration if it wasnt prime - was in old code.. */
+ generate_seed = 1;
+ }
+err:
+ *retm = m;
+ return ret;
+}
+
+static const char *default_mdname(size_t N)
+{
+ if (N == 160)
+ return "SHA1";
+ else if (N == 224)
+ return "SHA-224";
+ else if (N == 256)
+ return "SHA-256";
+ return NULL;
+}
+
+/*
+ * FIPS 186-4 FFC parameter generation (as defined in Appendix A).
+ * The same code is used for validation (when validate_flags != 0)
+ *
+ * The primes p & q are generated/validated using:
+ * A.1.1.2 Generation of probable primes p & q using approved hash.
+ * A.1.1.3 Validation of generated probable primes
+ *
+ * Generator 'g' has 2 types in FIPS 186-4:
+ * (1) A.2.1 unverifiable generation of generator g.
+ * A.2.2 Assurance of the validity of unverifiable generator g.
+ * (2) A.2.3 Verifiable Canonical Generation of the generator g.
+ * A.2.4 Validation for Canonical Generation of the generator g.
+ *
+ * Notes:
+ * (1) is only a partial validation of g, The validation of (2) requires
+ * the seed and index used during generation as input.
+ *
+ * params: used to pass in values for generation and validation.
+ * params->md: is the digest to use, If this value is NULL, then the digest is
+ * chosen using the value of N.
+ * params->flags:
+ * For validation one of:
+ * -FFC_PARAM_FLAG_VALIDATE_PQ
+ * -FFC_PARAM_FLAG_VALIDATE_G
+ * -FFC_PARAM_FLAG_VALIDATE_PQG
+ * For generation of p & q:
+ * - This is skipped if p & q are passed in.
+ * - If the seed is passed in then generation of p & q uses this seed (and if
+ * this fails an error will occur).
+ * - Otherwise the seed is generated, and values of p & q are generated and
+ * the value of seed and counter are optionally returned.
+ * For the generation of g (after the generation of p, q):
+ * - If the seed has been generated or passed in and a valid gindex is passed
+ * in then canonical generation of g is used otherwise unverifiable
+ * generation of g is chosen.
+ * For validation of p & q:
+ * - p, q, and the seed and counter used for generation must be passed in.
+ * For validation of g:
+ * - For a partial validation : p, q and g are required.
+ * - For a canonical validation : the gindex and seed used for generation are
+ * also required.
+ * mode: The mode - either FFC_PARAM_MODE_GENERATE or FFC_PARAM_MODE_VERIFY.
+ * type: The key type - FFC_PARAM_TYPE_DSA or FFC_PARAM_TYPE_DH.
+ * L: is the size of the prime p in bits (e.g 2048)
+ * N: is the size of the prime q in bits (e.g 256)
+ * res: A returned failure reason (One of FFC_CHECK_XXXX),
+ * or 0 for general failures.
+ * cb: A callback (can be NULL) that is called during different phases
+ *
+ * Returns:
+ * - FFC_PARAM_RET_STATUS_FAILED: if there was an error, or validation failed.
+ * - FFC_PARAM_RET_STATUS_SUCCESS if the generation or validation succeeded.
+ * - FFC_PARAM_RET_STATUS_UNVERIFIABLE_G if the validation of G succeeded,
+ * but G is unverifiable.
+ */
+int ossl_ffc_params_FIPS186_4_gen_verify(OSSL_LIB_CTX *libctx,
+ FFC_PARAMS *params, int mode, int type,
+ size_t L, size_t N, int *res,
+ BN_GENCB *cb)
+{
+ int ok = FFC_PARAM_RET_STATUS_FAILED;
+ unsigned char *seed = NULL, *seed_tmp = NULL;
+ int mdsize, counter = 0, pcounter = 0, r = 0;
+ size_t seedlen = 0;
+ BIGNUM *tmp, *pm1, *e, *test;
+ BIGNUM *g = NULL, *q = NULL, *p = NULL;
+ BN_MONT_CTX *mont = NULL;
+ int n = 0, m = 0, qsize;
+ int canonical_g = 0, hret = 0;
+ BN_CTX *ctx = NULL;
+ EVP_MD_CTX *mctx = NULL;
+ EVP_MD *md = NULL;
+ int verify = (mode == FFC_PARAM_MODE_VERIFY);
+ unsigned int flags = verify ? params->flags : 0;
+ const char *def_name;
+
+ *res = 0;
+
+ if (params->mdname != NULL) {
+ md = EVP_MD_fetch(libctx, params->mdname, params->mdprops);
+ } else {
+ if (N == 0)
+ N = (L >= 2048 ? SHA256_DIGEST_LENGTH : SHA_DIGEST_LENGTH) * 8;
+ def_name = default_mdname(N);
+ if (def_name == NULL) {
+ *res = FFC_CHECK_INVALID_Q_VALUE;
+ goto err;
+ }
+ md = EVP_MD_fetch(libctx, def_name, params->mdprops);
+ }
+ if (md == NULL)
+ goto err;
+ mdsize = EVP_MD_get_size(md);
+ if (mdsize <= 0)
+ goto err;
+
+ if (N == 0)
+ N = mdsize * 8;
+ qsize = N >> 3;
+
+ /*
+ * A.1.1.2 Step (1) AND
+ * A.1.1.3 Step (3)
+ * Check that the L,N pair is an acceptable pair.
+ */
+ if (L <= N || !ffc_validate_LN(L, N, type, verify)) {
+ *res = FFC_CHECK_BAD_LN_PAIR;
+ goto err;
+ }
+
+ mctx = EVP_MD_CTX_new();
+ if (mctx == NULL)
+ goto err;
+
+ if ((ctx = BN_CTX_new_ex(libctx)) == NULL)
+ goto err;
+
+ BN_CTX_start(ctx);
+ g = BN_CTX_get(ctx);
+ pm1 = BN_CTX_get(ctx);
+ e = BN_CTX_get(ctx);
+ test = BN_CTX_get(ctx);
+ tmp = BN_CTX_get(ctx);
+ if (tmp == NULL)
+ goto err;
+
+ seedlen = params->seedlen;
+ if (seedlen == 0)
+ seedlen = (size_t)mdsize;
+ /* If the seed was passed in - use this value as the seed */
+ if (params->seed != NULL)
+ seed = params->seed;
+
+ if (!verify) {
+ /* For generation: p & q must both be NULL or NON-NULL */
+ if ((params->p == NULL) != (params->q == NULL)) {
+ *res = FFC_CHECK_INVALID_PQ;
+ goto err;
+ }
+ } else {
+ /* Validation of p,q requires seed and counter to be valid */
+ if ((flags & FFC_PARAM_FLAG_VALIDATE_PQ) != 0) {
+ if (seed == NULL || params->pcounter < 0) {
+ *res = FFC_CHECK_MISSING_SEED_OR_COUNTER;
+ goto err;
+ }
+ }
+ if ((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0) {
+ /* validation of g also requires g to be set */
+ if (params->g == NULL) {
+ *res = FFC_CHECK_INVALID_G;
+ goto err;
+ }
+ }
+ }
+
+ /*
+ * If p & q are passed in and
+ * validate_flags = 0 then skip the generation of PQ.
+ * validate_flags = VALIDATE_G then also skip the validation of PQ.
+ */
+ if (params->p != NULL && ((flags & FFC_PARAM_FLAG_VALIDATE_PQ) == 0)) {
+ /* p and q already exists so only generate g */
+ p = params->p;
+ q = params->q;
+ goto g_only;
+ /* otherwise fall thru to validate p & q */
+ }
+
+ /* p & q will be used for generation and validation */
+ p = BN_CTX_get(ctx);
+ q = BN_CTX_get(ctx);
+ if (q == NULL)
+ goto err;
+
+ /*
+ * A.1.1.2 Step (2) AND
+ * A.1.1.3 Step (6)
+ * Return invalid if seedlen < N
+ */
+ if ((seedlen * 8) < N) {
+ *res = FFC_CHECK_INVALID_SEED_SIZE;
+ goto err;
+ }
+
+ seed_tmp = OPENSSL_malloc(seedlen);
+ if (seed_tmp == NULL)
+ goto err;
+
+ if (seed == NULL) {
+ /* Validation requires the seed to be supplied */
+ if (verify) {
+ *res = FFC_CHECK_MISSING_SEED_OR_COUNTER;
+ goto err;
+ }
+ /* if the seed is not supplied then alloc a seed buffer */
+ seed = OPENSSL_malloc(seedlen);
+ if (seed == NULL)
+ goto err;
+ }
+
+ /* A.1.1.2 Step (11): max loop count = 4L - 1 */
+ counter = 4 * L - 1;
+ /* Validation requires the counter to be supplied */
+ if (verify) {
+ /* A.1.1.3 Step (4) : if (counter > (4L -1)) return INVALID */
+ if (params->pcounter > counter) {
+ *res = FFC_CHECK_INVALID_COUNTER;
+ goto err;
+ }
+ counter = params->pcounter;
+ }
+
+ /*
+ * A.1.1.2 Step (3) AND
+ * A.1.1.3 Step (10)
+ * n = floor(L / hash_outlen) - 1
+ */
+ n = (L - 1 ) / (mdsize << 3);
+
+ /* Calculate 2^(L-1): Used in step A.1.1.2 Step (11.3) */
+ if (!BN_lshift(test, BN_value_one(), L - 1))
+ goto err;
+
+ for (;;) {
+ if (!generate_q_fips186_4(ctx, q, md, qsize, seed, seedlen,
+ seed != params->seed, &m, res, cb))
+ goto err;
+ /* A.1.1.3 Step (9): Verify that q matches the expected value */
+ if (verify && (BN_cmp(q, params->q) != 0)) {
+ *res = FFC_CHECK_Q_MISMATCH;
+ goto err;
+ }
+ if(!BN_GENCB_call(cb, 2, 0))
+ goto err;
+ if(!BN_GENCB_call(cb, 3, 0))
+ goto err;
+
+ memcpy(seed_tmp, seed, seedlen);
+ r = generate_p(ctx, md, counter, n, seed_tmp, seedlen, q, p, L,
+ cb, &pcounter, res);
+ if (r > 0)
+ break; /* found p */
+ if (r < 0)
+ goto err;
+ /*
+ * A.1.1.3 Step (14):
+ * If we get here we failed to get a p for the given seed. If the
+ * seed is not random then it needs to fail (as it will always fail).
+ */
+ if (seed == params->seed) {
+ *res = FFC_CHECK_P_NOT_PRIME;
+ goto err;
+ }
+ }
+ if(!BN_GENCB_call(cb, 2, 1))
+ goto err;
+ /*
+ * Gets here if we found p.
+ * A.1.1.3 Step (14): return error if i != counter OR computed_p != known_p.
+ */
+ if (verify && (pcounter != counter || (BN_cmp(p, params->p) != 0)))
+ goto err;
+
+ /* If validating p & q only then skip the g validation test */
+ if ((flags & FFC_PARAM_FLAG_VALIDATE_PQG) == FFC_PARAM_FLAG_VALIDATE_PQ)
+ goto pass;
+g_only:
+ if ((mont = BN_MONT_CTX_new()) == NULL)
+ goto err;
+ if (!BN_MONT_CTX_set(mont, p, ctx))
+ goto err;
+
+ if (((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0)
+ && !ossl_ffc_params_validate_unverifiable_g(ctx, mont, p, q, params->g,
+ tmp, res))
+ goto err;
+
+ /*
+ * A.2.1 Step (1) AND
+ * A.2.3 Step (3) AND
+ * A.2.4 Step (5)
+ * e = (p - 1) / q (i.e- Cofactor 'e' is given by p = q * e + 1)
+ */
+ if (!(BN_sub(pm1, p, BN_value_one()) && BN_div(e, NULL, pm1, q, ctx)))
+ goto err;
+
+ /* Canonical g requires a seed and index to be set */
+ if ((seed != NULL) && (params->gindex != FFC_UNVERIFIABLE_GINDEX)) {
+ canonical_g = 1;
+ if (!generate_canonical_g(ctx, mont, md, g, tmp, p, e,
+ params->gindex, seed, seedlen)) {
+ *res = FFC_CHECK_INVALID_G;
+ goto err;
+ }
+ /* A.2.4 Step (13): Return valid if computed_g == g */
+ if (verify && BN_cmp(g, params->g) != 0) {
+ *res = FFC_CHECK_G_MISMATCH;
+ goto err;
+ }
+ } else if (!verify) {
+ if (!generate_unverifiable_g(ctx, mont, g, tmp, p, e, pm1, &hret))
+ goto err;
+ }
+
+ if (!BN_GENCB_call(cb, 3, 1))
+ goto err;
+
+ if (!verify) {
+ if (p != params->p) {
+ BN_free(params->p);
+ params->p = BN_dup(p);
+ }
+ if (q != params->q) {
+ BN_free(params->q);
+ params->q = BN_dup(q);
+ }
+ if (g != params->g) {
+ BN_free(params->g);
+ params->g = BN_dup(g);
+ }
+ if (params->p == NULL || params->q == NULL || params->g == NULL)
+ goto err;
+ if (!ossl_ffc_params_set_validate_params(params, seed, seedlen,
+ pcounter))
+ goto err;
+ params->h = hret;
+ }
+pass:
+ if ((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0 && (canonical_g == 0))
+ /* Return for the case where g is partially valid */
+ ok = FFC_PARAM_RET_STATUS_UNVERIFIABLE_G;
+ else
+ ok = FFC_PARAM_RET_STATUS_SUCCESS;
+err:
+ if (seed != params->seed)
+ OPENSSL_free(seed);
+ OPENSSL_free(seed_tmp);
+ if (ctx != NULL)
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ BN_MONT_CTX_free(mont);
+ EVP_MD_CTX_free(mctx);
+ EVP_MD_free(md);
+ return ok;
+}
+
+/* Note this function is only used for verification in fips mode */
+int ossl_ffc_params_FIPS186_2_gen_verify(OSSL_LIB_CTX *libctx,
+ FFC_PARAMS *params, int mode, int type,
+ size_t L, size_t N, int *res,
+ BN_GENCB *cb)
+{
+ int ok = FFC_PARAM_RET_STATUS_FAILED;
+ unsigned char seed[SHA256_DIGEST_LENGTH];
+ unsigned char buf[SHA256_DIGEST_LENGTH];
+ BIGNUM *r0, *test, *tmp, *g = NULL, *q = NULL, *p = NULL;
+ BN_MONT_CTX *mont = NULL;
+ EVP_MD *md = NULL;
+ size_t qsize;
+ int n = 0, m = 0;
+ int counter = 0, pcounter = 0, use_random_seed;
+ int rv;
+ BN_CTX *ctx = NULL;
+ int hret = -1;
+ unsigned char *seed_in = params->seed;
+ size_t seed_len = params->seedlen;
+ int verify = (mode == FFC_PARAM_MODE_VERIFY);
+ unsigned int flags = verify ? params->flags : 0;
+ const char *def_name;
+
+ *res = 0;
+
+ if (params->mdname != NULL) {
+ md = EVP_MD_fetch(libctx, params->mdname, params->mdprops);
+ } else {
+ if (N == 0)
+ N = (L >= 2048 ? SHA256_DIGEST_LENGTH : SHA_DIGEST_LENGTH) * 8;
+ def_name = default_mdname(N);
+ if (def_name == NULL) {
+ *res = FFC_CHECK_INVALID_Q_VALUE;
+ goto err;
+ }
+ md = EVP_MD_fetch(libctx, def_name, params->mdprops);
+ }
+ if (md == NULL)
+ goto err;
+ if (N == 0)
+ N = EVP_MD_get_size(md) * 8;
+ qsize = N >> 3;
+
+ /*
+ * The original spec allowed L = 512 + 64*j (j = 0.. 8)
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf
+ * says that 512 can be used for legacy verification.
+ */
+ if (L < 512) {
+ *res = FFC_CHECK_BAD_LN_PAIR;
+ goto err;
+ }
+ if (qsize != SHA_DIGEST_LENGTH
+ && qsize != SHA224_DIGEST_LENGTH
+ && qsize != SHA256_DIGEST_LENGTH) {
+ /* invalid q size */
+ *res = FFC_CHECK_INVALID_Q_VALUE;
+ goto err;
+ }
+
+ L = (L + 63) / 64 * 64;
+
+ if (seed_in != NULL) {
+ if (seed_len < qsize) {
+ *res = FFC_CHECK_INVALID_SEED_SIZE;
+ goto err;
+ }
+ /* Only consume as much seed as is expected. */
+ if (seed_len > qsize)
+ seed_len = qsize;
+ memcpy(seed, seed_in, seed_len);
+ }
+
+ ctx = BN_CTX_new_ex(libctx);
+ if (ctx == NULL)
+ goto err;
+
+ BN_CTX_start(ctx);
+
+ r0 = BN_CTX_get(ctx);
+ g = BN_CTX_get(ctx);
+ q = BN_CTX_get(ctx);
+ p = BN_CTX_get(ctx);
+ tmp = BN_CTX_get(ctx);
+ test = BN_CTX_get(ctx);
+ if (test == NULL)
+ goto err;
+
+ if (!BN_lshift(test, BN_value_one(), L - 1))
+ goto err;
+
+ if (!verify) {
+ /* For generation: p & q must both be NULL or NON-NULL */
+ if ((params->p != NULL) != (params->q != NULL)) {
+ *res = FFC_CHECK_INVALID_PQ;
+ goto err;
+ }
+ } else {
+ if ((flags & FFC_PARAM_FLAG_VALIDATE_PQ) != 0) {
+ /* Validation of p,q requires seed and counter to be valid */
+ if (seed_in == NULL || params->pcounter < 0) {
+ *res = FFC_CHECK_MISSING_SEED_OR_COUNTER;
+ goto err;
+ }
+ }
+ if ((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0) {
+ /* validation of g also requires g to be set */
+ if (params->g == NULL) {
+ *res = FFC_CHECK_INVALID_G;
+ goto err;
+ }
+ }
+ }
+
+ if (params->p != NULL && ((flags & FFC_PARAM_FLAG_VALIDATE_PQ) == 0)) {
+ /* p and q already exists so only generate g */
+ p = params->p;
+ q = params->q;
+ goto g_only;
+ /* otherwise fall thru to validate p and q */
+ }
+
+ use_random_seed = (seed_in == NULL);
+ for (;;) {
+ if (!generate_q_fips186_2(ctx, q, md, buf, seed, qsize,
+ use_random_seed, &m, res, cb))
+ goto err;
+
+ if (!BN_GENCB_call(cb, 2, 0))
+ goto err;
+ if (!BN_GENCB_call(cb, 3, 0))
+ goto err;
+
+ /* step 6 */
+ n = (L - 1) / 160;
+ counter = 4 * L - 1; /* Was 4096 */
+ /* Validation requires the counter to be supplied */
+ if (verify) {
+ if (params->pcounter > counter) {
+ *res = FFC_CHECK_INVALID_COUNTER;
+ goto err;
+ }
+ counter = params->pcounter;
+ }
+
+ rv = generate_p(ctx, md, counter, n, buf, qsize, q, p, L, cb,
+ &pcounter, res);
+ if (rv > 0)
+ break; /* found it */
+ if (rv == -1)
+ goto err;
+ /* This is what the old code did - probably not a good idea! */
+ use_random_seed = 1;
+ }
+
+ if (!BN_GENCB_call(cb, 2, 1))
+ goto err;
+
+ if (verify) {
+ if (pcounter != counter) {
+ *res = FFC_CHECK_COUNTER_MISMATCH;
+ goto err;
+ }
+ if (BN_cmp(p, params->p) != 0) {
+ *res = FFC_CHECK_P_MISMATCH;
+ goto err;
+ }
+ }
+ /* If validating p & q only then skip the g validation test */
+ if ((flags & FFC_PARAM_FLAG_VALIDATE_PQG) == FFC_PARAM_FLAG_VALIDATE_PQ)
+ goto pass;
+g_only:
+ if ((mont = BN_MONT_CTX_new()) == NULL)
+ goto err;
+ if (!BN_MONT_CTX_set(mont, p, ctx))
+ goto err;
+
+ if (!verify) {
+ /* We now need to generate g */
+ /* set test = p - 1 */
+ if (!BN_sub(test, p, BN_value_one()))
+ goto err;
+ /* Set r0 = (p - 1) / q */
+ if (!BN_div(r0, NULL, test, q, ctx))
+ goto err;
+ if (!generate_unverifiable_g(ctx, mont, g, tmp, p, r0, test, &hret))
+ goto err;
+ } else if (((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0)
+ && !ossl_ffc_params_validate_unverifiable_g(ctx, mont, p, q,
+ params->g, tmp,
+ res)) {
+ goto err;
+ }
+
+ if (!BN_GENCB_call(cb, 3, 1))
+ goto err;
+
+ if (!verify) {
+ if (p != params->p) {
+ BN_free(params->p);
+ params->p = BN_dup(p);
+ }
+ if (q != params->q) {
+ BN_free(params->q);
+ params->q = BN_dup(q);
+ }
+ if (g != params->g) {
+ BN_free(params->g);
+ params->g = BN_dup(g);
+ }
+ if (params->p == NULL || params->q == NULL || params->g == NULL)
+ goto err;
+ if (!ossl_ffc_params_set_validate_params(params, seed, qsize, pcounter))
+ goto err;
+ params->h = hret;
+ }
+pass:
+ if ((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0)
+ ok = FFC_PARAM_RET_STATUS_UNVERIFIABLE_G;
+ else
+ ok = FFC_PARAM_RET_STATUS_SUCCESS;
+err:
+ if (ctx != NULL)
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ BN_MONT_CTX_free(mont);
+ EVP_MD_free(md);
+ return ok;
+}
+
+int ossl_ffc_params_FIPS186_4_generate(OSSL_LIB_CTX *libctx, FFC_PARAMS *params,
+ int type, size_t L, size_t N,
+ int *res, BN_GENCB *cb)
+{
+ return ossl_ffc_params_FIPS186_4_gen_verify(libctx, params,
+ FFC_PARAM_MODE_GENERATE,
+ type, L, N, res, cb);
+}
+
+/* This should no longer be used in FIPS mode */
+int ossl_ffc_params_FIPS186_2_generate(OSSL_LIB_CTX *libctx, FFC_PARAMS *params,
+ int type, size_t L, size_t N,
+ int *res, BN_GENCB *cb)
+{
+ if (!ossl_ffc_params_FIPS186_2_gen_verify(libctx, params,
+ FFC_PARAM_MODE_GENERATE,
+ type, L, N, res, cb))
+ return 0;
+
+ ossl_ffc_params_enable_flags(params, FFC_PARAM_FLAG_VALIDATE_LEGACY, 1);
+ return 1;
+}
diff --git a/crypto/ffc/ffc_params_validate.c b/crypto/ffc/ffc_params_validate.c
new file mode 100644
index 000000000000..c1b4cf05d200
--- /dev/null
+++ b/crypto/ffc/ffc_params_validate.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Finite Field cryptography (FFC) is used for DSA and DH.
+ * This file contains methods for validation of FFC parameters.
+ * It calls the same functions as the generation as the code is very similar.
+ */
+
+#include <openssl/err.h>
+#include <openssl/bn.h>
+#include <openssl/dsaerr.h>
+#include <openssl/dherr.h>
+#include "internal/ffc.h"
+
+/* FIPS186-4 A.2.2 Unverifiable partial validation of Generator g */
+int ossl_ffc_params_validate_unverifiable_g(BN_CTX *ctx, BN_MONT_CTX *mont,
+ const BIGNUM *p, const BIGNUM *q,
+ const BIGNUM *g, BIGNUM *tmp,
+ int *ret)
+{
+ /*
+ * A.2.2 Step (1) AND
+ * A.2.4 Step (2)
+ * Verify that 2 <= g <= (p - 1)
+ */
+ if (BN_cmp(g, BN_value_one()) <= 0 || BN_cmp(g, p) >= 0) {
+ *ret |= FFC_ERROR_NOT_SUITABLE_GENERATOR;
+ return 0;
+ }
+
+ /*
+ * A.2.2 Step (2) AND
+ * A.2.4 Step (3)
+ * Check g^q mod p = 1
+ */
+ if (!BN_mod_exp_mont(tmp, g, q, p, ctx, mont))
+ return 0;
+ if (BN_cmp(tmp, BN_value_one()) != 0) {
+ *ret |= FFC_ERROR_NOT_SUITABLE_GENERATOR;
+ return 0;
+ }
+ return 1;
+}
+
+int ossl_ffc_params_FIPS186_4_validate(OSSL_LIB_CTX *libctx,
+ const FFC_PARAMS *params, int type,
+ int *res, BN_GENCB *cb)
+{
+ size_t L, N;
+
+ if (params == NULL || params->p == NULL || params->q == NULL)
+ return FFC_PARAM_RET_STATUS_FAILED;
+
+ /* A.1.1.3 Step (1..2) : L = len(p), N = len(q) */
+ L = BN_num_bits(params->p);
+ N = BN_num_bits(params->q);
+ return ossl_ffc_params_FIPS186_4_gen_verify(libctx, (FFC_PARAMS *)params,
+ FFC_PARAM_MODE_VERIFY, type,
+ L, N, res, cb);
+}
+
+/* This may be used in FIPS mode to validate deprecated FIPS-186-2 Params */
+int ossl_ffc_params_FIPS186_2_validate(OSSL_LIB_CTX *libctx,
+ const FFC_PARAMS *params, int type,
+ int *res, BN_GENCB *cb)
+{
+ size_t L, N;
+
+ if (params == NULL || params->p == NULL || params->q == NULL) {
+ *res = FFC_CHECK_INVALID_PQ;
+ return FFC_PARAM_RET_STATUS_FAILED;
+ }
+
+ /* A.1.1.3 Step (1..2) : L = len(p), N = len(q) */
+ L = BN_num_bits(params->p);
+ N = BN_num_bits(params->q);
+ return ossl_ffc_params_FIPS186_2_gen_verify(libctx, (FFC_PARAMS *)params,
+ FFC_PARAM_MODE_VERIFY, type,
+ L, N, res, cb);
+}
+
+/*
+ * This does a simple check of L and N and partial g.
+ * It makes no attempt to do a full validation of p, q or g since these require
+ * extra parameters such as the digest and seed, which may not be available for
+ * this test.
+ */
+int ossl_ffc_params_simple_validate(OSSL_LIB_CTX *libctx, const FFC_PARAMS *params,
+ int paramstype, int *res)
+{
+ int ret;
+ int tmpres = 0;
+ FFC_PARAMS tmpparams = {0};
+
+ if (params == NULL)
+ return 0;
+
+ if (res == NULL)
+ res = &tmpres;
+
+ if (!ossl_ffc_params_copy(&tmpparams, params))
+ return 0;
+
+ tmpparams.flags = FFC_PARAM_FLAG_VALIDATE_G;
+ tmpparams.gindex = FFC_UNVERIFIABLE_GINDEX;
+
+#ifndef FIPS_MODULE
+ if (params->flags & FFC_PARAM_FLAG_VALIDATE_LEGACY)
+ ret = ossl_ffc_params_FIPS186_2_validate(libctx, &tmpparams, paramstype,
+ res, NULL);
+ else
+#endif
+ ret = ossl_ffc_params_FIPS186_4_validate(libctx, &tmpparams, paramstype,
+ res, NULL);
+#ifndef OPENSSL_NO_DH
+ if (ret == FFC_PARAM_RET_STATUS_FAILED
+ && (*res & FFC_ERROR_NOT_SUITABLE_GENERATOR) != 0) {
+ ERR_raise(ERR_LIB_DH, DH_R_NOT_SUITABLE_GENERATOR);
+ }
+#endif
+
+ ossl_ffc_params_cleanup(&tmpparams);
+
+ return ret != FFC_PARAM_RET_STATUS_FAILED;
+}
+
+/*
+ * If possible (or always in FIPS_MODULE) do full FIPS 186-4 validation.
+ * Otherwise do simple check but in addition also check the primality of the
+ * p and q.
+ */
+int ossl_ffc_params_full_validate(OSSL_LIB_CTX *libctx, const FFC_PARAMS *params,
+ int paramstype, int *res)
+{
+ int tmpres = 0;
+
+ if (params == NULL)
+ return 0;
+
+ if (res == NULL)
+ res = &tmpres;
+
+#ifdef FIPS_MODULE
+ return ossl_ffc_params_FIPS186_4_validate(libctx, params, paramstype,
+ res, NULL);
+#else
+ if (params->seed != NULL) {
+ if (params->flags & FFC_PARAM_FLAG_VALIDATE_LEGACY)
+ return ossl_ffc_params_FIPS186_2_validate(libctx, params, paramstype,
+ res, NULL);
+ else
+ return ossl_ffc_params_FIPS186_4_validate(libctx, params, paramstype,
+ res, NULL);
+ } else {
+ int ret = 0;
+
+ ret = ossl_ffc_params_simple_validate(libctx, params, paramstype, res);
+ if (ret) {
+ BN_CTX *ctx;
+
+ if ((ctx = BN_CTX_new_ex(libctx)) == NULL)
+ return 0;
+ if (BN_check_prime(params->q, ctx, NULL) != 1) {
+# ifndef OPENSSL_NO_DSA
+ ERR_raise(ERR_LIB_DSA, DSA_R_Q_NOT_PRIME);
+# endif
+ ret = 0;
+ }
+ if (ret && BN_check_prime(params->p, ctx, NULL) != 1) {
+# ifndef OPENSSL_NO_DSA
+ ERR_raise(ERR_LIB_DSA, DSA_R_P_NOT_PRIME);
+# endif
+ ret = 0;
+ }
+ BN_CTX_free(ctx);
+ }
+ return ret;
+ }
+#endif
+}
diff --git a/crypto/getenv.c b/crypto/getenv.c
index 7e98b645b0d1..e79b6cc1618f 100644
--- a/crypto/getenv.c
+++ b/crypto/getenv.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,9 +13,81 @@
#include <stdlib.h>
#include "internal/cryptlib.h"
+#include "e_os.h"
char *ossl_safe_getenv(const char *name)
{
+#if defined(_WIN32) && defined(CP_UTF8) && !defined(_WIN32_WCE)
+ if (GetEnvironmentVariableW(L"OPENSSL_WIN32_UTF8", NULL, 0) != 0) {
+ char *val = NULL;
+ int vallen = 0;
+ WCHAR *namew = NULL;
+ WCHAR *valw = NULL;
+ DWORD envlen = 0;
+ DWORD dwFlags = MB_ERR_INVALID_CHARS;
+ int rsize, fsize;
+ UINT curacp;
+
+ curacp = GetACP();
+
+ /*
+ * For the code pages listed below, dwFlags must be set to 0.
+ * Otherwise, the function fails with ERROR_INVALID_FLAGS.
+ */
+ if (curacp == 50220 || curacp == 50221 || curacp == 50222 ||
+ curacp == 50225 || curacp == 50227 || curacp == 50229 ||
+ (57002 <= curacp && curacp <=57011) || curacp == 65000 ||
+ curacp == 42)
+ dwFlags = 0;
+
+ /* query for buffer len */
+ rsize = MultiByteToWideChar(curacp, dwFlags, name, -1, NULL, 0);
+ /* if name is valid string and can be converted to wide string */
+ if (rsize > 0)
+ namew = _malloca(rsize * sizeof(WCHAR));
+
+ if (NULL != namew) {
+ /* convert name to wide string */
+ fsize = MultiByteToWideChar(curacp, dwFlags, name, -1, namew, rsize);
+ /* if conversion is ok, then determine value string size in wchars */
+ if (fsize > 0)
+ envlen = GetEnvironmentVariableW(namew, NULL, 0);
+ }
+
+ if (envlen > 0)
+ valw = _malloca(envlen * sizeof(WCHAR));
+
+ if (NULL != valw) {
+ /* if can get env value as wide string */
+ if (GetEnvironmentVariableW(namew, valw, envlen) < envlen) {
+ /* determine value string size in utf-8 */
+ vallen = WideCharToMultiByte(CP_UTF8, 0, valw, -1, NULL, 0,
+ NULL, NULL);
+ }
+ }
+
+ if (vallen > 0)
+ val = OPENSSL_malloc(vallen);
+
+ if (NULL != val) {
+ /* convert value string from wide to utf-8 */
+ if (WideCharToMultiByte(CP_UTF8, 0, valw, -1, val, vallen,
+ NULL, NULL) == 0) {
+ OPENSSL_free(val);
+ val = NULL;
+ }
+ }
+
+ if (NULL != namew)
+ _freea(namew);
+
+ if (NULL != valw)
+ _freea(valw);
+
+ return val;
+ }
+#endif
+
#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
# if __GLIBC_PREREQ(2, 17)
# define SECURE_GETENV
diff --git a/crypto/hmac/build.info b/crypto/hmac/build.info
index 09f67c2a028e..b828ab122e49 100644
--- a/crypto/hmac/build.info
+++ b/crypto/hmac/build.info
@@ -1,3 +1,6 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- hmac.c hm_ameth.c hm_pmeth.c
+
+$COMMON=hmac.c
+
+SOURCE[../../libcrypto]=$COMMON
+SOURCE[../../providers/libfips.a]=$COMMON
diff --git a/crypto/hmac/hm_ameth.c b/crypto/hmac/hm_ameth.c
deleted file mode 100644
index f871e4fe71e5..000000000000
--- a/crypto/hmac/hm_ameth.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/evp.h>
-#include "crypto/asn1.h"
-#include "crypto/evp.h"
-
-/*
- * HMAC "ASN1" method. This is just here to indicate the maximum HMAC output
- * length and to free up an HMAC key.
- */
-
-static int hmac_size(const EVP_PKEY *pkey)
-{
- return EVP_MAX_MD_SIZE;
-}
-
-static void hmac_key_free(EVP_PKEY *pkey)
-{
- ASN1_OCTET_STRING *os = EVP_PKEY_get0(pkey);
- if (os) {
- if (os->data)
- OPENSSL_cleanse(os->data, os->length);
- ASN1_OCTET_STRING_free(os);
- }
-}
-
-static int hmac_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
-{
- switch (op) {
- case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
- *(int *)arg2 = NID_sha256;
- return 1;
-
- default:
- return -2;
- }
-}
-
-static int hmac_pkey_public_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
-{
- /* the ameth pub_cmp must return 1 on match, 0 on mismatch */
- return ASN1_OCTET_STRING_cmp(EVP_PKEY_get0(a), EVP_PKEY_get0(b)) == 0;
-}
-
-static int hmac_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
- size_t len)
-{
- ASN1_OCTET_STRING *os;
-
- if (pkey->pkey.ptr != NULL)
- return 0;
-
- os = ASN1_OCTET_STRING_new();
- if (os == NULL)
- return 0;
-
-
- if (!ASN1_OCTET_STRING_set(os, priv, len)) {
- ASN1_OCTET_STRING_free(os);
- return 0;
- }
-
- pkey->pkey.ptr = os;
- return 1;
-}
-
-static int hmac_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
- size_t *len)
-{
- ASN1_OCTET_STRING *os = (ASN1_OCTET_STRING *)pkey->pkey.ptr;
-
- if (priv == NULL) {
- *len = ASN1_STRING_length(os);
- return 1;
- }
-
- if (os == NULL || *len < (size_t)ASN1_STRING_length(os))
- return 0;
-
- *len = ASN1_STRING_length(os);
- memcpy(priv, ASN1_STRING_get0_data(os), *len);
-
- return 1;
-}
-
-const EVP_PKEY_ASN1_METHOD hmac_asn1_meth = {
- EVP_PKEY_HMAC,
- EVP_PKEY_HMAC,
- 0,
-
- "HMAC",
- "OpenSSL HMAC method",
-
- 0, 0, hmac_pkey_public_cmp, 0,
-
- 0, 0, 0,
-
- hmac_size,
- 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-
- hmac_key_free,
- hmac_pkey_ctrl,
- NULL,
- NULL,
-
- NULL,
- NULL,
- NULL,
-
- NULL,
- NULL,
- NULL,
-
- hmac_set_priv_key,
- NULL,
- hmac_get_priv_key,
- NULL,
-};
diff --git a/crypto/hmac/hm_pmeth.c b/crypto/hmac/hm_pmeth.c
deleted file mode 100644
index 56f98707f539..000000000000
--- a/crypto/hmac/hm_pmeth.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-#include <openssl/evp.h>
-#include <openssl/hmac.h>
-#include <openssl/err.h>
-#include "crypto/evp.h"
-
-/* HMAC pkey context structure */
-
-typedef struct {
- const EVP_MD *md; /* MD for HMAC use */
- ASN1_OCTET_STRING ktmp; /* Temp storage for key */
- HMAC_CTX *ctx;
-} HMAC_PKEY_CTX;
-
-static int pkey_hmac_init(EVP_PKEY_CTX *ctx)
-{
- HMAC_PKEY_CTX *hctx;
-
- if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) {
- CRYPTOerr(CRYPTO_F_PKEY_HMAC_INIT, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- hctx->ktmp.type = V_ASN1_OCTET_STRING;
- hctx->ctx = HMAC_CTX_new();
- if (hctx->ctx == NULL) {
- OPENSSL_free(hctx);
- return 0;
- }
-
- ctx->data = hctx;
- ctx->keygen_info_count = 0;
-
- return 1;
-}
-
-static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx);
-
-static int pkey_hmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
-{
- HMAC_PKEY_CTX *sctx, *dctx;
-
- /* allocate memory for dst->data and a new HMAC_CTX in dst->data->ctx */
- if (!pkey_hmac_init(dst))
- return 0;
- sctx = EVP_PKEY_CTX_get_data(src);
- dctx = EVP_PKEY_CTX_get_data(dst);
- dctx->md = sctx->md;
- if (!HMAC_CTX_copy(dctx->ctx, sctx->ctx))
- goto err;
- if (sctx->ktmp.data) {
- if (!ASN1_OCTET_STRING_set(&dctx->ktmp,
- sctx->ktmp.data, sctx->ktmp.length))
- goto err;
- }
- return 1;
-err:
- /* release HMAC_CTX in dst->data->ctx and memory allocated for dst->data */
- pkey_hmac_cleanup (dst);
- return 0;
-}
-
-static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx)
-{
- HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
-
- if (hctx != NULL) {
- HMAC_CTX_free(hctx->ctx);
- OPENSSL_clear_free(hctx->ktmp.data, hctx->ktmp.length);
- OPENSSL_free(hctx);
- EVP_PKEY_CTX_set_data(ctx, NULL);
- }
-}
-
-static int pkey_hmac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
-{
- ASN1_OCTET_STRING *hkey = NULL;
- HMAC_PKEY_CTX *hctx = ctx->data;
- if (!hctx->ktmp.data)
- return 0;
- hkey = ASN1_OCTET_STRING_dup(&hctx->ktmp);
- if (!hkey)
- return 0;
- EVP_PKEY_assign(pkey, EVP_PKEY_HMAC, hkey);
-
- return 1;
-}
-
-static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- HMAC_PKEY_CTX *hctx = EVP_MD_CTX_pkey_ctx(ctx)->data;
- if (!HMAC_Update(hctx->ctx, data, count))
- return 0;
- return 1;
-}
-
-static int hmac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
-{
- HMAC_PKEY_CTX *hctx = ctx->data;
- HMAC_CTX_set_flags(hctx->ctx,
- EVP_MD_CTX_test_flags(mctx, ~EVP_MD_CTX_FLAG_NO_INIT));
- EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
- EVP_MD_CTX_set_update_fn(mctx, int_update);
- return 1;
-}
-
-static int hmac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
- EVP_MD_CTX *mctx)
-{
- unsigned int hlen;
- HMAC_PKEY_CTX *hctx = ctx->data;
- int l = EVP_MD_CTX_size(mctx);
-
- if (l < 0)
- return 0;
- *siglen = l;
- if (!sig)
- return 1;
-
- if (!HMAC_Final(hctx->ctx, sig, &hlen))
- return 0;
- *siglen = (size_t)hlen;
- return 1;
-}
-
-static int pkey_hmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
-{
- HMAC_PKEY_CTX *hctx = ctx->data;
- ASN1_OCTET_STRING *key;
- switch (type) {
-
- case EVP_PKEY_CTRL_SET_MAC_KEY:
- if ((!p2 && p1 > 0) || (p1 < -1))
- return 0;
- if (!ASN1_OCTET_STRING_set(&hctx->ktmp, p2, p1))
- return 0;
- break;
-
- case EVP_PKEY_CTRL_MD:
- hctx->md = p2;
- break;
-
- case EVP_PKEY_CTRL_DIGESTINIT:
- key = (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr;
- if (!HMAC_Init_ex(hctx->ctx, key->data, key->length, hctx->md,
- ctx->engine))
- return 0;
- break;
-
- default:
- return -2;
-
- }
- return 1;
-}
-
-static int pkey_hmac_ctrl_str(EVP_PKEY_CTX *ctx,
- const char *type, const char *value)
-{
- if (!value) {
- return 0;
- }
- if (strcmp(type, "key") == 0)
- return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
- if (strcmp(type, "hexkey") == 0)
- return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
- return -2;
-}
-
-const EVP_PKEY_METHOD hmac_pkey_meth = {
- EVP_PKEY_HMAC,
- 0,
- pkey_hmac_init,
- pkey_hmac_copy,
- pkey_hmac_cleanup,
-
- 0, 0,
-
- 0,
- pkey_hmac_keygen,
-
- 0, 0,
-
- 0, 0,
-
- 0, 0,
-
- hmac_signctx_init,
- hmac_signctx,
-
- 0, 0,
-
- 0, 0,
-
- 0, 0,
-
- 0, 0,
-
- pkey_hmac_ctrl,
- pkey_hmac_ctrl_str
-};
diff --git a/crypto/hmac/hmac.c b/crypto/hmac/hmac.c
index 5e087bf92ff2..940d867ca652 100644
--- a/crypto/hmac/hmac.c
+++ b/crypto/hmac/hmac.c
@@ -1,18 +1,25 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * HMAC low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "internal/cryptlib.h"
-#include <openssl/hmac.h>
#include <openssl/opensslconf.h>
+#include <openssl/hmac.h>
+#include <openssl/core_names.h>
#include "hmac_local.h"
int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
@@ -28,27 +35,28 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
if (md != NULL && md != ctx->md && (key == NULL || len < 0))
return 0;
- if (md != NULL) {
+ if (md != NULL)
ctx->md = md;
- } else if (ctx->md) {
+ else if (ctx->md != NULL)
md = ctx->md;
- } else {
+ else
return 0;
- }
/*
- * The HMAC construction is not allowed to be used with the
+ * The HMAC construction is not allowed to be used with the
* extendable-output functions (XOF) shake128 and shake256.
*/
- if ((EVP_MD_meth_get_flags(md) & EVP_MD_FLAG_XOF) != 0)
+ if ((EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF) != 0)
return 0;
if (key != NULL) {
reset = 1;
- j = EVP_MD_block_size(md);
+ j = EVP_MD_get_block_size(md);
if (!ossl_assert(j <= (int)sizeof(keytmp)))
return 0;
+ if (j < 0)
+ return 0;
if (j < len) {
if (!EVP_DigestInit_ex(ctx->md_ctx, md, impl)
|| !EVP_DigestUpdate(ctx->md_ctx, key, len)
@@ -68,13 +76,15 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
for (i = 0; i < HMAC_MAX_MD_CBLOCK_SIZE; i++)
pad[i] = 0x36 ^ keytmp[i];
if (!EVP_DigestInit_ex(ctx->i_ctx, md, impl)
- || !EVP_DigestUpdate(ctx->i_ctx, pad, EVP_MD_block_size(md)))
+ || !EVP_DigestUpdate(ctx->i_ctx, pad,
+ EVP_MD_get_block_size(md)))
goto err;
for (i = 0; i < HMAC_MAX_MD_CBLOCK_SIZE; i++)
pad[i] = 0x5c ^ keytmp[i];
if (!EVP_DigestInit_ex(ctx->o_ctx, md, impl)
- || !EVP_DigestUpdate(ctx->o_ctx, pad, EVP_MD_block_size(md)))
+ || !EVP_DigestUpdate(ctx->o_ctx, pad,
+ EVP_MD_get_block_size(md)))
goto err;
}
if (!EVP_MD_CTX_copy_ex(ctx->md_ctx, ctx->i_ctx))
@@ -88,7 +98,7 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
return rv;
}
-#if OPENSSL_API_COMPAT < 0x10100000L
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
int HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md)
{
if (key && md)
@@ -127,7 +137,7 @@ int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len)
size_t HMAC_size(const HMAC_CTX *ctx)
{
- int size = EVP_MD_size((ctx)->md);
+ int size = EVP_MD_get_size((ctx)->md);
return (size < 0) ? 0 : size;
}
@@ -209,34 +219,22 @@ int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx)
}
unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
- const unsigned char *d, size_t n, unsigned char *md,
- unsigned int *md_len)
+ const unsigned char *data, size_t data_len,
+ unsigned char *md, unsigned int *md_len)
{
- HMAC_CTX *c = NULL;
- static unsigned char m[EVP_MAX_MD_SIZE];
- static const unsigned char dummy_key[1] = {'\0'};
-
- if (md == NULL)
- md = m;
- if ((c = HMAC_CTX_new()) == NULL)
- goto err;
-
- /* For HMAC_Init_ex, NULL key signals reuse. */
- if (key == NULL && key_len == 0) {
- key = dummy_key;
+ static unsigned char static_md[EVP_MAX_MD_SIZE];
+ int size = EVP_MD_get_size(evp_md);
+ size_t temp_md_len = 0;
+ unsigned char *ret = NULL;
+
+ if (size >= 0) {
+ ret = EVP_Q_mac(NULL, "HMAC", NULL, EVP_MD_get0_name(evp_md), NULL,
+ key, key_len, data, data_len,
+ md == NULL ? static_md : md, size, &temp_md_len);
+ if (md_len != NULL)
+ *md_len = (unsigned int)temp_md_len;
}
-
- if (!HMAC_Init_ex(c, key, key_len, evp_md, NULL))
- goto err;
- if (!HMAC_Update(c, d, n))
- goto err;
- if (!HMAC_Final(c, md, md_len))
- goto err;
- HMAC_CTX_free(c);
- return md;
- err:
- HMAC_CTX_free(c);
- return NULL;
+ return ret;
}
void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags)
diff --git a/crypto/hmac/hmac_local.h b/crypto/hmac/hmac_local.h
index 8bcc55817ae5..495b8593ffc6 100644
--- a/crypto/hmac/hmac_local.h
+++ b/crypto/hmac/hmac_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/http/build.info b/crypto/http/build.info
new file mode 100644
index 000000000000..b4626b13de7f
--- /dev/null
+++ b/crypto/http/build.info
@@ -0,0 +1,2 @@
+LIBS=../../libcrypto
+SOURCE[../../libcrypto]=http_client.c http_err.c http_lib.c
diff --git a/crypto/http/http_client.c b/crypto/http/http_client.c
new file mode 100644
index 000000000000..0d62f1c7bf16
--- /dev/null
+++ b/crypto/http/http_client.c
@@ -0,0 +1,1422 @@
+/*
+ * Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Siemens AG 2018-2020
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "e_os.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "crypto/ctype.h"
+#include <string.h>
+#include <openssl/asn1.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/httperr.h>
+#include <openssl/cmperr.h>
+#include <openssl/buffer.h>
+#include <openssl/http.h>
+#include "internal/sockets.h"
+#include "internal/cryptlib.h" /* for ossl_assert() */
+
+#define HAS_PREFIX(str, prefix) (strncmp(str, prefix, sizeof(prefix) - 1) == 0)
+#define HTTP_PREFIX "HTTP/"
+#define HTTP_VERSION_PATT "1." /* allow 1.x */
+#define HTTP_VERSION_STR_LEN sizeof(HTTP_VERSION_PATT) /* == strlen("1.0") */
+#define HTTP_PREFIX_VERSION HTTP_PREFIX""HTTP_VERSION_PATT
+#define HTTP_1_0 HTTP_PREFIX_VERSION"0" /* "HTTP/1.0" */
+#define HTTP_LINE1_MINLEN (sizeof(HTTP_PREFIX_VERSION "x 200\n") - 1)
+#define HTTP_VERSION_MAX_REDIRECTIONS 50
+
+#define HTTP_STATUS_CODE_OK 200
+#define HTTP_STATUS_CODE_MOVED_PERMANENTLY 301
+#define HTTP_STATUS_CODE_FOUND 302
+
+/* Stateful HTTP request code, supporting blocking and non-blocking I/O */
+
+/* Opaque HTTP request status structure */
+
+struct ossl_http_req_ctx_st {
+ int state; /* Current I/O state */
+ unsigned char *buf; /* Buffer to write request or read response */
+ int buf_size; /* Buffer size */
+ int free_wbio; /* wbio allocated internally, free with ctx */
+ BIO *wbio; /* BIO to write/send request to */
+ BIO *rbio; /* BIO to read/receive response from */
+ OSSL_HTTP_bio_cb_t upd_fn; /* Optional BIO update callback used for TLS */
+ void *upd_arg; /* Optional arg for update callback function */
+ int use_ssl; /* Use HTTPS */
+ char *proxy; /* Optional proxy name or URI */
+ char *server; /* Optional server host name */
+ char *port; /* Optional server port */
+ BIO *mem; /* Mem BIO holding request header or response */
+ BIO *req; /* BIO holding the request provided by caller */
+ int method_POST; /* HTTP method is POST (else GET) */
+ char *expected_ct; /* Optional expected Content-Type */
+ int expect_asn1; /* Response must be ASN.1-encoded */
+ unsigned char *pos; /* Current position sending data */
+ long len_to_send; /* Number of bytes still to send */
+ size_t resp_len; /* Length of response */
+ size_t max_resp_len; /* Maximum length of response, or 0 */
+ int keep_alive; /* Persistent conn. 0=no, 1=prefer, 2=require */
+ time_t max_time; /* Maximum end time of current transfer, or 0 */
+ time_t max_total_time; /* Maximum end time of total transfer, or 0 */
+ char *redirection_url; /* Location obtained from HTTP status 301/302 */
+};
+
+/* HTTP states */
+
+#define OHS_NOREAD 0x1000 /* If set no reading should be performed */
+#define OHS_ERROR (0 | OHS_NOREAD) /* Error condition */
+#define OHS_ADD_HEADERS (1 | OHS_NOREAD) /* Adding header lines to request */
+#define OHS_WRITE_INIT (2 | OHS_NOREAD) /* 1st call: ready to start send */
+#define OHS_WRITE_HDR (3 | OHS_NOREAD) /* Request header being sent */
+#define OHS_WRITE_REQ (4 | OHS_NOREAD) /* Request contents being sent */
+#define OHS_FLUSH (5 | OHS_NOREAD) /* Request being flushed */
+#define OHS_FIRSTLINE 1 /* First line of response being read */
+#define OHS_HEADERS 2 /* MIME headers of response being read */
+#define OHS_REDIRECT 3 /* MIME headers being read, expecting Location */
+#define OHS_ASN1_HEADER 4 /* ASN1 sequence header (tag+length) being read */
+#define OHS_ASN1_CONTENT 5 /* ASN1 content octets being read */
+#define OHS_ASN1_DONE (6 | OHS_NOREAD) /* ASN1 content read completed */
+#define OHS_STREAM (7 | OHS_NOREAD) /* HTTP content stream to be read */
+
+/* Low-level HTTP API implementation */
+
+OSSL_HTTP_REQ_CTX *OSSL_HTTP_REQ_CTX_new(BIO *wbio, BIO *rbio, int buf_size)
+{
+ OSSL_HTTP_REQ_CTX *rctx;
+
+ if (wbio == NULL || rbio == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+
+ if ((rctx = OPENSSL_zalloc(sizeof(*rctx))) == NULL)
+ return NULL;
+ rctx->state = OHS_ERROR;
+ rctx->buf_size = buf_size > 0 ? buf_size : OSSL_HTTP_DEFAULT_MAX_LINE_LEN;
+ rctx->buf = OPENSSL_malloc(rctx->buf_size);
+ rctx->wbio = wbio;
+ rctx->rbio = rbio;
+ if (rctx->buf == NULL) {
+ OPENSSL_free(rctx);
+ return NULL;
+ }
+ rctx->max_resp_len = OSSL_HTTP_DEFAULT_MAX_RESP_LEN;
+ /* everything else is 0, e.g. rctx->len_to_send, or NULL, e.g. rctx->mem */
+ return rctx;
+}
+
+void OSSL_HTTP_REQ_CTX_free(OSSL_HTTP_REQ_CTX *rctx)
+{
+ if (rctx == NULL)
+ return;
+ /*
+ * Use BIO_free_all() because bio_update_fn may prepend or append to cbio.
+ * This also frees any (e.g., SSL/TLS) BIOs linked with bio and,
+ * like BIO_reset(bio), calls SSL_shutdown() to notify/alert the peer.
+ */
+ if (rctx->free_wbio)
+ BIO_free_all(rctx->wbio);
+ /* do not free rctx->rbio */
+ BIO_free(rctx->mem);
+ BIO_free(rctx->req);
+ OPENSSL_free(rctx->buf);
+ OPENSSL_free(rctx->proxy);
+ OPENSSL_free(rctx->server);
+ OPENSSL_free(rctx->port);
+ OPENSSL_free(rctx->expected_ct);
+ OPENSSL_free(rctx);
+}
+
+BIO *OSSL_HTTP_REQ_CTX_get0_mem_bio(const OSSL_HTTP_REQ_CTX *rctx)
+{
+ if (rctx == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ return rctx->mem;
+}
+
+size_t OSSL_HTTP_REQ_CTX_get_resp_len(const OSSL_HTTP_REQ_CTX *rctx)
+{
+ if (rctx == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ return rctx->resp_len;
+}
+
+void OSSL_HTTP_REQ_CTX_set_max_response_length(OSSL_HTTP_REQ_CTX *rctx,
+ unsigned long len)
+{
+ if (rctx == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return;
+ }
+ rctx->max_resp_len = len != 0 ? (size_t)len : OSSL_HTTP_DEFAULT_MAX_RESP_LEN;
+}
+
+/*
+ * Create request line using |rctx| and |path| (or "/" in case |path| is NULL).
+ * Server name (and port) must be given if and only if plain HTTP proxy is used.
+ */
+int OSSL_HTTP_REQ_CTX_set_request_line(OSSL_HTTP_REQ_CTX *rctx, int method_POST,
+ const char *server, const char *port,
+ const char *path)
+{
+ if (rctx == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ BIO_free(rctx->mem);
+ if ((rctx->mem = BIO_new(BIO_s_mem())) == NULL)
+ return 0;
+
+ rctx->method_POST = method_POST != 0;
+ if (BIO_printf(rctx->mem, "%s ", rctx->method_POST ? "POST" : "GET") <= 0)
+ return 0;
+
+ if (server != NULL) { /* HTTP (but not HTTPS) proxy is used */
+ /*
+ * Section 5.1.2 of RFC 1945 states that the absoluteURI form is only
+ * allowed when using a proxy
+ */
+ if (BIO_printf(rctx->mem, OSSL_HTTP_PREFIX"%s", server) <= 0)
+ return 0;
+ if (port != NULL && BIO_printf(rctx->mem, ":%s", port) <= 0)
+ return 0;
+ }
+
+ /* Make sure path includes a forward slash */
+ if (path == NULL)
+ path = "/";
+ if (path[0] != '/' && BIO_printf(rctx->mem, "/") <= 0)
+ return 0;
+ /*
+ * Add (the rest of) the path and the HTTP version,
+ * which is fixed to 1.0 for straightforward implementation of keep-alive
+ */
+ if (BIO_printf(rctx->mem, "%s "HTTP_1_0"\r\n", path) <= 0)
+ return 0;
+
+ rctx->resp_len = 0;
+ rctx->state = OHS_ADD_HEADERS;
+ return 1;
+}
+
+int OSSL_HTTP_REQ_CTX_add1_header(OSSL_HTTP_REQ_CTX *rctx,
+ const char *name, const char *value)
+{
+ if (rctx == NULL || name == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (rctx->mem == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ if (BIO_puts(rctx->mem, name) <= 0)
+ return 0;
+ if (value != NULL) {
+ if (BIO_write(rctx->mem, ": ", 2) != 2)
+ return 0;
+ if (BIO_puts(rctx->mem, value) <= 0)
+ return 0;
+ }
+ return BIO_write(rctx->mem, "\r\n", 2) == 2;
+}
+
+int OSSL_HTTP_REQ_CTX_set_expected(OSSL_HTTP_REQ_CTX *rctx,
+ const char *content_type, int asn1,
+ int timeout, int keep_alive)
+{
+ if (rctx == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (keep_alive != 0
+ && rctx->state != OHS_ERROR && rctx->state != OHS_ADD_HEADERS) {
+ /* Cannot anymore set keep-alive in request header */
+ ERR_raise(ERR_LIB_HTTP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ OPENSSL_free(rctx->expected_ct);
+ rctx->expected_ct = NULL;
+ if (content_type != NULL
+ && (rctx->expected_ct = OPENSSL_strdup(content_type)) == NULL)
+ return 0;
+
+ rctx->expect_asn1 = asn1;
+ if (timeout >= 0)
+ rctx->max_time = timeout > 0 ? time(NULL) + timeout : 0;
+ else /* take over any |overall_timeout| arg of OSSL_HTTP_open(), else 0 */
+ rctx->max_time = rctx->max_total_time;
+ rctx->keep_alive = keep_alive;
+ return 1;
+}
+
+static int set1_content(OSSL_HTTP_REQ_CTX *rctx,
+ const char *content_type, BIO *req)
+{
+ long req_len = 0;
+#ifndef OPENSSL_NO_STDIO
+ FILE *fp = NULL;
+#endif
+
+ if (rctx == NULL || (req == NULL && content_type != NULL)) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (rctx->keep_alive != 0
+ && !OSSL_HTTP_REQ_CTX_add1_header(rctx, "Connection", "keep-alive"))
+ return 0;
+
+ BIO_free(rctx->req);
+ rctx->req = NULL;
+ if (req == NULL)
+ return 1;
+ if (!rctx->method_POST) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ if (content_type != NULL
+ && BIO_printf(rctx->mem, "Content-Type: %s\r\n", content_type) <= 0)
+ return 0;
+
+ /*
+ * BIO_CTRL_INFO yields the data length at least for memory BIOs, but for
+ * file-based BIOs it gives the current position, which is not what we need.
+ */
+ if (BIO_method_type(req) == BIO_TYPE_FILE) {
+#ifndef OPENSSL_NO_STDIO
+ if (BIO_get_fp(req, &fp) == 1 && fseek(fp, 0, SEEK_END) == 0) {
+ req_len = ftell(fp);
+ (void)fseek(fp, 0, SEEK_SET);
+ } else {
+ fp = NULL;
+ }
+#endif
+ } else {
+ req_len = BIO_ctrl(req, BIO_CTRL_INFO, 0, NULL);
+ /*
+ * Streaming BIOs likely will not support querying the size at all,
+ * and we assume we got a correct value if req_len > 0.
+ */
+ }
+ if ((
+#ifndef OPENSSL_NO_STDIO
+ fp != NULL /* definitely correct req_len */ ||
+#endif
+ req_len > 0)
+ && BIO_printf(rctx->mem, "Content-Length: %ld\r\n", req_len) < 0)
+ return 0;
+
+ if (!BIO_up_ref(req))
+ return 0;
+ rctx->req = req;
+ return 1;
+}
+
+int OSSL_HTTP_REQ_CTX_set1_req(OSSL_HTTP_REQ_CTX *rctx, const char *content_type,
+ const ASN1_ITEM *it, const ASN1_VALUE *req)
+{
+ BIO *mem = NULL;
+ int res = 1;
+
+ if (req != NULL)
+ res = (mem = ASN1_item_i2d_mem_bio(it, req)) != NULL;
+ res = res && set1_content(rctx, content_type, mem);
+ BIO_free(mem);
+ return res;
+}
+
+static int add1_headers(OSSL_HTTP_REQ_CTX *rctx,
+ const STACK_OF(CONF_VALUE) *headers, const char *host)
+{
+ int i;
+ int add_host = host != NULL && *host != '\0';
+ CONF_VALUE *hdr;
+
+ for (i = 0; i < sk_CONF_VALUE_num(headers); i++) {
+ hdr = sk_CONF_VALUE_value(headers, i);
+ if (add_host && OPENSSL_strcasecmp("host", hdr->name) == 0)
+ add_host = 0;
+ if (!OSSL_HTTP_REQ_CTX_add1_header(rctx, hdr->name, hdr->value))
+ return 0;
+ }
+
+ if (add_host && !OSSL_HTTP_REQ_CTX_add1_header(rctx, "Host", host))
+ return 0;
+ return 1;
+}
+
+/* Create OSSL_HTTP_REQ_CTX structure using the values provided. */
+static OSSL_HTTP_REQ_CTX *http_req_ctx_new(int free_wbio, BIO *wbio, BIO *rbio,
+ OSSL_HTTP_bio_cb_t bio_update_fn,
+ void *arg, int use_ssl,
+ const char *proxy,
+ const char *server, const char *port,
+ int buf_size, int overall_timeout)
+{
+ OSSL_HTTP_REQ_CTX *rctx = OSSL_HTTP_REQ_CTX_new(wbio, rbio, buf_size);
+
+ if (rctx == NULL)
+ return NULL;
+ rctx->free_wbio = free_wbio;
+ rctx->upd_fn = bio_update_fn;
+ rctx->upd_arg = arg;
+ rctx->use_ssl = use_ssl;
+ if (proxy != NULL
+ && (rctx->proxy = OPENSSL_strdup(proxy)) == NULL)
+ goto err;
+ if (server != NULL
+ && (rctx->server = OPENSSL_strdup(server)) == NULL)
+ goto err;
+ if (port != NULL
+ && (rctx->port = OPENSSL_strdup(port)) == NULL)
+ goto err;
+ rctx->max_total_time =
+ overall_timeout > 0 ? time(NULL) + overall_timeout : 0;
+ return rctx;
+
+ err:
+ OSSL_HTTP_REQ_CTX_free(rctx);
+ return NULL;
+}
+
+/*
+ * Parse first HTTP response line. This should be like this: "HTTP/1.0 200 OK".
+ * We need to obtain the status code and (optional) informational message.
+ * Return any received HTTP response status code, or 0 on fatal error.
+ */
+
+static int parse_http_line1(char *line, int *found_keep_alive)
+{
+ int i, retcode, err;
+ char *code, *reason, *end;
+
+ if (!HAS_PREFIX(line, HTTP_PREFIX_VERSION))
+ goto err;
+ /* above HTTP 1.0, connection persistence is the default */
+ *found_keep_alive = line[strlen(HTTP_PREFIX_VERSION)] > '0';
+
+ /* Skip to first whitespace (past protocol info) */
+ for (code = line; *code != '\0' && !ossl_isspace(*code); code++)
+ continue;
+ if (*code == '\0')
+ goto err;
+
+ /* Skip past whitespace to start of response code */
+ while (*code != '\0' && ossl_isspace(*code))
+ code++;
+ if (*code == '\0')
+ goto err;
+
+ /* Find end of response code: first whitespace after start of code */
+ for (reason = code; *reason != '\0' && !ossl_isspace(*reason); reason++)
+ continue;
+
+ if (*reason == '\0')
+ goto err;
+
+ /* Set end of response code and start of message */
+ *reason++ = '\0';
+
+ /* Attempt to parse numeric code */
+ retcode = strtoul(code, &end, 10);
+ if (*end != '\0')
+ goto err;
+
+ /* Skip over any leading whitespace in message */
+ while (*reason != '\0' && ossl_isspace(*reason))
+ reason++;
+
+ if (*reason != '\0') {
+ /*
+ * Finally zap any trailing whitespace in message (include CRLF)
+ */
+
+ /* chop any trailing whitespace from reason */
+ /* We know reason has a non-whitespace character so this is OK */
+ for (end = reason + strlen(reason) - 1; ossl_isspace(*end); end--)
+ *end = '\0';
+ }
+
+ switch (retcode) {
+ case HTTP_STATUS_CODE_OK:
+ case HTTP_STATUS_CODE_MOVED_PERMANENTLY:
+ case HTTP_STATUS_CODE_FOUND:
+ return retcode;
+ default:
+ err = HTTP_R_RECEIVED_ERROR;
+ if (retcode < 400)
+ err = HTTP_R_STATUS_CODE_UNSUPPORTED;
+ if (*reason == '\0')
+ ERR_raise_data(ERR_LIB_HTTP, err, "code=%s", code);
+ else
+ ERR_raise_data(ERR_LIB_HTTP, err, "code=%s, reason=%s", code,
+ reason);
+ return retcode;
+ }
+
+ err:
+ for (i = 0; i < 60 && line[i] != '\0'; i++)
+ if (!ossl_isprint(line[i]))
+ line[i] = ' ';
+ line[i] = '\0';
+ ERR_raise_data(ERR_LIB_HTTP, HTTP_R_HEADER_PARSE_ERROR, "content=%s", line);
+ return 0;
+}
+
+static int check_set_resp_len(OSSL_HTTP_REQ_CTX *rctx, size_t len)
+{
+ if (rctx->max_resp_len != 0 && len > rctx->max_resp_len)
+ ERR_raise_data(ERR_LIB_HTTP, HTTP_R_MAX_RESP_LEN_EXCEEDED,
+ "length=%zu, max=%zu", len, rctx->max_resp_len);
+ if (rctx->resp_len != 0 && rctx->resp_len != len)
+ ERR_raise_data(ERR_LIB_HTTP, HTTP_R_INCONSISTENT_CONTENT_LENGTH,
+ "ASN.1 length=%zu, Content-Length=%zu",
+ len, rctx->resp_len);
+ rctx->resp_len = len;
+ return 1;
+}
+
+static int may_still_retry(time_t max_time, int *ptimeout)
+{
+ time_t time_diff, now = time(NULL);
+
+ if (max_time != 0) {
+ if (max_time < now) {
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_RETRY_TIMEOUT);
+ return 0;
+ }
+ time_diff = max_time - now;
+ *ptimeout = time_diff > INT_MAX ? INT_MAX : (int)time_diff;
+ }
+ return 1;
+}
+
+/*
+ * Try exchanging request and response via HTTP on (non-)blocking BIO in rctx.
+ * Returns 1 on success, 0 on error or redirection, -1 on BIO_should_retry.
+ */
+int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
+{
+ int i, found_expected_ct = 0, found_keep_alive = 0;
+ long n;
+ size_t resp_len;
+ const unsigned char *p;
+ char *buf, *key, *value, *line_end = NULL;
+
+ if (rctx == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (rctx->mem == NULL || rctx->wbio == NULL || rctx->rbio == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ rctx->redirection_url = NULL;
+ next_io:
+ buf = (char *)rctx->buf;
+ if ((rctx->state & OHS_NOREAD) == 0) {
+ if (rctx->expect_asn1) {
+ n = BIO_read(rctx->rbio, rctx->buf, rctx->buf_size);
+ } else {
+ (void)ERR_set_mark();
+ n = BIO_gets(rctx->rbio, buf, rctx->buf_size);
+ if (n == -2) { /* unsupported method */
+ (void)ERR_pop_to_mark();
+ n = BIO_get_line(rctx->rbio, buf, rctx->buf_size);
+ } else {
+ (void)ERR_clear_last_mark();
+ }
+ }
+ if (n <= 0) {
+ if (BIO_should_retry(rctx->rbio))
+ return -1;
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_FAILED_READING_DATA);
+ return 0;
+ }
+
+ /* Write data to memory BIO */
+ if (BIO_write(rctx->mem, rctx->buf, n) != n)
+ return 0;
+ }
+
+ switch (rctx->state) {
+ case OHS_ADD_HEADERS:
+ /* Last operation was adding headers: need a final \r\n */
+ if (BIO_write(rctx->mem, "\r\n", 2) != 2) {
+ rctx->state = OHS_ERROR;
+ return 0;
+ }
+ rctx->state = OHS_WRITE_INIT;
+
+ /* fall thru */
+ case OHS_WRITE_INIT:
+ rctx->len_to_send = BIO_get_mem_data(rctx->mem, &rctx->pos);
+ rctx->state = OHS_WRITE_HDR;
+
+ /* fall thru */
+ case OHS_WRITE_HDR:
+ /* Copy some chunk of data from rctx->mem to rctx->wbio */
+ case OHS_WRITE_REQ:
+ /* Copy some chunk of data from rctx->req to rctx->wbio */
+
+ if (rctx->len_to_send > 0) {
+ i = BIO_write(rctx->wbio, rctx->pos, rctx->len_to_send);
+ if (i <= 0) {
+ if (BIO_should_retry(rctx->wbio))
+ return -1;
+ rctx->state = OHS_ERROR;
+ return 0;
+ }
+ rctx->pos += i;
+ rctx->len_to_send -= i;
+ goto next_io;
+ }
+ if (rctx->state == OHS_WRITE_HDR) {
+ (void)BIO_reset(rctx->mem);
+ rctx->state = OHS_WRITE_REQ;
+ }
+ if (rctx->req != NULL && !BIO_eof(rctx->req)) {
+ n = BIO_read(rctx->req, rctx->buf, rctx->buf_size);
+ if (n <= 0) {
+ if (BIO_should_retry(rctx->req))
+ return -1;
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_FAILED_READING_DATA);
+ return 0;
+ }
+ rctx->pos = rctx->buf;
+ rctx->len_to_send = n;
+ goto next_io;
+ }
+ rctx->state = OHS_FLUSH;
+
+ /* fall thru */
+ case OHS_FLUSH:
+
+ i = BIO_flush(rctx->wbio);
+
+ if (i > 0) {
+ rctx->state = OHS_FIRSTLINE;
+ goto next_io;
+ }
+
+ if (BIO_should_retry(rctx->wbio))
+ return -1;
+
+ rctx->state = OHS_ERROR;
+ return 0;
+
+ case OHS_ERROR:
+ return 0;
+
+ case OHS_FIRSTLINE:
+ case OHS_HEADERS:
+ case OHS_REDIRECT:
+
+ /* Attempt to read a line in */
+ next_line:
+ /*
+ * Due to strange memory BIO behavior with BIO_gets we have to check
+ * there's a complete line in there before calling BIO_gets or we'll
+ * just get a partial read.
+ */
+ n = BIO_get_mem_data(rctx->mem, &p);
+ if (n <= 0 || memchr(p, '\n', n) == 0) {
+ if (n >= rctx->buf_size) {
+ rctx->state = OHS_ERROR;
+ return 0;
+ }
+ goto next_io;
+ }
+ n = BIO_gets(rctx->mem, buf, rctx->buf_size);
+
+ if (n <= 0) {
+ if (BIO_should_retry(rctx->mem))
+ goto next_io;
+ rctx->state = OHS_ERROR;
+ return 0;
+ }
+
+ /* Don't allow excessive lines */
+ if (n == rctx->buf_size) {
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_RESPONSE_LINE_TOO_LONG);
+ rctx->state = OHS_ERROR;
+ return 0;
+ }
+
+ /* First line */
+ if (rctx->state == OHS_FIRSTLINE) {
+ switch (parse_http_line1(buf, &found_keep_alive)) {
+ case HTTP_STATUS_CODE_OK:
+ rctx->state = OHS_HEADERS;
+ goto next_line;
+ case HTTP_STATUS_CODE_MOVED_PERMANENTLY:
+ case HTTP_STATUS_CODE_FOUND: /* i.e., moved temporarily */
+ if (!rctx->method_POST) { /* method is GET */
+ rctx->state = OHS_REDIRECT;
+ goto next_line;
+ }
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_REDIRECTION_NOT_ENABLED);
+ /* redirection is not supported/recommended for POST */
+ /* fall through */
+ default:
+ rctx->state = OHS_ERROR;
+ goto next_line;
+ }
+ }
+ key = buf;
+ value = strchr(key, ':');
+ if (value != NULL) {
+ *(value++) = '\0';
+ while (ossl_isspace(*value))
+ value++;
+ line_end = strchr(value, '\r');
+ if (line_end == NULL)
+ line_end = strchr(value, '\n');
+ if (line_end != NULL)
+ *line_end = '\0';
+ }
+ if (value != NULL && line_end != NULL) {
+ if (rctx->state == OHS_REDIRECT
+ && OPENSSL_strcasecmp(key, "Location") == 0) {
+ rctx->redirection_url = value;
+ return 0;
+ }
+ if (rctx->state == OHS_HEADERS && rctx->expected_ct != NULL
+ && OPENSSL_strcasecmp(key, "Content-Type") == 0) {
+ if (OPENSSL_strcasecmp(rctx->expected_ct, value) != 0) {
+ ERR_raise_data(ERR_LIB_HTTP, HTTP_R_UNEXPECTED_CONTENT_TYPE,
+ "expected=%s, actual=%s",
+ rctx->expected_ct, value);
+ return 0;
+ }
+ found_expected_ct = 1;
+ }
+
+ /* https://tools.ietf.org/html/rfc7230#section-6.3 Persistence */
+ if (OPENSSL_strcasecmp(key, "Connection") == 0) {
+ if (OPENSSL_strcasecmp(value, "keep-alive") == 0)
+ found_keep_alive = 1;
+ else if (OPENSSL_strcasecmp(value, "close") == 0)
+ found_keep_alive = 0;
+ } else if (OPENSSL_strcasecmp(key, "Content-Length") == 0) {
+ resp_len = (size_t)strtoul(value, &line_end, 10);
+ if (line_end == value || *line_end != '\0') {
+ ERR_raise_data(ERR_LIB_HTTP,
+ HTTP_R_ERROR_PARSING_CONTENT_LENGTH,
+ "input=%s", value);
+ return 0;
+ }
+ if (!check_set_resp_len(rctx, resp_len))
+ return 0;
+ }
+ }
+
+ /* Look for blank line indicating end of headers */
+ for (p = rctx->buf; *p != '\0'; p++) {
+ if (*p != '\r' && *p != '\n')
+ break;
+ }
+ if (*p != '\0') /* not end of headers */
+ goto next_line;
+
+ if (rctx->keep_alive != 0 /* do not let server initiate keep_alive */
+ && !found_keep_alive /* otherwise there is no change */) {
+ if (rctx->keep_alive == 2) {
+ rctx->keep_alive = 0;
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_SERVER_CANCELED_CONNECTION);
+ return 0;
+ }
+ rctx->keep_alive = 0;
+ }
+
+ if (rctx->state == OHS_ERROR)
+ return 0;
+
+ if (rctx->expected_ct != NULL && !found_expected_ct) {
+ ERR_raise_data(ERR_LIB_HTTP, HTTP_R_MISSING_CONTENT_TYPE,
+ "expected=%s", rctx->expected_ct);
+ return 0;
+ }
+ if (rctx->state == OHS_REDIRECT) {
+ /* http status code indicated redirect but there was no Location */
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_MISSING_REDIRECT_LOCATION);
+ return 0;
+ }
+
+ if (!rctx->expect_asn1) {
+ rctx->state = OHS_STREAM;
+ return 1;
+ }
+
+ rctx->state = OHS_ASN1_HEADER;
+
+ /* Fall thru */
+ case OHS_ASN1_HEADER:
+ /*
+ * Now reading ASN1 header: can read at least 2 bytes which is enough
+ * for ASN1 SEQUENCE header and either length field or at least the
+ * length of the length field.
+ */
+ n = BIO_get_mem_data(rctx->mem, &p);
+ if (n < 2)
+ goto next_io;
+
+ /* Check it is an ASN1 SEQUENCE */
+ if (*p++ != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)) {
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_MISSING_ASN1_ENCODING);
+ return 0;
+ }
+
+ /* Check out length field */
+ if ((*p & 0x80) != 0) {
+ /*
+ * If MSB set on initial length octet we can now always read 6
+ * octets: make sure we have them.
+ */
+ if (n < 6)
+ goto next_io;
+ n = *p & 0x7F;
+ /* Not NDEF or excessive length */
+ if (n == 0 || (n > 4)) {
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_ERROR_PARSING_ASN1_LENGTH);
+ return 0;
+ }
+ p++;
+ resp_len = 0;
+ for (i = 0; i < n; i++) {
+ resp_len <<= 8;
+ resp_len |= *p++;
+ }
+ resp_len += n + 2;
+ } else {
+ resp_len = *p + 2;
+ }
+ if (!check_set_resp_len(rctx, resp_len))
+ return 0;
+
+ rctx->state = OHS_ASN1_CONTENT;
+
+ /* Fall thru */
+ case OHS_ASN1_CONTENT:
+ default:
+ n = BIO_get_mem_data(rctx->mem, NULL);
+ if (n < 0 || (size_t)n < rctx->resp_len)
+ goto next_io;
+
+ rctx->state = OHS_ASN1_DONE;
+ return 1;
+ }
+}
+
+int OSSL_HTTP_REQ_CTX_nbio_d2i(OSSL_HTTP_REQ_CTX *rctx,
+ ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+ const unsigned char *p;
+ int rv;
+
+ *pval = NULL;
+ if ((rv = OSSL_HTTP_REQ_CTX_nbio(rctx)) != 1)
+ return rv;
+ *pval = ASN1_item_d2i(NULL, &p, BIO_get_mem_data(rctx->mem, &p), it);
+ return *pval != NULL;
+
+}
+
+#ifndef OPENSSL_NO_SOCK
+
+/* set up a new connection BIO, to HTTP server or to HTTP(S) proxy if given */
+static BIO *http_new_bio(const char *server /* optionally includes ":port" */,
+ const char *server_port /* explicit server port */,
+ int use_ssl,
+ const char *proxy /* optionally includes ":port" */,
+ const char *proxy_port /* explicit proxy port */)
+{
+ const char *host = server;
+ const char *port = server_port;
+ BIO *cbio;
+
+ if (!ossl_assert(server != NULL))
+ return NULL;
+
+ if (proxy != NULL) {
+ host = proxy;
+ port = proxy_port;
+ }
+
+ if (port == NULL && strchr(host, ':') == NULL)
+ port = use_ssl ? OSSL_HTTPS_PORT : OSSL_HTTP_PORT;
+
+ cbio = BIO_new_connect(host /* optionally includes ":port" */);
+ if (cbio == NULL)
+ goto end;
+ if (port != NULL)
+ (void)BIO_set_conn_port(cbio, port);
+
+ end:
+ return cbio;
+}
+#endif /* OPENSSL_NO_SOCK */
+
+/* Exchange request and response via HTTP on (non-)blocking BIO */
+BIO *OSSL_HTTP_REQ_CTX_exchange(OSSL_HTTP_REQ_CTX *rctx)
+{
+ int rv;
+
+ if (rctx == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+
+ for (;;) {
+ rv = OSSL_HTTP_REQ_CTX_nbio(rctx);
+ if (rv != -1)
+ break;
+ /* BIO_should_retry was true */
+ /* will not actually wait if rctx->max_time == 0 */
+ if (BIO_wait(rctx->rbio, rctx->max_time, 100 /* milliseconds */) <= 0)
+ return NULL;
+ }
+
+ if (rv == 0) {
+ if (rctx->redirection_url == NULL) { /* an error occurred */
+ if (rctx->len_to_send > 0)
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_ERROR_SENDING);
+ else
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_ERROR_RECEIVING);
+ }
+ return NULL;
+ }
+ return rctx->state == OHS_STREAM ? rctx->rbio : rctx->mem;
+}
+
+int OSSL_HTTP_is_alive(const OSSL_HTTP_REQ_CTX *rctx)
+{
+ return rctx != NULL && rctx->keep_alive != 0;
+}
+
+/* High-level HTTP API implementation */
+
+/* Initiate an HTTP session using bio, else use given server, proxy, etc. */
+OSSL_HTTP_REQ_CTX *OSSL_HTTP_open(const char *server, const char *port,
+ const char *proxy, const char *no_proxy,
+ int use_ssl, BIO *bio, BIO *rbio,
+ OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
+ int buf_size, int overall_timeout)
+{
+ BIO *cbio; /* == bio if supplied, used as connection BIO if rbio is NULL */
+ OSSL_HTTP_REQ_CTX *rctx = NULL;
+
+ if (use_ssl && bio_update_fn == NULL) {
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_TLS_NOT_ENABLED);
+ return NULL;
+ }
+ if (rbio != NULL && (bio == NULL || bio_update_fn != NULL)) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return NULL;
+ }
+
+ if (bio != NULL) {
+ cbio = bio;
+ if (proxy != NULL || no_proxy != NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return NULL;
+ }
+ } else {
+#ifndef OPENSSL_NO_SOCK
+ char *proxy_host = NULL, *proxy_port = NULL;
+
+ if (server == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ if (port != NULL && *port == '\0')
+ port = NULL;
+ if (port == NULL && strchr(server, ':') == NULL)
+ port = use_ssl ? OSSL_HTTPS_PORT : OSSL_HTTP_PORT;
+ proxy = OSSL_HTTP_adapt_proxy(proxy, no_proxy, server, use_ssl);
+ if (proxy != NULL
+ && !OSSL_HTTP_parse_url(proxy, NULL /* use_ssl */, NULL /* user */,
+ &proxy_host, &proxy_port, NULL /* num */,
+ NULL /* path */, NULL, NULL))
+ return NULL;
+ cbio = http_new_bio(server, port, use_ssl, proxy_host, proxy_port);
+ OPENSSL_free(proxy_host);
+ OPENSSL_free(proxy_port);
+ if (cbio == NULL)
+ return NULL;
+#else
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_SOCK_NOT_SUPPORTED);
+ return NULL;
+#endif
+ }
+
+ (void)ERR_set_mark(); /* prepare removing any spurious libssl errors */
+ if (rbio == NULL && BIO_do_connect_retry(cbio, overall_timeout, -1) <= 0) {
+ if (bio == NULL) /* cbio was not provided by caller */
+ BIO_free_all(cbio);
+ goto end;
+ }
+ /* now overall_timeout is guaranteed to be >= 0 */
+
+ /* adapt in order to fix callback design flaw, see #17088 */
+ /* callback can be used to wrap or prepend TLS session */
+ if (bio_update_fn != NULL) {
+ BIO *orig_bio = cbio;
+
+ cbio = (*bio_update_fn)(cbio, arg, 1 /* connect */, use_ssl != 0);
+ if (cbio == NULL) {
+ if (bio == NULL) /* cbio was not provided by caller */
+ BIO_free_all(orig_bio);
+ goto end;
+ }
+ }
+
+ rctx = http_req_ctx_new(bio == NULL, cbio, rbio != NULL ? rbio : cbio,
+ bio_update_fn, arg, use_ssl, proxy, server, port,
+ buf_size, overall_timeout);
+
+ end:
+ if (rctx != NULL)
+ /* remove any spurious error queue entries by ssl_add_cert_chain() */
+ (void)ERR_pop_to_mark();
+ else
+ (void)ERR_clear_last_mark();
+
+ return rctx;
+}
+
+int OSSL_HTTP_set1_request(OSSL_HTTP_REQ_CTX *rctx, const char *path,
+ const STACK_OF(CONF_VALUE) *headers,
+ const char *content_type, BIO *req,
+ const char *expected_content_type, int expect_asn1,
+ size_t max_resp_len, int timeout, int keep_alive)
+{
+ int use_http_proxy;
+
+ if (rctx == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ use_http_proxy = rctx->proxy != NULL && !rctx->use_ssl;
+ if (use_http_proxy && rctx->server == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ rctx->max_resp_len = max_resp_len; /* allows for 0: indefinite */
+
+ return OSSL_HTTP_REQ_CTX_set_request_line(rctx, req != NULL,
+ use_http_proxy ? rctx->server
+ : NULL, rctx->port, path)
+ && add1_headers(rctx, headers, rctx->server)
+ && OSSL_HTTP_REQ_CTX_set_expected(rctx, expected_content_type,
+ expect_asn1, timeout, keep_alive)
+ && set1_content(rctx, content_type, req);
+}
+
+/*-
+ * Exchange single HTTP request and response according to rctx.
+ * If rctx->method_POST then use POST, else use GET and ignore content_type.
+ * The redirection_url output (freed by caller) parameter is used only for GET.
+ */
+BIO *OSSL_HTTP_exchange(OSSL_HTTP_REQ_CTX *rctx, char **redirection_url)
+{
+ BIO *resp;
+
+ if (rctx == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+
+ if (redirection_url != NULL)
+ *redirection_url = NULL; /* do this beforehand to prevent dbl free */
+
+ resp = OSSL_HTTP_REQ_CTX_exchange(rctx);
+ if (resp == NULL) {
+ if (rctx->redirection_url != NULL) {
+ if (redirection_url == NULL)
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_REDIRECTION_NOT_ENABLED);
+ else
+ /* may be NULL if out of memory: */
+ *redirection_url = OPENSSL_strdup(rctx->redirection_url);
+ } else {
+ char buf[200];
+ unsigned long err = ERR_peek_error();
+ int lib = ERR_GET_LIB(err);
+ int reason = ERR_GET_REASON(err);
+
+ if (lib == ERR_LIB_SSL || lib == ERR_LIB_HTTP
+ || (lib == ERR_LIB_BIO && reason == BIO_R_CONNECT_TIMEOUT)
+ || (lib == ERR_LIB_BIO && reason == BIO_R_CONNECT_ERROR)
+#ifndef OPENSSL_NO_CMP
+ || (lib == ERR_LIB_CMP
+ && reason == CMP_R_POTENTIALLY_INVALID_CERTIFICATE)
+#endif
+ ) {
+ if (rctx->server != NULL) {
+ BIO_snprintf(buf, sizeof(buf), "server=http%s://%s%s%s",
+ rctx->use_ssl ? "s" : "", rctx->server,
+ rctx->port != NULL ? ":" : "",
+ rctx->port != NULL ? rctx->port : "");
+ ERR_add_error_data(1, buf);
+ }
+ if (rctx->proxy != NULL)
+ ERR_add_error_data(2, " proxy=", rctx->proxy);
+ if (err == 0) {
+ BIO_snprintf(buf, sizeof(buf), " peer has disconnected%s",
+ rctx->use_ssl ? " violating the protocol" :
+ ", likely because it requires the use of TLS");
+ ERR_add_error_data(1, buf);
+ }
+ }
+ }
+ }
+
+ if (resp != NULL && !BIO_up_ref(resp))
+ resp = NULL;
+ return resp;
+}
+
+static int redirection_ok(int n_redir, const char *old_url, const char *new_url)
+{
+ if (n_redir >= HTTP_VERSION_MAX_REDIRECTIONS) {
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_TOO_MANY_REDIRECTIONS);
+ return 0;
+ }
+ if (*new_url == '/') /* redirection to same server => same protocol */
+ return 1;
+ if (HAS_PREFIX(old_url, OSSL_HTTPS_NAME":") &&
+ !HAS_PREFIX(new_url, OSSL_HTTPS_NAME":")) {
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP);
+ return 0;
+ }
+ return 1;
+}
+
+/* Get data via HTTP from server at given URL, potentially with redirection */
+BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy,
+ BIO *bio, BIO *rbio,
+ OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
+ int buf_size, const STACK_OF(CONF_VALUE) *headers,
+ const char *expected_ct, int expect_asn1,
+ size_t max_resp_len, int timeout)
+{
+ char *current_url, *redirection_url = NULL;
+ int n_redirs = 0;
+ char *host;
+ char *port;
+ char *path;
+ int use_ssl;
+ OSSL_HTTP_REQ_CTX *rctx;
+ BIO *resp = NULL;
+ time_t max_time = timeout > 0 ? time(NULL) + timeout : 0;
+
+ if (url == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ if ((current_url = OPENSSL_strdup(url)) == NULL)
+ return NULL;
+
+ for (;;) {
+ if (!OSSL_HTTP_parse_url(current_url, &use_ssl, NULL /* user */, &host,
+ &port, NULL /* port_num */, &path, NULL, NULL))
+ break;
+
+ rctx = OSSL_HTTP_open(host, port, proxy, no_proxy,
+ use_ssl, bio, rbio, bio_update_fn, arg,
+ buf_size, timeout);
+ new_rpath:
+ if (rctx != NULL) {
+ if (!OSSL_HTTP_set1_request(rctx, path, headers,
+ NULL /* content_type */,
+ NULL /* req */,
+ expected_ct, expect_asn1, max_resp_len,
+ -1 /* use same max time (timeout) */,
+ 0 /* no keep_alive */))
+ OSSL_HTTP_REQ_CTX_free(rctx);
+ else
+ resp = OSSL_HTTP_exchange(rctx, &redirection_url);
+ }
+ OPENSSL_free(path);
+ if (resp == NULL && redirection_url != NULL) {
+ if (redirection_ok(++n_redirs, current_url, redirection_url)
+ && may_still_retry(max_time, &timeout)) {
+ (void)BIO_reset(bio);
+ OPENSSL_free(current_url);
+ current_url = redirection_url;
+ if (*redirection_url == '/') { /* redirection to same server */
+ path = OPENSSL_strdup(redirection_url);
+ if (path == NULL) {
+ OPENSSL_free(host);
+ OPENSSL_free(port);
+ (void)OSSL_HTTP_close(rctx, 1);
+ BIO_free(resp);
+ OPENSSL_free(current_url);
+ return NULL;
+ }
+ goto new_rpath;
+ }
+ OPENSSL_free(host);
+ OPENSSL_free(port);
+ (void)OSSL_HTTP_close(rctx, 1);
+ continue;
+ }
+ /* if redirection not allowed, ignore it */
+ OPENSSL_free(redirection_url);
+ }
+ OPENSSL_free(host);
+ OPENSSL_free(port);
+ if (!OSSL_HTTP_close(rctx, resp != NULL)) {
+ BIO_free(resp);
+ resp = NULL;
+ }
+ break;
+ }
+ OPENSSL_free(current_url);
+ return resp;
+}
+
+/* Exchange request and response over a connection managed via |prctx| */
+BIO *OSSL_HTTP_transfer(OSSL_HTTP_REQ_CTX **prctx,
+ const char *server, const char *port,
+ const char *path, int use_ssl,
+ const char *proxy, const char *no_proxy,
+ BIO *bio, BIO *rbio,
+ OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
+ int buf_size, const STACK_OF(CONF_VALUE) *headers,
+ const char *content_type, BIO *req,
+ const char *expected_ct, int expect_asn1,
+ size_t max_resp_len, int timeout, int keep_alive)
+{
+ OSSL_HTTP_REQ_CTX *rctx = prctx == NULL ? NULL : *prctx;
+ BIO *resp = NULL;
+
+ if (rctx == NULL) {
+ rctx = OSSL_HTTP_open(server, port, proxy, no_proxy,
+ use_ssl, bio, rbio, bio_update_fn, arg,
+ buf_size, timeout);
+ timeout = -1; /* Already set during opening the connection */
+ }
+ if (rctx != NULL) {
+ if (OSSL_HTTP_set1_request(rctx, path, headers, content_type, req,
+ expected_ct, expect_asn1,
+ max_resp_len, timeout, keep_alive))
+ resp = OSSL_HTTP_exchange(rctx, NULL);
+ if (resp == NULL || !OSSL_HTTP_is_alive(rctx)) {
+ if (!OSSL_HTTP_close(rctx, resp != NULL)) {
+ BIO_free(resp);
+ resp = NULL;
+ }
+ rctx = NULL;
+ }
+ }
+ if (prctx != NULL)
+ *prctx = rctx;
+ return resp;
+}
+
+int OSSL_HTTP_close(OSSL_HTTP_REQ_CTX *rctx, int ok)
+{
+ BIO *wbio;
+ int ret = 1;
+
+ /* callback can be used to finish TLS session and free its BIO */
+ if (rctx != NULL && rctx->upd_fn != NULL) {
+ wbio = (*rctx->upd_fn)(rctx->wbio, rctx->upd_arg,
+ 0 /* disconnect */, ok);
+ ret = wbio != NULL;
+ if (ret)
+ rctx->wbio = wbio;
+ }
+ OSSL_HTTP_REQ_CTX_free(rctx);
+ return ret;
+}
+
+/* BASE64 encoder used for encoding basic proxy authentication credentials */
+static char *base64encode(const void *buf, size_t len)
+{
+ int i;
+ size_t outl;
+ char *out;
+
+ /* Calculate size of encoded data */
+ outl = (len / 3);
+ if (len % 3 > 0)
+ outl++;
+ outl <<= 2;
+ out = OPENSSL_malloc(outl + 1);
+ if (out == NULL)
+ return 0;
+
+ i = EVP_EncodeBlock((unsigned char *)out, buf, len);
+ if (!ossl_assert(0 <= i && (size_t)i <= outl)) {
+ OPENSSL_free(out);
+ return NULL;
+ }
+ return out;
+}
+
+/*
+ * Promote the given connection BIO using the CONNECT method for a TLS proxy.
+ * This is typically called by an app, so bio_err and prog are used unless NULL
+ * to print additional diagnostic information in a user-oriented way.
+ */
+int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port,
+ const char *proxyuser, const char *proxypass,
+ int timeout, BIO *bio_err, const char *prog)
+{
+#undef BUF_SIZE
+#define BUF_SIZE (8 * 1024)
+ char *mbuf = OPENSSL_malloc(BUF_SIZE);
+ char *mbufp;
+ int read_len = 0;
+ int ret = 0;
+ BIO *fbio = BIO_new(BIO_f_buffer());
+ int rv;
+ time_t max_time = timeout > 0 ? time(NULL) + timeout : 0;
+
+ if (bio == NULL || server == NULL
+ || (bio_err != NULL && prog == NULL)) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ goto end;
+ }
+ if (port == NULL || *port == '\0')
+ port = OSSL_HTTPS_PORT;
+
+ if (mbuf == NULL || fbio == NULL) {
+ BIO_printf(bio_err /* may be NULL */, "%s: out of memory", prog);
+ goto end;
+ }
+ BIO_push(fbio, bio);
+
+ BIO_printf(fbio, "CONNECT %s:%s "HTTP_1_0"\r\n", server, port);
+
+ /*
+ * Workaround for broken proxies which would otherwise close
+ * the connection when entering tunnel mode (e.g., Squid 2.6)
+ */
+ BIO_printf(fbio, "Proxy-Connection: Keep-Alive\r\n");
+
+ /* Support for basic (base64) proxy authentication */
+ if (proxyuser != NULL) {
+ size_t len = strlen(proxyuser) + 1;
+ char *proxyauth, *proxyauthenc = NULL;
+
+ if (proxypass != NULL)
+ len += strlen(proxypass);
+ proxyauth = OPENSSL_malloc(len + 1);
+ if (proxyauth == NULL)
+ goto end;
+ if (BIO_snprintf(proxyauth, len + 1, "%s:%s", proxyuser,
+ proxypass != NULL ? proxypass : "") != (int)len)
+ goto proxy_end;
+ proxyauthenc = base64encode(proxyauth, len);
+ if (proxyauthenc != NULL) {
+ BIO_printf(fbio, "Proxy-Authorization: Basic %s\r\n", proxyauthenc);
+ OPENSSL_clear_free(proxyauthenc, strlen(proxyauthenc));
+ }
+ proxy_end:
+ OPENSSL_clear_free(proxyauth, len);
+ if (proxyauthenc == NULL)
+ goto end;
+ }
+
+ /* Terminate the HTTP CONNECT request */
+ BIO_printf(fbio, "\r\n");
+
+ for (;;) {
+ if (BIO_flush(fbio) != 0)
+ break;
+ /* potentially needs to be retried if BIO is non-blocking */
+ if (!BIO_should_retry(fbio))
+ break;
+ }
+
+ for (;;) {
+ /* will not actually wait if timeout == 0 */
+ rv = BIO_wait(fbio, max_time, 100 /* milliseconds */);
+ if (rv <= 0) {
+ BIO_printf(bio_err, "%s: HTTP CONNECT %s\n", prog,
+ rv == 0 ? "timed out" : "failed waiting for data");
+ goto end;
+ }
+
+ /*-
+ * The first line is the HTTP response.
+ * According to RFC 7230, it is formatted exactly like this:
+ * HTTP/d.d ddd reason text\r\n
+ */
+ read_len = BIO_gets(fbio, mbuf, BUF_SIZE);
+ /* the BIO may not block, so we must wait for the 1st line to come in */
+ if (read_len < (int)HTTP_LINE1_MINLEN)
+ continue;
+
+ /* Check for HTTP/1.x */
+ if (!HAS_PREFIX(mbuf, HTTP_PREFIX) != 0) {
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_HEADER_PARSE_ERROR);
+ BIO_printf(bio_err, "%s: HTTP CONNECT failed, non-HTTP response\n",
+ prog);
+ /* Wrong protocol, not even HTTP, so stop reading headers */
+ goto end;
+ }
+ mbufp = mbuf + strlen(HTTP_PREFIX);
+ if (!HAS_PREFIX(mbufp, HTTP_VERSION_PATT) != 0) {
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_RECEIVED_WRONG_HTTP_VERSION);
+ BIO_printf(bio_err,
+ "%s: HTTP CONNECT failed, bad HTTP version %.*s\n",
+ prog, (int)HTTP_VERSION_STR_LEN, mbufp);
+ goto end;
+ }
+ mbufp += HTTP_VERSION_STR_LEN;
+
+ /* RFC 7231 4.3.6: any 2xx status code is valid */
+ if (!HAS_PREFIX(mbufp, " 2")) {
+ /* chop any trailing whitespace */
+ while (read_len > 0 && ossl_isspace(mbuf[read_len - 1]))
+ read_len--;
+ mbuf[read_len] = '\0';
+ ERR_raise_data(ERR_LIB_HTTP, HTTP_R_CONNECT_FAILURE,
+ "reason=%s", mbufp);
+ BIO_printf(bio_err, "%s: HTTP CONNECT failed, reason=%s\n",
+ prog, mbufp);
+ goto end;
+ }
+ ret = 1;
+ break;
+ }
+
+ /* Read past all following headers */
+ do {
+ /*
+ * This does not necessarily catch the case when the full
+ * HTTP response came in in more than a single TCP message.
+ */
+ read_len = BIO_gets(fbio, mbuf, BUF_SIZE);
+ } while (read_len > 2);
+
+ end:
+ if (fbio != NULL) {
+ (void)BIO_flush(fbio);
+ BIO_pop(fbio);
+ BIO_free(fbio);
+ }
+ OPENSSL_free(mbuf);
+ return ret;
+#undef BUF_SIZE
+}
diff --git a/crypto/http/http_err.c b/crypto/http/http_err.c
new file mode 100644
index 000000000000..332ad926d367
--- /dev/null
+++ b/crypto/http/http_err.c
@@ -0,0 +1,82 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/httperr.h>
+#include "crypto/httperr.h"
+
+#ifndef OPENSSL_NO_ERR
+
+static const ERR_STRING_DATA HTTP_str_reasons[] = {
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ASN1_LEN_EXCEEDS_MAX_RESP_LEN),
+ "asn1 len exceeds max resp len"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_CONNECT_FAILURE), "connect failure"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ERROR_PARSING_ASN1_LENGTH),
+ "error parsing asn1 length"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ERROR_PARSING_CONTENT_LENGTH),
+ "error parsing content length"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ERROR_PARSING_URL), "error parsing url"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ERROR_RECEIVING), "error receiving"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ERROR_SENDING), "error sending"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_FAILED_READING_DATA),
+ "failed reading data"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_HEADER_PARSE_ERROR),
+ "header parse error"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_INCONSISTENT_CONTENT_LENGTH),
+ "inconsistent content length"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_INVALID_PORT_NUMBER),
+ "invalid port number"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_INVALID_URL_PATH), "invalid url path"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_INVALID_URL_SCHEME),
+ "invalid url scheme"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_MAX_RESP_LEN_EXCEEDED),
+ "max resp len exceeded"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_MISSING_ASN1_ENCODING),
+ "missing asn1 encoding"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_MISSING_CONTENT_TYPE),
+ "missing content type"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_MISSING_REDIRECT_LOCATION),
+ "missing redirect location"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RECEIVED_ERROR), "received error"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RECEIVED_WRONG_HTTP_VERSION),
+ "received wrong http version"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP),
+ "redirection from https to http"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_REDIRECTION_NOT_ENABLED),
+ "redirection not enabled"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RESPONSE_LINE_TOO_LONG),
+ "response line too long"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RESPONSE_PARSE_ERROR),
+ "response parse error"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RETRY_TIMEOUT), "retry timeout"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SERVER_CANCELED_CONNECTION),
+ "server canceled connection"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SOCK_NOT_SUPPORTED),
+ "sock not supported"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_STATUS_CODE_UNSUPPORTED),
+ "status code unsupported"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_TLS_NOT_ENABLED), "tls not enabled"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_TOO_MANY_REDIRECTIONS),
+ "too many redirections"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_UNEXPECTED_CONTENT_TYPE),
+ "unexpected content type"},
+ {0, NULL}
+};
+
+#endif
+
+int ossl_err_load_HTTP_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(HTTP_str_reasons[0].error) == NULL)
+ ERR_load_strings_const(HTTP_str_reasons);
+#endif
+ return 1;
+}
diff --git a/crypto/http/http_lib.c b/crypto/http/http_lib.c
new file mode 100644
index 000000000000..bd9c096b989c
--- /dev/null
+++ b/crypto/http/http_lib.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h> /* for sscanf() */
+#include <string.h>
+#include <openssl/http.h>
+#include <openssl/httperr.h>
+#include <openssl/bio.h> /* for BIO_snprintf() */
+#include <openssl/err.h>
+#include "internal/cryptlib.h" /* for ossl_assert() */
+
+static void init_pstring(char **pstr)
+{
+ if (pstr != NULL) {
+ *pstr = NULL;
+ }
+}
+
+static int copy_substring(char **dest, const char *start, const char *end)
+{
+ return dest == NULL
+ || (*dest = OPENSSL_strndup(start, end - start)) != NULL;
+}
+
+static void free_pstring(char **pstr)
+{
+ if (pstr != NULL) {
+ OPENSSL_free(*pstr);
+ *pstr = NULL;
+ }
+}
+
+int OSSL_parse_url(const char *url, char **pscheme, char **puser, char **phost,
+ char **pport, int *pport_num,
+ char **ppath, char **pquery, char **pfrag)
+{
+ const char *p, *tmp;
+ const char *scheme, *scheme_end;
+ const char *user, *user_end;
+ const char *host, *host_end;
+ const char *port, *port_end;
+ unsigned int portnum;
+ const char *path, *path_end;
+ const char *query, *query_end;
+ const char *frag, *frag_end;
+
+ init_pstring(pscheme);
+ init_pstring(puser);
+ init_pstring(phost);
+ init_pstring(pport);
+ init_pstring(ppath);
+ init_pstring(pfrag);
+ init_pstring(pquery);
+
+ if (url == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ /* check for optional prefix "<scheme>://" */
+ scheme = scheme_end = url;
+ p = strstr(url, "://");
+ if (p == NULL) {
+ p = url;
+ } else {
+ scheme_end = p;
+ if (scheme_end == scheme)
+ goto parse_err;
+ p += strlen("://");
+ }
+
+ /* parse optional "userinfo@" */
+ user = user_end = host = p;
+ host = strchr(p, '@');
+ if (host != NULL)
+ user_end = host++;
+ else
+ host = p;
+
+ /* parse host name/address as far as needed here */
+ if (host[0] == '[') {
+ /* ipv6 literal, which may include ':' */
+ host_end = strchr(host + 1, ']');
+ if (host_end == NULL)
+ goto parse_err;
+ p = ++host_end;
+ } else {
+ /* look for start of optional port, path, query, or fragment */
+ host_end = strchr(host, ':');
+ if (host_end == NULL)
+ host_end = strchr(host, '/');
+ if (host_end == NULL)
+ host_end = strchr(host, '?');
+ if (host_end == NULL)
+ host_end = strchr(host, '#');
+ if (host_end == NULL) /* the remaining string is just the hostname */
+ host_end = host + strlen(host);
+ p = host_end;
+ }
+
+ /* parse optional port specification starting with ':' */
+ port = "0"; /* default */
+ if (*p == ':')
+ port = ++p;
+ /* remaining port spec handling is also done for the default values */
+ /* make sure a decimal port number is given */
+ if (!sscanf(port, "%u", &portnum) || portnum > 65535) {
+ ERR_raise_data(ERR_LIB_HTTP, HTTP_R_INVALID_PORT_NUMBER, "%s", port);
+ goto err;
+ }
+ for (port_end = port; '0' <= *port_end && *port_end <= '9'; port_end++)
+ ;
+ if (port == p) /* port was given explicitly */
+ p += port_end - port;
+
+ /* check for optional path starting with '/' or '?'. Else must start '#' */
+ path = p;
+ if (*path != '\0' && *path != '/' && *path != '?' && *path != '#') {
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_INVALID_URL_PATH);
+ goto parse_err;
+ }
+ path_end = query = query_end = frag = frag_end = path + strlen(path);
+
+ /* parse optional "?query" */
+ tmp = strchr(p, '?');
+ if (tmp != NULL) {
+ p = tmp;
+ if (pquery != NULL) {
+ path_end = p;
+ query = p + 1;
+ }
+ }
+
+ /* parse optional "#fragment" */
+ tmp = strchr(p, '#');
+ if (tmp != NULL) {
+ if (query == path_end) /* we did not record a query component */
+ path_end = tmp;
+ query_end = tmp;
+ frag = tmp + 1;
+ }
+
+ if (!copy_substring(pscheme, scheme, scheme_end)
+ || !copy_substring(phost, host, host_end)
+ || !copy_substring(pport, port, port_end)
+ || !copy_substring(puser, user, user_end)
+ || !copy_substring(pquery, query, query_end)
+ || !copy_substring(pfrag, frag, frag_end))
+ goto err;
+ if (pport_num != NULL)
+ *pport_num = (int)portnum;
+ if (*path == '/') {
+ if (!copy_substring(ppath, path, path_end))
+ goto err;
+ } else if (ppath != NULL) { /* must prepend '/' */
+ size_t buflen = 1 + path_end - path + 1;
+
+ if ((*ppath = OPENSSL_malloc(buflen)) == NULL)
+ goto err;
+ BIO_snprintf(*ppath, buflen, "/%s", path);
+ }
+ return 1;
+
+ parse_err:
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_ERROR_PARSING_URL);
+
+ err:
+ free_pstring(pscheme);
+ free_pstring(puser);
+ free_pstring(phost);
+ free_pstring(pport);
+ free_pstring(ppath);
+ free_pstring(pquery);
+ free_pstring(pfrag);
+ return 0;
+}
+
+int OSSL_HTTP_parse_url(const char *url, int *pssl, char **puser, char **phost,
+ char **pport, int *pport_num,
+ char **ppath, char **pquery, char **pfrag)
+{
+ char *scheme, *port;
+ int ssl = 0, portnum;
+
+ init_pstring(pport);
+ if (pssl != NULL)
+ *pssl = 0;
+ if (!OSSL_parse_url(url, &scheme, puser, phost, &port, pport_num,
+ ppath, pquery, pfrag))
+ return 0;
+
+ /* check for optional HTTP scheme "http[s]" */
+ if (strcmp(scheme, OSSL_HTTPS_NAME) == 0) {
+ ssl = 1;
+ if (pssl != NULL)
+ *pssl = ssl;
+ } else if (*scheme != '\0' && strcmp(scheme, OSSL_HTTP_NAME) != 0) {
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_INVALID_URL_SCHEME);
+ OPENSSL_free(scheme);
+ OPENSSL_free(port);
+ goto err;
+ }
+ OPENSSL_free(scheme);
+
+ if (strcmp(port, "0") == 0) {
+ /* set default port */
+ OPENSSL_free(port);
+ port = ssl ? OSSL_HTTPS_PORT : OSSL_HTTP_PORT;
+ if (!ossl_assert(sscanf(port, "%d", &portnum) == 1))
+ goto err;
+ if (pport_num != NULL)
+ *pport_num = portnum;
+ if (pport != NULL) {
+ *pport = OPENSSL_strdup(port);
+ if (*pport == NULL)
+ goto err;
+ }
+ } else {
+ if (pport != NULL)
+ *pport = port;
+ else
+ OPENSSL_free(port);
+ }
+ return 1;
+
+ err:
+ free_pstring(puser);
+ free_pstring(phost);
+ free_pstring(ppath);
+ free_pstring(pquery);
+ free_pstring(pfrag);
+ return 0;
+}
+
+/* Respect no_proxy, taking default value from environment variable(s) */
+static int use_proxy(const char *no_proxy, const char *server)
+{
+ size_t sl;
+ const char *found = NULL;
+
+ if (!ossl_assert(server != NULL))
+ return 0;
+ sl = strlen(server);
+
+ /*
+ * using environment variable names, both lowercase and uppercase variants,
+ * compatible with other HTTP client implementations like wget, curl and git
+ */
+ if (no_proxy == NULL)
+ no_proxy = getenv("no_proxy");
+ if (no_proxy == NULL)
+ no_proxy = getenv(OPENSSL_NO_PROXY);
+
+ if (no_proxy != NULL)
+ found = strstr(no_proxy, server);
+ while (found != NULL
+ && ((found != no_proxy && found[-1] != ' ' && found[-1] != ',')
+ || (found[sl] != '\0' && found[sl] != ' ' && found[sl] != ',')))
+ found = strstr(found + 1, server);
+ return found == NULL;
+}
+
+/* Take default value from environment variable(s), respect no_proxy */
+const char *OSSL_HTTP_adapt_proxy(const char *proxy, const char *no_proxy,
+ const char *server, int use_ssl)
+{
+ /*
+ * using environment variable names, both lowercase and uppercase variants,
+ * compatible with other HTTP client implementations like wget, curl and git
+ */
+ if (proxy == NULL)
+ proxy = getenv(use_ssl ? "https_proxy" : "http_proxy");
+ if (proxy == NULL)
+ proxy = getenv(use_ssl ? OPENSSL_HTTP_PROXY :
+ OPENSSL_HTTPS_PROXY);
+
+ if (proxy == NULL || *proxy == '\0' || !use_proxy(no_proxy, server))
+ return NULL;
+ return proxy;
+}
diff --git a/crypto/ia64cpuid.S b/crypto/ia64cpuid.S
index 92c55124bd37..a09f8556372d 100644
--- a/crypto/ia64cpuid.S
+++ b/crypto/ia64cpuid.S
@@ -1,6 +1,6 @@
// Copyright 2004-2017 The OpenSSL Project Authors. All Rights Reserved.
//
-// Licensed under the OpenSSL license (the "License"). You may not use
+// Licensed under the Apache License 2.0 (the "License"). You may not use
// this file except in compliance with the License. You can obtain a copy
// in the file LICENSE in the source distribution or at
// https://www.openssl.org/source/license.html
diff --git a/crypto/idea/build.info b/crypto/idea/build.info
index 232612379720..7ac120918b91 100644
--- a/crypto/idea/build.info
+++ b/crypto/idea/build.info
@@ -1,3 +1,10 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- i_cbc.c i_cfb64.c i_ofb64.c i_ecb.c i_skey.c
+$ALL=i_cbc.c i_cfb64.c i_ofb64.c i_ecb.c i_skey.c
+
+SOURCE[../../libcrypto]=$ALL
+
+# When all deprecated symbols are removed, libcrypto doesn't export the
+# idea functions, so we must include them directly in liblegacy.a
+IF[{- $disabled{'deprecated-3.0'} && !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../../providers/liblegacy.a]=$ALL
+ENDIF
diff --git a/crypto/idea/i_cbc.c b/crypto/idea/i_cbc.c
index 4eff467111be..e9608e82f561 100644
--- a/crypto/idea/i_cbc.c
+++ b/crypto/idea/i_cbc.c
@@ -1,12 +1,19 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * IDEA low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/idea.h>
#include "idea_local.h"
diff --git a/crypto/idea/i_cfb64.c b/crypto/idea/i_cfb64.c
index 61c723015b99..afea89edfa08 100644
--- a/crypto/idea/i_cfb64.c
+++ b/crypto/idea/i_cfb64.c
@@ -1,12 +1,19 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * IDEA low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/idea.h>
#include "idea_local.h"
@@ -26,6 +33,11 @@ void IDEA_cfb64_encrypt(const unsigned char *in, unsigned char *out,
unsigned long ti[2];
unsigned char *iv, c, cc;
+ if (n < 0) {
+ *num = -1;
+ return;
+ }
+
iv = (unsigned char *)ivec;
if (encrypt) {
while (l--) {
diff --git a/crypto/idea/i_ecb.c b/crypto/idea/i_ecb.c
index cb724e1a6c0b..6304e6cac802 100644
--- a/crypto/idea/i_ecb.c
+++ b/crypto/idea/i_ecb.c
@@ -1,12 +1,19 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * IDEA low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/idea.h>
#include "idea_local.h"
#include <openssl/opensslv.h>
diff --git a/crypto/idea/i_ofb64.c b/crypto/idea/i_ofb64.c
index f000ced58620..a6a149764dbe 100644
--- a/crypto/idea/i_ofb64.c
+++ b/crypto/idea/i_ofb64.c
@@ -1,12 +1,19 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * IDEA low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/idea.h>
#include "idea_local.h"
@@ -28,6 +35,11 @@ void IDEA_ofb64_encrypt(const unsigned char *in, unsigned char *out,
unsigned char *iv;
int save = 0;
+ if (n < 0) {
+ *num = -1;
+ return;
+ }
+
iv = (unsigned char *)ivec;
n2l(iv, v0);
n2l(iv, v1);
diff --git a/crypto/idea/i_skey.c b/crypto/idea/i_skey.c
index 230338d7e3ab..7564bce5b131 100644
--- a/crypto/idea/i_skey.c
+++ b/crypto/idea/i_skey.c
@@ -1,12 +1,19 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * IDEA low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/idea.h>
#include "idea_local.h"
diff --git a/crypto/idea/idea_local.h b/crypto/idea/idea_local.h
index 50f81dfd8dee..3c9ffa0827d0 100644
--- a/crypto/idea/idea_local.h
+++ b/crypto/idea/idea_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/info.c b/crypto/info.c
new file mode 100644
index 000000000000..a0dc2e80136f
--- /dev/null
+++ b/crypto/info.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include "crypto/rand.h"
+#include "crypto/dso_conf.h"
+#include "internal/thread_once.h"
+#include "internal/cryptlib.h"
+#include "e_os.h"
+#include "buildinf.h"
+
+#if defined(__arm__) || defined(__arm) || defined(__aarch64__)
+# include "arm_arch.h"
+# define CPU_INFO_STR_LEN 128
+#elif defined(__s390__) || defined(__s390x__)
+# include "s390x_arch.h"
+# define CPU_INFO_STR_LEN 2048
+#else
+# define CPU_INFO_STR_LEN 128
+#endif
+
+/* extern declaration to avoid warning */
+extern char ossl_cpu_info_str[];
+
+static char *seed_sources = NULL;
+
+char ossl_cpu_info_str[CPU_INFO_STR_LEN] = "";
+#define CPUINFO_PREFIX "CPUINFO: "
+
+static CRYPTO_ONCE init_info = CRYPTO_ONCE_STATIC_INIT;
+
+DEFINE_RUN_ONCE_STATIC(init_info_strings)
+{
+#if defined(OPENSSL_CPUID_OBJ)
+# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
+ defined(__x86_64) || defined(__x86_64__) || \
+ defined(_M_AMD64) || defined(_M_X64)
+ const char *env;
+
+ BIO_snprintf(ossl_cpu_info_str, sizeof(ossl_cpu_info_str),
+ CPUINFO_PREFIX "OPENSSL_ia32cap=0x%llx:0x%llx",
+ (unsigned long long)OPENSSL_ia32cap_P[0] |
+ (unsigned long long)OPENSSL_ia32cap_P[1] << 32,
+ (unsigned long long)OPENSSL_ia32cap_P[2] |
+ (unsigned long long)OPENSSL_ia32cap_P[3] << 32);
+ if ((env = getenv("OPENSSL_ia32cap")) != NULL)
+ BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str),
+ sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str),
+ " env:%s", env);
+# elif defined(__arm__) || defined(__arm) || defined(__aarch64__)
+ const char *env;
+
+ BIO_snprintf(ossl_cpu_info_str, sizeof(ossl_cpu_info_str),
+ CPUINFO_PREFIX "OPENSSL_armcap=0x%x", OPENSSL_armcap_P);
+ if ((env = getenv("OPENSSL_armcap")) != NULL)
+ BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str),
+ sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str),
+ " env:%s", env);
+# elif defined(__s390__) || defined(__s390x__)
+ const char *env;
+
+ BIO_snprintf(ossl_cpu_info_str, sizeof(ossl_cpu_info_str),
+ CPUINFO_PREFIX "OPENSSL_s390xcap="
+ "stfle:0x%llx:0x%llx:0x%llx:0x%llx:"
+ "kimd:0x%llx:0x%llx:"
+ "klmd:0x%llx:0x%llx:"
+ "km:0x%llx:0x%llx:"
+ "kmc:0x%llx:0x%llx:"
+ "kmac:0x%llx:0x%llx:"
+ "kmctr:0x%llx:0x%llx:"
+ "kmo:0x%llx:0x%llx:"
+ "kmf:0x%llx:0x%llx:"
+ "prno:0x%llx:0x%llx:"
+ "kma:0x%llx:0x%llx:"
+ "pcc:0x%llx:0x%llx:"
+ "kdsa:0x%llx:0x%llx",
+ OPENSSL_s390xcap_P.stfle[0], OPENSSL_s390xcap_P.stfle[1],
+ OPENSSL_s390xcap_P.stfle[2], OPENSSL_s390xcap_P.stfle[3],
+ OPENSSL_s390xcap_P.kimd[0], OPENSSL_s390xcap_P.kimd[1],
+ OPENSSL_s390xcap_P.klmd[0], OPENSSL_s390xcap_P.klmd[1],
+ OPENSSL_s390xcap_P.km[0], OPENSSL_s390xcap_P.km[1],
+ OPENSSL_s390xcap_P.kmc[0], OPENSSL_s390xcap_P.kmc[1],
+ OPENSSL_s390xcap_P.kmac[0], OPENSSL_s390xcap_P.kmac[1],
+ OPENSSL_s390xcap_P.kmctr[0], OPENSSL_s390xcap_P.kmctr[1],
+ OPENSSL_s390xcap_P.kmo[0], OPENSSL_s390xcap_P.kmo[1],
+ OPENSSL_s390xcap_P.kmf[0], OPENSSL_s390xcap_P.kmf[1],
+ OPENSSL_s390xcap_P.prno[0], OPENSSL_s390xcap_P.prno[1],
+ OPENSSL_s390xcap_P.kma[0], OPENSSL_s390xcap_P.kma[1],
+ OPENSSL_s390xcap_P.pcc[0], OPENSSL_s390xcap_P.pcc[1],
+ OPENSSL_s390xcap_P.kdsa[0], OPENSSL_s390xcap_P.kdsa[1]);
+ if ((env = getenv("OPENSSL_s390xcap")) != NULL)
+ BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str),
+ sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str),
+ " env:%s", env);
+# endif
+#endif
+
+ {
+ static char seeds[512] = "";
+
+#define add_seeds_string(str) \
+ do { \
+ if (seeds[0] != '\0') \
+ OPENSSL_strlcat(seeds, " ", sizeof(seeds)); \
+ OPENSSL_strlcat(seeds, str, sizeof(seeds)); \
+ } while (0)
+#define add_seeds_stringlist(label, strlist) \
+ do { \
+ add_seeds_string(label "("); \
+ { \
+ const char *dev[] = { strlist, NULL }; \
+ const char **p; \
+ int first = 1; \
+ \
+ for (p = dev; *p != NULL; p++) { \
+ if (!first) \
+ OPENSSL_strlcat(seeds, " ", sizeof(seeds)); \
+ first = 0; \
+ OPENSSL_strlcat(seeds, *p, sizeof(seeds)); \
+ } \
+ } \
+ OPENSSL_strlcat(seeds, ")", sizeof(seeds)); \
+ } while (0)
+
+#ifdef OPENSSL_RAND_SEED_NONE
+ add_seeds_string("none");
+#endif
+#ifdef OPENSSL_RAND_SEED_RDTSC
+ add_seeds_string("rdtsc");
+#endif
+#ifdef OPENSSL_RAND_SEED_RDCPU
+ add_seeds_string("rdrand ( rdseed rdrand )");
+#endif
+#ifdef OPENSSL_RAND_SEED_LIBRANDOM
+ add_seeds_string("C-library-random");
+#endif
+#ifdef OPENSSL_RAND_SEED_GETRANDOM
+ add_seeds_string("getrandom-syscall");
+#endif
+#ifdef OPENSSL_RAND_SEED_DEVRANDOM
+ add_seeds_stringlist("random-device", DEVRANDOM);
+#endif
+#ifdef OPENSSL_RAND_SEED_EGD
+ add_seeds_stringlist("EGD", DEVRANDOM_EGD);
+#endif
+#ifdef OPENSSL_RAND_SEED_OS
+ add_seeds_string("os-specific");
+#endif
+ seed_sources = seeds;
+ }
+ return 1;
+}
+
+const char *OPENSSL_info(int t)
+{
+ /*
+ * We don't care about the result. Worst case scenario, the strings
+ * won't be initialised, i.e. remain NULL, which means that the info
+ * isn't available anyway...
+ */
+ (void)RUN_ONCE(&init_info, init_info_strings);
+
+ switch (t) {
+ case OPENSSL_INFO_CONFIG_DIR:
+ return OPENSSLDIR;
+ case OPENSSL_INFO_ENGINES_DIR:
+ return ENGINESDIR;
+ case OPENSSL_INFO_MODULES_DIR:
+ return MODULESDIR;
+ case OPENSSL_INFO_DSO_EXTENSION:
+ return DSO_EXTENSION;
+ case OPENSSL_INFO_DIR_FILENAME_SEPARATOR:
+#if defined(_WIN32)
+ return "\\";
+#elif defined(__VMS)
+ return "";
+#else /* Assume POSIX */
+ return "/";
+#endif
+ case OPENSSL_INFO_LIST_SEPARATOR:
+ {
+ static const char list_sep[] = { LIST_SEPARATOR_CHAR, '\0' };
+ return list_sep;
+ }
+ case OPENSSL_INFO_SEED_SOURCE:
+ return seed_sources;
+ case OPENSSL_INFO_CPU_SETTINGS:
+ /*
+ * If successfully initialized, ossl_cpu_info_str will start
+ * with CPUINFO_PREFIX, if failed it will be an empty string.
+ * Strip away the CPUINFO_PREFIX which we don't need here.
+ */
+ if (ossl_cpu_info_str[0] != '\0')
+ return ossl_cpu_info_str + strlen(CPUINFO_PREFIX);
+ break;
+ default:
+ break;
+ }
+ /* Not an error */
+ return NULL;
+}
diff --git a/crypto/init.c b/crypto/init.c
index b23af7977cd2..cacf637c89f8 100644
--- a/crypto/init.c
+++ b/crypto/init.c
@@ -1,12 +1,15 @@
/*
* Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "e_os.h"
#include "crypto/cryptlib.h"
#include <openssl/err.h>
@@ -27,53 +30,12 @@
#include "crypto/dso_conf.h"
#include "internal/dso.h"
#include "crypto/store.h"
+#include <openssl/cmp_util.h> /* for OSSL_CMP_log_close() */
+#include <openssl/trace.h>
+#include "crypto/ctype.h"
static int stopped = 0;
-
-/*
- * Since per-thread-specific-data destructors are not universally
- * available, i.e. not on Windows, only below CRYPTO_THREAD_LOCAL key
- * is assumed to have destructor associated. And then an effort is made
- * to call this single destructor on non-pthread platform[s].
- *
- * Initial value is "impossible". It is used as guard value to shortcut
- * destructor for threads terminating before libcrypto is initialized or
- * after it's de-initialized. Access to the key doesn't have to be
- * serialized for the said threads, because they didn't use libcrypto
- * and it doesn't matter if they pick "impossible" or dereference real
- * key value and pull NULL past initialization in the first thread that
- * intends to use libcrypto.
- */
-static union {
- long sane;
- CRYPTO_THREAD_LOCAL value;
-} destructor_key = { -1 };
-
-static void ossl_init_thread_stop(struct thread_local_inits_st *locals);
-
-static void ossl_init_thread_destructor(void *local)
-{
- ossl_init_thread_stop((struct thread_local_inits_st *)local);
-}
-
-static struct thread_local_inits_st *ossl_init_get_thread_local(int alloc)
-{
- struct thread_local_inits_st *local =
- CRYPTO_THREAD_get_local(&destructor_key.value);
-
- if (alloc) {
- if (local == NULL
- && (local = OPENSSL_zalloc(sizeof(*local))) != NULL
- && !CRYPTO_THREAD_set_local(&destructor_key.value, local)) {
- OPENSSL_free(local);
- return NULL;
- }
- } else {
- CRYPTO_THREAD_set_local(&destructor_key.value, NULL);
- }
-
- return local;
-}
+static uint64_t optsdone = 0;
typedef struct ossl_init_stop_st OPENSSL_INIT_STOP;
struct ossl_init_stop_st {
@@ -82,38 +44,45 @@ struct ossl_init_stop_st {
};
static OPENSSL_INIT_STOP *stop_handlers = NULL;
+/* Guards access to the optsdone variable on platforms without atomics */
+static CRYPTO_RWLOCK *optsdone_lock = NULL;
+/* Guards simultaneous INIT_LOAD_CONFIG calls with non-NULL settings */
static CRYPTO_RWLOCK *init_lock = NULL;
+static CRYPTO_THREAD_LOCAL in_init_config_local;
static CRYPTO_ONCE base = CRYPTO_ONCE_STATIC_INIT;
static int base_inited = 0;
DEFINE_RUN_ONCE_STATIC(ossl_init_base)
{
- CRYPTO_THREAD_LOCAL key;
+ /* no need to init trace */
-#ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_base: Setting up stop handlers\n");
-#endif
+ OSSL_TRACE(INIT, "ossl_init_base: setting up stop handlers\n");
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
ossl_malloc_setup_failures();
#endif
- if (!CRYPTO_THREAD_init_local(&key, ossl_init_thread_destructor))
- return 0;
- if ((init_lock = CRYPTO_THREAD_lock_new()) == NULL)
+
+ if ((optsdone_lock = CRYPTO_THREAD_lock_new()) == NULL
+ || (init_lock = CRYPTO_THREAD_lock_new()) == NULL)
goto err;
+
OPENSSL_cpuid_setup();
- destructor_key.value = key;
+ if (!ossl_init_thread())
+ goto err;
+
+ if (!CRYPTO_THREAD_init_local(&in_init_config_local, NULL))
+ goto err;
+
base_inited = 1;
return 1;
err:
-#ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_base not ok!\n");
-#endif
+ OSSL_TRACE(INIT, "ossl_init_base failed!\n");
+ CRYPTO_THREAD_lock_free(optsdone_lock);
+ optsdone_lock = NULL;
CRYPTO_THREAD_lock_free(init_lock);
init_lock = NULL;
- CRYPTO_THREAD_cleanup_local(&key);
return 0;
}
@@ -132,7 +101,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_register_atexit)
fprintf(stderr, "OPENSSL_INIT: ossl_init_register_atexit()\n");
#endif
#ifndef OPENSSL_SYS_UEFI
-# ifdef _WIN32
+# if defined(_WIN32) && !defined(__BORLANDC__)
/* We use _onexit() in preference because it gets called on DLL unload */
if (_onexit(win32atexit) == NULL)
return 0;
@@ -158,9 +127,8 @@ DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_register_atexit,
static CRYPTO_ONCE load_crypto_nodelete = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete)
{
-#ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_load_crypto_nodelete()\n");
-#endif
+ OSSL_TRACE(INIT, "ossl_init_load_crypto_nodelete()\n");
+
#if !defined(OPENSSL_USE_NODELETE) \
&& !defined(OPENSSL_NO_PINSHARED)
# if defined(DSO_WIN32) && !defined(_WIN32_WCE)
@@ -173,10 +141,10 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete)
| GET_MODULE_HANDLE_EX_FLAG_PIN,
(void *)&base_inited, &handle);
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: obtained DSO reference? %s\n",
- (ret == TRUE ? "No!" : "Yes."));
-# endif
+ OSSL_TRACE1(INIT,
+ "ossl_init_load_crypto_nodelete: "
+ "obtained DSO reference? %s\n",
+ (ret == TRUE ? "No!" : "Yes."));
return (ret == TRUE) ? 1 : 0;
}
# elif !defined(DSO_NONE)
@@ -192,15 +160,13 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete)
return 0;
dso = DSO_dsobyaddr(&base_inited, DSO_FLAG_NO_UNLOAD_ON_FREE);
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: obtained DSO reference? %s\n",
- (dso == NULL ? "No!" : "Yes."));
/*
* In case of No!, it is uncertain our exit()-handlers can still be
* called. After dlclose() the whole library might have been unloaded
* already.
*/
-# endif
+ OSSL_TRACE1(INIT, "obtained DSO reference? %s\n",
+ (dso == NULL ? "No!" : "Yes."));
DSO_free(dso);
err_unshelve_state(err);
}
@@ -220,11 +186,8 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_strings)
* pulling in all the error strings during static linking
*/
#if !defined(OPENSSL_NO_ERR) && !defined(OPENSSL_NO_AUTOERRINIT)
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_load_crypto_strings: "
- "err_load_crypto_strings_int()\n");
-# endif
- ret = err_load_crypto_strings_int();
+ OSSL_TRACE(INIT, "ossl_err_load_crypto_strings()\n");
+ ret = ossl_err_load_crypto_strings();
#endif
return ret;
}
@@ -244,10 +207,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_ciphers)
* pulling in all the ciphers during static linking
*/
#ifndef OPENSSL_NO_AUTOALGINIT
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_add_all_ciphers: "
- "openssl_add_all_ciphers_int()\n");
-# endif
+ OSSL_TRACE(INIT, "openssl_add_all_ciphers_int()\n");
openssl_add_all_ciphers_int();
#endif
return 1;
@@ -268,10 +228,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_digests)
* pulling in all the ciphers during static linking
*/
#ifndef OPENSSL_NO_AUTOALGINIT
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_add_all_digests: "
- "openssl_add_all_digests()\n");
-# endif
+ OSSL_TRACE(INIT, "openssl_add_all_digests()\n");
openssl_add_all_digests_int();
#endif
return 1;
@@ -289,17 +246,22 @@ static int config_inited = 0;
static const OPENSSL_INIT_SETTINGS *conf_settings = NULL;
DEFINE_RUN_ONCE_STATIC(ossl_init_config)
{
- int ret = openssl_config_int(conf_settings);
+ int ret = ossl_config_int(NULL);
+
+ config_inited = 1;
+ return ret;
+}
+DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_config_settings, ossl_init_config)
+{
+ int ret = ossl_config_int(conf_settings);
+
config_inited = 1;
return ret;
}
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_config, ossl_init_config)
{
-#ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr,
- "OPENSSL_INIT: ossl_init_config: openssl_no_config_int()\n");
-#endif
- openssl_no_config_int();
+ OSSL_TRACE(INIT, "ossl_no_config_int()\n");
+ ossl_no_config_int();
config_inited = 1;
return 1;
}
@@ -308,9 +270,7 @@ static CRYPTO_ONCE async = CRYPTO_ONCE_STATIC_INIT;
static int async_inited = 0;
DEFINE_RUN_ONCE_STATIC(ossl_init_async)
{
-#ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_async: async_init()\n");
-#endif
+ OSSL_TRACE(INIT, "async_init()\n");
if (!async_init())
return 0;
async_inited = 1;
@@ -321,34 +281,15 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_async)
static CRYPTO_ONCE engine_openssl = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_openssl)
{
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_openssl: "
- "engine_load_openssl_int()\n");
-# endif
+ OSSL_TRACE(INIT, "engine_load_openssl_int()\n");
engine_load_openssl_int();
return 1;
}
-# ifndef OPENSSL_NO_DEVCRYPTOENG
-static CRYPTO_ONCE engine_devcrypto = CRYPTO_ONCE_STATIC_INIT;
-DEFINE_RUN_ONCE_STATIC(ossl_init_engine_devcrypto)
-{
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_devcrypto: "
- "engine_load_devcrypto_int()\n");
-# endif
- engine_load_devcrypto_int();
- return 1;
-}
-# endif
-
# ifndef OPENSSL_NO_RDRAND
static CRYPTO_ONCE engine_rdrand = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_rdrand)
{
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_rdrand: "
- "engine_load_rdrand_int()\n");
-# endif
+ OSSL_TRACE(INIT, "engine_load_rdrand_int()\n");
engine_load_rdrand_int();
return 1;
}
@@ -356,22 +297,25 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_rdrand)
static CRYPTO_ONCE engine_dynamic = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_dynamic)
{
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_dynamic: "
- "engine_load_dynamic_int()\n");
-# endif
+ OSSL_TRACE(INIT, "engine_load_dynamic_int()\n");
engine_load_dynamic_int();
return 1;
}
# ifndef OPENSSL_NO_STATIC_ENGINE
-# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
+# ifndef OPENSSL_NO_DEVCRYPTOENG
+static CRYPTO_ONCE engine_devcrypto = CRYPTO_ONCE_STATIC_INIT;
+DEFINE_RUN_ONCE_STATIC(ossl_init_engine_devcrypto)
+{
+ OSSL_TRACE(INIT, "engine_load_devcrypto_int()\n");
+ engine_load_devcrypto_int();
+ return 1;
+}
+# endif
+# if !defined(OPENSSL_NO_PADLOCKENG)
static CRYPTO_ONCE engine_padlock = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_padlock)
{
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_padlock: "
- "engine_load_padlock_int()\n");
-# endif
+ OSSL_TRACE(INIT, "engine_load_padlock_int()\n");
engine_load_padlock_int();
return 1;
}
@@ -380,10 +324,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_padlock)
static CRYPTO_ONCE engine_capi = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_capi)
{
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_capi: "
- "engine_load_capi_int()\n");
-# endif
+ OSSL_TRACE(INIT, "engine_load_capi_int()\n");
engine_load_capi_int();
return 1;
}
@@ -392,10 +333,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_capi)
static CRYPTO_ONCE engine_afalg = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_afalg)
{
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_afalg: "
- "engine_load_afalg_int()\n");
-# endif
+ OSSL_TRACE(INIT, "engine_load_afalg_int()\n");
engine_load_afalg_int();
return 1;
}
@@ -403,100 +341,14 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_afalg)
# endif
#endif
-#ifndef OPENSSL_NO_COMP
-static CRYPTO_ONCE zlib = CRYPTO_ONCE_STATIC_INIT;
-
-static int zlib_inited = 0;
-DEFINE_RUN_ONCE_STATIC(ossl_init_zlib)
-{
- /* Do nothing - we need to know about this for the later cleanup */
- zlib_inited = 1;
- return 1;
-}
-#endif
-
-static void ossl_init_thread_stop(struct thread_local_inits_st *locals)
-{
- /* Can't do much about this */
- if (locals == NULL)
- return;
-
- if (locals->async) {
-#ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: "
- "async_delete_thread_state()\n");
-#endif
- async_delete_thread_state();
- }
-
- if (locals->err_state) {
-#ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: "
- "err_delete_thread_state()\n");
-#endif
- err_delete_thread_state();
- }
-
- if (locals->rand) {
-#ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: "
- "drbg_delete_thread_state()\n");
-#endif
- drbg_delete_thread_state();
- }
-
- OPENSSL_free(locals);
-}
-
-void OPENSSL_thread_stop(void)
-{
- if (destructor_key.sane != -1)
- ossl_init_thread_stop(ossl_init_get_thread_local(0));
-}
-
-int ossl_init_thread_start(uint64_t opts)
-{
- struct thread_local_inits_st *locals;
-
- if (!OPENSSL_init_crypto(0, NULL))
- return 0;
-
- locals = ossl_init_get_thread_local(1);
-
- if (locals == NULL)
- return 0;
-
- if (opts & OPENSSL_INIT_THREAD_ASYNC) {
-#ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_start: "
- "marking thread for async\n");
-#endif
- locals->async = 1;
- }
-
- if (opts & OPENSSL_INIT_THREAD_ERR_STATE) {
-#ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_start: "
- "marking thread for err_state\n");
-#endif
- locals->err_state = 1;
- }
-
- if (opts & OPENSSL_INIT_THREAD_RAND) {
-#ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_start: "
- "marking thread for rand\n");
-#endif
- locals->rand = 1;
- }
-
- return 1;
-}
-
void OPENSSL_cleanup(void)
{
OPENSSL_INIT_STOP *currhandler, *lasthandler;
- CRYPTO_THREAD_LOCAL key;
+
+ /*
+ * At some point we should consider looking at this function with a view to
+ * moving most/all of this into onfree handlers in OSSL_LIB_CTX.
+ */
/* If we've not been inited then no need to deinit */
if (!base_inited)
@@ -511,7 +363,7 @@ void OPENSSL_cleanup(void)
* Thread stop may not get automatically called by the thread library for
* the very last thread in some situations, so call it directly.
*/
- ossl_init_thread_stop(ossl_init_get_thread_local(0));
+ OPENSSL_thread_stop();
currhandler = stop_handlers;
while (currhandler != NULL) {
@@ -522,84 +374,83 @@ void OPENSSL_cleanup(void)
}
stop_handlers = NULL;
+ CRYPTO_THREAD_lock_free(optsdone_lock);
+ optsdone_lock = NULL;
CRYPTO_THREAD_lock_free(init_lock);
init_lock = NULL;
+ CRYPTO_THREAD_cleanup_local(&in_init_config_local);
+
/*
* We assume we are single-threaded for this function, i.e. no race
* conditions for the various "*_inited" vars below.
*/
#ifndef OPENSSL_NO_COMP
- if (zlib_inited) {
-#ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
- "comp_zlib_cleanup_int()\n");
-#endif
- comp_zlib_cleanup_int();
- }
+ OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_comp_zlib_cleanup()\n");
+ ossl_comp_zlib_cleanup();
#endif
if (async_inited) {
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
- "async_deinit()\n");
-# endif
+ OSSL_TRACE(INIT, "OPENSSL_cleanup: async_deinit()\n");
async_deinit();
}
- key = destructor_key.value;
- destructor_key.sane = -1;
- CRYPTO_THREAD_cleanup_local(&key);
-
-#ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
- "rand_cleanup_int()\n");
- fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
- "conf_modules_free_int()\n");
-#ifndef OPENSSL_NO_ENGINE
- fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
- "engine_cleanup_int()\n");
-#endif
- fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
- "crypto_cleanup_all_ex_data_int()\n");
- fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
- "bio_sock_cleanup_int()\n");
- fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
- "bio_cleanup()\n");
- fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
- "evp_cleanup_int()\n");
- fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
- "obj_cleanup_int()\n");
- fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
- "err_cleanup()\n");
-#endif
/*
* Note that cleanup order is important:
- * - rand_cleanup_int could call an ENGINE's RAND cleanup function so
+ * - ossl_rand_cleanup_int could call an ENGINE's RAND cleanup function so
* must be called before engine_cleanup_int()
* - ENGINEs use CRYPTO_EX_DATA and therefore, must be cleaned up
- * before the ex data handlers are wiped in CRYPTO_cleanup_all_ex_data().
- * - conf_modules_free_int() can end up in ENGINE code so must be called
+ * before the ex data handlers are wiped during default ossl_lib_ctx deinit.
+ * - ossl_config_modules_free() can end up in ENGINE code so must be called
* before engine_cleanup_int()
* - ENGINEs and additional EVP algorithms might use added OIDs names so
- * obj_cleanup_int() must be called last
+ * ossl_obj_cleanup_int() must be called last
*/
- rand_cleanup_int();
- rand_drbg_cleanup_int();
- conf_modules_free_int();
+ OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_rand_cleanup_int()\n");
+ ossl_rand_cleanup_int();
+
+ OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_config_modules_free()\n");
+ ossl_config_modules_free();
+
#ifndef OPENSSL_NO_ENGINE
+ OSSL_TRACE(INIT, "OPENSSL_cleanup: engine_cleanup_int()\n");
engine_cleanup_int();
#endif
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_store_cleanup_int()\n");
ossl_store_cleanup_int();
- crypto_cleanup_all_ex_data_int();
+#endif
+
+ OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_lib_ctx_default_deinit()\n");
+ ossl_lib_ctx_default_deinit();
+
+ ossl_cleanup_thread();
+
+ OSSL_TRACE(INIT, "OPENSSL_cleanup: bio_cleanup()\n");
bio_cleanup();
+
+ OSSL_TRACE(INIT, "OPENSSL_cleanup: evp_cleanup_int()\n");
evp_cleanup_int();
- obj_cleanup_int();
+
+ OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_obj_cleanup_int()\n");
+ ossl_obj_cleanup_int();
+
+ OSSL_TRACE(INIT, "OPENSSL_cleanup: err_int()\n");
err_cleanup();
+ OSSL_TRACE(INIT, "OPENSSL_cleanup: CRYPTO_secure_malloc_done()\n");
CRYPTO_secure_malloc_done();
+#ifndef OPENSSL_NO_CMP
+ OSSL_TRACE(INIT, "OPENSSL_cleanup: OSSL_CMP_log_close()\n");
+ OSSL_CMP_log_close();
+#endif
+
+ OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_trace_cleanup()\n");
+ ossl_trace_cleanup();
+
base_inited = 0;
}
@@ -610,13 +461,39 @@ void OPENSSL_cleanup(void)
*/
int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
{
+ uint64_t tmp;
+ int aloaddone = 0;
+
+ /* Applications depend on 0 being returned when cleanup was already done */
if (stopped) {
if (!(opts & OPENSSL_INIT_BASE_ONLY))
- CRYPTOerr(CRYPTO_F_OPENSSL_INIT_CRYPTO, ERR_R_INIT_FAIL);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_INIT_FAIL);
return 0;
}
/*
+ * We ignore failures from this function. It is probably because we are
+ * on a platform that doesn't support lockless atomic loads (we may not
+ * have created optsdone_lock yet so we can't use it). This is just an
+ * optimisation to skip the full checks in this function if we don't need
+ * to, so we carry on regardless in the event of failure.
+ *
+ * There could be a race here with other threads, so that optsdone has not
+ * been updated yet, even though the options have in fact been initialised.
+ * This doesn't matter - it just means we will run the full function
+ * unnecessarily - but all the critical code is contained in RUN_ONCE
+ * functions anyway so we are safe.
+ */
+ if (CRYPTO_atomic_load(&optsdone, &tmp, NULL)) {
+ if ((tmp & opts) == opts)
+ return 1;
+ aloaddone = 1;
+ }
+
+ /*
+ * At some point we should look at this function with a view to moving
+ * most/all of this into OSSL_LIB_CTX.
+ *
* When the caller specifies OPENSSL_INIT_BASE_ONLY, that should be the
* *only* option specified. With that option we return immediately after
* doing the requested limited initialization. Note that
@@ -629,10 +506,23 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
*/
if (!RUN_ONCE(&base, ossl_init_base))
return 0;
+
if (opts & OPENSSL_INIT_BASE_ONLY)
return 1;
/*
+ * optsdone_lock should definitely be set up now, so we can now repeat the
+ * same check from above but be sure that it will work even on platforms
+ * without lockless CRYPTO_atomic_load
+ */
+ if (!aloaddone) {
+ if (!CRYPTO_atomic_load(&optsdone, &tmp, optsdone_lock))
+ return 0;
+ if ((tmp & opts) == opts)
+ return 1;
+ }
+
+ /*
* Now we don't always set up exit handlers, the INIT_BASE_ONLY calls
* should not have the side-effect of setting up exit handlers, and
* therefore, this code block is below the INIT_BASE_ONLY-conditioned early
@@ -686,14 +576,29 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
return 0;
if (opts & OPENSSL_INIT_LOAD_CONFIG) {
- int ret;
- CRYPTO_THREAD_write_lock(init_lock);
- conf_settings = settings;
- ret = RUN_ONCE(&config, ossl_init_config);
- conf_settings = NULL;
- CRYPTO_THREAD_unlock(init_lock);
- if (ret <= 0)
- return 0;
+ int loading = CRYPTO_THREAD_get_local(&in_init_config_local) != NULL;
+
+ /* If called recursively from OBJ_ calls, just skip it. */
+ if (!loading) {
+ int ret;
+
+ if (!CRYPTO_THREAD_set_local(&in_init_config_local, (void *)-1))
+ return 0;
+ if (settings == NULL) {
+ ret = RUN_ONCE(&config, ossl_init_config);
+ } else {
+ if (!CRYPTO_THREAD_write_lock(init_lock))
+ return 0;
+ conf_settings = settings;
+ ret = RUN_ONCE_ALT(&config, ossl_init_config_settings,
+ ossl_init_config);
+ conf_settings = NULL;
+ CRYPTO_THREAD_unlock(init_lock);
+ }
+
+ if (ret <= 0)
+ return 0;
+ }
}
if ((opts & OPENSSL_INIT_ASYNC)
@@ -704,11 +609,6 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
if ((opts & OPENSSL_INIT_ENGINE_OPENSSL)
&& !RUN_ONCE(&engine_openssl, ossl_init_engine_openssl))
return 0;
-# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_DEVCRYPTOENG)
- if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV)
- && !RUN_ONCE(&engine_devcrypto, ossl_init_engine_devcrypto))
- return 0;
-# endif
# ifndef OPENSSL_NO_RDRAND
if ((opts & OPENSSL_INIT_ENGINE_RDRAND)
&& !RUN_ONCE(&engine_rdrand, ossl_init_engine_rdrand))
@@ -718,7 +618,12 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
&& !RUN_ONCE(&engine_dynamic, ossl_init_engine_dynamic))
return 0;
# ifndef OPENSSL_NO_STATIC_ENGINE
-# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
+# ifndef OPENSSL_NO_DEVCRYPTOENG
+ if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV)
+ && !RUN_ONCE(&engine_devcrypto, ossl_init_engine_devcrypto))
+ return 0;
+# endif
+# if !defined(OPENSSL_NO_PADLOCKENG)
if ((opts & OPENSSL_INIT_ENGINE_PADLOCK)
&& !RUN_ONCE(&engine_padlock, ossl_init_engine_padlock))
return 0;
@@ -741,11 +646,8 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
}
#endif
-#ifndef OPENSSL_NO_COMP
- if ((opts & OPENSSL_INIT_ZLIB)
- && !RUN_ONCE(&zlib, ossl_init_zlib))
+ if (!CRYPTO_atomic_or(&optsdone, opts, &tmp, optsdone_lock))
return 0;
-#endif
return 1;
}
@@ -757,28 +659,26 @@ int OPENSSL_atexit(void (*handler)(void))
#if !defined(OPENSSL_USE_NODELETE)\
&& !defined(OPENSSL_NO_PINSHARED)
{
+# if defined(DSO_WIN32) && !defined(_WIN32_WCE)
+ HMODULE handle = NULL;
+ BOOL ret;
union {
void *sym;
void (*func)(void);
} handlersym;
handlersym.func = handler;
-# if defined(DSO_WIN32) && !defined(_WIN32_WCE)
- {
- HMODULE handle = NULL;
- BOOL ret;
-
- /*
- * We don't use the DSO route for WIN32 because there is a better
- * way
- */
- ret = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
- | GET_MODULE_HANDLE_EX_FLAG_PIN,
- handlersym.sym, &handle);
-
- if (!ret)
- return 0;
- }
+
+ /*
+ * We don't use the DSO route for WIN32 because there is a better
+ * way
+ */
+ ret = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
+ | GET_MODULE_HANDLE_EX_FLAG_PIN,
+ handlersym.sym, &handle);
+
+ if (!ret)
+ return 0;
# elif !defined(DSO_NONE)
/*
* Deliberately leak a reference to the handler. This will force the
@@ -786,26 +686,28 @@ int OPENSSL_atexit(void (*handler)(void))
* atexit handler. If -znodelete has been used then this is
* unnecessary.
*/
- {
- DSO *dso = NULL;
-
- ERR_set_mark();
- dso = DSO_dsobyaddr(handlersym.sym, DSO_FLAG_NO_UNLOAD_ON_FREE);
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr,
- "OPENSSL_INIT: OPENSSL_atexit: obtained DSO reference? %s\n",
- (dso == NULL ? "No!" : "Yes."));
- /* See same code above in ossl_init_base() for an explanation. */
-# endif
- DSO_free(dso);
- ERR_pop_to_mark();
- }
+ DSO *dso = NULL;
+ union {
+ void *sym;
+ void (*func)(void);
+ } handlersym;
+
+ handlersym.func = handler;
+
+ ERR_set_mark();
+ dso = DSO_dsobyaddr(handlersym.sym, DSO_FLAG_NO_UNLOAD_ON_FREE);
+ /* See same code above in ossl_init_base() for an explanation. */
+ OSSL_TRACE1(INIT,
+ "atexit: obtained DSO reference? %s\n",
+ (dso == NULL ? "No!" : "Yes."));
+ DSO_free(dso);
+ ERR_pop_to_mark();
# endif
}
#endif
if ((newhand = OPENSSL_malloc(sizeof(*newhand))) == NULL) {
- CRYPTOerr(CRYPTO_F_OPENSSL_ATEXIT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -816,27 +718,3 @@ int OPENSSL_atexit(void (*handler)(void))
return 1;
}
-#ifdef OPENSSL_SYS_UNIX
-/*
- * The following three functions are for OpenSSL developers. This is
- * where we set/reset state across fork (called via pthread_atfork when
- * it exists, or manually by the application when it doesn't).
- *
- * WARNING! If you put code in either OPENSSL_fork_parent or
- * OPENSSL_fork_child, you MUST MAKE SURE that they are async-signal-
- * safe. See this link, for example:
- * http://man7.org/linux/man-pages/man7/signal-safety.7.html
- */
-
-void OPENSSL_fork_prepare(void)
-{
-}
-
-void OPENSSL_fork_parent(void)
-{
-}
-
-void OPENSSL_fork_child(void)
-{
-}
-#endif
diff --git a/crypto/initthread.c b/crypto/initthread.c
new file mode 100644
index 000000000000..1bdaeda9fc8e
--- /dev/null
+++ b/crypto/initthread.c
@@ -0,0 +1,467 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/core_dispatch.h>
+#include "crypto/cryptlib.h"
+#include "prov/providercommon.h"
+#include "internal/thread_once.h"
+
+#ifdef FIPS_MODULE
+#include "prov/provider_ctx.h"
+
+/*
+ * Thread aware code may want to be told about thread stop events. We register
+ * to hear about those thread stop events when we see a new thread has started.
+ * We call the ossl_init_thread_start function to do that. In the FIPS provider
+ * we have our own copy of ossl_init_thread_start, which cascades notifications
+ * about threads stopping from libcrypto to all the code in the FIPS provider
+ * that needs to know about it.
+ *
+ * The FIPS provider tells libcrypto about which threads it is interested in
+ * by calling "c_thread_start" which is a function pointer created during
+ * provider initialisation (i.e. OSSL_init_provider).
+ */
+extern OSSL_FUNC_core_thread_start_fn *c_thread_start;
+#endif
+
+typedef struct thread_event_handler_st THREAD_EVENT_HANDLER;
+struct thread_event_handler_st {
+#ifndef FIPS_MODULE
+ const void *index;
+#endif
+ void *arg;
+ OSSL_thread_stop_handler_fn handfn;
+ THREAD_EVENT_HANDLER *next;
+};
+
+#ifndef FIPS_MODULE
+DEFINE_SPECIAL_STACK_OF(THREAD_EVENT_HANDLER_PTR, THREAD_EVENT_HANDLER *)
+
+typedef struct global_tevent_register_st GLOBAL_TEVENT_REGISTER;
+struct global_tevent_register_st {
+ STACK_OF(THREAD_EVENT_HANDLER_PTR) *skhands;
+ CRYPTO_RWLOCK *lock;
+};
+
+static GLOBAL_TEVENT_REGISTER *glob_tevent_reg = NULL;
+
+static CRYPTO_ONCE tevent_register_runonce = CRYPTO_ONCE_STATIC_INIT;
+
+DEFINE_RUN_ONCE_STATIC(create_global_tevent_register)
+{
+ glob_tevent_reg = OPENSSL_zalloc(sizeof(*glob_tevent_reg));
+ if (glob_tevent_reg == NULL)
+ return 0;
+
+ glob_tevent_reg->skhands = sk_THREAD_EVENT_HANDLER_PTR_new_null();
+ glob_tevent_reg->lock = CRYPTO_THREAD_lock_new();
+ if (glob_tevent_reg->skhands == NULL || glob_tevent_reg->lock == NULL) {
+ sk_THREAD_EVENT_HANDLER_PTR_free(glob_tevent_reg->skhands);
+ CRYPTO_THREAD_lock_free(glob_tevent_reg->lock);
+ OPENSSL_free(glob_tevent_reg);
+ glob_tevent_reg = NULL;
+ return 0;
+ }
+
+ return 1;
+}
+
+static GLOBAL_TEVENT_REGISTER *get_global_tevent_register(void)
+{
+ if (!RUN_ONCE(&tevent_register_runonce, create_global_tevent_register))
+ return NULL;
+ return glob_tevent_reg;
+}
+#endif
+
+#ifndef FIPS_MODULE
+static int init_thread_push_handlers(THREAD_EVENT_HANDLER **hands);
+static void init_thread_remove_handlers(THREAD_EVENT_HANDLER **handsin);
+static void init_thread_destructor(void *hands);
+static int init_thread_deregister(void *arg, int all);
+#endif
+static void init_thread_stop(void *arg, THREAD_EVENT_HANDLER **hands);
+
+static THREAD_EVENT_HANDLER **
+init_get_thread_local(CRYPTO_THREAD_LOCAL *local, int alloc, int keep)
+{
+ THREAD_EVENT_HANDLER **hands = CRYPTO_THREAD_get_local(local);
+
+ if (alloc) {
+ if (hands == NULL) {
+
+ if ((hands = OPENSSL_zalloc(sizeof(*hands))) == NULL)
+ return NULL;
+
+ if (!CRYPTO_THREAD_set_local(local, hands)) {
+ OPENSSL_free(hands);
+ return NULL;
+ }
+
+#ifndef FIPS_MODULE
+ if (!init_thread_push_handlers(hands)) {
+ CRYPTO_THREAD_set_local(local, NULL);
+ OPENSSL_free(hands);
+ return NULL;
+ }
+#endif
+ }
+ } else if (!keep) {
+ CRYPTO_THREAD_set_local(local, NULL);
+ }
+
+ return hands;
+}
+
+#ifndef FIPS_MODULE
+/*
+ * Since per-thread-specific-data destructors are not universally
+ * available, i.e. not on Windows, only below CRYPTO_THREAD_LOCAL key
+ * is assumed to have destructor associated. And then an effort is made
+ * to call this single destructor on non-pthread platform[s].
+ *
+ * Initial value is "impossible". It is used as guard value to shortcut
+ * destructor for threads terminating before libcrypto is initialized or
+ * after it's de-initialized. Access to the key doesn't have to be
+ * serialized for the said threads, because they didn't use libcrypto
+ * and it doesn't matter if they pick "impossible" or dereference real
+ * key value and pull NULL past initialization in the first thread that
+ * intends to use libcrypto.
+ */
+static union {
+ long sane;
+ CRYPTO_THREAD_LOCAL value;
+} destructor_key = { -1 };
+
+/*
+ * The thread event handler list is a thread specific linked list
+ * of callback functions which are invoked in list order by the
+ * current thread in case of certain events. (Currently, there is
+ * only one type of event, the 'thread stop' event.)
+ *
+ * We also keep a global reference to that linked list, so that we
+ * can deregister handlers if necessary before all the threads are
+ * stopped.
+ */
+static int init_thread_push_handlers(THREAD_EVENT_HANDLER **hands)
+{
+ int ret;
+ GLOBAL_TEVENT_REGISTER *gtr;
+
+ gtr = get_global_tevent_register();
+ if (gtr == NULL)
+ return 0;
+
+ if (!CRYPTO_THREAD_write_lock(gtr->lock))
+ return 0;
+ ret = (sk_THREAD_EVENT_HANDLER_PTR_push(gtr->skhands, hands) != 0);
+ CRYPTO_THREAD_unlock(gtr->lock);
+
+ return ret;
+}
+
+static void init_thread_remove_handlers(THREAD_EVENT_HANDLER **handsin)
+{
+ GLOBAL_TEVENT_REGISTER *gtr;
+ int i;
+
+ gtr = get_global_tevent_register();
+ if (gtr == NULL)
+ return;
+ if (!CRYPTO_THREAD_write_lock(gtr->lock))
+ return;
+ for (i = 0; i < sk_THREAD_EVENT_HANDLER_PTR_num(gtr->skhands); i++) {
+ THREAD_EVENT_HANDLER **hands
+ = sk_THREAD_EVENT_HANDLER_PTR_value(gtr->skhands, i);
+
+ if (hands == handsin) {
+ sk_THREAD_EVENT_HANDLER_PTR_delete(gtr->skhands, i);
+ CRYPTO_THREAD_unlock(gtr->lock);
+ return;
+ }
+ }
+ CRYPTO_THREAD_unlock(gtr->lock);
+ return;
+}
+
+static void init_thread_destructor(void *hands)
+{
+ init_thread_stop(NULL, (THREAD_EVENT_HANDLER **)hands);
+ init_thread_remove_handlers(hands);
+ OPENSSL_free(hands);
+}
+
+int ossl_init_thread(void)
+{
+ if (!CRYPTO_THREAD_init_local(&destructor_key.value,
+ init_thread_destructor))
+ return 0;
+
+ return 1;
+}
+
+void ossl_cleanup_thread(void)
+{
+ init_thread_deregister(NULL, 1);
+ CRYPTO_THREAD_cleanup_local(&destructor_key.value);
+ destructor_key.sane = -1;
+}
+
+void OPENSSL_thread_stop_ex(OSSL_LIB_CTX *ctx)
+{
+ ctx = ossl_lib_ctx_get_concrete(ctx);
+ /*
+ * It would be nice if we could figure out a way to do this on all threads
+ * that have used the OSSL_LIB_CTX when the context is freed. This is
+ * currently not possible due to the use of thread local variables.
+ */
+ ossl_ctx_thread_stop(ctx);
+}
+
+void OPENSSL_thread_stop(void)
+{
+ if (destructor_key.sane != -1) {
+ THREAD_EVENT_HANDLER **hands
+ = init_get_thread_local(&destructor_key.value, 0, 0);
+ init_thread_stop(NULL, hands);
+
+ init_thread_remove_handlers(hands);
+ OPENSSL_free(hands);
+ }
+}
+
+void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx)
+{
+ if (destructor_key.sane != -1) {
+ THREAD_EVENT_HANDLER **hands
+ = init_get_thread_local(&destructor_key.value, 0, 1);
+ init_thread_stop(ctx, hands);
+ }
+}
+
+#else
+
+static void *thread_event_ossl_ctx_new(OSSL_LIB_CTX *libctx)
+{
+ THREAD_EVENT_HANDLER **hands = NULL;
+ CRYPTO_THREAD_LOCAL *tlocal = OPENSSL_zalloc(sizeof(*tlocal));
+
+ if (tlocal == NULL)
+ return NULL;
+
+ if (!CRYPTO_THREAD_init_local(tlocal, NULL)) {
+ goto err;
+ }
+
+ hands = OPENSSL_zalloc(sizeof(*hands));
+ if (hands == NULL)
+ goto err;
+
+ if (!CRYPTO_THREAD_set_local(tlocal, hands))
+ goto err;
+
+ return tlocal;
+ err:
+ OPENSSL_free(hands);
+ OPENSSL_free(tlocal);
+ return NULL;
+}
+
+static void thread_event_ossl_ctx_free(void *tlocal)
+{
+ OPENSSL_free(tlocal);
+}
+
+static const OSSL_LIB_CTX_METHOD thread_event_ossl_ctx_method = {
+ OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
+ thread_event_ossl_ctx_new,
+ thread_event_ossl_ctx_free,
+};
+
+static void ossl_arg_thread_stop(void *arg)
+{
+ ossl_ctx_thread_stop((OSSL_LIB_CTX *)arg);
+}
+
+void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx)
+{
+ THREAD_EVENT_HANDLER **hands;
+ CRYPTO_THREAD_LOCAL *local
+ = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX,
+ &thread_event_ossl_ctx_method);
+
+ if (local == NULL)
+ return;
+ hands = init_get_thread_local(local, 0, 0);
+ init_thread_stop(ctx, hands);
+ OPENSSL_free(hands);
+}
+#endif /* FIPS_MODULE */
+
+
+static void init_thread_stop(void *arg, THREAD_EVENT_HANDLER **hands)
+{
+ THREAD_EVENT_HANDLER *curr, *prev = NULL, *tmp;
+#ifndef FIPS_MODULE
+ GLOBAL_TEVENT_REGISTER *gtr;
+#endif
+
+ /* Can't do much about this */
+ if (hands == NULL)
+ return;
+
+#ifndef FIPS_MODULE
+ gtr = get_global_tevent_register();
+ if (gtr == NULL)
+ return;
+
+ if (!CRYPTO_THREAD_write_lock(gtr->lock))
+ return;
+#endif
+
+ curr = *hands;
+ while (curr != NULL) {
+ if (arg != NULL && curr->arg != arg) {
+ prev = curr;
+ curr = curr->next;
+ continue;
+ }
+ curr->handfn(curr->arg);
+ if (prev == NULL)
+ *hands = curr->next;
+ else
+ prev->next = curr->next;
+
+ tmp = curr;
+ curr = curr->next;
+
+ OPENSSL_free(tmp);
+ }
+#ifndef FIPS_MODULE
+ CRYPTO_THREAD_unlock(gtr->lock);
+#endif
+}
+
+int ossl_init_thread_start(const void *index, void *arg,
+ OSSL_thread_stop_handler_fn handfn)
+{
+ THREAD_EVENT_HANDLER **hands;
+ THREAD_EVENT_HANDLER *hand;
+#ifdef FIPS_MODULE
+ OSSL_LIB_CTX *ctx = arg;
+
+ /*
+ * In FIPS mode the list of THREAD_EVENT_HANDLERs is unique per combination
+ * of OSSL_LIB_CTX and thread. This is because in FIPS mode each
+ * OSSL_LIB_CTX gets informed about thread stop events individually.
+ */
+ CRYPTO_THREAD_LOCAL *local
+ = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX,
+ &thread_event_ossl_ctx_method);
+#else
+ /*
+ * Outside of FIPS mode the list of THREAD_EVENT_HANDLERs is unique per
+ * thread, but may hold multiple OSSL_LIB_CTXs. We only get told about
+ * thread stop events globally, so we have to ensure all affected
+ * OSSL_LIB_CTXs are informed.
+ */
+ CRYPTO_THREAD_LOCAL *local = &destructor_key.value;
+#endif
+
+ hands = init_get_thread_local(local, 1, 0);
+ if (hands == NULL)
+ return 0;
+
+#ifdef FIPS_MODULE
+ if (*hands == NULL) {
+ /*
+ * We've not yet registered any handlers for this thread. We need to get
+ * libcrypto to tell us about later thread stop events. c_thread_start
+ * is a callback to libcrypto defined in fipsprov.c
+ */
+ if (!c_thread_start(FIPS_get_core_handle(ctx), ossl_arg_thread_stop,
+ ctx))
+ return 0;
+ }
+#endif
+
+ hand = OPENSSL_malloc(sizeof(*hand));
+ if (hand == NULL)
+ return 0;
+
+ hand->handfn = handfn;
+ hand->arg = arg;
+#ifndef FIPS_MODULE
+ hand->index = index;
+#endif
+ hand->next = *hands;
+ *hands = hand;
+
+ return 1;
+}
+
+#ifndef FIPS_MODULE
+static int init_thread_deregister(void *index, int all)
+{
+ GLOBAL_TEVENT_REGISTER *gtr;
+ int i;
+
+ gtr = get_global_tevent_register();
+ if (gtr == NULL)
+ return 0;
+ if (!all) {
+ if (!CRYPTO_THREAD_write_lock(gtr->lock))
+ return 0;
+ } else {
+ glob_tevent_reg = NULL;
+ }
+ for (i = 0; i < sk_THREAD_EVENT_HANDLER_PTR_num(gtr->skhands); i++) {
+ THREAD_EVENT_HANDLER **hands
+ = sk_THREAD_EVENT_HANDLER_PTR_value(gtr->skhands, i);
+ THREAD_EVENT_HANDLER *curr = NULL, *prev = NULL, *tmp;
+
+ if (hands == NULL) {
+ if (!all)
+ CRYPTO_THREAD_unlock(gtr->lock);
+ return 0;
+ }
+ curr = *hands;
+ while (curr != NULL) {
+ if (all || curr->index == index) {
+ if (prev != NULL)
+ prev->next = curr->next;
+ else
+ *hands = curr->next;
+ tmp = curr;
+ curr = curr->next;
+ OPENSSL_free(tmp);
+ continue;
+ }
+ prev = curr;
+ curr = curr->next;
+ }
+ if (all)
+ OPENSSL_free(hands);
+ }
+ if (all) {
+ CRYPTO_THREAD_lock_free(gtr->lock);
+ sk_THREAD_EVENT_HANDLER_PTR_free(gtr->skhands);
+ OPENSSL_free(gtr);
+ } else {
+ CRYPTO_THREAD_unlock(gtr->lock);
+ }
+ return 1;
+}
+
+int ossl_init_thread_deregister(void *index)
+{
+ return init_thread_deregister(index, 0);
+}
+#endif
diff --git a/crypto/kdf/build.info b/crypto/kdf/build.info
index c166399d0ce7..7707c00988bb 100644
--- a/crypto/kdf/build.info
+++ b/crypto/kdf/build.info
@@ -1,3 +1,2 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- tls1_prf.c kdf_err.c hkdf.c scrypt.c
+SOURCE[../../libcrypto]=kdf_err.c
diff --git a/crypto/kdf/hkdf.c b/crypto/kdf/hkdf.c
deleted file mode 100644
index 25bf4b729f64..000000000000
--- a/crypto/kdf/hkdf.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <openssl/hmac.h>
-#include <openssl/kdf.h>
-#include <openssl/evp.h>
-#include "internal/cryptlib.h"
-#include "crypto/evp.h"
-
-#define HKDF_MAXBUF 1024
-
-static unsigned char *HKDF(const EVP_MD *evp_md,
- const unsigned char *salt, size_t salt_len,
- const unsigned char *key, size_t key_len,
- const unsigned char *info, size_t info_len,
- unsigned char *okm, size_t okm_len);
-
-static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
- const unsigned char *salt, size_t salt_len,
- const unsigned char *key, size_t key_len,
- unsigned char *prk, size_t *prk_len);
-
-static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
- const unsigned char *prk, size_t prk_len,
- const unsigned char *info, size_t info_len,
- unsigned char *okm, size_t okm_len);
-
-typedef struct {
- int mode;
- const EVP_MD *md;
- unsigned char *salt;
- size_t salt_len;
- unsigned char *key;
- size_t key_len;
- unsigned char info[HKDF_MAXBUF];
- size_t info_len;
-} HKDF_PKEY_CTX;
-
-static int pkey_hkdf_init(EVP_PKEY_CTX *ctx)
-{
- HKDF_PKEY_CTX *kctx;
-
- if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL) {
- KDFerr(KDF_F_PKEY_HKDF_INIT, ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- ctx->data = kctx;
-
- return 1;
-}
-
-static void pkey_hkdf_cleanup(EVP_PKEY_CTX *ctx)
-{
- HKDF_PKEY_CTX *kctx = ctx->data;
- OPENSSL_clear_free(kctx->salt, kctx->salt_len);
- OPENSSL_clear_free(kctx->key, kctx->key_len);
- OPENSSL_cleanse(kctx->info, kctx->info_len);
- OPENSSL_free(kctx);
-}
-
-static int pkey_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
-{
- HKDF_PKEY_CTX *kctx = ctx->data;
-
- switch (type) {
- case EVP_PKEY_CTRL_HKDF_MD:
- if (p2 == NULL)
- return 0;
-
- kctx->md = p2;
- return 1;
-
- case EVP_PKEY_CTRL_HKDF_MODE:
- kctx->mode = p1;
- return 1;
-
- case EVP_PKEY_CTRL_HKDF_SALT:
- if (p1 == 0 || p2 == NULL)
- return 1;
-
- if (p1 < 0)
- return 0;
-
- if (kctx->salt != NULL)
- OPENSSL_clear_free(kctx->salt, kctx->salt_len);
-
- kctx->salt = OPENSSL_memdup(p2, p1);
- if (kctx->salt == NULL)
- return 0;
-
- kctx->salt_len = p1;
- return 1;
-
- case EVP_PKEY_CTRL_HKDF_KEY:
- if (p1 < 0)
- return 0;
-
- if (kctx->key != NULL)
- OPENSSL_clear_free(kctx->key, kctx->key_len);
-
- kctx->key = OPENSSL_memdup(p2, p1);
- if (kctx->key == NULL)
- return 0;
-
- kctx->key_len = p1;
- return 1;
-
- case EVP_PKEY_CTRL_HKDF_INFO:
- if (p1 == 0 || p2 == NULL)
- return 1;
-
- if (p1 < 0 || p1 > (int)(HKDF_MAXBUF - kctx->info_len))
- return 0;
-
- memcpy(kctx->info + kctx->info_len, p2, p1);
- kctx->info_len += p1;
- return 1;
-
- default:
- return -2;
-
- }
-}
-
-static int pkey_hkdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
- const char *value)
-{
- if (strcmp(type, "mode") == 0) {
- int mode;
-
- if (strcmp(value, "EXTRACT_AND_EXPAND") == 0)
- mode = EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND;
- else if (strcmp(value, "EXTRACT_ONLY") == 0)
- mode = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY;
- else if (strcmp(value, "EXPAND_ONLY") == 0)
- mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY;
- else
- return 0;
-
- return EVP_PKEY_CTX_hkdf_mode(ctx, mode);
- }
-
- if (strcmp(type, "md") == 0)
- return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_DERIVE,
- EVP_PKEY_CTRL_HKDF_MD, value);
-
- if (strcmp(type, "salt") == 0)
- return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value);
-
- if (strcmp(type, "hexsalt") == 0)
- return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value);
-
- if (strcmp(type, "key") == 0)
- return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
-
- if (strcmp(type, "hexkey") == 0)
- return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
-
- if (strcmp(type, "info") == 0)
- return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value);
-
- if (strcmp(type, "hexinfo") == 0)
- return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value);
-
- KDFerr(KDF_F_PKEY_HKDF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
- return -2;
-}
-
-static int pkey_hkdf_derive_init(EVP_PKEY_CTX *ctx)
-{
- HKDF_PKEY_CTX *kctx = ctx->data;
-
- OPENSSL_clear_free(kctx->key, kctx->key_len);
- OPENSSL_clear_free(kctx->salt, kctx->salt_len);
- OPENSSL_cleanse(kctx->info, kctx->info_len);
- memset(kctx, 0, sizeof(*kctx));
-
- return 1;
-}
-
-static int pkey_hkdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
- size_t *keylen)
-{
- HKDF_PKEY_CTX *kctx = ctx->data;
-
- if (kctx->md == NULL) {
- KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
- return 0;
- }
- if (kctx->key == NULL) {
- KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_KEY);
- return 0;
- }
-
- switch (kctx->mode) {
- case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND:
- return HKDF(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
- kctx->key_len, kctx->info, kctx->info_len, key,
- *keylen) != NULL;
-
- case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY:
- if (key == NULL) {
- *keylen = EVP_MD_size(kctx->md);
- return 1;
- }
- return HKDF_Extract(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
- kctx->key_len, key, keylen) != NULL;
-
- case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY:
- return HKDF_Expand(kctx->md, kctx->key, kctx->key_len, kctx->info,
- kctx->info_len, key, *keylen) != NULL;
-
- default:
- return 0;
- }
-}
-
-const EVP_PKEY_METHOD hkdf_pkey_meth = {
- EVP_PKEY_HKDF,
- 0,
- pkey_hkdf_init,
- 0,
- pkey_hkdf_cleanup,
-
- 0, 0,
- 0, 0,
-
- 0,
- 0,
-
- 0,
- 0,
-
- 0, 0,
-
- 0, 0, 0, 0,
-
- 0, 0,
-
- 0, 0,
-
- pkey_hkdf_derive_init,
- pkey_hkdf_derive,
- pkey_hkdf_ctrl,
- pkey_hkdf_ctrl_str
-};
-
-static unsigned char *HKDF(const EVP_MD *evp_md,
- const unsigned char *salt, size_t salt_len,
- const unsigned char *key, size_t key_len,
- const unsigned char *info, size_t info_len,
- unsigned char *okm, size_t okm_len)
-{
- unsigned char prk[EVP_MAX_MD_SIZE];
- unsigned char *ret;
- size_t prk_len;
-
- if (!HKDF_Extract(evp_md, salt, salt_len, key, key_len, prk, &prk_len))
- return NULL;
-
- ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len);
- OPENSSL_cleanse(prk, sizeof(prk));
-
- return ret;
-}
-
-static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
- const unsigned char *salt, size_t salt_len,
- const unsigned char *key, size_t key_len,
- unsigned char *prk, size_t *prk_len)
-{
- unsigned int tmp_len;
-
- if (!HMAC(evp_md, salt, salt_len, key, key_len, prk, &tmp_len))
- return NULL;
-
- *prk_len = tmp_len;
- return prk;
-}
-
-static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
- const unsigned char *prk, size_t prk_len,
- const unsigned char *info, size_t info_len,
- unsigned char *okm, size_t okm_len)
-{
- HMAC_CTX *hmac;
- unsigned char *ret = NULL;
-
- unsigned int i;
-
- unsigned char prev[EVP_MAX_MD_SIZE];
-
- size_t done_len = 0, dig_len = EVP_MD_size(evp_md);
-
- size_t n = okm_len / dig_len;
- if (okm_len % dig_len)
- n++;
-
- if (n > 255 || okm == NULL)
- return NULL;
-
- if ((hmac = HMAC_CTX_new()) == NULL)
- return NULL;
-
- if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
- goto err;
-
- for (i = 1; i <= n; i++) {
- size_t copy_len;
- const unsigned char ctr = i;
-
- if (i > 1) {
- if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL))
- goto err;
-
- if (!HMAC_Update(hmac, prev, dig_len))
- goto err;
- }
-
- if (!HMAC_Update(hmac, info, info_len))
- goto err;
-
- if (!HMAC_Update(hmac, &ctr, 1))
- goto err;
-
- if (!HMAC_Final(hmac, prev, NULL))
- goto err;
-
- copy_len = (done_len + dig_len > okm_len) ?
- okm_len - done_len :
- dig_len;
-
- memcpy(okm + done_len, prev, copy_len);
-
- done_len += copy_len;
- }
- ret = okm;
-
- err:
- OPENSSL_cleanse(prev, sizeof(prev));
- HMAC_CTX_free(hmac);
- return ret;
-}
diff --git a/crypto/kdf/kdf_err.c b/crypto/kdf/kdf_err.c
index 1627c0a394b4..5b794285e47a 100644
--- a/crypto/kdf/kdf_err.c
+++ b/crypto/kdf/kdf_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,57 +11,9 @@
#include <openssl/err.h>
#include <openssl/kdferr.h>
-#ifndef OPENSSL_NO_ERR
-
-static const ERR_STRING_DATA KDF_str_functs[] = {
- {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_CTRL_STR, 0), "pkey_hkdf_ctrl_str"},
- {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_DERIVE, 0), "pkey_hkdf_derive"},
- {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_INIT, 0), "pkey_hkdf_init"},
- {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_SCRYPT_CTRL_STR, 0),
- "pkey_scrypt_ctrl_str"},
- {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_SCRYPT_CTRL_UINT64, 0),
- "pkey_scrypt_ctrl_uint64"},
- {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_SCRYPT_DERIVE, 0), "pkey_scrypt_derive"},
- {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_SCRYPT_INIT, 0), "pkey_scrypt_init"},
- {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_SCRYPT_SET_MEMBUF, 0),
- "pkey_scrypt_set_membuf"},
- {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_TLS1_PRF_CTRL_STR, 0),
- "pkey_tls1_prf_ctrl_str"},
- {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_TLS1_PRF_DERIVE, 0),
- "pkey_tls1_prf_derive"},
- {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_TLS1_PRF_INIT, 0), "pkey_tls1_prf_init"},
- {ERR_PACK(ERR_LIB_KDF, KDF_F_TLS1_PRF_ALG, 0), "tls1_prf_alg"},
- {0, NULL}
-};
-
-static const ERR_STRING_DATA KDF_str_reasons[] = {
- {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_INVALID_DIGEST), "invalid digest"},
- {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_ITERATION_COUNT),
- "missing iteration count"},
- {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_KEY), "missing key"},
- {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_MESSAGE_DIGEST),
- "missing message digest"},
- {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_PARAMETER), "missing parameter"},
- {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_PASS), "missing pass"},
- {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_SALT), "missing salt"},
- {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_SECRET), "missing secret"},
- {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_SEED), "missing seed"},
- {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_UNKNOWN_PARAMETER_TYPE),
- "unknown parameter type"},
- {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_VALUE_ERROR), "value error"},
- {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_VALUE_MISSING), "value missing"},
- {0, NULL}
-};
-
-#endif
-
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int ERR_load_KDF_strings(void)
{
-#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(KDF_str_functs[0].error) == NULL) {
- ERR_load_strings_const(KDF_str_functs);
- ERR_load_strings_const(KDF_str_reasons);
- }
-#endif
return 1;
}
+#endif
diff --git a/crypto/kdf/scrypt.c b/crypto/kdf/scrypt.c
deleted file mode 100644
index 68606ac00aed..000000000000
--- a/crypto/kdf/scrypt.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <openssl/hmac.h>
-#include <openssl/kdf.h>
-#include <openssl/evp.h>
-#include "internal/cryptlib.h"
-#include "crypto/evp.h"
-
-#ifndef OPENSSL_NO_SCRYPT
-
-static int atou64(const char *nptr, uint64_t *result);
-
-typedef struct {
- unsigned char *pass;
- size_t pass_len;
- unsigned char *salt;
- size_t salt_len;
- uint64_t N, r, p;
- uint64_t maxmem_bytes;
-} SCRYPT_PKEY_CTX;
-
-/* Custom uint64_t parser since we do not have strtoull */
-static int atou64(const char *nptr, uint64_t *result)
-{
- uint64_t value = 0;
-
- while (*nptr) {
- unsigned int digit;
- uint64_t new_value;
-
- if ((*nptr < '0') || (*nptr > '9')) {
- return 0;
- }
- digit = (unsigned int)(*nptr - '0');
- new_value = (value * 10) + digit;
- if ((new_value < digit) || ((new_value - digit) / 10 != value)) {
- /* Overflow */
- return 0;
- }
- value = new_value;
- nptr++;
- }
- *result = value;
- return 1;
-}
-
-static int pkey_scrypt_init(EVP_PKEY_CTX *ctx)
-{
- SCRYPT_PKEY_CTX *kctx;
-
- kctx = OPENSSL_zalloc(sizeof(*kctx));
- if (kctx == NULL) {
- KDFerr(KDF_F_PKEY_SCRYPT_INIT, ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- /* Default values are the most conservative recommendation given in the
- * original paper of C. Percival. Derivation uses roughly 1 GiB of memory
- * for this parameter choice (approx. 128 * r * (N + p) bytes).
- */
- kctx->N = 1 << 20;
- kctx->r = 8;
- kctx->p = 1;
- kctx->maxmem_bytes = 1025 * 1024 * 1024;
-
- ctx->data = kctx;
-
- return 1;
-}
-
-static void pkey_scrypt_cleanup(EVP_PKEY_CTX *ctx)
-{
- SCRYPT_PKEY_CTX *kctx = ctx->data;
-
- OPENSSL_clear_free(kctx->salt, kctx->salt_len);
- OPENSSL_clear_free(kctx->pass, kctx->pass_len);
- OPENSSL_free(kctx);
-}
-
-static int pkey_scrypt_set_membuf(unsigned char **buffer, size_t *buflen,
- const unsigned char *new_buffer,
- const int new_buflen)
-{
- if (new_buffer == NULL)
- return 1;
-
- if (new_buflen < 0)
- return 0;
-
- if (*buffer != NULL)
- OPENSSL_clear_free(*buffer, *buflen);
-
- if (new_buflen > 0) {
- *buffer = OPENSSL_memdup(new_buffer, new_buflen);
- } else {
- *buffer = OPENSSL_malloc(1);
- }
- if (*buffer == NULL) {
- KDFerr(KDF_F_PKEY_SCRYPT_SET_MEMBUF, ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- *buflen = new_buflen;
- return 1;
-}
-
-static int is_power_of_two(uint64_t value)
-{
- return (value != 0) && ((value & (value - 1)) == 0);
-}
-
-static int pkey_scrypt_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
-{
- SCRYPT_PKEY_CTX *kctx = ctx->data;
- uint64_t u64_value;
-
- switch (type) {
- case EVP_PKEY_CTRL_PASS:
- return pkey_scrypt_set_membuf(&kctx->pass, &kctx->pass_len, p2, p1);
-
- case EVP_PKEY_CTRL_SCRYPT_SALT:
- return pkey_scrypt_set_membuf(&kctx->salt, &kctx->salt_len, p2, p1);
-
- case EVP_PKEY_CTRL_SCRYPT_N:
- u64_value = *((uint64_t *)p2);
- if ((u64_value <= 1) || !is_power_of_two(u64_value))
- return 0;
- kctx->N = u64_value;
- return 1;
-
- case EVP_PKEY_CTRL_SCRYPT_R:
- u64_value = *((uint64_t *)p2);
- if (u64_value < 1)
- return 0;
- kctx->r = u64_value;
- return 1;
-
- case EVP_PKEY_CTRL_SCRYPT_P:
- u64_value = *((uint64_t *)p2);
- if (u64_value < 1)
- return 0;
- kctx->p = u64_value;
- return 1;
-
- case EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES:
- u64_value = *((uint64_t *)p2);
- if (u64_value < 1)
- return 0;
- kctx->maxmem_bytes = u64_value;
- return 1;
-
- default:
- return -2;
-
- }
-}
-
-static int pkey_scrypt_ctrl_uint64(EVP_PKEY_CTX *ctx, int type,
- const char *value)
-{
- uint64_t int_value;
-
- if (!atou64(value, &int_value)) {
- KDFerr(KDF_F_PKEY_SCRYPT_CTRL_UINT64, KDF_R_VALUE_ERROR);
- return 0;
- }
- return pkey_scrypt_ctrl(ctx, type, 0, &int_value);
-}
-
-static int pkey_scrypt_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
- const char *value)
-{
- if (value == NULL) {
- KDFerr(KDF_F_PKEY_SCRYPT_CTRL_STR, KDF_R_VALUE_MISSING);
- return 0;
- }
-
- if (strcmp(type, "pass") == 0)
- return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_PASS, value);
-
- if (strcmp(type, "hexpass") == 0)
- return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_PASS, value);
-
- if (strcmp(type, "salt") == 0)
- return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SCRYPT_SALT, value);
-
- if (strcmp(type, "hexsalt") == 0)
- return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SCRYPT_SALT, value);
-
- if (strcmp(type, "N") == 0)
- return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_N, value);
-
- if (strcmp(type, "r") == 0)
- return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_R, value);
-
- if (strcmp(type, "p") == 0)
- return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_P, value);
-
- if (strcmp(type, "maxmem_bytes") == 0)
- return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES,
- value);
-
- KDFerr(KDF_F_PKEY_SCRYPT_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
- return -2;
-}
-
-static int pkey_scrypt_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
- size_t *keylen)
-{
- SCRYPT_PKEY_CTX *kctx = ctx->data;
-
- if (kctx->pass == NULL) {
- KDFerr(KDF_F_PKEY_SCRYPT_DERIVE, KDF_R_MISSING_PASS);
- return 0;
- }
-
- if (kctx->salt == NULL) {
- KDFerr(KDF_F_PKEY_SCRYPT_DERIVE, KDF_R_MISSING_SALT);
- return 0;
- }
-
- return EVP_PBE_scrypt((char *)kctx->pass, kctx->pass_len, kctx->salt,
- kctx->salt_len, kctx->N, kctx->r, kctx->p,
- kctx->maxmem_bytes, key, *keylen);
-}
-
-const EVP_PKEY_METHOD scrypt_pkey_meth = {
- EVP_PKEY_SCRYPT,
- 0,
- pkey_scrypt_init,
- 0,
- pkey_scrypt_cleanup,
-
- 0, 0,
- 0, 0,
-
- 0,
- 0,
-
- 0,
- 0,
-
- 0, 0,
-
- 0, 0, 0, 0,
-
- 0, 0,
-
- 0, 0,
-
- 0,
- pkey_scrypt_derive,
- pkey_scrypt_ctrl,
- pkey_scrypt_ctrl_str
-};
-
-#endif
diff --git a/crypto/kdf/tls1_prf.c b/crypto/kdf/tls1_prf.c
deleted file mode 100644
index e9ca8e12780b..000000000000
--- a/crypto/kdf/tls1_prf.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/kdf.h>
-#include <openssl/evp.h>
-#include "crypto/evp.h"
-
-static int tls1_prf_alg(const EVP_MD *md,
- const unsigned char *sec, size_t slen,
- const unsigned char *seed, size_t seed_len,
- unsigned char *out, size_t olen);
-
-#define TLS1_PRF_MAXBUF 1024
-
-/* TLS KDF pkey context structure */
-
-typedef struct {
- /* Digest to use for PRF */
- const EVP_MD *md;
- /* Secret value to use for PRF */
- unsigned char *sec;
- size_t seclen;
- /* Buffer of concatenated seed data */
- unsigned char seed[TLS1_PRF_MAXBUF];
- size_t seedlen;
-} TLS1_PRF_PKEY_CTX;
-
-static int pkey_tls1_prf_init(EVP_PKEY_CTX *ctx)
-{
- TLS1_PRF_PKEY_CTX *kctx;
-
- if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL) {
- KDFerr(KDF_F_PKEY_TLS1_PRF_INIT, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- ctx->data = kctx;
-
- return 1;
-}
-
-static void pkey_tls1_prf_cleanup(EVP_PKEY_CTX *ctx)
-{
- TLS1_PRF_PKEY_CTX *kctx = ctx->data;
- OPENSSL_clear_free(kctx->sec, kctx->seclen);
- OPENSSL_cleanse(kctx->seed, kctx->seedlen);
- OPENSSL_free(kctx);
-}
-
-static int pkey_tls1_prf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
-{
- TLS1_PRF_PKEY_CTX *kctx = ctx->data;
- switch (type) {
- case EVP_PKEY_CTRL_TLS_MD:
- kctx->md = p2;
- return 1;
-
- case EVP_PKEY_CTRL_TLS_SECRET:
- if (p1 < 0)
- return 0;
- if (kctx->sec != NULL)
- OPENSSL_clear_free(kctx->sec, kctx->seclen);
- OPENSSL_cleanse(kctx->seed, kctx->seedlen);
- kctx->seedlen = 0;
- kctx->sec = OPENSSL_memdup(p2, p1);
- if (kctx->sec == NULL)
- return 0;
- kctx->seclen = p1;
- return 1;
-
- case EVP_PKEY_CTRL_TLS_SEED:
- if (p1 == 0 || p2 == NULL)
- return 1;
- if (p1 < 0 || p1 > (int)(TLS1_PRF_MAXBUF - kctx->seedlen))
- return 0;
- memcpy(kctx->seed + kctx->seedlen, p2, p1);
- kctx->seedlen += p1;
- return 1;
-
- default:
- return -2;
-
- }
-}
-
-static int pkey_tls1_prf_ctrl_str(EVP_PKEY_CTX *ctx,
- const char *type, const char *value)
-{
- if (value == NULL) {
- KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_VALUE_MISSING);
- return 0;
- }
- if (strcmp(type, "md") == 0) {
- TLS1_PRF_PKEY_CTX *kctx = ctx->data;
-
- const EVP_MD *md = EVP_get_digestbyname(value);
- if (md == NULL) {
- KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_INVALID_DIGEST);
- return 0;
- }
- kctx->md = md;
- return 1;
- }
- if (strcmp(type, "secret") == 0)
- return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value);
- if (strcmp(type, "hexsecret") == 0)
- return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value);
- if (strcmp(type, "seed") == 0)
- return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value);
- if (strcmp(type, "hexseed") == 0)
- return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value);
-
- KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
- return -2;
-}
-
-static int pkey_tls1_prf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
- size_t *keylen)
-{
- TLS1_PRF_PKEY_CTX *kctx = ctx->data;
- if (kctx->md == NULL) {
- KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
- return 0;
- }
- if (kctx->sec == NULL) {
- KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_SECRET);
- return 0;
- }
- if (kctx->seedlen == 0) {
- KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_SEED);
- return 0;
- }
- return tls1_prf_alg(kctx->md, kctx->sec, kctx->seclen,
- kctx->seed, kctx->seedlen,
- key, *keylen);
-}
-
-const EVP_PKEY_METHOD tls1_prf_pkey_meth = {
- EVP_PKEY_TLS1_PRF,
- 0,
- pkey_tls1_prf_init,
- 0,
- pkey_tls1_prf_cleanup,
-
- 0, 0,
- 0, 0,
-
- 0,
- 0,
-
- 0,
- 0,
-
- 0, 0,
-
- 0, 0, 0, 0,
-
- 0, 0,
-
- 0, 0,
-
- 0,
- pkey_tls1_prf_derive,
- pkey_tls1_prf_ctrl,
- pkey_tls1_prf_ctrl_str
-};
-
-static int tls1_prf_P_hash(const EVP_MD *md,
- const unsigned char *sec, size_t sec_len,
- const unsigned char *seed, size_t seed_len,
- unsigned char *out, size_t olen)
-{
- int chunk;
- EVP_MD_CTX *ctx = NULL, *ctx_tmp = NULL, *ctx_init = NULL;
- EVP_PKEY *mac_key = NULL;
- unsigned char A1[EVP_MAX_MD_SIZE];
- size_t A1_len;
- int ret = 0;
-
- chunk = EVP_MD_size(md);
- if (!ossl_assert(chunk > 0))
- goto err;
-
- ctx = EVP_MD_CTX_new();
- ctx_tmp = EVP_MD_CTX_new();
- ctx_init = EVP_MD_CTX_new();
- if (ctx == NULL || ctx_tmp == NULL || ctx_init == NULL)
- goto err;
- EVP_MD_CTX_set_flags(ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
- mac_key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, sec, sec_len);
- if (mac_key == NULL)
- goto err;
- if (!EVP_DigestSignInit(ctx_init, NULL, md, NULL, mac_key))
- goto err;
- if (!EVP_MD_CTX_copy_ex(ctx, ctx_init))
- goto err;
- if (seed != NULL && !EVP_DigestSignUpdate(ctx, seed, seed_len))
- goto err;
- if (!EVP_DigestSignFinal(ctx, A1, &A1_len))
- goto err;
-
- for (;;) {
- /* Reinit mac contexts */
- if (!EVP_MD_CTX_copy_ex(ctx, ctx_init))
- goto err;
- if (!EVP_DigestSignUpdate(ctx, A1, A1_len))
- goto err;
- if (olen > (size_t)chunk && !EVP_MD_CTX_copy_ex(ctx_tmp, ctx))
- goto err;
- if (seed && !EVP_DigestSignUpdate(ctx, seed, seed_len))
- goto err;
-
- if (olen > (size_t)chunk) {
- size_t mac_len;
- if (!EVP_DigestSignFinal(ctx, out, &mac_len))
- goto err;
- out += mac_len;
- olen -= mac_len;
- /* calc the next A1 value */
- if (!EVP_DigestSignFinal(ctx_tmp, A1, &A1_len))
- goto err;
- } else { /* last one */
-
- if (!EVP_DigestSignFinal(ctx, A1, &A1_len))
- goto err;
- memcpy(out, A1, olen);
- break;
- }
- }
- ret = 1;
- err:
- EVP_PKEY_free(mac_key);
- EVP_MD_CTX_free(ctx);
- EVP_MD_CTX_free(ctx_tmp);
- EVP_MD_CTX_free(ctx_init);
- OPENSSL_cleanse(A1, sizeof(A1));
- return ret;
-}
-
-static int tls1_prf_alg(const EVP_MD *md,
- const unsigned char *sec, size_t slen,
- const unsigned char *seed, size_t seed_len,
- unsigned char *out, size_t olen)
-{
-
- if (EVP_MD_type(md) == NID_md5_sha1) {
- size_t i;
- unsigned char *tmp;
- if (!tls1_prf_P_hash(EVP_md5(), sec, slen/2 + (slen & 1),
- seed, seed_len, out, olen))
- return 0;
-
- if ((tmp = OPENSSL_malloc(olen)) == NULL) {
- KDFerr(KDF_F_TLS1_PRF_ALG, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- if (!tls1_prf_P_hash(EVP_sha1(), sec + slen/2, slen/2 + (slen & 1),
- seed, seed_len, tmp, olen)) {
- OPENSSL_clear_free(tmp, olen);
- return 0;
- }
- for (i = 0; i < olen; i++)
- out[i] ^= tmp[i];
- OPENSSL_clear_free(tmp, olen);
- return 1;
- }
- if (!tls1_prf_P_hash(md, sec, slen, seed, seed_len, out, olen))
- return 0;
-
- return 1;
-}
diff --git a/crypto/lhash/build.info b/crypto/lhash/build.info
index 30797f2caf95..b3176b8358d4 100644
--- a/crypto/lhash/build.info
+++ b/crypto/lhash/build.info
@@ -1,3 +1,5 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
lhash.c lh_stats.c
+SOURCE[../../providers/libfips.a]=\
+ lhash.c
diff --git a/crypto/lhash/lh_stats.c b/crypto/lhash/lh_stats.c
index 45f1b105554f..ba4d4ea89708 100644
--- a/crypto/lhash/lh_stats.c
+++ b/crypto/lhash/lh_stats.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -64,19 +64,19 @@ void OPENSSL_LH_stats_bio(const OPENSSL_LHASH *lh, BIO *out)
BIO_printf(out, "num_items = %lu\n", lh->num_items);
BIO_printf(out, "num_nodes = %u\n", lh->num_nodes);
BIO_printf(out, "num_alloc_nodes = %u\n", lh->num_alloc_nodes);
- BIO_printf(out, "num_expands = %lu\n", lh->num_expands);
- BIO_printf(out, "num_expand_reallocs = %lu\n", lh->num_expand_reallocs);
- BIO_printf(out, "num_contracts = %lu\n", lh->num_contracts);
- BIO_printf(out, "num_contract_reallocs = %lu\n", lh->num_contract_reallocs);
- BIO_printf(out, "num_hash_calls = %lu\n", lh->num_hash_calls);
- BIO_printf(out, "num_comp_calls = %lu\n", lh->num_comp_calls);
- BIO_printf(out, "num_insert = %lu\n", lh->num_insert);
- BIO_printf(out, "num_replace = %lu\n", lh->num_replace);
- BIO_printf(out, "num_delete = %lu\n", lh->num_delete);
- BIO_printf(out, "num_no_delete = %lu\n", lh->num_no_delete);
- BIO_printf(out, "num_retrieve = %lu\n", lh->num_retrieve);
- BIO_printf(out, "num_retrieve_miss = %lu\n", lh->num_retrieve_miss);
- BIO_printf(out, "num_hash_comps = %lu\n", lh->num_hash_comps);
+ BIO_printf(out, "num_expands = 0\n");
+ BIO_printf(out, "num_expand_reallocs = 0\n");
+ BIO_printf(out, "num_contracts = 0\n");
+ BIO_printf(out, "num_contract_reallocs = 0\n");
+ BIO_printf(out, "num_hash_calls = 0\n");
+ BIO_printf(out, "num_comp_calls = 0\n");
+ BIO_printf(out, "num_insert = 0\n");
+ BIO_printf(out, "num_replace = 0\n");
+ BIO_printf(out, "num_delete = 0\n");
+ BIO_printf(out, "num_no_delete = 0\n");
+ BIO_printf(out, "num_retrieve = 0\n");
+ BIO_printf(out, "num_retrieve_miss = 0\n");
+ BIO_printf(out, "num_hash_comps = 0\n");
}
void OPENSSL_LH_node_stats_bio(const OPENSSL_LHASH *lh, BIO *out)
diff --git a/crypto/lhash/lhash.c b/crypto/lhash/lhash.c
index 603224975ca1..1cd988f01fc7 100644
--- a/crypto/lhash/lhash.c
+++ b/crypto/lhash/lhash.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -52,7 +52,7 @@ OPENSSL_LHASH *OPENSSL_LH_new(OPENSSL_LH_HASHFUNC h, OPENSSL_LH_COMPFUNC c)
/*
* Do not set the error code, because the ERR code uses LHASH
* and we want to avoid possible endless error loop.
- * CRYPTOerr(CRYPTO_F_OPENSSL_LH_NEW, ERR_R_MALLOC_FAILURE);
+ * ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
*/
return NULL;
}
@@ -75,6 +75,16 @@ err:
void OPENSSL_LH_free(OPENSSL_LHASH *lh)
{
+ if (lh == NULL)
+ return;
+
+ OPENSSL_LH_flush(lh);
+ OPENSSL_free(lh->b);
+ OPENSSL_free(lh);
+}
+
+void OPENSSL_LH_flush(OPENSSL_LHASH *lh)
+{
unsigned int i;
OPENSSL_LH_NODE *n, *nn;
@@ -88,9 +98,10 @@ void OPENSSL_LH_free(OPENSSL_LHASH *lh)
OPENSSL_free(n);
n = nn;
}
+ lh->b[i] = NULL;
}
- OPENSSL_free(lh->b);
- OPENSSL_free(lh);
+
+ lh->num_items = 0;
}
void *OPENSSL_LH_insert(OPENSSL_LHASH *lh, void *data)
@@ -115,12 +126,10 @@ void *OPENSSL_LH_insert(OPENSSL_LHASH *lh, void *data)
nn->hash = hash;
*rn = nn;
ret = NULL;
- lh->num_insert++;
lh->num_items++;
} else { /* replace same key */
ret = (*rn)->data;
(*rn)->data = data;
- lh->num_replace++;
}
return ret;
}
@@ -135,14 +144,12 @@ void *OPENSSL_LH_delete(OPENSSL_LHASH *lh, const void *data)
rn = getrn(lh, data, &hash);
if (*rn == NULL) {
- lh->num_no_delete++;
return NULL;
} else {
nn = *rn;
*rn = nn->next;
ret = nn->data;
OPENSSL_free(nn);
- lh->num_delete++;
}
lh->num_items--;
@@ -157,21 +164,13 @@ void *OPENSSL_LH_retrieve(OPENSSL_LHASH *lh, const void *data)
{
unsigned long hash;
OPENSSL_LH_NODE **rn;
- void *ret;
- tsan_store((TSAN_QUALIFIER int *)&lh->error, 0);
+ if (lh->error != 0)
+ lh->error = 0;
rn = getrn(lh, data, &hash);
- if (*rn == NULL) {
- tsan_counter(&lh->num_retrieve_miss);
- return NULL;
- } else {
- ret = (*rn)->data;
- tsan_counter(&lh->num_retrieve);
- }
-
- return ret;
+ return *rn == NULL ? NULL : (*rn)->data;
}
static void doall_util_fn(OPENSSL_LHASH *lh, int use_arg,
@@ -231,14 +230,12 @@ static int expand(OPENSSL_LHASH *lh)
memset(n + nni, 0, sizeof(*n) * (j - nni));
lh->pmax = nni;
lh->num_alloc_nodes = j;
- lh->num_expand_reallocs++;
lh->p = 0;
} else {
lh->p++;
}
lh->num_nodes++;
- lh->num_expands++;
n1 = &(lh->b[p]);
n2 = &(lh->b[p + pmax]);
*n2 = NULL;
@@ -271,7 +268,6 @@ static void contract(OPENSSL_LHASH *lh)
lh->error++;
return;
}
- lh->num_contract_reallocs++;
lh->num_alloc_nodes /= 2;
lh->pmax /= 2;
lh->p = lh->pmax - 1;
@@ -280,7 +276,6 @@ static void contract(OPENSSL_LHASH *lh)
lh->p--;
lh->num_nodes--;
- lh->num_contracts++;
n1 = lh->b[(int)lh->p];
if (n1 == NULL)
@@ -300,7 +295,6 @@ static OPENSSL_LH_NODE **getrn(OPENSSL_LHASH *lh,
OPENSSL_LH_COMPFUNC cf;
hash = (*(lh->hash)) (data);
- tsan_counter(&lh->num_hash_calls);
*rhash = hash;
nn = hash % lh->pmax;
@@ -310,12 +304,10 @@ static OPENSSL_LH_NODE **getrn(OPENSSL_LHASH *lh,
cf = lh->comp;
ret = &(lh->b[(int)nn]);
for (n1 = *ret; n1 != NULL; n1 = n1->next) {
- tsan_counter(&lh->num_hash_comps);
if (n1->hash != hash) {
ret = &(n1->next);
continue;
}
- tsan_counter(&lh->num_comp_calls);
if (cf(n1->data, data) == 0)
break;
ret = &(n1->next);
@@ -352,7 +344,7 @@ unsigned long OPENSSL_LH_strhash(const char *c)
return (ret >> 16) ^ ret;
}
-unsigned long openssl_lh_strcasehash(const char *c)
+unsigned long ossl_lh_strcasehash(const char *c)
{
unsigned long ret = 0;
long n;
diff --git a/crypto/lhash/lhash_local.h b/crypto/lhash/lhash_local.h
index 678224acd5d5..088ac94d2e63 100644
--- a/crypto/lhash/lhash_local.h
+++ b/crypto/lhash/lhash_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -27,18 +27,5 @@ struct lhash_st {
unsigned long up_load; /* load times 256 */
unsigned long down_load; /* load times 256 */
unsigned long num_items;
- unsigned long num_expands;
- unsigned long num_expand_reallocs;
- unsigned long num_contracts;
- unsigned long num_contract_reallocs;
- TSAN_QUALIFIER unsigned long num_hash_calls;
- TSAN_QUALIFIER unsigned long num_comp_calls;
- unsigned long num_insert;
- unsigned long num_replace;
- unsigned long num_delete;
- unsigned long num_no_delete;
- TSAN_QUALIFIER unsigned long num_retrieve;
- TSAN_QUALIFIER unsigned long num_retrieve_miss;
- TSAN_QUALIFIER unsigned long num_hash_comps;
int error;
};
diff --git a/crypto/md2/build.info b/crypto/md2/build.info
index e31948c23f5b..541245331f12 100644
--- a/crypto/md2/build.info
+++ b/crypto/md2/build.info
@@ -1,3 +1,9 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- md2_dgst.c md2_one.c
+
+SOURCE[../../libcrypto]=md2_dgst.c md2_one.c
+
+# When all deprecated symbols are removed, libcrypto doesn't export the
+# MD2 functions, so we must include them directly in liblegacy.a
+IF[{- $disabled{'deprecated-3.0'} && !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../../providers/liblegacy.a]=md2_dgst.c md2_one.c
+ENDIF
diff --git a/crypto/md2/md2_dgst.c b/crypto/md2/md2_dgst.c
index faa9393f2e46..0b0033543881 100644
--- a/crypto/md2/md2_dgst.c
+++ b/crypto/md2/md2_dgst.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * MD2 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/crypto/md2/md2_one.c b/crypto/md2/md2_one.c
index 5502b21696d4..f9be692732e0 100644
--- a/crypto/md2/md2_one.c
+++ b/crypto/md2/md2_one.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * MD2 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/md2.h>
diff --git a/crypto/md4/build.info b/crypto/md4/build.info
index 20846e0dcee8..ccd93835f708 100644
--- a/crypto/md4/build.info
+++ b/crypto/md4/build.info
@@ -1,3 +1,9 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- md4_dgst.c md4_one.c
+
+SOURCE[../../libcrypto]=md4_dgst.c md4_one.c
+
+# When all deprecated symbols are removed, libcrypto doesn't export the
+# MD4 functions, so we must include them directly in liblegacy.a
+IF[{- $disabled{'deprecated-3.0'} && !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../../providers/liblegacy.a]=md4_dgst.c md4_one.c
+ENDIF
diff --git a/crypto/md4/md4_dgst.c b/crypto/md4/md4_dgst.c
index 29b6b252bae3..aefe6a3a3770 100644
--- a/crypto/md4/md4_dgst.c
+++ b/crypto/md4/md4_dgst.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * MD4 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <openssl/opensslv.h>
#include "md4_local.h"
diff --git a/crypto/md4/md4_local.h b/crypto/md4/md4_local.h
index 5f05720e9769..66aa5e403897 100644
--- a/crypto/md4/md4_local.h
+++ b/crypto/md4/md4_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/md4/md4_one.c b/crypto/md4/md4_one.c
index 9e52303c2fca..36fa88dd4166 100644
--- a/crypto/md4/md4_one.c
+++ b/crypto/md4/md4_one.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * MD4 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <string.h>
#include <openssl/md4.h>
diff --git a/crypto/md5/asm/md5-586.pl b/crypto/md5/asm/md5-586.pl
index 7986a2413da2..8dd8fa0cf765 100644
--- a/crypto/md5/asm/md5-586.pl
+++ b/crypto/md5/asm/md5-586.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -18,8 +18,10 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output=pop;
-open STDOUT,">$output";
+# $output is the last argument if it looks like a file (it has an extension)
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+
+$output and open STDOUT,">$output";
&asm_init($ARGV[0]);
@@ -40,7 +42,7 @@ $X="esi";
0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9, # R3
);
-&md5_block("md5_block_asm_data_order");
+&md5_block("ossl_md5_block_asm_data_order");
&asm_finish();
close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/md5/asm/md5-sparcv9.pl b/crypto/md5/asm/md5-sparcv9.pl
index 3595e3d32fc9..c41ccf6ba901 100644
--- a/crypto/md5/asm/md5-sparcv9.pl
+++ b/crypto/md5/asm/md5-sparcv9.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -24,8 +24,10 @@
# single-process result on 8-core processor, or ~11GBps per 2.85GHz
# socket.
-$output=pop;
-open STDOUT,">$output";
+# $output is the last argument if it looks like a file (it has an extension)
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+
+$output and open STDOUT,">$output";
use integer;
@@ -201,7 +203,10 @@ ___
}
$code.=<<___;
-#include "sparc_arch.h"
+#ifndef __ASSEMBLER__
+# define __ASSEMBLER__ 1
+#endif
+#include "crypto/sparc_arch.h"
#ifdef __arch64__
.register %g2,#scratch
@@ -214,9 +219,9 @@ $code.=<<___;
SPARC_PIC_THUNK(%g1)
#endif
-.globl md5_block_asm_data_order
+.globl ossl_md5_block_asm_data_order
.align 32
-md5_block_asm_data_order:
+ossl_md5_block_asm_data_order:
SPARC_LOAD_ADDRESS_LEAF(OPENSSL_sparcv9cap_P,%g1,%g5)
ld [%g1+4],%g1 ! OPENSSL_sparcv9cap_P[1]
@@ -369,8 +374,8 @@ $code.=<<___;
wr %g0,$saved_asi,%asi
ret
restore
-.type md5_block_asm_data_order,#function
-.size md5_block_asm_data_order,(.-md5_block_asm_data_order)
+.type ossl_md5_block_asm_data_order,#function
+.size ossl_md5_block_asm_data_order,(.-ossl_md5_block_asm_data_order)
.asciz "MD5 block transform for SPARCv9, CRYPTOGAMS by <appro\@openssl.org>"
.align 4
diff --git a/crypto/md5/asm/md5-x86_64.pl b/crypto/md5/asm/md5-x86_64.pl
index c6a172d448c6..6625fb7d08aa 100755
--- a/crypto/md5/asm/md5-x86_64.pl
+++ b/crypto/md5/asm/md5-x86_64.pl
@@ -2,7 +2,7 @@
# Author: Marc Bevand <bevand_m (at) epita.fr>
# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -119,9 +119,10 @@ EOF
}
no warnings qw(uninitialized);
-my $flavour = shift;
-my $output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
my $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -130,16 +131,17 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; my $dir=$1; my $xlate;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
$code .= <<EOF;
.text
.align 16
-.globl md5_block_asm_data_order
-.type md5_block_asm_data_order,\@function,3
-md5_block_asm_data_order:
+.globl ossl_md5_block_asm_data_order
+.type ossl_md5_block_asm_data_order,\@function,3
+ossl_md5_block_asm_data_order:
.cfi_startproc
push %rbp
.cfi_push %rbp
@@ -281,7 +283,7 @@ $code .= <<EOF;
.Lepilogue:
ret
.cfi_endproc
-.size md5_block_asm_data_order,.-md5_block_asm_data_order
+.size ossl_md5_block_asm_data_order,.-ossl_md5_block_asm_data_order
EOF
# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
@@ -376,13 +378,13 @@ se_handler:
.section .pdata
.align 4
- .rva .LSEH_begin_md5_block_asm_data_order
- .rva .LSEH_end_md5_block_asm_data_order
- .rva .LSEH_info_md5_block_asm_data_order
+ .rva .LSEH_begin_ossl_md5_block_asm_data_order
+ .rva .LSEH_end_ossl_md5_block_asm_data_order
+ .rva .LSEH_info_ossl_md5_block_asm_data_order
.section .xdata
.align 8
-.LSEH_info_md5_block_asm_data_order:
+.LSEH_info_ossl_md5_block_asm_data_order:
.byte 9,0,0,0
.rva se_handler
___
diff --git a/crypto/md5/build.info b/crypto/md5/build.info
index e641fecd0d6e..9a325386065b 100644
--- a/crypto/md5/build.info
+++ b/crypto/md5/build.info
@@ -1,11 +1,40 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- md5_dgst.c md5_one.c {- $target{md5_asm_src} -}
-GENERATE[md5-586.s]=asm/md5-586.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS)
+$MD5ASM=
+IF[{- !$disabled{asm} -}]
+ $MD5ASM_x86=md5-586.S
+ $MD5ASM_x86_64=md5-x86_64.s
+ $MD5ASM_sparcv9=md5-sparcv9.S
-GENERATE[md5-x86_64.s]=asm/md5-x86_64.pl $(PERLASM_SCHEME)
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+ IF[$MD5ASM_{- $target{asm_arch} -}]
+ $MD5ASM=$MD5ASM_{- $target{asm_arch} -}
+ $MD5DEF=MD5_ASM
+ ENDIF
+ENDIF
-GENERATE[md5-sparcv9.S]=asm/md5-sparcv9.pl $(PERLASM_SCHEME)
+$COMMON=md5_dgst.c md5_one.c md5_sha1.c $MD5ASM
+SOURCE[../../libcrypto]=$COMMON
+
+# A no-deprecated no-shared build ends up with double function definitions
+# without conditioning this on dso. The issue is MD5 which is needed in the
+# legacy provider for one of the spliced algorithms, however it resides in the
+# default provider. A no-deprecated build removes the external definition from
+# libcrypto and this means that the code needs to be in liblegacy. However,
+# when building without 'dso', liblegacy is included in libcrypto.
+IF[{- !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../../providers/liblegacy.a]=$COMMON
+ENDIF
+
+# Implementations are now spread across several libraries, so the defines
+# need to be applied to all affected libraries and modules.
+DEFINE[../../libcrypto]=$MD5DEF
+DEFINE[../../providers/liblegacy.a]=$MD5DEF
+
+GENERATE[md5-586.S]=asm/md5-586.pl
+
+GENERATE[md5-x86_64.s]=asm/md5-x86_64.pl
+
+GENERATE[md5-sparcv9.S]=asm/md5-sparcv9.pl
INCLUDE[md5-sparcv9.o]=..
diff --git a/crypto/md5/md5_dgst.c b/crypto/md5/md5_dgst.c
index d84cba37ae98..913b1ea5cad6 100644
--- a/crypto/md5/md5_dgst.c
+++ b/crypto/md5/md5_dgst.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * MD5 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "md5_local.h"
#include <openssl/opensslv.h>
diff --git a/crypto/md5/md5_local.h b/crypto/md5/md5_local.h
index b0087bea81c4..22a0e0f62aed 100644
--- a/crypto/md5/md5_local.h
+++ b/crypto/md5/md5_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -15,11 +15,11 @@
#ifdef MD5_ASM
# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
-# define md5_block_data_order md5_block_asm_data_order
+# define md5_block_data_order ossl_md5_block_asm_data_order
# elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
-# define md5_block_data_order md5_block_asm_data_order
+# define md5_block_data_order ossl_md5_block_asm_data_order
# elif defined(__sparc) || defined(__sparc__)
-# define md5_block_data_order md5_block_asm_data_order
+# define md5_block_data_order ossl_md5_block_asm_data_order
# endif
#endif
diff --git a/crypto/md5/md5_one.c b/crypto/md5/md5_one.c
index c3bf2f88f0ba..fe9b3df29e83 100644
--- a/crypto/md5/md5_one.c
+++ b/crypto/md5/md5_one.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * MD5 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <string.h>
#include <openssl/md5.h>
diff --git a/crypto/md5/md5_sha1.c b/crypto/md5/md5_sha1.c
new file mode 100644
index 000000000000..56defab163fa
--- /dev/null
+++ b/crypto/md5/md5_sha1.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * MD5 and SHA-1 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h>
+#include "prov/md5_sha1.h"
+#include <openssl/evp.h>
+
+int ossl_md5_sha1_init(MD5_SHA1_CTX *mctx)
+{
+ if (!MD5_Init(&mctx->md5))
+ return 0;
+ return SHA1_Init(&mctx->sha1);
+}
+
+int ossl_md5_sha1_update(MD5_SHA1_CTX *mctx, const void *data, size_t count)
+{
+ if (!MD5_Update(&mctx->md5, data, count))
+ return 0;
+ return SHA1_Update(&mctx->sha1, data, count);
+}
+
+int ossl_md5_sha1_final(unsigned char *md, MD5_SHA1_CTX *mctx)
+{
+ if (!MD5_Final(md, &mctx->md5))
+ return 0;
+ return SHA1_Final(md + MD5_DIGEST_LENGTH, &mctx->sha1);
+}
+
+int ossl_md5_sha1_ctrl(MD5_SHA1_CTX *mctx, int cmd, int mslen, void *ms)
+{
+ unsigned char padtmp[48];
+ unsigned char md5tmp[MD5_DIGEST_LENGTH];
+ unsigned char sha1tmp[SHA_DIGEST_LENGTH];
+
+ if (cmd != EVP_CTRL_SSL3_MASTER_SECRET)
+ return -2;
+
+ if (mctx == NULL)
+ return 0;
+
+ /* SSLv3 client auth handling: see RFC-6101 5.6.8 */
+ if (mslen != 48)
+ return 0;
+
+ /* At this point hash contains all handshake messages, update
+ * with master secret and pad_1.
+ */
+
+ if (ossl_md5_sha1_update(mctx, ms, mslen) <= 0)
+ return 0;
+
+ /* Set padtmp to pad_1 value */
+ memset(padtmp, 0x36, sizeof(padtmp));
+
+ if (!MD5_Update(&mctx->md5, padtmp, sizeof(padtmp)))
+ return 0;
+
+ if (!MD5_Final(md5tmp, &mctx->md5))
+ return 0;
+
+ if (!SHA1_Update(&mctx->sha1, padtmp, 40))
+ return 0;
+
+ if (!SHA1_Final(sha1tmp, &mctx->sha1))
+ return 0;
+
+ /* Reinitialise context */
+
+ if (!ossl_md5_sha1_init(mctx))
+ return 0;
+
+ if (ossl_md5_sha1_update(mctx, ms, mslen) <= 0)
+ return 0;
+
+ /* Set padtmp to pad_2 value */
+ memset(padtmp, 0x5c, sizeof(padtmp));
+
+ if (!MD5_Update(&mctx->md5, padtmp, sizeof(padtmp)))
+ return 0;
+
+ if (!MD5_Update(&mctx->md5, md5tmp, sizeof(md5tmp)))
+ return 0;
+
+ if (!SHA1_Update(&mctx->sha1, padtmp, 40))
+ return 0;
+
+ if (!SHA1_Update(&mctx->sha1, sha1tmp, sizeof(sha1tmp)))
+ return 0;
+
+ /* Now when ctx is finalised it will return the SSL v3 hash value */
+
+ OPENSSL_cleanse(md5tmp, sizeof(md5tmp));
+ OPENSSL_cleanse(sha1tmp, sizeof(sha1tmp));
+
+ return 1;
+}
diff --git a/crypto/mdc2/build.info b/crypto/mdc2/build.info
index 8fe6878d600a..f748357b1a48 100644
--- a/crypto/mdc2/build.info
+++ b/crypto/mdc2/build.info
@@ -1,3 +1,9 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- mdc2dgst.c mdc2_one.c
+
+SOURCE[../../libcrypto]=mdc2dgst.c mdc2_one.c
+
+# When all deprecated symbols are removed, libcrypto doesn't export the
+# MDC2 functions, so we must include them directly in liblegacy.a
+IF[{- $disabled{'deprecated-3.0'} && !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../../providers/liblegacy.a]=mdc2dgst.c mdc2_one.c
+ENDIF
diff --git a/crypto/mdc2/mdc2_one.c b/crypto/mdc2/mdc2_one.c
index 58e1e0fdf6c7..cb978263ed5d 100644
--- a/crypto/mdc2/mdc2_one.c
+++ b/crypto/mdc2/mdc2_one.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * MD2 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/mdc2.h>
diff --git a/crypto/mdc2/mdc2dgst.c b/crypto/mdc2/mdc2dgst.c
index 14233b9aba08..607f9fc73a3e 100644
--- a/crypto/mdc2/mdc2dgst.c
+++ b/crypto/mdc2/mdc2dgst.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * MD2 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/crypto/mem.c b/crypto/mem.c
index 2b39ca3a1049..f6cdcf5a423e 100644
--- a/crypto/mem.c
+++ b/crypto/mem.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -14,36 +14,34 @@
#include <stdlib.h>
#include <limits.h>
#include <openssl/crypto.h>
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
-# include <execinfo.h>
-#endif
/*
* the following pointers may be changed as long as 'allow_customize' is set
*/
static int allow_customize = 1;
+static CRYPTO_malloc_fn malloc_impl = CRYPTO_malloc;
+static CRYPTO_realloc_fn realloc_impl = CRYPTO_realloc;
+static CRYPTO_free_fn free_impl = CRYPTO_free;
-static void *(*malloc_impl)(size_t, const char *, int)
- = CRYPTO_malloc;
-static void *(*realloc_impl)(void *, size_t, const char *, int)
- = CRYPTO_realloc;
-static void (*free_impl)(void *, const char *, int)
- = CRYPTO_free;
-
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
+#if !defined(OPENSSL_NO_CRYPTO_MDEBUG) && !defined(FIPS_MODULE)
# include "internal/tsan_assist.h"
+# ifdef TSAN_REQUIRES_LOCKING
+# define INCREMENT(x) /* empty */
+# define LOAD(x) 0
+# else /* TSAN_REQUIRES_LOCKING */
static TSAN_QUALIFIER int malloc_count;
static TSAN_QUALIFIER int realloc_count;
static TSAN_QUALIFIER int free_count;
-# define INCREMENT(x) tsan_counter(&(x))
+# define INCREMENT(x) tsan_counter(&(x))
+# define LOAD(x) tsan_load(&x)
+# endif /* TSAN_REQUIRES_LOCKING */
static char *md_failstring;
static long md_count;
static int md_fail_percent = 0;
static int md_tracefd = -1;
-static int call_malloc_debug = 1;
static void parseit(void);
static int shouldfail(void);
@@ -51,58 +49,47 @@ static int shouldfail(void);
# define FAILTEST() if (shouldfail()) return NULL
#else
-static int call_malloc_debug = 0;
# define INCREMENT(x) /* empty */
# define FAILTEST() /* empty */
#endif
-int CRYPTO_set_mem_functions(
- void *(*m)(size_t, const char *, int),
- void *(*r)(void *, size_t, const char *, int),
- void (*f)(void *, const char *, int))
-{
- if (!allow_customize)
- return 0;
- if (m)
- malloc_impl = m;
- if (r)
- realloc_impl = r;
- if (f)
- free_impl = f;
- return 1;
-}
-
-int CRYPTO_set_mem_debug(int flag)
+int CRYPTO_set_mem_functions(CRYPTO_malloc_fn malloc_fn,
+ CRYPTO_realloc_fn realloc_fn,
+ CRYPTO_free_fn free_fn)
{
if (!allow_customize)
return 0;
- call_malloc_debug = flag;
+ if (malloc_fn != NULL)
+ malloc_impl = malloc_fn;
+ if (realloc_fn != NULL)
+ realloc_impl = realloc_fn;
+ if (free_fn != NULL)
+ free_impl = free_fn;
return 1;
}
-void CRYPTO_get_mem_functions(
- void *(**m)(size_t, const char *, int),
- void *(**r)(void *, size_t, const char *, int),
- void (**f)(void *, const char *, int))
+void CRYPTO_get_mem_functions(CRYPTO_malloc_fn *malloc_fn,
+ CRYPTO_realloc_fn *realloc_fn,
+ CRYPTO_free_fn *free_fn)
{
- if (m != NULL)
- *m = malloc_impl;
- if (r != NULL)
- *r = realloc_impl;
- if (f != NULL)
- *f = free_impl;
+ if (malloc_fn != NULL)
+ *malloc_fn = malloc_impl;
+ if (realloc_fn != NULL)
+ *realloc_fn = realloc_impl;
+ if (free_fn != NULL)
+ *free_fn = free_impl;
}
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
+#if !defined(OPENSSL_NO_CRYPTO_MDEBUG) && !defined(FIPS_MODULE)
void CRYPTO_get_alloc_counts(int *mcount, int *rcount, int *fcount)
{
if (mcount != NULL)
- *mcount = tsan_load(&malloc_count);
+ *mcount = LOAD(malloc_count);
if (rcount != NULL)
- *rcount = tsan_load(&realloc_count);
+ *rcount = LOAD(realloc_count);
if (fcount != NULL)
- *fcount = tsan_load(&free_count);
+ *fcount = LOAD(free_count);
}
/*
@@ -158,14 +145,6 @@ static int shouldfail(void)
len = strlen(buff);
if (write(md_tracefd, buff, len) != len)
perror("shouldfail write failed");
-# ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
- if (shoulditfail) {
- void *addrs[30];
- int num = backtrace(addrs, OSSL_NELEM(addrs));
-
- backtrace_symbols_fd(addrs, num, md_tracefd);
- }
-# endif
}
# endif
@@ -191,10 +170,8 @@ void ossl_malloc_setup_failures(void)
void *CRYPTO_malloc(size_t num, const char *file, int line)
{
- void *ret = NULL;
-
INCREMENT(malloc_count);
- if (malloc_impl != NULL && malloc_impl != CRYPTO_malloc)
+ if (malloc_impl != CRYPTO_malloc)
return malloc_impl(num, file, line);
if (num == 0)
@@ -209,36 +186,26 @@ void *CRYPTO_malloc(size_t num, const char *file, int line)
*/
allow_customize = 0;
}
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
- if (call_malloc_debug) {
- CRYPTO_mem_debug_malloc(NULL, num, 0, file, line);
- ret = malloc(num);
- CRYPTO_mem_debug_malloc(ret, num, 1, file, line);
- } else {
- ret = malloc(num);
- }
-#else
- (void)(file); (void)(line);
- ret = malloc(num);
-#endif
- return ret;
+ return malloc(num);
}
void *CRYPTO_zalloc(size_t num, const char *file, int line)
{
- void *ret = CRYPTO_malloc(num, file, line);
+ void *ret;
+ ret = CRYPTO_malloc(num, file, line);
FAILTEST();
if (ret != NULL)
memset(ret, 0, num);
+
return ret;
}
void *CRYPTO_realloc(void *str, size_t num, const char *file, int line)
{
INCREMENT(realloc_count);
- if (realloc_impl != NULL && realloc_impl != &CRYPTO_realloc)
+ if (realloc_impl != CRYPTO_realloc)
return realloc_impl(str, num, file, line);
FAILTEST();
@@ -250,19 +217,7 @@ void *CRYPTO_realloc(void *str, size_t num, const char *file, int line)
return NULL;
}
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
- if (call_malloc_debug) {
- void *ret;
- CRYPTO_mem_debug_realloc(str, NULL, num, 0, file, line);
- ret = realloc(str, num);
- CRYPTO_mem_debug_realloc(str, ret, num, 1, file, line);
- return ret;
- }
-#else
- (void)(file); (void)(line);
-#endif
return realloc(str, num);
-
}
void *CRYPTO_clear_realloc(void *str, size_t old_len, size_t num,
@@ -295,22 +250,12 @@ void *CRYPTO_clear_realloc(void *str, size_t old_len, size_t num,
void CRYPTO_free(void *str, const char *file, int line)
{
INCREMENT(free_count);
- if (free_impl != NULL && free_impl != &CRYPTO_free) {
+ if (free_impl != CRYPTO_free) {
free_impl(str, file, line);
return;
}
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
- if (call_malloc_debug) {
- CRYPTO_mem_debug_free(str, 0, file, line);
- free(str);
- CRYPTO_mem_debug_free(str, 1, file, line);
- } else {
- free(str);
- }
-#else
free(str);
-#endif
}
void CRYPTO_clear_free(void *str, size_t num, const char *file, int line)
@@ -321,3 +266,72 @@ void CRYPTO_clear_free(void *str, size_t num, const char *file, int line)
OPENSSL_cleanse(str, num);
CRYPTO_free(str, file, line);
}
+
+#if !defined(OPENSSL_NO_CRYPTO_MDEBUG)
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+int CRYPTO_mem_ctrl(int mode)
+{
+ (void)mode;
+ return -1;
+}
+
+int CRYPTO_set_mem_debug(int flag)
+{
+ (void)flag;
+ return -1;
+}
+
+int CRYPTO_mem_debug_push(const char *info, const char *file, int line)
+{
+ (void)info; (void)file; (void)line;
+ return 0;
+}
+
+int CRYPTO_mem_debug_pop(void)
+{
+ return 0;
+}
+
+void CRYPTO_mem_debug_malloc(void *addr, size_t num, int flag,
+ const char *file, int line)
+{
+ (void)addr; (void)num; (void)flag; (void)file; (void)line;
+}
+
+void CRYPTO_mem_debug_realloc(void *addr1, void *addr2, size_t num, int flag,
+ const char *file, int line)
+{
+ (void)addr1; (void)addr2; (void)num; (void)flag; (void)file; (void)line;
+}
+
+void CRYPTO_mem_debug_free(void *addr, int flag,
+ const char *file, int line)
+{
+ (void)addr; (void)flag; (void)file; (void)line;
+}
+
+int CRYPTO_mem_leaks(BIO *b)
+{
+ (void)b;
+ return -1;
+}
+
+# ifndef OPENSSL_NO_STDIO
+int CRYPTO_mem_leaks_fp(FILE *fp)
+{
+ (void)fp;
+ return -1;
+}
+# endif
+
+int CRYPTO_mem_leaks_cb(int (*cb)(const char *str, size_t len, void *u),
+ void *u)
+{
+ (void)cb; (void)u;
+ return -1;
+}
+
+# endif
+
+#endif
diff --git a/crypto/mem_clr.c b/crypto/mem_clr.c
index 35bfb74eaebd..d76ef73179d0 100644
--- a/crypto/mem_clr.c
+++ b/crypto/mem_clr.c
@@ -1,7 +1,7 @@
/*
* Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/mem_dbg.c b/crypto/mem_dbg.c
deleted file mode 100644
index 0489e97adbda..000000000000
--- a/crypto/mem_dbg.c
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include "internal/cryptlib.h"
-#include "internal/thread_once.h"
-#include <openssl/crypto.h>
-#include <openssl/buffer.h>
-#include "internal/bio.h"
-#include <openssl/lhash.h>
-
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
-# include <execinfo.h>
-#endif
-
-/*
- * The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE when
- * the application asks for it (usually after library initialisation for
- * which no book-keeping is desired). State CRYPTO_MEM_CHECK_ON exists only
- * temporarily when the library thinks that certain allocations should not be
- * checked (e.g. the data structures used for memory checking). It is not
- * suitable as an initial state: the library will unexpectedly enable memory
- * checking when it executes one of those sections that want to disable
- * checking temporarily. State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes
- * no sense whatsoever.
- */
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
-static int mh_mode = CRYPTO_MEM_CHECK_OFF;
-#endif
-
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
-static unsigned long order = 0; /* number of memory requests */
-
-/*-
- * For application-defined information (static C-string `info')
- * to be displayed in memory leak list.
- * Each thread has its own stack. For applications, there is
- * OPENSSL_mem_debug_push("...") to push an entry,
- * OPENSSL_mem_debug_pop() to pop an entry,
- */
-struct app_mem_info_st {
- CRYPTO_THREAD_ID threadid;
- const char *file;
- int line;
- const char *info;
- struct app_mem_info_st *next; /* tail of thread's stack */
- int references;
-};
-
-static CRYPTO_ONCE memdbg_init = CRYPTO_ONCE_STATIC_INIT;
-CRYPTO_RWLOCK *memdbg_lock;
-static CRYPTO_RWLOCK *long_memdbg_lock;
-static CRYPTO_THREAD_LOCAL appinfokey;
-
-/* memory-block description */
-struct mem_st {
- void *addr;
- int num;
- const char *file;
- int line;
- CRYPTO_THREAD_ID threadid;
- unsigned long order;
- time_t time;
- APP_INFO *app_info;
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
- void *array[30];
- size_t array_siz;
-#endif
-};
-
-/*
- * hash-table of memory requests (address as * key); access requires
- * long_memdbg_lock lock
- */
-static LHASH_OF(MEM) *mh = NULL;
-
-/* num_disable > 0 iff mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE) */
-static unsigned int num_disable = 0;
-
-/*
- * Valid iff num_disable > 0. long_memdbg_lock is locked exactly in this
- * case (by the thread named in disabling_thread).
- */
-static CRYPTO_THREAD_ID disabling_threadid;
-
-DEFINE_RUN_ONCE_STATIC(do_memdbg_init)
-{
- memdbg_lock = CRYPTO_THREAD_lock_new();
- long_memdbg_lock = CRYPTO_THREAD_lock_new();
- if (memdbg_lock == NULL || long_memdbg_lock == NULL
- || !CRYPTO_THREAD_init_local(&appinfokey, NULL)) {
- CRYPTO_THREAD_lock_free(memdbg_lock);
- memdbg_lock = NULL;
- CRYPTO_THREAD_lock_free(long_memdbg_lock);
- long_memdbg_lock = NULL;
- return 0;
- }
- return 1;
-}
-
-static void app_info_free(APP_INFO *inf)
-{
- if (inf == NULL)
- return;
- if (--(inf->references) <= 0) {
- app_info_free(inf->next);
- OPENSSL_free(inf);
- }
-}
-#endif
-
-int CRYPTO_mem_ctrl(int mode)
-{
-#ifdef OPENSSL_NO_CRYPTO_MDEBUG
- return mode - mode;
-#else
- int ret = mh_mode;
-
- if (!RUN_ONCE(&memdbg_init, do_memdbg_init))
- return -1;
-
- CRYPTO_THREAD_write_lock(memdbg_lock);
- switch (mode) {
- default:
- break;
-
- case CRYPTO_MEM_CHECK_ON:
- mh_mode = CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE;
- num_disable = 0;
- break;
-
- case CRYPTO_MEM_CHECK_OFF:
- mh_mode = 0;
- num_disable = 0;
- break;
-
- /* switch off temporarily (for library-internal use): */
- case CRYPTO_MEM_CHECK_DISABLE:
- if (mh_mode & CRYPTO_MEM_CHECK_ON) {
- CRYPTO_THREAD_ID cur = CRYPTO_THREAD_get_current_id();
- /* see if we don't have long_memdbg_lock already */
- if (!num_disable
- || !CRYPTO_THREAD_compare_id(disabling_threadid, cur)) {
- /*
- * Long-time lock long_memdbg_lock must not be claimed
- * while we're holding memdbg_lock, or we'll deadlock
- * if somebody else holds long_memdbg_lock (and cannot
- * release it because we block entry to this function). Give
- * them a chance, first, and then claim the locks in
- * appropriate order (long-time lock first).
- */
- CRYPTO_THREAD_unlock(memdbg_lock);
- /*
- * Note that after we have waited for long_memdbg_lock and
- * memdbg_lock, we'll still be in the right "case" and
- * "if" branch because MemCheck_start and MemCheck_stop may
- * never be used while there are multiple OpenSSL threads.
- */
- CRYPTO_THREAD_write_lock(long_memdbg_lock);
- CRYPTO_THREAD_write_lock(memdbg_lock);
- mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
- disabling_threadid = cur;
- }
- num_disable++;
- }
- break;
-
- case CRYPTO_MEM_CHECK_ENABLE:
- if (mh_mode & CRYPTO_MEM_CHECK_ON) {
- if (num_disable) { /* always true, or something is going wrong */
- num_disable--;
- if (num_disable == 0) {
- mh_mode |= CRYPTO_MEM_CHECK_ENABLE;
- CRYPTO_THREAD_unlock(long_memdbg_lock);
- }
- }
- }
- break;
- }
- CRYPTO_THREAD_unlock(memdbg_lock);
- return ret;
-#endif
-}
-
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
-
-static int mem_check_on(void)
-{
- int ret = 0;
- CRYPTO_THREAD_ID cur;
-
- if (mh_mode & CRYPTO_MEM_CHECK_ON) {
- if (!RUN_ONCE(&memdbg_init, do_memdbg_init))
- return 0;
-
- cur = CRYPTO_THREAD_get_current_id();
- CRYPTO_THREAD_read_lock(memdbg_lock);
-
- ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
- || !CRYPTO_THREAD_compare_id(disabling_threadid, cur);
-
- CRYPTO_THREAD_unlock(memdbg_lock);
- }
- return ret;
-}
-
-static int mem_cmp(const MEM *a, const MEM *b)
-{
-#ifdef _WIN64
- const char *ap = (const char *)a->addr, *bp = (const char *)b->addr;
- if (ap == bp)
- return 0;
- else if (ap > bp)
- return 1;
- else
- return -1;
-#else
- return (const char *)a->addr - (const char *)b->addr;
-#endif
-}
-
-static unsigned long mem_hash(const MEM *a)
-{
- size_t ret;
-
- ret = (size_t)a->addr;
-
- ret = ret * 17851 + (ret >> 14) * 7 + (ret >> 4) * 251;
- return ret;
-}
-
-/* returns 1 if there was an info to pop, 0 if the stack was empty. */
-static int pop_info(void)
-{
- APP_INFO *current = NULL;
-
- if (!RUN_ONCE(&memdbg_init, do_memdbg_init))
- return 0;
-
- current = (APP_INFO *)CRYPTO_THREAD_get_local(&appinfokey);
- if (current != NULL) {
- APP_INFO *next = current->next;
-
- if (next != NULL) {
- next->references++;
- CRYPTO_THREAD_set_local(&appinfokey, next);
- } else {
- CRYPTO_THREAD_set_local(&appinfokey, NULL);
- }
- if (--(current->references) <= 0) {
- current->next = NULL;
- if (next != NULL)
- next->references--;
- OPENSSL_free(current);
- }
- return 1;
- }
- return 0;
-}
-
-int CRYPTO_mem_debug_push(const char *info, const char *file, int line)
-{
- APP_INFO *ami, *amim;
- int ret = 0;
-
- if (mem_check_on()) {
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
-
- if (!RUN_ONCE(&memdbg_init, do_memdbg_init)
- || (ami = OPENSSL_malloc(sizeof(*ami))) == NULL)
- goto err;
-
- ami->threadid = CRYPTO_THREAD_get_current_id();
- ami->file = file;
- ami->line = line;
- ami->info = info;
- ami->references = 1;
- ami->next = NULL;
-
- amim = (APP_INFO *)CRYPTO_THREAD_get_local(&appinfokey);
- CRYPTO_THREAD_set_local(&appinfokey, ami);
-
- if (amim != NULL)
- ami->next = amim;
- ret = 1;
- err:
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
- }
-
- return ret;
-}
-
-int CRYPTO_mem_debug_pop(void)
-{
- int ret = 0;
-
- if (mem_check_on()) {
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
- ret = pop_info();
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
- }
- return ret;
-}
-
-static unsigned long break_order_num = 0;
-
-void CRYPTO_mem_debug_malloc(void *addr, size_t num, int before_p,
- const char *file, int line)
-{
- MEM *m, *mm;
- APP_INFO *amim;
-
- switch (before_p & 127) {
- case 0:
- break;
- case 1:
- if (addr == NULL)
- break;
-
- if (mem_check_on()) {
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
-
- if (!RUN_ONCE(&memdbg_init, do_memdbg_init)
- || (m = OPENSSL_malloc(sizeof(*m))) == NULL) {
- OPENSSL_free(addr);
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
- return;
- }
- if (mh == NULL) {
- if ((mh = lh_MEM_new(mem_hash, mem_cmp)) == NULL) {
- OPENSSL_free(addr);
- OPENSSL_free(m);
- addr = NULL;
- goto err;
- }
- }
-
- m->addr = addr;
- m->file = file;
- m->line = line;
- m->num = num;
- m->threadid = CRYPTO_THREAD_get_current_id();
-
- if (order == break_order_num) {
- /* BREAK HERE */
- m->order = order;
- }
- m->order = order++;
-# ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
- m->array_siz = backtrace(m->array, OSSL_NELEM(m->array));
-# endif
- m->time = time(NULL);
-
- amim = (APP_INFO *)CRYPTO_THREAD_get_local(&appinfokey);
- m->app_info = amim;
- if (amim != NULL)
- amim->references++;
-
- if ((mm = lh_MEM_insert(mh, m)) != NULL) {
- /* Not good, but don't sweat it */
- if (mm->app_info != NULL) {
- mm->app_info->references--;
- }
- OPENSSL_free(mm);
- }
- err:
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
- }
- break;
- }
- return;
-}
-
-void CRYPTO_mem_debug_free(void *addr, int before_p,
- const char *file, int line)
-{
- MEM m, *mp;
-
- switch (before_p) {
- case 0:
- if (addr == NULL)
- break;
-
- if (mem_check_on() && (mh != NULL)) {
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
-
- m.addr = addr;
- mp = lh_MEM_delete(mh, &m);
- if (mp != NULL) {
- app_info_free(mp->app_info);
- OPENSSL_free(mp);
- }
-
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
- }
- break;
- case 1:
- break;
- }
-}
-
-void CRYPTO_mem_debug_realloc(void *addr1, void *addr2, size_t num,
- int before_p, const char *file, int line)
-{
- MEM m, *mp;
-
- switch (before_p) {
- case 0:
- break;
- case 1:
- if (addr2 == NULL)
- break;
-
- if (addr1 == NULL) {
- CRYPTO_mem_debug_malloc(addr2, num, 128 | before_p, file, line);
- break;
- }
-
- if (mem_check_on()) {
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
-
- m.addr = addr1;
- mp = lh_MEM_delete(mh, &m);
- if (mp != NULL) {
- mp->addr = addr2;
- mp->num = num;
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
- mp->array_siz = backtrace(mp->array, OSSL_NELEM(mp->array));
-#endif
- (void)lh_MEM_insert(mh, mp);
- }
-
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
- }
- break;
- }
- return;
-}
-
-typedef struct mem_leak_st {
- int (*print_cb) (const char *str, size_t len, void *u);
- void *print_cb_arg;
- int chunks;
- long bytes;
-} MEM_LEAK;
-
-static void print_leak(const MEM *m, MEM_LEAK *l)
-{
- char buf[1024];
- char *bufp = buf;
- size_t len = sizeof(buf), ami_cnt;
- APP_INFO *amip;
- int n;
- struct tm *lcl = NULL;
- /*
- * Convert between CRYPTO_THREAD_ID (which could be anything at all) and
- * a long. This may not be meaningful depending on what CRYPTO_THREAD_ID is
- * but hopefully should give something sensible on most platforms
- */
- union {
- CRYPTO_THREAD_ID tid;
- unsigned long ltid;
- } tid;
- CRYPTO_THREAD_ID ti;
-
- lcl = localtime(&m->time);
- n = BIO_snprintf(bufp, len, "[%02d:%02d:%02d] ",
- lcl->tm_hour, lcl->tm_min, lcl->tm_sec);
- if (n <= 0) {
- bufp[0] = '\0';
- return;
- }
- bufp += n;
- len -= n;
-
- n = BIO_snprintf(bufp, len, "%5lu file=%s, line=%d, ",
- m->order, m->file, m->line);
- if (n <= 0)
- return;
- bufp += n;
- len -= n;
-
- tid.ltid = 0;
- tid.tid = m->threadid;
- n = BIO_snprintf(bufp, len, "thread=%lu, ", tid.ltid);
- if (n <= 0)
- return;
- bufp += n;
- len -= n;
-
- n = BIO_snprintf(bufp, len, "number=%d, address=%p\n", m->num, m->addr);
- if (n <= 0)
- return;
- bufp += n;
- len -= n;
-
- l->print_cb(buf, (size_t)(bufp - buf), l->print_cb_arg);
-
- l->chunks++;
- l->bytes += m->num;
-
- amip = m->app_info;
- ami_cnt = 0;
-
- if (amip) {
- ti = amip->threadid;
-
- do {
- int buf_len;
- int info_len;
-
- ami_cnt++;
- if (ami_cnt >= sizeof(buf) - 1)
- break;
- memset(buf, '>', ami_cnt);
- buf[ami_cnt] = '\0';
- tid.ltid = 0;
- tid.tid = amip->threadid;
- n = BIO_snprintf(buf + ami_cnt, sizeof(buf) - ami_cnt,
- " thread=%lu, file=%s, line=%d, info=\"",
- tid.ltid, amip->file, amip->line);
- if (n <= 0)
- break;
- buf_len = ami_cnt + n;
- info_len = strlen(amip->info);
- if (128 - buf_len - 3 < info_len) {
- memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
- buf_len = 128 - 3;
- } else {
- n = BIO_snprintf(buf + buf_len, sizeof(buf) - buf_len, "%s",
- amip->info);
- if (n < 0)
- break;
- buf_len += n;
- }
- n = BIO_snprintf(buf + buf_len, sizeof(buf) - buf_len, "\"\n");
- if (n <= 0)
- break;
-
- l->print_cb(buf, buf_len + n, l->print_cb_arg);
-
- amip = amip->next;
- }
- while (amip && CRYPTO_THREAD_compare_id(amip->threadid, ti));
- }
-
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
- {
- size_t i;
- char **strings = backtrace_symbols(m->array, m->array_siz);
-
- for (i = 0; i < m->array_siz; i++)
- fprintf(stderr, "##> %s\n", strings[i]);
- free(strings);
- }
-#endif
-}
-
-IMPLEMENT_LHASH_DOALL_ARG_CONST(MEM, MEM_LEAK);
-
-int CRYPTO_mem_leaks_cb(int (*cb) (const char *str, size_t len, void *u),
- void *u)
-{
- MEM_LEAK ml;
-
- /* Ensure all resources are released */
- OPENSSL_cleanup();
-
- if (!RUN_ONCE(&memdbg_init, do_memdbg_init))
- return -1;
-
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
-
- ml.print_cb = cb;
- ml.print_cb_arg = u;
- ml.bytes = 0;
- ml.chunks = 0;
- if (mh != NULL)
- lh_MEM_doall_MEM_LEAK(mh, print_leak, &ml);
-
- if (ml.chunks != 0) {
- char buf[256];
-
- BIO_snprintf(buf, sizeof(buf), "%ld bytes leaked in %d chunks\n",
- ml.bytes, ml.chunks);
- cb(buf, strlen(buf), u);
- } else {
- /*
- * Make sure that, if we found no leaks, memory-leak debugging itself
- * does not introduce memory leaks (which might irritate external
- * debugging tools). (When someone enables leak checking, but does not
- * call this function, we declare it to be their fault.)
- */
- int old_mh_mode;
-
- CRYPTO_THREAD_write_lock(memdbg_lock);
-
- /*
- * avoid deadlock when lh_free() uses CRYPTO_mem_debug_free(), which uses
- * mem_check_on
- */
- old_mh_mode = mh_mode;
- mh_mode = CRYPTO_MEM_CHECK_OFF;
-
- lh_MEM_free(mh);
- mh = NULL;
-
- mh_mode = old_mh_mode;
- CRYPTO_THREAD_unlock(memdbg_lock);
- }
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF);
-
- /* Clean up locks etc */
- CRYPTO_THREAD_cleanup_local(&appinfokey);
- CRYPTO_THREAD_lock_free(memdbg_lock);
- CRYPTO_THREAD_lock_free(long_memdbg_lock);
- memdbg_lock = NULL;
- long_memdbg_lock = NULL;
-
- return ml.chunks == 0 ? 1 : 0;
-}
-
-static int print_bio(const char *str, size_t len, void *b)
-{
- return BIO_write((BIO *)b, str, len);
-}
-
-int CRYPTO_mem_leaks(BIO *b)
-{
- /*
- * OPENSSL_cleanup() will free the ex_data locks so we can't have any
- * ex_data hanging around
- */
- bio_free_ex_data(b);
-
- return CRYPTO_mem_leaks_cb(print_bio, b);
-}
-
-# ifndef OPENSSL_NO_STDIO
-int CRYPTO_mem_leaks_fp(FILE *fp)
-{
- BIO *b;
- int ret;
-
- /*
- * Need to turn off memory checking when allocated BIOs ... especially as
- * we're creating them at a time when we're trying to check we've not
- * left anything un-free()'d!!
- */
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
- b = BIO_new(BIO_s_file());
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
- if (b == NULL)
- return -1;
- BIO_set_fp(b, fp, BIO_NOCLOSE);
- ret = CRYPTO_mem_leaks_cb(print_bio, b);
- BIO_free(b);
- return ret;
-}
-# endif
-
-#endif
diff --git a/crypto/mem_sec.c b/crypto/mem_sec.c
index 222c786cbaef..6ba75486a897 100644
--- a/crypto/mem_sec.c
+++ b/crypto/mem_sec.c
@@ -1,8 +1,8 @@
/*
- * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2004-2014, Akamai Technologies. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -20,27 +20,48 @@
#include <string.h>
-/* e_os.h defines OPENSSL_SECURE_MEMORY if secure memory can be implemented */
-#ifdef OPENSSL_SECURE_MEMORY
+#ifndef OPENSSL_NO_SECURE_MEMORY
+# if defined(_WIN32)
+# include <windows.h>
+# if defined(WINAPI_FAMILY_PARTITION)
+# if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
+/*
+ * While VirtualLock is available under the app partition (e.g. UWP),
+ * the headers do not define the API. Define it ourselves instead.
+ */
+WINBASEAPI
+BOOL
+WINAPI
+VirtualLock(
+ _In_ LPVOID lpAddress,
+ _In_ SIZE_T dwSize
+ );
+# endif
+# endif
+# endif
# include <stdlib.h>
# include <assert.h>
-# include <unistd.h>
+# if defined(OPENSSL_SYS_UNIX)
+# include <unistd.h>
+# endif
# include <sys/types.h>
-# include <sys/mman.h>
+# if defined(OPENSSL_SYS_UNIX)
+# include <sys/mman.h>
+# if defined(__FreeBSD__)
+# define MADV_DONTDUMP MADV_NOCORE
+# endif
+# if !defined(MAP_CONCEAL)
+# define MAP_CONCEAL 0
+# endif
+# endif
# if defined(OPENSSL_SYS_LINUX)
# include <sys/syscall.h>
# if defined(SYS_mlock2)
# include <linux/mman.h>
# include <errno.h>
# endif
+# include <sys/param.h>
# endif
-# if defined(__FreeBSD__)
-# define MADV_DONTDUMP MADV_NOCORE
-# endif
-# if !defined(MAP_CONCEAL)
-# define MAP_CONCEAL 0
-# endif
-# include <sys/param.h>
# include <sys/stat.h>
# include <fcntl.h>
#endif
@@ -53,7 +74,7 @@
# define MAP_ANON MAP_ANONYMOUS
#endif
-#ifdef OPENSSL_SECURE_MEMORY
+#ifndef OPENSSL_NO_SECURE_MEMORY
static size_t secure_mem_used;
static int secure_mem_initialized;
@@ -63,7 +84,7 @@ static CRYPTO_RWLOCK *sec_malloc_lock = NULL;
/*
* These are the functions that must be implemented by a secure heap (sh).
*/
-static int sh_init(size_t size, int minsize);
+static int sh_init(size_t size, size_t minsize);
static void *sh_malloc(size_t size);
static void sh_free(void *ptr);
static void sh_done(void);
@@ -71,9 +92,9 @@ static size_t sh_actual_size(char *ptr);
static int sh_allocated(const char *ptr);
#endif
-int CRYPTO_secure_malloc_init(size_t size, int minsize)
+int CRYPTO_secure_malloc_init(size_t size, size_t minsize)
{
-#ifdef OPENSSL_SECURE_MEMORY
+#ifndef OPENSSL_NO_SECURE_MEMORY
int ret = 0;
if (!secure_mem_initialized) {
@@ -91,12 +112,12 @@ int CRYPTO_secure_malloc_init(size_t size, int minsize)
return ret;
#else
return 0;
-#endif /* OPENSSL_SECURE_MEMORY */
+#endif /* OPENSSL_NO_SECURE_MEMORY */
}
int CRYPTO_secure_malloc_done(void)
{
-#ifdef OPENSSL_SECURE_MEMORY
+#ifndef OPENSSL_NO_SECURE_MEMORY
if (secure_mem_used == 0) {
sh_done();
secure_mem_initialized = 0;
@@ -104,29 +125,30 @@ int CRYPTO_secure_malloc_done(void)
sec_malloc_lock = NULL;
return 1;
}
-#endif /* OPENSSL_SECURE_MEMORY */
+#endif /* OPENSSL_NO_SECURE_MEMORY */
return 0;
}
int CRYPTO_secure_malloc_initialized(void)
{
-#ifdef OPENSSL_SECURE_MEMORY
+#ifndef OPENSSL_NO_SECURE_MEMORY
return secure_mem_initialized;
#else
return 0;
-#endif /* OPENSSL_SECURE_MEMORY */
+#endif /* OPENSSL_NO_SECURE_MEMORY */
}
void *CRYPTO_secure_malloc(size_t num, const char *file, int line)
{
-#ifdef OPENSSL_SECURE_MEMORY
+#ifndef OPENSSL_NO_SECURE_MEMORY
void *ret;
size_t actual_size;
if (!secure_mem_initialized) {
return CRYPTO_malloc(num, file, line);
}
- CRYPTO_THREAD_write_lock(sec_malloc_lock);
+ if (!CRYPTO_THREAD_write_lock(sec_malloc_lock))
+ return NULL;
ret = sh_malloc(num);
actual_size = ret ? sh_actual_size(ret) : 0;
secure_mem_used += actual_size;
@@ -134,12 +156,12 @@ void *CRYPTO_secure_malloc(size_t num, const char *file, int line)
return ret;
#else
return CRYPTO_malloc(num, file, line);
-#endif /* OPENSSL_SECURE_MEMORY */
+#endif /* OPENSSL_NO_SECURE_MEMORY */
}
void *CRYPTO_secure_zalloc(size_t num, const char *file, int line)
{
-#ifdef OPENSSL_SECURE_MEMORY
+#ifndef OPENSSL_NO_SECURE_MEMORY
if (secure_mem_initialized)
/* CRYPTO_secure_malloc() zeroes allocations when it is implemented */
return CRYPTO_secure_malloc(num, file, line);
@@ -149,7 +171,7 @@ void *CRYPTO_secure_zalloc(size_t num, const char *file, int line)
void CRYPTO_secure_free(void *ptr, const char *file, int line)
{
-#ifdef OPENSSL_SECURE_MEMORY
+#ifndef OPENSSL_NO_SECURE_MEMORY
size_t actual_size;
if (ptr == NULL)
@@ -158,7 +180,8 @@ void CRYPTO_secure_free(void *ptr, const char *file, int line)
CRYPTO_free(ptr, file, line);
return;
}
- CRYPTO_THREAD_write_lock(sec_malloc_lock);
+ if (!CRYPTO_THREAD_write_lock(sec_malloc_lock))
+ return;
actual_size = sh_actual_size(ptr);
CLEAR(ptr, actual_size);
secure_mem_used -= actual_size;
@@ -166,13 +189,13 @@ void CRYPTO_secure_free(void *ptr, const char *file, int line)
CRYPTO_THREAD_unlock(sec_malloc_lock);
#else
CRYPTO_free(ptr, file, line);
-#endif /* OPENSSL_SECURE_MEMORY */
+#endif /* OPENSSL_NO_SECURE_MEMORY */
}
void CRYPTO_secure_clear_free(void *ptr, size_t num,
const char *file, int line)
{
-#ifdef OPENSSL_SECURE_MEMORY
+#ifndef OPENSSL_NO_SECURE_MEMORY
size_t actual_size;
if (ptr == NULL)
@@ -182,7 +205,8 @@ void CRYPTO_secure_clear_free(void *ptr, size_t num,
CRYPTO_free(ptr, file, line);
return;
}
- CRYPTO_THREAD_write_lock(sec_malloc_lock);
+ if (!CRYPTO_THREAD_write_lock(sec_malloc_lock))
+ return;
actual_size = sh_actual_size(ptr);
CLEAR(ptr, actual_size);
secure_mem_used -= actual_size;
@@ -193,40 +217,41 @@ void CRYPTO_secure_clear_free(void *ptr, size_t num,
return;
OPENSSL_cleanse(ptr, num);
CRYPTO_free(ptr, file, line);
-#endif /* OPENSSL_SECURE_MEMORY */
+#endif /* OPENSSL_NO_SECURE_MEMORY */
}
int CRYPTO_secure_allocated(const void *ptr)
{
-#ifdef OPENSSL_SECURE_MEMORY
- int ret;
-
+#ifndef OPENSSL_NO_SECURE_MEMORY
if (!secure_mem_initialized)
return 0;
- CRYPTO_THREAD_write_lock(sec_malloc_lock);
- ret = sh_allocated(ptr);
- CRYPTO_THREAD_unlock(sec_malloc_lock);
- return ret;
+ /*
+ * Only read accesses to the arena take place in sh_allocated() and this
+ * is only changed by the sh_init() and sh_done() calls which are not
+ * locked. Hence, it is safe to make this check without a lock too.
+ */
+ return sh_allocated(ptr);
#else
return 0;
-#endif /* OPENSSL_SECURE_MEMORY */
+#endif /* OPENSSL_NO_SECURE_MEMORY */
}
size_t CRYPTO_secure_used(void)
{
-#ifdef OPENSSL_SECURE_MEMORY
+#ifndef OPENSSL_NO_SECURE_MEMORY
return secure_mem_used;
#else
return 0;
-#endif /* OPENSSL_SECURE_MEMORY */
+#endif /* OPENSSL_NO_SECURE_MEMORY */
}
size_t CRYPTO_secure_actual_size(void *ptr)
{
-#ifdef OPENSSL_SECURE_MEMORY
+#ifndef OPENSSL_NO_SECURE_MEMORY
size_t actual_size;
- CRYPTO_THREAD_write_lock(sec_malloc_lock);
+ if (!CRYPTO_THREAD_write_lock(sec_malloc_lock))
+ return 0;
actual_size = sh_actual_size(ptr);
CRYPTO_THREAD_unlock(sec_malloc_lock);
return actual_size;
@@ -234,14 +259,11 @@ size_t CRYPTO_secure_actual_size(void *ptr)
return 0;
#endif
}
-/* END OF PAGE ...
-
- ... START OF PAGE */
/*
* SECURE HEAP IMPLEMENTATION
*/
-#ifdef OPENSSL_SECURE_MEMORY
+#ifndef OPENSSL_NO_SECURE_MEMORY
/*
@@ -379,27 +401,46 @@ static void sh_remove_from_list(char *ptr)
}
-static int sh_init(size_t size, int minsize)
+static int sh_init(size_t size, size_t minsize)
{
int ret;
size_t i;
size_t pgsize;
size_t aligned;
+#if defined(_WIN32)
+ DWORD flOldProtect;
+ SYSTEM_INFO systemInfo;
+#endif
memset(&sh, 0, sizeof(sh));
- /* make sure size and minsize are powers of 2 */
+ /* make sure size is a powers of 2 */
OPENSSL_assert(size > 0);
OPENSSL_assert((size & (size - 1)) == 0);
- OPENSSL_assert(minsize > 0);
- OPENSSL_assert((minsize & (minsize - 1)) == 0);
- if (size <= 0 || (size & (size - 1)) != 0)
- goto err;
- if (minsize <= 0 || (minsize & (minsize - 1)) != 0)
+ if (size == 0 || (size & (size - 1)) != 0)
goto err;
- while (minsize < (int)sizeof(SH_LIST))
- minsize *= 2;
+ if (minsize <= sizeof(SH_LIST)) {
+ OPENSSL_assert(sizeof(SH_LIST) <= 65536);
+ /*
+ * Compute the minimum possible allocation size.
+ * This must be a power of 2 and at least as large as the SH_LIST
+ * structure.
+ */
+ minsize = sizeof(SH_LIST) - 1;
+ minsize |= minsize >> 1;
+ minsize |= minsize >> 2;
+ if (sizeof(SH_LIST) > 16)
+ minsize |= minsize >> 4;
+ if (sizeof(SH_LIST) > 256)
+ minsize |= minsize >> 8;
+ minsize++;
+ } else {
+ /* make sure minsize is a powers of 2 */
+ OPENSSL_assert((minsize & (minsize - 1)) == 0);
+ if ((minsize & (minsize - 1)) != 0)
+ goto err;
+ }
sh.arena_size = size;
sh.minsize = minsize;
@@ -441,16 +482,20 @@ static int sh_init(size_t size, int minsize)
else
pgsize = (size_t)tmppgsize;
}
+#elif defined(_WIN32)
+ GetSystemInfo(&systemInfo);
+ pgsize = (size_t)systemInfo.dwPageSize;
#else
pgsize = PAGE_SIZE;
#endif
sh.map_size = pgsize + sh.arena_size + pgsize;
- if (1) {
-#ifdef MAP_ANON
- sh.map_result = mmap(NULL, sh.map_size,
- PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE|MAP_CONCEAL, -1, 0);
- } else {
-#endif
+
+#if !defined(_WIN32)
+# ifdef MAP_ANON
+ sh.map_result = mmap(NULL, sh.map_size,
+ PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE|MAP_CONCEAL, -1, 0);
+# else
+ {
int fd;
sh.map_result = MAP_FAILED;
@@ -460,8 +505,16 @@ static int sh_init(size_t size, int minsize)
close(fd);
}
}
+# endif
if (sh.map_result == MAP_FAILED)
goto err;
+#else
+ sh.map_result = VirtualAlloc(NULL, sh.map_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+
+ if (sh.map_result == NULL)
+ goto err;
+#endif
+
sh.arena = (char *)(sh.map_result + pgsize);
sh_setbit(sh.arena, 0, sh.bittable);
sh_add_to_list(&sh.freelist[0], sh.arena);
@@ -469,14 +522,24 @@ static int sh_init(size_t size, int minsize)
/* Now try to add guard pages and lock into memory. */
ret = 1;
+#if !defined(_WIN32)
/* Starting guard is already aligned from mmap. */
if (mprotect(sh.map_result, pgsize, PROT_NONE) < 0)
ret = 2;
+#else
+ if (VirtualProtect(sh.map_result, pgsize, PAGE_NOACCESS, &flOldProtect) == FALSE)
+ ret = 2;
+#endif
/* Ending guard page - need to round up to page boundary */
aligned = (pgsize + sh.arena_size + (pgsize - 1)) & ~(pgsize - 1);
+#if !defined(_WIN32)
if (mprotect(sh.map_result + aligned, pgsize, PROT_NONE) < 0)
ret = 2;
+#else
+ if (VirtualProtect(sh.map_result + aligned, pgsize, PAGE_NOACCESS, &flOldProtect) == FALSE)
+ ret = 2;
+#endif
#if defined(OPENSSL_SYS_LINUX) && defined(MLOCK_ONFAULT) && defined(SYS_mlock2)
if (syscall(SYS_mlock2, sh.arena, sh.arena_size, MLOCK_ONFAULT) < 0) {
@@ -487,6 +550,9 @@ static int sh_init(size_t size, int minsize)
ret = 2;
}
}
+#elif defined(_WIN32)
+ if (VirtualLock(sh.arena, sh.arena_size) == FALSE)
+ ret = 2;
#else
if (mlock(sh.arena, sh.arena_size) < 0)
ret = 2;
@@ -508,8 +574,13 @@ static void sh_done(void)
OPENSSL_free(sh.freelist);
OPENSSL_free(sh.bittable);
OPENSSL_free(sh.bitmalloc);
+#if !defined(_WIN32)
if (sh.map_result != MAP_FAILED && sh.map_size)
munmap(sh.map_result, sh.map_size);
+#else
+ if (sh.map_result != NULL && sh.map_size)
+ VirtualFree(sh.map_result, 0, MEM_RELEASE);
+#endif
memset(&sh, 0, sizeof(sh));
}
@@ -649,4 +720,4 @@ static size_t sh_actual_size(char *ptr)
OPENSSL_assert(sh_testbit(ptr, list, sh.bittable));
return sh.arena_size / (ONE << list);
}
-#endif /* OPENSSL_SECURE_MEMORY */
+#endif /* OPENSSL_NO_SECURE_MEMORY */
diff --git a/crypto/mips_arch.h b/crypto/mips_arch.h
index 4ae1a1a9339e..12a27615f14f 100644
--- a/crypto/mips_arch.h
+++ b/crypto/mips_arch.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/modes/asm/aes-gcm-armv8_64.pl b/crypto/modes/asm/aes-gcm-armv8_64.pl
new file mode 100755
index 000000000000..3b9d5b651193
--- /dev/null
+++ b/crypto/modes/asm/aes-gcm-armv8_64.pl
@@ -0,0 +1,5722 @@
+#! /usr/bin/env perl
+# Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+#
+#========================================================================
+# Written by Fangming Fang <fangming.fang@arm.com> for the OpenSSL project,
+# derived from https://github.com/ARM-software/AArch64cryptolib, original
+# author Samuel Lee <Samuel.Lee@arm.com>. The module is, however, dual
+# licensed under OpenSSL and CRYPTOGAMS licenses depending on where you
+# obtain it. For further details see http://www.openssl.org/~appro/cryptogams/.
+#========================================================================
+#
+# Approach - assume we don't want to reload constants, so reserve ~half of vector register file for constants
+#
+# main loop to act on 4 16B blocks per iteration, and then do modulo of the accumulated intermediate hashes from the 4 blocks
+#
+# ____________________________________________________
+# | |
+# | PRE |
+# |____________________________________________________|
+# | | | |
+# | CTR block 4k+8 | AES block 4k+4 | GHASH block 4k+0 |
+# |________________|________________|__________________|
+# | | | |
+# | CTR block 4k+9 | AES block 4k+5 | GHASH block 4k+1 |
+# |________________|________________|__________________|
+# | | | |
+# | CTR block 4k+10| AES block 4k+6 | GHASH block 4k+2 |
+# |________________|________________|__________________|
+# | | | |
+# | CTR block 4k+11| AES block 4k+7 | GHASH block 4k+3 |
+# |________________|____(mostly)____|__________________|
+# | |
+# | MODULO |
+# |____________________________________________________|
+#
+# PRE:
+# Ensure previous generated intermediate hash is aligned and merged with result for GHASH 4k+0
+# EXT low_acc, low_acc, low_acc, #8
+# EOR res_curr (4k+0), res_curr (4k+0), low_acc
+#
+# CTR block:
+# Increment and byte reverse counter in scalar registers and transfer to SIMD registers
+# REV ctr32, rev_ctr32
+# ORR ctr64, constctr96_top32, ctr32, LSL #32
+# INS ctr_next.d[0], constctr96_bottom64 // Keeping this in scalar registers to free up space in SIMD RF
+# INS ctr_next.d[1], ctr64X
+# ADD rev_ctr32, #1
+#
+# AES block:
+# Do AES encryption/decryption on CTR block X and EOR it with input block X. Take 256 bytes key below for example.
+# Doing small trick here of loading input in scalar registers, EORing with last key and then transferring
+# Given we are very constrained in our ASIMD registers this is quite important
+#
+# Encrypt:
+# LDR input_low, [ input_ptr ], #8
+# LDR input_high, [ input_ptr ], #8
+# EOR input_low, k14_low
+# EOR input_high, k14_high
+# INS res_curr.d[0], input_low
+# INS res_curr.d[1], input_high
+# AESE ctr_curr, k0; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k1; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k2; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k3; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k4; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k5; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k6; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k7; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k8; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k9; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k10; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k11; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k12; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k13
+# EOR res_curr, res_curr, ctr_curr
+# ST1 { res_curr.16b }, [ output_ptr ], #16
+#
+# Decrypt:
+# AESE ctr_curr, k0; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k1; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k2; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k3; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k4; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k5; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k6; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k7; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k8; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k9; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k10; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k11; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k12; AESMC ctr_curr, ctr_curr
+# AESE ctr_curr, k13
+# LDR res_curr, [ input_ptr ], #16
+# EOR res_curr, res_curr, ctr_curr
+# MOV output_low, res_curr.d[0]
+# MOV output_high, res_curr.d[1]
+# EOR output_low, k14_low
+# EOR output_high, k14_high
+# STP output_low, output_high, [ output_ptr ], #16
+#
+# GHASH block X:
+# do 128b karatsuba polynomial multiplication on block
+# We only have 64b->128b polynomial multipliers, naively that means we need to do 4 64b multiplies to generate a 128b
+#
+# multiplication:
+# Pmull(A,B) == (Pmull(Ah,Bh)<<128 | Pmull(Al,Bl)) ^ (Pmull(Ah,Bl) ^ Pmull(Al,Bh))<<64
+#
+# The idea behind Karatsuba multiplication is that we can do just 3 64b multiplies:
+# Pmull(A,B) == (Pmull(Ah,Bh)<<128 | Pmull(Al,Bl)) ^ (Pmull(Ah^Al,Bh^Bl) ^ Pmull(Ah,Bh) ^ Pmull(Al,Bl))<<64
+#
+# There is some complication here because the bit order of GHASH's PMULL is reversed compared to elsewhere, so we are
+# multiplying with "twisted" powers of H
+#
+# Note: We can PMULL directly into the acc_x in first GHASH of the loop
+# Note: For scheduling big cores we want to split the processing to happen over two loop iterations - otherwise the critical
+# path latency dominates the performance
+#
+# This has a knock on effect on register pressure, so we have to be a bit more clever with our temporary registers
+# than indicated here
+# REV64 res_curr, res_curr
+# INS t_m.d[0], res_curr.d[1]
+# EOR t_m.8B, t_m.8B, res_curr.8B
+# PMULL2 t_h, res_curr, HX
+# PMULL t_l, res_curr, HX
+# PMULL t_m, t_m, HX_k
+# EOR acc_h, acc_h, t_h
+# EOR acc_l, acc_l, t_l
+# EOR acc_m, acc_m, t_m
+#
+# MODULO: take the partial accumulators (~representing sum of 256b multiplication results), from GHASH and do modulo reduction on them
+# There is some complication here because the bit order of GHASH's PMULL is reversed compared to elsewhere, so we are doing modulo
+# with a reversed constant
+# EOR acc_m, acc_m, acc_h
+# EOR acc_m, acc_m, acc_l // Finish off karatsuba processing
+# PMULL t_mod, acc_h, mod_constant
+# EXT acc_h, acc_h, acc_h, #8
+# EOR acc_m, acc_m, acc_h
+# EOR acc_m, acc_m, t_mod
+# PMULL acc_h, acc_m, mod_constant
+# EXT acc_m, acc_m, acc_m, #8
+# EOR acc_l, acc_l, acc_h
+# EOR acc_l, acc_l, acc_m
+
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate ) or
+die "can't locate arm-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+$input_ptr="x0"; #argument block
+$bit_length="x1";
+$output_ptr="x2";
+$current_tag="x3";
+$counter="x16";
+$cc="x8";
+
+{
+my ($end_input_ptr,$main_end_input_ptr,$input_l0,$input_h0)=map("x$_",(4..7));
+my ($input_l1,$input_h1,$input_l2,$input_h2,$input_l3,$input_h3)=map("x$_",(19..24));
+my ($output_l1,$output_h1,$output_l2,$output_h2,$output_l3,$output_h3)=map("x$_",(19..24));
+my ($output_l0,$output_h0)=map("x$_",(6..7));
+
+my $ctr32w="w9";
+my ($ctr32x,$ctr96_b64x,$ctr96_t32x,$rctr32x,$rk10_l,$rk10_h,$len)=map("x$_",(9..15));
+my ($ctr96_t32w,$rctr32w)=map("w$_",(11..12));
+
+my ($ctr0b,$ctr1b,$ctr2b,$ctr3b,$res0b,$res1b,$res2b,$res3b)=map("v$_.16b",(0..7));
+my ($ctr0,$ctr1,$ctr2,$ctr3,$res0,$res1,$res2,$res3)=map("v$_",(0..7));
+my ($ctr0d,$ctr1d,$ctr2d,$ctr3d,$res0d,$res1d,$res2d,$res3d)=map("d$_",(0..7));
+my ($res0q,$res1q,$res2q,$res3q)=map("q$_",(4..7));
+
+my ($acc_hb,$acc_mb,$acc_lb)=map("v$_.16b",(9..11));
+my ($acc_h,$acc_m,$acc_l)=map("v$_",(9..11));
+my ($acc_hd,$acc_md,$acc_ld)=map("d$_",(9..11));
+
+my ($h1,$h2,$h3,$h4,$h12k,$h34k)=map("v$_",(12..17));
+my ($h1q,$h2q,$h3q,$h4q)=map("q$_",(12..15));
+my ($h1b,$h2b,$h3b,$h4b)=map("v$_.16b",(12..15));
+
+my $t0="v8";
+my $t0d="d8";
+
+my ($t1,$t2,$t3)=map("v$_",(28..30));
+my ($t1d,$t2d,$t3d)=map("d$_",(28..30));
+
+my $t4="v8";
+my $t4d="d8";
+my $t5="v28";
+my $t5d="d28";
+my $t6="v31";
+my $t6d="d31";
+
+my $t7="v4";
+my $t7d="d4";
+my $t8="v29";
+my $t8d="d29";
+my $t9="v30";
+my $t9d="d30";
+
+my ($ctr_t0,$ctr_t1,$ctr_t2,$ctr_t3)=map("v$_",(4..7));
+my ($ctr_t0d,$ctr_t1d,$ctr_t2d,$ctr_t3d)=map("d$_",(4..7));
+my ($ctr_t0b,$ctr_t1b,$ctr_t2b,$ctr_t3b)=map("v$_.16b",(4..7));
+
+my $mod_constantd="d8";
+my $mod_constant="v8";
+my $mod_t="v31";
+
+my ($rk0,$rk1,$rk2,$rk3,$rk4,$rk5,$rk6,$rk7,$rk8,$rk9)=map("v$_.16b",(18..27));
+my ($rk0q,$rk1q,$rk2q,$rk3q,$rk4q,$rk5q,$rk6q,$rk7q,$rk8q,$rk9q)=map("q$_",(18..27));
+my $rk2q1="v20.1q";
+my $rk3q1="v21.1q";
+my $rk4v="v22";
+my $rk4d="d22";
+
+$code=<<___;
+#include "arm_arch.h"
+
+#if __ARM_MAX_ARCH__>=8
+___
+$code.=".arch armv8-a+crypto\n.text\n" if ($flavour =~ /64/);
+$code.=<<___ if ($flavour !~ /64/);
+.fpu neon
+#ifdef __thumb2__
+.syntax unified
+.thumb
+# define INST(a,b,c,d) $_byte c,0xef,a,b
+#else
+.code 32
+# define INST(a,b,c,d) $_byte a,b,c,0xf2
+#endif
+
+.text
+___
+
+#########################################################################################
+# size_t aes_gcm_enc_128_kernel(const unsigned char *in,
+# size_t len,
+# unsigned char *out,
+# const void *key,
+# unsigned char ivec[16],
+# u64 *Xi);
+#
+$code.=<<___;
+.global aes_gcm_enc_128_kernel
+.type aes_gcm_enc_128_kernel,%function
+.align 4
+aes_gcm_enc_128_kernel:
+ cbz x1, .L128_enc_ret
+ stp x19, x20, [sp, #-112]!
+ mov x16, x4
+ mov x8, x5
+ stp x21, x22, [sp, #16]
+ stp x23, x24, [sp, #32]
+ stp d8, d9, [sp, #48]
+ stp d10, d11, [sp, #64]
+ stp d12, d13, [sp, #80]
+ stp d14, d15, [sp, #96]
+
+ ldp $ctr96_b64x, $ctr96_t32x, [$counter] @ ctr96_b64, ctr96_t32
+ ldp $rk10_l, $rk10_h, [$cc, #160] @ load rk10
+
+ ld1 {$acc_lb}, [$current_tag]
+ ext $acc_lb, $acc_lb, $acc_lb, #8
+ rev64 $acc_lb, $acc_lb
+ lsr $main_end_input_ptr, $bit_length, #3 @ byte_len
+ mov $len, $main_end_input_ptr
+
+ ldr $rk9q, [$cc, #144] @ load rk9
+ add $end_input_ptr, $input_ptr, $bit_length, lsr #3 @ end_input_ptr
+ sub $main_end_input_ptr, $main_end_input_ptr, #1 @ byte_len - 1
+
+ lsr $rctr32x, $ctr96_t32x, #32
+ ldr $h4q, [$current_tag, #112] @ load h4l | h4h
+ ext $h4b, $h4b, $h4b, #8
+
+ fmov $ctr1d, $ctr96_b64x @ CTR block 1
+ rev $rctr32w, $rctr32w @ rev_ctr32
+
+ add $rctr32w, $rctr32w, #1 @ increment rev_ctr32
+ orr $ctr96_t32w, $ctr96_t32w, $ctr96_t32w
+ ldr $rk0q, [$cc, #0] @ load rk0
+
+ rev $ctr32w, $rctr32w @ CTR block 1
+ add $rctr32w, $rctr32w, #1 @ CTR block 1
+ fmov $ctr3d, $ctr96_b64x @ CTR block 3
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 1
+ ld1 { $ctr0b}, [$counter] @ special case vector load initial counter so we can start first AES block as quickly as possible
+
+ fmov $ctr1.d[1], $ctr32x @ CTR block 1
+ rev $ctr32w, $rctr32w @ CTR block 2
+
+ fmov $ctr2d, $ctr96_b64x @ CTR block 2
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 2
+ add $rctr32w, $rctr32w, #1 @ CTR block 2
+
+ fmov $ctr2.d[1], $ctr32x @ CTR block 2
+ rev $ctr32w, $rctr32w @ CTR block 3
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 3
+ ldr $rk1q, [$cc, #16] @ load rk1
+
+ add $rctr32w, $rctr32w, #1 @ CTR block 3
+ fmov $ctr3.d[1], $ctr32x @ CTR block 3
+
+ ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+ ext $h3b, $h3b, $h3b, #8
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 0
+ ldr $rk2q, [$cc, #32] @ load rk2
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
+ ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+ ext $h1b, $h1b, $h1b, #8
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 0
+ ldr $rk8q, [$cc, #128] @ load rk8
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 0
+ ldr $rk3q, [$cc, #48] @ load rk3
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 1
+ trn2 $h34k.2d, $h3.2d, $h4.2d @ h4l | h3l
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 1
+ ldr $rk6q, [$cc, #96] @ load rk6
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
+ ldr $rk7q, [$cc, #112] @ load rk7
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 1
+ trn1 $acc_h.2d, $h3.2d, $h4.2d @ h4h | h3h
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 2
+ ldr $rk5q, [$cc, #80] @ load rk5
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 2
+ ldr $h2q, [$current_tag, #64] @ load h2l | h2h
+ ext $h2b, $h2b, $h2b, #8
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 2
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 2
+ eor $h34k.16b, $h34k.16b, $acc_h.16b @ h4k | h3k
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 3
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 3
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 3
+ ldr $rk4q, [$cc, #64] @ load rk4
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 3
+
+ and $main_end_input_ptr, $main_end_input_ptr, #0xffffffffffffffc0 @ number of bytes to be processed in main loop (at least 1 byte must be handled by tail)
+ trn2 $h12k.2d, $h1.2d, $h2.2d @ h2l | h1l
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 4
+ add $main_end_input_ptr, $main_end_input_ptr, $input_ptr
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 4
+ cmp $input_ptr, $main_end_input_ptr @ check if we have <= 4 blocks
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 4
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 5
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 5
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 5
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 6
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 4
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 6
+ trn1 $t0.2d, $h1.2d, $h2.2d @ h2h | h1h
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 6
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 5
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 7
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 7
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 6
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 7
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 8
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 7
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 8
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 8
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 8
+
+ aese $ctr2b, $rk9 @ AES block 2 - round 9
+
+ aese $ctr0b, $rk9 @ AES block 0 - round 9
+
+ eor $h12k.16b, $h12k.16b, $t0.16b @ h2k | h1k
+
+ aese $ctr1b, $rk9 @ AES block 1 - round 9
+
+ aese $ctr3b, $rk9 @ AES block 3 - round 9
+ b.ge .L128_enc_tail @ handle tail
+
+ ldp $input_l0, $input_h0, [$input_ptr, #0] @ AES block 0 - load plaintext
+
+ ldp $input_l2, $input_h2, [$input_ptr, #32] @ AES block 2 - load plaintext
+
+ ldp $input_l1, $input_h1, [$input_ptr, #16] @ AES block 1 - load plaintext
+
+ ldp $input_l3, $input_h3, [$input_ptr, #48] @ AES block 3 - load plaintext
+
+ eor $input_l0, $input_l0, $rk10_l @ AES block 0 - round 10 low
+ eor $input_h0, $input_h0, $rk10_h @ AES block 0 - round 10 high
+
+ eor $input_l2, $input_l2, $rk10_l @ AES block 2 - round 10 low
+ fmov $ctr_t0d, $input_l0 @ AES block 0 - mov low
+
+ eor $input_l1, $input_l1, $rk10_l @ AES block 1 - round 10 low
+ eor $input_h2, $input_h2, $rk10_h @ AES block 2 - round 10 high
+ fmov $ctr_t0.d[1], $input_h0 @ AES block 0 - mov high
+
+ fmov $ctr_t1d, $input_l1 @ AES block 1 - mov low
+ eor $input_h1, $input_h1, $rk10_h @ AES block 1 - round 10 high
+
+ eor $input_l3, $input_l3, $rk10_l @ AES block 3 - round 10 low
+ fmov $ctr_t1.d[1], $input_h1 @ AES block 1 - mov high
+
+ fmov $ctr_t2d, $input_l2 @ AES block 2 - mov low
+ eor $input_h3, $input_h3, $rk10_h @ AES block 3 - round 10 high
+ rev $ctr32w, $rctr32w @ CTR block 4
+
+ fmov $ctr_t2.d[1], $input_h2 @ AES block 2 - mov high
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4
+
+ eor $res0b, $ctr_t0b, $ctr0b @ AES block 0 - result
+ fmov $ctr0d, $ctr96_b64x @ CTR block 4
+ add $rctr32w, $rctr32w, #1 @ CTR block 4
+
+ fmov $ctr0.d[1], $ctr32x @ CTR block 4
+ rev $ctr32w, $rctr32w @ CTR block 5
+
+ eor $res1b, $ctr_t1b, $ctr1b @ AES block 1 - result
+ fmov $ctr1d, $ctr96_b64x @ CTR block 5
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 5
+
+ add $rctr32w, $rctr32w, #1 @ CTR block 5
+ add $input_ptr, $input_ptr, #64 @ AES input_ptr update
+ fmov $ctr1.d[1], $ctr32x @ CTR block 5
+
+ fmov $ctr_t3d, $input_l3 @ AES block 3 - mov low
+ rev $ctr32w, $rctr32w @ CTR block 6
+ st1 { $res0b}, [$output_ptr], #16 @ AES block 0 - store result
+
+ fmov $ctr_t3.d[1], $input_h3 @ AES block 3 - mov high
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 6
+
+ add $rctr32w, $rctr32w, #1 @ CTR block 6
+ eor $res2b, $ctr_t2b, $ctr2b @ AES block 2 - result
+ st1 { $res1b}, [$output_ptr], #16 @ AES block 1 - store result
+
+ fmov $ctr2d, $ctr96_b64x @ CTR block 6
+ cmp $input_ptr, $main_end_input_ptr @ check if we have <= 8 blocks
+
+ fmov $ctr2.d[1], $ctr32x @ CTR block 6
+ rev $ctr32w, $rctr32w @ CTR block 7
+ st1 { $res2b}, [$output_ptr], #16 @ AES block 2 - store result
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 7
+
+ eor $res3b, $ctr_t3b, $ctr3b @ AES block 3 - result
+ st1 { $res3b}, [$output_ptr], #16 @ AES block 3 - store result
+ b.ge .L128_enc_prepretail @ do prepretail
+
+ .L128_enc_main_loop: @ main loop start
+ ldp $input_l3, $input_h3, [$input_ptr, #48] @ AES block 4k+3 - load plaintext
+ rev64 $res0b, $res0b @ GHASH block 4k (only t0 is free)
+ rev64 $res2b, $res2b @ GHASH block 4k+2 (t0, t1, and t2 free)
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
+ fmov $ctr3d, $ctr96_b64x @ CTR block 4k+3
+
+ ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
+ rev64 $res1b, $res1b @ GHASH block 4k+1 (t0 and t1 free)
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+3
+ fmov $ctr3.d[1], $ctr32x @ CTR block 4k+3
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
+ mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
+ mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
+ eor $res0b, $res0b, $acc_lb @ PRE 1
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
+ eor $input_h3, $input_h3, $rk10_h @ AES block 4k+3 - round 10 high
+
+ pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
+ eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
+ ldp $input_l0, $input_h0, [$input_ptr, #0] @ AES block 4k+4 - load plaintext
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
+ rev $ctr32w, $rctr32w @ CTR block 4k+8
+
+ eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
+ mov $t0d, $res0.d[1] @ GHASH block 4k - mid
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+8
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+8
+ mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
+ eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
+
+ pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
+
+ pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
+ rev64 $res3b, $res3b @ GHASH block 4k+3 (t0, t1, t2 and t3 free)
+
+ pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
+
+ pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
+ ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
+
+ pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
+ eor $input_h0, $input_h0, $rk10_h @ AES block 4k+4 - round 10 high
+
+ eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
+ mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
+ eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
+ eor $input_l0, $input_l0, $rk10_l @ AES block 4k+4 - round 10 low
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
+ eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
+
+ pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
+ eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
+
+ pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
+
+ pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
+ movi $mod_constant.8b, #0xc2
+
+ pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
+ eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
+ eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
+ ldp $input_l1, $input_h1, [$input_ptr, #16] @ AES block 4k+5 - load plaintext
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
+ eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
+ ldp $input_l2, $input_h2, [$input_ptr, #32] @ AES block 4k+6 - load plaintext
+
+ pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
+ eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
+ eor $input_l1, $input_l1, $rk10_l @ AES block 4k+5 - round 10 low
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
+ eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
+ eor $input_l3, $input_l3, $rk10_l @ AES block 4k+3 - round 10 low
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
+ eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
+
+ fmov $ctr_t0d, $input_l0 @ AES block 4k+4 - mov low
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
+ fmov $ctr_t0.d[1], $input_h0 @ AES block 4k+4 - mov high
+
+ add $input_ptr, $input_ptr, #64 @ AES input_ptr update
+ fmov $ctr_t3d, $input_l3 @ AES block 4k+3 - mov low
+ ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
+ fmov $ctr_t1d, $input_l1 @ AES block 4k+5 - mov low
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
+ eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
+ eor $input_h1, $input_h1, $rk10_h @ AES block 4k+5 - round 10 high
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
+ fmov $ctr_t1.d[1], $input_h1 @ AES block 4k+5 - mov high
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
+ fmov $ctr_t3.d[1], $input_h3 @ AES block 4k+3 - mov high
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
+ cmp $input_ptr, $main_end_input_ptr @ LOOP CONTROL
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
+ eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
+
+ aese $ctr0b, $rk9 @ AES block 4k+4 - round 9
+ eor $input_l2, $input_l2, $rk10_l @ AES block 4k+6 - round 10 low
+ eor $input_h2, $input_h2, $rk10_h @ AES block 4k+6 - round 10 high
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
+ fmov $ctr_t2d, $input_l2 @ AES block 4k+6 - mov low
+
+ aese $ctr1b, $rk9 @ AES block 4k+5 - round 9
+ fmov $ctr_t2.d[1], $input_h2 @ AES block 4k+6 - mov high
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
+ eor $res0b, $ctr_t0b, $ctr0b @ AES block 4k+4 - result
+
+ fmov $ctr0d, $ctr96_b64x @ CTR block 4k+8
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
+
+ fmov $ctr0.d[1], $ctr32x @ CTR block 4k+8
+ rev $ctr32w, $rctr32w @ CTR block 4k+9
+ eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
+ eor $res1b, $ctr_t1b, $ctr1b @ AES block 4k+5 - result
+
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+9
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+9
+ fmov $ctr1d, $ctr96_b64x @ CTR block 4k+9
+
+ pmull $acc_h.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
+ fmov $ctr1.d[1], $ctr32x @ CTR block 4k+9
+ rev $ctr32w, $rctr32w @ CTR block 4k+10
+
+ aese $ctr2b, $rk9 @ AES block 4k+6 - round 9
+ st1 { $res0b}, [$output_ptr], #16 @ AES block 4k+4 - store result
+ eor $res2b, $ctr_t2b, $ctr2b @ AES block 4k+6 - result
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+10
+
+ aese $ctr3b, $rk9 @ AES block 4k+7 - round 9
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+10
+ ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
+ fmov $ctr2d, $ctr96_b64x @ CTR block 4k+10
+
+ eor $acc_lb, $acc_lb, $acc_hb @ MODULO - fold into low
+ st1 { $res1b}, [$output_ptr], #16 @ AES block 4k+5 - store result
+
+ fmov $ctr2.d[1], $ctr32x @ CTR block 4k+10
+ st1 { $res2b}, [$output_ptr], #16 @ AES block 4k+6 - store result
+ rev $ctr32w, $rctr32w @ CTR block 4k+11
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+11
+ eor $res3b, $ctr_t3b, $ctr3b @ AES block 4k+3 - result
+
+ eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
+ st1 { $res3b}, [$output_ptr], #16 @ AES block 4k+3 - store result
+ b.lt .L128_enc_main_loop
+
+ .L128_enc_prepretail: @ PREPRETAIL
+ rev64 $res0b, $res0b @ GHASH block 4k (only t0 is free)
+ fmov $ctr3d, $ctr96_b64x @ CTR block 4k+3
+ rev64 $res1b, $res1b @ GHASH block 4k+1 (t0 and t1 free)
+
+ ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+3
+ fmov $ctr3.d[1], $ctr32x @ CTR block 4k+3
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
+ rev64 $res2b, $res2b @ GHASH block 4k+2 (t0, t1, and t2 free)
+
+ pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
+
+ rev64 $res3b, $res3b @ GHASH block 4k+3 (t0, t1, t2 and t3 free)
+ eor $res0b, $res0b, $acc_lb @ PRE 1
+
+ pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
+ mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
+ mov $t0d, $res0.d[1] @ GHASH block 4k - mid
+
+ mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
+ mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
+ eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
+
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
+ eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
+
+ pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
+ eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
+
+ pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
+ ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
+
+ eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
+ mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
+ eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
+
+ pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
+
+ pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
+ eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
+
+ pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
+
+ pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
+ eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
+
+ pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
+ movi $mod_constant.8b, #0xc2
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
+ eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
+
+ pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
+ eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
+ eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
+
+ eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
+ eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
+
+ pmull $t1.1q, $acc_h.1d, $mod_constant.1d
+ eor $acc_mb, $acc_mb, $acc_hb @ karatsuba tidy up
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
+ ext $acc_hb, $acc_hb, $acc_hb, #8
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
+ eor $acc_mb, $acc_mb, $acc_lb
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
+ eor $acc_mb, $acc_mb, $t1.16b
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
+ eor $acc_mb, $acc_mb, $acc_hb
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
+
+ pmull $t1.1q, $acc_m.1d, $mod_constant.1d
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
+ ext $acc_mb, $acc_mb, $acc_mb, #8
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
+ eor $acc_lb, $acc_lb, $t1.16b
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
+
+ aese $ctr3b, $rk9 @ AES block 4k+7 - round 9
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
+
+ aese $ctr0b, $rk9 @ AES block 4k+4 - round 9
+
+ aese $ctr1b, $rk9 @ AES block 4k+5 - round 9
+ eor $acc_lb, $acc_lb, $acc_mb
+
+ aese $ctr2b, $rk9 @ AES block 4k+6 - round 9
+ .L128_enc_tail: @ TAIL
+
+ sub $main_end_input_ptr, $end_input_ptr, $input_ptr @ main_end_input_ptr is number of bytes left to process
+ ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES block 4k+4 - load plaintext
+
+ cmp $main_end_input_ptr, #48
+
+ ext $t0.16b, $acc_lb, $acc_lb, #8 @ prepare final partial tag
+ eor $input_l0, $input_l0, $rk10_l @ AES block 4k+4 - round 10 low
+ eor $input_h0, $input_h0, $rk10_h @ AES block 4k+4 - round 10 high
+
+ fmov $ctr_t0d, $input_l0 @ AES block 4k+4 - mov low
+
+ fmov $ctr_t0.d[1], $input_h0 @ AES block 4k+4 - mov high
+
+ eor $res1b, $ctr_t0b, $ctr0b @ AES block 4k+4 - result
+
+ b.gt .L128_enc_blocks_more_than_3
+
+ sub $rctr32w, $rctr32w, #1
+ movi $acc_l.8b, #0
+ mov $ctr3b, $ctr2b
+
+ cmp $main_end_input_ptr, #32
+ mov $ctr2b, $ctr1b
+ movi $acc_h.8b, #0
+
+ movi $acc_m.8b, #0
+ b.gt .L128_enc_blocks_more_than_2
+
+ mov $ctr3b, $ctr1b
+ cmp $main_end_input_ptr, #16
+
+ sub $rctr32w, $rctr32w, #1
+ b.gt .L128_enc_blocks_more_than_1
+
+ sub $rctr32w, $rctr32w, #1
+ b .L128_enc_blocks_less_than_1
+ .L128_enc_blocks_more_than_3: @ blocks left > 3
+ st1 { $res1b}, [$output_ptr], #16 @ AES final-3 block - store result
+
+ ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final-2 block - load input low & high
+
+ rev64 $res0b, $res1b @ GHASH final-3 block
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+ eor $input_h0, $input_h0, $rk10_h @ AES final-2 block - round 10 high
+ eor $input_l0, $input_l0, $rk10_l @ AES final-2 block - round 10 low
+
+ fmov $res1d, $input_l0 @ AES final-2 block - mov low
+
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+ fmov $res1.d[1], $input_h0 @ AES final-2 block - mov high
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH final-3 block - low
+ mov $rk4d, $res0.d[1] @ GHASH final-3 block - mid
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH final-3 block - high
+
+ mov $acc_md, $h34k.d[1] @ GHASH final-3 block - mid
+
+ eor $res1b, $res1b, $ctr1b @ AES final-2 block - result
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-3 block - mid
+
+ pmull $acc_m.1q, $rk4v.1d, $acc_m.1d @ GHASH final-3 block - mid
+ .L128_enc_blocks_more_than_2: @ blocks left > 2
+
+ st1 { $res1b}, [$output_ptr], #16 @ AES final-2 block - store result
+
+ rev64 $res0b, $res1b @ GHASH final-2 block
+ ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final-1 block - load input low & high
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ eor $input_l0, $input_l0, $rk10_l @ AES final-1 block - round 10 low
+
+ fmov $res1d, $input_l0 @ AES final-1 block - mov low
+ eor $input_h0, $input_h0, $rk10_h @ AES final-1 block - round 10 high
+
+ pmull2 $rk2q1, $res0.2d, $h3.2d @ GHASH final-2 block - high
+ fmov $res1.d[1], $input_h0 @ AES final-1 block - mov high
+
+ mov $rk4d, $res0.d[1] @ GHASH final-2 block - mid
+
+ pmull $rk3q1, $res0.1d, $h3.1d @ GHASH final-2 block - low
+
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final-2 block - high
+
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-2 block - mid
+
+ eor $res1b, $res1b, $ctr2b @ AES final-1 block - result
+
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final-2 block - low
+
+ pmull $rk4v.1q, $rk4v.1d, $h34k.1d @ GHASH final-2 block - mid
+
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+
+ eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-2 block - mid
+ .L128_enc_blocks_more_than_1: @ blocks left > 1
+
+ st1 { $res1b}, [$output_ptr], #16 @ AES final-1 block - store result
+
+ rev64 $res0b, $res1b @ GHASH final-1 block
+ ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final block - load input low & high
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ eor $input_h0, $input_h0, $rk10_h @ AES final block - round 10 high
+ eor $input_l0, $input_l0, $rk10_l @ AES final block - round 10 low
+
+ fmov $res1d, $input_l0 @ AES final block - mov low
+
+ pmull2 $rk2q1, $res0.2d, $h2.2d @ GHASH final-1 block - high
+ fmov $res1.d[1], $input_h0 @ AES final block - mov high
+
+ mov $rk4d, $res0.d[1] @ GHASH final-1 block - mid
+
+ pmull $rk3q1, $res0.1d, $h2.1d @ GHASH final-1 block - low
+
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-1 block - mid
+
+ eor $res1b, $res1b, $ctr3b @ AES final block - result
+
+ ins $rk4v.d[1], $rk4v.d[0] @ GHASH final-1 block - mid
+
+ pmull2 $rk4v.1q, $rk4v.2d, $h12k.2d @ GHASH final-1 block - mid
+
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final-1 block - low
+
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final-1 block - high
+
+ eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-1 block - mid
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+ .L128_enc_blocks_less_than_1: @ blocks left <= 1
+
+ and $bit_length, $bit_length, #127 @ bit_length %= 128
+ mvn $rk10_l, xzr @ rk10_l = 0xffffffffffffffff
+
+ mvn $rk10_h, xzr @ rk10_h = 0xffffffffffffffff
+ sub $bit_length, $bit_length, #128 @ bit_length -= 128
+
+ neg $bit_length, $bit_length @ bit_length = 128 - #bits in input (in range [1,128])
+
+ and $bit_length, $bit_length, #127 @ bit_length %= 128
+
+ lsr $rk10_h, $rk10_h, $bit_length @ rk10_h is mask for top 64b of last block
+ cmp $bit_length, #64
+
+ csel $input_l0, $rk10_l, $rk10_h, lt
+ csel $input_h0, $rk10_h, xzr, lt
+
+ fmov $ctr0d, $input_l0 @ ctr0b is mask for last block
+
+ fmov $ctr0.d[1], $input_h0
+
+ and $res1b, $res1b, $ctr0b @ possibly partial last block has zeroes in highest bits
+
+ rev64 $res0b, $res1b @ GHASH final block
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ mov $t0d, $res0.d[1] @ GHASH final block - mid
+
+ pmull $rk3q1, $res0.1d, $h1.1d @ GHASH final block - low
+ ld1 { $rk0}, [$output_ptr] @ load existing bytes where the possibly partial last block is to be stored
+
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH final block - mid
+
+ rev $ctr32w, $rctr32w
+
+ pmull2 $rk2q1, $res0.2d, $h1.2d @ GHASH final block - high
+
+ pmull $t0.1q, $t0.1d, $h12k.1d @ GHASH final block - mid
+
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final block - low
+
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final block - high
+
+ eor $acc_mb, $acc_mb, $t0.16b @ GHASH final block - mid
+ movi $mod_constant.8b, #0xc2
+
+ eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
+
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
+
+ pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
+
+ ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
+
+ eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
+
+ eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
+
+ pmull $acc_h.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
+
+ ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
+
+ bif $res1b, $rk0, $ctr0b @ insert existing bytes in top end of result before storing
+
+ eor $acc_lb, $acc_lb, $acc_hb @ MODULO - fold into low
+ st1 { $res1b}, [$output_ptr] @ store all 16B
+
+ str $ctr32w, [$counter, #12] @ store the updated counter
+
+ eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
+ ext $acc_lb, $acc_lb, $acc_lb, #8
+ rev64 $acc_lb, $acc_lb
+ mov x0, $len
+ st1 { $acc_l.16b }, [$current_tag]
+ ldp x21, x22, [sp, #16]
+ ldp x23, x24, [sp, #32]
+ ldp d8, d9, [sp, #48]
+ ldp d10, d11, [sp, #64]
+ ldp d12, d13, [sp, #80]
+ ldp d14, d15, [sp, #96]
+ ldp x19, x20, [sp], #112
+ ret
+
+.L128_enc_ret:
+ mov w0, #0x0
+ ret
+.size aes_gcm_enc_128_kernel,.-aes_gcm_enc_128_kernel
+___
+
+#########################################################################################
+# size_t aes_gcm_dec_128_kernel(const unsigned char *in,
+# size_t len,
+# unsigned char *out,
+# const void *key,
+# unsigned char ivec[16],
+# u64 *Xi);
+#
+$code.=<<___;
+.global aes_gcm_dec_128_kernel
+.type aes_gcm_dec_128_kernel,%function
+.align 4
+aes_gcm_dec_128_kernel:
+ cbz x1, .L128_dec_ret
+ stp x19, x20, [sp, #-112]!
+ mov x16, x4
+ mov x8, x5
+ stp x21, x22, [sp, #16]
+ stp x23, x24, [sp, #32]
+ stp d8, d9, [sp, #48]
+ stp d10, d11, [sp, #64]
+ stp d12, d13, [sp, #80]
+ stp d14, d15, [sp, #96]
+
+ lsr $main_end_input_ptr, $bit_length, #3 @ byte_len
+ mov $len, $main_end_input_ptr
+ ldp $ctr96_b64x, $ctr96_t32x, [$counter] @ ctr96_b64, ctr96_t32
+
+ sub $main_end_input_ptr, $main_end_input_ptr, #1 @ byte_len - 1
+ ldr $rk0q, [$cc, #0] @ load rk0
+
+ and $main_end_input_ptr, $main_end_input_ptr, #0xffffffffffffffc0 @ number of bytes to be processed in main loop (at least 1 byte must be handled by tail)
+ ld1 { $ctr0b}, [$counter] @ special case vector load initial counter so we can start first AES block as quickly as possible
+
+ ldr $h2q, [$current_tag, #64] @ load h2l | h2h
+ ext $h2b, $h2b, $h2b, #8
+
+ lsr $rctr32x, $ctr96_t32x, #32
+ fmov $ctr2d, $ctr96_b64x @ CTR block 2
+
+ ldr $rk1q, [$cc, #16] @ load rk1
+ orr $ctr96_t32w, $ctr96_t32w, $ctr96_t32w
+ rev $rctr32w, $rctr32w @ rev_ctr32
+
+ fmov $ctr1d, $ctr96_b64x @ CTR block 1
+ add $rctr32w, $rctr32w, #1 @ increment rev_ctr32
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 0
+ rev $ctr32w, $rctr32w @ CTR block 1
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 1
+ ldr $rk2q, [$cc, #32] @ load rk2
+ add $rctr32w, $rctr32w, #1 @ CTR block 1
+
+ fmov $ctr1.d[1], $ctr32x @ CTR block 1
+ rev $ctr32w, $rctr32w @ CTR block 2
+ add $rctr32w, $rctr32w, #1 @ CTR block 2
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 1
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 2
+
+ fmov $ctr2.d[1], $ctr32x @ CTR block 2
+ rev $ctr32w, $rctr32w @ CTR block 3
+
+ fmov $ctr3d, $ctr96_b64x @ CTR block 3
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 3
+ add $rctr32w, $rctr32w, #1 @ CTR block 3
+
+ fmov $ctr3.d[1], $ctr32x @ CTR block 3
+ add $end_input_ptr, $input_ptr, $bit_length, lsr #3 @ end_input_ptr
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 0
+ ldr $rk3q, [$cc, #48] @ load rk3
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 2
+ ldr $rk6q, [$cc, #96] @ load rk6
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
+ ldr $rk7q, [$cc, #112] @ load rk7
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
+ ldr $rk4q, [$cc, #64] @ load rk4
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 0
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 1
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 2
+ ldp $rk10_l, $rk10_h, [$cc, #160] @ load rk10
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 1
+ ld1 { $acc_lb}, [$current_tag]
+ ext $acc_lb, $acc_lb, $acc_lb, #8
+ rev64 $acc_lb, $acc_lb
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 3
+ ldr $rk5q, [$cc, #80] @ load rk5
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 3
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 2
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 2
+ ldr $rk9q, [$cc, #144] @ load rk9
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 4
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 3
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 3
+ ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+ ext $h3b, $h3b, $h3b, #8
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 4
+ ldr $rk8q, [$cc, #128] @ load rk8
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 5
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 4
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 4
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 5
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 5
+ ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+ ext $h1b, $h1b, $h1b, #8
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 5
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 6
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 6
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 6
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 6
+ trn1 $t0.2d, $h1.2d, $h2.2d @ h2h | h1h
+
+ ldr $h4q, [$current_tag, #112] @ load h4l | h4h
+ ext $h4b, $h4b, $h4b, #8
+ trn2 $h12k.2d, $h1.2d, $h2.2d @ h2l | h1l
+ add $main_end_input_ptr, $main_end_input_ptr, $input_ptr
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 7
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 7
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 7
+ eor $h12k.16b, $h12k.16b, $t0.16b @ h2k | h1k
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 7
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 8
+ trn2 $h34k.2d, $h3.2d, $h4.2d @ h4l | h3l
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 8
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 8
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 8
+ trn1 $acc_h.2d, $h3.2d, $h4.2d @ h4h | h3h
+
+ aese $ctr2b, $rk9 @ AES block 2 - round 9
+
+ aese $ctr3b, $rk9 @ AES block 3 - round 9
+
+ aese $ctr0b, $rk9 @ AES block 0 - round 9
+ cmp $input_ptr, $main_end_input_ptr @ check if we have <= 4 blocks
+
+ aese $ctr1b, $rk9 @ AES block 1 - round 9
+ eor $h34k.16b, $h34k.16b, $acc_h.16b @ h4k | h3k
+ b.ge .L128_dec_tail @ handle tail
+
+ ldr $res1q, [$input_ptr, #16] @ AES block 1 - load ciphertext
+
+ ldr $res0q, [$input_ptr, #0] @ AES block 0 - load ciphertext
+
+ eor $ctr1b, $res1b, $ctr1b @ AES block 1 - result
+ ldr $res2q, [$input_ptr, #32] @ AES block 2 - load ciphertext
+
+ eor $ctr0b, $res0b, $ctr0b @ AES block 0 - result
+ rev64 $res0b, $res0b @ GHASH block 0
+ rev $ctr32w, $rctr32w @ CTR block 4
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4
+ add $rctr32w, $rctr32w, #1 @ CTR block 4
+ ldr $res3q, [$input_ptr, #48] @ AES block 3 - load ciphertext
+
+ rev64 $res1b, $res1b @ GHASH block 1
+ add $input_ptr, $input_ptr, #64 @ AES input_ptr update
+ mov $output_l1, $ctr1.d[0] @ AES block 1 - mov low
+
+ mov $output_h1, $ctr1.d[1] @ AES block 1 - mov high
+
+ mov $output_l0, $ctr0.d[0] @ AES block 0 - mov low
+ cmp $input_ptr, $main_end_input_ptr @ check if we have <= 8 blocks
+
+ mov $output_h0, $ctr0.d[1] @ AES block 0 - mov high
+
+ fmov $ctr0d, $ctr96_b64x @ CTR block 4
+
+ fmov $ctr0.d[1], $ctr32x @ CTR block 4
+ rev $ctr32w, $rctr32w @ CTR block 5
+ eor $output_l1, $output_l1, $rk10_l @ AES block 1 - round 10 low
+
+ fmov $ctr1d, $ctr96_b64x @ CTR block 5
+ add $rctr32w, $rctr32w, #1 @ CTR block 5
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 5
+
+ fmov $ctr1.d[1], $ctr32x @ CTR block 5
+ rev $ctr32w, $rctr32w @ CTR block 6
+ add $rctr32w, $rctr32w, #1 @ CTR block 6
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 6
+
+ eor $output_h1, $output_h1, $rk10_h @ AES block 1 - round 10 high
+ eor $output_l0, $output_l0, $rk10_l @ AES block 0 - round 10 low
+ eor $ctr2b, $res2b, $ctr2b @ AES block 2 - result
+
+ eor $output_h0, $output_h0, $rk10_h @ AES block 0 - round 10 high
+ stp $output_l0, $output_h0, [$output_ptr], #16 @ AES block 0 - store result
+
+ stp $output_l1, $output_h1, [$output_ptr], #16 @ AES block 1 - store result
+ b.ge .L128_dec_prepretail @ do prepretail
+
+ .L128_dec_main_loop: @ main loop start
+ eor $ctr3b, $res3b, $ctr3b @ AES block 4k+3 - result
+ ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
+ mov $output_l2, $ctr2.d[0] @ AES block 4k+2 - mov low
+
+ pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
+ mov $output_h2, $ctr2.d[1] @ AES block 4k+2 - mov high
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
+ fmov $ctr2d, $ctr96_b64x @ CTR block 4k+6
+
+ rev64 $res2b, $res2b @ GHASH block 4k+2
+ fmov $ctr2.d[1], $ctr32x @ CTR block 4k+6
+ rev $ctr32w, $rctr32w @ CTR block 4k+7
+
+ mov $output_l3, $ctr3.d[0] @ AES block 4k+3 - mov low
+ eor $res0b, $res0b, $acc_lb @ PRE 1
+ mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
+ rev64 $res3b, $res3b @ GHASH block 4k+3
+
+ pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
+ mov $output_h3, $ctr3.d[1] @ AES block 4k+3 - mov high
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+7
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
+ fmov $ctr3d, $ctr96_b64x @ CTR block 4k+7
+ eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
+ fmov $ctr3.d[1], $ctr32x @ CTR block 4k+7
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
+ mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
+ eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
+
+ pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
+ mov $t0d, $res0.d[1] @ GHASH block 4k - mid
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
+ eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
+
+ pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
+ eor $output_l3, $output_l3, $rk10_l @ AES block 4k+3 - round 10 low
+
+ pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
+ eor $output_h2, $output_h2, $rk10_h @ AES block 4k+2 - round 10 high
+ mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
+ eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
+
+ pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
+ eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
+ eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
+
+ pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
+ ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
+
+ pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
+ mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
+ eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
+
+ pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
+ eor $output_h3, $output_h3, $rk10_h @ AES block 4k+3 - round 10 high
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
+ eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
+ eor $output_l2, $output_l2, $rk10_l @ AES block 4k+2 - round 10 low
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
+ movi $mod_constant.8b, #0xc2
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
+ eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
+ eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
+ stp $output_l2, $output_h2, [$output_ptr], #16 @ AES block 4k+2 - store result
+
+ pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
+ eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
+ ldr $res0q, [$input_ptr, #0] @ AES block 4k+4 - load ciphertext
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+7
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
+ eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
+ stp $output_l3, $output_h3, [$output_ptr], #16 @ AES block 4k+3 - store result
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
+ eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
+ rev $ctr32w, $rctr32w @ CTR block 4k+8
+
+ pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
+ ldr $res1q, [$input_ptr, #16] @ AES block 4k+5 - load ciphertext
+ ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
+
+ aese $ctr0b, $rk9 @ AES block 4k+4 - round 9
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+8
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
+ eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
+
+ aese $ctr1b, $rk9 @ AES block 4k+5 - round 9
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
+ eor $ctr0b, $res0b, $ctr0b @ AES block 4k+4 - result
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
+ ldr $res2q, [$input_ptr, #32] @ AES block 4k+6 - load ciphertext
+
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+8
+ eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
+ eor $ctr1b, $res1b, $ctr1b @ AES block 4k+5 - result
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
+ ldr $res3q, [$input_ptr, #48] @ AES block 4k+3 - load ciphertext
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
+ add $input_ptr, $input_ptr, #64 @ AES input_ptr update
+
+ rev64 $res1b, $res1b @ GHASH block 4k+5
+ eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
+ mov $output_h0, $ctr0.d[1] @ AES block 4k+4 - mov high
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
+ mov $output_l0, $ctr0.d[0] @ AES block 4k+4 - mov low
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
+ fmov $ctr0d, $ctr96_b64x @ CTR block 4k+8
+
+ pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
+ fmov $ctr0.d[1], $ctr32x @ CTR block 4k+8
+ rev $ctr32w, $rctr32w @ CTR block 4k+9
+
+ aese $ctr2b, $rk9 @ AES block 4k+6 - round 9
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+9
+ ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
+ eor $output_h0, $output_h0, $rk10_h @ AES block 4k+4 - round 10 high
+
+ eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
+ mov $output_h1, $ctr1.d[1] @ AES block 4k+5 - mov high
+ eor $output_l0, $output_l0, $rk10_l @ AES block 4k+4 - round 10 low
+
+ eor $ctr2b, $res2b, $ctr2b @ AES block 4k+6 - result
+ mov $output_l1, $ctr1.d[0] @ AES block 4k+5 - mov low
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+9
+
+ aese $ctr3b, $rk9 @ AES block 4k+7 - round 9
+ fmov $ctr1d, $ctr96_b64x @ CTR block 4k+9
+ cmp $input_ptr, $main_end_input_ptr @ LOOP CONTROL
+
+ rev64 $res0b, $res0b @ GHASH block 4k+4
+ eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
+ fmov $ctr1.d[1], $ctr32x @ CTR block 4k+9
+
+ rev $ctr32w, $rctr32w @ CTR block 4k+10
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+10
+
+ eor $output_h1, $output_h1, $rk10_h @ AES block 4k+5 - round 10 high
+ stp $output_l0, $output_h0, [$output_ptr], #16 @ AES block 4k+4 - store result
+
+ eor $output_l1, $output_l1, $rk10_l @ AES block 4k+5 - round 10 low
+ stp $output_l1, $output_h1, [$output_ptr], #16 @ AES block 4k+5 - store result
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+10
+ b.lt L128_dec_main_loop
+
+ .L128_dec_prepretail: @ PREPRETAIL
+ ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
+ mov $output_l2, $ctr2.d[0] @ AES block 4k+2 - mov low
+ mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
+ eor $ctr3b, $res3b, $ctr3b @ AES block 4k+3 - result
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
+ mov $output_h2, $ctr2.d[1] @ AES block 4k+2 - mov high
+
+ eor $res0b, $res0b, $acc_lb @ PRE 1
+ fmov $ctr2d, $ctr96_b64x @ CTR block 4k+6
+ rev64 $res2b, $res2b @ GHASH block 4k+2
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
+ fmov $ctr2.d[1], $ctr32x @ CTR block 4k+6
+
+ rev $ctr32w, $rctr32w @ CTR block 4k+7
+ mov $output_l3, $ctr3.d[0] @ AES block 4k+3 - mov low
+ eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
+ mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
+ mov $output_h3, $ctr3.d[1] @ AES block 4k+3 - mov high
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
+ mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+7
+
+ pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
+ mov $t0d, $res0.d[1] @ GHASH block 4k - mid
+ fmov $ctr3d, $ctr96_b64x @ CTR block 4k+7
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
+ fmov $ctr3.d[1], $ctr32x @ CTR block 4k+7
+
+ pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
+ eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
+
+ rev64 $res3b, $res3b @ GHASH block 4k+3
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
+ ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
+
+ pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
+
+ pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
+ eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
+
+ pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
+
+ pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
+ eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
+
+ eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
+
+ pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
+
+ pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
+ mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
+ eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
+
+ pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
+
+ eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
+ movi $mod_constant.8b, #0xc2
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
+ eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
+
+ eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
+ eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
+ eor $output_l3, $output_l3, $rk10_l @ AES block 4k+3 - round 10 low
+
+ pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
+ eor $output_l2, $output_l2, $rk10_l @ AES block 4k+2 - round 10 low
+ eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
+ eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
+ eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
+ eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
+
+ pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
+ ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
+ eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
+ eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
+
+ aese $ctr1b, $rk9 @ AES block 4k+5 - round 9
+
+ pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
+ eor $output_h3, $output_h3, $rk10_h @ AES block 4k+3 - round 10 high
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
+ ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
+ eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
+ eor $output_h2, $output_h2, $rk10_h @ AES block 4k+2 - round 10 high
+
+ aese $ctr0b, $rk9 @ AES block 4k+4 - round 9
+ stp $output_l2, $output_h2, [$output_ptr], #16 @ AES block 4k+2 - store result
+
+ aese $ctr2b, $rk9 @ AES block 4k+6 - round 9
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+7
+ stp $output_l3, $output_h3, [$output_ptr], #16 @ AES block 4k+3 - store result
+
+ aese $ctr3b, $rk9 @ AES block 4k+7 - round 9
+ eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
+ .L128_dec_tail: @ TAIL
+
+ sub $main_end_input_ptr, $end_input_ptr, $input_ptr @ main_end_input_ptr is number of bytes left to process
+ ld1 { $res1b}, [$input_ptr], #16 @ AES block 4k+4 - load ciphertext
+
+ eor $ctr0b, $res1b, $ctr0b @ AES block 4k+4 - result
+
+ mov $output_h0, $ctr0.d[1] @ AES block 4k+4 - mov high
+
+ mov $output_l0, $ctr0.d[0] @ AES block 4k+4 - mov low
+
+ cmp $main_end_input_ptr, #48
+
+ eor $output_h0, $output_h0, $rk10_h @ AES block 4k+4 - round 10 high
+
+ ext $t0.16b, $acc_lb, $acc_lb, #8 @ prepare final partial tag
+ eor $output_l0, $output_l0, $rk10_l @ AES block 4k+4 - round 10 low
+ b.gt .L128_dec_blocks_more_than_3
+
+ mov $ctr3b, $ctr2b
+ sub $rctr32w, $rctr32w, #1
+ movi $acc_l.8b, #0
+
+ movi $acc_h.8b, #0
+ mov $ctr2b, $ctr1b
+
+ movi $acc_m.8b, #0
+ cmp $main_end_input_ptr, #32
+ b.gt .L128_dec_blocks_more_than_2
+
+ cmp $main_end_input_ptr, #16
+
+ mov $ctr3b, $ctr1b
+ sub $rctr32w, $rctr32w, #1
+ b.gt .L128_dec_blocks_more_than_1
+
+ sub $rctr32w, $rctr32w, #1
+ b .L128_dec_blocks_less_than_1
+ .L128_dec_blocks_more_than_3: @ blocks left > 3
+ rev64 $res0b, $res1b @ GHASH final-3 block
+ ld1 { $res1b}, [$input_ptr], #16 @ AES final-2 block - load ciphertext
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ mov $acc_md, $h34k.d[1] @ GHASH final-3 block - mid
+ stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-3 block - store result
+ eor $ctr0b, $res1b, $ctr1b @ AES final-2 block - result
+
+ mov $rk4d, $res0.d[1] @ GHASH final-3 block - mid
+ mov $output_h0, $ctr0.d[1] @ AES final-2 block - mov high
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH final-3 block - low
+ mov $output_l0, $ctr0.d[0] @ AES final-2 block - mov low
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH final-3 block - high
+
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-3 block - mid
+
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+ eor $output_h0, $output_h0, $rk10_h @ AES final-2 block - round 10 high
+
+ pmull $acc_m.1q, $rk4v.1d, $acc_m.1d @ GHASH final-3 block - mid
+ eor $output_l0, $output_l0, $rk10_l @ AES final-2 block - round 10 low
+ .L128_dec_blocks_more_than_2: @ blocks left > 2
+
+ rev64 $res0b, $res1b @ GHASH final-2 block
+ ld1 { $res1b}, [$input_ptr], #16 @ AES final-1 block - load ciphertext
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ eor $ctr0b, $res1b, $ctr2b @ AES final-1 block - result
+ stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-2 block - store result
+
+ mov $rk4d, $res0.d[1] @ GHASH final-2 block - mid
+
+ pmull $rk3q1, $res0.1d, $h3.1d @ GHASH final-2 block - low
+
+ pmull2 $rk2q1, $res0.2d, $h3.2d @ GHASH final-2 block - high
+ mov $output_l0, $ctr0.d[0] @ AES final-1 block - mov low
+
+ mov $output_h0, $ctr0.d[1] @ AES final-1 block - mov high
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-2 block - mid
+
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+
+ pmull $rk4v.1q, $rk4v.1d, $h34k.1d @ GHASH final-2 block - mid
+
+ eor $output_l0, $output_l0, $rk10_l @ AES final-1 block - round 10 low
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final-2 block - low
+
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final-2 block - high
+
+ eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-2 block - mid
+ eor $output_h0, $output_h0, $rk10_h @ AES final-1 block - round 10 high
+ .L128_dec_blocks_more_than_1: @ blocks left > 1
+
+ rev64 $res0b, $res1b @ GHASH final-1 block
+
+ ld1 { $res1b}, [$input_ptr], #16 @ AES final block - load ciphertext
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ mov $rk4d, $res0.d[1] @ GHASH final-1 block - mid
+
+ eor $ctr0b, $res1b, $ctr3b @ AES final block - result
+
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-1 block - mid
+
+ stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-1 block - store result
+ mov $output_l0, $ctr0.d[0] @ AES final block - mov low
+
+ mov $output_h0, $ctr0.d[1] @ AES final block - mov high
+ ins $rk4v.d[1], $rk4v.d[0] @ GHASH final-1 block - mid
+
+ pmull $rk3q1, $res0.1d, $h2.1d @ GHASH final-1 block - low
+
+ pmull2 $rk2q1, $res0.2d, $h2.2d @ GHASH final-1 block - high
+
+ pmull2 $rk4v.1q, $rk4v.2d, $h12k.2d @ GHASH final-1 block - mid
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final-1 block - low
+
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final-1 block - high
+ eor $output_h0, $output_h0, $rk10_h @ AES final block - round 10 high
+
+ eor $output_l0, $output_l0, $rk10_l @ AES final block - round 10 low
+ eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-1 block - mid
+ .L128_dec_blocks_less_than_1: @ blocks left <= 1
+
+ mvn $rk10_h, xzr @ rk10_h = 0xffffffffffffffff
+ and $bit_length, $bit_length, #127 @ bit_length %= 128
+
+ mvn $rk10_l, xzr @ rk10_l = 0xffffffffffffffff
+ sub $bit_length, $bit_length, #128 @ bit_length -= 128
+
+ neg $bit_length, $bit_length @ bit_length = 128 - #bits in input (in range [1,128])
+
+ and $bit_length, $bit_length, #127 @ bit_length %= 128
+
+ lsr $rk10_h, $rk10_h, $bit_length @ rk10_h is mask for top 64b of last block
+ cmp $bit_length, #64
+
+ csel $ctr96_b64x, $rk10_h, xzr, lt
+ csel $ctr32x, $rk10_l, $rk10_h, lt
+
+ fmov $ctr0d, $ctr32x @ ctr0b is mask for last block
+
+ mov $ctr0.d[1], $ctr96_b64x
+
+ and $res1b, $res1b, $ctr0b @ possibly partial last block has zeroes in highest bits
+
+ rev64 $res0b, $res1b @ GHASH final block
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ ldp $end_input_ptr, $main_end_input_ptr, [$output_ptr] @ load existing bytes we need to not overwrite
+
+ and $output_h0, $output_h0, $ctr96_b64x
+
+ pmull2 $rk2q1, $res0.2d, $h1.2d @ GHASH final block - high
+ mov $t0d, $res0.d[1] @ GHASH final block - mid
+
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH final block - mid
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final block - high
+
+ pmull $t0.1q, $t0.1d, $h12k.1d @ GHASH final block - mid
+
+ pmull $rk3q1, $res0.1d, $h1.1d @ GHASH final block - low
+ bic $end_input_ptr, $end_input_ptr, $ctr32x @ mask out low existing bytes
+ and $output_l0, $output_l0, $ctr32x
+
+ rev $ctr32w, $rctr32w
+
+ eor $acc_mb, $acc_mb, $t0.16b @ GHASH final block - mid
+ movi $mod_constant.8b, #0xc2
+
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final block - low
+
+ bic $main_end_input_ptr, $main_end_input_ptr, $ctr96_b64x @ mask out high existing bytes
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
+
+ pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
+
+ eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
+
+ orr $output_l0, $output_l0, $end_input_ptr
+ str $ctr32w, [$counter, #12] @ store the updated counter
+
+ orr $output_h0, $output_h0, $main_end_input_ptr
+ stp $output_l0, $output_h0, [$output_ptr]
+ ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
+
+ eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
+
+ eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
+
+ pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
+ ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
+
+ eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
+
+ eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
+ ext $acc_lb, $acc_lb, $acc_lb, #8
+ rev64 $acc_lb, $acc_lb
+ mov x0, $len
+ st1 { $acc_l.16b }, [$current_tag]
+
+ ldp x21, x22, [sp, #16]
+ ldp x23, x24, [sp, #32]
+ ldp d8, d9, [sp, #48]
+ ldp d10, d11, [sp, #64]
+ ldp d12, d13, [sp, #80]
+ ldp d14, d15, [sp, #96]
+ ldp x19, x20, [sp], #112
+ ret
+
+ .L128_dec_ret:
+ mov w0, #0x0
+ ret
+.size aes_gcm_dec_128_kernel,.-aes_gcm_dec_128_kernel
+___
+}
+
+{
+my ($end_input_ptr,$main_end_input_ptr,$input_l0,$input_h0)=map("x$_",(4..7));
+my ($input_l1,$input_h1,$input_l2,$input_h2,$input_l3,$input_h3)=map("x$_",(19..24));
+my ($output_l1,$output_h1,$output_l2,$output_h2,$output_l3,$output_h3)=map("x$_",(19..24));
+my ($output_l0,$output_h0)=map("x$_",(6..7));
+
+my $ctr32w="w9";
+my ($ctr32x,$ctr96_b64x,$ctr96_t32x,$rctr32x,$rk12_l,$rk12_h,$len)=map("x$_",(9..15));
+my ($ctr96_t32w,$rctr32w)=map("w$_",(11..12));
+
+my ($ctr0b,$ctr1b,$ctr2b,$ctr3b,$res0b,$res1b,$res2b,$res3b)=map("v$_.16b",(0..7));
+my ($ctr0,$ctr1,$ctr2,$ctr3,$res0,$res1,$res2,$res3)=map("v$_",(0..7));
+my ($ctr0d,$ctr1d,$ctr2d,$ctr3d,$res0d,$res1d,$res2d,$res3d)=map("d$_",(0..7));
+my ($res0q,$res1q,$res2q,$res3q)=map("q$_",(4..7));
+
+my ($acc_hb,$acc_mb,$acc_lb)=map("v$_.16b",(9..11));
+my ($acc_h,$acc_m,$acc_l)=map("v$_",(9..11));
+my ($acc_hd,$acc_md,$acc_ld)=map("d$_",(9..11));
+
+my ($h1,$h2,$h3,$h4,$h12k,$h34k)=map("v$_",(12..17));
+my ($h1q,$h2q,$h3q,$h4q)=map("q$_",(12..15));
+my ($h1b,$h2b,$h3b,$h4b)=map("v$_.16b",(12..15));
+
+my $t0="v8";
+my $t0d="d8";
+my $t3="v4";
+my $t3d="d4";
+
+my ($t1,$t2)=map("v$_",(30..31));
+my ($t1d,$t2d)=map("d$_",(30..31));
+
+my $t4="v30";
+my $t4d="d30";
+my $t5="v8";
+my $t5d="d8";
+my $t6="v31";
+my $t6d="d31";
+
+my $t7="v5";
+my $t7d="d5";
+my $t8="v6";
+my $t8d="d6";
+my $t9="v30";
+my $t9d="d30";
+
+my ($ctr_t0,$ctr_t1,$ctr_t2,$ctr_t3)=map("v$_",(4..7));
+my ($ctr_t0d,$ctr_t1d,$ctr_t2d,$ctr_t3d)=map("d$_",(4..7));
+my ($ctr_t0b,$ctr_t1b,$ctr_t2b,$ctr_t3b)=map("v$_.16b",(4..7));
+
+my $mod_constantd="d8";
+my $mod_constant="v8";
+my $mod_t="v31";
+
+my ($rk0,$rk1,$rk2,$rk3,$rk4,$rk5,$rk6,$rk7,$rk8,$rk9,$rk10,$rk11)=map("v$_.16b",(18..29));
+my ($rk0q,$rk1q,$rk2q,$rk3q,$rk4q,$rk5q,$rk6q,$rk7q,$rk8q,$rk9q,$rk10q,$rk11q)=map("q$_",(18..29));
+my $rk2q1="v20.1q";
+my $rk3q1="v21.1q";
+my $rk4v="v22";
+my $rk4d="d22";
+
+#########################################################################################
+# size_t aes_gcm_enc_192_kernel(const unsigned char *in,
+# size_t len,
+# unsigned char *out,
+# const void *key,
+# unsigned char ivec[16],
+# u64 *Xi);
+#
+$code.=<<___;
+.global aes_gcm_enc_192_kernel
+.type aes_gcm_enc_192_kernel,%function
+.align 4
+aes_gcm_enc_192_kernel:
+ cbz x1, .L192_enc_ret
+ stp x19, x20, [sp, #-112]!
+ mov x16, x4
+ mov x8, x5
+ stp x21, x22, [sp, #16]
+ stp x23, x24, [sp, #32]
+ stp d8, d9, [sp, #48]
+ stp d10, d11, [sp, #64]
+ stp d12, d13, [sp, #80]
+ stp d14, d15, [sp, #96]
+
+ ldp $ctr96_b64x, $ctr96_t32x, [$counter] @ ctr96_b64, ctr96_t32
+
+ ldr $rk5q, [$cc, #80] @ load rk5
+
+ ldr $rk4q, [$cc, #64] @ load rk4
+
+ ldr $rk8q, [$cc, #128] @ load rk8
+
+ lsr $rctr32x, $ctr96_t32x, #32
+ ldr $rk6q, [$cc, #96] @ load rk6
+ orr $ctr96_t32w, $ctr96_t32w, $ctr96_t32w
+
+ ldr $rk7q, [$cc, #112] @ load rk7
+ rev $rctr32w, $rctr32w @ rev_ctr32
+
+ add $rctr32w, $rctr32w, #1 @ increment rev_ctr32
+ fmov $ctr3d, $ctr96_b64x @ CTR block 3
+
+ rev $ctr32w, $rctr32w @ CTR block 1
+ add $rctr32w, $rctr32w, #1 @ CTR block 1
+ fmov $ctr1d, $ctr96_b64x @ CTR block 1
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 1
+ ld1 { $ctr0b}, [$counter] @ special case vector load initial counter so we can start first AES block as quickly as possible
+
+ fmov $ctr1.d[1], $ctr32x @ CTR block 1
+ rev $ctr32w, $rctr32w @ CTR block 2
+ add $rctr32w, $rctr32w, #1 @ CTR block 2
+
+ fmov $ctr2d, $ctr96_b64x @ CTR block 2
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 2
+
+ fmov $ctr2.d[1], $ctr32x @ CTR block 2
+ rev $ctr32w, $rctr32w @ CTR block 3
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 3
+ ldr $rk0q, [$cc, #0] @ load rk0
+
+ fmov $ctr3.d[1], $ctr32x @ CTR block 3
+
+ ldr $rk3q, [$cc, #48] @ load rk3
+
+ ldp $rk12_l, $rk12_h, [$cc, #192] @ load rk12
+
+ ldr $rk1q, [$cc, #16] @ load rk1
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 0
+ ld1 { $acc_lb}, [$current_tag]
+ ext $acc_lb, $acc_lb, $acc_lb, #8
+ rev64 $acc_lb, $acc_lb
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 0
+ ldr $rk11q, [$cc, #176] @ load rk11
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 0
+ ldr $h4q, [$current_tag, #112] @ load h4l | h4h
+ ext $h4b, $h4b, $h4b, #8
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
+ ldr $rk2q, [$cc, #32] @ load rk2
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 1
+ ldr $rk10q, [$cc, #160] @ load rk10
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
+ ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+ ext $h1b, $h1b, $h1b, #8
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 1
+ ldr $rk9q, [$cc, #144] @ load rk9
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 1
+ ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+ ext $h3b, $h3b, $h3b, #8
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 2
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 2
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 2
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 3
+ trn1 $acc_h.2d, $h3.2d, $h4.2d @ h4h | h3h
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 3
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 2
+ trn2 $h34k.2d, $h3.2d, $h4.2d @ h4l | h3l
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 4
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 3
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 3
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 5
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 4
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 4
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 6
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 4
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 5
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 5
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 5
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 6
+ ldr $h2q, [$current_tag, #64] @ load h2l | h2h
+ ext $h2b, $h2b, $h2b, #8
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 6
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 6
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 7
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 7
+ trn2 $h12k.2d, $h1.2d, $h2.2d @ h2l | h1l
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 7
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 8
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 7
+ trn1 $t0.2d, $h1.2d, $h2.2d @ h2h | h1h
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 8
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 8
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 8
+
+ aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 9
+
+ aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 9
+
+ aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 9
+
+ aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 9
+
+ aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 10
+
+ aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 10
+
+ aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 10
+ lsr $main_end_input_ptr, $bit_length, #3 @ byte_len
+ mov $len, $main_end_input_ptr
+
+ aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 10
+ sub $main_end_input_ptr, $main_end_input_ptr, #1 @ byte_len - 1
+
+ eor $h12k.16b, $h12k.16b, $t0.16b @ h2k | h1k
+ and $main_end_input_ptr, $main_end_input_ptr, #0xffffffffffffffc0 @ number of bytes to be processed in main loop (at least 1 byte must be handled by tail)
+
+ eor $h34k.16b, $h34k.16b, $acc_h.16b @ h4k | h3k
+
+ aese $ctr2b, $rk11 @ AES block 2 - round 11
+ add $end_input_ptr, $input_ptr, $bit_length, lsr #3 @ end_input_ptr
+ add $main_end_input_ptr, $main_end_input_ptr, $input_ptr
+
+ aese $ctr1b, $rk11 @ AES block 1 - round 11
+ cmp $input_ptr, $main_end_input_ptr @ check if we have <= 4 blocks
+
+ aese $ctr0b, $rk11 @ AES block 0 - round 11
+ add $rctr32w, $rctr32w, #1 @ CTR block 3
+
+ aese $ctr3b, $rk11 @ AES block 3 - round 11
+ b.ge .L192_enc_tail @ handle tail
+
+ rev $ctr32w, $rctr32w @ CTR block 4
+ ldp $input_l0, $input_h0, [$input_ptr, #0] @ AES block 0 - load plaintext
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4
+ ldp $input_l2, $input_h2, [$input_ptr, #32] @ AES block 2 - load plaintext
+
+ ldp $input_l3, $input_h3, [$input_ptr, #48] @ AES block 3 - load plaintext
+
+ ldp $input_l1, $input_h1, [$input_ptr, #16] @ AES block 1 - load plaintext
+ add $input_ptr, $input_ptr, #64 @ AES input_ptr update
+ cmp $input_ptr, $main_end_input_ptr @ check if we have <= 8 blocks
+
+ eor $input_l0, $input_l0, $rk12_l @ AES block 0 - round 12 low
+
+ eor $input_h0, $input_h0, $rk12_h @ AES block 0 - round 12 high
+ eor $input_h2, $input_h2, $rk12_h @ AES block 2 - round 12 high
+ fmov $ctr_t0d, $input_l0 @ AES block 0 - mov low
+
+ eor $input_h3, $input_h3, $rk12_h @ AES block 3 - round 12 high
+ fmov $ctr_t0.d[1], $input_h0 @ AES block 0 - mov high
+
+ eor $input_l2, $input_l2, $rk12_l @ AES block 2 - round 12 low
+ eor $input_l1, $input_l1, $rk12_l @ AES block 1 - round 12 low
+
+ fmov $ctr_t1d, $input_l1 @ AES block 1 - mov low
+ eor $input_h1, $input_h1, $rk12_h @ AES block 1 - round 12 high
+
+ fmov $ctr_t1.d[1], $input_h1 @ AES block 1 - mov high
+
+ eor $input_l3, $input_l3, $rk12_l @ AES block 3 - round 12 low
+ fmov $ctr_t2d, $input_l2 @ AES block 2 - mov low
+
+ add $rctr32w, $rctr32w, #1 @ CTR block 4
+ eor $res0b, $ctr_t0b, $ctr0b @ AES block 0 - result
+ fmov $ctr0d, $ctr96_b64x @ CTR block 4
+
+ fmov $ctr0.d[1], $ctr32x @ CTR block 4
+ rev $ctr32w, $rctr32w @ CTR block 5
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 5
+ add $rctr32w, $rctr32w, #1 @ CTR block 5
+
+ fmov $ctr_t3d, $input_l3 @ AES block 3 - mov low
+ st1 { $res0b}, [$output_ptr], #16 @ AES block 0 - store result
+
+ fmov $ctr_t2.d[1], $input_h2 @ AES block 2 - mov high
+
+ eor $res1b, $ctr_t1b, $ctr1b @ AES block 1 - result
+ fmov $ctr1d, $ctr96_b64x @ CTR block 5
+ st1 { $res1b}, [$output_ptr], #16 @ AES block 1 - store result
+
+ fmov $ctr_t3.d[1], $input_h3 @ AES block 3 - mov high
+
+ fmov $ctr1.d[1], $ctr32x @ CTR block 5
+ rev $ctr32w, $rctr32w @ CTR block 6
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 6
+
+ add $rctr32w, $rctr32w, #1 @ CTR block 6
+ eor $res2b, $ctr_t2b, $ctr2b @ AES block 2 - result
+ fmov $ctr2d, $ctr96_b64x @ CTR block 6
+
+ fmov $ctr2.d[1], $ctr32x @ CTR block 6
+ rev $ctr32w, $rctr32w @ CTR block 7
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 7
+ st1 { $res2b}, [$output_ptr], #16 @ AES block 2 - store result
+
+ eor $res3b, $ctr_t3b, $ctr3b @ AES block 3 - result
+ st1 { $res3b}, [$output_ptr], #16 @ AES block 3 - store result
+ b.ge .L192_enc_prepretail @ do prepretail
+
+ .L192_enc_main_loop: @ main loop start
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
+ rev64 $res1b, $res1b @ GHASH block 4k+1 (t0 and t1 free)
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
+ ldp $input_l1, $input_h1, [$input_ptr, #16] @ AES block 4k+5 - load plaintext
+
+ ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
+ fmov $ctr3d, $ctr96_b64x @ CTR block 4k+3
+ rev64 $res0b, $res0b @ GHASH block 4k (only t0 is free)
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
+ fmov $ctr3.d[1], $ctr32x @ CTR block 4k+3
+
+ pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
+ rev64 $res3b, $res3b @ GHASH block 4k+3 (t0, t1, t2 and t3 free)
+ ldp $input_l2, $input_h2, [$input_ptr, #32] @ AES block 4k+6 - load plaintext
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
+ ldp $input_l3, $input_h3, [$input_ptr, #48] @ AES block 4k+3 - load plaintext
+
+ pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
+ eor $res0b, $res0b, $acc_lb @ PRE 1
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
+ rev64 $res2b, $res2b @ GHASH block 4k+2 (t0, t1, and t2 free)
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
+ eor $input_h3, $input_h3, $rk12_h @ AES block 4k+3 - round 12 high
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
+ mov $t0d, $res0.d[1] @ GHASH block 4k - mid
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
+ eor $input_l2, $input_l2, $rk12_l @ AES block 4k+6 - round 12 low
+
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
+ eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
+ eor $input_l1, $input_l1, $rk12_l @ AES block 4k+5 - round 12 low
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
+ mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
+ mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
+
+ mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
+ eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
+ eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
+
+ pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
+ eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
+
+ pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
+ eor $input_h1, $input_h1, $rk12_h @ AES block 4k+5 - round 12 high
+ ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+3
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
+ eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
+
+ pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
+ eor $input_h2, $input_h2, $rk12_h @ AES block 4k+6 - round 12 high
+
+ pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
+ eor $input_l3, $input_l3, $rk12_l @ AES block 4k+3 - round 12 low
+ mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
+
+ pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
+ rev $ctr32w, $rctr32w @ CTR block 4k+8
+
+ pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+8
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
+ eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
+ ldp $input_l0, $input_h0, [$input_ptr, #0] @ AES block 4k+4 - load plaintext
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
+ eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
+ add $input_ptr, $input_ptr, #64 @ AES input_ptr update
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
+ movi $mod_constant.8b, #0xc2
+
+ pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
+ eor $input_h0, $input_h0, $rk12_h @ AES block 4k+4 - round 12 high
+ eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
+ eor $input_l0, $input_l0, $rk12_l @ AES block 4k+4 - round 12 low
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
+ eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
+ fmov $ctr_t1d, $input_l1 @ AES block 4k+5 - mov low
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
+ eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
+ fmov $ctr_t1.d[1], $input_h1 @ AES block 4k+5 - mov high
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
+ eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
+
+ pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
+ cmp $input_ptr, $main_end_input_ptr @ LOOP CONTROL
+ fmov $ctr_t0d, $input_l0 @ AES block 4k+4 - mov low
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
+ fmov $ctr_t0.d[1], $input_h0 @ AES block 4k+4 - mov high
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
+ fmov $ctr_t3d, $input_l3 @ AES block 4k+3 - mov low
+
+ eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
+ eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+8
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
+ fmov $ctr_t3.d[1], $input_h3 @ AES block 4k+3 - mov high
+
+ pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
+ ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
+ fmov $ctr_t2d, $input_l2 @ AES block 4k+6 - mov low
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
+
+ aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 9
+ eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
+
+ aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 9
+
+ aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 10
+ eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
+
+ aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 9
+
+ aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 9
+
+ aese $ctr0b, $rk11 @ AES block 4k+4 - round 11
+
+ aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 10
+ eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
+
+ aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 10
+
+ eor $res0b, $ctr_t0b, $ctr0b @ AES block 4k+4 - result
+ fmov $ctr0d, $ctr96_b64x @ CTR block 4k+8
+
+ aese $ctr1b, $rk11 @ AES block 4k+5 - round 11
+ fmov $ctr0.d[1], $ctr32x @ CTR block 4k+8
+ rev $ctr32w, $rctr32w @ CTR block 4k+9
+
+ pmull $acc_h.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
+ fmov $ctr_t2.d[1], $input_h2 @ AES block 4k+6 - mov high
+ st1 { $res0b}, [$output_ptr], #16 @ AES block 4k+4 - store result
+
+ aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 10
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+9
+
+ eor $res1b, $ctr_t1b, $ctr1b @ AES block 4k+5 - result
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+9
+ fmov $ctr1d, $ctr96_b64x @ CTR block 4k+9
+
+ aese $ctr2b, $rk11 @ AES block 4k+6 - round 11
+ fmov $ctr1.d[1], $ctr32x @ CTR block 4k+9
+ rev $ctr32w, $rctr32w @ CTR block 4k+10
+
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+10
+ ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+10
+
+ st1 { $res1b}, [$output_ptr], #16 @ AES block 4k+5 - store result
+ eor $acc_lb, $acc_lb, $acc_hb @ MODULO - fold into low
+
+ aese $ctr3b, $rk11 @ AES block 4k+7 - round 11
+ eor $res2b, $ctr_t2b, $ctr2b @ AES block 4k+6 - result
+ fmov $ctr2d, $ctr96_b64x @ CTR block 4k+10
+
+ st1 { $res2b}, [$output_ptr], #16 @ AES block 4k+6 - store result
+ fmov $ctr2.d[1], $ctr32x @ CTR block 4k+10
+ rev $ctr32w, $rctr32w @ CTR block 4k+11
+
+ eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+11
+
+ eor $res3b, $ctr_t3b, $ctr3b @ AES block 4k+3 - result
+ st1 { $res3b}, [$output_ptr], #16 @ AES block 4k+3 - store result
+ b.lt .L192_enc_main_loop
+
+ .L192_enc_prepretail: @ PREPRETAIL
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
+ rev64 $res0b, $res0b @ GHASH block 4k (only t0 is free)
+
+ fmov $ctr3d, $ctr96_b64x @ CTR block 4k+3
+ ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+3
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
+ rev64 $res1b, $res1b @ GHASH block 4k+1 (t0 and t1 free)
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
+
+ fmov $ctr3.d[1], $ctr32x @ CTR block 4k+3
+ eor $res0b, $res0b, $acc_lb @ PRE 1
+ mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
+ rev64 $res2b, $res2b @ GHASH block 4k+2 (t0, t1, and t2 free)
+
+ pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
+ mov $t0d, $res0.d[1] @ GHASH block 4k - mid
+
+ pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
+ rev64 $res3b, $res3b @ GHASH block 4k+3 (t0, t1, t2 and t3 free)
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
+
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
+ mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
+
+ eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
+ mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
+ eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
+
+ pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
+
+ eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
+ eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
+ eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
+ mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
+
+ pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
+ ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
+
+ pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
+ eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
+
+ pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
+
+ pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
+
+ pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
+ eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
+
+ pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
+ eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
+ eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
+ eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
+
+ pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
+ movi $mod_constant.8b, #0xc2
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
+ eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
+ eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
+ eor $acc_mb, $acc_mb, $acc_hb @ karatsuba tidy up
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
+ eor $acc_mb, $acc_mb, $acc_lb
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
+
+ pmull $t1.1q, $acc_h.1d, $mod_constant.1d
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
+ ext $acc_hb, $acc_hb, $acc_hb, #8
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
+ eor $acc_mb, $acc_mb, $t1.16b
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
+
+ aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 9
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
+ eor $acc_mb, $acc_mb, $acc_hb
+
+ aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 9
+
+ aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 9
+
+ aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 9
+
+ pmull $t1.1q, $acc_m.1d, $mod_constant.1d
+
+ ext $acc_mb, $acc_mb, $acc_mb, #8
+
+ aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 10
+
+ aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 10
+
+ aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 10
+
+ aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 10
+ eor $acc_lb, $acc_lb, $t1.16b
+
+ aese $ctr0b, $rk11 @ AES block 4k+4 - round 11
+
+ aese $ctr3b, $rk11 @ AES block 4k+7 - round 11
+
+ aese $ctr2b, $rk11 @ AES block 4k+6 - round 11
+
+ aese $ctr1b, $rk11 @ AES block 4k+5 - round 11
+ eor $acc_lb, $acc_lb, $acc_mb
+ .L192_enc_tail: @ TAIL
+
+ sub $main_end_input_ptr, $end_input_ptr, $input_ptr @ main_end_input_ptr is number of bytes left to process
+ ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES block 4k+4 - load plaintext
+
+ eor $input_l0, $input_l0, $rk12_l @ AES block 4k+4 - round 12 low
+ eor $input_h0, $input_h0, $rk12_h @ AES block 4k+4 - round 12 high
+
+ fmov $ctr_t0d, $input_l0 @ AES block 4k+4 - mov low
+
+ fmov $ctr_t0.d[1], $input_h0 @ AES block 4k+4 - mov high
+ cmp $main_end_input_ptr, #48
+
+ eor $res1b, $ctr_t0b, $ctr0b @ AES block 4k+4 - result
+
+ ext $t0.16b, $acc_lb, $acc_lb, #8 @ prepare final partial tag
+ b.gt .L192_enc_blocks_more_than_3
+
+ sub $rctr32w, $rctr32w, #1
+ movi $acc_m.8b, #0
+
+ mov $ctr3b, $ctr2b
+ movi $acc_h.8b, #0
+ cmp $main_end_input_ptr, #32
+
+ mov $ctr2b, $ctr1b
+ movi $acc_l.8b, #0
+ b.gt .L192_enc_blocks_more_than_2
+
+ sub $rctr32w, $rctr32w, #1
+
+ mov $ctr3b, $ctr1b
+ cmp $main_end_input_ptr, #16
+ b.gt .L192_enc_blocks_more_than_1
+
+ sub $rctr32w, $rctr32w, #1
+ b .L192_enc_blocks_less_than_1
+ .L192_enc_blocks_more_than_3: @ blocks left > 3
+ st1 { $res1b}, [$output_ptr], #16 @ AES final-3 block - store result
+
+ ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final-2 block - load input low & high
+
+ rev64 $res0b, $res1b @ GHASH final-3 block
+
+ eor $input_l0, $input_l0, $rk12_l @ AES final-2 block - round 12 low
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ eor $input_h0, $input_h0, $rk12_h @ AES final-2 block - round 12 high
+ fmov $res1d, $input_l0 @ AES final-2 block - mov low
+
+ fmov $res1.d[1], $input_h0 @ AES final-2 block - mov high
+
+ mov $rk4d, $res0.d[1] @ GHASH final-3 block - mid
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH final-3 block - low
+
+ mov $acc_md, $h34k.d[1] @ GHASH final-3 block - mid
+
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-3 block - mid
+
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH final-3 block - high
+
+ pmull $acc_m.1q, $rk4v.1d, $acc_m.1d @ GHASH final-3 block - mid
+ eor $res1b, $res1b, $ctr1b @ AES final-2 block - result
+ .L192_enc_blocks_more_than_2: @ blocks left > 2
+
+ st1 { $res1b}, [$output_ptr], #16 @ AES final-2 block - store result
+
+ rev64 $res0b, $res1b @ GHASH final-2 block
+ ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final-1 block - load input low & high
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ eor $input_h0, $input_h0, $rk12_h @ AES final-1 block - round 12 high
+
+ pmull2 $rk2q1, $res0.2d, $h3.2d @ GHASH final-2 block - high
+ mov $rk4d, $res0.d[1] @ GHASH final-2 block - mid
+
+ pmull $rk3q1, $res0.1d, $h3.1d @ GHASH final-2 block - low
+ eor $input_l0, $input_l0, $rk12_l @ AES final-1 block - round 12 low
+
+ fmov $res1d, $input_l0 @ AES final-1 block - mov low
+
+ fmov $res1.d[1], $input_h0 @ AES final-1 block - mov high
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final-2 block - high
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-2 block - mid
+
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final-2 block - low
+
+ pmull $rk4v.1q, $rk4v.1d, $h34k.1d @ GHASH final-2 block - mid
+
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+
+ eor $res1b, $res1b, $ctr2b @ AES final-1 block - result
+
+ eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-2 block - mid
+ .L192_enc_blocks_more_than_1: @ blocks left > 1
+
+ st1 { $res1b}, [$output_ptr], #16 @ AES final-1 block - store result
+
+ ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final block - load input low & high
+
+ rev64 $res0b, $res1b @ GHASH final-1 block
+
+ eor $input_l0, $input_l0, $rk12_l @ AES final block - round 12 low
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+
+ mov $rk4d, $res0.d[1] @ GHASH final-1 block - mid
+
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-1 block - mid
+ eor $input_h0, $input_h0, $rk12_h @ AES final block - round 12 high
+ fmov $res1d, $input_l0 @ AES final block - mov low
+
+ pmull2 $rk2q1, $res0.2d, $h2.2d @ GHASH final-1 block - high
+ fmov $res1.d[1], $input_h0 @ AES final block - mov high
+
+ ins $rk4v.d[1], $rk4v.d[0] @ GHASH final-1 block - mid
+
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final-1 block - high
+
+ pmull $rk3q1, $res0.1d, $h2.1d @ GHASH final-1 block - low
+
+ pmull2 $rk4v.1q, $rk4v.2d, $h12k.2d @ GHASH final-1 block - mid
+
+ eor $res1b, $res1b, $ctr3b @ AES final block - result
+
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final-1 block - low
+
+ eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-1 block - mid
+ .L192_enc_blocks_less_than_1: @ blocks left <= 1
+
+ ld1 { $rk0}, [$output_ptr] @ load existing bytes where the possibly partial last block is to be stored
+ rev $ctr32w, $rctr32w
+ and $bit_length, $bit_length, #127 @ bit_length %= 128
+
+ sub $bit_length, $bit_length, #128 @ bit_length -= 128
+ mvn $rk12_h, xzr @ rk12_h = 0xffffffffffffffff
+
+ neg $bit_length, $bit_length @ bit_length = 128 - #bits in input (in range [1,128])
+ mvn $rk12_l, xzr @ rk12_l = 0xffffffffffffffff
+
+ and $bit_length, $bit_length, #127 @ bit_length %= 128
+
+ lsr $rk12_h, $rk12_h, $bit_length @ rk12_h is mask for top 64b of last block
+ cmp $bit_length, #64
+
+ csel $input_l0, $rk12_l, $rk12_h, lt
+ csel $input_h0, $rk12_h, xzr, lt
+
+ fmov $ctr0d, $input_l0 @ ctr0b is mask for last block
+
+ fmov $ctr0.d[1], $input_h0
+
+ and $res1b, $res1b, $ctr0b @ possibly partial last block has zeroes in highest bits
+
+ rev64 $res0b, $res1b @ GHASH final block
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ mov $t0d, $res0.d[1] @ GHASH final block - mid
+
+ pmull $rk3q1, $res0.1d, $h1.1d @ GHASH final block - low
+
+ pmull2 $rk2q1, $res0.2d, $h1.2d @ GHASH final block - high
+
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH final block - mid
+
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final block - low
+
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final block - high
+
+ pmull $t0.1q, $t0.1d, $h12k.1d @ GHASH final block - mid
+
+ eor $acc_mb, $acc_mb, $t0.16b @ GHASH final block - mid
+ movi $mod_constant.8b, #0xc2
+
+ eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
+
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ bif $res1b, $rk0, $ctr0b @ insert existing bytes in top end of result before storing
+
+ eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
+
+ pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
+
+ ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
+
+ eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
+
+ eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
+
+ pmull $acc_h.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
+
+ ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
+
+ eor $acc_lb, $acc_lb, $acc_hb @ MODULO - fold into low
+ str $ctr32w, [$counter, #12] @ store the updated counter
+
+ st1 { $res1b}, [$output_ptr] @ store all 16B
+
+ eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
+ ext $acc_lb, $acc_lb, $acc_lb, #8
+ rev64 $acc_lb, $acc_lb
+ mov x0, $len
+ st1 { $acc_l.16b }, [$current_tag]
+
+ ldp x21, x22, [sp, #16]
+ ldp x23, x24, [sp, #32]
+ ldp d8, d9, [sp, #48]
+ ldp d10, d11, [sp, #64]
+ ldp d12, d13, [sp, #80]
+ ldp d14, d15, [sp, #96]
+ ldp x19, x20, [sp], #112
+ ret
+
+.L192_enc_ret:
+ mov w0, #0x0
+ ret
+.size aes_gcm_enc_192_kernel,.-aes_gcm_enc_192_kernel
+___
+
+#########################################################################################
+# size_t aes_gcm_dec_192_kernel(const unsigned char *in,
+# size_t len,
+# unsigned char *out,
+# const void *key,
+# unsigned char ivec[16],
+# u64 *Xi);
+#
+$code.=<<___;
+.global aes_gcm_dec_192_kernel
+.type aes_gcm_dec_192_kernel,%function
+.align 4
+aes_gcm_dec_192_kernel:
+ cbz x1, .L192_dec_ret
+ stp x19, x20, [sp, #-112]!
+ mov x16, x4
+ mov x8, x5
+ stp x21, x22, [sp, #16]
+ stp x23, x24, [sp, #32]
+ stp d8, d9, [sp, #48]
+ stp d10, d11, [sp, #64]
+ stp d12, d13, [sp, #80]
+ stp d14, d15, [sp, #96]
+
+ add $end_input_ptr, $input_ptr, $bit_length, lsr #3 @ end_input_ptr
+ ldp $ctr96_b64x, $ctr96_t32x, [$counter] @ ctr96_b64, ctr96_t32
+
+ ld1 { $ctr0b}, [$counter] @ special case vector load initial counter so we can start first AES block as quickly as possible
+
+ ldr $rk0q, [$cc, #0] @ load rk0
+
+ lsr $main_end_input_ptr, $bit_length, #3 @ byte_len
+ mov $len, $main_end_input_ptr
+ ldr $rk2q, [$cc, #32] @ load rk2
+
+ lsr $rctr32x, $ctr96_t32x, #32
+ orr $ctr96_t32w, $ctr96_t32w, $ctr96_t32w
+ fmov $ctr3d, $ctr96_b64x @ CTR block 3
+
+ rev $rctr32w, $rctr32w @ rev_ctr32
+ fmov $ctr1d, $ctr96_b64x @ CTR block 1
+
+ add $rctr32w, $rctr32w, #1 @ increment rev_ctr32
+ ldr $rk1q, [$cc, #16] @ load rk1
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 0
+ rev $ctr32w, $rctr32w @ CTR block 1
+
+ add $rctr32w, $rctr32w, #1 @ CTR block 1
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 1
+ ldr $rk3q, [$cc, #48] @ load rk3
+
+ fmov $ctr1.d[1], $ctr32x @ CTR block 1
+ rev $ctr32w, $rctr32w @ CTR block 2
+ add $rctr32w, $rctr32w, #1 @ CTR block 2
+
+ fmov $ctr2d, $ctr96_b64x @ CTR block 2
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 2
+
+ fmov $ctr2.d[1], $ctr32x @ CTR block 2
+ rev $ctr32w, $rctr32w @ CTR block 3
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 1
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 3
+
+ fmov $ctr3.d[1], $ctr32x @ CTR block 3
+
+ ldr $rk8q, [$cc, #128] @ load rk8
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 2
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
+ ldr $rk11q, [$cc, #176] @ load rk11
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 0
+ ldr $h4q, [$current_tag, #112] @ load h4l | h4h
+ ext $h4b, $h4b, $h4b, #8
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 0
+ ldr $h2q, [$current_tag, #64] @ load h2l | h2h
+ ext $h2b, $h2b, $h2b, #8
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 1
+ ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+ ext $h3b, $h3b, $h3b, #8
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
+ ldp $rk12_l, $rk12_h, [$cc, #192] @ load rk12
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 1
+ ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+ ext $h1b, $h1b, $h1b, #8
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 2
+ ldr $rk10q, [$cc, #160] @ load rk10
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 3
+ ldr $rk9q, [$cc, #144] @ load rk9
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 2
+ ldr $rk7q, [$cc, #112] @ load rk7
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 2
+ ldr $rk4q, [$cc, #64] @ load rk4
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 3
+ ld1 { $acc_lb}, [$current_tag]
+ ext $acc_lb, $acc_lb, $acc_lb, #8
+ rev64 $acc_lb, $acc_lb
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 3
+ add $rctr32w, $rctr32w, #1 @ CTR block 3
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 3
+ trn1 $acc_h.2d, $h3.2d, $h4.2d @ h4h | h3h
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 4
+ ldr $rk5q, [$cc, #80] @ load rk5
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 4
+ trn2 $h34k.2d, $h3.2d, $h4.2d @ h4l | h3l
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 4
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 4
+ trn2 $h12k.2d, $h1.2d, $h2.2d @ h2l | h1l
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 5
+ ldr $rk6q, [$cc, #96] @ load rk6
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 5
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 5
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 5
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 6
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 6
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 6
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 7
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 7
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 7
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 6
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 8
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 8
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 7
+
+ aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 9
+
+ aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 9
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 8
+ sub $main_end_input_ptr, $main_end_input_ptr, #1 @ byte_len - 1
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 8
+ and $main_end_input_ptr, $main_end_input_ptr, #0xffffffffffffffc0 @ number of bytes to be processed in main loop (at least 1 byte must be handled by tail)
+
+ aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 10
+ add $main_end_input_ptr, $main_end_input_ptr, $input_ptr
+
+ aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 9
+ cmp $input_ptr, $main_end_input_ptr @ check if we have <= 4 blocks
+
+ aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 9
+ trn1 $t0.2d, $h1.2d, $h2.2d @ h2h | h1h
+
+ aese $ctr3b, $rk11 @ AES block 3 - round 11
+
+ aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 10
+
+ aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 10
+
+ aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 10
+ eor $h12k.16b, $h12k.16b, $t0.16b @ h2k | h1k
+
+ aese $ctr2b, $rk11 @ AES block 2 - round 11
+
+ aese $ctr1b, $rk11 @ AES block 1 - round 11
+ eor $h34k.16b, $h34k.16b, $acc_h.16b @ h4k | h3k
+
+ aese $ctr0b, $rk11 @ AES block 0 - round 11
+ b.ge .L192_dec_tail @ handle tail
+
+ ldr $res1q, [$input_ptr, #16] @ AES block 1 - load ciphertext
+
+ ldr $res0q, [$input_ptr, #0] @ AES block 0 - load ciphertext
+
+ eor $ctr1b, $res1b, $ctr1b @ AES block 1 - result
+
+ eor $ctr0b, $res0b, $ctr0b @ AES block 0 - result
+ rev $ctr32w, $rctr32w @ CTR block 4
+ ldr $res3q, [$input_ptr, #48] @ AES block 3 - load ciphertext
+
+ ldr $res2q, [$input_ptr, #32] @ AES block 2 - load ciphertext
+
+ mov $output_l1, $ctr1.d[0] @ AES block 1 - mov low
+
+ mov $output_h1, $ctr1.d[1] @ AES block 1 - mov high
+
+ mov $output_l0, $ctr0.d[0] @ AES block 0 - mov low
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4
+ add $rctr32w, $rctr32w, #1 @ CTR block 4
+
+ mov $output_h0, $ctr0.d[1] @ AES block 0 - mov high
+ rev64 $res0b, $res0b @ GHASH block 0
+ add $input_ptr, $input_ptr, #64 @ AES input_ptr update
+
+ fmov $ctr0d, $ctr96_b64x @ CTR block 4
+ rev64 $res1b, $res1b @ GHASH block 1
+ cmp $input_ptr, $main_end_input_ptr @ check if we have <= 8 blocks
+
+ eor $output_l1, $output_l1, $rk12_l @ AES block 1 - round 12 low
+ fmov $ctr0.d[1], $ctr32x @ CTR block 4
+ rev $ctr32w, $rctr32w @ CTR block 5
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 5
+ fmov $ctr1d, $ctr96_b64x @ CTR block 5
+ eor $output_h1, $output_h1, $rk12_h @ AES block 1 - round 12 high
+
+ add $rctr32w, $rctr32w, #1 @ CTR block 5
+ fmov $ctr1.d[1], $ctr32x @ CTR block 5
+ eor $output_l0, $output_l0, $rk12_l @ AES block 0 - round 12 low
+
+ rev $ctr32w, $rctr32w @ CTR block 6
+ eor $output_h0, $output_h0, $rk12_h @ AES block 0 - round 12 high
+
+ stp $output_l0, $output_h0, [$output_ptr], #16 @ AES block 0 - store result
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 6
+
+ stp $output_l1, $output_h1, [$output_ptr], #16 @ AES block 1 - store result
+
+ add $rctr32w, $rctr32w, #1 @ CTR block 6
+ eor $ctr2b, $res2b, $ctr2b @ AES block 2 - result
+ b.ge .L192_dec_prepretail @ do prepretail
+
+ .L192_dec_main_loop: @ main loop start
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
+ ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
+
+ pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
+ mov $output_l2, $ctr2.d[0] @ AES block 4k+2 - mov low
+
+ mov $output_h2, $ctr2.d[1] @ AES block 4k+2 - mov high
+ eor $ctr3b, $res3b, $ctr3b @ AES block 4k+3 - result
+ rev64 $res3b, $res3b @ GHASH block 4k+3
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
+ fmov $ctr2d, $ctr96_b64x @ CTR block 4k+6
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
+ eor $res0b, $res0b, $acc_lb @ PRE 1
+
+ pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
+ fmov $ctr2.d[1], $ctr32x @ CTR block 4k+6
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
+ mov $output_h3, $ctr3.d[1] @ AES block 4k+3 - mov high
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
+ mov $output_l3, $ctr3.d[0] @ AES block 4k+3 - mov low
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
+ fmov $ctr3d, $ctr96_b64x @ CTR block 4k+7
+ mov $t0d, $res0.d[1] @ GHASH block 4k - mid
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
+ mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
+ rev $ctr32w, $rctr32w @ CTR block 4k+7
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+7
+
+ fmov $ctr3.d[1], $ctr32x @ CTR block 4k+7
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
+ mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
+ eor $output_h2, $output_h2, $rk12_h @ AES block 4k+2 - round 12 high
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
+ eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
+
+ pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
+ rev64 $res2b, $res2b @ GHASH block 4k+2
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
+
+ pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
+ eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
+ eor $output_l2, $output_l2, $rk12_l @ AES block 4k+2 - round 12 low
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
+
+ eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
+ mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
+ eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
+
+ pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
+ eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
+
+ pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
+
+ eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
+ mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
+
+ pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
+ eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
+ ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
+
+ pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
+ eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
+
+ pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
+ eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
+ movi $mod_constant.8b, #0xc2
+
+ pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
+ eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
+
+ aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 9
+ eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
+ eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
+
+ aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 10
+
+ aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 9
+ eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 10
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
+ ldr $res2q, [$input_ptr, #32] @ AES block 4k+6 - load ciphertext
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
+ eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
+
+ pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
+ ldr $res3q, [$input_ptr, #48] @ AES block 4k+7 - load ciphertext
+ eor $output_l3, $output_l3, $rk12_l @ AES block 4k+3 - round 12 low
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
+ ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
+
+ aese $ctr0b, $rk11 @ AES block 4k+4 - round 11
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+7
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
+ eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
+ ldr $res0q, [$input_ptr, #0] @ AES block 4k+4 - load ciphertext
+
+ aese $ctr1b, $rk11 @ AES block 4k+5 - round 11
+ ldr $res1q, [$input_ptr, #16] @ AES block 4k+5 - load ciphertext
+ rev $ctr32w, $rctr32w @ CTR block 4k+8
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
+ stp $output_l2, $output_h2, [$output_ptr], #16 @ AES block 4k+2 - store result
+
+ aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 9
+ eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
+
+ add $input_ptr, $input_ptr, #64 @ AES input_ptr update
+ cmp $input_ptr, $main_end_input_ptr @ LOOP CONTROL
+
+ eor $ctr0b, $res0b, $ctr0b @ AES block 4k+4 - result
+ eor $output_h3, $output_h3, $rk12_h @ AES block 4k+3 - round 12 high
+ eor $ctr1b, $res1b, $ctr1b @ AES block 4k+5 - result
+
+ aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 10
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+8
+
+ aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 9
+
+ pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
+ mov $output_l1, $ctr1.d[0] @ AES block 4k+5 - mov low
+
+ mov $output_l0, $ctr0.d[0] @ AES block 4k+4 - mov low
+ stp $output_l3, $output_h3, [$output_ptr], #16 @ AES block 4k+3 - store result
+ rev64 $res1b, $res1b @ GHASH block 4k+5
+
+ aese $ctr2b, $rk11 @ AES block 4k+6 - round 11
+ mov $output_h0, $ctr0.d[1] @ AES block 4k+4 - mov high
+
+ aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 10
+ mov $output_h1, $ctr1.d[1] @ AES block 4k+5 - mov high
+
+ fmov $ctr0d, $ctr96_b64x @ CTR block 4k+8
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+8
+ ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
+
+ eor $ctr2b, $res2b, $ctr2b @ AES block 4k+6 - result
+ fmov $ctr0.d[1], $ctr32x @ CTR block 4k+8
+ rev $ctr32w, $rctr32w @ CTR block 4k+9
+
+ eor $output_l0, $output_l0, $rk12_l @ AES block 4k+4 - round 12 low
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+9
+ eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
+
+ fmov $ctr1d, $ctr96_b64x @ CTR block 4k+9
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+9
+ eor $output_l1, $output_l1, $rk12_l @ AES block 4k+5 - round 12 low
+
+ fmov $ctr1.d[1], $ctr32x @ CTR block 4k+9
+ rev $ctr32w, $rctr32w @ CTR block 4k+10
+ eor $output_h1, $output_h1, $rk12_h @ AES block 4k+5 - round 12 high
+
+ eor $output_h0, $output_h0, $rk12_h @ AES block 4k+4 - round 12 high
+ stp $output_l0, $output_h0, [$output_ptr], #16 @ AES block 4k+4 - store result
+ eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
+
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+10
+ rev64 $res0b, $res0b @ GHASH block 4k+4
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+10
+
+ aese $ctr3b, $rk11 @ AES block 4k+7 - round 11
+ stp $output_l1, $output_h1, [$output_ptr], #16 @ AES block 4k+5 - store result
+ b.lt .L192_dec_main_loop
+
+ .L192_dec_prepretail: @ PREPRETAIL
+ mov $output_h2, $ctr2.d[1] @ AES block 4k+2 - mov high
+ ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
+ eor $ctr3b, $res3b, $ctr3b @ AES block 4k+3 - result
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
+ mov $output_l2, $ctr2.d[0] @ AES block 4k+2 - mov low
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
+ mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
+
+ eor $res0b, $res0b, $acc_lb @ PRE 1
+ fmov $ctr2d, $ctr96_b64x @ CTR block 4k+6
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
+ mov $output_l3, $ctr3.d[0] @ AES block 4k+3 - mov low
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
+ mov $output_h3, $ctr3.d[1] @ AES block 4k+3 - mov high
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
+ mov $t0d, $res0.d[1] @ GHASH block 4k - mid
+ fmov $ctr3d, $ctr96_b64x @ CTR block 4k+7
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
+ rev64 $res2b, $res2b @ GHASH block 4k+2
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
+ fmov $ctr2.d[1], $ctr32x @ CTR block 4k+6
+ rev $ctr32w, $rctr32w @ CTR block 4k+7
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+7
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
+ mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
+
+ pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
+ eor $output_h3, $output_h3, $rk12_h @ AES block 4k+3 - round 12 high
+ fmov $ctr3.d[1], $ctr32x @ CTR block 4k+7
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
+ eor $output_l2, $output_l2, $rk12_l @ AES block 4k+2 - round 12 low
+
+ pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
+ eor $output_h2, $output_h2, $rk12_h @ AES block 4k+2 - round 12 high
+ eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
+
+ pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
+ eor $output_l3, $output_l3, $rk12_l @ AES block 4k+3 - round 12 low
+ stp $output_l2, $output_h2, [$output_ptr], #16 @ AES block 4k+2 - store result
+
+ rev64 $res3b, $res3b @ GHASH block 4k+3
+ stp $output_l3, $output_h3, [$output_ptr], #16 @ AES block 4k+3 - store result
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
+ eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
+
+ pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+7
+
+ pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
+ eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
+
+ eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
+ mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
+ eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
+
+ eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
+
+ pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
+ mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
+ ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
+
+ pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
+ eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
+
+ pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
+ eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
+
+ pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
+ movi $mod_constant.8b, #0xc2
+
+ pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
+
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+ eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
+ eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
+
+ pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
+ eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
+ eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
+ eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
+ ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
+ eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
+
+ aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 9
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
+ eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
+
+ aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 10
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
+ eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
+
+ aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 9
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
+
+ aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 9
+
+ pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
+
+ aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 9
+
+ aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 10
+
+ aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 10
+ ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
+
+ aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 10
+
+ aese $ctr0b, $rk11
+ eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
+
+ aese $ctr2b, $rk11
+
+ aese $ctr1b, $rk11
+
+ aese $ctr3b, $rk11
+
+ eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
+ .L192_dec_tail: @ TAIL
+
+ sub $main_end_input_ptr, $end_input_ptr, $input_ptr @ main_end_input_ptr is number of bytes left to process
+ ld1 { $res1b}, [$input_ptr], #16 @ AES block 4k+4 - load ciphertext
+
+ eor $ctr0b, $res1b, $ctr0b @ AES block 4k+4 - result
+
+ mov $output_h0, $ctr0.d[1] @ AES block 4k+4 - mov high
+
+ mov $output_l0, $ctr0.d[0] @ AES block 4k+4 - mov low
+
+ ext $t0.16b, $acc_lb, $acc_lb, #8 @ prepare final partial tag
+
+ cmp $main_end_input_ptr, #48
+
+ eor $output_h0, $output_h0, $rk12_h @ AES block 4k+4 - round 12 high
+
+ eor $output_l0, $output_l0, $rk12_l @ AES block 4k+4 - round 12 low
+ b.gt .L192_dec_blocks_more_than_3
+
+ movi $acc_l.8b, #0
+ movi $acc_h.8b, #0
+
+ mov $ctr3b, $ctr2b
+ mov $ctr2b, $ctr1b
+ sub $rctr32w, $rctr32w, #1
+
+ movi $acc_m.8b, #0
+ cmp $main_end_input_ptr, #32
+ b.gt .L192_dec_blocks_more_than_2
+
+ mov $ctr3b, $ctr1b
+ cmp $main_end_input_ptr, #16
+ sub $rctr32w, $rctr32w, #1
+
+ b.gt .L192_dec_blocks_more_than_1
+
+ sub $rctr32w, $rctr32w, #1
+ b .L192_dec_blocks_less_than_1
+ .L192_dec_blocks_more_than_3: @ blocks left > 3
+ rev64 $res0b, $res1b @ GHASH final-3 block
+ ld1 { $res1b}, [$input_ptr], #16 @ AES final-2 block - load ciphertext
+
+ stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-3 block - store result
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ eor $ctr0b, $res1b, $ctr1b @ AES final-2 block - result
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH final-3 block - low
+ mov $output_l0, $ctr0.d[0] @ AES final-2 block - mov low
+ mov $rk4d, $res0.d[1] @ GHASH final-3 block - mid
+
+ mov $output_h0, $ctr0.d[1] @ AES final-2 block - mov high
+
+ mov $acc_md, $h34k.d[1] @ GHASH final-3 block - mid
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-3 block - mid
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH final-3 block - high
+
+ eor $output_l0, $output_l0, $rk12_l @ AES final-2 block - round 12 low
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+
+ pmull $acc_m.1q, $rk4v.1d, $acc_m.1d @ GHASH final-3 block - mid
+ eor $output_h0, $output_h0, $rk12_h @ AES final-2 block - round 12 high
+ .L192_dec_blocks_more_than_2: @ blocks left > 2
+
+ rev64 $res0b, $res1b @ GHASH final-2 block
+ ld1 { $res1b}, [$input_ptr], #16 @ AES final-1 block - load ciphertext
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+
+ eor $ctr0b, $res1b, $ctr2b @ AES final-1 block - result
+
+ mov $rk4d, $res0.d[1] @ GHASH final-2 block - mid
+
+ pmull $rk3q1, $res0.1d, $h3.1d @ GHASH final-2 block - low
+
+ stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-2 block - store result
+
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-2 block - mid
+ mov $output_h0, $ctr0.d[1] @ AES final-1 block - mov high
+
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final-2 block - low
+ mov $output_l0, $ctr0.d[0] @ AES final-1 block - mov low
+
+ pmull2 $rk2q1, $res0.2d, $h3.2d @ GHASH final-2 block - high
+
+ pmull $rk4v.1q, $rk4v.1d, $h34k.1d @ GHASH final-2 block - mid
+
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final-2 block - high
+ eor $output_h0, $output_h0, $rk12_h @ AES final-1 block - round 12 high
+
+ eor $output_l0, $output_l0, $rk12_l @ AES final-1 block - round 12 low
+ eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-2 block - mid
+ .L192_dec_blocks_more_than_1: @ blocks left > 1
+
+ rev64 $res0b, $res1b @ GHASH final-1 block
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+ ld1 { $res1b}, [$input_ptr], #16 @ AES final block - load ciphertext
+
+ mov $rk4d, $res0.d[1] @ GHASH final-1 block - mid
+
+ pmull2 $rk2q1, $res0.2d, $h2.2d @ GHASH final-1 block - high
+
+ eor $ctr0b, $res1b, $ctr3b @ AES final block - result
+ stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-1 block - store result
+
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-1 block - mid
+
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final-1 block - high
+
+ pmull $rk3q1, $res0.1d, $h2.1d @ GHASH final-1 block - low
+ mov $output_h0, $ctr0.d[1] @ AES final block - mov high
+
+ ins $rk4v.d[1], $rk4v.d[0] @ GHASH final-1 block - mid
+ mov $output_l0, $ctr0.d[0] @ AES final block - mov low
+
+ pmull2 $rk4v.1q, $rk4v.2d, $h12k.2d @ GHASH final-1 block - mid
+
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final-1 block - low
+ eor $output_h0, $output_h0, $rk12_h @ AES final block - round 12 high
+
+ eor $output_l0, $output_l0, $rk12_l @ AES final block - round 12 low
+
+ eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-1 block - mid
+ .L192_dec_blocks_less_than_1: @ blocks left <= 1
+
+ mvn $rk12_l, xzr @ rk12_l = 0xffffffffffffffff
+ ldp $end_input_ptr, $main_end_input_ptr, [$output_ptr] @ load existing bytes we need to not overwrite
+ and $bit_length, $bit_length, #127 @ bit_length %= 128
+
+ sub $bit_length, $bit_length, #128 @ bit_length -= 128
+
+ neg $bit_length, $bit_length @ bit_length = 128 - #bits in input (in range [1,128])
+
+ and $bit_length, $bit_length, #127 @ bit_length %= 128
+ mvn $rk12_h, xzr @ rk12_h = 0xffffffffffffffff
+
+ lsr $rk12_h, $rk12_h, $bit_length @ rk12_h is mask for top 64b of last block
+ cmp $bit_length, #64
+
+ csel $ctr32x, $rk12_l, $rk12_h, lt
+ csel $ctr96_b64x, $rk12_h, xzr, lt
+
+ fmov $ctr0d, $ctr32x @ ctr0b is mask for last block
+ and $output_l0, $output_l0, $ctr32x
+ bic $end_input_ptr, $end_input_ptr, $ctr32x @ mask out low existing bytes
+
+ orr $output_l0, $output_l0, $end_input_ptr
+ mov $ctr0.d[1], $ctr96_b64x
+
+ rev $ctr32w, $rctr32w
+
+ and $res1b, $res1b, $ctr0b @ possibly partial last block has zeroes in highest bits
+ str $ctr32w, [$counter, #12] @ store the updated counter
+
+ rev64 $res0b, $res1b @ GHASH final block
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+ bic $main_end_input_ptr, $main_end_input_ptr, $ctr96_b64x @ mask out high existing bytes
+
+ and $output_h0, $output_h0, $ctr96_b64x
+
+ pmull2 $rk2q1, $res0.2d, $h1.2d @ GHASH final block - high
+ mov $t0d, $res0.d[1] @ GHASH final block - mid
+
+ pmull $rk3q1, $res0.1d, $h1.1d @ GHASH final block - low
+
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH final block - mid
+
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final block - high
+
+ pmull $t0.1q, $t0.1d, $h12k.1d @ GHASH final block - mid
+
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final block - low
+
+ eor $acc_mb, $acc_mb, $t0.16b @ GHASH final block - mid
+ movi $mod_constant.8b, #0xc2
+
+ eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
+
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
+
+ pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
+ orr $output_h0, $output_h0, $main_end_input_ptr
+ stp $output_l0, $output_h0, [$output_ptr]
+
+ ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
+
+ eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
+
+ eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
+
+ pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
+
+ eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
+
+ ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
+
+ eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
+ ext $acc_lb, $acc_lb, $acc_lb, #8
+ rev64 $acc_lb, $acc_lb
+ mov x0, $len
+ st1 { $acc_l.16b }, [$current_tag]
+
+ ldp x21, x22, [sp, #16]
+ ldp x23, x24, [sp, #32]
+ ldp d8, d9, [sp, #48]
+ ldp d10, d11, [sp, #64]
+ ldp d12, d13, [sp, #80]
+ ldp d14, d15, [sp, #96]
+ ldp x19, x20, [sp], #112
+ ret
+
+.L192_dec_ret:
+ mov w0, #0x0
+ ret
+.size aes_gcm_dec_192_kernel,.-aes_gcm_dec_192_kernel
+___
+}
+
+{
+my ($end_input_ptr,$main_end_input_ptr,$input_l0,$input_h0)=map("x$_",(4..7));
+my ($input_l1,$input_h1,$input_l2,$input_h2,$input_l3,$input_h3)=map("x$_",(19..24));
+my ($output_l1,$output_h1,$output_l2,$output_h2,$output_l3,$output_h3)=map("x$_",(19..24));
+my ($output_l0,$output_h0)=map("x$_",(6..7));
+
+my $ctr32w="w9";
+my ($ctr32x,$ctr96_b64x,$ctr96_t32x,$rctr32x,$rk14_l,$rk14_h,$len)=map("x$_",(9..15));
+my ($ctr96_t32w,$rctr32w)=map("w$_",(11..12));
+
+my ($ctr0b,$ctr1b,$ctr2b,$ctr3b,$res0b,$res1b,$res2b,$res3b)=map("v$_.16b",(0..7));
+my ($ctr0,$ctr1,$ctr2,$ctr3,$res0,$res1,$res2,$res3)=map("v$_",(0..7));
+my ($ctr0d,$ctr1d,$ctr2d,$ctr3d,$res0d,$res1d,$res2d,$res3d)=map("d$_",(0..7));
+my ($res0q,$res1q,$res2q,$res3q)=map("q$_",(4..7));
+
+my ($acc_hb,$acc_mb,$acc_lb)=map("v$_.16b",(9..11));
+my ($acc_h,$acc_m,$acc_l)=map("v$_",(9..11));
+my ($acc_hd,$acc_md,$acc_ld)=map("d$_",(9..11));
+
+my ($h1,$h2,$h3,$h4,$h12k,$h34k)=map("v$_",(12..17));
+my ($h1q,$h2q,$h3q,$h4q)=map("q$_",(12..15));
+my ($h1b,$h2b,$h3b,$h4b)=map("v$_.16b",(12..15));
+
+my $t0="v8";
+my $t0d="d8";
+my $t1="v4";
+my $t1d="d4";
+my $t2="v8";
+my $t2d="d8";
+my $t3="v4";
+my $t3d="d4";
+my $t4="v4";
+my $t4d="d4";
+my $t5="v5";
+my $t5d="d5";
+my $t6="v8";
+my $t6d="d8";
+my $t7="v5";
+my $t7d="d5";
+my $t8="v6";
+my $t8d="d6";
+my $t9="v4";
+my $t9d="d4";
+
+my ($ctr_t0,$ctr_t1,$ctr_t2,$ctr_t3)=map("v$_",(4..7));
+my ($ctr_t0d,$ctr_t1d,$ctr_t2d,$ctr_t3d)=map("d$_",(4..7));
+my ($ctr_t0b,$ctr_t1b,$ctr_t2b,$ctr_t3b)=map("v$_.16b",(4..7));
+
+my $mod_constantd="d8";
+my $mod_constant="v8";
+my $mod_t="v7";
+
+my ($rk0,$rk1,$rk2,$rk3,$rk4,$rk5,$rk6,$rk7,$rk8,$rk9,$rk10,$rk11,$rk12,$rk13)=map("v$_.16b",(18..31));
+my ($rk0q,$rk1q,$rk2q,$rk3q,$rk4q,$rk5q,$rk6q,$rk7q,$rk8q,$rk9q,$rk10q,$rk11q,$rk12q,$rk13q)=map("q$_",(18..31));
+my $rk2q1="v20.1q";
+my $rk3q1="v21.1q";
+my $rk4v="v22";
+my $rk4d="d22";
+
+#########################################################################################
+# size_t aes_gcm_enc_256_kernel(const unsigned char *in,
+# size_t len,
+# unsigned char *out,
+# const void *key,
+# unsigned char ivec[16],
+# u64 *Xi);
+#
+$code.=<<___;
+.global aes_gcm_enc_256_kernel
+.type aes_gcm_enc_256_kernel,%function
+.align 4
+aes_gcm_enc_256_kernel:
+ cbz x1, .L256_enc_ret
+ stp x19, x20, [sp, #-112]!
+ mov x16, x4
+ mov x8, x5
+ stp x21, x22, [sp, #16]
+ stp x23, x24, [sp, #32]
+ stp d8, d9, [sp, #48]
+ stp d10, d11, [sp, #64]
+ stp d12, d13, [sp, #80]
+ stp d14, d15, [sp, #96]
+
+ add $end_input_ptr, $input_ptr, $bit_length, lsr #3 @ end_input_ptr
+ lsr $main_end_input_ptr, $bit_length, #3 @ byte_len
+ mov $len, $main_end_input_ptr
+ ldp $ctr96_b64x, $ctr96_t32x, [$counter] @ ctr96_b64, ctr96_t32
+
+ ld1 { $ctr0b}, [$counter] @ special case vector load initial counter so we can start first AES block as quickly as possible
+ sub $main_end_input_ptr, $main_end_input_ptr, #1 @ byte_len - 1
+
+ ldr $rk0q, [$cc, #0] @ load rk0
+ and $main_end_input_ptr, $main_end_input_ptr, #0xffffffffffffffc0 @ number of bytes to be processed in main loop (at least 1 byte must be handled by tail)
+
+ ldr $rk7q, [$cc, #112] @ load rk7
+ add $main_end_input_ptr, $main_end_input_ptr, $input_ptr
+
+ lsr $rctr32x, $ctr96_t32x, #32
+ fmov $ctr2d, $ctr96_b64x @ CTR block 2
+ orr $ctr96_t32w, $ctr96_t32w, $ctr96_t32w
+
+ rev $rctr32w, $rctr32w @ rev_ctr32
+ cmp $input_ptr, $main_end_input_ptr @ check if we have <= 4 blocks
+ fmov $ctr1d, $ctr96_b64x @ CTR block 1
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 0
+ add $rctr32w, $rctr32w, #1 @ increment rev_ctr32
+
+ rev $ctr32w, $rctr32w @ CTR block 1
+ fmov $ctr3d, $ctr96_b64x @ CTR block 3
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 1
+ add $rctr32w, $rctr32w, #1 @ CTR block 1
+ ldr $rk1q, [$cc, #16] @ load rk1
+
+ fmov $ctr1.d[1], $ctr32x @ CTR block 1
+ rev $ctr32w, $rctr32w @ CTR block 2
+ add $rctr32w, $rctr32w, #1 @ CTR block 2
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 2
+ ldr $rk2q, [$cc, #32] @ load rk2
+
+ fmov $ctr2.d[1], $ctr32x @ CTR block 2
+ rev $ctr32w, $rctr32w @ CTR block 3
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 1
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 3
+
+ fmov $ctr3.d[1], $ctr32x @ CTR block 3
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 0
+ ldr $rk3q, [$cc, #48] @ load rk3
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 2
+ ldr $rk6q, [$cc, #96] @ load rk6
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
+ ldr $rk5q, [$cc, #80] @ load rk5
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
+ ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+ ext $h3b, $h3b, $h3b, #8
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 0
+ ldr $rk13q, [$cc, #208] @ load rk13
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 1
+ ldr $rk4q, [$cc, #64] @ load rk4
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 2
+ ldr $h2q, [$current_tag, #64] @ load h2l | h2h
+ ext $h2b, $h2b, $h2b, #8
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 1
+ ldr $rk12q, [$cc, #192] @ load rk12
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 2
+ ldr $h4q, [$current_tag, #112] @ load h4l | h4h
+ ext $h4b, $h4b, $h4b, #8
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 3
+ ldr $rk11q, [$cc, #176] @ load rk11
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 2
+ ldr $rk8q, [$cc, #128] @ load rk8
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 3
+ add $rctr32w, $rctr32w, #1 @ CTR block 3
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 3
+ ldp $rk14_l, $rk14_h, [$cc, #224] @ load rk14
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 3
+ ld1 { $acc_lb}, [$current_tag]
+ ext $acc_lb, $acc_lb, $acc_lb, #8
+ rev64 $acc_lb, $acc_lb
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 4
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 4
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 4
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 4
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 5
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 5
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 5
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 5
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 6
+ trn2 $h34k.2d, $h3.2d, $h4.2d @ h4l | h3l
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 6
+ ldr $rk9q, [$cc, #144] @ load rk9
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 6
+ ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+ ext $h1b, $h1b, $h1b, #8
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 6
+ ldr $rk10q, [$cc, #160] @ load rk10
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 7
+ trn1 $acc_h.2d, $h3.2d, $h4.2d @ h4h | h3h
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 7
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 7
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 7
+ trn2 $h12k.2d, $h1.2d, $h2.2d @ h2l | h1l
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 8
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 8
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 8
+
+ aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 9
+
+ aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 9
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 8
+
+ aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 10
+
+ aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 9
+
+ aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 9
+
+ aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 10
+
+ aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 10
+
+ aese $ctr1b, $rk11 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 11
+
+ aese $ctr2b, $rk11 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 11
+
+ aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 10
+
+ aese $ctr1b, $rk12 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 12
+
+ aese $ctr2b, $rk12 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 12
+
+ aese $ctr0b, $rk11 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 11
+ eor $h34k.16b, $h34k.16b, $acc_h.16b @ h4k | h3k
+
+ aese $ctr3b, $rk11 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 11
+
+ aese $ctr2b, $rk13 @ AES block 2 - round 13
+ trn1 $t0.2d, $h1.2d, $h2.2d @ h2h | h1h
+
+ aese $ctr0b, $rk12 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 12
+
+ aese $ctr3b, $rk12 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 12
+
+ aese $ctr1b, $rk13 @ AES block 1 - round 13
+
+ aese $ctr0b, $rk13 @ AES block 0 - round 13
+
+ aese $ctr3b, $rk13 @ AES block 3 - round 13
+ eor $h12k.16b, $h12k.16b, $t0.16b @ h2k | h1k
+ b.ge .L256_enc_tail @ handle tail
+
+ ldp $input_l1, $input_h1, [$input_ptr, #16] @ AES block 1 - load plaintext
+
+ rev $ctr32w, $rctr32w @ CTR block 4
+ ldp $input_l0, $input_h0, [$input_ptr, #0] @ AES block 0 - load plaintext
+
+ ldp $input_l3, $input_h3, [$input_ptr, #48] @ AES block 3 - load plaintext
+
+ ldp $input_l2, $input_h2, [$input_ptr, #32] @ AES block 2 - load plaintext
+ add $input_ptr, $input_ptr, #64 @ AES input_ptr update
+
+ eor $input_l1, $input_l1, $rk14_l @ AES block 1 - round 14 low
+ eor $input_h1, $input_h1, $rk14_h @ AES block 1 - round 14 high
+
+ fmov $ctr_t1d, $input_l1 @ AES block 1 - mov low
+ eor $input_l0, $input_l0, $rk14_l @ AES block 0 - round 14 low
+
+ eor $input_h0, $input_h0, $rk14_h @ AES block 0 - round 14 high
+ eor $input_h3, $input_h3, $rk14_h @ AES block 3 - round 14 high
+ fmov $ctr_t0d, $input_l0 @ AES block 0 - mov low
+
+ cmp $input_ptr, $main_end_input_ptr @ check if we have <= 8 blocks
+ fmov $ctr_t0.d[1], $input_h0 @ AES block 0 - mov high
+ eor $input_l3, $input_l3, $rk14_l @ AES block 3 - round 14 low
+
+ eor $input_l2, $input_l2, $rk14_l @ AES block 2 - round 14 low
+ fmov $ctr_t1.d[1], $input_h1 @ AES block 1 - mov high
+
+ fmov $ctr_t2d, $input_l2 @ AES block 2 - mov low
+ add $rctr32w, $rctr32w, #1 @ CTR block 4
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4
+ fmov $ctr_t3d, $input_l3 @ AES block 3 - mov low
+ eor $input_h2, $input_h2, $rk14_h @ AES block 2 - round 14 high
+
+ fmov $ctr_t2.d[1], $input_h2 @ AES block 2 - mov high
+
+ eor $res0b, $ctr_t0b, $ctr0b @ AES block 0 - result
+ fmov $ctr0d, $ctr96_b64x @ CTR block 4
+
+ fmov $ctr0.d[1], $ctr32x @ CTR block 4
+ rev $ctr32w, $rctr32w @ CTR block 5
+ add $rctr32w, $rctr32w, #1 @ CTR block 5
+
+ eor $res1b, $ctr_t1b, $ctr1b @ AES block 1 - result
+ fmov $ctr1d, $ctr96_b64x @ CTR block 5
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 5
+
+ fmov $ctr1.d[1], $ctr32x @ CTR block 5
+ rev $ctr32w, $rctr32w @ CTR block 6
+ st1 { $res0b}, [$output_ptr], #16 @ AES block 0 - store result
+
+ fmov $ctr_t3.d[1], $input_h3 @ AES block 3 - mov high
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 6
+ eor $res2b, $ctr_t2b, $ctr2b @ AES block 2 - result
+
+ st1 { $res1b}, [$output_ptr], #16 @ AES block 1 - store result
+
+ add $rctr32w, $rctr32w, #1 @ CTR block 6
+ fmov $ctr2d, $ctr96_b64x @ CTR block 6
+
+ fmov $ctr2.d[1], $ctr32x @ CTR block 6
+ st1 { $res2b}, [$output_ptr], #16 @ AES block 2 - store result
+ rev $ctr32w, $rctr32w @ CTR block 7
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 7
+
+ eor $res3b, $ctr_t3b, $ctr3b @ AES block 3 - result
+ st1 { $res3b}, [$output_ptr], #16 @ AES block 3 - store result
+ b.ge L256_enc_prepretail @ do prepretail
+
+ .L256_enc_main_loop: @ main loop start
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
+ rev64 $res0b, $res0b @ GHASH block 4k (only t0 is free)
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
+ fmov $ctr3d, $ctr96_b64x @ CTR block 4k+3
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
+ ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
+ fmov $ctr3.d[1], $ctr32x @ CTR block 4k+3
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
+ ldp $input_l3, $input_h3, [$input_ptr, #48] @ AES block 4k+7 - load plaintext
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
+ ldp $input_l2, $input_h2, [$input_ptr, #32] @ AES block 4k+6 - load plaintext
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
+ eor $res0b, $res0b, $acc_lb @ PRE 1
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
+ eor $input_l3, $input_l3, $rk14_l @ AES block 4k+7 - round 14 low
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
+ mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
+ eor $input_h2, $input_h2, $rk14_h @ AES block 4k+6 - round 14 high
+ mov $t0d, $res0.d[1] @ GHASH block 4k - mid
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
+ rev64 $res1b, $res1b @ GHASH block 4k+1 (t0 and t1 free)
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
+ rev64 $res3b, $res3b @ GHASH block 4k+3 (t0, t1, t2 and t3 free)
+
+ pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
+
+ pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
+ rev64 $res2b, $res2b @ GHASH block 4k+2 (t0, t1, and t2 free)
+
+ pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
+
+ eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
+ mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
+ eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
+ mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
+ eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
+ eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
+
+ pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
+ ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
+ eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
+
+ pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
+
+ pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
+
+ pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
+ eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
+ ldp $input_l1, $input_h1, [$input_ptr, #16] @ AES block 4k+5 - load plaintext
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
+ mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
+ eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
+
+ pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
+
+ pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
+ eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
+ eor $input_l1, $input_l1, $rk14_l @ AES block 4k+5 - round 14 low
+
+ aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 9
+ eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
+ eor $input_l2, $input_l2, $rk14_l @ AES block 4k+6 - round 14 low
+
+ aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 9
+ movi $mod_constant.8b, #0xc2
+
+ pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
+ eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
+ fmov $ctr_t1d, $input_l1 @ AES block 4k+5 - mov low
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
+ ldp $input_l0, $input_h0, [$input_ptr, #0] @ AES block 4k+4 - load plaintext
+
+ aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 10
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
+ eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
+
+ aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 9
+
+ aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 10
+ eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
+
+ aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 9
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+3
+
+ aese $ctr0b, $rk11 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 11
+ eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
+
+ aese $ctr1b, $rk11 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 11
+ add $input_ptr, $input_ptr, #64 @ AES input_ptr update
+
+ pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
+ rev $ctr32w, $rctr32w @ CTR block 4k+8
+ ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
+
+ aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 10
+ eor $input_l0, $input_l0, $rk14_l @ AES block 4k+4 - round 14 low
+
+ aese $ctr1b, $rk12 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 12
+ eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
+
+ aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 10
+ eor $input_h0, $input_h0, $rk14_h @ AES block 4k+4 - round 14 high
+
+ fmov $ctr_t0d, $input_l0 @ AES block 4k+4 - mov low
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+8
+ eor $mod_t.16b, $acc_hb, $mod_t.16b @ MODULO - fold into mid
+
+ aese $ctr0b, $rk12 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 12
+ eor $input_h1, $input_h1, $rk14_h @ AES block 4k+5 - round 14 high
+
+ aese $ctr2b, $rk11 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 11
+ eor $input_h3, $input_h3, $rk14_h @ AES block 4k+7 - round 14 high
+
+ aese $ctr3b, $rk11 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 11
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+8
+
+ aese $ctr0b, $rk13 @ AES block 4k+4 - round 13
+ fmov $ctr_t0.d[1], $input_h0 @ AES block 4k+4 - mov high
+ eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
+
+ aese $ctr2b, $rk12 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 12
+ fmov $ctr_t3d, $input_l3 @ AES block 4k+7 - mov low
+
+ aese $ctr1b, $rk13 @ AES block 4k+5 - round 13
+ fmov $ctr_t1.d[1], $input_h1 @ AES block 4k+5 - mov high
+
+ fmov $ctr_t2d, $input_l2 @ AES block 4k+6 - mov low
+ cmp $input_ptr, $main_end_input_ptr @ LOOP CONTROL
+
+ fmov $ctr_t2.d[1], $input_h2 @ AES block 4k+6 - mov high
+
+ pmull $acc_h.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
+ eor $res0b, $ctr_t0b, $ctr0b @ AES block 4k+4 - result
+ fmov $ctr0d, $ctr96_b64x @ CTR block 4k+8
+
+ fmov $ctr0.d[1], $ctr32x @ CTR block 4k+8
+ rev $ctr32w, $rctr32w @ CTR block 4k+9
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+9
+
+ eor $res1b, $ctr_t1b, $ctr1b @ AES block 4k+5 - result
+ fmov $ctr1d, $ctr96_b64x @ CTR block 4k+9
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+9
+
+ aese $ctr3b, $rk12 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 12
+ fmov $ctr1.d[1], $ctr32x @ CTR block 4k+9
+
+ aese $ctr2b, $rk13 @ AES block 4k+6 - round 13
+ rev $ctr32w, $rctr32w @ CTR block 4k+10
+ st1 { $res0b}, [$output_ptr], #16 @ AES block 4k+4 - store result
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+10
+ eor $acc_lb, $acc_lb, $acc_hb @ MODULO - fold into low
+ fmov $ctr_t3.d[1], $input_h3 @ AES block 4k+7 - mov high
+
+ ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
+ st1 { $res1b}, [$output_ptr], #16 @ AES block 4k+5 - store result
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+10
+
+ aese $ctr3b, $rk13 @ AES block 4k+7 - round 13
+ eor $res2b, $ctr_t2b, $ctr2b @ AES block 4k+6 - result
+ fmov $ctr2d, $ctr96_b64x @ CTR block 4k+10
+
+ st1 { $res2b}, [$output_ptr], #16 @ AES block 4k+6 - store result
+ fmov $ctr2.d[1], $ctr32x @ CTR block 4k+10
+ rev $ctr32w, $rctr32w @ CTR block 4k+11
+
+ eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+11
+
+ eor $res3b, $ctr_t3b, $ctr3b @ AES block 4k+7 - result
+ st1 { $res3b}, [$output_ptr], #16 @ AES block 4k+7 - store result
+ b.lt L256_enc_main_loop
+
+ .L256_enc_prepretail: @ PREPRETAIL
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
+ rev64 $res2b, $res2b @ GHASH block 4k+2 (t0, t1, and t2 free)
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
+ fmov $ctr3d, $ctr96_b64x @ CTR block 4k+3
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
+ rev64 $res0b, $res0b @ GHASH block 4k (only t0 is free)
+
+ fmov $ctr3.d[1], $ctr32x @ CTR block 4k+3
+ ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
+
+ eor $res0b, $res0b, $acc_lb @ PRE 1
+ rev64 $res1b, $res1b @ GHASH block 4k+1 (t0 and t1 free)
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
+ mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
+ mov $t0d, $res0.d[1] @ GHASH block 4k - mid
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
+
+ pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
+
+ pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
+
+ pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
+
+ eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
+ mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
+ eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
+
+ eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
+ mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
+ rev64 $res3b, $res3b @ GHASH block 4k+3 (t0, t1, t2 and t3 free)
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
+
+ pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
+ eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+3
+
+ pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
+ eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
+
+ pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
+
+ eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
+ ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
+
+ eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
+ mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
+
+ pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
+
+ eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
+
+ pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
+
+ pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
+ eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
+ movi $mod_constant.8b, #0xc2
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
+ eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
+ eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
+
+ pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
+
+ aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 9
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
+ eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
+
+ aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 9
+
+ eor $acc_mb, $acc_mb, $acc_hb @ karatsuba tidy up
+
+ pmull $t1.1q, $acc_h.1d, $mod_constant.1d
+ ext $acc_hb, $acc_hb, $acc_hb, #8
+
+ aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 10
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
+ eor $acc_mb, $acc_mb, $acc_lb
+
+ aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 10
+
+ aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 9
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
+
+ aese $ctr1b, $rk11 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 11
+ eor $acc_mb, $acc_mb, $t1.16b
+
+ aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 10
+
+ aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 9
+
+ aese $ctr1b, $rk12 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 12
+
+ aese $ctr0b, $rk11 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 11
+ eor $acc_mb, $acc_mb, $acc_hb
+
+ aese $ctr3b, $rk11 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 11
+
+ aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 10
+
+ aese $ctr0b, $rk12 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 12
+
+ pmull $t1.1q, $acc_m.1d, $mod_constant.1d
+
+ aese $ctr2b, $rk11 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 11
+ ext $acc_mb, $acc_mb, $acc_mb, #8
+
+ aese $ctr3b, $rk12 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 12
+
+ aese $ctr1b, $rk13 @ AES block 4k+5 - round 13
+ eor $acc_lb, $acc_lb, $t1.16b
+
+ aese $ctr2b, $rk12 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 12
+
+ aese $ctr3b, $rk13 @ AES block 4k+7 - round 13
+
+ aese $ctr0b, $rk13 @ AES block 4k+4 - round 13
+
+ aese $ctr2b, $rk13 @ AES block 4k+6 - round 13
+ eor $acc_lb, $acc_lb, $acc_mb
+ .L256_enc_tail: @ TAIL
+
+ ext $t0.16b, $acc_lb, $acc_lb, #8 @ prepare final partial tag
+ sub $main_end_input_ptr, $end_input_ptr, $input_ptr @ main_end_input_ptr is number of bytes left to process
+ ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES block 4k+4 - load plaintext
+
+ eor $input_l0, $input_l0, $rk14_l @ AES block 4k+4 - round 14 low
+ eor $input_h0, $input_h0, $rk14_h @ AES block 4k+4 - round 14 high
+
+ cmp $main_end_input_ptr, #48
+ fmov $ctr_t0d, $input_l0 @ AES block 4k+4 - mov low
+
+ fmov $ctr_t0.d[1], $input_h0 @ AES block 4k+4 - mov high
+
+ eor $res1b, $ctr_t0b, $ctr0b @ AES block 4k+4 - result
+ b.gt .L256_enc_blocks_more_than_3
+
+ cmp $main_end_input_ptr, #32
+ mov $ctr3b, $ctr2b
+ movi $acc_l.8b, #0
+
+ movi $acc_h.8b, #0
+ sub $rctr32w, $rctr32w, #1
+
+ mov $ctr2b, $ctr1b
+ movi $acc_m.8b, #0
+ b.gt .L256_enc_blocks_more_than_2
+
+ mov $ctr3b, $ctr1b
+ sub $rctr32w, $rctr32w, #1
+ cmp $main_end_input_ptr, #16
+
+ b.gt .L256_enc_blocks_more_than_1
+
+ sub $rctr32w, $rctr32w, #1
+ b .L256_enc_blocks_less_than_1
+ .L256_enc_blocks_more_than_3: @ blocks left > 3
+ st1 { $res1b}, [$output_ptr], #16 @ AES final-3 block - store result
+
+ ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final-2 block - load input low & high
+
+ rev64 $res0b, $res1b @ GHASH final-3 block
+
+ eor $input_l0, $input_l0, $rk14_l @ AES final-2 block - round 14 low
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ eor $input_h0, $input_h0, $rk14_h @ AES final-2 block - round 14 high
+
+ mov $rk4d, $res0.d[1] @ GHASH final-3 block - mid
+ fmov $res1d, $input_l0 @ AES final-2 block - mov low
+
+ fmov $res1.d[1], $input_h0 @ AES final-2 block - mov high
+
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-3 block - mid
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+
+ mov $acc_md, $h34k.d[1] @ GHASH final-3 block - mid
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH final-3 block - low
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH final-3 block - high
+
+ pmull $acc_m.1q, $rk4v.1d, $acc_m.1d @ GHASH final-3 block - mid
+ eor $res1b, $res1b, $ctr1b @ AES final-2 block - result
+ .L256_enc_blocks_more_than_2: @ blocks left > 2
+
+ st1 { $res1b}, [$output_ptr], #16 @ AES final-2 block - store result
+
+ ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final-1 block - load input low & high
+
+ rev64 $res0b, $res1b @ GHASH final-2 block
+
+ eor $input_l0, $input_l0, $rk14_l @ AES final-1 block - round 14 low
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ fmov $res1d, $input_l0 @ AES final-1 block - mov low
+ eor $input_h0, $input_h0, $rk14_h @ AES final-1 block - round 14 high
+
+ fmov $res1.d[1], $input_h0 @ AES final-1 block - mov high
+
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+
+ pmull2 $rk2q1, $res0.2d, $h3.2d @ GHASH final-2 block - high
+ mov $rk4d, $res0.d[1] @ GHASH final-2 block - mid
+
+ pmull $rk3q1, $res0.1d, $h3.1d @ GHASH final-2 block - low
+
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-2 block - mid
+
+ eor $res1b, $res1b, $ctr2b @ AES final-1 block - result
+
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final-2 block - high
+
+ pmull $rk4v.1q, $rk4v.1d, $h34k.1d @ GHASH final-2 block - mid
+
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final-2 block - low
+
+ eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-2 block - mid
+ .L256_enc_blocks_more_than_1: @ blocks left > 1
+
+ st1 { $res1b}, [$output_ptr], #16 @ AES final-1 block - store result
+
+ rev64 $res0b, $res1b @ GHASH final-1 block
+
+ ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final block - load input low & high
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+
+ eor $input_l0, $input_l0, $rk14_l @ AES final block - round 14 low
+ mov $rk4d, $res0.d[1] @ GHASH final-1 block - mid
+
+ pmull2 $rk2q1, $res0.2d, $h2.2d @ GHASH final-1 block - high
+ eor $input_h0, $input_h0, $rk14_h @ AES final block - round 14 high
+
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-1 block - mid
+
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final-1 block - high
+
+ ins $rk4v.d[1], $rk4v.d[0] @ GHASH final-1 block - mid
+ fmov $res1d, $input_l0 @ AES final block - mov low
+
+ fmov $res1.d[1], $input_h0 @ AES final block - mov high
+
+ pmull2 $rk4v.1q, $rk4v.2d, $h12k.2d @ GHASH final-1 block - mid
+
+ pmull $rk3q1, $res0.1d, $h2.1d @ GHASH final-1 block - low
+
+ eor $res1b, $res1b, $ctr3b @ AES final block - result
+ eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-1 block - mid
+
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final-1 block - low
+ .L256_enc_blocks_less_than_1: @ blocks left <= 1
+
+ and $bit_length, $bit_length, #127 @ bit_length %= 128
+
+ mvn $rk14_l, xzr @ rk14_l = 0xffffffffffffffff
+ sub $bit_length, $bit_length, #128 @ bit_length -= 128
+
+ neg $bit_length, $bit_length @ bit_length = 128 - #bits in input (in range [1,128])
+ ld1 { $rk0}, [$output_ptr] @ load existing bytes where the possibly partial last block is to be stored
+
+ mvn $rk14_h, xzr @ rk14_h = 0xffffffffffffffff
+ and $bit_length, $bit_length, #127 @ bit_length %= 128
+
+ lsr $rk14_h, $rk14_h, $bit_length @ rk14_h is mask for top 64b of last block
+ cmp $bit_length, #64
+
+ csel $input_l0, $rk14_l, $rk14_h, lt
+ csel $input_h0, $rk14_h, xzr, lt
+
+ fmov $ctr0d, $input_l0 @ ctr0b is mask for last block
+
+ fmov $ctr0.d[1], $input_h0
+
+ and $res1b, $res1b, $ctr0b @ possibly partial last block has zeroes in highest bits
+
+ rev64 $res0b, $res1b @ GHASH final block
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ bif $res1b, $rk0, $ctr0b @ insert existing bytes in top end of result before storing
+
+ pmull2 $rk2q1, $res0.2d, $h1.2d @ GHASH final block - high
+ mov $t0d, $res0.d[1] @ GHASH final block - mid
+ rev $ctr32w, $rctr32w
+
+ pmull $rk3q1, $res0.1d, $h1.1d @ GHASH final block - low
+
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final block - high
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH final block - mid
+
+ pmull $t0.1q, $t0.1d, $h12k.1d @ GHASH final block - mid
+
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final block - low
+
+ eor $acc_mb, $acc_mb, $t0.16b @ GHASH final block - mid
+ movi $mod_constant.8b, #0xc2
+
+ eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
+
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
+
+ pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
+
+ ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
+
+ eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
+
+ eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
+
+ pmull $acc_h.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
+
+ ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
+
+ str $ctr32w, [$counter, #12] @ store the updated counter
+
+ st1 { $res1b}, [$output_ptr] @ store all 16B
+ eor $acc_lb, $acc_lb, $acc_hb @ MODULO - fold into low
+
+ eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
+ ext $acc_lb, $acc_lb, $acc_lb, #8
+ rev64 $acc_lb, $acc_lb
+ mov x0, $len
+ st1 { $acc_l.16b }, [$current_tag]
+
+ ldp x21, x22, [sp, #16]
+ ldp x23, x24, [sp, #32]
+ ldp d8, d9, [sp, #48]
+ ldp d10, d11, [sp, #64]
+ ldp d12, d13, [sp, #80]
+ ldp d14, d15, [sp, #96]
+ ldp x19, x20, [sp], #112
+ ret
+
+.L256_enc_ret:
+ mov w0, #0x0
+ ret
+.size aes_gcm_enc_256_kernel,.-aes_gcm_enc_256_kernel
+___
+
+{
+my $t8="v4";
+my $t8d="d4";
+my $t9="v6";
+my $t9d="d6";
+#########################################################################################
+# size_t aes_gcm_dec_256_kernel(const unsigned char *in,
+# size_t len,
+# unsigned char *out,
+# const void *key,
+# unsigned char ivec[16],
+# u64 *Xi);
+#
+$code.=<<___;
+.global aes_gcm_dec_256_kernel
+.type aes_gcm_dec_256_kernel,%function
+.align 4
+aes_gcm_dec_256_kernel:
+ cbz x1, .L256_dec_ret
+ stp x19, x20, [sp, #-112]!
+ mov x16, x4
+ mov x8, x5
+ stp x21, x22, [sp, #16]
+ stp x23, x24, [sp, #32]
+ stp d8, d9, [sp, #48]
+ stp d10, d11, [sp, #64]
+ stp d12, d13, [sp, #80]
+ stp d14, d15, [sp, #96]
+
+ lsr $main_end_input_ptr, $bit_length, #3 @ byte_len
+ mov $len, $main_end_input_ptr
+ ldp $ctr96_b64x, $ctr96_t32x, [$counter] @ ctr96_b64, ctr96_t32
+
+ ldr $rk8q, [$cc, #128] @ load rk8
+ sub $main_end_input_ptr, $main_end_input_ptr, #1 @ byte_len - 1
+
+ ldr $rk7q, [$cc, #112] @ load rk7
+ and $main_end_input_ptr, $main_end_input_ptr, #0xffffffffffffffc0 @ number of bytes to be processed in main loop (at least 1 byte must be handled by tail)
+
+ add $end_input_ptr, $input_ptr, $bit_length, lsr #3 @ end_input_ptr
+ ldr $rk6q, [$cc, #96] @ load rk6
+
+ lsr $rctr32x, $ctr96_t32x, #32
+ ldr $rk5q, [$cc, #80] @ load rk5
+ orr $ctr96_t32w, $ctr96_t32w, $ctr96_t32w
+
+ ldr $rk3q, [$cc, #48] @ load rk3
+ add $main_end_input_ptr, $main_end_input_ptr, $input_ptr
+ rev $rctr32w, $rctr32w @ rev_ctr32
+
+ add $rctr32w, $rctr32w, #1 @ increment rev_ctr32
+ fmov $ctr3d, $ctr96_b64x @ CTR block 3
+
+ rev $ctr32w, $rctr32w @ CTR block 1
+ add $rctr32w, $rctr32w, #1 @ CTR block 1
+ fmov $ctr1d, $ctr96_b64x @ CTR block 1
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 1
+ ld1 { $ctr0b}, [$counter] @ special case vector load initial counter so we can start first AES block as quickly as possible
+
+ fmov $ctr1.d[1], $ctr32x @ CTR block 1
+ rev $ctr32w, $rctr32w @ CTR block 2
+ add $rctr32w, $rctr32w, #1 @ CTR block 2
+
+ fmov $ctr2d, $ctr96_b64x @ CTR block 2
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 2
+
+ fmov $ctr2.d[1], $ctr32x @ CTR block 2
+ rev $ctr32w, $rctr32w @ CTR block 3
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 3
+ ldr $rk0q, [$cc, #0] @ load rk0
+
+ fmov $ctr3.d[1], $ctr32x @ CTR block 3
+ add $rctr32w, $rctr32w, #1 @ CTR block 3
+
+ ldr $rk4q, [$cc, #64] @ load rk4
+
+ ldr $rk13q, [$cc, #208] @ load rk13
+
+ ldr $rk1q, [$cc, #16] @ load rk1
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 0
+ ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+ ext $h3b, $h3b, $h3b, #8
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 0
+ ldr $h4q, [$current_tag, #112] @ load h4l | h4h
+ ext $h4b, $h4b, $h4b, #8
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 0
+ ldr $h2q, [$current_tag, #64] @ load h2l | h2h
+ ext $h2b, $h2b, $h2b, #8
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
+ ldr $rk2q, [$cc, #32] @ load rk2
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 1
+ ldp $rk14_l, $rk14_h, [$cc, #224] @ load rk14
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
+ ld1 { $acc_lb}, [$current_tag]
+ ext $acc_lb, $acc_lb, $acc_lb, #8
+ rev64 $acc_lb, $acc_lb
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 1
+ ldr $rk9q, [$cc, #144] @ load rk9
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 1
+ ldr $rk12q, [$cc, #192] @ load rk12
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 2
+ ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+ ext $h1b, $h1b, $h1b, #8
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 2
+ ldr $rk10q, [$cc, #160] @ load rk10
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 2
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 3
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 2
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 3
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 4
+ cmp $input_ptr, $main_end_input_ptr @ check if we have <= 4 blocks
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 3
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 3
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 4
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 4
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 4
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 5
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 5
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 5
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 5
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 6
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 6
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 6
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 6
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 7
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 7
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 7
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 8
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 7
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 8
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 8
+
+ aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 9
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 8
+ ldr $rk11q, [$cc, #176] @ load rk11
+
+ aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 9
+
+ aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 10
+
+ aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 9
+
+ aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 10
+
+ aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 9
+
+ aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 10
+
+ aese $ctr0b, $rk11 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 11
+
+ aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 10
+
+ aese $ctr3b, $rk11 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 11
+
+ aese $ctr1b, $rk11 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 11
+
+ aese $ctr2b, $rk11 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 11
+
+ trn1 $acc_h.2d, $h3.2d, $h4.2d @ h4h | h3h
+
+ trn2 $h34k.2d, $h3.2d, $h4.2d @ h4l | h3l
+
+ trn1 $t0.2d, $h1.2d, $h2.2d @ h2h | h1h
+ trn2 $h12k.2d, $h1.2d, $h2.2d @ h2l | h1l
+
+ aese $ctr1b, $rk12 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 12
+
+ aese $ctr0b, $rk12 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 12
+
+ aese $ctr2b, $rk12 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 12
+
+ aese $ctr3b, $rk12 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 12
+ eor $h34k.16b, $h34k.16b, $acc_h.16b @ h4k | h3k
+
+ aese $ctr1b, $rk13 @ AES block 1 - round 13
+
+ aese $ctr2b, $rk13 @ AES block 2 - round 13
+ eor $h12k.16b, $h12k.16b, $t0.16b @ h2k | h1k
+
+ aese $ctr3b, $rk13 @ AES block 3 - round 13
+
+ aese $ctr0b, $rk13 @ AES block 0 - round 13
+ b.ge .L256_dec_tail @ handle tail
+
+ ldr $res0q, [$input_ptr, #0] @ AES block 0 - load ciphertext
+
+ ldr $res1q, [$input_ptr, #16] @ AES block 1 - load ciphertext
+
+ rev $ctr32w, $rctr32w @ CTR block 4
+
+ eor $ctr0b, $res0b, $ctr0b @ AES block 0 - result
+
+ eor $ctr1b, $res1b, $ctr1b @ AES block 1 - result
+ rev64 $res1b, $res1b @ GHASH block 1
+ ldr $res3q, [$input_ptr, #48] @ AES block 3 - load ciphertext
+
+ mov $output_h0, $ctr0.d[1] @ AES block 0 - mov high
+
+ mov $output_l0, $ctr0.d[0] @ AES block 0 - mov low
+ rev64 $res0b, $res0b @ GHASH block 0
+ add $rctr32w, $rctr32w, #1 @ CTR block 4
+
+ fmov $ctr0d, $ctr96_b64x @ CTR block 4
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4
+
+ fmov $ctr0.d[1], $ctr32x @ CTR block 4
+ rev $ctr32w, $rctr32w @ CTR block 5
+ add $rctr32w, $rctr32w, #1 @ CTR block 5
+
+ mov $output_l1, $ctr1.d[0] @ AES block 1 - mov low
+
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 5
+ mov $output_h1, $ctr1.d[1] @ AES block 1 - mov high
+ eor $output_h0, $output_h0, $rk14_h @ AES block 0 - round 14 high
+
+ eor $output_l0, $output_l0, $rk14_l @ AES block 0 - round 14 low
+ stp $output_l0, $output_h0, [$output_ptr], #16 @ AES block 0 - store result
+ fmov $ctr1d, $ctr96_b64x @ CTR block 5
+
+ ldr $res2q, [$input_ptr, #32] @ AES block 2 - load ciphertext
+ add $input_ptr, $input_ptr, #64 @ AES input_ptr update
+
+ fmov $ctr1.d[1], $ctr32x @ CTR block 5
+ rev $ctr32w, $rctr32w @ CTR block 6
+ add $rctr32w, $rctr32w, #1 @ CTR block 6
+
+ eor $output_l1, $output_l1, $rk14_l @ AES block 1 - round 14 low
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 6
+
+ eor $output_h1, $output_h1, $rk14_h @ AES block 1 - round 14 high
+ stp $output_l1, $output_h1, [$output_ptr], #16 @ AES block 1 - store result
+
+ eor $ctr2b, $res2b, $ctr2b @ AES block 2 - result
+ cmp $input_ptr, $main_end_input_ptr @ check if we have <= 8 blocks
+ b.ge .L256_dec_prepretail @ do prepretail
+
+ .L256_dec_main_loop: @ main loop start
+ mov $output_l2, $ctr2.d[0] @ AES block 4k+2 - mov low
+ ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
+ eor $ctr3b, $res3b, $ctr3b @ AES block 4k+3 - result
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
+ mov $output_h2, $ctr2.d[1] @ AES block 4k+2 - mov high
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
+ fmov $ctr2d, $ctr96_b64x @ CTR block 4k+6
+
+ fmov $ctr2.d[1], $ctr32x @ CTR block 4k+6
+ eor $res0b, $res0b, $acc_lb @ PRE 1
+ rev $ctr32w, $rctr32w @ CTR block 4k+7
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
+ mov $output_h3, $ctr3.d[1] @ AES block 4k+3 - mov high
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
+ mov $output_l3, $ctr3.d[0] @ AES block 4k+3 - mov low
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
+ mov $t0d, $res0.d[1] @ GHASH block 4k - mid
+ fmov $ctr3d, $ctr96_b64x @ CTR block 4k+7
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+7
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
+ fmov $ctr3.d[1], $ctr32x @ CTR block 4k+7
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
+ eor $output_h2, $output_h2, $rk14_h @ AES block 4k+2 - round 14 high
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
+ mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
+ rev64 $res2b, $res2b @ GHASH block 4k+2
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
+ eor $output_l2, $output_l2, $rk14_l @ AES block 4k+2 - round 14 low
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
+ stp $output_l2, $output_h2, [$output_ptr], #16 @ AES block 4k+2 - store result
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
+
+ pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
+ rev64 $res3b, $res3b @ GHASH block 4k+3
+
+ pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
+ eor $output_l3, $output_l3, $rk14_l @ AES block 4k+3 - round 14 low
+
+ pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
+ eor $output_h3, $output_h3, $rk14_h @ AES block 4k+3 - round 14 high
+ eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
+ mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
+ eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+7
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
+ mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
+ eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
+
+ pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
+ eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
+ eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
+
+ pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
+ rev $ctr32w, $rctr32w @ CTR block 4k+8
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
+ ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+8
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
+ eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
+
+ pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
+ mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
+
+ pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
+ eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
+
+ pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+8
+ eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
+
+ pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
+
+ aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 9
+ eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
+ eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
+
+ aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 10
+
+ pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
+ movi $mod_constant.8b, #0xc2
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
+ eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
+
+ aese $ctr0b, $rk11 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 11
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
+ eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
+
+ aese $ctr0b, $rk12 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 12
+
+ pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
+ eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
+
+ aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 9
+ ldr $res0q, [$input_ptr, #0] @ AES block 4k+4 - load ciphertext
+
+ aese $ctr0b, $rk13 @ AES block 4k+4 - round 13
+ ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
+
+ aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 10
+ eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
+
+ aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 9
+ ldr $res1q, [$input_ptr, #16] @ AES block 4k+5 - load ciphertext
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
+ eor $ctr0b, $res0b, $ctr0b @ AES block 4k+4 - result
+
+ aese $ctr1b, $rk11 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 11
+ stp $output_l3, $output_h3, [$output_ptr], #16 @ AES block 4k+3 - store result
+
+ aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 10
+ eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
+
+ aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 9
+ ldr $res3q, [$input_ptr, #48] @ AES block 4k+7 - load ciphertext
+
+ aese $ctr1b, $rk12 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 12
+ ldr $res2q, [$input_ptr, #32] @ AES block 4k+6 - load ciphertext
+
+ aese $ctr2b, $rk11 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 11
+ mov $output_h0, $ctr0.d[1] @ AES block 4k+4 - mov high
+
+ aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 10
+ eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
+
+ aese $ctr1b, $rk13 @ AES block 4k+5 - round 13
+ add $input_ptr, $input_ptr, #64 @ AES input_ptr update
+ mov $output_l0, $ctr0.d[0] @ AES block 4k+4 - mov low
+
+ aese $ctr2b, $rk12 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 12
+ fmov $ctr0d, $ctr96_b64x @ CTR block 4k+8
+
+ aese $ctr3b, $rk11 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 11
+ fmov $ctr0.d[1], $ctr32x @ CTR block 4k+8
+
+ pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
+ eor $ctr1b, $res1b, $ctr1b @ AES block 4k+5 - result
+ rev $ctr32w, $rctr32w @ CTR block 4k+9
+
+ aese $ctr2b, $rk13 @ AES block 4k+6 - round 13
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+9
+ cmp $input_ptr, $main_end_input_ptr @ LOOP CONTROL
+
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+9
+
+ eor $output_l0, $output_l0, $rk14_l @ AES block 4k+4 - round 14 low
+ eor $output_h0, $output_h0, $rk14_h @ AES block 4k+4 - round 14 high
+
+ mov $output_h1, $ctr1.d[1] @ AES block 4k+5 - mov high
+ eor $ctr2b, $res2b, $ctr2b @ AES block 4k+6 - result
+ eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
+
+ aese $ctr3b, $rk12 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 12
+ mov $output_l1, $ctr1.d[0] @ AES block 4k+5 - mov low
+
+ fmov $ctr1d, $ctr96_b64x @ CTR block 4k+9
+ ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
+
+ fmov $ctr1.d[1], $ctr32x @ CTR block 4k+9
+ rev $ctr32w, $rctr32w @ CTR block 4k+10
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+10
+
+ aese $ctr3b, $rk13 @ AES block 4k+7 - round 13
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+10
+
+ rev64 $res1b, $res1b @ GHASH block 4k+5
+ eor $output_h1, $output_h1, $rk14_h @ AES block 4k+5 - round 14 high
+ stp $output_l0, $output_h0, [$output_ptr], #16 @ AES block 4k+4 - store result
+
+ eor $output_l1, $output_l1, $rk14_l @ AES block 4k+5 - round 14 low
+ stp $output_l1, $output_h1, [$output_ptr], #16 @ AES block 4k+5 - store result
+
+ rev64 $res0b, $res0b @ GHASH block 4k+4
+ eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
+ b.lt .L256_dec_main_loop
+
+
+ .L256_dec_prepretail: @ PREPRETAIL
+ ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
+ mov $output_l2, $ctr2.d[0] @ AES block 4k+2 - mov low
+ eor $ctr3b, $res3b, $ctr3b @ AES block 4k+3 - result
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
+ mov $output_h2, $ctr2.d[1] @ AES block 4k+2 - mov high
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
+ fmov $ctr2d, $ctr96_b64x @ CTR block 4k+6
+
+ fmov $ctr2.d[1], $ctr32x @ CTR block 4k+6
+ rev $ctr32w, $rctr32w @ CTR block 4k+7
+ eor $res0b, $res0b, $acc_lb @ PRE 1
+
+ rev64 $res2b, $res2b @ GHASH block 4k+2
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+7
+ mov $output_l3, $ctr3.d[0] @ AES block 4k+3 - mov low
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
+ mov $output_h3, $ctr3.d[1] @ AES block 4k+3 - mov high
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
+ mov $t0d, $res0.d[1] @ GHASH block 4k - mid
+ fmov $ctr3d, $ctr96_b64x @ CTR block 4k+7
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
+ fmov $ctr3.d[1], $ctr32x @ CTR block 4k+7
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
+ mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
+
+ pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
+ rev64 $res3b, $res3b @ GHASH block 4k+3
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
+
+ pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
+ eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
+
+ pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
+ mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
+ eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
+ mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
+ eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
+
+ pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
+
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
+
+ aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
+ eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
+
+ pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
+
+ aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
+ eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
+
+ aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
+
+ pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
+ eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
+
+ pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
+
+ aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
+ ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
+
+ aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
+
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
+ eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
+
+ pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
+
+ aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
+ mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
+
+ aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
+
+ pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
+
+ aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
+ eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
+
+ aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
+ eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
+
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
+ movi $mod_constant.8b, #0xc2
+
+ aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
+ eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
+
+ pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
+
+ aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
+ eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
+
+ aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
+
+ aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
+ eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
+
+ aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
+
+ aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
+ eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
+
+ aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
+
+ aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
+
+ aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 9
+ eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
+
+ pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
+
+ aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 9
+ ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
+
+ aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 9
+
+ aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 9
+ eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
+
+ aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 10
+
+ aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 10
+
+ aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 10
+ eor $output_h2, $output_h2, $rk14_h @ AES block 4k+2 - round 14 high
+
+ aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 10
+ eor $output_l3, $output_l3, $rk14_l @ AES block 4k+3 - round 14 low
+
+ aese $ctr2b, $rk11 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 11
+ eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
+
+ aese $ctr0b, $rk11 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 11
+ add $rctr32w, $rctr32w, #1 @ CTR block 4k+7
+
+ aese $ctr1b, $rk11 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 11
+ eor $output_l2, $output_l2, $rk14_l @ AES block 4k+2 - round 14 low
+
+ aese $ctr2b, $rk12 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 12
+
+ pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
+ eor $output_h3, $output_h3, $rk14_h @ AES block 4k+3 - round 14 high
+
+ aese $ctr3b, $rk11 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 11
+ stp $output_l2, $output_h2, [$output_ptr], #16 @ AES block 4k+2 - store result
+
+ aese $ctr1b, $rk12 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 12
+ ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
+
+ aese $ctr0b, $rk12 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 12
+ stp $output_l3, $output_h3, [$output_ptr], #16 @ AES block 4k+3 - store result
+
+ aese $ctr3b, $rk12 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 12
+ eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
+
+ aese $ctr1b, $rk13 @ AES block 4k+5 - round 13
+
+ aese $ctr0b, $rk13 @ AES block 4k+4 - round 13
+
+ aese $ctr3b, $rk13 @ AES block 4k+7 - round 13
+
+ aese $ctr2b, $rk13 @ AES block 4k+6 - round 13
+ eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
+ .L256_dec_tail: @ TAIL
+
+ sub $main_end_input_ptr, $end_input_ptr, $input_ptr @ main_end_input_ptr is number of bytes left to process
+ ld1 { $res1b}, [$input_ptr], #16 @ AES block 4k+4 - load ciphertext
+
+ eor $ctr0b, $res1b, $ctr0b @ AES block 4k+4 - result
+
+ mov $output_l0, $ctr0.d[0] @ AES block 4k+4 - mov low
+
+ mov $output_h0, $ctr0.d[1] @ AES block 4k+4 - mov high
+ ext $t0.16b, $acc_lb, $acc_lb, #8 @ prepare final partial tag
+
+ cmp $main_end_input_ptr, #48
+
+ eor $output_l0, $output_l0, $rk14_l @ AES block 4k+4 - round 14 low
+
+ eor $output_h0, $output_h0, $rk14_h @ AES block 4k+4 - round 14 high
+ b.gt .L256_dec_blocks_more_than_3
+
+ sub $rctr32w, $rctr32w, #1
+ mov $ctr3b, $ctr2b
+ movi $acc_m.8b, #0
+
+ movi $acc_l.8b, #0
+ cmp $main_end_input_ptr, #32
+
+ movi $acc_h.8b, #0
+ mov $ctr2b, $ctr1b
+ b.gt .L256_dec_blocks_more_than_2
+
+ sub $rctr32w, $rctr32w, #1
+
+ mov $ctr3b, $ctr1b
+ cmp $main_end_input_ptr, #16
+ b.gt .L256_dec_blocks_more_than_1
+
+ sub $rctr32w, $rctr32w, #1
+ b .L256_dec_blocks_less_than_1
+ .L256_dec_blocks_more_than_3: @ blocks left > 3
+ rev64 $res0b, $res1b @ GHASH final-3 block
+ ld1 { $res1b}, [$input_ptr], #16 @ AES final-2 block - load ciphertext
+
+ stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-3 block - store result
+
+ mov $acc_md, $h34k.d[1] @ GHASH final-3 block - mid
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ eor $ctr0b, $res1b, $ctr1b @ AES final-2 block - result
+
+ mov $rk4d, $res0.d[1] @ GHASH final-3 block - mid
+
+ mov $output_l0, $ctr0.d[0] @ AES final-2 block - mov low
+
+ mov $output_h0, $ctr0.d[1] @ AES final-2 block - mov high
+
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-3 block - mid
+
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+
+ pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH final-3 block - high
+
+ pmull $acc_m.1q, $rk4v.1d, $acc_m.1d @ GHASH final-3 block - mid
+ eor $output_l0, $output_l0, $rk14_l @ AES final-2 block - round 14 low
+
+ pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH final-3 block - low
+ eor $output_h0, $output_h0, $rk14_h @ AES final-2 block - round 14 high
+ .L256_dec_blocks_more_than_2: @ blocks left > 2
+
+ rev64 $res0b, $res1b @ GHASH final-2 block
+ ld1 { $res1b}, [$input_ptr], #16 @ AES final-1 block - load ciphertext
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+ stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-2 block - store result
+
+ eor $ctr0b, $res1b, $ctr2b @ AES final-1 block - result
+
+ mov $rk4d, $res0.d[1] @ GHASH final-2 block - mid
+
+ pmull $rk3q1, $res0.1d, $h3.1d @ GHASH final-2 block - low
+
+ pmull2 $rk2q1, $res0.2d, $h3.2d @ GHASH final-2 block - high
+
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-2 block - mid
+ mov $output_l0, $ctr0.d[0] @ AES final-1 block - mov low
+
+ mov $output_h0, $ctr0.d[1] @ AES final-1 block - mov high
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final-2 block - low
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+
+ pmull $rk4v.1q, $rk4v.1d, $h34k.1d @ GHASH final-2 block - mid
+
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final-2 block - high
+ eor $output_l0, $output_l0, $rk14_l @ AES final-1 block - round 14 low
+
+ eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-2 block - mid
+ eor $output_h0, $output_h0, $rk14_h @ AES final-1 block - round 14 high
+ .L256_dec_blocks_more_than_1: @ blocks left > 1
+
+ stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-1 block - store result
+ rev64 $res0b, $res1b @ GHASH final-1 block
+
+ ld1 { $res1b}, [$input_ptr], #16 @ AES final block - load ciphertext
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+ movi $t0.8b, #0 @ suppress further partial tag feed in
+
+ mov $rk4d, $res0.d[1] @ GHASH final-1 block - mid
+
+ eor $ctr0b, $res1b, $ctr3b @ AES final block - result
+
+ pmull2 $rk2q1, $res0.2d, $h2.2d @ GHASH final-1 block - high
+
+ eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-1 block - mid
+
+ pmull $rk3q1, $res0.1d, $h2.1d @ GHASH final-1 block - low
+ mov $output_l0, $ctr0.d[0] @ AES final block - mov low
+
+ ins $rk4v.d[1], $rk4v.d[0] @ GHASH final-1 block - mid
+
+ mov $output_h0, $ctr0.d[1] @ AES final block - mov high
+
+ pmull2 $rk4v.1q, $rk4v.2d, $h12k.2d @ GHASH final-1 block - mid
+ eor $output_l0, $output_l0, $rk14_l @ AES final block - round 14 low
+
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final-1 block - low
+
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final-1 block - high
+
+ eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-1 block - mid
+ eor $output_h0, $output_h0, $rk14_h @ AES final block - round 14 high
+ .L256_dec_blocks_less_than_1: @ blocks left <= 1
+
+ and $bit_length, $bit_length, #127 @ bit_length %= 128
+ mvn $rk14_h, xzr @ rk14_h = 0xffffffffffffffff
+
+ sub $bit_length, $bit_length, #128 @ bit_length -= 128
+ mvn $rk14_l, xzr @ rk14_l = 0xffffffffffffffff
+
+ ldp $end_input_ptr, $main_end_input_ptr, [$output_ptr] @ load existing bytes we need to not overwrite
+ neg $bit_length, $bit_length @ bit_length = 128 - #bits in input (in range [1,128])
+
+ and $bit_length, $bit_length, #127 @ bit_length %= 128
+
+ lsr $rk14_h, $rk14_h, $bit_length @ rk14_h is mask for top 64b of last block
+ cmp $bit_length, #64
+
+ csel $ctr32x, $rk14_l, $rk14_h, lt
+ csel $ctr96_b64x, $rk14_h, xzr, lt
+
+ fmov $ctr0d, $ctr32x @ ctr0b is mask for last block
+ and $output_l0, $output_l0, $ctr32x
+
+ mov $ctr0.d[1], $ctr96_b64x
+ bic $end_input_ptr, $end_input_ptr, $ctr32x @ mask out low existing bytes
+
+ rev $ctr32w, $rctr32w
+
+ bic $main_end_input_ptr, $main_end_input_ptr, $ctr96_b64x @ mask out high existing bytes
+
+ orr $output_l0, $output_l0, $end_input_ptr
+
+ and $output_h0, $output_h0, $ctr96_b64x
+
+ orr $output_h0, $output_h0, $main_end_input_ptr
+
+ and $res1b, $res1b, $ctr0b @ possibly partial last block has zeroes in highest bits
+
+ rev64 $res0b, $res1b @ GHASH final block
+
+ eor $res0b, $res0b, $t0.16b @ feed in partial tag
+
+ pmull $rk3q1, $res0.1d, $h1.1d @ GHASH final block - low
+
+ mov $t0d, $res0.d[1] @ GHASH final block - mid
+
+ eor $t0.8b, $t0.8b, $res0.8b @ GHASH final block - mid
+
+ pmull2 $rk2q1, $res0.2d, $h1.2d @ GHASH final block - high
+
+ pmull $t0.1q, $t0.1d, $h12k.1d @ GHASH final block - mid
+
+ eor $acc_hb, $acc_hb, $rk2 @ GHASH final block - high
+
+ eor $acc_lb, $acc_lb, $rk3 @ GHASH final block - low
+
+ eor $acc_mb, $acc_mb, $t0.16b @ GHASH final block - mid
+ movi $mod_constant.8b, #0xc2
+
+ eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
+
+ shl $mod_constantd, $mod_constantd, #56 @ mod_constant
+
+ eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
+
+ pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
+
+ ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
+
+ eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
+
+ eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
+
+ pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
+
+ ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
+
+ eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
+
+ stp $output_l0, $output_h0, [$output_ptr]
+
+ str $ctr32w, [$counter, #12] @ store the updated counter
+
+ eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
+ ext $acc_lb, $acc_lb, $acc_lb, #8
+ rev64 $acc_lb, $acc_lb
+ mov x0, $len
+ st1 { $acc_l.16b }, [$current_tag]
+
+ ldp x21, x22, [sp, #16]
+ ldp x23, x24, [sp, #32]
+ ldp d8, d9, [sp, #48]
+ ldp d10, d11, [sp, #64]
+ ldp d12, d13, [sp, #80]
+ ldp d14, d15, [sp, #96]
+ ldp x19, x20, [sp], #112
+ ret
+
+.L256_dec_ret:
+ mov w0, #0x0
+ ret
+.size aes_gcm_dec_256_kernel,.-aes_gcm_dec_256_kernel
+___
+}
+}
+
+$code.=<<___;
+.asciz "GHASH for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
+.align 2
+#endif
+___
+
+if ($flavour =~ /64/) { ######## 64-bit code
+ sub unvmov {
+ my $arg=shift;
+
+ $arg =~ m/q([0-9]+)#(lo|hi),\s*q([0-9]+)#(lo|hi)/o &&
+ sprintf "ins v%d.d[%d],v%d.d[%d]",$1<8?$1:$1+8,($2 eq "lo")?0:1,
+ $3<8?$3:$3+8,($4 eq "lo")?0:1;
+ }
+ foreach(split("\n",$code)) {
+ s/@\s/\/\//o; # old->new style commentary
+ print $_,"\n";
+ }
+} else { ######## 32-bit code
+ sub unvdup32 {
+ my $arg=shift;
+
+ $arg =~ m/q([0-9]+),\s*q([0-9]+)\[([0-3])\]/o &&
+ sprintf "vdup.32 q%d,d%d[%d]",$1,2*$2+($3>>1),$3&1;
+ }
+ sub unvpmullp64 {
+ my ($mnemonic,$arg)=@_;
+
+ if ($arg =~ m/q([0-9]+),\s*q([0-9]+),\s*q([0-9]+)/o) {
+ my $word = 0xf2a00e00|(($1&7)<<13)|(($1&8)<<19)
+ |(($2&7)<<17)|(($2&8)<<4)
+ |(($3&7)<<1) |(($3&8)<<2);
+ $word |= 0x00010001 if ($mnemonic =~ "2");
+ # since ARMv7 instructions are always encoded little-endian.
+ # correct solution is to use .inst directive, but older%%%%
+ # assemblers don't implement it:-(
+ sprintf "INST(0x%02x,0x%02x,0x%02x,0x%02x)\t@ %s %s",
+ $word&0xff,($word>>8)&0xff,
+ ($word>>16)&0xff,($word>>24)&0xff,
+ $mnemonic,$arg;
+ }
+ }
+
+ foreach(split("\n",$code)) {
+ s/\b[wx]([0-9]+)\b/r$1/go; # new->old registers
+ s/\bv([0-9])\.[12468]+[bsd]\b/q$1/go; # new->old registers
+ s/\/\/\s?/@ /o; # new->old style commentary
+
+ # fix up remaining new-style suffixes
+ s/\],#[0-9]+/]!/o;
+
+ s/cclr\s+([^,]+),\s*([a-z]+)/mov.$2 $1,#0/o or
+ s/vdup\.32\s+(.*)/unvdup32($1)/geo or
+ s/v?(pmull2?)\.p64\s+(.*)/unvpmullp64($1,$2)/geo or
+ s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo or
+ s/^(\s+)b\./$1b/o or
+ s/^(\s+)ret/$1bx\tlr/o;
+
+ if (s/^(\s+)mov\.([a-z]+)/$1mov$2/) {
+ print " it $2\n";
+ }
+
+ print $_,"\n";
+ }
+}
+
+close STDOUT or die "error closing STDOUT: $!"; # enforce flush
diff --git a/crypto/modes/asm/aesni-gcm-x86_64.pl b/crypto/modes/asm/aesni-gcm-x86_64.pl
index 60f03e4fe25b..eaf4d9c755fb 100644
--- a/crypto/modes/asm/aesni-gcm-x86_64.pl
+++ b/crypto/modes/asm/aesni-gcm-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -40,9 +40,10 @@
# [1] http://rt.openssl.org/Ticket/Display.html?id=2900&user=guest&pass=guest
# [2] http://www.intel.com/content/dam/www/public/us/en/documents/software-support/enabling-high-performance-gcm.pdf
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -70,7 +71,8 @@ if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|.*based on LLVM) ([0
$avx = ($2>=3.0) + ($2>3.0);
}
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
if ($avx>1) {{{
diff --git a/crypto/modes/asm/ghash-armv4.pl b/crypto/modes/asm/ghash-armv4.pl
index d84ac6f2bf43..044f86f143f9 100644
--- a/crypto/modes/asm/ghash-armv4.pl
+++ b/crypto/modes/asm/ghash-armv4.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -78,9 +78,10 @@
# *native* byte order on current platform. See gcm128.c for working
# example...
-$flavour = shift;
-if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour && $flavour ne "void") {
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -88,9 +89,10 @@ if ($flavour && $flavour ne "void") {
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
- open STDOUT,"| \"$^X\" $xlate $flavour $output";
+ open STDOUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
} else {
- open STDOUT,">$output";
+ $output and open STDOUT,">$output";
}
$Xi="r0"; # argument block
@@ -142,7 +144,6 @@ ___
$code=<<___;
#include "arm_arch.h"
-.text
#if defined(__thumb2__) || defined(__clang__)
.syntax unified
#define ldrplb ldrbpl
@@ -154,6 +155,8 @@ $code=<<___;
.code 32
#endif
+.text
+
.type rem_4bit,%object
.align 5
rem_4bit:
diff --git a/crypto/modes/asm/ghash-c64xplus.pl b/crypto/modes/asm/ghash-c64xplus.pl
index 5826dcbdfe64..ded2f779e669 100644
--- a/crypto/modes/asm/ghash-c64xplus.pl
+++ b/crypto/modes/asm/ghash-c64xplus.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -26,8 +26,7 @@
# better, because theoretical [though not necessarily achievable]
# estimate for "4-bit" table-driven implementation is ~12 cycles.
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
($Xip,$Htable,$inp,$len)=("A4","B4","A6","B6"); # arguments
diff --git a/crypto/modes/asm/ghash-ia64.pl b/crypto/modes/asm/ghash-ia64.pl
index 6e29f995fa85..74b88176b842 100755
--- a/crypto/modes/asm/ghash-ia64.pl
+++ b/crypto/modes/asm/ghash-ia64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
diff --git a/crypto/modes/asm/ghash-parisc.pl b/crypto/modes/asm/ghash-parisc.pl
index d798b7abf490..7b5cc2f16e38 100644
--- a/crypto/modes/asm/ghash-parisc.pl
+++ b/crypto/modes/asm/ghash-parisc.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -27,9 +27,12 @@
#
# Special thanks to polarhome.com for providing HP-UX account.
-$flavour = shift;
-$output = shift;
-open STDOUT,">$output";
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+
+$output and open STDOUT,">$output";
if ($flavour =~ /64/) {
$LEVEL ="2.0W";
diff --git a/crypto/modes/asm/ghash-s390x.pl b/crypto/modes/asm/ghash-s390x.pl
index 2f3ca295bdca..ba9c5b4a4f4f 100644
--- a/crypto/modes/asm/ghash-s390x.pl
+++ b/crypto/modes/asm/ghash-s390x.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -44,7 +44,10 @@
# it's actually almost 2 times slower. Which is the reason why
# KIMD-GHASH is not used in gcm_gmult_4bit.
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /3[12]/) {
$SIZE_T=4;
@@ -54,8 +57,7 @@ if ($flavour =~ /3[12]/) {
$g="g";
}
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$output and open STDOUT,">$output";
$softonly=0;
diff --git a/crypto/modes/asm/ghash-sparcv9.pl b/crypto/modes/asm/ghash-sparcv9.pl
index ccebc74b4e97..e35064237f46 100644
--- a/crypto/modes/asm/ghash-sparcv9.pl
+++ b/crypto/modes/asm/ghash-sparcv9.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2010-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -53,8 +53,7 @@
# saturates at ~15.5x single-process result on 8-core processor,
# or ~20.5GBps per 2.85GHz socket.
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
$frame="STACK_FRAME";
$bias="STACK_BIAS";
@@ -81,7 +80,10 @@ $inp="%i2";
$len="%i3";
$code.=<<___;
-#include "sparc_arch.h"
+#ifndef __ASSEMBLER__
+# define __ASSEMBLER__ 1
+#endif
+#include "crypto/sparc_arch.h"
#ifdef __arch64__
.register %g2,#scratch
diff --git a/crypto/modes/asm/ghash-x86.pl b/crypto/modes/asm/ghash-x86.pl
index 4183d99b68b1..c796107c7f97 100644
--- a/crypto/modes/asm/ghash-x86.pl
+++ b/crypto/modes/asm/ghash-x86.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -135,8 +135,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
&asm_init($ARGV[0],$x86only = $ARGV[$#ARGV] eq "386");
diff --git a/crypto/modes/asm/ghash-x86_64.pl b/crypto/modes/asm/ghash-x86_64.pl
index 9bdba41d1de5..6709f96492ed 100644
--- a/crypto/modes/asm/ghash-x86_64.pl
+++ b/crypto/modes/asm/ghash-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -90,9 +90,10 @@
#
# [1] http://rt.openssl.org/Ticket/Display.html?id=2900&user=guest&pass=guest
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -120,7 +121,8 @@ if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|.*based on LLVM) ([0
$avx = ($2>=3.0) + ($2>3.0);
}
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
$do4xaggr=1;
@@ -239,6 +241,7 @@ $code=<<___;
.align 16
gcm_gmult_4bit:
.cfi_startproc
+ endbranch
push %rbx
.cfi_push %rbx
push %rbp # %rbp and others are pushed exclusively in
@@ -286,6 +289,7 @@ $code.=<<___;
.align 16
gcm_ghash_4bit:
.cfi_startproc
+ endbranch
push %rbx
.cfi_push %rbx
push %rbp
@@ -612,6 +616,7 @@ $code.=<<___;
.align 16
gcm_gmult_clmul:
.cfi_startproc
+ endbranch
.L_gmult_clmul:
movdqu ($Xip),$Xi
movdqa .Lbswap_mask(%rip),$T3
@@ -663,6 +668,7 @@ $code.=<<___;
.align 32
gcm_ghash_clmul:
.cfi_startproc
+ endbranch
.L_ghash_clmul:
___
$code.=<<___ if ($win64);
@@ -1166,6 +1172,7 @@ $code.=<<___;
.align 32
gcm_gmult_avx:
.cfi_startproc
+ endbranch
jmp .L_gmult_clmul
.cfi_endproc
.size gcm_gmult_avx,.-gcm_gmult_avx
@@ -1177,6 +1184,7 @@ $code.=<<___;
.align 32
gcm_ghash_avx:
.cfi_startproc
+ endbranch
___
if ($avx) {
my ($Xip,$Htbl,$inp,$len)=@_4args;
diff --git a/crypto/modes/asm/ghashp8-ppc.pl b/crypto/modes/asm/ghashp8-ppc.pl
index 447472cb4592..20f611dabd43 100755
--- a/crypto/modes/asm/ghashp8-ppc.pl
+++ b/crypto/modes/asm/ghashp8-ppc.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -32,8 +32,10 @@
# aggregated reduction - by 170% or 2.7x (resulting in 0.55 cpb).
# POWER9 delivers 0.51 cpb.
-$flavour=shift;
-$output =shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /64/) {
$SIZE_T=8;
@@ -61,7 +63,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour $output" || die "can't call $xlate: $!";
+open STDOUT,"| $^X $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
my ($Xip,$Htbl,$inp,$len)=map("r$_",(3..6)); # argument block
diff --git a/crypto/modes/asm/ghashv8-armx.pl b/crypto/modes/asm/ghashv8-armx.pl
index d0e398b50ae0..b1d35d25b5b1 100644
--- a/crypto/modes/asm/ghashv8-armx.pl
+++ b/crypto/modes/asm/ghashv8-armx.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -42,18 +42,22 @@
# Denver 0.51 0.65 6.02
# Mongoose 0.65 1.10 8.06
# Kryo 0.76 1.16 8.00
+# ThunderX2 1.05
#
# (*) presented for reference/comparison purposes;
-$flavour = shift;
-$output = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
$Xi="x0"; # argument block
@@ -66,18 +70,26 @@ $inc="x12";
{
my ($Xl,$Xm,$Xh,$IN)=map("q$_",(0..3));
my ($t0,$t1,$t2,$xC2,$H,$Hhl,$H2)=map("q$_",(8..14));
+my $_byte = ($flavour =~ /win/ ? "DCB" : ".byte");
$code=<<___;
#include "arm_arch.h"
#if __ARM_MAX_ARCH__>=7
-.text
___
-$code.=".arch armv8-a+crypto\n" if ($flavour =~ /64/);
-$code.=<<___ if ($flavour !~ /64/);
+$code.=".arch armv8-a+crypto\n.text\n" if ($flavour =~ /64/);
+$code.=<<___ if ($flavour !~ /64/);
.fpu neon
-.code 32
-#undef __thumb2__
+#ifdef __thumb2__
+.syntax unified
+.thumb
+# define INST(a,b,c,d) $_byte c,0xef,a,b
+#else
+.code 32
+# define INST(a,b,c,d) $_byte a,b,c,0xf2
+#endif
+
+.text
___
################################################################################
@@ -752,7 +764,7 @@ if ($flavour =~ /64/) { ######## 64-bit code
# since ARMv7 instructions are always encoded little-endian.
# correct solution is to use .inst directive, but older
# assemblers don't implement it:-(
- sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s",
+ sprintf "INST(0x%02x,0x%02x,0x%02x,0x%02x)\t@ %s %s",
$word&0xff,($word>>8)&0xff,
($word>>16)&0xff,($word>>24)&0xff,
$mnemonic,$arg;
@@ -767,13 +779,17 @@ if ($flavour =~ /64/) { ######## 64-bit code
# fix up remaining new-style suffixes
s/\],#[0-9]+/]!/o;
- s/cclr\s+([^,]+),\s*([a-z]+)/mov$2 $1,#0/o or
+ s/cclr\s+([^,]+),\s*([a-z]+)/mov.$2 $1,#0/o or
s/vdup\.32\s+(.*)/unvdup32($1)/geo or
s/v?(pmull2?)\.p64\s+(.*)/unvpmullp64($1,$2)/geo or
s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo or
s/^(\s+)b\./$1b/o or
s/^(\s+)ret/$1bx\tlr/o;
+ if (s/^(\s+)mov\.([a-z]+)/$1mov$2/) {
+ print " it $2\n";
+ }
+
print $_,"\n";
}
}
diff --git a/crypto/modes/build.info b/crypto/modes/build.info
index 821340eb909a..f3558fa1a465 100644
--- a/crypto/modes/build.info
+++ b/crypto/modes/build.info
@@ -1,30 +1,82 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- cbc128.c ctr128.c cts128.c cfb128.c ofb128.c gcm128.c \
- ccm128.c xts128.c wrap128.c ocb128.c \
- {- $target{modes_asm_src} -}
+
+$MODESASM=
+IF[{- !$disabled{asm} -}]
+ $MODESASM_x86=ghash-x86.S
+ $MODESDEF_x86=GHASH_ASM
+ $MODESASM_x86_64=ghash-x86_64.s aesni-gcm-x86_64.s
+ $MODESDEF_x86_64=GHASH_ASM
+
+ # ghash-ia64.s doesn't work on VMS
+ IF[{- $config{target} !~ /^vms-/ -}]
+ $MODESASM_ia64=ghash-ia64.s
+ $MODESDEF_ia64=GHASH_ASM
+ ENDIF
+
+ $MODESASM_sparcv9=ghash-sparcv9.S
+ $MODESDEF_sparcv9=GHASH_ASM
+
+ $MODESASM_alpha=ghash-alpha.S
+ $MODESDEF_alpha=GHASH_ASM
+
+ $MODESASM_s390x=ghash-s390x.S
+ $MODESDEF_s390x=GHASH_ASM
+
+ $MODESASM_armv4=ghash-armv4.S ghashv8-armx.S
+ $MODESDEF_armv4=GHASH_ASM
+ $MODESASM_aarch64=ghashv8-armx.S aes-gcm-armv8_64.S
+ $MODESDEF_aarch64=
+
+ $MODESASM_parisc11=ghash-parisc.s
+ $MODESDEF_parisc11=GHASH_ASM
+ $MODESASM_parisc20_64=$MODESASM_parisc11
+ $MODESDEF_parisc20_64=$MODESDEF_parisc11
+
+ $MODESASM_ppc32=ghashp8-ppc.s
+ $MODESDEF_ppc32=
+ $MODESASM_ppc64=$MODESASM_ppc32
+ $MODESDEF_ppc64=$MODESDEF_ppc32
+
+ $MODESASM_c64xplus=ghash-c64xplus.s
+ $MODESDEF_c64xplus=GHASH_ASM
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+ IF[$MODESASM_{- $target{asm_arch} -}]
+ $MODESASM=$MODESASM_{- $target{asm_arch} -}
+ $MODESDEF=$MODESDEF_{- $target{asm_arch} -}
+ ENDIF
+ENDIF
+
+$COMMON=cbc128.c ctr128.c cfb128.c ofb128.c gcm128.c ccm128.c xts128.c \
+ wrap128.c $MODESASM
+SOURCE[../../libcrypto]=$COMMON \
+ cts128.c ocb128.c siv128.c
+SOURCE[../../providers/libfips.a]=$COMMON
+
+# Implementations are now spread across several libraries, so the defines
+# need to be applied to all affected libraries and modules.
+DEFINE[../../libcrypto]=$MODESDEF
+DEFINE[../../providers/libfips.a]=$MODESDEF
+
INCLUDE[gcm128.o]=..
-GENERATE[ghash-ia64.s]=asm/ghash-ia64.pl $(LIB_CFLAGS) $(LIB_CPPFLAGS)
-GENERATE[ghash-x86.s]=asm/ghash-x86.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-GENERATE[ghash-x86_64.s]=asm/ghash-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[aesni-gcm-x86_64.s]=asm/aesni-gcm-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[ghash-sparcv9.S]=asm/ghash-sparcv9.pl $(PERLASM_SCHEME)
+GENERATE[ghash-ia64.s]=asm/ghash-ia64.pl
+GENERATE[ghash-x86.S]=asm/ghash-x86.pl
+GENERATE[ghash-x86_64.s]=asm/ghash-x86_64.pl
+GENERATE[aesni-gcm-x86_64.s]=asm/aesni-gcm-x86_64.pl
+GENERATE[ghash-sparcv9.S]=asm/ghash-sparcv9.pl
INCLUDE[ghash-sparcv9.o]=..
-GENERATE[ghash-alpha.S]=asm/ghash-alpha.pl $(PERLASM_SCHEME)
-GENERATE[ghash-parisc.s]=asm/ghash-parisc.pl $(PERLASM_SCHEME)
-GENERATE[ghashp8-ppc.s]=asm/ghashp8-ppc.pl $(PERLASM_SCHEME)
-GENERATE[ghash-armv4.S]=asm/ghash-armv4.pl $(PERLASM_SCHEME)
+GENERATE[ghash-alpha.S]=asm/ghash-alpha.pl
+GENERATE[ghash-parisc.s]=asm/ghash-parisc.pl
+GENERATE[ghashp8-ppc.s]=asm/ghashp8-ppc.pl
+GENERATE[ghash-armv4.S]=asm/ghash-armv4.pl
INCLUDE[ghash-armv4.o]=..
-GENERATE[ghashv8-armx.S]=asm/ghashv8-armx.pl $(PERLASM_SCHEME)
+GENERATE[ghashv8-armx.S]=asm/ghashv8-armx.pl
INCLUDE[ghashv8-armx.o]=..
-GENERATE[ghash-s390x.S]=asm/ghash-s390x.pl $(PERLASM_SCHEME)
+GENERATE[aes-gcm-armv8_64.S]=asm/aes-gcm-armv8_64.pl
+INCLUDE[aes-gcm-armv8_64.o]=..
+GENERATE[ghash-s390x.S]=asm/ghash-s390x.pl
INCLUDE[ghash-s390x.o]=..
-
-BEGINRAW[Makefile]
-# GNU make "catch all"
-{- $builddir -}/ghash-%.S: {- $sourcedir -}/asm/ghash-%.pl
- CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@
-ENDRAW[Makefile]
+GENERATE[ghash-c64xplus.S]=asm/ghash-c64xplus.pl
diff --git a/crypto/modes/cbc128.c b/crypto/modes/cbc128.c
index 15a14be70872..f3818032a490 100644
--- a/crypto/modes/cbc128.c
+++ b/crypto/modes/cbc128.c
@@ -1,15 +1,15 @@
/*
* Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/crypto.h>
-#include "modes_local.h"
#include <string.h>
+#include <openssl/crypto.h>
+#include "crypto/modes.h"
#if !defined(STRICT_ALIGNMENT) && !defined(PEDANTIC)
# define STRICT_ALIGNMENT 0
diff --git a/crypto/modes/ccm128.c b/crypto/modes/ccm128.c
index 655b10350201..eee7a69c3ab7 100644
--- a/crypto/modes/ccm128.c
+++ b/crypto/modes/ccm128.c
@@ -1,15 +1,15 @@
/*
* Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/crypto.h>
-#include "modes_local.h"
#include <string.h>
+#include <openssl/crypto.h>
+#include "crypto/modes.h"
#ifndef STRICT_ALIGNMENT
# ifdef __GNUC__
diff --git a/crypto/modes/cfb128.c b/crypto/modes/cfb128.c
index b2530007b6e4..2d37bcb586fd 100644
--- a/crypto/modes/cfb128.c
+++ b/crypto/modes/cfb128.c
@@ -1,15 +1,15 @@
/*
- * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/crypto.h>
-#include "modes_local.h"
#include <string.h>
+#include <openssl/crypto.h>
+#include "crypto/modes.h"
#if defined(__GNUC__) && !defined(STRICT_ALIGNMENT)
typedef size_t size_t_aX __attribute((__aligned__(1)));
@@ -30,6 +30,11 @@ void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out,
unsigned int n;
size_t l = 0;
+ if (*num < 0) {
+ /* There is no good way to signal an error return from here */
+ *num = -1;
+ return;
+ }
n = *num;
if (enc) {
diff --git a/crypto/modes/ctr128.c b/crypto/modes/ctr128.c
index 1ed7decedfd3..58014e76e275 100644
--- a/crypto/modes/ctr128.c
+++ b/crypto/modes/ctr128.c
@@ -1,15 +1,16 @@
/*
- * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/crypto.h>
-#include "modes_local.h"
#include <string.h>
+#include <openssl/crypto.h>
+#include "internal/endian.h"
+#include "crypto/modes.h"
#if defined(__GNUC__) && !defined(STRICT_ALIGNMENT)
typedef size_t size_t_aX __attribute((__aligned__(1)));
@@ -39,14 +40,9 @@ static void ctr128_inc(unsigned char *counter)
static void ctr128_inc_aligned(unsigned char *counter)
{
size_t *data, c, d, n;
- const union {
- long one;
- char little;
- } is_endian = {
- 1
- };
-
- if (is_endian.little || ((size_t)counter % sizeof(size_t)) != 0) {
+ DECLARE_IS_ENDIAN;
+
+ if (IS_LITTLE_ENDIAN || ((size_t)counter % sizeof(size_t)) != 0) {
ctr128_inc(counter);
return;
}
@@ -159,7 +155,7 @@ void CRYPTO_ctr128_encrypt_ctr32(const unsigned char *in, unsigned char *out,
{
unsigned int n, ctr32;
- n = *num;
+ n = *num;
while (n && len) {
*(out++) = *(in++) ^ ecount_buf[n];
diff --git a/crypto/modes/cts128.c b/crypto/modes/cts128.c
index 9052e857764f..5600d9c54b1b 100644
--- a/crypto/modes/cts128.c
+++ b/crypto/modes/cts128.c
@@ -1,15 +1,15 @@
/*
* Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/crypto.h>
-#include "modes_local.h"
#include <string.h>
+#include <openssl/crypto.h>
+#include "crypto/modes.h"
/*
* Trouble with Ciphertext Stealing, CTS, mode is that there is no
diff --git a/crypto/modes/gcm128.c b/crypto/modes/gcm128.c
index 8304efff48be..e7e719fc0e26 100644
--- a/crypto/modes/gcm128.c
+++ b/crypto/modes/gcm128.c
@@ -1,15 +1,17 @@
/*
* Copyright 2010-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/crypto.h>
-#include "modes_local.h"
#include <string.h>
+#include <openssl/crypto.h>
+#include "internal/cryptlib.h"
+#include "internal/endian.h"
+#include "crypto/modes.h"
#if defined(__GNUC__) && !defined(STRICT_ALIGNMENT)
typedef size_t size_t_aX __attribute((__aligned__(1)));
@@ -104,10 +106,7 @@ static void gcm_gmult_8bit(u64 Xi[2], const u128 Htable[256])
u128 Z = { 0, 0 };
const u8 *xi = (const u8 *)Xi + 15;
size_t rem, n = *xi;
- const union {
- long one;
- char little;
- } is_endian = { 1 };
+ DECLARE_IS_ENDIAN;
static const size_t rem_8bit[256] = {
PACK(0x0000), PACK(0x01C2), PACK(0x0384), PACK(0x0246),
PACK(0x0708), PACK(0x06CA), PACK(0x048C), PACK(0x054E),
@@ -193,7 +192,7 @@ static void gcm_gmult_8bit(u64 Xi[2], const u128 Htable[256])
Z.hi ^= (u64)rem_8bit[rem] << 32;
}
- if (is_endian.little) {
+ if (IS_LITTLE_ENDIAN) {
# ifdef BSWAP8
Xi[0] = BSWAP8(Z.hi);
Xi[1] = BSWAP8(Z.lo);
@@ -273,12 +272,9 @@ static void gcm_init_4bit(u128 Htable[16], u64 H[2])
*/
{
int j;
- const union {
- long one;
- char little;
- } is_endian = { 1 };
+ DECLARE_IS_ENDIAN;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
for (j = 0; j < 16; ++j) {
V = Htable[j];
Htable[j].hi = V.lo;
@@ -306,10 +302,7 @@ static void gcm_gmult_4bit(u64 Xi[2], const u128 Htable[16])
u128 Z;
int cnt = 15;
size_t rem, nlo, nhi;
- const union {
- long one;
- char little;
- } is_endian = { 1 };
+ DECLARE_IS_ENDIAN;
nlo = ((const u8 *)Xi)[15];
nhi = nlo >> 4;
@@ -349,7 +342,7 @@ static void gcm_gmult_4bit(u64 Xi[2], const u128 Htable[16])
Z.lo ^= Htable[nlo].lo;
}
- if (is_endian.little) {
+ if (IS_LITTLE_ENDIAN) {
# ifdef BSWAP8
Xi[0] = BSWAP8(Z.hi);
Xi[1] = BSWAP8(Z.lo);
@@ -385,10 +378,7 @@ static void gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16],
u128 Z;
int cnt;
size_t rem, nlo, nhi;
- const union {
- long one;
- char little;
- } is_endian = { 1 };
+ DECLARE_IS_ENDIAN;
# if 1
do {
@@ -527,7 +517,7 @@ static void gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16],
Z.hi ^= ((u64)rem_8bit[rem << 4]) << 48;
# endif
- if (is_endian.little) {
+ if (IS_LITTLE_ENDIAN) {
# ifdef BSWAP8
Xi[0] = BSWAP8(Z.hi);
Xi[1] = BSWAP8(Z.lo);
@@ -575,16 +565,13 @@ static void gcm_gmult_1bit(u64 Xi[2], const u64 H[2])
long X;
int i, j;
const long *xi = (const long *)Xi;
- const union {
- long one;
- char little;
- } is_endian = { 1 };
+ DECLARE_IS_ENDIAN;
V.hi = H[0]; /* H is in host byte order, no byte swapping */
V.lo = H[1];
for (j = 0; j < 16 / sizeof(long); ++j) {
- if (is_endian.little) {
+ if (IS_LITTLE_ENDIAN) {
if (sizeof(long) == 8) {
# ifdef BSWAP8
X = (long)(BSWAP8(xi[j]));
@@ -608,7 +595,7 @@ static void gcm_gmult_1bit(u64 Xi[2], const u64 H[2])
}
}
- if (is_endian.little) {
+ if (IS_LITTLE_ENDIAN) {
# ifdef BSWAP8
Xi[0] = BSWAP8(Z.hi);
Xi[1] = BSWAP8(Z.lo);
@@ -641,7 +628,6 @@ static void gcm_gmult_1bit(u64 Xi[2], const u64 H[2])
defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
# define GHASH_ASM_X86_OR_64
# define GCM_FUNCREF_4BIT
-extern unsigned int OPENSSL_ia32cap_P[];
void gcm_init_clmul(u128 Htable[16], const u64 Xi[2]);
void gcm_gmult_clmul(u64 Xi[2], const u128 Htable[16]);
@@ -688,16 +674,15 @@ void gcm_ghash_v8(u64 Xi[2], const u128 Htable[16], const u8 *inp,
size_t len);
# endif
# elif defined(__sparc__) || defined(__sparc)
-# include "sparc_arch.h"
+# include "crypto/sparc_arch.h"
# define GHASH_ASM_SPARC
# define GCM_FUNCREF_4BIT
-extern unsigned int OPENSSL_sparcv9cap_P[];
void gcm_init_vis3(u128 Htable[16], const u64 Xi[2]);
void gcm_gmult_vis3(u64 Xi[2], const u128 Htable[16]);
void gcm_ghash_vis3(u64 Xi[2], const u128 Htable[16], const u8 *inp,
size_t len);
# elif defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC))
-# include "ppc_arch.h"
+# include "crypto/ppc_arch.h"
# define GHASH_ASM_PPC
# define GCM_FUNCREF_4BIT
void gcm_init_p8(u128 Htable[16], const u64 Xi[2]);
@@ -718,10 +703,7 @@ void gcm_ghash_p8(u64 Xi[2], const u128 Htable[16], const u8 *inp,
void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, void *key, block128_f block)
{
- const union {
- long one;
- char little;
- } is_endian = { 1 };
+ DECLARE_IS_ENDIAN;
memset(ctx, 0, sizeof(*ctx));
ctx->block = block;
@@ -729,7 +711,7 @@ void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, void *key, block128_f block)
(*block) (ctx->H.c, ctx->H.c, key);
- if (is_endian.little) {
+ if (IS_LITTLE_ENDIAN) {
/* H is stored in host byte order */
#ifdef BSWAP8
ctx->H.u[0] = BSWAP8(ctx->H.u[0]);
@@ -833,10 +815,7 @@ void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, void *key, block128_f block)
void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const unsigned char *iv,
size_t len)
{
- const union {
- long one;
- char little;
- } is_endian = { 1 };
+ DECLARE_IS_ENDIAN;
unsigned int ctr;
#ifdef GCM_FUNCREF_4BIT
void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult;
@@ -875,7 +854,7 @@ void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const unsigned char *iv,
GCM_MUL(ctx);
}
len0 <<= 3;
- if (is_endian.little) {
+ if (IS_LITTLE_ENDIAN) {
#ifdef BSWAP8
ctx->Xi.u[1] ^= BSWAP8(len0);
#else
@@ -894,7 +873,7 @@ void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const unsigned char *iv,
GCM_MUL(ctx);
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
#ifdef BSWAP4
ctr = BSWAP4(ctx->Xi.d[3]);
#else
@@ -913,7 +892,7 @@ void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const unsigned char *iv,
(*ctx->block) (ctx->Yi.c, ctx->EK0.c, ctx->key);
++ctr;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
#ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
#else
@@ -988,10 +967,7 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
const unsigned char *in, unsigned char *out,
size_t len)
{
- const union {
- long one;
- char little;
- } is_endian = { 1 };
+ DECLARE_IS_ENDIAN;
unsigned int n, ctr, mres;
size_t i;
u64 mlen = ctx->len.u[1];
@@ -1030,7 +1006,7 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
ctx->ares = 0;
}
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
#ifdef BSWAP4
ctr = BSWAP4(ctx->Yi.d[3]);
#else
@@ -1091,7 +1067,7 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
(*block) (ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
# ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
# else
@@ -1118,7 +1094,7 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
(*block) (ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
# ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
# else
@@ -1141,7 +1117,7 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
(*block) (ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
# ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
# else
@@ -1160,7 +1136,7 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
if (len) {
(*block) (ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
# ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
# else
@@ -1191,7 +1167,7 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
if (n == 0) {
(*block) (ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
#ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
#else
@@ -1223,10 +1199,7 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
const unsigned char *in, unsigned char *out,
size_t len)
{
- const union {
- long one;
- char little;
- } is_endian = { 1 };
+ DECLARE_IS_ENDIAN;
unsigned int n, ctr, mres;
size_t i;
u64 mlen = ctx->len.u[1];
@@ -1265,7 +1238,7 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
ctx->ares = 0;
}
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
#ifdef BSWAP4
ctr = BSWAP4(ctx->Yi.d[3]);
#else
@@ -1329,7 +1302,7 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
(*block) (ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
# ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
# else
@@ -1354,7 +1327,7 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
(*block) (ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
# ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
# else
@@ -1376,7 +1349,7 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
(*block) (ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
# ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
# else
@@ -1398,7 +1371,7 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
if (len) {
(*block) (ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
# ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
# else
@@ -1432,7 +1405,7 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
if (n == 0) {
(*block) (ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
#ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
#else
@@ -1469,10 +1442,7 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
#if defined(OPENSSL_SMALL_FOOTPRINT)
return CRYPTO_gcm128_encrypt(ctx, in, out, len);
#else
- const union {
- long one;
- char little;
- } is_endian = { 1 };
+ DECLARE_IS_ENDIAN;
unsigned int n, ctr, mres;
size_t i;
u64 mlen = ctx->len.u[1];
@@ -1510,7 +1480,7 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
ctx->ares = 0;
}
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
# ifdef BSWAP4
ctr = BSWAP4(ctx->Yi.d[3]);
# else
@@ -1558,7 +1528,7 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
while (len >= GHASH_CHUNK) {
(*stream) (in, out, GHASH_CHUNK / 16, key, ctx->Yi.c);
ctr += GHASH_CHUNK / 16;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
# ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
# else
@@ -1578,7 +1548,7 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
(*stream) (in, out, j, key, ctx->Yi.c);
ctr += (unsigned int)j;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
# ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
# else
@@ -1603,7 +1573,7 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
if (len) {
(*ctx->block) (ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
# ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
# else
@@ -1633,10 +1603,7 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
#if defined(OPENSSL_SMALL_FOOTPRINT)
return CRYPTO_gcm128_decrypt(ctx, in, out, len);
#else
- const union {
- long one;
- char little;
- } is_endian = { 1 };
+ DECLARE_IS_ENDIAN;
unsigned int n, ctr, mres;
size_t i;
u64 mlen = ctx->len.u[1];
@@ -1674,7 +1641,7 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
ctx->ares = 0;
}
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
# ifdef BSWAP4
ctr = BSWAP4(ctx->Yi.d[3]);
# else
@@ -1725,7 +1692,7 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
GHASH(ctx, in, GHASH_CHUNK);
(*stream) (in, out, GHASH_CHUNK / 16, key, ctx->Yi.c);
ctr += GHASH_CHUNK / 16;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
# ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
# else
@@ -1757,7 +1724,7 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
# endif
(*stream) (in, out, j, key, ctx->Yi.c);
ctr += (unsigned int)j;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
# ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
# else
@@ -1772,7 +1739,7 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
if (len) {
(*ctx->block) (ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little)
+ if (IS_LITTLE_ENDIAN)
# ifdef BSWAP4
ctx->Yi.d[3] = BSWAP4(ctr);
# else
@@ -1800,10 +1767,7 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const unsigned char *tag,
size_t len)
{
- const union {
- long one;
- char little;
- } is_endian = { 1 };
+ DECLARE_IS_ENDIAN;
u64 alen = ctx->len.u[0] << 3;
u64 clen = ctx->len.u[1] << 3;
#ifdef GCM_FUNCREF_4BIT
@@ -1835,7 +1799,7 @@ int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const unsigned char *tag,
GCM_MUL(ctx);
#endif
- if (is_endian.little) {
+ if (IS_LITTLE_ENDIAN) {
#ifdef BSWAP8
alen = BSWAP8(alen);
clen = BSWAP8(clen);
diff --git a/crypto/modes/modes_local.h b/crypto/modes/modes_local.h
deleted file mode 100644
index 888141681e69..000000000000
--- a/crypto/modes/modes_local.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <openssl/modes.h>
-
-#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
-typedef __int64 i64;
-typedef unsigned __int64 u64;
-# define U64(C) C##UI64
-#elif defined(__arch64__)
-typedef long i64;
-typedef unsigned long u64;
-# define U64(C) C##UL
-#else
-typedef long long i64;
-typedef unsigned long long u64;
-# define U64(C) C##ULL
-#endif
-
-typedef unsigned int u32;
-typedef unsigned char u8;
-
-#define STRICT_ALIGNMENT 1
-#ifndef PEDANTIC
-# if defined(__i386) || defined(__i386__) || \
- defined(__x86_64) || defined(__x86_64__) || \
- defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || \
- defined(__aarch64__) || \
- defined(__s390__) || defined(__s390x__)
-# undef STRICT_ALIGNMENT
-# endif
-#endif
-
-#ifndef STRICT_ALIGNMENT
-# ifdef __GNUC__
-typedef u32 u32_a1 __attribute((__aligned__(1)));
-# else
-typedef u32 u32_a1;
-# endif
-#endif
-
-#if !defined(PEDANTIC) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
-# if defined(__GNUC__) && __GNUC__>=2
-# if defined(__x86_64) || defined(__x86_64__)
-# define BSWAP8(x) ({ u64 ret_=(x); \
- asm ("bswapq %0" \
- : "+r"(ret_)); ret_; })
-# define BSWAP4(x) ({ u32 ret_=(x); \
- asm ("bswapl %0" \
- : "+r"(ret_)); ret_; })
-# elif (defined(__i386) || defined(__i386__)) && !defined(I386_ONLY)
-# define BSWAP8(x) ({ u32 lo_=(u64)(x)>>32,hi_=(x); \
- asm ("bswapl %0; bswapl %1" \
- : "+r"(hi_),"+r"(lo_)); \
- (u64)hi_<<32|lo_; })
-# define BSWAP4(x) ({ u32 ret_=(x); \
- asm ("bswapl %0" \
- : "+r"(ret_)); ret_; })
-# elif defined(__aarch64__)
-# if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
- __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
-# define BSWAP8(x) ({ u64 ret_; \
- asm ("rev %0,%1" \
- : "=r"(ret_) : "r"(x)); ret_; })
-# define BSWAP4(x) ({ u32 ret_; \
- asm ("rev %w0,%w1" \
- : "=r"(ret_) : "r"(x)); ret_; })
-# endif
-# elif (defined(__arm__) || defined(__arm)) && !defined(STRICT_ALIGNMENT)
-# define BSWAP8(x) ({ u32 lo_=(u64)(x)>>32,hi_=(x); \
- asm ("rev %0,%0; rev %1,%1" \
- : "+r"(hi_),"+r"(lo_)); \
- (u64)hi_<<32|lo_; })
-# define BSWAP4(x) ({ u32 ret_; \
- asm ("rev %0,%1" \
- : "=r"(ret_) : "r"((u32)(x))); \
- ret_; })
-# endif
-# elif defined(_MSC_VER)
-# if _MSC_VER>=1300
-# include <stdlib.h>
-# pragma intrinsic(_byteswap_uint64,_byteswap_ulong)
-# define BSWAP8(x) _byteswap_uint64((u64)(x))
-# define BSWAP4(x) _byteswap_ulong((u32)(x))
-# elif defined(_M_IX86)
-__inline u32 _bswap4(u32 val)
-{
-_asm mov eax, val _asm bswap eax}
-# define BSWAP4(x) _bswap4(x)
-# endif
-# endif
-#endif
-#if defined(BSWAP4) && !defined(STRICT_ALIGNMENT)
-# define GETU32(p) BSWAP4(*(const u32_a1 *)(p))
-# define PUTU32(p,v) *(u32_a1 *)(p) = BSWAP4(v)
-#else
-# define GETU32(p) ((u32)(p)[0]<<24|(u32)(p)[1]<<16|(u32)(p)[2]<<8|(u32)(p)[3])
-# define PUTU32(p,v) ((p)[0]=(u8)((v)>>24),(p)[1]=(u8)((v)>>16),(p)[2]=(u8)((v)>>8),(p)[3]=(u8)(v))
-#endif
-/*- GCM definitions */ typedef struct {
- u64 hi, lo;
-} u128;
-
-#ifdef TABLE_BITS
-# undef TABLE_BITS
-#endif
-/*
- * Even though permitted values for TABLE_BITS are 8, 4 and 1, it should
- * never be set to 8 [or 1]. For further information see gcm128.c.
- */
-#define TABLE_BITS 4
-
-struct gcm128_context {
- /* Following 6 names follow names in GCM specification */
- union {
- u64 u[2];
- u32 d[4];
- u8 c[16];
- size_t t[16 / sizeof(size_t)];
- } Yi, EKi, EK0, len, Xi, H;
- /*
- * Relative position of Xi, H and pre-computed Htable is used in some
- * assembler modules, i.e. don't change the order!
- */
-#if TABLE_BITS==8
- u128 Htable[256];
-#else
- u128 Htable[16];
- void (*gmult) (u64 Xi[2], const u128 Htable[16]);
- void (*ghash) (u64 Xi[2], const u128 Htable[16], const u8 *inp,
- size_t len);
-#endif
- unsigned int mres, ares;
- block128_f block;
- void *key;
-#if !defined(OPENSSL_SMALL_FOOTPRINT)
- unsigned char Xn[48];
-#endif
-};
-
-struct xts128_context {
- void *key1, *key2;
- block128_f block1, block2;
-};
-
-struct ccm128_context {
- union {
- u64 u[2];
- u8 c[16];
- } nonce, cmac;
- u64 blocks;
- block128_f block;
- void *key;
-};
-
-#ifndef OPENSSL_NO_OCB
-
-typedef union {
- u64 a[2];
- unsigned char c[16];
-} OCB_BLOCK;
-# define ocb_block16_xor(in1,in2,out) \
- ( (out)->a[0]=(in1)->a[0]^(in2)->a[0], \
- (out)->a[1]=(in1)->a[1]^(in2)->a[1] )
-# if STRICT_ALIGNMENT
-# define ocb_block16_xor_misaligned(in1,in2,out) \
- ocb_block_xor((in1)->c,(in2)->c,16,(out)->c)
-# else
-# define ocb_block16_xor_misaligned ocb_block16_xor
-# endif
-
-struct ocb128_context {
- /* Need both encrypt and decrypt key schedules for decryption */
- block128_f encrypt;
- block128_f decrypt;
- void *keyenc;
- void *keydec;
- ocb128_f stream; /* direction dependent */
- /* Key dependent variables. Can be reused if key remains the same */
- size_t l_index;
- size_t max_l_index;
- OCB_BLOCK l_star;
- OCB_BLOCK l_dollar;
- OCB_BLOCK *l;
- /* Must be reset for each session */
- struct {
- u64 blocks_hashed;
- u64 blocks_processed;
- OCB_BLOCK offset_aad;
- OCB_BLOCK sum;
- OCB_BLOCK offset;
- OCB_BLOCK checksum;
- } sess;
-};
-#endif /* OPENSSL_NO_OCB */
diff --git a/crypto/modes/ocb128.c b/crypto/modes/ocb128.c
index b39a55a1a145..b5202ba5bd56 100644
--- a/crypto/modes/ocb128.c
+++ b/crypto/modes/ocb128.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,7 +10,7 @@
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
-#include "modes_local.h"
+#include "crypto/modes.h"
#ifndef OPENSSL_NO_OCB
@@ -156,7 +156,7 @@ int CRYPTO_ocb128_init(OCB128_CONTEXT *ctx, void *keyenc, void *keydec,
ctx->l_index = 0;
ctx->max_l_index = 5;
if ((ctx->l = OPENSSL_malloc(ctx->max_l_index * 16)) == NULL) {
- CRYPTOerr(CRYPTO_F_CRYPTO_OCB128_INIT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -203,7 +203,7 @@ int CRYPTO_ocb128_copy_ctx(OCB128_CONTEXT *dest, OCB128_CONTEXT *src,
dest->keydec = keydec;
if (src->l) {
if ((dest->l = OPENSSL_malloc(src->max_l_index * 16)) == NULL) {
- CRYPTOerr(CRYPTO_F_CRYPTO_OCB128_COPY_CTX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(dest->l, src->l, (src->l_index + 1) * 16);
diff --git a/crypto/modes/ofb128.c b/crypto/modes/ofb128.c
index a3469712b2de..d8319f861ed4 100644
--- a/crypto/modes/ofb128.c
+++ b/crypto/modes/ofb128.c
@@ -1,15 +1,15 @@
/*
- * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/crypto.h>
-#include "modes_local.h"
#include <string.h>
+#include <openssl/crypto.h>
+#include "crypto/modes.h"
#if defined(__GNUC__) && !defined(STRICT_ALIGNMENT)
typedef size_t size_t_aX __attribute((__aligned__(1)));
@@ -29,6 +29,11 @@ void CRYPTO_ofb128_encrypt(const unsigned char *in, unsigned char *out,
unsigned int n;
size_t l = 0;
+ if (*num < 0) {
+ /* There is no good way to signal an error return from here */
+ *num = -1;
+ return;
+ }
n = *num;
#if !defined(OPENSSL_SMALL_FOOTPRINT)
diff --git a/crypto/modes/siv128.c b/crypto/modes/siv128.c
new file mode 100644
index 000000000000..e6348a8d3753
--- /dev/null
+++ b/crypto/modes/siv128.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include "internal/endian.h"
+#include "crypto/modes.h"
+#include "crypto/siv.h"
+
+#ifndef OPENSSL_NO_SIV
+
+__owur static ossl_inline uint32_t rotl8(uint32_t x)
+{
+ return (x << 8) | (x >> 24);
+}
+
+__owur static ossl_inline uint32_t rotr8(uint32_t x)
+{
+ return (x >> 8) | (x << 24);
+}
+
+__owur static ossl_inline uint64_t byteswap8(uint64_t x)
+{
+ uint32_t high = (uint32_t)(x >> 32);
+ uint32_t low = (uint32_t)x;
+
+ high = (rotl8(high) & 0x00ff00ff) | (rotr8(high) & 0xff00ff00);
+ low = (rotl8(low) & 0x00ff00ff) | (rotr8(low) & 0xff00ff00);
+ return ((uint64_t)low) << 32 | (uint64_t)high;
+}
+
+__owur static ossl_inline uint64_t siv128_getword(SIV_BLOCK const *b, size_t i)
+{
+ DECLARE_IS_ENDIAN;
+
+ if (IS_LITTLE_ENDIAN)
+ return byteswap8(b->word[i]);
+ return b->word[i];
+}
+
+static ossl_inline void siv128_putword(SIV_BLOCK *b, size_t i, uint64_t x)
+{
+ DECLARE_IS_ENDIAN;
+
+ if (IS_LITTLE_ENDIAN)
+ b->word[i] = byteswap8(x);
+ else
+ b->word[i] = x;
+}
+
+static ossl_inline void siv128_xorblock(SIV_BLOCK *x,
+ SIV_BLOCK const *y)
+{
+ x->word[0] ^= y->word[0];
+ x->word[1] ^= y->word[1];
+}
+
+/*
+ * Doubles |b|, which is 16 bytes representing an element
+ * of GF(2**128) modulo the irreducible polynomial
+ * x**128 + x**7 + x**2 + x + 1.
+ * Assumes two's-complement arithmetic
+ */
+static ossl_inline void siv128_dbl(SIV_BLOCK *b)
+{
+ uint64_t high = siv128_getword(b, 0);
+ uint64_t low = siv128_getword(b, 1);
+ uint64_t high_carry = high & (((uint64_t)1) << 63);
+ uint64_t low_carry = low & (((uint64_t)1) << 63);
+ int64_t low_mask = -((int64_t)(high_carry >> 63)) & 0x87;
+ uint64_t high_mask = low_carry >> 63;
+
+ high = (high << 1) | high_mask;
+ low = (low << 1) ^ (uint64_t)low_mask;
+ siv128_putword(b, 0, high);
+ siv128_putword(b, 1, low);
+}
+
+__owur static ossl_inline int siv128_do_s2v_p(SIV128_CONTEXT *ctx, SIV_BLOCK *out,
+ unsigned char const* in, size_t len)
+{
+ SIV_BLOCK t;
+ size_t out_len = sizeof(out->byte);
+ EVP_MAC_CTX *mac_ctx;
+ int ret = 0;
+
+ mac_ctx = EVP_MAC_CTX_dup(ctx->mac_ctx_init);
+ if (mac_ctx == NULL)
+ return 0;
+
+ if (len >= SIV_LEN) {
+ if (!EVP_MAC_update(mac_ctx, in, len - SIV_LEN))
+ goto err;
+ memcpy(&t, in + (len-SIV_LEN), SIV_LEN);
+ siv128_xorblock(&t, &ctx->d);
+ if (!EVP_MAC_update(mac_ctx, t.byte, SIV_LEN))
+ goto err;
+ } else {
+ memset(&t, 0, sizeof(t));
+ memcpy(&t, in, len);
+ t.byte[len] = 0x80;
+ siv128_dbl(&ctx->d);
+ siv128_xorblock(&t, &ctx->d);
+ if (!EVP_MAC_update(mac_ctx, t.byte, SIV_LEN))
+ goto err;
+ }
+ if (!EVP_MAC_final(mac_ctx, out->byte, &out_len, sizeof(out->byte))
+ || out_len != SIV_LEN)
+ goto err;
+
+ ret = 1;
+
+err:
+ EVP_MAC_CTX_free(mac_ctx);
+ return ret;
+}
+
+
+__owur static ossl_inline int siv128_do_encrypt(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ unsigned char const *in, size_t len,
+ SIV_BLOCK *icv)
+{
+ int out_len = (int)len;
+
+ if (!EVP_CipherInit_ex(ctx, NULL, NULL, NULL, icv->byte, 1))
+ return 0;
+ return EVP_EncryptUpdate(ctx, out, &out_len, in, out_len);
+}
+
+/*
+ * Create a new SIV128_CONTEXT
+ */
+SIV128_CONTEXT *ossl_siv128_new(const unsigned char *key, int klen,
+ EVP_CIPHER *cbc, EVP_CIPHER *ctr,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ SIV128_CONTEXT *ctx;
+ int ret;
+
+ if ((ctx = OPENSSL_malloc(sizeof(*ctx))) != NULL) {
+ ret = ossl_siv128_init(ctx, key, klen, cbc, ctr, libctx, propq);
+ if (ret)
+ return ctx;
+ OPENSSL_free(ctx);
+ }
+
+ return NULL;
+}
+
+/*
+ * Initialise an existing SIV128_CONTEXT
+ */
+int ossl_siv128_init(SIV128_CONTEXT *ctx, const unsigned char *key, int klen,
+ const EVP_CIPHER *cbc, const EVP_CIPHER *ctr,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ static const unsigned char zero[SIV_LEN] = { 0 };
+ size_t out_len = SIV_LEN;
+ EVP_MAC_CTX *mac_ctx = NULL;
+ OSSL_PARAM params[3];
+ const char *cbc_name;
+
+ if (ctx == NULL)
+ return 0;
+
+ memset(&ctx->d, 0, sizeof(ctx->d));
+ EVP_CIPHER_CTX_free(ctx->cipher_ctx);
+ EVP_MAC_CTX_free(ctx->mac_ctx_init);
+ EVP_MAC_free(ctx->mac);
+ ctx->mac = NULL;
+ ctx->cipher_ctx = NULL;
+ ctx->mac_ctx_init = NULL;
+
+ if (key == NULL || cbc == NULL || ctr == NULL)
+ return 0;
+
+ cbc_name = EVP_CIPHER_get0_name(cbc);
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER,
+ (char *)cbc_name, 0);
+ params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ (void *)key, klen);
+ params[2] = OSSL_PARAM_construct_end();
+
+ if ((ctx->cipher_ctx = EVP_CIPHER_CTX_new()) == NULL
+ || (ctx->mac =
+ EVP_MAC_fetch(libctx, OSSL_MAC_NAME_CMAC, propq)) == NULL
+ || (ctx->mac_ctx_init = EVP_MAC_CTX_new(ctx->mac)) == NULL
+ || !EVP_MAC_CTX_set_params(ctx->mac_ctx_init, params)
+ || !EVP_EncryptInit_ex(ctx->cipher_ctx, ctr, NULL, key + klen, NULL)
+ || (mac_ctx = EVP_MAC_CTX_dup(ctx->mac_ctx_init)) == NULL
+ || !EVP_MAC_update(mac_ctx, zero, sizeof(zero))
+ || !EVP_MAC_final(mac_ctx, ctx->d.byte, &out_len,
+ sizeof(ctx->d.byte))) {
+ EVP_CIPHER_CTX_free(ctx->cipher_ctx);
+ EVP_MAC_CTX_free(ctx->mac_ctx_init);
+ EVP_MAC_CTX_free(mac_ctx);
+ EVP_MAC_free(ctx->mac);
+ return 0;
+ }
+ EVP_MAC_CTX_free(mac_ctx);
+
+ ctx->final_ret = -1;
+ ctx->crypto_ok = 1;
+
+ return 1;
+}
+
+/*
+ * Copy an SIV128_CONTEXT object
+ */
+int ossl_siv128_copy_ctx(SIV128_CONTEXT *dest, SIV128_CONTEXT *src)
+{
+ memcpy(&dest->d, &src->d, sizeof(src->d));
+ if (dest->cipher_ctx == NULL) {
+ dest->cipher_ctx = EVP_CIPHER_CTX_new();
+ if (dest->cipher_ctx == NULL)
+ return 0;
+ }
+ if (!EVP_CIPHER_CTX_copy(dest->cipher_ctx, src->cipher_ctx))
+ return 0;
+ EVP_MAC_CTX_free(dest->mac_ctx_init);
+ dest->mac_ctx_init = EVP_MAC_CTX_dup(src->mac_ctx_init);
+ if (dest->mac_ctx_init == NULL)
+ return 0;
+ dest->mac = src->mac;
+ if (dest->mac != NULL)
+ EVP_MAC_up_ref(dest->mac);
+ return 1;
+}
+
+/*
+ * Provide any AAD. This can be called multiple times.
+ * Per RFC5297, the last piece of associated data
+ * is the nonce, but it's not treated special
+ */
+int ossl_siv128_aad(SIV128_CONTEXT *ctx, const unsigned char *aad,
+ size_t len)
+{
+ SIV_BLOCK mac_out;
+ size_t out_len = SIV_LEN;
+ EVP_MAC_CTX *mac_ctx;
+
+ siv128_dbl(&ctx->d);
+
+ if ((mac_ctx = EVP_MAC_CTX_dup(ctx->mac_ctx_init)) == NULL
+ || !EVP_MAC_update(mac_ctx, aad, len)
+ || !EVP_MAC_final(mac_ctx, mac_out.byte, &out_len,
+ sizeof(mac_out.byte))
+ || out_len != SIV_LEN) {
+ EVP_MAC_CTX_free(mac_ctx);
+ return 0;
+ }
+ EVP_MAC_CTX_free(mac_ctx);
+
+ siv128_xorblock(&ctx->d, &mac_out);
+
+ return 1;
+}
+
+/*
+ * Provide any data to be encrypted. This can be called once.
+ */
+int ossl_siv128_encrypt(SIV128_CONTEXT *ctx,
+ const unsigned char *in, unsigned char *out,
+ size_t len)
+{
+ SIV_BLOCK q;
+
+ /* can only do one crypto operation */
+ if (ctx->crypto_ok == 0)
+ return 0;
+ ctx->crypto_ok--;
+
+ if (!siv128_do_s2v_p(ctx, &q, in, len))
+ return 0;
+
+ memcpy(ctx->tag.byte, &q, SIV_LEN);
+ q.byte[8] &= 0x7f;
+ q.byte[12] &= 0x7f;
+
+ if (!siv128_do_encrypt(ctx->cipher_ctx, out, in, len, &q))
+ return 0;
+ ctx->final_ret = 0;
+ return len;
+}
+
+/*
+ * Provide any data to be decrypted. This can be called once.
+ */
+int ossl_siv128_decrypt(SIV128_CONTEXT *ctx,
+ const unsigned char *in, unsigned char *out,
+ size_t len)
+{
+ unsigned char* p;
+ SIV_BLOCK t, q;
+ int i;
+
+ /* can only do one crypto operation */
+ if (ctx->crypto_ok == 0)
+ return 0;
+ ctx->crypto_ok--;
+
+ memcpy(&q, ctx->tag.byte, SIV_LEN);
+ q.byte[8] &= 0x7f;
+ q.byte[12] &= 0x7f;
+
+ if (!siv128_do_encrypt(ctx->cipher_ctx, out, in, len, &q)
+ || !siv128_do_s2v_p(ctx, &t, out, len))
+ return 0;
+
+ p = ctx->tag.byte;
+ for (i = 0; i < SIV_LEN; i++)
+ t.byte[i] ^= p[i];
+
+ if ((t.word[0] | t.word[1]) != 0) {
+ OPENSSL_cleanse(out, len);
+ return 0;
+ }
+ ctx->final_ret = 0;
+ return len;
+}
+
+/*
+ * Return the already calculated final result.
+ */
+int ossl_siv128_finish(SIV128_CONTEXT *ctx)
+{
+ return ctx->final_ret;
+}
+
+/*
+ * Set the tag
+ */
+int ossl_siv128_set_tag(SIV128_CONTEXT *ctx, const unsigned char *tag, size_t len)
+{
+ if (len != SIV_LEN)
+ return 0;
+
+ /* Copy the tag from the supplied buffer */
+ memcpy(ctx->tag.byte, tag, len);
+ return 1;
+}
+
+/*
+ * Retrieve the calculated tag
+ */
+int ossl_siv128_get_tag(SIV128_CONTEXT *ctx, unsigned char *tag, size_t len)
+{
+ if (len != SIV_LEN)
+ return 0;
+
+ /* Copy the tag into the supplied buffer */
+ memcpy(tag, ctx->tag.byte, len);
+ return 1;
+}
+
+/*
+ * Release all resources
+ */
+int ossl_siv128_cleanup(SIV128_CONTEXT *ctx)
+{
+ if (ctx != NULL) {
+ EVP_CIPHER_CTX_free(ctx->cipher_ctx);
+ ctx->cipher_ctx = NULL;
+ EVP_MAC_CTX_free(ctx->mac_ctx_init);
+ ctx->mac_ctx_init = NULL;
+ EVP_MAC_free(ctx->mac);
+ ctx->mac = NULL;
+ OPENSSL_cleanse(&ctx->d, sizeof(ctx->d));
+ OPENSSL_cleanse(&ctx->tag, sizeof(ctx->tag));
+ ctx->final_ret = -1;
+ ctx->crypto_ok = 1;
+ }
+ return 1;
+}
+
+int ossl_siv128_speed(SIV128_CONTEXT *ctx, int arg)
+{
+ ctx->crypto_ok = (arg == 1) ? -1 : 1;
+ return 1;
+}
+
+#endif /* OPENSSL_NO_SIV */
diff --git a/crypto/modes/wrap128.c b/crypto/modes/wrap128.c
index d7e56cc260ad..a9622c16bd76 100644
--- a/crypto/modes/wrap128.c
+++ b/crypto/modes/wrap128.c
@@ -1,7 +1,7 @@
/*
* Copyright 2013-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/modes/xts128.c b/crypto/modes/xts128.c
index fe1626c62e10..55b81366bf82 100644
--- a/crypto/modes/xts128.c
+++ b/crypto/modes/xts128.c
@@ -1,15 +1,16 @@
/*
* Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/crypto.h>
-#include "modes_local.h"
#include <string.h>
+#include <openssl/crypto.h>
+#include "internal/endian.h"
+#include "crypto/modes.h"
#ifndef STRICT_ALIGNMENT
# ifdef __GNUC__
@@ -24,12 +25,7 @@ int CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx,
const unsigned char *inp, unsigned char *out,
size_t len, int enc)
{
- const union {
- long one;
- char little;
- } is_endian = {
- 1
- };
+ DECLARE_IS_ENDIAN;
union {
u64 u[2];
u32 d[4];
@@ -72,7 +68,7 @@ int CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx,
if (len == 0)
return 0;
- if (is_endian.little) {
+ if (IS_LITTLE_ENDIAN) {
unsigned int carry, res;
res = 0x87 & (((int)tweak.d[3]) >> 31);
@@ -111,7 +107,7 @@ int CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx,
u8 c[16];
} tweak1;
- if (is_endian.little) {
+ if (IS_LITTLE_ENDIAN) {
unsigned int carry, res;
res = 0x87 & (((int)tweak.d[3]) >> 31);
diff --git a/crypto/o_dir.c b/crypto/o_dir.c
index fca9c75e0533..6857a2e17d4f 100644
--- a/crypto/o_dir.c
+++ b/crypto/o_dir.c
@@ -1,7 +1,7 @@
/*
* Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/o_fips.c b/crypto/o_fips.c
deleted file mode 100644
index 050ea9c216cf..000000000000
--- a/crypto/o_fips.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "internal/cryptlib.h"
-
-int FIPS_mode(void)
-{
- /* This version of the library does not support FIPS mode. */
- return 0;
-}
-
-int FIPS_mode_set(int r)
-{
- if (r == 0)
- return 1;
- CRYPTOerr(CRYPTO_F_FIPS_MODE_SET, CRYPTO_R_FIPS_MODE_NOT_SUPPORTED);
- return 0;
-}
diff --git a/crypto/o_fopen.c b/crypto/o_fopen.c
index 7d51ad725426..8095fffbe0c9 100644
--- a/crypto/o_fopen.c
+++ b/crypto/o_fopen.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -88,7 +88,7 @@ FILE *openssl_fopen(const char *filename, const char *mode)
char lastchar;
if ((newname = OPENSSL_malloc(strlen(filename) + 1)) == NULL) {
- CRYPTOerr(CRYPTO_F_OPENSSL_FOPEN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return NULL;
}
diff --git a/crypto/o_init.c b/crypto/o_init.c
index ed6b1303d8ad..a0b4256f78f6 100644
--- a/crypto/o_init.c
+++ b/crypto/o_init.c
@@ -1,7 +1,7 @@
/*
* Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/o_str.c b/crypto/o_str.c
index eb9f21cc0c45..7fa487dd5fcd 100644
--- a/crypto/o_str.c
+++ b/crypto/o_str.c
@@ -1,28 +1,22 @@
/*
- * Copyright 2003-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2003-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "e_os.h"
+#include <string.h>
#include <limits.h>
#include <openssl/crypto.h>
+#include "crypto/ctype.h"
#include "internal/cryptlib.h"
-#include "internal/o_str.h"
+#include "internal/thread_once.h"
-int OPENSSL_memcmp(const void *v1, const void *v2, size_t n)
-{
- const unsigned char *c1 = v1, *c2 = v2;
- int ret = 0;
-
- while (n && (ret = *c1 - *c2) == 0)
- n--, c1++, c2++;
-
- return ret;
-}
+#define DEFAULT_SEPARATOR ':'
+#define CH_ZERO '\0'
char *CRYPTO_strdup(const char *str, const char* file, int line)
{
@@ -49,7 +43,7 @@ char *CRYPTO_strndup(const char *str, size_t s, const char* file, int line)
ret = CRYPTO_malloc(maxlen + 1, file, line);
if (ret) {
memcpy(ret, str, maxlen);
- ret[maxlen] = '\0';
+ ret[maxlen] = CH_ZERO;
}
return ret;
}
@@ -63,7 +57,7 @@ void *CRYPTO_memdup(const void *data, size_t siz, const char* file, int line)
ret = CRYPTO_malloc(siz, file, line);
if (ret == NULL) {
- CRYPTOerr(CRYPTO_F_CRYPTO_MEMDUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return NULL;
}
return memcpy(ret, data, siz);
@@ -73,7 +67,7 @@ size_t OPENSSL_strnlen(const char *str, size_t maxlen)
{
const char *p;
- for (p = str; maxlen-- != 0 && *p != '\0'; ++p) ;
+ for (p = str; maxlen-- != 0 && *p != CH_ZERO; ++p) ;
return p - str;
}
@@ -86,7 +80,7 @@ size_t OPENSSL_strlcpy(char *dst, const char *src, size_t size)
l++;
}
if (size)
- *dst = '\0';
+ *dst = CH_ZERO;
return l + strlen(src);
}
@@ -141,81 +135,163 @@ int OPENSSL_hexchar2int(unsigned char c)
return -1;
}
-/*
- * Give a string of hex digits convert to a buffer
- */
-unsigned char *OPENSSL_hexstr2buf(const char *str, long *len)
+static int hexstr2buf_sep(unsigned char *buf, size_t buf_n, size_t *buflen,
+ const char *str, const char sep)
{
- unsigned char *hexbuf, *q;
+ unsigned char *q;
unsigned char ch, cl;
int chi, cli;
const unsigned char *p;
- size_t s;
+ size_t cnt;
- s = strlen(str);
- if ((hexbuf = OPENSSL_malloc(s >> 1)) == NULL) {
- CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- for (p = (const unsigned char *)str, q = hexbuf; *p; ) {
+ for (p = (const unsigned char *)str, q = buf, cnt = 0; *p; ) {
ch = *p++;
- if (ch == ':')
+ /* A separator of CH_ZERO means there is no separator */
+ if (ch == sep && sep != CH_ZERO)
continue;
cl = *p++;
if (!cl) {
- CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF,
- CRYPTO_R_ODD_NUMBER_OF_DIGITS);
- OPENSSL_free(hexbuf);
- return NULL;
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_ODD_NUMBER_OF_DIGITS);
+ return 0;
}
cli = OPENSSL_hexchar2int(cl);
chi = OPENSSL_hexchar2int(ch);
if (cli < 0 || chi < 0) {
- OPENSSL_free(hexbuf);
- CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, CRYPTO_R_ILLEGAL_HEX_DIGIT);
- return NULL;
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_ILLEGAL_HEX_DIGIT);
+ return 0;
+ }
+ cnt++;
+ if (q != NULL) {
+ if (cnt > buf_n) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_SMALL_BUFFER);
+ return 0;
+ }
+ *q++ = (unsigned char)((chi << 4) | cli);
}
- *q++ = (unsigned char)((chi << 4) | cli);
}
- if (len)
- *len = q - hexbuf;
- return hexbuf;
+ if (buflen != NULL)
+ *buflen = cnt;
+ return 1;
}
/*
- * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
- * hex representation @@@ (Contents of buffer are always kept in ASCII, also
- * on EBCDIC machines)
+ * Given a string of hex digits convert to a buffer
*/
-char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len)
+int OPENSSL_hexstr2buf_ex(unsigned char *buf, size_t buf_n, size_t *buflen,
+ const char *str, const char sep)
+{
+ return hexstr2buf_sep(buf, buf_n, buflen, str, sep);
+}
+
+unsigned char *ossl_hexstr2buf_sep(const char *str, long *buflen,
+ const char sep)
+{
+ unsigned char *buf;
+ size_t buf_n, tmp_buflen;
+
+ buf_n = strlen(str);
+ if (buf_n <= 1) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_HEX_STRING_TOO_SHORT);
+ return NULL;
+ }
+ buf_n /= 2;
+ if ((buf = OPENSSL_malloc(buf_n)) == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (buflen != NULL)
+ *buflen = 0;
+ tmp_buflen = 0;
+ if (hexstr2buf_sep(buf, buf_n, &tmp_buflen, str, sep)) {
+ if (buflen != NULL)
+ *buflen = (long)tmp_buflen;
+ return buf;
+ }
+ OPENSSL_free(buf);
+ return NULL;
+}
+
+unsigned char *OPENSSL_hexstr2buf(const char *str, long *buflen)
+{
+ return ossl_hexstr2buf_sep(str, buflen, DEFAULT_SEPARATOR);
+}
+
+static int buf2hexstr_sep(char *str, size_t str_n, size_t *strlength,
+ const unsigned char *buf, size_t buflen,
+ const char sep)
{
static const char hexdig[] = "0123456789ABCDEF";
- char *tmp, *q;
const unsigned char *p;
- int i;
+ char *q;
+ size_t i;
+ int has_sep = (sep != CH_ZERO);
+ size_t len = has_sep ? buflen * 3 : 1 + buflen * 2;
- if (len == 0)
- {
- return OPENSSL_zalloc(1);
- }
+ if (strlength != NULL)
+ *strlength = len;
+ if (str == NULL)
+ return 1;
- if ((tmp = OPENSSL_malloc(len * 3)) == NULL) {
- CRYPTOerr(CRYPTO_F_OPENSSL_BUF2HEXSTR, ERR_R_MALLOC_FAILURE);
- return NULL;
+ if (str_n < (unsigned long)len) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_SMALL_BUFFER);
+ return 0;
}
- q = tmp;
- for (i = 0, p = buffer; i < len; i++, p++) {
+
+ q = str;
+ for (i = 0, p = buf; i < buflen; i++, p++) {
*q++ = hexdig[(*p >> 4) & 0xf];
*q++ = hexdig[*p & 0xf];
- *q++ = ':';
+ if (has_sep)
+ *q++ = sep;
}
- q[-1] = 0;
+ if (has_sep)
+ --q;
+ *q = CH_ZERO;
+
#ifdef CHARSET_EBCDIC
- ebcdic2ascii(tmp, tmp, q - tmp - 1);
+ ebcdic2ascii(str, str, q - str - 1);
#endif
+ return 1;
+}
- return tmp;
+int OPENSSL_buf2hexstr_ex(char *str, size_t str_n, size_t *strlength,
+ const unsigned char *buf, size_t buflen,
+ const char sep)
+{
+ return buf2hexstr_sep(str, str_n, strlength, buf, buflen, sep);
+}
+
+char *ossl_buf2hexstr_sep(const unsigned char *buf, long buflen, char sep)
+{
+ char *tmp;
+ size_t tmp_n;
+
+ if (buflen == 0)
+ return OPENSSL_zalloc(1);
+
+ tmp_n = (sep != CH_ZERO) ? buflen * 3 : 1 + buflen * 2;
+ if ((tmp = OPENSSL_malloc(tmp_n)) == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (buf2hexstr_sep(tmp, tmp_n, NULL, buf, buflen, sep))
+ return tmp;
+ OPENSSL_free(tmp);
+ return NULL;
+}
+
+
+/*
+ * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
+ * hex representation @@@ (Contents of buffer are always kept in ASCII, also
+ * on EBCDIC machines)
+ */
+char *OPENSSL_buf2hexstr(const unsigned char *buf, long buflen)
+{
+ return ossl_buf2hexstr_sep(buf, buflen, ':');
}
int openssl_strerror_r(int errnum, char *buf, size_t buflen)
@@ -265,3 +341,26 @@ int openssl_strerror_r(int errnum, char *buf, size_t buflen)
return 1;
#endif
}
+
+int OPENSSL_strcasecmp(const char *s1, const char *s2)
+{
+ int t;
+
+ while ((t = ossl_tolower(*s1) - ossl_tolower(*s2++)) == 0)
+ if (*s1++ == '\0')
+ return 0;
+ return t;
+}
+
+int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n)
+{
+ int t;
+ size_t i;
+
+ for (i = 0; i < n; i++)
+ if ((t = ossl_tolower(*s1) - ossl_tolower(*s2++)) != 0)
+ return t;
+ else if (*s1++ == '\0')
+ return 0;
+ return 0;
+}
diff --git a/crypto/o_time.c b/crypto/o_time.c
index 3fa70c45af83..23ffe162453e 100644
--- a/crypto/o_time.c
+++ b/crypto/o_time.c
@@ -1,7 +1,7 @@
/*
* Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/objects/README b/crypto/objects/README
deleted file mode 100644
index 700f9c5e54f9..000000000000
--- a/crypto/objects/README
+++ /dev/null
@@ -1,44 +0,0 @@
-objects.txt syntax
-------------------
-
-To cover all the naming hacks that were previously in objects.h needed some
-kind of hacks in objects.txt.
-
-The basic syntax for adding an object is as follows:
-
- 1 2 3 4 : shortName : Long Name
-
- If Long Name contains only word characters and hyphen-minus
- (0x2D) or full stop (0x2E) then Long Name is used as basis
- for the base name in C. Otherwise, the shortName is used.
-
- The base name (let's call it 'base') will then be used to
- create the C macros SN_base, LN_base, NID_base and OBJ_base.
-
- Note that if the base name contains spaces, dashes or periods,
- those will be converted to underscore.
-
-Then there are some extra commands:
-
- !Alias foo 1 2 3 4
-
- This just makes a name foo for an OID. The C macro
- OBJ_foo will be created as a result.
-
- !Cname foo
-
- This makes sure that the name foo will be used as base name
- in C.
-
- !module foo
- 1 2 3 4 : shortName : Long Name
- !global
-
- The !module command was meant to define a kind of modularity.
- What it does is to make sure the module name is prepended
- to the base name. !global turns this off. This construction
- is not recursive.
-
-Lines starting with # are treated as comments, as well as any line starting
-with ! and not matching the commands above.
-
diff --git a/crypto/objects/README.md b/crypto/objects/README.md
new file mode 100644
index 000000000000..49c749887d2f
--- /dev/null
+++ b/crypto/objects/README.md
@@ -0,0 +1,43 @@
+objects.txt syntax
+==================
+
+To cover all the naming hacks that were previously in `objects.h` needed some
+kind of hacks in `objects.txt`.
+
+The basic syntax for adding an object is as follows:
+
+ 1 2 3 4 : shortName : Long Name
+
+ If Long Name contains only word characters and hyphen-minus
+ (0x2D) or full stop (0x2E) then Long Name is used as basis
+ for the base name in C. Otherwise, the shortName is used.
+
+ The base name (let's call it 'base') will then be used to
+ create the C macros SN_base, LN_base, NID_base and OBJ_base.
+
+ Note that if the base name contains spaces, dashes or periods,
+ those will be converted to underscore.
+
+Then there are some extra commands:
+
+ !Alias foo 1 2 3 4
+
+ This just makes a name foo for an OID. The C macro
+ OBJ_foo will be created as a result.
+
+ !Cname foo
+
+ This makes sure that the name foo will be used as base name
+ in C.
+
+ !module foo
+ 1 2 3 4 : shortName : Long Name
+ !global
+
+ The !module command was meant to define a kind of modularity.
+ What it does is to make sure the module name is prepended
+ to the base name. !global turns this off. This construction
+ is not recursive.
+
+Lines starting with `#` are treated as comments, as well as any line starting
+with ! and not matching the commands above.
diff --git a/crypto/objects/o_names.c b/crypto/objects/o_names.c
index 872676ba2277..791f2b011e35 100644
--- a/crypto/objects/o_names.c
+++ b/crypto/objects/o_names.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -22,23 +22,6 @@
#include "e_os.h"
/*
- * We define this wrapper for two reasons. Firstly, later versions of
- * DEC C add linkage information to certain functions, which makes it
- * tricky to use them as values to regular function pointers.
- * Secondly, in the EDK2 build environment, the strcasecmp function is
- * actually an external function with the Microsoft ABI, so we can't
- * transparently assign function pointers to it.
- */
-#if defined(OPENSSL_SYS_VMS_DECC) || defined(OPENSSL_SYS_UEFI)
-static int obj_strcasecmp(const char *a, const char *b)
-{
- return strcasecmp(a, b);
-}
-#else
-#define obj_strcasecmp strcasecmp
-#endif
-
-/*
* I use the ex_data stuff to manage the identifiers for the obj_name_types
* that applications may define. I only really use the free function field.
*/
@@ -66,7 +49,6 @@ static int obj_name_cmp(const OBJ_NAME *a, const OBJ_NAME *b);
static CRYPTO_ONCE init = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(o_names_init)
{
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
names_lh = NULL;
obj_lock = CRYPTO_THREAD_lock_new();
if (obj_lock != NULL)
@@ -75,7 +57,6 @@ DEFINE_RUN_ONCE_STATIC(o_names_init)
CRYPTO_THREAD_lock_free(obj_lock);
obj_lock = NULL;
}
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
return names_lh != NULL && obj_lock != NULL;
}
@@ -94,13 +75,11 @@ int OBJ_NAME_new_index(unsigned long (*hash_func) (const char *),
if (!OBJ_NAME_init())
return 0;
- CRYPTO_THREAD_write_lock(obj_lock);
+ if (!CRYPTO_THREAD_write_lock(obj_lock))
+ return 0;
- if (name_funcs_stack == NULL) {
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
+ if (name_funcs_stack == NULL)
name_funcs_stack = sk_NAME_FUNCS_new_null();
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
- }
if (name_funcs_stack == NULL) {
/* ERROR */
goto out;
@@ -108,23 +87,18 @@ int OBJ_NAME_new_index(unsigned long (*hash_func) (const char *),
ret = names_type_num;
names_type_num++;
for (i = sk_NAME_FUNCS_num(name_funcs_stack); i < names_type_num; i++) {
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
name_funcs = OPENSSL_zalloc(sizeof(*name_funcs));
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
if (name_funcs == NULL) {
- OBJerr(OBJ_F_OBJ_NAME_NEW_INDEX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE);
ret = 0;
goto out;
}
- name_funcs->hash_func = openssl_lh_strcasehash;
- name_funcs->cmp_func = obj_strcasecmp;
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
-
+ name_funcs->hash_func = ossl_lh_strcasehash;
+ name_funcs->cmp_func = OPENSSL_strcasecmp;
push = sk_NAME_FUNCS_push(name_funcs_stack, name_funcs);
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
if (!push) {
- OBJerr(OBJ_F_OBJ_NAME_NEW_INDEX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE);
OPENSSL_free(name_funcs);
ret = 0;
goto out;
@@ -154,7 +128,7 @@ static int obj_name_cmp(const OBJ_NAME *a, const OBJ_NAME *b)
ret = sk_NAME_FUNCS_value(name_funcs_stack,
a->type)->cmp_func(a->name, b->name);
} else
- ret = strcasecmp(a->name, b->name);
+ ret = OPENSSL_strcasecmp(a->name, b->name);
}
return ret;
}
@@ -169,7 +143,7 @@ static unsigned long obj_name_hash(const OBJ_NAME *a)
sk_NAME_FUNCS_value(name_funcs_stack,
a->type)->hash_func(a->name);
} else {
- ret = openssl_lh_strcasehash(a->name);
+ ret = ossl_lh_strcasehash(a->name);
}
ret ^= a->type;
return ret;
@@ -185,7 +159,8 @@ const char *OBJ_NAME_get(const char *name, int type)
return NULL;
if (!OBJ_NAME_init())
return NULL;
- CRYPTO_THREAD_read_lock(obj_lock);
+ if (!CRYPTO_THREAD_read_lock(obj_lock))
+ return NULL;
alias = type & OBJ_NAME_ALIAS;
type &= ~OBJ_NAME_ALIAS;
@@ -231,7 +206,10 @@ int OBJ_NAME_add(const char *name, int type, const char *data)
onp->type = type;
onp->data = data;
- CRYPTO_THREAD_write_lock(obj_lock);
+ if (!CRYPTO_THREAD_write_lock(obj_lock)) {
+ OPENSSL_free(onp);
+ return 0;
+ }
ret = lh_OBJ_NAME_insert(names_lh, onp);
if (ret != NULL) {
@@ -270,7 +248,8 @@ int OBJ_NAME_remove(const char *name, int type)
if (!OBJ_NAME_init())
return 0;
- CRYPTO_THREAD_write_lock(obj_lock);
+ if (!CRYPTO_THREAD_write_lock(obj_lock))
+ return 0;
type &= ~OBJ_NAME_ALIAS;
on.name = name;
diff --git a/crypto/objects/obj_compat.h b/crypto/objects/obj_compat.h
new file mode 100644
index 000000000000..7d890d1c0b85
--- /dev/null
+++ b/crypto/objects/obj_compat.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+
+#define SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm SN_magma_ctr_acpkm
+#define NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm NID_magma_ctr_acpkm
+#define OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm OBJ_magma_ctr_acpkm
+
+#define SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac SN_magma_ctr_acpkm_omac
+#define NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac NID_magma_ctr_acpkm_omac
+#define OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac OBJ_magma_ctr_acpkm_omac
+
+#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm SN_kuznyechik_ctr_acpkm
+#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm NID_kuznyechik_ctr_acpkm
+#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm OBJ_kuznyechik_ctr_acpkm
+
+#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac SN_kuznyechik_ctr_acpkm_omac
+#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac NID_kuznyechik_ctr_acpkm_omac
+#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac OBJ_kuznyechik_ctr_acpkm_omac
+
+#define SN_id_tc26_wrap_gostr3412_2015_magma_kexp15 SN_magma_kexp15
+#define NID_id_tc26_wrap_gostr3412_2015_magma_kexp15 NID_magma_kexp15
+#define OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 OBJ_magma_kexp15
+
+#define SN_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 SN_kuznyechik_kexp15
+#define NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 NID_kuznyechik_kexp15
+#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 OBJ_kuznyechik_kexp15
+
+#define SN_grasshopper_ecb SN_kuznyechik_ecb
+#define NID_grasshopper_ecb NID_kuznyechik_ecb
+
+#define SN_grasshopper_ctr SN_kuznyechik_ctr
+#define NID_grasshopper_ctr NID_kuznyechik_ctr
+
+#define SN_grasshopper_ofb SN_kuznyechik_ofb
+#define NID_grasshopper_ofb NID_kuznyechik_ofb
+
+#define SN_grasshopper_cbc SN_kuznyechik_cbc
+#define NID_grasshopper_cbc NID_kuznyechik_cbc
+
+#define SN_grasshopper_cfb SN_kuznyechik_cfb
+#define NID_grasshopper_cfb NID_kuznyechik_cfb
+
+#define SN_grasshopper_mac SN_kuznyechik_mac
+#define NID_grasshopper_mac NID_kuznyechik_mac
+
+#endif /* OPENSSL_NO_DEPRECATED_3_0 */
diff --git a/crypto/objects/obj_dat.c b/crypto/objects/obj_dat.c
index 7e8de727f310..01cde00e98b7 100644
--- a/crypto/objects/obj_dat.c
+++ b/crypto/objects/obj_dat.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -150,7 +150,7 @@ static void cleanup3_doall(ADDED_OBJ *a)
OPENSSL_free(a);
}
-void obj_cleanup_int(void)
+void ossl_obj_cleanup_int(void)
{
if (added == NULL)
return;
@@ -209,7 +209,7 @@ int OBJ_add_object(const ASN1_OBJECT *obj)
return o->nid;
err2:
- OBJerr(OBJ_F_OBJ_ADD_OBJECT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE);
err:
for (i = ADDED_DATA; i <= ADDED_NID; i++)
OPENSSL_free(ao[i]);
@@ -224,25 +224,27 @@ ASN1_OBJECT *OBJ_nid2obj(int n)
if ((n >= 0) && (n < NUM_NID)) {
if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {
- OBJerr(OBJ_F_OBJ_NID2OBJ, OBJ_R_UNKNOWN_NID);
+ ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_NID);
return NULL;
}
return (ASN1_OBJECT *)&(nid_objs[n]);
- } else if (added == NULL) {
- OBJerr(OBJ_F_OBJ_NID2OBJ, OBJ_R_UNKNOWN_NID);
- return NULL;
- } else {
- ad.type = ADDED_NID;
- ad.obj = &ob;
- ob.nid = n;
- adp = lh_ADDED_OBJ_retrieve(added, &ad);
- if (adp != NULL)
- return adp->obj;
- else {
- OBJerr(OBJ_F_OBJ_NID2OBJ, OBJ_R_UNKNOWN_NID);
- return NULL;
- }
}
+
+ /* Make sure we've loaded config before checking for any "added" objects */
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+
+ if (added == NULL)
+ return NULL;
+
+ ad.type = ADDED_NID;
+ ad.obj = &ob;
+ ob.nid = n;
+ adp = lh_ADDED_OBJ_retrieve(added, &ad);
+ if (adp != NULL)
+ return adp->obj;
+
+ ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_NID);
+ return NULL;
}
const char *OBJ_nid2sn(int n)
@@ -252,24 +254,27 @@ const char *OBJ_nid2sn(int n)
if ((n >= 0) && (n < NUM_NID)) {
if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {
- OBJerr(OBJ_F_OBJ_NID2SN, OBJ_R_UNKNOWN_NID);
+ ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_NID);
return NULL;
}
return nid_objs[n].sn;
- } else if (added == NULL)
- return NULL;
- else {
- ad.type = ADDED_NID;
- ad.obj = &ob;
- ob.nid = n;
- adp = lh_ADDED_OBJ_retrieve(added, &ad);
- if (adp != NULL)
- return adp->obj->sn;
- else {
- OBJerr(OBJ_F_OBJ_NID2SN, OBJ_R_UNKNOWN_NID);
- return NULL;
- }
}
+
+ /* Make sure we've loaded config before checking for any "added" objects */
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+
+ if (added == NULL)
+ return NULL;
+
+ ad.type = ADDED_NID;
+ ad.obj = &ob;
+ ob.nid = n;
+ adp = lh_ADDED_OBJ_retrieve(added, &ad);
+ if (adp != NULL)
+ return adp->obj->sn;
+
+ ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_NID);
+ return NULL;
}
const char *OBJ_nid2ln(int n)
@@ -279,24 +284,27 @@ const char *OBJ_nid2ln(int n)
if ((n >= 0) && (n < NUM_NID)) {
if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {
- OBJerr(OBJ_F_OBJ_NID2LN, OBJ_R_UNKNOWN_NID);
+ ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_NID);
return NULL;
}
return nid_objs[n].ln;
- } else if (added == NULL)
- return NULL;
- else {
- ad.type = ADDED_NID;
- ad.obj = &ob;
- ob.nid = n;
- adp = lh_ADDED_OBJ_retrieve(added, &ad);
- if (adp != NULL)
- return adp->obj->ln;
- else {
- OBJerr(OBJ_F_OBJ_NID2LN, OBJ_R_UNKNOWN_NID);
- return NULL;
- }
}
+
+ /* Make sure we've loaded config before checking for any "added" objects */
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+
+ if (added == NULL)
+ return NULL;
+
+ ad.type = ADDED_NID;
+ ad.obj = &ob;
+ ob.nid = n;
+ adp = lh_ADDED_OBJ_retrieve(added, &ad);
+ if (adp != NULL)
+ return adp->obj->ln;
+
+ ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_NID);
+ return NULL;
}
static int obj_cmp(const ASN1_OBJECT *const *ap, const unsigned int *bp)
@@ -328,6 +336,9 @@ int OBJ_obj2nid(const ASN1_OBJECT *a)
if (a->length == 0)
return NID_undef;
+ /* Make sure we've loaded config before checking for any "added" objects */
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+
if (added != NULL) {
ad.type = ADDED_DATA;
ad.obj = (ASN1_OBJECT *)a; /* XXX: ugly but harmless */
@@ -361,6 +372,10 @@ ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name)
if (((nid = OBJ_sn2nid(s)) != NID_undef) ||
((nid = OBJ_ln2nid(s)) != NID_undef))
return OBJ_nid2obj(nid);
+ if (!ossl_isdigit(*s)) {
+ ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_OBJECT_NAME);
+ return NULL;
+ }
}
/* Work out size of content octets */
@@ -378,7 +393,7 @@ ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name)
return NULL;
if ((buf = OPENSSL_malloc(j)) == NULL) {
- OBJerr(OBJ_F_OBJ_TXT2OBJ, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -545,6 +560,9 @@ int OBJ_ln2nid(const char *s)
ADDED_OBJ ad, *adp;
const unsigned int *op;
+ /* Make sure we've loaded config before checking for any "added" objects */
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+
o.ln = s;
if (added != NULL) {
ad.type = ADDED_LNAME;
@@ -566,6 +584,9 @@ int OBJ_sn2nid(const char *s)
ADDED_OBJ ad, *adp;
const unsigned int *op;
+ /* Make sure we've loaded config before checking for any "added" objects */
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+
o.sn = s;
if (added != NULL) {
ad.type = ADDED_SNAME;
@@ -586,52 +607,32 @@ const void *OBJ_bsearch_(const void *key, const void *base, int num, int size,
return OBJ_bsearch_ex_(key, base, num, size, cmp, 0);
}
-const void *OBJ_bsearch_ex_(const void *key, const void *base_, int num,
+const void *OBJ_bsearch_ex_(const void *key, const void *base, int num,
int size,
int (*cmp) (const void *, const void *),
int flags)
{
- const char *base = base_;
- int l, h, i = 0, c = 0;
- const char *p = NULL;
+ const char *p = ossl_bsearch(key, base, num, size, cmp, flags);
- if (num == 0)
- return NULL;
- l = 0;
- h = num;
- while (l < h) {
- i = (l + h) / 2;
- p = &(base[i * size]);
- c = (*cmp) (key, p);
- if (c < 0)
- h = i;
- else if (c > 0)
- l = i + 1;
- else
- break;
- }
#ifdef CHARSET_EBCDIC
/*
* THIS IS A KLUDGE - Because the *_obj is sorted in ASCII order, and I
* don't have perl (yet), we revert to a *LINEAR* search when the object
* wasn't found in the binary search.
*/
- if (c != 0) {
+ if (p == NULL) {
+ const char *base_ = base;
+ int l, h, i = 0, c = 0;
+
for (i = 0; i < num; ++i) {
- p = &(base[i * size]);
+ p = &(base_[i * size]);
c = (*cmp) (key, p);
- if (c == 0 || (c < 0 && (flags & OBJ_BSEARCH_VALUE_ON_NOMATCH)))
+ if (c == 0
+ || (c < 0 && (flags & OBJ_BSEARCH_VALUE_ON_NOMATCH)))
return p;
}
}
#endif
- if (c != 0 && !(flags & OBJ_BSEARCH_VALUE_ON_NOMATCH))
- p = NULL;
- else if (c == 0 && (flags & OBJ_BSEARCH_FIRST_VALUE_ON_MATCH)) {
- while (i > 0 && (*cmp) (key, &(base[(i - 1) * size])) == 0)
- i--;
- p = &(base[i * size]);
- }
return p;
}
@@ -696,7 +697,7 @@ int OBJ_create(const char *oid, const char *sn, const char *ln)
/* Check to see if short or long name already present */
if ((sn != NULL && OBJ_sn2nid(sn) != NID_undef)
|| (ln != NULL && OBJ_ln2nid(ln) != NID_undef)) {
- OBJerr(OBJ_F_OBJ_CREATE, OBJ_R_OID_EXISTS);
+ ERR_raise(ERR_LIB_OBJ, OBJ_R_OID_EXISTS);
return 0;
}
@@ -707,11 +708,14 @@ int OBJ_create(const char *oid, const char *sn, const char *ln)
/* If NID is not NID_undef then object already exists */
if (OBJ_obj2nid(tmpoid) != NID_undef) {
- OBJerr(OBJ_F_OBJ_CREATE, OBJ_R_OID_EXISTS);
+ ERR_raise(ERR_LIB_OBJ, OBJ_R_OID_EXISTS);
goto err;
}
tmpoid->nid = OBJ_new_nid(1);
+ if (tmpoid->nid == NID_undef)
+ goto err;
+
tmpoid->sn = (char *)sn;
tmpoid->ln = (char *)ln;
diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
index 63bf69e4437d..59d156117a00 100644
--- a/crypto/objects/obj_dat.h
+++ b/crypto/objects/obj_dat.h
@@ -3,14 +3,14 @@
* Generated by crypto/objects/obj_dat.pl
*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Serialized OID's */
-static const unsigned char so[7762] = {
+static const unsigned char so[8076] = {
0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 6] OBJ_pkcs */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02, /* [ 13] OBJ_md2 */
@@ -1061,24 +1061,63 @@ static const unsigned char so[7762] = {
0x2B,0x6F,0x02,0x8C,0x53, /* [ 7612] OBJ_ieee_siswg */
0x2A,0x81,0x1C,0xCF,0x55,0x01,0x82,0x2D, /* [ 7617] OBJ_sm2 */
0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x01, /* [ 7625] OBJ_id_tc26_cipher_gostr3412_2015_magma */
- 0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x01,0x01, /* [ 7633] OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm */
- 0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x01,0x02, /* [ 7642] OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac */
+ 0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x01,0x01, /* [ 7633] OBJ_magma_ctr_acpkm */
+ 0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x01,0x02, /* [ 7642] OBJ_magma_ctr_acpkm_omac */
0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x02, /* [ 7651] OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik */
- 0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x02,0x01, /* [ 7659] OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm */
- 0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x02,0x02, /* [ 7668] OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac */
+ 0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x02,0x01, /* [ 7659] OBJ_kuznyechik_ctr_acpkm */
+ 0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x02,0x02, /* [ 7668] OBJ_kuznyechik_ctr_acpkm_omac */
0x2A,0x85,0x03,0x07,0x01,0x01,0x07, /* [ 7677] OBJ_id_tc26_wrap */
0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01, /* [ 7684] OBJ_id_tc26_wrap_gostr3412_2015_magma */
- 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01,0x01, /* [ 7692] OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 */
+ 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01,0x01, /* [ 7692] OBJ_magma_kexp15 */
0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x02, /* [ 7701] OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik */
- 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x02,0x01, /* [ 7709] OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 */
+ 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x02,0x01, /* [ 7709] OBJ_kuznyechik_kexp15 */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x02, /* [ 7718] OBJ_id_tc26_gost_3410_2012_256_paramSetB */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x03, /* [ 7727] OBJ_id_tc26_gost_3410_2012_256_paramSetC */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x04, /* [ 7736] OBJ_id_tc26_gost_3410_2012_256_paramSetD */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0C, /* [ 7745] OBJ_hmacWithSHA512_224 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0D, /* [ 7753] OBJ_hmacWithSHA512_256 */
+ 0x28,0xCC,0x45,0x03,0x04, /* [ 7761] OBJ_gmac */
+ 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x13, /* [ 7766] OBJ_kmac128 */
+ 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x14, /* [ 7775] OBJ_kmac256 */
+ 0x2B,0x06,0x01,0x04,0x01,0x8D,0x3A,0x0C,0x02,0x01, /* [ 7784] OBJ_blake2bmac */
+ 0x2B,0x06,0x01,0x04,0x01,0x8D,0x3A,0x0C,0x02,0x02, /* [ 7794] OBJ_blake2smac */
+ 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x75, /* [ 7804] OBJ_SM2_with_SM3 */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x08,0x09, /* [ 7812] OBJ_id_on_SmtpUTF8Mailbox */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x08,0x05, /* [ 7820] OBJ_XmppAddr */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x08,0x07, /* [ 7828] OBJ_SRVName */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x08,0x08, /* [ 7836] OBJ_NAIRealm */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x1D, /* [ 7844] OBJ_cmcArchive */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x1E, /* [ 7852] OBJ_id_kp_bgpsec_router */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x1F, /* [ 7860] OBJ_id_kp_BrandIndicatorforMessageIdentification */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x20, /* [ 7868] OBJ_cmKGA */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x11, /* [ 7876] OBJ_id_it_caCerts */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x12, /* [ 7884] OBJ_id_it_rootCaKeyUpdate */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x13, /* [ 7892] OBJ_id_it_certReqTemplate */
+ 0x2A,0x85,0x03,0x64,0x05, /* [ 7900] OBJ_OGRNIP */
+ 0x2A,0x85,0x03,0x64,0x71, /* [ 7905] OBJ_classSignTool */
+ 0x2A,0x85,0x03,0x64,0x71,0x01, /* [ 7910] OBJ_classSignToolKC1 */
+ 0x2A,0x85,0x03,0x64,0x71,0x02, /* [ 7916] OBJ_classSignToolKC2 */
+ 0x2A,0x85,0x03,0x64,0x71,0x03, /* [ 7922] OBJ_classSignToolKC3 */
+ 0x2A,0x85,0x03,0x64,0x71,0x04, /* [ 7928] OBJ_classSignToolKB1 */
+ 0x2A,0x85,0x03,0x64,0x71,0x05, /* [ 7934] OBJ_classSignToolKB2 */
+ 0x2A,0x85,0x03,0x64,0x71,0x06, /* [ 7940] OBJ_classSignToolKA1 */
+ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x18, /* [ 7946] OBJ_id_ct_routeOriginAuthz */
+ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x1A, /* [ 7957] OBJ_id_ct_rpkiManifest */
+ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x23, /* [ 7968] OBJ_id_ct_rpkiGhostbusters */
+ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x24, /* [ 7979] OBJ_id_ct_resourceTaggedAttest */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x0E, /* [ 7990] OBJ_id_cp */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x1C, /* [ 7997] OBJ_sbgp_ipAddrBlockv2 */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x1D, /* [ 8005] OBJ_sbgp_autonomousSysNumv2 */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x0E,0x02, /* [ 8013] OBJ_ipAddr_asNumber */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x0E,0x03, /* [ 8021] OBJ_ipAddr_asNumberv2 */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x0A, /* [ 8029] OBJ_rpkiManifest */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x0B, /* [ 8037] OBJ_signedObject */
+ 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x0D, /* [ 8045] OBJ_rpkiNotify */
+ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x2F, /* [ 8053] OBJ_id_ct_geofeedCSVwithCRLF */
+ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x30, /* [ 8064] OBJ_id_ct_signedChecklist */
};
-#define NUM_NID 1195
+#define NUM_NID 1248
static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"UNDEF", "undefined", NID_undef},
{"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]},
@@ -2092,12 +2131,12 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"gost89-cbc", "gost89-cbc", NID_gost89_cbc},
{"gost89-ecb", "gost89-ecb", NID_gost89_ecb},
{"gost89-ctr", "gost89-ctr", NID_gost89_ctr},
- {"grasshopper-ecb", "grasshopper-ecb", NID_grasshopper_ecb},
- {"grasshopper-ctr", "grasshopper-ctr", NID_grasshopper_ctr},
- {"grasshopper-ofb", "grasshopper-ofb", NID_grasshopper_ofb},
- {"grasshopper-cbc", "grasshopper-cbc", NID_grasshopper_cbc},
- {"grasshopper-cfb", "grasshopper-cfb", NID_grasshopper_cfb},
- {"grasshopper-mac", "grasshopper-mac", NID_grasshopper_mac},
+ {"kuznyechik-ecb", "kuznyechik-ecb", NID_kuznyechik_ecb},
+ {"kuznyechik-ctr", "kuznyechik-ctr", NID_kuznyechik_ctr},
+ {"kuznyechik-ofb", "kuznyechik-ofb", NID_kuznyechik_ofb},
+ {"kuznyechik-cbc", "kuznyechik-cbc", NID_kuznyechik_cbc},
+ {"kuznyechik-cfb", "kuznyechik-cfb", NID_kuznyechik_cfb},
+ {"kuznyechik-mac", "kuznyechik-mac", NID_kuznyechik_mac},
{"ChaCha20-Poly1305", "chacha20-poly1305", NID_chacha20_poly1305},
{"ChaCha20", "chacha20", NID_chacha20},
{"tlsfeature", "TLS Feature", NID_tlsfeature, 8, &so[6619]},
@@ -2254,16 +2293,16 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"ieee-siswg", "IEEE Security in Storage Working Group", NID_ieee_siswg, 5, &so[7612]},
{"SM2", "sm2", NID_sm2, 8, &so[7617]},
{"id-tc26-cipher-gostr3412-2015-magma", "id-tc26-cipher-gostr3412-2015-magma", NID_id_tc26_cipher_gostr3412_2015_magma, 8, &so[7625]},
- {"id-tc26-cipher-gostr3412-2015-magma-ctracpkm", "id-tc26-cipher-gostr3412-2015-magma-ctracpkm", NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm, 9, &so[7633]},
- {"id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac", "id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac", NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac, 9, &so[7642]},
+ {"magma-ctr-acpkm", "magma-ctr-acpkm", NID_magma_ctr_acpkm, 9, &so[7633]},
+ {"magma-ctr-acpkm-omac", "magma-ctr-acpkm-omac", NID_magma_ctr_acpkm_omac, 9, &so[7642]},
{"id-tc26-cipher-gostr3412-2015-kuznyechik", "id-tc26-cipher-gostr3412-2015-kuznyechik", NID_id_tc26_cipher_gostr3412_2015_kuznyechik, 8, &so[7651]},
- {"id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm", "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm", NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm, 9, &so[7659]},
- {"id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac", "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac", NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac, 9, &so[7668]},
+ {"kuznyechik-ctr-acpkm", "kuznyechik-ctr-acpkm", NID_kuznyechik_ctr_acpkm, 9, &so[7659]},
+ {"kuznyechik-ctr-acpkm-omac", "kuznyechik-ctr-acpkm-omac", NID_kuznyechik_ctr_acpkm_omac, 9, &so[7668]},
{"id-tc26-wrap", "id-tc26-wrap", NID_id_tc26_wrap, 7, &so[7677]},
{"id-tc26-wrap-gostr3412-2015-magma", "id-tc26-wrap-gostr3412-2015-magma", NID_id_tc26_wrap_gostr3412_2015_magma, 8, &so[7684]},
- {"id-tc26-wrap-gostr3412-2015-magma-kexp15", "id-tc26-wrap-gostr3412-2015-magma-kexp15", NID_id_tc26_wrap_gostr3412_2015_magma_kexp15, 9, &so[7692]},
+ {"magma-kexp15", "magma-kexp15", NID_magma_kexp15, 9, &so[7692]},
{"id-tc26-wrap-gostr3412-2015-kuznyechik", "id-tc26-wrap-gostr3412-2015-kuznyechik", NID_id_tc26_wrap_gostr3412_2015_kuznyechik, 8, &so[7701]},
- {"id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15", "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15", NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15, 9, &so[7709]},
+ {"kuznyechik-kexp15", "kuznyechik-kexp15", NID_kuznyechik_kexp15, 9, &so[7709]},
{"id-tc26-gost-3410-2012-256-paramSetB", "GOST R 34.10-2012 (256 bit) ParamSet B", NID_id_tc26_gost_3410_2012_256_paramSetB, 9, &so[7718]},
{"id-tc26-gost-3410-2012-256-paramSetC", "GOST R 34.10-2012 (256 bit) ParamSet C", NID_id_tc26_gost_3410_2012_256_paramSetC, 9, &so[7727]},
{"id-tc26-gost-3410-2012-256-paramSetD", "GOST R 34.10-2012 (256 bit) ParamSet D", NID_id_tc26_gost_3410_2012_256_paramSetD, 9, &so[7736]},
@@ -2275,9 +2314,62 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"magma-mac", "magma-mac", NID_magma_mac},
{"hmacWithSHA512-224", "hmacWithSHA512-224", NID_hmacWithSHA512_224, 8, &so[7745]},
{"hmacWithSHA512-256", "hmacWithSHA512-256", NID_hmacWithSHA512_256, 8, &so[7753]},
+ {"GMAC", "gmac", NID_gmac, 5, &so[7761]},
+ {"KMAC128", "kmac128", NID_kmac128, 9, &so[7766]},
+ {"KMAC256", "kmac256", NID_kmac256, 9, &so[7775]},
+ {"AES-128-SIV", "aes-128-siv", NID_aes_128_siv},
+ {"AES-192-SIV", "aes-192-siv", NID_aes_192_siv},
+ {"AES-256-SIV", "aes-256-siv", NID_aes_256_siv},
+ {"BLAKE2BMAC", "blake2bmac", NID_blake2bmac, 10, &so[7784]},
+ {"BLAKE2SMAC", "blake2smac", NID_blake2smac, 10, &so[7794]},
+ {"SSHKDF", "sshkdf", NID_sshkdf},
+ {"SM2-SM3", "SM2-with-SM3", NID_SM2_with_SM3, 8, &so[7804]},
+ {"SSKDF", "sskdf", NID_sskdf},
+ {"X963KDF", "x963kdf", NID_x963kdf},
+ {"X942KDF", "x942kdf", NID_x942kdf},
+ {"id-on-SmtpUTF8Mailbox", "Smtp UTF8 Mailbox", NID_id_on_SmtpUTF8Mailbox, 8, &so[7812]},
+ {"id-on-xmppAddr", "XmppAddr", NID_XmppAddr, 8, &so[7820]},
+ {"id-on-dnsSRV", "SRVName", NID_SRVName, 8, &so[7828]},
+ {"id-on-NAIRealm", "NAIRealm", NID_NAIRealm, 8, &so[7836]},
+ {"modp_1536", "modp_1536", NID_modp_1536},
+ {"modp_2048", "modp_2048", NID_modp_2048},
+ {"modp_3072", "modp_3072", NID_modp_3072},
+ {"modp_4096", "modp_4096", NID_modp_4096},
+ {"modp_6144", "modp_6144", NID_modp_6144},
+ {"modp_8192", "modp_8192", NID_modp_8192},
+ {"KxGOST18", "kx-gost18", NID_kx_gost18},
+ {"cmcArchive", "CMC Archive Server", NID_cmcArchive, 8, &so[7844]},
+ {"id-kp-bgpsec-router", "BGPsec Router", NID_id_kp_bgpsec_router, 8, &so[7852]},
+ {"id-kp-BrandIndicatorforMessageIdentification", "Brand Indicator for Message Identification", NID_id_kp_BrandIndicatorforMessageIdentification, 8, &so[7860]},
+ {"cmKGA", "Certificate Management Key Generation Authority", NID_cmKGA, 8, &so[7868]},
+ {"id-it-caCerts", "id-it-caCerts", NID_id_it_caCerts, 8, &so[7876]},
+ {"id-it-rootCaKeyUpdate", "id-it-rootCaKeyUpdate", NID_id_it_rootCaKeyUpdate, 8, &so[7884]},
+ {"id-it-certReqTemplate", "id-it-certReqTemplate", NID_id_it_certReqTemplate, 8, &so[7892]},
+ {"OGRNIP", "OGRNIP", NID_OGRNIP, 5, &so[7900]},
+ {"classSignTool", "Class of Signing Tool", NID_classSignTool, 5, &so[7905]},
+ {"classSignToolKC1", "Class of Signing Tool KC1", NID_classSignToolKC1, 6, &so[7910]},
+ {"classSignToolKC2", "Class of Signing Tool KC2", NID_classSignToolKC2, 6, &so[7916]},
+ {"classSignToolKC3", "Class of Signing Tool KC3", NID_classSignToolKC3, 6, &so[7922]},
+ {"classSignToolKB1", "Class of Signing Tool KB1", NID_classSignToolKB1, 6, &so[7928]},
+ {"classSignToolKB2", "Class of Signing Tool KB2", NID_classSignToolKB2, 6, &so[7934]},
+ {"classSignToolKA1", "Class of Signing Tool KA1", NID_classSignToolKA1, 6, &so[7940]},
+ {"id-ct-routeOriginAuthz", "id-ct-routeOriginAuthz", NID_id_ct_routeOriginAuthz, 11, &so[7946]},
+ {"id-ct-rpkiManifest", "id-ct-rpkiManifest", NID_id_ct_rpkiManifest, 11, &so[7957]},
+ {"id-ct-rpkiGhostbusters", "id-ct-rpkiGhostbusters", NID_id_ct_rpkiGhostbusters, 11, &so[7968]},
+ {"id-ct-resourceTaggedAttest", "id-ct-resourceTaggedAttest", NID_id_ct_resourceTaggedAttest, 11, &so[7979]},
+ {"id-cp", "id-cp", NID_id_cp, 7, &so[7990]},
+ {"sbgp-ipAddrBlockv2", "sbgp-ipAddrBlockv2", NID_sbgp_ipAddrBlockv2, 8, &so[7997]},
+ {"sbgp-autonomousSysNumv2", "sbgp-autonomousSysNumv2", NID_sbgp_autonomousSysNumv2, 8, &so[8005]},
+ {"ipAddr-asNumber", "ipAddr-asNumber", NID_ipAddr_asNumber, 8, &so[8013]},
+ {"ipAddr-asNumberv2", "ipAddr-asNumberv2", NID_ipAddr_asNumberv2, 8, &so[8021]},
+ {"rpkiManifest", "RPKI Manifest", NID_rpkiManifest, 8, &so[8029]},
+ {"signedObject", "Signed Object", NID_signedObject, 8, &so[8037]},
+ {"rpkiNotify", "RPKI Notify", NID_rpkiNotify, 8, &so[8045]},
+ {"id-ct-geofeedCSVwithCRLF", "id-ct-geofeedCSVwithCRLF", NID_id_ct_geofeedCSVwithCRLF, 11, &so[8053]},
+ {"id-ct-signedChecklist", "id-ct-signedChecklist", NID_id_ct_signedChecklist, 11, &so[8064]},
};
-#define NUM_SN 1186
+#define NUM_SN 1239
static const unsigned int sn_objs[NUM_SN] = {
364, /* "AD_DVCS" */
419, /* "AES-128-CBC" */
@@ -2290,6 +2382,7 @@ static const unsigned int sn_objs[NUM_SN] = {
418, /* "AES-128-ECB" */
958, /* "AES-128-OCB" */
420, /* "AES-128-OFB" */
+ 1198, /* "AES-128-SIV" */
913, /* "AES-128-XTS" */
423, /* "AES-192-CBC" */
917, /* "AES-192-CBC-HMAC-SHA1" */
@@ -2301,6 +2394,7 @@ static const unsigned int sn_objs[NUM_SN] = {
422, /* "AES-192-ECB" */
959, /* "AES-192-OCB" */
424, /* "AES-192-OFB" */
+ 1199, /* "AES-192-SIV" */
427, /* "AES-256-CBC" */
918, /* "AES-256-CBC-HMAC-SHA1" */
950, /* "AES-256-CBC-HMAC-SHA256" */
@@ -2311,6 +2405,7 @@ static const unsigned int sn_objs[NUM_SN] = {
426, /* "AES-256-ECB" */
960, /* "AES-256-OCB" */
428, /* "AES-256-OFB" */
+ 1200, /* "AES-256-SIV" */
914, /* "AES-256-XTS" */
1066, /* "ARIA-128-CBC" */
1120, /* "ARIA-128-CCM" */
@@ -2352,6 +2447,8 @@ static const unsigned int sn_objs[NUM_SN] = {
93, /* "BF-CFB" */
92, /* "BF-ECB" */
94, /* "BF-OFB" */
+ 1201, /* "BLAKE2BMAC" */
+ 1202, /* "BLAKE2SMAC" */
1056, /* "BLAKE2b512" */
1057, /* "BLAKE2s256" */
14, /* "C" */
@@ -2424,6 +2521,7 @@ static const unsigned int sn_objs[NUM_SN] = {
297, /* "DVCS" */
1087, /* "ED25519" */
1088, /* "ED448" */
+ 1195, /* "GMAC" */
99, /* "GN" */
1036, /* "HKDF" */
855, /* "HMAC" */
@@ -2442,12 +2540,15 @@ static const unsigned int sn_objs[NUM_SN] = {
645, /* "ITU-T" */
646, /* "JOINT-ISO-ITU-T" */
773, /* "KISA" */
+ 1196, /* "KMAC128" */
+ 1197, /* "KMAC256" */
1063, /* "KxANY" */
1039, /* "KxDHE" */
1041, /* "KxDHE-PSK" */
1038, /* "KxECDHE" */
1040, /* "KxECDHE-PSK" */
1045, /* "KxGOST" */
+ 1218, /* "KxGOST18" */
1043, /* "KxPSK" */
1037, /* "KxRSA" */
1042, /* "KxRSA_PSK" */
@@ -2469,6 +2570,7 @@ static const unsigned int sn_objs[NUM_SN] = {
178, /* "OCSP" */
180, /* "OCSPSigning" */
1005, /* "OGRN" */
+ 1226, /* "OGRNIP" */
379, /* "ORG" */
18, /* "OU" */
749, /* "Oakley-EC2N-3" */
@@ -2543,6 +2645,7 @@ static const unsigned int sn_objs[NUM_SN] = {
1100, /* "SHAKE128" */
1101, /* "SHAKE256" */
1172, /* "SM2" */
+ 1204, /* "SM2-SM3" */
1143, /* "SM3" */
1134, /* "SM4-CBC" */
1137, /* "SM4-CFB" */
@@ -2555,6 +2658,8 @@ static const unsigned int sn_objs[NUM_SN] = {
167, /* "SMIME-CAPS" */
100, /* "SN" */
1006, /* "SNILS" */
+ 1203, /* "SSHKDF" */
+ 1205, /* "SSKDF" */
16, /* "ST" */
143, /* "SXNetID" */
1062, /* "SipHash" */
@@ -2567,6 +2672,8 @@ static const unsigned int sn_objs[NUM_SN] = {
378, /* "X500algorithms" */
12, /* "X509" */
184, /* "X9-57" */
+ 1207, /* "X942KDF" */
+ 1206, /* "X963KDF" */
185, /* "X9cm" */
125, /* "ZLIB" */
478, /* "aRecord" */
@@ -2642,8 +2749,17 @@ static const unsigned int sn_objs[NUM_SN] = {
883, /* "certificateRevocationList" */
54, /* "challengePassword" */
407, /* "characteristic-two-field" */
+ 1227, /* "classSignTool" */
+ 1233, /* "classSignToolKA1" */
+ 1231, /* "classSignToolKB1" */
+ 1232, /* "classSignToolKB2" */
+ 1228, /* "classSignToolKC1" */
+ 1229, /* "classSignToolKC2" */
+ 1230, /* "classSignToolKC3" */
395, /* "clearance" */
130, /* "clientAuth" */
+ 1222, /* "cmKGA" */
+ 1219, /* "cmcArchive" */
1131, /* "cmcCA" */
1132, /* "cmcRA" */
131, /* "codeSigning" */
@@ -2748,12 +2864,6 @@ static const unsigned int sn_objs[NUM_SN] = {
1010, /* "gost89-ecb" */
812, /* "gost94" */
850, /* "gost94cc" */
- 1015, /* "grasshopper-cbc" */
- 1016, /* "grasshopper-cfb" */
- 1013, /* "grasshopper-ctr" */
- 1012, /* "grasshopper-ecb" */
- 1017, /* "grasshopper-mac" */
- 1014, /* "grasshopper-ofb" */
1156, /* "hmacWithDstu34311" */
797, /* "hmacWithMD5" */
163, /* "hmacWithSHA1" */
@@ -2869,7 +2979,14 @@ static const unsigned int sn_objs[NUM_SN] = {
332, /* "id-cmc-senderNonce" */
327, /* "id-cmc-statusInfo" */
331, /* "id-cmc-transactionId" */
+ 1238, /* "id-cp" */
787, /* "id-ct-asciiTextWithCRLF" */
+ 1246, /* "id-ct-geofeedCSVwithCRLF" */
+ 1237, /* "id-ct-resourceTaggedAttest" */
+ 1234, /* "id-ct-routeOriginAuthz" */
+ 1236, /* "id-ct-rpkiGhostbusters" */
+ 1235, /* "id-ct-rpkiManifest" */
+ 1247, /* "id-ct-signedChecklist" */
1060, /* "id-ct-xml" */
1108, /* "id-dsa-with-sha3-224" */
1109, /* "id-dsa-with-sha3-256" */
@@ -2889,8 +3006,10 @@ static const unsigned int sn_objs[NUM_SN] = {
1104, /* "id-hmacWithSHA3-384" */
1105, /* "id-hmacWithSHA3-512" */
260, /* "id-it" */
+ 1223, /* "id-it-caCerts" */
302, /* "id-it-caKeyUpdateInfo" */
298, /* "id-it-caProtEncCert" */
+ 1225, /* "id-it-certReqTemplate" */
311, /* "id-it-confirmWaitTime" */
303, /* "id-it-currentCRL" */
300, /* "id-it-encKeyPairTypes" */
@@ -2900,12 +3019,15 @@ static const unsigned int sn_objs[NUM_SN] = {
312, /* "id-it-origPKIMessage" */
301, /* "id-it-preferredSymmAlg" */
309, /* "id-it-revPassphrase" */
+ 1224, /* "id-it-rootCaKeyUpdate" */
299, /* "id-it-signKeyPairTypes" */
305, /* "id-it-subscriptionRequest" */
306, /* "id-it-subscriptionResponse" */
784, /* "id-it-suppLangTags" */
304, /* "id-it-unsupportedOIDs" */
128, /* "id-kp" */
+ 1221, /* "id-kp-BrandIndicatorforMessageIdentification" */
+ 1220, /* "id-kp-bgpsec-router" */
280, /* "id-mod-attribute-cert" */
274, /* "id-mod-cmc" */
277, /* "id-mod-cmp" */
@@ -2919,8 +3041,12 @@ static const unsigned int sn_objs[NUM_SN] = {
279, /* "id-mod-qualified-cert-93" */
281, /* "id-mod-timestamp-protocol" */
264, /* "id-on" */
+ 1211, /* "id-on-NAIRealm" */
+ 1208, /* "id-on-SmtpUTF8Mailbox" */
+ 1210, /* "id-on-dnsSRV" */
858, /* "id-on-permanentIdentifier" */
347, /* "id-on-personalData" */
+ 1209, /* "id-on-xmppAddr" */
265, /* "id-pda" */
352, /* "id-pda-countryOfCitizenship" */
353, /* "id-pda-countryOfResidence" */
@@ -3040,11 +3166,7 @@ static const unsigned int sn_objs[NUM_SN] = {
990, /* "id-tc26-cipher" */
1001, /* "id-tc26-cipher-constants" */
1176, /* "id-tc26-cipher-gostr3412-2015-kuznyechik" */
- 1177, /* "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm" */
- 1178, /* "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac" */
1173, /* "id-tc26-cipher-gostr3412-2015-magma" */
- 1174, /* "id-tc26-cipher-gostr3412-2015-magma-ctracpkm" */
- 1175, /* "id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac" */
994, /* "id-tc26-constants" */
981, /* "id-tc26-digest" */
1000, /* "id-tc26-digest-constants" */
@@ -3070,9 +3192,7 @@ static const unsigned int sn_objs[NUM_SN] = {
986, /* "id-tc26-signwithdigest-gost3410-2012-512" */
1179, /* "id-tc26-wrap" */
1182, /* "id-tc26-wrap-gostr3412-2015-kuznyechik" */
- 1183, /* "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15" */
1180, /* "id-tc26-wrap-gostr3412-2015-magma" */
- 1181, /* "id-tc26-wrap-gostr3412-2015-magma-kexp15" */
676, /* "identified-organization" */
1170, /* "ieee" */
1171, /* "ieee-siswg" */
@@ -3082,6 +3202,8 @@ static const unsigned int sn_objs[NUM_SN] = {
647, /* "international-organizations" */
869, /* "internationaliSDNNumber" */
142, /* "invalidityDate" */
+ 1241, /* "ipAddr-asNumber" */
+ 1242, /* "ipAddr-asNumberv2" */
294, /* "ipsecEndSystem" */
1022, /* "ipsecIKE" */
295, /* "ipsecTunnel" */
@@ -3095,6 +3217,15 @@ static const unsigned int sn_objs[NUM_SN] = {
956, /* "jurisdictionST" */
150, /* "keyBag" */
83, /* "keyUsage" */
+ 1015, /* "kuznyechik-cbc" */
+ 1016, /* "kuznyechik-cfb" */
+ 1013, /* "kuznyechik-ctr" */
+ 1177, /* "kuznyechik-ctr-acpkm" */
+ 1178, /* "kuznyechik-ctr-acpkm-omac" */
+ 1012, /* "kuznyechik-ecb" */
+ 1183, /* "kuznyechik-kexp15" */
+ 1017, /* "kuznyechik-mac" */
+ 1014, /* "kuznyechik-ofb" */
477, /* "lastModifiedBy" */
476, /* "lastModifiedTime" */
157, /* "localKeyID" */
@@ -3102,7 +3233,10 @@ static const unsigned int sn_objs[NUM_SN] = {
1190, /* "magma-cbc" */
1191, /* "magma-cfb" */
1188, /* "magma-ctr" */
+ 1174, /* "magma-ctr-acpkm" */
+ 1175, /* "magma-ctr-acpkm-omac" */
1187, /* "magma-ecb" */
+ 1181, /* "magma-kexp15" */
1192, /* "magma-mac" */
1189, /* "magma-ofb" */
460, /* "mail" */
@@ -3119,6 +3253,12 @@ static const unsigned int sn_objs[NUM_SN] = {
506, /* "mime-mhs-bodies" */
505, /* "mime-mhs-headings" */
488, /* "mobileTelephoneNumber" */
+ 1212, /* "modp_1536" */
+ 1213, /* "modp_2048" */
+ 1214, /* "modp_3072" */
+ 1215, /* "modp_4096" */
+ 1216, /* "modp_6144" */
+ 1217, /* "modp_8192" */
136, /* "msCTLSign" */
135, /* "msCodeCom" */
134, /* "msCodeInd" */
@@ -3214,6 +3354,8 @@ static const unsigned int sn_objs[NUM_SN] = {
877, /* "roleOccupant" */
448, /* "room" */
463, /* "roomNumber" */
+ 1243, /* "rpkiManifest" */
+ 1245, /* "rpkiNotify" */
6, /* "rsaEncryption" */
644, /* "rsaOAEPEncryptionSET" */
377, /* "rsaSignature" */
@@ -3221,7 +3363,9 @@ static const unsigned int sn_objs[NUM_SN] = {
482, /* "sOARecord" */
155, /* "safeContentsBag" */
291, /* "sbgp-autonomousSysNum" */
+ 1240, /* "sbgp-autonomousSysNumv2" */
290, /* "sbgp-ipAddrBlock" */
+ 1239, /* "sbgp-ipAddrBlockv2" */
292, /* "sbgp-routerIdentifier" */
159, /* "sdsiCertificate" */
859, /* "searchGuide" */
@@ -3400,6 +3544,7 @@ static const unsigned int sn_objs[NUM_SN] = {
604, /* "setext-pinAny" */
603, /* "setext-pinSecure" */
605, /* "setext-track2" */
+ 1244, /* "signedObject" */
52, /* "signingTime" */
454, /* "simpleSecurityObject" */
496, /* "singleLevelQuality" */
@@ -3467,7 +3612,7 @@ static const unsigned int sn_objs[NUM_SN] = {
1093, /* "x509ExtAdmission" */
};
-#define NUM_LN 1186
+#define NUM_LN 1239
static const unsigned int ln_objs[NUM_LN] = {
363, /* "AD Time Stamping" */
405, /* "ANSI X9.62" */
@@ -3475,16 +3620,27 @@ static const unsigned int ln_objs[NUM_LN] = {
910, /* "Any Extended Key Usage" */
664, /* "Any language" */
177, /* "Authority Information Access" */
+ 1220, /* "BGPsec Router" */
365, /* "Basic OCSP Response" */
285, /* "Biometric Info" */
+ 1221, /* "Brand Indicator for Message Identification" */
179, /* "CA Issuers" */
785, /* "CA Repository" */
+ 1219, /* "CMC Archive Server" */
1131, /* "CMC Certificate Authority" */
1132, /* "CMC Registration Authority" */
954, /* "CT Certificate SCTs" */
952, /* "CT Precertificate Poison" */
951, /* "CT Precertificate SCTs" */
953, /* "CT Precertificate Signer" */
+ 1222, /* "Certificate Management Key Generation Authority" */
+ 1227, /* "Class of Signing Tool" */
+ 1233, /* "Class of Signing Tool KA1" */
+ 1231, /* "Class of Signing Tool KB1" */
+ 1232, /* "Class of Signing Tool KB2" */
+ 1228, /* "Class of Signing Tool KC1" */
+ 1229, /* "Class of Signing Tool KC2" */
+ 1230, /* "Class of Signing Tool KC3" */
131, /* "Code Signing" */
1024, /* "Ctrl/Provision WAP Termination" */
1023, /* "Ctrl/provision WAP Access" */
@@ -3581,6 +3737,7 @@ static const unsigned int ln_objs[NUM_LN] = {
648, /* "Microsoft Smartcard Login" */
136, /* "Microsoft Trust List Signing" */
649, /* "Microsoft User Principal Name" */
+ 1211, /* "NAIRealm" */
393, /* "NULL" */
404, /* "NULL" */
72, /* "Netscape Base Url" */
@@ -3604,6 +3761,7 @@ static const unsigned int ln_objs[NUM_LN] = {
371, /* "OCSP Service Locator" */
180, /* "OCSP Signing" */
1005, /* "OGRN" */
+ 1226, /* "OGRNIP" */
161, /* "PBES2" */
69, /* "PBKDF2" */
162, /* "PBMAC1" */
@@ -3615,6 +3773,8 @@ static const unsigned int ln_objs[NUM_LN] = {
385, /* "Private" */
1093, /* "Professional Information or basis for Admission" */
663, /* "Proxy Certificate Information" */
+ 1243, /* "RPKI Manifest" */
+ 1245, /* "RPKI Notify" */
1, /* "RSA Data Security, Inc." */
2, /* "RSA Data Security, Inc. PKCS" */
1116, /* "RSA-SHA3-224" */
@@ -3623,8 +3783,10 @@ static const unsigned int ln_objs[NUM_LN] = {
1119, /* "RSA-SHA3-512" */
188, /* "S/MIME" */
167, /* "S/MIME Capabilities" */
+ 1204, /* "SM2-with-SM3" */
1006, /* "SNILS" */
387, /* "SNMPv2" */
+ 1210, /* "SRVName" */
1025, /* "SSH Client" */
1026, /* "SSH Server" */
512, /* "Secure Electronic Transactions" */
@@ -3634,9 +3796,11 @@ static const unsigned int ln_objs[NUM_LN] = {
1030, /* "Send Proxied Owner" */
1028, /* "Send Proxied Router" */
1027, /* "Send Router" */
+ 1244, /* "Signed Object" */
1033, /* "Signing KDC Response" */
1008, /* "Signing Tool of Issuer" */
1007, /* "Signing Tool of Subject" */
+ 1208, /* "Smtp UTF8 Mailbox" */
143, /* "Strong Extranet ID" */
398, /* "Subject Information Access" */
1020, /* "TLS Feature" */
@@ -3674,6 +3838,7 @@ static const unsigned int ln_objs[NUM_LN] = {
920, /* "X9.42 DH" */
184, /* "X9.57" */
185, /* "X9.57 CM ?" */
+ 1209, /* "XmppAddr" */
478, /* "aRecord" */
289, /* "aaControls" */
287, /* "ac-auditEntity" */
@@ -3694,6 +3859,7 @@ static const unsigned int ln_objs[NUM_LN] = {
895, /* "aes-128-gcm" */
958, /* "aes-128-ocb" */
420, /* "aes-128-ofb" */
+ 1198, /* "aes-128-siv" */
913, /* "aes-128-xts" */
423, /* "aes-192-cbc" */
917, /* "aes-192-cbc-hmac-sha1" */
@@ -3707,6 +3873,7 @@ static const unsigned int ln_objs[NUM_LN] = {
898, /* "aes-192-gcm" */
959, /* "aes-192-ocb" */
424, /* "aes-192-ofb" */
+ 1199, /* "aes-192-siv" */
427, /* "aes-256-cbc" */
918, /* "aes-256-cbc-hmac-sha1" */
950, /* "aes-256-cbc-hmac-sha256" */
@@ -3719,6 +3886,7 @@ static const unsigned int ln_objs[NUM_LN] = {
901, /* "aes-256-gcm" */
960, /* "aes-256-ocb" */
428, /* "aes-256-ofb" */
+ 1200, /* "aes-256-siv" */
914, /* "aes-256-xts" */
376, /* "algorithm" */
1066, /* "aria-128-cbc" */
@@ -3766,7 +3934,9 @@ static const unsigned int ln_objs[NUM_LN] = {
92, /* "bf-ecb" */
94, /* "bf-ofb" */
1056, /* "blake2b512" */
+ 1201, /* "blake2bmac" */
1057, /* "blake2s256" */
+ 1202, /* "blake2smac" */
921, /* "brainpoolP160r1" */
922, /* "brainpoolP160t1" */
923, /* "brainpoolP192r1" */
@@ -3961,18 +4131,13 @@ static const unsigned int ln_objs[NUM_LN] = {
509, /* "generationQualifier" */
601, /* "generic cryptogram" */
99, /* "givenName" */
+ 1195, /* "gmac" */
976, /* "gost-mac-12" */
1009, /* "gost89-cbc" */
814, /* "gost89-cnt" */
975, /* "gost89-cnt-12" */
1011, /* "gost89-ctr" */
1010, /* "gost89-ecb" */
- 1015, /* "grasshopper-cbc" */
- 1016, /* "grasshopper-cfb" */
- 1013, /* "grasshopper-ctr" */
- 1012, /* "grasshopper-ecb" */
- 1017, /* "grasshopper-mac" */
- 1014, /* "grasshopper-ofb" */
1036, /* "hkdf" */
855, /* "hmac" */
780, /* "hmac-md5" */
@@ -4075,14 +4240,23 @@ static const unsigned int ln_objs[NUM_LN] = {
332, /* "id-cmc-senderNonce" */
327, /* "id-cmc-statusInfo" */
331, /* "id-cmc-transactionId" */
+ 1238, /* "id-cp" */
787, /* "id-ct-asciiTextWithCRLF" */
+ 1246, /* "id-ct-geofeedCSVwithCRLF" */
+ 1237, /* "id-ct-resourceTaggedAttest" */
+ 1234, /* "id-ct-routeOriginAuthz" */
+ 1236, /* "id-ct-rpkiGhostbusters" */
+ 1235, /* "id-ct-rpkiManifest" */
+ 1247, /* "id-ct-signedChecklist" */
1060, /* "id-ct-xml" */
408, /* "id-ecPublicKey" */
508, /* "id-hex-multipart-message" */
507, /* "id-hex-partial-message" */
260, /* "id-it" */
+ 1223, /* "id-it-caCerts" */
302, /* "id-it-caKeyUpdateInfo" */
298, /* "id-it-caProtEncCert" */
+ 1225, /* "id-it-certReqTemplate" */
311, /* "id-it-confirmWaitTime" */
303, /* "id-it-currentCRL" */
300, /* "id-it-encKeyPairTypes" */
@@ -4092,6 +4266,7 @@ static const unsigned int ln_objs[NUM_LN] = {
312, /* "id-it-origPKIMessage" */
301, /* "id-it-preferredSymmAlg" */
309, /* "id-it-revPassphrase" */
+ 1224, /* "id-it-rootCaKeyUpdate" */
299, /* "id-it-signKeyPairTypes" */
305, /* "id-it-subscriptionRequest" */
306, /* "id-it-subscriptionResponse" */
@@ -4220,11 +4395,7 @@ static const unsigned int ln_objs[NUM_LN] = {
990, /* "id-tc26-cipher" */
1001, /* "id-tc26-cipher-constants" */
1176, /* "id-tc26-cipher-gostr3412-2015-kuznyechik" */
- 1177, /* "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm" */
- 1178, /* "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac" */
1173, /* "id-tc26-cipher-gostr3412-2015-magma" */
- 1174, /* "id-tc26-cipher-gostr3412-2015-magma-ctracpkm" */
- 1175, /* "id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac" */
994, /* "id-tc26-constants" */
981, /* "id-tc26-digest" */
1000, /* "id-tc26-digest-constants" */
@@ -4237,9 +4408,7 @@ static const unsigned int ln_objs[NUM_LN] = {
984, /* "id-tc26-signwithdigest" */
1179, /* "id-tc26-wrap" */
1182, /* "id-tc26-wrap-gostr3412-2015-kuznyechik" */
- 1183, /* "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15" */
1180, /* "id-tc26-wrap-gostr3412-2015-magma" */
- 1181, /* "id-tc26-wrap-gostr3412-2015-magma-kexp15" */
34, /* "idea-cbc" */
35, /* "idea-cfb" */
36, /* "idea-ecb" */
@@ -4249,6 +4418,8 @@ static const unsigned int ln_objs[NUM_LN] = {
461, /* "info" */
101, /* "initials" */
869, /* "internationaliSDNNumber" */
+ 1241, /* "ipAddr-asNumber" */
+ 1242, /* "ipAddr-asNumberv2" */
1022, /* "ipsec Internet Key Exchange" */
749, /* "ipsec3" */
750, /* "ipsec4" */
@@ -4262,12 +4433,24 @@ static const unsigned int ln_objs[NUM_LN] = {
956, /* "jurisdictionStateOrProvinceName" */
150, /* "keyBag" */
773, /* "kisa" */
+ 1196, /* "kmac128" */
+ 1197, /* "kmac256" */
+ 1015, /* "kuznyechik-cbc" */
+ 1016, /* "kuznyechik-cfb" */
+ 1013, /* "kuznyechik-ctr" */
+ 1177, /* "kuznyechik-ctr-acpkm" */
+ 1178, /* "kuznyechik-ctr-acpkm-omac" */
+ 1012, /* "kuznyechik-ecb" */
+ 1183, /* "kuznyechik-kexp15" */
+ 1017, /* "kuznyechik-mac" */
+ 1014, /* "kuznyechik-ofb" */
1063, /* "kx-any" */
1039, /* "kx-dhe" */
1041, /* "kx-dhe-psk" */
1038, /* "kx-ecdhe" */
1040, /* "kx-ecdhe-psk" */
1045, /* "kx-gost" */
+ 1218, /* "kx-gost18" */
1043, /* "kx-psk" */
1037, /* "kx-rsa" */
1042, /* "kx-rsa-psk" */
@@ -4280,7 +4463,10 @@ static const unsigned int ln_objs[NUM_LN] = {
1190, /* "magma-cbc" */
1191, /* "magma-cfb" */
1188, /* "magma-ctr" */
+ 1174, /* "magma-ctr-acpkm" */
+ 1175, /* "magma-ctr-acpkm-omac" */
1187, /* "magma-ecb" */
+ 1181, /* "magma-kexp15" */
1192, /* "magma-mac" */
1189, /* "magma-ofb" */
493, /* "mailPreferenceOption" */
@@ -4303,6 +4489,12 @@ static const unsigned int ln_objs[NUM_LN] = {
506, /* "mime-mhs-bodies" */
505, /* "mime-mhs-headings" */
488, /* "mobileTelephoneNumber" */
+ 1212, /* "modp_1536" */
+ 1213, /* "modp_2048" */
+ 1214, /* "modp_3072" */
+ 1215, /* "modp_4096" */
+ 1216, /* "modp_6144" */
+ 1217, /* "modp_8192" */
481, /* "nSRecord" */
173, /* "name" */
681, /* "onBasis" */
@@ -4409,7 +4601,9 @@ static const unsigned int ln_objs[NUM_LN] = {
482, /* "sOARecord" */
155, /* "safeContentsBag" */
291, /* "sbgp-autonomousSysNum" */
+ 1240, /* "sbgp-autonomousSysNumv2" */
290, /* "sbgp-ipAddrBlock" */
+ 1239, /* "sbgp-ipAddrBlockv2" */
292, /* "sbgp-routerIdentifier" */
973, /* "scrypt" */
159, /* "sdsiCertificate" */
@@ -4609,6 +4803,8 @@ static const unsigned int ln_objs[NUM_LN] = {
1139, /* "sm4-ctr" */
1133, /* "sm4-ecb" */
1135, /* "sm4-ofb" */
+ 1203, /* "sshkdf" */
+ 1205, /* "sskdf" */
16, /* "stateOrProvinceName" */
660, /* "streetAddress" */
498, /* "subtreeMaximumQuality" */
@@ -4654,10 +4850,12 @@ static const unsigned int ln_objs[NUM_LN] = {
503, /* "x500UniqueIdentifier" */
158, /* "x509Certificate" */
160, /* "x509Crl" */
+ 1207, /* "x942kdf" */
+ 1206, /* "x963kdf" */
125, /* "zlib compression" */
};
-#define NUM_OBJ 1071
+#define NUM_OBJ 1110
static const unsigned int obj_objs[NUM_OBJ] = {
0, /* OBJ_undef 0 */
181, /* OBJ_iso 1 */
@@ -4904,14 +5102,17 @@ static const unsigned int obj_objs[NUM_OBJ] = {
637, /* OBJ_set_brand_Diners 2 23 42 8 30 */
638, /* OBJ_set_brand_AmericanExpress 2 23 42 8 34 */
639, /* OBJ_set_brand_JCB 2 23 42 8 35 */
+ 1195, /* OBJ_gmac 1 0 9797 3 4 */
1141, /* OBJ_oscca 1 2 156 10197 */
805, /* OBJ_cryptopro 1 2 643 2 2 */
806, /* OBJ_cryptocom 1 2 643 2 9 */
974, /* OBJ_id_tc26 1 2 643 7 1 */
1005, /* OBJ_OGRN 1 2 643 100 1 */
1006, /* OBJ_SNILS 1 2 643 100 3 */
+ 1226, /* OBJ_OGRNIP 1 2 643 100 5 */
1007, /* OBJ_subjectSignTool 1 2 643 100 111 */
1008, /* OBJ_issuerSignTool 1 2 643 100 112 */
+ 1227, /* OBJ_classSignTool 1 2 643 100 113 */
184, /* OBJ_X9_57 1 2 840 10040 */
405, /* OBJ_ansi_X9_62 1 2 840 10045 */
389, /* OBJ_Enterprises 1 3 6 1 4 1 */
@@ -5000,6 +5201,12 @@ static const unsigned int obj_objs[NUM_OBJ] = {
818, /* OBJ_id_GostR3410_94DH 1 2 643 2 2 99 */
977, /* OBJ_id_tc26_algorithms 1 2 643 7 1 1 */
994, /* OBJ_id_tc26_constants 1 2 643 7 1 2 */
+ 1228, /* OBJ_classSignToolKC1 1 2 643 100 113 1 */
+ 1229, /* OBJ_classSignToolKC2 1 2 643 100 113 2 */
+ 1230, /* OBJ_classSignToolKC3 1 2 643 100 113 3 */
+ 1231, /* OBJ_classSignToolKB1 1 2 643 100 113 4 */
+ 1232, /* OBJ_classSignToolKB2 1 2 643 100 113 5 */
+ 1233, /* OBJ_classSignToolKA1 1 2 643 100 113 6 */
1, /* OBJ_rsadsi 1 2 840 113549 */
185, /* OBJ_X9cm 1 2 840 10040 4 */
1031, /* OBJ_id_pkinit 1 3 6 1 5 2 3 */
@@ -5090,6 +5297,7 @@ static const unsigned int obj_objs[NUM_OBJ] = {
266, /* OBJ_id_aca 1 3 6 1 5 5 7 10 */
267, /* OBJ_id_qcs 1 3 6 1 5 5 7 11 */
268, /* OBJ_id_cct 1 3 6 1 5 5 7 12 */
+ 1238, /* OBJ_id_cp 1 3 6 1 5 5 7 14 */
662, /* OBJ_id_ppl 1 3 6 1 5 5 7 21 */
176, /* OBJ_id_ad 1 3 6 1 5 5 7 48 */
507, /* OBJ_id_hex_partial_message 1 3 6 1 7 1 1 1 */
@@ -5126,6 +5334,7 @@ static const unsigned int obj_objs[NUM_OBJ] = {
1139, /* OBJ_sm4_ctr 1 2 156 10197 1 104 7 */
1172, /* OBJ_sm2 1 2 156 10197 1 301 */
1143, /* OBJ_sm3 1 2 156 10197 1 401 */
+ 1204, /* OBJ_SM2_with_SM3 1 2 156 10197 1 501 */
1144, /* OBJ_sm3WithRSAEncryption 1 2 156 10197 1 504 */
776, /* OBJ_seed_ecb 1 2 410 200004 1 3 */
777, /* OBJ_seed_cbc 1 2 410 200004 1 4 */
@@ -5237,6 +5446,8 @@ static const unsigned int obj_objs[NUM_OBJ] = {
398, /* OBJ_sinfo_access 1 3 6 1 5 5 7 1 11 */
663, /* OBJ_proxyCertInfo 1 3 6 1 5 5 7 1 14 */
1020, /* OBJ_tlsfeature 1 3 6 1 5 5 7 1 24 */
+ 1239, /* OBJ_sbgp_ipAddrBlockv2 1 3 6 1 5 5 7 1 28 */
+ 1240, /* OBJ_sbgp_autonomousSysNumv2 1 3 6 1 5 5 7 1 29 */
164, /* OBJ_id_qt_cps 1 3 6 1 5 5 7 2 1 */
165, /* OBJ_id_qt_unotice 1 3 6 1 5 5 7 2 2 */
293, /* OBJ_textNotice 1 3 6 1 5 5 7 2 3 */
@@ -5261,6 +5472,10 @@ static const unsigned int obj_objs[NUM_OBJ] = {
1030, /* OBJ_sendProxiedOwner 1 3 6 1 5 5 7 3 26 */
1131, /* OBJ_cmcCA 1 3 6 1 5 5 7 3 27 */
1132, /* OBJ_cmcRA 1 3 6 1 5 5 7 3 28 */
+ 1219, /* OBJ_cmcArchive 1 3 6 1 5 5 7 3 29 */
+ 1220, /* OBJ_id_kp_bgpsec_router 1 3 6 1 5 5 7 3 30 */
+ 1221, /* OBJ_id_kp_BrandIndicatorforMessageIdentification 1 3 6 1 5 5 7 3 31 */
+ 1222, /* OBJ_cmKGA 1 3 6 1 5 5 7 3 32 */
298, /* OBJ_id_it_caProtEncCert 1 3 6 1 5 5 7 4 1 */
299, /* OBJ_id_it_signKeyPairTypes 1 3 6 1 5 5 7 4 2 */
300, /* OBJ_id_it_encKeyPairTypes 1 3 6 1 5 5 7 4 3 */
@@ -5277,6 +5492,9 @@ static const unsigned int obj_objs[NUM_OBJ] = {
311, /* OBJ_id_it_confirmWaitTime 1 3 6 1 5 5 7 4 14 */
312, /* OBJ_id_it_origPKIMessage 1 3 6 1 5 5 7 4 15 */
784, /* OBJ_id_it_suppLangTags 1 3 6 1 5 5 7 4 16 */
+ 1223, /* OBJ_id_it_caCerts 1 3 6 1 5 5 7 4 17 */
+ 1224, /* OBJ_id_it_rootCaKeyUpdate 1 3 6 1 5 5 7 4 18 */
+ 1225, /* OBJ_id_it_certReqTemplate 1 3 6 1 5 5 7 4 19 */
313, /* OBJ_id_regCtrl 1 3 6 1 5 5 7 5 1 */
314, /* OBJ_id_regInfo 1 3 6 1 5 5 7 5 2 */
323, /* OBJ_id_alg_des40 1 3 6 1 5 5 7 6 1 */
@@ -5305,6 +5523,10 @@ static const unsigned int obj_objs[NUM_OBJ] = {
346, /* OBJ_id_cmc_confirmCertAcceptance 1 3 6 1 5 5 7 7 24 */
347, /* OBJ_id_on_personalData 1 3 6 1 5 5 7 8 1 */
858, /* OBJ_id_on_permanentIdentifier 1 3 6 1 5 5 7 8 3 */
+ 1209, /* OBJ_XmppAddr 1 3 6 1 5 5 7 8 5 */
+ 1210, /* OBJ_SRVName 1 3 6 1 5 5 7 8 7 */
+ 1211, /* OBJ_NAIRealm 1 3 6 1 5 5 7 8 8 */
+ 1208, /* OBJ_id_on_SmtpUTF8Mailbox 1 3 6 1 5 5 7 8 9 */
348, /* OBJ_id_pda_dateOfBirth 1 3 6 1 5 5 7 9 1 */
349, /* OBJ_id_pda_placeOfBirth 1 3 6 1 5 5 7 9 2 */
351, /* OBJ_id_pda_gender 1 3 6 1 5 5 7 9 3 */
@@ -5320,6 +5542,8 @@ static const unsigned int obj_objs[NUM_OBJ] = {
360, /* OBJ_id_cct_crs 1 3 6 1 5 5 7 12 1 */
361, /* OBJ_id_cct_PKIData 1 3 6 1 5 5 7 12 2 */
362, /* OBJ_id_cct_PKIResponse 1 3 6 1 5 5 7 12 3 */
+ 1241, /* OBJ_ipAddr_asNumber 1 3 6 1 5 5 7 14 2 */
+ 1242, /* OBJ_ipAddr_asNumberv2 1 3 6 1 5 5 7 14 3 */
664, /* OBJ_id_ppl_anyLanguage 1 3 6 1 5 5 7 21 0 */
665, /* OBJ_id_ppl_inheritAll 1 3 6 1 5 5 7 21 1 */
667, /* OBJ_Independent 1 3 6 1 5 5 7 21 2 */
@@ -5328,6 +5552,9 @@ static const unsigned int obj_objs[NUM_OBJ] = {
363, /* OBJ_ad_timeStamping 1 3 6 1 5 5 7 48 3 */
364, /* OBJ_ad_dvcs 1 3 6 1 5 5 7 48 4 */
785, /* OBJ_caRepository 1 3 6 1 5 5 7 48 5 */
+ 1243, /* OBJ_rpkiManifest 1 3 6 1 5 5 7 48 10 */
+ 1244, /* OBJ_signedObject 1 3 6 1 5 5 7 48 11 */
+ 1245, /* OBJ_rpkiNotify 1 3 6 1 5 5 7 48 13 */
780, /* OBJ_hmac_md5 1 3 6 1 5 5 8 1 1 */
781, /* OBJ_hmac_sha1 1 3 6 1 5 5 8 1 2 */
913, /* OBJ_aes_128_xts 1 3 111 2 1619 0 1 1 */
@@ -5359,12 +5586,12 @@ static const unsigned int obj_objs[NUM_OBJ] = {
1120, /* OBJ_aria_128_ccm 1 2 410 200046 1 1 37 */
1121, /* OBJ_aria_192_ccm 1 2 410 200046 1 1 38 */
1122, /* OBJ_aria_256_ccm 1 2 410 200046 1 1 39 */
- 1174, /* OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm 1 2 643 7 1 1 5 1 1 */
- 1175, /* OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac 1 2 643 7 1 1 5 1 2 */
- 1177, /* OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm 1 2 643 7 1 1 5 2 1 */
- 1178, /* OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac 1 2 643 7 1 1 5 2 2 */
- 1181, /* OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 1 2 643 7 1 1 7 1 1 */
- 1183, /* OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1 2 643 7 1 1 7 2 1 */
+ 1174, /* OBJ_magma_ctr_acpkm 1 2 643 7 1 1 5 1 1 */
+ 1175, /* OBJ_magma_ctr_acpkm_omac 1 2 643 7 1 1 5 1 2 */
+ 1177, /* OBJ_kuznyechik_ctr_acpkm 1 2 643 7 1 1 5 2 1 */
+ 1178, /* OBJ_kuznyechik_ctr_acpkm_omac 1 2 643 7 1 1 5 2 2 */
+ 1181, /* OBJ_magma_kexp15 1 2 643 7 1 1 7 1 1 */
+ 1183, /* OBJ_kuznyechik_kexp15 1 2 643 7 1 1 7 2 1 */
1148, /* OBJ_id_tc26_gost_3410_2012_256_paramSetA 1 2 643 7 1 2 1 1 1 */
1184, /* OBJ_id_tc26_gost_3410_2012_256_paramSetB 1 2 643 7 1 2 1 1 2 */
1185, /* OBJ_id_tc26_gost_3410_2012_256_paramSetC 1 2 643 7 1 2 1 1 3 */
@@ -5507,6 +5734,8 @@ static const unsigned int obj_objs[NUM_OBJ] = {
1103, /* OBJ_hmac_sha3_256 2 16 840 1 101 3 4 2 14 */
1104, /* OBJ_hmac_sha3_384 2 16 840 1 101 3 4 2 15 */
1105, /* OBJ_hmac_sha3_512 2 16 840 1 101 3 4 2 16 */
+ 1196, /* OBJ_kmac128 2 16 840 1 101 3 4 2 19 */
+ 1197, /* OBJ_kmac256 2 16 840 1 101 3 4 2 20 */
802, /* OBJ_dsa_with_SHA224 2 16 840 1 101 3 4 3 1 */
803, /* OBJ_dsa_with_SHA256 2 16 840 1 101 3 4 3 2 */
1106, /* OBJ_dsa_with_SHA384 2 16 840 1 101 3 4 3 3 */
@@ -5624,6 +5853,8 @@ static const unsigned int obj_objs[NUM_OBJ] = {
138, /* OBJ_ms_efs 1 3 6 1 4 1 311 10 3 4 */
648, /* OBJ_ms_smartcard_login 1 3 6 1 4 1 311 20 2 2 */
649, /* OBJ_ms_upn 1 3 6 1 4 1 311 20 2 3 */
+ 1201, /* OBJ_blake2bmac 1 3 6 1 4 1 1722 12 2 1 */
+ 1202, /* OBJ_blake2smac 1 3 6 1 4 1 1722 12 2 2 */
951, /* OBJ_ct_precert_scts 1 3 6 1 4 1 11129 2 4 2 */
952, /* OBJ_ct_precert_poison 1 3 6 1 4 1 11129 2 4 3 */
953, /* OBJ_ct_precert_signer 1 3 6 1 4 1 11129 2 4 4 */
@@ -5657,8 +5888,14 @@ static const unsigned int obj_objs[NUM_OBJ] = {
786, /* OBJ_id_smime_ct_compressedData 1 2 840 113549 1 9 16 1 9 */
1058, /* OBJ_id_smime_ct_contentCollection 1 2 840 113549 1 9 16 1 19 */
1059, /* OBJ_id_smime_ct_authEnvelopedData 1 2 840 113549 1 9 16 1 23 */
+ 1234, /* OBJ_id_ct_routeOriginAuthz 1 2 840 113549 1 9 16 1 24 */
+ 1235, /* OBJ_id_ct_rpkiManifest 1 2 840 113549 1 9 16 1 26 */
787, /* OBJ_id_ct_asciiTextWithCRLF 1 2 840 113549 1 9 16 1 27 */
1060, /* OBJ_id_ct_xml 1 2 840 113549 1 9 16 1 28 */
+ 1236, /* OBJ_id_ct_rpkiGhostbusters 1 2 840 113549 1 9 16 1 35 */
+ 1237, /* OBJ_id_ct_resourceTaggedAttest 1 2 840 113549 1 9 16 1 36 */
+ 1246, /* OBJ_id_ct_geofeedCSVwithCRLF 1 2 840 113549 1 9 16 1 47 */
+ 1247, /* OBJ_id_ct_signedChecklist 1 2 840 113549 1 9 16 1 48 */
212, /* OBJ_id_smime_aa_receiptRequest 1 2 840 113549 1 9 16 2 1 */
213, /* OBJ_id_smime_aa_securityLabel 1 2 840 113549 1 9 16 2 2 */
214, /* OBJ_id_smime_aa_mlExpandHistory 1 2 840 113549 1 9 16 2 3 */
diff --git a/crypto/objects/obj_dat.pl b/crypto/objects/obj_dat.pl
index e1b4a02f288f..60a5e5a6833e 100644
--- a/crypto/objects/obj_dat.pl
+++ b/crypto/objects/obj_dat.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -159,7 +159,7 @@ print <<"EOF";
* Generated by crypto/objects/obj_dat.pl
*
* Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved.
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/objects/obj_err.c b/crypto/objects/obj_err.c
index be4f11ca208b..b4c8df09e66b 100644
--- a/crypto/objects/obj_err.c
+++ b/crypto/objects/obj_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,37 +10,25 @@
#include <openssl/err.h>
#include <openssl/objectserr.h>
+#include "crypto/objectserr.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA OBJ_str_functs[] = {
- {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_ADD_OBJECT, 0), "OBJ_add_object"},
- {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_ADD_SIGID, 0), "OBJ_add_sigid"},
- {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_CREATE, 0), "OBJ_create"},
- {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_DUP, 0), "OBJ_dup"},
- {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_NAME_NEW_INDEX, 0), "OBJ_NAME_new_index"},
- {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_NID2LN, 0), "OBJ_nid2ln"},
- {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_NID2OBJ, 0), "OBJ_nid2obj"},
- {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_NID2SN, 0), "OBJ_nid2sn"},
- {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_TXT2OBJ, 0), "OBJ_txt2obj"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA OBJ_str_reasons[] = {
{ERR_PACK(ERR_LIB_OBJ, 0, OBJ_R_OID_EXISTS), "oid exists"},
{ERR_PACK(ERR_LIB_OBJ, 0, OBJ_R_UNKNOWN_NID), "unknown nid"},
+ {ERR_PACK(ERR_LIB_OBJ, 0, OBJ_R_UNKNOWN_OBJECT_NAME),
+ "unknown object name"},
{0, NULL}
};
#endif
-int ERR_load_OBJ_strings(void)
+int ossl_err_load_OBJ_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(OBJ_str_functs[0].error) == NULL) {
- ERR_load_strings_const(OBJ_str_functs);
+ if (ERR_reason_error_string(OBJ_str_reasons[0].error) == NULL)
ERR_load_strings_const(OBJ_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/objects/obj_lib.c b/crypto/objects/obj_lib.c
index 456a1598cec5..72c0c2c81dd9 100644
--- a/crypto/objects/obj_lib.c
+++ b/crypto/objects/obj_lib.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -25,7 +25,7 @@ ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o)
r = ASN1_OBJECT_new();
if (r == NULL) {
- OBJerr(OBJ_F_OBJ_DUP, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_OBJ, ERR_R_ASN1_LIB);
return NULL;
}
@@ -50,7 +50,7 @@ ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o)
return r;
err:
ASN1_OBJECT_free(r);
- OBJerr(OBJ_F_OBJ_DUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE);
return NULL;
}
diff --git a/crypto/objects/obj_local.h b/crypto/objects/obj_local.h
index a417f7c46ef6..4436b799fd3b 100644
--- a/crypto/objects/obj_local.h
+++ b/crypto/objects/obj_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num
index 1b6a9c61a1c8..c626558ad5c1 100644
--- a/crypto/objects/obj_mac.num
+++ b/crypto/objects/obj_mac.num
@@ -1009,12 +1009,12 @@ issuerSignTool 1008
gost89_cbc 1009
gost89_ecb 1010
gost89_ctr 1011
-grasshopper_ecb 1012
-grasshopper_ctr 1013
-grasshopper_ofb 1014
-grasshopper_cbc 1015
-grasshopper_cfb 1016
-grasshopper_mac 1017
+kuznyechik_ecb 1012
+kuznyechik_ctr 1013
+kuznyechik_ofb 1014
+kuznyechik_cbc 1015
+kuznyechik_cfb 1016
+kuznyechik_mac 1017
chacha20_poly1305 1018
chacha20 1019
tlsfeature 1020
@@ -1171,16 +1171,16 @@ ieee 1170
ieee_siswg 1171
sm2 1172
id_tc26_cipher_gostr3412_2015_magma 1173
-id_tc26_cipher_gostr3412_2015_magma_ctracpkm 1174
-id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac 1175
+magma_ctr_acpkm 1174
+magma_ctr_acpkm_omac 1175
id_tc26_cipher_gostr3412_2015_kuznyechik 1176
-id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm 1177
-id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac 1178
+kuznyechik_ctr_acpkm 1177
+kuznyechik_ctr_acpkm_omac 1178
id_tc26_wrap 1179
id_tc26_wrap_gostr3412_2015_magma 1180
-id_tc26_wrap_gostr3412_2015_magma_kexp15 1181
+magma_kexp15 1181
id_tc26_wrap_gostr3412_2015_kuznyechik 1182
-id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1183
+kuznyechik_kexp15 1183
id_tc26_gost_3410_2012_256_paramSetB 1184
id_tc26_gost_3410_2012_256_paramSetC 1185
id_tc26_gost_3410_2012_256_paramSetD 1186
@@ -1192,3 +1192,56 @@ magma_cfb 1191
magma_mac 1192
hmacWithSHA512_224 1193
hmacWithSHA512_256 1194
+gmac 1195
+kmac128 1196
+kmac256 1197
+aes_128_siv 1198
+aes_192_siv 1199
+aes_256_siv 1200
+blake2bmac 1201
+blake2smac 1202
+sshkdf 1203
+SM2_with_SM3 1204
+sskdf 1205
+x963kdf 1206
+x942kdf 1207
+id_on_SmtpUTF8Mailbox 1208
+XmppAddr 1209
+SRVName 1210
+NAIRealm 1211
+modp_1536 1212
+modp_2048 1213
+modp_3072 1214
+modp_4096 1215
+modp_6144 1216
+modp_8192 1217
+kx_gost18 1218
+cmcArchive 1219
+id_kp_bgpsec_router 1220
+id_kp_BrandIndicatorforMessageIdentification 1221
+cmKGA 1222
+id_it_caCerts 1223
+id_it_rootCaKeyUpdate 1224
+id_it_certReqTemplate 1225
+OGRNIP 1226
+classSignTool 1227
+classSignToolKC1 1228
+classSignToolKC2 1229
+classSignToolKC3 1230
+classSignToolKB1 1231
+classSignToolKB2 1232
+classSignToolKA1 1233
+id_ct_routeOriginAuthz 1234
+id_ct_rpkiManifest 1235
+id_ct_rpkiGhostbusters 1236
+id_ct_resourceTaggedAttest 1237
+id_cp 1238
+sbgp_ipAddrBlockv2 1239
+sbgp_autonomousSysNumv2 1240
+ipAddr_asNumber 1241
+ipAddr_asNumberv2 1242
+rpkiManifest 1243
+signedObject 1244
+rpkiNotify 1245
+id_ct_geofeedCSVwithCRLF 1246
+id_ct_signedChecklist 1247
diff --git a/crypto/objects/obj_xref.c b/crypto/objects/obj_xref.c
index faf59eb20c83..da1035112f4f 100644
--- a/crypto/objects/obj_xref.c
+++ b/crypto/objects/obj_xref.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -104,7 +104,7 @@ int OBJ_add_sigid(int signid, int dig_id, int pkey_id)
if (sigx_app == NULL)
return 0;
if ((ntr = OPENSSL_malloc(sizeof(*ntr))) == NULL) {
- OBJerr(OBJ_F_OBJ_ADD_SIGID, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE);
return 0;
}
ntr->sign_id = signid;
diff --git a/crypto/objects/obj_xref.h b/crypto/objects/obj_xref.h
index 5ef094bbfd84..21a193ee98bc 100644
--- a/crypto/objects/obj_xref.h
+++ b/crypto/objects/obj_xref.h
@@ -2,9 +2,9 @@
* WARNING: do not edit!
* Generated by objxref.pl
*
- * Copyright 1998-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -53,7 +53,7 @@ static const nid_triple sigoid_srt[] = {
NID_id_GostR3410_94_cc},
{NID_id_GostR3411_94_with_GostR3410_2001_cc, NID_id_GostR3411_94,
NID_id_GostR3410_2001_cc},
- {NID_rsassaPss, NID_undef, NID_rsaEncryption},
+ {NID_rsassaPss, NID_undef, NID_rsassaPss},
{NID_dhSinglePass_stdDH_sha1kdf_scheme, NID_sha1, NID_dh_std_kdf},
{NID_dhSinglePass_stdDH_sha224kdf_scheme, NID_sha224, NID_dh_std_kdf},
{NID_dhSinglePass_stdDH_sha256kdf_scheme, NID_sha256, NID_dh_std_kdf},
@@ -79,6 +79,7 @@ static const nid_triple sigoid_srt[] = {
{NID_RSA_SHA3_256, NID_sha3_256, NID_rsaEncryption},
{NID_RSA_SHA3_384, NID_sha3_384, NID_rsaEncryption},
{NID_RSA_SHA3_512, NID_sha3_512, NID_rsaEncryption},
+ {NID_SM2_with_SM3, NID_sm3, NID_sm2},
};
static const nid_triple *const sigoid_srt_xref[] = {
@@ -125,4 +126,5 @@ static const nid_triple *const sigoid_srt_xref[] = {
&sigoid_srt[45],
&sigoid_srt[46],
&sigoid_srt[47],
+ &sigoid_srt[48],
};
diff --git a/crypto/objects/obj_xref.txt b/crypto/objects/obj_xref.txt
index ca3e74461d6c..2a61d4db5927 100644
--- a/crypto/objects/obj_xref.txt
+++ b/crypto/objects/obj_xref.txt
@@ -20,7 +20,7 @@ RSA_SHA3_512 sha3_512 rsaEncryption
# For PSS the digest algorithm can vary and depends on the included
# AlgorithmIdentifier. The digest "undef" indicates the public key
# method should handle this explicitly.
-rsassaPss undef rsaEncryption
+rsassaPss undef rsassaPss
ED25519 undef ED25519
ED448 undef ED448
@@ -64,3 +64,5 @@ dhSinglePass_cofactorDH_sha224kdf_scheme sha224 dh_cofactor_kdf
dhSinglePass_cofactorDH_sha256kdf_scheme sha256 dh_cofactor_kdf
dhSinglePass_cofactorDH_sha384kdf_scheme sha384 dh_cofactor_kdf
dhSinglePass_cofactorDH_sha512kdf_scheme sha512 dh_cofactor_kdf
+
+SM2_with_SM3 sm3 sm2
diff --git a/crypto/objects/objects.pl b/crypto/objects/objects.pl
index 8b258d4df509..51bc248b3f00 100644
--- a/crypto/objects/objects.pl
+++ b/crypto/objects/objects.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -141,12 +141,16 @@ print <<"EOF";
* Generated by crypto/objects/objects.pl
*
* Copyright 2000-$YEAR The OpenSSL Project Authors. All Rights Reserved.
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#ifndef OPENSSL_OBJ_MAC_H
+# define OPENSSL_OBJ_MAC_H
+# pragma once
+
#define SN_undef "UNDEF"
#define LN_undef "undefined"
#define NID_undef 0
@@ -172,6 +176,11 @@ foreach (sort { $a <=> $b } keys %ordern)
print expand("#define OBJ_$Cname\t\t$obj{$Cname}\n") if $obj{$Cname} ne "";
}
+print <<EOF;
+
+#endif /* OPENSSL_OBJ_MAC_H */
+EOF
+
sub process_oid
{
local($oid)=@_;
diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt
index c49d4c568b59..51dba7dcf397 100644
--- a/crypto/objects/objects.txt
+++ b/crypto/objects/objects.txt
@@ -11,6 +11,9 @@ iso 2 : member-body : ISO Member Body
iso 3 : identified-organization
+# GMAC OID
+iso 0 9797 3 4 : GMAC : gmac
+
# HMAC OIDs
identified-organization 6 1 5 5 8 1 1 : HMAC-MD5 : hmac-md5
identified-organization 6 1 5 5 8 1 2 : HMAC-SHA1 : hmac-sha1
@@ -271,8 +274,14 @@ id-smime-ct 8 : id-smime-ct-DVCSResponseData
id-smime-ct 9 : id-smime-ct-compressedData
id-smime-ct 19 : id-smime-ct-contentCollection
id-smime-ct 23 : id-smime-ct-authEnvelopedData
+id-smime-ct 24 : id-ct-routeOriginAuthz
+id-smime-ct 26 : id-ct-rpkiManifest
id-smime-ct 27 : id-ct-asciiTextWithCRLF
id-smime-ct 28 : id-ct-xml
+id-smime-ct 35 : id-ct-rpkiGhostbusters
+id-smime-ct 36 : id-ct-resourceTaggedAttest
+id-smime-ct 47 : id-ct-geofeedCSVwithCRLF
+id-smime-ct 48 : id-ct-signedChecklist
# S/MIME Attributes
id-smime-aa 1 : id-smime-aa-receiptRequest
@@ -385,6 +394,8 @@ sm-scheme 301 : SM2 : sm2
sm-scheme 401 : SM3 : sm3
sm-scheme 504 : RSA-SM3 : sm3WithRSAEncryption
+sm-scheme 501 : SM2-SM3 : SM2-with-SM3
+
# From RFC4231
rsadsi 2 8 : : hmacWithSHA224
rsadsi 2 9 : : hmacWithSHA256
@@ -460,6 +471,7 @@ id-pkix 8 : id-on
id-pkix 9 : id-pda
id-pkix 10 : id-aca
id-pkix 11 : id-qcs
+id-pkix 14 : id-cp
id-pkix 12 : id-cct
id-pkix 21 : id-ppl
id-pkix 48 : id-ad
@@ -498,12 +510,15 @@ id-pe 10 : ac-proxying
id-pe 11 : subjectInfoAccess : Subject Information Access
id-pe 14 : proxyCertInfo : Proxy Certificate Information
id-pe 24 : tlsfeature : TLS Feature
+id-pe 28 : sbgp-ipAddrBlockv2
+id-pe 29 : sbgp-autonomousSysNumv2
# PKIX policyQualifiers for Internet policy qualifiers
id-qt 1 : id-qt-cps : Policy Qualifier CPS
id-qt 2 : id-qt-unotice : Policy Qualifier User Notice
id-qt 3 : textNotice
+# https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-1.3.6.1.5.5.7.3
# PKIX key purpose identifiers
!Cname server-auth
id-kp 1 : serverAuth : TLS Web Server Authentication
@@ -536,7 +551,12 @@ id-kp 25 : sendOwner : Send Owner
id-kp 26 : sendProxiedOwner : Send Proxied Owner
id-kp 27 : cmcCA : CMC Certificate Authority
id-kp 28 : cmcRA : CMC Registration Authority
+id-kp 29 : cmcArchive : CMC Archive Server
+id-kp 30 : id-kp-bgpsec-router : BGPsec Router
+id-kp 31 : id-kp-BrandIndicatorforMessageIdentification : Brand Indicator for Message Identification
+id-kp 32 : cmKGA : Certificate Management Key Generation Authority
+# https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-1.3.6.1.5.5.7.4
# CMP information types
id-it 1 : id-it-caProtEncCert
id-it 2 : id-it-signKeyPairTypes
@@ -556,6 +576,9 @@ id-it 13 : id-it-implicitConfirm
id-it 14 : id-it-confirmWaitTime
id-it 15 : id-it-origPKIMessage
id-it 16 : id-it-suppLangTags
+id-it 17 : id-it-caCerts
+id-it 18 : id-it-rootCaKeyUpdate
+id-it 19 : id-it-certReqTemplate
# CRMF registration
id-pkip 1 : id-regCtrl
@@ -604,6 +627,10 @@ id-cmc 24 : id-cmc-confirmCertAcceptance
# other names
id-on 1 : id-on-personalData
id-on 3 : id-on-permanentIdentifier : Permanent Identifier
+id-on 5 : id-on-xmppAddr : XmppAddr
+id-on 7 : id-on-dnsSRV : SRVName
+id-on 8 : id-on-NAIRealm : NAIRealm
+id-on 9 : id-on-SmtpUTF8Mailbox : Smtp UTF8 Mailbox
# personal data attributes
id-pda 1 : id-pda-dateOfBirth
@@ -624,6 +651,10 @@ id-aca 6 : id-aca-encAttrs
# qualified certificate statements
id-qcs 1 : id-qcs-pkixQCSyntax-v1
+# PKIX Certificate Policies
+id-cp 2 : ipAddr-asNumber
+id-cp 3 : ipAddr-asNumberv2
+
# CMC content types
id-cct 1 : id-cct-crs
id-cct 2 : id-cct-PKIData
@@ -644,7 +675,9 @@ id-ad 3 : ad_timestamping : AD Time Stamping
!Cname ad-dvcs
id-ad 4 : AD_DVCS : ad dvcs
id-ad 5 : caRepository : CA Repository
-
+id-ad 10 : rpkiManifest : RPKI Manifest
+id-ad 11 : signedObject : Signed Object
+id-ad 13 : rpkiNotify : RPKI Notify
!Alias id-pkix-OCSP ad-OCSP
!module id-pkix-OCSP
@@ -698,8 +731,10 @@ algorithm 29 : RSA-SHA1-2 : sha1WithRSA
1 3 36 3 2 1 : RIPEMD160 : ripemd160
1 3 36 3 3 1 2 : RSA-RIPEMD160 : ripemd160WithRSA
-1 3 6 1 4 1 1722 12 2 1 16 : BLAKE2b512 : blake2b512
-1 3 6 1 4 1 1722 12 2 2 8 : BLAKE2s256 : blake2s256
+1 3 6 1 4 1 1722 12 2 1 : BLAKE2BMAC : blake2bmac
+1 3 6 1 4 1 1722 12 2 2 : BLAKE2SMAC : blake2smac
+blake2bmac 16 : BLAKE2b512 : blake2b512
+blake2smac 8 : BLAKE2s256 : blake2s256
!Cname sxnet
1 3 101 1 4 1 : SXNetID : Strong Extranet ID
@@ -976,6 +1011,10 @@ nist_hashalgs 16 : id-hmacWithSHA3-512 : hmac-sha3-512
# how to handle them...
# nist_hashalgs 17 : id-shake128-len : shake128-len
# nist_hashalgs 18 : id-shake256-len : shake256-len
+nist_hashalgs 19 : KMAC128 : kmac128
+nist_hashalgs 20 : KMAC256 : kmac256
+# nist_hashalgs 21 : KMAC128-XOF : kmac128-xof
+# nist_hashalgs 22 : KMAC256-XOF : kmac256-xof
# OIDs for dsa-with-sha224 and dsa-with-sha256
!Alias dsa_with_sha2 nistAlgorithms 3
@@ -1344,11 +1383,11 @@ id-tc26-mac 2 : id-tc26-hmac-gost-3411-2012-512 : HMAC GOST 34.11-2012 512 bit
id-tc26-algorithms 5 : id-tc26-cipher
id-tc26-cipher 1 : id-tc26-cipher-gostr3412-2015-magma
-id-tc26-cipher-gostr3412-2015-magma 1 : id-tc26-cipher-gostr3412-2015-magma-ctracpkm
-id-tc26-cipher-gostr3412-2015-magma 2 : id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac
+id-tc26-cipher-gostr3412-2015-magma 1 : magma-ctr-acpkm
+id-tc26-cipher-gostr3412-2015-magma 2 : magma-ctr-acpkm-omac
id-tc26-cipher 2 : id-tc26-cipher-gostr3412-2015-kuznyechik
-id-tc26-cipher-gostr3412-2015-kuznyechik 1 : id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm
-id-tc26-cipher-gostr3412-2015-kuznyechik 2 : id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac
+id-tc26-cipher-gostr3412-2015-kuznyechik 1 : kuznyechik-ctr-acpkm
+id-tc26-cipher-gostr3412-2015-kuznyechik 2 : kuznyechik-ctr-acpkm-omac
id-tc26-algorithms 6 : id-tc26-agreement
id-tc26-agreement 1 : id-tc26-agreement-gost-3410-2012-256
@@ -1356,9 +1395,9 @@ id-tc26-agreement 2 : id-tc26-agreement-gost-3410-2012-512
id-tc26-algorithms 7 : id-tc26-wrap
id-tc26-wrap 1 : id-tc26-wrap-gostr3412-2015-magma
-id-tc26-wrap-gostr3412-2015-magma 1 : id-tc26-wrap-gostr3412-2015-magma-kexp15
+id-tc26-wrap-gostr3412-2015-magma 1 : magma-kexp15
id-tc26-wrap 2 : id-tc26-wrap-gostr3412-2015-kuznyechik
-id-tc26-wrap-gostr3412-2015-kuznyechik 1 : id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15
+id-tc26-wrap-gostr3412-2015-kuznyechik 1 : kuznyechik-kexp15
id-tc26 2 : id-tc26-constants
@@ -1382,16 +1421,24 @@ id-tc26-gost-28147-constants 1 : id-tc26-gost-28147-param-Z : GOST 28147-89 TC26
member-body 643 3 131 1 1 : INN : INN
member-body 643 100 1 : OGRN : OGRN
member-body 643 100 3 : SNILS : SNILS
+member-body 643 100 5 : OGRNIP : OGRNIP
member-body 643 100 111 : subjectSignTool : Signing Tool of Subject
member-body 643 100 112 : issuerSignTool : Signing Tool of Issuer
+member-body 643 100 113 : classSignTool : Class of Signing Tool
+member-body 643 100 113 1 : classSignToolKC1 : Class of Signing Tool KC1
+member-body 643 100 113 2 : classSignToolKC2 : Class of Signing Tool KC2
+member-body 643 100 113 3 : classSignToolKC3 : Class of Signing Tool KC3
+member-body 643 100 113 4 : classSignToolKB1 : Class of Signing Tool KB1
+member-body 643 100 113 5 : classSignToolKB2 : Class of Signing Tool KB2
+member-body 643 100 113 6 : classSignToolKA1 : Class of Signing Tool KA1
#GOST R34.13-2015 Grasshopper "Kuznechik"
- : grasshopper-ecb
- : grasshopper-ctr
- : grasshopper-ofb
- : grasshopper-cbc
- : grasshopper-cfb
- : grasshopper-mac
+ : kuznyechik-ecb
+ : kuznyechik-ctr
+ : kuznyechik-ofb
+ : kuznyechik-cbc
+ : kuznyechik-cfb
+ : kuznyechik-mac
#GOST R34.13-2015 Magma
: magma-ecb
@@ -1600,6 +1647,17 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme
# NID for HKDF
: HKDF : hkdf
+# NID for SSHKDF
+ : SSHKDF : sshkdf
+
+# NID for SSKDF
+ : SSKDF : sskdf
+# NID for X942KDF
+ : X942KDF : x942kdf
+
+# NID for X963-2001 KDF
+ : X963KDF : x963kdf
+
# RFC 4556
1 3 6 1 5 2 3 : id-pkinit
id-pkinit 4 : pkInitClientAuth : PKINIT Client Auth
@@ -1622,6 +1680,7 @@ id-pkinit 5 : pkInitKDC : Signing KDC Response
: KxPSK : kx-psk
: KxSRP : kx-srp
: KxGOST : kx-gost
+ : KxGOST18 : kx-gost18
: KxANY : kx-any
# NIDs for cipher authentication
@@ -1638,13 +1697,19 @@ id-pkinit 5 : pkInitKDC : Signing KDC Response
: Poly1305 : poly1305
# NID for SipHash
: SipHash : siphash
-
# NIDs for RFC7919 DH parameters
: ffdhe2048
: ffdhe3072
: ffdhe4096
: ffdhe6144
: ffdhe8192
+# NIDs for RFC3526 DH parameters
+ : modp_1536
+ : modp_2048
+ : modp_3072
+ : modp_4096
+ : modp_6144
+ : modp_8192
# OIDs for DSTU-4145/DSTU-7564 (http://zakon2.rada.gov.ua/laws/show/z0423-17)
@@ -1675,3 +1740,7 @@ dstu4145le 2 6 : uacurve6 : DSTU curve 6
dstu4145le 2 7 : uacurve7 : DSTU curve 7
dstu4145le 2 8 : uacurve8 : DSTU curve 8
dstu4145le 2 9 : uacurve9 : DSTU curve 9
+# NID for AES-SIV
+ : AES-128-SIV : aes-128-siv
+ : AES-192-SIV : aes-192-siv
+ : AES-256-SIV : aes-256-siv
diff --git a/crypto/objects/objxref.pl b/crypto/objects/objxref.pl
index 4d4b9074fc26..a6748f00f45a 100644
--- a/crypto/objects/objxref.pl
+++ b/crypto/objects/objxref.pl
@@ -1,12 +1,11 @@
#! /usr/bin/env perl
-# Copyright 1998-2022 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
-
use strict;
use FindBin;
use lib "$FindBin::Bin/../../util/perl";
@@ -79,7 +78,7 @@ print <<EOF;
*
* Copyright 1998-$YEAR The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/ocsp/build.info b/crypto/ocsp/build.info
index 0902caae3de0..79a59004afbf 100644
--- a/crypto/ocsp/build.info
+++ b/crypto/ocsp/build.info
@@ -1,4 +1,4 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
- ocsp_asn.c ocsp_ext.c ocsp_ht.c ocsp_lib.c ocsp_cl.c \
+ ocsp_asn.c ocsp_ext.c ocsp_http.c ocsp_lib.c ocsp_cl.c \
ocsp_srv.c ocsp_prn.c ocsp_vfy.c ocsp_err.c v3_ocsp.c
diff --git a/crypto/ocsp/ocsp_asn.c b/crypto/ocsp/ocsp_asn.c
index a869e32bc8b3..4b4342825c3c 100644
--- a/crypto/ocsp/ocsp_asn.c
+++ b/crypto/ocsp/ocsp_asn.c
@@ -1,7 +1,7 @@
/*
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/ocsp/ocsp_cl.c b/crypto/ocsp/ocsp_cl.c
index 55ffd45c6ec0..c1dda38414f2 100644
--- a/crypto/ocsp/ocsp_cl.c
+++ b/crypto/ocsp/ocsp_cl.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -27,7 +27,6 @@
* Add an OCSP_CERTID to an OCSP request. Return new OCSP_ONEREQ pointer:
* useful if we want to add extensions.
*/
-
OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid)
{
OCSP_ONEREQ *one = NULL;
@@ -38,21 +37,17 @@ OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid)
one->reqCert = cid;
if (req && !sk_OCSP_ONEREQ_push(req->tbsRequest.requestList, one)) {
one->reqCert = NULL; /* do not free on error */
- goto err;
+ OCSP_ONEREQ_free(one);
+ return NULL;
}
return one;
- err:
- OCSP_ONEREQ_free(one);
- return NULL;
}
/* Set requestorName from an X509_NAME structure */
-
-int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm)
+int OCSP_request_set1_name(OCSP_REQUEST *req, const X509_NAME *nm)
{
- GENERAL_NAME *gen;
+ GENERAL_NAME *gen = GENERAL_NAME_new();
- gen = GENERAL_NAME_new();
if (gen == NULL)
return 0;
if (!X509_NAME_set(&gen->d.directoryName, nm)) {
@@ -66,25 +61,15 @@ int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm)
}
/* Add a certificate to an OCSP request */
-
int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert)
{
- OCSP_SIGNATURE *sig;
- if (req->optionalSignature == NULL)
- req->optionalSignature = OCSP_SIGNATURE_new();
- sig = req->optionalSignature;
- if (sig == NULL)
+ if (req->optionalSignature == NULL
+ && (req->optionalSignature = OCSP_SIGNATURE_new()) == NULL)
return 0;
if (cert == NULL)
return 1;
- if (sig->certs == NULL
- && (sig->certs = sk_X509_new_null()) == NULL)
- return 0;
-
- if (!sk_X509_push(sig->certs, cert))
- return 0;
- X509_up_ref(cert);
- return 1;
+ return ossl_x509_add_cert_new(&req->optionalSignature->certs, cert,
+ X509_ADD_FLAG_UP_REF);
}
/*
@@ -92,39 +77,32 @@ int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert)
* optional signers certificate and include one or more optional certificates
* in the request. Behaves like PKCS7_sign().
*/
-
int OCSP_request_sign(OCSP_REQUEST *req,
X509 *signer,
EVP_PKEY *key,
const EVP_MD *dgst,
STACK_OF(X509) *certs, unsigned long flags)
{
- int i;
- X509 *x;
-
if (!OCSP_request_set1_name(req, X509_get_subject_name(signer)))
goto err;
if ((req->optionalSignature = OCSP_SIGNATURE_new()) == NULL)
goto err;
- if (key) {
+ if (key != NULL) {
if (!X509_check_private_key(signer, key)) {
- OCSPerr(OCSP_F_OCSP_REQUEST_SIGN,
- OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
+ ERR_raise(ERR_LIB_OCSP,
+ OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
goto err;
}
- if (!OCSP_REQUEST_sign(req, key, dgst))
+ if (!OCSP_REQUEST_sign(req, key, dgst, signer->libctx, signer->propq))
goto err;
}
- if (!(flags & OCSP_NOCERTS)) {
- if (!OCSP_request_add1_cert(req, signer))
+ if ((flags & OCSP_NOCERTS) == 0) {
+ if (!OCSP_request_add1_cert(req, signer)
+ || !X509_add_certs(req->optionalSignature->certs, certs,
+ X509_ADD_FLAG_UP_REF))
goto err;
- for (i = 0; i < sk_X509_num(certs); i++) {
- x = sk_X509_value(certs, i);
- if (!OCSP_request_add1_cert(req, x))
- goto err;
- }
}
return 1;
@@ -135,7 +113,6 @@ int OCSP_request_sign(OCSP_REQUEST *req,
}
/* Get response status */
-
int OCSP_response_status(OCSP_RESPONSE *resp)
{
return ASN1_ENUMERATED_get(resp->responseStatus);
@@ -145,17 +122,16 @@ int OCSP_response_status(OCSP_RESPONSE *resp)
* Extract basic response from OCSP_RESPONSE or NULL if no basic response
* present.
*/
-
OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp)
{
- OCSP_RESPBYTES *rb;
- rb = resp->responseBytes;
- if (!rb) {
- OCSPerr(OCSP_F_OCSP_RESPONSE_GET1_BASIC, OCSP_R_NO_RESPONSE_DATA);
+ OCSP_RESPBYTES *rb = resp->responseBytes;
+
+ if (rb == NULL) {
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_NO_RESPONSE_DATA);
return NULL;
}
if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic) {
- OCSPerr(OCSP_F_OCSP_RESPONSE_GET1_BASIC, OCSP_R_NOT_BASIC_RESPONSE);
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_NOT_BASIC_RESPONSE);
return NULL;
}
@@ -177,27 +153,24 @@ const OCSP_RESPDATA *OCSP_resp_get0_respdata(const OCSP_BASICRESP *bs)
return &bs->tbsResponseData;
}
-/*
- * Return number of OCSP_SINGLERESP responses present in a basic response.
- */
+/* Return number of OCSP_SINGLERESP responses present in a basic response */
int OCSP_resp_count(OCSP_BASICRESP *bs)
{
- if (!bs)
+ if (bs == NULL)
return -1;
return sk_OCSP_SINGLERESP_num(bs->tbsResponseData.responses);
}
/* Extract an OCSP_SINGLERESP response with a given index */
-
OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx)
{
- if (!bs)
+ if (bs == NULL)
return NULL;
return sk_OCSP_SINGLERESP_value(bs->tbsResponseData.responses, idx);
}
-const ASN1_GENERALIZEDTIME *OCSP_resp_get0_produced_at(const OCSP_BASICRESP* bs)
+const ASN1_GENERALIZEDTIME *OCSP_resp_get0_produced_at(const OCSP_BASICRESP *bs)
{
return bs->tbsResponseData.producedAt;
}
@@ -246,13 +219,13 @@ int OCSP_resp_get1_id(const OCSP_BASICRESP *bs,
}
/* Look single response matching a given certificate ID */
-
int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last)
{
int i;
STACK_OF(OCSP_SINGLERESP) *sresp;
OCSP_SINGLERESP *single;
- if (!bs)
+
+ if (bs == NULL)
return -1;
if (last < 0)
last = 0;
@@ -272,7 +245,6 @@ int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last)
* revtime and reason values are only set if the certificate status is
* revoked. Returns numerical value of status.
*/
-
int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason,
ASN1_GENERALIZEDTIME **revtime,
ASN1_GENERALIZEDTIME **thisupd,
@@ -280,12 +252,14 @@ int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason,
{
int ret;
OCSP_CERTSTATUS *cst;
- if (!single)
+
+ if (single == NULL)
return -1;
cst = single->certStatus;
ret = cst->type;
if (ret == V_OCSP_CERTSTATUS_REVOKED) {
OCSP_REVOKEDINFO *rev = cst->value.revoked;
+
if (revtime)
*revtime = rev->revocationTime;
if (reason) {
@@ -295,9 +269,9 @@ int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason,
*reason = -1;
}
}
- if (thisupd)
+ if (thisupd != NULL)
*thisupd = single->thisUpdate;
- if (nextupd)
+ if (nextupd != NULL)
*nextupd = single->nextUpdate;
return ret;
}
@@ -306,22 +280,21 @@ int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason,
* This function combines the previous ones: look up a certificate ID and if
* found extract status information. Return 0 is successful.
*/
-
int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status,
int *reason,
ASN1_GENERALIZEDTIME **revtime,
ASN1_GENERALIZEDTIME **thisupd,
ASN1_GENERALIZEDTIME **nextupd)
{
- int i;
+ int i = OCSP_resp_find(bs, id, -1);
OCSP_SINGLERESP *single;
- i = OCSP_resp_find(bs, id, -1);
+
/* Maybe check for multiple responses and give an error? */
if (i < 0)
return 0;
single = OCSP_resp_get0(bs, i);
i = OCSP_single_get0_status(single, reason, revtime, thisupd, nextupd);
- if (status)
+ if (status != NULL)
*status = i;
return 1;
}
@@ -334,21 +307,21 @@ int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status,
* accepting very old responses without a nextUpdate field an optional maxage
* parameter specifies the maximum age the thisUpdate field can be.
*/
-
int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd,
ASN1_GENERALIZEDTIME *nextupd, long nsec, long maxsec)
{
int ret = 1;
time_t t_now, t_tmp;
+
time(&t_now);
/* Check thisUpdate is valid and not more than nsec in the future */
if (!ASN1_GENERALIZEDTIME_check(thisupd)) {
- OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_ERROR_IN_THISUPDATE_FIELD);
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_ERROR_IN_THISUPDATE_FIELD);
ret = 0;
} else {
t_tmp = t_now + nsec;
if (X509_cmp_time(thisupd, &t_tmp) > 0) {
- OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_STATUS_NOT_YET_VALID);
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_STATUS_NOT_YET_VALID);
ret = 0;
}
@@ -359,31 +332,30 @@ int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd,
if (maxsec >= 0) {
t_tmp = t_now - maxsec;
if (X509_cmp_time(thisupd, &t_tmp) < 0) {
- OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_STATUS_TOO_OLD);
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_STATUS_TOO_OLD);
ret = 0;
}
}
}
- if (!nextupd)
+ if (nextupd == NULL)
return ret;
/* Check nextUpdate is valid and not more than nsec in the past */
if (!ASN1_GENERALIZEDTIME_check(nextupd)) {
- OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_ERROR_IN_NEXTUPDATE_FIELD);
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_ERROR_IN_NEXTUPDATE_FIELD);
ret = 0;
} else {
t_tmp = t_now - nsec;
if (X509_cmp_time(nextupd, &t_tmp) < 0) {
- OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_STATUS_EXPIRED);
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_STATUS_EXPIRED);
ret = 0;
}
}
/* Also don't allow nextUpdate to precede thisUpdate */
if (ASN1_STRING_cmp(nextupd, thisupd) < 0) {
- OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY,
- OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE);
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE);
ret = 0;
}
diff --git a/crypto/ocsp/ocsp_err.c b/crypto/ocsp/ocsp_err.c
index 660e193665c1..c33a7d3e6b21 100644
--- a/crypto/ocsp/ocsp_err.c
+++ b/crypto/ocsp/ocsp_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,45 +10,22 @@
#include <openssl/err.h>
#include <openssl/ocsperr.h>
+#include "crypto/ocsperr.h"
-#ifndef OPENSSL_NO_ERR
+#ifndef OPENSSL_NO_OCSP
-static const ERR_STRING_DATA OCSP_str_functs[] = {
- {ERR_PACK(ERR_LIB_OCSP, OCSP_F_D2I_OCSP_NONCE, 0), "d2i_ocsp_nonce"},
- {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_BASIC_ADD1_STATUS, 0),
- "OCSP_basic_add1_status"},
- {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_BASIC_SIGN, 0), "OCSP_basic_sign"},
- {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_BASIC_SIGN_CTX, 0),
- "OCSP_basic_sign_ctx"},
- {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_BASIC_VERIFY, 0), "OCSP_basic_verify"},
- {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_CERT_ID_NEW, 0), "OCSP_cert_id_new"},
- {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_CHECK_DELEGATED, 0),
- "ocsp_check_delegated"},
- {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_CHECK_IDS, 0), "ocsp_check_ids"},
- {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_CHECK_ISSUER, 0), "ocsp_check_issuer"},
- {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_CHECK_VALIDITY, 0),
- "OCSP_check_validity"},
- {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_MATCH_ISSUERID, 0),
- "ocsp_match_issuerid"},
- {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_PARSE_URL, 0), "OCSP_parse_url"},
- {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_REQUEST_SIGN, 0), "OCSP_request_sign"},
- {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_REQUEST_VERIFY, 0),
- "OCSP_request_verify"},
- {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_RESPONSE_GET1_BASIC, 0),
- "OCSP_response_get1_basic"},
- {ERR_PACK(ERR_LIB_OCSP, OCSP_F_PARSE_HTTP_LINE1, 0), "parse_http_line1"},
- {0, NULL}
-};
+# ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA OCSP_str_reasons[] = {
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_CERTIFICATE_VERIFY_ERROR),
"certificate verify error"},
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_DIGEST_ERR), "digest err"},
+ {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_DIGEST_NAME_ERR), "digest name err"},
+ {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_DIGEST_SIZE_ERR), "digest size err"},
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_ERROR_IN_NEXTUPDATE_FIELD),
"error in nextupdate field"},
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_ERROR_IN_THISUPDATE_FIELD),
"error in thisupdate field"},
- {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_ERROR_PARSING_URL), "error parsing url"},
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_MISSING_OCSPSIGNING_USAGE),
"missing ocspsigning usage"},
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE),
@@ -68,10 +45,6 @@ static const ERR_STRING_DATA OCSP_str_reasons[] = {
"response contains no revocation data"},
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_ROOT_CA_NOT_TRUSTED),
"root ca not trusted"},
- {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_SERVER_RESPONSE_ERROR),
- "server response error"},
- {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_SERVER_RESPONSE_PARSE_ERROR),
- "server response parse error"},
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_SIGNATURE_FAILURE), "signature failure"},
{ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND),
"signer certificate not found"},
@@ -87,15 +60,16 @@ static const ERR_STRING_DATA OCSP_str_reasons[] = {
{0, NULL}
};
-#endif
+# endif
-int ERR_load_OCSP_strings(void)
+int ossl_err_load_OCSP_strings(void)
{
-#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(OCSP_str_functs[0].error) == NULL) {
- ERR_load_strings_const(OCSP_str_functs);
+# ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(OCSP_str_reasons[0].error) == NULL)
ERR_load_strings_const(OCSP_str_reasons);
- }
-#endif
+# endif
return 1;
}
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/crypto/ocsp/ocsp_ext.c b/crypto/ocsp/ocsp_ext.c
index f6c387ffb7d7..9707ccb94f4c 100644
--- a/crypto/ocsp/ocsp_ext.c
+++ b/crypto/ocsp/ocsp_ext.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -268,8 +268,8 @@ static int ocsp_add1_nonce(STACK_OF(X509_EXTENSION) **exts,
memcpy(tmpval, val, len);
else if (RAND_bytes(tmpval, len) <= 0)
goto err;
- if (!X509V3_add1_i2d(exts, NID_id_pkix_OCSP_Nonce,
- &os, 0, X509V3_ADD_REPLACE))
+ if (X509V3_add1_i2d(exts, NID_id_pkix_OCSP_Nonce,
+ &os, 0, X509V3_ADD_REPLACE) <= 0)
goto err;
ret = 1;
err:
@@ -430,7 +430,7 @@ X509_EXTENSION *OCSP_archive_cutoff_new(char *tim)
* two--NID_ad_ocsp, NID_id_ad_caIssuers--and GeneralName value. This method
* forces NID_ad_ocsp and uniformResourceLocator [6] IA5String.
*/
-X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME *issuer, const char **urls)
+X509_EXTENSION *OCSP_url_svcloc_new(const X509_NAME *issuer, const char **urls)
{
X509_EXTENSION *x = NULL;
ASN1_IA5STRING *ia5 = NULL;
diff --git a/crypto/ocsp/ocsp_ht.c b/crypto/ocsp/ocsp_ht.c
deleted file mode 100644
index ba408bc86f98..000000000000
--- a/crypto/ocsp/ocsp_ht.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- * Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "e_os.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include "crypto/ctype.h"
-#include <string.h>
-#include <openssl/asn1.h>
-#include <openssl/ocsp.h>
-#include <openssl/err.h>
-#include <openssl/buffer.h>
-
-/* Stateful OCSP request code, supporting non-blocking I/O */
-
-/* Opaque OCSP request status structure */
-
-struct ocsp_req_ctx_st {
- int state; /* Current I/O state */
- unsigned char *iobuf; /* Line buffer */
- int iobuflen; /* Line buffer length */
- BIO *io; /* BIO to perform I/O with */
- BIO *mem; /* Memory BIO response is built into */
- unsigned long asn1_len; /* ASN1 length of response */
- unsigned long max_resp_len; /* Maximum length of response */
-};
-
-#define OCSP_MAX_RESP_LENGTH (100 * 1024)
-#define OCSP_MAX_LINE_LEN 4096;
-
-/* OCSP states */
-
-/* If set no reading should be performed */
-#define OHS_NOREAD 0x1000
-/* Error condition */
-#define OHS_ERROR (0 | OHS_NOREAD)
-/* First line being read */
-#define OHS_FIRSTLINE 1
-/* MIME headers being read */
-#define OHS_HEADERS 2
-/* OCSP initial header (tag + length) being read */
-#define OHS_ASN1_HEADER 3
-/* OCSP content octets being read */
-#define OHS_ASN1_CONTENT 4
-/* First call: ready to start I/O */
-#define OHS_ASN1_WRITE_INIT (5 | OHS_NOREAD)
-/* Request being sent */
-#define OHS_ASN1_WRITE (6 | OHS_NOREAD)
-/* Request being flushed */
-#define OHS_ASN1_FLUSH (7 | OHS_NOREAD)
-/* Completed */
-#define OHS_DONE (8 | OHS_NOREAD)
-/* Headers set, no final \r\n included */
-#define OHS_HTTP_HEADER (9 | OHS_NOREAD)
-
-static int parse_http_line1(char *line);
-
-OCSP_REQ_CTX *OCSP_REQ_CTX_new(BIO *io, int maxline)
-{
- OCSP_REQ_CTX *rctx = OPENSSL_zalloc(sizeof(*rctx));
-
- if (rctx == NULL)
- return NULL;
- rctx->state = OHS_ERROR;
- rctx->max_resp_len = OCSP_MAX_RESP_LENGTH;
- rctx->mem = BIO_new(BIO_s_mem());
- rctx->io = io;
- if (maxline > 0)
- rctx->iobuflen = maxline;
- else
- rctx->iobuflen = OCSP_MAX_LINE_LEN;
- rctx->iobuf = OPENSSL_malloc(rctx->iobuflen);
- if (rctx->iobuf == NULL || rctx->mem == NULL) {
- OCSP_REQ_CTX_free(rctx);
- return NULL;
- }
- return rctx;
-}
-
-void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx)
-{
- if (!rctx)
- return;
- BIO_free(rctx->mem);
- OPENSSL_free(rctx->iobuf);
- OPENSSL_free(rctx);
-}
-
-BIO *OCSP_REQ_CTX_get0_mem_bio(OCSP_REQ_CTX *rctx)
-{
- return rctx->mem;
-}
-
-void OCSP_set_max_response_length(OCSP_REQ_CTX *rctx, unsigned long len)
-{
- if (len == 0)
- rctx->max_resp_len = OCSP_MAX_RESP_LENGTH;
- else
- rctx->max_resp_len = len;
-}
-
-int OCSP_REQ_CTX_i2d(OCSP_REQ_CTX *rctx, const ASN1_ITEM *it, ASN1_VALUE *val)
-{
- static const char req_hdr[] =
- "Content-Type: application/ocsp-request\r\n"
- "Content-Length: %d\r\n\r\n";
- int reqlen = ASN1_item_i2d(val, NULL, it);
- if (BIO_printf(rctx->mem, req_hdr, reqlen) <= 0)
- return 0;
- if (ASN1_item_i2d_bio(it, rctx->mem, val) <= 0)
- return 0;
- rctx->state = OHS_ASN1_WRITE_INIT;
- return 1;
-}
-
-int OCSP_REQ_CTX_nbio_d2i(OCSP_REQ_CTX *rctx,
- ASN1_VALUE **pval, const ASN1_ITEM *it)
-{
- int rv, len;
- const unsigned char *p;
-
- rv = OCSP_REQ_CTX_nbio(rctx);
- if (rv != 1)
- return rv;
-
- len = BIO_get_mem_data(rctx->mem, &p);
- *pval = ASN1_item_d2i(NULL, &p, len, it);
- if (*pval == NULL) {
- rctx->state = OHS_ERROR;
- return 0;
- }
- return 1;
-}
-
-int OCSP_REQ_CTX_http(OCSP_REQ_CTX *rctx, const char *op, const char *path)
-{
- static const char http_hdr[] = "%s %s HTTP/1.0\r\n";
-
- if (!path)
- path = "/";
-
- if (BIO_printf(rctx->mem, http_hdr, op, path) <= 0)
- return 0;
- rctx->state = OHS_HTTP_HEADER;
- return 1;
-}
-
-int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req)
-{
- return OCSP_REQ_CTX_i2d(rctx, ASN1_ITEM_rptr(OCSP_REQUEST),
- (ASN1_VALUE *)req);
-}
-
-int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx,
- const char *name, const char *value)
-{
- if (!name)
- return 0;
- if (BIO_puts(rctx->mem, name) <= 0)
- return 0;
- if (value) {
- if (BIO_write(rctx->mem, ": ", 2) != 2)
- return 0;
- if (BIO_puts(rctx->mem, value) <= 0)
- return 0;
- }
- if (BIO_write(rctx->mem, "\r\n", 2) != 2)
- return 0;
- rctx->state = OHS_HTTP_HEADER;
- return 1;
-}
-
-OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req,
- int maxline)
-{
-
- OCSP_REQ_CTX *rctx = NULL;
- rctx = OCSP_REQ_CTX_new(io, maxline);
- if (rctx == NULL)
- return NULL;
-
- if (!OCSP_REQ_CTX_http(rctx, "POST", path))
- goto err;
-
- if (req && !OCSP_REQ_CTX_set1_req(rctx, req))
- goto err;
-
- return rctx;
-
- err:
- OCSP_REQ_CTX_free(rctx);
- return NULL;
-}
-
-/*
- * Parse the HTTP response. This will look like this: "HTTP/1.0 200 OK". We
- * need to obtain the numeric code and (optional) informational message.
- */
-
-static int parse_http_line1(char *line)
-{
- int retcode;
- char *p, *q, *r;
- /* Skip to first white space (passed protocol info) */
-
- for (p = line; *p && !ossl_isspace(*p); p++)
- continue;
- if (!*p) {
- OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
- return 0;
- }
-
- /* Skip past white space to start of response code */
- while (*p && ossl_isspace(*p))
- p++;
-
- if (!*p) {
- OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
- return 0;
- }
-
- /* Find end of response code: first whitespace after start of code */
- for (q = p; *q && !ossl_isspace(*q); q++)
- continue;
-
- if (!*q) {
- OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
- return 0;
- }
-
- /* Set end of response code and start of message */
- *q++ = 0;
-
- /* Attempt to parse numeric code */
- retcode = strtoul(p, &r, 10);
-
- if (*r)
- return 0;
-
- /* Skip over any leading white space in message */
- while (*q && ossl_isspace(*q))
- q++;
-
- if (*q) {
- /*
- * Finally zap any trailing white space in message (include CRLF)
- */
-
- /* We know q has a non white space character so this is OK */
- for (r = q + strlen(q) - 1; ossl_isspace(*r); r--)
- *r = 0;
- }
- if (retcode != 200) {
- OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_ERROR);
- if (!*q)
- ERR_add_error_data(2, "Code=", p);
- else
- ERR_add_error_data(4, "Code=", p, ",Reason=", q);
- return 0;
- }
-
- return 1;
-
-}
-
-int OCSP_REQ_CTX_nbio(OCSP_REQ_CTX *rctx)
-{
- int i, n;
- const unsigned char *p;
- next_io:
- if (!(rctx->state & OHS_NOREAD)) {
- n = BIO_read(rctx->io, rctx->iobuf, rctx->iobuflen);
-
- if (n <= 0) {
- if (BIO_should_retry(rctx->io))
- return -1;
- return 0;
- }
-
- /* Write data to memory BIO */
-
- if (BIO_write(rctx->mem, rctx->iobuf, n) != n)
- return 0;
- }
-
- switch (rctx->state) {
- case OHS_HTTP_HEADER:
- /* Last operation was adding headers: need a final \r\n */
- if (BIO_write(rctx->mem, "\r\n", 2) != 2) {
- rctx->state = OHS_ERROR;
- return 0;
- }
- rctx->state = OHS_ASN1_WRITE_INIT;
-
- /* fall thru */
- case OHS_ASN1_WRITE_INIT:
- rctx->asn1_len = BIO_get_mem_data(rctx->mem, NULL);
- rctx->state = OHS_ASN1_WRITE;
-
- /* fall thru */
- case OHS_ASN1_WRITE:
- n = BIO_get_mem_data(rctx->mem, &p);
-
- i = BIO_write(rctx->io, p + (n - rctx->asn1_len), rctx->asn1_len);
-
- if (i <= 0) {
- if (BIO_should_retry(rctx->io))
- return -1;
- rctx->state = OHS_ERROR;
- return 0;
- }
-
- rctx->asn1_len -= i;
-
- if (rctx->asn1_len > 0)
- goto next_io;
-
- rctx->state = OHS_ASN1_FLUSH;
-
- (void)BIO_reset(rctx->mem);
-
- /* fall thru */
- case OHS_ASN1_FLUSH:
-
- i = BIO_flush(rctx->io);
-
- if (i > 0) {
- rctx->state = OHS_FIRSTLINE;
- goto next_io;
- }
-
- if (BIO_should_retry(rctx->io))
- return -1;
-
- rctx->state = OHS_ERROR;
- return 0;
-
- case OHS_ERROR:
- return 0;
-
- case OHS_FIRSTLINE:
- case OHS_HEADERS:
-
- /* Attempt to read a line in */
-
- next_line:
- /*
- * Due to &%^*$" memory BIO behaviour with BIO_gets we have to check
- * there's a complete line in there before calling BIO_gets or we'll
- * just get a partial read.
- */
- n = BIO_get_mem_data(rctx->mem, &p);
- if ((n <= 0) || !memchr(p, '\n', n)) {
- if (n >= rctx->iobuflen) {
- rctx->state = OHS_ERROR;
- return 0;
- }
- goto next_io;
- }
- n = BIO_gets(rctx->mem, (char *)rctx->iobuf, rctx->iobuflen);
-
- if (n <= 0) {
- if (BIO_should_retry(rctx->mem))
- goto next_io;
- rctx->state = OHS_ERROR;
- return 0;
- }
-
- /* Don't allow excessive lines */
- if (n == rctx->iobuflen) {
- rctx->state = OHS_ERROR;
- return 0;
- }
-
- /* First line */
- if (rctx->state == OHS_FIRSTLINE) {
- if (parse_http_line1((char *)rctx->iobuf)) {
- rctx->state = OHS_HEADERS;
- goto next_line;
- } else {
- rctx->state = OHS_ERROR;
- return 0;
- }
- } else {
- /* Look for blank line: end of headers */
- for (p = rctx->iobuf; *p; p++) {
- if ((*p != '\r') && (*p != '\n'))
- break;
- }
- if (*p)
- goto next_line;
-
- rctx->state = OHS_ASN1_HEADER;
-
- }
-
- /* Fall thru */
-
- case OHS_ASN1_HEADER:
- /*
- * Now reading ASN1 header: can read at least 2 bytes which is enough
- * for ASN1 SEQUENCE header and either length field or at least the
- * length of the length field.
- */
- n = BIO_get_mem_data(rctx->mem, &p);
- if (n < 2)
- goto next_io;
-
- /* Check it is an ASN1 SEQUENCE */
- if (*p++ != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)) {
- rctx->state = OHS_ERROR;
- return 0;
- }
-
- /* Check out length field */
- if (*p & 0x80) {
- /*
- * If MSB set on initial length octet we can now always read 6
- * octets: make sure we have them.
- */
- if (n < 6)
- goto next_io;
- n = *p & 0x7F;
- /* Not NDEF or excessive length */
- if (!n || (n > 4)) {
- rctx->state = OHS_ERROR;
- return 0;
- }
- p++;
- rctx->asn1_len = 0;
- for (i = 0; i < n; i++) {
- rctx->asn1_len <<= 8;
- rctx->asn1_len |= *p++;
- }
-
- if (rctx->asn1_len > rctx->max_resp_len) {
- rctx->state = OHS_ERROR;
- return 0;
- }
-
- rctx->asn1_len += n + 2;
- } else
- rctx->asn1_len = *p + 2;
-
- rctx->state = OHS_ASN1_CONTENT;
-
- /* Fall thru */
-
- case OHS_ASN1_CONTENT:
- n = BIO_get_mem_data(rctx->mem, NULL);
- if (n < (int)rctx->asn1_len)
- goto next_io;
-
- rctx->state = OHS_DONE;
- return 1;
-
- case OHS_DONE:
- return 1;
-
- }
-
- return 0;
-
-}
-
-int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx)
-{
- return OCSP_REQ_CTX_nbio_d2i(rctx,
- (ASN1_VALUE **)presp,
- ASN1_ITEM_rptr(OCSP_RESPONSE));
-}
-
-/* Blocking OCSP request handler: now a special case of non-blocking I/O */
-
-OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req)
-{
- OCSP_RESPONSE *resp = NULL;
- OCSP_REQ_CTX *ctx;
- int rv;
-
- ctx = OCSP_sendreq_new(b, path, req, -1);
-
- if (ctx == NULL)
- return NULL;
-
- do {
- rv = OCSP_sendreq_nbio(&resp, ctx);
- } while ((rv == -1) && BIO_should_retry(b));
-
- OCSP_REQ_CTX_free(ctx);
-
- if (rv)
- return resp;
-
- return NULL;
-}
diff --git a/crypto/ocsp/ocsp_http.c b/crypto/ocsp/ocsp_http.c
new file mode 100644
index 000000000000..e8b6406d3c38
--- /dev/null
+++ b/crypto/ocsp/ocsp_http.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/ocsp.h>
+#include <openssl/http.h>
+
+#ifndef OPENSSL_NO_OCSP
+
+OSSL_HTTP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path,
+ const OCSP_REQUEST *req, int buf_size)
+{
+ OSSL_HTTP_REQ_CTX *rctx = OSSL_HTTP_REQ_CTX_new(io, io, buf_size);
+
+ if (rctx == NULL)
+ return NULL;
+ /*-
+ * by default:
+ * no bio_update_fn (and consequently no arg)
+ * no ssl
+ * no proxy
+ * no timeout (blocking indefinitely)
+ * no expected content type
+ * max_resp_len = 100 KiB
+ */
+ if (!OSSL_HTTP_REQ_CTX_set_request_line(rctx, 1 /* POST */,
+ NULL, NULL, path))
+ goto err;
+ /* by default, no extra headers */
+ if (!OSSL_HTTP_REQ_CTX_set_expected(rctx,
+ NULL /* content_type */, 1 /* asn1 */,
+ 0 /* timeout */, 0 /* keep_alive */))
+ goto err;
+ if (req != NULL
+ && !OSSL_HTTP_REQ_CTX_set1_req(rctx, "application/ocsp-request",
+ ASN1_ITEM_rptr(OCSP_REQUEST),
+ (const ASN1_VALUE *)req))
+ goto err;
+ return rctx;
+
+ err:
+ OSSL_HTTP_REQ_CTX_free(rctx);
+ return NULL;
+}
+
+OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req)
+{
+ OCSP_RESPONSE *resp = NULL;
+ OSSL_HTTP_REQ_CTX *ctx;
+ BIO *mem;
+
+ ctx = OCSP_sendreq_new(b, path, req, 0 /* default buf_size */);
+ if (ctx == NULL)
+ return NULL;
+ mem = OSSL_HTTP_REQ_CTX_exchange(ctx);
+ /* ASN1_item_d2i_bio handles NULL bio gracefully */
+ resp = (OCSP_RESPONSE *)ASN1_item_d2i_bio(ASN1_ITEM_rptr(OCSP_RESPONSE),
+ mem, NULL);
+
+ OSSL_HTTP_REQ_CTX_free(ctx);
+ return resp;
+}
+#endif /* !defined(OPENSSL_NO_OCSP) */
diff --git a/crypto/ocsp/ocsp_lib.c b/crypto/ocsp/ocsp_lib.c
index 37ac6c03fd04..285634dec37b 100644
--- a/crypto/ocsp/ocsp_lib.c
+++ b/crypto/ocsp/ocsp_lib.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -22,9 +22,10 @@
OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject,
const X509 *issuer)
{
- X509_NAME *iname;
+ const X509_NAME *iname;
const ASN1_INTEGER *serial;
ASN1_BIT_STRING *ikey;
+
if (!dgst)
dgst = EVP_sha1();
if (subject) {
@@ -54,8 +55,8 @@ OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
alg = &cid->hashAlgorithm;
ASN1_OBJECT_free(alg->algorithm);
- if ((nid = EVP_MD_type(dgst)) == NID_undef) {
- OCSPerr(OCSP_F_OCSP_CERT_ID_NEW, OCSP_R_UNKNOWN_NID);
+ if ((nid = EVP_MD_get_type(dgst)) == NID_undef) {
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_UNKNOWN_NID);
goto err;
}
if ((alg->algorithm = OBJ_nid2obj(nid)) == NULL)
@@ -82,7 +83,7 @@ OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
}
return cid;
digerr:
- OCSPerr(OCSP_F_OCSP_CERT_ID_NEW, OCSP_R_DIGEST_ERR);
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_DIGEST_ERR);
err:
OCSP_CERTID_free(cid);
return NULL;
@@ -109,114 +110,4 @@ int OCSP_id_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b)
return ASN1_INTEGER_cmp(&a->serialNumber, &b->serialNumber);
}
-/*
- * Parse a URL and split it up into host, port and path components and
- * whether it is SSL.
- */
-
-int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath,
- int *pssl)
-{
- char *p, *buf;
-
- char *host, *port;
-
- *phost = NULL;
- *pport = NULL;
- *ppath = NULL;
-
- /* dup the buffer since we are going to mess with it */
- buf = OPENSSL_strdup(url);
- if (!buf)
- goto mem_err;
-
- /* Check for initial colon */
- p = strchr(buf, ':');
-
- if (!p)
- goto parse_err;
-
- *(p++) = '\0';
-
- if (strcmp(buf, "http") == 0) {
- *pssl = 0;
- port = "80";
- } else if (strcmp(buf, "https") == 0) {
- *pssl = 1;
- port = "443";
- } else
- goto parse_err;
-
- /* Check for double slash */
- if ((p[0] != '/') || (p[1] != '/'))
- goto parse_err;
-
- p += 2;
-
- host = p;
-
- /* Check for trailing part of path */
-
- p = strchr(p, '/');
-
- if (!p)
- *ppath = OPENSSL_strdup("/");
- else {
- *ppath = OPENSSL_strdup(p);
- /* Set start of path to 0 so hostname is valid */
- *p = '\0';
- }
-
- if (!*ppath)
- goto mem_err;
-
- p = host;
- if (host[0] == '[') {
- /* ipv6 literal */
- host++;
- p = strchr(host, ']');
- if (!p)
- goto parse_err;
- *p = '\0';
- p++;
- }
-
- /* Look for optional ':' for port number */
- if ((p = strchr(p, ':'))) {
- *p = 0;
- port = p + 1;
- }
-
- *pport = OPENSSL_strdup(port);
- if (!*pport)
- goto mem_err;
-
- *phost = OPENSSL_strdup(host);
-
- if (!*phost)
- goto mem_err;
-
- OPENSSL_free(buf);
-
- return 1;
-
- mem_err:
- OCSPerr(OCSP_F_OCSP_PARSE_URL, ERR_R_MALLOC_FAILURE);
- goto err;
-
- parse_err:
- OCSPerr(OCSP_F_OCSP_PARSE_URL, OCSP_R_ERROR_PARSING_URL);
-
- err:
- OPENSSL_free(buf);
- OPENSSL_free(*ppath);
- *ppath = NULL;
- OPENSSL_free(*pport);
- *pport = NULL;
- OPENSSL_free(*phost);
- *phost = NULL;
- return 0;
-
-}
-
IMPLEMENT_ASN1_DUP_FUNCTION(OCSP_CERTID)
diff --git a/crypto/ocsp/ocsp_local.h b/crypto/ocsp/ocsp_local.h
index 36646fdfc97a..e1633403c685 100644
--- a/crypto/ocsp/ocsp_local.h
+++ b/crypto/ocsp/ocsp_local.h
@@ -1,12 +1,14 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#include "crypto/x509.h" /* for ossl_x509_add_cert_new() */
+
/*- CertID ::= SEQUENCE {
* hashAlgorithm AlgorithmIdentifier,
* issuerNameHash OCTET STRING, -- Hash of Issuer's DN
@@ -215,22 +217,30 @@ struct ocsp_service_locator_st {
STACK_OF(ACCESS_DESCRIPTION) *locator;
};
-# define OCSP_REQUEST_sign(o,pkey,md) \
- ASN1_item_sign(ASN1_ITEM_rptr(OCSP_REQINFO),\
- &(o)->optionalSignature->signatureAlgorithm,NULL,\
- (o)->optionalSignature->signature,&(o)->tbsRequest,pkey,md)
-
-# define OCSP_BASICRESP_sign(o,pkey,md,d) \
- ASN1_item_sign(ASN1_ITEM_rptr(OCSP_RESPDATA),&(o)->signatureAlgorithm,\
- NULL,(o)->signature,&(o)->tbsResponseData,pkey,md)
-
-# define OCSP_BASICRESP_sign_ctx(o,ctx,d) \
- ASN1_item_sign_ctx(ASN1_ITEM_rptr(OCSP_RESPDATA),&(o)->signatureAlgorithm,\
- NULL,(o)->signature,&(o)->tbsResponseData,ctx)
-
-# define OCSP_REQUEST_verify(a,r) ASN1_item_verify(ASN1_ITEM_rptr(OCSP_REQINFO),\
- &(a)->optionalSignature->signatureAlgorithm,\
- (a)->optionalSignature->signature,&(a)->tbsRequest,r)
-
-# define OCSP_BASICRESP_verify(a,r,d) ASN1_item_verify(ASN1_ITEM_rptr(OCSP_RESPDATA),\
- &(a)->signatureAlgorithm,(a)->signature,&(a)->tbsResponseData,r)
+# define OCSP_REQUEST_sign(o, pkey, md, libctx, propq)\
+ ASN1_item_sign_ex(ASN1_ITEM_rptr(OCSP_REQINFO),\
+ &(o)->optionalSignature->signatureAlgorithm, NULL,\
+ (o)->optionalSignature->signature, &(o)->tbsRequest,\
+ NULL, pkey, md, libctx, propq)
+
+# define OCSP_BASICRESP_sign(o, pkey, md, d, libctx, propq)\
+ ASN1_item_sign_ex(ASN1_ITEM_rptr(OCSP_RESPDATA),\
+ &(o)->signatureAlgorithm, NULL,\
+ (o)->signature, &(o)->tbsResponseData,\
+ NULL, pkey, md, libctx, propq)
+
+# define OCSP_BASICRESP_sign_ctx(o, ctx, d)\
+ ASN1_item_sign_ctx(ASN1_ITEM_rptr(OCSP_RESPDATA),\
+ &(o)->signatureAlgorithm, NULL,\
+ (o)->signature, &(o)->tbsResponseData, ctx)
+
+# define OCSP_REQUEST_verify(a, r, libctx, propq)\
+ ASN1_item_verify_ex(ASN1_ITEM_rptr(OCSP_REQINFO),\
+ &(a)->optionalSignature->signatureAlgorithm,\
+ (a)->optionalSignature->signature, &(a)->tbsRequest,\
+ NULL, r, libctx, propq)
+
+# define OCSP_BASICRESP_verify(a, r, libctx, propq)\
+ ASN1_item_verify_ex(ASN1_ITEM_rptr(OCSP_RESPDATA),\
+ &(a)->signatureAlgorithm, (a)->signature,\
+ &(a)->tbsResponseData, NULL, r, libctx, propq)
diff --git a/crypto/ocsp/ocsp_prn.c b/crypto/ocsp/ocsp_prn.c
index 1965f2a183b3..654ddbc7fff3 100644
--- a/crypto/ocsp/ocsp_prn.c
+++ b/crypto/ocsp/ocsp_prn.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/ocsp/ocsp_srv.c b/crypto/ocsp/ocsp_srv.c
index e35fc52fd944..dbb6e760b20c 100644
--- a/crypto/ocsp/ocsp_srv.c
+++ b/crypto/ocsp/ocsp_srv.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -20,7 +20,6 @@
* Utility functions related to sending OCSP responses and extracting
* relevant information from the request.
*/
-
int OCSP_request_onereq_count(OCSP_REQUEST *req)
{
return sk_OCSP_ONEREQ_num(req->tbsRequest.requestList);
@@ -117,7 +116,7 @@ OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp,
switch (cs->type = status) {
case V_OCSP_CERTSTATUS_REVOKED:
if (!revtime) {
- OCSPerr(OCSP_F_OCSP_BASIC_ADD1_STATUS, OCSP_R_NO_REVOKED_TIME);
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_NO_REVOKED_TIME);
goto err;
}
if ((cs->value.revoked = ri = OCSP_REVOKEDINFO_new()) == NULL)
@@ -155,17 +154,9 @@ OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp,
}
/* Add a certificate to an OCSP request */
-
int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert)
{
- if (resp->certs == NULL
- && (resp->certs = sk_X509_new_null()) == NULL)
- return 0;
-
- if (!sk_X509_push(resp->certs, cert))
- return 0;
- X509_up_ref(cert);
- return 1;
+ return ossl_x509_add_cert_new(&resp->certs, cert, X509_ADD_FLAG_UP_REF);
}
/*
@@ -173,35 +164,28 @@ int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert)
* set the responderID to the subject name in the signer's certificate, and
* include one or more optional certificates in the response.
*/
-
int OCSP_basic_sign_ctx(OCSP_BASICRESP *brsp,
X509 *signer, EVP_MD_CTX *ctx,
STACK_OF(X509) *certs, unsigned long flags)
{
- int i;
OCSP_RESPID *rid;
EVP_PKEY *pkey;
- if (ctx == NULL || EVP_MD_CTX_pkey_ctx(ctx) == NULL) {
- OCSPerr(OCSP_F_OCSP_BASIC_SIGN_CTX, OCSP_R_NO_SIGNER_KEY);
+ if (ctx == NULL || EVP_MD_CTX_get_pkey_ctx(ctx) == NULL) {
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_NO_SIGNER_KEY);
goto err;
}
- pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx));
+ pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
if (pkey == NULL || !X509_check_private_key(signer, pkey)) {
- OCSPerr(OCSP_F_OCSP_BASIC_SIGN_CTX,
- OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
goto err;
}
if (!(flags & OCSP_NOCERTS)) {
- if (!OCSP_basic_add1_cert(brsp, signer))
+ if (!OCSP_basic_add1_cert(brsp, signer)
+ || !X509_add_certs(brsp->certs, certs, X509_ADD_FLAG_UP_REF))
goto err;
- for (i = 0; i < sk_X509_num(certs); i++) {
- X509 *tmpcert = sk_X509_value(certs, i);
- if (!OCSP_basic_add1_cert(brsp, tmpcert))
- goto err;
- }
}
rid = &brsp->tbsResponseData.responderId;
@@ -220,7 +204,6 @@ int OCSP_basic_sign_ctx(OCSP_BASICRESP *brsp,
* Right now, I think that not doing double hashing is the right thing.
* -- Richard Levitte
*/
-
if (!OCSP_BASICRESP_sign_ctx(brsp, ctx, 0))
goto err;
@@ -240,7 +223,8 @@ int OCSP_basic_sign(OCSP_BASICRESP *brsp,
if (ctx == NULL)
return 0;
- if (!EVP_DigestSignInit(ctx, &pkctx, dgst, NULL, key)) {
+ if (!EVP_DigestSignInit_ex(ctx, &pkctx, EVP_MD_get0_name(dgst),
+ signer->libctx, signer->propq, key, NULL)) {
EVP_MD_CTX_free(ctx);
return 0;
}
@@ -259,45 +243,69 @@ int OCSP_RESPID_set_by_name(OCSP_RESPID *respid, X509 *cert)
return 1;
}
-int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert)
+int OCSP_RESPID_set_by_key_ex(OCSP_RESPID *respid, X509 *cert,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
ASN1_OCTET_STRING *byKey = NULL;
unsigned char md[SHA_DIGEST_LENGTH];
+ EVP_MD *sha1 = EVP_MD_fetch(libctx, "SHA1", propq);
+ int ret = 0;
- /* RFC2560 requires SHA1 */
- if (!X509_pubkey_digest(cert, EVP_sha1(), md, NULL))
+ if (sha1 == NULL)
return 0;
+ /* RFC2560 requires SHA1 */
+ if (!X509_pubkey_digest(cert, sha1, md, NULL))
+ goto err;
+
byKey = ASN1_OCTET_STRING_new();
if (byKey == NULL)
- return 0;
+ goto err;
if (!(ASN1_OCTET_STRING_set(byKey, md, SHA_DIGEST_LENGTH))) {
ASN1_OCTET_STRING_free(byKey);
- return 0;
+ goto err;
}
respid->type = V_OCSP_RESPID_KEY;
respid->value.byKey = byKey;
- return 1;
+ ret = 1;
+ err:
+ EVP_MD_free(sha1);
+ return ret;
}
-int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert)
+int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert)
{
+ if (cert == NULL)
+ return 0;
+ return OCSP_RESPID_set_by_key_ex(respid, cert, cert->libctx, cert->propq);
+}
+
+int OCSP_RESPID_match_ex(OCSP_RESPID *respid, X509 *cert, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ EVP_MD *sha1 = NULL;
+ int ret = 0;
+
if (respid->type == V_OCSP_RESPID_KEY) {
unsigned char md[SHA_DIGEST_LENGTH];
+ sha1 = EVP_MD_fetch(libctx, "SHA1", propq);
+ if (sha1 == NULL)
+ goto err;
+
if (respid->value.byKey == NULL)
- return 0;
+ goto err;
/* RFC2560 requires SHA1 */
- if (!X509_pubkey_digest(cert, EVP_sha1(), md, NULL))
- return 0;
+ if (!X509_pubkey_digest(cert, sha1, md, NULL))
+ goto err;
- return (ASN1_STRING_length(respid->value.byKey) == SHA_DIGEST_LENGTH)
- && (memcmp(ASN1_STRING_get0_data(respid->value.byKey), md,
- SHA_DIGEST_LENGTH) == 0);
+ ret = (ASN1_STRING_length(respid->value.byKey) == SHA_DIGEST_LENGTH)
+ && (memcmp(ASN1_STRING_get0_data(respid->value.byKey), md,
+ SHA_DIGEST_LENGTH) == 0);
} else if (respid->type == V_OCSP_RESPID_NAME) {
if (respid->value.byName == NULL)
return 0;
@@ -306,5 +314,14 @@ int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert)
X509_get_subject_name(cert)) == 0;
}
- return 0;
+ err:
+ EVP_MD_free(sha1);
+ return ret;
+}
+
+int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert)
+{
+ if (cert == NULL)
+ return 0;
+ return OCSP_RESPID_match_ex(respid, cert, cert->libctx, cert->propq);
}
diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c
index e87b71c0c791..fa07539d7e86 100644
--- a/crypto/ocsp/ocsp_vfy.c
+++ b/crypto/ocsp/ocsp_vfy.c
@@ -1,16 +1,17 @@
/*
- * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#include <string.h>
#include <openssl/ocsp.h>
-#include "ocsp_local.h"
#include <openssl/err.h>
-#include <string.h>
+#include "internal/sizes.h"
+#include "ocsp_local.h"
static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs,
STACK_OF(X509) *certs, unsigned long flags);
@@ -22,80 +23,107 @@ static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid,
STACK_OF(OCSP_SINGLERESP) *sresp);
static int ocsp_check_delegated(X509 *x);
static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req,
- X509_NAME *nm, STACK_OF(X509) *certs,
+ const X509_NAME *nm, STACK_OF(X509) *certs,
unsigned long flags);
-/* Verify a basic response message */
+/* Returns 1 on success, 0 on failure, or -1 on fatal error */
+static int ocsp_verify_signer(X509 *signer, int response,
+ X509_STORE *st, unsigned long flags,
+ STACK_OF(X509) *untrusted, STACK_OF(X509) **chain)
+{
+ X509_STORE_CTX *ctx = X509_STORE_CTX_new();
+ X509_VERIFY_PARAM *vp;
+ int ret = -1;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_OCSP, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+ if (!X509_STORE_CTX_init(ctx, st, signer, untrusted)) {
+ ERR_raise(ERR_LIB_OCSP, ERR_R_X509_LIB);
+ goto end;
+ }
+ if ((vp = X509_STORE_CTX_get0_param(ctx)) == NULL)
+ goto end;
+ if ((flags & OCSP_PARTIAL_CHAIN) != 0)
+ X509_VERIFY_PARAM_set_flags(vp, X509_V_FLAG_PARTIAL_CHAIN);
+ if (response
+ && X509_get_ext_by_NID(signer, NID_id_pkix_OCSP_noCheck, -1) >= 0)
+ /*
+ * Locally disable revocation status checking for OCSP responder cert.
+ * Done here for CRLs; should be done also for OCSP-based checks.
+ */
+ X509_VERIFY_PARAM_clear_flags(vp, X509_V_FLAG_CRL_CHECK);
+ X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_OCSP_HELPER);
+ X509_STORE_CTX_set_trust(ctx, X509_TRUST_OCSP_REQUEST);
+
+ ret = X509_verify_cert(ctx);
+ if (ret <= 0) {
+ int err = X509_STORE_CTX_get_error(ctx);
+
+ ERR_raise_data(ERR_LIB_OCSP, OCSP_R_CERTIFICATE_VERIFY_ERROR,
+ "Verify error: %s", X509_verify_cert_error_string(err));
+ goto end;
+ }
+ if (chain != NULL)
+ *chain = X509_STORE_CTX_get1_chain(ctx);
+
+ end:
+ X509_STORE_CTX_free(ctx);
+ return ret;
+}
+
+static int ocsp_verify(OCSP_REQUEST *req, OCSP_BASICRESP *bs,
+ X509 *signer, unsigned long flags)
+{
+ EVP_PKEY *skey;
+ int ret = 1;
+
+ if ((flags & OCSP_NOSIGS) == 0) {
+ if ((skey = X509_get0_pubkey(signer)) == NULL) {
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_NO_SIGNER_KEY);
+ return -1;
+ }
+ if (req != NULL)
+ ret = OCSP_REQUEST_verify(req, skey, signer->libctx, signer->propq);
+ else
+ ret = OCSP_BASICRESP_verify(bs, skey, signer->libctx, signer->propq);
+ if (ret <= 0)
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_SIGNATURE_FAILURE);
+ }
+ return ret;
+}
+/* Verify a basic response message */
int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
X509_STORE *st, unsigned long flags)
{
X509 *signer, *x;
STACK_OF(X509) *chain = NULL;
STACK_OF(X509) *untrusted = NULL;
- X509_STORE_CTX *ctx = NULL;
- int i, ret = ocsp_find_signer(&signer, bs, certs, flags);
+ int ret = ocsp_find_signer(&signer, bs, certs, flags);
- if (!ret) {
- OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,
- OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
+ if (ret == 0) {
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
goto end;
}
- ctx = X509_STORE_CTX_new();
- if (ctx == NULL) {
- OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_MALLOC_FAILURE);
- goto f_err;
- }
- if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
+ if ((ret == 2) && (flags & OCSP_TRUSTOTHER) != 0)
flags |= OCSP_NOVERIFY;
- if (!(flags & OCSP_NOSIGS)) {
- EVP_PKEY *skey;
- skey = X509_get0_pubkey(signer);
- if (skey == NULL) {
- OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_NO_SIGNER_KEY);
- goto err;
- }
- ret = OCSP_BASICRESP_verify(bs, skey, 0);
- if (ret <= 0) {
- OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNATURE_FAILURE);
- goto end;
- }
- }
- if (!(flags & OCSP_NOVERIFY)) {
- int init_res;
- if (flags & OCSP_NOCHAIN) {
- untrusted = NULL;
- } else if (bs->certs && certs) {
- untrusted = sk_X509_dup(bs->certs);
- for (i = 0; i < sk_X509_num(certs); i++) {
- if (!sk_X509_push(untrusted, sk_X509_value(certs, i))) {
- OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_MALLOC_FAILURE);
- goto f_err;
- }
- }
- } else if (certs != NULL) {
- untrusted = certs;
- } else {
- untrusted = bs->certs;
- }
- init_res = X509_STORE_CTX_init(ctx, st, signer, untrusted);
- if (!init_res) {
- OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_X509_LIB);
- goto f_err;
- }
- X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_OCSP_HELPER);
- ret = X509_verify_cert(ctx);
- chain = X509_STORE_CTX_get1_chain(ctx);
- if (ret <= 0) {
- i = X509_STORE_CTX_get_error(ctx);
- OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,
- OCSP_R_CERTIFICATE_VERIFY_ERROR);
- ERR_add_error_data(2, "Verify error:",
- X509_verify_cert_error_string(i));
- goto end;
+ if ((ret = ocsp_verify(NULL, bs, signer, flags)) <= 0)
+ goto end;
+ if ((flags & OCSP_NOVERIFY) == 0) {
+ ret = -1;
+ if ((flags & OCSP_NOCHAIN) == 0) {
+ if ((untrusted = sk_X509_dup(bs->certs)) == NULL)
+ goto end;
+ if (!X509_add_certs(untrusted, certs, X509_ADD_FLAG_DEFAULT))
+ goto end;
}
- if (flags & OCSP_NOCHECKS) {
+ ret = ocsp_verify_signer(signer, 1, st, flags, untrusted, &chain);
+ if (ret <= 0)
+ goto end;
+ if ((flags & OCSP_NOCHECKS) != 0) {
ret = 1;
goto end;
}
@@ -113,38 +141,28 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
* Easy case: explicitly trusted. Get root CA and check for explicit
* trust
*/
- if (flags & OCSP_NOEXPLICIT)
+ if ((flags & OCSP_NOEXPLICIT) != 0)
goto end;
x = sk_X509_value(chain, sk_X509_num(chain) - 1);
if (X509_check_trust(x, NID_OCSP_sign, 0) != X509_TRUST_TRUSTED) {
- OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_ROOT_CA_NOT_TRUSTED);
- goto err;
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_ROOT_CA_NOT_TRUSTED);
+ ret = 0;
+ goto end;
}
ret = 1;
}
+
end:
- X509_STORE_CTX_free(ctx);
sk_X509_pop_free(chain, X509_free);
- if (bs->certs && certs)
- sk_X509_free(untrusted);
+ sk_X509_free(untrusted);
return ret;
-
- err:
- ret = 0;
- goto end;
- f_err:
- ret = -1;
- goto end;
}
int OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer,
STACK_OF(X509) *extra_certs)
{
- int ret;
-
- ret = ocsp_find_signer(signer, bs, extra_certs, 0);
- return (ret > 0) ? 1 : 0;
+ return ocsp_find_signer(signer, bs, extra_certs, 0) > 0;
}
static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs,
@@ -152,11 +170,12 @@ static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs,
{
X509 *signer;
OCSP_RESPID *rid = &bs->tbsResponseData.responderId;
- if ((signer = ocsp_find_signer_sk(certs, rid))) {
+
+ if ((signer = ocsp_find_signer_sk(certs, rid)) != NULL) {
*psigner = signer;
return 2;
}
- if (!(flags & OCSP_NOINTERN) &&
+ if ((flags & OCSP_NOINTERN) == 0 &&
(signer = ocsp_find_signer_sk(bs->certs, rid))) {
*psigner = signer;
return 1;
@@ -169,8 +188,9 @@ static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs,
static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
{
- int i;
+ int i, r;
unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
+ EVP_MD *md;
X509 *x;
/* Easy if lookup by name */
@@ -185,42 +205,47 @@ static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
keyhash = id->value.byKey->data;
/* Calculate hash of each key and compare */
for (i = 0; i < sk_X509_num(certs); i++) {
- x = sk_X509_value(certs, i);
- X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
- if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
- return x;
+ if ((x = sk_X509_value(certs, i)) != NULL) {
+ if ((md = EVP_MD_fetch(x->libctx, SN_sha1, x->propq)) == NULL)
+ break;
+ r = X509_pubkey_digest(x, md, tmphash, NULL);
+ EVP_MD_free(md);
+ if (!r)
+ break;
+ if (memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH) == 0)
+ return x;
+ }
}
return NULL;
}
static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain)
{
- STACK_OF(OCSP_SINGLERESP) *sresp;
+ STACK_OF(OCSP_SINGLERESP) *sresp = bs->tbsResponseData.responses;
X509 *signer, *sca;
OCSP_CERTID *caid = NULL;
- int i;
- sresp = bs->tbsResponseData.responses;
+ int ret;
if (sk_X509_num(chain) <= 0) {
- OCSPerr(OCSP_F_OCSP_CHECK_ISSUER, OCSP_R_NO_CERTIFICATES_IN_CHAIN);
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_NO_CERTIFICATES_IN_CHAIN);
return -1;
}
/* See if the issuer IDs match. */
- i = ocsp_check_ids(sresp, &caid);
+ ret = ocsp_check_ids(sresp, &caid);
/* If ID mismatch or other error then return */
- if (i <= 0)
- return i;
+ if (ret <= 0)
+ return ret;
signer = sk_X509_value(chain, 0);
/* Check to see if OCSP responder CA matches request CA */
if (sk_X509_num(chain) > 1) {
sca = sk_X509_value(chain, 1);
- i = ocsp_match_issuerid(sca, caid, sresp);
- if (i < 0)
- return i;
- if (i) {
+ ret = ocsp_match_issuerid(sca, caid, sresp);
+ if (ret < 0)
+ return ret;
+ if (ret != 0) {
/* We have a match, if extensions OK then success */
if (ocsp_check_delegated(signer))
return 1;
@@ -246,15 +271,13 @@ static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret)
idcount = sk_OCSP_SINGLERESP_num(sresp);
if (idcount <= 0) {
- OCSPerr(OCSP_F_OCSP_CHECK_IDS,
- OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA);
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA);
return -1;
}
cid = sk_OCSP_SINGLERESP_value(sresp, 0)->certId;
*ret = NULL;
-
for (i = 1; i < idcount; i++) {
tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId;
/* Check to see if IDs match */
@@ -273,52 +296,76 @@ static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret)
return 1;
}
+/*
+ * Match the certificate issuer ID.
+ * Returns -1 on fatal error, 0 if there is no match and 1 if there is a match.
+ */
static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid,
STACK_OF(OCSP_SINGLERESP) *sresp)
{
+ int ret = -1;
+ EVP_MD *dgst = NULL;
+
/* If only one ID to match then do it */
- if (cid) {
- const EVP_MD *dgst;
- X509_NAME *iname;
+ if (cid != NULL) {
+ char name[OSSL_MAX_NAME_SIZE];
+ const X509_NAME *iname;
int mdlen;
unsigned char md[EVP_MAX_MD_SIZE];
- if ((dgst = EVP_get_digestbyobj(cid->hashAlgorithm.algorithm))
- == NULL) {
- OCSPerr(OCSP_F_OCSP_MATCH_ISSUERID,
- OCSP_R_UNKNOWN_MESSAGE_DIGEST);
- return -1;
+
+ OBJ_obj2txt(name, sizeof(name), cid->hashAlgorithm.algorithm, 0);
+
+ (void)ERR_set_mark();
+ dgst = EVP_MD_fetch(NULL, name, NULL);
+ if (dgst == NULL)
+ dgst = (EVP_MD *)EVP_get_digestbyname(name);
+
+ if (dgst == NULL) {
+ (void)ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_UNKNOWN_MESSAGE_DIGEST);
+ goto end;
}
+ (void)ERR_pop_to_mark();
- mdlen = EVP_MD_size(dgst);
- if (mdlen < 0)
- return -1;
- if ((cid->issuerNameHash.length != mdlen) ||
- (cid->issuerKeyHash.length != mdlen))
- return 0;
+ mdlen = EVP_MD_get_size(dgst);
+ if (mdlen < 0) {
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_DIGEST_SIZE_ERR);
+ goto end;
+ }
+ if (cid->issuerNameHash.length != mdlen ||
+ cid->issuerKeyHash.length != mdlen) {
+ ret = 0;
+ goto end;
+ }
iname = X509_get_subject_name(cert);
if (!X509_NAME_digest(iname, dgst, md, NULL))
- return -1;
- if (memcmp(md, cid->issuerNameHash.data, mdlen))
- return 0;
- X509_pubkey_digest(cert, dgst, md, NULL);
- if (memcmp(md, cid->issuerKeyHash.data, mdlen))
- return 0;
-
- return 1;
-
+ goto end;
+ if (memcmp(md, cid->issuerNameHash.data, mdlen) != 0) {
+ ret = 0;
+ goto end;
+ }
+ if (!X509_pubkey_digest(cert, dgst, md, NULL)) {
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_DIGEST_ERR);
+ goto end;
+ }
+ ret = memcmp(md, cid->issuerKeyHash.data, mdlen) == 0;
+ goto end;
} else {
/* We have to match the whole lot */
- int i, ret;
+ int i;
OCSP_CERTID *tmpid;
+
for (i = 0; i < sk_OCSP_SINGLERESP_num(sresp); i++) {
tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId;
ret = ocsp_match_issuerid(cert, tmpid, NULL);
if (ret <= 0)
return ret;
}
- return 1;
}
-
+ return 1;
+end:
+ EVP_MD_free(dgst);
+ return ret;
}
static int ocsp_check_delegated(X509 *x)
@@ -326,108 +373,66 @@ static int ocsp_check_delegated(X509 *x)
if ((X509_get_extension_flags(x) & EXFLAG_XKUSAGE)
&& (X509_get_extended_key_usage(x) & XKU_OCSP_SIGN))
return 1;
- OCSPerr(OCSP_F_OCSP_CHECK_DELEGATED, OCSP_R_MISSING_OCSPSIGNING_USAGE);
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_MISSING_OCSPSIGNING_USAGE);
return 0;
}
/*
- * Verify an OCSP request. This is fortunately much easier than OCSP response
- * verify. Just find the signers certificate and verify it against a given
- * trust value.
+ * Verify an OCSP request. This is much easier than OCSP response verify.
+ * Just find the signer's certificate and verify it against a given trust value.
+ * Returns 1 on success, 0 on failure and on fatal error.
*/
-
int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs,
X509_STORE *store, unsigned long flags)
{
X509 *signer;
- X509_NAME *nm;
+ const X509_NAME *nm;
GENERAL_NAME *gen;
- int ret = 0;
- X509_STORE_CTX *ctx = X509_STORE_CTX_new();
-
- if (ctx == NULL) {
- OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, ERR_R_MALLOC_FAILURE);
- goto err;
- }
+ int ret;
if (!req->optionalSignature) {
- OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_REQUEST_NOT_SIGNED);
- goto err;
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_REQUEST_NOT_SIGNED);
+ return 0;
}
gen = req->tbsRequest.requestorName;
if (!gen || gen->type != GEN_DIRNAME) {
- OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,
- OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE);
- goto err;
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE);
+ return 0; /* not returning -1 here for backward compatibility*/
}
nm = gen->d.directoryName;
ret = ocsp_req_find_signer(&signer, req, nm, certs, flags);
if (ret <= 0) {
- OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,
- OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
- goto err;
+ ERR_raise(ERR_LIB_OCSP, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
+ return 0; /* not returning -1 here for backward compatibility*/
}
- if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
+ if ((ret == 2) && (flags & OCSP_TRUSTOTHER) != 0)
flags |= OCSP_NOVERIFY;
- if (!(flags & OCSP_NOSIGS)) {
- EVP_PKEY *skey;
- skey = X509_get0_pubkey(signer);
- ret = OCSP_REQUEST_verify(req, skey);
- if (ret <= 0) {
- OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_SIGNATURE_FAILURE);
- goto err;
- }
- }
- if (!(flags & OCSP_NOVERIFY)) {
- int init_res;
- if (flags & OCSP_NOCHAIN)
- init_res = X509_STORE_CTX_init(ctx, store, signer, NULL);
- else
- init_res = X509_STORE_CTX_init(ctx, store, signer,
- req->optionalSignature->certs);
- if (!init_res) {
- OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, ERR_R_X509_LIB);
- goto err;
- }
-
- X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_OCSP_HELPER);
- X509_STORE_CTX_set_trust(ctx, X509_TRUST_OCSP_REQUEST);
- ret = X509_verify_cert(ctx);
- if (ret <= 0) {
- ret = X509_STORE_CTX_get_error(ctx);
- OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,
- OCSP_R_CERTIFICATE_VERIFY_ERROR);
- ERR_add_error_data(2, "Verify error:",
- X509_verify_cert_error_string(ret));
- goto err;
- }
- }
- ret = 1;
- goto end;
-
-err:
- ret = 0;
-end:
- X509_STORE_CTX_free(ctx);
- return ret;
+ if ((ret = ocsp_verify(req, NULL, signer, flags)) <= 0)
+ return 0; /* not returning 'ret' here for backward compatibility*/
+ if ((flags & OCSP_NOVERIFY) != 0)
+ return 1;
+ return ocsp_verify_signer(signer, 0, store, flags,
+ (flags & OCSP_NOCHAIN) != 0 ?
+ NULL : req->optionalSignature->certs, NULL) > 0;
+ /* using '> 0' here to avoid breaking backward compatibility returning -1 */
}
static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req,
- X509_NAME *nm, STACK_OF(X509) *certs,
+ const X509_NAME *nm, STACK_OF(X509) *certs,
unsigned long flags)
{
X509 *signer;
- if (!(flags & OCSP_NOINTERN)) {
+
+ if ((flags & OCSP_NOINTERN) == 0) {
signer = X509_find_by_subject(req->optionalSignature->certs, nm);
- if (signer) {
+ if (signer != NULL) {
*psigner = signer;
return 1;
}
}
- signer = X509_find_by_subject(certs, nm);
- if (signer) {
+ if ((signer = X509_find_by_subject(certs, nm)) != NULL) {
*psigner = signer;
return 2;
}
diff --git a/crypto/ocsp/v3_ocsp.c b/crypto/ocsp/v3_ocsp.c
index a174ce15a60d..2250208a1577 100644
--- a/crypto/ocsp/v3_ocsp.c
+++ b/crypto/ocsp/v3_ocsp.c
@@ -1,20 +1,20 @@
/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-# include <stdio.h>
-# include "internal/cryptlib.h"
-# include <openssl/conf.h>
-# include <openssl/asn1.h>
-# include <openssl/ocsp.h>
-# include "ocsp_local.h"
-# include <openssl/x509v3.h>
-# include "../x509v3/ext_dat.h"
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/asn1.h>
+#include <openssl/ocsp.h>
+#include "ocsp_local.h"
+#include <openssl/x509v3.h>
+#include "../x509/ext_dat.h"
/*
* OCSP extensions and a couple of CRL entry extensions
@@ -28,7 +28,7 @@ static int i2r_object(const X509V3_EXT_METHOD *method, void *obj, BIO *out,
int indent);
static void *ocsp_nonce_new(void);
-static int i2d_ocsp_nonce(void *a, unsigned char **pp);
+static int i2d_ocsp_nonce(const void *a, unsigned char **pp);
static void *d2i_ocsp_nonce(void *a, const unsigned char **pp, long length);
static void ocsp_nonce_free(void *a);
static int i2r_ocsp_nonce(const X509V3_EXT_METHOD *method, void *nonce,
@@ -41,7 +41,7 @@ static void *s2i_ocsp_nocheck(const X509V3_EXT_METHOD *method,
static int i2r_ocsp_serviceloc(const X509V3_EXT_METHOD *method, void *in,
BIO *bp, int ind);
-const X509V3_EXT_METHOD v3_ocsp_crlid = {
+const X509V3_EXT_METHOD ossl_v3_ocsp_crlid = {
NID_id_pkix_OCSP_CrlID, 0, ASN1_ITEM_ref(OCSP_CRLID),
0, 0, 0, 0,
0, 0,
@@ -50,7 +50,7 @@ const X509V3_EXT_METHOD v3_ocsp_crlid = {
NULL
};
-const X509V3_EXT_METHOD v3_ocsp_acutoff = {
+const X509V3_EXT_METHOD ossl_v3_ocsp_acutoff = {
NID_id_pkix_OCSP_archiveCutoff, 0, ASN1_ITEM_ref(ASN1_GENERALIZEDTIME),
0, 0, 0, 0,
0, 0,
@@ -59,7 +59,7 @@ const X509V3_EXT_METHOD v3_ocsp_acutoff = {
NULL
};
-const X509V3_EXT_METHOD v3_crl_invdate = {
+const X509V3_EXT_METHOD ossl_v3_crl_invdate = {
NID_invalidity_date, 0, ASN1_ITEM_ref(ASN1_GENERALIZEDTIME),
0, 0, 0, 0,
0, 0,
@@ -68,7 +68,7 @@ const X509V3_EXT_METHOD v3_crl_invdate = {
NULL
};
-const X509V3_EXT_METHOD v3_crl_hold = {
+const X509V3_EXT_METHOD ossl_v3_crl_hold = {
NID_hold_instruction_code, 0, ASN1_ITEM_ref(ASN1_OBJECT),
0, 0, 0, 0,
0, 0,
@@ -77,7 +77,7 @@ const X509V3_EXT_METHOD v3_crl_hold = {
NULL
};
-const X509V3_EXT_METHOD v3_ocsp_nonce = {
+const X509V3_EXT_METHOD ossl_v3_ocsp_nonce = {
NID_id_pkix_OCSP_Nonce, 0, NULL,
ocsp_nonce_new,
ocsp_nonce_free,
@@ -89,7 +89,7 @@ const X509V3_EXT_METHOD v3_ocsp_nonce = {
NULL
};
-const X509V3_EXT_METHOD v3_ocsp_nocheck = {
+const X509V3_EXT_METHOD ossl_v3_ocsp_nocheck = {
NID_id_pkix_OCSP_noCheck, 0, ASN1_ITEM_ref(ASN1_NULL),
0, 0, 0, 0,
0, s2i_ocsp_nocheck,
@@ -98,7 +98,7 @@ const X509V3_EXT_METHOD v3_ocsp_nocheck = {
NULL
};
-const X509V3_EXT_METHOD v3_ocsp_serviceloc = {
+const X509V3_EXT_METHOD ossl_v3_ocsp_serviceloc = {
NID_id_pkix_OCSP_serviceLocator, 0, ASN1_ITEM_ref(OCSP_SERVICELOC),
0, 0, 0, 0,
0, 0,
@@ -170,9 +170,9 @@ static void *ocsp_nonce_new(void)
return ASN1_OCTET_STRING_new();
}
-static int i2d_ocsp_nonce(void *a, unsigned char **pp)
+static int i2d_ocsp_nonce(const void *a, unsigned char **pp)
{
- ASN1_OCTET_STRING *os = a;
+ const ASN1_OCTET_STRING *os = a;
if (pp) {
memcpy(*pp, os->data, os->length);
*pp += os->length;
@@ -203,7 +203,7 @@ static void *d2i_ocsp_nonce(void *a, const unsigned char **pp, long length)
err:
if ((pos == NULL) || (*pos != os))
ASN1_OCTET_STRING_free(os);
- OCSPerr(OCSP_F_D2I_OCSP_NONCE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OCSP, ERR_R_MALLOC_FAILURE);
return NULL;
}
diff --git a/crypto/packet.c b/crypto/packet.c
new file mode 100644
index 000000000000..927bb3f80f6c
--- /dev/null
+++ b/crypto/packet.c
@@ -0,0 +1,512 @@
+/*
+ * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/cryptlib.h"
+#include "internal/packet.h"
+#include <openssl/err.h>
+
+#define DEFAULT_BUF_SIZE 256
+
+int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
+{
+ if (!WPACKET_reserve_bytes(pkt, len, allocbytes))
+ return 0;
+
+ pkt->written += len;
+ pkt->curr += len;
+ return 1;
+}
+
+int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len,
+ unsigned char **allocbytes, size_t lenbytes)
+{
+ if (!WPACKET_start_sub_packet_len__(pkt, lenbytes)
+ || !WPACKET_allocate_bytes(pkt, len, allocbytes)
+ || !WPACKET_close(pkt))
+ return 0;
+
+ return 1;
+}
+
+#define GETBUF(p) (((p)->staticbuf != NULL) \
+ ? (p)->staticbuf \
+ : ((p)->buf != NULL \
+ ? (unsigned char *)(p)->buf->data \
+ : NULL))
+
+int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
+{
+ /* Internal API, so should not fail */
+ if (!ossl_assert(pkt->subs != NULL && len != 0))
+ return 0;
+
+ if (pkt->maxsize - pkt->written < len)
+ return 0;
+
+ if (pkt->buf != NULL && (pkt->buf->length - pkt->written < len)) {
+ size_t newlen;
+ size_t reflen;
+
+ reflen = (len > pkt->buf->length) ? len : pkt->buf->length;
+
+ if (reflen > SIZE_MAX / 2) {
+ newlen = SIZE_MAX;
+ } else {
+ newlen = reflen * 2;
+ if (newlen < DEFAULT_BUF_SIZE)
+ newlen = DEFAULT_BUF_SIZE;
+ }
+ if (BUF_MEM_grow(pkt->buf, newlen) == 0)
+ return 0;
+ }
+ if (allocbytes != NULL) {
+ *allocbytes = WPACKET_get_curr(pkt);
+ if (pkt->endfirst && *allocbytes != NULL)
+ *allocbytes -= len;
+ }
+
+ return 1;
+}
+
+int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len,
+ unsigned char **allocbytes, size_t lenbytes)
+{
+ if (pkt->endfirst && lenbytes > 0)
+ return 0;
+
+ if (!WPACKET_reserve_bytes(pkt, lenbytes + len, allocbytes))
+ return 0;
+
+ if (*allocbytes != NULL)
+ *allocbytes += lenbytes;
+
+ return 1;
+}
+
+static size_t maxmaxsize(size_t lenbytes)
+{
+ if (lenbytes >= sizeof(size_t) || lenbytes == 0)
+ return SIZE_MAX;
+
+ return ((size_t)1 << (lenbytes * 8)) - 1 + lenbytes;
+}
+
+static int wpacket_intern_init_len(WPACKET *pkt, size_t lenbytes)
+{
+ unsigned char *lenchars;
+
+ pkt->curr = 0;
+ pkt->written = 0;
+
+ if ((pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs))) == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (lenbytes == 0)
+ return 1;
+
+ pkt->subs->pwritten = lenbytes;
+ pkt->subs->lenbytes = lenbytes;
+
+ if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars)) {
+ OPENSSL_free(pkt->subs);
+ pkt->subs = NULL;
+ return 0;
+ }
+ pkt->subs->packet_len = 0;
+
+ return 1;
+}
+
+int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len,
+ size_t lenbytes)
+{
+ size_t max = maxmaxsize(lenbytes);
+
+ /* Internal API, so should not fail */
+ if (!ossl_assert(buf != NULL && len > 0))
+ return 0;
+
+ pkt->staticbuf = buf;
+ pkt->buf = NULL;
+ pkt->maxsize = (max < len) ? max : len;
+ pkt->endfirst = 0;
+
+ return wpacket_intern_init_len(pkt, lenbytes);
+}
+
+int WPACKET_init_der(WPACKET *pkt, unsigned char *buf, size_t len)
+{
+ /* Internal API, so should not fail */
+ if (!ossl_assert(buf != NULL && len > 0))
+ return 0;
+
+ pkt->staticbuf = buf;
+ pkt->buf = NULL;
+ pkt->maxsize = len;
+ pkt->endfirst = 1;
+
+ return wpacket_intern_init_len(pkt, 0);
+}
+
+int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes)
+{
+ /* Internal API, so should not fail */
+ if (!ossl_assert(buf != NULL))
+ return 0;
+
+ pkt->staticbuf = NULL;
+ pkt->buf = buf;
+ pkt->maxsize = maxmaxsize(lenbytes);
+ pkt->endfirst = 0;
+
+ return wpacket_intern_init_len(pkt, lenbytes);
+}
+
+int WPACKET_init(WPACKET *pkt, BUF_MEM *buf)
+{
+ return WPACKET_init_len(pkt, buf, 0);
+}
+
+int WPACKET_init_null(WPACKET *pkt, size_t lenbytes)
+{
+ pkt->staticbuf = NULL;
+ pkt->buf = NULL;
+ pkt->maxsize = maxmaxsize(lenbytes);
+ pkt->endfirst = 0;
+
+ return wpacket_intern_init_len(pkt, 0);
+}
+
+int WPACKET_init_null_der(WPACKET *pkt)
+{
+ pkt->staticbuf = NULL;
+ pkt->buf = NULL;
+ pkt->maxsize = SIZE_MAX;
+ pkt->endfirst = 1;
+
+ return wpacket_intern_init_len(pkt, 0);
+}
+
+int WPACKET_set_flags(WPACKET *pkt, unsigned int flags)
+{
+ /* Internal API, so should not fail */
+ if (!ossl_assert(pkt->subs != NULL))
+ return 0;
+
+ pkt->subs->flags = flags;
+
+ return 1;
+}
+
+/* Store the |value| of length |len| at location |data| */
+static int put_value(unsigned char *data, uint64_t value, size_t len)
+{
+ if (data == NULL)
+ return 1;
+
+ for (data += len - 1; len > 0; len--) {
+ *data = (unsigned char)(value & 0xff);
+ data--;
+ value >>= 8;
+ }
+
+ /* Check whether we could fit the value in the assigned number of bytes */
+ if (value > 0)
+ return 0;
+
+ return 1;
+}
+
+
+/*
+ * Internal helper function used by WPACKET_close(), WPACKET_finish() and
+ * WPACKET_fill_lengths() to close a sub-packet and write out its length if
+ * necessary. If |doclose| is 0 then it goes through the motions of closing
+ * (i.e. it fills in all the lengths), but doesn't actually close anything.
+ */
+static int wpacket_intern_close(WPACKET *pkt, WPACKET_SUB *sub, int doclose)
+{
+ size_t packlen = pkt->written - sub->pwritten;
+
+ if (packlen == 0
+ && (sub->flags & WPACKET_FLAGS_NON_ZERO_LENGTH) != 0)
+ return 0;
+
+ if (packlen == 0
+ && sub->flags & WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH) {
+ /* We can't handle this case. Return an error */
+ if (!doclose)
+ return 0;
+
+ /* Deallocate any bytes allocated for the length of the WPACKET */
+ if ((pkt->curr - sub->lenbytes) == sub->packet_len) {
+ pkt->written -= sub->lenbytes;
+ pkt->curr -= sub->lenbytes;
+ }
+
+ /* Don't write out the packet length */
+ sub->packet_len = 0;
+ sub->lenbytes = 0;
+ }
+
+ /* Write out the WPACKET length if needed */
+ if (sub->lenbytes > 0) {
+ unsigned char *buf = GETBUF(pkt);
+
+ if (buf != NULL
+ && !put_value(&buf[sub->packet_len], packlen,
+ sub->lenbytes))
+ return 0;
+ } else if (pkt->endfirst && sub->parent != NULL
+ && (packlen != 0
+ || (sub->flags
+ & WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH) == 0)) {
+ size_t tmplen = packlen;
+ size_t numlenbytes = 1;
+
+ while ((tmplen = tmplen >> 8) > 0)
+ numlenbytes++;
+ if (!WPACKET_put_bytes__(pkt, packlen, numlenbytes))
+ return 0;
+ if (packlen > 0x7f) {
+ numlenbytes |= 0x80;
+ if (!WPACKET_put_bytes_u8(pkt, numlenbytes))
+ return 0;
+ }
+ }
+
+ if (doclose) {
+ pkt->subs = sub->parent;
+ OPENSSL_free(sub);
+ }
+
+ return 1;
+}
+
+int WPACKET_fill_lengths(WPACKET *pkt)
+{
+ WPACKET_SUB *sub;
+
+ if (!ossl_assert(pkt->subs != NULL))
+ return 0;
+
+ for (sub = pkt->subs; sub != NULL; sub = sub->parent) {
+ if (!wpacket_intern_close(pkt, sub, 0))
+ return 0;
+ }
+
+ return 1;
+}
+
+int WPACKET_close(WPACKET *pkt)
+{
+ /*
+ * Internal API, so should not fail - but we do negative testing of this
+ * so no assert (otherwise the tests fail)
+ */
+ if (pkt->subs == NULL || pkt->subs->parent == NULL)
+ return 0;
+
+ return wpacket_intern_close(pkt, pkt->subs, 1);
+}
+
+int WPACKET_finish(WPACKET *pkt)
+{
+ int ret;
+
+ /*
+ * Internal API, so should not fail - but we do negative testing of this
+ * so no assert (otherwise the tests fail)
+ */
+ if (pkt->subs == NULL || pkt->subs->parent != NULL)
+ return 0;
+
+ ret = wpacket_intern_close(pkt, pkt->subs, 1);
+ if (ret) {
+ OPENSSL_free(pkt->subs);
+ pkt->subs = NULL;
+ }
+
+ return ret;
+}
+
+int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes)
+{
+ WPACKET_SUB *sub;
+ unsigned char *lenchars;
+
+ /* Internal API, so should not fail */
+ if (!ossl_assert(pkt->subs != NULL))
+ return 0;
+
+ /* We don't support lenbytes greater than 0 when doing endfirst writing */
+ if (lenbytes > 0 && pkt->endfirst)
+ return 0;
+
+ if ((sub = OPENSSL_zalloc(sizeof(*sub))) == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ sub->parent = pkt->subs;
+ pkt->subs = sub;
+ sub->pwritten = pkt->written + lenbytes;
+ sub->lenbytes = lenbytes;
+
+ if (lenbytes == 0) {
+ sub->packet_len = 0;
+ return 1;
+ }
+
+ sub->packet_len = pkt->written;
+
+ if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars))
+ return 0;
+
+ return 1;
+}
+
+int WPACKET_start_sub_packet(WPACKET *pkt)
+{
+ return WPACKET_start_sub_packet_len__(pkt, 0);
+}
+
+int WPACKET_put_bytes__(WPACKET *pkt, uint64_t val, size_t size)
+{
+ unsigned char *data;
+
+ /* Internal API, so should not fail */
+ if (!ossl_assert(size <= sizeof(uint64_t))
+ || !WPACKET_allocate_bytes(pkt, size, &data)
+ || !put_value(data, val, size))
+ return 0;
+
+ return 1;
+}
+
+int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize)
+{
+ WPACKET_SUB *sub;
+ size_t lenbytes;
+
+ /* Internal API, so should not fail */
+ if (!ossl_assert(pkt->subs != NULL))
+ return 0;
+
+ /* Find the WPACKET_SUB for the top level */
+ for (sub = pkt->subs; sub->parent != NULL; sub = sub->parent)
+ continue;
+
+ lenbytes = sub->lenbytes;
+ if (lenbytes == 0)
+ lenbytes = sizeof(pkt->maxsize);
+
+ if (maxmaxsize(lenbytes) < maxsize || maxsize < pkt->written)
+ return 0;
+
+ pkt->maxsize = maxsize;
+
+ return 1;
+}
+
+int WPACKET_memset(WPACKET *pkt, int ch, size_t len)
+{
+ unsigned char *dest;
+
+ if (len == 0)
+ return 1;
+
+ if (!WPACKET_allocate_bytes(pkt, len, &dest))
+ return 0;
+
+ if (dest != NULL)
+ memset(dest, ch, len);
+
+ return 1;
+}
+
+int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len)
+{
+ unsigned char *dest;
+
+ if (len == 0)
+ return 1;
+
+ if (!WPACKET_allocate_bytes(pkt, len, &dest))
+ return 0;
+
+ if (dest != NULL)
+ memcpy(dest, src, len);
+
+ return 1;
+}
+
+int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len,
+ size_t lenbytes)
+{
+ if (!WPACKET_start_sub_packet_len__(pkt, lenbytes)
+ || !WPACKET_memcpy(pkt, src, len)
+ || !WPACKET_close(pkt))
+ return 0;
+
+ return 1;
+}
+
+int WPACKET_get_total_written(WPACKET *pkt, size_t *written)
+{
+ /* Internal API, so should not fail */
+ if (!ossl_assert(written != NULL))
+ return 0;
+
+ *written = pkt->written;
+
+ return 1;
+}
+
+int WPACKET_get_length(WPACKET *pkt, size_t *len)
+{
+ /* Internal API, so should not fail */
+ if (!ossl_assert(pkt->subs != NULL && len != NULL))
+ return 0;
+
+ *len = pkt->written - pkt->subs->pwritten;
+
+ return 1;
+}
+
+unsigned char *WPACKET_get_curr(WPACKET *pkt)
+{
+ unsigned char *buf = GETBUF(pkt);
+
+ if (buf == NULL)
+ return NULL;
+
+ if (pkt->endfirst)
+ return buf + pkt->maxsize - pkt->curr;
+
+ return buf + pkt->curr;
+}
+
+int WPACKET_is_null_buf(WPACKET *pkt)
+{
+ return pkt->buf == NULL && pkt->staticbuf == NULL;
+}
+
+void WPACKET_cleanup(WPACKET *pkt)
+{
+ WPACKET_SUB *sub, *parent;
+
+ for (sub = pkt->subs; sub != NULL; sub = parent) {
+ parent = sub->parent;
+ OPENSSL_free(sub);
+ }
+ pkt->subs = NULL;
+}
diff --git a/crypto/param_build.c b/crypto/param_build.c
new file mode 100644
index 000000000000..51c8681f3be5
--- /dev/null
+++ b/crypto/param_build.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/err.h>
+#include <openssl/cryptoerr.h>
+#include <openssl/params.h>
+#include <openssl/types.h>
+#include <openssl/safestack.h>
+#include "internal/param_build_set.h"
+
+/*
+ * Special internal param type to indicate the end of an allocate OSSL_PARAM
+ * array.
+ */
+
+typedef struct {
+ const char *key;
+ int type;
+ int secure;
+ size_t size;
+ size_t alloc_blocks;
+ const BIGNUM *bn;
+ const void *string;
+ union {
+ /*
+ * These fields are never directly addressed, but their sizes are
+ * imporant so that all native types can be copied here without overrun.
+ */
+ ossl_intmax_t i;
+ ossl_uintmax_t u;
+ double d;
+ } num;
+} OSSL_PARAM_BLD_DEF;
+
+DEFINE_STACK_OF(OSSL_PARAM_BLD_DEF)
+
+struct ossl_param_bld_st {
+ size_t total_blocks;
+ size_t secure_blocks;
+ STACK_OF(OSSL_PARAM_BLD_DEF) *params;
+};
+
+static OSSL_PARAM_BLD_DEF *param_push(OSSL_PARAM_BLD *bld, const char *key,
+ int size, size_t alloc, int type,
+ int secure)
+{
+ OSSL_PARAM_BLD_DEF *pd = OPENSSL_zalloc(sizeof(*pd));
+
+ if (pd == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ pd->key = key;
+ pd->type = type;
+ pd->size = size;
+ pd->alloc_blocks = ossl_param_bytes_to_blocks(alloc);
+ if ((pd->secure = secure) != 0)
+ bld->secure_blocks += pd->alloc_blocks;
+ else
+ bld->total_blocks += pd->alloc_blocks;
+ if (sk_OSSL_PARAM_BLD_DEF_push(bld->params, pd) <= 0) {
+ OPENSSL_free(pd);
+ pd = NULL;
+ }
+ return pd;
+}
+
+static int param_push_num(OSSL_PARAM_BLD *bld, const char *key,
+ void *num, size_t size, int type)
+{
+ OSSL_PARAM_BLD_DEF *pd = param_push(bld, key, size, size, type, 0);
+
+ if (pd == NULL)
+ return 0;
+ if (size > sizeof(pd->num)) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_BYTES);
+ return 0;
+ }
+ memcpy(&pd->num, num, size);
+ return 1;
+}
+
+OSSL_PARAM_BLD *OSSL_PARAM_BLD_new(void)
+{
+ OSSL_PARAM_BLD *r = OPENSSL_zalloc(sizeof(OSSL_PARAM_BLD));
+
+ if (r != NULL) {
+ r->params = sk_OSSL_PARAM_BLD_DEF_new_null();
+ if (r->params == NULL) {
+ OPENSSL_free(r);
+ r = NULL;
+ }
+ }
+ return r;
+}
+
+static void free_all_params(OSSL_PARAM_BLD *bld)
+{
+ int i, n = sk_OSSL_PARAM_BLD_DEF_num(bld->params);
+
+ for (i = 0; i < n; i++)
+ OPENSSL_free(sk_OSSL_PARAM_BLD_DEF_pop(bld->params));
+}
+
+void OSSL_PARAM_BLD_free(OSSL_PARAM_BLD *bld)
+{
+ if (bld == NULL)
+ return;
+ free_all_params(bld);
+ sk_OSSL_PARAM_BLD_DEF_free(bld->params);
+ OPENSSL_free(bld);
+}
+
+int OSSL_PARAM_BLD_push_int(OSSL_PARAM_BLD *bld, const char *key, int num)
+{
+ return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER);
+}
+
+int OSSL_PARAM_BLD_push_uint(OSSL_PARAM_BLD *bld, const char *key,
+ unsigned int num)
+{
+ return param_push_num(bld, key, &num, sizeof(num),
+ OSSL_PARAM_UNSIGNED_INTEGER);
+}
+
+int OSSL_PARAM_BLD_push_long(OSSL_PARAM_BLD *bld, const char *key,
+ long int num)
+{
+ return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER);
+}
+
+int OSSL_PARAM_BLD_push_ulong(OSSL_PARAM_BLD *bld, const char *key,
+ unsigned long int num)
+{
+ return param_push_num(bld, key, &num, sizeof(num),
+ OSSL_PARAM_UNSIGNED_INTEGER);
+}
+
+int OSSL_PARAM_BLD_push_int32(OSSL_PARAM_BLD *bld, const char *key,
+ int32_t num)
+{
+ return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER);
+}
+
+int OSSL_PARAM_BLD_push_uint32(OSSL_PARAM_BLD *bld, const char *key,
+ uint32_t num)
+{
+ return param_push_num(bld, key, &num, sizeof(num),
+ OSSL_PARAM_UNSIGNED_INTEGER);
+}
+
+int OSSL_PARAM_BLD_push_int64(OSSL_PARAM_BLD *bld, const char *key,
+ int64_t num)
+{
+ return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER);
+}
+
+int OSSL_PARAM_BLD_push_uint64(OSSL_PARAM_BLD *bld, const char *key,
+ uint64_t num)
+{
+ return param_push_num(bld, key, &num, sizeof(num),
+ OSSL_PARAM_UNSIGNED_INTEGER);
+}
+
+int OSSL_PARAM_BLD_push_size_t(OSSL_PARAM_BLD *bld, const char *key,
+ size_t num)
+{
+ return param_push_num(bld, key, &num, sizeof(num),
+ OSSL_PARAM_UNSIGNED_INTEGER);
+}
+
+int OSSL_PARAM_BLD_push_time_t(OSSL_PARAM_BLD *bld, const char *key,
+ time_t num)
+{
+ return param_push_num(bld, key, &num, sizeof(num),
+ OSSL_PARAM_INTEGER);
+}
+
+int OSSL_PARAM_BLD_push_double(OSSL_PARAM_BLD *bld, const char *key,
+ double num)
+{
+ return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_REAL);
+}
+
+int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD *bld, const char *key,
+ const BIGNUM *bn)
+{
+ return OSSL_PARAM_BLD_push_BN_pad(bld, key, bn,
+ bn == NULL ? 0 : BN_num_bytes(bn));
+}
+
+int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
+ const BIGNUM *bn, size_t sz)
+{
+ int n, secure = 0;
+ OSSL_PARAM_BLD_DEF *pd;
+
+ if (bn != NULL) {
+ if (BN_is_negative(bn)) {
+ ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_UNSUPPORTED,
+ "Negative big numbers are unsupported for OSSL_PARAM");
+ return 0;
+ }
+
+ n = BN_num_bytes(bn);
+ if (n < 0) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_ZERO_LENGTH_NUMBER);
+ return 0;
+ }
+ if (sz < (size_t)n) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_SMALL_BUFFER);
+ return 0;
+ }
+ if (BN_get_flags(bn, BN_FLG_SECURE) == BN_FLG_SECURE)
+ secure = 1;
+
+ /* The BIGNUM is zero, we must transfer at least one byte */
+ if (sz == 0)
+ sz++;
+ }
+ pd = param_push(bld, key, sz, sz, OSSL_PARAM_UNSIGNED_INTEGER, secure);
+ if (pd == NULL)
+ return 0;
+ pd->bn = bn;
+ return 1;
+}
+
+int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key,
+ const char *buf, size_t bsize)
+{
+ OSSL_PARAM_BLD_DEF *pd;
+ int secure;
+
+ if (bsize == 0) {
+ bsize = strlen(buf);
+ } else if (bsize > INT_MAX) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_STRING_TOO_LONG);
+ return 0;
+ }
+ secure = CRYPTO_secure_allocated(buf);
+ pd = param_push(bld, key, bsize, bsize + 1, OSSL_PARAM_UTF8_STRING, secure);
+ if (pd == NULL)
+ return 0;
+ pd->string = buf;
+ return 1;
+}
+
+int OSSL_PARAM_BLD_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key,
+ char *buf, size_t bsize)
+{
+ OSSL_PARAM_BLD_DEF *pd;
+
+ if (bsize == 0) {
+ bsize = strlen(buf);
+ } else if (bsize > INT_MAX) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_STRING_TOO_LONG);
+ return 0;
+ }
+ pd = param_push(bld, key, bsize, sizeof(buf), OSSL_PARAM_UTF8_PTR, 0);
+ if (pd == NULL)
+ return 0;
+ pd->string = buf;
+ return 1;
+}
+
+int OSSL_PARAM_BLD_push_octet_string(OSSL_PARAM_BLD *bld, const char *key,
+ const void *buf, size_t bsize)
+{
+ OSSL_PARAM_BLD_DEF *pd;
+ int secure;
+
+ if (bsize > INT_MAX) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_STRING_TOO_LONG);
+ return 0;
+ }
+ secure = CRYPTO_secure_allocated(buf);
+ pd = param_push(bld, key, bsize, bsize, OSSL_PARAM_OCTET_STRING, secure);
+ if (pd == NULL)
+ return 0;
+ pd->string = buf;
+ return 1;
+}
+
+int OSSL_PARAM_BLD_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key,
+ void *buf, size_t bsize)
+{
+ OSSL_PARAM_BLD_DEF *pd;
+
+ if (bsize > INT_MAX) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_STRING_TOO_LONG);
+ return 0;
+ }
+ pd = param_push(bld, key, bsize, sizeof(buf), OSSL_PARAM_OCTET_PTR, 0);
+ if (pd == NULL)
+ return 0;
+ pd->string = buf;
+ return 1;
+}
+
+static OSSL_PARAM *param_bld_convert(OSSL_PARAM_BLD *bld, OSSL_PARAM *param,
+ OSSL_PARAM_ALIGNED_BLOCK *blk,
+ OSSL_PARAM_ALIGNED_BLOCK *secure)
+{
+ int i, num = sk_OSSL_PARAM_BLD_DEF_num(bld->params);
+ OSSL_PARAM_BLD_DEF *pd;
+ void *p;
+
+ for (i = 0; i < num; i++) {
+ pd = sk_OSSL_PARAM_BLD_DEF_value(bld->params, i);
+ param[i].key = pd->key;
+ param[i].data_type = pd->type;
+ param[i].data_size = pd->size;
+ param[i].return_size = OSSL_PARAM_UNMODIFIED;
+
+ if (pd->secure) {
+ p = secure;
+ secure += pd->alloc_blocks;
+ } else {
+ p = blk;
+ blk += pd->alloc_blocks;
+ }
+ param[i].data = p;
+ if (pd->bn != NULL) {
+ /* BIGNUM */
+ BN_bn2nativepad(pd->bn, (unsigned char *)p, pd->size);
+ } else if (pd->type == OSSL_PARAM_OCTET_PTR
+ || pd->type == OSSL_PARAM_UTF8_PTR) {
+ /* PTR */
+ *(const void **)p = pd->string;
+ } else if (pd->type == OSSL_PARAM_OCTET_STRING
+ || pd->type == OSSL_PARAM_UTF8_STRING) {
+ if (pd->string != NULL)
+ memcpy(p, pd->string, pd->size);
+ else
+ memset(p, 0, pd->size);
+ if (pd->type == OSSL_PARAM_UTF8_STRING)
+ ((char *)p)[pd->size] = '\0';
+ } else {
+ /* Number, but could also be a NULL BIGNUM */
+ if (pd->size > sizeof(pd->num))
+ memset(p, 0, pd->size);
+ else if (pd->size > 0)
+ memcpy(p, &pd->num, pd->size);
+ }
+ }
+ param[i] = OSSL_PARAM_construct_end();
+ return param + i;
+}
+
+OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld)
+{
+ OSSL_PARAM_ALIGNED_BLOCK *blk, *s = NULL;
+ OSSL_PARAM *params, *last;
+ const int num = sk_OSSL_PARAM_BLD_DEF_num(bld->params);
+ const size_t p_blks = ossl_param_bytes_to_blocks((1 + num) * sizeof(*params));
+ const size_t total = OSSL_PARAM_ALIGN_SIZE * (p_blks + bld->total_blocks);
+ const size_t ss = OSSL_PARAM_ALIGN_SIZE * bld->secure_blocks;
+
+ if (ss > 0) {
+ s = OPENSSL_secure_malloc(ss);
+ if (s == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_SECURE_MALLOC_FAILURE);
+ return NULL;
+ }
+ }
+ params = OPENSSL_malloc(total);
+ if (params == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ OPENSSL_secure_free(s);
+ return NULL;
+ }
+ blk = p_blks + (OSSL_PARAM_ALIGNED_BLOCK *)(params);
+ last = param_bld_convert(bld, params, blk, s);
+ ossl_param_set_secure_block(last, s, ss);
+
+ /* Reset builder for reuse */
+ bld->total_blocks = 0;
+ bld->secure_blocks = 0;
+ free_all_params(bld);
+ return params;
+}
diff --git a/crypto/param_build_set.c b/crypto/param_build_set.c
new file mode 100644
index 000000000000..8b570ded96eb
--- /dev/null
+++ b/crypto/param_build_set.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Key Management utility functions to share functionality between the export()
+ * and get_params() methods.
+ * export() uses OSSL_PARAM_BLD, and get_params() used the OSSL_PARAM[] to
+ * fill in parameter data for the same key and data fields.
+ */
+
+#include <openssl/core_names.h>
+#include "internal/param_build_set.h"
+
+DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
+
+int ossl_param_build_set_int(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+ const char *key, int num)
+{
+ if (bld != NULL)
+ return OSSL_PARAM_BLD_push_int(bld, key, num);
+ p = OSSL_PARAM_locate(p, key);
+ if (p != NULL)
+ return OSSL_PARAM_set_int(p, num);
+ return 1;
+}
+
+int ossl_param_build_set_long(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+ const char *key, long num)
+{
+ if (bld != NULL)
+ return OSSL_PARAM_BLD_push_long(bld, key, num);
+ p = OSSL_PARAM_locate(p, key);
+ if (p != NULL)
+ return OSSL_PARAM_set_long(p, num);
+ return 1;
+}
+
+int ossl_param_build_set_utf8_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+ const char *key, const char *buf)
+{
+ if (bld != NULL)
+ return OSSL_PARAM_BLD_push_utf8_string(bld, key, buf, 0);
+ p = OSSL_PARAM_locate(p, key);
+ if (p != NULL)
+ return OSSL_PARAM_set_utf8_string(p, buf);
+ return 1;
+}
+
+int ossl_param_build_set_octet_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+ const char *key,
+ const unsigned char *data,
+ size_t data_len)
+{
+ if (bld != NULL)
+ return OSSL_PARAM_BLD_push_octet_string(bld, key, data, data_len);
+
+ p = OSSL_PARAM_locate(p, key);
+ if (p != NULL)
+ return OSSL_PARAM_set_octet_string(p, data, data_len);
+ return 1;
+}
+
+int ossl_param_build_set_bn_pad(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+ const char *key, const BIGNUM *bn, size_t sz)
+{
+ if (bld != NULL)
+ return OSSL_PARAM_BLD_push_BN_pad(bld, key, bn, sz);
+ p = OSSL_PARAM_locate(p, key);
+ if (p != NULL) {
+ if (sz > p->data_size)
+ return 0;
+ p->data_size = sz;
+ return OSSL_PARAM_set_BN(p, bn);
+ }
+ return 1;
+}
+
+int ossl_param_build_set_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+ const char *key, const BIGNUM *bn)
+{
+ if (bld != NULL)
+ return OSSL_PARAM_BLD_push_BN(bld, key, bn);
+
+ p = OSSL_PARAM_locate(p, key);
+ if (p != NULL)
+ return OSSL_PARAM_set_BN(p, bn) > 0;
+ return 1;
+}
+
+int ossl_param_build_set_multi_key_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *params,
+ const char *names[],
+ STACK_OF(BIGNUM_const) *stk)
+{
+ int i, sz = sk_BIGNUM_const_num(stk);
+ OSSL_PARAM *p;
+
+
+ if (bld != NULL) {
+ for (i = 0; i < sz && names[i] != NULL; ++i) {
+ if (!OSSL_PARAM_BLD_push_BN(bld, names[i],
+ sk_BIGNUM_const_value(stk, i)))
+ return 0;
+ }
+ return 1;
+ }
+
+ for (i = 0; i < sz && names[i] != NULL; ++i) {
+ p = OSSL_PARAM_locate(params, names[i]);
+ if (p != NULL) {
+ if (!OSSL_PARAM_set_BN(p, sk_BIGNUM_const_value(stk, i)))
+ return 0;
+ }
+ }
+ return 1;
+}
diff --git a/crypto/params.c b/crypto/params.c
new file mode 100644
index 000000000000..5fd1e0028da9
--- /dev/null
+++ b/crypto/params.c
@@ -0,0 +1,1299 @@
+/*
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/params.h>
+#include "internal/thread_once.h"
+#include "internal/numbers.h"
+#include "internal/endian.h"
+
+/*
+ * Return the number of bits in the mantissa of a double. This is used to
+ * shift a larger integral value to determine if it will exactly fit into a
+ * double.
+ */
+static unsigned int real_shift(void)
+{
+ return sizeof(double) == 4 ? 24 : 53;
+}
+
+OSSL_PARAM *OSSL_PARAM_locate(OSSL_PARAM *p, const char *key)
+{
+ if (p != NULL && key != NULL)
+ for (; p->key != NULL; p++)
+ if (strcmp(key, p->key) == 0)
+ return p;
+ return NULL;
+}
+
+const OSSL_PARAM *OSSL_PARAM_locate_const(const OSSL_PARAM *p, const char *key)
+{
+ return OSSL_PARAM_locate((OSSL_PARAM *)p, key);
+}
+
+static OSSL_PARAM ossl_param_construct(const char *key, unsigned int data_type,
+ void *data, size_t data_size)
+{
+ OSSL_PARAM res;
+
+ res.key = key;
+ res.data_type = data_type;
+ res.data = data;
+ res.data_size = data_size;
+ res.return_size = OSSL_PARAM_UNMODIFIED;
+ return res;
+}
+
+int OSSL_PARAM_modified(const OSSL_PARAM *p)
+{
+ return p != NULL && p->return_size != OSSL_PARAM_UNMODIFIED;
+}
+
+void OSSL_PARAM_set_all_unmodified(OSSL_PARAM *p)
+{
+ if (p != NULL)
+ while (p->key != NULL)
+ p++->return_size = OSSL_PARAM_UNMODIFIED;
+}
+
+/* Return non-zero if the signed number is negative */
+static int is_negative(const void *number, size_t s)
+{
+ const unsigned char *n = number;
+ DECLARE_IS_ENDIAN;
+
+ return 0x80 & (IS_BIG_ENDIAN ? n[0] : n[s - 1]);
+}
+
+/* Check that all the bytes specified match the expected sign byte */
+static int check_sign_bytes(const unsigned char *p, size_t n, unsigned char s)
+{
+ size_t i;
+
+ for (i = 0; i < n; i++)
+ if (p[i] != s)
+ return 0;
+ return 1;
+}
+
+/*
+ * Copy an integer to another integer.
+ * Handle different length integers and signed and unsigned integers.
+ * Both integers are in native byte ordering.
+ */
+static int copy_integer(unsigned char *dest, size_t dest_len,
+ const unsigned char *src, size_t src_len,
+ unsigned char pad, int signed_int)
+{
+ size_t n;
+ DECLARE_IS_ENDIAN;
+
+ if (IS_BIG_ENDIAN) {
+ if (src_len < dest_len) {
+ n = dest_len - src_len;
+ memset(dest, pad, n);
+ memcpy(dest + n, src, src_len);
+ } else {
+ n = src_len - dest_len;
+ if (!check_sign_bytes(src, n, pad)
+ /*
+ * Shortening a signed value must retain the correct sign.
+ * Avoiding this kind of thing: -253 = 0xff03 -> 0x03 = 3
+ */
+ || (signed_int && ((pad ^ src[n]) & 0x80) != 0))
+ return 0;
+ memcpy(dest, src + n, dest_len);
+ }
+ } else /* IS_LITTLE_ENDIAN */ {
+ if (src_len < dest_len) {
+ n = dest_len - src_len;
+ memset(dest + src_len, pad, n);
+ memcpy(dest, src, src_len);
+ } else {
+ n = src_len - dest_len;
+ if (!check_sign_bytes(src + dest_len, n, pad)
+ /*
+ * Shortening a signed value must retain the correct sign.
+ * Avoiding this kind of thing: 130 = 0x0082 -> 0x82 = -126
+ */
+ || (signed_int && ((pad ^ src[dest_len - 1]) & 0x80) != 0))
+ return 0;
+ memcpy(dest, src, dest_len);
+ }
+ }
+ return 1;
+}
+
+/* Copy a signed number to a signed number of possibly different length */
+static int signed_from_signed(void *dest, size_t dest_len,
+ const void *src, size_t src_len)
+{
+ return copy_integer(dest, dest_len, src, src_len,
+ is_negative(src, src_len) ? 0xff : 0, 1);
+}
+
+/* Copy an unsigned number to a signed number of possibly different length */
+static int signed_from_unsigned(void *dest, size_t dest_len,
+ const void *src, size_t src_len)
+{
+ return copy_integer(dest, dest_len, src, src_len, 0, 1);
+}
+
+/* Copy a signed number to an unsigned number of possibly different length */
+static int unsigned_from_signed(void *dest, size_t dest_len,
+ const void *src, size_t src_len)
+{
+ if (is_negative(src, src_len))
+ return 0;
+ return copy_integer(dest, dest_len, src, src_len, 0, 0);
+}
+
+/* Copy an unsigned number to an unsigned number of possibly different length */
+static int unsigned_from_unsigned(void *dest, size_t dest_len,
+ const void *src, size_t src_len)
+{
+ return copy_integer(dest, dest_len, src, src_len, 0, 0);
+}
+
+/* General purpose get integer parameter call that handles odd sizes */
+static int general_get_int(const OSSL_PARAM *p, void *val, size_t val_size)
+{
+ if (p->data_type == OSSL_PARAM_INTEGER)
+ return signed_from_signed(val, val_size, p->data, p->data_size);
+ if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER)
+ return signed_from_unsigned(val, val_size, p->data, p->data_size);
+ return 0;
+}
+
+/* General purpose set integer parameter call that handles odd sizes */
+static int general_set_int(OSSL_PARAM *p, void *val, size_t val_size)
+{
+ int r = 0;
+
+ p->return_size = val_size; /* Expected size */
+ if (p->data == NULL)
+ return 1;
+ if (p->data_type == OSSL_PARAM_INTEGER)
+ r = signed_from_signed(p->data, p->data_size, val, val_size);
+ else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER)
+ r = unsigned_from_signed(p->data, p->data_size, val, val_size);
+ p->return_size = r ? p->data_size : val_size;
+ return r;
+}
+
+/* General purpose get unsigned integer parameter call that handles odd sizes */
+static int general_get_uint(const OSSL_PARAM *p, void *val, size_t val_size)
+{
+ if (p->data_type == OSSL_PARAM_INTEGER)
+ return unsigned_from_signed(val, val_size, p->data, p->data_size);
+ if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER)
+ return unsigned_from_unsigned(val, val_size, p->data, p->data_size);
+ return 0;
+}
+
+/* General purpose set unsigned integer parameter call that handles odd sizes */
+static int general_set_uint(OSSL_PARAM *p, void *val, size_t val_size)
+{
+ int r = 0;
+
+ p->return_size = val_size; /* Expected size */
+ if (p->data == NULL)
+ return 1;
+ if (p->data_type == OSSL_PARAM_INTEGER)
+ r = signed_from_unsigned(p->data, p->data_size, val, val_size);
+ else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER)
+ r = unsigned_from_unsigned(p->data, p->data_size, val, val_size);
+ p->return_size = r ? p->data_size : val_size;
+ return r;
+}
+
+int OSSL_PARAM_get_int(const OSSL_PARAM *p, int *val)
+{
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ switch (sizeof(int)) {
+ case sizeof(int32_t):
+ return OSSL_PARAM_get_int32(p, (int32_t *)val);
+ case sizeof(int64_t):
+ return OSSL_PARAM_get_int64(p, (int64_t *)val);
+ }
+#endif
+ return general_get_int(p, val, sizeof(*val));
+}
+
+int OSSL_PARAM_set_int(OSSL_PARAM *p, int val)
+{
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ switch (sizeof(int)) {
+ case sizeof(int32_t):
+ return OSSL_PARAM_set_int32(p, (int32_t)val);
+ case sizeof(int64_t):
+ return OSSL_PARAM_set_int64(p, (int64_t)val);
+ }
+#endif
+ return general_set_int(p, &val, sizeof(val));
+}
+
+OSSL_PARAM OSSL_PARAM_construct_int(const char *key, int *buf)
+{
+ return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(int));
+}
+
+int OSSL_PARAM_get_uint(const OSSL_PARAM *p, unsigned int *val)
+{
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ switch (sizeof(unsigned int)) {
+ case sizeof(uint32_t):
+ return OSSL_PARAM_get_uint32(p, (uint32_t *)val);
+ case sizeof(uint64_t):
+ return OSSL_PARAM_get_uint64(p, (uint64_t *)val);
+ }
+#endif
+ return general_get_uint(p, val, sizeof(*val));
+}
+
+int OSSL_PARAM_set_uint(OSSL_PARAM *p, unsigned int val)
+{
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ switch (sizeof(unsigned int)) {
+ case sizeof(uint32_t):
+ return OSSL_PARAM_set_uint32(p, (uint32_t)val);
+ case sizeof(uint64_t):
+ return OSSL_PARAM_set_uint64(p, (uint64_t)val);
+ }
+#endif
+ return general_set_uint(p, &val, sizeof(val));
+}
+
+OSSL_PARAM OSSL_PARAM_construct_uint(const char *key, unsigned int *buf)
+{
+ return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
+ sizeof(unsigned int));
+}
+
+int OSSL_PARAM_get_long(const OSSL_PARAM *p, long int *val)
+{
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ switch (sizeof(long int)) {
+ case sizeof(int32_t):
+ return OSSL_PARAM_get_int32(p, (int32_t *)val);
+ case sizeof(int64_t):
+ return OSSL_PARAM_get_int64(p, (int64_t *)val);
+ }
+#endif
+ return general_get_int(p, val, sizeof(*val));
+}
+
+int OSSL_PARAM_set_long(OSSL_PARAM *p, long int val)
+{
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ switch (sizeof(long int)) {
+ case sizeof(int32_t):
+ return OSSL_PARAM_set_int32(p, (int32_t)val);
+ case sizeof(int64_t):
+ return OSSL_PARAM_set_int64(p, (int64_t)val);
+ }
+#endif
+ return general_set_int(p, &val, sizeof(val));
+}
+
+OSSL_PARAM OSSL_PARAM_construct_long(const char *key, long int *buf)
+{
+ return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(long int));
+}
+
+int OSSL_PARAM_get_ulong(const OSSL_PARAM *p, unsigned long int *val)
+{
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ switch (sizeof(unsigned long int)) {
+ case sizeof(uint32_t):
+ return OSSL_PARAM_get_uint32(p, (uint32_t *)val);
+ case sizeof(uint64_t):
+ return OSSL_PARAM_get_uint64(p, (uint64_t *)val);
+ }
+#endif
+ return general_get_uint(p, val, sizeof(*val));
+}
+
+int OSSL_PARAM_set_ulong(OSSL_PARAM *p, unsigned long int val)
+{
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ switch (sizeof(unsigned long int)) {
+ case sizeof(uint32_t):
+ return OSSL_PARAM_set_uint32(p, (uint32_t)val);
+ case sizeof(uint64_t):
+ return OSSL_PARAM_set_uint64(p, (uint64_t)val);
+ }
+#endif
+ return general_set_uint(p, &val, sizeof(val));
+}
+
+OSSL_PARAM OSSL_PARAM_construct_ulong(const char *key, unsigned long int *buf)
+{
+ return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
+ sizeof(unsigned long int));
+}
+
+int OSSL_PARAM_get_int32(const OSSL_PARAM *p, int32_t *val)
+{
+ double d;
+
+ if (val == NULL || p == NULL )
+ return 0;
+
+ if (p->data_type == OSSL_PARAM_INTEGER) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ int64_t i64;
+
+ switch (p->data_size) {
+ case sizeof(int32_t):
+ *val = *(const int32_t *)p->data;
+ return 1;
+ case sizeof(int64_t):
+ i64 = *(const int64_t *)p->data;
+ if (i64 >= INT32_MIN && i64 <= INT32_MAX) {
+ *val = (int32_t)i64;
+ return 1;
+ }
+ return 0;
+ }
+#endif
+ return general_get_int(p, val, sizeof(*val));
+
+ } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ uint32_t u32;
+ uint64_t u64;
+
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ u32 = *(const uint32_t *)p->data;
+ if (u32 <= INT32_MAX) {
+ *val = (int32_t)u32;
+ return 1;
+ }
+ return 0;
+ case sizeof(uint64_t):
+ u64 = *(const uint64_t *)p->data;
+ if (u64 <= INT32_MAX) {
+ *val = (int32_t)u64;
+ return 1;
+ }
+ return 0;
+ }
+#endif
+ return general_get_int(p, val, sizeof(*val));
+
+ } else if (p->data_type == OSSL_PARAM_REAL) {
+ switch (p->data_size) {
+ case sizeof(double):
+ d = *(const double *)p->data;
+ if (d >= INT32_MIN && d <= INT32_MAX && d == (int32_t)d) {
+ *val = (int32_t)d;
+ return 1;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_int32(OSSL_PARAM *p, int32_t val)
+{
+ if (p == NULL)
+ return 0;
+ p->return_size = 0;
+ if (p->data_type == OSSL_PARAM_INTEGER) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ p->return_size = sizeof(int32_t); /* Minimum expected size */
+ if (p->data == NULL)
+ return 1;
+ switch (p->data_size) {
+ case sizeof(int32_t):
+ *(int32_t *)p->data = val;
+ return 1;
+ case sizeof(int64_t):
+ p->return_size = sizeof(int64_t);
+ *(int64_t *)p->data = (int64_t)val;
+ return 1;
+ }
+#endif
+ return general_set_int(p, &val, sizeof(val));
+ } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && val >= 0) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ p->return_size = sizeof(uint32_t); /* Minimum expected size */
+ if (p->data == NULL)
+ return 1;
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ *(uint32_t *)p->data = (uint32_t)val;
+ return 1;
+ case sizeof(uint64_t):
+ p->return_size = sizeof(uint64_t);
+ *(uint64_t *)p->data = (uint64_t)val;
+ return 1;
+ }
+#endif
+ return general_set_int(p, &val, sizeof(val));
+ } else if (p->data_type == OSSL_PARAM_REAL) {
+ p->return_size = sizeof(double);
+ if (p->data == NULL)
+ return 1;
+ switch (p->data_size) {
+ case sizeof(double):
+ *(double *)p->data = (double)val;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_int32(const char *key, int32_t *buf)
+{
+ return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf,
+ sizeof(int32_t));
+}
+
+int OSSL_PARAM_get_uint32(const OSSL_PARAM *p, uint32_t *val)
+{
+ double d;
+
+ if (val == NULL || p == NULL)
+ return 0;
+
+ if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ uint64_t u64;
+
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ *val = *(const uint32_t *)p->data;
+ return 1;
+ case sizeof(uint64_t):
+ u64 = *(const uint64_t *)p->data;
+ if (u64 <= UINT32_MAX) {
+ *val = (uint32_t)u64;
+ return 1;
+ }
+ return 0;
+ }
+#endif
+ return general_get_uint(p, val, sizeof(*val));
+ } else if (p->data_type == OSSL_PARAM_INTEGER) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ int32_t i32;
+ int64_t i64;
+
+ switch (p->data_size) {
+ case sizeof(int32_t):
+ i32 = *(const int32_t *)p->data;
+ if (i32 >= 0) {
+ *val = i32;
+ return 1;
+ }
+ return 0;
+ case sizeof(int64_t):
+ i64 = *(const int64_t *)p->data;
+ if (i64 >= 0 && i64 <= UINT32_MAX) {
+ *val = (uint32_t)i64;
+ return 1;
+ }
+ return 0;
+ }
+#endif
+ return general_get_uint(p, val, sizeof(*val));
+ } else if (p->data_type == OSSL_PARAM_REAL) {
+ switch (p->data_size) {
+ case sizeof(double):
+ d = *(const double *)p->data;
+ if (d >= 0 && d <= UINT32_MAX && d == (uint32_t)d) {
+ *val = (uint32_t)d;
+ return 1;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_uint32(OSSL_PARAM *p, uint32_t val)
+{
+ if (p == NULL)
+ return 0;
+ p->return_size = 0;
+
+ if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ p->return_size = sizeof(uint32_t); /* Minimum expected size */
+ if (p->data == NULL)
+ return 1;
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ *(uint32_t *)p->data = val;
+ return 1;
+ case sizeof(uint64_t):
+ p->return_size = sizeof(uint64_t);
+ *(uint64_t *)p->data = val;
+ return 1;
+ }
+#endif
+ return general_set_uint(p, &val, sizeof(val));
+ } else if (p->data_type == OSSL_PARAM_INTEGER) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ p->return_size = sizeof(int32_t); /* Minimum expected size */
+ if (p->data == NULL)
+ return 1;
+ switch (p->data_size) {
+ case sizeof(int32_t):
+ if (val <= INT32_MAX) {
+ *(int32_t *)p->data = (int32_t)val;
+ return 1;
+ }
+ return 0;
+ case sizeof(int64_t):
+ p->return_size = sizeof(int64_t);
+ *(int64_t *)p->data = (int64_t)val;
+ return 1;
+ }
+#endif
+ return general_set_uint(p, &val, sizeof(val));
+ } else if (p->data_type == OSSL_PARAM_REAL) {
+ p->return_size = sizeof(double);
+ if (p->data == NULL)
+ return 1;
+ switch (p->data_size) {
+ case sizeof(double):
+ *(double *)p->data = (double)val;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_uint32(const char *key, uint32_t *buf)
+{
+ return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
+ sizeof(uint32_t));
+}
+
+int OSSL_PARAM_get_int64(const OSSL_PARAM *p, int64_t *val)
+{
+ double d;
+
+ if (val == NULL || p == NULL )
+ return 0;
+
+ if (p->data_type == OSSL_PARAM_INTEGER) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ switch (p->data_size) {
+ case sizeof(int32_t):
+ *val = *(const int32_t *)p->data;
+ return 1;
+ case sizeof(int64_t):
+ *val = *(const int64_t *)p->data;
+ return 1;
+ }
+#endif
+ return general_get_int(p, val, sizeof(*val));
+ } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ uint64_t u64;
+
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ *val = *(const uint32_t *)p->data;
+ return 1;
+ case sizeof(uint64_t):
+ u64 = *(const uint64_t *)p->data;
+ if (u64 <= INT64_MAX) {
+ *val = (int64_t)u64;
+ return 1;
+ }
+ return 0;
+ }
+#endif
+ return general_get_int(p, val, sizeof(*val));
+ } else if (p->data_type == OSSL_PARAM_REAL) {
+ switch (p->data_size) {
+ case sizeof(double):
+ d = *(const double *)p->data;
+ if (d >= INT64_MIN
+ /*
+ * By subtracting 65535 (2^16-1) we cancel the low order
+ * 15 bits of INT64_MAX to avoid using imprecise floating
+ * point values.
+ */
+ && d < (double)(INT64_MAX - 65535) + 65536.0
+ && d == (int64_t)d) {
+ *val = (int64_t)d;
+ return 1;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_int64(OSSL_PARAM *p, int64_t val)
+{
+ uint64_t u64;
+
+ if (p == NULL)
+ return 0;
+ p->return_size = 0;
+ if (p->data_type == OSSL_PARAM_INTEGER) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ p->return_size = sizeof(int64_t); /* Expected size */
+ if (p->data == NULL)
+ return 1;
+ switch (p->data_size) {
+ case sizeof(int32_t):
+ if (val >= INT32_MIN && val <= INT32_MAX) {
+ p->return_size = sizeof(int32_t);
+ *(int32_t *)p->data = (int32_t)val;
+ return 1;
+ }
+ return 0;
+ case sizeof(int64_t):
+ *(int64_t *)p->data = val;
+ return 1;
+ }
+#endif
+ return general_set_int(p, &val, sizeof(val));
+ } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && val >= 0) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ p->return_size = sizeof(uint64_t); /* Expected size */
+ if (p->data == NULL)
+ return 1;
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ if (val <= UINT32_MAX) {
+ p->return_size = sizeof(uint32_t);
+ *(uint32_t *)p->data = (uint32_t)val;
+ return 1;
+ }
+ return 0;
+ case sizeof(uint64_t):
+ *(uint64_t *)p->data = (uint64_t)val;
+ return 1;
+ }
+#endif
+ return general_set_int(p, &val, sizeof(val));
+ } else if (p->data_type == OSSL_PARAM_REAL) {
+ p->return_size = sizeof(double);
+ if (p->data == NULL)
+ return 1;
+ switch (p->data_size) {
+ case sizeof(double):
+ u64 = val < 0 ? -val : val;
+ if ((u64 >> real_shift()) == 0) {
+ *(double *)p->data = (double)val;
+ return 1;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_int64(const char *key, int64_t *buf)
+{
+ return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(int64_t));
+}
+
+int OSSL_PARAM_get_uint64(const OSSL_PARAM *p, uint64_t *val)
+{
+ double d;
+
+ if (val == NULL || p == NULL)
+ return 0;
+
+ if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ *val = *(const uint32_t *)p->data;
+ return 1;
+ case sizeof(uint64_t):
+ *val = *(const uint64_t *)p->data;
+ return 1;
+ }
+#endif
+ return general_get_uint(p, val, sizeof(*val));
+ } else if (p->data_type == OSSL_PARAM_INTEGER) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ int32_t i32;
+ int64_t i64;
+
+ switch (p->data_size) {
+ case sizeof(int32_t):
+ i32 = *(const int32_t *)p->data;
+ if (i32 >= 0) {
+ *val = (uint64_t)i32;
+ return 1;
+ }
+ return 0;
+ case sizeof(int64_t):
+ i64 = *(const int64_t *)p->data;
+ if (i64 >= 0) {
+ *val = (uint64_t)i64;
+ return 1;
+ }
+ return 0;
+ }
+#endif
+ return general_get_uint(p, val, sizeof(*val));
+ } else if (p->data_type == OSSL_PARAM_REAL) {
+ switch (p->data_size) {
+ case sizeof(double):
+ d = *(const double *)p->data;
+ if (d >= 0
+ /*
+ * By subtracting 65535 (2^16-1) we cancel the low order
+ * 15 bits of UINT64_MAX to avoid using imprecise floating
+ * point values.
+ */
+ && d < (double)(UINT64_MAX - 65535) + 65536.0
+ && d == (uint64_t)d) {
+ *val = (uint64_t)d;
+ return 1;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_uint64(OSSL_PARAM *p, uint64_t val)
+{
+ if (p == NULL)
+ return 0;
+ p->return_size = 0;
+
+ if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ p->return_size = sizeof(uint64_t); /* Expected size */
+ if (p->data == NULL)
+ return 1;
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ if (val <= UINT32_MAX) {
+ p->return_size = sizeof(uint32_t);
+ *(uint32_t *)p->data = (uint32_t)val;
+ return 1;
+ }
+ return 0;
+ case sizeof(uint64_t):
+ *(uint64_t *)p->data = val;
+ return 1;
+ }
+#endif
+ return general_set_uint(p, &val, sizeof(val));
+ } else if (p->data_type == OSSL_PARAM_INTEGER) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ p->return_size = sizeof(int64_t); /* Expected size */
+ if (p->data == NULL)
+ return 1;
+ switch (p->data_size) {
+ case sizeof(int32_t):
+ if (val <= INT32_MAX) {
+ p->return_size = sizeof(int32_t);
+ *(int32_t *)p->data = (int32_t)val;
+ return 1;
+ }
+ return 0;
+ case sizeof(int64_t):
+ if (val <= INT64_MAX) {
+ *(int64_t *)p->data = (int64_t)val;
+ return 1;
+ }
+ return 0;
+ }
+#endif
+ return general_set_uint(p, &val, sizeof(val));
+ } else if (p->data_type == OSSL_PARAM_REAL) {
+ p->return_size = sizeof(double);
+ switch (p->data_size) {
+ case sizeof(double):
+ if ((val >> real_shift()) == 0) {
+ *(double *)p->data = (double)val;
+ return 1;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_uint64(const char *key, uint64_t *buf)
+{
+ return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
+ sizeof(uint64_t));
+}
+
+int OSSL_PARAM_get_size_t(const OSSL_PARAM *p, size_t *val)
+{
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ switch (sizeof(size_t)) {
+ case sizeof(uint32_t):
+ return OSSL_PARAM_get_uint32(p, (uint32_t *)val);
+ case sizeof(uint64_t):
+ return OSSL_PARAM_get_uint64(p, (uint64_t *)val);
+ }
+#endif
+ return general_get_uint(p, val, sizeof(*val));
+}
+
+int OSSL_PARAM_set_size_t(OSSL_PARAM *p, size_t val)
+{
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ switch (sizeof(size_t)) {
+ case sizeof(uint32_t):
+ return OSSL_PARAM_set_uint32(p, (uint32_t)val);
+ case sizeof(uint64_t):
+ return OSSL_PARAM_set_uint64(p, (uint64_t)val);
+ }
+#endif
+ return general_set_uint(p, &val, sizeof(val));
+}
+
+OSSL_PARAM OSSL_PARAM_construct_size_t(const char *key, size_t *buf)
+{
+ return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
+ sizeof(size_t));
+}
+
+int OSSL_PARAM_get_time_t(const OSSL_PARAM *p, time_t *val)
+{
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ switch (sizeof(time_t)) {
+ case sizeof(int32_t):
+ return OSSL_PARAM_get_int32(p, (int32_t *)val);
+ case sizeof(int64_t):
+ return OSSL_PARAM_get_int64(p, (int64_t *)val);
+ }
+#endif
+ return general_get_int(p, val, sizeof(*val));
+}
+
+int OSSL_PARAM_set_time_t(OSSL_PARAM *p, time_t val)
+{
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ switch (sizeof(time_t)) {
+ case sizeof(int32_t):
+ return OSSL_PARAM_set_int32(p, (int32_t)val);
+ case sizeof(int64_t):
+ return OSSL_PARAM_set_int64(p, (int64_t)val);
+ }
+#endif
+ return general_set_int(p, &val, sizeof(val));
+}
+
+OSSL_PARAM OSSL_PARAM_construct_time_t(const char *key, time_t *buf)
+{
+ return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(time_t));
+}
+
+int OSSL_PARAM_get_BN(const OSSL_PARAM *p, BIGNUM **val)
+{
+ BIGNUM *b;
+
+ if (val == NULL
+ || p == NULL
+ || p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
+ return 0;
+
+ b = BN_native2bn(p->data, (int)p->data_size, *val);
+ if (b != NULL) {
+ *val = b;
+ return 1;
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_BN(OSSL_PARAM *p, const BIGNUM *val)
+{
+ size_t bytes;
+
+ if (p == NULL)
+ return 0;
+ p->return_size = 0;
+ if (val == NULL || p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
+ return 0;
+
+ /* For the moment, only positive values are permitted */
+ if (BN_is_negative(val))
+ return 0;
+
+ bytes = (size_t)BN_num_bytes(val);
+ /* We make sure that at least one byte is used, so zero is properly set */
+ if (bytes == 0)
+ bytes++;
+
+ p->return_size = bytes;
+ if (p->data == NULL)
+ return 1;
+ if (p->data_size >= bytes) {
+ p->return_size = p->data_size;
+ return BN_bn2nativepad(val, p->data, p->data_size) >= 0;
+ }
+ return 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_BN(const char *key, unsigned char *buf,
+ size_t bsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER,
+ buf, bsize);
+}
+
+int OSSL_PARAM_get_double(const OSSL_PARAM *p, double *val)
+{
+ int64_t i64;
+ uint64_t u64;
+
+ if (val == NULL || p == NULL)
+ return 0;
+
+ if (p->data_type == OSSL_PARAM_REAL) {
+ switch (p->data_size) {
+ case sizeof(double):
+ *val = *(const double *)p->data;
+ return 1;
+ }
+ } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ *val = *(const uint32_t *)p->data;
+ return 1;
+ case sizeof(uint64_t):
+ u64 = *(const uint64_t *)p->data;
+ if ((u64 >> real_shift()) == 0) {
+ *val = (double)u64;
+ return 1;
+ }
+ break;
+ }
+ } else if (p->data_type == OSSL_PARAM_INTEGER) {
+ switch (p->data_size) {
+ case sizeof(int32_t):
+ *val = *(const int32_t *)p->data;
+ return 1;
+ case sizeof(int64_t):
+ i64 = *(const int64_t *)p->data;
+ u64 = i64 < 0 ? -i64 : i64;
+ if ((u64 >> real_shift()) == 0) {
+ *val = 0.0 + i64;
+ return 1;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_double(OSSL_PARAM *p, double val)
+{
+ if (p == NULL)
+ return 0;
+ p->return_size = 0;
+
+ if (p->data_type == OSSL_PARAM_REAL) {
+ p->return_size = sizeof(double);
+ if (p->data == NULL)
+ return 1;
+ switch (p->data_size) {
+ case sizeof(double):
+ *(double *)p->data = val;
+ return 1;
+ }
+ } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER
+ && val == (uint64_t)val) {
+ p->return_size = sizeof(double);
+ if (p->data == NULL)
+ return 1;
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ if (val >= 0 && val <= UINT32_MAX) {
+ p->return_size = sizeof(uint32_t);
+ *(uint32_t *)p->data = (uint32_t)val;
+ return 1;
+ }
+ break;
+ case sizeof(uint64_t):
+ if (val >= 0
+ /*
+ * By subtracting 65535 (2^16-1) we cancel the low order
+ * 15 bits of UINT64_MAX to avoid using imprecise floating
+ * point values.
+ */
+ && val < (double)(UINT64_MAX - 65535) + 65536.0) {
+ p->return_size = sizeof(uint64_t);
+ *(uint64_t *)p->data = (uint64_t)val;
+ return 1;
+ }
+ break; }
+ } else if (p->data_type == OSSL_PARAM_INTEGER && val == (int64_t)val) {
+ p->return_size = sizeof(double);
+ if (p->data == NULL)
+ return 1;
+ switch (p->data_size) {
+ case sizeof(int32_t):
+ if (val >= INT32_MIN && val <= INT32_MAX) {
+ p->return_size = sizeof(int32_t);
+ *(int32_t *)p->data = (int32_t)val;
+ return 1;
+ }
+ break;
+ case sizeof(int64_t):
+ if (val >= INT64_MIN
+ /*
+ * By subtracting 65535 (2^16-1) we cancel the low order
+ * 15 bits of INT64_MAX to avoid using imprecise floating
+ * point values.
+ */
+ && val < (double)(INT64_MAX - 65535) + 65536.0) {
+ p->return_size = sizeof(int64_t);
+ *(int64_t *)p->data = (int64_t)val;
+ return 1;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_double(const char *key, double *buf)
+{
+ return ossl_param_construct(key, OSSL_PARAM_REAL, buf, sizeof(double));
+}
+
+static int get_string_internal(const OSSL_PARAM *p, void **val,
+ size_t *max_len, size_t *used_len,
+ unsigned int type)
+{
+ size_t sz, alloc_sz;
+
+ if ((val == NULL && used_len == NULL) || p == NULL || p->data_type != type)
+ return 0;
+
+ sz = p->data_size;
+ /*
+ * If the input size is 0, or the input string needs NUL byte
+ * termination, allocate an extra byte.
+ */
+ alloc_sz = sz + (type == OSSL_PARAM_UTF8_STRING || sz == 0);
+
+ if (used_len != NULL)
+ *used_len = sz;
+
+ if (p->data == NULL)
+ return 0;
+
+ if (val == NULL)
+ return 1;
+
+ if (*val == NULL) {
+ char *const q = OPENSSL_malloc(alloc_sz);
+
+ if (q == NULL)
+ return 0;
+ *val = q;
+ *max_len = alloc_sz;
+ }
+
+ if (*max_len < sz)
+ return 0;
+ memcpy(*val, p->data, sz);
+ return 1;
+}
+
+int OSSL_PARAM_get_utf8_string(const OSSL_PARAM *p, char **val, size_t max_len)
+{
+ int ret = get_string_internal(p, (void **)val, &max_len, NULL,
+ OSSL_PARAM_UTF8_STRING);
+
+ /*
+ * We try to ensure that the copied string is terminated with a
+ * NUL byte. That should be easy, just place a NUL byte at
+ * |((char*)*val)[p->data_size]|.
+ * Unfortunately, we have seen cases where |p->data_size| doesn't
+ * correctly reflect the length of the string, and just happens
+ * to be out of bounds according to |max_len|, so in that case, we
+ * make the extra step of trying to find the true length of the
+ * string that |p->data| points at, and use that as an index to
+ * place the NUL byte in |*val|.
+ */
+ size_t data_length = p->data_size;
+
+ if (ret == 0)
+ return 0;
+ if (data_length >= max_len)
+ data_length = OPENSSL_strnlen(p->data, data_length);
+ if (data_length >= max_len)
+ return 0; /* No space for a terminating NUL byte */
+ (*val)[data_length] = '\0';
+
+ return ret;
+}
+
+int OSSL_PARAM_get_octet_string(const OSSL_PARAM *p, void **val, size_t max_len,
+ size_t *used_len)
+{
+ return get_string_internal(p, val, &max_len, used_len,
+ OSSL_PARAM_OCTET_STRING);
+}
+
+static int set_string_internal(OSSL_PARAM *p, const void *val, size_t len,
+ unsigned int type)
+{
+ p->return_size = len;
+ if (p->data == NULL)
+ return 1;
+ if (p->data_type != type || p->data_size < len)
+ return 0;
+
+ memcpy(p->data, val, len);
+ /* If possible within the size of p->data, add a NUL terminator byte */
+ if (type == OSSL_PARAM_UTF8_STRING && p->data_size > len)
+ ((char *)p->data)[len] = '\0';
+ return 1;
+}
+
+int OSSL_PARAM_set_utf8_string(OSSL_PARAM *p, const char *val)
+{
+ if (p == NULL)
+ return 0;
+
+ p->return_size = 0;
+ if (val == NULL)
+ return 0;
+ return set_string_internal(p, val, strlen(val), OSSL_PARAM_UTF8_STRING);
+}
+
+int OSSL_PARAM_set_octet_string(OSSL_PARAM *p, const void *val,
+ size_t len)
+{
+ if (p == NULL)
+ return 0;
+
+ p->return_size = 0;
+ if (val == NULL)
+ return 0;
+ return set_string_internal(p, val, len, OSSL_PARAM_OCTET_STRING);
+}
+
+OSSL_PARAM OSSL_PARAM_construct_utf8_string(const char *key, char *buf,
+ size_t bsize)
+{
+ if (buf != NULL && bsize == 0)
+ bsize = strlen(buf);
+ return ossl_param_construct(key, OSSL_PARAM_UTF8_STRING, buf, bsize);
+}
+
+OSSL_PARAM OSSL_PARAM_construct_octet_string(const char *key, void *buf,
+ size_t bsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_OCTET_STRING, buf, bsize);
+}
+
+static int get_ptr_internal(const OSSL_PARAM *p, const void **val,
+ size_t *used_len, unsigned int type)
+{
+ if (val == NULL || p == NULL || p->data_type != type)
+ return 0;
+ if (used_len != NULL)
+ *used_len = p->data_size;
+ *val = *(const void **)p->data;
+ return 1;
+}
+
+int OSSL_PARAM_get_utf8_ptr(const OSSL_PARAM *p, const char **val)
+{
+ return get_ptr_internal(p, (const void **)val, NULL, OSSL_PARAM_UTF8_PTR);
+}
+
+int OSSL_PARAM_get_octet_ptr(const OSSL_PARAM *p, const void **val,
+ size_t *used_len)
+{
+ return get_ptr_internal(p, val, used_len, OSSL_PARAM_OCTET_PTR);
+}
+
+static int set_ptr_internal(OSSL_PARAM *p, const void *val,
+ unsigned int type, size_t len)
+{
+ p->return_size = len;
+ if (p->data_type != type)
+ return 0;
+ if (p->data != NULL)
+ *(const void **)p->data = val;
+ return 1;
+}
+
+int OSSL_PARAM_set_utf8_ptr(OSSL_PARAM *p, const char *val)
+{
+ if (p == NULL)
+ return 0;
+ p->return_size = 0;
+ return set_ptr_internal(p, val, OSSL_PARAM_UTF8_PTR,
+ val == NULL ? 0 : strlen(val));
+}
+
+int OSSL_PARAM_set_octet_ptr(OSSL_PARAM *p, const void *val,
+ size_t used_len)
+{
+ if (p == NULL)
+ return 0;
+ p->return_size = 0;
+ return set_ptr_internal(p, val, OSSL_PARAM_OCTET_PTR, used_len);
+}
+
+OSSL_PARAM OSSL_PARAM_construct_utf8_ptr(const char *key, char **buf,
+ size_t bsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_UTF8_PTR, buf, bsize);
+}
+
+OSSL_PARAM OSSL_PARAM_construct_octet_ptr(const char *key, void **buf,
+ size_t bsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_OCTET_PTR, buf, bsize);
+}
+
+OSSL_PARAM OSSL_PARAM_construct_end(void)
+{
+ OSSL_PARAM end = OSSL_PARAM_END;
+
+ return end;
+}
+
+static int get_string_ptr_internal(const OSSL_PARAM *p, const void **val,
+ size_t *used_len, unsigned int type)
+{
+ if (val == NULL || p == NULL || p->data_type != type)
+ return 0;
+ if (used_len != NULL)
+ *used_len = p->data_size;
+ *val = p->data;
+ return 1;
+}
+
+int OSSL_PARAM_get_utf8_string_ptr(const OSSL_PARAM *p, const char **val)
+{
+ return OSSL_PARAM_get_utf8_ptr(p, val)
+ || get_string_ptr_internal(p, (const void **)val, NULL,
+ OSSL_PARAM_UTF8_STRING);
+}
+
+int OSSL_PARAM_get_octet_string_ptr(const OSSL_PARAM *p, const void **val,
+ size_t *used_len)
+{
+ return OSSL_PARAM_get_octet_ptr(p, val, used_len)
+ || get_string_ptr_internal(p, val, used_len, OSSL_PARAM_OCTET_STRING);
+}
diff --git a/crypto/params_dup.c b/crypto/params_dup.c
new file mode 100644
index 000000000000..bc1546fc53cb
--- /dev/null
+++ b/crypto/params_dup.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/params.h>
+#include <openssl/param_build.h>
+#include "internal/param_build_set.h"
+
+#define OSSL_PARAM_ALLOCATED_END 127
+#define OSSL_PARAM_MERGE_LIST_MAX 128
+
+#define OSSL_PARAM_BUF_PUBLIC 0
+#define OSSL_PARAM_BUF_SECURE 1
+#define OSSL_PARAM_BUF_MAX (OSSL_PARAM_BUF_SECURE + 1)
+
+typedef struct {
+ OSSL_PARAM_ALIGNED_BLOCK *alloc; /* The allocated buffer */
+ OSSL_PARAM_ALIGNED_BLOCK *cur; /* Current position in the allocated buf */
+ size_t blocks; /* Number of aligned blocks */
+ size_t alloc_sz; /* The size of the allocated buffer (in bytes) */
+} OSSL_PARAM_BUF;
+
+size_t ossl_param_bytes_to_blocks(size_t bytes)
+{
+ return (bytes + OSSL_PARAM_ALIGN_SIZE - 1) / OSSL_PARAM_ALIGN_SIZE;
+}
+
+static int ossl_param_buf_alloc(OSSL_PARAM_BUF *out, size_t extra_blocks,
+ int is_secure)
+{
+ size_t sz = OSSL_PARAM_ALIGN_SIZE * (extra_blocks + out->blocks);
+
+ out->alloc = is_secure ? OPENSSL_secure_zalloc(sz) : OPENSSL_zalloc(sz);
+ if (out->alloc == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, is_secure ? CRYPTO_R_SECURE_MALLOC_FAILURE
+ : ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ out->alloc_sz = sz;
+ out->cur = out->alloc + extra_blocks;
+ return 1;
+}
+
+void ossl_param_set_secure_block(OSSL_PARAM *last, void *secure_buffer,
+ size_t secure_buffer_sz)
+{
+ last->key = NULL;
+ last->data_size = secure_buffer_sz;
+ last->data = secure_buffer;
+ last->data_type = OSSL_PARAM_ALLOCATED_END;
+}
+
+static OSSL_PARAM *ossl_param_dup(const OSSL_PARAM *src, OSSL_PARAM *dst,
+ OSSL_PARAM_BUF buf[OSSL_PARAM_BUF_MAX],
+ int *param_count)
+{
+ const OSSL_PARAM *in;
+ int has_dst = (dst != NULL);
+ int is_secure;
+ size_t param_sz, blks;
+
+ for (in = src; in->key != NULL; in++) {
+ is_secure = CRYPTO_secure_allocated(in->data);
+ if (has_dst) {
+ *dst = *in;
+ dst->data = buf[is_secure].cur;
+ }
+
+ if (in->data_type == OSSL_PARAM_OCTET_PTR
+ || in->data_type == OSSL_PARAM_UTF8_PTR) {
+ param_sz = sizeof(in->data);
+ if (has_dst)
+ *((const void **)dst->data) = *(const void **)in->data;
+ } else {
+ param_sz = in->data_size;
+ if (has_dst)
+ memcpy(dst->data, in->data, param_sz);
+ }
+ if (in->data_type == OSSL_PARAM_UTF8_STRING)
+ param_sz++; /* NULL terminator */
+ blks = ossl_param_bytes_to_blocks(param_sz);
+
+ if (has_dst) {
+ dst++;
+ buf[is_secure].cur += blks;
+ } else {
+ buf[is_secure].blocks += blks;
+ }
+ if (param_count != NULL)
+ ++*param_count;
+ }
+ return dst;
+}
+
+OSSL_PARAM *OSSL_PARAM_dup(const OSSL_PARAM *src)
+{
+ size_t param_blocks;
+ OSSL_PARAM_BUF buf[OSSL_PARAM_BUF_MAX];
+ OSSL_PARAM *last, *dst;
+ int param_count = 1; /* Include terminator in the count */
+
+ if (src == NULL)
+ return NULL;
+
+ memset(buf, 0, sizeof(buf));
+
+ /* First Pass: get the param_count and block sizes required */
+ (void)ossl_param_dup(src, NULL, buf, &param_count);
+
+ param_blocks = ossl_param_bytes_to_blocks(param_count * sizeof(*src));
+ /*
+ * The allocated buffer consists of an array of OSSL_PARAM followed by
+ * aligned data bytes that the array elements will point to.
+ */
+ if (!ossl_param_buf_alloc(&buf[OSSL_PARAM_BUF_PUBLIC], param_blocks, 0))
+ return NULL;
+
+ /* Allocate a secure memory buffer if required */
+ if (buf[OSSL_PARAM_BUF_SECURE].blocks > 0
+ && !ossl_param_buf_alloc(&buf[OSSL_PARAM_BUF_SECURE], 0, 1)) {
+ OPENSSL_free(buf[OSSL_PARAM_BUF_PUBLIC].alloc);
+ return NULL;
+ }
+
+ dst = (OSSL_PARAM *)buf[OSSL_PARAM_BUF_PUBLIC].alloc;
+ last = ossl_param_dup(src, dst, buf, NULL);
+ /* Store the allocated secure memory buffer in the last param block */
+ ossl_param_set_secure_block(last, buf[OSSL_PARAM_BUF_SECURE].alloc,
+ buf[OSSL_PARAM_BUF_SECURE].alloc_sz);
+ return dst;
+}
+
+static int compare_params(const void *left, const void *right)
+{
+ const OSSL_PARAM *l = *(const OSSL_PARAM **)left;
+ const OSSL_PARAM *r = *(const OSSL_PARAM **)right;
+
+ return OPENSSL_strcasecmp(l->key, r->key);
+}
+
+OSSL_PARAM *OSSL_PARAM_merge(const OSSL_PARAM *p1, const OSSL_PARAM *p2)
+{
+ const OSSL_PARAM *list1[OSSL_PARAM_MERGE_LIST_MAX + 1];
+ const OSSL_PARAM *list2[OSSL_PARAM_MERGE_LIST_MAX + 1];
+ const OSSL_PARAM *p = NULL;
+ const OSSL_PARAM **p1cur, **p2cur;
+ OSSL_PARAM *params, *dst;
+ size_t list1_sz = 0, list2_sz = 0;
+ int diff;
+
+ if (p1 == NULL && p2 == NULL)
+ return NULL;
+
+ /* Copy p1 to list1 */
+ if (p1 != NULL) {
+ for (p = p1; p->key != NULL && list1_sz < OSSL_PARAM_MERGE_LIST_MAX; p++)
+ list1[list1_sz++] = p;
+ }
+ list1[list1_sz] = NULL;
+
+ /* copy p2 to a list2 */
+ if (p2 != NULL) {
+ for (p = p2; p->key != NULL && list2_sz < OSSL_PARAM_MERGE_LIST_MAX; p++)
+ list2[list2_sz++] = p;
+ }
+ list2[list2_sz] = NULL;
+ if (list1_sz == 0 && list2_sz == 0)
+ return NULL;
+
+ /* Sort the 2 lists */
+ qsort(list1, list1_sz, sizeof(OSSL_PARAM *), compare_params);
+ qsort(list2, list2_sz, sizeof(OSSL_PARAM *), compare_params);
+
+ /* Allocate enough space to store the merged parameters */
+ params = OPENSSL_zalloc((list1_sz + list2_sz + 1) * sizeof(*p1));
+ if (params == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ dst = params;
+ p1cur = list1;
+ p2cur = list2;
+ while (1) {
+ /* If list1 is finished just tack list2 onto the end */
+ if (*p1cur == NULL) {
+ do {
+ *dst++ = **p2cur;
+ p2cur++;
+ } while (*p2cur != NULL);
+ break;
+ }
+ /* If list2 is finished just tack list1 onto the end */
+ if (*p2cur == NULL) {
+ do {
+ *dst++ = **p1cur;
+ p1cur++;
+ } while (*p1cur != NULL);
+ break;
+ }
+ /* consume the list element with the smaller key */
+ diff = OPENSSL_strcasecmp((*p1cur)->key, (*p2cur)->key);
+ if (diff == 0) {
+ /* If the keys are the same then throw away the list1 element */
+ *dst++ = **p2cur;
+ p2cur++;
+ p1cur++;
+ } else if (diff > 0) {
+ *dst++ = **p2cur;
+ p2cur++;
+ } else {
+ *dst++ = **p1cur;
+ p1cur++;
+ }
+ }
+ return params;
+}
+
+void OSSL_PARAM_free(OSSL_PARAM *params)
+{
+ if (params != NULL) {
+ OSSL_PARAM *p;
+
+ for (p = params; p->key != NULL; p++)
+ ;
+ if (p->data_type == OSSL_PARAM_ALLOCATED_END)
+ OPENSSL_secure_clear_free(p->data, p->data_size);
+ OPENSSL_free(params);
+ }
+}
diff --git a/crypto/params_from_text.c b/crypto/params_from_text.c
new file mode 100644
index 000000000000..360f8933e135
--- /dev/null
+++ b/crypto/params_from_text.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/ebcdic.h>
+#include <openssl/err.h>
+#include <openssl/params.h>
+
+/*
+ * When processing text to params, we're trying to be smart with numbers.
+ * Instead of handling each specific separate integer type, we use a bignum
+ * and ensure that it isn't larger than the expected size, and we then make
+ * sure it is the expected size... if there is one given.
+ * (if the size can be arbitrary, then we give whatever we have)
+ */
+
+static int prepare_from_text(const OSSL_PARAM *paramdefs, const char *key,
+ const char *value, size_t value_n,
+ /* Output parameters */
+ const OSSL_PARAM **paramdef, int *ishex,
+ size_t *buf_n, BIGNUM **tmpbn, int *found)
+{
+ const OSSL_PARAM *p;
+ size_t buf_bits;
+ int r;
+
+ /*
+ * ishex is used to translate legacy style string controls in hex format
+ * to octet string parameters.
+ */
+ *ishex = strncmp(key, "hex", 3) == 0;
+
+ if (*ishex)
+ key += 3;
+
+ p = *paramdef = OSSL_PARAM_locate_const(paramdefs, key);
+ if (found != NULL)
+ *found = p != NULL;
+ if (p == NULL)
+ return 0;
+
+ switch (p->data_type) {
+ case OSSL_PARAM_INTEGER:
+ case OSSL_PARAM_UNSIGNED_INTEGER:
+ if (*ishex)
+ r = BN_hex2bn(tmpbn, value);
+ else
+ r = BN_asc2bn(tmpbn, value);
+
+ if (r == 0 || *tmpbn == NULL)
+ return 0;
+
+ if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER
+ && BN_is_negative(*tmpbn)) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_INVALID_NEGATIVE_VALUE);
+ return 0;
+ }
+
+ /*
+ * 2's complement negate, part 1
+ *
+ * BN_bn2nativepad puts the absolute value of the number in the
+ * buffer, i.e. if it's negative, we need to deal with it. We do
+ * it by subtracting 1 here and inverting the bytes in
+ * construct_from_text() below.
+ * To subtract 1 from an absolute value of a negative number we
+ * actually have to add 1: -3 - 1 = -4, |-3| = 3 + 1 = 4.
+ */
+ if (p->data_type == OSSL_PARAM_INTEGER && BN_is_negative(*tmpbn)
+ && !BN_add_word(*tmpbn, 1)) {
+ return 0;
+ }
+
+ buf_bits = (size_t)BN_num_bits(*tmpbn);
+
+ /*
+ * Compensate for cases where the most significant bit in
+ * the resulting OSSL_PARAM buffer will be set after the
+ * BN_bn2nativepad() call, as the implied sign may not be
+ * correct after the second part of the 2's complement
+ * negation has been performed.
+ * We fix these cases by extending the buffer by one byte
+ * (8 bits), which will give some padding. The second part
+ * of the 2's complement negation will do the rest.
+ */
+ if (p->data_type == OSSL_PARAM_INTEGER && buf_bits % 8 == 0)
+ buf_bits += 8;
+
+ *buf_n = (buf_bits + 7) / 8;
+
+ /*
+ * A zero data size means "arbitrary size", so only do the
+ * range checking if a size is specified.
+ */
+ if (p->data_size > 0) {
+ if (buf_bits > p->data_size * 8) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_SMALL_BUFFER);
+ /* Since this is a different error, we don't break */
+ return 0;
+ }
+ /* Change actual size to become the desired size. */
+ *buf_n = p->data_size;
+ }
+ break;
+ case OSSL_PARAM_UTF8_STRING:
+ if (*ishex) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ *buf_n = strlen(value) + 1;
+ break;
+ case OSSL_PARAM_OCTET_STRING:
+ if (*ishex) {
+ *buf_n = strlen(value) >> 1;
+ } else {
+ *buf_n = value_n;
+ }
+ break;
+ }
+
+ return 1;
+}
+
+static int construct_from_text(OSSL_PARAM *to, const OSSL_PARAM *paramdef,
+ const char *value, size_t value_n, int ishex,
+ void *buf, size_t buf_n, BIGNUM *tmpbn)
+{
+ if (buf == NULL)
+ return 0;
+
+ if (buf_n > 0) {
+ switch (paramdef->data_type) {
+ case OSSL_PARAM_INTEGER:
+ case OSSL_PARAM_UNSIGNED_INTEGER:
+ /*
+ {
+ if ((new_value = OPENSSL_malloc(new_value_n)) == NULL) {
+ BN_free(a);
+ break;
+ }
+ */
+
+ BN_bn2nativepad(tmpbn, buf, buf_n);
+
+ /*
+ * 2's complement negation, part two.
+ *
+ * Because we did the first part on the BIGNUM itself, we can just
+ * invert all the bytes here and be done with it.
+ */
+ if (paramdef->data_type == OSSL_PARAM_INTEGER
+ && BN_is_negative(tmpbn)) {
+ unsigned char *cp;
+ size_t i = buf_n;
+
+ for (cp = buf; i-- > 0; cp++)
+ *cp ^= 0xFF;
+ }
+ break;
+ case OSSL_PARAM_UTF8_STRING:
+#ifdef CHARSET_EBCDIC
+ ebcdic2ascii(buf, value, buf_n);
+#else
+ strncpy(buf, value, buf_n);
+#endif
+ /* Don't count the terminating NUL byte as data */
+ buf_n--;
+ break;
+ case OSSL_PARAM_OCTET_STRING:
+ if (ishex) {
+ size_t l = 0;
+
+ if (!OPENSSL_hexstr2buf_ex(buf, buf_n, &l, value, ':'))
+ return 0;
+ } else {
+ memcpy(buf, value, buf_n);
+ }
+ break;
+ }
+ }
+
+ *to = *paramdef;
+ to->data = buf;
+ to->data_size = buf_n;
+ to->return_size = OSSL_PARAM_UNMODIFIED;
+
+ return 1;
+}
+
+int OSSL_PARAM_allocate_from_text(OSSL_PARAM *to,
+ const OSSL_PARAM *paramdefs,
+ const char *key, const char *value,
+ size_t value_n, int *found)
+{
+ const OSSL_PARAM *paramdef = NULL;
+ int ishex = 0;
+ void *buf = NULL;
+ size_t buf_n = 0;
+ BIGNUM *tmpbn = NULL;
+ int ok = 0;
+
+ if (to == NULL || paramdefs == NULL)
+ return 0;
+
+ if (!prepare_from_text(paramdefs, key, value, value_n,
+ &paramdef, &ishex, &buf_n, &tmpbn, found))
+ goto err;
+
+ if ((buf = OPENSSL_zalloc(buf_n > 0 ? buf_n : 1)) == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ ok = construct_from_text(to, paramdef, value, value_n, ishex,
+ buf, buf_n, tmpbn);
+ BN_free(tmpbn);
+ if (!ok)
+ OPENSSL_free(buf);
+ return ok;
+ err:
+ BN_free(tmpbn);
+ return 0;
+}
diff --git a/crypto/pariscid.pl b/crypto/pariscid.pl
index f4d364754a1f..bad337545740 100644
--- a/crypto/pariscid.pl
+++ b/crypto/pariscid.pl
@@ -1,15 +1,18 @@
#! /usr/bin/env perl
# Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
-$flavour = shift;
-$output = shift;
-open STDOUT,">$output";
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+
+$output and open STDOUT,">$output";
if ($flavour =~ /64/) {
$LEVEL ="2.0W";
diff --git a/crypto/passphrase.c b/crypto/passphrase.c
new file mode 100644
index 000000000000..fcc40f6dab53
--- /dev/null
+++ b/crypto/passphrase.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/ui.h>
+#include <openssl/core_names.h>
+#include "internal/cryptlib.h"
+#include "internal/passphrase.h"
+
+void ossl_pw_clear_passphrase_data(struct ossl_passphrase_data_st *data)
+{
+ if (data != NULL) {
+ if (data->type == is_expl_passphrase)
+ OPENSSL_clear_free(data->_.expl_passphrase.passphrase_copy,
+ data->_.expl_passphrase.passphrase_len);
+ ossl_pw_clear_passphrase_cache(data);
+ memset(data, 0, sizeof(*data));
+ }
+}
+
+void ossl_pw_clear_passphrase_cache(struct ossl_passphrase_data_st *data)
+{
+ OPENSSL_clear_free(data->cached_passphrase, data->cached_passphrase_len);
+ data->cached_passphrase = NULL;
+}
+
+int ossl_pw_set_passphrase(struct ossl_passphrase_data_st *data,
+ const unsigned char *passphrase,
+ size_t passphrase_len)
+{
+ if (!ossl_assert(data != NULL && passphrase != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ ossl_pw_clear_passphrase_data(data);
+ data->type = is_expl_passphrase;
+ data->_.expl_passphrase.passphrase_copy =
+ passphrase_len != 0 ? OPENSSL_memdup(passphrase, passphrase_len)
+ : OPENSSL_malloc(1);
+ if (data->_.expl_passphrase.passphrase_copy == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ data->_.expl_passphrase.passphrase_len = passphrase_len;
+ return 1;
+}
+
+int ossl_pw_set_pem_password_cb(struct ossl_passphrase_data_st *data,
+ pem_password_cb *cb, void *cbarg)
+{
+ if (!ossl_assert(data != NULL && cb != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ ossl_pw_clear_passphrase_data(data);
+ data->type = is_pem_password;
+ data->_.pem_password.password_cb = cb;
+ data->_.pem_password.password_cbarg = cbarg;
+ return 1;
+}
+
+int ossl_pw_set_ossl_passphrase_cb(struct ossl_passphrase_data_st *data,
+ OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+{
+ if (!ossl_assert(data != NULL && cb != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ ossl_pw_clear_passphrase_data(data);
+ data->type = is_ossl_passphrase;
+ data->_.ossl_passphrase.passphrase_cb = cb;
+ data->_.ossl_passphrase.passphrase_cbarg = cbarg;
+ return 1;
+}
+
+int ossl_pw_set_ui_method(struct ossl_passphrase_data_st *data,
+ const UI_METHOD *ui_method, void *ui_data)
+{
+ if (!ossl_assert(data != NULL && ui_method != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ ossl_pw_clear_passphrase_data(data);
+ data->type = is_ui_method;
+ data->_.ui_method.ui_method = ui_method;
+ data->_.ui_method.ui_method_data = ui_data;
+ return 1;
+}
+
+int ossl_pw_enable_passphrase_caching(struct ossl_passphrase_data_st *data)
+{
+ data->flag_cache_passphrase = 1;
+ return 1;
+}
+
+int ossl_pw_disable_passphrase_caching(struct ossl_passphrase_data_st *data)
+{
+ data->flag_cache_passphrase = 0;
+ return 1;
+}
+
+
+/*-
+ * UI_METHOD processor. It differs from UI_UTIL_read_pw() like this:
+ *
+ * 1. It constructs a prompt on its own, based on |prompt_info|.
+ * 2. It allocates a buffer for password and verification on its own
+ * to compensate for NUL terminator in UI password strings.
+ * 3. It raises errors.
+ * 4. It reports back the length of the prompted pass phrase.
+ */
+static int do_ui_passphrase(char *pass, size_t pass_size, size_t *pass_len,
+ const char *prompt_info, int verify,
+ const UI_METHOD *ui_method, void *ui_data)
+{
+ char *prompt = NULL, *ipass = NULL, *vpass = NULL;
+ int prompt_idx = -1, verify_idx = -1, res;
+ UI *ui = NULL;
+ int ret = 0;
+
+ if (!ossl_assert(pass != NULL && pass_size != 0 && pass_len != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if ((ui = UI_new()) == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (ui_method != NULL) {
+ UI_set_method(ui, ui_method);
+ if (ui_data != NULL)
+ UI_add_user_data(ui, ui_data);
+ }
+
+ /* Get an application constructed prompt */
+ prompt = UI_construct_prompt(ui, "pass phrase", prompt_info);
+ if (prompt == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+
+ /* Get a buffer for verification prompt */
+ ipass = OPENSSL_zalloc(pass_size + 1);
+ if (ipass == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+
+ prompt_idx = UI_add_input_string(ui, prompt,
+ UI_INPUT_FLAG_DEFAULT_PWD,
+ ipass, 0, pass_size) - 1;
+ if (prompt_idx < 0) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_UI_LIB);
+ goto end;
+ }
+
+ if (verify) {
+ /* Get a buffer for verification prompt */
+ vpass = OPENSSL_zalloc(pass_size + 1);
+ if (vpass == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+ verify_idx = UI_add_verify_string(ui, prompt,
+ UI_INPUT_FLAG_DEFAULT_PWD,
+ vpass, 0, pass_size,
+ ipass) - 1;
+ if (verify_idx < 0) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_UI_LIB);
+ goto end;
+ }
+ }
+
+ switch (UI_process(ui)) {
+ case -2:
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERRUPTED_OR_CANCELLED);
+ break;
+ case -1:
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_UI_LIB);
+ break;
+ default:
+ res = UI_get_result_length(ui, prompt_idx);
+ if (res < 0) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_UI_LIB);
+ break;
+ }
+ *pass_len = (size_t)res;
+ memcpy(pass, ipass, *pass_len);
+ ret = 1;
+ break;
+ }
+
+ end:
+ OPENSSL_clear_free(vpass, pass_size + 1);
+ OPENSSL_clear_free(ipass, pass_size + 1);
+ OPENSSL_free(prompt);
+ UI_free(ui);
+ return ret;
+}
+
+/* Central pw prompting dispatcher */
+int ossl_pw_get_passphrase(char *pass, size_t pass_size, size_t *pass_len,
+ const OSSL_PARAM params[], int verify,
+ struct ossl_passphrase_data_st *data)
+{
+ const char *source = NULL;
+ size_t source_len = 0;
+ const char *prompt_info = NULL;
+ const UI_METHOD *ui_method = NULL;
+ UI_METHOD *allocated_ui_method = NULL;
+ void *ui_data = NULL;
+ const OSSL_PARAM *p = NULL;
+ int ret;
+
+ /* Handle explicit and cached passphrases */
+
+ if (data->type == is_expl_passphrase) {
+ source = data->_.expl_passphrase.passphrase_copy;
+ source_len = data->_.expl_passphrase.passphrase_len;
+ } else if (data->flag_cache_passphrase && data->cached_passphrase != NULL) {
+ source = data->cached_passphrase;
+ source_len = data->cached_passphrase_len;
+ }
+
+ if (source != NULL) {
+ if (source_len > pass_size)
+ source_len = pass_size;
+ memcpy(pass, source, source_len);
+ *pass_len = source_len;
+ return 1;
+ }
+
+ /* Handle the is_ossl_passphrase case... that's pretty direct */
+
+ if (data->type == is_ossl_passphrase) {
+ OSSL_PASSPHRASE_CALLBACK *cb = data->_.ossl_passphrase.passphrase_cb;
+ void *cbarg = data->_.ossl_passphrase.passphrase_cbarg;
+
+ ret = cb(pass, pass_size, pass_len, params, cbarg);
+ goto do_cache;
+ }
+
+ /* Handle the is_pem_password and is_ui_method cases */
+
+ if ((p = OSSL_PARAM_locate_const(params,
+ OSSL_PASSPHRASE_PARAM_INFO)) != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING) {
+ ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT,
+ "Prompt info data type incorrect");
+ return 0;
+ }
+ prompt_info = p->data;
+ }
+
+ if (data->type == is_pem_password) {
+ /* We use a UI wrapper for PEM */
+ pem_password_cb *cb = data->_.pem_password.password_cb;
+
+ ui_method = allocated_ui_method =
+ UI_UTIL_wrap_read_pem_callback(cb, verify);
+ ui_data = data->_.pem_password.password_cbarg;
+
+ if (ui_method == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else if (data->type == is_ui_method) {
+ ui_method = data->_.ui_method.ui_method;
+ ui_data = data->_.ui_method.ui_method_data;
+ }
+
+ if (ui_method == NULL) {
+ ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT,
+ "No password method specified");
+ return 0;
+ }
+
+ ret = do_ui_passphrase(pass, pass_size, pass_len, prompt_info, verify,
+ ui_method, ui_data);
+
+ UI_destroy_method(allocated_ui_method);
+
+ do_cache:
+ if (ret && data->flag_cache_passphrase) {
+ if (data->cached_passphrase == NULL
+ || *pass_len > data->cached_passphrase_len) {
+ void *new_cache =
+ OPENSSL_clear_realloc(data->cached_passphrase,
+ data->cached_passphrase_len,
+ *pass_len + 1);
+
+ if (new_cache == NULL) {
+ OPENSSL_cleanse(pass, *pass_len);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ data->cached_passphrase = new_cache;
+ }
+ memcpy(data->cached_passphrase, pass, *pass_len);
+ data->cached_passphrase[*pass_len] = '\0';
+ data->cached_passphrase_len = *pass_len;
+ }
+
+ return ret;
+}
+
+static int ossl_pw_get_password(char *buf, int size, int rwflag,
+ void *userdata, const char *info)
+{
+ size_t password_len = 0;
+ OSSL_PARAM params[] = {
+ OSSL_PARAM_utf8_string(OSSL_PASSPHRASE_PARAM_INFO, NULL, 0),
+ OSSL_PARAM_END
+ };
+
+ params[0].data = (void *)info;
+ if (ossl_pw_get_passphrase(buf, (size_t)size, &password_len, params,
+ rwflag, userdata))
+ return (int)password_len;
+ return -1;
+}
+
+int ossl_pw_pem_password(char *buf, int size, int rwflag, void *userdata)
+{
+ return ossl_pw_get_password(buf, size, rwflag, userdata, "PEM");
+}
+
+int ossl_pw_pvk_password(char *buf, int size, int rwflag, void *userdata)
+{
+ return ossl_pw_get_password(buf, size, rwflag, userdata, "PVK");
+}
+
+int ossl_pw_passphrase_callback_enc(char *pass, size_t pass_size,
+ size_t *pass_len,
+ const OSSL_PARAM params[], void *arg)
+{
+ return ossl_pw_get_passphrase(pass, pass_size, pass_len, params, 1, arg);
+}
+
+int ossl_pw_passphrase_callback_dec(char *pass, size_t pass_size,
+ size_t *pass_len,
+ const OSSL_PARAM params[], void *arg)
+{
+ return ossl_pw_get_passphrase(pass, pass_size, pass_len, params, 0, arg);
+}
diff --git a/crypto/pem/pem_all.c b/crypto/pem/pem_all.c
index 9d57ee7cc2e5..222af64397b4 100644
--- a/crypto/pem/pem_all.c
+++ b/crypto/pem/pem_all.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bio.h>
@@ -17,10 +23,9 @@
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/dh.h>
+#include "pem_local.h"
-#ifndef OPENSSL_NO_RSA
static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa);
-#endif
#ifndef OPENSSL_NO_DSA
static DSA *pkey_get_dsa(EVP_PKEY *key, DSA **dsa);
#endif
@@ -33,11 +38,12 @@ IMPLEMENT_PEM_rw(X509_REQ, X509_REQ, PEM_STRING_X509_REQ, X509_REQ)
IMPLEMENT_PEM_write(X509_REQ_NEW, X509_REQ, PEM_STRING_X509_REQ_OLD, X509_REQ)
IMPLEMENT_PEM_rw(X509_CRL, X509_CRL, PEM_STRING_X509_CRL, X509_CRL)
+IMPLEMENT_PEM_rw(X509_PUBKEY, X509_PUBKEY, PEM_STRING_PUBLIC, X509_PUBKEY)
IMPLEMENT_PEM_rw(PKCS7, PKCS7, PEM_STRING_PKCS7, PKCS7)
IMPLEMENT_PEM_rw(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE,
PEM_STRING_X509, NETSCAPE_CERT_SEQUENCE)
-#ifndef OPENSSL_NO_RSA
+#ifndef OPENSSL_NO_DEPRECATED_3_0
/*
* We treat RSA or DSA private keys as a special case. For private keys we
* read in an EVP_PKEY structure with PEM_read_bio_PrivateKey() and extract
@@ -79,12 +85,8 @@ RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **rsa, pem_password_cb *cb, void *u)
# endif
-IMPLEMENT_PEM_write_cb_const(RSAPrivateKey, RSA, PEM_STRING_RSA,
- RSAPrivateKey)
-
-
-IMPLEMENT_PEM_rw_const(RSAPublicKey, RSA, PEM_STRING_RSA_PUBLIC,
- RSAPublicKey)
+IMPLEMENT_PEM_write_cb(RSAPrivateKey, RSA, PEM_STRING_RSA, RSAPrivateKey)
+IMPLEMENT_PEM_rw(RSAPublicKey, RSA, PEM_STRING_RSA_PUBLIC, RSAPublicKey)
IMPLEMENT_PEM_rw(RSA_PUBKEY, RSA, PEM_STRING_PUBLIC, RSA_PUBKEY)
#endif
#ifndef OPENSSL_NO_DSA
@@ -112,8 +114,7 @@ DSA *PEM_read_bio_DSAPrivateKey(BIO *bp, DSA **dsa, pem_password_cb *cb,
return pkey_get_dsa(pktmp, dsa); /* will free pktmp */
}
-IMPLEMENT_PEM_write_cb_const(DSAPrivateKey, DSA, PEM_STRING_DSA,
- DSAPrivateKey)
+IMPLEMENT_PEM_write_cb(DSAPrivateKey, DSA, PEM_STRING_DSA, DSAPrivateKey)
IMPLEMENT_PEM_rw(DSA_PUBKEY, DSA, PEM_STRING_PUBLIC, DSA_PUBKEY)
# ifndef OPENSSL_NO_STDIO
DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **dsa, pem_password_cb *cb, void *u)
@@ -125,9 +126,11 @@ DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **dsa, pem_password_cb *cb, void *u)
# endif
-IMPLEMENT_PEM_rw_const(DSAparams, DSA, PEM_STRING_DSAPARAMS, DSAparams)
+IMPLEMENT_PEM_rw(DSAparams, DSA, PEM_STRING_DSAPARAMS, DSAparams)
#endif
-#ifndef OPENSSL_NO_EC
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef OPENSSL_NO_EC
static EC_KEY *pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey)
{
EC_KEY *dtmp;
@@ -152,14 +155,14 @@ EC_KEY *PEM_read_bio_ECPrivateKey(BIO *bp, EC_KEY **key, pem_password_cb *cb,
return pkey_get_eckey(pktmp, key); /* will free pktmp */
}
-IMPLEMENT_PEM_rw_const(ECPKParameters, EC_GROUP, PEM_STRING_ECPARAMETERS,
- ECPKParameters)
+IMPLEMENT_PEM_rw(ECPKParameters, EC_GROUP, PEM_STRING_ECPARAMETERS,
+ ECPKParameters)
IMPLEMENT_PEM_write_cb(ECPrivateKey, EC_KEY, PEM_STRING_ECPRIVATEKEY,
ECPrivateKey)
IMPLEMENT_PEM_rw(EC_PUBKEY, EC_KEY, PEM_STRING_PUBLIC, EC_PUBKEY)
-# ifndef OPENSSL_NO_STDIO
+# ifndef OPENSSL_NO_STDIO
EC_KEY *PEM_read_ECPrivateKey(FILE *fp, EC_KEY **eckey, pem_password_cb *cb,
void *u)
{
@@ -167,14 +170,57 @@ EC_KEY *PEM_read_ECPrivateKey(FILE *fp, EC_KEY **eckey, pem_password_cb *cb,
pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
return pkey_get_eckey(pktmp, eckey); /* will free pktmp */
}
+# endif
+# endif /* !OPENSSL_NO_EC */
+#endif /* !OPENSSL_NO_DEPRECATED_3_0 */
-# endif
+#ifndef OPENSSL_NO_DH
-#endif
+IMPLEMENT_PEM_write(DHparams, DH, PEM_STRING_DHPARAMS, DHparams)
+IMPLEMENT_PEM_write(DHxparams, DH, PEM_STRING_DHXPARAMS, DHxparams)
-#ifndef OPENSSL_NO_DH
+/* Transparently read in PKCS#3 or X9.42 DH parameters */
+
+DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u)
+{
+ char *nm = NULL;
+ const unsigned char *p = NULL;
+ unsigned char *data = NULL;
+ long len;
+ DH *ret = NULL;
+
+ if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_DHPARAMS, bp, cb, u))
+ return NULL;
+ p = data;
+
+ if (strcmp(nm, PEM_STRING_DHXPARAMS) == 0)
+ ret = d2i_DHxparams(x, &p, len);
+ else
+ ret = d2i_DHparams(x, &p, len);
+
+ if (ret == NULL)
+ ERR_raise(ERR_LIB_PEM, ERR_R_ASN1_LIB);
+ OPENSSL_free(nm);
+ OPENSSL_free(data);
+ return ret;
+}
+
+# ifndef OPENSSL_NO_STDIO
+DH *PEM_read_DHparams(FILE *fp, DH **x, pem_password_cb *cb, void *u)
+{
+ BIO *b;
+ DH *ret;
+
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
+ return 0;
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ ret = PEM_read_bio_DHparams(b, x, cb, u);
+ BIO_free(b);
+ return ret;
+}
+# endif
-IMPLEMENT_PEM_write_const(DHparams, DH, PEM_STRING_DHPARAMS, DHparams)
-IMPLEMENT_PEM_write_const(DHxparams, DH, PEM_STRING_DHXPARAMS, DHxparams)
#endif
-IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY)
+IMPLEMENT_PEM_provided_write(PUBKEY, EVP_PKEY, pkey, PEM_STRING_PUBLIC, PUBKEY)
diff --git a/crypto/pem/pem_err.c b/crypto/pem/pem_err.c
index 0f3cb02407e6..5fa9fc09bec7 100644
--- a/crypto/pem/pem_err.c
+++ b/crypto/pem/pem_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,68 +10,10 @@
#include <openssl/err.h>
#include <openssl/pemerr.h>
+#include "crypto/pemerr.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA PEM_str_functs[] = {
- {ERR_PACK(ERR_LIB_PEM, PEM_F_B2I_DSS, 0), "b2i_dss"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_B2I_PVK_BIO, 0), "b2i_PVK_bio"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_B2I_RSA, 0), "b2i_rsa"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_CHECK_BITLEN_DSA, 0), "check_bitlen_dsa"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_CHECK_BITLEN_RSA, 0), "check_bitlen_rsa"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_D2I_PKCS8PRIVATEKEY_BIO, 0),
- "d2i_PKCS8PrivateKey_bio"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_D2I_PKCS8PRIVATEKEY_FP, 0),
- "d2i_PKCS8PrivateKey_fp"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_DO_B2I, 0), "do_b2i"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_DO_B2I_BIO, 0), "do_b2i_bio"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_DO_BLOB_HEADER, 0), "do_blob_header"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_DO_I2B, 0), "do_i2b"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_DO_PK8PKEY, 0), "do_pk8pkey"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_DO_PK8PKEY_FP, 0), "do_pk8pkey_fp"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_DO_PVK_BODY, 0), "do_PVK_body"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_DO_PVK_HEADER, 0), "do_PVK_header"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_GET_HEADER_AND_DATA, 0),
- "get_header_and_data"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_GET_NAME, 0), "get_name"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_I2B_PVK, 0), "i2b_PVK"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_I2B_PVK_BIO, 0), "i2b_PVK_bio"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_LOAD_IV, 0), "load_iv"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_ASN1_READ, 0), "PEM_ASN1_read"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_ASN1_READ_BIO, 0), "PEM_ASN1_read_bio"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_ASN1_WRITE, 0), "PEM_ASN1_write"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_ASN1_WRITE_BIO, 0), "PEM_ASN1_write_bio"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_DEF_CALLBACK, 0), "PEM_def_callback"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_DO_HEADER, 0), "PEM_do_header"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_GET_EVP_CIPHER_INFO, 0),
- "PEM_get_EVP_CIPHER_INFO"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ, 0), "PEM_read"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_BIO, 0), "PEM_read_bio"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_BIO_DHPARAMS, 0),
- "PEM_read_bio_DHparams"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_BIO_EX, 0), "PEM_read_bio_ex"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_BIO_PARAMETERS, 0),
- "PEM_read_bio_Parameters"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_BIO_PRIVATEKEY, 0),
- "PEM_read_bio_PrivateKey"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_DHPARAMS, 0), "PEM_read_DHparams"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_PRIVATEKEY, 0),
- "PEM_read_PrivateKey"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_SIGNFINAL, 0), "PEM_SignFinal"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_WRITE, 0), "PEM_write"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_WRITE_BIO, 0), "PEM_write_bio"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_WRITE_BIO_PRIVATEKEY_TRADITIONAL, 0),
- "PEM_write_bio_PrivateKey_traditional"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_WRITE_PRIVATEKEY, 0),
- "PEM_write_PrivateKey"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_X509_INFO_READ, 0), "PEM_X509_INFO_read"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_X509_INFO_READ_BIO, 0),
- "PEM_X509_INFO_read_bio"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_X509_INFO_WRITE_BIO, 0),
- "PEM_X509_INFO_write_bio"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA PEM_str_reasons[] = {
{ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_BASE64_DECODE), "bad base64 decode"},
{ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_DECRYPT), "bad decrypt"},
@@ -84,10 +26,14 @@ static const ERR_STRING_DATA PEM_str_reasons[] = {
{ERR_PACK(ERR_LIB_PEM, 0, PEM_R_CIPHER_IS_NULL), "cipher is null"},
{ERR_PACK(ERR_LIB_PEM, 0, PEM_R_ERROR_CONVERTING_PRIVATE_KEY),
"error converting private key"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_EXPECTING_DSS_KEY_BLOB),
+ "expecting dss key blob"},
{ERR_PACK(ERR_LIB_PEM, 0, PEM_R_EXPECTING_PRIVATE_KEY_BLOB),
"expecting private key blob"},
{ERR_PACK(ERR_LIB_PEM, 0, PEM_R_EXPECTING_PUBLIC_KEY_BLOB),
"expecting public key blob"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_EXPECTING_RSA_KEY_BLOB),
+ "expecting rsa key blob"},
{ERR_PACK(ERR_LIB_PEM, 0, PEM_R_HEADER_TOO_LONG), "header too long"},
{ERR_PACK(ERR_LIB_PEM, 0, PEM_R_INCONSISTENT_HEADER),
"inconsistent header"},
@@ -118,13 +64,11 @@ static const ERR_STRING_DATA PEM_str_reasons[] = {
#endif
-int ERR_load_PEM_strings(void)
+int ossl_err_load_PEM_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(PEM_str_functs[0].error) == NULL) {
- ERR_load_strings_const(PEM_str_functs);
+ if (ERR_reason_error_string(PEM_str_reasons[0].error) == NULL)
ERR_load_strings_const(PEM_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/pem/pem_info.c b/crypto/pem/pem_info.c
index f90cb4465096..061c9b9f68c8 100644
--- a/crypto/pem/pem_info.c
+++ b/crypto/pem/pem_info.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
@@ -16,30 +22,40 @@
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
+#include "crypto/evp.h"
#ifndef OPENSSL_NO_STDIO
-STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
- pem_password_cb *cb, void *u)
+STACK_OF(X509_INFO)
+*PEM_X509_INFO_read_ex(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb,
+ void *u, OSSL_LIB_CTX *libctx, const char *propq)
{
BIO *b;
STACK_OF(X509_INFO) *ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- PEMerr(PEM_F_PEM_X509_INFO_READ, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
- ret = PEM_X509_INFO_read_bio(b, sk, cb, u);
+ ret = PEM_X509_INFO_read_bio_ex(b, sk, cb, u, libctx, propq);
BIO_free(b);
return ret;
}
+
+STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
+ pem_password_cb *cb, void *u)
+{
+ return PEM_X509_INFO_read_ex(fp, sk, cb, u, NULL, NULL);
+}
#endif
-STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
- pem_password_cb *cb, void *u)
+STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx,
+ const char *propq)
{
X509_INFO *xi = NULL;
- char *name = NULL, *header = NULL;
+ char *name = NULL, *header = NULL, *str;
void *pp;
unsigned char *data = NULL;
const unsigned char *p;
@@ -51,7 +67,7 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
if (sk == NULL) {
if ((ret = sk_X509_INFO_new_null()) == NULL) {
- PEMerr(PEM_F_PEM_X509_INFO_READ_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
goto err;
}
} else
@@ -62,29 +78,22 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
for (;;) {
raw = 0;
ptype = 0;
+ ERR_set_mark();
i = PEM_read_bio(bp, &name, &header, &data, &len);
if (i == 0) {
error = ERR_GET_REASON(ERR_peek_last_error());
if (error == PEM_R_NO_START_LINE) {
- ERR_clear_error();
+ ERR_pop_to_mark();
break;
}
+ ERR_clear_last_mark();
goto err;
}
+ ERR_clear_last_mark();
start:
- if ((strcmp(name, PEM_STRING_X509) == 0) ||
- (strcmp(name, PEM_STRING_X509_OLD) == 0)) {
- d2i = (D2I_OF(void)) d2i_X509;
- if (xi->x509 != NULL) {
- if (!sk_X509_INFO_push(ret, xi))
- goto err;
- if ((xi = X509_INFO_new()) == NULL)
- goto err;
- goto start;
- }
- pp = &(xi->x509);
- } else if ((strcmp(name, PEM_STRING_X509_TRUSTED) == 0)) {
- d2i = (D2I_OF(void)) d2i_X509_AUX;
+ if (strcmp(name, PEM_STRING_X509) == 0
+ || strcmp(name, PEM_STRING_X509_OLD) == 0
+ || strcmp(name, PEM_STRING_X509_TRUSTED) == 0) {
if (xi->x509 != NULL) {
if (!sk_X509_INFO_push(ret, xi))
goto err;
@@ -92,6 +101,13 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
goto err;
goto start;
}
+ if ((strcmp(name, PEM_STRING_X509_TRUSTED) == 0))
+ d2i = (D2I_OF(void)) d2i_X509_AUX;
+ else
+ d2i = (D2I_OF(void)) d2i_X509;
+ xi->x509 = X509_new_ex(libctx, propq);
+ if (xi->x509 == NULL)
+ goto err;
pp = &(xi->x509);
} else if (strcmp(name, PEM_STRING_X509_CRL) == 0) {
d2i = (D2I_OF(void)) d2i_X509_CRL;
@@ -103,10 +119,7 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
goto start;
}
pp = &(xi->crl);
- } else
-#ifndef OPENSSL_NO_RSA
- if (strcmp(name, PEM_STRING_RSA) == 0) {
- d2i = (D2I_OF(void)) d2i_RSAPrivateKey;
+ } else if ((str = strstr(name, PEM_STRING_PKCS8INF)) != NULL) {
if (xi->x_pkey != NULL) {
if (!sk_X509_INFO_push(ret, xi))
goto err;
@@ -114,66 +127,25 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
goto err;
goto start;
}
-
- xi->enc_data = NULL;
- xi->enc_len = 0;
-
- xi->x_pkey = X509_PKEY_new();
- if (xi->x_pkey == NULL)
- goto err;
- ptype = EVP_PKEY_RSA;
- pp = &xi->x_pkey->dec_pkey;
- if ((int)strlen(header) > 10) /* assume encrypted */
- raw = 1;
- } else
-#endif
-#ifndef OPENSSL_NO_DSA
- if (strcmp(name, PEM_STRING_DSA) == 0) {
- d2i = (D2I_OF(void)) d2i_DSAPrivateKey;
- if (xi->x_pkey != NULL) {
- if (!sk_X509_INFO_push(ret, xi))
- goto err;
- if ((xi = X509_INFO_new()) == NULL)
- goto err;
- goto start;
+ if (str == name || strcmp(name, PEM_STRING_PKCS8) == 0) {
+ ptype = EVP_PKEY_NONE;
+ } else {
+ /* chop " PRIVATE KEY" */
+ *--str = '\0';
+ ptype = evp_pkey_name2type(name);
}
-
xi->enc_data = NULL;
xi->enc_len = 0;
+ d2i = (D2I_OF(void)) d2i_AutoPrivateKey;
xi->x_pkey = X509_PKEY_new();
if (xi->x_pkey == NULL)
goto err;
- ptype = EVP_PKEY_DSA;
pp = &xi->x_pkey->dec_pkey;
- if ((int)strlen(header) > 10) /* assume encrypted */
+ if ((int)strlen(header) > 10 /* assume encrypted */
+ || strcmp(name, PEM_STRING_PKCS8) == 0)
raw = 1;
- } else
-#endif
-#ifndef OPENSSL_NO_EC
- if (strcmp(name, PEM_STRING_ECPRIVATEKEY) == 0) {
- d2i = (D2I_OF(void)) d2i_ECPrivateKey;
- if (xi->x_pkey != NULL) {
- if (!sk_X509_INFO_push(ret, xi))
- goto err;
- if ((xi = X509_INFO_new()) == NULL)
- goto err;
- goto start;
- }
-
- xi->enc_data = NULL;
- xi->enc_len = 0;
-
- xi->x_pkey = X509_PKEY_new();
- if (xi->x_pkey == NULL)
- goto err;
- ptype = EVP_PKEY_EC;
- pp = &xi->x_pkey->dec_pkey;
- if ((int)strlen(header) > 10) /* assume encrypted */
- raw = 1;
- } else
-#endif
- {
+ } else { /* unknown */
d2i = NULL;
pp = NULL;
}
@@ -188,23 +160,22 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
goto err;
p = data;
if (ptype) {
- if (!d2i_PrivateKey(ptype, pp, &p, len)) {
- PEMerr(PEM_F_PEM_X509_INFO_READ_BIO, ERR_R_ASN1_LIB);
+ if (d2i_PrivateKey_ex(ptype, pp, &p, len,
+ libctx, propq) == NULL) {
+ ERR_raise(ERR_LIB_PEM, ERR_R_ASN1_LIB);
goto err;
}
} else if (d2i(pp, &p, len) == NULL) {
- PEMerr(PEM_F_PEM_X509_INFO_READ_BIO, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_PEM, ERR_R_ASN1_LIB);
goto err;
}
- } else { /* encrypted RSA data */
+ } else { /* encrypted key data */
if (!PEM_get_EVP_CIPHER_INFO(header, &xi->enc_cipher))
goto err;
xi->enc_data = (char *)data;
xi->enc_len = (int)len;
data = NULL;
}
- } else {
- /* unknown */
}
OPENSSL_free(name);
name = NULL;
@@ -243,27 +214,33 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
return ret;
}
+STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
+ pem_password_cb *cb, void *u)
+{
+ return PEM_X509_INFO_read_bio_ex(bp, sk, cb, u, NULL, NULL);
+}
+
/* A TJH addition */
-int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
- unsigned char *kstr, int klen,
+int PEM_X509_INFO_write_bio(BIO *bp, const X509_INFO *xi, EVP_CIPHER *enc,
+ const unsigned char *kstr, int klen,
pem_password_cb *cb, void *u)
{
int i, ret = 0;
unsigned char *data = NULL;
const char *objstr = NULL;
char buf[PEM_BUFSIZE];
- unsigned char *iv = NULL;
+ const unsigned char *iv = NULL;
if (enc != NULL) {
- objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
+ objstr = EVP_CIPHER_get0_name(enc);
if (objstr == NULL
- /*
- * Check "Proc-Type: 4,Encrypted\nDEK-Info: objstr,hex-iv\n"
- * fits into buf
- */
- || (strlen(objstr) + 23 + 2 * EVP_CIPHER_iv_length(enc) + 13)
- > sizeof(buf)) {
- PEMerr(PEM_F_PEM_X509_INFO_WRITE_BIO, PEM_R_UNSUPPORTED_CIPHER);
+ /*
+ * Check "Proc-Type: 4,Encrypted\nDEK-Info: objstr,hex-iv\n"
+ * fits into buf
+ */
+ || strlen(objstr) + 23 + 2 * EVP_CIPHER_get_iv_length(enc) + 13
+ > sizeof(buf)) {
+ ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_CIPHER);
goto err;
}
}
@@ -276,7 +253,7 @@ int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
if (xi->x_pkey != NULL) {
if ((xi->enc_data != NULL) && (xi->enc_len > 0)) {
if (enc == NULL) {
- PEMerr(PEM_F_PEM_X509_INFO_WRITE_BIO, PEM_R_CIPHER_IS_NULL);
+ ERR_raise(ERR_LIB_PEM, PEM_R_CIPHER_IS_NULL);
goto err;
}
@@ -290,18 +267,17 @@ int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
* than what the user has passed us ... as we have to match
* exactly for some strange reason
*/
- objstr = OBJ_nid2sn(EVP_CIPHER_nid(xi->enc_cipher.cipher));
+ objstr = EVP_CIPHER_get0_name(xi->enc_cipher.cipher);
if (objstr == NULL) {
- PEMerr(PEM_F_PEM_X509_INFO_WRITE_BIO,
- PEM_R_UNSUPPORTED_CIPHER);
+ ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_CIPHER);
goto err;
}
/* Create the right magic header stuff */
buf[0] = '\0';
PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
- PEM_dek_info(buf, objstr, EVP_CIPHER_iv_length(enc),
- (char *)iv);
+ PEM_dek_info(buf, objstr, EVP_CIPHER_get_iv_length(enc),
+ (const char *)iv);
/* use the normal code to write things out */
i = PEM_write_bio(bp, PEM_STRING_RSA, buf, data, i);
@@ -309,13 +285,11 @@ int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
goto err;
} else {
/* Add DSA/DH */
-#ifndef OPENSSL_NO_RSA
/* normal optionally encrypted stuff */
if (PEM_write_bio_RSAPrivateKey(bp,
EVP_PKEY_get0_RSA(xi->x_pkey->dec_pkey),
enc, kstr, klen, cb, u) <= 0)
goto err;
-#endif
}
}
diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c
index 14f9ca4aa4d6..6cd998f21669 100644
--- a/crypto/pem/pem_lib.c
+++ b/crypto/pem/pem_lib.c
@@ -1,12 +1,15 @@
/*
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <stdio.h>
#include "crypto/ctype.h"
#include <string.h>
@@ -26,7 +29,7 @@
static int load_iv(char **fromp, unsigned char *to, int num);
static int check_pem(const char *nm, const char *name);
-int pem_check_suffix(const char *pem_str, const char *suffix);
+int ossl_pem_check_suffix(const char *pem_str, const char *suffix);
int PEM_def_callback(char *buf, int num, int rwflag, void *userdata)
{
@@ -56,7 +59,7 @@ int PEM_def_callback(char *buf, int num, int rwflag, void *userdata)
i = EVP_read_pw_string_min(buf, min_len, num, prompt, rwflag);
if (i != 0) {
- PEMerr(PEM_F_PEM_DEF_CALLBACK, PEM_R_PROBLEMS_GETTING_PASSWORD);
+ ERR_raise(ERR_LIB_PEM, PEM_R_PROBLEMS_GETTING_PASSWORD);
memset(buf, 0, (unsigned int)num);
return -1;
}
@@ -80,7 +83,7 @@ void PEM_proc_type(char *buf, int type)
BIO_snprintf(p, PEM_BUFSIZE - (size_t)(p - buf), "Proc-Type: 4,%s\n", str);
}
-void PEM_dek_info(char *buf, const char *type, int len, char *str)
+void PEM_dek_info(char *buf, const char *type, int len, const char *str)
{
long i;
char *p = buf + strlen(buf);
@@ -110,7 +113,7 @@ void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x,
void *ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- PEMerr(PEM_F_PEM_ASN1_READ, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
@@ -135,7 +138,7 @@ static int check_pem(const char *nm, const char *name)
return 1;
if (strcmp(nm, PEM_STRING_PKCS8INF) == 0)
return 1;
- slen = pem_check_suffix(nm, "PRIVATE KEY");
+ slen = ossl_pem_check_suffix(nm, "PRIVATE KEY");
if (slen > 0) {
/*
* NB: ENGINE implementations won't contain a deprecated old
@@ -151,7 +154,7 @@ static int check_pem(const char *nm, const char *name)
if (strcmp(name, PEM_STRING_PARAMETERS) == 0) {
int slen;
const EVP_PKEY_ASN1_METHOD *ameth;
- slen = pem_check_suffix(nm, "PARAMETERS");
+ slen = ossl_pem_check_suffix(nm, "PARAMETERS");
if (slen > 0) {
ENGINE *e;
ameth = EVP_PKEY_asn1_find_str(&e, nm, slen);
@@ -288,14 +291,15 @@ int PEM_bytes_read_bio_secmem(unsigned char **pdata, long *plen, char **pnm,
#ifndef OPENSSL_NO_STDIO
int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp,
- void *x, const EVP_CIPHER *enc, unsigned char *kstr,
- int klen, pem_password_cb *callback, void *u)
+ const void *x, const EVP_CIPHER *enc,
+ const unsigned char *kstr, int klen,
+ pem_password_cb *callback, void *u)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- PEMerr(PEM_F_PEM_ASN1_WRITE, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
@@ -306,8 +310,9 @@ int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp,
#endif
int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
- void *x, const EVP_CIPHER *enc, unsigned char *kstr,
- int klen, pem_password_cb *callback, void *u)
+ const void *x, const EVP_CIPHER *enc,
+ const unsigned char *kstr, int klen,
+ pem_password_cb *callback, void *u)
{
EVP_CIPHER_CTX *ctx = NULL;
int dsize = 0, i = 0, j = 0, ret = 0;
@@ -318,22 +323,22 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
unsigned char iv[EVP_MAX_IV_LENGTH];
if (enc != NULL) {
- objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
- if (objstr == NULL || EVP_CIPHER_iv_length(enc) == 0
- || EVP_CIPHER_iv_length(enc) > (int)sizeof(iv)
+ objstr = EVP_CIPHER_get0_name(enc);
+ if (objstr == NULL || EVP_CIPHER_get_iv_length(enc) == 0
+ || EVP_CIPHER_get_iv_length(enc) > (int)sizeof(iv)
/*
* Check "Proc-Type: 4,Encrypted\nDEK-Info: objstr,hex-iv\n"
* fits into buf
*/
- || (strlen(objstr) + 23 + 2 * EVP_CIPHER_iv_length(enc) + 13)
+ || strlen(objstr) + 23 + 2 * EVP_CIPHER_get_iv_length(enc) + 13
> sizeof(buf)) {
- PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, PEM_R_UNSUPPORTED_CIPHER);
+ ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_CIPHER);
goto err;
}
}
if ((dsize = i2d(x, NULL)) <= 0) {
- PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_PEM, ERR_R_ASN1_LIB);
dsize = 0;
goto err;
}
@@ -341,7 +346,7 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
/* actually it needs the cipher block size extra... */
data = OPENSSL_malloc((unsigned int)dsize + 20);
if (data == NULL) {
- PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
goto err;
}
p = data;
@@ -354,7 +359,7 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
else
klen = (*callback) (buf, PEM_BUFSIZE, 1, u);
if (klen <= 0) {
- PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, PEM_R_READ_KEY);
+ ERR_raise(ERR_LIB_PEM, PEM_R_READ_KEY);
goto err;
}
#ifdef CHARSET_EBCDIC
@@ -363,7 +368,8 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
#endif
kstr = (unsigned char *)buf;
}
- if (RAND_bytes(iv, EVP_CIPHER_iv_length(enc)) <= 0) /* Generate a salt */
+ /* Generate a salt */
+ if (RAND_bytes(iv, EVP_CIPHER_get_iv_length(enc)) <= 0)
goto err;
/*
* The 'iv' is used as the iv and as a salt. It is NOT taken from
@@ -377,7 +383,7 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
buf[0] = '\0';
PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
- PEM_dek_info(buf, objstr, EVP_CIPHER_iv_length(enc), (char *)iv);
+ PEM_dek_info(buf, objstr, EVP_CIPHER_get_iv_length(enc), (char *)iv);
/* k=strlen(buf); */
ret = 1;
@@ -419,7 +425,7 @@ int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen,
#if LONG_MAX > INT_MAX
/* Check that we did not truncate the length */
if (len > INT_MAX) {
- PEMerr(PEM_F_PEM_DO_HEADER, PEM_R_HEADER_TOO_LONG);
+ ERR_raise(ERR_LIB_PEM, PEM_R_HEADER_TOO_LONG);
return 0;
}
#endif
@@ -431,7 +437,7 @@ int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen,
else
keylen = callback(buf, PEM_BUFSIZE, 0, u);
if (keylen < 0) {
- PEMerr(PEM_F_PEM_DO_HEADER, PEM_R_BAD_PASSWORD_READ);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ);
return 0;
}
#ifdef CHARSET_EBCDIC
@@ -458,7 +464,7 @@ int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen,
if (ok)
*plen += ilen;
else
- PEMerr(PEM_F_PEM_DO_HEADER, PEM_R_BAD_DECRYPT);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_DECRYPT);
EVP_CIPHER_CTX_free(ctx);
OPENSSL_cleanse((char *)buf, sizeof(buf));
@@ -493,7 +499,7 @@ int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher)
return 1;
if (strncmp(header, ProcType, sizeof(ProcType)-1) != 0) {
- PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_NOT_PROC_TYPE);
+ ERR_raise(ERR_LIB_PEM, PEM_R_NOT_PROC_TYPE);
return 0;
}
header += sizeof(ProcType)-1;
@@ -506,13 +512,13 @@ int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher)
/* We expect "ENCRYPTED" followed by optional white-space + line break */
if (strncmp(header, ENCRYPTED, sizeof(ENCRYPTED)-1) != 0 ||
strspn(header+sizeof(ENCRYPTED)-1, " \t\r\n") == 0) {
- PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_NOT_ENCRYPTED);
+ ERR_raise(ERR_LIB_PEM, PEM_R_NOT_ENCRYPTED);
return 0;
}
header += sizeof(ENCRYPTED)-1;
header += strspn(header, " \t\r");
if (*header++ != '\n') {
- PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_SHORT_HEADER);
+ ERR_raise(ERR_LIB_PEM, PEM_R_SHORT_HEADER);
return 0;
}
@@ -521,7 +527,7 @@ int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher)
* We expect "DEK-Info: algo[,hex-parameters]"
*/
if (strncmp(header, DEKInfo, sizeof(DEKInfo)-1) != 0) {
- PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_NOT_DEK_INFO);
+ ERR_raise(ERR_LIB_PEM, PEM_R_NOT_DEK_INFO);
return 0;
}
header += sizeof(DEKInfo)-1;
@@ -540,19 +546,19 @@ int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher)
header += strspn(header, " \t");
if (enc == NULL) {
- PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_UNSUPPORTED_ENCRYPTION);
+ ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_ENCRYPTION);
return 0;
}
- ivlen = EVP_CIPHER_iv_length(enc);
+ ivlen = EVP_CIPHER_get_iv_length(enc);
if (ivlen > 0 && *header++ != ',') {
- PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_MISSING_DEK_IV);
+ ERR_raise(ERR_LIB_PEM, PEM_R_MISSING_DEK_IV);
return 0;
} else if (ivlen == 0 && *header == ',') {
- PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_UNEXPECTED_DEK_IV);
+ ERR_raise(ERR_LIB_PEM, PEM_R_UNEXPECTED_DEK_IV);
return 0;
}
- if (!load_iv(&header, cipher->iv, EVP_CIPHER_iv_length(enc)))
+ if (!load_iv(&header, cipher->iv, EVP_CIPHER_get_iv_length(enc)))
return 0;
return 1;
@@ -570,7 +576,7 @@ static int load_iv(char **fromp, unsigned char *to, int num)
for (i = 0; i < num; i++) {
v = OPENSSL_hexchar2int(*from);
if (v < 0) {
- PEMerr(PEM_F_LOAD_IV, PEM_R_BAD_IV_CHARS);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_IV_CHARS);
return 0;
}
from++;
@@ -589,7 +595,7 @@ int PEM_write(FILE *fp, const char *name, const char *header,
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- PEMerr(PEM_F_PEM_WRITE, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
@@ -655,7 +661,7 @@ int PEM_write_bio(BIO *bp, const char *name, const char *header,
err:
if (retval == 0)
- PEMerr(PEM_F_PEM_WRITE_BIO, reason);
+ ERR_raise(ERR_LIB_PEM, reason);
EVP_ENCODE_CTX_free(ctx);
OPENSSL_clear_free(buf, PEM_BUFSIZE * 8);
return retval;
@@ -669,7 +675,7 @@ int PEM_read(FILE *fp, char **name, char **header, unsigned char **data,
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- PEMerr(PEM_F_PEM_READ, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
@@ -680,9 +686,20 @@ int PEM_read(FILE *fp, char **name, char **header, unsigned char **data,
#endif
/* Some helpers for PEM_read_bio_ex(). */
-static int sanitize_line(char *linebuf, int len, unsigned int flags)
+static int sanitize_line(char *linebuf, int len, unsigned int flags, int first_call)
{
int i;
+ if (first_call) {
+ /* Other BOMs imply unsupported multibyte encoding,
+ * so don't strip them and let the error raise */
+ const unsigned char utf8_bom[3] = {0xEF, 0xBB, 0xBF};
+
+ if (len > 3 && memcmp(linebuf, utf8_bom, 3) == 0) {
+ memmove(linebuf, linebuf + 3, len - 3);
+ linebuf[len - 3] = 0;
+ len -= 3;
+ }
+ }
if (flags & PEM_FLAG_EAY_COMPATIBLE) {
/* Strip trailing whitespace */
@@ -727,6 +744,7 @@ static int get_name(BIO *bp, char **name, unsigned int flags)
char *linebuf;
int ret = 0;
int len;
+ int first_call = 1;
/*
* Need to hold trailing NUL (accounted for by BIO_gets() and the newline
@@ -734,7 +752,7 @@ static int get_name(BIO *bp, char **name, unsigned int flags)
*/
linebuf = pem_malloc(LINESIZE + 1, flags);
if (linebuf == NULL) {
- PEMerr(PEM_F_GET_NAME, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -742,12 +760,13 @@ static int get_name(BIO *bp, char **name, unsigned int flags)
len = BIO_gets(bp, linebuf, LINESIZE);
if (len <= 0) {
- PEMerr(PEM_F_GET_NAME, PEM_R_NO_START_LINE);
+ ERR_raise(ERR_LIB_PEM, PEM_R_NO_START_LINE);
goto err;
}
/* Strip trailing garbage and standardize ending. */
- len = sanitize_line(linebuf, len, flags & ~PEM_FLAG_ONLY_B64);
+ len = sanitize_line(linebuf, len, flags & ~PEM_FLAG_ONLY_B64, first_call);
+ first_call = 0;
/* Allow leading empty or non-matching lines. */
} while (strncmp(linebuf, beginstr, BEGINLEN) != 0
@@ -757,7 +776,7 @@ static int get_name(BIO *bp, char **name, unsigned int flags)
len = len - BEGINLEN - TAILLEN + 1;
*name = pem_malloc(len, flags);
if (*name == NULL) {
- PEMerr(PEM_F_GET_NAME, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
goto err;
}
memcpy(*name, linebuf + BEGINLEN, len);
@@ -801,15 +820,15 @@ static int get_header_and_data(BIO *bp, BIO **header, BIO **data, char *name,
* that will be added by sanitize_line() (the extra '1'). */
linebuf = pem_malloc(LINESIZE + 1, flags);
if (linebuf == NULL) {
- PEMerr(PEM_F_GET_HEADER_AND_DATA, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
return 0;
}
- for (;;) {
+ while(1) {
flags_mask = ~0u;
len = BIO_gets(bp, linebuf, LINESIZE);
if (len <= 0) {
- PEMerr(PEM_F_GET_HEADER_AND_DATA, PEM_R_BAD_END_LINE);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_END_LINE);
goto err;
}
@@ -827,7 +846,7 @@ static int get_header_and_data(BIO *bp, BIO **header, BIO **data, char *name,
}
if (!strncmp(linebuf, endstr, ENDLEN) || got_header == IN_HEADER)
flags_mask &= ~PEM_FLAG_ONLY_B64;
- len = sanitize_line(linebuf, len, flags & flags_mask);
+ len = sanitize_line(linebuf, len, flags & flags_mask, 0);
/* Check for end of header. */
if (linebuf[0] == '\n') {
@@ -838,7 +857,7 @@ static int get_header_and_data(BIO *bp, BIO **header, BIO **data, char *name,
if (!prev_partial_line_read) {
if (got_header == POST_HEADER) {
/* Another blank line is an error. */
- PEMerr(PEM_F_GET_HEADER_AND_DATA, PEM_R_BAD_END_LINE);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_END_LINE);
goto err;
}
got_header = POST_HEADER;
@@ -853,7 +872,7 @@ static int get_header_and_data(BIO *bp, BIO **header, BIO **data, char *name,
namelen = strlen(name);
if (strncmp(p, name, namelen) != 0 ||
strncmp(p + namelen, tailstr, TAILLEN) != 0) {
- PEMerr(PEM_F_GET_HEADER_AND_DATA, PEM_R_BAD_END_LINE);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_END_LINE);
goto err;
}
if (got_header == MAYBE_HEADER) {
@@ -863,7 +882,7 @@ static int get_header_and_data(BIO *bp, BIO **header, BIO **data, char *name,
break;
} else if (end) {
/* Malformed input; short line not at end of data. */
- PEMerr(PEM_F_GET_HEADER_AND_DATA, PEM_R_BAD_END_LINE);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_END_LINE);
goto err;
}
/*
@@ -911,7 +930,7 @@ int PEM_read_bio_ex(BIO *bp, char **name_out, char **header,
*data = NULL;
if ((flags & PEM_FLAG_EAY_COMPATIBLE) && (flags & PEM_FLAG_ONLY_B64)) {
/* These two are mutually incompatible; bail out. */
- PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_PASSED_INVALID_ARGUMENT);
+ ERR_raise(ERR_LIB_PEM, ERR_R_PASSED_INVALID_ARGUMENT);
goto end;
}
bmeth = (flags & PEM_FLAG_SECURE) ? BIO_s_secmem() : BIO_s_mem();
@@ -919,7 +938,7 @@ int PEM_read_bio_ex(BIO *bp, char **name_out, char **header,
headerB = BIO_new(bmeth);
dataB = BIO_new(bmeth);
if (headerB == NULL || dataB == NULL) {
- PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
goto end;
}
@@ -937,7 +956,7 @@ int PEM_read_bio_ex(BIO *bp, char **name_out, char **header,
ctx = EVP_ENCODE_CTX_new();
if (ctx == NULL) {
- PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
goto end;
}
@@ -946,7 +965,7 @@ int PEM_read_bio_ex(BIO *bp, char **name_out, char **header,
(unsigned char*)buf_mem->data, len) < 0
|| EVP_DecodeFinal(ctx, (unsigned char*)&(buf_mem->data[len]),
&taillen) < 0) {
- PEMerr(PEM_F_PEM_READ_BIO_EX, PEM_R_BAD_BASE64_DECODE);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_BASE64_DECODE);
goto end;
}
len += taillen;
@@ -955,21 +974,24 @@ int PEM_read_bio_ex(BIO *bp, char **name_out, char **header,
headerlen = BIO_get_mem_data(headerB, NULL);
*header = pem_malloc(headerlen + 1, flags);
*data = pem_malloc(len, flags);
- if (*header == NULL || *data == NULL) {
- pem_free(*header, flags, 0);
- *header = NULL;
- pem_free(*data, flags, 0);
- *data = NULL;
- goto end;
- }
- BIO_read(headerB, *header, headerlen);
+ if (*header == NULL || *data == NULL)
+ goto out_free;
+ if (headerlen != 0 && BIO_read(headerB, *header, headerlen) != headerlen)
+ goto out_free;
(*header)[headerlen] = '\0';
- BIO_read(dataB, *data, len);
+ if (BIO_read(dataB, *data, len) != len)
+ goto out_free;
*len_out = len;
*name_out = name;
name = NULL;
ret = 1;
+ goto end;
+out_free:
+ pem_free(*header, flags, 0);
+ *header = NULL;
+ pem_free(*data, flags, 0);
+ *data = NULL;
end:
EVP_ENCODE_CTX_free(ctx);
pem_free(name, flags, 0);
@@ -990,7 +1012,7 @@ int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
* string "RSA".
*/
-int pem_check_suffix(const char *pem_str, const char *suffix)
+int ossl_pem_check_suffix(const char *pem_str, const char *suffix)
{
int pem_len = strlen(pem_str);
int suffix_len = strlen(suffix);
diff --git a/crypto/pem/pem_local.h b/crypto/pem/pem_local.h
new file mode 100644
index 000000000000..5cc1c76fdbf7
--- /dev/null
+++ b/crypto/pem/pem_local.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_dispatch.h>
+#include <openssl/pem.h>
+#include <openssl/encoder.h>
+
+/*
+ * Selectors, named according to the ASN.1 names used throughout libcrypto.
+ *
+ * Note that these are not absolutely mandatory, they are rather a wishlist
+ * of sorts. The provider implementations are free to make choices that
+ * make sense for them, based on these selectors.
+ * For example, the EC backend is likely to really just output the private
+ * key to a PKCS#8 structure, even thought PEM_SELECTION_PrivateKey specifies
+ * the public key as well. This is fine, as long as the corresponding
+ * decoding operation can return an object that contains what libcrypto
+ * expects.
+ */
+# define PEM_SELECTION_PUBKEY EVP_PKEY_PUBLIC_KEY
+# define PEM_SELECTION_PrivateKey EVP_PKEY_KEYPAIR
+# define PEM_SELECTION_Parameters EVP_PKEY_KEY_PARAMETERS
+
+/*
+ * Properties, named according to the ASN.1 names used throughout libcrypto.
+ */
+# define PEM_STRUCTURE_PUBKEY "SubjectPublicKeyInfo"
+# define PEM_STRUCTURE_PrivateKey "PrivateKeyInfo"
+# define PEM_STRUCTURE_Parameters "type-specific"
+
+# define PEM_STRUCTURE_RSAPrivateKey "type-specific"
+# define PEM_STRUCTURE_RSAPublicKey "type-specific"
+
+/* Alternative IMPLEMENT macros for provided encoders */
+
+# define IMPLEMENT_PEM_provided_write_body_vars(type, asn1, pq) \
+ int ret = 0; \
+ OSSL_ENCODER_CTX *ctx = \
+ OSSL_ENCODER_CTX_new_for_##type(x, PEM_SELECTION_##asn1, \
+ "PEM", PEM_STRUCTURE_##asn1, \
+ (pq)); \
+ \
+ if (OSSL_ENCODER_CTX_get_num_encoders(ctx) == 0) { \
+ OSSL_ENCODER_CTX_free(ctx); \
+ goto legacy; \
+ }
+# define IMPLEMENT_PEM_provided_write_body_pass() \
+ ret = 1; \
+ if (kstr == NULL && cb == NULL) { \
+ if (u != NULL) { \
+ kstr = u; \
+ klen = strlen(u); \
+ } else { \
+ cb = PEM_def_callback; \
+ } \
+ } \
+ if (enc != NULL) { \
+ ret = 0; \
+ if (OSSL_ENCODER_CTX_set_cipher(ctx, EVP_CIPHER_get0_name(enc), \
+ NULL)) { \
+ ret = 1; \
+ if (kstr != NULL \
+ && !OSSL_ENCODER_CTX_set_passphrase(ctx, kstr, klen)) \
+ ret = 0; \
+ else if (cb != NULL \
+ && !OSSL_ENCODER_CTX_set_pem_password_cb(ctx, \
+ cb, u)) \
+ ret = 0; \
+ } \
+ } \
+ if (!ret) { \
+ OSSL_ENCODER_CTX_free(ctx); \
+ return 0; \
+ }
+# define IMPLEMENT_PEM_provided_write_body_main(type, outtype) \
+ ret = OSSL_ENCODER_to_##outtype(ctx, out); \
+ OSSL_ENCODER_CTX_free(ctx); \
+ return ret
+# define IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \
+ writename) \
+ legacy: \
+ return PEM_ASN1_##writename((i2d_of_void *)i2d_##asn1, str, out, \
+ x, NULL, NULL, 0, NULL, NULL)
+# define IMPLEMENT_PEM_provided_write_body_fallback_cb(str, asn1, \
+ writename) \
+ legacy: \
+ return PEM_ASN1_##writename##((i2d_of_void *)i2d_##asn1, str, out, \
+ x, enc, kstr, klen, cb, u)
+
+# define IMPLEMENT_PEM_provided_write_to(name, TYPE, type, str, asn1, \
+ OUTTYPE, outtype, writename) \
+ PEM_write_fnsig(name, TYPE, OUTTYPE, writename) \
+ { \
+ IMPLEMENT_PEM_provided_write_body_vars(type, asn1, NULL); \
+ IMPLEMENT_PEM_provided_write_body_main(type, outtype); \
+ IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \
+ writename); \
+ } \
+ PEM_write_ex_fnsig(name, TYPE, OUTTYPE, writename) \
+ { \
+ IMPLEMENT_PEM_provided_write_body_vars(type, asn1, propq); \
+ IMPLEMENT_PEM_provided_write_body_main(type, outtype); \
+ IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \
+ writename); \
+ }
+
+
+# define IMPLEMENT_PEM_provided_write_cb_to(name, TYPE, type, str, asn1, \
+ OUTTYPE, outtype, writename) \
+ PEM_write_cb_fnsig(name, TYPE, OUTTYPE, writename) \
+ { \
+ IMPLEMENT_PEM_provided_write_body_vars(type, asn1, NULL); \
+ IMPLEMENT_PEM_provided_write_body_pass(); \
+ IMPLEMENT_PEM_provided_write_body_main(type, outtype); \
+ IMPLEMENT_PEM_provided_write_body_fallback_cb(str, asn1, \
+ writename); \
+ } \
+ PEM_write_ex_cb_fnsig(name, TYPE, OUTTYPE, writename) \
+ { \
+ IMPLEMENT_PEM_provided_write_body_vars(type, asn1, propq); \
+ IMPLEMENT_PEM_provided_write_body_pass(); \
+ IMPLEMENT_PEM_provided_write_body_main(type, outtype); \
+ IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \
+ writename); \
+ }
+
+# ifdef OPENSSL_NO_STDIO
+
+# define IMPLEMENT_PEM_provided_write_fp(name, TYPE, type, str, asn1)
+# define IMPLEMENT_PEM_provided_write_cb_fp(name, TYPE, type, str, asn1)
+
+# else
+
+# define IMPLEMENT_PEM_provided_write_fp(name, TYPE, type, str, asn1) \
+ IMPLEMENT_PEM_provided_write_to(name, TYPE, type, str, asn1, FILE, fp, write)
+# define IMPLEMENT_PEM_provided_write_cb_fp(name, TYPE, type, str, asn1) \
+ IMPLEMENT_PEM_provided_write_cb_to(name, TYPE, type, str, asn1, FILE, fp, write)
+
+# endif
+
+# define IMPLEMENT_PEM_provided_write_bio(name, TYPE, type, str, asn1) \
+ IMPLEMENT_PEM_provided_write_to(name, TYPE, type, str, asn1, BIO, bio, write_bio)
+# define IMPLEMENT_PEM_provided_write_cb_bio(name, TYPE, type, str, asn1) \
+ IMPLEMENT_PEM_provided_write_cb_to(name, TYPE, type, str, asn1, BIO, bio, write_bio)
+
+# define IMPLEMENT_PEM_provided_write(name, TYPE, type, str, asn1) \
+ IMPLEMENT_PEM_provided_write_bio(name, TYPE, type, str, asn1) \
+ IMPLEMENT_PEM_provided_write_fp(name, TYPE, type, str, asn1)
+
+# define IMPLEMENT_PEM_provided_write_cb(name, TYPE, type, str, asn1) \
+ IMPLEMENT_PEM_provided_write_cb_bio(name, TYPE, type, str, asn1) \
+ IMPLEMENT_PEM_provided_write_cb_fp(name, TYPE, type, str, asn1)
+
+# define IMPLEMENT_PEM_provided_rw(name, TYPE, type, str, asn1) \
+ IMPLEMENT_PEM_read(name, TYPE, str, asn1) \
+ IMPLEMENT_PEM_provided_write(name, TYPE, type, str, asn1)
+
+# define IMPLEMENT_PEM_provided_rw_cb(name, TYPE, type, str, asn1) \
+ IMPLEMENT_PEM_read(name, TYPE, str, asn1) \
+ IMPLEMENT_PEM_provided_write_cb(name, TYPE, type, str, asn1)
+
diff --git a/crypto/pem/pem_oth.c b/crypto/pem/pem_oth.c
index 566205331f8a..db62246174e3 100644
--- a/crypto/pem/pem_oth.c
+++ b/crypto/pem/pem_oth.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -30,7 +30,7 @@ void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x,
p = data;
ret = d2i(x, &p, len);
if (ret == NULL)
- PEMerr(PEM_F_PEM_ASN1_READ_BIO, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_PEM, ERR_R_ASN1_LIB);
OPENSSL_free(data);
return ret;
}
diff --git a/crypto/pem/pem_pk8.c b/crypto/pem/pem_pk8.c
index ab6c4c6bde30..1592e351edef 100644
--- a/crypto/pem/pem_pk8.c
+++ b/crypto/pem/pem_pk8.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,21 +9,27 @@
#include <stdio.h>
#include "internal/cryptlib.h"
+#include <openssl/core_dispatch.h>
#include <openssl/buffer.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/pkcs12.h>
#include <openssl/pem.h>
+#include <openssl/encoder.h>
-static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder,
+static int do_pk8pkey(BIO *bp, const EVP_PKEY *x, int isder,
int nid, const EVP_CIPHER *enc,
- char *kstr, int klen, pem_password_cb *cb, void *u);
+ const char *kstr, int klen,
+ pem_password_cb *cb, void *u,
+ const char *propq);
#ifndef OPENSSL_NO_STDIO
-static int do_pk8pkey_fp(FILE *bp, EVP_PKEY *x, int isder,
+static int do_pk8pkey_fp(FILE *bp, const EVP_PKEY *x, int isder,
int nid, const EVP_CIPHER *enc,
- char *kstr, int klen, pem_password_cb *cb, void *u);
+ const char *kstr, int klen,
+ pem_password_cb *cb, void *u,
+ const char *propq);
#endif
/*
* These functions write a private key in PKCS#8 format: it is a "drop in"
@@ -32,81 +38,132 @@ static int do_pk8pkey_fp(FILE *bp, EVP_PKEY *x, int isder,
* uses PKCS#5 v1.5 PBE algorithms whereas the others use PKCS#5 v2.0.
*/
-int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid,
- char *kstr, int klen,
+int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, const EVP_PKEY *x, int nid,
+ const char *kstr, int klen,
pem_password_cb *cb, void *u)
{
- return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u);
+ return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u, NULL);
}
-int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
- char *kstr, int klen,
+int PEM_write_bio_PKCS8PrivateKey(BIO *bp, const EVP_PKEY *x, const EVP_CIPHER *enc,
+ const char *kstr, int klen,
pem_password_cb *cb, void *u)
{
- return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u);
+ return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u, NULL);
}
-int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
- char *kstr, int klen,
+int i2d_PKCS8PrivateKey_bio(BIO *bp, const EVP_PKEY *x, const EVP_CIPHER *enc,
+ const char *kstr, int klen,
pem_password_cb *cb, void *u)
{
- return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u);
+ return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u, NULL);
}
-int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid,
- char *kstr, int klen,
+int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, const EVP_PKEY *x, int nid,
+ const char *kstr, int klen,
pem_password_cb *cb, void *u)
{
- return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u);
+ return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u, NULL);
}
-static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, int nid,
- const EVP_CIPHER *enc, char *kstr, int klen,
- pem_password_cb *cb, void *u)
+static int do_pk8pkey(BIO *bp, const EVP_PKEY *x, int isder, int nid,
+ const EVP_CIPHER *enc, const char *kstr, int klen,
+ pem_password_cb *cb, void *u, const char *propq)
{
- X509_SIG *p8;
- PKCS8_PRIV_KEY_INFO *p8inf;
- char buf[PEM_BUFSIZE];
- int ret;
+ int ret = 0;
+ const char *outtype = isder ? "DER" : "PEM";
+ OSSL_ENCODER_CTX *ctx =
+ OSSL_ENCODER_CTX_new_for_pkey(x, OSSL_KEYMGMT_SELECT_ALL,
+ outtype, "PrivateKeyInfo", propq);
- if ((p8inf = EVP_PKEY2PKCS8(x)) == NULL) {
- PEMerr(PEM_F_DO_PK8PKEY, PEM_R_ERROR_CONVERTING_PRIVATE_KEY);
+ if (ctx == NULL)
return 0;
+
+ /*
+ * If no keystring or callback is set, OpenSSL traditionally uses the
+ * user's cb argument as a password string, or if that's NULL, it falls
+ * back on PEM_def_callback().
+ */
+ if (kstr == NULL && cb == NULL) {
+ if (u != NULL) {
+ kstr = u;
+ klen = strlen(u);
+ } else {
+ cb = PEM_def_callback;
+ }
}
- if (enc || (nid != -1)) {
- if (!kstr) {
- if (!cb)
- klen = PEM_def_callback(buf, PEM_BUFSIZE, 1, u);
- else
- klen = cb(buf, PEM_BUFSIZE, 1, u);
- if (klen <= 0) {
- PEMerr(PEM_F_DO_PK8PKEY, PEM_R_READ_KEY);
- PKCS8_PRIV_KEY_INFO_free(p8inf);
- return 0;
- }
- kstr = buf;
+ /*
+ * NOTE: There is no attempt to do a EVP_CIPHER_fetch() using the nid,
+ * since the nid is a PBE algorithm which can't be fetched currently.
+ * (e.g. NID_pbe_WithSHA1And2_Key_TripleDES_CBC). Just use the legacy
+ * path if the NID is passed.
+ */
+ if (nid == -1 && OSSL_ENCODER_CTX_get_num_encoders(ctx) != 0) {
+ ret = 1;
+ if (enc != NULL) {
+ ret = 0;
+ if (OSSL_ENCODER_CTX_set_cipher(ctx, EVP_CIPHER_get0_name(enc),
+ NULL)) {
+ const unsigned char *ukstr = (const unsigned char *)kstr;
+
+ /*
+ * Try to pass the passphrase if one was given, or the
+ * passphrase callback if one was given. If none of them
+ * are given and that's wrong, we rely on the _to_bio()
+ * call to generate errors.
+ */
+ ret = 1;
+ if (kstr != NULL
+ && !OSSL_ENCODER_CTX_set_passphrase(ctx, ukstr, klen))
+ ret = 0;
+ else if (cb != NULL
+ && !OSSL_ENCODER_CTX_set_pem_password_cb(ctx, cb, u))
+ ret = 0;
+ }
}
- p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf);
- if (kstr == buf)
- OPENSSL_cleanse(buf, klen);
- PKCS8_PRIV_KEY_INFO_free(p8inf);
- if (p8 == NULL)
- return 0;
- if (isder)
- ret = i2d_PKCS8_bio(bp, p8);
- else
- ret = PEM_write_bio_PKCS8(bp, p8);
- X509_SIG_free(p8);
- return ret;
+ ret = ret && OSSL_ENCODER_to_bio(ctx, bp);
} else {
- if (isder)
- ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
- else
- ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf);
+ X509_SIG *p8;
+ PKCS8_PRIV_KEY_INFO *p8inf;
+ char buf[PEM_BUFSIZE];
+
+ ret = 0;
+ if ((p8inf = EVP_PKEY2PKCS8(x)) == NULL) {
+ ERR_raise(ERR_LIB_PEM, PEM_R_ERROR_CONVERTING_PRIVATE_KEY);
+ goto legacy_end;
+ }
+ if (enc || (nid != -1)) {
+ if (kstr == NULL) {
+ klen = cb(buf, PEM_BUFSIZE, 1, u);
+ if (klen < 0) {
+ ERR_raise(ERR_LIB_PEM, PEM_R_READ_KEY);
+ goto legacy_end;
+ }
+
+ kstr = buf;
+ }
+ p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf);
+ if (kstr == buf)
+ OPENSSL_cleanse(buf, klen);
+ if (p8 == NULL)
+ goto legacy_end;
+ if (isder)
+ ret = i2d_PKCS8_bio(bp, p8);
+ else
+ ret = PEM_write_bio_PKCS8(bp, p8);
+ X509_SIG_free(p8);
+ } else {
+ if (isder)
+ ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
+ else
+ ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf);
+ }
+ legacy_end:
PKCS8_PRIV_KEY_INFO_free(p8inf);
- return ret;
}
+ OSSL_ENCODER_CTX_free(ctx);
+ return ret;
}
EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
@@ -117,28 +174,29 @@ EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
int klen;
EVP_PKEY *ret;
char psbuf[PEM_BUFSIZE];
+
p8 = d2i_PKCS8_bio(bp, NULL);
- if (!p8)
+ if (p8 == NULL)
return NULL;
- if (cb)
+ if (cb != NULL)
klen = cb(psbuf, PEM_BUFSIZE, 0, u);
else
klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
if (klen < 0) {
- PEMerr(PEM_F_D2I_PKCS8PRIVATEKEY_BIO, PEM_R_BAD_PASSWORD_READ);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ);
X509_SIG_free(p8);
return NULL;
}
p8inf = PKCS8_decrypt(p8, psbuf, klen);
X509_SIG_free(p8);
OPENSSL_cleanse(psbuf, klen);
- if (!p8inf)
+ if (p8inf == NULL)
return NULL;
ret = EVP_PKCS82PKEY(p8inf);
PKCS8_PRIV_KEY_INFO_free(p8inf);
if (!ret)
return NULL;
- if (x) {
+ if (x != NULL) {
EVP_PKEY_free(*x);
*x = ret;
}
@@ -147,45 +205,46 @@ EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
#ifndef OPENSSL_NO_STDIO
-int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
- char *kstr, int klen, pem_password_cb *cb, void *u)
+int i2d_PKCS8PrivateKey_fp(FILE *fp, const EVP_PKEY *x, const EVP_CIPHER *enc,
+ const char *kstr, int klen,
+ pem_password_cb *cb, void *u)
{
- return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u);
+ return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u, NULL);
}
-int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid,
- char *kstr, int klen,
+int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, const EVP_PKEY *x, int nid,
+ const char *kstr, int klen,
pem_password_cb *cb, void *u)
{
- return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u);
+ return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u, NULL);
}
-int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid,
- char *kstr, int klen,
+int PEM_write_PKCS8PrivateKey_nid(FILE *fp, const EVP_PKEY *x, int nid,
+ const char *kstr, int klen,
pem_password_cb *cb, void *u)
{
- return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u);
+ return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u, NULL);
}
-int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
- char *kstr, int klen, pem_password_cb *cb,
- void *u)
+int PEM_write_PKCS8PrivateKey(FILE *fp, const EVP_PKEY *x, const EVP_CIPHER *enc,
+ const char *kstr, int klen,
+ pem_password_cb *cb, void *u)
{
- return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u);
+ return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u, NULL);
}
-static int do_pk8pkey_fp(FILE *fp, EVP_PKEY *x, int isder, int nid,
- const EVP_CIPHER *enc, char *kstr, int klen,
- pem_password_cb *cb, void *u)
+static int do_pk8pkey_fp(FILE *fp, const EVP_PKEY *x, int isder, int nid,
+ const EVP_CIPHER *enc, const char *kstr, int klen,
+ pem_password_cb *cb, void *u, const char *propq)
{
BIO *bp;
int ret;
if ((bp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
- PEMerr(PEM_F_DO_PK8PKEY_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
return 0;
}
- ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u);
+ ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u, propq);
BIO_free(bp);
return ret;
}
@@ -197,7 +256,7 @@ EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
EVP_PKEY *ret;
if ((bp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
- PEMerr(PEM_F_D2I_PKCS8PRIVATEKEY_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
return NULL;
}
ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u);
@@ -211,4 +270,4 @@ IMPLEMENT_PEM_rw(PKCS8, X509_SIG, PEM_STRING_PKCS8, X509_SIG)
IMPLEMENT_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF,
- PKCS8_PRIV_KEY_INFO)
+ PKCS8_PRIV_KEY_INFO)
diff --git a/crypto/pem/pem_pkey.c b/crypto/pem/pem_pkey.c
index 4a9492724487..3e76852c67a4 100644
--- a/crypto/pem/pem_pkey.c
+++ b/crypto/pem/pem_pkey.c
@@ -1,14 +1,16 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <stdio.h>
-#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
@@ -17,13 +19,88 @@
#include <openssl/pem.h>
#include <openssl/engine.h>
#include <openssl/dh.h>
+#include <openssl/decoder.h>
+#include <openssl/ui.h>
+#include "internal/cryptlib.h"
+#include "internal/passphrase.h"
#include "crypto/asn1.h"
+#include "crypto/x509.h"
#include "crypto/evp.h"
+#include "pem_local.h"
-int pem_check_suffix(const char *pem_str, const char *suffix);
+int ossl_pem_check_suffix(const char *pem_str, const char *suffix);
-EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
- void *u)
+static EVP_PKEY *pem_read_bio_key_decoder(BIO *bp, EVP_PKEY **x,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx,
+ const char *propq,
+ int selection)
+{
+ EVP_PKEY *pkey = NULL;
+ OSSL_DECODER_CTX *dctx = NULL;
+ int pos, newpos;
+
+ if ((pos = BIO_tell(bp)) < 0)
+ /* We can depend on BIO_tell() thanks to the BIO_f_readbuffer() */
+ return NULL;
+
+ dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "PEM", NULL, NULL,
+ selection, libctx, propq);
+
+ if (dctx == NULL)
+ return NULL;
+
+ if (cb == NULL)
+ cb = PEM_def_callback;
+
+ if (!OSSL_DECODER_CTX_set_pem_password_cb(dctx, cb, u))
+ goto err;
+
+ ERR_set_mark();
+ while (!OSSL_DECODER_from_bio(dctx, bp) || pkey == NULL)
+ if (BIO_eof(bp) != 0 || (newpos = BIO_tell(bp)) < 0 || newpos <= pos) {
+ ERR_clear_last_mark();
+ goto err;
+ } else {
+ if (ERR_GET_REASON(ERR_peek_error()) == ERR_R_UNSUPPORTED) {
+ /* unsupported PEM data, try again */
+ ERR_pop_to_mark();
+ ERR_set_mark();
+ } else {
+ /* other error, bail out */
+ ERR_clear_last_mark();
+ goto err;
+ }
+ pos = newpos;
+ }
+ ERR_pop_to_mark();
+
+ /* if we were asked for private key, the public key is optional */
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ selection = selection & ~OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+
+ if (!evp_keymgmt_util_has(pkey, selection)) {
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
+ goto err;
+ }
+
+ if (x != NULL) {
+ EVP_PKEY_free(*x);
+ *x = pkey;
+ }
+
+ err:
+ OSSL_DECODER_CTX_free(dctx);
+ return pkey;
+}
+
+static EVP_PKEY *pem_read_bio_key_legacy(BIO *bp, EVP_PKEY **x,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx,
+ const char *propq,
+ int selection)
{
char *nm = NULL;
const unsigned char *p = NULL;
@@ -32,19 +109,37 @@ EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
int slen;
EVP_PKEY *ret = NULL;
- if (!PEM_bytes_read_bio_secmem(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp,
- cb, u))
- return NULL;
+ ERR_set_mark(); /* not interested in PEM read errors */
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ if (!PEM_bytes_read_bio_secmem(&data, &len, &nm,
+ PEM_STRING_EVP_PKEY,
+ bp, cb, u)) {
+ ERR_pop_to_mark();
+ return NULL;
+ }
+ } else {
+ const char *pem_string = PEM_STRING_PARAMETERS;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ pem_string = PEM_STRING_PUBLIC;
+ if (!PEM_bytes_read_bio(&data, &len, &nm,
+ pem_string,
+ bp, cb, u)) {
+ ERR_pop_to_mark();
+ return NULL;
+ }
+ }
+ ERR_clear_last_mark();
p = data;
if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) {
PKCS8_PRIV_KEY_INFO *p8inf;
- p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
- if (!p8inf)
+
+ if ((p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len)) == NULL)
goto p8err;
- ret = EVP_PKCS82PKEY(p8inf);
- if (x) {
- EVP_PKEY_free((EVP_PKEY *)*x);
+ ret = evp_pkcs82pkey_legacy(p8inf, libctx, propq);
+ if (x != NULL) {
+ EVP_PKEY_free(*x);
*x = ret;
}
PKCS8_PRIV_KEY_INFO_free(p8inf);
@@ -53,87 +148,43 @@ EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
X509_SIG *p8;
int klen;
char psbuf[PEM_BUFSIZE];
- p8 = d2i_X509_SIG(NULL, &p, len);
- if (!p8)
+
+ if ((p8 = d2i_X509_SIG(NULL, &p, len)) == NULL)
goto p8err;
- if (cb)
+ if (cb != NULL)
klen = cb(psbuf, PEM_BUFSIZE, 0, u);
else
klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
if (klen < 0) {
- PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY, PEM_R_BAD_PASSWORD_READ);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ);
X509_SIG_free(p8);
goto err;
}
p8inf = PKCS8_decrypt(p8, psbuf, klen);
X509_SIG_free(p8);
OPENSSL_cleanse(psbuf, klen);
- if (!p8inf)
+ if (p8inf == NULL)
goto p8err;
- ret = EVP_PKCS82PKEY(p8inf);
- if (x) {
- EVP_PKEY_free((EVP_PKEY *)*x);
+ ret = evp_pkcs82pkey_legacy(p8inf, libctx, propq);
+ if (x != NULL) {
+ EVP_PKEY_free(*x);
*x = ret;
}
PKCS8_PRIV_KEY_INFO_free(p8inf);
- } else if ((slen = pem_check_suffix(nm, "PRIVATE KEY")) > 0) {
+ } else if ((slen = ossl_pem_check_suffix(nm, "PRIVATE KEY")) > 0) {
const EVP_PKEY_ASN1_METHOD *ameth;
ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen);
- if (!ameth || !ameth->old_priv_decode)
+ if (ameth == NULL || ameth->old_priv_decode == NULL)
goto p8err;
- ret = d2i_PrivateKey(ameth->pkey_id, x, &p, len);
- }
- p8err:
- if (ret == NULL)
- PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY, ERR_R_ASN1_LIB);
- err:
- OPENSSL_secure_free(nm);
- OPENSSL_secure_clear_free(data, len);
- return ret;
-}
-
-int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
- unsigned char *kstr, int klen,
- pem_password_cb *cb, void *u)
-{
- if (x->ameth == NULL || x->ameth->priv_encode != NULL)
- return PEM_write_bio_PKCS8PrivateKey(bp, x, enc,
- (char *)kstr, klen, cb, u);
- return PEM_write_bio_PrivateKey_traditional(bp, x, enc, kstr, klen, cb, u);
-}
-
-int PEM_write_bio_PrivateKey_traditional(BIO *bp, EVP_PKEY *x,
- const EVP_CIPHER *enc,
- unsigned char *kstr, int klen,
- pem_password_cb *cb, void *u)
-{
- char pem_str[80];
-
- if (x->ameth == NULL || x->ameth->old_priv_encode == NULL) {
- PEMerr(PEM_F_PEM_WRITE_BIO_PRIVATEKEY_TRADITIONAL,
- PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
- return 0;
- }
- BIO_snprintf(pem_str, 80, "%s PRIVATE KEY", x->ameth->pem_str);
- return PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey,
- pem_str, bp, x, enc, kstr, klen, cb, u);
-}
-
-EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x)
-{
- char *nm = NULL;
- const unsigned char *p = NULL;
- unsigned char *data = NULL;
- long len;
- int slen;
- EVP_PKEY *ret = NULL;
-
- if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_PARAMETERS,
- bp, 0, NULL))
- return NULL;
- p = data;
-
- if ((slen = pem_check_suffix(nm, "PARAMETERS")) > 0) {
+ ret = ossl_d2i_PrivateKey_legacy(ameth->pkey_id, x, &p, len, libctx,
+ propq);
+ } else if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) == 0
+ && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ /* Trying legacy PUBKEY decoding only if we do not want private key. */
+ ret = ossl_d2i_PUBKEY_legacy(x, &p, len);
+ } else if ((selection & EVP_PKEY_KEYPAIR) == 0
+ && (slen = ossl_pem_check_suffix(nm, "PARAMETERS")) > 0) {
+ /* Trying legacy params decoding only if we do not want a key. */
ret = EVP_PKEY_new();
if (ret == NULL)
goto err;
@@ -145,107 +196,245 @@ EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x)
goto err;
}
if (x) {
- EVP_PKEY_free((EVP_PKEY *)*x);
+ EVP_PKEY_free(*x);
*x = ret;
}
}
+
+ p8err:
+ if (ret == NULL && ERR_peek_last_error() == 0)
+ /* ensure some error is reported but do not hide the real one */
+ ERR_raise(ERR_LIB_PEM, ERR_R_ASN1_LIB);
err:
- if (ret == NULL)
- PEMerr(PEM_F_PEM_READ_BIO_PARAMETERS, ERR_R_ASN1_LIB);
- OPENSSL_free(nm);
- OPENSSL_free(data);
+ OPENSSL_secure_free(nm);
+ OPENSSL_secure_clear_free(data, len);
return ret;
}
-int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x)
+static EVP_PKEY *pem_read_bio_key(BIO *bp, EVP_PKEY **x,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx,
+ const char *propq,
+ int selection)
{
- char pem_str[80];
- if (!x->ameth || !x->ameth->param_encode)
- return 0;
+ EVP_PKEY *ret = NULL;
+ BIO *new_bio = NULL;
+ int pos;
+ struct ossl_passphrase_data_st pwdata = { 0 };
- BIO_snprintf(pem_str, 80, "%s PARAMETERS", x->ameth->pem_str);
- return PEM_ASN1_write_bio((i2d_of_void *)x->ameth->param_encode,
- pem_str, bp, x, NULL, NULL, 0, 0, NULL);
+ if ((pos = BIO_tell(bp)) < 0) {
+ new_bio = BIO_new(BIO_f_readbuffer());
+ if (new_bio == NULL)
+ return NULL;
+ bp = BIO_push(new_bio, bp);
+ pos = BIO_tell(bp);
+ }
+
+ if (cb == NULL)
+ cb = PEM_def_callback;
+
+ if (!ossl_pw_set_pem_password_cb(&pwdata, cb, u)
+ || !ossl_pw_enable_passphrase_caching(&pwdata))
+ goto err;
+
+ ERR_set_mark();
+ ret = pem_read_bio_key_decoder(bp, x, ossl_pw_pem_password, &pwdata,
+ libctx, propq, selection);
+ if (ret == NULL
+ && (BIO_seek(bp, pos) < 0
+ || (ret = pem_read_bio_key_legacy(bp, x,
+ ossl_pw_pem_password, &pwdata,
+ libctx, propq,
+ selection)) == NULL))
+ ERR_clear_last_mark();
+ else
+ ERR_pop_to_mark();
+
+ err:
+ ossl_pw_clear_passphrase_data(&pwdata);
+ if (new_bio != NULL) {
+ BIO_pop(new_bio);
+ BIO_free(new_bio);
+ }
+ return ret;
}
-#ifndef OPENSSL_NO_STDIO
-EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
+EVP_PKEY *PEM_read_bio_PUBKEY_ex(BIO *bp, EVP_PKEY **x,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ return pem_read_bio_key(bp, x, cb, u, libctx, propq,
+ EVP_PKEY_PUBLIC_KEY);
+}
+
+EVP_PKEY *PEM_read_bio_PUBKEY(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
void *u)
{
+ return PEM_read_bio_PUBKEY_ex(bp, x, cb, u, NULL, NULL);
+}
+
+#ifndef OPENSSL_NO_STDIO
+EVP_PKEY *PEM_read_PUBKEY_ex(FILE *fp, EVP_PKEY **x,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
BIO *b;
EVP_PKEY *ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- PEMerr(PEM_F_PEM_READ_PRIVATEKEY, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
- ret = PEM_read_bio_PrivateKey(b, x, cb, u);
+ ret = PEM_read_bio_PUBKEY_ex(b, x, cb, u, libctx, propq);
BIO_free(b);
return ret;
}
-int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
- unsigned char *kstr, int klen,
- pem_password_cb *cb, void *u)
+EVP_PKEY *PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u)
{
- BIO *b;
+ return PEM_read_PUBKEY_ex(fp, x, cb, u, NULL, NULL);
+}
+#endif
+
+EVP_PKEY *PEM_read_bio_PrivateKey_ex(BIO *bp, EVP_PKEY **x,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ return pem_read_bio_key(bp, x, cb, u, libctx, propq,
+ /* we also want the public key, if available */
+ EVP_PKEY_KEYPAIR);
+}
+
+EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
+ void *u)
+{
+ return PEM_read_bio_PrivateKey_ex(bp, x, cb, u, NULL, NULL);
+}
+
+PEM_write_cb_ex_fnsig(PrivateKey, EVP_PKEY, BIO, write_bio)
+{
+ IMPLEMENT_PEM_provided_write_body_vars(pkey, PrivateKey, propq);
+
+ IMPLEMENT_PEM_provided_write_body_pass();
+ IMPLEMENT_PEM_provided_write_body_main(pkey, bio);
+
+ legacy:
+ if (x != NULL && (x->ameth == NULL || x->ameth->priv_encode != NULL))
+ return PEM_write_bio_PKCS8PrivateKey(out, x, enc,
+ (const char *)kstr, klen, cb, u);
+ return PEM_write_bio_PrivateKey_traditional(out, x, enc, kstr, klen, cb, u);
+}
+
+PEM_write_cb_fnsig(PrivateKey, EVP_PKEY, BIO, write_bio)
+{
+ return PEM_write_bio_PrivateKey_ex(out, x, enc, kstr, klen, cb, u,
+ NULL, NULL);
+}
+
+/*
+ * Note: there is no way to tell a provided pkey encoder to use "traditional"
+ * encoding. Therefore, if the pkey is provided, we try to take a copy
+ */
+int PEM_write_bio_PrivateKey_traditional(BIO *bp, const EVP_PKEY *x,
+ const EVP_CIPHER *enc,
+ const unsigned char *kstr, int klen,
+ pem_password_cb *cb, void *u)
+{
+ char pem_str[80];
+ EVP_PKEY *copy = NULL;
int ret;
- if ((b = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
- PEMerr(PEM_F_PEM_WRITE_PRIVATEKEY, ERR_R_BUF_LIB);
+ if (x == NULL)
+ return 0;
+
+ if (evp_pkey_is_assigned(x)
+ && evp_pkey_is_provided(x)
+ && evp_pkey_copy_downgraded(&copy, x))
+ x = copy;
+
+ if (x->ameth == NULL || x->ameth->old_priv_encode == NULL) {
+ ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+ EVP_PKEY_free(copy);
return 0;
}
- ret = PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u);
- BIO_free(b);
+ BIO_snprintf(pem_str, 80, "%s PRIVATE KEY", x->ameth->pem_str);
+ ret = PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey,
+ pem_str, bp, x, enc, kstr, klen, cb, u);
+
+ EVP_PKEY_free(copy);
return ret;
}
-#endif
-
-#ifndef OPENSSL_NO_DH
+EVP_PKEY *PEM_read_bio_Parameters_ex(BIO *bp, EVP_PKEY **x,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ return pem_read_bio_key(bp, x, NULL, NULL, libctx, propq,
+ EVP_PKEY_KEY_PARAMETERS);
+}
-/* Transparently read in PKCS#3 or X9.42 DH parameters */
+EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x)
+{
+ return PEM_read_bio_Parameters_ex(bp, x, NULL, NULL);
+}
-DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u)
+PEM_write_fnsig(Parameters, EVP_PKEY, BIO, write_bio)
{
- char *nm = NULL;
- const unsigned char *p = NULL;
- unsigned char *data = NULL;
- long len;
- DH *ret = NULL;
+ char pem_str[80];
+ IMPLEMENT_PEM_provided_write_body_vars(pkey, Parameters, NULL);
- if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_DHPARAMS, bp, cb, u))
- return NULL;
- p = data;
+ IMPLEMENT_PEM_provided_write_body_main(pkey, bio);
- if (strcmp(nm, PEM_STRING_DHXPARAMS) == 0)
- ret = d2i_DHxparams(x, &p, len);
- else
- ret = d2i_DHparams(x, &p, len);
+ legacy:
+ if (!x->ameth || !x->ameth->param_encode)
+ return 0;
- if (ret == NULL)
- PEMerr(PEM_F_PEM_READ_BIO_DHPARAMS, ERR_R_ASN1_LIB);
- OPENSSL_free(nm);
- OPENSSL_free(data);
- return ret;
+ BIO_snprintf(pem_str, 80, "%s PARAMETERS", x->ameth->pem_str);
+ return PEM_ASN1_write_bio((i2d_of_void *)x->ameth->param_encode,
+ pem_str, out, x, NULL, NULL, 0, 0, NULL);
}
-# ifndef OPENSSL_NO_STDIO
-DH *PEM_read_DHparams(FILE *fp, DH **x, pem_password_cb *cb, void *u)
+#ifndef OPENSSL_NO_STDIO
+EVP_PKEY *PEM_read_PrivateKey_ex(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
+ void *u, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
BIO *b;
- DH *ret;
+ EVP_PKEY *ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- PEMerr(PEM_F_PEM_READ_DHPARAMS, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
- ret = PEM_read_bio_DHparams(b, x, cb, u);
+ ret = PEM_read_bio_PrivateKey_ex(b, x, cb, u, libctx, propq);
+ BIO_free(b);
+ return ret;
+}
+
+EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
+ void *u)
+{
+ return PEM_read_PrivateKey_ex(fp, x, cb, u, NULL, NULL);
+}
+
+PEM_write_cb_ex_fnsig(PrivateKey, EVP_PKEY, FILE, write)
+{
+ BIO *b;
+ int ret;
+
+ if ((b = BIO_new_fp(out, BIO_NOCLOSE)) == NULL) {
+ ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
+ return 0;
+ }
+ ret = PEM_write_bio_PrivateKey_ex(b, x, enc, kstr, klen, cb, u,
+ libctx, propq);
BIO_free(b);
return ret;
}
-# endif
+PEM_write_cb_fnsig(PrivateKey, EVP_PKEY, FILE, write)
+{
+ return PEM_write_PrivateKey_ex(out, x, enc, kstr, klen, cb, u, NULL, NULL);
+}
#endif
diff --git a/crypto/pem/pem_sign.c b/crypto/pem/pem_sign.c
index 7e7b32ebf7d0..6ad8e4303721 100644
--- a/crypto/pem/pem_sign.c
+++ b/crypto/pem/pem_sign.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -19,7 +19,8 @@ int PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type)
return EVP_DigestInit_ex(ctx, type, NULL);
}
-int PEM_SignUpdate(EVP_MD_CTX *ctx, unsigned char *data, unsigned int count)
+int PEM_SignUpdate(EVP_MD_CTX *ctx,
+ const unsigned char *data, unsigned int count)
{
return EVP_DigestUpdate(ctx, data, count);
}
@@ -31,9 +32,9 @@ int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
int i, ret = 0;
unsigned int m_len;
- m = OPENSSL_malloc(EVP_PKEY_size(pkey));
+ m = OPENSSL_malloc(EVP_PKEY_get_size(pkey));
if (m == NULL) {
- PEMerr(PEM_F_PEM_SIGNFINAL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
goto err;
}
diff --git a/crypto/pem/pem_x509.c b/crypto/pem/pem_x509.c
index 3a997564a23f..93978ee24558 100644
--- a/crypto/pem/pem_x509.c
+++ b/crypto/pem/pem_x509.c
@@ -1,7 +1,7 @@
/*
* Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/pem/pem_xaux.c b/crypto/pem/pem_xaux.c
index 6d7e1db21afe..d416f088e398 100644
--- a/crypto/pem/pem_xaux.c
+++ b/crypto/pem/pem_xaux.c
@@ -1,7 +1,7 @@
/*
* Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/pem/pvkfmt.c b/crypto/pem/pvkfmt.c
index a933b7c1813c..21b16f5928c1 100644
--- a/crypto/pem/pvkfmt.c
+++ b/crypto/pem/pvkfmt.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,13 +12,20 @@
* and PRIVATEKEYBLOB).
*/
-#include "internal/cryptlib.h"
+/*
+ * RSA and DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/pem.h>
#include <openssl/rand.h>
#include <openssl/bn.h>
-#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
-# include <openssl/dsa.h>
-# include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#include <openssl/rsa.h>
+#include "internal/cryptlib.h"
+#include "crypto/pem.h"
+#include "crypto/evp.h"
/*
* Utility function: read a DWORD (4 byte unsigned integer) in little endian
@@ -29,6 +36,7 @@ static unsigned int read_ledword(const unsigned char **in)
{
const unsigned char *p = *in;
unsigned int ret;
+
ret = (unsigned int)*p++;
ret |= (unsigned int)*p++ << 8;
ret |= (unsigned int)*p++ << 16;
@@ -51,6 +59,65 @@ static int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r)
return 1;
}
+/*
+ * Create an EVP_PKEY from a type specific key.
+ * This takes ownership of |key|, as long as the |evp_type| is acceptable
+ * (EVP_PKEY_RSA or EVP_PKEY_DSA), even if the resulting EVP_PKEY wasn't
+ * created.
+ */
+#define isdss_to_evp_type(isdss) \
+ (isdss == 0 ? EVP_PKEY_RSA : isdss == 1 ? EVP_PKEY_DSA : EVP_PKEY_NONE)
+static EVP_PKEY *evp_pkey_new0_key(void *key, int evp_type)
+{
+ EVP_PKEY *pkey = NULL;
+
+ /*
+ * It's assumed that if |key| is NULL, something went wrong elsewhere
+ * and suitable errors are already reported.
+ */
+ if (key == NULL)
+ return NULL;
+
+ if (!ossl_assert(evp_type == EVP_PKEY_RSA || evp_type == EVP_PKEY_DSA)) {
+ ERR_raise(ERR_LIB_PEM, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ if ((pkey = EVP_PKEY_new()) != NULL) {
+ switch (evp_type) {
+ case EVP_PKEY_RSA:
+ if (EVP_PKEY_set1_RSA(pkey, key))
+ break;
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ break;
+#ifndef OPENSSL_NO_DSA
+ case EVP_PKEY_DSA:
+ if (EVP_PKEY_set1_DSA(pkey, key))
+ break;
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ break;
+#endif
+ }
+ }
+
+ switch (evp_type) {
+ case EVP_PKEY_RSA:
+ RSA_free(key);
+ break;
+#ifndef OPENSSL_NO_DSA
+ case EVP_PKEY_DSA:
+ DSA_free(key);
+ break;
+#endif
+ }
+
+ if (pkey == NULL)
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
+ return pkey;
+}
+
/* Convert private key blob to EVP_PKEY: RSA and DSA keys supported */
# define MS_PUBLICKEYBLOB 0x6
@@ -66,9 +133,6 @@ static int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r)
# define MS_KEYTYPE_KEYX 0x1
# define MS_KEYTYPE_SIGN 0x2
-/* Maximum length of a blob after header */
-# define BLOB_MAX_LENGTH 102400
-
/* The PVK file magic number: seems to spell out "bobsfile", who is Bob? */
# define MS_PVKMAGIC 0xb0b5f11eL
/* Salt length for PVK files */
@@ -78,79 +142,115 @@ static int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r)
/* Maximum salt length */
# define PVK_MAX_SALTLEN 10240
-static EVP_PKEY *b2i_rsa(const unsigned char **in,
- unsigned int bitlen, int ispub);
-static EVP_PKEY *b2i_dss(const unsigned char **in,
- unsigned int bitlen, int ispub);
-
-static int do_blob_header(const unsigned char **in, unsigned int length,
- unsigned int *pmagic, unsigned int *pbitlen,
- int *pisdss, int *pispub)
+/*
+ * Read the MSBLOB header and get relevant data from it.
+ *
+ * |pisdss| and |pispub| have a double role, as they can be used for
+ * discovery as well as to check the the blob meets expectations.
+ * |*pisdss| is the indicator for whether the key is a DSA key or not.
+ * |*pispub| is the indicator for whether the key is public or not.
+ * In both cases, the following input values apply:
+ *
+ * 0 Expected to not be what the variable indicates.
+ * 1 Expected to be what the variable indicates.
+ * -1 No expectations, this function will assign 0 or 1 depending on
+ * header data.
+ */
+int ossl_do_blob_header(const unsigned char **in, unsigned int length,
+ unsigned int *pmagic, unsigned int *pbitlen,
+ int *pisdss, int *pispub)
{
const unsigned char *p = *in;
+
if (length < 16)
return 0;
/* bType */
- if (*p == MS_PUBLICKEYBLOB) {
+ switch (*p) {
+ case MS_PUBLICKEYBLOB:
if (*pispub == 0) {
- PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
+ ERR_raise(ERR_LIB_PEM, PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
return 0;
}
*pispub = 1;
- } else if (*p == MS_PRIVATEKEYBLOB) {
+ break;
+
+ case MS_PRIVATEKEYBLOB:
if (*pispub == 1) {
- PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
+ ERR_raise(ERR_LIB_PEM, PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
return 0;
}
*pispub = 0;
- } else
+ break;
+
+ default:
return 0;
+ }
p++;
/* Version */
if (*p++ != 0x2) {
- PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_VERSION_NUMBER);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_VERSION_NUMBER);
return 0;
}
/* Ignore reserved, aiKeyAlg */
p += 6;
*pmagic = read_ledword(&p);
*pbitlen = read_ledword(&p);
- *pisdss = 0;
- switch (*pmagic) {
+ /* Consistency check for private vs public */
+ switch (*pmagic) {
case MS_DSS1MAGIC:
- *pisdss = 1;
- /* fall thru */
case MS_RSA1MAGIC:
if (*pispub == 0) {
- PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
+ ERR_raise(ERR_LIB_PEM, PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
return 0;
}
break;
case MS_DSS2MAGIC:
- *pisdss = 1;
- /* fall thru */
case MS_RSA2MAGIC:
if (*pispub == 1) {
- PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
+ ERR_raise(ERR_LIB_PEM, PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
return 0;
}
break;
default:
- PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_MAGIC_NUMBER);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_MAGIC_NUMBER);
+ return -1;
+ }
+
+ /* Check that we got the expected type */
+ switch (*pmagic) {
+ case MS_DSS1MAGIC:
+ case MS_DSS2MAGIC:
+ if (*pisdss == 0) {
+ ERR_raise(ERR_LIB_PEM, PEM_R_EXPECTING_DSS_KEY_BLOB);
+ return 0;
+ }
+ *pisdss = 1;
+ break;
+ case MS_RSA1MAGIC:
+ case MS_RSA2MAGIC:
+ if (*pisdss == 1) {
+ ERR_raise(ERR_LIB_PEM, PEM_R_EXPECTING_RSA_KEY_BLOB);
+ return 0;
+ }
+ *pisdss = 0;
+ break;
+
+ default:
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_MAGIC_NUMBER);
return -1;
}
*in = p;
return 1;
}
-static unsigned int blob_length(unsigned bitlen, int isdss, int ispub)
+unsigned int ossl_blob_length(unsigned bitlen, int isdss, int ispub)
{
- unsigned int nbyte, hnbyte;
- nbyte = (bitlen + 7) >> 3;
- hnbyte = (bitlen + 15) >> 4;
+ unsigned int nbyte = (bitlen + 7) >> 3;
+ unsigned int hnbyte = (bitlen + 15) >> 4;
+
if (isdss) {
/*
@@ -179,84 +279,109 @@ static unsigned int blob_length(unsigned bitlen, int isdss, int ispub)
}
-static EVP_PKEY *do_b2i(const unsigned char **in, unsigned int length,
- int ispub)
+static void *do_b2i_key(const unsigned char **in, unsigned int length,
+ int *isdss, int *ispub)
{
const unsigned char *p = *in;
unsigned int bitlen, magic;
- int isdss;
- if (do_blob_header(&p, length, &magic, &bitlen, &isdss, &ispub) <= 0) {
- PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_HEADER_PARSE_ERROR);
+ void *key = NULL;
+
+ if (ossl_do_blob_header(&p, length, &magic, &bitlen, isdss, ispub) <= 0) {
+ ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_HEADER_PARSE_ERROR);
return NULL;
}
length -= 16;
- if (length < blob_length(bitlen, isdss, ispub)) {
- PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_TOO_SHORT);
+ if (length < ossl_blob_length(bitlen, *isdss, *ispub)) {
+ ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT);
return NULL;
}
- if (isdss)
- return b2i_dss(&p, bitlen, ispub);
+ if (!*isdss)
+ key = ossl_b2i_RSA_after_header(&p, bitlen, *ispub);
+#ifndef OPENSSL_NO_DSA
else
- return b2i_rsa(&p, bitlen, ispub);
+ key = ossl_b2i_DSA_after_header(&p, bitlen, *ispub);
+#endif
+
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+ return NULL;
+ }
+
+ return key;
}
-static EVP_PKEY *do_b2i_bio(BIO *in, int ispub)
+EVP_PKEY *ossl_b2i(const unsigned char **in, unsigned int length, int *ispub)
+{
+ int isdss = -1;
+ void *key = do_b2i_key(in, length, &isdss, ispub);
+
+ return evp_pkey_new0_key(key, isdss_to_evp_type(isdss));
+}
+
+EVP_PKEY *ossl_b2i_bio(BIO *in, int *ispub)
{
const unsigned char *p;
unsigned char hdr_buf[16], *buf = NULL;
unsigned int bitlen, magic, length;
- int isdss;
- EVP_PKEY *ret = NULL;
+ int isdss = -1;
+ void *key = NULL;
+ EVP_PKEY *pkey = NULL;
+
if (BIO_read(in, hdr_buf, 16) != 16) {
- PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT);
+ ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT);
return NULL;
}
p = hdr_buf;
- if (do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) <= 0)
+ if (ossl_do_blob_header(&p, 16, &magic, &bitlen, &isdss, ispub) <= 0)
return NULL;
- length = blob_length(bitlen, isdss, ispub);
+ length = ossl_blob_length(bitlen, isdss, *ispub);
if (length > BLOB_MAX_LENGTH) {
- PEMerr(PEM_F_DO_B2I_BIO, PEM_R_HEADER_TOO_LONG);
+ ERR_raise(ERR_LIB_PEM, PEM_R_HEADER_TOO_LONG);
return NULL;
}
buf = OPENSSL_malloc(length);
if (buf == NULL) {
- PEMerr(PEM_F_DO_B2I_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
goto err;
}
p = buf;
if (BIO_read(in, buf, length) != (int)length) {
- PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT);
+ ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT);
goto err;
}
- if (isdss)
- ret = b2i_dss(&p, bitlen, ispub);
+ if (!isdss)
+ key = ossl_b2i_RSA_after_header(&p, bitlen, *ispub);
+#ifndef OPENSSL_NO_DSA
else
- ret = b2i_rsa(&p, bitlen, ispub);
+ key = ossl_b2i_DSA_after_header(&p, bitlen, *ispub);
+#endif
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+ goto err;
+ }
+
+ pkey = evp_pkey_new0_key(key, isdss_to_evp_type(isdss));
err:
OPENSSL_free(buf);
- return ret;
+ return pkey;
}
-static EVP_PKEY *b2i_dss(const unsigned char **in,
- unsigned int bitlen, int ispub)
+#ifndef OPENSSL_NO_DSA
+DSA *ossl_b2i_DSA_after_header(const unsigned char **in, unsigned int bitlen,
+ int ispub)
{
const unsigned char *p = *in;
- EVP_PKEY *ret = NULL;
DSA *dsa = NULL;
BN_CTX *ctx = NULL;
- unsigned int nbyte;
BIGNUM *pbn = NULL, *qbn = NULL, *gbn = NULL, *priv_key = NULL;
BIGNUM *pub_key = NULL;
-
- nbyte = (bitlen + 7) >> 3;
+ unsigned int nbyte = (bitlen + 7) >> 3;
dsa = DSA_new();
- ret = EVP_PKEY_new();
- if (dsa == NULL || ret == NULL)
+ if (dsa == NULL)
goto memerr;
if (!read_lebn(&p, nbyte, &pbn))
goto memerr;
@@ -297,39 +422,34 @@ static EVP_PKEY *b2i_dss(const unsigned char **in,
goto memerr;
pub_key = priv_key = NULL;
- if (!EVP_PKEY_set1_DSA(ret, dsa))
- goto memerr;
- DSA_free(dsa);
*in = p;
- return ret;
+ return dsa;
memerr:
- PEMerr(PEM_F_B2I_DSS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
DSA_free(dsa);
BN_free(pbn);
BN_free(qbn);
BN_free(gbn);
BN_free(pub_key);
BN_free(priv_key);
- EVP_PKEY_free(ret);
BN_CTX_free(ctx);
return NULL;
}
+#endif
-static EVP_PKEY *b2i_rsa(const unsigned char **in,
- unsigned int bitlen, int ispub)
+RSA *ossl_b2i_RSA_after_header(const unsigned char **in, unsigned int bitlen,
+ int ispub)
{
const unsigned char *pin = *in;
- EVP_PKEY *ret = NULL;
BIGNUM *e = NULL, *n = NULL, *d = NULL;
BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
RSA *rsa = NULL;
- unsigned int nbyte, hnbyte;
- nbyte = (bitlen + 7) >> 3;
- hnbyte = (bitlen + 15) >> 4;
+ unsigned int nbyte = (bitlen + 7) >> 3;
+ unsigned int hnbyte = (bitlen + 15) >> 4;
+
rsa = RSA_new();
- ret = EVP_PKEY_new();
- if (rsa == NULL || ret == NULL)
+ if (rsa == NULL)
goto memerr;
e = BN_new();
if (e == NULL)
@@ -362,13 +482,10 @@ static EVP_PKEY *b2i_rsa(const unsigned char **in,
goto memerr;
n = e = d = NULL;
- if (!EVP_PKEY_set1_RSA(ret, rsa))
- goto memerr;
- RSA_free(rsa);
*in = pin;
- return ret;
+ return rsa;
memerr:
- PEMerr(PEM_F_B2I_RSA, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
BN_free(e);
BN_free(n);
BN_free(p);
@@ -378,33 +495,41 @@ static EVP_PKEY *b2i_rsa(const unsigned char **in,
BN_free(iqmp);
BN_free(d);
RSA_free(rsa);
- EVP_PKEY_free(ret);
return NULL;
}
EVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length)
{
- return do_b2i(in, length, 0);
+ int ispub = 0;
+
+ return ossl_b2i(in, length, &ispub);
}
EVP_PKEY *b2i_PublicKey(const unsigned char **in, long length)
{
- return do_b2i(in, length, 1);
+ int ispub = 1;
+
+ return ossl_b2i(in, length, &ispub);
}
EVP_PKEY *b2i_PrivateKey_bio(BIO *in)
{
- return do_b2i_bio(in, 0);
+ int ispub = 0;
+
+ return ossl_b2i_bio(in, &ispub);
}
EVP_PKEY *b2i_PublicKey_bio(BIO *in)
{
- return do_b2i_bio(in, 1);
+ int ispub = 1;
+
+ return ossl_b2i_bio(in, &ispub);
}
static void write_ledword(unsigned char **out, unsigned int dw)
{
unsigned char *p = *out;
+
*p++ = dw & 0xff;
*p++ = (dw >> 8) & 0xff;
*p++ = (dw >> 16) & 0xff;
@@ -418,38 +543,43 @@ static void write_lebn(unsigned char **out, const BIGNUM *bn, int len)
*out += len;
}
-static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *magic);
-static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *magic);
+static int check_bitlen_rsa(const RSA *rsa, int ispub, unsigned int *magic);
+static void write_rsa(unsigned char **out, const RSA *rsa, int ispub);
-static void write_rsa(unsigned char **out, RSA *rsa, int ispub);
-static void write_dsa(unsigned char **out, DSA *dsa, int ispub);
+#ifndef OPENSSL_NO_DSA
+static int check_bitlen_dsa(const DSA *dsa, int ispub, unsigned int *magic);
+static void write_dsa(unsigned char **out, const DSA *dsa, int ispub);
+#endif
-static int do_i2b(unsigned char **out, EVP_PKEY *pk, int ispub)
+static int do_i2b(unsigned char **out, const EVP_PKEY *pk, int ispub)
{
unsigned char *p;
- unsigned int bitlen, magic = 0, keyalg;
- int outlen, noinc = 0;
- int pktype = EVP_PKEY_id(pk);
- if (pktype == EVP_PKEY_DSA) {
- bitlen = check_bitlen_dsa(EVP_PKEY_get0_DSA(pk), ispub, &magic);
- keyalg = MS_KEYALG_DSS_SIGN;
- } else if (pktype == EVP_PKEY_RSA) {
+ unsigned int bitlen = 0, magic = 0, keyalg = 0;
+ int outlen = -1, noinc = 0;
+
+ if (EVP_PKEY_is_a(pk, "RSA")) {
bitlen = check_bitlen_rsa(EVP_PKEY_get0_RSA(pk), ispub, &magic);
keyalg = MS_KEYALG_RSA_KEYX;
- } else
- return -1;
- if (bitlen == 0)
- return -1;
- outlen = 16 + blob_length(bitlen,
- keyalg == MS_KEYALG_DSS_SIGN ? 1 : 0, ispub);
+#ifndef OPENSSL_NO_DSA
+ } else if (EVP_PKEY_is_a(pk, "DSA")) {
+ bitlen = check_bitlen_dsa(EVP_PKEY_get0_DSA(pk), ispub, &magic);
+ keyalg = MS_KEYALG_DSS_SIGN;
+#endif
+ }
+ if (bitlen == 0) {
+ goto end;
+ }
+ outlen = 16
+ + ossl_blob_length(bitlen, keyalg == MS_KEYALG_DSS_SIGN ? 1 : 0, ispub);
if (out == NULL)
- return outlen;
+ goto end;
if (*out)
p = *out;
else {
if ((p = OPENSSL_malloc(outlen)) == NULL) {
- PEMerr(PEM_F_DO_I2B, ERR_R_MALLOC_FAILURE);
- return -1;
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
+ outlen = -1;
+ goto end;
}
*out = p;
noinc = 1;
@@ -464,19 +594,23 @@ static int do_i2b(unsigned char **out, EVP_PKEY *pk, int ispub)
write_ledword(&p, keyalg);
write_ledword(&p, magic);
write_ledword(&p, bitlen);
- if (keyalg == MS_KEYALG_DSS_SIGN)
- write_dsa(&p, EVP_PKEY_get0_DSA(pk), ispub);
- else
+ if (keyalg == MS_KEYALG_RSA_KEYX)
write_rsa(&p, EVP_PKEY_get0_RSA(pk), ispub);
+#ifndef OPENSSL_NO_DSA
+ else
+ write_dsa(&p, EVP_PKEY_get0_DSA(pk), ispub);
+#endif
if (!noinc)
*out += outlen;
+ end:
return outlen;
}
-static int do_i2b_bio(BIO *out, EVP_PKEY *pk, int ispub)
+static int do_i2b_bio(BIO *out, const EVP_PKEY *pk, int ispub)
{
unsigned char *tmp = NULL;
int outlen, wrlen;
+
outlen = do_i2b(&tmp, pk, ispub);
if (outlen < 0)
return -1;
@@ -487,35 +621,7 @@ static int do_i2b_bio(BIO *out, EVP_PKEY *pk, int ispub)
return -1;
}
-static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *pmagic)
-{
- int bitlen;
- const BIGNUM *p = NULL, *q = NULL, *g = NULL;
- const BIGNUM *pub_key = NULL, *priv_key = NULL;
-
- DSA_get0_pqg(dsa, &p, &q, &g);
- DSA_get0_key(dsa, &pub_key, &priv_key);
- bitlen = BN_num_bits(p);
- if ((bitlen & 7) || (BN_num_bits(q) != 160)
- || (BN_num_bits(g) > bitlen))
- goto badkey;
- if (ispub) {
- if (BN_num_bits(pub_key) > bitlen)
- goto badkey;
- *pmagic = MS_DSS1MAGIC;
- } else {
- if (BN_num_bits(priv_key) > 160)
- goto badkey;
- *pmagic = MS_DSS2MAGIC;
- }
-
- return bitlen;
- badkey:
- PEMerr(PEM_F_CHECK_BITLEN_DSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
- return 0;
-}
-
-static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic)
+static int check_bitlen_rsa(const RSA *rsa, int ispub, unsigned int *pmagic)
{
int nbyte, hnbyte, bitlen;
const BIGNUM *e;
@@ -551,11 +657,11 @@ static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic)
}
return bitlen;
badkey:
- PEMerr(PEM_F_CHECK_BITLEN_RSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
+ ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
return 0;
}
-static void write_rsa(unsigned char **out, RSA *rsa, int ispub)
+static void write_rsa(unsigned char **out, const RSA *rsa, int ispub)
{
int nbyte, hnbyte;
const BIGNUM *n, *d, *e, *p, *q, *iqmp, *dmp1, *dmq1;
@@ -577,7 +683,36 @@ static void write_rsa(unsigned char **out, RSA *rsa, int ispub)
write_lebn(out, d, nbyte);
}
-static void write_dsa(unsigned char **out, DSA *dsa, int ispub)
+#ifndef OPENSSL_NO_DSA
+static int check_bitlen_dsa(const DSA *dsa, int ispub, unsigned int *pmagic)
+{
+ int bitlen;
+ const BIGNUM *p = NULL, *q = NULL, *g = NULL;
+ const BIGNUM *pub_key = NULL, *priv_key = NULL;
+
+ DSA_get0_pqg(dsa, &p, &q, &g);
+ DSA_get0_key(dsa, &pub_key, &priv_key);
+ bitlen = BN_num_bits(p);
+ if ((bitlen & 7) || (BN_num_bits(q) != 160)
+ || (BN_num_bits(g) > bitlen))
+ goto badkey;
+ if (ispub) {
+ if (BN_num_bits(pub_key) > bitlen)
+ goto badkey;
+ *pmagic = MS_DSS1MAGIC;
+ } else {
+ if (BN_num_bits(priv_key) > 160)
+ goto badkey;
+ *pmagic = MS_DSS2MAGIC;
+ }
+
+ return bitlen;
+ badkey:
+ ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
+ return 0;
+}
+
+static void write_dsa(unsigned char **out, const DSA *dsa, int ispub)
{
int nbyte;
const BIGNUM *p = NULL, *q = NULL, *g = NULL;
@@ -598,38 +733,38 @@ static void write_dsa(unsigned char **out, DSA *dsa, int ispub)
*out += 24;
return;
}
+#endif
-int i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk)
+int i2b_PrivateKey_bio(BIO *out, const EVP_PKEY *pk)
{
return do_i2b_bio(out, pk, 0);
}
-int i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk)
+int i2b_PublicKey_bio(BIO *out, const EVP_PKEY *pk)
{
return do_i2b_bio(out, pk, 1);
}
-# ifndef OPENSSL_NO_RC4
-
-static int do_PVK_header(const unsigned char **in, unsigned int length,
- int skip_magic,
- unsigned int *psaltlen, unsigned int *pkeylen)
+int ossl_do_PVK_header(const unsigned char **in, unsigned int length,
+ int skip_magic,
+ unsigned int *psaltlen, unsigned int *pkeylen)
{
const unsigned char *p = *in;
unsigned int pvk_magic, is_encrypted;
+
if (skip_magic) {
if (length < 20) {
- PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);
+ ERR_raise(ERR_LIB_PEM, PEM_R_PVK_TOO_SHORT);
return 0;
}
} else {
if (length < 24) {
- PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);
+ ERR_raise(ERR_LIB_PEM, PEM_R_PVK_TOO_SHORT);
return 0;
}
pvk_magic = read_ledword(&p);
if (pvk_magic != MS_PVKMAGIC) {
- PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_BAD_MAGIC_NUMBER);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_MAGIC_NUMBER);
return 0;
}
}
@@ -645,8 +780,8 @@ static int do_PVK_header(const unsigned char **in, unsigned int length,
if (*pkeylen > PVK_MAX_KEYLEN || *psaltlen > PVK_MAX_SALTLEN)
return 0;
- if (is_encrypted && !*psaltlen) {
- PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_INCONSISTENT_HEADER);
+ if (is_encrypted && *psaltlen == 0) {
+ ERR_raise(ERR_LIB_PEM, PEM_R_INCONSISTENT_HEADER);
return 0;
}
@@ -654,64 +789,90 @@ static int do_PVK_header(const unsigned char **in, unsigned int length,
return 1;
}
+#ifndef OPENSSL_NO_RC4
static int derive_pvk_key(unsigned char *key,
const unsigned char *salt, unsigned int saltlen,
- const unsigned char *pass, int passlen)
+ const unsigned char *pass, int passlen,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
- int rv = 1;
+ int rv = 0;
+ EVP_MD *sha1 = NULL;
+
+ if ((sha1 = EVP_MD_fetch(libctx, SN_sha1, propq)) == NULL)
+ goto err;
+
if (mctx == NULL
- || !EVP_DigestInit_ex(mctx, EVP_sha1(), NULL)
+ || !EVP_DigestInit_ex(mctx, sha1, NULL)
|| !EVP_DigestUpdate(mctx, salt, saltlen)
|| !EVP_DigestUpdate(mctx, pass, passlen)
|| !EVP_DigestFinal_ex(mctx, key, NULL))
- rv = 0;
+ goto err;
+ rv = 1;
+err:
EVP_MD_CTX_free(mctx);
+ EVP_MD_free(sha1);
return rv;
}
+#endif
-static EVP_PKEY *do_PVK_body(const unsigned char **in,
+static void *do_PVK_body_key(const unsigned char **in,
unsigned int saltlen, unsigned int keylen,
- pem_password_cb *cb, void *u)
+ pem_password_cb *cb, void *u,
+ int *isdss, int *ispub,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
- EVP_PKEY *ret = NULL;
const unsigned char *p = *in;
- unsigned int magic;
- unsigned char *enctmp = NULL, *q;
+ unsigned char *enctmp = NULL;
unsigned char keybuf[20];
-
+ void *key = NULL;
+#ifndef OPENSSL_NO_RC4
+ EVP_CIPHER *rc4 = NULL;
+#endif
EVP_CIPHER_CTX *cctx = EVP_CIPHER_CTX_new();
+
+ if (cctx == NULL) {
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
if (saltlen) {
+#ifndef OPENSSL_NO_RC4
+ unsigned int magic;
char psbuf[PEM_BUFSIZE];
int enctmplen, inlen;
+ unsigned char *q;
+
if (cb)
inlen = cb(psbuf, PEM_BUFSIZE, 0, u);
else
inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
if (inlen < 0) {
- PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_PASSWORD_READ);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ);
goto err;
}
enctmp = OPENSSL_malloc(keylen + 8);
if (enctmp == NULL) {
- PEMerr(PEM_F_DO_PVK_BODY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!derive_pvk_key(keybuf, p, saltlen,
- (unsigned char *)psbuf, inlen))
+ (unsigned char *)psbuf, inlen, libctx, propq))
goto err;
p += saltlen;
/* Copy BLOBHEADER across, decrypt rest */
memcpy(enctmp, p, 8);
p += 8;
if (keylen < 8) {
- PEMerr(PEM_F_DO_PVK_BODY, PEM_R_PVK_TOO_SHORT);
+ ERR_raise(ERR_LIB_PEM, PEM_R_PVK_TOO_SHORT);
goto err;
}
inlen = keylen - 8;
q = enctmp + 8;
- if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
+ if ((rc4 = EVP_CIPHER_fetch(libctx, "RC4", propq)) == NULL)
+ goto err;
+ if (!EVP_DecryptInit_ex(cctx, rc4, NULL, keybuf, NULL))
goto err;
if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen))
goto err;
@@ -721,7 +882,7 @@ static EVP_PKEY *do_PVK_body(const unsigned char **in,
if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) {
q = enctmp + 8;
memset(keybuf + 5, 0, 11);
- if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
+ if (!EVP_DecryptInit_ex(cctx, rc4, NULL, keybuf, NULL))
goto err;
if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen))
goto err;
@@ -729,62 +890,124 @@ static EVP_PKEY *do_PVK_body(const unsigned char **in,
goto err;
magic = read_ledword((const unsigned char **)&q);
if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) {
- PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_DECRYPT);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_DECRYPT);
goto err;
}
}
p = enctmp;
+#else
+ ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_CIPHER);
+ goto err;
+#endif
}
- ret = b2i_PrivateKey(&p, keylen);
+ key = do_b2i_key(&p, keylen, isdss, ispub);
err:
EVP_CIPHER_CTX_free(cctx);
+#ifndef OPENSSL_NO_RC4
+ EVP_CIPHER_free(rc4);
+#endif
if (enctmp != NULL) {
OPENSSL_cleanse(keybuf, sizeof(keybuf));
OPENSSL_free(enctmp);
}
- return ret;
+ return key;
}
-EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
+static void *do_PVK_key_bio(BIO *in, pem_password_cb *cb, void *u,
+ int *isdss, int *ispub,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
unsigned char pvk_hdr[24], *buf = NULL;
const unsigned char *p;
int buflen;
- EVP_PKEY *ret = NULL;
+ void *key = NULL;
unsigned int saltlen, keylen;
+
if (BIO_read(in, pvk_hdr, 24) != 24) {
- PEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT);
+ ERR_raise(ERR_LIB_PEM, PEM_R_PVK_DATA_TOO_SHORT);
return NULL;
}
p = pvk_hdr;
- if (!do_PVK_header(&p, 24, 0, &saltlen, &keylen))
+ if (!ossl_do_PVK_header(&p, 24, 0, &saltlen, &keylen))
return 0;
buflen = (int)keylen + saltlen;
buf = OPENSSL_malloc(buflen);
if (buf == NULL) {
- PEMerr(PEM_F_B2I_PVK_BIO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
return 0;
}
p = buf;
if (BIO_read(in, buf, buflen) != buflen) {
- PEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT);
+ ERR_raise(ERR_LIB_PEM, PEM_R_PVK_DATA_TOO_SHORT);
goto err;
}
- ret = do_PVK_body(&p, saltlen, keylen, cb, u);
+ key = do_PVK_body_key(&p, saltlen, keylen, cb, u, isdss, ispub, libctx, propq);
err:
OPENSSL_clear_free(buf, buflen);
- return ret;
+ return key;
+}
+
+#ifndef OPENSSL_NO_DSA
+DSA *b2i_DSA_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ int isdss = 1;
+ int ispub = 0; /* PVK keys are always private */
+
+ return do_PVK_key_bio(in, cb, u, &isdss, &ispub, libctx, propq);
+}
+
+DSA *b2i_DSA_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
+{
+ return b2i_DSA_PVK_bio_ex(in, cb, u, NULL, NULL);
+}
+#endif
+
+RSA *b2i_RSA_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ int isdss = 0;
+ int ispub = 0; /* PVK keys are always private */
+
+ return do_PVK_key_bio(in, cb, u, &isdss, &ispub, libctx, propq);
}
-static int i2b_PVK(unsigned char **out, EVP_PKEY *pk, int enclevel,
- pem_password_cb *cb, void *u)
+RSA *b2i_RSA_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
+{
+ return b2i_RSA_PVK_bio_ex(in, cb, u, NULL, NULL);
+}
+
+EVP_PKEY *b2i_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ int isdss = -1;
+ int ispub = -1;
+ void *key = do_PVK_key_bio(in, cb, u, &isdss, &ispub, NULL, NULL);
+
+ return evp_pkey_new0_key(key, isdss_to_evp_type(isdss));
+}
+
+EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
{
+ return b2i_PVK_bio_ex(in, cb, u, NULL, NULL);
+}
+
+static int i2b_PVK(unsigned char **out, const EVP_PKEY *pk, int enclevel,
+ pem_password_cb *cb, void *u, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ int ret = -1;
int outlen = 24, pklen;
- unsigned char *p = NULL, *start = NULL, *salt = NULL;
+ unsigned char *p = NULL, *start = NULL;
EVP_CIPHER_CTX *cctx = NULL;
+#ifndef OPENSSL_NO_RC4
+ unsigned char *salt = NULL;
+ EVP_CIPHER *rc4 = NULL;
+#endif
+
if (enclevel)
outlen += PVK_SALTLEN;
pklen = do_i2b(NULL, pk, 0);
@@ -798,7 +1021,7 @@ static int i2b_PVK(unsigned char **out, EVP_PKEY *pk, int enclevel,
} else {
start = p = OPENSSL_malloc(outlen);
if (p == NULL) {
- PEMerr(PEM_F_I2B_PVK, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
return -1;
}
}
@@ -809,21 +1032,26 @@ static int i2b_PVK(unsigned char **out, EVP_PKEY *pk, int enclevel,
write_ledword(&p, MS_PVKMAGIC);
write_ledword(&p, 0);
- if (EVP_PKEY_id(pk) == EVP_PKEY_DSA)
- write_ledword(&p, MS_KEYTYPE_SIGN);
- else
+ if (EVP_PKEY_get_id(pk) == EVP_PKEY_RSA)
write_ledword(&p, MS_KEYTYPE_KEYX);
+#ifndef OPENSSL_NO_DSA
+ else
+ write_ledword(&p, MS_KEYTYPE_SIGN);
+#endif
write_ledword(&p, enclevel ? 1 : 0);
write_ledword(&p, enclevel ? PVK_SALTLEN : 0);
write_ledword(&p, pklen);
if (enclevel) {
- if (RAND_bytes(p, PVK_SALTLEN) <= 0)
+#ifndef OPENSSL_NO_RC4
+ if (RAND_bytes_ex(libctx, p, PVK_SALTLEN, 0) <= 0)
goto error;
salt = p;
p += PVK_SALTLEN;
+#endif
}
do_i2b(&p, pk, 0);
if (enclevel != 0) {
+#ifndef OPENSSL_NO_RC4
char psbuf[PEM_BUFSIZE];
unsigned char keybuf[20];
int enctmplen, inlen;
@@ -832,44 +1060,52 @@ static int i2b_PVK(unsigned char **out, EVP_PKEY *pk, int enclevel,
else
inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 1, u);
if (inlen <= 0) {
- PEMerr(PEM_F_I2B_PVK, PEM_R_BAD_PASSWORD_READ);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ);
goto error;
}
if (!derive_pvk_key(keybuf, salt, PVK_SALTLEN,
- (unsigned char *)psbuf, inlen))
+ (unsigned char *)psbuf, inlen, libctx, propq))
+ goto error;
+ if ((rc4 = EVP_CIPHER_fetch(libctx, "RC4", propq)) == NULL)
goto error;
if (enclevel == 1)
memset(keybuf + 5, 0, 11);
p = salt + PVK_SALTLEN + 8;
- if (!EVP_EncryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
+ if (!EVP_EncryptInit_ex(cctx, rc4, NULL, keybuf, NULL))
goto error;
OPENSSL_cleanse(keybuf, 20);
if (!EVP_EncryptUpdate(cctx, p, &enctmplen, p, pklen - 8))
goto error;
if (!EVP_EncryptFinal_ex(cctx, p + enctmplen, &enctmplen))
goto error;
+#else
+ ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_CIPHER);
+ goto error;
+#endif
}
- EVP_CIPHER_CTX_free(cctx);
-
if (*out == NULL)
*out = start;
-
- return outlen;
-
+ ret = outlen;
error:
EVP_CIPHER_CTX_free(cctx);
+#ifndef OPENSSL_NO_RC4
+ EVP_CIPHER_free(rc4);
+#endif
if (*out == NULL)
OPENSSL_free(start);
- return -1;
+
+ return ret;
}
-int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel,
- pem_password_cb *cb, void *u)
+int i2b_PVK_bio_ex(BIO *out, const EVP_PKEY *pk, int enclevel,
+ pem_password_cb *cb, void *u, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
unsigned char *tmp = NULL;
int outlen, wrlen;
- outlen = i2b_PVK(&tmp, pk, enclevel, cb, u);
+
+ outlen = i2b_PVK(&tmp, pk, enclevel, cb, u, libctx, propq);
if (outlen < 0)
return -1;
wrlen = BIO_write(out, tmp, outlen);
@@ -877,10 +1113,13 @@ int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel,
if (wrlen == outlen) {
return outlen;
}
- PEMerr(PEM_F_I2B_PVK_BIO, PEM_R_BIO_WRITE_FAILURE);
+ ERR_raise(ERR_LIB_PEM, PEM_R_BIO_WRITE_FAILURE);
return -1;
}
-# endif
+int i2b_PVK_bio(BIO *out, const EVP_PKEY *pk, int enclevel,
+ pem_password_cb *cb, void *u)
+{
+ return i2b_PVK_bio_ex(out, pk, enclevel, cb, u, NULL, NULL);
+}
-#endif
diff --git a/crypto/perlasm/README b/crypto/perlasm/README
deleted file mode 100644
index 59f2c95515fe..000000000000
--- a/crypto/perlasm/README
+++ /dev/null
@@ -1,124 +0,0 @@
-The perl scripts in this directory are my 'hack' to generate
-multiple different assembler formats via the one original script.
-
-The way to use this library is to start with adding the path to this directory
-and then include it.
-
-push(@INC,"perlasm","../../perlasm");
-require "x86asm.pl";
-
-The first thing we do is setup the file and type of assembler
-
-&asm_init($ARGV[0]);
-
-The first argument is the 'type'. Currently
-'cpp', 'sol', 'a.out', 'elf' or 'win32'.
-Argument 2 is the file name.
-
-The reciprocal function is
-&asm_finish() which should be called at the end.
-
-There are 2 main 'packages'. x86ms.pl, which is the Microsoft assembler,
-and x86unix.pl which is the unix (gas) version.
-
-Functions of interest are:
-&external_label("des_SPtrans"); declare and external variable
-&LB(reg); Low byte for a register
-&HB(reg); High byte for a register
-&BP(off,base,index,scale) Byte pointer addressing
-&DWP(off,base,index,scale) Word pointer addressing
-&stack_push(num) Basically a 'sub esp, num*4' with extra
-&stack_pop(num) inverse of stack_push
-&function_begin(name,extra) Start a function with pushing of
- edi, esi, ebx and ebp. extra is extra win32
- external info that may be required.
-&function_begin_B(name,extra) Same as normal function_begin but no pushing.
-&function_end(name) Call at end of function.
-&function_end_A(name) Standard pop and ret, for use inside functions
-&function_end_B(name) Call at end but with pop or ret.
-&swtmp(num) Address on stack temp word.
-&wparam(num) Parameter number num, that was push
- in C convention. This all works over pushes
- and pops.
-&comment("hello there") Put in a comment.
-&label("loop") Refer to a label, normally a jmp target.
-&set_label("loop") Set a label at this point.
-&data_word(word) Put in a word of data.
-
-So how does this all hold together? Given
-
-int calc(int len, int *data)
- {
- int i,j=0;
-
- for (i=0; i<len; i++)
- {
- j+=other(data[i]);
- }
- }
-
-So a very simple version of this function could be coded as
-
- push(@INC,"perlasm","../../perlasm");
- require "x86asm.pl";
-
- &asm_init($ARGV[0]);
-
- &external_label("other");
-
- $tmp1= "eax";
- $j= "edi";
- $data= "esi";
- $i= "ebp";
-
- &comment("a simple function");
- &function_begin("calc");
- &mov( $data, &wparam(1)); # data
- &xor( $j, $j);
- &xor( $i, $i);
-
- &set_label("loop");
- &cmp( $i, &wparam(0));
- &jge( &label("end"));
-
- &mov( $tmp1, &DWP(0,$data,$i,4));
- &push( $tmp1);
- &call( "other");
- &add( $j, "eax");
- &pop( $tmp1);
- &inc( $i);
- &jmp( &label("loop"));
-
- &set_label("end");
- &mov( "eax", $j);
-
- &function_end("calc");
-
- &asm_finish();
-
-The above example is very very unoptimised but gives an idea of how
-things work.
-
-There is also a cbc mode function generator in cbc.pl
-
-&cbc( $name,
- $encrypt_function_name,
- $decrypt_function_name,
- $true_if_byte_swap_needed,
- $parameter_number_for_iv,
- $parameter_number_for_encrypt_flag,
- $first_parameter_to_pass,
- $second_parameter_to_pass,
- $third_parameter_to_pass);
-
-So for example, given
-void BF_encrypt(BF_LONG *data,BF_KEY *key);
-void BF_decrypt(BF_LONG *data,BF_KEY *key);
-void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length,
- BF_KEY *ks, unsigned char *iv, int enc);
-
-&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",1,4,5,3,-1,-1);
-
-&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1);
-&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5);
-
diff --git a/crypto/perlasm/README.md b/crypto/perlasm/README.md
new file mode 100644
index 000000000000..912dac7f0736
--- /dev/null
+++ b/crypto/perlasm/README.md
@@ -0,0 +1,130 @@
+Perl scripts for assembler sources
+==================================
+
+The perl scripts in this directory are my 'hack' to generate
+multiple different assembler formats via the one original script.
+
+The way to use this library is to start with adding the path to this directory
+and then include it.
+
+ push(@INC,"perlasm","../../perlasm");
+ require "x86asm.pl";
+
+The first thing we do is setup the file and type of assembler
+
+ &asm_init($ARGV[0]);
+
+The first argument is the 'type'. Currently
+`cpp`, `sol`, `a.out`, `elf` or `win32`.
+The second argument is the file name.
+
+The reciprocal function is
+`&asm_finish()` which should be called at the end.
+
+There are two main 'packages'. `x86ms.pl`, which is the Microsoft assembler,
+and `x86unix.pl` which is the unix (gas) version.
+
+Functions of interest are:
+
+ &external_label("des_SPtrans"); declare and external variable
+ &LB(reg); Low byte for a register
+ &HB(reg); High byte for a register
+ &BP(off,base,index,scale) Byte pointer addressing
+ &DWP(off,base,index,scale) Word pointer addressing
+ &stack_push(num) Basically a 'sub esp, num*4' with extra
+ &stack_pop(num) inverse of stack_push
+ &function_begin(name,extra) Start a function with pushing of
+ edi, esi, ebx and ebp. extra is extra win32
+ external info that may be required.
+ &function_begin_B(name,extra) Same as normal function_begin but no
+ pushing.
+ &function_end(name) Call at end of function.
+ &function_end_A(name) Standard pop and ret, for use inside
+ functions.
+ &function_end_B(name) Call at end but with pop or ret.
+ &swtmp(num) Address on stack temp word.
+ &wparam(num) Parameter number num, that was push in
+ C convention. This all works over pushes
+ and pops.
+ &comment("hello there") Put in a comment.
+ &label("loop") Refer to a label, normally a jmp target.
+ &set_label("loop") Set a label at this point.
+ &data_word(word) Put in a word of data.
+
+So how does this all hold together? Given
+
+ int calc(int len, int *data)
+ {
+ int i,j=0;
+
+ for (i=0; i<len; i++)
+ {
+ j+=other(data[i]);
+ }
+ }
+
+So a very simple version of this function could be coded as
+
+ push(@INC,"perlasm","../../perlasm");
+ require "x86asm.pl";
+
+ &asm_init($ARGV[0]);
+
+ &external_label("other");
+
+ $tmp1= "eax";
+ $j= "edi";
+ $data= "esi";
+ $i= "ebp";
+
+ &comment("a simple function");
+ &function_begin("calc");
+ &mov( $data, &wparam(1)); # data
+ &xor( $j, $j);
+ &xor( $i, $i);
+
+ &set_label("loop");
+ &cmp( $i, &wparam(0));
+ &jge( &label("end"));
+
+ &mov( $tmp1, &DWP(0,$data,$i,4));
+ &push( $tmp1);
+ &call( "other");
+ &add( $j, "eax");
+ &pop( $tmp1);
+ &inc( $i);
+ &jmp( &label("loop"));
+
+ &set_label("end");
+ &mov( "eax", $j);
+
+ &function_end("calc");
+
+ &asm_finish();
+
+The above example is very very unoptimised but gives an idea of how
+things work.
+
+There is also a cbc mode function generator in cbc.pl
+
+ &cbc($name,
+ $encrypt_function_name,
+ $decrypt_function_name,
+ $true_if_byte_swap_needed,
+ $parameter_number_for_iv,
+ $parameter_number_for_encrypt_flag,
+ $first_parameter_to_pass,
+ $second_parameter_to_pass,
+ $third_parameter_to_pass);
+
+So for example, given
+
+ void BF_encrypt(BF_LONG *data,BF_KEY *key);
+ void BF_decrypt(BF_LONG *data,BF_KEY *key);
+ void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length,
+ BF_KEY *ks, unsigned char *iv, int enc);
+
+ &cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",1,4,5,3,-1,-1);
+
+ &cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1);
+ &cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5);
diff --git a/crypto/perlasm/arm-xlate.pl b/crypto/perlasm/arm-xlate.pl
index 48819be54052..a90885905c0f 100755
--- a/crypto/perlasm/arm-xlate.pl
+++ b/crypto/perlasm/arm-xlate.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -28,6 +28,13 @@ my $fpu = sub {
if ($flavour =~ /linux/) { ".fpu\t".join(',',@_); }
else { ""; }
};
+my $rodata = sub {
+ SWITCH: for ($flavour) {
+ /linux/ && return ".section\t.rodata";
+ /ios/ && return ".section\t__TEXT,__const";
+ last;
+ }
+};
my $hidden = sub {
if ($flavour =~ /ios/) { ".private_extern\t".join(',',@_); }
else { ".hidden\t".join(',',@_); }
@@ -96,6 +103,12 @@ my $asciz = sub {
{ ""; }
};
+my $adrp = sub {
+ my ($args,$comment) = split(m|\s*//|,shift);
+ "\tadrp\t$args\@PAGE";
+} if ($flavour =~ /ios64/);
+
+
sub range {
my ($r,$sfx,$start,$end) = @_;
@@ -125,6 +138,10 @@ sub expand_line {
$line =~ s/\b(\w+)/$GLOBALS{$1} or $1/ge;
+ if ($flavour =~ /ios64/) {
+ $line =~ s/#:lo12:(\w+)/$1\@PAGEOFF/;
+ }
+
return $line;
}
@@ -133,7 +150,7 @@ while(my $line=<>) {
if ($line =~ m/^\s*(#|@|\/\/)/) { print $line; next; }
$line =~ s|/\*.*\*/||; # get rid of C-style comments...
- $line =~ s|^\s+||; # ... and skip white spaces in beginning...
+ $line =~ s|^\s+||; # ... and skip whitespace in beginning...
$line =~ s|\s+$||; # ... and at the end
{
diff --git a/crypto/perlasm/cbc.pl b/crypto/perlasm/cbc.pl
index 01bafe457d68..ef09e0fd297a 100644
--- a/crypto/perlasm/cbc.pl
+++ b/crypto/perlasm/cbc.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -165,21 +165,28 @@ sub cbc
&jmp_ptr($count);
&set_label("ej7");
+ &endbranch()
&movb(&HB("edx"), &BP(6,$in,"",0));
&shl("edx",8);
&set_label("ej6");
+ &endbranch()
&movb(&HB("edx"), &BP(5,$in,"",0));
&set_label("ej5");
+ &endbranch()
&movb(&LB("edx"), &BP(4,$in,"",0));
&set_label("ej4");
+ &endbranch()
&mov("ecx", &DWP(0,$in,"",0));
&jmp(&label("ejend"));
&set_label("ej3");
+ &endbranch()
&movb(&HB("ecx"), &BP(2,$in,"",0));
&shl("ecx",8);
&set_label("ej2");
+ &endbranch()
&movb(&HB("ecx"), &BP(1,$in,"",0));
&set_label("ej1");
+ &endbranch()
&movb(&LB("ecx"), &BP(0,$in,"",0));
&set_label("ejend");
diff --git a/crypto/perlasm/ppc-xlate.pl b/crypto/perlasm/ppc-xlate.pl
index 08668b295bf6..2ee444045ff9 100755
--- a/crypto/perlasm/ppc-xlate.pl
+++ b/crypto/perlasm/ppc-xlate.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -49,7 +49,7 @@ my $globl = sub {
/osx/ && do { $name = "_$name";
last;
};
- /linux.*(32|64le)/
+ /linux.*(32|64(le|v2))/
&& do { $ret .= ".globl $name";
if (!$$type) {
$ret .= "\n.type $name,\@function";
@@ -80,7 +80,11 @@ my $globl = sub {
};
my $text = sub {
my $ret = ($flavour =~ /aix/) ? ".csect\t.text[PR],7" : ".text";
- $ret = ".abiversion 2\n".$ret if ($flavour =~ /linux.*64le/);
+ $ret = ".abiversion 2\n".$ret if ($flavour =~ /linux.*64(le|v2)/);
+ $ret;
+};
+my $p2align = sub {
+ my $ret = ($flavour =~ /aix64-as/) ? "" : ".p2align $line";
$ret;
};
my $machine = sub {
@@ -136,6 +140,72 @@ my $quad = sub {
};
################################################################
+# vector register number hacking
+################################################################
+
+# It is convenient to be able to set a variable like:
+# my $foo = "v33";
+# and use this in different contexts where:
+# * a VSR (Vector-Scaler Register) number (i.e. "v33") is required
+# * a VR (Vector Register) number (i.e. "v1") is required
+# Map VSR numbering to VR number for certain vector instructions.
+
+# vs<N> -> v<N-32> if N > 32
+sub vsr2vr1 {
+ my $in = shift;
+ my ($prefix, $reg) = ($in =~ m/(\D*)(\d+)/);
+
+ my $n = int($reg);
+ if ($n >= 32) {
+ $n -= 32;
+ }
+
+ return "${prefix}${n}";
+}
+# As above for first $num register args, returns list
+sub _vsr2vr {
+ my $num = shift;
+ my @rest = @_;
+ my @subst = splice(@rest, 0, $num);
+
+ @subst = map { vsr2vr1($_); } @subst;
+
+ return (@subst, @rest);
+}
+# As above but 1st arg ($f) is extracted and reinserted after
+# processing so that it can be ignored by a code generation function
+# that consumes the result
+sub vsr2vr_args {
+ my $num = shift;
+ my $f = shift;
+
+ my @out = _vsr2vr($num, @_);
+
+ return ($f, @out);
+}
+# As above but 1st arg is mnemonic, return formatted instruction
+sub vsr2vr {
+ my $mnemonic = shift;
+ my $num = shift;
+ my $f = shift;
+
+ my @out = _vsr2vr($num, @_);
+
+ " ${mnemonic}${f} " . join(",", @out);
+}
+
+# ISA 2.03
+my $vsel = sub { vsr2vr("vsel", 4, @_); };
+my $vsl = sub { vsr2vr("vsl", 3, @_); };
+my $vspltisb = sub { vsr2vr("vspltisb", 1, @_); };
+my $vspltisw = sub { vsr2vr("vspltisw", 1, @_); };
+my $vsr = sub { vsr2vr("vsr", 3, @_); };
+my $vsro = sub { vsr2vr("vsro", 3, @_); };
+
+# ISA 3.0
+my $lxsd = sub { vsr2vr("lxsd", 1, @_); };
+
+################################################################
# simplified mnemonics not handled by at least one assembler
################################################################
my $cmplw = sub {
@@ -186,7 +256,7 @@ my $vmr = sub {
# Some ABIs specify vrsave, special-purpose register #256, as reserved
# for system use.
-my $no_vrsave = ($flavour =~ /aix|linux64le/);
+my $no_vrsave = ($flavour =~ /aix|linux64(le|v2)/);
my $mtspr = sub {
my ($f,$idx,$ra) = @_;
if ($idx == 256 && $no_vrsave) {
@@ -226,13 +296,18 @@ my $vpermdi = sub { # xxpermdi
# PowerISA 2.07 stuff
sub vcrypto_op {
- my ($f, $vrt, $vra, $vrb, $op) = @_;
+ my ($f, $vrt, $vra, $vrb, $op) = vsr2vr_args(3, @_);
" .long ".sprintf "0x%X",(4<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|$op;
}
sub vfour {
my ($f, $vrt, $vra, $vrb, $vrc, $op) = @_;
" .long ".sprintf "0x%X",(4<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|($vrc<<6)|$op;
};
+sub vfour_vsr {
+ my ($f, $vrt, $vra, $vrb, $vrc, $op) = vsr2vr_args(4, @_);
+ " .long ".sprintf "0x%X",(4<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|($vrc<<6)|$op;
+};
+
my $vcipher = sub { vcrypto_op(@_, 1288); };
my $vcipherlast = sub { vcrypto_op(@_, 1289); };
my $vncipher = sub { vcrypto_op(@_, 1352); };
@@ -254,10 +329,10 @@ my $vsld = sub { vcrypto_op(@_, 1476); };
my $vsrd = sub { vcrypto_op(@_, 1732); };
my $vsubudm = sub { vcrypto_op(@_, 1216); };
my $vaddcuq = sub { vcrypto_op(@_, 320); };
-my $vaddeuqm = sub { vfour(@_,60); };
-my $vaddecuq = sub { vfour(@_,61); };
-my $vmrgew = sub { vfour(@_,0,1932); };
-my $vmrgow = sub { vfour(@_,0,1676); };
+my $vaddeuqm = sub { vfour_vsr(@_,60); };
+my $vaddecuq = sub { vfour_vsr(@_,61); };
+my $vmrgew = sub { vfour_vsr(@_,0,1932); };
+my $vmrgow = sub { vfour_vsr(@_,0,1676); };
my $mtsle = sub {
my ($f, $arg) = @_;
@@ -273,6 +348,8 @@ my $mtvrwz = sub {
my ($f, $vrt, $ra) = @_;
" .long ".sprintf "0x%X",(31<<26)|($vrt<<21)|($ra<<16)|(243<<1)|1;
};
+my $lvwzx_u = sub { vsxmem_op(@_, 12); }; # lxsiwzx
+my $stvwx_u = sub { vsxmem_op(@_, 140); }; # stxsiwx
# PowerISA 3.0 stuff
my $maddhdu = sub { vfour(@_,49); };
@@ -298,13 +375,13 @@ my $addex = sub {
my ($f, $rt, $ra, $rb, $cy) = @_; # only cy==0 is specified in 3.0B
" .long ".sprintf "0x%X",(31<<26)|($rt<<21)|($ra<<16)|($rb<<11)|($cy<<9)|(170<<1);
};
-my $vmsumudm = sub { vfour(@_,35); };
+my $vmsumudm = sub { vfour_vsr(@_, 35); };
while($line=<>) {
$line =~ s|[#!;].*$||; # get rid of asm-style comments...
$line =~ s|/\*.*\*/||; # ... and C-style comments...
- $line =~ s|^\s+||; # ... and skip white spaces in beginning...
+ $line =~ s|^\s+||; # ... and skip whitespaces in beginning...
$line =~ s|\s+$||; # ... and at the end
{
@@ -318,7 +395,7 @@ while($line=<>) {
if ($label) {
my $xlated = ($GLOBALS{$label} or $label);
print "$xlated:";
- if ($flavour =~ /linux.*64le/) {
+ if ($flavour =~ /linux.*64(le|v2)/) {
if ($TYPES{$label} =~ /function/) {
printf "\n.localentry %s,0\n",$xlated;
}
diff --git a/crypto/perlasm/s390x.pm b/crypto/perlasm/s390x.pm
new file mode 100644
index 000000000000..dbf48426813c
--- /dev/null
+++ b/crypto/perlasm/s390x.pm
@@ -0,0 +1,3175 @@
+#!/usr/bin/env perl
+# Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+# Copyright IBM Corp. 2018-2019
+# Author: Patrick Steuer <patrick.steuer@de.ibm.com>
+
+package perlasm::s390x;
+
+use strict;
+use warnings;
+use bigint;
+use Carp qw(confess);
+use Exporter qw(import);
+
+our @EXPORT=qw(PERLASM_BEGIN PERLASM_END);
+our @EXPORT_OK=qw(AUTOLOAD LABEL INCLUDE stfle stck);
+our %EXPORT_TAGS=(
+ # store-clock-fast facility
+ SCF => [qw(stckf)],
+ # general-instruction-extension facility
+ GE => [qw(risbg)],
+ # extended-immediate facility
+ EI => [qw(clfi clgfi lt)],
+ # miscellaneous-instruction-extensions facility 1
+ MI1 => [qw(risbgn)],
+ # message-security assist
+ MSA => [qw(kmac km kmc kimd klmd)],
+ # message-security-assist extension 4
+ MSA4 => [qw(kmf kmo pcc kmctr)],
+ # message-security-assist extension 5
+ MSA5 => [qw(ppno prno)],
+ # message-security-assist extension 8
+ MSA8 => [qw(kma)],
+ # message-security-assist extension 9
+ MSA9 => [qw(kdsa)],
+ # vector facility
+ VX => [qw(vgef vgeg vgbm vzero vone vgm vgmb vgmh vgmf vgmg
+ vl vlr vlrep vlrepb vlreph vlrepf vlrepg vleb vleh vlef vleg vleib
+ vleih vleif vleig vlgv vlgvb vlgvh vlgvf vlgvg vllez vllezb vllezh
+ vllezf vllezg vlm vlbb vlvg vlvgb vlvgh vlvgf vlvgg vlvgp
+ vll vmrh vmrhb vmrhh vmrhf vmrhg vmrl vmrlb vmrlh vmrlf vmrlg vpk
+ vpkh vpkf vpkg vpks vpksh vpksf vpksg vpkshs vpksfs vpksgs vpkls
+ vpklsh vpklsf vpklsg vpklshs vpklsfs vpklsgs vperm vpdi vrep vrepb
+ vreph vrepf vrepg vrepi vrepib vrepih vrepif vrepig vscef vsceg
+ vsel vseg vsegb vsegh vsegf vst vsteb vsteh vstef vsteg vstm vstl
+ vuph vuphb vuphh vuphf vuplh vuplhb vuplhh vuplhf vupl vuplb vuplhw
+ vuplf vupll vupllb vupllh vupllf va vab vah vaf vag vaq vacc vaccb
+ vacch vaccf vaccg vaccq vac vacq vaccc vacccq vn vnc vavg vavgb
+ vavgh vavgf vavgg vavgl vavglb vavglh vavglf vavglg vcksm vec_ vecb
+ vech vecf vecg vecl veclb veclh veclf veclg vceq vceqb vceqh vceqf
+ vceqg vceqbs vceqhs vceqfs vceqgs vch vchb vchh vchf vchg vchbs
+ vchhs vchfs vchgs vchl vchlb vchlh vchlf vchlg vchlbs vchlhs vchlfs
+ vchlgs vclz vclzb vclzh vclzf vclzg vctz vctzb vctzh vctzf vctzg
+ vx vgfm vgfmb vgfmh vgfmf vgfmg vgfma vgfmab vgfmah vgfmaf vgfmag
+ vlc vlcb vlch vlcf vlcg vlp vlpb vlph vlpf vlpg vmx vmxb vmxh vmxf
+ vmxg vmxl vmxlb vmxlh vmxlf vmxlg vmn vmnb vmnh vmnf vmng vmnl
+ vmnlb vmnlh vmnlf vmnlg vmal vmalb vmalhw vmalf vmah vmahb vmahh
+ vmahf vmalh vmalhb vmalhh vmalhf vmae vmaeb vmaeh vmaef vmale
+ vmaleb vmaleh vmalef vmao vmaob vmaoh vmaof vmalo vmalob vmaloh
+ vmalof vmh vmhb vmhh vmhf vmlh vmlhb vmlhh vmlhf vml vmlb vmlhw
+ vmlf vme vmeb vmeh vmef vmle vmleb vmleh vmlef vmo vmob vmoh vmof
+ vmlo vmlob vmloh vmlof vno vnot vo vpopct verllv verllvb verllvh
+ verllvf verllvg verll verllb verllh verllf verllg verim verimb
+ verimh verimf verimg veslv veslvb veslvh veslvf veslvg vesl veslb
+ veslh veslf veslg vesrav vesravb vesravh vesravf vesravg vesra
+ vesrab vesrah vesraf vesrag vesrlv vesrlvb vesrlvh vesrlvf vesrlvg
+ vesrl vesrlb vesrlh vesrlf vesrlg vsl vslb vsldb vsra vsrab vsrl
+ vsrlb vs vsb vsh vsf vsg vsq vscbi vscbib vscbih vscbif vscbig
+ vscbiq vsbi vsbiq vsbcbi vsbcbiq vsumg vsumgh vsumgf vsumq vsumqf
+ vsumqg vsum vsumb vsumh vtm vfae vfaeb vfaeh vfaef vfaebs vfaehs
+ vfaefs vfaezb vfaezh vfaezf vfaezbs vfaezhs vfaezfs vfee vfeeb
+ vfeeh vfeef vfeebs vfeehs vfeefs vfeezb vfeezh vfeezf vfeezbs
+ vfeezhs vfeezfs vfene vfeneb vfeneh vfenef vfenebs vfenehs vfenefs
+ vfenezb vfenezh vfenezf vfenezbs vfenezhs vfenezfs vistr vistrb
+ vistrh vistrf vistrbs vistrhs vistrfs vstrc vstrcb vstrch vstrcf
+ vstrcbs vstrchs vstrcfs vstrczb vstrczh vstrczf vstrczbs vstrczhs
+ vstrczfs vfa vfadb wfadb wfc wfcdb wfk wfkdb vfce vfcedb wfcedb
+ vfcedbs wfcedbs vfch vfchdb wfchdb vfchdbs wfchdbs vfche vfchedb
+ wfchedb vfchedbs wfchedbs vcdg vcdgb wcdgb vcdlg vcdlgb wcdlgb vcgd
+ vcgdb wcgdb vclgd vclgdb wclgdb vfd vfddb wfddb vfi vfidb wfidb
+ vlde vldeb wldeb vled vledb wledb vfm vfmdb wfmdb vfma vfmadb
+ wfmadb vfms vfmsdb wfmsdb vfpso vfpsodb wfpsodb vflcdb wflcdb
+ vflndb wflndb vflpdb wflpdb vfsq vfsqdb wfsqdb vfs vfsdb wfsdb
+ vftci vftcidb wftcidb)],
+ # vector-enhancements facility 1
+ VXE => [qw(vbperm vllezlf vmsl vmslg vnx vnn voc vpopctb vpopcth
+ vpopctf vpopctg vfasb wfasb wfaxb wfcsb wfcxb wfksb wfkxb vfcesb
+ vfcesbs wfcesb wfcesbs wfcexb wfcexbs vfchsb vfchsbs wfchsb wfchsbs
+ wfchxb wfchxbs vfchesb vfchesbs wfchesb wfchesbs wfchexb wfchexbs
+ vfdsb wfdsb wfdxb vfisb wfisb wfixb vfll vflls wflls wflld vflr
+ vflrd wflrd wflrx vfmax vfmaxsb vfmaxdb wfmaxsb wfmaxdb wfmaxxb
+ vfmin vfminsb vfmindb wfminsb wfmindb wfminxb vfmsb wfmsb wfmxb
+ vfnma vfnms vfmasb wfmasb wfmaxb vfmssb wfmssb wfmsxb vfnmasb
+ vfnmadb wfnmasb wfnmadb wfnmaxb vfnmssb vfnmsdb wfnmssb wfnmsdb
+ wfnmsxb vfpsosb wfpsosb vflcsb wflcsb vflnsb wflnsb vflpsb wflpsb
+ vfpsoxb wfpsoxb vflcxb wflcxb vflnxb wflnxb vflpxb wflpxb vfsqsb
+ wfsqsb wfsqxb vfssb wfssb wfsxb vftcisb wftcisb wftcixb)],
+ # vector-packed-decimal facility
+ VXD => [qw(vlrlr vlrl vstrlr vstrl vap vcp vcvb vcvbg vcvd vcvdg vdp
+ vlip vmp vmsp vpkz vpsop vrp vsdp vsrp vsp vtp vupkz)],
+);
+Exporter::export_ok_tags(qw(SCF GE EI MI1 MSA MSA4 MSA5 MSA8 MSA9 VX VXE VXD));
+
+our $AUTOLOAD;
+
+my $GR='(?:%r)?([0-9]|1[0-5])';
+my $VR='(?:%v)?([0-9]|1[0-9]|2[0-9]|3[0-1])';
+
+my ($file,$out);
+
+sub PERLASM_BEGIN
+{
+ ($file,$out)=(shift,"");
+}
+sub PERLASM_END
+{
+ if (defined($file)) {
+ open(my $fd,'>',$file)||die("can't open $file: $!");
+ print({$fd}$out);
+ close($fd);
+ } else {
+ print($out);
+ }
+}
+
+sub AUTOLOAD {
+ confess(err("PARSE")) if (grep(!defined($_),@_));
+ my $token;
+ for ($AUTOLOAD) {
+ $token=lc(".$1") if (/^.*::([A-Z_]+)$/);# uppercase: directive
+ $token="\t$1" if (/^.*::([a-z]+)$/); # lowercase: mnemonic
+ confess(err("PARSE")) if (!defined($token));
+ }
+ $token.="\t" if ($#_>=0);
+ $out.=$token.join(',',@_)."\n";
+}
+
+sub LABEL { # label directive
+ confess(err("ARGNUM")) if ($#_!=0);
+ my ($label)=@_;
+ $out.="$label:\n";
+}
+
+sub INCLUDE {
+ confess(err("ARGNUM")) if ($#_!=0);
+ my ($file)=@_;
+ $out.="#include \"$file\"\n";
+}
+
+#
+# Mnemonics
+#
+
+sub stfle {
+ confess(err("ARGNUM")) if ($#_!=0);
+ S(0xb2b0,@_);
+}
+
+sub stck {
+ confess(err("ARGNUM")) if ($#_!=0);
+ S(0xb205,@_);
+}
+
+# store-clock-fast facility
+
+sub stckf {
+ confess(err("ARGNUM")) if ($#_!=0);
+ S(0xb27c,@_);
+}
+
+# extended-immediate facility
+
+sub clfi {
+ confess(err("ARGNUM")) if ($#_!=1);
+ RILa(0xc2f,@_);
+}
+
+sub clgfi {
+ confess(err("ARGNUM")) if ($#_!=1);
+ RILa(0xc2e,@_);
+}
+
+sub lt {
+ confess(err("ARGNUM")) if ($#_!=1);
+ RXYa(0xe312,@_);
+}
+
+# general-instruction-extension facility
+
+sub risbg {
+ confess(err("ARGNUM")) if ($#_<3||$#_>4);
+ RIEf(0xec55,@_);
+}
+
+# miscellaneous-instruction-extensions facility 1
+
+sub risbgn {
+ confess(err("ARGNUM")) if ($#_<3||$#_>4);
+ RIEf(0xec59,@_);
+}
+
+# MSA
+
+sub kmac {
+ confess(err("ARGNUM")) if ($#_!=1);
+ RRE(0xb91e,@_);
+}
+
+sub km {
+ confess(err("ARGNUM")) if ($#_!=1);
+ RRE(0xb92e,@_);
+}
+
+sub kmc {
+ confess(err("ARGNUM")) if ($#_!=1);
+ RRE(0xb92f,@_);
+}
+
+sub kimd {
+ confess(err("ARGNUM")) if ($#_!=1);
+ RRE(0xb93e,@_);
+}
+
+sub klmd {
+ confess(err("ARGNUM")) if ($#_!=1);
+ RRE(0xb93f,@_);
+}
+
+# MSA4
+
+sub kmf {
+ confess(err("ARGNUM")) if ($#_!=1);
+ RRE(0xb92a,@_);
+}
+
+sub kmo {
+ confess(err("ARGNUM")) if ($#_!=1);
+ RRE(0xb92b,@_);
+}
+
+sub pcc {
+ confess(err("ARGNUM")) if ($#_!=-1);
+ RRE(0xb92c,@_);
+}
+
+sub kmctr {
+ confess(err("ARGNUM")) if ($#_!=2);
+ RRFb(0xb92d,@_);
+}
+
+# MSA5
+
+sub prno {
+ ppno(@_);
+}
+
+sub ppno { # deprecated, use prno
+ confess(err("ARGNUM")) if ($#_!=1);
+ RRE(0xb93c,@_);
+}
+
+# MSA8
+
+sub kma {
+ confess(err("ARGNUM")) if ($#_!=2);
+ RRFb(0xb929,@_);
+}
+
+# MSA9
+
+sub kdsa {
+ confess(err("ARGNUM")) if ($#_!=1);
+ RRE(0xb93a,@_);
+}
+
+# VX - Support Instructions
+
+sub vgef {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRV(0xe713,@_);
+}
+sub vgeg {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRV(0xe712,@_);
+}
+
+sub vgbm {
+ confess(err("ARGNUM")) if ($#_!=1);
+ VRIa(0xe744,@_);
+}
+sub vzero {
+ vgbm(@_,0);
+}
+sub vone {
+ vgbm(@_,0xffff);
+}
+
+sub vgm {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRIb(0xe746,@_);
+}
+sub vgmb {
+ vgm(@_,0);
+}
+sub vgmh {
+ vgm(@_,1);
+}
+sub vgmf {
+ vgm(@_,2);
+}
+sub vgmg {
+ vgm(@_,3);
+}
+
+sub vl {
+ confess(err("ARGNUM")) if ($#_<1||$#_>2);
+ VRX(0xe706,@_);
+}
+
+sub vlr {
+ confess(err("ARGNUM")) if ($#_!=1);
+ VRRa(0xe756,@_);
+}
+
+sub vlrep {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRX(0xe705,@_);
+}
+sub vlrepb {
+ vlrep(@_,0);
+}
+sub vlreph {
+ vlrep(@_,1);
+}
+sub vlrepf {
+ vlrep(@_,2);
+}
+sub vlrepg {
+ vlrep(@_,3);
+}
+
+sub vleb {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRX(0xe700,@_);
+}
+sub vleh {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRX(0xe701,@_);
+}
+sub vlef {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRX(0xe703,@_);
+}
+sub vleg {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRX(0xe702,@_);
+}
+
+sub vleib {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRIa(0xe740,@_);
+}
+sub vleih {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRIa(0xe741,@_);
+}
+sub vleif {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRIa(0xe743,@_);
+}
+sub vleig {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRIa(0xe742,@_);
+}
+
+sub vlgv {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRSc(0xe721,@_);
+}
+sub vlgvb {
+ vlgv(@_,0);
+}
+sub vlgvh {
+ vlgv(@_,1);
+}
+sub vlgvf {
+ vlgv(@_,2);
+}
+sub vlgvg {
+ vlgv(@_,3);
+}
+
+sub vllez {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRX(0xe704,@_);
+}
+sub vllezb {
+ vllez(@_,0);
+}
+sub vllezh {
+ vllez(@_,1);
+}
+sub vllezf {
+ vllez(@_,2);
+}
+sub vllezg {
+ vllez(@_,3);
+}
+
+sub vlm {
+ confess(err("ARGNUM")) if ($#_<2||$#_>3);
+ VRSa(0xe736,@_);
+}
+
+sub vlbb {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRX(0xe707,@_);
+}
+
+sub vlvg {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRSb(0xe722,@_);
+}
+sub vlvgb {
+ vlvg(@_,0);
+}
+sub vlvgh {
+ vlvg(@_,1);
+}
+sub vlvgf {
+ vlvg(@_,2);
+}
+sub vlvgg {
+ vlvg(@_,3);
+}
+
+sub vlvgp {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRf(0xe762,@_);
+}
+
+sub vll {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRSb(0xe737,@_);
+}
+
+sub vmrh {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe761,@_);
+}
+sub vmrhb {
+ vmrh(@_,0);
+}
+sub vmrhh {
+ vmrh(@_,1);
+}
+sub vmrhf {
+ vmrh(@_,2);
+}
+sub vmrhg {
+ vmrh(@_,3);
+}
+
+sub vmrl {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe760,@_);
+}
+sub vmrlb {
+ vmrl(@_,0);
+}
+sub vmrlh {
+ vmrl(@_,1);
+}
+sub vmrlf {
+ vmrl(@_,2);
+}
+sub vmrlg {
+ vmrl(@_,3);
+}
+
+sub vpk {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe794,@_);
+}
+sub vpkh {
+ vpk(@_,1);
+}
+sub vpkf {
+ vpk(@_,2);
+}
+sub vpkg {
+ vpk(@_,3);
+}
+
+sub vpks {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRb(0xe797,@_);
+}
+sub vpksh {
+ vpks(@_,1,0);
+}
+sub vpksf {
+ vpks(@_,2,0);
+}
+sub vpksg {
+ vpks(@_,3,0);
+}
+sub vpkshs {
+ vpks(@_,1,1);
+}
+sub vpksfs {
+ vpks(@_,2,1);
+}
+sub vpksgs {
+ vpks(@_,3,1);
+}
+
+sub vpkls {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRb(0xe795,@_);
+}
+sub vpklsh {
+ vpkls(@_,1,0);
+}
+sub vpklsf {
+ vpkls(@_,2,0);
+}
+sub vpklsg {
+ vpkls(@_,3,0);
+}
+sub vpklshs {
+ vpkls(@_,1,1);
+}
+sub vpklsfs {
+ vpkls(@_,2,1);
+}
+sub vpklsgs {
+ vpkls(@_,3,1);
+}
+
+sub vperm {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRe(0xe78c,@_);
+}
+
+sub vpdi {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe784,@_);
+}
+
+sub vrep {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRIc(0xe74d,@_);
+}
+sub vrepb {
+ vrep(@_,0);
+}
+sub vreph {
+ vrep(@_,1);
+}
+sub vrepf {
+ vrep(@_,2);
+}
+sub vrepg {
+ vrep(@_,3);
+}
+
+sub vrepi {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRIa(0xe745,@_);
+}
+sub vrepib {
+ vrepi(@_,0);
+}
+sub vrepih {
+ vrepi(@_,1);
+}
+sub vrepif {
+ vrepi(@_,2);
+}
+sub vrepig {
+ vrepi(@_,3);
+}
+
+sub vscef {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRV(0xe71b,@_);
+}
+sub vsceg {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRV(0xe71a,@_);
+}
+
+sub vsel {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRe(0xe78d,@_);
+}
+
+sub vseg {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRa(0xe75f,@_);
+}
+sub vsegb {
+ vseg(@_,0);
+}
+sub vsegh {
+ vseg(@_,1);
+}
+sub vsegf {
+ vseg(@_,2);
+}
+
+sub vst {
+ confess(err("ARGNUM")) if ($#_<1||$#_>2);
+ VRX(0xe70e,@_);
+}
+
+sub vsteb {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRX(0xe708,@_);
+}
+sub vsteh {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRX(0xe709,@_);
+}
+sub vstef {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRX(0xe70b,@_);
+}
+sub vsteg {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRX(0xe70a,@_);
+}
+
+sub vstm {
+ confess(err("ARGNUM")) if ($#_<2||$#_>3);
+ VRSa(0xe73e,@_);
+}
+
+sub vstl {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRSb(0xe73f,@_);
+}
+
+sub vuph {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRa(0xe7d7,@_);
+}
+sub vuphb {
+ vuph(@_,0);
+}
+sub vuphh {
+ vuph(@_,1);
+}
+sub vuphf {
+ vuph(@_,2);
+}
+
+sub vuplh {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRa(0xe7d5,@_);
+}
+sub vuplhb {
+ vuplh(@_,0);
+}
+sub vuplhh {
+ vuplh(@_,1);
+}
+sub vuplhf {
+ vuplh(@_,2);
+}
+
+sub vupl {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRa(0xe7d6,@_);
+}
+sub vuplb {
+ vupl(@_,0);
+}
+sub vuplhw {
+ vupl(@_,1);
+}
+sub vuplf {
+ vupl(@_,2);
+}
+
+sub vupll {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRa(0xe7d4,@_);
+}
+sub vupllb {
+ vupll(@_,0);
+}
+sub vupllh {
+ vupll(@_,1);
+}
+sub vupllf {
+ vupll(@_,2);
+}
+
+# VX - Integer Instructions
+
+sub va {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7f3,@_);
+}
+sub vab {
+ va(@_,0);
+}
+sub vah {
+ va(@_,1);
+}
+sub vaf {
+ va(@_,2);
+}
+sub vag {
+ va(@_,3);
+}
+sub vaq {
+ va(@_,4);
+}
+
+sub vacc {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7f1,@_);
+}
+sub vaccb {
+ vacc(@_,0);
+}
+sub vacch {
+ vacc(@_,1);
+}
+sub vaccf {
+ vacc(@_,2);
+}
+sub vaccg {
+ vacc(@_,3);
+}
+sub vaccq {
+ vacc(@_,4);
+}
+
+sub vac {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRd(0xe7bb,@_);
+}
+sub vacq {
+ vac(@_,4);
+}
+
+sub vaccc {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRd(0xe7b9,@_);
+}
+sub vacccq {
+ vaccc(@_,4);
+}
+
+sub vn {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRc(0xe768,@_);
+}
+
+sub vnc {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRc(0xe769,@_);
+}
+
+sub vavg {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7f2,@_);
+}
+sub vavgb {
+ vavg(@_,0);
+}
+sub vavgh {
+ vavg(@_,1);
+}
+sub vavgf {
+ vavg(@_,2);
+}
+sub vavgg {
+ vavg(@_,3);
+}
+
+sub vavgl {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7f0,@_);
+}
+sub vavglb {
+ vavgl(@_,0);
+}
+sub vavglh {
+ vavgl(@_,1);
+}
+sub vavglf {
+ vavgl(@_,2);
+}
+sub vavglg {
+ vavgl(@_,3);
+}
+
+sub vcksm {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRc(0xe766,@_);
+}
+
+sub vec_ {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRa(0xe7db,@_);
+}
+sub vecb {
+ vec_(@_,0);
+}
+sub vech {
+ vec_(@_,1);
+}
+sub vecf {
+ vec_(@_,2);
+}
+sub vecg {
+ vec_(@_,3);
+}
+
+sub vecl {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRa(0xe7d9,@_);
+}
+sub veclb {
+ vecl(@_,0);
+}
+sub veclh {
+ vecl(@_,1);
+}
+sub veclf {
+ vecl(@_,2);
+}
+sub veclg {
+ vecl(@_,3);
+}
+
+sub vceq {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRb(0xe7f8,@_);
+}
+sub vceqb {
+ vceq(@_,0,0);
+}
+sub vceqh {
+ vceq(@_,1,0);
+}
+sub vceqf {
+ vceq(@_,2,0);
+}
+sub vceqg {
+ vceq(@_,3,0);
+}
+sub vceqbs {
+ vceq(@_,0,1);
+}
+sub vceqhs {
+ vceq(@_,1,1);
+}
+sub vceqfs {
+ vceq(@_,2,1);
+}
+sub vceqgs {
+ vceq(@_,3,1);
+}
+
+sub vch {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRb(0xe7fb,@_);
+}
+sub vchb {
+ vch(@_,0,0);
+}
+sub vchh {
+ vch(@_,1,0);
+}
+sub vchf {
+ vch(@_,2,0);
+}
+sub vchg {
+ vch(@_,3,0);
+}
+sub vchbs {
+ vch(@_,0,1);
+}
+sub vchhs {
+ vch(@_,1,1);
+}
+sub vchfs {
+ vch(@_,2,1);
+}
+sub vchgs {
+ vch(@_,3,1);
+}
+
+sub vchl {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRb(0xe7f9,@_);
+}
+sub vchlb {
+ vchl(@_,0,0);
+}
+sub vchlh {
+ vchl(@_,1,0);
+}
+sub vchlf {
+ vchl(@_,2,0);
+}
+sub vchlg {
+ vchl(@_,3,0);
+}
+sub vchlbs {
+ vchl(@_,0,1);
+}
+sub vchlhs {
+ vchl(@_,1,1);
+}
+sub vchlfs {
+ vchl(@_,2,1);
+}
+sub vchlgs {
+ vchl(@_,3,1);
+}
+
+sub vclz {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRa(0xe753,@_);
+}
+sub vclzb {
+ vclz(@_,0);
+}
+sub vclzh {
+ vclz(@_,1);
+}
+sub vclzf {
+ vclz(@_,2);
+}
+sub vclzg {
+ vclz(@_,3);
+}
+
+sub vctz {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRa(0xe752,@_);
+}
+sub vctzb {
+ vctz(@_,0);
+}
+sub vctzh {
+ vctz(@_,1);
+}
+sub vctzf {
+ vctz(@_,2);
+}
+sub vctzg {
+ vctz(@_,3);
+}
+
+sub vx {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRc(0xe76d,@_);
+}
+
+sub vgfm {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7b4,@_);
+}
+sub vgfmb {
+ vgfm(@_,0);
+}
+sub vgfmh {
+ vgfm(@_,1);
+}
+sub vgfmf {
+ vgfm(@_,2);
+}
+sub vgfmg {
+ vgfm(@_,3);
+}
+
+sub vgfma {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRd(0xe7bc,@_);
+}
+sub vgfmab {
+ vgfma(@_,0);
+}
+sub vgfmah {
+ vgfma(@_,1);
+}
+sub vgfmaf {
+ vgfma(@_,2);
+}
+sub vgfmag {
+ vgfma(@_,3);
+}
+
+sub vlc {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRa(0xe7de,@_);
+}
+sub vlcb {
+ vlc(@_,0);
+}
+sub vlch {
+ vlc(@_,1);
+}
+sub vlcf {
+ vlc(@_,2);
+}
+sub vlcg {
+ vlc(@_,3);
+}
+
+sub vlp {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRa(0xe7df,@_);
+}
+sub vlpb {
+ vlp(@_,0);
+}
+sub vlph {
+ vlp(@_,1);
+}
+sub vlpf {
+ vlp(@_,2);
+}
+sub vlpg {
+ vlp(@_,3);
+}
+
+sub vmx {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7ff,@_);
+}
+sub vmxb {
+ vmx(@_,0);
+}
+sub vmxh {
+ vmx(@_,1);
+}
+sub vmxf {
+ vmx(@_,2);
+}
+sub vmxg {
+ vmx(@_,3);
+}
+
+sub vmxl {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7fd,@_);
+}
+sub vmxlb {
+ vmxl(@_,0);
+}
+sub vmxlh {
+ vmxl(@_,1);
+}
+sub vmxlf {
+ vmxl(@_,2);
+}
+sub vmxlg {
+ vmxl(@_,3);
+}
+
+sub vmn {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7fe,@_);
+}
+sub vmnb {
+ vmn(@_,0);
+}
+sub vmnh {
+ vmn(@_,1);
+}
+sub vmnf {
+ vmn(@_,2);
+}
+sub vmng {
+ vmn(@_,3);
+}
+
+sub vmnl {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7fc,@_);
+}
+sub vmnlb {
+ vmnl(@_,0);
+}
+sub vmnlh {
+ vmnl(@_,1);
+}
+sub vmnlf {
+ vmnl(@_,2);
+}
+sub vmnlg {
+ vmnl(@_,3);
+}
+
+sub vmal {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRd(0xe7aa,@_);
+}
+sub vmalb {
+ vmal(@_,0);
+}
+sub vmalhw {
+ vmal(@_,1);
+}
+sub vmalf {
+ vmal(@_,2);
+}
+
+sub vmah {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRd(0xe7ab,@_);
+}
+sub vmahb {
+ vmah(@_,0);
+}
+sub vmahh {
+ vmah(@_,1);
+}
+sub vmahf {
+ vmah(@_,2);
+}
+
+sub vmalh {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRd(0xe7a9,@_);
+}
+sub vmalhb {
+ vmalh(@_,0);
+}
+sub vmalhh {
+ vmalh(@_,1);
+}
+sub vmalhf {
+ vmalh(@_,2);
+}
+
+sub vmae {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRd(0xe7ae,@_);
+}
+sub vmaeb {
+ vmae(@_,0);
+}
+sub vmaeh {
+ vmae(@_,1);
+}
+sub vmaef {
+ vmae(@_,2);
+}
+
+sub vmale {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRd(0xe7ac,@_);
+}
+sub vmaleb {
+ vmale(@_,0);
+}
+sub vmaleh {
+ vmale(@_,1);
+}
+sub vmalef {
+ vmale(@_,2);
+}
+
+sub vmao {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRd(0xe7af,@_);
+}
+sub vmaob {
+ vmao(@_,0);
+}
+sub vmaoh {
+ vmao(@_,1);
+}
+sub vmaof {
+ vmao(@_,2);
+}
+
+sub vmalo {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRd(0xe7ad,@_);
+}
+sub vmalob {
+ vmalo(@_,0);
+}
+sub vmaloh {
+ vmalo(@_,1);
+}
+sub vmalof {
+ vmalo(@_,2);
+}
+
+sub vmh {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7a3,@_);
+}
+sub vmhb {
+ vmh(@_,0);
+}
+sub vmhh {
+ vmh(@_,1);
+}
+sub vmhf {
+ vmh(@_,2);
+}
+
+sub vmlh {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7a1,@_);
+}
+sub vmlhb {
+ vmlh(@_,0);
+}
+sub vmlhh {
+ vmlh(@_,1);
+}
+sub vmlhf {
+ vmlh(@_,2);
+}
+
+sub vml {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7a2,@_);
+}
+sub vmlb {
+ vml(@_,0);
+}
+sub vmlhw {
+ vml(@_,1);
+}
+sub vmlf {
+ vml(@_,2);
+}
+
+sub vme {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7a6,@_);
+}
+sub vmeb {
+ vme(@_,0);
+}
+sub vmeh {
+ vme(@_,1);
+}
+sub vmef {
+ vme(@_,2);
+}
+
+sub vmle {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7a4,@_);
+}
+sub vmleb {
+ vmle(@_,0);
+}
+sub vmleh {
+ vmle(@_,1);
+}
+sub vmlef {
+ vmle(@_,2);
+}
+
+sub vmo {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7a7,@_);
+}
+sub vmob {
+ vmo(@_,0);
+}
+sub vmoh {
+ vmo(@_,1);
+}
+sub vmof {
+ vmo(@_,2);
+}
+
+sub vmlo {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7a5,@_);
+}
+sub vmlob {
+ vmlo(@_,0);
+}
+sub vmloh {
+ vmlo(@_,1);
+}
+sub vmlof {
+ vmlo(@_,2);
+}
+
+sub vno {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRc(0xe76b,@_);
+}
+sub vnot {
+ vno(@_,$_[1]);
+}
+
+sub vo {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRc(0xe76a,@_);
+}
+
+sub vpopct {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRa(0xe750,@_);
+}
+
+sub verllv {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe773,@_);
+}
+sub verllvb {
+ verllv(@_,0);
+}
+sub verllvh {
+ verllv(@_,1);
+}
+sub verllvf {
+ verllv(@_,2);
+}
+sub verllvg {
+ verllv(@_,3);
+}
+
+sub verll {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRSa(0xe733,@_);
+}
+sub verllb {
+ verll(@_,0);
+}
+sub verllh {
+ verll(@_,1);
+}
+sub verllf {
+ verll(@_,2);
+}
+sub verllg {
+ verll(@_,3);
+}
+
+sub verim {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRId(0xe772,@_);
+}
+sub verimb {
+ verim(@_,0);
+}
+sub verimh {
+ verim(@_,1);
+}
+sub verimf {
+ verim(@_,2);
+}
+sub verimg {
+ verim(@_,3);
+}
+
+sub veslv {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe770,@_);
+}
+sub veslvb {
+ veslv(@_,0);
+}
+sub veslvh {
+ veslv(@_,1);
+}
+sub veslvf {
+ veslv(@_,2);
+}
+sub veslvg {
+ veslv(@_,3);
+}
+
+sub vesl {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRSa(0xe730,@_);
+}
+sub veslb {
+ vesl(@_,0);
+}
+sub veslh {
+ vesl(@_,1);
+}
+sub veslf {
+ vesl(@_,2);
+}
+sub veslg {
+ vesl(@_,3);
+}
+
+sub vesrav {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe77a,@_);
+}
+sub vesravb {
+ vesrav(@_,0);
+}
+sub vesravh {
+ vesrav(@_,1);
+}
+sub vesravf {
+ vesrav(@_,2);
+}
+sub vesravg {
+ vesrav(@_,3);
+}
+
+sub vesra {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRSa(0xe73a,@_);
+}
+sub vesrab {
+ vesra(@_,0);
+}
+sub vesrah {
+ vesra(@_,1);
+}
+sub vesraf {
+ vesra(@_,2);
+}
+sub vesrag {
+ vesra(@_,3);
+}
+
+sub vesrlv {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe778,@_);
+}
+sub vesrlvb {
+ vesrlv(@_,0);
+}
+sub vesrlvh {
+ vesrlv(@_,1);
+}
+sub vesrlvf {
+ vesrlv(@_,2);
+}
+sub vesrlvg {
+ vesrlv(@_,3);
+}
+
+sub vesrl {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRSa(0xe738,@_);
+}
+sub vesrlb {
+ vesrl(@_,0);
+}
+sub vesrlh {
+ vesrl(@_,1);
+}
+sub vesrlf {
+ vesrl(@_,2);
+}
+sub vesrlg {
+ vesrl(@_,3);
+}
+
+sub vsl {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRc(0xe774,@_);
+}
+
+sub vslb {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRc(0xe775,@_);
+}
+
+sub vsldb {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRId(0xe777,@_);
+}
+
+sub vsra {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRc(0xe77e,@_);
+}
+
+sub vsrab {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRc(0xe77f,@_);
+}
+
+sub vsrl {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRc(0xe77c,@_);
+}
+
+sub vsrlb {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRc(0xe77d,@_);
+}
+
+sub vs {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7f7,@_);
+}
+sub vsb {
+ vs(@_,0);
+}
+sub vsh {
+ vs(@_,1);
+}
+sub vsf {
+ vs(@_,2);
+}
+sub vsg {
+ vs(@_,3);
+}
+sub vsq {
+ vs(@_,4);
+}
+
+sub vscbi {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe7f5,@_);
+}
+sub vscbib {
+ vscbi(@_,0);
+}
+sub vscbih {
+ vscbi(@_,1);
+}
+sub vscbif {
+ vscbi(@_,2);
+}
+sub vscbig {
+ vscbi(@_,3);
+}
+sub vscbiq {
+ vscbi(@_,4);
+}
+
+sub vsbi {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRd(0xe7bf,@_);
+}
+sub vsbiq {
+ vsbi(@_,4);
+}
+
+sub vsbcbi {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRd(0xe7bd,@_);
+}
+sub vsbcbiq {
+ vsbcbi(@_,4);
+}
+
+sub vsumg {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe765,@_);
+}
+sub vsumgh {
+ vsumg(@_,1);
+}
+sub vsumgf {
+ vsumg(@_,2);
+}
+
+sub vsumq {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe767,@_);
+}
+sub vsumqf {
+ vsumq(@_,2);
+}
+sub vsumqg {
+ vsumq(@_,3);
+}
+
+sub vsum {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRc(0xe764,@_);
+}
+sub vsumb {
+ vsum(@_,0);
+}
+sub vsumh {
+ vsum(@_,1);
+}
+
+sub vtm {
+ confess(err("ARGNUM")) if ($#_!=1);
+ VRRa(0xe7d8,@_);
+}
+
+# VX - String Instructions
+
+sub vfae {
+ confess(err("ARGNUM")) if ($#_<3||$#_>4);
+ VRRb(0xe782,@_);
+}
+sub vfaeb {
+ vfae(@_[0..2],0,$_[3]);
+}
+sub vfaeh {
+ vfae(@_[0..2],1,$_[3]);
+}
+sub vfaef {
+ vfae(@_[0..2],2,$_[3]);
+}
+sub vfaebs {
+ $_[3]=0 if (!defined($_[3]));
+ vfae(@_[0..2],0,0x1|$_[3]);
+}
+sub vfaehs {
+ $_[3]=0 if (!defined($_[3]));
+ vfae(@_[0..2],1,0x1|$_[3]);
+}
+sub vfaefs {
+ $_[3]=0 if (!defined($_[3]));
+ vfae(@_[0..2],2,0x1|$_[3]);
+}
+sub vfaezb {
+ $_[3]=0 if (!defined($_[3]));
+ vfae(@_[0..2],0,0x2|$_[3]);
+}
+sub vfaezh {
+ $_[3]=0 if (!defined($_[3]));
+ vfae(@_[0..2],1,0x2|$_[3]);
+}
+sub vfaezf {
+ $_[3]=0 if (!defined($_[3]));
+ vfae(@_[0..2],2,0x2|$_[3]);
+}
+sub vfaezbs {
+ $_[3]=0 if (!defined($_[3]));
+ vfae(@_[0..2],0,0x3|$_[3]);
+}
+sub vfaezhs {
+ $_[3]=0 if (!defined($_[3]));
+ vfae(@_[0..2],1,0x3|$_[3]);
+}
+sub vfaezfs {
+ $_[3]=0 if (!defined($_[3]));
+ vfae(@_[0..2],2,0x3|$_[3]);
+}
+
+sub vfee {
+ confess(err("ARGNUM")) if ($#_<3||$#_>4);
+ VRRb(0xe780,@_);
+}
+sub vfeeb {
+ vfee(@_[0..2],0,$_[3]);
+}
+sub vfeeh {
+ vfee(@_[0..2],1,$_[3]);
+}
+sub vfeef {
+ vfee(@_[0..2],2,$_[3]);
+}
+sub vfeebs {
+ vfee(@_,0,1);
+}
+sub vfeehs {
+ vfee(@_,1,1);
+}
+sub vfeefs {
+ vfee(@_,2,1);
+}
+sub vfeezb {
+ vfee(@_,0,2);
+}
+sub vfeezh {
+ vfee(@_,1,2);
+}
+sub vfeezf {
+ vfee(@_,2,2);
+}
+sub vfeezbs {
+ vfee(@_,0,3);
+}
+sub vfeezhs {
+ vfee(@_,1,3);
+}
+sub vfeezfs {
+ vfee(@_,2,3);
+}
+
+sub vfene {
+ confess(err("ARGNUM")) if ($#_<3||$#_>4);
+ VRRb(0xe781,@_);
+}
+sub vfeneb {
+ vfene(@_[0..2],0,$_[3]);
+}
+sub vfeneh {
+ vfene(@_[0..2],1,$_[3]);
+}
+sub vfenef {
+ vfene(@_[0..2],2,$_[3]);
+}
+sub vfenebs {
+ vfene(@_,0,1);
+}
+sub vfenehs {
+ vfene(@_,1,1);
+}
+sub vfenefs {
+ vfene(@_,2,1);
+}
+sub vfenezb {
+ vfene(@_,0,2);
+}
+sub vfenezh {
+ vfene(@_,1,2);
+}
+sub vfenezf {
+ vfene(@_,2,2);
+}
+sub vfenezbs {
+ vfene(@_,0,3);
+}
+sub vfenezhs {
+ vfene(@_,1,3);
+}
+sub vfenezfs {
+ vfene(@_,2,3);
+}
+
+sub vistr {
+ confess(err("ARGNUM")) if ($#_<2||$#_>3);
+ VRRa(0xe75c,@_[0..2],0,$_[3]);
+}
+sub vistrb {
+ vistr(@_[0..1],0,$_[2]);
+}
+sub vistrh {
+ vistr(@_[0..1],1,$_[2]);
+}
+sub vistrf {
+ vistr(@_[0..1],2,$_[2]);
+}
+sub vistrbs {
+ vistr(@_,0,1);
+}
+sub vistrhs {
+ vistr(@_,1,1);
+}
+sub vistrfs {
+ vistr(@_,2,1);
+}
+
+sub vstrc {
+ confess(err("ARGNUM")) if ($#_<4||$#_>5);
+ VRRd(0xe78a,@_);
+}
+sub vstrcb {
+ vstrc(@_[0..3],0,$_[4]);
+}
+sub vstrch {
+ vstrc(@_[0..3],1,$_[4]);
+}
+sub vstrcf {
+ vstrc(@_[0..3],2,$_[4]);
+}
+sub vstrcbs {
+ $_[4]=0 if (!defined($_[4]));
+ vstrc(@_[0..3],0,0x1|$_[4]);
+}
+sub vstrchs {
+ $_[4]=0 if (!defined($_[4]));
+ vstrc(@_[0..3],1,0x1|$_[4]);
+}
+sub vstrcfs {
+ $_[4]=0 if (!defined($_[4]));
+ vstrc(@_[0..3],2,0x1|$_[4]);
+}
+sub vstrczb {
+ $_[4]=0 if (!defined($_[4]));
+ vstrc(@_[0..3],0,0x2|$_[4]);
+}
+sub vstrczh {
+ $_[4]=0 if (!defined($_[4]));
+ vstrc(@_[0..3],1,0x2|$_[4]);
+}
+sub vstrczf {
+ $_[4]=0 if (!defined($_[4]));
+ vstrc(@_[0..3],2,0x2|$_[4]);
+}
+sub vstrczbs {
+ $_[4]=0 if (!defined($_[4]));
+ vstrc(@_[0..3],0,0x3|$_[4]);
+}
+sub vstrczhs {
+ $_[4]=0 if (!defined($_[4]));
+ vstrc(@_[0..3],1,0x3|$_[4]);
+}
+sub vstrczfs {
+ $_[4]=0 if (!defined($_[4]));
+ vstrc(@_[0..3],2,0x3|$_[4]);
+}
+
+# VX - Floating-point Instructions
+
+sub vfa {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRc(0xe7e3,@_);
+}
+sub vfadb {
+ vfa(@_,3,0);
+}
+sub wfadb {
+ vfa(@_,3,8);
+}
+
+sub wfc {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRa(0xe7cb,@_);
+}
+sub wfcdb {
+ wfc(@_,3,0);
+}
+
+sub wfk {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRa(0xe7ca,@_);
+}
+sub wfksb {
+ wfk(@_,2,0);
+}
+sub wfkdb {
+ wfk(@_,3,0);
+}
+sub wfkxb {
+ wfk(@_,4,0);
+}
+
+sub vfce {
+ confess(err("ARGNUM")) if ($#_!=5);
+ VRRc(0xe7e8,@_);
+}
+sub vfcedb {
+ vfce(@_,3,0,0);
+}
+sub vfcedbs {
+ vfce(@_,3,0,1);
+}
+sub wfcedb {
+ vfce(@_,3,8,0);
+}
+sub wfcedbs {
+ vfce(@_,3,8,1);
+}
+
+sub vfch {
+ confess(err("ARGNUM")) if ($#_!=5);
+ VRRc(0xe7eb,@_);
+}
+sub vfchdb {
+ vfch(@_,3,0,0);
+}
+sub vfchdbs {
+ vfch(@_,3,0,1);
+}
+sub wfchdb {
+ vfch(@_,3,8,0);
+}
+sub wfchdbs {
+ vfch(@_,3,8,1);
+}
+
+sub vfche {
+ confess(err("ARGNUM")) if ($#_!=5);
+ VRRc(0xe7ea,@_);
+}
+sub vfchedb {
+ vfche(@_,3,0,0);
+}
+sub vfchedbs {
+ vfche(@_,3,0,1);
+}
+sub wfchedb {
+ vfche(@_,3,8,0);
+}
+sub wfchedbs {
+ vfche(@_,3,8,1);
+}
+
+sub vcdg {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRa(0xe7c3,@_);
+}
+sub vcdgb {
+ vcdg(@_[0..1],3,@_[2..3]);
+}
+sub wcdgb {
+ vcdg(@_[0..1],3,0x8|$_[2],$_[3]);
+}
+
+sub vcdlg {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRa(0xe7c1,@_);
+}
+sub vcdlgb {
+ vcdlg(@_[0..1],3,@_[2..3]);
+}
+sub wcdlgb {
+ vcdlg(@_[0..1],3,0x8|$_[2],$_[3]);
+}
+
+sub vcgd {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRa(0xe7c2,@_);
+}
+sub vcgdb {
+ vcgd(@_[0..1],3,@_[2..3]);
+}
+sub wcgdb {
+ vcgd(@_[0..1],3,0x8|$_[2],$_[3]);
+}
+
+sub vclgd {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRa(0xe7c0,@_);
+}
+sub vclgdb {
+ vclgd(@_[0..1],3,@_[2..3]);
+}
+sub wclgdb {
+ vclgd(@_[0..1],3,0x8|$_[2],$_[3]);
+}
+
+sub vfd {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRc(0xe7e5,@_);
+}
+sub vfddb {
+ vfd(@_,3,0);
+}
+sub wfddb {
+ vfd(@_,3,8);
+}
+
+sub vfi {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRa(0xe7c7,@_);
+}
+sub vfidb {
+ vfi(@_[0..1],3,@_[2..3]);
+}
+sub wfidb {
+ vfi(@_[0..1],3,0x8|$_[2],$_[3]);
+}
+
+sub vlde { # deprecated, use vfll
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRa(0xe7c4,@_);
+}
+sub vldeb { # deprecated, use vflls
+ vlde(@_,2,0);
+}
+sub wldeb { # deprecated, use wflls
+ vlde(@_,2,8);
+}
+
+sub vled { # deprecated, use vflr
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRa(0xe7c5,@_);
+}
+sub vledb { # deprecated, use vflrd
+ vled(@_[0..1],3,@_[2..3]);
+}
+sub wledb { # deprecated, use wflrd
+ vled(@_[0..1],3,0x8|$_[2],$_[3]);
+}
+
+sub vfm {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRc(0xe7e7,@_);
+}
+sub vfmdb {
+ vfm(@_,3,0);
+}
+sub wfmdb {
+ vfm(@_,3,8);
+}
+
+sub vfma {
+ confess(err("ARGNUM")) if ($#_!=5);
+ VRRe(0xe78f,@_);
+}
+sub vfmadb {
+ vfma(@_,0,3);
+}
+sub wfmadb {
+ vfma(@_,8,3);
+}
+
+sub vfms {
+ confess(err("ARGNUM")) if ($#_!=5);
+ VRRe(0xe78e,@_);
+}
+sub vfmsdb {
+ vfms(@_,0,3);
+}
+sub wfmsdb {
+ vfms(@_,8,3);
+}
+
+sub vfpso {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRa(0xe7cc,@_);
+}
+sub vfpsodb {
+ vfpso(@_[0..1],3,0,$_[2]);
+}
+sub wfpsodb {
+ vfpso(@_[0..1],3,8,$_[2]);
+}
+sub vflcdb {
+ vfpso(@_,3,0,0);
+}
+sub wflcdb {
+ vfpso(@_,3,8,0);
+}
+sub vflndb {
+ vfpso(@_,3,0,1);
+}
+sub wflndb {
+ vfpso(@_,3,8,1);
+}
+sub vflpdb {
+ vfpso(@_,3,0,2);
+}
+sub wflpdb {
+ vfpso(@_,3,8,2);
+}
+
+sub vfsq {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRRa(0xe7ce,@_);
+}
+sub vfsqdb {
+ vfsq(@_,3,0);
+}
+sub wfsqdb {
+ vfsq(@_,3,8);
+}
+
+sub vfs {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRRc(0xe7e2,@_);
+}
+sub vfsdb {
+ vfs(@_,3,0);
+}
+sub wfsdb {
+ vfs(@_,3,8);
+}
+
+sub vftci {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRIe(0xe74a,@_);
+}
+sub vftcidb {
+ vftci(@_,3,0);
+}
+sub wftcidb {
+ vftci(@_,3,8);
+}
+
+# VXE - Support Instructions
+
+sub vbperm {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRc(0xe785,@_);
+}
+
+sub vllezlf {
+ vllez(@_,6);
+}
+
+# VXE - Integer Instructions
+
+sub vmsl {
+ confess(err("ARGNUM")) if ($#_!=5);
+ VRRd(0xe7b8,@_);
+}
+sub vmslg {
+ vmsl(@_[0..3],3,$_[4]);
+}
+
+sub vnx {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRc(0xe76c,@_);
+}
+
+sub vnn {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRc(0xe76e,@_);
+}
+
+sub voc {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRc(0xe76f,@_);
+}
+
+sub vpopctb {
+ vpopct(@_,0);
+}
+sub vpopcth {
+ vpopct(@_,1);
+}
+sub vpopctf {
+ vpopct(@_,2);
+}
+sub vpopctg {
+ vpopct(@_,3);
+}
+
+# VXE - Floating-Point Instructions
+
+sub vfasb {
+ vfa(@_,2,0);
+}
+sub wfasb {
+ vfa(@_,2,8);
+}
+sub wfaxb {
+ vfa(@_,4,8);
+}
+
+sub wfcsb {
+ wfc(@_,2,0);
+}
+sub wfcxb {
+ wfc(@_,4,0);
+}
+
+sub vfcesb {
+ vfce(@_,2,0,0);
+}
+sub vfcesbs {
+ vfce(@_,2,0,1);
+}
+sub wfcesb {
+ vfce(@_,2,8,0);
+}
+sub wfcesbs {
+ vfce(@_,2,8,1);
+}
+sub wfcexb {
+ vfce(@_,4,8,0);
+}
+sub wfcexbs {
+ vfce(@_,4,8,1);
+}
+
+sub vfchsb {
+ vfch(@_,2,0,0);
+}
+sub vfchsbs {
+ vfch(@_,2,0,1);
+}
+sub wfchsb {
+ vfch(@_,2,8,0);
+}
+sub wfchsbs {
+ vfch(@_,2,8,1);
+}
+sub wfchxb {
+ vfch(@_,4,8,0);
+}
+sub wfchxbs {
+ vfch(@_,4,8,1);
+}
+
+sub vfchesb {
+ vfche(@_,2,0,0);
+}
+sub vfchesbs {
+ vfche(@_,2,0,1);
+}
+sub wfchesb {
+ vfche(@_,2,8,0);
+}
+sub wfchesbs {
+ vfche(@_,2,8,1);
+}
+sub wfchexb {
+ vfche(@_,4,8,0);
+}
+sub wfchexbs {
+ vfche(@_,4,8,1);
+}
+
+sub vfdsb {
+ vfd(@_,2,0);
+}
+sub wfdsb {
+ vfd(@_,2,8);
+}
+sub wfdxb {
+ vfd(@_,4,8);
+}
+
+sub vfisb {
+ vfi(@_[0..1],2,@_[2..3]);
+}
+sub wfisb {
+ vfi(@_[0..1],2,0x8|$_[2],$_[3]);
+}
+sub wfixb {
+ vfi(@_[0..1],4,0x8|$_[2],$_[3]);
+}
+
+sub vfll {
+ vlde(@_);
+}
+sub vflls {
+ vfll(@_,2,0);
+}
+sub wflls {
+ vfll(@_,2,8);
+}
+sub wflld {
+ vfll(@_,3,8);
+}
+
+sub vflr {
+ vled(@_);
+}
+sub vflrd {
+ vflr(@_[0..1],3,@_[2..3]);
+}
+sub wflrd {
+ vflr(@_[0..1],3,0x8|$_[2],$_[3]);
+}
+sub wflrx {
+ vflr(@_[0..1],4,0x8|$_[2],$_[3]);
+}
+
+sub vfmax {
+ confess(err("ARGNUM")) if ($#_!=5);
+ VRRc(0xe7ef,@_);
+}
+sub vfmaxsb {
+ vfmax(@_[0..2],2,0,$_[3]);
+}
+sub vfmaxdb {
+ vfmax(@_[0..2],3,0,$_[3]);
+}
+sub wfmaxsb {
+ vfmax(@_[0..2],2,8,$_[3]);
+}
+sub wfmaxdb {
+ vfmax(@_[0..2],3,8,$_[3]);
+}
+sub wfmaxxb {
+ vfmax(@_[0..2],4,8,$_[3]);
+}
+
+sub vfmin {
+ confess(err("ARGNUM")) if ($#_!=5);
+ VRRc(0xe7ee,@_);
+}
+sub vfminsb {
+ vfmin(@_[0..2],2,0,$_[5]);
+}
+sub vfmindb {
+ vfmin(@_[0..2],3,0,$_[5]);
+}
+sub wfminsb {
+ vfmin(@_[0..2],2,8,$_[5]);
+}
+sub wfmindb {
+ vfmin(@_[0..2],3,8,$_[5]);
+}
+sub wfminxb {
+ vfmin(@_[0..2],4,8,$_[5]);
+}
+
+sub vfmsb {
+ vfm(@_,2,0);
+}
+sub wfmsb {
+ vfm(@_,2,8);
+}
+sub wfmxb {
+ vfm(@_,4,8);
+}
+
+sub vfmasb {
+ vfma(@_,0,2);
+}
+sub wfmasb {
+ vfma(@_,8,2);
+}
+sub wfmaxb {
+ vfma(@_,8,4);
+}
+
+sub vfmssb {
+ vfms(@_,0,2);
+}
+sub wfmssb {
+ vfms(@_,8,2);
+}
+sub wfmsxb {
+ vfms(@_,8,4);
+}
+
+sub vfnma {
+ confess(err("ARGNUM")) if ($#_!=5);
+ VRRe(0xe79f,@_);
+}
+sub vfnmasb {
+ vfnma(@_,0,2);
+}
+sub vfnmadb {
+ vfnma(@_,0,3);
+}
+sub wfnmasb {
+ vfnma(@_,8,2);
+}
+sub wfnmadb {
+ vfnma(@_,8,3);
+}
+sub wfnmaxb {
+ vfnma(@_,8,4);
+}
+
+sub vfnms {
+ confess(err("ARGNUM")) if ($#_!=5);
+ VRRe(0xe79e,@_);
+}
+sub vfnmssb {
+ vfnms(@_,0,2);
+}
+sub vfnmsdb {
+ vfnms(@_,0,3);
+}
+sub wfnmssb {
+ vfnms(@_,8,2);
+}
+sub wfnmsdb {
+ vfnms(@_,8,3);
+}
+sub wfnmsxb {
+ vfnms(@_,8,4);
+}
+
+sub vfpsosb {
+ vfpso(@_[0..1],2,0,$_[2]);
+}
+sub wfpsosb {
+ vfpso(@_[0..1],2,8,$_[2]);
+}
+sub vflcsb {
+ vfpso(@_,2,0,0);
+}
+sub wflcsb {
+ vfpso(@_,2,8,0);
+}
+sub vflnsb {
+ vfpso(@_,2,0,1);
+}
+sub wflnsb {
+ vfpso(@_,2,8,1);
+}
+sub vflpsb {
+ vfpso(@_,2,0,2);
+}
+sub wflpsb {
+ vfpso(@_,2,8,2);
+}
+sub vfpsoxb {
+ vfpso(@_[0..1],4,0,$_[2]);
+}
+sub wfpsoxb {
+ vfpso(@_[0..1],4,8,$_[2]);
+}
+sub vflcxb {
+ vfpso(@_,4,0,0);
+}
+sub wflcxb {
+ vfpso(@_,4,8,0);
+}
+sub vflnxb {
+ vfpso(@_,4,0,1);
+}
+sub wflnxb {
+ vfpso(@_,4,8,1);
+}
+sub vflpxb {
+ vfpso(@_,4,0,2);
+}
+sub wflpxb {
+ vfpso(@_,4,8,2);
+}
+
+sub vfsqsb {
+ vfsq(@_,2,0);
+}
+sub wfsqsb {
+ vfsq(@_,2,8);
+}
+sub wfsqxb {
+ vfsq(@_,4,8);
+}
+
+sub vfssb {
+ vfs(@_,2,0);
+}
+sub wfssb {
+ vfs(@_,2,8);
+}
+sub wfsxb {
+ vfs(@_,4,8);
+}
+
+sub vftcisb {
+ vftci(@_,2,0);
+}
+sub wftcisb {
+ vftci(@_,2,8);
+}
+sub wftcixb {
+ vftci(@_,4,8);
+}
+
+# VXD - Support Instructions
+
+sub vlrlr {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRSd(0xe637,@_);
+}
+
+sub vlrl {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VSI(0xe635,@_);
+}
+
+sub vstrlr {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRSd(0xe63f,@_);
+}
+
+sub vstrl {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VSI(0xe63d,@_);
+}
+
+sub vap {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRIf(0xe671,@_);
+}
+
+sub vcp {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRh(0xe677,@_);
+}
+
+sub vcvb {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRi(0xe650,@_);
+}
+
+sub vcvbg {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRRi(0xe652,@_);
+}
+
+sub vcvd {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRIi(0xe658,@_);
+}
+
+sub vcvdg {
+ confess(err("ARGNUM")) if ($#_!=3);
+ VRIi(0xe65a,@_);
+}
+
+sub vdp {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRIf(0xe67a,@_);
+}
+
+sub vlip {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VRIh(0xe649,@_);
+}
+
+sub vmp {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRIf(0xe678,@_);
+}
+
+sub vmsp {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRIf(0xe679,@_);
+}
+
+sub vpkz {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VSI(0xe634,@_);
+}
+
+sub vpsop {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRIg(0xe65b,@_);
+}
+
+sub vrp {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRIf(0xe67b,@_);
+}
+
+sub vsdp {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRIf(0xe67e,@_);
+}
+
+sub vsrp {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRIg(0xe659,@_);
+}
+
+sub vsp {
+ confess(err("ARGNUM")) if ($#_!=4);
+ VRIf(0xe673,@_);
+}
+
+sub vtp {
+ confess(err("ARGNUM")) if ($#_!=0);
+ VRRg(0xe65f,@_);
+}
+
+sub vupkz {
+ confess(err("ARGNUM")) if ($#_!=2);
+ VSI(0xe63c,@_);
+}
+
+#
+# Instruction Formats
+#
+
+sub RIEf {
+ confess(err("ARGNUM")) if ($#_<4||5<$#_);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$r1,$r2,$i3,$i4,$i5)=(shift,get_R(shift),get_R(shift),
+ get_I(shift,8),get_I(shift,8),
+ get_I(shift,8));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",(($opcode>>8)<<8|$r1<<4|$r2)).",";
+ $out.=sprintf("%#06x",($i3<<8)|$i4).",";
+ $out.=sprintf("%#06x",($i5<<8)|($opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub RILa {
+ confess(err("ARGNUM")) if ($#_!=2);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$r1,$i2)=(shift,get_R(shift),get_I(shift,32));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",(($opcode>>4)<<8|$r1<<4|($opcode&0xf))).",";
+ $out.=sprintf("%#06x",($i2>>16)).",";
+ $out.=sprintf("%#06x",($i2&0xffff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub RRE {
+ confess(err("ARGNUM")) if ($#_<0||2<$#_);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$r1,$r2)=(shift,get_R(shift),get_R(shift));
+
+ $out.="\t.long\t".sprintf("%#010x",($opcode<<16|$r1<<4|$r2));
+ $out.="\t# $memn";
+ # RRE can have 0 ops e.g., pcc.
+ $out.="\t$ops" if ((defined($ops))&&($ops ne ''));
+ $out.="\n";
+}
+
+sub RRFb {
+ confess(err("ARGNUM")) if ($#_<3||4<$#_);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$r1,$r3,$r2,$m4)=(shift,get_R(shift),get_R(shift)
+ ,get_R(shift),get_M(shift));
+
+ $out.="\t.long\t"
+ .sprintf("%#010x",($opcode<<16|$r3<<12|$m4<<8|$r1<<4|$r2));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub RXYa {
+ confess(err("ARGNUM")) if ($#_!=2);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$r1,$d2,$x2,$b2)=(shift,get_R(shift),get_DXB(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",(($opcode>>8)<<8|$r1<<4|$x2)).",";
+ $out.=sprintf("%#06x",($b2<<12|($d2&0xfff))).",";
+ $out.=sprintf("%#06x",(($d2>>12)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub S {
+ confess(err("ARGNUM")) if ($#_<0||1<$#_);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$d2,$b2)=(shift,get_DB(shift));
+
+ $out.="\t.long\t".sprintf("%#010x",($opcode<<16|$b2<<12|$d2));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRIa {
+ confess(err("ARGNUM")) if ($#_<2||3<$#_);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$i2,$m3)=(shift,get_V(shift),get_I(shift,16),
+ get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)).",";
+ $out.=sprintf("%#06x",$i2).",";
+ $out.=sprintf("%#06x",($m3<<12|RXB($v1)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRIb {
+ confess(err("ARGNUM")) if ($#_!=4);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$i2,$i3,$m4)=(shift,get_V(shift),get_I(shift,8),
+ ,get_I(shift,8),get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)).",";
+ $out.=sprintf("%#06x",($i2<<8|$i3)).",";
+ $out.=sprintf("%#06x",($m4<<12|RXB($v1)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRIc {
+ confess(err("ARGNUM")) if ($#_!=4);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$v3,$i2,$m4)=(shift,get_V(shift),get_V(shift),
+ ,get_I(shift,16),get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)|($v3&0xf)).",";
+ $out.=sprintf("%#06x",$i2).",";
+ $out.=sprintf("%#06x",($m4<<12|RXB($v1,$v3)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRId {
+ confess(err("ARGNUM")) if ($#_<4||$#_>5);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$v2,$v3,$i4,$m5)=(shift,get_V(shift),get_V(shift),
+ ,get_V(shift),get_I(shift,8),get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)|($v2&0xf)).",";
+ $out.=sprintf("%#06x",(($v3&0xf)<<12|$i4)).",";
+ $out.=sprintf("%#06x",($m5<<12|RXB($v1,$v2,$v3)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRIe {
+ confess(err("ARGNUM")) if ($#_!=5);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$v2,$i3,$m4,$m5)=(shift,get_V(shift),get_V(shift),
+ ,get_I(shift,12),get_M(shift),get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)|($v2&0xf)).",";
+ $out.=sprintf("%#06x",($i3<<4|$m5)).",";
+ $out.=sprintf("%#06x",($m4<<12|RXB($v1,$v2)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRIf {
+ confess(err("ARGNUM")) if ($#_!=5);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$v2,$v3,$i4,$m5)=(shift,get_V(shift),get_V(shift),
+ ,get_V(shift),get_I(shift,8),get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)|($v2&0xf)).",";
+ $out.=sprintf("%#06x",(($v3&0xf)<<12|$m5<<4)|$i4>>4).",";
+ $out.=sprintf("%#06x",(($i4&0xf)<<12|RXB($v1,$v2,$v3)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRIg {
+ confess(err("ARGNUM")) if ($#_!=5);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$v2,$i3,$i4,$m5)=(shift,get_V(shift),get_V(shift),
+ ,get_I(shift,8),get_I(shift,8),get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)|($v2&0xf)).",";
+ $out.=sprintf("%#06x",($i4<<8|$m5<<4|$i3>>4)).",";
+ $out.=sprintf("%#06x",(($i3&0xf)<<12|RXB($v1,$v2)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRIh {
+ confess(err("ARGNUM")) if ($#_!=3);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$i2,$i3)=(shift,get_V(shift),get_I(shift,16),
+ get_I(shift,4));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)).",";
+ $out.=sprintf("%#06x",$i2).",";
+ $out.=sprintf("%#06x",($i3<<12|RXB($v1)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRIi {
+ confess(err("ARGNUM")) if ($#_!=4);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$r2,$i3,$m4)=(shift,get_V(shift),get_R(shift),
+ ,get_I(shift,8),get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)|$r2).",";
+ $out.=sprintf("%#06x",($m4<<4|$i3>>4)).",";
+ $out.=sprintf("%#06x",(($i3&0xf)<<12|RXB($v1)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRRa {
+ confess(err("ARGNUM")) if ($#_<2||5<$#_);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$v2,$m3,$m4,$m5)=(shift,get_V(shift),get_V(shift),
+ get_M(shift),get_M(shift),get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|($v2&0xf))).",";
+ $out.=sprintf("%#06x",($m5<<4|$m4)).",";
+ $out.=sprintf("%#06x",($m3<<12|RXB($v1,$v2)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRRb {
+ confess(err("ARGNUM")) if ($#_<3||5<$#_);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$v2,$v3,$m4,$m5)=(shift,get_V(shift),get_V(shift),
+ get_V(shift),get_M(shift),get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|($v2&0xf))).",";
+ $out.=sprintf("%#06x",(($v3&0xf)<<12|$m5<<4)).",";
+ $out.=sprintf("%#06x",($m4<<12|RXB($v1,$v2,$v3)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRRc {
+ confess(err("ARGNUM")) if ($#_<3||6<$#_);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$v2,$v3,$m4,$m5,$m6)=(shift,get_V(shift),get_V(shift),
+ get_V(shift),get_M(shift),get_M(shift),get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|($v2&0xf))).",";
+ $out.=sprintf("%#06x",(($v3&0xf)<<12|$m6<<4|$m5)).",";
+ $out.=sprintf("%#06x",($m4<<12|RXB($v1,$v2,$v3)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRRd {
+ confess(err("ARGNUM")) if ($#_<4||6<$#_);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$v2,$v3,$v4,$m5,$m6)=(shift,get_V(shift),get_V(shift),
+ get_V(shift),get_V(shift),get_M(shift),get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|($v2&0xf))).",";
+ $out.=sprintf("%#06x",(($v3&0xf)<<12|$m5<<8|$m6<<4)).",";
+ $out.=sprintf("%#06x",(($v4&0xf)<<12|RXB($v1,$v2,$v3,$v4)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRRe {
+ confess(err("ARGNUM")) if ($#_<4||6<$#_);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$v2,$v3,$v4,$m5,$m6)=(shift,get_V(shift),get_V(shift),
+ get_V(shift),get_V(shift),get_M(shift),get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|($v2&0xf))).",";
+ $out.=sprintf("%#06x",(($v3&0xf)<<12|$m6<<8|$m5)).",";
+ $out.=sprintf("%#06x",(($v4&0xf)<<12|RXB($v1,$v2,$v3,$v4)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRRf {
+ confess(err("ARGNUM")) if ($#_!=3);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$r2,$r3)=(shift,get_V(shift),get_R(shift),
+ get_R(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|$r2)).",";
+ $out.=sprintf("%#06x",($r3<<12)).",";
+ $out.=sprintf("%#06x",(RXB($v1)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRRg {
+ confess(err("ARGNUM")) if ($#_!=1);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1)=(shift,get_V(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf))).",";
+ $out.=sprintf("%#06x",0x0000).",";
+ $out.=sprintf("%#06x",(RXB(0,$v1)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRRh {
+ confess(err("ARGNUM")) if ($#_<2||$#_>3);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$v2,$m3)=(shift,get_V(shift),get_V(shift),
+ get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf))).",";
+ $out.=sprintf("%#06x",(($v2&0xf)<<12|$m3<<4)).",";
+ $out.=sprintf("%#06x",(RXB(0,$v1,$v2)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRRi {
+ confess(err("ARGNUM")) if ($#_!=3);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$r1,$v2,$m3)=(shift,get_R(shift),get_V(shift),
+ get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|$r1<<4|($v2&0xf))).",";
+ $out.=sprintf("%#06x",($m3<<4))."\,";
+ $out.=sprintf("%#06x",(RXB(0,$v2)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRSa {
+ confess(err("ARGNUM")) if ($#_<3||$#_>4);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$v3,$d2,$b2,$m4)=(shift,get_V(shift),get_V(shift),
+ get_DB(shift),get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|($v3&0xf))).",";
+ $out.=sprintf("%#06x",($b2<<12|$d2)).",";
+ $out.=sprintf("%#06x",($m4<<12|RXB($v1,$v3)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRSb {
+ confess(err("ARGNUM")) if ($#_<3||$#_>4);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$r3,$d2,$b2,$m4)=(shift,get_V(shift),get_R(shift),
+ get_DB(shift),get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|$r3)).",";
+ $out.=sprintf("%#06x",($b2<<12|$d2)).",";
+ $out.=sprintf("%#06x",($m4<<12|RXB($v1)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRSc {
+ confess(err("ARGNUM")) if ($#_!=4);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$r1,$v3,$d2,$b2,$m4)=(shift,get_R(shift),get_V(shift),
+ get_DB(shift),get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|$r1<<4|($v3&0xf))).",";
+ $out.=sprintf("%#06x",($b2<<12|$d2)).",";
+ $out.=sprintf("%#06x",($m4<<12|RXB(0,$v3)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRSd {
+ confess(err("ARGNUM")) if ($#_!=3);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$r3,$d2,$b2)=(shift,get_V(shift),get_R(shift),
+ get_DB(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|$r3)).",";
+ $out.=sprintf("%#06x",($b2<<12|$d2)).",";
+ $out.=sprintf("%#06x",(($v1&0xf)<<12|RXB(0,0,0,$v1)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRV {
+ confess(err("ARGNUM")) if ($#_<2||$#_>3);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$d2,$v2,$b2,$m3)=(shift,get_V(shift),get_DVB(shift),
+ get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|($v2&0xf))).",";
+ $out.=sprintf("%#06x",($b2<<12|$d2)).",";
+ $out.=sprintf("%#06x",($m3<<12|RXB($v1,$v2)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VRX {
+ confess(err("ARGNUM")) if ($#_<2||$#_>3);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$d2,$x2,$b2,$m3)=(shift,get_V(shift),get_DXB(shift),
+ get_M(shift));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|($x2))).",";
+ $out.=sprintf("%#06x",($b2<<12|$d2)).",";
+ $out.=sprintf("%#06x",($m3<<12|RXB($v1)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+sub VSI {
+ confess(err("ARGNUM")) if ($#_!=3);
+ my $ops=join(',',@_[1..$#_]);
+ my $memn=(caller(1))[3];
+ $memn=~s/^.*:://;
+ my ($opcode,$v1,$d2,$b2,$i3)=(shift,get_V(shift),get_DB(shift),
+ get_I(shift,8));
+
+ $out.="\t.word\t";
+ $out.=sprintf("%#06x",($opcode&0xff00|$i3)).",";
+ $out.=sprintf("%#06x",($b2<<12|$d2)).",";
+ $out.=sprintf("%#06x",(($v1&0xf)<<12|RXB(0,0,0,$v1)<<8|$opcode&0xff));
+ $out.="\t# $memn\t$ops\n";
+}
+
+#
+# Internal
+#
+
+sub get_R {
+ confess(err("ARGNUM")) if ($#_!=0);
+ my $r;
+
+ for (shift) {
+ if (!defined) {
+ $r=0;
+ } elsif (/^$GR$/) {
+ $r=$1;
+ } else {
+ confess(err("PARSE"));
+ }
+ }
+ confess(err("ARGRANGE")) if ($r&~0xf);
+
+ return $r;
+}
+
+sub get_V {
+ confess(err("ARGNUM")) if ($#_!=0);
+ my $v;
+
+ for (shift) {
+ if (!defined) {
+ $v=0;
+ } elsif (/^$VR$/) {
+ $v=$1;
+ } else {
+ confess(err("PARSE"));
+ }
+ }
+ confess(err("ARGRANGE")) if ($v&~0x1f);
+
+ return $v;
+}
+
+sub get_I {
+ confess(err("ARGNUM")) if ($#_!=1);
+ my ($i,$bits)=(shift,shift);
+
+ $i=defined($i)?(eval($i)):(0);
+ confess(err("PARSE")) if (!defined($i));
+ confess(err("ARGRANGE")) if (abs($i)&~(2**$bits-1));
+
+ return $i&(2**$bits-1);
+}
+
+sub get_M {
+ confess(err("ARGNUM")) if ($#_!=0);
+ my $m=shift;
+
+ $m=defined($m)?(eval($m)):(0);
+ confess(err("PARSE")) if (!defined($m));
+ confess(err("ARGRANGE")) if ($m&~0xf);
+
+ return $m;
+}
+
+sub get_DB
+{
+ confess(err("ARGNUM")) if ($#_!=0);
+ my ($d,$b);
+
+ for (shift) {
+ if (!defined) {
+ ($d,$b)=(0,0);
+ } elsif (/^(.+)\($GR\)$/) {
+ ($d,$b)=(eval($1),$2);
+ confess(err("PARSE")) if (!defined($d));
+ } elsif (/^(.+)$/) {
+ ($d,$b)=(eval($1),0);
+ confess(err("PARSE")) if (!defined($d));
+ } else {
+ confess(err("PARSE"));
+ }
+ }
+ confess(err("ARGRANGE")) if ($d&~0xfff||$b&~0xf);
+
+ return ($d,$b);
+}
+
+sub get_DVB
+{
+ confess(err("ARGNUM")) if ($#_!=0);
+ my ($d,$v,$b);
+
+ for (shift) {
+ if (!defined) {
+ ($d,$v,$b)=(0,0,0);
+ } elsif (/^(.+)\($VR,$GR\)$/) {
+ ($d,$v,$b)=(eval($1),$2,$3);
+ confess(err("PARSE")) if (!defined($d));
+ } elsif (/^(.+)\($GR\)$/) {
+ ($d,$v,$b)=(eval($1),0,$2);
+ confess(err("PARSE")) if (!defined($d));
+ } elsif (/^(.+)$/) {
+ ($d,$v,$b)=(eval($1),0,0);
+ confess(err("PARSE")) if (!defined($d));
+ } else {
+ confess(err("PARSE"));
+ }
+ }
+ confess(err("ARGRANGE")) if ($d&~0xfff||$v&~0x1f||$b&~0xf);
+
+ return ($d,$v,$b);
+}
+
+sub get_DXB
+{
+ confess(err("ARGNUM")) if ($#_!=0);
+ my ($d,$x,$b);
+
+ for (shift) {
+ if (!defined) {
+ ($d,$x,$b)=(0,0,0);
+ } elsif (/^(.+)\($GR,$GR\)$/) {
+ ($d,$x,$b)=(eval($1),$2,$3);
+ confess(err("PARSE")) if (!defined($d));
+ } elsif (/^(.+)\($GR\)$/) {
+ ($d,$x,$b)=(eval($1),0,$2);
+ confess(err("PARSE")) if (!defined($d));
+ } elsif (/^(.+)$/) {
+ ($d,$x,$b)=(eval($1),0,0);
+ confess(err("PARSE")) if (!defined($d));
+ } else {
+ confess(err("PARSE"));
+ }
+ }
+ confess(err("ARGRANGE")) if ($d&~0xfff||$x&~0xf||$b&~0xf);
+
+ return ($d,$x,$b);
+}
+
+sub RXB
+{
+ confess(err("ARGNUM")) if ($#_<0||3<$#_);
+ my $rxb=0;
+
+ $rxb|=0x08 if (defined($_[0])&&($_[0]&0x10));
+ $rxb|=0x04 if (defined($_[1])&&($_[1]&0x10));
+ $rxb|=0x02 if (defined($_[2])&&($_[2]&0x10));
+ $rxb|=0x01 if (defined($_[3])&&($_[3]&0x10));
+
+ return $rxb;
+}
+
+sub err {
+ my %ERR =
+ (
+ ARGNUM => 'Wrong number of arguments',
+ ARGRANGE=> 'Argument out of range',
+ PARSE => 'Parse error',
+ );
+ confess($ERR{ARGNUM}) if ($#_!=0);
+
+ return $ERR{$_[0]};
+}
+
+1;
diff --git a/crypto/perlasm/sparcv9_modes.pl b/crypto/perlasm/sparcv9_modes.pl
index b9922e031893..76a2727aba62 100644
--- a/crypto/perlasm/sparcv9_modes.pl
+++ b/crypto/perlasm/sparcv9_modes.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
diff --git a/crypto/perlasm/x86_64-support.pl b/crypto/perlasm/x86_64-support.pl
new file mode 100644
index 000000000000..0bacb7186469
--- /dev/null
+++ b/crypto/perlasm/x86_64-support.pl
@@ -0,0 +1,51 @@
+#! /usr/bin/env perl
+# Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+
+package x86_64support;
+
+# require "x86_64-support.pl";
+# $ptr_size=&pointer_size($flavour);
+# $ptr_reg=&pointer_register($flavour,$reg);
+
+sub ::pointer_size
+{
+ my($flavour)=@_;
+ my $ptr_size=8; $ptr_size=4 if ($flavour eq "elf32");
+ return $ptr_size;
+}
+
+sub ::pointer_register
+{
+ my($flavour,$reg)=@_;
+ if ($flavour eq "elf32") {
+ if ($reg eq "%rax") {
+ return "%eax";
+ } elsif ($reg eq "%rbx") {
+ return "%ebx";
+ } elsif ($reg eq "%rcx") {
+ return "%ecx";
+ } elsif ($reg eq "%rdx") {
+ return "%edx";
+ } elsif ($reg eq "%rdi") {
+ return "%edi";
+ } elsif ($reg eq "%rsi") {
+ return "%esi";
+ } elsif ($reg eq "%rbp") {
+ return "%ebp";
+ } elsif ($reg eq "%rsp") {
+ return "%esp";
+ } else {
+ return $reg."d";
+ }
+ } else {
+ return $reg;
+ }
+}
+
+1;
diff --git a/crypto/perlasm/x86_64-xlate.pl b/crypto/perlasm/x86_64-xlate.pl
index 59af6df9c200..1830b2556599 100755
--- a/crypto/perlasm/x86_64-xlate.pl
+++ b/crypto/perlasm/x86_64-xlate.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -83,6 +83,10 @@ my $PTR=" PTR";
my $nasmref=2.03;
my $nasm=0;
+# GNU as indicator, as opposed to $gas, which indicates acceptable
+# syntax
+my $gnuas=0;
+
if ($flavour eq "mingw64") { $gas=1; $elf=0; $win64=1;
$prefix=`echo __USER_LABEL_PREFIX__ | $ENV{CC} -E -P -`;
$prefix =~ s|\R$||; # Better chomp
@@ -100,6 +104,51 @@ elsif (!$gas)
$elf=0;
$decor="\$L\$";
}
+# Find out if we're using GNU as
+elsif (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
+ =~ /GNU assembler version ([2-9]\.[0-9]+)/)
+{
+ $gnuas=1;
+}
+elsif (`$ENV{CC} --version 2>/dev/null`
+ =~ /clang .*/)
+{
+ $gnuas=1;
+}
+
+my $cet_property;
+if ($flavour =~ /elf/) {
+ # Always generate .note.gnu.property section for ELF outputs to
+ # mark Intel CET support since all input files must be marked
+ # with Intel CET support in order for linker to mark output with
+ # Intel CET support.
+ my $p2align=3; $p2align=2 if ($flavour eq "elf32");
+ my $section='.note.gnu.property, #alloc';
+ $section='".note.gnu.property", "a"' if $gnuas;
+ $cet_property = <<_____;
+ .section $section
+ .p2align $p2align
+ .long 1f - 0f
+ .long 4f - 1f
+ .long 5
+0:
+ # "GNU" encoded with .byte, since .asciz isn't supported
+ # on Solaris.
+ .byte 0x47
+ .byte 0x4e
+ .byte 0x55
+ .byte 0
+1:
+ .p2align $p2align
+ .long 0xc0000002
+ .long 3f - 2f
+2:
+ .long 3
+3:
+ .p2align $p2align
+4:
+_____
+}
my $current_segment;
my $current_function;
@@ -1151,7 +1200,7 @@ while(defined(my $line=<>)) {
$line =~ s|[#!].*$||; # get rid of asm-style comments...
$line =~ s|/\*.*\*/||; # ... and C-style comments...
- $line =~ s|^\s+||; # ... and skip white spaces in beginning
+ $line =~ s|^\s+||; # ... and skip whitespaces in beginning
$line =~ s|\s+$||; # ... and at the end
if (my $label=label->re(\$line)) { print $label->out(); }
@@ -1213,10 +1262,11 @@ while(defined(my $line=<>)) {
print $line,"\n";
}
+print "$cet_property" if ($cet_property);
print "\n$current_segment\tENDS\n" if ($current_segment && $masm);
print "END\n" if ($masm);
-close STDOUT or die "error closing STDOUT: $!";
+close STDOUT or die "error closing STDOUT: $!;"
#################################################
# Cross-reference x86_64 ABI "card"
diff --git a/crypto/perlasm/x86asm.pl b/crypto/perlasm/x86asm.pl
index 29dc1a2cfbc9..8dcde9eacaa3 100644
--- a/crypto/perlasm/x86asm.pl
+++ b/crypto/perlasm/x86asm.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -174,7 +174,9 @@ sub ::vprotd
sub ::endbranch
{
+ &::generic("#ifdef __CET__\n");
&::data_byte(0xf3,0x0f,0x1e,0xfb);
+ &::generic("#endif\n");
}
# label management
diff --git a/crypto/perlasm/x86gas.pl b/crypto/perlasm/x86gas.pl
index 5c7ea3880e4d..1b2b27c02286 100644
--- a/crypto/perlasm/x86gas.pl
+++ b/crypto/perlasm/x86gas.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -124,6 +124,7 @@ sub ::function_begin_B
push(@out,".align\t$align\n");
push(@out,"$func:\n");
push(@out,"$begin:\n") if ($global);
+ &::endbranch();
$::stack=4;
}
@@ -172,6 +173,26 @@ sub ::file_end
else { push (@out,"$tmp\n"); }
}
push(@out,$initseg) if ($initseg);
+ if ($::elf) {
+ push(@out,"
+ .section \".note.gnu.property\", \"a\"
+ .p2align 2
+ .long 1f - 0f
+ .long 4f - 1f
+ .long 5
+0:
+ .asciz \"GNU\"
+1:
+ .p2align 2
+ .long 0xc0000002
+ .long 3f - 2f
+2:
+ .long 3
+3:
+ .p2align 2
+4:
+");
+ }
}
sub ::data_byte { push(@out,".byte\t".join(',',@_)."\n"); }
diff --git a/crypto/perlasm/x86masm.pl b/crypto/perlasm/x86masm.pl
index dffee762115f..2dcd3f79f6ed 100644
--- a/crypto/perlasm/x86masm.pl
+++ b/crypto/perlasm/x86masm.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
diff --git a/crypto/perlasm/x86nasm.pl b/crypto/perlasm/x86nasm.pl
index 4e64dad92d12..7017b88e80a3 100644
--- a/crypto/perlasm/x86nasm.pl
+++ b/crypto/perlasm/x86nasm.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
diff --git a/crypto/pkcs12/p12_add.c b/crypto/pkcs12/p12_add.c
index af184c86af5d..6fd4184af5a5 100644
--- a/crypto/pkcs12/p12_add.c
+++ b/crypto/pkcs12/p12_add.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,8 +9,11 @@
#include <stdio.h>
#include "internal/cryptlib.h"
+#include <openssl/core.h>
+#include <openssl/core_names.h>
#include <openssl/pkcs12.h>
#include "p12_local.h"
+#include "crypto/pkcs7/pk7_local.h"
/* Pack an object into an OCTET STRING and turn into a safebag */
@@ -21,16 +24,16 @@ PKCS12_SAFEBAG *PKCS12_item_pack_safebag(void *obj, const ASN1_ITEM *it,
PKCS12_SAFEBAG *safebag;
if ((bag = PKCS12_BAGS_new()) == NULL) {
- PKCS12err(PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
return NULL;
}
bag->type = OBJ_nid2obj(nid1);
if (!ASN1_item_pack(obj, it, &bag->value.octet)) {
- PKCS12err(PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
goto err;
}
if ((safebag = PKCS12_SAFEBAG_new()) == NULL) {
- PKCS12err(PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
goto err;
}
safebag->value.bag = bag;
@@ -48,17 +51,17 @@ PKCS7 *PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk)
PKCS7 *p7;
if ((p7 = PKCS7_new()) == NULL) {
- PKCS12err(PKCS12_F_PKCS12_PACK_P7DATA, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
return NULL;
}
p7->type = OBJ_nid2obj(NID_pkcs7_data);
if ((p7->d.data = ASN1_OCTET_STRING_new()) == NULL) {
- PKCS12err(PKCS12_F_PKCS12_PACK_P7DATA, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!ASN1_item_pack(sk, ASN1_ITEM_rptr(PKCS12_SAFEBAGS), &p7->d.data)) {
- PKCS12err(PKCS12_F_PKCS12_PACK_P7DATA, PKCS12_R_CANT_PACK_STRUCTURE);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CANT_PACK_STRUCTURE);
goto err;
}
return p7;
@@ -72,8 +75,7 @@ PKCS7 *PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk)
STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7)
{
if (!PKCS7_type_is_data(p7)) {
- PKCS12err(PKCS12_F_PKCS12_UNPACK_P7DATA,
- PKCS12_R_CONTENT_TYPE_NOT_DATA);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CONTENT_TYPE_NOT_DATA);
return NULL;
}
return ASN1_item_unpack(p7->d.data, ASN1_ITEM_rptr(PKCS12_SAFEBAGS));
@@ -81,67 +83,91 @@ STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7)
/* Turn a stack of SAFEBAGS into a PKCS#7 encrypted data ContentInfo */
-PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen,
- unsigned char *salt, int saltlen, int iter,
- STACK_OF(PKCS12_SAFEBAG) *bags)
+PKCS7 *PKCS12_pack_p7encdata_ex(int pbe_nid, const char *pass, int passlen,
+ unsigned char *salt, int saltlen, int iter,
+ STACK_OF(PKCS12_SAFEBAG) *bags,
+ OSSL_LIB_CTX *ctx, const char *propq)
{
PKCS7 *p7;
X509_ALGOR *pbe;
- const EVP_CIPHER *pbe_ciph;
+ const EVP_CIPHER *pbe_ciph = NULL;
+ EVP_CIPHER *pbe_ciph_fetch = NULL;
- if ((p7 = PKCS7_new()) == NULL) {
- PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, ERR_R_MALLOC_FAILURE);
+ if ((p7 = PKCS7_new_ex(ctx, propq)) == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (!PKCS7_set_type(p7, NID_pkcs7_encrypted)) {
- PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA,
- PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE);
goto err;
}
- pbe_ciph = EVP_get_cipherbynid(pbe_nid);
+ ERR_set_mark();
+ pbe_ciph = pbe_ciph_fetch = EVP_CIPHER_fetch(ctx, OBJ_nid2sn(pbe_nid), propq);
+ if (pbe_ciph == NULL)
+ pbe_ciph = EVP_get_cipherbynid(pbe_nid);
+ ERR_pop_to_mark();
- if (pbe_ciph)
- pbe = PKCS5_pbe2_set(pbe_ciph, iter, salt, saltlen);
- else
- pbe = PKCS5_pbe_set(pbe_nid, iter, salt, saltlen);
+ if (pbe_ciph != NULL) {
+ pbe = PKCS5_pbe2_set_iv_ex(pbe_ciph, iter, salt, saltlen, NULL, -1, ctx);
+ } else {
+ pbe = PKCS5_pbe_set_ex(pbe_nid, iter, salt, saltlen, ctx);
+ }
- if (!pbe) {
- PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, ERR_R_MALLOC_FAILURE);
+ if (pbe == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
goto err;
}
X509_ALGOR_free(p7->d.encrypted->enc_data->algorithm);
p7->d.encrypted->enc_data->algorithm = pbe;
ASN1_OCTET_STRING_free(p7->d.encrypted->enc_data->enc_data);
if (!(p7->d.encrypted->enc_data->enc_data =
- PKCS12_item_i2d_encrypt(pbe, ASN1_ITEM_rptr(PKCS12_SAFEBAGS), pass,
- passlen, bags, 1))) {
- PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, PKCS12_R_ENCRYPT_ERROR);
+ PKCS12_item_i2d_encrypt_ex(pbe, ASN1_ITEM_rptr(PKCS12_SAFEBAGS), pass,
+ passlen, bags, 1, ctx, propq))) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_ENCRYPT_ERROR);
goto err;
}
+ EVP_CIPHER_free(pbe_ciph_fetch);
return p7;
err:
PKCS7_free(p7);
+ EVP_CIPHER_free(pbe_ciph_fetch);
return NULL;
}
+PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen,
+ unsigned char *salt, int saltlen, int iter,
+ STACK_OF(PKCS12_SAFEBAG) *bags)
+{
+ return PKCS12_pack_p7encdata_ex(pbe_nid, pass, passlen, salt, saltlen,
+ iter, bags, NULL, NULL);
+}
+
STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass,
int passlen)
{
if (!PKCS7_type_is_encrypted(p7))
return NULL;
- return PKCS12_item_decrypt_d2i(p7->d.encrypted->enc_data->algorithm,
+ return PKCS12_item_decrypt_d2i_ex(p7->d.encrypted->enc_data->algorithm,
ASN1_ITEM_rptr(PKCS12_SAFEBAGS),
pass, passlen,
- p7->d.encrypted->enc_data->enc_data, 1);
+ p7->d.encrypted->enc_data->enc_data, 1,
+ p7->ctx.libctx, p7->ctx.propq);
+}
+
+PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey_ex(const PKCS12_SAFEBAG *bag,
+ const char *pass, int passlen,
+ OSSL_LIB_CTX *ctx, const char *propq)
+{
+ return PKCS8_decrypt_ex(bag->value.shkeybag, pass, passlen, ctx, propq);
}
PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(const PKCS12_SAFEBAG *bag,
const char *pass, int passlen)
{
- return PKCS8_decrypt(bag->value.shkeybag, pass, passlen);
+ return PKCS12_decrypt_skey_ex(bag, pass, passlen, NULL, NULL);
}
int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes)
@@ -154,11 +180,25 @@ int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes)
STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12)
{
+ STACK_OF(PKCS7) *p7s;
+ PKCS7 *p7;
+ int i;
+
if (!PKCS7_type_is_data(p12->authsafes)) {
- PKCS12err(PKCS12_F_PKCS12_UNPACK_AUTHSAFES,
- PKCS12_R_CONTENT_TYPE_NOT_DATA);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CONTENT_TYPE_NOT_DATA);
return NULL;
}
- return ASN1_item_unpack(p12->authsafes->d.data,
- ASN1_ITEM_rptr(PKCS12_AUTHSAFES));
+ p7s = ASN1_item_unpack(p12->authsafes->d.data,
+ ASN1_ITEM_rptr(PKCS12_AUTHSAFES));
+ if (p7s != NULL) {
+ for (i = 0; i < sk_PKCS7_num(p7s); i++) {
+ p7 = sk_PKCS7_value(p7s, i);
+ if (!ossl_pkcs7_ctx_propagate(p12->authsafes, p7))
+ goto err;
+ }
+ }
+ return p7s;
+err:
+ sk_PKCS7_free(p7s);
+ return NULL;
}
diff --git a/crypto/pkcs12/p12_asn.c b/crypto/pkcs12/p12_asn.c
index 88f145890cf6..aabbd38eefbe 100644
--- a/crypto/pkcs12/p12_asn.c
+++ b/crypto/pkcs12/p12_asn.c
@@ -1,7 +1,7 @@
/*
* Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/pkcs12/p12_attr.c b/crypto/pkcs12/p12_attr.c
index a958fdf3465e..da228336eb60 100644
--- a/crypto/pkcs12/p12_attr.c
+++ b/crypto/pkcs12/p12_attr.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -18,7 +18,7 @@ int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name,
int namelen)
{
if (X509at_add1_attr_by_NID(&bag->attrib, NID_localKeyID,
- V_ASN1_OCTET_STRING, name, namelen))
+ V_ASN1_OCTET_STRING, name, namelen) != NULL)
return 1;
else
return 0;
@@ -39,7 +39,7 @@ int PKCS12_add_friendlyname_asc(PKCS12_SAFEBAG *bag, const char *name,
int namelen)
{
if (X509at_add1_attr_by_NID(&bag->attrib, NID_friendlyName,
- MBSTRING_ASC, (unsigned char *)name, namelen))
+ MBSTRING_ASC, (unsigned char *)name, namelen) != NULL)
return 1;
else
return 0;
@@ -49,7 +49,7 @@ int PKCS12_add_friendlyname_utf8(PKCS12_SAFEBAG *bag, const char *name,
int namelen)
{
if (X509at_add1_attr_by_NID(&bag->attrib, NID_friendlyName,
- MBSTRING_UTF8, (unsigned char *)name, namelen))
+ MBSTRING_UTF8, (unsigned char *)name, namelen) != NULL)
return 1;
else
return 0;
@@ -59,7 +59,7 @@ int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag,
const unsigned char *name, int namelen)
{
if (X509at_add1_attr_by_NID(&bag->attrib, NID_friendlyName,
- MBSTRING_BMP, name, namelen))
+ MBSTRING_BMP, name, namelen) != NULL)
return 1;
else
return 0;
@@ -68,7 +68,25 @@ int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag,
int PKCS12_add_CSPName_asc(PKCS12_SAFEBAG *bag, const char *name, int namelen)
{
if (X509at_add1_attr_by_NID(&bag->attrib, NID_ms_csp_name,
- MBSTRING_ASC, (unsigned char *)name, namelen))
+ MBSTRING_ASC, (unsigned char *)name, namelen) != NULL)
+ return 1;
+ else
+ return 0;
+}
+
+int PKCS12_add1_attr_by_NID(PKCS12_SAFEBAG *bag, int nid, int type,
+ const unsigned char *bytes, int len)
+{
+ if (X509at_add1_attr_by_NID(&bag->attrib, nid, type, bytes, len) != NULL)
+ return 1;
+ else
+ return 0;
+}
+
+int PKCS12_add1_attr_by_txt(PKCS12_SAFEBAG *bag, const char *attrname, int type,
+ const unsigned char *bytes, int len)
+{
+ if (X509at_add1_attr_by_txt(&bag->attrib, attrname, type, bytes, len) != NULL)
return 1;
else
return 0;
diff --git a/crypto/pkcs12/p12_crpt.c b/crypto/pkcs12/p12_crpt.c
index feef9d1fc4cb..57d1caecfce7 100644
--- a/crypto/pkcs12/p12_crpt.c
+++ b/crypto/pkcs12/p12_crpt.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,6 +9,9 @@
#include <stdio.h>
#include "internal/cryptlib.h"
+#include <openssl/core.h>
+#include <openssl/core_names.h>
+#include "crypto/evp.h"
#include <openssl/pkcs12.h>
/* PKCS#12 PBE algorithms now in static table */
@@ -17,21 +20,16 @@ void PKCS12_PBE_add(void)
{
}
-int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
- ASN1_TYPE *param, const EVP_CIPHER *cipher,
- const EVP_MD *md, int en_de)
+int PKCS12_PBE_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md, int en_de,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
PBEPARAM *pbe;
int saltlen, iter, ret;
unsigned char *salt;
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
- int (*pkcs12_key_gen)(const char *pass, int passlen,
- unsigned char *salt, int slen,
- int id, int iter, int n,
- unsigned char *out,
- const EVP_MD *md_type);
-
- pkcs12_key_gen = PKCS12_key_gen_utf8;
+ unsigned char *piv = iv;
if (cipher == NULL)
return 0;
@@ -40,31 +38,48 @@ int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
pbe = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBEPARAM), param);
if (pbe == NULL) {
- PKCS12err(PKCS12_F_PKCS12_PBE_KEYIVGEN, PKCS12_R_DECODE_ERROR);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_DECODE_ERROR);
return 0;
}
- if (!pbe->iter)
+ if (pbe->iter == NULL)
iter = 1;
else
iter = ASN1_INTEGER_get(pbe->iter);
salt = pbe->salt->data;
saltlen = pbe->salt->length;
- if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_KEY_ID,
- iter, EVP_CIPHER_key_length(cipher), key, md)) {
- PKCS12err(PKCS12_F_PKCS12_PBE_KEYIVGEN, PKCS12_R_KEY_GEN_ERROR);
+ if (!PKCS12_key_gen_utf8_ex(pass, passlen, salt, saltlen, PKCS12_KEY_ID,
+ iter, EVP_CIPHER_get_key_length(cipher),
+ key, md,
+ libctx, propq)) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR);
PBEPARAM_free(pbe);
return 0;
}
- if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_IV_ID,
- iter, EVP_CIPHER_iv_length(cipher), iv, md)) {
- PKCS12err(PKCS12_F_PKCS12_PBE_KEYIVGEN, PKCS12_R_IV_GEN_ERROR);
- PBEPARAM_free(pbe);
- return 0;
+ if (EVP_CIPHER_get_iv_length(cipher) > 0) {
+ if (!PKCS12_key_gen_utf8_ex(pass, passlen, salt, saltlen, PKCS12_IV_ID,
+ iter, EVP_CIPHER_get_iv_length(cipher),
+ iv, md,
+ libctx, propq)) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_IV_GEN_ERROR);
+ PBEPARAM_free(pbe);
+ return 0;
+ }
+ } else {
+ piv = NULL;
}
PBEPARAM_free(pbe);
- ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, en_de);
+ ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, piv, en_de);
OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH);
OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH);
return ret;
}
+
+int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md, int en_de)
+{
+ return PKCS12_PBE_keyivgen_ex(ctx, pass, passlen, param, cipher, md, en_de,
+ NULL, NULL);
+}
+
diff --git a/crypto/pkcs12/p12_crt.c b/crypto/pkcs12/p12_crt.c
index bfcae3f697e9..00c71297463d 100644
--- a/crypto/pkcs12/p12_crt.c
+++ b/crypto/pkcs12/p12_crt.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -28,9 +28,10 @@ static int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid)
return 1;
}
-PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert,
- STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter,
- int mac_iter, int keytype)
+PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey,
+ X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
+ int iter, int mac_iter, int keytype,
+ OSSL_LIB_CTX *ctx, const char *propq)
{
PKCS12 *p12 = NULL;
STACK_OF(PKCS7) *safes = NULL;
@@ -41,21 +42,17 @@ PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *
unsigned int keyidlen = 0;
/* Set defaults */
- if (!nid_cert)
-#ifdef OPENSSL_NO_RC2
- nid_cert = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
-#else
- nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC;
-#endif
- if (!nid_key)
- nid_key = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
+ if (nid_cert == NID_undef)
+ nid_cert = NID_aes_256_cbc;
+ if (nid_key == NID_undef)
+ nid_key = NID_aes_256_cbc;
if (!iter)
iter = PKCS12_DEFAULT_ITER;
if (!mac_iter)
- mac_iter = 1;
+ mac_iter = PKCS12_DEFAULT_ITER;
- if (!pkey && !cert && !ca) {
- PKCS12err(PKCS12_F_PKCS12_CREATE, PKCS12_R_INVALID_NULL_ARGUMENT);
+ if (pkey == NULL && cert == NULL && ca == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_INVALID_NULL_ARGUMENT);
return NULL;
}
@@ -80,14 +77,16 @@ PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *
goto err;
}
- if (bags && !PKCS12_add_safe(&safes, bags, nid_cert, iter, pass))
+ if (bags && !PKCS12_add_safe_ex(&safes, bags, nid_cert, iter, pass,
+ ctx, propq))
goto err;
sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
bags = NULL;
if (pkey) {
- bag = PKCS12_add_key(&bags, pkey, keytype, iter, nid_key, pass);
+ bag = PKCS12_add_key_ex(&bags, pkey, keytype, iter, nid_key, pass,
+ ctx, propq);
if (!bag)
goto err;
@@ -109,9 +108,9 @@ PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *
sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
bags = NULL;
- p12 = PKCS12_add_safes(safes, 0);
+ p12 = PKCS12_add_safes_ex(safes, 0, ctx, propq);
- if (!p12)
+ if (p12 == NULL)
goto err;
sk_PKCS7_pop_free(safes, PKCS7_free);
@@ -132,6 +131,14 @@ PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *
}
+PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert,
+ STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter,
+ int mac_iter, int keytype)
+{
+ return PKCS12_create_ex(pass, name, pkey, cert, ca, nid_key, nid_cert,
+ iter, mac_iter, keytype, NULL, NULL);
+}
+
PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
{
PKCS12_SAFEBAG *bag = NULL;
@@ -169,9 +176,10 @@ PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
}
-PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
- EVP_PKEY *key, int key_usage, int iter,
- int nid_key, const char *pass)
+PKCS12_SAFEBAG *PKCS12_add_key_ex(STACK_OF(PKCS12_SAFEBAG) **pbags,
+ EVP_PKEY *key, int key_usage, int iter,
+ int nid_key, const char *pass,
+ OSSL_LIB_CTX *ctx, const char *propq)
{
PKCS12_SAFEBAG *bag = NULL;
@@ -183,8 +191,8 @@ PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
if (key_usage && !PKCS8_add_keyusage(p8, key_usage))
goto err;
if (nid_key != -1) {
- bag = PKCS12_SAFEBAG_create_pkcs8_encrypt(nid_key, pass, -1, NULL, 0,
- iter, p8);
+ bag = PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(nid_key, pass, -1, NULL, 0,
+ iter, p8, ctx, propq);
PKCS8_PRIV_KEY_INFO_free(p8);
} else
bag = PKCS12_SAFEBAG_create0_p8inf(p8);
@@ -203,19 +211,45 @@ PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
}
-int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
- int nid_safe, int iter, const char *pass)
+PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
+ EVP_PKEY *key, int key_usage, int iter,
+ int nid_key, const char *pass)
+{
+ return PKCS12_add_key_ex(pbags, key, key_usage, iter, nid_key, pass,
+ NULL, NULL);
+}
+
+PKCS12_SAFEBAG *PKCS12_add_secret(STACK_OF(PKCS12_SAFEBAG) **pbags,
+ int nid_type, const unsigned char *value, int len)
+{
+ PKCS12_SAFEBAG *bag = NULL;
+
+ /* Add secret, storing the value as an octet string */
+ if ((bag = PKCS12_SAFEBAG_create_secret(nid_type, V_ASN1_OCTET_STRING, value, len)) == NULL)
+ goto err;
+
+ if (!pkcs12_add_bag(pbags, bag))
+ goto err;
+
+ return bag;
+ err:
+ PKCS12_SAFEBAG_free(bag);
+ return NULL;
+}
+
+int PKCS12_add_safe_ex(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
+ int nid_safe, int iter, const char *pass,
+ OSSL_LIB_CTX *ctx, const char *propq)
{
PKCS7 *p7 = NULL;
int free_safes = 0;
- if (!*psafes) {
+ if (*psafes == NULL) {
*psafes = sk_PKCS7_new_null();
- if (!*psafes)
+ if (*psafes == NULL)
return 0;
free_safes = 1;
- } else
- free_safes = 0;
+ }
if (nid_safe == 0)
#ifdef OPENSSL_NO_RC2
@@ -227,8 +261,8 @@ int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
if (nid_safe == -1)
p7 = PKCS12_pack_p7data(bags);
else
- p7 = PKCS12_pack_p7encdata(nid_safe, pass, -1, NULL, 0, iter, bags);
- if (!p7)
+ p7 = PKCS12_pack_p7encdata_ex(nid_safe, pass, -1, NULL, 0, iter, bags, ctx, propq);
+ if (p7 == NULL)
goto err;
if (!sk_PKCS7_push(*psafes, p7))
@@ -243,22 +277,27 @@ int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
}
PKCS7_free(p7);
return 0;
+}
+int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
+ int nid_safe, int iter, const char *pass)
+{
+ return PKCS12_add_safe_ex(psafes, bags, nid_safe, iter, pass, NULL, NULL);
}
static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
PKCS12_SAFEBAG *bag)
{
- int free_bags;
- if (!pbags)
+ int free_bags = 0;
+
+ if (pbags == NULL)
return 1;
- if (!*pbags) {
+ if (*pbags == NULL) {
*pbags = sk_PKCS12_SAFEBAG_new_null();
- if (!*pbags)
+ if (*pbags == NULL)
return 0;
free_bags = 1;
- } else
- free_bags = 0;
+ }
if (!sk_PKCS12_SAFEBAG_push(*pbags, bag)) {
if (free_bags) {
@@ -272,14 +311,15 @@ static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
}
-PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int nid_p7)
+PKCS12 *PKCS12_add_safes_ex(STACK_OF(PKCS7) *safes, int nid_p7,
+ OSSL_LIB_CTX *ctx, const char *propq)
{
PKCS12 *p12;
+
if (nid_p7 <= 0)
nid_p7 = NID_pkcs7_data;
- p12 = PKCS12_init(nid_p7);
-
- if (!p12)
+ p12 = PKCS12_init_ex(nid_p7, ctx, propq);
+ if (p12 == NULL)
return NULL;
if (!PKCS12_pack_authsafes(p12, safes)) {
@@ -290,3 +330,8 @@ PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int nid_p7)
return p12;
}
+
+PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int nid_p7)
+{
+ return PKCS12_add_safes_ex(safes, nid_p7, NULL, NULL);
+}
diff --git a/crypto/pkcs12/p12_decr.c b/crypto/pkcs12/p12_decr.c
index 3c860584e80b..a5adafa954a3 100644
--- a/crypto/pkcs12/p12_decr.c
+++ b/crypto/pkcs12/p12_decr.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,48 +10,72 @@
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/pkcs12.h>
-
-/* Define this to dump decrypted output to files called DERnnn */
-/*
- * #define OPENSSL_DEBUG_DECRYPT
- */
+#include <openssl/trace.h>
/*
* Encrypt/Decrypt a buffer based on password and algor, result in a
* OPENSSL_malloc'ed buffer
*/
-unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor,
- const char *pass, int passlen,
- const unsigned char *in, int inlen,
- unsigned char **data, int *datalen, int en_de)
+unsigned char *PKCS12_pbe_crypt_ex(const X509_ALGOR *algor,
+ const char *pass, int passlen,
+ const unsigned char *in, int inlen,
+ unsigned char **data, int *datalen, int en_de,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
unsigned char *out = NULL;
int outlen, i;
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+ int max_out_len, mac_len = 0;
if (ctx == NULL) {
- PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
goto err;
}
- /* Decrypt data */
- if (!EVP_PBE_CipherInit(algor->algorithm, pass, passlen,
- algor->parameter, ctx, en_de)) {
- PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT,
- PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR);
+ /* Process data */
+ if (!EVP_PBE_CipherInit_ex(algor->algorithm, pass, passlen,
+ algor->parameter, ctx, en_de, libctx, propq))
goto err;
+
+ /*
+ * GOST algorithm specifics:
+ * OMAC algorithm calculate and encrypt MAC of the encrypted objects
+ * It's appended to encrypted text on encrypting
+ * MAC should be processed on decrypting separately from plain text
+ */
+ max_out_len = inlen + EVP_CIPHER_CTX_get_block_size(ctx);
+ if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx))
+ & EVP_CIPH_FLAG_CIPHER_WITH_MAC) != 0) {
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_TLS1_AAD, 0, &mac_len) < 0) {
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
+ max_out_len += mac_len;
+ } else {
+ if (inlen < mac_len) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_UNSUPPORTED_PKCS12_MODE);
+ goto err;
+ }
+ inlen -= mac_len;
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
+ (int)mac_len, (unsigned char *)in+inlen) < 0) {
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
}
- if ((out = OPENSSL_malloc(inlen + EVP_CIPHER_CTX_block_size(ctx)))
- == NULL) {
- PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT, ERR_R_MALLOC_FAILURE);
+ if ((out = OPENSSL_malloc(max_out_len)) == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EVP_CipherUpdate(ctx, out, &i, in, inlen)) {
OPENSSL_free(out);
out = NULL;
- PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_EVP_LIB);
goto err;
}
@@ -59,11 +83,25 @@ unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor,
if (!EVP_CipherFinal_ex(ctx, out + i, &i)) {
OPENSSL_free(out);
out = NULL;
- PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT,
- PKCS12_R_PKCS12_CIPHERFINAL_ERROR);
+ ERR_raise_data(ERR_LIB_PKCS12, PKCS12_R_PKCS12_CIPHERFINAL_ERROR,
+ passlen == 0 ? "empty password"
+ : "maybe wrong password");
goto err;
}
outlen += i;
+ if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx))
+ & EVP_CIPH_FLAG_CIPHER_WITH_MAC) != 0) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG,
+ (int)mac_len, out+outlen) < 0) {
+ OPENSSL_free(out);
+ out = NULL;
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ outlen += mac_len;
+ }
+ }
if (datalen)
*datalen = outlen;
if (data)
@@ -74,74 +112,85 @@ unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor,
}
+unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor,
+ const char *pass, int passlen,
+ const unsigned char *in, int inlen,
+ unsigned char **data, int *datalen, int en_de)
+{
+ return PKCS12_pbe_crypt_ex(algor, pass, passlen, in, inlen, data, datalen,
+ en_de, NULL, NULL);
+}
+
/*
* Decrypt an OCTET STRING and decode ASN1 structure if zbuf set zero buffer
* after use.
*/
-void *PKCS12_item_decrypt_d2i(const X509_ALGOR *algor, const ASN1_ITEM *it,
- const char *pass, int passlen,
- const ASN1_OCTET_STRING *oct, int zbuf)
+void *PKCS12_item_decrypt_d2i_ex(const X509_ALGOR *algor, const ASN1_ITEM *it,
+ const char *pass, int passlen,
+ const ASN1_OCTET_STRING *oct, int zbuf,
+ OSSL_LIB_CTX *libctx,
+ const char *propq)
{
- unsigned char *out;
+ unsigned char *out = NULL;
const unsigned char *p;
void *ret;
- int outlen;
+ int outlen = 0;
- if (!PKCS12_pbe_crypt(algor, pass, passlen, oct->data, oct->length,
- &out, &outlen, 0)) {
- PKCS12err(PKCS12_F_PKCS12_ITEM_DECRYPT_D2I,
- PKCS12_R_PKCS12_PBE_CRYPT_ERROR);
+ if (!PKCS12_pbe_crypt_ex(algor, pass, passlen, oct->data, oct->length,
+ &out, &outlen, 0, libctx, propq))
return NULL;
- }
p = out;
-#ifdef OPENSSL_DEBUG_DECRYPT
- {
- FILE *op;
-
- char fname[30];
- static int fnm = 1;
- sprintf(fname, "DER%d", fnm++);
- op = fopen(fname, "wb");
- fwrite(p, 1, outlen, op);
- fclose(op);
- }
-#endif
+ OSSL_TRACE_BEGIN(PKCS12_DECRYPT) {
+ BIO_printf(trc_out, "\n");
+ BIO_dump(trc_out, out, outlen);
+ BIO_printf(trc_out, "\n");
+ } OSSL_TRACE_END(PKCS12_DECRYPT);
ret = ASN1_item_d2i(NULL, &p, outlen, it);
if (zbuf)
OPENSSL_cleanse(out, outlen);
if (!ret)
- PKCS12err(PKCS12_F_PKCS12_ITEM_DECRYPT_D2I, PKCS12_R_DECODE_ERROR);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_DECODE_ERROR);
OPENSSL_free(out);
return ret;
}
+void *PKCS12_item_decrypt_d2i(const X509_ALGOR *algor, const ASN1_ITEM *it,
+ const char *pass, int passlen,
+ const ASN1_OCTET_STRING *oct, int zbuf)
+{
+ return PKCS12_item_decrypt_d2i_ex(algor, it, pass, passlen, oct, zbuf,
+ NULL, NULL);
+}
+
/*
* Encode ASN1 structure and encrypt, return OCTET STRING if zbuf set zero
* encoding.
*/
-ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor,
- const ASN1_ITEM *it,
- const char *pass, int passlen,
- void *obj, int zbuf)
+ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt_ex(X509_ALGOR *algor,
+ const ASN1_ITEM *it,
+ const char *pass, int passlen,
+ void *obj, int zbuf,
+ OSSL_LIB_CTX *ctx,
+ const char *propq)
{
ASN1_OCTET_STRING *oct = NULL;
unsigned char *in = NULL;
int inlen;
if ((oct = ASN1_OCTET_STRING_new()) == NULL) {
- PKCS12err(PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
goto err;
}
inlen = ASN1_item_i2d(obj, &in, it);
if (!in) {
- PKCS12err(PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT, PKCS12_R_ENCODE_ERROR);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_ENCODE_ERROR);
goto err;
}
- if (!PKCS12_pbe_crypt(algor, pass, passlen, in, inlen, &oct->data,
- &oct->length, 1)) {
- PKCS12err(PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT, PKCS12_R_ENCRYPT_ERROR);
+ if (!PKCS12_pbe_crypt_ex(algor, pass, passlen, in, inlen, &oct->data,
+ &oct->length, 1, ctx, propq)) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_ENCRYPT_ERROR);
OPENSSL_free(in);
goto err;
}
@@ -153,3 +202,11 @@ ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor,
ASN1_OCTET_STRING_free(oct);
return NULL;
}
+
+ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor,
+ const ASN1_ITEM *it,
+ const char *pass, int passlen,
+ void *obj, int zbuf)
+{
+ return PKCS12_item_i2d_encrypt_ex(algor, it, pass, passlen, obj, zbuf, NULL, NULL);
+}
diff --git a/crypto/pkcs12/p12_init.c b/crypto/pkcs12/p12_init.c
index 7ecc29ec0ce0..45aa2f9154b9 100644
--- a/crypto/pkcs12/p12_init.c
+++ b/crypto/pkcs12/p12_init.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,30 +10,38 @@
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/pkcs12.h>
+#include "crypto/pkcs7.h"
#include "p12_local.h"
/* Initialise a PKCS12 structure to take data */
-PKCS12 *PKCS12_init(int mode)
+PKCS12 *PKCS12_init_ex(int mode, OSSL_LIB_CTX *ctx, const char *propq)
{
PKCS12 *pkcs12;
if ((pkcs12 = PKCS12_new()) == NULL) {
- PKCS12err(PKCS12_F_PKCS12_INIT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (!ASN1_INTEGER_set(pkcs12->version, 3))
goto err;
pkcs12->authsafes->type = OBJ_nid2obj(mode);
+
+ ossl_pkcs7_set0_libctx(pkcs12->authsafes, ctx);
+ if (!ossl_pkcs7_set1_propq(pkcs12->authsafes, propq)) {
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
switch (mode) {
case NID_pkcs7_data:
if ((pkcs12->authsafes->d.data = ASN1_OCTET_STRING_new()) == NULL) {
- PKCS12err(PKCS12_F_PKCS12_INIT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
goto err;
}
break;
default:
- PKCS12err(PKCS12_F_PKCS12_INIT, PKCS12_R_UNSUPPORTED_PKCS12_MODE);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_UNSUPPORTED_PKCS12_MODE);
goto err;
}
return pkcs12;
@@ -42,3 +50,9 @@ PKCS12 *PKCS12_init(int mode)
PKCS12_free(pkcs12);
return NULL;
}
+
+PKCS12 *PKCS12_init(int mode)
+{
+ return PKCS12_init_ex(mode, NULL, NULL);
+}
+
diff --git a/crypto/pkcs12/p12_key.c b/crypto/pkcs12/p12_key.c
index 03eda2664251..41a2d7293e91 100644
--- a/crypto/pkcs12/p12_key.c
+++ b/crypto/pkcs12/p12_key.c
@@ -1,7 +1,7 @@
/*
* Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,173 +11,128 @@
#include "internal/cryptlib.h"
#include <openssl/pkcs12.h>
#include <openssl/bn.h>
+#include <openssl/trace.h>
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#include "internal/provider.h"
-/* Uncomment out this line to get debugging info about key generation */
-/*
- * #define OPENSSL_DEBUG_KEYGEN
- */
-#ifdef OPENSSL_DEBUG_KEYGEN
-# include <openssl/bio.h>
-extern BIO *bio_err;
-void h__dump(unsigned char *p, int len);
-#endif
-
-/* PKCS12 compatible key/IV generation */
-#ifndef min
-# define min(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
- int saltlen, int id, int iter, int n,
- unsigned char *out, const EVP_MD *md_type)
+int PKCS12_key_gen_asc_ex(const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type,
+ OSSL_LIB_CTX *ctx, const char *propq)
{
int ret;
unsigned char *unipass;
int uniplen;
- if (!pass) {
+ if (pass == NULL) {
unipass = NULL;
uniplen = 0;
} else if (!OPENSSL_asc2uni(pass, passlen, &unipass, &uniplen)) {
- PKCS12err(PKCS12_F_PKCS12_KEY_GEN_ASC, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
return 0;
}
- ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen,
- id, iter, n, out, md_type);
- if (ret <= 0)
- return 0;
+ ret = PKCS12_key_gen_uni_ex(unipass, uniplen, salt, saltlen, id, iter,
+ n, out, md_type, ctx, propq);
OPENSSL_clear_free(unipass, uniplen);
- return ret;
+ return ret > 0;
}
-int PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt,
- int saltlen, int id, int iter, int n,
- unsigned char *out, const EVP_MD *md_type)
+int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type)
+{
+ return PKCS12_key_gen_asc_ex(pass, passlen, salt, saltlen, id, iter, n,
+ out, md_type, NULL, NULL);
+}
+
+int PKCS12_key_gen_utf8_ex(const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type,
+ OSSL_LIB_CTX *ctx, const char *propq)
{
int ret;
unsigned char *unipass;
int uniplen;
- if (!pass) {
+ if (pass == NULL) {
unipass = NULL;
uniplen = 0;
} else if (!OPENSSL_utf82uni(pass, passlen, &unipass, &uniplen)) {
- PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UTF8, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
return 0;
}
- ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen,
- id, iter, n, out, md_type);
- if (ret <= 0)
- return 0;
+ ret = PKCS12_key_gen_uni_ex(unipass, uniplen, salt, saltlen, id, iter,
+ n, out, md_type, ctx, propq);
OPENSSL_clear_free(unipass, uniplen);
- return ret;
+ return ret > 0;
}
-int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
- int saltlen, int id, int iter, int n,
- unsigned char *out, const EVP_MD *md_type)
+int PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type)
{
- unsigned char *B = NULL, *D = NULL, *I = NULL, *p = NULL, *Ai = NULL;
- int Slen, Plen, Ilen;
- int i, j, u, v;
- int ret = 0;
- EVP_MD_CTX *ctx = NULL;
-#ifdef OPENSSL_DEBUG_KEYGEN
- unsigned char *tmpout = out;
- int tmpn = n;
-#endif
+ return PKCS12_key_gen_utf8_ex(pass, passlen, salt, saltlen, id, iter, n,
+ out, md_type, NULL, NULL);
+}
- ctx = EVP_MD_CTX_new();
- if (ctx == NULL)
- goto err;
+int PKCS12_key_gen_uni_ex(unsigned char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ int res = 0;
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *ctx;
+ OSSL_PARAM params[6], *p = params;
+
+ if (n <= 0)
+ return 0;
-#ifdef OPENSSL_DEBUG_KEYGEN
- fprintf(stderr, "KEYGEN DEBUG\n");
- fprintf(stderr, "ID %d, ITER %d\n", id, iter);
- fprintf(stderr, "Password (length %d):\n", passlen);
- h__dump(pass, passlen);
- fprintf(stderr, "Salt (length %d):\n", saltlen);
- h__dump(salt, saltlen);
-#endif
- v = EVP_MD_block_size(md_type);
- u = EVP_MD_size(md_type);
- if (u <= 0 || v <= 0)
- goto err;
- D = OPENSSL_malloc(v);
- Ai = OPENSSL_malloc(u);
- B = OPENSSL_malloc(v + 1);
- Slen = v * ((saltlen + v - 1) / v);
- if (passlen)
- Plen = v * ((passlen + v - 1) / v);
- else
- Plen = 0;
- Ilen = Slen + Plen;
- I = OPENSSL_malloc(Ilen);
- if (D == NULL || Ai == NULL || B == NULL || I == NULL)
- goto err;
- for (i = 0; i < v; i++)
- D[i] = id;
- p = I;
- for (i = 0; i < Slen; i++)
- *p++ = salt[i % saltlen];
- for (i = 0; i < Plen; i++)
- *p++ = pass[i % passlen];
- for (;;) {
- if (!EVP_DigestInit_ex(ctx, md_type, NULL)
- || !EVP_DigestUpdate(ctx, D, v)
- || !EVP_DigestUpdate(ctx, I, Ilen)
- || !EVP_DigestFinal_ex(ctx, Ai, NULL))
- goto err;
- for (j = 1; j < iter; j++) {
- if (!EVP_DigestInit_ex(ctx, md_type, NULL)
- || !EVP_DigestUpdate(ctx, Ai, u)
- || !EVP_DigestFinal_ex(ctx, Ai, NULL))
- goto err;
- }
- memcpy(out, Ai, min(n, u));
- if (u >= n) {
-#ifdef OPENSSL_DEBUG_KEYGEN
- fprintf(stderr, "Output KEY (length %d)\n", tmpn);
- h__dump(tmpout, tmpn);
-#endif
- ret = 1;
- goto end;
- }
- n -= u;
- out += u;
- for (j = 0; j < v; j++)
- B[j] = Ai[j % u];
- for (j = 0; j < Ilen; j += v) {
- int k;
- unsigned char *Ij = I + j;
- uint16_t c = 1;
+ kdf = EVP_KDF_fetch(libctx, "PKCS12KDF", propq);
+ if (kdf == NULL)
+ return 0;
+ ctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+ if (ctx == NULL)
+ return 0;
- /* Work out Ij = Ij + B + 1 */
- for (k = v - 1; k >= 0; k--) {
- c += Ij[k] + B[k];
- Ij[k] = (unsigned char)c;
- c >>= 8;
- }
- }
- }
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ (char *)EVP_MD_get0_name(md_type),
+ 0);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
+ pass, passlen);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ salt, saltlen);
+ *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_PKCS12_ID, &id);
+ *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_ITER, &iter);
+ *p = OSSL_PARAM_construct_end();
- err:
- PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI, ERR_R_MALLOC_FAILURE);
+ OSSL_TRACE_BEGIN(PKCS12_KEYGEN) {
+ BIO_printf(trc_out, "PKCS12_key_gen_uni_ex(): ID %d, ITER %d\n", id, iter);
+ BIO_printf(trc_out, "Password (length %d):\n", passlen);
+ BIO_hex_string(trc_out, 0, passlen, pass, passlen);
+ BIO_printf(trc_out, "\n");
+ BIO_printf(trc_out, "Salt (length %d):\n", saltlen);
+ BIO_hex_string(trc_out, 0, saltlen, salt, saltlen);
+ BIO_printf(trc_out, "\n");
+ } OSSL_TRACE_END(PKCS12_KEYGEN);
- end:
- OPENSSL_free(Ai);
- OPENSSL_free(B);
- OPENSSL_free(D);
- OPENSSL_free(I);
- EVP_MD_CTX_free(ctx);
- return ret;
+ if (EVP_KDF_derive(ctx, out, (size_t)n, params)) {
+ res = 1;
+ OSSL_TRACE_BEGIN(PKCS12_KEYGEN) {
+ BIO_printf(trc_out, "Output KEY (length %d)\n", n);
+ BIO_hex_string(trc_out, 0, n, out, n);
+ BIO_printf(trc_out, "\n");
+ } OSSL_TRACE_END(PKCS12_KEYGEN);
+ }
+ EVP_KDF_CTX_free(ctx);
+ return res;
}
-#ifdef OPENSSL_DEBUG_KEYGEN
-void h__dump(unsigned char *p, int len)
+int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type)
{
- for (; len--; p++)
- fprintf(stderr, "%02X", *p);
- fprintf(stderr, "\n");
+ return PKCS12_key_gen_uni_ex(pass, passlen, salt, saltlen, id, iter, n, out, md_type, NULL, NULL);
}
-#endif
diff --git a/crypto/pkcs12/p12_kiss.c b/crypto/pkcs12/p12_kiss.c
index 7ab98385a7b0..229b34cf6429 100644
--- a/crypto/pkcs12/p12_kiss.c
+++ b/crypto/pkcs12/p12_kiss.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,6 +10,7 @@
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/pkcs12.h>
+#include "crypto/x509.h" /* for ossl_x509_add_cert_new() */
/* Simplified PKCS#12 routines */
@@ -25,8 +26,8 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
/*
* Parse and decrypt a PKCS#12 structure returning user key, user cert and
* other (CA) certs. Note either ca should be NULL, *ca should be NULL, or it
- * should point to a valid STACK structure. pkey and cert can be passed
- * uninitialised.
+ * should point to a valid STACK structure. pkey and/or cert may be NULL;
+ * if non-NULL the variables they point to can be passed uninitialised.
*/
int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
@@ -35,16 +36,15 @@ int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
STACK_OF(X509) *ocerts = NULL;
X509 *x = NULL;
- if (pkey)
+ if (pkey != NULL)
*pkey = NULL;
- if (cert)
+ if (cert != NULL)
*cert = NULL;
/* Check for NULL PKCS12 structure */
- if (!p12) {
- PKCS12err(PKCS12_F_PKCS12_PARSE,
- PKCS12_R_INVALID_NULL_PKCS12_POINTER);
+ if (p12 == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_INVALID_NULL_PKCS12_POINTER);
return 0;
}
@@ -57,66 +57,70 @@ int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
* password are two different things...
*/
- if (!pass || !*pass) {
- if (PKCS12_verify_mac(p12, NULL, 0))
+ if (pass == NULL || *pass == '\0') {
+ if (!PKCS12_mac_present(p12)
+ || PKCS12_verify_mac(p12, NULL, 0))
pass = NULL;
else if (PKCS12_verify_mac(p12, "", 0))
pass = "";
else {
- PKCS12err(PKCS12_F_PKCS12_PARSE, PKCS12_R_MAC_VERIFY_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE);
goto err;
}
} else if (!PKCS12_verify_mac(p12, pass, -1)) {
- PKCS12err(PKCS12_F_PKCS12_PARSE, PKCS12_R_MAC_VERIFY_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE);
goto err;
}
- /* Allocate stack for other certificates */
- ocerts = sk_X509_new_null();
-
- if (!ocerts) {
- PKCS12err(PKCS12_F_PKCS12_PARSE, ERR_R_MALLOC_FAILURE);
+ /* If needed, allocate stack for other certificates */
+ if ((cert != NULL || ca != NULL)
+ && (ocerts = sk_X509_new_null()) == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!parse_pk12(p12, pass, -1, pkey, ocerts)) {
- PKCS12err(PKCS12_F_PKCS12_PARSE, PKCS12_R_PARSE_ERROR);
+ int err = ERR_peek_last_error();
+
+ if (ERR_GET_LIB(err) != ERR_LIB_EVP
+ && ERR_GET_REASON(err) != EVP_R_UNSUPPORTED_ALGORITHM)
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_PARSE_ERROR);
goto err;
}
- while ((x = sk_X509_pop(ocerts))) {
- if (pkey && *pkey && cert && !*cert) {
+ /* Split the certs in ocerts over *cert and *ca as far as requested */
+ while ((x = sk_X509_shift(ocerts)) != NULL) {
+ if (pkey != NULL && *pkey != NULL
+ && cert != NULL && *cert == NULL) {
+ int match;
+
ERR_set_mark();
- if (X509_check_private_key(x, *pkey)) {
+ match = X509_check_private_key(x, *pkey);
+ ERR_pop_to_mark();
+ if (match) {
*cert = x;
- x = NULL;
+ continue;
}
- ERR_pop_to_mark();
}
- if (ca && x) {
- if (!*ca)
- *ca = sk_X509_new_null();
- if (!*ca)
+ if (ca != NULL) {
+ if (!ossl_x509_add_cert_new(ca, x, X509_ADD_FLAG_DEFAULT))
goto err;
- if (!sk_X509_push(*ca, x))
- goto err;
- x = NULL;
+ continue;
}
X509_free(x);
}
-
- sk_X509_pop_free(ocerts, X509_free);
+ sk_X509_free(ocerts);
return 1;
err:
- if (pkey) {
+ if (pkey != NULL) {
EVP_PKEY_free(*pkey);
*pkey = NULL;
}
- if (cert) {
+ if (cert != NULL) {
X509_free(*cert);
*cert = NULL;
}
@@ -128,6 +132,7 @@ int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
/* Parse the outer PKCS#12 structure */
+/* pkey and/or ocerts may be NULL */
static int parse_pk12(PKCS12 *p12, const char *pass, int passlen,
EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
{
@@ -162,6 +167,7 @@ static int parse_pk12(PKCS12 *p12, const char *pass, int passlen,
return 1;
}
+/* pkey and/or ocerts may be NULL */
static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
{
@@ -174,6 +180,7 @@ static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
return 1;
}
+/* pkey and/or ocerts may be NULL */
static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
{
@@ -191,7 +198,7 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
switch (PKCS12_SAFEBAG_get_nid(bag)) {
case NID_keyBag:
- if (!pkey || *pkey)
+ if (pkey == NULL || *pkey != NULL)
return 1;
*pkey = EVP_PKCS82PKEY(PKCS12_SAFEBAG_get0_p8inf(bag));
if (*pkey == NULL)
@@ -199,7 +206,7 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
break;
case NID_pkcs8ShroudedKeyBag:
- if (!pkey || *pkey)
+ if (pkey == NULL || *pkey != NULL)
return 1;
if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL)
return 0;
@@ -210,7 +217,8 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
break;
case NID_certBag:
- if (PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate)
+ if (ocerts == NULL
+ || PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate)
return 1;
if ((x509 = PKCS12_SAFEBAG_get1_cert(bag)) == NULL)
return 0;
@@ -221,6 +229,7 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
if (fname) {
int len, r;
unsigned char *data;
+
len = ASN1_STRING_to_UTF8(&data, fname);
if (len >= 0) {
r = X509_alias_set1(x509, data, len);
diff --git a/crypto/pkcs12/p12_local.h b/crypto/pkcs12/p12_local.h
index 0b52f1e1fed9..acaa27b193fa 100644
--- a/crypto/pkcs12/p12_local.h
+++ b/crypto/pkcs12/p12_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/pkcs12/p12_mutl.c b/crypto/pkcs12/p12_mutl.c
index 3658003fe598..afdb8d688ba3 100644
--- a/crypto/pkcs12/p12_mutl.c
+++ b/crypto/pkcs12/p12_mutl.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * HMAC low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/crypto.h>
@@ -76,57 +82,75 @@ static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
const EVP_MD *md_type))
{
int ret = 0;
- const EVP_MD *md_type;
+ const EVP_MD *md;
+ EVP_MD *md_fetch;
HMAC_CTX *hmac = NULL;
unsigned char key[EVP_MAX_MD_SIZE], *salt;
int saltlen, iter;
+ char md_name[80];
int md_size = 0;
- int md_type_nid;
+ int md_nid;
const X509_ALGOR *macalg;
const ASN1_OBJECT *macoid;
- if (pkcs12_key_gen == NULL)
- pkcs12_key_gen = PKCS12_key_gen_utf8;
-
if (!PKCS7_type_is_data(p12->authsafes)) {
- PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_CONTENT_TYPE_NOT_DATA);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CONTENT_TYPE_NOT_DATA);
return 0;
}
salt = p12->mac->salt->data;
saltlen = p12->mac->salt->length;
- if (!p12->mac->iter)
+ if (p12->mac->iter == NULL)
iter = 1;
else
iter = ASN1_INTEGER_get(p12->mac->iter);
X509_SIG_get0(p12->mac->dinfo, &macalg, NULL);
X509_ALGOR_get0(&macoid, NULL, NULL, macalg);
- if ((md_type = EVP_get_digestbyobj(macoid)) == NULL) {
- PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_UNKNOWN_DIGEST_ALGORITHM);
+ if (OBJ_obj2txt(md_name, sizeof(md_name), macoid, 0) < 0)
+ return 0;
+ md = md_fetch = EVP_MD_fetch(p12->authsafes->ctx.libctx, md_name,
+ p12->authsafes->ctx.propq);
+ if (md == NULL)
+ md = EVP_get_digestbynid(OBJ_obj2nid(macoid));
+
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_UNKNOWN_DIGEST_ALGORITHM);
return 0;
}
- md_size = EVP_MD_size(md_type);
- md_type_nid = EVP_MD_type(md_type);
+ md_size = EVP_MD_get_size(md);
+ md_nid = EVP_MD_get_type(md);
if (md_size < 0)
- return 0;
- if ((md_type_nid == NID_id_GostR3411_94
- || md_type_nid == NID_id_GostR3411_2012_256
- || md_type_nid == NID_id_GostR3411_2012_512)
+ goto err;
+ if ((md_nid == NID_id_GostR3411_94
+ || md_nid == NID_id_GostR3411_2012_256
+ || md_nid == NID_id_GostR3411_2012_512)
&& ossl_safe_getenv("LEGACY_GOST_PKCS12") == NULL) {
md_size = TK26_MAC_KEY_LEN;
if (!pkcs12_gen_gost_mac_key(pass, passlen, salt, saltlen, iter,
- md_size, key, md_type)) {
- PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_KEY_GEN_ERROR);
+ md_size, key, md)) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR);
goto err;
}
- } else
- if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_MAC_ID,
- iter, md_size, key, md_type)) {
- PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_KEY_GEN_ERROR);
- goto err;
+ } else {
+ if (pkcs12_key_gen != NULL) {
+ if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_MAC_ID,
+ iter, md_size, key, md)) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR);
+ goto err;
+ }
+ } else {
+ /* Default to UTF-8 password */
+ if (!PKCS12_key_gen_utf8_ex(pass, passlen, salt, saltlen, PKCS12_MAC_ID,
+ iter, md_size, key, md,
+ p12->authsafes->ctx.libctx,
+ p12->authsafes->ctx.propq)) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR);
+ goto err;
+ }
+ }
}
if ((hmac = HMAC_CTX_new()) == NULL
- || !HMAC_Init_ex(hmac, key, md_size, md_type, NULL)
+ || !HMAC_Init_ex(hmac, key, md_size, md, NULL)
|| !HMAC_Update(hmac, p12->authsafes->d.data->data,
p12->authsafes->d.data->length)
|| !HMAC_Final(hmac, mac, maclen)) {
@@ -137,6 +161,7 @@ static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
err:
OPENSSL_cleanse(key, sizeof(key));
HMAC_CTX_free(hmac);
+ EVP_MD_free(md_fetch);
return ret;
}
@@ -154,12 +179,11 @@ int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen)
const ASN1_OCTET_STRING *macoct;
if (p12->mac == NULL) {
- PKCS12err(PKCS12_F_PKCS12_VERIFY_MAC, PKCS12_R_MAC_ABSENT);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_ABSENT);
return 0;
}
- if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen,
- PKCS12_key_gen_utf8)) {
- PKCS12err(PKCS12_F_PKCS12_VERIFY_MAC, PKCS12_R_MAC_GENERATION_ERROR);
+ if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, NULL)) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR);
return 0;
}
X509_SIG_get0(p12->mac->dinfo, NULL, &macoct);
@@ -180,23 +204,25 @@ int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
unsigned int maclen;
ASN1_OCTET_STRING *macoct;
- if (!md_type)
- md_type = EVP_sha1();
+ if (md_type == NULL)
+ /* No need to do a fetch as the md_type is used only to get a NID */
+ md_type = EVP_sha256();
+ if (!iter)
+ iter = PKCS12_DEFAULT_ITER;
if (PKCS12_setup_mac(p12, iter, salt, saltlen, md_type) == PKCS12_ERROR) {
- PKCS12err(PKCS12_F_PKCS12_SET_MAC, PKCS12_R_MAC_SETUP_ERROR);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_SETUP_ERROR);
return 0;
}
/*
* Note that output mac is forced to UTF-8...
*/
- if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen,
- PKCS12_key_gen_utf8)) {
- PKCS12err(PKCS12_F_PKCS12_SET_MAC, PKCS12_R_MAC_GENERATION_ERROR);
+ if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, NULL)) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR);
return 0;
}
X509_SIG_getm(p12->mac->dinfo, NULL, &macoct);
if (!ASN1_OCTET_STRING_set(macoct, mac, maclen)) {
- PKCS12err(PKCS12_F_PKCS12_SET_MAC, PKCS12_R_MAC_STRING_SET_ERROR);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_STRING_SET_ERROR);
return 0;
}
return 1;
@@ -215,30 +241,34 @@ int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen,
return PKCS12_ERROR;
if (iter > 1) {
if ((p12->mac->iter = ASN1_INTEGER_new()) == NULL) {
- PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!ASN1_INTEGER_set(p12->mac->iter, iter)) {
- PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
return 0;
}
}
- if (!saltlen)
+ if (saltlen == 0)
saltlen = PKCS12_SALT_LEN;
+ else if (saltlen < 0)
+ return 0;
if ((p12->mac->salt->data = OPENSSL_malloc(saltlen)) == NULL) {
- PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
return 0;
}
p12->mac->salt->length = saltlen;
- if (!salt) {
- if (RAND_bytes(p12->mac->salt->data, saltlen) <= 0)
+ if (salt == NULL) {
+ if (RAND_bytes_ex(p12->authsafes->ctx.libctx, p12->mac->salt->data,
+ (size_t)saltlen, 0) <= 0)
return 0;
- } else
+ } else {
memcpy(p12->mac->salt->data, salt, saltlen);
+ }
X509_SIG_getm(p12->mac->dinfo, &macalg, NULL);
- if (!X509_ALGOR_set0(macalg, OBJ_nid2obj(EVP_MD_type(md_type)),
+ if (!X509_ALGOR_set0(macalg, OBJ_nid2obj(EVP_MD_get_type(md_type)),
V_ASN1_NULL, NULL)) {
- PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
return 0;
}
diff --git a/crypto/pkcs12/p12_npas.c b/crypto/pkcs12/p12_npas.c
index 0334289a89fa..62230bc6187f 100644
--- a/crypto/pkcs12/p12_npas.c
+++ b/crypto/pkcs12/p12_npas.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -33,21 +33,20 @@ int PKCS12_newpass(PKCS12 *p12, const char *oldpass, const char *newpass)
{
/* Check for NULL PKCS12 structure */
- if (!p12) {
- PKCS12err(PKCS12_F_PKCS12_NEWPASS,
- PKCS12_R_INVALID_NULL_PKCS12_POINTER);
+ if (p12 == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_INVALID_NULL_PKCS12_POINTER);
return 0;
}
/* Check the mac */
if (!PKCS12_verify_mac(p12, oldpass, -1)) {
- PKCS12err(PKCS12_F_PKCS12_NEWPASS, PKCS12_R_MAC_VERIFY_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE);
return 0;
}
if (!newpass_p12(p12, oldpass, newpass)) {
- PKCS12err(PKCS12_F_PKCS12_NEWPASS, PKCS12_R_PARSE_ERROR);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_PARSE_ERROR);
return 0;
}
@@ -94,7 +93,7 @@ static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass)
else
p7new = PKCS12_pack_p7encdata(pbe_nid, newpass, -1, NULL,
pbe_saltlen, pbe_iter, bags);
- if (!p7new || !sk_PKCS7_push(newsafes, p7new))
+ if (p7new == NULL || !sk_PKCS7_push(newsafes, p7new))
goto err;
sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
bags = NULL;
@@ -157,8 +156,10 @@ static int newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass,
if ((p8 = PKCS8_decrypt(bag->value.shkeybag, oldpass, -1)) == NULL)
return 0;
X509_SIG_get0(bag->value.shkeybag, &shalg, NULL);
- if (!alg_get(shalg, &p8_nid, &p8_iter, &p8_saltlen))
+ if (!alg_get(shalg, &p8_nid, &p8_iter, &p8_saltlen)) {
+ PKCS8_PRIV_KEY_INFO_free(p8);
return 0;
+ }
p8new = PKCS8_encrypt(p8_nid, NULL, newpass, -1, NULL, p8_saltlen,
p8_iter, p8);
PKCS8_PRIV_KEY_INFO_free(p8);
@@ -173,8 +174,9 @@ static int alg_get(const X509_ALGOR *alg, int *pnid, int *piter,
int *psaltlen)
{
PBEPARAM *pbe;
+
pbe = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBEPARAM), alg->parameter);
- if (!pbe)
+ if (pbe == NULL)
return 0;
*pnid = OBJ_obj2nid(alg->algorithm);
*piter = ASN1_INTEGER_get(pbe->iter);
diff --git a/crypto/pkcs12/p12_p8d.c b/crypto/pkcs12/p12_p8d.c
index d926a77df87f..449336aa2df1 100644
--- a/crypto/pkcs12/p12_p8d.c
+++ b/crypto/pkcs12/p12_p8d.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,13 +11,22 @@
#include "internal/cryptlib.h"
#include <openssl/pkcs12.h>
-PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(const X509_SIG *p8, const char *pass,
- int passlen)
+PKCS8_PRIV_KEY_INFO *PKCS8_decrypt_ex(const X509_SIG *p8, const char *pass,
+ int passlen, OSSL_LIB_CTX *ctx,
+ const char *propq)
{
const X509_ALGOR *dalg;
const ASN1_OCTET_STRING *doct;
+
X509_SIG_get0(p8, &dalg, &doct);
- return PKCS12_item_decrypt_d2i(dalg,
+ return PKCS12_item_decrypt_d2i_ex(dalg,
ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass,
- passlen, doct, 1);
+ passlen, doct, 1, ctx, propq);
}
+
+PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(const X509_SIG *p8, const char *pass,
+ int passlen)
+{
+ return PKCS8_decrypt_ex(p8, pass, passlen, NULL, NULL);
+}
+
diff --git a/crypto/pkcs12/p12_p8e.c b/crypto/pkcs12/p12_p8e.c
index 05fc388a9969..9c2753401786 100644
--- a/crypto/pkcs12/p12_p8e.c
+++ b/crypto/pkcs12/p12_p8e.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,30 +9,46 @@
#include <stdio.h>
#include "internal/cryptlib.h"
+#include <openssl/core.h>
#include <openssl/pkcs12.h>
#include "crypto/x509.h"
-X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
- const char *pass, int passlen,
- unsigned char *salt, int saltlen, int iter,
- PKCS8_PRIV_KEY_INFO *p8inf)
+X509_SIG *PKCS8_encrypt_ex(int pbe_nid, const EVP_CIPHER *cipher,
+ const char *pass, int passlen,
+ unsigned char *salt, int saltlen, int iter,
+ PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
X509_SIG *p8 = NULL;
X509_ALGOR *pbe;
- if (pbe_nid == -1)
- pbe = PKCS5_pbe2_set(cipher, iter, salt, saltlen);
- else if (EVP_PBE_find(EVP_PBE_TYPE_PRF, pbe_nid, NULL, NULL, 0))
- pbe = PKCS5_pbe2_set_iv(cipher, iter, salt, saltlen, NULL, pbe_nid);
- else {
- ERR_clear_error();
- pbe = PKCS5_pbe_set(pbe_nid, iter, salt, saltlen);
+ if (pbe_nid == -1) {
+ if (cipher == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ pbe = PKCS5_pbe2_set_iv_ex(cipher, iter, salt, saltlen, NULL, -1,
+ libctx);
+ } else {
+ ERR_set_mark();
+ if (EVP_PBE_find(EVP_PBE_TYPE_PRF, pbe_nid, NULL, NULL, 0)) {
+ ERR_clear_last_mark();
+ if (cipher == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ pbe = PKCS5_pbe2_set_iv_ex(cipher, iter, salt, saltlen, NULL,
+ pbe_nid, libctx);
+ } else {
+ ERR_pop_to_mark();
+ pbe = PKCS5_pbe_set_ex(pbe_nid, iter, salt, saltlen, libctx);
+ }
}
- if (!pbe) {
- PKCS12err(PKCS12_F_PKCS8_ENCRYPT, ERR_R_ASN1_LIB);
+ if (pbe == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB);
return NULL;
}
- p8 = PKCS8_set0_pbe(pass, passlen, p8inf, pbe);
+ p8 = PKCS8_set0_pbe_ex(pass, passlen, p8inf, pbe, libctx, propq);
if (p8 == NULL) {
X509_ALGOR_free(pbe);
return NULL;
@@ -41,24 +57,34 @@ X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
return p8;
}
-X509_SIG *PKCS8_set0_pbe(const char *pass, int passlen,
- PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe)
+X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
+ const char *pass, int passlen,
+ unsigned char *salt, int saltlen, int iter,
+ PKCS8_PRIV_KEY_INFO *p8inf)
+{
+ return PKCS8_encrypt_ex(pbe_nid, cipher, pass, passlen, salt, saltlen, iter,
+ p8inf, NULL, NULL);
+}
+
+X509_SIG *PKCS8_set0_pbe_ex(const char *pass, int passlen,
+ PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe,
+ OSSL_LIB_CTX *ctx, const char *propq)
{
X509_SIG *p8;
ASN1_OCTET_STRING *enckey;
enckey =
- PKCS12_item_i2d_encrypt(pbe, ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO),
- pass, passlen, p8inf, 1);
+ PKCS12_item_i2d_encrypt_ex(pbe, ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO),
+ pass, passlen, p8inf, 1, ctx, propq);
if (!enckey) {
- PKCS12err(PKCS12_F_PKCS8_SET0_PBE, PKCS12_R_ENCRYPT_ERROR);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_ENCRYPT_ERROR);
return NULL;
}
p8 = OPENSSL_zalloc(sizeof(*p8));
if (p8 == NULL) {
- PKCS12err(PKCS12_F_PKCS8_SET0_PBE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
ASN1_OCTET_STRING_free(enckey);
return NULL;
}
@@ -67,3 +93,9 @@ X509_SIG *PKCS8_set0_pbe(const char *pass, int passlen,
return p8;
}
+
+X509_SIG *PKCS8_set0_pbe(const char *pass, int passlen,
+ PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe)
+{
+ return PKCS8_set0_pbe_ex(pass, passlen, p8inf, pbe, NULL, NULL);
+}
diff --git a/crypto/pkcs12/p12_sbag.c b/crypto/pkcs12/p12_sbag.c
index 7cf522786b03..7574c54120c7 100644
--- a/crypto/pkcs12/p12_sbag.c
+++ b/crypto/pkcs12/p12_sbag.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,7 +12,7 @@
#include <openssl/pkcs12.h>
#include "p12_local.h"
-#if OPENSSL_API_COMPAT < 0x10100000L
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
ASN1_TYPE *PKCS12_get_attr(const PKCS12_SAFEBAG *bag, int attr_nid)
{
return PKCS12_get_attr_gen(bag->attrib, attr_nid);
@@ -71,6 +71,16 @@ int PKCS12_SAFEBAG_get_bag_nid(const PKCS12_SAFEBAG *bag)
return OBJ_obj2nid(bag->value.bag->type);
}
+const ASN1_OBJECT *PKCS12_SAFEBAG_get0_bag_type(const PKCS12_SAFEBAG *bag)
+{
+ return bag->value.bag->type;
+}
+
+const ASN1_TYPE *PKCS12_SAFEBAG_get0_bag_obj(const PKCS12_SAFEBAG *bag)
+{
+ return bag->value.bag->value.other;
+}
+
X509 *PKCS12_SAFEBAG_get1_cert(const PKCS12_SAFEBAG *bag)
{
if (PKCS12_SAFEBAG_get_nid(bag) != NID_certBag)
@@ -103,6 +113,60 @@ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_crl(X509_CRL *crl)
NID_x509Crl, NID_crlBag);
}
+PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_secret(int type, int vtype, const unsigned char *value, int len)
+{
+ PKCS12_BAGS *bag;
+ PKCS12_SAFEBAG *safebag;
+
+ if ((bag = PKCS12_BAGS_new()) == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ bag->type = OBJ_nid2obj(type);
+
+ switch(vtype) {
+ case V_ASN1_OCTET_STRING:
+ {
+ ASN1_OCTET_STRING *strtmp = ASN1_OCTET_STRING_new();
+
+ if (strtmp == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ /* Pack data into an octet string */
+ if (!ASN1_OCTET_STRING_set(strtmp, value, len)) {
+ ASN1_OCTET_STRING_free(strtmp);
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_ENCODE_ERROR);
+ goto err;
+ }
+ bag->value.other = ASN1_TYPE_new();
+ if (bag->value.other == NULL) {
+ ASN1_OCTET_STRING_free(strtmp);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ ASN1_TYPE_set(bag->value.other, vtype, strtmp);
+ }
+ break;
+
+ default:
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_INVALID_TYPE);
+ goto err;
+ }
+
+ if ((safebag = PKCS12_SAFEBAG_new()) == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ safebag->value.bag = bag;
+ safebag->type = OBJ_nid2obj(NID_secretBag);
+ return safebag;
+
+ err:
+ PKCS12_BAGS_free(bag);
+ return NULL;
+}
+
/* Turn PKCS8 object into a keybag */
PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_p8inf(PKCS8_PRIV_KEY_INFO *p8)
@@ -110,7 +174,7 @@ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_p8inf(PKCS8_PRIV_KEY_INFO *p8)
PKCS12_SAFEBAG *bag = PKCS12_SAFEBAG_new();
if (bag == NULL) {
- PKCS12err(PKCS12_F_PKCS12_SAFEBAG_CREATE0_P8INF, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
return NULL;
}
bag->type = OBJ_nid2obj(NID_keyBag);
@@ -126,7 +190,7 @@ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_pkcs8(X509_SIG *p8)
/* Set up the safe bag */
if (bag == NULL) {
- PKCS12err(PKCS12_F_PKCS12_SAFEBAG_CREATE0_PKCS8, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
return NULL;
}
bag->type = OBJ_nid2obj(NID_pkcs8ShroudedKeyBag);
@@ -134,29 +198,51 @@ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_pkcs8(X509_SIG *p8)
return bag;
}
-PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt(int pbe_nid,
- const char *pass,
- int passlen,
- unsigned char *salt,
- int saltlen, int iter,
- PKCS8_PRIV_KEY_INFO *p8inf)
+PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(int pbe_nid,
+ const char *pass,
+ int passlen,
+ unsigned char *salt,
+ int saltlen, int iter,
+ PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *ctx,
+ const char *propq)
{
- PKCS12_SAFEBAG *bag;
- const EVP_CIPHER *pbe_ciph;
+ PKCS12_SAFEBAG *bag = NULL;
+ const EVP_CIPHER *pbe_ciph = NULL;
+ EVP_CIPHER *pbe_ciph_fetch = NULL;
X509_SIG *p8;
- pbe_ciph = EVP_get_cipherbynid(pbe_nid);
- if (pbe_ciph)
+ ERR_set_mark();
+ pbe_ciph = pbe_ciph_fetch = EVP_CIPHER_fetch(ctx, OBJ_nid2sn(pbe_nid), propq);
+ if (pbe_ciph == NULL)
+ pbe_ciph = EVP_get_cipherbynid(pbe_nid);
+ ERR_pop_to_mark();
+
+ if (pbe_ciph != NULL)
pbe_nid = -1;
- p8 = PKCS8_encrypt(pbe_nid, pbe_ciph, pass, passlen, salt, saltlen, iter,
- p8inf);
+ p8 = PKCS8_encrypt_ex(pbe_nid, pbe_ciph, pass, passlen, salt, saltlen, iter,
+ p8inf, ctx, propq);
if (p8 == NULL)
- return NULL;
+ goto err;
bag = PKCS12_SAFEBAG_create0_pkcs8(p8);
if (bag == NULL)
X509_SIG_free(p8);
+err:
+ EVP_CIPHER_free(pbe_ciph_fetch);
return bag;
}
+
+PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt(int pbe_nid,
+ const char *pass,
+ int passlen,
+ unsigned char *salt,
+ int saltlen, int iter,
+ PKCS8_PRIV_KEY_INFO *p8inf)
+{
+ return PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(pbe_nid, pass, passlen,
+ salt, saltlen, iter, p8inf,
+ NULL, NULL);
+}
diff --git a/crypto/pkcs12/p12_utl.c b/crypto/pkcs12/p12_utl.c
index 43b9e3a5941a..3afc8b2f13c9 100644
--- a/crypto/pkcs12/p12_utl.c
+++ b/crypto/pkcs12/p12_utl.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -21,9 +21,11 @@ unsigned char *OPENSSL_asc2uni(const char *asc, int asclen,
if (asclen == -1)
asclen = strlen(asc);
+ if (asclen < 0)
+ return NULL;
ulen = asclen * 2 + 2;
if ((unitmp = OPENSSL_malloc(ulen)) == NULL) {
- PKCS12err(PKCS12_F_OPENSSL_ASC2UNI, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
return NULL;
}
for (i = 0; i < ulen - 2; i += 2) {
@@ -44,16 +46,19 @@ char *OPENSSL_uni2asc(const unsigned char *uni, int unilen)
{
int asclen, i;
char *asctmp;
+
/* string must contain an even number of bytes */
if (unilen & 1)
return NULL;
+ if (unilen < 0)
+ return NULL;
asclen = unilen / 2;
/* If no terminating zero allow for one */
if (!unilen || uni[unilen - 1])
asclen++;
uni++;
if ((asctmp = OPENSSL_malloc(asclen)) == NULL) {
- PKCS12err(PKCS12_F_OPENSSL_UNI2ASC, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
return NULL;
}
for (i = 0; i < unilen; i += 2)
@@ -115,7 +120,7 @@ unsigned char *OPENSSL_utf82uni(const char *asc, int asclen,
ulen += 2; /* for trailing UTF16 zero */
if ((ret = OPENSSL_malloc(ulen)) == NULL) {
- PKCS12err(PKCS12_F_OPENSSL_UTF82UNI, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
return NULL;
}
/* re-run the loop writing down UTF-16 characters in big-endian order */
@@ -200,7 +205,7 @@ char *OPENSSL_uni2utf8(const unsigned char *uni, int unilen)
asclen++;
if ((asctmp = OPENSSL_malloc(asclen)) == NULL) {
- PKCS12err(PKCS12_F_OPENSSL_UNI2UTF8, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -219,13 +224,13 @@ char *OPENSSL_uni2utf8(const unsigned char *uni, int unilen)
return asctmp;
}
-int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12)
+int i2d_PKCS12_bio(BIO *bp, const PKCS12 *p12)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(PKCS12), bp, p12);
}
#ifndef OPENSSL_NO_STDIO
-int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12)
+int i2d_PKCS12_fp(FILE *fp, const PKCS12 *p12)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(PKCS12), fp, p12);
}
diff --git a/crypto/pkcs12/pk12err.c b/crypto/pkcs12/pk12err.c
index 38ce5197eeee..6e3ec78cd6ea 100644
--- a/crypto/pkcs12/pk12err.c
+++ b/crypto/pkcs12/pk12err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,61 +10,10 @@
#include <openssl/err.h>
#include <openssl/pkcs12err.h>
+#include "crypto/pkcs12err.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA PKCS12_str_functs[] = {
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_OPENSSL_ASC2UNI, 0), "OPENSSL_asc2uni"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_OPENSSL_UNI2ASC, 0), "OPENSSL_uni2asc"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_OPENSSL_UNI2UTF8, 0),
- "OPENSSL_uni2utf8"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_OPENSSL_UTF82UNI, 0),
- "OPENSSL_utf82uni"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_CREATE, 0), "PKCS12_create"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_GEN_MAC, 0), "PKCS12_gen_mac"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_INIT, 0), "PKCS12_init"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_ITEM_DECRYPT_D2I, 0),
- "PKCS12_item_decrypt_d2i"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT, 0),
- "PKCS12_item_i2d_encrypt"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG, 0),
- "PKCS12_item_pack_safebag"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_KEY_GEN_ASC, 0),
- "PKCS12_key_gen_asc"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_KEY_GEN_UNI, 0),
- "PKCS12_key_gen_uni"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_KEY_GEN_UTF8, 0),
- "PKCS12_key_gen_utf8"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_NEWPASS, 0), "PKCS12_newpass"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_PACK_P7DATA, 0),
- "PKCS12_pack_p7data"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_PACK_P7ENCDATA, 0),
- "PKCS12_pack_p7encdata"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_PARSE, 0), "PKCS12_parse"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_PBE_CRYPT, 0),
- "PKCS12_pbe_crypt"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_PBE_KEYIVGEN, 0),
- "PKCS12_PBE_keyivgen"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_SAFEBAG_CREATE0_P8INF, 0),
- "PKCS12_SAFEBAG_create0_p8inf"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_SAFEBAG_CREATE0_PKCS8, 0),
- "PKCS12_SAFEBAG_create0_pkcs8"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_SAFEBAG_CREATE_PKCS8_ENCRYPT, 0),
- "PKCS12_SAFEBAG_create_pkcs8_encrypt"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_SETUP_MAC, 0),
- "PKCS12_setup_mac"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_SET_MAC, 0), "PKCS12_set_mac"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_UNPACK_AUTHSAFES, 0),
- "PKCS12_unpack_authsafes"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_UNPACK_P7DATA, 0),
- "PKCS12_unpack_p7data"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_VERIFY_MAC, 0),
- "PKCS12_verify_mac"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS8_ENCRYPT, 0), "PKCS8_encrypt"},
- {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS8_SET0_PBE, 0), "PKCS8_set0_pbe"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA PKCS12_str_reasons[] = {
{ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_CANT_PACK_STRUCTURE),
"cant pack structure"},
@@ -79,6 +28,7 @@ static const ERR_STRING_DATA PKCS12_str_reasons[] = {
"invalid null argument"},
{ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_INVALID_NULL_PKCS12_POINTER),
"invalid null pkcs12 pointer"},
+ {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_INVALID_TYPE), "invalid type"},
{ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_IV_GEN_ERROR), "iv gen error"},
{ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_KEY_GEN_ERROR), "key gen error"},
{ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_MAC_ABSENT), "mac absent"},
@@ -90,12 +40,8 @@ static const ERR_STRING_DATA PKCS12_str_reasons[] = {
{ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_MAC_VERIFY_FAILURE),
"mac verify failure"},
{ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_PARSE_ERROR), "parse error"},
- {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR),
- "pkcs12 algor cipherinit error"},
{ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_PKCS12_CIPHERFINAL_ERROR),
"pkcs12 cipherfinal error"},
- {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_PKCS12_PBE_CRYPT_ERROR),
- "pkcs12 pbe crypt error"},
{ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_UNKNOWN_DIGEST_ALGORITHM),
"unknown digest algorithm"},
{ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_UNSUPPORTED_PKCS12_MODE),
@@ -105,13 +51,11 @@ static const ERR_STRING_DATA PKCS12_str_reasons[] = {
#endif
-int ERR_load_PKCS12_strings(void)
+int ossl_err_load_PKCS12_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(PKCS12_str_functs[0].error) == NULL) {
- ERR_load_strings_const(PKCS12_str_functs);
+ if (ERR_reason_error_string(PKCS12_str_reasons[0].error) == NULL)
ERR_load_strings_const(PKCS12_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/pkcs7/bio_pk7.c b/crypto/pkcs7/bio_pk7.c
index 29feaa3544e3..414f0da1c615 100644
--- a/crypto/pkcs7/bio_pk7.c
+++ b/crypto/pkcs7/bio_pk7.c
@@ -1,7 +1,7 @@
/*
* Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/pkcs7/pk7_asn1.c b/crypto/pkcs7/pk7_asn1.c
index cd9fb4f509f1..1cd867721ee1 100644
--- a/crypto/pkcs7/pk7_asn1.c
+++ b/crypto/pkcs7/pk7_asn1.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,6 +12,7 @@
#include <openssl/asn1t.h>
#include <openssl/pkcs7.h>
#include <openssl/x509.h>
+#include "pk7_local.h"
/* PKCS#7 ASN1 module */
@@ -62,7 +63,61 @@ ASN1_NDEF_SEQUENCE_cb(PKCS7, pk7_cb) = {
ASN1_ADB_OBJECT(PKCS7)
}ASN1_NDEF_SEQUENCE_END_cb(PKCS7, PKCS7)
-IMPLEMENT_ASN1_FUNCTIONS(PKCS7)
+PKCS7 *d2i_PKCS7(PKCS7 **a, const unsigned char **in, long len)
+{
+ PKCS7 *ret;
+ OSSL_LIB_CTX *libctx = NULL;
+ const char *propq = NULL;
+
+ if (a != NULL && *a != NULL) {
+ libctx = (*a)->ctx.libctx;
+ propq = (*a)->ctx.propq;
+ }
+
+ ret = (PKCS7 *)ASN1_item_d2i_ex((ASN1_VALUE **)a, in, len, (PKCS7_it()),
+ libctx, propq);
+ if (ret != NULL)
+ ossl_pkcs7_resolve_libctx(ret);
+ return ret;
+}
+
+int i2d_PKCS7(const PKCS7 *a, unsigned char **out)
+{
+ return ASN1_item_i2d((const ASN1_VALUE *)a, out, (PKCS7_it()));\
+}
+
+PKCS7 *PKCS7_new(void)
+{
+ return (PKCS7 *)ASN1_item_new(ASN1_ITEM_rptr(PKCS7));
+}
+
+PKCS7 *PKCS7_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
+{
+ PKCS7 *pkcs7 = (PKCS7 *)ASN1_item_new_ex(ASN1_ITEM_rptr(PKCS7), libctx,
+ propq);
+
+ if (pkcs7 != NULL) {
+ pkcs7->ctx.libctx = libctx;
+ pkcs7->ctx.propq = NULL;
+ if (propq != NULL) {
+ pkcs7->ctx.propq = OPENSSL_strdup(propq);
+ if (pkcs7->ctx.propq == NULL) {
+ PKCS7_free(pkcs7);
+ pkcs7 = NULL;
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ }
+ }
+ }
+ return pkcs7;
+}
+
+void PKCS7_free(PKCS7 *p7)
+{
+ if (p7 != NULL) {
+ OPENSSL_free(p7->ctx.propq);
+ ASN1_item_free((ASN1_VALUE *)p7, ASN1_ITEM_rptr(PKCS7));
+ }
+}
IMPLEMENT_ASN1_NDEF_FUNCTION(PKCS7)
diff --git a/crypto/pkcs7/pk7_attr.c b/crypto/pkcs7/pk7_attr.c
index e90bf03c5247..e9904c5950c6 100644
--- a/crypto/pkcs7/pk7_attr.c
+++ b/crypto/pkcs7/pk7_attr.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -23,7 +23,7 @@ int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si,
ASN1_STRING *seq;
if ((seq = ASN1_STRING_new()) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
seq->length = ASN1_item_i2d((ASN1_VALUE *)cap, &seq->data,
@@ -53,7 +53,7 @@ int PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *sk, int nid, int arg)
X509_ALGOR *alg;
if ((alg = X509_ALGOR_new()) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_SIMPLE_SMIMECAP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
ASN1_OBJECT_free(alg->algorithm);
@@ -77,7 +77,7 @@ int PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *sk, int nid, int arg)
}
return 1;
err:
- PKCS7err(PKCS7_F_PKCS7_SIMPLE_SMIMECAP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
ASN1_INTEGER_free(nbit);
X509_ALGOR_free(alg);
return 0;
@@ -96,8 +96,7 @@ int PKCS7_add_attrib_content_type(PKCS7_SIGNER_INFO *si, ASN1_OBJECT *coid)
int PKCS7_add0_attrib_signing_time(PKCS7_SIGNER_INFO *si, ASN1_TIME *t)
{
if (t == NULL && (t = X509_gmtime_adj(NULL, 0)) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_ADD0_ATTRIB_SIGNING_TIME,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
return PKCS7_add_signed_attribute(si, NID_pkcs9_signingTime,
diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c
index f63fbc50ea60..1cef67b211af 100644
--- a/crypto/pkcs7/pk7_doit.c
+++ b/crypto/pkcs7/pk7_doit.c
@@ -1,25 +1,27 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
-#include "internal/cryptlib.h"
#include <openssl/rand.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
+#include "internal/cryptlib.h"
+#include "internal/sizes.h"
+#include "pk7_local.h"
static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
void *value);
-static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid);
+static ASN1_TYPE *get_attribute(const STACK_OF(X509_ATTRIBUTE) *sk, int nid);
-static int PKCS7_type_is_other(PKCS7 *p7)
+int PKCS7_type_is_other(PKCS7 *p7)
{
int isOther = 1;
@@ -42,7 +44,7 @@ static int PKCS7_type_is_other(PKCS7 *p7)
}
-static ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7)
+ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7)
{
if (PKCS7_type_is_data(p7))
return p7->d.data;
@@ -52,26 +54,46 @@ static ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7)
return NULL;
}
-static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg)
+static int pkcs7_bio_add_digest(BIO **pbio, X509_ALGOR *alg,
+ const PKCS7_CTX *ctx)
{
BIO *btmp;
+ char name[OSSL_MAX_NAME_SIZE];
+ EVP_MD *fetched = NULL;
const EVP_MD *md;
+
if ((btmp = BIO_new(BIO_f_md())) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, ERR_R_BIO_LIB);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
goto err;
}
- md = EVP_get_digestbyobj(alg->algorithm);
+ OBJ_obj2txt(name, sizeof(name), alg->algorithm, 0);
+
+ (void)ERR_set_mark();
+ fetched = EVP_MD_fetch(ossl_pkcs7_ctx_get0_libctx(ctx), name,
+ ossl_pkcs7_ctx_get0_propq(ctx));
+ if (fetched != NULL)
+ md = fetched;
+ else
+ md = EVP_get_digestbyname(name);
+
if (md == NULL) {
- PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, PKCS7_R_UNKNOWN_DIGEST_TYPE);
+ (void)ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNKNOWN_DIGEST_TYPE);
goto err;
}
+ (void)ERR_pop_to_mark();
- BIO_set_md(btmp, md);
+ if (BIO_set_md(btmp, md) <= 0) {
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
+ EVP_MD_free(fetched);
+ goto err;
+ }
+ EVP_MD_free(fetched);
if (*pbio == NULL)
*pbio = btmp;
else if (!BIO_push(*pbio, btmp)) {
- PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, ERR_R_BIO_LIB);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
goto err;
}
btmp = NULL;
@@ -81,7 +103,6 @@ static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg)
err:
BIO_free(btmp);
return 0;
-
}
static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri,
@@ -92,32 +113,27 @@ static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri,
unsigned char *ek = NULL;
int ret = 0;
size_t eklen;
+ const PKCS7_CTX *ctx = ri->ctx;
pkey = X509_get0_pubkey(ri->cert);
-
- if (!pkey)
+ if (pkey == NULL)
return 0;
- pctx = EVP_PKEY_CTX_new(pkey, NULL);
- if (!pctx)
+ pctx = EVP_PKEY_CTX_new_from_pkey(ossl_pkcs7_ctx_get0_libctx(ctx), pkey,
+ ossl_pkcs7_ctx_get0_propq(ctx));
+ if (pctx == NULL)
return 0;
if (EVP_PKEY_encrypt_init(pctx) <= 0)
goto err;
- if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT,
- EVP_PKEY_CTRL_PKCS7_ENCRYPT, 0, ri) <= 0) {
- PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, PKCS7_R_CTRL_ERROR);
- goto err;
- }
-
if (EVP_PKEY_encrypt(pctx, NULL, &eklen, key, keylen) <= 0)
goto err;
ek = OPENSSL_malloc(eklen);
if (ek == NULL) {
- PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -143,22 +159,17 @@ static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen,
EVP_PKEY_CTX *pctx = NULL;
unsigned char *ek = NULL;
size_t eklen;
-
int ret = -1;
+ const PKCS7_CTX *ctx = ri->ctx;
- pctx = EVP_PKEY_CTX_new(pkey, NULL);
- if (!pctx)
+ pctx = EVP_PKEY_CTX_new_from_pkey(ossl_pkcs7_ctx_get0_libctx(ctx), pkey,
+ ossl_pkcs7_ctx_get0_propq(ctx));
+ if (pctx == NULL)
return -1;
if (EVP_PKEY_decrypt_init(pctx) <= 0)
goto err;
- if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT,
- EVP_PKEY_CTRL_PKCS7_DECRYPT, 0, ri) <= 0) {
- PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, PKCS7_R_CTRL_ERROR);
- goto err;
- }
-
if (EVP_PKEY_decrypt(pctx, NULL, &eklen,
ri->enc_key->data, ri->enc_key->length) <= 0)
goto err;
@@ -166,7 +177,7 @@ static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen,
ek = OPENSSL_malloc(eklen);
if (ek == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -175,7 +186,7 @@ static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen,
|| eklen == 0
|| (fixlen != 0 && eklen != fixlen)) {
ret = 0;
- PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_EVP_LIB);
goto err;
}
@@ -198,17 +209,26 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
int i;
BIO *out = NULL, *btmp = NULL;
X509_ALGOR *xa = NULL;
+ EVP_CIPHER *fetched_cipher = NULL;
+ const EVP_CIPHER *cipher;
const EVP_CIPHER *evp_cipher = NULL;
STACK_OF(X509_ALGOR) *md_sk = NULL;
STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL;
X509_ALGOR *xalg = NULL;
PKCS7_RECIP_INFO *ri = NULL;
ASN1_OCTET_STRING *os = NULL;
+ const PKCS7_CTX *p7_ctx;
+ OSSL_LIB_CTX *libctx;
+ const char *propq;
if (p7 == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER);
return NULL;
}
+ p7_ctx = ossl_pkcs7_get0_ctx(p7);
+ libctx = ossl_pkcs7_ctx_get0_libctx(p7_ctx);
+ propq = ossl_pkcs7_ctx_get0_propq(p7_ctx);
+
/*
* The content field in the PKCS7 ContentInfo is optional, but that really
* only applies to inner content (precisely, detached signatures).
@@ -220,7 +240,7 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
* calling this method, so a NULL p7->d is always an error.
*/
if (p7->d.ptr == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_NO_CONTENT);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
return NULL;
}
@@ -238,7 +258,7 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
xalg = p7->d.signed_and_enveloped->enc_data->algorithm;
evp_cipher = p7->d.signed_and_enveloped->enc_data->cipher;
if (evp_cipher == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_CIPHER_NOT_INITIALIZED);
goto err;
}
break;
@@ -247,7 +267,7 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
xalg = p7->d.enveloped->enc_data->algorithm;
evp_cipher = p7->d.enveloped->enc_data->cipher;
if (evp_cipher == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_CIPHER_NOT_INITIALIZED);
goto err;
}
break;
@@ -258,15 +278,15 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
case NID_pkcs7_data:
break;
default:
- PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
goto err;
}
for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++)
- if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i)))
+ if (!pkcs7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i), p7_ctx))
goto err;
- if (xa && !PKCS7_bio_add_digest(&out, xa))
+ if (xa && !pkcs7_bio_add_digest(&out, xa, p7_ctx))
goto err;
if (evp_cipher != NULL) {
@@ -276,18 +296,33 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
EVP_CIPHER_CTX *ctx;
if ((btmp = BIO_new(BIO_f_cipher())) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATAINIT, ERR_R_BIO_LIB);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
goto err;
}
BIO_get_cipher_ctx(btmp, &ctx);
- keylen = EVP_CIPHER_key_length(evp_cipher);
- ivlen = EVP_CIPHER_iv_length(evp_cipher);
- xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
+ keylen = EVP_CIPHER_get_key_length(evp_cipher);
+ ivlen = EVP_CIPHER_get_iv_length(evp_cipher);
+ xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_get_type(evp_cipher));
if (ivlen > 0)
- if (RAND_bytes(iv, ivlen) <= 0)
+ if (RAND_bytes_ex(libctx, iv, ivlen, 0) <= 0)
goto err;
- if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1) <= 0)
+
+ (void)ERR_set_mark();
+ fetched_cipher = EVP_CIPHER_fetch(libctx,
+ EVP_CIPHER_get0_name(evp_cipher),
+ propq);
+ (void)ERR_pop_to_mark();
+ if (fetched_cipher != NULL)
+ cipher = fetched_cipher;
+ else
+ cipher = evp_cipher;
+
+ if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, 1) <= 0)
goto err;
+
+ EVP_CIPHER_free(fetched_cipher);
+ fetched_cipher = NULL;
+
if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
goto err;
if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
@@ -299,7 +334,7 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
if (xalg->parameter == NULL)
goto err;
}
- if (EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
+ if (EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) <= 0)
goto err;
}
@@ -339,6 +374,7 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
return out;
err:
+ EVP_CIPHER_free(fetched_cipher);
BIO_free_all(out);
BIO_free_all(btmp);
return NULL;
@@ -351,19 +387,21 @@ static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert)
X509_get_issuer_name(pcert));
if (ret)
return ret;
- return ASN1_INTEGER_cmp(X509_get_serialNumber(pcert),
+ return ASN1_INTEGER_cmp(X509_get0_serialNumber(pcert),
ri->issuer_and_serial->serial);
}
/* int */
BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
{
- int i, j;
+ int i, len;
BIO *out = NULL, *btmp = NULL, *etmp = NULL, *bio = NULL;
X509_ALGOR *xa;
ASN1_OCTET_STRING *data_body = NULL;
- const EVP_MD *evp_md;
- const EVP_CIPHER *evp_cipher = NULL;
+ EVP_MD *evp_md = NULL;
+ const EVP_MD *md;
+ EVP_CIPHER *evp_cipher = NULL;
+ const EVP_CIPHER *cipher = NULL;
EVP_CIPHER_CTX *evp_ctx = NULL;
X509_ALGOR *enc_alg = NULL;
STACK_OF(X509_ALGOR) *md_sk = NULL;
@@ -371,14 +409,22 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
PKCS7_RECIP_INFO *ri = NULL;
unsigned char *ek = NULL, *tkey = NULL;
int eklen = 0, tkeylen = 0;
+ char name[OSSL_MAX_NAME_SIZE];
+ const PKCS7_CTX *p7_ctx;
+ OSSL_LIB_CTX *libctx;
+ const char *propq;
if (p7 == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER);
return NULL;
}
+ p7_ctx = ossl_pkcs7_get0_ctx(p7);
+ libctx = ossl_pkcs7_ctx_get0_libctx(p7_ctx);
+ propq = ossl_pkcs7_ctx_get0_propq(p7_ctx);
+
if (p7->d.ptr == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
return NULL;
}
@@ -395,8 +441,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
*/
data_body = PKCS7_get_octet_string(p7->d.sign->contents);
if (!PKCS7_is_detached(p7) && data_body == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATADECODE,
- PKCS7_R_INVALID_SIGNED_DATA_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_SIGNED_DATA_TYPE);
goto err;
}
md_sk = p7->d.sign->md_algs;
@@ -407,33 +452,52 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
/* data_body is NULL if the optional EncryptedContent is missing. */
data_body = p7->d.signed_and_enveloped->enc_data->enc_data;
enc_alg = p7->d.signed_and_enveloped->enc_data->algorithm;
- evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm);
- if (evp_cipher == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATADECODE,
- PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
+
+ OBJ_obj2txt(name, sizeof(name), enc_alg->algorithm, 0);
+
+ (void)ERR_set_mark();
+ evp_cipher = EVP_CIPHER_fetch(libctx, name, propq);
+ if (evp_cipher != NULL)
+ cipher = evp_cipher;
+ else
+ cipher = EVP_get_cipherbyname(name);
+
+ if (cipher == NULL) {
+ (void)ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
goto err;
}
+ (void)ERR_pop_to_mark();
break;
case NID_pkcs7_enveloped:
rsk = p7->d.enveloped->recipientinfo;
enc_alg = p7->d.enveloped->enc_data->algorithm;
/* data_body is NULL if the optional EncryptedContent is missing. */
data_body = p7->d.enveloped->enc_data->enc_data;
- evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm);
- if (evp_cipher == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATADECODE,
- PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
+ OBJ_obj2txt(name, sizeof(name), enc_alg->algorithm, 0);
+
+ (void)ERR_set_mark();
+ evp_cipher = EVP_CIPHER_fetch(libctx, name, propq);
+ if (evp_cipher != NULL)
+ cipher = evp_cipher;
+ else
+ cipher = EVP_get_cipherbyname(name);
+
+ if (cipher == NULL) {
+ (void)ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
goto err;
}
+ (void)ERR_pop_to_mark();
break;
default:
- PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
goto err;
}
/* Detached content must be supplied via in_bio instead. */
if (data_body == NULL && in_bio == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
goto err;
}
@@ -442,19 +506,32 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) {
xa = sk_X509_ALGOR_value(md_sk, i);
if ((btmp = BIO_new(BIO_f_md())) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_BIO_LIB);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
goto err;
}
- j = OBJ_obj2nid(xa->algorithm);
- evp_md = EVP_get_digestbynid(j);
- if (evp_md == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATADECODE,
- PKCS7_R_UNKNOWN_DIGEST_TYPE);
+ OBJ_obj2txt(name, sizeof(name), xa->algorithm, 0);
+
+ (void)ERR_set_mark();
+ evp_md = EVP_MD_fetch(libctx, name, propq);
+ if (evp_md != NULL)
+ md = evp_md;
+ else
+ md = EVP_get_digestbyname(name);
+
+ if (md == NULL) {
+ (void)ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNKNOWN_DIGEST_TYPE);
goto err;
}
+ (void)ERR_pop_to_mark();
- BIO_set_md(btmp, evp_md);
+ if (BIO_set_md(btmp, md) <= 0) {
+ EVP_MD_free(evp_md);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
+ goto err;
+ }
+ EVP_MD_free(evp_md);
if (out == NULL)
out = btmp;
else
@@ -463,9 +540,9 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
}
}
- if (evp_cipher != NULL) {
+ if (cipher != NULL) {
if ((etmp = BIO_new(BIO_f_cipher())) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_BIO_LIB);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
goto err;
}
@@ -487,8 +564,8 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
ri = NULL;
}
if (ri == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATADECODE,
- PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
+ ERR_raise(ERR_LIB_PKCS7,
+ PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
goto err;
}
}
@@ -501,13 +578,14 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
*/
for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) {
ri = sk_PKCS7_RECIP_INFO_value(rsk, i);
-
+ ri->ctx = p7_ctx;
if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey,
- EVP_CIPHER_key_length(evp_cipher)) < 0)
+ EVP_CIPHER_get_key_length(cipher)) < 0)
goto err;
ERR_clear_error();
}
} else {
+ ri->ctx = p7_ctx;
/* Only exit on fatal errors, not decrypt failure */
if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey, 0) < 0)
goto err;
@@ -516,12 +594,15 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
evp_ctx = NULL;
BIO_get_cipher_ctx(etmp, &evp_ctx);
- if (EVP_CipherInit_ex(evp_ctx, evp_cipher, NULL, NULL, NULL, 0) <= 0)
+ if (EVP_CipherInit_ex(evp_ctx, cipher, NULL, NULL, NULL, 0) <= 0)
goto err;
- if (EVP_CIPHER_asn1_to_param(evp_ctx, enc_alg->parameter) < 0)
+ if (EVP_CIPHER_asn1_to_param(evp_ctx, enc_alg->parameter) <= 0)
goto err;
/* Generate random key as MMA defence */
- tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx);
+ len = EVP_CIPHER_CTX_get_key_length(evp_ctx);
+ if (len <= 0)
+ goto err;
+ tkeylen = (size_t)len;
tkey = OPENSSL_malloc(tkeylen);
if (tkey == NULL)
goto err;
@@ -533,13 +614,13 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
tkey = NULL;
}
- if (eklen != EVP_CIPHER_CTX_key_length(evp_ctx)) {
+ if (eklen != EVP_CIPHER_CTX_get_key_length(evp_ctx)) {
/*
* Some S/MIME clients don't use the same key and effective key
* length. The key length is determined by the size of the
* decrypted RSA key.
*/
- if (!EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen)) {
+ if (EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen) <= 0) {
/* Use random key as MMA defence */
OPENSSL_clear_free(ek, eklen);
ek = tkey;
@@ -579,9 +660,11 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
}
BIO_push(out, bio);
bio = NULL;
+ EVP_CIPHER_free(evp_cipher);
return out;
err:
+ EVP_CIPHER_free(evp_cipher);
OPENSSL_clear_free(ek, eklen);
OPENSSL_clear_free(tkey, tkeylen);
BIO_free_all(out);
@@ -596,16 +679,15 @@ static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid)
for (;;) {
bio = BIO_find_type(bio, BIO_TYPE_MD);
if (bio == NULL) {
- PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,
- PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
return NULL;
}
BIO_get_md_ctx(bio, pmd);
if (*pmd == NULL) {
- PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_INTERNAL_ERROR);
return NULL;
}
- if (EVP_MD_CTX_type(*pmd) == nid)
+ if (EVP_MD_CTX_get_type(*pmd) == nid)
return bio;
bio = BIO_next(bio);
}
@@ -620,18 +702,18 @@ static int do_pkcs7_signed_attrib(PKCS7_SIGNER_INFO *si, EVP_MD_CTX *mctx)
/* Add signing time if not already present */
if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) {
if (!PKCS7_add0_attrib_signing_time(si, NULL)) {
- PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
}
/* Add digest */
if (!EVP_DigestFinal_ex(mctx, md_data, &md_len)) {
- PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_EVP_LIB);
return 0;
}
if (!PKCS7_add1_attrib_digest(si, md_data, md_len)) {
- PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -652,20 +734,23 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
STACK_OF(X509_ATTRIBUTE) *sk;
STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL;
ASN1_OCTET_STRING *os = NULL;
+ const PKCS7_CTX *p7_ctx;
if (p7 == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER);
return 0;
}
+ p7_ctx = ossl_pkcs7_get0_ctx(p7);
+
if (p7->d.ptr == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
return 0;
}
ctx_tmp = EVP_MD_CTX_new();
if (ctx_tmp == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -683,7 +768,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
if (os == NULL) {
os = ASN1_OCTET_STRING_new();
if (os == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
p7->d.signed_and_enveloped->enc_data->enc_data = os;
@@ -695,7 +780,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
if (os == NULL) {
os = ASN1_OCTET_STRING_new();
if (os == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
p7->d.enveloped->enc_data->enc_data = os;
@@ -723,7 +808,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
break;
default:
- PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
goto err;
}
@@ -760,14 +845,16 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
} else {
unsigned char *abuf = NULL;
unsigned int abuflen;
- abuflen = EVP_PKEY_size(si->pkey);
+ abuflen = EVP_PKEY_get_size(si->pkey);
abuf = OPENSSL_malloc(abuflen);
if (abuf == NULL)
goto err;
- if (!EVP_SignFinal(ctx_tmp, abuf, &abuflen, si->pkey)) {
+ if (!EVP_SignFinal_ex(ctx_tmp, abuf, &abuflen, si->pkey,
+ ossl_pkcs7_ctx_get0_libctx(p7_ctx),
+ ossl_pkcs7_ctx_get0_propq(p7_ctx))) {
OPENSSL_free(abuf);
- PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_EVP_LIB);
goto err;
}
ASN1_STRING_set0(si->enc_digest, abuf, abuflen);
@@ -797,7 +884,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
long contlen;
btmp = BIO_find_type(bio, BIO_TYPE_MEM);
if (btmp == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
goto err;
}
contlen = BIO_get_mem_data(btmp, &cont);
@@ -824,6 +911,7 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
int alen;
size_t siglen;
const EVP_MD *md = NULL;
+ const PKCS7_CTX *ctx = si->ctx;
md = EVP_get_digestbyobj(si->digest_alg->algorithm);
if (md == NULL)
@@ -831,19 +919,16 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
mctx = EVP_MD_CTX_new();
if (mctx == NULL) {
- PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (EVP_DigestSignInit(mctx, &pctx, md, NULL, si->pkey) <= 0)
+ if (EVP_DigestSignInit_ex(mctx, &pctx, EVP_MD_get0_name(md),
+ ossl_pkcs7_ctx_get0_libctx(ctx),
+ ossl_pkcs7_ctx_get0_propq(ctx), si->pkey,
+ NULL) <= 0)
goto err;
- if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
- EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0) {
- PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR);
- goto err;
- }
-
alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr, &abuf,
ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
if (!abuf)
@@ -860,12 +945,6 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
if (EVP_DigestSignFinal(mctx, abuf, &siglen) <= 0)
goto err;
- if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
- EVP_PKEY_CTRL_PKCS7_SIGN, 1, si) <= 0) {
- PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR);
- goto err;
- }
-
EVP_MD_CTX_free(mctx);
ASN1_STRING_set0(si->enc_digest, abuf, siglen);
@@ -876,7 +955,6 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
OPENSSL_free(abuf);
EVP_MD_CTX_free(mctx);
return 0;
-
}
int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
@@ -888,12 +966,12 @@ int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
X509 *x509;
if (p7 == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_INVALID_NULL_POINTER);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER);
return 0;
}
if (p7->d.ptr == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_NO_CONTENT);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
return 0;
}
@@ -902,7 +980,7 @@ int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
} else if (PKCS7_type_is_signedAndEnveloped(p7)) {
cert = p7->d.signed_and_enveloped->cert;
} else {
- PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_WRONG_PKCS7_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_PKCS7_TYPE);
goto err;
}
/* XXXXXXXXXXXXXXXXXXXXXXX */
@@ -912,24 +990,21 @@ int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
/* were we able to find the cert in passed to us */
if (x509 == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,
- PKCS7_R_UNABLE_TO_FIND_CERTIFICATE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_CERTIFICATE);
goto err;
}
/* Lets verify */
if (!X509_STORE_CTX_init(ctx, cert_store, x509, cert)) {
- PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, ERR_R_X509_LIB);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_X509_LIB);
goto err;
}
X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN);
i = X509_verify_cert(ctx);
if (i <= 0) {
- PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, ERR_R_X509_LIB);
- X509_STORE_CTX_cleanup(ctx);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_X509_LIB);
goto err;
}
- X509_STORE_CTX_cleanup(ctx);
return PKCS7_signatureVerify(bio, p7, si, x509);
err:
@@ -941,20 +1016,25 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
{
ASN1_OCTET_STRING *os;
EVP_MD_CTX *mdc_tmp, *mdc;
+ const EVP_MD *md;
+ EVP_MD *fetched_md = NULL;
int ret = 0, i;
int md_type;
STACK_OF(X509_ATTRIBUTE) *sk;
BIO *btmp;
EVP_PKEY *pkey;
+ const PKCS7_CTX *ctx = ossl_pkcs7_get0_ctx(p7);
+ OSSL_LIB_CTX *libctx = ossl_pkcs7_ctx_get0_libctx(ctx);
+ const char *propq = ossl_pkcs7_ctx_get0_propq(ctx);
mdc_tmp = EVP_MD_CTX_new();
if (mdc_tmp == NULL) {
- PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) {
- PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_WRONG_PKCS7_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_PKCS7_TYPE);
goto err;
}
@@ -964,22 +1044,21 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
for (;;) {
if ((btmp == NULL) ||
((btmp = BIO_find_type(btmp, BIO_TYPE_MD)) == NULL)) {
- PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
- PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
goto err;
}
BIO_get_md_ctx(btmp, &mdc);
if (mdc == NULL) {
- PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_INTERNAL_ERROR);
goto err;
}
- if (EVP_MD_CTX_type(mdc) == md_type)
+ if (EVP_MD_CTX_get_type(mdc) == md_type)
break;
/*
* Workaround for some broken clients that put the signature OID
* instead of the digest OID in digest_alg->algorithm
*/
- if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type)
+ if (EVP_MD_get_pkey_type(EVP_MD_CTX_get0_md(mdc)) == md_type)
break;
btmp = BIO_next(btmp);
}
@@ -1002,24 +1081,34 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
goto err;
message_digest = PKCS7_digest_from_attributes(sk);
if (!message_digest) {
- PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
- PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
goto err;
}
if ((message_digest->length != (int)md_len) ||
(memcmp(message_digest->data, md_dat, md_len))) {
- PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_DIGEST_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_DIGEST_FAILURE);
ret = -1;
goto err;
}
- if (!EVP_VerifyInit_ex(mdc_tmp, EVP_get_digestbynid(md_type), NULL))
+ (void)ERR_set_mark();
+ fetched_md = EVP_MD_fetch(libctx, OBJ_nid2sn(md_type), propq);
+
+ if (fetched_md != NULL)
+ md = fetched_md;
+ else
+ md = EVP_get_digestbynid(md_type);
+
+ if (md == NULL || !EVP_VerifyInit_ex(mdc_tmp, md, NULL)) {
+ (void)ERR_clear_last_mark();
goto err;
+ }
+ (void)ERR_pop_to_mark();
alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf,
ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY));
if (alen <= 0) {
- PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB);
ret = -1;
goto err;
}
@@ -1031,20 +1120,21 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
os = si->enc_digest;
pkey = X509_get0_pubkey(x509);
- if (!pkey) {
+ if (pkey == NULL) {
ret = -1;
goto err;
}
- i = EVP_VerifyFinal(mdc_tmp, os->data, os->length, pkey);
+ i = EVP_VerifyFinal_ex(mdc_tmp, os->data, os->length, pkey, libctx, propq);
if (i <= 0) {
- PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNATURE_FAILURE);
ret = -1;
goto err;
}
ret = 1;
err:
EVP_MD_CTX_free(mdc_tmp);
+ EVP_MD_free(fetched_md);
return ret;
}
@@ -1068,17 +1158,17 @@ PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
return ri->issuer_and_serial;
}
-ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid)
+ASN1_TYPE *PKCS7_get_signed_attribute(const PKCS7_SIGNER_INFO *si, int nid)
{
return get_attribute(si->auth_attr, nid);
}
-ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid)
+ASN1_TYPE *PKCS7_get_attribute(const PKCS7_SIGNER_INFO *si, int nid)
{
return get_attribute(si->unauth_attr, nid);
}
-static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid)
+static ASN1_TYPE *get_attribute(const STACK_OF(X509_ATTRIBUTE) *sk, int nid)
{
int idx;
X509_ATTRIBUTE *xa;
diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c
index ec4d9abd587f..5ce591f758f7 100644
--- a/crypto/pkcs7/pk7_lib.c
+++ b/crypto/pkcs7/pk7_lib.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,8 +11,11 @@
#include "internal/cryptlib.h"
#include <openssl/objects.h>
#include <openssl/x509.h>
+#include <openssl/pkcs7.h>
#include "crypto/asn1.h"
#include "crypto/evp.h"
+#include "crypto/x509.h" /* for sk_X509_add1_cert() */
+#include "pk7_local.h"
long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg)
{
@@ -33,28 +36,28 @@ long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg)
p7->d.sign->contents->d.data = NULL;
}
} else {
- PKCS7err(PKCS7_F_PKCS7_CTRL,
- PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE);
+ ERR_raise(ERR_LIB_PKCS7,
+ PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE);
ret = 0;
}
break;
case PKCS7_OP_GET_DETACHED_SIGNATURE:
if (nid == NID_pkcs7_signed) {
- if (!p7->d.sign || !p7->d.sign->contents->d.ptr)
+ if (p7->d.sign == NULL || p7->d.sign->contents->d.ptr == NULL)
ret = 1;
else
ret = 0;
p7->detached = ret;
} else {
- PKCS7err(PKCS7_F_PKCS7_CTRL,
- PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE);
+ ERR_raise(ERR_LIB_PKCS7,
+ PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE);
ret = 0;
}
break;
default:
- PKCS7err(PKCS7_F_PKCS7_CTRL, PKCS7_R_UNKNOWN_OPERATION);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNKNOWN_OPERATION);
ret = 0;
}
return ret;
@@ -96,7 +99,7 @@ int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data)
case NID_pkcs7_signedAndEnveloped:
case NID_pkcs7_encrypted:
default:
- PKCS7err(PKCS7_F_PKCS7_SET_CONTENT, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
goto err;
}
return 1;
@@ -167,7 +170,7 @@ int PKCS7_set_type(PKCS7 *p7, int type)
goto err;
break;
default:
- PKCS7err(PKCS7_F_PKCS7_SET_TYPE, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
goto err;
}
return 1;
@@ -184,7 +187,8 @@ int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other)
int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi)
{
- int i, j, nid;
+ int i, j;
+ ASN1_OBJECT *obj;
X509_ALGOR *alg;
STACK_OF(PKCS7_SIGNER_INFO) *signer_sk;
STACK_OF(X509_ALGOR) *md_sk;
@@ -200,36 +204,45 @@ int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi)
md_sk = p7->d.signed_and_enveloped->md_algs;
break;
default:
- PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER, PKCS7_R_WRONG_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
return 0;
}
- nid = OBJ_obj2nid(psi->digest_alg->algorithm);
-
+ obj = psi->digest_alg->algorithm;
/* If the digest is not currently listed, add it */
j = 0;
for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) {
alg = sk_X509_ALGOR_value(md_sk, i);
- if (OBJ_obj2nid(alg->algorithm) == nid) {
+ if (OBJ_cmp(obj, alg->algorithm) == 0) {
j = 1;
break;
}
}
if (!j) { /* we need to add another algorithm */
+ int nid;
+
if ((alg = X509_ALGOR_new()) == NULL
|| (alg->parameter = ASN1_TYPE_new()) == NULL) {
X509_ALGOR_free(alg);
- PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
- alg->algorithm = OBJ_nid2obj(nid);
+ /*
+ * If there is a constant copy of the ASN1 OBJECT in libcrypto, then
+ * use that. Otherwise, use a dynamically duplicated copy
+ */
+ if ((nid = OBJ_obj2nid(obj)) != NID_undef)
+ alg->algorithm = OBJ_nid2obj(nid);
+ else
+ alg->algorithm = OBJ_dup(obj);
alg->parameter->type = V_ASN1_NULL;
- if (!sk_X509_ALGOR_push(md_sk, alg)) {
+ if (alg->algorithm == NULL || !sk_X509_ALGOR_push(md_sk, alg)) {
X509_ALGOR_free(alg);
return 0;
}
}
+ psi->ctx = ossl_pkcs7_get0_ctx(p7);
if (!sk_PKCS7_SIGNER_INFO_push(signer_sk, psi))
return 0;
return 1;
@@ -249,22 +262,11 @@ int PKCS7_add_certificate(PKCS7 *p7, X509 *x509)
sk = &(p7->d.signed_and_enveloped->cert);
break;
default:
- PKCS7err(PKCS7_F_PKCS7_ADD_CERTIFICATE, PKCS7_R_WRONG_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
return 0;
}
- if (*sk == NULL)
- *sk = sk_X509_new_null();
- if (*sk == NULL) {
- PKCS7err(PKCS7_F_PKCS7_ADD_CERTIFICATE, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- X509_up_ref(x509);
- if (!sk_X509_push(*sk, x509)) {
- X509_free(x509);
- return 0;
- }
- return 1;
+ return ossl_x509_add_cert_new(sk, x509, X509_ADD_FLAG_UP_REF);
}
int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl)
@@ -281,14 +283,14 @@ int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl)
sk = &(p7->d.signed_and_enveloped->crl);
break;
default:
- PKCS7err(PKCS7_F_PKCS7_ADD_CRL, PKCS7_R_WRONG_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
return 0;
}
if (*sk == NULL)
*sk = sk_X509_CRL_new_null();
if (*sk == NULL) {
- PKCS7err(PKCS7_F_PKCS7_ADD_CRL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -300,6 +302,39 @@ int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl)
return 1;
}
+static int pkcs7_ecdsa_or_dsa_sign_verify_setup(PKCS7_SIGNER_INFO *si,
+ int verify)
+{
+ if (verify == 0) {
+ int snid, hnid;
+ X509_ALGOR *alg1, *alg2;
+ EVP_PKEY *pkey = si->pkey;
+
+ PKCS7_SIGNER_INFO_get0_algs(si, NULL, &alg1, &alg2);
+ if (alg1 == NULL || alg1->algorithm == NULL)
+ return -1;
+ hnid = OBJ_obj2nid(alg1->algorithm);
+ if (hnid == NID_undef)
+ return -1;
+ if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_get_id(pkey)))
+ return -1;
+ X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
+ }
+ return 1;
+}
+
+static int pkcs7_rsa_sign_verify_setup(PKCS7_SIGNER_INFO *si, int verify)
+{
+ if (verify == 0) {
+ X509_ALGOR *alg = NULL;
+
+ PKCS7_SIGNER_INFO_get0_algs(si, NULL, NULL, &alg);
+ if (alg != NULL)
+ X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
+ }
+ return 1;
+}
+
int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
const EVP_MD *dgst)
{
@@ -318,7 +353,7 @@ int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
*/
ASN1_INTEGER_free(p7i->issuer_and_serial->serial);
if (!(p7i->issuer_and_serial->serial =
- ASN1_INTEGER_dup(X509_get_serialNumber(x509))))
+ ASN1_INTEGER_dup(X509_get0_serialNumber(x509))))
goto err;
/* lets keep the pkey around for a while */
@@ -327,21 +362,24 @@ int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
/* Set the algorithms */
- X509_ALGOR_set0(p7i->digest_alg, OBJ_nid2obj(EVP_MD_type(dgst)),
+ X509_ALGOR_set0(p7i->digest_alg, OBJ_nid2obj(EVP_MD_get_type(dgst)),
V_ASN1_NULL, NULL);
- if (pkey->ameth && pkey->ameth->pkey_ctrl) {
+ if (EVP_PKEY_is_a(pkey, "EC") || EVP_PKEY_is_a(pkey, "DSA"))
+ return pkcs7_ecdsa_or_dsa_sign_verify_setup(p7i, 0);
+ if (EVP_PKEY_is_a(pkey, "RSA"))
+ return pkcs7_rsa_sign_verify_setup(p7i, 0);
+
+ if (pkey->ameth != NULL && pkey->ameth->pkey_ctrl != NULL) {
ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_SIGN, 0, p7i);
if (ret > 0)
return 1;
if (ret != -2) {
- PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SET,
- PKCS7_R_SIGNING_CTRL_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNING_CTRL_FAILURE);
return 0;
}
}
- PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SET,
- PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
err:
return 0;
}
@@ -357,14 +395,14 @@ PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey,
goto err;
dgst = EVP_get_digestbynid(def_nid);
if (dgst == NULL) {
- PKCS7err(PKCS7_F_PKCS7_ADD_SIGNATURE, PKCS7_R_NO_DEFAULT_DIGEST);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_DEFAULT_DIGEST);
goto err;
}
}
if ((si = PKCS7_SIGNER_INFO_new()) == NULL)
goto err;
- if (!PKCS7_SIGNER_INFO_set(si, x509, pkey, dgst))
+ if (PKCS7_SIGNER_INFO_set(si, x509, pkey, dgst) <= 0)
goto err;
if (!PKCS7_add_signer(p7, si))
goto err;
@@ -374,11 +412,116 @@ PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey,
return NULL;
}
+static STACK_OF(X509) *pkcs7_get_signer_certs(const PKCS7 *p7)
+{
+ if (p7->d.ptr == NULL)
+ return NULL;
+ if (PKCS7_type_is_signed(p7))
+ return p7->d.sign->cert;
+ if (PKCS7_type_is_signedAndEnveloped(p7))
+ return p7->d.signed_and_enveloped->cert;
+ return NULL;
+}
+
+static STACK_OF(PKCS7_RECIP_INFO) *pkcs7_get_recipient_info(const PKCS7 *p7)
+{
+ if (p7->d.ptr == NULL)
+ return NULL;
+ if (PKCS7_type_is_signedAndEnveloped(p7))
+ return p7->d.signed_and_enveloped->recipientinfo;
+ if (PKCS7_type_is_enveloped(p7))
+ return p7->d.enveloped->recipientinfo;
+ return NULL;
+}
+
+/*
+ * Set up the library context into any loaded structure that needs it.
+ * i.e loaded X509 objects.
+ */
+void ossl_pkcs7_resolve_libctx(PKCS7 *p7)
+{
+ int i;
+ const PKCS7_CTX *ctx = ossl_pkcs7_get0_ctx(p7);
+ OSSL_LIB_CTX *libctx = ossl_pkcs7_ctx_get0_libctx(ctx);
+ const char *propq = ossl_pkcs7_ctx_get0_propq(ctx);
+ STACK_OF(PKCS7_RECIP_INFO) *rinfos;
+ STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
+ STACK_OF(X509) *certs;
+
+ if (ctx == NULL || p7->d.ptr == NULL)
+ return;
+
+ rinfos = pkcs7_get_recipient_info(p7);
+ sinfos = PKCS7_get_signer_info(p7);
+ certs = pkcs7_get_signer_certs(p7);
+
+ for (i = 0; i < sk_X509_num(certs); i++)
+ ossl_x509_set0_libctx(sk_X509_value(certs, i), libctx, propq);
+
+ for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rinfos); i++) {
+ PKCS7_RECIP_INFO *ri = sk_PKCS7_RECIP_INFO_value(rinfos, i);
+
+ ossl_x509_set0_libctx(ri->cert, libctx, propq);
+ }
+
+ for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) {
+ PKCS7_SIGNER_INFO *si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
+
+ if (si != NULL)
+ si->ctx = ctx;
+ }
+}
+
+const PKCS7_CTX *ossl_pkcs7_get0_ctx(const PKCS7 *p7)
+{
+ return p7 != NULL ? &p7->ctx : NULL;
+}
+
+void ossl_pkcs7_set0_libctx(PKCS7 *p7, OSSL_LIB_CTX *ctx)
+{
+ p7->ctx.libctx = ctx;
+}
+
+int ossl_pkcs7_set1_propq(PKCS7 *p7, const char *propq)
+{
+ if (p7->ctx.propq != NULL) {
+ OPENSSL_free(p7->ctx.propq);
+ p7->ctx.propq = NULL;
+ }
+ if (propq != NULL) {
+ p7->ctx.propq = OPENSSL_strdup(propq);
+ if (p7->ctx.propq == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int ossl_pkcs7_ctx_propagate(const PKCS7 *from, PKCS7 *to)
+{
+ ossl_pkcs7_set0_libctx(to, from->ctx.libctx);
+ if (!ossl_pkcs7_set1_propq(to, from->ctx.propq))
+ return 0;
+
+ ossl_pkcs7_resolve_libctx(to);
+ return 1;
+}
+
+OSSL_LIB_CTX *ossl_pkcs7_ctx_get0_libctx(const PKCS7_CTX *ctx)
+{
+ return ctx != NULL ? ctx->libctx : NULL;
+}
+const char *ossl_pkcs7_ctx_get0_propq(const PKCS7_CTX *ctx)
+{
+ return ctx != NULL ? ctx->propq : NULL;
+}
+
int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md)
{
if (PKCS7_type_is_digest(p7)) {
if ((p7->d.digest->md->parameter = ASN1_TYPE_new()) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_SET_DIGEST, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
p7->d.digest->md->parameter->type = V_ASN1_NULL;
@@ -386,7 +529,7 @@ int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md)
return 1;
}
- PKCS7err(PKCS7_F_PKCS7_SET_DIGEST, PKCS7_R_WRONG_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
return 1;
}
@@ -425,10 +568,11 @@ PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509)
if ((ri = PKCS7_RECIP_INFO_new()) == NULL)
goto err;
- if (!PKCS7_RECIP_INFO_set(ri, x509))
+ if (PKCS7_RECIP_INFO_set(ri, x509) <= 0)
goto err;
if (!PKCS7_add_recipient_info(p7, ri))
goto err;
+ ri->ctx = ossl_pkcs7_get0_ctx(p7);
return ri;
err:
PKCS7_RECIP_INFO_free(ri);
@@ -449,8 +593,7 @@ int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri)
sk = p7->d.enveloped->recipientinfo;
break;
default:
- PKCS7err(PKCS7_F_PKCS7_ADD_RECIPIENT_INFO,
- PKCS7_R_WRONG_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
return 0;
}
@@ -459,6 +602,18 @@ int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri)
return 1;
}
+static int pkcs7_rsa_encrypt_decrypt_setup(PKCS7_RECIP_INFO *ri, int decrypt)
+{
+ X509_ALGOR *alg = NULL;
+
+ if (decrypt == 0) {
+ PKCS7_RECIP_INFO_get0_alg(ri, &alg);
+ if (alg != NULL)
+ X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
+ }
+ return 1;
+}
+
int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509)
{
int ret;
@@ -471,29 +626,38 @@ int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509)
ASN1_INTEGER_free(p7i->issuer_and_serial->serial);
if (!(p7i->issuer_and_serial->serial =
- ASN1_INTEGER_dup(X509_get_serialNumber(x509))))
+ ASN1_INTEGER_dup(X509_get0_serialNumber(x509))))
return 0;
pkey = X509_get0_pubkey(x509);
+ if (pkey == NULL)
+ return 0;
- if (!pkey || !pkey->ameth || !pkey->ameth->pkey_ctrl) {
- PKCS7err(PKCS7_F_PKCS7_RECIP_INFO_SET,
- PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+ if (EVP_PKEY_is_a(pkey, "RSA-PSS"))
+ return -2;
+ if (EVP_PKEY_is_a(pkey, "RSA")) {
+ if (pkcs7_rsa_encrypt_decrypt_setup(p7i, 0) <= 0)
+ goto err;
+ goto finished;
+ }
+
+ if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL) {
+ ERR_raise(ERR_LIB_PKCS7,
+ PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
goto err;
}
ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_ENCRYPT, 0, p7i);
if (ret == -2) {
- PKCS7err(PKCS7_F_PKCS7_RECIP_INFO_SET,
- PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+ ERR_raise(ERR_LIB_PKCS7,
+ PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
goto err;
}
if (ret <= 0) {
- PKCS7err(PKCS7_F_PKCS7_RECIP_INFO_SET,
- PKCS7_R_ENCRYPTION_CTRL_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_ENCRYPTION_CTRL_FAILURE);
goto err;
}
-
+finished:
X509_up_ref(x509);
p7i->cert = x509;
@@ -528,22 +692,23 @@ int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher)
ec = p7->d.enveloped->enc_data;
break;
default:
- PKCS7err(PKCS7_F_PKCS7_SET_CIPHER, PKCS7_R_WRONG_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
return 0;
}
/* Check cipher OID exists and has data in it */
- i = EVP_CIPHER_type(cipher);
+ i = EVP_CIPHER_get_type(cipher);
if (i == NID_undef) {
- PKCS7err(PKCS7_F_PKCS7_SET_CIPHER,
- PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
return 0;
}
ec->cipher = cipher;
+ ec->ctx = ossl_pkcs7_get0_ctx(p7);
return 1;
}
+/* unfortunately cannot constify BIO_new_NDEF() due to this and CMS_stream() */
int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7)
{
ASN1_OCTET_STRING *os = NULL;
diff --git a/crypto/pkcs7/pk7_local.h b/crypto/pkcs7/pk7_local.h
new file mode 100644
index 000000000000..8deb342b7913
--- /dev/null
+++ b/crypto/pkcs7/pk7_local.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "crypto/pkcs7.h"
+
+const PKCS7_CTX *ossl_pkcs7_get0_ctx(const PKCS7 *p7);
+OSSL_LIB_CTX *ossl_pkcs7_ctx_get0_libctx(const PKCS7_CTX *ctx);
+const char *ossl_pkcs7_ctx_get0_propq(const PKCS7_CTX *ctx);
+
+int ossl_pkcs7_ctx_propagate(const PKCS7 *from, PKCS7 *to);
diff --git a/crypto/pkcs7/pk7_mime.c b/crypto/pkcs7/pk7_mime.c
index 19e6868148b8..49a0da5f819c 100644
--- a/crypto/pkcs7/pk7_mime.c
+++ b/crypto/pkcs7/pk7_mime.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,6 +11,7 @@
#include "internal/cryptlib.h"
#include <openssl/x509.h>
#include <openssl/asn1.h>
+#include "pk7_local.h"
/* PKCS#7 wrappers round generalised stream and MIME routines */
@@ -30,6 +31,8 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
{
STACK_OF(X509_ALGOR) *mdalgs;
int ctype_nid = OBJ_obj2nid(p7->type);
+ const PKCS7_CTX *ctx = ossl_pkcs7_get0_ctx(p7);
+
if (ctype_nid == NID_pkcs7_signed)
mdalgs = p7->d.sign->md_algs;
else
@@ -37,12 +40,31 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
flags ^= SMIME_OLDMIME;
- return SMIME_write_ASN1(bio, (ASN1_VALUE *)p7, data, flags,
- ctype_nid, NID_undef, mdalgs,
- ASN1_ITEM_rptr(PKCS7));
+ return SMIME_write_ASN1_ex(bio, (ASN1_VALUE *)p7, data, flags, ctype_nid,
+ NID_undef, mdalgs, ASN1_ITEM_rptr(PKCS7),
+ ossl_pkcs7_ctx_get0_libctx(ctx),
+ ossl_pkcs7_ctx_get0_propq(ctx));
+}
+
+PKCS7 *SMIME_read_PKCS7_ex(BIO *bio, BIO **bcont, PKCS7 **p7)
+{
+ PKCS7 *ret;
+ OSSL_LIB_CTX *libctx = NULL;
+ const char *propq = NULL;
+
+ if (p7 != NULL && *p7 != NULL) {
+ libctx = (*p7)->ctx.libctx;
+ propq = (*p7)->ctx.propq;
+ }
+
+ ret = (PKCS7 *)SMIME_read_ASN1_ex(bio, 0, bcont, ASN1_ITEM_rptr(PKCS7),
+ (ASN1_VALUE **)p7, libctx, propq);
+ if (ret != NULL)
+ ossl_pkcs7_resolve_libctx(ret);
+ return ret;
}
PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont)
{
- return (PKCS7 *)SMIME_read_ASN1(bio, bcont, ASN1_ITEM_rptr(PKCS7));
+ return SMIME_read_PKCS7_ex(bio, bcont, NULL);
}
diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c
index a95db62178ed..4593da8f5b41 100644
--- a/crypto/pkcs7/pk7_smime.c
+++ b/crypto/pkcs7/pk7_smime.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,20 +13,22 @@
#include "internal/cryptlib.h"
#include <openssl/x509.h>
#include <openssl/x509v3.h>
-
+#include "pk7_local.h"
#define BUFFERSIZE 4096
+
static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si);
-PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
- BIO *data, int flags)
+PKCS7 *PKCS7_sign_ex(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+ BIO *data, int flags, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
PKCS7 *p7;
int i;
- if ((p7 = PKCS7_new()) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_SIGN, ERR_R_MALLOC_FAILURE);
+ if ((p7 = PKCS7_new_ex(libctx, propq)) == NULL) {
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -37,7 +39,7 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
goto err;
if (pkey && !PKCS7_sign_add_signer(p7, signcert, pkey, NULL, flags)) {
- PKCS7err(PKCS7_F_PKCS7_SIGN, PKCS7_R_PKCS7_ADD_SIGNER_ERROR);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_PKCS7_ADD_SIGNER_ERROR);
goto err;
}
@@ -62,28 +64,34 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
return NULL;
}
+PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+ BIO *data, int flags)
+{
+ return PKCS7_sign_ex(signcert, pkey, certs, data, flags, NULL, NULL);
+}
+
+
int PKCS7_final(PKCS7 *p7, BIO *data, int flags)
{
BIO *p7bio;
int ret = 0;
if ((p7bio = PKCS7_dataInit(p7, NULL)) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_FINAL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
- SMIME_crlf_copy(data, p7bio, flags);
+ if (!SMIME_crlf_copy(data, p7bio, flags))
+ goto err;
(void)BIO_flush(p7bio);
if (!PKCS7_dataFinal(p7, p7bio)) {
- PKCS7err(PKCS7_F_PKCS7_FINAL, PKCS7_R_PKCS7_DATASIGN);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_PKCS7_DATASIGN);
goto err;
}
-
ret = 1;
-
- err:
+err:
BIO_free_all(p7bio);
return ret;
@@ -112,18 +120,19 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert,
{
PKCS7_SIGNER_INFO *si = NULL;
STACK_OF(X509_ALGOR) *smcap = NULL;
+
if (!X509_check_private_key(signcert, pkey)) {
- PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER,
- PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
+ ERR_raise(ERR_LIB_PKCS7,
+ PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
return NULL;
}
if ((si = PKCS7_add_signature(p7, signcert, pkey, md)) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER,
- PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR);
return NULL;
}
+ si->ctx = ossl_pkcs7_get0_ctx(p7);
if (!(flags & PKCS7_NOCERTS)) {
if (!PKCS7_add_certificate(p7, signcert))
goto err;
@@ -135,7 +144,7 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert,
/* Add SMIMECapabilities */
if (!(flags & PKCS7_NOSMIMECAP)) {
if ((smcap = sk_X509_ALGOR_new_null()) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!add_cipher_smcap(smcap, NID_aes_256_cbc, -1)
@@ -158,7 +167,8 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert,
if (flags & PKCS7_REUSE_DIGEST) {
if (!pkcs7_copy_existing_digest(p7, si))
goto err;
- if (!(flags & PKCS7_PARTIAL) && !PKCS7_SIGNER_INFO_sign(si))
+ if (!(flags & PKCS7_PARTIAL)
+ && !PKCS7_SIGNER_INFO_sign(si))
goto err;
}
}
@@ -193,11 +203,10 @@ static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si)
}
- if (osdig)
+ if (osdig != NULL)
return PKCS7_add1_attrib_digest(si, osdig->data, osdig->length);
- PKCS7err(PKCS7_F_PKCS7_COPY_EXISTING_DIGEST,
- PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND);
return 0;
}
@@ -213,20 +222,21 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
int i, j = 0, k, ret = 0;
BIO *p7bio = NULL;
BIO *tmpin = NULL, *tmpout = NULL;
+ const PKCS7_CTX *p7_ctx;
- if (!p7) {
- PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_INVALID_NULL_POINTER);
+ if (p7 == NULL) {
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER);
return 0;
}
if (!PKCS7_type_is_signed(p7)) {
- PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_WRONG_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
return 0;
}
/* Check for no data and no content: no data to verify signature */
if (PKCS7_get_detached(p7) && !indata) {
- PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_NO_CONTENT);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
return 0;
}
@@ -239,7 +249,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
* process is different, but the existing PKCs7 verification works.
*/
if (!PKCS7_get_detached(p7) && indata) {
- PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_CONTENT_AND_DATA_PRESENT);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_CONTENT_AND_DATA_PRESENT);
return 0;
}
}
@@ -247,17 +257,18 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
sinfos = PKCS7_get_signer_info(p7);
if (!sinfos || !sk_PKCS7_SIGNER_INFO_num(sinfos)) {
- PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_NO_SIGNATURES_ON_DATA);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_SIGNATURES_ON_DATA);
return 0;
}
signers = PKCS7_get0_signers(p7, certs, flags);
- if (!signers)
+ if (signers == NULL)
return 0;
/* Now verify the certificates */
-
- cert_ctx = X509_STORE_CTX_new();
+ p7_ctx = ossl_pkcs7_get0_ctx(p7);
+ cert_ctx = X509_STORE_CTX_new_ex(ossl_pkcs7_ctx_get0_libctx(p7_ctx),
+ ossl_pkcs7_ctx_get0_propq(p7_ctx));
if (cert_ctx == NULL)
goto err;
if (!(flags & PKCS7_NOVERIFY))
@@ -266,12 +277,13 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
if (!(flags & PKCS7_NOCHAIN)) {
if (!X509_STORE_CTX_init(cert_ctx, store, signer,
p7->d.sign->cert)) {
- PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_X509_LIB);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_X509_LIB);
goto err;
}
- X509_STORE_CTX_set_default(cert_ctx, "smime_sign");
+ if (!X509_STORE_CTX_set_default(cert_ctx, "smime_sign"))
+ goto err;
} else if (!X509_STORE_CTX_init(cert_ctx, store, signer, NULL)) {
- PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_X509_LIB);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_X509_LIB);
goto err;
}
if (!(flags & PKCS7_NOCRL))
@@ -279,12 +291,10 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
i = X509_verify_cert(cert_ctx);
if (i <= 0)
j = X509_STORE_CTX_get_error(cert_ctx);
- X509_STORE_CTX_cleanup(cert_ctx);
if (i <= 0) {
- PKCS7err(PKCS7_F_PKCS7_VERIFY,
- PKCS7_R_CERTIFICATE_VERIFY_ERROR);
- ERR_add_error_data(2, "Verify error:",
- X509_verify_cert_error_string(j));
+ ERR_raise_data(ERR_LIB_PKCS7, PKCS7_R_CERTIFICATE_VERIFY_ERROR,
+ "Verify error: %s",
+ X509_verify_cert_error_string(j));
goto err;
}
/* Check for revocation status here */
@@ -303,7 +313,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
len = BIO_get_mem_data(indata, &ptr);
tmpin = (len == 0) ? indata : BIO_new_mem_buf(ptr, len);
if (tmpin == NULL) {
- PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
} else
@@ -314,7 +324,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
if (flags & PKCS7_TEXT) {
if ((tmpout = BIO_new(BIO_s_mem())) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
BIO_set_mem_eof_return(tmpout, 0);
@@ -323,7 +333,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
/* We now have to 'read' from p7bio to calculate digests etc. */
if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
for (;;) {
@@ -336,7 +346,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
if (flags & PKCS7_TEXT) {
if (!SMIME_text(tmpout, out)) {
- PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_SMIME_TEXT_ERROR);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SMIME_TEXT_ERROR);
BIO_free(tmpout);
goto err;
}
@@ -350,7 +360,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
signer = sk_X509_value(signers, i);
j = PKCS7_signatureVerify(p7bio, p7, si, signer);
if (j <= 0) {
- PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_SIGNATURE_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNATURE_FAILURE);
goto err;
}
}
@@ -379,13 +389,13 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs,
X509 *signer;
int i;
- if (!p7) {
- PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS, PKCS7_R_INVALID_NULL_POINTER);
+ if (p7 == NULL) {
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER);
return NULL;
}
if (!PKCS7_type_is_signed(p7)) {
- PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS, PKCS7_R_WRONG_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
return NULL;
}
@@ -394,12 +404,12 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs,
sinfos = PKCS7_get_signer_info(p7);
if (sk_PKCS7_SIGNER_INFO_num(sinfos) <= 0) {
- PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS, PKCS7_R_NO_SIGNERS);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_SIGNERS);
return 0;
}
if ((signers = sk_X509_new_null()) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -417,8 +427,7 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs,
X509_find_by_issuer_and_serial(p7->d.sign->cert,
ias->issuer, ias->serial);
if (!signer) {
- PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,
- PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND);
sk_X509_free(signers);
return 0;
}
@@ -433,29 +442,31 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs,
/* Build a complete PKCS#7 enveloped data */
-PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
- int flags)
+PKCS7 *PKCS7_encrypt_ex(STACK_OF(X509) *certs, BIO *in,
+ const EVP_CIPHER *cipher, int flags,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
PKCS7 *p7;
BIO *p7bio = NULL;
int i;
X509 *x509;
- if ((p7 = PKCS7_new()) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_ENCRYPT, ERR_R_MALLOC_FAILURE);
+
+ if ((p7 = PKCS7_new_ex(libctx, propq)) == NULL) {
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (!PKCS7_set_type(p7, NID_pkcs7_enveloped))
goto err;
if (!PKCS7_set_cipher(p7, cipher)) {
- PKCS7err(PKCS7_F_PKCS7_ENCRYPT, PKCS7_R_ERROR_SETTING_CIPHER);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_ERROR_SETTING_CIPHER);
goto err;
}
for (i = 0; i < sk_X509_num(certs); i++) {
x509 = sk_X509_value(certs, i);
if (!PKCS7_add_recipient(p7, x509)) {
- PKCS7err(PKCS7_F_PKCS7_ENCRYPT, PKCS7_R_ERROR_ADDING_RECIPIENT);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_ERROR_ADDING_RECIPIENT);
goto err;
}
}
@@ -474,30 +485,37 @@ PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
}
+PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
+ int flags)
+{
+ return PKCS7_encrypt_ex(certs, in, cipher, flags, NULL, NULL);
+}
+
+
int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
{
BIO *tmpmem;
int ret = 0, i;
char *buf = NULL;
- if (!p7) {
- PKCS7err(PKCS7_F_PKCS7_DECRYPT, PKCS7_R_INVALID_NULL_POINTER);
+ if (p7 == NULL) {
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER);
return 0;
}
if (!PKCS7_type_is_enveloped(p7)) {
- PKCS7err(PKCS7_F_PKCS7_DECRYPT, PKCS7_R_WRONG_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
return 0;
}
if (cert && !X509_check_private_key(cert, pkey)) {
- PKCS7err(PKCS7_F_PKCS7_DECRYPT,
- PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
+ ERR_raise(ERR_LIB_PKCS7,
+ PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
return 0;
}
if ((tmpmem = PKCS7_dataDecode(p7, pkey, NULL, cert)) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DECRYPT, PKCS7_R_DECRYPT_ERROR);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_DECRYPT_ERROR);
return 0;
}
@@ -505,26 +523,26 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
BIO *tmpbuf, *bread;
/* Encrypt BIOs can't do BIO_gets() so add a buffer BIO */
if ((tmpbuf = BIO_new(BIO_f_buffer())) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
BIO_free_all(tmpmem);
return 0;
}
if ((bread = BIO_push(tmpbuf, tmpmem)) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
BIO_free_all(tmpbuf);
BIO_free_all(tmpmem);
return 0;
}
ret = SMIME_text(bread, data);
if (ret > 0 && BIO_method_type(tmpmem) == BIO_TYPE_CIPHER) {
- if (!BIO_get_cipher_status(tmpmem))
+ if (BIO_get_cipher_status(tmpmem) <= 0)
ret = 0;
}
BIO_free_all(bread);
return ret;
}
if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL) {
- PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
goto err;
}
for (;;) {
@@ -532,7 +550,7 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
if (i <= 0) {
ret = 1;
if (BIO_method_type(tmpmem) == BIO_TYPE_CIPHER) {
- if (!BIO_get_cipher_status(tmpmem))
+ if (BIO_get_cipher_status(tmpmem) <= 0)
ret = 0;
}
diff --git a/crypto/pkcs7/pkcs7err.c b/crypto/pkcs7/pkcs7err.c
index 07490c1a5878..cd839511e31c 100644
--- a/crypto/pkcs7/pkcs7err.c
+++ b/crypto/pkcs7/pkcs7err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,66 +10,10 @@
#include <openssl/err.h>
#include <openssl/pkcs7err.h>
+#include "crypto/pkcs7err.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA PKCS7_str_functs[] = {
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, 0),
- "do_pkcs7_signed_attrib"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ADD0_ATTRIB_SIGNING_TIME, 0),
- "PKCS7_add0_attrib_signing_time"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP, 0),
- "PKCS7_add_attrib_smimecap"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ADD_CERTIFICATE, 0),
- "PKCS7_add_certificate"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ADD_CRL, 0), "PKCS7_add_crl"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ADD_RECIPIENT_INFO, 0),
- "PKCS7_add_recipient_info"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ADD_SIGNATURE, 0),
- "PKCS7_add_signature"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ADD_SIGNER, 0), "PKCS7_add_signer"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_BIO_ADD_DIGEST, 0),
- "PKCS7_bio_add_digest"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_COPY_EXISTING_DIGEST, 0),
- "pkcs7_copy_existing_digest"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_CTRL, 0), "PKCS7_ctrl"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_DATADECODE, 0), "PKCS7_dataDecode"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_DATAFINAL, 0), "PKCS7_dataFinal"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_DATAINIT, 0), "PKCS7_dataInit"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_DATAVERIFY, 0), "PKCS7_dataVerify"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_DECRYPT, 0), "PKCS7_decrypt"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_DECRYPT_RINFO, 0),
- "pkcs7_decrypt_rinfo"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ENCODE_RINFO, 0),
- "pkcs7_encode_rinfo"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ENCRYPT, 0), "PKCS7_encrypt"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_FINAL, 0), "PKCS7_final"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_FIND_DIGEST, 0),
- "PKCS7_find_digest"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_GET0_SIGNERS, 0),
- "PKCS7_get0_signers"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_RECIP_INFO_SET, 0),
- "PKCS7_RECIP_INFO_set"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SET_CIPHER, 0), "PKCS7_set_cipher"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SET_CONTENT, 0),
- "PKCS7_set_content"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SET_DIGEST, 0), "PKCS7_set_digest"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SET_TYPE, 0), "PKCS7_set_type"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SIGN, 0), "PKCS7_sign"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SIGNATUREVERIFY, 0),
- "PKCS7_signatureVerify"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SIGNER_INFO_SET, 0),
- "PKCS7_SIGNER_INFO_set"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SIGNER_INFO_SIGN, 0),
- "PKCS7_SIGNER_INFO_sign"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SIGN_ADD_SIGNER, 0),
- "PKCS7_sign_add_signer"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SIMPLE_SMIMECAP, 0),
- "PKCS7_simple_smimecap"},
- {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_VERIFY, 0), "PKCS7_verify"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA PKCS7_str_reasons[] = {
{ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_CERTIFICATE_VERIFY_ERROR),
"certificate verify error"},
@@ -144,13 +88,11 @@ static const ERR_STRING_DATA PKCS7_str_reasons[] = {
#endif
-int ERR_load_PKCS7_strings(void)
+int ossl_err_load_PKCS7_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(PKCS7_str_functs[0].error) == NULL) {
- ERR_load_strings_const(PKCS7_str_functs);
+ if (ERR_reason_error_string(PKCS7_str_reasons[0].error) == NULL)
ERR_load_strings_const(PKCS7_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/poly1305/asm/poly1305-armv4.pl b/crypto/poly1305/asm/poly1305-armv4.pl
index 70f46cd140aa..041bfd46e699 100755
--- a/crypto/poly1305/asm/poly1305-armv4.pl
+++ b/crypto/poly1305/asm/poly1305-armv4.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -28,9 +28,10 @@
# the cost of 15/12% regression on Cortex-A5/A7, it's even possible
# to improve Cortex-A9 result, but then A5/A7 loose more than 20%;
-$flavour = shift;
-if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour && $flavour ne "void") {
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -38,9 +39,10 @@ if ($flavour && $flavour ne "void") {
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
- open STDOUT,"| \"$^X\" $xlate $flavour $output";
+ open STDOUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
} else {
- open STDOUT,">$output";
+ $output and open STDOUT,">$output";
}
($ctx,$inp,$len,$padbit)=map("r$_",(0..3));
@@ -48,7 +50,6 @@ if ($flavour && $flavour ne "void") {
$code.=<<___;
#include "arm_arch.h"
-.text
#if defined(__thumb2__)
.syntax unified
.thumb
@@ -56,6 +57,8 @@ $code.=<<___;
.code 32
#endif
+.text
+
.globl poly1305_emit
.globl poly1305_blocks
.globl poly1305_init
@@ -100,8 +103,10 @@ poly1305_init:
and r4,r4,r10
#if __ARM_MAX_ARCH__>=7
+# if !defined(_WIN32)
ldr r12,[r11,r12] @ OPENSSL_armcap_P
-# ifdef __APPLE__
+# endif
+# if defined(__APPLE__) || defined(_WIN32)
ldr r12,[r12]
# endif
#endif
@@ -116,32 +121,22 @@ poly1305_init:
#if __ARM_MAX_ARCH__>=7
tst r12,#ARMV7_NEON @ check for NEON
-# ifdef __APPLE__
- adr r9,poly1305_blocks_neon
- adr r11,poly1305_blocks
-# ifdef __thumb2__
- it ne
-# endif
+# ifdef __thumb2__
+ adr r9,.Lpoly1305_blocks_neon
+ adr r11,.Lpoly1305_blocks
+ adr r12,.Lpoly1305_emit
+ adr r10,.Lpoly1305_emit_neon
+ itt ne
movne r11,r9
- adr r12,poly1305_emit
- adr r10,poly1305_emit_neon
-# ifdef __thumb2__
- it ne
-# endif
movne r12,r10
+ orr r11,r11,#1 @ thumb-ify address
+ orr r12,r12,#1
# else
-# ifdef __thumb2__
- itete eq
-# endif
addeq r12,r11,#(.Lpoly1305_emit-.Lpoly1305_init)
addne r12,r11,#(.Lpoly1305_emit_neon-.Lpoly1305_init)
addeq r11,r11,#(.Lpoly1305_blocks-.Lpoly1305_init)
addne r11,r11,#(.Lpoly1305_blocks_neon-.Lpoly1305_init)
# endif
-# ifdef __thumb2__
- orr r12,r12,#1 @ thumb-ify address
- orr r11,r11,#1
-# endif
#endif
ldrb r9,[$inp,#11]
orr r6,r6,r7,lsl#8
@@ -1232,7 +1227,11 @@ poly1305_emit_neon:
.Lzeros:
.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.LOPENSSL_armcap:
+# ifdef _WIN32
+.word OPENSSL_armcap_P
+# else
.word OPENSSL_armcap_P-.Lpoly1305_init
+# endif
#endif
___
} }
diff --git a/crypto/poly1305/asm/poly1305-armv8.pl b/crypto/poly1305/asm/poly1305-armv8.pl
index 2a42b64a929c..113a2151b6fa 100755
--- a/crypto/poly1305/asm/poly1305-armv8.pl
+++ b/crypto/poly1305/asm/poly1305-armv8.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -29,20 +29,24 @@
# X-Gene 2.13/+68% 2.27
# Mongoose 1.77/+75% 1.12
# Kryo 2.70/+55% 1.13
+# ThunderX2 1.17/+95% 1.36
#
# (*) estimate based on resources availability is less than 1.0,
# i.e. measured result is worse than expected, presumably binary
# translator is not almighty;
-$flavour=shift;
-$output=shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
my ($ctx,$inp,$len,$padbit) = map("x$_",(0..3));
@@ -75,17 +79,12 @@ poly1305_init:
csel x0,xzr,x0,eq
b.eq .Lno_key
-#ifdef __ILP32__
- ldrsw $t1,.LOPENSSL_armcap_P
-#else
- ldr $t1,.LOPENSSL_armcap_P
-#endif
- adr $t0,.LOPENSSL_armcap_P
+ adrp x17,OPENSSL_armcap_P
+ ldr w17,[x17,#:lo12:OPENSSL_armcap_P]
ldp $r0,$r1,[$inp] // load key
mov $s1,#0xfffffffc0fffffff
movk $s1,#0x0fff,lsl#48
- ldr w17,[$t0,$t1]
#ifdef __ARMEB__
rev $r0,$r0 // flip bytes
rev $r1,$r1
@@ -97,10 +96,10 @@ poly1305_init:
tst w17,#ARMV7_NEON
- adr $d0,poly1305_blocks
- adr $r0,poly1305_blocks_neon
- adr $d1,poly1305_emit
- adr $r1,poly1305_emit_neon
+ adr $d0,.Lpoly1305_blocks
+ adr $r0,.Lpoly1305_blocks_neon
+ adr $d1,.Lpoly1305_emit
+ adr $r1,.Lpoly1305_emit_neon
csel $d0,$d0,$r0,eq
csel $d1,$d1,$r1,eq
@@ -119,6 +118,7 @@ poly1305_init:
.type poly1305_blocks,%function
.align 5
poly1305_blocks:
+.Lpoly1305_blocks:
ands $len,$len,#-16
b.eq .Lno_data
@@ -183,6 +183,7 @@ poly1305_blocks:
.type poly1305_emit,%function
.align 5
poly1305_emit:
+.Lpoly1305_emit:
ldp $h0,$h1,[$ctx] // load hash base 2^64
ldr $h2,[$ctx,#16]
ldp $t0,$t1,[$nonce] // load nonce
@@ -289,10 +290,11 @@ poly1305_splat:
.type poly1305_blocks_neon,%function
.align 5
poly1305_blocks_neon:
+.Lpoly1305_blocks_neon:
ldr $is_base2_26,[$ctx,#24]
cmp $len,#128
b.hs .Lblocks_neon
- cbz $is_base2_26,poly1305_blocks
+ cbz $is_base2_26,.Lpoly1305_blocks
.Lblocks_neon:
.inst 0xd503233f // paciasp
@@ -435,7 +437,7 @@ poly1305_blocks_neon:
csel $in2,$zeros,$in2,lo
mov x4,#1
- str x4,[$ctx,#-24] // set is_base2_26
+ stur x4,[$ctx,#-24] // set is_base2_26
sub $ctx,$ctx,#48 // restore original $ctx
b .Ldo_neon
@@ -872,6 +874,7 @@ poly1305_blocks_neon:
.type poly1305_emit_neon,%function
.align 5
poly1305_emit_neon:
+.Lpoly1305_emit_neon:
ldr $is_base2_26,[$ctx,#24]
cbz $is_base2_26,poly1305_emit
@@ -924,12 +927,6 @@ poly1305_emit_neon:
.align 5
.Lzeros:
.long 0,0,0,0,0,0,0,0
-.LOPENSSL_armcap_P:
-#ifdef __ILP32__
-.long OPENSSL_armcap_P-.
-#else
-.quad OPENSSL_armcap_P-.
-#endif
.asciz "Poly1305 for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
.align 2
___
diff --git a/crypto/poly1305/asm/poly1305-c64xplus.pl b/crypto/poly1305/asm/poly1305-c64xplus.pl
index 93fef37e605b..2bcdced7f45c 100755
--- a/crypto/poly1305/asm/poly1305-c64xplus.pl
+++ b/crypto/poly1305/asm/poly1305-c64xplus.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -26,8 +26,7 @@
# time dependent on input length. This module on the other hand is free
# from such limitation.
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
($CTXA,$INPB,$LEN,$PADBIT)=("A4","B4","A6","B6");
($H0,$H1,$H2,$H3,$H4,$H4a)=("A8","B8","A10","B10","B2",$LEN);
diff --git a/crypto/poly1305/asm/poly1305-ia64.S b/crypto/poly1305/asm/poly1305-ia64.S
new file mode 100644
index 000000000000..54d6454f0322
--- /dev/null
+++ b/crypto/poly1305/asm/poly1305-ia64.S
@@ -0,0 +1,365 @@
+// ====================================================================
+// Written by Andy Polyakov, @dot-asm, initially for use in the OpenSSL
+// project.
+// ====================================================================
+//
+// Poly1305 for Itanium.
+//
+// January 2019
+//
+// Performance was reported to be ~2.1 cycles per byte on Itanium 2.
+// With exception for processors in 95xx family, which have higher
+// floating-point instructions' latencies and deliver ~2.6 cpb.
+// Comparison to compiler-generated code is not exactly fair, because
+// of different radixes. But just for reference, it was observed to be
+// >3x faster. Originally it was argued that floating-point base 2^32
+// implementation would be optimal. Upon closer look estimate for below
+// integer base 2^64 implementation turned to be approximately same on
+// Itanium 2. But floating-point code would be larger, and have higher
+// overhead, which would negatively affect small-block performance...
+
+#if defined(_HPUX_SOURCE)
+# if !defined(_LP64)
+# define ADDP addp4
+# else
+# define ADDP add
+# endif
+# define RUM rum
+# define SUM sum
+#else
+# define ADDP add
+# define RUM nop
+# define SUM nop
+#endif
+
+.text
+.explicit
+
+.global poly1305_init#
+.proc poly1305_init#
+.align 64
+poly1305_init:
+ .prologue
+ .save ar.pfs,r2
+{ .mmi; alloc r2=ar.pfs,2,0,0,0
+ cmp.eq p6,p7=0,r33 } // key == NULL?
+{ .mmi; ADDP r9=8,r32
+ ADDP r10=16,r32
+ ADDP r32=0,r32 };;
+ .body
+{ .mmi; st8 [r32]=r0,24 // ctx->h0 = 0
+ st8 [r9]=r0 // ctx->h1 = 0
+(p7) ADDP r8=0,r33 }
+{ .mib; st8 [r10]=r0 // ctx->h2 = 0
+(p6) mov r8=0
+(p6) br.ret.spnt b0 };;
+
+{ .mmi; ADDP r9=1,r33
+ ADDP r10=2,r33
+ ADDP r11=3,r33 };;
+{ .mmi; ld1 r16=[r8],4 // load key, little-endian
+ ld1 r17=[r9],4 }
+{ .mmi; ld1 r18=[r10],4
+ ld1 r19=[r11],4 };;
+{ .mmi; ld1 r20=[r8],4
+ ld1 r21=[r9],4 }
+{ .mmi; ld1 r22=[r10],4
+ ld1 r23=[r11],4
+ and r19=15,r19 };;
+{ .mmi; ld1 r24=[r8],4
+ ld1 r25=[r9],4
+ and r20=-4,r20 }
+{ .mmi; ld1 r26=[r10],4
+ ld1 r27=[r11],4
+ and r23=15,r23 };;
+{ .mmi; ld1 r28=[r8],4
+ ld1 r29=[r9],4
+ and r24=-4,r24 }
+{ .mmi; ld1 r30=[r10],4
+ ld1 r31=[r11],4
+ and r27=15,r27 };;
+
+{ .mii; and r28=-4,r28
+ dep r16=r17,r16,8,8
+ dep r18=r19,r18,8,8 };;
+{ .mii; and r31=15,r31
+ dep r16=r18,r16,16,16
+ dep r20=r21,r20,8,8 };;
+{ .mii; dep r16=r20,r16,32,16
+ dep r22=r23,r22,8,8 };;
+{ .mii; dep r16=r22,r16,48,16
+ dep r24=r25,r24,8,8 };;
+{ .mii; dep r26=r27,r26,8,8
+ dep r28=r29,r28,8,8 };;
+{ .mii; dep r24=r26,r24,16,16
+ dep r30=r31,r30,8,8 };;
+{ .mii; st8 [r32]=r16,8 // ctx->r0
+ dep r24=r28,r24,32,16;;
+ dep r24=r30,r24,48,16 };;
+{ .mii; st8 [r32]=r24,8 // ctx->r1
+ shr.u r25=r24,2;;
+ add r25=r25,r24 };;
+{ .mib; st8 [r32]=r25 // ctx->s1
+ mov r8=0
+ br.ret.sptk b0 };;
+.endp poly1305_init#
+
+h0=r17; h1=r18; h2=r19;
+i0=r20; i1=r21;
+HF0=f8; HF1=f9; HF2=f10;
+RF0=f11; RF1=f12; SF1=f13;
+
+.global poly1305_blocks#
+.proc poly1305_blocks#
+.align 64
+poly1305_blocks:
+ .prologue
+ .save ar.pfs,r2
+{ .mii; alloc r2=ar.pfs,4,1,0,0
+ .save ar.lc,r3
+ mov r3=ar.lc
+ .save pr,r36
+ mov r36=pr }
+
+ .body
+{ .mmi; ADDP r8=0,r32
+ ADDP r9=8,r32
+ and r29=7,r33 };;
+{ .mmi; ld8 h0=[r8],16
+ ld8 h1=[r9],16
+ and r33=-8,r33 };;
+{ .mmi; ld8 h2=[r8],16
+ ldf8 RF0=[r9],16
+ shr.u r34=r34,4 };;
+{ .mmi; ldf8 RF1=[r8],-32
+ ldf8 SF1=[r9],-32
+ cmp.ltu p16,p17=1,r34 };;
+{ .mmi;
+(p16) add r34=-2,r34
+(p17) mov r34=0
+ ADDP r10=0,r33 }
+{ .mii; ADDP r11=8,r33
+(p16) mov ar.ec=2
+(p17) mov ar.ec=1 };;
+{ .mib; RUM 1<<1 // go little-endian
+ mov ar.lc=r34
+ brp.loop.imp .Loop,.Lcend-16 }
+
+{ .mmi; cmp.eq p8,p7=0,r29
+ cmp.eq p9,p0=1,r29
+ cmp.eq p10,p0=2,r29 }
+{ .mmi; cmp.eq p11,p0=3,r29
+ cmp.eq p12,p0=4,r29
+ cmp.eq p13,p0=5,r29 }
+{ .mmi; cmp.eq p14,p0=6,r29
+ cmp.eq p15,p0=7,r29
+ add r16=16,r10 };;
+
+{ .mmb;
+(p8) ld8 i0=[r10],16 // aligned input
+(p8) ld8 i1=[r11],16
+(p8) br.cond.sptk .Loop };;
+
+ // align first block
+ .pred.rel "mutex",p8,p9,p10,p11,p12,p13,p14,p15
+{ .mmi; (p7) ld8 r14=[r10],24
+ (p7) ld8 r15=[r11],24 }
+
+{ .mii; (p7) ld8 r16=[r16]
+ nop.i 0;;
+ (p15) shrp i0=r15,r14,56 }
+{ .mii; (p15) shrp i1=r16,r15,56
+ (p14) shrp i0=r15,r14,48 }
+{ .mii; (p14) shrp i1=r16,r15,48
+ (p13) shrp i0=r15,r14,40 }
+{ .mii; (p13) shrp i1=r16,r15,40
+ (p12) shrp i0=r15,r14,32 }
+{ .mii; (p12) shrp i1=r16,r15,32
+ (p11) shrp i0=r15,r14,24 }
+{ .mii; (p11) shrp i1=r16,r15,24
+ (p10) shrp i0=r15,r14,16 }
+{ .mii; (p10) shrp i1=r16,r15,16
+ (p9) shrp i0=r15,r14,8 }
+{ .mii; (p9) shrp i1=r16,r15,8
+ mov r14=r16 };;
+
+.Loop:
+ .pred.rel "mutex",p8,p9,p10,p11,p12,p13,p14,p15
+{ .mmi; add h0=h0,i0
+ add h1=h1,i1
+ add h2=h2,r35 };;
+{ .mmi; setf.sig HF0=h0
+ cmp.ltu p6,p0=h0,i0
+ cmp.ltu p7,p0=h1,i1 };;
+{ .mmi; (p6) add h1=1,h1;;
+ setf.sig HF1=h1
+ (p6) cmp.eq.or p7,p0=0,h1 };;
+{ .mmi; (p7) add h2=1,h2;;
+ setf.sig HF2=h2 };;
+
+{ .mfi; (p16) ld8 r15=[r10],16
+ xmpy.lu f32=HF0,RF0 }
+{ .mfi; (p16) ld8 r16=[r11],16
+ xmpy.hu f33=HF0,RF0 }
+{ .mfi; xmpy.lu f36=HF0,RF1 }
+{ .mfi; xmpy.hu f37=HF0,RF1 };;
+{ .mfi; xmpy.lu f34=HF1,SF1
+ (p15) shrp i0=r15,r14,56 }
+{ .mfi; xmpy.hu f35=HF1,SF1 }
+{ .mfi; xmpy.lu f38=HF1,RF0
+ (p15) shrp i1=r16,r15,56 }
+{ .mfi; xmpy.hu f39=HF1,RF0 }
+{ .mfi; xmpy.lu f40=HF2,SF1
+ (p14) shrp i0=r15,r14,48 }
+{ .mfi; xmpy.lu f41=HF2,RF0 };;
+
+{ .mmi; getf.sig r22=f32
+ getf.sig r23=f33
+ (p14) shrp i1=r16,r15,48 }
+{ .mmi; getf.sig r24=f34
+ getf.sig r25=f35
+ (p13) shrp i0=r15,r14,40 }
+{ .mmi; getf.sig r26=f36
+ getf.sig r27=f37
+ (p13) shrp i1=r16,r15,40 }
+{ .mmi; getf.sig r28=f38
+ getf.sig r29=f39
+ (p12) shrp i0=r15,r14,32 }
+{ .mmi; getf.sig r30=f40
+ getf.sig r31=f41 };;
+
+{ .mmi; add h0=r22,r24
+ add r23=r23,r25
+ (p12) shrp i1=r16,r15,32 }
+{ .mmi; add h1=r26,r28
+ add r27=r27,r29
+ (p11) shrp i0=r15,r14,24 };;
+{ .mmi; cmp.ltu p6,p0=h0,r24
+ cmp.ltu p7,p0=h1,r28
+ add r23=r23,r30 };;
+{ .mmi; (p6) add r23=1,r23
+ (p7) add r27=1,r27
+ (p11) shrp i1=r16,r15,24 };;
+{ .mmi; add h1=h1,r23;;
+ cmp.ltu p6,p7=h1,r23
+ (p10) shrp i0=r15,r14,16 };;
+{ .mmi; (p6) add h2=r31,r27,1
+ (p7) add h2=r31,r27
+ (p10) shrp i1=r16,r15,16 };;
+
+{ .mmi; (p8) mov i0=r15
+ and r22=-4,h2
+ shr.u r23=h2,2 };;
+{ .mmi; add r22=r22,r23
+ and h2=3,h2
+ (p9) shrp i0=r15,r14,8 };;
+
+{ .mmi; add h0=h0,r22;;
+ cmp.ltu p6,p0=h0,r22
+ (p9) shrp i1=r16,r15,8 };;
+{ .mmi; (p8) mov i1=r16
+ (p6) cmp.eq.unc p7,p0=-1,h1
+ (p6) add h1=1,h1 };;
+{ .mmb; (p7) add h2=1,h2
+ mov r14=r16
+ br.ctop.sptk .Loop };;
+.Lcend:
+
+{ .mii; SUM 1<<1 // back to big-endian
+ mov ar.lc=r3 };;
+
+{ .mmi; st8 [r8]=h0,16
+ st8 [r9]=h1
+ mov pr=r36,0x1ffff };;
+{ .mmb; st8 [r8]=h2
+ rum 1<<5
+ br.ret.sptk b0 };;
+.endp poly1305_blocks#
+
+.global poly1305_emit#
+.proc poly1305_emit#
+.align 64
+poly1305_emit:
+ .prologue
+ .save ar.pfs,r2
+{ .mmi; alloc r2=ar.pfs,3,0,0,0
+ ADDP r8=0,r32
+ ADDP r9=8,r32 };;
+
+ .body
+{ .mmi; ld8 r16=[r8],16 // load hash
+ ld8 r17=[r9]
+ ADDP r10=0,r34 };;
+{ .mmi; ld8 r18=[r8]
+ ld4 r24=[r10],8 // load nonce
+ ADDP r11=4,r34 };;
+
+{ .mmi; ld4 r25=[r11],8
+ ld4 r26=[r10]
+ add r20=5,r16 };;
+
+{ .mmi; ld4 r27=[r11]
+ cmp.ltu p6,p7=r20,r16
+ shl r25=r25,32 };;
+{ .mmi;
+(p6) add r21=1,r17
+(p7) add r21=0,r17
+(p6) cmp.eq.or.andcm p6,p7=-1,r17 };;
+{ .mmi;
+(p6) add r22=1,r18
+(p7) add r22=0,r18
+ shl r27=r27,32 };;
+{ .mmi; or r24=r24,r25
+ or r26=r26,r27
+ cmp.leu p6,p7=4,r22 };;
+{ .mmi;
+(p6) add r16=r20,r24
+(p7) add r16=r16,r24
+(p6) add r17=r21,r26 };;
+{ .mii;
+(p7) add r17=r17,r26
+ cmp.ltu p6,p7=r16,r24;;
+(p6) add r17=1,r17 };;
+
+{ .mmi; ADDP r8=0,r33
+ ADDP r9=4,r33
+ shr.u r20=r16,32 }
+{ .mmi; ADDP r10=8,r33
+ ADDP r11=12,r33
+ shr.u r21=r17,32 };;
+
+{ .mmi; st1 [r8]=r16,1 // write mac, little-endian
+ st1 [r9]=r20,1
+ shr.u r16=r16,8 }
+{ .mii; st1 [r10]=r17,1
+ shr.u r20=r20,8
+ shr.u r17=r17,8 }
+{ .mmi; st1 [r11]=r21,1
+ shr.u r21=r21,8 };;
+
+{ .mmi; st1 [r8]=r16,1
+ st1 [r9]=r20,1
+ shr.u r16=r16,8 }
+{ .mii; st1 [r10]=r17,1
+ shr.u r20=r20,8
+ shr.u r17=r17,8 }
+{ .mmi; st1 [r11]=r21,1
+ shr.u r21=r21,8 };;
+
+{ .mmi; st1 [r8]=r16,1
+ st1 [r9]=r20,1
+ shr.u r16=r16,8 }
+{ .mii; st1 [r10]=r17,1
+ shr.u r20=r20,8
+ shr.u r17=r17,8 }
+{ .mmi; st1 [r11]=r21,1
+ shr.u r21=r21,8 };;
+
+{ .mmi; st1 [r8]=r16
+ st1 [r9]=r20 }
+{ .mmb; st1 [r10]=r17
+ st1 [r11]=r21
+ br.ret.sptk b0 };;
+.endp poly1305_emit#
+
+stringz "Poly1305 for IA64, CRYPTOGAMS by \@dot-asm"
diff --git a/crypto/poly1305/asm/poly1305-mips.pl b/crypto/poly1305/asm/poly1305-mips.pl
index 965825dc3eda..6c0b3292d07c 100755
--- a/crypto/poly1305/asm/poly1305-mips.pl
+++ b/crypto/poly1305/asm/poly1305-mips.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -56,7 +56,11 @@
#
######################################################################
-$flavour = shift || "o32"; # supported flavours are o32,n32,64,nubi32,nubi64
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+# supported flavours are o32,n32,64,nubi32,nubi64, default is o32
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : "o32";
die "MIPS64 only" unless ($flavour =~ /64|n32/i);
@@ -431,7 +435,7 @@ poly1305_emit:
___
}
-$output=pop and open STDOUT,">$output";
+$output and open STDOUT,">$output";
print $code;
close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/poly1305/asm/poly1305-ppc.pl b/crypto/poly1305/asm/poly1305-ppc.pl
index e5d6933ac4d5..9f86134d923f 100755
--- a/crypto/poly1305/asm/poly1305-ppc.pl
+++ b/crypto/poly1305/asm/poly1305-ppc.pl
@@ -1,17 +1,17 @@
#! /usr/bin/env perl
# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#
# ====================================================================
-# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
-# project. The module is, however, dual licensed under OpenSSL and
-# CRYPTOGAMS licenses depending on where you obtain it. For further
-# details see http://www.openssl.org/~appro/cryptogams/.
+# Written by Andy Polyakov, @dot-asm, initially for use in the OpenSSL
+# project. The module is dual licensed under OpenSSL and CRYPTOGAMS
+# licenses depending on where you obtain it. For further details see
+# https://github.com/dot-asm/cryptogams/.
# ====================================================================
#
# This module implements Poly1305 hash for PowerPC.
@@ -44,8 +44,18 @@
#
# On side note, Power ISA 2.07 enables vector base 2^26 implementation,
# and POWER8 might have capacity to break 1.0 cycle per byte barrier...
+#
+# January 2019
+#
+# ... Unfortunately not:-( Estimate was a projection of ARM result,
+# but ARM has vector multiply-n-add instruction, while PowerISA does
+# not, not one usable in the context. Improvement is ~40% over -m64
+# result above and is ~1.43 on little-endian systems.
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /64/) {
$SIZE_T =8;
@@ -72,7 +82,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
+open STDOUT,"| $^X $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
$FRAME=24*$SIZE_T;
@@ -99,6 +110,7 @@ $code.=<<___;
std r0,0($ctx) # zero hash value
std r0,8($ctx)
std r0,16($ctx)
+ stw r0,24($ctx) # clear is_base2_26
$UCMP $inp,r0
beq- Lno_key
@@ -140,6 +152,7 @@ Lno_key:
.globl .poly1305_blocks
.align 4
.poly1305_blocks:
+Lpoly1305_blocks:
srdi. $len,$len,4
beq- Labort
@@ -238,60 +251,120 @@ Labort:
.long 0
.byte 0,12,4,1,0x80,5,4,0
.size .poly1305_blocks,.-.poly1305_blocks
+___
+{
+my ($h0,$h1,$h2,$h3,$h4,$t0) = map("r$_",(7..12));
+$code.=<<___;
.globl .poly1305_emit
-.align 4
+.align 5
.poly1305_emit:
- ld $h0,0($ctx) # load hash
- ld $h1,8($ctx)
- ld $h2,16($ctx)
- ld $padbit,0($nonce) # load nonce
- ld $nonce,8($nonce)
-
- addic $d0,$h0,5 # compare to modulus
- addze $d1,$h1
- addze $d2,$h2
-
- srdi $mask,$d2,2 # did it carry/borrow?
- neg $mask,$mask
+ lwz $h0,0($ctx) # load hash value base 2^26
+ lwz $h1,4($ctx)
+ lwz $h2,8($ctx)
+ lwz $h3,12($ctx)
+ lwz $h4,16($ctx)
+ lwz r0,24($ctx) # is_base2_26
+
+ sldi $h1,$h1,26 # base 2^26 -> base 2^64
+ sldi $t0,$h2,52
+ srdi $h2,$h2,12
+ sldi $h3,$h3,14
+ add $h0,$h0,$h1
+ addc $h0,$h0,$t0
+ sldi $t0,$h4,40
+ srdi $h4,$h4,24
+ adde $h1,$h2,$h3
+ addc $h1,$h1,$t0
+ addze $h2,$h4
+
+ ld $h3,0($ctx) # load hash value base 2^64
+ ld $h4,8($ctx)
+ ld $t0,16($ctx)
+
+ neg r0,r0
+ xor $h0,$h0,$h3 # choose between radixes
+ xor $h1,$h1,$h4
+ xor $h2,$h2,$t0
+ and $h0,$h0,r0
+ and $h1,$h1,r0
+ and $h2,$h2,r0
+ xor $h0,$h0,$h3
+ xor $h1,$h1,$h4
+ xor $h2,$h2,$t0
+
+ addic $h3,$h0,5 # compare to modulus
+ addze $h4,$h1
+ addze $t0,$h2
+
+ srdi $t0,$t0,2 # see if it carried/borrowed
+ neg $t0,$t0
+
+ andc $h0,$h0,$t0
+ and $h3,$h3,$t0
+ andc $h1,$h1,$t0
+ and $h4,$h4,$t0
+ or $h0,$h0,$h3
+ or $h1,$h1,$h4
+
+ lwz $t0,4($nonce)
+ lwz $h2,12($nonce)
+ lwz $h3,0($nonce)
+ lwz $h4,8($nonce)
+
+ insrdi $h3,$t0,32,0
+ insrdi $h4,$h2,32,0
+
+ addc $h0,$h0,$h3 # accumulate nonce
+ adde $h1,$h1,$h4
+
+ addi $ctx,$mac,-1
+ addi $mac,$mac,7
+
+ stbu $h0,1($ctx) # write [little-endian] result
+ srdi $h0,$h0,8
+ stbu $h1,1($mac)
+ srdi $h1,$h1,8
+
+ stbu $h0,1($ctx)
+ srdi $h0,$h0,8
+ stbu $h1,1($mac)
+ srdi $h1,$h1,8
+
+ stbu $h0,1($ctx)
+ srdi $h0,$h0,8
+ stbu $h1,1($mac)
+ srdi $h1,$h1,8
+
+ stbu $h0,1($ctx)
+ srdi $h0,$h0,8
+ stbu $h1,1($mac)
+ srdi $h1,$h1,8
+
+ stbu $h0,1($ctx)
+ srdi $h0,$h0,8
+ stbu $h1,1($mac)
+ srdi $h1,$h1,8
+
+ stbu $h0,1($ctx)
+ srdi $h0,$h0,8
+ stbu $h1,1($mac)
+ srdi $h1,$h1,8
+
+ stbu $h0,1($ctx)
+ srdi $h0,$h0,8
+ stbu $h1,1($mac)
+ srdi $h1,$h1,8
+
+ stbu $h0,1($ctx)
+ stbu $h1,1($mac)
- andc $h0,$h0,$mask
- and $d0,$d0,$mask
- andc $h1,$h1,$mask
- and $d1,$d1,$mask
- or $h0,$h0,$d0
- or $h1,$h1,$d1
-___
-$code.=<<___ if (!$LITTLE_ENDIAN);
- rotldi $padbit,$padbit,32 # flip nonce words
- rotldi $nonce,$nonce,32
-___
-$code.=<<___;
- addc $h0,$h0,$padbit # accumulate nonce
- adde $h1,$h1,$nonce
-___
-$code.=<<___ if ($LITTLE_ENDIAN);
- std $h0,0($mac) # write result
- std $h1,8($mac)
-___
-$code.=<<___ if (!$LITTLE_ENDIAN);
- extrdi r0,$h0,32,0
- li $d0,4
- stwbrx $h0,0,$mac # write result
- extrdi $h0,$h1,32,0
- li $d1,8
- stwbrx r0,$d0,$mac
- li $d2,12
- stwbrx $h1,$d1,$mac
- stwbrx $h0,$d2,$mac
-___
-$code.=<<___;
blr
.long 0
.byte 0,12,0x14,0,0,0,3,0
.size .poly1305_emit,.-.poly1305_emit
___
- } else {
+} } else {
###############################################################################
# base 2^32 implementation
@@ -309,6 +382,7 @@ $code.=<<___;
stw r0,8($ctx)
stw r0,12($ctx)
stw r0,16($ctx)
+ stw r0,24($ctx) # clear is_base2_26
$UCMP $inp,r0
beq- Lno_key
@@ -353,6 +427,7 @@ Lno_key:
.globl .poly1305_blocks
.align 4
.poly1305_blocks:
+Lpoly1305_blocks:
srwi. $len,$len,4
beq- Labort
@@ -560,17 +635,389 @@ Labort:
.long 0
.byte 0,12,4,1,0x80,18,4,0
.size .poly1305_blocks,.-.poly1305_blocks
+___
+{
+my ($h0,$h1,$h2,$h3,$h4,$t0,$t1) = map("r$_",(6..12));
+$code.=<<___;
.globl .poly1305_emit
-.align 4
+.align 5
.poly1305_emit:
- $STU $sp,-$FRAME($sp)
+ lwz r0,24($ctx) # is_base2_26
+ lwz $h0,0($ctx) # load hash value
+ lwz $h1,4($ctx)
+ lwz $h2,8($ctx)
+ lwz $h3,12($ctx)
+ lwz $h4,16($ctx)
+ cmplwi r0,0
+ beq Lemit_base2_32
+
+ slwi $t0,$h1,26 # base 2^26 -> base 2^32
+ srwi $h1,$h1,6
+ slwi $t1,$h2,20
+ srwi $h2,$h2,12
+ addc $h0,$h0,$t0
+ slwi $t0,$h3,14
+ srwi $h3,$h3,18
+ adde $h1,$h1,$t1
+ slwi $t1,$h4,8
+ srwi $h4,$h4,24
+ adde $h2,$h2,$t0
+ adde $h3,$h3,$t1
+ addze $h4,$h4
+
+Lemit_base2_32:
+ addic r0,$h0,5 # compare to modulus
+ addze r0,$h1
+ addze r0,$h2
+ addze r0,$h3
+ addze r0,$h4
+
+ srwi r0,r0,2 # see if it carried/borrowed
+ neg r0,r0
+ andi. r0,r0,5
+
+ addc $h0,$h0,r0
+ lwz r0,0($nonce)
+ addze $h1,$h1
+ lwz $t0,4($nonce)
+ addze $h2,$h2
+ lwz $t1,8($nonce)
+ addze $h3,$h3
+ lwz $h4,12($nonce)
+
+ addc $h0,$h0,r0 # accumulate nonce
+ adde $h1,$h1,$t0
+ adde $h2,$h2,$t1
+ adde $h3,$h3,$h4
+
+ addi $ctx,$mac,-1
+ addi $mac,$mac,7
+
+ stbu $h0,1($ctx) # write [little-endian] result
+ srwi $h0,$h0,8
+ stbu $h2,1($mac)
+ srwi $h2,$h2,8
+
+ stbu $h0,1($ctx)
+ srwi $h0,$h0,8
+ stbu $h2,1($mac)
+ srwi $h2,$h2,8
+
+ stbu $h0,1($ctx)
+ srwi $h0,$h0,8
+ stbu $h2,1($mac)
+ srwi $h2,$h2,8
+
+ stbu $h0,1($ctx)
+ stbu $h2,1($mac)
+
+ stbu $h1,1($ctx)
+ srwi $h1,$h1,8
+ stbu $h3,1($mac)
+ srwi $h3,$h3,8
+
+ stbu $h1,1($ctx)
+ srwi $h1,$h1,8
+ stbu $h3,1($mac)
+ srwi $h3,$h3,8
+
+ stbu $h1,1($ctx)
+ srwi $h1,$h1,8
+ stbu $h3,1($mac)
+ srwi $h3,$h3,8
+
+ stbu $h1,1($ctx)
+ stbu $h3,1($mac)
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,3,0
+.size .poly1305_emit,.-.poly1305_emit
+___
+} }
+{{{
+########################################################################
+# PowerISA 2.07/VSX section #
+########################################################################
+
+my $LOCALS= 6*$SIZE_T;
+my $VSXFRAME = $LOCALS + 6*$SIZE_T;
+ $VSXFRAME += 128; # local variables
+ $VSXFRAME += 13*16; # v20-v31 offload
+
+my $BIG_ENDIAN = ($flavour !~ /le/) ? 4 : 0;
+
+########################################################################
+# Layout of opaque area is following:
+#
+# unsigned __int32 h[5]; # current hash value base 2^26
+# unsigned __int32 pad;
+# unsigned __int32 is_base2_26, pad;
+# unsigned __int64 r[2]; # key value base 2^64
+# struct { unsigned __int32 r^2, r^4, r^1, r^3; } r[9];
+#
+# where r^n are base 2^26 digits of powers of multiplier key. There are
+# 5 digits, but last four are interleaved with multiples of 5, totalling
+# in 9 elements: r0, r1, 5*r1, r2, 5*r2, r3, 5*r3, r4, 5*r4. Order of
+# powers is as they appear in register, not memory.
+
+my ($H0, $H1, $H2, $H3, $H4) = map("v$_",(0..4));
+my ($I0, $I1, $I2, $I3, $I4) = map("v$_",(5..9));
+my ($R0, $R1, $S1, $R2, $S2) = map("v$_",(10..14));
+my ($R3, $S3, $R4, $S4) = ($R1, $S1, $R2, $S2);
+my ($ACC0, $ACC1, $ACC2, $ACC3, $ACC4) = map("v$_",(15..19));
+my ($T0, $T1, $T2, $T3, $T4) = map("v$_",(20..24));
+my ($_26,$_4,$_40,$_14,$mask26,$padbits,$I2perm) = map("v$_",(25..31));
+my ($x00,$x60,$x70,$x10,$x20,$x30,$x40,$x50) = (0, map("r$_",(7,8,27..31)));
+my ($ctx_,$_ctx,$const) = map("r$_",(10..12));
+
+ if ($flavour =~ /64/) {
+###############################################################################
+# setup phase of poly1305_blocks_vsx is different on 32- and 64-bit platforms,
+# but the base 2^26 computational part is same...
+
+my ($h0,$h1,$h2,$d0,$d1,$d2, $r0,$r1,$s1, $t0,$t1) = map("r$_",(6..11,27..31));
+my $mask = "r0";
+
+$code.=<<___;
+.globl .poly1305_blocks_vsx
+.align 5
+.poly1305_blocks_vsx:
+ lwz r7,24($ctx) # is_base2_26
+ cmpldi $len,128
+ bge __poly1305_blocks_vsx
+
+ neg r0,r7 # is_base2_26 as mask
+ lwz r7,0($ctx) # load hash base 2^26
+ lwz r8,4($ctx)
+ lwz r9,8($ctx)
+ lwz r10,12($ctx)
+ lwz r11,16($ctx)
+
+ sldi r8,r8,26 # base 2^26 -> base 2^64
+ sldi r12,r9,52
+ add r7,r7,r8
+ srdi r9,r9,12
+ sldi r10,r10,14
+ addc r7,r7,r12
+ sldi r8,r11,40
+ adde r9,r9,r10
+ srdi r11,r11,24
+ addc r9,r9,r8
+ addze r11,r11
+
+ ld r8,0($ctx) # load hash base 2^64
+ ld r10,8($ctx)
+ ld r12,16($ctx)
+
+ xor r7,r7,r8 # select between radixes
+ xor r9,r9,r10
+ xor r11,r11,r12
+ and r7,r7,r0
+ and r9,r9,r0
+ and r11,r11,r0
+ xor r7,r7,r8
+ xor r9,r9,r10
+ xor r11,r11,r12
+
+ li r0,0
+ std r7,0($ctx) # store hash base 2^64
+ std r9,8($ctx)
+ std r11,16($ctx)
+ stw r0,24($ctx) # clear is_base2_26
+
+ b Lpoly1305_blocks
+ .long 0
+ .byte 0,12,0x14,0,0,0,4,0
+.size .poly1305_blocks_vsx,.-.poly1305_blocks_vsx
+
+.align 5
+__poly1305_mul:
+ mulld $d0,$h0,$r0 # h0*r0
+ mulhdu $d1,$h0,$r0
+
+ mulld $t0,$h1,$s1 # h1*5*r1
+ mulhdu $t1,$h1,$s1
+ addc $d0,$d0,$t0
+ adde $d1,$d1,$t1
+
+ mulld $t0,$h0,$r1 # h0*r1
+ mulhdu $d2,$h0,$r1
+ addc $d1,$d1,$t0
+ addze $d2,$d2
+
+ mulld $t0,$h1,$r0 # h1*r0
+ mulhdu $t1,$h1,$r0
+ addc $d1,$d1,$t0
+ adde $d2,$d2,$t1
+
+ mulld $t0,$h2,$s1 # h2*5*r1
+ mulld $t1,$h2,$r0 # h2*r0
+ addc $d1,$d1,$t0
+ adde $d2,$d2,$t1
+
+ andc $t0,$d2,$mask # final reduction step
+ and $h2,$d2,$mask
+ srdi $t1,$t0,2
+ add $t0,$t0,$t1
+ addc $h0,$d0,$t0
+ addze $h1,$d1
+ addze $h2,$h2
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,0,0
+.size __poly1305_mul,.-__poly1305_mul
+
+.align 5
+__poly1305_splat:
+ extrdi $d0,$h0,26,38
+ extrdi $d1,$h0,26,12
+ stw $d0,0x00($t1)
+
+ extrdi $d2,$h0,12,0
+ slwi $d0,$d1,2
+ stw $d1,0x10($t1)
+ add $d0,$d0,$d1 # * 5
+ stw $d0,0x20($t1)
+
+ insrdi $d2,$h1,14,38
+ slwi $d0,$d2,2
+ stw $d2,0x30($t1)
+ add $d0,$d0,$d2 # * 5
+ stw $d0,0x40($t1)
+
+ extrdi $d1,$h1,26,24
+ extrdi $d2,$h1,24,0
+ slwi $d0,$d1,2
+ stw $d1,0x50($t1)
+ add $d0,$d0,$d1 # * 5
+ stw $d0,0x60($t1)
+
+ insrdi $d2,$h2,3,37
+ slwi $d0,$d2,2
+ stw $d2,0x70($t1)
+ add $d0,$d0,$d2 # * 5
+ stw $d0,0x80($t1)
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,0,0
+.size __poly1305_splat,.-__poly1305_splat
+
+.align 5
+__poly1305_blocks_vsx:
+ $STU $sp,-$VSXFRAME($sp)
mflr r0
- $PUSH r28,`$FRAME-$SIZE_T*4`($sp)
- $PUSH r29,`$FRAME-$SIZE_T*3`($sp)
- $PUSH r30,`$FRAME-$SIZE_T*2`($sp)
- $PUSH r31,`$FRAME-$SIZE_T*1`($sp)
- $PUSH r0,`$FRAME+$LRSAVE`($sp)
+ li r10,`15+$LOCALS+128`
+ li r11,`31+$LOCALS+128`
+ mfspr r12,256
+ stvx v20,r10,$sp
+ addi r10,r10,32
+ stvx v21,r11,$sp
+ addi r11,r11,32
+ stvx v22,r10,$sp
+ addi r10,r10,32
+ stvx v23,r10,$sp
+ addi r10,r10,32
+ stvx v24,r11,$sp
+ addi r11,r11,32
+ stvx v25,r10,$sp
+ addi r10,r10,32
+ stvx v26,r10,$sp
+ addi r10,r10,32
+ stvx v27,r11,$sp
+ addi r11,r11,32
+ stvx v28,r10,$sp
+ addi r10,r10,32
+ stvx v29,r11,$sp
+ addi r11,r11,32
+ stvx v30,r10,$sp
+ stvx v31,r11,$sp
+ stw r12,`$VSXFRAME-$SIZE_T*5-4`($sp)# save vrsave
+ li r12,-1
+ mtspr 256,r12 # preserve all AltiVec registers
+ $PUSH r27,`$VSXFRAME-$SIZE_T*5`($sp)
+ $PUSH r28,`$VSXFRAME-$SIZE_T*4`($sp)
+ $PUSH r29,`$VSXFRAME-$SIZE_T*3`($sp)
+ $PUSH r30,`$VSXFRAME-$SIZE_T*2`($sp)
+ $PUSH r31,`$VSXFRAME-$SIZE_T*1`($sp)
+ $PUSH r0,`$VSXFRAME+$LRSAVE`($sp)
+
+ bl LPICmeup
+
+ li $x10,0x10
+ li $x20,0x20
+ li $x30,0x30
+ li $x40,0x40
+ li $x50,0x50
+ lvx_u $mask26,$x00,$const
+ lvx_u $_26,$x10,$const
+ lvx_u $_40,$x20,$const
+ lvx_u $I2perm,$x30,$const
+ lvx_u $padbits,$x40,$const
+
+ cmplwi r7,0 # is_base2_26?
+ bne Lskip_init_vsx
+
+ ld $r0,32($ctx) # load key base 2^64
+ ld $r1,40($ctx)
+ srdi $s1,$r1,2
+ li $mask,3
+ add $s1,$s1,$r1 # s1 = r1 + r1>>2
+
+ mr $h0,$r0 # "calculate" r^1
+ mr $h1,$r1
+ li $h2,0
+ addi $t1,$ctx,`48+(12^$BIG_ENDIAN)`
+ bl __poly1305_splat
+
+ bl __poly1305_mul # calculate r^2
+ addi $t1,$ctx,`48+(4^$BIG_ENDIAN)`
+ bl __poly1305_splat
+
+ bl __poly1305_mul # calculate r^3
+ addi $t1,$ctx,`48+(8^$BIG_ENDIAN)`
+ bl __poly1305_splat
+
+ bl __poly1305_mul # calculate r^4
+ addi $t1,$ctx,`48+(0^$BIG_ENDIAN)`
+ bl __poly1305_splat
+
+ ld $h0,0($ctx) # load hash
+ ld $h1,8($ctx)
+ ld $h2,16($ctx)
+
+ extrdi $d0,$h0,26,38 # base 2^64 -> base 2^26
+ extrdi $d1,$h0,26,12
+ extrdi $d2,$h0,12,0
+ mtvrwz $H0,$d0
+ insrdi $d2,$h1,14,38
+ mtvrwz $H1,$d1
+ extrdi $d1,$h1,26,24
+ mtvrwz $H2,$d2
+ extrdi $d2,$h1,24,0
+ mtvrwz $H3,$d1
+ insrdi $d2,$h2,3,37
+ mtvrwz $H4,$d2
+___
+ } else {
+###############################################################################
+# 32-bit initialization
+
+my ($h0,$h1,$h2,$h3,$h4,$t0,$t1) = map("r$_",(7..11,0,12));
+my ($R3,$S3,$R4,$S4)=($I1,$I2,$I3,$I4);
+
+$code.=<<___;
+.globl .poly1305_blocks_vsx
+.align 5
+.poly1305_blocks_vsx:
+ lwz r7,24($ctx) # is_base2_26
+ cmplwi $len,128
+ bge __poly1305_blocks_vsx
+ cmplwi r7,0
+ beq Lpoly1305_blocks
lwz $h0,0($ctx) # load hash
lwz $h1,4($ctx)
@@ -578,68 +1025,957 @@ Labort:
lwz $h3,12($ctx)
lwz $h4,16($ctx)
- addic $d0,$h0,5 # compare to modulus
- addze $d1,$h1
- addze $d2,$h2
- addze $d3,$h3
- addze $mask,$h4
+ slwi $t0,$h1,26 # base 2^26 -> base 2^32
+ srwi $h1,$h1,6
+ slwi $t1,$h2,20
+ srwi $h2,$h2,12
+ addc $h0,$h0,$t0
+ slwi $t0,$h3,14
+ srwi $h3,$h3,18
+ adde $h1,$h1,$t1
+ slwi $t1,$h4,8
+ srwi $h4,$h4,24
+ adde $h2,$h2,$t0
+ li $t0,0
+ adde $h3,$h3,$t1
+ addze $h4,$h4
- srwi $mask,$mask,2 # did it carry/borrow?
- neg $mask,$mask
+ stw $h0,0($ctx) # store hash base 2^32
+ stw $h1,4($ctx)
+ stw $h2,8($ctx)
+ stw $h3,12($ctx)
+ stw $h4,16($ctx)
+ stw $t0,24($ctx) # clear is_base2_26
- andc $h0,$h0,$mask
- and $d0,$d0,$mask
- andc $h1,$h1,$mask
- and $d1,$d1,$mask
- or $h0,$h0,$d0
- lwz $d0,0($nonce) # load nonce
- andc $h2,$h2,$mask
- and $d2,$d2,$mask
- or $h1,$h1,$d1
- lwz $d1,4($nonce)
- andc $h3,$h3,$mask
- and $d3,$d3,$mask
- or $h2,$h2,$d2
- lwz $d2,8($nonce)
- or $h3,$h3,$d3
- lwz $d3,12($nonce)
-
- addc $h0,$h0,$d0 # accumulate nonce
- adde $h1,$h1,$d1
- adde $h2,$h2,$d2
- adde $h3,$h3,$d3
-___
-$code.=<<___ if ($LITTLE_ENDIAN);
- stw $h0,0($mac) # write result
- stw $h1,4($mac)
- stw $h2,8($mac)
- stw $h3,12($mac)
-___
-$code.=<<___ if (!$LITTLE_ENDIAN);
- li $d1,4
- stwbrx $h0,0,$mac # write result
- li $d2,8
- stwbrx $h1,$d1,$mac
- li $d3,12
- stwbrx $h2,$d2,$mac
- stwbrx $h3,$d3,$mac
+ b Lpoly1305_blocks
+ .long 0
+ .byte 0,12,0x14,0,0,0,4,0
+.size .poly1305_blocks_vsx,.-.poly1305_blocks_vsx
+
+.align 5
+__poly1305_mul:
+ vmulouw $ACC0,$H0,$R0
+ vmulouw $ACC1,$H1,$R0
+ vmulouw $ACC2,$H2,$R0
+ vmulouw $ACC3,$H3,$R0
+ vmulouw $ACC4,$H4,$R0
+
+ vmulouw $T0,$H4,$S1
+ vaddudm $ACC0,$ACC0,$T0
+ vmulouw $T0,$H0,$R1
+ vaddudm $ACC1,$ACC1,$T0
+ vmulouw $T0,$H1,$R1
+ vaddudm $ACC2,$ACC2,$T0
+ vmulouw $T0,$H2,$R1
+ vaddudm $ACC3,$ACC3,$T0
+ vmulouw $T0,$H3,$R1
+ vaddudm $ACC4,$ACC4,$T0
+
+ vmulouw $T0,$H3,$S2
+ vaddudm $ACC0,$ACC0,$T0
+ vmulouw $T0,$H4,$S2
+ vaddudm $ACC1,$ACC1,$T0
+ vmulouw $T0,$H0,$R2
+ vaddudm $ACC2,$ACC2,$T0
+ vmulouw $T0,$H1,$R2
+ vaddudm $ACC3,$ACC3,$T0
+ vmulouw $T0,$H2,$R2
+ vaddudm $ACC4,$ACC4,$T0
+
+ vmulouw $T0,$H2,$S3
+ vaddudm $ACC0,$ACC0,$T0
+ vmulouw $T0,$H3,$S3
+ vaddudm $ACC1,$ACC1,$T0
+ vmulouw $T0,$H4,$S3
+ vaddudm $ACC2,$ACC2,$T0
+ vmulouw $T0,$H0,$R3
+ vaddudm $ACC3,$ACC3,$T0
+ vmulouw $T0,$H1,$R3
+ vaddudm $ACC4,$ACC4,$T0
+
+ vmulouw $T0,$H1,$S4
+ vaddudm $ACC0,$ACC0,$T0
+ vmulouw $T0,$H2,$S4
+ vaddudm $ACC1,$ACC1,$T0
+ vmulouw $T0,$H3,$S4
+ vaddudm $ACC2,$ACC2,$T0
+ vmulouw $T0,$H4,$S4
+ vaddudm $ACC3,$ACC3,$T0
+ vmulouw $T0,$H0,$R4
+ vaddudm $ACC4,$ACC4,$T0
+
+ ################################################################
+ # lazy reduction
+
+ vspltisb $T0,2
+ vsrd $H4,$ACC3,$_26
+ vsrd $H1,$ACC0,$_26
+ vand $H3,$ACC3,$mask26
+ vand $H0,$ACC0,$mask26
+ vaddudm $H4,$H4,$ACC4 # h3 -> h4
+ vaddudm $H1,$H1,$ACC1 # h0 -> h1
+
+ vsrd $ACC4,$H4,$_26
+ vsrd $ACC1,$H1,$_26
+ vand $H4,$H4,$mask26
+ vand $H1,$H1,$mask26
+ vaddudm $H0,$H0,$ACC4
+ vaddudm $H2,$ACC2,$ACC1 # h1 -> h2
+
+ vsld $ACC4,$ACC4,$T0 # <<2
+ vsrd $ACC2,$H2,$_26
+ vand $H2,$H2,$mask26
+ vaddudm $H0,$H0,$ACC4 # h4 -> h0
+ vaddudm $H3,$H3,$ACC2 # h2 -> h3
+
+ vsrd $ACC0,$H0,$_26
+ vsrd $ACC3,$H3,$_26
+ vand $H0,$H0,$mask26
+ vand $H3,$H3,$mask26
+ vaddudm $H1,$H1,$ACC0 # h0 -> h1
+ vaddudm $H4,$H4,$ACC3 # h3 -> h4
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,0,0
+.size __poly1305_mul,.-__poly1305_mul
+
+.align 5
+__poly1305_blocks_vsx:
+ $STU $sp,-$VSXFRAME($sp)
+ mflr r0
+ li r10,`15+$LOCALS+128`
+ li r11,`31+$LOCALS+128`
+ mfspr r12,256
+ stvx v20,r10,$sp
+ addi r10,r10,32
+ stvx v21,r11,$sp
+ addi r11,r11,32
+ stvx v22,r10,$sp
+ addi r10,r10,32
+ stvx v23,r10,$sp
+ addi r10,r10,32
+ stvx v24,r11,$sp
+ addi r11,r11,32
+ stvx v25,r10,$sp
+ addi r10,r10,32
+ stvx v26,r10,$sp
+ addi r10,r10,32
+ stvx v27,r11,$sp
+ addi r11,r11,32
+ stvx v28,r10,$sp
+ addi r10,r10,32
+ stvx v29,r11,$sp
+ addi r11,r11,32
+ stvx v30,r10,$sp
+ stvx v31,r11,$sp
+ stw r12,`$VSXFRAME-$SIZE_T*5-4`($sp)# save vrsave
+ li r12,-1
+ mtspr 256,r12 # preserve all AltiVec registers
+ $PUSH r27,`$VSXFRAME-$SIZE_T*5`($sp)
+ $PUSH r28,`$VSXFRAME-$SIZE_T*4`($sp)
+ $PUSH r29,`$VSXFRAME-$SIZE_T*3`($sp)
+ $PUSH r30,`$VSXFRAME-$SIZE_T*2`($sp)
+ $PUSH r31,`$VSXFRAME-$SIZE_T*1`($sp)
+ $PUSH r0,`$VSXFRAME+$LRSAVE`($sp)
+
+ bl LPICmeup
+
+ li $x10,0x10
+ li $x20,0x20
+ li $x30,0x30
+ li $x40,0x40
+ li $x50,0x50
+ lvx_u $mask26,$x00,$const
+ lvx_u $_26,$x10,$const
+ lvx_u $_40,$x20,$const
+ lvx_u $I2perm,$x30,$const
+ lvx_u $padbits,$x40,$const
+
+ cmplwi r7,0 # is_base2_26?
+ bne Lskip_init_vsx
+
+ lwz $h1,32($ctx) # load key base 2^32
+ lwz $h2,36($ctx)
+ lwz $h3,40($ctx)
+ lwz $h4,44($ctx)
+
+ extrwi $h0,$h1,26,6 # base 2^32 -> base 2^26
+ extrwi $h1,$h1,6,0
+ insrwi $h1,$h2,20,6
+ extrwi $h2,$h2,12,0
+ insrwi $h2,$h3,14,6
+ extrwi $h3,$h3,18,0
+ insrwi $h3,$h4,8,6
+ extrwi $h4,$h4,24,0
+
+ mtvrwz $R0,$h0
+ slwi $h0,$h1,2
+ mtvrwz $R1,$h1
+ add $h1,$h1,$h0
+ mtvrwz $S1,$h1
+ slwi $h1,$h2,2
+ mtvrwz $R2,$h2
+ add $h2,$h2,$h1
+ mtvrwz $S2,$h2
+ slwi $h2,$h3,2
+ mtvrwz $R3,$h3
+ add $h3,$h3,$h2
+ mtvrwz $S3,$h3
+ slwi $h3,$h4,2
+ mtvrwz $R4,$h4
+ add $h4,$h4,$h3
+ mtvrwz $S4,$h4
+
+ vmr $H0,$R0
+ vmr $H1,$R1
+ vmr $H2,$R2
+ vmr $H3,$R3
+ vmr $H4,$R4
+
+ bl __poly1305_mul # r^1:- * r^1:-
+
+ vpermdi $R0,$H0,$R0,0b00
+ vpermdi $R1,$H1,$R1,0b00
+ vpermdi $R2,$H2,$R2,0b00
+ vpermdi $R3,$H3,$R3,0b00
+ vpermdi $R4,$H4,$R4,0b00
+ vpermdi $H0,$H0,$H0,0b00
+ vpermdi $H1,$H1,$H1,0b00
+ vpermdi $H2,$H2,$H2,0b00
+ vpermdi $H3,$H3,$H3,0b00
+ vpermdi $H4,$H4,$H4,0b00
+ vsld $S1,$R1,$T0 # <<2
+ vsld $S2,$R2,$T0
+ vsld $S3,$R3,$T0
+ vsld $S4,$R4,$T0
+ vaddudm $S1,$S1,$R1
+ vaddudm $S2,$S2,$R2
+ vaddudm $S3,$S3,$R3
+ vaddudm $S4,$S4,$R4
+
+ bl __poly1305_mul # r^2:r^2 * r^2:r^1
+
+ addi $h0,$ctx,0x60
+ lwz $h1,0($ctx) # load hash
+ lwz $h2,4($ctx)
+ lwz $h3,8($ctx)
+ lwz $h4,12($ctx)
+ lwz $t0,16($ctx)
+
+ vmrgow $R0,$R0,$H0 # r^2:r^4:r^1:r^3
+ vmrgow $R1,$R1,$H1
+ vmrgow $R2,$R2,$H2
+ vmrgow $R3,$R3,$H3
+ vmrgow $R4,$R4,$H4
+ vslw $S1,$R1,$T0 # <<2
+ vslw $S2,$R2,$T0
+ vslw $S3,$R3,$T0
+ vslw $S4,$R4,$T0
+ vadduwm $S1,$S1,$R1
+ vadduwm $S2,$S2,$R2
+ vadduwm $S3,$S3,$R3
+ vadduwm $S4,$S4,$R4
+
+ stvx_u $R0,$x30,$ctx
+ stvx_u $R1,$x40,$ctx
+ stvx_u $S1,$x50,$ctx
+ stvx_u $R2,$x00,$h0
+ stvx_u $S2,$x10,$h0
+ stvx_u $R3,$x20,$h0
+ stvx_u $S3,$x30,$h0
+ stvx_u $R4,$x40,$h0
+ stvx_u $S4,$x50,$h0
+
+ extrwi $h0,$h1,26,6 # base 2^32 -> base 2^26
+ extrwi $h1,$h1,6,0
+ mtvrwz $H0,$h0
+ insrwi $h1,$h2,20,6
+ extrwi $h2,$h2,12,0
+ mtvrwz $H1,$h1
+ insrwi $h2,$h3,14,6
+ extrwi $h3,$h3,18,0
+ mtvrwz $H2,$h2
+ insrwi $h3,$h4,8,6
+ extrwi $h4,$h4,24,0
+ mtvrwz $H3,$h3
+ insrwi $h4,$t0,3,5
+ mtvrwz $H4,$h4
___
+ }
$code.=<<___;
- $POP r28,`$FRAME-$SIZE_T*4`($sp)
- $POP r29,`$FRAME-$SIZE_T*3`($sp)
- $POP r30,`$FRAME-$SIZE_T*2`($sp)
- $POP r31,`$FRAME-$SIZE_T*1`($sp)
- addi $sp,$sp,$FRAME
+ li r0,1
+ stw r0,24($ctx) # set is_base2_26
+ b Loaded_vsx
+
+.align 4
+Lskip_init_vsx:
+ li $x10,4
+ li $x20,8
+ li $x30,12
+ li $x40,16
+ lvwzx_u $H0,$x00,$ctx
+ lvwzx_u $H1,$x10,$ctx
+ lvwzx_u $H2,$x20,$ctx
+ lvwzx_u $H3,$x30,$ctx
+ lvwzx_u $H4,$x40,$ctx
+
+Loaded_vsx:
+ li $x10,0x10
+ li $x20,0x20
+ li $x30,0x30
+ li $x40,0x40
+ li $x50,0x50
+ li $x60,0x60
+ li $x70,0x70
+ addi $ctx_,$ctx,64 # &ctx->r[1]
+ addi $_ctx,$sp,`$LOCALS+15` # &ctx->r[1], r^2:r^4 shadow
+
+ vxor $T0,$T0,$T0 # ensure second half is zero
+ vpermdi $H0,$H0,$T0,0b00
+ vpermdi $H1,$H1,$T0,0b00
+ vpermdi $H2,$H2,$T0,0b00
+ vpermdi $H3,$H3,$T0,0b00
+ vpermdi $H4,$H4,$T0,0b00
+
+ be?lvx_u $_4,$x50,$const # byte swap mask
+ lvx_u $T1,$x00,$inp # load first input block
+ lvx_u $T2,$x10,$inp
+ lvx_u $T3,$x20,$inp
+ lvx_u $T4,$x30,$inp
+ be?vperm $T1,$T1,$T1,$_4
+ be?vperm $T2,$T2,$T2,$_4
+ be?vperm $T3,$T3,$T3,$_4
+ be?vperm $T4,$T4,$T4,$_4
+
+ vpermdi $I0,$T1,$T2,0b00 # smash input to base 2^26
+ vspltisb $_4,4
+ vperm $I2,$T1,$T2,$I2perm # 0x...0e0f0001...1e1f1011
+ vspltisb $_14,14
+ vpermdi $I3,$T1,$T2,0b11
+
+ vsrd $I1,$I0,$_26
+ vsrd $I2,$I2,$_4
+ vsrd $I4,$I3,$_40
+ vsrd $I3,$I3,$_14
+ vand $I0,$I0,$mask26
+ vand $I1,$I1,$mask26
+ vand $I2,$I2,$mask26
+ vand $I3,$I3,$mask26
+
+ vpermdi $T1,$T3,$T4,0b00
+ vperm $T2,$T3,$T4,$I2perm # 0x...0e0f0001...1e1f1011
+ vpermdi $T3,$T3,$T4,0b11
+
+ vsrd $T0,$T1,$_26
+ vsrd $T2,$T2,$_4
+ vsrd $T4,$T3,$_40
+ vsrd $T3,$T3,$_14
+ vand $T1,$T1,$mask26
+ vand $T0,$T0,$mask26
+ vand $T2,$T2,$mask26
+ vand $T3,$T3,$mask26
+
+ # inp[2]:inp[0]:inp[3]:inp[1]
+ vmrgow $I4,$T4,$I4
+ vmrgow $I0,$T1,$I0
+ vmrgow $I1,$T0,$I1
+ vmrgow $I2,$T2,$I2
+ vmrgow $I3,$T3,$I3
+ vor $I4,$I4,$padbits
+
+ lvx_splt $R0,$x30,$ctx # taking lvx_vsplt out of loop
+ lvx_splt $R1,$x00,$ctx_ # gives ~8% improvement
+ lvx_splt $S1,$x10,$ctx_
+ lvx_splt $R2,$x20,$ctx_
+ lvx_splt $S2,$x30,$ctx_
+ lvx_splt $T1,$x40,$ctx_
+ lvx_splt $T2,$x50,$ctx_
+ lvx_splt $T3,$x60,$ctx_
+ lvx_splt $T4,$x70,$ctx_
+ stvx $R1,$x00,$_ctx
+ stvx $S1,$x10,$_ctx
+ stvx $R2,$x20,$_ctx
+ stvx $S2,$x30,$_ctx
+ stvx $T1,$x40,$_ctx
+ stvx $T2,$x50,$_ctx
+ stvx $T3,$x60,$_ctx
+ stvx $T4,$x70,$_ctx
+
+ addi $inp,$inp,0x40
+ addi $const,$const,0x50
+ addi r0,$len,-64
+ srdi r0,r0,6
+ mtctr r0
+ b Loop_vsx
+
+.align 4
+Loop_vsx:
+ ################################################################
+ ## ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2
+ ## ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r
+ ## \___________________/
+ ##
+ ## Note that we start with inp[2:3]*r^2. This is because it
+ ## doesn't depend on reduction in previous iteration.
+ ################################################################
+ ## d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ ## d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ ## d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ ## d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ ## d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+
+ vmuleuw $ACC0,$I0,$R0
+ vmuleuw $ACC1,$I0,$R1
+ vmuleuw $ACC2,$I0,$R2
+ vmuleuw $ACC3,$I1,$R2
+
+ vmuleuw $T0,$I1,$R0
+ vaddudm $ACC1,$ACC1,$T0
+ vmuleuw $T0,$I1,$R1
+ vaddudm $ACC2,$ACC2,$T0
+ vmuleuw $ACC4,$I2,$R2
+ vmuleuw $T0,$I4,$S1
+ vaddudm $ACC0,$ACC0,$T0
+ vmuleuw $T0,$I2,$R1
+ vaddudm $ACC3,$ACC3,$T0
+ lvx $S3,$x50,$_ctx
+ vmuleuw $T0,$I3,$R1
+ vaddudm $ACC4,$ACC4,$T0
+ lvx $R3,$x40,$_ctx
+
+ vaddudm $H2,$H2,$I2
+ vaddudm $H0,$H0,$I0
+ vaddudm $H3,$H3,$I3
+ vaddudm $H1,$H1,$I1
+ vaddudm $H4,$H4,$I4
+
+ vmuleuw $T0,$I3,$S2
+ vaddudm $ACC0,$ACC0,$T0
+ vmuleuw $T0,$I4,$S2
+ vaddudm $ACC1,$ACC1,$T0
+ vmuleuw $T0,$I2,$R0
+ vaddudm $ACC2,$ACC2,$T0
+ vmuleuw $T0,$I3,$R0
+ vaddudm $ACC3,$ACC3,$T0
+ lvx $S4,$x70,$_ctx
+ vmuleuw $T0,$I4,$R0
+ vaddudm $ACC4,$ACC4,$T0
+ lvx $R4,$x60,$_ctx
+
+ vmuleuw $T0,$I2,$S3
+ vaddudm $ACC0,$ACC0,$T0
+ vmuleuw $T0,$I3,$S3
+ vaddudm $ACC1,$ACC1,$T0
+ vmuleuw $T0,$I4,$S3
+ vaddudm $ACC2,$ACC2,$T0
+ vmuleuw $T0,$I0,$R3
+ vaddudm $ACC3,$ACC3,$T0
+ vmuleuw $T0,$I1,$R3
+ vaddudm $ACC4,$ACC4,$T0
+
+ be?lvx_u $_4,$x00,$const # byte swap mask
+ lvx_u $T1,$x00,$inp # load next input block
+ lvx_u $T2,$x10,$inp
+ lvx_u $T3,$x20,$inp
+ lvx_u $T4,$x30,$inp
+ be?vperm $T1,$T1,$T1,$_4
+ be?vperm $T2,$T2,$T2,$_4
+ be?vperm $T3,$T3,$T3,$_4
+ be?vperm $T4,$T4,$T4,$_4
+
+ vmuleuw $T0,$I1,$S4
+ vaddudm $ACC0,$ACC0,$T0
+ vmuleuw $T0,$I2,$S4
+ vaddudm $ACC1,$ACC1,$T0
+ vmuleuw $T0,$I3,$S4
+ vaddudm $ACC2,$ACC2,$T0
+ vmuleuw $T0,$I4,$S4
+ vaddudm $ACC3,$ACC3,$T0
+ vmuleuw $T0,$I0,$R4
+ vaddudm $ACC4,$ACC4,$T0
+
+ vpermdi $I0,$T1,$T2,0b00 # smash input to base 2^26
+ vspltisb $_4,4
+ vperm $I2,$T1,$T2,$I2perm # 0x...0e0f0001...1e1f1011
+ vpermdi $I3,$T1,$T2,0b11
+
+ # (hash + inp[0:1]) * r^4
+ vmulouw $T0,$H0,$R0
+ vaddudm $ACC0,$ACC0,$T0
+ vmulouw $T0,$H1,$R0
+ vaddudm $ACC1,$ACC1,$T0
+ vmulouw $T0,$H2,$R0
+ vaddudm $ACC2,$ACC2,$T0
+ vmulouw $T0,$H3,$R0
+ vaddudm $ACC3,$ACC3,$T0
+ vmulouw $T0,$H4,$R0
+ vaddudm $ACC4,$ACC4,$T0
+
+ vpermdi $T1,$T3,$T4,0b00
+ vperm $T2,$T3,$T4,$I2perm # 0x...0e0f0001...1e1f1011
+ vpermdi $T3,$T3,$T4,0b11
+
+ vmulouw $T0,$H2,$S3
+ vaddudm $ACC0,$ACC0,$T0
+ vmulouw $T0,$H3,$S3
+ vaddudm $ACC1,$ACC1,$T0
+ vmulouw $T0,$H4,$S3
+ vaddudm $ACC2,$ACC2,$T0
+ vmulouw $T0,$H0,$R3
+ vaddudm $ACC3,$ACC3,$T0
+ lvx $S1,$x10,$_ctx
+ vmulouw $T0,$H1,$R3
+ vaddudm $ACC4,$ACC4,$T0
+ lvx $R1,$x00,$_ctx
+
+ vsrd $I1,$I0,$_26
+ vsrd $I2,$I2,$_4
+ vsrd $I4,$I3,$_40
+ vsrd $I3,$I3,$_14
+
+ vmulouw $T0,$H1,$S4
+ vaddudm $ACC0,$ACC0,$T0
+ vmulouw $T0,$H2,$S4
+ vaddudm $ACC1,$ACC1,$T0
+ vmulouw $T0,$H3,$S4
+ vaddudm $ACC2,$ACC2,$T0
+ vmulouw $T0,$H4,$S4
+ vaddudm $ACC3,$ACC3,$T0
+ lvx $S2,$x30,$_ctx
+ vmulouw $T0,$H0,$R4
+ vaddudm $ACC4,$ACC4,$T0
+ lvx $R2,$x20,$_ctx
+
+ vand $I0,$I0,$mask26
+ vand $I1,$I1,$mask26
+ vand $I2,$I2,$mask26
+ vand $I3,$I3,$mask26
+
+ vmulouw $T0,$H4,$S1
+ vaddudm $ACC0,$ACC0,$T0
+ vmulouw $T0,$H0,$R1
+ vaddudm $ACC1,$ACC1,$T0
+ vmulouw $T0,$H1,$R1
+ vaddudm $ACC2,$ACC2,$T0
+ vmulouw $T0,$H2,$R1
+ vaddudm $ACC3,$ACC3,$T0
+ vmulouw $T0,$H3,$R1
+ vaddudm $ACC4,$ACC4,$T0
+
+ vsrd $T2,$T2,$_4
+ vsrd $_4,$T1,$_26
+ vsrd $T4,$T3,$_40
+ vsrd $T3,$T3,$_14
+
+ vmulouw $T0,$H3,$S2
+ vaddudm $ACC0,$ACC0,$T0
+ vmulouw $T0,$H4,$S2
+ vaddudm $ACC1,$ACC1,$T0
+ vmulouw $T0,$H0,$R2
+ vaddudm $ACC2,$ACC2,$T0
+ vmulouw $T0,$H1,$R2
+ vaddudm $ACC3,$ACC3,$T0
+ vmulouw $T0,$H2,$R2
+ vaddudm $ACC4,$ACC4,$T0
+
+ vand $T1,$T1,$mask26
+ vand $_4,$_4,$mask26
+ vand $T2,$T2,$mask26
+ vand $T3,$T3,$mask26
+
+ ################################################################
+ # lazy reduction as discussed in "NEON crypto" by D.J. Bernstein
+ # and P. Schwabe
+
+ vspltisb $T0,2
+ vsrd $H4,$ACC3,$_26
+ vsrd $H1,$ACC0,$_26
+ vand $H3,$ACC3,$mask26
+ vand $H0,$ACC0,$mask26
+ vaddudm $H4,$H4,$ACC4 # h3 -> h4
+ vaddudm $H1,$H1,$ACC1 # h0 -> h1
+
+ vmrgow $I4,$T4,$I4
+ vmrgow $I0,$T1,$I0
+ vmrgow $I1,$_4,$I1
+ vmrgow $I2,$T2,$I2
+ vmrgow $I3,$T3,$I3
+ vor $I4,$I4,$padbits
+
+ vsrd $ACC4,$H4,$_26
+ vsrd $ACC1,$H1,$_26
+ vand $H4,$H4,$mask26
+ vand $H1,$H1,$mask26
+ vaddudm $H0,$H0,$ACC4
+ vaddudm $H2,$ACC2,$ACC1 # h1 -> h2
+
+ vsld $ACC4,$ACC4,$T0 # <<2
+ vsrd $ACC2,$H2,$_26
+ vand $H2,$H2,$mask26
+ vaddudm $H0,$H0,$ACC4 # h4 -> h0
+ vaddudm $H3,$H3,$ACC2 # h2 -> h3
+
+ vsrd $ACC0,$H0,$_26
+ vsrd $ACC3,$H3,$_26
+ vand $H0,$H0,$mask26
+ vand $H3,$H3,$mask26
+ vaddudm $H1,$H1,$ACC0 # h0 -> h1
+ vaddudm $H4,$H4,$ACC3 # h3 -> h4
+
+ addi $inp,$inp,0x40
+ bdnz Loop_vsx
+
+ neg $len,$len
+ andi. $len,$len,0x30
+ sub $inp,$inp,$len
+
+ lvx_u $R0,$x30,$ctx # load all powers
+ lvx_u $R1,$x00,$ctx_
+ lvx_u $S1,$x10,$ctx_
+ lvx_u $R2,$x20,$ctx_
+ lvx_u $S2,$x30,$ctx_
+
+Last_vsx:
+ vmuleuw $ACC0,$I0,$R0
+ vmuleuw $ACC1,$I1,$R0
+ vmuleuw $ACC2,$I2,$R0
+ vmuleuw $ACC3,$I3,$R0
+ vmuleuw $ACC4,$I4,$R0
+
+ vmuleuw $T0,$I4,$S1
+ vaddudm $ACC0,$ACC0,$T0
+ vmuleuw $T0,$I0,$R1
+ vaddudm $ACC1,$ACC1,$T0
+ vmuleuw $T0,$I1,$R1
+ vaddudm $ACC2,$ACC2,$T0
+ vmuleuw $T0,$I2,$R1
+ vaddudm $ACC3,$ACC3,$T0
+ lvx_u $S3,$x50,$ctx_
+ vmuleuw $T0,$I3,$R1
+ vaddudm $ACC4,$ACC4,$T0
+ lvx_u $R3,$x40,$ctx_
+
+ vaddudm $H2,$H2,$I2
+ vaddudm $H0,$H0,$I0
+ vaddudm $H3,$H3,$I3
+ vaddudm $H1,$H1,$I1
+ vaddudm $H4,$H4,$I4
+
+ vmuleuw $T0,$I3,$S2
+ vaddudm $ACC0,$ACC0,$T0
+ vmuleuw $T0,$I4,$S2
+ vaddudm $ACC1,$ACC1,$T0
+ vmuleuw $T0,$I0,$R2
+ vaddudm $ACC2,$ACC2,$T0
+ vmuleuw $T0,$I1,$R2
+ vaddudm $ACC3,$ACC3,$T0
+ lvx_u $S4,$x70,$ctx_
+ vmuleuw $T0,$I2,$R2
+ vaddudm $ACC4,$ACC4,$T0
+ lvx_u $R4,$x60,$ctx_
+
+ vmuleuw $T0,$I2,$S3
+ vaddudm $ACC0,$ACC0,$T0
+ vmuleuw $T0,$I3,$S3
+ vaddudm $ACC1,$ACC1,$T0
+ vmuleuw $T0,$I4,$S3
+ vaddudm $ACC2,$ACC2,$T0
+ vmuleuw $T0,$I0,$R3
+ vaddudm $ACC3,$ACC3,$T0
+ vmuleuw $T0,$I1,$R3
+ vaddudm $ACC4,$ACC4,$T0
+
+ vmuleuw $T0,$I1,$S4
+ vaddudm $ACC0,$ACC0,$T0
+ vmuleuw $T0,$I2,$S4
+ vaddudm $ACC1,$ACC1,$T0
+ vmuleuw $T0,$I3,$S4
+ vaddudm $ACC2,$ACC2,$T0
+ vmuleuw $T0,$I4,$S4
+ vaddudm $ACC3,$ACC3,$T0
+ vmuleuw $T0,$I0,$R4
+ vaddudm $ACC4,$ACC4,$T0
+
+ # (hash + inp[0:1]) * r^4
+ vmulouw $T0,$H0,$R0
+ vaddudm $ACC0,$ACC0,$T0
+ vmulouw $T0,$H1,$R0
+ vaddudm $ACC1,$ACC1,$T0
+ vmulouw $T0,$H2,$R0
+ vaddudm $ACC2,$ACC2,$T0
+ vmulouw $T0,$H3,$R0
+ vaddudm $ACC3,$ACC3,$T0
+ vmulouw $T0,$H4,$R0
+ vaddudm $ACC4,$ACC4,$T0
+
+ vmulouw $T0,$H2,$S3
+ vaddudm $ACC0,$ACC0,$T0
+ vmulouw $T0,$H3,$S3
+ vaddudm $ACC1,$ACC1,$T0
+ vmulouw $T0,$H4,$S3
+ vaddudm $ACC2,$ACC2,$T0
+ vmulouw $T0,$H0,$R3
+ vaddudm $ACC3,$ACC3,$T0
+ lvx_u $S1,$x10,$ctx_
+ vmulouw $T0,$H1,$R3
+ vaddudm $ACC4,$ACC4,$T0
+ lvx_u $R1,$x00,$ctx_
+
+ vmulouw $T0,$H1,$S4
+ vaddudm $ACC0,$ACC0,$T0
+ vmulouw $T0,$H2,$S4
+ vaddudm $ACC1,$ACC1,$T0
+ vmulouw $T0,$H3,$S4
+ vaddudm $ACC2,$ACC2,$T0
+ vmulouw $T0,$H4,$S4
+ vaddudm $ACC3,$ACC3,$T0
+ lvx_u $S2,$x30,$ctx_
+ vmulouw $T0,$H0,$R4
+ vaddudm $ACC4,$ACC4,$T0
+ lvx_u $R2,$x20,$ctx_
+
+ vmulouw $T0,$H4,$S1
+ vaddudm $ACC0,$ACC0,$T0
+ vmulouw $T0,$H0,$R1
+ vaddudm $ACC1,$ACC1,$T0
+ vmulouw $T0,$H1,$R1
+ vaddudm $ACC2,$ACC2,$T0
+ vmulouw $T0,$H2,$R1
+ vaddudm $ACC3,$ACC3,$T0
+ vmulouw $T0,$H3,$R1
+ vaddudm $ACC4,$ACC4,$T0
+
+ vmulouw $T0,$H3,$S2
+ vaddudm $ACC0,$ACC0,$T0
+ vmulouw $T0,$H4,$S2
+ vaddudm $ACC1,$ACC1,$T0
+ vmulouw $T0,$H0,$R2
+ vaddudm $ACC2,$ACC2,$T0
+ vmulouw $T0,$H1,$R2
+ vaddudm $ACC3,$ACC3,$T0
+ vmulouw $T0,$H2,$R2
+ vaddudm $ACC4,$ACC4,$T0
+
+ ################################################################
+ # horizontal addition
+
+ vpermdi $H0,$ACC0,$ACC0,0b10
+ vpermdi $H1,$ACC1,$ACC1,0b10
+ vpermdi $H2,$ACC2,$ACC2,0b10
+ vpermdi $H3,$ACC3,$ACC3,0b10
+ vpermdi $H4,$ACC4,$ACC4,0b10
+ vaddudm $ACC0,$ACC0,$H0
+ vaddudm $ACC1,$ACC1,$H1
+ vaddudm $ACC2,$ACC2,$H2
+ vaddudm $ACC3,$ACC3,$H3
+ vaddudm $ACC4,$ACC4,$H4
+
+ ################################################################
+ # lazy reduction
+
+ vspltisb $T0,2
+ vsrd $H4,$ACC3,$_26
+ vsrd $H1,$ACC0,$_26
+ vand $H3,$ACC3,$mask26
+ vand $H0,$ACC0,$mask26
+ vaddudm $H4,$H4,$ACC4 # h3 -> h4
+ vaddudm $H1,$H1,$ACC1 # h0 -> h1
+
+ vsrd $ACC4,$H4,$_26
+ vsrd $ACC1,$H1,$_26
+ vand $H4,$H4,$mask26
+ vand $H1,$H1,$mask26
+ vaddudm $H0,$H0,$ACC4
+ vaddudm $H2,$ACC2,$ACC1 # h1 -> h2
+
+ vsld $ACC4,$ACC4,$T0 # <<2
+ vsrd $ACC2,$H2,$_26
+ vand $H2,$H2,$mask26
+ vaddudm $H0,$H0,$ACC4 # h4 -> h0
+ vaddudm $H3,$H3,$ACC2 # h2 -> h3
+
+ vsrd $ACC0,$H0,$_26
+ vsrd $ACC3,$H3,$_26
+ vand $H0,$H0,$mask26
+ vand $H3,$H3,$mask26
+ vaddudm $H1,$H1,$ACC0 # h0 -> h1
+ vaddudm $H4,$H4,$ACC3 # h3 -> h4
+
+ beq Ldone_vsx
+
+ add r6,$const,$len
+
+ be?lvx_u $_4,$x00,$const # byte swap mask
+ lvx_u $T1,$x00,$inp # load last partial input block
+ lvx_u $T2,$x10,$inp
+ lvx_u $T3,$x20,$inp
+ lvx_u $T4,$x30,$inp
+ be?vperm $T1,$T1,$T1,$_4
+ be?vperm $T2,$T2,$T2,$_4
+ be?vperm $T3,$T3,$T3,$_4
+ be?vperm $T4,$T4,$T4,$_4
+
+ vpermdi $I0,$T1,$T2,0b00 # smash input to base 2^26
+ vspltisb $_4,4
+ vperm $I2,$T1,$T2,$I2perm # 0x...0e0f0001...1e1f1011
+ vpermdi $I3,$T1,$T2,0b11
+
+ vsrd $I1,$I0,$_26
+ vsrd $I2,$I2,$_4
+ vsrd $I4,$I3,$_40
+ vsrd $I3,$I3,$_14
+ vand $I0,$I0,$mask26
+ vand $I1,$I1,$mask26
+ vand $I2,$I2,$mask26
+ vand $I3,$I3,$mask26
+
+ vpermdi $T0,$T3,$T4,0b00
+ vperm $T1,$T3,$T4,$I2perm # 0x...0e0f0001...1e1f1011
+ vpermdi $T2,$T3,$T4,0b11
+
+ lvx_u $ACC0,$x00,r6
+ lvx_u $ACC1,$x30,r6
+
+ vsrd $T3,$T0,$_26
+ vsrd $T1,$T1,$_4
+ vsrd $T4,$T2,$_40
+ vsrd $T2,$T2,$_14
+ vand $T0,$T0,$mask26
+ vand $T3,$T3,$mask26
+ vand $T1,$T1,$mask26
+ vand $T2,$T2,$mask26
+
+ # inp[2]:inp[0]:inp[3]:inp[1]
+ vmrgow $I4,$T4,$I4
+ vmrgow $I0,$T0,$I0
+ vmrgow $I1,$T3,$I1
+ vmrgow $I2,$T1,$I2
+ vmrgow $I3,$T2,$I3
+ vor $I4,$I4,$padbits
+
+ vperm $H0,$H0,$H0,$ACC0 # move hash to right lane
+ vand $I0,$I0, $ACC1 # mask redundant input lane[s]
+ vperm $H1,$H1,$H1,$ACC0
+ vand $I1,$I1, $ACC1
+ vperm $H2,$H2,$H2,$ACC0
+ vand $I2,$I2, $ACC1
+ vperm $H3,$H3,$H3,$ACC0
+ vand $I3,$I3, $ACC1
+ vperm $H4,$H4,$H4,$ACC0
+ vand $I4,$I4, $ACC1
+
+ vaddudm $I0,$I0,$H0 # accumulate hash
+ vxor $H0,$H0,$H0 # wipe hash value
+ vaddudm $I1,$I1,$H1
+ vxor $H1,$H1,$H1
+ vaddudm $I2,$I2,$H2
+ vxor $H2,$H2,$H2
+ vaddudm $I3,$I3,$H3
+ vxor $H3,$H3,$H3
+ vaddudm $I4,$I4,$H4
+ vxor $H4,$H4,$H4
+
+ xor. $len,$len,$len
+ b Last_vsx
+
+.align 4
+Ldone_vsx:
+ $POP r0,`$VSXFRAME+$LRSAVE`($sp)
+ li $x10,4
+ li $x20,8
+ li $x30,12
+ li $x40,16
+ stvwx_u $H0,$x00,$ctx # store hash
+ stvwx_u $H1,$x10,$ctx
+ stvwx_u $H2,$x20,$ctx
+ stvwx_u $H3,$x30,$ctx
+ stvwx_u $H4,$x40,$ctx
+
+ lwz r12,`$VSXFRAME-$SIZE_T*5-4`($sp)# pull vrsave
+ mtlr r0
+ li r10,`15+$LOCALS+128`
+ li r11,`31+$LOCALS+128`
+ mtspr 256,r12 # restore vrsave
+ lvx v20,r10,$sp
+ addi r10,r10,32
+ lvx v21,r10,$sp
+ addi r10,r10,32
+ lvx v22,r11,$sp
+ addi r11,r11,32
+ lvx v23,r10,$sp
+ addi r10,r10,32
+ lvx v24,r11,$sp
+ addi r11,r11,32
+ lvx v25,r10,$sp
+ addi r10,r10,32
+ lvx v26,r11,$sp
+ addi r11,r11,32
+ lvx v27,r10,$sp
+ addi r10,r10,32
+ lvx v28,r11,$sp
+ addi r11,r11,32
+ lvx v29,r10,$sp
+ addi r10,r10,32
+ lvx v30,r11,$sp
+ lvx v31,r10,$sp
+ $POP r27,`$VSXFRAME-$SIZE_T*5`($sp)
+ $POP r28,`$VSXFRAME-$SIZE_T*4`($sp)
+ $POP r29,`$VSXFRAME-$SIZE_T*3`($sp)
+ $POP r30,`$VSXFRAME-$SIZE_T*2`($sp)
+ $POP r31,`$VSXFRAME-$SIZE_T*1`($sp)
+ addi $sp,$sp,$VSXFRAME
blr
.long 0
- .byte 0,12,4,1,0x80,4,3,0
-.size .poly1305_emit,.-.poly1305_emit
+ .byte 0,12,0x04,1,0x80,5,4,0
+ .long 0
+.size __poly1305_blocks_vsx,.-__poly1305_blocks_vsx
+
+.align 6
+LPICmeup:
+ mflr r0
+ bcl 20,31,\$+4
+ mflr $const # vvvvvv "distance" between . and 1st data entry
+ addi $const,$const,`64-8`
+ mtlr r0
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,0,0
+ .space `64-9*4`
+
+.quad 0x0000000003ffffff,0x0000000003ffffff # mask26
+.quad 0x000000000000001a,0x000000000000001a # _26
+.quad 0x0000000000000028,0x0000000000000028 # _40
+.quad 0x000000000e0f0001,0x000000001e1f1011 # I2perm
+.quad 0x0100000001000000,0x0100000001000000 # padbits
+.quad 0x0706050403020100,0x0f0e0d0c0b0a0908 # byte swap for big-endian
+
+.quad 0x0000000000000000,0x0000000004050607 # magic tail masks
+.quad 0x0405060700000000,0x0000000000000000
+.quad 0x0000000000000000,0x0405060700000000
+
+.quad 0xffffffff00000000,0xffffffffffffffff
+.quad 0xffffffff00000000,0xffffffff00000000
+.quad 0x0000000000000000,0xffffffff00000000
___
- }
+}}}
$code.=<<___;
-.asciz "Poly1305 for PPC, CRYPTOGAMS by <appro\@openssl.org>"
+.asciz "Poly1305 for PPC, CRYPTOGAMS by \@dot-asm"
___
-$code =~ s/\`([^\`]*)\`/eval $1/gem;
-print $code;
+foreach (split("\n",$code)) {
+ s/\`([^\`]*)\`/eval($1)/ge;
+
+ # instructions prefixed with '?' are endian-specific and need
+ # to be adjusted accordingly...
+ if ($flavour !~ /le$/) { # big-endian
+ s/be\?// or
+ s/le\?/#le#/
+ } else { # little-endian
+ s/le\?// or
+ s/be\?/#be#/
+ }
+
+ print $_,"\n";
+}
close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/poly1305/asm/poly1305-ppcfp.pl b/crypto/poly1305/asm/poly1305-ppcfp.pl
index a9ab20714697..218708a46257 100755
--- a/crypto/poly1305/asm/poly1305-ppcfp.pl
+++ b/crypto/poly1305/asm/poly1305-ppcfp.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -27,7 +27,10 @@
# POWER7 3.50/+30%
# POWER8 3.75/+10%
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /64/) {
$SIZE_T =8;
@@ -54,7 +57,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
+open STDOUT,"| $^X $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
$LOCALS=6*$SIZE_T;
$FRAME=$LOCALS+6*8+18*8;
diff --git a/crypto/poly1305/asm/poly1305-s390x.pl b/crypto/poly1305/asm/poly1305-s390x.pl
index bcc8fd3b886a..4a93064ff663 100755
--- a/crypto/poly1305/asm/poly1305-s390x.pl
+++ b/crypto/poly1305/asm/poly1305-s390x.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -24,204 +24,961 @@
#
# On side note, z13 enables vector base 2^26 implementation...
-$flavour = shift;
+#
+# January 2019
+#
+# Add vx code path (base 2^26).
+#
+# Copyright IBM Corp. 2019
+# Author: Patrick Steuer <patrick.steuer@de.ibm.com>
+#
+# January 2019
+#
+# Add vector base 2^26 implementation. It's problematic to accurately
+# measure performance, because reference system is hardly idle. But
+# it's sub-cycle, i.e. less than 1 cycle per processed byte, and it's
+# >=20% faster than IBM's submission on long inputs, and much faster on
+# short ones, because calculation of key powers is postponed till we
+# know that input is long enough to justify the additional overhead.
+
+use strict;
+use FindBin qw($Bin);
+use lib "$Bin/../..";
+use perlasm::s390x qw(:DEFAULT :GE :EI :MI1 :VX AUTOLOAD LABEL INCLUDE);
+
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+
+my ($z,$SIZE_T);
if ($flavour =~ /3[12]/) {
+ $z=0; # S/390 ABI
$SIZE_T=4;
- $g="";
} else {
+ $z=1; # zSeries ABI
$SIZE_T=8;
- $g="g";
}
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
-
-$sp="%r15";
+my $stdframe=16*$SIZE_T+4*8;
+my $sp="%r15";
my ($ctx,$inp,$len,$padbit) = map("%r$_",(2..5));
-$code.=<<___;
-.text
-
-.globl poly1305_init
-.type poly1305_init,\@function
-.align 16
-poly1305_init:
- lghi %r0,0
- lghi %r1,-1
- stg %r0,0($ctx) # zero hash value
- stg %r0,8($ctx)
- stg %r0,16($ctx)
-
- cl${g}r $inp,%r0
- je .Lno_key
-
- lrvg %r4,0($inp) # load little-endian key
- lrvg %r5,8($inp)
-
- nihl %r1,0xffc0 # 0xffffffc0ffffffff
- srlg %r0,%r1,4 # 0x0ffffffc0fffffff
- srlg %r1,%r1,4
- nill %r1,0xfffc # 0x0ffffffc0ffffffc
-
- ngr %r4,%r0
- ngr %r5,%r1
-
- stg %r4,32($ctx)
- stg %r5,40($ctx)
-
-.Lno_key:
- lghi %r2,0
- br %r14
-.size poly1305_init,.-poly1305_init
-___
+PERLASM_BEGIN($output);
+
+INCLUDE ("s390x_arch.h");
+TEXT ();
+
+################
+# static void poly1305_init(void *ctx, const unsigned char key[16])
+{
+GLOBL ("poly1305_init");
+TYPE ("poly1305_init","\@function");
+ALIGN (16);
+LABEL ("poly1305_init");
+ lghi ("%r0",0);
+ lghi ("%r1",-1);
+ stg ("%r0","0($ctx)"); # zero hash value
+ stg ("%r0","8($ctx)");
+ stg ("%r0","16($ctx)");
+ st ("%r0","24($ctx)"); # clear is_base2_26
+ lgr ("%r5",$ctx); # reassign $ctx
+ lghi ("%r2",0);
+
+&{$z? \&clgr:\&clr} ($inp,"%r0");
+ je (".Lno_key");
+
+ lrvg ("%r2","0($inp)"); # load little-endian key
+ lrvg ("%r3","8($inp)");
+
+ nihl ("%r1",0xffc0); # 0xffffffc0ffffffff
+ srlg ("%r0","%r1",4); # 0x0ffffffc0fffffff
+ srlg ("%r1","%r1",4);
+ nill ("%r1",0xfffc); # 0x0ffffffc0ffffffc
+
+ ngr ("%r2","%r0");
+ ngr ("%r3","%r1");
+
+ stmg ("%r2","%r3","32(%r5)");
+
+ larl ("%r1","OPENSSL_s390xcap_P");
+ lg ("%r0","16(%r1)");
+ srlg ("%r0","%r0",62);
+ nill ("%r0",1); # extract vx bit
+ lcgr ("%r0","%r0");
+ larl ("%r1",".Lpoly1305_blocks");
+ larl ("%r2",".Lpoly1305_blocks_vx");
+ larl ("%r3",".Lpoly1305_emit");
+&{$z? \&xgr:\&xr} ("%r2","%r1"); # select between scalar and vector
+&{$z? \&ngr:\&nr} ("%r2","%r0");
+&{$z? \&xgr:\&xr} ("%r2","%r1");
+&{$z? \&stmg:\&stm} ("%r2","%r3","0(%r4)");
+ lghi ("%r2",1);
+LABEL (".Lno_key");
+ br ("%r14");
+SIZE ("poly1305_init",".-poly1305_init");
+}
+
+################
+# static void poly1305_blocks(void *ctx, const unsigned char *inp,
+# size_t len, u32 padbit)
{
my ($d0hi,$d0lo,$d1hi,$d1lo,$t0,$h0,$t1,$h1,$h2) = map("%r$_",(6..14));
my ($r0,$r1,$s1) = map("%r$_",(0..2));
-$code.=<<___;
-.globl poly1305_blocks
-.type poly1305_blocks,\@function
-.align 16
-poly1305_blocks:
- srl${g} $len,4 # fixed-up in 64-bit build
- lghi %r0,0
- cl${g}r $len,%r0
- je .Lno_data
-
- stm${g} %r6,%r14,`6*$SIZE_T`($sp)
-
- llgfr $padbit,$padbit # clear upper half, much needed with
- # non-64-bit ABI
- lg $r0,32($ctx) # load key
- lg $r1,40($ctx)
-
- lg $h0,0($ctx) # load hash value
- lg $h1,8($ctx)
- lg $h2,16($ctx)
-
- st$g $ctx,`2*$SIZE_T`($sp) # off-load $ctx
- srlg $s1,$r1,2
- algr $s1,$r1 # s1 = r1 + r1>>2
- j .Loop
-
-.align 16
-.Loop:
- lrvg $d0lo,0($inp) # load little-endian input
- lrvg $d1lo,8($inp)
- la $inp,16($inp)
-
- algr $d0lo,$h0 # accumulate input
- alcgr $d1lo,$h1
-
- lgr $h0,$d0lo
- mlgr $d0hi,$r0 # h0*r0 -> $d0hi:$d0lo
- lgr $h1,$d1lo
- mlgr $d1hi,$s1 # h1*5*r1 -> $d1hi:$d1lo
-
- mlgr $t0,$r1 # h0*r1 -> $t0:$h0
- mlgr $t1,$r0 # h1*r0 -> $t1:$h1
- alcgr $h2,$padbit
-
- algr $d0lo,$d1lo
- lgr $d1lo,$h2
- alcgr $d0hi,$d1hi
- lghi $d1hi,0
-
- algr $h1,$h0
- alcgr $t1,$t0
-
- msgr $d1lo,$s1 # h2*s1
- msgr $h2,$r0 # h2*r0
-
- algr $h1,$d1lo
- alcgr $t1,$d1hi # $d1hi is zero
-
- algr $h1,$d0hi
- alcgr $h2,$t1
-
- lghi $h0,-4 # final reduction step
- ngr $h0,$h2
- srlg $t0,$h2,2
- algr $h0,$t0
- lghi $t1,3
- ngr $h2,$t1
-
- algr $h0,$d0lo
- alcgr $h1,$d1hi # $d1hi is still zero
- alcgr $h2,$d1hi # $d1hi is still zero
-
- brct$g $len,.Loop
-
- l$g $ctx,`2*$SIZE_T`($sp) # restore $ctx
-
- stg $h0,0($ctx) # store hash value
- stg $h1,8($ctx)
- stg $h2,16($ctx)
-
- lm${g} %r6,%r14,`6*$SIZE_T`($sp)
-.Lno_data:
- br %r14
-.size poly1305_blocks,.-poly1305_blocks
-___
+GLOBL ("poly1305_blocks");
+TYPE ("poly1305_blocks","\@function");
+ALIGN (16);
+LABEL ("poly1305_blocks");
+LABEL (".Lpoly1305_blocks");
+&{$z? \&ltgr:\&ltr} ("%r0",$len);
+ jz (".Lno_data");
+
+&{$z? \&stmg:\&stm} ("%r6","%r14","6*$SIZE_T($sp)");
+
+ lg ($h0,"0($ctx)"); # load hash value
+ lg ($h1,"8($ctx)");
+ lg ($h2,"16($ctx)");
+
+LABEL (".Lpoly1305_blocks_entry");
+if ($z) {
+ srlg ($len,$len,4);
+} else {
+ srl ($len,4);
+}
+ llgfr ($padbit,$padbit); # clear upper half, much needed with
+ # non-64-bit ABI
+ lg ($r0,"32($ctx)"); # load key
+ lg ($r1,"40($ctx)");
+
+&{$z? \&stg:\&st} ($ctx,"2*$SIZE_T($sp)"); # off-load $ctx
+ srlg ($s1,$r1,2);
+ algr ($s1,$r1); # s1 = r1 + r1>>2
+ j (".Loop");
+
+ALIGN (16);
+LABEL (".Loop");
+ lrvg ($d0lo,"0($inp)"); # load little-endian input
+ lrvg ($d1lo,"8($inp)");
+ la ($inp,"16($inp)");
+
+ algr ($d0lo,$h0); # accumulate input
+ alcgr ($d1lo,$h1);
+ alcgr ($h2,$padbit);
+
+ lgr ($h0,$d0lo);
+ mlgr ($d0hi,$r0); # h0*r0 -> $d0hi:$d0lo
+ lgr ($h1,$d1lo);
+ mlgr ($d1hi,$s1); # h1*5*r1 -> $d1hi:$d1lo
+
+ mlgr ($t0,$r1); # h0*r1 -> $t0:$h0
+ mlgr ($t1,$r0); # h1*r0 -> $t1:$h1
+
+ algr ($d0lo,$d1lo);
+ lgr ($d1lo,$h2);
+ alcgr ($d0hi,$d1hi);
+ lghi ($d1hi,0);
+
+ algr ($h1,$h0);
+ alcgr ($t1,$t0);
+
+ msgr ($d1lo,$s1); # h2*s1
+ msgr ($h2,$r0); # h2*r0
+
+ algr ($h1,$d1lo);
+ alcgr ($t1,$d1hi); # $d1hi is zero
+
+ algr ($h1,$d0hi);
+ alcgr ($h2,$t1);
+
+ lghi ($h0,-4); # final reduction step
+ ngr ($h0,$h2);
+ srlg ($t0,$h2,2);
+ algr ($h0,$t0);
+ lghi ($t1,3);
+ ngr ($h2,$t1);
+
+ algr ($h0,$d0lo);
+ alcgr ($h1,$d1hi); # $d1hi is still zero
+ alcgr ($h2,$d1hi); # $d1hi is still zero
+
+&{$z? \&brctg:\&brct} ($len,".Loop");
+
+&{$z? \&lg:\&l} ($ctx,"2*$SIZE_T($sp)");# restore $ctx
+
+ stg ($h0,"0($ctx)"); # store hash value
+ stg ($h1,"8($ctx)");
+ stg ($h2,"16($ctx)");
+
+&{$z? \&lmg:\&lm} ("%r6","%r14","6*$SIZE_T($sp)");
+LABEL (".Lno_data");
+ br ("%r14");
+SIZE ("poly1305_blocks",".-poly1305_blocks");
+}
+
+################
+# static void poly1305_blocks_vx(void *ctx, const unsigned char *inp,
+# size_t len, u32 padbit)
+{
+my ($H0, $H1, $H2, $H3, $H4) = map("%v$_",(0..4));
+my ($I0, $I1, $I2, $I3, $I4) = map("%v$_",(5..9));
+my ($R0, $R1, $S1, $R2, $S2) = map("%v$_",(10..14));
+my ($R3, $S3, $R4, $S4) = map("%v$_",(15..18));
+my ($ACC0, $ACC1, $ACC2, $ACC3, $ACC4) = map("%v$_",(19..23));
+my ($T1, $T2, $T3, $T4) = map("%v$_",(24..27));
+my ($mask26,$bswaplo,$bswaphi,$bswapmi) = map("%v$_",(28..31));
+
+my ($d2,$d0,$h0,$d1,$h1,$h2)=map("%r$_",(9..14));
+
+TYPE ("poly1305_blocks_vx","\@function");
+ALIGN (16);
+LABEL ("poly1305_blocks_vx");
+LABEL (".Lpoly1305_blocks_vx");
+&{$z? \&clgfi:\&clfi} ($len,128);
+ jhe ("__poly1305_blocks_vx");
+
+&{$z? \&stmg:\&stm} ("%r6","%r14","6*$SIZE_T($sp)");
+
+ lg ($d0,"0($ctx)");
+ lg ($d1,"8($ctx)");
+ lg ($d2,"16($ctx)");
+
+ llgfr ("%r0",$d0); # base 2^26 -> base 2^64
+ srlg ($h0,$d0,32);
+ llgfr ("%r1",$d1);
+ srlg ($h1,$d1,32);
+ srlg ($h2,$d2,32);
+
+ sllg ("%r0","%r0",26);
+ algr ($h0,"%r0");
+ sllg ("%r0",$h1,52);
+ srlg ($h1,$h1,12);
+ sllg ("%r1","%r1",14);
+ algr ($h0,"%r0");
+ alcgr ($h1,"%r1");
+ sllg ("%r0",$h2,40);
+ srlg ($h2,$h2,24);
+ lghi ("%r1",0);
+ algr ($h1,"%r0");
+ alcgr ($h2,"%r1");
+
+ llgf ("%r0","24($ctx)"); # is_base2_26
+ lcgr ("%r0","%r0");
+
+ xgr ($h0,$d0); # choose between radixes
+ xgr ($h1,$d1);
+ xgr ($h2,$d2);
+ ngr ($h0,"%r0");
+ ngr ($h1,"%r0");
+ ngr ($h2,"%r0");
+ xgr ($h0,$d0);
+ xgr ($h1,$d1);
+ xgr ($h2,$d2);
+
+ lhi ("%r0",0);
+ st ("%r0","24($ctx)"); # clear is_base2_26
+
+ j (".Lpoly1305_blocks_entry");
+SIZE ("poly1305_blocks_vx",".-poly1305_blocks_vx");
+
+TYPE ("__poly1305_mul","\@function");
+ALIGN (16);
+LABEL ("__poly1305_mul");
+ vmlof ($ACC0,$H0,$R0);
+ vmlof ($ACC1,$H0,$R1);
+ vmlof ($ACC2,$H0,$R2);
+ vmlof ($ACC3,$H0,$R3);
+ vmlof ($ACC4,$H0,$R4);
+
+ vmalof ($ACC0,$H1,$S4,$ACC0);
+ vmalof ($ACC1,$H1,$R0,$ACC1);
+ vmalof ($ACC2,$H1,$R1,$ACC2);
+ vmalof ($ACC3,$H1,$R2,$ACC3);
+ vmalof ($ACC4,$H1,$R3,$ACC4);
+
+ vmalof ($ACC0,$H2,$S3,$ACC0);
+ vmalof ($ACC1,$H2,$S4,$ACC1);
+ vmalof ($ACC2,$H2,$R0,$ACC2);
+ vmalof ($ACC3,$H2,$R1,$ACC3);
+ vmalof ($ACC4,$H2,$R2,$ACC4);
+
+ vmalof ($ACC0,$H3,$S2,$ACC0);
+ vmalof ($ACC1,$H3,$S3,$ACC1);
+ vmalof ($ACC2,$H3,$S4,$ACC2);
+ vmalof ($ACC3,$H3,$R0,$ACC3);
+ vmalof ($ACC4,$H3,$R1,$ACC4);
+
+ vmalof ($ACC0,$H4,$S1,$ACC0);
+ vmalof ($ACC1,$H4,$S2,$ACC1);
+ vmalof ($ACC2,$H4,$S3,$ACC2);
+ vmalof ($ACC3,$H4,$S4,$ACC3);
+ vmalof ($ACC4,$H4,$R0,$ACC4);
+
+ ################################################################
+ # lazy reduction
+
+ vesrlg ($H4,$ACC3,26);
+ vesrlg ($H1,$ACC0,26);
+ vn ($H3,$ACC3,$mask26);
+ vn ($H0,$ACC0,$mask26);
+ vag ($H4,$H4,$ACC4); # h3 -> h4
+ vag ($H1,$H1,$ACC1); # h0 -> h1
+
+ vesrlg ($ACC4,$H4,26);
+ vesrlg ($ACC1,$H1,26);
+ vn ($H4,$H4,$mask26);
+ vn ($H1,$H1,$mask26);
+ vag ($H0,$H0,$ACC4);
+ vag ($H2,$ACC2,$ACC1); # h1 -> h2
+
+ veslg ($ACC4,$ACC4,2); # <<2
+ vesrlg ($ACC2,$H2,26);
+ vn ($H2,$H2,$mask26);
+ vag ($H0,$H0,$ACC4); # h4 -> h0
+ vag ($H3,$H3,$ACC2); # h2 -> h3
+
+ vesrlg ($ACC0,$H0,26);
+ vesrlg ($ACC3,$H3,26);
+ vn ($H0,$H0,$mask26);
+ vn ($H3,$H3,$mask26);
+ vag ($H1,$H1,$ACC0); # h0 -> h1
+ vag ($H4,$H4,$ACC3); # h3 -> h4
+ br ("%r14");
+SIZE ("__poly1305_mul",".-__poly1305_mul");
+
+TYPE ("__poly1305_blocks_vx","\@function");
+ALIGN (16);
+LABEL ("__poly1305_blocks_vx");
+&{$z? \&lgr:\&lr} ("%r0",$sp);
+&{$z? \&stmg:\&stm} ("%r10","%r15","10*$SIZE_T($sp)");
+if (!$z) {
+ std ("%f4","16*$SIZE_T+2*8($sp)");
+ std ("%f6","16*$SIZE_T+3*8($sp)");
+ ahi ($sp,-$stdframe);
+ st ("%r0","0($sp)"); # back-chain
+
+ llgfr ($len,$len); # so that srlg works on $len
+} else {
+ aghi ($sp,"-($stdframe+8*8)");
+ stg ("%r0","0($sp)"); # back-chain
+
+ std ("%f8","$stdframe+0*8($sp)");
+ std ("%f9","$stdframe+1*8($sp)");
+ std ("%f10","$stdframe+2*8($sp)");
+ std ("%f11","$stdframe+3*8($sp)");
+ std ("%f12","$stdframe+4*8($sp)");
+ std ("%f13","$stdframe+5*8($sp)");
+ std ("%f14","$stdframe+6*8($sp)");
+ std ("%f15","$stdframe+7*8($sp)");
+}
+ larl ("%r1",".Lconst");
+ vgmg ($mask26,38,63);
+ vlm ($bswaplo,$bswapmi,"16(%r1)");
+
+ &lt ("%r0","24($ctx)"); # is_base2_26?
+ jnz (".Lskip_init");
+
+ lg ($h0,"32($ctx)"); # load key base 2^64
+ lg ($h1,"40($ctx)");
+
+ risbg ($d0,$h0,38,0x80+63,38); # base 2^64 -> 2^26
+ srlg ($d1,$h0,52);
+ risbg ($h0,$h0,38,0x80+63,0);
+ vlvgg ($R0,$h0,0);
+ risbg ($d1,$h1,38,51,12);
+ vlvgg ($R1,$d0,0);
+ risbg ($d0,$h1,38,63,50);
+ vlvgg ($R2,$d1,0);
+ srlg ($d1,$h1,40);
+ vlvgg ($R3,$d0,0);
+ vlvgg ($R4,$d1,0);
+
+ veslg ($S1,$R1,2);
+ veslg ($S2,$R2,2);
+ veslg ($S3,$R3,2);
+ veslg ($S4,$R4,2);
+ vlr ($H0,$R0);
+ vlr ($H1,$R1);
+ vlr ($H2,$R2);
+ vlr ($H3,$R3);
+ vlr ($H4,$R4);
+ vag ($S1,$S1,$R1); # * 5
+ vag ($S2,$S2,$R2);
+ vag ($S3,$S3,$R3);
+ vag ($S4,$S4,$R4);
+
+ brasl ("%r14","__poly1305_mul"); # r^1:- * r^1:-
+
+ vpdi ($R0,$H0,$R0,0); # r^2:r^1
+ vpdi ($R1,$H1,$R1,0);
+ vpdi ($R2,$H2,$R2,0);
+ vpdi ($R3,$H3,$R3,0);
+ vpdi ($R4,$H4,$R4,0);
+ vpdi ($H0,$H0,$H0,0); # r^2:r^2
+ vpdi ($H1,$H1,$H1,0);
+ vpdi ($H2,$H2,$H2,0);
+ vpdi ($H3,$H3,$H3,0);
+ vpdi ($H4,$H4,$H4,0);
+ veslg ($S1,$R1,2);
+ veslg ($S2,$R2,2);
+ veslg ($S3,$R3,2);
+ veslg ($S4,$R4,2);
+ vag ($S1,$S1,$R1); # * 5
+ vag ($S2,$S2,$R2);
+ vag ($S3,$S3,$R3);
+ vag ($S4,$S4,$R4);
+
+ brasl ("%r14,__poly1305_mul"); # r^2:r^2 * r^2:r^1
+
+ vl ($I0,"0(%r1)"); # borrow $I0
+ vperm ($R0,$R0,$H0,$I0); # r^2:r^4:r^1:r^3
+ vperm ($R1,$R1,$H1,$I0);
+ vperm ($R2,$R2,$H2,$I0);
+ vperm ($R3,$R3,$H3,$I0);
+ vperm ($R4,$R4,$H4,$I0);
+ veslf ($S1,$R1,2);
+ veslf ($S2,$R2,2);
+ veslf ($S3,$R3,2);
+ veslf ($S4,$R4,2);
+ vaf ($S1,$S1,$R1); # * 5
+ vaf ($S2,$S2,$R2);
+ vaf ($S3,$S3,$R3);
+ vaf ($S4,$S4,$R4);
+
+ lg ($h0,"0($ctx)"); # load hash base 2^64
+ lg ($h1,"8($ctx)");
+ lg ($h2,"16($ctx)");
+
+ vzero ($H0);
+ vzero ($H1);
+ vzero ($H2);
+ vzero ($H3);
+ vzero ($H4);
+
+ risbg ($d0,$h0,38,0x80+63,38); # base 2^64 -> 2^26
+ srlg ($d1,$h0,52);
+ risbg ($h0,$h0,38,0x80+63,0);
+ vlvgg ($H0,$h0,0);
+ risbg ($d1,$h1,38,51,12);
+ vlvgg ($H1,$d0,0);
+ risbg ($d0,$h1,38,63,50);
+ vlvgg ($H2,$d1,0);
+ srlg ($d1,$h1,40);
+ vlvgg ($H3,$d0,0);
+ risbg ($d1,$h2,37,39,24);
+ vlvgg ($H4,$d1,0);
+
+ lhi ("%r0",1);
+ st ("%r0","24($ctx)"); # set is_base2_26
+
+ vstm ($R0,$S4,"48($ctx)"); # save key schedule base 2^26
+
+ vpdi ($R0,$R0,$R0,0); # broadcast r^2:r^4
+ vpdi ($R1,$R1,$R1,0);
+ vpdi ($S1,$S1,$S1,0);
+ vpdi ($R2,$R2,$R2,0);
+ vpdi ($S2,$S2,$S2,0);
+ vpdi ($R3,$R3,$R3,0);
+ vpdi ($S3,$S3,$S3,0);
+ vpdi ($R4,$R4,$R4,0);
+ vpdi ($S4,$S4,$S4,0);
+
+ j (".Loaded_hash");
+
+ALIGN (16);
+LABEL (".Lskip_init");
+ vllezf ($H0,"0($ctx)"); # load hash base 2^26
+ vllezf ($H1,"4($ctx)");
+ vllezf ($H2,"8($ctx)");
+ vllezf ($H3,"12($ctx)");
+ vllezf ($H4,"16($ctx)");
+
+ vlrepg ($R0,"0x30($ctx)"); # broadcast r^2:r^4
+ vlrepg ($R1,"0x40($ctx)");
+ vlrepg ($S1,"0x50($ctx)");
+ vlrepg ($R2,"0x60($ctx)");
+ vlrepg ($S2,"0x70($ctx)");
+ vlrepg ($R3,"0x80($ctx)");
+ vlrepg ($S3,"0x90($ctx)");
+ vlrepg ($R4,"0xa0($ctx)");
+ vlrepg ($S4,"0xb0($ctx)");
+
+LABEL (".Loaded_hash");
+ vzero ($I1);
+ vzero ($I3);
+
+ vlm ($T1,$T4,"0x00($inp)"); # load first input block
+ la ($inp,"0x40($inp)");
+ vgmg ($mask26,6,31);
+ vgmf ($I4,5,5); # padbit<<2
+
+ vperm ($I0,$T3,$T4,$bswaplo);
+ vperm ($I2,$T3,$T4,$bswapmi);
+ vperm ($T3,$T3,$T4,$bswaphi);
+
+ verimg ($I1,$I0,$mask26,6); # >>26
+ veslg ($I0,$I0,32);
+ veslg ($I2,$I2,28); # >>4
+ verimg ($I3,$T3,$mask26,18); # >>14
+ verimg ($I4,$T3,$mask26,58); # >>38
+ vn ($I0,$I0,$mask26);
+ vn ($I2,$I2,$mask26);
+ vesrlf ($I4,$I4,2); # >>2
+
+ vgmg ($mask26,38,63);
+ vperm ($T3,$T1,$T2,$bswaplo);
+ vperm ($T4,$T1,$T2,$bswaphi);
+ vperm ($T2,$T1,$T2,$bswapmi);
+
+ verimg ($I0,$T3,$mask26,0);
+ verimg ($I1,$T3,$mask26,38); # >>26
+ verimg ($I2,$T2,$mask26,60); # >>4
+ verimg ($I3,$T4,$mask26,50); # >>14
+ vesrlg ($T4,$T4,40);
+ vo ($I4,$I4,$T4);
+
+ srlg ("%r0",$len,6);
+&{$z? \&aghi:\&ahi} ("%r0",-1);
+
+ALIGN (16);
+LABEL (".Loop_vx");
+ vmlef ($ACC0,$I0,$R0);
+ vmlef ($ACC1,$I0,$R1);
+ vmlef ($ACC2,$I0,$R2);
+ vmlef ($ACC3,$I0,$R3);
+ vmlef ($ACC4,$I0,$R4);
+
+ vmalef ($ACC0,$I1,$S4,$ACC0);
+ vmalef ($ACC1,$I1,$R0,$ACC1);
+ vmalef ($ACC2,$I1,$R1,$ACC2);
+ vmalef ($ACC3,$I1,$R2,$ACC3);
+ vmalef ($ACC4,$I1,$R3,$ACC4);
+
+ vaf ($H2,$H2,$I2);
+ vaf ($H0,$H0,$I0);
+ vaf ($H3,$H3,$I3);
+ vaf ($H1,$H1,$I1);
+ vaf ($H4,$H4,$I4);
+
+ vmalef ($ACC0,$I2,$S3,$ACC0);
+ vmalef ($ACC1,$I2,$S4,$ACC1);
+ vmalef ($ACC2,$I2,$R0,$ACC2);
+ vmalef ($ACC3,$I2,$R1,$ACC3);
+ vmalef ($ACC4,$I2,$R2,$ACC4);
+
+ vlm ($T1,$T4,"0x00($inp)"); # load next input block
+ la ($inp,"0x40($inp)");
+ vgmg ($mask26,6,31);
+
+ vmalef ($ACC0,$I3,$S2,$ACC0);
+ vmalef ($ACC1,$I3,$S3,$ACC1);
+ vmalef ($ACC2,$I3,$S4,$ACC2);
+ vmalef ($ACC3,$I3,$R0,$ACC3);
+ vmalef ($ACC4,$I3,$R1,$ACC4);
+
+ vperm ($I0,$T3,$T4,$bswaplo);
+ vperm ($I2,$T3,$T4,$bswapmi);
+ vperm ($T3,$T3,$T4,$bswaphi);
+
+ vmalef ($ACC0,$I4,$S1,$ACC0);
+ vmalef ($ACC1,$I4,$S2,$ACC1);
+ vmalef ($ACC2,$I4,$S3,$ACC2);
+ vmalef ($ACC3,$I4,$S4,$ACC3);
+ vmalef ($ACC4,$I4,$R0,$ACC4);
+
+ verimg ($I1,$I0,$mask26,6); # >>26
+ veslg ($I0,$I0,32);
+ veslg ($I2,$I2,28); # >>4
+ verimg ($I3,$T3,$mask26,18); # >>14
+
+ vmalof ($ACC0,$H0,$R0,$ACC0);
+ vmalof ($ACC1,$H0,$R1,$ACC1);
+ vmalof ($ACC2,$H0,$R2,$ACC2);
+ vmalof ($ACC3,$H0,$R3,$ACC3);
+ vmalof ($ACC4,$H0,$R4,$ACC4);
+
+ vgmf ($I4,5,5); # padbit<<2
+ verimg ($I4,$T3,$mask26,58); # >>38
+ vn ($I0,$I0,$mask26);
+ vn ($I2,$I2,$mask26);
+ vesrlf ($I4,$I4,2); # >>2
+
+ vmalof ($ACC0,$H1,$S4,$ACC0);
+ vmalof ($ACC1,$H1,$R0,$ACC1);
+ vmalof ($ACC2,$H1,$R1,$ACC2);
+ vmalof ($ACC3,$H1,$R2,$ACC3);
+ vmalof ($ACC4,$H1,$R3,$ACC4);
+
+ vgmg ($mask26,38,63);
+ vperm ($T3,$T1,$T2,$bswaplo);
+ vperm ($T4,$T1,$T2,$bswaphi);
+ vperm ($T2,$T1,$T2,$bswapmi);
+
+ vmalof ($ACC0,$H2,$S3,$ACC0);
+ vmalof ($ACC1,$H2,$S4,$ACC1);
+ vmalof ($ACC2,$H2,$R0,$ACC2);
+ vmalof ($ACC3,$H2,$R1,$ACC3);
+ vmalof ($ACC4,$H2,$R2,$ACC4);
+
+ verimg ($I0,$T3,$mask26,0);
+ verimg ($I1,$T3,$mask26,38); # >>26
+ verimg ($I2,$T2,$mask26,60); # >>4
+
+ vmalof ($ACC0,$H3,$S2,$ACC0);
+ vmalof ($ACC1,$H3,$S3,$ACC1);
+ vmalof ($ACC2,$H3,$S4,$ACC2);
+ vmalof ($ACC3,$H3,$R0,$ACC3);
+ vmalof ($ACC4,$H3,$R1,$ACC4);
+
+ verimg ($I3,$T4,$mask26,50); # >>14
+ vesrlg ($T4,$T4,40);
+ vo ($I4,$I4,$T4);
+
+ vmalof ($ACC0,$H4,$S1,$ACC0);
+ vmalof ($ACC1,$H4,$S2,$ACC1);
+ vmalof ($ACC2,$H4,$S3,$ACC2);
+ vmalof ($ACC3,$H4,$S4,$ACC3);
+ vmalof ($ACC4,$H4,$R0,$ACC4);
+
+ ################################################################
+ # lazy reduction as discussed in "NEON crypto" by D.J. Bernstein
+ # and P. Schwabe
+
+ vesrlg ($H4,$ACC3,26);
+ vesrlg ($H1,$ACC0,26);
+ vn ($H3,$ACC3,$mask26);
+ vn ($H0,$ACC0,$mask26);
+ vag ($H4,$H4,$ACC4); # h3 -> h4
+ vag ($H1,$H1,$ACC1); # h0 -> h1
+
+ vesrlg ($ACC4,$H4,26);
+ vesrlg ($ACC1,$H1,26);
+ vn ($H4,$H4,$mask26);
+ vn ($H1,$H1,$mask26);
+ vag ($H0,$H0,$ACC4);
+ vag ($H2,$ACC2,$ACC1); # h1 -> h2
+
+ veslg ($ACC4,$ACC4,2); # <<2
+ vesrlg ($ACC2,$H2,26);
+ vn ($H2,$H2,$mask26);
+ vag ($H0,$H0,$ACC4); # h4 -> h0
+ vag ($H3,$H3,$ACC2); # h2 -> h3
+
+ vesrlg ($ACC0,$H0,26);
+ vesrlg ($ACC3,$H3,26);
+ vn ($H0,$H0,$mask26);
+ vn ($H3,$H3,$mask26);
+ vag ($H1,$H1,$ACC0); # h0 -> h1
+ vag ($H4,$H4,$ACC3); # h3 -> h4
+
+&{$z? \&brctg:\&brct} ("%r0",".Loop_vx");
+
+ vlm ($R0,$S4,"48($ctx)"); # load all powers
+
+ lghi ("%r0",0x30);
+&{$z? \&lcgr:\&lcr} ($len,$len);
+&{$z? \&ngr:\&nr} ($len,"%r0");
+&{$z? \&slgr:\&slr} ($inp,$len);
+
+LABEL (".Last");
+ vmlef ($ACC0,$I0,$R0);
+ vmlef ($ACC1,$I0,$R1);
+ vmlef ($ACC2,$I0,$R2);
+ vmlef ($ACC3,$I0,$R3);
+ vmlef ($ACC4,$I0,$R4);
+
+ vmalef ($ACC0,$I1,$S4,$ACC0);
+ vmalef ($ACC1,$I1,$R0,$ACC1);
+ vmalef ($ACC2,$I1,$R1,$ACC2);
+ vmalef ($ACC3,$I1,$R2,$ACC3);
+ vmalef ($ACC4,$I1,$R3,$ACC4);
+
+ vaf ($H0,$H0,$I0);
+ vaf ($H1,$H1,$I1);
+ vaf ($H2,$H2,$I2);
+ vaf ($H3,$H3,$I3);
+ vaf ($H4,$H4,$I4);
+
+ vmalef ($ACC0,$I2,$S3,$ACC0);
+ vmalef ($ACC1,$I2,$S4,$ACC1);
+ vmalef ($ACC2,$I2,$R0,$ACC2);
+ vmalef ($ACC3,$I2,$R1,$ACC3);
+ vmalef ($ACC4,$I2,$R2,$ACC4);
+
+ vmalef ($ACC0,$I3,$S2,$ACC0);
+ vmalef ($ACC1,$I3,$S3,$ACC1);
+ vmalef ($ACC2,$I3,$S4,$ACC2);
+ vmalef ($ACC3,$I3,$R0,$ACC3);
+ vmalef ($ACC4,$I3,$R1,$ACC4);
+
+ vmalef ($ACC0,$I4,$S1,$ACC0);
+ vmalef ($ACC1,$I4,$S2,$ACC1);
+ vmalef ($ACC2,$I4,$S3,$ACC2);
+ vmalef ($ACC3,$I4,$S4,$ACC3);
+ vmalef ($ACC4,$I4,$R0,$ACC4);
+
+ vmalof ($ACC0,$H0,$R0,$ACC0);
+ vmalof ($ACC1,$H0,$R1,$ACC1);
+ vmalof ($ACC2,$H0,$R2,$ACC2);
+ vmalof ($ACC3,$H0,$R3,$ACC3);
+ vmalof ($ACC4,$H0,$R4,$ACC4);
+
+ vmalof ($ACC0,$H1,$S4,$ACC0);
+ vmalof ($ACC1,$H1,$R0,$ACC1);
+ vmalof ($ACC2,$H1,$R1,$ACC2);
+ vmalof ($ACC3,$H1,$R2,$ACC3);
+ vmalof ($ACC4,$H1,$R3,$ACC4);
+
+ vmalof ($ACC0,$H2,$S3,$ACC0);
+ vmalof ($ACC1,$H2,$S4,$ACC1);
+ vmalof ($ACC2,$H2,$R0,$ACC2);
+ vmalof ($ACC3,$H2,$R1,$ACC3);
+ vmalof ($ACC4,$H2,$R2,$ACC4);
+
+ vmalof ($ACC0,$H3,$S2,$ACC0);
+ vmalof ($ACC1,$H3,$S3,$ACC1);
+ vmalof ($ACC2,$H3,$S4,$ACC2);
+ vmalof ($ACC3,$H3,$R0,$ACC3);
+ vmalof ($ACC4,$H3,$R1,$ACC4);
+
+ vmalof ($ACC0,$H4,$S1,$ACC0);
+ vmalof ($ACC1,$H4,$S2,$ACC1);
+ vmalof ($ACC2,$H4,$S3,$ACC2);
+ vmalof ($ACC3,$H4,$S4,$ACC3);
+ vmalof ($ACC4,$H4,$R0,$ACC4);
+
+ ################################################################
+ # horizontal addition
+
+ vzero ($H0);
+ vsumqg ($ACC0,$ACC0,$H0);
+ vsumqg ($ACC1,$ACC1,$H0);
+ vsumqg ($ACC2,$ACC2,$H0);
+ vsumqg ($ACC3,$ACC3,$H0);
+ vsumqg ($ACC4,$ACC4,$H0);
+
+ ################################################################
+ # lazy reduction
+
+ vesrlg ($H4,$ACC3,26);
+ vesrlg ($H1,$ACC0,26);
+ vn ($H3,$ACC3,$mask26);
+ vn ($H0,$ACC0,$mask26);
+ vag ($H4,$H4,$ACC4); # h3 -> h4
+ vag ($H1,$H1,$ACC1); # h0 -> h1
+
+ vesrlg ($ACC4,$H4,26);
+ vesrlg ($ACC1,$H1,26);
+ vn ($H4,$H4,$mask26);
+ vn ($H1,$H1,$mask26);
+ vag ($H0,$H0,$ACC4);
+ vag ($H2,$ACC2,$ACC1); # h1 -> h2
+
+ veslg ($ACC4,$ACC4,2); # <<2
+ vesrlg ($ACC2,$H2,26);
+ vn ($H2,$H2,$mask26);
+ vag ($H0,$H0,$ACC4); # h4 -> h0
+ vag ($H3,$H3,$ACC2); # h2 -> h3
+
+ vesrlg ($ACC0,$H0,26);
+ vesrlg ($ACC3,$H3,26);
+ vn ($H0,$H0,$mask26);
+ vn ($H3,$H3,$mask26);
+ vag ($H1,$H1,$ACC0); # h0 -> h1
+ vag ($H4,$H4,$ACC3); # h3 -> h4
+
+&{$z? \&clgfi:\&clfi} ($len,0);
+ je (".Ldone");
+
+ vlm ($T1,$T4,"0x00($inp)"); # load last partial block
+ vgmg ($mask26,6,31);
+ vgmf ($I4,5,5); # padbit<<2
+
+ vperm ($I0,$T3,$T4,$bswaplo);
+ vperm ($I2,$T3,$T4,$bswapmi);
+ vperm ($T3,$T3,$T4,$bswaphi);
+
+ vl ($ACC0,"0x30($len,%r1)"); # borrow $ACC0,1
+ vl ($ACC1,"0x60($len,%r1)");
+
+ verimg ($I1,$I0,$mask26,6); # >>26
+ veslg ($I0,$I0,32);
+ veslg ($I2,$I2,28); # >>4
+ verimg ($I3,$T3,$mask26,18); # >>14
+ verimg ($I4,$T3,$mask26,58); # >>38
+ vn ($I0,$I0,$mask26);
+ vn ($I2,$I2,$mask26);
+ vesrlf ($I4,$I4,2); # >>2
+
+ vgmg ($mask26,38,63);
+ vperm ($T3,$T1,$T2,$bswaplo);
+ vperm ($T4,$T1,$T2,$bswaphi);
+ vperm ($T2,$T1,$T2,$bswapmi);
+
+ verimg ($I0,$T3,$mask26,0);
+ verimg ($I1,$T3,$mask26,38); # >>26
+ verimg ($I2,$T2,$mask26,60); # >>4
+ verimg ($I3,$T4,$mask26,50); # >>14
+ vesrlg ($T4,$T4,40);
+ vo ($I4,$I4,$T4);
+
+ vperm ($H0,$H0,$H0,$ACC0); # move hash to right lane
+ vn ($I0,$I0,$ACC1); # mask redundant lane[s]
+ vperm ($H1,$H1,$H1,$ACC0);
+ vn ($I1,$I1,$ACC1);
+ vperm ($H2,$H2,$H2,$ACC0);
+ vn ($I2,$I2,$ACC1);
+ vperm ($H3,$H3,$H3,$ACC0);
+ vn ($I3,$I3,$ACC1);
+ vperm ($H4,$H4,$H4,$ACC0);
+ vn ($I4,$I4,$ACC1);
+
+ vaf ($I0,$I0,$H0); # accumulate hash
+ vzero ($H0); # wipe hash value
+ vaf ($I1,$I1,$H1);
+ vzero ($H1);
+ vaf ($I2,$I2,$H2);
+ vzero ($H2);
+ vaf ($I3,$I3,$H3);
+ vzero ($H3);
+ vaf ($I4,$I4,$H4);
+ vzero ($H4);
+
+&{$z? \&lghi:\&lhi} ($len,0);
+ j (".Last");
+ # I don't bother to tell apart cases when only one multiplication
+ # pass is sufficient, because I argue that mispredicted branch
+ # penalties are comparable to overhead of sometimes redundant
+ # multiplication pass...
+
+LABEL (".Ldone");
+ vstef ($H0,"0($ctx)",3); # store hash base 2^26
+ vstef ($H1,"4($ctx)",3);
+ vstef ($H2,"8($ctx)",3);
+ vstef ($H3,"12($ctx)",3);
+ vstef ($H4,"16($ctx)",3);
+
+if ($z) {
+ ld ("%f8","$stdframe+0*8($sp)");
+ ld ("%f9","$stdframe+1*8($sp)");
+ ld ("%f10","$stdframe+2*8($sp)");
+ ld ("%f11","$stdframe+3*8($sp)");
+ ld ("%f12","$stdframe+4*8($sp)");
+ ld ("%f13","$stdframe+5*8($sp)");
+ ld ("%f14","$stdframe+6*8($sp)");
+ ld ("%f15","$stdframe+7*8($sp)");
+&{$z? \&lmg:\&lm} ("%r10","%r15","$stdframe+8*8+10*$SIZE_T($sp)");
+} else {
+ ld ("%f4","$stdframe+16*$SIZE_T+2*8($sp)");
+ ld ("%f6","$stdframe+16*$SIZE_T+3*8($sp)");
+&{$z? \&lmg:\&lm} ("%r10","%r15","$stdframe+10*$SIZE_T($sp)");
+}
+ br ("%r14");
+SIZE ("__poly1305_blocks_vx",".-__poly1305_blocks_vx");
}
+
+################
+# static void poly1305_emit(void *ctx, unsigned char mac[16],
+# const u32 nonce[4])
{
my ($mac,$nonce)=($inp,$len);
-my ($h0,$h1,$h2,$d0,$d1)=map("%r$_",(5..9));
-
-$code.=<<___;
-.globl poly1305_emit
-.type poly1305_emit,\@function
-.align 16
-poly1305_emit:
- stm${g} %r6,%r9,`6*$SIZE_T`($sp)
-
- lg $h0,0($ctx)
- lg $h1,8($ctx)
- lg $h2,16($ctx)
-
- lghi %r0,5
- lghi %r1,0
- lgr $d0,$h0
- lgr $d1,$h1
-
- algr $h0,%r0 # compare to modulus
- alcgr $h1,%r1
- alcgr $h2,%r1
-
- srlg $h2,$h2,2 # did it borrow/carry?
- slgr %r1,$h2 # 0-$h2>>2
- lg $h2,0($nonce) # load nonce
- lghi %r0,-1
- lg $ctx,8($nonce)
- xgr %r0,%r1 # ~%r1
-
- ngr $h0,%r1
- ngr $d0,%r0
- ngr $h1,%r1
- ngr $d1,%r0
- ogr $h0,$d0
- rllg $d0,$h2,32 # flip nonce words
- ogr $h1,$d1
- rllg $d1,$ctx,32
-
- algr $h0,$d0 # accumulate nonce
- alcgr $h1,$d1
-
- strvg $h0,0($mac) # write little-endian result
- strvg $h1,8($mac)
-
- lm${g} %r6,%r9,`6*$SIZE_T`($sp)
- br %r14
-.size poly1305_emit,.-poly1305_emit
-
-.string "Poly1305 for s390x, CRYPTOGAMS by <appro\@openssl.org>"
-___
+my ($h0,$h1,$h2,$d0,$d1,$d2)=map("%r$_",(5..10));
+
+GLOBL ("poly1305_emit");
+TYPE ("poly1305_emit","\@function");
+ALIGN (16);
+LABEL ("poly1305_emit");
+LABEL (".Lpoly1305_emit");
+&{$z? \&stmg:\&stm} ("%r6","%r10","6*$SIZE_T($sp)");
+
+ lg ($d0,"0($ctx)");
+ lg ($d1,"8($ctx)");
+ lg ($d2,"16($ctx)");
+
+ llgfr ("%r0",$d0); # base 2^26 -> base 2^64
+ srlg ($h0,$d0,32);
+ llgfr ("%r1",$d1);
+ srlg ($h1,$d1,32);
+ srlg ($h2,$d2,32);
+
+ sllg ("%r0","%r0",26);
+ algr ($h0,"%r0");
+ sllg ("%r0",$h1,52);
+ srlg ($h1,$h1,12);
+ sllg ("%r1","%r1",14);
+ algr ($h0,"%r0");
+ alcgr ($h1,"%r1");
+ sllg ("%r0",$h2,40);
+ srlg ($h2,$h2,24);
+ lghi ("%r1",0);
+ algr ($h1,"%r0");
+ alcgr ($h2,"%r1");
+
+ llgf ("%r0","24($ctx)"); # is_base2_26
+ lcgr ("%r0","%r0");
+
+ xgr ($h0,$d0); # choose between radixes
+ xgr ($h1,$d1);
+ xgr ($h2,$d2);
+ ngr ($h0,"%r0");
+ ngr ($h1,"%r0");
+ ngr ($h2,"%r0");
+ xgr ($h0,$d0);
+ xgr ($h1,$d1);
+ xgr ($h2,$d2);
+
+ lghi ("%r0",5);
+ lgr ($d0,$h0);
+ lgr ($d1,$h1);
+
+ algr ($h0,"%r0"); # compare to modulus
+ alcgr ($h1,"%r1");
+ alcgr ($h2,"%r1");
+
+ srlg ($h2,$h2,2); # did it borrow/carry?
+ slgr ("%r1",$h2); # 0-$h2>>2
+ lg ($d2,"0($nonce)"); # load nonce
+ lg ($ctx,"8($nonce)");
+
+ xgr ($h0,$d0);
+ xgr ($h1,$d1);
+ ngr ($h0,"%r1");
+ ngr ($h1,"%r1");
+ xgr ($h0,$d0);
+ rllg ($d0,$d2,32); # flip nonce words
+ xgr ($h1,$d1);
+ rllg ($d1,$ctx,32);
+
+ algr ($h0,$d0); # accumulate nonce
+ alcgr ($h1,$d1);
+
+ strvg ($h0,"0($mac)"); # write little-endian result
+ strvg ($h1,"8($mac)");
+
+&{$z? \&lmg:\&lm} ("%r6","%r10","6*$SIZE_T($sp)");
+ br ("%r14");
+SIZE ("poly1305_emit",".-poly1305_emit");
}
-$code =~ s/\`([^\`]*)\`/eval $1/gem;
-$code =~ s/\b(srlg\s+)(%r[0-9]+\s*,)\s*([0-9]+)/$1$2$2$3/gm;
+################
+
+ALIGN (16);
+LABEL (".Lconst");
+LONG (0x04050607,0x14151617,0x0c0d0e0f,0x1c1d1e1f); # merge odd
+LONG (0x07060504,0x03020100,0x17161514,0x13121110); # byte swap masks
+LONG (0x0f0e0d0c,0x0b0a0908,0x1f1e1d1c,0x1b1a1918);
+LONG (0x00000000,0x09080706,0x00000000,0x19181716);
+
+LONG (0x00000000,0x00000000,0x00000000,0x0c0d0e0f); # magic tail masks
+LONG (0x0c0d0e0f,0x00000000,0x00000000,0x00000000);
+LONG (0x00000000,0x00000000,0x0c0d0e0f,0x00000000);
+
+LONG (0xffffffff,0x00000000,0xffffffff,0xffffffff);
+LONG (0xffffffff,0x00000000,0xffffffff,0x00000000);
+LONG (0x00000000,0x00000000,0xffffffff,0x00000000);
+
+STRING ("\"Poly1305 for s390x, CRYPTOGAMS by <appro\@openssl.org>\"");
-print $code;
-close STDOUT or die "error closing STDOUT: $!";
+PERLASM_END();
diff --git a/crypto/poly1305/asm/poly1305-sparcv9.pl b/crypto/poly1305/asm/poly1305-sparcv9.pl
index 997e0d8344c6..dc592a07acac 100755
--- a/crypto/poly1305/asm/poly1305-sparcv9.pl
+++ b/crypto/poly1305/asm/poly1305-sparcv9.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -41,19 +41,21 @@
# (***) Multi-process benchmark saturates at ~12.5x single-process
# result on 8-core processor, or ~21GBps per 2.85GHz socket.
-my $output = pop;
-open STDOUT,">$output";
+# $output is the last argument if it looks like a file (it has an extension)
+my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+
+open STDOUT,">$output" if $output;
my ($ctx,$inp,$len,$padbit,$shl,$shr) = map("%i$_",(0..5));
my ($r0,$r1,$r2,$r3,$s1,$s2,$s3,$h4) = map("%l$_",(0..7));
my ($h0,$h1,$h2,$h3, $t0,$t1,$t2) = map("%o$_",(0..5,7));
my ($d0,$d1,$d2,$d3) = map("%g$_",(1..4));
-my $output = pop;
-open STDOUT,">$stdout";
-
$code.=<<___;
-#include "sparc_arch.h"
+#ifndef __ASSEMBLER__
+# define __ASSEMBLER__ 1
+#endif
+#include "crypto/sparc_arch.h"
#ifdef __arch64__
.register %g2,#scratch
diff --git a/crypto/poly1305/asm/poly1305-x86.pl b/crypto/poly1305/asm/poly1305-x86.pl
index 2ae16a230b66..c91d01fb3ba4 100755
--- a/crypto/poly1305/asm/poly1305-x86.pl
+++ b/crypto/poly1305/asm/poly1305-x86.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -47,8 +47,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386");
diff --git a/crypto/poly1305/asm/poly1305-x86_64.pl b/crypto/poly1305/asm/poly1305-x86_64.pl
index 5f834d8faf2a..fa9bfb7a7b81 100755
--- a/crypto/poly1305/asm/poly1305-x86_64.pl
+++ b/crypto/poly1305/asm/poly1305-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -63,9 +63,10 @@
# (***) strangely enough performance seems to vary from core to core,
# listed result is best case;
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -94,7 +95,8 @@ if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|.*based on LLVM) ([0
$avx = ($2>=3.0) + ($2>3.0);
}
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
my ($ctx,$inp,$len,$padbit)=("%rdi","%rsi","%rdx","%rcx");
@@ -2806,6 +2808,7 @@ $code.=<<___;
.align 32
poly1305_blocks_vpmadd52:
.cfi_startproc
+ endbranch
shr \$4,$len
jz .Lno_data_vpmadd52 # too short
@@ -3739,6 +3742,7 @@ $code.=<<___;
.align 32
poly1305_emit_base2_44:
.cfi_startproc
+ endbranch
mov 0($ctx),%r8 # load hash value
mov 8($ctx),%r9
mov 16($ctx),%r10
diff --git a/crypto/poly1305/build.info b/crypto/poly1305/build.info
index 4e4dcca521f6..e359a2225df5 100644
--- a/crypto/poly1305/build.info
+++ b/crypto/poly1305/build.info
@@ -1,25 +1,53 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- poly1305_pmeth.c \
- poly1305_ameth.c \
- poly1305.c {- $target{poly1305_asm_src} -}
-GENERATE[poly1305-sparcv9.S]=asm/poly1305-sparcv9.pl $(PERLASM_SCHEME)
+$POLY1305ASM=
+IF[{- !$disabled{asm} -}]
+ $POLY1305ASM_x86=poly1305-x86.S
+ $POLY1305ASM_x86_64=poly1305-x86_64.s
+
+ $POLY1305ASM_ia64=poly1305-ia64.s
+
+ $POLY1305ASM_sparcv9=poly1305-sparcv9.S
+
+ $POLY1305ASM_mips64=poly1305-mips.S
+
+ $POLY1305ASM_s390x=poly1305-s390x.S
+
+ $POLY1305ASM_armv4=poly1305-armv4.S
+ $POLY1305ASM_aarch64=poly1305-armv8.S
+
+ $POLY1305ASM_ppc32=poly1305_ppc.c poly1305-ppc.s poly1305-ppcfp.s
+ $POLY1305ASM_ppc64=$POLY1305ASM_ppc32
+
+ $POLY1305ASM_c64xplus=poly1305-c64xplus.s
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+ IF[$POLY1305ASM_{- $target{asm_arch} -}]
+ $POLY1305ASM=$POLY1305ASM_{- $target{asm_arch} -}
+ $POLY1305DEF=POLY1305_ASM
+ ENDIF
+ENDIF
+
+SOURCE[../../libcrypto]=poly1305.c $POLY1305ASM
+
+# Implementations are now spread across several libraries, so the defines
+# need to be applied to all affected libraries and modules.
+DEFINE[../../libcrypto]=$POLY1305DEF
+
+GENERATE[poly1305-sparcv9.S]=asm/poly1305-sparcv9.pl
INCLUDE[poly1305-sparcv9.o]=..
-GENERATE[poly1305-x86.s]=asm/poly1305-x86.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-GENERATE[poly1305-x86_64.s]=asm/poly1305-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[poly1305-ppc.s]=asm/poly1305-ppc.pl $(PERLASM_SCHEME)
-GENERATE[poly1305-ppcfp.s]=asm/poly1305-ppcfp.pl $(PERLASM_SCHEME)
-GENERATE[poly1305-armv4.S]=asm/poly1305-armv4.pl $(PERLASM_SCHEME)
+GENERATE[poly1305-x86.S]=asm/poly1305-x86.pl
+GENERATE[poly1305-x86_64.s]=asm/poly1305-x86_64.pl
+GENERATE[poly1305-ia64.s]=asm/poly1305-ia64.S
+GENERATE[poly1305-ppc.s]=asm/poly1305-ppc.pl
+GENERATE[poly1305-ppcfp.s]=asm/poly1305-ppcfp.pl
+GENERATE[poly1305-armv4.S]=asm/poly1305-armv4.pl
INCLUDE[poly1305-armv4.o]=..
-GENERATE[poly1305-armv8.S]=asm/poly1305-armv8.pl $(PERLASM_SCHEME)
+GENERATE[poly1305-armv8.S]=asm/poly1305-armv8.pl
INCLUDE[poly1305-armv8.o]=..
-GENERATE[poly1305-mips.S]=asm/poly1305-mips.pl $(PERLASM_SCHEME)
+GENERATE[poly1305-mips.S]=asm/poly1305-mips.pl
INCLUDE[poly1305-mips.o]=..
-GENERATE[poly1305-s390x.S]=asm/poly1305-s390x.pl $(PERLASM_SCHEME)
-
-BEGINRAW[Makefile(unix)]
-{- $builddir -}/poly1305-%.S: {- $sourcedir -}/asm/poly1305-%.pl
- CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@
-ENDRAW[Makefile(unix)]
+GENERATE[poly1305-c64xplus.S]=asm/poly1305-c64xplus.pl
+INCLUDE[poly1305-s390x.o]=..
+GENERATE[poly1305-s390x.S]=asm/poly1305-s390x.pl
diff --git a/crypto/poly1305/poly1305.c b/crypto/poly1305/poly1305.c
index e7f5b92c8f3d..b3bf2b117bbf 100644
--- a/crypto/poly1305/poly1305.c
+++ b/crypto/poly1305/poly1305.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,7 +12,6 @@
#include <openssl/crypto.h>
#include "crypto/poly1305.h"
-#include "poly1305_local.h"
size_t Poly1305_ctx_size(void)
{
@@ -95,11 +94,10 @@ poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, u32 padbit);
(a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(a) * 8 - 1) \
)
-# if (defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16) && \
- (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__==8)
+# if defined(INT64_MAX) && defined(INT128_MAX)
typedef unsigned long u64;
-typedef __uint128_t u128;
+typedef uint128_t u128;
typedef struct {
u64 h[3];
diff --git a/crypto/poly1305/poly1305_ameth.c b/crypto/poly1305/poly1305_ameth.c
deleted file mode 100644
index 0dddf79626e3..000000000000
--- a/crypto/poly1305/poly1305_ameth.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/evp.h>
-#include "crypto/asn1.h"
-#include "crypto/poly1305.h"
-#include "poly1305_local.h"
-#include "crypto/evp.h"
-
-/*
- * POLY1305 "ASN1" method. This is just here to indicate the maximum
- * POLY1305 output length and to free up a POLY1305 key.
- */
-
-static int poly1305_size(const EVP_PKEY *pkey)
-{
- return POLY1305_DIGEST_SIZE;
-}
-
-static void poly1305_key_free(EVP_PKEY *pkey)
-{
- ASN1_OCTET_STRING *os = EVP_PKEY_get0(pkey);
- if (os != NULL) {
- if (os->data != NULL)
- OPENSSL_cleanse(os->data, os->length);
- ASN1_OCTET_STRING_free(os);
- }
-}
-
-static int poly1305_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
-{
- /* nothing, (including ASN1_PKEY_CTRL_DEFAULT_MD_NID), is supported */
- return -2;
-}
-
-static int poly1305_pkey_public_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
-{
- return ASN1_OCTET_STRING_cmp(EVP_PKEY_get0(a), EVP_PKEY_get0(b)) == 0;
-}
-
-static int poly1305_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
- size_t len)
-{
- ASN1_OCTET_STRING *os;
-
- if (pkey->pkey.ptr != NULL || len != POLY1305_KEY_SIZE)
- return 0;
-
- os = ASN1_OCTET_STRING_new();
- if (os == NULL)
- return 0;
-
- if (!ASN1_OCTET_STRING_set(os, priv, len)) {
- ASN1_OCTET_STRING_free(os);
- return 0;
- }
-
- pkey->pkey.ptr = os;
- return 1;
-}
-
-static int poly1305_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
- size_t *len)
-{
- ASN1_OCTET_STRING *os = (ASN1_OCTET_STRING *)pkey->pkey.ptr;
-
- if (priv == NULL) {
- *len = POLY1305_KEY_SIZE;
- return 1;
- }
-
- if (os == NULL || *len < POLY1305_KEY_SIZE)
- return 0;
-
- memcpy(priv, ASN1_STRING_get0_data(os), ASN1_STRING_length(os));
- *len = POLY1305_KEY_SIZE;
-
- return 1;
-}
-
-const EVP_PKEY_ASN1_METHOD poly1305_asn1_meth = {
- EVP_PKEY_POLY1305,
- EVP_PKEY_POLY1305,
- 0,
-
- "POLY1305",
- "OpenSSL POLY1305 method",
-
- 0, 0, poly1305_pkey_public_cmp, 0,
-
- 0, 0, 0,
-
- poly1305_size,
- 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-
- poly1305_key_free,
- poly1305_pkey_ctrl,
- NULL,
- NULL,
-
- NULL,
- NULL,
- NULL,
-
- NULL,
- NULL,
- NULL,
-
- poly1305_set_priv_key,
- NULL,
- poly1305_get_priv_key,
- NULL,
-};
diff --git a/crypto/poly1305/poly1305_base2_44.c b/crypto/poly1305/poly1305_base2_44.c
index b6313d01ba4e..a71e5e86e6b9 100644
--- a/crypto/poly1305/poly1305_base2_44.c
+++ b/crypto/poly1305/poly1305_base2_44.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -18,7 +18,7 @@
typedef unsigned char u8;
typedef unsigned int u32;
typedef unsigned long u64;
-typedef unsigned __int128 u128;
+typedef uint128_t u128;
typedef struct {
u64 h[3];
diff --git a/crypto/poly1305/poly1305_ieee754.c b/crypto/poly1305/poly1305_ieee754.c
index 7cfd968645ff..110feb4d5720 100644
--- a/crypto/poly1305/poly1305_ieee754.c
+++ b/crypto/poly1305/poly1305_ieee754.c
@@ -1,7 +1,7 @@
/*
* Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/poly1305/poly1305_local.h b/crypto/poly1305/poly1305_local.h
deleted file mode 100644
index 6d4d9dc5b621..000000000000
--- a/crypto/poly1305/poly1305_local.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-typedef void (*poly1305_blocks_f) (void *ctx, const unsigned char *inp,
- size_t len, unsigned int padbit);
-typedef void (*poly1305_emit_f) (void *ctx, unsigned char mac[16],
- const unsigned int nonce[4]);
-
-struct poly1305_context {
- double opaque[24]; /* large enough to hold internal state, declared
- * 'double' to ensure at least 64-bit invariant
- * alignment across all platforms and
- * configurations */
- unsigned int nonce[4];
- unsigned char data[POLY1305_BLOCK_SIZE];
- size_t num;
- struct {
- poly1305_blocks_f blocks;
- poly1305_emit_f emit;
- } func;
-};
diff --git a/crypto/poly1305/poly1305_pmeth.c b/crypto/poly1305/poly1305_pmeth.c
deleted file mode 100644
index 49a799a12f51..000000000000
--- a/crypto/poly1305/poly1305_pmeth.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-#include <openssl/evp.h>
-#include <openssl/err.h>
-#include "crypto/poly1305.h"
-#include "poly1305_local.h"
-#include "crypto/evp.h"
-
-/* POLY1305 pkey context structure */
-
-typedef struct {
- ASN1_OCTET_STRING ktmp; /* Temp storage for key */
- POLY1305 ctx;
-} POLY1305_PKEY_CTX;
-
-static int pkey_poly1305_init(EVP_PKEY_CTX *ctx)
-{
- POLY1305_PKEY_CTX *pctx;
-
- if ((pctx = OPENSSL_zalloc(sizeof(*pctx))) == NULL) {
- CRYPTOerr(CRYPTO_F_PKEY_POLY1305_INIT, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- pctx->ktmp.type = V_ASN1_OCTET_STRING;
-
- EVP_PKEY_CTX_set_data(ctx, pctx);
- EVP_PKEY_CTX_set0_keygen_info(ctx, NULL, 0);
- return 1;
-}
-
-static void pkey_poly1305_cleanup(EVP_PKEY_CTX *ctx)
-{
- POLY1305_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
-
- if (pctx != NULL) {
- OPENSSL_clear_free(pctx->ktmp.data, pctx->ktmp.length);
- OPENSSL_clear_free(pctx, sizeof(*pctx));
- EVP_PKEY_CTX_set_data(ctx, NULL);
- }
-}
-
-static int pkey_poly1305_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
-{
- POLY1305_PKEY_CTX *sctx, *dctx;
-
- /* allocate memory for dst->data and a new POLY1305_CTX in dst->data->ctx */
- if (!pkey_poly1305_init(dst))
- return 0;
- sctx = EVP_PKEY_CTX_get_data(src);
- dctx = EVP_PKEY_CTX_get_data(dst);
- if (ASN1_STRING_get0_data(&sctx->ktmp) != NULL &&
- !ASN1_STRING_copy(&dctx->ktmp, &sctx->ktmp)) {
- /* cleanup and free the POLY1305_PKEY_CTX in dst->data */
- pkey_poly1305_cleanup(dst);
- return 0;
- }
- memcpy(&dctx->ctx, &sctx->ctx, sizeof(POLY1305));
- return 1;
-}
-
-static int pkey_poly1305_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
-{
- ASN1_OCTET_STRING *key;
- POLY1305_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
-
- if (ASN1_STRING_get0_data(&pctx->ktmp) == NULL)
- return 0;
- key = ASN1_OCTET_STRING_dup(&pctx->ktmp);
- if (key == NULL)
- return 0;
- return EVP_PKEY_assign_POLY1305(pkey, key);
-}
-
-static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- POLY1305_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx));
-
- Poly1305_Update(&pctx->ctx, data, count);
- return 1;
-}
-
-static int poly1305_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
-{
- POLY1305_PKEY_CTX *pctx = ctx->data;
- ASN1_OCTET_STRING *key = (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr;
-
- if (key->length != POLY1305_KEY_SIZE)
- return 0;
- EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
- EVP_MD_CTX_set_update_fn(mctx, int_update);
- Poly1305_Init(&pctx->ctx, key->data);
- return 1;
-}
-static int poly1305_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
- EVP_MD_CTX *mctx)
-{
- POLY1305_PKEY_CTX *pctx = ctx->data;
-
- *siglen = POLY1305_DIGEST_SIZE;
- if (sig != NULL)
- Poly1305_Final(&pctx->ctx, sig);
- return 1;
-}
-
-static int pkey_poly1305_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
-{
- POLY1305_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
- const unsigned char *key;
- size_t len;
-
- switch (type) {
-
- case EVP_PKEY_CTRL_MD:
- /* ignore */
- break;
-
- case EVP_PKEY_CTRL_SET_MAC_KEY:
- case EVP_PKEY_CTRL_DIGESTINIT:
- if (type == EVP_PKEY_CTRL_SET_MAC_KEY) {
- /* user explicitly setting the key */
- key = p2;
- len = p1;
- } else {
- /* user indirectly setting the key via EVP_DigestSignInit */
- key = EVP_PKEY_get0_poly1305(EVP_PKEY_CTX_get0_pkey(ctx), &len);
- }
- if (key == NULL || len != POLY1305_KEY_SIZE ||
- !ASN1_OCTET_STRING_set(&pctx->ktmp, key, len))
- return 0;
- Poly1305_Init(&pctx->ctx, ASN1_STRING_get0_data(&pctx->ktmp));
- break;
-
- default:
- return -2;
-
- }
- return 1;
-}
-
-static int pkey_poly1305_ctrl_str(EVP_PKEY_CTX *ctx,
- const char *type, const char *value)
-{
- if (value == NULL)
- return 0;
- if (strcmp(type, "key") == 0)
- return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
- if (strcmp(type, "hexkey") == 0)
- return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
- return -2;
-}
-
-const EVP_PKEY_METHOD poly1305_pkey_meth = {
- EVP_PKEY_POLY1305,
- EVP_PKEY_FLAG_SIGCTX_CUSTOM, /* we don't deal with a separate MD */
- pkey_poly1305_init,
- pkey_poly1305_copy,
- pkey_poly1305_cleanup,
-
- 0, 0,
-
- 0,
- pkey_poly1305_keygen,
-
- 0, 0,
-
- 0, 0,
-
- 0, 0,
-
- poly1305_signctx_init,
- poly1305_signctx,
-
- 0, 0,
-
- 0, 0,
-
- 0, 0,
-
- 0, 0,
-
- pkey_poly1305_ctrl,
- pkey_poly1305_ctrl_str
-};
diff --git a/crypto/poly1305/poly1305_ppc.c b/crypto/poly1305/poly1305_ppc.c
new file mode 100644
index 000000000000..4e4e3d1994f1
--- /dev/null
+++ b/crypto/poly1305/poly1305_ppc.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2009-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+#include <openssl/types.h>
+#include "crypto/poly1305.h"
+#include "crypto/ppc_arch.h"
+
+void poly1305_init_int(void *ctx, const unsigned char key[16]);
+void poly1305_blocks(void *ctx, const unsigned char *inp, size_t len,
+ unsigned int padbit);
+void poly1305_emit(void *ctx, unsigned char mac[16],
+ const unsigned int nonce[4]);
+void poly1305_init_fpu(void *ctx, const unsigned char key[16]);
+void poly1305_blocks_fpu(void *ctx, const unsigned char *inp, size_t len,
+ unsigned int padbit);
+void poly1305_emit_fpu(void *ctx, unsigned char mac[16],
+ const unsigned int nonce[4]);
+void poly1305_init_vsx(void *ctx, const unsigned char key[16]);
+void poly1305_blocks_vsx(void *ctx, const unsigned char *inp, size_t len,
+ unsigned int padbit);
+void poly1305_emit_vsx(void *ctx, unsigned char mac[16],
+ const unsigned int nonce[4]);
+int poly1305_init(void *ctx, const unsigned char key[16], void *func[2]);
+int poly1305_init(void *ctx, const unsigned char key[16], void *func[2])
+{
+ if (OPENSSL_ppccap_P & PPC_CRYPTO207) {
+ poly1305_init_int(ctx, key);
+ func[0] = (void*)(uintptr_t)poly1305_blocks_vsx;
+ func[1] = (void*)(uintptr_t)poly1305_emit;
+ } else if (sizeof(size_t) == 4 && (OPENSSL_ppccap_P & PPC_FPU)) {
+ poly1305_init_fpu(ctx, key);
+ func[0] = (void*)(uintptr_t)poly1305_blocks_fpu;
+ func[1] = (void*)(uintptr_t)poly1305_emit_fpu;
+ } else {
+ poly1305_init_int(ctx, key);
+ func[0] = (void*)(uintptr_t)poly1305_blocks;
+ func[1] = (void*)(uintptr_t)poly1305_emit;
+ }
+ return 1;
+}
diff --git a/crypto/ppc_arch.h b/crypto/ppc_arch.h
deleted file mode 100644
index e3845e9394ae..000000000000
--- a/crypto/ppc_arch.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2014-2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef OSSL_CRYPTO_PPC_ARCH_H
-# define OSSL_CRYPTO_PPC_ARCH_H
-
-extern unsigned int OPENSSL_ppccap_P;
-
-/*
- * Flags' usage can appear ambiguous, because they are set rather
- * to reflect OpenSSL performance preferences than actual processor
- * capabilities.
- */
-# define PPC_FPU64 (1<<0)
-# define PPC_ALTIVEC (1<<1)
-# define PPC_CRYPTO207 (1<<2)
-# define PPC_FPU (1<<3)
-# define PPC_MADD300 (1<<4)
-# define PPC_MFTB (1<<5)
-# define PPC_MFSPR268 (1<<6)
-
-#endif
diff --git a/crypto/ppccap.c b/crypto/ppccap.c
index eeaa47cc6b41..8bcfed25e057 100644
--- a/crypto/ppccap.c
+++ b/crypto/ppccap.c
@@ -1,7 +1,7 @@
/*
* Copyright 2009-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -27,135 +27,13 @@
# include <sys/sysctl.h>
#endif
#include <openssl/crypto.h>
-#include <openssl/bn.h>
-#include <internal/cryptlib.h>
-#include <crypto/chacha.h>
-#include "bn/bn_local.h"
-
-#include "ppc_arch.h"
+#include "internal/cryptlib.h"
+#include "crypto/ppc_arch.h"
unsigned int OPENSSL_ppccap_P = 0;
static sigset_t all_masked;
-#ifdef OPENSSL_BN_ASM_MONT
-int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
- const BN_ULONG *np, const BN_ULONG *n0, int num)
-{
- int bn_mul_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
- const BN_ULONG *np, const BN_ULONG *n0, int num);
- int bn_mul4x_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
- const BN_ULONG *np, const BN_ULONG *n0, int num);
-
- if (num < 4)
- return 0;
-
- if ((num & 3) == 0)
- return bn_mul4x_mont_int(rp, ap, bp, np, n0, num);
-
- /*
- * There used to be [optional] call to bn_mul_mont_fpu64 here,
- * but above subroutine is faster on contemporary processors.
- * Formulation means that there might be old processors where
- * FPU code path would be faster, POWER6 perhaps, but there was
- * no opportunity to figure it out...
- */
-
- return bn_mul_mont_int(rp, ap, bp, np, n0, num);
-}
-#endif
-
-void sha256_block_p8(void *ctx, const void *inp, size_t len);
-void sha256_block_ppc(void *ctx, const void *inp, size_t len);
-void sha256_block_data_order(void *ctx, const void *inp, size_t len);
-void sha256_block_data_order(void *ctx, const void *inp, size_t len)
-{
- OPENSSL_ppccap_P & PPC_CRYPTO207 ? sha256_block_p8(ctx, inp, len) :
- sha256_block_ppc(ctx, inp, len);
-}
-
-void sha512_block_p8(void *ctx, const void *inp, size_t len);
-void sha512_block_ppc(void *ctx, const void *inp, size_t len);
-void sha512_block_data_order(void *ctx, const void *inp, size_t len);
-void sha512_block_data_order(void *ctx, const void *inp, size_t len)
-{
- OPENSSL_ppccap_P & PPC_CRYPTO207 ? sha512_block_p8(ctx, inp, len) :
- sha512_block_ppc(ctx, inp, len);
-}
-
-#ifndef OPENSSL_NO_CHACHA
-void ChaCha20_ctr32_int(unsigned char *out, const unsigned char *inp,
- size_t len, const unsigned int key[8],
- const unsigned int counter[4]);
-void ChaCha20_ctr32_vmx(unsigned char *out, const unsigned char *inp,
- size_t len, const unsigned int key[8],
- const unsigned int counter[4]);
-void ChaCha20_ctr32_vsx(unsigned char *out, const unsigned char *inp,
- size_t len, const unsigned int key[8],
- const unsigned int counter[4]);
-void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp,
- size_t len, const unsigned int key[8],
- const unsigned int counter[4])
-{
- OPENSSL_ppccap_P & PPC_CRYPTO207
- ? ChaCha20_ctr32_vsx(out, inp, len, key, counter)
- : OPENSSL_ppccap_P & PPC_ALTIVEC
- ? ChaCha20_ctr32_vmx(out, inp, len, key, counter)
- : ChaCha20_ctr32_int(out, inp, len, key, counter);
-}
-#endif
-
-#ifndef OPENSSL_NO_POLY1305
-void poly1305_init_int(void *ctx, const unsigned char key[16]);
-void poly1305_blocks(void *ctx, const unsigned char *inp, size_t len,
- unsigned int padbit);
-void poly1305_emit(void *ctx, unsigned char mac[16],
- const unsigned int nonce[4]);
-void poly1305_init_fpu(void *ctx, const unsigned char key[16]);
-void poly1305_blocks_fpu(void *ctx, const unsigned char *inp, size_t len,
- unsigned int padbit);
-void poly1305_emit_fpu(void *ctx, unsigned char mac[16],
- const unsigned int nonce[4]);
-int poly1305_init(void *ctx, const unsigned char key[16], void *func[2]);
-int poly1305_init(void *ctx, const unsigned char key[16], void *func[2])
-{
- if (sizeof(size_t) == 4 && (OPENSSL_ppccap_P & PPC_FPU)) {
- poly1305_init_fpu(ctx, key);
- func[0] = (void*)(uintptr_t)poly1305_blocks_fpu;
- func[1] = (void*)(uintptr_t)poly1305_emit_fpu;
- } else {
- poly1305_init_int(ctx, key);
- func[0] = (void*)(uintptr_t)poly1305_blocks;
- func[1] = (void*)(uintptr_t)poly1305_emit;
- }
- return 1;
-}
-#endif
-
-#ifdef ECP_NISTZ256_ASM
-void ecp_nistz256_mul_mont(unsigned long res[4], const unsigned long a[4],
- const unsigned long b[4]);
-
-void ecp_nistz256_to_mont(unsigned long res[4], const unsigned long in[4]);
-void ecp_nistz256_to_mont(unsigned long res[4], const unsigned long in[4])
-{
- static const unsigned long RR[] = { 0x0000000000000003U,
- 0xfffffffbffffffffU,
- 0xfffffffffffffffeU,
- 0x00000004fffffffdU };
-
- ecp_nistz256_mul_mont(res, in, RR);
-}
-
-void ecp_nistz256_from_mont(unsigned long res[4], const unsigned long in[4]);
-void ecp_nistz256_from_mont(unsigned long res[4], const unsigned long in[4])
-{
- static const unsigned long one[] = { 1, 0, 0, 0 };
-
- ecp_nistz256_mul_mont(res, in, one);
-}
-#endif
-
static sigjmp_buf ill_jmp;
static void ill_handler(int sig)
{
diff --git a/crypto/ppccpuid.pl b/crypto/ppccpuid.pl
index 2065cbb84b10..c6555df5d8e3 100755
--- a/crypto/ppccpuid.pl
+++ b/crypto/ppccpuid.pl
@@ -1,20 +1,24 @@
#! /usr/bin/env perl
# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
( $xlate="${dir}perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
+open STDOUT,"| $^X $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
if ($flavour=~/64/) {
$CMPLI="cmpldi";
diff --git a/crypto/property/README.md b/crypto/property/README.md
new file mode 100644
index 000000000000..9d97a6987305
--- /dev/null
+++ b/crypto/property/README.md
@@ -0,0 +1,94 @@
+Selecting algorithm implementations by properties
+=================================================
+
+Properties are associated with algorithms and are used to select between
+different implementations dynamically.
+
+This implementation is based on a number of assumptions:
+
+* Property definition is uncommon. I.e. providers will be loaded and
+ unloaded relatively infrequently, if at all.
+
+* The number of distinct property names will be small.
+
+* Providers will often give the same implementation properties to most or
+ all of their implemented algorithms. E.g. the FIPS property would be set
+ across an entire provider. Likewise for, hardware, accelerated, software,
+ HSM and, perhaps, constant_time.
+
+* There are a lot of algorithm implementations, therefore property
+ definitions should be space efficient. However...
+
+* ... property queries are very common. These must be fast.
+
+* Property queries come from a small set and are reused many times typically.
+ I.e. an application tends to use the same set of queries over and over,
+ rather than spanning a wide variety of queries.
+
+* Property queries can never add new property definitions.
+
+Some consequences of these assumptions are:
+
+* That definition is uncommon and queries are very common, we can treat
+ the property definitions as almost immutable. Specifically, a query can
+ never change the state of the definitions.
+
+* That definition is uncommon and needs to be space efficient, it will
+ be feasible to use a hash table to contain the names (and possibly also
+ values) of all properties and to reference these instead of duplicating
+ strings. Moreover, such a data structure need not be garbage collected.
+ By converting strings to integers using a structure such as this, string
+ comparison degenerates to integer comparison. Additionally, lists of
+ properties can be sorted by the string index which makes comparisons linear
+ time rather than quadratic time - the O(n log n) sort cost being amortised.
+
+* A cache for property definitions is also viable, if only implementation
+ properties are used and not algorithm properties, or at least these are
+ maintained separately. This cache would be a hash table, indexed by
+ the property definition string, and algorithms with the same properties
+ would share their definition structure. Again, reducing space use.
+
+* A query cache is desirable. This would be a hash table keyed by the
+ algorithm identifier and the entire query string and it would map to
+ the chosen algorithm. When a provider is loaded or unloaded, this cache
+ must be invalidated. The cache will also be invalidated when the global
+ properties are changed as doing so removes the need to index on both the
+ global and requested property strings.
+
+The implementation:
+
+* [property_lock.c](property_lock.c)
+ contains some wrapper functions to handle the global
+ lock more easily. The global lock is held for short periods of time with
+ per algorithm locking being used for longer intervals.
+
+* [property_string.c](property_string.c)
+ contains the string cache which converts property
+ names and values to small integer indices. Names and values are stored in
+ separate hash tables. The two Boolean values, the strings "yes" and "no",
+ are populated as the first two members of the value table. All property
+ names reserved by OpenSSL are also populated here. No functions are
+ provided to convert from an index back to the original string (this can be
+ done by maintaining parallel stacks of strings if required).
+
+* [property_parse.c](property_parse.c)
+ contains the property definition and query parsers.
+ These convert ASCII strings into lists of properties. The resulting
+ lists are sorted by the name index. Some additional utility functions
+ for dealing with property lists are also included: comparison of a query
+ against a definition and merging two queries into a single larger query.
+
+* [property.c](property.c)
+ contains the main APIs for defining and using properties.
+ Algorithms are discovered from their NID and a query string.
+ The results are cached.
+
+ The caching of query results has to be efficient but it must also be robust
+ against a denial of service attack. The cache cannot be permitted to grow
+ without bounds and must garbage collect under-used entries. The garbage
+ collection does not have to be exact.
+
+* [defn_cache.c](defn_cache.c)
+ contains a cache that maps property definition strings to
+ parsed properties. It is used by property.c to improve performance when
+ the same definition appears multiple times.
diff --git a/crypto/property/build.info b/crypto/property/build.info
new file mode 100644
index 000000000000..12a6b8c9de22
--- /dev/null
+++ b/crypto/property/build.info
@@ -0,0 +1,4 @@
+LIBS=../../libcrypto
+$COMMON=property_string.c property_parse.c property_query.c property.c defn_cache.c
+SOURCE[../../libcrypto]=$COMMON property_err.c
+SOURCE[../../providers/libfips.a]=$COMMON
diff --git a/crypto/property/defn_cache.c b/crypto/property/defn_cache.c
new file mode 100644
index 000000000000..b43f2d247ef6
--- /dev/null
+++ b/crypto/property/defn_cache.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/err.h>
+#include <openssl/lhash.h>
+#include "internal/propertyerr.h"
+#include "internal/property.h"
+#include "internal/core.h"
+#include "property_local.h"
+
+/*
+ * Implement a property definition cache.
+ * These functions assume that they are called under a write lock.
+ * No attempt is made to clean out the cache, except when it is shut down.
+ */
+
+typedef struct {
+ const char *prop;
+ OSSL_PROPERTY_LIST *defn;
+ char body[1];
+} PROPERTY_DEFN_ELEM;
+
+DEFINE_LHASH_OF(PROPERTY_DEFN_ELEM);
+
+static unsigned long property_defn_hash(const PROPERTY_DEFN_ELEM *a)
+{
+ return OPENSSL_LH_strhash(a->prop);
+}
+
+static int property_defn_cmp(const PROPERTY_DEFN_ELEM *a,
+ const PROPERTY_DEFN_ELEM *b)
+{
+ return strcmp(a->prop, b->prop);
+}
+
+static void property_defn_free(PROPERTY_DEFN_ELEM *elem)
+{
+ ossl_property_free(elem->defn);
+ OPENSSL_free(elem);
+}
+
+static void property_defns_free(void *vproperty_defns)
+{
+ LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns = vproperty_defns;
+
+ if (property_defns != NULL) {
+ lh_PROPERTY_DEFN_ELEM_doall(property_defns,
+ &property_defn_free);
+ lh_PROPERTY_DEFN_ELEM_free(property_defns);
+ }
+}
+
+static void *property_defns_new(OSSL_LIB_CTX *ctx) {
+ return lh_PROPERTY_DEFN_ELEM_new(&property_defn_hash, &property_defn_cmp);
+}
+
+static const OSSL_LIB_CTX_METHOD property_defns_method = {
+ OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
+ property_defns_new,
+ property_defns_free,
+};
+
+OSSL_PROPERTY_LIST *ossl_prop_defn_get(OSSL_LIB_CTX *ctx, const char *prop)
+{
+ PROPERTY_DEFN_ELEM elem, *r;
+ LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns;
+
+ property_defns = ossl_lib_ctx_get_data(ctx,
+ OSSL_LIB_CTX_PROPERTY_DEFN_INDEX,
+ &property_defns_method);
+ if (property_defns == NULL || !ossl_lib_ctx_read_lock(ctx))
+ return NULL;
+
+ elem.prop = prop;
+ r = lh_PROPERTY_DEFN_ELEM_retrieve(property_defns, &elem);
+ ossl_lib_ctx_unlock(ctx);
+ if (r == NULL || !ossl_assert(r->defn != NULL))
+ return NULL;
+ return r->defn;
+}
+
+/*
+ * Cache the property list for a given property string *pl.
+ * If an entry already exists in the cache *pl is freed and
+ * overwritten with the existing entry from the cache.
+ */
+int ossl_prop_defn_set(OSSL_LIB_CTX *ctx, const char *prop,
+ OSSL_PROPERTY_LIST **pl)
+{
+ PROPERTY_DEFN_ELEM elem, *old, *p = NULL;
+ size_t len;
+ LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns;
+ int res = 1;
+
+ property_defns = ossl_lib_ctx_get_data(ctx,
+ OSSL_LIB_CTX_PROPERTY_DEFN_INDEX,
+ &property_defns_method);
+ if (property_defns == NULL)
+ return 0;
+
+ if (prop == NULL)
+ return 1;
+
+ if (!ossl_lib_ctx_write_lock(ctx))
+ return 0;
+ elem.prop = prop;
+ if (pl == NULL) {
+ lh_PROPERTY_DEFN_ELEM_delete(property_defns, &elem);
+ goto end;
+ }
+ /* check if property definition is in the cache already */
+ if ((p = lh_PROPERTY_DEFN_ELEM_retrieve(property_defns, &elem)) != NULL) {
+ ossl_property_free(*pl);
+ *pl = p->defn;
+ goto end;
+ }
+ len = strlen(prop);
+ p = OPENSSL_malloc(sizeof(*p) + len);
+ if (p != NULL) {
+ p->prop = p->body;
+ p->defn = *pl;
+ memcpy(p->body, prop, len + 1);
+ old = lh_PROPERTY_DEFN_ELEM_insert(property_defns, p);
+ if (!ossl_assert(old == NULL))
+ /* This should not happen. An existing entry is handled above. */
+ goto end;
+ if (!lh_PROPERTY_DEFN_ELEM_error(property_defns))
+ goto end;
+ }
+ OPENSSL_free(p);
+ res = 0;
+ end:
+ ossl_lib_ctx_unlock(ctx);
+ return res;
+}
diff --git a/crypto/property/property.c b/crypto/property/property.c
new file mode 100644
index 000000000000..844c25cee936
--- /dev/null
+++ b/crypto/property/property.c
@@ -0,0 +1,769 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <openssl/crypto.h>
+#include "internal/core.h"
+#include "internal/property.h"
+#include "internal/provider.h"
+#include "internal/tsan_assist.h"
+#include "crypto/ctype.h"
+#include <openssl/lhash.h>
+#include <openssl/rand.h>
+#include "internal/thread_once.h"
+#include "crypto/lhash.h"
+#include "crypto/sparse_array.h"
+#include "property_local.h"
+
+/*
+ * The number of elements in the query cache before we initiate a flush.
+ * If reducing this, also ensure the stochastic test in test/property_test.c
+ * isn't likely to fail.
+ */
+#define IMPL_CACHE_FLUSH_THRESHOLD 500
+
+typedef struct {
+ void *method;
+ int (*up_ref)(void *);
+ void (*free)(void *);
+} METHOD;
+
+typedef struct {
+ const OSSL_PROVIDER *provider;
+ OSSL_PROPERTY_LIST *properties;
+ METHOD method;
+} IMPLEMENTATION;
+
+DEFINE_STACK_OF(IMPLEMENTATION)
+
+typedef struct {
+ const OSSL_PROVIDER *provider;
+ const char *query;
+ METHOD method;
+ char body[1];
+} QUERY;
+
+DEFINE_LHASH_OF(QUERY);
+
+typedef struct {
+ int nid;
+ STACK_OF(IMPLEMENTATION) *impls;
+ LHASH_OF(QUERY) *cache;
+} ALGORITHM;
+
+struct ossl_method_store_st {
+ OSSL_LIB_CTX *ctx;
+ SPARSE_ARRAY_OF(ALGORITHM) *algs;
+ /*
+ * Lock to protect the |algs| array from concurrent writing, when
+ * individual implementations or queries are inserted. This is used
+ * by the appropriate functions here.
+ */
+ CRYPTO_RWLOCK *lock;
+ /*
+ * Lock to reserve the whole store. This is used when fetching a set
+ * of algorithms, via these functions, found in crypto/core_fetch.c:
+ * ossl_method_construct_reserve_store()
+ * ossl_method_construct_unreserve_store()
+ */
+ CRYPTO_RWLOCK *biglock;
+
+ /* query cache specific values */
+
+ /* Count of the query cache entries for all algs */
+ size_t cache_nelem;
+
+ /* Flag: 1 if query cache entries for all algs need flushing */
+ int cache_need_flush;
+};
+
+typedef struct {
+ LHASH_OF(QUERY) *cache;
+ size_t nelem;
+ uint32_t seed;
+ unsigned char using_global_seed;
+} IMPL_CACHE_FLUSH;
+
+DEFINE_SPARSE_ARRAY_OF(ALGORITHM);
+
+typedef struct ossl_global_properties_st {
+ OSSL_PROPERTY_LIST *list;
+#ifndef FIPS_MODULE
+ unsigned int no_mirrored : 1;
+#endif
+} OSSL_GLOBAL_PROPERTIES;
+
+static void ossl_method_cache_flush_alg(OSSL_METHOD_STORE *store,
+ ALGORITHM *alg);
+static void ossl_method_cache_flush(OSSL_METHOD_STORE *store, int nid);
+
+/* Global properties are stored per library context */
+static void ossl_ctx_global_properties_free(void *vglobp)
+{
+ OSSL_GLOBAL_PROPERTIES *globp = vglobp;
+
+ if (globp != NULL) {
+ ossl_property_free(globp->list);
+ OPENSSL_free(globp);
+ }
+}
+
+static void *ossl_ctx_global_properties_new(OSSL_LIB_CTX *ctx)
+{
+ return OPENSSL_zalloc(sizeof(OSSL_GLOBAL_PROPERTIES));
+}
+
+static const OSSL_LIB_CTX_METHOD ossl_ctx_global_properties_method = {
+ OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
+ ossl_ctx_global_properties_new,
+ ossl_ctx_global_properties_free,
+};
+
+OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *libctx,
+ int loadconfig)
+{
+ OSSL_GLOBAL_PROPERTIES *globp;
+
+#ifndef FIPS_MODULE
+ if (loadconfig && !OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL))
+ return NULL;
+#endif
+ globp = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES,
+ &ossl_ctx_global_properties_method);
+
+ return globp != NULL ? &globp->list : NULL;
+}
+
+#ifndef FIPS_MODULE
+int ossl_global_properties_no_mirrored(OSSL_LIB_CTX *libctx)
+{
+ OSSL_GLOBAL_PROPERTIES *globp
+ = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES,
+ &ossl_ctx_global_properties_method);
+
+ return globp != NULL && globp->no_mirrored ? 1 : 0;
+}
+
+void ossl_global_properties_stop_mirroring(OSSL_LIB_CTX *libctx)
+{
+ OSSL_GLOBAL_PROPERTIES *globp
+ = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES,
+ &ossl_ctx_global_properties_method);
+
+ if (globp != NULL)
+ globp->no_mirrored = 1;
+}
+#endif
+
+static int ossl_method_up_ref(METHOD *method)
+{
+ return (*method->up_ref)(method->method);
+}
+
+static void ossl_method_free(METHOD *method)
+{
+ (*method->free)(method->method);
+}
+
+static __owur int ossl_property_read_lock(OSSL_METHOD_STORE *p)
+{
+ return p != NULL ? CRYPTO_THREAD_read_lock(p->lock) : 0;
+}
+
+static __owur int ossl_property_write_lock(OSSL_METHOD_STORE *p)
+{
+ return p != NULL ? CRYPTO_THREAD_write_lock(p->lock) : 0;
+}
+
+static int ossl_property_unlock(OSSL_METHOD_STORE *p)
+{
+ return p != 0 ? CRYPTO_THREAD_unlock(p->lock) : 0;
+}
+
+static unsigned long query_hash(const QUERY *a)
+{
+ return OPENSSL_LH_strhash(a->query);
+}
+
+static int query_cmp(const QUERY *a, const QUERY *b)
+{
+ int res = strcmp(a->query, b->query);
+
+ if (res == 0 && a->provider != NULL && b->provider != NULL)
+ res = b->provider > a->provider ? 1
+ : b->provider < a->provider ? -1
+ : 0;
+ return res;
+}
+
+static void impl_free(IMPLEMENTATION *impl)
+{
+ if (impl != NULL) {
+ ossl_method_free(&impl->method);
+ OPENSSL_free(impl);
+ }
+}
+
+static void impl_cache_free(QUERY *elem)
+{
+ if (elem != NULL) {
+ ossl_method_free(&elem->method);
+ OPENSSL_free(elem);
+ }
+}
+
+static void impl_cache_flush_alg(ossl_uintmax_t idx, ALGORITHM *alg)
+{
+ lh_QUERY_doall(alg->cache, &impl_cache_free);
+ lh_QUERY_flush(alg->cache);
+}
+
+static void alg_cleanup(ossl_uintmax_t idx, ALGORITHM *a, void *arg)
+{
+ OSSL_METHOD_STORE *store = arg;
+
+ if (a != NULL) {
+ sk_IMPLEMENTATION_pop_free(a->impls, &impl_free);
+ lh_QUERY_doall(a->cache, &impl_cache_free);
+ lh_QUERY_free(a->cache);
+ OPENSSL_free(a);
+ }
+ if (store != NULL)
+ ossl_sa_ALGORITHM_set(store->algs, idx, NULL);
+}
+
+/*
+ * The OSSL_LIB_CTX param here allows access to underlying property data needed
+ * for computation
+ */
+OSSL_METHOD_STORE *ossl_method_store_new(OSSL_LIB_CTX *ctx)
+{
+ OSSL_METHOD_STORE *res;
+
+ res = OPENSSL_zalloc(sizeof(*res));
+ if (res != NULL) {
+ res->ctx = ctx;
+ if ((res->algs = ossl_sa_ALGORITHM_new()) == NULL
+ || (res->lock = CRYPTO_THREAD_lock_new()) == NULL
+ || (res->biglock = CRYPTO_THREAD_lock_new()) == NULL) {
+ ossl_method_store_free(res);
+ return NULL;
+ }
+ }
+ return res;
+}
+
+void ossl_method_store_free(OSSL_METHOD_STORE *store)
+{
+ if (store != NULL) {
+ if (store->algs != NULL)
+ ossl_sa_ALGORITHM_doall_arg(store->algs, &alg_cleanup, store);
+ ossl_sa_ALGORITHM_free(store->algs);
+ CRYPTO_THREAD_lock_free(store->lock);
+ CRYPTO_THREAD_lock_free(store->biglock);
+ OPENSSL_free(store);
+ }
+}
+
+int ossl_method_lock_store(OSSL_METHOD_STORE *store)
+{
+ return store != NULL ? CRYPTO_THREAD_write_lock(store->biglock) : 0;
+}
+
+int ossl_method_unlock_store(OSSL_METHOD_STORE *store)
+{
+ return store != NULL ? CRYPTO_THREAD_unlock(store->biglock) : 0;
+}
+
+static ALGORITHM *ossl_method_store_retrieve(OSSL_METHOD_STORE *store, int nid)
+{
+ return ossl_sa_ALGORITHM_get(store->algs, nid);
+}
+
+static int ossl_method_store_insert(OSSL_METHOD_STORE *store, ALGORITHM *alg)
+{
+ return ossl_sa_ALGORITHM_set(store->algs, alg->nid, alg);
+}
+
+int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov,
+ int nid, const char *properties, void *method,
+ int (*method_up_ref)(void *),
+ void (*method_destruct)(void *))
+{
+ ALGORITHM *alg = NULL;
+ IMPLEMENTATION *impl;
+ int ret = 0;
+ int i;
+
+ if (nid <= 0 || method == NULL || store == NULL)
+ return 0;
+ if (properties == NULL)
+ properties = "";
+
+ if (!ossl_assert(prov != NULL))
+ return 0;
+
+ /* Create new entry */
+ impl = OPENSSL_malloc(sizeof(*impl));
+ if (impl == NULL)
+ return 0;
+ impl->method.method = method;
+ impl->method.up_ref = method_up_ref;
+ impl->method.free = method_destruct;
+ if (!ossl_method_up_ref(&impl->method)) {
+ OPENSSL_free(impl);
+ return 0;
+ }
+ impl->provider = prov;
+
+ /* Insert into the hash table if required */
+ if (!ossl_property_write_lock(store)) {
+ OPENSSL_free(impl);
+ return 0;
+ }
+ ossl_method_cache_flush(store, nid);
+ if ((impl->properties = ossl_prop_defn_get(store->ctx, properties)) == NULL) {
+ impl->properties = ossl_parse_property(store->ctx, properties);
+ if (impl->properties == NULL)
+ goto err;
+ if (!ossl_prop_defn_set(store->ctx, properties, &impl->properties)) {
+ ossl_property_free(impl->properties);
+ impl->properties = NULL;
+ goto err;
+ }
+ }
+
+ alg = ossl_method_store_retrieve(store, nid);
+ if (alg == NULL) {
+ if ((alg = OPENSSL_zalloc(sizeof(*alg))) == NULL
+ || (alg->impls = sk_IMPLEMENTATION_new_null()) == NULL
+ || (alg->cache = lh_QUERY_new(&query_hash, &query_cmp)) == NULL)
+ goto err;
+ alg->nid = nid;
+ if (!ossl_method_store_insert(store, alg))
+ goto err;
+ }
+
+ /* Push onto stack if there isn't one there already */
+ for (i = 0; i < sk_IMPLEMENTATION_num(alg->impls); i++) {
+ const IMPLEMENTATION *tmpimpl = sk_IMPLEMENTATION_value(alg->impls, i);
+
+ if (tmpimpl->provider == impl->provider
+ && tmpimpl->properties == impl->properties)
+ break;
+ }
+ if (i == sk_IMPLEMENTATION_num(alg->impls)
+ && sk_IMPLEMENTATION_push(alg->impls, impl))
+ ret = 1;
+ ossl_property_unlock(store);
+ if (ret == 0)
+ impl_free(impl);
+ return ret;
+
+err:
+ ossl_property_unlock(store);
+ alg_cleanup(0, alg, NULL);
+ impl_free(impl);
+ return 0;
+}
+
+int ossl_method_store_remove(OSSL_METHOD_STORE *store, int nid,
+ const void *method)
+{
+ ALGORITHM *alg = NULL;
+ int i;
+
+ if (nid <= 0 || method == NULL || store == NULL)
+ return 0;
+
+ if (!ossl_property_write_lock(store))
+ return 0;
+ ossl_method_cache_flush(store, nid);
+ alg = ossl_method_store_retrieve(store, nid);
+ if (alg == NULL) {
+ ossl_property_unlock(store);
+ return 0;
+ }
+
+ /*
+ * A sorting find then a delete could be faster but these stacks should be
+ * relatively small, so we avoid the overhead. Sorting could also surprise
+ * users when result orderings change (even though they are not guaranteed).
+ */
+ for (i = 0; i < sk_IMPLEMENTATION_num(alg->impls); i++) {
+ IMPLEMENTATION *impl = sk_IMPLEMENTATION_value(alg->impls, i);
+
+ if (impl->method.method == method) {
+ impl_free(impl);
+ (void)sk_IMPLEMENTATION_delete(alg->impls, i);
+ ossl_property_unlock(store);
+ return 1;
+ }
+ }
+ ossl_property_unlock(store);
+ return 0;
+}
+
+struct alg_cleanup_by_provider_data_st {
+ OSSL_METHOD_STORE *store;
+ const OSSL_PROVIDER *prov;
+};
+
+static void
+alg_cleanup_by_provider(ossl_uintmax_t idx, ALGORITHM *alg, void *arg)
+{
+ struct alg_cleanup_by_provider_data_st *data = arg;
+ int i, count;
+
+ /*
+ * We walk the stack backwards, to avoid having to deal with stack shifts
+ * caused by deletion
+ */
+ for (count = 0, i = sk_IMPLEMENTATION_num(alg->impls); i-- > 0;) {
+ IMPLEMENTATION *impl = sk_IMPLEMENTATION_value(alg->impls, i);
+
+ if (impl->provider == data->prov) {
+ impl_free(impl);
+ (void)sk_IMPLEMENTATION_delete(alg->impls, i);
+ count++;
+ }
+ }
+
+ /*
+ * If we removed any implementation, we also clear the whole associated
+ * cache, 'cause that's the sensible thing to do.
+ * There's no point flushing the cache entries where we didn't remove
+ * any implementation, though.
+ */
+ if (count > 0)
+ ossl_method_cache_flush_alg(data->store, alg);
+}
+
+int ossl_method_store_remove_all_provided(OSSL_METHOD_STORE *store,
+ const OSSL_PROVIDER *prov)
+{
+ struct alg_cleanup_by_provider_data_st data;
+
+ if (!ossl_property_write_lock(store))
+ return 0;
+ data.prov = prov;
+ data.store = store;
+ ossl_sa_ALGORITHM_doall_arg(store->algs, &alg_cleanup_by_provider, &data);
+ ossl_property_unlock(store);
+ return 1;
+}
+
+static void alg_do_one(ALGORITHM *alg, IMPLEMENTATION *impl,
+ void (*fn)(int id, void *method, void *fnarg),
+ void *fnarg)
+{
+ fn(alg->nid, impl->method.method, fnarg);
+}
+
+struct alg_do_each_data_st {
+ void (*fn)(int id, void *method, void *fnarg);
+ void *fnarg;
+};
+
+static void alg_do_each(ossl_uintmax_t idx, ALGORITHM *alg, void *arg)
+{
+ struct alg_do_each_data_st *data = arg;
+ int i, end = sk_IMPLEMENTATION_num(alg->impls);
+
+ for (i = 0; i < end; i++) {
+ IMPLEMENTATION *impl = sk_IMPLEMENTATION_value(alg->impls, i);
+
+ alg_do_one(alg, impl, data->fn, data->fnarg);
+ }
+}
+
+void ossl_method_store_do_all(OSSL_METHOD_STORE *store,
+ void (*fn)(int id, void *method, void *fnarg),
+ void *fnarg)
+{
+ struct alg_do_each_data_st data;
+
+ data.fn = fn;
+ data.fnarg = fnarg;
+ if (store != NULL)
+ ossl_sa_ALGORITHM_doall_arg(store->algs, alg_do_each, &data);
+}
+
+int ossl_method_store_fetch(OSSL_METHOD_STORE *store,
+ int nid, const char *prop_query,
+ const OSSL_PROVIDER **prov_rw, void **method)
+{
+ OSSL_PROPERTY_LIST **plp;
+ ALGORITHM *alg;
+ IMPLEMENTATION *impl, *best_impl = NULL;
+ OSSL_PROPERTY_LIST *pq = NULL, *p2 = NULL;
+ const OSSL_PROVIDER *prov = prov_rw != NULL ? *prov_rw : NULL;
+ int ret = 0;
+ int j, best = -1, score, optional;
+
+#ifndef FIPS_MODULE
+ if (!OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL))
+ return 0;
+#endif
+
+ if (nid <= 0 || method == NULL || store == NULL)
+ return 0;
+
+ /* This only needs to be a read lock, because the query won't create anything */
+ if (!ossl_property_read_lock(store))
+ return 0;
+ alg = ossl_method_store_retrieve(store, nid);
+ if (alg == NULL) {
+ ossl_property_unlock(store);
+ return 0;
+ }
+
+ if (prop_query != NULL)
+ p2 = pq = ossl_parse_query(store->ctx, prop_query, 0);
+ plp = ossl_ctx_global_properties(store->ctx, 0);
+ if (plp != NULL && *plp != NULL) {
+ if (pq == NULL) {
+ pq = *plp;
+ } else {
+ p2 = ossl_property_merge(pq, *plp);
+ ossl_property_free(pq);
+ if (p2 == NULL)
+ goto fin;
+ pq = p2;
+ }
+ }
+
+ if (pq == NULL) {
+ for (j = 0; j < sk_IMPLEMENTATION_num(alg->impls); j++) {
+ if ((impl = sk_IMPLEMENTATION_value(alg->impls, j)) != NULL
+ && (prov == NULL || impl->provider == prov)) {
+ best_impl = impl;
+ ret = 1;
+ break;
+ }
+ }
+ goto fin;
+ }
+ optional = ossl_property_has_optional(pq);
+ for (j = 0; j < sk_IMPLEMENTATION_num(alg->impls); j++) {
+ if ((impl = sk_IMPLEMENTATION_value(alg->impls, j)) != NULL
+ && (prov == NULL || impl->provider == prov)) {
+ score = ossl_property_match_count(pq, impl->properties);
+ if (score > best) {
+ best_impl = impl;
+ best = score;
+ ret = 1;
+ if (!optional)
+ goto fin;
+ }
+ }
+ }
+fin:
+ if (ret && ossl_method_up_ref(&best_impl->method)) {
+ *method = best_impl->method.method;
+ if (prov_rw != NULL)
+ *prov_rw = best_impl->provider;
+ } else {
+ ret = 0;
+ }
+ ossl_property_unlock(store);
+ ossl_property_free(p2);
+ return ret;
+}
+
+static void ossl_method_cache_flush_alg(OSSL_METHOD_STORE *store,
+ ALGORITHM *alg)
+{
+ store->cache_nelem -= lh_QUERY_num_items(alg->cache);
+ impl_cache_flush_alg(0, alg);
+}
+
+static void ossl_method_cache_flush(OSSL_METHOD_STORE *store, int nid)
+{
+ ALGORITHM *alg = ossl_method_store_retrieve(store, nid);
+
+ if (alg != NULL)
+ ossl_method_cache_flush_alg(store, alg);
+}
+
+int ossl_method_store_cache_flush_all(OSSL_METHOD_STORE *store)
+{
+ if (!ossl_property_write_lock(store))
+ return 0;
+ ossl_sa_ALGORITHM_doall(store->algs, &impl_cache_flush_alg);
+ store->cache_nelem = 0;
+ ossl_property_unlock(store);
+ return 1;
+}
+
+IMPLEMENT_LHASH_DOALL_ARG(QUERY, IMPL_CACHE_FLUSH);
+
+/*
+ * Flush an element from the query cache (perhaps).
+ *
+ * In order to avoid taking a write lock or using atomic operations
+ * to keep accurate least recently used (LRU) or least frequently used
+ * (LFU) information, the procedure used here is to stochastically
+ * flush approximately half the cache.
+ *
+ * This procedure isn't ideal, LRU or LFU would be better. However,
+ * in normal operation, reaching a full cache would be unexpected.
+ * It means that no steady state of algorithm queries has been reached.
+ * That is, it is most likely an attack of some form. A suboptimal clearance
+ * strategy that doesn't degrade performance of the normal case is
+ * preferable to a more refined approach that imposes a performance
+ * impact.
+ */
+static void impl_cache_flush_cache(QUERY *c, IMPL_CACHE_FLUSH *state)
+{
+ uint32_t n;
+
+ /*
+ * Implement the 32 bit xorshift as suggested by George Marsaglia in:
+ * https://doi.org/10.18637/jss.v008.i14
+ *
+ * This is a very fast PRNG so there is no need to extract bits one at a
+ * time and use the entire value each time.
+ */
+ n = state->seed;
+ n ^= n << 13;
+ n ^= n >> 17;
+ n ^= n << 5;
+ state->seed = n;
+
+ if ((n & 1) != 0)
+ impl_cache_free(lh_QUERY_delete(state->cache, c));
+ else
+ state->nelem++;
+}
+
+static void impl_cache_flush_one_alg(ossl_uintmax_t idx, ALGORITHM *alg,
+ void *v)
+{
+ IMPL_CACHE_FLUSH *state = (IMPL_CACHE_FLUSH *)v;
+
+ state->cache = alg->cache;
+ lh_QUERY_doall_IMPL_CACHE_FLUSH(state->cache, &impl_cache_flush_cache,
+ state);
+}
+
+static void ossl_method_cache_flush_some(OSSL_METHOD_STORE *store)
+{
+ IMPL_CACHE_FLUSH state;
+ static TSAN_QUALIFIER uint32_t global_seed = 1;
+
+ state.nelem = 0;
+ state.using_global_seed = 0;
+ if ((state.seed = OPENSSL_rdtsc()) == 0) {
+ /* If there is no timer available, seed another way */
+ state.using_global_seed = 1;
+ state.seed = tsan_load(&global_seed);
+ }
+ store->cache_need_flush = 0;
+ ossl_sa_ALGORITHM_doall_arg(store->algs, &impl_cache_flush_one_alg, &state);
+ store->cache_nelem = state.nelem;
+ /* Without a timer, update the global seed */
+ if (state.using_global_seed)
+ tsan_store(&global_seed, state.seed);
+}
+
+int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
+ int nid, const char *prop_query, void **method)
+{
+ ALGORITHM *alg;
+ QUERY elem, *r;
+ int res = 0;
+
+ if (nid <= 0 || store == NULL || prop_query == NULL)
+ return 0;
+
+ if (!ossl_property_read_lock(store))
+ return 0;
+ alg = ossl_method_store_retrieve(store, nid);
+ if (alg == NULL)
+ goto err;
+
+ elem.query = prop_query;
+ elem.provider = prov;
+ r = lh_QUERY_retrieve(alg->cache, &elem);
+ if (r == NULL)
+ goto err;
+ if (ossl_method_up_ref(&r->method)) {
+ *method = r->method.method;
+ res = 1;
+ }
+err:
+ ossl_property_unlock(store);
+ return res;
+}
+
+int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
+ int nid, const char *prop_query, void *method,
+ int (*method_up_ref)(void *),
+ void (*method_destruct)(void *))
+{
+ QUERY elem, *old, *p = NULL;
+ ALGORITHM *alg;
+ size_t len;
+ int res = 1;
+
+ if (nid <= 0 || store == NULL || prop_query == NULL)
+ return 0;
+
+ if (!ossl_assert(prov != NULL))
+ return 0;
+
+ if (!ossl_property_write_lock(store))
+ return 0;
+ if (store->cache_need_flush)
+ ossl_method_cache_flush_some(store);
+ alg = ossl_method_store_retrieve(store, nid);
+ if (alg == NULL)
+ goto err;
+
+ if (method == NULL) {
+ elem.query = prop_query;
+ elem.provider = prov;
+ if ((old = lh_QUERY_delete(alg->cache, &elem)) != NULL) {
+ impl_cache_free(old);
+ store->cache_nelem--;
+ }
+ goto end;
+ }
+ p = OPENSSL_malloc(sizeof(*p) + (len = strlen(prop_query)));
+ if (p != NULL) {
+ p->query = p->body;
+ p->provider = prov;
+ p->method.method = method;
+ p->method.up_ref = method_up_ref;
+ p->method.free = method_destruct;
+ if (!ossl_method_up_ref(&p->method))
+ goto err;
+ memcpy((char *)p->query, prop_query, len + 1);
+ if ((old = lh_QUERY_insert(alg->cache, p)) != NULL) {
+ impl_cache_free(old);
+ goto end;
+ }
+ if (!lh_QUERY_error(alg->cache)) {
+ if (++store->cache_nelem >= IMPL_CACHE_FLUSH_THRESHOLD)
+ store->cache_need_flush = 1;
+ goto end;
+ }
+ ossl_method_free(&p->method);
+ }
+err:
+ res = 0;
+ OPENSSL_free(p);
+end:
+ ossl_property_unlock(store);
+ return res;
+}
diff --git a/crypto/property/property_err.c b/crypto/property/property_err.c
new file mode 100644
index 000000000000..9a25d602282e
--- /dev/null
+++ b/crypto/property/property_err.c
@@ -0,0 +1,46 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include "internal/propertyerr.h"
+
+#ifndef OPENSSL_NO_ERR
+
+static const ERR_STRING_DATA PROP_str_reasons[] = {
+ {ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NAME_TOO_LONG), "name too long"},
+ {ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NOT_AN_ASCII_CHARACTER),
+ "not an ascii character"},
+ {ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NOT_AN_HEXADECIMAL_DIGIT),
+ "not an hexadecimal digit"},
+ {ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NOT_AN_IDENTIFIER), "not an identifier"},
+ {ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NOT_AN_OCTAL_DIGIT),
+ "not an octal digit"},
+ {ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NOT_A_DECIMAL_DIGIT),
+ "not a decimal digit"},
+ {ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NO_MATCHING_STRING_DELIMITER),
+ "no matching string delimiter"},
+ {ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NO_VALUE), "no value"},
+ {ERR_PACK(ERR_LIB_PROP, 0, PROP_R_PARSE_FAILED), "parse failed"},
+ {ERR_PACK(ERR_LIB_PROP, 0, PROP_R_STRING_TOO_LONG), "string too long"},
+ {ERR_PACK(ERR_LIB_PROP, 0, PROP_R_TRAILING_CHARACTERS),
+ "trailing characters"},
+ {0, NULL}
+};
+
+#endif
+
+int ossl_err_load_PROP_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(PROP_str_reasons[0].error) == NULL)
+ ERR_load_strings_const(PROP_str_reasons);
+#endif
+ return 1;
+}
diff --git a/crypto/property/property_local.h b/crypto/property/property_local.h
new file mode 100644
index 000000000000..797fb3bf5f2b
--- /dev/null
+++ b/crypto/property/property_local.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include "internal/property.h"
+
+typedef int OSSL_PROPERTY_IDX;
+
+typedef enum {
+ OSSL_PROPERTY_OPER_EQ, OSSL_PROPERTY_OPER_NE, OSSL_PROPERTY_OVERRIDE
+} OSSL_PROPERTY_OPER;
+
+struct ossl_property_definition_st {
+ OSSL_PROPERTY_IDX name_idx;
+ OSSL_PROPERTY_TYPE type;
+ OSSL_PROPERTY_OPER oper;
+ unsigned int optional : 1;
+ union {
+ int64_t int_val; /* Signed integer */
+ OSSL_PROPERTY_IDX str_val; /* String */
+ } v;
+};
+
+struct ossl_property_list_st {
+ int num_properties;
+ unsigned int has_optional : 1;
+ OSSL_PROPERTY_DEFINITION properties[1];
+};
+
+#define OSSL_PROPERTY_TRUE 1
+#define OSSL_PROPERTY_FALSE 2
+
+/* Property string functions */
+OSSL_PROPERTY_IDX ossl_property_name(OSSL_LIB_CTX *ctx, const char *s,
+ int create);
+const char *ossl_property_name_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx);
+OSSL_PROPERTY_IDX ossl_property_value(OSSL_LIB_CTX *ctx, const char *s,
+ int create);
+const char *ossl_property_value_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx);
+
+/* Property list functions */
+void ossl_property_free(OSSL_PROPERTY_LIST *p);
+int ossl_property_has_optional(const OSSL_PROPERTY_LIST *query);
+
+/* Property definition cache functions */
+OSSL_PROPERTY_LIST *ossl_prop_defn_get(OSSL_LIB_CTX *ctx, const char *prop);
+int ossl_prop_defn_set(OSSL_LIB_CTX *ctx, const char *prop,
+ OSSL_PROPERTY_LIST **pl);
diff --git a/crypto/property/property_parse.c b/crypto/property/property_parse.c
new file mode 100644
index 000000000000..ca2bd33381bf
--- /dev/null
+++ b/crypto/property/property_parse.c
@@ -0,0 +1,706 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <openssl/err.h>
+#include "internal/propertyerr.h"
+#include "internal/property.h"
+#include "crypto/ctype.h"
+#include "internal/nelem.h"
+#include "property_local.h"
+#include "e_os.h"
+
+DEFINE_STACK_OF(OSSL_PROPERTY_DEFINITION)
+
+static const char *skip_space(const char *s)
+{
+ while (ossl_isspace(*s))
+ s++;
+ return s;
+}
+
+static int match_ch(const char *t[], char m)
+{
+ const char *s = *t;
+
+ if (*s == m) {
+ *t = skip_space(s + 1);
+ return 1;
+ }
+ return 0;
+}
+
+#define MATCH(s, m) match(s, m, sizeof(m) - 1)
+
+static int match(const char *t[], const char m[], size_t m_len)
+{
+ const char *s = *t;
+
+ if (OPENSSL_strncasecmp(s, m, m_len) == 0) {
+ *t = skip_space(s + m_len);
+ return 1;
+ }
+ return 0;
+}
+
+static int parse_name(OSSL_LIB_CTX *ctx, const char *t[], int create,
+ OSSL_PROPERTY_IDX *idx)
+{
+ char name[100];
+ int err = 0;
+ size_t i = 0;
+ const char *s = *t;
+ int user_name = 0;
+
+ for (;;) {
+ if (!ossl_isalpha(*s)) {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_IDENTIFIER,
+ "HERE-->%s", *t);
+ return 0;
+ }
+ do {
+ if (i < sizeof(name) - 1)
+ name[i++] = ossl_tolower(*s);
+ else
+ err = 1;
+ } while (*++s == '_' || ossl_isalnum(*s));
+ if (*s != '.')
+ break;
+ user_name = 1;
+ if (i < sizeof(name) - 1)
+ name[i++] = *s;
+ else
+ err = 1;
+ s++;
+ }
+ name[i] = '\0';
+ if (err) {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NAME_TOO_LONG, "HERE-->%s", *t);
+ return 0;
+ }
+ *t = skip_space(s);
+ *idx = ossl_property_name(ctx, name, user_name && create);
+ return 1;
+}
+
+static int parse_number(const char *t[], OSSL_PROPERTY_DEFINITION *res)
+{
+ const char *s = *t;
+ int64_t v = 0;
+
+ if (!ossl_isdigit(*s))
+ return 0;
+ do {
+ v = v * 10 + (*s++ - '0');
+ } while (ossl_isdigit(*s));
+ if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_A_DECIMAL_DIGIT,
+ "HERE-->%s", *t);
+ return 0;
+ }
+ *t = skip_space(s);
+ res->type = OSSL_PROPERTY_TYPE_NUMBER;
+ res->v.int_val = v;
+ return 1;
+}
+
+static int parse_hex(const char *t[], OSSL_PROPERTY_DEFINITION *res)
+{
+ const char *s = *t;
+ int64_t v = 0;
+
+ if (!ossl_isxdigit(*s))
+ return 0;
+ do {
+ v <<= 4;
+ if (ossl_isdigit(*s))
+ v += *s - '0';
+ else
+ v += ossl_tolower(*s) - 'a';
+ } while (ossl_isxdigit(*++s));
+ if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_HEXADECIMAL_DIGIT,
+ "HERE-->%s", *t);
+ return 0;
+ }
+ *t = skip_space(s);
+ res->type = OSSL_PROPERTY_TYPE_NUMBER;
+ res->v.int_val = v;
+ return 1;
+}
+
+static int parse_oct(const char *t[], OSSL_PROPERTY_DEFINITION *res)
+{
+ const char *s = *t;
+ int64_t v = 0;
+
+ if (*s == '9' || *s == '8' || !ossl_isdigit(*s))
+ return 0;
+ do {
+ v = (v << 3) + (*s - '0');
+ } while (ossl_isdigit(*++s) && *s != '9' && *s != '8');
+ if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_OCTAL_DIGIT,
+ "HERE-->%s", *t);
+ return 0;
+ }
+ *t = skip_space(s);
+ res->type = OSSL_PROPERTY_TYPE_NUMBER;
+ res->v.int_val = v;
+ return 1;
+}
+
+static int parse_string(OSSL_LIB_CTX *ctx, const char *t[], char delim,
+ OSSL_PROPERTY_DEFINITION *res, const int create)
+{
+ char v[1000];
+ const char *s = *t;
+ size_t i = 0;
+ int err = 0;
+
+ while (*s != '\0' && *s != delim) {
+ if (i < sizeof(v) - 1)
+ v[i++] = *s;
+ else
+ err = 1;
+ s++;
+ }
+ if (*s == '\0') {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NO_MATCHING_STRING_DELIMITER,
+ "HERE-->%c%s", delim, *t);
+ return 0;
+ }
+ v[i] = '\0';
+ if (err) {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_STRING_TOO_LONG, "HERE-->%s", *t);
+ } else {
+ res->v.str_val = ossl_property_value(ctx, v, create);
+ }
+ *t = skip_space(s + 1);
+ res->type = OSSL_PROPERTY_TYPE_STRING;
+ return !err;
+}
+
+static int parse_unquoted(OSSL_LIB_CTX *ctx, const char *t[],
+ OSSL_PROPERTY_DEFINITION *res, const int create)
+{
+ char v[1000];
+ const char *s = *t;
+ size_t i = 0;
+ int err = 0;
+
+ if (*s == '\0' || *s == ',')
+ return 0;
+ while (ossl_isprint(*s) && !ossl_isspace(*s) && *s != ',') {
+ if (i < sizeof(v) - 1)
+ v[i++] = ossl_tolower(*s);
+ else
+ err = 1;
+ s++;
+ }
+ if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_ASCII_CHARACTER,
+ "HERE-->%s", s);
+ return 0;
+ }
+ v[i] = 0;
+ if (err)
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_STRING_TOO_LONG, "HERE-->%s", *t);
+ else if ((res->v.str_val = ossl_property_value(ctx, v, create)) == 0)
+ err = 1;
+ *t = skip_space(s);
+ res->type = OSSL_PROPERTY_TYPE_STRING;
+ return !err;
+}
+
+static int parse_value(OSSL_LIB_CTX *ctx, const char *t[],
+ OSSL_PROPERTY_DEFINITION *res, int create)
+{
+ const char *s = *t;
+ int r = 0;
+
+ if (*s == '"' || *s == '\'') {
+ s++;
+ r = parse_string(ctx, &s, s[-1], res, create);
+ } else if (*s == '+') {
+ s++;
+ r = parse_number(&s, res);
+ } else if (*s == '-') {
+ s++;
+ r = parse_number(&s, res);
+ res->v.int_val = -res->v.int_val;
+ } else if (*s == '0' && s[1] == 'x') {
+ s += 2;
+ r = parse_hex(&s, res);
+ } else if (*s == '0' && ossl_isdigit(s[1])) {
+ s++;
+ r = parse_oct(&s, res);
+ } else if (ossl_isdigit(*s)) {
+ return parse_number(t, res);
+ } else if (ossl_isalpha(*s))
+ return parse_unquoted(ctx, t, res, create);
+ if (r)
+ *t = s;
+ return r;
+}
+
+static int pd_compare(const OSSL_PROPERTY_DEFINITION *const *p1,
+ const OSSL_PROPERTY_DEFINITION *const *p2)
+{
+ const OSSL_PROPERTY_DEFINITION *pd1 = *p1;
+ const OSSL_PROPERTY_DEFINITION *pd2 = *p2;
+
+ if (pd1->name_idx < pd2->name_idx)
+ return -1;
+ if (pd1->name_idx > pd2->name_idx)
+ return 1;
+ return 0;
+}
+
+static void pd_free(OSSL_PROPERTY_DEFINITION *pd)
+{
+ OPENSSL_free(pd);
+}
+
+/*
+ * Convert a stack of property definitions and queries into a fixed array.
+ * The items are sorted for efficient query. The stack is not freed.
+ * This function also checks for duplicated names and returns an error if
+ * any exist.
+ */
+static OSSL_PROPERTY_LIST *
+stack_to_property_list(OSSL_LIB_CTX *ctx,
+ STACK_OF(OSSL_PROPERTY_DEFINITION) *sk)
+{
+ const int n = sk_OSSL_PROPERTY_DEFINITION_num(sk);
+ OSSL_PROPERTY_LIST *r;
+ OSSL_PROPERTY_IDX prev_name_idx = 0;
+ int i;
+
+ r = OPENSSL_malloc(sizeof(*r)
+ + (n <= 0 ? 0 : n - 1) * sizeof(r->properties[0]));
+ if (r != NULL) {
+ sk_OSSL_PROPERTY_DEFINITION_sort(sk);
+
+ r->has_optional = 0;
+ for (i = 0; i < n; i++) {
+ r->properties[i] = *sk_OSSL_PROPERTY_DEFINITION_value(sk, i);
+ r->has_optional |= r->properties[i].optional;
+
+ /* Check for duplicated names */
+ if (i > 0 && r->properties[i].name_idx == prev_name_idx) {
+ OPENSSL_free(r);
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_PARSE_FAILED,
+ "Duplicated name `%s'",
+ ossl_property_name_str(ctx, prev_name_idx));
+ return NULL;
+ }
+ prev_name_idx = r->properties[i].name_idx;
+ }
+ r->num_properties = n;
+ }
+ return r;
+}
+
+OSSL_PROPERTY_LIST *ossl_parse_property(OSSL_LIB_CTX *ctx, const char *defn)
+{
+ OSSL_PROPERTY_DEFINITION *prop = NULL;
+ OSSL_PROPERTY_LIST *res = NULL;
+ STACK_OF(OSSL_PROPERTY_DEFINITION) *sk;
+ const char *s = defn;
+ int done;
+
+ if (s == NULL || (sk = sk_OSSL_PROPERTY_DEFINITION_new(&pd_compare)) == NULL)
+ return NULL;
+
+ s = skip_space(s);
+ done = *s == '\0';
+ while (!done) {
+ const char *start = s;
+
+ prop = OPENSSL_malloc(sizeof(*prop));
+ if (prop == NULL)
+ goto err;
+ memset(&prop->v, 0, sizeof(prop->v));
+ prop->optional = 0;
+ if (!parse_name(ctx, &s, 1, &prop->name_idx))
+ goto err;
+ prop->oper = OSSL_PROPERTY_OPER_EQ;
+ if (prop->name_idx == 0) {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_PARSE_FAILED,
+ "Unknown name HERE-->%s", start);
+ goto err;
+ }
+ if (match_ch(&s, '=')) {
+ if (!parse_value(ctx, &s, prop, 1)) {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NO_VALUE,
+ "HERE-->%s", start);
+ goto err;
+ }
+ } else {
+ /* A name alone means a true Boolean */
+ prop->type = OSSL_PROPERTY_TYPE_STRING;
+ prop->v.str_val = OSSL_PROPERTY_TRUE;
+ }
+
+ if (!sk_OSSL_PROPERTY_DEFINITION_push(sk, prop))
+ goto err;
+ prop = NULL;
+ done = !match_ch(&s, ',');
+ }
+ if (*s != '\0') {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_TRAILING_CHARACTERS,
+ "HERE-->%s", s);
+ goto err;
+ }
+ res = stack_to_property_list(ctx, sk);
+
+err:
+ OPENSSL_free(prop);
+ sk_OSSL_PROPERTY_DEFINITION_pop_free(sk, &pd_free);
+ return res;
+}
+
+OSSL_PROPERTY_LIST *ossl_parse_query(OSSL_LIB_CTX *ctx, const char *s,
+ int create_values)
+{
+ STACK_OF(OSSL_PROPERTY_DEFINITION) *sk;
+ OSSL_PROPERTY_LIST *res = NULL;
+ OSSL_PROPERTY_DEFINITION *prop = NULL;
+ int done;
+
+ if (s == NULL || (sk = sk_OSSL_PROPERTY_DEFINITION_new(&pd_compare)) == NULL)
+ return NULL;
+
+ s = skip_space(s);
+ done = *s == '\0';
+ while (!done) {
+ prop = OPENSSL_malloc(sizeof(*prop));
+ if (prop == NULL)
+ goto err;
+ memset(&prop->v, 0, sizeof(prop->v));
+
+ if (match_ch(&s, '-')) {
+ prop->oper = OSSL_PROPERTY_OVERRIDE;
+ prop->optional = 0;
+ if (!parse_name(ctx, &s, 1, &prop->name_idx))
+ goto err;
+ goto skip_value;
+ }
+ prop->optional = match_ch(&s, '?');
+ if (!parse_name(ctx, &s, 1, &prop->name_idx))
+ goto err;
+
+ if (match_ch(&s, '=')) {
+ prop->oper = OSSL_PROPERTY_OPER_EQ;
+ } else if (MATCH(&s, "!=")) {
+ prop->oper = OSSL_PROPERTY_OPER_NE;
+ } else {
+ /* A name alone is a Boolean comparison for true */
+ prop->oper = OSSL_PROPERTY_OPER_EQ;
+ prop->type = OSSL_PROPERTY_TYPE_STRING;
+ prop->v.str_val = OSSL_PROPERTY_TRUE;
+ goto skip_value;
+ }
+ if (!parse_value(ctx, &s, prop, create_values))
+ prop->type = OSSL_PROPERTY_TYPE_VALUE_UNDEFINED;
+
+skip_value:
+ if (!sk_OSSL_PROPERTY_DEFINITION_push(sk, prop))
+ goto err;
+ prop = NULL;
+ done = !match_ch(&s, ',');
+ }
+ if (*s != '\0') {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_TRAILING_CHARACTERS,
+ "HERE-->%s", s);
+ goto err;
+ }
+ res = stack_to_property_list(ctx, sk);
+
+err:
+ OPENSSL_free(prop);
+ sk_OSSL_PROPERTY_DEFINITION_pop_free(sk, &pd_free);
+ return res;
+}
+
+/*
+ * Compare a query against a definition.
+ * Return the number of clauses matched or -1 if a mandatory clause is false.
+ */
+int ossl_property_match_count(const OSSL_PROPERTY_LIST *query,
+ const OSSL_PROPERTY_LIST *defn)
+{
+ const OSSL_PROPERTY_DEFINITION *const q = query->properties;
+ const OSSL_PROPERTY_DEFINITION *const d = defn->properties;
+ int i = 0, j = 0, matches = 0;
+ OSSL_PROPERTY_OPER oper;
+
+ while (i < query->num_properties) {
+ if ((oper = q[i].oper) == OSSL_PROPERTY_OVERRIDE) {
+ i++;
+ continue;
+ }
+ if (j < defn->num_properties) {
+ if (q[i].name_idx > d[j].name_idx) { /* skip defn, not in query */
+ j++;
+ continue;
+ }
+ if (q[i].name_idx == d[j].name_idx) { /* both in defn and query */
+ const int eq = q[i].type == d[j].type
+ && memcmp(&q[i].v, &d[j].v, sizeof(q[i].v)) == 0;
+
+ if ((eq && oper == OSSL_PROPERTY_OPER_EQ)
+ || (!eq && oper == OSSL_PROPERTY_OPER_NE))
+ matches++;
+ else if (!q[i].optional)
+ return -1;
+ i++;
+ j++;
+ continue;
+ }
+ }
+
+ /*
+ * Handle the cases of a missing value and a query with no corresponding
+ * definition. The former fails for any comparison except inequality,
+ * the latter is treated as a comparison against the Boolean false.
+ */
+ if (q[i].type == OSSL_PROPERTY_TYPE_VALUE_UNDEFINED) {
+ if (oper == OSSL_PROPERTY_OPER_NE)
+ matches++;
+ else if (!q[i].optional)
+ return -1;
+ } else if (q[i].type != OSSL_PROPERTY_TYPE_STRING
+ || (oper == OSSL_PROPERTY_OPER_EQ
+ && q[i].v.str_val != OSSL_PROPERTY_FALSE)
+ || (oper == OSSL_PROPERTY_OPER_NE
+ && q[i].v.str_val == OSSL_PROPERTY_FALSE)) {
+ if (!q[i].optional)
+ return -1;
+ } else {
+ matches++;
+ }
+ i++;
+ }
+ return matches;
+}
+
+void ossl_property_free(OSSL_PROPERTY_LIST *p)
+{
+ OPENSSL_free(p);
+}
+
+/*
+ * Merge two property lists.
+ * If there is a common name, the one from the first list is used.
+ */
+OSSL_PROPERTY_LIST *ossl_property_merge(const OSSL_PROPERTY_LIST *a,
+ const OSSL_PROPERTY_LIST *b)
+{
+ const OSSL_PROPERTY_DEFINITION *const ap = a->properties;
+ const OSSL_PROPERTY_DEFINITION *const bp = b->properties;
+ const OSSL_PROPERTY_DEFINITION *copy;
+ OSSL_PROPERTY_LIST *r;
+ int i, j, n;
+ const int t = a->num_properties + b->num_properties;
+
+ r = OPENSSL_malloc(sizeof(*r)
+ + (t == 0 ? 0 : t - 1) * sizeof(r->properties[0]));
+ if (r == NULL)
+ return NULL;
+
+ r->has_optional = 0;
+ for (i = j = n = 0; i < a->num_properties || j < b->num_properties; n++) {
+ if (i >= a->num_properties) {
+ copy = &bp[j++];
+ } else if (j >= b->num_properties) {
+ copy = &ap[i++];
+ } else if (ap[i].name_idx <= bp[j].name_idx) {
+ if (ap[i].name_idx == bp[j].name_idx)
+ j++;
+ copy = &ap[i++];
+ } else {
+ copy = &bp[j++];
+ }
+ memcpy(r->properties + n, copy, sizeof(r->properties[0]));
+ r->has_optional |= copy->optional;
+ }
+ r->num_properties = n;
+ if (n != t)
+ r = OPENSSL_realloc(r, sizeof(*r) + (n - 1) * sizeof(r->properties[0]));
+ return r;
+}
+
+int ossl_property_parse_init(OSSL_LIB_CTX *ctx)
+{
+ static const char *const predefined_names[] = {
+ "provider", /* Name of provider (default, legacy, fips) */
+ "version", /* Version number of this provider */
+ "fips", /* FIPS validated or FIPS supporting algorithm */
+ "output", /* Output type for encoders */
+ "input", /* Input type for decoders */
+ "structure", /* Structure name for encoders and decoders */
+ };
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(predefined_names); i++)
+ if (ossl_property_name(ctx, predefined_names[i], 1) == 0)
+ goto err;
+
+ /*
+ * Pre-populate the two Boolean values. We must do them before any other
+ * values and in this order so that we get the same index as the global
+ * OSSL_PROPERTY_TRUE and OSSL_PROPERTY_FALSE values
+ */
+ if ((ossl_property_value(ctx, "yes", 1) != OSSL_PROPERTY_TRUE)
+ || (ossl_property_value(ctx, "no", 1) != OSSL_PROPERTY_FALSE))
+ goto err;
+
+ return 1;
+err:
+ return 0;
+}
+
+static void put_char(char ch, char **buf, size_t *remain, size_t *needed)
+{
+ if (*remain == 0) {
+ ++*needed;
+ return;
+ }
+ if (*remain == 1)
+ **buf = '\0';
+ else
+ **buf = ch;
+ ++*buf;
+ ++*needed;
+ --*remain;
+}
+
+static void put_str(const char *str, char **buf, size_t *remain, size_t *needed)
+{
+ size_t olen, len;
+
+ len = olen = strlen(str);
+ *needed += len;
+
+ if (*remain == 0)
+ return;
+
+ if (*remain < len + 1)
+ len = *remain - 1;
+
+ if (len > 0) {
+ memcpy(*buf, str, len);
+ *buf += len;
+ *remain -= len;
+ }
+
+ if (len < olen && *remain == 1) {
+ **buf = '\0';
+ ++*buf;
+ --*remain;
+ }
+}
+
+static void put_num(int64_t val, char **buf, size_t *remain, size_t *needed)
+{
+ int64_t tmpval = val;
+ size_t len = 1;
+
+ if (tmpval < 0) {
+ len++;
+ tmpval = -tmpval;
+ }
+ for (; tmpval > 9; len++, tmpval /= 10);
+
+ *needed += len;
+
+ if (*remain == 0)
+ return;
+
+ BIO_snprintf(*buf, *remain, "%lld", (long long int)val);
+ if (*remain < len) {
+ *buf += *remain;
+ *remain = 0;
+ } else {
+ *buf += len;
+ *remain -= len;
+ }
+}
+
+size_t ossl_property_list_to_string(OSSL_LIB_CTX *ctx,
+ const OSSL_PROPERTY_LIST *list, char *buf,
+ size_t bufsize)
+{
+ int i;
+ const OSSL_PROPERTY_DEFINITION *prop = NULL;
+ size_t needed = 0;
+ const char *val;
+
+ if (list == NULL) {
+ if (bufsize > 0)
+ *buf = '\0';
+ return 1;
+ }
+ if (list->num_properties != 0)
+ prop = &list->properties[list->num_properties - 1];
+ for (i = 0; i < list->num_properties; i++, prop--) {
+ /* Skip invalid names */
+ if (prop->name_idx == 0)
+ continue;
+
+ if (needed > 0)
+ put_char(',', &buf, &bufsize, &needed);
+
+ if (prop->optional)
+ put_char('?', &buf, &bufsize, &needed);
+ else if (prop->oper == OSSL_PROPERTY_OVERRIDE)
+ put_char('-', &buf, &bufsize, &needed);
+
+ val = ossl_property_name_str(ctx, prop->name_idx);
+ if (val == NULL)
+ return 0;
+ put_str(val, &buf, &bufsize, &needed);
+
+ switch (prop->oper) {
+ case OSSL_PROPERTY_OPER_NE:
+ put_char('!', &buf, &bufsize, &needed);
+ /* fall through */
+ case OSSL_PROPERTY_OPER_EQ:
+ put_char('=', &buf, &bufsize, &needed);
+ /* put value */
+ switch (prop->type) {
+ case OSSL_PROPERTY_TYPE_STRING:
+ val = ossl_property_value_str(ctx, prop->v.str_val);
+ if (val == NULL)
+ return 0;
+ put_str(val, &buf, &bufsize, &needed);
+ break;
+
+ case OSSL_PROPERTY_TYPE_NUMBER:
+ put_num(prop->v.int_val, &buf, &bufsize, &needed);
+ break;
+
+ default:
+ return 0;
+ }
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ }
+
+ put_char('\0', &buf, &bufsize, &needed);
+ return needed;
+}
diff --git a/crypto/property/property_query.c b/crypto/property/property_query.c
new file mode 100644
index 000000000000..28cc704840a4
--- /dev/null
+++ b/crypto/property/property_query.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/propertyerr.h"
+#include "internal/property.h"
+#include "property_local.h"
+
+static int property_idx_cmp(const void *keyp, const void *compare)
+{
+ OSSL_PROPERTY_IDX key = *(const OSSL_PROPERTY_IDX *)keyp;
+ const OSSL_PROPERTY_DEFINITION *defn =
+ (const OSSL_PROPERTY_DEFINITION *)compare;
+
+ return key - defn->name_idx;
+}
+
+const OSSL_PROPERTY_DEFINITION *
+ossl_property_find_property(const OSSL_PROPERTY_LIST *list,
+ OSSL_LIB_CTX *libctx, const char *name)
+{
+ OSSL_PROPERTY_IDX name_idx;
+
+ if (list == NULL || name == NULL
+ || (name_idx = ossl_property_name(libctx, name, 0)) == 0)
+ return NULL;
+
+ return ossl_bsearch(&name_idx, list->properties, list->num_properties,
+ sizeof(*list->properties), &property_idx_cmp, 0);
+}
+
+OSSL_PROPERTY_TYPE ossl_property_get_type(const OSSL_PROPERTY_DEFINITION *prop)
+{
+ return prop->type;
+}
+
+const char *ossl_property_get_string_value(OSSL_LIB_CTX *libctx,
+ const OSSL_PROPERTY_DEFINITION *prop)
+{
+ const char *value = NULL;
+
+ if (prop != NULL && prop->type == OSSL_PROPERTY_TYPE_STRING)
+ value = ossl_property_value_str(libctx, prop->v.str_val);
+ return value;
+}
+
+int64_t ossl_property_get_number_value(const OSSL_PROPERTY_DEFINITION *prop)
+{
+ int64_t value = 0;
+
+ if (prop != NULL && prop->type == OSSL_PROPERTY_TYPE_NUMBER)
+ value = prop->v.int_val;
+ return value;
+}
+
+/* Does a property query have any optional clauses */
+int ossl_property_has_optional(const OSSL_PROPERTY_LIST *query)
+{
+ return query->has_optional ? 1 : 0;
+}
+
+int ossl_property_is_enabled(OSSL_LIB_CTX *ctx, const char *property_name,
+ const OSSL_PROPERTY_LIST *prop_list)
+{
+ const OSSL_PROPERTY_DEFINITION *prop;
+
+ prop = ossl_property_find_property(prop_list, ctx, property_name);
+ /* Do a separate check for override as it does not set type */
+ if (prop == NULL || prop->optional || prop->oper == OSSL_PROPERTY_OVERRIDE)
+ return 0;
+ return (prop->type == OSSL_PROPERTY_TYPE_STRING
+ && ((prop->oper == OSSL_PROPERTY_OPER_EQ
+ && prop->v.str_val == OSSL_PROPERTY_TRUE)
+ || (prop->oper == OSSL_PROPERTY_OPER_NE
+ && prop->v.str_val != OSSL_PROPERTY_TRUE)));
+}
+
diff --git a/crypto/property/property_string.c b/crypto/property/property_string.c
new file mode 100644
index 000000000000..ef87a6a78235
--- /dev/null
+++ b/crypto/property/property_string.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/lhash.h>
+#include "crypto/lhash.h"
+#include "property_local.h"
+
+/*
+ * Property strings are a consolidation of all strings seen by the property
+ * subsystem. There are two name spaces to keep property names separate from
+ * property values (numeric values are not expected to be cached however).
+ * They allow a rapid conversion from a string to a unique index and any
+ * subsequent string comparison can be done via an integer compare.
+ *
+ * This implementation uses OpenSSL's standard hash table. There are more
+ * space and time efficient algorithms if this becomes a bottleneck.
+ */
+
+typedef struct {
+ const char *s;
+ OSSL_PROPERTY_IDX idx;
+ char body[1];
+} PROPERTY_STRING;
+
+DEFINE_LHASH_OF(PROPERTY_STRING);
+typedef LHASH_OF(PROPERTY_STRING) PROP_TABLE;
+
+typedef struct {
+ CRYPTO_RWLOCK *lock;
+ PROP_TABLE *prop_names;
+ PROP_TABLE *prop_values;
+ OSSL_PROPERTY_IDX prop_name_idx;
+ OSSL_PROPERTY_IDX prop_value_idx;
+} PROPERTY_STRING_DATA;
+
+static unsigned long property_hash(const PROPERTY_STRING *a)
+{
+ return OPENSSL_LH_strhash(a->s);
+}
+
+static int property_cmp(const PROPERTY_STRING *a, const PROPERTY_STRING *b)
+{
+ return strcmp(a->s, b->s);
+}
+
+static void property_free(PROPERTY_STRING *ps)
+{
+ OPENSSL_free(ps);
+}
+
+static void property_table_free(PROP_TABLE **pt)
+{
+ PROP_TABLE *t = *pt;
+
+ if (t != NULL) {
+ lh_PROPERTY_STRING_doall(t, &property_free);
+ lh_PROPERTY_STRING_free(t);
+ *pt = NULL;
+ }
+}
+
+static void property_string_data_free(void *vpropdata)
+{
+ PROPERTY_STRING_DATA *propdata = vpropdata;
+
+ if (propdata == NULL)
+ return;
+
+ CRYPTO_THREAD_lock_free(propdata->lock);
+ property_table_free(&propdata->prop_names);
+ property_table_free(&propdata->prop_values);
+ propdata->prop_name_idx = propdata->prop_value_idx = 0;
+
+ OPENSSL_free(propdata);
+}
+
+static void *property_string_data_new(OSSL_LIB_CTX *ctx) {
+ PROPERTY_STRING_DATA *propdata = OPENSSL_zalloc(sizeof(*propdata));
+
+ if (propdata == NULL)
+ return NULL;
+
+ propdata->lock = CRYPTO_THREAD_lock_new();
+ if (propdata->lock == NULL)
+ goto err;
+
+ propdata->prop_names = lh_PROPERTY_STRING_new(&property_hash,
+ &property_cmp);
+ if (propdata->prop_names == NULL)
+ goto err;
+
+ propdata->prop_values = lh_PROPERTY_STRING_new(&property_hash,
+ &property_cmp);
+ if (propdata->prop_values == NULL)
+ goto err;
+
+ return propdata;
+
+err:
+ property_string_data_free(propdata);
+ return NULL;
+}
+
+static const OSSL_LIB_CTX_METHOD property_string_data_method = {
+ OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
+ property_string_data_new,
+ property_string_data_free,
+};
+
+static PROPERTY_STRING *new_property_string(const char *s,
+ OSSL_PROPERTY_IDX *pidx)
+{
+ const size_t l = strlen(s);
+ PROPERTY_STRING *ps = OPENSSL_malloc(sizeof(*ps) + l);
+
+ if (ps != NULL) {
+ memcpy(ps->body, s, l + 1);
+ ps->s = ps->body;
+ ps->idx = ++*pidx;
+ if (ps->idx == 0) {
+ OPENSSL_free(ps);
+ return NULL;
+ }
+ }
+ return ps;
+}
+
+static OSSL_PROPERTY_IDX ossl_property_string(CRYPTO_RWLOCK *lock,
+ PROP_TABLE *t,
+ OSSL_PROPERTY_IDX *pidx,
+ const char *s)
+{
+ PROPERTY_STRING p, *ps, *ps_new;
+
+ p.s = s;
+ if (!CRYPTO_THREAD_read_lock(lock)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_UNABLE_TO_GET_READ_LOCK);
+ return 0;
+ }
+ ps = lh_PROPERTY_STRING_retrieve(t, &p);
+ if (ps == NULL && pidx != NULL) {
+ CRYPTO_THREAD_unlock(lock);
+ if (!CRYPTO_THREAD_write_lock(lock)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
+ return 0;
+ }
+ ps = lh_PROPERTY_STRING_retrieve(t, &p);
+ if (ps == NULL && (ps_new = new_property_string(s, pidx)) != NULL) {
+ lh_PROPERTY_STRING_insert(t, ps_new);
+ if (lh_PROPERTY_STRING_error(t)) {
+ property_free(ps_new);
+ CRYPTO_THREAD_unlock(lock);
+ return 0;
+ }
+ ps = ps_new;
+ }
+ }
+ CRYPTO_THREAD_unlock(lock);
+ return ps != NULL ? ps->idx : 0;
+}
+
+struct find_str_st {
+ const char *str;
+ OSSL_PROPERTY_IDX idx;
+};
+
+static void find_str_fn(PROPERTY_STRING *prop, void *vfindstr)
+{
+ struct find_str_st *findstr = vfindstr;
+
+ if (prop->idx == findstr->idx)
+ findstr->str = prop->s;
+}
+
+static const char *ossl_property_str(int name, OSSL_LIB_CTX *ctx,
+ OSSL_PROPERTY_IDX idx)
+{
+ struct find_str_st findstr;
+ PROPERTY_STRING_DATA *propdata
+ = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX,
+ &property_string_data_method);
+
+ if (propdata == NULL)
+ return NULL;
+
+ findstr.str = NULL;
+ findstr.idx = idx;
+
+ if (!CRYPTO_THREAD_read_lock(propdata->lock)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_UNABLE_TO_GET_READ_LOCK);
+ return NULL;
+ }
+ lh_PROPERTY_STRING_doall_arg(name ? propdata->prop_names
+ : propdata->prop_values,
+ find_str_fn, &findstr);
+ CRYPTO_THREAD_unlock(propdata->lock);
+
+ return findstr.str;
+}
+
+OSSL_PROPERTY_IDX ossl_property_name(OSSL_LIB_CTX *ctx, const char *s,
+ int create)
+{
+ PROPERTY_STRING_DATA *propdata
+ = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX,
+ &property_string_data_method);
+
+ if (propdata == NULL)
+ return 0;
+ return ossl_property_string(propdata->lock, propdata->prop_names,
+ create ? &propdata->prop_name_idx : NULL,
+ s);
+}
+
+const char *ossl_property_name_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx)
+{
+ return ossl_property_str(1, ctx, idx);
+}
+
+OSSL_PROPERTY_IDX ossl_property_value(OSSL_LIB_CTX *ctx, const char *s,
+ int create)
+{
+ PROPERTY_STRING_DATA *propdata
+ = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX,
+ &property_string_data_method);
+
+ if (propdata == NULL)
+ return 0;
+ return ossl_property_string(propdata->lock, propdata->prop_values,
+ create ? &propdata->prop_value_idx : NULL,
+ s);
+}
+
+const char *ossl_property_value_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx)
+{
+ return ossl_property_str(0, ctx, idx);
+}
diff --git a/crypto/provider.c b/crypto/provider.c
new file mode 100644
index 000000000000..114b42692940
--- /dev/null
+++ b/crypto/provider.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/err.h>
+#include <openssl/cryptoerr.h>
+#include <openssl/provider.h>
+#include <openssl/core_names.h>
+#include "internal/provider.h"
+#include "provider_local.h"
+
+OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *libctx, const char *name,
+ int retain_fallbacks)
+{
+ OSSL_PROVIDER *prov = NULL, *actual;
+ int isnew = 0;
+
+ /* Find it or create it */
+ if ((prov = ossl_provider_find(libctx, name, 0)) == NULL) {
+ if ((prov = ossl_provider_new(libctx, name, NULL, 0)) == NULL)
+ return NULL;
+ isnew = 1;
+ }
+
+ if (!ossl_provider_activate(prov, 1, 0)) {
+ ossl_provider_free(prov);
+ return NULL;
+ }
+
+ actual = prov;
+ if (isnew && !ossl_provider_add_to_store(prov, &actual, retain_fallbacks)) {
+ ossl_provider_deactivate(prov, 1);
+ ossl_provider_free(prov);
+ return NULL;
+ }
+ if (actual != prov) {
+ if (!ossl_provider_activate(actual, 1, 0)) {
+ ossl_provider_free(actual);
+ return NULL;
+ }
+ }
+
+ return actual;
+}
+
+OSSL_PROVIDER *OSSL_PROVIDER_load(OSSL_LIB_CTX *libctx, const char *name)
+{
+ /* Any attempt to load a provider disables auto-loading of defaults */
+ if (ossl_provider_disable_fallback_loading(libctx))
+ return OSSL_PROVIDER_try_load(libctx, name, 0);
+ return NULL;
+}
+
+int OSSL_PROVIDER_unload(OSSL_PROVIDER *prov)
+{
+ if (!ossl_provider_deactivate(prov, 1))
+ return 0;
+ ossl_provider_free(prov);
+ return 1;
+}
+
+const OSSL_PARAM *OSSL_PROVIDER_gettable_params(const OSSL_PROVIDER *prov)
+{
+ return ossl_provider_gettable_params(prov);
+}
+
+int OSSL_PROVIDER_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[])
+{
+ return ossl_provider_get_params(prov, params);
+}
+
+const OSSL_ALGORITHM *OSSL_PROVIDER_query_operation(const OSSL_PROVIDER *prov,
+ int operation_id,
+ int *no_cache)
+{
+ return ossl_provider_query_operation(prov, operation_id, no_cache);
+}
+
+void OSSL_PROVIDER_unquery_operation(const OSSL_PROVIDER *prov,
+ int operation_id,
+ const OSSL_ALGORITHM *algs)
+{
+ ossl_provider_unquery_operation(prov, operation_id, algs);
+}
+
+void *OSSL_PROVIDER_get0_provider_ctx(const OSSL_PROVIDER *prov)
+{
+ return ossl_provider_prov_ctx(prov);
+}
+
+const OSSL_DISPATCH *OSSL_PROVIDER_get0_dispatch(const OSSL_PROVIDER *prov)
+{
+ return ossl_provider_get0_dispatch(prov);
+}
+
+int OSSL_PROVIDER_self_test(const OSSL_PROVIDER *prov)
+{
+ return ossl_provider_self_test(prov);
+}
+
+int OSSL_PROVIDER_get_capabilities(const OSSL_PROVIDER *prov,
+ const char *capability,
+ OSSL_CALLBACK *cb,
+ void *arg)
+{
+ return ossl_provider_get_capabilities(prov, capability, cb, arg);
+}
+
+int OSSL_PROVIDER_add_builtin(OSSL_LIB_CTX *libctx, const char *name,
+ OSSL_provider_init_fn *init_fn)
+{
+ OSSL_PROVIDER_INFO entry;
+
+ if (name == NULL || init_fn == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ memset(&entry, 0, sizeof(entry));
+ entry.name = OPENSSL_strdup(name);
+ if (entry.name == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ entry.init = init_fn;
+ if (!ossl_provider_info_add_to_store(libctx, &entry)) {
+ ossl_provider_info_clear(&entry);
+ return 0;
+ }
+ return 1;
+}
+
+const char *OSSL_PROVIDER_get0_name(const OSSL_PROVIDER *prov)
+{
+ return ossl_provider_name(prov);
+}
+
+int OSSL_PROVIDER_do_all(OSSL_LIB_CTX *ctx,
+ int (*cb)(OSSL_PROVIDER *provider,
+ void *cbdata),
+ void *cbdata)
+{
+ return ossl_provider_doall_activated(ctx, cb, cbdata);
+}
diff --git a/crypto/provider_child.c b/crypto/provider_child.c
new file mode 100644
index 000000000000..861bcb035baa
--- /dev/null
+++ b/crypto/provider_child.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <assert.h>
+#include <openssl/crypto.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/provider.h>
+#include <openssl/evp.h>
+#include "internal/provider.h"
+#include "internal/cryptlib.h"
+#include "crypto/evp.h"
+
+DEFINE_STACK_OF(OSSL_PROVIDER)
+
+struct child_prov_globals {
+ const OSSL_CORE_HANDLE *handle;
+ const OSSL_CORE_HANDLE *curr_prov;
+ CRYPTO_RWLOCK *lock;
+ OSSL_FUNC_core_get_libctx_fn *c_get_libctx;
+ OSSL_FUNC_provider_register_child_cb_fn *c_provider_register_child_cb;
+ OSSL_FUNC_provider_deregister_child_cb_fn *c_provider_deregister_child_cb;
+ OSSL_FUNC_provider_name_fn *c_prov_name;
+ OSSL_FUNC_provider_get0_provider_ctx_fn *c_prov_get0_provider_ctx;
+ OSSL_FUNC_provider_get0_dispatch_fn *c_prov_get0_dispatch;
+ OSSL_FUNC_provider_up_ref_fn *c_prov_up_ref;
+ OSSL_FUNC_provider_free_fn *c_prov_free;
+};
+
+static void *child_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx)
+{
+ return OPENSSL_zalloc(sizeof(struct child_prov_globals));
+}
+
+static void child_prov_ossl_ctx_free(void *vgbl)
+{
+ struct child_prov_globals *gbl = vgbl;
+
+ CRYPTO_THREAD_lock_free(gbl->lock);
+ OPENSSL_free(gbl);
+}
+
+static const OSSL_LIB_CTX_METHOD child_prov_ossl_ctx_method = {
+ OSSL_LIB_CTX_METHOD_LOW_PRIORITY,
+ child_prov_ossl_ctx_new,
+ child_prov_ossl_ctx_free,
+};
+
+static OSSL_provider_init_fn ossl_child_provider_init;
+
+static int ossl_child_provider_init(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in,
+ const OSSL_DISPATCH **out,
+ void **provctx)
+{
+ OSSL_FUNC_core_get_libctx_fn *c_get_libctx = NULL;
+ OSSL_LIB_CTX *ctx;
+ struct child_prov_globals *gbl;
+
+ for (; in->function_id != 0; in++) {
+ switch (in->function_id) {
+ case OSSL_FUNC_CORE_GET_LIBCTX:
+ c_get_libctx = OSSL_FUNC_core_get_libctx(in);
+ break;
+ default:
+ /* Just ignore anything we don't understand */
+ break;
+ }
+ }
+
+ if (c_get_libctx == NULL)
+ return 0;
+
+ /*
+ * We need an OSSL_LIB_CTX but c_get_libctx returns OPENSSL_CORE_CTX. We are
+ * a built-in provider and so we can get away with this cast. Normal
+ * providers can't do this.
+ */
+ ctx = (OSSL_LIB_CTX *)c_get_libctx(handle);
+
+ gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX,
+ &child_prov_ossl_ctx_method);
+ if (gbl == NULL)
+ return 0;
+
+ *provctx = gbl->c_prov_get0_provider_ctx(gbl->curr_prov);
+ *out = gbl->c_prov_get0_dispatch(gbl->curr_prov);
+
+ return 1;
+}
+
+static int provider_create_child_cb(const OSSL_CORE_HANDLE *prov, void *cbdata)
+{
+ OSSL_LIB_CTX *ctx = cbdata;
+ struct child_prov_globals *gbl;
+ const char *provname;
+ OSSL_PROVIDER *cprov;
+ int ret = 0;
+
+ gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX,
+ &child_prov_ossl_ctx_method);
+ if (gbl == NULL)
+ return 0;
+
+ if (!CRYPTO_THREAD_write_lock(gbl->lock))
+ return 0;
+
+ provname = gbl->c_prov_name(prov);
+
+ /*
+ * We're operating under a lock so we can store the "current" provider in
+ * the global data.
+ */
+ gbl->curr_prov = prov;
+
+ if ((cprov = ossl_provider_find(ctx, provname, 1)) != NULL) {
+ /*
+ * We free the newly created ref. We rely on the provider sticking around
+ * in the provider store.
+ */
+ ossl_provider_free(cprov);
+
+ /*
+ * The provider already exists. It could be a previously created child,
+ * or it could have been explicitly loaded. If explicitly loaded we
+ * ignore it - i.e. we don't start treating it like a child.
+ */
+ if (!ossl_provider_activate(cprov, 0, 1))
+ goto err;
+ } else {
+ /*
+ * Create it - passing 1 as final param so we don't try and recursively
+ * init children
+ */
+ if ((cprov = ossl_provider_new(ctx, provname, ossl_child_provider_init,
+ 1)) == NULL)
+ goto err;
+
+ if (!ossl_provider_activate(cprov, 0, 0)) {
+ ossl_provider_free(cprov);
+ goto err;
+ }
+
+ if (!ossl_provider_set_child(cprov, prov)
+ || !ossl_provider_add_to_store(cprov, NULL, 0)) {
+ ossl_provider_deactivate(cprov, 0);
+ ossl_provider_free(cprov);
+ goto err;
+ }
+ }
+
+ ret = 1;
+ err:
+ CRYPTO_THREAD_unlock(gbl->lock);
+ return ret;
+}
+
+static int provider_remove_child_cb(const OSSL_CORE_HANDLE *prov, void *cbdata)
+{
+ OSSL_LIB_CTX *ctx = cbdata;
+ struct child_prov_globals *gbl;
+ const char *provname;
+ OSSL_PROVIDER *cprov;
+
+ gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX,
+ &child_prov_ossl_ctx_method);
+ if (gbl == NULL)
+ return 0;
+
+ provname = gbl->c_prov_name(prov);
+ cprov = ossl_provider_find(ctx, provname, 1);
+ if (cprov == NULL)
+ return 0;
+ /*
+ * ossl_provider_find ups the ref count, so we free it again here. We can
+ * rely on the provider store reference count.
+ */
+ ossl_provider_free(cprov);
+ if (ossl_provider_is_child(cprov)
+ && !ossl_provider_deactivate(cprov, 1))
+ return 0;
+
+ return 1;
+}
+
+static int provider_global_props_cb(const char *props, void *cbdata)
+{
+ OSSL_LIB_CTX *ctx = cbdata;
+
+ return evp_set_default_properties_int(ctx, props, 0, 1);
+}
+
+int ossl_provider_init_as_child(OSSL_LIB_CTX *ctx,
+ const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in)
+{
+ struct child_prov_globals *gbl;
+
+ if (ctx == NULL)
+ return 0;
+
+ gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX,
+ &child_prov_ossl_ctx_method);
+ if (gbl == NULL)
+ return 0;
+
+ gbl->handle = handle;
+ for (; in->function_id != 0; in++) {
+ switch (in->function_id) {
+ case OSSL_FUNC_CORE_GET_LIBCTX:
+ gbl->c_get_libctx = OSSL_FUNC_core_get_libctx(in);
+ break;
+ case OSSL_FUNC_PROVIDER_REGISTER_CHILD_CB:
+ gbl->c_provider_register_child_cb
+ = OSSL_FUNC_provider_register_child_cb(in);
+ break;
+ case OSSL_FUNC_PROVIDER_DEREGISTER_CHILD_CB:
+ gbl->c_provider_deregister_child_cb
+ = OSSL_FUNC_provider_deregister_child_cb(in);
+ break;
+ case OSSL_FUNC_PROVIDER_NAME:
+ gbl->c_prov_name = OSSL_FUNC_provider_name(in);
+ break;
+ case OSSL_FUNC_PROVIDER_GET0_PROVIDER_CTX:
+ gbl->c_prov_get0_provider_ctx
+ = OSSL_FUNC_provider_get0_provider_ctx(in);
+ break;
+ case OSSL_FUNC_PROVIDER_GET0_DISPATCH:
+ gbl->c_prov_get0_dispatch = OSSL_FUNC_provider_get0_dispatch(in);
+ break;
+ case OSSL_FUNC_PROVIDER_UP_REF:
+ gbl->c_prov_up_ref
+ = OSSL_FUNC_provider_up_ref(in);
+ break;
+ case OSSL_FUNC_PROVIDER_FREE:
+ gbl->c_prov_free = OSSL_FUNC_provider_free(in);
+ break;
+ default:
+ /* Just ignore anything we don't understand */
+ break;
+ }
+ }
+
+ if (gbl->c_get_libctx == NULL
+ || gbl->c_provider_register_child_cb == NULL
+ || gbl->c_prov_name == NULL
+ || gbl->c_prov_get0_provider_ctx == NULL
+ || gbl->c_prov_get0_dispatch == NULL
+ || gbl->c_prov_up_ref == NULL
+ || gbl->c_prov_free == NULL)
+ return 0;
+
+ gbl->lock = CRYPTO_THREAD_lock_new();
+ if (gbl->lock == NULL)
+ return 0;
+
+ if (!gbl->c_provider_register_child_cb(gbl->handle,
+ provider_create_child_cb,
+ provider_remove_child_cb,
+ provider_global_props_cb,
+ ctx))
+ return 0;
+
+ return 1;
+}
+
+void ossl_provider_deinit_child(OSSL_LIB_CTX *ctx)
+{
+ struct child_prov_globals *gbl
+ = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX,
+ &child_prov_ossl_ctx_method);
+ if (gbl == NULL)
+ return;
+
+ gbl->c_provider_deregister_child_cb(gbl->handle);
+}
+
+/*
+ * ossl_provider_up_ref_parent() and ossl_provider_free_parent() do
+ * nothing in "self-referencing" child providers, i.e. when the parent
+ * of the child provider is the same as the provider where this child
+ * provider was created.
+ * This allows the teardown function in the parent provider to be called
+ * at the correct moment.
+ * For child providers in other providers, the reference count is done to
+ * ensure that cross referencing is recorded. These should be cleared up
+ * through that providers teardown, as part of freeing its child libctx.
+ */
+
+int ossl_provider_up_ref_parent(OSSL_PROVIDER *prov, int activate)
+{
+ struct child_prov_globals *gbl;
+ const OSSL_CORE_HANDLE *parent_handle;
+
+ gbl = ossl_lib_ctx_get_data(ossl_provider_libctx(prov),
+ OSSL_LIB_CTX_CHILD_PROVIDER_INDEX,
+ &child_prov_ossl_ctx_method);
+ if (gbl == NULL)
+ return 0;
+
+ parent_handle = ossl_provider_get_parent(prov);
+ if (parent_handle == gbl->handle)
+ return 1;
+ return gbl->c_prov_up_ref(parent_handle, activate);
+}
+
+int ossl_provider_free_parent(OSSL_PROVIDER *prov, int deactivate)
+{
+ struct child_prov_globals *gbl;
+ const OSSL_CORE_HANDLE *parent_handle;
+
+ gbl = ossl_lib_ctx_get_data(ossl_provider_libctx(prov),
+ OSSL_LIB_CTX_CHILD_PROVIDER_INDEX,
+ &child_prov_ossl_ctx_method);
+ if (gbl == NULL)
+ return 0;
+
+ parent_handle = ossl_provider_get_parent(prov);
+ if (parent_handle == gbl->handle)
+ return 1;
+ return gbl->c_prov_free(ossl_provider_get_parent(prov), deactivate);
+}
diff --git a/crypto/provider_conf.c b/crypto/provider_conf.c
new file mode 100644
index 000000000000..c13c887c3d4a
--- /dev/null
+++ b/crypto/provider_conf.c
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/trace.h>
+#include <openssl/err.h>
+#include <openssl/conf.h>
+#include <openssl/safestack.h>
+#include <openssl/provider.h>
+#include "internal/provider.h"
+#include "internal/cryptlib.h"
+#include "provider_local.h"
+
+DEFINE_STACK_OF(OSSL_PROVIDER)
+
+/* PROVIDER config module */
+
+typedef struct {
+ CRYPTO_RWLOCK *lock;
+ STACK_OF(OSSL_PROVIDER) *activated_providers;
+} PROVIDER_CONF_GLOBAL;
+
+static void *prov_conf_ossl_ctx_new(OSSL_LIB_CTX *libctx)
+{
+ PROVIDER_CONF_GLOBAL *pcgbl = OPENSSL_zalloc(sizeof(*pcgbl));
+
+ if (pcgbl == NULL)
+ return NULL;
+
+ pcgbl->lock = CRYPTO_THREAD_lock_new();
+ if (pcgbl->lock == NULL) {
+ OPENSSL_free(pcgbl);
+ return NULL;
+ }
+
+ return pcgbl;
+}
+
+static void prov_conf_ossl_ctx_free(void *vpcgbl)
+{
+ PROVIDER_CONF_GLOBAL *pcgbl = vpcgbl;
+
+ sk_OSSL_PROVIDER_pop_free(pcgbl->activated_providers,
+ ossl_provider_free);
+
+ OSSL_TRACE(CONF, "Cleaned up providers\n");
+ CRYPTO_THREAD_lock_free(pcgbl->lock);
+ OPENSSL_free(pcgbl);
+}
+
+static const OSSL_LIB_CTX_METHOD provider_conf_ossl_ctx_method = {
+ /* Must be freed before the provider store is freed */
+ OSSL_LIB_CTX_METHOD_PRIORITY_2,
+ prov_conf_ossl_ctx_new,
+ prov_conf_ossl_ctx_free,
+};
+
+static const char *skip_dot(const char *name)
+{
+ const char *p = strchr(name, '.');
+
+ if (p != NULL)
+ return p + 1;
+ return name;
+}
+
+static int provider_conf_params(OSSL_PROVIDER *prov,
+ OSSL_PROVIDER_INFO *provinfo,
+ const char *name, const char *value,
+ const CONF *cnf)
+{
+ STACK_OF(CONF_VALUE) *sect;
+ int ok = 1;
+
+ sect = NCONF_get_section(cnf, value);
+ if (sect != NULL) {
+ int i;
+ char buffer[512];
+ size_t buffer_len = 0;
+
+ OSSL_TRACE1(CONF, "Provider params: start section %s\n", value);
+
+ if (name != NULL) {
+ OPENSSL_strlcpy(buffer, name, sizeof(buffer));
+ OPENSSL_strlcat(buffer, ".", sizeof(buffer));
+ buffer_len = strlen(buffer);
+ }
+
+ for (i = 0; i < sk_CONF_VALUE_num(sect); i++) {
+ CONF_VALUE *sectconf = sk_CONF_VALUE_value(sect, i);
+
+ if (buffer_len + strlen(sectconf->name) >= sizeof(buffer))
+ return 0;
+ buffer[buffer_len] = '\0';
+ OPENSSL_strlcat(buffer, sectconf->name, sizeof(buffer));
+ if (!provider_conf_params(prov, provinfo, buffer, sectconf->value,
+ cnf))
+ return 0;
+ }
+
+ OSSL_TRACE1(CONF, "Provider params: finish section %s\n", value);
+ } else {
+ OSSL_TRACE2(CONF, "Provider params: %s = %s\n", name, value);
+ if (prov != NULL)
+ ok = ossl_provider_add_parameter(prov, name, value);
+ else
+ ok = ossl_provider_info_add_parameter(provinfo, name, value);
+ }
+
+ return ok;
+}
+
+static int prov_already_activated(const char *name,
+ STACK_OF(OSSL_PROVIDER) *activated)
+{
+ int i, max;
+
+ if (activated == NULL)
+ return 0;
+
+ max = sk_OSSL_PROVIDER_num(activated);
+ for (i = 0; i < max; i++) {
+ OSSL_PROVIDER *tstprov = sk_OSSL_PROVIDER_value(activated, i);
+
+ if (strcmp(OSSL_PROVIDER_get0_name(tstprov), name) == 0) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name,
+ const char *value, const CONF *cnf)
+{
+ int i;
+ STACK_OF(CONF_VALUE) *ecmds;
+ int soft = 0;
+ OSSL_PROVIDER *prov = NULL, *actual = NULL;
+ const char *path = NULL;
+ long activate = 0;
+ int ok = 0;
+
+ name = skip_dot(name);
+ OSSL_TRACE1(CONF, "Configuring provider %s\n", name);
+ /* Value is a section containing PROVIDER commands */
+ ecmds = NCONF_get_section(cnf, value);
+
+ if (!ecmds) {
+ ERR_raise_data(ERR_LIB_CRYPTO, CRYPTO_R_PROVIDER_SECTION_ERROR,
+ "section=%s not found", value);
+ return 0;
+ }
+
+ /* Find the needed data first */
+ for (i = 0; i < sk_CONF_VALUE_num(ecmds); i++) {
+ CONF_VALUE *ecmd = sk_CONF_VALUE_value(ecmds, i);
+ const char *confname = skip_dot(ecmd->name);
+ const char *confvalue = ecmd->value;
+
+ OSSL_TRACE2(CONF, "Provider command: %s = %s\n",
+ confname, confvalue);
+
+ /* First handle some special pseudo confs */
+
+ /* Override provider name to use */
+ if (strcmp(confname, "identity") == 0)
+ name = confvalue;
+ else if (strcmp(confname, "soft_load") == 0)
+ soft = 1;
+ /* Load a dynamic PROVIDER */
+ else if (strcmp(confname, "module") == 0)
+ path = confvalue;
+ else if (strcmp(confname, "activate") == 0)
+ activate = 1;
+ }
+
+ if (activate) {
+ PROVIDER_CONF_GLOBAL *pcgbl
+ = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_PROVIDER_CONF_INDEX,
+ &provider_conf_ossl_ctx_method);
+
+ if (pcgbl == NULL || !CRYPTO_THREAD_write_lock(pcgbl->lock)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ if (!prov_already_activated(name, pcgbl->activated_providers)) {
+ /*
+ * There is an attempt to activate a provider, so we should disable
+ * loading of fallbacks. Otherwise a misconfiguration could mean the
+ * intended provider does not get loaded. Subsequent fetches could
+ * then fallback to the default provider - which may be the wrong
+ * thing.
+ */
+ if (!ossl_provider_disable_fallback_loading(libctx)) {
+ CRYPTO_THREAD_unlock(pcgbl->lock);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ prov = ossl_provider_find(libctx, name, 1);
+ if (prov == NULL)
+ prov = ossl_provider_new(libctx, name, NULL, 1);
+ if (prov == NULL) {
+ CRYPTO_THREAD_unlock(pcgbl->lock);
+ if (soft)
+ ERR_clear_error();
+ return 0;
+ }
+
+ if (path != NULL)
+ ossl_provider_set_module_path(prov, path);
+
+ ok = provider_conf_params(prov, NULL, NULL, value, cnf);
+
+ if (ok) {
+ if (!ossl_provider_activate(prov, 1, 0)) {
+ ok = 0;
+ } else if (!ossl_provider_add_to_store(prov, &actual, 0)) {
+ ossl_provider_deactivate(prov, 1);
+ ok = 0;
+ } else if (actual != prov
+ && !ossl_provider_activate(actual, 1, 0)) {
+ ossl_provider_free(actual);
+ ok = 0;
+ } else {
+ if (pcgbl->activated_providers == NULL)
+ pcgbl->activated_providers = sk_OSSL_PROVIDER_new_null();
+ if (pcgbl->activated_providers == NULL
+ || !sk_OSSL_PROVIDER_push(pcgbl->activated_providers,
+ actual)) {
+ ossl_provider_deactivate(actual, 1);
+ ossl_provider_free(actual);
+ ok = 0;
+ } else {
+ ok = 1;
+ }
+ }
+ }
+ if (!ok)
+ ossl_provider_free(prov);
+ }
+ CRYPTO_THREAD_unlock(pcgbl->lock);
+ } else {
+ OSSL_PROVIDER_INFO entry;
+
+ memset(&entry, 0, sizeof(entry));
+ ok = 1;
+ if (name != NULL) {
+ entry.name = OPENSSL_strdup(name);
+ if (entry.name == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ ok = 0;
+ }
+ }
+ if (ok && path != NULL) {
+ entry.path = OPENSSL_strdup(path);
+ if (entry.path == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ ok = 0;
+ }
+ }
+ if (ok)
+ ok = provider_conf_params(NULL, &entry, NULL, value, cnf);
+ if (ok && (entry.path != NULL || entry.parameters != NULL))
+ ok = ossl_provider_info_add_to_store(libctx, &entry);
+ if (!ok || (entry.path == NULL && entry.parameters == NULL)) {
+ ossl_provider_info_clear(&entry);
+ }
+
+ }
+
+ /*
+ * Even if ok is 0, we still return success. Failure to load a provider is
+ * not fatal. We want to continue to load the rest of the config file.
+ */
+ return 1;
+}
+
+static int provider_conf_init(CONF_IMODULE *md, const CONF *cnf)
+{
+ STACK_OF(CONF_VALUE) *elist;
+ CONF_VALUE *cval;
+ int i;
+
+ OSSL_TRACE1(CONF, "Loading providers module: section %s\n",
+ CONF_imodule_get_value(md));
+
+ /* Value is a section containing PROVIDERs to configure */
+ elist = NCONF_get_section(cnf, CONF_imodule_get_value(md));
+
+ if (!elist) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_PROVIDER_SECTION_ERROR);
+ return 0;
+ }
+
+ for (i = 0; i < sk_CONF_VALUE_num(elist); i++) {
+ cval = sk_CONF_VALUE_value(elist, i);
+ if (!provider_conf_load(NCONF_get0_libctx((CONF *)cnf),
+ cval->name, cval->value, cnf))
+ return 0;
+ }
+
+ return 1;
+}
+
+void ossl_provider_add_conf_module(void)
+{
+ OSSL_TRACE(CONF, "Adding config module 'providers'\n");
+ CONF_module_add("providers", provider_conf_init, NULL);
+}
diff --git a/crypto/provider_core.c b/crypto/provider_core.c
new file mode 100644
index 000000000000..7a1232812162
--- /dev/null
+++ b/crypto/provider_core.c
@@ -0,0 +1,2171 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <assert.h>
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/provider.h>
+#include <openssl/params.h>
+#include <openssl/opensslv.h>
+#include "crypto/cryptlib.h"
+#ifndef FIPS_MODULE
+#include "crypto/decoder.h" /* ossl_decoder_store_cache_flush */
+#include "crypto/encoder.h" /* ossl_encoder_store_cache_flush */
+#include "crypto/store.h" /* ossl_store_loader_store_cache_flush */
+#endif
+#include "crypto/evp.h" /* evp_method_store_cache_flush */
+#include "crypto/rand.h"
+#include "internal/nelem.h"
+#include "internal/thread_once.h"
+#include "internal/provider.h"
+#include "internal/refcount.h"
+#include "internal/bio.h"
+#include "internal/core.h"
+#include "provider_local.h"
+#ifndef FIPS_MODULE
+# include <openssl/self_test.h>
+#endif
+
+/*
+ * This file defines and uses a number of different structures:
+ *
+ * OSSL_PROVIDER (provider_st): Used to represent all information related to a
+ * single instance of a provider.
+ *
+ * provider_store_st: Holds information about the collection of providers that
+ * are available within the current library context (OSSL_LIB_CTX). It also
+ * holds configuration information about providers that could be loaded at some
+ * future point.
+ *
+ * OSSL_PROVIDER_CHILD_CB: An instance of this structure holds the callbacks
+ * that have been registered for a child library context and the associated
+ * provider that registered those callbacks.
+ *
+ * Where a child library context exists then it has its own instance of the
+ * provider store. Each provider that exists in the parent provider store, has
+ * an associated child provider in the child library context's provider store.
+ * As providers get activated or deactivated this needs to be mirrored in the
+ * associated child providers.
+ *
+ * LOCKING
+ * =======
+ *
+ * There are a number of different locks used in this file and it is important
+ * to understand how they should be used in order to avoid deadlocks.
+ *
+ * Fields within a structure can often be "write once" on creation, and then
+ * "read many". Creation of a structure is done by a single thread, and
+ * therefore no lock is required for the "write once/read many" fields. It is
+ * safe for multiple threads to read these fields without a lock, because they
+ * will never be changed.
+ *
+ * However some fields may be changed after a structure has been created and
+ * shared between multiple threads. Where this is the case a lock is required.
+ *
+ * The locks available are:
+ *
+ * The provider flag_lock: Used to control updates to the various provider
+ * "flags" (flag_initialized, flag_activated, flag_fallback) and associated
+ * "counts" (activatecnt).
+ *
+ * The provider refcnt_lock: Only ever used to control updates to the provider
+ * refcnt value.
+ *
+ * The provider optbits_lock: Used to control access to the provider's
+ * operation_bits and operation_bits_sz fields.
+ *
+ * The store default_path_lock: Used to control access to the provider store's
+ * default search path value (default_path)
+ *
+ * The store lock: Used to control the stack of provider's held within the
+ * provider store, as well as the stack of registered child provider callbacks.
+ *
+ * As a general rule-of-thumb it is best to:
+ * - keep the scope of the code that is protected by a lock to the absolute
+ * minimum possible;
+ * - try to keep the scope of the lock to within a single function (i.e. avoid
+ * making calls to other functions while holding a lock);
+ * - try to only ever hold one lock at a time.
+ *
+ * Unfortunately, it is not always possible to stick to the above guidelines.
+ * Where they are not adhered to there is always a danger of inadvertently
+ * introducing the possibility of deadlock. The following rules MUST be adhered
+ * to in order to avoid that:
+ * - Holding multiple locks at the same time is only allowed for the
+ * provider store lock, the provider flag_lock and the provider refcnt_lock.
+ * - When holding multiple locks they must be acquired in the following order of
+ * precedence:
+ * 1) provider store lock
+ * 2) provider flag_lock
+ * 3) provider refcnt_lock
+ * - When releasing locks they must be released in the reverse order to which
+ * they were acquired
+ * - No locks may be held when making an upcall. NOTE: Some common functions
+ * can make upcalls as part of their normal operation. If you need to call
+ * some other function while holding a lock make sure you know whether it
+ * will make any upcalls or not. For example ossl_provider_up_ref() can call
+ * ossl_provider_up_ref_parent() which can call the c_prov_up_ref() upcall.
+ * - It is permissible to hold the store and flag locks when calling child
+ * provider callbacks. No other locks may be held during such callbacks.
+ */
+
+static OSSL_PROVIDER *provider_new(const char *name,
+ OSSL_provider_init_fn *init_function,
+ STACK_OF(INFOPAIR) *parameters);
+
+/*-
+ * Provider Object structure
+ * =========================
+ */
+
+#ifndef FIPS_MODULE
+typedef struct {
+ OSSL_PROVIDER *prov;
+ int (*create_cb)(const OSSL_CORE_HANDLE *provider, void *cbdata);
+ int (*remove_cb)(const OSSL_CORE_HANDLE *provider, void *cbdata);
+ int (*global_props_cb)(const char *props, void *cbdata);
+ void *cbdata;
+} OSSL_PROVIDER_CHILD_CB;
+DEFINE_STACK_OF(OSSL_PROVIDER_CHILD_CB)
+#endif
+
+struct provider_store_st; /* Forward declaration */
+
+struct ossl_provider_st {
+ /* Flag bits */
+ unsigned int flag_initialized:1;
+ unsigned int flag_activated:1;
+ unsigned int flag_fallback:1; /* Can be used as fallback */
+
+ /* Getting and setting the flags require synchronization */
+ CRYPTO_RWLOCK *flag_lock;
+
+ /* OpenSSL library side data */
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *refcnt_lock; /* For the ref counter */
+ int activatecnt;
+ char *name;
+ char *path;
+ DSO *module;
+ OSSL_provider_init_fn *init_function;
+ STACK_OF(INFOPAIR) *parameters;
+ OSSL_LIB_CTX *libctx; /* The library context this instance is in */
+ struct provider_store_st *store; /* The store this instance belongs to */
+#ifndef FIPS_MODULE
+ /*
+ * In the FIPS module inner provider, this isn't needed, since the
+ * error upcalls are always direct calls to the outer provider.
+ */
+ int error_lib; /* ERR library number, one for each provider */
+# ifndef OPENSSL_NO_ERR
+ ERR_STRING_DATA *error_strings; /* Copy of what the provider gives us */
+# endif
+#endif
+
+ /* Provider side functions */
+ OSSL_FUNC_provider_teardown_fn *teardown;
+ OSSL_FUNC_provider_gettable_params_fn *gettable_params;
+ OSSL_FUNC_provider_get_params_fn *get_params;
+ OSSL_FUNC_provider_get_capabilities_fn *get_capabilities;
+ OSSL_FUNC_provider_self_test_fn *self_test;
+ OSSL_FUNC_provider_query_operation_fn *query_operation;
+ OSSL_FUNC_provider_unquery_operation_fn *unquery_operation;
+
+ /*
+ * Cache of bit to indicate of query_operation() has been called on
+ * a specific operation or not.
+ */
+ unsigned char *operation_bits;
+ size_t operation_bits_sz;
+ CRYPTO_RWLOCK *opbits_lock;
+
+#ifndef FIPS_MODULE
+ /* Whether this provider is the child of some other provider */
+ const OSSL_CORE_HANDLE *handle;
+ unsigned int ischild:1;
+#endif
+
+ /* Provider side data */
+ void *provctx;
+ const OSSL_DISPATCH *dispatch;
+};
+DEFINE_STACK_OF(OSSL_PROVIDER)
+
+static int ossl_provider_cmp(const OSSL_PROVIDER * const *a,
+ const OSSL_PROVIDER * const *b)
+{
+ return strcmp((*a)->name, (*b)->name);
+}
+
+/*-
+ * Provider Object store
+ * =====================
+ *
+ * The Provider Object store is a library context object, and therefore needs
+ * an index.
+ */
+
+struct provider_store_st {
+ OSSL_LIB_CTX *libctx;
+ STACK_OF(OSSL_PROVIDER) *providers;
+ STACK_OF(OSSL_PROVIDER_CHILD_CB) *child_cbs;
+ CRYPTO_RWLOCK *default_path_lock;
+ CRYPTO_RWLOCK *lock;
+ char *default_path;
+ OSSL_PROVIDER_INFO *provinfo;
+ size_t numprovinfo;
+ size_t provinfosz;
+ unsigned int use_fallbacks:1;
+ unsigned int freeing:1;
+};
+
+/*
+ * provider_deactivate_free() is a wrapper around ossl_provider_deactivate()
+ * and ossl_provider_free(), called as needed.
+ * Since this is only called when the provider store is being emptied, we
+ * don't need to care about any lock.
+ */
+static void provider_deactivate_free(OSSL_PROVIDER *prov)
+{
+ if (prov->flag_activated)
+ ossl_provider_deactivate(prov, 1);
+ ossl_provider_free(prov);
+}
+
+#ifndef FIPS_MODULE
+static void ossl_provider_child_cb_free(OSSL_PROVIDER_CHILD_CB *cb)
+{
+ OPENSSL_free(cb);
+}
+#endif
+
+static void infopair_free(INFOPAIR *pair)
+{
+ OPENSSL_free(pair->name);
+ OPENSSL_free(pair->value);
+ OPENSSL_free(pair);
+}
+
+static INFOPAIR *infopair_copy(const INFOPAIR *src)
+{
+ INFOPAIR *dest = OPENSSL_zalloc(sizeof(*dest));
+
+ if (dest == NULL)
+ return NULL;
+ if (src->name != NULL) {
+ dest->name = OPENSSL_strdup(src->name);
+ if (dest->name == NULL)
+ goto err;
+ }
+ if (src->value != NULL) {
+ dest->value = OPENSSL_strdup(src->value);
+ if (dest->value == NULL)
+ goto err;
+ }
+ return dest;
+ err:
+ OPENSSL_free(dest->name);
+ OPENSSL_free(dest);
+ return NULL;
+}
+
+void ossl_provider_info_clear(OSSL_PROVIDER_INFO *info)
+{
+ OPENSSL_free(info->name);
+ OPENSSL_free(info->path);
+ sk_INFOPAIR_pop_free(info->parameters, infopair_free);
+}
+
+static void provider_store_free(void *vstore)
+{
+ struct provider_store_st *store = vstore;
+ size_t i;
+
+ if (store == NULL)
+ return;
+ store->freeing = 1;
+ OPENSSL_free(store->default_path);
+ sk_OSSL_PROVIDER_pop_free(store->providers, provider_deactivate_free);
+#ifndef FIPS_MODULE
+ sk_OSSL_PROVIDER_CHILD_CB_pop_free(store->child_cbs,
+ ossl_provider_child_cb_free);
+#endif
+ CRYPTO_THREAD_lock_free(store->default_path_lock);
+ CRYPTO_THREAD_lock_free(store->lock);
+ for (i = 0; i < store->numprovinfo; i++)
+ ossl_provider_info_clear(&store->provinfo[i]);
+ OPENSSL_free(store->provinfo);
+ OPENSSL_free(store);
+}
+
+static void *provider_store_new(OSSL_LIB_CTX *ctx)
+{
+ struct provider_store_st *store = OPENSSL_zalloc(sizeof(*store));
+
+ if (store == NULL
+ || (store->providers = sk_OSSL_PROVIDER_new(ossl_provider_cmp)) == NULL
+ || (store->default_path_lock = CRYPTO_THREAD_lock_new()) == NULL
+#ifndef FIPS_MODULE
+ || (store->child_cbs = sk_OSSL_PROVIDER_CHILD_CB_new_null()) == NULL
+#endif
+ || (store->lock = CRYPTO_THREAD_lock_new()) == NULL) {
+ provider_store_free(store);
+ return NULL;
+ }
+ store->libctx = ctx;
+ store->use_fallbacks = 1;
+
+ return store;
+}
+
+static const OSSL_LIB_CTX_METHOD provider_store_method = {
+ /* Needs to be freed before the child provider data is freed */
+ OSSL_LIB_CTX_METHOD_PRIORITY_1,
+ provider_store_new,
+ provider_store_free,
+};
+
+static struct provider_store_st *get_provider_store(OSSL_LIB_CTX *libctx)
+{
+ struct provider_store_st *store = NULL;
+
+ store = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_PROVIDER_STORE_INDEX,
+ &provider_store_method);
+ if (store == NULL)
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
+ return store;
+}
+
+int ossl_provider_disable_fallback_loading(OSSL_LIB_CTX *libctx)
+{
+ struct provider_store_st *store;
+
+ if ((store = get_provider_store(libctx)) != NULL) {
+ if (!CRYPTO_THREAD_write_lock(store->lock))
+ return 0;
+ store->use_fallbacks = 0;
+ CRYPTO_THREAD_unlock(store->lock);
+ return 1;
+ }
+ return 0;
+}
+
+#define BUILTINS_BLOCK_SIZE 10
+
+int ossl_provider_info_add_to_store(OSSL_LIB_CTX *libctx,
+ OSSL_PROVIDER_INFO *entry)
+{
+ struct provider_store_st *store = get_provider_store(libctx);
+ int ret = 0;
+
+ if (entry->name == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (store == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (!CRYPTO_THREAD_write_lock(store->lock))
+ return 0;
+ if (store->provinfosz == 0) {
+ store->provinfo = OPENSSL_zalloc(sizeof(*store->provinfo)
+ * BUILTINS_BLOCK_SIZE);
+ if (store->provinfo == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ store->provinfosz = BUILTINS_BLOCK_SIZE;
+ } else if (store->numprovinfo == store->provinfosz) {
+ OSSL_PROVIDER_INFO *tmpbuiltins;
+ size_t newsz = store->provinfosz + BUILTINS_BLOCK_SIZE;
+
+ tmpbuiltins = OPENSSL_realloc(store->provinfo,
+ sizeof(*store->provinfo) * newsz);
+ if (tmpbuiltins == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ store->provinfo = tmpbuiltins;
+ store->provinfosz = newsz;
+ }
+ store->provinfo[store->numprovinfo] = *entry;
+ store->numprovinfo++;
+
+ ret = 1;
+ err:
+ CRYPTO_THREAD_unlock(store->lock);
+ return ret;
+}
+
+OSSL_PROVIDER *ossl_provider_find(OSSL_LIB_CTX *libctx, const char *name,
+ int noconfig)
+{
+ struct provider_store_st *store = NULL;
+ OSSL_PROVIDER *prov = NULL;
+
+ if ((store = get_provider_store(libctx)) != NULL) {
+ OSSL_PROVIDER tmpl = { 0, };
+ int i;
+
+#ifndef FIPS_MODULE
+ /*
+ * Make sure any providers are loaded from config before we try to find
+ * them.
+ */
+ if (!noconfig) {
+ if (ossl_lib_ctx_is_default(libctx))
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+ }
+#endif
+
+ tmpl.name = (char *)name;
+ /*
+ * A "find" operation can sort the stack, and therefore a write lock is
+ * required.
+ */
+ if (!CRYPTO_THREAD_write_lock(store->lock))
+ return NULL;
+ if ((i = sk_OSSL_PROVIDER_find(store->providers, &tmpl)) != -1)
+ prov = sk_OSSL_PROVIDER_value(store->providers, i);
+ CRYPTO_THREAD_unlock(store->lock);
+ if (prov != NULL && !ossl_provider_up_ref(prov))
+ prov = NULL;
+ }
+
+ return prov;
+}
+
+/*-
+ * Provider Object methods
+ * =======================
+ */
+
+static OSSL_PROVIDER *provider_new(const char *name,
+ OSSL_provider_init_fn *init_function,
+ STACK_OF(INFOPAIR) *parameters)
+{
+ OSSL_PROVIDER *prov = NULL;
+
+ if ((prov = OPENSSL_zalloc(sizeof(*prov))) == NULL
+#ifndef HAVE_ATOMICS
+ || (prov->refcnt_lock = CRYPTO_THREAD_lock_new()) == NULL
+#endif
+ ) {
+ OPENSSL_free(prov);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ prov->refcnt = 1; /* 1 One reference to be returned */
+
+ if ((prov->opbits_lock = CRYPTO_THREAD_lock_new()) == NULL
+ || (prov->flag_lock = CRYPTO_THREAD_lock_new()) == NULL
+ || (prov->name = OPENSSL_strdup(name)) == NULL
+ || (prov->parameters = sk_INFOPAIR_deep_copy(parameters,
+ infopair_copy,
+ infopair_free)) == NULL) {
+ ossl_provider_free(prov);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ prov->init_function = init_function;
+
+ return prov;
+}
+
+int ossl_provider_up_ref(OSSL_PROVIDER *prov)
+{
+ int ref = 0;
+
+ if (CRYPTO_UP_REF(&prov->refcnt, &ref, prov->refcnt_lock) <= 0)
+ return 0;
+
+#ifndef FIPS_MODULE
+ if (prov->ischild) {
+ if (!ossl_provider_up_ref_parent(prov, 0)) {
+ ossl_provider_free(prov);
+ return 0;
+ }
+ }
+#endif
+
+ return ref;
+}
+
+#ifndef FIPS_MODULE
+static int provider_up_ref_intern(OSSL_PROVIDER *prov, int activate)
+{
+ if (activate)
+ return ossl_provider_activate(prov, 1, 0);
+
+ return ossl_provider_up_ref(prov);
+}
+
+static int provider_free_intern(OSSL_PROVIDER *prov, int deactivate)
+{
+ if (deactivate)
+ return ossl_provider_deactivate(prov, 1);
+
+ ossl_provider_free(prov);
+ return 1;
+}
+#endif
+
+/*
+ * We assume that the requested provider does not already exist in the store.
+ * The caller should check. If it does exist then adding it to the store later
+ * will fail.
+ */
+OSSL_PROVIDER *ossl_provider_new(OSSL_LIB_CTX *libctx, const char *name,
+ OSSL_provider_init_fn *init_function,
+ int noconfig)
+{
+ struct provider_store_st *store = NULL;
+ OSSL_PROVIDER_INFO template;
+ OSSL_PROVIDER *prov = NULL;
+
+ if ((store = get_provider_store(libctx)) == NULL)
+ return NULL;
+
+ memset(&template, 0, sizeof(template));
+ if (init_function == NULL) {
+ const OSSL_PROVIDER_INFO *p;
+ size_t i;
+
+ /* Check if this is a predefined builtin provider */
+ for (p = ossl_predefined_providers; p->name != NULL; p++) {
+ if (strcmp(p->name, name) == 0) {
+ template = *p;
+ break;
+ }
+ }
+ if (p->name == NULL) {
+ /* Check if this is a user added builtin provider */
+ if (!CRYPTO_THREAD_read_lock(store->lock))
+ return NULL;
+ for (i = 0, p = store->provinfo; i < store->numprovinfo; p++, i++) {
+ if (strcmp(p->name, name) == 0) {
+ template = *p;
+ break;
+ }
+ }
+ CRYPTO_THREAD_unlock(store->lock);
+ }
+ } else {
+ template.init = init_function;
+ }
+
+ /* provider_new() generates an error, so no need here */
+ if ((prov = provider_new(name, template.init, template.parameters)) == NULL)
+ return NULL;
+
+ prov->libctx = libctx;
+#ifndef FIPS_MODULE
+ prov->error_lib = ERR_get_next_error_library();
+#endif
+
+ /*
+ * At this point, the provider is only partially "loaded". To be
+ * fully "loaded", ossl_provider_activate() must also be called and it must
+ * then be added to the provider store.
+ */
+
+ return prov;
+}
+
+/* Assumes that the store lock is held */
+static int create_provider_children(OSSL_PROVIDER *prov)
+{
+ int ret = 1;
+#ifndef FIPS_MODULE
+ struct provider_store_st *store = prov->store;
+ OSSL_PROVIDER_CHILD_CB *child_cb;
+ int i, max;
+
+ max = sk_OSSL_PROVIDER_CHILD_CB_num(store->child_cbs);
+ for (i = 0; i < max; i++) {
+ /*
+ * This is newly activated (activatecnt == 1), so we need to
+ * create child providers as necessary.
+ */
+ child_cb = sk_OSSL_PROVIDER_CHILD_CB_value(store->child_cbs, i);
+ ret &= child_cb->create_cb((OSSL_CORE_HANDLE *)prov, child_cb->cbdata);
+ }
+#endif
+
+ return ret;
+}
+
+int ossl_provider_add_to_store(OSSL_PROVIDER *prov, OSSL_PROVIDER **actualprov,
+ int retain_fallbacks)
+{
+ struct provider_store_st *store;
+ int idx;
+ OSSL_PROVIDER tmpl = { 0, };
+ OSSL_PROVIDER *actualtmp = NULL;
+
+ if (actualprov != NULL)
+ *actualprov = NULL;
+
+ if ((store = get_provider_store(prov->libctx)) == NULL)
+ return 0;
+
+ if (!CRYPTO_THREAD_write_lock(store->lock))
+ return 0;
+
+ tmpl.name = (char *)prov->name;
+ idx = sk_OSSL_PROVIDER_find(store->providers, &tmpl);
+ if (idx == -1)
+ actualtmp = prov;
+ else
+ actualtmp = sk_OSSL_PROVIDER_value(store->providers, idx);
+
+ if (idx == -1) {
+ if (sk_OSSL_PROVIDER_push(store->providers, prov) == 0)
+ goto err;
+ prov->store = store;
+ if (!create_provider_children(prov)) {
+ sk_OSSL_PROVIDER_delete_ptr(store->providers, prov);
+ goto err;
+ }
+ if (!retain_fallbacks)
+ store->use_fallbacks = 0;
+ }
+
+ CRYPTO_THREAD_unlock(store->lock);
+
+ if (actualprov != NULL) {
+ if (!ossl_provider_up_ref(actualtmp)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ actualtmp = NULL;
+ return 0;
+ }
+ *actualprov = actualtmp;
+ }
+
+ if (idx >= 0) {
+ /*
+ * The provider is already in the store. Probably two threads
+ * independently initialised their own provider objects with the same
+ * name and raced to put them in the store. This thread lost. We
+ * deactivate the one we just created and use the one that already
+ * exists instead.
+ * If we get here then we know we did not create provider children
+ * above, so we inform ossl_provider_deactivate not to attempt to remove
+ * any.
+ */
+ ossl_provider_deactivate(prov, 0);
+ ossl_provider_free(prov);
+ }
+
+ return 1;
+
+ err:
+ CRYPTO_THREAD_unlock(store->lock);
+ return 0;
+}
+
+void ossl_provider_free(OSSL_PROVIDER *prov)
+{
+ if (prov != NULL) {
+ int ref = 0;
+
+ CRYPTO_DOWN_REF(&prov->refcnt, &ref, prov->refcnt_lock);
+
+ /*
+ * When the refcount drops to zero, we clean up the provider.
+ * Note that this also does teardown, which may seem late,
+ * considering that init happens on first activation. However,
+ * there may be other structures hanging on to the provider after
+ * the last deactivation and may therefore need full access to the
+ * provider's services. Therefore, we deinit late.
+ */
+ if (ref == 0) {
+ if (prov->flag_initialized) {
+ ossl_provider_teardown(prov);
+#ifndef OPENSSL_NO_ERR
+# ifndef FIPS_MODULE
+ if (prov->error_strings != NULL) {
+ ERR_unload_strings(prov->error_lib, prov->error_strings);
+ OPENSSL_free(prov->error_strings);
+ prov->error_strings = NULL;
+ }
+# endif
+#endif
+ OPENSSL_free(prov->operation_bits);
+ prov->operation_bits = NULL;
+ prov->operation_bits_sz = 0;
+ prov->flag_initialized = 0;
+ }
+
+#ifndef FIPS_MODULE
+ /*
+ * We deregister thread handling whether or not the provider was
+ * initialized. If init was attempted but was not successful then
+ * the provider may still have registered a thread handler.
+ */
+ ossl_init_thread_deregister(prov);
+ DSO_free(prov->module);
+#endif
+ OPENSSL_free(prov->name);
+ OPENSSL_free(prov->path);
+ sk_INFOPAIR_pop_free(prov->parameters, infopair_free);
+ CRYPTO_THREAD_lock_free(prov->opbits_lock);
+ CRYPTO_THREAD_lock_free(prov->flag_lock);
+#ifndef HAVE_ATOMICS
+ CRYPTO_THREAD_lock_free(prov->refcnt_lock);
+#endif
+ OPENSSL_free(prov);
+ }
+#ifndef FIPS_MODULE
+ else if (prov->ischild) {
+ ossl_provider_free_parent(prov, 0);
+ }
+#endif
+ }
+}
+
+/* Setters */
+int ossl_provider_set_module_path(OSSL_PROVIDER *prov, const char *module_path)
+{
+ OPENSSL_free(prov->path);
+ prov->path = NULL;
+ if (module_path == NULL)
+ return 1;
+ if ((prov->path = OPENSSL_strdup(module_path)) != NULL)
+ return 1;
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+}
+
+static int infopair_add(STACK_OF(INFOPAIR) **infopairsk, const char *name,
+ const char *value)
+{
+ INFOPAIR *pair = NULL;
+
+ if ((pair = OPENSSL_zalloc(sizeof(*pair))) != NULL
+ && (*infopairsk != NULL
+ || (*infopairsk = sk_INFOPAIR_new_null()) != NULL)
+ && (pair->name = OPENSSL_strdup(name)) != NULL
+ && (pair->value = OPENSSL_strdup(value)) != NULL
+ && sk_INFOPAIR_push(*infopairsk, pair) > 0)
+ return 1;
+
+ if (pair != NULL) {
+ OPENSSL_free(pair->name);
+ OPENSSL_free(pair->value);
+ OPENSSL_free(pair);
+ }
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+}
+
+int ossl_provider_add_parameter(OSSL_PROVIDER *prov,
+ const char *name, const char *value)
+{
+ return infopair_add(&prov->parameters, name, value);
+}
+
+int ossl_provider_info_add_parameter(OSSL_PROVIDER_INFO *provinfo,
+ const char *name,
+ const char *value)
+{
+ return infopair_add(&provinfo->parameters, name, value);
+}
+
+/*
+ * Provider activation.
+ *
+ * What "activation" means depends on the provider form; for built in
+ * providers (in the library or the application alike), the provider
+ * can already be considered to be loaded, all that's needed is to
+ * initialize it. However, for dynamically loadable provider modules,
+ * we must first load that module.
+ *
+ * Built in modules are distinguished from dynamically loaded modules
+ * with an already assigned init function.
+ */
+static const OSSL_DISPATCH *core_dispatch; /* Define further down */
+
+int OSSL_PROVIDER_set_default_search_path(OSSL_LIB_CTX *libctx,
+ const char *path)
+{
+ struct provider_store_st *store;
+ char *p = NULL;
+
+ if (path != NULL) {
+ p = OPENSSL_strdup(path);
+ if (p == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ if ((store = get_provider_store(libctx)) != NULL
+ && CRYPTO_THREAD_write_lock(store->default_path_lock)) {
+ OPENSSL_free(store->default_path);
+ store->default_path = p;
+ CRYPTO_THREAD_unlock(store->default_path_lock);
+ return 1;
+ }
+ OPENSSL_free(p);
+ return 0;
+}
+
+/*
+ * Internal version that doesn't affect the store flags, and thereby avoid
+ * locking. Direct callers must remember to set the store flags when
+ * appropriate.
+ */
+static int provider_init(OSSL_PROVIDER *prov)
+{
+ const OSSL_DISPATCH *provider_dispatch = NULL;
+ void *tmp_provctx = NULL; /* safety measure */
+#ifndef OPENSSL_NO_ERR
+# ifndef FIPS_MODULE
+ OSSL_FUNC_provider_get_reason_strings_fn *p_get_reason_strings = NULL;
+# endif
+#endif
+ int ok = 0;
+
+ if (!ossl_assert(!prov->flag_initialized)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
+ goto end;
+ }
+
+ /*
+ * If the init function isn't set, it indicates that this provider is
+ * a loadable module.
+ */
+ if (prov->init_function == NULL) {
+#ifdef FIPS_MODULE
+ goto end;
+#else
+ if (prov->module == NULL) {
+ char *allocated_path = NULL;
+ const char *module_path = NULL;
+ char *merged_path = NULL;
+ const char *load_dir = NULL;
+ char *allocated_load_dir = NULL;
+ struct provider_store_st *store;
+
+ if ((prov->module = DSO_new()) == NULL) {
+ /* DSO_new() generates an error already */
+ goto end;
+ }
+
+ if ((store = get_provider_store(prov->libctx)) == NULL
+ || !CRYPTO_THREAD_read_lock(store->default_path_lock))
+ goto end;
+
+ if (store->default_path != NULL) {
+ allocated_load_dir = OPENSSL_strdup(store->default_path);
+ CRYPTO_THREAD_unlock(store->default_path_lock);
+ if (allocated_load_dir == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+ load_dir = allocated_load_dir;
+ } else {
+ CRYPTO_THREAD_unlock(store->default_path_lock);
+ }
+
+ if (load_dir == NULL) {
+ load_dir = ossl_safe_getenv("OPENSSL_MODULES");
+ if (load_dir == NULL)
+ load_dir = MODULESDIR;
+ }
+
+ DSO_ctrl(prov->module, DSO_CTRL_SET_FLAGS,
+ DSO_FLAG_NAME_TRANSLATION_EXT_ONLY, NULL);
+
+ module_path = prov->path;
+ if (module_path == NULL)
+ module_path = allocated_path =
+ DSO_convert_filename(prov->module, prov->name);
+ if (module_path != NULL)
+ merged_path = DSO_merge(prov->module, module_path, load_dir);
+
+ if (merged_path == NULL
+ || (DSO_load(prov->module, merged_path, NULL, 0)) == NULL) {
+ DSO_free(prov->module);
+ prov->module = NULL;
+ }
+
+ OPENSSL_free(merged_path);
+ OPENSSL_free(allocated_path);
+ OPENSSL_free(allocated_load_dir);
+ }
+
+ if (prov->module == NULL) {
+ /* DSO has already recorded errors, this is just a tracepoint */
+ ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_DSO_LIB,
+ "name=%s", prov->name);
+ goto end;
+ }
+
+ prov->init_function = (OSSL_provider_init_fn *)
+ DSO_bind_func(prov->module, "OSSL_provider_init");
+#endif
+ }
+
+ /* Check for and call the initialise function for the provider. */
+ if (prov->init_function == NULL) {
+ ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_UNSUPPORTED,
+ "name=%s, provider has no provider init function",
+ prov->name);
+ goto end;
+ }
+
+ if (!prov->init_function((OSSL_CORE_HANDLE *)prov, core_dispatch,
+ &provider_dispatch, &tmp_provctx)) {
+ ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INIT_FAIL,
+ "name=%s", prov->name);
+ goto end;
+ }
+ prov->provctx = tmp_provctx;
+ prov->dispatch = provider_dispatch;
+
+ for (; provider_dispatch->function_id != 0; provider_dispatch++) {
+ switch (provider_dispatch->function_id) {
+ case OSSL_FUNC_PROVIDER_TEARDOWN:
+ prov->teardown =
+ OSSL_FUNC_provider_teardown(provider_dispatch);
+ break;
+ case OSSL_FUNC_PROVIDER_GETTABLE_PARAMS:
+ prov->gettable_params =
+ OSSL_FUNC_provider_gettable_params(provider_dispatch);
+ break;
+ case OSSL_FUNC_PROVIDER_GET_PARAMS:
+ prov->get_params =
+ OSSL_FUNC_provider_get_params(provider_dispatch);
+ break;
+ case OSSL_FUNC_PROVIDER_SELF_TEST:
+ prov->self_test =
+ OSSL_FUNC_provider_self_test(provider_dispatch);
+ break;
+ case OSSL_FUNC_PROVIDER_GET_CAPABILITIES:
+ prov->get_capabilities =
+ OSSL_FUNC_provider_get_capabilities(provider_dispatch);
+ break;
+ case OSSL_FUNC_PROVIDER_QUERY_OPERATION:
+ prov->query_operation =
+ OSSL_FUNC_provider_query_operation(provider_dispatch);
+ break;
+ case OSSL_FUNC_PROVIDER_UNQUERY_OPERATION:
+ prov->unquery_operation =
+ OSSL_FUNC_provider_unquery_operation(provider_dispatch);
+ break;
+#ifndef OPENSSL_NO_ERR
+# ifndef FIPS_MODULE
+ case OSSL_FUNC_PROVIDER_GET_REASON_STRINGS:
+ p_get_reason_strings =
+ OSSL_FUNC_provider_get_reason_strings(provider_dispatch);
+ break;
+# endif
+#endif
+ }
+ }
+
+#ifndef OPENSSL_NO_ERR
+# ifndef FIPS_MODULE
+ if (p_get_reason_strings != NULL) {
+ const OSSL_ITEM *reasonstrings = p_get_reason_strings(prov->provctx);
+ size_t cnt, cnt2;
+
+ /*
+ * ERR_load_strings() handles ERR_STRING_DATA rather than OSSL_ITEM,
+ * although they are essentially the same type.
+ * Furthermore, ERR_load_strings() patches the array's error number
+ * with the error library number, so we need to make a copy of that
+ * array either way.
+ */
+ cnt = 0;
+ while (reasonstrings[cnt].id != 0) {
+ if (ERR_GET_LIB(reasonstrings[cnt].id) != 0)
+ goto end;
+ cnt++;
+ }
+ cnt++; /* One for the terminating item */
+
+ /* Allocate one extra item for the "library" name */
+ prov->error_strings =
+ OPENSSL_zalloc(sizeof(ERR_STRING_DATA) * (cnt + 1));
+ if (prov->error_strings == NULL)
+ goto end;
+
+ /*
+ * Set the "library" name.
+ */
+ prov->error_strings[0].error = ERR_PACK(prov->error_lib, 0, 0);
+ prov->error_strings[0].string = prov->name;
+ /*
+ * Copy reasonstrings item 0..cnt-1 to prov->error_trings positions
+ * 1..cnt.
+ */
+ for (cnt2 = 1; cnt2 <= cnt; cnt2++) {
+ prov->error_strings[cnt2].error = (int)reasonstrings[cnt2-1].id;
+ prov->error_strings[cnt2].string = reasonstrings[cnt2-1].ptr;
+ }
+
+ ERR_load_strings(prov->error_lib, prov->error_strings);
+ }
+# endif
+#endif
+
+ /* With this flag set, this provider has become fully "loaded". */
+ prov->flag_initialized = 1;
+ ok = 1;
+
+ end:
+ return ok;
+}
+
+/*
+ * Deactivate a provider. If upcalls is 0 then we suppress any upcalls to a
+ * parent provider. If removechildren is 0 then we suppress any calls to remove
+ * child providers.
+ * Return -1 on failure and the activation count on success
+ */
+static int provider_deactivate(OSSL_PROVIDER *prov, int upcalls,
+ int removechildren)
+{
+ int count;
+ struct provider_store_st *store;
+#ifndef FIPS_MODULE
+ int freeparent = 0;
+#endif
+ int lock = 1;
+
+ if (!ossl_assert(prov != NULL))
+ return -1;
+
+ /*
+ * No need to lock if we've got no store because we've not been shared with
+ * other threads.
+ */
+ store = get_provider_store(prov->libctx);
+ if (store == NULL)
+ lock = 0;
+
+ if (lock && !CRYPTO_THREAD_read_lock(store->lock))
+ return -1;
+ if (lock && !CRYPTO_THREAD_write_lock(prov->flag_lock)) {
+ CRYPTO_THREAD_unlock(store->lock);
+ return -1;
+ }
+
+#ifndef FIPS_MODULE
+ if (prov->activatecnt >= 2 && prov->ischild && upcalls) {
+ /*
+ * We have had a direct activation in this child libctx so we need to
+ * now down the ref count in the parent provider. We do the actual down
+ * ref outside of the flag_lock, since it could involve getting other
+ * locks.
+ */
+ freeparent = 1;
+ }
+#endif
+
+ if ((count = --prov->activatecnt) < 1)
+ prov->flag_activated = 0;
+#ifndef FIPS_MODULE
+ else
+ removechildren = 0;
+#endif
+
+#ifndef FIPS_MODULE
+ if (removechildren && store != NULL) {
+ int i, max = sk_OSSL_PROVIDER_CHILD_CB_num(store->child_cbs);
+ OSSL_PROVIDER_CHILD_CB *child_cb;
+
+ for (i = 0; i < max; i++) {
+ child_cb = sk_OSSL_PROVIDER_CHILD_CB_value(store->child_cbs, i);
+ child_cb->remove_cb((OSSL_CORE_HANDLE *)prov, child_cb->cbdata);
+ }
+ }
+#endif
+ if (lock) {
+ CRYPTO_THREAD_unlock(prov->flag_lock);
+ CRYPTO_THREAD_unlock(store->lock);
+ }
+#ifndef FIPS_MODULE
+ if (freeparent)
+ ossl_provider_free_parent(prov, 1);
+#endif
+
+ /* We don't deinit here, that's done in ossl_provider_free() */
+ return count;
+}
+
+/*
+ * Activate a provider.
+ * Return -1 on failure and the activation count on success
+ */
+static int provider_activate(OSSL_PROVIDER *prov, int lock, int upcalls)
+{
+ int count = -1;
+ struct provider_store_st *store;
+ int ret = 1;
+
+ store = prov->store;
+ /*
+ * If the provider hasn't been added to the store, then we don't need
+ * any locks because we've not shared it with other threads.
+ */
+ if (store == NULL) {
+ lock = 0;
+ if (!provider_init(prov))
+ return -1;
+ }
+
+#ifndef FIPS_MODULE
+ if (prov->ischild && upcalls && !ossl_provider_up_ref_parent(prov, 1))
+ return -1;
+#endif
+
+ if (lock && !CRYPTO_THREAD_read_lock(store->lock)) {
+#ifndef FIPS_MODULE
+ if (prov->ischild && upcalls)
+ ossl_provider_free_parent(prov, 1);
+#endif
+ return -1;
+ }
+
+ if (lock && !CRYPTO_THREAD_write_lock(prov->flag_lock)) {
+ CRYPTO_THREAD_unlock(store->lock);
+#ifndef FIPS_MODULE
+ if (prov->ischild && upcalls)
+ ossl_provider_free_parent(prov, 1);
+#endif
+ return -1;
+ }
+
+ count = ++prov->activatecnt;
+ prov->flag_activated = 1;
+
+ if (prov->activatecnt == 1 && store != NULL) {
+ ret = create_provider_children(prov);
+ }
+ if (lock) {
+ CRYPTO_THREAD_unlock(prov->flag_lock);
+ CRYPTO_THREAD_unlock(store->lock);
+ }
+
+ if (!ret)
+ return -1;
+
+ return count;
+}
+
+static int provider_flush_store_cache(const OSSL_PROVIDER *prov)
+{
+ struct provider_store_st *store;
+ int freeing;
+
+ if ((store = get_provider_store(prov->libctx)) == NULL)
+ return 0;
+
+ if (!CRYPTO_THREAD_read_lock(store->lock))
+ return 0;
+ freeing = store->freeing;
+ CRYPTO_THREAD_unlock(store->lock);
+
+ if (!freeing) {
+ int acc
+ = evp_method_store_cache_flush(prov->libctx)
+#ifndef FIPS_MODULE
+ + ossl_encoder_store_cache_flush(prov->libctx)
+ + ossl_decoder_store_cache_flush(prov->libctx)
+ + ossl_store_loader_store_cache_flush(prov->libctx)
+#endif
+ ;
+
+#ifndef FIPS_MODULE
+ return acc == 4;
+#else
+ return acc == 1;
+#endif
+ }
+ return 1;
+}
+
+static int provider_remove_store_methods(OSSL_PROVIDER *prov)
+{
+ struct provider_store_st *store;
+ int freeing;
+
+ if ((store = get_provider_store(prov->libctx)) == NULL)
+ return 0;
+
+ if (!CRYPTO_THREAD_read_lock(store->lock))
+ return 0;
+ freeing = store->freeing;
+ CRYPTO_THREAD_unlock(store->lock);
+
+ if (!freeing) {
+ int acc;
+
+ if (!CRYPTO_THREAD_write_lock(prov->opbits_lock))
+ return 0;
+ OPENSSL_free(prov->operation_bits);
+ prov->operation_bits = NULL;
+ prov->operation_bits_sz = 0;
+ CRYPTO_THREAD_unlock(prov->opbits_lock);
+
+ acc = evp_method_store_remove_all_provided(prov)
+#ifndef FIPS_MODULE
+ + ossl_encoder_store_remove_all_provided(prov)
+ + ossl_decoder_store_remove_all_provided(prov)
+ + ossl_store_loader_store_remove_all_provided(prov)
+#endif
+ ;
+
+#ifndef FIPS_MODULE
+ return acc == 4;
+#else
+ return acc == 1;
+#endif
+ }
+ return 1;
+}
+
+int ossl_provider_activate(OSSL_PROVIDER *prov, int upcalls, int aschild)
+{
+ int count;
+
+ if (prov == NULL)
+ return 0;
+#ifndef FIPS_MODULE
+ /*
+ * If aschild is true, then we only actually do the activation if the
+ * provider is a child. If its not, this is still success.
+ */
+ if (aschild && !prov->ischild)
+ return 1;
+#endif
+ if ((count = provider_activate(prov, 1, upcalls)) > 0)
+ return count == 1 ? provider_flush_store_cache(prov) : 1;
+
+ return 0;
+}
+
+int ossl_provider_deactivate(OSSL_PROVIDER *prov, int removechildren)
+{
+ int count;
+
+ if (prov == NULL
+ || (count = provider_deactivate(prov, 1, removechildren)) < 0)
+ return 0;
+ return count == 0 ? provider_remove_store_methods(prov) : 1;
+}
+
+void *ossl_provider_ctx(const OSSL_PROVIDER *prov)
+{
+ return prov != NULL ? prov->provctx : NULL;
+}
+
+/*
+ * This function only does something once when store->use_fallbacks == 1,
+ * and then sets store->use_fallbacks = 0, so the second call and so on is
+ * effectively a no-op.
+ */
+static int provider_activate_fallbacks(struct provider_store_st *store)
+{
+ int use_fallbacks;
+ int activated_fallback_count = 0;
+ int ret = 0;
+ const OSSL_PROVIDER_INFO *p;
+
+ if (!CRYPTO_THREAD_read_lock(store->lock))
+ return 0;
+ use_fallbacks = store->use_fallbacks;
+ CRYPTO_THREAD_unlock(store->lock);
+ if (!use_fallbacks)
+ return 1;
+
+ if (!CRYPTO_THREAD_write_lock(store->lock))
+ return 0;
+ /* Check again, just in case another thread changed it */
+ use_fallbacks = store->use_fallbacks;
+ if (!use_fallbacks) {
+ CRYPTO_THREAD_unlock(store->lock);
+ return 1;
+ }
+
+ for (p = ossl_predefined_providers; p->name != NULL; p++) {
+ OSSL_PROVIDER *prov = NULL;
+
+ if (!p->is_fallback)
+ continue;
+ /*
+ * We use the internal constructor directly here,
+ * otherwise we get a call loop
+ */
+ prov = provider_new(p->name, p->init, NULL);
+ if (prov == NULL)
+ goto err;
+ prov->libctx = store->libctx;
+#ifndef FIPS_MODULE
+ prov->error_lib = ERR_get_next_error_library();
+#endif
+
+ /*
+ * We are calling provider_activate while holding the store lock. This
+ * means the init function will be called while holding a lock. Normally
+ * we try to avoid calling a user callback while holding a lock.
+ * However, fallbacks are never third party providers so we accept this.
+ */
+ if (provider_activate(prov, 0, 0) < 0) {
+ ossl_provider_free(prov);
+ goto err;
+ }
+ prov->store = store;
+ if (sk_OSSL_PROVIDER_push(store->providers, prov) == 0) {
+ ossl_provider_free(prov);
+ goto err;
+ }
+ activated_fallback_count++;
+ }
+
+ if (activated_fallback_count > 0) {
+ store->use_fallbacks = 0;
+ ret = 1;
+ }
+ err:
+ CRYPTO_THREAD_unlock(store->lock);
+ return ret;
+}
+
+int ossl_provider_doall_activated(OSSL_LIB_CTX *ctx,
+ int (*cb)(OSSL_PROVIDER *provider,
+ void *cbdata),
+ void *cbdata)
+{
+ int ret = 0, curr, max, ref = 0;
+ struct provider_store_st *store = get_provider_store(ctx);
+ STACK_OF(OSSL_PROVIDER) *provs = NULL;
+
+#ifndef FIPS_MODULE
+ /*
+ * Make sure any providers are loaded from config before we try to use
+ * them.
+ */
+ if (ossl_lib_ctx_is_default(ctx))
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+#endif
+
+ if (store == NULL)
+ return 1;
+ if (!provider_activate_fallbacks(store))
+ return 0;
+
+ /*
+ * Under lock, grab a copy of the provider list and up_ref each
+ * provider so that they don't disappear underneath us.
+ */
+ if (!CRYPTO_THREAD_read_lock(store->lock))
+ return 0;
+ provs = sk_OSSL_PROVIDER_dup(store->providers);
+ if (provs == NULL) {
+ CRYPTO_THREAD_unlock(store->lock);
+ return 0;
+ }
+ max = sk_OSSL_PROVIDER_num(provs);
+ /*
+ * We work backwards through the stack so that we can safely delete items
+ * as we go.
+ */
+ for (curr = max - 1; curr >= 0; curr--) {
+ OSSL_PROVIDER *prov = sk_OSSL_PROVIDER_value(provs, curr);
+
+ if (!CRYPTO_THREAD_write_lock(prov->flag_lock))
+ goto err_unlock;
+ if (prov->flag_activated) {
+ /*
+ * We call CRYPTO_UP_REF directly rather than ossl_provider_up_ref
+ * to avoid upping the ref count on the parent provider, which we
+ * must not do while holding locks.
+ */
+ if (CRYPTO_UP_REF(&prov->refcnt, &ref, prov->refcnt_lock) <= 0) {
+ CRYPTO_THREAD_unlock(prov->flag_lock);
+ goto err_unlock;
+ }
+ /*
+ * It's already activated, but we up the activated count to ensure
+ * it remains activated until after we've called the user callback.
+ * We do this with no locking (because we already hold the locks)
+ * and no upcalls (which must not be called when locks are held). In
+ * theory this could mean the parent provider goes inactive, whilst
+ * still activated in the child for a short period. That's ok.
+ */
+ if (provider_activate(prov, 0, 0) < 0) {
+ CRYPTO_DOWN_REF(&prov->refcnt, &ref, prov->refcnt_lock);
+ CRYPTO_THREAD_unlock(prov->flag_lock);
+ goto err_unlock;
+ }
+ } else {
+ sk_OSSL_PROVIDER_delete(provs, curr);
+ max--;
+ }
+ CRYPTO_THREAD_unlock(prov->flag_lock);
+ }
+ CRYPTO_THREAD_unlock(store->lock);
+
+ /*
+ * Now, we sweep through all providers not under lock
+ */
+ for (curr = 0; curr < max; curr++) {
+ OSSL_PROVIDER *prov = sk_OSSL_PROVIDER_value(provs, curr);
+
+ if (!cb(prov, cbdata)) {
+ curr = -1;
+ goto finish;
+ }
+ }
+ curr = -1;
+
+ ret = 1;
+ goto finish;
+
+ err_unlock:
+ CRYPTO_THREAD_unlock(store->lock);
+ finish:
+ /*
+ * The pop_free call doesn't do what we want on an error condition. We
+ * either start from the first item in the stack, or part way through if
+ * we only processed some of the items.
+ */
+ for (curr++; curr < max; curr++) {
+ OSSL_PROVIDER *prov = sk_OSSL_PROVIDER_value(provs, curr);
+
+ provider_deactivate(prov, 0, 1);
+ /*
+ * As above where we did the up-ref, we don't call ossl_provider_free
+ * to avoid making upcalls. There should always be at least one ref
+ * to the provider in the store, so this should never drop to 0.
+ */
+ CRYPTO_DOWN_REF(&prov->refcnt, &ref, prov->refcnt_lock);
+ /*
+ * Not much we can do if this assert ever fails. So we don't use
+ * ossl_assert here.
+ */
+ assert(ref > 0);
+ }
+ sk_OSSL_PROVIDER_free(provs);
+ return ret;
+}
+
+int OSSL_PROVIDER_available(OSSL_LIB_CTX *libctx, const char *name)
+{
+ OSSL_PROVIDER *prov = NULL;
+ int available = 0;
+ struct provider_store_st *store = get_provider_store(libctx);
+
+ if (store == NULL || !provider_activate_fallbacks(store))
+ return 0;
+
+ prov = ossl_provider_find(libctx, name, 0);
+ if (prov != NULL) {
+ if (!CRYPTO_THREAD_read_lock(prov->flag_lock))
+ return 0;
+ available = prov->flag_activated;
+ CRYPTO_THREAD_unlock(prov->flag_lock);
+ ossl_provider_free(prov);
+ }
+ return available;
+}
+
+/* Setters of Provider Object data */
+int ossl_provider_set_fallback(OSSL_PROVIDER *prov)
+{
+ if (prov == NULL)
+ return 0;
+
+ prov->flag_fallback = 1;
+ return 1;
+}
+
+/* Getters of Provider Object data */
+const char *ossl_provider_name(const OSSL_PROVIDER *prov)
+{
+ return prov->name;
+}
+
+const DSO *ossl_provider_dso(const OSSL_PROVIDER *prov)
+{
+ return prov->module;
+}
+
+const char *ossl_provider_module_name(const OSSL_PROVIDER *prov)
+{
+#ifdef FIPS_MODULE
+ return NULL;
+#else
+ return DSO_get_filename(prov->module);
+#endif
+}
+
+const char *ossl_provider_module_path(const OSSL_PROVIDER *prov)
+{
+#ifdef FIPS_MODULE
+ return NULL;
+#else
+ /* FIXME: Ensure it's a full path */
+ return DSO_get_filename(prov->module);
+#endif
+}
+
+void *ossl_provider_prov_ctx(const OSSL_PROVIDER *prov)
+{
+ if (prov != NULL)
+ return prov->provctx;
+
+ return NULL;
+}
+
+const OSSL_DISPATCH *ossl_provider_get0_dispatch(const OSSL_PROVIDER *prov)
+{
+ if (prov != NULL)
+ return prov->dispatch;
+
+ return NULL;
+}
+
+OSSL_LIB_CTX *ossl_provider_libctx(const OSSL_PROVIDER *prov)
+{
+ return prov != NULL ? prov->libctx : NULL;
+}
+
+/* Wrappers around calls to the provider */
+void ossl_provider_teardown(const OSSL_PROVIDER *prov)
+{
+ if (prov->teardown != NULL
+#ifndef FIPS_MODULE
+ && !prov->ischild
+#endif
+ )
+ prov->teardown(prov->provctx);
+}
+
+const OSSL_PARAM *ossl_provider_gettable_params(const OSSL_PROVIDER *prov)
+{
+ return prov->gettable_params == NULL
+ ? NULL : prov->gettable_params(prov->provctx);
+}
+
+int ossl_provider_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[])
+{
+ return prov->get_params == NULL
+ ? 0 : prov->get_params(prov->provctx, params);
+}
+
+int ossl_provider_self_test(const OSSL_PROVIDER *prov)
+{
+ int ret;
+
+ if (prov->self_test == NULL)
+ return 1;
+ ret = prov->self_test(prov->provctx);
+ if (ret == 0)
+ (void)provider_remove_store_methods((OSSL_PROVIDER *)prov);
+ return ret;
+}
+
+int ossl_provider_get_capabilities(const OSSL_PROVIDER *prov,
+ const char *capability,
+ OSSL_CALLBACK *cb,
+ void *arg)
+{
+ return prov->get_capabilities == NULL
+ ? 1 : prov->get_capabilities(prov->provctx, capability, cb, arg);
+}
+
+const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov,
+ int operation_id,
+ int *no_cache)
+{
+ const OSSL_ALGORITHM *res;
+
+ if (prov->query_operation == NULL)
+ return NULL;
+ res = prov->query_operation(prov->provctx, operation_id, no_cache);
+#if defined(OPENSSL_NO_CACHED_FETCH)
+ /* Forcing the non-caching of queries */
+ if (no_cache != NULL)
+ *no_cache = 1;
+#endif
+ return res;
+}
+
+void ossl_provider_unquery_operation(const OSSL_PROVIDER *prov,
+ int operation_id,
+ const OSSL_ALGORITHM *algs)
+{
+ if (prov->unquery_operation != NULL)
+ prov->unquery_operation(prov->provctx, operation_id, algs);
+}
+
+int ossl_provider_set_operation_bit(OSSL_PROVIDER *provider, size_t bitnum)
+{
+ size_t byte = bitnum / 8;
+ unsigned char bit = (1 << (bitnum % 8)) & 0xFF;
+
+ if (!CRYPTO_THREAD_write_lock(provider->opbits_lock))
+ return 0;
+ if (provider->operation_bits_sz <= byte) {
+ unsigned char *tmp = OPENSSL_realloc(provider->operation_bits,
+ byte + 1);
+
+ if (tmp == NULL) {
+ CRYPTO_THREAD_unlock(provider->opbits_lock);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ provider->operation_bits = tmp;
+ memset(provider->operation_bits + provider->operation_bits_sz,
+ '\0', byte + 1 - provider->operation_bits_sz);
+ provider->operation_bits_sz = byte + 1;
+ }
+ provider->operation_bits[byte] |= bit;
+ CRYPTO_THREAD_unlock(provider->opbits_lock);
+ return 1;
+}
+
+int ossl_provider_test_operation_bit(OSSL_PROVIDER *provider, size_t bitnum,
+ int *result)
+{
+ size_t byte = bitnum / 8;
+ unsigned char bit = (1 << (bitnum % 8)) & 0xFF;
+
+ if (!ossl_assert(result != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ *result = 0;
+ if (!CRYPTO_THREAD_read_lock(provider->opbits_lock))
+ return 0;
+ if (provider->operation_bits_sz > byte)
+ *result = ((provider->operation_bits[byte] & bit) != 0);
+ CRYPTO_THREAD_unlock(provider->opbits_lock);
+ return 1;
+}
+
+#ifndef FIPS_MODULE
+const OSSL_CORE_HANDLE *ossl_provider_get_parent(OSSL_PROVIDER *prov)
+{
+ return prov->handle;
+}
+
+int ossl_provider_is_child(const OSSL_PROVIDER *prov)
+{
+ return prov->ischild;
+}
+
+int ossl_provider_set_child(OSSL_PROVIDER *prov, const OSSL_CORE_HANDLE *handle)
+{
+ prov->handle = handle;
+ prov->ischild = 1;
+
+ return 1;
+}
+
+int ossl_provider_default_props_update(OSSL_LIB_CTX *libctx, const char *props)
+{
+#ifndef FIPS_MODULE
+ struct provider_store_st *store = NULL;
+ int i, max;
+ OSSL_PROVIDER_CHILD_CB *child_cb;
+
+ if ((store = get_provider_store(libctx)) == NULL)
+ return 0;
+
+ if (!CRYPTO_THREAD_read_lock(store->lock))
+ return 0;
+
+ max = sk_OSSL_PROVIDER_CHILD_CB_num(store->child_cbs);
+ for (i = 0; i < max; i++) {
+ child_cb = sk_OSSL_PROVIDER_CHILD_CB_value(store->child_cbs, i);
+ child_cb->global_props_cb(props, child_cb->cbdata);
+ }
+
+ CRYPTO_THREAD_unlock(store->lock);
+#endif
+ return 1;
+}
+
+static int ossl_provider_register_child_cb(const OSSL_CORE_HANDLE *handle,
+ int (*create_cb)(
+ const OSSL_CORE_HANDLE *provider,
+ void *cbdata),
+ int (*remove_cb)(
+ const OSSL_CORE_HANDLE *provider,
+ void *cbdata),
+ int (*global_props_cb)(
+ const char *props,
+ void *cbdata),
+ void *cbdata)
+{
+ /*
+ * This is really an OSSL_PROVIDER that we created and cast to
+ * OSSL_CORE_HANDLE originally. Therefore it is safe to cast it back.
+ */
+ OSSL_PROVIDER *thisprov = (OSSL_PROVIDER *)handle;
+ OSSL_PROVIDER *prov;
+ OSSL_LIB_CTX *libctx = thisprov->libctx;
+ struct provider_store_st *store = NULL;
+ int ret = 0, i, max;
+ OSSL_PROVIDER_CHILD_CB *child_cb;
+ char *propsstr = NULL;
+
+ if ((store = get_provider_store(libctx)) == NULL)
+ return 0;
+
+ child_cb = OPENSSL_malloc(sizeof(*child_cb));
+ if (child_cb == NULL)
+ return 0;
+ child_cb->prov = thisprov;
+ child_cb->create_cb = create_cb;
+ child_cb->remove_cb = remove_cb;
+ child_cb->global_props_cb = global_props_cb;
+ child_cb->cbdata = cbdata;
+
+ if (!CRYPTO_THREAD_write_lock(store->lock)) {
+ OPENSSL_free(child_cb);
+ return 0;
+ }
+ propsstr = evp_get_global_properties_str(libctx, 0);
+
+ if (propsstr != NULL) {
+ global_props_cb(propsstr, cbdata);
+ OPENSSL_free(propsstr);
+ }
+ max = sk_OSSL_PROVIDER_num(store->providers);
+ for (i = 0; i < max; i++) {
+ int activated;
+
+ prov = sk_OSSL_PROVIDER_value(store->providers, i);
+
+ if (!CRYPTO_THREAD_read_lock(prov->flag_lock))
+ break;
+ activated = prov->flag_activated;
+ CRYPTO_THREAD_unlock(prov->flag_lock);
+ /*
+ * We hold the store lock while calling the user callback. This means
+ * that the user callback must be short and simple and not do anything
+ * likely to cause a deadlock. We don't hold the flag_lock during this
+ * call. In theory this means that another thread could deactivate it
+ * while we are calling create. This is ok because the other thread
+ * will also call remove_cb, but won't be able to do so until we release
+ * the store lock.
+ */
+ if (activated && !create_cb((OSSL_CORE_HANDLE *)prov, cbdata))
+ break;
+ }
+ if (i == max) {
+ /* Success */
+ ret = sk_OSSL_PROVIDER_CHILD_CB_push(store->child_cbs, child_cb);
+ }
+ if (i != max || ret <= 0) {
+ /* Failed during creation. Remove everything we just added */
+ for (; i >= 0; i--) {
+ prov = sk_OSSL_PROVIDER_value(store->providers, i);
+ remove_cb((OSSL_CORE_HANDLE *)prov, cbdata);
+ }
+ OPENSSL_free(child_cb);
+ ret = 0;
+ }
+ CRYPTO_THREAD_unlock(store->lock);
+
+ return ret;
+}
+
+static void ossl_provider_deregister_child_cb(const OSSL_CORE_HANDLE *handle)
+{
+ /*
+ * This is really an OSSL_PROVIDER that we created and cast to
+ * OSSL_CORE_HANDLE originally. Therefore it is safe to cast it back.
+ */
+ OSSL_PROVIDER *thisprov = (OSSL_PROVIDER *)handle;
+ OSSL_LIB_CTX *libctx = thisprov->libctx;
+ struct provider_store_st *store = NULL;
+ int i, max;
+ OSSL_PROVIDER_CHILD_CB *child_cb;
+
+ if ((store = get_provider_store(libctx)) == NULL)
+ return;
+
+ if (!CRYPTO_THREAD_write_lock(store->lock))
+ return;
+ max = sk_OSSL_PROVIDER_CHILD_CB_num(store->child_cbs);
+ for (i = 0; i < max; i++) {
+ child_cb = sk_OSSL_PROVIDER_CHILD_CB_value(store->child_cbs, i);
+ if (child_cb->prov == thisprov) {
+ /* Found an entry */
+ sk_OSSL_PROVIDER_CHILD_CB_delete(store->child_cbs, i);
+ OPENSSL_free(child_cb);
+ break;
+ }
+ }
+ CRYPTO_THREAD_unlock(store->lock);
+}
+#endif
+
+/*-
+ * Core functions for the provider
+ * ===============================
+ *
+ * This is the set of functions that the core makes available to the provider
+ */
+
+/*
+ * This returns a list of Provider Object parameters with their types, for
+ * discovery. We do not expect that many providers will use this, but one
+ * never knows.
+ */
+static const OSSL_PARAM param_types[] = {
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_CORE_VERSION, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_CORE_PROV_NAME, OSSL_PARAM_UTF8_PTR,
+ NULL, 0),
+#ifndef FIPS_MODULE
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_CORE_MODULE_FILENAME, OSSL_PARAM_UTF8_PTR,
+ NULL, 0),
+#endif
+ OSSL_PARAM_END
+};
+
+/*
+ * Forward declare all the functions that are provided aa dispatch.
+ * This ensures that the compiler will complain if they aren't defined
+ * with the correct signature.
+ */
+static OSSL_FUNC_core_gettable_params_fn core_gettable_params;
+static OSSL_FUNC_core_get_params_fn core_get_params;
+static OSSL_FUNC_core_get_libctx_fn core_get_libctx;
+static OSSL_FUNC_core_thread_start_fn core_thread_start;
+#ifndef FIPS_MODULE
+static OSSL_FUNC_core_new_error_fn core_new_error;
+static OSSL_FUNC_core_set_error_debug_fn core_set_error_debug;
+static OSSL_FUNC_core_vset_error_fn core_vset_error;
+static OSSL_FUNC_core_set_error_mark_fn core_set_error_mark;
+static OSSL_FUNC_core_clear_last_error_mark_fn core_clear_last_error_mark;
+static OSSL_FUNC_core_pop_error_to_mark_fn core_pop_error_to_mark;
+OSSL_FUNC_BIO_new_file_fn ossl_core_bio_new_file;
+OSSL_FUNC_BIO_new_membuf_fn ossl_core_bio_new_mem_buf;
+OSSL_FUNC_BIO_read_ex_fn ossl_core_bio_read_ex;
+OSSL_FUNC_BIO_write_ex_fn ossl_core_bio_write_ex;
+OSSL_FUNC_BIO_gets_fn ossl_core_bio_gets;
+OSSL_FUNC_BIO_puts_fn ossl_core_bio_puts;
+OSSL_FUNC_BIO_up_ref_fn ossl_core_bio_up_ref;
+OSSL_FUNC_BIO_free_fn ossl_core_bio_free;
+OSSL_FUNC_BIO_vprintf_fn ossl_core_bio_vprintf;
+OSSL_FUNC_BIO_vsnprintf_fn BIO_vsnprintf;
+static OSSL_FUNC_self_test_cb_fn core_self_test_get_callback;
+OSSL_FUNC_get_entropy_fn ossl_rand_get_entropy;
+OSSL_FUNC_cleanup_entropy_fn ossl_rand_cleanup_entropy;
+OSSL_FUNC_get_nonce_fn ossl_rand_get_nonce;
+OSSL_FUNC_cleanup_nonce_fn ossl_rand_cleanup_nonce;
+#endif
+OSSL_FUNC_CRYPTO_malloc_fn CRYPTO_malloc;
+OSSL_FUNC_CRYPTO_zalloc_fn CRYPTO_zalloc;
+OSSL_FUNC_CRYPTO_free_fn CRYPTO_free;
+OSSL_FUNC_CRYPTO_clear_free_fn CRYPTO_clear_free;
+OSSL_FUNC_CRYPTO_realloc_fn CRYPTO_realloc;
+OSSL_FUNC_CRYPTO_clear_realloc_fn CRYPTO_clear_realloc;
+OSSL_FUNC_CRYPTO_secure_malloc_fn CRYPTO_secure_malloc;
+OSSL_FUNC_CRYPTO_secure_zalloc_fn CRYPTO_secure_zalloc;
+OSSL_FUNC_CRYPTO_secure_free_fn CRYPTO_secure_free;
+OSSL_FUNC_CRYPTO_secure_clear_free_fn CRYPTO_secure_clear_free;
+OSSL_FUNC_CRYPTO_secure_allocated_fn CRYPTO_secure_allocated;
+OSSL_FUNC_OPENSSL_cleanse_fn OPENSSL_cleanse;
+#ifndef FIPS_MODULE
+OSSL_FUNC_provider_register_child_cb_fn ossl_provider_register_child_cb;
+OSSL_FUNC_provider_deregister_child_cb_fn ossl_provider_deregister_child_cb;
+static OSSL_FUNC_provider_name_fn core_provider_get0_name;
+static OSSL_FUNC_provider_get0_provider_ctx_fn core_provider_get0_provider_ctx;
+static OSSL_FUNC_provider_get0_dispatch_fn core_provider_get0_dispatch;
+static OSSL_FUNC_provider_up_ref_fn core_provider_up_ref_intern;
+static OSSL_FUNC_provider_free_fn core_provider_free_intern;
+static OSSL_FUNC_core_obj_add_sigid_fn core_obj_add_sigid;
+static OSSL_FUNC_core_obj_create_fn core_obj_create;
+#endif
+
+static const OSSL_PARAM *core_gettable_params(const OSSL_CORE_HANDLE *handle)
+{
+ return param_types;
+}
+
+static int core_get_params(const OSSL_CORE_HANDLE *handle, OSSL_PARAM params[])
+{
+ int i;
+ OSSL_PARAM *p;
+ /*
+ * We created this object originally and we know it is actually an
+ * OSSL_PROVIDER *, so the cast is safe
+ */
+ OSSL_PROVIDER *prov = (OSSL_PROVIDER *)handle;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_CORE_VERSION)) != NULL)
+ OSSL_PARAM_set_utf8_ptr(p, OPENSSL_VERSION_STR);
+ if ((p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_CORE_PROV_NAME)) != NULL)
+ OSSL_PARAM_set_utf8_ptr(p, prov->name);
+
+#ifndef FIPS_MODULE
+ if ((p = OSSL_PARAM_locate(params,
+ OSSL_PROV_PARAM_CORE_MODULE_FILENAME)) != NULL)
+ OSSL_PARAM_set_utf8_ptr(p, ossl_provider_module_path(prov));
+#endif
+
+ if (prov->parameters == NULL)
+ return 1;
+
+ for (i = 0; i < sk_INFOPAIR_num(prov->parameters); i++) {
+ INFOPAIR *pair = sk_INFOPAIR_value(prov->parameters, i);
+
+ if ((p = OSSL_PARAM_locate(params, pair->name)) != NULL)
+ OSSL_PARAM_set_utf8_ptr(p, pair->value);
+ }
+ return 1;
+}
+
+static OPENSSL_CORE_CTX *core_get_libctx(const OSSL_CORE_HANDLE *handle)
+{
+ /*
+ * We created this object originally and we know it is actually an
+ * OSSL_PROVIDER *, so the cast is safe
+ */
+ OSSL_PROVIDER *prov = (OSSL_PROVIDER *)handle;
+
+ /*
+ * Using ossl_provider_libctx would be wrong as that returns
+ * NULL for |prov| == NULL and NULL libctx has a special meaning
+ * that does not apply here. Here |prov| == NULL can happen only in
+ * case of a coding error.
+ */
+ assert(prov != NULL);
+ return (OPENSSL_CORE_CTX *)prov->libctx;
+}
+
+static int core_thread_start(const OSSL_CORE_HANDLE *handle,
+ OSSL_thread_stop_handler_fn handfn,
+ void *arg)
+{
+ /*
+ * We created this object originally and we know it is actually an
+ * OSSL_PROVIDER *, so the cast is safe
+ */
+ OSSL_PROVIDER *prov = (OSSL_PROVIDER *)handle;
+
+ return ossl_init_thread_start(prov, arg, handfn);
+}
+
+/*
+ * The FIPS module inner provider doesn't implement these. They aren't
+ * needed there, since the FIPS module upcalls are always the outer provider
+ * ones.
+ */
+#ifndef FIPS_MODULE
+/*
+ * These error functions should use |handle| to select the proper
+ * library context to report in the correct error stack if error
+ * stacks become tied to the library context.
+ * We cannot currently do that since there's no support for it in the
+ * ERR subsystem.
+ */
+static void core_new_error(const OSSL_CORE_HANDLE *handle)
+{
+ ERR_new();
+}
+
+static void core_set_error_debug(const OSSL_CORE_HANDLE *handle,
+ const char *file, int line, const char *func)
+{
+ ERR_set_debug(file, line, func);
+}
+
+static void core_vset_error(const OSSL_CORE_HANDLE *handle,
+ uint32_t reason, const char *fmt, va_list args)
+{
+ /*
+ * We created this object originally and we know it is actually an
+ * OSSL_PROVIDER *, so the cast is safe
+ */
+ OSSL_PROVIDER *prov = (OSSL_PROVIDER *)handle;
+
+ /*
+ * If the uppermost 8 bits are non-zero, it's an OpenSSL library
+ * error and will be treated as such. Otherwise, it's a new style
+ * provider error and will be treated as such.
+ */
+ if (ERR_GET_LIB(reason) != 0) {
+ ERR_vset_error(ERR_GET_LIB(reason), ERR_GET_REASON(reason), fmt, args);
+ } else {
+ ERR_vset_error(prov->error_lib, (int)reason, fmt, args);
+ }
+}
+
+static int core_set_error_mark(const OSSL_CORE_HANDLE *handle)
+{
+ return ERR_set_mark();
+}
+
+static int core_clear_last_error_mark(const OSSL_CORE_HANDLE *handle)
+{
+ return ERR_clear_last_mark();
+}
+
+static int core_pop_error_to_mark(const OSSL_CORE_HANDLE *handle)
+{
+ return ERR_pop_to_mark();
+}
+
+static void core_self_test_get_callback(OPENSSL_CORE_CTX *libctx,
+ OSSL_CALLBACK **cb, void **cbarg)
+{
+ OSSL_SELF_TEST_get_callback((OSSL_LIB_CTX *)libctx, cb, cbarg);
+}
+
+static const char *core_provider_get0_name(const OSSL_CORE_HANDLE *prov)
+{
+ return OSSL_PROVIDER_get0_name((const OSSL_PROVIDER *)prov);
+}
+
+static void *core_provider_get0_provider_ctx(const OSSL_CORE_HANDLE *prov)
+{
+ return OSSL_PROVIDER_get0_provider_ctx((const OSSL_PROVIDER *)prov);
+}
+
+static const OSSL_DISPATCH *
+core_provider_get0_dispatch(const OSSL_CORE_HANDLE *prov)
+{
+ return OSSL_PROVIDER_get0_dispatch((const OSSL_PROVIDER *)prov);
+}
+
+static int core_provider_up_ref_intern(const OSSL_CORE_HANDLE *prov,
+ int activate)
+{
+ return provider_up_ref_intern((OSSL_PROVIDER *)prov, activate);
+}
+
+static int core_provider_free_intern(const OSSL_CORE_HANDLE *prov,
+ int deactivate)
+{
+ return provider_free_intern((OSSL_PROVIDER *)prov, deactivate);
+}
+
+static int core_obj_add_sigid(const OSSL_CORE_HANDLE *prov,
+ const char *sign_name, const char *digest_name,
+ const char *pkey_name)
+{
+ int sign_nid = OBJ_txt2nid(sign_name);
+ int digest_nid = NID_undef;
+ int pkey_nid = OBJ_txt2nid(pkey_name);
+
+ if (digest_name != NULL && digest_name[0] != '\0'
+ && (digest_nid = OBJ_txt2nid(digest_name)) == NID_undef)
+ return 0;
+
+ if (sign_nid == NID_undef)
+ return 0;
+
+ /*
+ * Check if it already exists. This is a success if so (even if we don't
+ * have nids for the digest/pkey)
+ */
+ if (OBJ_find_sigid_algs(sign_nid, NULL, NULL))
+ return 1;
+
+ if (pkey_nid == NID_undef)
+ return 0;
+
+ return OBJ_add_sigid(sign_nid, digest_nid, pkey_nid);
+}
+
+static int core_obj_create(const OSSL_CORE_HANDLE *prov, const char *oid,
+ const char *sn, const char *ln)
+{
+ /* Check if it already exists and create it if not */
+ return OBJ_txt2nid(oid) != NID_undef
+ || OBJ_create(oid, sn, ln) != NID_undef;
+}
+#endif /* FIPS_MODULE */
+
+/*
+ * Functions provided by the core.
+ */
+static const OSSL_DISPATCH core_dispatch_[] = {
+ { OSSL_FUNC_CORE_GETTABLE_PARAMS, (void (*)(void))core_gettable_params },
+ { OSSL_FUNC_CORE_GET_PARAMS, (void (*)(void))core_get_params },
+ { OSSL_FUNC_CORE_GET_LIBCTX, (void (*)(void))core_get_libctx },
+ { OSSL_FUNC_CORE_THREAD_START, (void (*)(void))core_thread_start },
+#ifndef FIPS_MODULE
+ { OSSL_FUNC_CORE_NEW_ERROR, (void (*)(void))core_new_error },
+ { OSSL_FUNC_CORE_SET_ERROR_DEBUG, (void (*)(void))core_set_error_debug },
+ { OSSL_FUNC_CORE_VSET_ERROR, (void (*)(void))core_vset_error },
+ { OSSL_FUNC_CORE_SET_ERROR_MARK, (void (*)(void))core_set_error_mark },
+ { OSSL_FUNC_CORE_CLEAR_LAST_ERROR_MARK,
+ (void (*)(void))core_clear_last_error_mark },
+ { OSSL_FUNC_CORE_POP_ERROR_TO_MARK, (void (*)(void))core_pop_error_to_mark },
+ { OSSL_FUNC_BIO_NEW_FILE, (void (*)(void))ossl_core_bio_new_file },
+ { OSSL_FUNC_BIO_NEW_MEMBUF, (void (*)(void))ossl_core_bio_new_mem_buf },
+ { OSSL_FUNC_BIO_READ_EX, (void (*)(void))ossl_core_bio_read_ex },
+ { OSSL_FUNC_BIO_WRITE_EX, (void (*)(void))ossl_core_bio_write_ex },
+ { OSSL_FUNC_BIO_GETS, (void (*)(void))ossl_core_bio_gets },
+ { OSSL_FUNC_BIO_PUTS, (void (*)(void))ossl_core_bio_puts },
+ { OSSL_FUNC_BIO_CTRL, (void (*)(void))ossl_core_bio_ctrl },
+ { OSSL_FUNC_BIO_UP_REF, (void (*)(void))ossl_core_bio_up_ref },
+ { OSSL_FUNC_BIO_FREE, (void (*)(void))ossl_core_bio_free },
+ { OSSL_FUNC_BIO_VPRINTF, (void (*)(void))ossl_core_bio_vprintf },
+ { OSSL_FUNC_BIO_VSNPRINTF, (void (*)(void))BIO_vsnprintf },
+ { OSSL_FUNC_SELF_TEST_CB, (void (*)(void))core_self_test_get_callback },
+ { OSSL_FUNC_GET_ENTROPY, (void (*)(void))ossl_rand_get_entropy },
+ { OSSL_FUNC_CLEANUP_ENTROPY, (void (*)(void))ossl_rand_cleanup_entropy },
+ { OSSL_FUNC_GET_NONCE, (void (*)(void))ossl_rand_get_nonce },
+ { OSSL_FUNC_CLEANUP_NONCE, (void (*)(void))ossl_rand_cleanup_nonce },
+#endif
+ { OSSL_FUNC_CRYPTO_MALLOC, (void (*)(void))CRYPTO_malloc },
+ { OSSL_FUNC_CRYPTO_ZALLOC, (void (*)(void))CRYPTO_zalloc },
+ { OSSL_FUNC_CRYPTO_FREE, (void (*)(void))CRYPTO_free },
+ { OSSL_FUNC_CRYPTO_CLEAR_FREE, (void (*)(void))CRYPTO_clear_free },
+ { OSSL_FUNC_CRYPTO_REALLOC, (void (*)(void))CRYPTO_realloc },
+ { OSSL_FUNC_CRYPTO_CLEAR_REALLOC, (void (*)(void))CRYPTO_clear_realloc },
+ { OSSL_FUNC_CRYPTO_SECURE_MALLOC, (void (*)(void))CRYPTO_secure_malloc },
+ { OSSL_FUNC_CRYPTO_SECURE_ZALLOC, (void (*)(void))CRYPTO_secure_zalloc },
+ { OSSL_FUNC_CRYPTO_SECURE_FREE, (void (*)(void))CRYPTO_secure_free },
+ { OSSL_FUNC_CRYPTO_SECURE_CLEAR_FREE,
+ (void (*)(void))CRYPTO_secure_clear_free },
+ { OSSL_FUNC_CRYPTO_SECURE_ALLOCATED,
+ (void (*)(void))CRYPTO_secure_allocated },
+ { OSSL_FUNC_OPENSSL_CLEANSE, (void (*)(void))OPENSSL_cleanse },
+#ifndef FIPS_MODULE
+ { OSSL_FUNC_PROVIDER_REGISTER_CHILD_CB,
+ (void (*)(void))ossl_provider_register_child_cb },
+ { OSSL_FUNC_PROVIDER_DEREGISTER_CHILD_CB,
+ (void (*)(void))ossl_provider_deregister_child_cb },
+ { OSSL_FUNC_PROVIDER_NAME,
+ (void (*)(void))core_provider_get0_name },
+ { OSSL_FUNC_PROVIDER_GET0_PROVIDER_CTX,
+ (void (*)(void))core_provider_get0_provider_ctx },
+ { OSSL_FUNC_PROVIDER_GET0_DISPATCH,
+ (void (*)(void))core_provider_get0_dispatch },
+ { OSSL_FUNC_PROVIDER_UP_REF,
+ (void (*)(void))core_provider_up_ref_intern },
+ { OSSL_FUNC_PROVIDER_FREE,
+ (void (*)(void))core_provider_free_intern },
+ { OSSL_FUNC_CORE_OBJ_ADD_SIGID, (void (*)(void))core_obj_add_sigid },
+ { OSSL_FUNC_CORE_OBJ_CREATE, (void (*)(void))core_obj_create },
+#endif
+ { 0, NULL }
+};
+static const OSSL_DISPATCH *core_dispatch = core_dispatch_;
diff --git a/crypto/provider_local.h b/crypto/provider_local.h
new file mode 100644
index 000000000000..e0bcbcb9f94e
--- /dev/null
+++ b/crypto/provider_local.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core.h>
+
+typedef struct {
+ char *name;
+ char *value;
+} INFOPAIR;
+DEFINE_STACK_OF(INFOPAIR)
+
+typedef struct {
+ char *name;
+ char *path;
+ OSSL_provider_init_fn *init;
+ STACK_OF(INFOPAIR) *parameters;
+ unsigned int is_fallback:1;
+} OSSL_PROVIDER_INFO;
+
+extern const OSSL_PROVIDER_INFO ossl_predefined_providers[];
+
+void ossl_provider_info_clear(OSSL_PROVIDER_INFO *info);
+int ossl_provider_info_add_to_store(OSSL_LIB_CTX *libctx,
+ OSSL_PROVIDER_INFO *entry);
+int ossl_provider_info_add_parameter(OSSL_PROVIDER_INFO *provinfo,
+ const char *name,
+ const char *value);
diff --git a/crypto/provider_predefined.c b/crypto/provider_predefined.c
new file mode 100644
index 000000000000..068e0b7cd96a
--- /dev/null
+++ b/crypto/provider_predefined.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core.h>
+#include "provider_local.h"
+
+OSSL_provider_init_fn ossl_default_provider_init;
+OSSL_provider_init_fn ossl_base_provider_init;
+OSSL_provider_init_fn ossl_null_provider_init;
+OSSL_provider_init_fn ossl_fips_intern_provider_init;
+#ifdef STATIC_LEGACY
+OSSL_provider_init_fn ossl_legacy_provider_init;
+#endif
+const OSSL_PROVIDER_INFO ossl_predefined_providers[] = {
+#ifdef FIPS_MODULE
+ { "fips", NULL, ossl_fips_intern_provider_init, NULL, 1 },
+#else
+ { "default", NULL, ossl_default_provider_init, NULL, 1 },
+# ifdef STATIC_LEGACY
+ { "legacy", NULL, ossl_legacy_provider_init, NULL, 0 },
+# endif
+ { "base", NULL, ossl_base_provider_init, NULL, 0 },
+ { "null", NULL, ossl_null_provider_init, NULL, 0 },
+#endif
+ { NULL, NULL, NULL, NULL, 0 }
+};
diff --git a/crypto/punycode.c b/crypto/punycode.c
new file mode 100644
index 000000000000..2de32dc18873
--- /dev/null
+++ b/crypto/punycode.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+#include <openssl/e_os2.h>
+#include "crypto/punycode.h"
+
+static const unsigned int base = 36;
+static const unsigned int tmin = 1;
+static const unsigned int tmax = 26;
+static const unsigned int skew = 38;
+static const unsigned int damp = 700;
+static const unsigned int initial_bias = 72;
+static const unsigned int initial_n = 0x80;
+static const unsigned int maxint = 0xFFFFFFFF;
+static const char delimiter = '-';
+
+#define LABEL_BUF_SIZE 512
+
+/*-
+ * Pseudocode:
+ *
+ * function adapt(delta,numpoints,firsttime):
+ * if firsttime then let delta = delta div damp
+ * else let delta = delta div 2
+ * let delta = delta + (delta div numpoints)
+ * let k = 0
+ * while delta > ((base - tmin) * tmax) div 2 do begin
+ * let delta = delta div (base - tmin)
+ * let k = k + base
+ * end
+ * return k + (((base - tmin + 1) * delta) div (delta + skew))
+ */
+
+static int adapt(unsigned int delta, unsigned int numpoints,
+ unsigned int firsttime)
+{
+ unsigned int k = 0;
+
+ delta = (firsttime) ? delta / damp : delta / 2;
+ delta = delta + delta / numpoints;
+
+ while (delta > ((base - tmin) * tmax) / 2) {
+ delta = delta / (base - tmin);
+ k = k + base;
+ }
+
+ return k + (((base - tmin + 1) * delta) / (delta + skew));
+}
+
+static ossl_inline int is_basic(unsigned int a)
+{
+ return (a < 0x80) ? 1 : 0;
+}
+
+/*-
+ * code points digit-values
+ * ------------ ----------------------
+ * 41..5A (A-Z) = 0 to 25, respectively
+ * 61..7A (a-z) = 0 to 25, respectively
+ * 30..39 (0-9) = 26 to 35, respectively
+ */
+static ossl_inline int digit_decoded(const unsigned char a)
+{
+ if (a >= 0x41 && a <= 0x5A)
+ return a - 0x41;
+
+ if (a >= 0x61 && a <= 0x7A)
+ return a - 0x61;
+
+ if (a >= 0x30 && a <= 0x39)
+ return a - 0x30 + 26;
+
+ return -1;
+}
+
+/*-
+ * Pseudocode:
+ *
+ * function ossl_punycode_decode
+ * let n = initial_n
+ * let i = 0
+ * let bias = initial_bias
+ * let output = an empty string indexed from 0
+ * consume all code points before the last delimiter (if there is one)
+ * and copy them to output, fail on any non-basic code point
+ * if more than zero code points were consumed then consume one more
+ * (which will be the last delimiter)
+ * while the input is not exhausted do begin
+ * let oldi = i
+ * let w = 1
+ * for k = base to infinity in steps of base do begin
+ * consume a code point, or fail if there was none to consume
+ * let digit = the code point's digit-value, fail if it has none
+ * let i = i + digit * w, fail on overflow
+ * let t = tmin if k <= bias {+ tmin}, or
+ * tmax if k >= bias + tmax, or k - bias otherwise
+ * if digit < t then break
+ * let w = w * (base - t), fail on overflow
+ * end
+ * let bias = adapt(i - oldi, length(output) + 1, test oldi is 0?)
+ * let n = n + i div (length(output) + 1), fail on overflow
+ * let i = i mod (length(output) + 1)
+ * {if n is a basic code point then fail}
+ * insert n into output at position i
+ * increment i
+ * end
+ */
+
+int ossl_punycode_decode(const char *pEncoded, const size_t enc_len,
+ unsigned int *pDecoded, unsigned int *pout_length)
+{
+ unsigned int n = initial_n;
+ unsigned int i = 0;
+ unsigned int bias = initial_bias;
+ size_t processed_in = 0, written_out = 0;
+ unsigned int max_out = *pout_length;
+ unsigned int basic_count = 0;
+ unsigned int loop;
+
+ for (loop = 0; loop < enc_len; loop++) {
+ if (pEncoded[loop] == delimiter)
+ basic_count = loop;
+ }
+
+ if (basic_count > 0) {
+ if (basic_count > max_out)
+ return 0;
+
+ for (loop = 0; loop < basic_count; loop++) {
+ if (is_basic(pEncoded[loop]) == 0)
+ return 0;
+
+ pDecoded[loop] = pEncoded[loop];
+ written_out++;
+ }
+ processed_in = basic_count + 1;
+ }
+
+ for (loop = processed_in; loop < enc_len;) {
+ unsigned int oldi = i;
+ unsigned int w = 1;
+ unsigned int k, t;
+ int digit;
+
+ for (k = base;; k += base) {
+ if (loop >= enc_len)
+ return 0;
+
+ digit = digit_decoded(pEncoded[loop]);
+ loop++;
+
+ if (digit < 0)
+ return 0;
+ if ((unsigned int)digit > (maxint - i) / w)
+ return 0;
+
+ i = i + digit * w;
+ t = (k <= bias) ? tmin : (k >= bias + tmax) ? tmax : k - bias;
+
+ if ((unsigned int)digit < t)
+ break;
+
+ if (w > maxint / (base - t))
+ return 0;
+ w = w * (base - t);
+ }
+
+ bias = adapt(i - oldi, written_out + 1, (oldi == 0));
+ if (i / (written_out + 1) > maxint - n)
+ return 0;
+ n = n + i / (written_out + 1);
+ i %= (written_out + 1);
+
+ if (written_out >= max_out)
+ return 0;
+
+ memmove(pDecoded + i + 1, pDecoded + i,
+ (written_out - i) * sizeof(*pDecoded));
+ pDecoded[i] = n;
+ i++;
+ written_out++;
+ }
+
+ *pout_length = written_out;
+ return 1;
+}
+
+/*
+ * Encode a code point using UTF-8
+ * return number of bytes on success, 0 on failure
+ * (also produces U+FFFD, which uses 3 bytes on failure)
+ */
+static int codepoint2utf8(unsigned char *out, unsigned long utf)
+{
+ if (utf <= 0x7F) {
+ /* Plain ASCII */
+ out[0] = (unsigned char)utf;
+ out[1] = 0;
+ return 1;
+ } else if (utf <= 0x07FF) {
+ /* 2-byte unicode */
+ out[0] = (unsigned char)(((utf >> 6) & 0x1F) | 0xC0);
+ out[1] = (unsigned char)(((utf >> 0) & 0x3F) | 0x80);
+ out[2] = 0;
+ return 2;
+ } else if (utf <= 0xFFFF) {
+ /* 3-byte unicode */
+ out[0] = (unsigned char)(((utf >> 12) & 0x0F) | 0xE0);
+ out[1] = (unsigned char)(((utf >> 6) & 0x3F) | 0x80);
+ out[2] = (unsigned char)(((utf >> 0) & 0x3F) | 0x80);
+ out[3] = 0;
+ return 3;
+ } else if (utf <= 0x10FFFF) {
+ /* 4-byte unicode */
+ out[0] = (unsigned char)(((utf >> 18) & 0x07) | 0xF0);
+ out[1] = (unsigned char)(((utf >> 12) & 0x3F) | 0x80);
+ out[2] = (unsigned char)(((utf >> 6) & 0x3F) | 0x80);
+ out[3] = (unsigned char)(((utf >> 0) & 0x3F) | 0x80);
+ out[4] = 0;
+ return 4;
+ } else {
+ /* error - use replacement character */
+ out[0] = (unsigned char)0xEF;
+ out[1] = (unsigned char)0xBF;
+ out[2] = (unsigned char)0xBD;
+ out[3] = 0;
+ return 0;
+ }
+}
+
+/*-
+ * Return values:
+ * 1 - ok, *outlen contains valid buf length
+ * 0 - ok but buf was too short, *outlen contains valid buf length
+ * -1 - bad string passed
+ */
+
+int ossl_a2ulabel(const char *in, char *out, size_t *outlen)
+{
+ /*-
+ * Domain name has some parts consisting of ASCII chars joined with dot.
+ * If a part is shorter than 5 chars, it becomes U-label as is.
+ * If it does not start with xn--, it becomes U-label as is.
+ * Otherwise we try to decode it.
+ */
+ char *outptr = out;
+ const char *inptr = in;
+ size_t size = 0, maxsize;
+ int result = 1;
+ unsigned int i, j;
+ unsigned int buf[LABEL_BUF_SIZE]; /* It's a hostname */
+
+ if (out == NULL) {
+ result = 0;
+ maxsize = 0;
+ } else {
+ maxsize = *outlen;
+ }
+
+#define PUSHC(c) \
+ do \
+ if (size++ < maxsize) \
+ *outptr++ = c; \
+ else \
+ result = 0; \
+ while (0)
+
+ while (1) {
+ char *tmpptr = strchr(inptr, '.');
+ size_t delta = tmpptr != NULL ? (size_t)(tmpptr - inptr) : strlen(inptr);
+
+ if (strncmp(inptr, "xn--", 4) != 0) {
+ for (i = 0; i < delta + 1; i++)
+ PUSHC(inptr[i]);
+ } else {
+ unsigned int bufsize = LABEL_BUF_SIZE;
+
+ if (ossl_punycode_decode(inptr + 4, delta - 4, buf, &bufsize) <= 0)
+ return -1;
+
+ for (i = 0; i < bufsize; i++) {
+ unsigned char seed[6];
+ size_t utfsize = codepoint2utf8(seed, buf[i]);
+
+ if (utfsize == 0)
+ return -1;
+
+ for (j = 0; j < utfsize; j++)
+ PUSHC(seed[j]);
+ }
+
+ PUSHC(tmpptr != NULL ? '.' : '\0');
+ }
+
+ if (tmpptr == NULL)
+ break;
+
+ inptr = tmpptr + 1;
+ }
+#undef PUSHC
+
+ *outlen = size;
+ return result;
+}
+
+/*-
+ * a MUST be A-label
+ * u MUST be U-label
+ * Returns 0 if compared values are equal
+ * 1 if not
+ * -1 in case of errors
+ */
+
+int ossl_a2ucompare(const char *a, const char *u)
+{
+ char a_ulabel[LABEL_BUF_SIZE + 1];
+ size_t a_size = sizeof(a_ulabel);
+
+ if (ossl_a2ulabel(a, a_ulabel, &a_size) <= 0)
+ return -1;
+
+ return strcmp(a_ulabel, u) != 0;
+}
diff --git a/crypto/rand/build.info b/crypto/rand/build.info
index a4e7900bdbff..a74282516f24 100644
--- a/crypto/rand/build.info
+++ b/crypto/rand/build.info
@@ -1,6 +1,14 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- randfile.c rand_lib.c rand_err.c rand_egd.c \
- rand_win.c rand_unix.c rand_vms.c drbg_lib.c drbg_ctr.c
-INCLUDE[drbg_ctr.o]=../modes
+$COMMON=rand_lib.c
+$CRYPTO=randfile.c rand_err.c rand_deprecated.c prov_seed.c rand_pool.c
+
+IF[{- !$disabled{'egd'} -}]
+ $CRYPTO=$CRYPTO rand_egd.c
+ENDIF
+IF[{- !$disabled{'deprecated-3.0'} -}]
+ $CRYPTO=$CRYPTO rand_meth.c
+ENDIF
+
+SOURCE[../../libcrypto]=$COMMON $CRYPTO
+SOURCE[../../providers/libfips.a]=$COMMON
diff --git a/crypto/rand/drbg_ctr.c b/crypto/rand/drbg_ctr.c
deleted file mode 100644
index a757d0a258ab..000000000000
--- a/crypto/rand/drbg_ctr.c
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <openssl/crypto.h>
-#include <openssl/err.h>
-#include <openssl/rand.h>
-#include "modes_local.h"
-#include "internal/thread_once.h"
-#include "rand_local.h"
-
-/*
- * Implementation of NIST SP 800-90A CTR DRBG.
- */
-
-static void inc_128(RAND_DRBG_CTR *ctr)
-{
- unsigned char *p = &ctr->V[0];
- u32 n = 16, c = 1;
-
- do {
- --n;
- c += p[n];
- p[n] = (u8)c;
- c >>= 8;
- } while (n);
-}
-
-static void ctr_XOR(RAND_DRBG_CTR *ctr, const unsigned char *in, size_t inlen)
-{
- size_t i, n;
-
- if (in == NULL || inlen == 0)
- return;
-
- /*
- * Any zero padding will have no effect on the result as we
- * are XORing. So just process however much input we have.
- */
- n = inlen < ctr->keylen ? inlen : ctr->keylen;
- for (i = 0; i < n; i++)
- ctr->K[i] ^= in[i];
- if (inlen <= ctr->keylen)
- return;
-
- n = inlen - ctr->keylen;
- if (n > 16) {
- /* Should never happen */
- n = 16;
- }
- for (i = 0; i < n; i++)
- ctr->V[i] ^= in[i + ctr->keylen];
-}
-
-/*
- * Process a complete block using BCC algorithm of SP 800-90A 10.3.3
- */
-__owur static int ctr_BCC_block(RAND_DRBG_CTR *ctr, unsigned char *out,
- const unsigned char *in, int len)
-{
- int i, outlen = AES_BLOCK_SIZE;
-
- for (i = 0; i < len; i++)
- out[i] ^= in[i];
-
- if (!EVP_CipherUpdate(ctr->ctx_df, out, &outlen, out, len)
- || outlen != len)
- return 0;
- return 1;
-}
-
-
-/*
- * Handle several BCC operations for as much data as we need for K and X
- */
-__owur static int ctr_BCC_blocks(RAND_DRBG_CTR *ctr, const unsigned char *in)
-{
- unsigned char in_tmp[48];
- unsigned char num_of_blk = 2;
-
- memcpy(in_tmp, in, 16);
- memcpy(in_tmp + 16, in, 16);
- if (ctr->keylen != 16) {
- memcpy(in_tmp + 32, in, 16);
- num_of_blk = 3;
- }
- return ctr_BCC_block(ctr, ctr->KX, in_tmp, AES_BLOCK_SIZE * num_of_blk);
-}
-
-/*
- * Initialise BCC blocks: these have the value 0,1,2 in leftmost positions:
- * see 10.3.1 stage 7.
- */
-__owur static int ctr_BCC_init(RAND_DRBG_CTR *ctr)
-{
- unsigned char bltmp[48] = {0};
- unsigned char num_of_blk;
-
- memset(ctr->KX, 0, 48);
- num_of_blk = ctr->keylen == 16 ? 2 : 3;
- bltmp[(AES_BLOCK_SIZE * 1) + 3] = 1;
- bltmp[(AES_BLOCK_SIZE * 2) + 3] = 2;
- return ctr_BCC_block(ctr, ctr->KX, bltmp, num_of_blk * AES_BLOCK_SIZE);
-}
-
-/*
- * Process several blocks into BCC algorithm, some possibly partial
- */
-__owur static int ctr_BCC_update(RAND_DRBG_CTR *ctr,
- const unsigned char *in, size_t inlen)
-{
- if (in == NULL || inlen == 0)
- return 1;
-
- /* If we have partial block handle it first */
- if (ctr->bltmp_pos) {
- size_t left = 16 - ctr->bltmp_pos;
-
- /* If we now have a complete block process it */
- if (inlen >= left) {
- memcpy(ctr->bltmp + ctr->bltmp_pos, in, left);
- if (!ctr_BCC_blocks(ctr, ctr->bltmp))
- return 0;
- ctr->bltmp_pos = 0;
- inlen -= left;
- in += left;
- }
- }
-
- /* Process zero or more complete blocks */
- for (; inlen >= 16; in += 16, inlen -= 16) {
- if (!ctr_BCC_blocks(ctr, in))
- return 0;
- }
-
- /* Copy any remaining partial block to the temporary buffer */
- if (inlen > 0) {
- memcpy(ctr->bltmp + ctr->bltmp_pos, in, inlen);
- ctr->bltmp_pos += inlen;
- }
- return 1;
-}
-
-__owur static int ctr_BCC_final(RAND_DRBG_CTR *ctr)
-{
- if (ctr->bltmp_pos) {
- memset(ctr->bltmp + ctr->bltmp_pos, 0, 16 - ctr->bltmp_pos);
- if (!ctr_BCC_blocks(ctr, ctr->bltmp))
- return 0;
- }
- return 1;
-}
-
-__owur static int ctr_df(RAND_DRBG_CTR *ctr,
- const unsigned char *in1, size_t in1len,
- const unsigned char *in2, size_t in2len,
- const unsigned char *in3, size_t in3len)
-{
- static unsigned char c80 = 0x80;
- size_t inlen;
- unsigned char *p = ctr->bltmp;
- int outlen = AES_BLOCK_SIZE;
-
- if (!ctr_BCC_init(ctr))
- return 0;
- if (in1 == NULL)
- in1len = 0;
- if (in2 == NULL)
- in2len = 0;
- if (in3 == NULL)
- in3len = 0;
- inlen = in1len + in2len + in3len;
- /* Initialise L||N in temporary block */
- *p++ = (inlen >> 24) & 0xff;
- *p++ = (inlen >> 16) & 0xff;
- *p++ = (inlen >> 8) & 0xff;
- *p++ = inlen & 0xff;
-
- /* NB keylen is at most 32 bytes */
- *p++ = 0;
- *p++ = 0;
- *p++ = 0;
- *p = (unsigned char)((ctr->keylen + 16) & 0xff);
- ctr->bltmp_pos = 8;
- if (!ctr_BCC_update(ctr, in1, in1len)
- || !ctr_BCC_update(ctr, in2, in2len)
- || !ctr_BCC_update(ctr, in3, in3len)
- || !ctr_BCC_update(ctr, &c80, 1)
- || !ctr_BCC_final(ctr))
- return 0;
- /* Set up key K */
- if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->KX, NULL, -1))
- return 0;
- /* X follows key K */
- if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX, &outlen, ctr->KX + ctr->keylen,
- AES_BLOCK_SIZE)
- || outlen != AES_BLOCK_SIZE)
- return 0;
- if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX + 16, &outlen, ctr->KX,
- AES_BLOCK_SIZE)
- || outlen != AES_BLOCK_SIZE)
- return 0;
- if (ctr->keylen != 16)
- if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX + 32, &outlen,
- ctr->KX + 16, AES_BLOCK_SIZE)
- || outlen != AES_BLOCK_SIZE)
- return 0;
- return 1;
-}
-
-/*
- * NB the no-df Update in SP800-90A specifies a constant input length
- * of seedlen, however other uses of this algorithm pad the input with
- * zeroes if necessary and have up to two parameters XORed together,
- * so we handle both cases in this function instead.
- */
-__owur static int ctr_update(RAND_DRBG *drbg,
- const unsigned char *in1, size_t in1len,
- const unsigned char *in2, size_t in2len,
- const unsigned char *nonce, size_t noncelen)
-{
- RAND_DRBG_CTR *ctr = &drbg->data.ctr;
- int outlen = AES_BLOCK_SIZE;
- unsigned char V_tmp[48], out[48];
- unsigned char len;
-
- /* correct key is already set up. */
- memcpy(V_tmp, ctr->V, 16);
- inc_128(ctr);
- memcpy(V_tmp + 16, ctr->V, 16);
- if (ctr->keylen == 16) {
- len = 32;
- } else {
- inc_128(ctr);
- memcpy(V_tmp + 32, ctr->V, 16);
- len = 48;
- }
- if (!EVP_CipherUpdate(ctr->ctx_ecb, out, &outlen, V_tmp, len)
- || outlen != len)
- return 0;
- memcpy(ctr->K, out, ctr->keylen);
- memcpy(ctr->V, out + ctr->keylen, 16);
-
- if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
- /* If no input reuse existing derived value */
- if (in1 != NULL || nonce != NULL || in2 != NULL)
- if (!ctr_df(ctr, in1, in1len, nonce, noncelen, in2, in2len))
- return 0;
- /* If this a reuse input in1len != 0 */
- if (in1len)
- ctr_XOR(ctr, ctr->KX, drbg->seedlen);
- } else {
- ctr_XOR(ctr, in1, in1len);
- ctr_XOR(ctr, in2, in2len);
- }
-
- if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->K, NULL, -1)
- || !EVP_CipherInit_ex(ctr->ctx_ctr, NULL, NULL, ctr->K, NULL, -1))
- return 0;
- return 1;
-}
-
-__owur static int drbg_ctr_instantiate(RAND_DRBG *drbg,
- const unsigned char *entropy, size_t entropylen,
- const unsigned char *nonce, size_t noncelen,
- const unsigned char *pers, size_t perslen)
-{
- RAND_DRBG_CTR *ctr = &drbg->data.ctr;
-
- if (entropy == NULL)
- return 0;
-
- memset(ctr->K, 0, sizeof(ctr->K));
- memset(ctr->V, 0, sizeof(ctr->V));
- if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->K, NULL, -1))
- return 0;
-
- inc_128(ctr);
- if (!ctr_update(drbg, entropy, entropylen, pers, perslen, nonce, noncelen))
- return 0;
- return 1;
-}
-
-__owur static int drbg_ctr_reseed(RAND_DRBG *drbg,
- const unsigned char *entropy, size_t entropylen,
- const unsigned char *adin, size_t adinlen)
-{
- RAND_DRBG_CTR *ctr = &drbg->data.ctr;
-
- if (entropy == NULL)
- return 0;
-
- inc_128(ctr);
- if (!ctr_update(drbg, entropy, entropylen, adin, adinlen, NULL, 0))
- return 0;
- return 1;
-}
-
-static void ctr96_inc(unsigned char *counter)
-{
- u32 n = 12, c = 1;
-
- do {
- --n;
- c += counter[n];
- counter[n] = (u8)c;
- c >>= 8;
- } while (n);
-}
-
-__owur static int drbg_ctr_generate(RAND_DRBG *drbg,
- unsigned char *out, size_t outlen,
- const unsigned char *adin, size_t adinlen)
-{
- RAND_DRBG_CTR *ctr = &drbg->data.ctr;
- unsigned int ctr32, blocks;
- int outl, buflen;
-
- if (adin != NULL && adinlen != 0) {
- inc_128(ctr);
-
- if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
- return 0;
- /* This means we reuse derived value */
- if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
- adin = NULL;
- adinlen = 1;
- }
- } else {
- adinlen = 0;
- }
-
- inc_128(ctr);
-
- if (outlen == 0) {
- inc_128(ctr);
-
- if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
- return 0;
- return 1;
- }
-
- memset(out, 0, outlen);
-
- do {
- if (!EVP_CipherInit_ex(ctr->ctx_ctr,
- NULL, NULL, NULL, ctr->V, -1))
- return 0;
-
- /*-
- * outlen has type size_t while EVP_CipherUpdate takes an
- * int argument and thus cannot be guaranteed to process more
- * than 2^31-1 bytes at a time. We process such huge generate
- * requests in 2^30 byte chunks, which is the greatest multiple
- * of AES block size lower than or equal to 2^31-1.
- */
- buflen = outlen > (1U << 30) ? (1U << 30) : outlen;
- blocks = (buflen + 15) / 16;
-
- ctr32 = GETU32(ctr->V + 12) + blocks;
- if (ctr32 < blocks) {
- /* 32-bit counter overflow into V. */
- if (ctr32 != 0) {
- blocks -= ctr32;
- buflen = blocks * 16;
- ctr32 = 0;
- }
- ctr96_inc(ctr->V);
- }
- PUTU32(ctr->V + 12, ctr32);
-
- if (!EVP_CipherUpdate(ctr->ctx_ctr, out, &outl, out, buflen)
- || outl != buflen)
- return 0;
-
- out += buflen;
- outlen -= buflen;
- } while (outlen);
-
- if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
- return 0;
- return 1;
-}
-
-static int drbg_ctr_uninstantiate(RAND_DRBG *drbg)
-{
- EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_ecb);
- EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_ctr);
- EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_df);
- OPENSSL_cleanse(&drbg->data.ctr, sizeof(drbg->data.ctr));
- return 1;
-}
-
-static RAND_DRBG_METHOD drbg_ctr_meth = {
- drbg_ctr_instantiate,
- drbg_ctr_reseed,
- drbg_ctr_generate,
- drbg_ctr_uninstantiate
-};
-
-int drbg_ctr_init(RAND_DRBG *drbg)
-{
- RAND_DRBG_CTR *ctr = &drbg->data.ctr;
- size_t keylen;
-
- switch (drbg->type) {
- default:
- /* This can't happen, but silence the compiler warning. */
- return 0;
- case NID_aes_128_ctr:
- keylen = 16;
- ctr->cipher_ecb = EVP_aes_128_ecb();
- ctr->cipher_ctr = EVP_aes_128_ctr();
- break;
- case NID_aes_192_ctr:
- keylen = 24;
- ctr->cipher_ecb = EVP_aes_192_ecb();
- ctr->cipher_ctr = EVP_aes_192_ctr();
- break;
- case NID_aes_256_ctr:
- keylen = 32;
- ctr->cipher_ecb = EVP_aes_256_ecb();
- ctr->cipher_ctr = EVP_aes_256_ctr();
- break;
- }
-
- drbg->meth = &drbg_ctr_meth;
-
- ctr->keylen = keylen;
- if (ctr->ctx_ecb == NULL)
- ctr->ctx_ecb = EVP_CIPHER_CTX_new();
- if (ctr->ctx_ctr == NULL)
- ctr->ctx_ctr = EVP_CIPHER_CTX_new();
- if (ctr->ctx_ecb == NULL || ctr->ctx_ctr == NULL
- || !EVP_CipherInit_ex(ctr->ctx_ecb,
- ctr->cipher_ecb, NULL, NULL, NULL, 1)
- || !EVP_CipherInit_ex(ctr->ctx_ctr,
- ctr->cipher_ctr, NULL, NULL, NULL, 1))
- return 0;
-
- drbg->meth = &drbg_ctr_meth;
- drbg->strength = keylen * 8;
- drbg->seedlen = keylen + 16;
-
- if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
- /* df initialisation */
- static const unsigned char df_key[32] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
- };
-
- if (ctr->ctx_df == NULL)
- ctr->ctx_df = EVP_CIPHER_CTX_new();
- if (ctr->ctx_df == NULL)
- return 0;
- /* Set key schedule for df_key */
- if (!EVP_CipherInit_ex(ctr->ctx_df,
- ctr->cipher_ecb, NULL, df_key, NULL, 1))
- return 0;
-
- drbg->min_entropylen = ctr->keylen;
- drbg->max_entropylen = DRBG_MAX_LENGTH;
- drbg->min_noncelen = drbg->min_entropylen / 2;
- drbg->max_noncelen = DRBG_MAX_LENGTH;
- drbg->max_perslen = DRBG_MAX_LENGTH;
- drbg->max_adinlen = DRBG_MAX_LENGTH;
- } else {
- drbg->min_entropylen = drbg->seedlen;
- drbg->max_entropylen = drbg->seedlen;
- /* Nonce not used */
- drbg->min_noncelen = 0;
- drbg->max_noncelen = 0;
- drbg->max_perslen = drbg->seedlen;
- drbg->max_adinlen = drbg->seedlen;
- }
-
- drbg->max_request = 1 << 16;
-
- return 1;
-}
diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c
deleted file mode 100644
index d32fa80cf89d..000000000000
--- a/crypto/rand/drbg_lib.c
+++ /dev/null
@@ -1,1148 +0,0 @@
-/*
- * Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <string.h>
-#include <openssl/crypto.h>
-#include <openssl/err.h>
-#include <openssl/rand.h>
-#include "rand_local.h"
-#include "internal/thread_once.h"
-#include "crypto/rand.h"
-#include "crypto/cryptlib.h"
-
-/*
- * Support framework for NIST SP 800-90A DRBG
- *
- * See manual page RAND_DRBG(7) for a general overview.
- *
- * The OpenSSL model is to have new and free functions, and that new
- * does all initialization. That is not the NIST model, which has
- * instantiation and un-instantiate, and re-use within a new/free
- * lifecycle. (No doubt this comes from the desire to support hardware
- * DRBG, where allocation of resources on something like an HSM is
- * a much bigger deal than just re-setting an allocated resource.)
- */
-
-/*
- * The three shared DRBG instances
- *
- * There are three shared DRBG instances: <master>, <public>, and <private>.
- */
-
-/*
- * The <master> DRBG
- *
- * Not used directly by the application, only for reseeding the two other
- * DRBGs. It reseeds itself by pulling either randomness from os entropy
- * sources or by consuming randomness which was added by RAND_add().
- *
- * The <master> DRBG is a global instance which is accessed concurrently by
- * all threads. The necessary locking is managed automatically by its child
- * DRBG instances during reseeding.
- */
-static RAND_DRBG *master_drbg;
-/*
- * The <public> DRBG
- *
- * Used by default for generating random bytes using RAND_bytes().
- *
- * The <public> DRBG is thread-local, i.e., there is one instance per thread.
- */
-static CRYPTO_THREAD_LOCAL public_drbg;
-/*
- * The <private> DRBG
- *
- * Used by default for generating private keys using RAND_priv_bytes()
- *
- * The <private> DRBG is thread-local, i.e., there is one instance per thread.
- */
-static CRYPTO_THREAD_LOCAL private_drbg;
-
-
-
-/* NIST SP 800-90A DRBG recommends the use of a personalization string. */
-static const char ossl_pers_string[] = "OpenSSL NIST SP 800-90A DRBG";
-
-static CRYPTO_ONCE rand_drbg_init = CRYPTO_ONCE_STATIC_INIT;
-
-
-
-static int rand_drbg_type = RAND_DRBG_TYPE;
-static unsigned int rand_drbg_flags = RAND_DRBG_FLAGS;
-
-static unsigned int master_reseed_interval = MASTER_RESEED_INTERVAL;
-static unsigned int slave_reseed_interval = SLAVE_RESEED_INTERVAL;
-
-static time_t master_reseed_time_interval = MASTER_RESEED_TIME_INTERVAL;
-static time_t slave_reseed_time_interval = SLAVE_RESEED_TIME_INTERVAL;
-
-/* A logical OR of all used DRBG flag bits (currently there is only one) */
-static const unsigned int rand_drbg_used_flags =
- RAND_DRBG_FLAG_CTR_NO_DF;
-
-static RAND_DRBG *drbg_setup(RAND_DRBG *parent);
-
-static RAND_DRBG *rand_drbg_new(int secure,
- int type,
- unsigned int flags,
- RAND_DRBG *parent);
-
-/*
- * Set/initialize |drbg| to be of type |type|, with optional |flags|.
- *
- * If |type| and |flags| are zero, use the defaults
- *
- * Returns 1 on success, 0 on failure.
- */
-int RAND_DRBG_set(RAND_DRBG *drbg, int type, unsigned int flags)
-{
- int ret = 1;
-
- if (type == 0 && flags == 0) {
- type = rand_drbg_type;
- flags = rand_drbg_flags;
- }
-
- /* If set is called multiple times - clear the old one */
- if (drbg->type != 0 && (type != drbg->type || flags != drbg->flags)) {
- drbg->meth->uninstantiate(drbg);
- rand_pool_free(drbg->adin_pool);
- drbg->adin_pool = NULL;
- }
-
- drbg->state = DRBG_UNINITIALISED;
- drbg->flags = flags;
- drbg->type = type;
-
- switch (type) {
- default:
- drbg->type = 0;
- drbg->flags = 0;
- drbg->meth = NULL;
- RANDerr(RAND_F_RAND_DRBG_SET, RAND_R_UNSUPPORTED_DRBG_TYPE);
- return 0;
- case 0:
- /* Uninitialized; that's okay. */
- drbg->meth = NULL;
- return 1;
- case NID_aes_128_ctr:
- case NID_aes_192_ctr:
- case NID_aes_256_ctr:
- ret = drbg_ctr_init(drbg);
- break;
- }
-
- if (ret == 0) {
- drbg->state = DRBG_ERROR;
- RANDerr(RAND_F_RAND_DRBG_SET, RAND_R_ERROR_INITIALISING_DRBG);
- }
- return ret;
-}
-
-/*
- * Set/initialize default |type| and |flag| for new drbg instances.
- *
- * Returns 1 on success, 0 on failure.
- */
-int RAND_DRBG_set_defaults(int type, unsigned int flags)
-{
- int ret = 1;
-
- switch (type) {
- default:
- RANDerr(RAND_F_RAND_DRBG_SET_DEFAULTS, RAND_R_UNSUPPORTED_DRBG_TYPE);
- return 0;
- case NID_aes_128_ctr:
- case NID_aes_192_ctr:
- case NID_aes_256_ctr:
- break;
- }
-
- if ((flags & ~rand_drbg_used_flags) != 0) {
- RANDerr(RAND_F_RAND_DRBG_SET_DEFAULTS, RAND_R_UNSUPPORTED_DRBG_FLAGS);
- return 0;
- }
-
- rand_drbg_type = type;
- rand_drbg_flags = flags;
-
- return ret;
-}
-
-
-/*
- * Allocate memory and initialize a new DRBG. The DRBG is allocated on
- * the secure heap if |secure| is nonzero and the secure heap is enabled.
- * The |parent|, if not NULL, will be used as random source for reseeding.
- *
- * Returns a pointer to the new DRBG instance on success, NULL on failure.
- */
-static RAND_DRBG *rand_drbg_new(int secure,
- int type,
- unsigned int flags,
- RAND_DRBG *parent)
-{
- RAND_DRBG *drbg = secure ? OPENSSL_secure_zalloc(sizeof(*drbg))
- : OPENSSL_zalloc(sizeof(*drbg));
-
- if (drbg == NULL) {
- RANDerr(RAND_F_RAND_DRBG_NEW, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- drbg->secure = secure && CRYPTO_secure_allocated(drbg);
- drbg->fork_id = openssl_get_fork_id();
- drbg->parent = parent;
-
- if (parent == NULL) {
- drbg->get_entropy = rand_drbg_get_entropy;
- drbg->cleanup_entropy = rand_drbg_cleanup_entropy;
-#ifndef RAND_DRBG_GET_RANDOM_NONCE
- drbg->get_nonce = rand_drbg_get_nonce;
- drbg->cleanup_nonce = rand_drbg_cleanup_nonce;
-#endif
-
- drbg->reseed_interval = master_reseed_interval;
- drbg->reseed_time_interval = master_reseed_time_interval;
- } else {
- drbg->get_entropy = rand_drbg_get_entropy;
- drbg->cleanup_entropy = rand_drbg_cleanup_entropy;
- /*
- * Do not provide nonce callbacks, the child DRBGs will
- * obtain their nonce using random bits from the parent.
- */
-
- drbg->reseed_interval = slave_reseed_interval;
- drbg->reseed_time_interval = slave_reseed_time_interval;
- }
-
- if (RAND_DRBG_set(drbg, type, flags) == 0)
- goto err;
-
- if (parent != NULL) {
- rand_drbg_lock(parent);
- if (drbg->strength > parent->strength) {
- /*
- * We currently don't support the algorithm from NIST SP 800-90C
- * 10.1.2 to use a weaker DRBG as source
- */
- rand_drbg_unlock(parent);
- RANDerr(RAND_F_RAND_DRBG_NEW, RAND_R_PARENT_STRENGTH_TOO_WEAK);
- goto err;
- }
- rand_drbg_unlock(parent);
- }
-
- return drbg;
-
- err:
- RAND_DRBG_free(drbg);
-
- return NULL;
-}
-
-RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent)
-{
- return rand_drbg_new(0, type, flags, parent);
-}
-
-RAND_DRBG *RAND_DRBG_secure_new(int type, unsigned int flags, RAND_DRBG *parent)
-{
- return rand_drbg_new(1, type, flags, parent);
-}
-
-/*
- * Uninstantiate |drbg| and free all memory.
- */
-void RAND_DRBG_free(RAND_DRBG *drbg)
-{
- if (drbg == NULL)
- return;
-
- if (drbg->meth != NULL)
- drbg->meth->uninstantiate(drbg);
- rand_pool_free(drbg->adin_pool);
- CRYPTO_THREAD_lock_free(drbg->lock);
- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DRBG, drbg, &drbg->ex_data);
-
- if (drbg->secure)
- OPENSSL_secure_clear_free(drbg, sizeof(*drbg));
- else
- OPENSSL_clear_free(drbg, sizeof(*drbg));
-}
-
-/*
- * Instantiate |drbg|, after it has been initialized. Use |pers| and
- * |perslen| as prediction-resistance input.
- *
- * Requires that drbg->lock is already locked for write, if non-null.
- *
- * Returns 1 on success, 0 on failure.
- */
-int RAND_DRBG_instantiate(RAND_DRBG *drbg,
- const unsigned char *pers, size_t perslen)
-{
- unsigned char *nonce = NULL, *entropy = NULL;
- size_t noncelen = 0, entropylen = 0;
- size_t min_entropy = drbg->strength;
- size_t min_entropylen = drbg->min_entropylen;
- size_t max_entropylen = drbg->max_entropylen;
-
- if (perslen > drbg->max_perslen) {
- RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
- RAND_R_PERSONALISATION_STRING_TOO_LONG);
- goto end;
- }
-
- if (drbg->meth == NULL) {
- RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
- RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED);
- goto end;
- }
-
- if (drbg->state != DRBG_UNINITIALISED) {
- RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
- drbg->state == DRBG_ERROR ? RAND_R_IN_ERROR_STATE
- : RAND_R_ALREADY_INSTANTIATED);
- goto end;
- }
-
- drbg->state = DRBG_ERROR;
-
- /*
- * NIST SP800-90Ar1 section 9.1 says you can combine getting the entropy
- * and nonce in 1 call by increasing the entropy with 50% and increasing
- * the minimum length to accommodate the length of the nonce.
- * We do this in case a nonce is require and get_nonce is NULL.
- */
- if (drbg->min_noncelen > 0 && drbg->get_nonce == NULL) {
- min_entropy += drbg->strength / 2;
- min_entropylen += drbg->min_noncelen;
- max_entropylen += drbg->max_noncelen;
- }
-
- if (drbg->get_entropy != NULL)
- entropylen = drbg->get_entropy(drbg, &entropy, min_entropy,
- min_entropylen, max_entropylen, 0);
- if (entropylen < min_entropylen
- || entropylen > max_entropylen) {
- RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_RETRIEVING_ENTROPY);
- goto end;
- }
-
- if (drbg->min_noncelen > 0 && drbg->get_nonce != NULL) {
- noncelen = drbg->get_nonce(drbg, &nonce, drbg->strength / 2,
- drbg->min_noncelen, drbg->max_noncelen);
- if (noncelen < drbg->min_noncelen || noncelen > drbg->max_noncelen) {
- RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_RETRIEVING_NONCE);
- goto end;
- }
- }
-
- if (!drbg->meth->instantiate(drbg, entropy, entropylen,
- nonce, noncelen, pers, perslen)) {
- RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_INSTANTIATING_DRBG);
- goto end;
- }
-
- drbg->state = DRBG_READY;
- drbg->generate_counter = 1;
- drbg->reseed_time = time(NULL);
- if (drbg->enable_reseed_propagation && drbg->parent == NULL)
- tsan_counter(&drbg->reseed_counter);
-
- end:
- if (entropy != NULL && drbg->cleanup_entropy != NULL)
- drbg->cleanup_entropy(drbg, entropy, entropylen);
- if (nonce != NULL && drbg->cleanup_nonce != NULL)
- drbg->cleanup_nonce(drbg, nonce, noncelen);
- if (drbg->state == DRBG_READY)
- return 1;
- return 0;
-}
-
-/*
- * Uninstantiate |drbg|. Must be instantiated before it can be used.
- *
- * Requires that drbg->lock is already locked for write, if non-null.
- *
- * Returns 1 on success, 0 on failure.
- */
-int RAND_DRBG_uninstantiate(RAND_DRBG *drbg)
-{
- if (drbg->meth == NULL) {
- drbg->state = DRBG_ERROR;
- RANDerr(RAND_F_RAND_DRBG_UNINSTANTIATE,
- RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED);
- return 0;
- }
-
- /* Clear the entire drbg->ctr struct, then reset some important
- * members of the drbg->ctr struct (e.g. keysize, df_ks) to their
- * initial values.
- */
- drbg->meth->uninstantiate(drbg);
- return RAND_DRBG_set(drbg, drbg->type, drbg->flags);
-}
-
-/*
- * Reseed |drbg|, mixing in the specified data
- *
- * Requires that drbg->lock is already locked for write, if non-null.
- *
- * Returns 1 on success, 0 on failure.
- */
-int RAND_DRBG_reseed(RAND_DRBG *drbg,
- const unsigned char *adin, size_t adinlen,
- int prediction_resistance)
-{
- unsigned char *entropy = NULL;
- size_t entropylen = 0;
-
- if (drbg->state == DRBG_ERROR) {
- RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_IN_ERROR_STATE);
- return 0;
- }
- if (drbg->state == DRBG_UNINITIALISED) {
- RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_NOT_INSTANTIATED);
- return 0;
- }
-
- if (adin == NULL) {
- adinlen = 0;
- } else if (adinlen > drbg->max_adinlen) {
- RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_ADDITIONAL_INPUT_TOO_LONG);
- return 0;
- }
-
- drbg->state = DRBG_ERROR;
- if (drbg->get_entropy != NULL)
- entropylen = drbg->get_entropy(drbg, &entropy, drbg->strength,
- drbg->min_entropylen,
- drbg->max_entropylen,
- prediction_resistance);
- if (entropylen < drbg->min_entropylen
- || entropylen > drbg->max_entropylen) {
- RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_ERROR_RETRIEVING_ENTROPY);
- goto end;
- }
-
- if (!drbg->meth->reseed(drbg, entropy, entropylen, adin, adinlen))
- goto end;
-
- drbg->state = DRBG_READY;
- drbg->generate_counter = 1;
- drbg->reseed_time = time(NULL);
- if (drbg->enable_reseed_propagation && drbg->parent == NULL)
- tsan_counter(&drbg->reseed_counter);
-
- end:
- if (entropy != NULL && drbg->cleanup_entropy != NULL)
- drbg->cleanup_entropy(drbg, entropy, entropylen);
- if (drbg->state == DRBG_READY)
- return 1;
- return 0;
-}
-
-/*
- * Restart |drbg|, using the specified entropy or additional input
- *
- * Tries its best to get the drbg instantiated by all means,
- * regardless of its current state.
- *
- * Optionally, a |buffer| of |len| random bytes can be passed,
- * which is assumed to contain at least |entropy| bits of entropy.
- *
- * If |entropy| > 0, the buffer content is used as entropy input.
- *
- * If |entropy| == 0, the buffer content is used as additional input
- *
- * Returns 1 on success, 0 on failure.
- *
- * This function is used internally only.
- */
-int rand_drbg_restart(RAND_DRBG *drbg,
- const unsigned char *buffer, size_t len, size_t entropy)
-{
- int reseeded = 0;
- const unsigned char *adin = NULL;
- size_t adinlen = 0;
-
- if (drbg->seed_pool != NULL) {
- RANDerr(RAND_F_RAND_DRBG_RESTART, ERR_R_INTERNAL_ERROR);
- drbg->state = DRBG_ERROR;
- rand_pool_free(drbg->seed_pool);
- drbg->seed_pool = NULL;
- return 0;
- }
-
- if (buffer != NULL) {
- if (entropy > 0) {
- if (drbg->max_entropylen < len) {
- RANDerr(RAND_F_RAND_DRBG_RESTART,
- RAND_R_ENTROPY_INPUT_TOO_LONG);
- drbg->state = DRBG_ERROR;
- return 0;
- }
-
- if (entropy > 8 * len) {
- RANDerr(RAND_F_RAND_DRBG_RESTART, RAND_R_ENTROPY_OUT_OF_RANGE);
- drbg->state = DRBG_ERROR;
- return 0;
- }
-
- /* will be picked up by the rand_drbg_get_entropy() callback */
- drbg->seed_pool = rand_pool_attach(buffer, len, entropy);
- if (drbg->seed_pool == NULL)
- return 0;
- } else {
- if (drbg->max_adinlen < len) {
- RANDerr(RAND_F_RAND_DRBG_RESTART,
- RAND_R_ADDITIONAL_INPUT_TOO_LONG);
- drbg->state = DRBG_ERROR;
- return 0;
- }
- adin = buffer;
- adinlen = len;
- }
- }
-
- /* repair error state */
- if (drbg->state == DRBG_ERROR)
- RAND_DRBG_uninstantiate(drbg);
-
- /* repair uninitialized state */
- if (drbg->state == DRBG_UNINITIALISED) {
- /* reinstantiate drbg */
- RAND_DRBG_instantiate(drbg,
- (const unsigned char *) ossl_pers_string,
- sizeof(ossl_pers_string) - 1);
- /* already reseeded. prevent second reseeding below */
- reseeded = (drbg->state == DRBG_READY);
- }
-
- /* refresh current state if entropy or additional input has been provided */
- if (drbg->state == DRBG_READY) {
- if (adin != NULL) {
- /*
- * mix in additional input without reseeding
- *
- * Similar to RAND_DRBG_reseed(), but the provided additional
- * data |adin| is mixed into the current state without pulling
- * entropy from the trusted entropy source using get_entropy().
- * This is not a reseeding in the strict sense of NIST SP 800-90A.
- */
- drbg->meth->reseed(drbg, adin, adinlen, NULL, 0);
- } else if (reseeded == 0) {
- /* do a full reseeding if it has not been done yet above */
- if (!RAND_DRBG_reseed(drbg, NULL, 0, 0)) {
- RANDerr(RAND_F_RAND_DRBG_RESTART, RAND_R_RESEED_ERROR);
- }
- }
- }
-
- rand_pool_free(drbg->seed_pool);
- drbg->seed_pool = NULL;
-
- return drbg->state == DRBG_READY;
-}
-
-/*
- * Generate |outlen| bytes into the buffer at |out|. Reseed if we need
- * to or if |prediction_resistance| is set. Additional input can be
- * sent in |adin| and |adinlen|.
- *
- * Requires that drbg->lock is already locked for write, if non-null.
- *
- * Returns 1 on success, 0 on failure.
- *
- */
-int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
- int prediction_resistance,
- const unsigned char *adin, size_t adinlen)
-{
- int fork_id;
- int reseed_required = 0;
-
- if (drbg->state != DRBG_READY) {
- /* try to recover from previous errors */
- rand_drbg_restart(drbg, NULL, 0, 0);
-
- if (drbg->state == DRBG_ERROR) {
- RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_IN_ERROR_STATE);
- return 0;
- }
- if (drbg->state == DRBG_UNINITIALISED) {
- RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_NOT_INSTANTIATED);
- return 0;
- }
- }
-
- if (outlen > drbg->max_request) {
- RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_REQUEST_TOO_LARGE_FOR_DRBG);
- return 0;
- }
- if (adinlen > drbg->max_adinlen) {
- RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_ADDITIONAL_INPUT_TOO_LONG);
- return 0;
- }
-
- fork_id = openssl_get_fork_id();
-
- if (drbg->fork_id != fork_id) {
- drbg->fork_id = fork_id;
- reseed_required = 1;
- }
-
- if (drbg->reseed_interval > 0) {
- if (drbg->generate_counter >= drbg->reseed_interval)
- reseed_required = 1;
- }
- if (drbg->reseed_time_interval > 0) {
- time_t now = time(NULL);
- if (now < drbg->reseed_time
- || now - drbg->reseed_time >= drbg->reseed_time_interval)
- reseed_required = 1;
- }
- if (drbg->enable_reseed_propagation && drbg->parent != NULL) {
- if (drbg->reseed_counter != tsan_load(&drbg->parent->reseed_counter))
- reseed_required = 1;
- }
-
- if (reseed_required || prediction_resistance) {
- if (!RAND_DRBG_reseed(drbg, adin, adinlen, prediction_resistance)) {
- RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_RESEED_ERROR);
- return 0;
- }
- adin = NULL;
- adinlen = 0;
- }
-
- if (!drbg->meth->generate(drbg, out, outlen, adin, adinlen)) {
- drbg->state = DRBG_ERROR;
- RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_GENERATE_ERROR);
- return 0;
- }
-
- drbg->generate_counter++;
-
- return 1;
-}
-
-/*
- * Generates |outlen| random bytes and stores them in |out|. It will
- * using the given |drbg| to generate the bytes.
- *
- * Requires that drbg->lock is already locked for write, if non-null.
- *
- * Returns 1 on success 0 on failure.
- */
-int RAND_DRBG_bytes(RAND_DRBG *drbg, unsigned char *out, size_t outlen)
-{
- unsigned char *additional = NULL;
- size_t additional_len;
- size_t chunk;
- size_t ret = 0;
-
- if (drbg->adin_pool == NULL) {
- if (drbg->type == 0)
- goto err;
- drbg->adin_pool = rand_pool_new(0, 0, 0, drbg->max_adinlen);
- if (drbg->adin_pool == NULL)
- goto err;
- }
-
- additional_len = rand_drbg_get_additional_data(drbg->adin_pool,
- &additional);
-
- for ( ; outlen > 0; outlen -= chunk, out += chunk) {
- chunk = outlen;
- if (chunk > drbg->max_request)
- chunk = drbg->max_request;
- ret = RAND_DRBG_generate(drbg, out, chunk, 0, additional, additional_len);
- if (!ret)
- goto err;
- }
- ret = 1;
-
- err:
- if (additional != NULL)
- rand_drbg_cleanup_additional_data(drbg->adin_pool, additional);
-
- return ret;
-}
-
-/*
- * Set the RAND_DRBG callbacks for obtaining entropy and nonce.
- *
- * Setting the callbacks is allowed only if the drbg has not been
- * initialized yet. Otherwise, the operation will fail.
- *
- * Returns 1 on success, 0 on failure.
- */
-int RAND_DRBG_set_callbacks(RAND_DRBG *drbg,
- RAND_DRBG_get_entropy_fn get_entropy,
- RAND_DRBG_cleanup_entropy_fn cleanup_entropy,
- RAND_DRBG_get_nonce_fn get_nonce,
- RAND_DRBG_cleanup_nonce_fn cleanup_nonce)
-{
- if (drbg->state != DRBG_UNINITIALISED)
- return 0;
- drbg->get_entropy = get_entropy;
- drbg->cleanup_entropy = cleanup_entropy;
- drbg->get_nonce = get_nonce;
- drbg->cleanup_nonce = cleanup_nonce;
- return 1;
-}
-
-/*
- * Set the reseed interval.
- *
- * The drbg will reseed automatically whenever the number of generate
- * requests exceeds the given reseed interval. If the reseed interval
- * is 0, then this feature is disabled.
- *
- * Returns 1 on success, 0 on failure.
- */
-int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, unsigned int interval)
-{
- if (interval > MAX_RESEED_INTERVAL)
- return 0;
- drbg->reseed_interval = interval;
- return 1;
-}
-
-/*
- * Set the reseed time interval.
- *
- * The drbg will reseed automatically whenever the time elapsed since
- * the last reseeding exceeds the given reseed time interval. For safety,
- * a reseeding will also occur if the clock has been reset to a smaller
- * value.
- *
- * Returns 1 on success, 0 on failure.
- */
-int RAND_DRBG_set_reseed_time_interval(RAND_DRBG *drbg, time_t interval)
-{
- if (interval > MAX_RESEED_TIME_INTERVAL)
- return 0;
- drbg->reseed_time_interval = interval;
- return 1;
-}
-
-/*
- * Set the default values for reseed (time) intervals of new DRBG instances
- *
- * The default values can be set independently for master DRBG instances
- * (without a parent) and slave DRBG instances (with parent).
- *
- * Returns 1 on success, 0 on failure.
- */
-
-int RAND_DRBG_set_reseed_defaults(
- unsigned int _master_reseed_interval,
- unsigned int _slave_reseed_interval,
- time_t _master_reseed_time_interval,
- time_t _slave_reseed_time_interval
- )
-{
- if (_master_reseed_interval > MAX_RESEED_INTERVAL
- || _slave_reseed_interval > MAX_RESEED_INTERVAL)
- return 0;
-
- if (_master_reseed_time_interval > MAX_RESEED_TIME_INTERVAL
- || _slave_reseed_time_interval > MAX_RESEED_TIME_INTERVAL)
- return 0;
-
- master_reseed_interval = _master_reseed_interval;
- slave_reseed_interval = _slave_reseed_interval;
-
- master_reseed_time_interval = _master_reseed_time_interval;
- slave_reseed_time_interval = _slave_reseed_time_interval;
-
- return 1;
-}
-
-/*
- * Locks the given drbg. Locking a drbg which does not have locking
- * enabled is considered a successful no-op.
- *
- * Returns 1 on success, 0 on failure.
- */
-int rand_drbg_lock(RAND_DRBG *drbg)
-{
- if (drbg->lock != NULL)
- return CRYPTO_THREAD_write_lock(drbg->lock);
-
- return 1;
-}
-
-/*
- * Unlocks the given drbg. Unlocking a drbg which does not have locking
- * enabled is considered a successful no-op.
- *
- * Returns 1 on success, 0 on failure.
- */
-int rand_drbg_unlock(RAND_DRBG *drbg)
-{
- if (drbg->lock != NULL)
- return CRYPTO_THREAD_unlock(drbg->lock);
-
- return 1;
-}
-
-/*
- * Enables locking for the given drbg
- *
- * Locking can only be enabled if the random generator
- * is in the uninitialized state.
- *
- * Returns 1 on success, 0 on failure.
- */
-int rand_drbg_enable_locking(RAND_DRBG *drbg)
-{
- if (drbg->state != DRBG_UNINITIALISED) {
- RANDerr(RAND_F_RAND_DRBG_ENABLE_LOCKING,
- RAND_R_DRBG_ALREADY_INITIALIZED);
- return 0;
- }
-
- if (drbg->lock == NULL) {
- if (drbg->parent != NULL && drbg->parent->lock == NULL) {
- RANDerr(RAND_F_RAND_DRBG_ENABLE_LOCKING,
- RAND_R_PARENT_LOCKING_NOT_ENABLED);
- return 0;
- }
-
- drbg->lock = CRYPTO_THREAD_lock_new();
- if (drbg->lock == NULL) {
- RANDerr(RAND_F_RAND_DRBG_ENABLE_LOCKING,
- RAND_R_FAILED_TO_CREATE_LOCK);
- return 0;
- }
- }
-
- return 1;
-}
-
-/*
- * Get and set the EXDATA
- */
-int RAND_DRBG_set_ex_data(RAND_DRBG *drbg, int idx, void *arg)
-{
- return CRYPTO_set_ex_data(&drbg->ex_data, idx, arg);
-}
-
-void *RAND_DRBG_get_ex_data(const RAND_DRBG *drbg, int idx)
-{
- return CRYPTO_get_ex_data(&drbg->ex_data, idx);
-}
-
-
-/*
- * The following functions provide a RAND_METHOD that works on the
- * global DRBG. They lock.
- */
-
-/*
- * Allocates a new global DRBG on the secure heap (if enabled) and
- * initializes it with default settings.
- *
- * Returns a pointer to the new DRBG instance on success, NULL on failure.
- */
-static RAND_DRBG *drbg_setup(RAND_DRBG *parent)
-{
- RAND_DRBG *drbg;
-
- drbg = RAND_DRBG_secure_new(rand_drbg_type, rand_drbg_flags, parent);
- if (drbg == NULL)
- return NULL;
-
- /* Only the master DRBG needs to have a lock */
- if (parent == NULL && rand_drbg_enable_locking(drbg) == 0)
- goto err;
-
- /* enable reseed propagation */
- drbg->enable_reseed_propagation = 1;
- drbg->reseed_counter = 1;
-
- /*
- * Ignore instantiation error to support just-in-time instantiation.
- *
- * The state of the drbg will be checked in RAND_DRBG_generate() and
- * an automatic recovery is attempted.
- */
- (void)RAND_DRBG_instantiate(drbg,
- (const unsigned char *) ossl_pers_string,
- sizeof(ossl_pers_string) - 1);
- return drbg;
-
-err:
- RAND_DRBG_free(drbg);
- return NULL;
-}
-
-/*
- * Initialize the global DRBGs on first use.
- * Returns 1 on success, 0 on failure.
- */
-DEFINE_RUN_ONCE_STATIC(do_rand_drbg_init)
-{
- /*
- * ensure that libcrypto is initialized, otherwise the
- * DRBG locks are not cleaned up properly
- */
- if (!OPENSSL_init_crypto(0, NULL))
- return 0;
-
- if (!CRYPTO_THREAD_init_local(&private_drbg, NULL))
- return 0;
-
- if (!CRYPTO_THREAD_init_local(&public_drbg, NULL))
- goto err1;
-
- master_drbg = drbg_setup(NULL);
- if (master_drbg == NULL)
- goto err2;
-
- return 1;
-
-err2:
- CRYPTO_THREAD_cleanup_local(&public_drbg);
-err1:
- CRYPTO_THREAD_cleanup_local(&private_drbg);
- return 0;
-}
-
-/* Clean up the global DRBGs before exit */
-void rand_drbg_cleanup_int(void)
-{
- if (master_drbg != NULL) {
- RAND_DRBG_free(master_drbg);
- master_drbg = NULL;
-
- CRYPTO_THREAD_cleanup_local(&private_drbg);
- CRYPTO_THREAD_cleanup_local(&public_drbg);
- }
-}
-
-void drbg_delete_thread_state(void)
-{
- RAND_DRBG *drbg;
-
- drbg = CRYPTO_THREAD_get_local(&public_drbg);
- CRYPTO_THREAD_set_local(&public_drbg, NULL);
- RAND_DRBG_free(drbg);
-
- drbg = CRYPTO_THREAD_get_local(&private_drbg);
- CRYPTO_THREAD_set_local(&private_drbg, NULL);
- RAND_DRBG_free(drbg);
-}
-
-/* Implements the default OpenSSL RAND_bytes() method */
-static int drbg_bytes(unsigned char *out, int count)
-{
- int ret;
- RAND_DRBG *drbg = RAND_DRBG_get0_public();
-
- if (drbg == NULL)
- return 0;
-
- ret = RAND_DRBG_bytes(drbg, out, count);
-
- return ret;
-}
-
-/*
- * Calculates the minimum length of a full entropy buffer
- * which is necessary to seed (i.e. instantiate) the DRBG
- * successfully.
- */
-size_t rand_drbg_seedlen(RAND_DRBG *drbg)
-{
- /*
- * If no os entropy source is available then RAND_seed(buffer, bufsize)
- * is expected to succeed if and only if the buffer length satisfies
- * the following requirements, which follow from the calculations
- * in RAND_DRBG_instantiate().
- */
- size_t min_entropy = drbg->strength;
- size_t min_entropylen = drbg->min_entropylen;
-
- /*
- * Extra entropy for the random nonce in the absence of a
- * get_nonce callback, see comment in RAND_DRBG_instantiate().
- */
- if (drbg->min_noncelen > 0 && drbg->get_nonce == NULL) {
- min_entropy += drbg->strength / 2;
- min_entropylen += drbg->min_noncelen;
- }
-
- /*
- * Convert entropy requirement from bits to bytes
- * (dividing by 8 without rounding upwards, because
- * all entropy requirements are divisible by 8).
- */
- min_entropy >>= 3;
-
- /* Return a value that satisfies both requirements */
- return min_entropy > min_entropylen ? min_entropy : min_entropylen;
-}
-
-/* Implements the default OpenSSL RAND_add() method */
-static int drbg_add(const void *buf, int num, double randomness)
-{
- int ret = 0;
- RAND_DRBG *drbg = RAND_DRBG_get0_master();
- size_t buflen;
- size_t seedlen;
-
- if (drbg == NULL)
- return 0;
-
- if (num < 0 || randomness < 0.0)
- return 0;
-
- rand_drbg_lock(drbg);
- seedlen = rand_drbg_seedlen(drbg);
-
- buflen = (size_t)num;
-
- if (buflen < seedlen || randomness < (double) seedlen) {
-#if defined(OPENSSL_RAND_SEED_NONE)
- /*
- * If no os entropy source is available, a reseeding will fail
- * inevitably. So we use a trick to mix the buffer contents into
- * the DRBG state without forcing a reseeding: we generate a
- * dummy random byte, using the buffer content as additional data.
- * Note: This won't work with RAND_DRBG_FLAG_CTR_NO_DF.
- */
- unsigned char dummy[1];
-
- ret = RAND_DRBG_generate(drbg, dummy, sizeof(dummy), 0, buf, buflen);
- rand_drbg_unlock(drbg);
- return ret;
-#else
- /*
- * If an os entropy source is available then we declare the buffer content
- * as additional data by setting randomness to zero and trigger a regular
- * reseeding.
- */
- randomness = 0.0;
-#endif
- }
-
-
- if (randomness > (double)seedlen) {
- /*
- * The purpose of this check is to bound |randomness| by a
- * relatively small value in order to prevent an integer
- * overflow when multiplying by 8 in the rand_drbg_restart()
- * call below. Note that randomness is measured in bytes,
- * not bits, so this value corresponds to eight times the
- * security strength.
- */
- randomness = (double)seedlen;
- }
-
- ret = rand_drbg_restart(drbg, buf, buflen, (size_t)(8 * randomness));
- rand_drbg_unlock(drbg);
-
- return ret;
-}
-
-/* Implements the default OpenSSL RAND_seed() method */
-static int drbg_seed(const void *buf, int num)
-{
- return drbg_add(buf, num, num);
-}
-
-/* Implements the default OpenSSL RAND_status() method */
-static int drbg_status(void)
-{
- int ret;
- RAND_DRBG *drbg = RAND_DRBG_get0_master();
-
- if (drbg == NULL)
- return 0;
-
- rand_drbg_lock(drbg);
- ret = drbg->state == DRBG_READY ? 1 : 0;
- rand_drbg_unlock(drbg);
- return ret;
-}
-
-/*
- * Get the master DRBG.
- * Returns pointer to the DRBG on success, NULL on failure.
- *
- */
-RAND_DRBG *RAND_DRBG_get0_master(void)
-{
- if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
- return NULL;
-
- return master_drbg;
-}
-
-/*
- * Get the public DRBG.
- * Returns pointer to the DRBG on success, NULL on failure.
- */
-RAND_DRBG *RAND_DRBG_get0_public(void)
-{
- RAND_DRBG *drbg;
-
- if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
- return NULL;
-
- drbg = CRYPTO_THREAD_get_local(&public_drbg);
- if (drbg == NULL) {
- if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_RAND))
- return NULL;
- drbg = drbg_setup(master_drbg);
- CRYPTO_THREAD_set_local(&public_drbg, drbg);
- }
- return drbg;
-}
-
-/*
- * Get the private DRBG.
- * Returns pointer to the DRBG on success, NULL on failure.
- */
-RAND_DRBG *RAND_DRBG_get0_private(void)
-{
- RAND_DRBG *drbg;
-
- if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
- return NULL;
-
- drbg = CRYPTO_THREAD_get_local(&private_drbg);
- if (drbg == NULL) {
- if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_RAND))
- return NULL;
- drbg = drbg_setup(master_drbg);
- CRYPTO_THREAD_set_local(&private_drbg, drbg);
- }
- return drbg;
-}
-
-RAND_METHOD rand_meth = {
- drbg_seed,
- drbg_bytes,
- NULL,
- drbg_add,
- drbg_bytes,
- drbg_status
-};
-
-RAND_METHOD *RAND_OpenSSL(void)
-{
- return &rand_meth;
-}
diff --git a/crypto/rand/prov_seed.c b/crypto/rand/prov_seed.c
new file mode 100644
index 000000000000..96c499c95709
--- /dev/null
+++ b/crypto/rand/prov_seed.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "crypto/rand.h"
+#include "crypto/rand_pool.h"
+#include <openssl/core_dispatch.h>
+#include <openssl/err.h>
+
+size_t ossl_rand_get_entropy(ossl_unused const OSSL_CORE_HANDLE *handle,
+ unsigned char **pout, int entropy,
+ size_t min_len, size_t max_len)
+{
+ size_t ret = 0;
+ size_t entropy_available;
+ RAND_POOL *pool;
+
+ pool = ossl_rand_pool_new(entropy, 1, min_len, max_len);
+ if (pool == NULL) {
+ ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ /* Get entropy by polling system entropy sources. */
+ entropy_available = ossl_pool_acquire_entropy(pool);
+
+ if (entropy_available > 0) {
+ ret = ossl_rand_pool_length(pool);
+ *pout = ossl_rand_pool_detach(pool);
+ }
+
+ ossl_rand_pool_free(pool);
+ return ret;
+}
+
+void ossl_rand_cleanup_entropy(ossl_unused const OSSL_CORE_HANDLE *handle,
+ unsigned char *buf, size_t len)
+{
+ OPENSSL_secure_clear_free(buf, len);
+}
+
+size_t ossl_rand_get_nonce(ossl_unused const OSSL_CORE_HANDLE *handle,
+ unsigned char **pout, size_t min_len, size_t max_len,
+ const void *salt, size_t salt_len)
+{
+ size_t ret = 0;
+ RAND_POOL *pool;
+
+ pool = ossl_rand_pool_new(0, 0, min_len, max_len);
+ if (pool == NULL) {
+ ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (!ossl_pool_add_nonce_data(pool))
+ goto err;
+
+ if (salt != NULL && !ossl_rand_pool_add(pool, salt, salt_len, 0))
+ goto err;
+ ret = ossl_rand_pool_length(pool);
+ *pout = ossl_rand_pool_detach(pool);
+ err:
+ ossl_rand_pool_free(pool);
+ return ret;
+}
+
+void ossl_rand_cleanup_nonce(ossl_unused const OSSL_CORE_HANDLE *handle,
+ unsigned char *buf, size_t len)
+{
+ OPENSSL_clear_free(buf, len);
+}
diff --git a/crypto/rand/rand_deprecated.c b/crypto/rand/rand_deprecated.c
new file mode 100644
index 000000000000..dd69f1beb726
--- /dev/null
+++ b/crypto/rand/rand_deprecated.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <e_os.h>
+#include <openssl/macros.h>
+#include <openssl/rand.h>
+
+#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
+# include <windows.h>
+# if OPENSSL_API_COMPAT < 0x10100000L
+
+# define DEPRECATED_RAND_FUNCTIONS_DEFINED
+
+int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam)
+{
+ RAND_poll();
+ return RAND_status();
+}
+
+void RAND_screen(void)
+{
+ RAND_poll();
+}
+# endif
+#endif
+
+#ifndef DEPRECATED_RAND_FUNCTIONS_DEFINED
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/crypto/rand/rand_egd.c b/crypto/rand/rand_egd.c
index da3017df3142..1699e7f38f0f 100644
--- a/crypto/rand/rand_egd.c
+++ b/crypto/rand/rand_egd.c
@@ -1,26 +1,23 @@
/*
- * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/opensslconf.h>
-#ifdef OPENSSL_NO_EGD
-NON_EMPTY_TRANSLATION_UNIT
-#else
-# include <openssl/crypto.h>
-# include <openssl/e_os2.h>
-# include <openssl/rand.h>
+#include <openssl/crypto.h>
+#include <openssl/e_os2.h>
+#include <openssl/rand.h>
/*
* Query an EGD
*/
-# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_VOS) || defined(OPENSSL_SYS_UEFI)
+#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_VOS) || defined(OPENSSL_SYS_UEFI)
int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
{
return -1;
@@ -36,26 +33,78 @@ int RAND_egd_bytes(const char *path, int bytes)
return -1;
}
-# else
+#else
-# include OPENSSL_UNISTD
-# include <stddef.h>
-# include <sys/types.h>
-# include <sys/socket.h>
-# ifndef NO_SYS_UN_H
-# ifdef OPENSSL_SYS_VXWORKS
-# include <streams/un.h>
-# else
-# include <sys/un.h>
-# endif
-# else
+# include <unistd.h>
+# include <stddef.h>
+# include <sys/types.h>
+# include <sys/socket.h>
+# ifndef NO_SYS_UN_H
+# include <sys/un.h>
+# else
struct sockaddr_un {
short sun_family; /* AF_UNIX */
char sun_path[108]; /* path name (gag) */
};
-# endif /* NO_SYS_UN_H */
-# include <string.h>
-# include <errno.h>
+# endif /* NO_SYS_UN_H */
+# include <string.h>
+# include <errno.h>
+
+# if defined(OPENSSL_SYS_TANDEM)
+/*
+ * HPNS:
+ *
+ * This code forces the use of compatibility mode if required on HPE NonStop
+ * when coreutils PRNGD is used and then restores the previous mode
+ * after establishing the socket. This is not required on x86 where hardware
+ * randomization should be used instead of EGD available as of OpenSSL 3.0.
+ * Use --with-rand-seed=rdcpu when configuring x86 with 3.0 and above.
+ *
+ * Needs review:
+ *
+ * The better long-term solution is to either run two EGD's each in one of
+ * the two modes or revise the EGD code to listen on two different sockets
+ * (each in one of the two modes) or use the hardware randomizer.
+ */
+_variable
+int hpns_socket(int family,
+ int type,
+ int protocol,
+ char* transport)
+{
+ int socket_rc;
+ char current_transport[20];
+
+# define AF_UNIX_PORTABILITY "$ZAFN2"
+# define AF_UNIX_COMPATIBILITY "$ZPLS"
+
+ if (!_arg_present(transport) || transport == NULL || transport[0] == '\0')
+ return socket(family, type, protocol);
+
+ socket_transport_name_get(AF_UNIX, current_transport, 20);
+
+ if (strcmp(current_transport,transport) == 0)
+ return socket(family, type, protocol);
+
+ /* set the requested socket transport */
+ if (socket_transport_name_set(AF_UNIX, transport))
+ return -1;
+
+ socket_rc = socket(family,type,protocol);
+
+ /* set mode back to what it was */
+ if (socket_transport_name_set(AF_UNIX, current_transport))
+ return -1;
+
+ return socket_rc;
+}
+
+/*#define socket(a,b,c,...) hpns_socket(a,b,c,__VA_ARGS__) */
+
+static int hpns_connect_attempt = 0;
+
+# endif /* defined(OPENSSL_SYS_HPNS) */
+
int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
{
@@ -74,7 +123,11 @@ int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
return -1;
strcpy(addr.sun_path, path);
i = offsetof(struct sockaddr_un, sun_path) + strlen(path);
+#if defined(OPENSSL_SYS_TANDEM)
+ fd = hpns_socket(AF_UNIX, SOCK_STREAM, 0, AF_UNIX_COMPATIBILITY);
+#else
fd = socket(AF_UNIX, SOCK_STREAM, 0);
+#endif
if (fd == -1 || (fp = fdopen(fd, "r+")) == NULL)
return -1;
setbuf(fp, NULL);
@@ -83,26 +136,38 @@ int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
for ( ; ; ) {
if (connect(fd, (struct sockaddr *)&addr, i) == 0)
break;
-# ifdef EISCONN
+# ifdef EISCONN
if (errno == EISCONN)
break;
-# endif
+# endif
switch (errno) {
-# ifdef EINTR
+# ifdef EINTR
case EINTR:
-# endif
-# ifdef EAGAIN
+# endif
+# ifdef EAGAIN
case EAGAIN:
-# endif
-# ifdef EINPROGRESS
+# endif
+# ifdef EINPROGRESS
case EINPROGRESS:
-# endif
-# ifdef EALREADY
+# endif
+# ifdef EALREADY
case EALREADY:
-# endif
+# endif
/* No error, try again */
break;
default:
+# if defined(OPENSSL_SYS_TANDEM)
+ if (hpns_connect_attempt == 0) {
+ /* try the other kind of AF_UNIX socket */
+ close(fd);
+ fd = hpns_socket(AF_UNIX, SOCK_STREAM, 0, AF_UNIX_PORTABILITY);
+ if (fd == -1)
+ return -1;
+ ++hpns_connect_attempt;
+ break; /* try the connect again */
+ }
+# endif
+
ret = -1;
goto err;
}
@@ -153,6 +218,4 @@ int RAND_egd(const char *path)
return RAND_egd_bytes(path, 255);
}
-# endif
-
#endif
diff --git a/crypto/rand/rand_err.c b/crypto/rand/rand_err.c
index a3ae5f53c295..b9c2bf1760f5 100644
--- a/crypto/rand/rand_err.c
+++ b/crypto/rand/rand_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,52 +10,10 @@
#include <openssl/err.h>
#include <openssl/randerr.h>
+#include "crypto/randerr.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA RAND_str_functs[] = {
- {ERR_PACK(ERR_LIB_RAND, RAND_F_DATA_COLLECT_METHOD, 0),
- "data_collect_method"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_DRBG_BYTES, 0), "drbg_bytes"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_DRBG_GET_ENTROPY, 0), "drbg_get_entropy"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_DRBG_SETUP, 0), "drbg_setup"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_GET_ENTROPY, 0), "get_entropy"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_BYTES, 0), "RAND_bytes"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_ENABLE_LOCKING, 0),
- "rand_drbg_enable_locking"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_GENERATE, 0),
- "RAND_DRBG_generate"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_GET_ENTROPY, 0),
- "rand_drbg_get_entropy"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_GET_NONCE, 0),
- "rand_drbg_get_nonce"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_INSTANTIATE, 0),
- "RAND_DRBG_instantiate"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_NEW, 0), "RAND_DRBG_new"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_RESEED, 0), "RAND_DRBG_reseed"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_RESTART, 0), "rand_drbg_restart"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_SET, 0), "RAND_DRBG_set"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_SET_DEFAULTS, 0),
- "RAND_DRBG_set_defaults"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_UNINSTANTIATE, 0),
- "RAND_DRBG_uninstantiate"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_LOAD_FILE, 0), "RAND_load_file"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ACQUIRE_ENTROPY, 0),
- "rand_pool_acquire_entropy"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ADD, 0), "rand_pool_add"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ADD_BEGIN, 0),
- "rand_pool_add_begin"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ADD_END, 0), "rand_pool_add_end"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ATTACH, 0), "rand_pool_attach"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_BYTES_NEEDED, 0),
- "rand_pool_bytes_needed"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_GROW, 0), "rand_pool_grow"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_NEW, 0), "rand_pool_new"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_PSEUDO_BYTES, 0), "RAND_pseudo_bytes"},
- {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_WRITE_FILE, 0), "RAND_write_file"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA RAND_str_reasons[] = {
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ADDITIONAL_INPUT_TOO_LONG),
"additional input too long"},
@@ -90,6 +48,8 @@ static const ERR_STRING_DATA RAND_str_reasons[] = {
"Function not implemented"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_FWRITE_ERROR), "Error writing file"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_GENERATE_ERROR), "generate error"},
+ {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INSUFFICIENT_DRBG_STRENGTH),
+ "insufficient drbg strength"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INTERNAL_ERROR), "internal error"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_IN_ERROR_STATE), "in error state"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NOT_A_REGULAR_FILE),
@@ -118,6 +78,16 @@ static const ERR_STRING_DATA RAND_str_reasons[] = {
"too little nonce requested"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_TOO_MUCH_NONCE_REQUESTED),
"too much nonce requested"},
+ {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_CREATE_DRBG),
+ "unable to create drbg"},
+ {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_FETCH_DRBG),
+ "unable to fetch drbg"},
+ {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER),
+ "unable to get parent reseed prop counter"},
+ {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_GET_PARENT_STRENGTH),
+ "unable to get parent strength"},
+ {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_LOCK_PARENT),
+ "unable to lock parent"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNSUPPORTED_DRBG_FLAGS),
"unsupported drbg flags"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNSUPPORTED_DRBG_TYPE),
@@ -127,13 +97,11 @@ static const ERR_STRING_DATA RAND_str_reasons[] = {
#endif
-int ERR_load_RAND_strings(void)
+int ossl_err_load_RAND_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(RAND_str_functs[0].error) == NULL) {
- ERR_load_strings_const(RAND_str_functs);
+ if (ERR_reason_error_string(RAND_str_reasons[0].error) == NULL)
ERR_load_strings_const(RAND_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
index 3fdb56cb0024..f341d915db76 100644
--- a/crypto/rand/rand_lib.c
+++ b/crypto/rand/rand_lib.c
@@ -1,348 +1,83 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <stdio.h>
-#include <time.h>
-#include "internal/cryptlib.h"
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include <openssl/err.h>
#include <openssl/opensslconf.h>
-#include "crypto/rand.h"
-#include <openssl/engine.h>
+#include <openssl/core_names.h>
+#include "internal/cryptlib.h"
#include "internal/thread_once.h"
+#include "crypto/rand.h"
+#include "crypto/cryptlib.h"
#include "rand_local.h"
-#include "e_os.h"
-#ifndef OPENSSL_NO_ENGINE
+#ifndef FIPS_MODULE
+# include <stdio.h>
+# include <time.h>
+# include <limits.h>
+# include <openssl/conf.h>
+# include <openssl/trace.h>
+# include <openssl/engine.h>
+# include "crypto/rand_pool.h"
+# include "prov/seeding.h"
+# include "e_os.h"
+
+# ifndef OPENSSL_NO_ENGINE
/* non-NULL if default_RAND_meth is ENGINE-provided */
static ENGINE *funct_ref;
static CRYPTO_RWLOCK *rand_engine_lock;
-#endif
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
static CRYPTO_RWLOCK *rand_meth_lock;
static const RAND_METHOD *default_RAND_meth;
+# endif
static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT;
-static CRYPTO_RWLOCK *rand_nonce_lock;
-static int rand_nonce_count;
-
static int rand_inited = 0;
-#ifdef OPENSSL_RAND_SEED_RDTSC
-/*
- * IMPORTANT NOTE: It is not currently possible to use this code
- * because we are not sure about the amount of randomness it provides.
- * Some SP900 tests have been run, but there is internal skepticism.
- * So for now this code is not used.
- */
-# error "RDTSC enabled? Should not be possible!"
-
-/*
- * Acquire entropy from high-speed clock
- *
- * Since we get some randomness from the low-order bits of the
- * high-speed clock, it can help.
- *
- * Returns the total entropy count, if it exceeds the requested
- * entropy count. Otherwise, returns an entropy count of 0.
- */
-size_t rand_acquire_entropy_from_tsc(RAND_POOL *pool)
-{
- unsigned char c;
- int i;
-
- if ((OPENSSL_ia32cap_P[0] & (1 << 4)) != 0) {
- for (i = 0; i < TSC_READ_COUNT; i++) {
- c = (unsigned char)(OPENSSL_rdtsc() & 0xFF);
- rand_pool_add(pool, &c, 1, 4);
- }
- }
- return rand_pool_entropy_available(pool);
-}
-#endif
-
-#ifdef OPENSSL_RAND_SEED_RDCPU
-size_t OPENSSL_ia32_rdseed_bytes(unsigned char *buf, size_t len);
-size_t OPENSSL_ia32_rdrand_bytes(unsigned char *buf, size_t len);
-
-extern unsigned int OPENSSL_ia32cap_P[];
-
-/*
- * Acquire entropy using Intel-specific cpu instructions
- *
- * Uses the RDSEED instruction if available, otherwise uses
- * RDRAND if available.
- *
- * For the differences between RDSEED and RDRAND, and why RDSEED
- * is the preferred choice, see https://goo.gl/oK3KcN
- *
- * Returns the total entropy count, if it exceeds the requested
- * entropy count. Otherwise, returns an entropy count of 0.
- */
-size_t rand_acquire_entropy_from_cpu(RAND_POOL *pool)
-{
- size_t bytes_needed;
- unsigned char *buffer;
-
- bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
- if (bytes_needed > 0) {
- buffer = rand_pool_add_begin(pool, bytes_needed);
-
- if (buffer != NULL) {
- /* Whichever comes first, use RDSEED, RDRAND or nothing */
- if ((OPENSSL_ia32cap_P[2] & (1 << 18)) != 0) {
- if (OPENSSL_ia32_rdseed_bytes(buffer, bytes_needed)
- == bytes_needed) {
- rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed);
- }
- } else if ((OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) != 0) {
- if (OPENSSL_ia32_rdrand_bytes(buffer, bytes_needed)
- == bytes_needed) {
- rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed);
- }
- } else {
- rand_pool_add_end(pool, 0, 0);
- }
- }
- }
-
- return rand_pool_entropy_available(pool);
-}
-#endif
-
-
-/*
- * Implements the get_entropy() callback (see RAND_DRBG_set_callbacks())
- *
- * If the DRBG has a parent, then the required amount of entropy input
- * is fetched using the parent's RAND_DRBG_generate().
- *
- * Otherwise, the entropy is polled from the system entropy sources
- * using rand_pool_acquire_entropy().
- *
- * If a random pool has been added to the DRBG using RAND_add(), then
- * its entropy will be used up first.
- */
-size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
- unsigned char **pout,
- int entropy, size_t min_len, size_t max_len,
- int prediction_resistance)
-{
- size_t ret = 0;
- size_t entropy_available = 0;
- RAND_POOL *pool;
-
- if (drbg->parent != NULL && drbg->strength > drbg->parent->strength) {
- /*
- * We currently don't support the algorithm from NIST SP 800-90C
- * 10.1.2 to use a weaker DRBG as source
- */
- RANDerr(RAND_F_RAND_DRBG_GET_ENTROPY, RAND_R_PARENT_STRENGTH_TOO_WEAK);
- return 0;
- }
-
- if (drbg->seed_pool != NULL) {
- pool = drbg->seed_pool;
- pool->entropy_requested = entropy;
- } else {
- pool = rand_pool_new(entropy, drbg->secure, min_len, max_len);
- if (pool == NULL)
- return 0;
- }
-
- if (drbg->parent != NULL) {
- size_t bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
- unsigned char *buffer = rand_pool_add_begin(pool, bytes_needed);
-
- if (buffer != NULL) {
- size_t bytes = 0;
-
- /*
- * Get random data from parent. Include our address as additional input,
- * in order to provide some additional distinction between different
- * DRBG child instances.
- * Our lock is already held, but we need to lock our parent before
- * generating bits from it. (Note: taking the lock will be a no-op
- * if locking if drbg->parent->lock == NULL.)
- */
- rand_drbg_lock(drbg->parent);
- if (RAND_DRBG_generate(drbg->parent,
- buffer, bytes_needed,
- prediction_resistance,
- (unsigned char *)&drbg, sizeof(drbg)) != 0) {
- bytes = bytes_needed;
- if (drbg->enable_reseed_propagation)
- tsan_store(&drbg->reseed_counter,
- tsan_load(&drbg->parent->reseed_counter));
- }
- rand_drbg_unlock(drbg->parent);
-
- rand_pool_add_end(pool, bytes, 8 * bytes);
- entropy_available = rand_pool_entropy_available(pool);
- }
-
- } else {
- if (prediction_resistance) {
- /*
- * We don't have any entropy sources that comply with the NIST
- * standard to provide prediction resistance (see NIST SP 800-90C,
- * Section 5.4).
- */
- RANDerr(RAND_F_RAND_DRBG_GET_ENTROPY,
- RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED);
- goto err;
- }
-
- /* Get entropy by polling system entropy sources. */
- entropy_available = rand_pool_acquire_entropy(pool);
- }
-
- if (entropy_available > 0) {
- ret = rand_pool_length(pool);
- *pout = rand_pool_detach(pool);
- }
-
- err:
- if (drbg->seed_pool == NULL)
- rand_pool_free(pool);
- return ret;
-}
-
-/*
- * Implements the cleanup_entropy() callback (see RAND_DRBG_set_callbacks())
- *
- */
-void rand_drbg_cleanup_entropy(RAND_DRBG *drbg,
- unsigned char *out, size_t outlen)
-{
- if (drbg->seed_pool == NULL) {
- if (drbg->secure)
- OPENSSL_secure_clear_free(out, outlen);
- else
- OPENSSL_clear_free(out, outlen);
- }
-}
-
-
-/*
- * Implements the get_nonce() callback (see RAND_DRBG_set_callbacks())
- *
- */
-size_t rand_drbg_get_nonce(RAND_DRBG *drbg,
- unsigned char **pout,
- int entropy, size_t min_len, size_t max_len)
-{
- size_t ret = 0;
- RAND_POOL *pool;
-
- struct {
- void * instance;
- int count;
- } data;
-
- memset(&data, 0, sizeof(data));
- pool = rand_pool_new(0, 0, min_len, max_len);
- if (pool == NULL)
- return 0;
-
- if (rand_pool_add_nonce_data(pool) == 0)
- goto err;
-
- data.instance = drbg;
- CRYPTO_atomic_add(&rand_nonce_count, 1, &data.count, rand_nonce_lock);
-
- if (rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0) == 0)
- goto err;
-
- ret = rand_pool_length(pool);
- *pout = rand_pool_detach(pool);
-
- err:
- rand_pool_free(pool);
-
- return ret;
-}
-
-/*
- * Implements the cleanup_nonce() callback (see RAND_DRBG_set_callbacks())
- *
- */
-void rand_drbg_cleanup_nonce(RAND_DRBG *drbg,
- unsigned char *out, size_t outlen)
-{
- OPENSSL_clear_free(out, outlen);
-}
-
-/*
- * Generate additional data that can be used for the drbg. The data does
- * not need to contain entropy, but it's useful if it contains at least
- * some bits that are unpredictable.
- *
- * Returns 0 on failure.
- *
- * On success it allocates a buffer at |*pout| and returns the length of
- * the data. The buffer should get freed using OPENSSL_secure_clear_free().
- */
-size_t rand_drbg_get_additional_data(RAND_POOL *pool, unsigned char **pout)
-{
- size_t ret = 0;
-
- if (rand_pool_add_additional_data(pool) == 0)
- goto err;
-
- ret = rand_pool_length(pool);
- *pout = rand_pool_detach(pool);
-
- err:
- return ret;
-}
-
-void rand_drbg_cleanup_additional_data(RAND_POOL *pool, unsigned char *out)
-{
- rand_pool_reattach(pool, out);
-}
-
DEFINE_RUN_ONCE_STATIC(do_rand_init)
{
-#ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_ENGINE
rand_engine_lock = CRYPTO_THREAD_lock_new();
if (rand_engine_lock == NULL)
return 0;
-#endif
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
rand_meth_lock = CRYPTO_THREAD_lock_new();
if (rand_meth_lock == NULL)
- goto err1;
-
- rand_nonce_lock = CRYPTO_THREAD_lock_new();
- if (rand_nonce_lock == NULL)
- goto err2;
+ goto err;
+# endif
- if (!rand_pool_init())
- goto err3;
+ if (!ossl_rand_pool_init())
+ goto err;
rand_inited = 1;
return 1;
-err3:
- CRYPTO_THREAD_lock_free(rand_nonce_lock);
- rand_nonce_lock = NULL;
-err2:
+ err:
+# ifndef OPENSSL_NO_DEPRECATED_3_0
CRYPTO_THREAD_lock_free(rand_meth_lock);
rand_meth_lock = NULL;
-err1:
-#ifndef OPENSSL_NO_ENGINE
+# endif
+# ifndef OPENSSL_NO_ENGINE
CRYPTO_THREAD_lock_free(rand_engine_lock);
rand_engine_lock = NULL;
-#endif
+# endif
return 0;
}
-void rand_cleanup_int(void)
+void ossl_rand_cleanup_int(void)
{
+# ifndef OPENSSL_NO_DEPRECATED_3_0
const RAND_METHOD *meth = default_RAND_meth;
if (!rand_inited)
@@ -351,26 +86,29 @@ void rand_cleanup_int(void)
if (meth != NULL && meth->cleanup != NULL)
meth->cleanup();
RAND_set_rand_method(NULL);
- rand_pool_cleanup();
-#ifndef OPENSSL_NO_ENGINE
+# endif
+ ossl_rand_pool_cleanup();
+# ifndef OPENSSL_NO_ENGINE
CRYPTO_THREAD_lock_free(rand_engine_lock);
rand_engine_lock = NULL;
-#endif
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
CRYPTO_THREAD_lock_free(rand_meth_lock);
rand_meth_lock = NULL;
- CRYPTO_THREAD_lock_free(rand_nonce_lock);
- rand_nonce_lock = NULL;
+# endif
+ ossl_release_default_drbg_ctx();
rand_inited = 0;
}
/*
* RAND_close_seed_files() ensures that any seed file descriptors are
- * closed after use.
+ * closed after use. This only applies to libcrypto/default provider,
+ * it does not apply to other providers.
*/
void RAND_keep_random_devices_open(int keep)
{
if (RUN_ONCE(&rand_init, do_rand_init))
- rand_pool_keep_random_devices_open(keep);
+ ossl_rand_pool_keep_random_devices_open(keep);
}
/*
@@ -382,588 +120,725 @@ void RAND_keep_random_devices_open(int keep)
*/
int RAND_poll(void)
{
- int ret = 0;
-
- RAND_POOL *pool = NULL;
-
+# ifndef OPENSSL_NO_DEPRECATED_3_0
const RAND_METHOD *meth = RAND_get_rand_method();
+ int ret = meth == RAND_OpenSSL();
if (meth == NULL)
return 0;
- if (meth == RAND_OpenSSL()) {
- /* fill random pool and seed the master DRBG */
- RAND_DRBG *drbg = RAND_DRBG_get0_master();
-
- if (drbg == NULL)
- return 0;
-
- rand_drbg_lock(drbg);
- ret = rand_drbg_restart(drbg, NULL, 0, 0);
- rand_drbg_unlock(drbg);
-
- return ret;
-
- } else {
+ if (!ret) {
/* fill random pool and seed the current legacy RNG */
- pool = rand_pool_new(RAND_DRBG_STRENGTH, 1,
- (RAND_DRBG_STRENGTH + 7) / 8,
- RAND_POOL_MAX_LENGTH);
+ RAND_POOL *pool = ossl_rand_pool_new(RAND_DRBG_STRENGTH, 1,
+ (RAND_DRBG_STRENGTH + 7) / 8,
+ RAND_POOL_MAX_LENGTH);
+
if (pool == NULL)
return 0;
- if (rand_pool_acquire_entropy(pool) == 0)
+ if (ossl_pool_acquire_entropy(pool) == 0)
goto err;
if (meth->add == NULL
- || meth->add(rand_pool_buffer(pool),
- rand_pool_length(pool),
- (rand_pool_entropy(pool) / 8.0)) == 0)
+ || meth->add(ossl_rand_pool_buffer(pool),
+ ossl_rand_pool_length(pool),
+ (ossl_rand_pool_entropy(pool) / 8.0)) == 0)
goto err;
ret = 1;
+ err:
+ ossl_rand_pool_free(pool);
}
-
-err:
- rand_pool_free(pool);
return ret;
+# else
+ static const char salt[] = "polling";
+
+ RAND_seed(salt, sizeof(salt));
+ return 1;
+# endif
}
-/*
- * Allocate memory and initialize a new random pool
- */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+static int rand_set_rand_method_internal(const RAND_METHOD *meth,
+ ossl_unused ENGINE *e)
+{
+ if (!RUN_ONCE(&rand_init, do_rand_init))
+ return 0;
+
+ if (!CRYPTO_THREAD_write_lock(rand_meth_lock))
+ return 0;
+# ifndef OPENSSL_NO_ENGINE
+ ENGINE_finish(funct_ref);
+ funct_ref = e;
+# endif
+ default_RAND_meth = meth;
+ CRYPTO_THREAD_unlock(rand_meth_lock);
+ return 1;
+}
-RAND_POOL *rand_pool_new(int entropy_requested, int secure,
- size_t min_len, size_t max_len)
+int RAND_set_rand_method(const RAND_METHOD *meth)
+{
+ return rand_set_rand_method_internal(meth, NULL);
+}
+
+const RAND_METHOD *RAND_get_rand_method(void)
{
- RAND_POOL *pool;
- size_t min_alloc_size = RAND_POOL_MIN_ALLOCATION(secure);
+ const RAND_METHOD *tmp_meth = NULL;
if (!RUN_ONCE(&rand_init, do_rand_init))
return NULL;
- pool = OPENSSL_zalloc(sizeof(*pool));
- if (pool == NULL) {
- RANDerr(RAND_F_RAND_POOL_NEW, ERR_R_MALLOC_FAILURE);
+ if (!CRYPTO_THREAD_write_lock(rand_meth_lock))
return NULL;
+ if (default_RAND_meth == NULL) {
+# ifndef OPENSSL_NO_ENGINE
+ ENGINE *e;
+
+ /* If we have an engine that can do RAND, use it. */
+ if ((e = ENGINE_get_default_RAND()) != NULL
+ && (tmp_meth = ENGINE_get_RAND(e)) != NULL) {
+ funct_ref = e;
+ default_RAND_meth = tmp_meth;
+ } else {
+ ENGINE_finish(e);
+ default_RAND_meth = &ossl_rand_meth;
+ }
+# else
+ default_RAND_meth = &ossl_rand_meth;
+# endif
}
+ tmp_meth = default_RAND_meth;
+ CRYPTO_THREAD_unlock(rand_meth_lock);
+ return tmp_meth;
+}
- pool->min_len = min_len;
- pool->max_len = (max_len > RAND_POOL_MAX_LENGTH) ?
- RAND_POOL_MAX_LENGTH : max_len;
- pool->alloc_len = min_len < min_alloc_size ? min_alloc_size : min_len;
- if (pool->alloc_len > pool->max_len)
- pool->alloc_len = pool->max_len;
+# if !defined(OPENSSL_NO_ENGINE)
+int RAND_set_rand_engine(ENGINE *engine)
+{
+ const RAND_METHOD *tmp_meth = NULL;
- if (secure)
- pool->buffer = OPENSSL_secure_zalloc(pool->alloc_len);
- else
- pool->buffer = OPENSSL_zalloc(pool->alloc_len);
+ if (!RUN_ONCE(&rand_init, do_rand_init))
+ return 0;
- if (pool->buffer == NULL) {
- RANDerr(RAND_F_RAND_POOL_NEW, ERR_R_MALLOC_FAILURE);
- goto err;
+ if (engine != NULL) {
+ if (!ENGINE_init(engine))
+ return 0;
+ tmp_meth = ENGINE_get_RAND(engine);
+ if (tmp_meth == NULL) {
+ ENGINE_finish(engine);
+ return 0;
+ }
+ }
+ if (!CRYPTO_THREAD_write_lock(rand_engine_lock)) {
+ ENGINE_finish(engine);
+ return 0;
}
- pool->entropy_requested = entropy_requested;
- pool->secure = secure;
-
- return pool;
-
-err:
- OPENSSL_free(pool);
- return NULL;
+ /* This function releases any prior ENGINE so call it first */
+ rand_set_rand_method_internal(tmp_meth, engine);
+ CRYPTO_THREAD_unlock(rand_engine_lock);
+ return 1;
}
+# endif
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
-/*
- * Attach new random pool to the given buffer
- *
- * This function is intended to be used only for feeding random data
- * provided by RAND_add() and RAND_seed() into the <master> DRBG.
- */
-RAND_POOL *rand_pool_attach(const unsigned char *buffer, size_t len,
- size_t entropy)
+void RAND_seed(const void *buf, int num)
{
- RAND_POOL *pool = OPENSSL_zalloc(sizeof(*pool));
+ EVP_RAND_CTX *drbg;
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+ const RAND_METHOD *meth = RAND_get_rand_method();
- if (pool == NULL) {
- RANDerr(RAND_F_RAND_POOL_ATTACH, ERR_R_MALLOC_FAILURE);
- return NULL;
+ if (meth != NULL && meth->seed != NULL) {
+ meth->seed(buf, num);
+ return;
}
+# endif
- /*
- * The const needs to be cast away, but attached buffers will not be
- * modified (in contrary to allocated buffers which are zeroed and
- * freed in the end).
- */
- pool->buffer = (unsigned char *) buffer;
- pool->len = len;
+ drbg = RAND_get0_primary(NULL);
+ if (drbg != NULL && num > 0)
+ EVP_RAND_reseed(drbg, 0, NULL, 0, buf, num);
+}
+
+void RAND_add(const void *buf, int num, double randomness)
+{
+ EVP_RAND_CTX *drbg;
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+ const RAND_METHOD *meth = RAND_get_rand_method();
- pool->attached = 1;
+ if (meth != NULL && meth->add != NULL) {
+ meth->add(buf, num, randomness);
+ return;
+ }
+# endif
+ drbg = RAND_get0_primary(NULL);
+ if (drbg != NULL && num > 0)
+ EVP_RAND_reseed(drbg, 0, NULL, 0, buf, num);
+}
- pool->min_len = pool->max_len = pool->alloc_len = pool->len;
- pool->entropy = entropy;
+# if !defined(OPENSSL_NO_DEPRECATED_1_1_0)
+int RAND_pseudo_bytes(unsigned char *buf, int num)
+{
+ const RAND_METHOD *meth = RAND_get_rand_method();
- return pool;
+ if (meth != NULL && meth->pseudorand != NULL)
+ return meth->pseudorand(buf, num);
+ ERR_raise(ERR_LIB_RAND, RAND_R_FUNC_NOT_IMPLEMENTED);
+ return -1;
}
+# endif
-/*
- * Free |pool|, securely erasing its buffer.
- */
-void rand_pool_free(RAND_POOL *pool)
+int RAND_status(void)
{
- if (pool == NULL)
- return;
+ EVP_RAND_CTX *rand;
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+ const RAND_METHOD *meth = RAND_get_rand_method();
- /*
- * Although it would be advisable from a cryptographical viewpoint,
- * we are not allowed to clear attached buffers, since they are passed
- * to rand_pool_attach() as `const unsigned char*`.
- * (see corresponding comment in rand_pool_attach()).
- */
- if (!pool->attached) {
- if (pool->secure)
- OPENSSL_secure_clear_free(pool->buffer, pool->alloc_len);
- else
- OPENSSL_clear_free(pool->buffer, pool->alloc_len);
- }
+ if (meth != NULL && meth != RAND_OpenSSL())
+ return meth->status != NULL ? meth->status() : 0;
+# endif
- OPENSSL_free(pool);
+ if ((rand = RAND_get0_primary(NULL)) == NULL)
+ return 0;
+ return EVP_RAND_get_state(rand) == EVP_RAND_STATE_READY;
}
+# else /* !FIPS_MODULE */
-/*
- * Return the |pool|'s buffer to the caller (readonly).
- */
-const unsigned char *rand_pool_buffer(RAND_POOL *pool)
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+const RAND_METHOD *RAND_get_rand_method(void)
{
- return pool->buffer;
+ return NULL;
}
+# endif
+#endif /* !FIPS_MODULE */
/*
- * Return the |pool|'s entropy to the caller.
+ * This function is not part of RAND_METHOD, so if we're not using
+ * the default method, then just call RAND_bytes(). Otherwise make
+ * sure we're instantiated and use the private DRBG.
*/
-size_t rand_pool_entropy(RAND_POOL *pool)
+int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num,
+ unsigned int strength)
{
- return pool->entropy;
+ EVP_RAND_CTX *rand;
+#if !defined(OPENSSL_NO_DEPRECATED_3_0) && !defined(FIPS_MODULE)
+ const RAND_METHOD *meth = RAND_get_rand_method();
+
+ if (meth != NULL && meth != RAND_OpenSSL()) {
+ if (meth->bytes != NULL)
+ return meth->bytes(buf, num);
+ ERR_raise(ERR_LIB_RAND, RAND_R_FUNC_NOT_IMPLEMENTED);
+ return -1;
+ }
+#endif
+
+ rand = RAND_get0_private(ctx);
+ if (rand != NULL)
+ return EVP_RAND_generate(rand, buf, num, strength, 0, NULL, 0);
+
+ return 0;
}
-/*
- * Return the |pool|'s buffer length to the caller.
- */
-size_t rand_pool_length(RAND_POOL *pool)
+int RAND_priv_bytes(unsigned char *buf, int num)
{
- return pool->len;
+ if (num < 0)
+ return 0;
+ return RAND_priv_bytes_ex(NULL, buf, (size_t)num, 0);
}
-/*
- * Detach the |pool| buffer and return it to the caller.
- * It's the responsibility of the caller to free the buffer
- * using OPENSSL_secure_clear_free() or to re-attach it
- * again to the pool using rand_pool_reattach().
- */
-unsigned char *rand_pool_detach(RAND_POOL *pool)
+int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num,
+ unsigned int strength)
{
- unsigned char *ret = pool->buffer;
- pool->buffer = NULL;
- pool->entropy = 0;
- return ret;
+ EVP_RAND_CTX *rand;
+#if !defined(OPENSSL_NO_DEPRECATED_3_0) && !defined(FIPS_MODULE)
+ const RAND_METHOD *meth = RAND_get_rand_method();
+
+ if (meth != NULL && meth != RAND_OpenSSL()) {
+ if (meth->bytes != NULL)
+ return meth->bytes(buf, num);
+ ERR_raise(ERR_LIB_RAND, RAND_R_FUNC_NOT_IMPLEMENTED);
+ return -1;
+ }
+#endif
+
+ rand = RAND_get0_public(ctx);
+ if (rand != NULL)
+ return EVP_RAND_generate(rand, buf, num, strength, 0, NULL, 0);
+
+ return 0;
}
-/*
- * Re-attach the |pool| buffer. It is only allowed to pass
- * the |buffer| which was previously detached from the same pool.
- */
-void rand_pool_reattach(RAND_POOL *pool, unsigned char *buffer)
+int RAND_bytes(unsigned char *buf, int num)
{
- pool->buffer = buffer;
- OPENSSL_cleanse(pool->buffer, pool->len);
- pool->len = 0;
+ if (num < 0)
+ return 0;
+ return RAND_bytes_ex(NULL, buf, (size_t)num, 0);
}
-/*
- * If |entropy_factor| bits contain 1 bit of entropy, how many bytes does one
- * need to obtain at least |bits| bits of entropy?
- */
-#define ENTROPY_TO_BYTES(bits, entropy_factor) \
- (((bits) * (entropy_factor) + 7) / 8)
+typedef struct rand_global_st {
+ /*
+ * The three shared DRBG instances
+ *
+ * There are three shared DRBG instances: <primary>, <public>, and
+ * <private>. The <public> and <private> DRBGs are secondary ones.
+ * These are used for non-secret (e.g. nonces) and secret
+ * (e.g. private keys) data respectively.
+ */
+ CRYPTO_RWLOCK *lock;
+
+ EVP_RAND_CTX *seed;
+
+ /*
+ * The <primary> DRBG
+ *
+ * Not used directly by the application, only for reseeding the two other
+ * DRBGs. It reseeds itself by pulling either randomness from os entropy
+ * sources or by consuming randomness which was added by RAND_add().
+ *
+ * The <primary> DRBG is a global instance which is accessed concurrently by
+ * all threads. The necessary locking is managed automatically by its child
+ * DRBG instances during reseeding.
+ */
+ EVP_RAND_CTX *primary;
+
+ /*
+ * The <public> DRBG
+ *
+ * Used by default for generating random bytes using RAND_bytes().
+ *
+ * The <public> secondary DRBG is thread-local, i.e., there is one instance
+ * per thread.
+ */
+ CRYPTO_THREAD_LOCAL public;
+
+ /*
+ * The <private> DRBG
+ *
+ * Used by default for generating private keys using RAND_priv_bytes()
+ *
+ * The <private> secondary DRBG is thread-local, i.e., there is one
+ * instance per thread.
+ */
+ CRYPTO_THREAD_LOCAL private;
+ /* Which RNG is being used by default and it's configuration settings */
+ char *rng_name;
+ char *rng_cipher;
+ char *rng_digest;
+ char *rng_propq;
+
+ /* Allow the randomness source to be changed */
+ char *seed_name;
+ char *seed_propq;
+} RAND_GLOBAL;
/*
- * Checks whether the |pool|'s entropy is available to the caller.
- * This is the case when entropy count and buffer length are high enough.
- * Returns
- *
- * |entropy| if the entropy count and buffer size is large enough
- * 0 otherwise
+ * Initialize the OSSL_LIB_CTX global DRBGs on first use.
+ * Returns the allocated global data on success or NULL on failure.
*/
-size_t rand_pool_entropy_available(RAND_POOL *pool)
+static void *rand_ossl_ctx_new(OSSL_LIB_CTX *libctx)
{
- if (pool->entropy < pool->entropy_requested)
- return 0;
+ RAND_GLOBAL *dgbl = OPENSSL_zalloc(sizeof(*dgbl));
- if (pool->len < pool->min_len)
- return 0;
+ if (dgbl == NULL)
+ return NULL;
- return pool->entropy;
-}
+#ifndef FIPS_MODULE
+ /*
+ * We need to ensure that base libcrypto thread handling has been
+ * initialised.
+ */
+ OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL);
+#endif
-/*
- * Returns the (remaining) amount of entropy needed to fill
- * the random pool.
- */
+ dgbl->lock = CRYPTO_THREAD_lock_new();
+ if (dgbl->lock == NULL)
+ goto err1;
-size_t rand_pool_entropy_needed(RAND_POOL *pool)
-{
- if (pool->entropy < pool->entropy_requested)
- return pool->entropy_requested - pool->entropy;
+ if (!CRYPTO_THREAD_init_local(&dgbl->private, NULL))
+ goto err1;
- return 0;
+ if (!CRYPTO_THREAD_init_local(&dgbl->public, NULL))
+ goto err2;
+
+ return dgbl;
+
+ err2:
+ CRYPTO_THREAD_cleanup_local(&dgbl->private);
+ err1:
+ CRYPTO_THREAD_lock_free(dgbl->lock);
+ OPENSSL_free(dgbl);
+ return NULL;
}
-/* Increase the allocation size -- not usable for an attached pool */
-static int rand_pool_grow(RAND_POOL *pool, size_t len)
+void ossl_rand_ctx_free(void *vdgbl)
{
- if (len > pool->alloc_len - pool->len) {
- unsigned char *p;
- const size_t limit = pool->max_len / 2;
- size_t newlen = pool->alloc_len;
+ RAND_GLOBAL *dgbl = vdgbl;
- if (pool->attached || len > pool->max_len - pool->len) {
- RANDerr(RAND_F_RAND_POOL_GROW, ERR_R_INTERNAL_ERROR);
- return 0;
- }
+ if (dgbl == NULL)
+ return;
- do
- newlen = newlen < limit ? newlen * 2 : pool->max_len;
- while (len > newlen - pool->len);
+ CRYPTO_THREAD_lock_free(dgbl->lock);
+ CRYPTO_THREAD_cleanup_local(&dgbl->private);
+ CRYPTO_THREAD_cleanup_local(&dgbl->public);
+ EVP_RAND_CTX_free(dgbl->primary);
+ EVP_RAND_CTX_free(dgbl->seed);
+ OPENSSL_free(dgbl->rng_name);
+ OPENSSL_free(dgbl->rng_cipher);
+ OPENSSL_free(dgbl->rng_digest);
+ OPENSSL_free(dgbl->rng_propq);
+ OPENSSL_free(dgbl->seed_name);
+ OPENSSL_free(dgbl->seed_propq);
- if (pool->secure)
- p = OPENSSL_secure_zalloc(newlen);
- else
- p = OPENSSL_zalloc(newlen);
- if (p == NULL) {
- RANDerr(RAND_F_RAND_POOL_GROW, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- memcpy(p, pool->buffer, pool->len);
- if (pool->secure)
- OPENSSL_secure_clear_free(pool->buffer, pool->alloc_len);
- else
- OPENSSL_clear_free(pool->buffer, pool->alloc_len);
- pool->buffer = p;
- pool->alloc_len = newlen;
- }
- return 1;
+ OPENSSL_free(dgbl);
}
-/*
- * Returns the number of bytes needed to fill the pool, assuming
- * the input has 1 / |entropy_factor| entropy bits per data bit.
- * In case of an error, 0 is returned.
- */
+static const OSSL_LIB_CTX_METHOD rand_drbg_ossl_ctx_method = {
+ OSSL_LIB_CTX_METHOD_PRIORITY_2,
+ rand_ossl_ctx_new,
+ ossl_rand_ctx_free,
+};
-size_t rand_pool_bytes_needed(RAND_POOL *pool, unsigned int entropy_factor)
+static RAND_GLOBAL *rand_get_global(OSSL_LIB_CTX *libctx)
{
- size_t bytes_needed;
- size_t entropy_needed = rand_pool_entropy_needed(pool);
-
- if (entropy_factor < 1) {
- RANDerr(RAND_F_RAND_POOL_BYTES_NEEDED, RAND_R_ARGUMENT_OUT_OF_RANGE);
- return 0;
- }
-
- bytes_needed = ENTROPY_TO_BYTES(entropy_needed, entropy_factor);
+ return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_INDEX,
+ &rand_drbg_ossl_ctx_method);
+}
- if (bytes_needed > pool->max_len - pool->len) {
- /* not enough space left */
- RANDerr(RAND_F_RAND_POOL_BYTES_NEEDED, RAND_R_RANDOM_POOL_OVERFLOW);
- return 0;
- }
+static void rand_delete_thread_state(void *arg)
+{
+ OSSL_LIB_CTX *ctx = arg;
+ RAND_GLOBAL *dgbl = rand_get_global(ctx);
+ EVP_RAND_CTX *rand;
- if (pool->len < pool->min_len &&
- bytes_needed < pool->min_len - pool->len)
- /* to meet the min_len requirement */
- bytes_needed = pool->min_len - pool->len;
+ if (dgbl == NULL)
+ return;
- /*
- * Make sure the buffer is large enough for the requested amount
- * of data. This guarantees that existing code patterns where
- * rand_pool_add_begin, rand_pool_add_end or rand_pool_add
- * are used to collect entropy data without any error handling
- * whatsoever, continue to be valid.
- * Furthermore if the allocation here fails once, make sure that
- * we don't fall back to a less secure or even blocking random source,
- * as that could happen by the existing code patterns.
- * This is not a concern for additional data, therefore that
- * is not needed if rand_pool_grow fails in other places.
- */
- if (!rand_pool_grow(pool, bytes_needed)) {
- /* persistent error for this pool */
- pool->max_len = pool->len = 0;
- return 0;
- }
+ rand = CRYPTO_THREAD_get_local(&dgbl->public);
+ CRYPTO_THREAD_set_local(&dgbl->public, NULL);
+ EVP_RAND_CTX_free(rand);
- return bytes_needed;
+ rand = CRYPTO_THREAD_get_local(&dgbl->private);
+ CRYPTO_THREAD_set_local(&dgbl->private, NULL);
+ EVP_RAND_CTX_free(rand);
}
-/* Returns the remaining number of bytes available */
-size_t rand_pool_bytes_remaining(RAND_POOL *pool)
+#ifndef FIPS_MODULE
+static EVP_RAND_CTX *rand_new_seed(OSSL_LIB_CTX *libctx)
{
- return pool->max_len - pool->len;
-}
+ EVP_RAND *rand;
+ RAND_GLOBAL *dgbl = rand_get_global(libctx);
+ EVP_RAND_CTX *ctx;
+ char *name;
-/*
- * Add random bytes to the random pool.
- *
- * It is expected that the |buffer| contains |len| bytes of
- * random input which contains at least |entropy| bits of
- * randomness.
- *
- * Returns 1 if the added amount is adequate, otherwise 0
- */
-int rand_pool_add(RAND_POOL *pool,
- const unsigned char *buffer, size_t len, size_t entropy)
-{
- if (len > pool->max_len - pool->len) {
- RANDerr(RAND_F_RAND_POOL_ADD, RAND_R_ENTROPY_INPUT_TOO_LONG);
- return 0;
+ if (dgbl == NULL)
+ return NULL;
+ name = dgbl->seed_name != NULL ? dgbl->seed_name : "SEED-SRC";
+ rand = EVP_RAND_fetch(libctx, name, dgbl->seed_propq);
+ if (rand == NULL) {
+ ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_FETCH_DRBG);
+ return NULL;
}
-
- if (pool->buffer == NULL) {
- RANDerr(RAND_F_RAND_POOL_ADD, ERR_R_INTERNAL_ERROR);
- return 0;
+ ctx = EVP_RAND_CTX_new(rand, NULL);
+ EVP_RAND_free(rand);
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_CREATE_DRBG);
+ return NULL;
}
-
- if (len > 0) {
- /*
- * This is to protect us from accidentally passing the buffer
- * returned from rand_pool_add_begin.
- * The check for alloc_len makes sure we do not compare the
- * address of the end of the allocated memory to something
- * different, since that comparison would have an
- * indeterminate result.
- */
- if (pool->alloc_len > pool->len && pool->buffer + pool->len == buffer) {
- RANDerr(RAND_F_RAND_POOL_ADD, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- /*
- * We have that only for cases when a pool is used to collect
- * additional data.
- * For entropy data, as long as the allocation request stays within
- * the limits given by rand_pool_bytes_needed this rand_pool_grow
- * below is guaranteed to succeed, thus no allocation happens.
- */
- if (!rand_pool_grow(pool, len))
- return 0;
- memcpy(pool->buffer + pool->len, buffer, len);
- pool->len += len;
- pool->entropy += entropy;
+ if (!EVP_RAND_instantiate(ctx, 0, 0, NULL, 0, NULL)) {
+ ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_INSTANTIATING_DRBG);
+ EVP_RAND_CTX_free(ctx);
+ return NULL;
}
-
- return 1;
+ return ctx;
}
+#endif
-/*
- * Start to add random bytes to the random pool in-place.
- *
- * Reserves the next |len| bytes for adding random bytes in-place
- * and returns a pointer to the buffer.
- * The caller is allowed to copy up to |len| bytes into the buffer.
- * If |len| == 0 this is considered a no-op and a NULL pointer
- * is returned without producing an error message.
- *
- * After updating the buffer, rand_pool_add_end() needs to be called
- * to finish the update operation (see next comment).
- */
-unsigned char *rand_pool_add_begin(RAND_POOL *pool, size_t len)
+static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent,
+ unsigned int reseed_interval,
+ time_t reseed_time_interval)
{
- if (len == 0)
- return NULL;
+ EVP_RAND *rand;
+ RAND_GLOBAL *dgbl = rand_get_global(libctx);
+ EVP_RAND_CTX *ctx;
+ OSSL_PARAM params[7], *p = params;
+ char *name, *cipher;
- if (len > pool->max_len - pool->len) {
- RANDerr(RAND_F_RAND_POOL_ADD_BEGIN, RAND_R_RANDOM_POOL_OVERFLOW);
+ if (dgbl == NULL)
+ return NULL;
+ name = dgbl->rng_name != NULL ? dgbl->rng_name : "CTR-DRBG";
+ rand = EVP_RAND_fetch(libctx, name, dgbl->rng_propq);
+ if (rand == NULL) {
+ ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_FETCH_DRBG);
return NULL;
}
-
- if (pool->buffer == NULL) {
- RANDerr(RAND_F_RAND_POOL_ADD_BEGIN, ERR_R_INTERNAL_ERROR);
+ ctx = EVP_RAND_CTX_new(rand, parent);
+ EVP_RAND_free(rand);
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_CREATE_DRBG);
return NULL;
}
/*
- * As long as the allocation request stays within the limits given
- * by rand_pool_bytes_needed this rand_pool_grow below is guaranteed
- * to succeed, thus no allocation happens.
- * We have that only for cases when a pool is used to collect
- * additional data. Then the buffer might need to grow here,
- * and of course the caller is responsible to check the return
- * value of this function.
+ * Rather than trying to decode the DRBG settings, just pass them through
+ * and rely on the other end to ignore those it doesn't care about.
*/
- if (!rand_pool_grow(pool, len))
+ cipher = dgbl->rng_cipher != NULL ? dgbl->rng_cipher : "AES-256-CTR";
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER,
+ cipher, 0);
+ if (dgbl->rng_digest != NULL)
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_DIGEST,
+ dgbl->rng_digest, 0);
+ if (dgbl->rng_propq != NULL)
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_PROPERTIES,
+ dgbl->rng_propq, 0);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_MAC, "HMAC", 0);
+ *p++ = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS,
+ &reseed_interval);
+ *p++ = OSSL_PARAM_construct_time_t(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL,
+ &reseed_time_interval);
+ *p = OSSL_PARAM_construct_end();
+ if (!EVP_RAND_instantiate(ctx, 0, 0, NULL, 0, params)) {
+ ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_INSTANTIATING_DRBG);
+ EVP_RAND_CTX_free(ctx);
return NULL;
-
- return pool->buffer + pool->len;
+ }
+ return ctx;
}
/*
- * Finish to add random bytes to the random pool in-place.
+ * Get the primary random generator.
+ * Returns pointer to its EVP_RAND_CTX on success, NULL on failure.
*
- * Finishes an in-place update of the random pool started by
- * rand_pool_add_begin() (see previous comment).
- * It is expected that |len| bytes of random input have been added
- * to the buffer which contain at least |entropy| bits of randomness.
- * It is allowed to add less bytes than originally reserved.
*/
-int rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy)
+EVP_RAND_CTX *RAND_get0_primary(OSSL_LIB_CTX *ctx)
{
- if (len > pool->alloc_len - pool->len) {
- RANDerr(RAND_F_RAND_POOL_ADD_END, RAND_R_RANDOM_POOL_OVERFLOW);
- return 0;
- }
+ RAND_GLOBAL *dgbl = rand_get_global(ctx);
+ EVP_RAND_CTX *ret;
- if (len > 0) {
- pool->len += len;
- pool->entropy += entropy;
- }
-
- return 1;
-}
+ if (dgbl == NULL)
+ return NULL;
-int RAND_set_rand_method(const RAND_METHOD *meth)
-{
- if (!RUN_ONCE(&rand_init, do_rand_init))
- return 0;
+ if (!CRYPTO_THREAD_read_lock(dgbl->lock))
+ return NULL;
- CRYPTO_THREAD_write_lock(rand_meth_lock);
-#ifndef OPENSSL_NO_ENGINE
- ENGINE_finish(funct_ref);
- funct_ref = NULL;
-#endif
- default_RAND_meth = meth;
- CRYPTO_THREAD_unlock(rand_meth_lock);
- return 1;
-}
+ ret = dgbl->primary;
+ CRYPTO_THREAD_unlock(dgbl->lock);
-const RAND_METHOD *RAND_get_rand_method(void)
-{
- const RAND_METHOD *tmp_meth = NULL;
+ if (ret != NULL)
+ return ret;
- if (!RUN_ONCE(&rand_init, do_rand_init))
+ if (!CRYPTO_THREAD_write_lock(dgbl->lock))
return NULL;
- CRYPTO_THREAD_write_lock(rand_meth_lock);
- if (default_RAND_meth == NULL) {
-#ifndef OPENSSL_NO_ENGINE
- ENGINE *e;
+ ret = dgbl->primary;
+ if (ret != NULL) {
+ CRYPTO_THREAD_unlock(dgbl->lock);
+ return ret;
+ }
- /* If we have an engine that can do RAND, use it. */
- if ((e = ENGINE_get_default_RAND()) != NULL
- && (tmp_meth = ENGINE_get_RAND(e)) != NULL) {
- funct_ref = e;
- default_RAND_meth = tmp_meth;
- } else {
- ENGINE_finish(e);
- default_RAND_meth = &rand_meth;
- }
-#else
- default_RAND_meth = &rand_meth;
+#ifndef FIPS_MODULE
+ if (dgbl->seed == NULL) {
+ ERR_set_mark();
+ dgbl->seed = rand_new_seed(ctx);
+ ERR_pop_to_mark();
+ }
#endif
+
+ ret = dgbl->primary = rand_new_drbg(ctx, dgbl->seed,
+ PRIMARY_RESEED_INTERVAL,
+ PRIMARY_RESEED_TIME_INTERVAL);
+ /*
+ * The primary DRBG may be shared between multiple threads so we must
+ * enable locking.
+ */
+ if (ret != NULL && !EVP_RAND_enable_locking(ret)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNABLE_TO_ENABLE_LOCKING);
+ EVP_RAND_CTX_free(ret);
+ ret = dgbl->primary = NULL;
}
- tmp_meth = default_RAND_meth;
- CRYPTO_THREAD_unlock(rand_meth_lock);
- return tmp_meth;
+ CRYPTO_THREAD_unlock(dgbl->lock);
+
+ return ret;
}
-#ifndef OPENSSL_NO_ENGINE
-int RAND_set_rand_engine(ENGINE *engine)
+/*
+ * Get the public random generator.
+ * Returns pointer to its EVP_RAND_CTX on success, NULL on failure.
+ */
+EVP_RAND_CTX *RAND_get0_public(OSSL_LIB_CTX *ctx)
{
- const RAND_METHOD *tmp_meth = NULL;
+ RAND_GLOBAL *dgbl = rand_get_global(ctx);
+ EVP_RAND_CTX *rand, *primary;
- if (!RUN_ONCE(&rand_init, do_rand_init))
- return 0;
+ if (dgbl == NULL)
+ return NULL;
- if (engine != NULL) {
- if (!ENGINE_init(engine))
- return 0;
- tmp_meth = ENGINE_get_RAND(engine);
- if (tmp_meth == NULL) {
- ENGINE_finish(engine);
- return 0;
- }
+ rand = CRYPTO_THREAD_get_local(&dgbl->public);
+ if (rand == NULL) {
+ primary = RAND_get0_primary(ctx);
+ if (primary == NULL)
+ return NULL;
+
+ ctx = ossl_lib_ctx_get_concrete(ctx);
+ /*
+ * If the private is also NULL then this is the first time we've
+ * used this thread.
+ */
+ if (CRYPTO_THREAD_get_local(&dgbl->private) == NULL
+ && !ossl_init_thread_start(NULL, ctx, rand_delete_thread_state))
+ return NULL;
+ rand = rand_new_drbg(ctx, primary, SECONDARY_RESEED_INTERVAL,
+ SECONDARY_RESEED_TIME_INTERVAL);
+ CRYPTO_THREAD_set_local(&dgbl->public, rand);
}
- CRYPTO_THREAD_write_lock(rand_engine_lock);
- /* This function releases any prior ENGINE so call it first */
- RAND_set_rand_method(tmp_meth);
- funct_ref = engine;
- CRYPTO_THREAD_unlock(rand_engine_lock);
- return 1;
+ return rand;
}
-#endif
-void RAND_seed(const void *buf, int num)
+/*
+ * Get the private random generator.
+ * Returns pointer to its EVP_RAND_CTX on success, NULL on failure.
+ */
+EVP_RAND_CTX *RAND_get0_private(OSSL_LIB_CTX *ctx)
{
- const RAND_METHOD *meth = RAND_get_rand_method();
+ RAND_GLOBAL *dgbl = rand_get_global(ctx);
+ EVP_RAND_CTX *rand, *primary;
- if (meth != NULL && meth->seed != NULL)
- meth->seed(buf, num);
+ if (dgbl == NULL)
+ return NULL;
+
+ rand = CRYPTO_THREAD_get_local(&dgbl->private);
+ if (rand == NULL) {
+ primary = RAND_get0_primary(ctx);
+ if (primary == NULL)
+ return NULL;
+
+ ctx = ossl_lib_ctx_get_concrete(ctx);
+ /*
+ * If the public is also NULL then this is the first time we've
+ * used this thread.
+ */
+ if (CRYPTO_THREAD_get_local(&dgbl->public) == NULL
+ && !ossl_init_thread_start(NULL, ctx, rand_delete_thread_state))
+ return NULL;
+ rand = rand_new_drbg(ctx, primary, SECONDARY_RESEED_INTERVAL,
+ SECONDARY_RESEED_TIME_INTERVAL);
+ CRYPTO_THREAD_set_local(&dgbl->private, rand);
+ }
+ return rand;
}
-void RAND_add(const void *buf, int num, double randomness)
+#ifndef FIPS_MODULE
+static int random_set_string(char **p, const char *s)
{
- const RAND_METHOD *meth = RAND_get_rand_method();
+ char *d = NULL;
- if (meth != NULL && meth->add != NULL)
- meth->add(buf, num, randomness);
+ if (s != NULL) {
+ d = OPENSSL_strdup(s);
+ if (d == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ OPENSSL_free(*p);
+ *p = d;
+ return 1;
}
/*
- * This function is not part of RAND_METHOD, so if we're not using
- * the default method, then just call RAND_bytes(). Otherwise make
- * sure we're instantiated and use the private DRBG.
+ * Load the DRBG definitions from a configuration file.
*/
-int RAND_priv_bytes(unsigned char *buf, int num)
+static int random_conf_init(CONF_IMODULE *md, const CONF *cnf)
{
- const RAND_METHOD *meth = RAND_get_rand_method();
- RAND_DRBG *drbg;
+ STACK_OF(CONF_VALUE) *elist;
+ CONF_VALUE *cval;
+ RAND_GLOBAL *dgbl = rand_get_global(NCONF_get0_libctx((CONF *)cnf));
+ int i, r = 1;
- if (meth != NULL && meth != RAND_OpenSSL())
- return RAND_bytes(buf, num);
+ OSSL_TRACE1(CONF, "Loading random module: section %s\n",
+ CONF_imodule_get_value(md));
- drbg = RAND_DRBG_get0_private();
- if (drbg != NULL)
- return RAND_DRBG_bytes(drbg, buf, num);
+ /* Value is a section containing RANDOM configuration */
+ elist = NCONF_get_section(cnf, CONF_imodule_get_value(md));
+ if (elist == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_RANDOM_SECTION_ERROR);
+ return 0;
+ }
- return 0;
+ if (dgbl == NULL)
+ return 0;
+
+ for (i = 0; i < sk_CONF_VALUE_num(elist); i++) {
+ cval = sk_CONF_VALUE_value(elist, i);
+ if (OPENSSL_strcasecmp(cval->name, "random") == 0) {
+ if (!random_set_string(&dgbl->rng_name, cval->value))
+ return 0;
+ } else if (OPENSSL_strcasecmp(cval->name, "cipher") == 0) {
+ if (!random_set_string(&dgbl->rng_cipher, cval->value))
+ return 0;
+ } else if (OPENSSL_strcasecmp(cval->name, "digest") == 0) {
+ if (!random_set_string(&dgbl->rng_digest, cval->value))
+ return 0;
+ } else if (OPENSSL_strcasecmp(cval->name, "properties") == 0) {
+ if (!random_set_string(&dgbl->rng_propq, cval->value))
+ return 0;
+ } else if (OPENSSL_strcasecmp(cval->name, "seed") == 0) {
+ if (!random_set_string(&dgbl->seed_name, cval->value))
+ return 0;
+ } else if (OPENSSL_strcasecmp(cval->name, "seed_properties") == 0) {
+ if (!random_set_string(&dgbl->seed_propq, cval->value))
+ return 0;
+ } else {
+ ERR_raise_data(ERR_LIB_CRYPTO,
+ CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION,
+ "name=%s, value=%s", cval->name, cval->value);
+ r = 0;
+ }
+ }
+ return r;
}
-int RAND_bytes(unsigned char *buf, int num)
+
+static void random_conf_deinit(CONF_IMODULE *md)
{
- const RAND_METHOD *meth = RAND_get_rand_method();
+ OSSL_TRACE(CONF, "Cleaned up random\n");
+}
- if (meth != NULL && meth->bytes != NULL)
- return meth->bytes(buf, num);
- RANDerr(RAND_F_RAND_BYTES, RAND_R_FUNC_NOT_IMPLEMENTED);
- return -1;
+void ossl_random_add_conf_module(void)
+{
+ OSSL_TRACE(CONF, "Adding config module 'random'\n");
+ CONF_module_add("random", random_conf_init, random_conf_deinit);
}
-#if OPENSSL_API_COMPAT < 0x10100000L
-int RAND_pseudo_bytes(unsigned char *buf, int num)
+int RAND_set_DRBG_type(OSSL_LIB_CTX *ctx, const char *drbg, const char *propq,
+ const char *cipher, const char *digest)
{
- const RAND_METHOD *meth = RAND_get_rand_method();
+ RAND_GLOBAL *dgbl = rand_get_global(ctx);
- if (meth != NULL && meth->pseudorand != NULL)
- return meth->pseudorand(buf, num);
- RANDerr(RAND_F_RAND_PSEUDO_BYTES, RAND_R_FUNC_NOT_IMPLEMENTED);
- return -1;
+ if (dgbl == NULL)
+ return 0;
+ if (dgbl->primary != NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, RAND_R_ALREADY_INSTANTIATED);
+ return 0;
+ }
+ return random_set_string(&dgbl->rng_name, drbg)
+ && random_set_string(&dgbl->rng_propq, propq)
+ && random_set_string(&dgbl->rng_cipher, cipher)
+ && random_set_string(&dgbl->rng_digest, digest);
}
-#endif
-int RAND_status(void)
+int RAND_set_seed_source_type(OSSL_LIB_CTX *ctx, const char *seed,
+ const char *propq)
{
- const RAND_METHOD *meth = RAND_get_rand_method();
+ RAND_GLOBAL *dgbl = rand_get_global(ctx);
- if (meth != NULL && meth->status != NULL)
- return meth->status();
- return 0;
+ if (dgbl == NULL)
+ return 0;
+ if (dgbl->primary != NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, RAND_R_ALREADY_INSTANTIATED);
+ return 0;
+ }
+ return random_set_string(&dgbl->seed_name, seed)
+ && random_set_string(&dgbl->seed_propq, propq);
}
+
+#endif
diff --git a/crypto/rand/rand_local.h b/crypto/rand/rand_local.h
index a5de5252dcdc..31428f20c85e 100644
--- a/crypto/rand/rand_local.h
+++ b/crypto/rand/rand_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -15,292 +15,19 @@
# include <openssl/sha.h>
# include <openssl/hmac.h>
# include <openssl/ec.h>
-# include <openssl/rand_drbg.h>
+# include <openssl/rand.h>
# include "internal/tsan_assist.h"
-
-# include "internal/numbers.h"
-
-/* How many times to read the TSC as a randomness source. */
-# define TSC_READ_COUNT 4
-
-/* Maximum reseed intervals */
-# define MAX_RESEED_INTERVAL (1 << 24)
-# define MAX_RESEED_TIME_INTERVAL (1 << 20) /* approx. 12 days */
+# include "crypto/rand.h"
/* Default reseed intervals */
-# define MASTER_RESEED_INTERVAL (1 << 8)
-# define SLAVE_RESEED_INTERVAL (1 << 16)
-# define MASTER_RESEED_TIME_INTERVAL (60*60) /* 1 hour */
-# define SLAVE_RESEED_TIME_INTERVAL (7*60) /* 7 minutes */
-
-
-
-/*
- * Maximum input size for the DRBG (entropy, nonce, personalization string)
- *
- * NIST SP800 90Ar1 allows a maximum of (1 << 35) bits i.e., (1 << 32) bytes.
- *
- * We lower it to 'only' INT32_MAX bytes, which is equivalent to 2 gigabytes.
- */
-# define DRBG_MAX_LENGTH INT32_MAX
-
-
-/*
- * Maximum allocation size for RANDOM_POOL buffers
- *
- * The max_len value for the buffer provided to the rand_drbg_get_entropy()
- * callback is currently 2^31 bytes (2 gigabytes), if a derivation function
- * is used. Since this is much too large to be allocated, the rand_pool_new()
- * function chooses more modest values as default pool length, bounded
- * by RAND_POOL_MIN_LENGTH and RAND_POOL_MAX_LENGTH
- *
- * The choice of the RAND_POOL_FACTOR is large enough such that the
- * RAND_POOL can store a random input which has a lousy entropy rate of
- * 8/256 (= 0.03125) bits per byte. This input will be sent through the
- * derivation function which 'compresses' the low quality input into a
- * high quality output.
- *
- * The factor 1.5 below is the pessimistic estimate for the extra amount
- * of entropy required when no get_nonce() callback is defined.
- */
-# define RAND_POOL_FACTOR 256
-# define RAND_POOL_MAX_LENGTH (RAND_POOL_FACTOR * \
- 3 * (RAND_DRBG_STRENGTH / 16))
-/*
- * = (RAND_POOL_FACTOR * \
- * 1.5 * (RAND_DRBG_STRENGTH / 8))
- */
-
-/*
- * Initial allocation minimum.
- *
- * There is a distinction between the secure and normal allocation minimums.
- * Ideally, the secure allocation size should be a power of two. The normal
- * allocation size doesn't have any such restriction.
- *
- * The secure value is based on 128 bits of secure material, which is 16 bytes.
- * Typically, the DRBGs will set a minimum larger than this so optimal
- * allocation ought to take place (for full quality seed material).
- *
- * The normal value has been chosen by noticing that the rand_drbg_get_nonce
- * function is usually the largest of the built in allocation (twenty four
- * bytes and then appending another sixteen bytes). This means the buffer ends
- * with 40 bytes. The value of forty eight is comfortably above this which
- * allows some slack in the platform specific values used.
- */
-# define RAND_POOL_MIN_ALLOCATION(secure) ((secure) ? 16 : 48)
-
-/* DRBG status values */
-typedef enum drbg_status_e {
- DRBG_UNINITIALISED,
- DRBG_READY,
- DRBG_ERROR
-} DRBG_STATUS;
-
-
-/* instantiate */
-typedef int (*RAND_DRBG_instantiate_fn)(RAND_DRBG *ctx,
- const unsigned char *ent,
- size_t entlen,
- const unsigned char *nonce,
- size_t noncelen,
- const unsigned char *pers,
- size_t perslen);
-/* reseed */
-typedef int (*RAND_DRBG_reseed_fn)(RAND_DRBG *ctx,
- const unsigned char *ent,
- size_t entlen,
- const unsigned char *adin,
- size_t adinlen);
-/* generate output */
-typedef int (*RAND_DRBG_generate_fn)(RAND_DRBG *ctx,
- unsigned char *out,
- size_t outlen,
- const unsigned char *adin,
- size_t adinlen);
-/* uninstantiate */
-typedef int (*RAND_DRBG_uninstantiate_fn)(RAND_DRBG *ctx);
-
-
-/*
- * The DRBG methods
- */
-
-typedef struct rand_drbg_method_st {
- RAND_DRBG_instantiate_fn instantiate;
- RAND_DRBG_reseed_fn reseed;
- RAND_DRBG_generate_fn generate;
- RAND_DRBG_uninstantiate_fn uninstantiate;
-} RAND_DRBG_METHOD;
-
-
-/*
- * The state of a DRBG AES-CTR.
- */
-typedef struct rand_drbg_ctr_st {
- EVP_CIPHER_CTX *ctx_ecb;
- EVP_CIPHER_CTX *ctx_ctr;
- EVP_CIPHER_CTX *ctx_df;
- const EVP_CIPHER *cipher_ecb;
- const EVP_CIPHER *cipher_ctr;
- size_t keylen;
- unsigned char K[32];
- unsigned char V[16];
- /* Temporary block storage used by ctr_df */
- unsigned char bltmp[16];
- size_t bltmp_pos;
- unsigned char KX[48];
-} RAND_DRBG_CTR;
-
-
-/*
- * The 'random pool' acts as a dumb container for collecting random
- * input from various entropy sources. The pool has no knowledge about
- * whether its randomness is fed into a legacy RAND_METHOD via RAND_add()
- * or into a new style RAND_DRBG. It is the callers duty to 1) initialize the
- * random pool, 2) pass it to the polling callbacks, 3) seed the RNG, and
- * 4) cleanup the random pool again.
- *
- * The random pool contains no locking mechanism because its scope and
- * lifetime is intended to be restricted to a single stack frame.
- */
-struct rand_pool_st {
- unsigned char *buffer; /* points to the beginning of the random pool */
- size_t len; /* current number of random bytes contained in the pool */
-
- int attached; /* true pool was attached to existing buffer */
- int secure; /* 1: allocated on the secure heap, 0: otherwise */
-
- size_t min_len; /* minimum number of random bytes requested */
- size_t max_len; /* maximum number of random bytes (allocated buffer size) */
- size_t alloc_len; /* current number of bytes allocated */
- size_t entropy; /* current entropy count in bits */
- size_t entropy_requested; /* requested entropy count in bits */
-};
-
-/*
- * The state of all types of DRBGs, even though we only have CTR mode
- * right now.
- */
-struct rand_drbg_st {
- CRYPTO_RWLOCK *lock;
- RAND_DRBG *parent;
- int secure; /* 1: allocated on the secure heap, 0: otherwise */
- int type; /* the nid of the underlying algorithm */
- /*
- * Stores the return value of openssl_get_fork_id() as of when we last
- * reseeded. The DRBG reseeds automatically whenever drbg->fork_id !=
- * openssl_get_fork_id(). Used to provide fork-safety and reseed this
- * DRBG in the child process.
- */
- int fork_id;
- unsigned short flags; /* various external flags */
-
- /*
- * The random_data is used by RAND_add()/drbg_add() to attach random
- * data to the global drbg, such that the rand_drbg_get_entropy() callback
- * can pull it during instantiation and reseeding. This is necessary to
- * reconcile the different philosophies of the RAND and the RAND_DRBG
- * with respect to how randomness is added to the RNG during reseeding
- * (see PR #4328).
- */
- struct rand_pool_st *seed_pool;
-
- /*
- * Auxiliary pool for additional data.
- */
- struct rand_pool_st *adin_pool;
-
- /*
- * The following parameters are setup by the per-type "init" function.
- *
- * Currently the only type is CTR_DRBG, its init function is drbg_ctr_init().
- *
- * The parameters are closely related to the ones described in
- * section '10.2.1 CTR_DRBG' of [NIST SP 800-90Ar1], with one
- * crucial difference: In the NIST standard, all counts are given
- * in bits, whereas in OpenSSL entropy counts are given in bits
- * and buffer lengths are given in bytes.
- *
- * Since this difference has lead to some confusion in the past,
- * (see [GitHub Issue #2443], formerly [rt.openssl.org #4055])
- * the 'len' suffix has been added to all buffer sizes for
- * clarification.
- */
-
- int strength;
- size_t max_request;
- size_t min_entropylen, max_entropylen;
- size_t min_noncelen, max_noncelen;
- size_t max_perslen, max_adinlen;
-
- /* Counts the number of generate requests since the last reseed. */
- unsigned int generate_counter;
- /*
- * Maximum number of generate requests until a reseed is required.
- * This value is ignored if it is zero.
- */
- unsigned int reseed_interval;
- /* Stores the time when the last reseeding occurred */
- time_t reseed_time;
- /*
- * Specifies the maximum time interval (in seconds) between reseeds.
- * This value is ignored if it is zero.
- */
- time_t reseed_time_interval;
-
- /*
- * Enables reseed propagation (see following comment)
- */
- unsigned int enable_reseed_propagation;
-
- /*
- * Counts the number of reseeds since instantiation.
- * This value is ignored if enable_reseed_propagation is zero.
- *
- * This counter is used only for seed propagation from the <master> DRBG
- * to its two children, the <public> and <private> DRBG. This feature is
- * very special and its sole purpose is to ensure that any randomness which
- * is added by RAND_add() or RAND_seed() will have an immediate effect on
- * the output of RAND_bytes() resp. RAND_priv_bytes().
- */
- TSAN_QUALIFIER unsigned int reseed_counter;
-
- size_t seedlen;
- DRBG_STATUS state;
-
- /* Application data, mainly used in the KATs. */
- CRYPTO_EX_DATA ex_data;
-
- /* Implementation specific data (currently only one implementation) */
- union {
- RAND_DRBG_CTR ctr;
- } data;
-
- /* Implementation specific methods */
- RAND_DRBG_METHOD *meth;
-
- /* Callback functions. See comments in rand_lib.c */
- RAND_DRBG_get_entropy_fn get_entropy;
- RAND_DRBG_cleanup_entropy_fn cleanup_entropy;
- RAND_DRBG_get_nonce_fn get_nonce;
- RAND_DRBG_cleanup_nonce_fn cleanup_nonce;
-};
+# define PRIMARY_RESEED_INTERVAL (1 << 8)
+# define SECONDARY_RESEED_INTERVAL (1 << 16)
+# define PRIMARY_RESEED_TIME_INTERVAL (60 * 60) /* 1 hour */
+# define SECONDARY_RESEED_TIME_INTERVAL (7 * 60) /* 7 minutes */
+# ifndef FIPS_MODULE
/* The global RAND method, and the global buffer and DRBG instance. */
-extern RAND_METHOD rand_meth;
-
-/* DRBG helpers */
-int rand_drbg_restart(RAND_DRBG *drbg,
- const unsigned char *buffer, size_t len, size_t entropy);
-size_t rand_drbg_seedlen(RAND_DRBG *drbg);
-/* locking api */
-int rand_drbg_lock(RAND_DRBG *drbg);
-int rand_drbg_unlock(RAND_DRBG *drbg);
-int rand_drbg_enable_locking(RAND_DRBG *drbg);
-
-
-/* initializes the AES-CTR DRBG implementation */
-int drbg_ctr_init(RAND_DRBG *drbg);
+extern RAND_METHOD ossl_rand_meth;
+# endif
#endif
diff --git a/crypto/rand/rand_meth.c b/crypto/rand/rand_meth.c
new file mode 100644
index 000000000000..276763057db2
--- /dev/null
+++ b/crypto/rand/rand_meth.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include "rand_local.h"
+
+/* Implements the default OpenSSL RAND_add() method */
+static int drbg_add(const void *buf, int num, double randomness)
+{
+ EVP_RAND_CTX *drbg = RAND_get0_primary(NULL);
+
+ if (drbg == NULL || num <= 0)
+ return 0;
+
+ return EVP_RAND_reseed(drbg, 0, NULL, 0, buf, num);
+}
+
+/* Implements the default OpenSSL RAND_seed() method */
+static int drbg_seed(const void *buf, int num)
+{
+ return drbg_add(buf, num, num);
+}
+
+/* Implements the default OpenSSL RAND_status() method */
+static int drbg_status(void)
+{
+ EVP_RAND_CTX *drbg = RAND_get0_primary(NULL);
+
+ if (drbg == NULL)
+ return 0;
+
+ return EVP_RAND_get_state(drbg) == EVP_RAND_STATE_READY ? 1 : 0;
+}
+
+/* Implements the default OpenSSL RAND_bytes() method */
+static int drbg_bytes(unsigned char *out, int count)
+{
+ EVP_RAND_CTX *drbg = RAND_get0_public(NULL);
+
+ if (drbg == NULL)
+ return 0;
+
+ return EVP_RAND_generate(drbg, out, count, 0, 0, NULL, 0);
+}
+
+RAND_METHOD ossl_rand_meth = {
+ drbg_seed,
+ drbg_bytes,
+ NULL,
+ drbg_add,
+ drbg_bytes,
+ drbg_status
+};
+
+RAND_METHOD *RAND_OpenSSL(void)
+{
+ return &ossl_rand_meth;
+}
diff --git a/crypto/rand/rand_pool.c b/crypto/rand/rand_pool.c
new file mode 100644
index 000000000000..55f14be60e63
--- /dev/null
+++ b/crypto/rand/rand_pool.c
@@ -0,0 +1,412 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include "internal/cryptlib.h"
+#include <openssl/opensslconf.h>
+#include "crypto/rand.h"
+#include <openssl/engine.h>
+#include "internal/thread_once.h"
+#include "crypto/rand_pool.h"
+
+/*
+ * Allocate memory and initialize a new random pool
+ */
+RAND_POOL *ossl_rand_pool_new(int entropy_requested, int secure,
+ size_t min_len, size_t max_len)
+{
+ RAND_POOL *pool = OPENSSL_zalloc(sizeof(*pool));
+ size_t min_alloc_size = RAND_POOL_MIN_ALLOCATION(secure);
+
+ if (pool == NULL) {
+ ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ pool->min_len = min_len;
+ pool->max_len = (max_len > RAND_POOL_MAX_LENGTH) ?
+ RAND_POOL_MAX_LENGTH : max_len;
+ pool->alloc_len = min_len < min_alloc_size ? min_alloc_size : min_len;
+ if (pool->alloc_len > pool->max_len)
+ pool->alloc_len = pool->max_len;
+
+ if (secure)
+ pool->buffer = OPENSSL_secure_zalloc(pool->alloc_len);
+ else
+ pool->buffer = OPENSSL_zalloc(pool->alloc_len);
+
+ if (pool->buffer == NULL) {
+ ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ pool->entropy_requested = entropy_requested;
+ pool->secure = secure;
+ return pool;
+
+err:
+ OPENSSL_free(pool);
+ return NULL;
+}
+
+/*
+ * Attach new random pool to the given buffer
+ *
+ * This function is intended to be used only for feeding random data
+ * provided by RAND_add() and RAND_seed() into the <master> DRBG.
+ */
+RAND_POOL *ossl_rand_pool_attach(const unsigned char *buffer, size_t len,
+ size_t entropy)
+{
+ RAND_POOL *pool = OPENSSL_zalloc(sizeof(*pool));
+
+ if (pool == NULL) {
+ ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ /*
+ * The const needs to be cast away, but attached buffers will not be
+ * modified (in contrary to allocated buffers which are zeroed and
+ * freed in the end).
+ */
+ pool->buffer = (unsigned char *) buffer;
+ pool->len = len;
+
+ pool->attached = 1;
+
+ pool->min_len = pool->max_len = pool->alloc_len = pool->len;
+ pool->entropy = entropy;
+
+ return pool;
+}
+
+/*
+ * Free |pool|, securely erasing its buffer.
+ */
+void ossl_rand_pool_free(RAND_POOL *pool)
+{
+ if (pool == NULL)
+ return;
+
+ /*
+ * Although it would be advisable from a cryptographical viewpoint,
+ * we are not allowed to clear attached buffers, since they are passed
+ * to ossl_rand_pool_attach() as `const unsigned char*`.
+ * (see corresponding comment in ossl_rand_pool_attach()).
+ */
+ if (!pool->attached) {
+ if (pool->secure)
+ OPENSSL_secure_clear_free(pool->buffer, pool->alloc_len);
+ else
+ OPENSSL_clear_free(pool->buffer, pool->alloc_len);
+ }
+
+ OPENSSL_free(pool);
+}
+
+/*
+ * Return the |pool|'s buffer to the caller (readonly).
+ */
+const unsigned char *ossl_rand_pool_buffer(RAND_POOL *pool)
+{
+ return pool->buffer;
+}
+
+/*
+ * Return the |pool|'s entropy to the caller.
+ */
+size_t ossl_rand_pool_entropy(RAND_POOL *pool)
+{
+ return pool->entropy;
+}
+
+/*
+ * Return the |pool|'s buffer length to the caller.
+ */
+size_t ossl_rand_pool_length(RAND_POOL *pool)
+{
+ return pool->len;
+}
+
+/*
+ * Detach the |pool| buffer and return it to the caller.
+ * It's the responsibility of the caller to free the buffer
+ * using OPENSSL_secure_clear_free() or to re-attach it
+ * again to the pool using ossl_rand_pool_reattach().
+ */
+unsigned char *ossl_rand_pool_detach(RAND_POOL *pool)
+{
+ unsigned char *ret = pool->buffer;
+ pool->buffer = NULL;
+ pool->entropy = 0;
+ return ret;
+}
+
+/*
+ * Re-attach the |pool| buffer. It is only allowed to pass
+ * the |buffer| which was previously detached from the same pool.
+ */
+void ossl_rand_pool_reattach(RAND_POOL *pool, unsigned char *buffer)
+{
+ pool->buffer = buffer;
+ OPENSSL_cleanse(pool->buffer, pool->len);
+ pool->len = 0;
+}
+
+/*
+ * If |entropy_factor| bits contain 1 bit of entropy, how many bytes does one
+ * need to obtain at least |bits| bits of entropy?
+ */
+#define ENTROPY_TO_BYTES(bits, entropy_factor) \
+ (((bits) * (entropy_factor) + 7) / 8)
+
+
+/*
+ * Checks whether the |pool|'s entropy is available to the caller.
+ * This is the case when entropy count and buffer length are high enough.
+ * Returns
+ *
+ * |entropy| if the entropy count and buffer size is large enough
+ * 0 otherwise
+ */
+size_t ossl_rand_pool_entropy_available(RAND_POOL *pool)
+{
+ if (pool->entropy < pool->entropy_requested)
+ return 0;
+
+ if (pool->len < pool->min_len)
+ return 0;
+
+ return pool->entropy;
+}
+
+/*
+ * Returns the (remaining) amount of entropy needed to fill
+ * the random pool.
+ */
+
+size_t ossl_rand_pool_entropy_needed(RAND_POOL *pool)
+{
+ if (pool->entropy < pool->entropy_requested)
+ return pool->entropy_requested - pool->entropy;
+
+ return 0;
+}
+
+/* Increase the allocation size -- not usable for an attached pool */
+static int rand_pool_grow(RAND_POOL *pool, size_t len)
+{
+ if (len > pool->alloc_len - pool->len) {
+ unsigned char *p;
+ const size_t limit = pool->max_len / 2;
+ size_t newlen = pool->alloc_len;
+
+ if (pool->attached || len > pool->max_len - pool->len) {
+ ERR_raise(ERR_LIB_RAND, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ do
+ newlen = newlen < limit ? newlen * 2 : pool->max_len;
+ while (len > newlen - pool->len);
+
+ if (pool->secure)
+ p = OPENSSL_secure_zalloc(newlen);
+ else
+ p = OPENSSL_zalloc(newlen);
+ if (p == NULL) {
+ ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ memcpy(p, pool->buffer, pool->len);
+ if (pool->secure)
+ OPENSSL_secure_clear_free(pool->buffer, pool->alloc_len);
+ else
+ OPENSSL_clear_free(pool->buffer, pool->alloc_len);
+ pool->buffer = p;
+ pool->alloc_len = newlen;
+ }
+ return 1;
+}
+
+/*
+ * Returns the number of bytes needed to fill the pool, assuming
+ * the input has 1 / |entropy_factor| entropy bits per data bit.
+ * In case of an error, 0 is returned.
+ */
+
+size_t ossl_rand_pool_bytes_needed(RAND_POOL *pool, unsigned int entropy_factor)
+{
+ size_t bytes_needed;
+ size_t entropy_needed = ossl_rand_pool_entropy_needed(pool);
+
+ if (entropy_factor < 1) {
+ ERR_raise(ERR_LIB_RAND, RAND_R_ARGUMENT_OUT_OF_RANGE);
+ return 0;
+ }
+
+ bytes_needed = ENTROPY_TO_BYTES(entropy_needed, entropy_factor);
+
+ if (bytes_needed > pool->max_len - pool->len) {
+ /* not enough space left */
+ ERR_raise(ERR_LIB_RAND, RAND_R_RANDOM_POOL_OVERFLOW);
+ return 0;
+ }
+
+ if (pool->len < pool->min_len &&
+ bytes_needed < pool->min_len - pool->len)
+ /* to meet the min_len requirement */
+ bytes_needed = pool->min_len - pool->len;
+
+ /*
+ * Make sure the buffer is large enough for the requested amount
+ * of data. This guarantees that existing code patterns where
+ * ossl_rand_pool_add_begin, ossl_rand_pool_add_end or ossl_rand_pool_add
+ * are used to collect entropy data without any error handling
+ * whatsoever, continue to be valid.
+ * Furthermore if the allocation here fails once, make sure that
+ * we don't fall back to a less secure or even blocking random source,
+ * as that could happen by the existing code patterns.
+ * This is not a concern for additional data, therefore that
+ * is not needed if rand_pool_grow fails in other places.
+ */
+ if (!rand_pool_grow(pool, bytes_needed)) {
+ /* persistent error for this pool */
+ pool->max_len = pool->len = 0;
+ return 0;
+ }
+
+ return bytes_needed;
+}
+
+/* Returns the remaining number of bytes available */
+size_t ossl_rand_pool_bytes_remaining(RAND_POOL *pool)
+{
+ return pool->max_len - pool->len;
+}
+
+/*
+ * Add random bytes to the random pool.
+ *
+ * It is expected that the |buffer| contains |len| bytes of
+ * random input which contains at least |entropy| bits of
+ * randomness.
+ *
+ * Returns 1 if the added amount is adequate, otherwise 0
+ */
+int ossl_rand_pool_add(RAND_POOL *pool,
+ const unsigned char *buffer, size_t len, size_t entropy)
+{
+ if (len > pool->max_len - pool->len) {
+ ERR_raise(ERR_LIB_RAND, RAND_R_ENTROPY_INPUT_TOO_LONG);
+ return 0;
+ }
+
+ if (pool->buffer == NULL) {
+ ERR_raise(ERR_LIB_RAND, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (len > 0) {
+ /*
+ * This is to protect us from accidentally passing the buffer
+ * returned from ossl_rand_pool_add_begin.
+ * The check for alloc_len makes sure we do not compare the
+ * address of the end of the allocated memory to something
+ * different, since that comparison would have an
+ * indeterminate result.
+ */
+ if (pool->alloc_len > pool->len && pool->buffer + pool->len == buffer) {
+ ERR_raise(ERR_LIB_RAND, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ /*
+ * We have that only for cases when a pool is used to collect
+ * additional data.
+ * For entropy data, as long as the allocation request stays within
+ * the limits given by ossl_rand_pool_bytes_needed this rand_pool_grow
+ * below is guaranteed to succeed, thus no allocation happens.
+ */
+ if (!rand_pool_grow(pool, len))
+ return 0;
+ memcpy(pool->buffer + pool->len, buffer, len);
+ pool->len += len;
+ pool->entropy += entropy;
+ }
+
+ return 1;
+}
+
+/*
+ * Start to add random bytes to the random pool in-place.
+ *
+ * Reserves the next |len| bytes for adding random bytes in-place
+ * and returns a pointer to the buffer.
+ * The caller is allowed to copy up to |len| bytes into the buffer.
+ * If |len| == 0 this is considered a no-op and a NULL pointer
+ * is returned without producing an error message.
+ *
+ * After updating the buffer, ossl_rand_pool_add_end() needs to be called
+ * to finish the update operation (see next comment).
+ */
+unsigned char *ossl_rand_pool_add_begin(RAND_POOL *pool, size_t len)
+{
+ if (len == 0)
+ return NULL;
+
+ if (len > pool->max_len - pool->len) {
+ ERR_raise(ERR_LIB_RAND, RAND_R_RANDOM_POOL_OVERFLOW);
+ return NULL;
+ }
+
+ if (pool->buffer == NULL) {
+ ERR_raise(ERR_LIB_RAND, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ /*
+ * As long as the allocation request stays within the limits given
+ * by ossl_rand_pool_bytes_needed this rand_pool_grow below is guaranteed
+ * to succeed, thus no allocation happens.
+ * We have that only for cases when a pool is used to collect
+ * additional data. Then the buffer might need to grow here,
+ * and of course the caller is responsible to check the return
+ * value of this function.
+ */
+ if (!rand_pool_grow(pool, len))
+ return NULL;
+
+ return pool->buffer + pool->len;
+}
+
+/*
+ * Finish to add random bytes to the random pool in-place.
+ *
+ * Finishes an in-place update of the random pool started by
+ * ossl_rand_pool_add_begin() (see previous comment).
+ * It is expected that |len| bytes of random input have been added
+ * to the buffer which contain at least |entropy| bits of randomness.
+ * It is allowed to add less bytes than originally reserved.
+ */
+int ossl_rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy)
+{
+ if (len > pool->alloc_len - pool->len) {
+ ERR_raise(ERR_LIB_RAND, RAND_R_RANDOM_POOL_OVERFLOW);
+ return 0;
+ }
+
+ if (len > 0) {
+ pool->len += len;
+ pool->entropy += entropy;
+ }
+
+ return 1;
+}
diff --git a/crypto/rand/rand_unix.c b/crypto/rand/rand_unix.c
deleted file mode 100644
index 0f4525106af7..000000000000
--- a/crypto/rand/rand_unix.c
+++ /dev/null
@@ -1,880 +0,0 @@
-/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-#endif
-#include "e_os.h"
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/rand.h>
-#include <openssl/crypto.h>
-#include "rand_local.h"
-#include "crypto/rand.h"
-#include <stdio.h>
-#include "internal/dso.h"
-#ifdef __linux
-# include <sys/syscall.h>
-# ifdef DEVRANDOM_WAIT
-# include <sys/shm.h>
-# include <sys/utsname.h>
-# endif
-#endif
-#if (defined(__FreeBSD__) || defined(__NetBSD__)) && !defined(OPENSSL_SYS_UEFI)
-# include <sys/types.h>
-# include <sys/sysctl.h>
-# include <sys/param.h>
-#endif
-#if defined(__OpenBSD__)
-# include <sys/param.h>
-#endif
-
-#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <fcntl.h>
-# include <unistd.h>
-# include <sys/time.h>
-
-static uint64_t get_time_stamp(void);
-static uint64_t get_timer_bits(void);
-
-/* Macro to convert two thirty two bit values into a sixty four bit one */
-# define TWO32TO64(a, b) ((((uint64_t)(a)) << 32) + (b))
-
-/*
- * Check for the existence and support of POSIX timers. The standard
- * says that the _POSIX_TIMERS macro will have a positive value if they
- * are available.
- *
- * However, we want an additional constraint: that the timer support does
- * not require an extra library dependency. Early versions of glibc
- * require -lrt to be specified on the link line to access the timers,
- * so this needs to be checked for.
- *
- * It is worse because some libraries define __GLIBC__ but don't
- * support the version testing macro (e.g. uClibc). This means
- * an extra check is needed.
- *
- * The final condition is:
- * "have posix timers and either not glibc or glibc without -lrt"
- *
- * The nested #if sequences are required to avoid using a parameterised
- * macro that might be undefined.
- */
-# undef OSSL_POSIX_TIMER_OKAY
-# if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
-# if defined(__GLIBC__)
-# if defined(__GLIBC_PREREQ)
-# if __GLIBC_PREREQ(2, 17)
-# define OSSL_POSIX_TIMER_OKAY
-# endif
-# endif
-# else
-# define OSSL_POSIX_TIMER_OKAY
-# endif
-# endif
-#endif /* (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS))
- || defined(__DJGPP__) */
-
-#if defined(OPENSSL_RAND_SEED_NONE)
-/* none means none. this simplifies the following logic */
-# undef OPENSSL_RAND_SEED_OS
-# undef OPENSSL_RAND_SEED_GETRANDOM
-# undef OPENSSL_RAND_SEED_LIBRANDOM
-# undef OPENSSL_RAND_SEED_DEVRANDOM
-# undef OPENSSL_RAND_SEED_RDTSC
-# undef OPENSSL_RAND_SEED_RDCPU
-# undef OPENSSL_RAND_SEED_EGD
-#endif
-
-#if (defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)) && \
- !defined(OPENSSL_RAND_SEED_NONE)
-# error "UEFI and VXWorks only support seeding NONE"
-#endif
-
-#if defined(OPENSSL_SYS_VXWORKS)
-/* empty implementation */
-int rand_pool_init(void)
-{
- return 1;
-}
-
-void rand_pool_cleanup(void)
-{
-}
-
-void rand_pool_keep_random_devices_open(int keep)
-{
-}
-
-size_t rand_pool_acquire_entropy(RAND_POOL *pool)
-{
- return rand_pool_entropy_available(pool);
-}
-#endif
-
-#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) \
- || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_VXWORKS) \
- || defined(OPENSSL_SYS_UEFI))
-
-# if defined(OPENSSL_SYS_VOS)
-
-# ifndef OPENSSL_RAND_SEED_OS
-# error "Unsupported seeding method configured; must be os"
-# endif
-
-# if defined(OPENSSL_SYS_VOS_HPPA) && defined(OPENSSL_SYS_VOS_IA32)
-# error "Unsupported HP-PA and IA32 at the same time."
-# endif
-# if !defined(OPENSSL_SYS_VOS_HPPA) && !defined(OPENSSL_SYS_VOS_IA32)
-# error "Must have one of HP-PA or IA32"
-# endif
-
-/*
- * The following algorithm repeatedly samples the real-time clock (RTC) to
- * generate a sequence of unpredictable data. The algorithm relies upon the
- * uneven execution speed of the code (due to factors such as cache misses,
- * interrupts, bus activity, and scheduling) and upon the rather large
- * relative difference between the speed of the clock and the rate at which
- * it can be read. If it is ported to an environment where execution speed
- * is more constant or where the RTC ticks at a much slower rate, or the
- * clock can be read with fewer instructions, it is likely that the results
- * would be far more predictable. This should only be used for legacy
- * platforms.
- *
- * As a precaution, we assume only 2 bits of entropy per byte.
- */
-size_t rand_pool_acquire_entropy(RAND_POOL *pool)
-{
- short int code;
- int i, k;
- size_t bytes_needed;
- struct timespec ts;
- unsigned char v;
-# ifdef OPENSSL_SYS_VOS_HPPA
- long duration;
- extern void s$sleep(long *_duration, short int *_code);
-# else
- long long duration;
- extern void s$sleep2(long long *_duration, short int *_code);
-# endif
-
- bytes_needed = rand_pool_bytes_needed(pool, 4 /*entropy_factor*/);
-
- for (i = 0; i < bytes_needed; i++) {
- /*
- * burn some cpu; hope for interrupts, cache collisions, bus
- * interference, etc.
- */
- for (k = 0; k < 99; k++)
- ts.tv_nsec = random();
-
-# ifdef OPENSSL_SYS_VOS_HPPA
- /* sleep for 1/1024 of a second (976 us). */
- duration = 1;
- s$sleep(&duration, &code);
-# else
- /* sleep for 1/65536 of a second (15 us). */
- duration = 1;
- s$sleep2(&duration, &code);
-# endif
-
- /* Get wall clock time, take 8 bits. */
- clock_gettime(CLOCK_REALTIME, &ts);
- v = (unsigned char)(ts.tv_nsec & 0xFF);
- rand_pool_add(pool, arg, &v, sizeof(v) , 2);
- }
- return rand_pool_entropy_available(pool);
-}
-
-void rand_pool_cleanup(void)
-{
-}
-
-void rand_pool_keep_random_devices_open(int keep)
-{
-}
-
-# else
-
-# if defined(OPENSSL_RAND_SEED_EGD) && \
- (defined(OPENSSL_NO_EGD) || !defined(DEVRANDOM_EGD))
-# error "Seeding uses EGD but EGD is turned off or no device given"
-# endif
-
-# if defined(OPENSSL_RAND_SEED_DEVRANDOM) && !defined(DEVRANDOM)
-# error "Seeding uses urandom but DEVRANDOM is not configured"
-# endif
-
-# if defined(OPENSSL_RAND_SEED_OS)
-# if !defined(DEVRANDOM)
-# error "OS seeding requires DEVRANDOM to be configured"
-# endif
-# define OPENSSL_RAND_SEED_GETRANDOM
-# define OPENSSL_RAND_SEED_DEVRANDOM
-# endif
-
-# if defined(OPENSSL_RAND_SEED_LIBRANDOM)
-# error "librandom not (yet) supported"
-# endif
-
-# if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
-/*
- * sysctl_random(): Use sysctl() to read a random number from the kernel
- * Returns the number of bytes returned in buf on success, -1 on failure.
- */
-static ssize_t sysctl_random(char *buf, size_t buflen)
-{
- int mib[2];
- size_t done = 0;
- size_t len;
-
- /*
- * Note: sign conversion between size_t and ssize_t is safe even
- * without a range check, see comment in syscall_random()
- */
-
- /*
- * On FreeBSD old implementations returned longs, newer versions support
- * variable sizes up to 256 byte. The code below would not work properly
- * when the sysctl returns long and we want to request something not a
- * multiple of longs, which should never be the case.
- */
-#if defined(__FreeBSD__)
- if (!ossl_assert(buflen % sizeof(long) == 0)) {
- errno = EINVAL;
- return -1;
- }
-#endif
-
- /*
- * On NetBSD before 4.0 KERN_ARND was an alias for KERN_URND, and only
- * filled in an int, leaving the rest uninitialized. Since NetBSD 4.0
- * it returns a variable number of bytes with the current version supporting
- * up to 256 bytes.
- * Just return an error on older NetBSD versions.
- */
-#if defined(__NetBSD__) && __NetBSD_Version__ < 400000000
- errno = ENOSYS;
- return -1;
-#endif
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_ARND;
-
- do {
- len = buflen > 256 ? 256 : buflen;
- if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)
- return done > 0 ? done : -1;
- done += len;
- buf += len;
- buflen -= len;
- } while (buflen > 0);
-
- return done;
-}
-# endif
-
-# if defined(OPENSSL_RAND_SEED_GETRANDOM)
-
-# if defined(__linux) && !defined(__NR_getrandom)
-# if defined(__arm__)
-# define __NR_getrandom (__NR_SYSCALL_BASE+384)
-# elif defined(__i386__)
-# define __NR_getrandom 355
-# elif defined(__x86_64__)
-# if defined(__ILP32__)
-# define __NR_getrandom (__X32_SYSCALL_BIT + 318)
-# else
-# define __NR_getrandom 318
-# endif
-# elif defined(__xtensa__)
-# define __NR_getrandom 338
-# elif defined(__s390__) || defined(__s390x__)
-# define __NR_getrandom 349
-# elif defined(__bfin__)
-# define __NR_getrandom 389
-# elif defined(__powerpc__)
-# define __NR_getrandom 359
-# elif defined(__mips__) || defined(__mips64)
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __NR_getrandom (__NR_Linux + 353)
-# elif _MIPS_SIM == _MIPS_SIM_ABI64
-# define __NR_getrandom (__NR_Linux + 313)
-# elif _MIPS_SIM == _MIPS_SIM_NABI32
-# define __NR_getrandom (__NR_Linux + 317)
-# endif
-# elif defined(__hppa__)
-# define __NR_getrandom (__NR_Linux + 339)
-# elif defined(__sparc__)
-# define __NR_getrandom 347
-# elif defined(__ia64__)
-# define __NR_getrandom 1339
-# elif defined(__alpha__)
-# define __NR_getrandom 511
-# elif defined(__sh__)
-# if defined(__SH5__)
-# define __NR_getrandom 373
-# else
-# define __NR_getrandom 384
-# endif
-# elif defined(__avr32__)
-# define __NR_getrandom 317
-# elif defined(__microblaze__)
-# define __NR_getrandom 385
-# elif defined(__m68k__)
-# define __NR_getrandom 352
-# elif defined(__cris__)
-# define __NR_getrandom 356
-# elif defined(__aarch64__)
-# define __NR_getrandom 278
-# else /* generic */
-# define __NR_getrandom 278
-# endif
-# endif
-
-/*
- * syscall_random(): Try to get random data using a system call
- * returns the number of bytes returned in buf, or < 0 on error.
- */
-static ssize_t syscall_random(void *buf, size_t buflen)
-{
- /*
- * Note: 'buflen' equals the size of the buffer which is used by the
- * get_entropy() callback of the RAND_DRBG. It is roughly bounded by
- *
- * 2 * RAND_POOL_FACTOR * (RAND_DRBG_STRENGTH / 8) = 2^14
- *
- * which is way below the OSSL_SSIZE_MAX limit. Therefore sign conversion
- * between size_t and ssize_t is safe even without a range check.
- */
-
- /*
- * Do runtime detection to find getentropy().
- *
- * Known OSs that should support this:
- * - Darwin since 16 (OSX 10.12, IOS 10.0).
- * - Solaris since 11.3
- * - OpenBSD since 5.6
- * - Linux since 3.17 with glibc 2.25
- * - FreeBSD since 12.0 (1200061)
- *
- * Note: Sometimes getentropy() can be provided but not implemented
- * internally. So we need to check errno for ENOSYS
- */
-# if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux)
- extern int getentropy(void *buffer, size_t length) __attribute__((weak));
-
- if (getentropy != NULL) {
- if (getentropy(buf, buflen) == 0)
- return (ssize_t)buflen;
- if (errno != ENOSYS)
- return -1;
- }
-# elif defined(OPENSSL_APPLE_CRYPTO_RANDOM)
- if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess)
- return (ssize_t)buflen;
-
- return -1;
-# else
- union {
- void *p;
- int (*f)(void *buffer, size_t length);
- } p_getentropy;
-
- /*
- * We could cache the result of the lookup, but we normally don't
- * call this function often.
- */
- ERR_set_mark();
- p_getentropy.p = DSO_global_lookup("getentropy");
- ERR_pop_to_mark();
- if (p_getentropy.p != NULL)
- return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1;
-# endif
-
- /* Linux supports this since version 3.17 */
-# if defined(__linux) && defined(__NR_getrandom)
- return syscall(__NR_getrandom, buf, buflen, 0);
-# elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
- return sysctl_random(buf, buflen);
-# else
- errno = ENOSYS;
- return -1;
-# endif
-}
-# endif /* defined(OPENSSL_RAND_SEED_GETRANDOM) */
-
-# if defined(OPENSSL_RAND_SEED_DEVRANDOM)
-static const char *random_device_paths[] = { DEVRANDOM };
-static struct random_device {
- int fd;
- dev_t dev;
- ino_t ino;
- mode_t mode;
- dev_t rdev;
-} random_devices[OSSL_NELEM(random_device_paths)];
-static int keep_random_devices_open = 1;
-
-# if defined(__linux) && defined(DEVRANDOM_WAIT) \
- && defined(OPENSSL_RAND_SEED_GETRANDOM)
-static void *shm_addr;
-
-static void cleanup_shm(void)
-{
- shmdt(shm_addr);
-}
-
-/*
- * Ensure that the system randomness source has been adequately seeded.
- * This is done by having the first start of libcrypto, wait until the device
- * /dev/random becomes able to supply a byte of entropy. Subsequent starts
- * of the library and later reseedings do not need to do this.
- */
-static int wait_random_seeded(void)
-{
- static int seeded = OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID < 0;
- static const int kernel_version[] = { DEVRANDOM_SAFE_KERNEL };
- int kernel[2];
- int shm_id, fd, r;
- char c, *p;
- struct utsname un;
- fd_set fds;
-
- if (!seeded) {
- /* See if anything has created the global seeded indication */
- if ((shm_id = shmget(OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID, 1, 0)) == -1) {
- /*
- * Check the kernel's version and fail if it is too recent.
- *
- * Linux kernels from 4.8 onwards do not guarantee that
- * /dev/urandom is properly seeded when /dev/random becomes
- * readable. However, such kernels support the getentropy(2)
- * system call and this should always succeed which renders
- * this alternative but essentially identical source moot.
- */
- if (uname(&un) == 0) {
- kernel[0] = atoi(un.release);
- p = strchr(un.release, '.');
- kernel[1] = p == NULL ? 0 : atoi(p + 1);
- if (kernel[0] > kernel_version[0]
- || (kernel[0] == kernel_version[0]
- && kernel[1] >= kernel_version[1])) {
- return 0;
- }
- }
- /* Open /dev/random and wait for it to be readable */
- if ((fd = open(DEVRANDOM_WAIT, O_RDONLY)) != -1) {
- if (DEVRANDM_WAIT_USE_SELECT && fd < FD_SETSIZE) {
- FD_ZERO(&fds);
- FD_SET(fd, &fds);
- while ((r = select(fd + 1, &fds, NULL, NULL, NULL)) < 0
- && errno == EINTR);
- } else {
- while ((r = read(fd, &c, 1)) < 0 && errno == EINTR);
- }
- close(fd);
- if (r == 1) {
- seeded = 1;
- /* Create the shared memory indicator */
- shm_id = shmget(OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID, 1,
- IPC_CREAT | S_IRUSR | S_IRGRP | S_IROTH);
- }
- }
- }
- if (shm_id != -1) {
- seeded = 1;
- /*
- * Map the shared memory to prevent its premature destruction.
- * If this call fails, it isn't a big problem.
- */
- shm_addr = shmat(shm_id, NULL, SHM_RDONLY);
- if (shm_addr != (void *)-1)
- OPENSSL_atexit(&cleanup_shm);
- }
- }
- return seeded;
-}
-# else /* defined __linux && DEVRANDOM_WAIT && OPENSSL_RAND_SEED_GETRANDOM */
-static int wait_random_seeded(void)
-{
- return 1;
-}
-# endif
-
-/*
- * Verify that the file descriptor associated with the random source is
- * still valid. The rationale for doing this is the fact that it is not
- * uncommon for daemons to close all open file handles when daemonizing.
- * So the handle might have been closed or even reused for opening
- * another file.
- */
-static int check_random_device(struct random_device * rd)
-{
- struct stat st;
-
- return rd->fd != -1
- && fstat(rd->fd, &st) != -1
- && rd->dev == st.st_dev
- && rd->ino == st.st_ino
- && ((rd->mode ^ st.st_mode) & ~(S_IRWXU | S_IRWXG | S_IRWXO)) == 0
- && rd->rdev == st.st_rdev;
-}
-
-/*
- * Open a random device if required and return its file descriptor or -1 on error
- */
-static int get_random_device(size_t n)
-{
- struct stat st;
- struct random_device * rd = &random_devices[n];
-
- /* reuse existing file descriptor if it is (still) valid */
- if (check_random_device(rd))
- return rd->fd;
-
- /* open the random device ... */
- if ((rd->fd = open(random_device_paths[n], O_RDONLY)) == -1)
- return rd->fd;
-
- /* ... and cache its relevant stat(2) data */
- if (fstat(rd->fd, &st) != -1) {
- rd->dev = st.st_dev;
- rd->ino = st.st_ino;
- rd->mode = st.st_mode;
- rd->rdev = st.st_rdev;
- } else {
- close(rd->fd);
- rd->fd = -1;
- }
-
- return rd->fd;
-}
-
-/*
- * Close a random device making sure it is a random device
- */
-static void close_random_device(size_t n)
-{
- struct random_device * rd = &random_devices[n];
-
- if (check_random_device(rd))
- close(rd->fd);
- rd->fd = -1;
-}
-
-int rand_pool_init(void)
-{
- size_t i;
-
- for (i = 0; i < OSSL_NELEM(random_devices); i++)
- random_devices[i].fd = -1;
-
- return 1;
-}
-
-void rand_pool_cleanup(void)
-{
- size_t i;
-
- for (i = 0; i < OSSL_NELEM(random_devices); i++)
- close_random_device(i);
-}
-
-void rand_pool_keep_random_devices_open(int keep)
-{
- if (!keep)
- rand_pool_cleanup();
-
- keep_random_devices_open = keep;
-}
-
-# else /* !defined(OPENSSL_RAND_SEED_DEVRANDOM) */
-
-int rand_pool_init(void)
-{
- return 1;
-}
-
-void rand_pool_cleanup(void)
-{
-}
-
-void rand_pool_keep_random_devices_open(int keep)
-{
-}
-
-# endif /* defined(OPENSSL_RAND_SEED_DEVRANDOM) */
-
-/*
- * Try the various seeding methods in turn, exit when successful.
- *
- * TODO(DRBG): If more than one entropy source is available, is it
- * preferable to stop as soon as enough entropy has been collected
- * (as favored by @rsalz) or should one rather be defensive and add
- * more entropy than requested and/or from different sources?
- *
- * Currently, the user can select multiple entropy sources in the
- * configure step, yet in practice only the first available source
- * will be used. A more flexible solution has been requested, but
- * currently it is not clear how this can be achieved without
- * overengineering the problem. There are many parameters which
- * could be taken into account when selecting the order and amount
- * of input from the different entropy sources (trust, quality,
- * possibility of blocking).
- */
-size_t rand_pool_acquire_entropy(RAND_POOL *pool)
-{
-# if defined(OPENSSL_RAND_SEED_NONE)
- return rand_pool_entropy_available(pool);
-# else
- size_t entropy_available;
-
-# if defined(OPENSSL_RAND_SEED_GETRANDOM)
- {
- size_t bytes_needed;
- unsigned char *buffer;
- ssize_t bytes;
- /* Maximum allowed number of consecutive unsuccessful attempts */
- int attempts = 3;
-
- bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
- while (bytes_needed != 0 && attempts-- > 0) {
- buffer = rand_pool_add_begin(pool, bytes_needed);
- bytes = syscall_random(buffer, bytes_needed);
- if (bytes > 0) {
- rand_pool_add_end(pool, bytes, 8 * bytes);
- bytes_needed -= bytes;
- attempts = 3; /* reset counter after successful attempt */
- } else if (bytes < 0 && errno != EINTR) {
- break;
- }
- }
- }
- entropy_available = rand_pool_entropy_available(pool);
- if (entropy_available > 0)
- return entropy_available;
-# endif
-
-# if defined(OPENSSL_RAND_SEED_LIBRANDOM)
- {
- /* Not yet implemented. */
- }
-# endif
-
-# if defined(OPENSSL_RAND_SEED_DEVRANDOM)
- if (wait_random_seeded()) {
- size_t bytes_needed;
- unsigned char *buffer;
- size_t i;
-
- bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
- for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths);
- i++) {
- ssize_t bytes = 0;
- /* Maximum number of consecutive unsuccessful attempts */
- int attempts = 3;
- const int fd = get_random_device(i);
-
- if (fd == -1)
- continue;
-
- while (bytes_needed != 0 && attempts-- > 0) {
- buffer = rand_pool_add_begin(pool, bytes_needed);
- bytes = read(fd, buffer, bytes_needed);
-
- if (bytes > 0) {
- rand_pool_add_end(pool, bytes, 8 * bytes);
- bytes_needed -= bytes;
- attempts = 3; /* reset counter on successful attempt */
- } else if (bytes < 0 && errno != EINTR) {
- break;
- }
- }
- if (bytes < 0 || !keep_random_devices_open)
- close_random_device(i);
-
- bytes_needed = rand_pool_bytes_needed(pool, 1);
- }
- entropy_available = rand_pool_entropy_available(pool);
- if (entropy_available > 0)
- return entropy_available;
- }
-# endif
-
-# if defined(OPENSSL_RAND_SEED_RDTSC)
- entropy_available = rand_acquire_entropy_from_tsc(pool);
- if (entropy_available > 0)
- return entropy_available;
-# endif
-
-# if defined(OPENSSL_RAND_SEED_RDCPU)
- entropy_available = rand_acquire_entropy_from_cpu(pool);
- if (entropy_available > 0)
- return entropy_available;
-# endif
-
-# if defined(OPENSSL_RAND_SEED_EGD)
- {
- static const char *paths[] = { DEVRANDOM_EGD, NULL };
- size_t bytes_needed;
- unsigned char *buffer;
- int i;
-
- bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
- for (i = 0; bytes_needed > 0 && paths[i] != NULL; i++) {
- size_t bytes = 0;
- int num;
-
- buffer = rand_pool_add_begin(pool, bytes_needed);
- num = RAND_query_egd_bytes(paths[i],
- buffer, (int)bytes_needed);
- if (num == (int)bytes_needed)
- bytes = bytes_needed;
-
- rand_pool_add_end(pool, bytes, 8 * bytes);
- bytes_needed = rand_pool_bytes_needed(pool, 1);
- }
- entropy_available = rand_pool_entropy_available(pool);
- if (entropy_available > 0)
- return entropy_available;
- }
-# endif
-
- return rand_pool_entropy_available(pool);
-# endif
-}
-# endif
-#endif
-
-#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
-int rand_pool_add_nonce_data(RAND_POOL *pool)
-{
- struct {
- pid_t pid;
- CRYPTO_THREAD_ID tid;
- uint64_t time;
- } data = { 0 };
-
- /*
- * Add process id, thread id, and a high resolution timestamp to
- * ensure that the nonce is unique with high probability for
- * different process instances.
- */
- data.pid = getpid();
- data.tid = CRYPTO_THREAD_get_current_id();
- data.time = get_time_stamp();
-
- return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
-}
-
-int rand_pool_add_additional_data(RAND_POOL *pool)
-{
- struct {
- int fork_id;
- CRYPTO_THREAD_ID tid;
- uint64_t time;
- } data = { 0 };
-
- /*
- * Add some noise from the thread id and a high resolution timer.
- * The fork_id adds some extra fork-safety.
- * The thread id adds a little randomness if the drbg is accessed
- * concurrently (which is the case for the <master> drbg).
- */
- data.fork_id = openssl_get_fork_id();
- data.tid = CRYPTO_THREAD_get_current_id();
- data.time = get_timer_bits();
-
- return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
-}
-
-
-/*
- * Get the current time with the highest possible resolution
- *
- * The time stamp is added to the nonce, so it is optimized for not repeating.
- * The current time is ideal for this purpose, provided the computer's clock
- * is synchronized.
- */
-static uint64_t get_time_stamp(void)
-{
-# if defined(OSSL_POSIX_TIMER_OKAY)
- {
- struct timespec ts;
-
- if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
- return TWO32TO64(ts.tv_sec, ts.tv_nsec);
- }
-# endif
-# if defined(__unix__) \
- || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
- {
- struct timeval tv;
-
- if (gettimeofday(&tv, NULL) == 0)
- return TWO32TO64(tv.tv_sec, tv.tv_usec);
- }
-# endif
- return time(NULL);
-}
-
-/*
- * Get an arbitrary timer value of the highest possible resolution
- *
- * The timer value is added as random noise to the additional data,
- * which is not considered a trusted entropy sourec, so any result
- * is acceptable.
- */
-static uint64_t get_timer_bits(void)
-{
- uint64_t res = OPENSSL_rdtsc();
-
- if (res != 0)
- return res;
-
-# if defined(__sun) || defined(__hpux)
- return gethrtime();
-# elif defined(_AIX)
- {
- timebasestruct_t t;
-
- read_wall_time(&t, TIMEBASE_SZ);
- return TWO32TO64(t.tb_high, t.tb_low);
- }
-# elif defined(OSSL_POSIX_TIMER_OKAY)
- {
- struct timespec ts;
-
-# ifdef CLOCK_BOOTTIME
-# define CLOCK_TYPE CLOCK_BOOTTIME
-# elif defined(_POSIX_MONOTONIC_CLOCK)
-# define CLOCK_TYPE CLOCK_MONOTONIC
-# else
-# define CLOCK_TYPE CLOCK_REALTIME
-# endif
-
- if (clock_gettime(CLOCK_TYPE, &ts) == 0)
- return TWO32TO64(ts.tv_sec, ts.tv_nsec);
- }
-# endif
-# if defined(__unix__) \
- || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
- {
- struct timeval tv;
-
- if (gettimeofday(&tv, NULL) == 0)
- return TWO32TO64(tv.tv_sec, tv.tv_usec);
- }
-# endif
- return time(NULL);
-}
-#endif /* (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS))
- || defined(__DJGPP__) */
diff --git a/crypto/rand/randfile.c b/crypto/rand/randfile.c
index 229ce864a312..82f41637387b 100644
--- a/crypto/rand/randfile.c
+++ b/crypto/rand/randfile.c
@@ -1,12 +1,21 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#if defined (__TANDEM) && defined (_SPT_MODEL_)
+/*
+ * These definitions have to come first in SPT due to scoping of the
+ * declarations in c99 associated with SPT use of stat.
+ */
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif
+
#include "internal/cryptlib.h"
#include <errno.h>
@@ -16,7 +25,6 @@
#include <openssl/crypto.h>
#include <openssl/rand.h>
-#include <openssl/rand_drbg.h>
#include <openssl/buffer.h>
#ifdef OPENSSL_SYS_VMS
@@ -95,15 +103,15 @@ int RAND_load_file(const char *file, long bytes)
return 0;
if ((in = openssl_fopen(file, "rb")) == NULL) {
- RANDerr(RAND_F_RAND_LOAD_FILE, RAND_R_CANNOT_OPEN_FILE);
- ERR_add_error_data(2, "Filename=", file);
+ ERR_raise_data(ERR_LIB_RAND, RAND_R_CANNOT_OPEN_FILE,
+ "Filename=%s", file);
return -1;
}
#ifndef OPENSSL_NO_POSIX_IO
if (fstat(fileno(in), &sb) < 0) {
- RANDerr(RAND_F_RAND_LOAD_FILE, RAND_R_INTERNAL_ERROR);
- ERR_add_error_data(2, "Filename=", file);
+ ERR_raise_data(ERR_LIB_RAND, RAND_R_INTERNAL_ERROR,
+ "Filename=%s", file);
fclose(in);
return -1;
}
@@ -163,8 +171,7 @@ int RAND_load_file(const char *file, long bytes)
OPENSSL_cleanse(buf, sizeof(buf));
fclose(in);
if (!RAND_status()) {
- RANDerr(RAND_F_RAND_LOAD_FILE, RAND_R_RESEED_ERROR);
- ERR_add_error_data(2, "Filename=", file);
+ ERR_raise_data(ERR_LIB_RAND, RAND_R_RESEED_ERROR, "Filename=%s", file);
return -1;
}
@@ -180,8 +187,8 @@ int RAND_write_file(const char *file)
struct stat sb;
if (stat(file, &sb) >= 0 && !S_ISREG(sb.st_mode)) {
- RANDerr(RAND_F_RAND_WRITE_FILE, RAND_R_NOT_A_REGULAR_FILE);
- ERR_add_error_data(2, "Filename=", file);
+ ERR_raise_data(ERR_LIB_RAND, RAND_R_NOT_A_REGULAR_FILE,
+ "Filename=%s", file);
return -1;
}
#endif
@@ -230,8 +237,8 @@ int RAND_write_file(const char *file)
if (out == NULL)
out = openssl_fopen(file, "wb");
if (out == NULL) {
- RANDerr(RAND_F_RAND_WRITE_FILE, RAND_R_CANNOT_OPEN_FILE);
- ERR_add_error_data(2, "Filename=", file);
+ ERR_raise_data(ERR_LIB_RAND, RAND_R_CANNOT_OPEN_FILE,
+ "Filename=%s", file);
return -1;
}
diff --git a/crypto/rc2/build.info b/crypto/rc2/build.info
index 47a3fd0d4e35..d1f0ff9c7b69 100644
--- a/crypto/rc2/build.info
+++ b/crypto/rc2/build.info
@@ -1,3 +1,11 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- rc2_ecb.c rc2_skey.c rc2_cbc.c rc2cfb64.c rc2ofb64.c
+
+$ALL=rc2_ecb.c rc2_skey.c rc2_cbc.c rc2cfb64.c rc2ofb64.c
+
+SOURCE[../../libcrypto]=$ALL
+
+# When all deprecated symbols are removed, libcrypto doesn't export the
+# rc2 functions, so we must include them directly in liblegacy.a
+IF[{- $disabled{'deprecated-3.0'} && !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../../providers/liblegacy.a]=$ALL
+ENDIF
diff --git a/crypto/rc2/rc2_cbc.c b/crypto/rc2/rc2_cbc.c
index 17e86f690e01..d37093fcc76c 100644
--- a/crypto/rc2/rc2_cbc.c
+++ b/crypto/rc2/rc2_cbc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RC2 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/rc2.h>
#include "rc2_local.h"
diff --git a/crypto/rc2/rc2_ecb.c b/crypto/rc2/rc2_ecb.c
index 8d9927cd5858..8861d05673b9 100644
--- a/crypto/rc2/rc2_ecb.c
+++ b/crypto/rc2/rc2_ecb.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RC2 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/rc2.h>
#include "rc2_local.h"
#include <openssl/opensslv.h>
diff --git a/crypto/rc2/rc2_local.h b/crypto/rc2/rc2_local.h
index e4dad947872c..8faa7b840a54 100644
--- a/crypto/rc2/rc2_local.h
+++ b/crypto/rc2/rc2_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/rc2/rc2_skey.c b/crypto/rc2/rc2_skey.c
index 60ebd42f2636..e43b84af1715 100644
--- a/crypto/rc2/rc2_skey.c
+++ b/crypto/rc2/rc2_skey.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RC2 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/rc2.h>
#include "rc2_local.h"
@@ -41,8 +47,8 @@ static const unsigned char key_table[256] = {
/*
* It has come to my attention that there are 2 versions of the RC2 key
- * schedule. One which is normal, and anther which has a hook to use a
- * reduced key length. BSAFE uses the 'retarded' version. What I previously
+ * schedule. One which is normal, and another which has a hook to use a
+ * reduced key length. BSAFE uses the latter version. What I previously
* shipped is the same as specifying 1024 for the 'bits' parameter. Bsafe
* uses a version where the bits parameter is the same as len*8
*/
diff --git a/crypto/rc2/rc2cfb64.c b/crypto/rc2/rc2cfb64.c
index 8d1c3a4d8f66..19612d933383 100644
--- a/crypto/rc2/rc2cfb64.c
+++ b/crypto/rc2/rc2cfb64.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RC2 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/rc2.h>
#include "rc2_local.h"
diff --git a/crypto/rc2/rc2ofb64.c b/crypto/rc2/rc2ofb64.c
index 61b2c56434bf..82c34b3aab02 100644
--- a/crypto/rc2/rc2ofb64.c
+++ b/crypto/rc2/rc2ofb64.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RC2 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/rc2.h>
#include "rc2_local.h"
diff --git a/crypto/rc4/asm/rc4-586.pl b/crypto/rc4/asm/rc4-586.pl
index 3a936de1f9a7..1fae93ae1a70 100644
--- a/crypto/rc4/asm/rc4-586.pl
+++ b/crypto/rc4/asm/rc4-586.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 1998-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -68,8 +68,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output=pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
&asm_init($ARGV[0],$x86only = $ARGV[$#ARGV] eq "386");
diff --git a/crypto/rc4/asm/rc4-c64xplus.pl b/crypto/rc4/asm/rc4-c64xplus.pl
index b12d044af465..bd1745f1f32b 100644
--- a/crypto/rc4/asm/rc4-c64xplus.pl
+++ b/crypto/rc4/asm/rc4-c64xplus.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -186,7 +186,6 @@ rc4_options:
.align 4
___
-$output=pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
print $code;
close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/rc4/asm/rc4-md5-x86_64.pl b/crypto/rc4/asm/rc4-md5-x86_64.pl
index 7aa5c21bd836..90c94dcb5e3d 100644
--- a/crypto/rc4/asm/rc4-md5-x86_64.pl
+++ b/crypto/rc4/asm/rc4-md5-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -27,7 +27,7 @@
# minimize register usage, which was used as "main thread" with RC4
# weaved into it, one RC4 round per one MD5 round. In addition to the
# stiched subroutine the script can generate standalone replacement
-# md5_block_asm_data_order and RC4. Below are performance numbers in
+# ossl_md5_block_asm_data_order and RC4. Below are performance numbers in
# cycles per processed byte, less is better, for these the standalone
# subroutines, sum of them, and stitched one:
#
@@ -53,9 +53,10 @@ my $D="#" if (!$md5); # if set to "#", MD5 is stitched into RC4(),
# to be able to use 'openssl speed rc4' for
# benchmarking the stitched subroutine...
-my $flavour = shift;
-my $output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
my $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -64,7 +65,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; my $dir=$1; my $xlate;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
my ($dat,$in0,$out,$ctx,$inp,$len, $func,$nargs);
@@ -74,7 +76,7 @@ if ($rc4 && !$md5) {
$func="RC4"; $nargs=4;
} elsif ($md5 && !$rc4) {
($ctx,$inp,$len) = ("%rdi","%rsi","%rdx");
- $func="md5_block_asm_data_order"; $nargs=3;
+ $func="ossl_md5_block_asm_data_order"; $nargs=3;
} else {
($dat,$in0,$out,$ctx,$inp,$len) = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9");
$func="rc4_md5_enc"; $nargs=6;
diff --git a/crypto/rc4/asm/rc4-parisc.pl b/crypto/rc4/asm/rc4-parisc.pl
index 631e742b739d..9a38674a59f5 100644
--- a/crypto/rc4/asm/rc4-parisc.pl
+++ b/crypto/rc4/asm/rc4-parisc.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -27,9 +27,12 @@
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
-$flavour = shift;
-$output = shift;
-open STDOUT,">$output";
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+
+$output and open STDOUT,">$output";
if ($flavour =~ /64/) {
$LEVEL ="2.0W";
diff --git a/crypto/rc4/asm/rc4-s390x.pl b/crypto/rc4/asm/rc4-s390x.pl
index dded0b75e7f9..d5250f57f192 100644
--- a/crypto/rc4/asm/rc4-s390x.pl
+++ b/crypto/rc4/asm/rc4-s390x.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -30,7 +30,10 @@
# remains z/Architecture specific. On z990 it was measured to perform
# 50% better than code generated by gcc 4.3.
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /3[12]/) {
$SIZE_T=4;
@@ -40,8 +43,7 @@ if ($flavour =~ /3[12]/) {
$g="g";
}
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$output and open STDOUT,">$output";
$rp="%r14";
$sp="%r15";
diff --git a/crypto/rc4/asm/rc4-x86_64.pl b/crypto/rc4/asm/rc4-x86_64.pl
index 423eb5b4a997..5a903f5739e1 100755
--- a/crypto/rc4/asm/rc4-x86_64.pl
+++ b/crypto/rc4/asm/rc4-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -111,9 +111,10 @@
# but more than likely at the cost of the others (see rc4-586.pl
# to get the idea)...
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -122,7 +123,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
$dat="%rdi"; # arg1
@@ -140,6 +142,7 @@ $code=<<___;
.align 16
RC4:
.cfi_startproc
+ endbranch
or $len,$len
jne .Lentry
ret
@@ -455,6 +458,7 @@ $code.=<<___;
.align 16
RC4_set_key:
.cfi_startproc
+ endbranch
lea 8($dat),$dat
lea ($inp,$len),$inp
neg $len
@@ -529,6 +533,7 @@ RC4_set_key:
.align 16
RC4_options:
.cfi_startproc
+ endbranch
lea .Lopts(%rip),%rax
mov OPENSSL_ia32cap_P(%rip),%edx
bt \$20,%edx
diff --git a/crypto/rc4/build.info b/crypto/rc4/build.info
index 913942b5e980..68b3c73f55b0 100644
--- a/crypto/rc4/build.info
+++ b/crypto/rc4/build.info
@@ -1,20 +1,36 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- {- $target{rc4_asm_src} -}
-GENERATE[rc4-586.s]=asm/rc4-586.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-DEPEND[rc4-586.s]=../perlasm/x86asm.pl
+$RC4ASM=rc4_enc.c rc4_skey.c
+IF[{- !$disabled{asm} -}]
+ $RC4ASM_x86=rc4-586.S
+ $RC4ASM_x86_64=rc4-x86_64.s rc4-md5-x86_64.s
+ $RC4ASM_s390x=rc4-s390x.s
+ $RC4ASM_parisc11=rc4-parisc.s
+ $RC4ASM_parisc20_64=$RC4ASM_parisc11
+ $RC4ASM_c64xplus=rc4-c64xplus.s
-GENERATE[rc4-x86_64.s]=asm/rc4-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[rc4-md5-x86_64.s]=asm/rc4-md5-x86_64.pl $(PERLASM_SCHEME)
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+ IF[$RC4ASM_{- $target{asm_arch} -}]
+ $RC4ASM=$RC4ASM_{- $target{asm_arch} -}
+ $RC4DEF=RC4_ASM
+ ENDIF
+ENDIF
-GENERATE[rc4-parisc.s]=asm/rc4-parisc.pl $(PERLASM_SCHEME)
+SOURCE[../../libcrypto]=$RC4ASM
-GENERATE[rc4-s390x.s]=asm/rc4-s390x.pl $(PERLASM_SCHEME)
+# When all deprecated symbols are removed, libcrypto doesn't export the
+# rc4 functions, so we must include them directly in liblegacy.a
+IF[{- $disabled{'deprecated-3.0'} && !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../../providers/liblegacy.a]=$RC4ASM
+ENDIF
-BEGINRAW[Makefile]
-# GNU make "catch all"
-{- $builddir -}/rc4-%.s: {- $sourcedir -}/asm/rc4-%.pl
- CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@
-ENDRAW[Makefile]
+GENERATE[rc4-586.S]=asm/rc4-586.pl
+DEPEND[rc4-586.S]=../perlasm/x86asm.pl
+
+GENERATE[rc4-x86_64.s]=asm/rc4-x86_64.pl
+GENERATE[rc4-md5-x86_64.s]=asm/rc4-md5-x86_64.pl
+
+GENERATE[rc4-parisc.s]=asm/rc4-parisc.pl
+GENERATE[rc4-c64xplus.s]=asm/rc4-c64xplus.pl
+GENERATE[rc4-s390x.s]=asm/rc4-s390x.pl
diff --git a/crypto/rc4/rc4_enc.c b/crypto/rc4/rc4_enc.c
index 09ef6a896f07..4015332757e3 100644
--- a/crypto/rc4/rc4_enc.c
+++ b/crypto/rc4/rc4_enc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RC4 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/rc4.h>
#include "rc4_local.h"
diff --git a/crypto/rc4/rc4_local.h b/crypto/rc4/rc4_local.h
index e739be4be793..f8cf9a89b3eb 100644
--- a/crypto/rc4/rc4_local.h
+++ b/crypto/rc4/rc4_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/rc4/rc4_skey.c b/crypto/rc4/rc4_skey.c
index 100eb79c2ada..3797eff3e2b7 100644
--- a/crypto/rc4/rc4_skey.c
+++ b/crypto/rc4/rc4_skey.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RC4 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/rc4.h>
#include "rc4_local.h"
#include <openssl/opensslv.h>
diff --git a/crypto/rc5/asm/rc5-586.pl b/crypto/rc5/asm/rc5-586.pl
index af11be816259..6def6fcacb0f 100644
--- a/crypto/rc5/asm/rc5-586.pl
+++ b/crypto/rc5/asm/rc5-586.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -12,8 +12,7 @@ push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
require "cbc.pl";
-$output = pop;
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
&asm_init($ARGV[0]);
diff --git a/crypto/rc5/build.info b/crypto/rc5/build.info
index 928a62cd85bf..1b396252bb5c 100644
--- a/crypto/rc5/build.info
+++ b/crypto/rc5/build.info
@@ -1,7 +1,26 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- rc5_skey.c rc5_ecb.c {- $target{rc5_asm_src} -} rc5cfb64.c rc5ofb64.c
-GENERATE[rc5-586.s]=asm/rc5-586.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS)
-DEPEND[rc5-586.s]=../perlasm/x86asm.pl ../perlasm/cbc.pl
+$RC5ASM=rc5_enc.c
+IF[{- !$disabled{asm} -}]
+ $RC5ASM_x86=rc5-586.S
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+ IF[$RC5ASM_{- $target{asm_arch} -}]
+ $RC5ASM=$RC5ASM_{- $target{asm_arch} -}
+ $RC5DEF=RC5_ASM
+ ENDIF
+ENDIF
+
+$ALL=rc5_skey.c rc5_ecb.c $RC5ASM rc5cfb64.c rc5ofb64.c
+
+SOURCE[../../libcrypto]=$ALL
+
+# When all deprecated symbols are removed, libcrypto doesn't export the
+# rc5 functions, so we must include them directly in liblegacy.a
+IF[{- $disabled{'deprecated-3.0'} && !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../../providers/liblegacy.a]=$ALL
+ENDIF
+
+GENERATE[rc5-586.S]=asm/rc5-586.pl
+DEPEND[rc5-586.S]=../perlasm/x86asm.pl ../perlasm/cbc.pl
diff --git a/crypto/rc5/rc5_ecb.c b/crypto/rc5/rc5_ecb.c
index 94ec646390dd..e533b9ea7e19 100644
--- a/crypto/rc5/rc5_ecb.c
+++ b/crypto/rc5/rc5_ecb.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RC5 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/rc5.h>
#include "rc5_local.h"
#include <openssl/opensslv.h>
diff --git a/crypto/rc5/rc5_enc.c b/crypto/rc5/rc5_enc.c
index 75ddeb2eaf2b..2f9feee0e0f8 100644
--- a/crypto/rc5/rc5_enc.c
+++ b/crypto/rc5/rc5_enc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RC5 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <openssl/rc5.h>
#include "rc5_local.h"
diff --git a/crypto/rc5/rc5_local.h b/crypto/rc5/rc5_local.h
index 41130fe33be4..df7df608dc07 100644
--- a/crypto/rc5/rc5_local.h
+++ b/crypto/rc5/rc5_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/rc5/rc5_skey.c b/crypto/rc5/rc5_skey.c
index b2e6bbb1af24..a08b940badf6 100644
--- a/crypto/rc5/rc5_skey.c
+++ b/crypto/rc5/rc5_skey.c
@@ -1,21 +1,30 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RC5 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/rc5.h>
#include "rc5_local.h"
-void RC5_32_set_key(RC5_32_KEY *key, int len, const unsigned char *data,
- int rounds)
+int RC5_32_set_key(RC5_32_KEY *key, int len, const unsigned char *data,
+ int rounds)
{
RC5_32_INT L[64], l, ll, A, B, *S, k;
int i, j, m, c, t, ii, jj;
+ if (len > 255)
+ return 0;
+
if ((rounds != RC5_16_ROUNDS) &&
(rounds != RC5_12_ROUNDS) && (rounds != RC5_8_ROUNDS))
rounds = RC5_16_ROUNDS;
@@ -58,4 +67,6 @@ void RC5_32_set_key(RC5_32_KEY *key, int len, const unsigned char *data,
if (++jj >= c)
jj = 0;
}
+
+ return 1;
}
diff --git a/crypto/rc5/rc5cfb64.c b/crypto/rc5/rc5cfb64.c
index cfce7ec1e84c..9088eb7eddae 100644
--- a/crypto/rc5/rc5cfb64.c
+++ b/crypto/rc5/rc5cfb64.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RC5 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/rc5.h>
#include "rc5_local.h"
diff --git a/crypto/rc5/rc5ofb64.c b/crypto/rc5/rc5ofb64.c
index 224eb968579c..b1128b1f4806 100644
--- a/crypto/rc5/rc5ofb64.c
+++ b/crypto/rc5/rc5ofb64.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RC5 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/rc5.h>
#include "rc5_local.h"
diff --git a/crypto/ripemd/asm/rmd-586.pl b/crypto/ripemd/asm/rmd-586.pl
index e8d02812ba5e..354bf44e20a1 100644
--- a/crypto/ripemd/asm/rmd-586.pl
+++ b/crypto/ripemd/asm/rmd-586.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -16,8 +16,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
&asm_init($ARGV[0]);
diff --git a/crypto/ripemd/build.info b/crypto/ripemd/build.info
index a4a894e2d1f9..17acec0bedcf 100644
--- a/crypto/ripemd/build.info
+++ b/crypto/ripemd/build.info
@@ -1,7 +1,29 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- rmd_dgst.c rmd_one.c {- $target{rmd160_asm_src} -}
-GENERATE[rmd-586.s]=asm/rmd-586.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS)
-DEPEND[rmd-586.s]=../perlasm/x86asm.pl
+$RMD160ASM=
+IF[{- !$disabled{asm} -}]
+ $RMD160ASM_x86=rmd-586.S
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+ IF[$RMD160ASM_{- $target{asm_arch} -}]
+ $RMD160ASM=$RMD160ASM_{- $target{asm_arch} -}
+ $RMD160DEF=RMD160_ASM
+ ENDIF
+ENDIF
+
+# Implementations are now spread across several libraries, so the defines
+# need to be applied to all affected libraries and modules
+
+SOURCE[../../libcrypto]=rmd_dgst.c rmd_one.c $RMD160ASM
+DEFINE[../../libcrypto]=$RMD160DEF
+
+# When all deprecated symbols are removed, libcrypto doesn't export the
+# RIPEMD160 functions, so we must include them directly in liblegacy.a
+IF[{- $disabled{'deprecated-3.0'} && !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../../providers/liblegacy.a]=rmd_dgst.c rmd_one.c $RMD160ASM
+ DEFINE[../../providers/liblegacy.a]=$RMD160DEF
+ENDIF
+
+GENERATE[rmd-586.S]=asm/rmd-586.pl
+DEPEND[rmd-586.S]=../perlasm/x86asm.pl
diff --git a/crypto/ripemd/rmd_dgst.c b/crypto/ripemd/rmd_dgst.c
index e9e440f18c10..77b9d32d2b14 100644
--- a/crypto/ripemd/rmd_dgst.c
+++ b/crypto/ripemd/rmd_dgst.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RIPEMD160 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "rmd_local.h"
#include <openssl/opensslv.h>
diff --git a/crypto/ripemd/rmd_local.h b/crypto/ripemd/rmd_local.h
index f3604e349006..325cb98cc309 100644
--- a/crypto/ripemd/rmd_local.h
+++ b/crypto/ripemd/rmd_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/ripemd/rmd_one.c b/crypto/ripemd/rmd_one.c
index cc01f15c7f1c..dcd7bae1dc89 100644
--- a/crypto/ripemd/rmd_one.c
+++ b/crypto/ripemd/rmd_one.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RIPEMD160 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <string.h>
#include <openssl/ripemd.h>
diff --git a/crypto/ripemd/rmdconst.h b/crypto/ripemd/rmdconst.h
index b81013239bbe..0e19410ade10 100644
--- a/crypto/ripemd/rmdconst.h
+++ b/crypto/ripemd/rmdconst.h
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/rsa/build.info b/crypto/rsa/build.info
index 87f924922f63..ad3370db397c 100644
--- a/crypto/rsa/build.info
+++ b/crypto/rsa/build.info
@@ -1,6 +1,22 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- rsa_ossl.c rsa_gen.c rsa_lib.c rsa_sign.c rsa_saos.c rsa_err.c \
- rsa_pk1.c rsa_ssl.c rsa_none.c rsa_oaep.c rsa_chk.c \
- rsa_pss.c rsa_x931.c rsa_asn1.c rsa_depr.c rsa_ameth.c rsa_prn.c \
- rsa_pmeth.c rsa_crpt.c rsa_x931g.c rsa_meth.c rsa_mp.c
+
+$COMMON=rsa_ossl.c rsa_gen.c rsa_lib.c rsa_sign.c rsa_pk1.c \
+ rsa_none.c rsa_oaep.c rsa_chk.c rsa_pss.c rsa_x931.c rsa_crpt.c \
+ rsa_sp800_56b_gen.c rsa_sp800_56b_check.c rsa_backend.c \
+ rsa_mp_names.c rsa_schemes.c
+
+SOURCE[../../libcrypto]=$COMMON\
+ rsa_saos.c rsa_err.c rsa_asn1.c rsa_ameth.c rsa_prn.c \
+ rsa_pmeth.c rsa_meth.c rsa_mp.c
+IF[{- !$disabled{'deprecated-0.9.8'} -}]
+ SOURCE[../../libcrypto]=rsa_depr.c
+ENDIF
+IF[{- !$disabled{'deprecated-3.0'} -}]
+ SOURCE[../../libcrypto]=rsa_x931g.c
+ENDIF
+
+SOURCE[../../providers/libfips.a]=$COMMON
+
+IF[{- !$disabled{'acvp-tests'} -}]
+ SOURCE[../../providers/libfips.a]=rsa_acvp_test_params.c
+ENDIF
diff --git a/crypto/rsa/rsa_acvp_test_params.c b/crypto/rsa/rsa_acvp_test_params.c
new file mode 100644
index 000000000000..fddc1e099412
--- /dev/null
+++ b/crypto/rsa/rsa_acvp_test_params.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h> /* memcpy */
+#include <openssl/core_names.h>
+#include <openssl/param_build.h>
+#include "crypto/rsa.h"
+#include "rsa_local.h"
+
+int ossl_rsa_acvp_test_gen_params_new(OSSL_PARAM **dst, const OSSL_PARAM src[])
+{
+ const OSSL_PARAM *p, *s;
+ OSSL_PARAM *d, *alloc = NULL;
+ int ret = 1;
+
+ static const OSSL_PARAM settable[] = {
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XP, NULL, 0),
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XP1, NULL, 0),
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XP2, NULL, 0),
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XQ, NULL, 0),
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XQ1, NULL, 0),
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XQ2, NULL, 0),
+ OSSL_PARAM_END
+ };
+
+ /* Assume the first element is a required field if this feature is used */
+ p = OSSL_PARAM_locate_const(src, settable[0].key);
+ if (p == NULL)
+ return 1;
+
+ /* Zeroing here means the terminator is always set at the end */
+ alloc = OPENSSL_zalloc(sizeof(settable));
+ if (alloc == NULL)
+ return 0;
+
+ d = alloc;
+ for (s = settable; s->key != NULL; ++s) {
+ /* If src contains a key from settable then copy the src to the dest */
+ p = OSSL_PARAM_locate_const(src, s->key);
+ if (p != NULL) {
+ *d = *s; /* shallow copy from the static settable[] */
+ d->data_size = p->data_size;
+ d->data = OPENSSL_memdup(p->data, p->data_size);
+ if (d->data == NULL)
+ ret = 0;
+ ++d;
+ }
+ }
+ if (ret == 0) {
+ ossl_rsa_acvp_test_gen_params_free(alloc);
+ alloc = NULL;
+ }
+ if (*dst != NULL)
+ ossl_rsa_acvp_test_gen_params_free(*dst);
+ *dst = alloc;
+ return ret;
+}
+
+void ossl_rsa_acvp_test_gen_params_free(OSSL_PARAM *dst)
+{
+ OSSL_PARAM *p;
+
+ if (dst == NULL)
+ return;
+
+ for (p = dst; p->key != NULL; ++p) {
+ OPENSSL_free(p->data);
+ p->data = NULL;
+ }
+ OPENSSL_free(dst);
+}
+
+int ossl_rsa_acvp_test_set_params(RSA *r, const OSSL_PARAM params[])
+{
+ RSA_ACVP_TEST *t;
+ const OSSL_PARAM *p;
+
+ if (r->acvp_test != NULL) {
+ ossl_rsa_acvp_test_free(r->acvp_test);
+ r->acvp_test = NULL;
+ }
+
+ t = OPENSSL_zalloc(sizeof(*t));
+ if (t == NULL)
+ return 0;
+
+ /* Set the input parameters */
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XP1)) != NULL
+ && !OSSL_PARAM_get_BN(p, &t->Xp1))
+ goto err;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XP2)) != NULL
+ && !OSSL_PARAM_get_BN(p, &t->Xp2))
+ goto err;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XP)) != NULL
+ && !OSSL_PARAM_get_BN(p, &t->Xp))
+ goto err;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XQ1)) != NULL
+ && !OSSL_PARAM_get_BN(p, &t->Xq1))
+ goto err;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XQ2)) != NULL
+ && !OSSL_PARAM_get_BN(p, &t->Xq2))
+ goto err;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XQ)) != NULL
+ && !OSSL_PARAM_get_BN(p, &t->Xq))
+ goto err;
+
+ /* Setup the output parameters */
+ t->p1 = BN_new();
+ t->p2 = BN_new();
+ t->q1 = BN_new();
+ t->q2 = BN_new();
+ r->acvp_test = t;
+ return 1;
+err:
+ ossl_rsa_acvp_test_free(t);
+ return 0;
+}
+
+int ossl_rsa_acvp_test_get_params(RSA *r, OSSL_PARAM params[])
+{
+ RSA_ACVP_TEST *t;
+ OSSL_PARAM *p;
+
+ if (r == NULL)
+ return 0;
+
+ t = r->acvp_test;
+ if (t != NULL) {
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_TEST_P1)) != NULL
+ && !OSSL_PARAM_set_BN(p, t->p1))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_TEST_P2)) != NULL
+ && !OSSL_PARAM_set_BN(p, t->p2))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_TEST_Q1)) != NULL
+ && !OSSL_PARAM_set_BN(p, t->q1))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_TEST_Q2)) != NULL
+ && !OSSL_PARAM_set_BN(p, t->q2))
+ return 0;
+ }
+ return 1;
+}
+
+void ossl_rsa_acvp_test_free(RSA_ACVP_TEST *t)
+{
+ if (t != NULL) {
+ BN_free(t->Xp1);
+ BN_free(t->Xp2);
+ BN_free(t->Xp);
+ BN_free(t->Xq1);
+ BN_free(t->Xq2);
+ BN_free(t->Xq);
+ BN_free(t->p1);
+ BN_free(t->p2);
+ BN_free(t->q1);
+ BN_free(t->q2);
+ OPENSSL_free(t);
+ }
+}
+
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
index 2c9c46ea53c8..61ec53d4244c 100644
--- a/crypto/rsa/rsa_ameth.c
+++ b/crypto/rsa/rsa_ameth.c
@@ -1,31 +1,30 @@
/*
- * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/bn.h>
-#include <openssl/cms.h>
+#include <openssl/core_names.h>
+#include <openssl/param_build.h>
#include "crypto/asn1.h"
#include "crypto/evp.h"
+#include "crypto/rsa.h"
#include "rsa_local.h"
-#ifndef OPENSSL_NO_CMS
-static int rsa_cms_sign(CMS_SignerInfo *si);
-static int rsa_cms_verify(CMS_SignerInfo *si);
-static int rsa_cms_decrypt(CMS_RecipientInfo *ri);
-static int rsa_cms_encrypt(CMS_RecipientInfo *ri);
-#endif
-
-static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg);
-
/* Set any parameters associated with pkey */
static int rsa_param_encode(const EVP_PKEY *pkey,
ASN1_STRING **pstr, int *pstrtype)
@@ -34,7 +33,7 @@ static int rsa_param_encode(const EVP_PKEY *pkey,
*pstr = NULL;
/* If RSA it's just NULL type */
- if (pkey->ameth->pkey_id != EVP_PKEY_RSA_PSS) {
+ if (RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK) != RSA_FLAG_TYPE_RSASSAPSS) {
*pstrtype = V_ASN1_NULL;
return 1;
}
@@ -51,27 +50,6 @@ static int rsa_param_encode(const EVP_PKEY *pkey,
return 1;
}
/* Decode any parameters and set them in RSA structure */
-static int rsa_param_decode(RSA *rsa, const X509_ALGOR *alg)
-{
- const ASN1_OBJECT *algoid;
- const void *algp;
- int algptype;
-
- X509_ALGOR_get0(&algoid, &algptype, &algp, alg);
- if (OBJ_obj2nid(algoid) != EVP_PKEY_RSA_PSS)
- return 1;
- if (algptype == V_ASN1_UNDEF)
- return 1;
- if (algptype != V_ASN1_SEQUENCE) {
- RSAerr(RSA_F_RSA_PARAM_DECODE, RSA_R_INVALID_PSS_PARAMETERS);
- return 0;
- }
- rsa->pss = rsa_pss_decode(alg);
- if (rsa->pss == NULL)
- return 0;
- return 1;
-}
-
static int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
{
unsigned char *penc = NULL;
@@ -92,7 +70,7 @@ static int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
return 0;
}
-static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
+static int rsa_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
{
const unsigned char *p;
int pklen;
@@ -101,14 +79,26 @@ static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &alg, pubkey))
return 0;
- if ((rsa = d2i_RSAPublicKey(NULL, &p, pklen)) == NULL) {
- RSAerr(RSA_F_RSA_PUB_DECODE, ERR_R_RSA_LIB);
+ if ((rsa = d2i_RSAPublicKey(NULL, &p, pklen)) == NULL)
return 0;
- }
- if (!rsa_param_decode(rsa, alg)) {
+ if (!ossl_rsa_param_decode(rsa, alg)) {
RSA_free(rsa);
return 0;
}
+
+ RSA_clear_flags(rsa, RSA_FLAG_TYPE_MASK);
+ switch (pkey->ameth->pkey_id) {
+ case EVP_PKEY_RSA:
+ RSA_set_flags(rsa, RSA_FLAG_TYPE_RSA);
+ break;
+ case EVP_PKEY_RSA_PSS:
+ RSA_set_flags(rsa, RSA_FLAG_TYPE_RSASSAPSS);
+ break;
+ default:
+ /* Leave the type bits zero */
+ break;
+ }
+
if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa)) {
RSA_free(rsa);
return 0;
@@ -138,10 +128,8 @@ static int old_rsa_priv_decode(EVP_PKEY *pkey,
{
RSA *rsa;
- if ((rsa = d2i_RSAPrivateKey(NULL, pder, derlen)) == NULL) {
- RSAerr(RSA_F_OLD_RSA_PRIV_DECODE, ERR_R_RSA_LIB);
+ if ((rsa = d2i_RSAPrivateKey(NULL, pder, derlen)) == NULL)
return 0;
- }
EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa);
return 1;
}
@@ -163,14 +151,14 @@ static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
rklen = i2d_RSAPrivateKey(pkey->pkey.rsa, &rk);
if (rklen <= 0) {
- RSAerr(RSA_F_RSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
ASN1_STRING_free(str);
return 0;
}
if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
strtype, str, rk, rklen)) {
- RSAerr(RSA_F_RSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
ASN1_STRING_free(str);
OPENSSL_clear_free(rk, rklen);
return 0;
@@ -181,24 +169,14 @@ static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
static int rsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
{
- const unsigned char *p;
- RSA *rsa;
- int pklen;
- const X509_ALGOR *alg;
+ int ret = 0;
+ RSA *rsa = ossl_rsa_key_from_pkcs8(p8, NULL, NULL);
- if (!PKCS8_pkey_get0(NULL, &p, &pklen, &alg, p8))
- return 0;
- rsa = d2i_RSAPrivateKey(NULL, &p, pklen);
- if (rsa == NULL) {
- RSAerr(RSA_F_RSA_PRIV_DECODE, ERR_R_RSA_LIB);
- return 0;
+ if (rsa != NULL) {
+ ret = 1;
+ EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa);
}
- if (!rsa_param_decode(rsa, alg)) {
- RSA_free(rsa);
- return 0;
- }
- EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa);
- return 1;
+ return ret;
}
static int int_rsa_size(const EVP_PKEY *pkey)
@@ -221,14 +199,6 @@ static void int_rsa_free(EVP_PKEY *pkey)
RSA_free(pkey->pkey.rsa);
}
-static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg)
-{
- if (OBJ_obj2nid(alg->algorithm) != NID_mgf1)
- return NULL;
- return ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR),
- alg->parameter);
-}
-
static int rsa_pss_param_print(BIO *bp, int pss_key, RSA_PSS_PARAMS *pss,
int indent)
{
@@ -280,7 +250,7 @@ static int rsa_pss_param_print(BIO *bp, int pss_key, RSA_PSS_PARAMS *pss,
goto err;
if (BIO_puts(bp, " with ") <= 0)
goto err;
- maskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
+ maskHash = ossl_x509_algor_mgf1_decode(pss->maskGenAlgorithm);
if (maskHash != NULL) {
if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0)
goto err;
@@ -311,7 +281,7 @@ static int rsa_pss_param_print(BIO *bp, int pss_key, RSA_PSS_PARAMS *pss,
if (pss->trailerField) {
if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0)
goto err;
- } else if (BIO_puts(bp, "BC (default)") <= 0) {
+ } else if (BIO_puts(bp, "01 (default)") <= 0) {
goto err;
}
BIO_puts(bp, "\n");
@@ -425,39 +395,18 @@ static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
return pkey_rsa_print(bp, pkey, indent, 1);
}
-static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg)
-{
- RSA_PSS_PARAMS *pss;
-
- pss = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_PSS_PARAMS),
- alg->parameter);
-
- if (pss == NULL)
- return NULL;
-
- if (pss->maskGenAlgorithm != NULL) {
- pss->maskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
- if (pss->maskHash == NULL) {
- RSA_PSS_PARAMS_free(pss);
- return NULL;
- }
- }
-
- return pss;
-}
-
static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx)
{
if (OBJ_obj2nid(sigalg->algorithm) == EVP_PKEY_RSA_PSS) {
int rv;
- RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg);
+ RSA_PSS_PARAMS *pss = ossl_rsa_pss_decode(sigalg);
rv = rsa_pss_param_print(bp, 0, pss, indent);
RSA_PSS_PARAMS_free(pss);
if (!rv)
return 0;
- } else if (!sig && BIO_puts(bp, "\n") <= 0) {
+ } else if (BIO_puts(bp, "\n") <= 0) {
return 0;
}
if (sig)
@@ -467,56 +416,19 @@ static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
{
- X509_ALGOR *alg = NULL;
const EVP_MD *md;
const EVP_MD *mgf1md;
int min_saltlen;
switch (op) {
-
- case ASN1_PKEY_CTRL_PKCS7_SIGN:
- if (arg1 == 0)
- PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, NULL, &alg);
- break;
-
- case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
- if (pkey_is_pss(pkey))
- return -2;
- if (arg1 == 0)
- PKCS7_RECIP_INFO_get0_alg(arg2, &alg);
- break;
-#ifndef OPENSSL_NO_CMS
- case ASN1_PKEY_CTRL_CMS_SIGN:
- if (arg1 == 0)
- return rsa_cms_sign(arg2);
- else if (arg1 == 1)
- return rsa_cms_verify(arg2);
- break;
-
- case ASN1_PKEY_CTRL_CMS_ENVELOPE:
- if (pkey_is_pss(pkey))
- return -2;
- if (arg1 == 0)
- return rsa_cms_encrypt(arg2);
- else if (arg1 == 1)
- return rsa_cms_decrypt(arg2);
- break;
-
- case ASN1_PKEY_CTRL_CMS_RI_TYPE:
- if (pkey_is_pss(pkey))
- return -2;
- *(int *)arg2 = CMS_RECIPINFO_TRANS;
- return 1;
-#endif
-
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
if (pkey->pkey.rsa->pss != NULL) {
- if (!rsa_pss_get_param(pkey->pkey.rsa->pss, &md, &mgf1md,
- &min_saltlen)) {
- RSAerr(0, ERR_R_INTERNAL_ERROR);
+ if (!ossl_rsa_pss_get_param(pkey->pkey.rsa->pss, &md, &mgf1md,
+ &min_saltlen)) {
+ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
return 0;
}
- *(int *)arg2 = EVP_MD_type(md);
+ *(int *)arg2 = EVP_MD_get_type(md);
/* Return of 2 indicates this MD is mandatory */
return 2;
}
@@ -525,66 +437,7 @@ static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
default:
return -2;
-
}
-
- if (alg)
- X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
-
- return 1;
-
-}
-
-/* allocate and set algorithm ID from EVP_MD, default SHA1 */
-static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md)
-{
- if (md == NULL || EVP_MD_type(md) == NID_sha1)
- return 1;
- *palg = X509_ALGOR_new();
- if (*palg == NULL)
- return 0;
- X509_ALGOR_set_md(*palg, md);
- return 1;
-}
-
-/* Allocate and set MGF1 algorithm ID from EVP_MD */
-static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md)
-{
- X509_ALGOR *algtmp = NULL;
- ASN1_STRING *stmp = NULL;
-
- *palg = NULL;
- if (mgf1md == NULL || EVP_MD_type(mgf1md) == NID_sha1)
- return 1;
- /* need to embed algorithm ID inside another */
- if (!rsa_md_to_algor(&algtmp, mgf1md))
- goto err;
- if (ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp) == NULL)
- goto err;
- *palg = X509_ALGOR_new();
- if (*palg == NULL)
- goto err;
- X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
- stmp = NULL;
- err:
- ASN1_STRING_free(stmp);
- X509_ALGOR_free(algtmp);
- if (*palg)
- return 1;
- return 0;
-}
-
-/* convert algorithm ID to EVP_MD, default SHA1 */
-static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg)
-{
- const EVP_MD *md;
-
- if (!alg)
- return EVP_sha1();
- md = EVP_get_digestbyobj(alg->algorithm);
- if (md == NULL)
- RSAerr(RSA_F_RSA_ALGOR_TO_MD, RSA_R_UNKNOWN_DIGEST);
- return md;
}
/*
@@ -602,23 +455,23 @@ static RSA_PSS_PARAMS *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx)
return NULL;
if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0)
return NULL;
- if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen))
+ if (EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen) <= 0)
return NULL;
if (saltlen == -1) {
- saltlen = EVP_MD_size(sigmd);
+ saltlen = EVP_MD_get_size(sigmd);
} else if (saltlen == -2 || saltlen == -3) {
- saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
- if ((EVP_PKEY_bits(pk) & 0x7) == 1)
+ saltlen = EVP_PKEY_get_size(pk) - EVP_MD_get_size(sigmd) - 2;
+ if ((EVP_PKEY_get_bits(pk) & 0x7) == 1)
saltlen--;
if (saltlen < 0)
return NULL;
}
- return rsa_pss_params_create(sigmd, mgf1md, saltlen);
+ return ossl_rsa_pss_params_create(sigmd, mgf1md, saltlen);
}
-RSA_PSS_PARAMS *rsa_pss_params_create(const EVP_MD *sigmd,
- const EVP_MD *mgf1md, int saltlen)
+RSA_PSS_PARAMS *ossl_rsa_pss_params_create(const EVP_MD *sigmd,
+ const EVP_MD *mgf1md, int saltlen)
{
RSA_PSS_PARAMS *pss = RSA_PSS_PARAMS_new();
@@ -631,13 +484,13 @@ RSA_PSS_PARAMS *rsa_pss_params_create(const EVP_MD *sigmd,
if (!ASN1_INTEGER_set(pss->saltLength, saltlen))
goto err;
}
- if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd))
+ if (!ossl_x509_algor_new_from_md(&pss->hashAlgorithm, sigmd))
goto err;
if (mgf1md == NULL)
mgf1md = sigmd;
- if (!rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md))
+ if (!ossl_x509_algor_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md))
goto err;
- if (!rsa_md_to_algor(&pss->maskHash, mgf1md))
+ if (!ossl_x509_algor_new_from_md(&pss->maskHash, mgf1md))
goto err;
return pss;
err:
@@ -645,7 +498,7 @@ RSA_PSS_PARAMS *rsa_pss_params_create(const EVP_MD *sigmd,
return NULL;
}
-static ASN1_STRING *rsa_ctx_to_pss_string(EVP_PKEY_CTX *pkctx)
+ASN1_STRING *ossl_rsa_ctx_to_pss_string(EVP_PKEY_CTX *pkctx)
{
RSA_PSS_PARAMS *pss = rsa_ctx_to_pss(pkctx);
ASN1_STRING *os;
@@ -664,8 +517,8 @@ static ASN1_STRING *rsa_ctx_to_pss_string(EVP_PKEY_CTX *pkctx)
* passed to pkctx instead.
*/
-static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
- X509_ALGOR *sigalg, EVP_PKEY *pkey)
+int ossl_rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
+ const X509_ALGOR *sigalg, EVP_PKEY *pkey)
{
int rv = -1;
int saltlen;
@@ -674,14 +527,14 @@ static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
/* Sanity check: make sure it is PSS */
if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS) {
- RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
return -1;
}
/* Decode PSS parameters */
- pss = rsa_pss_decode(sigalg);
+ pss = ossl_rsa_pss_decode(sigalg);
- if (!rsa_pss_get_param(pss, &md, &mgf1md, &saltlen)) {
- RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_PSS_PARAMETERS);
+ if (!ossl_rsa_pss_get_param(pss, &md, &mgf1md, &saltlen)) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PSS_PARAMETERS);
goto err;
}
@@ -693,8 +546,8 @@ static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
const EVP_MD *checkmd;
if (EVP_PKEY_CTX_get_signature_md(pkctx, &checkmd) <= 0)
goto err;
- if (EVP_MD_type(md) != EVP_MD_type(checkmd)) {
- RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_DIGEST_DOES_NOT_MATCH);
+ if (EVP_MD_get_type(md) != EVP_MD_get_type(checkmd)) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_DIGEST_DOES_NOT_MATCH);
goto err;
}
}
@@ -715,143 +568,99 @@ static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
return rv;
}
-int rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
- const EVP_MD **pmgf1md, int *psaltlen)
+static int rsa_pss_verify_param(const EVP_MD **pmd, const EVP_MD **pmgf1md,
+ int *psaltlen, int *ptrailerField)
{
- if (pss == NULL)
+ if (psaltlen != NULL && *psaltlen < 0) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_SALT_LENGTH);
return 0;
- *pmd = rsa_algor_to_md(pss->hashAlgorithm);
- if (*pmd == NULL)
- return 0;
- *pmgf1md = rsa_algor_to_md(pss->maskHash);
- if (*pmgf1md == NULL)
- return 0;
- if (pss->saltLength) {
- *psaltlen = ASN1_INTEGER_get(pss->saltLength);
- if (*psaltlen < 0) {
- RSAerr(RSA_F_RSA_PSS_GET_PARAM, RSA_R_INVALID_SALT_LENGTH);
- return 0;
- }
- } else {
- *psaltlen = 20;
}
-
/*
* low-level routines support only trailer field 0xbc (value 1) and
* PKCS#1 says we should reject any other value anyway.
*/
- if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) {
- RSAerr(RSA_F_RSA_PSS_GET_PARAM, RSA_R_INVALID_TRAILER);
+ if (ptrailerField != NULL && *ptrailerField != 1) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_TRAILER);
return 0;
}
-
return 1;
}
-#ifndef OPENSSL_NO_CMS
-static int rsa_cms_verify(CMS_SignerInfo *si)
+int ossl_rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
+ const EVP_MD **pmgf1md, int *psaltlen)
{
- int nid, nid2;
- X509_ALGOR *alg;
- EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
-
- CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
- nid = OBJ_obj2nid(alg->algorithm);
- if (nid == EVP_PKEY_RSA_PSS)
- return rsa_pss_to_ctx(NULL, pkctx, alg, NULL);
- /* Only PSS allowed for PSS keys */
- if (pkey_ctx_is_pss(pkctx)) {
- RSAerr(RSA_F_RSA_CMS_VERIFY, RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
- return 0;
- }
- if (nid == NID_rsaEncryption)
- return 1;
- /* Workaround for some implementation that use a signature OID */
- if (OBJ_find_sigid_algs(nid, NULL, &nid2)) {
- if (nid2 == NID_rsaEncryption)
- return 1;
- }
- return 0;
+ /*
+ * Callers do not care about the trailer field, and yet, we must
+ * pass it from get_param to verify_param, since the latter checks
+ * its value.
+ *
+ * When callers start caring, it's a simple thing to add another
+ * argument to this function.
+ */
+ int trailerField = 0;
+
+ return ossl_rsa_pss_get_param_unverified(pss, pmd, pmgf1md, psaltlen,
+ &trailerField)
+ && rsa_pss_verify_param(pmd, pmgf1md, psaltlen, &trailerField);
}
-#endif
/*
* Customised RSA item verification routine. This is called when a signature
* is encountered requiring special handling. We currently only handle PSS.
*/
-static int rsa_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
- X509_ALGOR *sigalg, ASN1_BIT_STRING *sig,
- EVP_PKEY *pkey)
+static int rsa_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
+ const void *asn, const X509_ALGOR *sigalg,
+ const ASN1_BIT_STRING *sig, EVP_PKEY *pkey)
{
/* Sanity check: make sure it is PSS */
if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS) {
- RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
return -1;
}
- if (rsa_pss_to_ctx(ctx, NULL, sigalg, pkey) > 0) {
+ if (ossl_rsa_pss_to_ctx(ctx, NULL, sigalg, pkey) > 0) {
/* Carry on */
return 2;
}
return -1;
}
-#ifndef OPENSSL_NO_CMS
-static int rsa_cms_sign(CMS_SignerInfo *si)
-{
- int pad_mode = RSA_PKCS1_PADDING;
- X509_ALGOR *alg;
- EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
- ASN1_STRING *os = NULL;
-
- CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
- if (pkctx) {
- if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
- return 0;
- }
- if (pad_mode == RSA_PKCS1_PADDING) {
- X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
- return 1;
- }
- /* We don't support it */
- if (pad_mode != RSA_PKCS1_PSS_PADDING)
- return 0;
- os = rsa_ctx_to_pss_string(pkctx);
- if (!os)
- return 0;
- X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_PKEY_RSA_PSS), V_ASN1_SEQUENCE, os);
- return 1;
-}
-#endif
-
-static int rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
+static int rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, const void *asn,
X509_ALGOR *alg1, X509_ALGOR *alg2,
ASN1_BIT_STRING *sig)
{
int pad_mode;
- EVP_PKEY_CTX *pkctx = EVP_MD_CTX_pkey_ctx(ctx);
+ EVP_PKEY_CTX *pkctx = EVP_MD_CTX_get_pkey_ctx(ctx);
if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
return 0;
if (pad_mode == RSA_PKCS1_PADDING)
return 2;
if (pad_mode == RSA_PKCS1_PSS_PADDING) {
- ASN1_STRING *os1 = NULL;
- os1 = rsa_ctx_to_pss_string(pkctx);
- if (!os1)
+ unsigned char aid[128];
+ size_t aid_len = 0;
+ OSSL_PARAM params[2];
+
+ params[0] = OSSL_PARAM_construct_octet_string(
+ OSSL_SIGNATURE_PARAM_ALGORITHM_ID, aid, sizeof(aid));
+ params[1] = OSSL_PARAM_construct_end();
+
+ if (EVP_PKEY_CTX_get_params(pkctx, params) <= 0)
return 0;
- /* Duplicate parameters if we have to */
- if (alg2) {
- ASN1_STRING *os2 = ASN1_STRING_dup(os1);
- if (!os2) {
- ASN1_STRING_free(os1);
+ if ((aid_len = params[0].return_size) == 0)
+ return 0;
+
+ if (alg1 != NULL) {
+ const unsigned char *pp = aid;
+ if (d2i_X509_ALGOR(&alg1, &pp, aid_len) == NULL)
return 0;
- }
- X509_ALGOR_set0(alg2, OBJ_nid2obj(EVP_PKEY_RSA_PSS),
- V_ASN1_SEQUENCE, os2);
}
- X509_ALGOR_set0(alg1, OBJ_nid2obj(EVP_PKEY_RSA_PSS),
- V_ASN1_SEQUENCE, os1);
+ if (alg2 != NULL) {
+ const unsigned char *pp = aid;
+ if (d2i_X509_ALGOR(&alg2, &pp, aid_len) == NULL)
+ return 0;
+ }
+
return 3;
}
return 2;
@@ -865,26 +674,45 @@ static int rsa_sig_info_set(X509_SIG_INFO *siginf, const X509_ALGOR *sigalg,
uint32_t flags;
const EVP_MD *mgf1md = NULL, *md = NULL;
RSA_PSS_PARAMS *pss;
+ int secbits;
/* Sanity check: make sure it is PSS */
if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS)
return 0;
/* Decode PSS parameters */
- pss = rsa_pss_decode(sigalg);
- if (!rsa_pss_get_param(pss, &md, &mgf1md, &saltlen))
+ pss = ossl_rsa_pss_decode(sigalg);
+ if (!ossl_rsa_pss_get_param(pss, &md, &mgf1md, &saltlen))
goto err;
- mdnid = EVP_MD_type(md);
+ mdnid = EVP_MD_get_type(md);
/*
* For TLS need SHA256, SHA384 or SHA512, digest and MGF1 digest must
* match and salt length must equal digest size
*/
if ((mdnid == NID_sha256 || mdnid == NID_sha384 || mdnid == NID_sha512)
- && mdnid == EVP_MD_type(mgf1md) && saltlen == EVP_MD_size(md))
+ && mdnid == EVP_MD_get_type(mgf1md)
+ && saltlen == EVP_MD_get_size(md))
flags = X509_SIG_INFO_TLS;
else
flags = 0;
/* Note: security bits half number of digest bits */
- X509_SIG_INFO_set(siginf, mdnid, EVP_PKEY_RSA_PSS, EVP_MD_size(md) * 4,
+ secbits = EVP_MD_get_size(md) * 4;
+ /*
+ * SHA1 and MD5 are known to be broken. Reduce security bits so that
+ * they're no longer accepted at security level 1. The real values don't
+ * really matter as long as they're lower than 80, which is our security
+ * level 1.
+ * https://eprint.iacr.org/2020/014 puts a chosen-prefix attack for SHA1 at
+ * 2^63.4
+ * https://documents.epfl.ch/users/l/le/lenstra/public/papers/lat.pdf
+ * puts a chosen-prefix attack for MD5 at 2^39.
+ */
+ if (mdnid == NID_sha1)
+ secbits = 64;
+ else if (mdnid == NID_md5_sha1)
+ secbits = 68;
+ else if (mdnid == NID_md5)
+ secbits = 39;
+ X509_SIG_INFO_set(siginf, mdnid, EVP_PKEY_RSA_PSS, secbits,
flags);
rv = 1;
err:
@@ -892,170 +720,193 @@ static int rsa_sig_info_set(X509_SIG_INFO *siginf, const X509_ALGOR *sigalg,
return rv;
}
-#ifndef OPENSSL_NO_CMS
-static RSA_OAEP_PARAMS *rsa_oaep_decode(const X509_ALGOR *alg)
+static int rsa_pkey_check(const EVP_PKEY *pkey)
{
- RSA_OAEP_PARAMS *oaep;
-
- oaep = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_OAEP_PARAMS),
- alg->parameter);
-
- if (oaep == NULL)
- return NULL;
-
- if (oaep->maskGenFunc != NULL) {
- oaep->maskHash = rsa_mgf1_decode(oaep->maskGenFunc);
- if (oaep->maskHash == NULL) {
- RSA_OAEP_PARAMS_free(oaep);
- return NULL;
- }
- }
- return oaep;
+ return RSA_check_key_ex(pkey->pkey.rsa, NULL);
}
-static int rsa_cms_decrypt(CMS_RecipientInfo *ri)
+static size_t rsa_pkey_dirty_cnt(const EVP_PKEY *pkey)
{
- EVP_PKEY_CTX *pkctx;
- X509_ALGOR *cmsalg;
- int nid;
- int rv = -1;
- unsigned char *label = NULL;
- int labellen = 0;
- const EVP_MD *mgf1md = NULL, *md = NULL;
- RSA_OAEP_PARAMS *oaep;
+ return pkey->pkey.rsa->dirty_cnt;
+}
- pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
- if (pkctx == NULL)
- return 0;
- if (!CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &cmsalg))
- return -1;
- nid = OBJ_obj2nid(cmsalg->algorithm);
- if (nid == NID_rsaEncryption)
- return 1;
- if (nid != NID_rsaesOaep) {
- RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_ENCRYPTION_TYPE);
- return -1;
- }
- /* Decode OAEP parameters */
- oaep = rsa_oaep_decode(cmsalg);
+/*
+ * There is no need to do RSA_test_flags(rsa, RSA_FLAG_TYPE_RSASSAPSS)
+ * checks in this method since the caller tests EVP_KEYMGMT_is_a() first.
+ */
+static int rsa_int_export_to(const EVP_PKEY *from, int rsa_type,
+ void *to_keydata,
+ OSSL_FUNC_keymgmt_import_fn *importer,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ RSA *rsa = from->pkey.rsa;
+ OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new();
+ OSSL_PARAM *params = NULL;
+ int selection = 0;
+ int rv = 0;
- if (oaep == NULL) {
- RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_OAEP_PARAMETERS);
+ if (tmpl == NULL)
+ return 0;
+ /* Public parameters must always be present */
+ if (RSA_get0_n(rsa) == NULL || RSA_get0_e(rsa) == NULL)
goto err;
- }
- mgf1md = rsa_algor_to_md(oaep->maskHash);
- if (mgf1md == NULL)
- goto err;
- md = rsa_algor_to_md(oaep->hashFunc);
- if (md == NULL)
+ if (!ossl_rsa_todata(rsa, tmpl, NULL, 1))
goto err;
- if (oaep->pSourceFunc != NULL) {
- X509_ALGOR *plab = oaep->pSourceFunc;
+ selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+ if (RSA_get0_d(rsa) != NULL)
+ selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
+
+ if (rsa->pss != NULL) {
+ const EVP_MD *md = NULL, *mgf1md = NULL;
+ int md_nid, mgf1md_nid, saltlen, trailerfield;
+ RSA_PSS_PARAMS_30 pss_params;
- if (OBJ_obj2nid(plab->algorithm) != NID_pSpecified) {
- RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_LABEL_SOURCE);
+ if (!ossl_rsa_pss_get_param_unverified(rsa->pss, &md, &mgf1md,
+ &saltlen, &trailerfield))
goto err;
- }
- if (plab->parameter->type != V_ASN1_OCTET_STRING) {
- RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_LABEL);
+ md_nid = EVP_MD_get_type(md);
+ mgf1md_nid = EVP_MD_get_type(mgf1md);
+ if (!ossl_rsa_pss_params_30_set_defaults(&pss_params)
+ || !ossl_rsa_pss_params_30_set_hashalg(&pss_params, md_nid)
+ || !ossl_rsa_pss_params_30_set_maskgenhashalg(&pss_params,
+ mgf1md_nid)
+ || !ossl_rsa_pss_params_30_set_saltlen(&pss_params, saltlen)
+ || !ossl_rsa_pss_params_30_todata(&pss_params, tmpl, NULL))
goto err;
- }
-
- label = plab->parameter->value.octet_string->data;
- /* Stop label being freed when OAEP parameters are freed */
- plab->parameter->value.octet_string->data = NULL;
- labellen = plab->parameter->value.octet_string->length;
+ selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS;
}
- if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0)
- goto err;
- if (EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, md) <= 0)
- goto err;
- if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0)
- goto err;
- if (EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, label, labellen) <= 0)
+ if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
goto err;
- /* Carry on */
- rv = 1;
+
+ /* We export, the provider imports */
+ rv = importer(to_keydata, selection, params);
err:
- RSA_OAEP_PARAMS_free(oaep);
+ OSSL_PARAM_free(params);
+ OSSL_PARAM_BLD_free(tmpl);
return rv;
}
-static int rsa_cms_encrypt(CMS_RecipientInfo *ri)
+static int rsa_int_import_from(const OSSL_PARAM params[], void *vpctx,
+ int rsa_type)
{
- const EVP_MD *md, *mgf1md;
- RSA_OAEP_PARAMS *oaep = NULL;
- ASN1_STRING *os = NULL;
- X509_ALGOR *alg;
- EVP_PKEY_CTX *pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
- int pad_mode = RSA_PKCS1_PADDING, rv = 0, labellen;
- unsigned char *label;
+ EVP_PKEY_CTX *pctx = vpctx;
+ EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
+ RSA *rsa = ossl_rsa_new_with_ctx(pctx->libctx);
+ RSA_PSS_PARAMS_30 rsa_pss_params = { 0, };
+ int pss_defaults_set = 0;
+ int ok = 0;
- if (CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &alg) <= 0)
+ if (rsa == NULL) {
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
return 0;
- if (pkctx) {
- if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
- return 0;
- }
- if (pad_mode == RSA_PKCS1_PADDING) {
- X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
- return 1;
}
- /* Not supported */
- if (pad_mode != RSA_PKCS1_OAEP_PADDING)
- return 0;
- if (EVP_PKEY_CTX_get_rsa_oaep_md(pkctx, &md) <= 0)
- goto err;
- if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0)
- goto err;
- labellen = EVP_PKEY_CTX_get0_rsa_oaep_label(pkctx, &label);
- if (labellen < 0)
- goto err;
- oaep = RSA_OAEP_PARAMS_new();
- if (oaep == NULL)
- goto err;
- if (!rsa_md_to_algor(&oaep->hashFunc, md))
- goto err;
- if (!rsa_md_to_mgf1(&oaep->maskGenFunc, mgf1md))
+
+ RSA_clear_flags(rsa, RSA_FLAG_TYPE_MASK);
+ RSA_set_flags(rsa, rsa_type);
+
+ if (!ossl_rsa_pss_params_30_fromdata(&rsa_pss_params, &pss_defaults_set,
+ params, pctx->libctx))
goto err;
- if (labellen > 0) {
- ASN1_OCTET_STRING *los;
- oaep->pSourceFunc = X509_ALGOR_new();
- if (oaep->pSourceFunc == NULL)
- goto err;
- los = ASN1_OCTET_STRING_new();
- if (los == NULL)
- goto err;
- if (!ASN1_OCTET_STRING_set(los, label, labellen)) {
- ASN1_OCTET_STRING_free(los);
+
+ switch (rsa_type) {
+ case RSA_FLAG_TYPE_RSA:
+ /*
+ * Were PSS parameters filled in?
+ * In that case, something's wrong
+ */
+ if (!ossl_rsa_pss_params_30_is_unrestricted(&rsa_pss_params))
goto err;
+ break;
+ case RSA_FLAG_TYPE_RSASSAPSS:
+ /*
+ * Were PSS parameters filled in? In that case, create the old
+ * RSA_PSS_PARAMS structure. Otherwise, this is an unrestricted key.
+ */
+ if (!ossl_rsa_pss_params_30_is_unrestricted(&rsa_pss_params)) {
+ /* Create the older RSA_PSS_PARAMS from RSA_PSS_PARAMS_30 data */
+ int mdnid = ossl_rsa_pss_params_30_hashalg(&rsa_pss_params);
+ int mgf1mdnid = ossl_rsa_pss_params_30_maskgenhashalg(&rsa_pss_params);
+ int saltlen = ossl_rsa_pss_params_30_saltlen(&rsa_pss_params);
+ const EVP_MD *md = EVP_get_digestbynid(mdnid);
+ const EVP_MD *mgf1md = EVP_get_digestbynid(mgf1mdnid);
+
+ if ((rsa->pss = ossl_rsa_pss_params_create(md, mgf1md,
+ saltlen)) == NULL)
+ goto err;
}
- X509_ALGOR_set0(oaep->pSourceFunc, OBJ_nid2obj(NID_pSpecified),
- V_ASN1_OCTET_STRING, los);
+ break;
+ default:
+ /* RSA key sub-types we don't know how to handle yet */
+ goto err;
}
- /* create string with pss parameter encoding. */
- if (!ASN1_item_pack(oaep, ASN1_ITEM_rptr(RSA_OAEP_PARAMS), &os))
- goto err;
- X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaesOaep), V_ASN1_SEQUENCE, os);
- os = NULL;
- rv = 1;
+
+ if (!ossl_rsa_fromdata(rsa, params, 1))
+ goto err;
+
+ switch (rsa_type) {
+ case RSA_FLAG_TYPE_RSA:
+ ok = EVP_PKEY_assign_RSA(pkey, rsa);
+ break;
+ case RSA_FLAG_TYPE_RSASSAPSS:
+ ok = EVP_PKEY_assign(pkey, EVP_PKEY_RSA_PSS, rsa);
+ break;
+ }
+
err:
- RSA_OAEP_PARAMS_free(oaep);
- ASN1_STRING_free(os);
- return rv;
+ if (!ok)
+ RSA_free(rsa);
+ return ok;
}
-#endif
-static int rsa_pkey_check(const EVP_PKEY *pkey)
+static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
+ OSSL_FUNC_keymgmt_import_fn *importer,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
- return RSA_check_key_ex(pkey->pkey.rsa, NULL);
+ return rsa_int_export_to(from, RSA_FLAG_TYPE_RSA, to_keydata,
+ importer, libctx, propq);
+}
+
+static int rsa_pss_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
+ OSSL_FUNC_keymgmt_import_fn *importer,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ return rsa_int_export_to(from, RSA_FLAG_TYPE_RSASSAPSS, to_keydata,
+ importer, libctx, propq);
+}
+
+static int rsa_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
+{
+ return rsa_int_import_from(params, vpctx, RSA_FLAG_TYPE_RSA);
+}
+
+static int rsa_pss_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
+{
+ return rsa_int_import_from(params, vpctx, RSA_FLAG_TYPE_RSASSAPSS);
+}
+
+static int rsa_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
+{
+ RSA *rsa = from->pkey.rsa;
+ RSA *dupkey = NULL;
+ int ret;
+
+ if (rsa != NULL) {
+ dupkey = ossl_rsa_dup(rsa, OSSL_KEYMGMT_SELECT_ALL);
+ if (dupkey == NULL)
+ return 0;
+ }
+
+ ret = EVP_PKEY_assign(to, from->type, dupkey);
+ if (!ret)
+ RSA_free(dupkey);
+ return ret;
}
-const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {
+const EVP_PKEY_ASN1_METHOD ossl_rsa_asn1_meths[2] = {
{
EVP_PKEY_RSA,
EVP_PKEY_RSA,
@@ -1087,7 +938,15 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {
rsa_item_verify,
rsa_item_sign,
rsa_sig_info_set,
- rsa_pkey_check
+ rsa_pkey_check,
+
+ 0, 0,
+ 0, 0, 0, 0,
+
+ rsa_pkey_dirty_cnt,
+ rsa_pkey_export_to,
+ rsa_pkey_import_from,
+ rsa_pkey_copy
},
{
@@ -1096,7 +955,7 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {
ASN1_PKEY_ALIAS}
};
-const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth = {
+const EVP_PKEY_ASN1_METHOD ossl_rsa_pss_asn1_meth = {
EVP_PKEY_RSA_PSS,
EVP_PKEY_RSA_PSS,
ASN1_PKEY_SIGPARAM_NULL,
@@ -1125,6 +984,14 @@ const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth = {
0, 0,
rsa_item_verify,
rsa_item_sign,
- 0,
- rsa_pkey_check
+ rsa_sig_info_set,
+ rsa_pkey_check,
+
+ 0, 0,
+ 0, 0, 0, 0,
+
+ rsa_pkey_dirty_cnt,
+ rsa_pss_pkey_export_to,
+ rsa_pss_pkey_import_from,
+ rsa_pkey_copy
};
diff --git a/crypto/rsa/rsa_asn1.c b/crypto/rsa/rsa_asn1.c
index e8df8d762e16..c14cdf415e9d 100644
--- a/crypto/rsa/rsa_asn1.c
+++ b/crypto/rsa/rsa_asn1.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
@@ -36,7 +42,7 @@ static int rsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
/* not a multi-prime key, skip */
return 1;
}
- return (rsa_multip_calc_product((RSA *)*pval) == 1) ? 2 : 0;
+ return (ossl_rsa_multip_calc_product((RSA *)*pval) == 1) ? 2 : 0;
}
return 1;
}
@@ -86,6 +92,7 @@ ASN1_SEQUENCE_cb(RSA_PSS_PARAMS, rsa_pss_cb) = {
} ASN1_SEQUENCE_END_cb(RSA_PSS_PARAMS, RSA_PSS_PARAMS)
IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
+IMPLEMENT_ASN1_DUP_FUNCTION(RSA_PSS_PARAMS)
/* Free up maskHash */
static int rsa_oaep_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
@@ -106,16 +113,16 @@ ASN1_SEQUENCE_cb(RSA_OAEP_PARAMS, rsa_oaep_cb) = {
IMPLEMENT_ASN1_FUNCTIONS(RSA_OAEP_PARAMS)
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPrivateKey, RSAPrivateKey)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(RSA, RSAPrivateKey, RSAPrivateKey)
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPublicKey, RSAPublicKey)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(RSA, RSAPublicKey, RSAPublicKey)
-RSA *RSAPublicKey_dup(RSA *rsa)
+RSA *RSAPublicKey_dup(const RSA *rsa)
{
return ASN1_item_dup(ASN1_ITEM_rptr(RSAPublicKey), rsa);
}
-RSA *RSAPrivateKey_dup(RSA *rsa)
+RSA *RSAPrivateKey_dup(const RSA *rsa)
{
return ASN1_item_dup(ASN1_ITEM_rptr(RSAPrivateKey), rsa);
}
diff --git a/crypto/rsa/rsa_backend.c b/crypto/rsa/rsa_backend.c
new file mode 100644
index 000000000000..58187fa2ef59
--- /dev/null
+++ b/crypto/rsa/rsa_backend.c
@@ -0,0 +1,595 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#ifndef FIPS_MODULE
+# include <openssl/x509.h>
+# include "crypto/asn1.h"
+#endif
+#include "internal/sizes.h"
+#include "internal/param_build_set.h"
+#include "crypto/rsa.h"
+#include "rsa_local.h"
+
+/*
+ * The intention with the "backend" source file is to offer backend support
+ * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
+ * implementations alike.
+ */
+
+DEFINE_STACK_OF(BIGNUM)
+
+static int collect_numbers(STACK_OF(BIGNUM) *numbers,
+ const OSSL_PARAM params[], const char *names[])
+{
+ const OSSL_PARAM *p = NULL;
+ int i;
+
+ if (numbers == NULL)
+ return 0;
+
+ for (i = 0; names[i] != NULL; i++){
+ p = OSSL_PARAM_locate_const(params, names[i]);
+ if (p != NULL) {
+ BIGNUM *tmp = NULL;
+
+ if (!OSSL_PARAM_get_BN(p, &tmp))
+ return 0;
+ if (sk_BIGNUM_push(numbers, tmp) == 0) {
+ BN_clear_free(tmp);
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[], int include_private)
+{
+ const OSSL_PARAM *param_n, *param_e, *param_d = NULL;
+ BIGNUM *n = NULL, *e = NULL, *d = NULL;
+ STACK_OF(BIGNUM) *factors = NULL, *exps = NULL, *coeffs = NULL;
+ int is_private = 0;
+
+ if (rsa == NULL)
+ return 0;
+
+ param_n = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N);
+ param_e = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E);
+ if (include_private)
+ param_d = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D);
+
+ if ((param_n != NULL && !OSSL_PARAM_get_BN(param_n, &n))
+ || (param_e != NULL && !OSSL_PARAM_get_BN(param_e, &e))
+ || (param_d != NULL && !OSSL_PARAM_get_BN(param_d, &d)))
+ goto err;
+
+ is_private = (d != NULL);
+
+ if (!RSA_set0_key(rsa, n, e, d))
+ goto err;
+ n = e = d = NULL;
+
+ if (is_private) {
+ if (!collect_numbers(factors = sk_BIGNUM_new_null(), params,
+ ossl_rsa_mp_factor_names)
+ || !collect_numbers(exps = sk_BIGNUM_new_null(), params,
+ ossl_rsa_mp_exp_names)
+ || !collect_numbers(coeffs = sk_BIGNUM_new_null(), params,
+ ossl_rsa_mp_coeff_names))
+ goto err;
+
+ /* It's ok if this private key just has n, e and d */
+ if (sk_BIGNUM_num(factors) != 0
+ && !ossl_rsa_set0_all_params(rsa, factors, exps, coeffs))
+ goto err;
+ }
+
+
+ sk_BIGNUM_free(factors);
+ sk_BIGNUM_free(exps);
+ sk_BIGNUM_free(coeffs);
+ return 1;
+
+ err:
+ BN_free(n);
+ BN_free(e);
+ BN_free(d);
+ sk_BIGNUM_pop_free(factors, BN_free);
+ sk_BIGNUM_pop_free(exps, BN_free);
+ sk_BIGNUM_pop_free(coeffs, BN_free);
+ return 0;
+}
+
+DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
+
+int ossl_rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[],
+ int include_private)
+{
+ int ret = 0;
+ const BIGNUM *rsa_d = NULL, *rsa_n = NULL, *rsa_e = NULL;
+ STACK_OF(BIGNUM_const) *factors = sk_BIGNUM_const_new_null();
+ STACK_OF(BIGNUM_const) *exps = sk_BIGNUM_const_new_null();
+ STACK_OF(BIGNUM_const) *coeffs = sk_BIGNUM_const_new_null();
+
+ if (rsa == NULL || factors == NULL || exps == NULL || coeffs == NULL)
+ goto err;
+
+ RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d);
+ ossl_rsa_get0_all_params(rsa, factors, exps, coeffs);
+
+ if (!ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_RSA_N, rsa_n)
+ || !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_RSA_E, rsa_e))
+ goto err;
+
+ /* Check private key data integrity */
+ if (include_private && rsa_d != NULL) {
+ int numprimes = sk_BIGNUM_const_num(factors);
+ int numexps = sk_BIGNUM_const_num(exps);
+ int numcoeffs = sk_BIGNUM_const_num(coeffs);
+
+ /*
+ * It's permissible to have zero primes, i.e. no CRT params.
+ * Otherwise, there must be at least two, as many exponents,
+ * and one coefficient less.
+ */
+ if (numprimes != 0
+ && (numprimes < 2 || numexps < 2 || numcoeffs < 1))
+ goto err;
+
+ if (!ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_RSA_D,
+ rsa_d)
+ || !ossl_param_build_set_multi_key_bn(bld, params,
+ ossl_rsa_mp_factor_names,
+ factors)
+ || !ossl_param_build_set_multi_key_bn(bld, params,
+ ossl_rsa_mp_exp_names, exps)
+ || !ossl_param_build_set_multi_key_bn(bld, params,
+ ossl_rsa_mp_coeff_names,
+ coeffs))
+ goto err;
+ }
+
+#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+ /* The acvp test results are not meant for export so check for bld == NULL */
+ if (bld == NULL)
+ ossl_rsa_acvp_test_get_params(rsa, params);
+#endif
+ ret = 1;
+ err:
+ sk_BIGNUM_const_free(factors);
+ sk_BIGNUM_const_free(exps);
+ sk_BIGNUM_const_free(coeffs);
+ return ret;
+}
+
+int ossl_rsa_pss_params_30_todata(const RSA_PSS_PARAMS_30 *pss,
+ OSSL_PARAM_BLD *bld, OSSL_PARAM params[])
+{
+ if (!ossl_rsa_pss_params_30_is_unrestricted(pss)) {
+ int hashalg_nid = ossl_rsa_pss_params_30_hashalg(pss);
+ int maskgenalg_nid = ossl_rsa_pss_params_30_maskgenalg(pss);
+ int maskgenhashalg_nid = ossl_rsa_pss_params_30_maskgenhashalg(pss);
+ int saltlen = ossl_rsa_pss_params_30_saltlen(pss);
+ int default_hashalg_nid = ossl_rsa_pss_params_30_hashalg(NULL);
+ int default_maskgenalg_nid = ossl_rsa_pss_params_30_maskgenalg(NULL);
+ int default_maskgenhashalg_nid =
+ ossl_rsa_pss_params_30_maskgenhashalg(NULL);
+ const char *mdname =
+ (hashalg_nid == default_hashalg_nid
+ ? NULL : ossl_rsa_oaeppss_nid2name(hashalg_nid));
+ const char *mgfname =
+ (maskgenalg_nid == default_maskgenalg_nid
+ ? NULL : ossl_rsa_oaeppss_nid2name(maskgenalg_nid));
+ const char *mgf1mdname =
+ (maskgenhashalg_nid == default_maskgenhashalg_nid
+ ? NULL : ossl_rsa_oaeppss_nid2name(maskgenhashalg_nid));
+ const char *key_md = OSSL_PKEY_PARAM_RSA_DIGEST;
+ const char *key_mgf = OSSL_PKEY_PARAM_RSA_MASKGENFUNC;
+ const char *key_mgf1_md = OSSL_PKEY_PARAM_RSA_MGF1_DIGEST;
+ const char *key_saltlen = OSSL_PKEY_PARAM_RSA_PSS_SALTLEN;
+
+ /*
+ * To ensure that the key isn't seen as unrestricted by the recipient,
+ * we make sure that at least one PSS-related parameter is passed, even
+ * if it has a default value; saltlen.
+ */
+ if ((mdname != NULL
+ && !ossl_param_build_set_utf8_string(bld, params, key_md, mdname))
+ || (mgfname != NULL
+ && !ossl_param_build_set_utf8_string(bld, params,
+ key_mgf, mgfname))
+ || (mgf1mdname != NULL
+ && !ossl_param_build_set_utf8_string(bld, params,
+ key_mgf1_md, mgf1mdname))
+ || (!ossl_param_build_set_int(bld, params, key_saltlen, saltlen)))
+ return 0;
+ }
+ return 1;
+}
+
+int ossl_rsa_pss_params_30_fromdata(RSA_PSS_PARAMS_30 *pss_params,
+ int *defaults_set,
+ const OSSL_PARAM params[],
+ OSSL_LIB_CTX *libctx)
+{
+ const OSSL_PARAM *param_md, *param_mgf, *param_mgf1md, *param_saltlen;
+ const OSSL_PARAM *param_propq;
+ const char *propq = NULL;
+ EVP_MD *md = NULL, *mgf1md = NULL;
+ int saltlen;
+ int ret = 0;
+
+ if (pss_params == NULL)
+ return 0;
+ param_propq =
+ OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_DIGEST_PROPS);
+ param_md =
+ OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_DIGEST);
+ param_mgf =
+ OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_MASKGENFUNC);
+ param_mgf1md =
+ OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_MGF1_DIGEST);
+ param_saltlen =
+ OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_PSS_SALTLEN);
+
+ if (param_propq != NULL) {
+ if (param_propq->data_type == OSSL_PARAM_UTF8_STRING)
+ propq = param_propq->data;
+ }
+ /*
+ * If we get any of the parameters, we know we have at least some
+ * restrictions, so we start by setting default values, and let each
+ * parameter override their specific restriction data.
+ */
+ if (!*defaults_set
+ && (param_md != NULL || param_mgf != NULL || param_mgf1md != NULL
+ || param_saltlen != NULL)) {
+ if (!ossl_rsa_pss_params_30_set_defaults(pss_params))
+ return 0;
+ *defaults_set = 1;
+ }
+
+ if (param_mgf != NULL) {
+ int default_maskgenalg_nid = ossl_rsa_pss_params_30_maskgenalg(NULL);
+ const char *mgfname = NULL;
+
+ if (param_mgf->data_type == OSSL_PARAM_UTF8_STRING)
+ mgfname = param_mgf->data;
+ else if (!OSSL_PARAM_get_utf8_ptr(param_mgf, &mgfname))
+ return 0;
+
+ if (OPENSSL_strcasecmp(param_mgf->data,
+ ossl_rsa_mgf_nid2name(default_maskgenalg_nid)) != 0)
+ return 0;
+ }
+
+ /*
+ * We're only interested in the NIDs that correspond to the MDs, so the
+ * exact propquery is unimportant in the EVP_MD_fetch() calls below.
+ */
+
+ if (param_md != NULL) {
+ const char *mdname = NULL;
+
+ if (param_md->data_type == OSSL_PARAM_UTF8_STRING)
+ mdname = param_md->data;
+ else if (!OSSL_PARAM_get_utf8_ptr(param_mgf, &mdname))
+ goto err;
+
+ if ((md = EVP_MD_fetch(libctx, mdname, propq)) == NULL
+ || !ossl_rsa_pss_params_30_set_hashalg(pss_params,
+ ossl_rsa_oaeppss_md2nid(md)))
+ goto err;
+ }
+
+ if (param_mgf1md != NULL) {
+ const char *mgf1mdname = NULL;
+
+ if (param_mgf1md->data_type == OSSL_PARAM_UTF8_STRING)
+ mgf1mdname = param_mgf1md->data;
+ else if (!OSSL_PARAM_get_utf8_ptr(param_mgf, &mgf1mdname))
+ goto err;
+
+ if ((mgf1md = EVP_MD_fetch(libctx, mgf1mdname, propq)) == NULL
+ || !ossl_rsa_pss_params_30_set_maskgenhashalg(
+ pss_params, ossl_rsa_oaeppss_md2nid(mgf1md)))
+ goto err;
+ }
+
+ if (param_saltlen != NULL) {
+ if (!OSSL_PARAM_get_int(param_saltlen, &saltlen)
+ || !ossl_rsa_pss_params_30_set_saltlen(pss_params, saltlen))
+ goto err;
+ }
+
+ ret = 1;
+
+ err:
+ EVP_MD_free(md);
+ EVP_MD_free(mgf1md);
+ return ret;
+}
+
+int ossl_rsa_is_foreign(const RSA *rsa)
+{
+#ifndef FIPS_MODULE
+ if (rsa->engine != NULL || RSA_get_method(rsa) != RSA_PKCS1_OpenSSL())
+ return 1;
+#endif
+ return 0;
+}
+
+static ossl_inline int rsa_bn_dup_check(BIGNUM **out, const BIGNUM *f)
+{
+ if (f != NULL && (*out = BN_dup(f)) == NULL)
+ return 0;
+ return 1;
+}
+
+RSA *ossl_rsa_dup(const RSA *rsa, int selection)
+{
+ RSA *dupkey = NULL;
+#ifndef FIPS_MODULE
+ int pnum, i;
+#endif
+
+ /* Do not try to duplicate foreign RSA keys */
+ if (ossl_rsa_is_foreign(rsa))
+ return NULL;
+
+ if ((dupkey = ossl_rsa_new_with_ctx(rsa->libctx)) == NULL)
+ return NULL;
+
+ /* public key */
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ if (!rsa_bn_dup_check(&dupkey->n, rsa->n))
+ goto err;
+ if (!rsa_bn_dup_check(&dupkey->e, rsa->e))
+ goto err;
+ }
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+
+ /* private key */
+ if (!rsa_bn_dup_check(&dupkey->d, rsa->d))
+ goto err;
+
+ /* factors and crt params */
+ if (!rsa_bn_dup_check(&dupkey->p, rsa->p))
+ goto err;
+ if (!rsa_bn_dup_check(&dupkey->q, rsa->q))
+ goto err;
+ if (!rsa_bn_dup_check(&dupkey->dmp1, rsa->dmp1))
+ goto err;
+ if (!rsa_bn_dup_check(&dupkey->dmq1, rsa->dmq1))
+ goto err;
+ if (!rsa_bn_dup_check(&dupkey->iqmp, rsa->iqmp))
+ goto err;
+ }
+
+ dupkey->version = rsa->version;
+ dupkey->flags = rsa->flags;
+ /* we always copy the PSS parameters regardless of selection */
+ dupkey->pss_params = rsa->pss_params;
+
+#ifndef FIPS_MODULE
+ /* multiprime */
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
+ && (pnum = sk_RSA_PRIME_INFO_num(rsa->prime_infos)) > 0) {
+ dupkey->prime_infos = sk_RSA_PRIME_INFO_new_reserve(NULL, pnum);
+ if (dupkey->prime_infos == NULL)
+ goto err;
+ for (i = 0; i < pnum; i++) {
+ const RSA_PRIME_INFO *pinfo = NULL;
+ RSA_PRIME_INFO *duppinfo = NULL;
+
+ if ((duppinfo = OPENSSL_zalloc(sizeof(*duppinfo))) == NULL) {
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ /* push first so cleanup in error case works */
+ (void)sk_RSA_PRIME_INFO_push(dupkey->prime_infos, duppinfo);
+
+ pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
+ if (!rsa_bn_dup_check(&duppinfo->r, pinfo->r))
+ goto err;
+ if (!rsa_bn_dup_check(&duppinfo->d, pinfo->d))
+ goto err;
+ if (!rsa_bn_dup_check(&duppinfo->t, pinfo->t))
+ goto err;
+ }
+ if (!ossl_rsa_multip_calc_product(dupkey))
+ goto err;
+ }
+
+ if (rsa->pss != NULL) {
+ dupkey->pss = RSA_PSS_PARAMS_dup(rsa->pss);
+ if (rsa->pss->maskGenAlgorithm != NULL
+ && dupkey->pss->maskGenAlgorithm == NULL) {
+ dupkey->pss->maskHash = ossl_x509_algor_mgf1_decode(rsa->pss->maskGenAlgorithm);
+ if (dupkey->pss->maskHash == NULL)
+ goto err;
+ }
+ }
+ if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_RSA,
+ &dupkey->ex_data, &rsa->ex_data))
+ goto err;
+#endif
+
+ return dupkey;
+
+ err:
+ RSA_free(dupkey);
+ return NULL;
+}
+
+#ifndef FIPS_MODULE
+RSA_PSS_PARAMS *ossl_rsa_pss_decode(const X509_ALGOR *alg)
+{
+ RSA_PSS_PARAMS *pss;
+
+ pss = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_PSS_PARAMS),
+ alg->parameter);
+
+ if (pss == NULL)
+ return NULL;
+
+ if (pss->maskGenAlgorithm != NULL) {
+ pss->maskHash = ossl_x509_algor_mgf1_decode(pss->maskGenAlgorithm);
+ if (pss->maskHash == NULL) {
+ RSA_PSS_PARAMS_free(pss);
+ return NULL;
+ }
+ }
+
+ return pss;
+}
+
+static int ossl_rsa_sync_to_pss_params_30(RSA *rsa)
+{
+ const RSA_PSS_PARAMS *legacy_pss = NULL;
+ RSA_PSS_PARAMS_30 *pss = NULL;
+
+ if (rsa != NULL
+ && (legacy_pss = RSA_get0_pss_params(rsa)) != NULL
+ && (pss = ossl_rsa_get0_pss_params_30(rsa)) != NULL) {
+ const EVP_MD *md = NULL, *mgf1md = NULL;
+ int md_nid, mgf1md_nid, saltlen, trailerField;
+ RSA_PSS_PARAMS_30 pss_params;
+
+ /*
+ * We don't care about the validity of the fields here, we just
+ * want to synchronise values. Verifying here makes it impossible
+ * to even read a key with invalid values, making it hard to test
+ * a bad situation.
+ *
+ * Other routines use ossl_rsa_pss_get_param(), so the values will
+ * be checked, eventually.
+ */
+ if (!ossl_rsa_pss_get_param_unverified(legacy_pss, &md, &mgf1md,
+ &saltlen, &trailerField))
+ return 0;
+ md_nid = EVP_MD_get_type(md);
+ mgf1md_nid = EVP_MD_get_type(mgf1md);
+ if (!ossl_rsa_pss_params_30_set_defaults(&pss_params)
+ || !ossl_rsa_pss_params_30_set_hashalg(&pss_params, md_nid)
+ || !ossl_rsa_pss_params_30_set_maskgenhashalg(&pss_params,
+ mgf1md_nid)
+ || !ossl_rsa_pss_params_30_set_saltlen(&pss_params, saltlen)
+ || !ossl_rsa_pss_params_30_set_trailerfield(&pss_params,
+ trailerField))
+ return 0;
+ *pss = pss_params;
+ }
+ return 1;
+}
+
+int ossl_rsa_pss_get_param_unverified(const RSA_PSS_PARAMS *pss,
+ const EVP_MD **pmd, const EVP_MD **pmgf1md,
+ int *psaltlen, int *ptrailerField)
+{
+ RSA_PSS_PARAMS_30 pss_params;
+
+ /* Get the defaults from the ONE place */
+ (void)ossl_rsa_pss_params_30_set_defaults(&pss_params);
+
+ if (pss == NULL)
+ return 0;
+ *pmd = ossl_x509_algor_get_md(pss->hashAlgorithm);
+ if (*pmd == NULL)
+ return 0;
+ *pmgf1md = ossl_x509_algor_get_md(pss->maskHash);
+ if (*pmgf1md == NULL)
+ return 0;
+ if (pss->saltLength)
+ *psaltlen = ASN1_INTEGER_get(pss->saltLength);
+ else
+ *psaltlen = ossl_rsa_pss_params_30_saltlen(&pss_params);
+ if (pss->trailerField)
+ *ptrailerField = ASN1_INTEGER_get(pss->trailerField);
+ else
+ *ptrailerField = ossl_rsa_pss_params_30_trailerfield(&pss_params);;
+
+ return 1;
+}
+
+int ossl_rsa_param_decode(RSA *rsa, const X509_ALGOR *alg)
+{
+ RSA_PSS_PARAMS *pss;
+ const ASN1_OBJECT *algoid;
+ const void *algp;
+ int algptype;
+
+ X509_ALGOR_get0(&algoid, &algptype, &algp, alg);
+ if (OBJ_obj2nid(algoid) != EVP_PKEY_RSA_PSS)
+ return 1;
+ if (algptype == V_ASN1_UNDEF)
+ return 1;
+ if (algptype != V_ASN1_SEQUENCE) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PSS_PARAMETERS);
+ return 0;
+ }
+ if ((pss = ossl_rsa_pss_decode(alg)) == NULL
+ || !ossl_rsa_set0_pss_params(rsa, pss)) {
+ RSA_PSS_PARAMS_free(pss);
+ return 0;
+ }
+ if (!ossl_rsa_sync_to_pss_params_30(rsa))
+ return 0;
+ return 1;
+}
+
+RSA *ossl_rsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ const unsigned char *p;
+ RSA *rsa;
+ int pklen;
+ const X509_ALGOR *alg;
+
+ if (!PKCS8_pkey_get0(NULL, &p, &pklen, &alg, p8inf))
+ return 0;
+ rsa = d2i_RSAPrivateKey(NULL, &p, pklen);
+ if (rsa == NULL) {
+ ERR_raise(ERR_LIB_RSA, ERR_R_RSA_LIB);
+ return NULL;
+ }
+ if (!ossl_rsa_param_decode(rsa, alg)) {
+ RSA_free(rsa);
+ return NULL;
+ }
+
+ RSA_clear_flags(rsa, RSA_FLAG_TYPE_MASK);
+ switch (OBJ_obj2nid(alg->algorithm)) {
+ case EVP_PKEY_RSA:
+ RSA_set_flags(rsa, RSA_FLAG_TYPE_RSA);
+ break;
+ case EVP_PKEY_RSA_PSS:
+ RSA_set_flags(rsa, RSA_FLAG_TYPE_RSASSAPSS);
+ break;
+ default:
+ /* Leave the type bits zero */
+ break;
+ }
+
+ return rsa;
+}
+#endif
diff --git a/crypto/rsa/rsa_chk.c b/crypto/rsa/rsa_chk.c
index b4ba7fce3ffb..cccc2d5bac2a 100644
--- a/crypto/rsa/rsa_chk.c
+++ b/crypto/rsa/rsa_chk.c
@@ -1,22 +1,25 @@
/*
- * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/bn.h>
#include <openssl/err.h>
+#include "crypto/rsa.h"
#include "rsa_local.h"
-int RSA_check_key(const RSA *key)
-{
- return RSA_check_key_ex(key, NULL);
-}
-
-int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
+#ifndef FIPS_MODULE
+static int rsa_validate_keypair_multiprime(const RSA *key, BN_GENCB *cb)
{
BIGNUM *i, *j, *k, *l, *m;
BN_CTX *ctx;
@@ -25,7 +28,7 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
if (key->p == NULL || key->q == NULL || key->n == NULL
|| key->e == NULL || key->d == NULL) {
- RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_VALUE_MISSING);
+ ERR_raise(ERR_LIB_RSA, RSA_R_VALUE_MISSING);
return 0;
}
@@ -33,8 +36,8 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
if (key->version == RSA_ASN1_VERSION_MULTI) {
ex_primes = sk_RSA_PRIME_INFO_num(key->prime_infos);
if (ex_primes <= 0
- || (ex_primes + 2) > rsa_multip_cap(BN_num_bits(key->n))) {
- RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_INVALID_MULTI_PRIME_KEY);
+ || (ex_primes + 2) > ossl_rsa_multip_cap(BN_num_bits(key->n))) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MULTI_PRIME_KEY);
return 0;
}
}
@@ -44,41 +47,41 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
k = BN_new();
l = BN_new();
m = BN_new();
- ctx = BN_CTX_new();
+ ctx = BN_CTX_new_ex(key->libctx);
if (i == NULL || j == NULL || k == NULL || l == NULL
|| m == NULL || ctx == NULL) {
ret = -1;
- RSAerr(RSA_F_RSA_CHECK_KEY_EX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
if (BN_is_one(key->e)) {
ret = 0;
- RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_BAD_E_VALUE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE);
}
if (!BN_is_odd(key->e)) {
ret = 0;
- RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_BAD_E_VALUE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE);
}
/* p prime? */
- if (BN_is_prime_ex(key->p, BN_prime_checks, NULL, cb) != 1) {
+ if (BN_check_prime(key->p, ctx, cb) != 1) {
ret = 0;
- RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_P_NOT_PRIME);
+ ERR_raise(ERR_LIB_RSA, RSA_R_P_NOT_PRIME);
}
/* q prime? */
- if (BN_is_prime_ex(key->q, BN_prime_checks, NULL, cb) != 1) {
+ if (BN_check_prime(key->q, ctx, cb) != 1) {
ret = 0;
- RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_Q_NOT_PRIME);
+ ERR_raise(ERR_LIB_RSA, RSA_R_Q_NOT_PRIME);
}
/* r_i prime? */
for (idx = 0; idx < ex_primes; idx++) {
pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
- if (BN_is_prime_ex(pinfo->r, BN_prime_checks, NULL, cb) != 1) {
+ if (BN_check_prime(pinfo->r, ctx, cb) != 1) {
ret = 0;
- RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_R_NOT_PRIME);
+ ERR_raise(ERR_LIB_RSA, RSA_R_MP_R_NOT_PRIME);
}
}
@@ -97,10 +100,9 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
if (BN_cmp(i, key->n) != 0) {
ret = 0;
if (ex_primes)
- RSAerr(RSA_F_RSA_CHECK_KEY_EX,
- RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES);
+ ERR_raise(ERR_LIB_RSA, RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES);
else
- RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_N_DOES_NOT_EQUAL_P_Q);
+ ERR_raise(ERR_LIB_RSA, RSA_R_N_DOES_NOT_EQUAL_P_Q);
}
/* d*e = 1 mod \lambda(n)? */
@@ -148,7 +150,7 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
if (!BN_is_one(i)) {
ret = 0;
- RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_D_E_NOT_CONGRUENT_TO_1);
+ ERR_raise(ERR_LIB_RSA, RSA_R_D_E_NOT_CONGRUENT_TO_1);
}
if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) {
@@ -163,7 +165,7 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
}
if (BN_cmp(j, key->dmp1) != 0) {
ret = 0;
- RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_DMP1_NOT_CONGRUENT_TO_D);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DMP1_NOT_CONGRUENT_TO_D);
}
/* dmq1 = d mod (q-1)? */
@@ -177,7 +179,7 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
}
if (BN_cmp(j, key->dmq1) != 0) {
ret = 0;
- RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_DMQ1_NOT_CONGRUENT_TO_D);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DMQ1_NOT_CONGRUENT_TO_D);
}
/* iqmp = q^-1 mod p? */
@@ -187,7 +189,7 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
}
if (BN_cmp(i, key->iqmp) != 0) {
ret = 0;
- RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_IQMP_NOT_INVERSE_OF_Q);
+ ERR_raise(ERR_LIB_RSA, RSA_R_IQMP_NOT_INVERSE_OF_Q);
}
}
@@ -204,7 +206,7 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
}
if (BN_cmp(j, pinfo->d) != 0) {
ret = 0;
- RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D);
+ ERR_raise(ERR_LIB_RSA, RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D);
}
/* t_i = R_i ^ -1 mod r_i ? */
if (!BN_mod_inverse(i, pinfo->pp, pinfo->r, ctx)) {
@@ -213,7 +215,7 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
}
if (BN_cmp(i, pinfo->t) != 0) {
ret = 0;
- RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R);
+ ERR_raise(ERR_LIB_RSA, RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R);
}
}
@@ -226,3 +228,39 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
BN_CTX_free(ctx);
return ret;
}
+#endif /* FIPS_MODULE */
+
+int ossl_rsa_validate_public(const RSA *key)
+{
+ return ossl_rsa_sp800_56b_check_public(key);
+}
+
+int ossl_rsa_validate_private(const RSA *key)
+{
+ return ossl_rsa_sp800_56b_check_private(key);
+}
+
+int ossl_rsa_validate_pairwise(const RSA *key)
+{
+#ifdef FIPS_MODULE
+ return ossl_rsa_sp800_56b_check_keypair(key, NULL, -1, RSA_bits(key));
+#else
+ return rsa_validate_keypair_multiprime(key, NULL) > 0;
+#endif
+}
+
+int RSA_check_key(const RSA *key)
+{
+ return RSA_check_key_ex(key, NULL);
+}
+
+int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
+{
+#ifdef FIPS_MODULE
+ return ossl_rsa_validate_public(key)
+ && ossl_rsa_validate_private(key)
+ && ossl_rsa_validate_pairwise(key);
+#else
+ return rsa_validate_keypair_multiprime(key, cb);
+#endif /* FIPS_MODULE */
+}
diff --git a/crypto/rsa/rsa_crpt.c b/crypto/rsa/rsa_crpt.c
index f1131ce9e0ad..6bc6aafcc893 100644
--- a/crypto/rsa/rsa_crpt.c
+++ b/crypto/rsa/rsa_crpt.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <openssl/crypto.h>
#include "internal/cryptlib.h"
@@ -114,7 +120,7 @@ BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx)
BN_BLINDING *ret = NULL;
if (in_ctx == NULL) {
- if ((ctx = BN_CTX_new()) == NULL)
+ if ((ctx = BN_CTX_new_ex(rsa->libctx)) == NULL)
return 0;
} else {
ctx = in_ctx;
@@ -123,14 +129,14 @@ BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx)
BN_CTX_start(ctx);
e = BN_CTX_get(ctx);
if (e == NULL) {
- RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
if (rsa->e == NULL) {
e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx);
if (e == NULL) {
- RSAerr(RSA_F_RSA_SETUP_BLINDING, RSA_R_NO_PUBLIC_EXPONENT);
+ ERR_raise(ERR_LIB_RSA, RSA_R_NO_PUBLIC_EXPONENT);
goto err;
}
} else {
@@ -141,7 +147,7 @@ BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx)
BIGNUM *n = BN_new();
if (n == NULL) {
- RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME);
@@ -152,7 +158,7 @@ BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx)
BN_free(n);
}
if (ret == NULL) {
- RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_RSA, ERR_R_BN_LIB);
goto err;
}
diff --git a/crypto/rsa/rsa_depr.c b/crypto/rsa/rsa_depr.c
index 21e0562525d0..3cc89b26a99c 100644
--- a/crypto/rsa/rsa_depr.c
+++ b/crypto/rsa/rsa_depr.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,17 +12,19 @@
* "new" versions).
*/
-#include <openssl/opensslconf.h>
-#if OPENSSL_API_COMPAT >= 0x00908000L
-NON_EMPTY_TRANSLATION_UNIT
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
-#else
+#include <openssl/opensslconf.h>
-# include <stdio.h>
-# include <time.h>
-# include "internal/cryptlib.h"
-# include <openssl/bn.h>
-# include <openssl/rsa.h>
+#include <stdio.h>
+#include <time.h>
+#include "internal/cryptlib.h"
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
RSA *RSA_generate_key(int bits, unsigned long e_value,
void (*callback) (int, int, void *), void *cb_arg)
@@ -58,4 +60,3 @@ RSA *RSA_generate_key(int bits, unsigned long e_value,
BN_GENCB_free(cb);
return 0;
}
-#endif
diff --git a/crypto/rsa/rsa_err.c b/crypto/rsa/rsa_err.c
index 0687c1e62602..269971c07b8d 100644
--- a/crypto/rsa/rsa_err.c
+++ b/crypto/rsa/rsa_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,102 +10,10 @@
#include <openssl/err.h>
#include <openssl/rsaerr.h>
+#include "crypto/rsaerr.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA RSA_str_functs[] = {
- {ERR_PACK(ERR_LIB_RSA, RSA_F_CHECK_PADDING_MD, 0), "check_padding_md"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_ENCODE_PKCS1, 0), "encode_pkcs1"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_INT_RSA_VERIFY, 0), "int_rsa_verify"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_OLD_RSA_PRIV_DECODE, 0),
- "old_rsa_priv_decode"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_PSS_INIT, 0), "pkey_pss_init"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_CTRL, 0), "pkey_rsa_ctrl"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_CTRL_STR, 0), "pkey_rsa_ctrl_str"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_SIGN, 0), "pkey_rsa_sign"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_VERIFY, 0), "pkey_rsa_verify"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_VERIFYRECOVER, 0),
- "pkey_rsa_verifyrecover"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_ALGOR_TO_MD, 0), "rsa_algor_to_md"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_BUILTIN_KEYGEN, 0), "rsa_builtin_keygen"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_CHECK_KEY, 0), "RSA_check_key"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_CHECK_KEY_EX, 0), "RSA_check_key_ex"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_CMS_DECRYPT, 0), "rsa_cms_decrypt"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_CMS_VERIFY, 0), "rsa_cms_verify"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_ITEM_VERIFY, 0), "rsa_item_verify"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_METH_DUP, 0), "RSA_meth_dup"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_METH_NEW, 0), "RSA_meth_new"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_METH_SET1_NAME, 0), "RSA_meth_set1_name"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_MGF1_TO_MD, 0), ""},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_MULTIP_INFO_NEW, 0),
- "rsa_multip_info_new"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NEW_METHOD, 0), "RSA_new_method"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NULL, 0), ""},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NULL_PRIVATE_DECRYPT, 0), ""},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NULL_PRIVATE_ENCRYPT, 0), ""},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NULL_PUBLIC_DECRYPT, 0), ""},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NULL_PUBLIC_ENCRYPT, 0), ""},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PRIVATE_DECRYPT, 0),
- "rsa_ossl_private_decrypt"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, 0),
- "rsa_ossl_private_encrypt"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PUBLIC_DECRYPT, 0),
- "rsa_ossl_public_decrypt"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, 0),
- "rsa_ossl_public_encrypt"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_NONE, 0),
- "RSA_padding_add_none"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, 0),
- "RSA_padding_add_PKCS1_OAEP"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, 0),
- "RSA_padding_add_PKCS1_OAEP_mgf1"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_PSS, 0),
- "RSA_padding_add_PKCS1_PSS"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, 0),
- "RSA_padding_add_PKCS1_PSS_mgf1"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1, 0),
- "RSA_padding_add_PKCS1_type_1"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2, 0),
- "RSA_padding_add_PKCS1_type_2"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_SSLV23, 0),
- "RSA_padding_add_SSLv23"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_X931, 0),
- "RSA_padding_add_X931"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_NONE, 0),
- "RSA_padding_check_none"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, 0),
- "RSA_padding_check_PKCS1_OAEP"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, 0),
- "RSA_padding_check_PKCS1_OAEP_mgf1"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1, 0),
- "RSA_padding_check_PKCS1_type_1"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, 0),
- "RSA_padding_check_PKCS1_type_2"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_SSLV23, 0),
- "RSA_padding_check_SSLv23"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_X931, 0),
- "RSA_padding_check_X931"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PARAM_DECODE, 0), "rsa_param_decode"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRINT, 0), "RSA_print"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRINT_FP, 0), "RSA_print_fp"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRIV_DECODE, 0), "rsa_priv_decode"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRIV_ENCODE, 0), "rsa_priv_encode"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PSS_GET_PARAM, 0), "rsa_pss_get_param"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PSS_TO_CTX, 0), "rsa_pss_to_ctx"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PUB_DECODE, 0), "rsa_pub_decode"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_SETUP_BLINDING, 0), "RSA_setup_blinding"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_SIGN, 0), "RSA_sign"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_SIGN_ASN1_OCTET_STRING, 0),
- "RSA_sign_ASN1_OCTET_STRING"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_VERIFY, 0), "RSA_verify"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_VERIFY_ASN1_OCTET_STRING, 0),
- "RSA_verify_ASN1_OCTET_STRING"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, 0),
- "RSA_verify_PKCS1_PSS_mgf1"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_SETUP_TBUF, 0), "setup_tbuf"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA RSA_str_reasons[] = {
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_ALGORITHM_MISMATCH), "algorithm mismatch"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_E_VALUE), "bad e value"},
@@ -146,10 +54,14 @@ static const ERR_STRING_DATA RSA_str_reasons[] = {
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_DIGEST_LENGTH),
"invalid digest length"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_HEADER), "invalid header"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_KEYPAIR), "invalid keypair"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_KEY_LENGTH), "invalid key length"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_LABEL), "invalid label"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_LENGTH), "invalid length"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_MESSAGE_LENGTH),
"invalid message length"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_MGF1_MD), "invalid mgf1 md"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_MODULUS), "invalid modulus"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_MULTI_PRIME_KEY),
"invalid multi prime key"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_OAEP_PARAMETERS),
@@ -161,8 +73,10 @@ static const ERR_STRING_DATA RSA_str_reasons[] = {
"invalid pss parameters"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_PSS_SALTLEN),
"invalid pss saltlen"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_REQUEST), "invalid request"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_SALT_LENGTH),
"invalid salt length"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_STRENGTH), "invalid strength"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_TRAILER), "invalid trailer"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_X931_DIGEST),
"invalid x931 digest"},
@@ -195,12 +109,18 @@ static const ERR_STRING_DATA RSA_str_reasons[] = {
"operation not supported for this keytype"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_PADDING_CHECK_FAILED),
"padding check failed"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_PAIRWISE_TEST_FAILURE),
+ "pairwise test failure"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_PKCS_DECODING_ERROR),
"pkcs decoding error"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_PSS_SALTLEN_TOO_SMALL),
"pss saltlen too small"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_PUB_EXPONENT_OUT_OF_RANGE),
+ "pub exponent out of range"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_P_NOT_PRIME), "p not prime"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_Q_NOT_PRIME), "q not prime"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT),
+ "randomness source strength insufficient"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED),
"rsa operations not supported"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_SLEN_CHECK_FAILED),
@@ -236,13 +156,11 @@ static const ERR_STRING_DATA RSA_str_reasons[] = {
#endif
-int ERR_load_RSA_strings(void)
+int ossl_err_load_RSA_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(RSA_str_functs[0].error) == NULL) {
- ERR_load_strings_const(RSA_str_functs);
+ if (ERR_reason_error_string(RSA_str_reasons[0].error) == NULL)
ERR_load_strings_const(RSA_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/rsa/rsa_gen.c b/crypto/rsa/rsa_gen.c
index 29056a62a1ae..e0d139d3121c 100644
--- a/crypto/rsa/rsa_gen.c
+++ b/crypto/rsa/rsa_gen.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,14 +13,23 @@
* Geoff
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <time.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
+#include <openssl/self_test.h>
+#include "prov/providercommon.h"
#include "rsa_local.h"
-static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
- BN_GENCB *cb);
+static int rsa_keygen_pairwise_test(RSA *rsa, OSSL_CALLBACK *cb, void *cbarg);
+static int rsa_keygen(OSSL_LIB_CTX *libctx, RSA *rsa, int bits, int primes,
+ BIGNUM *e_value, BN_GENCB *cb, int pairwise_test);
/*
* NB: this wrapper would normally be placed in rsa_lib.c and the static
@@ -41,6 +50,7 @@ int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb)
int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes,
BIGNUM *e_value, BN_GENCB *cb)
{
+#ifndef FIPS_MODULE
/* multi-prime is only supported with the builtin key generation */
if (rsa->meth->rsa_multi_prime_keygen != NULL) {
return rsa->meth->rsa_multi_prime_keygen(rsa, bits, primes,
@@ -57,35 +67,43 @@ int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes,
else
return 0;
}
-
- return rsa_builtin_keygen(rsa, bits, primes, e_value, cb);
+#endif /* FIPS_MODULE */
+ return rsa_keygen(rsa->libctx, rsa, bits, primes, e_value, cb, 0);
}
-static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
- BN_GENCB *cb)
+#ifndef FIPS_MODULE
+static int rsa_multiprime_keygen(RSA *rsa, int bits, int primes,
+ BIGNUM *e_value, BN_GENCB *cb)
{
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *tmp, *prime;
- int ok = -1, n = 0, bitsr[RSA_MAX_PRIME_NUM], bitse = 0;
+ int n = 0, bitsr[RSA_MAX_PRIME_NUM], bitse = 0;
int i = 0, quo = 0, rmd = 0, adj = 0, retries = 0;
RSA_PRIME_INFO *pinfo = NULL;
STACK_OF(RSA_PRIME_INFO) *prime_infos = NULL;
BN_CTX *ctx = NULL;
BN_ULONG bitst = 0;
unsigned long error = 0;
+ int ok = -1;
if (bits < RSA_MIN_MODULUS_BITS) {
ok = 0; /* we set our own err */
- RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_KEY_SIZE_TOO_SMALL);
+ ERR_raise(ERR_LIB_RSA, RSA_R_KEY_SIZE_TOO_SMALL);
goto err;
}
- if (primes < RSA_DEFAULT_PRIME_NUM || primes > rsa_multip_cap(bits)) {
+ /* A bad value for e can cause infinite loops */
+ if (e_value != NULL && !ossl_rsa_check_public_exponent(e_value)) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_PUB_EXPONENT_OUT_OF_RANGE);
+ return 0;
+ }
+
+ if (primes < RSA_DEFAULT_PRIME_NUM || primes > ossl_rsa_multip_cap(bits)) {
ok = 0; /* we set our own err */
- RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_KEY_PRIME_NUM_INVALID);
+ ERR_raise(ERR_LIB_RSA, RSA_R_KEY_PRIME_NUM_INVALID);
goto err;
}
- ctx = BN_CTX_new();
+ ctx = BN_CTX_new_ex(rsa->libctx);
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
@@ -102,23 +120,31 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
for (i = 0; i < primes; i++)
bitsr[i] = (i < rmd) ? quo + 1 : quo;
+ rsa->dirty_cnt++;
+
/* We need the RSA components non-NULL */
if (!rsa->n && ((rsa->n = BN_new()) == NULL))
goto err;
if (!rsa->d && ((rsa->d = BN_secure_new()) == NULL))
goto err;
+ BN_set_flags(rsa->d, BN_FLG_CONSTTIME);
if (!rsa->e && ((rsa->e = BN_new()) == NULL))
goto err;
if (!rsa->p && ((rsa->p = BN_secure_new()) == NULL))
goto err;
+ BN_set_flags(rsa->p, BN_FLG_CONSTTIME);
if (!rsa->q && ((rsa->q = BN_secure_new()) == NULL))
goto err;
+ BN_set_flags(rsa->q, BN_FLG_CONSTTIME);
if (!rsa->dmp1 && ((rsa->dmp1 = BN_secure_new()) == NULL))
goto err;
+ BN_set_flags(rsa->dmp1, BN_FLG_CONSTTIME);
if (!rsa->dmq1 && ((rsa->dmq1 = BN_secure_new()) == NULL))
goto err;
+ BN_set_flags(rsa->dmq1, BN_FLG_CONSTTIME);
if (!rsa->iqmp && ((rsa->iqmp = BN_secure_new()) == NULL))
goto err;
+ BN_set_flags(rsa->iqmp, BN_FLG_CONSTTIME);
/* initialize multi-prime components */
if (primes > RSA_DEFAULT_PRIME_NUM) {
@@ -128,13 +154,14 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
goto err;
if (rsa->prime_infos != NULL) {
/* could this happen? */
- sk_RSA_PRIME_INFO_pop_free(rsa->prime_infos, rsa_multip_info_free);
+ sk_RSA_PRIME_INFO_pop_free(rsa->prime_infos,
+ ossl_rsa_multip_info_free);
}
rsa->prime_infos = prime_infos;
/* prime_info from 2 to |primes| -1 */
for (i = 2; i < primes; i++) {
- pinfo = rsa_multip_info_new();
+ pinfo = ossl_rsa_multip_info_new();
if (pinfo == NULL)
goto err;
(void)sk_RSA_PRIME_INFO_push(prime_infos, pinfo);
@@ -161,7 +188,8 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
for (;;) {
redo:
- if (!BN_generate_prime_ex(prime, bitsr[i] + adj, 0, NULL, NULL, cb))
+ if (!BN_generate_prime_ex2(prime, bitsr[i] + adj, 0, NULL, NULL,
+ cb, ctx))
goto err;
/*
* prime should not be equal to p, q, r_3...
@@ -384,10 +412,118 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
ok = 1;
err:
if (ok == -1) {
- RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, ERR_LIB_BN);
+ ERR_raise(ERR_LIB_RSA, ERR_R_BN_LIB);
ok = 0;
}
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ok;
}
+#endif /* FIPS_MODULE */
+
+static int rsa_keygen(OSSL_LIB_CTX *libctx, RSA *rsa, int bits, int primes,
+ BIGNUM *e_value, BN_GENCB *cb, int pairwise_test)
+{
+ int ok = 0;
+
+#ifdef FIPS_MODULE
+ ok = ossl_rsa_sp800_56b_generate_key(rsa, bits, e_value, cb);
+ pairwise_test = 1; /* FIPS MODE needs to always run the pairwise test */
+#else
+ /*
+ * Only multi-prime keys or insecure keys with a small key length or a
+ * public exponent <= 2^16 will use the older rsa_multiprime_keygen().
+ */
+ if (primes == 2
+ && bits >= 2048
+ && (e_value == NULL || BN_num_bits(e_value) > 16))
+ ok = ossl_rsa_sp800_56b_generate_key(rsa, bits, e_value, cb);
+ else
+ ok = rsa_multiprime_keygen(rsa, bits, primes, e_value, cb);
+#endif /* FIPS_MODULE */
+
+ if (pairwise_test && ok > 0) {
+ OSSL_CALLBACK *stcb = NULL;
+ void *stcbarg = NULL;
+
+ OSSL_SELF_TEST_get_callback(libctx, &stcb, &stcbarg);
+ ok = rsa_keygen_pairwise_test(rsa, stcb, stcbarg);
+ if (!ok) {
+ ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
+ /* Clear intermediate results */
+ BN_clear_free(rsa->d);
+ BN_clear_free(rsa->p);
+ BN_clear_free(rsa->q);
+ BN_clear_free(rsa->dmp1);
+ BN_clear_free(rsa->dmq1);
+ BN_clear_free(rsa->iqmp);
+ rsa->d = NULL;
+ rsa->p = NULL;
+ rsa->q = NULL;
+ rsa->dmp1 = NULL;
+ rsa->dmq1 = NULL;
+ rsa->iqmp = NULL;
+ }
+ }
+ return ok;
+}
+
+/*
+ * For RSA key generation it is not known whether the key pair will be used
+ * for key transport or signatures. FIPS 140-2 IG 9.9 states that in this case
+ * either a signature verification OR an encryption operation may be used to
+ * perform the pairwise consistency check. The simpler encrypt/decrypt operation
+ * has been chosen for this case.
+ */
+static int rsa_keygen_pairwise_test(RSA *rsa, OSSL_CALLBACK *cb, void *cbarg)
+{
+ int ret = 0;
+ unsigned int ciphertxt_len;
+ unsigned char *ciphertxt = NULL;
+ const unsigned char plaintxt[16] = {0};
+ unsigned char *decoded = NULL;
+ unsigned int decoded_len;
+ unsigned int plaintxt_len = (unsigned int)sizeof(plaintxt_len);
+ int padding = RSA_PKCS1_PADDING;
+ OSSL_SELF_TEST *st = NULL;
+
+ st = OSSL_SELF_TEST_new(cb, cbarg);
+ if (st == NULL)
+ goto err;
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
+ OSSL_SELF_TEST_DESC_PCT_RSA_PKCS1);
+
+ ciphertxt_len = RSA_size(rsa);
+ /*
+ * RSA_private_encrypt() and RSA_private_decrypt() requires the 'to'
+ * parameter to be a maximum of RSA_size() - allocate space for both.
+ */
+ ciphertxt = OPENSSL_zalloc(ciphertxt_len * 2);
+ if (ciphertxt == NULL)
+ goto err;
+ decoded = ciphertxt + ciphertxt_len;
+
+ ciphertxt_len = RSA_public_encrypt(plaintxt_len, plaintxt, ciphertxt, rsa,
+ padding);
+ if (ciphertxt_len <= 0)
+ goto err;
+ if (ciphertxt_len == plaintxt_len
+ && memcmp(ciphertxt, plaintxt, plaintxt_len) == 0)
+ goto err;
+
+ OSSL_SELF_TEST_oncorrupt_byte(st, ciphertxt);
+
+ decoded_len = RSA_private_decrypt(ciphertxt_len, ciphertxt, decoded, rsa,
+ padding);
+ if (decoded_len != plaintxt_len
+ || memcmp(decoded, plaintxt, decoded_len) != 0)
+ goto err;
+
+ ret = 1;
+err:
+ OSSL_SELF_TEST_onend(st, ret);
+ OSSL_SELF_TEST_free(st);
+ OPENSSL_free(ciphertxt);
+
+ return ret;
+}
diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c
index 63fd1a6db492..449097b8b27a 100644
--- a/crypto/rsa/rsa_lib.c
+++ b/crypto/rsa/rsa_lib.c
@@ -1,25 +1,39 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <stdio.h>
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/crypto.h>
+#include <openssl/core_names.h>
+#ifndef FIPS_MODULE
+# include <openssl/engine.h>
+#endif
+#include <openssl/evp.h>
+#include <openssl/param_build.h>
#include "internal/cryptlib.h"
#include "internal/refcount.h"
#include "crypto/bn.h"
-#include <openssl/engine.h>
-#include <openssl/evp.h>
#include "crypto/evp.h"
+#include "crypto/rsa.h"
+#include "crypto/security_bits.h"
#include "rsa_local.h"
+static RSA *rsa_new_intern(ENGINE *engine, OSSL_LIB_CTX *libctx);
+
+#ifndef FIPS_MODULE
RSA *RSA_new(void)
{
- return RSA_new_method(NULL);
+ return rsa_new_intern(NULL, NULL);
}
const RSA_METHOD *RSA_get_method(const RSA *rsa)
@@ -49,27 +63,39 @@ int RSA_set_method(RSA *rsa, const RSA_METHOD *meth)
RSA *RSA_new_method(ENGINE *engine)
{
+ return rsa_new_intern(engine, NULL);
+}
+#endif
+
+RSA *ossl_rsa_new_with_ctx(OSSL_LIB_CTX *libctx)
+{
+ return rsa_new_intern(NULL, libctx);
+}
+
+static RSA *rsa_new_intern(ENGINE *engine, OSSL_LIB_CTX *libctx)
+{
RSA *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->references = 1;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
- RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
+ ret->libctx = libctx;
ret->meth = RSA_get_default_method();
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
ret->flags = ret->meth->flags & ~RSA_FLAG_NON_FIPS_ALLOW;
if (engine) {
if (!ENGINE_init(engine)) {
- RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_ENGINE_LIB);
+ ERR_raise(ERR_LIB_RSA, ERR_R_ENGINE_LIB);
goto err;
}
ret->engine = engine;
@@ -79,19 +105,21 @@ RSA *RSA_new_method(ENGINE *engine)
if (ret->engine) {
ret->meth = ENGINE_get_RSA(ret->engine);
if (ret->meth == NULL) {
- RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_ENGINE_LIB);
+ ERR_raise(ERR_LIB_RSA, ERR_R_ENGINE_LIB);
goto err;
}
}
#endif
ret->flags = ret->meth->flags & ~RSA_FLAG_NON_FIPS_ALLOW;
+#ifndef FIPS_MODULE
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data)) {
goto err;
}
+#endif
if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
- RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_INIT_FAIL);
+ ERR_raise(ERR_LIB_RSA, ERR_R_INIT_FAIL);
goto err;
}
@@ -117,11 +145,13 @@ void RSA_free(RSA *r)
if (r->meth != NULL && r->meth->finish != NULL)
r->meth->finish(r);
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
ENGINE_finish(r->engine);
#endif
+#ifndef FIPS_MODULE
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, r, &r->ex_data);
+#endif
CRYPTO_THREAD_lock_free(r->lock);
@@ -133,11 +163,17 @@ void RSA_free(RSA *r)
BN_clear_free(r->dmp1);
BN_clear_free(r->dmq1);
BN_clear_free(r->iqmp);
+
+#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+ ossl_rsa_acvp_test_free(r->acvp_test);
+#endif
+
+#ifndef FIPS_MODULE
RSA_PSS_PARAMS_free(r->pss);
- sk_RSA_PRIME_INFO_pop_free(r->prime_infos, rsa_multip_info_free);
+ sk_RSA_PRIME_INFO_pop_free(r->prime_infos, ossl_rsa_multip_info_free);
+#endif
BN_BLINDING_free(r->blinding);
BN_BLINDING_free(r->mt_blinding);
- OPENSSL_free(r->bignum_data);
OPENSSL_free(r);
}
@@ -153,6 +189,17 @@ int RSA_up_ref(RSA *r)
return i > 1 ? 1 : 0;
}
+OSSL_LIB_CTX *ossl_rsa_get0_libctx(RSA *r)
+{
+ return r->libctx;
+}
+
+void ossl_rsa_set0_libctx(RSA *r, OSSL_LIB_CTX *libctx)
+{
+ r->libctx = libctx;
+}
+
+#ifndef FIPS_MODULE
int RSA_set_ex_data(RSA *r, int idx, void *arg)
{
return CRYPTO_set_ex_data(&r->ex_data, idx, arg);
@@ -162,19 +209,184 @@ void *RSA_get_ex_data(const RSA *r, int idx)
{
return CRYPTO_get_ex_data(&r->ex_data, idx);
}
+#endif
+
+/*
+ * Define a scaling constant for our fixed point arithmetic.
+ * This value must be a power of two because the base two logarithm code
+ * makes this assumption. The exponent must also be a multiple of three so
+ * that the scale factor has an exact cube root. Finally, the scale factor
+ * should not be so large that a multiplication of two scaled numbers
+ * overflows a 64 bit unsigned integer.
+ */
+static const unsigned int scale = 1 << 18;
+static const unsigned int cbrt_scale = 1 << (2 * 18 / 3);
+
+/* Define some constants, none exceed 32 bits */
+static const unsigned int log_2 = 0x02c5c8; /* scale * log(2) */
+static const unsigned int log_e = 0x05c551; /* scale * log2(M_E) */
+static const unsigned int c1_923 = 0x07b126; /* scale * 1.923 */
+static const unsigned int c4_690 = 0x12c28f; /* scale * 4.690 */
+
+/*
+ * Multiply two scaled integers together and rescale the result.
+ */
+static ossl_inline uint64_t mul2(uint64_t a, uint64_t b)
+{
+ return a * b / scale;
+}
+
+/*
+ * Calculate the cube root of a 64 bit scaled integer.
+ * Although the cube root of a 64 bit number does fit into a 32 bit unsigned
+ * integer, this is not guaranteed after scaling, so this function has a
+ * 64 bit return. This uses the shifting nth root algorithm with some
+ * algebraic simplifications.
+ */
+static uint64_t icbrt64(uint64_t x)
+{
+ uint64_t r = 0;
+ uint64_t b;
+ int s;
+
+ for (s = 63; s >= 0; s -= 3) {
+ r <<= 1;
+ b = 3 * r * (r + 1) + 1;
+ if ((x >> s) >= b) {
+ x -= b << s;
+ r++;
+ }
+ }
+ return r * cbrt_scale;
+}
+
+/*
+ * Calculate the natural logarithm of a 64 bit scaled integer.
+ * This is done by calculating a base two logarithm and scaling.
+ * The maximum logarithm (base 2) is 64 and this reduces base e, so
+ * a 32 bit result should not overflow. The argument passed must be
+ * greater than unity so we don't need to handle negative results.
+ */
+static uint32_t ilog_e(uint64_t v)
+{
+ uint32_t i, r = 0;
+
+ /*
+ * Scale down the value into the range 1 .. 2.
+ *
+ * If fractional numbers need to be processed, another loop needs
+ * to go here that checks v < scale and if so multiplies it by 2 and
+ * reduces r by scale. This also means making r signed.
+ */
+ while (v >= 2 * scale) {
+ v >>= 1;
+ r += scale;
+ }
+ for (i = scale / 2; i != 0; i /= 2) {
+ v = mul2(v, v);
+ if (v >= 2 * scale) {
+ v >>= 1;
+ r += i;
+ }
+ }
+ r = (r * (uint64_t)scale) / log_e;
+ return r;
+}
+
+/*
+ * NIST SP 800-56B rev 2 Appendix D: Maximum Security Strength Estimates for IFC
+ * Modulus Lengths.
+ *
+ * Note that this formula is also referred to in SP800-56A rev3 Appendix D:
+ * for FFC safe prime groups for modp and ffdhe.
+ * After Table 25 and Table 26 it refers to
+ * "The maximum security strength estimates were calculated using the formula in
+ * Section 7.5 of the FIPS 140 IG and rounded to the nearest multiple of eight
+ * bits".
+ *
+ * The formula is:
+ *
+ * E = \frac{1.923 \sqrt[3]{nBits \cdot log_e(2)}
+ * \cdot(log_e(nBits \cdot log_e(2))^{2/3} - 4.69}{log_e(2)}
+ * The two cube roots are merged together here.
+ */
+uint16_t ossl_ifc_ffc_compute_security_bits(int n)
+{
+ uint64_t x;
+ uint32_t lx;
+ uint16_t y, cap;
+
+ /*
+ * Look for common values as listed in standards.
+ * These values are not exactly equal to the results from the formulae in
+ * the standards but are defined to be canonical.
+ */
+ switch (n) {
+ case 2048: /* SP 800-56B rev 2 Appendix D and FIPS 140-2 IG 7.5 */
+ return 112;
+ case 3072: /* SP 800-56B rev 2 Appendix D and FIPS 140-2 IG 7.5 */
+ return 128;
+ case 4096: /* SP 800-56B rev 2 Appendix D */
+ return 152;
+ case 6144: /* SP 800-56B rev 2 Appendix D */
+ return 176;
+ case 7680: /* FIPS 140-2 IG 7.5 */
+ return 192;
+ case 8192: /* SP 800-56B rev 2 Appendix D */
+ return 200;
+ case 15360: /* FIPS 140-2 IG 7.5 */
+ return 256;
+ }
+
+ /*
+ * The first incorrect result (i.e. not accurate or off by one low) occurs
+ * for n = 699668. The true value here is 1200. Instead of using this n
+ * as the check threshold, the smallest n such that the correct result is
+ * 1200 is used instead.
+ */
+ if (n >= 687737)
+ return 1200;
+ if (n < 8)
+ return 0;
+
+ /*
+ * To ensure that the output is non-decreasing with respect to n,
+ * a cap needs to be applied to the two values where the function over
+ * estimates the strength (according to the above fast path).
+ */
+ if (n <= 7680)
+ cap = 192;
+ else if (n <= 15360)
+ cap = 256;
+ else
+ cap = 1200;
+
+ x = n * (uint64_t)log_2;
+ lx = ilog_e(x);
+ y = (uint16_t)((mul2(c1_923, icbrt64(mul2(mul2(x, lx), lx))) - c4_690)
+ / log_2);
+ y = (y + 4) & ~7;
+ if (y > cap)
+ y = cap;
+ return y;
+}
+
+
int RSA_security_bits(const RSA *rsa)
{
int bits = BN_num_bits(rsa->n);
+#ifndef FIPS_MODULE
if (rsa->version == RSA_ASN1_VERSION_MULTI) {
/* This ought to mean that we have private key at hand. */
int ex_primes = sk_RSA_PRIME_INFO_num(rsa->prime_infos);
- if (ex_primes <= 0 || (ex_primes + 2) > rsa_multip_cap(bits))
+ if (ex_primes <= 0 || (ex_primes + 2) > ossl_rsa_multip_cap(bits))
return 0;
}
- return BN_security_bits(bits, -1);
+#endif
+ return ossl_ifc_ffc_compute_security_bits(bits);
}
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
@@ -200,6 +412,7 @@ int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
r->d = d;
BN_set_flags(r->d, BN_FLG_CONSTTIME);
}
+ r->dirty_cnt++;
return 1;
}
@@ -223,6 +436,7 @@ int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
r->q = q;
BN_set_flags(r->q, BN_FLG_CONSTTIME);
}
+ r->dirty_cnt++;
return 1;
}
@@ -252,10 +466,12 @@ int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
r->iqmp = iqmp;
BN_set_flags(r->iqmp, BN_FLG_CONSTTIME);
}
+ r->dirty_cnt++;
return 1;
}
+#ifndef FIPS_MODULE
/*
* Is it better to export RSA_PRIME_INFO structure
* and related functions to let user pass a triplet?
@@ -278,7 +494,7 @@ int RSA_set0_multi_prime_params(RSA *r, BIGNUM *primes[], BIGNUM *exps[],
old = r->prime_infos;
for (i = 0; i < pnum; i++) {
- pinfo = rsa_multip_info_new();
+ pinfo = ossl_rsa_multip_info_new();
if (pinfo == NULL)
goto err;
if (primes[i] != NULL && exps[i] != NULL && coeffs[i] != NULL) {
@@ -292,7 +508,7 @@ int RSA_set0_multi_prime_params(RSA *r, BIGNUM *primes[], BIGNUM *exps[],
BN_set_flags(pinfo->d, BN_FLG_CONSTTIME);
BN_set_flags(pinfo->t, BN_FLG_CONSTTIME);
} else {
- rsa_multip_info_free(pinfo);
+ ossl_rsa_multip_info_free(pinfo);
goto err;
}
(void)sk_RSA_PRIME_INFO_push(prime_infos, pinfo);
@@ -300,7 +516,7 @@ int RSA_set0_multi_prime_params(RSA *r, BIGNUM *primes[], BIGNUM *exps[],
r->prime_infos = prime_infos;
- if (!rsa_multip_calc_product(r)) {
+ if (!ossl_rsa_multip_calc_product(r)) {
r->prime_infos = old;
goto err;
}
@@ -312,17 +528,19 @@ int RSA_set0_multi_prime_params(RSA *r, BIGNUM *primes[], BIGNUM *exps[],
* be freed in that case. So currently, stay consistent
* with other *set0* functions: just free it...
*/
- sk_RSA_PRIME_INFO_pop_free(old, rsa_multip_info_free);
+ sk_RSA_PRIME_INFO_pop_free(old, ossl_rsa_multip_info_free);
}
r->version = RSA_ASN1_VERSION_MULTI;
+ r->dirty_cnt++;
return 1;
err:
/* r, d, t should not be freed */
- sk_RSA_PRIME_INFO_pop_free(prime_infos, rsa_multip_info_free_ex);
+ sk_RSA_PRIME_INFO_pop_free(prime_infos, ossl_rsa_multip_info_free_ex);
return 0;
}
+#endif
void RSA_get0_key(const RSA *r,
const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
@@ -343,6 +561,7 @@ void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
*q = r->q;
}
+#ifndef FIPS_MODULE
int RSA_get_multi_prime_extra_count(const RSA *r)
{
int pnum;
@@ -372,6 +591,7 @@ int RSA_get0_multi_prime_factors(const RSA *r, const BIGNUM *primes[])
return 1;
}
+#endif
void RSA_get0_crt_params(const RSA *r,
const BIGNUM **dmp1, const BIGNUM **dmq1,
@@ -385,6 +605,7 @@ void RSA_get0_crt_params(const RSA *r,
*iqmp = r->iqmp;
}
+#ifndef FIPS_MODULE
int RSA_get0_multi_prime_crt_params(const RSA *r, const BIGNUM *exps[],
const BIGNUM *coeffs[])
{
@@ -410,6 +631,7 @@ int RSA_get0_multi_prime_crt_params(const RSA *r, const BIGNUM *exps[],
return 1;
}
+#endif
const BIGNUM *RSA_get0_n(const RSA *r)
{
@@ -453,7 +675,29 @@ const BIGNUM *RSA_get0_iqmp(const RSA *r)
const RSA_PSS_PARAMS *RSA_get0_pss_params(const RSA *r)
{
+#ifdef FIPS_MODULE
+ return NULL;
+#else
return r->pss;
+#endif
+}
+
+/* Internal */
+int ossl_rsa_set0_pss_params(RSA *r, RSA_PSS_PARAMS *pss)
+{
+#ifdef FIPS_MODULE
+ return 0;
+#else
+ RSA_PSS_PARAMS_free(r->pss);
+ r->pss = pss;
+ return 1;
+#endif
+}
+
+/* Internal */
+RSA_PSS_PARAMS_30 *ossl_rsa_get0_pss_params_30(RSA *r)
+{
+ return &r->pss_params;
}
void RSA_clear_flags(RSA *r, int flags)
@@ -477,6 +721,7 @@ int RSA_get_version(RSA *r)
return r->version;
}
+#ifndef FIPS_MODULE
ENGINE *RSA_get0_engine(const RSA *r)
{
return r->engine;
@@ -491,3 +736,547 @@ int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2)
return -1;
return EVP_PKEY_CTX_ctrl(ctx, -1, optype, cmd, p1, p2);
}
+#endif
+
+DEFINE_STACK_OF(BIGNUM)
+
+int ossl_rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes,
+ const STACK_OF(BIGNUM) *exps,
+ const STACK_OF(BIGNUM) *coeffs)
+{
+#ifndef FIPS_MODULE
+ STACK_OF(RSA_PRIME_INFO) *prime_infos, *old_infos = NULL;
+#endif
+ int pnum;
+
+ if (primes == NULL || exps == NULL || coeffs == NULL)
+ return 0;
+
+ pnum = sk_BIGNUM_num(primes);
+ if (pnum < 2
+ || pnum != sk_BIGNUM_num(exps)
+ || pnum != sk_BIGNUM_num(coeffs) + 1)
+ return 0;
+
+ if (!RSA_set0_factors(r, sk_BIGNUM_value(primes, 0),
+ sk_BIGNUM_value(primes, 1))
+ || !RSA_set0_crt_params(r, sk_BIGNUM_value(exps, 0),
+ sk_BIGNUM_value(exps, 1),
+ sk_BIGNUM_value(coeffs, 0)))
+ return 0;
+
+#ifndef FIPS_MODULE
+ old_infos = r->prime_infos;
+#endif
+
+ if (pnum > 2) {
+#ifndef FIPS_MODULE
+ int i;
+
+ prime_infos = sk_RSA_PRIME_INFO_new_reserve(NULL, pnum);
+ if (prime_infos == NULL)
+ return 0;
+
+ for (i = 2; i < pnum; i++) {
+ BIGNUM *prime = sk_BIGNUM_value(primes, i);
+ BIGNUM *exp = sk_BIGNUM_value(exps, i);
+ BIGNUM *coeff = sk_BIGNUM_value(coeffs, i - 1);
+ RSA_PRIME_INFO *pinfo = NULL;
+
+ if (!ossl_assert(prime != NULL && exp != NULL && coeff != NULL))
+ goto err;
+
+ /* Using ossl_rsa_multip_info_new() is wasteful, so allocate directly */
+ if ((pinfo = OPENSSL_zalloc(sizeof(*pinfo))) == NULL) {
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ pinfo->r = prime;
+ pinfo->d = exp;
+ pinfo->t = coeff;
+ BN_set_flags(pinfo->r, BN_FLG_CONSTTIME);
+ BN_set_flags(pinfo->d, BN_FLG_CONSTTIME);
+ BN_set_flags(pinfo->t, BN_FLG_CONSTTIME);
+ (void)sk_RSA_PRIME_INFO_push(prime_infos, pinfo);
+ }
+
+ r->prime_infos = prime_infos;
+
+ if (!ossl_rsa_multip_calc_product(r)) {
+ r->prime_infos = old_infos;
+ goto err;
+ }
+#else
+ return 0;
+#endif
+ }
+
+#ifndef FIPS_MODULE
+ if (old_infos != NULL) {
+ /*
+ * This is hard to deal with, since the old infos could
+ * also be set by this function and r, d, t should not
+ * be freed in that case. So currently, stay consistent
+ * with other *set0* functions: just free it...
+ */
+ sk_RSA_PRIME_INFO_pop_free(old_infos, ossl_rsa_multip_info_free);
+ }
+#endif
+
+ r->version = pnum > 2 ? RSA_ASN1_VERSION_MULTI : RSA_ASN1_VERSION_DEFAULT;
+ r->dirty_cnt++;
+
+ return 1;
+#ifndef FIPS_MODULE
+ err:
+ /* r, d, t should not be freed */
+ sk_RSA_PRIME_INFO_pop_free(prime_infos, ossl_rsa_multip_info_free_ex);
+ return 0;
+#endif
+}
+
+DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
+
+int ossl_rsa_get0_all_params(RSA *r, STACK_OF(BIGNUM_const) *primes,
+ STACK_OF(BIGNUM_const) *exps,
+ STACK_OF(BIGNUM_const) *coeffs)
+{
+#ifndef FIPS_MODULE
+ RSA_PRIME_INFO *pinfo;
+ int i, pnum;
+#endif
+
+ if (r == NULL)
+ return 0;
+
+ /* If |p| is NULL, there are no CRT parameters */
+ if (RSA_get0_p(r) == NULL)
+ return 1;
+
+ sk_BIGNUM_const_push(primes, RSA_get0_p(r));
+ sk_BIGNUM_const_push(primes, RSA_get0_q(r));
+ sk_BIGNUM_const_push(exps, RSA_get0_dmp1(r));
+ sk_BIGNUM_const_push(exps, RSA_get0_dmq1(r));
+ sk_BIGNUM_const_push(coeffs, RSA_get0_iqmp(r));
+
+#ifndef FIPS_MODULE
+ pnum = RSA_get_multi_prime_extra_count(r);
+ for (i = 0; i < pnum; i++) {
+ pinfo = sk_RSA_PRIME_INFO_value(r->prime_infos, i);
+ sk_BIGNUM_const_push(primes, pinfo->r);
+ sk_BIGNUM_const_push(exps, pinfo->d);
+ sk_BIGNUM_const_push(coeffs, pinfo->t);
+ }
+#endif
+
+ return 1;
+}
+
+#ifndef FIPS_MODULE
+/* Helpers to set or get diverse hash algorithm names */
+static int int_set_rsa_md_name(EVP_PKEY_CTX *ctx,
+ /* For checks */
+ int keytype, int optype,
+ /* For EVP_PKEY_CTX_set_params() */
+ const char *mdkey, const char *mdname,
+ const char *propkey, const char *mdprops)
+{
+ OSSL_PARAM params[3], *p = params;
+
+ if (ctx == NULL || mdname == NULL || (ctx->operation & optype) == 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+
+ /* If key type not RSA return error */
+ switch (keytype) {
+ case -1:
+ if (!EVP_PKEY_CTX_is_a(ctx, "RSA")
+ && !EVP_PKEY_CTX_is_a(ctx, "RSA-PSS"))
+ return -1;
+ break;
+ default:
+ if (!EVP_PKEY_CTX_is_a(ctx, evp_pkey_type2name(keytype)))
+ return -1;
+ break;
+ }
+
+ /* Cast away the const. This is read only so should be safe */
+ *p++ = OSSL_PARAM_construct_utf8_string(mdkey, (char *)mdname, 0);
+ if (evp_pkey_ctx_is_provided(ctx) && mdprops != NULL) {
+ /* Cast away the const. This is read only so should be safe */
+ *p++ = OSSL_PARAM_construct_utf8_string(propkey, (char *)mdprops, 0);
+ }
+ *p++ = OSSL_PARAM_construct_end();
+
+ return evp_pkey_ctx_set_params_strict(ctx, params);
+}
+
+/* Helpers to set or get diverse hash algorithm names */
+static int int_get_rsa_md_name(EVP_PKEY_CTX *ctx,
+ /* For checks */
+ int keytype, int optype,
+ /* For EVP_PKEY_CTX_get_params() */
+ const char *mdkey,
+ char *mdname, size_t mdnamesize)
+{
+ OSSL_PARAM params[2], *p = params;
+
+ if (ctx == NULL || mdname == NULL || (ctx->operation & optype) == 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+
+ /* If key type not RSA return error */
+ switch (keytype) {
+ case -1:
+ if (!EVP_PKEY_CTX_is_a(ctx, "RSA")
+ && !EVP_PKEY_CTX_is_a(ctx, "RSA-PSS"))
+ return -1;
+ break;
+ default:
+ if (!EVP_PKEY_CTX_is_a(ctx, evp_pkey_type2name(keytype)))
+ return -1;
+ break;
+ }
+
+ /* Cast away the const. This is read only so should be safe */
+ *p++ = OSSL_PARAM_construct_utf8_string(mdkey, (char *)mdname, mdnamesize);
+ *p++ = OSSL_PARAM_construct_end();
+
+ return evp_pkey_ctx_get_params_strict(ctx, params);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad_mode)
+{
+ return RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_RSA_PADDING,
+ pad_mode, NULL);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad_mode)
+{
+ return RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_GET_RSA_PADDING,
+ 0, pad_mode);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_set_rsa_pss_keygen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_MD, 0, (void *)(md));
+}
+
+int EVP_PKEY_CTX_set_rsa_pss_keygen_md_name(EVP_PKEY_CTX *ctx,
+ const char *mdname,
+ const char *mdprops)
+{
+ return int_set_rsa_md_name(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN,
+ OSSL_PKEY_PARAM_RSA_DIGEST, mdname,
+ OSSL_PKEY_PARAM_RSA_DIGEST_PROPS, mdprops);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_RSA_OAEP_MD, 0, (void *)(md));
+}
+
+int EVP_PKEY_CTX_set_rsa_oaep_md_name(EVP_PKEY_CTX *ctx, const char *mdname,
+ const char *mdprops)
+{
+ return
+ int_set_rsa_md_name(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
+ OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, mdname,
+ OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS, mdprops);
+}
+
+int EVP_PKEY_CTX_get_rsa_oaep_md_name(EVP_PKEY_CTX *ctx, char *name,
+ size_t namesize)
+{
+ return int_get_rsa_md_name(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
+ OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST,
+ name, namesize);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD **md)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_GET_RSA_OAEP_MD, 0, (void *)md);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
+{
+ return RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)(md));
+}
+
+int EVP_PKEY_CTX_set_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, const char *mdname,
+ const char *mdprops)
+{
+ return int_set_rsa_md_name(ctx, -1,
+ EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_TYPE_SIG,
+ OSSL_PKEY_PARAM_MGF1_DIGEST, mdname,
+ OSSL_PKEY_PARAM_MGF1_PROPERTIES, mdprops);
+}
+
+int EVP_PKEY_CTX_get_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, char *name,
+ size_t namesize)
+{
+ return int_get_rsa_md_name(ctx, -1,
+ EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_TYPE_SIG,
+ OSSL_PKEY_PARAM_MGF1_DIGEST, name, namesize);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
+{
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)(md));
+}
+
+int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md_name(EVP_PKEY_CTX *ctx,
+ const char *mdname)
+{
+ return int_set_rsa_md_name(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN,
+ OSSL_PKEY_PARAM_MGF1_DIGEST, mdname,
+ NULL, NULL);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **md)
+{
+ return RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void *)(md));
+}
+
+int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, void *label, int llen)
+{
+ OSSL_PARAM rsa_params[2], *p = rsa_params;
+ int ret;
+
+ if (ctx == NULL || !EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+
+ /* If key type not RSA return error */
+ if (!EVP_PKEY_CTX_is_a(ctx, "RSA"))
+ return -1;
+
+ /* Cast away the const. This is read only so should be safe */
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL,
+ (void *)label, (size_t)llen);
+ *p++ = OSSL_PARAM_construct_end();
+
+ ret = evp_pkey_ctx_set_params_strict(ctx, rsa_params);
+ if (ret <= 0)
+ return ret;
+
+ /* Ownership is supposed to be transfered to the callee. */
+ OPENSSL_free(label);
+ return 1;
+}
+
+int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char **label)
+{
+ OSSL_PARAM rsa_params[2], *p = rsa_params;
+ size_t labellen;
+
+ if (ctx == NULL || !EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+
+ /* If key type not RSA return error */
+ if (!EVP_PKEY_CTX_is_a(ctx, "RSA"))
+ return -1;
+
+ *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL,
+ (void **)label, 0);
+ *p++ = OSSL_PARAM_construct_end();
+
+ if (!EVP_PKEY_CTX_get_params(ctx, rsa_params))
+ return -1;
+
+ labellen = rsa_params[0].return_size;
+ if (labellen > INT_MAX)
+ return -1;
+
+ return (int)labellen;
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int saltlen)
+{
+ /*
+ * For some reason, the optype was set to this:
+ *
+ * EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY
+ *
+ * However, we do use RSA-PSS with the whole gamut of diverse signature
+ * and verification operations, so the optype gets upgraded to this:
+ *
+ * EVP_PKEY_OP_TYPE_SIG
+ */
+ return RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG,
+ EVP_PKEY_CTRL_RSA_PSS_SALTLEN, saltlen, NULL);
+}
+
+/*
+ * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
+ * simply because that's easier.
+ */
+int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen)
+{
+ /*
+ * Because of circumstances, the optype is updated from:
+ *
+ * EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY
+ *
+ * to:
+ *
+ * EVP_PKEY_OP_TYPE_SIG
+ */
+ return RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG,
+ EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, 0, saltlen);
+}
+
+int EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(EVP_PKEY_CTX *ctx, int saltlen)
+{
+ OSSL_PARAM pad_params[2], *p = pad_params;
+
+ if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+
+ if (!EVP_PKEY_CTX_is_a(ctx, "RSA-PSS"))
+ return -1;
+
+ *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_PSS_SALTLEN,
+ &saltlen);
+ *p++ = OSSL_PARAM_construct_end();
+
+ return evp_pkey_ctx_set_params_strict(ctx, pad_params);
+}
+
+int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int bits)
+{
+ OSSL_PARAM params[2], *p = params;
+ size_t bits2 = bits;
+
+ if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+
+ /* If key type not RSA return error */
+ if (!EVP_PKEY_CTX_is_a(ctx, "RSA")
+ && !EVP_PKEY_CTX_is_a(ctx, "RSA-PSS"))
+ return -1;
+
+ *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_RSA_BITS, &bits2);
+ *p++ = OSSL_PARAM_construct_end();
+
+ return evp_pkey_ctx_set_params_strict(ctx, params);
+}
+
+int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp)
+{
+ int ret = RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp);
+
+ /*
+ * Satisfy memory semantics for pre-3.0 callers of
+ * EVP_PKEY_CTX_set_rsa_keygen_pubexp(): their expectation is that input
+ * pubexp BIGNUM becomes managed by the EVP_PKEY_CTX on success.
+ */
+ if (ret > 0 && evp_pkey_ctx_is_provided(ctx)) {
+ BN_free(ctx->rsa_pubexp);
+ ctx->rsa_pubexp = pubexp;
+ }
+
+ return ret;
+}
+
+int EVP_PKEY_CTX_set1_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp)
+{
+ int ret = 0;
+
+ /*
+ * When we're dealing with a provider, there's no need to duplicate
+ * pubexp, as it gets copied when transforming to an OSSL_PARAM anyway.
+ */
+ if (evp_pkey_ctx_is_legacy(ctx)) {
+ pubexp = BN_dup(pubexp);
+ if (pubexp == NULL)
+ return 0;
+ }
+ ret = EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp);
+ if (evp_pkey_ctx_is_legacy(ctx) && ret <= 0)
+ BN_free(pubexp);
+ return ret;
+}
+
+int EVP_PKEY_CTX_set_rsa_keygen_primes(EVP_PKEY_CTX *ctx, int primes)
+{
+ OSSL_PARAM params[2], *p = params;
+ size_t primes2 = primes;
+
+ if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+ return -2;
+ }
+
+ /* If key type not RSA return error */
+ if (!EVP_PKEY_CTX_is_a(ctx, "RSA")
+ && !EVP_PKEY_CTX_is_a(ctx, "RSA-PSS"))
+ return -1;
+
+ *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_RSA_PRIMES, &primes2);
+ *p++ = OSSL_PARAM_construct_end();
+
+ return evp_pkey_ctx_set_params_strict(ctx, params);
+}
+#endif
diff --git a/crypto/rsa/rsa_local.h b/crypto/rsa/rsa_local.h
index 2b94462a94c6..ea70da05ad78 100644
--- a/crypto/rsa/rsa_local.h
+++ b/crypto/rsa/rsa_local.h
@@ -1,17 +1,19 @@
/*
- * Copyright 2006-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/rsa.h>
+#ifndef OSSL_CRYPTO_RSA_LOCAL_H
+#define OSSL_CRYPTO_RSA_LOCAL_H
+
#include "internal/refcount.h"
+#include "crypto/rsa.h"
#define RSA_MAX_PRIME_NUM 5
-#define RSA_MIN_MODULUS_BITS 512
typedef struct rsa_prime_info_st {
BIGNUM *r;
@@ -25,12 +27,34 @@ typedef struct rsa_prime_info_st {
DECLARE_ASN1_ITEM(RSA_PRIME_INFO)
DEFINE_STACK_OF(RSA_PRIME_INFO)
+#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+struct rsa_acvp_test_st {
+ /* optional inputs */
+ BIGNUM *Xp1;
+ BIGNUM *Xp2;
+ BIGNUM *Xq1;
+ BIGNUM *Xq2;
+ BIGNUM *Xp;
+ BIGNUM *Xq;
+
+ /* optional outputs */
+ BIGNUM *p1;
+ BIGNUM *p2;
+ BIGNUM *q1;
+ BIGNUM *q2;
+};
+#endif
+
struct rsa_st {
/*
- * The first parameter is used to pickup errors where this is passed
- * instead of an EVP_PKEY, it is set to 0
+ * #legacy
+ * The first field is used to pickup errors where this is passed
+ * instead of an EVP_PKEY. It is always zero.
+ * THIS MUST REMAIN THE FIRST FIELD.
*/
- int pad;
+ int dummy_zero;
+
+ OSSL_LIB_CTX *libctx;
int32_t version;
const RSA_METHOD *meth;
/* functional reference if 'meth' is ENGINE-provided */
@@ -43,26 +67,37 @@ struct rsa_st {
BIGNUM *dmp1;
BIGNUM *dmq1;
BIGNUM *iqmp;
+
+ /*
+ * If a PSS only key this contains the parameter restrictions.
+ * There are two structures for the same thing, used in different cases.
+ */
+ /* This is used uniquely by OpenSSL provider implementations. */
+ RSA_PSS_PARAMS_30 pss_params;
+
+#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+ RSA_ACVP_TEST *acvp_test;
+#endif
+
+#ifndef FIPS_MODULE
+ /* This is used uniquely by rsa_ameth.c and rsa_pmeth.c. */
+ RSA_PSS_PARAMS *pss;
/* for multi-prime RSA, defined in RFC 8017 */
STACK_OF(RSA_PRIME_INFO) *prime_infos;
- /* If a PSS only key this contains the parameter restrictions */
- RSA_PSS_PARAMS *pss;
- /* be careful using this if the RSA structure is shared */
+ /* Be careful using this if the RSA structure is shared */
CRYPTO_EX_DATA ex_data;
+#endif
CRYPTO_REF_COUNT references;
int flags;
/* Used to cache montgomery values */
BN_MONT_CTX *_method_mod_n;
BN_MONT_CTX *_method_mod_p;
BN_MONT_CTX *_method_mod_q;
- /*
- * all BIGNUM values are actually in the following data, if it is not
- * NULL
- */
- char *bignum_data;
BN_BLINDING *blinding;
BN_BLINDING *mt_blinding;
CRYPTO_RWLOCK *lock;
+
+ int dirty_cnt;
};
struct rsa_meth_st {
@@ -92,7 +127,7 @@ struct rsa_meth_st {
* New sign and verify functions: some libraries don't allow arbitrary
* data to be signed/verified: this allows them to be used. Note: for
* this to work the RSA_public_decrypt() and RSA_private_encrypt() should
- * *NOT* be used RSA_sign(), RSA_verify() should be used instead.
+ * *NOT* be used. RSA_sign(), RSA_verify() should be used instead.
*/
int (*rsa_sign) (int type,
const unsigned char *m, unsigned int m_length,
@@ -112,21 +147,50 @@ struct rsa_meth_st {
BIGNUM *e, BN_GENCB *cb);
};
-extern int int_rsa_verify(int dtype, const unsigned char *m,
- unsigned int m_len, unsigned char *rm,
- size_t *prm_len, const unsigned char *sigbuf,
- size_t siglen, RSA *rsa);
/* Macros to test if a pkey or ctx is for a PSS key */
#define pkey_is_pss(pkey) (pkey->ameth->pkey_id == EVP_PKEY_RSA_PSS)
#define pkey_ctx_is_pss(ctx) (ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS)
-RSA_PSS_PARAMS *rsa_pss_params_create(const EVP_MD *sigmd,
- const EVP_MD *mgf1md, int saltlen);
-int rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
- const EVP_MD **pmgf1md, int *psaltlen);
+RSA_PSS_PARAMS *ossl_rsa_pss_params_create(const EVP_MD *sigmd,
+ const EVP_MD *mgf1md, int saltlen);
+int ossl_rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
+ const EVP_MD **pmgf1md, int *psaltlen);
/* internal function to clear and free multi-prime parameters */
-void rsa_multip_info_free_ex(RSA_PRIME_INFO *pinfo);
-void rsa_multip_info_free(RSA_PRIME_INFO *pinfo);
-RSA_PRIME_INFO *rsa_multip_info_new(void);
-int rsa_multip_calc_product(RSA *rsa);
-int rsa_multip_cap(int bits);
+void ossl_rsa_multip_info_free_ex(RSA_PRIME_INFO *pinfo);
+void ossl_rsa_multip_info_free(RSA_PRIME_INFO *pinfo);
+RSA_PRIME_INFO *ossl_rsa_multip_info_new(void);
+int ossl_rsa_multip_calc_product(RSA *rsa);
+int ossl_rsa_multip_cap(int bits);
+
+int ossl_rsa_sp800_56b_validate_strength(int nbits, int strength);
+int ossl_rsa_check_pminusq_diff(BIGNUM *diff, const BIGNUM *p, const BIGNUM *q,
+ int nbits);
+int ossl_rsa_get_lcm(BN_CTX *ctx, const BIGNUM *p, const BIGNUM *q,
+ BIGNUM *lcm, BIGNUM *gcd, BIGNUM *p1, BIGNUM *q1,
+ BIGNUM *p1q1);
+
+int ossl_rsa_check_public_exponent(const BIGNUM *e);
+int ossl_rsa_check_private_exponent(const RSA *rsa, int nbits, BN_CTX *ctx);
+int ossl_rsa_check_prime_factor(BIGNUM *p, BIGNUM *e, int nbits, BN_CTX *ctx);
+int ossl_rsa_check_prime_factor_range(const BIGNUM *p, int nbits, BN_CTX *ctx);
+int ossl_rsa_check_crt_components(const RSA *rsa, BN_CTX *ctx);
+
+int ossl_rsa_sp800_56b_pairwise_test(RSA *rsa, BN_CTX *ctx);
+int ossl_rsa_sp800_56b_check_public(const RSA *rsa);
+int ossl_rsa_sp800_56b_check_private(const RSA *rsa);
+int ossl_rsa_sp800_56b_check_keypair(const RSA *rsa, const BIGNUM *efixed,
+ int strength, int nbits);
+int ossl_rsa_sp800_56b_generate_key(RSA *rsa, int nbits, const BIGNUM *efixed,
+ BN_GENCB *cb);
+
+int ossl_rsa_sp800_56b_derive_params_from_pq(RSA *rsa, int nbits,
+ const BIGNUM *e, BN_CTX *ctx);
+int ossl_rsa_fips186_4_gen_prob_primes(RSA *rsa, RSA_ACVP_TEST *test,
+ int nbits, const BIGNUM *e, BN_CTX *ctx,
+ BN_GENCB *cb);
+
+int ossl_rsa_padding_add_PKCS1_type_2_ex(OSSL_LIB_CTX *libctx, unsigned char *to,
+ int tlen, const unsigned char *from,
+ int flen);
+
+#endif /* OSSL_CRYPTO_RSA_LOCAL_H */
diff --git a/crypto/rsa/rsa_meth.c b/crypto/rsa/rsa_meth.c
index 2845b79db8ef..82f13bb35976 100644
--- a/crypto/rsa/rsa_meth.c
+++ b/crypto/rsa/rsa_meth.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <string.h>
#include "rsa_local.h"
#include <openssl/err.h>
@@ -25,7 +31,7 @@ RSA_METHOD *RSA_meth_new(const char *name, int flags)
OPENSSL_free(meth);
}
- RSAerr(RSA_F_RSA_METH_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -51,7 +57,7 @@ RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth)
OPENSSL_free(ret);
}
- RSAerr(RSA_F_RSA_METH_DUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -65,7 +71,7 @@ int RSA_meth_set1_name(RSA_METHOD *meth, const char *name)
char *tmpname = OPENSSL_strdup(name);
if (tmpname == NULL) {
- RSAerr(RSA_F_RSA_METH_SET1_NAME, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
return 0;
}
diff --git a/crypto/rsa/rsa_mp.c b/crypto/rsa/rsa_mp.c
index 44dda8f800bc..f827c0a2f8fd 100644
--- a/crypto/rsa/rsa_mp.c
+++ b/crypto/rsa/rsa_mp.c
@@ -1,8 +1,8 @@
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2017 BaishanCloud. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,29 +12,29 @@
#include <openssl/err.h>
#include "rsa_local.h"
-void rsa_multip_info_free_ex(RSA_PRIME_INFO *pinfo)
+void ossl_rsa_multip_info_free_ex(RSA_PRIME_INFO *pinfo)
{
/* free pp and pinfo only */
BN_clear_free(pinfo->pp);
OPENSSL_free(pinfo);
}
-void rsa_multip_info_free(RSA_PRIME_INFO *pinfo)
+void ossl_rsa_multip_info_free(RSA_PRIME_INFO *pinfo)
{
- /* free a RSA_PRIME_INFO structure */
+ /* free an RSA_PRIME_INFO structure */
BN_clear_free(pinfo->r);
BN_clear_free(pinfo->d);
BN_clear_free(pinfo->t);
- rsa_multip_info_free_ex(pinfo);
+ ossl_rsa_multip_info_free_ex(pinfo);
}
-RSA_PRIME_INFO *rsa_multip_info_new(void)
+RSA_PRIME_INFO *ossl_rsa_multip_info_new(void)
{
RSA_PRIME_INFO *pinfo;
- /* create a RSA_PRIME_INFO structure */
+ /* create an RSA_PRIME_INFO structure */
if ((pinfo = OPENSSL_zalloc(sizeof(RSA_PRIME_INFO))) == NULL) {
- RSAerr(RSA_F_RSA_MULTIP_INFO_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
return NULL;
}
if ((pinfo->r = BN_secure_new()) == NULL)
@@ -58,7 +58,7 @@ RSA_PRIME_INFO *rsa_multip_info_new(void)
}
/* Refill products of primes */
-int rsa_multip_calc_product(RSA *rsa)
+int ossl_rsa_multip_calc_product(RSA *rsa)
{
RSA_PRIME_INFO *pinfo;
BIGNUM *p1 = NULL, *p2 = NULL;
@@ -97,7 +97,7 @@ int rsa_multip_calc_product(RSA *rsa)
return rv;
}
-int rsa_multip_cap(int bits)
+int ossl_rsa_multip_cap(int bits)
{
int cap = 5;
diff --git a/crypto/rsa/rsa_mp_names.c b/crypto/rsa/rsa_mp_names.c
new file mode 100644
index 000000000000..8291b79e7afd
--- /dev/null
+++ b/crypto/rsa/rsa_mp_names.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_names.h>
+#include "crypto/rsa.h"
+
+/*
+ * The following tables are constants used during RSA parameter building
+ * operations. It is easier to point to one of these fixed strings than have
+ * to dynamically add and generate the names on the fly.
+ */
+
+/*
+ * A fixed table of names for the RSA prime factors starting with
+ * P,Q and up to 8 additional primes.
+ */
+const char *ossl_rsa_mp_factor_names[] = {
+ OSSL_PKEY_PARAM_RSA_FACTOR1,
+ OSSL_PKEY_PARAM_RSA_FACTOR2,
+#ifndef FIPS_MODULE
+ OSSL_PKEY_PARAM_RSA_FACTOR3,
+ OSSL_PKEY_PARAM_RSA_FACTOR4,
+ OSSL_PKEY_PARAM_RSA_FACTOR5,
+ OSSL_PKEY_PARAM_RSA_FACTOR6,
+ OSSL_PKEY_PARAM_RSA_FACTOR7,
+ OSSL_PKEY_PARAM_RSA_FACTOR8,
+ OSSL_PKEY_PARAM_RSA_FACTOR9,
+ OSSL_PKEY_PARAM_RSA_FACTOR10,
+#endif
+ NULL
+};
+
+/*
+ * A fixed table of names for the RSA exponents starting with
+ * DP,DQ and up to 8 additional exponents.
+ */
+const char *ossl_rsa_mp_exp_names[] = {
+ OSSL_PKEY_PARAM_RSA_EXPONENT1,
+ OSSL_PKEY_PARAM_RSA_EXPONENT2,
+#ifndef FIPS_MODULE
+ OSSL_PKEY_PARAM_RSA_EXPONENT3,
+ OSSL_PKEY_PARAM_RSA_EXPONENT4,
+ OSSL_PKEY_PARAM_RSA_EXPONENT5,
+ OSSL_PKEY_PARAM_RSA_EXPONENT6,
+ OSSL_PKEY_PARAM_RSA_EXPONENT7,
+ OSSL_PKEY_PARAM_RSA_EXPONENT8,
+ OSSL_PKEY_PARAM_RSA_EXPONENT9,
+ OSSL_PKEY_PARAM_RSA_EXPONENT10,
+#endif
+ NULL
+};
+
+/*
+ * A fixed table of names for the RSA coefficients starting with
+ * QINV and up to 8 additional exponents.
+ */
+const char *ossl_rsa_mp_coeff_names[] = {
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT1,
+#ifndef FIPS_MODULE
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT2,
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT3,
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT4,
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT5,
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT6,
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT7,
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT8,
+ OSSL_PKEY_PARAM_RSA_COEFFICIENT9,
+#endif
+ NULL
+};
diff --git a/crypto/rsa/rsa_none.c b/crypto/rsa/rsa_none.c
index f16cc67066d7..df93525fc5b8 100644
--- a/crypto/rsa/rsa_none.c
+++ b/crypto/rsa/rsa_none.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <openssl/rsa.h>
@@ -15,12 +21,12 @@ int RSA_padding_add_none(unsigned char *to, int tlen,
const unsigned char *from, int flen)
{
if (flen > tlen) {
- RSAerr(RSA_F_RSA_PADDING_ADD_NONE, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return 0;
}
if (flen < tlen) {
- RSAerr(RSA_F_RSA_PADDING_ADD_NONE, RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE);
return 0;
}
@@ -33,7 +39,7 @@ int RSA_padding_check_none(unsigned char *to, int tlen,
{
if (flen > tlen) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_NONE, RSA_R_DATA_TOO_LARGE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE);
return -1;
}
diff --git a/crypto/rsa/rsa_oaep.c b/crypto/rsa/rsa_oaep.c
index 302360a96415..d9be1a4f98c7 100644
--- a/crypto/rsa/rsa_oaep.c
+++ b/crypto/rsa/rsa_oaep.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -20,6 +20,12 @@
* one-wayness. For the RSA function, this is an equivalent notion.
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include "internal/constant_time.h"
#include <stdio.h>
@@ -34,14 +40,23 @@ int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
const unsigned char *from, int flen,
const unsigned char *param, int plen)
{
- return RSA_padding_add_PKCS1_OAEP_mgf1(to, tlen, from, flen,
- param, plen, NULL, NULL);
+ return ossl_rsa_padding_add_PKCS1_OAEP_mgf1_ex(NULL, to, tlen, from, flen,
+ param, plen, NULL, NULL);
}
-int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
- const unsigned char *from, int flen,
- const unsigned char *param, int plen,
- const EVP_MD *md, const EVP_MD *mgf1md)
+/*
+ * Perform the padding as per NIST 800-56B 7.2.2.3
+ * from (K) is the key material.
+ * param (A) is the additional input.
+ * Step numbers are included here but not in the constant time inverse below
+ * to avoid complicating an already difficult enough function.
+ */
+int ossl_rsa_padding_add_PKCS1_OAEP_mgf1_ex(OSSL_LIB_CTX *libctx,
+ unsigned char *to, int tlen,
+ const unsigned char *from, int flen,
+ const unsigned char *param,
+ int plen, const EVP_MD *md,
+ const EVP_MD *mgf1md)
{
int rv = 0;
int i, emlen = tlen - 1;
@@ -50,51 +65,69 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
unsigned char seedmask[EVP_MAX_MD_SIZE];
int mdlen, dbmask_len = 0;
- if (md == NULL)
+ if (md == NULL) {
+#ifndef FIPS_MODULE
md = EVP_sha1();
+#else
+ ERR_raise(ERR_LIB_RSA, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+#endif
+ }
if (mgf1md == NULL)
mgf1md = md;
- mdlen = EVP_MD_size(md);
+ mdlen = EVP_MD_get_size(md);
+ if (mdlen <= 0) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_LENGTH);
+ return 0;
+ }
+ /* step 2b: check KLen > nLen - 2 HLen - 2 */
if (flen > emlen - 2 * mdlen - 1) {
- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1,
- RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return 0;
}
if (emlen < 2 * mdlen + 1) {
- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1,
- RSA_R_KEY_SIZE_TOO_SMALL);
+ ERR_raise(ERR_LIB_RSA, RSA_R_KEY_SIZE_TOO_SMALL);
return 0;
}
+ /* step 3i: EM = 00000000 || maskedMGF || maskedDB */
to[0] = 0;
seed = to + 1;
db = to + mdlen + 1;
+ /* step 3a: hash the additional input */
if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL))
goto err;
+ /* step 3b: zero bytes array of length nLen - KLen - 2 HLen -2 */
memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1);
+ /* step 3c: DB = HA || PS || 00000001 || K */
db[emlen - flen - mdlen - 1] = 0x01;
memcpy(db + emlen - flen - mdlen, from, (unsigned int)flen);
- if (RAND_bytes(seed, mdlen) <= 0)
+ /* step 3d: generate random byte string */
+ if (RAND_bytes_ex(libctx, seed, mdlen, 0) <= 0)
goto err;
dbmask_len = emlen - mdlen;
dbmask = OPENSSL_malloc(dbmask_len);
if (dbmask == NULL) {
- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
+ /* step 3e: dbMask = MGF(mgfSeed, nLen - HLen - 1) */
if (PKCS1_MGF1(dbmask, dbmask_len, seed, mdlen, mgf1md) < 0)
goto err;
+ /* step 3f: maskedDB = DB XOR dbMask */
for (i = 0; i < dbmask_len; i++)
db[i] ^= dbmask[i];
+ /* step 3g: mgfSeed = MGF(maskedDB, HLen) */
if (PKCS1_MGF1(seedmask, mdlen, db, dbmask_len, mgf1md) < 0)
goto err;
+ /* stepo 3h: maskedMGFSeed = mgfSeed XOR mgfSeedMask */
for (i = 0; i < mdlen; i++)
seed[i] ^= seedmask[i];
rv = 1;
@@ -105,6 +138,15 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
return rv;
}
+int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
+ const unsigned char *from, int flen,
+ const unsigned char *param, int plen,
+ const EVP_MD *md, const EVP_MD *mgf1md)
+{
+ return ossl_rsa_padding_add_PKCS1_OAEP_mgf1_ex(NULL, to, tlen, from, flen,
+ param, plen, md, mgf1md);
+}
+
int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
const unsigned char *from, int flen, int num,
const unsigned char *param, int plen)
@@ -130,12 +172,19 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
phash[EVP_MAX_MD_SIZE];
int mdlen;
- if (md == NULL)
+ if (md == NULL) {
+#ifndef FIPS_MODULE
md = EVP_sha1();
+#else
+ ERR_raise(ERR_LIB_RSA, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+#endif
+ }
+
if (mgf1md == NULL)
mgf1md = md;
- mdlen = EVP_MD_size(md);
+ mdlen = EVP_MD_get_size(md);
if (tlen <= 0 || flen <= 0)
return -1;
@@ -148,22 +197,20 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
* This does not leak any side-channel information.
*/
if (num < flen || num < 2 * mdlen + 2) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1,
- RSA_R_OAEP_DECODING_ERROR);
+ ERR_raise(ERR_LIB_RSA, RSA_R_OAEP_DECODING_ERROR);
return -1;
}
dblen = num - mdlen - 1;
db = OPENSSL_malloc(dblen);
if (db == NULL) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto cleanup;
}
em = OPENSSL_malloc(num);
if (em == NULL) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto cleanup;
}
@@ -255,13 +302,18 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
to[i] = constant_time_select_8(mask, db[i + mdlen + 1], to[i]);
}
+#ifndef FIPS_MODULE
/*
* To avoid chosen ciphertext attacks, the error message should not
* reveal which kind of decoding error happened.
+ *
+ * This trick doesn't work in the FIPS provider because libcrypto manages
+ * the error stack. Instead we opt not to put an error on the stack at all
+ * in case of padding failure in the FIPS provider.
*/
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1,
- RSA_R_OAEP_DECODING_ERROR);
+ ERR_raise(ERR_LIB_RSA, RSA_R_OAEP_DECODING_ERROR);
err_clear_last_constant_time(1 & good);
+#endif
cleanup:
OPENSSL_cleanse(seed, sizeof(seed));
OPENSSL_clear_free(db, dblen);
@@ -270,6 +322,13 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
return constant_time_select_int(good, mlen, -1);
}
+/*
+ * Mask Generation Function corresponding to section 7.2.2.2 of NIST SP 800-56B.
+ * The variables are named differently to NIST:
+ * mask (T) and len (maskLen)are the returned mask.
+ * seed (mgfSeed).
+ * The range checking steps inm the process are performed outside.
+ */
int PKCS1_MGF1(unsigned char *mask, long len,
const unsigned char *seed, long seedlen, const EVP_MD *dgst)
{
@@ -282,14 +341,17 @@ int PKCS1_MGF1(unsigned char *mask, long len,
if (c == NULL)
goto err;
- mdlen = EVP_MD_size(dgst);
+ mdlen = EVP_MD_get_size(dgst);
if (mdlen < 0)
goto err;
+ /* step 4 */
for (i = 0; outlen < len; i++) {
+ /* step 4a: D = I2BS(counter, 4) */
cnt[0] = (unsigned char)((i >> 24) & 255);
cnt[1] = (unsigned char)((i >> 16) & 255);
cnt[2] = (unsigned char)((i >> 8)) & 255;
cnt[3] = (unsigned char)(i & 255);
+ /* step 4b: T =T || hash(mgfSeed || D) */
if (!EVP_DigestInit_ex(c, dgst, NULL)
|| !EVP_DigestUpdate(c, seed, seedlen)
|| !EVP_DigestUpdate(c, cnt, 4))
diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c
index 2e3ee4ab33dc..96fed3ca597c 100644
--- a/crypto/rsa/rsa_ossl.c
+++ b/crypto/rsa/rsa_ossl.c
@@ -1,12 +1,18 @@
/*
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include "internal/cryptlib.h"
#include "crypto/bn.h"
#include "rsa_local.h"
@@ -74,24 +80,24 @@ static int rsa_ossl_public_encrypt(int flen, const unsigned char *from,
BN_CTX *ctx = NULL;
if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
- RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_MODULUS_TOO_LARGE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_MODULUS_TOO_LARGE);
return -1;
}
if (BN_ucmp(rsa->n, rsa->e) <= 0) {
- RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE);
return -1;
}
/* for large moduli, enforce exponent limit */
if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) {
if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
- RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE);
return -1;
}
}
- if ((ctx = BN_CTX_new()) == NULL)
+ if ((ctx = BN_CTX_new_ex(rsa->libctx)) == NULL)
goto err;
BN_CTX_start(ctx);
f = BN_CTX_get(ctx);
@@ -99,25 +105,25 @@ static int rsa_ossl_public_encrypt(int flen, const unsigned char *from,
num = BN_num_bytes(rsa->n);
buf = OPENSSL_malloc(num);
if (ret == NULL || buf == NULL) {
- RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
switch (padding) {
case RSA_PKCS1_PADDING:
- i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen);
+ i = ossl_rsa_padding_add_PKCS1_type_2_ex(rsa->libctx, buf, num,
+ from, flen);
break;
case RSA_PKCS1_OAEP_PADDING:
- i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0);
- break;
- case RSA_SSLV23_PADDING:
- i = RSA_padding_add_SSLv23(buf, num, from, flen);
+ i = ossl_rsa_padding_add_PKCS1_OAEP_mgf1_ex(rsa->libctx, buf, num,
+ from, flen, NULL, 0,
+ NULL, NULL);
break;
case RSA_NO_PADDING:
i = RSA_padding_add_none(buf, num, from, flen);
break;
default:
- RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
if (i <= 0)
@@ -128,8 +134,7 @@ static int rsa_ossl_public_encrypt(int flen, const unsigned char *from,
if (BN_ucmp(f, rsa->n) >= 0) {
/* usually the padding functions would catch this */
- RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT,
- RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
}
@@ -158,7 +163,8 @@ static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
{
BN_BLINDING *ret;
- CRYPTO_THREAD_write_lock(rsa->lock);
+ if (!CRYPTO_THREAD_write_lock(rsa->lock))
+ return NULL;
if (rsa->blinding == NULL) {
rsa->blinding = RSA_setup_blinding(rsa, ctx);
@@ -207,7 +213,9 @@ static int rsa_blinding_convert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind,
*/
int ret;
- BN_BLINDING_lock(b);
+ if (!BN_BLINDING_lock(b))
+ return 0;
+
ret = BN_BLINDING_convert_ex(f, unblind, b, ctx);
BN_BLINDING_unlock(b);
@@ -246,7 +254,7 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
BIGNUM *unblind = NULL;
BN_BLINDING *blinding = NULL;
- if ((ctx = BN_CTX_new()) == NULL)
+ if ((ctx = BN_CTX_new_ex(rsa->libctx)) == NULL)
goto err;
BN_CTX_start(ctx);
f = BN_CTX_get(ctx);
@@ -254,7 +262,7 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
num = BN_num_bytes(rsa->n);
buf = OPENSSL_malloc(num);
if (ret == NULL || buf == NULL) {
- RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -268,9 +276,8 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
case RSA_NO_PADDING:
i = RSA_padding_add_none(buf, num, from, flen);
break;
- case RSA_SSLV23_PADDING:
default:
- RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
if (i <= 0)
@@ -281,8 +288,7 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
if (BN_ucmp(f, rsa->n) >= 0) {
/* usually the padding functions would catch this */
- RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT,
- RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
}
@@ -294,14 +300,14 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
if (blinding == NULL) {
- RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (blinding != NULL) {
if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) {
- RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!rsa_blinding_convert(blinding, f, unblind, ctx))
@@ -318,11 +324,11 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
} else {
BIGNUM *d = BN_new();
if (d == NULL) {
- RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
if (rsa->d == NULL) {
- RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_MISSING_PRIVATE_KEY);
+ ERR_raise(ERR_LIB_RSA, RSA_R_MISSING_PRIVATE_KEY);
BN_free(d);
goto err;
}
@@ -380,7 +386,7 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
BIGNUM *unblind = NULL;
BN_BLINDING *blinding = NULL;
- if ((ctx = BN_CTX_new()) == NULL)
+ if ((ctx = BN_CTX_new_ex(rsa->libctx)) == NULL)
goto err;
BN_CTX_start(ctx);
f = BN_CTX_get(ctx);
@@ -388,7 +394,7 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
num = BN_num_bytes(rsa->n);
buf = OPENSSL_malloc(num);
if (ret == NULL || buf == NULL) {
- RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -397,8 +403,7 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
* top '0' bytes
*/
if (flen > num) {
- RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT,
- RSA_R_DATA_GREATER_THAN_MOD_LEN);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_GREATER_THAN_MOD_LEN);
goto err;
}
@@ -407,22 +412,21 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
goto err;
if (BN_ucmp(f, rsa->n) >= 0) {
- RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT,
- RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
}
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
if (blinding == NULL) {
- RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (blinding != NULL) {
if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) {
- RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!rsa_blinding_convert(blinding, f, unblind, ctx))
@@ -440,11 +444,11 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
} else {
BIGNUM *d = BN_new();
if (d == NULL) {
- RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
if (rsa->d == NULL) {
- RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_MISSING_PRIVATE_KEY);
+ ERR_raise(ERR_LIB_RSA, RSA_R_MISSING_PRIVATE_KEY);
BN_free(d);
goto err;
}
@@ -487,18 +491,22 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
case RSA_PKCS1_OAEP_PADDING:
r = RSA_padding_check_PKCS1_OAEP(to, num, buf, j, num, NULL, 0);
break;
- case RSA_SSLV23_PADDING:
- r = RSA_padding_check_SSLv23(to, num, buf, j, num);
- break;
case RSA_NO_PADDING:
memcpy(to, buf, (r = j));
break;
default:
- RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
- RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_PADDING_CHECK_FAILED);
+#ifndef FIPS_MODULE
+ /*
+ * This trick doesn't work in the FIPS provider because libcrypto manages
+ * the error stack. Instead we opt not to put an error on the stack at all
+ * in case of padding failure in the FIPS provider.
+ */
+ ERR_raise(ERR_LIB_RSA, RSA_R_PADDING_CHECK_FAILED);
err_clear_last_constant_time(1 & ~constant_time_msb(r));
+#endif
err:
BN_CTX_end(ctx);
@@ -517,24 +525,24 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
BN_CTX *ctx = NULL;
if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
- RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_MODULUS_TOO_LARGE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_MODULUS_TOO_LARGE);
return -1;
}
if (BN_ucmp(rsa->n, rsa->e) <= 0) {
- RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE);
return -1;
}
/* for large moduli, enforce exponent limit */
if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) {
if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
- RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE);
return -1;
}
}
- if ((ctx = BN_CTX_new()) == NULL)
+ if ((ctx = BN_CTX_new_ex(rsa->libctx)) == NULL)
goto err;
BN_CTX_start(ctx);
f = BN_CTX_get(ctx);
@@ -542,7 +550,7 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
num = BN_num_bytes(rsa->n);
buf = OPENSSL_malloc(num);
if (ret == NULL || buf == NULL) {
- RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -551,7 +559,7 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
* top '0' bytes
*/
if (flen > num) {
- RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_DATA_GREATER_THAN_MOD_LEN);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_GREATER_THAN_MOD_LEN);
goto err;
}
@@ -559,8 +567,7 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
goto err;
if (BN_ucmp(f, rsa->n) >= 0) {
- RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT,
- RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
}
@@ -578,6 +585,8 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
goto err;
i = BN_bn2binpad(ret, buf, num);
+ if (i < 0)
+ goto err;
switch (padding) {
case RSA_PKCS1_PADDING:
@@ -590,11 +599,11 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
memcpy(to, buf, (r = i));
break;
default:
- RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
if (r < 0)
- RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_PADDING_CHECK_FAILED);
+ ERR_raise(ERR_LIB_RSA, RSA_R_PADDING_CHECK_FAILED);
err:
BN_CTX_end(ctx);
@@ -605,23 +614,31 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
{
- BIGNUM *r1, *m1, *vrfy, *r2, *m[RSA_MAX_PRIME_NUM - 2];
- int ret = 0, i, ex_primes = 0, smooth = 0;
+ BIGNUM *r1, *m1, *vrfy;
+ int ret = 0, smooth = 0;
+#ifndef FIPS_MODULE
+ BIGNUM *r2, *m[RSA_MAX_PRIME_NUM - 2];
+ int i, ex_primes = 0;
RSA_PRIME_INFO *pinfo;
+#endif
BN_CTX_start(ctx);
r1 = BN_CTX_get(ctx);
+#ifndef FIPS_MODULE
r2 = BN_CTX_get(ctx);
+#endif
m1 = BN_CTX_get(ctx);
vrfy = BN_CTX_get(ctx);
if (vrfy == NULL)
goto err;
+#ifndef FIPS_MODULE
if (rsa->version == RSA_ASN1_VERSION_MULTI
&& ((ex_primes = sk_RSA_PRIME_INFO_num(rsa->prime_infos)) <= 0
|| ex_primes > RSA_MAX_PRIME_NUM - 2))
goto err;
+#endif
if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) {
BIGNUM *factor = BN_new();
@@ -642,6 +659,7 @@ static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
BN_free(factor);
goto err;
}
+#ifndef FIPS_MODULE
for (i = 0; i < ex_primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
BN_with_flags(factor, pinfo->r, BN_FLG_CONSTTIME);
@@ -650,13 +668,16 @@ static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
goto err;
}
}
+#endif
/*
* We MUST free |factor| before any further use of the prime factors
*/
BN_free(factor);
- smooth = (ex_primes == 0)
- && (rsa->meth->bn_mod_exp == BN_mod_exp_mont)
+ smooth = (rsa->meth->bn_mod_exp == BN_mod_exp_mont)
+#ifndef FIPS_MODULE
+ && (ex_primes == 0)
+#endif
&& (BN_num_bits(rsa->q) == BN_num_bits(rsa->p));
}
@@ -676,15 +697,20 @@ static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
if (/* m1 = I moq q */
!bn_from_mont_fixed_top(m1, I, rsa->_method_mod_q, ctx)
|| !bn_to_mont_fixed_top(m1, m1, rsa->_method_mod_q, ctx)
- /* m1 = m1^dmq1 mod q */
- || !BN_mod_exp_mont_consttime(m1, m1, rsa->dmq1, rsa->q, ctx,
- rsa->_method_mod_q)
/* r1 = I mod p */
|| !bn_from_mont_fixed_top(r1, I, rsa->_method_mod_p, ctx)
|| !bn_to_mont_fixed_top(r1, r1, rsa->_method_mod_p, ctx)
- /* r1 = r1^dmp1 mod p */
- || !BN_mod_exp_mont_consttime(r1, r1, rsa->dmp1, rsa->p, ctx,
- rsa->_method_mod_p)
+ /*
+ * Use parallel exponentiations optimization if possible,
+ * otherwise fallback to two sequential exponentiations:
+ * m1 = m1^dmq1 mod q
+ * r1 = r1^dmp1 mod p
+ */
+ || !BN_mod_exp_mont_consttime_x2(m1, m1, rsa->dmq1, rsa->q,
+ rsa->_method_mod_q,
+ r1, r1, rsa->dmp1, rsa->p,
+ rsa->_method_mod_p,
+ ctx)
/* r1 = (r1 - m1) mod p */
/*
* bn_mod_sub_fixed_top is not regular modular subtraction,
@@ -762,16 +788,7 @@ static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
BN_free(dmp1);
}
- /*
- * calculate m_i in multi-prime case
- *
- * TODO:
- * 1. squash the following two loops and calculate |m_i| there.
- * 2. remove cc and reuse |c|.
- * 3. remove |dmq1| and |dmp1| in previous block and use |di|.
- *
- * If these things are done, the code will be more readable.
- */
+#ifndef FIPS_MODULE
if (ex_primes > 0) {
BIGNUM *di = BN_new(), *cc = BN_new();
@@ -811,6 +828,7 @@ static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
BN_free(cc);
BN_free(di);
}
+#endif
if (!BN_sub(r0, r0, m1))
goto err;
@@ -854,6 +872,7 @@ static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
if (!BN_add(r0, r1, m1))
goto err;
+#ifndef FIPS_MODULE
/* add m_i to m in multi-prime case */
if (ex_primes > 0) {
BIGNUM *pr2 = BN_new();
@@ -896,6 +915,7 @@ static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
}
BN_free(pr2);
}
+#endif
tail:
if (rsa->e && rsa->n) {
@@ -971,15 +991,18 @@ static int rsa_ossl_init(RSA *rsa)
static int rsa_ossl_finish(RSA *rsa)
{
+#ifndef FIPS_MODULE
int i;
RSA_PRIME_INFO *pinfo;
- BN_MONT_CTX_free(rsa->_method_mod_n);
- BN_MONT_CTX_free(rsa->_method_mod_p);
- BN_MONT_CTX_free(rsa->_method_mod_q);
for (i = 0; i < sk_RSA_PRIME_INFO_num(rsa->prime_infos); i++) {
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
BN_MONT_CTX_free(pinfo->m);
}
+#endif
+
+ BN_MONT_CTX_free(rsa->_method_mod_n);
+ BN_MONT_CTX_free(rsa->_method_mod_p);
+ BN_MONT_CTX_free(rsa->_method_mod_q);
return 1;
}
diff --git a/crypto/rsa/rsa_pk1.c b/crypto/rsa/rsa_pk1.c
index a3d0b7cef81e..51507fc030a7 100644
--- a/crypto/rsa/rsa_pk1.c
+++ b/crypto/rsa/rsa_pk1.c
@@ -1,19 +1,29 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include "internal/constant_time.h"
#include <stdio.h>
-#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/rand.h>
+/* Just for the SSL_MAX_MASTER_KEY_LENGTH value */
+#include <openssl/prov_ssl.h>
+#include "internal/cryptlib.h"
+#include "crypto/rsa.h"
+#include "rsa_local.h"
int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen,
const unsigned char *from, int flen)
@@ -22,8 +32,7 @@ int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen,
unsigned char *p;
if (flen > (tlen - RSA_PKCS1_PADDING_SIZE)) {
- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1,
- RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return 0;
}
@@ -63,16 +72,14 @@ int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen,
/* Accept inputs with and without the leading 0-byte. */
if (num == flen) {
if ((*p++) != 0x00) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
- RSA_R_INVALID_PADDING);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING);
return -1;
}
flen--;
}
if ((num != (flen + 1)) || (*(p++) != 0x01)) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
- RSA_R_BLOCK_TYPE_IS_NOT_01);
+ ERR_raise(ERR_LIB_RSA, RSA_R_BLOCK_TYPE_IS_NOT_01);
return -1;
}
@@ -84,8 +91,7 @@ int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen,
p++;
break;
} else {
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
- RSA_R_BAD_FIXED_HEADER_DECRYPT);
+ ERR_raise(ERR_LIB_RSA, RSA_R_BAD_FIXED_HEADER_DECRYPT);
return -1;
}
}
@@ -93,20 +99,18 @@ int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen,
}
if (i == j) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
- RSA_R_NULL_BEFORE_BLOCK_MISSING);
+ ERR_raise(ERR_LIB_RSA, RSA_R_NULL_BEFORE_BLOCK_MISSING);
return -1;
}
if (i < 8) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
- RSA_R_BAD_PAD_BYTE_COUNT);
+ ERR_raise(ERR_LIB_RSA, RSA_R_BAD_PAD_BYTE_COUNT);
return -1;
}
i++; /* Skip over the '\0' */
j -= i;
if (j > tlen) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1, RSA_R_DATA_TOO_LARGE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE);
return -1;
}
memcpy(to, p, (unsigned int)j);
@@ -114,15 +118,18 @@ int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen,
return j;
}
-int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen,
- const unsigned char *from, int flen)
+int ossl_rsa_padding_add_PKCS1_type_2_ex(OSSL_LIB_CTX *libctx, unsigned char *to,
+ int tlen, const unsigned char *from,
+ int flen)
{
int i, j;
unsigned char *p;
if (flen > (tlen - RSA_PKCS1_PADDING_SIZE)) {
- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2,
- RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ return 0;
+ } else if (flen < 0) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_LENGTH);
return 0;
}
@@ -134,12 +141,12 @@ int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen,
/* pad out with non-zero random data */
j = tlen - 3 - flen;
- if (RAND_bytes(p, j) <= 0)
+ if (RAND_bytes_ex(libctx, p, j, 0) <= 0)
return 0;
for (i = 0; i < j; i++) {
if (*p == '\0')
do {
- if (RAND_bytes(p, 1) <= 0)
+ if (RAND_bytes_ex(libctx, p, 1, 0) <= 0)
return 0;
} while (*p == '\0');
p++;
@@ -151,6 +158,12 @@ int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen,
return 1;
}
+int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen,
+ const unsigned char *from, int flen)
+{
+ return ossl_rsa_padding_add_PKCS1_type_2_ex(NULL, to, tlen, from, flen);
+}
+
int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
const unsigned char *from, int flen,
int num)
@@ -170,14 +183,13 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
*/
if (flen > num || num < RSA_PKCS1_PADDING_SIZE) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2,
- RSA_R_PKCS_DECODING_ERROR);
+ ERR_raise(ERR_LIB_RSA, RSA_R_PKCS_DECODING_ERROR);
return -1;
}
em = OPENSSL_malloc(num);
if (em == NULL) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
return -1;
}
/*
@@ -248,8 +260,137 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
}
OPENSSL_clear_free(em, num);
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, RSA_R_PKCS_DECODING_ERROR);
+#ifndef FIPS_MODULE
+ /*
+ * This trick doesn't work in the FIPS provider because libcrypto manages
+ * the error stack. Instead we opt not to put an error on the stack at all
+ * in case of padding failure in the FIPS provider.
+ */
+ ERR_raise(ERR_LIB_RSA, RSA_R_PKCS_DECODING_ERROR);
err_clear_last_constant_time(1 & good);
+#endif
return constant_time_select_int(good, mlen, -1);
}
+
+/*
+ * ossl_rsa_padding_check_PKCS1_type_2_TLS() checks and removes the PKCS1 type 2
+ * padding from a decrypted RSA message in a TLS signature. The result is stored
+ * in the buffer pointed to by |to| which should be |tlen| bytes long. |tlen|
+ * must be at least SSL_MAX_MASTER_KEY_LENGTH. The original decrypted message
+ * should be stored in |from| which must be |flen| bytes in length and padded
+ * such that |flen == RSA_size()|. The TLS protocol version that the client
+ * originally requested should be passed in |client_version|. Some buggy clients
+ * can exist which use the negotiated version instead of the originally
+ * requested protocol version. If it is necessary to work around this bug then
+ * the negotiated protocol version can be passed in |alt_version|, otherwise 0
+ * should be passed.
+ *
+ * If the passed message is publicly invalid or some other error that can be
+ * treated in non-constant time occurs then -1 is returned. On success the
+ * length of the decrypted data is returned. This will always be
+ * SSL_MAX_MASTER_KEY_LENGTH. If an error occurs that should be treated in
+ * constant time then this function will appear to return successfully, but the
+ * decrypted data will be randomly generated (as per
+ * https://tools.ietf.org/html/rfc5246#section-7.4.7.1).
+ */
+int ossl_rsa_padding_check_PKCS1_type_2_TLS(OSSL_LIB_CTX *libctx,
+ unsigned char *to, size_t tlen,
+ const unsigned char *from,
+ size_t flen, int client_version,
+ int alt_version)
+{
+ unsigned int i, good, version_good;
+ unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
+
+ /*
+ * If these checks fail then either the message in publicly invalid, or
+ * we've been called incorrectly. We can fail immediately.
+ */
+ if (flen < RSA_PKCS1_PADDING_SIZE + SSL_MAX_MASTER_KEY_LENGTH
+ || tlen < SSL_MAX_MASTER_KEY_LENGTH) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_PKCS_DECODING_ERROR);
+ return -1;
+ }
+
+ /*
+ * Generate a random premaster secret to use in the event that we fail
+ * to decrypt.
+ */
+ if (RAND_priv_bytes_ex(libctx, rand_premaster_secret,
+ sizeof(rand_premaster_secret), 0) <= 0) {
+ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ good = constant_time_is_zero(from[0]);
+ good &= constant_time_eq(from[1], 2);
+
+ /* Check we have the expected padding data */
+ for (i = 2; i < flen - SSL_MAX_MASTER_KEY_LENGTH - 1; i++)
+ good &= ~constant_time_is_zero_8(from[i]);
+ good &= constant_time_is_zero_8(from[flen - SSL_MAX_MASTER_KEY_LENGTH - 1]);
+
+
+ /*
+ * If the version in the decrypted pre-master secret is correct then
+ * version_good will be 0xff, otherwise it'll be zero. The
+ * Klima-Pokorny-Rosa extension of Bleichenbacher's attack
+ * (http://eprint.iacr.org/2003/052/) exploits the version number
+ * check as a "bad version oracle". Thus version checks are done in
+ * constant time and are treated like any other decryption error.
+ */
+ version_good =
+ constant_time_eq(from[flen - SSL_MAX_MASTER_KEY_LENGTH],
+ (client_version >> 8) & 0xff);
+ version_good &=
+ constant_time_eq(from[flen - SSL_MAX_MASTER_KEY_LENGTH + 1],
+ client_version & 0xff);
+
+ /*
+ * The premaster secret must contain the same version number as the
+ * ClientHello to detect version rollback attacks (strangely, the
+ * protocol does not offer such protection for DH ciphersuites).
+ * However, buggy clients exist that send the negotiated protocol
+ * version instead if the server does not support the requested
+ * protocol version. If SSL_OP_TLS_ROLLBACK_BUG is set then we tolerate
+ * such clients. In that case alt_version will be non-zero and set to
+ * the negotiated version.
+ */
+ if (alt_version > 0) {
+ unsigned int workaround_good;
+
+ workaround_good =
+ constant_time_eq(from[flen - SSL_MAX_MASTER_KEY_LENGTH],
+ (alt_version >> 8) & 0xff);
+ workaround_good &=
+ constant_time_eq(from[flen - SSL_MAX_MASTER_KEY_LENGTH + 1],
+ alt_version & 0xff);
+ version_good |= workaround_good;
+ }
+
+ good &= version_good;
+
+
+ /*
+ * Now copy the result over to the to buffer if good, or random data if
+ * not good.
+ */
+ for (i = 0; i < SSL_MAX_MASTER_KEY_LENGTH; i++) {
+ to[i] =
+ constant_time_select_8(good,
+ from[flen - SSL_MAX_MASTER_KEY_LENGTH + i],
+ rand_premaster_secret[i]);
+ }
+
+ /*
+ * We must not leak whether a decryption failure occurs because of
+ * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246,
+ * section 7.4.7.1). The code follows that advice of the TLS RFC and
+ * generates a random premaster secret for the case that the decrypt
+ * fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
+ * So, whether we actually succeeded or not, return success.
+ */
+
+ return SSL_MAX_MASTER_KEY_LENGTH;
+}
diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c
index 0eb21c8af975..44c819a5c3ce 100644
--- a/crypto/rsa/rsa_pmeth.c
+++ b/crypto/rsa/rsa_pmeth.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include "internal/constant_time.h"
#include <stdio.h>
@@ -19,6 +25,7 @@
#include <openssl/x509v3.h>
#include <openssl/cms.h>
#include "crypto/evp.h"
+#include "crypto/rsa.h"
#include "rsa_local.h"
/* RSA pkey context structure */
@@ -72,7 +79,7 @@ static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
return 1;
}
-static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+static int pkey_rsa_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
{
RSA_PKEY_CTX *dctx, *sctx;
@@ -89,6 +96,7 @@ static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
dctx->pad_mode = sctx->pad_mode;
dctx->md = sctx->md;
dctx->mgf1md = sctx->mgf1md;
+ dctx->saltlen = sctx->saltlen;
if (sctx->oaep_label) {
OPENSSL_free(dctx->oaep_label);
dctx->oaep_label = OPENSSL_memdup(sctx->oaep_label, sctx->oaep_labellen);
@@ -103,8 +111,9 @@ static int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk)
{
if (ctx->tbuf != NULL)
return 1;
- if ((ctx->tbuf = OPENSSL_malloc(EVP_PKEY_size(pk->pkey))) == NULL) {
- RSAerr(RSA_F_SETUP_TBUF, ERR_R_MALLOC_FAILURE);
+ if ((ctx->tbuf =
+ OPENSSL_malloc(RSA_size(EVP_PKEY_get0_RSA(pk->pkey)))) == NULL) {
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
@@ -127,40 +136,44 @@ static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig,
{
int ret;
RSA_PKEY_CTX *rctx = ctx->data;
- RSA *rsa = ctx->pkey->pkey.rsa;
+ /*
+ * Discard const. Its marked as const because this may be a cached copy of
+ * the "real" key. These calls don't make any modifications that need to
+ * be reflected back in the "original" key.
+ */
+ RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey);
if (rctx->md) {
- if (tbslen != (size_t)EVP_MD_size(rctx->md)) {
- RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_INVALID_DIGEST_LENGTH);
+ if (tbslen != (size_t)EVP_MD_get_size(rctx->md)) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH);
return -1;
}
- if (EVP_MD_type(rctx->md) == NID_mdc2) {
+ if (EVP_MD_get_type(rctx->md) == NID_mdc2) {
unsigned int sltmp;
if (rctx->pad_mode != RSA_PKCS1_PADDING)
return -1;
- ret = RSA_sign_ASN1_OCTET_STRING(0,
- tbs, tbslen, sig, &sltmp, rsa);
+ ret = RSA_sign_ASN1_OCTET_STRING(0, tbs, tbslen, sig, &sltmp, rsa);
if (ret <= 0)
return ret;
ret = sltmp;
} else if (rctx->pad_mode == RSA_X931_PADDING) {
- if ((size_t)EVP_PKEY_size(ctx->pkey) < tbslen + 1) {
- RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_KEY_SIZE_TOO_SMALL);
+ if ((size_t)RSA_size(rsa) < tbslen + 1) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_KEY_SIZE_TOO_SMALL);
return -1;
}
if (!setup_tbuf(rctx, ctx)) {
- RSAerr(RSA_F_PKEY_RSA_SIGN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
return -1;
}
memcpy(rctx->tbuf, tbs, tbslen);
- rctx->tbuf[tbslen] = RSA_X931_hash_id(EVP_MD_type(rctx->md));
+ rctx->tbuf[tbslen] = RSA_X931_hash_id(EVP_MD_get_type(rctx->md));
ret = RSA_private_encrypt(tbslen + 1, rctx->tbuf,
sig, rsa, RSA_X931_PADDING);
} else if (rctx->pad_mode == RSA_PKCS1_PADDING) {
unsigned int sltmp;
- ret = RSA_sign(EVP_MD_type(rctx->md),
+ ret = RSA_sign(EVP_MD_get_type(rctx->md),
tbs, tbslen, sig, &sltmp, rsa);
if (ret <= 0)
return ret;
@@ -179,8 +192,7 @@ static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig,
return -1;
}
} else {
- ret = RSA_private_encrypt(tbslen, tbs, sig, ctx->pkey->pkey.rsa,
- rctx->pad_mode);
+ ret = RSA_private_encrypt(tbslen, tbs, sig, rsa, rctx->pad_mode);
}
if (ret < 0)
return ret;
@@ -194,34 +206,37 @@ static int pkey_rsa_verifyrecover(EVP_PKEY_CTX *ctx,
{
int ret;
RSA_PKEY_CTX *rctx = ctx->data;
+ /*
+ * Discard const. Its marked as const because this may be a cached copy of
+ * the "real" key. These calls don't make any modifications that need to
+ * be reflected back in the "original" key.
+ */
+ RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey);
if (rctx->md) {
if (rctx->pad_mode == RSA_X931_PADDING) {
if (!setup_tbuf(rctx, ctx))
return -1;
- ret = RSA_public_decrypt(siglen, sig,
- rctx->tbuf, ctx->pkey->pkey.rsa,
+ ret = RSA_public_decrypt(siglen, sig, rctx->tbuf, rsa,
RSA_X931_PADDING);
if (ret < 1)
return 0;
ret--;
- if (rctx->tbuf[ret] != RSA_X931_hash_id(EVP_MD_type(rctx->md))) {
- RSAerr(RSA_F_PKEY_RSA_VERIFYRECOVER,
- RSA_R_ALGORITHM_MISMATCH);
+ if (rctx->tbuf[ret] != RSA_X931_hash_id(EVP_MD_get_type(rctx->md))) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_ALGORITHM_MISMATCH);
return 0;
}
- if (ret != EVP_MD_size(rctx->md)) {
- RSAerr(RSA_F_PKEY_RSA_VERIFYRECOVER,
- RSA_R_INVALID_DIGEST_LENGTH);
+ if (ret != EVP_MD_get_size(rctx->md)) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH);
return 0;
}
if (rout)
memcpy(rout, rctx->tbuf, ret);
} else if (rctx->pad_mode == RSA_PKCS1_PADDING) {
size_t sltmp;
- ret = int_rsa_verify(EVP_MD_type(rctx->md),
- NULL, 0, rout, &sltmp,
- sig, siglen, ctx->pkey->pkey.rsa);
+ ret = ossl_rsa_verify(EVP_MD_get_type(rctx->md),
+ NULL, 0, rout, &sltmp,
+ sig, siglen, rsa);
if (ret <= 0)
return 0;
ret = sltmp;
@@ -229,8 +244,7 @@ static int pkey_rsa_verifyrecover(EVP_PKEY_CTX *ctx,
return -1;
}
} else {
- ret = RSA_public_decrypt(siglen, sig, rout, ctx->pkey->pkey.rsa,
- rctx->pad_mode);
+ ret = RSA_public_decrypt(siglen, sig, rout, rsa, rctx->pad_mode);
}
if (ret < 0)
return ret;
@@ -243,15 +257,20 @@ static int pkey_rsa_verify(EVP_PKEY_CTX *ctx,
const unsigned char *tbs, size_t tbslen)
{
RSA_PKEY_CTX *rctx = ctx->data;
- RSA *rsa = ctx->pkey->pkey.rsa;
+ /*
+ * Discard const. Its marked as const because this may be a cached copy of
+ * the "real" key. These calls don't make any modifications that need to
+ * be reflected back in the "original" key.
+ */
+ RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey);
size_t rslen;
if (rctx->md) {
if (rctx->pad_mode == RSA_PKCS1_PADDING)
- return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen,
+ return RSA_verify(EVP_MD_get_type(rctx->md), tbs, tbslen,
sig, siglen, rsa);
- if (tbslen != (size_t)EVP_MD_size(rctx->md)) {
- RSAerr(RSA_F_PKEY_RSA_VERIFY, RSA_R_INVALID_DIGEST_LENGTH);
+ if (tbslen != (size_t)EVP_MD_get_size(rctx->md)) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH);
return -1;
}
if (rctx->pad_mode == RSA_X931_PADDING) {
@@ -296,9 +315,15 @@ static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx,
{
int ret;
RSA_PKEY_CTX *rctx = ctx->data;
+ /*
+ * Discard const. Its marked as const because this may be a cached copy of
+ * the "real" key. These calls don't make any modifications that need to
+ * be reflected back in the "original" key.
+ */
+ RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey);
if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
- int klen = RSA_size(ctx->pkey->pkey.rsa);
+ int klen = RSA_size(rsa);
if (!setup_tbuf(rctx, ctx))
return -1;
if (!RSA_padding_add_PKCS1_OAEP_mgf1(rctx->tbuf, klen,
@@ -307,11 +332,9 @@ static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx,
rctx->oaep_labellen,
rctx->md, rctx->mgf1md))
return -1;
- ret = RSA_public_encrypt(klen, rctx->tbuf, out,
- ctx->pkey->pkey.rsa, RSA_NO_PADDING);
+ ret = RSA_public_encrypt(klen, rctx->tbuf, out, rsa, RSA_NO_PADDING);
} else {
- ret = RSA_public_encrypt(inlen, in, out, ctx->pkey->pkey.rsa,
- rctx->pad_mode);
+ ret = RSA_public_encrypt(inlen, in, out, rsa, rctx->pad_mode);
}
if (ret < 0)
return ret;
@@ -325,12 +348,17 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx,
{
int ret;
RSA_PKEY_CTX *rctx = ctx->data;
+ /*
+ * Discard const. Its marked as const because this may be a cached copy of
+ * the "real" key. These calls don't make any modifications that need to
+ * be reflected back in the "original" key.
+ */
+ RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey);
if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
if (!setup_tbuf(rctx, ctx))
return -1;
- ret = RSA_private_decrypt(inlen, in, rctx->tbuf,
- ctx->pkey->pkey.rsa, RSA_NO_PADDING);
+ ret = RSA_private_decrypt(inlen, in, rctx->tbuf, rsa, RSA_NO_PADDING);
if (ret <= 0)
return ret;
ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, ret, rctx->tbuf,
@@ -339,8 +367,7 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx,
rctx->oaep_labellen,
rctx->md, rctx->mgf1md);
} else {
- ret = RSA_private_decrypt(inlen, in, out, ctx->pkey->pkey.rsa,
- rctx->pad_mode);
+ ret = RSA_private_decrypt(inlen, in, out, rsa, rctx->pad_mode);
}
*outlen = constant_time_select_s(constant_time_msb_s(ret), *outlen, ret);
ret = constant_time_select_int(constant_time_msb(ret), ret, 1);
@@ -354,16 +381,16 @@ static int check_padding_md(const EVP_MD *md, int padding)
if (!md)
return 1;
- mdnid = EVP_MD_type(md);
+ mdnid = EVP_MD_get_type(md);
if (padding == RSA_NO_PADDING) {
- RSAerr(RSA_F_CHECK_PADDING_MD, RSA_R_INVALID_PADDING_MODE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING_MODE);
return 0;
}
if (padding == RSA_X931_PADDING) {
if (RSA_X931_hash_id(mdnid) == -1) {
- RSAerr(RSA_F_CHECK_PADDING_MD, RSA_R_INVALID_X931_DIGEST);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_X931_DIGEST);
return 0;
}
} else {
@@ -374,6 +401,8 @@ static int check_padding_md(const EVP_MD *md, int padding)
case NID_sha256:
case NID_sha384:
case NID_sha512:
+ case NID_sha512_224:
+ case NID_sha512_256:
case NID_md5:
case NID_md5_sha1:
case NID_md2:
@@ -387,7 +416,7 @@ static int check_padding_md(const EVP_MD *md, int padding)
return 1;
default:
- RSAerr(RSA_F_CHECK_PADDING_MD, RSA_R_INVALID_DIGEST);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST);
return 0;
}
@@ -424,8 +453,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return 1;
}
bad_pad:
- RSAerr(RSA_F_PKEY_RSA_CTRL,
- RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
return -2;
case EVP_PKEY_CTRL_GET_RSA_PADDING:
@@ -435,7 +463,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) {
- RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PSS_SALTLEN);
return -2;
}
if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) {
@@ -446,13 +474,13 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
if (rsa_pss_restricted(rctx)) {
if (p1 == RSA_PSS_SALTLEN_AUTO
&& ctx->operation == EVP_PKEY_OP_VERIFY) {
- RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PSS_SALTLEN);
return -2;
}
if ((p1 == RSA_PSS_SALTLEN_DIGEST
- && rctx->min_saltlen > EVP_MD_size(rctx->md))
+ && rctx->min_saltlen > EVP_MD_get_size(rctx->md))
|| (p1 >= 0 && p1 < rctx->min_saltlen)) {
- RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_PSS_SALTLEN_TOO_SMALL);
+ ERR_raise(ERR_LIB_RSA, RSA_R_PSS_SALTLEN_TOO_SMALL);
return 0;
}
}
@@ -462,7 +490,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
if (p1 < RSA_MIN_MODULUS_BITS) {
- RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_KEY_SIZE_TOO_SMALL);
+ ERR_raise(ERR_LIB_RSA, RSA_R_KEY_SIZE_TOO_SMALL);
return -2;
}
rctx->nbits = p1;
@@ -470,7 +498,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
if (p2 == NULL || !BN_is_odd((BIGNUM *)p2) || BN_is_one((BIGNUM *)p2)) {
- RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_BAD_E_VALUE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE);
return -2;
}
BN_free(rctx->pub_exp);
@@ -479,7 +507,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES:
if (p1 < RSA_DEFAULT_PRIME_NUM || p1 > RSA_MAX_PRIME_NUM) {
- RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_KEY_PRIME_NUM_INVALID);
+ ERR_raise(ERR_LIB_RSA, RSA_R_KEY_PRIME_NUM_INVALID);
return -2;
}
rctx->primes = p1;
@@ -488,7 +516,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_RSA_OAEP_MD:
case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
- RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PADDING_MODE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING_MODE);
return -2;
}
if (type == EVP_PKEY_CTRL_GET_RSA_OAEP_MD)
@@ -501,9 +529,9 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
if (!check_padding_md(p2, rctx->pad_mode))
return 0;
if (rsa_pss_restricted(rctx)) {
- if (EVP_MD_type(rctx->md) == EVP_MD_type(p2))
+ if (EVP_MD_get_type(rctx->md) == EVP_MD_get_type(p2))
return 1;
- RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_DIGEST_NOT_ALLOWED);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DIGEST_NOT_ALLOWED);
return 0;
}
rctx->md = p2;
@@ -517,7 +545,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING
&& rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
- RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_MGF1_MD);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MGF1_MD);
return -2;
}
if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD) {
@@ -527,9 +555,9 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
*(const EVP_MD **)p2 = rctx->md;
} else {
if (rsa_pss_restricted(rctx)) {
- if (EVP_MD_type(rctx->mgf1md) == EVP_MD_type(p2))
+ if (EVP_MD_get_type(rctx->mgf1md) == EVP_MD_get_type(p2))
return 1;
- RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_MGF1_DIGEST_NOT_ALLOWED);
+ ERR_raise(ERR_LIB_RSA, RSA_R_MGF1_DIGEST_NOT_ALLOWED);
return 0;
}
rctx->mgf1md = p2;
@@ -538,7 +566,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
- RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PADDING_MODE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING_MODE);
return -2;
}
OPENSSL_free(rctx->oaep_label);
@@ -553,7 +581,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
- RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PADDING_MODE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING_MODE);
return -2;
}
*(unsigned char **)p2 = rctx->oaep_label;
@@ -576,8 +604,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return 1;
/* fall through */
case EVP_PKEY_CTRL_PEER_KEY:
- RSAerr(RSA_F_PKEY_RSA_CTRL,
- RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
default:
@@ -590,7 +617,7 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
{
if (value == NULL) {
- RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_VALUE_MISSING);
+ ERR_raise(ERR_LIB_RSA, RSA_R_VALUE_MISSING);
return 0;
}
if (strcmp(type, "rsa_padding_mode") == 0) {
@@ -598,8 +625,6 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
if (strcmp(value, "pkcs1") == 0) {
pm = RSA_PKCS1_PADDING;
- } else if (strcmp(value, "sslv23") == 0) {
- pm = RSA_SSLV23_PADDING;
} else if (strcmp(value, "none") == 0) {
pm = RSA_NO_PADDING;
} else if (strcmp(value, "oeap") == 0) {
@@ -611,7 +636,7 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
} else if (strcmp(value, "pss") == 0) {
pm = RSA_PKCS1_PSS_PADDING;
} else {
- RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_UNKNOWN_PADDING_TYPE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE);
return -2;
}
return EVP_PKEY_CTX_set_rsa_padding(ctx, pm);
@@ -643,9 +668,8 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
BIGNUM *pubexp = NULL;
if (!BN_asc2bn(&pubexp, value))
return 0;
- ret = EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp);
- if (ret <= 0)
- BN_free(pubexp);
+ ret = EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, pubexp);
+ BN_free(pubexp);
return ret;
}
@@ -708,8 +732,9 @@ static int rsa_set_pss_param(RSA *rsa, EVP_PKEY_CTX *ctx)
/* If all parameters are default values don't set pss */
if (rctx->md == NULL && rctx->mgf1md == NULL && rctx->saltlen == -2)
return 1;
- rsa->pss = rsa_pss_params_create(rctx->md, rctx->mgf1md,
- rctx->saltlen == -2 ? 0 : rctx->saltlen);
+ rsa->pss = ossl_rsa_pss_params_create(rctx->md, rctx->mgf1md,
+ rctx->saltlen == -2
+ ? 0 : rctx->saltlen);
if (rsa->pss == NULL)
return 0;
return 1;
@@ -754,7 +779,7 @@ static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
return ret;
}
-const EVP_PKEY_METHOD rsa_pkey_meth = {
+static const EVP_PKEY_METHOD rsa_pkey_meth = {
EVP_PKEY_RSA,
EVP_PKEY_FLAG_AUTOARGLEN,
pkey_rsa_init,
@@ -789,6 +814,11 @@ const EVP_PKEY_METHOD rsa_pkey_meth = {
pkey_rsa_ctrl_str
};
+const EVP_PKEY_METHOD *ossl_rsa_pkey_method(void)
+{
+ return &rsa_pkey_meth;
+}
+
/*
* Called for PSS sign or verify initialisation: checks PSS parameter
* sanity and sets any restrictions on key usage.
@@ -796,7 +826,7 @@ const EVP_PKEY_METHOD rsa_pkey_meth = {
static int pkey_pss_init(EVP_PKEY_CTX *ctx)
{
- RSA *rsa;
+ const RSA *rsa;
RSA_PKEY_CTX *rctx = ctx->data;
const EVP_MD *md;
const EVP_MD *mgf1md;
@@ -805,20 +835,20 @@ static int pkey_pss_init(EVP_PKEY_CTX *ctx)
/* Should never happen */
if (!pkey_ctx_is_pss(ctx))
return 0;
- rsa = ctx->pkey->pkey.rsa;
+ rsa = EVP_PKEY_get0_RSA(ctx->pkey);
/* If no restrictions just return */
if (rsa->pss == NULL)
return 1;
/* Get and check parameters */
- if (!rsa_pss_get_param(rsa->pss, &md, &mgf1md, &min_saltlen))
+ if (!ossl_rsa_pss_get_param(rsa->pss, &md, &mgf1md, &min_saltlen))
return 0;
/* See if minimum salt length exceeds maximum possible */
- max_saltlen = RSA_size(rsa) - EVP_MD_size(md);
+ max_saltlen = RSA_size(rsa) - EVP_MD_get_size(md);
if ((RSA_bits(rsa) & 0x7) == 1)
max_saltlen--;
if (min_saltlen > max_saltlen) {
- RSAerr(RSA_F_PKEY_PSS_INIT, RSA_R_INVALID_SALT_LENGTH);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_SALT_LENGTH);
return 0;
}
@@ -836,7 +866,7 @@ static int pkey_pss_init(EVP_PKEY_CTX *ctx)
return 1;
}
-const EVP_PKEY_METHOD rsa_pss_pkey_meth = {
+static const EVP_PKEY_METHOD rsa_pss_pkey_meth = {
EVP_PKEY_RSA_PSS,
EVP_PKEY_FLAG_AUTOARGLEN,
pkey_rsa_init,
@@ -859,3 +889,8 @@ const EVP_PKEY_METHOD rsa_pss_pkey_meth = {
pkey_rsa_ctrl,
pkey_rsa_ctrl_str
};
+
+const EVP_PKEY_METHOD *ossl_rsa_pss_pkey_method(void)
+{
+ return &rsa_pss_pkey_meth;
+}
diff --git a/crypto/rsa/rsa_prn.c b/crypto/rsa/rsa_prn.c
index 23df448a5212..3a9892ebdd4a 100644
--- a/crypto/rsa/rsa_prn.c
+++ b/crypto/rsa/rsa_prn.c
@@ -1,12 +1,18 @@
/*
* Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/rsa.h>
@@ -19,7 +25,7 @@ int RSA_print_fp(FILE *fp, const RSA *x, int off)
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- RSAerr(RSA_F_RSA_PRINT_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_RSA, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
diff --git a/crypto/rsa/rsa_pss.c b/crypto/rsa/rsa_pss.c
index 40ce1c4d378a..33874bfef8a2 100644
--- a/crypto/rsa/rsa_pss.c
+++ b/crypto/rsa/rsa_pss.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
@@ -47,7 +53,7 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash,
if (mgf1Hash == NULL)
mgf1Hash = Hash;
- hLen = EVP_MD_size(Hash);
+ hLen = EVP_MD_get_size(Hash);
if (hLen < 0)
goto err;
/*-
@@ -60,14 +66,14 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash,
if (sLen == RSA_PSS_SALTLEN_DIGEST) {
sLen = hLen;
} else if (sLen < RSA_PSS_SALTLEN_MAX) {
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED);
+ ERR_raise(ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED);
goto err;
}
MSBits = (BN_num_bits(rsa->n) - 1) & 0x7;
emLen = RSA_size(rsa);
if (EM[0] & (0xFF << MSBits)) {
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_FIRST_OCTET_INVALID);
+ ERR_raise(ERR_LIB_RSA, RSA_R_FIRST_OCTET_INVALID);
goto err;
}
if (MSBits == 0) {
@@ -75,24 +81,24 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash,
emLen--;
}
if (emLen < hLen + 2) {
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_DATA_TOO_LARGE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE);
goto err;
}
if (sLen == RSA_PSS_SALTLEN_MAX) {
sLen = emLen - hLen - 2;
} else if (sLen > emLen - hLen - 2) { /* sLen can be small negative */
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_DATA_TOO_LARGE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE);
goto err;
}
if (EM[emLen - 1] != 0xbc) {
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_LAST_OCTET_INVALID);
+ ERR_raise(ERR_LIB_RSA, RSA_R_LAST_OCTET_INVALID);
goto err;
}
maskedDBLen = emLen - hLen - 1;
H = EM + maskedDBLen;
DB = OPENSSL_malloc(maskedDBLen);
if (DB == NULL) {
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
if (PKCS1_MGF1(DB, maskedDBLen, H, hLen, mgf1Hash) < 0)
@@ -103,11 +109,13 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash,
DB[0] &= 0xFF >> (8 - MSBits);
for (i = 0; DB[i] == 0 && i < (maskedDBLen - 1); i++) ;
if (DB[i++] != 0x1) {
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_RECOVERY_FAILED);
+ ERR_raise(ERR_LIB_RSA, RSA_R_SLEN_RECOVERY_FAILED);
goto err;
}
if (sLen != RSA_PSS_SALTLEN_AUTO && (maskedDBLen - i) != sLen) {
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED);
+ ERR_raise_data(ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED,
+ "expected: %d retrieved: %d", sLen,
+ maskedDBLen - i);
goto err;
}
if (!EVP_DigestInit_ex(ctx, Hash, NULL)
@@ -121,7 +129,7 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash,
if (!EVP_DigestFinal_ex(ctx, H_, NULL))
goto err;
if (memcmp(H_, H, hLen)) {
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_BAD_SIGNATURE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_BAD_SIGNATURE);
ret = 0;
} else {
ret = 1;
@@ -156,7 +164,7 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
if (mgf1Hash == NULL)
mgf1Hash = Hash;
- hLen = EVP_MD_size(Hash);
+ hLen = EVP_MD_get_size(Hash);
if (hLen < 0)
goto err;
/*-
@@ -171,7 +179,7 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
} else if (sLen == RSA_PSS_SALTLEN_MAX_SIGN) {
sLen = RSA_PSS_SALTLEN_MAX;
} else if (sLen < RSA_PSS_SALTLEN_MAX) {
- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED);
+ ERR_raise(ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED);
goto err;
}
@@ -182,25 +190,22 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
emLen--;
}
if (emLen < hLen + 2) {
- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1,
- RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
goto err;
}
if (sLen == RSA_PSS_SALTLEN_MAX) {
sLen = emLen - hLen - 2;
} else if (sLen > emLen - hLen - 2) {
- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1,
- RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
goto err;
}
if (sLen > 0) {
salt = OPENSSL_malloc(sLen);
if (salt == NULL) {
- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (RAND_bytes(salt, sLen) <= 0)
+ if (RAND_bytes_ex(rsa->libctx, salt, sLen, 0) <= 0)
goto err;
}
maskedDBLen = emLen - hLen - 1;
@@ -250,6 +255,142 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
}
+/*
+ * The defaults for PSS restrictions are defined in RFC 8017, A.2.3 RSASSA-PSS
+ * (https://tools.ietf.org/html/rfc8017#appendix-A.2.3):
+ *
+ * If the default values of the hashAlgorithm, maskGenAlgorithm, and
+ * trailerField fields of RSASSA-PSS-params are used, then the algorithm
+ * identifier will have the following value:
+ *
+ * rSASSA-PSS-Default-Identifier RSASSA-AlgorithmIdentifier ::= {
+ * algorithm id-RSASSA-PSS,
+ * parameters RSASSA-PSS-params : {
+ * hashAlgorithm sha1,
+ * maskGenAlgorithm mgf1SHA1,
+ * saltLength 20,
+ * trailerField trailerFieldBC
+ * }
+ * }
+ *
+ * RSASSA-AlgorithmIdentifier ::= AlgorithmIdentifier {
+ * {PKCS1Algorithms}
+ * }
+ */
+static const RSA_PSS_PARAMS_30 default_RSASSA_PSS_params = {
+ NID_sha1, /* default hashAlgorithm */
+ {
+ NID_mgf1, /* default maskGenAlgorithm */
+ NID_sha1 /* default MGF1 hash */
+ },
+ 20, /* default saltLength */
+ 1 /* default trailerField (0xBC) */
+};
+
+int ossl_rsa_pss_params_30_set_defaults(RSA_PSS_PARAMS_30 *rsa_pss_params)
+{
+ if (rsa_pss_params == NULL)
+ return 0;
+ *rsa_pss_params = default_RSASSA_PSS_params;
+ return 1;
+}
+
+int ossl_rsa_pss_params_30_is_unrestricted(const RSA_PSS_PARAMS_30 *rsa_pss_params)
+{
+ static RSA_PSS_PARAMS_30 pss_params_cmp = { 0, };
+
+ return rsa_pss_params == NULL
+ || memcmp(rsa_pss_params, &pss_params_cmp,
+ sizeof(*rsa_pss_params)) == 0;
+}
+
+int ossl_rsa_pss_params_30_copy(RSA_PSS_PARAMS_30 *to,
+ const RSA_PSS_PARAMS_30 *from)
+{
+ memcpy(to, from, sizeof(*to));
+ return 1;
+}
+
+int ossl_rsa_pss_params_30_set_hashalg(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int hashalg_nid)
+{
+ if (rsa_pss_params == NULL)
+ return 0;
+ rsa_pss_params->hash_algorithm_nid = hashalg_nid;
+ return 1;
+}
+
+int ossl_rsa_pss_params_30_set_maskgenalg(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int maskgenalg_nid)
+{
+ if (rsa_pss_params == NULL)
+ return 0;
+ rsa_pss_params->mask_gen.algorithm_nid = maskgenalg_nid;
+ return 1;
+}
+
+int ossl_rsa_pss_params_30_set_maskgenhashalg(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int maskgenhashalg_nid)
+{
+ if (rsa_pss_params == NULL)
+ return 0;
+ rsa_pss_params->mask_gen.hash_algorithm_nid = maskgenhashalg_nid;
+ return 1;
+}
+
+int ossl_rsa_pss_params_30_set_saltlen(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int saltlen)
+{
+ if (rsa_pss_params == NULL)
+ return 0;
+ rsa_pss_params->salt_len = saltlen;
+ return 1;
+}
+
+int ossl_rsa_pss_params_30_set_trailerfield(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int trailerfield)
+{
+ if (rsa_pss_params == NULL)
+ return 0;
+ rsa_pss_params->trailer_field = trailerfield;
+ return 1;
+}
+
+int ossl_rsa_pss_params_30_hashalg(const RSA_PSS_PARAMS_30 *rsa_pss_params)
+{
+ if (rsa_pss_params == NULL)
+ return default_RSASSA_PSS_params.hash_algorithm_nid;
+ return rsa_pss_params->hash_algorithm_nid;
+}
+
+int ossl_rsa_pss_params_30_maskgenalg(const RSA_PSS_PARAMS_30 *rsa_pss_params)
+{
+ if (rsa_pss_params == NULL)
+ return default_RSASSA_PSS_params.mask_gen.algorithm_nid;
+ return rsa_pss_params->mask_gen.algorithm_nid;
+}
+
+int ossl_rsa_pss_params_30_maskgenhashalg(const RSA_PSS_PARAMS_30 *rsa_pss_params)
+{
+ if (rsa_pss_params == NULL)
+ return default_RSASSA_PSS_params.hash_algorithm_nid;
+ return rsa_pss_params->mask_gen.hash_algorithm_nid;
+}
+
+int ossl_rsa_pss_params_30_saltlen(const RSA_PSS_PARAMS_30 *rsa_pss_params)
+{
+ if (rsa_pss_params == NULL)
+ return default_RSASSA_PSS_params.salt_len;
+ return rsa_pss_params->salt_len;
+}
+
+int ossl_rsa_pss_params_30_trailerfield(const RSA_PSS_PARAMS_30 *rsa_pss_params)
+{
+ if (rsa_pss_params == NULL)
+ return default_RSASSA_PSS_params.trailer_field;
+ return rsa_pss_params->trailer_field;
+}
+
#if defined(_MSC_VER)
# pragma optimize("",on)
#endif
diff --git a/crypto/rsa/rsa_saos.c b/crypto/rsa/rsa_saos.c
index 8336f32f1687..58fa50785bd5 100644
--- a/crypto/rsa/rsa_saos.c
+++ b/crypto/rsa/rsa_saos.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
@@ -30,13 +36,12 @@ int RSA_sign_ASN1_OCTET_STRING(int type,
i = i2d_ASN1_OCTET_STRING(&sig, NULL);
j = RSA_size(rsa);
if (i > (j - RSA_PKCS1_PADDING_SIZE)) {
- RSAerr(RSA_F_RSA_SIGN_ASN1_OCTET_STRING,
- RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
return 0;
}
s = OPENSSL_malloc((unsigned int)j + 1);
if (s == NULL) {
- RSAerr(RSA_F_RSA_SIGN_ASN1_OCTET_STRING, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
return 0;
}
p = s;
@@ -62,14 +67,13 @@ int RSA_verify_ASN1_OCTET_STRING(int dtype,
ASN1_OCTET_STRING *sig = NULL;
if (siglen != (unsigned int)RSA_size(rsa)) {
- RSAerr(RSA_F_RSA_VERIFY_ASN1_OCTET_STRING,
- RSA_R_WRONG_SIGNATURE_LENGTH);
+ ERR_raise(ERR_LIB_RSA, RSA_R_WRONG_SIGNATURE_LENGTH);
return 0;
}
s = OPENSSL_malloc((unsigned int)siglen);
if (s == NULL) {
- RSAerr(RSA_F_RSA_VERIFY_ASN1_OCTET_STRING, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
i = RSA_public_decrypt((int)siglen, sigbuf, s, rsa, RSA_PKCS1_PADDING);
@@ -84,7 +88,7 @@ int RSA_verify_ASN1_OCTET_STRING(int dtype,
if (((unsigned int)sig->length != m_len) ||
(memcmp(m, sig->data, m_len) != 0)) {
- RSAerr(RSA_F_RSA_VERIFY_ASN1_OCTET_STRING, RSA_R_BAD_SIGNATURE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_BAD_SIGNATURE);
} else {
ret = 1;
}
diff --git a/crypto/rsa/rsa_schemes.c b/crypto/rsa/rsa_schemes.c
new file mode 100644
index 000000000000..98ab13956dbb
--- /dev/null
+++ b/crypto/rsa/rsa_schemes.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core.h>
+#include <openssl/core_names.h>
+#include <openssl/evp.h>
+#include <openssl/obj_mac.h>
+#include "internal/nelem.h"
+#include "crypto/rsa.h"
+
+static int meth2nid(const void *meth,
+ int (*meth_is_a)(const void *meth, const char *name),
+ const OSSL_ITEM *items, size_t items_n)
+{
+ size_t i;
+
+ if (meth != NULL)
+ for (i = 0; i < items_n; i++)
+ if (meth_is_a(meth, items[i].ptr))
+ return (int)items[i].id;
+ return NID_undef;
+}
+
+static const char *nid2name(int meth, const OSSL_ITEM *items, size_t items_n)
+{
+ size_t i;
+
+ for (i = 0; i < items_n; i++)
+ if (meth == (int)items[i].id)
+ return items[i].ptr;
+ return NULL;
+}
+
+/*
+ * The list of permitted hash functions are taken from
+ * https://tools.ietf.org/html/rfc8017#appendix-A.2.1:
+ *
+ * OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-sha1 PARAMETERS NULL }|
+ * { OID id-sha224 PARAMETERS NULL }|
+ * { OID id-sha256 PARAMETERS NULL }|
+ * { OID id-sha384 PARAMETERS NULL }|
+ * { OID id-sha512 PARAMETERS NULL }|
+ * { OID id-sha512-224 PARAMETERS NULL }|
+ * { OID id-sha512-256 PARAMETERS NULL },
+ * ... -- Allows for future expansion --
+ * }
+ */
+static const OSSL_ITEM oaeppss_name_nid_map[] = {
+ { NID_sha1, OSSL_DIGEST_NAME_SHA1 },
+ { NID_sha224, OSSL_DIGEST_NAME_SHA2_224 },
+ { NID_sha256, OSSL_DIGEST_NAME_SHA2_256 },
+ { NID_sha384, OSSL_DIGEST_NAME_SHA2_384 },
+ { NID_sha512, OSSL_DIGEST_NAME_SHA2_512 },
+ { NID_sha512_224, OSSL_DIGEST_NAME_SHA2_512_224 },
+ { NID_sha512_256, OSSL_DIGEST_NAME_SHA2_512_256 },
+};
+
+static int md_is_a(const void *md, const char *name)
+{
+ return EVP_MD_is_a(md, name);
+}
+
+int ossl_rsa_oaeppss_md2nid(const EVP_MD *md)
+{
+ return meth2nid(md, md_is_a,
+ oaeppss_name_nid_map, OSSL_NELEM(oaeppss_name_nid_map));
+}
+
+const char *ossl_rsa_oaeppss_nid2name(int md)
+{
+ return nid2name(md, oaeppss_name_nid_map, OSSL_NELEM(oaeppss_name_nid_map));
+}
+
+const char *ossl_rsa_mgf_nid2name(int mgf)
+{
+ if (mgf == NID_mgf1)
+ return SN_mgf1;
+ return NULL;
+}
diff --git a/crypto/rsa/rsa_sign.c b/crypto/rsa/rsa_sign.c
index 7fc69361bf0a..5745513c2f8e 100644
--- a/crypto/rsa/rsa_sign.c
+++ b/crypto/rsa/rsa_sign.c
@@ -1,81 +1,287 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/objects.h>
-#include <openssl/x509.h>
-#include "crypto/x509.h"
+#ifndef FIPS_MODULE
+# ifndef OPENSSL_NO_MD2
+# include <openssl/md2.h> /* uses MD2_DIGEST_LENGTH */
+# endif
+# ifndef OPENSSL_NO_MD4
+# include <openssl/md4.h> /* uses MD4_DIGEST_LENGTH */
+# endif
+# ifndef OPENSSL_NO_MD5
+# include <openssl/md5.h> /* uses MD5_DIGEST_LENGTH */
+# endif
+# ifndef OPENSSL_NO_MDC2
+# include <openssl/mdc2.h> /* uses MDC2_DIGEST_LENGTH */
+# endif
+# ifndef OPENSSL_NO_RMD160
+# include <openssl/ripemd.h> /* uses RIPEMD160_DIGEST_LENGTH */
+# endif
+#endif
+#include <openssl/sha.h> /* uses SHA???_DIGEST_LENGTH */
+#include "crypto/rsa.h"
#include "rsa_local.h"
+/*
+ * The general purpose ASN1 code is not available inside the FIPS provider.
+ * To remove the dependency RSASSA-PKCS1-v1_5 DigestInfo encodings can be
+ * treated as a special case by pregenerating the required ASN1 encoding.
+ * This encoding will also be shared by the default provider.
+ *
+ * The EMSA-PKCS1-v1_5 encoding method includes an ASN.1 value of type
+ * DigestInfo, where the type DigestInfo has the syntax
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm DigestAlgorithm,
+ * digest OCTET STRING
+ * }
+ *
+ * DigestAlgorithm ::= AlgorithmIdentifier {
+ * {PKCS1-v1-5DigestAlgorithms}
+ * }
+ *
+ * The AlgorithmIdentifier is a sequence containing the digest OID and
+ * parameters (a value of type NULL).
+ *
+ * The ENCODE_DIGESTINFO_SHA() and ENCODE_DIGESTINFO_MD() macros define an
+ * initialized array containing the DER encoded DigestInfo for the specified
+ * SHA or MD digest. The content of the OCTET STRING is not included.
+ * |name| is the digest name.
+ * |n| is last byte in the encoded OID for the digest.
+ * |sz| is the digest length in bytes. It must not be greater than 110.
+ */
+
+#define ASN1_SEQUENCE 0x30
+#define ASN1_OCTET_STRING 0x04
+#define ASN1_NULL 0x05
+#define ASN1_OID 0x06
+
+/* SHA OIDs are of the form: (2 16 840 1 101 3 4 2 |n|) */
+#define ENCODE_DIGESTINFO_SHA(name, n, sz) \
+static const unsigned char digestinfo_##name##_der[] = { \
+ ASN1_SEQUENCE, 0x11 + sz, \
+ ASN1_SEQUENCE, 0x0d, \
+ ASN1_OID, 0x09, 2 * 40 + 16, 0x86, 0x48, 1, 101, 3, 4, 2, n, \
+ ASN1_NULL, 0x00, \
+ ASN1_OCTET_STRING, sz \
+};
+
+/* MD2, MD4 and MD5 OIDs are of the form: (1 2 840 113549 2 |n|) */
+#define ENCODE_DIGESTINFO_MD(name, n, sz) \
+static const unsigned char digestinfo_##name##_der[] = { \
+ ASN1_SEQUENCE, 0x10 + sz, \
+ ASN1_SEQUENCE, 0x0c, \
+ ASN1_OID, 0x08, 1 * 40 + 2, 0x86, 0x48, 0x86, 0xf7, 0x0d, 2, n, \
+ ASN1_NULL, 0x00, \
+ ASN1_OCTET_STRING, sz \
+};
+
+#ifndef FIPS_MODULE
+# ifndef OPENSSL_NO_MD2
+ENCODE_DIGESTINFO_MD(md2, 0x02, MD2_DIGEST_LENGTH)
+# endif
+# ifndef OPENSSL_NO_MD4
+ENCODE_DIGESTINFO_MD(md4, 0x03, MD4_DIGEST_LENGTH)
+# endif
+# ifndef OPENSSL_NO_MD5
+ENCODE_DIGESTINFO_MD(md5, 0x05, MD5_DIGEST_LENGTH)
+# endif
+# ifndef OPENSSL_NO_MDC2
+/* MDC-2 (2 5 8 3 101) */
+static const unsigned char digestinfo_mdc2_der[] = {
+ ASN1_SEQUENCE, 0x0c + MDC2_DIGEST_LENGTH,
+ ASN1_SEQUENCE, 0x08,
+ ASN1_OID, 0x04, 2 * 40 + 5, 8, 3, 101,
+ ASN1_NULL, 0x00,
+ ASN1_OCTET_STRING, MDC2_DIGEST_LENGTH
+};
+# endif
+# ifndef OPENSSL_NO_RMD160
+/* RIPEMD160 (1 3 36 3 2 1) */
+static const unsigned char digestinfo_ripemd160_der[] = {
+ ASN1_SEQUENCE, 0x0d + RIPEMD160_DIGEST_LENGTH,
+ ASN1_SEQUENCE, 0x09,
+ ASN1_OID, 0x05, 1 * 40 + 3, 36, 3, 2, 1,
+ ASN1_NULL, 0x00,
+ ASN1_OCTET_STRING, RIPEMD160_DIGEST_LENGTH
+};
+# endif
+#endif /* FIPS_MODULE */
+
+/* SHA-1 (1 3 14 3 2 26) */
+static const unsigned char digestinfo_sha1_der[] = {
+ ASN1_SEQUENCE, 0x0d + SHA_DIGEST_LENGTH,
+ ASN1_SEQUENCE, 0x09,
+ ASN1_OID, 0x05, 1 * 40 + 3, 14, 3, 2, 26,
+ ASN1_NULL, 0x00,
+ ASN1_OCTET_STRING, SHA_DIGEST_LENGTH
+};
+
+ENCODE_DIGESTINFO_SHA(sha256, 0x01, SHA256_DIGEST_LENGTH)
+ENCODE_DIGESTINFO_SHA(sha384, 0x02, SHA384_DIGEST_LENGTH)
+ENCODE_DIGESTINFO_SHA(sha512, 0x03, SHA512_DIGEST_LENGTH)
+ENCODE_DIGESTINFO_SHA(sha224, 0x04, SHA224_DIGEST_LENGTH)
+ENCODE_DIGESTINFO_SHA(sha512_224, 0x05, SHA224_DIGEST_LENGTH)
+ENCODE_DIGESTINFO_SHA(sha512_256, 0x06, SHA256_DIGEST_LENGTH)
+ENCODE_DIGESTINFO_SHA(sha3_224, 0x07, SHA224_DIGEST_LENGTH)
+ENCODE_DIGESTINFO_SHA(sha3_256, 0x08, SHA256_DIGEST_LENGTH)
+ENCODE_DIGESTINFO_SHA(sha3_384, 0x09, SHA384_DIGEST_LENGTH)
+ENCODE_DIGESTINFO_SHA(sha3_512, 0x0a, SHA512_DIGEST_LENGTH)
+
+#define MD_CASE(name) \
+ case NID_##name: \
+ *len = sizeof(digestinfo_##name##_der); \
+ return digestinfo_##name##_der;
+
+const unsigned char *ossl_rsa_digestinfo_encoding(int md_nid, size_t *len)
+{
+ switch (md_nid) {
+#ifndef FIPS_MODULE
+# ifndef OPENSSL_NO_MDC2
+ MD_CASE(mdc2)
+# endif
+# ifndef OPENSSL_NO_MD2
+ MD_CASE(md2)
+# endif
+# ifndef OPENSSL_NO_MD4
+ MD_CASE(md4)
+# endif
+# ifndef OPENSSL_NO_MD5
+ MD_CASE(md5)
+# endif
+# ifndef OPENSSL_NO_RMD160
+ MD_CASE(ripemd160)
+# endif
+#endif /* FIPS_MODULE */
+ MD_CASE(sha1)
+ MD_CASE(sha224)
+ MD_CASE(sha256)
+ MD_CASE(sha384)
+ MD_CASE(sha512)
+ MD_CASE(sha512_224)
+ MD_CASE(sha512_256)
+ MD_CASE(sha3_224)
+ MD_CASE(sha3_256)
+ MD_CASE(sha3_384)
+ MD_CASE(sha3_512)
+ default:
+ return NULL;
+ }
+}
+
+#define MD_NID_CASE(name, sz) \
+ case NID_##name: \
+ return sz;
+
+static int digest_sz_from_nid(int nid)
+{
+ switch (nid) {
+#ifndef FIPS_MODULE
+# ifndef OPENSSL_NO_MDC2
+ MD_NID_CASE(mdc2, MDC2_DIGEST_LENGTH)
+# endif
+# ifndef OPENSSL_NO_MD2
+ MD_NID_CASE(md2, MD2_DIGEST_LENGTH)
+# endif
+# ifndef OPENSSL_NO_MD4
+ MD_NID_CASE(md4, MD4_DIGEST_LENGTH)
+# endif
+# ifndef OPENSSL_NO_MD5
+ MD_NID_CASE(md5, MD5_DIGEST_LENGTH)
+# endif
+# ifndef OPENSSL_NO_RMD160
+ MD_NID_CASE(ripemd160, RIPEMD160_DIGEST_LENGTH)
+# endif
+#endif /* FIPS_MODULE */
+ MD_NID_CASE(sha1, SHA_DIGEST_LENGTH)
+ MD_NID_CASE(sha224, SHA224_DIGEST_LENGTH)
+ MD_NID_CASE(sha256, SHA256_DIGEST_LENGTH)
+ MD_NID_CASE(sha384, SHA384_DIGEST_LENGTH)
+ MD_NID_CASE(sha512, SHA512_DIGEST_LENGTH)
+ MD_NID_CASE(sha512_224, SHA224_DIGEST_LENGTH)
+ MD_NID_CASE(sha512_256, SHA256_DIGEST_LENGTH)
+ MD_NID_CASE(sha3_224, SHA224_DIGEST_LENGTH)
+ MD_NID_CASE(sha3_256, SHA256_DIGEST_LENGTH)
+ MD_NID_CASE(sha3_384, SHA384_DIGEST_LENGTH)
+ MD_NID_CASE(sha3_512, SHA512_DIGEST_LENGTH)
+ default:
+ return 0;
+ }
+}
+
+
/* Size of an SSL signature: MD5+SHA1 */
#define SSL_SIG_LENGTH 36
/*
- * encode_pkcs1 encodes a DigestInfo prefix of hash |type| and digest |m|, as
+ * Encodes a DigestInfo prefix of hash |type| and digest |m|, as
* described in EMSA-PKCS1-v1_5-ENCODE, RFC 3447 section 9.2 step 2. This
* encodes the DigestInfo (T and tLen) but does not add the padding.
*
* On success, it returns one and sets |*out| to a newly allocated buffer
* containing the result and |*out_len| to its length. The caller must free
- * |*out| with |OPENSSL_free|. Otherwise, it returns zero.
+ * |*out| with OPENSSL_free(). Otherwise, it returns zero.
*/
-static int encode_pkcs1(unsigned char **out, int *out_len, int type,
- const unsigned char *m, unsigned int m_len)
+static int encode_pkcs1(unsigned char **out, size_t *out_len, int type,
+ const unsigned char *m, size_t m_len)
{
- X509_SIG sig;
- X509_ALGOR algor;
- ASN1_TYPE parameter;
- ASN1_OCTET_STRING digest;
- uint8_t *der = NULL;
- int len;
-
- sig.algor = &algor;
- sig.algor->algorithm = OBJ_nid2obj(type);
- if (sig.algor->algorithm == NULL) {
- RSAerr(RSA_F_ENCODE_PKCS1, RSA_R_UNKNOWN_ALGORITHM_TYPE);
+ size_t di_prefix_len, dig_info_len;
+ const unsigned char *di_prefix;
+ unsigned char *dig_info;
+
+ if (type == NID_undef) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE);
return 0;
}
- if (OBJ_length(sig.algor->algorithm) == 0) {
- RSAerr(RSA_F_ENCODE_PKCS1,
- RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
+ di_prefix = ossl_rsa_digestinfo_encoding(type, &di_prefix_len);
+ if (di_prefix == NULL) {
+ ERR_raise(ERR_LIB_RSA,
+ RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
return 0;
}
- parameter.type = V_ASN1_NULL;
- parameter.value.ptr = NULL;
- sig.algor->parameter = &parameter;
-
- sig.digest = &digest;
- sig.digest->data = (unsigned char *)m;
- sig.digest->length = m_len;
-
- len = i2d_X509_SIG(&sig, &der);
- if (len < 0)
+ dig_info_len = di_prefix_len + m_len;
+ dig_info = OPENSSL_malloc(dig_info_len);
+ if (dig_info == NULL) {
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
return 0;
+ }
+ memcpy(dig_info, di_prefix, di_prefix_len);
+ memcpy(dig_info + di_prefix_len, m, m_len);
- *out = der;
- *out_len = len;
+ *out = dig_info;
+ *out_len = dig_info_len;
return 1;
}
int RSA_sign(int type, const unsigned char *m, unsigned int m_len,
unsigned char *sigret, unsigned int *siglen, RSA *rsa)
{
- int encrypt_len, encoded_len = 0, ret = 0;
+ int encrypt_len, ret = 0;
+ size_t encoded_len = 0;
unsigned char *tmps = NULL;
const unsigned char *encoded = NULL;
- if (rsa->meth->rsa_sign) {
- return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa);
- }
+#ifndef FIPS_MODULE
+ if (rsa->meth->rsa_sign != NULL)
+ return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa) > 0;
+#endif /* FIPS_MODULE */
/* Compute the encoded digest. */
if (type == NID_md5_sha1) {
@@ -85,7 +291,7 @@ int RSA_sign(int type, const unsigned char *m, unsigned int m_len,
* RSASSA-PKCS1-v1_5.
*/
if (m_len != SSL_SIG_LENGTH) {
- RSAerr(RSA_F_RSA_SIGN, RSA_R_INVALID_MESSAGE_LENGTH);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MESSAGE_LENGTH);
return 0;
}
encoded_len = SSL_SIG_LENGTH;
@@ -96,11 +302,11 @@ int RSA_sign(int type, const unsigned char *m, unsigned int m_len,
encoded = tmps;
}
- if (encoded_len > RSA_size(rsa) - RSA_PKCS1_PADDING_SIZE) {
- RSAerr(RSA_F_RSA_SIGN, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
+ if (encoded_len + RSA_PKCS1_PADDING_SIZE > (size_t)RSA_size(rsa)) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
goto err;
}
- encrypt_len = RSA_private_encrypt(encoded_len, encoded, sigret, rsa,
+ encrypt_len = RSA_private_encrypt((int)encoded_len, encoded, sigret, rsa,
RSA_PKCS1_PADDING);
if (encrypt_len <= 0)
goto err;
@@ -109,42 +315,46 @@ int RSA_sign(int type, const unsigned char *m, unsigned int m_len,
ret = 1;
err:
- OPENSSL_clear_free(tmps, (size_t)encoded_len);
+ OPENSSL_clear_free(tmps, encoded_len);
return ret;
}
/*
- * int_rsa_verify verifies an RSA signature in |sigbuf| using |rsa|. It may be
- * called in two modes. If |rm| is NULL, it verifies the signature for digest
- * |m|. Otherwise, it recovers the digest from the signature, writing the digest
- * to |rm| and the length to |*prm_len|. |type| is the NID of the digest
- * algorithm to use. It returns one on successful verification and zero
- * otherwise.
+ * Verify an RSA signature in |sigbuf| using |rsa|.
+ * |type| is the NID of the digest algorithm to use.
+ * If |rm| is NULL, it verifies the signature for digest |m|, otherwise
+ * it recovers the digest from the signature, writing the digest to |rm| and
+ * the length to |*prm_len|.
+ *
+ * It returns one on successful verification or zero otherwise.
*/
-int int_rsa_verify(int type, const unsigned char *m, unsigned int m_len,
- unsigned char *rm, size_t *prm_len,
- const unsigned char *sigbuf, size_t siglen, RSA *rsa)
+int ossl_rsa_verify(int type, const unsigned char *m, unsigned int m_len,
+ unsigned char *rm, size_t *prm_len,
+ const unsigned char *sigbuf, size_t siglen, RSA *rsa)
{
- int decrypt_len, ret = 0, encoded_len = 0;
+ int len, ret = 0;
+ size_t decrypt_len, encoded_len = 0;
unsigned char *decrypt_buf = NULL, *encoded = NULL;
if (siglen != (size_t)RSA_size(rsa)) {
- RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_WRONG_SIGNATURE_LENGTH);
+ ERR_raise(ERR_LIB_RSA, RSA_R_WRONG_SIGNATURE_LENGTH);
return 0;
}
/* Recover the encoded digest. */
decrypt_buf = OPENSSL_malloc(siglen);
if (decrypt_buf == NULL) {
- RSAerr(RSA_F_INT_RSA_VERIFY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
- decrypt_len = RSA_public_decrypt((int)siglen, sigbuf, decrypt_buf, rsa,
- RSA_PKCS1_PADDING);
- if (decrypt_len <= 0)
+ len = RSA_public_decrypt((int)siglen, sigbuf, decrypt_buf, rsa,
+ RSA_PKCS1_PADDING);
+ if (len <= 0)
goto err;
+ decrypt_len = len;
+#ifndef FIPS_MODULE
if (type == NID_md5_sha1) {
/*
* NID_md5_sha1 corresponds to the MD5/SHA1 combination in TLS 1.1 and
@@ -152,7 +362,7 @@ int int_rsa_verify(int type, const unsigned char *m, unsigned int m_len,
* RSASSA-PKCS1-v1_5.
*/
if (decrypt_len != SSL_SIG_LENGTH) {
- RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_BAD_SIGNATURE);
goto err;
}
@@ -161,12 +371,12 @@ int int_rsa_verify(int type, const unsigned char *m, unsigned int m_len,
*prm_len = SSL_SIG_LENGTH;
} else {
if (m_len != SSL_SIG_LENGTH) {
- RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_MESSAGE_LENGTH);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MESSAGE_LENGTH);
goto err;
}
if (memcmp(decrypt_buf, m, SSL_SIG_LENGTH) != 0) {
- RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_BAD_SIGNATURE);
goto err;
}
}
@@ -181,31 +391,31 @@ int int_rsa_verify(int type, const unsigned char *m, unsigned int m_len,
*prm_len = 16;
} else {
if (m_len != 16) {
- RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_MESSAGE_LENGTH);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MESSAGE_LENGTH);
goto err;
}
if (memcmp(m, decrypt_buf + 2, 16) != 0) {
- RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_BAD_SIGNATURE);
goto err;
}
}
- } else {
+ } else
+#endif /* FIPS_MODULE */
+ {
/*
* If recovering the digest, extract a digest-sized output from the end
* of |decrypt_buf| for |encode_pkcs1|, then compare the decryption
* output as in a standard verification.
*/
if (rm != NULL) {
- const EVP_MD *md = EVP_get_digestbynid(type);
- if (md == NULL) {
- RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_UNKNOWN_ALGORITHM_TYPE);
- goto err;
- }
+ len = digest_sz_from_nid(type);
- m_len = EVP_MD_size(md);
- if (m_len > (size_t)decrypt_len) {
- RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_DIGEST_LENGTH);
+ if (len <= 0)
+ goto err;
+ m_len = (unsigned int)len;
+ if (m_len > decrypt_len) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH);
goto err;
}
m = decrypt_buf + decrypt_len - m_len;
@@ -216,8 +426,8 @@ int int_rsa_verify(int type, const unsigned char *m, unsigned int m_len,
goto err;
if (encoded_len != decrypt_len
- || memcmp(encoded, decrypt_buf, encoded_len) != 0) {
- RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
+ || memcmp(encoded, decrypt_buf, encoded_len) != 0) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_BAD_SIGNATURE);
goto err;
}
@@ -231,7 +441,7 @@ int int_rsa_verify(int type, const unsigned char *m, unsigned int m_len,
ret = 1;
err:
- OPENSSL_clear_free(encoded, (size_t)encoded_len);
+ OPENSSL_clear_free(encoded, encoded_len);
OPENSSL_clear_free(decrypt_buf, siglen);
return ret;
}
@@ -240,9 +450,8 @@ int RSA_verify(int type, const unsigned char *m, unsigned int m_len,
const unsigned char *sigbuf, unsigned int siglen, RSA *rsa)
{
- if (rsa->meth->rsa_verify) {
+ if (rsa->meth->rsa_verify != NULL)
return rsa->meth->rsa_verify(type, m, m_len, sigbuf, siglen, rsa);
- }
- return int_rsa_verify(type, m, m_len, NULL, NULL, sigbuf, siglen, rsa);
+ return ossl_rsa_verify(type, m, m_len, NULL, NULL, sigbuf, siglen, rsa);
}
diff --git a/crypto/rsa/rsa_sp800_56b_check.c b/crypto/rsa/rsa_sp800_56b_check.c
new file mode 100644
index 000000000000..fc8f19b48770
--- /dev/null
+++ b/crypto/rsa/rsa_sp800_56b_check.c
@@ -0,0 +1,437 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2018-2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/bn.h>
+#include "crypto/bn.h"
+#include "rsa_local.h"
+
+/*
+ * Part of the RSA keypair test.
+ * Check the Chinese Remainder Theorem components are valid.
+ *
+ * See SP800-5bBr1
+ * 6.4.1.2.3: rsakpv1-crt Step 7
+ * 6.4.1.3.3: rsakpv2-crt Step 7
+ */
+int ossl_rsa_check_crt_components(const RSA *rsa, BN_CTX *ctx)
+{
+ int ret = 0;
+ BIGNUM *r = NULL, *p1 = NULL, *q1 = NULL;
+
+ /* check if only some of the crt components are set */
+ if (rsa->dmp1 == NULL || rsa->dmq1 == NULL || rsa->iqmp == NULL) {
+ if (rsa->dmp1 != NULL || rsa->dmq1 != NULL || rsa->iqmp != NULL)
+ return 0;
+ return 1; /* return ok if all components are NULL */
+ }
+
+ BN_CTX_start(ctx);
+ r = BN_CTX_get(ctx);
+ p1 = BN_CTX_get(ctx);
+ q1 = BN_CTX_get(ctx);
+ if (q1 != NULL) {
+ BN_set_flags(r, BN_FLG_CONSTTIME);
+ BN_set_flags(p1, BN_FLG_CONSTTIME);
+ BN_set_flags(q1, BN_FLG_CONSTTIME);
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+ ret = ret
+ /* p1 = p -1 */
+ && (BN_copy(p1, rsa->p) != NULL)
+ && BN_sub_word(p1, 1)
+ /* q1 = q - 1 */
+ && (BN_copy(q1, rsa->q) != NULL)
+ && BN_sub_word(q1, 1)
+ /* (a) 1 < dP < (p – 1). */
+ && (BN_cmp(rsa->dmp1, BN_value_one()) > 0)
+ && (BN_cmp(rsa->dmp1, p1) < 0)
+ /* (b) 1 < dQ < (q - 1). */
+ && (BN_cmp(rsa->dmq1, BN_value_one()) > 0)
+ && (BN_cmp(rsa->dmq1, q1) < 0)
+ /* (c) 1 < qInv < p */
+ && (BN_cmp(rsa->iqmp, BN_value_one()) > 0)
+ && (BN_cmp(rsa->iqmp, rsa->p) < 0)
+ /* (d) 1 = (dP . e) mod (p - 1)*/
+ && BN_mod_mul(r, rsa->dmp1, rsa->e, p1, ctx)
+ && BN_is_one(r)
+ /* (e) 1 = (dQ . e) mod (q - 1) */
+ && BN_mod_mul(r, rsa->dmq1, rsa->e, q1, ctx)
+ && BN_is_one(r)
+ /* (f) 1 = (qInv . q) mod p */
+ && BN_mod_mul(r, rsa->iqmp, rsa->q, rsa->p, ctx)
+ && BN_is_one(r);
+ BN_clear(r);
+ BN_clear(p1);
+ BN_clear(q1);
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+/*
+ * Part of the RSA keypair test.
+ * Check that (√2)(2^(nbits/2 - 1) <= p <= 2^(nbits/2) - 1
+ *
+ * See SP800-5bBr1 6.4.1.2.1 Part 5 (c) & (g) - used for both p and q.
+ *
+ * (√2)(2^(nbits/2 - 1) = (√2/2)(2^(nbits/2))
+ */
+int ossl_rsa_check_prime_factor_range(const BIGNUM *p, int nbits, BN_CTX *ctx)
+{
+ int ret = 0;
+ BIGNUM *low;
+ int shift;
+
+ nbits >>= 1;
+ shift = nbits - BN_num_bits(&ossl_bn_inv_sqrt_2);
+
+ /* Upper bound check */
+ if (BN_num_bits(p) != nbits)
+ return 0;
+
+ BN_CTX_start(ctx);
+ low = BN_CTX_get(ctx);
+ if (low == NULL)
+ goto err;
+
+ /* set low = (√2)(2^(nbits/2 - 1) */
+ if (!BN_copy(low, &ossl_bn_inv_sqrt_2))
+ goto err;
+
+ if (shift >= 0) {
+ /*
+ * We don't have all the bits. ossl_bn_inv_sqrt_2 contains a rounded up
+ * value, so there is a very low probability that we'll reject a valid
+ * value.
+ */
+ if (!BN_lshift(low, low, shift))
+ goto err;
+ } else if (!BN_rshift(low, low, -shift)) {
+ goto err;
+ }
+ if (BN_cmp(p, low) <= 0)
+ goto err;
+ ret = 1;
+err:
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+/*
+ * Part of the RSA keypair test.
+ * Check the prime factor (for either p or q)
+ * i.e: p is prime AND GCD(p - 1, e) = 1
+ *
+ * See SP800-56Br1 6.4.1.2.3 Step 5 (a to d) & (e to h).
+ */
+int ossl_rsa_check_prime_factor(BIGNUM *p, BIGNUM *e, int nbits, BN_CTX *ctx)
+{
+ int ret = 0;
+ BIGNUM *p1 = NULL, *gcd = NULL;
+
+ /* (Steps 5 a-b) prime test */
+ if (BN_check_prime(p, ctx, NULL) != 1
+ /* (Step 5c) (√2)(2^(nbits/2 - 1) <= p <= 2^(nbits/2 - 1) */
+ || ossl_rsa_check_prime_factor_range(p, nbits, ctx) != 1)
+ return 0;
+
+ BN_CTX_start(ctx);
+ p1 = BN_CTX_get(ctx);
+ gcd = BN_CTX_get(ctx);
+ if (gcd != NULL) {
+ BN_set_flags(p1, BN_FLG_CONSTTIME);
+ BN_set_flags(gcd, BN_FLG_CONSTTIME);
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+ ret = ret
+ /* (Step 5d) GCD(p-1, e) = 1 */
+ && (BN_copy(p1, p) != NULL)
+ && BN_sub_word(p1, 1)
+ && BN_gcd(gcd, p1, e, ctx)
+ && BN_is_one(gcd);
+
+ BN_clear(p1);
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+/*
+ * See SP800-56Br1 6.4.1.2.3 Part 6(a-b) Check the private exponent d
+ * satisfies:
+ * (Step 6a) 2^(nBit/2) < d < LCM(p–1, q–1).
+ * (Step 6b) 1 = (d*e) mod LCM(p–1, q–1)
+ */
+int ossl_rsa_check_private_exponent(const RSA *rsa, int nbits, BN_CTX *ctx)
+{
+ int ret;
+ BIGNUM *r, *p1, *q1, *lcm, *p1q1, *gcd;
+
+ /* (Step 6a) 2^(nbits/2) < d */
+ if (BN_num_bits(rsa->d) <= (nbits >> 1))
+ return 0;
+
+ BN_CTX_start(ctx);
+ r = BN_CTX_get(ctx);
+ p1 = BN_CTX_get(ctx);
+ q1 = BN_CTX_get(ctx);
+ lcm = BN_CTX_get(ctx);
+ p1q1 = BN_CTX_get(ctx);
+ gcd = BN_CTX_get(ctx);
+ if (gcd != NULL) {
+ BN_set_flags(r, BN_FLG_CONSTTIME);
+ BN_set_flags(p1, BN_FLG_CONSTTIME);
+ BN_set_flags(q1, BN_FLG_CONSTTIME);
+ BN_set_flags(lcm, BN_FLG_CONSTTIME);
+ BN_set_flags(p1q1, BN_FLG_CONSTTIME);
+ BN_set_flags(gcd, BN_FLG_CONSTTIME);
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+ ret = (ret
+ /* LCM(p - 1, q - 1) */
+ && (ossl_rsa_get_lcm(ctx, rsa->p, rsa->q, lcm, gcd, p1, q1,
+ p1q1) == 1)
+ /* (Step 6a) d < LCM(p - 1, q - 1) */
+ && (BN_cmp(rsa->d, lcm) < 0)
+ /* (Step 6b) 1 = (e . d) mod LCM(p - 1, q - 1) */
+ && BN_mod_mul(r, rsa->e, rsa->d, lcm, ctx)
+ && BN_is_one(r));
+
+ BN_clear(r);
+ BN_clear(p1);
+ BN_clear(q1);
+ BN_clear(lcm);
+ BN_clear(gcd);
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+/*
+ * Check exponent is odd.
+ * For FIPS also check the bit length is in the range [17..256]
+ */
+int ossl_rsa_check_public_exponent(const BIGNUM *e)
+{
+#ifdef FIPS_MODULE
+ int bitlen;
+
+ bitlen = BN_num_bits(e);
+ return (BN_is_odd(e) && bitlen > 16 && bitlen < 257);
+#else
+ /* Allow small exponents larger than 1 for legacy purposes */
+ return BN_is_odd(e) && BN_cmp(e, BN_value_one()) > 0;
+#endif /* FIPS_MODULE */
+}
+
+/*
+ * SP800-56Br1 6.4.1.2.1 (Step 5i): |p - q| > 2^(nbits/2 - 100)
+ * i.e- numbits(p-q-1) > (nbits/2 -100)
+ */
+int ossl_rsa_check_pminusq_diff(BIGNUM *diff, const BIGNUM *p, const BIGNUM *q,
+ int nbits)
+{
+ int bitlen = (nbits >> 1) - 100;
+
+ if (!BN_sub(diff, p, q))
+ return -1;
+ BN_set_negative(diff, 0);
+
+ if (BN_is_zero(diff))
+ return 0;
+
+ if (!BN_sub_word(diff, 1))
+ return -1;
+ return (BN_num_bits(diff) > bitlen);
+}
+
+/*
+ * return LCM(p-1, q-1)
+ *
+ * Caller should ensure that lcm, gcd, p1, q1, p1q1 are flagged with
+ * BN_FLG_CONSTTIME.
+ */
+int ossl_rsa_get_lcm(BN_CTX *ctx, const BIGNUM *p, const BIGNUM *q,
+ BIGNUM *lcm, BIGNUM *gcd, BIGNUM *p1, BIGNUM *q1,
+ BIGNUM *p1q1)
+{
+ return BN_sub(p1, p, BN_value_one()) /* p-1 */
+ && BN_sub(q1, q, BN_value_one()) /* q-1 */
+ && BN_mul(p1q1, p1, q1, ctx) /* (p-1)(q-1) */
+ && BN_gcd(gcd, p1, q1, ctx)
+ && BN_div(lcm, NULL, p1q1, gcd, ctx); /* LCM((p-1, q-1)) */
+}
+
+/*
+ * SP800-56Br1 6.4.2.2 Partial Public Key Validation for RSA refers to
+ * SP800-89 5.3.3 (Explicit) Partial Public Key Validation for RSA
+ * caveat is that the modulus must be as specified in SP800-56Br1
+ */
+int ossl_rsa_sp800_56b_check_public(const RSA *rsa)
+{
+ int ret = 0, status;
+ int nbits;
+ BN_CTX *ctx = NULL;
+ BIGNUM *gcd = NULL;
+
+ if (rsa->n == NULL || rsa->e == NULL)
+ return 0;
+
+ nbits = BN_num_bits(rsa->n);
+#ifdef FIPS_MODULE
+ /*
+ * (Step a): modulus must be 2048 or 3072 (caveat from SP800-56Br1)
+ * NOTE: changed to allow keys >= 2048
+ */
+ if (!ossl_rsa_sp800_56b_validate_strength(nbits, -1)) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+#endif
+ if (!BN_is_odd(rsa->n)) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MODULUS);
+ return 0;
+ }
+ /* (Steps b-c): 2^16 < e < 2^256, n and e must be odd */
+ if (!ossl_rsa_check_public_exponent(rsa->e)) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_PUB_EXPONENT_OUT_OF_RANGE);
+ return 0;
+ }
+
+ ctx = BN_CTX_new_ex(rsa->libctx);
+ gcd = BN_new();
+ if (ctx == NULL || gcd == NULL)
+ goto err;
+
+ /* (Steps d-f):
+ * The modulus is composite, but not a power of a prime.
+ * The modulus has no factors smaller than 752.
+ */
+ if (!BN_gcd(gcd, rsa->n, ossl_bn_get0_small_factors(), ctx)
+ || !BN_is_one(gcd)) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MODULUS);
+ goto err;
+ }
+
+ ret = ossl_bn_miller_rabin_is_prime(rsa->n, 0, ctx, NULL, 1, &status);
+#ifdef FIPS_MODULE
+ if (ret != 1 || status != BN_PRIMETEST_COMPOSITE_NOT_POWER_OF_PRIME) {
+#else
+ if (ret != 1 || (status != BN_PRIMETEST_COMPOSITE_NOT_POWER_OF_PRIME
+ && (nbits >= RSA_MIN_MODULUS_BITS
+ || status != BN_PRIMETEST_COMPOSITE_WITH_FACTOR))) {
+#endif
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MODULUS);
+ ret = 0;
+ goto err;
+ }
+
+ ret = 1;
+err:
+ BN_free(gcd);
+ BN_CTX_free(ctx);
+ return ret;
+}
+
+/*
+ * Perform validation of the RSA private key to check that 0 < D < N.
+ */
+int ossl_rsa_sp800_56b_check_private(const RSA *rsa)
+{
+ if (rsa->d == NULL || rsa->n == NULL)
+ return 0;
+ return BN_cmp(rsa->d, BN_value_one()) >= 0 && BN_cmp(rsa->d, rsa->n) < 0;
+}
+
+/*
+ * RSA key pair validation.
+ *
+ * SP800-56Br1.
+ * 6.4.1.2 "RSAKPV1 Family: RSA Key - Pair Validation with a Fixed Exponent"
+ * 6.4.1.3 "RSAKPV2 Family: RSA Key - Pair Validation with a Random Exponent"
+ *
+ * It uses:
+ * 6.4.1.2.3 "rsakpv1 - crt"
+ * 6.4.1.3.3 "rsakpv2 - crt"
+ */
+int ossl_rsa_sp800_56b_check_keypair(const RSA *rsa, const BIGNUM *efixed,
+ int strength, int nbits)
+{
+ int ret = 0;
+ BN_CTX *ctx = NULL;
+ BIGNUM *r = NULL;
+
+ if (rsa->p == NULL
+ || rsa->q == NULL
+ || rsa->e == NULL
+ || rsa->d == NULL
+ || rsa->n == NULL) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_REQUEST);
+ return 0;
+ }
+ /* (Step 1): Check Ranges */
+ if (!ossl_rsa_sp800_56b_validate_strength(nbits, strength))
+ return 0;
+
+ /* If the exponent is known */
+ if (efixed != NULL) {
+ /* (2): Check fixed exponent matches public exponent. */
+ if (BN_cmp(efixed, rsa->e) != 0) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_REQUEST);
+ return 0;
+ }
+ }
+ /* (Step 1.c): e is odd integer 65537 <= e < 2^256 */
+ if (!ossl_rsa_check_public_exponent(rsa->e)) {
+ /* exponent out of range */
+ ERR_raise(ERR_LIB_RSA, RSA_R_PUB_EXPONENT_OUT_OF_RANGE);
+ return 0;
+ }
+ /* (Step 3.b): check the modulus */
+ if (nbits != BN_num_bits(rsa->n)) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_KEYPAIR);
+ return 0;
+ }
+
+ ctx = BN_CTX_new_ex(rsa->libctx);
+ if (ctx == NULL)
+ return 0;
+
+ BN_CTX_start(ctx);
+ r = BN_CTX_get(ctx);
+ if (r == NULL || !BN_mul(r, rsa->p, rsa->q, ctx))
+ goto err;
+ /* (Step 4.c): Check n = pq */
+ if (BN_cmp(rsa->n, r) != 0) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_REQUEST);
+ goto err;
+ }
+
+ /* (Step 5): check prime factors p & q */
+ ret = ossl_rsa_check_prime_factor(rsa->p, rsa->e, nbits, ctx)
+ && ossl_rsa_check_prime_factor(rsa->q, rsa->e, nbits, ctx)
+ && (ossl_rsa_check_pminusq_diff(r, rsa->p, rsa->q, nbits) > 0)
+ /* (Step 6): Check the private exponent d */
+ && ossl_rsa_check_private_exponent(rsa, nbits, ctx)
+ /* 6.4.1.2.3 (Step 7): Check the CRT components */
+ && ossl_rsa_check_crt_components(rsa, ctx);
+ if (ret != 1)
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_KEYPAIR);
+
+err:
+ BN_clear(r);
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ return ret;
+}
diff --git a/crypto/rsa/rsa_sp800_56b_gen.c b/crypto/rsa/rsa_sp800_56b_gen.c
new file mode 100644
index 000000000000..df2240555bfd
--- /dev/null
+++ b/crypto/rsa/rsa_sp800_56b_gen.c
@@ -0,0 +1,440 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2018-2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/bn.h>
+#include <openssl/core.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include "crypto/bn.h"
+#include "crypto/security_bits.h"
+#include "rsa_local.h"
+
+#define RSA_FIPS1864_MIN_KEYGEN_KEYSIZE 2048
+#define RSA_FIPS1864_MIN_KEYGEN_STRENGTH 112
+
+/*
+ * Generate probable primes 'p' & 'q'. See FIPS 186-4 Section B.3.6
+ * "Generation of Probable Primes with Conditions Based on Auxiliary Probable
+ * Primes".
+ *
+ * Params:
+ * rsa Object used to store primes p & q.
+ * test Object used for CAVS testing only.that contains..
+ * p1, p2 The returned auxiliary primes for p.
+ * If NULL they are not returned.
+ * Xpout An optionally returned random number used during generation of p.
+ * Xp An optional passed in value (that is random number used during
+ * generation of p).
+ * Xp1, Xp2 Optionally passed in randomly generated numbers from which
+ * auxiliary primes p1 & p2 are calculated. If NULL these values
+ * are generated internally.
+ * q1, q2 The returned auxiliary primes for q.
+ * If NULL they are not returned.
+ * Xqout An optionally returned random number used during generation of q.
+ * Xq An optional passed in value (that is random number used during
+ * generation of q).
+ * Xq1, Xq2 Optionally passed in randomly generated numbers from which
+ * auxiliary primes q1 & q2 are calculated. If NULL these values
+ * are generated internally.
+ * nbits The key size in bits (The size of the modulus n).
+ * e The public exponent.
+ * ctx A BN_CTX object.
+ * cb An optional BIGNUM callback.
+ * Returns: 1 if successful, or 0 otherwise.
+ * Notes:
+ * p1, p2, q1, q2, Xpout, Xqout are returned if they are not NULL.
+ * Xp, Xp1, Xp2, Xq, Xq1, Xq2 are optionally passed in.
+ * (Required for CAVS testing).
+ */
+int ossl_rsa_fips186_4_gen_prob_primes(RSA *rsa, RSA_ACVP_TEST *test,
+ int nbits, const BIGNUM *e, BN_CTX *ctx,
+ BN_GENCB *cb)
+{
+ int ret = 0, ok;
+ /* Temp allocated BIGNUMS */
+ BIGNUM *Xpo = NULL, *Xqo = NULL, *tmp = NULL;
+ /* Intermediate BIGNUMS that can be returned for testing */
+ BIGNUM *p1 = NULL, *p2 = NULL;
+ BIGNUM *q1 = NULL, *q2 = NULL;
+ /* Intermediate BIGNUMS that can be input for testing */
+ BIGNUM *Xpout = NULL, *Xqout = NULL;
+ BIGNUM *Xp = NULL, *Xp1 = NULL, *Xp2 = NULL;
+ BIGNUM *Xq = NULL, *Xq1 = NULL, *Xq2 = NULL;
+
+#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+ if (test != NULL) {
+ Xp1 = test->Xp1;
+ Xp2 = test->Xp2;
+ Xq1 = test->Xq1;
+ Xq2 = test->Xq2;
+ Xp = test->Xp;
+ Xq = test->Xq;
+ p1 = test->p1;
+ p2 = test->p2;
+ q1 = test->q1;
+ q2 = test->q2;
+ }
+#endif
+
+ /* (Step 1) Check key length
+ * NOTE: SP800-131A Rev1 Disallows key lengths of < 2048 bits for RSA
+ * Signature Generation and Key Agree/Transport.
+ */
+ if (nbits < RSA_FIPS1864_MIN_KEYGEN_KEYSIZE) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_KEY_SIZE_TOO_SMALL);
+ return 0;
+ }
+
+ if (!ossl_rsa_check_public_exponent(e)) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_PUB_EXPONENT_OUT_OF_RANGE);
+ return 0;
+ }
+
+ /* (Step 3) Determine strength and check rand generator strength is ok -
+ * this step is redundant because the generator always returns a higher
+ * strength than is required.
+ */
+
+ BN_CTX_start(ctx);
+ tmp = BN_CTX_get(ctx);
+ Xpo = (Xpout != NULL) ? Xpout : BN_CTX_get(ctx);
+ Xqo = (Xqout != NULL) ? Xqout : BN_CTX_get(ctx);
+ if (tmp == NULL || Xpo == NULL || Xqo == NULL)
+ goto err;
+ BN_set_flags(Xpo, BN_FLG_CONSTTIME);
+ BN_set_flags(Xqo, BN_FLG_CONSTTIME);
+
+ if (rsa->p == NULL)
+ rsa->p = BN_secure_new();
+ if (rsa->q == NULL)
+ rsa->q = BN_secure_new();
+ if (rsa->p == NULL || rsa->q == NULL)
+ goto err;
+ BN_set_flags(rsa->p, BN_FLG_CONSTTIME);
+ BN_set_flags(rsa->q, BN_FLG_CONSTTIME);
+
+ /* (Step 4) Generate p, Xp */
+ if (!ossl_bn_rsa_fips186_4_gen_prob_primes(rsa->p, Xpo, p1, p2, Xp, Xp1, Xp2,
+ nbits, e, ctx, cb))
+ goto err;
+ for(;;) {
+ /* (Step 5) Generate q, Xq*/
+ if (!ossl_bn_rsa_fips186_4_gen_prob_primes(rsa->q, Xqo, q1, q2, Xq, Xq1,
+ Xq2, nbits, e, ctx, cb))
+ goto err;
+
+ /* (Step 6) |Xp - Xq| > 2^(nbitlen/2 - 100) */
+ ok = ossl_rsa_check_pminusq_diff(tmp, Xpo, Xqo, nbits);
+ if (ok < 0)
+ goto err;
+ if (ok == 0)
+ continue;
+
+ /* (Step 6) |p - q| > 2^(nbitlen/2 - 100) */
+ ok = ossl_rsa_check_pminusq_diff(tmp, rsa->p, rsa->q, nbits);
+ if (ok < 0)
+ goto err;
+ if (ok == 0)
+ continue;
+ break; /* successfully finished */
+ }
+ rsa->dirty_cnt++;
+ ret = 1;
+err:
+ /* Zeroize any internally generated values that are not returned */
+ if (Xpo != Xpout)
+ BN_clear(Xpo);
+ if (Xqo != Xqout)
+ BN_clear(Xqo);
+ BN_clear(tmp);
+
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+/*
+ * Validates the RSA key size based on the target strength.
+ * See SP800-56Br1 6.3.1.1 (Steps 1a-1b)
+ *
+ * Params:
+ * nbits The key size in bits.
+ * strength The target strength in bits. -1 means the target
+ * strength is unknown.
+ * Returns: 1 if the key size matches the target strength, or 0 otherwise.
+ */
+int ossl_rsa_sp800_56b_validate_strength(int nbits, int strength)
+{
+ int s = (int)ossl_ifc_ffc_compute_security_bits(nbits);
+
+#ifdef FIPS_MODULE
+ if (s < RSA_FIPS1864_MIN_KEYGEN_STRENGTH) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MODULUS);
+ return 0;
+ }
+#endif
+ if (strength != -1 && s != strength) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_STRENGTH);
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Validate that the random bit generator is of sufficient strength to generate
+ * a key of the specified length.
+ */
+static int rsa_validate_rng_strength(EVP_RAND_CTX *rng, int nbits)
+{
+ if (rng == NULL)
+ return 0;
+#ifdef FIPS_MODULE
+ /*
+ * This should become mainstream once similar tests are added to the other
+ * key generations and once there is a way to disable these checks.
+ */
+ if (EVP_RAND_get_strength(rng) < ossl_ifc_ffc_compute_security_bits(nbits)) {
+ ERR_raise(ERR_LIB_RSA,
+ RSA_R_RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT);
+ return 0;
+ }
+#endif
+ return 1;
+}
+
+/*
+ *
+ * Using p & q, calculate other required parameters such as n, d.
+ * as well as the CRT parameters dP, dQ, qInv.
+ *
+ * See SP800-56Br1
+ * 6.3.1.1 rsakpg1 - basic (Steps 3-4)
+ * 6.3.1.3 rsakpg1 - crt (Step 5)
+ *
+ * Params:
+ * rsa An rsa object.
+ * nbits The key size.
+ * e The public exponent.
+ * ctx A BN_CTX object.
+ * Notes:
+ * There is a small chance that the generated d will be too small.
+ * Returns: -1 = error,
+ * 0 = d is too small,
+ * 1 = success.
+ */
+int ossl_rsa_sp800_56b_derive_params_from_pq(RSA *rsa, int nbits,
+ const BIGNUM *e, BN_CTX *ctx)
+{
+ int ret = -1;
+ BIGNUM *p1, *q1, *lcm, *p1q1, *gcd;
+
+ BN_CTX_start(ctx);
+ p1 = BN_CTX_get(ctx);
+ q1 = BN_CTX_get(ctx);
+ lcm = BN_CTX_get(ctx);
+ p1q1 = BN_CTX_get(ctx);
+ gcd = BN_CTX_get(ctx);
+ if (gcd == NULL)
+ goto err;
+
+ BN_set_flags(p1, BN_FLG_CONSTTIME);
+ BN_set_flags(q1, BN_FLG_CONSTTIME);
+ BN_set_flags(lcm, BN_FLG_CONSTTIME);
+ BN_set_flags(p1q1, BN_FLG_CONSTTIME);
+ BN_set_flags(gcd, BN_FLG_CONSTTIME);
+
+ /* LCM((p-1, q-1)) */
+ if (ossl_rsa_get_lcm(ctx, rsa->p, rsa->q, lcm, gcd, p1, q1, p1q1) != 1)
+ goto err;
+
+ /* copy e */
+ BN_free(rsa->e);
+ rsa->e = BN_dup(e);
+ if (rsa->e == NULL)
+ goto err;
+
+ BN_clear_free(rsa->d);
+ /* (Step 3) d = (e^-1) mod (LCM(p-1, q-1)) */
+ rsa->d = BN_secure_new();
+ if (rsa->d == NULL)
+ goto err;
+ BN_set_flags(rsa->d, BN_FLG_CONSTTIME);
+ if (BN_mod_inverse(rsa->d, e, lcm, ctx) == NULL)
+ goto err;
+
+ /* (Step 3) return an error if d is too small */
+ if (BN_num_bits(rsa->d) <= (nbits >> 1)) {
+ ret = 0;
+ goto err;
+ }
+
+ /* (Step 4) n = pq */
+ if (rsa->n == NULL)
+ rsa->n = BN_new();
+ if (rsa->n == NULL || !BN_mul(rsa->n, rsa->p, rsa->q, ctx))
+ goto err;
+
+ /* (Step 5a) dP = d mod (p-1) */
+ if (rsa->dmp1 == NULL)
+ rsa->dmp1 = BN_secure_new();
+ if (rsa->dmp1 == NULL)
+ goto err;
+ BN_set_flags(rsa->dmp1, BN_FLG_CONSTTIME);
+ if (!BN_mod(rsa->dmp1, rsa->d, p1, ctx))
+ goto err;
+
+ /* (Step 5b) dQ = d mod (q-1) */
+ if (rsa->dmq1 == NULL)
+ rsa->dmq1 = BN_secure_new();
+ if (rsa->dmq1 == NULL)
+ goto err;
+ BN_set_flags(rsa->dmq1, BN_FLG_CONSTTIME);
+ if (!BN_mod(rsa->dmq1, rsa->d, q1, ctx))
+ goto err;
+
+ /* (Step 5c) qInv = (inverse of q) mod p */
+ BN_free(rsa->iqmp);
+ rsa->iqmp = BN_secure_new();
+ if (rsa->iqmp == NULL)
+ goto err;
+ BN_set_flags(rsa->iqmp, BN_FLG_CONSTTIME);
+ if (BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx) == NULL)
+ goto err;
+
+ rsa->dirty_cnt++;
+ ret = 1;
+err:
+ if (ret != 1) {
+ BN_free(rsa->e);
+ rsa->e = NULL;
+ BN_free(rsa->d);
+ rsa->d = NULL;
+ BN_free(rsa->n);
+ rsa->n = NULL;
+ BN_free(rsa->iqmp);
+ rsa->iqmp = NULL;
+ BN_free(rsa->dmq1);
+ rsa->dmq1 = NULL;
+ BN_free(rsa->dmp1);
+ rsa->dmp1 = NULL;
+ }
+ BN_clear(p1);
+ BN_clear(q1);
+ BN_clear(lcm);
+ BN_clear(p1q1);
+ BN_clear(gcd);
+
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+/*
+ * Generate a SP800-56B RSA key.
+ *
+ * See SP800-56Br1 6.3.1 "RSA Key-Pair Generation with a Fixed Public Exponent"
+ * 6.3.1.1 rsakpg1 - basic
+ * 6.3.1.3 rsakpg1 - crt
+ *
+ * See also FIPS 186-4 Section B.3.6
+ * "Generation of Probable Primes with Conditions Based on Auxiliary
+ * Probable Primes."
+ *
+ * Params:
+ * rsa The rsa object.
+ * nbits The intended key size in bits.
+ * efixed The public exponent. If NULL a default of 65537 is used.
+ * cb An optional BIGNUM callback.
+ * Returns: 1 if successfully generated otherwise it returns 0.
+ */
+int ossl_rsa_sp800_56b_generate_key(RSA *rsa, int nbits, const BIGNUM *efixed,
+ BN_GENCB *cb)
+{
+ int ret = 0;
+ int ok;
+ BN_CTX *ctx = NULL;
+ BIGNUM *e = NULL;
+ RSA_ACVP_TEST *info = NULL;
+
+#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+ info = rsa->acvp_test;
+#endif
+
+ /* (Steps 1a-1b) : Currently ignores the strength check */
+ if (!ossl_rsa_sp800_56b_validate_strength(nbits, -1))
+ return 0;
+
+ /* Check that the RNG is capable of generating a key this large */
+ if (!rsa_validate_rng_strength(RAND_get0_private(rsa->libctx), nbits))
+ return 0;
+
+ ctx = BN_CTX_new_ex(rsa->libctx);
+ if (ctx == NULL)
+ return 0;
+
+ /* Set default if e is not passed in */
+ if (efixed == NULL) {
+ e = BN_new();
+ if (e == NULL || !BN_set_word(e, 65537))
+ goto err;
+ } else {
+ e = (BIGNUM *)efixed;
+ }
+ /* (Step 1c) fixed exponent is checked later .*/
+
+ for (;;) {
+ /* (Step 2) Generate prime factors */
+ if (!ossl_rsa_fips186_4_gen_prob_primes(rsa, info, nbits, e, ctx, cb))
+ goto err;
+ /* (Steps 3-5) Compute params d, n, dP, dQ, qInv */
+ ok = ossl_rsa_sp800_56b_derive_params_from_pq(rsa, nbits, e, ctx);
+ if (ok < 0)
+ goto err;
+ if (ok > 0)
+ break;
+ /* Gets here if computed d is too small - so try again */
+ }
+
+ /* (Step 6) Do pairwise test - optional validity test has been omitted */
+ ret = ossl_rsa_sp800_56b_pairwise_test(rsa, ctx);
+err:
+ if (efixed == NULL)
+ BN_free(e);
+ BN_CTX_free(ctx);
+ return ret;
+}
+
+/*
+ * See SP800-56Br1 6.3.1.3 (Step 6) Perform a pair-wise consistency test by
+ * verifying that: k = (k^e)^d mod n for some integer k where 1 < k < n-1.
+ *
+ * Returns 1 if the RSA key passes the pairwise test or 0 it it fails.
+ */
+int ossl_rsa_sp800_56b_pairwise_test(RSA *rsa, BN_CTX *ctx)
+{
+ int ret = 0;
+ BIGNUM *k, *tmp;
+
+ BN_CTX_start(ctx);
+ tmp = BN_CTX_get(ctx);
+ k = BN_CTX_get(ctx);
+ if (k == NULL)
+ goto err;
+ BN_set_flags(k, BN_FLG_CONSTTIME);
+
+ ret = (BN_set_word(k, 2)
+ && BN_mod_exp(tmp, k, rsa->e, rsa->n, ctx)
+ && BN_mod_exp(tmp, tmp, rsa->d, rsa->n, ctx)
+ && BN_cmp(k, tmp) == 0);
+ if (ret == 0)
+ ERR_raise(ERR_LIB_RSA, RSA_R_PAIRWISE_TEST_FAILURE);
+err:
+ BN_CTX_end(ctx);
+ return ret;
+}
diff --git a/crypto/rsa/rsa_ssl.c b/crypto/rsa/rsa_ssl.c
deleted file mode 100644
index e1c755ae460b..000000000000
--- a/crypto/rsa/rsa_ssl.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/bn.h>
-#include <openssl/rsa.h>
-#include <openssl/rand.h>
-#include "internal/constant_time.h"
-
-int RSA_padding_add_SSLv23(unsigned char *to, int tlen,
- const unsigned char *from, int flen)
-{
- int i, j;
- unsigned char *p;
-
- if (flen > (tlen - RSA_PKCS1_PADDING_SIZE)) {
- RSAerr(RSA_F_RSA_PADDING_ADD_SSLV23,
- RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
- return 0;
- }
-
- p = (unsigned char *)to;
-
- *(p++) = 0;
- *(p++) = 2; /* Public Key BT (Block Type) */
-
- /* pad out with non-zero random data */
- j = tlen - 3 - 8 - flen;
-
- if (RAND_bytes(p, j) <= 0)
- return 0;
- for (i = 0; i < j; i++) {
- if (*p == '\0')
- do {
- if (RAND_bytes(p, 1) <= 0)
- return 0;
- } while (*p == '\0');
- p++;
- }
-
- memset(p, 3, 8);
- p += 8;
- *(p++) = '\0';
-
- memcpy(p, from, (unsigned int)flen);
- return 1;
-}
-
-/*
- * Copy of RSA_padding_check_PKCS1_type_2 with a twist that rejects padding
- * if nul delimiter is preceded by 8 consecutive 0x03 bytes. It also
- * preserves error code reporting for backward compatibility.
- */
-int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
- const unsigned char *from, int flen, int num)
-{
- int i;
- /* |em| is the encoded message, zero-padded to exactly |num| bytes */
- unsigned char *em = NULL;
- unsigned int good, found_zero_byte, mask, threes_in_row;
- int zero_index = 0, msg_index, mlen = -1, err;
-
- if (tlen <= 0 || flen <= 0)
- return -1;
-
- if (flen > num || num < RSA_PKCS1_PADDING_SIZE) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_DATA_TOO_SMALL);
- return -1;
- }
-
- em = OPENSSL_malloc(num);
- if (em == NULL) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, ERR_R_MALLOC_FAILURE);
- return -1;
- }
- /*
- * Caller is encouraged to pass zero-padded message created with
- * BN_bn2binpad. Trouble is that since we can't read out of |from|'s
- * bounds, it's impossible to have an invariant memory access pattern
- * in case |from| was not zero-padded in advance.
- */
- for (from += flen, em += num, i = 0; i < num; i++) {
- mask = ~constant_time_is_zero(flen);
- flen -= 1 & mask;
- from -= 1 & mask;
- *--em = *from & mask;
- }
-
- good = constant_time_is_zero(em[0]);
- good &= constant_time_eq(em[1], 2);
- err = constant_time_select_int(good, 0, RSA_R_BLOCK_TYPE_IS_NOT_02);
- mask = ~good;
-
- /* scan over padding data */
- found_zero_byte = 0;
- threes_in_row = 0;
- for (i = 2; i < num; i++) {
- unsigned int equals0 = constant_time_is_zero(em[i]);
-
- zero_index = constant_time_select_int(~found_zero_byte & equals0,
- i, zero_index);
- found_zero_byte |= equals0;
-
- threes_in_row += 1 & ~found_zero_byte;
- threes_in_row &= found_zero_byte | constant_time_eq(em[i], 3);
- }
-
- /*
- * PS must be at least 8 bytes long, and it starts two bytes into |em|.
- * If we never found a 0-byte, then |zero_index| is 0 and the check
- * also fails.
- */
- good &= constant_time_ge(zero_index, 2 + 8);
- err = constant_time_select_int(mask | good, err,
- RSA_R_NULL_BEFORE_BLOCK_MISSING);
- mask = ~good;
-
- /*
- * Reject if nul delimiter is preceded by 8 consecutive 0x03 bytes. Note
- * that RFC5246 incorrectly states this the other way around, i.e. reject
- * if it is not preceded by 8 consecutive 0x03 bytes. However this is
- * corrected in subsequent errata for that RFC.
- */
- good &= constant_time_lt(threes_in_row, 8);
- err = constant_time_select_int(mask | good, err,
- RSA_R_SSLV3_ROLLBACK_ATTACK);
- mask = ~good;
-
- /*
- * Skip the zero byte. This is incorrect if we never found a zero-byte
- * but in this case we also do not copy the message out.
- */
- msg_index = zero_index + 1;
- mlen = num - msg_index;
-
- /*
- * For good measure, do this check in constant time as well.
- */
- good &= constant_time_ge(tlen, mlen);
- err = constant_time_select_int(mask | good, err, RSA_R_DATA_TOO_LARGE);
-
- /*
- * Move the result in-place by |num|-RSA_PKCS1_PADDING_SIZE-|mlen| bytes to the left.
- * Then if |good| move |mlen| bytes from |em|+RSA_PKCS1_PADDING_SIZE to |to|.
- * Otherwise leave |to| unchanged.
- * Copy the memory back in a way that does not reveal the size of
- * the data being copied via a timing side channel. This requires copying
- * parts of the buffer multiple times based on the bits set in the real
- * length. Clear bits do a non-copy with identical access pattern.
- * The loop below has overall complexity of O(N*log(N)).
- */
- tlen = constant_time_select_int(constant_time_lt(num - RSA_PKCS1_PADDING_SIZE, tlen),
- num - RSA_PKCS1_PADDING_SIZE, tlen);
- for (msg_index = 1; msg_index < num - RSA_PKCS1_PADDING_SIZE; msg_index <<= 1) {
- mask = ~constant_time_eq(msg_index & (num - RSA_PKCS1_PADDING_SIZE - mlen), 0);
- for (i = RSA_PKCS1_PADDING_SIZE; i < num - msg_index; i++)
- em[i] = constant_time_select_8(mask, em[i + msg_index], em[i]);
- }
- for (i = 0; i < tlen; i++) {
- mask = good & constant_time_lt(i, mlen);
- to[i] = constant_time_select_8(mask, em[i + RSA_PKCS1_PADDING_SIZE], to[i]);
- }
-
- OPENSSL_clear_free(em, num);
- RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, err);
- err_clear_last_constant_time(1 & good);
-
- return constant_time_select_int(good, mlen, -1);
-}
diff --git a/crypto/rsa/rsa_x931.c b/crypto/rsa/rsa_x931.c
index 7b0486c0f263..9d331ab9a7f3 100644
--- a/crypto/rsa/rsa_x931.c
+++ b/crypto/rsa/rsa_x931.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2005-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
@@ -27,7 +33,7 @@ int RSA_padding_add_X931(unsigned char *to, int tlen,
j = tlen - flen - 2;
if (j < 0) {
- RSAerr(RSA_F_RSA_PADDING_ADD_X931, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return -1;
}
@@ -58,7 +64,7 @@ int RSA_padding_check_X931(unsigned char *to, int tlen,
p = from;
if ((num != flen) || ((*p != 0x6A) && (*p != 0x6B))) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_X931, RSA_R_INVALID_HEADER);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_HEADER);
return -1;
}
@@ -69,7 +75,7 @@ int RSA_padding_check_X931(unsigned char *to, int tlen,
if (c == 0xBA)
break;
if (c != 0xBB) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_X931, RSA_R_INVALID_PADDING);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING);
return -1;
}
}
@@ -77,7 +83,7 @@ int RSA_padding_check_X931(unsigned char *to, int tlen,
j -= i;
if (i == 0) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_X931, RSA_R_INVALID_PADDING);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING);
return -1;
}
@@ -86,7 +92,7 @@ int RSA_padding_check_X931(unsigned char *to, int tlen,
}
if (p[j] != 0xCC) {
- RSAerr(RSA_F_RSA_PADDING_CHECK_X931, RSA_R_INVALID_TRAILER);
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_TRAILER);
return -1;
}
diff --git a/crypto/rsa/rsa_x931g.c b/crypto/rsa/rsa_x931g.c
index 322cd14a840d..5a309a98c347 100644
--- a/crypto/rsa/rsa_x931g.c
+++ b/crypto/rsa/rsa_x931g.c
@@ -1,12 +1,18 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <stdio.h>
#include <string.h>
#include <time.h>
@@ -131,6 +137,7 @@ int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1,
if (rsa->iqmp == NULL)
goto err;
+ rsa->dirty_cnt++;
ret = 1;
err:
BN_CTX_end(ctx);
@@ -184,6 +191,7 @@ int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e,
NULL, NULL, NULL, NULL, NULL, NULL, e, cb))
goto error;
+ rsa->dirty_cnt++;
ok = 1;
error:
diff --git a/crypto/s390x_arch.h b/crypto/s390x_arch.h
index 64e7ebb5662e..a7bde67d90f5 100644
--- a/crypto/s390x_arch.h
+++ b/crypto/s390x_arch.h
@@ -1,7 +1,7 @@
/*
* Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -26,6 +26,29 @@ void s390x_kmf(const unsigned char *in, size_t len, unsigned char *out,
unsigned int fc, void *param);
void s390x_kma(const unsigned char *aad, size_t alen, const unsigned char *in,
size_t len, unsigned char *out, unsigned int fc, void *param);
+int s390x_pcc(unsigned int fc, void *param);
+int s390x_kdsa(unsigned int fc, void *param, const unsigned char *in,
+ size_t len);
+
+void s390x_flip_endian32(unsigned char dst[32], const unsigned char src[32]);
+void s390x_flip_endian64(unsigned char dst[64], const unsigned char src[64]);
+
+int s390x_x25519_mul(unsigned char u_dst[32],
+ const unsigned char u_src[32],
+ const unsigned char d_src[32]);
+int s390x_x448_mul(unsigned char u_dst[56],
+ const unsigned char u_src[56],
+ const unsigned char d_src[56]);
+int s390x_ed25519_mul(unsigned char x_dst[32],
+ unsigned char y_dst[32],
+ const unsigned char x_src[32],
+ const unsigned char y_src[32],
+ const unsigned char d_src[32]);
+int s390x_ed448_mul(unsigned char x_dst[57],
+ unsigned char y_dst[57],
+ const unsigned char x_src[57],
+ const unsigned char y_src[57],
+ const unsigned char d_src[57]);
/*
* The field elements of OPENSSL_s390xcap_P are the 64-bit words returned by
@@ -45,6 +68,8 @@ struct OPENSSL_s390xcap_st {
unsigned long long kmf[2];
unsigned long long prno[2];
unsigned long long kma[2];
+ unsigned long long pcc[2];
+ unsigned long long kdsa[2];
};
#if defined(__GNUC__) && defined(__linux)
@@ -52,55 +77,97 @@ __attribute__ ((visibility("hidden")))
#endif
extern struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P;
+/* Max number of 64-bit words currently returned by STFLE */
+# define S390X_STFLE_MAX 3
+
/* convert facility bit number or function code to bit mask */
-# define S390X_CAPBIT(i) (1ULL << (63 - (i) % 64))
+# define S390X_CAPBIT(i) (1ULL << (63 - (i) % 64))
# endif
/* OPENSSL_s390xcap_P offsets [bytes] */
-# define S390X_STFLE 0x00
-# define S390X_KIMD 0x20
-# define S390X_KLMD 0x30
-# define S390X_KM 0x40
-# define S390X_KMC 0x50
-# define S390X_KMAC 0x60
-# define S390X_KMCTR 0x70
-# define S390X_KMO 0x80
-# define S390X_KMF 0x90
-# define S390X_PRNO 0xa0
-# define S390X_KMA 0xb0
+# define S390X_STFLE 0x00
+# define S390X_KIMD 0x20
+# define S390X_KLMD 0x30
+# define S390X_KM 0x40
+# define S390X_KMC 0x50
+# define S390X_KMAC 0x60
+# define S390X_KMCTR 0x70
+# define S390X_KMO 0x80
+# define S390X_KMF 0x90
+# define S390X_PRNO 0xa0
+# define S390X_KMA 0xb0
+# define S390X_PCC 0xc0
+# define S390X_KDSA 0xd0
/* Facility Bit Numbers */
-# define S390X_VX 129
-# define S390X_VXD 134
-# define S390X_VXE 135
+# define S390X_MSA 17 /* message-security-assist */
+# define S390X_STCKF 25 /* store-clock-fast */
+# define S390X_MSA5 57 /* message-security-assist-ext. 5 */
+# define S390X_MSA3 76 /* message-security-assist-ext. 3 */
+# define S390X_MSA4 77 /* message-security-assist-ext. 4 */
+# define S390X_VX 129 /* vector */
+# define S390X_VXD 134 /* vector packed decimal */
+# define S390X_VXE 135 /* vector enhancements 1 */
+# define S390X_MSA8 146 /* message-security-assist-ext. 8 */
+# define S390X_MSA9 155 /* message-security-assist-ext. 9 */
/* Function Codes */
/* all instructions */
-# define S390X_QUERY 0
+# define S390X_QUERY 0
/* kimd/klmd */
-# define S390X_SHA3_224 32
-# define S390X_SHA3_256 33
-# define S390X_SHA3_384 34
-# define S390X_SHA3_512 35
-# define S390X_SHAKE_128 36
-# define S390X_SHAKE_256 37
-# define S390X_GHASH 65
+# define S390X_SHA_1 1
+# define S390X_SHA_256 2
+# define S390X_SHA_512 3
+# define S390X_SHA3_224 32
+# define S390X_SHA3_256 33
+# define S390X_SHA3_384 34
+# define S390X_SHA3_512 35
+# define S390X_SHAKE_128 36
+# define S390X_SHAKE_256 37
+# define S390X_GHASH 65
/* km/kmc/kmac/kmctr/kmo/kmf/kma */
-# define S390X_AES_128 18
-# define S390X_AES_192 19
-# define S390X_AES_256 20
+# define S390X_AES_128 18
+# define S390X_AES_192 19
+# define S390X_AES_256 20
+
+/* km */
+# define S390X_XTS_AES_128 50
+# define S390X_XTS_AES_256 52
/* prno */
-# define S390X_TRNG 114
+# define S390X_SHA_512_DRNG 3
+# define S390X_TRNG 114
+
+/* pcc */
+# define S390X_SCALAR_MULTIPLY_P256 64
+# define S390X_SCALAR_MULTIPLY_P384 65
+# define S390X_SCALAR_MULTIPLY_P521 66
+# define S390X_SCALAR_MULTIPLY_ED25519 72
+# define S390X_SCALAR_MULTIPLY_ED448 73
+# define S390X_SCALAR_MULTIPLY_X25519 80
+# define S390X_SCALAR_MULTIPLY_X448 81
+
+/* kdsa */
+# define S390X_ECDSA_VERIFY_P256 1
+# define S390X_ECDSA_VERIFY_P384 2
+# define S390X_ECDSA_VERIFY_P521 3
+# define S390X_ECDSA_SIGN_P256 9
+# define S390X_ECDSA_SIGN_P384 10
+# define S390X_ECDSA_SIGN_P521 11
+# define S390X_EDDSA_VERIFY_ED25519 32
+# define S390X_EDDSA_VERIFY_ED448 36
+# define S390X_EDDSA_SIGN_ED25519 40
+# define S390X_EDDSA_SIGN_ED448 44
/* Register 0 Flags */
-# define S390X_DECRYPT 0x80
-# define S390X_KMA_LPC 0x100
-# define S390X_KMA_LAAD 0x200
-# define S390X_KMA_HS 0x400
+# define S390X_DECRYPT 0x80
+# define S390X_KMA_LPC 0x100
+# define S390X_KMA_LAAD 0x200
+# define S390X_KMA_HS 0x400
+# define S390X_KDSA_D 0x80
#endif
diff --git a/crypto/s390xcap.c b/crypto/s390xcap.c
index 1097c703b4fb..ea38ff8f0856 100644
--- a/crypto/s390xcap.c
+++ b/crypto/s390xcap.c
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,16 +13,64 @@
#include <setjmp.h>
#include <signal.h>
#include "internal/cryptlib.h"
+#include "crypto/ctype.h"
#include "s390x_arch.h"
+#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
+# if __GLIBC_PREREQ(2, 16)
+# include <sys/auxv.h>
+# if defined(HWCAP_S390_STFLE) && defined(HWCAP_S390_VX)
+# define OSSL_IMPLEMENT_GETAUXVAL
+# endif
+# endif
+#endif
+
+#define LEN 128
+#define STR_(S) #S
+#define STR(S) STR_(S)
+
+#define TOK_FUNC(NAME) \
+ (sscanf(tok_begin, \
+ " " STR(NAME) " : %" STR(LEN) "[^:] : " \
+ "%" STR(LEN) "s %" STR(LEN) "s ", \
+ tok[0], tok[1], tok[2]) == 2) { \
+ \
+ off = (tok[0][0] == '~') ? 1 : 0; \
+ if (sscanf(tok[0] + off, "%llx", &cap->NAME[0]) != 1) \
+ goto ret; \
+ if (off) \
+ cap->NAME[0] = ~cap->NAME[0]; \
+ \
+ off = (tok[1][0] == '~') ? 1 : 0; \
+ if (sscanf(tok[1] + off, "%llx", &cap->NAME[1]) != 1) \
+ goto ret; \
+ if (off) \
+ cap->NAME[1] = ~cap->NAME[1]; \
+ }
+
+#define TOK_CPU(NAME) \
+ (sscanf(tok_begin, \
+ " %" STR(LEN) "s %" STR(LEN) "s ", \
+ tok[0], tok[1]) == 1 \
+ && !strcmp(tok[0], #NAME)) { \
+ memcpy(cap, &NAME, sizeof(*cap)); \
+ }
+
+#ifndef OSSL_IMPLEMENT_GETAUXVAL
static sigjmp_buf ill_jmp;
static void ill_handler(int sig)
{
siglongjmp(ill_jmp, sig);
}
-void OPENSSL_s390x_facilities(void);
void OPENSSL_vx_probe(void);
+#endif
+
+static const char *env;
+static int parse_env(struct OPENSSL_s390xcap_st *cap);
+
+void OPENSSL_s390x_facilities(void);
+void OPENSSL_s390x_functions(void);
struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P;
@@ -31,8 +79,7 @@ __attribute__ ((visibility("hidden")))
#endif
void OPENSSL_cpuid_setup(void)
{
- sigset_t oset;
- struct sigaction ill_act, oact_ill, oact_fpe;
+ struct OPENSSL_s390xcap_st cap;
if (OPENSSL_s390xcap_P.stfle[0])
return;
@@ -40,31 +87,659 @@ void OPENSSL_cpuid_setup(void)
/* set a bit that will not be tested later */
OPENSSL_s390xcap_P.stfle[0] |= S390X_CAPBIT(0);
- memset(&ill_act, 0, sizeof(ill_act));
- ill_act.sa_handler = ill_handler;
- sigfillset(&ill_act.sa_mask);
- sigdelset(&ill_act.sa_mask, SIGILL);
- sigdelset(&ill_act.sa_mask, SIGFPE);
- sigdelset(&ill_act.sa_mask, SIGTRAP);
- sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset);
- sigaction(SIGILL, &ill_act, &oact_ill);
- sigaction(SIGFPE, &ill_act, &oact_fpe);
-
- /* protection against missing store-facility-list-extended */
- if (sigsetjmp(ill_jmp, 1) == 0)
- OPENSSL_s390x_facilities();
-
- /* protection against disabled vector facility */
- if ((OPENSSL_s390xcap_P.stfle[2] & S390X_CAPBIT(S390X_VX))
- && (sigsetjmp(ill_jmp, 1) == 0)) {
- OPENSSL_vx_probe();
- } else {
- OPENSSL_s390xcap_P.stfle[2] &= ~(S390X_CAPBIT(S390X_VX)
- | S390X_CAPBIT(S390X_VXD)
- | S390X_CAPBIT(S390X_VXE));
+#if defined(OSSL_IMPLEMENT_GETAUXVAL)
+ {
+ const unsigned long hwcap = getauxval(AT_HWCAP);
+
+ /* protection against missing store-facility-list-extended */
+ if (hwcap & HWCAP_S390_STFLE)
+ OPENSSL_s390x_facilities();
+
+ /* protection against disabled vector facility */
+ if (!(hwcap & HWCAP_S390_VX)) {
+ OPENSSL_s390xcap_P.stfle[2] &= ~(S390X_CAPBIT(S390X_VX)
+ | S390X_CAPBIT(S390X_VXD)
+ | S390X_CAPBIT(S390X_VXE));
+ }
+ }
+#else
+ {
+ sigset_t oset;
+ struct sigaction ill_act, oact_ill, oact_fpe;
+
+ memset(&ill_act, 0, sizeof(ill_act));
+ ill_act.sa_handler = ill_handler;
+ sigfillset(&ill_act.sa_mask);
+ sigdelset(&ill_act.sa_mask, SIGILL);
+ sigdelset(&ill_act.sa_mask, SIGFPE);
+ sigdelset(&ill_act.sa_mask, SIGTRAP);
+
+ sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset);
+ sigaction(SIGILL, &ill_act, &oact_ill);
+ sigaction(SIGFPE, &ill_act, &oact_fpe);
+
+ /* protection against missing store-facility-list-extended */
+ if (sigsetjmp(ill_jmp, 1) == 0)
+ OPENSSL_s390x_facilities();
+
+ /* protection against disabled vector facility */
+ if ((OPENSSL_s390xcap_P.stfle[2] & S390X_CAPBIT(S390X_VX))
+ && (sigsetjmp(ill_jmp, 1) == 0)) {
+ OPENSSL_vx_probe();
+ } else {
+ OPENSSL_s390xcap_P.stfle[2] &= ~(S390X_CAPBIT(S390X_VX)
+ | S390X_CAPBIT(S390X_VXD)
+ | S390X_CAPBIT(S390X_VXE));
+ }
+
+ sigaction(SIGFPE, &oact_fpe, NULL);
+ sigaction(SIGILL, &oact_ill, NULL);
+ sigprocmask(SIG_SETMASK, &oset, NULL);
+ }
+#endif
+
+ env = getenv("OPENSSL_s390xcap");
+ if (env != NULL) {
+ if (!parse_env(&cap))
+ env = NULL;
+ }
+
+ if (env != NULL) {
+ OPENSSL_s390xcap_P.stfle[0] &= cap.stfle[0];
+ OPENSSL_s390xcap_P.stfle[1] &= cap.stfle[1];
+ OPENSSL_s390xcap_P.stfle[2] &= cap.stfle[2];
+ }
+
+ OPENSSL_s390x_functions(); /* check OPENSSL_s390xcap_P.stfle */
+
+ if (env != NULL) {
+ OPENSSL_s390xcap_P.kimd[0] &= cap.kimd[0];
+ OPENSSL_s390xcap_P.kimd[1] &= cap.kimd[1];
+ OPENSSL_s390xcap_P.klmd[0] &= cap.klmd[0];
+ OPENSSL_s390xcap_P.klmd[1] &= cap.klmd[1];
+ OPENSSL_s390xcap_P.km[0] &= cap.km[0];
+ OPENSSL_s390xcap_P.km[1] &= cap.km[1];
+ OPENSSL_s390xcap_P.kmc[0] &= cap.kmc[0];
+ OPENSSL_s390xcap_P.kmc[1] &= cap.kmc[1];
+ OPENSSL_s390xcap_P.kmac[0] &= cap.kmac[0];
+ OPENSSL_s390xcap_P.kmac[1] &= cap.kmac[1];
+ OPENSSL_s390xcap_P.kmctr[0] &= cap.kmctr[0];
+ OPENSSL_s390xcap_P.kmctr[1] &= cap.kmctr[1];
+ OPENSSL_s390xcap_P.kmo[0] &= cap.kmo[0];
+ OPENSSL_s390xcap_P.kmo[1] &= cap.kmo[1];
+ OPENSSL_s390xcap_P.kmf[0] &= cap.kmf[0];
+ OPENSSL_s390xcap_P.kmf[1] &= cap.kmf[1];
+ OPENSSL_s390xcap_P.prno[0] &= cap.prno[0];
+ OPENSSL_s390xcap_P.prno[1] &= cap.prno[1];
+ OPENSSL_s390xcap_P.kma[0] &= cap.kma[0];
+ OPENSSL_s390xcap_P.kma[1] &= cap.kma[1];
+ OPENSSL_s390xcap_P.pcc[0] &= cap.pcc[0];
+ OPENSSL_s390xcap_P.pcc[1] &= cap.pcc[1];
+ OPENSSL_s390xcap_P.kdsa[0] &= cap.kdsa[0];
+ OPENSSL_s390xcap_P.kdsa[1] &= cap.kdsa[1];
+ }
+}
+
+static int parse_env(struct OPENSSL_s390xcap_st *cap)
+{
+ /*-
+ * CPU model data
+ * (only the STFLE- and QUERY-bits relevant to libcrypto are set)
+ */
+
+ /*-
+ * z900 (2000) - z/Architecture POP SA22-7832-00
+ * Facility detection would fail on real hw (no STFLE).
+ */
+ static const struct OPENSSL_s390xcap_st z900 = {
+ /*.stfle = */{0ULL, 0ULL, 0ULL, 0ULL},
+ /*.kimd = */{0ULL, 0ULL},
+ /*.klmd = */{0ULL, 0ULL},
+ /*.km = */{0ULL, 0ULL},
+ /*.kmc = */{0ULL, 0ULL},
+ /*.kmac = */{0ULL, 0ULL},
+ /*.kmctr = */{0ULL, 0ULL},
+ /*.kmo = */{0ULL, 0ULL},
+ /*.kmf = */{0ULL, 0ULL},
+ /*.prno = */{0ULL, 0ULL},
+ /*.kma = */{0ULL, 0ULL},
+ /*.pcc = */{0ULL, 0ULL},
+ /*.kdsa = */{0ULL, 0ULL},
+ };
+
+ /*-
+ * z990 (2003) - z/Architecture POP SA22-7832-02
+ * Implements MSA. Facility detection would fail on real hw (no STFLE).
+ */
+ static const struct OPENSSL_s390xcap_st z990 = {
+ /*.stfle = */{S390X_CAPBIT(S390X_MSA),
+ 0ULL, 0ULL, 0ULL},
+ /*.kimd = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_1),
+ 0ULL},
+ /*.klmd = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_1),
+ 0ULL},
+ /*.km = */{S390X_CAPBIT(S390X_QUERY),
+ 0ULL},
+ /*.kmc = */{S390X_CAPBIT(S390X_QUERY),
+ 0ULL},
+ /*.kmac = */{S390X_CAPBIT(S390X_QUERY),
+ 0ULL},
+ /*.kmctr = */{0ULL, 0ULL},
+ /*.kmo = */{0ULL, 0ULL},
+ /*.kmf = */{0ULL, 0ULL},
+ /*.prno = */{0ULL, 0ULL},
+ /*.kma = */{0ULL, 0ULL},
+ /*.pcc = */{0ULL, 0ULL},
+ /*.kdsa = */{0ULL, 0ULL},
+ };
+
+ /*-
+ * z9 (2005) - z/Architecture POP SA22-7832-04
+ * Implements MSA and MSA1.
+ */
+ static const struct OPENSSL_s390xcap_st z9 = {
+ /*.stfle = */{S390X_CAPBIT(S390X_MSA)
+ | S390X_CAPBIT(S390X_STCKF),
+ 0ULL, 0ULL, 0ULL},
+ /*.kimd = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_1)
+ | S390X_CAPBIT(S390X_SHA_256),
+ 0ULL},
+ /*.klmd = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_1)
+ | S390X_CAPBIT(S390X_SHA_256),
+ 0ULL},
+ /*.km = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128),
+ 0ULL},
+ /*.kmc = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128),
+ 0ULL},
+ /*.kmac = */{S390X_CAPBIT(S390X_QUERY),
+ 0ULL},
+ /*.kmctr = */{0ULL, 0ULL},
+ /*.kmo = */{0ULL, 0ULL},
+ /*.kmf = */{0ULL, 0ULL},
+ /*.prno = */{0ULL, 0ULL},
+ /*.kma = */{0ULL, 0ULL},
+ /*.pcc = */{0ULL, 0ULL},
+ /*.kdsa = */{0ULL, 0ULL},
+ };
+
+ /*-
+ * z10 (2008) - z/Architecture POP SA22-7832-06
+ * Implements MSA and MSA1-2.
+ */
+ static const struct OPENSSL_s390xcap_st z10 = {
+ /*.stfle = */{S390X_CAPBIT(S390X_MSA)
+ | S390X_CAPBIT(S390X_STCKF),
+ 0ULL, 0ULL, 0ULL},
+ /*.kimd = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_1)
+ | S390X_CAPBIT(S390X_SHA_256)
+ | S390X_CAPBIT(S390X_SHA_512),
+ 0ULL},
+ /*.klmd = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_1)
+ | S390X_CAPBIT(S390X_SHA_256)
+ | S390X_CAPBIT(S390X_SHA_512),
+ 0ULL},
+ /*.km = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmc = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmac = */{S390X_CAPBIT(S390X_QUERY),
+ 0ULL},
+ /*.kmctr = */{0ULL, 0ULL},
+ /*.kmo = */{0ULL, 0ULL},
+ /*.kmf = */{0ULL, 0ULL},
+ /*.prno = */{0ULL, 0ULL},
+ /*.kma = */{0ULL, 0ULL},
+ /*.pcc = */{0ULL, 0ULL},
+ /*.kdsa = */{0ULL, 0ULL},
+ };
+
+ /*-
+ * z196 (2010) - z/Architecture POP SA22-7832-08
+ * Implements MSA and MSA1-4.
+ */
+ static const struct OPENSSL_s390xcap_st z196 = {
+ /*.stfle = */{S390X_CAPBIT(S390X_MSA)
+ | S390X_CAPBIT(S390X_STCKF),
+ S390X_CAPBIT(S390X_MSA3)
+ | S390X_CAPBIT(S390X_MSA4),
+ 0ULL, 0ULL},
+ /*.kimd = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_1)
+ | S390X_CAPBIT(S390X_SHA_256)
+ | S390X_CAPBIT(S390X_SHA_512),
+ S390X_CAPBIT(S390X_GHASH)},
+ /*.klmd = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_1)
+ | S390X_CAPBIT(S390X_SHA_256)
+ | S390X_CAPBIT(S390X_SHA_512),
+ 0ULL},
+ /*.km = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256)
+ | S390X_CAPBIT(S390X_XTS_AES_128)
+ | S390X_CAPBIT(S390X_XTS_AES_256),
+ 0ULL},
+ /*.kmc = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmac = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmctr = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmo = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmf = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.prno = */{0ULL, 0ULL},
+ /*.kma = */{0ULL, 0ULL},
+ /*.pcc = */{S390X_CAPBIT(S390X_QUERY),
+ 0ULL},
+ /*.kdsa = */{0ULL, 0ULL},
+ };
+
+ /*-
+ * zEC12 (2012) - z/Architecture POP SA22-7832-09
+ * Implements MSA and MSA1-4.
+ */
+ static const struct OPENSSL_s390xcap_st zEC12 = {
+ /*.stfle = */{S390X_CAPBIT(S390X_MSA)
+ | S390X_CAPBIT(S390X_STCKF),
+ S390X_CAPBIT(S390X_MSA3)
+ | S390X_CAPBIT(S390X_MSA4),
+ 0ULL, 0ULL},
+ /*.kimd = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_1)
+ | S390X_CAPBIT(S390X_SHA_256)
+ | S390X_CAPBIT(S390X_SHA_512),
+ S390X_CAPBIT(S390X_GHASH)},
+ /*.klmd = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_1)
+ | S390X_CAPBIT(S390X_SHA_256)
+ | S390X_CAPBIT(S390X_SHA_512),
+ 0ULL},
+ /*.km = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256)
+ | S390X_CAPBIT(S390X_XTS_AES_128)
+ | S390X_CAPBIT(S390X_XTS_AES_256),
+ 0ULL},
+ /*.kmc = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmac = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmctr = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmo = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmf = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.prno = */{0ULL, 0ULL},
+ /*.kma = */{0ULL, 0ULL},
+ /*.pcc = */{S390X_CAPBIT(S390X_QUERY),
+ 0ULL},
+ /*.kdsa = */{0ULL, 0ULL},
+ };
+
+ /*-
+ * z13 (2015) - z/Architecture POP SA22-7832-10
+ * Implements MSA and MSA1-5.
+ */
+ static const struct OPENSSL_s390xcap_st z13 = {
+ /*.stfle = */{S390X_CAPBIT(S390X_MSA)
+ | S390X_CAPBIT(S390X_STCKF)
+ | S390X_CAPBIT(S390X_MSA5),
+ S390X_CAPBIT(S390X_MSA3)
+ | S390X_CAPBIT(S390X_MSA4),
+ S390X_CAPBIT(S390X_VX),
+ 0ULL},
+ /*.kimd = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_1)
+ | S390X_CAPBIT(S390X_SHA_256)
+ | S390X_CAPBIT(S390X_SHA_512),
+ S390X_CAPBIT(S390X_GHASH)},
+ /*.klmd = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_1)
+ | S390X_CAPBIT(S390X_SHA_256)
+ | S390X_CAPBIT(S390X_SHA_512),
+ 0ULL},
+ /*.km = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256)
+ | S390X_CAPBIT(S390X_XTS_AES_128)
+ | S390X_CAPBIT(S390X_XTS_AES_256),
+ 0ULL},
+ /*.kmc = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmac = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmctr = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmo = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmf = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.prno = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_512_DRNG),
+ 0ULL},
+ /*.kma = */{0ULL, 0ULL},
+ /*.pcc = */{S390X_CAPBIT(S390X_QUERY),
+ 0ULL},
+ /*.kdsa = */{0ULL, 0ULL},
+ };
+
+ /*-
+ * z14 (2017) - z/Architecture POP SA22-7832-11
+ * Implements MSA and MSA1-8.
+ */
+ static const struct OPENSSL_s390xcap_st z14 = {
+ /*.stfle = */{S390X_CAPBIT(S390X_MSA)
+ | S390X_CAPBIT(S390X_STCKF)
+ | S390X_CAPBIT(S390X_MSA5),
+ S390X_CAPBIT(S390X_MSA3)
+ | S390X_CAPBIT(S390X_MSA4),
+ S390X_CAPBIT(S390X_VX)
+ | S390X_CAPBIT(S390X_VXD)
+ | S390X_CAPBIT(S390X_VXE)
+ | S390X_CAPBIT(S390X_MSA8),
+ 0ULL},
+ /*.kimd = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_1)
+ | S390X_CAPBIT(S390X_SHA_256)
+ | S390X_CAPBIT(S390X_SHA_512)
+ | S390X_CAPBIT(S390X_SHA3_224)
+ | S390X_CAPBIT(S390X_SHA3_256)
+ | S390X_CAPBIT(S390X_SHA3_384)
+ | S390X_CAPBIT(S390X_SHA3_512)
+ | S390X_CAPBIT(S390X_SHAKE_128)
+ | S390X_CAPBIT(S390X_SHAKE_256),
+ S390X_CAPBIT(S390X_GHASH)},
+ /*.klmd = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_1)
+ | S390X_CAPBIT(S390X_SHA_256)
+ | S390X_CAPBIT(S390X_SHA_512)
+ | S390X_CAPBIT(S390X_SHA3_224)
+ | S390X_CAPBIT(S390X_SHA3_256)
+ | S390X_CAPBIT(S390X_SHA3_384)
+ | S390X_CAPBIT(S390X_SHA3_512)
+ | S390X_CAPBIT(S390X_SHAKE_128)
+ | S390X_CAPBIT(S390X_SHAKE_256),
+ 0ULL},
+ /*.km = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256)
+ | S390X_CAPBIT(S390X_XTS_AES_128)
+ | S390X_CAPBIT(S390X_XTS_AES_256),
+ 0ULL},
+ /*.kmc = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmac = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmctr = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmo = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmf = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.prno = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_512_DRNG),
+ S390X_CAPBIT(S390X_TRNG)},
+ /*.kma = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.pcc = */{S390X_CAPBIT(S390X_QUERY),
+ 0ULL},
+ /*.kdsa = */{0ULL, 0ULL},
+ };
+
+ /*-
+ * z15 (2019) - z/Architecture POP SA22-7832-12
+ * Implements MSA and MSA1-9.
+ */
+ static const struct OPENSSL_s390xcap_st z15 = {
+ /*.stfle = */{S390X_CAPBIT(S390X_MSA)
+ | S390X_CAPBIT(S390X_STCKF)
+ | S390X_CAPBIT(S390X_MSA5),
+ S390X_CAPBIT(S390X_MSA3)
+ | S390X_CAPBIT(S390X_MSA4),
+ S390X_CAPBIT(S390X_VX)
+ | S390X_CAPBIT(S390X_VXD)
+ | S390X_CAPBIT(S390X_VXE)
+ | S390X_CAPBIT(S390X_MSA8)
+ | S390X_CAPBIT(S390X_MSA9),
+ 0ULL},
+ /*.kimd = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_1)
+ | S390X_CAPBIT(S390X_SHA_256)
+ | S390X_CAPBIT(S390X_SHA_512)
+ | S390X_CAPBIT(S390X_SHA3_224)
+ | S390X_CAPBIT(S390X_SHA3_256)
+ | S390X_CAPBIT(S390X_SHA3_384)
+ | S390X_CAPBIT(S390X_SHA3_512)
+ | S390X_CAPBIT(S390X_SHAKE_128)
+ | S390X_CAPBIT(S390X_SHAKE_256),
+ S390X_CAPBIT(S390X_GHASH)},
+ /*.klmd = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_1)
+ | S390X_CAPBIT(S390X_SHA_256)
+ | S390X_CAPBIT(S390X_SHA_512)
+ | S390X_CAPBIT(S390X_SHA3_224)
+ | S390X_CAPBIT(S390X_SHA3_256)
+ | S390X_CAPBIT(S390X_SHA3_384)
+ | S390X_CAPBIT(S390X_SHA3_512)
+ | S390X_CAPBIT(S390X_SHAKE_128)
+ | S390X_CAPBIT(S390X_SHAKE_256),
+ 0ULL},
+ /*.km = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256)
+ | S390X_CAPBIT(S390X_XTS_AES_128)
+ | S390X_CAPBIT(S390X_XTS_AES_256),
+ 0ULL},
+ /*.kmc = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmac = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmctr = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmo = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.kmf = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.prno = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_SHA_512_DRNG),
+ S390X_CAPBIT(S390X_TRNG)},
+ /*.kma = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_AES_128)
+ | S390X_CAPBIT(S390X_AES_192)
+ | S390X_CAPBIT(S390X_AES_256),
+ 0ULL},
+ /*.pcc = */{S390X_CAPBIT(S390X_QUERY),
+ S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P256)
+ | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P384)
+ | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P521)
+ | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
+ | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
+ | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519)
+ | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448)},
+ /*.kdsa = */{S390X_CAPBIT(S390X_QUERY)
+ | S390X_CAPBIT(S390X_ECDSA_VERIFY_P256)
+ | S390X_CAPBIT(S390X_ECDSA_VERIFY_P384)
+ | S390X_CAPBIT(S390X_ECDSA_VERIFY_P521)
+ | S390X_CAPBIT(S390X_ECDSA_SIGN_P256)
+ | S390X_CAPBIT(S390X_ECDSA_SIGN_P384)
+ | S390X_CAPBIT(S390X_ECDSA_SIGN_P521)
+ | S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519)
+ | S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448)
+ | S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
+ | S390X_CAPBIT(S390X_EDDSA_SIGN_ED448),
+ 0ULL},
+ };
+
+ char *tok_begin, *tok_end, *buff, tok[S390X_STFLE_MAX][LEN + 1];
+ int rc, off, i, n;
+
+ buff = malloc(strlen(env) + 1);
+ if (buff == NULL)
+ return 0;
+
+ rc = 0;
+ memset(cap, ~0, sizeof(*cap));
+ strcpy(buff, env);
+
+ tok_begin = buff + strspn(buff, ";");
+ strtok(tok_begin, ";");
+ tok_end = strtok(NULL, ";");
+
+ while (tok_begin != NULL) {
+ /* stfle token */
+ if ((n = sscanf(tok_begin,
+ " stfle : %" STR(LEN) "[^:] : "
+ "%" STR(LEN) "[^:] : %" STR(LEN) "s ",
+ tok[0], tok[1], tok[2]))) {
+ for (i = 0; i < n; i++) {
+ off = (tok[i][0] == '~') ? 1 : 0;
+ if (sscanf(tok[i] + off, "%llx", &cap->stfle[i]) != 1)
+ goto ret;
+ if (off)
+ cap->stfle[i] = ~cap->stfle[i];
+ }
+ }
+
+ /* query function tokens */
+ else if TOK_FUNC(kimd)
+ else if TOK_FUNC(klmd)
+ else if TOK_FUNC(km)
+ else if TOK_FUNC(kmc)
+ else if TOK_FUNC(kmac)
+ else if TOK_FUNC(kmctr)
+ else if TOK_FUNC(kmo)
+ else if TOK_FUNC(kmf)
+ else if TOK_FUNC(prno)
+ else if TOK_FUNC(kma)
+ else if TOK_FUNC(pcc)
+ else if TOK_FUNC(kdsa)
+
+ /* CPU model tokens */
+ else if TOK_CPU(z900)
+ else if TOK_CPU(z990)
+ else if TOK_CPU(z9)
+ else if TOK_CPU(z10)
+ else if TOK_CPU(z196)
+ else if TOK_CPU(zEC12)
+ else if TOK_CPU(z13)
+ else if TOK_CPU(z14)
+ else if TOK_CPU(z15)
+
+ /* whitespace(ignored) or invalid tokens */
+ else {
+ while (*tok_begin != '\0') {
+ if (!ossl_isspace(*tok_begin))
+ goto ret;
+ tok_begin++;
+ }
+ }
+
+ tok_begin = tok_end;
+ tok_end = strtok(NULL, ";");
}
- sigaction(SIGFPE, &oact_fpe, NULL);
- sigaction(SIGILL, &oact_ill, NULL);
- sigprocmask(SIG_SETMASK, &oset, NULL);
+ rc = 1;
+ret:
+ free(buff);
+ return rc;
}
diff --git a/crypto/s390xcpuid.pl b/crypto/s390xcpuid.pl
index 5cbb962530c5..560a2f09e97e 100755
--- a/crypto/s390xcpuid.pl
+++ b/crypto/s390xcpuid.pl
@@ -1,12 +1,15 @@
#! /usr/bin/env perl
# Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /3[12]/) {
$SIZE_T=4;
@@ -16,8 +19,7 @@ if ($flavour =~ /3[12]/) {
$g="g";
}
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$output and open STDOUT,">$output";
$ra="%r14";
$sp="%r15";
@@ -38,7 +40,26 @@ OPENSSL_s390x_facilities:
stg %r0,S390X_STFLE+8(%r4) # wipe capability vectors
stg %r0,S390X_STFLE+16(%r4)
stg %r0,S390X_STFLE+24(%r4)
- stg %r0,S390X_KIMD(%r4)
+
+ .long 0xb2b04000 # stfle 0(%r4)
+ brc 8,.Ldone
+ lghi %r0,1
+ .long 0xb2b04000 # stfle 0(%r4)
+ brc 8,.Ldone
+ lghi %r0,2
+ .long 0xb2b04000 # stfle 0(%r4)
+.Ldone:
+ br $ra
+.size OPENSSL_s390x_facilities,.-OPENSSL_s390x_facilities
+
+.globl OPENSSL_s390x_functions
+.type OPENSSL_s390x_functions,\@function
+.align 16
+OPENSSL_s390x_functions:
+ lghi %r0,0
+ larl %r4,OPENSSL_s390xcap_P
+
+ stg %r0,S390X_KIMD(%r4) # wipe capability vectors
stg %r0,S390X_KIMD+8(%r4)
stg %r0,S390X_KLMD(%r4)
stg %r0,S390X_KLMD+8(%r4)
@@ -58,16 +79,13 @@ OPENSSL_s390x_facilities:
stg %r0,S390X_PRNO+8(%r4)
stg %r0,S390X_KMA(%r4)
stg %r0,S390X_KMA+8(%r4)
+ stg %r0,S390X_PCC(%r4)
+ stg %r0,S390X_PCC+8(%r4)
+ stg %r0,S390X_KDSA(%r4)
+ stg %r0,S390X_KDSA+8(%r4)
- .long 0xb2b04000 # stfle 0(%r4)
- brc 8,.Ldone
- lghi %r0,1
- .long 0xb2b04000 # stfle 0(%r4)
- brc 8,.Ldone
- lghi %r0,2
- .long 0xb2b04000 # stfle 0(%r4)
-.Ldone:
lmg %r2,%r3,S390X_STFLE(%r4)
+
tmhl %r2,0x4000 # check for message-security-assist
jz .Lret
@@ -91,6 +109,13 @@ OPENSSL_s390x_facilities:
la %r1,S390X_KMAC(%r4)
.long 0xb91e0042 # kmac %r4,%r2
+ tmhh %r3,0x0008 # check for message-security-assist-3
+ jz .Lret
+
+ lghi %r0,S390X_QUERY # query pcc capability vector
+ la %r1,S390X_PCC(%r4)
+ .long 0xb92c0000 # pcc
+
tmhh %r3,0x0004 # check for message-security-assist-4
jz .Lret
@@ -114,6 +139,7 @@ OPENSSL_s390x_facilities:
.long 0xb93c0042 # prno %r4,%r2
lg %r2,S390X_STFLE+16(%r4)
+
tmhl %r2,0x2000 # check for message-security-assist-8
jz .Lret
@@ -121,9 +147,16 @@ OPENSSL_s390x_facilities:
la %r1,S390X_KMA(%r4)
.long 0xb9294022 # kma %r2,%r4,%r2
+ tmhl %r2,0x0010 # check for message-security-assist-9
+ jz .Lret
+
+ lghi %r0,S390X_QUERY # query kdsa capability vector
+ la %r1,S390X_KDSA(%r4)
+ .long 0xb93a0002 # kdsa %r0,%r2
+
.Lret:
br $ra
-.size OPENSSL_s390x_facilities,.-OPENSSL_s390x_facilities
+.size OPENSSL_s390x_functions,.-OPENSSL_s390x_functions
.globl OPENSSL_rdtsc
.type OPENSSL_rdtsc,\@function
@@ -411,6 +444,113 @@ s390x_kma:
___
}
+################
+# int s390x_pcc(unsigned int fc, void *param)
+{
+my ($fc,$param) = map("%r$_",(2..3));
+$code.=<<___;
+.globl s390x_pcc
+.type s390x_pcc,\@function
+.align 16
+s390x_pcc:
+ lr %r0,$fc
+ l${g}r %r1,$param
+ lhi %r2,0
+
+ .long 0xb92c0000 # pcc
+ brc 1,.-4 # pay attention to "partial completion"
+ brc 7,.Lpcc_err # if CC==0 return 0, else return 1
+.Lpcc_out:
+ br $ra
+.Lpcc_err:
+ lhi %r2,1
+ j .Lpcc_out
+.size s390x_pcc,.-s390x_pcc
+___
+}
+
+################
+# int s390x_kdsa(unsigned int fc, void *param,
+# const unsigned char *in, size_t len)
+{
+my ($fc,$param,$in,$len) = map("%r$_",(2..5));
+$code.=<<___;
+.globl s390x_kdsa
+.type s390x_kdsa,\@function
+.align 16
+s390x_kdsa:
+ lr %r0,$fc
+ l${g}r %r1,$param
+ lhi %r2,0
+
+ .long 0xb93a0004 # kdsa %r0,$in
+ brc 1,.-4 # pay attention to "partial completion"
+ brc 7,.Lkdsa_err # if CC==0 return 0, else return 1
+.Lkdsa_out:
+ br $ra
+.Lkdsa_err:
+ lhi %r2,1
+ j .Lkdsa_out
+.size s390x_kdsa,.-s390x_kdsa
+___
+}
+
+################
+# void s390x_flip_endian32(unsigned char dst[32], const unsigned char src[32])
+{
+my ($dst,$src) = map("%r$_",(2..3));
+$code.=<<___;
+.globl s390x_flip_endian32
+.type s390x_flip_endian32,\@function
+.align 16
+s390x_flip_endian32:
+ lrvg %r0,0($src)
+ lrvg %r1,8($src)
+ lrvg %r4,16($src)
+ lrvg %r5,24($src)
+ stg %r0,24($dst)
+ stg %r1,16($dst)
+ stg %r4,8($dst)
+ stg %r5,0($dst)
+ br $ra
+.size s390x_flip_endian32,.-s390x_flip_endian32
+___
+}
+
+################
+# void s390x_flip_endian64(unsigned char dst[64], const unsigned char src[64])
+{
+my ($dst,$src) = map("%r$_",(2..3));
+$code.=<<___;
+.globl s390x_flip_endian64
+.type s390x_flip_endian64,\@function
+.align 16
+s390x_flip_endian64:
+ stmg %r6,%r9,6*$SIZE_T($sp)
+
+ lrvg %r0,0($src)
+ lrvg %r1,8($src)
+ lrvg %r4,16($src)
+ lrvg %r5,24($src)
+ lrvg %r6,32($src)
+ lrvg %r7,40($src)
+ lrvg %r8,48($src)
+ lrvg %r9,56($src)
+ stg %r0,56($dst)
+ stg %r1,48($dst)
+ stg %r4,40($dst)
+ stg %r5,32($dst)
+ stg %r6,24($dst)
+ stg %r7,16($dst)
+ stg %r8,8($dst)
+ stg %r9,0($dst)
+
+ lmg %r6,%r9,6*$SIZE_T($sp)
+ br $ra
+.size s390x_flip_endian64,.-s390x_flip_endian64
+___
+}
+
$code.=<<___;
.section .init
brasl $ra,OPENSSL_cpuid_setup
diff --git a/crypto/seed/build.info b/crypto/seed/build.info
index abdcbcaa94e5..f513654ecb67 100644
--- a/crypto/seed/build.info
+++ b/crypto/seed/build.info
@@ -1,2 +1,10 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=seed.c seed_ecb.c seed_cbc.c seed_cfb.c seed_ofb.c
+$ALL=seed.c seed_ecb.c seed_cbc.c seed_cfb.c seed_ofb.c
+
+SOURCE[../../libcrypto]=$ALL
+
+# When all deprecated symbols are removed, libcrypto doesn't export the
+# seed functions, so we must include them directly in liblegacy.a
+IF[{- $disabled{'deprecated-3.0'} && !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../../providers/liblegacy.a]=$ALL
+ENDIF
diff --git a/crypto/seed/seed.c b/crypto/seed/seed.c
index c3a1f183a5cc..de3b3958ea60 100644
--- a/crypto/seed/seed.c
+++ b/crypto/seed/seed.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -34,6 +34,12 @@
*/
#ifndef OPENSSL_NO_SEED
+/*
+ * SEED low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
diff --git a/crypto/seed/seed_cbc.c b/crypto/seed/seed_cbc.c
index c9a4fe217b9b..d5a324fd4443 100644
--- a/crypto/seed/seed_cbc.c
+++ b/crypto/seed/seed_cbc.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * SEED low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/seed.h>
#include <openssl/modes.h>
diff --git a/crypto/seed/seed_cfb.c b/crypto/seed/seed_cfb.c
index 2aee1ffe39a6..24fbfbf746e3 100644
--- a/crypto/seed/seed_cfb.c
+++ b/crypto/seed/seed_cfb.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * SEED low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/seed.h>
#include <openssl/modes.h>
diff --git a/crypto/seed/seed_ecb.c b/crypto/seed/seed_ecb.c
index b6e301ccdaac..9f357511cd94 100644
--- a/crypto/seed/seed_ecb.c
+++ b/crypto/seed/seed_ecb.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * SEED low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/seed.h>
void SEED_ecb_encrypt(const unsigned char *in, unsigned char *out,
diff --git a/crypto/seed/seed_local.h b/crypto/seed/seed_local.h
index e3681f8bd455..dd40ee69deb6 100644
--- a/crypto/seed/seed_local.h
+++ b/crypto/seed/seed_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -35,7 +35,7 @@
#ifndef OSSL_CRYPTO_SEED_LOCAL_H
# define OSSL_CRYPTO_SEED_LOCAL_H
-# include "openssl/e_os2.h"
+# include <openssl/e_os2.h>
# include <openssl/seed.h>
# ifdef SEED_LONG /* need 32-bit type */
diff --git a/crypto/seed/seed_ofb.c b/crypto/seed/seed_ofb.c
index b45554058501..b2e905331d9f 100644
--- a/crypto/seed/seed_ofb.c
+++ b/crypto/seed/seed_ofb.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * SEED low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/seed.h>
#include <openssl/modes.h>
diff --git a/crypto/self_test_core.c b/crypto/self_test_core.c
new file mode 100644
index 000000000000..dad4be208a4a
--- /dev/null
+++ b/crypto/self_test_core.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/self_test.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include "internal/cryptlib.h"
+
+typedef struct self_test_cb_st
+{
+ OSSL_CALLBACK *cb;
+ void *cbarg;
+} SELF_TEST_CB;
+
+struct ossl_self_test_st
+{
+ /* local state variables */
+ const char *phase;
+ const char *type;
+ const char *desc;
+ OSSL_CALLBACK *cb;
+
+ /* callback related variables used to pass the state back to the user */
+ OSSL_PARAM params[4];
+ void *cb_arg;
+};
+
+#ifndef FIPS_MODULE
+static void *self_test_set_callback_new(OSSL_LIB_CTX *ctx)
+{
+ SELF_TEST_CB *stcb;
+
+ stcb = OPENSSL_zalloc(sizeof(*stcb));
+ return stcb;
+}
+
+static void self_test_set_callback_free(void *stcb)
+{
+ OPENSSL_free(stcb);
+}
+
+static const OSSL_LIB_CTX_METHOD self_test_set_callback_method = {
+ OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
+ self_test_set_callback_new,
+ self_test_set_callback_free,
+};
+
+static SELF_TEST_CB *get_self_test_callback(OSSL_LIB_CTX *libctx)
+{
+ return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_SELF_TEST_CB_INDEX,
+ &self_test_set_callback_method);
+}
+
+void OSSL_SELF_TEST_set_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK *cb,
+ void *cbarg)
+{
+ SELF_TEST_CB *stcb = get_self_test_callback(libctx);
+
+ if (stcb != NULL) {
+ stcb->cb = cb;
+ stcb->cbarg = cbarg;
+ }
+}
+
+void OSSL_SELF_TEST_get_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK **cb,
+ void **cbarg)
+{
+ SELF_TEST_CB *stcb = get_self_test_callback(libctx);
+
+ if (cb != NULL)
+ *cb = (stcb != NULL ? stcb->cb : NULL);
+ if (cbarg != NULL)
+ *cbarg = (stcb != NULL ? stcb->cbarg : NULL);
+}
+#endif /* FIPS_MODULE */
+
+static void self_test_setparams(OSSL_SELF_TEST *st)
+{
+ size_t n = 0;
+
+ if (st->cb != NULL) {
+ st->params[n++] =
+ OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_PHASE,
+ (char *)st->phase, 0);
+ st->params[n++] =
+ OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_TYPE,
+ (char *)st->type, 0);
+ st->params[n++] =
+ OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_DESC,
+ (char *)st->desc, 0);
+ }
+ st->params[n++] = OSSL_PARAM_construct_end();
+}
+
+OSSL_SELF_TEST *OSSL_SELF_TEST_new(OSSL_CALLBACK *cb, void *cbarg)
+{
+ OSSL_SELF_TEST *ret = OPENSSL_zalloc(sizeof(*ret));
+
+ if (ret == NULL)
+ return NULL;
+
+ ret->cb = cb;
+ ret->cb_arg = cbarg;
+ ret->phase = "";
+ ret->type = "";
+ ret->desc = "";
+ self_test_setparams(ret);
+ return ret;
+}
+
+void OSSL_SELF_TEST_free(OSSL_SELF_TEST *st)
+{
+ OPENSSL_free(st);
+}
+
+/* Can be used during application testing to log that a test has started. */
+void OSSL_SELF_TEST_onbegin(OSSL_SELF_TEST *st, const char *type,
+ const char *desc)
+{
+ if (st != NULL && st->cb != NULL) {
+ st->phase = OSSL_SELF_TEST_PHASE_START;
+ st->type = type;
+ st->desc = desc;
+ self_test_setparams(st);
+ (void)st->cb(st->params, st->cb_arg);
+ }
+}
+
+/*
+ * Can be used during application testing to log that a test has either
+ * passed or failed.
+ */
+void OSSL_SELF_TEST_onend(OSSL_SELF_TEST *st, int ret)
+{
+ if (st != NULL && st->cb != NULL) {
+ st->phase =
+ (ret == 1 ? OSSL_SELF_TEST_PHASE_PASS : OSSL_SELF_TEST_PHASE_FAIL);
+ self_test_setparams(st);
+ (void)st->cb(st->params, st->cb_arg);
+
+ st->phase = OSSL_SELF_TEST_PHASE_NONE;
+ st->type = OSSL_SELF_TEST_TYPE_NONE;
+ st->desc = OSSL_SELF_TEST_DESC_NONE;
+ }
+}
+
+/*
+ * Used for failure testing.
+ *
+ * Call the applications SELF_TEST_cb() if it exists.
+ * If the application callback decides to return 0 then the first byte of 'bytes'
+ * is modified (corrupted). This is used to modify output signatures or
+ * ciphertext before they are verified or decrypted.
+ */
+int OSSL_SELF_TEST_oncorrupt_byte(OSSL_SELF_TEST *st, unsigned char *bytes)
+{
+ if (st != NULL && st->cb != NULL) {
+ st->phase = OSSL_SELF_TEST_PHASE_CORRUPT;
+ self_test_setparams(st);
+ if (!st->cb(st->params, st->cb_arg)) {
+ bytes[0] ^= 1;
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/crypto/sha/asm/keccak1600-armv4.pl b/crypto/sha/asm/keccak1600-armv4.pl
index 39fe559e974b..eaad86d39ddf 100755
--- a/crypto/sha/asm/keccak1600-armv4.pl
+++ b/crypto/sha/asm/keccak1600-armv4.pl
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
# Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -70,9 +70,10 @@
# Cortex-Mx, x>=3. Otherwise, non-NEON results for NEON-capable
# processors are presented mostly for reference purposes.
-$flavour = shift;
-if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour && $flavour ne "void") {
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -80,9 +81,10 @@ if ($flavour && $flavour ne "void") {
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
- open STDOUT,"| \"$^X\" $xlate $flavour $output";
+ open STDOUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
} else {
- open STDOUT,">$output";
+ $output and open STDOUT,">$output";
}
my @C = map("r$_",(0..9));
@@ -113,8 +115,6 @@ my @T = map([ 8*$_, 8*($_+1), 8*($_+2), 8*($_+3), 8*($_+4) ], (30,35,40,45,50));
$code.=<<___;
#include "arm_arch.h"
-.text
-
#if defined(__thumb2__)
.syntax unified
.thumb
@@ -122,6 +122,8 @@ $code.=<<___;
.code 32
#endif
+.text
+
.type iotas32, %object
.align 5
iotas32:
@@ -691,7 +693,14 @@ ___
$code.=<<___;
blo .Lround2x
+#if __ARM_ARCH__>=5
ldr pc,[sp,#440]
+#else
+ ldr lr,[sp,#440]
+ tst lr,#1
+ moveq pc,lr @ be binary compatible with V4, yet
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
.size KeccakF1600_int,.-KeccakF1600_int
.type KeccakF1600, %function
@@ -730,7 +739,14 @@ KeccakF1600:
stmia @E[1], {@C[0]-@C[9]}
add sp,sp,#440+20
+#if __ARM_ARCH__>=5
ldmia sp!,{r4-r11,pc}
+#else
+ ldmia sp!,{r4-r11,lr}
+ tst lr,#1
+ moveq pc,lr @ be binary compatible with V4, yet
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
.size KeccakF1600,.-KeccakF1600
___
{ my ($A_flat,$inp,$len,$bsz) = map("r$_",(10..12,14));
@@ -905,7 +921,14 @@ SHA3_absorb:
.Labsorb_abort:
add sp,sp,#456+32
mov r0,$len @ return value
+#if __ARM_ARCH__>=5
ldmia sp!,{r4-r12,pc}
+#else
+ ldmia sp!,{r4-r12,lr}
+ tst lr,#1
+ moveq pc,lr @ be binary compatible with V4, yet
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
.size SHA3_absorb,.-SHA3_absorb
___
}
@@ -1055,7 +1078,14 @@ SHA3_squeeze:
.align 4
.Lsqueeze_done:
add sp,sp,#24
+#if __ARM_ARCH__>=5
ldmia sp!,{r4-r10,pc}
+#else
+ ldmia sp!,{r4-r10,lr}
+ tst lr,#1
+ moveq pc,lr @ be binary compatible with V4, yet
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
.size SHA3_squeeze,.-SHA3_squeeze
___
}
@@ -1265,7 +1295,7 @@ KeccakF1600_neon:
subs r3, r3, #1
bne .Loop_neon
- bx lr
+ ret
.size KeccakF1600_neon,.-KeccakF1600_neon
.global SHA3_absorb_neon
diff --git a/crypto/sha/asm/keccak1600-armv8.pl b/crypto/sha/asm/keccak1600-armv8.pl
index ce5df4d6de1b..65102e7c292f 100755
--- a/crypto/sha/asm/keccak1600-armv8.pl
+++ b/crypto/sha/asm/keccak1600-armv8.pl
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
# Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -51,6 +51,7 @@
# Kryo 12
# Denver 7.8
# Apple A7 7.2
+# ThunderX2 9.7
#
# (*) Corresponds to SHA3-256. No improvement coefficients are listed
# because they vary too much from compiler to compiler. Newer
@@ -58,15 +59,18 @@
# Cortex-A57 to 25% on Cortex-A53. While in comparison to older
# compiler this code is at least 2x faster...
-$flavour = shift;
-$output = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
my @rhotates = ([ 0, 1, 62, 28, 27 ],
@@ -541,30 +545,28 @@ my @A = map([ "v".$_.".16b", "v".($_+1).".16b", "v".($_+2).".16b",
(0, 5, 10, 15, 20));
my @C = map("v$_.16b", (25..31));
+my @D = @C[4,5,6,2,3];
$code.=<<___;
.type KeccakF1600_ce,%function
.align 5
KeccakF1600_ce:
- mov x9,#12
+ mov x9,#24
adr x10,iotas
b .Loop_ce
.align 4
.Loop_ce:
-___
-for($i=0; $i<2; $i++) {
-$code.=<<___;
////////////////////////////////////////////////// Theta
- eor3 $C[0],$A[0][0],$A[1][0],$A[2][0]
- eor3 $C[1],$A[0][1],$A[1][1],$A[2][1]
- eor3 $C[2],$A[0][2],$A[1][2],$A[2][2]
- eor3 $C[3],$A[0][3],$A[1][3],$A[2][3]
- eor3 $C[4],$A[0][4],$A[1][4],$A[2][4]
- eor3 $C[0],$C[0], $A[3][0],$A[4][0]
- eor3 $C[1],$C[1], $A[3][1],$A[4][1]
- eor3 $C[2],$C[2], $A[3][2],$A[4][2]
- eor3 $C[3],$C[3], $A[3][3],$A[4][3]
- eor3 $C[4],$C[4], $A[3][4],$A[4][4]
+ eor3 $C[0],$A[4][0],$A[3][0],$A[2][0]
+ eor3 $C[1],$A[4][1],$A[3][1],$A[2][1]
+ eor3 $C[2],$A[4][2],$A[3][2],$A[2][2]
+ eor3 $C[3],$A[4][3],$A[3][3],$A[2][3]
+ eor3 $C[4],$A[4][4],$A[3][4],$A[2][4]
+ eor3 $C[0],$C[0], $A[1][0],$A[0][0]
+ eor3 $C[1],$C[1], $A[1][1],$A[0][1]
+ eor3 $C[2],$C[2], $A[1][2],$A[0][2]
+ eor3 $C[3],$C[3], $A[1][3],$A[0][3]
+ eor3 $C[4],$C[4], $A[1][4],$A[0][4]
rax1 $C[5],$C[0],$C[2] // D[1]
rax1 $C[6],$C[1],$C[3] // D[2]
@@ -573,81 +575,75 @@ $code.=<<___;
rax1 $C[4],$C[4],$C[1] // D[0]
////////////////////////////////////////////////// Theta+Rho+Pi
- xar $C[0], $A[1][1],$C[5],#64-$rhotates[1][1] // C[0]=A[0][1]
- xar $A[1][1],$A[1][4],$C[3],#64-$rhotates[1][4]
- xar $A[1][4],$A[4][2],$C[6],#64-$rhotates[4][2]
- xar $A[4][2],$A[2][4],$C[3],#64-$rhotates[2][4]
- xar $A[2][4],$A[4][0],$C[4],#64-$rhotates[4][0]
+ xar $C[0], $A[0][1],$D[1],#64-$rhotates[0][1] // C[0]=A[2][0]
- xar $A[4][0],$A[0][2],$C[6],#64-$rhotates[0][2]
+ xar $A[0][1],$A[1][1],$D[1],#64-$rhotates[1][1]
+ xar $A[1][1],$A[1][4],$D[4],#64-$rhotates[1][4]
+ xar $A[1][4],$A[4][2],$D[2],#64-$rhotates[4][2]
+ xar $A[4][2],$A[2][4],$D[4],#64-$rhotates[2][4]
+ xar $A[2][4],$A[4][0],$D[0],#64-$rhotates[4][0]
- xar $A[0][2],$A[2][2],$C[6],#64-$rhotates[2][2]
- xar $A[2][2],$A[2][3],$C[2],#64-$rhotates[2][3]
- xar $A[2][3],$A[3][4],$C[3],#64-$rhotates[3][4]
- xar $A[3][4],$A[4][3],$C[2],#64-$rhotates[4][3]
- xar $A[4][3],$A[3][0],$C[4],#64-$rhotates[3][0]
+ xar $C[1], $A[0][2],$D[2],#64-$rhotates[0][2] // C[1]=A[4][0]
- xar $A[3][0],$A[0][4],$C[3],#64-$rhotates[0][4]
+ xar $A[0][2],$A[2][2],$D[2],#64-$rhotates[2][2]
+ xar $A[2][2],$A[2][3],$D[3],#64-$rhotates[2][3]
+ xar $A[2][3],$A[3][4],$D[4],#64-$rhotates[3][4]
+ xar $A[3][4],$A[4][3],$D[3],#64-$rhotates[4][3]
+ xar $A[4][3],$A[3][0],$D[0],#64-$rhotates[3][0]
- eor $A[0][0],$A[0][0],$C[4]
- ldr x11,[x10],#8
+ xar $A[3][0],$A[0][4],$D[4],#64-$rhotates[0][4]
- xar $C[1], $A[3][3],$C[2],#64-$rhotates[3][3] // C[1]=A[0][3]
- xar $A[3][3],$A[3][2],$C[6],#64-$rhotates[3][2]
- xar $A[3][2],$A[2][1],$C[5],#64-$rhotates[2][1]
- xar $A[2][1],$A[1][2],$C[6],#64-$rhotates[1][2]
- xar $A[1][2],$A[2][0],$C[4],#64-$rhotates[2][0]
+ xar $D[4], $A[4][4],$D[4],#64-$rhotates[4][4] // D[4]=A[0][4]
+ xar $A[4][4],$A[4][1],$D[1],#64-$rhotates[4][1]
+ xar $A[1][3],$A[1][3],$D[3],#64-$rhotates[1][3] // A[1][3]=A[4][1]
+ xar $A[0][4],$A[3][1],$D[1],#64-$rhotates[3][1] // A[0][4]=A[1][3]
+ xar $A[3][1],$A[1][0],$D[0],#64-$rhotates[1][0]
- xar $A[2][0],$A[0][1],$C[5],#64-$rhotates[0][1] // *
+ xar $A[1][0],$A[0][3],$D[3],#64-$rhotates[0][3]
- xar $A[0][4],$A[4][4],$C[3],#64-$rhotates[4][4]
- xar $A[4][4],$A[4][1],$C[5],#64-$rhotates[4][1]
- xar $A[4][1],$A[1][3],$C[2],#64-$rhotates[1][3]
- xar $A[1][3],$A[3][1],$C[5],#64-$rhotates[3][1]
- xar $A[3][1],$A[1][0],$C[4],#64-$rhotates[1][0]
+ eor $A[0][0],$A[0][0],$D[0]
- xar $C[2], $A[0][3],$C[2],#64-$rhotates[0][3] // C[2]=A[1][0]
+ xar $D[3], $A[3][3],$D[3],#64-$rhotates[3][3] // D[3]=A[0][3]
+ xar $A[0][3],$A[3][2],$D[2],#64-$rhotates[3][2] // A[0][3]=A[3][3]
+ xar $D[1], $A[2][1],$D[1],#64-$rhotates[2][1] // D[1]=A[3][2]
+ xar $D[2], $A[1][2],$D[2],#64-$rhotates[1][2] // D[2]=A[2][1]
+ xar $D[0], $A[2][0],$D[0],#64-$rhotates[2][0] // D[0]=A[1][2]
////////////////////////////////////////////////// Chi+Iota
- dup $C[6],x11 // borrow C[6]
- bcax $C[3], $A[0][0],$A[0][2],$C[0] // *
- bcax $A[0][1],$C[0], $C[1], $A[0][2] // *
- bcax $A[0][2],$A[0][2],$A[0][4],$C[1]
- bcax $A[0][3],$C[1], $A[0][0],$A[0][4]
- bcax $A[0][4],$A[0][4],$C[0], $A[0][0]
-
- bcax $A[1][0],$C[2], $A[1][2],$A[1][1] // *
- bcax $C[0], $A[1][1],$A[1][3],$A[1][2] // *
- bcax $A[1][2],$A[1][2],$A[1][4],$A[1][3]
- bcax $A[1][3],$A[1][3],$C[2], $A[1][4]
- bcax $A[1][4],$A[1][4],$A[1][1],$C[2]
-
- eor $A[0][0],$C[3],$C[6] // Iota
-
- bcax $C[1], $A[2][0],$A[2][2],$A[2][1] // *
- bcax $C[2], $A[2][1],$A[2][3],$A[2][2] // *
- bcax $A[2][2],$A[2][2],$A[2][4],$A[2][3]
- bcax $A[2][3],$A[2][3],$A[2][0],$A[2][4]
- bcax $A[2][4],$A[2][4],$A[2][1],$A[2][0]
+ bcax $A[4][0],$C[1], $A[4][2],$A[1][3] // A[1][3]=A[4][1]
+ bcax $A[4][1],$A[1][3],$A[4][3],$A[4][2] // A[1][3]=A[4][1]
+ bcax $A[4][2],$A[4][2],$A[4][4],$A[4][3]
+ bcax $A[4][3],$A[4][3],$C[1], $A[4][4]
+ bcax $A[4][4],$A[4][4],$A[1][3],$C[1] // A[1][3]=A[4][1]
+
+ ld1r {$C[1]},[x10],#8
- bcax $C[3], $A[3][0],$A[3][2],$A[3][1] // *
- bcax $C[4], $A[3][1],$A[3][3],$A[3][2] // *
- bcax $A[3][2],$A[3][2],$A[3][4],$A[3][3]
- bcax $A[3][3],$A[3][3],$A[3][0],$A[3][4]
+ bcax $A[3][2],$D[1], $A[3][4],$A[0][3] // A[0][3]=A[3][3]
+ bcax $A[3][3],$A[0][3],$A[3][0],$A[3][4] // A[0][3]=A[3][3]
bcax $A[3][4],$A[3][4],$A[3][1],$A[3][0]
+ bcax $A[3][0],$A[3][0],$D[1], $A[3][1]
+ bcax $A[3][1],$A[3][1],$A[0][3],$D[1] // A[0][3]=A[3][3]
+
+ bcax $A[2][0],$C[0], $A[2][2],$D[2]
+ bcax $A[2][1],$D[2], $A[2][3],$A[2][2]
+ bcax $A[2][2],$A[2][2],$A[2][4],$A[2][3]
+ bcax $A[2][3],$A[2][3],$C[0], $A[2][4]
+ bcax $A[2][4],$A[2][4],$D[2], $C[0]
+
+ bcax $A[1][2],$D[0], $A[1][4],$A[0][4] // A[0][4]=A[1][3]
+ bcax $A[1][3],$A[0][4],$A[1][0],$A[1][4] // A[0][4]=A[1][3]
+ bcax $A[1][4],$A[1][4],$A[1][1],$A[1][0]
+ bcax $A[1][0],$A[1][0],$D[0], $A[1][1]
+ bcax $A[1][1],$A[1][1],$A[0][4],$D[0] // A[0][4]=A[1][3]
+
+ bcax $A[0][3],$D[3], $A[0][0],$D[4]
+ bcax $A[0][4],$D[4], $A[0][1],$A[0][0]
+ bcax $A[0][0],$A[0][0],$A[0][2],$A[0][1]
+ bcax $A[0][1],$A[0][1],$D[3], $A[0][2]
+ bcax $A[0][2],$A[0][2],$D[4], $D[3]
+
+ eor $A[0][0],$A[0][0],$C[1]
- bcax $C[5], $A[4][0],$A[4][2],$A[4][1] // *
- bcax $C[6], $A[4][1],$A[4][3],$A[4][2] // *
- bcax $A[4][2],$A[4][2],$A[4][4],$A[4][3]
- bcax $A[4][3],$A[4][3],$A[4][0],$A[4][4]
- bcax $A[4][4],$A[4][4],$A[4][1],$A[4][0]
-___
- ( $A[1][1], $C[0]) = ( $C[0], $A[1][1]);
- ($A[2][0],$A[2][1], $C[1],$C[2]) = ($C[1],$C[2], $A[2][0],$A[2][1]);
- ($A[3][0],$A[3][1], $C[3],$C[4]) = ($C[3],$C[4], $A[3][0],$A[3][1]);
- ($A[4][0],$A[4][1], $C[5],$C[6]) = ($C[5],$C[6], $A[4][0],$A[4][1]);
-}
-$code.=<<___;
subs x9,x9,#1
bne .Loop_ce
@@ -871,7 +867,7 @@ foreach(split("\n",$code)) {
s/\`([^\`]*)\`/eval($1)/ge;
- m/\bdup\b/ and s/\.16b/.2d/g or
+ m/\bld1r\b/ and s/\.16b/.2d/g or
s/\b(eor3|rax1|xar|bcax)\s+(v.*)/unsha3($1,$2)/ge;
print $_,"\n";
diff --git a/crypto/sha/asm/keccak1600-avx2.pl b/crypto/sha/asm/keccak1600-avx2.pl
index 6104caf4ff1f..84682289bf7a 100755
--- a/crypto/sha/asm/keccak1600-avx2.pl
+++ b/crypto/sha/asm/keccak1600-avx2.pl
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
# Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -476,7 +476,6 @@ iotas:
.asciz "Keccak-1600 absorb and squeeze for AVX2, CRYPTOGAMS by <appro\@openssl.org>"
___
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
print $code;
close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/sha/asm/keccak1600-avx512.pl b/crypto/sha/asm/keccak1600-avx512.pl
index 6bfff7881756..85d6e7ffe424 100755
--- a/crypto/sha/asm/keccak1600-avx512.pl
+++ b/crypto/sha/asm/keccak1600-avx512.pl
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
# Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -545,7 +545,6 @@ iotas:
.asciz "Keccak-1600 absorb and squeeze for AVX-512F, CRYPTOGAMS by <appro\@openssl.org>"
___
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
print $code;
close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/sha/asm/keccak1600-avx512vl.pl b/crypto/sha/asm/keccak1600-avx512vl.pl
index 446706fc67d1..73e75f363f20 100755
--- a/crypto/sha/asm/keccak1600-avx512vl.pl
+++ b/crypto/sha/asm/keccak1600-avx512vl.pl
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
# Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -386,7 +386,6 @@ iotas:
.asciz "Keccak-1600 absorb and squeeze for AVX512VL, CRYPTOGAMS by <appro\@openssl.org>"
___
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
print $code;
close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/sha/asm/keccak1600-c64x.pl b/crypto/sha/asm/keccak1600-c64x.pl
index 4d1bbee2cfdd..0a9dec85c299 100755
--- a/crypto/sha/asm/keccak1600-c64x.pl
+++ b/crypto/sha/asm/keccak1600-c64x.pl
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
# Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -879,7 +879,6 @@ iotas:
.align 4
___
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
print $code;
close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/sha/asm/keccak1600-mmx.pl b/crypto/sha/asm/keccak1600-mmx.pl
index 353f1e147c3b..7657a23a9c27 100755
--- a/crypto/sha/asm/keccak1600-mmx.pl
+++ b/crypto/sha/asm/keccak1600-mmx.pl
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
# Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -65,8 +65,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386");
diff --git a/crypto/sha/asm/keccak1600-ppc64.pl b/crypto/sha/asm/keccak1600-ppc64.pl
index 11b6329f09c0..83f8d8ef337b 100755
--- a/crypto/sha/asm/keccak1600-ppc64.pl
+++ b/crypto/sha/asm/keccak1600-ppc64.pl
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
# Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -27,17 +27,20 @@
#
# r=1088(*)
#
-# PPC970/G5 14.6/+120%
-# POWER7 10.3/+100%
-# POWER8 11.5/+85%
-# POWER9 9.4/+45%
+# PPC970/G5 14.0/+130%
+# POWER7 9.7/+110%
+# POWER8 10.6/+100%
+# POWER9 8.2/+66%
#
# (*) Corresponds to SHA3-256. Percentage after slash is improvement
# over gcc-4.x-generated KECCAK_1X_ALT code. Newer compilers do
# much better (but watch out for them generating code specific
# to processor they execute on).
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /64/) {
$SIZE_T =8;
@@ -53,7 +56,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
+open STDOUT,"| $^X $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
$FRAME=24*$SIZE_T+6*$SIZE_T+32;
$LOCALS=6*$SIZE_T;
@@ -384,19 +388,19 @@ KeccakF1600:
.type dword_le_load,\@function
.align 5
dword_le_load:
- lbzu r0,1(r3)
- lbzu r4,1(r3)
- lbzu r5,1(r3)
+ lbz r0,1(r3)
+ lbz r4,2(r3)
+ lbz r5,3(r3)
insrdi r0,r4,8,48
- lbzu r4,1(r3)
+ lbz r4,4(r3)
insrdi r0,r5,8,40
- lbzu r5,1(r3)
+ lbz r5,5(r3)
insrdi r0,r4,8,32
- lbzu r4,1(r3)
+ lbz r4,6(r3)
insrdi r0,r5,8,24
- lbzu r5,1(r3)
+ lbz r5,7(r3)
insrdi r0,r4,8,16
- lbzu r4,1(r3)
+ lbzu r4,8(r3)
insrdi r0,r5,8,8
insrdi r0,r4,8,0
blr
@@ -657,21 +661,21 @@ SHA3_squeeze:
${UCMP}i $len,8
blt .Lsqueeze_tail
- stbu r0,1($out)
+ stb r0,1($out)
srdi r0,r0,8
- stbu r0,1($out)
+ stb r0,2($out)
srdi r0,r0,8
- stbu r0,1($out)
+ stb r0,3($out)
srdi r0,r0,8
- stbu r0,1($out)
+ stb r0,4($out)
srdi r0,r0,8
- stbu r0,1($out)
+ stb r0,5($out)
srdi r0,r0,8
- stbu r0,1($out)
+ stb r0,6($out)
srdi r0,r0,8
- stbu r0,1($out)
+ stb r0,7($out)
srdi r0,r0,8
- stbu r0,1($out)
+ stbu r0,8($out)
subic. $len,$len,8
beq .Lsqueeze_done
diff --git a/crypto/sha/asm/keccak1600-s390x.pl b/crypto/sha/asm/keccak1600-s390x.pl
index a7d819a59057..86233c7e38f2 100755
--- a/crypto/sha/asm/keccak1600-s390x.pl
+++ b/crypto/sha/asm/keccak1600-s390x.pl
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
# Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -30,7 +30,10 @@
# amount of instruction and assumed instruction issue rate. It's ~2.5x
# faster than compiler-generated code.
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /3[12]/) {
$SIZE_T=4;
@@ -40,8 +43,7 @@ if ($flavour =~ /3[12]/) {
$g="g";
}
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$output and open STDOUT,">$output";
my @A = map([ 8*$_, 8*($_+1), 8*($_+2), 8*($_+3), 8*($_+4) ], (0,5,10,15,20));
diff --git a/crypto/sha/asm/keccak1600-x86_64.pl b/crypto/sha/asm/keccak1600-x86_64.pl
index b1a7e65e6baa..02f0116014d6 100755
--- a/crypto/sha/asm/keccak1600-x86_64.pl
+++ b/crypto/sha/asm/keccak1600-x86_64.pl
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
# Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -50,9 +50,10 @@
# improved by 14% by replacing rotates with double-precision
# shift with same register as source and destination.
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -61,7 +62,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
my @A = map([ 8*$_-100, 8*($_+1)-100, 8*($_+2)-100,
diff --git a/crypto/sha/asm/keccak1600p8-ppc.pl b/crypto/sha/asm/keccak1600p8-ppc.pl
index c04c7deafeda..7554c87f2083 100755
--- a/crypto/sha/asm/keccak1600p8-ppc.pl
+++ b/crypto/sha/asm/keccak1600p8-ppc.pl
@@ -1,7 +1,7 @@
#!/usr/bin/env perl
# Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -25,7 +25,10 @@
# successor can achieve higher scalar instruction issue rate, then
# this module will loose... And it does on POWER9 with 12.0 vs. 9.4.
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /64/) {
$SIZE_T =8;
@@ -48,7 +51,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
+open STDOUT,"| $^X $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
$FRAME=6*$SIZE_T+13*16; # 13*16 is for v20-v31 offload
diff --git a/crypto/sha/asm/sha1-586.pl b/crypto/sha/asm/sha1-586.pl
index b72869b86d4a..00350324a117 100644
--- a/crypto/sha/asm/sha1-586.pl
+++ b/crypto/sha/asm/sha1-586.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 1998-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -123,8 +123,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386");
diff --git a/crypto/sha/asm/sha1-armv4-large.pl b/crypto/sha/asm/sha1-armv4-large.pl
index 52d426bb29f8..6a2e12bf17d7 100644
--- a/crypto/sha/asm/sha1-armv4-large.pl
+++ b/crypto/sha/asm/sha1-armv4-large.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -75,9 +75,10 @@
#
# Add ARMv8 code path performing at 2.35 cpb on Apple A7.
-$flavour = shift;
-if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour && $flavour ne "void") {
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -85,9 +86,10 @@ if ($flavour && $flavour ne "void") {
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
- open STDOUT,"| \"$^X\" $xlate $flavour $output";
+ open STDOUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
} else {
- open STDOUT,">$output";
+ $output and open STDOUT,">$output";
}
$ctx="r0";
@@ -187,7 +189,6 @@ ___
$code=<<___;
#include "arm_arch.h"
-.text
#if defined(__thumb2__)
.syntax unified
.thumb
@@ -195,6 +196,8 @@ $code=<<___;
.code 32
#endif
+.text
+
.global sha1_block_data_order
.type sha1_block_data_order,%function
@@ -202,12 +205,14 @@ $code=<<___;
sha1_block_data_order:
#if __ARM_MAX_ARCH__>=7
.Lsha1_block:
- adr r3,.Lsha1_block
ldr r12,.LOPENSSL_armcap
+# if !defined(_WIN32)
+ adr r3,.Lsha1_block
ldr r12,[r3,r12] @ OPENSSL_armcap_P
-#ifdef __APPLE__
+# endif
+# if defined(__APPLE__) || defined(_WIN32)
ldr r12,[r12]
-#endif
+# endif
tst r12,#ARMV8_SHA1
bne .LARMv8
tst r12,#ARMV7_NEON
@@ -311,7 +316,11 @@ $code.=<<___;
.LK_60_79: .word 0xca62c1d6
#if __ARM_MAX_ARCH__>=7
.LOPENSSL_armcap:
+# ifdef _WIN32
+.word OPENSSL_armcap_P
+# else
.word OPENSSL_armcap_P-.Lsha1_block
+# endif
#endif
.asciz "SHA1 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
.align 5
@@ -613,14 +622,15 @@ my ($ABCD,$E,$E0,$E1)=map("q$_",(0..3));
my @MSG=map("q$_",(4..7));
my @Kxx=map("q$_",(8..11));
my ($W0,$W1,$ABCD_SAVE)=map("q$_",(12..14));
+my $_byte = ($flavour =~ /win/ ? "DCB" : ".byte");
$code.=<<___;
#if __ARM_MAX_ARCH__>=7
# if defined(__thumb2__)
-# define INST(a,b,c,d) .byte c,d|0xf,a,b
+# define INST(a,b,c,d) $_byte c,d|0xf,a,b
# else
-# define INST(a,b,c,d) .byte a,b,c,d|0x10
+# define INST(a,b,c,d) $_byte a,b,c,d|0x10
# endif
.type sha1_block_data_order_armv8,%function
diff --git a/crypto/sha/asm/sha1-armv8.pl b/crypto/sha/asm/sha1-armv8.pl
index 557cabc018e0..cdea8845af85 100644
--- a/crypto/sha/asm/sha1-armv8.pl
+++ b/crypto/sha/asm/sha1-armv8.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -27,20 +27,24 @@
# X-Gene 8.80 (+200%)
# Mongoose 2.05 6.50 (+160%)
# Kryo 1.88 8.00 (+90%)
+# ThunderX2 2.64 6.36 (+150%)
#
# (*) Software results are presented mostly for reference purposes.
# (**) Keep in mind that Denver relies on binary translation, which
# optimizes compiler output at run-time.
-$flavour = shift;
-$output = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $1";
*STDOUT=*OUT;
($ctx,$inp,$num)=("x0","x1","x2");
@@ -58,10 +62,10 @@ $code.=<<___ if ($i<15 && !($i&1));
lsr @Xx[$i+1],@Xx[$i],#32
___
$code.=<<___ if ($i<14 && !($i&1));
- ldr @Xx[$i+2],[$inp,#`($i+2)*4-64`]
+ ldur @Xx[$i+2],[$inp,#`($i+2)*4-64`]
___
$code.=<<___ if ($i<14 && ($i&1));
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
ror @Xx[$i+1],@Xx[$i+1],#32
#else
rev32 @Xx[$i+1],@Xx[$i+1]
@@ -171,24 +175,20 @@ ___
}
$code.=<<___;
-#include "arm_arch.h"
+#ifndef __KERNEL__
+# include "arm_arch.h"
+.extern OPENSSL_armcap_P
+.hidden OPENSSL_armcap_P
+#endif
.text
-.extern OPENSSL_armcap_P
-.hidden OPENSSL_armcap_P
.globl sha1_block_data_order
.type sha1_block_data_order,%function
.align 6
sha1_block_data_order:
-#ifdef __ILP32__
- ldrsw x16,.LOPENSSL_armcap_P
-#else
- ldr x16,.LOPENSSL_armcap_P
-#endif
- adr x17,.LOPENSSL_armcap_P
- add x16,x16,x17
- ldr w16,[x16]
+ adrp x16,OPENSSL_armcap_P
+ ldr w16,[x16,#:lo12:OPENSSL_armcap_P]
tst w16,#ARMV8_SHA1
b.ne .Lv8_entry
@@ -209,7 +209,7 @@ sha1_block_data_order:
movz $K,#0x7999
sub $num,$num,#1
movk $K,#0x5a82,lsl#16
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
ror $Xx[0],@Xx[0],#32
#else
rev32 @Xx[0],@Xx[0]
@@ -322,12 +322,6 @@ $code.=<<___;
.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1 //K_20_39
.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc //K_40_59
.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6 //K_60_79
-.LOPENSSL_armcap_P:
-#ifdef __ILP32__
-.long OPENSSL_armcap_P-.
-#else
-.quad OPENSSL_armcap_P-.
-#endif
.asciz "SHA1 block transform for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
.align 2
___
diff --git a/crypto/sha/asm/sha1-c64xplus.pl b/crypto/sha/asm/sha1-c64xplus.pl
index ceec503a9829..6a97da2b5702 100644
--- a/crypto/sha/asm/sha1-c64xplus.pl
+++ b/crypto/sha/asm/sha1-c64xplus.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -32,8 +32,7 @@
# service routines are expected to preserve it and for own well-being
# zero it upon entry.
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
($CTX,$INP,$NUM) = ("A4","B4","A6"); # arguments
diff --git a/crypto/sha/asm/sha1-ia64.pl b/crypto/sha/asm/sha1-ia64.pl
index bf1d2ebeb0ab..f1b412dcf2e3 100644
--- a/crypto/sha/asm/sha1-ia64.pl
+++ b/crypto/sha/asm/sha1-ia64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -21,7 +21,8 @@
# Performance under big-endian OS such as HP-UX is 179MBps*1GHz, which
# is >50% better than HP C and >2x better than gcc.
-$output = pop;
+# $output is the last argument if it looks like a file (it has an extension)
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
$code=<<___;
.ident \"sha1-ia64.s, version 1.3\"
diff --git a/crypto/sha/asm/sha1-mb-x86_64.pl b/crypto/sha/asm/sha1-mb-x86_64.pl
index 47c588715163..67faba136d05 100644
--- a/crypto/sha/asm/sha1-mb-x86_64.pl
+++ b/crypto/sha/asm/sha1-mb-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -38,9 +38,10 @@
# in real-life application are somewhat lower, e.g. for 2KB
# fragments they range from 30% to 100% (on Haswell);
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -49,6 +50,11 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86_64-support.pl";
+
+$ptr_size=&pointer_size($flavour);
+
$avx=0;
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
@@ -70,7 +76,8 @@ if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|.*based on LLVM) ([0
$avx = ($2>=3.0) + ($2>3.0);
}
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
# void sha1_multi_block (
@@ -87,6 +94,7 @@ $inp="%rsi"; # 2nd arg
$num="%edx";
@ptr=map("%r$_",(8..11));
$Tbl="%rbp";
+$inp_elm_size=2*$ptr_size;
@V=($A,$B,$C,$D,$E)=map("%xmm$_",(0..4));
($t0,$t1,$t2,$t3,$tx)=map("%xmm$_",(5..9));
@@ -407,9 +415,12 @@ $code.=<<___;
xor $num,$num
___
for($i=0;$i<4;$i++) {
+ $ptr_reg=&pointer_register($flavour,@ptr[$i]);
$code.=<<___;
- mov `16*$i+0`($inp),@ptr[$i] # input pointer
- mov `16*$i+8`($inp),%ecx # number of blocks
+ # input pointer
+ mov `$inp_elm_size*$i+0`($inp),$ptr_reg
+ # number of blocks
+ mov `$inp_elm_size*$i+$ptr_size`($inp),%ecx
cmp $num,%ecx
cmovg %ecx,$num # find maximum
test %ecx,%ecx
@@ -486,7 +497,7 @@ $code.=<<___;
mov `$REG_SZ*17+8`(%rsp),$num
lea $REG_SZ($ctx),$ctx
- lea `16*$REG_SZ/4`($inp),$inp
+ lea `$inp_elm_size*$REG_SZ/4`($inp),$inp
dec $num
jnz .Loop_grande
@@ -564,9 +575,12 @@ $code.=<<___;
xor $num,$num
___
for($i=0;$i<2;$i++) {
+ $ptr_reg=&pointer_register($flavour,@ptr[$i]);
$code.=<<___;
- mov `16*$i+0`($inp),@ptr[$i] # input pointer
- mov `16*$i+8`($inp),%ecx # number of blocks
+ # input pointer
+ mov `$inp_elm_size*$i+0`($inp),$ptr_reg
+ # number of blocks
+ mov `$inp_elm_size*$i+$ptr_size`($inp),%ecx
cmp $num,%ecx
cmovg %ecx,$num # find maximum
test %ecx,%ecx
@@ -749,7 +763,7 @@ $code.=<<___;
movq $E0,0x80-0x40($ctx) # e1.e0
lea `$REG_SZ/2`($ctx),$ctx
- lea `16*2`($inp),$inp
+ lea `$inp_elm_size*2`($inp),$inp
dec $num
jnz .Loop_grande_shaext
@@ -1069,9 +1083,12 @@ $code.=<<___;
xor $num,$num
___
for($i=0;$i<4;$i++) {
+ $ptr_reg=&pointer_register($flavour,@ptr[$i]);
$code.=<<___;
- mov `16*$i+0`($inp),@ptr[$i] # input pointer
- mov `16*$i+8`($inp),%ecx # number of blocks
+ # input pointer
+ mov `$inp_elm_size*$i+0`($inp),$ptr_reg
+ # number of blocks
+ mov `$inp_elm_size*$i+$ptr_size`($inp),%ecx
cmp $num,%ecx
cmovg %ecx,$num # find maximum
test %ecx,%ecx
@@ -1142,7 +1159,7 @@ $code.=<<___;
mov `$REG_SZ*17+8`(%rsp),$num
lea $REG_SZ($ctx),$ctx
- lea `16*$REG_SZ/4`($inp),$inp
+ lea `$inp_elm_size*$REG_SZ/4`($inp),$inp
dec $num
jnz .Loop_grande_avx
@@ -1238,9 +1255,12 @@ $code.=<<___;
lea `$REG_SZ*16`(%rsp),%rbx
___
for($i=0;$i<8;$i++) {
+ $ptr_reg=&pointer_register($flavour,@ptr[$i]);
$code.=<<___;
- mov `16*$i+0`($inp),@ptr[$i] # input pointer
- mov `16*$i+8`($inp),%ecx # number of blocks
+ # input pointer
+ mov `$inp_elm_size*$i+0`($inp),$ptr_reg
+ # number of blocks
+ mov `$inp_elm_size*$i+$ptr_size`($inp),%ecx
cmp $num,%ecx
cmovg %ecx,$num # find maximum
test %ecx,%ecx
@@ -1311,7 +1331,7 @@ $code.=<<___;
#mov `$REG_SZ*17+8`(%rsp),$num
#lea $REG_SZ($ctx),$ctx
- #lea `16*$REG_SZ/4`($inp),$inp
+ #lea `$inp_elm_size*$REG_SZ/4`($inp),$inp
#dec $num
#jnz .Loop_grande_avx2
diff --git a/crypto/sha/asm/sha1-mips.pl b/crypto/sha/asm/sha1-mips.pl
index c293cd3bfa4e..b41dd7a5d269 100644
--- a/crypto/sha/asm/sha1-mips.pl
+++ b/crypto/sha/asm/sha1-mips.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -52,8 +52,12 @@
# ($t0,$t1,$t2,$t3,$t8,$t9)=map("\$$_",(12..15,24,25));
# ($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7)=map("\$$_",(16..23));
# ($gp,$sp,$fp,$ra)=map("\$$_",(28..31));
-#
-$flavour = shift || "o32"; # supported flavours are o32,n32,64,nubi32,nubi64
+
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+# supported flavours are o32,n32,64,nubi32,nubi64, default is o32
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : "o32";
if ($flavour =~ /64|n32/i) {
$PTR_ADD="daddu"; # incidentally works even on n32
@@ -77,8 +81,7 @@ if ($flavour =~ /64|n32/i) {
$big_endian=(`echo MIPSEB | $ENV{CC} -E -`=~/MIPSEB/)?0:1 if ($ENV{CC});
-for (@ARGV) { $output=$_ if (/\w[\w\-]*\.\w+$/); }
-open STDOUT,">$output";
+$output and open STDOUT,">$output";
if (!defined($big_endian))
{ $big_endian=(unpack('L',pack('N',1))==1); }
diff --git a/crypto/sha/asm/sha1-parisc.pl b/crypto/sha/asm/sha1-parisc.pl
index 70ef7956abfa..9eb98e8036a3 100644
--- a/crypto/sha/asm/sha1-parisc.pl
+++ b/crypto/sha/asm/sha1-parisc.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -26,9 +26,12 @@
#
# Special thanks to polarhome.com for providing HP-UX account.
-$flavour = shift;
-$output = shift;
-open STDOUT,">$output";
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+
+$output and open STDOUT,">$output";
if ($flavour =~ /64/) {
$LEVEL ="2.0W";
diff --git a/crypto/sha/asm/sha1-ppc.pl b/crypto/sha/asm/sha1-ppc.pl
index 650a62912008..acea2e94f392 100755
--- a/crypto/sha/asm/sha1-ppc.pl
+++ b/crypto/sha/asm/sha1-ppc.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -26,7 +26,10 @@
# PPC970,gcc-4.0.0 +76% +59%
# Power6,xlc-7 +68% +33%
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /64/) {
$SIZE_T =8;
@@ -53,7 +56,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
+open STDOUT,"| $^X $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
$FRAME=24*$SIZE_T+64;
$LOCALS=6*$SIZE_T;
diff --git a/crypto/sha/asm/sha1-s390x.pl b/crypto/sha/asm/sha1-s390x.pl
index 653a6cb50a8a..d870e0078eb8 100644
--- a/crypto/sha/asm/sha1-s390x.pl
+++ b/crypto/sha/asm/sha1-s390x.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -40,7 +40,10 @@
$kimdfunc=1; # magic function code for kimd instruction
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /3[12]/) {
$SIZE_T=4;
@@ -50,8 +53,7 @@ if ($flavour =~ /3[12]/) {
$g="g";
}
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$output and open STDOUT,">$output";
$K_00_39="%r0"; $K=$K_00_39;
$K_40_79="%r1";
diff --git a/crypto/sha/asm/sha1-sparcv9.pl b/crypto/sha/asm/sha1-sparcv9.pl
index 8c23d85a3d09..904eda646558 100644
--- a/crypto/sha/asm/sha1-sparcv9.pl
+++ b/crypto/sha/asm/sha1-sparcv9.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -32,8 +32,7 @@
# single-process result on 8-core processor, or ~9GBps per 2.85GHz
# socket.
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
@X=("%o0","%o1","%o2","%o3","%o4","%o5","%g1","%o7");
$rot1m="%g2";
@@ -188,7 +187,10 @@ ___
}
$code.=<<___;
-#include "sparc_arch.h"
+#ifndef __ASSEMBLER__
+# define __ASSEMBLER__ 1
+#endif
+#include "crypto/sparc_arch.h"
#ifdef __arch64__
.register %g2,#scratch
diff --git a/crypto/sha/asm/sha1-sparcv9a.pl b/crypto/sha/asm/sha1-sparcv9a.pl
index 4e90da4b8bc9..1b7a7f9c912b 100644
--- a/crypto/sha/asm/sha1-sparcv9a.pl
+++ b/crypto/sha/asm/sha1-sparcv9a.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -47,8 +47,7 @@ for (@ARGV) { $bits=64 if (/\-m64/ || /\-xarch\=v9/); }
if ($bits==64) { $bias=2047; $frame=192; }
else { $bias=0; $frame=112; }
-$output=shift;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
$ctx="%i0";
$inp="%i1";
diff --git a/crypto/sha/asm/sha1-thumb.pl b/crypto/sha/asm/sha1-thumb.pl
index b53e0bee052d..aece5ea0cddb 100644
--- a/crypto/sha/asm/sha1-thumb.pl
+++ b/crypto/sha/asm/sha1-thumb.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -26,8 +26,7 @@
# by over 40%, while code increases by only 10% or 32 bytes. But once
# again, the goal was to establish _size_ benchmark, not performance.
-$output=shift;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
$inline=0;
#$cheat_on_binutils=1;
diff --git a/crypto/sha/asm/sha1-x86_64.pl b/crypto/sha/asm/sha1-x86_64.pl
index 89146d137b9b..c66b8fca875e 100755
--- a/crypto/sha/asm/sha1-x86_64.pl
+++ b/crypto/sha/asm/sha1-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -93,9 +93,10 @@
# because SSSE3 code is compiled unconditionally;
# (**) SHAEXT result
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -126,7 +127,8 @@ if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|.*based on LLVM) ([0
$shaext=1; ### set to zero if compiling for 1.0.1
$avx=1 if (!$shaext && $avx);
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
$ctx="%rdi"; # 1st arg
diff --git a/crypto/sha/asm/sha256-586.pl b/crypto/sha/asm/sha256-586.pl
index 7523dbc165fa..8e19cd875e3f 100644
--- a/crypto/sha/asm/sha256-586.pl
+++ b/crypto/sha/asm/sha256-586.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -73,8 +73,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386");
diff --git a/crypto/sha/asm/sha256-armv4.pl b/crypto/sha/asm/sha256-armv4.pl
index d120febb4832..e8af05c2981f 100644
--- a/crypto/sha/asm/sha256-armv4.pl
+++ b/crypto/sha/asm/sha256-armv4.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -44,9 +44,10 @@
#
# Add ARMv8 code path performing at 2.0 cpb on Apple A7.
-$flavour = shift;
-if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour && $flavour ne "void") {
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -54,9 +55,10 @@ if ($flavour && $flavour ne "void") {
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
- open STDOUT,"| \"$^X\" $xlate $flavour $output";
+ open STDOUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
} else {
- open STDOUT,">$output";
+ $output and open STDOUT,">$output";
}
$ctx="r0"; $t0="r0";
@@ -181,7 +183,6 @@ $code=<<___;
# define __ARM_MAX_ARCH__ 7
#endif
-.text
#if defined(__thumb2__)
.syntax unified
.thumb
@@ -189,6 +190,8 @@ $code=<<___;
.code 32
#endif
+.text
+
.type K256,%object
.align 5
K256:
@@ -212,7 +215,11 @@ K256:
.word 0 @ terminator
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
.LOPENSSL_armcap:
+# ifdef _WIN32
+.word OPENSSL_armcap_P
+# else
.word OPENSSL_armcap_P-.Lsha256_block_data_order
+# endif
#endif
.align 5
@@ -227,10 +234,12 @@ sha256_block_data_order:
#endif
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
ldr r12,.LOPENSSL_armcap
+# if !defined(_WIN32)
ldr r12,[r3,r12] @ OPENSSL_armcap_P
-#ifdef __APPLE__
+# endif
+# if defined(__APPLE__) || defined(_WIN32)
ldr r12,[r12]
-#endif
+# endif
tst r12,#ARMV8_SHA256
bne .LARMv8
tst r12,#ARMV7_NEON
@@ -598,14 +607,15 @@ my ($ABCD,$EFGH,$abcd)=map("q$_",(0..2));
my @MSG=map("q$_",(8..11));
my ($W0,$W1,$ABCD_SAVE,$EFGH_SAVE)=map("q$_",(12..15));
my $Ktbl="r3";
+my $_byte = ($flavour =~ /win/ ? "DCB" : ".byte");
$code.=<<___;
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
# if defined(__thumb2__)
-# define INST(a,b,c,d) .byte c,d|0xc,a,b
+# define INST(a,b,c,d) $_byte c,d|0xc,a,b
# else
-# define INST(a,b,c,d) .byte a,b,c,d
+# define INST(a,b,c,d) $_byte a,b,c,d
# endif
.type sha256_block_data_order_armv8,%function
diff --git a/crypto/sha/asm/sha256-c64xplus.pl b/crypto/sha/asm/sha256-c64xplus.pl
index b2d00e4fb1ab..13fd45fd762d 100644
--- a/crypto/sha/asm/sha256-c64xplus.pl
+++ b/crypto/sha/asm/sha256-c64xplus.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -26,8 +26,7 @@
# service routines are expected to preserve it and for own well-being
# zero it upon entry.
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$output = pop and open STDOUT,">$output";
($CTXA,$INP,$NUM) = ("A4","B4","A6"); # arguments
$K256="A3";
diff --git a/crypto/sha/asm/sha256-mb-x86_64.pl b/crypto/sha/asm/sha256-mb-x86_64.pl
index c8cc6efac95c..fa2ca86046cc 100644
--- a/crypto/sha/asm/sha256-mb-x86_64.pl
+++ b/crypto/sha/asm/sha256-mb-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -39,9 +39,10 @@
# in real-life application are somewhat lower, e.g. for 2KB
# fragments they range from 75% to 130% (on Haswell);
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -50,6 +51,11 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86_64-support.pl";
+
+$ptr_size=&pointer_size($flavour);
+
$avx=0;
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
@@ -71,7 +77,8 @@ if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|.*based on LLVM) ([0
$avx = ($2>=3.0) + ($2>3.0);
}
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
# void sha256_multi_block (
@@ -91,6 +98,7 @@ $inp="%rsi"; # 2nd arg
$num="%edx"; # 3rd arg
@ptr=map("%r$_",(8..11));
$Tbl="%rbp";
+$inp_elm_size=2*$ptr_size;
@V=($A,$B,$C,$D,$E,$F,$G,$H)=map("%xmm$_",(8..15));
($t1,$t2,$t3,$axb,$bxc,$Xi,$Xn,$sigma)=map("%xmm$_",(0..7));
@@ -289,9 +297,12 @@ $code.=<<___;
xor $num,$num
___
for($i=0;$i<4;$i++) {
+ $ptr_reg=&pointer_register($flavour,@ptr[$i]);
$code.=<<___;
- mov `16*$i+0`($inp),@ptr[$i] # input pointer
- mov `16*$i+8`($inp),%ecx # number of blocks
+ # input pointer
+ mov `$inp_elm_size*$i+0`($inp),$ptr_reg
+ # number of blocks
+ mov `$inp_elm_size*$i+$ptr_size`($inp),%ecx
cmp $num,%ecx
cmovg %ecx,$num # find maximum
test %ecx,%ecx
@@ -390,7 +401,7 @@ $code.=<<___;
mov `$REG_SZ*17+8`(%rsp),$num
lea $REG_SZ($ctx),$ctx
- lea `16*$REG_SZ/4`($inp),$inp
+ lea `$inp_elm_size*$REG_SZ/4`($inp),$inp
dec $num
jnz .Loop_grande
@@ -468,9 +479,12 @@ $code.=<<___;
xor $num,$num
___
for($i=0;$i<2;$i++) {
+ $ptr_reg=&pointer_register($flavour,@ptr[$i]);
$code.=<<___;
- mov `16*$i+0`($inp),@ptr[$i] # input pointer
- mov `16*$i+8`($inp),%ecx # number of blocks
+ # input pointer
+ mov `$inp_elm_size*$i+0`($inp),$ptr_reg
+ # number of blocks
+ mov `$inp_elm_size*$i+$ptr_size`($inp),%ecx
cmp $num,%ecx
cmovg %ecx,$num # find maximum
test %ecx,%ecx
@@ -751,7 +765,7 @@ $code.=<<___;
movq @MSG0[1],0xe0-0x80($ctx) # H1.H0
lea `$REG_SZ/2`($ctx),$ctx
- lea `16*2`($inp),$inp
+ lea `$inp_elm_size*2`($inp),$inp
dec $num
jnz .Loop_grande_shaext
@@ -988,9 +1002,12 @@ $code.=<<___;
xor $num,$num
___
for($i=0;$i<4;$i++) {
+ $ptr_reg=&pointer_register($flavour,@ptr[$i]);
$code.=<<___;
- mov `16*$i+0`($inp),@ptr[$i] # input pointer
- mov `16*$i+8`($inp),%ecx # number of blocks
+ # input pointer
+ mov `$inp_elm_size*$i+0`($inp),$ptr_reg
+ # number of blocks
+ mov `$inp_elm_size*$i+$ptr_size`($inp),%ecx
cmp $num,%ecx
cmovg %ecx,$num # find maximum
test %ecx,%ecx
@@ -1087,7 +1104,7 @@ $code.=<<___;
mov `$REG_SZ*17+8`(%rsp),$num
lea $REG_SZ($ctx),$ctx
- lea `16*$REG_SZ/4`($inp),$inp
+ lea `$inp_elm_size*$REG_SZ/4`($inp),$inp
dec $num
jnz .Loop_grande_avx
@@ -1178,9 +1195,12 @@ $code.=<<___;
lea `$REG_SZ*16`(%rsp),%rbx
___
for($i=0;$i<8;$i++) {
+ $ptr_reg=&pointer_register($flavour,@ptr[$i]);
$code.=<<___;
- mov `16*$i+0`($inp),@ptr[$i] # input pointer
- mov `16*$i+8`($inp),%ecx # number of blocks
+ # input pointer
+ mov `$inp_elm_size*$i+0`($inp),$ptr_reg
+ # number of blocks
+ mov `$inp_elm_size*$i+$ptr_size`($inp),%ecx
cmp $num,%ecx
cmovg %ecx,$num # find maximum
test %ecx,%ecx
@@ -1277,7 +1297,7 @@ $code.=<<___;
#mov `$REG_SZ*17+8`(%rsp),$num
#lea $REG_SZ($ctx),$ctx
- #lea `16*$REG_SZ/4`($inp),$inp
+ #lea `$inp_elm_size*$REG_SZ/4`($inp),$inp
#dec $num
#jnz .Loop_grande_avx2
diff --git a/crypto/sha/asm/sha512-586.pl b/crypto/sha/asm/sha512-586.pl
index 66b6e96f9ded..c25e773b0aa3 100644
--- a/crypto/sha/asm/sha512-586.pl
+++ b/crypto/sha/asm/sha512-586.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -59,8 +59,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386");
diff --git a/crypto/sha/asm/sha512-armv4.pl b/crypto/sha/asm/sha512-armv4.pl
index e9c5e0ce7687..1751c671e6d8 100644
--- a/crypto/sha/asm/sha512-armv4.pl
+++ b/crypto/sha/asm/sha512-armv4.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -57,9 +57,10 @@ $hi="HI";
$lo="LO";
# ====================================================================
-$flavour = shift;
-if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour && $flavour ne "void") {
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -67,9 +68,10 @@ if ($flavour && $flavour ne "void") {
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
- open STDOUT,"| \"$^X\" $xlate $flavour $output";
+ open STDOUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
} else {
- open STDOUT,">$output";
+ $output and open STDOUT,">$output";
}
$ctx="r0"; # parameter block
@@ -196,6 +198,9 @@ $code.=<<___;
add $Ktbl,$Ktbl,#8
___
}
+
+my $_word = ($flavour =~ /win/ ? "DCDU" : ".word");
+
$code=<<___;
#ifndef __KERNEL__
# include "arm_arch.h"
@@ -211,14 +216,13 @@ $code=<<___;
#ifdef __ARMEL__
# define LO 0
# define HI 4
-# define WORD64(hi0,lo0,hi1,lo1) .word lo0,hi0, lo1,hi1
+# define WORD64(hi0,lo0,hi1,lo1) $_word lo0,hi0, lo1,hi1
#else
# define HI 0
# define LO 4
-# define WORD64(hi0,lo0,hi1,lo1) .word hi0,lo0, hi1,lo1
+# define WORD64(hi0,lo0,hi1,lo1) $_word hi0,lo0, hi1,lo1
#endif
-.text
#if defined(__thumb2__)
.syntax unified
.thumb
@@ -227,6 +231,8 @@ $code=<<___;
.code 32
#endif
+.text
+
.type K512,%object
.align 5
K512:
@@ -273,7 +279,11 @@ WORD64(0x5fcb6fab,0x3ad6faec, 0x6c44198c,0x4a475817)
.size K512,.-K512
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
.LOPENSSL_armcap:
+# ifdef _WIN32
+.word OPENSSL_armcap_P
+# else
.word OPENSSL_armcap_P-.Lsha512_block_data_order
+# endif
.skip 32-4
#else
.skip 32
@@ -290,10 +300,12 @@ sha512_block_data_order:
#endif
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
ldr r12,.LOPENSSL_armcap
+# if !defined(_WIN32)
ldr r12,[r3,r12] @ OPENSSL_armcap_P
-#ifdef __APPLE__
+# endif
+# if defined(__APPLE__) || defined(_WIN32)
ldr r12,[r12]
-#endif
+# endif
tst r12,#ARMV7_NEON
bne .LNEON
#endif
diff --git a/crypto/sha/asm/sha512-armv8.pl b/crypto/sha/asm/sha512-armv8.pl
index 3188c905ea2d..6bcff0b7d3f3 100644
--- a/crypto/sha/asm/sha512-armv8.pl
+++ b/crypto/sha/asm/sha512-armv8.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -28,6 +28,7 @@
# X-Gene 20.0 (+100%) 12.8 (+300%(***))
# Mongoose 2.36 13.0 (+50%) 8.36 (+33%)
# Kryo 1.92 17.4 (+30%) 11.2 (+8%)
+# ThunderX2 2.54 13.2 (+40%) 8.40 (+18%)
#
# (*) Software SHA256 results are of lesser relevance, presented
# mostly for informational purposes.
@@ -53,8 +54,10 @@
# deliver much less improvement, likely *negative* on Cortex-A5x.
# Which is why NEON support is limited to SHA256.]
-$output=pop;
-$flavour=pop;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour && $flavour ne "void") {
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -62,10 +65,11 @@ if ($flavour && $flavour ne "void") {
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
- open OUT,"| \"$^X\" $xlate $flavour $output";
+ open OUT,"| \"$^X\" $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
} else {
- open STDOUT,">$output";
+ $output and open STDOUT,">$output";
}
if ($output =~ /512/) {
@@ -188,25 +192,19 @@ ___
$code.=<<___;
#ifndef __KERNEL__
# include "arm_arch.h"
+.extern OPENSSL_armcap_P
+.hidden OPENSSL_armcap_P
#endif
.text
-.extern OPENSSL_armcap_P
-.hidden OPENSSL_armcap_P
.globl $func
.type $func,%function
.align 6
$func:
#ifndef __KERNEL__
-# ifdef __ILP32__
- ldrsw x16,.LOPENSSL_armcap_P
-# else
- ldr x16,.LOPENSSL_armcap_P
-# endif
- adr x17,.LOPENSSL_armcap_P
- add x16,x16,x17
- ldr w16,[x16]
+ adrp x16,OPENSSL_armcap_P
+ ldr w16,[x16,#:lo12:OPENSSL_armcap_P]
___
$code.=<<___ if ($SZ==4);
tst w16,#ARMV8_SHA256
@@ -354,15 +352,6 @@ $code.=<<___ if ($SZ==4);
___
$code.=<<___;
.size .LK$BITS,.-.LK$BITS
-#ifndef __KERNEL__
-.align 3
-.LOPENSSL_armcap_P:
-# ifdef __ILP32__
- .long OPENSSL_armcap_P-.
-# else
- .quad OPENSSL_armcap_P-.
-# endif
-#endif
.asciz "SHA$BITS block transform for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
.align 2
___
diff --git a/crypto/sha/asm/sha512-c64xplus.pl b/crypto/sha/asm/sha512-c64xplus.pl
index 4263fb1349aa..867f2a42d65b 100644
--- a/crypto/sha/asm/sha512-c64xplus.pl
+++ b/crypto/sha/asm/sha512-c64xplus.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -29,8 +29,7 @@
# service routines are expected to preserve it and for own well-being
# zero it upon entry.
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+($output = pop) =~ m|\.\w+$| and open STDOUT,">$output";
($CTXA,$INP,$NUM) = ("A4","B4","A6"); # arguments
$K512="A3";
diff --git a/crypto/sha/asm/sha512-ia64.pl b/crypto/sha/asm/sha512-ia64.pl
index 356a46aced78..e147f2682d5b 100755
--- a/crypto/sha/asm/sha512-ia64.pl
+++ b/crypto/sha/asm/sha512-ia64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -75,9 +75,10 @@
# To generate code, pass the file name with either 256 or 512 in its
# name and compiler flags.
-$output=pop;
+# $output is the last argument if it looks like a file (it has an extension)
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
-if ($output =~ /512.*\.[s|asm]/) {
+if ($output =~ /512.*\.[s|asm]/i) {
$SZ=8;
$BITS=8*$SZ;
$LDW="ld8";
@@ -91,7 +92,7 @@ if ($output =~ /512.*\.[s|asm]/) {
@sigma0=(1, 8, 7);
@sigma1=(19,61, 6);
$rounds=80;
-} elsif ($output =~ /256.*\.[s|asm]/) {
+} elsif ($output =~ /256.*\.[s|asm]/i) {
$SZ=4;
$BITS=8*$SZ;
$LDW="ld4";
@@ -107,7 +108,7 @@ if ($output =~ /512.*\.[s|asm]/) {
$rounds=64;
} else { die "nonsense $output"; }
-open STDOUT,">$output" || die "can't open $output: $!";
+$output and (open STDOUT,">$output" or die "can't open $output: $!");
if ($^O eq "hpux") {
$ADDP="addp4";
diff --git a/crypto/sha/asm/sha512-mips.pl b/crypto/sha/asm/sha512-mips.pl
index 15acd5308dda..573bb574fc6d 100644
--- a/crypto/sha/asm/sha512-mips.pl
+++ b/crypto/sha/asm/sha512-mips.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -56,7 +56,14 @@
# ($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7)=map("\$$_",(16..23));
# ($gp,$sp,$fp,$ra)=map("\$$_",(28..31));
#
-$flavour = shift || "o32"; # supported flavours are o32,n32,64,nubi32,nubi64
+# if $output doesn't have an extension, it's not an output file
+# so use it for $flavour.
+
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+# supported flavours are o32,n32,64,nubi32,nubi64, default is o32
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : "o32";
if ($flavour =~ /64|n32/i) {
$PTR_LA="dla";
@@ -83,7 +90,6 @@ $pf = ($flavour =~ /nubi/i) ? $t0 : $t2;
$big_endian=(`echo MIPSEB | $ENV{CC} -E -`=~/MIPSEB/)?0:1 if ($ENV{CC});
-for (@ARGV) { $output=$_ if (/\w[\w\-]*\.\w+$/); }
open STDOUT,">$output";
if (!defined($big_endian)) { $big_endian=(unpack('L',pack('N',1))==1); }
diff --git a/crypto/sha/asm/sha512-parisc.pl b/crypto/sha/asm/sha512-parisc.pl
index 132f1db8eb9e..d0e5a4d5cec2 100755
--- a/crypto/sha/asm/sha512-parisc.pl
+++ b/crypto/sha/asm/sha512-parisc.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -32,9 +32,12 @@
#
# Special thanks to polarhome.com for providing HP-UX account.
-$flavour = shift;
-$output = shift;
-open STDOUT,">$output";
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+
+$output and open STDOUT,">$output";
if ($flavour =~ /64/) {
$LEVEL ="2.0W";
diff --git a/crypto/sha/asm/sha512-ppc.pl b/crypto/sha/asm/sha512-ppc.pl
index 265ecfa58c87..966713936e62 100755
--- a/crypto/sha/asm/sha512-ppc.pl
+++ b/crypto/sha/asm/sha512-ppc.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -41,8 +41,10 @@
# block signals prior calling this routine. For the record, in 32-bit
# context R2 serves as TLS pointer, while in 64-bit context - R13.
-$flavour=shift;
-$output =shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /64/) {
$SIZE_T=8;
@@ -69,7 +71,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour $output" || die "can't call $xlate: $!";
+open STDOUT,"| $^X $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
if ($output =~ /512/) {
$func="sha512_block_ppc";
diff --git a/crypto/sha/asm/sha512-s390x.pl b/crypto/sha/asm/sha512-s390x.pl
index 9752fed4ea26..bc8ab0ca9fdd 100644
--- a/crypto/sha/asm/sha512-s390x.pl
+++ b/crypto/sha/asm/sha512-s390x.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -43,7 +43,10 @@
# remains z/Architecture specific. On z990 SHA256 was measured to
# perform 2.4x and SHA512 - 13x better than code generated by gcc 4.3.
-$flavour = shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /3[12]/) {
$SIZE_T=4;
@@ -71,7 +74,6 @@ $tbl="%r13";
$T1="%r14";
$sp="%r15";
-while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
open STDOUT,">$output";
if ($output =~ /512/) {
diff --git a/crypto/sha/asm/sha512-sparcv9.pl b/crypto/sha/asm/sha512-sparcv9.pl
index 54429d34e398..6bf366ef1241 100644
--- a/crypto/sha/asm/sha512-sparcv9.pl
+++ b/crypto/sha/asm/sha512-sparcv9.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -56,8 +56,10 @@
# saturates at 11.5x single-process result on 8-core processor, or
# ~11/16GBps per 2.85GHz socket.
-$output=pop;
-open STDOUT,">$output";
+# $output is the last argument if it looks like a file (it has an extension)
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+
+$output and open STDOUT,">$output";
if ($output =~ /512/) {
$label="512";
@@ -392,7 +394,10 @@ ___
} if ($SZ==8);
$code.=<<___;
-#include "sparc_arch.h"
+#ifndef __ASSEMBLER__
+# define __ASSEMBLER__ 1
+#endif
+#include "crypto/sparc_arch.h"
#ifdef __arch64__
.register %g2,#scratch
diff --git a/crypto/sha/asm/sha512-x86_64.pl b/crypto/sha/asm/sha512-x86_64.pl
index ad37850e6130..1bd0256954b3 100755
--- a/crypto/sha/asm/sha512-x86_64.pl
+++ b/crypto/sha/asm/sha512-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -10,7 +10,7 @@
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
# project. Rights for redistribution and usage in source and binary
-# forms are granted according to the OpenSSL license.
+# forms are granted according to the License.
# ====================================================================
#
# sha256/512_block procedure for x86_64.
@@ -109,9 +109,10 @@
# below certain limit makes no difference/sense; to conserve
# space SHA256 XOP code path is therefore omitted;
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -142,7 +143,8 @@ if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|.*based on LLVM) ([0
$shaext=1; ### set to zero if compiling for 1.0.1
$avx=1 if (!$shaext && $avx);
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
if ($output =~ /512/) {
diff --git a/crypto/sha/asm/sha512p8-ppc.pl b/crypto/sha/asm/sha512p8-ppc.pl
index 3f202964261d..97df14ef4ccd 100755
--- a/crypto/sha/asm/sha512p8-ppc.pl
+++ b/crypto/sha/asm/sha512p8-ppc.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -40,8 +40,10 @@
# SHA256 9.7 [15.8] 11.2 [12.5]
# SHA512 6.1 [10.3] 7.0 [7.9]
-$flavour=shift;
-$output =shift;
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour =~ /64/) {
$SIZE_T=8;
@@ -64,7 +66,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
-open STDOUT,"| $^X $xlate $flavour $output" || die "can't call $xlate: $!";
+open STDOUT,"| $^X $xlate $flavour \"$output\""
+ or die "can't call $xlate: $!";
if ($output =~ /512/) {
$bits=512;
diff --git a/crypto/sha/build.info b/crypto/sha/build.info
index 5dd5a9941d34..d61f7de9b6bd 100644
--- a/crypto/sha/build.info
+++ b/crypto/sha/build.info
@@ -1,89 +1,176 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- sha1dgst.c sha1_one.c sha256.c sha512.c {- $target{sha1_asm_src} -} \
- {- $target{keccak1600_asm_src} -}
-
-GENERATE[sha1-586.s]=asm/sha1-586.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-DEPEND[sha1-586.s]=../perlasm/x86asm.pl
-GENERATE[sha256-586.s]=asm/sha256-586.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-DEPEND[sha256-586.s]=../perlasm/x86asm.pl
-GENERATE[sha512-586.s]=asm/sha512-586.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-DEPEND[sha512-586.s]=../perlasm/x86asm.pl
-
-GENERATE[sha1-ia64.s]=asm/sha1-ia64.pl $(LIB_CFLAGS) $(LIB_CPPFLAGS)
-GENERATE[sha256-ia64.s]=asm/sha512-ia64.pl $(LIB_CFLAGS) $(LIB_CPPFLAGS)
-GENERATE[sha512-ia64.s]=asm/sha512-ia64.pl $(LIB_CFLAGS) $(LIB_CPPFLAGS)
-
-GENERATE[sha1-alpha.S]=asm/sha1-alpha.pl $(PERLASM_SCHEME)
-
-GENERATE[sha1-x86_64.s]=asm/sha1-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[sha1-mb-x86_64.s]=asm/sha1-mb-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[sha256-x86_64.s]=asm/sha512-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[sha256-mb-x86_64.s]=asm/sha256-mb-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[sha512-x86_64.s]=asm/sha512-x86_64.pl $(PERLASM_SCHEME)
-GENERATE[keccak1600-x86_64.s]=asm/keccak1600-x86_64.pl $(PERLASM_SCHEME)
-
-GENERATE[sha1-sparcv9.S]=asm/sha1-sparcv9.pl $(PERLASM_SCHEME)
+
+$SHA1ASM=
+IF[{- !$disabled{asm} -}]
+ $SHA1ASM_x86=sha1-586.S sha256-586.S sha512-586.S
+ $SHA1DEF_x86=SHA1_ASM SHA256_ASM SHA512_ASM
+ $SHA1ASM_x86_64=\
+ sha1-x86_64.s sha256-x86_64.s sha512-x86_64.s sha1-mb-x86_64.s \
+ sha256-mb-x86_64.s
+ $SHA1DEF_x86_64=SHA1_ASM SHA256_ASM SHA512_ASM
+
+ $SHA1ASM_ia64=sha1-ia64.s sha256-ia64.s sha512-ia64.s
+ $SHA1DEF_ia64=SHA1_ASM SHA256_ASM SHA512_ASM
+
+ $SHA1ASM_sparcv9=sha1-sparcv9.S sha256-sparcv9.S sha512-sparcv9.S
+ $SHA1DEF_sparcv9=SHA1_ASM SHA256_ASM SHA512_ASM
+
+ $SHA1ASM_alpha=sha1-alpha.S
+ $SHA1DEF_alpha=SHA1_ASM
+
+ $SHA1ASM_mips32=sha1-mips.S sha256-mips.S
+ $SHA1DEF_mips32=SHA1_ASM SHA256_ASM
+ $SHA1ASM_mips64=$SHA1ASM_mips32 sha512-mips.S
+ $SHA1DEF_mips64=$SHA1DEF_mips32 SHA512_ASM
+
+ $SHA1ASM_s390x=sha1-s390x.S sha256-s390x.S sha512-s390x.S
+ $SHA1DEF_s390x=SHA1_ASM SHA256_ASM SHA512_ASM
+
+ $SHA1ASM_armv4=sha1-armv4-large.S sha256-armv4.S sha512-armv4.S
+ $SHA1DEF_armv4=SHA1_ASM SHA256_ASM SHA512_ASM
+ $SHA1ASM_aarch64=sha1-armv8.S sha256-armv8.S sha512-armv8.S
+ $SHA1DEF_aarch64=SHA1_ASM SHA256_ASM SHA512_ASM
+
+ $SHA1ASM_parisc11=sha1-parisc.s sha256-parisc.s sha512-parisc.s
+ $SHA1DEF_parisc11=SHA1_ASM SHA256_ASM SHA512_ASM
+ $SHA1ASM_parisc20_64=$SHA1ASM_parisc11
+ $SHA1DEF_parisc20_64=$SHA1DEF_parisc11
+
+ $SHA1ASM_ppc32=\
+ sha_ppc.c sha1-ppc.s sha256-ppc.s sha512-ppc.s sha256p8-ppc.s \
+ sha512p8-ppc.s
+ $SHA1DEF_ppc32=SHA1_ASM SHA256_ASM SHA512_ASM
+ $SHA1ASM_ppc64=$SHA1ASM_ppc32
+ $SHA1DEF_ppc64=$SHA1DEF_ppc32
+
+ $SHA1ASM_c64xplus=sha1-c64xplus.s sha256-c64xplus.s sha512-c64xplus.s
+ $SHA1DEF_c64xplus=SHA1_ASM SHA256_ASM SHA512_ASM
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+ IF[$SHA1ASM_{- $target{asm_arch} -}]
+ $SHA1ASM=$SHA1ASM_{- $target{asm_arch} -}
+ $SHA1DEF=$SHA1DEF_{- $target{asm_arch} -}
+ ENDIF
+ENDIF
+
+$KECCAK1600ASM=keccak1600.c
+IF[{- !$disabled{asm} -}]
+ $KECCAK1600ASM_x86=
+ $KECCAK1600ASM_x86_64=keccak1600-x86_64.s
+
+ $KECCAK1600ASM_s390x=keccak1600-s390x.S
+
+ $KECCAK1600ASM_armv4=keccak1600-armv4.S
+ $KECCAK1600ASM_aarch64=keccak1600-armv8.S
+
+ $KECCAK1600ASM_ppc64=keccak1600-ppc64.s
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+ IF[$KECCAK1600ASM_{- $target{asm_arch} -}]
+ $KECCAK1600ASM=$KECCAK1600ASM_{- $target{asm_arch} -}
+ $KECCAK1600DEF=KECCAK1600_ASM
+ ENDIF
+ENDIF
+
+$COMMON=sha1dgst.c sha256.c sha512.c sha3.c $SHA1ASM $KECCAK1600ASM
+SOURCE[../../libcrypto]=$COMMON sha1_one.c
+SOURCE[../../providers/libfips.a]= $COMMON
+
+# Implementations are now spread across several libraries, so the defines
+# need to be applied to all affected libraries and modules.
+DEFINE[../../libcrypto]=$SHA1DEF $KECCAK1600DEF
+DEFINE[../../providers/libfips.a]=$SHA1DEF $KECCAK1600DEF
+DEFINE[../../providers/libdefault.a]=$SHA1DEF $KECCAK1600DEF
+# We only need to include the SHA1DEF and KECCAK1600DEF stuff in the
+# legacy provider when it's a separate module and it's dynamically
+# linked with libcrypto. Otherwise, it already gets everything that
+# the static libcrypto.a has, and doesn't need it added again.
+IF[{- !$disabled{module} && !$disabled{shared} -}]
+ DEFINE[../providers/liblegacy.a]=$SHA1DEF $KECCAK1600DEF
+ENDIF
+
+GENERATE[sha1-586.S]=asm/sha1-586.pl
+DEPEND[sha1-586.S]=../perlasm/x86asm.pl
+GENERATE[sha256-586.S]=asm/sha256-586.pl
+DEPEND[sha256-586.S]=../perlasm/x86asm.pl
+GENERATE[sha512-586.S]=asm/sha512-586.pl
+DEPEND[sha512-586.S]=../perlasm/x86asm.pl
+
+GENERATE[sha1-ia64.s]=asm/sha1-ia64.pl
+GENERATE[sha256-ia64.s]=asm/sha512-ia64.pl
+GENERATE[sha512-ia64.s]=asm/sha512-ia64.pl
+
+GENERATE[sha1-alpha.S]=asm/sha1-alpha.pl
+
+GENERATE[sha1-x86_64.s]=asm/sha1-x86_64.pl
+GENERATE[sha1-mb-x86_64.s]=asm/sha1-mb-x86_64.pl
+GENERATE[sha256-x86_64.s]=asm/sha512-x86_64.pl
+GENERATE[sha256-mb-x86_64.s]=asm/sha256-mb-x86_64.pl
+GENERATE[sha512-x86_64.s]=asm/sha512-x86_64.pl
+GENERATE[keccak1600-x86_64.s]=asm/keccak1600-x86_64.pl
+
+GENERATE[sha1-sparcv9a.S]=asm/sha1-sparcv9a.pl
+GENERATE[sha1-sparcv9.S]=asm/sha1-sparcv9.pl
INCLUDE[sha1-sparcv9.o]=..
-GENERATE[sha256-sparcv9.S]=asm/sha512-sparcv9.pl $(PERLASM_SCHEME)
+GENERATE[sha256-sparcv9.S]=asm/sha512-sparcv9.pl
INCLUDE[sha256-sparcv9.o]=..
-GENERATE[sha512-sparcv9.S]=asm/sha512-sparcv9.pl $(PERLASM_SCHEME)
+GENERATE[sha512-sparcv9.S]=asm/sha512-sparcv9.pl
INCLUDE[sha512-sparcv9.o]=..
-GENERATE[sha1-ppc.s]=asm/sha1-ppc.pl $(PERLASM_SCHEME)
-GENERATE[sha256-ppc.s]=asm/sha512-ppc.pl $(PERLASM_SCHEME)
-GENERATE[sha512-ppc.s]=asm/sha512-ppc.pl $(PERLASM_SCHEME)
-GENERATE[sha256p8-ppc.s]=asm/sha512p8-ppc.pl $(PERLASM_SCHEME)
-GENERATE[sha512p8-ppc.s]=asm/sha512p8-ppc.pl $(PERLASM_SCHEME)
-GENERATE[keccak1600-ppc64.s]=asm/keccak1600-ppc64.pl $(PERLASM_SCHEME)
+GENERATE[sha1-ppc.s]=asm/sha1-ppc.pl
+GENERATE[sha256-ppc.s]=asm/sha512-ppc.pl
+GENERATE[sha512-ppc.s]=asm/sha512-ppc.pl
+GENERATE[sha256p8-ppc.s]=asm/sha512p8-ppc.pl
+GENERATE[sha512p8-ppc.s]=asm/sha512p8-ppc.pl
+GENERATE[keccak1600-ppc64.s]=asm/keccak1600-ppc64.pl
-GENERATE[sha1-parisc.s]=asm/sha1-parisc.pl $(PERLASM_SCHEME)
-GENERATE[sha256-parisc.s]=asm/sha512-parisc.pl $(PERLASM_SCHEME)
-GENERATE[sha512-parisc.s]=asm/sha512-parisc.pl $(PERLASM_SCHEME)
+GENERATE[sha1-parisc.s]=asm/sha1-parisc.pl
+GENERATE[sha256-parisc.s]=asm/sha512-parisc.pl
+GENERATE[sha512-parisc.s]=asm/sha512-parisc.pl
-GENERATE[sha1-mips.S]=asm/sha1-mips.pl $(PERLASM_SCHEME)
+GENERATE[sha1-mips.S]=asm/sha1-mips.pl
INCLUDE[sha1-mips.o]=..
-GENERATE[sha256-mips.S]=asm/sha512-mips.pl $(PERLASM_SCHEME)
+GENERATE[sha256-mips.S]=asm/sha512-mips.pl
INCLUDE[sha256-mips.o]=..
-GENERATE[sha512-mips.S]=asm/sha512-mips.pl $(PERLASM_SCHEME)
+GENERATE[sha512-mips.S]=asm/sha512-mips.pl
INCLUDE[sha512-mips.o]=..
-GENERATE[sha1-armv4-large.S]=asm/sha1-armv4-large.pl $(PERLASM_SCHEME)
+GENERATE[sha1-armv4-large.S]=asm/sha1-armv4-large.pl
INCLUDE[sha1-armv4-large.o]=..
-GENERATE[sha256-armv4.S]=asm/sha256-armv4.pl $(PERLASM_SCHEME)
+GENERATE[sha256-armv4.S]=asm/sha256-armv4.pl
INCLUDE[sha256-armv4.o]=..
-GENERATE[sha512-armv4.S]=asm/sha512-armv4.pl $(PERLASM_SCHEME)
+GENERATE[sha512-armv4.S]=asm/sha512-armv4.pl
INCLUDE[sha512-armv4.o]=..
-GENERATE[keccak1600-armv4.S]=asm/keccak1600-armv4.pl $(PERLASM_SCHEME)
+GENERATE[keccak1600-armv4.S]=asm/keccak1600-armv4.pl
INCLUDE[keccak1600-armv4.o]=..
-GENERATE[sha1-armv8.S]=asm/sha1-armv8.pl $(PERLASM_SCHEME)
+GENERATE[sha1-armv8.S]=asm/sha1-armv8.pl
INCLUDE[sha1-armv8.o]=..
-GENERATE[sha256-armv8.S]=asm/sha512-armv8.pl $(PERLASM_SCHEME)
+GENERATE[sha256-armv8.S]=asm/sha512-armv8.pl
INCLUDE[sha256-armv8.o]=..
-GENERATE[sha512-armv8.S]=asm/sha512-armv8.pl $(PERLASM_SCHEME)
+GENERATE[sha512-armv8.S]=asm/sha512-armv8.pl
INCLUDE[sha512-armv8.o]=..
-GENERATE[keccak1600-armv8.S]=asm/keccak1600-armv8.pl $(PERLASM_SCHEME)
+GENERATE[keccak1600-armv8.S]=asm/keccak1600-armv8.pl
-GENERATE[sha1-s390x.S]=asm/sha1-s390x.pl $(PERLASM_SCHEME)
+GENERATE[sha1-s390x.S]=asm/sha1-s390x.pl
INCLUDE[sha1-s390x.o]=..
-GENERATE[sha256-s390x.S]=asm/sha512-s390x.pl $(PERLASM_SCHEME)
+GENERATE[sha256-s390x.S]=asm/sha512-s390x.pl
INCLUDE[sha256-s390x.o]=..
-GENERATE[sha512-s390x.S]=asm/sha512-s390x.pl $(PERLASM_SCHEME)
+GENERATE[sha512-s390x.S]=asm/sha512-s390x.pl
INCLUDE[sha512-s390x.o]=..
-GENERATE[keccak1600-s390x.S]=asm/keccak1600-s390x.pl $(PERLASM_SCHEME)
-
-BEGINRAW[Makefile(unix)]
-##### SHA assembler implementations
-
-# GNU make "catch all"
-{- $builddir -}/sha1-%.S: {- $sourcedir -}/asm/sha1-%.pl
- CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@
-{- $builddir -}/sha256-%.S: {- $sourcedir -}/asm/sha512-%.pl
- CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@
-{- $builddir -}/sha512-%.S: {- $sourcedir -}/asm/sha512-%.pl
- CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@
-ENDRAW[Makefile(unix)]
+GENERATE[keccak1600-s390x.S]=asm/keccak1600-s390x.pl
+
+GENERATE[sha1-c64xplus.S]=asm/sha1-c64xplus.pl
+GENERATE[sha256-c64xplus.S]=asm/sha256-c64xplus.pl
+GENERATE[sha512-c64xplus.S]=asm/sha512-c64xplus.pl
+GENERATE[keccak1600-c64x.S]=asm/keccak1600-c64x.pl
+
+# These are not yet used
+GENERATE[keccak1600-avx2.S]=asm/keccak1600-avx2.pl
+GENERATE[keccak1600-avx512.S]=asm/keccak1600-avx512.pl
+GENERATE[keccak1600-avx512vl.S]=asm/keccak1600-avx512vl.pl
+GENERATE[keccak1600-mmx.S]=asm/keccak1600-mmx.pl
+GENERATE[keccak1600p8-ppc.S]=asm/keccak1600p8-ppc.pl
+GENERATE[sha1-thumb.S]=asm/sha1-thumb.pl
diff --git a/crypto/sha/keccak1600.c b/crypto/sha/keccak1600.c
index 55a44023d51a..ccbf12b1c60d 100644
--- a/crypto/sha/keccak1600.c
+++ b/crypto/sha/keccak1600.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -25,7 +25,14 @@ void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r);
# define KECCAK_2X /* default to KECCAK_2X variant */
#endif
-#if defined(__i386) || defined(__i386__) || defined(_M_IX86)
+#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
+ (defined(__x86_64) && !defined(__BMI__)) || defined(_M_X64) || \
+ defined(__mips) || defined(__riscv) || defined(__s390__) || \
+ defined(__EMSCRIPTEN__)
+/*
+ * These don't have "and with complement" instruction, so minimize amount
+ * of "not"-s. Implemented only in the [default] KECCAK_2X variant.
+ */
# define KECCAK_COMPLEMENTING_TRANSFORM
#endif
@@ -1083,7 +1090,7 @@ size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len,
}
/*
- * SHA3_squeeze is called once at the end to generate |out| hash value
+ * sha3_squeeze is called once at the end to generate |out| hash value
* of |len| bytes.
*/
void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r)
diff --git a/crypto/sha/sha1_one.c b/crypto/sha/sha1_one.c
index e5b38211d2da..d1fa3d84f12a 100644
--- a/crypto/sha/sha1_one.c
+++ b/crypto/sha/sha1_one.c
@@ -1,18 +1,26 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * SHA-1 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/sha.h>
+#include <openssl/evp.h>
+#include "crypto/sha.h"
-unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md)
+unsigned char *ossl_sha1(const unsigned char *d, size_t n, unsigned char *md)
{
SHA_CTX c;
static unsigned char m[SHA_DIGEST_LENGTH];
@@ -26,3 +34,48 @@ unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md)
OPENSSL_cleanse(&c, sizeof(c));
return md;
}
+
+unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md)
+{
+ static unsigned char m[SHA_DIGEST_LENGTH];
+
+ if (md == NULL)
+ md = m;
+ return EVP_Q_digest(NULL, "SHA1", NULL, d, n, md, NULL) ? md : NULL;
+}
+
+unsigned char *SHA224(const unsigned char *d, size_t n, unsigned char *md)
+{
+ static unsigned char m[SHA224_DIGEST_LENGTH];
+
+ if (md == NULL)
+ md = m;
+ return EVP_Q_digest(NULL, "SHA224", NULL, d, n, md, NULL) ? md : NULL;
+}
+
+unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md)
+{
+ static unsigned char m[SHA256_DIGEST_LENGTH];
+
+ if (md == NULL)
+ md = m;
+ return EVP_Q_digest(NULL, "SHA256", NULL, d, n, md, NULL) ? md : NULL;
+}
+
+unsigned char *SHA384(const unsigned char *d, size_t n, unsigned char *md)
+{
+ static unsigned char m[SHA384_DIGEST_LENGTH];
+
+ if (md == NULL)
+ md = m;
+ return EVP_Q_digest(NULL, "SHA384", NULL, d, n, md, NULL) ? md : NULL;
+}
+
+unsigned char *SHA512(const unsigned char *d, size_t n, unsigned char *md)
+{
+ static unsigned char m[SHA512_DIGEST_LENGTH];
+
+ if (md == NULL)
+ md = m;
+ return EVP_Q_digest(NULL, "SHA512", NULL, d, n, md, NULL) ? md : NULL;
+}
diff --git a/crypto/sha/sha1dgst.c b/crypto/sha/sha1dgst.c
index 7965829e64b0..65d7e62e58e7 100644
--- a/crypto/sha/sha1dgst.c
+++ b/crypto/sha/sha1dgst.c
@@ -1,17 +1,80 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * SHA-1 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/crypto.h>
#include <openssl/opensslconf.h>
-# include <openssl/opensslv.h>
+#include <openssl/opensslv.h>
+#include <openssl/evp.h>
+#include <openssl/sha.h>
/* The implementation is in ../md32_common.h */
-# include "sha_local.h"
+#include "sha_local.h"
+#include "crypto/sha.h"
+
+int ossl_sha1_ctrl(SHA_CTX *sha1, int cmd, int mslen, void *ms)
+{
+ unsigned char padtmp[40];
+ unsigned char sha1tmp[SHA_DIGEST_LENGTH];
+
+ if (cmd != EVP_CTRL_SSL3_MASTER_SECRET)
+ return -2;
+
+ if (sha1 == NULL)
+ return 0;
+
+ /* SSLv3 client auth handling: see RFC-6101 5.6.8 */
+ if (mslen != 48)
+ return 0;
+
+ /* At this point hash contains all handshake messages, update
+ * with master secret and pad_1.
+ */
+
+ if (SHA1_Update(sha1, ms, mslen) <= 0)
+ return 0;
+
+ /* Set padtmp to pad_1 value */
+ memset(padtmp, 0x36, sizeof(padtmp));
+
+ if (!SHA1_Update(sha1, padtmp, sizeof(padtmp)))
+ return 0;
+
+ if (!SHA1_Final(sha1tmp, sha1))
+ return 0;
+
+ /* Reinitialise context */
+
+ if (!SHA1_Init(sha1))
+ return 0;
+
+ if (SHA1_Update(sha1, ms, mslen) <= 0)
+ return 0;
+
+ /* Set padtmp to pad_2 value */
+ memset(padtmp, 0x5c, sizeof(padtmp));
+
+ if (!SHA1_Update(sha1, padtmp, sizeof(padtmp)))
+ return 0;
+
+ if (!SHA1_Update(sha1, sha1tmp, sizeof(sha1tmp)))
+ return 0;
+
+ /* Now when ctx is finalised it will return the SSL v3 hash value */
+ OPENSSL_cleanse(sha1tmp, sizeof(sha1tmp));
+
+ return 1;
+}
diff --git a/crypto/sha/sha256.c b/crypto/sha/sha256.c
index 11050ba54714..5845c389379e 100644
--- a/crypto/sha/sha256.c
+++ b/crypto/sha/sha256.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * SHA256 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/opensslconf.h>
#include <stdlib.h>
@@ -15,6 +21,7 @@
#include <openssl/crypto.h>
#include <openssl/sha.h>
#include <openssl/opensslv.h>
+#include "internal/endian.h"
int SHA224_Init(SHA256_CTX *c)
{
@@ -46,34 +53,6 @@ int SHA256_Init(SHA256_CTX *c)
return 1;
}
-unsigned char *SHA224(const unsigned char *d, size_t n, unsigned char *md)
-{
- SHA256_CTX c;
- static unsigned char m[SHA224_DIGEST_LENGTH];
-
- if (md == NULL)
- md = m;
- SHA224_Init(&c);
- SHA256_Update(&c, d, n);
- SHA256_Final(md, &c);
- OPENSSL_cleanse(&c, sizeof(c));
- return md;
-}
-
-unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md)
-{
- SHA256_CTX c;
- static unsigned char m[SHA256_DIGEST_LENGTH];
-
- if (md == NULL)
- md = m;
- SHA256_Init(&c);
- SHA256_Update(&c, d, n);
- SHA256_Final(md, &c);
- OPENSSL_cleanse(&c, sizeof(c));
- return md;
-}
-
int SHA224_Update(SHA256_CTX *c, const void *data, size_t len)
{
return SHA256_Update(c, data, len);
@@ -250,12 +229,7 @@ static void sha256_block_data_order(SHA256_CTX *ctx, const void *in,
SHA_LONG X[16];
int i;
const unsigned char *data = in;
- const union {
- long one;
- char little;
- } is_endian = {
- 1
- };
+ DECLARE_IS_ENDIAN;
while (num--) {
@@ -268,7 +242,7 @@ static void sha256_block_data_order(SHA256_CTX *ctx, const void *in,
g = ctx->h[6];
h = ctx->h[7];
- if (!is_endian.little && sizeof(SHA_LONG) == 4
+ if (!IS_LITTLE_ENDIAN && sizeof(SHA_LONG) == 4
&& ((size_t)in % 4) == 0) {
const SHA_LONG *W = (const SHA_LONG *)data;
diff --git a/crypto/sha/sha3.c b/crypto/sha/sha3.c
new file mode 100644
index 000000000000..633bc2e1208b
--- /dev/null
+++ b/crypto/sha/sha3.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include "internal/sha3.h"
+
+void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r);
+
+void ossl_sha3_reset(KECCAK1600_CTX *ctx)
+{
+ memset(ctx->A, 0, sizeof(ctx->A));
+ ctx->bufsz = 0;
+}
+
+int ossl_sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen)
+{
+ size_t bsz = SHA3_BLOCKSIZE(bitlen);
+
+ if (bsz <= sizeof(ctx->buf)) {
+ ossl_sha3_reset(ctx);
+ ctx->block_size = bsz;
+ ctx->md_size = bitlen / 8;
+ ctx->pad = pad;
+ return 1;
+ }
+
+ return 0;
+}
+
+int ossl_keccak_kmac_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen)
+{
+ int ret = ossl_sha3_init(ctx, pad, bitlen);
+
+ if (ret)
+ ctx->md_size *= 2;
+ return ret;
+}
+
+int ossl_sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len)
+{
+ const unsigned char *inp = _inp;
+ size_t bsz = ctx->block_size;
+ size_t num, rem;
+
+ if (len == 0)
+ return 1;
+
+ if ((num = ctx->bufsz) != 0) { /* process intermediate buffer? */
+ rem = bsz - num;
+
+ if (len < rem) {
+ memcpy(ctx->buf + num, inp, len);
+ ctx->bufsz += len;
+ return 1;
+ }
+ /*
+ * We have enough data to fill or overflow the intermediate
+ * buffer. So we append |rem| bytes and process the block,
+ * leaving the rest for later processing...
+ */
+ memcpy(ctx->buf + num, inp, rem);
+ inp += rem, len -= rem;
+ (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
+ ctx->bufsz = 0;
+ /* ctx->buf is processed, ctx->num is guaranteed to be zero */
+ }
+
+ if (len >= bsz)
+ rem = SHA3_absorb(ctx->A, inp, len, bsz);
+ else
+ rem = len;
+
+ if (rem) {
+ memcpy(ctx->buf, inp + len - rem, rem);
+ ctx->bufsz = rem;
+ }
+
+ return 1;
+}
+
+int ossl_sha3_final(unsigned char *md, KECCAK1600_CTX *ctx)
+{
+ size_t bsz = ctx->block_size;
+ size_t num = ctx->bufsz;
+
+ if (ctx->md_size == 0)
+ return 1;
+
+ /*
+ * Pad the data with 10*1. Note that |num| can be |bsz - 1|
+ * in which case both byte operations below are performed on
+ * same byte...
+ */
+ memset(ctx->buf + num, 0, bsz - num);
+ ctx->buf[num] = ctx->pad;
+ ctx->buf[bsz - 1] |= 0x80;
+
+ (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
+
+ SHA3_squeeze(ctx->A, md, ctx->md_size, bsz);
+
+ return 1;
+}
diff --git a/crypto/sha/sha512.c b/crypto/sha/sha512.c
index ca1f387a64f8..ff035c469f94 100644
--- a/crypto/sha/sha512.c
+++ b/crypto/sha/sha512.c
@@ -1,12 +1,19 @@
/*
- * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * SHA512 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <stdio.h>
#include <openssl/opensslconf.h>
/*-
* IMPLEMENTATION NOTES.
@@ -60,6 +67,14 @@
# define SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA
#endif
+#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
+# define U64(C) C##UI64
+#elif defined(__arch64__)
+# define U64(C) C##UL
+#else
+# define U64(C) C##ULL
+#endif
+
int sha512_224_init(SHA512_CTX *c)
{
c->h[0] = U64(0x8c3d37c819544da2);
@@ -323,34 +338,6 @@ void SHA512_Transform(SHA512_CTX *c, const unsigned char *data)
sha512_block_data_order(c, data, 1);
}
-unsigned char *SHA384(const unsigned char *d, size_t n, unsigned char *md)
-{
- SHA512_CTX c;
- static unsigned char m[SHA384_DIGEST_LENGTH];
-
- if (md == NULL)
- md = m;
- SHA384_Init(&c);
- SHA512_Update(&c, d, n);
- SHA512_Final(md, &c);
- OPENSSL_cleanse(&c, sizeof(c));
- return md;
-}
-
-unsigned char *SHA512(const unsigned char *d, size_t n, unsigned char *md)
-{
- SHA512_CTX c;
- static unsigned char m[SHA512_DIGEST_LENGTH];
-
- if (md == NULL)
- md = m;
- SHA512_Init(&c);
- SHA512_Update(&c, d, n);
- SHA512_Final(md, &c);
- OPENSSL_cleanse(&c, sizeof(c));
- return md;
-}
-
#ifndef SHA512_ASM
static const SHA_LONG64 K512[80] = {
U64(0x428a2f98d728ae22), U64(0x7137449123ef65cd),
diff --git a/crypto/sha/sha_local.h b/crypto/sha/sha_local.h
index 6edb9ef1d27e..81de72ba4f90 100644
--- a/crypto/sha/sha_local.h
+++ b/crypto/sha/sha_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,6 +12,7 @@
#include <openssl/opensslconf.h>
#include <openssl/sha.h>
+#include "internal/endian.h"
#define DATA_ORDER_IS_BIG_ENDIAN
@@ -151,14 +152,9 @@ static void HASH_BLOCK_DATA_ORDER(SHA_CTX *c, const void *p, size_t num)
E = c->h4;
for (;;) {
- const union {
- long one;
- char little;
- } is_endian = {
- 1
- };
-
- if (!is_endian.little && sizeof(SHA_LONG) == 4
+ DECLARE_IS_ENDIAN;
+
+ if (!IS_LITTLE_ENDIAN && sizeof(SHA_LONG) == 4
&& ((size_t)p % 4) == 0) {
const SHA_LONG *W = (const SHA_LONG *)data;
diff --git a/crypto/sha/sha_ppc.c b/crypto/sha/sha_ppc.c
new file mode 100644
index 000000000000..accf19d8a231
--- /dev/null
+++ b/crypto/sha/sha_ppc.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2009-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/opensslconf.h>
+#include <openssl/sha.h>
+#include "crypto/ppc_arch.h"
+
+void sha256_block_p8(void *ctx, const void *inp, size_t len);
+void sha256_block_ppc(void *ctx, const void *inp, size_t len);
+void sha256_block_data_order(void *ctx, const void *inp, size_t len);
+void sha256_block_data_order(void *ctx, const void *inp, size_t len)
+{
+ OPENSSL_ppccap_P & PPC_CRYPTO207 ? sha256_block_p8(ctx, inp, len) :
+ sha256_block_ppc(ctx, inp, len);
+}
+
+void sha512_block_p8(void *ctx, const void *inp, size_t len);
+void sha512_block_ppc(void *ctx, const void *inp, size_t len);
+void sha512_block_data_order(void *ctx, const void *inp, size_t len);
+void sha512_block_data_order(void *ctx, const void *inp, size_t len)
+{
+ OPENSSL_ppccap_P & PPC_CRYPTO207 ? sha512_block_p8(ctx, inp, len) :
+ sha512_block_ppc(ctx, inp, len);
+}
diff --git a/crypto/siphash/build.info b/crypto/siphash/build.info
index 4166344a5bfb..432b6f5ec355 100644
--- a/crypto/siphash/build.info
+++ b/crypto/siphash/build.info
@@ -1,5 +1,3 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
- siphash.c \
- siphash_pmeth.c \
- siphash_ameth.c
+ siphash.c
diff --git a/crypto/siphash/siphash.c b/crypto/siphash/siphash.c
index 07d94c1e6e59..57f61c1db1a5 100644
--- a/crypto/siphash/siphash.c
+++ b/crypto/siphash/siphash.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -28,11 +28,6 @@
#include <openssl/crypto.h>
#include "crypto/siphash.h"
-#include "siphash_local.h"
-
-/* default: SipHash-2-4 */
-#define SIPHASH_C_ROUNDS 2
-#define SIPHASH_D_ROUNDS 4
#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
@@ -146,7 +141,7 @@ void SipHash_Update(SIPHASH *ctx, const unsigned char *in, size_t inlen)
uint64_t m;
const uint8_t *end;
int left;
- int i;
+ unsigned int i;
uint64_t v0 = ctx->v0;
uint64_t v1 = ctx->v1;
uint64_t v2 = ctx->v2;
@@ -202,14 +197,14 @@ void SipHash_Update(SIPHASH *ctx, const unsigned char *in, size_t inlen)
int SipHash_Final(SIPHASH *ctx, unsigned char *out, size_t outlen)
{
/* finalize hash */
- int i;
+ unsigned int i;
uint64_t b = ctx->total_inlen << 56;
uint64_t v0 = ctx->v0;
uint64_t v1 = ctx->v1;
uint64_t v2 = ctx->v2;
uint64_t v3 = ctx->v3;
- if (outlen != (size_t)ctx->hash_size)
+ if (ctx->crounds == 0 || outlen == 0 || outlen != (size_t)ctx->hash_size)
return 0;
switch (ctx->len) {
diff --git a/crypto/siphash/siphash_ameth.c b/crypto/siphash/siphash_ameth.c
deleted file mode 100644
index 7fce76390ef4..000000000000
--- a/crypto/siphash/siphash_ameth.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/evp.h>
-#include "crypto/asn1.h"
-#include "crypto/siphash.h"
-#include "siphash_local.h"
-#include "crypto/evp.h"
-
-/*
- * SIPHASH "ASN1" method. This is just here to indicate the maximum
- * SIPHASH output length and to free up a SIPHASH key.
- */
-
-static int siphash_size(const EVP_PKEY *pkey)
-{
- return SIPHASH_MAX_DIGEST_SIZE;
-}
-
-static void siphash_key_free(EVP_PKEY *pkey)
-{
- ASN1_OCTET_STRING *os = EVP_PKEY_get0(pkey);
-
- if (os != NULL) {
- if (os->data != NULL)
- OPENSSL_cleanse(os->data, os->length);
- ASN1_OCTET_STRING_free(os);
- }
-}
-
-static int siphash_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
-{
- /* nothing (including ASN1_PKEY_CTRL_DEFAULT_MD_NID), is supported */
- return -2;
-}
-
-static int siphash_pkey_public_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
-{
- return ASN1_OCTET_STRING_cmp(EVP_PKEY_get0(a), EVP_PKEY_get0(b)) == 0;
-}
-
-static int siphash_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
- size_t len)
-{
- ASN1_OCTET_STRING *os;
-
- if (pkey->pkey.ptr != NULL || len != SIPHASH_KEY_SIZE)
- return 0;
-
- os = ASN1_OCTET_STRING_new();
- if (os == NULL)
- return 0;
-
- if (!ASN1_OCTET_STRING_set(os, priv, len)) {
- ASN1_OCTET_STRING_free(os);
- return 0;
- }
-
- pkey->pkey.ptr = os;
- return 1;
-}
-
-static int siphash_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
- size_t *len)
-{
- ASN1_OCTET_STRING *os = (ASN1_OCTET_STRING *)pkey->pkey.ptr;
-
- if (priv == NULL) {
- *len = SIPHASH_KEY_SIZE;
- return 1;
- }
-
- if (os == NULL || *len < SIPHASH_KEY_SIZE)
- return 0;
-
- memcpy(priv, ASN1_STRING_get0_data(os), ASN1_STRING_length(os));
- *len = SIPHASH_KEY_SIZE;
-
- return 1;
-}
-
-const EVP_PKEY_ASN1_METHOD siphash_asn1_meth = {
- EVP_PKEY_SIPHASH,
- EVP_PKEY_SIPHASH,
- 0,
-
- "SIPHASH",
- "OpenSSL SIPHASH method",
-
- 0, 0, siphash_pkey_public_cmp, 0,
-
- 0, 0, 0,
-
- siphash_size,
- 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-
- siphash_key_free,
- siphash_pkey_ctrl,
- NULL,
- NULL,
-
- NULL,
- NULL,
- NULL,
-
- NULL,
- NULL,
- NULL,
-
- siphash_set_priv_key,
- NULL,
- siphash_get_priv_key,
- NULL,
-};
diff --git a/crypto/siphash/siphash_local.h b/crypto/siphash/siphash_local.h
deleted file mode 100644
index 5ad34764634d..000000000000
--- a/crypto/siphash/siphash_local.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/* Based on https://131002.net/siphash C reference implementation */
-
-struct siphash_st {
- uint64_t total_inlen;
- uint64_t v0;
- uint64_t v1;
- uint64_t v2;
- uint64_t v3;
- unsigned int len;
- int hash_size;
- int crounds;
- int drounds;
- unsigned char leavings[SIPHASH_BLOCK_SIZE];
-};
diff --git a/crypto/siphash/siphash_pmeth.c b/crypto/siphash/siphash_pmeth.c
deleted file mode 100644
index 0c7d2c61902c..000000000000
--- a/crypto/siphash/siphash_pmeth.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-#include <openssl/evp.h>
-#include <openssl/err.h>
-#include "crypto/siphash.h"
-#include "siphash_local.h"
-#include "crypto/evp.h"
-
-/* SIPHASH pkey context structure */
-
-typedef struct siphash_pkey_ctx_st {
- ASN1_OCTET_STRING ktmp; /* Temp storage for key */
- SIPHASH ctx;
-} SIPHASH_PKEY_CTX;
-
-static int pkey_siphash_init(EVP_PKEY_CTX *ctx)
-{
- SIPHASH_PKEY_CTX *pctx;
-
- if ((pctx = OPENSSL_zalloc(sizeof(*pctx))) == NULL) {
- CRYPTOerr(CRYPTO_F_PKEY_SIPHASH_INIT, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- pctx->ktmp.type = V_ASN1_OCTET_STRING;
-
- EVP_PKEY_CTX_set_data(ctx, pctx);
- EVP_PKEY_CTX_set0_keygen_info(ctx, NULL, 0);
- return 1;
-}
-
-static void pkey_siphash_cleanup(EVP_PKEY_CTX *ctx)
-{
- SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
-
- if (pctx != NULL) {
- OPENSSL_clear_free(pctx->ktmp.data, pctx->ktmp.length);
- OPENSSL_clear_free(pctx, sizeof(*pctx));
- EVP_PKEY_CTX_set_data(ctx, NULL);
- }
-}
-
-static int pkey_siphash_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
-{
- SIPHASH_PKEY_CTX *sctx, *dctx;
-
- /* allocate memory for dst->data and a new SIPHASH_CTX in dst->data->ctx */
- if (!pkey_siphash_init(dst))
- return 0;
- sctx = EVP_PKEY_CTX_get_data(src);
- dctx = EVP_PKEY_CTX_get_data(dst);
- if (ASN1_STRING_get0_data(&sctx->ktmp) != NULL &&
- !ASN1_STRING_copy(&dctx->ktmp, &sctx->ktmp)) {
- /* cleanup and free the SIPHASH_PKEY_CTX in dst->data */
- pkey_siphash_cleanup(dst);
- return 0;
- }
- memcpy(&dctx->ctx, &sctx->ctx, sizeof(SIPHASH));
- return 1;
-}
-
-static int pkey_siphash_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
-{
- ASN1_OCTET_STRING *key;
- SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
-
- if (ASN1_STRING_get0_data(&pctx->ktmp) == NULL)
- return 0;
- key = ASN1_OCTET_STRING_dup(&pctx->ktmp);
- if (key == NULL)
- return 0;
- return EVP_PKEY_assign_SIPHASH(pkey, key);
-}
-
-static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx));
-
- SipHash_Update(&pctx->ctx, data, count);
- return 1;
-}
-
-static int siphash_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
-{
- SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
- const unsigned char* key;
- size_t len;
-
- key = EVP_PKEY_get0_siphash(EVP_PKEY_CTX_get0_pkey(ctx), &len);
- if (key == NULL || len != SIPHASH_KEY_SIZE)
- return 0;
- EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
- EVP_MD_CTX_set_update_fn(mctx, int_update);
- return SipHash_Init(&pctx->ctx, key, 0, 0);
-}
-static int siphash_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
- EVP_MD_CTX *mctx)
-{
- SIPHASH_PKEY_CTX *pctx = ctx->data;
-
- *siglen = SipHash_hash_size(&pctx->ctx);
- if (sig != NULL)
- return SipHash_Final(&pctx->ctx, sig, *siglen);
- return 1;
-}
-
-static int pkey_siphash_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
-{
- SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
- const unsigned char *key;
- size_t len;
-
- switch (type) {
-
- case EVP_PKEY_CTRL_MD:
- /* ignore */
- break;
-
- case EVP_PKEY_CTRL_SET_DIGEST_SIZE:
- return SipHash_set_hash_size(&pctx->ctx, p1);
-
- case EVP_PKEY_CTRL_SET_MAC_KEY:
- case EVP_PKEY_CTRL_DIGESTINIT:
- if (type == EVP_PKEY_CTRL_SET_MAC_KEY) {
- /* user explicitly setting the key */
- key = p2;
- len = p1;
- } else {
- /* user indirectly setting the key via EVP_DigestSignInit */
- key = EVP_PKEY_get0_siphash(EVP_PKEY_CTX_get0_pkey(ctx), &len);
- }
- if (key == NULL || len != SIPHASH_KEY_SIZE ||
- !ASN1_OCTET_STRING_set(&pctx->ktmp, key, len))
- return 0;
- /* use default rounds (2,4) */
- return SipHash_Init(&pctx->ctx, ASN1_STRING_get0_data(&pctx->ktmp),
- 0, 0);
-
- default:
- return -2;
-
- }
- return 1;
-}
-
-static int pkey_siphash_ctrl_str(EVP_PKEY_CTX *ctx,
- const char *type, const char *value)
-{
- if (value == NULL)
- return 0;
- if (strcmp(type, "digestsize") == 0) {
- size_t hash_size = atoi(value);
-
- return pkey_siphash_ctrl(ctx, EVP_PKEY_CTRL_SET_DIGEST_SIZE, hash_size,
- NULL);
- }
- if (strcmp(type, "key") == 0)
- return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
- if (strcmp(type, "hexkey") == 0)
- return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
- return -2;
-}
-
-const EVP_PKEY_METHOD siphash_pkey_meth = {
- EVP_PKEY_SIPHASH,
- EVP_PKEY_FLAG_SIGCTX_CUSTOM, /* we don't deal with a separate MD */
- pkey_siphash_init,
- pkey_siphash_copy,
- pkey_siphash_cleanup,
-
- 0, 0,
-
- 0,
- pkey_siphash_keygen,
-
- 0, 0,
-
- 0, 0,
-
- 0, 0,
-
- siphash_signctx_init,
- siphash_signctx,
-
- 0, 0,
-
- 0, 0,
-
- 0, 0,
-
- 0, 0,
-
- pkey_siphash_ctrl,
- pkey_siphash_ctrl_str
-};
diff --git a/crypto/sm2/build.info b/crypto/sm2/build.info
index be76d96d3160..a50d08d0bc9a 100644
--- a/crypto/sm2/build.info
+++ b/crypto/sm2/build.info
@@ -1,5 +1,5 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
- sm2_sign.c sm2_crypt.c sm2_err.c sm2_pmeth.c
+ sm2_sign.c sm2_crypt.c sm2_err.c sm2_key.c
diff --git a/crypto/sm2/sm2_crypt.c b/crypto/sm2/sm2_crypt.c
index 83b97f4edc88..5318c6199f68 100644
--- a/crypto/sm2/sm2_crypt.c
+++ b/crypto/sm2/sm2_crypt.c
@@ -3,15 +3,21 @@
* Copyright 2017 Ribose Inc. All Rights Reserved.
* Ported from Ribose contributions from Botan.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include "crypto/sm2.h"
#include "crypto/sm2err.h"
-#include "crypto/ec.h" /* ecdh_KDF_X9_63() */
+#include "crypto/ec.h" /* ossl_ecdh_kdf_X9_63() */
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
@@ -61,14 +67,15 @@ static size_t ec_field_size(const EC_GROUP *group)
return field_size;
}
-int sm2_plaintext_size(const unsigned char *ct, size_t ct_size, size_t *pt_size)
+int ossl_sm2_plaintext_size(const unsigned char *ct, size_t ct_size,
+ size_t *pt_size)
{
struct SM2_Ciphertext_st *sm2_ctext = NULL;
sm2_ctext = d2i_SM2_Ciphertext(NULL, &ct, ct_size);
if (sm2_ctext == NULL) {
- SM2err(SM2_F_SM2_PLAINTEXT_SIZE, SM2_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING);
return 0;
}
@@ -78,11 +85,11 @@ int sm2_plaintext_size(const unsigned char *ct, size_t ct_size, size_t *pt_size)
return 1;
}
-int sm2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len,
- size_t *ct_size)
+int ossl_sm2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest,
+ size_t msg_len, size_t *ct_size)
{
const size_t field_size = ec_field_size(EC_KEY_get0_group(key));
- const int md_size = EVP_MD_size(digest);
+ const int md_size = EVP_MD_get_size(digest);
size_t sz;
if (field_size == 0 || md_size < 0)
@@ -98,10 +105,10 @@ int sm2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len,
return 1;
}
-int sm2_encrypt(const EC_KEY *key,
- const EVP_MD *digest,
- const uint8_t *msg,
- size_t msg_len, uint8_t *ciphertext_buf, size_t *ciphertext_len)
+int ossl_sm2_encrypt(const EC_KEY *key,
+ const EVP_MD *digest,
+ const uint8_t *msg, size_t msg_len,
+ uint8_t *ciphertext_buf, size_t *ciphertext_len)
{
int rc = 0, ciphertext_leni;
size_t i;
@@ -122,28 +129,31 @@ int sm2_encrypt(const EC_KEY *key,
uint8_t *x2y2 = NULL;
uint8_t *C3 = NULL;
size_t field_size;
- const int C3_size = EVP_MD_size(digest);
+ const int C3_size = EVP_MD_get_size(digest);
+ EVP_MD *fetched_digest = NULL;
+ OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key);
+ const char *propq = ossl_ec_key_get0_propq(key);
/* NULL these before any "goto done" */
ctext_struct.C2 = NULL;
ctext_struct.C3 = NULL;
if (hash == NULL || C3_size <= 0) {
- SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
field_size = ec_field_size(group);
if (field_size == 0) {
- SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
kG = EC_POINT_new(group);
kP = EC_POINT_new(group);
- ctx = BN_CTX_new();
+ ctx = BN_CTX_new_ex(libctx);
if (kG == NULL || kP == NULL || ctx == NULL) {
- SM2err(SM2_F_SM2_ENCRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
@@ -155,7 +165,7 @@ int sm2_encrypt(const EC_KEY *key,
y2 = BN_CTX_get(ctx);
if (y2 == NULL) {
- SM2err(SM2_F_SM2_ENCRYPT, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
goto done;
}
@@ -163,14 +173,14 @@ int sm2_encrypt(const EC_KEY *key,
C3 = OPENSSL_zalloc(C3_size);
if (x2y2 == NULL || C3 == NULL) {
- SM2err(SM2_F_SM2_ENCRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
memset(ciphertext_buf, 0, *ciphertext_len);
- if (!BN_priv_rand_range(k, order)) {
- SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR);
+ if (!BN_priv_rand_range_ex(k, order, 0, ctx)) {
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
@@ -178,38 +188,43 @@ int sm2_encrypt(const EC_KEY *key,
|| !EC_POINT_get_affine_coordinates(group, kG, x1, y1, ctx)
|| !EC_POINT_mul(group, kP, NULL, P, k, ctx)
|| !EC_POINT_get_affine_coordinates(group, kP, x2, y2, ctx)) {
- SM2err(SM2_F_SM2_ENCRYPT, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB);
goto done;
}
if (BN_bn2binpad(x2, x2y2, field_size) < 0
|| BN_bn2binpad(y2, x2y2 + field_size, field_size) < 0) {
- SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
msg_mask = OPENSSL_zalloc(msg_len);
if (msg_mask == NULL) {
- SM2err(SM2_F_SM2_ENCRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
/* X9.63 with no salt happens to match the KDF used in SM2 */
- if (!ecdh_KDF_X9_63(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0,
- digest)) {
- SM2err(SM2_F_SM2_ENCRYPT, ERR_R_EVP_LIB);
+ if (!ossl_ecdh_kdf_X9_63(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0,
+ digest, libctx, propq)) {
+ ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
goto done;
}
for (i = 0; i != msg_len; ++i)
msg_mask[i] ^= msg[i];
- if (EVP_DigestInit(hash, digest) == 0
+ fetched_digest = EVP_MD_fetch(libctx, EVP_MD_get0_name(digest), propq);
+ if (fetched_digest == NULL) {
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
+ goto done;
+ }
+ if (EVP_DigestInit(hash, fetched_digest) == 0
|| EVP_DigestUpdate(hash, x2y2, field_size) == 0
|| EVP_DigestUpdate(hash, msg, msg_len) == 0
|| EVP_DigestUpdate(hash, x2y2 + field_size, field_size) == 0
|| EVP_DigestFinal(hash, C3, NULL) == 0) {
- SM2err(SM2_F_SM2_ENCRYPT, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
goto done;
}
@@ -219,19 +234,19 @@ int sm2_encrypt(const EC_KEY *key,
ctext_struct.C2 = ASN1_OCTET_STRING_new();
if (ctext_struct.C3 == NULL || ctext_struct.C2 == NULL) {
- SM2err(SM2_F_SM2_ENCRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
if (!ASN1_OCTET_STRING_set(ctext_struct.C3, C3, C3_size)
|| !ASN1_OCTET_STRING_set(ctext_struct.C2, msg_mask, msg_len)) {
- SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
ciphertext_leni = i2d_SM2_Ciphertext(&ctext_struct, &ciphertext_buf);
/* Ensure cast to size_t is safe */
if (ciphertext_leni < 0) {
- SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
*ciphertext_len = (size_t)ciphertext_leni;
@@ -239,6 +254,7 @@ int sm2_encrypt(const EC_KEY *key,
rc = 1;
done:
+ EVP_MD_free(fetched_digest);
ASN1_OCTET_STRING_free(ctext_struct.C2);
ASN1_OCTET_STRING_free(ctext_struct.C3);
OPENSSL_free(msg_mask);
@@ -251,10 +267,10 @@ int sm2_encrypt(const EC_KEY *key,
return rc;
}
-int sm2_decrypt(const EC_KEY *key,
- const EVP_MD *digest,
- const uint8_t *ciphertext,
- size_t ciphertext_len, uint8_t *ptext_buf, size_t *ptext_len)
+int ossl_sm2_decrypt(const EC_KEY *key,
+ const EVP_MD *digest,
+ const uint8_t *ciphertext, size_t ciphertext_len,
+ uint8_t *ptext_buf, size_t *ptext_len)
{
int rc = 0;
int i;
@@ -267,12 +283,14 @@ int sm2_decrypt(const EC_KEY *key,
uint8_t *x2y2 = NULL;
uint8_t *computed_C3 = NULL;
const size_t field_size = ec_field_size(group);
- const int hash_size = EVP_MD_size(digest);
+ const int hash_size = EVP_MD_get_size(digest);
uint8_t *msg_mask = NULL;
const uint8_t *C2 = NULL;
const uint8_t *C3 = NULL;
int msg_len = 0;
EVP_MD_CTX *hash = NULL;
+ OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key);
+ const char *propq = ossl_ec_key_get0_propq(key);
if (field_size == 0 || hash_size <= 0)
goto done;
@@ -282,12 +300,12 @@ int sm2_decrypt(const EC_KEY *key,
sm2_ctext = d2i_SM2_Ciphertext(NULL, &ciphertext, ciphertext_len);
if (sm2_ctext == NULL) {
- SM2err(SM2_F_SM2_DECRYPT, SM2_R_ASN1_ERROR);
+ ERR_raise(ERR_LIB_SM2, SM2_R_ASN1_ERROR);
goto done;
}
if (sm2_ctext->C3->length != hash_size) {
- SM2err(SM2_F_SM2_DECRYPT, SM2_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING);
goto done;
}
@@ -295,13 +313,13 @@ int sm2_decrypt(const EC_KEY *key,
C3 = sm2_ctext->C3->data;
msg_len = sm2_ctext->C2->length;
if (*ptext_len < (size_t)msg_len) {
- SM2err(SM2_F_SM2_DECRYPT, SM2_R_BUFFER_TOO_SMALL);
+ ERR_raise(ERR_LIB_SM2, SM2_R_BUFFER_TOO_SMALL);
goto done;
}
- ctx = BN_CTX_new();
+ ctx = BN_CTX_new_ex(libctx);
if (ctx == NULL) {
- SM2err(SM2_F_SM2_DECRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
@@ -310,7 +328,7 @@ int sm2_decrypt(const EC_KEY *key,
y2 = BN_CTX_get(ctx);
if (y2 == NULL) {
- SM2err(SM2_F_SM2_DECRYPT, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
goto done;
}
@@ -319,13 +337,13 @@ int sm2_decrypt(const EC_KEY *key,
computed_C3 = OPENSSL_zalloc(hash_size);
if (msg_mask == NULL || x2y2 == NULL || computed_C3 == NULL) {
- SM2err(SM2_F_SM2_DECRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
C1 = EC_POINT_new(group);
if (C1 == NULL) {
- SM2err(SM2_F_SM2_DECRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
@@ -334,15 +352,15 @@ int sm2_decrypt(const EC_KEY *key,
|| !EC_POINT_mul(group, C1, NULL, C1, EC_KEY_get0_private_key(key),
ctx)
|| !EC_POINT_get_affine_coordinates(group, C1, x2, y2, ctx)) {
- SM2err(SM2_F_SM2_DECRYPT, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB);
goto done;
}
if (BN_bn2binpad(x2, x2y2, field_size) < 0
|| BN_bn2binpad(y2, x2y2 + field_size, field_size) < 0
- || !ecdh_KDF_X9_63(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0,
- digest)) {
- SM2err(SM2_F_SM2_DECRYPT, ERR_R_INTERNAL_ERROR);
+ || !ossl_ecdh_kdf_X9_63(msg_mask, msg_len, x2y2, 2 * field_size,
+ NULL, 0, digest, libctx, propq)) {
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
@@ -351,7 +369,7 @@ int sm2_decrypt(const EC_KEY *key,
hash = EVP_MD_CTX_new();
if (hash == NULL) {
- SM2err(SM2_F_SM2_DECRYPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
@@ -360,12 +378,12 @@ int sm2_decrypt(const EC_KEY *key,
|| !EVP_DigestUpdate(hash, ptext_buf, msg_len)
|| !EVP_DigestUpdate(hash, x2y2 + field_size, field_size)
|| !EVP_DigestFinal(hash, computed_C3, NULL)) {
- SM2err(SM2_F_SM2_DECRYPT, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
goto done;
}
if (CRYPTO_memcmp(computed_C3, C3, hash_size) != 0) {
- SM2err(SM2_F_SM2_DECRYPT, SM2_R_INVALID_DIGEST);
+ ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_DIGEST);
goto done;
}
diff --git a/crypto/sm2/sm2_err.c b/crypto/sm2/sm2_err.c
index e5973e9c7140..d420d4e597d1 100644
--- a/crypto/sm2/sm2_err.c
+++ b/crypto/sm2/sm2_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,31 +11,9 @@
#include <openssl/err.h>
#include "crypto/sm2err.h"
-#ifndef OPENSSL_NO_ERR
+#ifndef OPENSSL_NO_SM2
-static const ERR_STRING_DATA SM2_str_functs[] = {
- {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_COPY, 0), "pkey_sm2_copy"},
- {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_CTRL, 0), "pkey_sm2_ctrl"},
- {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_CTRL_STR, 0), "pkey_sm2_ctrl_str"},
- {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_DIGEST_CUSTOM, 0),
- "pkey_sm2_digest_custom"},
- {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_INIT, 0), "pkey_sm2_init"},
- {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_SIGN, 0), "pkey_sm2_sign"},
- {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_MSG_HASH, 0),
- "sm2_compute_msg_hash"},
- {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_USERID_DIGEST, 0),
- "sm2_compute_userid_digest"},
- {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_Z_DIGEST, 0),
- "sm2_compute_z_digest"},
- {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_DECRYPT, 0), "sm2_decrypt"},
- {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_ENCRYPT, 0), "sm2_encrypt"},
- {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_PLAINTEXT_SIZE, 0), "sm2_plaintext_size"},
- {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_SIGN, 0), "sm2_sign"},
- {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_SIG_GEN, 0), "sm2_sig_gen"},
- {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_SIG_VERIFY, 0), "sm2_sig_verify"},
- {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_VERIFY, 0), "sm2_verify"},
- {0, NULL}
-};
+# ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA SM2_str_reasons[] = {
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_ASN1_ERROR), "asn1 error"},
@@ -50,20 +28,23 @@ static const ERR_STRING_DATA SM2_str_reasons[] = {
"invalid digest type"},
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_ENCODING), "invalid encoding"},
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_FIELD), "invalid field"},
+ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_PRIVATE_KEY),
+ "invalid private key"},
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_NO_PARAMETERS_SET), "no parameters set"},
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_USER_ID_TOO_LARGE), "user id too large"},
{0, NULL}
};
-#endif
+# endif
-int ERR_load_SM2_strings(void)
+int ossl_err_load_SM2_strings(void)
{
-#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(SM2_str_functs[0].error) == NULL) {
- ERR_load_strings_const(SM2_str_functs);
+# ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(SM2_str_reasons[0].error) == NULL)
ERR_load_strings_const(SM2_str_reasons);
- }
-#endif
+# endif
return 1;
}
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/crypto/sm2/sm2_key.c b/crypto/sm2/sm2_key.c
new file mode 100644
index 000000000000..9d0b9208facf
--- /dev/null
+++ b/crypto/sm2/sm2_key.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/deprecated.h" /* to be able to use EC_KEY and EC_GROUP */
+
+#include <openssl/err.h>
+#include "crypto/sm2err.h"
+#include "crypto/sm2.h"
+#include <openssl/ec.h> /* EC_KEY and EC_GROUP functions */
+
+/*
+ * SM2 key generation is implemented within ec_generate_key() in
+ * crypto/ec/ec_key.c
+ */
+
+int ossl_sm2_key_private_check(const EC_KEY *eckey)
+{
+ int ret = 0;
+ BIGNUM *max = NULL;
+ const EC_GROUP *group = NULL;
+ const BIGNUM *priv_key = NULL, *order = NULL;
+
+ if (eckey == NULL
+ || (group = EC_KEY_get0_group(eckey)) == NULL
+ || (priv_key = EC_KEY_get0_private_key(eckey)) == NULL
+ || (order = EC_GROUP_get0_order(group)) == NULL ) {
+ ERR_raise(ERR_LIB_SM2, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ /* range of SM2 private key is [1, n-1) */
+ max = BN_dup(order);
+ if (max == NULL || !BN_sub_word(max, 1))
+ goto end;
+ if (BN_cmp(priv_key, BN_value_one()) < 0
+ || BN_cmp(priv_key, max) >= 0) {
+ ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_PRIVATE_KEY);
+ goto end;
+ }
+ ret = 1;
+
+ end:
+ BN_free(max);
+ return ret;
+}
diff --git a/crypto/sm2/sm2_pmeth.c b/crypto/sm2/sm2_pmeth.c
deleted file mode 100644
index 0e722b910b57..000000000000
--- a/crypto/sm2/sm2_pmeth.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "internal/cryptlib.h"
-#include <openssl/asn1t.h>
-#include <openssl/ec.h>
-#include <openssl/evp.h>
-#include "crypto/evp.h"
-#include "crypto/sm2.h"
-#include "crypto/sm2err.h"
-
-/* EC pkey context structure */
-
-typedef struct {
- /* Key and paramgen group */
- EC_GROUP *gen_group;
- /* message digest */
- const EVP_MD *md;
- /* Distinguishing Identifier, ISO/IEC 15946-3 */
- uint8_t *id;
- size_t id_len;
- /* id_set indicates if the 'id' field is set (1) or not (0) */
- int id_set;
-} SM2_PKEY_CTX;
-
-static int pkey_sm2_init(EVP_PKEY_CTX *ctx)
-{
- SM2_PKEY_CTX *smctx;
-
- if ((smctx = OPENSSL_zalloc(sizeof(*smctx))) == NULL) {
- SM2err(SM2_F_PKEY_SM2_INIT, ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- ctx->data = smctx;
- return 1;
-}
-
-static void pkey_sm2_cleanup(EVP_PKEY_CTX *ctx)
-{
- SM2_PKEY_CTX *smctx = ctx->data;
-
- if (smctx != NULL) {
- EC_GROUP_free(smctx->gen_group);
- OPENSSL_free(smctx->id);
- OPENSSL_free(smctx);
- ctx->data = NULL;
- }
-}
-
-static int pkey_sm2_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
-{
- SM2_PKEY_CTX *dctx, *sctx;
-
- if (!pkey_sm2_init(dst))
- return 0;
- sctx = src->data;
- dctx = dst->data;
- if (sctx->gen_group != NULL) {
- dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
- if (dctx->gen_group == NULL) {
- pkey_sm2_cleanup(dst);
- return 0;
- }
- }
- if (sctx->id != NULL) {
- dctx->id = OPENSSL_malloc(sctx->id_len);
- if (dctx->id == NULL) {
- SM2err(SM2_F_PKEY_SM2_COPY, ERR_R_MALLOC_FAILURE);
- pkey_sm2_cleanup(dst);
- return 0;
- }
- memcpy(dctx->id, sctx->id, sctx->id_len);
- }
- dctx->id_len = sctx->id_len;
- dctx->id_set = sctx->id_set;
- dctx->md = sctx->md;
-
- return 1;
-}
-
-static int pkey_sm2_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
- const unsigned char *tbs, size_t tbslen)
-{
- int ret;
- unsigned int sltmp;
- EC_KEY *ec = ctx->pkey->pkey.ec;
- const int sig_sz = ECDSA_size(ctx->pkey->pkey.ec);
-
- if (sig_sz <= 0) {
- return 0;
- }
-
- if (sig == NULL) {
- *siglen = (size_t)sig_sz;
- return 1;
- }
-
- if (*siglen < (size_t)sig_sz) {
- SM2err(SM2_F_PKEY_SM2_SIGN, SM2_R_BUFFER_TOO_SMALL);
- return 0;
- }
-
- ret = sm2_sign(tbs, tbslen, sig, &sltmp, ec);
-
- if (ret <= 0)
- return ret;
- *siglen = (size_t)sltmp;
- return 1;
-}
-
-static int pkey_sm2_verify(EVP_PKEY_CTX *ctx,
- const unsigned char *sig, size_t siglen,
- const unsigned char *tbs, size_t tbslen)
-{
- EC_KEY *ec = ctx->pkey->pkey.ec;
-
- return sm2_verify(tbs, tbslen, sig, siglen, ec);
-}
-
-static int pkey_sm2_encrypt(EVP_PKEY_CTX *ctx,
- unsigned char *out, size_t *outlen,
- const unsigned char *in, size_t inlen)
-{
- EC_KEY *ec = ctx->pkey->pkey.ec;
- SM2_PKEY_CTX *dctx = ctx->data;
- const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md;
-
- if (out == NULL) {
- if (!sm2_ciphertext_size(ec, md, inlen, outlen))
- return -1;
- else
- return 1;
- }
-
- return sm2_encrypt(ec, md, in, inlen, out, outlen);
-}
-
-static int pkey_sm2_decrypt(EVP_PKEY_CTX *ctx,
- unsigned char *out, size_t *outlen,
- const unsigned char *in, size_t inlen)
-{
- EC_KEY *ec = ctx->pkey->pkey.ec;
- SM2_PKEY_CTX *dctx = ctx->data;
- const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md;
-
- if (out == NULL) {
- if (!sm2_plaintext_size(in, inlen, outlen))
- return -1;
- else
- return 1;
- }
-
- return sm2_decrypt(ec, md, in, inlen, out, outlen);
-}
-
-static int pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
-{
- SM2_PKEY_CTX *smctx = ctx->data;
- EC_GROUP *group;
- uint8_t *tmp_id;
-
- switch (type) {
- case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
- group = EC_GROUP_new_by_curve_name(p1);
- if (group == NULL) {
- SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_INVALID_CURVE);
- return 0;
- }
- EC_GROUP_free(smctx->gen_group);
- smctx->gen_group = group;
- return 1;
-
- case EVP_PKEY_CTRL_EC_PARAM_ENC:
- if (smctx->gen_group == NULL) {
- SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_NO_PARAMETERS_SET);
- return 0;
- }
- EC_GROUP_set_asn1_flag(smctx->gen_group, p1);
- return 1;
-
- case EVP_PKEY_CTRL_MD:
- smctx->md = p2;
- return 1;
-
- case EVP_PKEY_CTRL_GET_MD:
- *(const EVP_MD **)p2 = smctx->md;
- return 1;
-
- case EVP_PKEY_CTRL_SET1_ID:
- if (p1 > 0) {
- tmp_id = OPENSSL_malloc(p1);
- if (tmp_id == NULL) {
- SM2err(SM2_F_PKEY_SM2_CTRL, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- memcpy(tmp_id, p2, p1);
- OPENSSL_free(smctx->id);
- smctx->id = tmp_id;
- } else {
- /* set null-ID */
- OPENSSL_free(smctx->id);
- smctx->id = NULL;
- }
- smctx->id_len = (size_t)p1;
- smctx->id_set = 1;
- return 1;
-
- case EVP_PKEY_CTRL_GET1_ID:
- memcpy(p2, smctx->id, smctx->id_len);
- return 1;
-
- case EVP_PKEY_CTRL_GET1_ID_LEN:
- *(size_t *)p2 = smctx->id_len;
- return 1;
-
- case EVP_PKEY_CTRL_DIGESTINIT:
- /* nothing to be inited, this is to suppress the error... */
- return 1;
-
- default:
- return -2;
- }
-}
-
-static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx,
- const char *type, const char *value)
-{
- if (strcmp(type, "ec_paramgen_curve") == 0) {
- int nid = NID_undef;
-
- if (((nid = EC_curve_nist2nid(value)) == NID_undef)
- && ((nid = OBJ_sn2nid(value)) == NID_undef)
- && ((nid = OBJ_ln2nid(value)) == NID_undef)) {
- SM2err(SM2_F_PKEY_SM2_CTRL_STR, SM2_R_INVALID_CURVE);
- return 0;
- }
- return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
- } else if (strcmp(type, "ec_param_enc") == 0) {
- int param_enc;
-
- if (strcmp(value, "explicit") == 0)
- param_enc = 0;
- else if (strcmp(value, "named_curve") == 0)
- param_enc = OPENSSL_EC_NAMED_CURVE;
- else
- return -2;
- return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc);
- }
-
- return -2;
-}
-
-static int pkey_sm2_digest_custom(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
-{
- uint8_t z[EVP_MAX_MD_SIZE];
- SM2_PKEY_CTX *smctx = ctx->data;
- EC_KEY *ec = ctx->pkey->pkey.ec;
- const EVP_MD *md = EVP_MD_CTX_md(mctx);
- int mdlen = EVP_MD_size(md);
-
- if (!smctx->id_set) {
- /*
- * An ID value must be set. The specifications are not clear whether a
- * NULL is allowed. We only allow it if set explicitly for maximum
- * flexibility.
- */
- SM2err(SM2_F_PKEY_SM2_DIGEST_CUSTOM, SM2_R_ID_NOT_SET);
- return 0;
- }
-
- if (mdlen < 0) {
- SM2err(SM2_F_PKEY_SM2_DIGEST_CUSTOM, SM2_R_INVALID_DIGEST);
- return 0;
- }
-
- /* get hashed prefix 'z' of tbs message */
- if (!sm2_compute_z_digest(z, md, smctx->id, smctx->id_len, ec))
- return 0;
-
- return EVP_DigestUpdate(mctx, z, (size_t)mdlen);
-}
-
-const EVP_PKEY_METHOD sm2_pkey_meth = {
- EVP_PKEY_SM2,
- 0,
- pkey_sm2_init,
- pkey_sm2_copy,
- pkey_sm2_cleanup,
-
- 0,
- 0,
-
- 0,
- 0,
-
- 0,
- pkey_sm2_sign,
-
- 0,
- pkey_sm2_verify,
-
- 0, 0,
-
- 0, 0, 0, 0,
-
- 0,
- pkey_sm2_encrypt,
-
- 0,
- pkey_sm2_decrypt,
-
- 0,
- 0,
- pkey_sm2_ctrl,
- pkey_sm2_ctrl_str,
-
- 0, 0,
-
- 0, 0, 0,
-
- pkey_sm2_digest_custom
-};
diff --git a/crypto/sm2/sm2_sign.c b/crypto/sm2/sm2_sign.c
index 683f03f93580..5861f420fb66 100644
--- a/crypto/sm2/sm2_sign.c
+++ b/crypto/sm2/sm2_sign.c
@@ -1,17 +1,19 @@
/*
- * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2017 Ribose Inc. All Rights Reserved.
* Ported from Ribose contributions from Botan.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#include "internal/deprecated.h"
+
#include "crypto/sm2.h"
#include "crypto/sm2err.h"
-#include "crypto/ec.h" /* ec_group_do_inverse_ord() */
+#include "crypto/ec.h" /* ossl_ec_group_do_inverse_ord() */
#include "internal/numbers.h"
#include <openssl/err.h>
#include <openssl/evp.h>
@@ -19,11 +21,11 @@
#include <openssl/bn.h>
#include <string.h>
-int sm2_compute_z_digest(uint8_t *out,
- const EVP_MD *digest,
- const uint8_t *id,
- const size_t id_len,
- const EC_KEY *key)
+int ossl_sm2_compute_z_digest(uint8_t *out,
+ const EVP_MD *digest,
+ const uint8_t *id,
+ const size_t id_len,
+ const EC_KEY *key)
{
int rc = 0;
const EC_GROUP *group = EC_KEY_get0_group(key);
@@ -42,9 +44,9 @@ int sm2_compute_z_digest(uint8_t *out,
uint8_t e_byte = 0;
hash = EVP_MD_CTX_new();
- ctx = BN_CTX_new();
+ ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(key));
if (hash == NULL || ctx == NULL) {
- SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
@@ -57,12 +59,12 @@ int sm2_compute_z_digest(uint8_t *out,
yA = BN_CTX_get(ctx);
if (yA == NULL) {
- SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
if (!EVP_DigestInit(hash, digest)) {
- SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
goto done;
}
@@ -70,7 +72,7 @@ int sm2_compute_z_digest(uint8_t *out,
if (id_len >= (UINT16_MAX / 8)) {
/* too large */
- SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, SM2_R_ID_TOO_LARGE);
+ ERR_raise(ERR_LIB_SM2, SM2_R_ID_TOO_LARGE);
goto done;
}
@@ -78,29 +80,29 @@ int sm2_compute_z_digest(uint8_t *out,
e_byte = entl >> 8;
if (!EVP_DigestUpdate(hash, &e_byte, 1)) {
- SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
goto done;
}
e_byte = entl & 0xFF;
if (!EVP_DigestUpdate(hash, &e_byte, 1)) {
- SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
goto done;
}
if (id_len > 0 && !EVP_DigestUpdate(hash, id, id_len)) {
- SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
goto done;
}
if (!EC_GROUP_get_curve(group, p, a, b, ctx)) {
- SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB);
goto done;
}
p_bytes = BN_num_bytes(p);
buf = OPENSSL_zalloc(p_bytes);
if (buf == NULL) {
- SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
@@ -123,7 +125,7 @@ int sm2_compute_z_digest(uint8_t *out,
|| BN_bn2binpad(yA, buf, p_bytes) < 0
|| !EVP_DigestUpdate(hash, buf, p_bytes)
|| !EVP_DigestFinal(hash, out, NULL)) {
- SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
@@ -143,40 +145,50 @@ static BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest,
const uint8_t *msg, size_t msg_len)
{
EVP_MD_CTX *hash = EVP_MD_CTX_new();
- const int md_size = EVP_MD_size(digest);
+ const int md_size = EVP_MD_get_size(digest);
uint8_t *z = NULL;
BIGNUM *e = NULL;
+ EVP_MD *fetched_digest = NULL;
+ OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key);
+ const char *propq = ossl_ec_key_get0_propq(key);
if (md_size < 0) {
- SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, SM2_R_INVALID_DIGEST);
+ ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_DIGEST);
goto done;
}
z = OPENSSL_zalloc(md_size);
if (hash == NULL || z == NULL) {
- SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
- if (!sm2_compute_z_digest(z, digest, id, id_len, key)) {
+ fetched_digest = EVP_MD_fetch(libctx, EVP_MD_get0_name(digest), propq);
+ if (fetched_digest == NULL) {
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
+ goto done;
+ }
+
+ if (!ossl_sm2_compute_z_digest(z, fetched_digest, id, id_len, key)) {
/* SM2err already called */
goto done;
}
- if (!EVP_DigestInit(hash, digest)
+ if (!EVP_DigestInit(hash, fetched_digest)
|| !EVP_DigestUpdate(hash, z, md_size)
|| !EVP_DigestUpdate(hash, msg, msg_len)
/* reuse z buffer to hold H(Z || M) */
|| !EVP_DigestFinal(hash, z, NULL)) {
- SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
goto done;
}
e = BN_bin2bn(z, md_size, NULL);
if (e == NULL)
- SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
done:
+ EVP_MD_free(fetched_digest);
OPENSSL_free(z);
EVP_MD_CTX_free(hash);
return e;
@@ -196,11 +208,12 @@ static ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e)
BIGNUM *s = NULL;
BIGNUM *x1 = NULL;
BIGNUM *tmp = NULL;
+ OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key);
kG = EC_POINT_new(group);
- ctx = BN_CTX_new();
+ ctx = BN_CTX_new_ex(libctx);
if (kG == NULL || ctx == NULL) {
- SM2err(SM2_F_SM2_SIG_GEN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
@@ -210,7 +223,7 @@ static ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e)
x1 = BN_CTX_get(ctx);
tmp = BN_CTX_get(ctx);
if (tmp == NULL) {
- SM2err(SM2_F_SM2_SIG_GEN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
@@ -222,13 +235,22 @@ static ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e)
s = BN_new();
if (r == NULL || s == NULL) {
- SM2err(SM2_F_SM2_SIG_GEN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
+ /*
+ * A3: Generate a random number k in [1,n-1] using random number generators;
+ * A4: Compute (x1,y1)=[k]G, and convert the type of data x1 to be integer
+ * as specified in clause 4.2.8 of GM/T 0003.1-2012;
+ * A5: Compute r=(e+x1) mod n. If r=0 or r+k=n, then go to A3;
+ * A6: Compute s=(1/(1+dA)*(k-r*dA)) mod n. If s=0, then go to A3;
+ * A7: Convert the type of data (r,s) to be bit strings according to the details
+ * in clause 4.2.2 of GM/T 0003.1-2012. Then the signature of message M is (r,s).
+ */
for (;;) {
- if (!BN_priv_rand_range(k, order)) {
- SM2err(SM2_F_SM2_SIG_GEN, ERR_R_INTERNAL_ERROR);
+ if (!BN_priv_rand_range_ex(k, order, 0, ctx)) {
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
@@ -236,7 +258,7 @@ static ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e)
|| !EC_POINT_get_affine_coordinates(group, kG, x1, NULL,
ctx)
|| !BN_mod_add(r, e, x1, order, ctx)) {
- SM2err(SM2_F_SM2_SIG_GEN, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
@@ -245,7 +267,7 @@ static ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e)
continue;
if (!BN_add(rk, r, k)) {
- SM2err(SM2_F_SM2_SIG_GEN, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
@@ -253,17 +275,21 @@ static ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e)
continue;
if (!BN_add(s, dA, BN_value_one())
- || !ec_group_do_inverse_ord(group, s, s, ctx)
+ || !ossl_ec_group_do_inverse_ord(group, s, s, ctx)
|| !BN_mod_mul(tmp, dA, r, order, ctx)
|| !BN_sub(tmp, k, tmp)
|| !BN_mod_mul(s, s, tmp, order, ctx)) {
- SM2err(SM2_F_SM2_SIG_GEN, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
goto done;
}
+ /* try again if s == 0 */
+ if (BN_is_zero(s))
+ continue;
+
sig = ECDSA_SIG_new();
if (sig == NULL) {
- SM2err(SM2_F_SM2_SIG_GEN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
@@ -295,11 +321,12 @@ static int sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig,
BIGNUM *x1 = NULL;
const BIGNUM *r = NULL;
const BIGNUM *s = NULL;
+ OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key);
- ctx = BN_CTX_new();
+ ctx = BN_CTX_new_ex(libctx);
pt = EC_POINT_new(group);
if (ctx == NULL || pt == NULL) {
- SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
@@ -307,7 +334,7 @@ static int sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig,
t = BN_CTX_get(ctx);
x1 = BN_CTX_get(ctx);
if (x1 == NULL) {
- SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
@@ -327,28 +354,28 @@ static int sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig,
|| BN_cmp(s, BN_value_one()) < 0
|| BN_cmp(order, r) <= 0
|| BN_cmp(order, s) <= 0) {
- SM2err(SM2_F_SM2_SIG_VERIFY, SM2_R_BAD_SIGNATURE);
+ ERR_raise(ERR_LIB_SM2, SM2_R_BAD_SIGNATURE);
goto done;
}
if (!BN_mod_add(t, r, s, order, ctx)) {
- SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
goto done;
}
if (BN_is_zero(t)) {
- SM2err(SM2_F_SM2_SIG_VERIFY, SM2_R_BAD_SIGNATURE);
+ ERR_raise(ERR_LIB_SM2, SM2_R_BAD_SIGNATURE);
goto done;
}
if (!EC_POINT_mul(group, pt, s, EC_KEY_get0_public_key(key), t, ctx)
|| !EC_POINT_get_affine_coordinates(group, pt, x1, NULL, ctx)) {
- SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_EC_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB);
goto done;
}
if (!BN_mod_add(t, e, x1, order, ctx)) {
- SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
goto done;
}
@@ -361,11 +388,11 @@ static int sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig,
return ret;
}
-ECDSA_SIG *sm2_do_sign(const EC_KEY *key,
- const EVP_MD *digest,
- const uint8_t *id,
- const size_t id_len,
- const uint8_t *msg, size_t msg_len)
+ECDSA_SIG *ossl_sm2_do_sign(const EC_KEY *key,
+ const EVP_MD *digest,
+ const uint8_t *id,
+ const size_t id_len,
+ const uint8_t *msg, size_t msg_len)
{
BIGNUM *e = NULL;
ECDSA_SIG *sig = NULL;
@@ -383,12 +410,12 @@ ECDSA_SIG *sm2_do_sign(const EC_KEY *key,
return sig;
}
-int sm2_do_verify(const EC_KEY *key,
- const EVP_MD *digest,
- const ECDSA_SIG *sig,
- const uint8_t *id,
- const size_t id_len,
- const uint8_t *msg, size_t msg_len)
+int ossl_sm2_do_verify(const EC_KEY *key,
+ const EVP_MD *digest,
+ const ECDSA_SIG *sig,
+ const uint8_t *id,
+ const size_t id_len,
+ const uint8_t *msg, size_t msg_len)
{
BIGNUM *e = NULL;
int ret = 0;
@@ -406,8 +433,9 @@ int sm2_do_verify(const EC_KEY *key,
return ret;
}
-int sm2_sign(const unsigned char *dgst, int dgstlen,
- unsigned char *sig, unsigned int *siglen, EC_KEY *eckey)
+int ossl_sm2_internal_sign(const unsigned char *dgst, int dgstlen,
+ unsigned char *sig, unsigned int *siglen,
+ EC_KEY *eckey)
{
BIGNUM *e = NULL;
ECDSA_SIG *s = NULL;
@@ -416,15 +444,19 @@ int sm2_sign(const unsigned char *dgst, int dgstlen,
e = BN_bin2bn(dgst, dgstlen, NULL);
if (e == NULL) {
- SM2err(SM2_F_SM2_SIGN, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
goto done;
}
s = sm2_sig_gen(eckey, e);
+ if (s == NULL) {
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
+ goto done;
+ }
sigleni = i2d_ECDSA_SIG(s, &sig);
if (sigleni < 0) {
- SM2err(SM2_F_SM2_SIGN, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
*siglen = (unsigned int)sigleni;
@@ -437,8 +469,9 @@ int sm2_sign(const unsigned char *dgst, int dgstlen,
return ret;
}
-int sm2_verify(const unsigned char *dgst, int dgstlen,
- const unsigned char *sig, int sig_len, EC_KEY *eckey)
+int ossl_sm2_internal_verify(const unsigned char *dgst, int dgstlen,
+ const unsigned char *sig, int sig_len,
+ EC_KEY *eckey)
{
ECDSA_SIG *s = NULL;
BIGNUM *e = NULL;
@@ -449,23 +482,23 @@ int sm2_verify(const unsigned char *dgst, int dgstlen,
s = ECDSA_SIG_new();
if (s == NULL) {
- SM2err(SM2_F_SM2_VERIFY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) {
- SM2err(SM2_F_SM2_VERIFY, SM2_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING);
goto done;
}
/* Ensure signature uses DER and doesn't have trailing garbage */
derlen = i2d_ECDSA_SIG(s, &der);
if (derlen != sig_len || memcmp(sig, der, derlen) != 0) {
- SM2err(SM2_F_SM2_VERIFY, SM2_R_INVALID_ENCODING);
+ ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING);
goto done;
}
e = BN_bin2bn(dgst, dgstlen, NULL);
if (e == NULL) {
- SM2err(SM2_F_SM2_VERIFY, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
goto done;
}
diff --git a/crypto/sm3/build.info b/crypto/sm3/build.info
index 6009b1949eb6..eca68216f27e 100644
--- a/crypto/sm3/build.info
+++ b/crypto/sm3/build.info
@@ -1,2 +1,5 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=sm3.c m_sm3.c
+
+IF[{- !$disabled{sm3} -}]
+ SOURCE[../../libcrypto]=sm3.c legacy_sm3.c
+ENDIF \ No newline at end of file
diff --git a/crypto/sm3/legacy_sm3.c b/crypto/sm3/legacy_sm3.c
new file mode 100644
index 000000000000..c81f3b4ab45d
--- /dev/null
+++ b/crypto/sm3/legacy_sm3.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017 Ribose Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+
+#include "crypto/evp.h"
+#include "../evp/legacy_meth.h"
+#include "internal/sm3.h"
+
+IMPLEMENT_LEGACY_EVP_MD_METH_LC(sm3_int, ossl_sm3)
+
+static const EVP_MD sm3_md = {
+ NID_sm3,
+ NID_sm3WithRSAEncryption,
+ SM3_DIGEST_LENGTH,
+ 0,
+ EVP_ORIG_GLOBAL,
+ LEGACY_EVP_MD_METH_TABLE(sm3_int_init, sm3_int_update, sm3_int_final, NULL,
+ SM3_CBLOCK),
+};
+
+const EVP_MD *EVP_sm3(void)
+{
+ return &sm3_md;
+}
diff --git a/crypto/sm3/m_sm3.c b/crypto/sm3/m_sm3.c
deleted file mode 100644
index 7e54f4298431..000000000000
--- a/crypto/sm3/m_sm3.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright 2017 Ribose Inc. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "internal/cryptlib.h"
-
-#ifndef OPENSSL_NO_SM3
-# include <openssl/evp.h>
-# include "crypto/evp.h"
-# include "crypto/sm3.h"
-
-static int init(EVP_MD_CTX *ctx)
-{
- return sm3_init(EVP_MD_CTX_md_data(ctx));
-}
-
-static int update(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
- return sm3_update(EVP_MD_CTX_md_data(ctx), data, count);
-}
-
-static int final(EVP_MD_CTX *ctx, unsigned char *md)
-{
- return sm3_final(md, EVP_MD_CTX_md_data(ctx));
-}
-
-static const EVP_MD sm3_md = {
- NID_sm3,
- NID_sm3WithRSAEncryption,
- SM3_DIGEST_LENGTH,
- 0,
- init,
- update,
- final,
- NULL,
- NULL,
- SM3_CBLOCK,
- sizeof(EVP_MD *) + sizeof(SM3_CTX),
-};
-
-const EVP_MD *EVP_sm3(void)
-{
- return &sm3_md;
-}
-
-#endif
diff --git a/crypto/sm3/sm3.c b/crypto/sm3/sm3.c
index d78292b4c5b7..ff78fb763e00 100644
--- a/crypto/sm3/sm3.c
+++ b/crypto/sm3/sm3.c
@@ -1,9 +1,9 @@
/*
- * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2017 Ribose Inc. All Rights Reserved.
* Ported from Ribose contributions from Botan.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,7 +12,7 @@
#include <openssl/e_os2.h>
#include "sm3_local.h"
-int sm3_init(SM3_CTX *c)
+int ossl_sm3_init(SM3_CTX *c)
{
memset(c, 0, sizeof(*c));
c->A = SM3_A;
@@ -26,7 +26,7 @@ int sm3_init(SM3_CTX *c)
return 1;
}
-void sm3_block_data_order(SM3_CTX *ctx, const void *p, size_t num)
+void ossl_sm3_block_data_order(SM3_CTX *ctx, const void *p, size_t num)
{
const unsigned char *data = p;
register unsigned MD32_REG_T A, B, C, D, E, F, G, H;
@@ -193,4 +193,3 @@ void sm3_block_data_order(SM3_CTX *ctx, const void *p, size_t num)
ctx->H ^= H;
}
}
-
diff --git a/crypto/sm3/sm3_local.h b/crypto/sm3/sm3_local.h
index 7171de510de3..6daeb878a887 100644
--- a/crypto/sm3/sm3_local.h
+++ b/crypto/sm3/sm3_local.h
@@ -1,25 +1,25 @@
/*
- * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2017 Ribose Inc. All Rights Reserved.
* Ported from Ribose contributions from Botan.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
-#include "crypto/sm3.h"
+#include "internal/sm3.h"
#define DATA_ORDER_IS_BIG_ENDIAN
#define HASH_LONG SM3_WORD
#define HASH_CTX SM3_CTX
#define HASH_CBLOCK SM3_CBLOCK
-#define HASH_UPDATE sm3_update
-#define HASH_TRANSFORM sm3_transform
-#define HASH_FINAL sm3_final
+#define HASH_UPDATE ossl_sm3_update
+#define HASH_TRANSFORM ossl_sm3_transform
+#define HASH_FINAL ossl_sm3_final
#define HASH_MAKE_STRING(c, s) \
do { \
unsigned long ll; \
@@ -32,9 +32,10 @@
ll=(c)->G; (void)HOST_l2c(ll, (s)); \
ll=(c)->H; (void)HOST_l2c(ll, (s)); \
} while (0)
-#define HASH_BLOCK_DATA_ORDER sm3_block_data_order
+#define HASH_BLOCK_DATA_ORDER ossl_sm3_block_data_order
-void sm3_transform(SM3_CTX *c, const unsigned char *data);
+void ossl_sm3_block_data_order(SM3_CTX *c, const void *p, size_t num);
+void ossl_sm3_transform(SM3_CTX *c, const unsigned char *data);
#include "crypto/md32_common.h"
diff --git a/crypto/sm4/sm4.c b/crypto/sm4/sm4.c
index 5750e763319a..1e11ee650632 100644
--- a/crypto/sm4/sm4.c
+++ b/crypto/sm4/sm4.c
@@ -1,9 +1,9 @@
/*
- * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2017 Ribose Inc. All Rights Reserved.
* Ported from Ribose contributions from Botan.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -129,7 +129,7 @@ static ossl_inline uint32_t SM4_T(uint32_t X)
rotl(SM4_SBOX_T[(uint8_t)X], 8);
}
-int SM4_set_key(const uint8_t *key, SM4_KEY *ks)
+int ossl_sm4_set_key(const uint8_t *key, SM4_KEY *ks)
{
/*
* Family Key
@@ -184,7 +184,7 @@ int SM4_set_key(const uint8_t *key, SM4_KEY *ks)
B3 ^= F(B0 ^ B1 ^ B2 ^ ks->rk[k3]); \
} while(0)
-void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks)
+void ossl_sm4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks)
{
uint32_t B0 = load_u32_be(in, 0);
uint32_t B1 = load_u32_be(in, 1);
@@ -210,7 +210,7 @@ void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks)
store_u32_be(B0, out + 12);
}
-void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks)
+void ossl_sm4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks)
{
uint32_t B0 = load_u32_be(in, 0);
uint32_t B1 = load_u32_be(in, 1);
diff --git a/crypto/sparc_arch.h b/crypto/sparc_arch.h
deleted file mode 100644
index c74063be2fa6..000000000000
--- a/crypto/sparc_arch.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef OSSL_CRYPTO_SPARC_ARCH_H
-# define OSSL_CRYPTO_SPARC_ARCH_H
-
-# define SPARCV9_TICK_PRIVILEGED (1<<0)
-# define SPARCV9_PREFER_FPU (1<<1)
-# define SPARCV9_VIS1 (1<<2)
-# define SPARCV9_VIS2 (1<<3)/* reserved */
-# define SPARCV9_FMADD (1<<4)
-# define SPARCV9_BLK (1<<5)/* VIS1 block copy */
-# define SPARCV9_VIS3 (1<<6)
-# define SPARCV9_RANDOM (1<<7)
-# define SPARCV9_64BIT_STACK (1<<8)
-# define SPARCV9_FJAESX (1<<9)/* Fujitsu SPARC64 X AES */
-# define SPARCV9_FJDESX (1<<10)/* Fujitsu SPARC64 X DES, reserved */
-# define SPARCV9_FJHPCACE (1<<11)/* Fujitsu HPC-ACE, reserved */
-# define SPARCV9_IMA (1<<13)/* reserved */
-# define SPARCV9_VIS4 (1<<14)/* reserved */
-
-/*
- * OPENSSL_sparcv9cap_P[1] is copy of Compatibility Feature Register,
- * %asr26, SPARC-T4 and later. There is no SPARCV9_CFR bit in
- * OPENSSL_sparcv9cap_P[0], as %cfr copy is sufficient...
- */
-# define CFR_AES 0x00000001/* Supports AES opcodes */
-# define CFR_DES 0x00000002/* Supports DES opcodes */
-# define CFR_KASUMI 0x00000004/* Supports KASUMI opcodes */
-# define CFR_CAMELLIA 0x00000008/* Supports CAMELLIA opcodes */
-# define CFR_MD5 0x00000010/* Supports MD5 opcodes */
-# define CFR_SHA1 0x00000020/* Supports SHA1 opcodes */
-# define CFR_SHA256 0x00000040/* Supports SHA256 opcodes */
-# define CFR_SHA512 0x00000080/* Supports SHA512 opcodes */
-# define CFR_MPMUL 0x00000100/* Supports MPMUL opcodes */
-# define CFR_MONTMUL 0x00000200/* Supports MONTMUL opcodes */
-# define CFR_MONTSQR 0x00000400/* Supports MONTSQR opcodes */
-# define CFR_CRC32C 0x00000800/* Supports CRC32C opcodes */
-# define CFR_XMPMUL 0x00001000/* Supports XMPMUL opcodes */
-# define CFR_XMONTMUL 0x00002000/* Supports XMONTMUL opcodes */
-# define CFR_XMONTSQR 0x00004000/* Supports XMONTSQR opcodes */
-
-# if defined(OPENSSL_PIC) && !defined(__PIC__)
-# define __PIC__
-# endif
-
-# if defined(__SUNPRO_C) && defined(__sparcv9) && !defined(__arch64__)
-# define __arch64__
-# endif
-
-# define SPARC_PIC_THUNK(reg) \
- .align 32; \
-.Lpic_thunk: \
- jmp %o7 + 8; \
- add %o7, reg, reg;
-
-# define SPARC_PIC_THUNK_CALL(reg) \
- sethi %hi(_GLOBAL_OFFSET_TABLE_-4), reg; \
- call .Lpic_thunk; \
- or reg, %lo(_GLOBAL_OFFSET_TABLE_+4), reg;
-
-# if 1
-# define SPARC_SETUP_GOT_REG(reg) SPARC_PIC_THUNK_CALL(reg)
-# else
-# define SPARC_SETUP_GOT_REG(reg) \
- sethi %hi(_GLOBAL_OFFSET_TABLE_-4), reg; \
- call .+8; \
- or reg,%lo(_GLOBAL_OFFSET_TABLE_+4), reg; \
- add %o7, reg, reg
-# endif
-
-# if defined(__arch64__)
-
-# define SPARC_LOAD_ADDRESS(SYM, reg) \
- setx SYM, %o7, reg;
-# define LDPTR ldx
-# define SIZE_T_CC %xcc
-# define STACK_FRAME 192
-# define STACK_BIAS 2047
-# define STACK_7thARG (STACK_BIAS+176)
-
-# else
-
-# define SPARC_LOAD_ADDRESS(SYM, reg) \
- set SYM, reg;
-# define LDPTR ld
-# define SIZE_T_CC %icc
-# define STACK_FRAME 112
-# define STACK_BIAS 0
-# define STACK_7thARG 92
-# define SPARC_LOAD_ADDRESS_LEAF(SYM,reg,tmp) SPARC_LOAD_ADDRESS(SYM,reg)
-
-# endif
-
-# ifdef __PIC__
-# undef SPARC_LOAD_ADDRESS
-# undef SPARC_LOAD_ADDRESS_LEAF
-# define SPARC_LOAD_ADDRESS(SYM, reg) \
- SPARC_SETUP_GOT_REG(reg); \
- sethi %hi(SYM), %o7; \
- or %o7, %lo(SYM), %o7; \
- LDPTR [reg + %o7], reg;
-# endif
-
-# ifndef SPARC_LOAD_ADDRESS_LEAF
-# define SPARC_LOAD_ADDRESS_LEAF(SYM, reg, tmp) \
- mov %o7, tmp; \
- SPARC_LOAD_ADDRESS(SYM, reg) \
- mov tmp, %o7;
-# endif
-
-#endif /* OSSL_CRYPTO_SPARC_ARCH_H */
diff --git a/crypto/sparccpuid.S b/crypto/sparccpuid.S
index 95acd2f9d4d2..4771dd508793 100644
--- a/crypto/sparccpuid.S
+++ b/crypto/sparccpuid.S
@@ -1,6 +1,6 @@
! Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
!
-! Licensed under the OpenSSL license (the "License"). You may not use
+! Licensed under the Apache License 2.0 (the "License"). You may not use
! this file except in compliance with the License. You can obtain a copy
! in the file LICENSE in the source distribution or at
! https://www.openssl.org/source/license.html
diff --git a/crypto/sparcv9cap.c b/crypto/sparcv9cap.c
index b3cb3d4be958..53c0c3e0456b 100644
--- a/crypto/sparcv9cap.c
+++ b/crypto/sparcv9cap.c
@@ -1,7 +1,7 @@
/*
* Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -16,78 +16,13 @@
#include <unistd.h>
#include <openssl/bn.h>
#include "internal/cryptlib.h"
-#include "bn/bn_local.h" /* for definition of bn_mul_mont */
-
-#include "sparc_arch.h"
+#include "crypto/sparc_arch.h"
#if defined(__GNUC__) && defined(__linux)
__attribute__ ((visibility("hidden")))
#endif
unsigned int OPENSSL_sparcv9cap_P[2] = { SPARCV9_TICK_PRIVILEGED, 0 };
-int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
- const BN_ULONG *np, const BN_ULONG *n0, int num)
-{
- int bn_mul_mont_vis3(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
- const BN_ULONG *np, const BN_ULONG *n0, int num);
- int bn_mul_mont_fpu(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
- const BN_ULONG *np, const BN_ULONG *n0, int num);
- int bn_mul_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
- const BN_ULONG *np, const BN_ULONG *n0, int num);
-
- if (!(num & 1) && num >= 6) {
- if ((num & 15) == 0 && num <= 64 &&
- (OPENSSL_sparcv9cap_P[1] & (CFR_MONTMUL | CFR_MONTSQR)) ==
- (CFR_MONTMUL | CFR_MONTSQR)) {
- typedef int (*bn_mul_mont_f) (BN_ULONG *rp, const BN_ULONG *ap,
- const BN_ULONG *bp,
- const BN_ULONG *np,
- const BN_ULONG *n0);
- int bn_mul_mont_t4_8(BN_ULONG *rp, const BN_ULONG *ap,
- const BN_ULONG *bp, const BN_ULONG *np,
- const BN_ULONG *n0);
- int bn_mul_mont_t4_16(BN_ULONG *rp, const BN_ULONG *ap,
- const BN_ULONG *bp, const BN_ULONG *np,
- const BN_ULONG *n0);
- int bn_mul_mont_t4_24(BN_ULONG *rp, const BN_ULONG *ap,
- const BN_ULONG *bp, const BN_ULONG *np,
- const BN_ULONG *n0);
- int bn_mul_mont_t4_32(BN_ULONG *rp, const BN_ULONG *ap,
- const BN_ULONG *bp, const BN_ULONG *np,
- const BN_ULONG *n0);
- static const bn_mul_mont_f funcs[4] = {
- bn_mul_mont_t4_8, bn_mul_mont_t4_16,
- bn_mul_mont_t4_24, bn_mul_mont_t4_32
- };
- bn_mul_mont_f worker = funcs[num / 16 - 1];
-
- if ((*worker) (rp, ap, bp, np, n0))
- return 1;
- /* retry once and fall back */
- if ((*worker) (rp, ap, bp, np, n0))
- return 1;
- return bn_mul_mont_vis3(rp, ap, bp, np, n0, num);
- }
- if ((OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS3))
- return bn_mul_mont_vis3(rp, ap, bp, np, n0, num);
- else if (num >= 8 &&
- /*
- * bn_mul_mont_fpu doesn't use FMADD, we just use the
- * flag to detect when FPU path is preferable in cases
- * when current heuristics is unreliable. [it works
- * out because FMADD-capable processors where FPU
- * code path is undesirable are also VIS3-capable and
- * VIS3 code path takes precedence.]
- */
- ( (OPENSSL_sparcv9cap_P[0] & SPARCV9_FMADD) ||
- (OPENSSL_sparcv9cap_P[0] &
- (SPARCV9_PREFER_FPU | SPARCV9_VIS1)) ==
- (SPARCV9_PREFER_FPU | SPARCV9_VIS1) ))
- return bn_mul_mont_fpu(rp, ap, bp, np, n0, num);
- }
- return bn_mul_mont_int(rp, ap, bp, np, n0, num);
-}
-
unsigned long _sparcv9_rdtick(void);
void _sparcv9_vis1_probe(void);
unsigned long _sparcv9_vis1_instrument(void);
diff --git a/crypto/sparse_array.c b/crypto/sparse_array.c
new file mode 100644
index 000000000000..bbbc9cdb3696
--- /dev/null
+++ b/crypto/sparse_array.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/bn.h>
+#include "crypto/sparse_array.h"
+
+/*
+ * How many bits are used to index each level in the tree structure?
+ * This setting determines the number of pointers stored in each node of the
+ * tree used to represent the sparse array. Having more pointers reduces the
+ * depth of the tree but potentially wastes more memory. That is, this is a
+ * direct space versus time tradeoff.
+ *
+ * The default is to use four bits which means that the are 16
+ * pointers in each tree node.
+ *
+ * The library builder is also permitted to define other sizes in the closed
+ * interval [2, sizeof(ossl_uintmax_t) * 8]. Space use generally scales
+ * exponentially with the block size, although the implementation only
+ * creates enough blocks to support the largest used index. The depth is:
+ * ceil(log_2(largest index) / 2^{block size})
+ * E.g. with a block size of 4, and a largest index of 1000, the depth
+ * will be three.
+ */
+#ifndef OPENSSL_SA_BLOCK_BITS
+# define OPENSSL_SA_BLOCK_BITS 4
+#elif OPENSSL_SA_BLOCK_BITS < 2 || OPENSSL_SA_BLOCK_BITS > (BN_BITS2 - 1)
+# error OPENSSL_SA_BLOCK_BITS is out of range
+#endif
+
+/*
+ * From the number of bits, work out:
+ * the number of pointers in a tree node;
+ * a bit mask to quickly extract an index and
+ * the maximum depth of the tree structure.
+ */
+#define SA_BLOCK_MAX (1 << OPENSSL_SA_BLOCK_BITS)
+#define SA_BLOCK_MASK (SA_BLOCK_MAX - 1)
+#define SA_BLOCK_MAX_LEVELS (((int)sizeof(ossl_uintmax_t) * 8 \
+ + OPENSSL_SA_BLOCK_BITS - 1) \
+ / OPENSSL_SA_BLOCK_BITS)
+
+struct sparse_array_st {
+ int levels;
+ ossl_uintmax_t top;
+ size_t nelem;
+ void **nodes;
+};
+
+OPENSSL_SA *ossl_sa_new(void)
+{
+ OPENSSL_SA *res = OPENSSL_zalloc(sizeof(*res));
+
+ return res;
+}
+
+static void sa_doall(const OPENSSL_SA *sa, void (*node)(void **),
+ void (*leaf)(ossl_uintmax_t, void *, void *), void *arg)
+{
+ int i[SA_BLOCK_MAX_LEVELS];
+ void *nodes[SA_BLOCK_MAX_LEVELS];
+ ossl_uintmax_t idx = 0;
+ int l = 0;
+
+ i[0] = 0;
+ nodes[0] = sa->nodes;
+ while (l >= 0) {
+ const int n = i[l];
+ void ** const p = nodes[l];
+
+ if (n >= SA_BLOCK_MAX) {
+ if (p != NULL && node != NULL)
+ (*node)(p);
+ l--;
+ idx >>= OPENSSL_SA_BLOCK_BITS;
+ } else {
+ i[l] = n + 1;
+ if (p != NULL && p[n] != NULL) {
+ idx = (idx & ~SA_BLOCK_MASK) | n;
+ if (l < sa->levels - 1) {
+ i[++l] = 0;
+ nodes[l] = p[n];
+ idx <<= OPENSSL_SA_BLOCK_BITS;
+ } else if (leaf != NULL) {
+ (*leaf)(idx, p[n], arg);
+ }
+ }
+ }
+ }
+}
+
+static void sa_free_node(void **p)
+{
+ OPENSSL_free(p);
+}
+
+static void sa_free_leaf(ossl_uintmax_t n, void *p, void *arg)
+{
+ OPENSSL_free(p);
+}
+
+void ossl_sa_free(OPENSSL_SA *sa)
+{
+ if (sa != NULL) {
+ sa_doall(sa, &sa_free_node, NULL, NULL);
+ OPENSSL_free(sa);
+ }
+}
+
+void ossl_sa_free_leaves(OPENSSL_SA *sa)
+{
+ sa_doall(sa, &sa_free_node, &sa_free_leaf, NULL);
+ OPENSSL_free(sa);
+}
+
+/* Wrap this in a structure to avoid compiler warnings */
+struct trampoline_st {
+ void (*func)(ossl_uintmax_t, void *);
+};
+
+static void trampoline(ossl_uintmax_t n, void *l, void *arg)
+{
+ ((const struct trampoline_st *)arg)->func(n, l);
+}
+
+void ossl_sa_doall(const OPENSSL_SA *sa, void (*leaf)(ossl_uintmax_t, void *))
+{
+ struct trampoline_st tramp;
+
+ tramp.func = leaf;
+ if (sa != NULL)
+ sa_doall(sa, NULL, &trampoline, &tramp);
+}
+
+void ossl_sa_doall_arg(const OPENSSL_SA *sa,
+ void (*leaf)(ossl_uintmax_t, void *, void *),
+ void *arg)
+{
+ if (sa != NULL)
+ sa_doall(sa, NULL, leaf, arg);
+}
+
+size_t ossl_sa_num(const OPENSSL_SA *sa)
+{
+ return sa == NULL ? 0 : sa->nelem;
+}
+
+void *ossl_sa_get(const OPENSSL_SA *sa, ossl_uintmax_t n)
+{
+ int level;
+ void **p, *r = NULL;
+
+ if (sa == NULL || sa->nelem == 0)
+ return NULL;
+
+ if (n <= sa->top) {
+ p = sa->nodes;
+ for (level = sa->levels - 1; p != NULL && level > 0; level--)
+ p = (void **)p[(n >> (OPENSSL_SA_BLOCK_BITS * level))
+ & SA_BLOCK_MASK];
+ r = p == NULL ? NULL : p[n & SA_BLOCK_MASK];
+ }
+ return r;
+}
+
+static ossl_inline void **alloc_node(void)
+{
+ return OPENSSL_zalloc(SA_BLOCK_MAX * sizeof(void *));
+}
+
+int ossl_sa_set(OPENSSL_SA *sa, ossl_uintmax_t posn, void *val)
+{
+ int i, level = 1;
+ ossl_uintmax_t n = posn;
+ void **p;
+
+ if (sa == NULL)
+ return 0;
+
+ for (level = 1; level < SA_BLOCK_MAX_LEVELS; level++)
+ if ((n >>= OPENSSL_SA_BLOCK_BITS) == 0)
+ break;
+
+ for (;sa->levels < level; sa->levels++) {
+ p = alloc_node();
+ if (p == NULL)
+ return 0;
+ p[0] = sa->nodes;
+ sa->nodes = p;
+ }
+ if (sa->top < posn)
+ sa->top = posn;
+
+ p = sa->nodes;
+ for (level = sa->levels - 1; level > 0; level--) {
+ i = (posn >> (OPENSSL_SA_BLOCK_BITS * level)) & SA_BLOCK_MASK;
+ if (p[i] == NULL && (p[i] = alloc_node()) == NULL)
+ return 0;
+ p = p[i];
+ }
+ p += posn & SA_BLOCK_MASK;
+ if (val == NULL && *p != NULL)
+ sa->nelem--;
+ else if (val != NULL && *p == NULL)
+ sa->nelem++;
+ *p = val;
+ return 1;
+}
diff --git a/crypto/srp/srp_lib.c b/crypto/srp/srp_lib.c
index ce3504825c53..df0d3720ff0d 100644
--- a/crypto/srp/srp_lib.c
+++ b/crypto/srp/srp_lib.c
@@ -2,7 +2,7 @@
* Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2004, EdelKey Project. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,6 +11,9 @@
* for the EdelKey project.
*/
+/* All the SRP APIs in this file are deprecated */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#ifndef OPENSSL_NO_SRP
# include "internal/cryptlib.h"
# include <openssl/sha.h>
@@ -20,39 +23,54 @@
/* calculate = SHA1(PAD(x) || PAD(y)) */
-static BIGNUM *srp_Calc_xy(const BIGNUM *x, const BIGNUM *y, const BIGNUM *N)
+static BIGNUM *srp_Calc_xy(const BIGNUM *x, const BIGNUM *y, const BIGNUM *N,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
unsigned char digest[SHA_DIGEST_LENGTH];
unsigned char *tmp = NULL;
int numN = BN_num_bytes(N);
BIGNUM *res = NULL;
+ EVP_MD *sha1 = EVP_MD_fetch(libctx, "SHA1", propq);
- if (x != N && BN_ucmp(x, N) >= 0)
+ if (sha1 == NULL)
return NULL;
+
+ if (x != N && BN_ucmp(x, N) >= 0)
+ goto err;
if (y != N && BN_ucmp(y, N) >= 0)
- return NULL;
+ goto err;
if ((tmp = OPENSSL_malloc(numN * 2)) == NULL)
goto err;
if (BN_bn2binpad(x, tmp, numN) < 0
|| BN_bn2binpad(y, tmp + numN, numN) < 0
- || !EVP_Digest(tmp, numN * 2, digest, NULL, EVP_sha1(), NULL))
+ || !EVP_Digest(tmp, numN * 2, digest, NULL, sha1, NULL))
goto err;
res = BN_bin2bn(digest, sizeof(digest), NULL);
err:
+ EVP_MD_free(sha1);
OPENSSL_free(tmp);
return res;
}
-static BIGNUM *srp_Calc_k(const BIGNUM *N, const BIGNUM *g)
+static BIGNUM *srp_Calc_k(const BIGNUM *N, const BIGNUM *g,
+ OSSL_LIB_CTX *libctx,
+ const char *propq)
{
- /* k = SHA1(N | PAD(g)) -- tls-srp draft 8 */
- return srp_Calc_xy(N, g, N);
+ /* k = SHA1(N | PAD(g)) -- tls-srp RFC 5054 */
+ return srp_Calc_xy(N, g, N, libctx, propq);
+}
+
+BIGNUM *SRP_Calc_u_ex(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ /* u = SHA1(PAD(A) || PAD(B) ) -- tls-srp RFC 5054 */
+ return srp_Calc_xy(A, B, N, libctx, propq);
}
BIGNUM *SRP_Calc_u(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N)
{
- /* k = SHA1(PAD(A) || PAD(B) ) -- tls-srp draft 8 */
- return srp_Calc_xy(A, B, N);
+ /* u = SHA1(PAD(A) || PAD(B) ) -- tls-srp RFC 5054 */
+ return srp_Calc_xy(A, B, N, NULL, NULL);
}
BIGNUM *SRP_Calc_server_key(const BIGNUM *A, const BIGNUM *v, const BIGNUM *u,
@@ -85,15 +103,15 @@ BIGNUM *SRP_Calc_server_key(const BIGNUM *A, const BIGNUM *v, const BIGNUM *u,
return S;
}
-BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g,
- const BIGNUM *v)
+BIGNUM *SRP_Calc_B_ex(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g,
+ const BIGNUM *v, OSSL_LIB_CTX *libctx, const char *propq)
{
BIGNUM *kv = NULL, *gb = NULL;
BIGNUM *B = NULL, *k = NULL;
BN_CTX *bn_ctx;
if (b == NULL || N == NULL || g == NULL || v == NULL ||
- (bn_ctx = BN_CTX_new()) == NULL)
+ (bn_ctx = BN_CTX_new_ex(libctx)) == NULL)
return NULL;
if ((kv = BN_new()) == NULL ||
@@ -103,7 +121,7 @@ BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g,
/* B = g**b + k*v */
if (!BN_mod_exp(gb, g, b, N, bn_ctx)
- || (k = srp_Calc_k(N, g)) == NULL
+ || (k = srp_Calc_k(N, g, libctx, propq)) == NULL
|| !BN_mod_mul(kv, v, k, N, bn_ctx)
|| !BN_mod_add(B, gb, kv, N, bn_ctx)) {
BN_free(B);
@@ -117,12 +135,20 @@ BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g,
return B;
}
-BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass)
+BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g,
+ const BIGNUM *v)
+{
+ return SRP_Calc_B_ex(b, N, g, v, NULL, NULL);
+}
+
+BIGNUM *SRP_Calc_x_ex(const BIGNUM *s, const char *user, const char *pass,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
unsigned char dig[SHA_DIGEST_LENGTH];
EVP_MD_CTX *ctxt;
unsigned char *cs = NULL;
BIGNUM *res = NULL;
+ EVP_MD *sha1 = NULL;
if ((s == NULL) || (user == NULL) || (pass == NULL))
return NULL;
@@ -133,12 +159,16 @@ BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass)
if ((cs = OPENSSL_malloc(BN_num_bytes(s))) == NULL)
goto err;
- if (!EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL)
+ sha1 = EVP_MD_fetch(libctx, "SHA1", propq);
+ if (sha1 == NULL)
+ goto err;
+
+ if (!EVP_DigestInit_ex(ctxt, sha1, NULL)
|| !EVP_DigestUpdate(ctxt, user, strlen(user))
|| !EVP_DigestUpdate(ctxt, ":", 1)
|| !EVP_DigestUpdate(ctxt, pass, strlen(pass))
|| !EVP_DigestFinal_ex(ctxt, dig, NULL)
- || !EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL))
+ || !EVP_DigestInit_ex(ctxt, sha1, NULL))
goto err;
if (BN_bn2bin(s, cs) < 0)
goto err;
@@ -152,11 +182,17 @@ BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass)
res = BN_bin2bn(dig, sizeof(dig), NULL);
err:
+ EVP_MD_free(sha1);
OPENSSL_free(cs);
EVP_MD_CTX_free(ctxt);
return res;
}
+BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass)
+{
+ return SRP_Calc_x_ex(s, user, pass, NULL, NULL);
+}
+
BIGNUM *SRP_Calc_A(const BIGNUM *a, const BIGNUM *N, const BIGNUM *g)
{
BN_CTX *bn_ctx;
@@ -173,15 +209,16 @@ BIGNUM *SRP_Calc_A(const BIGNUM *a, const BIGNUM *N, const BIGNUM *g)
return A;
}
-BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g,
- const BIGNUM *x, const BIGNUM *a, const BIGNUM *u)
+BIGNUM *SRP_Calc_client_key_ex(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g,
+ const BIGNUM *x, const BIGNUM *a, const BIGNUM *u,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
BIGNUM *tmp = NULL, *tmp2 = NULL, *tmp3 = NULL, *k = NULL, *K = NULL;
BIGNUM *xtmp = NULL;
BN_CTX *bn_ctx;
if (u == NULL || B == NULL || N == NULL || g == NULL || x == NULL
- || a == NULL || (bn_ctx = BN_CTX_new()) == NULL)
+ || a == NULL || (bn_ctx = BN_CTX_new_ex(libctx)) == NULL)
return NULL;
if ((tmp = BN_new()) == NULL ||
@@ -194,7 +231,7 @@ BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g,
BN_set_flags(tmp, BN_FLG_CONSTTIME);
if (!BN_mod_exp(tmp, g, xtmp, N, bn_ctx))
goto err;
- if ((k = srp_Calc_k(N, g)) == NULL)
+ if ((k = srp_Calc_k(N, g, libctx, propq)) == NULL)
goto err;
if (!BN_mod_mul(tmp2, tmp, k, N, bn_ctx))
goto err;
@@ -220,6 +257,12 @@ BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g,
return K;
}
+BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g,
+ const BIGNUM *x, const BIGNUM *a, const BIGNUM *u)
+{
+ return SRP_Calc_client_key_ex(N, B, g, x, a, u, NULL, NULL);
+}
+
int SRP_Verify_B_mod_N(const BIGNUM *B, const BIGNUM *N)
{
BIGNUM *r;
@@ -248,26 +291,26 @@ int SRP_Verify_A_mod_N(const BIGNUM *A, const BIGNUM *N)
}
static SRP_gN knowngN[] = {
- {"8192", &bn_generator_19, &bn_group_8192},
- {"6144", &bn_generator_5, &bn_group_6144},
- {"4096", &bn_generator_5, &bn_group_4096},
- {"3072", &bn_generator_5, &bn_group_3072},
- {"2048", &bn_generator_2, &bn_group_2048},
- {"1536", &bn_generator_2, &bn_group_1536},
- {"1024", &bn_generator_2, &bn_group_1024},
+ {"8192", &ossl_bn_generator_19, &ossl_bn_group_8192},
+ {"6144", &ossl_bn_generator_5, &ossl_bn_group_6144},
+ {"4096", &ossl_bn_generator_5, &ossl_bn_group_4096},
+ {"3072", &ossl_bn_generator_5, &ossl_bn_group_3072},
+ {"2048", &ossl_bn_generator_2, &ossl_bn_group_2048},
+ {"1536", &ossl_bn_generator_2, &ossl_bn_group_1536},
+ {"1024", &ossl_bn_generator_2, &ossl_bn_group_1024},
};
# define KNOWN_GN_NUMBER sizeof(knowngN) / sizeof(SRP_gN)
/*
* Check if G and N are known parameters. The values have been generated
- * from the ietf-tls-srp draft version 8
+ * from the IETF RFC 5054
*/
char *SRP_check_known_gN_param(const BIGNUM *g, const BIGNUM *N)
{
size_t i;
if ((g == NULL) || (N == NULL))
- return 0;
+ return NULL;
for (i = 0; i < KNOWN_GN_NUMBER; i++) {
if (BN_cmp(knowngN[i].g, g) == 0 && BN_cmp(knowngN[i].N, N) == 0)
diff --git a/crypto/srp/srp_vfy.c b/crypto/srp/srp_vfy.c
index 394e1180dfa4..e8beb60d278a 100644
--- a/crypto/srp/srp_vfy.c
+++ b/crypto/srp/srp_vfy.c
@@ -2,7 +2,7 @@
* Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2004, EdelKey Project. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,6 +11,9 @@
* for the EdelKey project.
*/
+/* All the SRP APIs in this file are deprecated */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#ifndef OPENSSL_NO_SRP
# include "internal/cryptlib.h"
# include "crypto/evp.h"
@@ -184,12 +187,12 @@ void SRP_user_pwd_free(SRP_user_pwd *user_pwd)
OPENSSL_free(user_pwd);
}
-static SRP_user_pwd *SRP_user_pwd_new(void)
+SRP_user_pwd *SRP_user_pwd_new(void)
{
SRP_user_pwd *ret;
if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) {
- /* SRPerr(SRP_F_SRP_USER_PWD_NEW, ERR_R_MALLOC_FAILURE); */ /*ckerr_ignore*/
+ /* ERR_raise(ERR_LIB_SRP, ERR_R_MALLOC_FAILURE); */ /*ckerr_ignore*/
return NULL;
}
ret->N = NULL;
@@ -201,16 +204,18 @@ static SRP_user_pwd *SRP_user_pwd_new(void)
return ret;
}
-static void SRP_user_pwd_set_gN(SRP_user_pwd *vinfo, const BIGNUM *g,
- const BIGNUM *N)
+void SRP_user_pwd_set_gN(SRP_user_pwd *vinfo, const BIGNUM *g,
+ const BIGNUM *N)
{
vinfo->N = N;
vinfo->g = g;
}
-static int SRP_user_pwd_set_ids(SRP_user_pwd *vinfo, const char *id,
- const char *info)
+int SRP_user_pwd_set1_ids(SRP_user_pwd *vinfo, const char *id,
+ const char *info)
{
+ OPENSSL_free(vinfo->id);
+ OPENSSL_free(vinfo->info);
if (id != NULL && NULL == (vinfo->id = OPENSSL_strdup(id)))
return 0;
return (info == NULL || NULL != (vinfo->info = OPENSSL_strdup(info)));
@@ -243,8 +248,10 @@ static int SRP_user_pwd_set_sv(SRP_user_pwd *vinfo, const char *s,
return 0;
}
-static int SRP_user_pwd_set_sv_BN(SRP_user_pwd *vinfo, BIGNUM *s, BIGNUM *v)
+int SRP_user_pwd_set0_sv(SRP_user_pwd *vinfo, BIGNUM *s, BIGNUM *v)
{
+ BN_free(vinfo->s);
+ BN_clear_free(vinfo->v);
vinfo->v = v;
vinfo->s = s;
return (vinfo->s != NULL && vinfo->v != NULL);
@@ -260,8 +267,8 @@ static SRP_user_pwd *srp_user_pwd_dup(SRP_user_pwd *src)
return NULL;
SRP_user_pwd_set_gN(ret, src->g, src->N);
- if (!SRP_user_pwd_set_ids(ret, src->id, src->info)
- || !SRP_user_pwd_set_sv_BN(ret, BN_dup(src->s), BN_dup(src->v))) {
+ if (!SRP_user_pwd_set1_ids(ret, src->id, src->info)
+ || !SRP_user_pwd_set0_sv(ret, BN_dup(src->s), BN_dup(src->v))) {
SRP_user_pwd_free(ret);
return NULL;
}
@@ -340,12 +347,13 @@ static SRP_gN *SRP_get_gN_by_id(const char *id, STACK_OF(SRP_gN) *gN_tab)
int i;
SRP_gN *gN;
- if (gN_tab != NULL)
+ if (gN_tab != NULL) {
for (i = 0; i < sk_SRP_gN_num(gN_tab); i++) {
gN = sk_SRP_gN_value(gN_tab, i);
if (gN && (id == NULL || strcmp(gN->id, id) == 0))
return gN;
}
+ }
return SRP_get_default_gN(id);
}
@@ -374,9 +382,13 @@ static BIGNUM *SRP_gN_place_bn(STACK_OF(SRP_gN_cache) *gN_cache, char *ch)
}
/*
- * this function parses verifier file. Format is:
- * string(index):base64(N):base64(g):0
- * string(username):base64(v):base64(salt):int(index)
+ * This function parses the verifier file generated by the srp app.
+ * The format for each entry is:
+ * V base64(verifier) base64(salt) username gNid userinfo(optional)
+ * or
+ * I base64(N) base64(g)
+ * Note that base64 is the SRP variant of base64 encoding described
+ * in t_fromb64().
*/
int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file)
@@ -441,7 +453,7 @@ int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file)
goto err;
SRP_user_pwd_set_gN(user_pwd, lgN->g, lgN->N);
- if (!SRP_user_pwd_set_ids
+ if (!SRP_user_pwd_set1_ids
(user_pwd, pp[DB_srpid], pp[DB_srpinfo]))
goto err;
@@ -509,7 +521,14 @@ static SRP_user_pwd *find_user(SRP_VBASE *vb, char *username)
return NULL;
}
-# if OPENSSL_API_COMPAT < 0x10100000L
+int SRP_VBASE_add0_user(SRP_VBASE *vb, SRP_user_pwd *user_pwd)
+{
+ if (sk_SRP_user_pwd_push(vb->users_pwd, user_pwd) <= 0)
+ return 0;
+ return 1;
+}
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
/*
* DEPRECATED: use SRP_VBASE_get1_by_user instead.
* This method ignores the configured seed and fails for an unknown user.
@@ -532,6 +551,7 @@ SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username)
unsigned char digv[SHA_DIGEST_LENGTH];
unsigned char digs[SHA_DIGEST_LENGTH];
EVP_MD_CTX *ctxt = NULL;
+ EVP_MD *md = NULL;
if (vb == NULL)
return NULL;
@@ -550,26 +570,32 @@ SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username)
SRP_user_pwd_set_gN(user, vb->default_g, vb->default_N);
- if (!SRP_user_pwd_set_ids(user, username, NULL))
+ if (!SRP_user_pwd_set1_ids(user, username, NULL))
goto err;
if (RAND_priv_bytes(digv, SHA_DIGEST_LENGTH) <= 0)
goto err;
+ md = EVP_MD_fetch(NULL, SN_sha1, NULL);
+ if (md == NULL)
+ goto err;
ctxt = EVP_MD_CTX_new();
if (ctxt == NULL
- || !EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL)
+ || !EVP_DigestInit_ex(ctxt, md, NULL)
|| !EVP_DigestUpdate(ctxt, vb->seed_key, strlen(vb->seed_key))
|| !EVP_DigestUpdate(ctxt, username, strlen(username))
|| !EVP_DigestFinal_ex(ctxt, digs, NULL))
goto err;
EVP_MD_CTX_free(ctxt);
ctxt = NULL;
- if (SRP_user_pwd_set_sv_BN(user,
- BN_bin2bn(digs, SHA_DIGEST_LENGTH, NULL),
- BN_bin2bn(digv, SHA_DIGEST_LENGTH, NULL)))
+ EVP_MD_free(md);
+ md = NULL;
+ if (SRP_user_pwd_set0_sv(user,
+ BN_bin2bn(digs, SHA_DIGEST_LENGTH, NULL),
+ BN_bin2bn(digv, SHA_DIGEST_LENGTH, NULL)))
return user;
err:
+ EVP_MD_free(md);
EVP_MD_CTX_free(ctxt);
SRP_user_pwd_free(user);
return NULL;
@@ -578,8 +604,9 @@ SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username)
/*
* create a verifier (*salt,*verifier,g and N are in base64)
*/
-char *SRP_create_verifier(const char *user, const char *pass, char **salt,
- char **verifier, const char *N, const char *g)
+char *SRP_create_verifier_ex(const char *user, const char *pass, char **salt,
+ char **verifier, const char *N, const char *g,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
int len;
char *result = NULL, *vf = NULL;
@@ -609,7 +636,7 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt,
g_bn = g_bn_alloc;
defgNid = "*";
} else {
- SRP_gN *gN = SRP_get_gN_by_id(g, NULL);
+ SRP_gN *gN = SRP_get_default_gN(g);
if (gN == NULL)
goto err;
N_bn = gN->N;
@@ -618,7 +645,7 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt,
}
if (*salt == NULL) {
- if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0)
+ if (RAND_bytes_ex(libctx, tmp2, SRP_RANDOM_SALT_LEN, 0) <= 0)
goto err;
s = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL);
@@ -630,7 +657,8 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt,
if (s == NULL)
goto err;
- if (!SRP_create_verifier_BN(user, pass, &s, &v, N_bn, g_bn))
+ if (!SRP_create_verifier_BN_ex(user, pass, &s, &v, N_bn, g_bn, libctx,
+ propq))
goto err;
if (BN_bn2bin(v, tmp) < 0)
@@ -667,6 +695,12 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt,
return result;
}
+char *SRP_create_verifier(const char *user, const char *pass, char **salt,
+ char **verifier, const char *N, const char *g)
+{
+ return SRP_create_verifier_ex(user, pass, salt, verifier, N, g, NULL, NULL);
+}
+
/*
* create a verifier (*salt,*verifier,g and N are BIGNUMs). If *salt != NULL
* then the provided salt will be used. On successful exit *verifier will point
@@ -676,13 +710,14 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt,
* The caller is responsible for freeing the allocated *salt and *verifier
* BIGNUMS.
*/
-int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt,
- BIGNUM **verifier, const BIGNUM *N,
- const BIGNUM *g)
+int SRP_create_verifier_BN_ex(const char *user, const char *pass, BIGNUM **salt,
+ BIGNUM **verifier, const BIGNUM *N,
+ const BIGNUM *g, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
int result = 0;
BIGNUM *x = NULL;
- BN_CTX *bn_ctx = BN_CTX_new();
+ BN_CTX *bn_ctx = BN_CTX_new_ex(libctx);
unsigned char tmp2[MAX_LEN];
BIGNUM *salttmp = NULL, *verif;
@@ -693,7 +728,7 @@ int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt,
goto err;
if (*salt == NULL) {
- if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0)
+ if (RAND_bytes_ex(libctx, tmp2, SRP_RANDOM_SALT_LEN, 0) <= 0)
goto err;
salttmp = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL);
@@ -703,7 +738,7 @@ int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt,
salttmp = *salt;
}
- x = SRP_Calc_x(salttmp, user, pass);
+ x = SRP_Calc_x_ex(salttmp, user, pass, libctx, propq);
if (x == NULL)
goto err;
@@ -728,4 +763,11 @@ int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt,
return result;
}
+int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt,
+ BIGNUM **verifier, const BIGNUM *N,
+ const BIGNUM *g)
+{
+ return SRP_create_verifier_BN_ex(user, pass, salt, verifier, N, g, NULL,
+ NULL);
+}
#endif
diff --git a/crypto/stack/build.info b/crypto/stack/build.info
index e5870210ac38..23d83a6f111b 100644
--- a/crypto/stack/build.info
+++ b/crypto/stack/build.info
@@ -1,2 +1,3 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=stack.c
+SOURCE[../../providers/libfips.a]=stack.c
diff --git a/crypto/stack/stack.c b/crypto/stack/stack.c
index 975515db5972..51080b876797 100644
--- a/crypto/stack/stack.c
+++ b/crypto/stack/stack.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,7 +11,6 @@
#include "internal/cryptlib.h"
#include "internal/numbers.h"
#include <openssl/stack.h>
-#include <openssl/objects.h>
#include <errno.h>
#include <openssl/e_os2.h> /* For ossl_inline */
@@ -20,8 +19,7 @@
*/
static const int min_nodes = 4;
static const int max_nodes = SIZE_MAX / sizeof(void *) < INT_MAX
- ? (int)(SIZE_MAX / sizeof(void *))
- : INT_MAX;
+ ? (int)(SIZE_MAX / sizeof(void *)) : INT_MAX;
struct stack_st {
int num;
@@ -31,7 +29,8 @@ struct stack_st {
OPENSSL_sk_compfunc comp;
};
-OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, OPENSSL_sk_compfunc c)
+OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk,
+ OPENSSL_sk_compfunc c)
{
OPENSSL_sk_compfunc old = sk->comp;
@@ -46,46 +45,58 @@ OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk)
{
OPENSSL_STACK *ret;
- if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) {
- CRYPTOerr(CRYPTO_F_OPENSSL_SK_DUP, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
+ if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
+ goto err;
- /* direct structure assignment */
- *ret = *sk;
+ if (sk == NULL) {
+ ret->num = 0;
+ ret->sorted = 0;
+ ret->comp = NULL;
+ } else {
+ /* direct structure assignment */
+ *ret = *sk;
+ }
- if (sk->num == 0) {
+ if (sk == NULL || sk->num == 0) {
/* postpone |ret->data| allocation */
ret->data = NULL;
ret->num_alloc = 0;
return ret;
}
+
/* duplicate |sk->data| content */
- if ((ret->data = OPENSSL_malloc(sizeof(*ret->data) * sk->num_alloc)) == NULL)
+ ret->data = OPENSSL_malloc(sizeof(*ret->data) * sk->num_alloc);
+ if (ret->data == NULL)
goto err;
memcpy(ret->data, sk->data, sizeof(void *) * sk->num);
return ret;
+
err:
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
OPENSSL_sk_free(ret);
return NULL;
}
OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk,
- OPENSSL_sk_copyfunc copy_func,
- OPENSSL_sk_freefunc free_func)
+ OPENSSL_sk_copyfunc copy_func,
+ OPENSSL_sk_freefunc free_func)
{
OPENSSL_STACK *ret;
int i;
- if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) {
- CRYPTOerr(CRYPTO_F_OPENSSL_SK_DEEP_COPY, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
+ if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
+ goto err;
- /* direct structure assignment */
- *ret = *sk;
+ if (sk == NULL) {
+ ret->num = 0;
+ ret->sorted = 0;
+ ret->comp = NULL;
+ } else {
+ /* direct structure assignment */
+ *ret = *sk;
+ }
- if (sk->num == 0) {
+ if (sk == NULL || sk->num == 0) {
/* postpone |ret| data allocation */
ret->data = NULL;
ret->num_alloc = 0;
@@ -94,10 +105,8 @@ OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk,
ret->num_alloc = sk->num > min_nodes ? sk->num : min_nodes;
ret->data = OPENSSL_zalloc(sizeof(*ret->data) * ret->num_alloc);
- if (ret->data == NULL) {
- OPENSSL_free(ret);
- return NULL;
- }
+ if (ret->data == NULL)
+ goto err;
for (i = 0; i < ret->num; ++i) {
if (sk->data[i] == NULL)
@@ -106,11 +115,15 @@ OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk,
while (--i >= 0)
if (ret->data[i] != NULL)
free_func((void *)ret->data[i]);
- OPENSSL_sk_free(ret);
- return NULL;
+ goto err;
}
}
return ret;
+
+ err:
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ OPENSSL_sk_free(ret);
+ return NULL;
}
OPENSSL_STACK *OPENSSL_sk_new_null(void)
@@ -163,8 +176,10 @@ static int sk_reserve(OPENSSL_STACK *st, int n, int exact)
int num_alloc;
/* Check to see the reservation isn't exceeding the hard limit */
- if (n > max_nodes - st->num)
+ if (n > max_nodes - st->num) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS);
return 0;
+ }
/* Figure out the new size */
num_alloc = st->num + n;
@@ -178,7 +193,7 @@ static int sk_reserve(OPENSSL_STACK *st, int n, int exact)
* so |num_alloc| value is |n| or |min_nodes| if greater than |n|.
*/
if ((st->data = OPENSSL_zalloc(sizeof(void *) * num_alloc)) == NULL) {
- CRYPTOerr(CRYPTO_F_SK_RESERVE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return 0;
}
st->num_alloc = num_alloc;
@@ -189,15 +204,19 @@ static int sk_reserve(OPENSSL_STACK *st, int n, int exact)
if (num_alloc <= st->num_alloc)
return 1;
num_alloc = compute_growth(num_alloc, st->num_alloc);
- if (num_alloc == 0)
+ if (num_alloc == 0) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS);
return 0;
+ }
} else if (num_alloc == st->num_alloc) {
return 1;
}
tmpdata = OPENSSL_realloc((void *)st->data, sizeof(void *) * num_alloc);
- if (tmpdata == NULL)
+ if (tmpdata == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return 0;
+ }
st->data = tmpdata;
st->num_alloc = num_alloc;
@@ -208,8 +227,10 @@ OPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n)
{
OPENSSL_STACK *st = OPENSSL_zalloc(sizeof(OPENSSL_STACK));
- if (st == NULL)
+ if (st == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return NULL;
+ }
st->comp = c;
@@ -226,8 +247,10 @@ OPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n)
int OPENSSL_sk_reserve(OPENSSL_STACK *st, int n)
{
- if (st == NULL)
+ if (st == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
+ }
if (n < 0)
return 1;
@@ -236,8 +259,14 @@ int OPENSSL_sk_reserve(OPENSSL_STACK *st, int n)
int OPENSSL_sk_insert(OPENSSL_STACK *st, const void *data, int loc)
{
- if (st == NULL || st->num == max_nodes)
+ if (st == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
+ }
+ if (st->num == max_nodes) {
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS);
+ return 0;
+ }
if (!sk_reserve(st, 1, 0))
return 0;
@@ -259,8 +288,8 @@ static ossl_inline void *internal_delete(OPENSSL_STACK *st, int loc)
const void *ret = st->data[loc];
if (loc != st->num - 1)
- memmove(&st->data[loc], &st->data[loc + 1],
- sizeof(st->data[0]) * (st->num - loc - 1));
+ memmove(&st->data[loc], &st->data[loc + 1],
+ sizeof(st->data[0]) * (st->num - loc - 1));
st->num--;
return (void *)ret;
@@ -270,6 +299,9 @@ void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p)
{
int i;
+ if (st == NULL)
+ return NULL;
+
for (i = 0; i < st->num; i++)
if (st->data[i] == p)
return internal_delete(st, i);
@@ -285,7 +317,7 @@ void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc)
}
static int internal_find(OPENSSL_STACK *st, const void *data,
- int ret_val_options)
+ int ret_val_options, int *pnum)
{
const void *r;
int i;
@@ -295,8 +327,13 @@ static int internal_find(OPENSSL_STACK *st, const void *data,
if (st->comp == NULL) {
for (i = 0; i < st->num; i++)
- if (st->data[i] == data)
+ if (st->data[i] == data) {
+ if (pnum != NULL)
+ *pnum = 1;
return i;
+ }
+ if (pnum != NULL)
+ *pnum = 0;
return -1;
}
@@ -307,20 +344,41 @@ static int internal_find(OPENSSL_STACK *st, const void *data,
}
if (data == NULL)
return -1;
- r = OBJ_bsearch_ex_(&data, st->data, st->num, sizeof(void *), st->comp,
- ret_val_options);
+ if (pnum != NULL)
+ ret_val_options |= OSSL_BSEARCH_FIRST_VALUE_ON_MATCH;
+ r = ossl_bsearch(&data, st->data, st->num, sizeof(void *), st->comp,
+ ret_val_options);
+
+ if (pnum != NULL) {
+ *pnum = 0;
+ if (r != NULL) {
+ const void **p = (const void **)r;
+
+ while (p < st->data + st->num) {
+ if (st->comp(&data, p) != 0)
+ break;
+ ++*pnum;
+ ++p;
+ }
+ }
+ }
return r == NULL ? -1 : (int)((const void **)r - st->data);
}
int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data)
{
- return internal_find(st, data, OBJ_BSEARCH_FIRST_VALUE_ON_MATCH);
+ return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, NULL);
}
int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data)
{
- return internal_find(st, data, OBJ_BSEARCH_VALUE_ON_NOMATCH);
+ return internal_find(st, data, OSSL_BSEARCH_VALUE_ON_NOMATCH, NULL);
+}
+
+int OPENSSL_sk_find_all(OPENSSL_STACK *st, const void *data, int *pnum)
+{
+ return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, pnum);
}
int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data)
@@ -391,8 +449,15 @@ void *OPENSSL_sk_value(const OPENSSL_STACK *st, int i)
void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data)
{
- if (st == NULL || i < 0 || i >= st->num)
+ if (st == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
+ }
+ if (i < 0 || i >= st->num) {
+ ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT,
+ "i=%d", i);
+ return NULL;
+ }
st->data[i] = data;
st->sorted = 0;
return (void *)st->data[i];
diff --git a/crypto/store/build.info b/crypto/store/build.info
index 7d882f313ea5..43d9e544a01f 100644
--- a/crypto/store/build.info
+++ b/crypto/store/build.info
@@ -1,4 +1,7 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
- store_err.c store_init.c store_lib.c store_register.c store_strings.c \
- loader_file.c
+ store_err.c store_lib.c store_result.c store_strings.c store_meth.c
+
+IF[{- !$disabled{'deprecated-3.0'} -}]
+ SOURCE[../../libcrypto]=store_init.c store_register.c
+ENDIF
diff --git a/crypto/store/loader_file.c b/crypto/store/loader_file.c
deleted file mode 100644
index 32e7b9f65a41..000000000000
--- a/crypto/store/loader_file.c
+++ /dev/null
@@ -1,1477 +0,0 @@
-/*
- * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "e_os.h"
-#include <string.h>
-#include <sys/stat.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include <openssl/bio.h>
-#include <openssl/dsa.h> /* For d2i_DSAPrivateKey */
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/pem.h>
-#include <openssl/pkcs12.h> /* For the PKCS8 stuff o.O */
-#include <openssl/rsa.h> /* For d2i_RSAPrivateKey */
-#include <openssl/safestack.h>
-#include <openssl/store.h>
-#include <openssl/ui.h>
-#include <openssl/x509.h> /* For the PKCS8 stuff o.O */
-#include "crypto/asn1.h"
-#include "crypto/ctype.h"
-#include "internal/o_dir.h"
-#include "internal/cryptlib.h"
-#include "crypto/store.h"
-#include "store_local.h"
-
-#ifdef _WIN32
-# define stat _stat
-#endif
-
-#ifndef S_ISDIR
-# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
-#endif
-
-/*-
- * Password prompting
- * ------------------
- */
-
-static char *file_get_pass(const UI_METHOD *ui_method, char *pass,
- size_t maxsize, const char *prompt_info, void *data)
-{
- UI *ui = UI_new();
- char *prompt = NULL;
-
- if (ui == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- if (ui_method != NULL)
- UI_set_method(ui, ui_method);
- UI_add_user_data(ui, data);
-
- if ((prompt = UI_construct_prompt(ui, "pass phrase",
- prompt_info)) == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, ERR_R_MALLOC_FAILURE);
- pass = NULL;
- } else if (!UI_add_input_string(ui, prompt, UI_INPUT_FLAG_DEFAULT_PWD,
- pass, 0, maxsize - 1)) {
- OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, ERR_R_UI_LIB);
- pass = NULL;
- } else {
- switch (UI_process(ui)) {
- case -2:
- OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS,
- OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED);
- pass = NULL;
- break;
- case -1:
- OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, ERR_R_UI_LIB);
- pass = NULL;
- break;
- default:
- break;
- }
- }
-
- OPENSSL_free(prompt);
- UI_free(ui);
- return pass;
-}
-
-struct pem_pass_data {
- const UI_METHOD *ui_method;
- void *data;
- const char *prompt_info;
-};
-
-static int file_fill_pem_pass_data(struct pem_pass_data *pass_data,
- const char *prompt_info,
- const UI_METHOD *ui_method, void *ui_data)
-{
- if (pass_data == NULL)
- return 0;
- pass_data->ui_method = ui_method;
- pass_data->data = ui_data;
- pass_data->prompt_info = prompt_info;
- return 1;
-}
-
-/* This is used anywhere a pem_password_cb is needed */
-static int file_get_pem_pass(char *buf, int num, int w, void *data)
-{
- struct pem_pass_data *pass_data = data;
- char *pass = file_get_pass(pass_data->ui_method, buf, num,
- pass_data->prompt_info, pass_data->data);
-
- return pass == NULL ? 0 : strlen(pass);
-}
-
-/*-
- * The file scheme decoders
- * ------------------------
- *
- * Each possible data type has its own decoder, which either operates
- * through a given PEM name, or attempts to decode to see if the blob
- * it's given is decodable for its data type. The assumption is that
- * only the correct data type will match the content.
- */
-
-/*-
- * The try_decode function is called to check if the blob of data can
- * be used by this handler, and if it can, decodes it into a supported
- * OpenSSL type and returns a OSSL_STORE_INFO with the decoded data.
- * Input:
- * pem_name: If this blob comes from a PEM file, this holds
- * the PEM name. If it comes from another type of
- * file, this is NULL.
- * pem_header: If this blob comes from a PEM file, this holds
- * the PEM headers. If it comes from another type of
- * file, this is NULL.
- * blob: The blob of data to match with what this handler
- * can use.
- * len: The length of the blob.
- * handler_ctx: For a handler marked repeatable, this pointer can
- * be used to create a context for the handler. IT IS
- * THE HANDLER'S RESPONSIBILITY TO CREATE AND DESTROY
- * THIS CONTEXT APPROPRIATELY, i.e. create on first call
- * and destroy when about to return NULL.
- * matchcount: A pointer to an int to count matches for this data.
- * Usually becomes 0 (no match) or 1 (match!), but may
- * be higher in the (unlikely) event that the data matches
- * more than one possibility. The int will always be
- * zero when the function is called.
- * ui_method: Application UI method for getting a password, pin
- * or any other interactive data.
- * ui_data: Application data to be passed to ui_method when
- * it's called.
- * Output:
- * a OSSL_STORE_INFO
- */
-typedef OSSL_STORE_INFO *(*file_try_decode_fn)(const char *pem_name,
- const char *pem_header,
- const unsigned char *blob,
- size_t len, void **handler_ctx,
- int *matchcount,
- const UI_METHOD *ui_method,
- void *ui_data);
-/*
- * The eof function should return 1 if there's no more data to be found
- * with the handler_ctx, otherwise 0. This is only used when the handler is
- * marked repeatable.
- */
-typedef int (*file_eof_fn)(void *handler_ctx);
-/*
- * The destroy_ctx function is used to destroy the handler_ctx that was
- * initiated by a repeatable try_decode function. This is only used when
- * the handler is marked repeatable.
- */
-typedef void (*file_destroy_ctx_fn)(void **handler_ctx);
-
-typedef struct file_handler_st {
- const char *name;
- file_try_decode_fn try_decode;
- file_eof_fn eof;
- file_destroy_ctx_fn destroy_ctx;
-
- /* flags */
- int repeatable;
-} FILE_HANDLER;
-
-/*
- * PKCS#12 decoder. It operates by decoding all of the blob content,
- * extracting all the interesting data from it and storing them internally,
- * then serving them one piece at a time.
- */
-static OSSL_STORE_INFO *try_decode_PKCS12(const char *pem_name,
- const char *pem_header,
- const unsigned char *blob,
- size_t len, void **pctx,
- int *matchcount,
- const UI_METHOD *ui_method,
- void *ui_data)
-{
- OSSL_STORE_INFO *store_info = NULL;
- STACK_OF(OSSL_STORE_INFO) *ctx = *pctx;
-
- if (ctx == NULL) {
- /* Initial parsing */
- PKCS12 *p12;
- int ok = 0;
-
- if (pem_name != NULL)
- /* No match, there is no PEM PKCS12 tag */
- return NULL;
-
- if ((p12 = d2i_PKCS12(NULL, &blob, len)) != NULL) {
- char *pass = NULL;
- char tpass[PEM_BUFSIZE];
- EVP_PKEY *pkey = NULL;
- X509 *cert = NULL;
- STACK_OF(X509) *chain = NULL;
-
- *matchcount = 1;
-
- if (PKCS12_verify_mac(p12, "", 0)
- || PKCS12_verify_mac(p12, NULL, 0)) {
- pass = "";
- } else {
- if ((pass = file_get_pass(ui_method, tpass, PEM_BUFSIZE,
- "PKCS12 import password",
- ui_data)) == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS12,
- OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR);
- goto p12_end;
- }
- if (!PKCS12_verify_mac(p12, pass, strlen(pass))) {
- OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS12,
- OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC);
- goto p12_end;
- }
- }
-
- if (PKCS12_parse(p12, pass, &pkey, &cert, &chain)) {
- OSSL_STORE_INFO *osi_pkey = NULL;
- OSSL_STORE_INFO *osi_cert = NULL;
- OSSL_STORE_INFO *osi_ca = NULL;
-
- if ((ctx = sk_OSSL_STORE_INFO_new_null()) != NULL
- && (osi_pkey = OSSL_STORE_INFO_new_PKEY(pkey)) != NULL
- && sk_OSSL_STORE_INFO_push(ctx, osi_pkey) != 0
- && (osi_cert = OSSL_STORE_INFO_new_CERT(cert)) != NULL
- && sk_OSSL_STORE_INFO_push(ctx, osi_cert) != 0) {
- ok = 1;
- osi_pkey = NULL;
- osi_cert = NULL;
-
- while(sk_X509_num(chain) > 0) {
- X509 *ca = sk_X509_value(chain, 0);
-
- if ((osi_ca = OSSL_STORE_INFO_new_CERT(ca)) == NULL
- || sk_OSSL_STORE_INFO_push(ctx, osi_ca) == 0) {
- ok = 0;
- break;
- }
- osi_ca = NULL;
- (void)sk_X509_shift(chain);
- }
- }
- if (!ok) {
- OSSL_STORE_INFO_free(osi_ca);
- OSSL_STORE_INFO_free(osi_cert);
- OSSL_STORE_INFO_free(osi_pkey);
- sk_OSSL_STORE_INFO_pop_free(ctx, OSSL_STORE_INFO_free);
- EVP_PKEY_free(pkey);
- X509_free(cert);
- sk_X509_pop_free(chain, X509_free);
- ctx = NULL;
- }
- *pctx = ctx;
- }
- }
- p12_end:
- PKCS12_free(p12);
- if (!ok)
- return NULL;
- }
-
- if (ctx != NULL) {
- *matchcount = 1;
- store_info = sk_OSSL_STORE_INFO_shift(ctx);
- }
-
- return store_info;
-}
-
-static int eof_PKCS12(void *ctx_)
-{
- STACK_OF(OSSL_STORE_INFO) *ctx = ctx_;
-
- return ctx == NULL || sk_OSSL_STORE_INFO_num(ctx) == 0;
-}
-
-static void destroy_ctx_PKCS12(void **pctx)
-{
- STACK_OF(OSSL_STORE_INFO) *ctx = *pctx;
-
- sk_OSSL_STORE_INFO_pop_free(ctx, OSSL_STORE_INFO_free);
- *pctx = NULL;
-}
-
-static FILE_HANDLER PKCS12_handler = {
- "PKCS12",
- try_decode_PKCS12,
- eof_PKCS12,
- destroy_ctx_PKCS12,
- 1 /* repeatable */
-};
-
-/*
- * Encrypted PKCS#8 decoder. It operates by just decrypting the given blob
- * into a new blob, which is returned as an EMBEDDED STORE_INFO. The whole
- * decoding process will then start over with the new blob.
- */
-static OSSL_STORE_INFO *try_decode_PKCS8Encrypted(const char *pem_name,
- const char *pem_header,
- const unsigned char *blob,
- size_t len, void **pctx,
- int *matchcount,
- const UI_METHOD *ui_method,
- void *ui_data)
-{
- X509_SIG *p8 = NULL;
- char kbuf[PEM_BUFSIZE];
- char *pass = NULL;
- const X509_ALGOR *dalg = NULL;
- const ASN1_OCTET_STRING *doct = NULL;
- OSSL_STORE_INFO *store_info = NULL;
- BUF_MEM *mem = NULL;
- unsigned char *new_data = NULL;
- int new_data_len;
-
- if (pem_name != NULL) {
- if (strcmp(pem_name, PEM_STRING_PKCS8) != 0)
- return NULL;
- *matchcount = 1;
- }
-
- if ((p8 = d2i_X509_SIG(NULL, &blob, len)) == NULL)
- return NULL;
-
- *matchcount = 1;
-
- if ((mem = BUF_MEM_new()) == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED,
- ERR_R_MALLOC_FAILURE);
- goto nop8;
- }
-
- if ((pass = file_get_pass(ui_method, kbuf, PEM_BUFSIZE,
- "PKCS8 decrypt password", ui_data)) == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED,
- OSSL_STORE_R_BAD_PASSWORD_READ);
- goto nop8;
- }
-
- X509_SIG_get0(p8, &dalg, &doct);
- if (!PKCS12_pbe_crypt(dalg, pass, strlen(pass), doct->data, doct->length,
- &new_data, &new_data_len, 0))
- goto nop8;
-
- mem->data = (char *)new_data;
- mem->max = mem->length = (size_t)new_data_len;
- X509_SIG_free(p8);
- p8 = NULL;
-
- store_info = ossl_store_info_new_EMBEDDED(PEM_STRING_PKCS8INF, mem);
- if (store_info == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED,
- ERR_R_MALLOC_FAILURE);
- goto nop8;
- }
-
- return store_info;
- nop8:
- X509_SIG_free(p8);
- BUF_MEM_free(mem);
- return NULL;
-}
-
-static FILE_HANDLER PKCS8Encrypted_handler = {
- "PKCS8Encrypted",
- try_decode_PKCS8Encrypted
-};
-
-/*
- * Private key decoder. Decodes all sorts of private keys, both PKCS#8
- * encoded ones and old style PEM ones (with the key type is encoded into
- * the PEM name).
- */
-int pem_check_suffix(const char *pem_str, const char *suffix);
-static OSSL_STORE_INFO *try_decode_PrivateKey(const char *pem_name,
- const char *pem_header,
- const unsigned char *blob,
- size_t len, void **pctx,
- int *matchcount,
- const UI_METHOD *ui_method,
- void *ui_data)
-{
- OSSL_STORE_INFO *store_info = NULL;
- EVP_PKEY *pkey = NULL;
- const EVP_PKEY_ASN1_METHOD *ameth = NULL;
-
- if (pem_name != NULL) {
- if (strcmp(pem_name, PEM_STRING_PKCS8INF) == 0) {
- PKCS8_PRIV_KEY_INFO *p8inf =
- d2i_PKCS8_PRIV_KEY_INFO(NULL, &blob, len);
-
- *matchcount = 1;
- if (p8inf != NULL)
- pkey = EVP_PKCS82PKEY(p8inf);
- PKCS8_PRIV_KEY_INFO_free(p8inf);
- } else {
- int slen;
-
- if ((slen = pem_check_suffix(pem_name, "PRIVATE KEY")) > 0
- && (ameth = EVP_PKEY_asn1_find_str(NULL, pem_name,
- slen)) != NULL) {
- *matchcount = 1;
- pkey = d2i_PrivateKey(ameth->pkey_id, NULL, &blob, len);
- }
- }
- } else {
- int i;
-#ifndef OPENSSL_NO_ENGINE
- ENGINE *curengine = ENGINE_get_first();
-
- while (curengine != NULL) {
- ENGINE_PKEY_ASN1_METHS_PTR asn1meths =
- ENGINE_get_pkey_asn1_meths(curengine);
-
- if (asn1meths != NULL) {
- const int *nids = NULL;
- int nids_n = asn1meths(curengine, NULL, &nids, 0);
-
- for (i = 0; i < nids_n; i++) {
- EVP_PKEY_ASN1_METHOD *ameth2 = NULL;
- EVP_PKEY *tmp_pkey = NULL;
- const unsigned char *tmp_blob = blob;
-
- if (!asn1meths(curengine, &ameth2, NULL, nids[i]))
- continue;
- if (ameth2 == NULL
- || ameth2->pkey_flags & ASN1_PKEY_ALIAS)
- continue;
-
- tmp_pkey = d2i_PrivateKey(ameth2->pkey_id, NULL,
- &tmp_blob, len);
- if (tmp_pkey != NULL) {
- if (pkey != NULL)
- EVP_PKEY_free(tmp_pkey);
- else
- pkey = tmp_pkey;
- (*matchcount)++;
- }
- }
- }
- curengine = ENGINE_get_next(curengine);
- }
-#endif
-
- for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
- EVP_PKEY *tmp_pkey = NULL;
- const unsigned char *tmp_blob = blob;
-
- ameth = EVP_PKEY_asn1_get0(i);
- if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
- continue;
-
- tmp_pkey = d2i_PrivateKey(ameth->pkey_id, NULL, &tmp_blob, len);
- if (tmp_pkey != NULL) {
- if (pkey != NULL)
- EVP_PKEY_free(tmp_pkey);
- else
- pkey = tmp_pkey;
- (*matchcount)++;
- }
- }
-
- if (*matchcount > 1) {
- EVP_PKEY_free(pkey);
- pkey = NULL;
- }
- }
- if (pkey == NULL)
- /* No match */
- return NULL;
-
- store_info = OSSL_STORE_INFO_new_PKEY(pkey);
- if (store_info == NULL)
- EVP_PKEY_free(pkey);
-
- return store_info;
-}
-
-static FILE_HANDLER PrivateKey_handler = {
- "PrivateKey",
- try_decode_PrivateKey
-};
-
-/*
- * Public key decoder. Only supports SubjectPublicKeyInfo formatted keys.
- */
-static OSSL_STORE_INFO *try_decode_PUBKEY(const char *pem_name,
- const char *pem_header,
- const unsigned char *blob,
- size_t len, void **pctx,
- int *matchcount,
- const UI_METHOD *ui_method,
- void *ui_data)
-{
- OSSL_STORE_INFO *store_info = NULL;
- EVP_PKEY *pkey = NULL;
-
- if (pem_name != NULL) {
- if (strcmp(pem_name, PEM_STRING_PUBLIC) != 0)
- /* No match */
- return NULL;
- *matchcount = 1;
- }
-
- if ((pkey = d2i_PUBKEY(NULL, &blob, len)) != NULL) {
- *matchcount = 1;
- store_info = OSSL_STORE_INFO_new_PKEY(pkey);
- }
-
- return store_info;
-}
-
-static FILE_HANDLER PUBKEY_handler = {
- "PUBKEY",
- try_decode_PUBKEY
-};
-
-/*
- * Key parameter decoder.
- */
-static OSSL_STORE_INFO *try_decode_params(const char *pem_name,
- const char *pem_header,
- const unsigned char *blob,
- size_t len, void **pctx,
- int *matchcount,
- const UI_METHOD *ui_method,
- void *ui_data)
-{
- OSSL_STORE_INFO *store_info = NULL;
- int slen = 0;
- EVP_PKEY *pkey = NULL;
- const EVP_PKEY_ASN1_METHOD *ameth = NULL;
- int ok = 0;
-
- if (pem_name != NULL) {
- if ((slen = pem_check_suffix(pem_name, "PARAMETERS")) == 0)
- return NULL;
- *matchcount = 1;
- }
-
- if (slen > 0) {
- if ((pkey = EVP_PKEY_new()) == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PARAMS, ERR_R_EVP_LIB);
- return NULL;
- }
-
-
- if (EVP_PKEY_set_type_str(pkey, pem_name, slen)
- && (ameth = EVP_PKEY_get0_asn1(pkey)) != NULL
- && ameth->param_decode != NULL
- && ameth->param_decode(pkey, &blob, len))
- ok = 1;
- } else {
- int i;
- EVP_PKEY *tmp_pkey = NULL;
-
- for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
- const unsigned char *tmp_blob = blob;
-
- if (tmp_pkey == NULL && (tmp_pkey = EVP_PKEY_new()) == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PARAMS, ERR_R_EVP_LIB);
- break;
- }
-
- ameth = EVP_PKEY_asn1_get0(i);
- if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
- continue;
-
- if (EVP_PKEY_set_type(tmp_pkey, ameth->pkey_id)
- && (ameth = EVP_PKEY_get0_asn1(tmp_pkey)) != NULL
- && ameth->param_decode != NULL
- && ameth->param_decode(tmp_pkey, &tmp_blob, len)) {
- if (pkey != NULL)
- EVP_PKEY_free(tmp_pkey);
- else
- pkey = tmp_pkey;
- tmp_pkey = NULL;
- (*matchcount)++;
- }
- }
-
- EVP_PKEY_free(tmp_pkey);
- if (*matchcount == 1) {
- ok = 1;
- }
- }
-
- if (ok)
- store_info = OSSL_STORE_INFO_new_PARAMS(pkey);
- if (store_info == NULL)
- EVP_PKEY_free(pkey);
-
- return store_info;
-}
-
-static FILE_HANDLER params_handler = {
- "params",
- try_decode_params
-};
-
-/*
- * X.509 certificate decoder.
- */
-static OSSL_STORE_INFO *try_decode_X509Certificate(const char *pem_name,
- const char *pem_header,
- const unsigned char *blob,
- size_t len, void **pctx,
- int *matchcount,
- const UI_METHOD *ui_method,
- void *ui_data)
-{
- OSSL_STORE_INFO *store_info = NULL;
- X509 *cert = NULL;
-
- /*
- * In most cases, we can try to interpret the serialized data as a trusted
- * cert (X509 + X509_AUX) and fall back to reading it as a normal cert
- * (just X509), but if the PEM name specifically declares it as a trusted
- * cert, then no fallback should be engaged. |ignore_trusted| tells if
- * the fallback can be used (1) or not (0).
- */
- int ignore_trusted = 1;
-
- if (pem_name != NULL) {
- if (strcmp(pem_name, PEM_STRING_X509_TRUSTED) == 0)
- ignore_trusted = 0;
- else if (strcmp(pem_name, PEM_STRING_X509_OLD) != 0
- && strcmp(pem_name, PEM_STRING_X509) != 0)
- /* No match */
- return NULL;
- *matchcount = 1;
- }
-
- if ((cert = d2i_X509_AUX(NULL, &blob, len)) != NULL
- || (ignore_trusted && (cert = d2i_X509(NULL, &blob, len)) != NULL)) {
- *matchcount = 1;
- store_info = OSSL_STORE_INFO_new_CERT(cert);
- }
-
- if (store_info == NULL)
- X509_free(cert);
-
- return store_info;
-}
-
-static FILE_HANDLER X509Certificate_handler = {
- "X509Certificate",
- try_decode_X509Certificate
-};
-
-/*
- * X.509 CRL decoder.
- */
-static OSSL_STORE_INFO *try_decode_X509CRL(const char *pem_name,
- const char *pem_header,
- const unsigned char *blob,
- size_t len, void **pctx,
- int *matchcount,
- const UI_METHOD *ui_method,
- void *ui_data)
-{
- OSSL_STORE_INFO *store_info = NULL;
- X509_CRL *crl = NULL;
-
- if (pem_name != NULL) {
- if (strcmp(pem_name, PEM_STRING_X509_CRL) != 0)
- /* No match */
- return NULL;
- *matchcount = 1;
- }
-
- if ((crl = d2i_X509_CRL(NULL, &blob, len)) != NULL) {
- *matchcount = 1;
- store_info = OSSL_STORE_INFO_new_CRL(crl);
- }
-
- if (store_info == NULL)
- X509_CRL_free(crl);
-
- return store_info;
-}
-
-static FILE_HANDLER X509CRL_handler = {
- "X509CRL",
- try_decode_X509CRL
-};
-
-/*
- * To finish it all off, we collect all the handlers.
- */
-static const FILE_HANDLER *file_handlers[] = {
- &PKCS12_handler,
- &PKCS8Encrypted_handler,
- &X509Certificate_handler,
- &X509CRL_handler,
- &params_handler,
- &PUBKEY_handler,
- &PrivateKey_handler,
-};
-
-
-/*-
- * The loader itself
- * -----------------
- */
-
-struct ossl_store_loader_ctx_st {
- enum {
- is_raw = 0,
- is_pem,
- is_dir
- } type;
- int errcnt;
-#define FILE_FLAG_SECMEM (1<<0)
- unsigned int flags;
- union {
- struct { /* Used with is_raw and is_pem */
- BIO *file;
-
- /*
- * The following are used when the handler is marked as
- * repeatable
- */
- const FILE_HANDLER *last_handler;
- void *last_handler_ctx;
- } file;
- struct { /* Used with is_dir */
- OPENSSL_DIR_CTX *ctx;
- int end_reached;
- char *uri;
-
- /*
- * When a search expression is given, these are filled in.
- * |search_name| contains the file basename to look for.
- * The string is exactly 8 characters long.
- */
- char search_name[9];
-
- /*
- * The directory reading utility we have combines opening with
- * reading the first name. To make sure we can detect the end
- * at the right time, we read early and cache the name.
- */
- const char *last_entry;
- int last_errno;
- } dir;
- } _;
-
- /* Expected object type. May be unspecified */
- int expected_type;
-};
-
-static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx)
-{
- if (ctx->type == is_dir) {
- OPENSSL_free(ctx->_.dir.uri);
- } else {
- if (ctx->_.file.last_handler != NULL) {
- ctx->_.file.last_handler->destroy_ctx(&ctx->_.file.last_handler_ctx);
- ctx->_.file.last_handler_ctx = NULL;
- ctx->_.file.last_handler = NULL;
- }
- }
- OPENSSL_free(ctx);
-}
-
-static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader,
- const char *uri,
- const UI_METHOD *ui_method,
- void *ui_data)
-{
- OSSL_STORE_LOADER_CTX *ctx = NULL;
- struct stat st;
- struct {
- const char *path;
- unsigned int check_absolute:1;
- } path_data[2];
- size_t path_data_n = 0, i;
- const char *path;
-
- /*
- * First step, just take the URI as is.
- */
- path_data[path_data_n].check_absolute = 0;
- path_data[path_data_n++].path = uri;
-
- /*
- * Second step, if the URI appears to start with the 'file' scheme,
- * extract the path and make that the second path to check.
- * There's a special case if the URI also contains an authority, then
- * the full URI shouldn't be used as a path anywhere.
- */
- if (strncasecmp(uri, "file:", 5) == 0) {
- const char *p = &uri[5];
-
- if (strncmp(&uri[5], "//", 2) == 0) {
- path_data_n--; /* Invalidate using the full URI */
- if (strncasecmp(&uri[7], "localhost/", 10) == 0) {
- p = &uri[16];
- } else if (uri[7] == '/') {
- p = &uri[7];
- } else {
- OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN,
- OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED);
- return NULL;
- }
- }
-
- path_data[path_data_n].check_absolute = 1;
-#ifdef _WIN32
- /* Windows file: URIs with a drive letter start with a / */
- if (p[0] == '/' && p[2] == ':' && p[3] == '/') {
- char c = ossl_tolower(p[1]);
-
- if (c >= 'a' && c <= 'z') {
- p++;
- /* We know it's absolute, so no need to check */
- path_data[path_data_n].check_absolute = 0;
- }
- }
-#endif
- path_data[path_data_n++].path = p;
- }
-
-
- for (i = 0, path = NULL; path == NULL && i < path_data_n; i++) {
- /*
- * If the scheme "file" was an explicit part of the URI, the path must
- * be absolute. So says RFC 8089
- */
- if (path_data[i].check_absolute && path_data[i].path[0] != '/') {
- OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN,
- OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE);
- ERR_add_error_data(1, path_data[i].path);
- return NULL;
- }
-
- if (stat(path_data[i].path, &st) < 0) {
- SYSerr(SYS_F_STAT, errno);
- ERR_add_error_data(1, path_data[i].path);
- } else {
- path = path_data[i].path;
- }
- }
- if (path == NULL) {
- return NULL;
- }
-
- /* Successfully found a working path, clear possible collected errors */
- ERR_clear_error();
-
- ctx = OPENSSL_zalloc(sizeof(*ctx));
- if (ctx == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- if (S_ISDIR(st.st_mode)) {
- /*
- * Try to copy everything, even if we know that some of them must be
- * NULL for the moment. This prevents errors in the future, when more
- * components may be used.
- */
- ctx->_.dir.uri = OPENSSL_strdup(uri);
- ctx->type = is_dir;
-
- if (ctx->_.dir.uri == NULL)
- goto err;
-
- ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx, path);
- ctx->_.dir.last_errno = errno;
- if (ctx->_.dir.last_entry == NULL) {
- if (ctx->_.dir.last_errno != 0) {
- char errbuf[256];
- OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN, ERR_R_SYS_LIB);
- errno = ctx->_.dir.last_errno;
- if (openssl_strerror_r(errno, errbuf, sizeof(errbuf)))
- ERR_add_error_data(1, errbuf);
- goto err;
- }
- ctx->_.dir.end_reached = 1;
- }
- } else {
- BIO *buff = NULL;
- char peekbuf[4096] = { 0, };
-
- if ((buff = BIO_new(BIO_f_buffer())) == NULL
- || (ctx->_.file.file = BIO_new_file(path, "rb")) == NULL) {
- BIO_free_all(buff);
- goto err;
- }
-
- ctx->_.file.file = BIO_push(buff, ctx->_.file.file);
- if (BIO_buffer_peek(ctx->_.file.file, peekbuf, sizeof(peekbuf) - 1) > 0) {
- peekbuf[sizeof(peekbuf) - 1] = '\0';
- if (strstr(peekbuf, "-----BEGIN ") != NULL)
- ctx->type = is_pem;
- }
- }
-
- return ctx;
- err:
- OSSL_STORE_LOADER_CTX_free(ctx);
- return NULL;
-}
-
-static int file_ctrl(OSSL_STORE_LOADER_CTX *ctx, int cmd, va_list args)
-{
- int ret = 1;
-
- switch (cmd) {
- case OSSL_STORE_C_USE_SECMEM:
- {
- int on = *(va_arg(args, int *));
-
- switch (on) {
- case 0:
- ctx->flags &= ~FILE_FLAG_SECMEM;
- break;
- case 1:
- ctx->flags |= FILE_FLAG_SECMEM;
- break;
- default:
- OSSL_STOREerr(OSSL_STORE_F_FILE_CTRL,
- ERR_R_PASSED_INVALID_ARGUMENT);
- ret = 0;
- break;
- }
- }
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-static int file_expect(OSSL_STORE_LOADER_CTX *ctx, int expected)
-{
- ctx->expected_type = expected;
- return 1;
-}
-
-static int file_find(OSSL_STORE_LOADER_CTX *ctx, OSSL_STORE_SEARCH *search)
-{
- /*
- * If ctx == NULL, the library is looking to know if this loader supports
- * the given search type.
- */
-
- if (OSSL_STORE_SEARCH_get_type(search) == OSSL_STORE_SEARCH_BY_NAME) {
- unsigned long hash = 0;
-
- if (ctx == NULL)
- return 1;
-
- if (ctx->type != is_dir) {
- OSSL_STOREerr(OSSL_STORE_F_FILE_FIND,
- OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES);
- return 0;
- }
-
- hash = X509_NAME_hash(OSSL_STORE_SEARCH_get0_name(search));
- BIO_snprintf(ctx->_.dir.search_name, sizeof(ctx->_.dir.search_name),
- "%08lx", hash);
- return 1;
- }
-
- if (ctx != NULL)
- OSSL_STOREerr(OSSL_STORE_F_FILE_FIND,
- OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE);
- return 0;
-}
-
-/* Internal function to decode an already opened PEM file */
-OSSL_STORE_LOADER_CTX *ossl_store_file_attach_pem_bio_int(BIO *bp)
-{
- OSSL_STORE_LOADER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
-
- if (ctx == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_FILE_ATTACH_PEM_BIO_INT,
- ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- ctx->_.file.file = bp;
- ctx->type = is_pem;
-
- return ctx;
-}
-
-static OSSL_STORE_INFO *file_load_try_decode(OSSL_STORE_LOADER_CTX *ctx,
- const char *pem_name,
- const char *pem_header,
- unsigned char *data, size_t len,
- const UI_METHOD *ui_method,
- void *ui_data, int *matchcount)
-{
- OSSL_STORE_INFO *result = NULL;
- BUF_MEM *new_mem = NULL;
- char *new_pem_name = NULL;
- int t = 0;
-
- again:
- {
- size_t i = 0;
- void *handler_ctx = NULL;
- const FILE_HANDLER **matching_handlers =
- OPENSSL_zalloc(sizeof(*matching_handlers)
- * OSSL_NELEM(file_handlers));
-
- if (matching_handlers == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD_TRY_DECODE,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- *matchcount = 0;
- for (i = 0; i < OSSL_NELEM(file_handlers); i++) {
- const FILE_HANDLER *handler = file_handlers[i];
- int try_matchcount = 0;
- void *tmp_handler_ctx = NULL;
- OSSL_STORE_INFO *tmp_result =
- handler->try_decode(pem_name, pem_header, data, len,
- &tmp_handler_ctx, &try_matchcount,
- ui_method, ui_data);
-
- if (try_matchcount > 0) {
-
- matching_handlers[*matchcount] = handler;
-
- if (handler_ctx)
- handler->destroy_ctx(&handler_ctx);
- handler_ctx = tmp_handler_ctx;
-
- if ((*matchcount += try_matchcount) > 1) {
- /* more than one match => ambiguous, kill any result */
- OSSL_STORE_INFO_free(result);
- OSSL_STORE_INFO_free(tmp_result);
- if (handler->destroy_ctx != NULL)
- handler->destroy_ctx(&handler_ctx);
- handler_ctx = NULL;
- tmp_result = NULL;
- result = NULL;
- }
- if (result == NULL)
- result = tmp_result;
- }
- }
-
- if (*matchcount == 1 && matching_handlers[0]->repeatable) {
- ctx->_.file.last_handler = matching_handlers[0];
- ctx->_.file.last_handler_ctx = handler_ctx;
- }
-
- OPENSSL_free(matching_handlers);
- }
-
- err:
- OPENSSL_free(new_pem_name);
- BUF_MEM_free(new_mem);
-
- if (result != NULL
- && (t = OSSL_STORE_INFO_get_type(result)) == OSSL_STORE_INFO_EMBEDDED) {
- pem_name = new_pem_name =
- ossl_store_info_get0_EMBEDDED_pem_name(result);
- new_mem = ossl_store_info_get0_EMBEDDED_buffer(result);
- data = (unsigned char *)new_mem->data;
- len = new_mem->length;
- OPENSSL_free(result);
- result = NULL;
- goto again;
- }
-
- if (result != NULL)
- ERR_clear_error();
-
- return result;
-}
-
-static OSSL_STORE_INFO *file_load_try_repeat(OSSL_STORE_LOADER_CTX *ctx,
- const UI_METHOD *ui_method,
- void *ui_data)
-{
- OSSL_STORE_INFO *result = NULL;
- int try_matchcount = 0;
-
- if (ctx->_.file.last_handler != NULL) {
- result =
- ctx->_.file.last_handler->try_decode(NULL, NULL, NULL, 0,
- &ctx->_.file.last_handler_ctx,
- &try_matchcount,
- ui_method, ui_data);
-
- if (result == NULL) {
- ctx->_.file.last_handler->destroy_ctx(&ctx->_.file.last_handler_ctx);
- ctx->_.file.last_handler_ctx = NULL;
- ctx->_.file.last_handler = NULL;
- }
- }
- return result;
-}
-
-static void pem_free_flag(void *pem_data, int secure, size_t num)
-{
- if (secure)
- OPENSSL_secure_clear_free(pem_data, num);
- else
- OPENSSL_free(pem_data);
-}
-static int file_read_pem(BIO *bp, char **pem_name, char **pem_header,
- unsigned char **data, long *len,
- const UI_METHOD *ui_method,
- void *ui_data, int secure)
-{
- int i = secure
- ? PEM_read_bio_ex(bp, pem_name, pem_header, data, len,
- PEM_FLAG_SECURE | PEM_FLAG_EAY_COMPATIBLE)
- : PEM_read_bio(bp, pem_name, pem_header, data, len);
-
- if (i <= 0)
- return 0;
-
- /*
- * 10 is the number of characters in "Proc-Type:", which
- * PEM_get_EVP_CIPHER_INFO() requires to be present.
- * If the PEM header has less characters than that, it's
- * not worth spending cycles on it.
- */
- if (strlen(*pem_header) > 10) {
- EVP_CIPHER_INFO cipher;
- struct pem_pass_data pass_data;
-
- if (!PEM_get_EVP_CIPHER_INFO(*pem_header, &cipher)
- || !file_fill_pem_pass_data(&pass_data, "PEM", ui_method, ui_data)
- || !PEM_do_header(&cipher, *data, len, file_get_pem_pass,
- &pass_data)) {
- return 0;
- }
- }
- return 1;
-}
-
-static int file_read_asn1(BIO *bp, unsigned char **data, long *len)
-{
- BUF_MEM *mem = NULL;
-
- if (asn1_d2i_read_bio(bp, &mem) < 0)
- return 0;
-
- *data = (unsigned char *)mem->data;
- *len = (long)mem->length;
- OPENSSL_free(mem);
-
- return 1;
-}
-
-static int ends_with_dirsep(const char *uri)
-{
- if (*uri != '\0')
- uri += strlen(uri) - 1;
-#if defined __VMS
- if (*uri == ']' || *uri == '>' || *uri == ':')
- return 1;
-#elif defined _WIN32
- if (*uri == '\\')
- return 1;
-#endif
- return *uri == '/';
-}
-
-static int file_name_to_uri(OSSL_STORE_LOADER_CTX *ctx, const char *name,
- char **data)
-{
- assert(name != NULL);
- assert(data != NULL);
- {
- const char *pathsep = ends_with_dirsep(ctx->_.dir.uri) ? "" : "/";
- long calculated_length = strlen(ctx->_.dir.uri) + strlen(pathsep)
- + strlen(name) + 1 /* \0 */;
-
- *data = OPENSSL_zalloc(calculated_length);
- if (*data == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_FILE_NAME_TO_URI, ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- OPENSSL_strlcat(*data, ctx->_.dir.uri, calculated_length);
- OPENSSL_strlcat(*data, pathsep, calculated_length);
- OPENSSL_strlcat(*data, name, calculated_length);
- }
- return 1;
-}
-
-static int file_name_check(OSSL_STORE_LOADER_CTX *ctx, const char *name)
-{
- const char *p = NULL;
-
- /* If there are no search criteria, all names are accepted */
- if (ctx->_.dir.search_name[0] == '\0')
- return 1;
-
- /* If the expected type isn't supported, no name is accepted */
- if (ctx->expected_type != 0
- && ctx->expected_type != OSSL_STORE_INFO_CERT
- && ctx->expected_type != OSSL_STORE_INFO_CRL)
- return 0;
-
- /*
- * First, check the basename
- */
- if (strncasecmp(name, ctx->_.dir.search_name,
- sizeof(ctx->_.dir.search_name) - 1) != 0
- || name[sizeof(ctx->_.dir.search_name) - 1] != '.')
- return 0;
- p = &name[sizeof(ctx->_.dir.search_name)];
-
- /*
- * Then, if the expected type is a CRL, check that the extension starts
- * with 'r'
- */
- if (*p == 'r') {
- p++;
- if (ctx->expected_type != 0
- && ctx->expected_type != OSSL_STORE_INFO_CRL)
- return 0;
- } else if (ctx->expected_type == OSSL_STORE_INFO_CRL) {
- return 0;
- }
-
- /*
- * Last, check that the rest of the extension is a decimal number, at
- * least one digit long.
- */
- if (!ossl_isdigit(*p))
- return 0;
- while (ossl_isdigit(*p))
- p++;
-
-# ifdef __VMS
- /*
- * One extra step here, check for a possible generation number.
- */
- if (*p == ';')
- for (p++; *p != '\0'; p++)
- if (!ossl_isdigit(*p))
- break;
-# endif
-
- /*
- * If we've reached the end of the string at this point, we've successfully
- * found a fitting file name.
- */
- return *p == '\0';
-}
-
-static int file_eof(OSSL_STORE_LOADER_CTX *ctx);
-static int file_error(OSSL_STORE_LOADER_CTX *ctx);
-static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
- const UI_METHOD *ui_method, void *ui_data)
-{
- OSSL_STORE_INFO *result = NULL;
-
- ctx->errcnt = 0;
- ERR_clear_error();
-
- if (ctx->type == is_dir) {
- do {
- char *newname = NULL;
-
- if (ctx->_.dir.last_entry == NULL) {
- if (!ctx->_.dir.end_reached) {
- char errbuf[256];
- assert(ctx->_.dir.last_errno != 0);
- OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD, ERR_R_SYS_LIB);
- errno = ctx->_.dir.last_errno;
- ctx->errcnt++;
- if (openssl_strerror_r(errno, errbuf, sizeof(errbuf)))
- ERR_add_error_data(1, errbuf);
- }
- return NULL;
- }
-
- if (ctx->_.dir.last_entry[0] != '.'
- && file_name_check(ctx, ctx->_.dir.last_entry)
- && !file_name_to_uri(ctx, ctx->_.dir.last_entry, &newname))
- return NULL;
-
- /*
- * On the first call (with a NULL context), OPENSSL_DIR_read()
- * cares about the second argument. On the following calls, it
- * only cares that it isn't NULL. Therefore, we can safely give
- * it our URI here.
- */
- ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx,
- ctx->_.dir.uri);
- ctx->_.dir.last_errno = errno;
- if (ctx->_.dir.last_entry == NULL && ctx->_.dir.last_errno == 0)
- ctx->_.dir.end_reached = 1;
-
- if (newname != NULL
- && (result = OSSL_STORE_INFO_new_NAME(newname)) == NULL) {
- OPENSSL_free(newname);
- OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD, ERR_R_OSSL_STORE_LIB);
- return NULL;
- }
- } while (result == NULL && !file_eof(ctx));
- } else {
- int matchcount = -1;
-
- again:
- result = file_load_try_repeat(ctx, ui_method, ui_data);
- if (result != NULL)
- return result;
-
- if (file_eof(ctx))
- return NULL;
-
- do {
- char *pem_name = NULL; /* PEM record name */
- char *pem_header = NULL; /* PEM record header */
- unsigned char *data = NULL; /* DER encoded data */
- long len = 0; /* DER encoded data length */
-
- matchcount = -1;
- if (ctx->type == is_pem) {
- if (!file_read_pem(ctx->_.file.file, &pem_name, &pem_header,
- &data, &len, ui_method, ui_data,
- (ctx->flags & FILE_FLAG_SECMEM) != 0)) {
- ctx->errcnt++;
- goto endloop;
- }
- } else {
- if (!file_read_asn1(ctx->_.file.file, &data, &len)) {
- ctx->errcnt++;
- goto endloop;
- }
- }
-
- result = file_load_try_decode(ctx, pem_name, pem_header, data, len,
- ui_method, ui_data, &matchcount);
-
- if (result != NULL)
- goto endloop;
-
- /*
- * If a PEM name matches more than one handler, the handlers are
- * badly coded.
- */
- if (!ossl_assert(pem_name == NULL || matchcount <= 1)) {
- ctx->errcnt++;
- goto endloop;
- }
-
- if (matchcount > 1) {
- OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD,
- OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE);
- } else if (matchcount == 1) {
- /*
- * If there are other errors on the stack, they already show
- * what the problem is.
- */
- if (ERR_peek_error() == 0) {
- OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD,
- OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE);
- if (pem_name != NULL)
- ERR_add_error_data(3, "PEM type is '", pem_name, "'");
- }
- }
- if (matchcount > 0)
- ctx->errcnt++;
-
- endloop:
- pem_free_flag(pem_name, (ctx->flags & FILE_FLAG_SECMEM) != 0, 0);
- pem_free_flag(pem_header, (ctx->flags & FILE_FLAG_SECMEM) != 0, 0);
- pem_free_flag(data, (ctx->flags & FILE_FLAG_SECMEM) != 0, len);
- } while (matchcount == 0 && !file_eof(ctx) && !file_error(ctx));
-
- /* We bail out on ambiguity */
- if (matchcount > 1)
- return NULL;
-
- if (result != NULL
- && ctx->expected_type != 0
- && ctx->expected_type != OSSL_STORE_INFO_get_type(result)) {
- OSSL_STORE_INFO_free(result);
- goto again;
- }
- }
-
- return result;
-}
-
-static int file_error(OSSL_STORE_LOADER_CTX *ctx)
-{
- return ctx->errcnt > 0;
-}
-
-static int file_eof(OSSL_STORE_LOADER_CTX *ctx)
-{
- if (ctx->type == is_dir)
- return ctx->_.dir.end_reached;
-
- if (ctx->_.file.last_handler != NULL
- && !ctx->_.file.last_handler->eof(ctx->_.file.last_handler_ctx))
- return 0;
- return BIO_eof(ctx->_.file.file);
-}
-
-static int file_close(OSSL_STORE_LOADER_CTX *ctx)
-{
- if (ctx->type == is_dir) {
- OPENSSL_DIR_end(&ctx->_.dir.ctx);
- } else {
- BIO_free_all(ctx->_.file.file);
- }
- OSSL_STORE_LOADER_CTX_free(ctx);
- return 1;
-}
-
-int ossl_store_file_detach_pem_bio_int(OSSL_STORE_LOADER_CTX *ctx)
-{
- OSSL_STORE_LOADER_CTX_free(ctx);
- return 1;
-}
-
-static OSSL_STORE_LOADER file_loader =
- {
- "file",
- NULL,
- file_open,
- file_ctrl,
- file_expect,
- file_find,
- file_load,
- file_eof,
- file_error,
- file_close
- };
-
-static void store_file_loader_deinit(void)
-{
- ossl_store_unregister_loader_int(file_loader.scheme);
-}
-
-int ossl_store_file_loader_init(void)
-{
- int ret = ossl_store_register_loader_int(&file_loader);
-
- OPENSSL_atexit(store_file_loader_deinit);
- return ret;
-}
diff --git a/crypto/store/store_err.c b/crypto/store/store_err.c
index 5a8a8404dd9b..ec62b358c589 100644
--- a/crypto/store/store_err.c
+++ b/crypto/store/store_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,84 +10,10 @@
#include <openssl/err.h>
#include <openssl/storeerr.h>
+#include "crypto/storeerr.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA OSSL_STORE_str_functs[] = {
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_CTRL, 0), "file_ctrl"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_FIND, 0), "file_find"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_GET_PASS, 0),
- "file_get_pass"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_LOAD, 0), "file_load"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_LOAD_TRY_DECODE, 0),
- "file_load_try_decode"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_NAME_TO_URI, 0),
- "file_name_to_uri"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_OPEN, 0), "file_open"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_ATTACH_PEM_BIO, 0),
- "ossl_store_attach_pem_bio"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_EXPECT, 0),
- "OSSL_STORE_expect"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_FILE_ATTACH_PEM_BIO_INT, 0),
- "ossl_store_file_attach_pem_bio_int"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_FIND, 0),
- "OSSL_STORE_find"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT, 0),
- "ossl_store_get0_loader_int"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT, 0),
- "OSSL_STORE_INFO_get1_CERT"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL, 0),
- "OSSL_STORE_INFO_get1_CRL"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME, 0),
- "OSSL_STORE_INFO_get1_NAME"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION, 0),
- "OSSL_STORE_INFO_get1_NAME_description"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS, 0),
- "OSSL_STORE_INFO_get1_PARAMS"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY, 0),
- "OSSL_STORE_INFO_get1_PKEY"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT, 0),
- "OSSL_STORE_INFO_new_CERT"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL, 0),
- "OSSL_STORE_INFO_new_CRL"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED, 0),
- "ossl_store_info_new_EMBEDDED"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME, 0),
- "OSSL_STORE_INFO_new_NAME"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS, 0),
- "OSSL_STORE_INFO_new_PARAMS"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY, 0),
- "OSSL_STORE_INFO_new_PKEY"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION, 0),
- "OSSL_STORE_INFO_set0_NAME_description"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INIT_ONCE, 0),
- "ossl_store_init_once"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_LOADER_NEW, 0),
- "OSSL_STORE_LOADER_new"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_OPEN, 0),
- "OSSL_STORE_open"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_OPEN_INT, 0), ""},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT, 0),
- "ossl_store_register_loader_int"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ALIAS, 0),
- "OSSL_STORE_SEARCH_by_alias"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ISSUER_SERIAL, 0),
- "OSSL_STORE_SEARCH_by_issuer_serial"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT, 0),
- "OSSL_STORE_SEARCH_by_key_fingerprint"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_SEARCH_BY_NAME, 0),
- "OSSL_STORE_SEARCH_by_name"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT, 0),
- "ossl_store_unregister_loader_int"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_TRY_DECODE_PARAMS, 0),
- "try_decode_params"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_TRY_DECODE_PKCS12, 0),
- "try_decode_PKCS12"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED, 0),
- "try_decode_PKCS8Encrypted"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = {
{ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE),
"ambiguous content type"},
@@ -107,10 +33,15 @@ static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = {
{ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_CERTIFICATE),
"not a certificate"},
{ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_CRL), "not a crl"},
- {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_KEY), "not a key"},
{ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_NAME), "not a name"},
+ {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_PRIVATE_KEY),
+ "not a private key"},
+ {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_PUBLIC_KEY),
+ "not a public key"},
{ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_PARAMETERS),
"not parameters"},
+ {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NO_LOADERS_FOUND),
+ "no loaders found"},
{ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR),
"passphrase callback error"},
{ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE),
@@ -134,13 +65,11 @@ static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = {
#endif
-int ERR_load_OSSL_STORE_strings(void)
+int ossl_err_load_OSSL_STORE_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(OSSL_STORE_str_functs[0].error) == NULL) {
- ERR_load_strings_const(OSSL_STORE_str_functs);
+ if (ERR_reason_error_string(OSSL_STORE_str_reasons[0].error) == NULL)
ERR_load_strings_const(OSSL_STORE_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/store/store_init.c b/crypto/store/store_init.c
index 0103c8db8aaf..9df8ef12a241 100644
--- a/crypto/store/store_init.c
+++ b/crypto/store/store_init.c
@@ -1,32 +1,15 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/err.h>
#include "crypto/store.h"
#include "store_local.h"
-static CRYPTO_ONCE store_init = CRYPTO_ONCE_STATIC_INIT;
-DEFINE_RUN_ONCE_STATIC(do_store_init)
-{
- return OPENSSL_init_crypto(0, NULL)
- && ossl_store_file_loader_init();
-}
-
-int ossl_store_init_once(void)
-{
- if (!RUN_ONCE(&store_init, do_store_init)) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INIT_ONCE, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- return 1;
-}
-
void ossl_store_cleanup_int(void)
{
ossl_store_destroy_loaders_int();
diff --git a/crypto/store/store_lib.c b/crypto/store/store_lib.c
index fb71f84725b1..5ff927862916 100644
--- a/crypto/store/store_lib.c
+++ b/crypto/store/store_lib.c
@@ -1,48 +1,78 @@
/*
- * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include "e_os.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+/* We need to use some STORE deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include "e_os.h"
#include <openssl/crypto.h>
#include <openssl/err.h>
+#include <openssl/trace.h>
+#include <openssl/core_names.h>
+#include <openssl/provider.h>
+#include <openssl/param_build.h>
#include <openssl/store.h>
#include "internal/thread_once.h"
+#include "internal/cryptlib.h"
+#include "internal/provider.h"
+#include "internal/bio.h"
#include "crypto/store.h"
#include "store_local.h"
-struct ossl_store_ctx_st {
- const OSSL_STORE_LOADER *loader;
- OSSL_STORE_LOADER_CTX *loader_ctx;
- const UI_METHOD *ui_method;
- void *ui_data;
- OSSL_STORE_post_process_info_fn post_process;
- void *post_process_data;
- int expected_type;
-
- /* 0 before the first STORE_load(), 1 otherwise */
- int loading;
-};
-
-OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
- void *ui_data,
- OSSL_STORE_post_process_info_fn post_process,
- void *post_process_data)
+static int ossl_store_close_it(OSSL_STORE_CTX *ctx);
+
+static int loader_set_params(OSSL_STORE_LOADER *loader,
+ OSSL_STORE_LOADER_CTX *loader_ctx,
+ const OSSL_PARAM params[], const char *propq)
+{
+ if (params != NULL) {
+ if (!loader->p_set_ctx_params(loader_ctx, params))
+ return 0;
+ }
+
+ if (propq != NULL) {
+ OSSL_PARAM propp[2];
+
+ if (OSSL_PARAM_locate_const(params,
+ OSSL_STORE_PARAM_PROPERTIES) != NULL)
+ /* use the propq from params */
+ return 1;
+
+ propp[0] = OSSL_PARAM_construct_utf8_string(OSSL_STORE_PARAM_PROPERTIES,
+ (char *)propq, 0);
+ propp[1] = OSSL_PARAM_construct_end();
+
+ if (!loader->p_set_ctx_params(loader_ctx, propp))
+ return 0;
+ }
+ return 1;
+}
+
+OSSL_STORE_CTX *
+OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq,
+ const UI_METHOD *ui_method, void *ui_data,
+ const OSSL_PARAM params[],
+ OSSL_STORE_post_process_info_fn post_process,
+ void *post_process_data)
{
const OSSL_STORE_LOADER *loader = NULL;
+ OSSL_STORE_LOADER *fetched_loader = NULL;
OSSL_STORE_LOADER_CTX *loader_ctx = NULL;
OSSL_STORE_CTX *ctx = NULL;
- char scheme_copy[256], *p, *schemes[2];
+ char *propq_copy = NULL;
+ int no_loader_found = 1;
+ char scheme_copy[256], *p, *schemes[2], *scheme = NULL;
size_t schemes_n = 0;
size_t i;
@@ -63,7 +93,7 @@ OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
OPENSSL_strlcpy(scheme_copy, uri, sizeof(scheme_copy));
if ((p = strchr(scheme_copy, ':')) != NULL) {
*p++ = '\0';
- if (strcasecmp(scheme_copy, "file") != 0) {
+ if (OPENSSL_strcasecmp(scheme_copy, "file") != 0) {
if (strncmp(p, "//", 2) == 0)
schemes_n--; /* Invalidate the file scheme */
schemes[schemes_n++] = scheme_copy;
@@ -72,23 +102,83 @@ OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
ERR_set_mark();
- /* Try each scheme until we find one that could open the URI */
+ /*
+ * Try each scheme until we find one that could open the URI.
+ *
+ * For each scheme, we look for the engine implementation first, and
+ * failing that, we then try to fetch a provided implementation.
+ * This is consistent with how we handle legacy / engine implementations
+ * elsewhere.
+ */
for (i = 0; loader_ctx == NULL && i < schemes_n; i++) {
- if ((loader = ossl_store_get0_loader_int(schemes[i])) != NULL)
- loader_ctx = loader->open(loader, uri, ui_method, ui_data);
+ scheme = schemes[i];
+ OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if ((loader = ossl_store_get0_loader_int(scheme)) != NULL) {
+ no_loader_found = 0;
+ if (loader->open_ex != NULL)
+ loader_ctx = loader->open_ex(loader, uri, libctx, propq,
+ ui_method, ui_data);
+ else
+ loader_ctx = loader->open(loader, uri, ui_method, ui_data);
+ }
+#endif
+ if (loader == NULL
+ && (fetched_loader =
+ OSSL_STORE_LOADER_fetch(libctx, scheme, propq)) != NULL) {
+ const OSSL_PROVIDER *provider =
+ OSSL_STORE_LOADER_get0_provider(fetched_loader);
+ void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider);
+
+ no_loader_found = 0;
+ loader_ctx = fetched_loader->p_open(provctx, uri);
+ if (loader_ctx == NULL) {
+ OSSL_STORE_LOADER_free(fetched_loader);
+ fetched_loader = NULL;
+ } else if(!loader_set_params(fetched_loader, loader_ctx,
+ params, propq)) {
+ (void)fetched_loader->p_close(loader_ctx);
+ OSSL_STORE_LOADER_free(fetched_loader);
+ fetched_loader = NULL;
+ }
+ loader = fetched_loader;
+ }
}
+
+ if (no_loader_found)
+ /*
+ * It's assumed that ossl_store_get0_loader_int() and
+ * OSSL_STORE_LOADER_fetch() report their own errors
+ */
+ goto err;
+
+ OSSL_TRACE1(STORE, "Found loader for scheme %s\n", scheme);
+
if (loader_ctx == NULL)
+ /*
+ * It's assumed that the loader's open() method reports its own
+ * errors
+ */
goto err;
- if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_OPEN, ERR_R_MALLOC_FAILURE);
+ OSSL_TRACE2(STORE, "Opened %s => %p\n", uri, (void *)loader_ctx);
+
+ if ((propq != NULL && (propq_copy = OPENSSL_strdup(propq)) == NULL)
+ || (ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
goto err;
}
+ if (ui_method != NULL
+ && (!ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data)
+ || !ossl_pw_enable_passphrase_caching(&ctx->pwdata))) {
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB);
+ goto err;
+ }
+ ctx->properties = propq_copy;
+ ctx->fetched_loader = fetched_loader;
ctx->loader = loader;
ctx->loader_ctx = loader_ctx;
- ctx->ui_method = ui_method;
- ctx->ui_data = ui_data;
ctx->post_process = post_process;
ctx->post_process_data = post_process_data;
@@ -105,15 +195,38 @@ OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
ERR_clear_last_mark();
if (loader_ctx != NULL) {
/*
+ * Temporary structure so OSSL_STORE_close() can work even when
+ * |ctx| couldn't be allocated properly
+ */
+ OSSL_STORE_CTX tmpctx = { NULL, };
+
+ tmpctx.fetched_loader = fetched_loader;
+ tmpctx.loader = loader;
+ tmpctx.loader_ctx = loader_ctx;
+
+ /*
* We ignore a returned error because we will return NULL anyway in
* this case, so if something goes wrong when closing, that'll simply
* just add another entry on the error stack.
*/
- (void)loader->close(loader_ctx);
+ (void)ossl_store_close_it(&tmpctx);
}
+ OSSL_STORE_LOADER_free(fetched_loader);
+ OPENSSL_free(propq_copy);
+ OPENSSL_free(ctx);
return NULL;
}
+OSSL_STORE_CTX *OSSL_STORE_open(const char *uri,
+ const UI_METHOD *ui_method, void *ui_data,
+ OSSL_STORE_post_process_info_fn post_process,
+ void *post_process_data)
+{
+ return OSSL_STORE_open_ex(uri, NULL, NULL, ui_method, ui_data, NULL,
+ post_process, post_process_data);
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ...)
{
va_list args;
@@ -128,39 +241,161 @@ int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ...)
int OSSL_STORE_vctrl(OSSL_STORE_CTX *ctx, int cmd, va_list args)
{
- if (ctx->loader->ctrl != NULL)
+ if (ctx->fetched_loader != NULL) {
+ if (ctx->fetched_loader->p_set_ctx_params != NULL) {
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ switch (cmd) {
+ case OSSL_STORE_C_USE_SECMEM:
+ {
+ int on = *(va_arg(args, int *));
+
+ params[0] = OSSL_PARAM_construct_int("use_secmem", &on);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return ctx->fetched_loader->p_set_ctx_params(ctx->loader_ctx,
+ params);
+ }
+ } else if (ctx->loader->ctrl != NULL) {
return ctx->loader->ctrl(ctx->loader_ctx, cmd, args);
- return 0;
+ }
+
+ /*
+ * If the fetched loader doesn't have a set_ctx_params or a ctrl, it's as
+ * if there was one that ignored our params, which usually returns 1.
+ */
+ return 1;
}
+#endif
int OSSL_STORE_expect(OSSL_STORE_CTX *ctx, int expected_type)
{
+ int ret = 1;
+
+ if (ctx == NULL
+ || expected_type < 0 || expected_type > OSSL_STORE_INFO_CRL) {
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
if (ctx->loading) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_EXPECT,
- OSSL_STORE_R_LOADING_STARTED);
+ ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADING_STARTED);
return 0;
}
ctx->expected_type = expected_type;
- if (ctx->loader->expect != NULL)
- return ctx->loader->expect(ctx->loader_ctx, expected_type);
- return 1;
+ if (ctx->fetched_loader != NULL
+ && ctx->fetched_loader->p_set_ctx_params != NULL) {
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] =
+ OSSL_PARAM_construct_int(OSSL_STORE_PARAM_EXPECT, &expected_type);
+ ret = ctx->fetched_loader->p_set_ctx_params(ctx->loader_ctx, params);
+ }
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (ctx->fetched_loader == NULL
+ && ctx->loader->expect != NULL) {
+ ret = ctx->loader->expect(ctx->loader_ctx, expected_type);
+ }
+#endif
+ return ret;
}
-int OSSL_STORE_find(OSSL_STORE_CTX *ctx, OSSL_STORE_SEARCH *search)
+int OSSL_STORE_find(OSSL_STORE_CTX *ctx, const OSSL_STORE_SEARCH *search)
{
+ int ret = 1;
+
if (ctx->loading) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_FIND,
- OSSL_STORE_R_LOADING_STARTED);
+ ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADING_STARTED);
return 0;
}
- if (ctx->loader->find == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_FIND,
- OSSL_STORE_R_UNSUPPORTED_OPERATION);
+ if (search == NULL) {
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
- return ctx->loader->find(ctx->loader_ctx, search);
+ if (ctx->fetched_loader != NULL) {
+ OSSL_PARAM_BLD *bld;
+ OSSL_PARAM *params;
+ /* OSSL_STORE_SEARCH_BY_NAME, OSSL_STORE_SEARCH_BY_ISSUER_SERIAL*/
+ void *name_der = NULL;
+ int name_der_sz;
+ /* OSSL_STORE_SEARCH_BY_ISSUER_SERIAL */
+ BIGNUM *number = NULL;
+
+ if (ctx->fetched_loader->p_set_ctx_params == NULL) {
+ ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNSUPPORTED_OPERATION);
+ return 0;
+ }
+
+ if ((bld = OSSL_PARAM_BLD_new()) == NULL) {
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ ret = 0; /* Assume the worst */
+
+ switch (search->search_type) {
+ case OSSL_STORE_SEARCH_BY_NAME:
+ if ((name_der_sz = i2d_X509_NAME(search->name,
+ (unsigned char **)&name_der)) > 0
+ && OSSL_PARAM_BLD_push_octet_string(bld,
+ OSSL_STORE_PARAM_SUBJECT,
+ name_der, name_der_sz))
+ ret = 1;
+ break;
+ case OSSL_STORE_SEARCH_BY_ISSUER_SERIAL:
+ if ((name_der_sz = i2d_X509_NAME(search->name,
+ (unsigned char **)&name_der)) > 0
+ && (number = ASN1_INTEGER_to_BN(search->serial, NULL)) != NULL
+ && OSSL_PARAM_BLD_push_octet_string(bld,
+ OSSL_STORE_PARAM_ISSUER,
+ name_der, name_der_sz)
+ && OSSL_PARAM_BLD_push_BN(bld, OSSL_STORE_PARAM_SERIAL,
+ number))
+ ret = 1;
+ break;
+ case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:
+ if (OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_STORE_PARAM_DIGEST,
+ EVP_MD_get0_name(search->digest),
+ 0)
+ && OSSL_PARAM_BLD_push_octet_string(bld,
+ OSSL_STORE_PARAM_FINGERPRINT,
+ search->string,
+ search->stringlength))
+ ret = 1;
+ break;
+ case OSSL_STORE_SEARCH_BY_ALIAS:
+ if (OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_STORE_PARAM_ALIAS,
+ (char *)search->string,
+ search->stringlength))
+ ret = 1;
+ break;
+ }
+ if (ret) {
+ params = OSSL_PARAM_BLD_to_param(bld);
+ ret = ctx->fetched_loader->p_set_ctx_params(ctx->loader_ctx,
+ params);
+ OSSL_PARAM_free(params);
+ }
+ OSSL_PARAM_BLD_free(bld);
+ OPENSSL_free(name_der);
+ BN_free(number);
+ } else {
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ /* legacy loader section */
+ if (ctx->loader->find == NULL) {
+ ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNSUPPORTED_OPERATION);
+ return 0;
+ }
+ ret = ctx->loader->find(ctx->loader_ctx, search);
+#endif
+ }
+
+ return ret;
}
OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx)
@@ -172,7 +407,42 @@ OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx)
if (OSSL_STORE_eof(ctx))
return NULL;
- v = ctx->loader->load(ctx->loader_ctx, ctx->ui_method, ctx->ui_data);
+ if (ctx->loader != NULL)
+ OSSL_TRACE(STORE, "Loading next object\n");
+
+ if (ctx->cached_info != NULL
+ && sk_OSSL_STORE_INFO_num(ctx->cached_info) == 0) {
+ sk_OSSL_STORE_INFO_free(ctx->cached_info);
+ ctx->cached_info = NULL;
+ }
+
+ if (ctx->cached_info != NULL) {
+ v = sk_OSSL_STORE_INFO_shift(ctx->cached_info);
+ } else {
+ if (ctx->fetched_loader != NULL) {
+ struct ossl_load_result_data_st load_data;
+
+ load_data.v = NULL;
+ load_data.ctx = ctx;
+
+ if (!ctx->fetched_loader->p_load(ctx->loader_ctx,
+ ossl_store_handle_load_result,
+ &load_data,
+ ossl_pw_passphrase_callback_dec,
+ &ctx->pwdata)) {
+ if (!OSSL_STORE_eof(ctx))
+ ctx->error_flag = 1;
+ return NULL;
+ }
+ v = load_data.v;
+ }
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (ctx->fetched_loader == NULL)
+ v = ctx->loader->load(ctx->loader_ctx,
+ ctx->pwdata._.ui_method.ui_method,
+ ctx->pwdata._.ui_method.ui_method_data);
+#endif
+ }
if (ctx->post_process != NULL && v != NULL) {
v = ctx->post_process(v, ctx->post_process_data);
@@ -185,17 +455,13 @@ OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx)
goto again;
}
+ /* Clear any internally cached passphrase */
+ (void)ossl_pw_clear_passphrase_cache(&ctx->pwdata);
+
if (v != NULL && ctx->expected_type != 0) {
int returned_type = OSSL_STORE_INFO_get_type(v);
if (returned_type != OSSL_STORE_INFO_NAME && returned_type != 0) {
- /*
- * Soft assert here so those who want to harsly weed out faulty
- * loaders can do so using a debugging version of libcrypto.
- */
- if (ctx->loader->expect != NULL)
- assert(ctx->expected_type == returned_type);
-
if (ctx->expected_type != returned_type) {
OSSL_STORE_INFO_free(v);
goto again;
@@ -203,29 +469,67 @@ OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx)
}
}
+ if (v != NULL)
+ OSSL_TRACE1(STORE, "Got a %s\n",
+ OSSL_STORE_INFO_type_string(OSSL_STORE_INFO_get_type(v)));
+
return v;
}
int OSSL_STORE_error(OSSL_STORE_CTX *ctx)
{
- return ctx->loader->error(ctx->loader_ctx);
+ int ret = 1;
+
+ if (ctx->fetched_loader != NULL)
+ ret = ctx->error_flag;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (ctx->fetched_loader == NULL)
+ ret = ctx->loader->error(ctx->loader_ctx);
+#endif
+ return ret;
}
int OSSL_STORE_eof(OSSL_STORE_CTX *ctx)
{
- return ctx->loader->eof(ctx->loader_ctx);
+ int ret = 1;
+
+ if (ctx->fetched_loader != NULL)
+ ret = ctx->loader->p_eof(ctx->loader_ctx);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (ctx->fetched_loader == NULL)
+ ret = ctx->loader->eof(ctx->loader_ctx);
+#endif
+ return ret != 0;
}
-int OSSL_STORE_close(OSSL_STORE_CTX *ctx)
+static int ossl_store_close_it(OSSL_STORE_CTX *ctx)
{
- int loader_ret;
+ int ret = 0;
if (ctx == NULL)
return 1;
- loader_ret = ctx->loader->close(ctx->loader_ctx);
+ OSSL_TRACE1(STORE, "Closing %p\n", (void *)ctx->loader_ctx);
+
+ if (ctx->fetched_loader != NULL)
+ ret = ctx->loader->p_close(ctx->loader_ctx);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (ctx->fetched_loader == NULL)
+ ret = ctx->loader->closefn(ctx->loader_ctx);
+#endif
+
+ sk_OSSL_STORE_INFO_pop_free(ctx->cached_info, OSSL_STORE_INFO_free);
+ OSSL_STORE_LOADER_free(ctx->fetched_loader);
+ OPENSSL_free(ctx->properties);
+ ossl_pw_clear_passphrase_data(&ctx->pwdata);
+ return ret;
+}
+
+int OSSL_STORE_close(OSSL_STORE_CTX *ctx)
+{
+ int ret = ossl_store_close_it(ctx);
OPENSSL_free(ctx);
- return loader_ret;
+ return ret;
}
/*
@@ -235,7 +539,7 @@ int OSSL_STORE_close(OSSL_STORE_CTX *ctx)
* In all cases, ownership of the object is transferred to the OSSL_STORE_INFO
* and will therefore be freed when the OSSL_STORE_INFO is freed.
*/
-static OSSL_STORE_INFO *store_info_new(int type, void *data)
+OSSL_STORE_INFO *OSSL_STORE_INFO_new(int type, void *data)
{
OSSL_STORE_INFO *info = OPENSSL_zalloc(sizeof(*info));
@@ -249,11 +553,10 @@ static OSSL_STORE_INFO *store_info_new(int type, void *data)
OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name)
{
- OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_NAME, NULL);
+ OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_NAME, NULL);
if (info == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -266,8 +569,7 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name)
int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc)
{
if (info->type != OSSL_STORE_INFO_NAME) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION,
- ERR_R_PASSED_INVALID_ARGUMENT);
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
@@ -277,41 +579,46 @@ int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc)
}
OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params)
{
- OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_PARAMS, params);
+ OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PARAMS, params);
if (info == NULL)
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
+ return info;
+}
+
+OSSL_STORE_INFO *OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY *pkey)
+{
+ OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PUBKEY, pkey);
+
+ if (info == NULL)
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
return info;
}
OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey)
{
- OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_PKEY, pkey);
+ OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PKEY, pkey);
if (info == NULL)
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
return info;
}
OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509)
{
- OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_CERT, x509);
+ OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_CERT, x509);
if (info == NULL)
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
return info;
}
OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl)
{
- OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_CRL, crl);
+ OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_CRL, crl);
if (info == NULL)
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
return info;
}
@@ -323,6 +630,13 @@ int OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO *info)
return info->type;
}
+void *OSSL_STORE_INFO_get0_data(int type, const OSSL_STORE_INFO *info)
+{
+ if (info->type == type)
+ return info->_.data;
+ return NULL;
+}
+
const char *OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO *info)
{
if (info->type == OSSL_STORE_INFO_NAME)
@@ -336,12 +650,10 @@ char *OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO *info)
char *ret = OPENSSL_strdup(info->_.name.name);
if (ret == NULL)
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
return ret;
}
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME,
- OSSL_STORE_R_NOT_A_NAME);
+ ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_NAME);
return NULL;
}
@@ -359,12 +671,10 @@ char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *info)
? info->_.name.desc : "");
if (ret == NULL)
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
return ret;
}
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION,
- OSSL_STORE_R_NOT_A_NAME);
+ ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_NAME);
return NULL;
}
@@ -381,8 +691,24 @@ EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info)
EVP_PKEY_up_ref(info->_.params);
return info->_.params;
}
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS,
- OSSL_STORE_R_NOT_PARAMETERS);
+ ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_PARAMETERS);
+ return NULL;
+}
+
+EVP_PKEY *OSSL_STORE_INFO_get0_PUBKEY(const OSSL_STORE_INFO *info)
+{
+ if (info->type == OSSL_STORE_INFO_PUBKEY)
+ return info->_.pubkey;
+ return NULL;
+}
+
+EVP_PKEY *OSSL_STORE_INFO_get1_PUBKEY(const OSSL_STORE_INFO *info)
+{
+ if (info->type == OSSL_STORE_INFO_PUBKEY) {
+ EVP_PKEY_up_ref(info->_.pubkey);
+ return info->_.pubkey;
+ }
+ ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_PUBLIC_KEY);
return NULL;
}
@@ -399,8 +725,7 @@ EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info)
EVP_PKEY_up_ref(info->_.pkey);
return info->_.pkey;
}
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY,
- OSSL_STORE_R_NOT_A_KEY);
+ ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_PRIVATE_KEY);
return NULL;
}
@@ -417,8 +742,7 @@ X509 *OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO *info)
X509_up_ref(info->_.x509);
return info->_.x509;
}
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT,
- OSSL_STORE_R_NOT_A_CERTIFICATE);
+ ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_CERTIFICATE);
return NULL;
}
@@ -435,8 +759,7 @@ X509_CRL *OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO *info)
X509_CRL_up_ref(info->_.crl);
return info->_.crl;
}
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL,
- OSSL_STORE_R_NOT_A_CRL);
+ ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_CRL);
return NULL;
}
@@ -447,10 +770,6 @@ void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info)
{
if (info != NULL) {
switch (info->type) {
- case OSSL_STORE_INFO_EMBEDDED:
- BUF_MEM_free(info->_.embedded.blob);
- OPENSSL_free(info->_.embedded.pem_name);
- break;
case OSSL_STORE_INFO_NAME:
OPENSSL_free(info->_.name.name);
OPENSSL_free(info->_.name.desc);
@@ -458,6 +777,9 @@ void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info)
case OSSL_STORE_INFO_PARAMS:
EVP_PKEY_free(info->_.params);
break;
+ case OSSL_STORE_INFO_PUBKEY:
+ EVP_PKEY_free(info->_.pubkey);
+ break;
case OSSL_STORE_INFO_PKEY:
EVP_PKEY_free(info->_.pkey);
break;
@@ -474,12 +796,55 @@ void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info)
int OSSL_STORE_supports_search(OSSL_STORE_CTX *ctx, int search_type)
{
- OSSL_STORE_SEARCH tmp_search;
-
- if (ctx->loader->find == NULL)
- return 0;
- tmp_search.search_type = search_type;
- return ctx->loader->find(NULL, &tmp_search);
+ int ret = 0;
+
+ if (ctx->fetched_loader != NULL) {
+ void *provctx =
+ ossl_provider_ctx(OSSL_STORE_LOADER_get0_provider(ctx->fetched_loader));
+ const OSSL_PARAM *params;
+ const OSSL_PARAM *p_subject = NULL;
+ const OSSL_PARAM *p_issuer = NULL;
+ const OSSL_PARAM *p_serial = NULL;
+ const OSSL_PARAM *p_fingerprint = NULL;
+ const OSSL_PARAM *p_alias = NULL;
+
+ if (ctx->fetched_loader->p_settable_ctx_params == NULL)
+ return 0;
+
+ params = ctx->fetched_loader->p_settable_ctx_params(provctx);
+ p_subject = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_SUBJECT);
+ p_issuer = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_ISSUER);
+ p_serial = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_SERIAL);
+ p_fingerprint =
+ OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_FINGERPRINT);
+ p_alias = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_ALIAS);
+
+ switch (search_type) {
+ case OSSL_STORE_SEARCH_BY_NAME:
+ ret = (p_subject != NULL);
+ break;
+ case OSSL_STORE_SEARCH_BY_ISSUER_SERIAL:
+ ret = (p_issuer != NULL && p_serial != NULL);
+ break;
+ case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:
+ ret = (p_fingerprint != NULL);
+ break;
+ case OSSL_STORE_SEARCH_BY_ALIAS:
+ ret = (p_alias != NULL);
+ break;
+ }
+ }
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (ctx->fetched_loader == NULL) {
+ OSSL_STORE_SEARCH tmp_search;
+
+ if (ctx->loader->find == NULL)
+ return 0;
+ tmp_search.search_type = search_type;
+ ret = ctx->loader->find(NULL, &tmp_search);
+ }
+#endif
+ return ret;
}
/* Search term constructors */
@@ -488,8 +853,7 @@ OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_name(X509_NAME *name)
OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
if (search == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_NAME,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -499,13 +863,12 @@ OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_name(X509_NAME *name)
}
OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME *name,
- const ASN1_INTEGER *serial)
+ const ASN1_INTEGER *serial)
{
OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
if (search == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ISSUER_SERIAL,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -522,20 +885,17 @@ OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD *digest,
OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
if (search == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
return NULL;
}
- if (digest != NULL && len != (size_t)EVP_MD_size(digest)) {
- char buf1[20], buf2[20];
-
- BIO_snprintf(buf1, sizeof(buf1), "%d", EVP_MD_size(digest));
- BIO_snprintf(buf2, sizeof(buf2), "%zu", len);
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT,
- OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST);
- ERR_add_error_data(5, EVP_MD_name(digest), " size is ", buf1,
- ", fingerprint size is ", buf2);
+ if (digest != NULL && len != (size_t)EVP_MD_get_size(digest)) {
+ ERR_raise_data(ERR_LIB_OSSL_STORE,
+ OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST,
+ "%s size is %d, fingerprint size is %zu",
+ EVP_MD_get0_name(digest), EVP_MD_get_size(digest), len);
+ OPENSSL_free(search);
+ return NULL;
}
search->search_type = OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT;
@@ -550,8 +910,7 @@ OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_alias(const char *alias)
OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
if (search == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ALIAS,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -573,13 +932,13 @@ int OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH *criterion)
return criterion->search_type;
}
-X509_NAME *OSSL_STORE_SEARCH_get0_name(OSSL_STORE_SEARCH *criterion)
+X509_NAME *OSSL_STORE_SEARCH_get0_name(const OSSL_STORE_SEARCH *criterion)
{
return criterion->name;
}
const ASN1_INTEGER *OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH
- *criterion)
+ *criterion)
{
return criterion->serial;
}
@@ -601,85 +960,80 @@ const EVP_MD *OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH *criterion)
return criterion->digest;
}
-/* Internal functions */
-OSSL_STORE_INFO *ossl_store_info_new_EMBEDDED(const char *new_pem_name,
- BUF_MEM *embedded)
+OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bp, const char *scheme,
+ OSSL_LIB_CTX *libctx, const char *propq,
+ const UI_METHOD *ui_method, void *ui_data,
+ const OSSL_PARAM params[],
+ OSSL_STORE_post_process_info_fn post_process,
+ void *post_process_data)
{
- OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_EMBEDDED, NULL);
-
- if (info == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED,
- ERR_R_MALLOC_FAILURE);
- return NULL;
- }
+ const OSSL_STORE_LOADER *loader = NULL;
+ OSSL_STORE_LOADER *fetched_loader = NULL;
+ OSSL_STORE_LOADER_CTX *loader_ctx = NULL;
+ OSSL_STORE_CTX *ctx = NULL;
- info->_.embedded.blob = embedded;
- info->_.embedded.pem_name =
- new_pem_name == NULL ? NULL : OPENSSL_strdup(new_pem_name);
+ if (scheme == NULL)
+ scheme = "file";
- if (new_pem_name != NULL && info->_.embedded.pem_name == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED,
- ERR_R_MALLOC_FAILURE);
- OSSL_STORE_INFO_free(info);
- info = NULL;
+ OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme);
+ ERR_set_mark();
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if ((loader = ossl_store_get0_loader_int(scheme)) != NULL)
+ loader_ctx = loader->attach(loader, bp, libctx, propq,
+ ui_method, ui_data);
+#endif
+ if (loader == NULL
+ && (fetched_loader =
+ OSSL_STORE_LOADER_fetch(libctx, scheme, propq)) != NULL) {
+ const OSSL_PROVIDER *provider =
+ OSSL_STORE_LOADER_get0_provider(fetched_loader);
+ void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider);
+ OSSL_CORE_BIO *cbio = ossl_core_bio_new_from_bio(bp);
+
+ if (cbio == NULL
+ || (loader_ctx = fetched_loader->p_attach(provctx, cbio)) == NULL) {
+ OSSL_STORE_LOADER_free(fetched_loader);
+ fetched_loader = NULL;
+ } else if (!loader_set_params(fetched_loader, loader_ctx,
+ params, propq)) {
+ (void)fetched_loader->p_close(loader_ctx);
+ OSSL_STORE_LOADER_free(fetched_loader);
+ fetched_loader = NULL;
+ }
+ loader = fetched_loader;
+ ossl_core_bio_free(cbio);
}
- return info;
-}
-
-BUF_MEM *ossl_store_info_get0_EMBEDDED_buffer(OSSL_STORE_INFO *info)
-{
- if (info->type == OSSL_STORE_INFO_EMBEDDED)
- return info->_.embedded.blob;
- return NULL;
-}
-
-char *ossl_store_info_get0_EMBEDDED_pem_name(OSSL_STORE_INFO *info)
-{
- if (info->type == OSSL_STORE_INFO_EMBEDDED)
- return info->_.embedded.pem_name;
- return NULL;
-}
-
-OSSL_STORE_CTX *ossl_store_attach_pem_bio(BIO *bp, const UI_METHOD *ui_method,
- void *ui_data)
-{
- OSSL_STORE_CTX *ctx = NULL;
- const OSSL_STORE_LOADER *loader = NULL;
- OSSL_STORE_LOADER_CTX *loader_ctx = NULL;
+ if (loader_ctx == NULL) {
+ ERR_clear_last_mark();
+ return NULL;
+ }
- if ((loader = ossl_store_get0_loader_int("file")) == NULL
- || ((loader_ctx = ossl_store_file_attach_pem_bio_int(bp)) == NULL))
- goto done;
if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_ATTACH_PEM_BIO,
- ERR_R_MALLOC_FAILURE);
- goto done;
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (ui_method != NULL
+ && !ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data)) {
+ ERR_clear_last_mark();
+ OPENSSL_free(ctx);
+ return NULL;
}
+ ctx->fetched_loader = fetched_loader;
ctx->loader = loader;
ctx->loader_ctx = loader_ctx;
- loader_ctx = NULL;
- ctx->ui_method = ui_method;
- ctx->ui_data = ui_data;
- ctx->post_process = NULL;
- ctx->post_process_data = NULL;
-
- done:
- if (loader_ctx != NULL)
- /*
- * We ignore a returned error because we will return NULL anyway in
- * this case, so if something goes wrong when closing, that'll simply
- * just add another entry on the error stack.
- */
- (void)loader->close(loader_ctx);
- return ctx;
-}
+ ctx->post_process = post_process;
+ ctx->post_process_data = post_process_data;
-int ossl_store_detach_pem_bio(OSSL_STORE_CTX *ctx)
-{
- int loader_ret = ossl_store_file_detach_pem_bio_int(ctx->loader_ctx);
+ /*
+ * ossl_store_get0_loader_int will raise an error if the loader for the
+ * the scheme cannot be retrieved. But if a loader was successfully
+ * fetched then we remove this error from the error stack.
+ */
+ ERR_pop_to_mark();
- OPENSSL_free(ctx);
- return loader_ret;
+ return ctx;
}
diff --git a/crypto/store/store_local.h b/crypto/store/store_local.h
index 369dcb33f2d6..8f817fd514bb 100644
--- a/crypto/store/store_local.h
+++ b/crypto/store/store_local.h
@@ -1,19 +1,22 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#include <openssl/core_dispatch.h>
#include "internal/thread_once.h"
+#include "internal/refcount.h"
#include <openssl/dsa.h>
#include <openssl/engine.h>
#include <openssl/evp.h>
#include <openssl/lhash.h>
#include <openssl/x509.h>
#include <openssl/store.h>
+#include "internal/passphrase.h"
/*-
* OSSL_STORE_INFO stuff
@@ -26,41 +29,19 @@ struct ossl_store_info_st {
void *data; /* used internally as generic pointer */
struct {
- BUF_MEM *blob;
- char *pem_name;
- } embedded; /* when type == OSSL_STORE_INFO_EMBEDDED */
-
- struct {
char *name;
char *desc;
} name; /* when type == OSSL_STORE_INFO_NAME */
EVP_PKEY *params; /* when type == OSSL_STORE_INFO_PARAMS */
+ EVP_PKEY *pubkey; /* when type == OSSL_STORE_INFO_PUBKEY */
EVP_PKEY *pkey; /* when type == OSSL_STORE_INFO_PKEY */
X509 *x509; /* when type == OSSL_STORE_INFO_CERT */
X509_CRL *crl; /* when type == OSSL_STORE_INFO_CRL */
} _;
};
-
DEFINE_STACK_OF(OSSL_STORE_INFO)
-/*
- * EMBEDDED is a special type of OSSL_STORE_INFO, specially for the file
- * handlers. It should never reach a calling application or any engine.
- * However, it can be used by a FILE_HANDLER's try_decode function to signal
- * that it has decoded the incoming blob into a new blob, and that the
- * attempted decoding should be immediately restarted with the new blob, using
- * the new PEM name.
- */
-/*
- * Because this is an internal type, we don't make it public.
- */
-#define OSSL_STORE_INFO_EMBEDDED -1
-OSSL_STORE_INFO *ossl_store_info_new_EMBEDDED(const char *new_pem_name,
- BUF_MEM *embedded);
-BUF_MEM *ossl_store_info_get0_EMBEDDED_buffer(OSSL_STORE_INFO *info);
-char *ossl_store_info_get0_EMBEDDED_pem_name(OSSL_STORE_INFO *info);
-
/*-
* OSSL_STORE_SEARCH stuff
* -----------------------
@@ -99,29 +80,78 @@ OSSL_STORE_LOADER *ossl_store_unregister_loader_int(const char *scheme);
/* loader stuff */
struct ossl_store_loader_st {
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ /* Legacy stuff */
const char *scheme;
ENGINE *engine;
OSSL_STORE_open_fn open;
+ OSSL_STORE_attach_fn attach;
OSSL_STORE_ctrl_fn ctrl;
OSSL_STORE_expect_fn expect;
OSSL_STORE_find_fn find;
OSSL_STORE_load_fn load;
OSSL_STORE_eof_fn eof;
OSSL_STORE_error_fn error;
- OSSL_STORE_close_fn close;
+ OSSL_STORE_close_fn closefn;
+ OSSL_STORE_open_ex_fn open_ex;
+#endif
+
+ /* Provider stuff */
+ OSSL_PROVIDER *prov;
+ int scheme_id;
+ const char *propdef;
+ const char *description;
+
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+
+ OSSL_FUNC_store_open_fn *p_open;
+ OSSL_FUNC_store_attach_fn *p_attach;
+ OSSL_FUNC_store_settable_ctx_params_fn *p_settable_ctx_params;
+ OSSL_FUNC_store_set_ctx_params_fn *p_set_ctx_params;
+ OSSL_FUNC_store_load_fn *p_load;
+ OSSL_FUNC_store_eof_fn *p_eof;
+ OSSL_FUNC_store_close_fn *p_close;
+ OSSL_FUNC_store_export_object_fn *p_export_object;
};
DEFINE_LHASH_OF(OSSL_STORE_LOADER);
const OSSL_STORE_LOADER *ossl_store_get0_loader_int(const char *scheme);
void ossl_store_destroy_loaders_int(void);
+#ifdef OPENSSL_NO_DEPRECATED_3_0
+/* struct ossl_store_loader_ctx_st is defined differently by each loader */
+typedef struct ossl_store_loader_ctx_st OSSL_STORE_LOADER_CTX;
+#endif
+
/*-
- * OSSL_STORE init stuff
+ * OSSL_STORE_CTX stuff
* ---------------------
*/
-int ossl_store_init_once(void);
-int ossl_store_file_loader_init(void);
+struct ossl_store_ctx_st {
+ const OSSL_STORE_LOADER *loader; /* legacy */
+ OSSL_STORE_LOADER *fetched_loader;
+ OSSL_STORE_LOADER_CTX *loader_ctx;
+ OSSL_STORE_post_process_info_fn post_process;
+ void *post_process_data;
+ int expected_type;
+
+ char *properties;
+
+ /* 0 before the first STORE_load(), 1 otherwise */
+ int loading;
+ /* 1 on load error, only valid for fetched loaders */
+ int error_flag;
+
+ /*
+ * Cache of stuff, to be able to return the contents of a PKCS#12
+ * blob, one object at a time.
+ */
+ STACK_OF(OSSL_STORE_INFO) *cached_info;
+
+ struct ossl_passphrase_data_st pwdata;
+};
/*-
* 'file' scheme stuff
@@ -130,3 +160,21 @@ int ossl_store_file_loader_init(void);
OSSL_STORE_LOADER_CTX *ossl_store_file_attach_pem_bio_int(BIO *bp);
int ossl_store_file_detach_pem_bio_int(OSSL_STORE_LOADER_CTX *ctx);
+
+/*-
+ * Provider stuff
+ * -------------------
+ */
+OSSL_STORE_LOADER *ossl_store_loader_fetch(OSSL_LIB_CTX *libctx,
+ const char *scheme,
+ const char *properties);
+OSSL_STORE_LOADER *ossl_store_loader_fetch_by_number(OSSL_LIB_CTX *libctx,
+ int scheme_id,
+ const char *properties);
+
+/* Standard function to handle the result from OSSL_FUNC_store_load() */
+struct ossl_load_result_data_st {
+ OSSL_STORE_INFO *v; /* To be filled in */
+ OSSL_STORE_CTX *ctx;
+};
+OSSL_CALLBACK ossl_store_handle_load_result;
diff --git a/crypto/store/store_meth.c b/crypto/store/store_meth.c
new file mode 100644
index 000000000000..a5b0d1b0957c
--- /dev/null
+++ b/crypto/store/store_meth.c
@@ -0,0 +1,538 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include "crypto/store.h"
+#include "internal/core.h"
+#include "internal/namemap.h"
+#include "internal/property.h"
+#include "internal/provider.h"
+#include "store_local.h"
+
+int OSSL_STORE_LOADER_up_ref(OSSL_STORE_LOADER *loader)
+{
+ int ref = 0;
+
+ if (loader->prov != NULL)
+ CRYPTO_UP_REF(&loader->refcnt, &ref, loader->lock);
+ return 1;
+}
+
+void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader)
+{
+ if (loader != NULL && loader->prov != NULL) {
+ int i;
+
+ CRYPTO_DOWN_REF(&loader->refcnt, &i, loader->lock);
+ if (i > 0)
+ return;
+ ossl_provider_free(loader->prov);
+ CRYPTO_THREAD_lock_free(loader->lock);
+ }
+ OPENSSL_free(loader);
+}
+
+/*
+ * OSSL_STORE_LOADER_new() expects the scheme as a constant string,
+ * which we currently don't have, so we need an alternative allocator.
+ */
+static OSSL_STORE_LOADER *new_loader(OSSL_PROVIDER *prov)
+{
+ OSSL_STORE_LOADER *loader;
+
+ if ((loader = OPENSSL_zalloc(sizeof(*loader))) == NULL
+ || (loader->lock = CRYPTO_THREAD_lock_new()) == NULL) {
+ OPENSSL_free(loader);
+ return NULL;
+ }
+ loader->prov = prov;
+ ossl_provider_up_ref(prov);
+ loader->refcnt = 1;
+
+ return loader;
+}
+
+static int up_ref_loader(void *method)
+{
+ return OSSL_STORE_LOADER_up_ref(method);
+}
+
+static void free_loader(void *method)
+{
+ OSSL_STORE_LOADER_free(method);
+}
+
+/* Permanent loader method store, constructor and destructor */
+static void loader_store_free(void *vstore)
+{
+ ossl_method_store_free(vstore);
+}
+
+static void *loader_store_new(OSSL_LIB_CTX *ctx)
+{
+ return ossl_method_store_new(ctx);
+}
+
+
+static const OSSL_LIB_CTX_METHOD loader_store_method = {
+ /* We want loader_store to be cleaned up before the provider store */
+ OSSL_LIB_CTX_METHOD_PRIORITY_2,
+ loader_store_new,
+ loader_store_free,
+};
+
+/* Data to be passed through ossl_method_construct() */
+struct loader_data_st {
+ OSSL_LIB_CTX *libctx;
+ int scheme_id; /* For get_loader_from_store() */
+ const char *scheme; /* For get_loader_from_store() */
+ const char *propquery; /* For get_loader_from_store() */
+
+ OSSL_METHOD_STORE *tmp_store; /* For get_tmp_loader_store() */
+
+ unsigned int flag_construct_error_occurred : 1;
+};
+
+/*
+ * Generic routines to fetch / create OSSL_STORE methods with
+ * ossl_method_construct()
+ */
+
+/* Temporary loader method store, constructor and destructor */
+static void *get_tmp_loader_store(void *data)
+{
+ struct loader_data_st *methdata = data;
+
+ if (methdata->tmp_store == NULL)
+ methdata->tmp_store = ossl_method_store_new(methdata->libctx);
+ return methdata->tmp_store;
+}
+
+ static void dealloc_tmp_loader_store(void *store)
+{
+ if (store != NULL)
+ ossl_method_store_free(store);
+}
+
+/* Get the permanent loader store */
+static OSSL_METHOD_STORE *get_loader_store(OSSL_LIB_CTX *libctx)
+{
+ return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_STORE_LOADER_STORE_INDEX,
+ &loader_store_method);
+}
+
+static int reserve_loader_store(void *store, void *data)
+{
+ struct loader_data_st *methdata = data;
+
+ if (store == NULL
+ && (store = get_loader_store(methdata->libctx)) == NULL)
+ return 0;
+
+ return ossl_method_lock_store(store);
+}
+
+static int unreserve_loader_store(void *store, void *data)
+{
+ struct loader_data_st *methdata = data;
+
+ if (store == NULL
+ && (store = get_loader_store(methdata->libctx)) == NULL)
+ return 0;
+
+ return ossl_method_unlock_store(store);
+}
+
+/* Get loader methods from a store, or put one in */
+static void *get_loader_from_store(void *store, const OSSL_PROVIDER **prov,
+ void *data)
+{
+ struct loader_data_st *methdata = data;
+ void *method = NULL;
+ int id;
+
+ if ((id = methdata->scheme_id) == 0) {
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
+
+ id = ossl_namemap_name2num(namemap, methdata->scheme);
+ }
+
+ if (store == NULL
+ && (store = get_loader_store(methdata->libctx)) == NULL)
+ return NULL;
+
+ if (!ossl_method_store_fetch(store, id, methdata->propquery, prov, &method))
+ return NULL;
+ return method;
+}
+
+static int put_loader_in_store(void *store, void *method,
+ const OSSL_PROVIDER *prov,
+ const char *scheme, const char *propdef,
+ void *data)
+{
+ struct loader_data_st *methdata = data;
+ OSSL_NAMEMAP *namemap;
+ int id;
+
+ if ((namemap = ossl_namemap_stored(methdata->libctx)) == NULL
+ || (id = ossl_namemap_name2num(namemap, scheme)) == 0)
+ return 0;
+
+ if (store == NULL && (store = get_loader_store(methdata->libctx)) == NULL)
+ return 0;
+
+ return ossl_method_store_add(store, prov, id, propdef, method,
+ up_ref_loader, free_loader);
+}
+
+static void *loader_from_algorithm(int scheme_id, const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov)
+{
+ OSSL_STORE_LOADER *loader = NULL;
+ const OSSL_DISPATCH *fns = algodef->implementation;
+
+ if ((loader = new_loader(prov)) == NULL)
+ return NULL;
+ loader->scheme_id = scheme_id;
+ loader->propdef = algodef->property_definition;
+ loader->description = algodef->algorithm_description;
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_STORE_OPEN:
+ if (loader->p_open == NULL)
+ loader->p_open = OSSL_FUNC_store_open(fns);
+ break;
+ case OSSL_FUNC_STORE_ATTACH:
+ if (loader->p_attach == NULL)
+ loader->p_attach = OSSL_FUNC_store_attach(fns);
+ break;
+ case OSSL_FUNC_STORE_SETTABLE_CTX_PARAMS:
+ if (loader->p_settable_ctx_params == NULL)
+ loader->p_settable_ctx_params =
+ OSSL_FUNC_store_settable_ctx_params(fns);
+ break;
+ case OSSL_FUNC_STORE_SET_CTX_PARAMS:
+ if (loader->p_set_ctx_params == NULL)
+ loader->p_set_ctx_params = OSSL_FUNC_store_set_ctx_params(fns);
+ break;
+ case OSSL_FUNC_STORE_LOAD:
+ if (loader->p_load == NULL)
+ loader->p_load = OSSL_FUNC_store_load(fns);
+ break;
+ case OSSL_FUNC_STORE_EOF:
+ if (loader->p_eof == NULL)
+ loader->p_eof = OSSL_FUNC_store_eof(fns);
+ break;
+ case OSSL_FUNC_STORE_CLOSE:
+ if (loader->p_close == NULL)
+ loader->p_close = OSSL_FUNC_store_close(fns);
+ break;
+ case OSSL_FUNC_STORE_EXPORT_OBJECT:
+ if (loader->p_export_object == NULL)
+ loader->p_export_object = OSSL_FUNC_store_export_object(fns);
+ break;
+ }
+ }
+
+ if ((loader->p_open == NULL && loader->p_attach == NULL)
+ || loader->p_load == NULL
+ || loader->p_eof == NULL
+ || loader->p_close == NULL) {
+ /* Only set_ctx_params is optionaal */
+ OSSL_STORE_LOADER_free(loader);
+ ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADER_INCOMPLETE);
+ return NULL;
+ }
+ return loader;
+}
+
+/*
+ * The core fetching functionality passes the scheme of the implementation.
+ * This function is responsible to getting an identity number for them,
+ * then call loader_from_algorithm() with that identity number.
+ */
+static void *construct_loader(const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov, void *data)
+{
+ /*
+ * This function is only called if get_loader_from_store() returned
+ * NULL, so it's safe to say that of all the spots to create a new
+ * namemap entry, this is it. Should the scheme already exist there, we
+ * know that ossl_namemap_add() will return its corresponding number.
+ */
+ struct loader_data_st *methdata = data;
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+ const char *scheme = algodef->algorithm_names;
+ int id = ossl_namemap_add_name(namemap, 0, scheme);
+ void *method = NULL;
+
+ if (id != 0)
+ method = loader_from_algorithm(id, algodef, prov);
+
+ /*
+ * Flag to indicate that there was actual construction errors. This
+ * helps inner_loader_fetch() determine what error it should
+ * record on inaccessible algorithms.
+ */
+ if (method == NULL)
+ methdata->flag_construct_error_occurred = 1;
+
+ return method;
+}
+
+/* Intermediary function to avoid ugly casts, used below */
+static void destruct_loader(void *method, void *data)
+{
+ OSSL_STORE_LOADER_free(method);
+}
+
+/* Fetching support. Can fetch by numeric identity or by scheme */
+static OSSL_STORE_LOADER *
+inner_loader_fetch(struct loader_data_st *methdata, int id,
+ const char *scheme, const char *properties)
+{
+ OSSL_METHOD_STORE *store = get_loader_store(methdata->libctx);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
+ const char *const propq = properties != NULL ? properties : "";
+ void *method = NULL;
+ int unsupported = 0;
+
+ if (store == NULL || namemap == NULL) {
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_INVALID_ARGUMENT);
+ return NULL;
+ }
+
+ /*
+ * If we have been passed both an id and a scheme, we have an
+ * internal programming error.
+ */
+ if (!ossl_assert(id == 0 || scheme == NULL)) {
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ /* If we haven't received a name id yet, try to get one for the name */
+ if (id == 0 && scheme != NULL)
+ id = ossl_namemap_name2num(namemap, scheme);
+
+ /*
+ * If we haven't found the name yet, chances are that the algorithm to
+ * be fetched is unsupported.
+ */
+ if (id == 0)
+ unsupported = 1;
+
+ if (id == 0
+ || !ossl_method_store_cache_get(store, NULL, id, propq, &method)) {
+ OSSL_METHOD_CONSTRUCT_METHOD mcm = {
+ get_tmp_loader_store,
+ reserve_loader_store,
+ unreserve_loader_store,
+ get_loader_from_store,
+ put_loader_in_store,
+ construct_loader,
+ destruct_loader
+ };
+ OSSL_PROVIDER *prov = NULL;
+
+ methdata->scheme_id = id;
+ methdata->scheme = scheme;
+ methdata->propquery = propq;
+ methdata->flag_construct_error_occurred = 0;
+ if ((method = ossl_method_construct(methdata->libctx, OSSL_OP_STORE,
+ &prov, 0 /* !force_cache */,
+ &mcm, methdata)) != NULL) {
+ /*
+ * If construction did create a method for us, we know that there
+ * is a correct scheme_id, since those have already been calculated
+ * in get_loader_from_store() and put_loader_in_store() above.
+ */
+ if (id == 0)
+ id = ossl_namemap_name2num(namemap, scheme);
+ ossl_method_store_cache_set(store, prov, id, propq, method,
+ up_ref_loader, free_loader);
+ }
+
+ /*
+ * If we never were in the constructor, the algorithm to be fetched
+ * is unsupported.
+ */
+ unsupported = !methdata->flag_construct_error_occurred;
+ }
+
+ if ((id != 0 || scheme != NULL) && method == NULL) {
+ int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED;
+ const char *helpful_msg =
+ unsupported
+ ? ( "No store loader found. For standard store loaders you need "
+ "at least one of the default or base providers available. "
+ "Did you forget to load them? Info: " )
+ : "";
+
+ if (scheme == NULL)
+ scheme = ossl_namemap_num2name(namemap, id, 0);
+ ERR_raise_data(ERR_LIB_OSSL_STORE, code,
+ "%s%s, Scheme (%s : %d), Properties (%s)",
+ helpful_msg,
+ ossl_lib_ctx_get_descriptor(methdata->libctx),
+ scheme == NULL ? "<null>" : scheme, id,
+ properties == NULL ? "<null>" : properties);
+ }
+
+ return method;
+}
+
+OSSL_STORE_LOADER *OSSL_STORE_LOADER_fetch(OSSL_LIB_CTX *libctx,
+ const char *scheme,
+ const char *properties)
+{
+ struct loader_data_st methdata;
+ void *method;
+
+ methdata.libctx = libctx;
+ methdata.tmp_store = NULL;
+ method = inner_loader_fetch(&methdata, 0, scheme, properties);
+ dealloc_tmp_loader_store(methdata.tmp_store);
+ return method;
+}
+
+OSSL_STORE_LOADER *ossl_store_loader_fetch_by_number(OSSL_LIB_CTX *libctx,
+ int scheme_id,
+ const char *properties)
+{
+ struct loader_data_st methdata;
+ void *method;
+
+ methdata.libctx = libctx;
+ methdata.tmp_store = NULL;
+ method = inner_loader_fetch(&methdata, scheme_id, NULL, properties);
+ dealloc_tmp_loader_store(methdata.tmp_store);
+ return method;
+}
+
+int ossl_store_loader_store_cache_flush(OSSL_LIB_CTX *libctx)
+{
+ OSSL_METHOD_STORE *store = get_loader_store(libctx);
+
+ if (store != NULL)
+ return ossl_method_store_cache_flush_all(store);
+ return 1;
+}
+
+int ossl_store_loader_store_remove_all_provided(const OSSL_PROVIDER *prov)
+{
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
+ OSSL_METHOD_STORE *store = get_loader_store(libctx);
+
+ if (store != NULL)
+ return ossl_method_store_remove_all_provided(store, prov);
+ return 1;
+}
+
+/*
+ * Library of basic method functions
+ */
+
+const OSSL_PROVIDER *OSSL_STORE_LOADER_get0_provider(const OSSL_STORE_LOADER *loader)
+{
+ if (!ossl_assert(loader != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ return loader->prov;
+}
+
+const char *OSSL_STORE_LOADER_get0_properties(const OSSL_STORE_LOADER *loader)
+{
+ if (!ossl_assert(loader != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ return loader->propdef;
+}
+
+int ossl_store_loader_get_number(const OSSL_STORE_LOADER *loader)
+{
+ if (!ossl_assert(loader != NULL)) {
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ return loader->scheme_id;
+}
+
+const char *OSSL_STORE_LOADER_get0_description(const OSSL_STORE_LOADER *loader)
+{
+ return loader->description;
+}
+
+int OSSL_STORE_LOADER_is_a(const OSSL_STORE_LOADER *loader, const char *name)
+{
+ if (loader->prov != NULL) {
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(loader->prov);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+
+ return ossl_namemap_name2num(namemap, name) == loader->scheme_id;
+ }
+ return 0;
+}
+
+struct do_one_data_st {
+ void (*user_fn)(OSSL_STORE_LOADER *loader, void *arg);
+ void *user_arg;
+};
+
+static void do_one(ossl_unused int id, void *method, void *arg)
+{
+ struct do_one_data_st *data = arg;
+
+ data->user_fn(method, data->user_arg);
+}
+
+void OSSL_STORE_LOADER_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*user_fn)(OSSL_STORE_LOADER *loader,
+ void *arg),
+ void *user_arg)
+{
+ struct loader_data_st methdata;
+ struct do_one_data_st data;
+
+ methdata.libctx = libctx;
+ methdata.tmp_store = NULL;
+ (void)inner_loader_fetch(&methdata, 0, NULL, NULL /* properties */);
+
+ data.user_fn = user_fn;
+ data.user_arg = user_arg;
+ if (methdata.tmp_store != NULL)
+ ossl_method_store_do_all(methdata.tmp_store, &do_one, &data);
+ ossl_method_store_do_all(get_loader_store(libctx), &do_one, &data);
+ dealloc_tmp_loader_store(methdata.tmp_store);
+}
+
+int OSSL_STORE_LOADER_names_do_all(const OSSL_STORE_LOADER *loader,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (loader == NULL)
+ return 0;
+
+ if (loader->prov != NULL) {
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(loader->prov);
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+
+ return ossl_namemap_doall_names(namemap, loader->scheme_id, fn, data);
+ }
+
+ return 1;
+}
diff --git a/crypto/store/store_register.c b/crypto/store/store_register.c
index 3631d9b50634..6fa7352ccdc1 100644
--- a/crypto/store/store_register.c
+++ b/crypto/store/store_register.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -39,13 +39,12 @@ OSSL_STORE_LOADER *OSSL_STORE_LOADER_new(ENGINE *e, const char *scheme)
* later on.
*/
if (scheme == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_LOADER_NEW,
- OSSL_STORE_R_INVALID_SCHEME);
+ ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_INVALID_SCHEME);
return NULL;
}
if ((res = OPENSSL_zalloc(sizeof(*res))) == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_LOADER_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -71,6 +70,21 @@ int OSSL_STORE_LOADER_set_open(OSSL_STORE_LOADER *loader,
return 1;
}
+int OSSL_STORE_LOADER_set_open_ex
+ (OSSL_STORE_LOADER *loader,
+ OSSL_STORE_open_ex_fn open_ex_function)
+{
+ loader->open_ex = open_ex_function;
+ return 1;
+}
+
+int OSSL_STORE_LOADER_set_attach(OSSL_STORE_LOADER *loader,
+ OSSL_STORE_attach_fn attach_function)
+{
+ loader->attach = attach_function;
+ return 1;
+}
+
int OSSL_STORE_LOADER_set_ctrl(OSSL_STORE_LOADER *loader,
OSSL_STORE_ctrl_fn ctrl_function)
{
@@ -116,15 +130,10 @@ int OSSL_STORE_LOADER_set_error(OSSL_STORE_LOADER *loader,
int OSSL_STORE_LOADER_set_close(OSSL_STORE_LOADER *loader,
OSSL_STORE_close_fn close_function)
{
- loader->close = close_function;
+ loader->closefn = close_function;
return 1;
}
-void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader)
-{
- OPENSSL_free(loader);
-}
-
/*
* Functions for registering OSSL_STORE_LOADERs
*/
@@ -142,6 +151,14 @@ static int store_loader_cmp(const OSSL_STORE_LOADER *a,
}
static LHASH_OF(OSSL_STORE_LOADER) *loader_register = NULL;
+static int ossl_store_register_init(void)
+{
+ if (loader_register == NULL) {
+ loader_register = lh_OSSL_STORE_LOADER_new(store_loader_hash,
+ store_loader_cmp);
+ }
+ return loader_register != NULL;
+}
int ossl_store_register_loader_int(OSSL_STORE_LOADER *loader)
{
@@ -161,33 +178,26 @@ int ossl_store_register_loader_int(OSSL_STORE_LOADER *loader)
|| strchr("+-.", *scheme) != NULL))
scheme++;
if (*scheme != '\0') {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT,
- OSSL_STORE_R_INVALID_SCHEME);
- ERR_add_error_data(2, "scheme=", loader->scheme);
+ ERR_raise_data(ERR_LIB_OSSL_STORE, OSSL_STORE_R_INVALID_SCHEME,
+ "scheme=%s", loader->scheme);
return 0;
}
/* Check that functions we absolutely require are present */
if (loader->open == NULL || loader->load == NULL || loader->eof == NULL
- || loader->error == NULL || loader->close == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT,
- OSSL_STORE_R_LOADER_INCOMPLETE);
+ || loader->error == NULL || loader->closefn == NULL) {
+ ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADER_INCOMPLETE);
return 0;
}
if (!RUN_ONCE(&registry_init, do_registry_init)) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
return 0;
}
- CRYPTO_THREAD_write_lock(registry_lock);
-
- if (loader_register == NULL) {
- loader_register = lh_OSSL_STORE_LOADER_new(store_loader_hash,
- store_loader_cmp);
- }
+ if (!CRYPTO_THREAD_write_lock(registry_lock))
+ return 0;
- if (loader_register != NULL
+ if (ossl_store_register_init()
&& (lh_OSSL_STORE_LOADER_insert(loader_register, loader) != NULL
|| lh_OSSL_STORE_LOADER_error(loader_register) == 0))
ok = 1;
@@ -198,8 +208,6 @@ int ossl_store_register_loader_int(OSSL_STORE_LOADER *loader)
}
int OSSL_STORE_register_loader(OSSL_STORE_LOADER *loader)
{
- if (!ossl_store_init_once())
- return 0;
return ossl_store_register_loader_int(loader);
}
@@ -212,25 +220,22 @@ const OSSL_STORE_LOADER *ossl_store_get0_loader_int(const char *scheme)
template.open = NULL;
template.load = NULL;
template.eof = NULL;
- template.close = NULL;
-
- if (!ossl_store_init_once())
- return NULL;
+ template.closefn = NULL;
+ template.open_ex = NULL;
if (!RUN_ONCE(&registry_init, do_registry_init)) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
return NULL;
}
- CRYPTO_THREAD_write_lock(registry_lock);
-
- loader = lh_OSSL_STORE_LOADER_retrieve(loader_register, &template);
+ if (!CRYPTO_THREAD_write_lock(registry_lock))
+ return NULL;
- if (loader == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT,
- OSSL_STORE_R_UNREGISTERED_SCHEME);
- ERR_add_error_data(2, "scheme=", scheme);
- }
+ if (!ossl_store_register_init())
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_INTERNAL_ERROR);
+ else if ((loader = lh_OSSL_STORE_LOADER_retrieve(loader_register,
+ &template)) == NULL)
+ ERR_raise_data(ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNREGISTERED_SCHEME,
+ "scheme=%s", scheme);
CRYPTO_THREAD_unlock(registry_lock);
@@ -246,22 +251,21 @@ OSSL_STORE_LOADER *ossl_store_unregister_loader_int(const char *scheme)
template.open = NULL;
template.load = NULL;
template.eof = NULL;
- template.close = NULL;
+ template.closefn = NULL;
if (!RUN_ONCE(&registry_init, do_registry_init)) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
return NULL;
}
- CRYPTO_THREAD_write_lock(registry_lock);
-
- loader = lh_OSSL_STORE_LOADER_delete(loader_register, &template);
+ if (!CRYPTO_THREAD_write_lock(registry_lock))
+ return NULL;
- if (loader == NULL) {
- OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT,
- OSSL_STORE_R_UNREGISTERED_SCHEME);
- ERR_add_error_data(2, "scheme=", scheme);
- }
+ if (!ossl_store_register_init())
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_INTERNAL_ERROR);
+ else if ((loader = lh_OSSL_STORE_LOADER_delete(loader_register,
+ &template)) == NULL)
+ ERR_raise_data(ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNREGISTERED_SCHEME,
+ "scheme=%s", scheme);
CRYPTO_THREAD_unlock(registry_lock);
@@ -269,14 +273,11 @@ OSSL_STORE_LOADER *ossl_store_unregister_loader_int(const char *scheme)
}
OSSL_STORE_LOADER *OSSL_STORE_unregister_loader(const char *scheme)
{
- if (!ossl_store_init_once())
- return 0;
return ossl_store_unregister_loader_int(scheme);
}
void ossl_store_destroy_loaders_int(void)
{
- assert(lh_OSSL_STORE_LOADER_num_items(loader_register) == 0);
lh_OSSL_STORE_LOADER_free(loader_register);
loader_register = NULL;
CRYPTO_THREAD_lock_free(registry_lock);
@@ -292,6 +293,7 @@ int OSSL_STORE_do_all_loaders(void (*do_function) (const OSSL_STORE_LOADER
*loader, void *do_arg),
void *do_arg)
{
- lh_OSSL_STORE_LOADER_doall_void(loader_register, do_function, do_arg);
+ if (ossl_store_register_init())
+ lh_OSSL_STORE_LOADER_doall_void(loader_register, do_function, do_arg);
return 1;
}
diff --git a/crypto/store/store_result.c b/crypto/store/store_result.c
new file mode 100644
index 000000000000..96d31199074d
--- /dev/null
+++ b/crypto/store/store_result.c
@@ -0,0 +1,648 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "e_os.h"
+#include <string.h>
+
+#include <openssl/core.h>
+#include <openssl/core_names.h>
+#include <openssl/core_object.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
+#include <openssl/provider.h>
+#include <openssl/decoder.h>
+#include <openssl/store.h>
+#include "internal/provider.h"
+#include "internal/passphrase.h"
+#include "crypto/evp.h"
+#include "crypto/x509.h"
+#include "store_local.h"
+
+#ifndef OSSL_OBJECT_PKCS12
+/*
+ * The object abstraction doesn't know PKCS#12, but we want to indicate
+ * it anyway, so we create our own. Since the public macros use positive
+ * numbers, negative ones should be fine. They must never slip out from
+ * this translation unit anyway.
+ */
+# define OSSL_OBJECT_PKCS12 -1
+#endif
+
+/*
+ * ossl_store_handle_load_result() is initially written to be a companion
+ * to our 'file:' scheme provider implementation, but has been made generic
+ * to serve others as well.
+ *
+ * This result handler takes any object abstraction (see provider-object(7))
+ * and does the best it can with it. If the object is passed by value (not
+ * by reference), the contents are currently expected to be DER encoded.
+ * If an object type is specified, that will be respected; otherwise, this
+ * handler will guess the contents, by trying the following in order:
+ *
+ * 1. Decode it into an EVP_PKEY, using OSSL_DECODER.
+ * 2. Decode it into an X.509 certificate, using d2i_X509 / d2i_X509_AUX.
+ * 3. Decode it into an X.509 CRL, using d2i_X509_CRL.
+ * 4. Decode it into a PKCS#12 structure, using d2i_PKCS12 (*).
+ *
+ * For the 'file:' scheme implementation, this is division of labor. Since
+ * the libcrypto <-> provider interface currently doesn't support certain
+ * structures as first class objects, they must be unpacked from DER here
+ * rather than in the provider. The current exception is asymmetric keys,
+ * which can reside within the provider boundary, most of all thanks to
+ * OSSL_FUNC_keymgmt_load(), which allows loading the key material by
+ * reference.
+ */
+
+struct extracted_param_data_st {
+ int object_type;
+ const char *data_type;
+ const char *data_structure;
+ const char *utf8_data;
+ const void *octet_data;
+ size_t octet_data_size;
+ const void *ref;
+ size_t ref_size;
+ const char *desc;
+};
+
+static int try_name(struct extracted_param_data_st *, OSSL_STORE_INFO **);
+static int try_key(struct extracted_param_data_st *, OSSL_STORE_INFO **,
+ OSSL_STORE_CTX *, const OSSL_PROVIDER *,
+ OSSL_LIB_CTX *, const char *);
+static int try_cert(struct extracted_param_data_st *, OSSL_STORE_INFO **,
+ OSSL_LIB_CTX *, const char *);
+static int try_crl(struct extracted_param_data_st *, OSSL_STORE_INFO **,
+ OSSL_LIB_CTX *, const char *);
+static int try_pkcs12(struct extracted_param_data_st *, OSSL_STORE_INFO **,
+ OSSL_STORE_CTX *, OSSL_LIB_CTX *, const char *);
+
+int ossl_store_handle_load_result(const OSSL_PARAM params[], void *arg)
+{
+ struct ossl_load_result_data_st *cbdata = arg;
+ OSSL_STORE_INFO **v = &cbdata->v;
+ OSSL_STORE_CTX *ctx = cbdata->ctx;
+ const OSSL_PROVIDER *provider =
+ OSSL_STORE_LOADER_get0_provider(ctx->fetched_loader);
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(provider);
+ const char *propq = ctx->properties;
+ const OSSL_PARAM *p;
+ struct extracted_param_data_st helper_data;
+
+ memset(&helper_data, 0, sizeof(helper_data));
+ helper_data.object_type = OSSL_OBJECT_UNKNOWN;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_TYPE)) != NULL
+ && !OSSL_PARAM_get_int(p, &helper_data.object_type))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA_TYPE);
+ if (p != NULL
+ && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.data_type))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA);
+ if (p != NULL
+ && !OSSL_PARAM_get_octet_string_ptr(p, &helper_data.octet_data,
+ &helper_data.octet_data_size)
+ && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.utf8_data))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA_STRUCTURE);
+ if (p != NULL
+ && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.data_structure))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_REFERENCE);
+ if (p != NULL && !OSSL_PARAM_get_octet_string_ptr(p, &helper_data.ref,
+ &helper_data.ref_size))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DESC);
+ if (p != NULL && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.desc))
+ return 0;
+
+ /*
+ * The helper functions return 0 on actual errors, otherwise 1, even if
+ * they didn't fill out |*v|.
+ */
+ ERR_set_mark();
+ if (*v == NULL && !try_name(&helper_data, v))
+ goto err;
+ ERR_pop_to_mark();
+ ERR_set_mark();
+ if (*v == NULL && !try_key(&helper_data, v, ctx, provider, libctx, propq))
+ goto err;
+ ERR_pop_to_mark();
+ ERR_set_mark();
+ if (*v == NULL && !try_cert(&helper_data, v, libctx, propq))
+ goto err;
+ ERR_pop_to_mark();
+ ERR_set_mark();
+ if (*v == NULL && !try_crl(&helper_data, v, libctx, propq))
+ goto err;
+ ERR_pop_to_mark();
+ ERR_set_mark();
+ if (*v == NULL && !try_pkcs12(&helper_data, v, ctx, libctx, propq))
+ goto err;
+ ERR_pop_to_mark();
+
+ if (*v == NULL)
+ ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_UNSUPPORTED);
+
+ return (*v != NULL);
+ err:
+ ERR_clear_last_mark();
+ return 0;
+}
+
+static int try_name(struct extracted_param_data_st *data, OSSL_STORE_INFO **v)
+{
+ if (data->object_type == OSSL_OBJECT_NAME) {
+ char *newname = NULL, *newdesc = NULL;
+
+ if (data->utf8_data == NULL)
+ return 0;
+ if ((newname = OPENSSL_strdup(data->utf8_data)) == NULL
+ || (data->desc != NULL
+ && (newdesc = OPENSSL_strdup(data->desc)) == NULL)
+ || (*v = OSSL_STORE_INFO_new_NAME(newname)) == NULL) {
+ OPENSSL_free(newname);
+ OPENSSL_free(newdesc);
+ return 0;
+ }
+ OSSL_STORE_INFO_set0_NAME_description(*v, newdesc);
+ }
+ return 1;
+}
+
+/*
+ * For the rest of the object types, the provider code may not know what
+ * type of data it gave us, so we may need to figure that out on our own.
+ * Therefore, we do check for OSSL_OBJECT_UNKNOWN everywhere below, and
+ * only return 0 on error if the object type is known.
+ */
+
+static EVP_PKEY *try_key_ref(struct extracted_param_data_st *data,
+ OSSL_STORE_CTX *ctx,
+ const OSSL_PROVIDER *provider,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ EVP_PKEY *pk = NULL;
+ EVP_KEYMGMT *keymgmt = NULL;
+ void *keydata = NULL;
+ int try_fallback = 2;
+
+ /* If we have an object reference, we must have a data type */
+ if (data->data_type == NULL)
+ return 0;
+
+ keymgmt = EVP_KEYMGMT_fetch(libctx, data->data_type, propq);
+ ERR_set_mark();
+ while (keymgmt != NULL && keydata == NULL && try_fallback-- > 0) {
+ /*
+ * There are two possible cases
+ *
+ * 1. The keymgmt is from the same provider as the loader,
+ * so we can use evp_keymgmt_load()
+ * 2. The keymgmt is from another provider, then we must
+ * do the export/import dance.
+ */
+ if (EVP_KEYMGMT_get0_provider(keymgmt) == provider) {
+ /* no point trying fallback here */
+ try_fallback = 0;
+ keydata = evp_keymgmt_load(keymgmt, data->ref, data->ref_size);
+ } else {
+ struct evp_keymgmt_util_try_import_data_st import_data;
+ OSSL_FUNC_store_export_object_fn *export_object =
+ ctx->fetched_loader->p_export_object;
+
+ import_data.keymgmt = keymgmt;
+ import_data.keydata = NULL;
+ import_data.selection = OSSL_KEYMGMT_SELECT_ALL;
+
+ if (export_object != NULL) {
+ /*
+ * No need to check for errors here, the value of
+ * |import_data.keydata| is as much an indicator.
+ */
+ (void)export_object(ctx->loader_ctx,
+ data->ref, data->ref_size,
+ &evp_keymgmt_util_try_import,
+ &import_data);
+ }
+
+ keydata = import_data.keydata;
+ }
+
+ if (keydata == NULL && try_fallback > 0) {
+ EVP_KEYMGMT_free(keymgmt);
+ keymgmt = evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)provider,
+ data->data_type, propq);
+ if (keymgmt != NULL) {
+ ERR_pop_to_mark();
+ ERR_set_mark();
+ }
+ }
+ }
+ if (keydata != NULL) {
+ ERR_pop_to_mark();
+ pk = evp_keymgmt_util_make_pkey(keymgmt, keydata);
+ } else {
+ ERR_clear_last_mark();
+ }
+ EVP_KEYMGMT_free(keymgmt);
+
+ return pk;
+}
+
+static EVP_PKEY *try_key_value(struct extracted_param_data_st *data,
+ OSSL_STORE_CTX *ctx,
+ OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ EVP_PKEY *pk = NULL;
+ OSSL_DECODER_CTX *decoderctx = NULL;
+ const unsigned char *pdata = data->octet_data;
+ size_t pdatalen = data->octet_data_size;
+ int selection = 0;
+
+ switch (ctx->expected_type) {
+ case 0:
+ break;
+ case OSSL_STORE_INFO_PARAMS:
+ selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
+ break;
+ case OSSL_STORE_INFO_PUBKEY:
+ selection =
+ OSSL_KEYMGMT_SELECT_PUBLIC_KEY
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
+ break;
+ case OSSL_STORE_INFO_PKEY:
+ selection = OSSL_KEYMGMT_SELECT_ALL;
+ break;
+ default:
+ return NULL;
+ }
+
+ decoderctx =
+ OSSL_DECODER_CTX_new_for_pkey(&pk, NULL, data->data_structure,
+ data->data_type, selection, libctx,
+ propq);
+ (void)OSSL_DECODER_CTX_set_passphrase_cb(decoderctx, cb, cbarg);
+
+ /* No error if this couldn't be decoded */
+ (void)OSSL_DECODER_from_data(decoderctx, &pdata, &pdatalen);
+
+ OSSL_DECODER_CTX_free(decoderctx);
+
+ return pk;
+}
+
+typedef OSSL_STORE_INFO *store_info_new_fn(EVP_PKEY *);
+
+static EVP_PKEY *try_key_value_legacy(struct extracted_param_data_st *data,
+ store_info_new_fn **store_info_new,
+ OSSL_STORE_CTX *ctx,
+ OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ EVP_PKEY *pk = NULL;
+ const unsigned char *der = data->octet_data, *derp;
+ long der_len = (long)data->octet_data_size;
+
+ /* Try PUBKEY first, that's a real easy target */
+ if (ctx->expected_type == 0
+ || ctx->expected_type == OSSL_STORE_INFO_PUBKEY) {
+ derp = der;
+ pk = d2i_PUBKEY_ex(NULL, &derp, der_len, libctx, propq);
+
+ if (pk != NULL)
+ *store_info_new = OSSL_STORE_INFO_new_PUBKEY;
+ }
+
+ /* Try private keys next */
+ if (pk == NULL
+ && (ctx->expected_type == 0
+ || ctx->expected_type == OSSL_STORE_INFO_PKEY)) {
+ unsigned char *new_der = NULL;
+ X509_SIG *p8 = NULL;
+ PKCS8_PRIV_KEY_INFO *p8info = NULL;
+
+ /* See if it's an encrypted PKCS#8 and decrypt it. */
+ derp = der;
+ p8 = d2i_X509_SIG(NULL, &derp, der_len);
+
+ if (p8 != NULL) {
+ char pbuf[PEM_BUFSIZE];
+ size_t plen = 0;
+
+ if (!cb(pbuf, sizeof(pbuf), &plen, NULL, cbarg)) {
+ ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_BAD_PASSWORD_READ);
+ } else {
+ const X509_ALGOR *alg = NULL;
+ const ASN1_OCTET_STRING *oct = NULL;
+ int len = 0;
+
+ X509_SIG_get0(p8, &alg, &oct);
+
+ /*
+ * No need to check the returned value, |new_der|
+ * will be NULL on error anyway.
+ */
+ PKCS12_pbe_crypt(alg, pbuf, plen,
+ oct->data, oct->length,
+ &new_der, &len, 0);
+ der_len = len;
+ der = new_der;
+ }
+ X509_SIG_free(p8);
+ }
+
+ /*
+ * If the encrypted PKCS#8 couldn't be decrypted,
+ * |der| is NULL
+ */
+ if (der != NULL) {
+ /* Try to unpack an unencrypted PKCS#8, that's easy */
+ derp = der;
+ p8info = d2i_PKCS8_PRIV_KEY_INFO(NULL, &derp, der_len);
+
+ if (p8info != NULL) {
+ pk = EVP_PKCS82PKEY_ex(p8info, libctx, propq);
+ PKCS8_PRIV_KEY_INFO_free(p8info);
+ }
+ }
+
+ if (pk != NULL)
+ *store_info_new = OSSL_STORE_INFO_new_PKEY;
+
+ OPENSSL_free(new_der);
+ }
+
+ return pk;
+}
+
+static int try_key(struct extracted_param_data_st *data, OSSL_STORE_INFO **v,
+ OSSL_STORE_CTX *ctx, const OSSL_PROVIDER *provider,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ store_info_new_fn *store_info_new = NULL;
+
+ if (data->object_type == OSSL_OBJECT_UNKNOWN
+ || data->object_type == OSSL_OBJECT_PKEY) {
+ EVP_PKEY *pk = NULL;
+
+ /* Prefer key by reference than key by value */
+ if (data->object_type == OSSL_OBJECT_PKEY && data->ref != NULL) {
+ pk = try_key_ref(data, ctx, provider, libctx, propq);
+
+ /*
+ * If for some reason we couldn't get a key, it's an error.
+ * It indicates that while decoders could make a key reference,
+ * the keymgmt somehow couldn't handle it, or doesn't have a
+ * OSSL_FUNC_keymgmt_load function.
+ */
+ if (pk == NULL)
+ return 0;
+ } else if (data->octet_data != NULL) {
+ OSSL_PASSPHRASE_CALLBACK *cb = ossl_pw_passphrase_callback_dec;
+ void *cbarg = &ctx->pwdata;
+
+ pk = try_key_value(data, ctx, cb, cbarg, libctx, propq);
+
+ /*
+ * Desperate last maneuver, in case the decoders don't support
+ * the data we have, then we try on our own to at least get an
+ * engine provided legacy key.
+ * This is the same as der2key_decode() does, but in a limited
+ * way and within the walls of libcrypto.
+ */
+ if (pk == NULL)
+ pk = try_key_value_legacy(data, &store_info_new, ctx,
+ cb, cbarg, libctx, propq);
+ }
+
+ if (pk != NULL) {
+ data->object_type = OSSL_OBJECT_PKEY;
+
+ if (store_info_new == NULL) {
+ /*
+ * We determined the object type for OSSL_STORE_INFO, which
+ * makes an explicit difference between an EVP_PKEY with just
+ * (domain) parameters and an EVP_PKEY with actual key
+ * material.
+ * The logic is that an EVP_PKEY with actual key material
+ * always has the public half.
+ */
+ if (evp_keymgmt_util_has(pk, OSSL_KEYMGMT_SELECT_PRIVATE_KEY))
+ store_info_new = OSSL_STORE_INFO_new_PKEY;
+ else if (evp_keymgmt_util_has(pk,
+ OSSL_KEYMGMT_SELECT_PUBLIC_KEY))
+ store_info_new = OSSL_STORE_INFO_new_PUBKEY;
+ else
+ store_info_new = OSSL_STORE_INFO_new_PARAMS;
+ }
+ *v = store_info_new(pk);
+ }
+
+ if (*v == NULL)
+ EVP_PKEY_free(pk);
+ }
+
+ return 1;
+}
+
+static int try_cert(struct extracted_param_data_st *data, OSSL_STORE_INFO **v,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ if (data->object_type == OSSL_OBJECT_UNKNOWN
+ || data->object_type == OSSL_OBJECT_CERT) {
+ /*
+ * In most cases, we can try to interpret the serialized
+ * data as a trusted cert (X509 + X509_AUX) and fall back
+ * to reading it as a normal cert (just X509), but if
+ * |data_type| (the PEM name) specifically declares it as a
+ * trusted cert, then no fallback should be engaged.
+ * |ignore_trusted| tells if the fallback can be used (1)
+ * or not (0).
+ */
+ int ignore_trusted = 1;
+ X509 *cert = X509_new_ex(libctx, propq);
+
+ if (cert == NULL)
+ return 0;
+
+ /* If we have a data type, it should be a PEM name */
+ if (data->data_type != NULL
+ && (OPENSSL_strcasecmp(data->data_type, PEM_STRING_X509_TRUSTED) == 0))
+ ignore_trusted = 0;
+
+ if (d2i_X509_AUX(&cert, (const unsigned char **)&data->octet_data,
+ data->octet_data_size) == NULL
+ && (!ignore_trusted
+ || d2i_X509(&cert, (const unsigned char **)&data->octet_data,
+ data->octet_data_size) == NULL)) {
+ X509_free(cert);
+ cert = NULL;
+ }
+
+ if (cert != NULL) {
+ /* We determined the object type */
+ data->object_type = OSSL_OBJECT_CERT;
+ *v = OSSL_STORE_INFO_new_CERT(cert);
+ if (*v == NULL)
+ X509_free(cert);
+ }
+ }
+
+ return 1;
+}
+
+static int try_crl(struct extracted_param_data_st *data, OSSL_STORE_INFO **v,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ if (data->object_type == OSSL_OBJECT_UNKNOWN
+ || data->object_type == OSSL_OBJECT_CRL) {
+ X509_CRL *crl;
+
+ crl = d2i_X509_CRL(NULL, (const unsigned char **)&data->octet_data,
+ data->octet_data_size);
+
+ if (crl != NULL)
+ /* We determined the object type */
+ data->object_type = OSSL_OBJECT_CRL;
+
+ if (crl != NULL && !ossl_x509_crl_set0_libctx(crl, libctx, propq)) {
+ X509_CRL_free(crl);
+ crl = NULL;
+ }
+
+ if (crl != NULL)
+ *v = OSSL_STORE_INFO_new_CRL(crl);
+ if (*v == NULL)
+ X509_CRL_free(crl);
+ }
+
+ return 1;
+}
+
+static int try_pkcs12(struct extracted_param_data_st *data, OSSL_STORE_INFO **v,
+ OSSL_STORE_CTX *ctx,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ int ok = 1;
+
+ /* There is no specific object type for PKCS12 */
+ if (data->object_type == OSSL_OBJECT_UNKNOWN) {
+ /* Initial parsing */
+ PKCS12 *p12;
+
+ p12 = d2i_PKCS12(NULL, (const unsigned char **)&data->octet_data,
+ data->octet_data_size);
+
+ if (p12 != NULL) {
+ char *pass = NULL;
+ char tpass[PEM_BUFSIZE + 1];
+ size_t tpass_len;
+ EVP_PKEY *pkey = NULL;
+ X509 *cert = NULL;
+ STACK_OF(X509) *chain = NULL;
+
+ data->object_type = OSSL_OBJECT_PKCS12;
+
+ ok = 0; /* Assume decryption or parse error */
+
+ if (PKCS12_verify_mac(p12, "", 0)
+ || PKCS12_verify_mac(p12, NULL, 0)) {
+ pass = "";
+ } else {
+ static char prompt_info[] = "PKCS12 import pass phrase";
+ OSSL_PARAM pw_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_PASSPHRASE_PARAM_INFO,
+ prompt_info,
+ sizeof(prompt_info) - 1),
+ OSSL_PARAM_END
+ };
+
+ if (!ossl_pw_get_passphrase(tpass, sizeof(tpass) - 1,
+ &tpass_len,
+ pw_params, 0, &ctx->pwdata)) {
+ ERR_raise(ERR_LIB_OSSL_STORE,
+ OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR);
+ goto p12_end;
+ }
+ pass = tpass;
+ /*
+ * ossl_pw_get_passphrase() does not NUL terminate but
+ * we must do it for PKCS12_parse()
+ */
+ pass[tpass_len] = '\0';
+ if (!PKCS12_verify_mac(p12, pass, tpass_len)) {
+ ERR_raise_data(ERR_LIB_OSSL_STORE,
+ OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC,
+ tpass_len == 0 ? "empty password" :
+ "maybe wrong password");
+ goto p12_end;
+ }
+ }
+
+ if (PKCS12_parse(p12, pass, &pkey, &cert, &chain)) {
+ STACK_OF(OSSL_STORE_INFO) *infos = NULL;
+ OSSL_STORE_INFO *osi_pkey = NULL;
+ OSSL_STORE_INFO *osi_cert = NULL;
+ OSSL_STORE_INFO *osi_ca = NULL;
+
+ ok = 1; /* Parsing went through correctly! */
+
+ if ((infos = sk_OSSL_STORE_INFO_new_null()) != NULL) {
+ if (pkey != NULL) {
+ if ((osi_pkey = OSSL_STORE_INFO_new_PKEY(pkey)) != NULL
+ /* clearing pkey here avoids case distinctions */
+ && (pkey = NULL) == NULL
+ && sk_OSSL_STORE_INFO_push(infos, osi_pkey) != 0)
+ osi_pkey = NULL;
+ else
+ ok = 0;
+ }
+ if (ok && cert != NULL) {
+ if ((osi_cert = OSSL_STORE_INFO_new_CERT(cert)) != NULL
+ /* clearing cert here avoids case distinctions */
+ && (cert = NULL) == NULL
+ && sk_OSSL_STORE_INFO_push(infos, osi_cert) != 0)
+ osi_cert = NULL;
+ else
+ ok = 0;
+ }
+ while (ok && sk_X509_num(chain) > 0) {
+ X509 *ca = sk_X509_value(chain, 0);
+
+ if ((osi_ca = OSSL_STORE_INFO_new_CERT(ca)) != NULL
+ && sk_X509_shift(chain) != NULL
+ && sk_OSSL_STORE_INFO_push(infos, osi_ca) != 0)
+ osi_ca = NULL;
+ else
+ ok = 0;
+ }
+ }
+ EVP_PKEY_free(pkey);
+ X509_free(cert);
+ sk_X509_pop_free(chain, X509_free);
+ OSSL_STORE_INFO_free(osi_pkey);
+ OSSL_STORE_INFO_free(osi_cert);
+ OSSL_STORE_INFO_free(osi_ca);
+ if (!ok) {
+ sk_OSSL_STORE_INFO_pop_free(infos, OSSL_STORE_INFO_free);
+ infos = NULL;
+ }
+ ctx->cached_info = infos;
+ }
+ p12_end:
+ OPENSSL_cleanse(tpass, sizeof(tpass));
+ PKCS12_free(p12);
+ }
+ *v = sk_OSSL_STORE_INFO_shift(ctx->cached_info);
+ }
+
+ return ok;
+}
diff --git a/crypto/store/store_strings.c b/crypto/store/store_strings.c
index 76cf3164837c..3d4a8ea73079 100644
--- a/crypto/store/store_strings.c
+++ b/crypto/store/store_strings.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,6 +12,7 @@
static char *type_strings[] = {
"Name", /* OSSL_STORE_INFO_NAME */
"Parameters", /* OSSL_STORE_INFO_PARAMS */
+ "Public key", /* OSSL_STORE_INFO_PUBKEY */
"Pkey", /* OSSL_STORE_INFO_PKEY */
"Certificate", /* OSSL_STORE_INFO_CERT */
"CRL" /* OSSL_STORE_INFO_CRL */
diff --git a/crypto/threads_lib.c b/crypto/threads_lib.c
new file mode 100644
index 000000000000..0c7162392df8
--- /dev/null
+++ b/crypto/threads_lib.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+#include <openssl/crypto.h>
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+
+void OPENSSL_fork_prepare(void)
+{
+}
+
+void OPENSSL_fork_parent(void)
+{
+}
+
+void OPENSSL_fork_child(void)
+{
+}
+
+#endif
diff --git a/crypto/threads_none.c b/crypto/threads_none.c
index aaaaae872a9b..2570efde2378 100644
--- a/crypto/threads_none.c
+++ b/crypto/threads_none.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -31,14 +31,14 @@ CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
return lock;
}
-int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
+__owur int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
{
if (!ossl_assert(*(unsigned int *)lock == 1))
return 0;
return 1;
}
-int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
+__owur int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
{
if (!ossl_assert(*(unsigned int *)lock == 1))
return 0;
@@ -133,6 +133,22 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
return 1;
}
+int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret,
+ CRYPTO_RWLOCK *lock)
+{
+ *val |= op;
+ *ret = *val;
+
+ return 1;
+}
+
+int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock)
+{
+ *ret = *val;
+
+ return 1;
+}
+
int openssl_init_fork_handlers(void)
{
return 0;
diff --git a/crypto/threads_pthread.c b/crypto/threads_pthread.c
index 1774a2b2ac16..bfc05a4e878c 100644
--- a/crypto/threads_pthread.c
+++ b/crypto/threads_pthread.c
@@ -1,15 +1,34 @@
/*
- * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use the OPENSSL_fork_*() deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <openssl/crypto.h>
#include "internal/cryptlib.h"
+#if defined(__sun)
+# include <atomic.h>
+#endif
+
+#if defined(__apple_build_version__) && __apple_build_version__ < 6000000
+/*
+ * OS/X 10.7 and 10.8 had a weird version of clang which has __ATOMIC_ACQUIRE and
+ * __ATOMIC_ACQ_REL but which expects only one parameter for __atomic_is_lock_free()
+ * rather than two which has signature __atomic_is_lock_free(sizeof(_Atomic(T))).
+ * All of this makes impossible to use __atomic_is_lock_free here.
+ *
+ * See: https://github.com/llvm/llvm-project/commit/a4c2602b714e6c6edb98164550a5ae829b2de760
+ */
+#define BROKEN_CLANG_ATOMICS
+#endif
+
#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && !defined(OPENSSL_SYS_WINDOWS)
# if defined(OPENSSL_SYS_UNIX)
@@ -17,6 +36,8 @@
# include <unistd.h>
#endif
+# include <assert.h>
+
# ifdef PTHREAD_RWLOCK_INITIALIZER
# define USE_RWLOCK
# endif
@@ -44,8 +65,19 @@ CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
return NULL;
}
+ /*
+ * We don't use recursive mutexes, but try to catch errors if we do.
+ */
pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+# if !defined (__TANDEM) && !defined (_SPT_MODEL_)
+# if !defined(NDEBUG) && !defined(OPENSSL_NO_MUTEX_ERRORCHECK)
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
+# else
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
+# endif
+# else
+ /* The SPT Thread Library does not define MUTEX attributes. */
+# endif
if (pthread_mutex_init(lock, &attr) != 0) {
pthread_mutexattr_destroy(&attr);
@@ -59,27 +91,31 @@ CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
return lock;
}
-int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
+__owur int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
{
# ifdef USE_RWLOCK
if (pthread_rwlock_rdlock(lock) != 0)
return 0;
# else
- if (pthread_mutex_lock(lock) != 0)
+ if (pthread_mutex_lock(lock) != 0) {
+ assert(errno != EDEADLK && errno != EBUSY);
return 0;
+ }
# endif
return 1;
}
-int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
+__owur int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
{
# ifdef USE_RWLOCK
if (pthread_rwlock_wrlock(lock) != 0)
return 0;
# else
- if (pthread_mutex_lock(lock) != 0)
+ if (pthread_mutex_lock(lock) != 0) {
+ assert(errno != EDEADLK && errno != EBUSY);
return 0;
+ }
# endif
return 1;
@@ -91,8 +127,10 @@ int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock)
if (pthread_rwlock_unlock(lock) != 0)
return 0;
# else
- if (pthread_mutex_unlock(lock) != 0)
+ if (pthread_mutex_unlock(lock) != 0) {
+ assert(errno != EPERM);
return 0;
+ }
# endif
return 1;
@@ -162,13 +200,19 @@ int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b)
int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
{
-# if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL)
+# if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL) && !defined(BROKEN_CLANG_ATOMICS)
if (__atomic_is_lock_free(sizeof(*val), val)) {
*ret = __atomic_add_fetch(val, amount, __ATOMIC_ACQ_REL);
return 1;
}
+# elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11))
+ /* This will work for all future Solaris versions. */
+ if (ret != NULL) {
+ *ret = atomic_add_int_nv((volatile unsigned int *)val, amount);
+ return 1;
+ }
# endif
- if (!CRYPTO_THREAD_write_lock(lock))
+ if (lock == NULL || !CRYPTO_THREAD_write_lock(lock))
return 0;
*val += amount;
@@ -180,24 +224,60 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
return 1;
}
-# ifdef OPENSSL_SYS_UNIX
-static pthread_once_t fork_once_control = PTHREAD_ONCE_INIT;
-
-static void fork_once_func(void)
+int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret,
+ CRYPTO_RWLOCK *lock)
{
- pthread_atfork(OPENSSL_fork_prepare,
- OPENSSL_fork_parent, OPENSSL_fork_child);
-}
+# if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL) && !defined(BROKEN_CLANG_ATOMICS)
+ if (__atomic_is_lock_free(sizeof(*val), val)) {
+ *ret = __atomic_or_fetch(val, op, __ATOMIC_ACQ_REL);
+ return 1;
+ }
+# elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11))
+ /* This will work for all future Solaris versions. */
+ if (ret != NULL) {
+ *ret = atomic_or_64_nv(val, op);
+ return 1;
+ }
# endif
+ if (lock == NULL || !CRYPTO_THREAD_write_lock(lock))
+ return 0;
+ *val |= op;
+ *ret = *val;
-int openssl_init_fork_handlers(void)
+ if (!CRYPTO_THREAD_unlock(lock))
+ return 0;
+
+ return 1;
+}
+
+int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock)
{
-# ifdef OPENSSL_SYS_UNIX
- if (pthread_once(&fork_once_control, fork_once_func) == 0)
+# if defined(__GNUC__) && defined(__ATOMIC_ACQUIRE) && !defined(BROKEN_CLANG_ATOMICS)
+ if (__atomic_is_lock_free(sizeof(*val), val)) {
+ __atomic_load(val, ret, __ATOMIC_ACQUIRE);
+ return 1;
+ }
+# elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11))
+ /* This will work for all future Solaris versions. */
+ if (ret != NULL) {
+ *ret = atomic_or_64_nv(val, 0);
return 1;
+ }
# endif
- return 0;
+ if (lock == NULL || !CRYPTO_THREAD_read_lock(lock))
+ return 0;
+ *ret = *val;
+ if (!CRYPTO_THREAD_unlock(lock))
+ return 0;
+
+ return 1;
+}
+# ifndef FIPS_MODULE
+int openssl_init_fork_handlers(void)
+{
+ return 1;
}
+# endif /* FIPS_MODULE */
int openssl_get_fork_id(void)
{
diff --git a/crypto/trace.c b/crypto/trace.c
new file mode 100644
index 000000000000..3df9b5a51e99
--- /dev/null
+++ b/crypto/trace.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "internal/thread_once.h"
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/trace.h>
+#include "internal/bio.h"
+#include "internal/nelem.h"
+#include "internal/refcount.h"
+#include "crypto/cryptlib.h"
+
+#ifndef OPENSSL_NO_TRACE
+
+static CRYPTO_RWLOCK *trace_lock = NULL;
+
+static const BIO *current_channel = NULL;
+
+/*-
+ * INTERNAL TRACE CHANNEL IMPLEMENTATION
+ *
+ * For our own flexibility, all trace categories are associated with a
+ * BIO sink object, also called the trace channel. Instead of a BIO object,
+ * the application can also provide a callback function, in which case an
+ * internal trace channel is attached, which simply calls the registered
+ * callback function.
+ */
+static int trace_write(BIO *b, const char *buf,
+ size_t num, size_t *written);
+static int trace_puts(BIO *b, const char *str);
+static long trace_ctrl(BIO *channel, int cmd, long argl, void *argp);
+static int trace_free(BIO *b);
+
+static const BIO_METHOD trace_method = {
+ BIO_TYPE_SOURCE_SINK,
+ "trace",
+ trace_write,
+ NULL, /* old write */
+ NULL, /* read_ex */
+ NULL, /* read */
+ trace_puts,
+ NULL, /* gets */
+ trace_ctrl, /* ctrl */
+ NULL, /* create */
+ trace_free, /* free */
+ NULL, /* callback_ctrl */
+};
+
+struct trace_data_st {
+ OSSL_trace_cb callback;
+ int category;
+ void *data;
+};
+
+static int trace_write(BIO *channel,
+ const char *buf, size_t num, size_t *written)
+{
+ struct trace_data_st *ctx = BIO_get_data(channel);
+ size_t cnt = ctx->callback(buf, num, ctx->category, OSSL_TRACE_CTRL_WRITE,
+ ctx->data);
+
+ *written = cnt;
+ return cnt != 0;
+}
+
+static int trace_puts(BIO *channel, const char *str)
+{
+ size_t written;
+
+ if (trace_write(channel, str, strlen(str), &written))
+ return (int)written;
+
+ return EOF;
+}
+
+static long trace_ctrl(BIO *channel, int cmd, long argl, void *argp)
+{
+ struct trace_data_st *ctx = BIO_get_data(channel);
+
+ switch (cmd) {
+ case OSSL_TRACE_CTRL_BEGIN:
+ case OSSL_TRACE_CTRL_END:
+ /* We know that the callback is likely to return 0 here */
+ ctx->callback("", 0, ctx->category, cmd, ctx->data);
+ return 1;
+ default:
+ break;
+ }
+ return -2; /* Unsupported */
+}
+
+static int trace_free(BIO *channel)
+{
+ if (channel == NULL)
+ return 0;
+ OPENSSL_free(BIO_get_data(channel));
+ return 1;
+}
+#endif
+
+/*-
+ * TRACE
+ */
+
+/* Helper struct and macro to get name string to number mapping */
+struct trace_category_st {
+ const char * const name;
+ const int num;
+};
+#define TRACE_CATEGORY_(name) { #name, OSSL_TRACE_CATEGORY_##name }
+
+static const struct trace_category_st
+ trace_categories[OSSL_TRACE_CATEGORY_NUM] = {
+ TRACE_CATEGORY_(ALL),
+ TRACE_CATEGORY_(TRACE),
+ TRACE_CATEGORY_(INIT),
+ TRACE_CATEGORY_(TLS),
+ TRACE_CATEGORY_(TLS_CIPHER),
+ TRACE_CATEGORY_(CONF),
+ TRACE_CATEGORY_(ENGINE_TABLE),
+ TRACE_CATEGORY_(ENGINE_REF_COUNT),
+ TRACE_CATEGORY_(PKCS5V2),
+ TRACE_CATEGORY_(PKCS12_KEYGEN),
+ TRACE_CATEGORY_(PKCS12_DECRYPT),
+ TRACE_CATEGORY_(X509V3_POLICY),
+ TRACE_CATEGORY_(BN_CTX),
+ TRACE_CATEGORY_(CMP),
+ TRACE_CATEGORY_(STORE),
+ TRACE_CATEGORY_(DECODER),
+ TRACE_CATEGORY_(ENCODER),
+ TRACE_CATEGORY_(REF_COUNT)
+};
+
+const char *OSSL_trace_get_category_name(int num)
+{
+ if (num < 0 || (size_t)num >= OSSL_NELEM(trace_categories))
+ return NULL;
+ /*
+ * Partial check that OSSL_TRACE_CATEGORY_... macros
+ * are synced with trace_categories array
+ */
+ if (!ossl_assert(trace_categories[num].name != NULL)
+ || !ossl_assert(trace_categories[num].num == num))
+ return NULL;
+ return trace_categories[num].name;
+}
+
+int OSSL_trace_get_category_num(const char *name)
+{
+ size_t i;
+
+ if (name == NULL)
+ return -1;
+
+ for (i = 0; i < OSSL_NELEM(trace_categories); i++)
+ if (OPENSSL_strcasecmp(name, trace_categories[i].name) == 0)
+ return trace_categories[i].num;
+
+ return -1; /* not found */
+}
+
+#ifndef OPENSSL_NO_TRACE
+
+/* We use one trace channel for each trace category */
+static struct {
+ enum { SIMPLE_CHANNEL, CALLBACK_CHANNEL } type;
+ BIO *bio;
+ char *prefix;
+ char *suffix;
+} trace_channels[OSSL_TRACE_CATEGORY_NUM] = {
+ { 0, NULL, NULL, NULL },
+};
+
+#endif
+
+#ifndef OPENSSL_NO_TRACE
+
+enum {
+ CHANNEL,
+ PREFIX,
+ SUFFIX
+};
+
+static int trace_attach_cb(int category, int type, const void *data)
+{
+ switch (type) {
+ case CHANNEL:
+ OSSL_TRACE2(TRACE, "Attach channel %p to category '%s'\n",
+ data, trace_categories[category].name);
+ break;
+ case PREFIX:
+ OSSL_TRACE2(TRACE, "Attach prefix \"%s\" to category '%s'\n",
+ (const char *)data, trace_categories[category].name);
+ break;
+ case SUFFIX:
+ OSSL_TRACE2(TRACE, "Attach suffix \"%s\" to category '%s'\n",
+ (const char *)data, trace_categories[category].name);
+ break;
+ default: /* No clue */
+ break;
+ }
+ return 1;
+}
+
+static int trace_detach_cb(int category, int type, const void *data)
+{
+ switch (type) {
+ case CHANNEL:
+ OSSL_TRACE2(TRACE, "Detach channel %p from category '%s'\n",
+ data, trace_categories[category].name);
+ break;
+ case PREFIX:
+ OSSL_TRACE2(TRACE, "Detach prefix \"%s\" from category '%s'\n",
+ (const char *)data, trace_categories[category].name);
+ break;
+ case SUFFIX:
+ OSSL_TRACE2(TRACE, "Detach suffix \"%s\" from category '%s'\n",
+ (const char *)data, trace_categories[category].name);
+ break;
+ default: /* No clue */
+ break;
+ }
+ return 1;
+}
+
+static int do_ossl_trace_init(void);
+static CRYPTO_ONCE trace_inited = CRYPTO_ONCE_STATIC_INIT;
+DEFINE_RUN_ONCE_STATIC(ossl_trace_init)
+{
+ return do_ossl_trace_init();
+}
+
+static int set_trace_data(int category, int type, BIO **channel,
+ const char **prefix, const char **suffix,
+ int (*attach_cb)(int, int, const void *),
+ int (*detach_cb)(int, int, const void *))
+{
+ BIO *curr_channel = NULL;
+ char *curr_prefix = NULL;
+ char *curr_suffix = NULL;
+
+ /* Ensure do_ossl_trace_init() is called once */
+ if (!RUN_ONCE(&trace_inited, ossl_trace_init))
+ return 0;
+
+ curr_channel = trace_channels[category].bio;
+ curr_prefix = trace_channels[category].prefix;
+ curr_suffix = trace_channels[category].suffix;
+
+ /* Make sure to run the detach callback first on all data */
+ if (prefix != NULL && curr_prefix != NULL) {
+ detach_cb(category, PREFIX, curr_prefix);
+ }
+
+ if (suffix != NULL && curr_suffix != NULL) {
+ detach_cb(category, SUFFIX, curr_suffix);
+ }
+
+ if (channel != NULL && curr_channel != NULL) {
+ detach_cb(category, CHANNEL, curr_channel);
+ }
+
+ /* After detach callbacks are done, clear data where appropriate */
+ if (prefix != NULL && curr_prefix != NULL) {
+ OPENSSL_free(curr_prefix);
+ trace_channels[category].prefix = NULL;
+ }
+
+ if (suffix != NULL && curr_suffix != NULL) {
+ OPENSSL_free(curr_suffix);
+ trace_channels[category].suffix = NULL;
+ }
+
+ if (channel != NULL && curr_channel != NULL) {
+ BIO_free(curr_channel);
+ trace_channels[category].type = 0;
+ trace_channels[category].bio = NULL;
+ }
+
+ /* Before running callbacks are done, set new data where appropriate */
+ if (prefix != NULL && *prefix != NULL) {
+ if ((curr_prefix = OPENSSL_strdup(*prefix)) == NULL)
+ return 0;
+ trace_channels[category].prefix = curr_prefix;
+ }
+
+ if (suffix != NULL && *suffix != NULL) {
+ if ((curr_suffix = OPENSSL_strdup(*suffix)) == NULL)
+ return 0;
+ trace_channels[category].suffix = curr_suffix;
+ }
+
+ if (channel != NULL && *channel != NULL) {
+ trace_channels[category].type = type;
+ trace_channels[category].bio = *channel;
+ /*
+ * This must not be done before setting prefix/suffix,
+ * as those may fail, and then the caller is mislead to free *channel.
+ */
+ }
+
+ /* Finally, run the attach callback on the new data */
+ if (channel != NULL && *channel != NULL) {
+ attach_cb(category, CHANNEL, *channel);
+ }
+
+ if (prefix != NULL && *prefix != NULL) {
+ attach_cb(category, PREFIX, *prefix);
+ }
+
+ if (suffix != NULL && *suffix != NULL) {
+ attach_cb(category, SUFFIX, *suffix);
+ }
+
+ return 1;
+}
+
+static int do_ossl_trace_init(void)
+{
+ trace_lock = CRYPTO_THREAD_lock_new();
+ return trace_lock != NULL;
+}
+
+#endif
+
+void ossl_trace_cleanup(void)
+{
+#ifndef OPENSSL_NO_TRACE
+ int category;
+ BIO *channel = NULL;
+ const char *prefix = NULL;
+ const char *suffix = NULL;
+
+ for (category = 0; category < OSSL_TRACE_CATEGORY_NUM; category++) {
+ /* We force the TRACE category to be treated last */
+ if (category == OSSL_TRACE_CATEGORY_TRACE)
+ continue;
+ set_trace_data(category, 0, &channel, &prefix, &suffix,
+ trace_attach_cb, trace_detach_cb);
+ }
+ set_trace_data(OSSL_TRACE_CATEGORY_TRACE, 0, &channel,
+ &prefix, &suffix,
+ trace_attach_cb, trace_detach_cb);
+ CRYPTO_THREAD_lock_free(trace_lock);
+#endif
+}
+
+int OSSL_trace_set_channel(int category, BIO *channel)
+{
+#ifndef OPENSSL_NO_TRACE
+ if (category >= 0 && category < OSSL_TRACE_CATEGORY_NUM)
+ return set_trace_data(category, SIMPLE_CHANNEL, &channel, NULL, NULL,
+ trace_attach_cb, trace_detach_cb);
+#endif
+ return 0;
+}
+
+#ifndef OPENSSL_NO_TRACE
+static int trace_attach_w_callback_cb(int category, int type, const void *data)
+{
+ switch (type) {
+ case CHANNEL:
+ OSSL_TRACE2(TRACE,
+ "Attach channel %p to category '%s' (with callback)\n",
+ data, trace_categories[category].name);
+ break;
+ case PREFIX:
+ OSSL_TRACE2(TRACE, "Attach prefix \"%s\" to category '%s'\n",
+ (const char *)data, trace_categories[category].name);
+ break;
+ case SUFFIX:
+ OSSL_TRACE2(TRACE, "Attach suffix \"%s\" to category '%s'\n",
+ (const char *)data, trace_categories[category].name);
+ break;
+ default: /* No clue */
+ break;
+ }
+ return 1;
+}
+#endif
+
+int OSSL_trace_set_callback(int category, OSSL_trace_cb callback, void *data)
+{
+#ifndef OPENSSL_NO_TRACE
+ BIO *channel = NULL;
+ struct trace_data_st *trace_data = NULL;
+
+ if (category < 0 || category >= OSSL_TRACE_CATEGORY_NUM)
+ return 0;
+
+ if (callback != NULL) {
+ if ((channel = BIO_new(&trace_method)) == NULL
+ || (trace_data =
+ OPENSSL_zalloc(sizeof(struct trace_data_st))) == NULL)
+ goto err;
+
+ trace_data->callback = callback;
+ trace_data->category = category;
+ trace_data->data = data;
+
+ BIO_set_data(channel, trace_data);
+ }
+
+ if (!set_trace_data(category, CALLBACK_CHANNEL, &channel, NULL, NULL,
+ trace_attach_w_callback_cb, trace_detach_cb))
+ goto err;
+
+ return 1;
+
+ err:
+ BIO_free(channel);
+ OPENSSL_free(trace_data);
+#endif
+
+ return 0;
+}
+
+int OSSL_trace_set_prefix(int category, const char *prefix)
+{
+#ifndef OPENSSL_NO_TRACE
+ if (category >= 0 && category < OSSL_TRACE_CATEGORY_NUM)
+ return set_trace_data(category, 0, NULL, &prefix, NULL,
+ trace_attach_cb, trace_detach_cb);
+#endif
+ return 0;
+}
+
+int OSSL_trace_set_suffix(int category, const char *suffix)
+{
+#ifndef OPENSSL_NO_TRACE
+ if (category >= 0 && category < OSSL_TRACE_CATEGORY_NUM)
+ return set_trace_data(category, 0, NULL, NULL, &suffix,
+ trace_attach_cb, trace_detach_cb);
+#endif
+ return 0;
+}
+
+#ifndef OPENSSL_NO_TRACE
+static int ossl_trace_get_category(int category)
+{
+ if (category < 0 || category >= OSSL_TRACE_CATEGORY_NUM)
+ return -1;
+ if (trace_channels[category].bio != NULL)
+ return category;
+ return OSSL_TRACE_CATEGORY_ALL;
+}
+#endif
+
+int OSSL_trace_enabled(int category)
+{
+ int ret = 0;
+#ifndef OPENSSL_NO_TRACE
+ category = ossl_trace_get_category(category);
+ if (category >= 0)
+ ret = trace_channels[category].bio != NULL;
+#endif
+ return ret;
+}
+
+BIO *OSSL_trace_begin(int category)
+{
+ BIO *channel = NULL;
+#ifndef OPENSSL_NO_TRACE
+ char *prefix = NULL;
+
+ category = ossl_trace_get_category(category);
+ if (category < 0)
+ return NULL;
+
+ channel = trace_channels[category].bio;
+ prefix = trace_channels[category].prefix;
+
+ if (channel != NULL) {
+ if (!CRYPTO_THREAD_write_lock(trace_lock))
+ return NULL;
+ current_channel = channel;
+ switch (trace_channels[category].type) {
+ case SIMPLE_CHANNEL:
+ if (prefix != NULL) {
+ (void)BIO_puts(channel, prefix);
+ (void)BIO_puts(channel, "\n");
+ }
+ break;
+ case CALLBACK_CHANNEL:
+ (void)BIO_ctrl(channel, OSSL_TRACE_CTRL_BEGIN,
+ prefix == NULL ? 0 : strlen(prefix), prefix);
+ break;
+ }
+ }
+#endif
+ return channel;
+}
+
+void OSSL_trace_end(int category, BIO * channel)
+{
+#ifndef OPENSSL_NO_TRACE
+ char *suffix = NULL;
+
+ category = ossl_trace_get_category(category);
+ if (category < 0)
+ return;
+ suffix = trace_channels[category].suffix;
+ if (channel != NULL
+ && ossl_assert(channel == current_channel)) {
+ (void)BIO_flush(channel);
+ switch (trace_channels[category].type) {
+ case SIMPLE_CHANNEL:
+ if (suffix != NULL) {
+ (void)BIO_puts(channel, suffix);
+ (void)BIO_puts(channel, "\n");
+ }
+ break;
+ case CALLBACK_CHANNEL:
+ (void)BIO_ctrl(channel, OSSL_TRACE_CTRL_END,
+ suffix == NULL ? 0 : strlen(suffix), suffix);
+ break;
+ }
+ current_channel = NULL;
+ CRYPTO_THREAD_unlock(trace_lock);
+ }
+#endif
+}
diff --git a/crypto/ts/ts_asn1.c b/crypto/ts/ts_asn1.c
index 2840f5858acb..ba3195eab8b3 100644
--- a/crypto/ts/ts_asn1.c
+++ b/crypto/ts/ts_asn1.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -17,7 +17,7 @@ ASN1_SEQUENCE(TS_MSG_IMPRINT) = {
ASN1_SIMPLE(TS_MSG_IMPRINT, hashed_msg, ASN1_OCTET_STRING)
} static_ASN1_SEQUENCE_END(TS_MSG_IMPRINT)
-IMPLEMENT_ASN1_FUNCTIONS_const(TS_MSG_IMPRINT)
+IMPLEMENT_ASN1_FUNCTIONS(TS_MSG_IMPRINT)
IMPLEMENT_ASN1_DUP_FUNCTION(TS_MSG_IMPRINT)
TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_bio(BIO *bp, TS_MSG_IMPRINT **a)
{
@@ -25,9 +25,9 @@ TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_bio(BIO *bp, TS_MSG_IMPRINT **a)
d2i_TS_MSG_IMPRINT, bp, a);
}
-int i2d_TS_MSG_IMPRINT_bio(BIO *bp, TS_MSG_IMPRINT *a)
+int i2d_TS_MSG_IMPRINT_bio(BIO *bp, const TS_MSG_IMPRINT *a)
{
- return ASN1_i2d_bio_of_const(TS_MSG_IMPRINT, i2d_TS_MSG_IMPRINT, bp, a);
+ return ASN1_i2d_bio_of(TS_MSG_IMPRINT, i2d_TS_MSG_IMPRINT, bp, a);
}
#ifndef OPENSSL_NO_STDIO
TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT **a)
@@ -36,9 +36,9 @@ TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT **a)
d2i_TS_MSG_IMPRINT, fp, a);
}
-int i2d_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT *a)
+int i2d_TS_MSG_IMPRINT_fp(FILE *fp, const TS_MSG_IMPRINT *a)
{
- return ASN1_i2d_fp_of_const(TS_MSG_IMPRINT, i2d_TS_MSG_IMPRINT, fp, a);
+ return ASN1_i2d_fp_of(TS_MSG_IMPRINT, i2d_TS_MSG_IMPRINT, fp, a);
}
#endif
@@ -51,16 +51,16 @@ ASN1_SEQUENCE(TS_REQ) = {
ASN1_IMP_SEQUENCE_OF_OPT(TS_REQ, extensions, X509_EXTENSION, 0)
} static_ASN1_SEQUENCE_END(TS_REQ)
-IMPLEMENT_ASN1_FUNCTIONS_const(TS_REQ)
+IMPLEMENT_ASN1_FUNCTIONS(TS_REQ)
IMPLEMENT_ASN1_DUP_FUNCTION(TS_REQ)
TS_REQ *d2i_TS_REQ_bio(BIO *bp, TS_REQ **a)
{
return ASN1_d2i_bio_of(TS_REQ, TS_REQ_new, d2i_TS_REQ, bp, a);
}
-int i2d_TS_REQ_bio(BIO *bp, TS_REQ *a)
+int i2d_TS_REQ_bio(BIO *bp, const TS_REQ *a)
{
- return ASN1_i2d_bio_of_const(TS_REQ, i2d_TS_REQ, bp, a);
+ return ASN1_i2d_bio_of(TS_REQ, i2d_TS_REQ, bp, a);
}
#ifndef OPENSSL_NO_STDIO
TS_REQ *d2i_TS_REQ_fp(FILE *fp, TS_REQ **a)
@@ -68,9 +68,9 @@ TS_REQ *d2i_TS_REQ_fp(FILE *fp, TS_REQ **a)
return ASN1_d2i_fp_of(TS_REQ, TS_REQ_new, d2i_TS_REQ, fp, a);
}
-int i2d_TS_REQ_fp(FILE *fp, TS_REQ *a)
+int i2d_TS_REQ_fp(FILE *fp, const TS_REQ *a)
{
- return ASN1_i2d_fp_of_const(TS_REQ, i2d_TS_REQ, fp, a);
+ return ASN1_i2d_fp_of(TS_REQ, i2d_TS_REQ, fp, a);
}
#endif
@@ -80,7 +80,7 @@ ASN1_SEQUENCE(TS_ACCURACY) = {
ASN1_IMP_OPT(TS_ACCURACY, micros, ASN1_INTEGER, 1)
} static_ASN1_SEQUENCE_END(TS_ACCURACY)
-IMPLEMENT_ASN1_FUNCTIONS_const(TS_ACCURACY)
+IMPLEMENT_ASN1_FUNCTIONS(TS_ACCURACY)
IMPLEMENT_ASN1_DUP_FUNCTION(TS_ACCURACY)
ASN1_SEQUENCE(TS_TST_INFO) = {
@@ -96,7 +96,7 @@ ASN1_SEQUENCE(TS_TST_INFO) = {
ASN1_IMP_SEQUENCE_OF_OPT(TS_TST_INFO, extensions, X509_EXTENSION, 1)
} static_ASN1_SEQUENCE_END(TS_TST_INFO)
-IMPLEMENT_ASN1_FUNCTIONS_const(TS_TST_INFO)
+IMPLEMENT_ASN1_FUNCTIONS(TS_TST_INFO)
IMPLEMENT_ASN1_DUP_FUNCTION(TS_TST_INFO)
TS_TST_INFO *d2i_TS_TST_INFO_bio(BIO *bp, TS_TST_INFO **a)
{
@@ -104,9 +104,9 @@ TS_TST_INFO *d2i_TS_TST_INFO_bio(BIO *bp, TS_TST_INFO **a)
a);
}
-int i2d_TS_TST_INFO_bio(BIO *bp, TS_TST_INFO *a)
+int i2d_TS_TST_INFO_bio(BIO *bp, const TS_TST_INFO *a)
{
- return ASN1_i2d_bio_of_const(TS_TST_INFO, i2d_TS_TST_INFO, bp, a);
+ return ASN1_i2d_bio_of(TS_TST_INFO, i2d_TS_TST_INFO, bp, a);
}
#ifndef OPENSSL_NO_STDIO
TS_TST_INFO *d2i_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO **a)
@@ -115,9 +115,9 @@ TS_TST_INFO *d2i_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO **a)
a);
}
-int i2d_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO *a)
+int i2d_TS_TST_INFO_fp(FILE *fp, const TS_TST_INFO *a)
{
- return ASN1_i2d_fp_of_const(TS_TST_INFO, i2d_TS_TST_INFO, fp, a);
+ return ASN1_i2d_fp_of(TS_TST_INFO, i2d_TS_TST_INFO, fp, a);
}
#endif
@@ -127,7 +127,7 @@ ASN1_SEQUENCE(TS_STATUS_INFO) = {
ASN1_OPT(TS_STATUS_INFO, failure_info, ASN1_BIT_STRING)
} static_ASN1_SEQUENCE_END(TS_STATUS_INFO)
-IMPLEMENT_ASN1_FUNCTIONS_const(TS_STATUS_INFO)
+IMPLEMENT_ASN1_FUNCTIONS(TS_STATUS_INFO)
IMPLEMENT_ASN1_DUP_FUNCTION(TS_STATUS_INFO)
static int ts_resp_set_tst_info(TS_RESP *a)
@@ -138,18 +138,17 @@ static int ts_resp_set_tst_info(TS_RESP *a)
if (a->token) {
if (status != 0 && status != 1) {
- TSerr(TS_F_TS_RESP_SET_TST_INFO, TS_R_TOKEN_PRESENT);
+ ERR_raise(ERR_LIB_TS, TS_R_TOKEN_PRESENT);
return 0;
}
TS_TST_INFO_free(a->tst_info);
a->tst_info = PKCS7_to_TS_TST_INFO(a->token);
if (!a->tst_info) {
- TSerr(TS_F_TS_RESP_SET_TST_INFO,
- TS_R_PKCS7_TO_TS_TST_INFO_FAILED);
+ ERR_raise(ERR_LIB_TS, TS_R_PKCS7_TO_TS_TST_INFO_FAILED);
return 0;
}
} else if (status == 0 || status == 1) {
- TSerr(TS_F_TS_RESP_SET_TST_INFO, TS_R_TOKEN_NOT_PRESENT);
+ ERR_raise(ERR_LIB_TS, TS_R_TOKEN_NOT_PRESENT);
return 0;
}
@@ -176,7 +175,7 @@ ASN1_SEQUENCE_cb(TS_RESP, ts_resp_cb) = {
ASN1_OPT(TS_RESP, token, PKCS7),
} static_ASN1_SEQUENCE_END_cb(TS_RESP, TS_RESP)
-IMPLEMENT_ASN1_FUNCTIONS_const(TS_RESP)
+IMPLEMENT_ASN1_FUNCTIONS(TS_RESP)
IMPLEMENT_ASN1_DUP_FUNCTION(TS_RESP)
@@ -185,9 +184,9 @@ TS_RESP *d2i_TS_RESP_bio(BIO *bp, TS_RESP **a)
return ASN1_d2i_bio_of(TS_RESP, TS_RESP_new, d2i_TS_RESP, bp, a);
}
-int i2d_TS_RESP_bio(BIO *bp, TS_RESP *a)
+int i2d_TS_RESP_bio(BIO *bp, const TS_RESP *a)
{
- return ASN1_i2d_bio_of_const(TS_RESP, i2d_TS_RESP, bp, a);
+ return ASN1_i2d_bio_of(TS_RESP, i2d_TS_RESP, bp, a);
}
#ifndef OPENSSL_NO_STDIO
TS_RESP *d2i_TS_RESP_fp(FILE *fp, TS_RESP **a)
@@ -195,53 +194,12 @@ TS_RESP *d2i_TS_RESP_fp(FILE *fp, TS_RESP **a)
return ASN1_d2i_fp_of(TS_RESP, TS_RESP_new, d2i_TS_RESP, fp, a);
}
-int i2d_TS_RESP_fp(FILE *fp, TS_RESP *a)
+int i2d_TS_RESP_fp(FILE *fp, const TS_RESP *a)
{
- return ASN1_i2d_fp_of_const(TS_RESP, i2d_TS_RESP, fp, a);
+ return ASN1_i2d_fp_of(TS_RESP, i2d_TS_RESP, fp, a);
}
#endif
-ASN1_SEQUENCE(ESS_ISSUER_SERIAL) = {
- ASN1_SEQUENCE_OF(ESS_ISSUER_SERIAL, issuer, GENERAL_NAME),
- ASN1_SIMPLE(ESS_ISSUER_SERIAL, serial, ASN1_INTEGER)
-} static_ASN1_SEQUENCE_END(ESS_ISSUER_SERIAL)
-
-IMPLEMENT_ASN1_FUNCTIONS_const(ESS_ISSUER_SERIAL)
-IMPLEMENT_ASN1_DUP_FUNCTION(ESS_ISSUER_SERIAL)
-
-ASN1_SEQUENCE(ESS_CERT_ID) = {
- ASN1_SIMPLE(ESS_CERT_ID, hash, ASN1_OCTET_STRING),
- ASN1_OPT(ESS_CERT_ID, issuer_serial, ESS_ISSUER_SERIAL)
-} static_ASN1_SEQUENCE_END(ESS_CERT_ID)
-
-IMPLEMENT_ASN1_FUNCTIONS_const(ESS_CERT_ID)
-IMPLEMENT_ASN1_DUP_FUNCTION(ESS_CERT_ID)
-
-ASN1_SEQUENCE(ESS_SIGNING_CERT) = {
- ASN1_SEQUENCE_OF(ESS_SIGNING_CERT, cert_ids, ESS_CERT_ID),
- ASN1_SEQUENCE_OF_OPT(ESS_SIGNING_CERT, policy_info, POLICYINFO)
-} static_ASN1_SEQUENCE_END(ESS_SIGNING_CERT)
-
-IMPLEMENT_ASN1_FUNCTIONS_const(ESS_SIGNING_CERT)
-IMPLEMENT_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT)
-
-ASN1_SEQUENCE(ESS_CERT_ID_V2) = {
- ASN1_OPT(ESS_CERT_ID_V2, hash_alg, X509_ALGOR),
- ASN1_SIMPLE(ESS_CERT_ID_V2, hash, ASN1_OCTET_STRING),
- ASN1_OPT(ESS_CERT_ID_V2, issuer_serial, ESS_ISSUER_SERIAL)
-} static_ASN1_SEQUENCE_END(ESS_CERT_ID_V2)
-
-IMPLEMENT_ASN1_FUNCTIONS_const(ESS_CERT_ID_V2)
-IMPLEMENT_ASN1_DUP_FUNCTION(ESS_CERT_ID_V2)
-
-ASN1_SEQUENCE(ESS_SIGNING_CERT_V2) = {
- ASN1_SEQUENCE_OF(ESS_SIGNING_CERT_V2, cert_ids, ESS_CERT_ID_V2),
- ASN1_SEQUENCE_OF_OPT(ESS_SIGNING_CERT_V2, policy_info, POLICYINFO)
-} static_ASN1_SEQUENCE_END(ESS_SIGNING_CERT_V2)
-
-IMPLEMENT_ASN1_FUNCTIONS_const(ESS_SIGNING_CERT_V2)
-IMPLEMENT_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT_V2)
-
/* Getting encapsulated TS_TST_INFO object from PKCS7. */
TS_TST_INFO *PKCS7_to_TS_TST_INFO(PKCS7 *token)
{
@@ -252,22 +210,22 @@ TS_TST_INFO *PKCS7_to_TS_TST_INFO(PKCS7 *token)
const unsigned char *p;
if (!PKCS7_type_is_signed(token)) {
- TSerr(TS_F_PKCS7_TO_TS_TST_INFO, TS_R_BAD_PKCS7_TYPE);
+ ERR_raise(ERR_LIB_TS, TS_R_BAD_PKCS7_TYPE);
return NULL;
}
if (PKCS7_get_detached(token)) {
- TSerr(TS_F_PKCS7_TO_TS_TST_INFO, TS_R_DETACHED_CONTENT);
+ ERR_raise(ERR_LIB_TS, TS_R_DETACHED_CONTENT);
return NULL;
}
pkcs7_signed = token->d.sign;
enveloped = pkcs7_signed->contents;
if (OBJ_obj2nid(enveloped->type) != NID_id_smime_ct_TSTInfo) {
- TSerr(TS_F_PKCS7_TO_TS_TST_INFO, TS_R_BAD_PKCS7_TYPE);
+ ERR_raise(ERR_LIB_TS, TS_R_BAD_PKCS7_TYPE);
return NULL;
}
tst_info_wrapper = enveloped->d.other;
if (tst_info_wrapper->type != V_ASN1_OCTET_STRING) {
- TSerr(TS_F_PKCS7_TO_TS_TST_INFO, TS_R_BAD_TYPE);
+ ERR_raise(ERR_LIB_TS, TS_R_BAD_TYPE);
return NULL;
}
tst_info_der = tst_info_wrapper->value.octet_string;
diff --git a/crypto/ts/ts_conf.c b/crypto/ts/ts_conf.c
index 625089a59bf9..fd2ad90754b0 100644
--- a/crypto/ts/ts_conf.c
+++ b/crypto/ts/ts_conf.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <string.h>
#include <openssl/crypto.h>
@@ -14,6 +17,7 @@
#include <openssl/pem.h>
#include <openssl/engine.h>
#include <openssl/ts.h>
+#include <openssl/conf_api.h>
/* Macro definitions for the configuration file. */
#define BASE_SECTION "tsa"
@@ -51,7 +55,7 @@ X509 *TS_CONF_load_cert(const char *file)
x = PEM_read_bio_X509_AUX(cert, NULL, NULL, NULL);
end:
if (x == NULL)
- TSerr(TS_F_TS_CONF_LOAD_CERT, TS_R_CANNOT_LOAD_CERT);
+ ERR_raise(ERR_LIB_TS, TS_R_CANNOT_LOAD_CERT);
BIO_free(cert);
return x;
}
@@ -71,14 +75,19 @@ STACK_OF(X509) *TS_CONF_load_certs(const char *file)
allcerts = PEM_X509_INFO_read_bio(certs, NULL, NULL, NULL);
for (i = 0; i < sk_X509_INFO_num(allcerts); i++) {
X509_INFO *xi = sk_X509_INFO_value(allcerts, i);
- if (xi->x509) {
- sk_X509_push(othercerts, xi->x509);
+
+ if (xi->x509 != NULL) {
+ if (!X509_add_cert(othercerts, xi->x509, X509_ADD_FLAG_DEFAULT)) {
+ sk_X509_pop_free(othercerts, X509_free);
+ othercerts = NULL;
+ goto end;
+ }
xi->x509 = NULL;
}
}
end:
if (othercerts == NULL)
- TSerr(TS_F_TS_CONF_LOAD_CERTS, TS_R_CANNOT_LOAD_CERT);
+ ERR_raise(ERR_LIB_TS, TS_R_CANNOT_LOAD_CERT);
sk_X509_INFO_pop_free(allcerts, X509_INFO_free);
BIO_free(certs);
return othercerts;
@@ -94,7 +103,7 @@ EVP_PKEY *TS_CONF_load_key(const char *file, const char *pass)
pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, (char *)pass);
end:
if (pkey == NULL)
- TSerr(TS_F_TS_CONF_LOAD_KEY, TS_R_CANNOT_LOAD_KEY);
+ ERR_raise(ERR_LIB_TS, TS_R_CANNOT_LOAD_KEY);
BIO_free(key);
return pkey;
}
@@ -103,14 +112,12 @@ EVP_PKEY *TS_CONF_load_key(const char *file, const char *pass)
static void ts_CONF_lookup_fail(const char *name, const char *tag)
{
- TSerr(TS_F_TS_CONF_LOOKUP_FAIL, TS_R_VAR_LOOKUP_FAILURE);
- ERR_add_error_data(3, name, "::", tag);
+ ERR_raise_data(ERR_LIB_TS, TS_R_VAR_LOOKUP_FAILURE, "%s::%s", name, tag);
}
static void ts_CONF_invalid(const char *name, const char *tag)
{
- TSerr(TS_F_TS_CONF_INVALID, TS_R_VAR_BAD_VALUE);
- ERR_add_error_data(3, name, "::", tag);
+ ERR_raise_data(ERR_LIB_TS, TS_R_VAR_BAD_VALUE, "%s::%s", name, tag);
}
const char *TS_CONF_get_tsa_section(CONF *conf, const char *section)
@@ -175,10 +182,9 @@ int TS_CONF_set_default_engine(const char *name)
ret = 1;
err:
- if (!ret) {
- TSerr(TS_F_TS_CONF_SET_DEFAULT_ENGINE, TS_R_COULD_NOT_SET_ENGINE);
- ERR_add_error_data(2, "engine:", name);
- }
+ if (!ret)
+ ERR_raise_data(ERR_LIB_TS, TS_R_COULD_NOT_SET_ENGINE,
+ "engine:%s", name);
ENGINE_free(e);
return ret;
}
@@ -283,9 +289,10 @@ int TS_CONF_set_def_policy(CONF *conf, const char *section,
{
int ret = 0;
ASN1_OBJECT *policy_obj = NULL;
- if (!policy)
+
+ if (policy == NULL)
policy = NCONF_get_string(conf, section, ENV_DEFAULT_POLICY);
- if (!policy) {
+ if (policy == NULL) {
ts_CONF_lookup_fail(section, ENV_DEFAULT_POLICY);
goto err;
}
@@ -409,7 +416,7 @@ int TS_CONF_set_accuracy(CONF *conf, const char *section, TS_RESP_CTX *ctx)
return ret;
}
-int TS_CONF_set_clock_precision_digits(CONF *conf, const char *section,
+int TS_CONF_set_clock_precision_digits(const CONF *conf, const char *section,
TS_RESP_CTX *ctx)
{
int ret = 0;
@@ -418,9 +425,7 @@ int TS_CONF_set_clock_precision_digits(CONF *conf, const char *section,
/*
* If not specified, set the default value to 0, i.e. sec precision
*/
- if (!NCONF_get_number_e(conf, section, ENV_CLOCK_PRECISION_DIGITS,
- &digits))
- digits = 0;
+ digits = _CONF_get_number(conf, section, ENV_CLOCK_PRECISION_DIGITS);
if (digits < 0 || digits > TS_MAX_CLOCK_PRECISION_DIGITS) {
ts_CONF_invalid(section, ENV_CLOCK_PRECISION_DIGITS);
goto err;
diff --git a/crypto/ts/ts_err.c b/crypto/ts/ts_err.c
index 1f3854d8491e..46e89beee8a2 100644
--- a/crypto/ts/ts_err.c
+++ b/crypto/ts/ts_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,105 +10,11 @@
#include <openssl/err.h>
#include <openssl/tserr.h>
+#include "crypto/tserr.h"
-#ifndef OPENSSL_NO_ERR
+#ifndef OPENSSL_NO_TS
-static const ERR_STRING_DATA TS_str_functs[] = {
- {ERR_PACK(ERR_LIB_TS, TS_F_DEF_SERIAL_CB, 0), "def_serial_cb"},
- {ERR_PACK(ERR_LIB_TS, TS_F_DEF_TIME_CB, 0), "def_time_cb"},
- {ERR_PACK(ERR_LIB_TS, TS_F_ESS_ADD_SIGNING_CERT, 0),
- "ess_add_signing_cert"},
- {ERR_PACK(ERR_LIB_TS, TS_F_ESS_ADD_SIGNING_CERT_V2, 0),
- "ess_add_signing_cert_v2"},
- {ERR_PACK(ERR_LIB_TS, TS_F_ESS_CERT_ID_NEW_INIT, 0),
- "ess_CERT_ID_new_init"},
- {ERR_PACK(ERR_LIB_TS, TS_F_ESS_CERT_ID_V2_NEW_INIT, 0),
- "ess_cert_id_v2_new_init"},
- {ERR_PACK(ERR_LIB_TS, TS_F_ESS_SIGNING_CERT_NEW_INIT, 0),
- "ess_SIGNING_CERT_new_init"},
- {ERR_PACK(ERR_LIB_TS, TS_F_ESS_SIGNING_CERT_V2_NEW_INIT, 0),
- "ess_signing_cert_v2_new_init"},
- {ERR_PACK(ERR_LIB_TS, TS_F_INT_TS_RESP_VERIFY_TOKEN, 0),
- "int_ts_RESP_verify_token"},
- {ERR_PACK(ERR_LIB_TS, TS_F_PKCS7_TO_TS_TST_INFO, 0),
- "PKCS7_to_TS_TST_INFO"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_ACCURACY_SET_MICROS, 0),
- "TS_ACCURACY_set_micros"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_ACCURACY_SET_MILLIS, 0),
- "TS_ACCURACY_set_millis"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_ACCURACY_SET_SECONDS, 0),
- "TS_ACCURACY_set_seconds"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_CHECK_IMPRINTS, 0), "ts_check_imprints"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_CHECK_NONCES, 0), "ts_check_nonces"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_CHECK_POLICY, 0), "ts_check_policy"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_CHECK_SIGNING_CERTS, 0),
- "ts_check_signing_certs"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_CHECK_STATUS_INFO, 0),
- "ts_check_status_info"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_COMPUTE_IMPRINT, 0), "ts_compute_imprint"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_CONF_INVALID, 0), "ts_CONF_invalid"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_CONF_LOAD_CERT, 0), "TS_CONF_load_cert"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_CONF_LOAD_CERTS, 0), "TS_CONF_load_certs"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_CONF_LOAD_KEY, 0), "TS_CONF_load_key"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_CONF_LOOKUP_FAIL, 0), "ts_CONF_lookup_fail"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_CONF_SET_DEFAULT_ENGINE, 0),
- "TS_CONF_set_default_engine"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_GET_STATUS_TEXT, 0), "ts_get_status_text"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_MSG_IMPRINT_SET_ALGO, 0),
- "TS_MSG_IMPRINT_set_algo"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_REQ_SET_MSG_IMPRINT, 0),
- "TS_REQ_set_msg_imprint"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_REQ_SET_NONCE, 0), "TS_REQ_set_nonce"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_REQ_SET_POLICY_ID, 0),
- "TS_REQ_set_policy_id"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CREATE_RESPONSE, 0),
- "TS_RESP_create_response"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CREATE_TST_INFO, 0),
- "ts_RESP_create_tst_info"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_ADD_FAILURE_INFO, 0),
- "TS_RESP_CTX_add_failure_info"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_ADD_MD, 0), "TS_RESP_CTX_add_md"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_ADD_POLICY, 0),
- "TS_RESP_CTX_add_policy"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_NEW, 0), "TS_RESP_CTX_new"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_SET_ACCURACY, 0),
- "TS_RESP_CTX_set_accuracy"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_SET_CERTS, 0),
- "TS_RESP_CTX_set_certs"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_SET_DEF_POLICY, 0),
- "TS_RESP_CTX_set_def_policy"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_SET_SIGNER_CERT, 0),
- "TS_RESP_CTX_set_signer_cert"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_SET_STATUS_INFO, 0),
- "TS_RESP_CTX_set_status_info"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_GET_POLICY, 0), "ts_RESP_get_policy"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_SET_GENTIME_WITH_PRECISION, 0),
- "TS_RESP_set_genTime_with_precision"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_SET_STATUS_INFO, 0),
- "TS_RESP_set_status_info"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_SET_TST_INFO, 0),
- "TS_RESP_set_tst_info"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_SIGN, 0), "ts_RESP_sign"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_VERIFY_SIGNATURE, 0),
- "TS_RESP_verify_signature"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_TST_INFO_SET_ACCURACY, 0),
- "TS_TST_INFO_set_accuracy"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_TST_INFO_SET_MSG_IMPRINT, 0),
- "TS_TST_INFO_set_msg_imprint"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_TST_INFO_SET_NONCE, 0),
- "TS_TST_INFO_set_nonce"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_TST_INFO_SET_POLICY_ID, 0),
- "TS_TST_INFO_set_policy_id"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_TST_INFO_SET_SERIAL, 0),
- "TS_TST_INFO_set_serial"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_TST_INFO_SET_TIME, 0),
- "TS_TST_INFO_set_time"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_TST_INFO_SET_TSA, 0), "TS_TST_INFO_set_tsa"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_VERIFY, 0), ""},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_VERIFY_CERT, 0), "ts_verify_cert"},
- {ERR_PACK(ERR_LIB_TS, TS_F_TS_VERIFY_CTX_NEW, 0), "TS_VERIFY_CTX_new"},
- {0, NULL}
-};
+# ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA TS_str_reasons[] = {
{ERR_PACK(ERR_LIB_TS, 0, TS_R_BAD_PKCS7_TYPE), "bad pkcs7 type"},
@@ -170,15 +76,16 @@ static const ERR_STRING_DATA TS_str_reasons[] = {
{0, NULL}
};
-#endif
+# endif
-int ERR_load_TS_strings(void)
+int ossl_err_load_TS_strings(void)
{
-#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(TS_str_functs[0].error) == NULL) {
- ERR_load_strings_const(TS_str_functs);
+# ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(TS_str_reasons[0].error) == NULL)
ERR_load_strings_const(TS_str_reasons);
- }
-#endif
+# endif
return 1;
}
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/crypto/ts/ts_lib.c b/crypto/ts/ts_lib.c
index bfe981364b03..5a99c9df1759 100644
--- a/crypto/ts/ts_lib.c
+++ b/crypto/ts/ts_lib.c
@@ -1,7 +1,7 @@
/*
* Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/ts/ts_local.h b/crypto/ts/ts_local.h
index 771784fef7c8..4dcb7af960b2 100644
--- a/crypto/ts/ts_local.h
+++ b/crypto/ts/ts_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -98,67 +98,6 @@ struct TS_status_info_st {
ASN1_BIT_STRING *failure_info;
};
-/*-
- * IssuerSerial ::= SEQUENCE {
- * issuer GeneralNames,
- * serialNumber CertificateSerialNumber
- * }
- */
-struct ESS_issuer_serial {
- STACK_OF(GENERAL_NAME) *issuer;
- ASN1_INTEGER *serial;
-};
-
-/*-
- * ESSCertID ::= SEQUENCE {
- * certHash Hash,
- * issuerSerial IssuerSerial OPTIONAL
- * }
- */
-struct ESS_cert_id {
- ASN1_OCTET_STRING *hash; /* Always SHA-1 digest. */
- ESS_ISSUER_SERIAL *issuer_serial;
-};
-
-/*-
- * SigningCertificate ::= SEQUENCE {
- * certs SEQUENCE OF ESSCertID,
- * policies SEQUENCE OF PolicyInformation OPTIONAL
- * }
- */
-struct ESS_signing_cert {
- STACK_OF(ESS_CERT_ID) *cert_ids;
- STACK_OF(POLICYINFO) *policy_info;
-};
-
-/*-
- * ESSCertIDv2 ::= SEQUENCE {
- * hashAlgorithm AlgorithmIdentifier
- * DEFAULT {algorithm id-sha256},
- * certHash Hash,
- * issuerSerial IssuerSerial OPTIONAL
- * }
- */
-
-struct ESS_cert_id_v2_st {
- X509_ALGOR *hash_alg; /* Default: SHA-256 */
- ASN1_OCTET_STRING *hash;
- ESS_ISSUER_SERIAL *issuer_serial;
-};
-
-/*-
- * SigningCertificateV2 ::= SEQUENCE {
- * certs SEQUENCE OF ESSCertIDv2,
- * policies SEQUENCE OF PolicyInformation OPTIONAL
- * }
- */
-
-struct ESS_signing_cert_v2_st {
- STACK_OF(ESS_CERT_ID_V2) *cert_ids;
- STACK_OF(POLICYINFO) *policy_info;
-};
-
-
struct TS_resp_ctx {
X509 *signer_cert;
EVP_PKEY *signer_key;
@@ -185,6 +124,8 @@ struct TS_resp_ctx {
TS_REQ *request;
TS_RESP *response;
TS_TST_INFO *tst_info;
+ OSSL_LIB_CTX *libctx;
+ char *propq;
};
struct TS_verify_ctx {
diff --git a/crypto/ts/ts_req_print.c b/crypto/ts/ts_req_print.c
index 4eba5cf0181c..968816ae2858 100644
--- a/crypto/ts/ts_req_print.c
+++ b/crypto/ts/ts_req_print.c
@@ -1,7 +1,7 @@
/*
* Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/ts/ts_req_utils.c b/crypto/ts/ts_req_utils.c
index a4568e3b779d..b560fc7b38a9 100644
--- a/crypto/ts/ts_req_utils.c
+++ b/crypto/ts/ts_req_utils.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -32,7 +32,7 @@ int TS_REQ_set_msg_imprint(TS_REQ *a, TS_MSG_IMPRINT *msg_imprint)
return 1;
new_msg_imprint = TS_MSG_IMPRINT_dup(msg_imprint);
if (new_msg_imprint == NULL) {
- TSerr(TS_F_TS_REQ_SET_MSG_IMPRINT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
TS_MSG_IMPRINT_free(a->msg_imprint);
@@ -53,7 +53,7 @@ int TS_MSG_IMPRINT_set_algo(TS_MSG_IMPRINT *a, X509_ALGOR *alg)
return 1;
new_alg = X509_ALGOR_dup(alg);
if (new_alg == NULL) {
- TSerr(TS_F_TS_MSG_IMPRINT_SET_ALGO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
X509_ALGOR_free(a->hash_algo);
@@ -84,7 +84,7 @@ int TS_REQ_set_policy_id(TS_REQ *a, const ASN1_OBJECT *policy)
return 1;
new_policy = OBJ_dup(policy);
if (new_policy == NULL) {
- TSerr(TS_F_TS_REQ_SET_POLICY_ID, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
ASN1_OBJECT_free(a->policy_id);
@@ -105,7 +105,7 @@ int TS_REQ_set_nonce(TS_REQ *a, const ASN1_INTEGER *nonce)
return 1;
new_nonce = ASN1_INTEGER_dup(nonce);
if (new_nonce == NULL) {
- TSerr(TS_F_TS_REQ_SET_NONCE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
ASN1_INTEGER_free(a->nonce);
diff --git a/crypto/ts/ts_rsp_print.c b/crypto/ts/ts_rsp_print.c
index a2451aaa8d81..ca2d8a6dc154 100644
--- a/crypto/ts/ts_rsp_print.c
+++ b/crypto/ts/ts_rsp_print.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/ts/ts_rsp_sign.c b/crypto/ts/ts_rsp_sign.c
index 342582f024b2..8937bb2d6671 100644
--- a/crypto/ts/ts_rsp_sign.c
+++ b/crypto/ts/ts_rsp_sign.c
@@ -1,21 +1,25 @@
/*
- * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "e_os.h"
-#include "internal/cryptlib.h"
#include <openssl/objects.h>
#include <openssl/ts.h>
#include <openssl/pkcs7.h>
#include <openssl/crypto.h>
+#include "internal/cryptlib.h"
+#include "internal/sizes.h"
+#include "crypto/ess.h"
#include "ts_local.h"
+DEFINE_STACK_OF_CONST(EVP_MD)
+
static ASN1_INTEGER *def_serial_cb(struct TS_resp_ctx *, void *);
static int def_time_cb(struct TS_resp_ctx *, void *, long *sec, long *usec);
static int def_extension_cb(struct TS_resp_ctx *, X509_EXTENSION *, void *);
@@ -29,20 +33,7 @@ static TS_TST_INFO *ts_RESP_create_tst_info(TS_RESP_CTX *ctx,
static int ts_RESP_process_extensions(TS_RESP_CTX *ctx);
static int ts_RESP_sign(TS_RESP_CTX *ctx);
-static ESS_SIGNING_CERT *ess_SIGNING_CERT_new_init(X509 *signcert,
- STACK_OF(X509) *certs);
-static ESS_CERT_ID *ess_CERT_ID_new_init(X509 *cert, int issuer_needed);
static int ts_TST_INFO_content_new(PKCS7 *p7);
-static int ess_add_signing_cert(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc);
-
-static ESS_SIGNING_CERT_V2 *ess_signing_cert_v2_new_init(const EVP_MD *hash_alg,
- X509 *signcert,
- STACK_OF(X509)
- *certs);
-static ESS_CERT_ID_V2 *ess_cert_id_v2_new_init(const EVP_MD *hash_alg,
- X509 *cert, int issuer_needed);
-static int ess_add_signing_cert_v2(PKCS7_SIGNER_INFO *si,
- ESS_SIGNING_CERT_V2 *sc);
static ASN1_GENERALIZEDTIME
*TS_RESP_set_genTime_with_precision(ASN1_GENERALIZEDTIME *, long, long,
@@ -57,11 +48,10 @@ static ASN1_INTEGER *def_serial_cb(struct TS_resp_ctx *ctx, void *data)
goto err;
if (!ASN1_INTEGER_set(serial, 1))
goto err;
-
return serial;
err:
- TSerr(TS_F_DEF_SERIAL_CB, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
"Error during serial number generation.");
ASN1_INTEGER_free(serial);
@@ -75,7 +65,7 @@ static int def_time_cb(struct TS_resp_ctx *ctx, void *data,
{
struct timeval tv;
if (gettimeofday(&tv, NULL) != 0) {
- TSerr(TS_F_DEF_TIME_CB, TS_R_TIME_SYSCALL_ERROR);
+ ERR_raise(ERR_LIB_TS, TS_R_TIME_SYSCALL_ERROR);
TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
"Time is not available.");
TS_RESP_CTX_add_failure_info(ctx, TS_INFO_TIME_NOT_AVAILABLE);
@@ -94,7 +84,7 @@ static int def_time_cb(struct TS_resp_ctx *ctx, void *data,
{
time_t t;
if (time(&t) == (time_t)-1) {
- TSerr(TS_F_DEF_TIME_CB, TS_R_TIME_SYSCALL_ERROR);
+ ERR_raise(ERR_LIB_TS, TS_R_TIME_SYSCALL_ERROR);
TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
"Time is not available.");
TS_RESP_CTX_add_failure_info(ctx, TS_INFO_TIME_NOT_AVAILABLE);
@@ -119,17 +109,24 @@ static int def_extension_cb(struct TS_resp_ctx *ctx, X509_EXTENSION *ext,
/* TS_RESP_CTX management functions. */
-TS_RESP_CTX *TS_RESP_CTX_new(void)
+TS_RESP_CTX *TS_RESP_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
{
TS_RESP_CTX *ctx;
if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
- TSerr(TS_F_TS_RESP_CTX_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return NULL;
}
- ctx->signer_md = EVP_sha256();
-
+ if (propq != NULL) {
+ ctx->propq = OPENSSL_strdup(propq);
+ if (ctx->propq == NULL) {
+ OPENSSL_free(ctx);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ }
+ ctx->libctx = libctx;
ctx->serial_cb = def_serial_cb;
ctx->time_cb = def_time_cb;
ctx->extension_cb = def_extension_cb;
@@ -137,11 +134,17 @@ TS_RESP_CTX *TS_RESP_CTX_new(void)
return ctx;
}
+TS_RESP_CTX *TS_RESP_CTX_new(void)
+{
+ return TS_RESP_CTX_new_ex(NULL, NULL);
+}
+
void TS_RESP_CTX_free(TS_RESP_CTX *ctx)
{
if (!ctx)
return;
+ OPENSSL_free(ctx->propq);
X509_free(ctx->signer_cert);
EVP_PKEY_free(ctx->signer_key);
sk_X509_pop_free(ctx->certs, X509_free);
@@ -157,8 +160,7 @@ void TS_RESP_CTX_free(TS_RESP_CTX *ctx)
int TS_RESP_CTX_set_signer_cert(TS_RESP_CTX *ctx, X509 *signer)
{
if (X509_check_purpose(signer, X509_PURPOSE_TIMESTAMP_SIGN, 0) != 1) {
- TSerr(TS_F_TS_RESP_CTX_SET_SIGNER_CERT,
- TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE);
+ ERR_raise(ERR_LIB_TS, TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE);
return 0;
}
X509_free(ctx->signer_cert);
@@ -189,23 +191,16 @@ int TS_RESP_CTX_set_def_policy(TS_RESP_CTX *ctx, const ASN1_OBJECT *def_policy)
goto err;
return 1;
err:
- TSerr(TS_F_TS_RESP_CTX_SET_DEF_POLICY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
int TS_RESP_CTX_set_certs(TS_RESP_CTX *ctx, STACK_OF(X509) *certs)
{
-
sk_X509_pop_free(ctx->certs, X509_free);
ctx->certs = NULL;
- if (!certs)
- return 1;
- if ((ctx->certs = X509_chain_up_ref(certs)) == NULL) {
- TSerr(TS_F_TS_RESP_CTX_SET_CERTS, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- return 1;
+ return certs == NULL || (ctx->certs = X509_chain_up_ref(certs)) != NULL;
}
int TS_RESP_CTX_add_policy(TS_RESP_CTX *ctx, const ASN1_OBJECT *policy)
@@ -222,7 +217,7 @@ int TS_RESP_CTX_add_policy(TS_RESP_CTX *ctx, const ASN1_OBJECT *policy)
return 1;
err:
- TSerr(TS_F_TS_RESP_CTX_ADD_POLICY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
ASN1_OBJECT_free(copy);
return 0;
}
@@ -237,7 +232,7 @@ int TS_RESP_CTX_add_md(TS_RESP_CTX *ctx, const EVP_MD *md)
return 1;
err:
- TSerr(TS_F_TS_RESP_CTX_ADD_MD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -270,7 +265,7 @@ int TS_RESP_CTX_set_accuracy(TS_RESP_CTX *ctx,
return 1;
err:
TS_RESP_CTX_accuracy_free(ctx);
- TSerr(TS_F_TS_RESP_CTX_SET_ACCURACY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -325,7 +320,7 @@ int TS_RESP_CTX_set_status_info(TS_RESP_CTX *ctx,
ret = 1;
err:
if (!ret)
- TSerr(TS_F_TS_RESP_CTX_SET_STATUS_INFO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
TS_STATUS_INFO_free(si);
ASN1_UTF8STRING_free(utf8_text);
return ret;
@@ -353,7 +348,7 @@ int TS_RESP_CTX_add_failure_info(TS_RESP_CTX *ctx, int failure)
goto err;
return 1;
err:
- TSerr(TS_F_TS_RESP_CTX_ADD_FAILURE_INFO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -386,7 +381,7 @@ TS_RESP *TS_RESP_create_response(TS_RESP_CTX *ctx, BIO *req_bio)
ts_RESP_CTX_init(ctx);
if ((ctx->response = TS_RESP_new()) == NULL) {
- TSerr(TS_F_TS_RESP_CREATE_RESPONSE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
goto end;
}
if ((ctx->request = d2i_TS_REQ_bio(req_bio, NULL)) == NULL) {
@@ -411,7 +406,7 @@ TS_RESP *TS_RESP_create_response(TS_RESP_CTX *ctx, BIO *req_bio)
end:
if (!result) {
- TSerr(TS_F_TS_RESP_CREATE_RESPONSE, TS_R_RESPONSE_SETUP_ERROR);
+ ERR_raise(ERR_LIB_TS, TS_R_RESPONSE_SETUP_ERROR);
if (ctx->response != NULL) {
if (TS_RESP_CTX_set_status_info_cond(ctx,
TS_STATUS_REJECTION,
@@ -453,7 +448,7 @@ static int ts_RESP_check_request(TS_RESP_CTX *ctx)
TS_REQ *request = ctx->request;
TS_MSG_IMPRINT *msg_imprint;
X509_ALGOR *md_alg;
- int md_alg_id;
+ char md_alg_name[OSSL_MAX_NAME_SIZE];
const ASN1_OCTET_STRING *digest;
const EVP_MD *md = NULL;
int i;
@@ -467,10 +462,10 @@ static int ts_RESP_check_request(TS_RESP_CTX *ctx)
msg_imprint = request->msg_imprint;
md_alg = msg_imprint->hash_algo;
- md_alg_id = OBJ_obj2nid(md_alg->algorithm);
+ OBJ_obj2txt(md_alg_name, sizeof(md_alg_name), md_alg->algorithm, 0);
for (i = 0; !md && i < sk_EVP_MD_num(ctx->mds); ++i) {
const EVP_MD *current_md = sk_EVP_MD_value(ctx->mds, i);
- if (md_alg_id == EVP_MD_type(current_md))
+ if (EVP_MD_is_a(current_md, md_alg_name))
md = current_md;
}
if (!md) {
@@ -489,7 +484,7 @@ static int ts_RESP_check_request(TS_RESP_CTX *ctx)
return 0;
}
digest = msg_imprint->hashed_msg;
- if (digest->length != EVP_MD_size(md)) {
+ if (digest->length != EVP_MD_get_size(md)) {
TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
"Bad message digest.");
TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_DATA_FORMAT);
@@ -507,7 +502,7 @@ static ASN1_OBJECT *ts_RESP_get_policy(TS_RESP_CTX *ctx)
int i;
if (ctx->default_policy == NULL) {
- TSerr(TS_F_TS_RESP_GET_POLICY, TS_R_INVALID_NULL_POINTER);
+ ERR_raise(ERR_LIB_TS, TS_R_INVALID_NULL_POINTER);
return NULL;
}
if (!requested || !OBJ_cmp(requested, ctx->default_policy))
@@ -519,8 +514,8 @@ static ASN1_OBJECT *ts_RESP_get_policy(TS_RESP_CTX *ctx)
if (!OBJ_cmp(requested, current))
policy = current;
}
- if (!policy) {
- TSerr(TS_F_TS_RESP_GET_POLICY, TS_R_UNACCEPTABLE_POLICY);
+ if (policy == NULL) {
+ ERR_raise(ERR_LIB_TS, TS_R_UNACCEPTABLE_POLICY);
TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
"Requested policy is not " "supported.");
TS_RESP_CTX_add_failure_info(ctx, TS_INFO_UNACCEPTED_POLICY);
@@ -596,7 +591,7 @@ static TS_TST_INFO *ts_RESP_create_tst_info(TS_RESP_CTX *ctx,
if (!result) {
TS_TST_INFO_free(tst_info);
tst_info = NULL;
- TSerr(TS_F_TS_RESP_CREATE_TST_INFO, TS_R_TST_INFO_SETUP_ERROR);
+ ERR_raise(ERR_LIB_TS, TS_R_TST_INFO_SETUP_ERROR);
TS_RESP_CTX_set_status_info_cond(ctx, TS_STATUS_REJECTION,
"Error during TSTInfo "
"generation.");
@@ -631,6 +626,52 @@ static int ts_RESP_process_extensions(TS_RESP_CTX *ctx)
}
/* Functions for signing the TS_TST_INFO structure of the context. */
+static int ossl_ess_add1_signing_cert(PKCS7_SIGNER_INFO *si,
+ const ESS_SIGNING_CERT *sc)
+{
+ ASN1_STRING *seq = NULL;
+ int len = i2d_ESS_SIGNING_CERT(sc, NULL);
+ unsigned char *p, *pp = OPENSSL_malloc(len);
+
+ if (pp == NULL)
+ return 0;
+
+ p = pp;
+ i2d_ESS_SIGNING_CERT(sc, &p);
+ if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set(seq, pp, len)) {
+ ASN1_STRING_free(seq);
+ OPENSSL_free(pp);
+ return 0;
+ }
+
+ OPENSSL_free(pp);
+ return PKCS7_add_signed_attribute(si, NID_id_smime_aa_signingCertificate,
+ V_ASN1_SEQUENCE, seq);
+}
+
+static int ossl_ess_add1_signing_cert_v2(PKCS7_SIGNER_INFO *si,
+ const ESS_SIGNING_CERT_V2 *sc)
+{
+ ASN1_STRING *seq = NULL;
+ int len = i2d_ESS_SIGNING_CERT_V2(sc, NULL);
+ unsigned char *p, *pp = OPENSSL_malloc(len);
+
+ if (pp == NULL)
+ return 0;
+
+ p = pp;
+ i2d_ESS_SIGNING_CERT_V2(sc, &p);
+ if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set(seq, pp, len)) {
+ ASN1_STRING_free(seq);
+ OPENSSL_free(pp);
+ return 0;
+ }
+
+ OPENSSL_free(pp);
+ return PKCS7_add_signed_attribute(si, NID_id_smime_aa_signingCertificateV2,
+ V_ASN1_SEQUENCE, seq);
+}
+
static int ts_RESP_sign(TS_RESP_CTX *ctx)
{
int ret = 0;
@@ -642,14 +683,15 @@ static int ts_RESP_sign(TS_RESP_CTX *ctx)
ASN1_OBJECT *oid;
BIO *p7bio = NULL;
int i;
+ EVP_MD *signer_md = NULL;
if (!X509_check_private_key(ctx->signer_cert, ctx->signer_key)) {
- TSerr(TS_F_TS_RESP_SIGN, TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
+ ERR_raise(ERR_LIB_TS, TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
goto err;
}
- if ((p7 = PKCS7_new()) == NULL) {
- TSerr(TS_F_TS_RESP_SIGN, ERR_R_MALLOC_FAILURE);
+ if ((p7 = PKCS7_new_ex(ctx->libctx, ctx->propq)) == NULL) {
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!PKCS7_set_type(p7, NID_pkcs7_signed))
@@ -667,37 +709,46 @@ static int ts_RESP_sign(TS_RESP_CTX *ctx)
}
}
+ if (ctx->signer_md == NULL)
+ signer_md = EVP_MD_fetch(ctx->libctx, "SHA256", ctx->propq);
+ else if (EVP_MD_get0_provider(ctx->signer_md) == NULL)
+ signer_md = EVP_MD_fetch(ctx->libctx, EVP_MD_get0_name(ctx->signer_md),
+ ctx->propq);
+ else
+ signer_md = (EVP_MD *)ctx->signer_md;
+
if ((si = PKCS7_add_signature(p7, ctx->signer_cert,
- ctx->signer_key, ctx->signer_md)) == NULL) {
- TSerr(TS_F_TS_RESP_SIGN, TS_R_PKCS7_ADD_SIGNATURE_ERROR);
+ ctx->signer_key, signer_md)) == NULL) {
+ ERR_raise(ERR_LIB_TS, TS_R_PKCS7_ADD_SIGNATURE_ERROR);
goto err;
}
oid = OBJ_nid2obj(NID_id_smime_ct_TSTInfo);
if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
V_ASN1_OBJECT, oid)) {
- TSerr(TS_F_TS_RESP_SIGN, TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR);
+ ERR_raise(ERR_LIB_TS, TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR);
goto err;
}
certs = ctx->flags & TS_ESS_CERT_ID_CHAIN ? ctx->certs : NULL;
if (ctx->ess_cert_id_digest == NULL
- || ctx->ess_cert_id_digest == EVP_sha1()) {
- if ((sc = ess_SIGNING_CERT_new_init(ctx->signer_cert, certs)) == NULL)
+ || EVP_MD_is_a(ctx->ess_cert_id_digest, SN_sha1)) {
+ if ((sc = OSSL_ESS_signing_cert_new_init(ctx->signer_cert,
+ certs, 0)) == NULL)
goto err;
- if (!ess_add_signing_cert(si, sc)) {
- TSerr(TS_F_TS_RESP_SIGN, TS_R_ESS_ADD_SIGNING_CERT_ERROR);
+ if (!ossl_ess_add1_signing_cert(si, sc)) {
+ ERR_raise(ERR_LIB_TS, TS_R_ESS_ADD_SIGNING_CERT_ERROR);
goto err;
}
} else {
- sc2 = ess_signing_cert_v2_new_init(ctx->ess_cert_id_digest,
- ctx->signer_cert, certs);
+ sc2 = OSSL_ESS_signing_cert_v2_new_init(ctx->ess_cert_id_digest,
+ ctx->signer_cert, certs, 0);
if (sc2 == NULL)
goto err;
- if (!ess_add_signing_cert_v2(si, sc2)) {
- TSerr(TS_F_TS_RESP_SIGN, TS_R_ESS_ADD_SIGNING_CERT_V2_ERROR);
+ if (!ossl_ess_add1_signing_cert_v2(si, sc2)) {
+ ERR_raise(ERR_LIB_TS, TS_R_ESS_ADD_SIGNING_CERT_V2_ERROR);
goto err;
}
}
@@ -705,15 +756,15 @@ static int ts_RESP_sign(TS_RESP_CTX *ctx)
if (!ts_TST_INFO_content_new(p7))
goto err;
if ((p7bio = PKCS7_dataInit(p7, NULL)) == NULL) {
- TSerr(TS_F_TS_RESP_SIGN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!i2d_TS_TST_INFO_bio(p7bio, ctx->tst_info)) {
- TSerr(TS_F_TS_RESP_SIGN, TS_R_TS_DATASIGN);
+ ERR_raise(ERR_LIB_TS, TS_R_TS_DATASIGN);
goto err;
}
if (!PKCS7_dataFinal(p7, p7bio)) {
- TSerr(TS_F_TS_RESP_SIGN, TS_R_TS_DATASIGN);
+ ERR_raise(ERR_LIB_TS, TS_R_TS_DATASIGN);
goto err;
}
TS_RESP_set_tst_info(ctx->response, p7, ctx->tst_info);
@@ -722,6 +773,9 @@ static int ts_RESP_sign(TS_RESP_CTX *ctx)
ret = 1;
err:
+ if (signer_md != ctx->signer_md)
+ EVP_MD_free(signer_md);
+
if (!ret)
TS_RESP_CTX_set_status_info_cond(ctx, TS_STATUS_REJECTION,
"Error during signature "
@@ -733,78 +787,6 @@ static int ts_RESP_sign(TS_RESP_CTX *ctx)
return ret;
}
-static ESS_SIGNING_CERT *ess_SIGNING_CERT_new_init(X509 *signcert,
- STACK_OF(X509) *certs)
-{
- ESS_CERT_ID *cid;
- ESS_SIGNING_CERT *sc = NULL;
- int i;
-
- if ((sc = ESS_SIGNING_CERT_new()) == NULL)
- goto err;
- if (sc->cert_ids == NULL
- && (sc->cert_ids = sk_ESS_CERT_ID_new_null()) == NULL)
- goto err;
-
- if ((cid = ess_CERT_ID_new_init(signcert, 0)) == NULL
- || !sk_ESS_CERT_ID_push(sc->cert_ids, cid))
- goto err;
- for (i = 0; i < sk_X509_num(certs); ++i) {
- X509 *cert = sk_X509_value(certs, i);
- if ((cid = ess_CERT_ID_new_init(cert, 1)) == NULL
- || !sk_ESS_CERT_ID_push(sc->cert_ids, cid))
- goto err;
- }
-
- return sc;
- err:
- ESS_SIGNING_CERT_free(sc);
- TSerr(TS_F_ESS_SIGNING_CERT_NEW_INIT, ERR_R_MALLOC_FAILURE);
- return NULL;
-}
-
-static ESS_CERT_ID *ess_CERT_ID_new_init(X509 *cert, int issuer_needed)
-{
- ESS_CERT_ID *cid = NULL;
- GENERAL_NAME *name = NULL;
- unsigned char cert_sha1[SHA_DIGEST_LENGTH];
-
- /* Call for side-effect of computing hash and caching extensions */
- X509_check_purpose(cert, -1, 0);
- if ((cid = ESS_CERT_ID_new()) == NULL)
- goto err;
- if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL))
- goto err;
- if (!ASN1_OCTET_STRING_set(cid->hash, cert_sha1, SHA_DIGEST_LENGTH))
- goto err;
-
- /* Setting the issuer/serial if requested. */
- if (issuer_needed) {
- if (cid->issuer_serial == NULL
- && (cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL)
- goto err;
- if ((name = GENERAL_NAME_new()) == NULL)
- goto err;
- name->type = GEN_DIRNAME;
- if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL)
- goto err;
- if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name))
- goto err;
- name = NULL; /* Ownership is lost. */
- ASN1_INTEGER_free(cid->issuer_serial->serial);
- if (!(cid->issuer_serial->serial =
- ASN1_INTEGER_dup(X509_get_serialNumber(cert))))
- goto err;
- }
-
- return cid;
- err:
- GENERAL_NAME_free(name);
- ESS_CERT_ID_free(cid);
- TSerr(TS_F_ESS_CERT_ID_NEW_INIT, ERR_R_MALLOC_FAILURE);
- return NULL;
-}
-
static int ts_TST_INFO_content_new(PKCS7 *p7)
{
PKCS7 *ret = NULL;
@@ -832,159 +814,6 @@ static int ts_TST_INFO_content_new(PKCS7 *p7)
return 0;
}
-static int ess_add_signing_cert(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc)
-{
- ASN1_STRING *seq = NULL;
- unsigned char *p, *pp = NULL;
- int len;
-
- len = i2d_ESS_SIGNING_CERT(sc, NULL);
- if ((pp = OPENSSL_malloc(len)) == NULL) {
- TSerr(TS_F_ESS_ADD_SIGNING_CERT, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- p = pp;
- i2d_ESS_SIGNING_CERT(sc, &p);
- if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set(seq, pp, len)) {
- TSerr(TS_F_ESS_ADD_SIGNING_CERT, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- OPENSSL_free(pp);
- pp = NULL;
- return PKCS7_add_signed_attribute(si,
- NID_id_smime_aa_signingCertificate,
- V_ASN1_SEQUENCE, seq);
- err:
- ASN1_STRING_free(seq);
- OPENSSL_free(pp);
-
- return 0;
-}
-
-static ESS_SIGNING_CERT_V2 *ess_signing_cert_v2_new_init(const EVP_MD *hash_alg,
- X509 *signcert,
- STACK_OF(X509) *certs)
-{
- ESS_CERT_ID_V2 *cid = NULL;
- ESS_SIGNING_CERT_V2 *sc = NULL;
- int i;
-
- if ((sc = ESS_SIGNING_CERT_V2_new()) == NULL)
- goto err;
- if ((cid = ess_cert_id_v2_new_init(hash_alg, signcert, 0)) == NULL)
- goto err;
- if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid))
- goto err;
- cid = NULL;
-
- for (i = 0; i < sk_X509_num(certs); ++i) {
- X509 *cert = sk_X509_value(certs, i);
-
- if ((cid = ess_cert_id_v2_new_init(hash_alg, cert, 1)) == NULL)
- goto err;
- if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid))
- goto err;
- cid = NULL;
- }
-
- return sc;
- err:
- ESS_SIGNING_CERT_V2_free(sc);
- ESS_CERT_ID_V2_free(cid);
- TSerr(TS_F_ESS_SIGNING_CERT_V2_NEW_INIT, ERR_R_MALLOC_FAILURE);
- return NULL;
-}
-
-static ESS_CERT_ID_V2 *ess_cert_id_v2_new_init(const EVP_MD *hash_alg,
- X509 *cert, int issuer_needed)
-{
- ESS_CERT_ID_V2 *cid = NULL;
- GENERAL_NAME *name = NULL;
- unsigned char hash[EVP_MAX_MD_SIZE];
- unsigned int hash_len = sizeof(hash);
- X509_ALGOR *alg = NULL;
-
- memset(hash, 0, sizeof(hash));
-
- if ((cid = ESS_CERT_ID_V2_new()) == NULL)
- goto err;
-
- if (hash_alg != EVP_sha256()) {
- alg = X509_ALGOR_new();
- if (alg == NULL)
- goto err;
- X509_ALGOR_set_md(alg, hash_alg);
- if (alg->algorithm == NULL)
- goto err;
- cid->hash_alg = alg;
- alg = NULL;
- } else {
- cid->hash_alg = NULL;
- }
-
- if (!X509_digest(cert, hash_alg, hash, &hash_len))
- goto err;
-
- if (!ASN1_OCTET_STRING_set(cid->hash, hash, hash_len))
- goto err;
-
- if (issuer_needed) {
- if ((cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL)
- goto err;
- if ((name = GENERAL_NAME_new()) == NULL)
- goto err;
- name->type = GEN_DIRNAME;
- if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL)
- goto err;
- if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name))
- goto err;
- name = NULL; /* Ownership is lost. */
- ASN1_INTEGER_free(cid->issuer_serial->serial);
- cid->issuer_serial->serial =
- ASN1_INTEGER_dup(X509_get_serialNumber(cert));
- if (cid->issuer_serial->serial == NULL)
- goto err;
- }
-
- return cid;
- err:
- X509_ALGOR_free(alg);
- GENERAL_NAME_free(name);
- ESS_CERT_ID_V2_free(cid);
- TSerr(TS_F_ESS_CERT_ID_V2_NEW_INIT, ERR_R_MALLOC_FAILURE);
- return NULL;
-}
-
-static int ess_add_signing_cert_v2(PKCS7_SIGNER_INFO *si,
- ESS_SIGNING_CERT_V2 *sc)
-{
- ASN1_STRING *seq = NULL;
- unsigned char *p, *pp = NULL;
- int len = i2d_ESS_SIGNING_CERT_V2(sc, NULL);
-
- if ((pp = OPENSSL_malloc(len)) == NULL) {
- TSerr(TS_F_ESS_ADD_SIGNING_CERT_V2, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- p = pp;
- i2d_ESS_SIGNING_CERT_V2(sc, &p);
- if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set(seq, pp, len)) {
- TSerr(TS_F_ESS_ADD_SIGNING_CERT_V2, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- OPENSSL_free(pp);
- pp = NULL;
- return PKCS7_add_signed_attribute(si,
- NID_id_smime_aa_signingCertificateV2,
- V_ASN1_SEQUENCE, seq);
- err:
- ASN1_STRING_free(seq);
- OPENSSL_free(pp);
- return 0;
-}
-
static ASN1_GENERALIZEDTIME *TS_RESP_set_genTime_with_precision(
ASN1_GENERALIZEDTIME *asn1_time, long sec, long usec,
unsigned precision)
@@ -1049,7 +878,7 @@ static ASN1_GENERALIZEDTIME *TS_RESP_set_genTime_with_precision(
return asn1_time;
err:
- TSerr(TS_F_TS_RESP_SET_GENTIME_WITH_PRECISION, TS_R_COULD_NOT_SET_TIME);
+ ERR_raise(ERR_LIB_TS, TS_R_COULD_NOT_SET_TIME);
return NULL;
}
diff --git a/crypto/ts/ts_rsp_utils.c b/crypto/ts/ts_rsp_utils.c
index 3fa0dbd0f09e..cae076f21a6a 100644
--- a/crypto/ts/ts_rsp_utils.c
+++ b/crypto/ts/ts_rsp_utils.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -22,7 +22,7 @@ int TS_RESP_set_status_info(TS_RESP *a, TS_STATUS_INFO *status_info)
return 1;
new_status_info = TS_STATUS_INFO_dup(status_info);
if (new_status_info == NULL) {
- TSerr(TS_F_TS_RESP_SET_STATUS_INFO, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
TS_STATUS_INFO_free(a->status_info);
@@ -73,7 +73,7 @@ int TS_TST_INFO_set_policy_id(TS_TST_INFO *a, ASN1_OBJECT *policy)
return 1;
new_policy = OBJ_dup(policy);
if (new_policy == NULL) {
- TSerr(TS_F_TS_TST_INFO_SET_POLICY_ID, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
ASN1_OBJECT_free(a->policy_id);
@@ -94,7 +94,7 @@ int TS_TST_INFO_set_msg_imprint(TS_TST_INFO *a, TS_MSG_IMPRINT *msg_imprint)
return 1;
new_msg_imprint = TS_MSG_IMPRINT_dup(msg_imprint);
if (new_msg_imprint == NULL) {
- TSerr(TS_F_TS_TST_INFO_SET_MSG_IMPRINT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
TS_MSG_IMPRINT_free(a->msg_imprint);
@@ -115,7 +115,7 @@ int TS_TST_INFO_set_serial(TS_TST_INFO *a, const ASN1_INTEGER *serial)
return 1;
new_serial = ASN1_INTEGER_dup(serial);
if (new_serial == NULL) {
- TSerr(TS_F_TS_TST_INFO_SET_SERIAL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
ASN1_INTEGER_free(a->serial);
@@ -136,7 +136,7 @@ int TS_TST_INFO_set_time(TS_TST_INFO *a, const ASN1_GENERALIZEDTIME *gtime)
return 1;
new_time = ASN1_STRING_dup(gtime);
if (new_time == NULL) {
- TSerr(TS_F_TS_TST_INFO_SET_TIME, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
ASN1_GENERALIZEDTIME_free(a->time);
@@ -157,7 +157,7 @@ int TS_TST_INFO_set_accuracy(TS_TST_INFO *a, TS_ACCURACY *accuracy)
return 1;
new_accuracy = TS_ACCURACY_dup(accuracy);
if (new_accuracy == NULL) {
- TSerr(TS_F_TS_TST_INFO_SET_ACCURACY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
TS_ACCURACY_free(a->accuracy);
@@ -178,7 +178,7 @@ int TS_ACCURACY_set_seconds(TS_ACCURACY *a, const ASN1_INTEGER *seconds)
return 1;
new_seconds = ASN1_INTEGER_dup(seconds);
if (new_seconds == NULL) {
- TSerr(TS_F_TS_ACCURACY_SET_SECONDS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
ASN1_INTEGER_free(a->seconds);
@@ -200,7 +200,7 @@ int TS_ACCURACY_set_millis(TS_ACCURACY *a, const ASN1_INTEGER *millis)
if (millis != NULL) {
new_millis = ASN1_INTEGER_dup(millis);
if (new_millis == NULL) {
- TSerr(TS_F_TS_ACCURACY_SET_MILLIS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
}
@@ -223,7 +223,7 @@ int TS_ACCURACY_set_micros(TS_ACCURACY *a, const ASN1_INTEGER *micros)
if (micros != NULL) {
new_micros = ASN1_INTEGER_dup(micros);
if (new_micros == NULL) {
- TSerr(TS_F_TS_ACCURACY_SET_MICROS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
}
@@ -256,7 +256,7 @@ int TS_TST_INFO_set_nonce(TS_TST_INFO *a, const ASN1_INTEGER *nonce)
return 1;
new_nonce = ASN1_INTEGER_dup(nonce);
if (new_nonce == NULL) {
- TSerr(TS_F_TS_TST_INFO_SET_NONCE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
ASN1_INTEGER_free(a->nonce);
@@ -277,7 +277,7 @@ int TS_TST_INFO_set_tsa(TS_TST_INFO *a, GENERAL_NAME *tsa)
return 1;
new_tsa = GENERAL_NAME_dup(tsa);
if (new_tsa == NULL) {
- TSerr(TS_F_TS_TST_INFO_SET_TSA, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return 0;
}
GENERAL_NAME_free(a->tsa);
diff --git a/crypto/ts/ts_rsp_verify.c b/crypto/ts/ts_rsp_verify.c
index 7fe3d27e74a2..792a27ce572b 100644
--- a/crypto/ts/ts_rsp_verify.c
+++ b/crypto/ts/ts_rsp_verify.c
@@ -1,26 +1,26 @@
/*
* Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
-#include "internal/cryptlib.h"
#include <openssl/objects.h>
#include <openssl/ts.h>
#include <openssl/pkcs7.h>
+#include "internal/cryptlib.h"
+#include "internal/sizes.h"
+#include "crypto/ess.h"
#include "ts_local.h"
static int ts_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted,
X509 *signer, STACK_OF(X509) **chain);
-static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si,
- STACK_OF(X509) *chain);
-static ESS_SIGNING_CERT *ess_get_signing_cert(PKCS7_SIGNER_INFO *si);
-static int ts_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert);
-static int ts_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509 *cert);
+static int ts_check_signing_certs(const PKCS7_SIGNER_INFO *si,
+ const STACK_OF(X509) *chain);
+
static int int_ts_RESP_verify_token(TS_VERIFY_CTX *ctx,
PKCS7 *token, TS_TST_INFO *tst_info);
static int ts_check_status_info(TS_RESP *response);
@@ -37,8 +37,6 @@ static int ts_check_nonces(const ASN1_INTEGER *a, TS_TST_INFO *tst_info);
static int ts_check_signer_name(GENERAL_NAME *tsa_name, X509 *signer);
static int ts_find_name(STACK_OF(GENERAL_NAME) *gen_names,
GENERAL_NAME *name);
-static int ts_find_cert_v2(STACK_OF(ESS_CERT_ID_V2) *cert_ids, X509 *cert);
-static ESS_SIGNING_CERT_V2 *ess_get_signing_cert_v2(PKCS7_SIGNER_INFO *si);
/*
* This must be large enough to hold all values in ts_status_text (with
@@ -92,6 +90,7 @@ int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs,
{
STACK_OF(PKCS7_SIGNER_INFO) *sinfos = NULL;
PKCS7_SIGNER_INFO *si;
+ STACK_OF(X509) *untrusted = NULL;
STACK_OF(X509) *signers = NULL;
X509 *signer;
STACK_OF(X509) *chain = NULL;
@@ -101,21 +100,21 @@ int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs,
/* Some sanity checks first. */
if (!token) {
- TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_INVALID_NULL_POINTER);
+ ERR_raise(ERR_LIB_TS, TS_R_INVALID_NULL_POINTER);
goto err;
}
if (!PKCS7_type_is_signed(token)) {
- TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_WRONG_CONTENT_TYPE);
+ ERR_raise(ERR_LIB_TS, TS_R_WRONG_CONTENT_TYPE);
goto err;
}
sinfos = PKCS7_get_signer_info(token);
if (!sinfos || sk_PKCS7_SIGNER_INFO_num(sinfos) != 1) {
- TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_THERE_MUST_BE_ONE_SIGNER);
+ ERR_raise(ERR_LIB_TS, TS_R_THERE_MUST_BE_ONE_SIGNER);
goto err;
}
si = sk_PKCS7_SIGNER_INFO_value(sinfos, 0);
if (PKCS7_get_detached(token)) {
- TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_NO_CONTENT);
+ ERR_raise(ERR_LIB_TS, TS_R_NO_CONTENT);
goto err;
}
@@ -128,7 +127,13 @@ int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs,
goto err;
signer = sk_X509_value(signers, 0);
- if (!ts_verify_cert(store, certs, signer, &chain))
+ untrusted = sk_X509_new_reserve(NULL, sk_X509_num(certs)
+ + sk_X509_num(token->d.sign->cert));
+ if (untrusted == NULL
+ || !X509_add_certs(untrusted, certs, 0)
+ || !X509_add_certs(untrusted, token->d.sign->cert, 0))
+ goto err;
+ if (!ts_verify_cert(store, untrusted, signer, &chain))
goto err;
if (!ts_check_signing_certs(si, chain))
goto err;
@@ -140,7 +145,7 @@ int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs,
j = PKCS7_signatureVerify(p7bio, token, si, signer);
if (j <= 0) {
- TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_SIGNATURE_FAILURE);
+ ERR_raise(ERR_LIB_TS, TS_R_SIGNATURE_FAILURE);
goto err;
}
@@ -152,6 +157,7 @@ int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs,
err:
BIO_free_all(p7bio);
+ sk_X509_free(untrusted);
sk_X509_pop_free(chain, X509_free);
sk_X509_free(signers);
@@ -172,7 +178,7 @@ static int ts_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted,
*chain = NULL;
cert_ctx = X509_STORE_CTX_new();
if (cert_ctx == NULL) {
- TSerr(TS_F_TS_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!X509_STORE_CTX_init(cert_ctx, store, signer, untrusted))
@@ -181,9 +187,8 @@ static int ts_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted,
i = X509_verify_cert(cert_ctx);
if (i <= 0) {
int j = X509_STORE_CTX_get_error(cert_ctx);
- TSerr(TS_F_TS_VERIFY_CERT, TS_R_CERTIFICATE_VERIFY_ERROR);
- ERR_add_error_data(2, "Verify error:",
- X509_verify_cert_error_string(j));
+ ERR_raise_data(ERR_LIB_TS, TS_R_CERTIFICATE_VERIFY_ERROR,
+ "Verify error:%s", X509_verify_cert_error_string(j));
goto err;
}
*chain = X509_STORE_CTX_get1_chain(cert_ctx);
@@ -198,77 +203,20 @@ end:
return ret;
}
-static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si,
- STACK_OF(X509) *chain)
-{
- ESS_SIGNING_CERT *ss = ess_get_signing_cert(si);
- STACK_OF(ESS_CERT_ID) *cert_ids = NULL;
- ESS_SIGNING_CERT_V2 *ssv2 = ess_get_signing_cert_v2(si);
- STACK_OF(ESS_CERT_ID_V2) *cert_ids_v2 = NULL;
- X509 *cert;
- int i = 0;
- int ret = 0;
-
- if (ss != NULL) {
- cert_ids = ss->cert_ids;
- cert = sk_X509_value(chain, 0);
- if (ts_find_cert(cert_ids, cert) != 0)
- goto err;
-
- /*
- * Check the other certificates of the chain if there are more than one
- * certificate ids in cert_ids.
- */
- if (sk_ESS_CERT_ID_num(cert_ids) > 1) {
- for (i = 1; i < sk_X509_num(chain); ++i) {
- cert = sk_X509_value(chain, i);
- if (ts_find_cert(cert_ids, cert) < 0)
- goto err;
- }
- }
- } else if (ssv2 != NULL) {
- cert_ids_v2 = ssv2->cert_ids;
- cert = sk_X509_value(chain, 0);
- if (ts_find_cert_v2(cert_ids_v2, cert) != 0)
- goto err;
-
- /*
- * Check the other certificates of the chain if there are more than one
- * certificate ids in cert_ids.
- */
- if (sk_ESS_CERT_ID_V2_num(cert_ids_v2) > 1) {
- for (i = 1; i < sk_X509_num(chain); ++i) {
- cert = sk_X509_value(chain, i);
- if (ts_find_cert_v2(cert_ids_v2, cert) < 0)
- goto err;
- }
- }
- } else {
- goto err;
- }
-
- ret = 1;
- err:
- if (!ret)
- TSerr(TS_F_TS_CHECK_SIGNING_CERTS,
- TS_R_ESS_SIGNING_CERTIFICATE_ERROR);
- ESS_SIGNING_CERT_free(ss);
- ESS_SIGNING_CERT_V2_free(ssv2);
- return ret;
-}
-
-static ESS_SIGNING_CERT *ess_get_signing_cert(PKCS7_SIGNER_INFO *si)
+static ESS_SIGNING_CERT *ossl_ess_get_signing_cert(const PKCS7_SIGNER_INFO *si)
{
ASN1_TYPE *attr;
const unsigned char *p;
+
attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificate);
- if (!attr)
+ if (attr == NULL)
return NULL;
p = attr->value.sequence->data;
return d2i_ESS_SIGNING_CERT(NULL, &p, attr->value.sequence->length);
}
-static ESS_SIGNING_CERT_V2 *ess_get_signing_cert_v2(PKCS7_SIGNER_INFO *si)
+static
+ESS_SIGNING_CERT_V2 *ossl_ess_get_signing_cert_v2(const PKCS7_SIGNER_INFO *si)
{
ASN1_TYPE *attr;
const unsigned char *p;
@@ -280,85 +228,16 @@ static ESS_SIGNING_CERT_V2 *ess_get_signing_cert_v2(PKCS7_SIGNER_INFO *si)
return d2i_ESS_SIGNING_CERT_V2(NULL, &p, attr->value.sequence->length);
}
-/* Returns < 0 if certificate is not found, certificate index otherwise. */
-static int ts_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert)
+static int ts_check_signing_certs(const PKCS7_SIGNER_INFO *si,
+ const STACK_OF(X509) *chain)
{
- int i;
- unsigned char cert_sha1[SHA_DIGEST_LENGTH];
-
- if (!cert_ids || !cert)
- return -1;
+ ESS_SIGNING_CERT *ss = ossl_ess_get_signing_cert(si);
+ ESS_SIGNING_CERT_V2 *ssv2 = ossl_ess_get_signing_cert_v2(si);
+ int ret = OSSL_ESS_check_signing_certs(ss, ssv2, chain, 1) > 0;
- /* Recompute SHA1 hash of certificate if necessary (side effect). */
- X509_check_purpose(cert, -1, 0);
-
- if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL))
- return -1;
-
- /* Look for cert in the cert_ids vector. */
- for (i = 0; i < sk_ESS_CERT_ID_num(cert_ids); ++i) {
- ESS_CERT_ID *cid = sk_ESS_CERT_ID_value(cert_ids, i);
-
- if (cid->hash->length == SHA_DIGEST_LENGTH
- && memcmp(cid->hash->data, cert_sha1, SHA_DIGEST_LENGTH) == 0) {
- ESS_ISSUER_SERIAL *is = cid->issuer_serial;
- if (!is || !ts_issuer_serial_cmp(is, cert))
- return i;
- }
- }
-
- return -1;
-}
-
-/* Returns < 0 if certificate is not found, certificate index otherwise. */
-static int ts_find_cert_v2(STACK_OF(ESS_CERT_ID_V2) *cert_ids, X509 *cert)
-{
- int i;
- unsigned char cert_digest[EVP_MAX_MD_SIZE];
- unsigned int len;
-
- /* Look for cert in the cert_ids vector. */
- for (i = 0; i < sk_ESS_CERT_ID_V2_num(cert_ids); ++i) {
- ESS_CERT_ID_V2 *cid = sk_ESS_CERT_ID_V2_value(cert_ids, i);
- const EVP_MD *md;
-
- if (cid->hash_alg != NULL)
- md = EVP_get_digestbyobj(cid->hash_alg->algorithm);
- else
- md = EVP_sha256();
-
- if (!X509_digest(cert, md, cert_digest, &len))
- return -1;
- if (cid->hash->length != (int)len)
- return -1;
-
- if (memcmp(cid->hash->data, cert_digest, cid->hash->length) == 0) {
- ESS_ISSUER_SERIAL *is = cid->issuer_serial;
-
- if (is == NULL || !ts_issuer_serial_cmp(is, cert))
- return i;
- }
- }
-
- return -1;
-}
-
-static int ts_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509 *cert)
-{
- GENERAL_NAME *issuer;
-
- if (!is || !cert || sk_GENERAL_NAME_num(is->issuer) != 1)
- return -1;
-
- issuer = sk_GENERAL_NAME_value(is->issuer, 0);
- if (issuer->type != GEN_DIRNAME
- || X509_NAME_cmp(issuer->d.dirn, X509_get_issuer_name(cert)))
- return -1;
-
- if (ASN1_INTEGER_cmp(is->serial, X509_get_serialNumber(cert)))
- return -1;
-
- return 0;
+ ESS_SIGNING_CERT_free(ss);
+ ESS_SIGNING_CERT_V2_free(ssv2);
+ return ret;
}
/*-
@@ -432,7 +311,7 @@ static int int_ts_RESP_verify_token(TS_VERIFY_CTX *ctx,
goto err;
if ((flags & TS_VFY_VERSION)
&& TS_TST_INFO_get_version(tst_info) != 1) {
- TSerr(TS_F_INT_TS_RESP_VERIFY_TOKEN, TS_R_UNSUPPORTED_VERSION);
+ ERR_raise(ERR_LIB_TS, TS_R_UNSUPPORTED_VERSION);
goto err;
}
if ((flags & TS_VFY_POLICY)
@@ -452,12 +331,12 @@ static int int_ts_RESP_verify_token(TS_VERIFY_CTX *ctx,
goto err;
if ((flags & TS_VFY_SIGNER)
&& tsa_name && !ts_check_signer_name(tsa_name, signer)) {
- TSerr(TS_F_INT_TS_RESP_VERIFY_TOKEN, TS_R_TSA_NAME_MISMATCH);
+ ERR_raise(ERR_LIB_TS, TS_R_TSA_NAME_MISMATCH);
goto err;
}
if ((flags & TS_VFY_TSA_NAME)
&& !ts_check_signer_name(ctx->tsa_name, signer)) {
- TSerr(TS_F_INT_TS_RESP_VERIFY_TOKEN, TS_R_TSA_UNTRUSTED);
+ ERR_raise(ERR_LIB_TS, TS_R_TSA_UNTRUSTED);
goto err;
}
ret = 1;
@@ -508,12 +387,11 @@ static int ts_check_status_info(TS_RESP *response)
if (failure_text[0] == '\0')
strcpy(failure_text, "unspecified");
- TSerr(TS_F_TS_CHECK_STATUS_INFO, TS_R_NO_TIME_STAMP_TOKEN);
- ERR_add_error_data(6,
- "status code: ", status_text,
- ", status text: ", embedded_status_text ?
- embedded_status_text : "unspecified",
- ", failure codes: ", failure_text);
+ ERR_raise_data(ERR_LIB_TS, TS_R_NO_TIME_STAMP_TOKEN,
+ "status code: %s, status text: %s, failure codes: %s",
+ status_text,
+ embedded_status_text ? embedded_status_text : "unspecified",
+ failure_text);
OPENSSL_free(embedded_status_text);
return 0;
@@ -521,34 +399,7 @@ static int ts_check_status_info(TS_RESP *response)
static char *ts_get_status_text(STACK_OF(ASN1_UTF8STRING) *text)
{
- int i;
- int length = 0;
- char *result = NULL;
- char *p;
-
- for (i = 0; i < sk_ASN1_UTF8STRING_num(text); ++i) {
- ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i);
- if (ASN1_STRING_length(current) > TS_MAX_STATUS_LENGTH - length - 1)
- return NULL;
- length += ASN1_STRING_length(current);
- length += 1; /* separator character */
- }
- if ((result = OPENSSL_malloc(length)) == NULL) {
- TSerr(TS_F_TS_GET_STATUS_TEXT, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- for (i = 0, p = result; i < sk_ASN1_UTF8STRING_num(text); ++i) {
- ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i);
- length = ASN1_STRING_length(current);
- if (i > 0)
- *p++ = '/';
- strncpy(p, (const char *)ASN1_STRING_get0_data(current), length);
- p += length;
- }
- *p = '\0';
-
- return result;
+ return ossl_sk_ASN1_UTF8STRING2text(text, "/", TS_MAX_STATUS_LENGTH);
}
static int ts_check_policy(const ASN1_OBJECT *req_oid,
@@ -557,7 +408,7 @@ static int ts_check_policy(const ASN1_OBJECT *req_oid,
const ASN1_OBJECT *resp_oid = tst_info->policy_id;
if (OBJ_cmp(req_oid, resp_oid) != 0) {
- TSerr(TS_F_TS_CHECK_POLICY, TS_R_POLICY_MISMATCH);
+ ERR_raise(ERR_LIB_TS, TS_R_POLICY_MISMATCH);
return 0;
}
@@ -570,9 +421,10 @@ static int ts_compute_imprint(BIO *data, TS_TST_INFO *tst_info,
{
TS_MSG_IMPRINT *msg_imprint = tst_info->msg_imprint;
X509_ALGOR *md_alg_resp = msg_imprint->hash_algo;
- const EVP_MD *md;
+ EVP_MD *md = NULL;
EVP_MD_CTX *md_ctx = NULL;
unsigned char buffer[4096];
+ char name[OSSL_MAX_NAME_SIZE];
int length;
*md_alg = NULL;
@@ -580,26 +432,39 @@ static int ts_compute_imprint(BIO *data, TS_TST_INFO *tst_info,
if ((*md_alg = X509_ALGOR_dup(md_alg_resp)) == NULL)
goto err;
- if ((md = EVP_get_digestbyobj((*md_alg)->algorithm)) == NULL) {
- TSerr(TS_F_TS_COMPUTE_IMPRINT, TS_R_UNSUPPORTED_MD_ALGORITHM);
+
+ OBJ_obj2txt(name, sizeof(name), md_alg_resp->algorithm, 0);
+
+ (void)ERR_set_mark();
+ md = EVP_MD_fetch(NULL, name, NULL);
+
+ if (md == NULL)
+ md = (EVP_MD *)EVP_get_digestbyname(name);
+
+ if (md == NULL) {
+ (void)ERR_clear_last_mark();
goto err;
}
- length = EVP_MD_size(md);
+ (void)ERR_pop_to_mark();
+
+ length = EVP_MD_get_size(md);
if (length < 0)
goto err;
*imprint_len = length;
if ((*imprint = OPENSSL_malloc(*imprint_len)) == NULL) {
- TSerr(TS_F_TS_COMPUTE_IMPRINT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
goto err;
}
md_ctx = EVP_MD_CTX_new();
if (md_ctx == NULL) {
- TSerr(TS_F_TS_COMPUTE_IMPRINT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EVP_DigestInit(md_ctx, md))
goto err;
+ EVP_MD_free(md);
+ md = NULL;
while ((length = BIO_read(data, buffer, sizeof(buffer))) > 0) {
if (!EVP_DigestUpdate(md_ctx, buffer, length))
goto err;
@@ -611,6 +476,7 @@ static int ts_compute_imprint(BIO *data, TS_TST_INFO *tst_info,
return 1;
err:
EVP_MD_CTX_free(md_ctx);
+ EVP_MD_free(md);
X509_ALGOR_free(*md_alg);
*md_alg = NULL;
OPENSSL_free(*imprint);
@@ -643,7 +509,7 @@ static int ts_check_imprints(X509_ALGOR *algor_a,
memcmp(imprint_a, ASN1_STRING_get0_data(b->hashed_msg), len_a) == 0;
err:
if (!ret)
- TSerr(TS_F_TS_CHECK_IMPRINTS, TS_R_MESSAGE_IMPRINT_MISMATCH);
+ ERR_raise(ERR_LIB_TS, TS_R_MESSAGE_IMPRINT_MISMATCH);
return ret;
}
@@ -652,13 +518,13 @@ static int ts_check_nonces(const ASN1_INTEGER *a, TS_TST_INFO *tst_info)
const ASN1_INTEGER *b = tst_info->nonce;
if (!b) {
- TSerr(TS_F_TS_CHECK_NONCES, TS_R_NONCE_NOT_RETURNED);
+ ERR_raise(ERR_LIB_TS, TS_R_NONCE_NOT_RETURNED);
return 0;
}
/* No error if a nonce is returned without being requested. */
if (ASN1_INTEGER_cmp(a, b) != 0) {
- TSerr(TS_F_TS_CHECK_NONCES, TS_R_NONCE_MISMATCH);
+ ERR_raise(ERR_LIB_TS, TS_R_NONCE_MISMATCH);
return 0;
}
diff --git a/crypto/ts/ts_verify_ctx.c b/crypto/ts/ts_verify_ctx.c
index b504649a415f..2f6f00c0ccd6 100644
--- a/crypto/ts/ts_verify_ctx.c
+++ b/crypto/ts/ts_verify_ctx.c
@@ -1,7 +1,7 @@
/*
* Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -17,7 +17,7 @@ TS_VERIFY_CTX *TS_VERIFY_CTX_new(void)
TS_VERIFY_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL)
- TSerr(TS_F_TS_VERIFY_CTX_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE);
return ctx;
}
@@ -60,7 +60,7 @@ X509_STORE *TS_VERIFY_CTX_set_store(TS_VERIFY_CTX *ctx, X509_STORE *s)
return ctx->store;
}
-STACK_OF(X509) *TS_VERIFY_CTS_set_certs(TS_VERIFY_CTX *ctx,
+STACK_OF(X509) *TS_VERIFY_CTX_set_certs(TS_VERIFY_CTX *ctx,
STACK_OF(X509) *certs)
{
ctx->certs = certs;
diff --git a/crypto/txt_db/txt_db.c b/crypto/txt_db/txt_db.c
index cbb81905ac81..2c1cbfb4f129 100644
--- a/crypto/txt_db/txt_db.c
+++ b/crypto/txt_db/txt_db.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/ui/ui_err.c b/crypto/ui/ui_err.c
index b806872c30bd..9b9c12133270 100644
--- a/crypto/ui/ui_err.c
+++ b/crypto/ui/ui_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,39 +10,10 @@
#include <openssl/err.h>
#include <openssl/uierr.h>
+#include "crypto/uierr.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA UI_str_functs[] = {
- {ERR_PACK(ERR_LIB_UI, UI_F_CLOSE_CONSOLE, 0), "close_console"},
- {ERR_PACK(ERR_LIB_UI, UI_F_ECHO_CONSOLE, 0), "echo_console"},
- {ERR_PACK(ERR_LIB_UI, UI_F_GENERAL_ALLOCATE_BOOLEAN, 0),
- "general_allocate_boolean"},
- {ERR_PACK(ERR_LIB_UI, UI_F_GENERAL_ALLOCATE_PROMPT, 0),
- "general_allocate_prompt"},
- {ERR_PACK(ERR_LIB_UI, UI_F_NOECHO_CONSOLE, 0), "noecho_console"},
- {ERR_PACK(ERR_LIB_UI, UI_F_OPEN_CONSOLE, 0), "open_console"},
- {ERR_PACK(ERR_LIB_UI, UI_F_UI_CONSTRUCT_PROMPT, 0), "UI_construct_prompt"},
- {ERR_PACK(ERR_LIB_UI, UI_F_UI_CREATE_METHOD, 0), "UI_create_method"},
- {ERR_PACK(ERR_LIB_UI, UI_F_UI_CTRL, 0), "UI_ctrl"},
- {ERR_PACK(ERR_LIB_UI, UI_F_UI_DUP_ERROR_STRING, 0), "UI_dup_error_string"},
- {ERR_PACK(ERR_LIB_UI, UI_F_UI_DUP_INFO_STRING, 0), "UI_dup_info_string"},
- {ERR_PACK(ERR_LIB_UI, UI_F_UI_DUP_INPUT_BOOLEAN, 0),
- "UI_dup_input_boolean"},
- {ERR_PACK(ERR_LIB_UI, UI_F_UI_DUP_INPUT_STRING, 0), "UI_dup_input_string"},
- {ERR_PACK(ERR_LIB_UI, UI_F_UI_DUP_USER_DATA, 0), "UI_dup_user_data"},
- {ERR_PACK(ERR_LIB_UI, UI_F_UI_DUP_VERIFY_STRING, 0),
- "UI_dup_verify_string"},
- {ERR_PACK(ERR_LIB_UI, UI_F_UI_GET0_RESULT, 0), "UI_get0_result"},
- {ERR_PACK(ERR_LIB_UI, UI_F_UI_GET_RESULT_LENGTH, 0),
- "UI_get_result_length"},
- {ERR_PACK(ERR_LIB_UI, UI_F_UI_NEW_METHOD, 0), "UI_new_method"},
- {ERR_PACK(ERR_LIB_UI, UI_F_UI_PROCESS, 0), "UI_process"},
- {ERR_PACK(ERR_LIB_UI, UI_F_UI_SET_RESULT, 0), "UI_set_result"},
- {ERR_PACK(ERR_LIB_UI, UI_F_UI_SET_RESULT_EX, 0), "UI_set_result_ex"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA UI_str_reasons[] = {
{ERR_PACK(ERR_LIB_UI, 0, UI_R_COMMON_OK_AND_CANCEL_CHARACTERS),
"common ok and cancel characters"},
@@ -66,13 +37,11 @@ static const ERR_STRING_DATA UI_str_reasons[] = {
#endif
-int ERR_load_UI_strings(void)
+int ossl_err_load_UI_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(UI_str_functs[0].error) == NULL) {
- ERR_load_strings_const(UI_str_functs);
+ if (ERR_reason_error_string(UI_str_reasons[0].error) == NULL)
ERR_load_strings_const(UI_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/ui/ui_lib.c b/crypto/ui/ui_lib.c
index 49cc45057c4c..1ff8c6fa35f3 100644
--- a/crypto/ui/ui_lib.c
+++ b/crypto/ui/ui_lib.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -25,13 +25,13 @@ UI *UI_new_method(const UI_METHOD *method)
UI *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- UIerr(UI_F_UI_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
- UIerr(UI_F_UI_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
@@ -43,7 +43,7 @@ UI *UI_new_method(const UI_METHOD *method)
ret->meth = method;
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data)) {
- OPENSSL_free(ret);
+ UI_free(ret);
return NULL;
}
return ret;
@@ -102,11 +102,11 @@ static UI_STRING *general_allocate_prompt(UI *ui, const char *prompt,
UI_STRING *ret = NULL;
if (prompt == NULL) {
- UIerr(UI_F_GENERAL_ALLOCATE_PROMPT, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_UI, ERR_R_PASSED_NULL_PARAMETER);
} else if ((type == UIT_PROMPT || type == UIT_VERIFY
|| type == UIT_BOOLEAN) && result_buf == NULL) {
- UIerr(UI_F_GENERAL_ALLOCATE_PROMPT, UI_R_NO_RESULT_BUFFER);
- } else if ((ret = OPENSSL_malloc(sizeof(*ret))) != NULL) {
+ ERR_raise(ERR_LIB_UI, UI_R_NO_RESULT_BUFFER);
+ } else if ((ret = OPENSSL_zalloc(sizeof(*ret))) != NULL) {
ret->out_string = prompt;
ret->flags = prompt_freeable ? OUT_STRING_FREEABLE : 0;
ret->input_flags = input_flags;
@@ -157,14 +157,13 @@ static int general_allocate_boolean(UI *ui,
const char *p;
if (ok_chars == NULL) {
- UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_UI, ERR_R_PASSED_NULL_PARAMETER);
} else if (cancel_chars == NULL) {
- UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_UI, ERR_R_PASSED_NULL_PARAMETER);
} else {
for (p = ok_chars; *p != '\0'; p++) {
if (strchr(cancel_chars, *p) != NULL) {
- UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,
- UI_R_COMMON_OK_AND_CANCEL_CHARACTERS);
+ ERR_raise(ERR_LIB_UI, UI_R_COMMON_OK_AND_CANCEL_CHARACTERS);
}
}
@@ -212,7 +211,7 @@ int UI_dup_input_string(UI *ui, const char *prompt, int flags,
if (prompt != NULL) {
prompt_copy = OPENSSL_strdup(prompt);
if (prompt_copy == NULL) {
- UIerr(UI_F_UI_DUP_INPUT_STRING, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
return 0;
}
}
@@ -240,7 +239,7 @@ int UI_dup_verify_string(UI *ui, const char *prompt, int flags,
if (prompt != NULL) {
prompt_copy = OPENSSL_strdup(prompt);
if (prompt_copy == NULL) {
- UIerr(UI_F_UI_DUP_VERIFY_STRING, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
return -1;
}
}
@@ -271,7 +270,7 @@ int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc,
if (prompt != NULL) {
prompt_copy = OPENSSL_strdup(prompt);
if (prompt_copy == NULL) {
- UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -279,7 +278,7 @@ int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc,
if (action_desc != NULL) {
action_desc_copy = OPENSSL_strdup(action_desc);
if (action_desc_copy == NULL) {
- UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -287,7 +286,7 @@ int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc,
if (ok_chars != NULL) {
ok_chars_copy = OPENSSL_strdup(ok_chars);
if (ok_chars_copy == NULL) {
- UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -295,7 +294,7 @@ int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc,
if (cancel_chars != NULL) {
cancel_chars_copy = OPENSSL_strdup(cancel_chars);
if (cancel_chars_copy == NULL) {
- UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -324,7 +323,7 @@ int UI_dup_info_string(UI *ui, const char *text)
if (text != NULL) {
text_copy = OPENSSL_strdup(text);
if (text_copy == NULL) {
- UIerr(UI_F_UI_DUP_INFO_STRING, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
return -1;
}
}
@@ -346,7 +345,7 @@ int UI_dup_error_string(UI *ui, const char *text)
if (text != NULL) {
text_copy = OPENSSL_strdup(text);
if (text_copy == NULL) {
- UIerr(UI_F_UI_DUP_ERROR_STRING, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
return -1;
}
}
@@ -354,32 +353,32 @@ int UI_dup_error_string(UI *ui, const char *text)
0, 0, NULL);
}
-char *UI_construct_prompt(UI *ui, const char *object_desc,
+char *UI_construct_prompt(UI *ui, const char *phrase_desc,
const char *object_name)
{
char *prompt = NULL;
- if (ui->meth->ui_construct_prompt != NULL)
- prompt = ui->meth->ui_construct_prompt(ui, object_desc, object_name);
+ if (ui != NULL && ui->meth != NULL && ui->meth->ui_construct_prompt != NULL)
+ prompt = ui->meth->ui_construct_prompt(ui, phrase_desc, object_name);
else {
char prompt1[] = "Enter ";
char prompt2[] = " for ";
char prompt3[] = ":";
int len = 0;
- if (object_desc == NULL)
+ if (phrase_desc == NULL)
return NULL;
- len = sizeof(prompt1) - 1 + strlen(object_desc);
+ len = sizeof(prompt1) - 1 + strlen(phrase_desc);
if (object_name != NULL)
len += sizeof(prompt2) - 1 + strlen(object_name);
len += sizeof(prompt3) - 1;
if ((prompt = OPENSSL_malloc(len + 1)) == NULL) {
- UIerr(UI_F_UI_CONSTRUCT_PROMPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
return NULL;
}
OPENSSL_strlcpy(prompt, prompt1, len + 1);
- OPENSSL_strlcat(prompt, object_desc, len + 1);
+ OPENSSL_strlcat(prompt, phrase_desc, len + 1);
if (object_name != NULL) {
OPENSSL_strlcat(prompt, prompt2, len + 1);
OPENSSL_strlcat(prompt, object_name, len + 1);
@@ -408,13 +407,13 @@ int UI_dup_user_data(UI *ui, void *user_data)
if (ui->meth->ui_duplicate_data == NULL
|| ui->meth->ui_destroy_data == NULL) {
- UIerr(UI_F_UI_DUP_USER_DATA, UI_R_USER_DATA_DUPLICATION_UNSUPPORTED);
+ ERR_raise(ERR_LIB_UI, UI_R_USER_DATA_DUPLICATION_UNSUPPORTED);
return -1;
}
duplicate = ui->meth->ui_duplicate_data(ui, user_data);
if (duplicate == NULL) {
- UIerr(UI_F_UI_DUP_USER_DATA, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
return -1;
}
@@ -432,11 +431,11 @@ void *UI_get0_user_data(UI *ui)
const char *UI_get0_result(UI *ui, int i)
{
if (i < 0) {
- UIerr(UI_F_UI_GET0_RESULT, UI_R_INDEX_TOO_SMALL);
+ ERR_raise(ERR_LIB_UI, UI_R_INDEX_TOO_SMALL);
return NULL;
}
if (i >= sk_UI_STRING_num(ui->strings)) {
- UIerr(UI_F_UI_GET0_RESULT, UI_R_INDEX_TOO_LARGE);
+ ERR_raise(ERR_LIB_UI, UI_R_INDEX_TOO_LARGE);
return NULL;
}
return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i));
@@ -445,11 +444,11 @@ const char *UI_get0_result(UI *ui, int i)
int UI_get_result_length(UI *ui, int i)
{
if (i < 0) {
- UIerr(UI_F_UI_GET_RESULT_LENGTH, UI_R_INDEX_TOO_SMALL);
+ ERR_raise(ERR_LIB_UI, UI_R_INDEX_TOO_SMALL);
return -1;
}
if (i >= sk_UI_STRING_num(ui->strings)) {
- UIerr(UI_F_UI_GET_RESULT_LENGTH, UI_R_INDEX_TOO_LARGE);
+ ERR_raise(ERR_LIB_UI, UI_R_INDEX_TOO_LARGE);
return -1;
}
return UI_get_result_string_length(sk_UI_STRING_value(ui->strings, i));
@@ -541,17 +540,15 @@ int UI_process(UI *ui)
ok = -1;
}
- if (ok == -1) {
- UIerr(UI_F_UI_PROCESS, UI_R_PROCESSING_ERROR);
- ERR_add_error_data(2, "while ", state);
- }
+ if (ok == -1)
+ ERR_raise_data(ERR_LIB_UI, UI_R_PROCESSING_ERROR, "while %s", state);
return ok;
}
int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void))
{
if (ui == NULL) {
- UIerr(UI_F_UI_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_UI, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
switch (cmd) {
@@ -569,7 +566,7 @@ int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void))
default:
break;
}
- UIerr(UI_F_UI_CTRL, UI_R_UNKNOWN_CONTROL_COMMAND);
+ ERR_raise(ERR_LIB_UI, UI_R_UNKNOWN_CONTROL_COMMAND);
return -1;
}
@@ -578,7 +575,7 @@ int UI_set_ex_data(UI *r, int idx, void *arg)
return CRYPTO_set_ex_data(&r->ex_data, idx, arg);
}
-void *UI_get_ex_data(UI *r, int idx)
+void *UI_get_ex_data(const UI *r, int idx)
{
return CRYPTO_get_ex_data(&r->ex_data, idx);
}
@@ -605,7 +602,7 @@ UI_METHOD *UI_create_method(const char *name)
if (ui_method)
OPENSSL_free(ui_method->name);
OPENSSL_free(ui_method);
- UIerr(UI_F_UI_CREATE_METHOD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
return NULL;
}
return ui_method;
@@ -688,10 +685,8 @@ int UI_method_set_data_duplicator(UI_METHOD *method,
int UI_method_set_prompt_constructor(UI_METHOD *method,
char *(*prompt_constructor) (UI *ui,
- const char
- *object_desc,
- const char
- *object_name))
+ const char *,
+ const char *))
{
if (method != NULL) {
method->ui_construct_prompt = prompt_constructor;
@@ -874,13 +869,6 @@ int UI_get_result_maxsize(UI_STRING *uis)
int UI_set_result(UI *ui, UI_STRING *uis, const char *result)
{
-#if 0
- /*
- * This is placed here solely to preserve UI_F_UI_SET_RESULT
- * To be removed for OpenSSL 1.2.0
- */
- UIerr(UI_F_UI_SET_RESULT, ERR_R_DISABLED);
-#endif
return UI_set_result_ex(ui, uis, result, strlen(result));
}
@@ -891,33 +879,25 @@ int UI_set_result_ex(UI *ui, UI_STRING *uis, const char *result, int len)
switch (uis->type) {
case UIT_PROMPT:
case UIT_VERIFY:
- {
- char number1[DECIMAL_SIZE(uis->_.string_data.result_minsize) + 1];
- char number2[DECIMAL_SIZE(uis->_.string_data.result_maxsize) + 1];
-
- BIO_snprintf(number1, sizeof(number1), "%d",
- uis->_.string_data.result_minsize);
- BIO_snprintf(number2, sizeof(number2), "%d",
- uis->_.string_data.result_maxsize);
-
- if (len < uis->_.string_data.result_minsize) {
- ui->flags |= UI_FLAG_REDOABLE;
- UIerr(UI_F_UI_SET_RESULT_EX, UI_R_RESULT_TOO_SMALL);
- ERR_add_error_data(5, "You must type in ",
- number1, " to ", number2, " characters");
- return -1;
- }
- if (len > uis->_.string_data.result_maxsize) {
- ui->flags |= UI_FLAG_REDOABLE;
- UIerr(UI_F_UI_SET_RESULT_EX, UI_R_RESULT_TOO_LARGE);
- ERR_add_error_data(5, "You must type in ",
- number1, " to ", number2, " characters");
- return -1;
- }
+ if (len < uis->_.string_data.result_minsize) {
+ ui->flags |= UI_FLAG_REDOABLE;
+ ERR_raise_data(ERR_LIB_UI, UI_R_RESULT_TOO_SMALL,
+ "You must type in %d to %d characters",
+ uis->_.string_data.result_minsize,
+ uis->_.string_data.result_maxsize);
+ return -1;
+ }
+ if (len > uis->_.string_data.result_maxsize) {
+ ui->flags |= UI_FLAG_REDOABLE;
+ ERR_raise_data(ERR_LIB_UI, UI_R_RESULT_TOO_LARGE,
+ "You must type in %d to %d characters",
+ uis->_.string_data.result_minsize,
+ uis->_.string_data.result_maxsize);
+ return -1;
}
if (uis->result_buf == NULL) {
- UIerr(UI_F_UI_SET_RESULT_EX, UI_R_NO_RESULT_BUFFER);
+ ERR_raise(ERR_LIB_UI, UI_R_NO_RESULT_BUFFER);
return -1;
}
@@ -931,7 +911,7 @@ int UI_set_result_ex(UI *ui, UI_STRING *uis, const char *result, int len)
const char *p;
if (uis->result_buf == NULL) {
- UIerr(UI_F_UI_SET_RESULT_EX, UI_R_NO_RESULT_BUFFER);
+ ERR_raise(ERR_LIB_UI, UI_R_NO_RESULT_BUFFER);
return -1;
}
diff --git a/crypto/ui/ui_local.h b/crypto/ui/ui_local.h
index 8a7dbda14721..36b3e6194b0a 100644
--- a/crypto/ui/ui_local.h
+++ b/crypto/ui/ui_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/ui/ui_null.c b/crypto/ui/ui_null.c
index 9ab00e0a7cb8..f002448d2cd4 100644
--- a/crypto/ui/ui_null.c
+++ b/crypto/ui/ui_null.c
@@ -1,7 +1,7 @@
/*
* Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/ui/ui_openssl.c b/crypto/ui/ui_openssl.c
index 0f630a5bd963..8007f2f70c87 100644
--- a/crypto/ui/ui_openssl.c
+++ b/crypto/ui/ui_openssl.c
@@ -1,7 +1,7 @@
/*
* Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -34,11 +34,7 @@
# include <errno.h>
# if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS)
-# ifdef OPENSSL_UNISTD
-# include OPENSSL_UNISTD
-# else
-# include <unistd.h>
-# endif
+# include <unistd.h>
/*
* If unistd.h defines _POSIX_VERSION, we conclude that we are on a POSIX
* system and have sigaction and termios.
@@ -92,8 +88,8 @@
* We know that VMS, MSDOS, VXWORKS, use entirely other mechanisms.
*/
# elif !defined(OPENSSL_SYS_VMS) \
- && !defined(OPENSSL_SYS_MSDOS) \
- && !defined(OPENSSL_SYS_VXWORKS)
+ && !defined(OPENSSL_SYS_MSDOS) \
+ && !defined(OPENSSL_SYS_VXWORKS)
# define TERMIOS
# undef TERMIO
# undef SGTTY
@@ -131,7 +127,7 @@
# define TTY_set(tty,data) ioctl(tty,TIOCSETP,data)
# endif
-# if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS)
+# if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) && ! (defined(OPENSSL_SYS_TANDEM) && defined(_SPT_MODEL_))
# include <sys/ioctl.h>
# endif
@@ -376,7 +372,8 @@ static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl)
/* Internal functions to open, handle and close a channel to the console. */
static int open_console(UI *ui)
{
- CRYPTO_THREAD_write_lock(ui->lock);
+ if (!CRYPTO_THREAD_write_lock(ui->lock))
+ return 0;
is_a_tty = 1;
# if defined(OPENSSL_SYS_VXWORKS)
@@ -455,15 +452,12 @@ static int open_console(UI *ui)
* which seems appropriate.
*/
if (errno == ENODEV)
- is_a_tty = 0;
+ is_a_tty = 0;
else
# endif
{
- char tmp_num[10];
- BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%d", errno);
- UIerr(UI_F_OPEN_CONSOLE, UI_R_UNKNOWN_TTYGET_ERRNO_VALUE);
- ERR_add_error_data(2, "errno=", tmp_num);
-
+ ERR_raise_data(ERR_LIB_UI, UI_R_UNKNOWN_TTYGET_ERRNO_VALUE,
+ "errno=%d", errno);
return 0;
}
}
@@ -473,11 +467,8 @@ static int open_console(UI *ui)
/* if there isn't a TT device, something is very wrong */
if (status != SS$_NORMAL) {
- char tmp_num[12];
-
- BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%%X%08X", status);
- UIerr(UI_F_OPEN_CONSOLE, UI_R_SYSASSIGN_ERROR);
- ERR_add_error_data(2, "status=", tmp_num);
+ ERR_raise_data(ERR_LIB_UI, UI_R_SYSASSIGN_ERROR,
+ "status=%%X%08X", status);
return 0;
}
@@ -510,15 +501,9 @@ static int noecho_console(UI *ui)
status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12,
0, 0, 0, 0);
if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) {
- char tmp_num[2][12];
-
- BIO_snprintf(tmp_num[0], sizeof(tmp_num[0]) - 1, "%%X%08X",
- status);
- BIO_snprintf(tmp_num[1], sizeof(tmp_num[1]) - 1, "%%X%08X",
- iosb.iosb$w_value);
- UIerr(UI_F_NOECHO_CONSOLE, UI_R_SYSQIOW_ERROR);
- ERR_add_error_data(5, "status=", tmp_num[0],
- ",", "iosb.iosb$w_value=", tmp_num[1]);
+ ERR_raise_data(ERR_LIB_UI, UI_R_SYSQIOW_ERROR,
+ "status=%%X%08X, iosb.iosb$w_value=%%X%08X",
+ status, iosb.iosb$w_value);
return 0;
}
}
@@ -548,15 +533,9 @@ static int echo_console(UI *ui)
status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12,
0, 0, 0, 0);
if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) {
- char tmp_num[2][12];
-
- BIO_snprintf(tmp_num[0], sizeof(tmp_num[0]) - 1, "%%X%08X",
- status);
- BIO_snprintf(tmp_num[1], sizeof(tmp_num[1]) - 1, "%%X%08X",
- iosb.iosb$w_value);
- UIerr(UI_F_ECHO_CONSOLE, UI_R_SYSQIOW_ERROR);
- ERR_add_error_data(5, "status=", tmp_num[0],
- ",", "iosb.iosb$w_value=", tmp_num[1]);
+ ERR_raise_data(ERR_LIB_UI, UI_R_SYSQIOW_ERROR,
+ "status=%%X%08X, iosb.iosb$w_value=%%X%08X",
+ status, iosb.iosb$w_value);
return 0;
}
}
@@ -581,11 +560,8 @@ static int close_console(UI *ui)
# ifdef OPENSSL_SYS_VMS
status = sys$dassgn(channel);
if (status != SS$_NORMAL) {
- char tmp_num[12];
-
- BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%%X%08X", status);
- UIerr(UI_F_CLOSE_CONSOLE, UI_R_SYSDASSGN_ERROR);
- ERR_add_error_data(2, "status=", tmp_num);
+ ERR_raise_data(ERR_LIB_UI, UI_R_SYSDASSGN_ERROR,
+ "status=%%X%08X", status);
ret = 0;
}
# endif
diff --git a/crypto/ui/ui_util.c b/crypto/ui/ui_util.c
index 32a3c4e38de2..80297969ab1d 100644
--- a/crypto/ui/ui_util.c
+++ b/crypto/ui/ui_util.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -71,12 +71,14 @@ static void ui_new_method_data(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
}
static int ui_dup_method_data(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from,
- void *from_d, int idx, long argl, void *argp)
+ void **pptr, int idx, long argl, void *argp)
{
- void **pptr = (void **)from_d;
- if (*pptr != NULL)
+ if (*pptr != NULL) {
*pptr = OPENSSL_memdup(*pptr, sizeof(struct pem_password_cb_data));
- return 1;
+ if (*pptr != NULL)
+ return 1;
+ }
+ return 0;
}
static void ui_free_method_data(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
@@ -115,7 +117,7 @@ static int ui_read(UI *ui, UI_STRING *uis)
if (len >= 0)
result[len] = '\0';
- if (len <= 0)
+ if (len < 0)
return len;
if (UI_set_result_ex(ui, uis, result, len) >= 0)
return 1;
@@ -151,7 +153,7 @@ UI_METHOD *UI_UTIL_wrap_read_pem_callback(pem_password_cb *cb, int rwflag)
|| UI_method_set_writer(ui_method, ui_write) < 0
|| UI_method_set_closer(ui_method, ui_close) < 0
|| !RUN_ONCE(&get_index_once, ui_method_data_index_init)
- || UI_method_set_ex_data(ui_method, ui_method_data_index, data) < 0) {
+ || !UI_method_set_ex_data(ui_method, ui_method_data_index, data)) {
UI_destroy_method(ui_method);
OPENSSL_free(data);
return NULL;
diff --git a/crypto/uid.c b/crypto/uid.c
index a9eae36818ca..698127779f54 100644
--- a/crypto/uid.c
+++ b/crypto/uid.c
@@ -1,7 +1,7 @@
/*
* Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -19,7 +19,7 @@ int OPENSSL_issetugid(void)
#elif defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD__ > 2) || defined(__DragonFly__) || (defined(__GLIBC__) && defined(__FreeBSD_kernel__))
-# include OPENSSL_UNISTD
+# include <unistd.h>
int OPENSSL_issetugid(void)
{
@@ -28,7 +28,7 @@ int OPENSSL_issetugid(void)
#else
-# include OPENSSL_UNISTD
+# include <unistd.h>
# include <sys/types.h>
# if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
diff --git a/crypto/vms_rms.h b/crypto/vms_rms.h
index 3b994a0aba2c..ae74ba68294e 100644
--- a/crypto/vms_rms.h
+++ b/crypto/vms_rms.h
@@ -1,7 +1,7 @@
/*
* Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/whrlpool/asm/wp-mmx.pl b/crypto/whrlpool/asm/wp-mmx.pl
index 176be50a67f2..ad2528a9e28a 100644
--- a/crypto/whrlpool/asm/wp-mmx.pl
+++ b/crypto/whrlpool/asm/wp-mmx.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -10,7 +10,7 @@
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
# project. Rights for redistribution and usage in source and binary
-# forms are granted according to the OpenSSL license.
+# forms are granted according to the License.
# ====================================================================
#
# whirlpool_block_mmx implementation.
@@ -56,8 +56,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
&asm_init($ARGV[0]);
diff --git a/crypto/whrlpool/asm/wp-x86_64.pl b/crypto/whrlpool/asm/wp-x86_64.pl
index b4fcd8be3c75..f94152af9769 100644
--- a/crypto/whrlpool/asm/wp-x86_64.pl
+++ b/crypto/whrlpool/asm/wp-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -10,7 +10,7 @@
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
# project. Rights for redistribution and usage in source and binary
-# forms are granted according to the OpenSSL license.
+# forms are granted according to the License.
# ====================================================================
#
# whirlpool_block for x86_64.
@@ -37,9 +37,10 @@
# 3 on Opteron] and which is *unacceptably* slow with 64-bit
# operand.
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -48,7 +49,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; my $dir=$1; my $xlate;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
sub L() { $code.=".byte ".join(',',@_)."\n"; }
diff --git a/crypto/whrlpool/build.info b/crypto/whrlpool/build.info
index 4b167b504ec3..c7dbecb4fd79 100644
--- a/crypto/whrlpool/build.info
+++ b/crypto/whrlpool/build.info
@@ -1,8 +1,33 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]=wp_dgst.c {- $target{wp_asm_src} -}
-GENERATE[wp-mmx.s]=asm/wp-mmx.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
-DEPEND[wp-mmx.s]=../perlasm/x86asm.pl
+$WPASM=wp_block.c
+IF[{- !$disabled{asm} -}]
+ IF[{- $config{processor} ne "386" -}]
+ $WPASM_x86=wp_block.c wp-mmx.S
+ $WPDEF_x86=WHIRLPOOL_ASM
+ ENDIF
+ $WPASM_x86_64=wp-x86_64.s
+ $WPDEF_x86_64=WHIRLPOOL_ASM
-GENERATE[wp-x86_64.s]=asm/wp-x86_64.pl $(PERLASM_SCHEME)
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+ IF[$WPASM_{- $target{asm_arch} -}]
+ $WPASM=$WPASM_{- $target{asm_arch} -}
+ $WPDEF=$WPDEF_{- $target{asm_arch} -}
+ ENDIF
+ENDIF
+
+SOURCE[../../libcrypto]=wp_dgst.c $WPASM
+DEFINE[../../libcrypto]=$WPDEF
+
+# When all deprecated symbols are removed, libcrypto doesn't export the
+# WHIRLPOOL functions, so we must include them directly in liblegacy.a
+IF[{- $disabled{'deprecated-3.0'} && !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../../providers/liblegacy.a]=wp_dgst.c $WPASM
+ DEFINE[../../providers/liblegacy.a]=$WPDEF
+ENDIF
+
+GENERATE[wp-mmx.S]=asm/wp-mmx.pl
+DEPEND[wp-mmx.S]=../perlasm/x86asm.pl
+
+GENERATE[wp-x86_64.s]=asm/wp-x86_64.pl
diff --git a/crypto/whrlpool/wp_block.c b/crypto/whrlpool/wp_block.c
index 39ad009c01bf..bcf7a199ed0e 100644
--- a/crypto/whrlpool/wp_block.c
+++ b/crypto/whrlpool/wp_block.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -36,6 +36,13 @@
*
*/
+/*
+ * Whirlpool low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include "internal/cryptlib.h"
#include "wp_local.h"
#include <string.h>
@@ -89,7 +96,6 @@ typedef u64 u64_aX;
# define OPENSSL_SMALL_FOOTPRINT
# endif
# define GO_FOR_MMX(ctx,inp,num) do { \
- extern unsigned long OPENSSL_ia32cap_P[]; \
void whirlpool_block_mmx(void *,const void *,size_t); \
if (!(OPENSSL_ia32cap_P[0] & (1<<23))) break; \
whirlpool_block_mmx(ctx->H.c,inp,num); return; \
@@ -159,7 +165,7 @@ typedef u64 u64_aX;
*/
/*
* Note that every Cn macro expands as two loads: one byte load and
- * one quadword load. One can argue that that many single-byte loads
+ * one quadword load. One can argue that many single-byte loads
* is too excessive, as one could load a quadword and "milk" it for
* eight 8-bit values instead. Well, yes, but in order to do so *and*
* avoid excessive loads you have to accommodate a handful of 64-bit
diff --git a/crypto/whrlpool/wp_dgst.c b/crypto/whrlpool/wp_dgst.c
index e8a3392268aa..4a1d912d6290 100644
--- a/crypto/whrlpool/wp_dgst.c
+++ b/crypto/whrlpool/wp_dgst.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -52,6 +52,12 @@
* input. This is done for performance.
*/
+/*
+ * Whirlpool low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <openssl/crypto.h>
#include "wp_local.h"
#include <string.h>
diff --git a/crypto/whrlpool/wp_local.h b/crypto/whrlpool/wp_local.h
index 3a81cfd58c1a..73dc2a003da3 100644
--- a/crypto/whrlpool/wp_local.h
+++ b/crypto/whrlpool/wp_local.h
@@ -1,7 +1,7 @@
/*
* Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/x509/build.info b/crypto/x509/build.info
index afd0b6134e52..8820f983bb3d 100644
--- a/crypto/x509/build.info
+++ b/crypto/x509/build.info
@@ -4,7 +4,18 @@ SOURCE[../../libcrypto]=\
x509_obj.c x509_req.c x509spki.c x509_vfy.c \
x509_set.c x509cset.c x509rset.c x509_err.c \
x509name.c x509_v3.c x509_ext.c x509_att.c \
- x509type.c x509_meth.c x509_lu.c x_all.c x509_txt.c \
- x509_trs.c by_file.c by_dir.c x509_vpm.c \
+ x509_meth.c x509_lu.c x_all.c x509_txt.c \
+ x509_trust.c by_file.c by_dir.c by_store.c x509_vpm.c \
x_crl.c t_crl.c x_req.c t_req.c x_x509.c t_x509.c \
- x_pubkey.c x_x509a.c x_attrib.c x_exten.c x_name.c
+ x_pubkey.c x_x509a.c x_attrib.c x_exten.c x_name.c \
+ v3_bcons.c v3_bitst.c v3_conf.c v3_extku.c v3_ia5.c v3_utf8.c v3_lib.c \
+ v3_prn.c v3_utl.c v3err.c v3_genn.c v3_san.c v3_skid.c v3_akid.c \
+ v3_pku.c v3_int.c v3_enum.c v3_sxnet.c v3_cpols.c v3_crld.c v3_purp.c \
+ v3_info.c v3_akeya.c v3_pmaps.c v3_pcons.c v3_ncons.c \
+ v3_pcia.c v3_pci.c v3_ist.c \
+ pcy_cache.c pcy_node.c pcy_data.c pcy_map.c pcy_tree.c pcy_lib.c \
+ v3_asid.c v3_addr.c v3_tlsf.c v3_admis.c
+
+IF[{- !$disabled{'deprecated-3.0'} -}]
+ SOURCE[../../libcrypto]=x509type.c
+ENDIF
diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c
index 46a861e90de0..cb40c7737f72 100644
--- a/crypto/x509/by_dir.c
+++ b/crypto/x509/by_dir.c
@@ -1,12 +1,21 @@
/*
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#if defined (__TANDEM) && defined (_SPT_MODEL_)
+ /*
+ * These definitions have to come first in SPT due to scoping of the
+ * declarations in c99 associated with SPT use of stat.
+ */
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif
+
#include "e_os.h"
#include "internal/cryptlib.h"
#include <stdio.h>
@@ -40,23 +49,29 @@ typedef struct lookup_dir_st {
} BY_DIR;
static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
- char **ret);
+ char **retp);
+
static int new_dir(X509_LOOKUP *lu);
static void free_dir(X509_LOOKUP *lu);
static int add_cert_dir(BY_DIR *ctx, const char *dir, int type);
static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
- X509_NAME *name, X509_OBJECT *ret);
+ const X509_NAME *name, X509_OBJECT *ret);
+static int get_cert_by_subject_ex(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
+ const X509_NAME *name, X509_OBJECT *ret,
+ OSSL_LIB_CTX *libctx, const char *propq);
static X509_LOOKUP_METHOD x509_dir_lookup = {
"Load certs from files in a directory",
- new_dir, /* new_item */
- free_dir, /* free */
- NULL, /* init */
- NULL, /* shutdown */
- dir_ctrl, /* ctrl */
- get_cert_by_subject, /* get_by_subject */
- NULL, /* get_by_issuer_serial */
- NULL, /* get_by_fingerprint */
- NULL, /* get_by_alias */
+ new_dir, /* new_item */
+ free_dir, /* free */
+ NULL, /* init */
+ NULL, /* shutdown */
+ dir_ctrl, /* ctrl */
+ get_cert_by_subject, /* get_by_subject */
+ NULL, /* get_by_issuer_serial */
+ NULL, /* get_by_fingerprint */
+ NULL, /* get_by_alias */
+ get_cert_by_subject_ex, /* get_by_subject_ex */
+ NULL, /* ctrl_ex */
};
X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void)
@@ -81,7 +96,7 @@ static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
ret = add_cert_dir(ld, X509_get_default_cert_dir(),
X509_FILETYPE_PEM);
if (!ret) {
- X509err(X509_F_DIR_CTRL, X509_R_LOADING_CERT_DIR);
+ ERR_raise(ERR_LIB_X509, X509_R_LOADING_CERT_DIR);
}
} else
ret = add_cert_dir(ld, argp, (int)argl);
@@ -95,19 +110,19 @@ static int new_dir(X509_LOOKUP *lu)
BY_DIR *a = OPENSSL_malloc(sizeof(*a));
if (a == NULL) {
- X509err(X509_F_NEW_DIR, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return 0;
}
if ((a->buffer = BUF_MEM_new()) == NULL) {
- X509err(X509_F_NEW_DIR, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
a->dirs = NULL;
a->lock = CRYPTO_THREAD_lock_new();
if (a->lock == NULL) {
BUF_MEM_free(a->buffer);
- X509err(X509_F_NEW_DIR, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
lu->method_data = a;
@@ -156,8 +171,8 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
size_t len;
const char *s, *ss, *p;
- if (dir == NULL || !*dir) {
- X509err(X509_F_ADD_CERT_DIR, X509_R_INVALID_DIRECTORY);
+ if (dir == NULL || *dir == '\0') {
+ ERR_raise(ERR_LIB_X509, X509_R_INVALID_DIRECTORY);
return 0;
}
@@ -182,13 +197,13 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
if (ctx->dirs == NULL) {
ctx->dirs = sk_BY_DIR_ENTRY_new_null();
if (!ctx->dirs) {
- X509err(X509_F_ADD_CERT_DIR, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return 0;
}
}
ent = OPENSSL_malloc(sizeof(*ent));
if (ent == NULL) {
- X509err(X509_F_ADD_CERT_DIR, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return 0;
}
ent->dir_type = type;
@@ -200,7 +215,7 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
}
if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent)) {
by_dir_entry_free(ent);
- X509err(X509_F_ADD_CERT_DIR, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return 0;
}
}
@@ -208,8 +223,9 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
return 1;
}
-static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
- X509_NAME *name, X509_OBJECT *ret)
+static int get_cert_by_subject_ex(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
+ const X509_NAME *name, X509_OBJECT *ret,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
BY_DIR *ctx;
union {
@@ -228,26 +244,26 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
stmp.type = type;
if (type == X509_LU_X509) {
- data.st_x509.cert_info.subject = name;
+ data.st_x509.cert_info.subject = (X509_NAME *)name; /* won't modify it */
stmp.data.x509 = &data.st_x509;
- postfix = "";
} else if (type == X509_LU_CRL) {
- data.crl.crl.issuer = name;
+ data.crl.crl.issuer = (X509_NAME *)name; /* won't modify it */
stmp.data.crl = &data.crl;
postfix = "r";
} else {
- X509err(X509_F_GET_CERT_BY_SUBJECT, X509_R_WRONG_LOOKUP_TYPE);
+ ERR_raise(ERR_LIB_X509, X509_R_WRONG_LOOKUP_TYPE);
goto finish;
}
if ((b = BUF_MEM_new()) == NULL) {
- X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_X509, ERR_R_BUF_LIB);
goto finish;
}
ctx = (BY_DIR *)xl->method_data;
-
- h = X509_NAME_hash(name);
+ h = X509_NAME_hash_ex(name, libctx, propq, &i);
+ if (i == 0)
+ goto finish;
for (i = 0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) {
BY_DIR_ENTRY *ent;
int idx;
@@ -256,12 +272,13 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i);
j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1;
if (!BUF_MEM_grow(b, j)) {
- X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto finish;
}
if (type == X509_LU_CRL && ent->hashes) {
htmp.hash = h;
- CRYPTO_THREAD_read_lock(ctx->lock);
+ if (!CRYPTO_THREAD_read_lock(ctx->lock))
+ goto finish;
idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);
if (idx >= 0) {
hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
@@ -277,6 +294,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
}
for (;;) {
char c = '/';
+
#ifdef OPENSSL_SYS_VMS
c = ent->dir[strlen(ent->dir) - 1];
if (c != ':' && c != '>' && c != ']') {
@@ -290,7 +308,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
} else {
c = '\0';
}
-#endif
+
if (c == '\0') {
/*
* This is special. When c == '\0', no directory separator
@@ -298,7 +316,9 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
*/
BIO_snprintf(b->data, b->max,
"%s%08lx.%s%d", ent->dir, h, postfix, k);
- } else {
+ } else
+#endif
+ {
BIO_snprintf(b->data, b->max,
"%s%c%08lx.%s%d", ent->dir, c, h, postfix, k);
}
@@ -314,7 +334,8 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
#endif
/* found one. */
if (type == X509_LU_X509) {
- if ((X509_load_cert_file(xl, b->data, ent->dir_type)) == 0)
+ if ((X509_load_cert_file_ex(xl, b->data, ent->dir_type, libctx,
+ propq)) == 0)
break;
} else if (type == X509_LU_CRL) {
if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0)
@@ -339,7 +360,8 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
* simple case where no CRL is present for a hash.
*/
if (type == X509_LU_CRL && k > 0) {
- CRYPTO_THREAD_write_lock(ctx->lock);
+ if (!CRYPTO_THREAD_write_lock(ctx->lock))
+ goto finish;
/*
* Look for entry again in case another thread added an entry
* first.
@@ -353,7 +375,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
hent = OPENSSL_malloc(sizeof(*hent));
if (hent == NULL) {
CRYPTO_THREAD_unlock(ctx->lock);
- X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
ok = 0;
goto finish;
}
@@ -362,7 +384,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) {
CRYPTO_THREAD_unlock(ctx->lock);
OPENSSL_free(hent);
- X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
ok = 0;
goto finish;
}
@@ -398,3 +420,9 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
BUF_MEM_free(b);
return ok;
}
+
+static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
+ const X509_NAME *name, X509_OBJECT *ret)
+{
+ return get_cert_by_subject_ex(xl, type, name, ret, NULL, NULL);
+}
diff --git a/crypto/x509/by_file.c b/crypto/x509/by_file.c
index 237b362e2746..37d73ca84c54 100644
--- a/crypto/x509/by_file.c
+++ b/crypto/x509/by_file.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -19,6 +19,11 @@
static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
long argl, char **ret);
+static int by_file_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argc,
+ long argl, char **ret, OSSL_LIB_CTX *libctx,
+ const char *propq);
+
+
static X509_LOOKUP_METHOD x509_file_lookup = {
"Load file into cache",
NULL, /* new_item */
@@ -30,6 +35,8 @@ static X509_LOOKUP_METHOD x509_file_lookup = {
NULL, /* get_by_issuer_serial */
NULL, /* get_by_fingerprint */
NULL, /* get_by_alias */
+ NULL, /* get_by_subject_ex */
+ by_file_ctrl_ex, /* ctrl_ex */
};
X509_LOOKUP_METHOD *X509_LOOKUP_file(void)
@@ -37,8 +44,9 @@ X509_LOOKUP_METHOD *X509_LOOKUP_file(void)
return &x509_file_lookup;
}
-static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp,
- long argl, char **ret)
+static int by_file_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argp,
+ long argl, char **ret, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
int ok = 0;
const char *file;
@@ -48,30 +56,38 @@ static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp,
if (argl == X509_FILETYPE_DEFAULT) {
file = ossl_safe_getenv(X509_get_default_cert_file_env());
if (file)
- ok = (X509_load_cert_crl_file(ctx, file,
- X509_FILETYPE_PEM) != 0);
+ ok = (X509_load_cert_crl_file_ex(ctx, file, X509_FILETYPE_PEM,
+ libctx, propq) != 0);
else
- ok = (X509_load_cert_crl_file
- (ctx, X509_get_default_cert_file(),
- X509_FILETYPE_PEM) != 0);
+ ok = (X509_load_cert_crl_file_ex(
+ ctx, X509_get_default_cert_file(),
+ X509_FILETYPE_PEM, libctx, propq) != 0);
if (!ok) {
- X509err(X509_F_BY_FILE_CTRL, X509_R_LOADING_DEFAULTS);
+ ERR_raise(ERR_LIB_X509, X509_R_LOADING_DEFAULTS);
}
} else {
if (argl == X509_FILETYPE_PEM)
- ok = (X509_load_cert_crl_file(ctx, argp,
- X509_FILETYPE_PEM) != 0);
+ ok = (X509_load_cert_crl_file_ex(ctx, argp, X509_FILETYPE_PEM,
+ libctx, propq) != 0);
else
- ok = (X509_load_cert_file(ctx, argp, (int)argl) != 0);
+ ok = (X509_load_cert_file_ex(ctx, argp, (int)argl, libctx,
+ propq) != 0);
}
break;
}
return ok;
}
-int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
+static int by_file_ctrl(X509_LOOKUP *ctx, int cmd,
+ const char *argp, long argl, char **ret)
+{
+ return by_file_ctrl_ex(ctx, cmd, argp, argl, ret, NULL, NULL);
+}
+
+int X509_load_cert_file_ex(X509_LOOKUP *ctx, const char *file, int type,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
int ret = 0;
BIO *in = NULL;
@@ -81,23 +97,34 @@ int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
in = BIO_new(BIO_s_file());
if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
- X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_SYS_LIB);
+ ERR_raise(ERR_LIB_X509, ERR_R_SYS_LIB);
+ goto err;
+ }
+
+ if (type != X509_FILETYPE_PEM && type != X509_FILETYPE_ASN1) {
+ ERR_raise(ERR_LIB_X509, X509_R_BAD_X509_FILETYPE);
+ goto err;
+ }
+ x = X509_new_ex(libctx, propq);
+ if (x == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
if (type == X509_FILETYPE_PEM) {
for (;;) {
- x = PEM_read_bio_X509_AUX(in, NULL, NULL, "");
- if (x == NULL) {
+ ERR_set_mark();
+ if (PEM_read_bio_X509_AUX(in, &x, NULL, "") == NULL) {
if ((ERR_GET_REASON(ERR_peek_last_error()) ==
PEM_R_NO_START_LINE) && (count > 0)) {
- ERR_clear_error();
+ ERR_pop_to_mark();
break;
} else {
- X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_PEM_LIB);
+ ERR_clear_last_mark();
goto err;
}
}
+ ERR_clear_last_mark();
i = X509_STORE_add_cert(ctx->store_ctx, x);
if (!i)
goto err;
@@ -107,27 +134,28 @@ int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
}
ret = count;
} else if (type == X509_FILETYPE_ASN1) {
- x = d2i_X509_bio(in, NULL);
- if (x == NULL) {
- X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_ASN1_LIB);
+ if (d2i_X509_bio(in, &x) == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB);
goto err;
}
i = X509_STORE_add_cert(ctx->store_ctx, x);
if (!i)
goto err;
ret = i;
- } else {
- X509err(X509_F_X509_LOAD_CERT_FILE, X509_R_BAD_X509_FILETYPE);
- goto err;
}
if (ret == 0)
- X509err(X509_F_X509_LOAD_CERT_FILE, X509_R_NO_CERTIFICATE_FOUND);
+ ERR_raise(ERR_LIB_X509, X509_R_NO_CERTIFICATE_FOUND);
err:
X509_free(x);
BIO_free(in);
return ret;
}
+int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
+{
+ return X509_load_cert_file_ex(ctx, file, type, NULL, NULL);
+}
+
int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
{
int ret = 0;
@@ -138,7 +166,7 @@ int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
in = BIO_new(BIO_s_file());
if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
- X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_SYS_LIB);
+ ERR_raise(ERR_LIB_X509, ERR_R_SYS_LIB);
goto err;
}
@@ -151,7 +179,7 @@ int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
ERR_clear_error();
break;
} else {
- X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_PEM_LIB);
+ ERR_raise(ERR_LIB_X509, ERR_R_PEM_LIB);
goto err;
}
}
@@ -166,7 +194,7 @@ int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
} else if (type == X509_FILETYPE_ASN1) {
x = d2i_X509_CRL_bio(in, NULL);
if (x == NULL) {
- X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB);
goto err;
}
i = X509_STORE_add_crl(ctx->store_ctx, x);
@@ -174,18 +202,19 @@ int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
goto err;
ret = i;
} else {
- X509err(X509_F_X509_LOAD_CRL_FILE, X509_R_BAD_X509_FILETYPE);
+ ERR_raise(ERR_LIB_X509, X509_R_BAD_X509_FILETYPE);
goto err;
}
if (ret == 0)
- X509err(X509_F_X509_LOAD_CRL_FILE, X509_R_NO_CRL_FOUND);
+ ERR_raise(ERR_LIB_X509, X509_R_NO_CRL_FOUND);
err:
X509_CRL_free(x);
BIO_free(in);
return ret;
}
-int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
+int X509_load_cert_crl_file_ex(X509_LOOKUP *ctx, const char *file, int type,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
STACK_OF(X509_INFO) *inf;
X509_INFO *itmp;
@@ -193,16 +222,16 @@ int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
int i, count = 0;
if (type != X509_FILETYPE_PEM)
- return X509_load_cert_file(ctx, file, type);
+ return X509_load_cert_file_ex(ctx, file, type, libctx, propq);
in = BIO_new_file(file, "r");
if (!in) {
- X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_SYS_LIB);
+ ERR_raise(ERR_LIB_X509, ERR_R_SYS_LIB);
return 0;
}
- inf = PEM_X509_INFO_read_bio(in, NULL, NULL, "");
+ inf = PEM_X509_INFO_read_bio_ex(in, NULL, NULL, "", libctx, propq);
BIO_free(in);
if (!inf) {
- X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_PEM_LIB);
+ ERR_raise(ERR_LIB_X509, ERR_R_PEM_LIB);
return 0;
}
for (i = 0; i < sk_X509_INFO_num(inf); i++) {
@@ -219,9 +248,14 @@ int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
}
}
if (count == 0)
- X509err(X509_F_X509_LOAD_CERT_CRL_FILE,
- X509_R_NO_CERTIFICATE_OR_CRL_FOUND);
+ ERR_raise(ERR_LIB_X509, X509_R_NO_CERTIFICATE_OR_CRL_FOUND);
err:
sk_X509_INFO_pop_free(inf, X509_INFO_free);
return count;
}
+
+int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
+{
+ return X509_load_cert_crl_file_ex(ctx, file, type, NULL, NULL);
+}
+
diff --git a/crypto/x509/by_store.c b/crypto/x509/by_store.c
new file mode 100644
index 000000000000..050735ce3247
--- /dev/null
+++ b/crypto/x509/by_store.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/store.h>
+#include "internal/cryptlib.h"
+#include "crypto/x509.h"
+#include "x509_local.h"
+
+/* Generic object loader, given expected type and criterion */
+static int cache_objects(X509_LOOKUP *lctx, const char *uri,
+ const OSSL_STORE_SEARCH *criterion,
+ int depth, OSSL_LIB_CTX *libctx, const char *propq)
+{
+ int ok = 0;
+ OSSL_STORE_CTX *ctx = NULL;
+ X509_STORE *xstore = X509_LOOKUP_get_store(lctx);
+
+ if ((ctx = OSSL_STORE_open_ex(uri, libctx, propq, NULL, NULL, NULL,
+ NULL, NULL)) == NULL)
+ return 0;
+
+ /*
+ * We try to set the criterion, but don't care if it was valid or not.
+ * For a OSSL_STORE, it merely serves as an optimization, the expectation
+ * being that if the criterion couldn't be used, we will get *everything*
+ * from the container that the URI represents rather than the subset that
+ * the criterion indicates, so the biggest harm is that we cache more
+ * objects certs and CRLs than we may expect, but that's ok.
+ *
+ * Specifically for OpenSSL's own file: scheme, the only workable
+ * criterion is the BY_NAME one, which it can only apply on directories,
+ * but it's possible that the URI is a single file rather than a directory,
+ * and in that case, the BY_NAME criterion is pointless.
+ *
+ * We could very simply not apply any criterion at all here, and just let
+ * the code that selects certs and CRLs from the cached objects do its job,
+ * but it's a nice optimization when it can be applied (such as on an
+ * actual directory with a thousand CA certs).
+ */
+ if (criterion != NULL)
+ OSSL_STORE_find(ctx, criterion);
+
+ for (;;) {
+ OSSL_STORE_INFO *info = OSSL_STORE_load(ctx);
+ int infotype;
+
+ /* NULL means error or "end of file". Either way, we break. */
+ if (info == NULL)
+ break;
+
+ infotype = OSSL_STORE_INFO_get_type(info);
+ ok = 0;
+
+ if (infotype == OSSL_STORE_INFO_NAME) {
+ /*
+ * This is an entry in the "directory" represented by the current
+ * uri. if |depth| allows, dive into it.
+ */
+ if (depth > 0)
+ ok = cache_objects(lctx, OSSL_STORE_INFO_get0_NAME(info),
+ criterion, depth - 1, libctx, propq);
+ } else {
+ /*
+ * We know that X509_STORE_add_{cert|crl} increments the object's
+ * refcount, so we can safely use OSSL_STORE_INFO_get0_{cert,crl}
+ * to get them.
+ */
+ switch (infotype) {
+ case OSSL_STORE_INFO_CERT:
+ ok = X509_STORE_add_cert(xstore,
+ OSSL_STORE_INFO_get0_CERT(info));
+ break;
+ case OSSL_STORE_INFO_CRL:
+ ok = X509_STORE_add_crl(xstore,
+ OSSL_STORE_INFO_get0_CRL(info));
+ break;
+ }
+ }
+
+ OSSL_STORE_INFO_free(info);
+ if (!ok)
+ break;
+ }
+ OSSL_STORE_close(ctx);
+
+ return ok;
+}
+
+
+/* Because OPENSSL_free is a macro and for C type match */
+static void free_uri(OPENSSL_STRING data)
+{
+ OPENSSL_free(data);
+}
+
+static void by_store_free(X509_LOOKUP *ctx)
+{
+ STACK_OF(OPENSSL_STRING) *uris = X509_LOOKUP_get_method_data(ctx);
+ sk_OPENSSL_STRING_pop_free(uris, free_uri);
+}
+
+static int by_store_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argp,
+ long argl, char **retp, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ switch (cmd) {
+ case X509_L_ADD_STORE:
+ /* If no URI is given, use the default cert dir as default URI */
+ if (argp == NULL)
+ argp = ossl_safe_getenv(X509_get_default_cert_dir_env());
+ if (argp == NULL)
+ argp = X509_get_default_cert_dir();
+
+ {
+ STACK_OF(OPENSSL_STRING) *uris = X509_LOOKUP_get_method_data(ctx);
+ char *data = OPENSSL_strdup(argp);
+
+ if (data == NULL) {
+ return 0;
+ }
+ if (uris == NULL) {
+ uris = sk_OPENSSL_STRING_new_null();
+ X509_LOOKUP_set_method_data(ctx, uris);
+ }
+ return sk_OPENSSL_STRING_push(uris, data) > 0;
+ }
+ case X509_L_LOAD_STORE:
+ /* This is a shortcut for quick loading of specific containers */
+ return cache_objects(ctx, argp, NULL, 0, libctx, propq);
+ }
+
+ return 0;
+}
+
+static int by_store_ctrl(X509_LOOKUP *ctx, int cmd,
+ const char *argp, long argl, char **retp)
+{
+ return by_store_ctrl_ex(ctx, cmd, argp, argl, retp, NULL, NULL);
+}
+
+static int by_store(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+ const OSSL_STORE_SEARCH *criterion, X509_OBJECT *ret,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ STACK_OF(OPENSSL_STRING) *uris = X509_LOOKUP_get_method_data(ctx);
+ int i;
+ int ok = 0;
+
+ for (i = 0; i < sk_OPENSSL_STRING_num(uris); i++) {
+ ok = cache_objects(ctx, sk_OPENSSL_STRING_value(uris, i), criterion,
+ 1 /* depth */, libctx, propq);
+
+ if (ok)
+ break;
+ }
+ return ok;
+}
+
+static int by_store_subject_ex(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+ const X509_NAME *name, X509_OBJECT *ret,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ OSSL_STORE_SEARCH *criterion =
+ OSSL_STORE_SEARCH_by_name((X509_NAME *)name); /* won't modify it */
+ int ok = by_store(ctx, type, criterion, ret, libctx, propq);
+ STACK_OF(X509_OBJECT) *store_objects =
+ X509_STORE_get0_objects(X509_LOOKUP_get_store(ctx));
+ X509_OBJECT *tmp = NULL;
+
+ OSSL_STORE_SEARCH_free(criterion);
+
+ if (ok)
+ tmp = X509_OBJECT_retrieve_by_subject(store_objects, type, name);
+
+ ok = 0;
+ if (tmp != NULL) {
+ /*
+ * This could also be done like this:
+ *
+ * if (tmp != NULL) {
+ * *ret = *tmp;
+ * ok = 1;
+ * }
+ *
+ * However, we want to exercise the documented API to the max, so
+ * we do it the hard way.
+ *
+ * To be noted is that X509_OBJECT_set1_* increment the refcount,
+ * but so does X509_STORE_CTX_get_by_subject upon return of this
+ * function, so we must ensure the refcount is decremented
+ * before we return, or we will get a refcount leak. We cannot do
+ * this with X509_OBJECT_free(), though, as that will free a bit
+ * too much.
+ */
+ switch (type) {
+ case X509_LU_X509:
+ ok = X509_OBJECT_set1_X509(ret, tmp->data.x509);
+ if (ok)
+ X509_free(tmp->data.x509);
+ break;
+ case X509_LU_CRL:
+ ok = X509_OBJECT_set1_X509_CRL(ret, tmp->data.crl);
+ if (ok)
+ X509_CRL_free(tmp->data.crl);
+ break;
+ case X509_LU_NONE:
+ break;
+ }
+ }
+ return ok;
+}
+
+static int by_store_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+ const X509_NAME *name, X509_OBJECT *ret)
+{
+ return by_store_subject_ex(ctx, type, name, ret, NULL, NULL);
+}
+
+/*
+ * We lack the implementations for get_by_issuer_serial, get_by_fingerprint
+ * and get_by_alias. There's simply not enough support in the X509_LOOKUP
+ * or X509_STORE APIs.
+ */
+
+static X509_LOOKUP_METHOD x509_store_lookup = {
+ "Load certs from STORE URIs",
+ NULL, /* new_item */
+ by_store_free, /* free */
+ NULL, /* init */
+ NULL, /* shutdown */
+ by_store_ctrl, /* ctrl */
+ by_store_subject, /* get_by_subject */
+ NULL, /* get_by_issuer_serial */
+ NULL, /* get_by_fingerprint */
+ NULL, /* get_by_alias */
+ by_store_subject_ex,
+ by_store_ctrl_ex
+};
+
+X509_LOOKUP_METHOD *X509_LOOKUP_store(void)
+{
+ return &x509_store_lookup;
+}
diff --git a/crypto/x509/ext_dat.h b/crypto/x509/ext_dat.h
new file mode 100644
index 000000000000..a0a7f88ccd8a
--- /dev/null
+++ b/crypto/x509/ext_dat.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+int ossl_v3_name_cmp(const char *name, const char *cmp);
+
+extern const X509V3_EXT_METHOD ossl_v3_bcons, ossl_v3_nscert, ossl_v3_key_usage, ossl_v3_ext_ku;
+extern const X509V3_EXT_METHOD ossl_v3_pkey_usage_period, ossl_v3_sxnet, ossl_v3_info, ossl_v3_sinfo;
+extern const X509V3_EXT_METHOD ossl_v3_ns_ia5_list[8], ossl_v3_alt[3], ossl_v3_skey_id, ossl_v3_akey_id;
+extern const X509V3_EXT_METHOD ossl_v3_crl_num, ossl_v3_crl_reason, ossl_v3_crl_invdate;
+extern const X509V3_EXT_METHOD ossl_v3_delta_crl, ossl_v3_cpols, ossl_v3_crld, ossl_v3_freshest_crl;
+extern const X509V3_EXT_METHOD ossl_v3_ocsp_nonce, ossl_v3_ocsp_accresp, ossl_v3_ocsp_acutoff;
+extern const X509V3_EXT_METHOD ossl_v3_ocsp_crlid, ossl_v3_ocsp_nocheck, ossl_v3_ocsp_serviceloc;
+extern const X509V3_EXT_METHOD ossl_v3_crl_hold, ossl_v3_pci;
+extern const X509V3_EXT_METHOD ossl_v3_policy_mappings, ossl_v3_policy_constraints;
+extern const X509V3_EXT_METHOD ossl_v3_name_constraints, ossl_v3_inhibit_anyp, ossl_v3_idp;
+extern const X509V3_EXT_METHOD ossl_v3_addr, ossl_v3_asid;
+extern const X509V3_EXT_METHOD ossl_v3_ct_scts[3];
+extern const X509V3_EXT_METHOD ossl_v3_tls_feature;
+extern const X509V3_EXT_METHOD ossl_v3_ext_admission;
+extern const X509V3_EXT_METHOD ossl_v3_utf8_list[1];
+extern const X509V3_EXT_METHOD ossl_v3_issuer_sign_tool;
diff --git a/crypto/x509/pcy_cache.c b/crypto/x509/pcy_cache.c
new file mode 100644
index 000000000000..1339f994aee1
--- /dev/null
+++ b/crypto/x509/pcy_cache.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/cryptlib.h"
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include "crypto/x509.h"
+
+#include "pcy_local.h"
+
+static int policy_data_cmp(const X509_POLICY_DATA *const *a,
+ const X509_POLICY_DATA *const *b);
+static int policy_cache_set_int(long *out, ASN1_INTEGER *value);
+
+/*
+ * Set cache entry according to CertificatePolicies extension. Note: this
+ * destroys the passed CERTIFICATEPOLICIES structure.
+ */
+
+static int policy_cache_create(X509 *x,
+ CERTIFICATEPOLICIES *policies, int crit)
+{
+ int i, num, ret = 0;
+ X509_POLICY_CACHE *cache = x->policy_cache;
+ X509_POLICY_DATA *data = NULL;
+ POLICYINFO *policy;
+
+ if ((num = sk_POLICYINFO_num(policies)) <= 0)
+ goto bad_policy;
+ cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp);
+ if (cache->data == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto just_cleanup;
+ }
+ for (i = 0; i < num; i++) {
+ policy = sk_POLICYINFO_value(policies, i);
+ data = ossl_policy_data_new(policy, NULL, crit);
+ if (data == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto just_cleanup;
+ }
+ /*
+ * Duplicate policy OIDs are illegal: reject if matches found.
+ */
+ if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
+ if (cache->anyPolicy) {
+ ret = -1;
+ goto bad_policy;
+ }
+ cache->anyPolicy = data;
+ } else if (sk_X509_POLICY_DATA_find(cache->data, data) >=0 ) {
+ ret = -1;
+ goto bad_policy;
+ } else if (!sk_X509_POLICY_DATA_push(cache->data, data)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto bad_policy;
+ }
+ data = NULL;
+ }
+ ret = 1;
+
+ bad_policy:
+ if (ret == -1)
+ x->ex_flags |= EXFLAG_INVALID_POLICY;
+ ossl_policy_data_free(data);
+ just_cleanup:
+ sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
+ if (ret <= 0) {
+ sk_X509_POLICY_DATA_pop_free(cache->data, ossl_policy_data_free);
+ cache->data = NULL;
+ }
+ return ret;
+}
+
+static int policy_cache_new(X509 *x)
+{
+ X509_POLICY_CACHE *cache;
+ ASN1_INTEGER *ext_any = NULL;
+ POLICY_CONSTRAINTS *ext_pcons = NULL;
+ CERTIFICATEPOLICIES *ext_cpols = NULL;
+ POLICY_MAPPINGS *ext_pmaps = NULL;
+ int i;
+
+ if (x->policy_cache != NULL)
+ return 1;
+ cache = OPENSSL_malloc(sizeof(*cache));
+ if (cache == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ cache->anyPolicy = NULL;
+ cache->data = NULL;
+ cache->any_skip = -1;
+ cache->explicit_skip = -1;
+ cache->map_skip = -1;
+
+ x->policy_cache = cache;
+
+ /*
+ * Handle requireExplicitPolicy *first*. Need to process this even if we
+ * don't have any policies.
+ */
+ ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL);
+
+ if (!ext_pcons) {
+ if (i != -1)
+ goto bad_cache;
+ } else {
+ if (!ext_pcons->requireExplicitPolicy
+ && !ext_pcons->inhibitPolicyMapping)
+ goto bad_cache;
+ if (!policy_cache_set_int(&cache->explicit_skip,
+ ext_pcons->requireExplicitPolicy))
+ goto bad_cache;
+ if (!policy_cache_set_int(&cache->map_skip,
+ ext_pcons->inhibitPolicyMapping))
+ goto bad_cache;
+ }
+
+ /* Process CertificatePolicies */
+
+ ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL);
+ /*
+ * If no CertificatePolicies extension or problem decoding then there is
+ * no point continuing because the valid policies will be NULL.
+ */
+ if (!ext_cpols) {
+ /* If not absent some problem with extension */
+ if (i != -1)
+ goto bad_cache;
+ return 1;
+ }
+
+ i = policy_cache_create(x, ext_cpols, i);
+
+ /* NB: ext_cpols freed by policy_cache_set_policies */
+
+ if (i <= 0)
+ return i;
+
+ ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL);
+
+ if (!ext_pmaps) {
+ /* If not absent some problem with extension */
+ if (i != -1)
+ goto bad_cache;
+ } else {
+ i = ossl_policy_cache_set_mapping(x, ext_pmaps);
+ if (i <= 0)
+ goto bad_cache;
+ }
+
+ ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL);
+
+ if (!ext_any) {
+ if (i != -1)
+ goto bad_cache;
+ } else if (!policy_cache_set_int(&cache->any_skip, ext_any))
+ goto bad_cache;
+ goto just_cleanup;
+
+ bad_cache:
+ x->ex_flags |= EXFLAG_INVALID_POLICY;
+
+ just_cleanup:
+ POLICY_CONSTRAINTS_free(ext_pcons);
+ ASN1_INTEGER_free(ext_any);
+ return 1;
+
+}
+
+void ossl_policy_cache_free(X509_POLICY_CACHE *cache)
+{
+ if (!cache)
+ return;
+ ossl_policy_data_free(cache->anyPolicy);
+ sk_X509_POLICY_DATA_pop_free(cache->data, ossl_policy_data_free);
+ OPENSSL_free(cache);
+}
+
+const X509_POLICY_CACHE *ossl_policy_cache_set(X509 *x)
+{
+
+ if (x->policy_cache == NULL) {
+ if (!CRYPTO_THREAD_write_lock(x->lock))
+ return NULL;
+ policy_cache_new(x);
+ CRYPTO_THREAD_unlock(x->lock);
+ }
+
+ return x->policy_cache;
+
+}
+
+X509_POLICY_DATA *ossl_policy_cache_find_data(const X509_POLICY_CACHE *cache,
+ const ASN1_OBJECT *id)
+{
+ int idx;
+ X509_POLICY_DATA tmp;
+ tmp.valid_policy = (ASN1_OBJECT *)id;
+ idx = sk_X509_POLICY_DATA_find(cache->data, &tmp);
+ return sk_X509_POLICY_DATA_value(cache->data, idx);
+}
+
+static int policy_data_cmp(const X509_POLICY_DATA *const *a,
+ const X509_POLICY_DATA *const *b)
+{
+ return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy);
+}
+
+static int policy_cache_set_int(long *out, ASN1_INTEGER *value)
+{
+ if (value == NULL)
+ return 1;
+ if (value->type == V_ASN1_NEG_INTEGER)
+ return 0;
+ *out = ASN1_INTEGER_get(value);
+ return 1;
+}
diff --git a/crypto/x509/pcy_data.c b/crypto/x509/pcy_data.c
new file mode 100644
index 000000000000..6fb8f14ba8e8
--- /dev/null
+++ b/crypto/x509/pcy_data.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/cryptlib.h"
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "pcy_local.h"
+
+/* Policy Node routines */
+
+void ossl_policy_data_free(X509_POLICY_DATA *data)
+{
+ if (data == NULL)
+ return;
+ ASN1_OBJECT_free(data->valid_policy);
+ /* Don't free qualifiers if shared */
+ if (!(data->flags & POLICY_DATA_FLAG_SHARED_QUALIFIERS))
+ sk_POLICYQUALINFO_pop_free(data->qualifier_set, POLICYQUALINFO_free);
+ sk_ASN1_OBJECT_pop_free(data->expected_policy_set, ASN1_OBJECT_free);
+ OPENSSL_free(data);
+}
+
+/*
+ * Create a data based on an existing policy. If 'id' is NULL use the OID in
+ * the policy, otherwise use 'id'. This behaviour covers the two types of
+ * data in RFC3280: data with from a CertificatePolicies extension and
+ * additional data with just the qualifiers of anyPolicy and ID from another
+ * source.
+ */
+
+X509_POLICY_DATA *ossl_policy_data_new(POLICYINFO *policy,
+ const ASN1_OBJECT *cid, int crit)
+{
+ X509_POLICY_DATA *ret;
+ ASN1_OBJECT *id;
+
+ if (policy == NULL && cid == NULL)
+ return NULL;
+ if (cid) {
+ id = OBJ_dup(cid);
+ if (id == NULL)
+ return NULL;
+ } else
+ id = NULL;
+ ret = OPENSSL_zalloc(sizeof(*ret));
+ if (ret == NULL) {
+ ASN1_OBJECT_free(id);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ ret->expected_policy_set = sk_ASN1_OBJECT_new_null();
+ if (ret->expected_policy_set == NULL) {
+ OPENSSL_free(ret);
+ ASN1_OBJECT_free(id);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (crit)
+ ret->flags = POLICY_DATA_FLAG_CRITICAL;
+
+ if (id)
+ ret->valid_policy = id;
+ else {
+ ret->valid_policy = policy->policyid;
+ policy->policyid = NULL;
+ }
+
+ if (policy) {
+ ret->qualifier_set = policy->qualifiers;
+ policy->qualifiers = NULL;
+ }
+
+ return ret;
+}
diff --git a/crypto/x509/pcy_lib.c b/crypto/x509/pcy_lib.c
new file mode 100644
index 000000000000..c4740a0a30c5
--- /dev/null
+++ b/crypto/x509/pcy_lib.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/cryptlib.h"
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "pcy_local.h"
+
+/* accessor functions */
+
+/* X509_POLICY_TREE stuff */
+
+int X509_policy_tree_level_count(const X509_POLICY_TREE *tree)
+{
+ if (!tree)
+ return 0;
+ return tree->nlevel;
+}
+
+X509_POLICY_LEVEL *X509_policy_tree_get0_level(const X509_POLICY_TREE *tree,
+ int i)
+{
+ if (!tree || (i < 0) || (i >= tree->nlevel))
+ return NULL;
+ return tree->levels + i;
+}
+
+STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_policies(const
+ X509_POLICY_TREE
+ *tree)
+{
+ if (!tree)
+ return NULL;
+ return tree->auth_policies;
+}
+
+STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_user_policies(const
+ X509_POLICY_TREE
+ *tree)
+{
+ if (!tree)
+ return NULL;
+ if (tree->flags & POLICY_FLAG_ANY_POLICY)
+ return tree->auth_policies;
+ else
+ return tree->user_policies;
+}
+
+/* X509_POLICY_LEVEL stuff */
+
+int X509_policy_level_node_count(X509_POLICY_LEVEL *level)
+{
+ int n;
+ if (!level)
+ return 0;
+ if (level->anyPolicy)
+ n = 1;
+ else
+ n = 0;
+ if (level->nodes)
+ n += sk_X509_POLICY_NODE_num(level->nodes);
+ return n;
+}
+
+X509_POLICY_NODE *X509_policy_level_get0_node(const X509_POLICY_LEVEL *level, int i)
+{
+ if (!level)
+ return NULL;
+ if (level->anyPolicy) {
+ if (i == 0)
+ return level->anyPolicy;
+ i--;
+ }
+ return sk_X509_POLICY_NODE_value(level->nodes, i);
+}
+
+/* X509_POLICY_NODE stuff */
+
+const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node)
+{
+ if (!node)
+ return NULL;
+ return node->data->valid_policy;
+}
+
+STACK_OF(POLICYQUALINFO) *X509_policy_node_get0_qualifiers(const
+ X509_POLICY_NODE
+ *node)
+{
+ if (!node)
+ return NULL;
+ return node->data->qualifier_set;
+}
+
+const X509_POLICY_NODE *X509_policy_node_get0_parent(const X509_POLICY_NODE
+ *node)
+{
+ if (!node)
+ return NULL;
+ return node->parent;
+}
diff --git a/crypto/x509/pcy_local.h b/crypto/x509/pcy_local.h
new file mode 100644
index 000000000000..18b53cc09ebf
--- /dev/null
+++ b/crypto/x509/pcy_local.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+typedef struct X509_POLICY_DATA_st X509_POLICY_DATA;
+
+DEFINE_STACK_OF(X509_POLICY_DATA)
+
+/* Internal structures */
+
+/*
+ * This structure and the field names correspond to the Policy 'node' of
+ * RFC3280. NB this structure contains no pointers to parent or child data:
+ * X509_POLICY_NODE contains that. This means that the main policy data can
+ * be kept static and cached with the certificate.
+ */
+
+struct X509_POLICY_DATA_st {
+ unsigned int flags;
+ /* Policy OID and qualifiers for this data */
+ ASN1_OBJECT *valid_policy;
+ STACK_OF(POLICYQUALINFO) *qualifier_set;
+ STACK_OF(ASN1_OBJECT) *expected_policy_set;
+};
+
+/* X509_POLICY_DATA flags values */
+
+/*
+ * This flag indicates the structure has been mapped using a policy mapping
+ * extension. If policy mapping is not active its references get deleted.
+ */
+
+#define POLICY_DATA_FLAG_MAPPED 0x1
+
+/*
+ * This flag indicates the data doesn't correspond to a policy in Certificate
+ * Policies: it has been mapped to any policy.
+ */
+
+#define POLICY_DATA_FLAG_MAPPED_ANY 0x2
+
+/* AND with flags to see if any mapping has occurred */
+
+#define POLICY_DATA_FLAG_MAP_MASK 0x3
+
+/* qualifiers are shared and shouldn't be freed */
+
+#define POLICY_DATA_FLAG_SHARED_QUALIFIERS 0x4
+
+/* Parent node is an extra node and should be freed */
+
+#define POLICY_DATA_FLAG_EXTRA_NODE 0x8
+
+/* Corresponding CertificatePolicies is critical */
+
+#define POLICY_DATA_FLAG_CRITICAL 0x10
+
+/* This structure is cached with a certificate */
+
+struct X509_POLICY_CACHE_st {
+ /* anyPolicy data or NULL if no anyPolicy */
+ X509_POLICY_DATA *anyPolicy;
+ /* other policy data */
+ STACK_OF(X509_POLICY_DATA) *data;
+ /* If InhibitAnyPolicy present this is its value or -1 if absent. */
+ long any_skip;
+ /*
+ * If policyConstraints and requireExplicitPolicy present this is its
+ * value or -1 if absent.
+ */
+ long explicit_skip;
+ /*
+ * If policyConstraints and policyMapping present this is its value or -1
+ * if absent.
+ */
+ long map_skip;
+};
+
+/*
+ * #define POLICY_CACHE_FLAG_CRITICAL POLICY_DATA_FLAG_CRITICAL
+ */
+
+/* This structure represents the relationship between nodes */
+
+struct X509_POLICY_NODE_st {
+ /* node data this refers to */
+ const X509_POLICY_DATA *data;
+ /* Parent node */
+ X509_POLICY_NODE *parent;
+ /* Number of child nodes */
+ int nchild;
+};
+
+struct X509_POLICY_LEVEL_st {
+ /* Cert for this level */
+ X509 *cert;
+ /* nodes at this level */
+ STACK_OF(X509_POLICY_NODE) *nodes;
+ /* anyPolicy node */
+ X509_POLICY_NODE *anyPolicy;
+ /* Extra data */
+ /*
+ * STACK_OF(X509_POLICY_DATA) *extra_data;
+ */
+ unsigned int flags;
+};
+
+struct X509_POLICY_TREE_st {
+ /* This is the tree 'level' data */
+ X509_POLICY_LEVEL *levels;
+ int nlevel;
+ /*
+ * Extra policy data when additional nodes (not from the certificate) are
+ * required.
+ */
+ STACK_OF(X509_POLICY_DATA) *extra_data;
+ /* This is the authority constrained policy set */
+ STACK_OF(X509_POLICY_NODE) *auth_policies;
+ STACK_OF(X509_POLICY_NODE) *user_policies;
+ unsigned int flags;
+};
+
+/* Set if anyPolicy present in user policies */
+#define POLICY_FLAG_ANY_POLICY 0x2
+
+/* Useful macros */
+
+#define node_data_critical(data) (data->flags & POLICY_DATA_FLAG_CRITICAL)
+#define node_critical(node) node_data_critical(node->data)
+
+/* Internal functions */
+
+X509_POLICY_DATA *ossl_policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *id,
+ int crit);
+void ossl_policy_data_free(X509_POLICY_DATA *data);
+
+X509_POLICY_DATA *ossl_policy_cache_find_data(const X509_POLICY_CACHE *cache,
+ const ASN1_OBJECT *id);
+int ossl_policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps);
+
+STACK_OF(X509_POLICY_NODE) *ossl_policy_node_cmp_new(void);
+
+void ossl_policy_cache_free(X509_POLICY_CACHE *cache);
+
+X509_POLICY_NODE *ossl_policy_level_find_node(const X509_POLICY_LEVEL *level,
+ const X509_POLICY_NODE *parent,
+ const ASN1_OBJECT *id);
+
+X509_POLICY_NODE *ossl_policy_tree_find_sk(STACK_OF(X509_POLICY_NODE) *sk,
+ const ASN1_OBJECT *id);
+
+X509_POLICY_NODE *ossl_policy_level_add_node(X509_POLICY_LEVEL *level,
+ X509_POLICY_DATA *data,
+ X509_POLICY_NODE *parent,
+ X509_POLICY_TREE *tree);
+void ossl_policy_node_free(X509_POLICY_NODE *node);
+int ossl_policy_node_match(const X509_POLICY_LEVEL *lvl,
+ const X509_POLICY_NODE *node, const ASN1_OBJECT *oid);
+
+const X509_POLICY_CACHE *ossl_policy_cache_set(X509 *x);
diff --git a/crypto/x509/pcy_map.c b/crypto/x509/pcy_map.c
new file mode 100644
index 000000000000..60dfd1e3203b
--- /dev/null
+++ b/crypto/x509/pcy_map.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/cryptlib.h"
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include "crypto/x509.h"
+
+#include "pcy_local.h"
+
+/*
+ * Set policy mapping entries in cache. Note: this modifies the passed
+ * POLICY_MAPPINGS structure
+ */
+
+int ossl_policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
+{
+ POLICY_MAPPING *map;
+ X509_POLICY_DATA *data;
+ X509_POLICY_CACHE *cache = x->policy_cache;
+ int i;
+ int ret = 0;
+ if (sk_POLICY_MAPPING_num(maps) == 0) {
+ ret = -1;
+ goto bad_mapping;
+ }
+ for (i = 0; i < sk_POLICY_MAPPING_num(maps); i++) {
+ map = sk_POLICY_MAPPING_value(maps, i);
+ /* Reject if map to or from anyPolicy */
+ if ((OBJ_obj2nid(map->subjectDomainPolicy) == NID_any_policy)
+ || (OBJ_obj2nid(map->issuerDomainPolicy) == NID_any_policy)) {
+ ret = -1;
+ goto bad_mapping;
+ }
+
+ /* Attempt to find matching policy data */
+ data = ossl_policy_cache_find_data(cache, map->issuerDomainPolicy);
+ /* If we don't have anyPolicy can't map */
+ if (data == NULL && !cache->anyPolicy)
+ continue;
+
+ /* Create a NODE from anyPolicy */
+ if (data == NULL) {
+ data = ossl_policy_data_new(NULL, map->issuerDomainPolicy,
+ cache->anyPolicy->flags
+ & POLICY_DATA_FLAG_CRITICAL);
+ if (data == NULL)
+ goto bad_mapping;
+ data->qualifier_set = cache->anyPolicy->qualifier_set;
+ /*
+ * map->issuerDomainPolicy = NULL;
+ */
+ data->flags |= POLICY_DATA_FLAG_MAPPED_ANY;
+ data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
+ if (!sk_X509_POLICY_DATA_push(cache->data, data)) {
+ ossl_policy_data_free(data);
+ goto bad_mapping;
+ }
+ } else
+ data->flags |= POLICY_DATA_FLAG_MAPPED;
+ if (!sk_ASN1_OBJECT_push(data->expected_policy_set,
+ map->subjectDomainPolicy))
+ goto bad_mapping;
+ map->subjectDomainPolicy = NULL;
+
+ }
+
+ ret = 1;
+ bad_mapping:
+ sk_POLICY_MAPPING_pop_free(maps, POLICY_MAPPING_free);
+ return ret;
+
+}
diff --git a/crypto/x509/pcy_node.c b/crypto/x509/pcy_node.c
new file mode 100644
index 000000000000..9d9a7ea1799c
--- /dev/null
+++ b/crypto/x509/pcy_node.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/asn1.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+
+#include "pcy_local.h"
+
+static int node_cmp(const X509_POLICY_NODE *const *a,
+ const X509_POLICY_NODE *const *b)
+{
+ return OBJ_cmp((*a)->data->valid_policy, (*b)->data->valid_policy);
+}
+
+STACK_OF(X509_POLICY_NODE) *ossl_policy_node_cmp_new(void)
+{
+ return sk_X509_POLICY_NODE_new(node_cmp);
+}
+
+X509_POLICY_NODE *ossl_policy_tree_find_sk(STACK_OF(X509_POLICY_NODE) *nodes,
+ const ASN1_OBJECT *id)
+{
+ X509_POLICY_DATA n;
+ X509_POLICY_NODE l;
+ int idx;
+
+ n.valid_policy = (ASN1_OBJECT *)id;
+ l.data = &n;
+
+ idx = sk_X509_POLICY_NODE_find(nodes, &l);
+ return sk_X509_POLICY_NODE_value(nodes, idx);
+
+}
+
+X509_POLICY_NODE *ossl_policy_level_find_node(const X509_POLICY_LEVEL *level,
+ const X509_POLICY_NODE *parent,
+ const ASN1_OBJECT *id)
+{
+ X509_POLICY_NODE *node;
+ int i;
+ for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++) {
+ node = sk_X509_POLICY_NODE_value(level->nodes, i);
+ if (node->parent == parent) {
+ if (!OBJ_cmp(node->data->valid_policy, id))
+ return node;
+ }
+ }
+ return NULL;
+}
+
+X509_POLICY_NODE *ossl_policy_level_add_node(X509_POLICY_LEVEL *level,
+ X509_POLICY_DATA *data,
+ X509_POLICY_NODE *parent,
+ X509_POLICY_TREE *tree)
+{
+ X509_POLICY_NODE *node;
+
+ node = OPENSSL_zalloc(sizeof(*node));
+ if (node == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ node->data = data;
+ node->parent = parent;
+ if (level) {
+ if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
+ if (level->anyPolicy)
+ goto node_error;
+ level->anyPolicy = node;
+ } else {
+
+ if (level->nodes == NULL)
+ level->nodes = ossl_policy_node_cmp_new();
+ if (level->nodes == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto node_error;
+ }
+ if (!sk_X509_POLICY_NODE_push(level->nodes, node)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto node_error;
+ }
+ }
+ }
+
+ if (tree) {
+ if (tree->extra_data == NULL)
+ tree->extra_data = sk_X509_POLICY_DATA_new_null();
+ if (tree->extra_data == NULL){
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto node_error;
+ }
+ if (!sk_X509_POLICY_DATA_push(tree->extra_data, data)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto node_error;
+ }
+ }
+
+ if (parent)
+ parent->nchild++;
+
+ return node;
+
+ node_error:
+ ossl_policy_node_free(node);
+ return NULL;
+}
+
+void ossl_policy_node_free(X509_POLICY_NODE *node)
+{
+ OPENSSL_free(node);
+}
+
+/*
+ * See if a policy node matches a policy OID. If mapping enabled look through
+ * expected policy set otherwise just valid policy.
+ */
+
+int ossl_policy_node_match(const X509_POLICY_LEVEL *lvl,
+ const X509_POLICY_NODE *node, const ASN1_OBJECT *oid)
+{
+ int i;
+ ASN1_OBJECT *policy_oid;
+ const X509_POLICY_DATA *x = node->data;
+
+ if ((lvl->flags & X509_V_FLAG_INHIBIT_MAP)
+ || !(x->flags & POLICY_DATA_FLAG_MAP_MASK)) {
+ if (!OBJ_cmp(x->valid_policy, oid))
+ return 1;
+ return 0;
+ }
+
+ for (i = 0; i < sk_ASN1_OBJECT_num(x->expected_policy_set); i++) {
+ policy_oid = sk_ASN1_OBJECT_value(x->expected_policy_set, i);
+ if (!OBJ_cmp(policy_oid, oid))
+ return 1;
+ }
+ return 0;
+
+}
diff --git a/crypto/x509/pcy_tree.c b/crypto/x509/pcy_tree.c
new file mode 100644
index 000000000000..fa45da5117a1
--- /dev/null
+++ b/crypto/x509/pcy_tree.c
@@ -0,0 +1,697 @@
+/*
+ * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/cryptlib.h"
+#include <openssl/trace.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "pcy_local.h"
+
+static void expected_print(BIO *channel,
+ X509_POLICY_LEVEL *lev, X509_POLICY_NODE *node,
+ int indent)
+{
+ if ((lev->flags & X509_V_FLAG_INHIBIT_MAP)
+ || !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
+ BIO_puts(channel, " Not Mapped\n");
+ else {
+ int i;
+
+ STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
+ ASN1_OBJECT *oid;
+ BIO_puts(channel, " Expected: ");
+ for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++) {
+ oid = sk_ASN1_OBJECT_value(pset, i);
+ if (i)
+ BIO_puts(channel, ", ");
+ i2a_ASN1_OBJECT(channel, oid);
+ }
+ BIO_puts(channel, "\n");
+ }
+}
+
+static void tree_print(BIO *channel,
+ char *str, X509_POLICY_TREE *tree,
+ X509_POLICY_LEVEL *curr)
+{
+ X509_POLICY_LEVEL *plev;
+
+ if (!curr)
+ curr = tree->levels + tree->nlevel;
+ else
+ curr++;
+
+ BIO_printf(channel, "Level print after %s\n", str);
+ BIO_printf(channel, "Printing Up to Level %ld\n",
+ (long)(curr - tree->levels));
+ for (plev = tree->levels; plev != curr; plev++) {
+ int i;
+
+ BIO_printf(channel, "Level %ld, flags = %x\n",
+ (long)(plev - tree->levels), plev->flags);
+ for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++) {
+ X509_POLICY_NODE *node =
+ sk_X509_POLICY_NODE_value(plev->nodes, i);
+
+ X509_POLICY_NODE_print(channel, node, 2);
+ expected_print(channel, plev, node, 2);
+ BIO_printf(channel, " Flags: %x\n", node->data->flags);
+ }
+ if (plev->anyPolicy)
+ X509_POLICY_NODE_print(channel, plev->anyPolicy, 2);
+ }
+}
+
+#define TREE_PRINT(str, tree, curr) \
+ OSSL_TRACE_BEGIN(X509V3_POLICY) { \
+ tree_print(trc_out, "before tree_prune()", tree, curr); \
+ } OSSL_TRACE_END(X509V3_POLICY)
+
+/*-
+ * Return value: <= 0 on error, or positive bit mask:
+ *
+ * X509_PCY_TREE_VALID: valid tree
+ * X509_PCY_TREE_EMPTY: empty tree (including bare TA case)
+ * X509_PCY_TREE_EXPLICIT: explicit policy required
+ */
+static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
+ unsigned int flags)
+{
+ X509_POLICY_TREE *tree;
+ X509_POLICY_LEVEL *level;
+ const X509_POLICY_CACHE *cache;
+ X509_POLICY_DATA *data = NULL;
+ int ret = X509_PCY_TREE_VALID;
+ int n = sk_X509_num(certs) - 1; /* RFC5280 paths omit the TA */
+ int explicit_policy = (flags & X509_V_FLAG_EXPLICIT_POLICY) ? 0 : n+1;
+ int any_skip = (flags & X509_V_FLAG_INHIBIT_ANY) ? 0 : n+1;
+ int map_skip = (flags & X509_V_FLAG_INHIBIT_MAP) ? 0 : n+1;
+ int i;
+
+ *ptree = NULL;
+
+ /* Can't do anything with just a trust anchor */
+ if (n == 0)
+ return X509_PCY_TREE_EMPTY;
+
+ /*
+ * First setup the policy cache in all n non-TA certificates, this will be
+ * used in X509_verify_cert() which will invoke the verify callback for all
+ * certificates with invalid policy extensions.
+ */
+ for (i = n - 1; i >= 0; i--) {
+ X509 *x = sk_X509_value(certs, i);
+
+ /* Call for side-effect of computing hash and caching extensions */
+ X509_check_purpose(x, -1, 0);
+
+ /* If cache is NULL, likely ENOMEM: return immediately */
+ if (ossl_policy_cache_set(x) == NULL)
+ return X509_PCY_TREE_INTERNAL;
+ }
+
+ /*
+ * At this point check for invalid policies and required explicit policy.
+ * Note that the explicit_policy counter is a count-down to zero, with the
+ * requirement kicking in if and once it does that. The counter is
+ * decremented for every non-self-issued certificate in the path, but may
+ * be further reduced by policy constraints in a non-leaf certificate.
+ *
+ * The ultimate policy set is the intersection of all the policies along
+ * the path, if we hit a certificate with an empty policy set, and explicit
+ * policy is required we're done.
+ */
+ for (i = n - 1;
+ i >= 0 && (explicit_policy > 0 || (ret & X509_PCY_TREE_EMPTY) == 0);
+ i--) {
+ X509 *x = sk_X509_value(certs, i);
+ uint32_t ex_flags = X509_get_extension_flags(x);
+
+ /* All the policies are already cached, we can return early */
+ if (ex_flags & EXFLAG_INVALID_POLICY)
+ return X509_PCY_TREE_INVALID;
+
+ /* Access the cache which we now know exists */
+ cache = ossl_policy_cache_set(x);
+
+ if ((ret & X509_PCY_TREE_VALID) && cache->data == NULL)
+ ret = X509_PCY_TREE_EMPTY;
+ if (explicit_policy > 0) {
+ if (!(ex_flags & EXFLAG_SI))
+ explicit_policy--;
+ if ((cache->explicit_skip >= 0)
+ && (cache->explicit_skip < explicit_policy))
+ explicit_policy = cache->explicit_skip;
+ }
+ }
+
+ if (explicit_policy == 0)
+ ret |= X509_PCY_TREE_EXPLICIT;
+ if ((ret & X509_PCY_TREE_VALID) == 0)
+ return ret;
+
+ /* If we get this far initialize the tree */
+ if ((tree = OPENSSL_zalloc(sizeof(*tree))) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return X509_PCY_TREE_INTERNAL;
+ }
+
+ /*
+ * http://tools.ietf.org/html/rfc5280#section-6.1.2, figure 3.
+ *
+ * The top level is implicitly for the trust anchor with valid expected
+ * policies of anyPolicy. (RFC 5280 has the TA at depth 0 and the leaf at
+ * depth n, we have the leaf at depth 0 and the TA at depth n).
+ */
+ if ((tree->levels = OPENSSL_zalloc(sizeof(*tree->levels)*(n+1))) == NULL) {
+ OPENSSL_free(tree);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return X509_PCY_TREE_INTERNAL;
+ }
+ tree->nlevel = n+1;
+ level = tree->levels;
+ if ((data = ossl_policy_data_new(NULL,
+ OBJ_nid2obj(NID_any_policy), 0)) == NULL)
+ goto bad_tree;
+ if (ossl_policy_level_add_node(level, data, NULL, tree) == NULL) {
+ ossl_policy_data_free(data);
+ goto bad_tree;
+ }
+
+ /*
+ * In this pass initialize all the tree levels and whether anyPolicy and
+ * policy mapping are inhibited at each level.
+ */
+ for (i = n - 1; i >= 0; i--) {
+ X509 *x = sk_X509_value(certs, i);
+ uint32_t ex_flags = X509_get_extension_flags(x);
+
+ /* Access the cache which we now know exists */
+ cache = ossl_policy_cache_set(x);
+
+ X509_up_ref(x);
+ (++level)->cert = x;
+
+ if (!cache->anyPolicy)
+ level->flags |= X509_V_FLAG_INHIBIT_ANY;
+
+ /* Determine inhibit any and inhibit map flags */
+ if (any_skip == 0) {
+ /*
+ * Any matching allowed only if certificate is self issued and not
+ * the last in the chain.
+ */
+ if (!(ex_flags & EXFLAG_SI) || (i == 0))
+ level->flags |= X509_V_FLAG_INHIBIT_ANY;
+ } else {
+ if (!(ex_flags & EXFLAG_SI))
+ any_skip--;
+ if ((cache->any_skip >= 0) && (cache->any_skip < any_skip))
+ any_skip = cache->any_skip;
+ }
+
+ if (map_skip == 0)
+ level->flags |= X509_V_FLAG_INHIBIT_MAP;
+ else {
+ if (!(ex_flags & EXFLAG_SI))
+ map_skip--;
+ if ((cache->map_skip >= 0) && (cache->map_skip < map_skip))
+ map_skip = cache->map_skip;
+ }
+ }
+
+ *ptree = tree;
+ return ret;
+
+ bad_tree:
+ X509_policy_tree_free(tree);
+ return X509_PCY_TREE_INTERNAL;
+}
+
+/*
+ * Return value: 1 on success, 0 otherwise
+ */
+static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
+ X509_POLICY_DATA *data)
+{
+ X509_POLICY_LEVEL *last = curr - 1;
+ int i, matched = 0;
+
+ /* Iterate through all in nodes linking matches */
+ for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
+ X509_POLICY_NODE *node = sk_X509_POLICY_NODE_value(last->nodes, i);
+
+ if (ossl_policy_node_match(last, node, data->valid_policy)) {
+ if (ossl_policy_level_add_node(curr, data, node, NULL) == NULL)
+ return 0;
+ matched = 1;
+ }
+ }
+ if (!matched && last->anyPolicy) {
+ if (ossl_policy_level_add_node(curr, data, last->anyPolicy, NULL) == NULL)
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * This corresponds to RFC3280 6.1.3(d)(1): link any data from
+ * CertificatePolicies onto matching parent or anyPolicy if no match.
+ *
+ * Return value: 1 on success, 0 otherwise.
+ */
+static int tree_link_nodes(X509_POLICY_LEVEL *curr,
+ const X509_POLICY_CACHE *cache)
+{
+ int i;
+
+ for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) {
+ X509_POLICY_DATA *data = sk_X509_POLICY_DATA_value(cache->data, i);
+
+ /* Look for matching nodes in previous level */
+ if (!tree_link_matching_nodes(curr, data))
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * This corresponds to RFC3280 6.1.3(d)(2): Create new data for any unmatched
+ * policies in the parent and link to anyPolicy.
+ *
+ * Return value: 1 on success, 0 otherwise.
+ */
+static int tree_add_unmatched(X509_POLICY_LEVEL *curr,
+ const X509_POLICY_CACHE *cache,
+ const ASN1_OBJECT *id,
+ X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
+{
+ X509_POLICY_DATA *data;
+
+ if (id == NULL)
+ id = node->data->valid_policy;
+ /*
+ * Create a new node with qualifiers from anyPolicy and id from unmatched
+ * node.
+ */
+ if ((data = ossl_policy_data_new(NULL, id, node_critical(node))) == NULL)
+ return 0;
+
+ /* Curr may not have anyPolicy */
+ data->qualifier_set = cache->anyPolicy->qualifier_set;
+ data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
+ if (ossl_policy_level_add_node(curr, data, node, tree) == NULL) {
+ ossl_policy_data_free(data);
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Return value: 1 on success, 0 otherwise.
+ */
+static int tree_link_unmatched(X509_POLICY_LEVEL *curr,
+ const X509_POLICY_CACHE *cache,
+ X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
+{
+ const X509_POLICY_LEVEL *last = curr - 1;
+ int i;
+
+ if ((last->flags & X509_V_FLAG_INHIBIT_MAP)
+ || !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) {
+ /* If no policy mapping: matched if one child present */
+ if (node->nchild)
+ return 1;
+ if (!tree_add_unmatched(curr, cache, NULL, node, tree))
+ return 0;
+ /* Add it */
+ } else {
+ /* If mapping: matched if one child per expected policy set */
+ STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
+ if (node->nchild == sk_ASN1_OBJECT_num(expset))
+ return 1;
+ /* Locate unmatched nodes */
+ for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) {
+ ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
+ if (ossl_policy_level_find_node(curr, node, oid))
+ continue;
+ if (!tree_add_unmatched(curr, cache, oid, node, tree))
+ return 0;
+ }
+
+ }
+ return 1;
+}
+
+/*
+ * Return value: 1 on success, 0 otherwise
+ */
+static int tree_link_any(X509_POLICY_LEVEL *curr,
+ const X509_POLICY_CACHE *cache,
+ X509_POLICY_TREE *tree)
+{
+ int i;
+ X509_POLICY_NODE *node;
+ X509_POLICY_LEVEL *last = curr - 1;
+
+ for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
+ node = sk_X509_POLICY_NODE_value(last->nodes, i);
+
+ if (!tree_link_unmatched(curr, cache, node, tree))
+ return 0;
+ }
+ /* Finally add link to anyPolicy */
+ if (last->anyPolicy &&
+ ossl_policy_level_add_node(curr, cache->anyPolicy,
+ last->anyPolicy, NULL) == NULL)
+ return 0;
+ return 1;
+}
+
+/*-
+ * Prune the tree: delete any child mapped child data on the current level then
+ * proceed up the tree deleting any data with no children. If we ever have no
+ * data on a level we can halt because the tree will be empty.
+ *
+ * Return value: <= 0 error, otherwise one of:
+ *
+ * X509_PCY_TREE_VALID: valid tree
+ * X509_PCY_TREE_EMPTY: empty tree
+ */
+static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
+{
+ STACK_OF(X509_POLICY_NODE) *nodes;
+ X509_POLICY_NODE *node;
+ int i;
+ nodes = curr->nodes;
+ if (curr->flags & X509_V_FLAG_INHIBIT_MAP) {
+ for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
+ node = sk_X509_POLICY_NODE_value(nodes, i);
+ /* Delete any mapped data: see RFC3280 XXXX */
+ if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) {
+ node->parent->nchild--;
+ OPENSSL_free(node);
+ (void)sk_X509_POLICY_NODE_delete(nodes, i);
+ }
+ }
+ }
+
+ for (;;) {
+ --curr;
+ nodes = curr->nodes;
+ for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
+ node = sk_X509_POLICY_NODE_value(nodes, i);
+ if (node->nchild == 0) {
+ node->parent->nchild--;
+ OPENSSL_free(node);
+ (void)sk_X509_POLICY_NODE_delete(nodes, i);
+ }
+ }
+ if (curr->anyPolicy && !curr->anyPolicy->nchild) {
+ if (curr->anyPolicy->parent)
+ curr->anyPolicy->parent->nchild--;
+ OPENSSL_free(curr->anyPolicy);
+ curr->anyPolicy = NULL;
+ }
+ if (curr == tree->levels) {
+ /* If we zapped anyPolicy at top then tree is empty */
+ if (!curr->anyPolicy)
+ return X509_PCY_TREE_EMPTY;
+ break;
+ }
+ }
+ return X509_PCY_TREE_VALID;
+}
+
+/*
+ * Return value: 1 on success, 0 otherwise.
+ */
+static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
+ X509_POLICY_NODE *pcy)
+{
+ if (*pnodes == NULL &&
+ (*pnodes = ossl_policy_node_cmp_new()) == NULL)
+ return 0;
+ if (sk_X509_POLICY_NODE_find(*pnodes, pcy) >= 0)
+ return 1;
+ return sk_X509_POLICY_NODE_push(*pnodes, pcy) != 0;
+}
+
+#define TREE_CALC_FAILURE 0
+#define TREE_CALC_OK_NOFREE 1
+#define TREE_CALC_OK_DOFREE 2
+
+/*-
+ * Calculate the authority set based on policy tree. The 'pnodes' parameter is
+ * used as a store for the set of policy nodes used to calculate the user set.
+ * If the authority set is not anyPolicy then pnodes will just point to the
+ * authority set. If however the authority set is anyPolicy then the set of
+ * valid policies (other than anyPolicy) is store in pnodes.
+ *
+ * Return value:
+ * TREE_CALC_FAILURE on failure,
+ * TREE_CALC_OK_NOFREE on success and pnodes need not be freed,
+ * TREE_CALC_OK_DOFREE on success and pnodes needs to be freed
+ */
+static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
+ STACK_OF(X509_POLICY_NODE) **pnodes)
+{
+ X509_POLICY_LEVEL *curr;
+ X509_POLICY_NODE *node, *anyptr;
+ STACK_OF(X509_POLICY_NODE) **addnodes;
+ int i, j;
+ curr = tree->levels + tree->nlevel - 1;
+
+ /* If last level contains anyPolicy set is anyPolicy */
+ if (curr->anyPolicy) {
+ if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
+ return TREE_CALC_FAILURE;
+ addnodes = pnodes;
+ } else
+ /* Add policies to authority set */
+ addnodes = &tree->auth_policies;
+
+ curr = tree->levels;
+ for (i = 1; i < tree->nlevel; i++) {
+ /*
+ * If no anyPolicy node on this level it can't appear on lower
+ * levels so end search.
+ */
+ if ((anyptr = curr->anyPolicy) == NULL)
+ break;
+ curr++;
+ for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) {
+ node = sk_X509_POLICY_NODE_value(curr->nodes, j);
+ if ((node->parent == anyptr)
+ && !tree_add_auth_node(addnodes, node)) {
+ if (addnodes == pnodes) {
+ sk_X509_POLICY_NODE_free(*pnodes);
+ *pnodes = NULL;
+ }
+ return TREE_CALC_FAILURE;
+ }
+ }
+ }
+ if (addnodes == pnodes)
+ return TREE_CALC_OK_DOFREE;
+
+ *pnodes = tree->auth_policies;
+ return TREE_CALC_OK_NOFREE;
+}
+
+/*
+ * Return value: 1 on success, 0 otherwise.
+ */
+static int tree_calculate_user_set(X509_POLICY_TREE *tree,
+ STACK_OF(ASN1_OBJECT) *policy_oids,
+ STACK_OF(X509_POLICY_NODE) *auth_nodes)
+{
+ int i;
+ X509_POLICY_NODE *node;
+ ASN1_OBJECT *oid;
+ X509_POLICY_NODE *anyPolicy;
+ X509_POLICY_DATA *extra;
+
+ /*
+ * Check if anyPolicy present in authority constrained policy set: this
+ * will happen if it is a leaf node.
+ */
+ if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
+ return 1;
+
+ anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
+
+ for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
+ oid = sk_ASN1_OBJECT_value(policy_oids, i);
+ if (OBJ_obj2nid(oid) == NID_any_policy) {
+ tree->flags |= POLICY_FLAG_ANY_POLICY;
+ return 1;
+ }
+ }
+
+ for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
+ oid = sk_ASN1_OBJECT_value(policy_oids, i);
+ node = ossl_policy_tree_find_sk(auth_nodes, oid);
+ if (!node) {
+ if (!anyPolicy)
+ continue;
+ /*
+ * Create a new node with policy ID from user set and qualifiers
+ * from anyPolicy.
+ */
+ extra = ossl_policy_data_new(NULL, oid, node_critical(anyPolicy));
+ if (extra == NULL)
+ return 0;
+ extra->qualifier_set = anyPolicy->data->qualifier_set;
+ extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
+ | POLICY_DATA_FLAG_EXTRA_NODE;
+ node = ossl_policy_level_add_node(NULL, extra, anyPolicy->parent,
+ tree);
+ }
+ if (!tree->user_policies) {
+ tree->user_policies = sk_X509_POLICY_NODE_new_null();
+ if (!tree->user_policies)
+ return 1;
+ }
+ if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
+ return 0;
+ }
+ return 1;
+}
+
+/*-
+ * Return value: <= 0 error, otherwise one of:
+ * X509_PCY_TREE_VALID: valid tree
+ * X509_PCY_TREE_EMPTY: empty tree
+ * (see tree_prune()).
+ */
+static int tree_evaluate(X509_POLICY_TREE *tree)
+{
+ int ret, i;
+ X509_POLICY_LEVEL *curr = tree->levels + 1;
+ const X509_POLICY_CACHE *cache;
+
+ for (i = 1; i < tree->nlevel; i++, curr++) {
+ cache = ossl_policy_cache_set(curr->cert);
+ if (!tree_link_nodes(curr, cache))
+ return X509_PCY_TREE_INTERNAL;
+
+ if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
+ && !tree_link_any(curr, cache, tree))
+ return X509_PCY_TREE_INTERNAL;
+ TREE_PRINT("before tree_prune()", tree, curr);
+ ret = tree_prune(tree, curr);
+ if (ret != X509_PCY_TREE_VALID)
+ return ret;
+ }
+ return X509_PCY_TREE_VALID;
+}
+
+static void exnode_free(X509_POLICY_NODE *node)
+{
+ if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
+ OPENSSL_free(node);
+}
+
+void X509_policy_tree_free(X509_POLICY_TREE *tree)
+{
+ X509_POLICY_LEVEL *curr;
+ int i;
+
+ if (!tree)
+ return;
+
+ sk_X509_POLICY_NODE_free(tree->auth_policies);
+ sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
+
+ for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) {
+ X509_free(curr->cert);
+ sk_X509_POLICY_NODE_pop_free(curr->nodes, ossl_policy_node_free);
+ ossl_policy_node_free(curr->anyPolicy);
+ }
+
+ sk_X509_POLICY_DATA_pop_free(tree->extra_data, ossl_policy_data_free);
+ OPENSSL_free(tree->levels);
+ OPENSSL_free(tree);
+
+}
+
+/*-
+ * Application policy checking function.
+ * Return codes:
+ * X509_PCY_TREE_FAILURE: Failure to satisfy explicit policy
+ * X509_PCY_TREE_INVALID: Inconsistent or invalid extensions
+ * X509_PCY_TREE_INTERNAL: Internal error, most likely malloc
+ * X509_PCY_TREE_VALID: Success (null tree if empty or bare TA)
+ */
+int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
+ STACK_OF(X509) *certs,
+ STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags)
+{
+ int init_ret;
+ int ret;
+ int calc_ret;
+ X509_POLICY_TREE *tree = NULL;
+ STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
+
+ *ptree = NULL;
+ *pexplicit_policy = 0;
+ init_ret = tree_init(&tree, certs, flags);
+
+ if (init_ret <= 0)
+ return init_ret;
+
+ if ((init_ret & X509_PCY_TREE_EXPLICIT) == 0) {
+ if (init_ret & X509_PCY_TREE_EMPTY) {
+ X509_policy_tree_free(tree);
+ return X509_PCY_TREE_VALID;
+ }
+ } else {
+ *pexplicit_policy = 1;
+ /* Tree empty and requireExplicit True: Error */
+ if (init_ret & X509_PCY_TREE_EMPTY)
+ return X509_PCY_TREE_FAILURE;
+ }
+
+ ret = tree_evaluate(tree);
+ TREE_PRINT("tree_evaluate()", tree, NULL);
+ if (ret <= 0)
+ goto error;
+
+ if (ret == X509_PCY_TREE_EMPTY) {
+ X509_policy_tree_free(tree);
+ if (init_ret & X509_PCY_TREE_EXPLICIT)
+ return X509_PCY_TREE_FAILURE;
+ return X509_PCY_TREE_VALID;
+ }
+
+ /* Tree is not empty: continue */
+
+ if ((calc_ret = tree_calculate_authority_set(tree, &auth_nodes)) == 0)
+ goto error;
+ ret = tree_calculate_user_set(tree, policy_oids, auth_nodes);
+ if (calc_ret == TREE_CALC_OK_DOFREE)
+ sk_X509_POLICY_NODE_free(auth_nodes);
+ if (!ret)
+ goto error;
+
+ *ptree = tree;
+
+ if (init_ret & X509_PCY_TREE_EXPLICIT) {
+ nodes = X509_policy_tree_get0_user_policies(tree);
+ if (sk_X509_POLICY_NODE_num(nodes) <= 0)
+ return X509_PCY_TREE_FAILURE;
+ }
+ return X509_PCY_TREE_VALID;
+
+ error:
+ X509_policy_tree_free(tree);
+ return X509_PCY_TREE_INTERNAL;
+}
diff --git a/crypto/x509/standard_exts.h b/crypto/x509/standard_exts.h
new file mode 100644
index 000000000000..27a99a4b13ed
--- /dev/null
+++ b/crypto/x509/standard_exts.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This table will be searched using OBJ_bsearch so it *must* kept in order
+ * of the ext_nid values.
+ */
+
+static const X509V3_EXT_METHOD *standard_exts[] = {
+ &ossl_v3_nscert,
+ &ossl_v3_ns_ia5_list[0],
+ &ossl_v3_ns_ia5_list[1],
+ &ossl_v3_ns_ia5_list[2],
+ &ossl_v3_ns_ia5_list[3],
+ &ossl_v3_ns_ia5_list[4],
+ &ossl_v3_ns_ia5_list[5],
+ &ossl_v3_ns_ia5_list[6],
+ &ossl_v3_skey_id,
+ &ossl_v3_key_usage,
+ &ossl_v3_pkey_usage_period,
+ &ossl_v3_alt[0],
+ &ossl_v3_alt[1],
+ &ossl_v3_bcons,
+ &ossl_v3_crl_num,
+ &ossl_v3_cpols,
+ &ossl_v3_akey_id,
+ &ossl_v3_crld,
+ &ossl_v3_ext_ku,
+ &ossl_v3_delta_crl,
+ &ossl_v3_crl_reason,
+#ifndef OPENSSL_NO_OCSP
+ &ossl_v3_crl_invdate,
+#endif
+ &ossl_v3_sxnet,
+ &ossl_v3_info,
+#ifndef OPENSSL_NO_RFC3779
+ &ossl_v3_addr,
+ &ossl_v3_asid,
+#endif
+#ifndef OPENSSL_NO_OCSP
+ &ossl_v3_ocsp_nonce,
+ &ossl_v3_ocsp_crlid,
+ &ossl_v3_ocsp_accresp,
+ &ossl_v3_ocsp_nocheck,
+ &ossl_v3_ocsp_acutoff,
+ &ossl_v3_ocsp_serviceloc,
+#endif
+ &ossl_v3_sinfo,
+ &ossl_v3_policy_constraints,
+#ifndef OPENSSL_NO_OCSP
+ &ossl_v3_crl_hold,
+#endif
+ &ossl_v3_pci,
+ &ossl_v3_name_constraints,
+ &ossl_v3_policy_mappings,
+ &ossl_v3_inhibit_anyp,
+ &ossl_v3_idp,
+ &ossl_v3_alt[2],
+ &ossl_v3_freshest_crl,
+#ifndef OPENSSL_NO_CT
+ &ossl_v3_ct_scts[0],
+ &ossl_v3_ct_scts[1],
+ &ossl_v3_ct_scts[2],
+#endif
+ &ossl_v3_utf8_list[0],
+ &ossl_v3_issuer_sign_tool,
+ &ossl_v3_tls_feature,
+ &ossl_v3_ext_admission
+};
+
+/* Number of standard extensions */
+
+#define STANDARD_EXTENSION_COUNT OSSL_NELEM(standard_exts)
+
diff --git a/crypto/x509/t_crl.c b/crypto/x509/t_crl.c
index 8e262912ffaa..e77a77978a83 100644
--- a/crypto/x509/t_crl.c
+++ b/crypto/x509/t_crl.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -22,7 +22,7 @@ int X509_CRL_print_fp(FILE *fp, X509_CRL *x)
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- X509err(X509_F_X509_CRL_PRINT_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_X509, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
@@ -48,7 +48,7 @@ int X509_CRL_print_ex(BIO *out, X509_CRL *x, unsigned long nmflag)
BIO_printf(out, "Certificate Revocation List (CRL):\n");
l = X509_CRL_get_version(x);
- if (l >= 0 && l <= 1)
+ if (l >= X509_CRL_VERSION_1 && l <= X509_CRL_VERSION_2)
BIO_printf(out, "%8sVersion %ld (0x%lx)\n", "", l + 1, (unsigned long)l);
else
BIO_printf(out, "%8sVersion unknown (%ld)\n", "", l);
diff --git a/crypto/x509/t_req.c b/crypto/x509/t_req.c
index dc3b4f262de9..095c16510099 100644
--- a/crypto/x509/t_req.c
+++ b/crypto/x509/t_req.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -24,7 +24,7 @@ int X509_REQ_print_fp(FILE *fp, X509_REQ *x)
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- X509err(X509_F_X509_REQ_PRINT_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_X509, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
@@ -60,7 +60,7 @@ int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags,
}
if (!(cflag & X509_FLAG_NO_VERSION)) {
l = X509_REQ_get_version(x);
- if (l >= 0 && l <= 2) {
+ if (l == X509_REQ_VERSION_1) {
if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n", "", l + 1, (unsigned long)l) <= 0)
goto err;
} else {
@@ -108,7 +108,7 @@ int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags,
goto err;
if (X509_REQ_get_attr_count(x) == 0) {
- if (BIO_printf(bp, "%12sa0:00\n", "") <= 0)
+ if (BIO_printf(bp, "%12s(none)\n", "") <= 0)
goto err;
} else {
for (i = 0; i < X509_REQ_get_attr_count(x); i++) {
@@ -128,7 +128,7 @@ int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags,
ii = 0;
count = X509_ATTRIBUTE_count(a);
if (count == 0) {
- X509err(X509_F_X509_REQ_PRINT_EX, X509_R_INVALID_ATTRIBUTES);
+ ERR_raise(ERR_LIB_X509, X509_R_INVALID_ATTRIBUTES);
return 0;
}
get_next:
@@ -166,14 +166,14 @@ int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags,
if (!(cflag & X509_FLAG_NO_EXTENSIONS)) {
exts = X509_REQ_get_extensions(x);
if (exts) {
- if (BIO_printf(bp, "%8sRequested Extensions:\n", "") <= 0)
+ if (BIO_printf(bp, "%12sRequested Extensions:\n", "") <= 0)
goto err;
for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
ASN1_OBJECT *obj;
X509_EXTENSION *ex;
int critical;
ex = sk_X509_EXTENSION_value(exts, i);
- if (BIO_printf(bp, "%12s", "") <= 0)
+ if (BIO_printf(bp, "%16s", "") <= 0)
goto err;
obj = X509_EXTENSION_get_object(ex);
if (i2a_ASN1_OBJECT(bp, obj) <= 0)
@@ -181,8 +181,8 @@ int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags,
critical = X509_EXTENSION_get_critical(ex);
if (BIO_printf(bp, ": %s\n", critical ? "critical" : "") <= 0)
goto err;
- if (!X509V3_EXT_print(bp, ex, cflag, 16)) {
- if (BIO_printf(bp, "%16s", "") <= 0
+ if (!X509V3_EXT_print(bp, ex, cflag, 20)) {
+ if (BIO_printf(bp, "%20s", "") <= 0
|| ASN1_STRING_print(bp,
X509_EXTENSION_get_data(ex)) <= 0)
goto err;
@@ -204,7 +204,7 @@ int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags,
return 1;
err:
- X509err(X509_F_X509_REQ_PRINT_EX, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_X509, ERR_R_BUF_LIB);
return 0;
}
diff --git a/crypto/x509/t_x509.c b/crypto/x509/t_x509.c
index ece987a6bdbe..95ee5f519fdd 100644
--- a/crypto/x509/t_x509.c
+++ b/crypto/x509/t_x509.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -15,6 +15,7 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "crypto/asn1.h"
+#include "crypto/x509.h"
#ifndef OPENSSL_NO_STDIO
int X509_print_fp(FILE *fp, X509 *x)
@@ -29,7 +30,7 @@ int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag,
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- X509err(X509_F_X509_PRINT_EX_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_X509, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
@@ -50,8 +51,7 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
long l;
int ret = 0, i;
char *m = NULL, mlch = ' ';
- int nmindent = 0;
- ASN1_INTEGER *bs;
+ int nmindent = 0, printok = 0;
EVP_PKEY *pkey = NULL;
const char *neg;
@@ -60,8 +60,10 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
nmindent = 12;
}
- if (nmflags == X509_FLAG_COMPAT)
+ if (nmflags == X509_FLAG_COMPAT) {
nmindent = 16;
+ printok = 1;
+ }
if (!(cflag & X509_FLAG_NO_HEADER)) {
if (BIO_write(bp, "Certificate:\n", 13) <= 0)
@@ -71,7 +73,7 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
}
if (!(cflag & X509_FLAG_NO_VERSION)) {
l = X509_get_version(x);
- if (l >= 0 && l <= 2) {
+ if (l >= X509_VERSION_1 && l <= X509_VERSION_3) {
if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n", "", l + 1, (unsigned long)l) <= 0)
goto err;
} else {
@@ -80,11 +82,11 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
}
}
if (!(cflag & X509_FLAG_NO_SERIAL)) {
+ const ASN1_INTEGER *bs = X509_get0_serialNumber(x);
if (BIO_write(bp, " Serial Number:", 22) <= 0)
goto err;
- bs = X509_get_serialNumber(x);
if (bs->length <= (int)sizeof(long)) {
ERR_set_mark();
l = ASN1_INTEGER_get(bs);
@@ -130,7 +132,7 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
if (BIO_printf(bp, " Issuer:%c", mlch) <= 0)
goto err;
if (X509_NAME_print_ex(bp, X509_get_issuer_name(x), nmindent, nmflags)
- < 0)
+ < printok)
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
@@ -140,11 +142,11 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
goto err;
if (BIO_write(bp, " Not Before: ", 24) <= 0)
goto err;
- if (!ASN1_TIME_print(bp, X509_get0_notBefore(x)))
+ if (ossl_asn1_time_print_ex(bp, X509_get0_notBefore(x), ASN1_DTFLGS_RFC822) == 0)
goto err;
if (BIO_write(bp, "\n Not After : ", 25) <= 0)
goto err;
- if (!ASN1_TIME_print(bp, X509_get0_notAfter(x)))
+ if (ossl_asn1_time_print_ex(bp, X509_get0_notAfter(x), ASN1_DTFLGS_RFC822) == 0)
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
@@ -153,7 +155,7 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
if (BIO_printf(bp, " Subject:%c", mlch) <= 0)
goto err;
if (X509_NAME_print_ex
- (bp, X509_get_subject_name(x), nmindent, nmflags) < 0)
+ (bp, X509_get_subject_name(x), nmindent, nmflags) < printok)
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
@@ -197,9 +199,10 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
}
}
- if (!(cflag & X509_FLAG_NO_EXTENSIONS))
- X509V3_extensions_print(bp, "X509v3 extensions",
- X509_get0_extensions(x), cflag, 8);
+ if (!(cflag & X509_FLAG_NO_EXTENSIONS)
+ && !X509V3_extensions_print(bp, "X509v3 extensions",
+ X509_get0_extensions(x), cflag, 8))
+ goto err;
if (!(cflag & X509_FLAG_NO_SIGDUMP)) {
const X509_ALGOR *sig_alg;
@@ -226,8 +229,11 @@ int X509_ocspid_print(BIO *bp, X509 *x)
int i;
unsigned char SHA1md[SHA_DIGEST_LENGTH];
ASN1_BIT_STRING *keybstr;
- X509_NAME *subj;
+ const X509_NAME *subj;
+ EVP_MD *md = NULL;
+ if (x == NULL || bp == NULL)
+ return 0;
/*
* display the hash of the subject as it would appear in OCSP requests
*/
@@ -235,11 +241,16 @@ int X509_ocspid_print(BIO *bp, X509 *x)
goto err;
subj = X509_get_subject_name(x);
derlen = i2d_X509_NAME(subj, NULL);
+ if (derlen <= 0)
+ goto err;
if ((der = dertmp = OPENSSL_malloc(derlen)) == NULL)
goto err;
i2d_X509_NAME(subj, &dertmp);
- if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL))
+ md = EVP_MD_fetch(x->libctx, SN_sha1, x->propq);
+ if (md == NULL)
+ goto err;
+ if (!EVP_Digest(der, derlen, SHA1md, NULL, md, NULL))
goto err;
for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
@@ -260,18 +271,19 @@ int X509_ocspid_print(BIO *bp, X509 *x)
goto err;
if (!EVP_Digest(ASN1_STRING_get0_data(keybstr),
- ASN1_STRING_length(keybstr), SHA1md, NULL, EVP_sha1(),
- NULL))
+ ASN1_STRING_length(keybstr), SHA1md, NULL, md, NULL))
goto err;
for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
goto err;
}
BIO_printf(bp, "\n");
+ EVP_MD_free(md);
return 1;
err:
OPENSSL_free(der);
+ EVP_MD_free(md);
return 0;
}
@@ -284,7 +296,7 @@ int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent)
s = sig->data;
for (i = 0; i < n; i++) {
if ((i % 18) == 0) {
- if (BIO_write(bp, "\n", 1) <= 0)
+ if (i > 0 && BIO_write(bp, "\n", 1) <= 0)
return 0;
if (BIO_indent(bp, indent, indent) <= 0)
return 0;
@@ -302,11 +314,14 @@ int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg,
const ASN1_STRING *sig)
{
int sig_nid;
- if (BIO_puts(bp, " Signature Algorithm: ") <= 0)
+ int indent = 4;
+ if (BIO_printf(bp, "%*sSignature Algorithm: ", indent, "") <= 0)
return 0;
if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0)
return 0;
+ if (sig && BIO_printf(bp, "\n%*sSignature Value:", indent, "") <= 0)
+ return 0;
sig_nid = OBJ_obj2nid(sigalg->algorithm);
if (sig_nid != NID_undef) {
int pkey_nid, dig_nid;
@@ -314,13 +329,13 @@ int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg,
if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid)) {
ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
if (ameth && ameth->sig_print)
- return ameth->sig_print(bp, sigalg, sig, 9, 0);
+ return ameth->sig_print(bp, sigalg, sig, indent + 4, 0);
}
}
- if (sig)
- return X509_signature_dump(bp, sig, 9);
- else if (BIO_puts(bp, "\n") <= 0)
+ if (BIO_write(bp, "\n", 1) != 1)
return 0;
+ if (sig)
+ return X509_signature_dump(bp, sig, indent + 4);
return 1;
}
@@ -377,3 +392,138 @@ int X509_aux_print(BIO *out, X509 *x, int indent)
}
return 1;
}
+
+/*
+ * Helper functions for improving certificate verification error diagnostics
+ */
+
+int ossl_x509_print_ex_brief(BIO *bio, X509 *cert, unsigned long neg_cflags)
+{
+ unsigned long flags = ASN1_STRFLGS_RFC2253 | ASN1_STRFLGS_ESC_QUOTE |
+ XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_FN_SN;
+
+ if (cert == NULL)
+ return BIO_printf(bio, " (no certificate)\n") > 0;
+ if (BIO_printf(bio, " certificate\n") <= 0
+ || !X509_print_ex(bio, cert, flags, ~X509_FLAG_NO_SUBJECT))
+ return 0;
+ if (X509_check_issued((X509 *)cert, cert) == X509_V_OK) {
+ if (BIO_printf(bio, " self-issued\n") <= 0)
+ return 0;
+ } else {
+ if (BIO_printf(bio, " ") <= 0
+ || !X509_print_ex(bio, cert, flags, ~X509_FLAG_NO_ISSUER))
+ return 0;
+ }
+ if (!X509_print_ex(bio, cert, flags,
+ ~(X509_FLAG_NO_SERIAL | X509_FLAG_NO_VALIDITY)))
+ return 0;
+ if (X509_cmp_current_time(X509_get0_notBefore(cert)) > 0)
+ if (BIO_printf(bio, " not yet valid\n") <= 0)
+ return 0;
+ if (X509_cmp_current_time(X509_get0_notAfter(cert)) < 0)
+ if (BIO_printf(bio, " no more valid\n") <= 0)
+ return 0;
+ return X509_print_ex(bio, cert, flags,
+ ~neg_cflags & ~X509_FLAG_EXTENSIONS_ONLY_KID);
+}
+
+static int print_certs(BIO *bio, const STACK_OF(X509) *certs)
+{
+ int i;
+
+ if (certs == NULL || sk_X509_num(certs) <= 0)
+ return BIO_printf(bio, " (no certificates)\n") >= 0;
+
+ for (i = 0; i < sk_X509_num(certs); i++) {
+ X509 *cert = sk_X509_value(certs, i);
+
+ if (cert != NULL) {
+ if (!ossl_x509_print_ex_brief(bio, cert, 0))
+ return 0;
+ if (!X509V3_extensions_print(bio, NULL,
+ X509_get0_extensions(cert),
+ X509_FLAG_EXTENSIONS_ONLY_KID, 8))
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int print_store_certs(BIO *bio, X509_STORE *store)
+{
+ if (store != NULL) {
+ STACK_OF(X509) *certs = X509_STORE_get1_all_certs(store);
+ int ret = print_certs(bio, certs);
+
+ sk_X509_pop_free(certs, X509_free);
+ return ret;
+ } else {
+ return BIO_printf(bio, " (no trusted store)\n") >= 0;
+ }
+}
+
+/* Extend the error queue with details on a failed cert verification */
+int X509_STORE_CTX_print_verify_cb(int ok, X509_STORE_CTX *ctx)
+{
+ if (ok == 0 && ctx != NULL) {
+ int cert_error = X509_STORE_CTX_get_error(ctx);
+ BIO *bio = BIO_new(BIO_s_mem()); /* may be NULL */
+
+ BIO_printf(bio, "%s at depth = %d error = %d (%s)\n",
+ X509_STORE_CTX_get0_parent_ctx(ctx) != NULL
+ ? "CRL path validation"
+ : "Certificate verification",
+ X509_STORE_CTX_get_error_depth(ctx),
+ cert_error, X509_verify_cert_error_string(cert_error));
+ {
+ X509_STORE *ts = X509_STORE_CTX_get0_store(ctx);
+ X509_VERIFY_PARAM *vpm = X509_STORE_get0_param(ts);
+ char *str;
+ int idx = 0;
+
+ switch (cert_error) {
+ case X509_V_ERR_HOSTNAME_MISMATCH:
+ BIO_printf(bio, "Expected hostname(s) = ");
+ while ((str = X509_VERIFY_PARAM_get0_host(vpm, idx++)) != NULL)
+ BIO_printf(bio, "%s%s", idx == 1 ? "" : ", ", str);
+ BIO_printf(bio, "\n");
+ break;
+ case X509_V_ERR_EMAIL_MISMATCH:
+ str = X509_VERIFY_PARAM_get0_email(vpm);
+ if (str != NULL)
+ BIO_printf(bio, "Expected email address = %s\n", str);
+ break;
+ case X509_V_ERR_IP_ADDRESS_MISMATCH:
+ str = X509_VERIFY_PARAM_get1_ip_asc(vpm);
+ if (str != NULL)
+ BIO_printf(bio, "Expected IP address = %s\n", str);
+ OPENSSL_free(str);
+ break;
+ default:
+ break;
+ }
+ }
+
+ BIO_printf(bio, "Failure for:\n");
+ ossl_x509_print_ex_brief(bio, X509_STORE_CTX_get_current_cert(ctx),
+ X509_FLAG_NO_EXTENSIONS);
+ if (cert_error == X509_V_ERR_CERT_UNTRUSTED
+ || cert_error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
+ || cert_error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
+ || cert_error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
+ || cert_error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
+ || cert_error == X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER
+ || cert_error == X509_V_ERR_STORE_LOOKUP) {
+ BIO_printf(bio, "Non-trusted certs:\n");
+ print_certs(bio, X509_STORE_CTX_get0_untrusted(ctx));
+ BIO_printf(bio, "Certs in trust store:\n");
+ print_store_certs(bio, X509_STORE_CTX_get0_store(ctx));
+ }
+ ERR_raise(ERR_LIB_X509, X509_R_CERTIFICATE_VERIFICATION_FAILED);
+ ERR_add_error_mem_bio("\n", bio);
+ BIO_free(bio);
+ }
+
+ return ok;
+}
diff --git a/crypto/x509/v3_addr.c b/crypto/x509/v3_addr.c
new file mode 100644
index 000000000000..db010720741c
--- /dev/null
+++ b/crypto/x509/v3_addr.c
@@ -0,0 +1,1357 @@
+/*
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Implementation of RFC 3779 section 2.2.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "internal/cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/buffer.h>
+#include <openssl/x509v3.h>
+#include "crypto/x509.h"
+#include "ext_dat.h"
+#include "x509_local.h"
+
+#ifndef OPENSSL_NO_RFC3779
+
+/*
+ * OpenSSL ASN.1 template translation of RFC 3779 2.2.3.
+ */
+
+ASN1_SEQUENCE(IPAddressRange) = {
+ ASN1_SIMPLE(IPAddressRange, min, ASN1_BIT_STRING),
+ ASN1_SIMPLE(IPAddressRange, max, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(IPAddressRange)
+
+ASN1_CHOICE(IPAddressOrRange) = {
+ ASN1_SIMPLE(IPAddressOrRange, u.addressPrefix, ASN1_BIT_STRING),
+ ASN1_SIMPLE(IPAddressOrRange, u.addressRange, IPAddressRange)
+} ASN1_CHOICE_END(IPAddressOrRange)
+
+ASN1_CHOICE(IPAddressChoice) = {
+ ASN1_SIMPLE(IPAddressChoice, u.inherit, ASN1_NULL),
+ ASN1_SEQUENCE_OF(IPAddressChoice, u.addressesOrRanges, IPAddressOrRange)
+} ASN1_CHOICE_END(IPAddressChoice)
+
+ASN1_SEQUENCE(IPAddressFamily) = {
+ ASN1_SIMPLE(IPAddressFamily, addressFamily, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(IPAddressFamily, ipAddressChoice, IPAddressChoice)
+} ASN1_SEQUENCE_END(IPAddressFamily)
+
+ASN1_ITEM_TEMPLATE(IPAddrBlocks) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0,
+ IPAddrBlocks, IPAddressFamily)
+static_ASN1_ITEM_TEMPLATE_END(IPAddrBlocks)
+
+IMPLEMENT_ASN1_FUNCTIONS(IPAddressRange)
+IMPLEMENT_ASN1_FUNCTIONS(IPAddressOrRange)
+IMPLEMENT_ASN1_FUNCTIONS(IPAddressChoice)
+IMPLEMENT_ASN1_FUNCTIONS(IPAddressFamily)
+
+/*
+ * How much buffer space do we need for a raw address?
+ */
+#define ADDR_RAW_BUF_LEN 16
+
+/*
+ * What's the address length associated with this AFI?
+ */
+static int length_from_afi(const unsigned afi)
+{
+ switch (afi) {
+ case IANA_AFI_IPV4:
+ return 4;
+ case IANA_AFI_IPV6:
+ return 16;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * Extract the AFI from an IPAddressFamily.
+ */
+unsigned int X509v3_addr_get_afi(const IPAddressFamily *f)
+{
+ if (f == NULL
+ || f->addressFamily == NULL
+ || f->addressFamily->data == NULL
+ || f->addressFamily->length < 2)
+ return 0;
+ return (f->addressFamily->data[0] << 8) | f->addressFamily->data[1];
+}
+
+/*
+ * Expand the bitstring form of an address into a raw byte array.
+ * At the moment this is coded for simplicity, not speed.
+ */
+static int addr_expand(unsigned char *addr,
+ const ASN1_BIT_STRING *bs,
+ const int length, const unsigned char fill)
+{
+ if (bs->length < 0 || bs->length > length)
+ return 0;
+ if (bs->length > 0) {
+ memcpy(addr, bs->data, bs->length);
+ if ((bs->flags & 7) != 0) {
+ unsigned char mask = 0xFF >> (8 - (bs->flags & 7));
+ if (fill == 0)
+ addr[bs->length - 1] &= ~mask;
+ else
+ addr[bs->length - 1] |= mask;
+ }
+ }
+ memset(addr + bs->length, fill, length - bs->length);
+ return 1;
+}
+
+/*
+ * Extract the prefix length from a bitstring.
+ */
+#define addr_prefixlen(bs) ((int) ((bs)->length * 8 - ((bs)->flags & 7)))
+
+/*
+ * i2r handler for one address bitstring.
+ */
+static int i2r_address(BIO *out,
+ const unsigned afi,
+ const unsigned char fill, const ASN1_BIT_STRING *bs)
+{
+ unsigned char addr[ADDR_RAW_BUF_LEN];
+ int i, n;
+
+ if (bs->length < 0)
+ return 0;
+ switch (afi) {
+ case IANA_AFI_IPV4:
+ if (!addr_expand(addr, bs, 4, fill))
+ return 0;
+ BIO_printf(out, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
+ break;
+ case IANA_AFI_IPV6:
+ if (!addr_expand(addr, bs, 16, fill))
+ return 0;
+ for (n = 16; n > 1 && addr[n - 1] == 0x00 && addr[n - 2] == 0x00;
+ n -= 2) ;
+ for (i = 0; i < n; i += 2)
+ BIO_printf(out, "%x%s", (addr[i] << 8) | addr[i + 1],
+ (i < 14 ? ":" : ""));
+ if (i < 16)
+ BIO_puts(out, ":");
+ if (i == 0)
+ BIO_puts(out, ":");
+ break;
+ default:
+ for (i = 0; i < bs->length; i++)
+ BIO_printf(out, "%s%02x", (i > 0 ? ":" : ""), bs->data[i]);
+ BIO_printf(out, "[%d]", (int)(bs->flags & 7));
+ break;
+ }
+ return 1;
+}
+
+/*
+ * i2r handler for a sequence of addresses and ranges.
+ */
+static int i2r_IPAddressOrRanges(BIO *out,
+ const int indent,
+ const IPAddressOrRanges *aors,
+ const unsigned afi)
+{
+ int i;
+ for (i = 0; i < sk_IPAddressOrRange_num(aors); i++) {
+ const IPAddressOrRange *aor = sk_IPAddressOrRange_value(aors, i);
+ BIO_printf(out, "%*s", indent, "");
+ switch (aor->type) {
+ case IPAddressOrRange_addressPrefix:
+ if (!i2r_address(out, afi, 0x00, aor->u.addressPrefix))
+ return 0;
+ BIO_printf(out, "/%d\n", addr_prefixlen(aor->u.addressPrefix));
+ continue;
+ case IPAddressOrRange_addressRange:
+ if (!i2r_address(out, afi, 0x00, aor->u.addressRange->min))
+ return 0;
+ BIO_puts(out, "-");
+ if (!i2r_address(out, afi, 0xFF, aor->u.addressRange->max))
+ return 0;
+ BIO_puts(out, "\n");
+ continue;
+ }
+ }
+ return 1;
+}
+
+/*
+ * i2r handler for an IPAddrBlocks extension.
+ */
+static int i2r_IPAddrBlocks(const X509V3_EXT_METHOD *method,
+ void *ext, BIO *out, int indent)
+{
+ const IPAddrBlocks *addr = ext;
+ int i;
+ for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
+ IPAddressFamily *f = sk_IPAddressFamily_value(addr, i);
+ const unsigned int afi = X509v3_addr_get_afi(f);
+ switch (afi) {
+ case IANA_AFI_IPV4:
+ BIO_printf(out, "%*sIPv4", indent, "");
+ break;
+ case IANA_AFI_IPV6:
+ BIO_printf(out, "%*sIPv6", indent, "");
+ break;
+ default:
+ BIO_printf(out, "%*sUnknown AFI %u", indent, "", afi);
+ break;
+ }
+ if (f->addressFamily->length > 2) {
+ switch (f->addressFamily->data[2]) {
+ case 1:
+ BIO_puts(out, " (Unicast)");
+ break;
+ case 2:
+ BIO_puts(out, " (Multicast)");
+ break;
+ case 3:
+ BIO_puts(out, " (Unicast/Multicast)");
+ break;
+ case 4:
+ BIO_puts(out, " (MPLS)");
+ break;
+ case 64:
+ BIO_puts(out, " (Tunnel)");
+ break;
+ case 65:
+ BIO_puts(out, " (VPLS)");
+ break;
+ case 66:
+ BIO_puts(out, " (BGP MDT)");
+ break;
+ case 128:
+ BIO_puts(out, " (MPLS-labeled VPN)");
+ break;
+ default:
+ BIO_printf(out, " (Unknown SAFI %u)",
+ (unsigned)f->addressFamily->data[2]);
+ break;
+ }
+ }
+ switch (f->ipAddressChoice->type) {
+ case IPAddressChoice_inherit:
+ BIO_puts(out, ": inherit\n");
+ break;
+ case IPAddressChoice_addressesOrRanges:
+ BIO_puts(out, ":\n");
+ if (!i2r_IPAddressOrRanges(out,
+ indent + 2,
+ f->ipAddressChoice->
+ u.addressesOrRanges, afi))
+ return 0;
+ break;
+ }
+ }
+ return 1;
+}
+
+/*
+ * Sort comparison function for a sequence of IPAddressOrRange
+ * elements.
+ *
+ * There's no sane answer we can give if addr_expand() fails, and an
+ * assertion failure on externally supplied data is seriously uncool,
+ * so we just arbitrarily declare that if given invalid inputs this
+ * function returns -1. If this messes up your preferred sort order
+ * for garbage input, tough noogies.
+ */
+static int IPAddressOrRange_cmp(const IPAddressOrRange *a,
+ const IPAddressOrRange *b, const int length)
+{
+ unsigned char addr_a[ADDR_RAW_BUF_LEN], addr_b[ADDR_RAW_BUF_LEN];
+ int prefixlen_a = 0, prefixlen_b = 0;
+ int r;
+
+ switch (a->type) {
+ case IPAddressOrRange_addressPrefix:
+ if (!addr_expand(addr_a, a->u.addressPrefix, length, 0x00))
+ return -1;
+ prefixlen_a = addr_prefixlen(a->u.addressPrefix);
+ break;
+ case IPAddressOrRange_addressRange:
+ if (!addr_expand(addr_a, a->u.addressRange->min, length, 0x00))
+ return -1;
+ prefixlen_a = length * 8;
+ break;
+ }
+
+ switch (b->type) {
+ case IPAddressOrRange_addressPrefix:
+ if (!addr_expand(addr_b, b->u.addressPrefix, length, 0x00))
+ return -1;
+ prefixlen_b = addr_prefixlen(b->u.addressPrefix);
+ break;
+ case IPAddressOrRange_addressRange:
+ if (!addr_expand(addr_b, b->u.addressRange->min, length, 0x00))
+ return -1;
+ prefixlen_b = length * 8;
+ break;
+ }
+
+ if ((r = memcmp(addr_a, addr_b, length)) != 0)
+ return r;
+ else
+ return prefixlen_a - prefixlen_b;
+}
+
+/*
+ * IPv4-specific closure over IPAddressOrRange_cmp, since sk_sort()
+ * comparison routines are only allowed two arguments.
+ */
+static int v4IPAddressOrRange_cmp(const IPAddressOrRange *const *a,
+ const IPAddressOrRange *const *b)
+{
+ return IPAddressOrRange_cmp(*a, *b, 4);
+}
+
+/*
+ * IPv6-specific closure over IPAddressOrRange_cmp, since sk_sort()
+ * comparison routines are only allowed two arguments.
+ */
+static int v6IPAddressOrRange_cmp(const IPAddressOrRange *const *a,
+ const IPAddressOrRange *const *b)
+{
+ return IPAddressOrRange_cmp(*a, *b, 16);
+}
+
+/*
+ * Calculate whether a range collapses to a prefix.
+ * See last paragraph of RFC 3779 2.2.3.7.
+ */
+static int range_should_be_prefix(const unsigned char *min,
+ const unsigned char *max, const int length)
+{
+ unsigned char mask;
+ int i, j;
+
+ /*
+ * It is the responsibility of the caller to confirm min <= max. We don't
+ * use ossl_assert() here since we have no way of signalling an error from
+ * this function - so we just use a plain assert instead.
+ */
+ assert(memcmp(min, max, length) <= 0);
+
+ for (i = 0; i < length && min[i] == max[i]; i++) ;
+ for (j = length - 1; j >= 0 && min[j] == 0x00 && max[j] == 0xFF; j--) ;
+ if (i < j)
+ return -1;
+ if (i > j)
+ return i * 8;
+ mask = min[i] ^ max[i];
+ switch (mask) {
+ case 0x01:
+ j = 7;
+ break;
+ case 0x03:
+ j = 6;
+ break;
+ case 0x07:
+ j = 5;
+ break;
+ case 0x0F:
+ j = 4;
+ break;
+ case 0x1F:
+ j = 3;
+ break;
+ case 0x3F:
+ j = 2;
+ break;
+ case 0x7F:
+ j = 1;
+ break;
+ default:
+ return -1;
+ }
+ if ((min[i] & mask) != 0 || (max[i] & mask) != mask)
+ return -1;
+ else
+ return i * 8 + j;
+}
+
+/*
+ * Construct a prefix.
+ */
+static int make_addressPrefix(IPAddressOrRange **result, unsigned char *addr,
+ const int prefixlen, const int afilen)
+{
+ int bytelen = (prefixlen + 7) / 8, bitlen = prefixlen % 8;
+ IPAddressOrRange *aor = IPAddressOrRange_new();
+
+ if (prefixlen < 0 || prefixlen > (afilen * 8))
+ return 0;
+ if (aor == NULL)
+ return 0;
+ aor->type = IPAddressOrRange_addressPrefix;
+ if (aor->u.addressPrefix == NULL &&
+ (aor->u.addressPrefix = ASN1_BIT_STRING_new()) == NULL)
+ goto err;
+ if (!ASN1_BIT_STRING_set(aor->u.addressPrefix, addr, bytelen))
+ goto err;
+ aor->u.addressPrefix->flags &= ~7;
+ aor->u.addressPrefix->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+ if (bitlen > 0) {
+ aor->u.addressPrefix->data[bytelen - 1] &= ~(0xFF >> bitlen);
+ aor->u.addressPrefix->flags |= 8 - bitlen;
+ }
+
+ *result = aor;
+ return 1;
+
+ err:
+ IPAddressOrRange_free(aor);
+ return 0;
+}
+
+/*
+ * Construct a range. If it can be expressed as a prefix,
+ * return a prefix instead. Doing this here simplifies
+ * the rest of the code considerably.
+ */
+static int make_addressRange(IPAddressOrRange **result,
+ unsigned char *min,
+ unsigned char *max, const int length)
+{
+ IPAddressOrRange *aor;
+ int i, prefixlen;
+
+ if (memcmp(min, max, length) > 0)
+ return 0;
+
+ if ((prefixlen = range_should_be_prefix(min, max, length)) >= 0)
+ return make_addressPrefix(result, min, prefixlen, length);
+
+ if ((aor = IPAddressOrRange_new()) == NULL)
+ return 0;
+ aor->type = IPAddressOrRange_addressRange;
+ if ((aor->u.addressRange = IPAddressRange_new()) == NULL)
+ goto err;
+ if (aor->u.addressRange->min == NULL &&
+ (aor->u.addressRange->min = ASN1_BIT_STRING_new()) == NULL)
+ goto err;
+ if (aor->u.addressRange->max == NULL &&
+ (aor->u.addressRange->max = ASN1_BIT_STRING_new()) == NULL)
+ goto err;
+
+ for (i = length; i > 0 && min[i - 1] == 0x00; --i) ;
+ if (!ASN1_BIT_STRING_set(aor->u.addressRange->min, min, i))
+ goto err;
+ aor->u.addressRange->min->flags &= ~7;
+ aor->u.addressRange->min->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+ if (i > 0) {
+ unsigned char b = min[i - 1];
+ int j = 1;
+ while ((b & (0xFFU >> j)) != 0)
+ ++j;
+ aor->u.addressRange->min->flags |= 8 - j;
+ }
+
+ for (i = length; i > 0 && max[i - 1] == 0xFF; --i) ;
+ if (!ASN1_BIT_STRING_set(aor->u.addressRange->max, max, i))
+ goto err;
+ aor->u.addressRange->max->flags &= ~7;
+ aor->u.addressRange->max->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+ if (i > 0) {
+ unsigned char b = max[i - 1];
+ int j = 1;
+ while ((b & (0xFFU >> j)) != (0xFFU >> j))
+ ++j;
+ aor->u.addressRange->max->flags |= 8 - j;
+ }
+
+ *result = aor;
+ return 1;
+
+ err:
+ IPAddressOrRange_free(aor);
+ return 0;
+}
+
+/*
+ * Construct a new address family or find an existing one.
+ */
+static IPAddressFamily *make_IPAddressFamily(IPAddrBlocks *addr,
+ const unsigned afi,
+ const unsigned *safi)
+{
+ IPAddressFamily *f;
+ unsigned char key[3];
+ int keylen;
+ int i;
+
+ key[0] = (afi >> 8) & 0xFF;
+ key[1] = afi & 0xFF;
+ if (safi != NULL) {
+ key[2] = *safi & 0xFF;
+ keylen = 3;
+ } else {
+ keylen = 2;
+ }
+
+ for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
+ f = sk_IPAddressFamily_value(addr, i);
+ if (f->addressFamily->length == keylen &&
+ !memcmp(f->addressFamily->data, key, keylen))
+ return f;
+ }
+
+ if ((f = IPAddressFamily_new()) == NULL)
+ goto err;
+ if (f->ipAddressChoice == NULL &&
+ (f->ipAddressChoice = IPAddressChoice_new()) == NULL)
+ goto err;
+ if (f->addressFamily == NULL &&
+ (f->addressFamily = ASN1_OCTET_STRING_new()) == NULL)
+ goto err;
+ if (!ASN1_OCTET_STRING_set(f->addressFamily, key, keylen))
+ goto err;
+ if (!sk_IPAddressFamily_push(addr, f))
+ goto err;
+
+ return f;
+
+ err:
+ IPAddressFamily_free(f);
+ return NULL;
+}
+
+/*
+ * Add an inheritance element.
+ */
+int X509v3_addr_add_inherit(IPAddrBlocks *addr,
+ const unsigned afi, const unsigned *safi)
+{
+ IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi);
+ if (f == NULL ||
+ f->ipAddressChoice == NULL ||
+ (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges &&
+ f->ipAddressChoice->u.addressesOrRanges != NULL))
+ return 0;
+ if (f->ipAddressChoice->type == IPAddressChoice_inherit &&
+ f->ipAddressChoice->u.inherit != NULL)
+ return 1;
+ if (f->ipAddressChoice->u.inherit == NULL &&
+ (f->ipAddressChoice->u.inherit = ASN1_NULL_new()) == NULL)
+ return 0;
+ f->ipAddressChoice->type = IPAddressChoice_inherit;
+ return 1;
+}
+
+/*
+ * Construct an IPAddressOrRange sequence, or return an existing one.
+ */
+static IPAddressOrRanges *make_prefix_or_range(IPAddrBlocks *addr,
+ const unsigned afi,
+ const unsigned *safi)
+{
+ IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi);
+ IPAddressOrRanges *aors = NULL;
+
+ if (f == NULL ||
+ f->ipAddressChoice == NULL ||
+ (f->ipAddressChoice->type == IPAddressChoice_inherit &&
+ f->ipAddressChoice->u.inherit != NULL))
+ return NULL;
+ if (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges)
+ aors = f->ipAddressChoice->u.addressesOrRanges;
+ if (aors != NULL)
+ return aors;
+ if ((aors = sk_IPAddressOrRange_new_null()) == NULL)
+ return NULL;
+ switch (afi) {
+ case IANA_AFI_IPV4:
+ (void)sk_IPAddressOrRange_set_cmp_func(aors, v4IPAddressOrRange_cmp);
+ break;
+ case IANA_AFI_IPV6:
+ (void)sk_IPAddressOrRange_set_cmp_func(aors, v6IPAddressOrRange_cmp);
+ break;
+ }
+ f->ipAddressChoice->type = IPAddressChoice_addressesOrRanges;
+ f->ipAddressChoice->u.addressesOrRanges = aors;
+ return aors;
+}
+
+/*
+ * Add a prefix.
+ */
+int X509v3_addr_add_prefix(IPAddrBlocks *addr,
+ const unsigned afi,
+ const unsigned *safi,
+ unsigned char *a, const int prefixlen)
+{
+ IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi);
+ IPAddressOrRange *aor;
+
+ if (aors == NULL
+ || !make_addressPrefix(&aor, a, prefixlen, length_from_afi(afi)))
+ return 0;
+ if (sk_IPAddressOrRange_push(aors, aor))
+ return 1;
+ IPAddressOrRange_free(aor);
+ return 0;
+}
+
+/*
+ * Add a range.
+ */
+int X509v3_addr_add_range(IPAddrBlocks *addr,
+ const unsigned afi,
+ const unsigned *safi,
+ unsigned char *min, unsigned char *max)
+{
+ IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi);
+ IPAddressOrRange *aor;
+ int length = length_from_afi(afi);
+ if (aors == NULL)
+ return 0;
+ if (!make_addressRange(&aor, min, max, length))
+ return 0;
+ if (sk_IPAddressOrRange_push(aors, aor))
+ return 1;
+ IPAddressOrRange_free(aor);
+ return 0;
+}
+
+/*
+ * Extract min and max values from an IPAddressOrRange.
+ */
+static int extract_min_max(IPAddressOrRange *aor,
+ unsigned char *min, unsigned char *max, int length)
+{
+ if (aor == NULL || min == NULL || max == NULL)
+ return 0;
+ switch (aor->type) {
+ case IPAddressOrRange_addressPrefix:
+ return (addr_expand(min, aor->u.addressPrefix, length, 0x00) &&
+ addr_expand(max, aor->u.addressPrefix, length, 0xFF));
+ case IPAddressOrRange_addressRange:
+ return (addr_expand(min, aor->u.addressRange->min, length, 0x00) &&
+ addr_expand(max, aor->u.addressRange->max, length, 0xFF));
+ }
+ return 0;
+}
+
+/*
+ * Public wrapper for extract_min_max().
+ */
+int X509v3_addr_get_range(IPAddressOrRange *aor,
+ const unsigned afi,
+ unsigned char *min,
+ unsigned char *max, const int length)
+{
+ int afi_length = length_from_afi(afi);
+ if (aor == NULL || min == NULL || max == NULL ||
+ afi_length == 0 || length < afi_length ||
+ (aor->type != IPAddressOrRange_addressPrefix &&
+ aor->type != IPAddressOrRange_addressRange) ||
+ !extract_min_max(aor, min, max, afi_length))
+ return 0;
+
+ return afi_length;
+}
+
+/*
+ * Sort comparison function for a sequence of IPAddressFamily.
+ *
+ * The last paragraph of RFC 3779 2.2.3.3 is slightly ambiguous about
+ * the ordering: I can read it as meaning that IPv6 without a SAFI
+ * comes before IPv4 with a SAFI, which seems pretty weird. The
+ * examples in appendix B suggest that the author intended the
+ * null-SAFI rule to apply only within a single AFI, which is what I
+ * would have expected and is what the following code implements.
+ */
+static int IPAddressFamily_cmp(const IPAddressFamily *const *a_,
+ const IPAddressFamily *const *b_)
+{
+ const ASN1_OCTET_STRING *a = (*a_)->addressFamily;
+ const ASN1_OCTET_STRING *b = (*b_)->addressFamily;
+ int len = ((a->length <= b->length) ? a->length : b->length);
+ int cmp = memcmp(a->data, b->data, len);
+ return cmp ? cmp : a->length - b->length;
+}
+
+static int IPAddressFamily_check_len(const IPAddressFamily *f)
+{
+ if (f->addressFamily->length < 2 || f->addressFamily->length > 3)
+ return 0;
+ else
+ return 1;
+}
+
+/*
+ * Check whether an IPAddrBLocks is in canonical form.
+ */
+int X509v3_addr_is_canonical(IPAddrBlocks *addr)
+{
+ unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN];
+ unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN];
+ IPAddressOrRanges *aors;
+ int i, j, k;
+
+ /*
+ * Empty extension is canonical.
+ */
+ if (addr == NULL)
+ return 1;
+
+ /*
+ * Check whether the top-level list is in order.
+ */
+ for (i = 0; i < sk_IPAddressFamily_num(addr) - 1; i++) {
+ const IPAddressFamily *a = sk_IPAddressFamily_value(addr, i);
+ const IPAddressFamily *b = sk_IPAddressFamily_value(addr, i + 1);
+
+ if (!IPAddressFamily_check_len(a) || !IPAddressFamily_check_len(b))
+ return 0;
+
+ if (IPAddressFamily_cmp(&a, &b) >= 0)
+ return 0;
+ }
+
+ /*
+ * Top level's ok, now check each address family.
+ */
+ for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
+ IPAddressFamily *f = sk_IPAddressFamily_value(addr, i);
+ int length = length_from_afi(X509v3_addr_get_afi(f));
+
+ /*
+ * Inheritance is canonical. Anything other than inheritance or
+ * a SEQUENCE OF IPAddressOrRange is an ASN.1 error or something.
+ */
+ if (f == NULL || f->ipAddressChoice == NULL)
+ return 0;
+ switch (f->ipAddressChoice->type) {
+ case IPAddressChoice_inherit:
+ continue;
+ case IPAddressChoice_addressesOrRanges:
+ break;
+ default:
+ return 0;
+ }
+
+ if (!IPAddressFamily_check_len(f))
+ return 0;
+
+ /*
+ * It's an IPAddressOrRanges sequence, check it.
+ */
+ aors = f->ipAddressChoice->u.addressesOrRanges;
+ if (sk_IPAddressOrRange_num(aors) == 0)
+ return 0;
+ for (j = 0; j < sk_IPAddressOrRange_num(aors) - 1; j++) {
+ IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j);
+ IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, j + 1);
+
+ if (!extract_min_max(a, a_min, a_max, length) ||
+ !extract_min_max(b, b_min, b_max, length))
+ return 0;
+
+ /*
+ * Punt misordered list, overlapping start, or inverted range.
+ */
+ if (memcmp(a_min, b_min, length) >= 0 ||
+ memcmp(a_min, a_max, length) > 0 ||
+ memcmp(b_min, b_max, length) > 0)
+ return 0;
+
+ /*
+ * Punt if adjacent or overlapping. Check for adjacency by
+ * subtracting one from b_min first.
+ */
+ for (k = length - 1; k >= 0 && b_min[k]-- == 0x00; k--) ;
+ if (memcmp(a_max, b_min, length) >= 0)
+ return 0;
+
+ /*
+ * Check for range that should be expressed as a prefix.
+ */
+ if (a->type == IPAddressOrRange_addressRange &&
+ range_should_be_prefix(a_min, a_max, length) >= 0)
+ return 0;
+ }
+
+ /*
+ * Check range to see if it's inverted or should be a
+ * prefix.
+ */
+ j = sk_IPAddressOrRange_num(aors) - 1;
+ {
+ IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j);
+ if (a != NULL && a->type == IPAddressOrRange_addressRange) {
+ if (!extract_min_max(a, a_min, a_max, length))
+ return 0;
+ if (memcmp(a_min, a_max, length) > 0 ||
+ range_should_be_prefix(a_min, a_max, length) >= 0)
+ return 0;
+ }
+ }
+ }
+
+ /*
+ * If we made it through all that, we're happy.
+ */
+ return 1;
+}
+
+/*
+ * Whack an IPAddressOrRanges into canonical form.
+ */
+static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors,
+ const unsigned afi)
+{
+ int i, j, length = length_from_afi(afi);
+
+ /*
+ * Sort the IPAddressOrRanges sequence.
+ */
+ sk_IPAddressOrRange_sort(aors);
+
+ /*
+ * Clean up representation issues, punt on duplicates or overlaps.
+ */
+ for (i = 0; i < sk_IPAddressOrRange_num(aors) - 1; i++) {
+ IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, i);
+ IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, i + 1);
+ unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN];
+ unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN];
+
+ if (!extract_min_max(a, a_min, a_max, length) ||
+ !extract_min_max(b, b_min, b_max, length))
+ return 0;
+
+ /*
+ * Punt inverted ranges.
+ */
+ if (memcmp(a_min, a_max, length) > 0 ||
+ memcmp(b_min, b_max, length) > 0)
+ return 0;
+
+ /*
+ * Punt overlaps.
+ */
+ if (memcmp(a_max, b_min, length) >= 0)
+ return 0;
+
+ /*
+ * Merge if a and b are adjacent. We check for
+ * adjacency by subtracting one from b_min first.
+ */
+ for (j = length - 1; j >= 0 && b_min[j]-- == 0x00; j--) ;
+ if (memcmp(a_max, b_min, length) == 0) {
+ IPAddressOrRange *merged;
+ if (!make_addressRange(&merged, a_min, b_max, length))
+ return 0;
+ (void)sk_IPAddressOrRange_set(aors, i, merged);
+ (void)sk_IPAddressOrRange_delete(aors, i + 1);
+ IPAddressOrRange_free(a);
+ IPAddressOrRange_free(b);
+ --i;
+ continue;
+ }
+ }
+
+ /*
+ * Check for inverted final range.
+ */
+ j = sk_IPAddressOrRange_num(aors) - 1;
+ {
+ IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j);
+ if (a != NULL && a->type == IPAddressOrRange_addressRange) {
+ unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN];
+ if (!extract_min_max(a, a_min, a_max, length))
+ return 0;
+ if (memcmp(a_min, a_max, length) > 0)
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * Whack an IPAddrBlocks extension into canonical form.
+ */
+int X509v3_addr_canonize(IPAddrBlocks *addr)
+{
+ int i;
+ for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
+ IPAddressFamily *f = sk_IPAddressFamily_value(addr, i);
+
+ if (!IPAddressFamily_check_len(f))
+ return 0;
+
+ if (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges &&
+ !IPAddressOrRanges_canonize(f->ipAddressChoice->
+ u.addressesOrRanges,
+ X509v3_addr_get_afi(f)))
+ return 0;
+ }
+ (void)sk_IPAddressFamily_set_cmp_func(addr, IPAddressFamily_cmp);
+ sk_IPAddressFamily_sort(addr);
+ if (!ossl_assert(X509v3_addr_is_canonical(addr)))
+ return 0;
+ return 1;
+}
+
+/*
+ * v2i handler for the IPAddrBlocks extension.
+ */
+static void *v2i_IPAddrBlocks(const struct v3_ext_method *method,
+ struct v3_ext_ctx *ctx,
+ STACK_OF(CONF_VALUE) *values)
+{
+ static const char v4addr_chars[] = "0123456789.";
+ static const char v6addr_chars[] = "0123456789.:abcdefABCDEF";
+ IPAddrBlocks *addr = NULL;
+ char *s = NULL, *t;
+ int i;
+
+ if ((addr = sk_IPAddressFamily_new(IPAddressFamily_cmp)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
+ CONF_VALUE *val = sk_CONF_VALUE_value(values, i);
+ unsigned char min[ADDR_RAW_BUF_LEN], max[ADDR_RAW_BUF_LEN];
+ unsigned afi, *safi = NULL, safi_;
+ const char *addr_chars = NULL;
+ int prefixlen, i1, i2, delim, length;
+
+ if (!ossl_v3_name_cmp(val->name, "IPv4")) {
+ afi = IANA_AFI_IPV4;
+ } else if (!ossl_v3_name_cmp(val->name, "IPv6")) {
+ afi = IANA_AFI_IPV6;
+ } else if (!ossl_v3_name_cmp(val->name, "IPv4-SAFI")) {
+ afi = IANA_AFI_IPV4;
+ safi = &safi_;
+ } else if (!ossl_v3_name_cmp(val->name, "IPv6-SAFI")) {
+ afi = IANA_AFI_IPV6;
+ safi = &safi_;
+ } else {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_EXTENSION_NAME_ERROR,
+ "%s", val->name);
+ goto err;
+ }
+
+ switch (afi) {
+ case IANA_AFI_IPV4:
+ addr_chars = v4addr_chars;
+ break;
+ case IANA_AFI_IPV6:
+ addr_chars = v6addr_chars;
+ break;
+ }
+
+ length = length_from_afi(afi);
+
+ /*
+ * Handle SAFI, if any, and OPENSSL_strdup() so we can null-terminate
+ * the other input values.
+ */
+ if (safi != NULL) {
+ *safi = strtoul(val->value, &t, 0);
+ t += strspn(t, " \t");
+ if (*safi > 0xFF || *t++ != ':') {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_SAFI);
+ X509V3_conf_add_error_name_value(val);
+ goto err;
+ }
+ t += strspn(t, " \t");
+ s = OPENSSL_strdup(t);
+ } else {
+ s = OPENSSL_strdup(val->value);
+ }
+ if (s == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /*
+ * Check for inheritance. Not worth additional complexity to
+ * optimize this (seldom-used) case.
+ */
+ if (strcmp(s, "inherit") == 0) {
+ if (!X509v3_addr_add_inherit(addr, afi, safi)) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_INHERITANCE);
+ X509V3_conf_add_error_name_value(val);
+ goto err;
+ }
+ OPENSSL_free(s);
+ s = NULL;
+ continue;
+ }
+
+ i1 = strspn(s, addr_chars);
+ i2 = i1 + strspn(s + i1, " \t");
+ delim = s[i2++];
+ s[i1] = '\0';
+
+ if (ossl_a2i_ipadd(min, s) != length) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_IPADDRESS);
+ X509V3_conf_add_error_name_value(val);
+ goto err;
+ }
+
+ switch (delim) {
+ case '/':
+ prefixlen = (int)strtoul(s + i2, &t, 10);
+ if (t == s + i2
+ || *t != '\0'
+ || prefixlen > (length * 8)
+ || prefixlen < 0) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
+ X509V3_conf_add_error_name_value(val);
+ goto err;
+ }
+ if (!X509v3_addr_add_prefix(addr, afi, safi, min, prefixlen)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ break;
+ case '-':
+ i1 = i2 + strspn(s + i2, " \t");
+ i2 = i1 + strspn(s + i1, addr_chars);
+ if (i1 == i2 || s[i2] != '\0') {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
+ X509V3_conf_add_error_name_value(val);
+ goto err;
+ }
+ if (ossl_a2i_ipadd(max, s + i1) != length) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_IPADDRESS);
+ X509V3_conf_add_error_name_value(val);
+ goto err;
+ }
+ if (memcmp(min, max, length_from_afi(afi)) > 0) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
+ X509V3_conf_add_error_name_value(val);
+ goto err;
+ }
+ if (!X509v3_addr_add_range(addr, afi, safi, min, max)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ break;
+ case '\0':
+ if (!X509v3_addr_add_prefix(addr, afi, safi, min, length * 8)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ break;
+ default:
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
+ X509V3_conf_add_error_name_value(val);
+ goto err;
+ }
+
+ OPENSSL_free(s);
+ s = NULL;
+ }
+
+ /*
+ * Canonize the result, then we're done.
+ */
+ if (!X509v3_addr_canonize(addr))
+ goto err;
+ return addr;
+
+ err:
+ OPENSSL_free(s);
+ sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free);
+ return NULL;
+}
+
+/*
+ * OpenSSL dispatch
+ */
+const X509V3_EXT_METHOD ossl_v3_addr = {
+ NID_sbgp_ipAddrBlock, /* nid */
+ 0, /* flags */
+ ASN1_ITEM_ref(IPAddrBlocks), /* template */
+ 0, 0, 0, 0, /* old functions, ignored */
+ 0, /* i2s */
+ 0, /* s2i */
+ 0, /* i2v */
+ v2i_IPAddrBlocks, /* v2i */
+ i2r_IPAddrBlocks, /* i2r */
+ 0, /* r2i */
+ NULL /* extension-specific data */
+};
+
+/*
+ * Figure out whether extension sues inheritance.
+ */
+int X509v3_addr_inherits(IPAddrBlocks *addr)
+{
+ int i;
+ if (addr == NULL)
+ return 0;
+ for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
+ IPAddressFamily *f = sk_IPAddressFamily_value(addr, i);
+ if (f->ipAddressChoice->type == IPAddressChoice_inherit)
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Figure out whether parent contains child.
+ */
+static int addr_contains(IPAddressOrRanges *parent,
+ IPAddressOrRanges *child, int length)
+{
+ unsigned char p_min[ADDR_RAW_BUF_LEN], p_max[ADDR_RAW_BUF_LEN];
+ unsigned char c_min[ADDR_RAW_BUF_LEN], c_max[ADDR_RAW_BUF_LEN];
+ int p, c;
+
+ if (child == NULL || parent == child)
+ return 1;
+ if (parent == NULL)
+ return 0;
+
+ p = 0;
+ for (c = 0; c < sk_IPAddressOrRange_num(child); c++) {
+ if (!extract_min_max(sk_IPAddressOrRange_value(child, c),
+ c_min, c_max, length))
+ return 0;
+ for (;; p++) {
+ if (p >= sk_IPAddressOrRange_num(parent))
+ return 0;
+ if (!extract_min_max(sk_IPAddressOrRange_value(parent, p),
+ p_min, p_max, length))
+ return 0;
+ if (memcmp(p_max, c_max, length) < 0)
+ continue;
+ if (memcmp(p_min, c_min, length) > 0)
+ return 0;
+ break;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * Test whether a is a subset of b.
+ */
+int X509v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b)
+{
+ int i;
+ if (a == NULL || a == b)
+ return 1;
+ if (b == NULL || X509v3_addr_inherits(a) || X509v3_addr_inherits(b))
+ return 0;
+ (void)sk_IPAddressFamily_set_cmp_func(b, IPAddressFamily_cmp);
+ for (i = 0; i < sk_IPAddressFamily_num(a); i++) {
+ IPAddressFamily *fa = sk_IPAddressFamily_value(a, i);
+ int j = sk_IPAddressFamily_find(b, fa);
+ IPAddressFamily *fb = sk_IPAddressFamily_value(b, j);
+
+ if (fb == NULL)
+ return 0;
+ if (!IPAddressFamily_check_len(fa) || !IPAddressFamily_check_len(fb))
+ return 0;
+ if (!addr_contains(fb->ipAddressChoice->u.addressesOrRanges,
+ fa->ipAddressChoice->u.addressesOrRanges,
+ length_from_afi(X509v3_addr_get_afi(fb))))
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Validation error handling via callback.
+ */
+# define validation_err(_err_) \
+ do { \
+ if (ctx != NULL) { \
+ ctx->error = _err_; \
+ ctx->error_depth = i; \
+ ctx->current_cert = x; \
+ rv = ctx->verify_cb(0, ctx); \
+ } else { \
+ rv = 0; \
+ } \
+ if (rv == 0) \
+ goto done; \
+ } while (0)
+
+/*
+ * Core code for RFC 3779 2.3 path validation.
+ *
+ * Returns 1 for success, 0 on error.
+ *
+ * When returning 0, ctx->error MUST be set to an appropriate value other than
+ * X509_V_OK.
+ */
+static int addr_validate_path_internal(X509_STORE_CTX *ctx,
+ STACK_OF(X509) *chain,
+ IPAddrBlocks *ext)
+{
+ IPAddrBlocks *child = NULL;
+ int i, j, ret = 0, rv;
+ X509 *x;
+
+ if (!ossl_assert(chain != NULL && sk_X509_num(chain) > 0)
+ || !ossl_assert(ctx != NULL || ext != NULL)
+ || !ossl_assert(ctx == NULL || ctx->verify_cb != NULL)) {
+ if (ctx != NULL)
+ ctx->error = X509_V_ERR_UNSPECIFIED;
+ return 0;
+ }
+
+ /*
+ * Figure out where to start. If we don't have an extension to
+ * check, we're done. Otherwise, check canonical form and
+ * set up for walking up the chain.
+ */
+ if (ext != NULL) {
+ i = -1;
+ x = NULL;
+ } else {
+ i = 0;
+ x = sk_X509_value(chain, i);
+ if ((ext = x->rfc3779_addr) == NULL)
+ return 1; /* Return success */
+ }
+ if (!X509v3_addr_is_canonical(ext))
+ validation_err(X509_V_ERR_INVALID_EXTENSION);
+ (void)sk_IPAddressFamily_set_cmp_func(ext, IPAddressFamily_cmp);
+ if ((child = sk_IPAddressFamily_dup(ext)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ if (ctx != NULL)
+ ctx->error = X509_V_ERR_OUT_OF_MEM;
+ goto done;
+ }
+
+ /*
+ * Now walk up the chain. No cert may list resources that its
+ * parent doesn't list.
+ */
+ for (i++; i < sk_X509_num(chain); i++) {
+ x = sk_X509_value(chain, i);
+ if (!X509v3_addr_is_canonical(x->rfc3779_addr))
+ validation_err(X509_V_ERR_INVALID_EXTENSION);
+ if (x->rfc3779_addr == NULL) {
+ for (j = 0; j < sk_IPAddressFamily_num(child); j++) {
+ IPAddressFamily *fc = sk_IPAddressFamily_value(child, j);
+
+ if (!IPAddressFamily_check_len(fc))
+ goto done;
+
+ if (fc->ipAddressChoice->type != IPAddressChoice_inherit) {
+ validation_err(X509_V_ERR_UNNESTED_RESOURCE);
+ break;
+ }
+ }
+ continue;
+ }
+ (void)sk_IPAddressFamily_set_cmp_func(x->rfc3779_addr,
+ IPAddressFamily_cmp);
+ for (j = 0; j < sk_IPAddressFamily_num(child); j++) {
+ IPAddressFamily *fc = sk_IPAddressFamily_value(child, j);
+ int k = sk_IPAddressFamily_find(x->rfc3779_addr, fc);
+ IPAddressFamily *fp =
+ sk_IPAddressFamily_value(x->rfc3779_addr, k);
+
+ if (fp == NULL) {
+ if (fc->ipAddressChoice->type ==
+ IPAddressChoice_addressesOrRanges) {
+ validation_err(X509_V_ERR_UNNESTED_RESOURCE);
+ break;
+ }
+ continue;
+ }
+
+ if (!IPAddressFamily_check_len(fc) || !IPAddressFamily_check_len(fp))
+ goto done;
+
+ if (fp->ipAddressChoice->type ==
+ IPAddressChoice_addressesOrRanges) {
+ if (fc->ipAddressChoice->type == IPAddressChoice_inherit
+ || addr_contains(fp->ipAddressChoice->u.addressesOrRanges,
+ fc->ipAddressChoice->u.addressesOrRanges,
+ length_from_afi(X509v3_addr_get_afi(fc))))
+ (void)sk_IPAddressFamily_set(child, j, fp);
+ else
+ validation_err(X509_V_ERR_UNNESTED_RESOURCE);
+ }
+ }
+ }
+
+ /*
+ * Trust anchor can't inherit.
+ */
+ if (x->rfc3779_addr != NULL) {
+ for (j = 0; j < sk_IPAddressFamily_num(x->rfc3779_addr); j++) {
+ IPAddressFamily *fp = sk_IPAddressFamily_value(x->rfc3779_addr, j);
+
+ if (!IPAddressFamily_check_len(fp))
+ goto done;
+
+ if (fp->ipAddressChoice->type == IPAddressChoice_inherit
+ && sk_IPAddressFamily_find(child, fp) >= 0)
+ validation_err(X509_V_ERR_UNNESTED_RESOURCE);
+ }
+ }
+ ret = 1;
+ done:
+ sk_IPAddressFamily_free(child);
+ return ret;
+}
+
+#undef validation_err
+
+/*
+ * RFC 3779 2.3 path validation -- called from X509_verify_cert().
+ */
+int X509v3_addr_validate_path(X509_STORE_CTX *ctx)
+{
+ if (ctx->chain == NULL
+ || sk_X509_num(ctx->chain) == 0
+ || ctx->verify_cb == NULL) {
+ ctx->error = X509_V_ERR_UNSPECIFIED;
+ return 0;
+ }
+ return addr_validate_path_internal(ctx, ctx->chain, NULL);
+}
+
+/*
+ * RFC 3779 2.3 path validation of an extension.
+ * Test whether chain covers extension.
+ */
+int X509v3_addr_validate_resource_set(STACK_OF(X509) *chain,
+ IPAddrBlocks *ext, int allow_inheritance)
+{
+ if (ext == NULL)
+ return 1;
+ if (chain == NULL || sk_X509_num(chain) == 0)
+ return 0;
+ if (!allow_inheritance && X509v3_addr_inherits(ext))
+ return 0;
+ return addr_validate_path_internal(NULL, chain, ext);
+}
+
+#endif /* OPENSSL_NO_RFC3779 */
diff --git a/crypto/x509/v3_admis.c b/crypto/x509/v3_admis.c
new file mode 100644
index 000000000000..3bce232ed2fe
--- /dev/null
+++ b/crypto/x509/v3_admis.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/types.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+
+#include <openssl/x509v3.h>
+
+#include <openssl/safestack.h>
+
+#include "v3_admis.h"
+#include "ext_dat.h"
+
+ASN1_SEQUENCE(NAMING_AUTHORITY) = {
+ ASN1_OPT(NAMING_AUTHORITY, namingAuthorityId, ASN1_OBJECT),
+ ASN1_OPT(NAMING_AUTHORITY, namingAuthorityUrl, ASN1_IA5STRING),
+ ASN1_OPT(NAMING_AUTHORITY, namingAuthorityText, DIRECTORYSTRING),
+} ASN1_SEQUENCE_END(NAMING_AUTHORITY)
+
+ASN1_SEQUENCE(PROFESSION_INFO) = {
+ ASN1_EXP_OPT(PROFESSION_INFO, namingAuthority, NAMING_AUTHORITY, 0),
+ ASN1_SEQUENCE_OF(PROFESSION_INFO, professionItems, DIRECTORYSTRING),
+ ASN1_SEQUENCE_OF_OPT(PROFESSION_INFO, professionOIDs, ASN1_OBJECT),
+ ASN1_OPT(PROFESSION_INFO, registrationNumber, ASN1_PRINTABLESTRING),
+ ASN1_OPT(PROFESSION_INFO, addProfessionInfo, ASN1_OCTET_STRING),
+} ASN1_SEQUENCE_END(PROFESSION_INFO)
+
+ASN1_SEQUENCE(ADMISSIONS) = {
+ ASN1_EXP_OPT(ADMISSIONS, admissionAuthority, GENERAL_NAME, 0),
+ ASN1_EXP_OPT(ADMISSIONS, namingAuthority, NAMING_AUTHORITY, 1),
+ ASN1_SEQUENCE_OF(ADMISSIONS, professionInfos, PROFESSION_INFO),
+} ASN1_SEQUENCE_END(ADMISSIONS)
+
+ASN1_SEQUENCE(ADMISSION_SYNTAX) = {
+ ASN1_OPT(ADMISSION_SYNTAX, admissionAuthority, GENERAL_NAME),
+ ASN1_SEQUENCE_OF(ADMISSION_SYNTAX, contentsOfAdmissions, ADMISSIONS),
+} ASN1_SEQUENCE_END(ADMISSION_SYNTAX)
+
+IMPLEMENT_ASN1_FUNCTIONS(NAMING_AUTHORITY)
+IMPLEMENT_ASN1_FUNCTIONS(PROFESSION_INFO)
+IMPLEMENT_ASN1_FUNCTIONS(ADMISSIONS)
+IMPLEMENT_ASN1_FUNCTIONS(ADMISSION_SYNTAX)
+
+static int i2r_ADMISSION_SYNTAX(const struct v3_ext_method *method, void *in,
+ BIO *bp, int ind);
+
+const X509V3_EXT_METHOD ossl_v3_ext_admission = {
+ NID_x509ExtAdmission, /* .ext_nid = */
+ 0, /* .ext_flags = */
+ ASN1_ITEM_ref(ADMISSION_SYNTAX), /* .it = */
+ NULL, NULL, NULL, NULL,
+ NULL, /* .i2s = */
+ NULL, /* .s2i = */
+ NULL, /* .i2v = */
+ NULL, /* .v2i = */
+ &i2r_ADMISSION_SYNTAX, /* .i2r = */
+ NULL, /* .r2i = */
+ NULL /* extension-specific data */
+};
+
+
+static int i2r_NAMING_AUTHORITY(const struct v3_ext_method *method, void *in,
+ BIO *bp, int ind)
+{
+ NAMING_AUTHORITY * namingAuthority = (NAMING_AUTHORITY*) in;
+
+ if (namingAuthority == NULL)
+ return 0;
+
+ if (namingAuthority->namingAuthorityId == NULL
+ && namingAuthority->namingAuthorityText == NULL
+ && namingAuthority->namingAuthorityUrl == NULL)
+ return 0;
+
+ if (BIO_printf(bp, "%*snamingAuthority: ", ind, "") <= 0)
+ goto err;
+
+ if (namingAuthority->namingAuthorityId != NULL) {
+ char objbuf[128];
+ const char *ln = OBJ_nid2ln(OBJ_obj2nid(namingAuthority->namingAuthorityId));
+
+ if (BIO_printf(bp, "%*s admissionAuthorityId: ", ind, "") <= 0)
+ goto err;
+
+ OBJ_obj2txt(objbuf, sizeof(objbuf), namingAuthority->namingAuthorityId, 1);
+
+ if (BIO_printf(bp, "%s%s%s%s\n", ln ? ln : "",
+ ln ? " (" : "", objbuf, ln ? ")" : "") <= 0)
+ goto err;
+ }
+ if (namingAuthority->namingAuthorityText != NULL) {
+ if (BIO_printf(bp, "%*s namingAuthorityText: ", ind, "") <= 0
+ || ASN1_STRING_print(bp, namingAuthority->namingAuthorityText) <= 0
+ || BIO_printf(bp, "\n") <= 0)
+ goto err;
+ }
+ if (namingAuthority->namingAuthorityUrl != NULL ) {
+ if (BIO_printf(bp, "%*s namingAuthorityUrl: ", ind, "") <= 0
+ || ASN1_STRING_print(bp, namingAuthority->namingAuthorityUrl) <= 0
+ || BIO_printf(bp, "\n") <= 0)
+ goto err;
+ }
+ return 1;
+
+err:
+ return 0;
+}
+
+static int i2r_ADMISSION_SYNTAX(const struct v3_ext_method *method, void *in,
+ BIO *bp, int ind)
+{
+ ADMISSION_SYNTAX * admission = (ADMISSION_SYNTAX *)in;
+ int i, j, k;
+
+ if (admission->admissionAuthority != NULL) {
+ if (BIO_printf(bp, "%*sadmissionAuthority:\n", ind, "") <= 0
+ || BIO_printf(bp, "%*s ", ind, "") <= 0
+ || GENERAL_NAME_print(bp, admission->admissionAuthority) <= 0
+ || BIO_printf(bp, "\n") <= 0)
+ goto err;
+ }
+
+ for (i = 0; i < sk_ADMISSIONS_num(admission->contentsOfAdmissions); i++) {
+ ADMISSIONS* entry = sk_ADMISSIONS_value(admission->contentsOfAdmissions, i);
+
+ if (BIO_printf(bp, "%*sEntry %0d:\n", ind, "", 1 + i) <= 0) goto err;
+
+ if (entry->admissionAuthority != NULL) {
+ if (BIO_printf(bp, "%*s admissionAuthority:\n", ind, "") <= 0
+ || BIO_printf(bp, "%*s ", ind, "") <= 0
+ || GENERAL_NAME_print(bp, entry->admissionAuthority) <= 0
+ || BIO_printf(bp, "\n") <= 0)
+ goto err;
+ }
+
+ if (entry->namingAuthority != NULL) {
+ if (i2r_NAMING_AUTHORITY(method, entry->namingAuthority, bp, ind) <= 0)
+ goto err;
+ }
+
+ for (j = 0; j < sk_PROFESSION_INFO_num(entry->professionInfos); j++) {
+ PROFESSION_INFO* pinfo = sk_PROFESSION_INFO_value(entry->professionInfos, j);
+
+ if (BIO_printf(bp, "%*s Profession Info Entry %0d:\n", ind, "", 1 + j) <= 0)
+ goto err;
+
+ if (pinfo->registrationNumber != NULL) {
+ if (BIO_printf(bp, "%*s registrationNumber: ", ind, "") <= 0
+ || ASN1_STRING_print(bp, pinfo->registrationNumber) <= 0
+ || BIO_printf(bp, "\n") <= 0)
+ goto err;
+ }
+
+ if (pinfo->namingAuthority != NULL) {
+ if (i2r_NAMING_AUTHORITY(method, pinfo->namingAuthority, bp, ind + 2) <= 0)
+ goto err;
+ }
+
+ if (pinfo->professionItems != NULL) {
+
+ if (BIO_printf(bp, "%*s Info Entries:\n", ind, "") <= 0)
+ goto err;
+ for (k = 0; k < sk_ASN1_STRING_num(pinfo->professionItems); k++) {
+ ASN1_STRING* val = sk_ASN1_STRING_value(pinfo->professionItems, k);
+
+ if (BIO_printf(bp, "%*s ", ind, "") <= 0
+ || ASN1_STRING_print(bp, val) <= 0
+ || BIO_printf(bp, "\n") <= 0)
+ goto err;
+ }
+ }
+
+ if (pinfo->professionOIDs != NULL) {
+ if (BIO_printf(bp, "%*s Profession OIDs:\n", ind, "") <= 0)
+ goto err;
+ for (k = 0; k < sk_ASN1_OBJECT_num(pinfo->professionOIDs); k++) {
+ ASN1_OBJECT* obj = sk_ASN1_OBJECT_value(pinfo->professionOIDs, k);
+ const char *ln = OBJ_nid2ln(OBJ_obj2nid(obj));
+ char objbuf[128];
+
+ OBJ_obj2txt(objbuf, sizeof(objbuf), obj, 1);
+ if (BIO_printf(bp, "%*s %s%s%s%s\n", ind, "",
+ ln ? ln : "", ln ? " (" : "",
+ objbuf, ln ? ")" : "") <= 0)
+ goto err;
+ }
+ }
+ }
+ }
+ return 1;
+
+err:
+ return 0;
+}
+
+const ASN1_OBJECT *NAMING_AUTHORITY_get0_authorityId(const NAMING_AUTHORITY *n)
+{
+ return n->namingAuthorityId;
+}
+
+void NAMING_AUTHORITY_set0_authorityId(NAMING_AUTHORITY *n, ASN1_OBJECT* id)
+{
+ ASN1_OBJECT_free(n->namingAuthorityId);
+ n->namingAuthorityId = id;
+}
+
+const ASN1_IA5STRING *NAMING_AUTHORITY_get0_authorityURL(
+ const NAMING_AUTHORITY *n)
+{
+ return n->namingAuthorityUrl;
+}
+
+void NAMING_AUTHORITY_set0_authorityURL(NAMING_AUTHORITY *n, ASN1_IA5STRING* u)
+{
+ ASN1_IA5STRING_free(n->namingAuthorityUrl);
+ n->namingAuthorityUrl = u;
+}
+
+const ASN1_STRING *NAMING_AUTHORITY_get0_authorityText(
+ const NAMING_AUTHORITY *n)
+{
+ return n->namingAuthorityText;
+}
+
+void NAMING_AUTHORITY_set0_authorityText(NAMING_AUTHORITY *n, ASN1_STRING* t)
+{
+ ASN1_IA5STRING_free(n->namingAuthorityText);
+ n->namingAuthorityText = t;
+}
+
+const GENERAL_NAME *ADMISSION_SYNTAX_get0_admissionAuthority(const ADMISSION_SYNTAX *as)
+{
+ return as->admissionAuthority;
+}
+
+void ADMISSION_SYNTAX_set0_admissionAuthority(ADMISSION_SYNTAX *as,
+ GENERAL_NAME *aa)
+{
+ GENERAL_NAME_free(as->admissionAuthority);
+ as->admissionAuthority = aa;
+}
+
+const STACK_OF(ADMISSIONS) *ADMISSION_SYNTAX_get0_contentsOfAdmissions(const ADMISSION_SYNTAX *as)
+{
+ return as->contentsOfAdmissions;
+}
+
+void ADMISSION_SYNTAX_set0_contentsOfAdmissions(ADMISSION_SYNTAX *as,
+ STACK_OF(ADMISSIONS) *a)
+{
+ sk_ADMISSIONS_pop_free(as->contentsOfAdmissions, ADMISSIONS_free);
+ as->contentsOfAdmissions = a;
+}
+
+const GENERAL_NAME *ADMISSIONS_get0_admissionAuthority(const ADMISSIONS *a)
+{
+ return a->admissionAuthority;
+}
+
+void ADMISSIONS_set0_admissionAuthority(ADMISSIONS *a, GENERAL_NAME *aa)
+{
+ GENERAL_NAME_free(a->admissionAuthority);
+ a->admissionAuthority = aa;
+}
+
+const NAMING_AUTHORITY *ADMISSIONS_get0_namingAuthority(const ADMISSIONS *a)
+{
+ return a->namingAuthority;
+}
+
+void ADMISSIONS_set0_namingAuthority(ADMISSIONS *a, NAMING_AUTHORITY *na)
+{
+ NAMING_AUTHORITY_free(a->namingAuthority);
+ a->namingAuthority = na;
+}
+
+const PROFESSION_INFOS *ADMISSIONS_get0_professionInfos(const ADMISSIONS *a)
+{
+ return a->professionInfos;
+}
+
+void ADMISSIONS_set0_professionInfos(ADMISSIONS *a, PROFESSION_INFOS *pi)
+{
+ sk_PROFESSION_INFO_pop_free(a->professionInfos, PROFESSION_INFO_free);
+ a->professionInfos = pi;
+}
+
+const ASN1_OCTET_STRING *PROFESSION_INFO_get0_addProfessionInfo(const PROFESSION_INFO *pi)
+{
+ return pi->addProfessionInfo;
+}
+
+void PROFESSION_INFO_set0_addProfessionInfo(PROFESSION_INFO *pi,
+ ASN1_OCTET_STRING *aos)
+{
+ ASN1_OCTET_STRING_free(pi->addProfessionInfo);
+ pi->addProfessionInfo = aos;
+}
+
+const NAMING_AUTHORITY *PROFESSION_INFO_get0_namingAuthority(const PROFESSION_INFO *pi)
+{
+ return pi->namingAuthority;
+}
+
+void PROFESSION_INFO_set0_namingAuthority(PROFESSION_INFO *pi,
+ NAMING_AUTHORITY *na)
+{
+ NAMING_AUTHORITY_free(pi->namingAuthority);
+ pi->namingAuthority = na;
+}
+
+const STACK_OF(ASN1_STRING) *PROFESSION_INFO_get0_professionItems(const PROFESSION_INFO *pi)
+{
+ return pi->professionItems;
+}
+
+void PROFESSION_INFO_set0_professionItems(PROFESSION_INFO *pi,
+ STACK_OF(ASN1_STRING) *as)
+{
+ sk_ASN1_STRING_pop_free(pi->professionItems, ASN1_STRING_free);
+ pi->professionItems = as;
+}
+
+const STACK_OF(ASN1_OBJECT) *PROFESSION_INFO_get0_professionOIDs(const PROFESSION_INFO *pi)
+{
+ return pi->professionOIDs;
+}
+
+void PROFESSION_INFO_set0_professionOIDs(PROFESSION_INFO *pi,
+ STACK_OF(ASN1_OBJECT) *po)
+{
+ sk_ASN1_OBJECT_pop_free(pi->professionOIDs, ASN1_OBJECT_free);
+ pi->professionOIDs = po;
+}
+
+const ASN1_PRINTABLESTRING *PROFESSION_INFO_get0_registrationNumber(const PROFESSION_INFO *pi)
+{
+ return pi->registrationNumber;
+}
+
+void PROFESSION_INFO_set0_registrationNumber(PROFESSION_INFO *pi,
+ ASN1_PRINTABLESTRING *rn)
+{
+ ASN1_PRINTABLESTRING_free(pi->registrationNumber);
+ pi->registrationNumber = rn;
+}
diff --git a/crypto/x509/v3_admis.h b/crypto/x509/v3_admis.h
new file mode 100644
index 000000000000..1e82c0f4a33f
--- /dev/null
+++ b/crypto/x509/v3_admis.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_X509_V3_ADMIS_H
+# define OSSL_CRYPTO_X509_V3_ADMIS_H
+
+struct NamingAuthority_st {
+ ASN1_OBJECT* namingAuthorityId;
+ ASN1_IA5STRING* namingAuthorityUrl;
+ ASN1_STRING* namingAuthorityText; /* i.e. DIRECTORYSTRING */
+};
+
+struct ProfessionInfo_st {
+ NAMING_AUTHORITY* namingAuthority;
+ STACK_OF(ASN1_STRING)* professionItems; /* i.e. DIRECTORYSTRING */
+ STACK_OF(ASN1_OBJECT)* professionOIDs;
+ ASN1_PRINTABLESTRING* registrationNumber;
+ ASN1_OCTET_STRING* addProfessionInfo;
+};
+
+struct Admissions_st {
+ GENERAL_NAME* admissionAuthority;
+ NAMING_AUTHORITY* namingAuthority;
+ STACK_OF(PROFESSION_INFO)* professionInfos;
+};
+
+struct AdmissionSyntax_st {
+ GENERAL_NAME* admissionAuthority;
+ STACK_OF(ADMISSIONS)* contentsOfAdmissions;
+};
+
+#endif
diff --git a/crypto/x509/v3_akeya.c b/crypto/x509/v3_akeya.c
new file mode 100644
index 000000000000..aae8c21e73c2
--- /dev/null
+++ b/crypto/x509/v3_akeya.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509v3.h>
+
+ASN1_SEQUENCE(AUTHORITY_KEYID) = {
+ ASN1_IMP_OPT(AUTHORITY_KEYID, keyid, ASN1_OCTET_STRING, 0),
+ ASN1_IMP_SEQUENCE_OF_OPT(AUTHORITY_KEYID, issuer, GENERAL_NAME, 1),
+ ASN1_IMP_OPT(AUTHORITY_KEYID, serial, ASN1_INTEGER, 2)
+} ASN1_SEQUENCE_END(AUTHORITY_KEYID)
+
+IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_KEYID)
diff --git a/crypto/x509/v3_akid.c b/crypto/x509/v3_akid.c
new file mode 100644
index 000000000000..43b515f50c49
--- /dev/null
+++ b/crypto/x509/v3_akid.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509v3.h>
+#include "crypto/x509.h"
+#include "ext_dat.h"
+
+static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
+ AUTHORITY_KEYID *akeyid,
+ STACK_OF(CONF_VALUE)
+ *extlist);
+static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *values);
+
+const X509V3_EXT_METHOD ossl_v3_akey_id = {
+ NID_authority_key_identifier,
+ X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_KEYID),
+ 0, 0, 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2V) i2v_AUTHORITY_KEYID,
+ (X509V3_EXT_V2I)v2i_AUTHORITY_KEYID,
+ 0, 0,
+ NULL
+};
+
+static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
+ AUTHORITY_KEYID *akeyid,
+ STACK_OF(CONF_VALUE)
+ *extlist)
+{
+ char *tmp = NULL;
+ STACK_OF(CONF_VALUE) *origextlist = extlist, *tmpextlist;
+
+ if (akeyid->keyid) {
+ tmp = OPENSSL_buf2hexstr(akeyid->keyid->data, akeyid->keyid->length);
+ if (tmp == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ if (!X509V3_add_value((akeyid->issuer || akeyid->serial) ? "keyid" : NULL,
+ tmp, &extlist)) {
+ OPENSSL_free(tmp);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_X509_LIB);
+ goto err;
+ }
+ OPENSSL_free(tmp);
+ }
+ if (akeyid->issuer) {
+ tmpextlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist);
+ if (tmpextlist == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_X509_LIB);
+ goto err;
+ }
+ extlist = tmpextlist;
+ }
+ if (akeyid->serial) {
+ tmp = OPENSSL_buf2hexstr(akeyid->serial->data, akeyid->serial->length);
+ if (tmp == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!X509V3_add_value("serial", tmp, &extlist)) {
+ OPENSSL_free(tmp);
+ goto err;
+ }
+ OPENSSL_free(tmp);
+ }
+ return extlist;
+ err:
+ if (origextlist == NULL)
+ sk_CONF_VALUE_pop_free(extlist, X509V3_conf_free);
+ return NULL;
+}
+
+/*-
+ * Currently two options:
+ * keyid: use the issuers subject keyid, the value 'always' means its is
+ * an error if the issuer certificate doesn't have a key id.
+ * issuer: use the issuers cert issuer and serial number. The default is
+ * to only use this if keyid is not present. With the option 'always'
+ * this is always included.
+ */
+
+static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *values)
+{
+ char keyid = 0, issuer = 0;
+ int i, n = sk_CONF_VALUE_num(values);
+ CONF_VALUE *cnf;
+ ASN1_OCTET_STRING *ikeyid = NULL;
+ X509_NAME *isname = NULL;
+ GENERAL_NAMES *gens = NULL;
+ GENERAL_NAME *gen = NULL;
+ ASN1_INTEGER *serial = NULL;
+ X509_EXTENSION *ext;
+ X509 *issuer_cert;
+ int same_issuer, ss;
+ AUTHORITY_KEYID *akeyid = AUTHORITY_KEYID_new();
+
+ if (akeyid == NULL)
+ goto err;
+
+ if (n == 1 && strcmp(sk_CONF_VALUE_value(values, 0)->name, "none") == 0) {
+ return akeyid;
+ }
+
+ for (i = 0; i < n; i++) {
+ cnf = sk_CONF_VALUE_value(values, i);
+ if (strcmp(cnf->name, "keyid") == 0) {
+ keyid = 1;
+ if (cnf->value && strcmp(cnf->value, "always") == 0)
+ keyid = 2;
+ } else if (strcmp(cnf->name, "issuer") == 0) {
+ issuer = 1;
+ if (cnf->value && strcmp(cnf->value, "always") == 0)
+ issuer = 2;
+ } else {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_UNKNOWN_OPTION,
+ "name=%s", cnf->name);
+ goto err;
+ }
+ }
+
+ if (ctx != NULL && (ctx->flags & X509V3_CTX_TEST) != 0)
+ return akeyid;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_NULL_PARAMETER);
+ goto err;
+ }
+ if ((issuer_cert = ctx->issuer_cert) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_ISSUER_CERTIFICATE);
+ goto err;
+ }
+ same_issuer = ctx->subject_cert == ctx->issuer_cert;
+ ERR_set_mark();
+ if (ctx->issuer_pkey != NULL)
+ ss = X509_check_private_key(ctx->subject_cert, ctx->issuer_pkey);
+ else
+ ss = same_issuer;
+ ERR_pop_to_mark();
+
+ /* unless forced with "always", AKID is suppressed for self-signed certs */
+ if (keyid == 2 || (keyid == 1 && !ss)) {
+ /*
+ * prefer any pre-existing subject key identifier of the issuer cert
+ * except issuer cert is same as subject cert and is not self-signed
+ */
+ i = X509_get_ext_by_NID(issuer_cert, NID_subject_key_identifier, -1);
+ if (i >= 0 && (ext = X509_get_ext(issuer_cert, i)) != NULL
+ && !(same_issuer && !ss))
+ ikeyid = X509V3_EXT_d2i(ext);
+ if (ikeyid == NULL && same_issuer && ctx->issuer_pkey != NULL) {
+ /* generate fallback AKID, emulating s2i_skey_id(..., "hash") */
+ X509_PUBKEY *pubkey = NULL;
+
+ if (X509_PUBKEY_set(&pubkey, ctx->issuer_pkey))
+ ikeyid = ossl_x509_pubkey_hash(pubkey);
+ X509_PUBKEY_free(pubkey);
+ }
+ if ((keyid == 2 || issuer == 0)
+ && (ikeyid == NULL
+ || ASN1_STRING_length(ikeyid) <= 2) /* indicating "none" */) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID);
+ goto err;
+ }
+ }
+
+ if (issuer == 2 || (issuer == 1 && ikeyid == NULL)) {
+ isname = X509_NAME_dup(X509_get_issuer_name(issuer_cert));
+ serial = ASN1_INTEGER_dup(X509_get0_serialNumber(issuer_cert));
+ if (isname == NULL || serial == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS);
+ goto err;
+ }
+ }
+
+ if (isname != NULL) {
+ if ((gens = sk_GENERAL_NAME_new_null()) == NULL
+ || (gen = GENERAL_NAME_new()) == NULL
+ || !sk_GENERAL_NAME_push(gens, gen)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ gen->type = GEN_DIRNAME;
+ gen->d.dirn = isname;
+ }
+
+ akeyid->issuer = gens;
+ gen = NULL;
+ gens = NULL;
+ akeyid->serial = serial;
+ akeyid->keyid = ikeyid;
+
+ return akeyid;
+
+ err:
+ sk_GENERAL_NAME_free(gens);
+ GENERAL_NAME_free(gen);
+ X509_NAME_free(isname);
+ ASN1_INTEGER_free(serial);
+ ASN1_OCTET_STRING_free(ikeyid);
+ AUTHORITY_KEYID_free(akeyid);
+ return NULL;
+}
diff --git a/crypto/x509/v3_asid.c b/crypto/x509/v3_asid.c
new file mode 100644
index 000000000000..86577d6ca48c
--- /dev/null
+++ b/crypto/x509/v3_asid.c
@@ -0,0 +1,896 @@
+/*
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Implementation of RFC 3779 section 3.2.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "internal/cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509v3.h>
+#include <openssl/x509.h>
+#include "crypto/x509.h"
+#include <openssl/bn.h>
+#include "ext_dat.h"
+#include "x509_local.h"
+
+#ifndef OPENSSL_NO_RFC3779
+
+/*
+ * OpenSSL ASN.1 template translation of RFC 3779 3.2.3.
+ */
+
+ASN1_SEQUENCE(ASRange) = {
+ ASN1_SIMPLE(ASRange, min, ASN1_INTEGER),
+ ASN1_SIMPLE(ASRange, max, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(ASRange)
+
+ASN1_CHOICE(ASIdOrRange) = {
+ ASN1_SIMPLE(ASIdOrRange, u.id, ASN1_INTEGER),
+ ASN1_SIMPLE(ASIdOrRange, u.range, ASRange)
+} ASN1_CHOICE_END(ASIdOrRange)
+
+ASN1_CHOICE(ASIdentifierChoice) = {
+ ASN1_SIMPLE(ASIdentifierChoice, u.inherit, ASN1_NULL),
+ ASN1_SEQUENCE_OF(ASIdentifierChoice, u.asIdsOrRanges, ASIdOrRange)
+} ASN1_CHOICE_END(ASIdentifierChoice)
+
+ASN1_SEQUENCE(ASIdentifiers) = {
+ ASN1_EXP_OPT(ASIdentifiers, asnum, ASIdentifierChoice, 0),
+ ASN1_EXP_OPT(ASIdentifiers, rdi, ASIdentifierChoice, 1)
+} ASN1_SEQUENCE_END(ASIdentifiers)
+
+IMPLEMENT_ASN1_FUNCTIONS(ASRange)
+IMPLEMENT_ASN1_FUNCTIONS(ASIdOrRange)
+IMPLEMENT_ASN1_FUNCTIONS(ASIdentifierChoice)
+IMPLEMENT_ASN1_FUNCTIONS(ASIdentifiers)
+
+/*
+ * i2r method for an ASIdentifierChoice.
+ */
+static int i2r_ASIdentifierChoice(BIO *out,
+ ASIdentifierChoice *choice,
+ int indent, const char *msg)
+{
+ int i;
+ char *s;
+ if (choice == NULL)
+ return 1;
+ BIO_printf(out, "%*s%s:\n", indent, "", msg);
+ switch (choice->type) {
+ case ASIdentifierChoice_inherit:
+ BIO_printf(out, "%*sinherit\n", indent + 2, "");
+ break;
+ case ASIdentifierChoice_asIdsOrRanges:
+ for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges); i++) {
+ ASIdOrRange *aor =
+ sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
+ switch (aor->type) {
+ case ASIdOrRange_id:
+ if ((s = i2s_ASN1_INTEGER(NULL, aor->u.id)) == NULL)
+ return 0;
+ BIO_printf(out, "%*s%s\n", indent + 2, "", s);
+ OPENSSL_free(s);
+ break;
+ case ASIdOrRange_range:
+ if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->min)) == NULL)
+ return 0;
+ BIO_printf(out, "%*s%s-", indent + 2, "", s);
+ OPENSSL_free(s);
+ if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->max)) == NULL)
+ return 0;
+ BIO_printf(out, "%s\n", s);
+ OPENSSL_free(s);
+ break;
+ default:
+ return 0;
+ }
+ }
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * i2r method for an ASIdentifier extension.
+ */
+static int i2r_ASIdentifiers(const X509V3_EXT_METHOD *method,
+ void *ext, BIO *out, int indent)
+{
+ ASIdentifiers *asid = ext;
+ return (i2r_ASIdentifierChoice(out, asid->asnum, indent,
+ "Autonomous System Numbers") &&
+ i2r_ASIdentifierChoice(out, asid->rdi, indent,
+ "Routing Domain Identifiers"));
+}
+
+/*
+ * Sort comparison function for a sequence of ASIdOrRange elements.
+ */
+static int ASIdOrRange_cmp(const ASIdOrRange *const *a_,
+ const ASIdOrRange *const *b_)
+{
+ const ASIdOrRange *a = *a_, *b = *b_;
+
+ assert((a->type == ASIdOrRange_id && a->u.id != NULL) ||
+ (a->type == ASIdOrRange_range && a->u.range != NULL &&
+ a->u.range->min != NULL && a->u.range->max != NULL));
+
+ assert((b->type == ASIdOrRange_id && b->u.id != NULL) ||
+ (b->type == ASIdOrRange_range && b->u.range != NULL &&
+ b->u.range->min != NULL && b->u.range->max != NULL));
+
+ if (a->type == ASIdOrRange_id && b->type == ASIdOrRange_id)
+ return ASN1_INTEGER_cmp(a->u.id, b->u.id);
+
+ if (a->type == ASIdOrRange_range && b->type == ASIdOrRange_range) {
+ int r = ASN1_INTEGER_cmp(a->u.range->min, b->u.range->min);
+ return r != 0 ? r : ASN1_INTEGER_cmp(a->u.range->max,
+ b->u.range->max);
+ }
+
+ if (a->type == ASIdOrRange_id)
+ return ASN1_INTEGER_cmp(a->u.id, b->u.range->min);
+ else
+ return ASN1_INTEGER_cmp(a->u.range->min, b->u.id);
+}
+
+/*
+ * Add an inherit element.
+ */
+int X509v3_asid_add_inherit(ASIdentifiers *asid, int which)
+{
+ ASIdentifierChoice **choice;
+ if (asid == NULL)
+ return 0;
+ switch (which) {
+ case V3_ASID_ASNUM:
+ choice = &asid->asnum;
+ break;
+ case V3_ASID_RDI:
+ choice = &asid->rdi;
+ break;
+ default:
+ return 0;
+ }
+ if (*choice == NULL) {
+ if ((*choice = ASIdentifierChoice_new()) == NULL)
+ return 0;
+ if (((*choice)->u.inherit = ASN1_NULL_new()) == NULL)
+ return 0;
+ (*choice)->type = ASIdentifierChoice_inherit;
+ }
+ return (*choice)->type == ASIdentifierChoice_inherit;
+}
+
+/*
+ * Add an ID or range to an ASIdentifierChoice.
+ */
+int X509v3_asid_add_id_or_range(ASIdentifiers *asid,
+ int which, ASN1_INTEGER *min, ASN1_INTEGER *max)
+{
+ ASIdentifierChoice **choice;
+ ASIdOrRange *aor;
+ if (asid == NULL)
+ return 0;
+ switch (which) {
+ case V3_ASID_ASNUM:
+ choice = &asid->asnum;
+ break;
+ case V3_ASID_RDI:
+ choice = &asid->rdi;
+ break;
+ default:
+ return 0;
+ }
+ if (*choice != NULL && (*choice)->type == ASIdentifierChoice_inherit)
+ return 0;
+ if (*choice == NULL) {
+ if ((*choice = ASIdentifierChoice_new()) == NULL)
+ return 0;
+ (*choice)->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp);
+ if ((*choice)->u.asIdsOrRanges == NULL)
+ return 0;
+ (*choice)->type = ASIdentifierChoice_asIdsOrRanges;
+ }
+ if ((aor = ASIdOrRange_new()) == NULL)
+ return 0;
+ if (max == NULL) {
+ aor->type = ASIdOrRange_id;
+ aor->u.id = min;
+ } else {
+ aor->type = ASIdOrRange_range;
+ if ((aor->u.range = ASRange_new()) == NULL)
+ goto err;
+ ASN1_INTEGER_free(aor->u.range->min);
+ aor->u.range->min = min;
+ ASN1_INTEGER_free(aor->u.range->max);
+ aor->u.range->max = max;
+ }
+ if (!(sk_ASIdOrRange_push((*choice)->u.asIdsOrRanges, aor)))
+ goto err;
+ return 1;
+
+ err:
+ ASIdOrRange_free(aor);
+ return 0;
+}
+
+/*
+ * Extract min and max values from an ASIdOrRange.
+ */
+static int extract_min_max(ASIdOrRange *aor,
+ ASN1_INTEGER **min, ASN1_INTEGER **max)
+{
+ if (!ossl_assert(aor != NULL))
+ return 0;
+ switch (aor->type) {
+ case ASIdOrRange_id:
+ *min = aor->u.id;
+ *max = aor->u.id;
+ return 1;
+ case ASIdOrRange_range:
+ *min = aor->u.range->min;
+ *max = aor->u.range->max;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Check whether an ASIdentifierChoice is in canonical form.
+ */
+static int ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice)
+{
+ ASN1_INTEGER *a_max_plus_one = NULL;
+ ASN1_INTEGER *orig;
+ BIGNUM *bn = NULL;
+ int i, ret = 0;
+
+ /*
+ * Empty element or inheritance is canonical.
+ */
+ if (choice == NULL || choice->type == ASIdentifierChoice_inherit)
+ return 1;
+
+ /*
+ * If not a list, or if empty list, it's broken.
+ */
+ if (choice->type != ASIdentifierChoice_asIdsOrRanges ||
+ sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0)
+ return 0;
+
+ /*
+ * It's a list, check it.
+ */
+ for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) {
+ ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
+ ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1);
+ ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max =
+ NULL;
+
+ if (!extract_min_max(a, &a_min, &a_max)
+ || !extract_min_max(b, &b_min, &b_max))
+ goto done;
+
+ /*
+ * Punt misordered list, overlapping start, or inverted range.
+ */
+ if (ASN1_INTEGER_cmp(a_min, b_min) >= 0 ||
+ ASN1_INTEGER_cmp(a_min, a_max) > 0 ||
+ ASN1_INTEGER_cmp(b_min, b_max) > 0)
+ goto done;
+
+ /*
+ * Calculate a_max + 1 to check for adjacency.
+ */
+ if ((bn == NULL && (bn = BN_new()) == NULL) ||
+ ASN1_INTEGER_to_BN(a_max, bn) == NULL ||
+ !BN_add_word(bn, 1)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto done;
+ }
+
+ if ((a_max_plus_one =
+ BN_to_ASN1_INTEGER(bn, orig = a_max_plus_one)) == NULL) {
+ a_max_plus_one = orig;
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto done;
+ }
+
+ /*
+ * Punt if adjacent or overlapping.
+ */
+ if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) >= 0)
+ goto done;
+ }
+
+ /*
+ * Check for inverted range.
+ */
+ i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1;
+ {
+ ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
+ ASN1_INTEGER *a_min, *a_max;
+ if (a != NULL && a->type == ASIdOrRange_range) {
+ if (!extract_min_max(a, &a_min, &a_max)
+ || ASN1_INTEGER_cmp(a_min, a_max) > 0)
+ goto done;
+ }
+ }
+
+ ret = 1;
+
+ done:
+ ASN1_INTEGER_free(a_max_plus_one);
+ BN_free(bn);
+ return ret;
+}
+
+/*
+ * Check whether an ASIdentifier extension is in canonical form.
+ */
+int X509v3_asid_is_canonical(ASIdentifiers *asid)
+{
+ return (asid == NULL ||
+ (ASIdentifierChoice_is_canonical(asid->asnum) &&
+ ASIdentifierChoice_is_canonical(asid->rdi)));
+}
+
+/*
+ * Whack an ASIdentifierChoice into canonical form.
+ */
+static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice)
+{
+ ASN1_INTEGER *a_max_plus_one = NULL;
+ ASN1_INTEGER *orig;
+ BIGNUM *bn = NULL;
+ int i, ret = 0;
+
+ /*
+ * Nothing to do for empty element or inheritance.
+ */
+ if (choice == NULL || choice->type == ASIdentifierChoice_inherit)
+ return 1;
+
+ /*
+ * If not a list, or if empty list, it's broken.
+ */
+ if (choice->type != ASIdentifierChoice_asIdsOrRanges ||
+ sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
+ return 0;
+ }
+
+ /*
+ * We have a non-empty list. Sort it.
+ */
+ sk_ASIdOrRange_sort(choice->u.asIdsOrRanges);
+
+ /*
+ * Now check for errors and suboptimal encoding, rejecting the
+ * former and fixing the latter.
+ */
+ for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) {
+ ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
+ ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1);
+ ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max =
+ NULL;
+
+ if (!extract_min_max(a, &a_min, &a_max)
+ || !extract_min_max(b, &b_min, &b_max))
+ goto done;
+
+ /*
+ * Make sure we're properly sorted (paranoia).
+ */
+ if (!ossl_assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0))
+ goto done;
+
+ /*
+ * Punt inverted ranges.
+ */
+ if (ASN1_INTEGER_cmp(a_min, a_max) > 0 ||
+ ASN1_INTEGER_cmp(b_min, b_max) > 0)
+ goto done;
+
+ /*
+ * Check for overlaps.
+ */
+ if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
+ goto done;
+ }
+
+ /*
+ * Calculate a_max + 1 to check for adjacency.
+ */
+ if ((bn == NULL && (bn = BN_new()) == NULL) ||
+ ASN1_INTEGER_to_BN(a_max, bn) == NULL ||
+ !BN_add_word(bn, 1)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto done;
+ }
+
+ if ((a_max_plus_one =
+ BN_to_ASN1_INTEGER(bn, orig = a_max_plus_one)) == NULL) {
+ a_max_plus_one = orig;
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto done;
+ }
+
+ /*
+ * If a and b are adjacent, merge them.
+ */
+ if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) {
+ ASRange *r;
+ switch (a->type) {
+ case ASIdOrRange_id:
+ if ((r = OPENSSL_malloc(sizeof(*r))) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto done;
+ }
+ r->min = a_min;
+ r->max = b_max;
+ a->type = ASIdOrRange_range;
+ a->u.range = r;
+ break;
+ case ASIdOrRange_range:
+ ASN1_INTEGER_free(a->u.range->max);
+ a->u.range->max = b_max;
+ break;
+ }
+ switch (b->type) {
+ case ASIdOrRange_id:
+ b->u.id = NULL;
+ break;
+ case ASIdOrRange_range:
+ b->u.range->max = NULL;
+ break;
+ }
+ ASIdOrRange_free(b);
+ (void)sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1);
+ i--;
+ continue;
+ }
+ }
+
+ /*
+ * Check for final inverted range.
+ */
+ i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1;
+ {
+ ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
+ ASN1_INTEGER *a_min, *a_max;
+ if (a != NULL && a->type == ASIdOrRange_range) {
+ if (!extract_min_max(a, &a_min, &a_max)
+ || ASN1_INTEGER_cmp(a_min, a_max) > 0)
+ goto done;
+ }
+ }
+
+ /* Paranoia */
+ if (!ossl_assert(ASIdentifierChoice_is_canonical(choice)))
+ goto done;
+
+ ret = 1;
+
+ done:
+ ASN1_INTEGER_free(a_max_plus_one);
+ BN_free(bn);
+ return ret;
+}
+
+/*
+ * Whack an ASIdentifier extension into canonical form.
+ */
+int X509v3_asid_canonize(ASIdentifiers *asid)
+{
+ return (asid == NULL ||
+ (ASIdentifierChoice_canonize(asid->asnum) &&
+ ASIdentifierChoice_canonize(asid->rdi)));
+}
+
+/*
+ * v2i method for an ASIdentifier extension.
+ */
+static void *v2i_ASIdentifiers(const struct v3_ext_method *method,
+ struct v3_ext_ctx *ctx,
+ STACK_OF(CONF_VALUE) *values)
+{
+ ASN1_INTEGER *min = NULL, *max = NULL;
+ ASIdentifiers *asid = NULL;
+ int i;
+
+ if ((asid = ASIdentifiers_new()) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
+ CONF_VALUE *val = sk_CONF_VALUE_value(values, i);
+ int i1 = 0, i2 = 0, i3 = 0, is_range = 0, which = 0;
+
+ /*
+ * Figure out whether this is an AS or an RDI.
+ */
+ if (!ossl_v3_name_cmp(val->name, "AS")) {
+ which = V3_ASID_ASNUM;
+ } else if (!ossl_v3_name_cmp(val->name, "RDI")) {
+ which = V3_ASID_RDI;
+ } else {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_NAME_ERROR);
+ X509V3_conf_add_error_name_value(val);
+ goto err;
+ }
+
+ /*
+ * Handle inheritance.
+ */
+ if (strcmp(val->value, "inherit") == 0) {
+ if (X509v3_asid_add_inherit(asid, which))
+ continue;
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_INHERITANCE);
+ X509V3_conf_add_error_name_value(val);
+ goto err;
+ }
+
+ /*
+ * Number, range, or mistake, pick it apart and figure out which.
+ */
+ i1 = strspn(val->value, "0123456789");
+ if (val->value[i1] == '\0') {
+ is_range = 0;
+ } else {
+ is_range = 1;
+ i2 = i1 + strspn(val->value + i1, " \t");
+ if (val->value[i2] != '-') {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_ASNUMBER);
+ X509V3_conf_add_error_name_value(val);
+ goto err;
+ }
+ i2++;
+ i2 = i2 + strspn(val->value + i2, " \t");
+ i3 = i2 + strspn(val->value + i2, "0123456789");
+ if (val->value[i3] != '\0') {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_ASRANGE);
+ X509V3_conf_add_error_name_value(val);
+ goto err;
+ }
+ }
+
+ /*
+ * Syntax is ok, read and add it.
+ */
+ if (!is_range) {
+ if (!X509V3_get_value_int(val, &min)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ } else {
+ char *s = OPENSSL_strdup(val->value);
+ if (s == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ s[i1] = '\0';
+ min = s2i_ASN1_INTEGER(NULL, s);
+ max = s2i_ASN1_INTEGER(NULL, s + i2);
+ OPENSSL_free(s);
+ if (min == NULL || max == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (ASN1_INTEGER_cmp(min, max) > 0) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
+ goto err;
+ }
+ }
+ if (!X509v3_asid_add_id_or_range(asid, which, min, max)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ min = max = NULL;
+ }
+
+ /*
+ * Canonize the result, then we're done.
+ */
+ if (!X509v3_asid_canonize(asid))
+ goto err;
+ return asid;
+
+ err:
+ ASIdentifiers_free(asid);
+ ASN1_INTEGER_free(min);
+ ASN1_INTEGER_free(max);
+ return NULL;
+}
+
+/*
+ * OpenSSL dispatch.
+ */
+const X509V3_EXT_METHOD ossl_v3_asid = {
+ NID_sbgp_autonomousSysNum, /* nid */
+ 0, /* flags */
+ ASN1_ITEM_ref(ASIdentifiers), /* template */
+ 0, 0, 0, 0, /* old functions, ignored */
+ 0, /* i2s */
+ 0, /* s2i */
+ 0, /* i2v */
+ v2i_ASIdentifiers, /* v2i */
+ i2r_ASIdentifiers, /* i2r */
+ 0, /* r2i */
+ NULL /* extension-specific data */
+};
+
+/*
+ * Figure out whether extension uses inheritance.
+ */
+int X509v3_asid_inherits(ASIdentifiers *asid)
+{
+ return (asid != NULL &&
+ ((asid->asnum != NULL &&
+ asid->asnum->type == ASIdentifierChoice_inherit) ||
+ (asid->rdi != NULL &&
+ asid->rdi->type == ASIdentifierChoice_inherit)));
+}
+
+/*
+ * Figure out whether parent contains child.
+ */
+static int asid_contains(ASIdOrRanges *parent, ASIdOrRanges *child)
+{
+ ASN1_INTEGER *p_min = NULL, *p_max = NULL, *c_min = NULL, *c_max = NULL;
+ int p, c;
+
+ if (child == NULL || parent == child)
+ return 1;
+ if (parent == NULL)
+ return 0;
+
+ p = 0;
+ for (c = 0; c < sk_ASIdOrRange_num(child); c++) {
+ if (!extract_min_max(sk_ASIdOrRange_value(child, c), &c_min, &c_max))
+ return 0;
+ for (;; p++) {
+ if (p >= sk_ASIdOrRange_num(parent))
+ return 0;
+ if (!extract_min_max(sk_ASIdOrRange_value(parent, p), &p_min,
+ &p_max))
+ return 0;
+ if (ASN1_INTEGER_cmp(p_max, c_max) < 0)
+ continue;
+ if (ASN1_INTEGER_cmp(p_min, c_min) > 0)
+ return 0;
+ break;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * Test whether a is a subset of b.
+ */
+int X509v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b)
+{
+ int subset;
+
+ if (a == NULL || a == b)
+ return 1;
+
+ if (b == NULL)
+ return 0;
+
+ if (X509v3_asid_inherits(a) || X509v3_asid_inherits(b))
+ return 0;
+
+ subset = a->asnum == NULL
+ || (b->asnum != NULL
+ && asid_contains(b->asnum->u.asIdsOrRanges,
+ a->asnum->u.asIdsOrRanges));
+ if (!subset)
+ return 0;
+
+ return a->rdi == NULL
+ || (b->rdi != NULL
+ && asid_contains(b->rdi->u.asIdsOrRanges,
+ a->rdi->u.asIdsOrRanges));
+}
+
+/*
+ * Validation error handling via callback.
+ */
+#define validation_err(_err_) \
+ do { \
+ if (ctx != NULL) { \
+ ctx->error = _err_; \
+ ctx->error_depth = i; \
+ ctx->current_cert = x; \
+ ret = ctx->verify_cb(0, ctx); \
+ } else { \
+ ret = 0; \
+ } \
+ if (!ret) \
+ goto done; \
+ } while (0)
+
+/*
+ * Core code for RFC 3779 3.3 path validation.
+ */
+static int asid_validate_path_internal(X509_STORE_CTX *ctx,
+ STACK_OF(X509) *chain,
+ ASIdentifiers *ext)
+{
+ ASIdOrRanges *child_as = NULL, *child_rdi = NULL;
+ int i, ret = 1, inherit_as = 0, inherit_rdi = 0;
+ X509 *x;
+
+ if (!ossl_assert(chain != NULL && sk_X509_num(chain) > 0)
+ || !ossl_assert(ctx != NULL || ext != NULL)
+ || !ossl_assert(ctx == NULL || ctx->verify_cb != NULL)) {
+ if (ctx != NULL)
+ ctx->error = X509_V_ERR_UNSPECIFIED;
+ return 0;
+ }
+
+
+ /*
+ * Figure out where to start. If we don't have an extension to
+ * check, we're done. Otherwise, check canonical form and
+ * set up for walking up the chain.
+ */
+ if (ext != NULL) {
+ i = -1;
+ x = NULL;
+ } else {
+ i = 0;
+ x = sk_X509_value(chain, i);
+ if ((ext = x->rfc3779_asid) == NULL)
+ goto done;
+ }
+ if (!X509v3_asid_is_canonical(ext))
+ validation_err(X509_V_ERR_INVALID_EXTENSION);
+ if (ext->asnum != NULL) {
+ switch (ext->asnum->type) {
+ case ASIdentifierChoice_inherit:
+ inherit_as = 1;
+ break;
+ case ASIdentifierChoice_asIdsOrRanges:
+ child_as = ext->asnum->u.asIdsOrRanges;
+ break;
+ }
+ }
+ if (ext->rdi != NULL) {
+ switch (ext->rdi->type) {
+ case ASIdentifierChoice_inherit:
+ inherit_rdi = 1;
+ break;
+ case ASIdentifierChoice_asIdsOrRanges:
+ child_rdi = ext->rdi->u.asIdsOrRanges;
+ break;
+ }
+ }
+
+ /*
+ * Now walk up the chain. Extensions must be in canonical form, no
+ * cert may list resources that its parent doesn't list.
+ */
+ for (i++; i < sk_X509_num(chain); i++) {
+ x = sk_X509_value(chain, i);
+ if (!ossl_assert(x != NULL)) {
+ if (ctx != NULL)
+ ctx->error = X509_V_ERR_UNSPECIFIED;
+ return 0;
+ }
+ if (x->rfc3779_asid == NULL) {
+ if (child_as != NULL || child_rdi != NULL)
+ validation_err(X509_V_ERR_UNNESTED_RESOURCE);
+ continue;
+ }
+ if (!X509v3_asid_is_canonical(x->rfc3779_asid))
+ validation_err(X509_V_ERR_INVALID_EXTENSION);
+ if (x->rfc3779_asid->asnum == NULL && child_as != NULL) {
+ validation_err(X509_V_ERR_UNNESTED_RESOURCE);
+ child_as = NULL;
+ inherit_as = 0;
+ }
+ if (x->rfc3779_asid->asnum != NULL &&
+ x->rfc3779_asid->asnum->type ==
+ ASIdentifierChoice_asIdsOrRanges) {
+ if (inherit_as
+ || asid_contains(x->rfc3779_asid->asnum->u.asIdsOrRanges,
+ child_as)) {
+ child_as = x->rfc3779_asid->asnum->u.asIdsOrRanges;
+ inherit_as = 0;
+ } else {
+ validation_err(X509_V_ERR_UNNESTED_RESOURCE);
+ }
+ }
+ if (x->rfc3779_asid->rdi == NULL && child_rdi != NULL) {
+ validation_err(X509_V_ERR_UNNESTED_RESOURCE);
+ child_rdi = NULL;
+ inherit_rdi = 0;
+ }
+ if (x->rfc3779_asid->rdi != NULL &&
+ x->rfc3779_asid->rdi->type == ASIdentifierChoice_asIdsOrRanges) {
+ if (inherit_rdi ||
+ asid_contains(x->rfc3779_asid->rdi->u.asIdsOrRanges,
+ child_rdi)) {
+ child_rdi = x->rfc3779_asid->rdi->u.asIdsOrRanges;
+ inherit_rdi = 0;
+ } else {
+ validation_err(X509_V_ERR_UNNESTED_RESOURCE);
+ }
+ }
+ }
+
+ /*
+ * Trust anchor can't inherit.
+ */
+ if (!ossl_assert(x != NULL)) {
+ if (ctx != NULL)
+ ctx->error = X509_V_ERR_UNSPECIFIED;
+ return 0;
+ }
+ if (x->rfc3779_asid != NULL) {
+ if (x->rfc3779_asid->asnum != NULL &&
+ x->rfc3779_asid->asnum->type == ASIdentifierChoice_inherit)
+ validation_err(X509_V_ERR_UNNESTED_RESOURCE);
+ if (x->rfc3779_asid->rdi != NULL &&
+ x->rfc3779_asid->rdi->type == ASIdentifierChoice_inherit)
+ validation_err(X509_V_ERR_UNNESTED_RESOURCE);
+ }
+
+ done:
+ return ret;
+}
+
+#undef validation_err
+
+/*
+ * RFC 3779 3.3 path validation -- called from X509_verify_cert().
+ */
+int X509v3_asid_validate_path(X509_STORE_CTX *ctx)
+{
+ if (ctx->chain == NULL
+ || sk_X509_num(ctx->chain) == 0
+ || ctx->verify_cb == NULL) {
+ ctx->error = X509_V_ERR_UNSPECIFIED;
+ return 0;
+ }
+ return asid_validate_path_internal(ctx, ctx->chain, NULL);
+}
+
+/*
+ * RFC 3779 3.3 path validation of an extension.
+ * Test whether chain covers extension.
+ */
+int X509v3_asid_validate_resource_set(STACK_OF(X509) *chain,
+ ASIdentifiers *ext, int allow_inheritance)
+{
+ if (ext == NULL)
+ return 1;
+ if (chain == NULL || sk_X509_num(chain) == 0)
+ return 0;
+ if (!allow_inheritance && X509v3_asid_inherits(ext))
+ return 0;
+ return asid_validate_path_internal(NULL, chain, ext);
+}
+
+#endif /* OPENSSL_NO_RFC3779 */
diff --git a/crypto/x509/v3_bcons.c b/crypto/x509/v3_bcons.c
new file mode 100644
index 000000000000..6e7a165f26e8
--- /dev/null
+++ b/crypto/x509/v3_bcons.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include "ext_dat.h"
+#include "x509_local.h"
+
+static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
+ BASIC_CONSTRAINTS *bcons,
+ STACK_OF(CONF_VALUE)
+ *extlist);
+static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *values);
+
+const X509V3_EXT_METHOD ossl_v3_bcons = {
+ NID_basic_constraints, 0,
+ ASN1_ITEM_ref(BASIC_CONSTRAINTS),
+ 0, 0, 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2V) i2v_BASIC_CONSTRAINTS,
+ (X509V3_EXT_V2I)v2i_BASIC_CONSTRAINTS,
+ NULL, NULL,
+ NULL
+};
+
+ASN1_SEQUENCE(BASIC_CONSTRAINTS) = {
+ ASN1_OPT(BASIC_CONSTRAINTS, ca, ASN1_FBOOLEAN),
+ ASN1_OPT(BASIC_CONSTRAINTS, pathlen, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(BASIC_CONSTRAINTS)
+
+IMPLEMENT_ASN1_FUNCTIONS(BASIC_CONSTRAINTS)
+
+static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
+ BASIC_CONSTRAINTS *bcons,
+ STACK_OF(CONF_VALUE)
+ *extlist)
+{
+ X509V3_add_value_bool("CA", bcons->ca, &extlist);
+ X509V3_add_value_int("pathlen", bcons->pathlen, &extlist);
+ return extlist;
+}
+
+static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *values)
+{
+ BASIC_CONSTRAINTS *bcons = NULL;
+ CONF_VALUE *val;
+ int i;
+
+ if ((bcons = BASIC_CONSTRAINTS_new()) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
+ val = sk_CONF_VALUE_value(values, i);
+ if (strcmp(val->name, "CA") == 0) {
+ if (!X509V3_get_value_bool(val, &bcons->ca))
+ goto err;
+ } else if (strcmp(val->name, "pathlen") == 0) {
+ if (!X509V3_get_value_int(val, &bcons->pathlen))
+ goto err;
+ } else {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NAME);
+ X509V3_conf_add_error_name_value(val);
+ goto err;
+ }
+ }
+ return bcons;
+ err:
+ BASIC_CONSTRAINTS_free(bcons);
+ return NULL;
+}
diff --git a/crypto/x509/v3_bitst.c b/crypto/x509/v3_bitst.c
new file mode 100644
index 000000000000..b53c5ba3ecd3
--- /dev/null
+++ b/crypto/x509/v3_bitst.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include "ext_dat.h"
+
+static BIT_STRING_BITNAME ns_cert_type_table[] = {
+ {0, "SSL Client", "client"},
+ {1, "SSL Server", "server"},
+ {2, "S/MIME", "email"},
+ {3, "Object Signing", "objsign"},
+ {4, "Unused", "reserved"},
+ {5, "SSL CA", "sslCA"},
+ {6, "S/MIME CA", "emailCA"},
+ {7, "Object Signing CA", "objCA"},
+ {-1, NULL, NULL}
+};
+
+static BIT_STRING_BITNAME key_usage_type_table[] = {
+ {0, "Digital Signature", "digitalSignature"},
+ {1, "Non Repudiation", "nonRepudiation"},
+ {2, "Key Encipherment", "keyEncipherment"},
+ {3, "Data Encipherment", "dataEncipherment"},
+ {4, "Key Agreement", "keyAgreement"},
+ {5, "Certificate Sign", "keyCertSign"},
+ {6, "CRL Sign", "cRLSign"},
+ {7, "Encipher Only", "encipherOnly"},
+ {8, "Decipher Only", "decipherOnly"},
+ {-1, NULL, NULL}
+};
+
+const X509V3_EXT_METHOD ossl_v3_nscert =
+EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table);
+const X509V3_EXT_METHOD ossl_v3_key_usage =
+EXT_BITSTRING(NID_key_usage, key_usage_type_table);
+
+STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
+ ASN1_BIT_STRING *bits,
+ STACK_OF(CONF_VALUE) *ret)
+{
+ BIT_STRING_BITNAME *bnam;
+ for (bnam = method->usr_data; bnam->lname; bnam++) {
+ if (ASN1_BIT_STRING_get_bit(bits, bnam->bitnum))
+ X509V3_add_value(bnam->lname, NULL, &ret);
+ }
+ return ret;
+}
+
+ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval)
+{
+ CONF_VALUE *val;
+ ASN1_BIT_STRING *bs;
+ int i;
+ BIT_STRING_BITNAME *bnam;
+ if ((bs = ASN1_BIT_STRING_new()) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ val = sk_CONF_VALUE_value(nval, i);
+ for (bnam = method->usr_data; bnam->lname; bnam++) {
+ if (strcmp(bnam->sname, val->name) == 0
+ || strcmp(bnam->lname, val->name) == 0) {
+ if (!ASN1_BIT_STRING_set_bit(bs, bnam->bitnum, 1)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ ASN1_BIT_STRING_free(bs);
+ return NULL;
+ }
+ break;
+ }
+ }
+ if (!bnam->lname) {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT,
+ "%s", val->name);
+ ASN1_BIT_STRING_free(bs);
+ return NULL;
+ }
+ }
+ return bs;
+}
diff --git a/crypto/x509/v3_conf.c b/crypto/x509/v3_conf.c
new file mode 100644
index 000000000000..1c11d671b2ed
--- /dev/null
+++ b/crypto/x509/v3_conf.c
@@ -0,0 +1,584 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* extension creation utilities */
+
+#include <stdio.h>
+#include "crypto/ctype.h"
+#include "internal/cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/x509.h>
+#include "crypto/x509.h"
+#include <openssl/x509v3.h>
+
+static int v3_check_critical(const char **value);
+static int v3_check_generic(const char **value);
+static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
+ int crit, const char *value);
+static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value,
+ int crit, int type,
+ X509V3_CTX *ctx);
+static char *conf_lhash_get_string(void *db, const char *section, const char *value);
+static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, const char *section);
+static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method,
+ int ext_nid, int crit, void *ext_struc);
+static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx,
+ long *ext_len);
+
+static X509_EXTENSION *X509V3_EXT_nconf_int(CONF *conf, X509V3_CTX *ctx,
+ const char *section,
+ const char *name, const char *value)
+{
+ int crit;
+ int ext_type;
+ X509_EXTENSION *ret;
+
+ crit = v3_check_critical(&value);
+ if ((ext_type = v3_check_generic(&value)))
+ return v3_generic_extension(name, value, crit, ext_type, ctx);
+ ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value);
+ if (!ret) {
+ if (section != NULL)
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_ERROR_IN_EXTENSION,
+ "section=%s, name=%s, value=%s",
+ section, name, value);
+ else
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_ERROR_IN_EXTENSION,
+ "name=%s, value=%s", name, value);
+ }
+ return ret;
+}
+
+X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, const char *name,
+ const char *value)
+{
+ return X509V3_EXT_nconf_int(conf, ctx, NULL, name, value);
+}
+
+X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
+ const char *value)
+{
+ int crit;
+ int ext_type;
+
+ crit = v3_check_critical(&value);
+ if ((ext_type = v3_check_generic(&value)))
+ return v3_generic_extension(OBJ_nid2sn(ext_nid),
+ value, crit, ext_type, ctx);
+ return do_ext_nconf(conf, ctx, ext_nid, crit, value);
+}
+
+/* CONF *conf: Config file */
+/* char *value: Value */
+static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
+ int crit, const char *value)
+{
+ const X509V3_EXT_METHOD *method;
+ X509_EXTENSION *ext;
+ STACK_OF(CONF_VALUE) *nval;
+ void *ext_struc;
+
+ if (ext_nid == NID_undef) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_UNKNOWN_EXTENSION_NAME);
+ return NULL;
+ }
+ if ((method = X509V3_EXT_get_nid(ext_nid)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_UNKNOWN_EXTENSION);
+ return NULL;
+ }
+ /* Now get internal extension representation based on type */
+ if (method->v2i) {
+ if (*value == '@')
+ nval = NCONF_get_section(conf, value + 1);
+ else
+ nval = X509V3_parse_list(value);
+ if (nval == NULL || sk_CONF_VALUE_num(nval) <= 0) {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_INVALID_EXTENSION_STRING,
+ "name=%s,section=%s", OBJ_nid2sn(ext_nid), value);
+ if (*value != '@')
+ sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
+ return NULL;
+ }
+ ext_struc = method->v2i(method, ctx, nval);
+ if (*value != '@')
+ sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
+ if (!ext_struc)
+ return NULL;
+ } else if (method->s2i) {
+ if ((ext_struc = method->s2i(method, ctx, value)) == NULL)
+ return NULL;
+ } else if (method->r2i) {
+ if (!ctx->db || !ctx->db_meth) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_CONFIG_DATABASE);
+ return NULL;
+ }
+ if ((ext_struc = method->r2i(method, ctx, value)) == NULL)
+ return NULL;
+ } else {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED,
+ "name=%s", OBJ_nid2sn(ext_nid));
+ return NULL;
+ }
+
+ ext = do_ext_i2d(method, ext_nid, crit, ext_struc);
+ if (method->it)
+ ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it));
+ else
+ method->ext_free(ext_struc);
+ return ext;
+
+}
+
+static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method,
+ int ext_nid, int crit, void *ext_struc)
+{
+ unsigned char *ext_der = NULL;
+ int ext_len;
+ ASN1_OCTET_STRING *ext_oct = NULL;
+ X509_EXTENSION *ext;
+
+ /* Convert internal representation to DER */
+ if (method->it) {
+ ext_der = NULL;
+ ext_len =
+ ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it));
+ if (ext_len < 0)
+ goto merr;
+ } else {
+ unsigned char *p;
+
+ ext_len = method->i2d(ext_struc, NULL);
+ if (ext_len <= 0)
+ goto merr;
+ if ((ext_der = OPENSSL_malloc(ext_len)) == NULL)
+ goto merr;
+ p = ext_der;
+ method->i2d(ext_struc, &p);
+ }
+ if ((ext_oct = ASN1_OCTET_STRING_new()) == NULL)
+ goto merr;
+ ext_oct->data = ext_der;
+ ext_der = NULL;
+ ext_oct->length = ext_len;
+
+ ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct);
+ if (!ext)
+ goto merr;
+ ASN1_OCTET_STRING_free(ext_oct);
+
+ return ext;
+
+ merr:
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(ext_der);
+ ASN1_OCTET_STRING_free(ext_oct);
+ return NULL;
+
+}
+
+/* Given an internal structure, nid and critical flag create an extension */
+
+X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc)
+{
+ const X509V3_EXT_METHOD *method;
+
+ if ((method = X509V3_EXT_get_nid(ext_nid)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_UNKNOWN_EXTENSION);
+ return NULL;
+ }
+ return do_ext_i2d(method, ext_nid, crit, ext_struc);
+}
+
+/* Check the extension string for critical flag */
+static int v3_check_critical(const char **value)
+{
+ const char *p = *value;
+
+ if ((strlen(p) < 9) || strncmp(p, "critical,", 9))
+ return 0;
+ p += 9;
+ while (ossl_isspace(*p))
+ p++;
+ *value = p;
+ return 1;
+}
+
+/* Check extension string for generic extension and return the type */
+static int v3_check_generic(const char **value)
+{
+ int gen_type = 0;
+ const char *p = *value;
+
+ if ((strlen(p) >= 4) && strncmp(p, "DER:", 4) == 0) {
+ p += 4;
+ gen_type = 1;
+ } else if ((strlen(p) >= 5) && strncmp(p, "ASN1:", 5) == 0) {
+ p += 5;
+ gen_type = 2;
+ } else
+ return 0;
+
+ while (ossl_isspace(*p))
+ p++;
+ *value = p;
+ return gen_type;
+}
+
+/* Create a generic extension: for now just handle DER type */
+static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value,
+ int crit, int gen_type,
+ X509V3_CTX *ctx)
+{
+ unsigned char *ext_der = NULL;
+ long ext_len = 0;
+ ASN1_OBJECT *obj = NULL;
+ ASN1_OCTET_STRING *oct = NULL;
+ X509_EXTENSION *extension = NULL;
+
+ if ((obj = OBJ_txt2obj(ext, 0)) == NULL) {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_EXTENSION_NAME_ERROR,
+ "name=%s", ext);
+ goto err;
+ }
+
+ if (gen_type == 1)
+ ext_der = OPENSSL_hexstr2buf(value, &ext_len);
+ else if (gen_type == 2)
+ ext_der = generic_asn1(value, ctx, &ext_len);
+
+ if (ext_der == NULL) {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR,
+ "value=%s", value);
+ goto err;
+ }
+
+ if ((oct = ASN1_OCTET_STRING_new()) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ oct->data = ext_der;
+ oct->length = ext_len;
+ ext_der = NULL;
+
+ extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct);
+
+ err:
+ ASN1_OBJECT_free(obj);
+ ASN1_OCTET_STRING_free(oct);
+ OPENSSL_free(ext_der);
+ return extension;
+
+}
+
+static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx,
+ long *ext_len)
+{
+ ASN1_TYPE *typ;
+ unsigned char *ext_der = NULL;
+
+ typ = ASN1_generate_v3(value, ctx);
+ if (typ == NULL)
+ return NULL;
+ *ext_len = i2d_ASN1_TYPE(typ, &ext_der);
+ ASN1_TYPE_free(typ);
+ return ext_der;
+}
+
+static void delete_ext(STACK_OF(X509_EXTENSION) *sk, X509_EXTENSION *dext)
+{
+ int idx;
+ ASN1_OBJECT *obj;
+
+ obj = X509_EXTENSION_get_object(dext);
+ while ((idx = X509v3_get_ext_by_OBJ(sk, obj, -1)) >= 0)
+ X509_EXTENSION_free(X509v3_delete_ext(sk, idx));
+}
+
+/*
+ * This is the main function: add a bunch of extensions based on a config
+ * file section to an extension STACK. Just check in case sk == NULL.
+ * Note that on error new elements may have been added to *sk if sk != NULL.
+ */
+int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section,
+ STACK_OF(X509_EXTENSION) **sk)
+{
+ X509_EXTENSION *ext;
+ STACK_OF(CONF_VALUE) *nval;
+ CONF_VALUE *val;
+ int i;
+
+ if ((nval = NCONF_get_section(conf, section)) == NULL)
+ return 0;
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ val = sk_CONF_VALUE_value(nval, i);
+ if ((ext = X509V3_EXT_nconf_int(conf, ctx, val->section,
+ val->name, val->value)) == NULL)
+ return 0;
+ if (sk != NULL) {
+ if (ctx->flags == X509V3_CTX_REPLACE)
+ delete_ext(*sk, ext);
+ if (X509v3_add_ext(sk, ext, -1) == NULL) {
+ X509_EXTENSION_free(ext);
+ return 0;
+ }
+ }
+ X509_EXTENSION_free(ext);
+ }
+ return 1;
+}
+
+/*
+ * Add extensions to a certificate. Just check in case cert == NULL.
+ * Note that on error new elements may remain added to cert if cert != NULL.
+ */
+int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
+ X509 *cert)
+{
+ STACK_OF(X509_EXTENSION) **sk = NULL;
+ if (cert != NULL)
+ sk = &cert->cert_info.extensions;
+ return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
+}
+
+/*
+ * Add extensions to a CRL. Just check in case crl == NULL.
+ * Note that on error new elements may remain added to crl if crl != NULL.
+ */
+int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
+ X509_CRL *crl)
+{
+ STACK_OF(X509_EXTENSION) **sk = NULL;
+ if (crl != NULL)
+ sk = &crl->crl.extensions;
+ return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
+}
+
+/*
+ * Add extensions to certificate request. Just check in case req is NULL.
+ * Note that on error new elements may remain added to req if req != NULL.
+ */
+int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
+ X509_REQ *req)
+{
+ STACK_OF(X509_EXTENSION) *exts = NULL;
+ int ret = X509V3_EXT_add_nconf_sk(conf, ctx, section, &exts);
+
+ if (ret && req != NULL && exts != NULL)
+ ret = X509_REQ_add_extensions(req, exts);
+ sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+ return ret;
+}
+
+/* Config database functions */
+
+char *X509V3_get_string(X509V3_CTX *ctx, const char *name, const char *section)
+{
+ if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_OPERATION_NOT_DEFINED);
+ return NULL;
+ }
+ if (ctx->db_meth->get_string)
+ return ctx->db_meth->get_string(ctx->db, name, section);
+ return NULL;
+}
+
+STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, const char *section)
+{
+ if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_OPERATION_NOT_DEFINED);
+ return NULL;
+ }
+ if (ctx->db_meth->get_section)
+ return ctx->db_meth->get_section(ctx->db, section);
+ return NULL;
+}
+
+void X509V3_string_free(X509V3_CTX *ctx, char *str)
+{
+ if (!str)
+ return;
+ if (ctx->db_meth->free_string)
+ ctx->db_meth->free_string(ctx->db, str);
+}
+
+void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section)
+{
+ if (!section)
+ return;
+ if (ctx->db_meth->free_section)
+ ctx->db_meth->free_section(ctx->db, section);
+}
+
+static char *nconf_get_string(void *db, const char *section, const char *value)
+{
+ return NCONF_get_string(db, section, value);
+}
+
+static STACK_OF(CONF_VALUE) *nconf_get_section(void *db, const char *section)
+{
+ return NCONF_get_section(db, section);
+}
+
+static X509V3_CONF_METHOD nconf_method = {
+ nconf_get_string,
+ nconf_get_section,
+ NULL,
+ NULL
+};
+
+void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_NULL_PARAMETER);
+ return;
+ }
+ ctx->db_meth = &nconf_method;
+ ctx->db = conf;
+}
+
+void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req,
+ X509_CRL *crl, int flags)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_NULL_PARAMETER);
+ return;
+ }
+ ctx->flags = flags;
+ ctx->issuer_cert = issuer;
+ ctx->subject_cert = subj;
+ ctx->subject_req = req;
+ ctx->crl = crl;
+ ctx->db_meth = NULL;
+ ctx->db = NULL;
+ ctx->issuer_pkey = NULL;
+}
+
+/* For API backward compatibility, this is separate from X509V3_set_ctx() */
+int X509V3_set_issuer_pkey(X509V3_CTX *ctx, EVP_PKEY *pkey)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (ctx->subject_cert == NULL && pkey != NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ ctx->issuer_pkey = pkey;
+ return 1;
+}
+
+/* Old conf compatibility functions */
+
+X509_EXTENSION *X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ const char *name, const char *value)
+{
+ CONF *ctmp;
+ X509_EXTENSION *ret;
+
+ if ((ctmp = NCONF_new(NULL)) == NULL)
+ return NULL;
+ CONF_set_nconf(ctmp, conf);
+ ret = X509V3_EXT_nconf(ctmp, ctx, name, value);
+ CONF_set_nconf(ctmp, NULL);
+ NCONF_free(ctmp);
+ return ret;
+}
+
+X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf,
+ X509V3_CTX *ctx, int ext_nid, const char *value)
+{
+ CONF *ctmp;
+ X509_EXTENSION *ret;
+
+ if ((ctmp = NCONF_new(NULL)) == NULL)
+ return NULL;
+ CONF_set_nconf(ctmp, conf);
+ ret = X509V3_EXT_nconf_nid(ctmp, ctx, ext_nid, value);
+ CONF_set_nconf(ctmp, NULL);
+ NCONF_free(ctmp);
+ return ret;
+}
+
+static char *conf_lhash_get_string(void *db, const char *section, const char *value)
+{
+ return CONF_get_string(db, section, value);
+}
+
+static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, const char *section)
+{
+ return CONF_get_section(db, section);
+}
+
+static X509V3_CONF_METHOD conf_lhash_method = {
+ conf_lhash_get_string,
+ conf_lhash_get_section,
+ NULL,
+ NULL
+};
+
+void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_NULL_PARAMETER);
+ return;
+ }
+ ctx->db_meth = &conf_lhash_method;
+ ctx->db = lhash;
+}
+
+int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ const char *section, X509 *cert)
+{
+ CONF *ctmp;
+ int ret;
+
+ if ((ctmp = NCONF_new(NULL)) == NULL)
+ return 0;
+ CONF_set_nconf(ctmp, conf);
+ ret = X509V3_EXT_add_nconf(ctmp, ctx, section, cert);
+ CONF_set_nconf(ctmp, NULL);
+ NCONF_free(ctmp);
+ return ret;
+}
+
+/* Same as above but for a CRL */
+
+int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ const char *section, X509_CRL *crl)
+{
+ CONF *ctmp;
+ int ret;
+
+ if ((ctmp = NCONF_new(NULL)) == NULL)
+ return 0;
+ CONF_set_nconf(ctmp, conf);
+ ret = X509V3_EXT_CRL_add_nconf(ctmp, ctx, section, crl);
+ CONF_set_nconf(ctmp, NULL);
+ NCONF_free(ctmp);
+ return ret;
+}
+
+/* Add extensions to certificate request */
+
+int X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ const char *section, X509_REQ *req)
+{
+ CONF *ctmp;
+ int ret;
+
+ if ((ctmp = NCONF_new(NULL)) == NULL)
+ return 0;
+ CONF_set_nconf(ctmp, conf);
+ ret = X509V3_EXT_REQ_add_nconf(ctmp, ctx, section, req);
+ CONF_set_nconf(ctmp, NULL);
+ NCONF_free(ctmp);
+ return ret;
+}
diff --git a/crypto/x509/v3_cpols.c b/crypto/x509/v3_cpols.c
new file mode 100644
index 000000000000..5353a6916761
--- /dev/null
+++ b/crypto/x509/v3_cpols.c
@@ -0,0 +1,500 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509v3.h>
+
+#include "x509_local.h"
+#include "pcy_local.h"
+#include "ext_dat.h"
+
+/* Certificate policies extension support: this one is a bit complex... */
+
+static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
+ BIO *out, int indent);
+static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, const char *value);
+static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
+ int indent);
+static void print_notice(BIO *out, USERNOTICE *notice, int indent);
+static POLICYINFO *policy_section(X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *polstrs, int ia5org);
+static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *unot, int ia5org);
+static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos);
+static int displaytext_str2tag(const char *tagstr, unsigned int *tag_len);
+static int displaytext_get_tag_len(const char *tagstr);
+
+const X509V3_EXT_METHOD ossl_v3_cpols = {
+ NID_certificate_policies, 0, ASN1_ITEM_ref(CERTIFICATEPOLICIES),
+ 0, 0, 0, 0,
+ 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2R)i2r_certpol,
+ (X509V3_EXT_R2I)r2i_certpol,
+ NULL
+};
+
+ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO)
+ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES)
+
+IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
+
+ASN1_SEQUENCE(POLICYINFO) = {
+ ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT),
+ ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO)
+} ASN1_SEQUENCE_END(POLICYINFO)
+
+IMPLEMENT_ASN1_FUNCTIONS(POLICYINFO)
+
+ASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, ASN1_ANY);
+
+ASN1_ADB(POLICYQUALINFO) = {
+ ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)),
+ ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE))
+} ASN1_ADB_END(POLICYQUALINFO, 0, pqualid, 0, &policydefault_tt, NULL);
+
+ASN1_SEQUENCE(POLICYQUALINFO) = {
+ ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT),
+ ASN1_ADB_OBJECT(POLICYQUALINFO)
+} ASN1_SEQUENCE_END(POLICYQUALINFO)
+
+IMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO)
+
+ASN1_SEQUENCE(USERNOTICE) = {
+ ASN1_OPT(USERNOTICE, noticeref, NOTICEREF),
+ ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT)
+} ASN1_SEQUENCE_END(USERNOTICE)
+
+IMPLEMENT_ASN1_FUNCTIONS(USERNOTICE)
+
+ASN1_SEQUENCE(NOTICEREF) = {
+ ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT),
+ ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(NOTICEREF)
+
+IMPLEMENT_ASN1_FUNCTIONS(NOTICEREF)
+
+static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, const char *value)
+{
+ STACK_OF(POLICYINFO) *pols;
+ char *pstr;
+ POLICYINFO *pol;
+ ASN1_OBJECT *pobj;
+ STACK_OF(CONF_VALUE) *vals = X509V3_parse_list(value);
+ CONF_VALUE *cnf;
+ const int num = sk_CONF_VALUE_num(vals);
+ int i, ia5org;
+
+ if (vals == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_X509V3_LIB);
+ return NULL;
+ }
+
+ pols = sk_POLICYINFO_new_reserve(NULL, num);
+ if (pols == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ ia5org = 0;
+ for (i = 0; i < num; i++) {
+ cnf = sk_CONF_VALUE_value(vals, i);
+ if (cnf->value != NULL || cnf->name == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_POLICY_IDENTIFIER);
+ X509V3_conf_add_error_name_value(cnf);
+ goto err;
+ }
+ pstr = cnf->name;
+ if (strcmp(pstr, "ia5org") == 0) {
+ ia5org = 1;
+ continue;
+ } else if (*pstr == '@') {
+ STACK_OF(CONF_VALUE) *polsect;
+
+ polsect = X509V3_get_section(ctx, pstr + 1);
+ if (polsect == NULL) {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_INVALID_SECTION,
+ "%s", cnf->name);
+ goto err;
+ }
+ pol = policy_section(ctx, polsect, ia5org);
+ X509V3_section_free(ctx, polsect);
+ if (pol == NULL)
+ goto err;
+ } else {
+ if ((pobj = OBJ_txt2obj(cnf->name, 0)) == NULL) {
+ ERR_raise_data(ERR_LIB_X509V3,
+ X509V3_R_INVALID_OBJECT_IDENTIFIER,
+ "%s", cnf->name);
+ goto err;
+ }
+ pol = POLICYINFO_new();
+ if (pol == NULL) {
+ ASN1_OBJECT_free(pobj);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ pol->policyid = pobj;
+ }
+ if (!sk_POLICYINFO_push(pols, pol)) {
+ POLICYINFO_free(pol);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
+ return pols;
+ err:
+ sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
+ sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
+ return NULL;
+}
+
+static POLICYINFO *policy_section(X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *polstrs, int ia5org)
+{
+ int i;
+ CONF_VALUE *cnf;
+ POLICYINFO *pol;
+ POLICYQUALINFO *qual;
+
+ if ((pol = POLICYINFO_new()) == NULL)
+ goto merr;
+ for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) {
+ cnf = sk_CONF_VALUE_value(polstrs, i);
+ if (strcmp(cnf->name, "policyIdentifier") == 0) {
+ ASN1_OBJECT *pobj;
+
+ if ((pobj = OBJ_txt2obj(cnf->value, 0)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ pol->policyid = pobj;
+
+ } else if (!ossl_v3_name_cmp(cnf->name, "CPS")) {
+ if (pol->qualifiers == NULL)
+ pol->qualifiers = sk_POLICYQUALINFO_new_null();
+ if ((qual = POLICYQUALINFO_new()) == NULL)
+ goto merr;
+ if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
+ goto merr;
+ if ((qual->pqualid = OBJ_nid2obj(NID_id_qt_cps)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ if ((qual->d.cpsuri = ASN1_IA5STRING_new()) == NULL)
+ goto merr;
+ if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value,
+ strlen(cnf->value)))
+ goto merr;
+ } else if (!ossl_v3_name_cmp(cnf->name, "userNotice")) {
+ STACK_OF(CONF_VALUE) *unot;
+ if (*cnf->value != '@') {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_EXPECTED_A_SECTION_NAME);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ unot = X509V3_get_section(ctx, cnf->value + 1);
+ if (!unot) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_SECTION);
+
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ qual = notice_section(ctx, unot, ia5org);
+ X509V3_section_free(ctx, unot);
+ if (!qual)
+ goto err;
+ if (pol->qualifiers == NULL)
+ pol->qualifiers = sk_POLICYQUALINFO_new_null();
+ if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
+ goto merr;
+ } else {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_OPTION);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ }
+ if (pol->policyid == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_POLICY_IDENTIFIER);
+ goto err;
+ }
+
+ return pol;
+
+ merr:
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+
+ err:
+ POLICYINFO_free(pol);
+ return NULL;
+}
+
+static int displaytext_get_tag_len(const char *tagstr)
+{
+ char *colon = strchr(tagstr, ':');
+
+ return (colon == NULL) ? -1 : colon - tagstr;
+}
+
+static int displaytext_str2tag(const char *tagstr, unsigned int *tag_len)
+{
+ int len;
+
+ *tag_len = 0;
+ len = displaytext_get_tag_len(tagstr);
+
+ if (len == -1)
+ return V_ASN1_VISIBLESTRING;
+ *tag_len = len;
+ if (len == sizeof("UTF8") - 1 && strncmp(tagstr, "UTF8", len) == 0)
+ return V_ASN1_UTF8STRING;
+ if (len == sizeof("UTF8String") - 1 && strncmp(tagstr, "UTF8String", len) == 0)
+ return V_ASN1_UTF8STRING;
+ if (len == sizeof("BMP") - 1 && strncmp(tagstr, "BMP", len) == 0)
+ return V_ASN1_BMPSTRING;
+ if (len == sizeof("BMPSTRING") - 1 && strncmp(tagstr, "BMPSTRING", len) == 0)
+ return V_ASN1_BMPSTRING;
+ if (len == sizeof("VISIBLE") - 1 && strncmp(tagstr, "VISIBLE", len) == 0)
+ return V_ASN1_VISIBLESTRING;
+ if (len == sizeof("VISIBLESTRING") - 1 && strncmp(tagstr, "VISIBLESTRING", len) == 0)
+ return V_ASN1_VISIBLESTRING;
+ *tag_len = 0;
+ return V_ASN1_VISIBLESTRING;
+}
+
+static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *unot, int ia5org)
+{
+ int i, ret, len, tag;
+ unsigned int tag_len;
+ CONF_VALUE *cnf;
+ USERNOTICE *not;
+ POLICYQUALINFO *qual;
+ char *value = NULL;
+
+ if ((qual = POLICYQUALINFO_new()) == NULL)
+ goto merr;
+ if ((qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ if ((not = USERNOTICE_new()) == NULL)
+ goto merr;
+ qual->d.usernotice = not;
+ for (i = 0; i < sk_CONF_VALUE_num(unot); i++) {
+ cnf = sk_CONF_VALUE_value(unot, i);
+
+ value = cnf->value;
+ if (strcmp(cnf->name, "explicitText") == 0) {
+ tag = displaytext_str2tag(value, &tag_len);
+ if ((not->exptext = ASN1_STRING_type_new(tag)) == NULL)
+ goto merr;
+ if (tag_len != 0)
+ value += tag_len + 1;
+ len = strlen(value);
+ if (!ASN1_STRING_set(not->exptext, value, len))
+ goto merr;
+ } else if (strcmp(cnf->name, "organization") == 0) {
+ NOTICEREF *nref;
+
+ if (!not->noticeref) {
+ if ((nref = NOTICEREF_new()) == NULL)
+ goto merr;
+ not->noticeref = nref;
+ } else
+ nref = not->noticeref;
+ if (ia5org)
+ nref->organization->type = V_ASN1_IA5STRING;
+ else
+ nref->organization->type = V_ASN1_VISIBLESTRING;
+ if (!ASN1_STRING_set(nref->organization, cnf->value,
+ strlen(cnf->value)))
+ goto merr;
+ } else if (strcmp(cnf->name, "noticeNumbers") == 0) {
+ NOTICEREF *nref;
+
+ STACK_OF(CONF_VALUE) *nos;
+ if (!not->noticeref) {
+ if ((nref = NOTICEREF_new()) == NULL)
+ goto merr;
+ not->noticeref = nref;
+ } else
+ nref = not->noticeref;
+ nos = X509V3_parse_list(cnf->value);
+ if (!nos || !sk_CONF_VALUE_num(nos)) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NUMBERS);
+ X509V3_conf_add_error_name_value(cnf);
+ sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
+ goto err;
+ }
+ ret = nref_nos(nref->noticenos, nos);
+ sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
+ if (!ret)
+ goto err;
+ } else {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_OPTION);
+ X509V3_conf_add_error_name_value(cnf);
+ goto err;
+ }
+ }
+
+ if (not->noticeref &&
+ (!not->noticeref->noticenos || !not->noticeref->organization)) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
+ goto err;
+ }
+
+ return qual;
+
+ merr:
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+
+ err:
+ POLICYQUALINFO_free(qual);
+ return NULL;
+}
+
+static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos)
+{
+ CONF_VALUE *cnf;
+ ASN1_INTEGER *aint;
+
+ int i;
+
+ for (i = 0; i < sk_CONF_VALUE_num(nos); i++) {
+ cnf = sk_CONF_VALUE_value(nos, i);
+ if ((aint = s2i_ASN1_INTEGER(NULL, cnf->name)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NUMBER);
+ goto err;
+ }
+ if (!sk_ASN1_INTEGER_push(nnums, aint))
+ goto merr;
+ }
+ return 1;
+
+ merr:
+ ASN1_INTEGER_free(aint);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+
+ err:
+ return 0;
+}
+
+static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
+ BIO *out, int indent)
+{
+ int i;
+ POLICYINFO *pinfo;
+ /* First print out the policy OIDs */
+ for (i = 0; i < sk_POLICYINFO_num(pol); i++) {
+ if (i > 0)
+ BIO_puts(out, "\n");
+ pinfo = sk_POLICYINFO_value(pol, i);
+ BIO_printf(out, "%*sPolicy: ", indent, "");
+ i2a_ASN1_OBJECT(out, pinfo->policyid);
+ if (pinfo->qualifiers) {
+ BIO_puts(out, "\n");
+ print_qualifiers(out, pinfo->qualifiers, indent + 2);
+ }
+ }
+ return 1;
+}
+
+static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
+ int indent)
+{
+ POLICYQUALINFO *qualinfo;
+ int i;
+ for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
+ if (i > 0)
+ BIO_puts(out, "\n");
+ qualinfo = sk_POLICYQUALINFO_value(quals, i);
+ switch (OBJ_obj2nid(qualinfo->pqualid)) {
+ case NID_id_qt_cps:
+ BIO_printf(out, "%*sCPS: %.*s", indent, "",
+ qualinfo->d.cpsuri->length,
+ qualinfo->d.cpsuri->data);
+ break;
+
+ case NID_id_qt_unotice:
+ BIO_printf(out, "%*sUser Notice:\n", indent, "");
+ print_notice(out, qualinfo->d.usernotice, indent + 2);
+ break;
+
+ default:
+ BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, "");
+
+ i2a_ASN1_OBJECT(out, qualinfo->pqualid);
+ break;
+ }
+ }
+}
+
+static void print_notice(BIO *out, USERNOTICE *notice, int indent)
+{
+ int i;
+ if (notice->noticeref) {
+ NOTICEREF *ref;
+ ref = notice->noticeref;
+ BIO_printf(out, "%*sOrganization: %.*s\n", indent, "",
+ ref->organization->length,
+ ref->organization->data);
+ BIO_printf(out, "%*sNumber%s: ", indent, "",
+ sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : "");
+ for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) {
+ ASN1_INTEGER *num;
+ char *tmp;
+ num = sk_ASN1_INTEGER_value(ref->noticenos, i);
+ if (i)
+ BIO_puts(out, ", ");
+ if (num == NULL)
+ BIO_puts(out, "(null)");
+ else {
+ tmp = i2s_ASN1_INTEGER(NULL, num);
+ if (tmp == NULL)
+ return;
+ BIO_puts(out, tmp);
+ OPENSSL_free(tmp);
+ }
+ }
+ if (notice->exptext)
+ BIO_puts(out, "\n");
+ }
+ if (notice->exptext)
+ BIO_printf(out, "%*sExplicit Text: %.*s", indent, "",
+ notice->exptext->length,
+ notice->exptext->data);
+}
+
+void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent)
+{
+ const X509_POLICY_DATA *dat = node->data;
+
+ BIO_printf(out, "%*sPolicy: ", indent, "");
+
+ i2a_ASN1_OBJECT(out, dat->valid_policy);
+ BIO_puts(out, "\n");
+ BIO_printf(out, "%*s%s\n", indent + 2, "",
+ node_data_critical(dat) ? "Critical" : "Non Critical");
+ if (dat->qualifier_set) {
+ print_qualifiers(out, dat->qualifier_set, indent + 2);
+ BIO_puts(out, "\n");
+ }
+ else
+ BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
+}
diff --git a/crypto/x509/v3_crld.c b/crypto/x509/v3_crld.c
new file mode 100644
index 000000000000..0289df4de789
--- /dev/null
+++ b/crypto/x509/v3_crld.c
@@ -0,0 +1,508 @@
+/*
+ * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509v3.h>
+
+#include "crypto/x509.h"
+#include "ext_dat.h"
+#include "x509_local.h"
+
+static void *v2i_crld(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
+ int indent);
+
+const X509V3_EXT_METHOD ossl_v3_crld = {
+ NID_crl_distribution_points, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
+ 0, 0, 0, 0,
+ 0, 0,
+ 0,
+ v2i_crld,
+ i2r_crldp, 0,
+ NULL
+};
+
+const X509V3_EXT_METHOD ossl_v3_freshest_crl = {
+ NID_freshest_crl, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
+ 0, 0, 0, 0,
+ 0, 0,
+ 0,
+ v2i_crld,
+ i2r_crldp, 0,
+ NULL
+};
+
+static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx,
+ char *sect)
+{
+ STACK_OF(CONF_VALUE) *gnsect;
+ STACK_OF(GENERAL_NAME) *gens;
+ if (*sect == '@')
+ gnsect = X509V3_get_section(ctx, sect + 1);
+ else
+ gnsect = X509V3_parse_list(sect);
+ if (!gnsect) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_SECTION_NOT_FOUND);
+ return NULL;
+ }
+ gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect);
+ if (*sect == '@')
+ X509V3_section_free(ctx, gnsect);
+ else
+ sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free);
+ return gens;
+}
+
+static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx,
+ CONF_VALUE *cnf)
+{
+ STACK_OF(GENERAL_NAME) *fnm = NULL;
+ STACK_OF(X509_NAME_ENTRY) *rnm = NULL;
+
+ if (strncmp(cnf->name, "fullname", 9) == 0) {
+ fnm = gnames_from_sectname(ctx, cnf->value);
+ if (!fnm)
+ goto err;
+ } else if (strcmp(cnf->name, "relativename") == 0) {
+ int ret;
+ STACK_OF(CONF_VALUE) *dnsect;
+ X509_NAME *nm;
+ nm = X509_NAME_new();
+ if (nm == NULL)
+ return -1;
+ dnsect = X509V3_get_section(ctx, cnf->value);
+ if (!dnsect) {
+ X509_NAME_free(nm);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_SECTION_NOT_FOUND);
+ return -1;
+ }
+ ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC);
+ X509V3_section_free(ctx, dnsect);
+ rnm = nm->entries;
+ nm->entries = NULL;
+ X509_NAME_free(nm);
+ if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0)
+ goto err;
+ /*
+ * Since its a name fragment can't have more than one RDNSequence
+ */
+ if (sk_X509_NAME_ENTRY_value(rnm,
+ sk_X509_NAME_ENTRY_num(rnm) - 1)->set) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_MULTIPLE_RDNS);
+ goto err;
+ }
+ } else
+ return 0;
+
+ if (*pdp) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_DISTPOINT_ALREADY_SET);
+ goto err;
+ }
+
+ *pdp = DIST_POINT_NAME_new();
+ if (*pdp == NULL)
+ goto err;
+ if (fnm) {
+ (*pdp)->type = 0;
+ (*pdp)->name.fullname = fnm;
+ } else {
+ (*pdp)->type = 1;
+ (*pdp)->name.relativename = rnm;
+ }
+
+ return 1;
+
+ err:
+ sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free);
+ sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free);
+ return -1;
+}
+
+static const BIT_STRING_BITNAME reason_flags[] = {
+ {0, "Unused", "unused"},
+ {1, "Key Compromise", "keyCompromise"},
+ {2, "CA Compromise", "CACompromise"},
+ {3, "Affiliation Changed", "affiliationChanged"},
+ {4, "Superseded", "superseded"},
+ {5, "Cessation Of Operation", "cessationOfOperation"},
+ {6, "Certificate Hold", "certificateHold"},
+ {7, "Privilege Withdrawn", "privilegeWithdrawn"},
+ {8, "AA Compromise", "AACompromise"},
+ {-1, NULL, NULL}
+};
+
+static int set_reasons(ASN1_BIT_STRING **preas, char *value)
+{
+ STACK_OF(CONF_VALUE) *rsk = NULL;
+ const BIT_STRING_BITNAME *pbn;
+ const char *bnam;
+ int i, ret = 0;
+ rsk = X509V3_parse_list(value);
+ if (rsk == NULL)
+ return 0;
+ if (*preas != NULL)
+ goto err;
+ for (i = 0; i < sk_CONF_VALUE_num(rsk); i++) {
+ bnam = sk_CONF_VALUE_value(rsk, i)->name;
+ if (*preas == NULL) {
+ *preas = ASN1_BIT_STRING_new();
+ if (*preas == NULL)
+ goto err;
+ }
+ for (pbn = reason_flags; pbn->lname; pbn++) {
+ if (strcmp(pbn->sname, bnam) == 0) {
+ if (!ASN1_BIT_STRING_set_bit(*preas, pbn->bitnum, 1))
+ goto err;
+ break;
+ }
+ }
+ if (pbn->lname == NULL)
+ goto err;
+ }
+ ret = 1;
+
+ err:
+ sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free);
+ return ret;
+}
+
+static int print_reasons(BIO *out, const char *rname,
+ ASN1_BIT_STRING *rflags, int indent)
+{
+ int first = 1;
+ const BIT_STRING_BITNAME *pbn;
+ BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, "");
+ for (pbn = reason_flags; pbn->lname; pbn++) {
+ if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum)) {
+ if (first)
+ first = 0;
+ else
+ BIO_puts(out, ", ");
+ BIO_puts(out, pbn->lname);
+ }
+ }
+ if (first)
+ BIO_puts(out, "<EMPTY>\n");
+ else
+ BIO_puts(out, "\n");
+ return 1;
+}
+
+static DIST_POINT *crldp_from_section(X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval)
+{
+ int i;
+ CONF_VALUE *cnf;
+ DIST_POINT *point = DIST_POINT_new();
+
+ if (point == NULL)
+ goto err;
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ int ret;
+ cnf = sk_CONF_VALUE_value(nval, i);
+ ret = set_dist_point_name(&point->distpoint, ctx, cnf);
+ if (ret > 0)
+ continue;
+ if (ret < 0)
+ goto err;
+ if (strcmp(cnf->name, "reasons") == 0) {
+ if (!set_reasons(&point->reasons, cnf->value))
+ goto err;
+ } else if (strcmp(cnf->name, "CRLissuer") == 0) {
+ point->CRLissuer = gnames_from_sectname(ctx, cnf->value);
+ if (point->CRLissuer == NULL)
+ goto err;
+ }
+ }
+
+ return point;
+
+ err:
+ DIST_POINT_free(point);
+ return NULL;
+}
+
+static void *v2i_crld(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+{
+ STACK_OF(DIST_POINT) *crld;
+ GENERAL_NAMES *gens = NULL;
+ GENERAL_NAME *gen = NULL;
+ CONF_VALUE *cnf;
+ const int num = sk_CONF_VALUE_num(nval);
+ int i;
+
+ crld = sk_DIST_POINT_new_reserve(NULL, num);
+ if (crld == NULL)
+ goto merr;
+ for (i = 0; i < num; i++) {
+ DIST_POINT *point;
+
+ cnf = sk_CONF_VALUE_value(nval, i);
+ if (cnf->value == NULL) {
+ STACK_OF(CONF_VALUE) *dpsect;
+ dpsect = X509V3_get_section(ctx, cnf->name);
+ if (!dpsect)
+ goto err;
+ point = crldp_from_section(ctx, dpsect);
+ X509V3_section_free(ctx, dpsect);
+ if (point == NULL)
+ goto err;
+ sk_DIST_POINT_push(crld, point); /* no failure as it was reserved */
+ } else {
+ if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
+ goto err;
+ if ((gens = GENERAL_NAMES_new()) == NULL)
+ goto merr;
+ if (!sk_GENERAL_NAME_push(gens, gen))
+ goto merr;
+ gen = NULL;
+ if ((point = DIST_POINT_new()) == NULL)
+ goto merr;
+ sk_DIST_POINT_push(crld, point); /* no failure as it was reserved */
+ if ((point->distpoint = DIST_POINT_NAME_new()) == NULL)
+ goto merr;
+ point->distpoint->name.fullname = gens;
+ point->distpoint->type = 0;
+ gens = NULL;
+ }
+ }
+ return crld;
+
+ merr:
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ err:
+ GENERAL_NAME_free(gen);
+ GENERAL_NAMES_free(gens);
+ sk_DIST_POINT_pop_free(crld, DIST_POINT_free);
+ return NULL;
+}
+
+static int dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ void *exarg)
+{
+ DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval;
+
+ switch (operation) {
+ case ASN1_OP_NEW_POST:
+ dpn->dpname = NULL;
+ break;
+
+ case ASN1_OP_FREE_POST:
+ X509_NAME_free(dpn->dpname);
+ break;
+ }
+ return 1;
+}
+
+
+ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = {
+ ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0),
+ ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1)
+} ASN1_CHOICE_END_cb(DIST_POINT_NAME, DIST_POINT_NAME, type)
+
+
+IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME)
+
+ASN1_SEQUENCE(DIST_POINT) = {
+ ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0),
+ ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1),
+ ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2)
+} ASN1_SEQUENCE_END(DIST_POINT)
+
+IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT)
+
+ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT)
+ASN1_ITEM_TEMPLATE_END(CRL_DIST_POINTS)
+
+IMPLEMENT_ASN1_FUNCTIONS(CRL_DIST_POINTS)
+
+ASN1_SEQUENCE(ISSUING_DIST_POINT) = {
+ ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0),
+ ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1),
+ ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2),
+ ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3),
+ ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4),
+ ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5)
+} ASN1_SEQUENCE_END(ISSUING_DIST_POINT)
+
+IMPLEMENT_ASN1_FUNCTIONS(ISSUING_DIST_POINT)
+
+static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
+ int indent);
+static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval);
+
+const X509V3_EXT_METHOD ossl_v3_idp = {
+ NID_issuing_distribution_point, X509V3_EXT_MULTILINE,
+ ASN1_ITEM_ref(ISSUING_DIST_POINT),
+ 0, 0, 0, 0,
+ 0, 0,
+ 0,
+ v2i_idp,
+ i2r_idp, 0,
+ NULL
+};
+
+static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval)
+{
+ ISSUING_DIST_POINT *idp = NULL;
+ CONF_VALUE *cnf;
+ char *name, *val;
+ int i, ret;
+ idp = ISSUING_DIST_POINT_new();
+ if (idp == NULL)
+ goto merr;
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ cnf = sk_CONF_VALUE_value(nval, i);
+ name = cnf->name;
+ val = cnf->value;
+ ret = set_dist_point_name(&idp->distpoint, ctx, cnf);
+ if (ret > 0)
+ continue;
+ if (ret < 0)
+ goto err;
+ if (strcmp(name, "onlyuser") == 0) {
+ if (!X509V3_get_value_bool(cnf, &idp->onlyuser))
+ goto err;
+ } else if (strcmp(name, "onlyCA") == 0) {
+ if (!X509V3_get_value_bool(cnf, &idp->onlyCA))
+ goto err;
+ } else if (strcmp(name, "onlyAA") == 0) {
+ if (!X509V3_get_value_bool(cnf, &idp->onlyattr))
+ goto err;
+ } else if (strcmp(name, "indirectCRL") == 0) {
+ if (!X509V3_get_value_bool(cnf, &idp->indirectCRL))
+ goto err;
+ } else if (strcmp(name, "onlysomereasons") == 0) {
+ if (!set_reasons(&idp->onlysomereasons, val))
+ goto err;
+ } else {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NAME);
+ X509V3_conf_add_error_name_value(cnf);
+ goto err;
+ }
+ }
+ return idp;
+
+ merr:
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ err:
+ ISSUING_DIST_POINT_free(idp);
+ return NULL;
+}
+
+static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent)
+{
+ int i;
+ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+ if (i > 0)
+ BIO_puts(out, "\n");
+ BIO_printf(out, "%*s", indent + 2, "");
+ GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i));
+ }
+ return 1;
+}
+
+static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent)
+{
+ if (dpn->type == 0) {
+ BIO_printf(out, "%*sFull Name:\n", indent, "");
+ print_gens(out, dpn->name.fullname, indent);
+ } else {
+ X509_NAME ntmp;
+ ntmp.entries = dpn->name.relativename;
+ BIO_printf(out, "%*sRelative Name:\n%*s", indent, "", indent + 2, "");
+ X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE);
+ BIO_puts(out, "\n");
+ }
+ return 1;
+}
+
+static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
+ int indent)
+{
+ ISSUING_DIST_POINT *idp = pidp;
+ if (idp->distpoint)
+ print_distpoint(out, idp->distpoint, indent);
+ if (idp->onlyuser > 0)
+ BIO_printf(out, "%*sOnly User Certificates\n", indent, "");
+ if (idp->onlyCA > 0)
+ BIO_printf(out, "%*sOnly CA Certificates\n", indent, "");
+ if (idp->indirectCRL > 0)
+ BIO_printf(out, "%*sIndirect CRL\n", indent, "");
+ if (idp->onlysomereasons)
+ print_reasons(out, "Only Some Reasons", idp->onlysomereasons, indent);
+ if (idp->onlyattr > 0)
+ BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, "");
+ if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0)
+ && (idp->indirectCRL <= 0) && !idp->onlysomereasons
+ && (idp->onlyattr <= 0))
+ BIO_printf(out, "%*s<EMPTY>\n", indent, "");
+
+ return 1;
+}
+
+static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
+ int indent)
+{
+ STACK_OF(DIST_POINT) *crld = pcrldp;
+ DIST_POINT *point;
+ int i;
+ for (i = 0; i < sk_DIST_POINT_num(crld); i++) {
+ if (i > 0)
+ BIO_puts(out, "\n");
+ point = sk_DIST_POINT_value(crld, i);
+ if (point->distpoint)
+ print_distpoint(out, point->distpoint, indent);
+ if (point->reasons)
+ print_reasons(out, "Reasons", point->reasons, indent);
+ if (point->CRLissuer) {
+ BIO_printf(out, "%*sCRL Issuer:\n", indent, "");
+ print_gens(out, point->CRLissuer, indent);
+ }
+ }
+ return 1;
+}
+
+/* Append any nameRelativeToCRLIssuer in dpn to iname, set in dpn->dpname */
+int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, const X509_NAME *iname)
+{
+ int i;
+ STACK_OF(X509_NAME_ENTRY) *frag;
+ X509_NAME_ENTRY *ne;
+
+ if (dpn == NULL || dpn->type != 1)
+ return 1;
+ frag = dpn->name.relativename;
+ X509_NAME_free(dpn->dpname); /* just in case it was already set */
+ dpn->dpname = X509_NAME_dup(iname);
+ if (dpn->dpname == NULL)
+ return 0;
+ for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) {
+ ne = sk_X509_NAME_ENTRY_value(frag, i);
+ if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1))
+ goto err;
+ }
+ /* generate cached encoding of name */
+ if (i2d_X509_NAME(dpn->dpname, NULL) >= 0)
+ return 1;
+
+ err:
+ X509_NAME_free(dpn->dpname);
+ dpn->dpname = NULL;
+ return 0;
+}
diff --git a/crypto/x509/v3_enum.c b/crypto/x509/v3_enum.c
new file mode 100644
index 000000000000..b73a6d55162b
--- /dev/null
+++ b/crypto/x509/v3_enum.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/x509v3.h>
+#include "ext_dat.h"
+
+static ENUMERATED_NAMES crl_reasons[] = {
+ {CRL_REASON_UNSPECIFIED, "Unspecified", "unspecified"},
+ {CRL_REASON_KEY_COMPROMISE, "Key Compromise", "keyCompromise"},
+ {CRL_REASON_CA_COMPROMISE, "CA Compromise", "CACompromise"},
+ {CRL_REASON_AFFILIATION_CHANGED, "Affiliation Changed",
+ "affiliationChanged"},
+ {CRL_REASON_SUPERSEDED, "Superseded", "superseded"},
+ {CRL_REASON_CESSATION_OF_OPERATION,
+ "Cessation Of Operation", "cessationOfOperation"},
+ {CRL_REASON_CERTIFICATE_HOLD, "Certificate Hold", "certificateHold"},
+ {CRL_REASON_REMOVE_FROM_CRL, "Remove From CRL", "removeFromCRL"},
+ {CRL_REASON_PRIVILEGE_WITHDRAWN, "Privilege Withdrawn",
+ "privilegeWithdrawn"},
+ {CRL_REASON_AA_COMPROMISE, "AA Compromise", "AACompromise"},
+ {-1, NULL, NULL}
+};
+
+const X509V3_EXT_METHOD ossl_v3_crl_reason = {
+ NID_crl_reason, 0, ASN1_ITEM_ref(ASN1_ENUMERATED),
+ 0, 0, 0, 0,
+ (X509V3_EXT_I2S)i2s_ASN1_ENUMERATED_TABLE,
+ 0,
+ 0, 0, 0, 0,
+ crl_reasons
+};
+
+char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method,
+ const ASN1_ENUMERATED *e)
+{
+ ENUMERATED_NAMES *enam;
+ long strval;
+
+ strval = ASN1_ENUMERATED_get(e);
+ for (enam = method->usr_data; enam->lname; enam++) {
+ if (strval == enam->bitnum)
+ return OPENSSL_strdup(enam->lname);
+ }
+ return i2s_ASN1_ENUMERATED(method, e);
+}
diff --git a/crypto/x509/v3_extku.c b/crypto/x509/v3_extku.c
new file mode 100644
index 000000000000..4f2a86bdcb2b
--- /dev/null
+++ b/crypto/x509/v3_extku.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include "ext_dat.h"
+
+static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval);
+static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD
+ *method, void *eku, STACK_OF(CONF_VALUE)
+ *extlist);
+
+const X509V3_EXT_METHOD ossl_v3_ext_ku = {
+ NID_ext_key_usage, 0,
+ ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
+ 0, 0, 0, 0,
+ 0, 0,
+ i2v_EXTENDED_KEY_USAGE,
+ v2i_EXTENDED_KEY_USAGE,
+ 0, 0,
+ NULL
+};
+
+/* NB OCSP acceptable responses also is a SEQUENCE OF OBJECT */
+const X509V3_EXT_METHOD ossl_v3_ocsp_accresp = {
+ NID_id_pkix_OCSP_acceptableResponses, 0,
+ ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
+ 0, 0, 0, 0,
+ 0, 0,
+ i2v_EXTENDED_KEY_USAGE,
+ v2i_EXTENDED_KEY_USAGE,
+ 0, 0,
+ NULL
+};
+
+ASN1_ITEM_TEMPLATE(EXTENDED_KEY_USAGE) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, EXTENDED_KEY_USAGE, ASN1_OBJECT)
+ASN1_ITEM_TEMPLATE_END(EXTENDED_KEY_USAGE)
+
+IMPLEMENT_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE)
+
+static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD
+ *method, void *a, STACK_OF(CONF_VALUE)
+ *ext_list)
+{
+ EXTENDED_KEY_USAGE *eku = a;
+ int i;
+ ASN1_OBJECT *obj;
+ char obj_tmp[80];
+ for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
+ obj = sk_ASN1_OBJECT_value(eku, i);
+ i2t_ASN1_OBJECT(obj_tmp, 80, obj);
+ X509V3_add_value(NULL, obj_tmp, &ext_list);
+ }
+ return ext_list;
+}
+
+static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval)
+{
+ EXTENDED_KEY_USAGE *extku;
+ char *extval;
+ ASN1_OBJECT *objtmp;
+ CONF_VALUE *val;
+ const int num = sk_CONF_VALUE_num(nval);
+ int i;
+
+ extku = sk_ASN1_OBJECT_new_reserve(NULL, num);
+ if (extku == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ sk_ASN1_OBJECT_free(extku);
+ return NULL;
+ }
+
+ for (i = 0; i < num; i++) {
+ val = sk_CONF_VALUE_value(nval, i);
+ if (val->value)
+ extval = val->value;
+ else
+ extval = val->name;
+ if ((objtmp = OBJ_txt2obj(extval, 0)) == NULL) {
+ sk_ASN1_OBJECT_pop_free(extku, ASN1_OBJECT_free);
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER,
+ "%s", extval);
+ return NULL;
+ }
+ sk_ASN1_OBJECT_push(extku, objtmp); /* no failure as it was reserved */
+ }
+ return extku;
+}
diff --git a/crypto/x509/v3_genn.c b/crypto/x509/v3_genn.c
new file mode 100644
index 000000000000..1f67bf2f63ab
--- /dev/null
+++ b/crypto/x509/v3_genn.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+
+ASN1_SEQUENCE(OTHERNAME) = {
+ ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT),
+ /* Maybe have a true ANY DEFINED BY later */
+ ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0)
+} ASN1_SEQUENCE_END(OTHERNAME)
+
+IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME)
+
+ASN1_SEQUENCE(EDIPARTYNAME) = {
+ /* DirectoryString is a CHOICE type so use explicit tagging */
+ ASN1_EXP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0),
+ ASN1_EXP(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1)
+} ASN1_SEQUENCE_END(EDIPARTYNAME)
+
+IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME)
+
+ASN1_CHOICE(GENERAL_NAME) = {
+ ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME),
+ ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL),
+ ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS),
+ /* Don't decode this */
+ ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400),
+ /* X509_NAME is a CHOICE type so use EXPLICIT */
+ ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME),
+ ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY),
+ ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, GEN_URI),
+ ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD),
+ ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID)
+} ASN1_CHOICE_END(GENERAL_NAME)
+
+IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAME)
+
+ASN1_ITEM_TEMPLATE(GENERAL_NAMES) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME)
+ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES)
+
+IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES)
+
+GENERAL_NAME *GENERAL_NAME_dup(const GENERAL_NAME *a)
+{
+ return (GENERAL_NAME *)ASN1_dup((i2d_of_void *)i2d_GENERAL_NAME,
+ (d2i_of_void *)d2i_GENERAL_NAME,
+ (char *)a);
+}
+
+static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b)
+{
+ int res;
+
+ if (a == NULL || b == NULL) {
+ /*
+ * Shouldn't be possible in a valid GENERAL_NAME, but we handle it
+ * anyway. OTHERNAME_cmp treats NULL != NULL so we do the same here
+ */
+ return -1;
+ }
+ if (a->nameAssigner == NULL && b->nameAssigner != NULL)
+ return -1;
+ if (a->nameAssigner != NULL && b->nameAssigner == NULL)
+ return 1;
+ /* If we get here then both have nameAssigner set, or both unset */
+ if (a->nameAssigner != NULL) {
+ res = ASN1_STRING_cmp(a->nameAssigner, b->nameAssigner);
+ if (res != 0)
+ return res;
+ }
+ /*
+ * partyName is required, so these should never be NULL. We treat it in
+ * the same way as the a == NULL || b == NULL case above
+ */
+ if (a->partyName == NULL || b->partyName == NULL)
+ return -1;
+
+ return ASN1_STRING_cmp(a->partyName, b->partyName);
+}
+
+/* Returns 0 if they are equal, != 0 otherwise. */
+int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b)
+{
+ int result = -1;
+
+ if (!a || !b || a->type != b->type)
+ return -1;
+ switch (a->type) {
+ case GEN_X400:
+ result = ASN1_STRING_cmp(a->d.x400Address, b->d.x400Address);
+ break;
+
+ case GEN_EDIPARTY:
+ result = edipartyname_cmp(a->d.ediPartyName, b->d.ediPartyName);
+ break;
+
+ case GEN_OTHERNAME:
+ result = OTHERNAME_cmp(a->d.otherName, b->d.otherName);
+ break;
+
+ case GEN_EMAIL:
+ case GEN_DNS:
+ case GEN_URI:
+ result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5);
+ break;
+
+ case GEN_DIRNAME:
+ result = X509_NAME_cmp(a->d.dirn, b->d.dirn);
+ break;
+
+ case GEN_IPADD:
+ result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip);
+ break;
+
+ case GEN_RID:
+ result = OBJ_cmp(a->d.rid, b->d.rid);
+ break;
+ }
+ return result;
+}
+
+/* Returns 0 if they are equal, != 0 otherwise. */
+int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b)
+{
+ int result = -1;
+
+ if (!a || !b)
+ return -1;
+ /* Check their type first. */
+ if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0)
+ return result;
+ /* Check the value. */
+ result = ASN1_TYPE_cmp(a->value, b->value);
+ return result;
+}
+
+void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
+{
+ switch (type) {
+ case GEN_X400:
+ a->d.x400Address = value;
+ break;
+
+ case GEN_EDIPARTY:
+ a->d.ediPartyName = value;
+ break;
+
+ case GEN_OTHERNAME:
+ a->d.otherName = value;
+ break;
+
+ case GEN_EMAIL:
+ case GEN_DNS:
+ case GEN_URI:
+ a->d.ia5 = value;
+ break;
+
+ case GEN_DIRNAME:
+ a->d.dirn = value;
+ break;
+
+ case GEN_IPADD:
+ a->d.ip = value;
+ break;
+
+ case GEN_RID:
+ a->d.rid = value;
+ break;
+ }
+ a->type = type;
+}
+
+void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype)
+{
+ if (ptype)
+ *ptype = a->type;
+ switch (a->type) {
+ case GEN_X400:
+ return a->d.x400Address;
+
+ case GEN_EDIPARTY:
+ return a->d.ediPartyName;
+
+ case GEN_OTHERNAME:
+ return a->d.otherName;
+
+ case GEN_EMAIL:
+ case GEN_DNS:
+ case GEN_URI:
+ return a->d.ia5;
+
+ case GEN_DIRNAME:
+ return a->d.dirn;
+
+ case GEN_IPADD:
+ return a->d.ip;
+
+ case GEN_RID:
+ return a->d.rid;
+
+ default:
+ return NULL;
+ }
+}
+
+int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
+ ASN1_OBJECT *oid, ASN1_TYPE *value)
+{
+ OTHERNAME *oth;
+ oth = OTHERNAME_new();
+ if (oth == NULL)
+ return 0;
+ ASN1_TYPE_free(oth->value);
+ oth->type_id = oid;
+ oth->value = value;
+ GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
+ return 1;
+}
+
+int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen,
+ ASN1_OBJECT **poid, ASN1_TYPE **pvalue)
+{
+ if (gen->type != GEN_OTHERNAME)
+ return 0;
+ if (poid)
+ *poid = gen->d.otherName->type_id;
+ if (pvalue)
+ *pvalue = gen->d.otherName->value;
+ return 1;
+}
diff --git a/crypto/x509/v3_ia5.c b/crypto/x509/v3_ia5.c
new file mode 100644
index 000000000000..6722b6c01f05
--- /dev/null
+++ b/crypto/x509/v3_ia5.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/asn1.h>
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include "ext_dat.h"
+
+const X509V3_EXT_METHOD ossl_v3_ns_ia5_list[8] = {
+ EXT_IA5STRING(NID_netscape_base_url),
+ EXT_IA5STRING(NID_netscape_revocation_url),
+ EXT_IA5STRING(NID_netscape_ca_revocation_url),
+ EXT_IA5STRING(NID_netscape_renewal_url),
+ EXT_IA5STRING(NID_netscape_ca_policy_url),
+ EXT_IA5STRING(NID_netscape_ssl_server_name),
+ EXT_IA5STRING(NID_netscape_comment),
+ EXT_END
+};
+
+char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5)
+{
+ char *tmp;
+
+ if (ia5 == NULL || ia5->length <= 0)
+ return NULL;
+ if ((tmp = OPENSSL_malloc(ia5->length + 1)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ memcpy(tmp, ia5->data, ia5->length);
+ tmp[ia5->length] = 0;
+ return tmp;
+}
+
+ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, const char *str)
+{
+ ASN1_IA5STRING *ia5;
+ if (str == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
+ return NULL;
+ }
+ if ((ia5 = ASN1_IA5STRING_new()) == NULL)
+ goto err;
+ if (!ASN1_STRING_set((ASN1_STRING *)ia5, str, strlen(str))) {
+ ASN1_IA5STRING_free(ia5);
+ return NULL;
+ }
+#ifdef CHARSET_EBCDIC
+ ebcdic2ascii(ia5->data, ia5->data, ia5->length);
+#endif /* CHARSET_EBCDIC */
+ return ia5;
+ err:
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+}
diff --git a/crypto/x509/v3_info.c b/crypto/x509/v3_info.c
new file mode 100644
index 000000000000..5f21ce11e7d5
--- /dev/null
+++ b/crypto/x509/v3_info.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509v3.h>
+#include "ext_dat.h"
+
+static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
+ *method, AUTHORITY_INFO_ACCESS
+ *ainfo, STACK_OF(CONF_VALUE)
+ *ret);
+static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
+ *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE)
+ *nval);
+
+const X509V3_EXT_METHOD ossl_v3_info = { NID_info_access, X509V3_EXT_MULTILINE,
+ ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
+ 0, 0, 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2V) i2v_AUTHORITY_INFO_ACCESS,
+ (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS,
+ 0, 0,
+ NULL
+};
+
+const X509V3_EXT_METHOD ossl_v3_sinfo = { NID_sinfo_access, X509V3_EXT_MULTILINE,
+ ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
+ 0, 0, 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2V) i2v_AUTHORITY_INFO_ACCESS,
+ (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS,
+ 0, 0,
+ NULL
+};
+
+ASN1_SEQUENCE(ACCESS_DESCRIPTION) = {
+ ASN1_SIMPLE(ACCESS_DESCRIPTION, method, ASN1_OBJECT),
+ ASN1_SIMPLE(ACCESS_DESCRIPTION, location, GENERAL_NAME)
+} ASN1_SEQUENCE_END(ACCESS_DESCRIPTION)
+
+IMPLEMENT_ASN1_FUNCTIONS(ACCESS_DESCRIPTION)
+
+ASN1_ITEM_TEMPLATE(AUTHORITY_INFO_ACCESS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, ACCESS_DESCRIPTION)
+ASN1_ITEM_TEMPLATE_END(AUTHORITY_INFO_ACCESS)
+
+IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS)
+
+static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(
+ X509V3_EXT_METHOD *method, AUTHORITY_INFO_ACCESS *ainfo,
+ STACK_OF(CONF_VALUE) *ret)
+{
+ ACCESS_DESCRIPTION *desc;
+ int i, nlen;
+ char objtmp[80], *ntmp;
+ CONF_VALUE *vtmp;
+ STACK_OF(CONF_VALUE) *tret = ret;
+
+ for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ainfo); i++) {
+ STACK_OF(CONF_VALUE) *tmp;
+
+ desc = sk_ACCESS_DESCRIPTION_value(ainfo, i);
+ tmp = i2v_GENERAL_NAME(method, desc->location, tret);
+ if (tmp == NULL)
+ goto err;
+ tret = tmp;
+ vtmp = sk_CONF_VALUE_value(tret, i);
+ i2t_ASN1_OBJECT(objtmp, sizeof(objtmp), desc->method);
+ nlen = strlen(objtmp) + 3 + strlen(vtmp->name) + 1;
+ ntmp = OPENSSL_malloc(nlen);
+ if (ntmp == NULL)
+ goto err;
+ BIO_snprintf(ntmp, nlen, "%s - %s", objtmp, vtmp->name);
+ OPENSSL_free(vtmp->name);
+ vtmp->name = ntmp;
+ }
+ if (ret == NULL && tret == NULL)
+ return sk_CONF_VALUE_new_null();
+
+ return tret;
+ err:
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ if (ret == NULL && tret != NULL)
+ sk_CONF_VALUE_pop_free(tret, X509V3_conf_free);
+ return NULL;
+}
+
+static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
+ *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE)
+ *nval)
+{
+ AUTHORITY_INFO_ACCESS *ainfo = NULL;
+ CONF_VALUE *cnf, ctmp;
+ ACCESS_DESCRIPTION *acc;
+ int i;
+ const int num = sk_CONF_VALUE_num(nval);
+ char *objtmp, *ptmp;
+
+ if ((ainfo = sk_ACCESS_DESCRIPTION_new_reserve(NULL, num)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for (i = 0; i < num; i++) {
+ cnf = sk_CONF_VALUE_value(nval, i);
+ if ((acc = ACCESS_DESCRIPTION_new()) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ sk_ACCESS_DESCRIPTION_push(ainfo, acc); /* Cannot fail due to reserve */
+ ptmp = strchr(cnf->name, ';');
+ if (ptmp == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_SYNTAX);
+ goto err;
+ }
+ ctmp.name = ptmp + 1;
+ ctmp.value = cnf->value;
+ if (!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0))
+ goto err;
+ if ((objtmp = OPENSSL_strndup(cnf->name, ptmp - cnf->name)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ acc->method = OBJ_txt2obj(objtmp, 0);
+ if (!acc->method) {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_BAD_OBJECT,
+ "value=%s", objtmp);
+ OPENSSL_free(objtmp);
+ goto err;
+ }
+ OPENSSL_free(objtmp);
+ }
+ return ainfo;
+ err:
+ sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free);
+ return NULL;
+}
+
+int i2a_ACCESS_DESCRIPTION(BIO *bp, const ACCESS_DESCRIPTION *a)
+{
+ i2a_ASN1_OBJECT(bp, a->method);
+ return 2;
+}
diff --git a/crypto/x509/v3_int.c b/crypto/x509/v3_int.c
new file mode 100644
index 000000000000..dae26a5ba9d7
--- /dev/null
+++ b/crypto/x509/v3_int.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/x509v3.h>
+#include "ext_dat.h"
+
+const X509V3_EXT_METHOD ossl_v3_crl_num = {
+ NID_crl_number, 0, ASN1_ITEM_ref(ASN1_INTEGER),
+ 0, 0, 0, 0,
+ (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
+ 0,
+ 0, 0, 0, 0, NULL
+};
+
+const X509V3_EXT_METHOD ossl_v3_delta_crl = {
+ NID_delta_crl, 0, ASN1_ITEM_ref(ASN1_INTEGER),
+ 0, 0, 0, 0,
+ (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
+ 0,
+ 0, 0, 0, 0, NULL
+};
+
+static void *s2i_asn1_int(X509V3_EXT_METHOD *meth, X509V3_CTX *ctx,
+ const char *value)
+{
+ return s2i_ASN1_INTEGER(meth, value);
+}
+
+const X509V3_EXT_METHOD ossl_v3_inhibit_anyp = {
+ NID_inhibit_any_policy, 0, ASN1_ITEM_ref(ASN1_INTEGER),
+ 0, 0, 0, 0,
+ (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
+ (X509V3_EXT_S2I)s2i_asn1_int,
+ 0, 0, 0, 0, NULL
+};
diff --git a/crypto/x509/v3_ist.c b/crypto/x509/v3_ist.c
new file mode 100644
index 000000000000..0de281f66871
--- /dev/null
+++ b/crypto/x509/v3_ist.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509v3.h>
+#include "ext_dat.h"
+
+/*
+ * Issuer Sign Tool (1.2.643.100.112) The name of the tool used to signs the subject (ASN1_SEQUENCE)
+ * This extention is required to obtain the status of a qualified certificate at Russian Federation.
+ * RFC-style description is available here: https://tools.ietf.org/html/draft-deremin-rfc4491-bis-04#section-5
+ * Russian Federal Law 63 "Digital Sign" is available here: http://www.consultant.ru/document/cons_doc_LAW_112701/
+ */
+
+ASN1_SEQUENCE(ISSUER_SIGN_TOOL) = {
+ ASN1_SIMPLE(ISSUER_SIGN_TOOL, signTool, ASN1_UTF8STRING),
+ ASN1_SIMPLE(ISSUER_SIGN_TOOL, cATool, ASN1_UTF8STRING),
+ ASN1_SIMPLE(ISSUER_SIGN_TOOL, signToolCert, ASN1_UTF8STRING),
+ ASN1_SIMPLE(ISSUER_SIGN_TOOL, cAToolCert, ASN1_UTF8STRING)
+} ASN1_SEQUENCE_END(ISSUER_SIGN_TOOL)
+
+IMPLEMENT_ASN1_FUNCTIONS(ISSUER_SIGN_TOOL)
+
+
+static ISSUER_SIGN_TOOL *v2i_issuer_sign_tool(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval)
+{
+ ISSUER_SIGN_TOOL *ist = ISSUER_SIGN_TOOL_new();
+ int i;
+
+ if (ist == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for (i = 0; i < sk_CONF_VALUE_num(nval); ++i) {
+ CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
+
+ if (cnf == NULL) {
+ continue;
+ }
+ if (strcmp(cnf->name, "signTool") == 0) {
+ ist->signTool = ASN1_UTF8STRING_new();
+ if (ist->signTool == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ ISSUER_SIGN_TOOL_free(ist);
+ return NULL;
+ }
+ ASN1_STRING_set(ist->signTool, cnf->value, strlen(cnf->value));
+ } else if (strcmp(cnf->name, "cATool") == 0) {
+ ist->cATool = ASN1_UTF8STRING_new();
+ if (ist->cATool == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ ISSUER_SIGN_TOOL_free(ist);
+ return NULL;
+ }
+ ASN1_STRING_set(ist->cATool, cnf->value, strlen(cnf->value));
+ } else if (strcmp(cnf->name, "signToolCert") == 0) {
+ ist->signToolCert = ASN1_UTF8STRING_new();
+ if (ist->signToolCert == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ ISSUER_SIGN_TOOL_free(ist);
+ return NULL;
+ }
+ ASN1_STRING_set(ist->signToolCert, cnf->value, strlen(cnf->value));
+ } else if (strcmp(cnf->name, "cAToolCert") == 0) {
+ ist->cAToolCert = ASN1_UTF8STRING_new();
+ if (ist->cAToolCert == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ ISSUER_SIGN_TOOL_free(ist);
+ return NULL;
+ }
+ ASN1_STRING_set(ist->cAToolCert, cnf->value, strlen(cnf->value));
+ } else {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_INVALID_ARGUMENT);
+ ISSUER_SIGN_TOOL_free(ist);
+ return NULL;
+ }
+ }
+ return ist;
+}
+
+static int i2r_issuer_sign_tool(X509V3_EXT_METHOD *method,
+ ISSUER_SIGN_TOOL *ist, BIO *out,
+ int indent)
+{
+ int new_line = 0;
+
+ if (ist == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ if (ist->signTool != NULL) {
+ if (new_line == 1) {
+ BIO_write(out, "\n", 1);
+ }
+ BIO_printf(out, "%*ssignTool : ", indent, "");
+ BIO_write(out, ist->signTool->data, ist->signTool->length);
+ new_line = 1;
+ }
+ if (ist->cATool != NULL) {
+ if (new_line == 1) {
+ BIO_write(out, "\n", 1);
+ }
+ BIO_printf(out, "%*scATool : ", indent, "");
+ BIO_write(out, ist->cATool->data, ist->cATool->length);
+ new_line = 1;
+ }
+ if (ist->signToolCert != NULL) {
+ if (new_line == 1) {
+ BIO_write(out, "\n", 1);
+ }
+ BIO_printf(out, "%*ssignToolCert: ", indent, "");
+ BIO_write(out, ist->signToolCert->data, ist->signToolCert->length);
+ new_line = 1;
+ }
+ if (ist->cAToolCert != NULL) {
+ if (new_line == 1) {
+ BIO_write(out, "\n", 1);
+ }
+ BIO_printf(out, "%*scAToolCert : ", indent, "");
+ BIO_write(out, ist->cAToolCert->data, ist->cAToolCert->length);
+ new_line = 1;
+ }
+ return 1;
+}
+
+const X509V3_EXT_METHOD ossl_v3_issuer_sign_tool = {
+ NID_issuerSignTool, /* nid */
+ X509V3_EXT_MULTILINE, /* flags */
+ ASN1_ITEM_ref(ISSUER_SIGN_TOOL), /* template */
+ 0, 0, 0, 0, /* old functions, ignored */
+ 0, /* i2s */
+ 0, /* s2i */
+ 0, /* i2v */
+ (X509V3_EXT_V2I)v2i_issuer_sign_tool, /* v2i */
+ (X509V3_EXT_I2R)i2r_issuer_sign_tool, /* i2r */
+ 0, /* r2i */
+ NULL /* extension-specific data */
+};
diff --git a/crypto/x509/v3_lib.c b/crypto/x509/v3_lib.c
new file mode 100644
index 000000000000..5ffeb75d9f5b
--- /dev/null
+++ b/crypto/x509/v3_lib.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* X509 v3 extension utilities */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+
+#include "ext_dat.h"
+
+static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL;
+
+static int ext_cmp(const X509V3_EXT_METHOD *const *a,
+ const X509V3_EXT_METHOD *const *b);
+static void ext_list_free(X509V3_EXT_METHOD *ext);
+
+int X509V3_EXT_add(X509V3_EXT_METHOD *ext)
+{
+ if (ext_list == NULL
+ && (ext_list = sk_X509V3_EXT_METHOD_new(ext_cmp)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ return 1;
+}
+
+static int ext_cmp(const X509V3_EXT_METHOD *const *a,
+ const X509V3_EXT_METHOD *const *b)
+{
+ return ((*a)->ext_nid - (*b)->ext_nid);
+}
+
+DECLARE_OBJ_BSEARCH_CMP_FN(const X509V3_EXT_METHOD *,
+ const X509V3_EXT_METHOD *, ext);
+IMPLEMENT_OBJ_BSEARCH_CMP_FN(const X509V3_EXT_METHOD *,
+ const X509V3_EXT_METHOD *, ext);
+
+#include "standard_exts.h"
+
+const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid)
+{
+ X509V3_EXT_METHOD tmp;
+ const X509V3_EXT_METHOD *t = &tmp, *const *ret;
+ int idx;
+
+ if (nid < 0)
+ return NULL;
+ tmp.ext_nid = nid;
+ ret = OBJ_bsearch_ext(&t, standard_exts, STANDARD_EXTENSION_COUNT);
+ if (ret)
+ return *ret;
+ if (!ext_list)
+ return NULL;
+ idx = sk_X509V3_EXT_METHOD_find(ext_list, &tmp);
+ return sk_X509V3_EXT_METHOD_value(ext_list, idx);
+}
+
+const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext)
+{
+ int nid;
+ if ((nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext))) == NID_undef)
+ return NULL;
+ return X509V3_EXT_get_nid(nid);
+}
+
+int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist)
+{
+ for (; extlist->ext_nid != -1; extlist++)
+ if (!X509V3_EXT_add(extlist))
+ return 0;
+ return 1;
+}
+
+int X509V3_EXT_add_alias(int nid_to, int nid_from)
+{
+ const X509V3_EXT_METHOD *ext;
+ X509V3_EXT_METHOD *tmpext;
+
+ if ((ext = X509V3_EXT_get_nid(nid_from)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_NOT_FOUND);
+ return 0;
+ }
+ if ((tmpext = OPENSSL_malloc(sizeof(*tmpext))) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ *tmpext = *ext;
+ tmpext->ext_nid = nid_to;
+ tmpext->ext_flags |= X509V3_EXT_DYNAMIC;
+ return X509V3_EXT_add(tmpext);
+}
+
+void X509V3_EXT_cleanup(void)
+{
+ sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free);
+ ext_list = NULL;
+}
+
+static void ext_list_free(X509V3_EXT_METHOD *ext)
+{
+ if (ext->ext_flags & X509V3_EXT_DYNAMIC)
+ OPENSSL_free(ext);
+}
+
+/*
+ * Legacy function: we don't need to add standard extensions any more because
+ * they are now kept in ext_dat.h.
+ */
+
+int X509V3_add_standard_extensions(void)
+{
+ return 1;
+}
+
+/* Return an extension internal structure */
+
+void *X509V3_EXT_d2i(X509_EXTENSION *ext)
+{
+ const X509V3_EXT_METHOD *method;
+ const unsigned char *p;
+ ASN1_STRING *extvalue;
+ int extlen;
+
+ if ((method = X509V3_EXT_get(ext)) == NULL)
+ return NULL;
+ extvalue = X509_EXTENSION_get_data(ext);
+ p = ASN1_STRING_get0_data(extvalue);
+ extlen = ASN1_STRING_length(extvalue);
+ if (method->it)
+ return ASN1_item_d2i(NULL, &p, extlen, ASN1_ITEM_ptr(method->it));
+ return method->d2i(NULL, &p, extlen);
+}
+
+/*-
+ * Get critical flag and decoded version of extension from a NID.
+ * The "idx" variable returns the last found extension and can
+ * be used to retrieve multiple extensions of the same NID.
+ * However multiple extensions with the same NID is usually
+ * due to a badly encoded certificate so if idx is NULL we
+ * choke if multiple extensions exist.
+ * The "crit" variable is set to the critical value.
+ * The return value is the decoded extension or NULL on
+ * error. The actual error can have several different causes,
+ * the value of *crit reflects the cause:
+ * >= 0, extension found but not decoded (reflects critical value).
+ * -1 extension not found.
+ * -2 extension occurs more than once.
+ */
+
+void *X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *x, int nid, int *crit,
+ int *idx)
+{
+ int lastpos, i;
+ X509_EXTENSION *ex, *found_ex = NULL;
+
+ if (!x) {
+ if (idx)
+ *idx = -1;
+ if (crit)
+ *crit = -1;
+ return NULL;
+ }
+ if (idx)
+ lastpos = *idx + 1;
+ else
+ lastpos = 0;
+ if (lastpos < 0)
+ lastpos = 0;
+ for (i = lastpos; i < sk_X509_EXTENSION_num(x); i++) {
+ ex = sk_X509_EXTENSION_value(x, i);
+ if (OBJ_obj2nid(X509_EXTENSION_get_object(ex)) == nid) {
+ if (idx) {
+ *idx = i;
+ found_ex = ex;
+ break;
+ } else if (found_ex) {
+ /* Found more than one */
+ if (crit)
+ *crit = -2;
+ return NULL;
+ }
+ found_ex = ex;
+ }
+ }
+ if (found_ex) {
+ /* Found it */
+ if (crit)
+ *crit = X509_EXTENSION_get_critical(found_ex);
+ return X509V3_EXT_d2i(found_ex);
+ }
+
+ /* Extension not found */
+ if (idx)
+ *idx = -1;
+ if (crit)
+ *crit = -1;
+ return NULL;
+}
+
+/*
+ * This function is a general extension append, replace and delete utility.
+ * The precise operation is governed by the 'flags' value. The 'crit' and
+ * 'value' arguments (if relevant) are the extensions internal structure.
+ */
+
+int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
+ int crit, unsigned long flags)
+{
+ int errcode, extidx = -1;
+ X509_EXTENSION *ext = NULL, *extmp;
+ STACK_OF(X509_EXTENSION) *ret = NULL;
+ unsigned long ext_op = flags & X509V3_ADD_OP_MASK;
+
+ /*
+ * If appending we don't care if it exists, otherwise look for existing
+ * extension.
+ */
+ if (ext_op != X509V3_ADD_APPEND)
+ extidx = X509v3_get_ext_by_NID(*x, nid, -1);
+
+ /* See if extension exists */
+ if (extidx >= 0) {
+ /* If keep existing, nothing to do */
+ if (ext_op == X509V3_ADD_KEEP_EXISTING)
+ return 1;
+ /* If default then its an error */
+ if (ext_op == X509V3_ADD_DEFAULT) {
+ errcode = X509V3_R_EXTENSION_EXISTS;
+ goto err;
+ }
+ /* If delete, just delete it */
+ if (ext_op == X509V3_ADD_DELETE) {
+ extmp = sk_X509_EXTENSION_delete(*x, extidx);
+ if (extmp == NULL)
+ return -1;
+ X509_EXTENSION_free(extmp);
+ return 1;
+ }
+ } else {
+ /*
+ * If replace existing or delete, error since extension must exist
+ */
+ if ((ext_op == X509V3_ADD_REPLACE_EXISTING) ||
+ (ext_op == X509V3_ADD_DELETE)) {
+ errcode = X509V3_R_EXTENSION_NOT_FOUND;
+ goto err;
+ }
+ }
+
+ /*
+ * If we get this far then we have to create an extension: could have
+ * some flags for alternative encoding schemes...
+ */
+
+ ext = X509V3_EXT_i2d(nid, crit, value);
+
+ if (!ext) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_ERROR_CREATING_EXTENSION);
+ return 0;
+ }
+
+ /* If extension exists replace it.. */
+ if (extidx >= 0) {
+ extmp = sk_X509_EXTENSION_value(*x, extidx);
+ X509_EXTENSION_free(extmp);
+ if (!sk_X509_EXTENSION_set(*x, extidx, ext))
+ return -1;
+ return 1;
+ }
+
+ ret = *x;
+ if (*x == NULL
+ && (ret = sk_X509_EXTENSION_new_null()) == NULL)
+ goto m_fail;
+ if (!sk_X509_EXTENSION_push(ret, ext))
+ goto m_fail;
+
+ *x = ret;
+ return 1;
+
+ m_fail:
+ /* ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); */
+ if (ret != *x)
+ sk_X509_EXTENSION_free(ret);
+ X509_EXTENSION_free(ext);
+ return -1;
+
+ err:
+ if (!(flags & X509V3_ADD_SILENT))
+ ERR_raise(ERR_LIB_X509V3, errcode);
+ return 0;
+}
diff --git a/crypto/x509/v3_ncons.c b/crypto/x509/v3_ncons.c
new file mode 100644
index 000000000000..a51354e7fc4c
--- /dev/null
+++ b/crypto/x509/v3_ncons.c
@@ -0,0 +1,834 @@
+/*
+ * Copyright 2003-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/cryptlib.h"
+#include "internal/numbers.h"
+#include <stdio.h>
+#include "crypto/asn1.h"
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include <openssl/bn.h>
+
+#include "crypto/x509.h"
+#include "crypto/punycode.h"
+#include "ext_dat.h"
+
+static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval);
+static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a,
+ BIO *bp, int ind);
+static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method,
+ STACK_OF(GENERAL_SUBTREE) *trees, BIO *bp,
+ int ind, const char *name);
+static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip);
+
+static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc);
+static int nc_match_single(int effective_type, GENERAL_NAME *sub,
+ GENERAL_NAME *gen);
+static int nc_dn(const X509_NAME *sub, const X509_NAME *nm);
+static int nc_dns(ASN1_IA5STRING *sub, ASN1_IA5STRING *dns);
+static int nc_email(ASN1_IA5STRING *sub, ASN1_IA5STRING *eml);
+static int nc_email_eai(ASN1_TYPE *emltype, ASN1_IA5STRING *base);
+static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base);
+static int nc_ip(ASN1_OCTET_STRING *ip, ASN1_OCTET_STRING *base);
+
+const X509V3_EXT_METHOD ossl_v3_name_constraints = {
+ NID_name_constraints, 0,
+ ASN1_ITEM_ref(NAME_CONSTRAINTS),
+ 0, 0, 0, 0,
+ 0, 0,
+ 0, v2i_NAME_CONSTRAINTS,
+ i2r_NAME_CONSTRAINTS, 0,
+ NULL
+};
+
+ASN1_SEQUENCE(GENERAL_SUBTREE) = {
+ ASN1_SIMPLE(GENERAL_SUBTREE, base, GENERAL_NAME),
+ ASN1_IMP_OPT(GENERAL_SUBTREE, minimum, ASN1_INTEGER, 0),
+ ASN1_IMP_OPT(GENERAL_SUBTREE, maximum, ASN1_INTEGER, 1)
+} ASN1_SEQUENCE_END(GENERAL_SUBTREE)
+
+ASN1_SEQUENCE(NAME_CONSTRAINTS) = {
+ ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, permittedSubtrees,
+ GENERAL_SUBTREE, 0),
+ ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, excludedSubtrees,
+ GENERAL_SUBTREE, 1),
+} ASN1_SEQUENCE_END(NAME_CONSTRAINTS)
+
+
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
+
+
+#define IA5_OFFSET_LEN(ia5base, offset) \
+ ((ia5base)->length - ((unsigned char *)(offset) - (ia5base)->data))
+
+/* Like memchr but for ASN1_IA5STRING. Additionally you can specify the
+ * starting point to search from
+ */
+# define ia5memchr(str, start, c) memchr(start, c, IA5_OFFSET_LEN(str, start))
+
+/* Like memrrchr but for ASN1_IA5STRING */
+static char *ia5memrchr(ASN1_IA5STRING *str, int c)
+{
+ int i;
+
+ for (i = str->length; i > 0 && str->data[i - 1] != c; i--);
+
+ if (i == 0)
+ return NULL;
+
+ return (char *)&str->data[i - 1];
+}
+
+/*
+ * We cannot use strncasecmp here because that applies locale specific rules. It
+ * also doesn't work with ASN1_STRINGs that may have embedded NUL characters.
+ * For example in Turkish 'I' is not the uppercase character for 'i'. We need to
+ * do a simple ASCII case comparison ignoring the locale (that is why we use
+ * numeric constants below).
+ */
+static int ia5ncasecmp(const char *s1, const char *s2, size_t n)
+{
+ for (; n > 0; n--, s1++, s2++) {
+ if (*s1 != *s2) {
+ unsigned char c1 = (unsigned char)*s1, c2 = (unsigned char)*s2;
+
+ /* Convert to lower case */
+ if (c1 >= 0x41 /* A */ && c1 <= 0x5A /* Z */)
+ c1 += 0x20;
+ if (c2 >= 0x41 /* A */ && c2 <= 0x5A /* Z */)
+ c2 += 0x20;
+
+ if (c1 == c2)
+ continue;
+
+ if (c1 < c2)
+ return -1;
+
+ /* c1 > c2 */
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+{
+ int i;
+ CONF_VALUE tval, *val;
+ STACK_OF(GENERAL_SUBTREE) **ptree = NULL;
+ NAME_CONSTRAINTS *ncons = NULL;
+ GENERAL_SUBTREE *sub = NULL;
+
+ ncons = NAME_CONSTRAINTS_new();
+ if (ncons == NULL)
+ goto memerr;
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ val = sk_CONF_VALUE_value(nval, i);
+ if (strncmp(val->name, "permitted", 9) == 0 && val->name[9]) {
+ ptree = &ncons->permittedSubtrees;
+ tval.name = val->name + 10;
+ } else if (strncmp(val->name, "excluded", 8) == 0 && val->name[8]) {
+ ptree = &ncons->excludedSubtrees;
+ tval.name = val->name + 9;
+ } else {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_SYNTAX);
+ goto err;
+ }
+ tval.value = val->value;
+ sub = GENERAL_SUBTREE_new();
+ if (sub == NULL)
+ goto memerr;
+ if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1))
+ goto err;
+ if (*ptree == NULL)
+ *ptree = sk_GENERAL_SUBTREE_new_null();
+ if (*ptree == NULL || !sk_GENERAL_SUBTREE_push(*ptree, sub))
+ goto memerr;
+ sub = NULL;
+ }
+
+ return ncons;
+
+ memerr:
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ err:
+ NAME_CONSTRAINTS_free(ncons);
+ GENERAL_SUBTREE_free(sub);
+
+ return NULL;
+}
+
+static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a,
+ BIO *bp, int ind)
+{
+ NAME_CONSTRAINTS *ncons = a;
+ do_i2r_name_constraints(method, ncons->permittedSubtrees,
+ bp, ind, "Permitted");
+ if (ncons->permittedSubtrees && ncons->excludedSubtrees)
+ BIO_puts(bp, "\n");
+ do_i2r_name_constraints(method, ncons->excludedSubtrees,
+ bp, ind, "Excluded");
+ return 1;
+}
+
+static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method,
+ STACK_OF(GENERAL_SUBTREE) *trees,
+ BIO *bp, int ind, const char *name)
+{
+ GENERAL_SUBTREE *tree;
+ int i;
+ if (sk_GENERAL_SUBTREE_num(trees) > 0)
+ BIO_printf(bp, "%*s%s:\n", ind, "", name);
+ for (i = 0; i < sk_GENERAL_SUBTREE_num(trees); i++) {
+ if (i > 0)
+ BIO_puts(bp, "\n");
+ tree = sk_GENERAL_SUBTREE_value(trees, i);
+ BIO_printf(bp, "%*s", ind + 2, "");
+ if (tree->base->type == GEN_IPADD)
+ print_nc_ipadd(bp, tree->base->d.ip);
+ else
+ GENERAL_NAME_print(bp, tree->base);
+ }
+ return 1;
+}
+
+static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip)
+{
+ /* ip->length should be 8 or 32 and len1 == len2 == 4 or len1 == len2 == 16 */
+ int len1 = ip->length >= 16 ? 16 : ip->length >= 4 ? 4 : ip->length;
+ int len2 = ip->length - len1;
+ char *ip1 = ossl_ipaddr_to_asc(ip->data, len1);
+ char *ip2 = ossl_ipaddr_to_asc(ip->data + len1, len2);
+ int ret = ip1 != NULL && ip2 != NULL
+ && BIO_printf(bp, "IP:%s/%s", ip1, ip2) > 0;
+
+ OPENSSL_free(ip1);
+ OPENSSL_free(ip2);
+ return ret;
+}
+
+#define NAME_CHECK_MAX (1 << 20)
+
+static int add_lengths(int *out, int a, int b)
+{
+ /* sk_FOO_num(NULL) returns -1 but is effectively 0 when iterating. */
+ if (a < 0)
+ a = 0;
+ if (b < 0)
+ b = 0;
+
+ if (a > INT_MAX - b)
+ return 0;
+ *out = a + b;
+ return 1;
+}
+
+/*-
+ * Check a certificate conforms to a specified set of constraints.
+ * Return values:
+ * X509_V_OK: All constraints obeyed.
+ * X509_V_ERR_PERMITTED_VIOLATION: Permitted subtree violation.
+ * X509_V_ERR_EXCLUDED_VIOLATION: Excluded subtree violation.
+ * X509_V_ERR_SUBTREE_MINMAX: Min or max values present and matching type.
+ * X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: Unsupported constraint type.
+ * X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: bad unsupported constraint syntax.
+ * X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: bad or unsupported syntax of name
+ */
+
+int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc)
+{
+ int r, i, name_count, constraint_count;
+ X509_NAME *nm;
+
+ nm = X509_get_subject_name(x);
+
+ /*
+ * Guard against certificates with an excessive number of names or
+ * constraints causing a computationally expensive name constraints check.
+ */
+ if (!add_lengths(&name_count, X509_NAME_entry_count(nm),
+ sk_GENERAL_NAME_num(x->altname))
+ || !add_lengths(&constraint_count,
+ sk_GENERAL_SUBTREE_num(nc->permittedSubtrees),
+ sk_GENERAL_SUBTREE_num(nc->excludedSubtrees))
+ || (name_count > 0 && constraint_count > NAME_CHECK_MAX / name_count))
+ return X509_V_ERR_UNSPECIFIED;
+
+ if (X509_NAME_entry_count(nm) > 0) {
+ GENERAL_NAME gntmp;
+ gntmp.type = GEN_DIRNAME;
+ gntmp.d.directoryName = nm;
+
+ r = nc_match(&gntmp, nc);
+
+ if (r != X509_V_OK)
+ return r;
+
+ gntmp.type = GEN_EMAIL;
+
+ /* Process any email address attributes in subject name */
+
+ for (i = -1;;) {
+ const X509_NAME_ENTRY *ne;
+
+ i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i);
+ if (i == -1)
+ break;
+ ne = X509_NAME_get_entry(nm, i);
+ gntmp.d.rfc822Name = X509_NAME_ENTRY_get_data(ne);
+ if (gntmp.d.rfc822Name->type != V_ASN1_IA5STRING)
+ return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+
+ r = nc_match(&gntmp, nc);
+
+ if (r != X509_V_OK)
+ return r;
+ }
+
+ }
+
+ for (i = 0; i < sk_GENERAL_NAME_num(x->altname); i++) {
+ GENERAL_NAME *gen = sk_GENERAL_NAME_value(x->altname, i);
+ r = nc_match(gen, nc);
+ if (r != X509_V_OK)
+ return r;
+ }
+
+ return X509_V_OK;
+
+}
+
+static int cn2dnsid(ASN1_STRING *cn, unsigned char **dnsid, size_t *idlen)
+{
+ int utf8_length;
+ unsigned char *utf8_value;
+ int i;
+ int isdnsname = 0;
+
+ /* Don't leave outputs uninitialized */
+ *dnsid = NULL;
+ *idlen = 0;
+
+ /*-
+ * Per RFC 6125, DNS-IDs representing internationalized domain names appear
+ * in certificates in A-label encoded form:
+ *
+ * https://tools.ietf.org/html/rfc6125#section-6.4.2
+ *
+ * The same applies to CNs which are intended to represent DNS names.
+ * However, while in the SAN DNS-IDs are IA5Strings, as CNs they may be
+ * needlessly encoded in 16-bit Unicode. We perform a conversion to UTF-8
+ * to ensure that we get an ASCII representation of any CNs that are
+ * representable as ASCII, but just not encoded as ASCII. The UTF-8 form
+ * may contain some non-ASCII octets, and that's fine, such CNs are not
+ * valid legacy DNS names.
+ *
+ * Note, 'int' is the return type of ASN1_STRING_to_UTF8() so that's what
+ * we must use for 'utf8_length'.
+ */
+ if ((utf8_length = ASN1_STRING_to_UTF8(&utf8_value, cn)) < 0)
+ return X509_V_ERR_OUT_OF_MEM;
+
+ /*
+ * Some certificates have had names that include a *trailing* NUL byte.
+ * Remove these harmless NUL characters. They would otherwise yield false
+ * alarms with the following embedded NUL check.
+ */
+ while (utf8_length > 0 && utf8_value[utf8_length - 1] == '\0')
+ --utf8_length;
+
+ /* Reject *embedded* NULs */
+ if (memchr(utf8_value, 0, utf8_length) != NULL) {
+ OPENSSL_free(utf8_value);
+ return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+ }
+
+ /*
+ * XXX: Deviation from strict DNS name syntax, also check names with '_'
+ * Check DNS name syntax, any '-' or '.' must be internal,
+ * and on either side of each '.' we can't have a '-' or '.'.
+ *
+ * If the name has just one label, we don't consider it a DNS name. This
+ * means that "CN=sometld" cannot be precluded by DNS name constraints, but
+ * that is not a problem.
+ */
+ for (i = 0; i < utf8_length; ++i) {
+ unsigned char c = utf8_value[i];
+
+ if ((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')
+ || c == '_')
+ continue;
+
+ /* Dot and hyphen cannot be first or last. */
+ if (i > 0 && i < utf8_length - 1) {
+ if (c == '-')
+ continue;
+ /*
+ * Next to a dot the preceding and following characters must not be
+ * another dot or a hyphen. Otherwise, record that the name is
+ * plausible, since it has two or more labels.
+ */
+ if (c == '.'
+ && utf8_value[i + 1] != '.'
+ && utf8_value[i - 1] != '-'
+ && utf8_value[i + 1] != '-') {
+ isdnsname = 1;
+ continue;
+ }
+ }
+ isdnsname = 0;
+ break;
+ }
+
+ if (isdnsname) {
+ *dnsid = utf8_value;
+ *idlen = (size_t)utf8_length;
+ return X509_V_OK;
+ }
+ OPENSSL_free(utf8_value);
+ return X509_V_OK;
+}
+
+/*
+ * Check CN against DNS-ID name constraints.
+ */
+int NAME_CONSTRAINTS_check_CN(X509 *x, NAME_CONSTRAINTS *nc)
+{
+ int r, i;
+ const X509_NAME *nm = X509_get_subject_name(x);
+ ASN1_STRING stmp;
+ GENERAL_NAME gntmp;
+
+ stmp.flags = 0;
+ stmp.type = V_ASN1_IA5STRING;
+ gntmp.type = GEN_DNS;
+ gntmp.d.dNSName = &stmp;
+
+ /* Process any commonName attributes in subject name */
+
+ for (i = -1;;) {
+ X509_NAME_ENTRY *ne;
+ ASN1_STRING *cn;
+ unsigned char *idval;
+ size_t idlen;
+
+ i = X509_NAME_get_index_by_NID(nm, NID_commonName, i);
+ if (i == -1)
+ break;
+ ne = X509_NAME_get_entry(nm, i);
+ cn = X509_NAME_ENTRY_get_data(ne);
+
+ /* Only process attributes that look like host names */
+ if ((r = cn2dnsid(cn, &idval, &idlen)) != X509_V_OK)
+ return r;
+ if (idlen == 0)
+ continue;
+
+ stmp.length = idlen;
+ stmp.data = idval;
+ r = nc_match(&gntmp, nc);
+ OPENSSL_free(idval);
+ if (r != X509_V_OK)
+ return r;
+ }
+ return X509_V_OK;
+}
+
+/*
+ * Return nonzero if the GeneralSubtree has valid 'minimum' field
+ * (must be absent or 0) and valid 'maximum' field (must be absent).
+ */
+static int nc_minmax_valid(GENERAL_SUBTREE *sub) {
+ BIGNUM *bn = NULL;
+ int ok = 1;
+
+ if (sub->maximum)
+ ok = 0;
+
+ if (sub->minimum) {
+ bn = ASN1_INTEGER_to_BN(sub->minimum, NULL);
+ if (bn == NULL || !BN_is_zero(bn))
+ ok = 0;
+ BN_free(bn);
+ }
+
+ return ok;
+}
+
+static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc)
+{
+ GENERAL_SUBTREE *sub;
+ int i, r, match = 0;
+ int effective_type = gen->type;
+
+ /*
+ * We need to compare not gen->type field but an "effective" type because
+ * the otherName field may contain EAI email address treated specially
+ * according to RFC 8398, section 6
+ */
+ if (effective_type == GEN_OTHERNAME &&
+ (OBJ_obj2nid(gen->d.otherName->type_id) == NID_id_on_SmtpUTF8Mailbox)) {
+ effective_type = GEN_EMAIL;
+ }
+
+ /*
+ * Permitted subtrees: if any subtrees exist of matching the type at
+ * least one subtree must match.
+ */
+
+ for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++) {
+ sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i);
+ if (effective_type != sub->base->type
+ || (effective_type == GEN_OTHERNAME &&
+ OBJ_cmp(gen->d.otherName->type_id,
+ sub->base->d.otherName->type_id) != 0))
+ continue;
+ if (!nc_minmax_valid(sub))
+ return X509_V_ERR_SUBTREE_MINMAX;
+ /* If we already have a match don't bother trying any more */
+ if (match == 2)
+ continue;
+ if (match == 0)
+ match = 1;
+ r = nc_match_single(effective_type, gen, sub->base);
+ if (r == X509_V_OK)
+ match = 2;
+ else if (r != X509_V_ERR_PERMITTED_VIOLATION)
+ return r;
+ }
+
+ if (match == 1)
+ return X509_V_ERR_PERMITTED_VIOLATION;
+
+ /* Excluded subtrees: must not match any of these */
+
+ for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++) {
+ sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i);
+ if (effective_type != sub->base->type
+ || (effective_type == GEN_OTHERNAME &&
+ OBJ_cmp(gen->d.otherName->type_id,
+ sub->base->d.otherName->type_id) != 0))
+ continue;
+ if (!nc_minmax_valid(sub))
+ return X509_V_ERR_SUBTREE_MINMAX;
+
+ r = nc_match_single(effective_type, gen, sub->base);
+ if (r == X509_V_OK)
+ return X509_V_ERR_EXCLUDED_VIOLATION;
+ else if (r != X509_V_ERR_PERMITTED_VIOLATION)
+ return r;
+
+ }
+
+ return X509_V_OK;
+
+}
+
+static int nc_match_single(int effective_type, GENERAL_NAME *gen,
+ GENERAL_NAME *base)
+{
+ switch (gen->type) {
+ case GEN_OTHERNAME:
+ switch (effective_type) {
+ case GEN_EMAIL:
+ /*
+ * We are here only when we have SmtpUTF8 name,
+ * so we match the value of othername with base->d.rfc822Name
+ */
+ return nc_email_eai(gen->d.otherName->value, base->d.rfc822Name);
+
+ default:
+ return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE;
+ }
+
+ case GEN_DIRNAME:
+ return nc_dn(gen->d.directoryName, base->d.directoryName);
+
+ case GEN_DNS:
+ return nc_dns(gen->d.dNSName, base->d.dNSName);
+
+ case GEN_EMAIL:
+ return nc_email(gen->d.rfc822Name, base->d.rfc822Name);
+
+ case GEN_URI:
+ return nc_uri(gen->d.uniformResourceIdentifier,
+ base->d.uniformResourceIdentifier);
+
+ case GEN_IPADD:
+ return nc_ip(gen->d.iPAddress, base->d.iPAddress);
+
+ default:
+ return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE;
+ }
+
+}
+
+/*
+ * directoryName name constraint matching. The canonical encoding of
+ * X509_NAME makes this comparison easy. It is matched if the subtree is a
+ * subset of the name.
+ */
+
+static int nc_dn(const X509_NAME *nm, const X509_NAME *base)
+{
+ /* Ensure canonical encodings are up to date. */
+ if (nm->modified && i2d_X509_NAME(nm, NULL) < 0)
+ return X509_V_ERR_OUT_OF_MEM;
+ if (base->modified && i2d_X509_NAME(base, NULL) < 0)
+ return X509_V_ERR_OUT_OF_MEM;
+ if (base->canon_enclen > nm->canon_enclen)
+ return X509_V_ERR_PERMITTED_VIOLATION;
+ if (memcmp(base->canon_enc, nm->canon_enc, base->canon_enclen))
+ return X509_V_ERR_PERMITTED_VIOLATION;
+ return X509_V_OK;
+}
+
+static int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base)
+{
+ char *baseptr = (char *)base->data;
+ char *dnsptr = (char *)dns->data;
+
+ /* Empty matches everything */
+ if (base->length == 0)
+ return X509_V_OK;
+
+ if (dns->length < base->length)
+ return X509_V_ERR_PERMITTED_VIOLATION;
+
+ /*
+ * Otherwise can add zero or more components on the left so compare RHS
+ * and if dns is longer and expect '.' as preceding character.
+ */
+ if (dns->length > base->length) {
+ dnsptr += dns->length - base->length;
+ if (*baseptr != '.' && dnsptr[-1] != '.')
+ return X509_V_ERR_PERMITTED_VIOLATION;
+ }
+
+ if (ia5ncasecmp(baseptr, dnsptr, base->length))
+ return X509_V_ERR_PERMITTED_VIOLATION;
+
+ return X509_V_OK;
+
+}
+
+/*
+ * This function implements comparison between ASCII/U-label in emltype
+ * and A-label in base according to RFC 8398, section 6.
+ * Convert base to U-label and ASCII-parts of domain names, for base
+ * Octet-to-octet comparison of `emltype` and `base` hostname parts
+ * (ASCII-parts should be compared in case-insensitive manner)
+ */
+static int nc_email_eai(ASN1_TYPE *emltype, ASN1_IA5STRING *base)
+{
+ ASN1_UTF8STRING *eml;
+ char *baseptr = NULL;
+ const char *emlptr;
+ const char *emlat;
+ char ulabel[256];
+ size_t size = sizeof(ulabel) - 1;
+ int ret = X509_V_OK;
+ size_t emlhostlen;
+
+ /* We do not accept embedded NUL characters */
+ if (base->length > 0 && memchr(base->data, 0, base->length) != NULL)
+ return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+
+ /* 'base' may not be NUL terminated. Create a copy that is */
+ baseptr = OPENSSL_strndup((char *)base->data, base->length);
+ if (baseptr == NULL)
+ return X509_V_ERR_OUT_OF_MEM;
+
+ if (emltype->type != V_ASN1_UTF8STRING) {
+ ret = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+ goto end;
+ }
+
+ eml = emltype->value.utf8string;
+ emlptr = (char *)eml->data;
+ emlat = ia5memrchr(eml, '@');
+
+ if (emlat == NULL) {
+ ret = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+ goto end;
+ }
+
+ memset(ulabel, 0, sizeof(ulabel));
+ /* Special case: initial '.' is RHS match */
+ if (*baseptr == '.') {
+ ulabel[0] = '.';
+ size -= 1;
+ if (ossl_a2ulabel(baseptr, ulabel + 1, &size) <= 0) {
+ ret = X509_V_ERR_UNSPECIFIED;
+ goto end;
+ }
+
+ if ((size_t)eml->length > strlen(ulabel)) {
+ emlptr += eml->length - (strlen(ulabel));
+ /* X509_V_OK */
+ if (ia5ncasecmp(ulabel, emlptr, strlen(ulabel)) == 0)
+ goto end;
+ }
+ ret = X509_V_ERR_PERMITTED_VIOLATION;
+ goto end;
+ }
+
+ if (ossl_a2ulabel(baseptr, ulabel, &size) <= 0) {
+ ret = X509_V_ERR_UNSPECIFIED;
+ goto end;
+ }
+ /* Just have hostname left to match: case insensitive */
+ emlptr = emlat + 1;
+ emlhostlen = IA5_OFFSET_LEN(eml, emlptr);
+ if (emlhostlen != strlen(ulabel)
+ || ia5ncasecmp(ulabel, emlptr, emlhostlen) != 0) {
+ ret = X509_V_ERR_PERMITTED_VIOLATION;
+ goto end;
+ }
+
+ end:
+ OPENSSL_free(baseptr);
+ return ret;
+}
+
+static int nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base)
+{
+ const char *baseptr = (char *)base->data;
+ const char *emlptr = (char *)eml->data;
+ const char *baseat = ia5memrchr(base, '@');
+ const char *emlat = ia5memrchr(eml, '@');
+ size_t basehostlen, emlhostlen;
+
+ if (!emlat)
+ return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+ /* Special case: initial '.' is RHS match */
+ if (!baseat && base->length > 0 && (*baseptr == '.')) {
+ if (eml->length > base->length) {
+ emlptr += eml->length - base->length;
+ if (ia5ncasecmp(baseptr, emlptr, base->length) == 0)
+ return X509_V_OK;
+ }
+ return X509_V_ERR_PERMITTED_VIOLATION;
+ }
+
+ /* If we have anything before '@' match local part */
+
+ if (baseat) {
+ if (baseat != baseptr) {
+ if ((baseat - baseptr) != (emlat - emlptr))
+ return X509_V_ERR_PERMITTED_VIOLATION;
+ if (memchr(baseptr, 0, baseat - baseptr) ||
+ memchr(emlptr, 0, emlat - emlptr))
+ return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+ /* Case sensitive match of local part */
+ if (strncmp(baseptr, emlptr, emlat - emlptr))
+ return X509_V_ERR_PERMITTED_VIOLATION;
+ }
+ /* Position base after '@' */
+ baseptr = baseat + 1;
+ }
+ emlptr = emlat + 1;
+ basehostlen = IA5_OFFSET_LEN(base, baseptr);
+ emlhostlen = IA5_OFFSET_LEN(eml, emlptr);
+ /* Just have hostname left to match: case insensitive */
+ if (basehostlen != emlhostlen || ia5ncasecmp(baseptr, emlptr, emlhostlen))
+ return X509_V_ERR_PERMITTED_VIOLATION;
+
+ return X509_V_OK;
+
+}
+
+static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base)
+{
+ const char *baseptr = (char *)base->data;
+ const char *hostptr = (char *)uri->data;
+ const char *p = ia5memchr(uri, (char *)uri->data, ':');
+ int hostlen;
+
+ /* Check for foo:// and skip past it */
+ if (p == NULL
+ || IA5_OFFSET_LEN(uri, p) < 3
+ || p[1] != '/'
+ || p[2] != '/')
+ return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+ hostptr = p + 3;
+
+ /* Determine length of hostname part of URI */
+
+ /* Look for a port indicator as end of hostname first */
+
+ p = ia5memchr(uri, hostptr, ':');
+ /* Otherwise look for trailing slash */
+ if (p == NULL)
+ p = ia5memchr(uri, hostptr, '/');
+
+ if (p == NULL)
+ hostlen = IA5_OFFSET_LEN(uri, hostptr);
+ else
+ hostlen = p - hostptr;
+
+ if (hostlen == 0)
+ return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+
+ /* Special case: initial '.' is RHS match */
+ if (base->length > 0 && *baseptr == '.') {
+ if (hostlen > base->length) {
+ p = hostptr + hostlen - base->length;
+ if (ia5ncasecmp(p, baseptr, base->length) == 0)
+ return X509_V_OK;
+ }
+ return X509_V_ERR_PERMITTED_VIOLATION;
+ }
+
+ if ((base->length != (int)hostlen)
+ || ia5ncasecmp(hostptr, baseptr, hostlen))
+ return X509_V_ERR_PERMITTED_VIOLATION;
+
+ return X509_V_OK;
+
+}
+
+static int nc_ip(ASN1_OCTET_STRING *ip, ASN1_OCTET_STRING *base)
+{
+ int hostlen, baselen, i;
+ unsigned char *hostptr, *baseptr, *maskptr;
+ hostptr = ip->data;
+ hostlen = ip->length;
+ baseptr = base->data;
+ baselen = base->length;
+
+ /* Invalid if not IPv4 or IPv6 */
+ if (!((hostlen == 4) || (hostlen == 16)))
+ return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+ if (!((baselen == 8) || (baselen == 32)))
+ return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+
+ /* Do not match IPv4 with IPv6 */
+ if (hostlen * 2 != baselen)
+ return X509_V_ERR_PERMITTED_VIOLATION;
+
+ maskptr = base->data + hostlen;
+
+ /* Considering possible not aligned base ipAddress */
+ /* Not checking for wrong mask definition: i.e.: 255.0.255.0 */
+ for (i = 0; i < hostlen; i++)
+ if ((hostptr[i] & maskptr[i]) != (baseptr[i] & maskptr[i]))
+ return X509_V_ERR_PERMITTED_VIOLATION;
+
+ return X509_V_OK;
+
+}
diff --git a/crypto/x509/v3_pci.c b/crypto/x509/v3_pci.c
new file mode 100644
index 000000000000..a931e01a9c92
--- /dev/null
+++ b/crypto/x509/v3_pci.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This file is dual-licensed and is also available under the following
+ * terms:
+ *
+ * Copyright (c) 2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include "ext_dat.h"
+
+static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *ext,
+ BIO *out, int indent);
+static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, char *str);
+
+const X509V3_EXT_METHOD ossl_v3_pci =
+ { NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION),
+ 0, 0, 0, 0,
+ 0, 0,
+ NULL, NULL,
+ (X509V3_EXT_I2R)i2r_pci,
+ (X509V3_EXT_R2I)r2i_pci,
+ NULL,
+};
+
+static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *pci,
+ BIO *out, int indent)
+{
+ BIO_printf(out, "%*sPath Length Constraint: ", indent, "");
+ if (pci->pcPathLengthConstraint)
+ i2a_ASN1_INTEGER(out, pci->pcPathLengthConstraint);
+ else
+ BIO_printf(out, "infinite");
+ BIO_puts(out, "\n");
+ BIO_printf(out, "%*sPolicy Language: ", indent, "");
+ i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage);
+ if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data)
+ BIO_printf(out, "\n%*sPolicy Text: %.*s", indent, "",
+ pci->proxyPolicy->policy->length,
+ pci->proxyPolicy->policy->data);
+ return 1;
+}
+
+static int process_pci_value(CONF_VALUE *val,
+ ASN1_OBJECT **language, ASN1_INTEGER **pathlen,
+ ASN1_OCTET_STRING **policy)
+{
+ int free_policy = 0;
+
+ if (strcmp(val->name, "language") == 0) {
+ if (*language) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED);
+ X509V3_conf_err(val);
+ return 0;
+ }
+ if ((*language = OBJ_txt2obj(val->value, 0)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+ X509V3_conf_err(val);
+ return 0;
+ }
+ } else if (strcmp(val->name, "pathlen") == 0) {
+ if (*pathlen) {
+ ERR_raise(ERR_LIB_X509V3,
+ X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED);
+ X509V3_conf_err(val);
+ return 0;
+ }
+ if (!X509V3_get_value_int(val, pathlen)) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_POLICY_PATH_LENGTH);
+ X509V3_conf_err(val);
+ return 0;
+ }
+ } else if (strcmp(val->name, "policy") == 0) {
+ unsigned char *tmp_data = NULL;
+ long val_len;
+
+ if (*policy == NULL) {
+ *policy = ASN1_OCTET_STRING_new();
+ if (*policy == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ X509V3_conf_err(val);
+ return 0;
+ }
+ free_policy = 1;
+ }
+ if (strncmp(val->value, "hex:", 4) == 0) {
+ unsigned char *tmp_data2 =
+ OPENSSL_hexstr2buf(val->value + 4, &val_len);
+
+ if (!tmp_data2) {
+ X509V3_conf_err(val);
+ goto err;
+ }
+
+ tmp_data = OPENSSL_realloc((*policy)->data,
+ (*policy)->length + val_len + 1);
+ if (tmp_data) {
+ (*policy)->data = tmp_data;
+ memcpy(&(*policy)->data[(*policy)->length],
+ tmp_data2, val_len);
+ (*policy)->length += val_len;
+ (*policy)->data[(*policy)->length] = '\0';
+ } else {
+ OPENSSL_free(tmp_data2);
+ /*
+ * realloc failure implies the original data space is b0rked
+ * too!
+ */
+ OPENSSL_free((*policy)->data);
+ (*policy)->data = NULL;
+ (*policy)->length = 0;
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ OPENSSL_free(tmp_data2);
+ } else if (strncmp(val->value, "file:", 5) == 0) {
+ unsigned char buf[2048];
+ int n;
+ BIO *b = BIO_new_file(val->value + 5, "r");
+ if (!b) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_BIO_LIB);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ while ((n = BIO_read(b, buf, sizeof(buf))) > 0
+ || (n == 0 && BIO_should_retry(b))) {
+ if (!n)
+ continue;
+
+ tmp_data = OPENSSL_realloc((*policy)->data,
+ (*policy)->length + n + 1);
+
+ if (!tmp_data) {
+ OPENSSL_free((*policy)->data);
+ (*policy)->data = NULL;
+ (*policy)->length = 0;
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ X509V3_conf_err(val);
+ BIO_free_all(b);
+ goto err;
+ }
+
+ (*policy)->data = tmp_data;
+ memcpy(&(*policy)->data[(*policy)->length], buf, n);
+ (*policy)->length += n;
+ (*policy)->data[(*policy)->length] = '\0';
+ }
+ BIO_free_all(b);
+
+ if (n < 0) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_BIO_LIB);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ } else if (strncmp(val->value, "text:", 5) == 0) {
+ val_len = strlen(val->value + 5);
+ tmp_data = OPENSSL_realloc((*policy)->data,
+ (*policy)->length + val_len + 1);
+ if (tmp_data) {
+ (*policy)->data = tmp_data;
+ memcpy(&(*policy)->data[(*policy)->length],
+ val->value + 5, val_len);
+ (*policy)->length += val_len;
+ (*policy)->data[(*policy)->length] = '\0';
+ } else {
+ /*
+ * realloc failure implies the original data space is b0rked
+ * too!
+ */
+ OPENSSL_free((*policy)->data);
+ (*policy)->data = NULL;
+ (*policy)->length = 0;
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ } else {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ if (!tmp_data) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ }
+ return 1;
+ err:
+ if (free_policy) {
+ ASN1_OCTET_STRING_free(*policy);
+ *policy = NULL;
+ }
+ return 0;
+}
+
+static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, char *value)
+{
+ PROXY_CERT_INFO_EXTENSION *pci = NULL;
+ STACK_OF(CONF_VALUE) *vals;
+ ASN1_OBJECT *language = NULL;
+ ASN1_INTEGER *pathlen = NULL;
+ ASN1_OCTET_STRING *policy = NULL;
+ int i, j;
+
+ vals = X509V3_parse_list(value);
+ for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
+ CONF_VALUE *cnf = sk_CONF_VALUE_value(vals, i);
+
+ if (!cnf->name || (*cnf->name != '@' && !cnf->value)) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_PROXY_POLICY_SETTING);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ if (*cnf->name == '@') {
+ STACK_OF(CONF_VALUE) *sect;
+ int success_p = 1;
+
+ sect = X509V3_get_section(ctx, cnf->name + 1);
+ if (!sect) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_SECTION);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ for (j = 0; success_p && j < sk_CONF_VALUE_num(sect); j++) {
+ success_p =
+ process_pci_value(sk_CONF_VALUE_value(sect, j),
+ &language, &pathlen, &policy);
+ }
+ X509V3_section_free(ctx, sect);
+ if (!success_p)
+ goto err;
+ } else {
+ if (!process_pci_value(cnf, &language, &pathlen, &policy)) {
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ }
+ }
+
+ /* Language is mandatory */
+ if (!language) {
+ ERR_raise(ERR_LIB_X509V3,
+ X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED);
+ goto err;
+ }
+ i = OBJ_obj2nid(language);
+ if ((i == NID_Independent || i == NID_id_ppl_inheritAll) && policy) {
+ ERR_raise(ERR_LIB_X509V3,
+ X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY);
+ goto err;
+ }
+
+ pci = PROXY_CERT_INFO_EXTENSION_new();
+ if (pci == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ pci->proxyPolicy->policyLanguage = language;
+ language = NULL;
+ pci->proxyPolicy->policy = policy;
+ policy = NULL;
+ pci->pcPathLengthConstraint = pathlen;
+ pathlen = NULL;
+ goto end;
+ err:
+ ASN1_OBJECT_free(language);
+ ASN1_INTEGER_free(pathlen);
+ pathlen = NULL;
+ ASN1_OCTET_STRING_free(policy);
+ policy = NULL;
+ PROXY_CERT_INFO_EXTENSION_free(pci);
+ pci = NULL;
+ end:
+ sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
+ return pci;
+}
diff --git a/crypto/x509/v3_pcia.c b/crypto/x509/v3_pcia.c
new file mode 100644
index 000000000000..7f5985f5e859
--- /dev/null
+++ b/crypto/x509/v3_pcia.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This file is dual-licensed and is also available under the following
+ * terms:
+ *
+ * Copyright (c) 2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509v3.h>
+
+ASN1_SEQUENCE(PROXY_POLICY) =
+ {
+ ASN1_SIMPLE(PROXY_POLICY,policyLanguage,ASN1_OBJECT),
+ ASN1_OPT(PROXY_POLICY,policy,ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(PROXY_POLICY)
+
+IMPLEMENT_ASN1_FUNCTIONS(PROXY_POLICY)
+
+ASN1_SEQUENCE(PROXY_CERT_INFO_EXTENSION) =
+ {
+ ASN1_OPT(PROXY_CERT_INFO_EXTENSION,pcPathLengthConstraint,ASN1_INTEGER),
+ ASN1_SIMPLE(PROXY_CERT_INFO_EXTENSION,proxyPolicy,PROXY_POLICY)
+} ASN1_SEQUENCE_END(PROXY_CERT_INFO_EXTENSION)
+
+IMPLEMENT_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION)
diff --git a/crypto/x509/v3_pcons.c b/crypto/x509/v3_pcons.c
new file mode 100644
index 000000000000..128365f572e2
--- /dev/null
+++ b/crypto/x509/v3_pcons.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2003-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include "ext_dat.h"
+
+static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD
+ *method, void *bcons, STACK_OF(CONF_VALUE)
+ *extlist);
+static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *values);
+
+const X509V3_EXT_METHOD ossl_v3_policy_constraints = {
+ NID_policy_constraints, 0,
+ ASN1_ITEM_ref(POLICY_CONSTRAINTS),
+ 0, 0, 0, 0,
+ 0, 0,
+ i2v_POLICY_CONSTRAINTS,
+ v2i_POLICY_CONSTRAINTS,
+ NULL, NULL,
+ NULL
+};
+
+ASN1_SEQUENCE(POLICY_CONSTRAINTS) = {
+ ASN1_IMP_OPT(POLICY_CONSTRAINTS, requireExplicitPolicy, ASN1_INTEGER,0),
+ ASN1_IMP_OPT(POLICY_CONSTRAINTS, inhibitPolicyMapping, ASN1_INTEGER,1)
+} ASN1_SEQUENCE_END(POLICY_CONSTRAINTS)
+
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS)
+
+static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD
+ *method, void *a, STACK_OF(CONF_VALUE)
+ *extlist)
+{
+ POLICY_CONSTRAINTS *pcons = a;
+ X509V3_add_value_int("Require Explicit Policy",
+ pcons->requireExplicitPolicy, &extlist);
+ X509V3_add_value_int("Inhibit Policy Mapping",
+ pcons->inhibitPolicyMapping, &extlist);
+ return extlist;
+}
+
+static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *values)
+{
+ POLICY_CONSTRAINTS *pcons = NULL;
+ CONF_VALUE *val;
+ int i;
+
+ if ((pcons = POLICY_CONSTRAINTS_new()) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
+ val = sk_CONF_VALUE_value(values, i);
+ if (strcmp(val->name, "requireExplicitPolicy") == 0) {
+ if (!X509V3_get_value_int(val, &pcons->requireExplicitPolicy))
+ goto err;
+ } else if (strcmp(val->name, "inhibitPolicyMapping") == 0) {
+ if (!X509V3_get_value_int(val, &pcons->inhibitPolicyMapping))
+ goto err;
+ } else {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_INVALID_NAME,
+ "%s", val->name);
+ goto err;
+ }
+ }
+ if (pcons->inhibitPolicyMapping == NULL
+ && pcons->requireExplicitPolicy == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_ILLEGAL_EMPTY_EXTENSION);
+ goto err;
+ }
+
+ return pcons;
+ err:
+ POLICY_CONSTRAINTS_free(pcons);
+ return NULL;
+}
diff --git a/crypto/x509/v3_pku.c b/crypto/x509/v3_pku.c
new file mode 100644
index 000000000000..8f7e7d681300
--- /dev/null
+++ b/crypto/x509/v3_pku.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509v3.h>
+#include "ext_dat.h"
+
+static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method,
+ PKEY_USAGE_PERIOD *usage, BIO *out,
+ int indent);
+
+const X509V3_EXT_METHOD ossl_v3_pkey_usage_period = {
+ NID_private_key_usage_period, 0, ASN1_ITEM_ref(PKEY_USAGE_PERIOD),
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ (X509V3_EXT_I2R)i2r_PKEY_USAGE_PERIOD, NULL,
+ NULL
+};
+
+ASN1_SEQUENCE(PKEY_USAGE_PERIOD) = {
+ ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notBefore, ASN1_GENERALIZEDTIME, 0),
+ ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notAfter, ASN1_GENERALIZEDTIME, 1)
+} ASN1_SEQUENCE_END(PKEY_USAGE_PERIOD)
+
+IMPLEMENT_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD)
+
+static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method,
+ PKEY_USAGE_PERIOD *usage, BIO *out,
+ int indent)
+{
+ BIO_printf(out, "%*s", indent, "");
+ if (usage->notBefore) {
+ BIO_write(out, "Not Before: ", 12);
+ ASN1_GENERALIZEDTIME_print(out, usage->notBefore);
+ if (usage->notAfter)
+ BIO_write(out, ", ", 2);
+ }
+ if (usage->notAfter) {
+ BIO_write(out, "Not After: ", 11);
+ ASN1_GENERALIZEDTIME_print(out, usage->notAfter);
+ }
+ return 1;
+}
diff --git a/crypto/x509/v3_pmaps.c b/crypto/x509/v3_pmaps.c
new file mode 100644
index 000000000000..2094e9671141
--- /dev/null
+++ b/crypto/x509/v3_pmaps.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2003-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include "ext_dat.h"
+
+static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD
+ *method, void *pmps, STACK_OF(CONF_VALUE)
+ *extlist);
+
+const X509V3_EXT_METHOD ossl_v3_policy_mappings = {
+ NID_policy_mappings, 0,
+ ASN1_ITEM_ref(POLICY_MAPPINGS),
+ 0, 0, 0, 0,
+ 0, 0,
+ i2v_POLICY_MAPPINGS,
+ v2i_POLICY_MAPPINGS,
+ 0, 0,
+ NULL
+};
+
+ASN1_SEQUENCE(POLICY_MAPPING) = {
+ ASN1_SIMPLE(POLICY_MAPPING, issuerDomainPolicy, ASN1_OBJECT),
+ ASN1_SIMPLE(POLICY_MAPPING, subjectDomainPolicy, ASN1_OBJECT)
+} ASN1_SEQUENCE_END(POLICY_MAPPING)
+
+ASN1_ITEM_TEMPLATE(POLICY_MAPPINGS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, POLICY_MAPPINGS,
+ POLICY_MAPPING)
+ASN1_ITEM_TEMPLATE_END(POLICY_MAPPINGS)
+
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING)
+
+static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD
+ *method, void *a, STACK_OF(CONF_VALUE)
+ *ext_list)
+{
+ POLICY_MAPPINGS *pmaps = a;
+ POLICY_MAPPING *pmap;
+ int i;
+ char obj_tmp1[80];
+ char obj_tmp2[80];
+
+ for (i = 0; i < sk_POLICY_MAPPING_num(pmaps); i++) {
+ pmap = sk_POLICY_MAPPING_value(pmaps, i);
+ i2t_ASN1_OBJECT(obj_tmp1, 80, pmap->issuerDomainPolicy);
+ i2t_ASN1_OBJECT(obj_tmp2, 80, pmap->subjectDomainPolicy);
+ X509V3_add_value(obj_tmp1, obj_tmp2, &ext_list);
+ }
+ return ext_list;
+}
+
+static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+{
+ POLICY_MAPPING *pmap = NULL;
+ ASN1_OBJECT *obj1 = NULL, *obj2 = NULL;
+ CONF_VALUE *val;
+ POLICY_MAPPINGS *pmaps;
+ const int num = sk_CONF_VALUE_num(nval);
+ int i;
+
+ if ((pmaps = sk_POLICY_MAPPING_new_reserve(NULL, num)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ for (i = 0; i < num; i++) {
+ val = sk_CONF_VALUE_value(nval, i);
+ if (!val->value || !val->name) {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER,
+ "%s", val->name);
+ goto err;
+ }
+ obj1 = OBJ_txt2obj(val->name, 0);
+ obj2 = OBJ_txt2obj(val->value, 0);
+ if (!obj1 || !obj2) {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER,
+ "%s", val->name);
+ goto err;
+ }
+ pmap = POLICY_MAPPING_new();
+ if (pmap == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ pmap->issuerDomainPolicy = obj1;
+ pmap->subjectDomainPolicy = obj2;
+ obj1 = obj2 = NULL;
+ sk_POLICY_MAPPING_push(pmaps, pmap); /* no failure as it was reserved */
+ }
+ return pmaps;
+ err:
+ ASN1_OBJECT_free(obj1);
+ ASN1_OBJECT_free(obj2);
+ sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
+ return NULL;
+}
diff --git a/crypto/x509/v3_prn.c b/crypto/x509/v3_prn.c
new file mode 100644
index 000000000000..1e4516a713c2
--- /dev/null
+++ b/crypto/x509/v3_prn.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* X509 v3 extension utilities */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+
+/* Extension printing routines */
+
+static int unknown_ext_print(BIO *out, const unsigned char *ext, int extlen,
+ unsigned long flag, int indent, int supported);
+
+/* Print out a name+value stack */
+
+void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
+ int ml)
+{
+ int i;
+ CONF_VALUE *nval;
+ if (!val)
+ return;
+ if (!ml || !sk_CONF_VALUE_num(val)) {
+ BIO_printf(out, "%*s", indent, "");
+ if (!sk_CONF_VALUE_num(val))
+ BIO_puts(out, "<EMPTY>\n");
+ }
+ for (i = 0; i < sk_CONF_VALUE_num(val); i++) {
+ if (ml) {
+ if (i > 0)
+ BIO_printf(out, "\n");
+ BIO_printf(out, "%*s", indent, "");
+ }
+ else if (i > 0)
+ BIO_printf(out, ", ");
+ nval = sk_CONF_VALUE_value(val, i);
+ if (!nval->name)
+ BIO_puts(out, nval->value);
+ else if (!nval->value)
+ BIO_puts(out, nval->name);
+#ifndef CHARSET_EBCDIC
+ else
+ BIO_printf(out, "%s:%s", nval->name, nval->value);
+#else
+ else {
+ int len;
+ char *tmp;
+ len = strlen(nval->value) + 1;
+ tmp = OPENSSL_malloc(len);
+ if (tmp != NULL) {
+ ascii2ebcdic(tmp, nval->value, len);
+ BIO_printf(out, "%s:%s", nval->name, tmp);
+ OPENSSL_free(tmp);
+ }
+ }
+#endif
+ }
+}
+
+/* Main routine: print out a general extension */
+
+int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag,
+ int indent)
+{
+ void *ext_str = NULL;
+ char *value = NULL;
+ ASN1_OCTET_STRING *extoct;
+ const unsigned char *p;
+ int extlen;
+ const X509V3_EXT_METHOD *method;
+ STACK_OF(CONF_VALUE) *nval = NULL;
+ int ok = 1;
+
+ extoct = X509_EXTENSION_get_data(ext);
+ p = ASN1_STRING_get0_data(extoct);
+ extlen = ASN1_STRING_length(extoct);
+
+ if ((method = X509V3_EXT_get(ext)) == NULL)
+ return unknown_ext_print(out, p, extlen, flag, indent, 0);
+ if (method->it)
+ ext_str = ASN1_item_d2i(NULL, &p, extlen, ASN1_ITEM_ptr(method->it));
+ else
+ ext_str = method->d2i(NULL, &p, extlen);
+
+ if (!ext_str)
+ return unknown_ext_print(out, p, extlen, flag, indent, 1);
+
+ if (method->i2s) {
+ if ((value = method->i2s(method, ext_str)) == NULL) {
+ ok = 0;
+ goto err;
+ }
+#ifndef CHARSET_EBCDIC
+ BIO_printf(out, "%*s%s", indent, "", value);
+#else
+ {
+ int len;
+ char *tmp;
+ len = strlen(value) + 1;
+ tmp = OPENSSL_malloc(len);
+ if (tmp != NULL) {
+ ascii2ebcdic(tmp, value, len);
+ BIO_printf(out, "%*s%s", indent, "", tmp);
+ OPENSSL_free(tmp);
+ }
+ }
+#endif
+ } else if (method->i2v) {
+ if ((nval = method->i2v(method, ext_str, NULL)) == NULL) {
+ ok = 0;
+ goto err;
+ }
+ X509V3_EXT_val_prn(out, nval, indent,
+ method->ext_flags & X509V3_EXT_MULTILINE);
+ } else if (method->i2r) {
+ if (!method->i2r(method, ext_str, out, indent))
+ ok = 0;
+ } else
+ ok = 0;
+
+ err:
+ sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
+ OPENSSL_free(value);
+ if (method->it)
+ ASN1_item_free(ext_str, ASN1_ITEM_ptr(method->it));
+ else
+ method->ext_free(ext_str);
+ return ok;
+}
+
+int X509V3_extensions_print(BIO *bp, const char *title,
+ const STACK_OF(X509_EXTENSION) *exts,
+ unsigned long flag, int indent)
+{
+ int i, j;
+
+ if (sk_X509_EXTENSION_num(exts) <= 0)
+ return 1;
+
+ if (title) {
+ BIO_printf(bp, "%*s%s:\n", indent, "", title);
+ indent += 4;
+ }
+
+ for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
+ ASN1_OBJECT *obj;
+ X509_EXTENSION *ex;
+
+ ex = sk_X509_EXTENSION_value(exts, i);
+ obj = X509_EXTENSION_get_object(ex);
+ if ((flag & X509_FLAG_EXTENSIONS_ONLY_KID) != 0
+ && OBJ_obj2nid(obj) != NID_subject_key_identifier
+ && OBJ_obj2nid(obj) != NID_authority_key_identifier)
+ continue;
+ if (indent && BIO_printf(bp, "%*s", indent, "") <= 0)
+ return 0;
+ i2a_ASN1_OBJECT(bp, obj);
+ j = X509_EXTENSION_get_critical(ex);
+ if (BIO_printf(bp, ": %s\n", j ? "critical" : "") <= 0)
+ return 0;
+ if (!X509V3_EXT_print(bp, ex, flag, indent + 4)) {
+ BIO_printf(bp, "%*s", indent + 4, "");
+ ASN1_STRING_print(bp, X509_EXTENSION_get_data(ex));
+ }
+ if (BIO_write(bp, "\n", 1) <= 0)
+ return 0;
+ }
+ return 1;
+}
+
+static int unknown_ext_print(BIO *out, const unsigned char *ext, int extlen,
+ unsigned long flag, int indent, int supported)
+{
+ switch (flag & X509V3_EXT_UNKNOWN_MASK) {
+
+ case X509V3_EXT_DEFAULT:
+ return 0;
+
+ case X509V3_EXT_ERROR_UNKNOWN:
+ if (supported)
+ BIO_printf(out, "%*s<Parse Error>", indent, "");
+ else
+ BIO_printf(out, "%*s<Not Supported>", indent, "");
+ return 1;
+
+ case X509V3_EXT_PARSE_UNKNOWN:
+ return ASN1_parse_dump(out, ext, extlen, indent, -1);
+ case X509V3_EXT_DUMP_UNKNOWN:
+ return BIO_dump_indent(out, (const char *)ext, extlen, indent);
+
+ default:
+ return 1;
+ }
+}
+
+#ifndef OPENSSL_NO_STDIO
+int X509V3_EXT_print_fp(FILE *fp, X509_EXTENSION *ext, int flag, int indent)
+{
+ BIO *bio_tmp;
+ int ret;
+
+ if ((bio_tmp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL)
+ return 0;
+ ret = X509V3_EXT_print(bio_tmp, ext, flag, indent);
+ BIO_free(bio_tmp);
+ return ret;
+}
+#endif
diff --git a/crypto/x509/v3_purp.c b/crypto/x509/v3_purp.c
new file mode 100644
index 000000000000..a6ebbd5f94f6
--- /dev/null
+++ b/crypto/x509/v3_purp.c
@@ -0,0 +1,1066 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include "internal/numbers.h"
+#include <openssl/x509v3.h>
+#include <openssl/x509_vfy.h>
+#include "crypto/x509.h"
+#include "internal/tsan_assist.h"
+#include "x509_local.h"
+
+static int check_ssl_ca(const X509 *x);
+static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca);
+static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca);
+static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca);
+static int purpose_smime(const X509 *x, int require_ca);
+static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca);
+static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca);
+static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca);
+static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca);
+static int no_check_purpose(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca);
+static int check_purpose_ocsp_helper(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca);
+
+static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b);
+static void xptable_free(X509_PURPOSE *p);
+
+static X509_PURPOSE xstandard[] = {
+ {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0,
+ check_purpose_ssl_client, "SSL client", "sslclient", NULL},
+ {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0,
+ check_purpose_ssl_server, "SSL server", "sslserver", NULL},
+ {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0,
+ check_purpose_ns_ssl_server, "Netscape SSL server", "nssslserver", NULL},
+ {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign,
+ "S/MIME signing", "smimesign", NULL},
+ {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0,
+ check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL},
+ {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign,
+ "CRL signing", "crlsign", NULL},
+ {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check_purpose,
+ "Any Purpose", "any",
+ NULL},
+ {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, check_purpose_ocsp_helper,
+ "OCSP helper", "ocsphelper", NULL},
+ {X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0,
+ check_purpose_timestamp_sign, "Time Stamp signing", "timestampsign",
+ NULL},
+};
+
+#define X509_PURPOSE_COUNT OSSL_NELEM(xstandard)
+
+static STACK_OF(X509_PURPOSE) *xptable = NULL;
+
+static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b)
+{
+ return (*a)->purpose - (*b)->purpose;
+}
+
+/*
+ * As much as I'd like to make X509_check_purpose use a "const" X509* I really
+ * can't because it does recalculate hashes and do other non-const things.
+ * If id == -1 it just calls x509v3_cache_extensions() for its side-effect.
+ * Returns 1 on success, 0 if x does not allow purpose, -1 on (internal) error.
+ */
+int X509_check_purpose(X509 *x, int id, int require_ca)
+{
+ int idx;
+ const X509_PURPOSE *pt;
+
+ if (!ossl_x509v3_cache_extensions(x))
+ return -1;
+ if (id == -1)
+ return 1;
+
+ idx = X509_PURPOSE_get_by_id(id);
+ if (idx == -1)
+ return -1;
+ pt = X509_PURPOSE_get0(idx);
+ return pt->check_purpose(pt, x, require_ca);
+}
+
+int X509_PURPOSE_set(int *p, int purpose)
+{
+ if (X509_PURPOSE_get_by_id(purpose) == -1) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_PURPOSE);
+ return 0;
+ }
+ *p = purpose;
+ return 1;
+}
+
+int X509_PURPOSE_get_count(void)
+{
+ if (!xptable)
+ return X509_PURPOSE_COUNT;
+ return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT;
+}
+
+X509_PURPOSE *X509_PURPOSE_get0(int idx)
+{
+ if (idx < 0)
+ return NULL;
+ if (idx < (int)X509_PURPOSE_COUNT)
+ return xstandard + idx;
+ return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT);
+}
+
+int X509_PURPOSE_get_by_sname(const char *sname)
+{
+ int i;
+ X509_PURPOSE *xptmp;
+ for (i = 0; i < X509_PURPOSE_get_count(); i++) {
+ xptmp = X509_PURPOSE_get0(i);
+ if (strcmp(xptmp->sname, sname) == 0)
+ return i;
+ }
+ return -1;
+}
+
+/* Returns -1 on error, else an index => 0 in standard/extended purpose table */
+int X509_PURPOSE_get_by_id(int purpose)
+{
+ X509_PURPOSE tmp;
+ int idx;
+
+ if (purpose >= X509_PURPOSE_MIN && purpose <= X509_PURPOSE_MAX)
+ return purpose - X509_PURPOSE_MIN;
+ if (xptable == NULL)
+ return -1;
+ tmp.purpose = purpose;
+ idx = sk_X509_PURPOSE_find(xptable, &tmp);
+ if (idx < 0)
+ return -1;
+ return idx + X509_PURPOSE_COUNT;
+}
+
+int X509_PURPOSE_add(int id, int trust, int flags,
+ int (*ck) (const X509_PURPOSE *, const X509 *, int),
+ const char *name, const char *sname, void *arg)
+{
+ int idx;
+ X509_PURPOSE *ptmp;
+
+ /* This is set according to what we change: application can't set it */
+ flags &= ~X509_PURPOSE_DYNAMIC;
+ /* This will always be set for application modified trust entries */
+ flags |= X509_PURPOSE_DYNAMIC_NAME;
+ /* Get existing entry if any */
+ idx = X509_PURPOSE_get_by_id(id);
+ /* Need a new entry */
+ if (idx == -1) {
+ if ((ptmp = OPENSSL_malloc(sizeof(*ptmp))) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ ptmp->flags = X509_PURPOSE_DYNAMIC;
+ } else
+ ptmp = X509_PURPOSE_get0(idx);
+
+ /* OPENSSL_free existing name if dynamic */
+ if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) {
+ OPENSSL_free(ptmp->name);
+ OPENSSL_free(ptmp->sname);
+ }
+ /* Dup supplied name */
+ ptmp->name = OPENSSL_strdup(name);
+ ptmp->sname = OPENSSL_strdup(sname);
+ if (ptmp->name == NULL|| ptmp->sname == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ /* Keep the dynamic flag of existing entry */
+ ptmp->flags &= X509_PURPOSE_DYNAMIC;
+ /* Set all other flags */
+ ptmp->flags |= flags;
+
+ ptmp->purpose = id;
+ ptmp->trust = trust;
+ ptmp->check_purpose = ck;
+ ptmp->usr_data = arg;
+
+ /* If its a new entry manage the dynamic table */
+ if (idx == -1) {
+ if (xptable == NULL
+ && (xptable = sk_X509_PURPOSE_new(xp_cmp)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!sk_X509_PURPOSE_push(xptable, ptmp)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ return 1;
+ err:
+ if (idx == -1) {
+ OPENSSL_free(ptmp->name);
+ OPENSSL_free(ptmp->sname);
+ OPENSSL_free(ptmp);
+ }
+ return 0;
+}
+
+static void xptable_free(X509_PURPOSE *p)
+{
+ if (p == NULL)
+ return;
+ if (p->flags & X509_PURPOSE_DYNAMIC) {
+ if (p->flags & X509_PURPOSE_DYNAMIC_NAME) {
+ OPENSSL_free(p->name);
+ OPENSSL_free(p->sname);
+ }
+ OPENSSL_free(p);
+ }
+}
+
+void X509_PURPOSE_cleanup(void)
+{
+ sk_X509_PURPOSE_pop_free(xptable, xptable_free);
+ xptable = NULL;
+}
+
+int X509_PURPOSE_get_id(const X509_PURPOSE *xp)
+{
+ return xp->purpose;
+}
+
+char *X509_PURPOSE_get0_name(const X509_PURPOSE *xp)
+{
+ return xp->name;
+}
+
+char *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp)
+{
+ return xp->sname;
+}
+
+int X509_PURPOSE_get_trust(const X509_PURPOSE *xp)
+{
+ return xp->trust;
+}
+
+static int nid_cmp(const int *a, const int *b)
+{
+ return *a - *b;
+}
+
+DECLARE_OBJ_BSEARCH_CMP_FN(int, int, nid);
+IMPLEMENT_OBJ_BSEARCH_CMP_FN(int, int, nid);
+
+int X509_supported_extension(X509_EXTENSION *ex)
+{
+ /*
+ * This table is a list of the NIDs of supported extensions: that is
+ * those which are used by the verify process. If an extension is
+ * critical and doesn't appear in this list then the verify process will
+ * normally reject the certificate. The list must be kept in numerical
+ * order because it will be searched using bsearch.
+ */
+ static const int supported_nids[] = {
+ NID_netscape_cert_type, /* 71 */
+ NID_key_usage, /* 83 */
+ NID_subject_alt_name, /* 85 */
+ NID_basic_constraints, /* 87 */
+ NID_certificate_policies, /* 89 */
+ NID_crl_distribution_points, /* 103 */
+ NID_ext_key_usage, /* 126 */
+#ifndef OPENSSL_NO_RFC3779
+ NID_sbgp_ipAddrBlock, /* 290 */
+ NID_sbgp_autonomousSysNum, /* 291 */
+#endif
+ NID_id_pkix_OCSP_noCheck, /* 369 */
+ NID_policy_constraints, /* 401 */
+ NID_proxyCertInfo, /* 663 */
+ NID_name_constraints, /* 666 */
+ NID_policy_mappings, /* 747 */
+ NID_inhibit_any_policy /* 748 */
+ };
+
+ int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
+
+ if (ex_nid == NID_undef)
+ return 0;
+
+ if (OBJ_bsearch_nid(&ex_nid, supported_nids, OSSL_NELEM(supported_nids)))
+ return 1;
+ return 0;
+}
+
+/* Returns 1 on success, 0 if x is invalid, -1 on (internal) error. */
+static int setup_dp(const X509 *x, DIST_POINT *dp)
+{
+ const X509_NAME *iname = NULL;
+ int i;
+
+ if (dp->distpoint == NULL && sk_GENERAL_NAME_num(dp->CRLissuer) <= 0) {
+ ERR_raise(ERR_LIB_X509, X509_R_INVALID_DISTPOINT);
+ return 0;
+ }
+ if (dp->reasons != NULL) {
+ if (dp->reasons->length > 0)
+ dp->dp_reasons = dp->reasons->data[0];
+ if (dp->reasons->length > 1)
+ dp->dp_reasons |= (dp->reasons->data[1] << 8);
+ dp->dp_reasons &= CRLDP_ALL_REASONS;
+ } else {
+ dp->dp_reasons = CRLDP_ALL_REASONS;
+ }
+ if (dp->distpoint == NULL || dp->distpoint->type != 1)
+ return 1;
+
+ /* Handle name fragment given by nameRelativeToCRLIssuer */
+ /*
+ * Note that the below way of determining iname is not really compliant
+ * with https://tools.ietf.org/html/rfc5280#section-4.2.1.13
+ * According to it, sk_GENERAL_NAME_num(dp->CRLissuer) MUST be <= 1
+ * and any CRLissuer could be of type different to GEN_DIRNAME.
+ */
+ for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) {
+ GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
+
+ if (gen->type == GEN_DIRNAME) {
+ iname = gen->d.directoryName;
+ break;
+ }
+ }
+ if (iname == NULL)
+ iname = X509_get_issuer_name(x);
+ return DIST_POINT_set_dpname(dp->distpoint, iname) ? 1 : -1;
+}
+
+/* Return 1 on success, 0 if x is invalid, -1 on (internal) error. */
+static int setup_crldp(X509 *x)
+{
+ int i;
+
+ x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, &i, NULL);
+ if (x->crldp == NULL && i != -1)
+ return 0;
+
+ for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) {
+ int res = setup_dp(x, sk_DIST_POINT_value(x->crldp, i));
+
+ if (res < 1)
+ return res;
+ }
+ return 1;
+}
+
+/* Check that issuer public key algorithm matches subject signature algorithm */
+static int check_sig_alg_match(const EVP_PKEY *issuer_key, const X509 *subject)
+{
+ int subj_sig_nid;
+
+ if (issuer_key == NULL)
+ return X509_V_ERR_NO_ISSUER_PUBLIC_KEY;
+ if (OBJ_find_sigid_algs(OBJ_obj2nid(subject->cert_info.signature.algorithm),
+ NULL, &subj_sig_nid) == 0)
+ return X509_V_ERR_UNSUPPORTED_SIGNATURE_ALGORITHM;
+ if (EVP_PKEY_is_a(issuer_key, OBJ_nid2sn(subj_sig_nid))
+ || (EVP_PKEY_is_a(issuer_key, "RSA") && subj_sig_nid == NID_rsassaPss))
+ return X509_V_OK;
+ return X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH;
+}
+
+#define V1_ROOT (EXFLAG_V1|EXFLAG_SS)
+#define ku_reject(x, usage) \
+ (((x)->ex_flags & EXFLAG_KUSAGE) != 0 && ((x)->ex_kusage & (usage)) == 0)
+#define xku_reject(x, usage) \
+ (((x)->ex_flags & EXFLAG_XKUSAGE) != 0 && ((x)->ex_xkusage & (usage)) == 0)
+#define ns_reject(x, usage) \
+ (((x)->ex_flags & EXFLAG_NSCERT) != 0 && ((x)->ex_nscert & (usage)) == 0)
+
+/*
+ * Cache info on various X.509v3 extensions and further derived information,
+ * e.g., if cert 'x' is self-issued, in x->ex_flags and other internal fields.
+ * x->sha1_hash is filled in, or else EXFLAG_NO_FINGERPRINT is set in x->flags.
+ * X509_SIG_INFO_VALID is set in x->flags if x->siginf was filled successfully.
+ * Set EXFLAG_INVALID and return 0 in case the certificate is invalid.
+ */
+int ossl_x509v3_cache_extensions(X509 *x)
+{
+ BASIC_CONSTRAINTS *bs;
+ PROXY_CERT_INFO_EXTENSION *pci;
+ ASN1_BIT_STRING *usage;
+ ASN1_BIT_STRING *ns;
+ EXTENDED_KEY_USAGE *extusage;
+ int i;
+ int res;
+
+#ifdef tsan_ld_acq
+ /* Fast lock-free check, see end of the function for details. */
+ if (tsan_ld_acq((TSAN_QUALIFIER int *)&x->ex_cached))
+ return (x->ex_flags & EXFLAG_INVALID) == 0;
+#endif
+
+ if (!CRYPTO_THREAD_write_lock(x->lock))
+ return 0;
+ if (x->ex_flags & EXFLAG_SET) { /* Cert has already been processed */
+ CRYPTO_THREAD_unlock(x->lock);
+ return (x->ex_flags & EXFLAG_INVALID) == 0;
+ }
+
+ /* Cache the SHA1 digest of the cert */
+ if (!X509_digest(x, EVP_sha1(), x->sha1_hash, NULL))
+ x->ex_flags |= EXFLAG_NO_FINGERPRINT;
+
+ ERR_set_mark();
+
+ /* V1 should mean no extensions ... */
+ if (X509_get_version(x) == X509_VERSION_1)
+ x->ex_flags |= EXFLAG_V1;
+
+ /* Handle basic constraints */
+ x->ex_pathlen = -1;
+ if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, &i, NULL)) != NULL) {
+ if (bs->ca)
+ x->ex_flags |= EXFLAG_CA;
+ if (bs->pathlen != NULL) {
+ /*
+ * The error case !bs->ca is checked by check_chain()
+ * in case ctx->param->flags & X509_V_FLAG_X509_STRICT
+ */
+ if (bs->pathlen->type == V_ASN1_NEG_INTEGER) {
+ ERR_raise(ERR_LIB_X509, X509V3_R_NEGATIVE_PATHLEN);
+ x->ex_flags |= EXFLAG_INVALID;
+ } else {
+ x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen);
+ }
+ }
+ BASIC_CONSTRAINTS_free(bs);
+ x->ex_flags |= EXFLAG_BCONS;
+ } else if (i != -1) {
+ x->ex_flags |= EXFLAG_INVALID;
+ }
+
+ /* Handle proxy certificates */
+ if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, &i, NULL)) != NULL) {
+ if (x->ex_flags & EXFLAG_CA
+ || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0
+ || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) {
+ x->ex_flags |= EXFLAG_INVALID;
+ }
+ if (pci->pcPathLengthConstraint != NULL)
+ x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint);
+ else
+ x->ex_pcpathlen = -1;
+ PROXY_CERT_INFO_EXTENSION_free(pci);
+ x->ex_flags |= EXFLAG_PROXY;
+ } else if (i != -1) {
+ x->ex_flags |= EXFLAG_INVALID;
+ }
+
+ /* Handle (basic) key usage */
+ if ((usage = X509_get_ext_d2i(x, NID_key_usage, &i, NULL)) != NULL) {
+ x->ex_kusage = 0;
+ if (usage->length > 0) {
+ x->ex_kusage = usage->data[0];
+ if (usage->length > 1)
+ x->ex_kusage |= usage->data[1] << 8;
+ }
+ x->ex_flags |= EXFLAG_KUSAGE;
+ ASN1_BIT_STRING_free(usage);
+ /* Check for empty key usage according to RFC 5280 section 4.2.1.3 */
+ if (x->ex_kusage == 0) {
+ ERR_raise(ERR_LIB_X509, X509V3_R_EMPTY_KEY_USAGE);
+ x->ex_flags |= EXFLAG_INVALID;
+ }
+ } else if (i != -1) {
+ x->ex_flags |= EXFLAG_INVALID;
+ }
+
+ /* Handle extended key usage */
+ x->ex_xkusage = 0;
+ if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, &i, NULL)) != NULL) {
+ x->ex_flags |= EXFLAG_XKUSAGE;
+ for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) {
+ switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) {
+ case NID_server_auth:
+ x->ex_xkusage |= XKU_SSL_SERVER;
+ break;
+ case NID_client_auth:
+ x->ex_xkusage |= XKU_SSL_CLIENT;
+ break;
+ case NID_email_protect:
+ x->ex_xkusage |= XKU_SMIME;
+ break;
+ case NID_code_sign:
+ x->ex_xkusage |= XKU_CODE_SIGN;
+ break;
+ case NID_ms_sgc:
+ case NID_ns_sgc:
+ x->ex_xkusage |= XKU_SGC;
+ break;
+ case NID_OCSP_sign:
+ x->ex_xkusage |= XKU_OCSP_SIGN;
+ break;
+ case NID_time_stamp:
+ x->ex_xkusage |= XKU_TIMESTAMP;
+ break;
+ case NID_dvcs:
+ x->ex_xkusage |= XKU_DVCS;
+ break;
+ case NID_anyExtendedKeyUsage:
+ x->ex_xkusage |= XKU_ANYEKU;
+ break;
+ default:
+ /* Ignore unknown extended key usage */
+ break;
+ }
+ }
+ sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
+ } else if (i != -1) {
+ x->ex_flags |= EXFLAG_INVALID;
+ }
+
+ /* Handle legacy Netscape extension */
+ if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, &i, NULL)) != NULL) {
+ if (ns->length > 0)
+ x->ex_nscert = ns->data[0];
+ else
+ x->ex_nscert = 0;
+ x->ex_flags |= EXFLAG_NSCERT;
+ ASN1_BIT_STRING_free(ns);
+ } else if (i != -1) {
+ x->ex_flags |= EXFLAG_INVALID;
+ }
+
+ /* Handle subject key identifier and issuer/authority key identifier */
+ x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, &i, NULL);
+ if (x->skid == NULL && i != -1)
+ x->ex_flags |= EXFLAG_INVALID;
+
+ x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, &i, NULL);
+ if (x->akid == NULL && i != -1)
+ x->ex_flags |= EXFLAG_INVALID;
+
+ /* Check if subject name matches issuer */
+ if (X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x)) == 0) {
+ x->ex_flags |= EXFLAG_SI; /* Cert is self-issued */
+ if (X509_check_akid(x, x->akid) == X509_V_OK /* SKID matches AKID */
+ /* .. and the signature alg matches the PUBKEY alg: */
+ && check_sig_alg_match(X509_get0_pubkey(x), x) == X509_V_OK)
+ x->ex_flags |= EXFLAG_SS; /* indicate self-signed */
+ /* This is very related to ossl_x509_likely_issued(x, x) == X509_V_OK */
+ }
+
+ /* Handle subject alternative names and various other extensions */
+ x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, &i, NULL);
+ if (x->altname == NULL && i != -1)
+ x->ex_flags |= EXFLAG_INVALID;
+ x->nc = X509_get_ext_d2i(x, NID_name_constraints, &i, NULL);
+ if (x->nc == NULL && i != -1)
+ x->ex_flags |= EXFLAG_INVALID;
+
+ /* Handle CRL distribution point entries */
+ res = setup_crldp(x);
+ if (res == 0)
+ x->ex_flags |= EXFLAG_INVALID;
+ else if (res < 0)
+ goto err;
+
+#ifndef OPENSSL_NO_RFC3779
+ x->rfc3779_addr = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, &i, NULL);
+ if (x->rfc3779_addr == NULL && i != -1)
+ x->ex_flags |= EXFLAG_INVALID;
+ x->rfc3779_asid = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, &i, NULL);
+ if (x->rfc3779_asid == NULL && i != -1)
+ x->ex_flags |= EXFLAG_INVALID;
+#endif
+ for (i = 0; i < X509_get_ext_count(x); i++) {
+ X509_EXTENSION *ex = X509_get_ext(x, i);
+ int nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
+
+ if (nid == NID_freshest_crl)
+ x->ex_flags |= EXFLAG_FRESHEST;
+ if (!X509_EXTENSION_get_critical(ex))
+ continue;
+ if (!X509_supported_extension(ex)) {
+ x->ex_flags |= EXFLAG_CRITICAL;
+ break;
+ }
+ switch (nid) {
+ case NID_basic_constraints:
+ x->ex_flags |= EXFLAG_BCONS_CRITICAL;
+ break;
+ case NID_authority_key_identifier:
+ x->ex_flags |= EXFLAG_AKID_CRITICAL;
+ break;
+ case NID_subject_key_identifier:
+ x->ex_flags |= EXFLAG_SKID_CRITICAL;
+ break;
+ case NID_subject_alt_name:
+ x->ex_flags |= EXFLAG_SAN_CRITICAL;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Set x->siginf, ignoring errors due to unsupported algos */
+ (void)ossl_x509_init_sig_info(x);
+
+ x->ex_flags |= EXFLAG_SET; /* Indicate that cert has been processed */
+#ifdef tsan_st_rel
+ tsan_st_rel((TSAN_QUALIFIER int *)&x->ex_cached, 1);
+ /*
+ * Above store triggers fast lock-free check in the beginning of the
+ * function. But one has to ensure that the structure is "stable", i.e.
+ * all stores are visible on all processors. Hence the release fence.
+ */
+#endif
+ ERR_pop_to_mark();
+ if ((x->ex_flags & (EXFLAG_INVALID | EXFLAG_NO_FINGERPRINT)) == 0) {
+ CRYPTO_THREAD_unlock(x->lock);
+ return 1;
+ }
+ if ((x->ex_flags & EXFLAG_INVALID) != 0)
+ ERR_raise(ERR_LIB_X509, X509V3_R_INVALID_CERTIFICATE);
+ /* If computing sha1_hash failed the error queue already reflects this. */
+
+ err:
+ x->ex_flags |= EXFLAG_SET; /* indicate that cert has been processed */
+ CRYPTO_THREAD_unlock(x->lock);
+ return 0;
+}
+
+/*-
+ * CA checks common to all purposes
+ * return codes:
+ * 0 not a CA
+ * 1 is a CA
+ * 2 Only possible in older versions of openSSL when basicConstraints are absent
+ * new versions will not return this value. May be a CA
+ * 3 basicConstraints absent but self-signed V1.
+ * 4 basicConstraints absent but keyUsage present and keyCertSign asserted.
+ * 5 Netscape specific CA Flags present
+ */
+
+static int check_ca(const X509 *x)
+{
+ /* keyUsage if present should allow cert signing */
+ if (ku_reject(x, KU_KEY_CERT_SIGN))
+ return 0;
+ if ((x->ex_flags & EXFLAG_BCONS) != 0) {
+ /* If basicConstraints says not a CA then say so */
+ return (x->ex_flags & EXFLAG_CA) != 0;
+ } else {
+ /* We support V1 roots for... uh, I don't really know why. */
+ if ((x->ex_flags & V1_ROOT) == V1_ROOT)
+ return 3;
+ /*
+ * If key usage present it must have certSign so tolerate it
+ */
+ else if (x->ex_flags & EXFLAG_KUSAGE)
+ return 4;
+ /* Older certificates could have Netscape-specific CA types */
+ else if (x->ex_flags & EXFLAG_NSCERT && x->ex_nscert & NS_ANY_CA)
+ return 5;
+ /* Can this still be regarded a CA certificate? I doubt it. */
+ return 0;
+ }
+}
+
+void X509_set_proxy_flag(X509 *x)
+{
+ if (CRYPTO_THREAD_write_lock(x->lock)) {
+ x->ex_flags |= EXFLAG_PROXY;
+ CRYPTO_THREAD_unlock(x->lock);
+ }
+}
+
+void X509_set_proxy_pathlen(X509 *x, long l)
+{
+ x->ex_pcpathlen = l;
+}
+
+int X509_check_ca(X509 *x)
+{
+ /* Note 0 normally means "not a CA" - but in this case means error. */
+ if (!ossl_x509v3_cache_extensions(x))
+ return 0;
+
+ return check_ca(x);
+}
+
+/* Check SSL CA: common checks for SSL client and server. */
+static int check_ssl_ca(const X509 *x)
+{
+ int ca_ret = check_ca(x);
+
+ if (ca_ret == 0)
+ return 0;
+ /* Check nsCertType if present */
+ return ca_ret != 5 || (x->ex_nscert & NS_SSL_CA) != 0;
+}
+
+static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca)
+{
+ if (xku_reject(x, XKU_SSL_CLIENT))
+ return 0;
+ if (require_ca)
+ return check_ssl_ca(x);
+ /* We need to do digital signatures or key agreement */
+ if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT))
+ return 0;
+ /* nsCertType if present should allow SSL client use */
+ if (ns_reject(x, NS_SSL_CLIENT))
+ return 0;
+ return 1;
+}
+
+/*
+ * Key usage needed for TLS/SSL server: digital signature, encipherment or
+ * key agreement. The ssl code can check this more thoroughly for individual
+ * key types.
+ */
+#define KU_TLS \
+ KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT
+
+static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca)
+{
+ if (xku_reject(x, XKU_SSL_SERVER | XKU_SGC))
+ return 0;
+ if (require_ca)
+ return check_ssl_ca(x);
+
+ if (ns_reject(x, NS_SSL_SERVER))
+ return 0;
+ if (ku_reject(x, KU_TLS))
+ return 0;
+
+ return 1;
+
+}
+
+static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca)
+{
+ int ret;
+ ret = check_purpose_ssl_server(xp, x, require_ca);
+ if (!ret || require_ca)
+ return ret;
+ /* We need to encipher or Netscape complains */
+ if (ku_reject(x, KU_KEY_ENCIPHERMENT))
+ return 0;
+ return ret;
+}
+
+/* common S/MIME checks */
+static int purpose_smime(const X509 *x, int require_ca)
+{
+ if (xku_reject(x, XKU_SMIME))
+ return 0;
+ if (require_ca) {
+ int ca_ret;
+ ca_ret = check_ca(x);
+ if (ca_ret == 0)
+ return 0;
+ /* Check nsCertType if present */
+ if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA)
+ return ca_ret;
+ else
+ return 0;
+ }
+ if (x->ex_flags & EXFLAG_NSCERT) {
+ if (x->ex_nscert & NS_SMIME)
+ return 1;
+ /* Workaround for some buggy certificates */
+ if (x->ex_nscert & NS_SSL_CLIENT)
+ return 2;
+ return 0;
+ }
+ return 1;
+}
+
+static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca)
+{
+ int ret;
+ ret = purpose_smime(x, require_ca);
+ if (!ret || require_ca)
+ return ret;
+ if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION))
+ return 0;
+ return ret;
+}
+
+static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca)
+{
+ int ret;
+ ret = purpose_smime(x, require_ca);
+ if (!ret || require_ca)
+ return ret;
+ if (ku_reject(x, KU_KEY_ENCIPHERMENT))
+ return 0;
+ return ret;
+}
+
+static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca)
+{
+ if (require_ca) {
+ int ca_ret;
+ if ((ca_ret = check_ca(x)) != 2)
+ return ca_ret;
+ else
+ return 0;
+ }
+ if (ku_reject(x, KU_CRL_SIGN))
+ return 0;
+ return 1;
+}
+
+/*
+ * OCSP helper: this is *not* a full OCSP check. It just checks that each CA
+ * is valid. Additional checks must be made on the chain.
+ */
+static int check_purpose_ocsp_helper(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca)
+{
+ /*
+ * Must be a valid CA. Should we really support the "I don't know" value
+ * (2)?
+ */
+ if (require_ca)
+ return check_ca(x);
+ /* Leaf certificate is checked in OCSP_verify() */
+ return 1;
+}
+
+static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca)
+{
+ int i_ext;
+
+ /* If ca is true we must return if this is a valid CA certificate. */
+ if (require_ca)
+ return check_ca(x);
+
+ /*
+ * Check the optional key usage field:
+ * if Key Usage is present, it must be one of digitalSignature
+ * and/or nonRepudiation (other values are not consistent and shall
+ * be rejected).
+ */
+ if ((x->ex_flags & EXFLAG_KUSAGE)
+ && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) ||
+ !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE))))
+ return 0;
+
+ /* Only time stamp key usage is permitted and it's required. */
+ if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP)
+ return 0;
+
+ /* Extended Key Usage MUST be critical */
+ i_ext = X509_get_ext_by_NID(x, NID_ext_key_usage, -1);
+ if (i_ext >= 0) {
+ X509_EXTENSION *ext = X509_get_ext((X509 *)x, i_ext);
+ if (!X509_EXTENSION_get_critical(ext))
+ return 0;
+ }
+
+ return 1;
+}
+
+static int no_check_purpose(const X509_PURPOSE *xp, const X509 *x,
+ int require_ca)
+{
+ return 1;
+}
+
+/*-
+ * Various checks to see if one certificate potentially issued the second.
+ * This can be used to prune a set of possible issuer certificates which
+ * have been looked up using some simple method such as by subject name.
+ * These are:
+ * 1. issuer_name(subject) == subject_name(issuer)
+ * 2. If akid(subject) exists, it matches the respective issuer fields.
+ * 3. subject signature algorithm == issuer public key algorithm
+ * 4. If key_usage(issuer) exists, it allows for signing subject.
+ * Note that this does not include actually checking the signature.
+ * Returns 0 for OK, or positive for reason for mismatch
+ * where reason codes match those for X509_verify_cert().
+ */
+int X509_check_issued(X509 *issuer, X509 *subject)
+{
+ int ret;
+
+ if ((ret = ossl_x509_likely_issued(issuer, subject)) != X509_V_OK)
+ return ret;
+ return ossl_x509_signing_allowed(issuer, subject);
+}
+
+/* do the checks 1., 2., and 3. as described above for X509_check_issued() */
+int ossl_x509_likely_issued(X509 *issuer, X509 *subject)
+{
+ int ret;
+
+ if (X509_NAME_cmp(X509_get_subject_name(issuer),
+ X509_get_issuer_name(subject)) != 0)
+ return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
+
+ /* set issuer->skid and subject->akid */
+ if (!ossl_x509v3_cache_extensions(issuer)
+ || !ossl_x509v3_cache_extensions(subject))
+ return X509_V_ERR_UNSPECIFIED;
+
+ ret = X509_check_akid(issuer, subject->akid);
+ if (ret != X509_V_OK)
+ return ret;
+
+ /* Check if the subject signature alg matches the issuer's PUBKEY alg */
+ return check_sig_alg_match(X509_get0_pubkey(issuer), subject);
+}
+
+/*-
+ * Check if certificate I<issuer> is allowed to issue certificate I<subject>
+ * according to the B<keyUsage> field of I<issuer> if present
+ * depending on any proxyCertInfo extension of I<subject>.
+ * Returns 0 for OK, or positive for reason for rejection
+ * where reason codes match those for X509_verify_cert().
+ */
+int ossl_x509_signing_allowed(const X509 *issuer, const X509 *subject)
+{
+ if (subject->ex_flags & EXFLAG_PROXY) {
+ if (ku_reject(issuer, KU_DIGITAL_SIGNATURE))
+ return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE;
+ } else if (ku_reject(issuer, KU_KEY_CERT_SIGN))
+ return X509_V_ERR_KEYUSAGE_NO_CERTSIGN;
+ return X509_V_OK;
+}
+
+int X509_check_akid(const X509 *issuer, const AUTHORITY_KEYID *akid)
+{
+ if (akid == NULL)
+ return X509_V_OK;
+
+ /* Check key ids (if present) */
+ if (akid->keyid && issuer->skid &&
+ ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid))
+ return X509_V_ERR_AKID_SKID_MISMATCH;
+ /* Check serial number */
+ if (akid->serial &&
+ ASN1_INTEGER_cmp(X509_get0_serialNumber(issuer), akid->serial))
+ return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
+ /* Check issuer name */
+ if (akid->issuer) {
+ /*
+ * Ugh, for some peculiar reason AKID includes SEQUENCE OF
+ * GeneralName. So look for a DirName. There may be more than one but
+ * we only take any notice of the first.
+ */
+ GENERAL_NAMES *gens;
+ GENERAL_NAME *gen;
+ X509_NAME *nm = NULL;
+ int i;
+ gens = akid->issuer;
+ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+ gen = sk_GENERAL_NAME_value(gens, i);
+ if (gen->type == GEN_DIRNAME) {
+ nm = gen->d.dirn;
+ break;
+ }
+ }
+ if (nm != NULL && X509_NAME_cmp(nm, X509_get_issuer_name(issuer)) != 0)
+ return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
+ }
+ return X509_V_OK;
+}
+
+uint32_t X509_get_extension_flags(X509 *x)
+{
+ /* Call for side-effect of computing hash and caching extensions */
+ X509_check_purpose(x, -1, 0);
+ return x->ex_flags;
+}
+
+uint32_t X509_get_key_usage(X509 *x)
+{
+ /* Call for side-effect of computing hash and caching extensions */
+ if (X509_check_purpose(x, -1, 0) != 1)
+ return 0;
+ if (x->ex_flags & EXFLAG_KUSAGE)
+ return x->ex_kusage;
+ return UINT32_MAX;
+}
+
+uint32_t X509_get_extended_key_usage(X509 *x)
+{
+ /* Call for side-effect of computing hash and caching extensions */
+ if (X509_check_purpose(x, -1, 0) != 1)
+ return 0;
+ if (x->ex_flags & EXFLAG_XKUSAGE)
+ return x->ex_xkusage;
+ return UINT32_MAX;
+}
+
+const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x)
+{
+ /* Call for side-effect of computing hash and caching extensions */
+ if (X509_check_purpose(x, -1, 0) != 1)
+ return NULL;
+ return x->skid;
+}
+
+const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x)
+{
+ /* Call for side-effect of computing hash and caching extensions */
+ if (X509_check_purpose(x, -1, 0) != 1)
+ return NULL;
+ return (x->akid != NULL ? x->akid->keyid : NULL);
+}
+
+const GENERAL_NAMES *X509_get0_authority_issuer(X509 *x)
+{
+ /* Call for side-effect of computing hash and caching extensions */
+ if (X509_check_purpose(x, -1, 0) != 1)
+ return NULL;
+ return (x->akid != NULL ? x->akid->issuer : NULL);
+}
+
+const ASN1_INTEGER *X509_get0_authority_serial(X509 *x)
+{
+ /* Call for side-effect of computing hash and caching extensions */
+ if (X509_check_purpose(x, -1, 0) != 1)
+ return NULL;
+ return (x->akid != NULL ? x->akid->serial : NULL);
+}
+
+long X509_get_pathlen(X509 *x)
+{
+ /* Called for side effect of caching extensions */
+ if (X509_check_purpose(x, -1, 0) != 1
+ || (x->ex_flags & EXFLAG_BCONS) == 0)
+ return -1;
+ return x->ex_pathlen;
+}
+
+long X509_get_proxy_pathlen(X509 *x)
+{
+ /* Called for side effect of caching extensions */
+ if (X509_check_purpose(x, -1, 0) != 1
+ || (x->ex_flags & EXFLAG_PROXY) == 0)
+ return -1;
+ return x->ex_pcpathlen;
+}
diff --git a/crypto/x509/v3_san.c b/crypto/x509/v3_san.c
new file mode 100644
index 000000000000..c081f02e19e4
--- /dev/null
+++ b/crypto/x509/v3_san.c
@@ -0,0 +1,691 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include "crypto/x509.h"
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include <openssl/bio.h>
+#include "ext_dat.h"
+
+static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval);
+static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval);
+static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
+static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
+static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
+static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
+
+const X509V3_EXT_METHOD ossl_v3_alt[3] = {
+ {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
+ 0, 0, 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
+ (X509V3_EXT_V2I)v2i_subject_alt,
+ NULL, NULL, NULL},
+
+ {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
+ 0, 0, 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
+ (X509V3_EXT_V2I)v2i_issuer_alt,
+ NULL, NULL, NULL},
+
+ {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES),
+ 0, 0, 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
+ NULL, NULL, NULL, NULL},
+};
+
+STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
+ GENERAL_NAMES *gens,
+ STACK_OF(CONF_VALUE) *ret)
+{
+ int i;
+ GENERAL_NAME *gen;
+ STACK_OF(CONF_VALUE) *tmpret = NULL, *origret = ret;
+
+ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+ gen = sk_GENERAL_NAME_value(gens, i);
+ /*
+ * i2v_GENERAL_NAME allocates ret if it is NULL. If something goes
+ * wrong we need to free the stack - but only if it was empty when we
+ * originally entered this function.
+ */
+ tmpret = i2v_GENERAL_NAME(method, gen, ret);
+ if (tmpret == NULL) {
+ if (origret == NULL)
+ sk_CONF_VALUE_pop_free(ret, X509V3_conf_free);
+ return NULL;
+ }
+ ret = tmpret;
+ }
+ if (ret == NULL)
+ return sk_CONF_VALUE_new_null();
+ return ret;
+}
+
+STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
+ GENERAL_NAME *gen,
+ STACK_OF(CONF_VALUE) *ret)
+{
+ char othername[300];
+ char oline[256], *tmp;
+
+ switch (gen->type) {
+ case GEN_OTHERNAME:
+ switch (OBJ_obj2nid(gen->d.otherName->type_id)) {
+ case NID_id_on_SmtpUTF8Mailbox:
+ if (gen->d.otherName->value->type != V_ASN1_UTF8STRING
+ || !x509v3_add_len_value_uchar("othername: SmtpUTF8Mailbox:",
+ gen->d.otherName->value->value.utf8string->data,
+ gen->d.otherName->value->value.utf8string->length,
+ &ret))
+ return NULL;
+ break;
+ case NID_XmppAddr:
+ if (gen->d.otherName->value->type != V_ASN1_UTF8STRING
+ || !x509v3_add_len_value_uchar("othername: XmppAddr:",
+ gen->d.otherName->value->value.utf8string->data,
+ gen->d.otherName->value->value.utf8string->length,
+ &ret))
+ return NULL;
+ break;
+ case NID_SRVName:
+ if (gen->d.otherName->value->type != V_ASN1_IA5STRING
+ || !x509v3_add_len_value_uchar("othername: SRVName:",
+ gen->d.otherName->value->value.ia5string->data,
+ gen->d.otherName->value->value.ia5string->length,
+ &ret))
+ return NULL;
+ break;
+ case NID_ms_upn:
+ if (gen->d.otherName->value->type != V_ASN1_UTF8STRING
+ || !x509v3_add_len_value_uchar("othername: UPN:",
+ gen->d.otherName->value->value.utf8string->data,
+ gen->d.otherName->value->value.utf8string->length,
+ &ret))
+ return NULL;
+ break;
+ case NID_NAIRealm:
+ if (gen->d.otherName->value->type != V_ASN1_UTF8STRING
+ || !x509v3_add_len_value_uchar("othername: NAIRealm:",
+ gen->d.otherName->value->value.utf8string->data,
+ gen->d.otherName->value->value.utf8string->length,
+ &ret))
+ return NULL;
+ break;
+ default:
+ if (OBJ_obj2txt(oline, sizeof(oline), gen->d.otherName->type_id, 0) > 0)
+ BIO_snprintf(othername, sizeof(othername), "othername: %s:",
+ oline);
+ else
+ OPENSSL_strlcpy(othername, "othername:", sizeof(othername));
+
+ /* check if the value is something printable */
+ if (gen->d.otherName->value->type == V_ASN1_IA5STRING) {
+ if (x509v3_add_len_value_uchar(othername,
+ gen->d.otherName->value->value.ia5string->data,
+ gen->d.otherName->value->value.ia5string->length,
+ &ret))
+ return ret;
+ }
+ if (gen->d.otherName->value->type == V_ASN1_UTF8STRING) {
+ if (x509v3_add_len_value_uchar(othername,
+ gen->d.otherName->value->value.utf8string->data,
+ gen->d.otherName->value->value.utf8string->length,
+ &ret))
+ return ret;
+ }
+ if (!X509V3_add_value(othername, "<unsupported>", &ret))
+ return NULL;
+ break;
+ }
+ break;
+
+ case GEN_X400:
+ if (!X509V3_add_value("X400Name", "<unsupported>", &ret))
+ return NULL;
+ break;
+
+ case GEN_EDIPARTY:
+ if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret))
+ return NULL;
+ break;
+
+ case GEN_EMAIL:
+ if (!x509v3_add_len_value_uchar("email", gen->d.ia5->data,
+ gen->d.ia5->length, &ret))
+ return NULL;
+ break;
+
+ case GEN_DNS:
+ if (!x509v3_add_len_value_uchar("DNS", gen->d.ia5->data,
+ gen->d.ia5->length, &ret))
+ return NULL;
+ break;
+
+ case GEN_URI:
+ if (!x509v3_add_len_value_uchar("URI", gen->d.ia5->data,
+ gen->d.ia5->length, &ret))
+ return NULL;
+ break;
+
+ case GEN_DIRNAME:
+ if (X509_NAME_oneline(gen->d.dirn, oline, sizeof(oline)) == NULL
+ || !X509V3_add_value("DirName", oline, &ret))
+ return NULL;
+ break;
+
+ case GEN_IPADD:
+ tmp = ossl_ipaddr_to_asc(gen->d.ip->data, gen->d.ip->length);
+ if (tmp == NULL || !X509V3_add_value("IP Address", tmp, &ret))
+ ret = NULL;
+ OPENSSL_free(tmp);
+ break;
+
+ case GEN_RID:
+ i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
+ if (!X509V3_add_value("Registered ID", oline, &ret))
+ return NULL;
+ break;
+ }
+ return ret;
+}
+
+int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
+{
+ char *tmp;
+ int nid;
+
+ switch (gen->type) {
+ case GEN_OTHERNAME:
+ nid = OBJ_obj2nid(gen->d.otherName->type_id);
+ /* Validate the types are as we expect before we use them */
+ if ((nid == NID_SRVName
+ && gen->d.otherName->value->type != V_ASN1_IA5STRING)
+ || (nid != NID_SRVName
+ && gen->d.otherName->value->type != V_ASN1_UTF8STRING)) {
+ BIO_printf(out, "othername:<unsupported>");
+ break;
+ }
+
+ switch (nid) {
+ case NID_id_on_SmtpUTF8Mailbox:
+ BIO_printf(out, "othername:SmtpUTF8Mailbox:%.*s",
+ gen->d.otherName->value->value.utf8string->length,
+ gen->d.otherName->value->value.utf8string->data);
+ break;
+ case NID_XmppAddr:
+ BIO_printf(out, "othername:XmppAddr:%.*s",
+ gen->d.otherName->value->value.utf8string->length,
+ gen->d.otherName->value->value.utf8string->data);
+ break;
+ case NID_SRVName:
+ BIO_printf(out, "othername:SRVName:%.*s",
+ gen->d.otherName->value->value.ia5string->length,
+ gen->d.otherName->value->value.ia5string->data);
+ break;
+ case NID_ms_upn:
+ BIO_printf(out, "othername:UPN:%.*s",
+ gen->d.otherName->value->value.utf8string->length,
+ gen->d.otherName->value->value.utf8string->data);
+ break;
+ case NID_NAIRealm:
+ BIO_printf(out, "othername:NAIRealm:%.*s",
+ gen->d.otherName->value->value.utf8string->length,
+ gen->d.otherName->value->value.utf8string->data);
+ break;
+ default:
+ BIO_printf(out, "othername:<unsupported>");
+ break;
+ }
+ break;
+
+ case GEN_X400:
+ BIO_printf(out, "X400Name:<unsupported>");
+ break;
+
+ case GEN_EDIPARTY:
+ /* Maybe fix this: it is supported now */
+ BIO_printf(out, "EdiPartyName:<unsupported>");
+ break;
+
+ case GEN_EMAIL:
+ BIO_printf(out, "email:");
+ ASN1_STRING_print(out, gen->d.ia5);
+ break;
+
+ case GEN_DNS:
+ BIO_printf(out, "DNS:");
+ ASN1_STRING_print(out, gen->d.ia5);
+ break;
+
+ case GEN_URI:
+ BIO_printf(out, "URI:");
+ ASN1_STRING_print(out, gen->d.ia5);
+ break;
+
+ case GEN_DIRNAME:
+ BIO_printf(out, "DirName:");
+ X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
+ break;
+
+ case GEN_IPADD:
+ tmp = ossl_ipaddr_to_asc(gen->d.ip->data, gen->d.ip->length);
+ if (tmp == NULL)
+ return 0;
+ BIO_printf(out, "IP Address:%s", tmp);
+ OPENSSL_free(tmp);
+ break;
+
+ case GEN_RID:
+ BIO_printf(out, "Registered ID:");
+ i2a_ASN1_OBJECT(out, gen->d.rid);
+ break;
+ }
+ return 1;
+}
+
+static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval)
+{
+ const int num = sk_CONF_VALUE_num(nval);
+ GENERAL_NAMES *gens = sk_GENERAL_NAME_new_reserve(NULL, num);
+ int i;
+
+ if (gens == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ sk_GENERAL_NAME_free(gens);
+ return NULL;
+ }
+ for (i = 0; i < num; i++) {
+ CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
+
+ if (!ossl_v3_name_cmp(cnf->name, "issuer")
+ && cnf->value && strcmp(cnf->value, "copy") == 0) {
+ if (!copy_issuer(ctx, gens))
+ goto err;
+ } else {
+ GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf);
+
+ if (gen == NULL)
+ goto err;
+ sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
+ }
+ }
+ return gens;
+ err:
+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+ return NULL;
+}
+
+/* Append subject altname of issuer to issuer alt name of subject */
+
+static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
+{
+ GENERAL_NAMES *ialt;
+ GENERAL_NAME *gen;
+ X509_EXTENSION *ext;
+ int i, num;
+
+ if (ctx != NULL && (ctx->flags & X509V3_CTX_TEST) != 0)
+ return 1;
+ if (!ctx || !ctx->issuer_cert) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_ISSUER_DETAILS);
+ goto err;
+ }
+ i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
+ if (i < 0)
+ return 1;
+ if ((ext = X509_get_ext(ctx->issuer_cert, i)) == NULL
+ || (ialt = X509V3_EXT_d2i(ext)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_ISSUER_DECODE_ERROR);
+ goto err;
+ }
+
+ num = sk_GENERAL_NAME_num(ialt);
+ if (!sk_GENERAL_NAME_reserve(gens, num)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ for (i = 0; i < num; i++) {
+ gen = sk_GENERAL_NAME_value(ialt, i);
+ sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
+ }
+ sk_GENERAL_NAME_free(ialt);
+
+ return 1;
+
+ err:
+ return 0;
+
+}
+
+static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval)
+{
+ GENERAL_NAMES *gens;
+ CONF_VALUE *cnf;
+ const int num = sk_CONF_VALUE_num(nval);
+ int i;
+
+ gens = sk_GENERAL_NAME_new_reserve(NULL, num);
+ if (gens == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ sk_GENERAL_NAME_free(gens);
+ return NULL;
+ }
+
+ for (i = 0; i < num; i++) {
+ cnf = sk_CONF_VALUE_value(nval, i);
+ if (ossl_v3_name_cmp(cnf->name, "email") == 0
+ && cnf->value && strcmp(cnf->value, "copy") == 0) {
+ if (!copy_email(ctx, gens, 0))
+ goto err;
+ } else if (ossl_v3_name_cmp(cnf->name, "email") == 0
+ && cnf->value && strcmp(cnf->value, "move") == 0) {
+ if (!copy_email(ctx, gens, 1))
+ goto err;
+ } else {
+ GENERAL_NAME *gen;
+ if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
+ goto err;
+ sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
+ }
+ }
+ return gens;
+ err:
+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+ return NULL;
+}
+
+/*
+ * Copy any email addresses in a certificate or request to GENERAL_NAMES
+ */
+
+static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
+{
+ X509_NAME *nm;
+ ASN1_IA5STRING *email = NULL;
+ X509_NAME_ENTRY *ne;
+ GENERAL_NAME *gen = NULL;
+ int i = -1;
+
+ if (ctx != NULL && (ctx->flags & X509V3_CTX_TEST) != 0)
+ return 1;
+ if (ctx == NULL
+ || (ctx->subject_cert == NULL && ctx->subject_req == NULL)) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_SUBJECT_DETAILS);
+ return 0;
+ }
+ /* Find the subject name */
+ nm = ctx->subject_cert != NULL ?
+ X509_get_subject_name(ctx->subject_cert) :
+ X509_REQ_get_subject_name(ctx->subject_req);
+
+ /* Now add any email address(es) to STACK */
+ while ((i = X509_NAME_get_index_by_NID(nm,
+ NID_pkcs9_emailAddress, i)) >= 0) {
+ ne = X509_NAME_get_entry(nm, i);
+ email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne));
+ if (move_p) {
+ X509_NAME_delete_entry(nm, i);
+ X509_NAME_ENTRY_free(ne);
+ i--;
+ }
+ if (email == NULL || (gen = GENERAL_NAME_new()) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ gen->d.ia5 = email;
+ email = NULL;
+ gen->type = GEN_EMAIL;
+ if (!sk_GENERAL_NAME_push(gens, gen)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ gen = NULL;
+ }
+
+ return 1;
+
+ err:
+ GENERAL_NAME_free(gen);
+ ASN1_IA5STRING_free(email);
+ return 0;
+
+}
+
+GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+{
+ GENERAL_NAME *gen;
+ GENERAL_NAMES *gens;
+ CONF_VALUE *cnf;
+ const int num = sk_CONF_VALUE_num(nval);
+ int i;
+
+ gens = sk_GENERAL_NAME_new_reserve(NULL, num);
+ if (gens == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ sk_GENERAL_NAME_free(gens);
+ return NULL;
+ }
+
+ for (i = 0; i < num; i++) {
+ cnf = sk_CONF_VALUE_value(nval, i);
+ if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
+ goto err;
+ sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
+ }
+ return gens;
+ err:
+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+ return NULL;
+}
+
+GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, CONF_VALUE *cnf)
+{
+ return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
+}
+
+GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
+ const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, int gen_type, const char *value,
+ int is_nc)
+{
+ char is_string = 0;
+ GENERAL_NAME *gen = NULL;
+
+ if (!value) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_MISSING_VALUE);
+ return NULL;
+ }
+
+ if (out)
+ gen = out;
+ else {
+ gen = GENERAL_NAME_new();
+ if (gen == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ }
+
+ switch (gen_type) {
+ case GEN_URI:
+ case GEN_EMAIL:
+ case GEN_DNS:
+ is_string = 1;
+ break;
+
+ case GEN_RID:
+ {
+ ASN1_OBJECT *obj;
+ if ((obj = OBJ_txt2obj(value, 0)) == NULL) {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_BAD_OBJECT,
+ "value=%s", value);
+ goto err;
+ }
+ gen->d.rid = obj;
+ }
+ break;
+
+ case GEN_IPADD:
+ if (is_nc)
+ gen->d.ip = a2i_IPADDRESS_NC(value);
+ else
+ gen->d.ip = a2i_IPADDRESS(value);
+ if (gen->d.ip == NULL) {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_BAD_IP_ADDRESS,
+ "value=%s", value);
+ goto err;
+ }
+ break;
+
+ case GEN_DIRNAME:
+ if (!do_dirname(gen, value, ctx)) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_DIRNAME_ERROR);
+ goto err;
+ }
+ break;
+
+ case GEN_OTHERNAME:
+ if (!do_othername(gen, value, ctx)) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_OTHERNAME_ERROR);
+ goto err;
+ }
+ break;
+ default:
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_UNSUPPORTED_TYPE);
+ goto err;
+ }
+
+ if (is_string) {
+ if ((gen->d.ia5 = ASN1_IA5STRING_new()) == NULL ||
+ !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value,
+ strlen(value))) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ gen->type = gen_type;
+
+ return gen;
+
+ err:
+ if (!out)
+ GENERAL_NAME_free(gen);
+ return NULL;
+}
+
+GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
+ const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc)
+{
+ int type;
+
+ char *name, *value;
+
+ name = cnf->name;
+ value = cnf->value;
+
+ if (!value) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_MISSING_VALUE);
+ return NULL;
+ }
+
+ if (!ossl_v3_name_cmp(name, "email"))
+ type = GEN_EMAIL;
+ else if (!ossl_v3_name_cmp(name, "URI"))
+ type = GEN_URI;
+ else if (!ossl_v3_name_cmp(name, "DNS"))
+ type = GEN_DNS;
+ else if (!ossl_v3_name_cmp(name, "RID"))
+ type = GEN_RID;
+ else if (!ossl_v3_name_cmp(name, "IP"))
+ type = GEN_IPADD;
+ else if (!ossl_v3_name_cmp(name, "dirName"))
+ type = GEN_DIRNAME;
+ else if (!ossl_v3_name_cmp(name, "otherName"))
+ type = GEN_OTHERNAME;
+ else {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_UNSUPPORTED_OPTION,
+ "name=%s", name);
+ return NULL;
+ }
+
+ return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
+
+}
+
+static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
+{
+ char *objtmp = NULL, *p;
+ int objlen;
+
+ if ((p = strchr(value, ';')) == NULL)
+ return 0;
+ if ((gen->d.otherName = OTHERNAME_new()) == NULL)
+ return 0;
+ /*
+ * Free this up because we will overwrite it. no need to free type_id
+ * because it is static
+ */
+ ASN1_TYPE_free(gen->d.otherName->value);
+ if ((gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)) == NULL)
+ return 0;
+ objlen = p - value;
+ objtmp = OPENSSL_strndup(value, objlen);
+ if (objtmp == NULL)
+ return 0;
+ gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
+ OPENSSL_free(objtmp);
+ if (!gen->d.otherName->type_id)
+ return 0;
+ return 1;
+}
+
+static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
+{
+ int ret = 0;
+ STACK_OF(CONF_VALUE) *sk = NULL;
+ X509_NAME *nm;
+
+ if ((nm = X509_NAME_new()) == NULL)
+ goto err;
+ sk = X509V3_get_section(ctx, value);
+ if (!sk) {
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_SECTION_NOT_FOUND,
+ "section=%s", value);
+ goto err;
+ }
+ /* FIXME: should allow other character types... */
+ ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
+ if (!ret)
+ goto err;
+ gen->d.dirn = nm;
+
+err:
+ if (ret == 0)
+ X509_NAME_free(nm);
+ X509V3_section_free(ctx, sk);
+ return ret;
+}
diff --git a/crypto/x509/v3_skid.c b/crypto/x509/v3_skid.c
new file mode 100644
index 000000000000..18223f2ef496
--- /dev/null
+++ b/crypto/x509/v3_skid.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/x509v3.h>
+#include "crypto/x509.h"
+#include "ext_dat.h"
+
+static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, char *str);
+const X509V3_EXT_METHOD ossl_v3_skey_id = {
+ NID_subject_key_identifier, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING),
+ 0, 0, 0, 0,
+ (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING,
+ (X509V3_EXT_S2I)s2i_skey_id,
+ 0, 0, 0, 0,
+ NULL
+};
+
+char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
+ const ASN1_OCTET_STRING *oct)
+{
+ return OPENSSL_buf2hexstr(oct->data, oct->length);
+}
+
+ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, const char *str)
+{
+ ASN1_OCTET_STRING *oct;
+ long length;
+
+ if ((oct = ASN1_OCTET_STRING_new()) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if ((oct->data = OPENSSL_hexstr2buf(str, &length)) == NULL) {
+ ASN1_OCTET_STRING_free(oct);
+ return NULL;
+ }
+
+ oct->length = length;
+
+ return oct;
+
+}
+
+ASN1_OCTET_STRING *ossl_x509_pubkey_hash(X509_PUBKEY *pubkey)
+{
+ ASN1_OCTET_STRING *oct;
+ const unsigned char *pk;
+ int pklen;
+ unsigned char pkey_dig[EVP_MAX_MD_SIZE];
+ unsigned int diglen;
+ const char *propq;
+ OSSL_LIB_CTX *libctx;
+ EVP_MD *md;
+
+ if (pubkey == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_PUBLIC_KEY);
+ return NULL;
+ }
+ if (!ossl_x509_PUBKEY_get0_libctx(&libctx, &propq, pubkey))
+ return NULL;
+ if ((md = EVP_MD_fetch(libctx, SN_sha1, propq)) == NULL)
+ return NULL;
+ if ((oct = ASN1_OCTET_STRING_new()) == NULL) {
+ EVP_MD_free(md);
+ return NULL;
+ }
+
+ X509_PUBKEY_get0_param(NULL, &pk, &pklen, NULL, pubkey);
+ if (EVP_Digest(pk, pklen, pkey_dig, &diglen, md, NULL)
+ && ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) {
+ EVP_MD_free(md);
+ return oct;
+ }
+
+ EVP_MD_free(md);
+ ASN1_OCTET_STRING_free(oct);
+ return NULL;
+}
+
+static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, char *str)
+{
+ if (strcmp(str, "none") == 0)
+ return ASN1_OCTET_STRING_new(); /* dummy */
+
+ if (strcmp(str, "hash") != 0)
+ return s2i_ASN1_OCTET_STRING(method, ctx /* not used */, str);
+
+ if (ctx != NULL && (ctx->flags & X509V3_CTX_TEST) != 0)
+ return ASN1_OCTET_STRING_new();
+ if (ctx == NULL
+ || (ctx->subject_cert == NULL && ctx->subject_req == NULL)) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_SUBJECT_DETAILS);
+ return NULL;
+ }
+
+ return ossl_x509_pubkey_hash(ctx->subject_cert != NULL ?
+ ctx->subject_cert->cert_info.key :
+ ctx->subject_req->req_info.pubkey);
+}
diff --git a/crypto/x509/v3_sxnet.c b/crypto/x509/v3_sxnet.c
new file mode 100644
index 000000000000..ca46dc1a5c32
--- /dev/null
+++ b/crypto/x509/v3_sxnet.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509v3.h>
+#include "ext_dat.h"
+
+/* Support for Thawte strong extranet extension */
+
+#define SXNET_TEST
+
+static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out,
+ int indent);
+#ifdef SXNET_TEST
+static SXNET *sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval);
+#endif
+const X509V3_EXT_METHOD ossl_v3_sxnet = {
+ NID_sxnet, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(SXNET),
+ 0, 0, 0, 0,
+ 0, 0,
+ 0,
+#ifdef SXNET_TEST
+ (X509V3_EXT_V2I)sxnet_v2i,
+#else
+ 0,
+#endif
+ (X509V3_EXT_I2R)sxnet_i2r,
+ 0,
+ NULL
+};
+
+ASN1_SEQUENCE(SXNETID) = {
+ ASN1_SIMPLE(SXNETID, zone, ASN1_INTEGER),
+ ASN1_SIMPLE(SXNETID, user, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(SXNETID)
+
+IMPLEMENT_ASN1_FUNCTIONS(SXNETID)
+
+ASN1_SEQUENCE(SXNET) = {
+ ASN1_SIMPLE(SXNET, version, ASN1_INTEGER),
+ ASN1_SEQUENCE_OF(SXNET, ids, SXNETID)
+} ASN1_SEQUENCE_END(SXNET)
+
+IMPLEMENT_ASN1_FUNCTIONS(SXNET)
+
+static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out,
+ int indent)
+{
+ int64_t v;
+ char *tmp;
+ SXNETID *id;
+ int i;
+
+ /*
+ * Since we add 1 to the version number to display it, we don't support
+ * LONG_MAX since that would cause on overflow.
+ */
+ if (!ASN1_INTEGER_get_int64(&v, sx->version)
+ || v >= LONG_MAX
+ || v < LONG_MIN) {
+ BIO_printf(out, "%*sVersion: <unsupported>", indent, "");
+ } else {
+ long vl = (long)v;
+
+ BIO_printf(out, "%*sVersion: %ld (0x%lX)", indent, "", vl + 1, vl);
+ }
+ for (i = 0; i < sk_SXNETID_num(sx->ids); i++) {
+ id = sk_SXNETID_value(sx->ids, i);
+ tmp = i2s_ASN1_INTEGER(NULL, id->zone);
+ if (tmp == NULL)
+ return 0;
+ BIO_printf(out, "\n%*sZone: %s, User: ", indent, "", tmp);
+ OPENSSL_free(tmp);
+ ASN1_STRING_print(out, id->user);
+ }
+ return 1;
+}
+
+#ifdef SXNET_TEST
+
+/*
+ * NBB: this is used for testing only. It should *not* be used for anything
+ * else because it will just take static IDs from the configuration file and
+ * they should really be separate values for each user.
+ */
+
+static SXNET *sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval)
+{
+ CONF_VALUE *cnf;
+ SXNET *sx = NULL;
+ int i;
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ cnf = sk_CONF_VALUE_value(nval, i);
+ if (!SXNET_add_id_asc(&sx, cnf->name, cnf->value, -1))
+ return NULL;
+ }
+ return sx;
+}
+
+#endif
+
+/* Strong Extranet utility functions */
+
+/* Add an id given the zone as an ASCII number */
+
+int SXNET_add_id_asc(SXNET **psx, const char *zone, const char *user, int userlen)
+{
+ ASN1_INTEGER *izone;
+
+ if ((izone = s2i_ASN1_INTEGER(NULL, zone)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_ERROR_CONVERTING_ZONE);
+ return 0;
+ }
+ return SXNET_add_id_INTEGER(psx, izone, user, userlen);
+}
+
+/* Add an id given the zone as an unsigned long */
+
+int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, const char *user,
+ int userlen)
+{
+ ASN1_INTEGER *izone;
+
+ if ((izone = ASN1_INTEGER_new()) == NULL
+ || !ASN1_INTEGER_set(izone, lzone)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ ASN1_INTEGER_free(izone);
+ return 0;
+ }
+ return SXNET_add_id_INTEGER(psx, izone, user, userlen);
+
+}
+
+/*
+ * Add an id given the zone as an ASN1_INTEGER. Note this version uses the
+ * passed integer and doesn't make a copy so don't free it up afterwards.
+ */
+
+int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *zone, const char *user,
+ int userlen)
+{
+ SXNET *sx = NULL;
+ SXNETID *id = NULL;
+
+ if (psx == NULL || zone == NULL || user == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
+ return 0;
+ }
+ if (userlen == -1)
+ userlen = strlen(user);
+ if (userlen > 64) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_USER_TOO_LONG);
+ return 0;
+ }
+ if (*psx == NULL) {
+ if ((sx = SXNET_new()) == NULL)
+ goto err;
+ if (!ASN1_INTEGER_set(sx->version, 0))
+ goto err;
+ } else
+ sx = *psx;
+ if (SXNET_get_id_INTEGER(sx, zone)) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_DUPLICATE_ZONE_ID);
+ if (*psx == NULL)
+ SXNET_free(sx);
+ return 0;
+ }
+
+ if ((id = SXNETID_new()) == NULL)
+ goto err;
+ if (userlen == -1)
+ userlen = strlen(user);
+
+ if (!ASN1_OCTET_STRING_set(id->user, (const unsigned char *)user, userlen))
+ goto err;
+ if (!sk_SXNETID_push(sx->ids, id))
+ goto err;
+ id->zone = zone;
+ *psx = sx;
+ return 1;
+
+ err:
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ SXNETID_free(id);
+ if (*psx == NULL)
+ SXNET_free(sx);
+ return 0;
+}
+
+ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, const char *zone)
+{
+ ASN1_INTEGER *izone;
+ ASN1_OCTET_STRING *oct;
+
+ if ((izone = s2i_ASN1_INTEGER(NULL, zone)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_ERROR_CONVERTING_ZONE);
+ return NULL;
+ }
+ oct = SXNET_get_id_INTEGER(sx, izone);
+ ASN1_INTEGER_free(izone);
+ return oct;
+}
+
+ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone)
+{
+ ASN1_INTEGER *izone;
+ ASN1_OCTET_STRING *oct;
+
+ if ((izone = ASN1_INTEGER_new()) == NULL
+ || !ASN1_INTEGER_set(izone, lzone)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ ASN1_INTEGER_free(izone);
+ return NULL;
+ }
+ oct = SXNET_get_id_INTEGER(sx, izone);
+ ASN1_INTEGER_free(izone);
+ return oct;
+}
+
+ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone)
+{
+ SXNETID *id;
+ int i;
+ for (i = 0; i < sk_SXNETID_num(sx->ids); i++) {
+ id = sk_SXNETID_value(sx->ids, i);
+ if (!ASN1_INTEGER_cmp(id->zone, zone))
+ return id->user;
+ }
+ return NULL;
+}
diff --git a/crypto/x509/v3_tlsf.c b/crypto/x509/v3_tlsf.c
new file mode 100644
index 000000000000..3a457fa57bee
--- /dev/null
+++ b/crypto/x509/v3_tlsf.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "e_os.h"
+#include "internal/cryptlib.h"
+#include <stdio.h>
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include "ext_dat.h"
+#include "x509_local.h"
+
+static STACK_OF(CONF_VALUE) *i2v_TLS_FEATURE(const X509V3_EXT_METHOD *method,
+ TLS_FEATURE *tls_feature,
+ STACK_OF(CONF_VALUE) *ext_list);
+static TLS_FEATURE *v2i_TLS_FEATURE(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval);
+
+ASN1_ITEM_TEMPLATE(TLS_FEATURE) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, TLS_FEATURE, ASN1_INTEGER)
+static_ASN1_ITEM_TEMPLATE_END(TLS_FEATURE)
+
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(TLS_FEATURE)
+
+const X509V3_EXT_METHOD ossl_v3_tls_feature = {
+ NID_tlsfeature, 0,
+ ASN1_ITEM_ref(TLS_FEATURE),
+ 0, 0, 0, 0,
+ 0, 0,
+ (X509V3_EXT_I2V)i2v_TLS_FEATURE,
+ (X509V3_EXT_V2I)v2i_TLS_FEATURE,
+ 0, 0,
+ NULL
+};
+
+
+typedef struct {
+ long num;
+ const char *name;
+} TLS_FEATURE_NAME;
+
+static TLS_FEATURE_NAME tls_feature_tbl[] = {
+ { 5, "status_request" },
+ { 17, "status_request_v2" }
+};
+
+/*
+ * i2v_TLS_FEATURE converts the TLS_FEATURE structure tls_feature into the
+ * STACK_OF(CONF_VALUE) structure ext_list. STACK_OF(CONF_VALUE) is the format
+ * used by the CONF library to represent a multi-valued extension. ext_list is
+ * returned.
+ */
+static STACK_OF(CONF_VALUE) *i2v_TLS_FEATURE(const X509V3_EXT_METHOD *method,
+ TLS_FEATURE *tls_feature,
+ STACK_OF(CONF_VALUE) *ext_list)
+{
+ int i;
+ size_t j;
+ ASN1_INTEGER *ai;
+ long tlsextid;
+ for (i = 0; i < sk_ASN1_INTEGER_num(tls_feature); i++) {
+ ai = sk_ASN1_INTEGER_value(tls_feature, i);
+ tlsextid = ASN1_INTEGER_get(ai);
+ for (j = 0; j < OSSL_NELEM(tls_feature_tbl); j++)
+ if (tlsextid == tls_feature_tbl[j].num)
+ break;
+ if (j < OSSL_NELEM(tls_feature_tbl))
+ X509V3_add_value(NULL, tls_feature_tbl[j].name, &ext_list);
+ else
+ X509V3_add_value_int(NULL, ai, &ext_list);
+ }
+ return ext_list;
+}
+
+/*
+ * v2i_TLS_FEATURE converts the multi-valued extension nval into a TLS_FEATURE
+ * structure, which is returned if the conversion is successful. In case of
+ * error, NULL is returned.
+ */
+static TLS_FEATURE *v2i_TLS_FEATURE(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+{
+ TLS_FEATURE *tlsf;
+ char *extval, *endptr;
+ ASN1_INTEGER *ai = NULL;
+ CONF_VALUE *val;
+ int i;
+ size_t j;
+ long tlsextid;
+
+ if ((tlsf = sk_ASN1_INTEGER_new_null()) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ val = sk_CONF_VALUE_value(nval, i);
+ if (val->value)
+ extval = val->value;
+ else
+ extval = val->name;
+
+ for (j = 0; j < OSSL_NELEM(tls_feature_tbl); j++)
+ if (OPENSSL_strcasecmp(extval, tls_feature_tbl[j].name) == 0)
+ break;
+ if (j < OSSL_NELEM(tls_feature_tbl))
+ tlsextid = tls_feature_tbl[j].num;
+ else {
+ tlsextid = strtol(extval, &endptr, 10);
+ if (((*endptr) != '\0') || (extval == endptr) || (tlsextid < 0) ||
+ (tlsextid > 65535)) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_SYNTAX);
+ X509V3_conf_add_error_name_value(val);
+ goto err;
+ }
+ }
+
+ if ((ai = ASN1_INTEGER_new()) == NULL
+ || !ASN1_INTEGER_set(ai, tlsextid)
+ || sk_ASN1_INTEGER_push(tlsf, ai) <= 0) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ /* So it doesn't get purged if an error occurs next time around */
+ ai = NULL;
+ }
+ return tlsf;
+
+ err:
+ sk_ASN1_INTEGER_pop_free(tlsf, ASN1_INTEGER_free);
+ ASN1_INTEGER_free(ai);
+ return NULL;
+}
diff --git a/crypto/x509/v3_utf8.c b/crypto/x509/v3_utf8.c
new file mode 100644
index 000000000000..1c4f79c4cd9b
--- /dev/null
+++ b/crypto/x509/v3_utf8.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/asn1.h>
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include "ext_dat.h"
+
+/*
+ * Subject Sign Tool (1.2.643.100.111) The name of the tool used to signs the subject (UTF8String)
+ * This extention is required to obtain the status of a qualified certificate at Russian Federation.
+ * RFC-style description is available here: https://tools.ietf.org/html/draft-deremin-rfc4491-bis-04#section-5
+ * Russian Federal Law 63 "Digital Sign" is available here: http://www.consultant.ru/document/cons_doc_LAW_112701/
+ */
+
+
+const X509V3_EXT_METHOD ossl_v3_utf8_list[1] = {
+ EXT_UTF8STRING(NID_subjectSignTool),
+};
+
+char *i2s_ASN1_UTF8STRING(X509V3_EXT_METHOD *method,
+ ASN1_UTF8STRING *utf8)
+{
+ char *tmp;
+
+ if (utf8 == NULL || utf8->length == 0) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ if ((tmp = OPENSSL_malloc(utf8->length + 1)) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ memcpy(tmp, utf8->data, utf8->length);
+ tmp[utf8->length] = 0;
+ return tmp;
+}
+
+ASN1_UTF8STRING *s2i_ASN1_UTF8STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, const char *str)
+{
+ ASN1_UTF8STRING *utf8;
+ if (str == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
+ return NULL;
+ }
+ if ((utf8 = ASN1_UTF8STRING_new()) == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ if (!ASN1_STRING_set((ASN1_STRING *)utf8, str, strlen(str))) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ ASN1_UTF8STRING_free(utf8);
+ return NULL;
+ }
+#ifdef CHARSET_EBCDIC
+ ebcdic2ascii(utf8->data, utf8->data, utf8->length);
+#endif /* CHARSET_EBCDIC */
+ return utf8;
+}
diff --git a/crypto/x509/v3_utl.c b/crypto/x509/v3_utl.c
new file mode 100644
index 000000000000..6e4ef26ed608
--- /dev/null
+++ b/crypto/x509/v3_utl.c
@@ -0,0 +1,1358 @@
+/*
+ * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* X509 v3 extension utilities */
+
+#include "e_os.h"
+#include "internal/cryptlib.h"
+#include <stdio.h>
+#include <string.h>
+#include "crypto/ctype.h"
+#include <openssl/conf.h>
+#include <openssl/crypto.h>
+#include <openssl/x509v3.h>
+#include "crypto/x509.h"
+#include <openssl/bn.h>
+#include "ext_dat.h"
+#include "x509_local.h"
+
+static char *strip_spaces(char *name);
+static int sk_strcmp(const char *const *a, const char *const *b);
+static STACK_OF(OPENSSL_STRING) *get_email(const X509_NAME *name,
+ GENERAL_NAMES *gens);
+static void str_free(OPENSSL_STRING str);
+static int append_ia5(STACK_OF(OPENSSL_STRING) **sk,
+ const ASN1_IA5STRING *email);
+
+static int ipv4_from_asc(unsigned char *v4, const char *in);
+static int ipv6_from_asc(unsigned char *v6, const char *in);
+static int ipv6_cb(const char *elem, int len, void *usr);
+static int ipv6_hex(unsigned char *out, const char *in, int inlen);
+
+/* Add a CONF_VALUE name value pair to stack */
+
+static int x509v3_add_len_value(const char *name, const char *value,
+ size_t vallen, STACK_OF(CONF_VALUE) **extlist)
+{
+ CONF_VALUE *vtmp = NULL;
+ char *tname = NULL, *tvalue = NULL;
+ int sk_allocated = (*extlist == NULL);
+
+ if (name != NULL && (tname = OPENSSL_strdup(name)) == NULL)
+ goto err;
+ if (value != NULL) {
+ /* We don't allow embeded NUL characters */
+ if (memchr(value, 0, vallen) != NULL)
+ goto err;
+ tvalue = OPENSSL_strndup(value, vallen);
+ if (tvalue == NULL)
+ goto err;
+ }
+ if ((vtmp = OPENSSL_malloc(sizeof(*vtmp))) == NULL)
+ goto err;
+ if (sk_allocated && (*extlist = sk_CONF_VALUE_new_null()) == NULL)
+ goto err;
+ vtmp->section = NULL;
+ vtmp->name = tname;
+ vtmp->value = tvalue;
+ if (!sk_CONF_VALUE_push(*extlist, vtmp))
+ goto err;
+ return 1;
+ err:
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ if (sk_allocated) {
+ sk_CONF_VALUE_free(*extlist);
+ *extlist = NULL;
+ }
+ OPENSSL_free(vtmp);
+ OPENSSL_free(tname);
+ OPENSSL_free(tvalue);
+ return 0;
+}
+
+int X509V3_add_value(const char *name, const char *value,
+ STACK_OF(CONF_VALUE) **extlist)
+{
+ return x509v3_add_len_value(name, value,
+ value != NULL ? strlen((const char *)value) : 0,
+ extlist);
+}
+
+int X509V3_add_value_uchar(const char *name, const unsigned char *value,
+ STACK_OF(CONF_VALUE) **extlist)
+{
+ return x509v3_add_len_value(name, (const char *)value,
+ value != NULL ? strlen((const char *)value) : 0,
+ extlist);
+}
+
+int x509v3_add_len_value_uchar(const char *name, const unsigned char *value,
+ size_t vallen, STACK_OF(CONF_VALUE) **extlist)
+{
+ return x509v3_add_len_value(name, (const char *)value, vallen, extlist);
+}
+
+/* Free function for STACK_OF(CONF_VALUE) */
+
+void X509V3_conf_free(CONF_VALUE *conf)
+{
+ if (!conf)
+ return;
+ OPENSSL_free(conf->name);
+ OPENSSL_free(conf->value);
+ OPENSSL_free(conf->section);
+ OPENSSL_free(conf);
+}
+
+int X509V3_add_value_bool(const char *name, int asn1_bool,
+ STACK_OF(CONF_VALUE) **extlist)
+{
+ if (asn1_bool)
+ return X509V3_add_value(name, "TRUE", extlist);
+ return X509V3_add_value(name, "FALSE", extlist);
+}
+
+int X509V3_add_value_bool_nf(const char *name, int asn1_bool,
+ STACK_OF(CONF_VALUE) **extlist)
+{
+ if (asn1_bool)
+ return X509V3_add_value(name, "TRUE", extlist);
+ return 1;
+}
+
+static char *bignum_to_string(const BIGNUM *bn)
+{
+ char *tmp, *ret;
+ size_t len;
+
+ /*
+ * Display large numbers in hex and small numbers in decimal. Converting to
+ * decimal takes quadratic time and is no more useful than hex for large
+ * numbers.
+ */
+ if (BN_num_bits(bn) < 128)
+ return BN_bn2dec(bn);
+
+ tmp = BN_bn2hex(bn);
+ if (tmp == NULL)
+ return NULL;
+
+ len = strlen(tmp) + 3;
+ ret = OPENSSL_malloc(len);
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(tmp);
+ return NULL;
+ }
+
+ /* Prepend "0x", but place it after the "-" if negative. */
+ if (tmp[0] == '-') {
+ OPENSSL_strlcpy(ret, "-0x", len);
+ OPENSSL_strlcat(ret, tmp + 1, len);
+ } else {
+ OPENSSL_strlcpy(ret, "0x", len);
+ OPENSSL_strlcat(ret, tmp, len);
+ }
+ OPENSSL_free(tmp);
+ return ret;
+}
+
+char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *a)
+{
+ BIGNUM *bntmp = NULL;
+ char *strtmp = NULL;
+
+ if (!a)
+ return NULL;
+ if ((bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) == NULL
+ || (strtmp = bignum_to_string(bntmp)) == NULL)
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ BN_free(bntmp);
+ return strtmp;
+}
+
+char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, const ASN1_INTEGER *a)
+{
+ BIGNUM *bntmp = NULL;
+ char *strtmp = NULL;
+
+ if (!a)
+ return NULL;
+ if ((bntmp = ASN1_INTEGER_to_BN(a, NULL)) == NULL
+ || (strtmp = bignum_to_string(bntmp)) == NULL)
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ BN_free(bntmp);
+ return strtmp;
+}
+
+ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value)
+{
+ BIGNUM *bn = NULL;
+ ASN1_INTEGER *aint;
+ int isneg, ishex;
+ int ret;
+
+ if (value == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_VALUE);
+ return NULL;
+ }
+ bn = BN_new();
+ if (bn == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ if (value[0] == '-') {
+ value++;
+ isneg = 1;
+ } else {
+ isneg = 0;
+ }
+
+ if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
+ value += 2;
+ ishex = 1;
+ } else {
+ ishex = 0;
+ }
+
+ if (ishex)
+ ret = BN_hex2bn(&bn, value);
+ else
+ ret = BN_dec2bn(&bn, value);
+
+ if (!ret || value[ret]) {
+ BN_free(bn);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_BN_DEC2BN_ERROR);
+ return NULL;
+ }
+
+ if (isneg && BN_is_zero(bn))
+ isneg = 0;
+
+ aint = BN_to_ASN1_INTEGER(bn, NULL);
+ BN_free(bn);
+ if (!aint) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
+ return NULL;
+ }
+ if (isneg)
+ aint->type |= V_ASN1_NEG;
+ return aint;
+}
+
+int X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint,
+ STACK_OF(CONF_VALUE) **extlist)
+{
+ char *strtmp;
+ int ret;
+
+ if (!aint)
+ return 1;
+ if ((strtmp = i2s_ASN1_INTEGER(NULL, aint)) == NULL)
+ return 0;
+ ret = X509V3_add_value(name, strtmp, extlist);
+ OPENSSL_free(strtmp);
+ return ret;
+}
+
+int X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool)
+{
+ const char *btmp;
+
+ if ((btmp = value->value) == NULL)
+ goto err;
+ if (strcmp(btmp, "TRUE") == 0
+ || strcmp(btmp, "true") == 0
+ || strcmp(btmp, "Y") == 0
+ || strcmp(btmp, "y") == 0
+ || strcmp(btmp, "YES") == 0
+ || strcmp(btmp, "yes") == 0) {
+ *asn1_bool = 0xff;
+ return 1;
+ }
+ if (strcmp(btmp, "FALSE") == 0
+ || strcmp(btmp, "false") == 0
+ || strcmp(btmp, "N") == 0
+ || strcmp(btmp, "n") == 0
+ || strcmp(btmp, "NO") == 0
+ || strcmp(btmp, "no") == 0) {
+ *asn1_bool = 0;
+ return 1;
+ }
+ err:
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_BOOLEAN_STRING);
+ X509V3_conf_add_error_name_value(value);
+ return 0;
+}
+
+int X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint)
+{
+ ASN1_INTEGER *itmp;
+
+ if ((itmp = s2i_ASN1_INTEGER(NULL, value->value)) == NULL) {
+ X509V3_conf_add_error_name_value(value);
+ return 0;
+ }
+ *aint = itmp;
+ return 1;
+}
+
+#define HDR_NAME 1
+#define HDR_VALUE 2
+
+/*
+ * #define DEBUG
+ */
+
+STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
+{
+ char *p, *q, c;
+ char *ntmp, *vtmp;
+ STACK_OF(CONF_VALUE) *values = NULL;
+ char *linebuf;
+ int state;
+
+ /* We are going to modify the line so copy it first */
+ linebuf = OPENSSL_strdup(line);
+ if (linebuf == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ state = HDR_NAME;
+ ntmp = NULL;
+ /* Go through all characters */
+ for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n');
+ p++) {
+
+ switch (state) {
+ case HDR_NAME:
+ if (c == ':') {
+ state = HDR_VALUE;
+ *p = 0;
+ ntmp = strip_spaces(q);
+ if (!ntmp) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_EMPTY_NAME);
+ goto err;
+ }
+ q = p + 1;
+ } else if (c == ',') {
+ *p = 0;
+ ntmp = strip_spaces(q);
+ q = p + 1;
+ if (!ntmp) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_EMPTY_NAME);
+ goto err;
+ }
+ if (!X509V3_add_value(ntmp, NULL, &values)) {
+ goto err;
+ }
+ }
+ break;
+
+ case HDR_VALUE:
+ if (c == ',') {
+ state = HDR_NAME;
+ *p = 0;
+ vtmp = strip_spaces(q);
+ if (!vtmp) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_VALUE);
+ goto err;
+ }
+ if (!X509V3_add_value(ntmp, vtmp, &values)) {
+ goto err;
+ }
+ ntmp = NULL;
+ q = p + 1;
+ }
+
+ }
+ }
+
+ if (state == HDR_VALUE) {
+ vtmp = strip_spaces(q);
+ if (!vtmp) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_VALUE);
+ goto err;
+ }
+ if (!X509V3_add_value(ntmp, vtmp, &values)) {
+ goto err;
+ }
+ } else {
+ ntmp = strip_spaces(q);
+ if (!ntmp) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_EMPTY_NAME);
+ goto err;
+ }
+ if (!X509V3_add_value(ntmp, NULL, &values)) {
+ goto err;
+ }
+ }
+ OPENSSL_free(linebuf);
+ return values;
+
+ err:
+ OPENSSL_free(linebuf);
+ sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
+ return NULL;
+
+}
+
+/* Delete leading and trailing spaces from a string */
+static char *strip_spaces(char *name)
+{
+ char *p, *q;
+
+ /* Skip over leading spaces */
+ p = name;
+ while (*p && ossl_isspace(*p))
+ p++;
+ if (*p == '\0')
+ return NULL;
+ q = p + strlen(p) - 1;
+ while ((q != p) && ossl_isspace(*q))
+ q--;
+ if (p != q)
+ q[1] = 0;
+ if (*p == '\0')
+ return NULL;
+ return p;
+}
+
+
+/*
+ * V2I name comparison function: returns zero if 'name' matches cmp or cmp.*
+ */
+
+int ossl_v3_name_cmp(const char *name, const char *cmp)
+{
+ int len, ret;
+ char c;
+
+ len = strlen(cmp);
+ if ((ret = strncmp(name, cmp, len)))
+ return ret;
+ c = name[len];
+ if (!c || (c == '.'))
+ return 0;
+ return 1;
+}
+
+static int sk_strcmp(const char *const *a, const char *const *b)
+{
+ return strcmp(*a, *b);
+}
+
+STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x)
+{
+ GENERAL_NAMES *gens;
+ STACK_OF(OPENSSL_STRING) *ret;
+
+ gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
+ ret = get_email(X509_get_subject_name(x), gens);
+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+ return ret;
+}
+
+STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x)
+{
+ AUTHORITY_INFO_ACCESS *info;
+ STACK_OF(OPENSSL_STRING) *ret = NULL;
+ int i;
+
+ info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
+ if (!info)
+ return NULL;
+ for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
+ ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
+ if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) {
+ if (ad->location->type == GEN_URI) {
+ if (!append_ia5
+ (&ret, ad->location->d.uniformResourceIdentifier))
+ break;
+ }
+ }
+ }
+ AUTHORITY_INFO_ACCESS_free(info);
+ return ret;
+}
+
+STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x)
+{
+ GENERAL_NAMES *gens;
+ STACK_OF(X509_EXTENSION) *exts;
+ STACK_OF(OPENSSL_STRING) *ret;
+
+ exts = X509_REQ_get_extensions(x);
+ gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
+ ret = get_email(X509_REQ_get_subject_name(x), gens);
+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+ sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+ return ret;
+}
+
+static STACK_OF(OPENSSL_STRING) *get_email(const X509_NAME *name,
+ GENERAL_NAMES *gens)
+{
+ STACK_OF(OPENSSL_STRING) *ret = NULL;
+ X509_NAME_ENTRY *ne;
+ const ASN1_IA5STRING *email;
+ GENERAL_NAME *gen;
+ int i = -1;
+
+ /* Now add any email address(es) to STACK */
+ /* First supplied X509_NAME */
+ while ((i = X509_NAME_get_index_by_NID(name,
+ NID_pkcs9_emailAddress, i)) >= 0) {
+ ne = X509_NAME_get_entry(name, i);
+ email = X509_NAME_ENTRY_get_data(ne);
+ if (!append_ia5(&ret, email))
+ return NULL;
+ }
+ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+ gen = sk_GENERAL_NAME_value(gens, i);
+ if (gen->type != GEN_EMAIL)
+ continue;
+ if (!append_ia5(&ret, gen->d.ia5))
+ return NULL;
+ }
+ return ret;
+}
+
+static void str_free(OPENSSL_STRING str)
+{
+ OPENSSL_free(str);
+}
+
+static int append_ia5(STACK_OF(OPENSSL_STRING) **sk,
+ const ASN1_IA5STRING *email)
+{
+ char *emtmp;
+
+ /* First some sanity checks */
+ if (email->type != V_ASN1_IA5STRING)
+ return 1;
+ if (email->data == NULL || email->length == 0)
+ return 1;
+ if (memchr(email->data, 0, email->length) != NULL)
+ return 1;
+ if (*sk == NULL)
+ *sk = sk_OPENSSL_STRING_new(sk_strcmp);
+ if (*sk == NULL)
+ return 0;
+
+ emtmp = OPENSSL_strndup((char *)email->data, email->length);
+ if (emtmp == NULL) {
+ X509_email_free(*sk);
+ *sk = NULL;
+ return 0;
+ }
+
+ /* Don't add duplicates */
+ if (sk_OPENSSL_STRING_find(*sk, emtmp) != -1) {
+ OPENSSL_free(emtmp);
+ return 1;
+ }
+ if (!sk_OPENSSL_STRING_push(*sk, emtmp)) {
+ OPENSSL_free(emtmp); /* free on push failure */
+ X509_email_free(*sk);
+ *sk = NULL;
+ return 0;
+ }
+ return 1;
+}
+
+void X509_email_free(STACK_OF(OPENSSL_STRING) *sk)
+{
+ sk_OPENSSL_STRING_pop_free(sk, str_free);
+}
+
+typedef int (*equal_fn) (const unsigned char *pattern, size_t pattern_len,
+ const unsigned char *subject, size_t subject_len,
+ unsigned int flags);
+
+/* Skip pattern prefix to match "wildcard" subject */
+static void skip_prefix(const unsigned char **p, size_t *plen,
+ size_t subject_len,
+ unsigned int flags)
+{
+ const unsigned char *pattern = *p;
+ size_t pattern_len = *plen;
+
+ /*
+ * If subject starts with a leading '.' followed by more octets, and
+ * pattern is longer, compare just an equal-length suffix with the
+ * full subject (starting at the '.'), provided the prefix contains
+ * no NULs.
+ */
+ if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0)
+ return;
+
+ while (pattern_len > subject_len && *pattern) {
+ if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) &&
+ *pattern == '.')
+ break;
+ ++pattern;
+ --pattern_len;
+ }
+
+ /* Skip if entire prefix acceptable */
+ if (pattern_len == subject_len) {
+ *p = pattern;
+ *plen = pattern_len;
+ }
+}
+
+/* Compare while ASCII ignoring case. */
+static int equal_nocase(const unsigned char *pattern, size_t pattern_len,
+ const unsigned char *subject, size_t subject_len,
+ unsigned int flags)
+{
+ skip_prefix(&pattern, &pattern_len, subject_len, flags);
+ if (pattern_len != subject_len)
+ return 0;
+ while (pattern_len != 0) {
+ unsigned char l = *pattern;
+ unsigned char r = *subject;
+
+ /* The pattern must not contain NUL characters. */
+ if (l == 0)
+ return 0;
+ if (l != r) {
+ if ('A' <= l && l <= 'Z')
+ l = (l - 'A') + 'a';
+ if ('A' <= r && r <= 'Z')
+ r = (r - 'A') + 'a';
+ if (l != r)
+ return 0;
+ }
+ ++pattern;
+ ++subject;
+ --pattern_len;
+ }
+ return 1;
+}
+
+/* Compare using memcmp. */
+static int equal_case(const unsigned char *pattern, size_t pattern_len,
+ const unsigned char *subject, size_t subject_len,
+ unsigned int flags)
+{
+ skip_prefix(&pattern, &pattern_len, subject_len, flags);
+ if (pattern_len != subject_len)
+ return 0;
+ return !memcmp(pattern, subject, pattern_len);
+}
+
+/*
+ * RFC 5280, section 7.5, requires that only the domain is compared in a
+ * case-insensitive manner.
+ */
+static int equal_email(const unsigned char *a, size_t a_len,
+ const unsigned char *b, size_t b_len,
+ unsigned int unused_flags)
+{
+ size_t i = a_len;
+
+ if (a_len != b_len)
+ return 0;
+ /*
+ * We search backwards for the '@' character, so that we do not have to
+ * deal with quoted local-parts. The domain part is compared in a
+ * case-insensitive manner.
+ */
+ while (i > 0) {
+ --i;
+ if (a[i] == '@' || b[i] == '@') {
+ if (!equal_nocase(a + i, a_len - i, b + i, a_len - i, 0))
+ return 0;
+ break;
+ }
+ }
+ if (i == 0)
+ i = a_len;
+ return equal_case(a, i, b, i, 0);
+}
+
+/*
+ * Compare the prefix and suffix with the subject, and check that the
+ * characters in-between are valid.
+ */
+static int wildcard_match(const unsigned char *prefix, size_t prefix_len,
+ const unsigned char *suffix, size_t suffix_len,
+ const unsigned char *subject, size_t subject_len,
+ unsigned int flags)
+{
+ const unsigned char *wildcard_start;
+ const unsigned char *wildcard_end;
+ const unsigned char *p;
+ int allow_multi = 0;
+ int allow_idna = 0;
+
+ if (subject_len < prefix_len + suffix_len)
+ return 0;
+ if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags))
+ return 0;
+ wildcard_start = subject + prefix_len;
+ wildcard_end = subject + (subject_len - suffix_len);
+ if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags))
+ return 0;
+ /*
+ * If the wildcard makes up the entire first label, it must match at
+ * least one character.
+ */
+ if (prefix_len == 0 && *suffix == '.') {
+ if (wildcard_start == wildcard_end)
+ return 0;
+ allow_idna = 1;
+ if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS)
+ allow_multi = 1;
+ }
+ /* IDNA labels cannot match partial wildcards */
+ if (!allow_idna &&
+ subject_len >= 4 && OPENSSL_strncasecmp((char *)subject, "xn--", 4) == 0)
+ return 0;
+ /* The wildcard may match a literal '*' */
+ if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*')
+ return 1;
+ /*
+ * Check that the part matched by the wildcard contains only
+ * permitted characters and only matches a single label unless
+ * allow_multi is set.
+ */
+ for (p = wildcard_start; p != wildcard_end; ++p)
+ if (!(('0' <= *p && *p <= '9') ||
+ ('A' <= *p && *p <= 'Z') ||
+ ('a' <= *p && *p <= 'z') ||
+ *p == '-' || (allow_multi && *p == '.')))
+ return 0;
+ return 1;
+}
+
+#define LABEL_START (1 << 0)
+#define LABEL_END (1 << 1)
+#define LABEL_HYPHEN (1 << 2)
+#define LABEL_IDNA (1 << 3)
+
+static const unsigned char *valid_star(const unsigned char *p, size_t len,
+ unsigned int flags)
+{
+ const unsigned char *star = 0;
+ size_t i;
+ int state = LABEL_START;
+ int dots = 0;
+
+ for (i = 0; i < len; ++i) {
+ /*
+ * Locate first and only legal wildcard, either at the start
+ * or end of a non-IDNA first and not final label.
+ */
+ if (p[i] == '*') {
+ int atstart = (state & LABEL_START);
+ int atend = (i == len - 1 || p[i + 1] == '.');
+ /*-
+ * At most one wildcard per pattern.
+ * No wildcards in IDNA labels.
+ * No wildcards after the first label.
+ */
+ if (star != NULL || (state & LABEL_IDNA) != 0 || dots)
+ return NULL;
+ /* Only full-label '*.example.com' wildcards? */
+ if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS)
+ && (!atstart || !atend))
+ return NULL;
+ /* No 'foo*bar' wildcards */
+ if (!atstart && !atend)
+ return NULL;
+ star = &p[i];
+ state &= ~LABEL_START;
+ } else if (('a' <= p[i] && p[i] <= 'z')
+ || ('A' <= p[i] && p[i] <= 'Z')
+ || ('0' <= p[i] && p[i] <= '9')) {
+ if ((state & LABEL_START) != 0
+ && len - i >= 4 && OPENSSL_strncasecmp((char *)&p[i], "xn--", 4) == 0)
+ state |= LABEL_IDNA;
+ state &= ~(LABEL_HYPHEN | LABEL_START);
+ } else if (p[i] == '.') {
+ if ((state & (LABEL_HYPHEN | LABEL_START)) != 0)
+ return NULL;
+ state = LABEL_START;
+ ++dots;
+ } else if (p[i] == '-') {
+ /* no domain/subdomain starts with '-' */
+ if ((state & LABEL_START) != 0)
+ return NULL;
+ state |= LABEL_HYPHEN;
+ } else {
+ return NULL;
+ }
+ }
+
+ /*
+ * The final label must not end in a hyphen or ".", and
+ * there must be at least two dots after the star.
+ */
+ if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2)
+ return NULL;
+ return star;
+}
+
+/* Compare using wildcards. */
+static int equal_wildcard(const unsigned char *pattern, size_t pattern_len,
+ const unsigned char *subject, size_t subject_len,
+ unsigned int flags)
+{
+ const unsigned char *star = NULL;
+
+ /*
+ * Subject names starting with '.' can only match a wildcard pattern
+ * via a subject sub-domain pattern suffix match.
+ */
+ if (!(subject_len > 1 && subject[0] == '.'))
+ star = valid_star(pattern, pattern_len, flags);
+ if (star == NULL)
+ return equal_nocase(pattern, pattern_len,
+ subject, subject_len, flags);
+ return wildcard_match(pattern, star - pattern,
+ star + 1, (pattern + pattern_len) - star - 1,
+ subject, subject_len, flags);
+}
+
+/*
+ * Compare an ASN1_STRING to a supplied string. If they match return 1. If
+ * cmp_type > 0 only compare if string matches the type, otherwise convert it
+ * to UTF8.
+ */
+
+static int do_check_string(const ASN1_STRING *a, int cmp_type, equal_fn equal,
+ unsigned int flags, const char *b, size_t blen,
+ char **peername)
+{
+ int rv = 0;
+
+ if (!a->data || !a->length)
+ return 0;
+ if (cmp_type > 0) {
+ if (cmp_type != a->type)
+ return 0;
+ if (cmp_type == V_ASN1_IA5STRING)
+ rv = equal(a->data, a->length, (unsigned char *)b, blen, flags);
+ else if (a->length == (int)blen && !memcmp(a->data, b, blen))
+ rv = 1;
+ if (rv > 0 && peername != NULL) {
+ *peername = OPENSSL_strndup((char *)a->data, a->length);
+ if (*peername == NULL)
+ return -1;
+ }
+ } else {
+ int astrlen;
+ unsigned char *astr;
+ astrlen = ASN1_STRING_to_UTF8(&astr, a);
+ if (astrlen < 0) {
+ /*
+ * -1 could be an internal malloc failure or a decoding error from
+ * malformed input; we can't distinguish.
+ */
+ return -1;
+ }
+ rv = equal(astr, astrlen, (unsigned char *)b, blen, flags);
+ if (rv > 0 && peername != NULL) {
+ *peername = OPENSSL_strndup((char *)astr, astrlen);
+ if (*peername == NULL) {
+ OPENSSL_free(astr);
+ return -1;
+ }
+ }
+ OPENSSL_free(astr);
+ }
+ return rv;
+}
+
+static int do_x509_check(X509 *x, const char *chk, size_t chklen,
+ unsigned int flags, int check_type, char **peername)
+{
+ GENERAL_NAMES *gens = NULL;
+ const X509_NAME *name = NULL;
+ int i;
+ int cnid = NID_undef;
+ int alt_type;
+ int san_present = 0;
+ int rv = 0;
+ equal_fn equal;
+
+ /* See below, this flag is internal-only */
+ flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS;
+ if (check_type == GEN_EMAIL) {
+ cnid = NID_pkcs9_emailAddress;
+ alt_type = V_ASN1_IA5STRING;
+ equal = equal_email;
+ } else if (check_type == GEN_DNS) {
+ cnid = NID_commonName;
+ /* Implicit client-side DNS sub-domain pattern */
+ if (chklen > 1 && chk[0] == '.')
+ flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS;
+ alt_type = V_ASN1_IA5STRING;
+ if (flags & X509_CHECK_FLAG_NO_WILDCARDS)
+ equal = equal_nocase;
+ else
+ equal = equal_wildcard;
+ } else {
+ alt_type = V_ASN1_OCTET_STRING;
+ equal = equal_case;
+ }
+
+ if (chklen == 0)
+ chklen = strlen(chk);
+
+ gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
+ if (gens) {
+ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+ GENERAL_NAME *gen;
+ ASN1_STRING *cstr;
+
+ gen = sk_GENERAL_NAME_value(gens, i);
+ if ((gen->type == GEN_OTHERNAME) && (check_type == GEN_EMAIL)) {
+ if (OBJ_obj2nid(gen->d.otherName->type_id) ==
+ NID_id_on_SmtpUTF8Mailbox) {
+ san_present = 1;
+
+ /*
+ * If it is not a UTF8String then that is unexpected and we
+ * treat it as no match
+ */
+ if (gen->d.otherName->value->type == V_ASN1_UTF8STRING) {
+ cstr = gen->d.otherName->value->value.utf8string;
+
+ /* Positive on success, negative on error! */
+ if ((rv = do_check_string(cstr, 0, equal, flags,
+ chk, chklen, peername)) != 0)
+ break;
+ }
+ } else
+ continue;
+ } else {
+ if ((gen->type != check_type) && (gen->type != GEN_OTHERNAME))
+ continue;
+ }
+ san_present = 1;
+ if (check_type == GEN_EMAIL)
+ cstr = gen->d.rfc822Name;
+ else if (check_type == GEN_DNS)
+ cstr = gen->d.dNSName;
+ else
+ cstr = gen->d.iPAddress;
+ /* Positive on success, negative on error! */
+ if ((rv = do_check_string(cstr, alt_type, equal, flags,
+ chk, chklen, peername)) != 0)
+ break;
+ }
+ GENERAL_NAMES_free(gens);
+ if (rv != 0)
+ return rv;
+ if (san_present && !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT))
+ return 0;
+ }
+
+ /* We're done if CN-ID is not pertinent */
+ if (cnid == NID_undef || (flags & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT))
+ return 0;
+
+ i = -1;
+ name = X509_get_subject_name(x);
+ while ((i = X509_NAME_get_index_by_NID(name, cnid, i)) >= 0) {
+ const X509_NAME_ENTRY *ne = X509_NAME_get_entry(name, i);
+ const ASN1_STRING *str = X509_NAME_ENTRY_get_data(ne);
+
+ /* Positive on success, negative on error! */
+ if ((rv = do_check_string(str, -1, equal, flags,
+ chk, chklen, peername)) != 0)
+ return rv;
+ }
+ return 0;
+}
+
+int X509_check_host(X509 *x, const char *chk, size_t chklen,
+ unsigned int flags, char **peername)
+{
+ if (chk == NULL)
+ return -2;
+ /*
+ * Embedded NULs are disallowed, except as the last character of a
+ * string of length 2 or more (tolerate caller including terminating
+ * NUL in string length).
+ */
+ if (chklen == 0)
+ chklen = strlen(chk);
+ else if (memchr(chk, '\0', chklen > 1 ? chklen - 1 : chklen))
+ return -2;
+ if (chklen > 1 && chk[chklen - 1] == '\0')
+ --chklen;
+ return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername);
+}
+
+int X509_check_email(X509 *x, const char *chk, size_t chklen,
+ unsigned int flags)
+{
+ if (chk == NULL)
+ return -2;
+ /*
+ * Embedded NULs are disallowed, except as the last character of a
+ * string of length 2 or more (tolerate caller including terminating
+ * NUL in string length).
+ */
+ if (chklen == 0)
+ chklen = strlen((char *)chk);
+ else if (memchr(chk, '\0', chklen > 1 ? chklen - 1 : chklen))
+ return -2;
+ if (chklen > 1 && chk[chklen - 1] == '\0')
+ --chklen;
+ return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL);
+}
+
+int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
+ unsigned int flags)
+{
+ if (chk == NULL)
+ return -2;
+ return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL);
+}
+
+int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
+{
+ unsigned char ipout[16];
+ size_t iplen;
+
+ if (ipasc == NULL)
+ return -2;
+ iplen = (size_t)ossl_a2i_ipadd(ipout, ipasc);
+ if (iplen == 0)
+ return -2;
+ return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
+}
+
+char *ossl_ipaddr_to_asc(unsigned char *p, int len)
+{
+ /*
+ * 40 is enough space for the longest IPv6 address + nul terminator byte
+ * XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX\0
+ */
+ char buf[40], *out;
+ int i = 0, remain = 0, bytes = 0;
+
+ switch (len) {
+ case 4: /* IPv4 */
+ BIO_snprintf(buf, sizeof(buf), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+ break;
+ case 16: /* IPv6 */
+ for (out = buf, i = 8, remain = sizeof(buf);
+ i-- > 0 && bytes >= 0;
+ remain -= bytes, out += bytes) {
+ const char *template = (i > 0 ? "%X:" : "%X");
+
+ bytes = BIO_snprintf(out, remain, template, p[0] << 8 | p[1]);
+ p += 2;
+ }
+ break;
+ default:
+ BIO_snprintf(buf, sizeof(buf), "<invalid length=%d>", len);
+ break;
+ }
+ return OPENSSL_strdup(buf);
+}
+
+/*
+ * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible
+ * with RFC3280.
+ */
+
+ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
+{
+ unsigned char ipout[16];
+ ASN1_OCTET_STRING *ret;
+ int iplen;
+
+ /* If string contains a ':' assume IPv6 */
+
+ iplen = ossl_a2i_ipadd(ipout, ipasc);
+
+ if (!iplen)
+ return NULL;
+
+ ret = ASN1_OCTET_STRING_new();
+ if (ret == NULL)
+ return NULL;
+ if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) {
+ ASN1_OCTET_STRING_free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
+ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
+{
+ ASN1_OCTET_STRING *ret = NULL;
+ unsigned char ipout[32];
+ char *iptmp = NULL, *p;
+ int iplen1, iplen2;
+
+ p = strchr(ipasc, '/');
+ if (p == NULL)
+ return NULL;
+ iptmp = OPENSSL_strdup(ipasc);
+ if (iptmp == NULL)
+ return NULL;
+ p = iptmp + (p - ipasc);
+ *p++ = 0;
+
+ iplen1 = ossl_a2i_ipadd(ipout, iptmp);
+
+ if (!iplen1)
+ goto err;
+
+ iplen2 = ossl_a2i_ipadd(ipout + iplen1, p);
+
+ OPENSSL_free(iptmp);
+ iptmp = NULL;
+
+ if (!iplen2 || (iplen1 != iplen2))
+ goto err;
+
+ ret = ASN1_OCTET_STRING_new();
+ if (ret == NULL)
+ goto err;
+ if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
+ goto err;
+
+ return ret;
+
+ err:
+ OPENSSL_free(iptmp);
+ ASN1_OCTET_STRING_free(ret);
+ return NULL;
+}
+
+int ossl_a2i_ipadd(unsigned char *ipout, const char *ipasc)
+{
+ /* If string contains a ':' assume IPv6 */
+
+ if (strchr(ipasc, ':')) {
+ if (!ipv6_from_asc(ipout, ipasc))
+ return 0;
+ return 16;
+ } else {
+ if (!ipv4_from_asc(ipout, ipasc))
+ return 0;
+ return 4;
+ }
+}
+
+static int ipv4_from_asc(unsigned char *v4, const char *in)
+{
+ const char *p;
+ int a0, a1, a2, a3, n;
+
+ if (sscanf(in, "%d.%d.%d.%d%n", &a0, &a1, &a2, &a3, &n) != 4)
+ return 0;
+ if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
+ || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
+ return 0;
+ p = in + n;
+ if (!(*p == '\0' || ossl_isspace(*p)))
+ return 0;
+ v4[0] = a0;
+ v4[1] = a1;
+ v4[2] = a2;
+ v4[3] = a3;
+ return 1;
+}
+
+typedef struct {
+ /* Temporary store for IPV6 output */
+ unsigned char tmp[16];
+ /* Total number of bytes in tmp */
+ int total;
+ /* The position of a zero (corresponding to '::') */
+ int zero_pos;
+ /* Number of zeroes */
+ int zero_cnt;
+} IPV6_STAT;
+
+static int ipv6_from_asc(unsigned char *v6, const char *in)
+{
+ IPV6_STAT v6stat;
+
+ v6stat.total = 0;
+ v6stat.zero_pos = -1;
+ v6stat.zero_cnt = 0;
+ /*
+ * Treat the IPv6 representation as a list of values separated by ':'.
+ * The presence of a '::' will parse as one, two or three zero length
+ * elements.
+ */
+ if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
+ return 0;
+
+ /* Now for some sanity checks */
+
+ if (v6stat.zero_pos == -1) {
+ /* If no '::' must have exactly 16 bytes */
+ if (v6stat.total != 16)
+ return 0;
+ } else {
+ /* If '::' must have less than 16 bytes */
+ if (v6stat.total == 16)
+ return 0;
+ /* More than three zeroes is an error */
+ if (v6stat.zero_cnt > 3) {
+ return 0;
+ /* Can only have three zeroes if nothing else present */
+ } else if (v6stat.zero_cnt == 3) {
+ if (v6stat.total > 0)
+ return 0;
+ } else if (v6stat.zero_cnt == 2) {
+ /* Can only have two zeroes if at start or end */
+ if ((v6stat.zero_pos != 0)
+ && (v6stat.zero_pos != v6stat.total))
+ return 0;
+ } else {
+ /* Can only have one zero if *not* start or end */
+ if ((v6stat.zero_pos == 0)
+ || (v6stat.zero_pos == v6stat.total))
+ return 0;
+ }
+ }
+
+ /* Format result */
+
+ if (v6stat.zero_pos >= 0) {
+ /* Copy initial part */
+ memcpy(v6, v6stat.tmp, v6stat.zero_pos);
+ /* Zero middle */
+ memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
+ /* Copy final part */
+ if (v6stat.total != v6stat.zero_pos)
+ memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
+ v6stat.tmp + v6stat.zero_pos,
+ v6stat.total - v6stat.zero_pos);
+ } else {
+ memcpy(v6, v6stat.tmp, 16);
+ }
+
+ return 1;
+}
+
+static int ipv6_cb(const char *elem, int len, void *usr)
+{
+ IPV6_STAT *s = usr;
+
+ /* Error if 16 bytes written */
+ if (s->total == 16)
+ return 0;
+ if (len == 0) {
+ /* Zero length element, corresponds to '::' */
+ if (s->zero_pos == -1)
+ s->zero_pos = s->total;
+ /* If we've already got a :: its an error */
+ else if (s->zero_pos != s->total)
+ return 0;
+ s->zero_cnt++;
+ } else {
+ /* If more than 4 characters could be final a.b.c.d form */
+ if (len > 4) {
+ /* Need at least 4 bytes left */
+ if (s->total > 12)
+ return 0;
+ /* Must be end of string */
+ if (elem[len])
+ return 0;
+ if (!ipv4_from_asc(s->tmp + s->total, elem))
+ return 0;
+ s->total += 4;
+ } else {
+ if (!ipv6_hex(s->tmp + s->total, elem, len))
+ return 0;
+ s->total += 2;
+ }
+ }
+ return 1;
+}
+
+/*
+ * Convert a string of up to 4 hex digits into the corresponding IPv6 form.
+ */
+
+static int ipv6_hex(unsigned char *out, const char *in, int inlen)
+{
+ unsigned char c;
+ unsigned int num = 0;
+ int x;
+
+ if (inlen > 4)
+ return 0;
+ while (inlen--) {
+ c = *in++;
+ num <<= 4;
+ x = OPENSSL_hexchar2int(c);
+ if (x < 0)
+ return 0;
+ num |= (char)x;
+ }
+ out[0] = num >> 8;
+ out[1] = num & 0xff;
+ return 1;
+}
+
+int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
+ unsigned long chtype)
+{
+ CONF_VALUE *v;
+ int i, mval, spec_char, plus_char;
+ char *p, *type;
+
+ if (!nm)
+ return 0;
+
+ for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
+ v = sk_CONF_VALUE_value(dn_sk, i);
+ type = v->name;
+ /*
+ * Skip past any leading X. X: X, etc to allow for multiple instances
+ */
+ for (p = type; *p; p++) {
+#ifndef CHARSET_EBCDIC
+ spec_char = ((*p == ':') || (*p == ',') || (*p == '.'));
+#else
+ spec_char = ((*p == os_toascii[':']) || (*p == os_toascii[','])
+ || (*p == os_toascii['.']));
+#endif
+ if (spec_char) {
+ p++;
+ if (*p)
+ type = p;
+ break;
+ }
+ }
+#ifndef CHARSET_EBCDIC
+ plus_char = (*type == '+');
+#else
+ plus_char = (*type == os_toascii['+']);
+#endif
+ if (plus_char) {
+ mval = -1;
+ type++;
+ } else {
+ mval = 0;
+ }
+ if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
+ (unsigned char *)v->value, -1, -1,
+ mval))
+ return 0;
+
+ }
+ return 1;
+}
diff --git a/crypto/x509/v3err.c b/crypto/x509/v3err.c
new file mode 100644
index 000000000000..6f38034c1afe
--- /dev/null
+++ b/crypto/x509/v3err.c
@@ -0,0 +1,147 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/x509v3err.h>
+#include "crypto/x509v3err.h"
+
+#ifndef OPENSSL_NO_ERR
+
+static const ERR_STRING_DATA X509V3_str_reasons[] = {
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BAD_IP_ADDRESS), "bad ip address"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BAD_OBJECT), "bad object"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BN_DEC2BN_ERROR), "bn dec2bn error"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BN_TO_ASN1_INTEGER_ERROR),
+ "bn to asn1 integer error"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DIRNAME_ERROR), "dirname error"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DISTPOINT_ALREADY_SET),
+ "distpoint already set"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DUPLICATE_ZONE_ID),
+ "duplicate zone id"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EMPTY_KEY_USAGE), "empty key usage"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_CONVERTING_ZONE),
+ "error converting zone"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_CREATING_EXTENSION),
+ "error creating extension"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_IN_EXTENSION),
+ "error in extension"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXPECTED_A_SECTION_NAME),
+ "expected a section name"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_EXISTS),
+ "extension exists"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_NAME_ERROR),
+ "extension name error"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_NOT_FOUND),
+ "extension not found"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED),
+ "extension setting not supported"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_VALUE_ERROR),
+ "extension value error"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ILLEGAL_EMPTY_EXTENSION),
+ "illegal empty extension"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG),
+ "incorrect policy syntax tag"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_ASNUMBER),
+ "invalid asnumber"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_ASRANGE), "invalid asrange"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_BOOLEAN_STRING),
+ "invalid boolean string"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_CERTIFICATE),
+ "invalid certificate"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_EMPTY_NAME),
+ "invalid empty name"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_EXTENSION_STRING),
+ "invalid extension string"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_INHERITANCE),
+ "invalid inheritance"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_IPADDRESS),
+ "invalid ipaddress"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_MULTIPLE_RDNS),
+ "invalid multiple rdns"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NAME), "invalid name"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_ARGUMENT),
+ "invalid null argument"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_VALUE),
+ "invalid null value"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NUMBER), "invalid number"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NUMBERS), "invalid numbers"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_OBJECT_IDENTIFIER),
+ "invalid object identifier"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_OPTION), "invalid option"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_POLICY_IDENTIFIER),
+ "invalid policy identifier"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_PROXY_POLICY_SETTING),
+ "invalid proxy policy setting"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_PURPOSE), "invalid purpose"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SAFI), "invalid safi"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SECTION), "invalid section"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SYNTAX), "invalid syntax"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ISSUER_DECODE_ERROR),
+ "issuer decode error"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_MISSING_VALUE), "missing value"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS),
+ "need organization and numbers"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NEGATIVE_PATHLEN),
+ "negative pathlen"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_CONFIG_DATABASE),
+ "no config database"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_ISSUER_CERTIFICATE),
+ "no issuer certificate"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_ISSUER_DETAILS),
+ "no issuer details"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_POLICY_IDENTIFIER),
+ "no policy identifier"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED),
+ "no proxy cert policy language defined"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_PUBLIC_KEY), "no public key"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_SUBJECT_DETAILS),
+ "no subject details"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_OPERATION_NOT_DEFINED),
+ "operation not defined"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_OTHERNAME_ERROR), "othername error"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED),
+ "policy language already defined"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_PATH_LENGTH),
+ "policy path length"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED),
+ "policy path length already defined"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY),
+ "policy when proxy language requires no policy"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_SECTION_NOT_FOUND),
+ "section not found"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS),
+ "unable to get issuer details"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID),
+ "unable to get issuer keyid"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT),
+ "unknown bit string argument"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_EXTENSION),
+ "unknown extension"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_EXTENSION_NAME),
+ "unknown extension name"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_OPTION), "unknown option"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNSUPPORTED_OPTION),
+ "unsupported option"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNSUPPORTED_TYPE),
+ "unsupported type"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_USER_TOO_LONG), "user too long"},
+ {0, NULL}
+};
+
+#endif
+
+int ossl_err_load_X509V3_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(X509V3_str_reasons[0].error) == NULL)
+ ERR_load_strings_const(X509V3_str_reasons);
+#endif
+ return 1;
+}
diff --git a/crypto/x509/x509_att.c b/crypto/x509/x509_att.c
index cc9f9d19099d..73ac59454d1f 100644
--- a/crypto/x509/x509_att.c
+++ b/crypto/x509/x509_att.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -15,6 +15,7 @@
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
+#include "crypto/x509.h"
#include "x509_local.h"
int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x)
@@ -77,15 +78,16 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
STACK_OF(X509_ATTRIBUTE) *sk = NULL;
if (x == NULL) {
- X509err(X509_F_X509AT_ADD1_ATTR, ERR_R_PASSED_NULL_PARAMETER);
- goto err2;
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
}
if (*x == NULL) {
if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL)
goto err;
- } else
+ } else {
sk = *x;
+ }
if ((new_attr = X509_ATTRIBUTE_dup(attr)) == NULL)
goto err2;
@@ -95,10 +97,11 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
*x = sk;
return sk;
err:
- X509err(X509_F_X509AT_ADD1_ATTR, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
err2:
X509_ATTRIBUTE_free(new_attr);
- sk_X509_ATTRIBUTE_free(sk);
+ if (*x == NULL)
+ sk_X509_ATTRIBUTE_free(sk);
return NULL;
}
@@ -165,6 +168,23 @@ void *X509at_get0_data_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *x,
return X509_ATTRIBUTE_get0_data(at, 0, type, NULL);
}
+STACK_OF(X509_ATTRIBUTE) *ossl_x509at_dup(const STACK_OF(X509_ATTRIBUTE) *x)
+{
+ int i, n;
+ STACK_OF(X509_ATTRIBUTE) *sk = NULL;
+
+ n = sk_X509_ATTRIBUTE_num(x);
+ for (i = 0; i < n; ++i) {
+ X509_ATTRIBUTE *attr = sk_X509_ATTRIBUTE_value(x, i);
+
+ if (X509at_add1_attr(&sk, attr) == NULL) {
+ sk_X509_ATTRIBUTE_pop_free(sk, X509_ATTRIBUTE_free);
+ return NULL;
+ }
+ }
+ return sk;
+}
+
X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
int atrtype, const void *data,
int len)
@@ -174,7 +194,7 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
obj = OBJ_nid2obj(nid);
if (obj == NULL) {
- X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_NID, X509_R_UNKNOWN_NID);
+ ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_NID);
return NULL;
}
ret = X509_ATTRIBUTE_create_by_OBJ(attr, obj, atrtype, data, len);
@@ -192,8 +212,7 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
if ((attr == NULL) || (*attr == NULL)) {
if ((ret = X509_ATTRIBUTE_new()) == NULL) {
- X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else
@@ -223,9 +242,8 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr,
obj = OBJ_txt2obj(atrname, 0);
if (obj == NULL) {
- X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_TXT,
- X509_R_INVALID_FIELD_NAME);
- ERR_add_error_data(2, "name=", atrname);
+ ERR_raise_data(ERR_LIB_X509, X509_R_INVALID_FIELD_NAME,
+ "name=%s", atrname);
return NULL;
}
nattr = X509_ATTRIBUTE_create_by_OBJ(attr, obj, type, bytes, len);
@@ -254,7 +272,7 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype,
stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype,
OBJ_obj2nid(attr->object));
if (!stmp) {
- X509err(X509_F_X509_ATTRIBUTE_SET1_DATA, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB);
return 0;
}
atype = stmp->type;
@@ -287,7 +305,7 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype,
goto err;
return 1;
err:
- X509err(X509_F_X509_ATTRIBUTE_SET1_DATA, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
ASN1_TYPE_free(ttmp);
ASN1_STRING_free(stmp);
return 0;
@@ -317,7 +335,7 @@ void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx,
if (atrtype == V_ASN1_BOOLEAN
|| atrtype == V_ASN1_NULL
|| atrtype != ASN1_TYPE_get(ttmp)) {
- X509err(X509_F_X509_ATTRIBUTE_GET0_DATA, X509_R_WRONG_TYPE);
+ ERR_raise(ERR_LIB_X509, X509_R_WRONG_TYPE);
return NULL;
}
return ttmp->value.ptr;
diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c
index 3724a118f343..5c9d91f4073d 100644
--- a/crypto/x509/x509_cmp.c
+++ b/crypto/x509/x509_cmp.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,6 +13,7 @@
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
+#include <openssl/core_names.h>
#include "crypto/x509.h"
int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b)
@@ -20,11 +21,15 @@ int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b)
int i;
const X509_CINF *ai, *bi;
+ if (b == NULL)
+ return a != NULL;
+ if (a == NULL)
+ return -1;
ai = &a->cert_info;
bi = &b->cert_info;
i = ASN1_INTEGER_cmp(&ai->serialNumber, &bi->serialNumber);
- if (i)
- return i;
+ if (i != 0)
+ return i < 0 ? -1 : 1;
return X509_NAME_cmp(ai->issuer, bi->issuer);
}
@@ -35,13 +40,18 @@ unsigned long X509_issuer_and_serial_hash(X509 *a)
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
unsigned char md[16];
char *f = NULL;
+ EVP_MD *digest = NULL;
if (ctx == NULL)
goto err;
f = X509_NAME_oneline(a->cert_info.issuer, NULL, 0);
if (f == NULL)
goto err;
- if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL))
+ digest = EVP_MD_fetch(a->libctx, SN_md5, a->propq);
+ if (digest == NULL)
+ goto err;
+
+ if (!EVP_DigestInit_ex(ctx, digest, NULL))
goto err;
if (!EVP_DigestUpdate(ctx, (unsigned char *)f, strlen(f)))
goto err;
@@ -56,6 +66,7 @@ unsigned long X509_issuer_and_serial_hash(X509 *a)
) & 0xffffffffL;
err:
OPENSSL_free(f);
+ EVP_MD_free(digest);
EVP_MD_CTX_free(ctx);
return ret;
}
@@ -78,7 +89,15 @@ int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b)
int X509_CRL_match(const X509_CRL *a, const X509_CRL *b)
{
- return memcmp(a->sha1_hash, b->sha1_hash, 20);
+ int rv;
+
+ if ((a->flags & EXFLAG_NO_FINGERPRINT) == 0
+ && (b->flags & EXFLAG_NO_FINGERPRINT) == 0)
+ rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
+ else
+ return -2;
+
+ return rv < 0 ? -1 : rv > 0;
}
X509_NAME *X509_get_issuer_name(const X509 *a)
@@ -88,7 +107,7 @@ X509_NAME *X509_get_issuer_name(const X509 *a)
unsigned long X509_issuer_name_hash(X509 *x)
{
- return X509_NAME_hash(x->cert_info.issuer);
+ return X509_NAME_hash_ex(x->cert_info.issuer, NULL, NULL, NULL);
}
#ifndef OPENSSL_NO_MD5
@@ -115,7 +134,7 @@ const ASN1_INTEGER *X509_get0_serialNumber(const X509 *a)
unsigned long X509_subject_name_hash(X509 *x)
{
- return X509_NAME_hash(x->cert_info.subject);
+ return X509_NAME_hash_ex(x->cert_info.subject, NULL, NULL, NULL);
}
#ifndef OPENSSL_NO_MD5
@@ -140,7 +159,7 @@ int X509_cmp(const X509 *a, const X509 *b)
if (a == b) /* for efficiency */
return 0;
- /* try to make sure hash is valid */
+ /* attempt to compute cert hash */
(void)X509_check_purpose((X509 *)a, -1, 0);
(void)X509_check_purpose((X509 *)b, -1, 0);
@@ -148,7 +167,7 @@ int X509_cmp(const X509 *a, const X509 *b)
&& (b->ex_flags & EXFLAG_NO_FINGERPRINT) == 0)
rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
if (rv != 0)
- return rv;
+ return rv < 0 ? -1 : 1;
/* Check for match against stored encoding too */
if (!a->cert_info.enc.modified && !b->cert_info.enc.modified) {
@@ -156,53 +175,137 @@ int X509_cmp(const X509 *a, const X509 *b)
return -1;
if (a->cert_info.enc.len > b->cert_info.enc.len)
return 1;
- return memcmp(a->cert_info.enc.enc, b->cert_info.enc.enc,
- a->cert_info.enc.len);
+ rv = memcmp(a->cert_info.enc.enc,
+ b->cert_info.enc.enc, a->cert_info.enc.len);
}
- return rv;
+ return rv < 0 ? -1 : rv > 0;
+}
+
+int ossl_x509_add_cert_new(STACK_OF(X509) **p_sk, X509 *cert, int flags)
+{
+ if (*p_sk == NULL && (*p_sk = sk_X509_new_null()) == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ return X509_add_cert(*p_sk, cert, flags);
+}
+
+int X509_add_cert(STACK_OF(X509) *sk, X509 *cert, int flags)
+{
+ if (sk == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if ((flags & X509_ADD_FLAG_NO_DUP) != 0) {
+ /*
+ * not using sk_X509_set_cmp_func() and sk_X509_find()
+ * because this re-orders the certs on the stack
+ */
+ int i;
+
+ for (i = 0; i < sk_X509_num(sk); i++) {
+ if (X509_cmp(sk_X509_value(sk, i), cert) == 0)
+ return 1;
+ }
+ }
+ if ((flags & X509_ADD_FLAG_NO_SS) != 0) {
+ int ret = X509_self_signed(cert, 0);
+
+ if (ret != 0)
+ return ret > 0 ? 1 : 0;
+ }
+ if (!sk_X509_insert(sk, cert,
+ (flags & X509_ADD_FLAG_PREPEND) != 0 ? 0 : -1)) {
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if ((flags & X509_ADD_FLAG_UP_REF) != 0)
+ (void)X509_up_ref(cert);
+ return 1;
+}
+
+int X509_add_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs, int flags)
+/* compiler would allow 'const' for the certs, yet they may get up-ref'ed */
+{
+ if (sk == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ return ossl_x509_add_certs_new(&sk, certs, flags);
+}
+
+int ossl_x509_add_certs_new(STACK_OF(X509) **p_sk, STACK_OF(X509) *certs,
+ int flags)
+/* compiler would allow 'const' for the certs, yet they may get up-ref'ed */
+{
+ int n = sk_X509_num(certs /* may be NULL */);
+ int i;
+
+ for (i = 0; i < n; i++) {
+ int j = (flags & X509_ADD_FLAG_PREPEND) == 0 ? i : n - 1 - i;
+ /* if prepend, add certs in reverse order to keep original order */
+
+ if (!ossl_x509_add_cert_new(p_sk, sk_X509_value(certs, j), flags))
+ return 0;
+ }
+ return 1;
}
int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
{
int ret;
- /* Ensure canonical encoding is present and up to date */
+ if (b == NULL)
+ return a != NULL;
+ if (a == NULL)
+ return -1;
- if (!a->canon_enc || a->modified) {
+ /* Ensure canonical encoding is present and up to date */
+ if (a->canon_enc == NULL || a->modified) {
ret = i2d_X509_NAME((X509_NAME *)a, NULL);
if (ret < 0)
return -2;
}
- if (!b->canon_enc || b->modified) {
+ if (b->canon_enc == NULL || b->modified) {
ret = i2d_X509_NAME((X509_NAME *)b, NULL);
if (ret < 0)
return -2;
}
ret = a->canon_enclen - b->canon_enclen;
+ if (ret == 0 && a->canon_enclen == 0)
+ return 0;
- if (ret != 0 || a->canon_enclen == 0)
- return ret;
+ if (a->canon_enc == NULL || b->canon_enc == NULL)
+ return -2;
- return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
+ if (ret == 0)
+ ret = memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
+ return ret < 0 ? -1 : ret > 0;
}
-unsigned long X509_NAME_hash(X509_NAME *x)
+unsigned long X509_NAME_hash_ex(const X509_NAME *x, OSSL_LIB_CTX *libctx,
+ const char *propq, int *ok)
{
unsigned long ret = 0;
unsigned char md[SHA_DIGEST_LENGTH];
+ EVP_MD *sha1 = EVP_MD_fetch(libctx, "SHA1", propq);
/* Make sure X509_NAME structure contains valid cached encoding */
i2d_X509_NAME(x, NULL);
- if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(),
- NULL))
- return 0;
-
- ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
- ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
- ) & 0xffffffffL;
+ if (ok != NULL)
+ *ok = 0;
+ if (sha1 != NULL
+ && EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, sha1, NULL)) {
+ ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
+ ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
+ ) & 0xffffffffL;
+ if (ok != NULL)
+ *ok = 1;
+ }
+ EVP_MD_free(sha1);
return ret;
}
@@ -211,34 +314,36 @@ unsigned long X509_NAME_hash(X509_NAME *x)
* I now DER encode the name and hash it. Since I cache the DER encoding,
* this is reasonably efficient.
*/
-
-unsigned long X509_NAME_hash_old(X509_NAME *x)
+unsigned long X509_NAME_hash_old(const X509_NAME *x)
{
+ EVP_MD *md5 = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_MD5, "-fips");
EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
unsigned long ret = 0;
unsigned char md[16];
- if (md_ctx == NULL)
- return ret;
+ if (md5 == NULL || md_ctx == NULL)
+ goto end;
/* Make sure X509_NAME structure contains valid cached encoding */
i2d_X509_NAME(x, NULL);
- EVP_MD_CTX_set_flags(md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
- if (EVP_DigestInit_ex(md_ctx, EVP_md5(), NULL)
+ if (EVP_DigestInit_ex(md_ctx, md5, NULL)
&& EVP_DigestUpdate(md_ctx, x->bytes->data, x->bytes->length)
&& EVP_DigestFinal_ex(md_ctx, md, NULL))
ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
) & 0xffffffffL;
+
+ end:
EVP_MD_CTX_free(md_ctx);
+ EVP_MD_free(md5);
return ret;
}
#endif
/* Search a stack of X509 for a match */
-X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name,
- ASN1_INTEGER *serial)
+X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, const X509_NAME *name,
+ const ASN1_INTEGER *serial)
{
int i;
X509 x, *x509 = NULL;
@@ -247,7 +352,7 @@ X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name,
return NULL;
x.cert_info.serialNumber = *serial;
- x.cert_info.issuer = name;
+ x.cert_info.issuer = (X509_NAME *)name; /* won't modify it */
for (i = 0; i < sk_X509_num(sk); i++) {
x509 = sk_X509_value(sk, i);
@@ -257,7 +362,7 @@ X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name,
return NULL;
}
-X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name)
+X509 *X509_find_by_subject(STACK_OF(X509) *sk, const X509_NAME *name)
{
X509 *x509;
int i;
@@ -290,27 +395,24 @@ int X509_check_private_key(const X509 *x, const EVP_PKEY *k)
int ret;
xk = X509_get0_pubkey(x);
+ if (xk == NULL) {
+ ERR_raise(ERR_LIB_X509, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
+ return 0;
+ }
- if (xk)
- ret = EVP_PKEY_cmp(xk, k);
- else
- ret = -2;
-
- switch (ret) {
- case 1:
- break;
+ switch (ret = EVP_PKEY_eq(xk, k)) {
case 0:
- X509err(X509_F_X509_CHECK_PRIVATE_KEY, X509_R_KEY_VALUES_MISMATCH);
+ ERR_raise(ERR_LIB_X509, X509_R_KEY_VALUES_MISMATCH);
break;
case -1:
- X509err(X509_F_X509_CHECK_PRIVATE_KEY, X509_R_KEY_TYPE_MISMATCH);
+ ERR_raise(ERR_LIB_X509, X509_R_KEY_TYPE_MISMATCH);
break;
case -2:
- X509err(X509_F_X509_CHECK_PRIVATE_KEY, X509_R_UNKNOWN_KEY_TYPE);
+ ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_KEY_TYPE);
+ break;
}
- if (ret > 0)
- return 1;
- return 0;
+
+ return ret > 0;
}
/*
@@ -323,13 +425,18 @@ int X509_check_private_key(const X509 *x, const EVP_PKEY *k)
static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags)
{
- const EC_GROUP *grp = NULL;
+ char curve_name[80];
+ size_t curve_name_len;
int curve_nid;
- if (pkey && EVP_PKEY_id(pkey) == EVP_PKEY_EC)
- grp = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey));
- if (!grp)
+
+ if (pkey == NULL || !EVP_PKEY_is_a(pkey, "EC"))
return X509_V_ERR_SUITE_B_INVALID_ALGORITHM;
- curve_nid = EC_GROUP_get_curve_name(grp);
+
+ if (!EVP_PKEY_get_group_name(pkey, curve_name, sizeof(curve_name),
+ &curve_name_len))
+ return X509_V_ERR_SUITE_B_INVALID_CURVE;
+
+ curve_nid = OBJ_txt2nid(curve_name);
/* Check curve is consistent with LOS */
if (curve_nid == NID_secp384r1) { /* P-384 */
/*
@@ -346,9 +453,9 @@ static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags)
return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY))
return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
- } else
+ } else {
return X509_V_ERR_SUITE_B_INVALID_CURVE;
-
+ }
return X509_V_OK;
}
@@ -366,9 +473,9 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
if (x == NULL) {
x = sk_X509_value(chain, 0);
i = 1;
- } else
+ } else {
i = 0;
-
+ }
pk = X509_get0_pubkey(x);
/*
@@ -380,7 +487,7 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
if (chain == NULL)
return check_suite_b(pk, -1, &tflags);
- if (X509_get_version(x) != 2) {
+ if (X509_get_version(x) != X509_VERSION_3) {
rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
/* Correct error depth */
i = 0;
@@ -397,7 +504,7 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
for (; i < sk_X509_num(chain); i++) {
sign_nid = X509_get_signature_nid(x);
x = sk_X509_value(chain, i);
- if (X509_get_version(x) != 2) {
+ if (X509_get_version(x) != X509_VERSION_3) {
rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
goto end;
}
@@ -449,6 +556,7 @@ int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags)
}
#endif
+
/*
* Not strictly speaking an "up_ref" as a STACK doesn't have a reference
* count but it has the same effect by duping the STACK and upping the ref of
@@ -456,20 +564,22 @@ int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags)
*/
STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain)
{
- STACK_OF(X509) *ret;
+ STACK_OF(X509) *ret = sk_X509_dup(chain);
int i;
- ret = sk_X509_dup(chain);
+
if (ret == NULL)
return NULL;
for (i = 0; i < sk_X509_num(ret); i++) {
X509 *x = sk_X509_value(ret, i);
+
if (!X509_up_ref(x))
goto err;
}
return ret;
+
err:
while (i-- > 0)
- X509_free (sk_X509_value(ret, i));
+ X509_free(sk_X509_value(ret, i));
sk_X509_free(ret);
return NULL;
}
diff --git a/crypto/x509/x509_d2.c b/crypto/x509/x509_d2.c
index 099ffda1e15c..62aceb7acade 100644
--- a/crypto/x509/x509_d2.c
+++ b/crypto/x509/x509_d2.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,46 +12,100 @@
#include <openssl/crypto.h>
#include <openssl/x509.h>
-int X509_STORE_set_default_paths(X509_STORE *ctx)
+int X509_STORE_set_default_paths_ex(X509_STORE *ctx, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
X509_LOOKUP *lookup;
lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file());
if (lookup == NULL)
return 0;
- X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
+ X509_LOOKUP_load_file_ex(lookup, NULL, X509_FILETYPE_DEFAULT, libctx, propq);
lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir());
if (lookup == NULL)
return 0;
X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
+ lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_store());
+ if (lookup == NULL)
+ return 0;
+ X509_LOOKUP_add_store_ex(lookup, NULL, libctx, propq);
+
/* clear any errors */
ERR_clear_error();
return 1;
}
+int X509_STORE_set_default_paths(X509_STORE *ctx)
+{
+ return X509_STORE_set_default_paths_ex(ctx, NULL, NULL);
+}
-int X509_STORE_load_locations(X509_STORE *ctx, const char *file,
- const char *path)
+int X509_STORE_load_file_ex(X509_STORE *ctx, const char *file,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ X509_LOOKUP *lookup;
+
+ if (file == NULL
+ || (lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file())) == NULL
+ || X509_LOOKUP_load_file_ex(lookup, file, X509_FILETYPE_PEM, libctx,
+ propq) <= 0)
+ return 0;
+
+ return 1;
+}
+
+int X509_STORE_load_file(X509_STORE *ctx, const char *file)
+{
+ return X509_STORE_load_file_ex(ctx, file, NULL, NULL);
+}
+
+int X509_STORE_load_path(X509_STORE *ctx, const char *path)
+{
+ X509_LOOKUP *lookup;
+
+ if (path == NULL
+ || (lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir())) == NULL
+ || X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) <= 0)
+ return 0;
+
+ return 1;
+}
+
+int X509_STORE_load_store_ex(X509_STORE *ctx, const char *uri,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
X509_LOOKUP *lookup;
- if (file != NULL) {
- lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file());
- if (lookup == NULL)
- return 0;
- if (X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM) != 1)
- return 0;
- }
- if (path != NULL) {
- lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir());
- if (lookup == NULL)
- return 0;
- if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1)
- return 0;
- }
- if ((path == NULL) && (file == NULL))
+ if (uri == NULL
+ || (lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_store())) == NULL
+ || X509_LOOKUP_add_store_ex(lookup, uri, libctx, propq) == 0)
+ return 0;
+
+ return 1;
+}
+
+int X509_STORE_load_store(X509_STORE *ctx, const char *uri)
+{
+ return X509_STORE_load_store_ex(ctx, uri, NULL, NULL);
+}
+
+int X509_STORE_load_locations_ex(X509_STORE *ctx, const char *file,
+ const char *path, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ if (file == NULL && path == NULL)
+ return 0;
+ if (file != NULL && !X509_STORE_load_file_ex(ctx, file, libctx, propq))
+ return 0;
+ if (path != NULL && !X509_STORE_load_path(ctx, path))
return 0;
return 1;
}
+
+int X509_STORE_load_locations(X509_STORE *ctx, const char *file,
+ const char *path)
+{
+ return X509_STORE_load_locations_ex(ctx, file, path, NULL, NULL);
+}
diff --git a/crypto/x509/x509_def.c b/crypto/x509/x509_def.c
index bfa8d7d8522a..b8bdcb484195 100644
--- a/crypto/x509/x509_def.c
+++ b/crypto/x509/x509_def.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c
index bdd1e67cd3fd..a933aeef351f 100644
--- a/crypto/x509/x509_err.c
+++ b/crypto/x509/x509_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,107 +10,10 @@
#include <openssl/err.h>
#include <openssl/x509err.h>
+#include "crypto/x509err.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA X509_str_functs[] = {
- {ERR_PACK(ERR_LIB_X509, X509_F_ADD_CERT_DIR, 0), "add_cert_dir"},
- {ERR_PACK(ERR_LIB_X509, X509_F_BUILD_CHAIN, 0), "build_chain"},
- {ERR_PACK(ERR_LIB_X509, X509_F_BY_FILE_CTRL, 0), "by_file_ctrl"},
- {ERR_PACK(ERR_LIB_X509, X509_F_CHECK_NAME_CONSTRAINTS, 0),
- "check_name_constraints"},
- {ERR_PACK(ERR_LIB_X509, X509_F_CHECK_POLICY, 0), "check_policy"},
- {ERR_PACK(ERR_LIB_X509, X509_F_DANE_I2D, 0), "dane_i2d"},
- {ERR_PACK(ERR_LIB_X509, X509_F_DIR_CTRL, 0), "dir_ctrl"},
- {ERR_PACK(ERR_LIB_X509, X509_F_GET_CERT_BY_SUBJECT, 0),
- "get_cert_by_subject"},
- {ERR_PACK(ERR_LIB_X509, X509_F_I2D_X509_AUX, 0), "i2d_X509_AUX"},
- {ERR_PACK(ERR_LIB_X509, X509_F_LOOKUP_CERTS_SK, 0), "lookup_certs_sk"},
- {ERR_PACK(ERR_LIB_X509, X509_F_NETSCAPE_SPKI_B64_DECODE, 0),
- "NETSCAPE_SPKI_b64_decode"},
- {ERR_PACK(ERR_LIB_X509, X509_F_NETSCAPE_SPKI_B64_ENCODE, 0),
- "NETSCAPE_SPKI_b64_encode"},
- {ERR_PACK(ERR_LIB_X509, X509_F_NEW_DIR, 0), "new_dir"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509AT_ADD1_ATTR, 0), "X509at_add1_attr"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509V3_ADD_EXT, 0), "X509v3_add_ext"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_CREATE_BY_NID, 0),
- "X509_ATTRIBUTE_create_by_NID"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ, 0),
- "X509_ATTRIBUTE_create_by_OBJ"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_CREATE_BY_TXT, 0),
- "X509_ATTRIBUTE_create_by_txt"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_GET0_DATA, 0),
- "X509_ATTRIBUTE_get0_data"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_SET1_DATA, 0),
- "X509_ATTRIBUTE_set1_data"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_CHECK_PRIVATE_KEY, 0),
- "X509_check_private_key"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_DIFF, 0), "X509_CRL_diff"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_METHOD_NEW, 0),
- "X509_CRL_METHOD_new"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_PRINT_FP, 0), "X509_CRL_print_fp"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_EXTENSION_CREATE_BY_NID, 0),
- "X509_EXTENSION_create_by_NID"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_EXTENSION_CREATE_BY_OBJ, 0),
- "X509_EXTENSION_create_by_OBJ"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_GET_PUBKEY_PARAMETERS, 0),
- "X509_get_pubkey_parameters"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_LOAD_CERT_CRL_FILE, 0),
- "X509_load_cert_crl_file"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_LOAD_CERT_FILE, 0),
- "X509_load_cert_file"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_LOAD_CRL_FILE, 0),
- "X509_load_crl_file"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_LOOKUP_METH_NEW, 0),
- "X509_LOOKUP_meth_new"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_LOOKUP_NEW, 0), "X509_LOOKUP_new"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ADD_ENTRY, 0),
- "X509_NAME_add_entry"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_CANON, 0), "x509_name_canon"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_CREATE_BY_NID, 0),
- "X509_NAME_ENTRY_create_by_NID"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_CREATE_BY_TXT, 0),
- "X509_NAME_ENTRY_create_by_txt"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_SET_OBJECT, 0),
- "X509_NAME_ENTRY_set_object"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ONELINE, 0), "X509_NAME_oneline"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_PRINT, 0), "X509_NAME_print"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_OBJECT_NEW, 0), "X509_OBJECT_new"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_PRINT_EX_FP, 0), "X509_print_ex_fp"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_DECODE, 0),
- "x509_pubkey_decode"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_GET, 0), "X509_PUBKEY_get"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_GET0, 0), "X509_PUBKEY_get0"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_SET, 0), "X509_PUBKEY_set"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_CHECK_PRIVATE_KEY, 0),
- "X509_REQ_check_private_key"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_PRINT_EX, 0), "X509_REQ_print_ex"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_PRINT_FP, 0), "X509_REQ_print_fp"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_TO_X509, 0), "X509_REQ_to_X509"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_ADD_CERT, 0),
- "X509_STORE_add_cert"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_ADD_CRL, 0),
- "X509_STORE_add_crl"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_ADD_LOOKUP, 0),
- "X509_STORE_add_lookup"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_GET1_ISSUER, 0),
- "X509_STORE_CTX_get1_issuer"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_INIT, 0),
- "X509_STORE_CTX_init"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_NEW, 0),
- "X509_STORE_CTX_new"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_PURPOSE_INHERIT, 0),
- "X509_STORE_CTX_purpose_inherit"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_NEW, 0), "X509_STORE_new"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_TO_X509_REQ, 0), "X509_to_X509_REQ"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_ADD, 0), "X509_TRUST_add"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_SET, 0), "X509_TRUST_set"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_VERIFY_CERT, 0), "X509_verify_cert"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_VERIFY_PARAM_NEW, 0),
- "X509_VERIFY_PARAM_new"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA X509_str_reasons[] = {
{ERR_PACK(ERR_LIB_X509, 0, X509_R_AKID_MISMATCH), "akid mismatch"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_BAD_SELECTOR), "bad selector"},
@@ -118,15 +21,22 @@ static const ERR_STRING_DATA X509_str_reasons[] = {
{ERR_PACK(ERR_LIB_X509, 0, X509_R_BASE64_DECODE_ERROR),
"base64 decode error"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_CANT_CHECK_DH_KEY), "cant check dh key"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_CERTIFICATE_VERIFICATION_FAILED),
+ "certificate verification failed"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_CERT_ALREADY_IN_HASH_TABLE),
"cert already in hash table"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_ALREADY_DELTA), "crl already delta"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_VERIFY_FAILURE),
"crl verify failure"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_ERROR_GETTING_MD_BY_NID),
+ "error getting md by nid"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_ERROR_USING_SIGINF_SET),
+ "error using siginf set"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_IDP_MISMATCH), "idp mismatch"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_ATTRIBUTES),
"invalid attributes"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_DIRECTORY), "invalid directory"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_DISTPOINT), "invalid distpoint"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_FIELD_NAME),
"invalid field name"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_TRUST), "invalid trust"},
@@ -162,6 +72,8 @@ static const ERR_STRING_DATA X509_str_reasons[] = {
{ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_NID), "unknown nid"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_PURPOSE_ID),
"unknown purpose id"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_SIGID_ALGS),
+ "unknown sigid algs"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_TRUST_ID), "unknown trust id"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_UNSUPPORTED_ALGORITHM),
"unsupported algorithm"},
@@ -172,13 +84,11 @@ static const ERR_STRING_DATA X509_str_reasons[] = {
#endif
-int ERR_load_X509_strings(void)
+int ossl_err_load_X509_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(X509_str_functs[0].error) == NULL) {
- ERR_load_strings_const(X509_str_functs);
+ if (ERR_reason_error_string(X509_str_reasons[0].error) == NULL)
ERR_load_strings_const(X509_str_reasons);
- }
#endif
return 1;
}
diff --git a/crypto/x509/x509_ext.c b/crypto/x509/x509_ext.c
index 4cdab724eadf..a7b85857bdad 100644
--- a/crypto/x509/x509_ext.c
+++ b/crypto/x509/x509_ext.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/x509/x509_local.h b/crypto/x509/x509_local.h
index 10807e1def04..6d602e1d8ef5 100644
--- a/crypto/x509/x509_local.h
+++ b/crypto/x509/x509_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,6 +9,9 @@
#include "internal/refcount.h"
+#define X509V3_conf_add_error_name_value(val) \
+ ERR_add_error_data(4, "name=", (val)->name, ", value=", (val)->value)
+
/*
* This structure holds all parameters associated with a verify operation by
* including an X509_VERIFY_PARAM structure in related structures the
@@ -36,7 +39,7 @@ struct X509_VERIFY_PARAM_st {
};
/* No error callback if depth < 0 */
-int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth);
+int ossl_x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth);
/* a sequence of these are used */
struct x509_attributes_st {
@@ -64,7 +67,7 @@ struct x509_crl_method_st {
int (*crl_init) (X509_CRL *crl);
int (*crl_free) (X509_CRL *crl);
int (*crl_lookup) (X509_CRL *crl, X509_REVOKED **ret,
- ASN1_INTEGER *ser, X509_NAME *issuer);
+ const ASN1_INTEGER *ser, const X509_NAME *issuer);
int (*crl_verify) (X509_CRL *crl, EVP_PKEY *pk);
};
@@ -77,15 +80,21 @@ struct x509_lookup_method_st {
int (*ctrl) (X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
char **ret);
int (*get_by_subject) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
- X509_NAME *name, X509_OBJECT *ret);
+ const X509_NAME *name, X509_OBJECT *ret);
int (*get_by_issuer_serial) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
- X509_NAME *name, ASN1_INTEGER *serial,
+ const X509_NAME *name,
+ const ASN1_INTEGER *serial,
X509_OBJECT *ret);
int (*get_by_fingerprint) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
const unsigned char *bytes, int len,
X509_OBJECT *ret);
int (*get_by_alias) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
const char *str, int len, X509_OBJECT *ret);
+ int (*get_by_subject_ex) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+ const X509_NAME *name, X509_OBJECT *ret,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ int (*ctrl_ex) (X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
+ char **ret, OSSL_LIB_CTX *libctx, const char *propq);
};
/* This is the functions plus an instance of the local variables. */
@@ -128,8 +137,11 @@ struct x509_store_st {
int (*cert_crl) (X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x);
/* Check policy status of the chain */
int (*check_policy) (X509_STORE_CTX *ctx);
- STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx, X509_NAME *nm);
- STACK_OF(X509_CRL) *(*lookup_crls) (X509_STORE_CTX *ctx, X509_NAME *nm);
+ STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx,
+ const X509_NAME *nm);
+ /* cannot constify 'ctx' param due to lookup_certs_sk() in x509_vfy.c */
+ STACK_OF(X509_CRL) *(*lookup_crls) (const X509_STORE_CTX *ctx,
+ const X509_NAME *nm);
int (*cleanup) (X509_STORE_CTX *ctx);
CRYPTO_EX_DATA ex_data;
CRYPTO_REF_COUNT references;
@@ -143,7 +155,5 @@ DEFINE_STACK_OF(BY_DIR_ENTRY)
typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY;
DEFINE_STACK_OF(STACK_OF_X509_NAME_ENTRY)
-void x509_set_signature_info(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
- const ASN1_STRING *sig);
-int x509_likely_issued(X509 *issuer, X509 *subject);
-int x509_signing_allowed(const X509 *issuer, const X509 *subject);
+int ossl_x509_likely_issued(X509 *issuer, X509 *subject);
+int ossl_x509_signing_allowed(const X509 *issuer, const X509 *subject);
diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c
index 641a41c35c78..d8927bda0706 100644
--- a/crypto/x509/x509_lu.c
+++ b/crypto/x509/x509_lu.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -20,7 +20,7 @@ X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
X509_LOOKUP *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- X509err(X509_F_X509_LOOKUP_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -71,29 +71,49 @@ int X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
return 1;
}
-int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
- char **ret)
+int X509_LOOKUP_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
+ char **ret, OSSL_LIB_CTX *libctx, const char *propq)
{
if (ctx->method == NULL)
return -1;
+ if (ctx->method->ctrl_ex != NULL)
+ return ctx->method->ctrl_ex(ctx, cmd, argc, argl, ret, libctx, propq);
if (ctx->method->ctrl != NULL)
return ctx->method->ctrl(ctx, cmd, argc, argl, ret);
+ return 1;
+}
+
+int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
+ char **ret)
+{
+ return X509_LOOKUP_ctrl_ex(ctx, cmd, argc, argl, ret, NULL, NULL);
+}
+
+int X509_LOOKUP_by_subject_ex(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+ const X509_NAME *name, X509_OBJECT *ret,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ if (ctx->skip
+ || ctx->method == NULL
+ || (ctx->method->get_by_subject == NULL
+ && ctx->method->get_by_subject_ex == NULL))
+ return 0;
+ if (ctx->method->get_by_subject_ex != NULL)
+ return ctx->method->get_by_subject_ex(ctx, type, name, ret, libctx,
+ propq);
else
- return 1;
+ return ctx->method->get_by_subject(ctx, type, name, ret);
}
int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
- X509_NAME *name, X509_OBJECT *ret)
+ const X509_NAME *name, X509_OBJECT *ret)
{
- if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
- return 0;
- if (ctx->skip)
- return 0;
- return ctx->method->get_by_subject(ctx, type, name, ret);
+ return X509_LOOKUP_by_subject_ex(ctx, type, name, ret, NULL, NULL);
}
int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
- X509_NAME *name, ASN1_INTEGER *serial,
+ const X509_NAME *name,
+ const ASN1_INTEGER *serial,
X509_OBJECT *ret)
{
if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL))
@@ -162,34 +182,33 @@ X509_STORE *X509_STORE_new(void)
X509_STORE *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return NULL;
}
if ((ret->objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL) {
- X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->cache = 1;
if ((ret->get_cert_methods = sk_X509_LOOKUP_new_null()) == NULL) {
- X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
if ((ret->param = X509_VERIFY_PARAM_new()) == NULL) {
- X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data)) {
- X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
- X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
-
ret->references = 1;
return ret;
@@ -237,7 +256,7 @@ int X509_STORE_up_ref(X509_STORE *vfy)
if (CRYPTO_UP_REF(&vfy->references, &i, vfy->lock) <= 0)
return 0;
- REF_PRINT_COUNT("X509_STORE", a);
+ REF_PRINT_COUNT("X509_STORE", vfy);
REF_ASSERT_ISNT(i < 2);
return ((i > 1) ? 1 : 0);
}
@@ -258,7 +277,7 @@ X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
/* a new one */
lu = X509_LOOKUP_new(m);
if (lu == NULL) {
- X509err(X509_F_X509_STORE_ADD_LOOKUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -266,14 +285,14 @@ X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
if (sk_X509_LOOKUP_push(v->get_cert_methods, lu))
return lu;
/* malloc failed */
- X509err(X509_F_X509_STORE_ADD_LOOKUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
X509_LOOKUP_free(lu);
return NULL;
}
X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs,
X509_LOOKUP_TYPE type,
- X509_NAME *name)
+ const X509_NAME *name)
{
X509_OBJECT *ret = X509_OBJECT_new();
@@ -286,10 +305,12 @@ X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs,
return ret;
}
-int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type,
- X509_NAME *name, X509_OBJECT *ret)
+/* Also fill the cache with all matching certificates */
+int X509_STORE_CTX_get_by_subject(const X509_STORE_CTX *vs,
+ X509_LOOKUP_TYPE type,
+ const X509_NAME *name, X509_OBJECT *ret)
{
- X509_STORE *store = vs->ctx;
+ X509_STORE *store = vs->store;
X509_LOOKUP *lu;
X509_OBJECT stmp, *tmp;
int i, j;
@@ -300,15 +321,17 @@ int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type,
stmp.type = X509_LU_NONE;
stmp.data.ptr = NULL;
+ if (!X509_STORE_lock(store))
+ return 0;
- X509_STORE_lock(store);
tmp = X509_OBJECT_retrieve_by_subject(store->objs, type, name);
X509_STORE_unlock(store);
if (tmp == NULL || type == X509_LU_CRL) {
for (i = 0; i < sk_X509_LOOKUP_num(store->get_cert_methods); i++) {
lu = sk_X509_LOOKUP_value(store->get_cert_methods, i);
- j = X509_LOOKUP_by_subject(lu, type, name, &stmp);
+ j = X509_LOOKUP_by_subject_ex(lu, type, name, &stmp, vs->libctx,
+ vs->propq);
if (j) {
tmp = &stmp;
break;
@@ -350,7 +373,12 @@ static int x509_store_add(X509_STORE *store, void *x, int crl) {
return 0;
}
- X509_STORE_lock(store);
+ if (!X509_STORE_lock(store)) {
+ obj->type = X509_LU_NONE;
+ X509_OBJECT_free(obj);
+ return 0;
+ }
+
if (X509_OBJECT_retrieve_match(store->objs, obj)) {
ret = 1;
} else {
@@ -368,7 +396,7 @@ static int x509_store_add(X509_STORE *store, void *x, int crl) {
int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
{
if (!x509_store_add(ctx, x, 0)) {
- X509err(X509_F_X509_STORE_ADD_CERT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
@@ -377,7 +405,7 @@ int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
{
if (!x509_store_add(ctx, x, 1)) {
- X509err(X509_F_X509_STORE_ADD_CRL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
@@ -403,7 +431,7 @@ X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a)
return a->data.x509;
}
-X509_CRL *X509_OBJECT_get0_X509_CRL(X509_OBJECT *a)
+X509_CRL *X509_OBJECT_get0_X509_CRL(const X509_OBJECT *a)
{
if (a == NULL || a->type != X509_LU_CRL)
return NULL;
@@ -420,7 +448,7 @@ X509_OBJECT *X509_OBJECT_new(void)
X509_OBJECT *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- X509err(X509_F_X509_OBJECT_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->type = X509_LU_NONE;
@@ -472,7 +500,7 @@ void X509_OBJECT_free(X509_OBJECT *a)
}
static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
- X509_NAME *name, int *pnmatch)
+ const X509_NAME *name, int *pnmatch)
{
X509_OBJECT stmp;
X509 x509_s;
@@ -483,42 +511,30 @@ static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
switch (type) {
case X509_LU_X509:
stmp.data.x509 = &x509_s;
- x509_s.cert_info.subject = name;
+ x509_s.cert_info.subject = (X509_NAME *)name; /* won't modify it */
break;
case X509_LU_CRL:
stmp.data.crl = &crl_s;
- crl_s.crl.issuer = name;
+ crl_s.crl.issuer = (X509_NAME *)name; /* won't modify it */
break;
case X509_LU_NONE:
/* abort(); */
return -1;
}
- idx = sk_X509_OBJECT_find(h, &stmp);
- if (idx >= 0 && pnmatch) {
- int tidx;
- const X509_OBJECT *tobj, *pstmp;
- *pnmatch = 1;
- pstmp = &stmp;
- for (tidx = idx + 1; tidx < sk_X509_OBJECT_num(h); tidx++) {
- tobj = sk_X509_OBJECT_value(h, tidx);
- if (x509_object_cmp(&tobj, &pstmp))
- break;
- (*pnmatch)++;
- }
- }
+ idx = sk_X509_OBJECT_find_all(h, &stmp, pnmatch);
return idx;
}
int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
- X509_NAME *name)
+ const X509_NAME *name)
{
return x509_object_idx_cnt(h, type, name, NULL);
}
X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
X509_LOOKUP_TYPE type,
- X509_NAME *name)
+ const X509_NAME *name)
{
int idx;
idx = X509_OBJECT_idx_by_subject(h, type, name);
@@ -527,23 +543,59 @@ X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
return sk_X509_OBJECT_value(h, idx);
}
-STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *v)
+STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(const X509_STORE *v)
{
return v->objs;
}
-STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
+STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *store)
+{
+ STACK_OF(X509) *sk;
+ STACK_OF(X509_OBJECT) *objs;
+ int i;
+
+ if (store == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ if ((sk = sk_X509_new_null()) == NULL)
+ return NULL;
+ if (!X509_STORE_lock(store))
+ goto out_free;
+
+ objs = X509_STORE_get0_objects(store);
+ for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
+ X509 *cert = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
+
+ if (cert != NULL
+ && !X509_add_cert(sk, cert, X509_ADD_FLAG_UP_REF))
+ goto err;
+ }
+ X509_STORE_unlock(store);
+ return sk;
+
+ err:
+ X509_STORE_unlock(store);
+ out_free:
+ sk_X509_pop_free(sk, X509_free);
+ return NULL;
+}
+
+STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx,
+ const X509_NAME *nm)
{
int i, idx, cnt;
STACK_OF(X509) *sk = NULL;
X509 *x;
X509_OBJECT *obj;
- X509_STORE *store = ctx->ctx;
+ X509_STORE *store = ctx->store;
if (store == NULL)
return NULL;
- X509_STORE_lock(store);
+ if (!X509_STORE_lock(store))
+ return NULL;
+
idx = x509_object_idx_cnt(store->objs, X509_LU_X509, nm, &cnt);
if (idx < 0) {
/*
@@ -561,7 +613,8 @@ STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
return NULL;
}
X509_OBJECT_free(xobj);
- X509_STORE_lock(store);
+ if (!X509_STORE_lock(store))
+ return NULL;
idx = x509_object_idx_cnt(store->objs, X509_LU_X509, nm, &cnt);
if (idx < 0) {
X509_STORE_unlock(store);
@@ -573,29 +626,24 @@ STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
for (i = 0; i < cnt; i++, idx++) {
obj = sk_X509_OBJECT_value(store->objs, idx);
x = obj->data.x509;
- if (!X509_up_ref(x)) {
+ if (!X509_add_cert(sk, x, X509_ADD_FLAG_UP_REF)) {
X509_STORE_unlock(store);
sk_X509_pop_free(sk, X509_free);
return NULL;
}
- if (!sk_X509_push(sk, x)) {
- X509_STORE_unlock(store);
- X509_free(x);
- sk_X509_pop_free(sk, X509_free);
- return NULL;
- }
}
X509_STORE_unlock(store);
return sk;
}
-STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
+STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(const X509_STORE_CTX *ctx,
+ const X509_NAME *nm)
{
int i, idx, cnt;
STACK_OF(X509_CRL) *sk = sk_X509_CRL_new_null();
X509_CRL *x;
X509_OBJECT *obj, *xobj = X509_OBJECT_new();
- X509_STORE *store = ctx->ctx;
+ X509_STORE *store = ctx->store;
/* Always do lookup to possibly add new CRLs to cache */
if (sk == NULL
@@ -607,7 +655,10 @@ STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
return NULL;
}
X509_OBJECT_free(xobj);
- X509_STORE_lock(store);
+ if (!X509_STORE_lock(store)) {
+ sk_X509_CRL_free(sk);
+ return NULL;
+ }
idx = x509_object_idx_cnt(store->objs, X509_LU_CRL, nm, &cnt);
if (idx < 0) {
X509_STORE_unlock(store);
@@ -654,7 +705,7 @@ X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
if (!X509_cmp(obj->data.x509, x->data.x509))
return obj;
} else if (x->type == X509_LU_CRL) {
- if (!X509_CRL_match(obj->data.crl, x->data.crl))
+ if (X509_CRL_match(obj->data.crl, x->data.crl) == 0)
return obj;
} else
return obj;
@@ -663,11 +714,8 @@ X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
}
/*-
- * Try to get issuer certificate from store. Due to limitations
- * of the API this can only retrieve a single certificate matching
- * a given subject name. However it will fill the cache with all
- * matching certificates, so we can examine the cache for all
- * matches.
+ * Try to get issuer cert from |ctx->store| matching the subject name of |x|.
+ * Prefer the first non-expired one, else take the most recently expired one.
*
* Return values are:
* 1 lookup successful.
@@ -676,10 +724,10 @@ X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
*/
int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
{
- X509_NAME *xn;
+ const X509_NAME *xn;
X509_OBJECT *obj = X509_OBJECT_new(), *pobj = NULL;
- X509_STORE *store = ctx->ctx;
- int i, ok, idx, ret;
+ X509_STORE *store = ctx->store;
+ int i, ok, idx, ret, nmatch = 0;
if (obj == NULL)
return -1;
@@ -690,53 +738,58 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
X509_OBJECT_free(obj);
return 0;
}
- /* If certificate matches all OK */
+ /* If certificate matches and is currently valid all OK */
if (ctx->check_issued(ctx, x, obj->data.x509)) {
- if (x509_check_cert_time(ctx, obj->data.x509, -1)) {
+ if (ossl_x509_check_cert_time(ctx, obj->data.x509, -1)) {
*issuer = obj->data.x509;
- if (!X509_up_ref(*issuer)) {
- *issuer = NULL;
- ok = -1;
- }
+ /* |*issuer| has taken over the cert reference from |obj| */
+ obj->type = X509_LU_NONE;
X509_OBJECT_free(obj);
- return ok;
+ return 1;
}
}
X509_OBJECT_free(obj);
+ /*
+ * Due to limitations of the API this can only retrieve a single cert.
+ * However it will fill the cache with all matching certificates,
+ * so we can examine the cache for all matches.
+ */
if (store == NULL)
return 0;
- /* Else find index of first cert accepted by 'check_issued' */
+ /* Find index of first currently valid cert accepted by 'check_issued' */
ret = 0;
- X509_STORE_lock(store);
- idx = X509_OBJECT_idx_by_subject(store->objs, X509_LU_X509, xn);
- if (idx != -1) { /* should be true as we've had at least one
- * match */
+ if (!X509_STORE_lock(store))
+ return 0;
+
+ idx = x509_object_idx_cnt(store->objs, X509_LU_X509, xn, &nmatch);
+ if (idx != -1) { /* should be true as we've had at least one match */
/* Look through all matching certs for suitable issuer */
- for (i = idx; i < sk_X509_OBJECT_num(store->objs); i++) {
+ for (i = idx; i < idx + nmatch; i++) {
pobj = sk_X509_OBJECT_value(store->objs, i);
/* See if we've run past the matches */
if (pobj->type != X509_LU_X509)
break;
- if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509)))
- break;
if (ctx->check_issued(ctx, x, pobj->data.x509)) {
- *issuer = pobj->data.x509;
ret = 1;
+ /* If times check fine, exit with match, else keep looking. */
+ if (ossl_x509_check_cert_time(ctx, pobj->data.x509, -1)) {
+ *issuer = pobj->data.x509;
+ break;
+ }
/*
- * If times check, exit with match,
- * otherwise keep looking. Leave last
- * match in issuer so we return nearest
- * match if no certificate time is OK.
+ * Leave the so far most recently expired match in *issuer
+ * so we return nearest match if no certificate time is OK.
*/
-
- if (x509_check_cert_time(ctx, *issuer, -1))
- break;
+ if (*issuer == NULL
+ || ASN1_TIME_compare(X509_get0_notAfter(pobj->data.x509),
+ X509_get0_notAfter(*issuer)) > 0)
+ *issuer = pobj->data.x509;
}
}
}
- if (*issuer && !X509_up_ref(*issuer)) {
+ if (*issuer != NULL && !X509_up_ref(*issuer)) {
*issuer = NULL;
ret = -1;
}
@@ -765,12 +818,12 @@ int X509_STORE_set_trust(X509_STORE *ctx, int trust)
return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
}
-int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param)
+int X509_STORE_set1_param(X509_STORE *ctx, const X509_VERIFY_PARAM *param)
{
return X509_VERIFY_PARAM_set1(ctx->param, param);
}
-X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx)
+X509_VERIFY_PARAM *X509_STORE_get0_param(const X509_STORE *ctx)
{
return ctx->param;
}
@@ -780,7 +833,7 @@ void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify)
ctx->verify = verify;
}
-X509_STORE_CTX_verify_fn X509_STORE_get_verify(X509_STORE *ctx)
+X509_STORE_CTX_verify_fn X509_STORE_get_verify(const X509_STORE *ctx)
{
return ctx->verify;
}
@@ -791,7 +844,7 @@ void X509_STORE_set_verify_cb(X509_STORE *ctx,
ctx->verify_cb = verify_cb;
}
-X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(X509_STORE *ctx)
+X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(const X509_STORE *ctx)
{
return ctx->verify_cb;
}
@@ -802,7 +855,7 @@ void X509_STORE_set_get_issuer(X509_STORE *ctx,
ctx->get_issuer = get_issuer;
}
-X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(X509_STORE *ctx)
+X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(const X509_STORE *ctx)
{
return ctx->get_issuer;
}
@@ -813,7 +866,7 @@ void X509_STORE_set_check_issued(X509_STORE *ctx,
ctx->check_issued = check_issued;
}
-X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(X509_STORE *ctx)
+X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(const X509_STORE *ctx)
{
return ctx->check_issued;
}
@@ -824,7 +877,7 @@ void X509_STORE_set_check_revocation(X509_STORE *ctx,
ctx->check_revocation = check_revocation;
}
-X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(X509_STORE *ctx)
+X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(const X509_STORE *ctx)
{
return ctx->check_revocation;
}
@@ -835,7 +888,7 @@ void X509_STORE_set_get_crl(X509_STORE *ctx,
ctx->get_crl = get_crl;
}
-X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(X509_STORE *ctx)
+X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(const X509_STORE *ctx)
{
return ctx->get_crl;
}
@@ -846,7 +899,7 @@ void X509_STORE_set_check_crl(X509_STORE *ctx,
ctx->check_crl = check_crl;
}
-X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(X509_STORE *ctx)
+X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(const X509_STORE *ctx)
{
return ctx->check_crl;
}
@@ -857,7 +910,7 @@ void X509_STORE_set_cert_crl(X509_STORE *ctx,
ctx->cert_crl = cert_crl;
}
-X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(X509_STORE *ctx)
+X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(const X509_STORE *ctx)
{
return ctx->cert_crl;
}
@@ -868,7 +921,7 @@ void X509_STORE_set_check_policy(X509_STORE *ctx,
ctx->check_policy = check_policy;
}
-X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(X509_STORE *ctx)
+X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(const X509_STORE *ctx)
{
return ctx->check_policy;
}
@@ -879,7 +932,7 @@ void X509_STORE_set_lookup_certs(X509_STORE *ctx,
ctx->lookup_certs = lookup_certs;
}
-X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(X509_STORE *ctx)
+X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(const X509_STORE *ctx)
{
return ctx->lookup_certs;
}
@@ -890,7 +943,7 @@ void X509_STORE_set_lookup_crls(X509_STORE *ctx,
ctx->lookup_crls = lookup_crls;
}
-X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(X509_STORE *ctx)
+X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(const X509_STORE *ctx)
{
return ctx->lookup_crls;
}
@@ -901,7 +954,7 @@ void X509_STORE_set_cleanup(X509_STORE *ctx,
ctx->cleanup = ctx_cleanup;
}
-X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(X509_STORE *ctx)
+X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(const X509_STORE *ctx)
{
return ctx->cleanup;
}
@@ -911,12 +964,12 @@ int X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data)
return CRYPTO_set_ex_data(&ctx->ex_data, idx, data);
}
-void *X509_STORE_get_ex_data(X509_STORE *ctx, int idx)
+void *X509_STORE_get_ex_data(const X509_STORE *ctx, int idx)
{
return CRYPTO_get_ex_data(&ctx->ex_data, idx);
}
-X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx)
+X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx)
{
- return ctx->ctx;
+ return ctx->store;
}
diff --git a/crypto/x509/x509_meth.c b/crypto/x509/x509_meth.c
index 9348cc8eb788..a8eedd9b59af 100644
--- a/crypto/x509/x509_meth.c
+++ b/crypto/x509/x509_meth.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -14,7 +14,7 @@
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/x509.h>
-#include <openssl/ossl_typ.h>
+#include <openssl/types.h>
#include "x509_local.h"
X509_LOOKUP_METHOD *X509_LOOKUP_meth_new(const char *name)
@@ -24,7 +24,7 @@ X509_LOOKUP_METHOD *X509_LOOKUP_meth_new(const char *name)
if (method != NULL) {
method->name = OPENSSL_strdup(name);
if (method->name == NULL) {
- X509err(X509_F_X509_LOOKUP_METH_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
}
diff --git a/crypto/x509/x509_obj.c b/crypto/x509/x509_obj.c
index f54d483cc4dd..12c6d6f78b6e 100644
--- a/crypto/x509/x509_obj.c
+++ b/crypto/x509/x509_obj.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,6 +13,7 @@
#include <openssl/x509.h>
#include <openssl/buffer.h>
#include "crypto/x509.h"
+#include "crypto/ctype.h"
/*
* Limit to ensure we don't overflow: much greater than
@@ -26,6 +27,7 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len)
const X509_NAME_ENTRY *ne;
int i;
int n, lold, l, l1, l2, num, j, type;
+ int prev_set = -1;
const char *s;
char *p;
unsigned char *q;
@@ -71,7 +73,7 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len)
type = ne->value->type;
num = ne->value->length;
if (num > NAME_ONELINE_MAX) {
- X509err(X509_F_X509_NAME_ONELINE, X509_R_NAME_TOO_LONG);
+ ERR_raise(ERR_LIB_X509, X509_R_NAME_TOO_LONG);
goto end;
}
q = ne->value->data;
@@ -107,20 +109,17 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len)
if (!gs_doit[j & 3])
continue;
l2++;
-#ifndef CHARSET_EBCDIC
- if ((q[j] < ' ') || (q[j] > '~'))
- l2 += 3;
-#else
- if ((os_toascii[q[j]] < os_toascii[' ']) ||
- (os_toascii[q[j]] > os_toascii['~']))
+ if (q[j] == '/' || q[j] == '+')
+ l2++; /* char needs to be escaped */
+ else if ((ossl_toascii(q[j]) < ossl_toascii(' ')) ||
+ (ossl_toascii(q[j]) > ossl_toascii('~')))
l2 += 3;
-#endif
}
lold = l;
l += 1 + l1 + 1 + l2;
if (l > NAME_ONELINE_MAX) {
- X509err(X509_F_X509_NAME_ONELINE, X509_R_NAME_TOO_LONG);
+ ERR_raise(ERR_LIB_X509, X509_R_NAME_TOO_LONG);
goto end;
}
if (b != NULL) {
@@ -131,7 +130,7 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len)
break;
} else
p = &(buf[lold]);
- *(p++) = '/';
+ *(p++) = prev_set == ne->set ? '+' : '/';
memcpy(p, s, (unsigned int)l1);
p += l1;
*(p++) = '=';
@@ -150,8 +149,11 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len)
*(p++) = 'x';
*(p++) = hex[(n >> 4) & 0x0f];
*(p++) = hex[n & 0x0f];
- } else
+ } else {
+ if (n == '/' || n == '+')
+ *(p++) = '\\';
*(p++) = n;
+ }
#else
n = os_toascii[q[j]];
if ((n < os_toascii[' ']) || (n > os_toascii['~'])) {
@@ -159,11 +161,15 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len)
*(p++) = 'x';
*(p++) = hex[(n >> 4) & 0x0f];
*(p++) = hex[n & 0x0f];
- } else
+ } else {
+ if (n == os_toascii['/'] || n == os_toascii['+'])
+ *(p++) = '\\';
*(p++) = q[j];
+ }
#endif
}
*p = '\0';
+ prev_set = ne->set;
}
if (b != NULL) {
p = b->data;
@@ -174,7 +180,7 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len)
*p = '\0';
return p;
err:
- X509err(X509_F_X509_NAME_ONELINE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
end:
BUF_MEM_free(b);
return NULL;
diff --git a/crypto/x509/x509_r2x.c b/crypto/x509/x509_r2x.c
index 6b1623feacb7..c7f6181c4465 100644
--- a/crypto/x509/x509_r2x.c
+++ b/crypto/x509/x509_r2x.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -21,11 +21,11 @@ X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey)
{
X509 *ret = NULL;
X509_CINF *xi = NULL;
- X509_NAME *xn;
+ const X509_NAME *xn;
EVP_PKEY *pubkey = NULL;
if ((ret = X509_new()) == NULL) {
- X509err(X509_F_X509_REQ_TO_X509, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return NULL;
}
diff --git a/crypto/x509/x509_req.c b/crypto/x509/x509_req.c
index c2b8cb9f3e2d..5428bdaf4ca6 100644
--- a/crypto/x509/x509_req.c
+++ b/crypto/x509/x509_req.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -26,9 +26,9 @@ X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
int i;
EVP_PKEY *pktmp;
- ret = X509_REQ_new();
+ ret = X509_REQ_new_ex(x->libctx, x->propq);
if (ret == NULL) {
- X509err(X509_F_X509_TO_X509_REQ, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -85,33 +85,18 @@ int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k)
int ok = 0;
xk = X509_REQ_get_pubkey(x);
- switch (EVP_PKEY_cmp(xk, k)) {
+ switch (EVP_PKEY_eq(xk, k)) {
case 1:
ok = 1;
break;
case 0:
- X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY,
- X509_R_KEY_VALUES_MISMATCH);
+ ERR_raise(ERR_LIB_X509, X509_R_KEY_VALUES_MISMATCH);
break;
case -1:
- X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, X509_R_KEY_TYPE_MISMATCH);
+ ERR_raise(ERR_LIB_X509, X509_R_KEY_TYPE_MISMATCH);
break;
case -2:
-#ifndef OPENSSL_NO_EC
- if (EVP_PKEY_id(k) == EVP_PKEY_EC) {
- X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, ERR_R_EC_LIB);
- break;
- }
-#endif
-#ifndef OPENSSL_NO_DH
- if (EVP_PKEY_id(k) == EVP_PKEY_DH) {
- /* No idea */
- X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY,
- X509_R_CANT_CHECK_DH_KEY);
- break;
- }
-#endif
- X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, X509_R_UNKNOWN_KEY_TYPE);
+ ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_KEY_TYPE);
}
EVP_PKEY_free(xk);
@@ -131,6 +116,7 @@ static int *ext_nids = ext_nid_list;
int X509_REQ_extension_nid(int req_nid)
{
int i, nid;
+
for (i = 0;; i++) {
nid = ext_nids[i];
if (nid == NID_undef)
@@ -157,7 +143,7 @@ STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req)
int idx, *pnid;
const unsigned char *p;
- if ((req == NULL) || !ext_nids)
+ if (req == NULL || !ext_nids)
return NULL;
for (pnid = ext_nids; *pnid != NID_undef; pnid++) {
idx = X509_REQ_get_attr_by_NID(req, *pnid, -1);
@@ -181,15 +167,15 @@ STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req)
* Add a STACK_OF extensions to a certificate request: allow alternative OIDs
* in case we want to create a non standard one.
*/
-
-int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts,
- int nid)
+int X509_REQ_add_extensions_nid(X509_REQ *req,
+ const STACK_OF(X509_EXTENSION) *exts, int nid)
{
int extlen;
int rv = 0;
unsigned char *ext = NULL;
+
/* Generate encoding of extensions */
- extlen = ASN1_item_i2d((ASN1_VALUE *)exts, &ext,
+ extlen = ASN1_item_i2d((const ASN1_VALUE *)exts, &ext,
ASN1_ITEM_rptr(X509_EXTENSIONS));
if (extlen <= 0)
return 0;
@@ -199,7 +185,7 @@ int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts,
}
/* This is the normal usage: use the "official" OID */
-int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts)
+int X509_REQ_add_extensions(X509_REQ *req, const STACK_OF(X509_EXTENSION) *exts)
{
return X509_REQ_add_extensions_nid(req, exts, NID_ext_req);
}
@@ -229,8 +215,13 @@ X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc)
X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc)
{
- X509_ATTRIBUTE *attr = X509at_delete_attr(req->req_info.attributes, loc);
+ X509_ATTRIBUTE *attr;
+ if (req == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ attr = X509at_delete_attr(req->req_info.attributes, loc);
if (attr != NULL)
req->req_info.enc.modified = 1;
return attr;
@@ -238,6 +229,10 @@ X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc)
int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr)
{
+ if (req == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
if (!X509at_add1_attr(&req->req_info.attributes, attr))
return 0;
req->req_info.enc.modified = 1;
@@ -248,6 +243,10 @@ int X509_REQ_add1_attr_by_OBJ(X509_REQ *req,
const ASN1_OBJECT *obj, int type,
const unsigned char *bytes, int len)
{
+ if (req == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
if (!X509at_add1_attr_by_OBJ(&req->req_info.attributes, obj,
type, bytes, len))
return 0;
@@ -259,6 +258,10 @@ int X509_REQ_add1_attr_by_NID(X509_REQ *req,
int nid, int type,
const unsigned char *bytes, int len)
{
+ if (req == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
if (!X509at_add1_attr_by_NID(&req->req_info.attributes, nid,
type, bytes, len))
return 0;
@@ -270,6 +273,10 @@ int X509_REQ_add1_attr_by_txt(X509_REQ *req,
const char *attrname, int type,
const unsigned char *bytes, int len)
{
+ if (req == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
if (!X509at_add1_attr_by_txt(&req->req_info.attributes, attrname,
type, bytes, len))
return 0;
@@ -299,7 +306,7 @@ void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig,
void X509_REQ_set0_signature(X509_REQ *req, ASN1_BIT_STRING *psig)
{
if (req->signature)
- ASN1_BIT_STRING_free(req->signature);
+ ASN1_BIT_STRING_free(req->signature);
req->signature = psig;
}
@@ -315,6 +322,10 @@ int X509_REQ_get_signature_nid(const X509_REQ *req)
int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp)
{
+ if (req == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
req->req_info.enc.modified = 1;
return i2d_X509_REQ_INFO(&req->req_info, pp);
}
diff --git a/crypto/x509/x509_set.c b/crypto/x509/x509_set.c
index 164b4e2be136..d8ddde8aaa51 100644
--- a/crypto/x509/x509_set.c
+++ b/crypto/x509/x509_set.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -47,21 +47,21 @@ int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial)
return 1;
}
-int X509_set_issuer_name(X509 *x, X509_NAME *name)
+int X509_set_issuer_name(X509 *x, const X509_NAME *name)
{
if (x == NULL)
return 0;
return X509_NAME_set(&x->cert_info.issuer, name);
}
-int X509_set_subject_name(X509 *x, X509_NAME *name)
+int X509_set_subject_name(X509 *x, const X509_NAME *name)
{
if (x == NULL)
return 0;
return X509_NAME_set(&x->cert_info.subject, name);
}
-int x509_set1_time(ASN1_TIME **ptm, const ASN1_TIME *tm)
+int ossl_x509_set1_time(ASN1_TIME **ptm, const ASN1_TIME *tm)
{
ASN1_TIME *in;
in = *ptm;
@@ -79,14 +79,14 @@ int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm)
{
if (x == NULL)
return 0;
- return x509_set1_time(&x->cert_info.validity.notBefore, tm);
+ return ossl_x509_set1_time(&x->cert_info.validity.notBefore, tm);
}
int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm)
{
if (x == NULL)
return 0;
- return x509_set1_time(&x->cert_info.validity.notAfter, tm);
+ return ossl_x509_set1_time(&x->cert_info.validity.notAfter, tm);
}
int X509_set_pubkey(X509 *x, EVP_PKEY *pkey)
@@ -192,46 +192,85 @@ int X509_get_signature_info(X509 *x, int *mdnid, int *pknid, int *secbits,
return X509_SIG_INFO_get(&x->siginf, mdnid, pknid, secbits, flags);
}
-static void x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
- const ASN1_STRING *sig)
+/* Modify *siginf according to alg and sig. Return 1 on success, else 0. */
+static int x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
+ const ASN1_STRING *sig)
{
int pknid, mdnid;
const EVP_MD *md;
+ const EVP_PKEY_ASN1_METHOD *ameth;
siginf->mdnid = NID_undef;
siginf->pknid = NID_undef;
siginf->secbits = -1;
siginf->flags = 0;
if (!OBJ_find_sigid_algs(OBJ_obj2nid(alg->algorithm), &mdnid, &pknid)
- || pknid == NID_undef)
- return;
+ || pknid == NID_undef) {
+ ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_SIGID_ALGS);
+ return 0;
+ }
+ siginf->mdnid = mdnid;
siginf->pknid = pknid;
- if (mdnid == NID_undef) {
+
+ switch (mdnid) {
+ case NID_undef:
/* If we have one, use a custom handler for this algorithm */
- const EVP_PKEY_ASN1_METHOD *ameth = EVP_PKEY_asn1_find(NULL, pknid);
+ ameth = EVP_PKEY_asn1_find(NULL, pknid);
if (ameth == NULL || ameth->siginf_set == NULL
- || ameth->siginf_set(siginf, alg, sig) == 0)
- return;
- siginf->flags |= X509_SIG_INFO_VALID;
- return;
+ || !ameth->siginf_set(siginf, alg, sig)) {
+ ERR_raise(ERR_LIB_X509, X509_R_ERROR_USING_SIGINF_SET);
+ return 0;
+ }
+ break;
+ /*
+ * SHA1 and MD5 are known to be broken. Reduce security bits so that
+ * they're no longer accepted at security level 1.
+ * The real values don't really matter as long as they're lower than 80,
+ * which is our security level 1.
+ */
+ case NID_sha1:
+ /*
+ * https://eprint.iacr.org/2020/014 puts a chosen-prefix attack
+ * for SHA1 at2^63.4
+ */
+ siginf->secbits = 63;
+ break;
+ case NID_md5:
+ /*
+ * https://documents.epfl.ch/users/l/le/lenstra/public/papers/lat.pdf
+ * puts a chosen-prefix attack for MD5 at 2^39.
+ */
+ siginf->secbits = 39;
+ break;
+ case NID_id_GostR3411_94:
+ /*
+ * There is a collision attack on GOST R 34.11-94 at 2^105, see
+ * https://link.springer.com/chapter/10.1007%2F978-3-540-85174-5_10
+ */
+ siginf->secbits = 105;
+ break;
+ default:
+ /* Security bits: half number of bits in digest */
+ if ((md = EVP_get_digestbynid(mdnid)) == NULL) {
+ ERR_raise(ERR_LIB_X509, X509_R_ERROR_GETTING_MD_BY_NID);
+ return 0;
+ }
+ siginf->secbits = EVP_MD_get_size(md) * 4;
+ break;
}
- siginf->flags |= X509_SIG_INFO_VALID;
- siginf->mdnid = mdnid;
- md = EVP_get_digestbynid(mdnid);
- if (md == NULL)
- return;
- /* Security bits: half number of bits in digest */
- siginf->secbits = EVP_MD_size(md) * 4;
switch (mdnid) {
- case NID_sha1:
- case NID_sha256:
- case NID_sha384:
- case NID_sha512:
+ case NID_sha1:
+ case NID_sha256:
+ case NID_sha384:
+ case NID_sha512:
siginf->flags |= X509_SIG_INFO_TLS;
}
+ siginf->flags |= X509_SIG_INFO_VALID;
+ return 1;
}
-void x509_init_sig_info(X509 *x)
+/* Returns 1 on success, 0 on failure */
+int ossl_x509_init_sig_info(X509 *x)
{
- x509_sig_info_init(&x->siginf, &x->sig_alg, &x->signature);
+ return x509_sig_info_init(&x->siginf, &x->sig_alg, &x->signature);
}
diff --git a/crypto/x509/x509_trs.c b/crypto/x509/x509_trs.c
deleted file mode 100644
index a10d437735b8..000000000000
--- a/crypto/x509/x509_trs.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/x509v3.h>
-#include "crypto/x509.h"
-
-static int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b);
-static void trtable_free(X509_TRUST *p);
-
-static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags);
-static int trust_1oid(X509_TRUST *trust, X509 *x, int flags);
-static int trust_compat(X509_TRUST *trust, X509 *x, int flags);
-
-static int obj_trust(int id, X509 *x, int flags);
-static int (*default_trust) (int id, X509 *x, int flags) = obj_trust;
-
-/*
- * WARNING: the following table should be kept in order of trust and without
- * any gaps so we can just subtract the minimum trust value to get an index
- * into the table
- */
-
-static X509_TRUST trstandard[] = {
- {X509_TRUST_COMPAT, 0, trust_compat, "compatible", 0, NULL},
- {X509_TRUST_SSL_CLIENT, 0, trust_1oidany, "SSL Client", NID_client_auth,
- NULL},
- {X509_TRUST_SSL_SERVER, 0, trust_1oidany, "SSL Server", NID_server_auth,
- NULL},
- {X509_TRUST_EMAIL, 0, trust_1oidany, "S/MIME email", NID_email_protect,
- NULL},
- {X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, "Object Signer", NID_code_sign,
- NULL},
- {X509_TRUST_OCSP_SIGN, 0, trust_1oid, "OCSP responder", NID_OCSP_sign,
- NULL},
- {X509_TRUST_OCSP_REQUEST, 0, trust_1oid, "OCSP request", NID_ad_OCSP,
- NULL},
- {X509_TRUST_TSA, 0, trust_1oidany, "TSA server", NID_time_stamp, NULL}
-};
-
-#define X509_TRUST_COUNT OSSL_NELEM(trstandard)
-
-static STACK_OF(X509_TRUST) *trtable = NULL;
-
-static int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b)
-{
- return (*a)->trust - (*b)->trust;
-}
-
-int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *,
- int) {
- int (*oldtrust) (int, X509 *, int);
- oldtrust = default_trust;
- default_trust = trust;
- return oldtrust;
-}
-
-int X509_check_trust(X509 *x, int id, int flags)
-{
- X509_TRUST *pt;
- int idx;
-
- /* We get this as a default value */
- if (id == X509_TRUST_DEFAULT)
- return obj_trust(NID_anyExtendedKeyUsage, x,
- flags | X509_TRUST_DO_SS_COMPAT);
- idx = X509_TRUST_get_by_id(id);
- if (idx == -1)
- return default_trust(id, x, flags);
- pt = X509_TRUST_get0(idx);
- return pt->check_trust(pt, x, flags);
-}
-
-int X509_TRUST_get_count(void)
-{
- if (!trtable)
- return X509_TRUST_COUNT;
- return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT;
-}
-
-X509_TRUST *X509_TRUST_get0(int idx)
-{
- if (idx < 0)
- return NULL;
- if (idx < (int)X509_TRUST_COUNT)
- return trstandard + idx;
- return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT);
-}
-
-int X509_TRUST_get_by_id(int id)
-{
- X509_TRUST tmp;
- int idx;
-
- if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX))
- return id - X509_TRUST_MIN;
- if (trtable == NULL)
- return -1;
- tmp.trust = id;
- idx = sk_X509_TRUST_find(trtable, &tmp);
- if (idx < 0)
- return -1;
- return idx + X509_TRUST_COUNT;
-}
-
-int X509_TRUST_set(int *t, int trust)
-{
- if (X509_TRUST_get_by_id(trust) == -1) {
- X509err(X509_F_X509_TRUST_SET, X509_R_INVALID_TRUST);
- return 0;
- }
- *t = trust;
- return 1;
-}
-
-int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int),
- const char *name, int arg1, void *arg2)
-{
- int idx;
- X509_TRUST *trtmp;
- /*
- * This is set according to what we change: application can't set it
- */
- flags &= ~X509_TRUST_DYNAMIC;
- /* This will always be set for application modified trust entries */
- flags |= X509_TRUST_DYNAMIC_NAME;
- /* Get existing entry if any */
- idx = X509_TRUST_get_by_id(id);
- /* Need a new entry */
- if (idx == -1) {
- if ((trtmp = OPENSSL_malloc(sizeof(*trtmp))) == NULL) {
- X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- trtmp->flags = X509_TRUST_DYNAMIC;
- } else
- trtmp = X509_TRUST_get0(idx);
-
- /* OPENSSL_free existing name if dynamic */
- if (trtmp->flags & X509_TRUST_DYNAMIC_NAME)
- OPENSSL_free(trtmp->name);
- /* dup supplied name */
- if ((trtmp->name = OPENSSL_strdup(name)) == NULL) {
- X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- /* Keep the dynamic flag of existing entry */
- trtmp->flags &= X509_TRUST_DYNAMIC;
- /* Set all other flags */
- trtmp->flags |= flags;
-
- trtmp->trust = id;
- trtmp->check_trust = ck;
- trtmp->arg1 = arg1;
- trtmp->arg2 = arg2;
-
- /* If its a new entry manage the dynamic table */
- if (idx == -1) {
- if (trtable == NULL
- && (trtable = sk_X509_TRUST_new(tr_cmp)) == NULL) {
- X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
- goto err;;
- }
- if (!sk_X509_TRUST_push(trtable, trtmp)) {
- X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
- return 1;
- err:
- if (idx == -1) {
- OPENSSL_free(trtmp->name);
- OPENSSL_free(trtmp);
- }
- return 0;
-}
-
-static void trtable_free(X509_TRUST *p)
-{
- if (!p)
- return;
- if (p->flags & X509_TRUST_DYNAMIC) {
- if (p->flags & X509_TRUST_DYNAMIC_NAME)
- OPENSSL_free(p->name);
- OPENSSL_free(p);
- }
-}
-
-void X509_TRUST_cleanup(void)
-{
- sk_X509_TRUST_pop_free(trtable, trtable_free);
- trtable = NULL;
-}
-
-int X509_TRUST_get_flags(const X509_TRUST *xp)
-{
- return xp->flags;
-}
-
-char *X509_TRUST_get0_name(const X509_TRUST *xp)
-{
- return xp->name;
-}
-
-int X509_TRUST_get_trust(const X509_TRUST *xp)
-{
- return xp->trust;
-}
-
-static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags)
-{
- /*
- * Declare the chain verified if the desired trust OID is not rejected in
- * any auxiliary trust info for this certificate, and the OID is either
- * expressly trusted, or else either "anyEKU" is trusted, or the
- * certificate is self-signed.
- */
- flags |= X509_TRUST_DO_SS_COMPAT | X509_TRUST_OK_ANY_EKU;
- return obj_trust(trust->arg1, x, flags);
-}
-
-static int trust_1oid(X509_TRUST *trust, X509 *x, int flags)
-{
- /*
- * Declare the chain verified only if the desired trust OID is not
- * rejected and is expressly trusted. Neither "anyEKU" nor "compat"
- * trust in self-signed certificates apply.
- */
- flags &= ~(X509_TRUST_DO_SS_COMPAT | X509_TRUST_OK_ANY_EKU);
- return obj_trust(trust->arg1, x, flags);
-}
-
-static int trust_compat(X509_TRUST *trust, X509 *x, int flags)
-{
- /* Call for side-effect of computing hash and caching extensions */
- if (X509_check_purpose(x, -1, 0) != 1)
- return X509_TRUST_UNTRUSTED;
- if ((flags & X509_TRUST_NO_SS_COMPAT) == 0 && (x->ex_flags & EXFLAG_SS))
- return X509_TRUST_TRUSTED;
- else
- return X509_TRUST_UNTRUSTED;
-}
-
-static int obj_trust(int id, X509 *x, int flags)
-{
- X509_CERT_AUX *ax = x->aux;
- int i;
-
- if (ax && ax->reject) {
- for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) {
- ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->reject, i);
- int nid = OBJ_obj2nid(obj);
-
- if (nid == id || (nid == NID_anyExtendedKeyUsage &&
- (flags & X509_TRUST_OK_ANY_EKU)))
- return X509_TRUST_REJECTED;
- }
- }
-
- if (ax && ax->trust) {
- for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) {
- ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->trust, i);
- int nid = OBJ_obj2nid(obj);
-
- if (nid == id || (nid == NID_anyExtendedKeyUsage &&
- (flags & X509_TRUST_OK_ANY_EKU)))
- return X509_TRUST_TRUSTED;
- }
- /*
- * Reject when explicit trust EKU are set and none match.
- *
- * Returning untrusted is enough for for full chains that end in
- * self-signed roots, because when explicit trust is specified it
- * suppresses the default blanket trust of self-signed objects.
- *
- * But for partial chains, this is not enough, because absent a similar
- * trust-self-signed policy, non matching EKUs are indistinguishable
- * from lack of EKU constraints.
- *
- * Therefore, failure to match any trusted purpose must trigger an
- * explicit reject.
- */
- return X509_TRUST_REJECTED;
- }
-
- if ((flags & X509_TRUST_DO_SS_COMPAT) == 0)
- return X509_TRUST_UNTRUSTED;
-
- /*
- * Not rejected, and there is no list of accepted uses, try compat.
- */
- return trust_compat(NULL, x, flags);
-}
diff --git a/crypto/x509/x509_trust.c b/crypto/x509/x509_trust.c
new file mode 100644
index 000000000000..fd77b0c6fe61
--- /dev/null
+++ b/crypto/x509/x509_trust.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/x509v3.h>
+#include "crypto/x509.h"
+
+static int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b);
+static void trtable_free(X509_TRUST *p);
+
+static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags);
+static int trust_1oid(X509_TRUST *trust, X509 *x, int flags);
+static int trust_compat(X509_TRUST *trust, X509 *x, int flags);
+
+static int obj_trust(int id, X509 *x, int flags);
+static int (*default_trust) (int id, X509 *x, int flags) = obj_trust;
+
+/*
+ * WARNING: the following table should be kept in order of trust and without
+ * any gaps so we can just subtract the minimum trust value to get an index
+ * into the table
+ */
+
+static X509_TRUST trstandard[] = {
+ {X509_TRUST_COMPAT, 0, trust_compat, "compatible", 0, NULL},
+ {X509_TRUST_SSL_CLIENT, 0, trust_1oidany, "SSL Client", NID_client_auth,
+ NULL},
+ {X509_TRUST_SSL_SERVER, 0, trust_1oidany, "SSL Server", NID_server_auth,
+ NULL},
+ {X509_TRUST_EMAIL, 0, trust_1oidany, "S/MIME email", NID_email_protect,
+ NULL},
+ {X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, "Object Signer", NID_code_sign,
+ NULL},
+ {X509_TRUST_OCSP_SIGN, 0, trust_1oid, "OCSP responder", NID_OCSP_sign,
+ NULL},
+ {X509_TRUST_OCSP_REQUEST, 0, trust_1oid, "OCSP request", NID_ad_OCSP,
+ NULL},
+ {X509_TRUST_TSA, 0, trust_1oidany, "TSA server", NID_time_stamp, NULL}
+};
+
+#define X509_TRUST_COUNT OSSL_NELEM(trstandard)
+
+static STACK_OF(X509_TRUST) *trtable = NULL;
+
+static int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b)
+{
+ return (*a)->trust - (*b)->trust;
+}
+
+int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *,
+ int) {
+ int (*oldtrust) (int, X509 *, int);
+ oldtrust = default_trust;
+ default_trust = trust;
+ return oldtrust;
+}
+
+int X509_check_trust(X509 *x, int id, int flags)
+{
+ X509_TRUST *pt;
+ int idx;
+
+ /* We get this as a default value */
+ if (id == X509_TRUST_DEFAULT)
+ return obj_trust(NID_anyExtendedKeyUsage, x,
+ flags | X509_TRUST_DO_SS_COMPAT);
+ idx = X509_TRUST_get_by_id(id);
+ if (idx < 0)
+ return default_trust(id, x, flags);
+ pt = X509_TRUST_get0(idx);
+ return pt->check_trust(pt, x, flags);
+}
+
+int X509_TRUST_get_count(void)
+{
+ if (!trtable)
+ return X509_TRUST_COUNT;
+ return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT;
+}
+
+X509_TRUST *X509_TRUST_get0(int idx)
+{
+ if (idx < 0)
+ return NULL;
+ if (idx < (int)X509_TRUST_COUNT)
+ return trstandard + idx;
+ return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT);
+}
+
+int X509_TRUST_get_by_id(int id)
+{
+ X509_TRUST tmp;
+ int idx;
+
+ if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX))
+ return id - X509_TRUST_MIN;
+ if (trtable == NULL)
+ return -1;
+ tmp.trust = id;
+ idx = sk_X509_TRUST_find(trtable, &tmp);
+ if (idx < 0)
+ return -1;
+ return idx + X509_TRUST_COUNT;
+}
+
+int X509_TRUST_set(int *t, int trust)
+{
+ if (X509_TRUST_get_by_id(trust) < 0) {
+ ERR_raise(ERR_LIB_X509, X509_R_INVALID_TRUST);
+ return 0;
+ }
+ *t = trust;
+ return 1;
+}
+
+int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int),
+ const char *name, int arg1, void *arg2)
+{
+ int idx;
+ X509_TRUST *trtmp;
+ /*
+ * This is set according to what we change: application can't set it
+ */
+ flags &= ~X509_TRUST_DYNAMIC;
+ /* This will always be set for application modified trust entries */
+ flags |= X509_TRUST_DYNAMIC_NAME;
+ /* Get existing entry if any */
+ idx = X509_TRUST_get_by_id(id);
+ /* Need a new entry */
+ if (idx < 0) {
+ if ((trtmp = OPENSSL_malloc(sizeof(*trtmp))) == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ trtmp->flags = X509_TRUST_DYNAMIC;
+ } else
+ trtmp = X509_TRUST_get0(idx);
+
+ /* OPENSSL_free existing name if dynamic */
+ if (trtmp->flags & X509_TRUST_DYNAMIC_NAME)
+ OPENSSL_free(trtmp->name);
+ /* dup supplied name */
+ if ((trtmp->name = OPENSSL_strdup(name)) == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ /* Keep the dynamic flag of existing entry */
+ trtmp->flags &= X509_TRUST_DYNAMIC;
+ /* Set all other flags */
+ trtmp->flags |= flags;
+
+ trtmp->trust = id;
+ trtmp->check_trust = ck;
+ trtmp->arg1 = arg1;
+ trtmp->arg2 = arg2;
+
+ /* If its a new entry manage the dynamic table */
+ if (idx < 0) {
+ if (trtable == NULL
+ && (trtable = sk_X509_TRUST_new(tr_cmp)) == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
+ goto err;;
+ }
+ if (!sk_X509_TRUST_push(trtable, trtmp)) {
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ return 1;
+ err:
+ if (idx < 0) {
+ OPENSSL_free(trtmp->name);
+ OPENSSL_free(trtmp);
+ }
+ return 0;
+}
+
+static void trtable_free(X509_TRUST *p)
+{
+ if (p == NULL)
+ return;
+ if (p->flags & X509_TRUST_DYNAMIC) {
+ if (p->flags & X509_TRUST_DYNAMIC_NAME)
+ OPENSSL_free(p->name);
+ OPENSSL_free(p);
+ }
+}
+
+void X509_TRUST_cleanup(void)
+{
+ sk_X509_TRUST_pop_free(trtable, trtable_free);
+ trtable = NULL;
+}
+
+int X509_TRUST_get_flags(const X509_TRUST *xp)
+{
+ return xp->flags;
+}
+
+char *X509_TRUST_get0_name(const X509_TRUST *xp)
+{
+ return xp->name;
+}
+
+int X509_TRUST_get_trust(const X509_TRUST *xp)
+{
+ return xp->trust;
+}
+
+static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags)
+{
+ /*
+ * Declare the chain verified if the desired trust OID is not rejected in
+ * any auxiliary trust info for this certificate, and the OID is either
+ * expressly trusted, or else either "anyEKU" is trusted, or the
+ * certificate is self-signed and X509_TRUST_NO_SS_COMPAT is not set.
+ */
+ flags |= X509_TRUST_DO_SS_COMPAT | X509_TRUST_OK_ANY_EKU;
+ return obj_trust(trust->arg1, x, flags);
+}
+
+static int trust_1oid(X509_TRUST *trust, X509 *x, int flags)
+{
+ /*
+ * Declare the chain verified only if the desired trust OID is not
+ * rejected and is expressly trusted. Neither "anyEKU" nor "compat"
+ * trust in self-signed certificates apply.
+ */
+ flags &= ~(X509_TRUST_DO_SS_COMPAT | X509_TRUST_OK_ANY_EKU);
+ return obj_trust(trust->arg1, x, flags);
+}
+
+static int trust_compat(X509_TRUST *trust, X509 *x, int flags)
+{
+ /* Call for side-effect of setting EXFLAG_SS for self-signed-certs */
+ if (X509_check_purpose(x, -1, 0) != 1)
+ return X509_TRUST_UNTRUSTED;
+ if ((flags & X509_TRUST_NO_SS_COMPAT) == 0 && (x->ex_flags & EXFLAG_SS))
+ return X509_TRUST_TRUSTED;
+ else
+ return X509_TRUST_UNTRUSTED;
+}
+
+static int obj_trust(int id, X509 *x, int flags)
+{
+ X509_CERT_AUX *ax = x->aux;
+ int i;
+
+ if (ax && ax->reject) {
+ for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) {
+ ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->reject, i);
+ int nid = OBJ_obj2nid(obj);
+
+ if (nid == id || (nid == NID_anyExtendedKeyUsage &&
+ (flags & X509_TRUST_OK_ANY_EKU)))
+ return X509_TRUST_REJECTED;
+ }
+ }
+
+ if (ax && ax->trust) {
+ for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) {
+ ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->trust, i);
+ int nid = OBJ_obj2nid(obj);
+
+ if (nid == id || (nid == NID_anyExtendedKeyUsage &&
+ (flags & X509_TRUST_OK_ANY_EKU)))
+ return X509_TRUST_TRUSTED;
+ }
+ /*
+ * Reject when explicit trust EKU are set and none match.
+ *
+ * Returning untrusted is enough for for full chains that end in
+ * self-signed roots, because when explicit trust is specified it
+ * suppresses the default blanket trust of self-signed objects.
+ *
+ * But for partial chains, this is not enough, because absent a similar
+ * trust-self-signed policy, non matching EKUs are indistinguishable
+ * from lack of EKU constraints.
+ *
+ * Therefore, failure to match any trusted purpose must trigger an
+ * explicit reject.
+ */
+ return X509_TRUST_REJECTED;
+ }
+
+ if ((flags & X509_TRUST_DO_SS_COMPAT) == 0)
+ return X509_TRUST_UNTRUSTED;
+
+ /*
+ * Not rejected, and there is no list of accepted uses, try compat.
+ */
+ return trust_compat(NULL, x, flags);
+}
diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c
index 02bde640d8e8..f25bb41acb52 100644
--- a/crypto/x509/x509_txt.c
+++ b/crypto/x509/x509_txt.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -58,9 +58,9 @@ const char *X509_verify_cert_error_string(long n)
case X509_V_ERR_OUT_OF_MEM:
return "out of memory";
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
- return "self signed certificate";
+ return "self-signed certificate";
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
- return "self signed certificate in certificate chain";
+ return "self-signed certificate in certificate chain";
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
return "unable to get local issuer certificate";
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
@@ -69,12 +69,12 @@ const char *X509_verify_cert_error_string(long n)
return "certificate chain too long";
case X509_V_ERR_CERT_REVOKED:
return "certificate revoked";
- case X509_V_ERR_INVALID_CA:
- return "invalid CA certificate";
+ case X509_V_ERR_NO_ISSUER_PUBLIC_KEY:
+ return "issuer certificate doesn't have a public key";
case X509_V_ERR_PATH_LENGTH_EXCEEDED:
return "path length constraint exceeded";
case X509_V_ERR_INVALID_PURPOSE:
- return "unsupported certificate purpose";
+ return "unsuitable certificate purpose";
case X509_V_ERR_CERT_UNTRUSTED:
return "certificate not trusted";
case X509_V_ERR_CERT_REJECTED:
@@ -111,9 +111,9 @@ const char *X509_verify_cert_error_string(long n)
case X509_V_ERR_NO_EXPLICIT_POLICY:
return "no explicit policy";
case X509_V_ERR_DIFFERENT_CRL_SCOPE:
- return "Different CRL scope";
+ return "different CRL scope";
case X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE:
- return "Unsupported extension feature";
+ return "unsupported extension feature";
case X509_V_ERR_UNNESTED_RESOURCE:
return "RFC 3779 resource not subset of parent's resources";
case X509_V_ERR_PERMITTED_VIOLATION:
@@ -133,7 +133,7 @@ const char *X509_verify_cert_error_string(long n)
case X509_V_ERR_CRL_PATH_VALIDATION_ERROR:
return "CRL path validation error";
case X509_V_ERR_PATH_LOOP:
- return "Path Loop";
+ return "path loop";
case X509_V_ERR_SUITE_B_INVALID_VERSION:
return "Suite B: certificate version invalid";
case X509_V_ERR_SUITE_B_INVALID_ALGORITHM:
@@ -147,13 +147,13 @@ const char *X509_verify_cert_error_string(long n)
case X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256:
return "Suite B: cannot sign P-384 with P-256";
case X509_V_ERR_HOSTNAME_MISMATCH:
- return "Hostname mismatch";
+ return "hostname mismatch";
case X509_V_ERR_EMAIL_MISMATCH:
- return "Email address mismatch";
+ return "email address mismatch";
case X509_V_ERR_IP_ADDRESS_MISMATCH:
return "IP address mismatch";
case X509_V_ERR_DANE_NO_MATCH:
- return "No matching DANE TLSA records";
+ return "no matching DANE TLSA records";
case X509_V_ERR_EE_KEY_TOO_SMALL:
return "EE certificate key too weak";
case X509_V_ERR_CA_KEY_TOO_SMALL:
@@ -161,9 +161,9 @@ const char *X509_verify_cert_error_string(long n)
case X509_V_ERR_CA_MD_TOO_WEAK:
return "CA signature digest algorithm too weak";
case X509_V_ERR_INVALID_CALL:
- return "Invalid certificate verification context";
+ return "invalid certificate verification context";
case X509_V_ERR_STORE_LOOKUP:
- return "Issuer certificate lookup error";
+ return "issuer certificate lookup error";
case X509_V_ERR_NO_VALID_SCTS:
return "Certificate Transparency required, but no valid SCTs found";
case X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION:
@@ -174,6 +174,42 @@ const char *X509_verify_cert_error_string(long n)
return "OCSP verification failed";
case X509_V_ERR_OCSP_CERT_UNKNOWN:
return "OCSP unknown cert";
+ case X509_V_ERR_UNSUPPORTED_SIGNATURE_ALGORITHM:
+ return "Cannot find certificate signature algorithm";
+ case X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH:
+ return "subject signature algorithm and issuer public key algorithm mismatch";
+ case X509_V_ERR_SIGNATURE_ALGORITHM_INCONSISTENCY:
+ return "cert info siganature and signature algorithm mismatch";
+ case X509_V_ERR_INVALID_CA:
+ return "invalid CA certificate";
+ case X509_V_ERR_PATHLEN_INVALID_FOR_NON_CA:
+ return "Path length invalid for non-CA cert";
+ case X509_V_ERR_PATHLEN_WITHOUT_KU_KEY_CERT_SIGN:
+ return "Path length given without key usage keyCertSign";
+ case X509_V_ERR_KU_KEY_CERT_SIGN_INVALID_FOR_NON_CA:
+ return "Key usage keyCertSign invalid for non-CA cert";
+ case X509_V_ERR_ISSUER_NAME_EMPTY:
+ return "Issuer name empty";
+ case X509_V_ERR_SUBJECT_NAME_EMPTY:
+ return "Subject name empty";
+ case X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER:
+ return "Missing Authority Key Identifier";
+ case X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER:
+ return "Missing Subject Key Identifier";
+ case X509_V_ERR_EMPTY_SUBJECT_ALT_NAME:
+ return "Empty Subject Alternative Name extension";
+ case X509_V_ERR_CA_BCONS_NOT_CRITICAL:
+ return "Basic Constraints of CA cert not marked critical";
+ case X509_V_ERR_EMPTY_SUBJECT_SAN_NOT_CRITICAL:
+ return "Subject empty and Subject Alt Name extension not critical";
+ case X509_V_ERR_AUTHORITY_KEY_IDENTIFIER_CRITICAL:
+ return "Authority Key Identifier marked critical";
+ case X509_V_ERR_SUBJECT_KEY_IDENTIFIER_CRITICAL:
+ return "Subject Key Identifier marked critical";
+ case X509_V_ERR_CA_CERT_MISSING_KEY_USAGE:
+ return "CA cert does not include key usage extension";
+ case X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3:
+ return "Using cert extension requires at least X509v3";
case X509_V_ERR_EC_KEY_EXPLICIT_PARAMS:
return "Certificate public key has explicit ECC parameters";
diff --git a/crypto/x509/x509_v3.c b/crypto/x509/x509_v3.c
index c7876023304c..62ae7d6b8d62 100644
--- a/crypto/x509/x509_v3.c
+++ b/crypto/x509/x509_v3.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -19,9 +19,12 @@
int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x)
{
+ int ret;
+
if (x == NULL)
return 0;
- return sk_X509_EXTENSION_num(x);
+ ret = sk_X509_EXTENSION_num(x);
+ return ret > 0 ? ret : 0;
}
int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, int nid,
@@ -101,7 +104,7 @@ STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x,
STACK_OF(X509_EXTENSION) *sk = NULL;
if (x == NULL) {
- X509err(X509_F_X509V3_ADD_EXT, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
goto err2;
}
@@ -125,7 +128,7 @@ STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x,
*x = sk;
return sk;
err:
- X509err(X509_F_X509V3_ADD_EXT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
err2:
X509_EXTENSION_free(new_ex);
if (x != NULL && *x == NULL)
@@ -142,7 +145,7 @@ X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid,
obj = OBJ_nid2obj(nid);
if (obj == NULL) {
- X509err(X509_F_X509_EXTENSION_CREATE_BY_NID, X509_R_UNKNOWN_NID);
+ ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_NID);
return NULL;
}
ret = X509_EXTENSION_create_by_OBJ(ex, obj, crit, data);
@@ -159,8 +162,7 @@ X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex,
if ((ex == NULL) || (*ex == NULL)) {
if ((ret = X509_EXTENSION_new()) == NULL) {
- X509err(X509_F_X509_EXTENSION_CREATE_BY_OBJ,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 925fbb541258..9384f1da9bad 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -1,12 +1,14 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <time.h>
#include <errno.h>
@@ -21,47 +23,23 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/objects.h>
+#include <openssl/core_names.h>
#include "internal/dane.h"
#include "crypto/x509.h"
#include "x509_local.h"
/* CRL score values */
-/* No unhandled critical extensions */
-
-#define CRL_SCORE_NOCRITICAL 0x100
-
-/* certificate is within CRL scope */
-
-#define CRL_SCORE_SCOPE 0x080
-
-/* CRL times valid */
-
-#define CRL_SCORE_TIME 0x040
-
-/* Issuer name matches certificate */
-
-#define CRL_SCORE_ISSUER_NAME 0x020
-
-/* If this score or above CRL is probably valid */
-
-#define CRL_SCORE_VALID (CRL_SCORE_NOCRITICAL|CRL_SCORE_TIME|CRL_SCORE_SCOPE)
-
-/* CRL issuer is certificate issuer */
-
-#define CRL_SCORE_ISSUER_CERT 0x018
-
-/* CRL issuer is on certificate path */
-
-#define CRL_SCORE_SAME_PATH 0x008
-
-/* CRL issuer matches CRL AKID */
-
-#define CRL_SCORE_AKID 0x004
-
-/* Have a delta CRL with valid times */
-
-#define CRL_SCORE_TIME_DELTA 0x002
+#define CRL_SCORE_NOCRITICAL 0x100 /* No unhandled critical extensions */
+#define CRL_SCORE_SCOPE 0x080 /* certificate is within CRL scope */
+#define CRL_SCORE_TIME 0x040 /* CRL times valid */
+#define CRL_SCORE_ISSUER_NAME 0x020 /* Issuer name matches certificate */
+#define CRL_SCORE_VALID /* If this score or above CRL is probably valid */ \
+ (CRL_SCORE_NOCRITICAL | CRL_SCORE_TIME | CRL_SCORE_SCOPE)
+#define CRL_SCORE_ISSUER_CERT 0x018 /* CRL issuer is certificate issuer */
+#define CRL_SCORE_SAME_PATH 0x008 /* CRL issuer is on certificate path */
+#define CRL_SCORE_AKID 0x004 /* CRL issuer matches CRL AKID */
+#define CRL_SCORE_TIME_DELTA 0x002 /* Have a delta CRL with valid times */
static int build_chain(X509_STORE_CTX *ctx);
static int verify_chain(X509_STORE_CTX *ctx);
@@ -69,7 +47,7 @@ static int dane_verify(X509_STORE_CTX *ctx);
static int null_callback(int ok, X509_STORE_CTX *e);
static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x);
-static int check_chain_extensions(X509_STORE_CTX *ctx);
+static int check_extensions(X509_STORE_CTX *ctx);
static int check_name_constraints(X509_STORE_CTX *ctx);
static int check_id(X509_STORE_CTX *ctx);
static int check_trust(X509_STORE_CTX *ctx, int num_untrusted);
@@ -105,64 +83,90 @@ static int null_callback(int ok, X509_STORE_CTX *e)
return ok;
}
-/*
- * Return 1 if given cert is considered self-signed, 0 if not or on error.
- * This does not verify self-signedness but relies on x509v3_cache_extensions()
- * matching issuer and subject names (i.e., the cert being self-issued) and any
- * present authority key identifier matching the subject key identifier, etc.
+/*-
+ * Return 1 if given cert is considered self-signed, 0 if not, or -1 on error.
+ * This actually verifies self-signedness only if requested.
+ * It calls ossl_x509v3_cache_extensions()
+ * to match issuer and subject names (i.e., the cert being self-issued) and any
+ * present authority key identifier to match the subject key identifier, etc.
*/
-static int cert_self_signed(X509 *x)
+int X509_self_signed(X509 *cert, int verify_signature)
{
- if (X509_check_purpose(x, -1, 0) != 1)
+ EVP_PKEY *pkey;
+
+ if ((pkey = X509_get0_pubkey(cert)) == NULL) { /* handles cert == NULL */
+ ERR_raise(ERR_LIB_X509, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
+ return -1;
+ }
+ if (!ossl_x509v3_cache_extensions(cert))
+ return -1;
+ if ((cert->ex_flags & EXFLAG_SS) == 0)
return 0;
- if (x->ex_flags & EXFLAG_SS)
+ if (!verify_signature)
return 1;
- else
- return 0;
+ return X509_verify(cert, pkey);
}
-/* Given a certificate try and find an exact match in the store */
-
-static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x)
+/*
+ * Given a certificate, try and find an exact match in the store.
+ * Returns 1 on success, 0 on not found, -1 on internal error.
+ */
+static int lookup_cert_match(X509 **result, X509_STORE_CTX *ctx, X509 *x)
{
STACK_OF(X509) *certs;
X509 *xtmp = NULL;
- int i;
+ int i, ret;
+
+ *result = NULL;
/* Lookup all certs with matching subject name */
+ ERR_set_mark();
certs = ctx->lookup_certs(ctx, X509_get_subject_name(x));
+ ERR_pop_to_mark();
if (certs == NULL)
- return NULL;
+ return -1;
/* Look for exact match */
for (i = 0; i < sk_X509_num(certs); i++) {
xtmp = sk_X509_value(certs, i);
- if (!X509_cmp(xtmp, x))
+ if (X509_cmp(xtmp, x) == 0)
break;
xtmp = NULL;
}
- if (xtmp != NULL && !X509_up_ref(xtmp))
- xtmp = NULL;
+ ret = xtmp != NULL;
+ if (ret) {
+ if (!X509_up_ref(xtmp))
+ ret = -1;
+ else
+ *result = xtmp;
+ }
sk_X509_pop_free(certs, X509_free);
- return xtmp;
+ return ret;
}
/*-
* Inform the verify callback of an error.
- * If B<x> is not NULL it is the error cert, otherwise use the chain cert at
- * B<depth>.
- * If B<err> is not X509_V_OK, that's the error value, otherwise leave
- * unchanged (presumably set by the caller).
+ * The error code is set to |err| if |err| is not X509_V_OK, else
+ * |ctx->error| is left unchanged (under the assumption it is set elsewhere).
+ * The error depth is |depth| if >= 0, else it defaults to |ctx->error_depth|.
+ * The error cert is |x| if not NULL, else defaults to the chain cert at depth.
*
* Returns 0 to abort verification with an error, non-zero to continue.
*/
static int verify_cb_cert(X509_STORE_CTX *ctx, X509 *x, int depth, int err)
{
- ctx->error_depth = depth;
+ if (depth < 0)
+ depth = ctx->error_depth;
+ else
+ ctx->error_depth = depth;
ctx->current_cert = (x != NULL) ? x : sk_X509_value(ctx->chain, depth);
if (err != X509_V_OK)
ctx->error = err;
return ctx->verify_cb(0, ctx);
}
+#define CB_FAIL_IF(cond, ctx, cert, depth, err) \
+ if ((cond) && verify_cb_cert(ctx, cert, depth, err) == 0) \
+ return 0
+
/*-
* Inform the verify callback of an error, CRL-specific variant. Here, the
* error depth and certificate are already set, we just specify the error
@@ -191,73 +195,79 @@ static int check_auth_level(X509_STORE_CTX *ctx)
* We've already checked the security of the leaf key, so here we only
* check the security of issuer keys.
*/
- if (i > 0 && !check_key_level(ctx, cert) &&
- verify_cb_cert(ctx, cert, i, X509_V_ERR_CA_KEY_TOO_SMALL) == 0)
- return 0;
+ CB_FAIL_IF(i > 0 && !check_key_level(ctx, cert),
+ ctx, cert, i, X509_V_ERR_CA_KEY_TOO_SMALL);
/*
* We also check the signature algorithm security of all certificates
* except those of the trust anchor at index num-1.
*/
- if (i < num - 1 && !check_sig_level(ctx, cert) &&
- verify_cb_cert(ctx, cert, i, X509_V_ERR_CA_MD_TOO_WEAK) == 0)
- return 0;
+ CB_FAIL_IF(i < num - 1 && !check_sig_level(ctx, cert),
+ ctx, cert, i, X509_V_ERR_CA_MD_TOO_WEAK);
}
return 1;
}
+/* Returns -1 on internal error */
static int verify_chain(X509_STORE_CTX *ctx)
{
int err;
int ok;
- /*
- * Before either returning with an error, or continuing with CRL checks,
- * instantiate chain public key parameters.
- */
- if ((ok = build_chain(ctx)) == 0 ||
- (ok = check_chain_extensions(ctx)) == 0 ||
- (ok = check_auth_level(ctx)) == 0 ||
- (ok = check_id(ctx)) == 0 || 1)
- X509_get_pubkey_parameters(NULL, ctx->chain);
- if (ok == 0 || (ok = ctx->check_revocation(ctx)) == 0)
+ if ((ok = build_chain(ctx)) <= 0
+ || (ok = check_extensions(ctx)) <= 0
+ || (ok = check_auth_level(ctx)) <= 0
+ || (ok = check_id(ctx)) <= 0
+ || (ok = X509_get_pubkey_parameters(NULL, ctx->chain) ? 1 : -1) <= 0
+ || (ok = ctx->check_revocation(ctx)) <= 0)
return ok;
err = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain,
ctx->param->flags);
- if (err != X509_V_OK) {
- if ((ok = verify_cb_cert(ctx, NULL, ctx->error_depth, err)) == 0)
- return ok;
- }
+ CB_FAIL_IF(err != X509_V_OK, ctx, NULL, ctx->error_depth, err);
/* Verify chain signatures and expiration times */
- ok = (ctx->verify != NULL) ? ctx->verify(ctx) : internal_verify(ctx);
- if (!ok)
+ ok = ctx->verify != NULL ? ctx->verify(ctx) : internal_verify(ctx);
+ if (ok <= 0)
return ok;
- if ((ok = check_name_constraints(ctx)) == 0)
+ if ((ok = check_name_constraints(ctx)) <= 0)
return ok;
#ifndef OPENSSL_NO_RFC3779
/* RFC 3779 path validation, now that CRL check has been done */
- if ((ok = X509v3_asid_validate_path(ctx)) == 0)
+ if ((ok = X509v3_asid_validate_path(ctx)) <= 0)
return ok;
- if ((ok = X509v3_addr_validate_path(ctx)) == 0)
+ if ((ok = X509v3_addr_validate_path(ctx)) <= 0)
return ok;
#endif
/* If we get this far evaluate policies */
- if (ctx->param->flags & X509_V_FLAG_POLICY_CHECK)
+ if ((ctx->param->flags & X509_V_FLAG_POLICY_CHECK) != 0)
ok = ctx->check_policy(ctx);
return ok;
}
+int X509_STORE_CTX_verify(X509_STORE_CTX *ctx)
+{
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+ if (ctx->cert == NULL && sk_X509_num(ctx->untrusted) >= 1)
+ ctx->cert = sk_X509_value(ctx->untrusted, 0);
+ return X509_verify_cert(ctx);
+}
+
int X509_verify_cert(X509_STORE_CTX *ctx)
{
- SSL_DANE *dane = ctx->dane;
int ret;
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
if (ctx->cert == NULL) {
- X509err(X509_F_X509_VERIFY_CERT, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
+ ERR_raise(ERR_LIB_X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
ctx->error = X509_V_ERR_INVALID_CALL;
return -1;
}
@@ -267,40 +277,22 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
* This X509_STORE_CTX has already been used to verify a cert. We
* cannot do another one.
*/
- X509err(X509_F_X509_VERIFY_CERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_X509, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
ctx->error = X509_V_ERR_INVALID_CALL;
return -1;
}
- if (!X509_up_ref(ctx->cert)) {
- X509err(X509_F_X509_VERIFY_CERT, ERR_R_INTERNAL_ERROR);
- ctx->error = X509_V_ERR_UNSPECIFIED;
- return -1;
- }
-
- /*
- * first we make sure the chain we are going to build is present and that
- * the first entry is in place
- */
- if ((ctx->chain = sk_X509_new_null()) == NULL
- || !sk_X509_push(ctx->chain, ctx->cert)) {
- X509_free(ctx->cert);
- X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
+ if (!ossl_x509_add_cert_new(&ctx->chain, ctx->cert, X509_ADD_FLAG_UP_REF)) {
ctx->error = X509_V_ERR_OUT_OF_MEM;
return -1;
}
-
ctx->num_untrusted = 1;
/* If the peer's public key is too weak, we can stop early. */
- if (!check_key_level(ctx, ctx->cert) &&
- !verify_cb_cert(ctx, ctx->cert, 0, X509_V_ERR_EE_KEY_TOO_SMALL))
- return 0;
+ CB_FAIL_IF(!check_key_level(ctx, ctx->cert),
+ ctx, ctx->cert, 0, X509_V_ERR_EE_KEY_TOO_SMALL);
- if (DANETLS_ENABLED(dane))
- ret = dane_verify(ctx);
- else
- ret = verify_chain(ctx);
+ ret = DANETLS_ENABLED(ctx->dane) ? dane_verify(ctx) : verify_chain(ctx);
/*
* Safety-net. If we are returning an error, we must also set ctx->error,
@@ -323,10 +315,10 @@ static int sk_X509_contains(STACK_OF(X509) *sk, X509 *cert)
}
/*
- * Find in given STACK_OF(X509) sk an issuer cert of given cert x.
- * The issuer must not yet be in ctx->chain, where the exceptional case
- * that x is self-issued and ctx->chain has just one element is allowed.
- * Prefer the first one that is not expired, else take the last expired one.
+ * Find in given STACK_OF(X509) |sk| an issuer cert (if any) of given cert |x|.
+ * The issuer must not yet be in |ctx->chain|, yet allowing the exception that
+ * |x| is self-issued and |ctx->chain| has just one element.
+ * Prefer the first non-expired one, else take the most recently expired one.
*/
static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x)
{
@@ -338,56 +330,60 @@ static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x)
if (ctx->check_issued(ctx, x, issuer)
&& (((x->ex_flags & EXFLAG_SI) != 0 && sk_X509_num(ctx->chain) == 1)
|| !sk_X509_contains(ctx->chain, issuer))) {
- rv = issuer;
- if (x509_check_cert_time(ctx, rv, -1))
- break;
+ if (ossl_x509_check_cert_time(ctx, issuer, -1))
+ return issuer;
+ if (rv == NULL || ASN1_TIME_compare(X509_get0_notAfter(issuer),
+ X509_get0_notAfter(rv)) > 0)
+ rv = issuer;
}
}
return rv;
}
/* Check that the given certificate 'x' is issued by the certificate 'issuer' */
-static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
+static int check_issued(ossl_unused X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
{
- return x509_likely_issued(issuer, x) == X509_V_OK;
+ int err = ossl_x509_likely_issued(issuer, x);
+
+ if (err == X509_V_OK)
+ return 1;
+ /*
+ * SUBJECT_ISSUER_MISMATCH just means 'x' is clearly not issued by 'issuer'.
+ * Every other error code likely indicates a real error.
+ */
+ return 0;
}
-/* Alternative lookup method: look from a STACK stored in other_ctx */
+/*-
+ * Alternative get_issuer method: look up from a STACK_OF(X509) in other_ctx.
+ * Returns -1 on internal error.
+ */
static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
{
*issuer = find_issuer(ctx, ctx->other_ctx, x);
-
- if (*issuer == NULL || !X509_up_ref(*issuer))
- goto err;
-
- return 1;
-
- err:
- *issuer = NULL;
+ if (*issuer != NULL)
+ return X509_up_ref(*issuer) ? 1 : -1;
return 0;
}
-static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx, X509_NAME *nm)
+/*-
+ * Alternative lookup method: look from a STACK stored in other_ctx.
+ * Returns NULL on internal error (such as out of memory).
+ */
+static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx,
+ const X509_NAME *nm)
{
- STACK_OF(X509) *sk = NULL;
+ STACK_OF(X509) *sk = sk_X509_new_null();
X509 *x;
int i;
+ if (sk == NULL)
+ return NULL;
for (i = 0; i < sk_X509_num(ctx->other_ctx); i++) {
x = sk_X509_value(ctx->other_ctx, i);
if (X509_NAME_cmp(nm, X509_get_subject_name(x)) == 0) {
- if (!X509_up_ref(x)) {
+ if (!X509_add_cert(sk, x, X509_ADD_FLAG_UP_REF)) {
sk_X509_pop_free(sk, X509_free);
- X509err(X509_F_LOOKUP_CERTS_SK, ERR_R_INTERNAL_ERROR);
- ctx->error = X509_V_ERR_UNSPECIFIED;
- return NULL;
- }
- if (sk == NULL)
- sk = sk_X509_new_null();
- if (sk == NULL || !sk_X509_push(sk, x)) {
- X509_free(x);
- sk_X509_pop_free(sk, X509_free);
- X509err(X509_F_LOOKUP_CERTS_SK, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return NULL;
}
@@ -399,6 +395,7 @@ static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx, X509_NAME *nm)
/*
* Check EE or CA certificate purpose. For trusted certificates explicit local
* auxiliary trust can be used to override EKU-restrictions.
+ * Sadly, returns 0 also on internal error.
*/
static int check_purpose(X509_STORE_CTX *ctx, X509 *x, int purpose, int depth,
int must_be_ca)
@@ -448,18 +445,15 @@ static int check_purpose(X509_STORE_CTX *ctx, X509 *x, int purpose, int depth,
}
/*
- * Check a certificate chains extensions for consistency with the supplied
- * purpose
+ * Check extensions of a cert chain for consistency with the supplied purpose.
+ * Sadly, returns 0 also on internal error.
*/
-
-static int check_chain_extensions(X509_STORE_CTX *ctx)
+static int check_extensions(X509_STORE_CTX *ctx)
{
int i, must_be_ca, plen = 0;
X509 *x;
- int proxy_path_length = 0;
- int purpose;
- int allow_proxy_certs;
- int num = sk_X509_num(ctx->chain);
+ int ret, proxy_path_length = 0;
+ int purpose, allow_proxy_certs, num = sk_X509_num(ctx->chain);
/*-
* must_be_ca can have 1 of 3 values:
@@ -473,87 +467,127 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
must_be_ca = -1;
/* CRL path validation */
- if (ctx->parent) {
+ if (ctx->parent != NULL) {
allow_proxy_certs = 0;
purpose = X509_PURPOSE_CRL_SIGN;
} else {
allow_proxy_certs =
- ! !(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS);
+ (ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS) != 0;
purpose = ctx->param->purpose;
}
for (i = 0; i < num; i++) {
- int ret;
x = sk_X509_value(ctx->chain, i);
- if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
- && (x->ex_flags & EXFLAG_CRITICAL)) {
- if (!verify_cb_cert(ctx, x, i,
- X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION))
- return 0;
- }
- if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY)) {
- if (!verify_cb_cert(ctx, x, i,
- X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED))
- return 0;
- }
+ CB_FAIL_IF((ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) == 0
+ && (x->ex_flags & EXFLAG_CRITICAL) != 0,
+ ctx, x, i, X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION);
+ CB_FAIL_IF(!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY) != 0,
+ ctx, x, i, X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED);
ret = X509_check_ca(x);
switch (must_be_ca) {
case -1:
- if ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
- && (ret != 1) && (ret != 0)) {
- ret = 0;
- ctx->error = X509_V_ERR_INVALID_CA;
- } else
- ret = 1;
+ CB_FAIL_IF((ctx->param->flags & X509_V_FLAG_X509_STRICT) != 0
+ && ret != 1 && ret != 0,
+ ctx, x, i, X509_V_ERR_INVALID_CA);
break;
case 0:
- if (ret != 0) {
- ret = 0;
- ctx->error = X509_V_ERR_INVALID_NON_CA;
- } else
- ret = 1;
+ CB_FAIL_IF(ret != 0, ctx, x, i, X509_V_ERR_INVALID_NON_CA);
break;
default:
/* X509_V_FLAG_X509_STRICT is implicit for intermediate CAs */
- if ((ret == 0)
- || ((i + 1 < num || ctx->param->flags & X509_V_FLAG_X509_STRICT)
- && (ret != 1))) {
- ret = 0;
- ctx->error = X509_V_ERR_INVALID_CA;
- } else
- ret = 1;
+ CB_FAIL_IF(ret == 0
+ || ((i + 1 < num
+ || (ctx->param->flags & X509_V_FLAG_X509_STRICT) != 0)
+ && ret != 1), ctx, x, i, X509_V_ERR_INVALID_CA);
break;
}
- if (ret > 0
- && (ctx->param->flags & X509_V_FLAG_X509_STRICT) && num > 1) {
+ if (num > 1) {
/* Check for presence of explicit elliptic curve parameters */
ret = check_curve(x);
- if (ret < 0) {
- ctx->error = X509_V_ERR_UNSPECIFIED;
- ret = 0;
- } else if (ret == 0) {
- ctx->error = X509_V_ERR_EC_KEY_EXPLICIT_PARAMS;
- }
+ CB_FAIL_IF(ret < 0, ctx, x, i, X509_V_ERR_UNSPECIFIED);
+ CB_FAIL_IF(ret == 0, ctx, x, i, X509_V_ERR_EC_KEY_EXPLICIT_PARAMS);
}
- if (ret > 0
- && (x->ex_flags & EXFLAG_CA) == 0
- && x->ex_pathlen != -1
- && (ctx->param->flags & X509_V_FLAG_X509_STRICT)) {
- ctx->error = X509_V_ERR_INVALID_EXTENSION;
- ret = 0;
+ /*
+ * Do the following set of checks only if strict checking is requested
+ * and not for self-issued (including self-signed) EE (non-CA) certs
+ * because RFC 5280 does not apply to them according RFC 6818 section 2.
+ */
+ if ((ctx->param->flags & X509_V_FLAG_X509_STRICT) != 0
+ && num > 1) { /*
+ * this should imply
+ * !(i == 0 && (x->ex_flags & EXFLAG_CA) == 0
+ * && (x->ex_flags & EXFLAG_SI) != 0)
+ */
+ /* Check Basic Constraints according to RFC 5280 section 4.2.1.9 */
+ if (x->ex_pathlen != -1) {
+ CB_FAIL_IF((x->ex_flags & EXFLAG_CA) == 0,
+ ctx, x, i, X509_V_ERR_PATHLEN_INVALID_FOR_NON_CA);
+ CB_FAIL_IF((x->ex_kusage & KU_KEY_CERT_SIGN) == 0, ctx,
+ x, i, X509_V_ERR_PATHLEN_WITHOUT_KU_KEY_CERT_SIGN);
+ }
+ CB_FAIL_IF((x->ex_flags & EXFLAG_CA) != 0
+ && (x->ex_flags & EXFLAG_BCONS) != 0
+ && (x->ex_flags & EXFLAG_BCONS_CRITICAL) == 0,
+ ctx, x, i, X509_V_ERR_CA_BCONS_NOT_CRITICAL);
+ /* Check Key Usage according to RFC 5280 section 4.2.1.3 */
+ if ((x->ex_flags & EXFLAG_CA) != 0) {
+ CB_FAIL_IF((x->ex_flags & EXFLAG_KUSAGE) == 0,
+ ctx, x, i, X509_V_ERR_CA_CERT_MISSING_KEY_USAGE);
+ } else {
+ CB_FAIL_IF((x->ex_kusage & KU_KEY_CERT_SIGN) != 0, ctx, x, i,
+ X509_V_ERR_KU_KEY_CERT_SIGN_INVALID_FOR_NON_CA);
+ }
+ /* Check issuer is non-empty acc. to RFC 5280 section 4.1.2.4 */
+ CB_FAIL_IF(X509_NAME_entry_count(X509_get_issuer_name(x)) == 0,
+ ctx, x, i, X509_V_ERR_ISSUER_NAME_EMPTY);
+ /* Check subject is non-empty acc. to RFC 5280 section 4.1.2.6 */
+ CB_FAIL_IF(((x->ex_flags & EXFLAG_CA) != 0
+ || (x->ex_kusage & KU_CRL_SIGN) != 0
+ || x->altname == NULL)
+ && X509_NAME_entry_count(X509_get_subject_name(x)) == 0,
+ ctx, x, i, X509_V_ERR_SUBJECT_NAME_EMPTY);
+ CB_FAIL_IF(X509_NAME_entry_count(X509_get_subject_name(x)) == 0
+ && x->altname != NULL
+ && (x->ex_flags & EXFLAG_SAN_CRITICAL) == 0,
+ ctx, x, i, X509_V_ERR_EMPTY_SUBJECT_SAN_NOT_CRITICAL);
+ /* Check SAN is non-empty according to RFC 5280 section 4.2.1.6 */
+ CB_FAIL_IF(x->altname != NULL
+ && sk_GENERAL_NAME_num(x->altname) <= 0,
+ ctx, x, i, X509_V_ERR_EMPTY_SUBJECT_ALT_NAME);
+ /* Check sig alg consistency acc. to RFC 5280 section 4.1.1.2 */
+ CB_FAIL_IF(X509_ALGOR_cmp(&x->sig_alg, &x->cert_info.signature) != 0,
+ ctx, x, i, X509_V_ERR_SIGNATURE_ALGORITHM_INCONSISTENCY);
+ CB_FAIL_IF(x->akid != NULL
+ && (x->ex_flags & EXFLAG_AKID_CRITICAL) != 0,
+ ctx, x, i, X509_V_ERR_AUTHORITY_KEY_IDENTIFIER_CRITICAL);
+ CB_FAIL_IF(x->skid != NULL
+ && (x->ex_flags & EXFLAG_SKID_CRITICAL) != 0,
+ ctx, x, i, X509_V_ERR_SUBJECT_KEY_IDENTIFIER_CRITICAL);
+ if (X509_get_version(x) >= X509_VERSION_3) {
+ /* Check AKID presence acc. to RFC 5280 section 4.2.1.1 */
+ CB_FAIL_IF(i + 1 < num /*
+ * this means not last cert in chain,
+ * taken as "generated by conforming CAs"
+ */
+ && (x->akid == NULL || x->akid->keyid == NULL), ctx,
+ x, i, X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER);
+ /* Check SKID presence acc. to RFC 5280 section 4.2.1.2 */
+ CB_FAIL_IF((x->ex_flags & EXFLAG_CA) != 0 && x->skid == NULL,
+ ctx, x, i, X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER);
+ } else {
+ CB_FAIL_IF(sk_X509_EXTENSION_num(X509_get0_extensions(x)) > 0,
+ ctx, x, i, X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3);
+ }
}
- if (ret == 0 && !verify_cb_cert(ctx, x, i, X509_V_OK))
- return 0;
+
/* check_purpose() makes the callback as needed */
if (purpose > 0 && !check_purpose(ctx, x, purpose, i, must_be_ca))
return 0;
- /* Check pathlen */
- if ((i > 1) && (x->ex_pathlen != -1)
- && (plen > (x->ex_pathlen + proxy_path_length))) {
- if (!verify_cb_cert(ctx, x, i, X509_V_ERR_PATH_LENGTH_EXCEEDED))
- return 0;
- }
- /* Increment path length if not a self issued intermediate CA */
+ /* Check path length */
+ CB_FAIL_IF(i > 1 && x->ex_pathlen != -1
+ && plen > x->ex_pathlen + proxy_path_length,
+ ctx, x, i, X509_V_ERR_PATH_LENGTH_EXCEEDED);
+ /* Increment path length if not a self-issued intermediate CA */
if (i > 0 && (x->ex_flags & EXFLAG_SI) == 0)
plen++;
/*
@@ -574,17 +608,15 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
* increment proxy_path_length.
*/
if (x->ex_pcpathlen != -1) {
- if (proxy_path_length > x->ex_pcpathlen) {
- if (!verify_cb_cert(ctx, x, i,
- X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED))
- return 0;
- }
+ CB_FAIL_IF(proxy_path_length > x->ex_pcpathlen,
+ ctx, x, i, X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED);
proxy_path_length = x->ex_pcpathlen;
}
proxy_path_length++;
must_be_ca = 0;
- } else
+ } else {
must_be_ca = 1;
+ }
}
return 1;
}
@@ -610,6 +642,7 @@ static int has_san_id(X509 *x, int gtype)
return ret;
}
+/* Returns -1 on internal error */
static int check_name_constraints(X509_STORE_CTX *ctx)
{
int i;
@@ -619,8 +652,8 @@ static int check_name_constraints(X509_STORE_CTX *ctx)
X509 *x = sk_X509_value(ctx->chain, i);
int j;
- /* Ignore self issued certs unless last in chain */
- if (i && (x->ex_flags & EXFLAG_SI))
+ /* Ignore self-issued certs unless last in chain */
+ if (i != 0 && (x->ex_flags & EXFLAG_SI) != 0)
continue;
/*
@@ -629,16 +662,16 @@ static int check_name_constraints(X509_STORE_CTX *ctx)
* added.
* (RFC 3820: 3.4, 4.1.3 (a)(4))
*/
- if (x->ex_flags & EXFLAG_PROXY) {
+ if ((x->ex_flags & EXFLAG_PROXY) != 0) {
X509_NAME *tmpsubject = X509_get_subject_name(x);
X509_NAME *tmpissuer = X509_get_issuer_name(x);
X509_NAME_ENTRY *tmpentry = NULL;
- int last_object_nid = 0;
+ int last_nid = 0;
int err = X509_V_OK;
- int last_object_loc = X509_NAME_entry_count(tmpsubject) - 1;
+ int last_loc = X509_NAME_entry_count(tmpsubject) - 1;
/* Check that there are at least two RDNs */
- if (last_object_loc < 1) {
+ if (last_loc < 1) {
err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
goto proxy_name_done;
}
@@ -655,12 +688,11 @@ static int check_name_constraints(X509_STORE_CTX *ctx)
/*
* Check that the last subject component isn't part of a
- * multivalued RDN
+ * multi-valued RDN
*/
- if (X509_NAME_ENTRY_set(X509_NAME_get_entry(tmpsubject,
- last_object_loc))
+ if (X509_NAME_ENTRY_set(X509_NAME_get_entry(tmpsubject, last_loc))
== X509_NAME_ENTRY_set(X509_NAME_get_entry(tmpsubject,
- last_object_loc - 1))) {
+ last_loc - 1))) {
err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
goto proxy_name_done;
}
@@ -671,17 +703,15 @@ static int check_name_constraints(X509_STORE_CTX *ctx)
*/
tmpsubject = X509_NAME_dup(tmpsubject);
if (tmpsubject == NULL) {
- X509err(X509_F_CHECK_NAME_CONSTRAINTS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
- return 0;
+ return -1;
}
- tmpentry =
- X509_NAME_delete_entry(tmpsubject, last_object_loc);
- last_object_nid =
- OBJ_obj2nid(X509_NAME_ENTRY_get_object(tmpentry));
+ tmpentry = X509_NAME_delete_entry(tmpsubject, last_loc);
+ last_nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(tmpentry));
- if (last_object_nid != NID_commonName
+ if (last_nid != NID_commonName
|| X509_NAME_cmp(tmpsubject, tmpissuer) != 0) {
err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
}
@@ -689,10 +719,8 @@ static int check_name_constraints(X509_STORE_CTX *ctx)
X509_NAME_ENTRY_free(tmpentry);
X509_NAME_free(tmpsubject);
- proxy_name_done:
- if (err != X509_V_OK
- && !verify_cb_cert(ctx, x, i, err))
- return 0;
+ proxy_name_done:
+ CB_FAIL_IF(err != X509_V_OK, ctx, x, i, err);
}
/*
@@ -706,6 +734,7 @@ static int check_name_constraints(X509_STORE_CTX *ctx)
if (nc) {
int rv = NAME_CONSTRAINTS_check(x, nc);
+ int ret = 1;
/* If EE certificate check commonName too */
if (rv == X509_V_OK && i == 0
@@ -713,17 +742,18 @@ static int check_name_constraints(X509_STORE_CTX *ctx)
& X509_CHECK_FLAG_NEVER_CHECK_SUBJECT) == 0
&& ((ctx->param->hostflags
& X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT) != 0
- || !has_san_id(x, GEN_DNS)))
+ || (ret = has_san_id(x, GEN_DNS)) == 0))
rv = NAME_CONSTRAINTS_check_CN(x, nc);
+ if (ret < 0)
+ return ret;
switch (rv) {
case X509_V_OK:
break;
case X509_V_ERR_OUT_OF_MEM:
- return 0;
+ return -1;
default:
- if (!verify_cb_cert(ctx, x, i, rv))
- return 0;
+ CB_FAIL_IF(1, ctx, x, i, rv);
break;
}
}
@@ -759,24 +789,27 @@ static int check_id(X509_STORE_CTX *ctx)
{
X509_VERIFY_PARAM *vpm = ctx->param;
X509 *x = ctx->cert;
- if (vpm->hosts && check_hosts(x, vpm) <= 0) {
+
+ if (vpm->hosts != NULL && check_hosts(x, vpm) <= 0) {
if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH))
return 0;
}
- if (vpm->email && X509_check_email(x, vpm->email, vpm->emaillen, 0) <= 0) {
+ if (vpm->email != NULL
+ && X509_check_email(x, vpm->email, vpm->emaillen, 0) <= 0) {
if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH))
return 0;
}
- if (vpm->ip && X509_check_ip(x, vpm->ip, vpm->iplen, 0) <= 0) {
+ if (vpm->ip != NULL && X509_check_ip(x, vpm->ip, vpm->iplen, 0) <= 0) {
if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH))
return 0;
}
return 1;
}
+/* Returns -1 on internal error */
static int check_trust(X509_STORE_CTX *ctx, int num_untrusted)
{
- int i;
+ int i, res;
X509 *x = NULL;
X509 *mx;
SSL_DANE *dane = ctx->dane;
@@ -788,11 +821,9 @@ static int check_trust(X509_STORE_CTX *ctx, int num_untrusted)
* match, we're done, otherwise we'll merely record the match depth.
*/
if (DANETLS_HAS_TA(dane) && num_untrusted > 0 && num_untrusted < num) {
- switch (trust = check_dane_issuer(ctx, num_untrusted)) {
- case X509_TRUST_TRUSTED:
- case X509_TRUST_REJECTED:
+ trust = check_dane_issuer(ctx, num_untrusted);
+ if (trust != X509_TRUST_UNTRUSTED)
return trust;
- }
}
/*
@@ -804,7 +835,7 @@ static int check_trust(X509_STORE_CTX *ctx, int num_untrusted)
for (i = num_untrusted; i < num; i++) {
x = sk_X509_value(ctx->chain, i);
trust = X509_check_trust(x, ctx->param->trust, 0);
- /* If explicitly trusted return trusted */
+ /* If explicitly trusted (so not neutral nor rejected) return trusted */
if (trust == X509_TRUST_TRUSTED)
goto trusted;
if (trust == X509_TRUST_REJECTED)
@@ -816,20 +847,23 @@ static int check_trust(X509_STORE_CTX *ctx, int num_untrusted)
* the chain is PKIX trusted.
*/
if (num_untrusted < num) {
- if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN)
+ if ((ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) != 0)
goto trusted;
return X509_TRUST_UNTRUSTED;
}
- if (num_untrusted == num && ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) {
+ if (num_untrusted == num
+ && (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) != 0) {
/*
* Last-resort call with no new trusted certificates, check the leaf
* for a direct trust store match.
*/
i = 0;
x = sk_X509_value(ctx->chain, i);
- mx = lookup_cert_match(ctx, x);
- if (!mx)
+ res = lookup_cert_match(&mx, ctx, x);
+ if (res < 0)
+ return res;
+ if (mx == NULL)
return X509_TRUST_UNTRUSTED;
/*
@@ -843,7 +877,7 @@ static int check_trust(X509_STORE_CTX *ctx, int num_untrusted)
}
/* Replace leaf with trusted match */
- (void) sk_X509_set(ctx->chain, 0, mx);
+ (void)sk_X509_set(ctx->chain, 0, mx);
X509_free(x);
ctx->num_untrusted = 0;
goto trusted;
@@ -856,9 +890,8 @@ static int check_trust(X509_STORE_CTX *ctx, int num_untrusted)
return X509_TRUST_UNTRUSTED;
rejected:
- if (!verify_cb_cert(ctx, x, i, X509_V_ERR_CERT_REJECTED))
- return X509_TRUST_REJECTED;
- return X509_TRUST_UNTRUSTED;
+ return verify_cb_cert(ctx, x, i, X509_V_ERR_CERT_REJECTED) == 0
+ ? X509_TRUST_REJECTED : X509_TRUST_UNTRUSTED;
trusted:
if (!DANETLS_ENABLED(dane))
@@ -871,14 +904,16 @@ static int check_trust(X509_STORE_CTX *ctx, int num_untrusted)
return X509_TRUST_UNTRUSTED;
}
+/* Sadly, returns 0 also on internal error. */
static int check_revocation(X509_STORE_CTX *ctx)
{
int i = 0, last = 0, ok = 0;
- if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK))
+
+ if ((ctx->param->flags & X509_V_FLAG_CRL_CHECK) == 0)
return 1;
- if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL)
+ if ((ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL) != 0) {
last = sk_X509_num(ctx->chain) - 1;
- else {
+ } else {
/* If checking CRL paths this isn't the EE certificate */
if (ctx->parent)
return 1;
@@ -893,6 +928,7 @@ static int check_revocation(X509_STORE_CTX *ctx)
return 1;
}
+/* Sadly, returns 0 also on internal error. */
static int check_cert(X509_STORE_CTX *ctx)
{
X509_CRL *crl = NULL, *dcrl = NULL;
@@ -905,20 +941,18 @@ static int check_cert(X509_STORE_CTX *ctx)
ctx->current_crl_score = 0;
ctx->current_reasons = 0;
- if (x->ex_flags & EXFLAG_PROXY)
+ if ((x->ex_flags & EXFLAG_PROXY) != 0)
return 1;
while (ctx->current_reasons != CRLDP_ALL_REASONS) {
unsigned int last_reasons = ctx->current_reasons;
/* Try to retrieve relevant CRL */
- if (ctx->get_crl)
+ if (ctx->get_crl != NULL)
ok = ctx->get_crl(ctx, &crl, x);
else
ok = get_crl_delta(ctx, &crl, &dcrl, x);
- /*
- * If error looking up CRL, nothing we can do except notify callback
- */
+ /* If error looking up CRL, nothing we can do except notify callback */
if (!ok) {
ok = verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_GET_CRL);
goto done;
@@ -928,15 +962,16 @@ static int check_cert(X509_STORE_CTX *ctx)
if (!ok)
goto done;
- if (dcrl) {
+ if (dcrl != NULL) {
ok = ctx->check_crl(ctx, dcrl);
if (!ok)
goto done;
ok = ctx->cert_crl(ctx, dcrl, x);
if (!ok)
goto done;
- } else
+ } else {
ok = 1;
+ }
/* Don't look in full CRL if delta reason is removefromCRL */
if (ok != 2) {
@@ -967,15 +1002,14 @@ static int check_cert(X509_STORE_CTX *ctx)
}
/* Check CRL times against values in X509_STORE_CTX */
-
static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify)
{
time_t *ptime;
int i;
- if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
+ if ((ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) != 0)
ptime = &ctx->param->check_time;
- else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME)
+ else if ((ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) != 0)
return 1;
else
ptime = NULL;
@@ -1006,11 +1040,9 @@ static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify)
if (!verify_cb_crl(ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD))
return 0;
}
- /* Ignore expiry of base CRL is delta is valid */
- if ((i < 0) && !(ctx->current_crl_score & CRL_SCORE_TIME_DELTA)) {
- if (!notify)
- return 0;
- if (!verify_cb_crl(ctx, X509_V_ERR_CRL_HAS_EXPIRED))
+ /* Ignore expiration of base CRL is delta is valid */
+ if (i < 0 && (ctx->current_crl_score & CRL_SCORE_TIME_DELTA) == 0) {
+ if (!notify || !verify_cb_crl(ctx, X509_V_ERR_CRL_HAS_EXPIRED))
return 0;
}
}
@@ -1040,6 +1072,7 @@ static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl,
/* If current CRL is equivalent use it if it is newer */
if (crl_score == best_score && best_crl != NULL) {
int day, sec;
+
if (ASN1_TIME_diff(&day, &sec, X509_CRL_get0_lastUpdate(best_crl),
X509_CRL_get0_lastUpdate(crl)) == 0)
continue;
@@ -1056,7 +1089,7 @@ static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl,
best_reasons = reasons;
}
- if (best_crl) {
+ if (best_crl != NULL) {
X509_CRL_free(*pcrl);
*pcrl = best_crl;
*pissuer = best_crl_issuer;
@@ -1078,54 +1111,46 @@ static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl,
* Compare two CRL extensions for delta checking purposes. They should be
* both present or both absent. If both present all fields must be identical.
*/
-
static int crl_extension_match(X509_CRL *a, X509_CRL *b, int nid)
{
- ASN1_OCTET_STRING *exta, *extb;
- int i;
- i = X509_CRL_get_ext_by_NID(a, nid, -1);
+ ASN1_OCTET_STRING *exta = NULL, *extb = NULL;
+ int i = X509_CRL_get_ext_by_NID(a, nid, -1);
+
if (i >= 0) {
/* Can't have multiple occurrences */
if (X509_CRL_get_ext_by_NID(a, nid, i) != -1)
return 0;
exta = X509_EXTENSION_get_data(X509_CRL_get_ext(a, i));
- } else
- exta = NULL;
+ }
i = X509_CRL_get_ext_by_NID(b, nid, -1);
-
if (i >= 0) {
-
if (X509_CRL_get_ext_by_NID(b, nid, i) != -1)
return 0;
extb = X509_EXTENSION_get_data(X509_CRL_get_ext(b, i));
- } else
- extb = NULL;
+ }
- if (!exta && !extb)
+ if (exta == NULL && extb == NULL)
return 1;
- if (!exta || !extb)
+ if (exta == NULL || extb == NULL)
return 0;
- if (ASN1_OCTET_STRING_cmp(exta, extb))
- return 0;
-
- return 1;
+ return ASN1_OCTET_STRING_cmp(exta, extb) == 0;
}
/* See if a base and delta are compatible */
-
static int check_delta_base(X509_CRL *delta, X509_CRL *base)
{
/* Delta CRL must be a delta */
- if (!delta->base_crl_number)
+ if (delta->base_crl_number == NULL)
return 0;
/* Base must have a CRL number */
- if (!base->crl_number)
+ if (base->crl_number == NULL)
return 0;
/* Issuer names must match */
- if (X509_NAME_cmp(X509_CRL_get_issuer(base), X509_CRL_get_issuer(delta)))
+ if (X509_NAME_cmp(X509_CRL_get_issuer(base),
+ X509_CRL_get_issuer(delta)) != 0)
return 0;
/* AKID and IDP must match */
if (!crl_extension_match(delta, base, NID_authority_key_identifier))
@@ -1136,24 +1161,22 @@ static int check_delta_base(X509_CRL *delta, X509_CRL *base)
if (ASN1_INTEGER_cmp(delta->base_crl_number, base->crl_number) > 0)
return 0;
/* Delta CRL number must exceed full CRL number */
- if (ASN1_INTEGER_cmp(delta->crl_number, base->crl_number) > 0)
- return 1;
- return 0;
+ return ASN1_INTEGER_cmp(delta->crl_number, base->crl_number) > 0;
}
/*
* For a given base CRL find a delta... maybe extend to delta scoring or
* retrieve a chain of deltas...
*/
-
static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pscore,
X509_CRL *base, STACK_OF(X509_CRL) *crls)
{
X509_CRL *delta;
int i;
- if (!(ctx->param->flags & X509_V_FLAG_USE_DELTAS))
+
+ if ((ctx->param->flags & X509_V_FLAG_USE_DELTAS) == 0)
return;
- if (!((ctx->current_cert->ex_flags | base->flags) & EXFLAG_FRESHEST))
+ if (((ctx->current_cert->ex_flags | base->flags) & EXFLAG_FRESHEST) == 0)
return;
for (i = 0; i < sk_X509_CRL_num(crls); i++) {
delta = sk_X509_CRL_value(crls, i);
@@ -1175,42 +1198,41 @@ static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pscore,
* also used to determine if the CRL is suitable: if no new reasons the CRL
* is rejected, otherwise reasons is updated.
*/
-
static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
unsigned int *preasons, X509_CRL *crl, X509 *x)
{
-
int crl_score = 0;
unsigned int tmp_reasons = *preasons, crl_reasons;
/* First see if we can reject CRL straight away */
/* Invalid IDP cannot be processed */
- if (crl->idp_flags & IDP_INVALID)
+ if ((crl->idp_flags & IDP_INVALID) != 0)
return 0;
/* Reason codes or indirect CRLs need extended CRL support */
- if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) {
+ if ((ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT) == 0) {
if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS))
return 0;
- } else if (crl->idp_flags & IDP_REASONS) {
+ } else if ((crl->idp_flags & IDP_REASONS) != 0) {
/* If no new reasons reject */
- if (!(crl->idp_reasons & ~tmp_reasons))
+ if ((crl->idp_reasons & ~tmp_reasons) == 0)
return 0;
}
/* Don't process deltas at this stage */
- else if (crl->base_crl_number)
+ else if (crl->base_crl_number != NULL)
return 0;
/* If issuer name doesn't match certificate need indirect CRL */
- if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl))) {
- if (!(crl->idp_flags & IDP_INDIRECT))
+ if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl)) != 0) {
+ if ((crl->idp_flags & IDP_INDIRECT) == 0)
return 0;
- } else
+ } else {
crl_score |= CRL_SCORE_ISSUER_NAME;
+ }
- if (!(crl->flags & EXFLAG_CRITICAL))
+ if ((crl->flags & EXFLAG_CRITICAL) == 0)
crl_score |= CRL_SCORE_NOCRITICAL;
- /* Check expiry */
+ /* Check expiration */
if (check_crl_time(ctx, crl, 0))
crl_score |= CRL_SCORE_TIME;
@@ -1218,15 +1240,13 @@ static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
crl_akid_check(ctx, crl, pissuer, &crl_score);
/* If we can't locate certificate issuer at this point forget it */
-
- if (!(crl_score & CRL_SCORE_AKID))
+ if ((crl_score & CRL_SCORE_AKID) == 0)
return 0;
/* Check cert for matching CRL distribution points */
-
if (crl_crldp_check(x, crl, crl_score, &crl_reasons)) {
/* If no new reasons reject */
- if (!(crl_reasons & ~tmp_reasons))
+ if ((crl_reasons & ~tmp_reasons) == 0)
return 0;
tmp_reasons |= crl_reasons;
crl_score |= CRL_SCORE_SCOPE;
@@ -1242,7 +1262,7 @@ static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl,
X509 **pissuer, int *pcrl_score)
{
X509 *crl_issuer = NULL;
- X509_NAME *cnm = X509_CRL_get_issuer(crl);
+ const X509_NAME *cnm = X509_CRL_get_issuer(crl);
int cidx = ctx->error_depth;
int i;
@@ -1271,8 +1291,7 @@ static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl,
}
/* Anything else needs extended CRL support */
-
- if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT))
+ if ((ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT) == 0)
return;
/*
@@ -1281,7 +1300,7 @@ static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl,
*/
for (i = 0; i < sk_X509_num(ctx->untrusted); i++) {
crl_issuer = sk_X509_value(ctx->untrusted, i);
- if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
+ if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm) != 0)
continue;
if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) {
*pissuer = crl_issuer;
@@ -1297,16 +1316,15 @@ static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl,
* parent. This could be optimised somewhat since a lot of path checking will
* be duplicated by the parent, but this will rarely be used in practice.
*/
-
static int check_crl_path(X509_STORE_CTX *ctx, X509 *x)
{
- X509_STORE_CTX crl_ctx;
+ X509_STORE_CTX crl_ctx = {0};
int ret;
/* Don't allow recursive CRL path validation */
- if (ctx->parent)
+ if (ctx->parent != NULL)
return 0;
- if (!X509_STORE_CTX_init(&crl_ctx, ctx->ctx, x, ctx->untrusted))
+ if (!X509_STORE_CTX_init(&crl_ctx, ctx->store, x, ctx->untrusted))
return -1;
crl_ctx.crls = ctx->crls;
@@ -1331,22 +1349,19 @@ static int check_crl_path(X509_STORE_CTX *ctx, X509 *x)
/*
* RFC3280 says nothing about the relationship between CRL path and
* certificate path, which could lead to situations where a certificate could
- * be revoked or validated by a CA not authorised to do so. RFC5280 is more
+ * be revoked or validated by a CA not authorized to do so. RFC5280 is more
* strict and states that the two paths must end in the same trust anchor,
* though some discussions remain... until this is resolved we use the
* RFC5280 version
*/
-
static int check_crl_chain(X509_STORE_CTX *ctx,
STACK_OF(X509) *cert_path,
STACK_OF(X509) *crl_path)
{
- X509 *cert_ta, *crl_ta;
- cert_ta = sk_X509_value(cert_path, sk_X509_num(cert_path) - 1);
- crl_ta = sk_X509_value(crl_path, sk_X509_num(crl_path) - 1);
- if (!X509_cmp(cert_ta, crl_ta))
- return 1;
- return 0;
+ X509 *cert_ta = sk_X509_value(cert_path, sk_X509_num(cert_path) - 1);
+ X509 *crl_ta = sk_X509_value(crl_path, sk_X509_num(crl_path) - 1);
+
+ return X509_cmp(cert_ta, crl_ta) == 0;
}
/*-
@@ -1356,32 +1371,29 @@ static int check_crl_chain(X509_STORE_CTX *ctx,
* 3. Both are full names and compare two GENERAL_NAMES.
* 4. One is NULL: automatic match.
*/
-
static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b)
{
X509_NAME *nm = NULL;
GENERAL_NAMES *gens = NULL;
GENERAL_NAME *gena, *genb;
int i, j;
- if (!a || !b)
+
+ if (a == NULL || b == NULL)
return 1;
if (a->type == 1) {
- if (!a->dpname)
+ if (a->dpname == NULL)
return 0;
/* Case 1: two X509_NAME */
if (b->type == 1) {
- if (!b->dpname)
- return 0;
- if (!X509_NAME_cmp(a->dpname, b->dpname))
- return 1;
- else
+ if (b->dpname == NULL)
return 0;
+ return X509_NAME_cmp(a->dpname, b->dpname) == 0;
}
/* Case 2: set name and GENERAL_NAMES appropriately */
nm = a->dpname;
gens = b->name.fullname;
} else if (b->type == 1) {
- if (!b->dpname)
+ if (b->dpname == NULL)
return 0;
/* Case 2: set name and GENERAL_NAMES appropriately */
gens = a->name.fullname;
@@ -1389,12 +1401,12 @@ static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b)
}
/* Handle case 2 with one GENERAL_NAMES and one X509_NAME */
- if (nm) {
+ if (nm != NULL) {
for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
gena = sk_GENERAL_NAME_value(gens, i);
if (gena->type != GEN_DIRNAME)
continue;
- if (!X509_NAME_cmp(nm, gena->d.directoryName))
+ if (X509_NAME_cmp(nm, gena->d.directoryName) == 0)
return 1;
}
return 0;
@@ -1406,7 +1418,7 @@ static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b)
gena = sk_GENERAL_NAME_value(a->name.fullname, i);
for (j = 0; j < sk_GENERAL_NAME_num(b->name.fullname); j++) {
genb = sk_GENERAL_NAME_value(b->name.fullname, j);
- if (!GENERAL_NAME_cmp(gena, genb))
+ if (GENERAL_NAME_cmp(gena, genb) == 0)
return 1;
}
}
@@ -1418,56 +1430,57 @@ static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b)
static int crldp_check_crlissuer(DIST_POINT *dp, X509_CRL *crl, int crl_score)
{
int i;
- X509_NAME *nm = X509_CRL_get_issuer(crl);
+ const X509_NAME *nm = X509_CRL_get_issuer(crl);
+
/* If no CRLissuer return is successful iff don't need a match */
- if (!dp->CRLissuer)
- return ! !(crl_score & CRL_SCORE_ISSUER_NAME);
+ if (dp->CRLissuer == NULL)
+ return (crl_score & CRL_SCORE_ISSUER_NAME) != 0;
for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) {
GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
+
if (gen->type != GEN_DIRNAME)
continue;
- if (!X509_NAME_cmp(gen->d.directoryName, nm))
+ if (X509_NAME_cmp(gen->d.directoryName, nm) == 0)
return 1;
}
return 0;
}
/* Check CRLDP and IDP */
-
static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score,
unsigned int *preasons)
{
int i;
- if (crl->idp_flags & IDP_ONLYATTR)
+
+ if ((crl->idp_flags & IDP_ONLYATTR) != 0)
return 0;
- if (x->ex_flags & EXFLAG_CA) {
- if (crl->idp_flags & IDP_ONLYUSER)
+ if ((x->ex_flags & EXFLAG_CA) != 0) {
+ if ((crl->idp_flags & IDP_ONLYUSER) != 0)
return 0;
} else {
- if (crl->idp_flags & IDP_ONLYCA)
+ if ((crl->idp_flags & IDP_ONLYCA) != 0)
return 0;
}
*preasons = crl->idp_reasons;
for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) {
DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, i);
+
if (crldp_check_crlissuer(dp, crl, crl_score)) {
- if (!crl->idp || idp_check_dp(dp->distpoint, crl->idp->distpoint)) {
+ if (crl->idp == NULL
+ || idp_check_dp(dp->distpoint, crl->idp->distpoint)) {
*preasons &= dp->dp_reasons;
return 1;
}
}
}
- if ((!crl->idp || !crl->idp->distpoint)
- && (crl_score & CRL_SCORE_ISSUER_NAME))
- return 1;
- return 0;
+ return (crl->idp == NULL || crl->idp->distpoint == NULL)
+ && (crl_score & CRL_SCORE_ISSUER_NAME) != 0;
}
/*
* Retrieve CRL corresponding to current certificate. If deltas enabled try
* to find a delta CRL too
*/
-
static int get_crl_delta(X509_STORE_CTX *ctx,
X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x)
{
@@ -1477,7 +1490,7 @@ static int get_crl_delta(X509_STORE_CTX *ctx,
unsigned int reasons;
X509_CRL *crl = NULL, *dcrl = NULL;
STACK_OF(X509_CRL) *skcrl;
- X509_NAME *nm = X509_get_issuer_name(x);
+ const X509_NAME *nm = X509_get_issuer_name(x);
reasons = ctx->current_reasons;
ok = get_crl_sk(ctx, &crl, &dcrl,
@@ -1486,11 +1499,10 @@ static int get_crl_delta(X509_STORE_CTX *ctx,
goto done;
/* Lookup CRLs from store */
-
skcrl = ctx->lookup_crls(ctx, nm);
/* If no CRLs found and a near match from get_crl_sk use that */
- if (!skcrl && crl)
+ if (skcrl == NULL && crl != NULL)
goto done;
get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, skcrl);
@@ -1499,7 +1511,7 @@ static int get_crl_delta(X509_STORE_CTX *ctx,
done:
/* If we got any kind of CRL use it and return success */
- if (crl) {
+ if (crl != NULL) {
ctx->current_issuer = issuer;
ctx->current_crl_score = crl_score;
ctx->current_reasons = reasons;
@@ -1518,18 +1530,18 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl)
int cnum = ctx->error_depth;
int chnum = sk_X509_num(ctx->chain) - 1;
- /* if we have an alternative CRL issuer cert use that */
- if (ctx->current_issuer)
+ /* If we have an alternative CRL issuer cert use that */
+ if (ctx->current_issuer != NULL) {
issuer = ctx->current_issuer;
/*
* Else find CRL issuer: if not last certificate then issuer is next
* certificate in chain.
*/
- else if (cnum < chnum)
+ } else if (cnum < chnum) {
issuer = sk_X509_value(ctx->chain, cnum + 1);
- else {
+ } else {
issuer = sk_X509_value(ctx->chain, chnum);
- /* If not self signed, can't check signature */
+ /* If not self-issued, can't check signature */
if (!ctx->check_issued(ctx, issuer, issuer) &&
!verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER))
return 0;
@@ -1541,39 +1553,38 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl)
/*
* Skip most tests for deltas because they have already been done
*/
- if (!crl->base_crl_number) {
+ if (crl->base_crl_number == NULL) {
/* Check for cRLSign bit if keyUsage present */
- if ((issuer->ex_flags & EXFLAG_KUSAGE) &&
- !(issuer->ex_kusage & KU_CRL_SIGN) &&
+ if ((issuer->ex_flags & EXFLAG_KUSAGE) != 0 &&
+ (issuer->ex_kusage & KU_CRL_SIGN) == 0 &&
!verify_cb_crl(ctx, X509_V_ERR_KEYUSAGE_NO_CRL_SIGN))
return 0;
- if (!(ctx->current_crl_score & CRL_SCORE_SCOPE) &&
+ if ((ctx->current_crl_score & CRL_SCORE_SCOPE) == 0 &&
!verify_cb_crl(ctx, X509_V_ERR_DIFFERENT_CRL_SCOPE))
return 0;
- if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH) &&
+ if ((ctx->current_crl_score & CRL_SCORE_SAME_PATH) == 0 &&
check_crl_path(ctx, ctx->current_issuer) <= 0 &&
!verify_cb_crl(ctx, X509_V_ERR_CRL_PATH_VALIDATION_ERROR))
return 0;
- if ((crl->idp_flags & IDP_INVALID) &&
+ if ((crl->idp_flags & IDP_INVALID) != 0 &&
!verify_cb_crl(ctx, X509_V_ERR_INVALID_EXTENSION))
return 0;
}
- if (!(ctx->current_crl_score & CRL_SCORE_TIME) &&
+ if ((ctx->current_crl_score & CRL_SCORE_TIME) == 0 &&
!check_crl_time(ctx, crl, 1))
return 0;
/* Attempt to get issuer certificate public key */
ikey = X509_get0_pubkey(issuer);
-
- if (!ikey &&
+ if (ikey == NULL &&
!verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY))
return 0;
- if (ikey) {
+ if (ikey != NULL) {
int rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags);
if (rv != X509_V_OK && !verify_cb_crl(ctx, rv))
@@ -1597,8 +1608,8 @@ static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
* was revoked. This has since been changed since critical extensions can
* change the meaning of CRL entries.
*/
- if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
- && (crl->flags & EXFLAG_CRITICAL) &&
+ if ((ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) == 0
+ && (crl->flags & EXFLAG_CRITICAL) != 0 &&
!verify_cb_crl(ctx, X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION))
return 0;
/*
@@ -1632,21 +1643,15 @@ static int check_policy(X509_STORE_CTX *ctx)
* was verified via a bare public key, and pop it off right after the
* X509_policy_check() call.
*/
- if (ctx->bare_ta_signed && !sk_X509_push(ctx->chain, NULL)) {
- X509err(X509_F_CHECK_POLICY, ERR_R_MALLOC_FAILURE);
- ctx->error = X509_V_ERR_OUT_OF_MEM;
- return 0;
- }
+ if (ctx->bare_ta_signed && !sk_X509_push(ctx->chain, NULL))
+ goto memerr;
ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain,
ctx->param->policies, ctx->param->flags);
if (ctx->bare_ta_signed)
- sk_X509_pop(ctx->chain);
+ (void)sk_X509_pop(ctx->chain);
- if (ret == X509_PCY_TREE_INTERNAL) {
- X509err(X509_F_CHECK_POLICY, ERR_R_MALLOC_FAILURE);
- ctx->error = X509_V_ERR_OUT_OF_MEM;
- return 0;
- }
+ if (ret == X509_PCY_TREE_INTERNAL)
+ goto memerr;
/* Invalid or inconsistent extensions */
if (ret == X509_PCY_TREE_INVALID) {
int i;
@@ -1655,11 +1660,8 @@ static int check_policy(X509_STORE_CTX *ctx)
for (i = 1; i < sk_X509_num(ctx->chain); i++) {
X509 *x = sk_X509_value(ctx->chain, i);
- if (!(x->ex_flags & EXFLAG_INVALID_POLICY))
- continue;
- if (!verify_cb_cert(ctx, x, i,
- X509_V_ERR_INVALID_POLICY_EXTENSION))
- return 0;
+ CB_FAIL_IF((x->ex_flags & EXFLAG_INVALID_POLICY) != 0,
+ ctx, x, i, X509_V_ERR_INVALID_POLICY_EXTENSION);
}
return 1;
}
@@ -1669,11 +1671,11 @@ static int check_policy(X509_STORE_CTX *ctx)
return ctx->verify_cb(0, ctx);
}
if (ret != X509_PCY_TREE_VALID) {
- X509err(X509_F_CHECK_POLICY, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_X509, ERR_R_INTERNAL_ERROR);
return 0;
}
- if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) {
+ if ((ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) != 0) {
ctx->current_cert = NULL;
/*
* Verification errors need to be "sticky", a callback may have allowed
@@ -1686,6 +1688,11 @@ static int check_policy(X509_STORE_CTX *ctx)
}
return 1;
+
+ memerr:
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
+ ctx->error = X509_V_ERR_OUT_OF_MEM;
+ return -1;
}
/*-
@@ -1695,14 +1702,14 @@ static int check_policy(X509_STORE_CTX *ctx)
*
* Return 1 on success, 0 otherwise.
*/
-int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth)
+int ossl_x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth)
{
time_t *ptime;
int i;
- if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
+ if ((ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) != 0)
ptime = &ctx->param->check_time;
- else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME)
+ else if ((ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) != 0)
return 1;
else
ptime = NULL;
@@ -1710,79 +1717,73 @@ int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth)
i = X509_cmp_time(X509_get0_notBefore(x), ptime);
if (i >= 0 && depth < 0)
return 0;
- if (i == 0 && !verify_cb_cert(ctx, x, depth,
- X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD))
- return 0;
- if (i > 0 && !verify_cb_cert(ctx, x, depth, X509_V_ERR_CERT_NOT_YET_VALID))
- return 0;
+ CB_FAIL_IF(i == 0, ctx, x, depth, X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD);
+ CB_FAIL_IF(i > 0, ctx, x, depth, X509_V_ERR_CERT_NOT_YET_VALID);
i = X509_cmp_time(X509_get0_notAfter(x), ptime);
if (i <= 0 && depth < 0)
return 0;
- if (i == 0 && !verify_cb_cert(ctx, x, depth,
- X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD))
- return 0;
- if (i < 0 && !verify_cb_cert(ctx, x, depth, X509_V_ERR_CERT_HAS_EXPIRED))
- return 0;
+ CB_FAIL_IF(i == 0, ctx, x, depth, X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD);
+ CB_FAIL_IF(i < 0, ctx, x, depth, X509_V_ERR_CERT_HAS_EXPIRED);
return 1;
}
-/* verify the issuer signatures and cert times of ctx->chain */
+/*
+ * Verify the issuer signatures and cert times of ctx->chain.
+ * Sadly, returns 0 also on internal error.
+ */
static int internal_verify(X509_STORE_CTX *ctx)
{
int n = sk_X509_num(ctx->chain) - 1;
X509 *xi = sk_X509_value(ctx->chain, n);
- X509 *xs;
+ X509 *xs = xi;
- /*
- * With DANE-verified bare public key TA signatures, it remains only to
- * check the timestamps of the top certificate. We report the issuer as
- * NULL, since all we have is a bare key.
- */
+ ctx->error_depth = n;
if (ctx->bare_ta_signed) {
- xs = xi;
+ /*
+ * With DANE-verified bare public key TA signatures,
+ * on the top certificate we check only the timestamps.
+ * We report the issuer as NULL because all we have is a bare key.
+ */
xi = NULL;
- goto check_cert_time;
- }
-
- if (ctx->check_issued(ctx, xi, xi))
- xs = xi; /* the typical case: last cert in the chain is self-issued */
- else {
- if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) {
- xs = xi;
- goto check_cert_time;
- }
- if (n <= 0) {
- if (!verify_cb_cert(ctx, xi, 0,
- X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE))
- return 0;
-
- xs = xi;
- goto check_cert_time;
+ } else if (ossl_x509_likely_issued(xi, xi) != X509_V_OK
+ /* exceptional case: last cert in the chain is not self-issued */
+ && ((ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) == 0)) {
+ if (n > 0) {
+ n--;
+ ctx->error_depth = n;
+ xs = sk_X509_value(ctx->chain, n);
+ } else {
+ CB_FAIL_IF(1, ctx, xi, 0,
+ X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE);
}
-
- n--;
- ctx->error_depth = n;
- xs = sk_X509_value(ctx->chain, n);
+ /*
+ * The below code will certainly not do a
+ * self-signature check on xi because it is not self-issued.
+ */
}
/*
- * Do not clear ctx->error=0, it must be "sticky", only the user's callback
- * is allowed to reset errors (at its own peril).
+ * Do not clear error (by ctx->error = X509_V_OK), it must be "sticky",
+ * only the user's callback is allowed to reset errors (at its own peril).
*/
while (n >= 0) {
- /*
+ /*-
* For each iteration of this loop:
* n is the subject depth
* xs is the subject cert, for which the signature is to be checked
- * xi is the supposed issuer cert containing the public key to use
+ * xi is NULL for DANE-verified bare public key TA signatures
+ * else the supposed issuer cert containing the public key to use
* Initially xs == xi if the last cert in the chain is self-issued.
- *
- * Skip signature check for self-signed certificates unless explicitly
+ */
+ /*
+ * Do signature check for self-signed certificates only if explicitly
* asked for because it does not add any security and just wastes time.
*/
- if (xs != xi || ((ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)
- && (xi->ex_flags & EXFLAG_SS) != 0)) {
+ if (xi != NULL
+ && (xs != xi
+ || ((ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE) != 0
+ && (xi->ex_flags & EXFLAG_SS) != 0))) {
EVP_PKEY *pkey;
/*
* If the issuer's public key is not available or its key usage
@@ -1795,8 +1796,8 @@ static int internal_verify(X509_STORE_CTX *ctx)
* step (n) we must check any given key usage extension in a CA cert
* when preparing the verification of a certificate issued by it.
* According to https://tools.ietf.org/html/rfc5280#section-4.2.1.3
- * we must not verify a certifiate signature if the key usage of the
- * CA certificate that issued the certificate prohibits signing.
+ * we must not verify a certificate signature if the key usage of
+ * the CA certificate that issued the certificate prohibits signing.
* In case the 'issuing' certificate is the last in the chain and is
* not a CA certificate but a 'self-issued' end-entity cert (i.e.,
* xs == xi && !(xi->ex_flags & EXFLAG_CA)) RFC 5280 does not apply
@@ -1804,24 +1805,21 @@ static int internal_verify(X509_STORE_CTX *ctx)
* we are free to ignore any key usage restrictions on such certs.
*/
int ret = xs == xi && (xi->ex_flags & EXFLAG_CA) == 0
- ? X509_V_OK : x509_signing_allowed(xi, xs);
+ ? X509_V_OK : ossl_x509_signing_allowed(xi, xs);
- if (ret != X509_V_OK && !verify_cb_cert(ctx, xi, issuer_depth, ret))
- return 0;
+ CB_FAIL_IF(ret != X509_V_OK, ctx, xi, issuer_depth, ret);
if ((pkey = X509_get0_pubkey(xi)) == NULL) {
- ret = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
- if (!verify_cb_cert(ctx, xi, issuer_depth, ret))
- return 0;
- } else if (X509_verify(xs, pkey) <= 0) {
- ret = X509_V_ERR_CERT_SIGNATURE_FAILURE;
- if (!verify_cb_cert(ctx, xs, n, ret))
- return 0;
+ CB_FAIL_IF(1, ctx, xi, issuer_depth,
+ X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY);
+ } else {
+ CB_FAIL_IF(X509_verify(xs, pkey) <= 0,
+ ctx, xs, n, X509_V_ERR_CERT_SIGNATURE_FAILURE);
}
}
- check_cert_time: /* in addition to RFC 5280, do also for trusted (root) cert */
+ /* In addition to RFC 5280 requirements do also for trust anchor cert */
/* Calls verify callback as needed */
- if (!x509_check_cert_time(ctx, xs, n))
+ if (!ossl_x509_check_cert_time(ctx, xs, n))
return 0;
/*
@@ -1858,7 +1856,8 @@ int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
#else
const char upper_z = 'Z';
#endif
- /*
+
+ /*-
* Note that ASN.1 allows much more slack in the time format than RFC5280.
* In RFC5280, the representation is fixed:
* UTCTime: YYMMDDHHMMSSZ
@@ -1888,7 +1887,7 @@ int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
* Digit and date ranges will be verified in the conversion methods.
*/
for (i = 0; i < ctm->length - 1; i++) {
- if (!ascii_isdigit(ctm->data[i]))
+ if (!ossl_ascii_isdigit(ctm->data[i]))
return 0;
}
if (ctm->data[ctm->length - 1] != upper_z)
@@ -1902,7 +1901,7 @@ int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
asn1_cmp_time = X509_time_adj(NULL, 0, cmp_time);
if (asn1_cmp_time == NULL)
goto err;
- if (!ASN1_TIME_diff(&day, &sec, ctm, asn1_cmp_time))
+ if (ASN1_TIME_diff(&day, &sec, ctm, asn1_cmp_time) == 0)
goto err;
/*
@@ -1916,6 +1915,31 @@ int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
return ret;
}
+/*
+ * Return 0 if time should not be checked or reference time is in range,
+ * or else 1 if it is past the end, or -1 if it is before the start
+ */
+int X509_cmp_timeframe(const X509_VERIFY_PARAM *vpm,
+ const ASN1_TIME *start, const ASN1_TIME *end)
+{
+ time_t ref_time;
+ time_t *time = NULL;
+ unsigned long flags = vpm == NULL ? 0 : X509_VERIFY_PARAM_get_flags(vpm);
+
+ if ((flags & X509_V_FLAG_USE_CHECK_TIME) != 0) {
+ ref_time = X509_VERIFY_PARAM_get_time(vpm);
+ time = &ref_time;
+ } else if ((flags & X509_V_FLAG_NO_CHECK_TIME) != 0) {
+ return 0; /* this means ok */
+ } /* else reference time is the current time */
+
+ if (end != NULL && X509_cmp_time(end, time) < 0)
+ return 1;
+ if (start != NULL && X509_cmp_time(start, time) > 0)
+ return -1;
+ return 0;
+}
+
ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
{
return X509_time_adj(s, adj, NULL);
@@ -1936,7 +1960,7 @@ ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s,
else
time(&t);
- if (s && !(s->flags & ASN1_STRING_FLAG_MSTRING)) {
+ if (s != NULL && (s->flags & ASN1_STRING_FLAG_MSTRING) == 0) {
if (s->type == V_ASN1_UTCTIME)
return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
if (s->type == V_ASN1_GENERALIZEDTIME)
@@ -1945,87 +1969,92 @@ ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s,
return ASN1_TIME_adj(s, t, offset_day, offset_sec);
}
+/* Copy any missing public key parameters up the chain towards pkey */
int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)
{
EVP_PKEY *ktmp = NULL, *ktmp2;
int i, j;
- if ((pkey != NULL) && !EVP_PKEY_missing_parameters(pkey))
+ if (pkey != NULL && !EVP_PKEY_missing_parameters(pkey))
return 1;
for (i = 0; i < sk_X509_num(chain); i++) {
ktmp = X509_get0_pubkey(sk_X509_value(chain, i));
if (ktmp == NULL) {
- X509err(X509_F_X509_GET_PUBKEY_PARAMETERS,
- X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
+ ERR_raise(ERR_LIB_X509, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
return 0;
}
if (!EVP_PKEY_missing_parameters(ktmp))
break;
+ ktmp = NULL;
}
if (ktmp == NULL) {
- X509err(X509_F_X509_GET_PUBKEY_PARAMETERS,
- X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN);
+ ERR_raise(ERR_LIB_X509, X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN);
return 0;
}
/* first, populate the other certs */
for (j = i - 1; j >= 0; j--) {
ktmp2 = X509_get0_pubkey(sk_X509_value(chain, j));
- EVP_PKEY_copy_parameters(ktmp2, ktmp);
+ if (!EVP_PKEY_copy_parameters(ktmp2, ktmp))
+ return 0;
}
if (pkey != NULL)
- EVP_PKEY_copy_parameters(pkey, ktmp);
+ return EVP_PKEY_copy_parameters(pkey, ktmp);
return 1;
}
-/* Make a delta CRL as the diff between two full CRLs */
-
+/*
+ * Make a delta CRL as the difference between two full CRLs.
+ * Sadly, returns NULL also on internal error.
+ */
X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
EVP_PKEY *skey, const EVP_MD *md, unsigned int flags)
{
X509_CRL *crl = NULL;
int i;
+
STACK_OF(X509_REVOKED) *revs = NULL;
/* CRLs can't be delta already */
- if (base->base_crl_number || newer->base_crl_number) {
- X509err(X509_F_X509_CRL_DIFF, X509_R_CRL_ALREADY_DELTA);
+ if (base->base_crl_number != NULL || newer->base_crl_number != NULL) {
+ ERR_raise(ERR_LIB_X509, X509_R_CRL_ALREADY_DELTA);
return NULL;
}
/* Base and new CRL must have a CRL number */
- if (!base->crl_number || !newer->crl_number) {
- X509err(X509_F_X509_CRL_DIFF, X509_R_NO_CRL_NUMBER);
+ if (base->crl_number == NULL || newer->crl_number == NULL) {
+ ERR_raise(ERR_LIB_X509, X509_R_NO_CRL_NUMBER);
return NULL;
}
/* Issuer names must match */
- if (X509_NAME_cmp(X509_CRL_get_issuer(base), X509_CRL_get_issuer(newer))) {
- X509err(X509_F_X509_CRL_DIFF, X509_R_ISSUER_MISMATCH);
+ if (X509_NAME_cmp(X509_CRL_get_issuer(base),
+ X509_CRL_get_issuer(newer)) != 0) {
+ ERR_raise(ERR_LIB_X509, X509_R_ISSUER_MISMATCH);
return NULL;
}
/* AKID and IDP must match */
if (!crl_extension_match(base, newer, NID_authority_key_identifier)) {
- X509err(X509_F_X509_CRL_DIFF, X509_R_AKID_MISMATCH);
+ ERR_raise(ERR_LIB_X509, X509_R_AKID_MISMATCH);
return NULL;
}
if (!crl_extension_match(base, newer, NID_issuing_distribution_point)) {
- X509err(X509_F_X509_CRL_DIFF, X509_R_IDP_MISMATCH);
+ ERR_raise(ERR_LIB_X509, X509_R_IDP_MISMATCH);
return NULL;
}
/* Newer CRL number must exceed full CRL number */
if (ASN1_INTEGER_cmp(newer->crl_number, base->crl_number) <= 0) {
- X509err(X509_F_X509_CRL_DIFF, X509_R_NEWER_CRL_NOT_NEWER);
+ ERR_raise(ERR_LIB_X509, X509_R_NEWER_CRL_NOT_NEWER);
return NULL;
}
/* CRLs must verify */
- if (skey && (X509_CRL_verify(base, skey) <= 0 ||
- X509_CRL_verify(newer, skey) <= 0)) {
- X509err(X509_F_X509_CRL_DIFF, X509_R_CRL_VERIFY_FAILURE);
+ if (skey != NULL && (X509_CRL_verify(base, skey) <= 0 ||
+ X509_CRL_verify(newer, skey) <= 0)) {
+ ERR_raise(ERR_LIB_X509, X509_R_CRL_VERIFY_FAILURE);
return NULL;
}
/* Create new CRL */
- crl = X509_CRL_new();
- if (crl == NULL || !X509_CRL_set_version(crl, 1))
+ crl = X509_CRL_new_ex(base->libctx, base->propq);
+ if (crl == NULL || !X509_CRL_set_version(crl, X509_CRL_VERSION_2))
goto memerr;
/* Set issuer name */
if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer)))
@@ -2037,7 +2066,6 @@ X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
goto memerr;
/* Set base CRL number: must be critical */
-
if (!X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0))
goto memerr;
@@ -2045,28 +2073,28 @@ X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
* Copy extensions across from newest CRL to delta: this will set CRL
* number to correct value too.
*/
-
for (i = 0; i < X509_CRL_get_ext_count(newer); i++) {
- X509_EXTENSION *ext;
- ext = X509_CRL_get_ext(newer, i);
+ X509_EXTENSION *ext = X509_CRL_get_ext(newer, i);
+
if (!X509_CRL_add_ext(crl, ext, -1))
goto memerr;
}
/* Go through revoked entries, copying as needed */
-
revs = X509_CRL_get_REVOKED(newer);
for (i = 0; i < sk_X509_REVOKED_num(revs); i++) {
X509_REVOKED *rvn, *rvtmp;
+
rvn = sk_X509_REVOKED_value(revs, i);
/*
- * Add only if not also in base. TODO: need something cleverer here
- * for some more complex CRLs covering multiple CAs.
+ * Add only if not also in base.
+ * Need something cleverer here for some more complex CRLs covering
+ * multiple CAs.
*/
if (!X509_CRL_get0_by_serial(base, &rvtmp, &rvn->serialNumber)) {
rvtmp = X509_REVOKED_dup(rvn);
- if (!rvtmp)
+ if (rvtmp == NULL)
goto memerr;
if (!X509_CRL_add0_revoked(crl, rvtmp)) {
X509_REVOKED_free(rvtmp);
@@ -2074,15 +2102,14 @@ X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
}
}
}
- /* TODO: optionally prune deleted entries */
- if (skey && md && !X509_CRL_sign(crl, skey, md))
+ if (skey != NULL && md != NULL && !X509_CRL_sign(crl, skey, md))
goto memerr;
return crl;
memerr:
- X509err(X509_F_X509_CRL_DIFF, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
X509_CRL_free(crl);
return NULL;
}
@@ -2092,12 +2119,12 @@ int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data)
return CRYPTO_set_ex_data(&ctx->ex_data, idx, data);
}
-void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx)
+void *X509_STORE_CTX_get_ex_data(const X509_STORE_CTX *ctx, int idx)
{
return CRYPTO_get_ex_data(&ctx->ex_data, idx);
}
-int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)
+int X509_STORE_CTX_get_error(const X509_STORE_CTX *ctx)
{
return ctx->error;
}
@@ -2107,7 +2134,7 @@ void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err)
ctx->error = err;
}
-int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
+int X509_STORE_CTX_get_error_depth(const X509_STORE_CTX *ctx)
{
return ctx->error_depth;
}
@@ -2117,7 +2144,7 @@ void X509_STORE_CTX_set_error_depth(X509_STORE_CTX *ctx, int depth)
ctx->error_depth = depth;
}
-X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx)
+X509 *X509_STORE_CTX_get_current_cert(const X509_STORE_CTX *ctx)
{
return ctx->current_cert;
}
@@ -2127,29 +2154,29 @@ void X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x)
ctx->current_cert = x;
}
-STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx)
+STACK_OF(X509) *X509_STORE_CTX_get0_chain(const X509_STORE_CTX *ctx)
{
return ctx->chain;
}
-STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx)
+STACK_OF(X509) *X509_STORE_CTX_get1_chain(const X509_STORE_CTX *ctx)
{
- if (!ctx->chain)
+ if (ctx->chain == NULL)
return NULL;
return X509_chain_up_ref(ctx->chain);
}
-X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx)
+X509 *X509_STORE_CTX_get0_current_issuer(const X509_STORE_CTX *ctx)
{
return ctx->current_issuer;
}
-X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx)
+X509_CRL *X509_STORE_CTX_get0_current_crl(const X509_STORE_CTX *ctx)
{
return ctx->current_crl;
}
-X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx)
+X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(const X509_STORE_CTX *ctx)
{
return ctx->parent;
}
@@ -2193,13 +2220,13 @@ int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
* application can set: if they aren't set then we use the default of SSL
* client/server.
*/
-
int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
int purpose, int trust)
{
int idx;
+
/* If purpose not set use default */
- if (!purpose)
+ if (purpose == 0)
purpose = def_purpose;
/*
* If purpose is set but we don't have a default then set the default to
@@ -2208,70 +2235,91 @@ int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
else if (def_purpose == 0)
def_purpose = purpose;
/* If we have a purpose then check it is valid */
- if (purpose) {
+ if (purpose != 0) {
X509_PURPOSE *ptmp;
+
idx = X509_PURPOSE_get_by_id(purpose);
if (idx == -1) {
- X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
- X509_R_UNKNOWN_PURPOSE_ID);
+ ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_PURPOSE_ID);
return 0;
}
ptmp = X509_PURPOSE_get0(idx);
if (ptmp->trust == X509_TRUST_DEFAULT) {
idx = X509_PURPOSE_get_by_id(def_purpose);
if (idx == -1) {
- X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
- X509_R_UNKNOWN_PURPOSE_ID);
+ ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_PURPOSE_ID);
return 0;
}
ptmp = X509_PURPOSE_get0(idx);
}
/* If trust not set then get from purpose default */
- if (!trust)
+ if (trust == 0)
trust = ptmp->trust;
}
- if (trust) {
+ if (trust != 0) {
idx = X509_TRUST_get_by_id(trust);
if (idx == -1) {
- X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
- X509_R_UNKNOWN_TRUST_ID);
+ ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_TRUST_ID);
return 0;
}
}
- if (purpose && !ctx->param->purpose)
+ if (ctx->param->purpose == 0 && purpose != 0)
ctx->param->purpose = purpose;
- if (trust && !ctx->param->trust)
+ if (ctx->param->trust == 0 && trust != 0)
ctx->param->trust = trust;
return 1;
}
-X509_STORE_CTX *X509_STORE_CTX_new(void)
+X509_STORE_CTX *X509_STORE_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
{
X509_STORE_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL) {
- X509err(X509_F_X509_STORE_CTX_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return NULL;
}
+
+ ctx->libctx = libctx;
+ if (propq != NULL) {
+ ctx->propq = OPENSSL_strdup(propq);
+ if (ctx->propq == NULL) {
+ OPENSSL_free(ctx);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ }
+
return ctx;
}
+X509_STORE_CTX *X509_STORE_CTX_new(void)
+{
+ return X509_STORE_CTX_new_ex(NULL, NULL);
+}
+
void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
{
if (ctx == NULL)
return;
X509_STORE_CTX_cleanup(ctx);
+
+ /* libctx and propq survive X509_STORE_CTX_cleanup() */
+ OPENSSL_free(ctx->propq);
OPENSSL_free(ctx);
}
int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
STACK_OF(X509) *chain)
{
- int ret = 1;
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ X509_STORE_CTX_cleanup(ctx);
- ctx->ctx = store;
+ ctx->store = store;
ctx->cert = x509;
ctx->untrusted = chain;
ctx->crls = NULL;
@@ -2279,7 +2327,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
ctx->other_ctx = NULL;
ctx->valid = 0;
ctx->chain = NULL;
- ctx->error = 0;
+ ctx->error = X509_V_OK;
ctx->explicit_policy = 0;
ctx->error_depth = 0;
ctx->current_cert = NULL;
@@ -2295,88 +2343,80 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
memset(&ctx->ex_data, 0, sizeof(ctx->ex_data));
/* store->cleanup is always 0 in OpenSSL, if set must be idempotent */
- if (store)
+ if (store != NULL)
ctx->cleanup = store->cleanup;
else
- ctx->cleanup = 0;
+ ctx->cleanup = NULL;
- if (store && store->check_issued)
+ if (store != NULL && store->check_issued != NULL)
ctx->check_issued = store->check_issued;
else
ctx->check_issued = check_issued;
- if (store && store->get_issuer)
+ if (store != NULL && store->get_issuer != NULL)
ctx->get_issuer = store->get_issuer;
else
ctx->get_issuer = X509_STORE_CTX_get1_issuer;
- if (store && store->verify_cb)
+ if (store != NULL && store->verify_cb != NULL)
ctx->verify_cb = store->verify_cb;
else
ctx->verify_cb = null_callback;
- if (store && store->verify)
+ if (store != NULL && store->verify != NULL)
ctx->verify = store->verify;
else
ctx->verify = internal_verify;
- if (store && store->check_revocation)
+ if (store != NULL && store->check_revocation != NULL)
ctx->check_revocation = store->check_revocation;
else
ctx->check_revocation = check_revocation;
- if (store && store->get_crl)
+ if (store != NULL && store->get_crl != NULL)
ctx->get_crl = store->get_crl;
else
ctx->get_crl = NULL;
- if (store && store->check_crl)
+ if (store != NULL && store->check_crl != NULL)
ctx->check_crl = store->check_crl;
else
ctx->check_crl = check_crl;
- if (store && store->cert_crl)
+ if (store != NULL && store->cert_crl != NULL)
ctx->cert_crl = store->cert_crl;
else
ctx->cert_crl = cert_crl;
- if (store && store->check_policy)
+ if (store != NULL && store->check_policy != NULL)
ctx->check_policy = store->check_policy;
else
ctx->check_policy = check_policy;
- if (store && store->lookup_certs)
+ if (store != NULL && store->lookup_certs != NULL)
ctx->lookup_certs = store->lookup_certs;
else
ctx->lookup_certs = X509_STORE_CTX_get1_certs;
- if (store && store->lookup_crls)
+ if (store != NULL && store->lookup_crls != NULL)
ctx->lookup_crls = store->lookup_crls;
else
ctx->lookup_crls = X509_STORE_CTX_get1_crls;
ctx->param = X509_VERIFY_PARAM_new();
if (ctx->param == NULL) {
- X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
- /*
- * Inherit callbacks and flags from X509_STORE if not set use defaults.
- */
- if (store)
- ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
- else
+ /* Inherit callbacks and flags from X509_STORE if not set use defaults. */
+ if (store == NULL)
ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT | X509_VP_FLAG_ONCE;
+ else if (X509_VERIFY_PARAM_inherit(ctx->param, store->param) == 0)
+ goto err;
- if (ret)
- ret = X509_VERIFY_PARAM_inherit(ctx->param,
- X509_VERIFY_PARAM_lookup("default"));
-
- if (ret == 0) {
- X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE);
+ if (!X509_STORE_CTX_set_default(ctx, "default"))
goto err;
- }
/*
* XXX: For now, continue to inherit trust from VPM, but infer from the
@@ -2393,7 +2433,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
if (CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
&ctx->ex_data))
return 1;
- X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
err:
/*
@@ -2405,8 +2445,8 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
}
/*
- * Set alternative lookup method: just a STACK of trusted certificates. This
- * avoids X509_STORE nastiness where it isn't needed.
+ * Set alternative get_issuer method: just from a STACK of trusted certificates.
+ * This avoids the complexity of X509_STORE where it is not needed.
*/
void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
{
@@ -2423,7 +2463,7 @@ void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
* calls cleanup() for the same object twice! Thus we must zero the
* pointers below after they're freed!
*/
- /* Seems to always be 0 in OpenSSL, do this at most once. */
+ /* Seems to always be NULL in OpenSSL, do this at most once. */
if (ctx->cleanup != NULL) {
ctx->cleanup(ctx);
ctx->cleanup = NULL;
@@ -2457,12 +2497,12 @@ void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags,
X509_VERIFY_PARAM_set_time(ctx->param, t);
}
-X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx)
+X509 *X509_STORE_CTX_get0_cert(const X509_STORE_CTX *ctx)
{
return ctx->cert;
}
-STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx)
+STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx)
{
return ctx->untrusted;
}
@@ -2484,7 +2524,7 @@ void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
ctx->verify_cb = verify_cb;
}
-X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx)
+X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(const X509_STORE_CTX *ctx)
{
return ctx->verify_cb;
}
@@ -2495,72 +2535,80 @@ void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx,
ctx->verify = verify;
}
-X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx)
+X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(const X509_STORE_CTX *ctx)
{
return ctx->verify;
}
-X509_STORE_CTX_get_issuer_fn X509_STORE_CTX_get_get_issuer(X509_STORE_CTX *ctx)
+X509_STORE_CTX_get_issuer_fn
+X509_STORE_CTX_get_get_issuer(const X509_STORE_CTX *ctx)
{
return ctx->get_issuer;
}
-X509_STORE_CTX_check_issued_fn X509_STORE_CTX_get_check_issued(X509_STORE_CTX *ctx)
+X509_STORE_CTX_check_issued_fn
+X509_STORE_CTX_get_check_issued(const X509_STORE_CTX *ctx)
{
return ctx->check_issued;
}
-X509_STORE_CTX_check_revocation_fn X509_STORE_CTX_get_check_revocation(X509_STORE_CTX *ctx)
+X509_STORE_CTX_check_revocation_fn
+X509_STORE_CTX_get_check_revocation(const X509_STORE_CTX *ctx)
{
return ctx->check_revocation;
}
-X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(X509_STORE_CTX *ctx)
+X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(const X509_STORE_CTX *ctx)
{
return ctx->get_crl;
}
-X509_STORE_CTX_check_crl_fn X509_STORE_CTX_get_check_crl(X509_STORE_CTX *ctx)
+X509_STORE_CTX_check_crl_fn
+X509_STORE_CTX_get_check_crl(const X509_STORE_CTX *ctx)
{
return ctx->check_crl;
}
-X509_STORE_CTX_cert_crl_fn X509_STORE_CTX_get_cert_crl(X509_STORE_CTX *ctx)
+X509_STORE_CTX_cert_crl_fn
+X509_STORE_CTX_get_cert_crl(const X509_STORE_CTX *ctx)
{
return ctx->cert_crl;
}
-X509_STORE_CTX_check_policy_fn X509_STORE_CTX_get_check_policy(X509_STORE_CTX *ctx)
+X509_STORE_CTX_check_policy_fn
+X509_STORE_CTX_get_check_policy(const X509_STORE_CTX *ctx)
{
return ctx->check_policy;
}
-X509_STORE_CTX_lookup_certs_fn X509_STORE_CTX_get_lookup_certs(X509_STORE_CTX *ctx)
+X509_STORE_CTX_lookup_certs_fn
+X509_STORE_CTX_get_lookup_certs(const X509_STORE_CTX *ctx)
{
return ctx->lookup_certs;
}
-X509_STORE_CTX_lookup_crls_fn X509_STORE_CTX_get_lookup_crls(X509_STORE_CTX *ctx)
+X509_STORE_CTX_lookup_crls_fn
+X509_STORE_CTX_get_lookup_crls(const X509_STORE_CTX *ctx)
{
return ctx->lookup_crls;
}
-X509_STORE_CTX_cleanup_fn X509_STORE_CTX_get_cleanup(X509_STORE_CTX *ctx)
+X509_STORE_CTX_cleanup_fn X509_STORE_CTX_get_cleanup(const X509_STORE_CTX *ctx)
{
return ctx->cleanup;
}
-X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx)
+X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(const X509_STORE_CTX *ctx)
{
return ctx->tree;
}
-int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx)
+int X509_STORE_CTX_get_explicit_policy(const X509_STORE_CTX *ctx)
{
return ctx->explicit_policy;
}
-int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx)
+int X509_STORE_CTX_get_num_untrusted(const X509_STORE_CTX *ctx)
{
return ctx->num_untrusted;
}
@@ -2568,13 +2616,16 @@ int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx)
int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name)
{
const X509_VERIFY_PARAM *param;
+
param = X509_VERIFY_PARAM_lookup(name);
- if (!param)
+ if (param == NULL) {
+ ERR_raise_data(ERR_LIB_X509, X509_R_UNKNOWN_PURPOSE_ID, "name=%s", name);
return 0;
+ }
return X509_VERIFY_PARAM_inherit(ctx->param, param);
}
-X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx)
+X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(const X509_STORE_CTX *ctx)
{
return ctx->param;
}
@@ -2590,10 +2641,8 @@ void X509_STORE_CTX_set0_dane(X509_STORE_CTX *ctx, SSL_DANE *dane)
ctx->dane = dane;
}
-static unsigned char *dane_i2d(
- X509 *cert,
- uint8_t selector,
- unsigned int *i2dlen)
+static unsigned char *dane_i2d(X509 *cert, uint8_t selector,
+ unsigned int *i2dlen)
{
unsigned char *buf = NULL;
int len;
@@ -2609,12 +2658,12 @@ static unsigned char *dane_i2d(
len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &buf);
break;
default:
- X509err(X509_F_DANE_I2D, X509_R_BAD_SELECTOR);
+ ERR_raise(ERR_LIB_X509, X509_R_BAD_SELECTOR);
return NULL;
}
if (len < 0 || buf == NULL) {
- X509err(X509_F_DANE_I2D, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -2622,8 +2671,9 @@ static unsigned char *dane_i2d(
return buf;
}
-#define DANETLS_NONE 256 /* impossible uint8_t */
+#define DANETLS_NONE 256 /* impossible uint8_t */
+/* Returns -1 on internal error */
static int dane_match(X509_STORE_CTX *ctx, X509 *cert, int depth)
{
SSL_DANE *dane = ctx->dane;
@@ -2644,9 +2694,7 @@ static int dane_match(X509_STORE_CTX *ctx, X509 *cert, int depth)
mask = (depth == 0) ? DANETLS_EE_MASK : DANETLS_TA_MASK;
- /*
- * The trust store is not applicable with DANE-TA(2)
- */
+ /* The trust store is not applicable with DANE-TA(2) */
if (depth >= ctx->num_untrusted)
mask &= DANETLS_PKIX_MASK;
@@ -2686,7 +2734,7 @@ static int dane_match(X509_STORE_CTX *ctx, X509 *cert, int depth)
* exhausting all DANE-?? records, we've matched a PKIX-?? record, which is
* sufficient for DANE, and what remains to do is ordinary PKIX validation.
*/
- recnum = (dane->umask & mask) ? sk_danetls_record_num(dane->trecs) : 0;
+ recnum = (dane->umask & mask) != 0 ? sk_danetls_record_num(dane->trecs) : 0;
for (i = 0; matched == 0 && i < recnum; ++i) {
t = sk_danetls_record_value(dane->trecs, i);
if ((DANETLS_USAGE_BIT(t->usage) & mask) == 0)
@@ -2730,6 +2778,7 @@ static int dane_match(X509_STORE_CTX *ctx, X509 *cert, int depth)
*/
if (t->mtype != mtype) {
const EVP_MD *md = dane->dctx->mdevp[mtype = t->mtype];
+
cmpbuf = i2dbuf;
cmplen = i2dlen;
@@ -2767,6 +2816,7 @@ static int dane_match(X509_STORE_CTX *ctx, X509 *cert, int depth)
return matched;
}
+/* Returns -1 on internal error */
static int check_dane_issuer(X509_STORE_CTX *ctx, int depth)
{
SSL_DANE *dane = ctx->dane;
@@ -2774,22 +2824,22 @@ static int check_dane_issuer(X509_STORE_CTX *ctx, int depth)
X509 *cert;
if (!DANETLS_HAS_TA(dane) || depth == 0)
- return X509_TRUST_UNTRUSTED;
+ return X509_TRUST_UNTRUSTED;
/*
- * Record any DANE trust-anchor matches, for the first depth to test, if
+ * Record any DANE trust anchor matches, for the first depth to test, if
* there's one at that depth. (This'll be false for length 1 chains looking
* for an exact match for the leaf certificate).
*/
cert = sk_X509_value(ctx->chain, depth);
if (cert != NULL && (matched = dane_match(ctx, cert, depth)) < 0)
- return X509_TRUST_REJECTED;
+ return matched;
if (matched > 0) {
ctx->num_untrusted = depth - 1;
- return X509_TRUST_TRUSTED;
+ return X509_TRUST_TRUSTED;
}
- return X509_TRUST_UNTRUSTED;
+ return X509_TRUST_UNTRUSTED;
}
static int check_dane_pkeys(X509_STORE_CTX *ctx)
@@ -2831,9 +2881,7 @@ static int check_dane_pkeys(X509_STORE_CTX *ctx)
static void dane_reset(SSL_DANE *dane)
{
- /*
- * Reset state to verify another chain, or clear after failure.
- */
+ /* Reset state to verify another chain, or clear after failure. */
X509_free(dane->mcert);
dane->mcert = NULL;
dane->mtlsa = NULL;
@@ -2845,11 +2893,11 @@ static int check_leaf_suiteb(X509_STORE_CTX *ctx, X509 *cert)
{
int err = X509_chain_check_suiteb(NULL, cert, NULL, ctx->param->flags);
- if (err == X509_V_OK)
- return 1;
- return verify_cb_cert(ctx, cert, 0, err);
+ CB_FAIL_IF(err != X509_V_OK, ctx, cert, 0, err);
+ return 1;
}
+/* Returns -1 on internal error */
static int dane_verify(X509_STORE_CTX *ctx)
{
X509 *cert = ctx->cert;
@@ -2863,7 +2911,7 @@ static int dane_verify(X509_STORE_CTX *ctx)
* When testing the leaf certificate, if we match a DANE-EE(3) record,
* dane_match() returns 1 and we're done. If however we match a PKIX-EE(1)
* record, the match depth and matching TLSA record are recorded, but the
- * return value is 0, because we still need to find a PKIX trust-anchor.
+ * return value is 0, because we still need to find a PKIX trust anchor.
* Therefore, when DANE authentication is enabled (required), we're done
* if:
* + matched < 0, internal error.
@@ -2874,8 +2922,8 @@ static int dane_verify(X509_STORE_CTX *ctx)
matched = dane_match(ctx, ctx->cert, 0);
done = matched != 0 || (!DANETLS_HAS_TA(dane) && dane->mdpth < 0);
- if (done)
- X509_get_pubkey_parameters(NULL, ctx->chain);
+ if (done && !X509_get_pubkey_parameters(NULL, ctx->chain))
+ return -1;
if (matched > 0) {
/* Callback invoked as needed */
@@ -2912,8 +2960,11 @@ static int dane_verify(X509_STORE_CTX *ctx)
return verify_chain(ctx);
}
-/* Get issuer, without duplicate suppression */
-static int get_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *cert)
+/*
+ * Get trusted issuer, without duplicate suppression
+ * Returns -1 on internal error.
+ */
+static int get1_trusted_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *cert)
{
STACK_OF(X509) *saved_chain = ctx->chain;
int ok;
@@ -2925,118 +2976,89 @@ static int get_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *cert)
return ok;
}
-static int augment_stack(STACK_OF(X509) *src, STACK_OF(X509) **dstPtr)
-{
- if (src) {
- STACK_OF(X509) *dst;
- int i;
-
- if (*dstPtr == NULL)
- return ((*dstPtr = sk_X509_dup(src)) != NULL);
-
- for (dst = *dstPtr, i = 0; i < sk_X509_num(src); ++i) {
- if (!sk_X509_push(dst, sk_X509_value(src, i))) {
- sk_X509_free(dst);
- *dstPtr = NULL;
- return 0;
- }
- }
- }
- return 1;
-}
-
+/* Returns -1 on internal error */
static int build_chain(X509_STORE_CTX *ctx)
{
SSL_DANE *dane = ctx->dane;
int num = sk_X509_num(ctx->chain);
- X509 *cert = sk_X509_value(ctx->chain, num - 1);
- int ss = cert_self_signed(cert);
- STACK_OF(X509) *sktmp = NULL;
+ STACK_OF(X509) *sk_untrusted = NULL;
unsigned int search;
int may_trusted = 0;
int may_alternate = 0;
int trust = X509_TRUST_UNTRUSTED;
int alt_untrusted = 0;
- int depth;
+ int max_depth;
int ok = 0;
int i;
/* Our chain starts with a single untrusted element. */
- if (!ossl_assert(num == 1 && ctx->num_untrusted == num)) {
- X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR);
- ctx->error = X509_V_ERR_UNSPECIFIED;
- return 0;
- }
+ if (!ossl_assert(num == 1 && ctx->num_untrusted == num))
+ goto int_err;
-#define S_DOUNTRUSTED (1 << 0) /* Search untrusted chain */
-#define S_DOTRUSTED (1 << 1) /* Search trusted store */
-#define S_DOALTERNATE (1 << 2) /* Retry with pruned alternate chain */
+#define S_DOUNTRUSTED (1 << 0) /* Search untrusted chain */
+#define S_DOTRUSTED (1 << 1) /* Search trusted store */
+#define S_DOALTERNATE (1 << 2) /* Retry with pruned alternate chain */
/*
- * Set up search policy, untrusted if possible, trusted-first if enabled.
+ * Set up search policy, untrusted if possible, trusted-first if enabled,
+ * which is the default.
* If we're doing DANE and not doing PKIX-TA/PKIX-EE, we never look in the
* trust_store, otherwise we might look there first. If not trusted-first,
* and alternate chains are not disabled, try building an alternate chain
* if no luck with untrusted first.
*/
- search = (ctx->untrusted != NULL) ? S_DOUNTRUSTED : 0;
+ search = ctx->untrusted != NULL ? S_DOUNTRUSTED : 0;
if (DANETLS_HAS_PKIX(dane) || !DANETLS_HAS_DANE(dane)) {
- if (search == 0 || ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST)
+ if (search == 0 || (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) != 0)
search |= S_DOTRUSTED;
else if (!(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS))
may_alternate = 1;
may_trusted = 1;
}
+ /* Initialize empty untrusted stack. */
+ if ((sk_untrusted = sk_X509_new_null()) == NULL)
+ goto memerr;
+
/*
- * If we got any "Cert(0) Full(0)" issuer certificates from DNS, *prepend*
- * them to our working copy of the untrusted certificate stack. Since the
- * caller of X509_STORE_CTX_init() may have provided only a leaf cert with
- * no corresponding stack of untrusted certificates, we may need to create
- * an empty stack first. [ At present only the ssl library provides DANE
- * support, and ssl_verify_cert_chain() always provides a non-null stack
- * containing at least the leaf certificate, but we must be prepared for
- * this to change. ]
+ * If we got any "Cert(0) Full(0)" trust anchors from DNS, *prepend* them
+ * to our working copy of the untrusted certificate stack.
*/
- if (DANETLS_ENABLED(dane) && !augment_stack(dane->certs, &sktmp)) {
- X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE);
- ctx->error = X509_V_ERR_OUT_OF_MEM;
- return 0;
- }
+ if (DANETLS_ENABLED(dane) && dane->certs != NULL
+ && !X509_add_certs(sk_untrusted, dane->certs, X509_ADD_FLAG_DEFAULT))
+ goto memerr;
/*
* Shallow-copy the stack of untrusted certificates (with TLS, this is
- * typically the content of the peer's certificate message) so can make
+ * typically the content of the peer's certificate message) so we can make
* multiple passes over it, while free to remove elements as we go.
*/
- if (!augment_stack(ctx->untrusted, &sktmp)) {
- X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE);
- ctx->error = X509_V_ERR_OUT_OF_MEM;
- return 0;
- }
+ if (!X509_add_certs(sk_untrusted, ctx->untrusted, X509_ADD_FLAG_DEFAULT))
+ goto memerr;
/*
* Still absurdly large, but arithmetically safe, a lower hard upper bound
* might be reasonable.
*/
- if (ctx->param->depth > INT_MAX/2)
- ctx->param->depth = INT_MAX/2;
+ if (ctx->param->depth > INT_MAX / 2)
+ ctx->param->depth = INT_MAX / 2;
/*
- * Try to Extend the chain until we reach an ultimately trusted issuer.
+ * Try to extend the chain until we reach an ultimately trusted issuer.
* Build chains up to one longer the limit, later fail if we hit the limit,
* with an X509_V_ERR_CERT_CHAIN_TOO_LONG error code.
*/
- depth = ctx->param->depth + 1;
+ max_depth = ctx->param->depth + 1;
while (search != 0) {
- X509 *x;
- X509 *xtmp = NULL;
+ X509 *curr, *issuer = NULL;
+ num = sk_X509_num(ctx->chain);
+ ctx->error_depth = num - 1;
/*
* Look in the trust store if enabled for first lookup, or we've run
* out of untrusted issuers and search here is not disabled. When we
* reach the depth limit, we stop extending the chain, if by that point
- * we've not found a trust-anchor, any trusted chain would be too long.
+ * we've not found a trust anchor, any trusted chain would be too long.
*
* The error reported to the application verify callback is at the
* maximal valid depth with the current certificate equal to the last
@@ -3047,7 +3069,7 @@ static int build_chain(X509_STORE_CTX *ctx)
* would be a-priori too long.
*/
if ((search & S_DOTRUSTED) != 0) {
- i = num = sk_X509_num(ctx->chain);
+ i = num;
if ((search & S_DOALTERNATE) != 0) {
/*
* As high up the chain as we can, look for an alternative
@@ -3066,24 +3088,30 @@ static int build_chain(X509_STORE_CTX *ctx)
*/
i = alt_untrusted;
}
- x = sk_X509_value(ctx->chain, i-1);
+ curr = sk_X509_value(ctx->chain, i - 1);
- ok = (depth < num) ? 0 : get_issuer(&xtmp, ctx, x);
+ /* Note: get1_trusted_issuer() must be used even if self-signed. */
+ ok = num > max_depth ? 0 : get1_trusted_issuer(&issuer, ctx, curr);
if (ok < 0) {
- trust = X509_TRUST_REJECTED;
+ trust = -1;
ctx->error = X509_V_ERR_STORE_LOOKUP;
- search = 0;
- continue;
+ break;
}
if (ok > 0) {
+ int self_signed = X509_self_signed(curr, 0);
+
+ if (self_signed < 0) {
+ X509_free(issuer);
+ goto int_err;
+ }
/*
* Alternative trusted issuer for a mid-chain untrusted cert?
* Pop the untrusted cert's successors and retry. We might now
* be able to complete a valid chain via the trust store. Note
- * that despite the current trust-store match we might still
- * fail complete the chain to a suitable trust-anchor, in which
+ * that despite the current trust store match we might still
+ * fail complete the chain to a suitable trust anchor, in which
* case we may prune some more untrusted certificates and try
* again. Thus the S_DOALTERNATE bit may yet be turned on
* again with an even shorter untrusted chain!
@@ -3093,13 +3121,9 @@ static int build_chain(X509_STORE_CTX *ctx)
* certificate among the ones from the trust store.
*/
if ((search & S_DOALTERNATE) != 0) {
- if (!ossl_assert(num > i && i > 0 && ss == 0)) {
- X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR);
- X509_free(xtmp);
- trust = X509_TRUST_REJECTED;
- ctx->error = X509_V_ERR_UNSPECIFIED;
- search = 0;
- continue;
+ if (!ossl_assert(num > i && i > 0 && !self_signed)) {
+ X509_free(issuer);
+ goto int_err;
}
search &= ~S_DOALTERNATE;
for (; num > i; --num)
@@ -3121,36 +3145,33 @@ static int build_chain(X509_STORE_CTX *ctx)
* Self-signed untrusted certificates get replaced by their
* trusted matching issuer. Otherwise, grow the chain.
*/
- if (ss == 0) {
- if (!sk_X509_push(ctx->chain, x = xtmp)) {
- X509_free(xtmp);
- X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE);
- trust = X509_TRUST_REJECTED;
- ctx->error = X509_V_ERR_OUT_OF_MEM;
- search = 0;
- continue;
+ if (!self_signed) {
+ if (!sk_X509_push(ctx->chain, issuer)) {
+ X509_free(issuer);
+ goto memerr;
}
- ss = cert_self_signed(x);
- } else if (num == ctx->num_untrusted) {
+ if ((self_signed = X509_self_signed(issuer, 0)) < 0)
+ goto int_err;
+ } else {
/*
* We have a self-signed certificate that has the same
* subject name (and perhaps keyid and/or serial number) as
- * a trust-anchor. We must have an exact match to avoid
+ * a trust anchor. We must have an exact match to avoid
* possible impersonation via key substitution etc.
*/
- if (X509_cmp(x, xtmp) != 0) {
+ if (X509_cmp(curr, issuer) != 0) {
/* Self-signed untrusted mimic. */
- X509_free(xtmp);
+ X509_free(issuer);
ok = 0;
- } else {
- X509_free(x);
+ } else { /* curr "==" issuer */
+ X509_free(curr);
ctx->num_untrusted = --num;
- (void) sk_X509_set(ctx->chain, num, x = xtmp);
+ (void)sk_X509_set(ctx->chain, num, issuer);
}
}
/*
- * We've added a new trusted certificate to the chain, recheck
+ * We've added a new trusted certificate to the chain, re-check
* trust. If not done, and not self-signed look deeper.
* Whether or not we're doing "trusted first", we no longer
* look for untrusted certificates from the peer's chain.
@@ -3163,21 +3184,13 @@ static int build_chain(X509_STORE_CTX *ctx)
* certificate with ctx->num_untrusted <= num.
*/
if (ok) {
- if (!ossl_assert(ctx->num_untrusted <= num)) {
- X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR);
- trust = X509_TRUST_REJECTED;
- ctx->error = X509_V_ERR_UNSPECIFIED;
- search = 0;
- continue;
- }
+ if (!ossl_assert(ctx->num_untrusted <= num))
+ goto int_err;
search &= ~S_DOUNTRUSTED;
- switch (trust = check_trust(ctx, num)) {
- case X509_TRUST_TRUSTED:
- case X509_TRUST_REJECTED:
- search = 0;
- continue;
- }
- if (ss == 0)
+ trust = check_trust(ctx, num);
+ if (trust != X509_TRUST_UNTRUSTED)
+ break;
+ if (!self_signed)
continue;
}
}
@@ -3199,30 +3212,25 @@ static int build_chain(X509_STORE_CTX *ctx)
/* Search for a trusted issuer of a shorter chain */
search |= S_DOALTERNATE;
alt_untrusted = ctx->num_untrusted - 1;
- ss = 0;
}
}
/*
- * Extend chain with peer-provided certificates
+ * Extend chain with peer-provided untrusted certificates
*/
if ((search & S_DOUNTRUSTED) != 0) {
num = sk_X509_num(ctx->chain);
- if (!ossl_assert(num == ctx->num_untrusted)) {
- X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR);
- trust = X509_TRUST_REJECTED;
- ctx->error = X509_V_ERR_UNSPECIFIED;
- search = 0;
- continue;
- }
- x = sk_X509_value(ctx->chain, num-1);
-
- /*
- * Once we run out of untrusted issuers, we stop looking for more
- * and start looking only in the trust store if enabled.
- */
- xtmp = (ss || depth < num) ? NULL : find_issuer(ctx, sktmp, x);
- if (xtmp == NULL) {
+ if (!ossl_assert(num == ctx->num_untrusted))
+ goto int_err;
+ curr = sk_X509_value(ctx->chain, num - 1);
+ issuer = (X509_self_signed(curr, 0) > 0 || num > max_depth) ?
+ NULL : find_issuer(ctx, sk_untrusted, curr);
+ if (issuer == NULL) {
+ /*
+ * Once we have reached a self-signed cert or num > max_depth
+ * or can't find an issuer in the untrusted list we stop looking
+ * there and start looking only in the trust store if enabled.
+ */
search &= ~S_DOUNTRUSTED;
if (may_trusted)
search |= S_DOTRUSTED;
@@ -3230,48 +3238,30 @@ static int build_chain(X509_STORE_CTX *ctx)
}
/* Drop this issuer from future consideration */
- (void) sk_X509_delete_ptr(sktmp, xtmp);
-
- if (!X509_up_ref(xtmp)) {
- X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR);
- trust = X509_TRUST_REJECTED;
- ctx->error = X509_V_ERR_UNSPECIFIED;
- search = 0;
- continue;
- }
+ (void)sk_X509_delete_ptr(sk_untrusted, issuer);
- if (!sk_X509_push(ctx->chain, xtmp)) {
- X509_free(xtmp);
- X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE);
- trust = X509_TRUST_REJECTED;
- ctx->error = X509_V_ERR_OUT_OF_MEM;
- search = 0;
- continue;
- }
+ if (!X509_add_cert(ctx->chain, issuer, X509_ADD_FLAG_UP_REF))
+ goto int_err;
- x = xtmp;
++ctx->num_untrusted;
- ss = cert_self_signed(xtmp);
- /*
- * Check for DANE-TA trust of the topmost untrusted certificate.
- */
- switch (trust = check_dane_issuer(ctx, ctx->num_untrusted - 1)) {
- case X509_TRUST_TRUSTED:
- case X509_TRUST_REJECTED:
- search = 0;
- continue;
- }
+ /* Check for DANE-TA trust of the topmost untrusted certificate. */
+ trust = check_dane_issuer(ctx, ctx->num_untrusted - 1);
+ if (trust == X509_TRUST_TRUSTED || trust == X509_TRUST_REJECTED)
+ break;
}
}
- sk_X509_free(sktmp);
+ sk_X509_free(sk_untrusted);
+
+ if (trust < 0) /* internal error */
+ return trust;
/*
* Last chance to make a trusted chain, either bare DANE-TA public-key
* signers, or else direct leaf PKIX trust.
*/
num = sk_X509_num(ctx->chain);
- if (num <= depth) {
+ if (num <= max_depth) {
if (trust == X509_TRUST_UNTRUSTED && DANETLS_HAS_DANE_TA(dane))
trust = check_dane_pkeys(ctx);
if (trust == X509_TRUST_UNTRUSTED && num == ctx->num_untrusted)
@@ -3286,34 +3276,97 @@ static int build_chain(X509_STORE_CTX *ctx)
return 0;
case X509_TRUST_UNTRUSTED:
default:
- num = sk_X509_num(ctx->chain);
- if (num > depth)
- return verify_cb_cert(ctx, NULL, num-1,
- X509_V_ERR_CERT_CHAIN_TOO_LONG);
- if (DANETLS_ENABLED(dane) &&
- (!DANETLS_HAS_PKIX(dane) || dane->pdpth >= 0))
- return verify_cb_cert(ctx, NULL, num-1, X509_V_ERR_DANE_NO_MATCH);
- if (ss && sk_X509_num(ctx->chain) == 1)
- return verify_cb_cert(ctx, NULL, num-1,
- X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT);
- if (ss)
- return verify_cb_cert(ctx, NULL, num-1,
- X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN);
- if (ctx->num_untrusted < num)
- return verify_cb_cert(ctx, NULL, num-1,
- X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT);
- return verify_cb_cert(ctx, NULL, num-1,
- X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY);
+ switch(ctx->error) {
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ return 0; /* Callback already issued by ossl_x509_check_cert_time() */
+ default: /* A preliminary error has become final */
+ return verify_cb_cert(ctx, NULL, num - 1, ctx->error);
+ case X509_V_OK:
+ break;
+ }
+ CB_FAIL_IF(num > max_depth,
+ ctx, NULL, num - 1, X509_V_ERR_CERT_CHAIN_TOO_LONG);
+ CB_FAIL_IF(DANETLS_ENABLED(dane)
+ && (!DANETLS_HAS_PKIX(dane) || dane->pdpth >= 0),
+ ctx, NULL, num - 1, X509_V_ERR_DANE_NO_MATCH);
+ if (X509_self_signed(sk_X509_value(ctx->chain, num - 1), 0) > 0)
+ return verify_cb_cert(ctx, NULL, num - 1,
+ num == 1
+ ? X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
+ : X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN);
+ return verify_cb_cert(ctx, NULL, num - 1,
+ ctx->num_untrusted < num
+ ? X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
+ : X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY);
+ }
+
+ int_err:
+ ERR_raise(ERR_LIB_X509, ERR_R_INTERNAL_ERROR);
+ ctx->error = X509_V_ERR_UNSPECIFIED;
+ sk_X509_free(sk_untrusted);
+ return -1;
+
+ memerr:
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
+ ctx->error = X509_V_ERR_OUT_OF_MEM;
+ sk_X509_free(sk_untrusted);
+ return -1;
+}
+
+STACK_OF(X509) *X509_build_chain(X509 *target, STACK_OF(X509) *certs,
+ X509_STORE *store, int with_self_signed,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ int finish_chain = store != NULL;
+ X509_STORE_CTX *ctx;
+ int flags = X509_ADD_FLAG_UP_REF;
+ STACK_OF(X509) *result = NULL;
+
+ if (target == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+
+ if ((ctx = X509_STORE_CTX_new_ex(libctx, propq)) == NULL)
+ return NULL;
+ if (!X509_STORE_CTX_init(ctx, store, target, finish_chain ? certs : NULL))
+ goto err;
+ if (!finish_chain)
+ X509_STORE_CTX_set0_trusted_stack(ctx, certs);
+ if (!ossl_x509_add_cert_new(&ctx->chain, target, X509_ADD_FLAG_UP_REF)) {
+ ctx->error = X509_V_ERR_OUT_OF_MEM;
+ goto err;
}
+ ctx->num_untrusted = 1;
+
+ if (!build_chain(ctx) && finish_chain)
+ goto err;
+
+ /* result list to store the up_ref'ed certificates */
+ if (sk_X509_num(ctx->chain) > 1 && !with_self_signed)
+ flags |= X509_ADD_FLAG_NO_SS;
+ if (!ossl_x509_add_certs_new(&result, ctx->chain, flags)) {
+ sk_X509_free(result);
+ result = NULL;
+ }
+
+ err:
+ X509_STORE_CTX_free(ctx);
+ return result;
}
+/*
+ * note that there's a corresponding minbits_table in ssl/ssl_cert.c
+ * in ssl_get_security_level_bits that's used for selection of DH parameters
+ */
static const int minbits_table[] = { 80, 112, 128, 192, 256 };
static const int NUM_AUTH_LEVELS = OSSL_NELEM(minbits_table);
-/*
- * Check whether the public key of ``cert`` meets the security level of
- * ``ctx``.
- *
+/*-
+ * Check whether the public key of `cert` meets the security level of `ctx`.
* Returns 1 on success, 0 otherwise.
*/
static int check_key_level(X509_STORE_CTX *ctx, X509 *cert)
@@ -3337,10 +3390,10 @@ static int check_key_level(X509_STORE_CTX *ctx, X509 *cert)
if (level > NUM_AUTH_LEVELS)
level = NUM_AUTH_LEVELS;
- return EVP_PKEY_security_bits(pkey) >= minbits_table[level - 1];
+ return EVP_PKEY_get_security_bits(pkey) >= minbits_table[level - 1];
}
-/*
+/*-
* Check whether the public key of ``cert`` does not use explicit params
* for an elliptic curve.
*
@@ -3348,25 +3401,25 @@ static int check_key_level(X509_STORE_CTX *ctx, X509 *cert)
*/
static int check_curve(X509 *cert)
{
-#ifndef OPENSSL_NO_EC
EVP_PKEY *pkey = X509_get0_pubkey(cert);
/* Unsupported or malformed key */
if (pkey == NULL)
return -1;
- if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) {
- int ret;
+ if (EVP_PKEY_get_id(pkey) == EVP_PKEY_EC) {
+ int ret, val;
- ret = EC_KEY_decoded_from_explicit_params(EVP_PKEY_get0_EC_KEY(pkey));
- return ret < 0 ? ret : !ret;
+ ret = EVP_PKEY_get_int_param(pkey,
+ OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS,
+ &val);
+ return ret < 0 ? ret : !val;
}
-#endif
return 1;
}
-/*
+/*-
* Check whether the signature digest algorithm of ``cert`` meets the security
* level of ``ctx``. Should not be checked for trust anchors (whether
* self-signed or otherwise).
diff --git a/crypto/x509/x509_vpm.c b/crypto/x509/x509_vpm.c
index 535f169a29e7..b4f4c45998be 100644
--- a/crypto/x509/x509_vpm.c
+++ b/crypto/x509/x509_vpm.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -44,7 +44,8 @@ static int int_x509_param_set_hosts(X509_VERIFY_PARAM *vpm, int mode,
*/
if (namelen == 0 || name == NULL)
namelen = name ? strlen(name) : 0;
- else if (name && memchr(name, '\0', namelen > 1 ? namelen - 1 : namelen))
+ else if (name != NULL
+ && memchr(name, '\0', namelen > 1 ? namelen - 1 : namelen) != NULL)
return 0;
if (namelen > 0 && name[namelen - 1] == '\0')
--namelen;
@@ -78,14 +79,13 @@ static int int_x509_param_set_hosts(X509_VERIFY_PARAM *vpm, int mode,
return 1;
}
-
X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void)
{
X509_VERIFY_PARAM *param;
param = OPENSSL_zalloc(sizeof(*param));
if (param == NULL) {
- X509err(X509_F_X509_VERIFY_PARAM_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return NULL;
}
param->trust = X509_TRUST_DEFAULT;
@@ -142,39 +142,32 @@ void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
/* Macro to test if a field should be copied from src to dest */
#define test_x509_verify_param_copy(field, def) \
- (to_overwrite || \
- ((src->field != def) && (to_default || (dest->field == def))))
+ (to_overwrite || (src->field != def && (to_default || dest->field == def)))
/* Macro to test and copy a field if necessary */
#define x509_verify_param_copy(field, def) \
- if (test_x509_verify_param_copy(field, def)) \
- dest->field = src->field
+ if (test_x509_verify_param_copy(field, def)) \
+ dest->field = src->field;
int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
const X509_VERIFY_PARAM *src)
{
unsigned long inh_flags;
int to_default, to_overwrite;
- if (!src)
+
+ if (src == NULL)
return 1;
inh_flags = dest->inh_flags | src->inh_flags;
- if (inh_flags & X509_VP_FLAG_ONCE)
+ if ((inh_flags & X509_VP_FLAG_ONCE) != 0)
dest->inh_flags = 0;
- if (inh_flags & X509_VP_FLAG_LOCKED)
+ if ((inh_flags & X509_VP_FLAG_LOCKED) != 0)
return 1;
- if (inh_flags & X509_VP_FLAG_DEFAULT)
- to_default = 1;
- else
- to_default = 0;
-
- if (inh_flags & X509_VP_FLAG_OVERWRITE)
- to_overwrite = 1;
- else
- to_overwrite = 0;
+ to_default = (inh_flags & X509_VP_FLAG_DEFAULT) != 0;
+ to_overwrite = (inh_flags & X509_VP_FLAG_OVERWRITE) != 0;
x509_verify_param_copy(purpose, 0);
x509_verify_param_copy(trust, X509_TRUST_DEFAULT);
@@ -183,13 +176,13 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
/* If overwrite or check time not set, copy across */
- if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
+ if (to_overwrite || (dest->flags & X509_V_FLAG_USE_CHECK_TIME) == 0) {
dest->check_time = src->check_time;
dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
/* Don't need to copy flag: that is done below */
}
- if (inh_flags & X509_VP_FLAG_RESET_FLAGS)
+ if ((inh_flags & X509_VP_FLAG_RESET_FLAGS) != 0)
dest->flags = 0;
dest->flags |= src->flags;
@@ -204,7 +197,7 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
if (test_x509_verify_param_copy(hosts, NULL)) {
sk_OPENSSL_STRING_pop_free(dest->hosts, str_free);
dest->hosts = NULL;
- if (src->hosts) {
+ if (src->hosts != NULL) {
dest->hosts =
sk_OPENSSL_STRING_deep_copy(src->hosts, str_copy, str_free);
if (dest->hosts == NULL)
@@ -228,8 +221,14 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
const X509_VERIFY_PARAM *from)
{
- unsigned long save_flags = to->inh_flags;
+ unsigned long save_flags;
int ret;
+
+ if (to == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ save_flags = to->inh_flags;
to->inh_flags |= X509_VP_FLAG_DEFAULT;
ret = X509_VERIFY_PARAM_inherit(to, from);
to->inh_flags = save_flags;
@@ -239,14 +238,17 @@ int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
static int int_x509_param_set1(char **pdest, size_t *pdestlen,
const char *src, size_t srclen)
{
- void *tmp;
- if (src) {
+ char *tmp;
+
+ if (src != NULL) {
if (srclen == 0)
srclen = strlen(src);
- tmp = OPENSSL_memdup(src, srclen);
+ tmp = OPENSSL_malloc(srclen + 1);
if (tmp == NULL)
return 0;
+ memcpy(tmp, src, srclen);
+ tmp[srclen] = '\0'; /* enforce NUL termination */
} else {
tmp = NULL;
srclen = 0;
@@ -262,15 +264,13 @@ int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
{
OPENSSL_free(param->name);
param->name = OPENSSL_strdup(name);
- if (param->name)
- return 1;
- return 0;
+ return param->name != NULL;
}
int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
{
param->flags |= flags;
- if (flags & X509_V_FLAG_POLICY_MASK)
+ if ((flags & X509_V_FLAG_POLICY_MASK) != 0)
param->flags |= X509_V_FLAG_POLICY_CHECK;
return 1;
}
@@ -282,7 +282,7 @@ int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
return 1;
}
-unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param)
+unsigned long X509_VERIFY_PARAM_get_flags(const X509_VERIFY_PARAM *param)
{
return param->flags;
}
@@ -332,14 +332,12 @@ void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
ASN1_OBJECT *policy)
{
- if (!param->policies) {
+ if (param->policies == NULL) {
param->policies = sk_ASN1_OBJECT_new_null();
- if (!param->policies)
+ if (param->policies == NULL)
return 0;
}
- if (!sk_ASN1_OBJECT_push(param->policies, policy))
- return 0;
- return 1;
+ return sk_ASN1_OBJECT_push(param->policies, policy);
}
int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
@@ -348,23 +346,25 @@ int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
int i;
ASN1_OBJECT *oid, *doid;
- if (!param)
+ if (param == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return 0;
+ }
sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
- if (!policies) {
+ if (policies == NULL) {
param->policies = NULL;
return 1;
}
param->policies = sk_ASN1_OBJECT_new_null();
- if (!param->policies)
+ if (param->policies == NULL)
return 0;
for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) {
oid = sk_ASN1_OBJECT_value(policies, i);
doid = OBJ_dup(oid);
- if (!doid)
+ if (doid == NULL)
return 0;
if (!sk_ASN1_OBJECT_push(param->policies, doid)) {
ASN1_OBJECT_free(doid);
@@ -375,6 +375,11 @@ int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
return 1;
}
+char *X509_VERIFY_PARAM_get0_host(X509_VERIFY_PARAM *param, int idx)
+{
+ return sk_OPENSSL_STRING_value(param->hosts, idx);
+}
+
int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
const char *name, size_t namelen)
{
@@ -398,7 +403,7 @@ unsigned int X509_VERIFY_PARAM_get_hostflags(const X509_VERIFY_PARAM *param)
return param->hostflags;
}
-char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param)
+char *X509_VERIFY_PARAM_get0_peername(const X509_VERIFY_PARAM *param)
{
return param->peername;
}
@@ -417,10 +422,15 @@ void X509_VERIFY_PARAM_move_peername(X509_VERIFY_PARAM *to,
OPENSSL_free(to->peername);
to->peername = peername;
}
- if (from)
+ if (from != NULL)
from->peername = NULL;
}
+char *X509_VERIFY_PARAM_get0_email(X509_VERIFY_PARAM *param)
+{
+ return param->email;
+}
+
int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
const char *email, size_t emaillen)
{
@@ -428,11 +438,33 @@ int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
email, emaillen);
}
+static unsigned char
+*int_X509_VERIFY_PARAM_get0_ip(X509_VERIFY_PARAM *param, size_t *plen)
+{
+ if (param == NULL || param->ip == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ if (plen != NULL)
+ *plen = param->iplen;
+ return param->ip;
+}
+
+char *X509_VERIFY_PARAM_get1_ip_asc(X509_VERIFY_PARAM *param)
+{
+ size_t iplen;
+ unsigned char *ip = int_X509_VERIFY_PARAM_get0_ip(param, &iplen);
+
+ return ip == NULL ? NULL : ossl_ipaddr_to_asc(ip, iplen);
+}
+
int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
const unsigned char *ip, size_t iplen)
{
- if (iplen != 0 && iplen != 4 && iplen != 16)
+ if (iplen != 0 && iplen != 4 && iplen != 16) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
+ }
return int_x509_param_set1((char **)&param->ip, &param->iplen,
(char *)ip, iplen);
}
@@ -440,9 +472,8 @@ int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
{
unsigned char ipout[16];
- size_t iplen;
+ size_t iplen = (size_t)ossl_a2i_ipadd(ipout, ipasc);
- iplen = (size_t)a2i_ipadd(ipout, ipasc);
if (iplen == 0)
return 0;
return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
@@ -474,8 +505,8 @@ const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
static const X509_VERIFY_PARAM default_table[] = {
{
"default", /* X509 default parameters */
- 0, /* Check time */
- 0, /* internal flags */
+ 0, /* check time to use */
+ 0, /* inheritance flags */
X509_V_FLAG_TRUSTED_FIRST, /* flags */
0, /* purpose */
0, /* trust */
@@ -485,8 +516,8 @@ static const X509_VERIFY_PARAM default_table[] = {
vpm_empty_id},
{
"pkcs7", /* S/MIME sign parameters */
- 0, /* Check time */
- 0, /* internal flags */
+ 0, /* check time to use */
+ 0, /* inheritance flags */
0, /* flags */
X509_PURPOSE_SMIME_SIGN, /* purpose */
X509_TRUST_EMAIL, /* trust */
@@ -496,8 +527,8 @@ static const X509_VERIFY_PARAM default_table[] = {
vpm_empty_id},
{
"smime_sign", /* S/MIME sign parameters */
- 0, /* Check time */
- 0, /* internal flags */
+ 0, /* check time to use */
+ 0, /* inheritance flags */
0, /* flags */
X509_PURPOSE_SMIME_SIGN, /* purpose */
X509_TRUST_EMAIL, /* trust */
@@ -507,8 +538,8 @@ static const X509_VERIFY_PARAM default_table[] = {
vpm_empty_id},
{
"ssl_client", /* SSL/TLS client parameters */
- 0, /* Check time */
- 0, /* internal flags */
+ 0, /* check time to use */
+ 0, /* inheritance flags */
0, /* flags */
X509_PURPOSE_SSL_CLIENT, /* purpose */
X509_TRUST_SSL_CLIENT, /* trust */
@@ -518,8 +549,8 @@ static const X509_VERIFY_PARAM default_table[] = {
vpm_empty_id},
{
"ssl_server", /* SSL/TLS server parameters */
- 0, /* Check time */
- 0, /* internal flags */
+ 0, /* check time to use */
+ 0, /* inheritance flags */
0, /* flags */
X509_PURPOSE_SSL_SERVER, /* purpose */
X509_TRUST_SSL_SERVER, /* trust */
@@ -549,6 +580,7 @@ int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
{
int idx;
X509_VERIFY_PARAM *ptmp;
+
if (param_table == NULL) {
param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
if (param_table == NULL)
@@ -560,15 +592,14 @@ int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
X509_VERIFY_PARAM_free(ptmp);
}
}
- if (!sk_X509_VERIFY_PARAM_push(param_table, param))
- return 0;
- return 1;
+ return sk_X509_VERIFY_PARAM_push(param_table, param);
}
int X509_VERIFY_PARAM_get_count(void)
{
int num = OSSL_NELEM(default_table);
- if (param_table)
+
+ if (param_table != NULL)
num += sk_X509_VERIFY_PARAM_num(param_table);
return num;
}
@@ -576,6 +607,7 @@ int X509_VERIFY_PARAM_get_count(void)
const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id)
{
int num = OSSL_NELEM(default_table);
+
if (id < num)
return default_table + id;
return sk_X509_VERIFY_PARAM_value(param_table, id - num);
diff --git a/crypto/x509/x509cset.c b/crypto/x509/x509cset.c
index 6c08509138d5..2746b9892506 100644
--- a/crypto/x509/x509cset.c
+++ b/crypto/x509/x509cset.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -27,7 +27,7 @@ int X509_CRL_set_version(X509_CRL *x, long version)
return ASN1_INTEGER_set(x->crl.version, version);
}
-int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name)
+int X509_CRL_set_issuer_name(X509_CRL *x, const X509_NAME *name)
{
if (x == NULL)
return 0;
@@ -38,14 +38,14 @@ int X509_CRL_set1_lastUpdate(X509_CRL *x, const ASN1_TIME *tm)
{
if (x == NULL)
return 0;
- return x509_set1_time(&x->crl.lastUpdate, tm);
+ return ossl_x509_set1_time(&x->crl.lastUpdate, tm);
}
int X509_CRL_set1_nextUpdate(X509_CRL *x, const ASN1_TIME *tm)
{
if (x == NULL)
return 0;
- return x509_set1_time(&x->crl.nextUpdate, tm);
+ return ossl_x509_set1_time(&x->crl.nextUpdate, tm);
}
int X509_CRL_sort(X509_CRL *c)
@@ -91,7 +91,7 @@ const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl)
return crl->crl.nextUpdate;
}
-#if OPENSSL_API_COMPAT < 0x10100000L
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *crl)
{
return crl->crl.lastUpdate;
diff --git a/crypto/x509/x509name.c b/crypto/x509/x509name.c
index c86d8e7914f1..9ae0dc5de48f 100644
--- a/crypto/x509/x509name.c
+++ b/crypto/x509/x509name.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -16,7 +16,8 @@
#include <openssl/x509.h>
#include "crypto/x509.h"
-int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len)
+int X509_NAME_get_text_by_NID(const X509_NAME *name, int nid,
+ char *buf, int len)
{
ASN1_OBJECT *obj;
@@ -26,7 +27,7 @@ int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len)
return X509_NAME_get_text_by_OBJ(name, obj, buf, len);
}
-int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj,
+int X509_NAME_get_text_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj,
char *buf, int len)
{
int i;
@@ -48,12 +49,15 @@ int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj,
int X509_NAME_entry_count(const X509_NAME *name)
{
+ int ret;
+
if (name == NULL)
return 0;
- return sk_X509_NAME_ENTRY_num(name->entries);
+ ret = sk_X509_NAME_ENTRY_num(name->entries);
+ return ret > 0 ? ret : 0;
}
-int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos)
+int X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, int lastpos)
{
ASN1_OBJECT *obj;
@@ -64,7 +68,8 @@ int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos)
}
/* NOTE: you should be passing -1, not 0 as lastpos */
-int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int lastpos)
+int X509_NAME_get_index_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj,
+ int lastpos)
{
int n;
X509_NAME_ENTRY *ne;
@@ -216,15 +221,11 @@ int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, int loc,
set = sk_X509_NAME_ENTRY_value(sk, loc)->set;
}
- /*
- * X509_NAME_ENTRY_dup is ASN1 generated code, that can't be easily
- * const'ified; harmless cast since dup() don't modify its input.
- */
- if ((new_name = X509_NAME_ENTRY_dup((X509_NAME_ENTRY *)ne)) == NULL)
+ if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL)
goto err;
new_name->set = set;
if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) {
- X509err(X509_F_X509_NAME_ADD_ENTRY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
if (inc) {
@@ -248,9 +249,8 @@ X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
obj = OBJ_txt2obj(field, 0);
if (obj == NULL) {
- X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT,
- X509_R_INVALID_FIELD_NAME);
- ERR_add_error_data(2, "name=", field);
+ ERR_raise_data(ERR_LIB_X509, X509_R_INVALID_FIELD_NAME,
+ "name=%s", field);
return NULL;
}
nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
@@ -268,7 +268,7 @@ X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
obj = OBJ_nid2obj(nid);
if (obj == NULL) {
- X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_NID, X509_R_UNKNOWN_NID);
+ ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_NID);
return NULL;
}
nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
@@ -306,8 +306,7 @@ X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj)
{
if ((ne == NULL) || (obj == NULL)) {
- X509err(X509_F_X509_NAME_ENTRY_SET_OBJECT,
- ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
ASN1_OBJECT_free(ne->object);
diff --git a/crypto/x509/x509rset.c b/crypto/x509/x509rset.c
index 9da3f2ee27df..344993d4c78c 100644
--- a/crypto/x509/x509rset.c
+++ b/crypto/x509/x509rset.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -23,7 +23,7 @@ int X509_REQ_set_version(X509_REQ *x, long version)
return ASN1_INTEGER_set(x->req_info.version, version);
}
-int X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name)
+int X509_REQ_set_subject_name(X509_REQ *x, const X509_NAME *name)
{
if (x == NULL)
return 0;
diff --git a/crypto/x509/x509spki.c b/crypto/x509/x509spki.c
index fd8162af6df2..1d66697db00d 100644
--- a/crypto/x509/x509spki.c
+++ b/crypto/x509/x509spki.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -36,12 +36,12 @@ NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len)
if (len <= 0)
len = strlen(str);
if ((spki_der = OPENSSL_malloc(len + 1)) == NULL) {
- X509err(X509_F_NETSCAPE_SPKI_B64_DECODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return NULL;
}
spki_len = EVP_DecodeBlock(spki_der, (const unsigned char *)str, len);
if (spki_len < 0) {
- X509err(X509_F_NETSCAPE_SPKI_B64_DECODE, X509_R_BASE64_DECODE_ERROR);
+ ERR_raise(ERR_LIB_X509, X509_R_BASE64_DECODE_ERROR);
OPENSSL_free(spki_der);
return NULL;
}
@@ -58,11 +58,14 @@ char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki)
unsigned char *der_spki, *p;
char *b64_str;
int der_len;
+
der_len = i2d_NETSCAPE_SPKI(spki, NULL);
+ if (der_len <= 0)
+ return NULL;
der_spki = OPENSSL_malloc(der_len);
b64_str = OPENSSL_malloc(der_len * 2);
if (der_spki == NULL || b64_str == NULL) {
- X509err(X509_F_NETSCAPE_SPKI_B64_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
OPENSSL_free(der_spki);
OPENSSL_free(b64_str);
return NULL;
diff --git a/crypto/x509/x509type.c b/crypto/x509/x509type.c
index 0e33b424be51..79fd5e7db609 100644
--- a/crypto/x509/x509type.c
+++ b/crypto/x509/x509type.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -29,7 +29,7 @@ int X509_certificate_type(const X509 *x, const EVP_PKEY *pkey)
if (pk == NULL)
return 0;
- switch (EVP_PKEY_id(pk)) {
+ switch (EVP_PKEY_get_id(pk)) {
case EVP_PKEY_RSA:
ret = EVP_PK_RSA | EVP_PKT_SIGN;
/* if (!sign only extension) */
diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c
index fcf6b5ba3780..e58c9ab1c117 100644
--- a/crypto/x509/x_all.c
+++ b/crypto/x509/x_all.c
@@ -1,46 +1,69 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * Low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/asn1.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
-#include "crypto/x509.h"
-#include <openssl/ocsp.h>
+#include <openssl/http.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/x509v3.h>
+#include "internal/asn1.h"
+#include "crypto/pkcs7.h"
+#include "crypto/x509.h"
+#include "crypto/rsa.h"
int X509_verify(X509 *a, EVP_PKEY *r)
{
- if (X509_ALGOR_cmp(&a->sig_alg, &a->cert_info.signature))
+ if (X509_ALGOR_cmp(&a->sig_alg, &a->cert_info.signature) != 0)
return 0;
- return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), &a->sig_alg,
- &a->signature, &a->cert_info, r));
+
+ return ASN1_item_verify_ex(ASN1_ITEM_rptr(X509_CINF), &a->sig_alg,
+ &a->signature, &a->cert_info,
+ a->distinguishing_id, r, a->libctx, a->propq);
+}
+
+int X509_REQ_verify_ex(X509_REQ *a, EVP_PKEY *r, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ return ASN1_item_verify_ex(ASN1_ITEM_rptr(X509_REQ_INFO), &a->sig_alg,
+ a->signature, &a->req_info, a->distinguishing_id,
+ r, libctx, propq);
}
int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r)
{
- return (ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO),
- &a->sig_alg, a->signature, &a->req_info, r));
+ return X509_REQ_verify_ex(a, r, NULL, NULL);
}
int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r)
{
- return (ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC),
- &a->sig_algor, a->signature, a->spkac, r));
+ return ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC),
+ &a->sig_algor, a->signature, a->spkac, r);
}
int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
{
+ if (x == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
/*
* Setting the modified flag before signing it. This makes the cached
* encoding to be ignored, so even if the certificate fields have changed,
@@ -49,36 +72,61 @@ int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
* which exist below are the same.
*/
x->cert_info.enc.modified = 1;
- return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), &x->cert_info.signature,
- &x->sig_alg, &x->signature, &x->cert_info, pkey,
- md));
+ return ASN1_item_sign_ex(ASN1_ITEM_rptr(X509_CINF), &x->cert_info.signature,
+ &x->sig_alg, &x->signature, &x->cert_info, NULL,
+ pkey, md, x->libctx, x->propq);
}
int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx)
{
+ if (x == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
x->cert_info.enc.modified = 1;
return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF),
&x->cert_info.signature,
&x->sig_alg, &x->signature, &x->cert_info, ctx);
}
-#ifndef OPENSSL_NO_OCSP
-int X509_http_nbio(OCSP_REQ_CTX *rctx, X509 **pcert)
+static ASN1_VALUE *simple_get_asn1(const char *url, BIO *bio, BIO *rbio,
+ int timeout, const ASN1_ITEM *it)
{
- return OCSP_REQ_CTX_nbio_d2i(rctx,
- (ASN1_VALUE **)pcert, ASN1_ITEM_rptr(X509));
+ BIO *mem = OSSL_HTTP_get(url, NULL /* proxy */, NULL /* no_proxy */,
+ bio, rbio, NULL /* cb */, NULL /* arg */,
+ 1024 /* buf_size */, NULL /* headers */,
+ NULL /* expected_ct */, 1 /* expect_asn1 */,
+ OSSL_HTTP_DEFAULT_MAX_RESP_LEN, timeout);
+ ASN1_VALUE *res = ASN1_item_d2i_bio(it, mem, NULL);
+
+ BIO_free(mem);
+ return res;
+}
+
+X509 *X509_load_http(const char *url, BIO *bio, BIO *rbio, int timeout)
+{
+ return (X509 *)simple_get_asn1(url, bio, rbio, timeout,
+ ASN1_ITEM_rptr(X509));
}
-#endif
int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md)
{
+ if (x == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
x->req_info.enc.modified = 1;
- return (ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO), &x->sig_alg, NULL,
- x->signature, &x->req_info, pkey, md));
+ return ASN1_item_sign_ex(ASN1_ITEM_rptr(X509_REQ_INFO), &x->sig_alg, NULL,
+ x->signature, &x->req_info, NULL,
+ pkey, md, x->libctx, x->propq);
}
int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx)
{
+ if (x == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
x->req_info.enc.modified = 1;
return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO),
&x->sig_alg, NULL, x->signature, &x->req_info,
@@ -87,32 +135,39 @@ int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx)
int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md)
{
+ if (x == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
x->crl.enc.modified = 1;
- return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO), &x->crl.sig_alg,
- &x->sig_alg, &x->signature, &x->crl, pkey, md));
+ return ASN1_item_sign_ex(ASN1_ITEM_rptr(X509_CRL_INFO), &x->crl.sig_alg,
+ &x->sig_alg, &x->signature, &x->crl, NULL,
+ pkey, md, x->libctx, x->propq);
}
int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx)
{
+ if (x == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
x->crl.enc.modified = 1;
return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO),
&x->crl.sig_alg, &x->sig_alg, &x->signature,
&x->crl, ctx);
}
-#ifndef OPENSSL_NO_OCSP
-int X509_CRL_http_nbio(OCSP_REQ_CTX *rctx, X509_CRL **pcrl)
+X509_CRL *X509_CRL_load_http(const char *url, BIO *bio, BIO *rbio, int timeout)
{
- return OCSP_REQ_CTX_nbio_d2i(rctx,
- (ASN1_VALUE **)pcrl,
- ASN1_ITEM_rptr(X509_CRL));
+ return (X509_CRL *)simple_get_asn1(url, bio, rbio, timeout,
+ ASN1_ITEM_rptr(X509_CRL));
}
-#endif
int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md)
{
- return (ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), &x->sig_algor, NULL,
- x->signature, x->spkac, pkey, md));
+ return
+ ASN1_item_sign_ex(ASN1_ITEM_rptr(NETSCAPE_SPKAC), &x->sig_algor, NULL,
+ x->signature, x->spkac, NULL, pkey, md, NULL, NULL);
}
#ifndef OPENSSL_NO_STDIO
@@ -121,7 +176,7 @@ X509 *d2i_X509_fp(FILE *fp, X509 **x509)
return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509), fp, x509);
}
-int i2d_X509_fp(FILE *fp, X509 *x509)
+int i2d_X509_fp(FILE *fp, const X509 *x509)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509), fp, x509);
}
@@ -132,7 +187,7 @@ X509 *d2i_X509_bio(BIO *bp, X509 **x509)
return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509), bp, x509);
}
-int i2d_X509_bio(BIO *bp, X509 *x509)
+int i2d_X509_bio(BIO *bp, const X509 *x509)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bp, x509);
}
@@ -143,7 +198,7 @@ X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl)
return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
}
-int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl)
+int i2d_X509_CRL_fp(FILE *fp, const X509_CRL *crl)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
}
@@ -154,7 +209,7 @@ X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl)
return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
}
-int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl)
+int i2d_X509_CRL_bio(BIO *bp, const X509_CRL *crl)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
}
@@ -162,10 +217,22 @@ int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl)
#ifndef OPENSSL_NO_STDIO
PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7)
{
- return ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS7), fp, p7);
+ PKCS7 *ret;
+ OSSL_LIB_CTX *libctx = NULL;
+ const char *propq = NULL;
+
+ if (p7 != NULL && *p7 != NULL) {
+ libctx = (*p7)->ctx.libctx;
+ propq = (*p7)->ctx.propq;
+ }
+
+ ret = ASN1_item_d2i_fp_ex(ASN1_ITEM_rptr(PKCS7), fp, p7, libctx, propq);
+ if (ret != NULL)
+ ossl_pkcs7_resolve_libctx(ret);
+ return ret;
}
-int i2d_PKCS7_fp(FILE *fp, PKCS7 *p7)
+int i2d_PKCS7_fp(FILE *fp, const PKCS7 *p7)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(PKCS7), fp, p7);
}
@@ -173,10 +240,22 @@ int i2d_PKCS7_fp(FILE *fp, PKCS7 *p7)
PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7)
{
- return ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS7), bp, p7);
+ PKCS7 *ret;
+ OSSL_LIB_CTX *libctx = NULL;
+ const char *propq = NULL;
+
+ if (p7 != NULL && *p7 != NULL) {
+ libctx = (*p7)->ctx.libctx;
+ propq = (*p7)->ctx.propq;
+ }
+
+ ret = ASN1_item_d2i_bio_ex(ASN1_ITEM_rptr(PKCS7), bp, p7, libctx, propq);
+ if (ret != NULL)
+ ossl_pkcs7_resolve_libctx(ret);
+ return ret;
}
-int i2d_PKCS7_bio(BIO *bp, PKCS7 *p7)
+int i2d_PKCS7_bio(BIO *bp, const PKCS7 *p7)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(PKCS7), bp, p7);
}
@@ -187,7 +266,7 @@ X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req)
return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
}
-int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req)
+int i2d_X509_REQ_fp(FILE *fp, const X509_REQ *req)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
}
@@ -195,23 +274,29 @@ int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req)
X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req)
{
- return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
+ OSSL_LIB_CTX *libctx = NULL;
+ const char *propq = NULL;
+
+ if (req != NULL && *req != NULL) {
+ libctx = (*req)->libctx;
+ propq = (*req)->propq;
+ }
+
+ return ASN1_item_d2i_bio_ex(ASN1_ITEM_rptr(X509_REQ), bp, req, libctx, propq);
}
-int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req)
+int i2d_X509_REQ_bio(BIO *bp, const X509_REQ *req)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
}
-#ifndef OPENSSL_NO_RSA
-
-# ifndef OPENSSL_NO_STDIO
+#ifndef OPENSSL_NO_STDIO
RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa)
{
return ASN1_item_d2i_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa);
}
-int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa)
+int i2d_RSAPrivateKey_fp(FILE *fp, const RSA *rsa)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa);
}
@@ -228,23 +313,23 @@ RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa)
(void **)rsa);
}
-int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa)
+int i2d_RSAPublicKey_fp(FILE *fp, const RSA *rsa)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(RSAPublicKey), fp, rsa);
}
-int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa)
+int i2d_RSA_PUBKEY_fp(FILE *fp, const RSA *rsa)
{
return ASN1_i2d_fp((I2D_OF(void))i2d_RSA_PUBKEY, fp, rsa);
}
-# endif
+#endif
RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa)
{
return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa);
}
-int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa)
+int i2d_RSAPrivateKey_bio(BIO *bp, const RSA *rsa)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa);
}
@@ -259,16 +344,15 @@ RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa)
return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSA_PUBKEY, bp, rsa);
}
-int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa)
+int i2d_RSAPublicKey_bio(BIO *bp, const RSA *rsa)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa);
}
-int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa)
+int i2d_RSA_PUBKEY_bio(BIO *bp, const RSA *rsa)
{
return ASN1_i2d_bio_of(RSA, i2d_RSA_PUBKEY, bp, rsa);
}
-#endif
#ifndef OPENSSL_NO_DSA
# ifndef OPENSSL_NO_STDIO
@@ -277,9 +361,9 @@ DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa)
return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSAPrivateKey, fp, dsa);
}
-int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa)
+int i2d_DSAPrivateKey_fp(FILE *fp, const DSA *dsa)
{
- return ASN1_i2d_fp_of_const(DSA, i2d_DSAPrivateKey, fp, dsa);
+ return ASN1_i2d_fp_of(DSA, i2d_DSAPrivateKey, fp, dsa);
}
DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa)
@@ -287,7 +371,7 @@ DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa)
return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSA_PUBKEY, fp, dsa);
}
-int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa)
+int i2d_DSA_PUBKEY_fp(FILE *fp, const DSA *dsa)
{
return ASN1_i2d_fp_of(DSA, i2d_DSA_PUBKEY, fp, dsa);
}
@@ -298,9 +382,9 @@ DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa)
return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSAPrivateKey, bp, dsa);
}
-int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa)
+int i2d_DSAPrivateKey_bio(BIO *bp, const DSA *dsa)
{
- return ASN1_i2d_bio_of_const(DSA, i2d_DSAPrivateKey, bp, dsa);
+ return ASN1_i2d_bio_of(DSA, i2d_DSAPrivateKey, bp, dsa);
}
DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa)
@@ -308,7 +392,7 @@ DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa)
return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSA_PUBKEY, bp, dsa);
}
-int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa)
+int i2d_DSA_PUBKEY_bio(BIO *bp, const DSA *dsa)
{
return ASN1_i2d_bio_of(DSA, i2d_DSA_PUBKEY, bp, dsa);
}
@@ -322,7 +406,7 @@ EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey)
return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, fp, eckey);
}
-int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey)
+int i2d_EC_PUBKEY_fp(FILE *fp, const EC_KEY *eckey)
{
return ASN1_i2d_fp_of(EC_KEY, i2d_EC_PUBKEY, fp, eckey);
}
@@ -332,7 +416,7 @@ EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey)
return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, fp, eckey);
}
-int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey)
+int i2d_ECPrivateKey_fp(FILE *fp, const EC_KEY *eckey)
{
return ASN1_i2d_fp_of(EC_KEY, i2d_ECPrivateKey, fp, eckey);
}
@@ -342,7 +426,7 @@ EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey)
return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, bp, eckey);
}
-int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *ecdsa)
+int i2d_EC_PUBKEY_bio(BIO *bp, const EC_KEY *ecdsa)
{
return ASN1_i2d_bio_of(EC_KEY, i2d_EC_PUBKEY, bp, ecdsa);
}
@@ -352,7 +436,7 @@ EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey)
return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, bp, eckey);
}
-int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey)
+int i2d_ECPrivateKey_bio(BIO *bp, const EC_KEY *eckey)
{
return ASN1_i2d_bio_of(EC_KEY, i2d_ECPrivateKey, bp, eckey);
}
@@ -361,63 +445,160 @@ int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey)
int X509_pubkey_digest(const X509 *data, const EVP_MD *type,
unsigned char *md, unsigned int *len)
{
- ASN1_BIT_STRING *key;
- key = X509_get0_pubkey_bitstr(data);
- if (!key)
+ ASN1_BIT_STRING *key = X509_get0_pubkey_bitstr(data);
+
+ if (key == NULL)
return 0;
return EVP_Digest(key->data, key->length, md, len, type, NULL);
}
-int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
+int X509_digest(const X509 *cert, const EVP_MD *md, unsigned char *data,
unsigned int *len)
{
- if (type == EVP_sha1() && (data->ex_flags & EXFLAG_SET) != 0
- && (data->ex_flags & EXFLAG_NO_FINGERPRINT) == 0) {
+ if (EVP_MD_is_a(md, SN_sha1) && (cert->ex_flags & EXFLAG_SET) != 0
+ && (cert->ex_flags & EXFLAG_NO_FINGERPRINT) == 0) {
/* Asking for SHA1 and we already computed it. */
if (len != NULL)
- *len = sizeof(data->sha1_hash);
- memcpy(md, data->sha1_hash, sizeof(data->sha1_hash));
+ *len = sizeof(cert->sha1_hash);
+ memcpy(data, cert->sha1_hash, sizeof(cert->sha1_hash));
return 1;
}
- return (ASN1_item_digest
- (ASN1_ITEM_rptr(X509), type, (char *)data, md, len));
+ return ossl_asn1_item_digest_ex(ASN1_ITEM_rptr(X509), md, (char *)cert,
+ data, len, cert->libctx, cert->propq);
+}
+
+/* calculate cert digest using the same hash algorithm as in its signature */
+ASN1_OCTET_STRING *X509_digest_sig(const X509 *cert,
+ EVP_MD **md_used, int *md_is_fallback)
+{
+ unsigned int len;
+ unsigned char hash[EVP_MAX_MD_SIZE];
+ int mdnid, pknid;
+ EVP_MD *md = NULL;
+ const char *md_name;
+ ASN1_OCTET_STRING *new;
+
+ if (md_used != NULL)
+ *md_used = NULL;
+ if (md_is_fallback != NULL)
+ *md_is_fallback = 0;
+
+ if (cert == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+
+ if (!OBJ_find_sigid_algs(X509_get_signature_nid(cert), &mdnid, &pknid)) {
+ ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_SIGID_ALGS);
+ return NULL;
+ }
+
+ if (mdnid == NID_undef) {
+ if (pknid == EVP_PKEY_RSA_PSS) {
+ RSA_PSS_PARAMS *pss = ossl_rsa_pss_decode(&cert->sig_alg);
+ const EVP_MD *mgf1md, *mmd = NULL;
+ int saltlen, trailerfield;
+
+ if (pss == NULL
+ || !ossl_rsa_pss_get_param_unverified(pss, &mmd, &mgf1md,
+ &saltlen,
+ &trailerfield)
+ || mmd == NULL) {
+ RSA_PSS_PARAMS_free(pss);
+ ERR_raise(ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM);
+ return NULL;
+ }
+ RSA_PSS_PARAMS_free(pss);
+ /* Fetch explicitly and do not fallback */
+ if ((md = EVP_MD_fetch(cert->libctx, EVP_MD_get0_name(mmd),
+ cert->propq)) == NULL)
+ /* Error code from fetch is sufficient */
+ return NULL;
+ } else if (pknid != NID_undef) {
+ /* A known algorithm, but without a digest */
+ switch (pknid) {
+ case NID_ED25519: /* Follow CMS default given in RFC8419 */
+ md_name = "SHA512";
+ break;
+ case NID_ED448: /* Follow CMS default given in RFC8419 */
+ md_name = "SHAKE256";
+ break;
+ default: /* Fall back to SHA-256 */
+ md_name = "SHA256";
+ break;
+ }
+ if ((md = EVP_MD_fetch(cert->libctx, md_name,
+ cert->propq)) == NULL)
+ return NULL;
+ if (md_is_fallback != NULL)
+ *md_is_fallback = 1;
+ } else {
+ /* A completely unknown algorithm */
+ ERR_raise(ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM);
+ return NULL;
+ }
+ } else if ((md = EVP_MD_fetch(cert->libctx, OBJ_nid2sn(mdnid),
+ cert->propq)) == NULL
+ && (md = (EVP_MD *)EVP_get_digestbynid(mdnid)) == NULL) {
+ ERR_raise(ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM);
+ return NULL;
+ }
+ if (!X509_digest(cert, md, hash, &len)
+ || (new = ASN1_OCTET_STRING_new()) == NULL)
+ goto err;
+ if (ASN1_OCTET_STRING_set(new, hash, len)) {
+ if (md_used != NULL)
+ *md_used = md;
+ else
+ EVP_MD_free(md);
+ return new;
+ }
+ ASN1_OCTET_STRING_free(new);
+ err:
+ EVP_MD_free(md);
+ return NULL;
}
int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type,
unsigned char *md, unsigned int *len)
{
- if (type == EVP_sha1() && (data->flags & EXFLAG_SET) != 0
- && (data->flags & EXFLAG_INVALID) == 0) {
+ if (type == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (EVP_MD_is_a(type, SN_sha1)
+ && (data->flags & EXFLAG_SET) != 0
+ && (data->flags & EXFLAG_NO_FINGERPRINT) == 0) {
/* Asking for SHA1; always computed in CRL d2i. */
if (len != NULL)
*len = sizeof(data->sha1_hash);
memcpy(md, data->sha1_hash, sizeof(data->sha1_hash));
return 1;
}
- return (ASN1_item_digest
- (ASN1_ITEM_rptr(X509_CRL), type, (char *)data, md, len));
+ return ossl_asn1_item_digest_ex(ASN1_ITEM_rptr(X509_CRL), type, (char *)data,
+ md, len, data->libctx, data->propq);
}
int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type,
unsigned char *md, unsigned int *len)
{
- return (ASN1_item_digest
- (ASN1_ITEM_rptr(X509_REQ), type, (char *)data, md, len));
+ return ossl_asn1_item_digest_ex(ASN1_ITEM_rptr(X509_REQ), type, (char *)data,
+ md, len, data->libctx, data->propq);
}
int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type,
unsigned char *md, unsigned int *len)
{
- return (ASN1_item_digest
- (ASN1_ITEM_rptr(X509_NAME), type, (char *)data, md, len));
+ return ASN1_item_digest(ASN1_ITEM_rptr(X509_NAME), type, (char *)data,
+ md, len);
}
int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data,
const EVP_MD *type, unsigned char *md,
unsigned int *len)
{
- return (ASN1_item_digest(ASN1_ITEM_rptr(PKCS7_ISSUER_AND_SERIAL), type,
- (char *)data, md, len));
+ return ASN1_item_digest(ASN1_ITEM_rptr(PKCS7_ISSUER_AND_SERIAL), type,
+ (char *)data, md, len);
}
#ifndef OPENSSL_NO_STDIO
@@ -426,7 +607,7 @@ X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8)
return ASN1_d2i_fp_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, fp, p8);
}
-int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8)
+int i2d_PKCS8_fp(FILE *fp, const X509_SIG *p8)
{
return ASN1_i2d_fp_of(X509_SIG, i2d_X509_SIG, fp, p8);
}
@@ -437,12 +618,36 @@ X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8)
return ASN1_d2i_bio_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, bp, p8);
}
-int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8)
+int i2d_PKCS8_bio(BIO *bp, const X509_SIG *p8)
{
return ASN1_i2d_bio_of(X509_SIG, i2d_X509_SIG, bp, p8);
}
#ifndef OPENSSL_NO_STDIO
+X509_PUBKEY *d2i_X509_PUBKEY_fp(FILE *fp, X509_PUBKEY **xpk)
+{
+ return ASN1_d2i_fp_of(X509_PUBKEY, X509_PUBKEY_new, d2i_X509_PUBKEY,
+ fp, xpk);
+}
+
+int i2d_X509_PUBKEY_fp(FILE *fp, const X509_PUBKEY *xpk)
+{
+ return ASN1_i2d_fp_of(X509_PUBKEY, i2d_X509_PUBKEY, fp, xpk);
+}
+#endif
+
+X509_PUBKEY *d2i_X509_PUBKEY_bio(BIO *bp, X509_PUBKEY **xpk)
+{
+ return ASN1_d2i_bio_of(X509_PUBKEY, X509_PUBKEY_new, d2i_X509_PUBKEY,
+ bp, xpk);
+}
+
+int i2d_X509_PUBKEY_bio(BIO *bp, const X509_PUBKEY *xpk)
+{
+ return ASN1_i2d_bio_of(X509_PUBKEY, i2d_X509_PUBKEY, bp, xpk);
+}
+
+#ifndef OPENSSL_NO_STDIO
PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
PKCS8_PRIV_KEY_INFO **p8inf)
{
@@ -450,25 +655,26 @@ PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
d2i_PKCS8_PRIV_KEY_INFO, fp, p8inf);
}
-int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf)
+int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, const PKCS8_PRIV_KEY_INFO *p8inf)
{
return ASN1_i2d_fp_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, fp,
p8inf);
}
-int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key)
+int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, const EVP_PKEY *key)
{
PKCS8_PRIV_KEY_INFO *p8inf;
int ret;
+
p8inf = EVP_PKEY2PKCS8(key);
- if (!p8inf)
+ if (p8inf == NULL)
return 0;
ret = i2d_PKCS8_PRIV_KEY_INFO_fp(fp, p8inf);
PKCS8_PRIV_KEY_INFO_free(p8inf);
return ret;
}
-int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey)
+int i2d_PrivateKey_fp(FILE *fp, const EVP_PKEY *pkey)
{
return ASN1_i2d_fp_of(EVP_PKEY, i2d_PrivateKey, fp, pkey);
}
@@ -478,7 +684,23 @@ EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a)
return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, fp, a);
}
-int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey)
+EVP_PKEY *d2i_PrivateKey_ex_fp(FILE *fp, EVP_PKEY **a, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ BIO *b;
+ void *ret;
+
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_BUF_LIB);
+ return NULL;
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ ret = d2i_PrivateKey_ex_bio(b, a, libctx, propq);
+ BIO_free(b);
+ return ret;
+}
+
+int i2d_PUBKEY_fp(FILE *fp, const EVP_PKEY *pkey)
{
return ASN1_i2d_fp_of(EVP_PKEY, i2d_PUBKEY, fp, pkey);
}
@@ -497,25 +719,26 @@ PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
d2i_PKCS8_PRIV_KEY_INFO, bp, p8inf);
}
-int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf)
+int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, const PKCS8_PRIV_KEY_INFO *p8inf)
{
return ASN1_i2d_bio_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, bp,
p8inf);
}
-int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key)
+int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, const EVP_PKEY *key)
{
PKCS8_PRIV_KEY_INFO *p8inf;
int ret;
+
p8inf = EVP_PKEY2PKCS8(key);
- if (!p8inf)
+ if (p8inf == NULL)
return 0;
ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
PKCS8_PRIV_KEY_INFO_free(p8inf);
return ret;
}
-int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey)
+int i2d_PrivateKey_bio(BIO *bp, const EVP_PKEY *pkey)
{
return ASN1_i2d_bio_of(EVP_PKEY, i2d_PrivateKey, bp, pkey);
}
@@ -525,7 +748,26 @@ EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a)
return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, bp, a);
}
-int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey)
+EVP_PKEY *d2i_PrivateKey_ex_bio(BIO *bp, EVP_PKEY **a, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ BUF_MEM *b = NULL;
+ const unsigned char *p;
+ void *ret = NULL;
+ int len;
+
+ len = asn1_d2i_read_bio(bp, &b);
+ if (len < 0)
+ goto err;
+
+ p = (unsigned char *)b->data;
+ ret = d2i_AutoPrivateKey_ex(a, &p, len, libctx, propq);
+ err:
+ BUF_MEM_free(b);
+ return ret;
+}
+
+int i2d_PUBKEY_bio(BIO *bp, const EVP_PKEY *pkey)
{
return ASN1_i2d_bio_of(EVP_PKEY, i2d_PUBKEY, bp, pkey);
}
diff --git a/crypto/x509/x_attrib.c b/crypto/x509/x_attrib.c
index 7342c4f6bcb5..5c7e622d1a0b 100644
--- a/crypto/x509/x_attrib.c
+++ b/crypto/x509/x_attrib.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/x509/x_crl.c b/crypto/x509/x_crl.c
index df0041c0108c..fd98ad6926cf 100644
--- a/crypto/x509/x_crl.c
+++ b/crypto/x509/x_crl.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -27,8 +27,8 @@ ASN1_SEQUENCE(X509_REVOKED) = {
static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r);
static int def_crl_lookup(X509_CRL *crl,
- X509_REVOKED **ret, ASN1_INTEGER *serial,
- X509_NAME *issuer);
+ X509_REVOKED **ret, const ASN1_INTEGER *serial,
+ const X509_NAME *issuer);
static X509_CRL_METHOD int_crl_meth = {
0,
@@ -151,7 +151,7 @@ static int crl_set_issuers(X509_CRL *crl)
/*
* The X509_CRL structure needs a bit of customisation. Cache some extensions
- * and hash of the whole CRL.
+ * and hash of the whole CRL or set EXFLAG_NO_FINGERPRINT if this fails.
*/
static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
@@ -189,7 +189,7 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
case ASN1_OP_D2I_POST:
if (!X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL))
- crl->flags |= EXFLAG_INVALID;
+ crl->flags |= EXFLAG_NO_FINGERPRINT;
crl->idp = X509_CRL_get_ext_d2i(crl,
NID_issuing_distribution_point, &i,
NULL);
@@ -268,6 +268,15 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
ASN1_INTEGER_free(crl->crl_number);
ASN1_INTEGER_free(crl->base_crl_number);
sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free);
+ OPENSSL_free(crl->propq);
+ break;
+ case ASN1_OP_DUP_POST:
+ {
+ X509_CRL *old = exarg;
+
+ if (!ossl_x509_crl_set0_libctx(crl, old->libctx, old->propq))
+ return 0;
+ }
break;
}
return 1;
@@ -335,6 +344,18 @@ static int X509_REVOKED_cmp(const X509_REVOKED *const *a,
(ASN1_STRING *)&(*b)->serialNumber));
}
+X509_CRL *X509_CRL_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
+{
+ X509_CRL *crl = NULL;
+
+ crl = (X509_CRL *)ASN1_item_new((X509_CRL_it()));
+ if (!ossl_x509_crl_set0_libctx(crl, libctx, propq)) {
+ X509_CRL_free(crl);
+ crl = NULL;
+ }
+ return crl;
+}
+
int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
{
X509_CRL_INFO *inf;
@@ -343,7 +364,7 @@ int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
if (inf->revoked == NULL)
inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp);
if (inf->revoked == NULL || !sk_X509_REVOKED_push(inf->revoked, rev)) {
- ASN1err(ASN1_F_X509_CRL_ADD0_REVOKED, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
inf->enc.modified = 1;
@@ -358,7 +379,7 @@ int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *r)
}
int X509_CRL_get0_by_serial(X509_CRL *crl,
- X509_REVOKED **ret, ASN1_INTEGER *serial)
+ X509_REVOKED **ret, const ASN1_INTEGER *serial)
{
if (crl->meth->crl_lookup)
return crl->meth->crl_lookup(crl, ret, serial, NULL);
@@ -369,18 +390,19 @@ int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x)
{
if (crl->meth->crl_lookup)
return crl->meth->crl_lookup(crl, ret,
- X509_get_serialNumber(x),
+ X509_get0_serialNumber(x),
X509_get_issuer_name(x));
return 0;
}
static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r)
{
- return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO),
- &crl->sig_alg, &crl->signature, &crl->crl, r));
+ return ASN1_item_verify_ex(ASN1_ITEM_rptr(X509_CRL_INFO),
+ &crl->sig_alg, &crl->signature, &crl->crl, NULL,
+ r, crl->libctx, crl->propq);
}
-static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm,
+static int crl_revoked_issuer_match(X509_CRL *crl, const X509_NAME *nm,
X509_REVOKED *rev)
{
int i;
@@ -408,8 +430,8 @@ static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm,
}
static int def_crl_lookup(X509_CRL *crl,
- X509_REVOKED **ret, ASN1_INTEGER *serial,
- X509_NAME *issuer)
+ X509_REVOKED **ret, const ASN1_INTEGER *serial,
+ const X509_NAME *issuer)
{
X509_REVOKED rtmp, *rev;
int idx, num;
@@ -422,7 +444,8 @@ static int def_crl_lookup(X509_CRL *crl,
* under a lock to avoid race condition.
*/
if (!sk_X509_REVOKED_is_sorted(crl->crl.revoked)) {
- CRYPTO_THREAD_write_lock(crl->lock);
+ if (!CRYPTO_THREAD_write_lock(crl->lock))
+ return 0;
sk_X509_REVOKED_sort(crl->crl.revoked);
CRYPTO_THREAD_unlock(crl->lock);
}
@@ -458,15 +481,15 @@ X509_CRL_METHOD *X509_CRL_METHOD_new(int (*crl_init) (X509_CRL *crl),
int (*crl_free) (X509_CRL *crl),
int (*crl_lookup) (X509_CRL *crl,
X509_REVOKED **ret,
- ASN1_INTEGER *ser,
- X509_NAME *issuer),
+ const ASN1_INTEGER *ser,
+ const X509_NAME *issuer),
int (*crl_verify) (X509_CRL *crl,
EVP_PKEY *pk))
{
X509_CRL_METHOD *m = OPENSSL_malloc(sizeof(*m));
if (m == NULL) {
- X509err(X509_F_X509_CRL_METHOD_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return NULL;
}
m->crl_init = crl_init;
@@ -493,3 +516,19 @@ void *X509_CRL_get_meth_data(X509_CRL *crl)
{
return crl->meth_data;
}
+
+int ossl_x509_crl_set0_libctx(X509_CRL *x, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ if (x != NULL) {
+ x->libctx = libctx;
+ OPENSSL_free(x->propq);
+ x->propq = NULL;
+ if (propq != NULL) {
+ x->propq = OPENSSL_strdup(propq);
+ if (x->propq == NULL)
+ return 0;
+ }
+ }
+ return 1;
+}
diff --git a/crypto/x509/x_exten.c b/crypto/x509/x_exten.c
index bd7518ef12bf..4e63b50caa62 100644
--- a/crypto/x509/x_exten.c
+++ b/crypto/x509/x_exten.c
@@ -1,7 +1,7 @@
/*
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/crypto/x509/x_name.c b/crypto/x509/x_name.c
index dc4a494fb543..944eb9992486 100644
--- a/crypto/x509/x_name.c
+++ b/crypto/x509/x_name.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -28,7 +28,7 @@ static int x509_name_ex_d2i(ASN1_VALUE **val,
const ASN1_ITEM *it,
int tag, int aclass, char opt, ASN1_TLC *ctx);
-static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out,
+static int x509_name_ex_i2d(const ASN1_VALUE **val, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass);
static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it);
static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it);
@@ -36,10 +36,10 @@ static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it);
static int x509_name_encode(X509_NAME *a);
static int x509_name_canon(X509_NAME *a);
static int asn1_string_canon(ASN1_STRING *out, const ASN1_STRING *in);
-static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * intname,
+static int i2d_name_canon(const STACK_OF(STACK_OF_X509_NAME_ENTRY) * intname,
unsigned char **in);
-static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval,
+static int x509_name_ex_print(BIO *out, const ASN1_VALUE **pval,
int indent,
const char *fname, const ASN1_PCTX *pctx);
@@ -102,7 +102,7 @@ static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it)
return 1;
memerr:
- ASN1err(ASN1_F_X509_NAME_EX_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
if (ret) {
sk_X509_NAME_ENTRY_free(ret->entries);
OPENSSL_free(ret);
@@ -114,7 +114,7 @@ static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
X509_NAME *a;
- if (!pval || !*pval)
+ if (pval == NULL || *pval == NULL)
return;
a = (X509_NAME *)*pval;
@@ -156,6 +156,7 @@ static int x509_name_ex_d2i(ASN1_VALUE **val,
int i, j, ret;
STACK_OF(X509_NAME_ENTRY) *entries;
X509_NAME_ENTRY *entry;
+
if (len > X509_NAME_MAX)
len = X509_NAME_MAX;
q = p;
@@ -185,7 +186,7 @@ static int x509_name_ex_d2i(ASN1_VALUE **val,
entry->set = i;
if (!sk_X509_NAME_ENTRY_push(nm.x->entries, entry))
goto err;
- sk_X509_NAME_ENTRY_set(entries, j, NULL);
+ (void)sk_X509_NAME_ENTRY_set(entries, j, NULL);
}
}
ret = x509_name_canon(nm.x);
@@ -203,15 +204,16 @@ static int x509_name_ex_d2i(ASN1_VALUE **val,
X509_NAME_free(nm.x);
sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
local_sk_X509_NAME_ENTRY_pop_free);
- ASN1err(ASN1_F_X509_NAME_EX_D2I, ERR_R_NESTED_ASN1_ERROR);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
return 0;
}
-static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out,
+static int x509_name_ex_i2d(const ASN1_VALUE **val, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass)
{
int ret;
X509_NAME *a = (X509_NAME *)*val;
+
if (a->modified) {
ret = x509_name_encode(a);
if (ret < 0)
@@ -232,7 +234,7 @@ static int x509_name_encode(X509_NAME *a)
{
union {
STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
- ASN1_VALUE *a;
+ const ASN1_VALUE *a;
} intname = {
NULL
};
@@ -241,6 +243,7 @@ static int x509_name_encode(X509_NAME *a)
STACK_OF(X509_NAME_ENTRY) *entries = NULL;
X509_NAME_ENTRY *entry;
int i, set = -1;
+
intname.s = sk_STACK_OF_X509_NAME_ENTRY_new_null();
if (!intname.s)
goto memerr;
@@ -273,11 +276,11 @@ static int x509_name_encode(X509_NAME *a)
memerr:
sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
local_sk_X509_NAME_ENTRY_free);
- ASN1err(ASN1_F_X509_NAME_ENCODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
-static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval,
+static int x509_name_ex_print(BIO *out, const ASN1_VALUE **pval,
int indent,
const char *fname, const ASN1_PCTX *pctx)
{
@@ -295,6 +298,7 @@ static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval,
* comparison of Name structures can be rapidly performed by just using
* memcmp() of the canonical encoding. By omitting the leading SEQUENCE name
* constraints of type dirName can also be checked with a simple memcmp().
+ * NOTE: For empty X509_NAME (NULL-DN), canon_enclen == 0 && canon_enc == NULL
*/
static int x509_name_canon(X509_NAME *a)
@@ -314,7 +318,7 @@ static int x509_name_canon(X509_NAME *a)
}
intname = sk_STACK_OF_X509_NAME_ENTRY_new_null();
if (intname == NULL) {
- X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
@@ -325,25 +329,25 @@ static int x509_name_canon(X509_NAME *a)
goto err;
if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) {
sk_X509_NAME_ENTRY_free(entries);
- X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
set = entry->set;
}
tmpentry = X509_NAME_ENTRY_new();
if (tmpentry == NULL) {
- X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
tmpentry->object = OBJ_dup(entry->object);
if (tmpentry->object == NULL) {
- X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!asn1_string_canon(tmpentry->value, entry->value))
goto err;
if (!sk_X509_NAME_ENTRY_push(entries, tmpentry)) {
- X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
tmpentry = NULL;
@@ -357,7 +361,7 @@ static int x509_name_canon(X509_NAME *a)
p = OPENSSL_malloc(a->canon_enclen);
if (p == NULL) {
- X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -460,11 +464,11 @@ static int asn1_string_canon(ASN1_STRING *out, const ASN1_STRING *in)
}
-static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * _intname,
+static int i2d_name_canon(const STACK_OF(STACK_OF_X509_NAME_ENTRY) * _intname,
unsigned char **in)
{
int i, len, ltmp;
- ASN1_VALUE *v;
+ const ASN1_VALUE *v;
STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname;
len = 0;
@@ -479,14 +483,16 @@ static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * _intname,
return len;
}
-int X509_NAME_set(X509_NAME **xn, X509_NAME *name)
+int X509_NAME_set(X509_NAME **xn, const X509_NAME *name)
{
+ X509_NAME *name_copy;
+
if (*xn == name)
return *xn != NULL;
- if ((name = X509_NAME_dup(name)) == NULL)
+ if ((name_copy = X509_NAME_dup(name)) == NULL)
return 0;
X509_NAME_free(*xn);
- *xn = name;
+ *xn = name_copy;
return 1;
}
@@ -496,9 +502,9 @@ int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase)
int i;
b = X509_NAME_oneline(name, NULL, 0);
- if (!b)
+ if (b == NULL)
return 0;
- if (!*b) {
+ if (*b == '\0') {
OPENSSL_free(b);
return 1;
}
@@ -528,12 +534,12 @@ int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase)
OPENSSL_free(b);
return 1;
err:
- X509err(X509_F_X509_NAME_PRINT, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_X509, ERR_R_BUF_LIB);
OPENSSL_free(b);
return 0;
}
-int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder,
+int X509_NAME_get0_der(const X509_NAME *nm, const unsigned char **pder,
size_t *pderlen)
{
/* Make sure encoding is valid */
diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c
index 9be7e9286571..b290075c8589 100644
--- a/crypto/x509/x_pubkey.c
+++ b/crypto/x509/x_pubkey.c
@@ -1,92 +1,386 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
+#include <openssl/engine.h>
#include "crypto/asn1.h"
#include "crypto/evp.h"
#include "crypto/x509.h"
#include <openssl/rsa.h>
#include <openssl/dsa.h>
+#include <openssl/decoder.h>
+#include <openssl/encoder.h>
+#include "internal/provider.h"
+#include "internal/sizes.h"
struct X509_pubkey_st {
X509_ALGOR *algor;
ASN1_BIT_STRING *public_key;
+
EVP_PKEY *pkey;
+
+ /* extra data for the callback, used by d2i_PUBKEY_ex */
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+
+ /* Flag to force legacy keys */
+ unsigned int flag_force_legacy : 1;
};
-static int x509_pubkey_decode(EVP_PKEY **pk, X509_PUBKEY *key);
+static int x509_pubkey_decode(EVP_PKEY **pk, const X509_PUBKEY *key);
-/* Minor tweak to operation: free up EVP_PKEY */
-static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
- void *exarg)
+static int x509_pubkey_set0_libctx(X509_PUBKEY *x, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
- if (operation == ASN1_OP_FREE_POST) {
- X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
- EVP_PKEY_free(pubkey->pkey);
- } else if (operation == ASN1_OP_D2I_POST) {
- /* Attempt to decode public key and cache in pubkey structure. */
- X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
- EVP_PKEY_free(pubkey->pkey);
- pubkey->pkey = NULL;
- /*
- * Opportunistically decode the key but remove any non fatal errors
- * from the queue. Subsequent explicit attempts to decode/use the key
- * will return an appropriate error.
- */
- ERR_set_mark();
- if (x509_pubkey_decode(&pubkey->pkey, pubkey) == -1)
- return 0;
- ERR_pop_to_mark();
+ if (x != NULL) {
+ x->libctx = libctx;
+ OPENSSL_free(x->propq);
+ x->propq = NULL;
+ if (propq != NULL) {
+ x->propq = OPENSSL_strdup(propq);
+ if (x->propq == NULL)
+ return 0;
+ }
}
return 1;
}
-ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = {
+ASN1_SEQUENCE(X509_PUBKEY_INTERNAL) = {
ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR),
ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING)
-} ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY)
+} static_ASN1_SEQUENCE_END_name(X509_PUBKEY, X509_PUBKEY_INTERNAL)
+
+X509_PUBKEY *ossl_d2i_X509_PUBKEY_INTERNAL(const unsigned char **pp,
+ long len, OSSL_LIB_CTX *libctx)
+{
+ X509_PUBKEY *xpub = OPENSSL_zalloc(sizeof(*xpub));
+
+ if (xpub == NULL)
+ return NULL;
+ return (X509_PUBKEY *)ASN1_item_d2i_ex((ASN1_VALUE **)&xpub, pp, len,
+ ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL),
+ libctx, NULL);
+}
+
+void ossl_X509_PUBKEY_INTERNAL_free(X509_PUBKEY *xpub)
+{
+ ASN1_item_free((ASN1_VALUE *)xpub, ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL));
+}
+
+static void x509_pubkey_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+ X509_PUBKEY *pubkey;
+
+ if (pval != NULL && (pubkey = (X509_PUBKEY *)*pval) != NULL) {
+ X509_ALGOR_free(pubkey->algor);
+ ASN1_BIT_STRING_free(pubkey->public_key);
+ EVP_PKEY_free(pubkey->pkey);
+ OPENSSL_free(pubkey->propq);
+ OPENSSL_free(pubkey);
+ *pval = NULL;
+ }
+}
+
+static int x509_pubkey_ex_populate(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+ X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
+
+ return (pubkey->algor != NULL
+ || (pubkey->algor = X509_ALGOR_new()) != NULL)
+ && (pubkey->public_key != NULL
+ || (pubkey->public_key = ASN1_BIT_STRING_new()) != NULL);
+}
+
+
+static int x509_pubkey_ex_new_ex(ASN1_VALUE **pval, const ASN1_ITEM *it,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ X509_PUBKEY *ret;
+
+ if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL
+ || !x509_pubkey_ex_populate((ASN1_VALUE **)&ret, NULL)
+ || !x509_pubkey_set0_libctx(ret, libctx, propq)) {
+ x509_pubkey_ex_free((ASN1_VALUE **)&ret, NULL);
+ ret = NULL;
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
+ } else {
+ *pval = (ASN1_VALUE *)ret;
+ }
+
+ return ret != NULL;
+}
+
+static int x509_pubkey_ex_d2i_ex(ASN1_VALUE **pval,
+ const unsigned char **in, long len,
+ const ASN1_ITEM *it, int tag, int aclass,
+ char opt, ASN1_TLC *ctx, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ const unsigned char *in_saved = *in;
+ size_t publen;
+ X509_PUBKEY *pubkey;
+ int ret;
+ OSSL_DECODER_CTX *dctx = NULL;
+ unsigned char *tmpbuf = NULL;
+
+ if (*pval == NULL && !x509_pubkey_ex_new_ex(pval, it, libctx, propq))
+ return 0;
+ if (!x509_pubkey_ex_populate(pval, NULL)) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ /* This ensures that |*in| advances properly no matter what */
+ if ((ret = ASN1_item_ex_d2i(pval, in, len,
+ ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL),
+ tag, aclass, opt, ctx)) <= 0)
+ return ret;
+
+ publen = *in - in_saved;
+ if (!ossl_assert(publen > 0)) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ pubkey = (X509_PUBKEY *)*pval;
+ EVP_PKEY_free(pubkey->pkey);
+ pubkey->pkey = NULL;
+
+ /*
+ * Opportunistically decode the key but remove any non fatal errors
+ * from the queue. Subsequent explicit attempts to decode/use the key
+ * will return an appropriate error.
+ */
+ ERR_set_mark();
+ /*
+ * Try to decode with legacy method first. This ensures that engines
+ * aren't overriden by providers.
+ */
+ if ((ret = x509_pubkey_decode(&pubkey->pkey, pubkey)) == -1) {
+ /* -1 indicates a fatal error, like malloc failure */
+ ERR_clear_last_mark();
+ goto end;
+ }
+
+ /* Try to decode it into an EVP_PKEY with OSSL_DECODER */
+ if (ret <= 0 && !pubkey->flag_force_legacy) {
+ const unsigned char *p;
+ char txtoidname[OSSL_MAX_NAME_SIZE];
+ size_t slen = publen;
+
+ /*
+ * The decoders don't know how to handle anything other than Universal
+ * class so we modify the data accordingly.
+ */
+ if (aclass != V_ASN1_UNIVERSAL) {
+ tmpbuf = OPENSSL_memdup(in_saved, publen);
+ if (tmpbuf == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ in_saved = tmpbuf;
+ *tmpbuf = V_ASN1_CONSTRUCTED | V_ASN1_SEQUENCE;
+ }
+ p = in_saved;
+
+ if (OBJ_obj2txt(txtoidname, sizeof(txtoidname),
+ pubkey->algor->algorithm, 0) <= 0) {
+ ERR_clear_last_mark();
+ goto end;
+ }
+ if ((dctx =
+ OSSL_DECODER_CTX_new_for_pkey(&pubkey->pkey,
+ "DER", "SubjectPublicKeyInfo",
+ txtoidname, EVP_PKEY_PUBLIC_KEY,
+ pubkey->libctx,
+ pubkey->propq)) != NULL)
+ /*
+ * As said higher up, we're being opportunistic. In other words,
+ * we don't care if we fail.
+ */
+ if (OSSL_DECODER_from_data(dctx, &p, &slen)) {
+ if (slen != 0) {
+ /*
+ * If we successfully decoded then we *must* consume all the
+ * bytes.
+ */
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_ASN1, EVP_R_DECODE_ERROR);
+ goto end;
+ }
+ }
+ }
+
+ ERR_pop_to_mark();
+ ret = 1;
+ end:
+ OSSL_DECODER_CTX_free(dctx);
+ OPENSSL_free(tmpbuf);
+ return ret;
+}
+
+static int x509_pubkey_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
+ const ASN1_ITEM *it, int tag, int aclass)
+{
+ return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL),
+ tag, aclass);
+}
+
+static int x509_pubkey_ex_print(BIO *out, const ASN1_VALUE **pval, int indent,
+ const char *fname, const ASN1_PCTX *pctx)
+{
+ return ASN1_item_print(out, *pval, indent,
+ ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL), pctx);
+}
+
+static const ASN1_EXTERN_FUNCS x509_pubkey_ff = {
+ NULL,
+ NULL,
+ x509_pubkey_ex_free,
+ 0, /* Default clear behaviour is OK */
+ NULL,
+ x509_pubkey_ex_i2d,
+ x509_pubkey_ex_print,
+ x509_pubkey_ex_new_ex,
+ x509_pubkey_ex_d2i_ex,
+};
+
+IMPLEMENT_EXTERN_ASN1(X509_PUBKEY, V_ASN1_SEQUENCE, x509_pubkey_ff)
IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY)
+X509_PUBKEY *X509_PUBKEY_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
+{
+ X509_PUBKEY *pubkey = NULL;
+
+ pubkey = (X509_PUBKEY *)ASN1_item_new_ex(X509_PUBKEY_it(), libctx, propq);
+ if (!x509_pubkey_set0_libctx(pubkey, libctx, propq)) {
+ X509_PUBKEY_free(pubkey);
+ pubkey = NULL;
+ }
+ return pubkey;
+}
+
+/*
+ * X509_PUBKEY_dup() must be implemented manually, because there is no
+ * support for it in ASN1_EXTERN_FUNCS.
+ */
+X509_PUBKEY *X509_PUBKEY_dup(const X509_PUBKEY *a)
+{
+ X509_PUBKEY *pubkey = OPENSSL_zalloc(sizeof(*pubkey));
+
+ if (pubkey == NULL
+ || !x509_pubkey_set0_libctx(pubkey, a->libctx, a->propq)
+ || (pubkey->algor = X509_ALGOR_dup(a->algor)) == NULL
+ || (pubkey->public_key = ASN1_BIT_STRING_new()) == NULL
+ || !ASN1_BIT_STRING_set(pubkey->public_key,
+ a->public_key->data,
+ a->public_key->length)) {
+ x509_pubkey_ex_free((ASN1_VALUE **)&pubkey,
+ ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL));
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (a->pkey != NULL) {
+ ERR_set_mark();
+ pubkey->pkey = EVP_PKEY_dup(a->pkey);
+ if (pubkey->pkey == NULL) {
+ pubkey->flag_force_legacy = 1;
+ if (x509_pubkey_decode(&pubkey->pkey, pubkey) <= 0) {
+ x509_pubkey_ex_free((ASN1_VALUE **)&pubkey,
+ ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL));
+ ERR_clear_last_mark();
+ return NULL;
+ }
+ }
+ ERR_pop_to_mark();
+ }
+ return pubkey;
+}
+
int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
{
X509_PUBKEY *pk = NULL;
- if (x == NULL)
+ if (x == NULL || pkey == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return 0;
+ }
- if ((pk = X509_PUBKEY_new()) == NULL)
- goto error;
-
- if (pkey->ameth) {
- if (pkey->ameth->pub_encode) {
+ if (pkey->ameth != NULL) {
+ if ((pk = X509_PUBKEY_new()) == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
+ goto error;
+ }
+ if (pkey->ameth->pub_encode != NULL) {
if (!pkey->ameth->pub_encode(pk, pkey)) {
- X509err(X509_F_X509_PUBKEY_SET,
- X509_R_PUBLIC_KEY_ENCODE_ERROR);
+ ERR_raise(ERR_LIB_X509, X509_R_PUBLIC_KEY_ENCODE_ERROR);
goto error;
}
} else {
- X509err(X509_F_X509_PUBKEY_SET, X509_R_METHOD_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_X509, X509_R_METHOD_NOT_SUPPORTED);
goto error;
}
- } else {
- X509err(X509_F_X509_PUBKEY_SET, X509_R_UNSUPPORTED_ALGORITHM);
+ } else if (evp_pkey_is_provided(pkey)) {
+ unsigned char *der = NULL;
+ size_t derlen = 0;
+ OSSL_ENCODER_CTX *ectx =
+ OSSL_ENCODER_CTX_new_for_pkey(pkey, EVP_PKEY_PUBLIC_KEY,
+ "DER", "SubjectPublicKeyInfo",
+ NULL);
+
+ if (OSSL_ENCODER_to_data(ectx, &der, &derlen)) {
+ const unsigned char *pder = der;
+
+ pk = d2i_X509_PUBKEY(NULL, &pder, (long)derlen);
+ }
+
+ OSSL_ENCODER_CTX_free(ectx);
+ OPENSSL_free(der);
+ }
+
+ if (pk == NULL) {
+ ERR_raise(ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM);
goto error;
}
X509_PUBKEY_free(*x);
+ if (!EVP_PKEY_up_ref(pkey)) {
+ ERR_raise(ERR_LIB_X509, ERR_R_INTERNAL_ERROR);
+ goto error;
+ }
*x = pk;
+
+ /*
+ * pk->pkey is NULL when using the legacy routine, but is non-NULL when
+ * going through the encoder, and for all intents and purposes, it's
+ * a perfect copy of the public key portions of |pkey|, just not the same
+ * instance. If that's all there was to pkey then we could simply return
+ * early, right here. However, some application might very well depend on
+ * the passed |pkey| being used and none other, so we spend a few more
+ * cycles throwing away the newly created |pk->pkey| and replace it with
+ * |pkey|.
+ */
+ if (pk->pkey != NULL)
+ EVP_PKEY_free(pk->pkey);
+
pk->pkey = pkey;
- EVP_PKEY_up_ref(pkey);
return 1;
error:
@@ -98,20 +392,36 @@ int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
* Attempt to decode a public key.
* Returns 1 on success, 0 for a decode failure and -1 for a fatal
* error e.g. malloc failure.
+ *
+ * This function is #legacy.
*/
+static int x509_pubkey_decode(EVP_PKEY **ppkey, const X509_PUBKEY *key)
+{
+ EVP_PKEY *pkey;
+ int nid;
+ nid = OBJ_obj2nid(key->algor->algorithm);
+ if (!key->flag_force_legacy) {
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE *e = NULL;
-static int x509_pubkey_decode(EVP_PKEY **ppkey, X509_PUBKEY *key)
-{
- EVP_PKEY *pkey = EVP_PKEY_new();
+ e = ENGINE_get_pkey_meth_engine(nid);
+ if (e == NULL)
+ return 0;
+ ENGINE_finish(e);
+#else
+ return 0;
+#endif
+ }
+ pkey = EVP_PKEY_new();
if (pkey == NULL) {
- X509err(X509_F_X509_PUBKEY_DECODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return -1;
}
- if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(key->algor->algorithm))) {
- X509err(X509_F_X509_PUBKEY_DECODE, X509_R_UNSUPPORTED_ALGORITHM);
+ if (!EVP_PKEY_set_type(pkey, nid)) {
+ ERR_raise(ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM);
goto error;
}
@@ -121,12 +431,10 @@ static int x509_pubkey_decode(EVP_PKEY **ppkey, X509_PUBKEY *key)
* future we could have different return codes for decode
* errors and fatal errors such as malloc failure.
*/
- if (!pkey->ameth->pub_decode(pkey, key)) {
- X509err(X509_F_X509_PUBKEY_DECODE, X509_R_PUBLIC_KEY_DECODE_ERROR);
+ if (!pkey->ameth->pub_decode(pkey, key))
goto error;
- }
} else {
- X509err(X509_F_X509_PUBKEY_DECODE, X509_R_METHOD_NOT_SUPPORTED);
+ ERR_raise(ERR_LIB_X509, X509_R_METHOD_NOT_SUPPORTED);
goto error;
}
@@ -138,110 +446,181 @@ static int x509_pubkey_decode(EVP_PKEY **ppkey, X509_PUBKEY *key)
return 0;
}
-EVP_PKEY *X509_PUBKEY_get0(X509_PUBKEY *key)
+EVP_PKEY *X509_PUBKEY_get0(const X509_PUBKEY *key)
{
- EVP_PKEY *ret = NULL;
-
- if (key == NULL || key->public_key == NULL)
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
+ }
- if (key->pkey != NULL)
- return key->pkey;
-
- /*
- * When the key ASN.1 is initially parsed an attempt is made to
- * decode the public key and cache the EVP_PKEY structure. If this
- * operation fails the cached value will be NULL. Parsing continues
- * to allow parsing of unknown key types or unsupported forms.
- * We repeat the decode operation so the appropriate errors are left
- * in the queue.
- */
- x509_pubkey_decode(&ret, key);
- /* If decode doesn't fail something bad happened */
- if (ret != NULL) {
- X509err(X509_F_X509_PUBKEY_GET0, ERR_R_INTERNAL_ERROR);
- EVP_PKEY_free(ret);
+ if (key->pkey == NULL) {
+ /* We failed to decode the key when we loaded it, or it was never set */
+ ERR_raise(ERR_LIB_EVP, EVP_R_DECODE_ERROR);
+ return NULL;
}
- return NULL;
+ return key->pkey;
}
-EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
+EVP_PKEY *X509_PUBKEY_get(const X509_PUBKEY *key)
{
EVP_PKEY *ret = X509_PUBKEY_get0(key);
if (ret != NULL && !EVP_PKEY_up_ref(ret)) {
- X509err(X509_F_X509_PUBKEY_GET, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_X509, ERR_R_INTERNAL_ERROR);
ret = NULL;
}
return ret;
}
/*
- * Now two pseudo ASN1 routines that take an EVP_PKEY structure and encode or
- * decode as X509_PUBKEY
+ * Now three pseudo ASN1 routines that take an EVP_PKEY structure and encode
+ * or decode as X509_PUBKEY
*/
-
-EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length)
+static EVP_PKEY *d2i_PUBKEY_int(EVP_PKEY **a,
+ const unsigned char **pp, long length,
+ OSSL_LIB_CTX *libctx, const char *propq,
+ unsigned int force_legacy,
+ X509_PUBKEY *
+ (*d2i_x509_pubkey)(X509_PUBKEY **a,
+ const unsigned char **in,
+ long len))
{
- X509_PUBKEY *xpk;
- EVP_PKEY *pktmp;
+ X509_PUBKEY *xpk, *xpk2 = NULL, **pxpk = NULL;
+ EVP_PKEY *pktmp = NULL;
const unsigned char *q;
+
q = *pp;
- xpk = d2i_X509_PUBKEY(NULL, &q, length);
- if (!xpk)
- return NULL;
+
+ /*
+ * If libctx or propq are non-NULL, we take advantage of the reuse
+ * feature. It's not generally recommended, but is safe enough for
+ * newly created structures.
+ */
+ if (libctx != NULL || propq != NULL || force_legacy) {
+ xpk2 = OPENSSL_zalloc(sizeof(*xpk2));
+ if (xpk2 == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ if (!x509_pubkey_set0_libctx(xpk2, libctx, propq))
+ goto end;
+ xpk2->flag_force_legacy = !!force_legacy;
+ pxpk = &xpk2;
+ }
+ xpk = d2i_x509_pubkey(pxpk, &q, length);
+ if (xpk == NULL)
+ goto end;
pktmp = X509_PUBKEY_get(xpk);
X509_PUBKEY_free(xpk);
- if (!pktmp)
- return NULL;
+ xpk2 = NULL; /* We know that xpk == xpk2 */
+ if (pktmp == NULL)
+ goto end;
*pp = q;
- if (a) {
+ if (a != NULL) {
EVP_PKEY_free(*a);
*a = pktmp;
}
+ end:
+ X509_PUBKEY_free(xpk2);
return pktmp;
}
-int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp)
+/* For the algorithm specific d2i functions further down */
+EVP_PKEY *ossl_d2i_PUBKEY_legacy(EVP_PKEY **a, const unsigned char **pp,
+ long length)
{
- X509_PUBKEY *xpk = NULL;
- int ret;
- if (!a)
+ return d2i_PUBKEY_int(a, pp, length, NULL, NULL, 1, d2i_X509_PUBKEY);
+}
+
+EVP_PKEY *d2i_PUBKEY_ex(EVP_PKEY **a, const unsigned char **pp, long length,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ return d2i_PUBKEY_int(a, pp, length, libctx, propq, 0, d2i_X509_PUBKEY);
+}
+
+EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length)
+{
+ return d2i_PUBKEY_ex(a, pp, length, NULL, NULL);
+}
+
+int i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp)
+{
+ int ret = -1;
+
+ if (a == NULL)
return 0;
- if (!X509_PUBKEY_set(&xpk, a))
- return -1;
- ret = i2d_X509_PUBKEY(xpk, pp);
- X509_PUBKEY_free(xpk);
+ if (a->ameth != NULL) {
+ X509_PUBKEY *xpk = NULL;
+
+ if ((xpk = X509_PUBKEY_new()) == NULL)
+ return -1;
+
+ /* pub_encode() only encode parameters, not the key itself */
+ if (a->ameth->pub_encode != NULL && a->ameth->pub_encode(xpk, a)) {
+ xpk->pkey = (EVP_PKEY *)a;
+ ret = i2d_X509_PUBKEY(xpk, pp);
+ xpk->pkey = NULL;
+ }
+ X509_PUBKEY_free(xpk);
+ } else if (a->keymgmt != NULL) {
+ OSSL_ENCODER_CTX *ctx =
+ OSSL_ENCODER_CTX_new_for_pkey(a, EVP_PKEY_PUBLIC_KEY,
+ "DER", "SubjectPublicKeyInfo",
+ NULL);
+ BIO *out = BIO_new(BIO_s_mem());
+ BUF_MEM *buf = NULL;
+
+ if (OSSL_ENCODER_CTX_get_num_encoders(ctx) != 0
+ && out != NULL
+ && OSSL_ENCODER_to_bio(ctx, out)
+ && BIO_get_mem_ptr(out, &buf) > 0) {
+ ret = buf->length;
+
+ if (pp != NULL) {
+ if (*pp == NULL) {
+ *pp = (unsigned char *)buf->data;
+ buf->length = 0;
+ buf->data = NULL;
+ } else {
+ memcpy(*pp, buf->data, ret);
+ *pp += ret;
+ }
+ }
+ }
+ BIO_free(out);
+ OSSL_ENCODER_CTX_free(ctx);
+ }
+
return ret;
}
/*
* The following are equivalents but which return RSA and DSA keys
*/
-#ifndef OPENSSL_NO_RSA
RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length)
{
EVP_PKEY *pkey;
- RSA *key;
+ RSA *key = NULL;
const unsigned char *q;
+
q = *pp;
- pkey = d2i_PUBKEY(NULL, &q, length);
- if (!pkey)
+ pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
+ if (pkey == NULL)
return NULL;
key = EVP_PKEY_get1_RSA(pkey);
EVP_PKEY_free(pkey);
- if (!key)
+ if (key == NULL)
return NULL;
*pp = q;
- if (a) {
+ if (a != NULL) {
RSA_free(*a);
*a = key;
}
return key;
}
-int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp)
+int i2d_RSA_PUBKEY(const RSA *a, unsigned char **pp)
{
EVP_PKEY *pktmp;
int ret;
@@ -249,11 +628,95 @@ int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp)
return 0;
pktmp = EVP_PKEY_new();
if (pktmp == NULL) {
- ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
- EVP_PKEY_set1_RSA(pktmp, a);
+ (void)EVP_PKEY_assign_RSA(pktmp, (RSA *)a);
ret = i2d_PUBKEY(pktmp, pp);
+ pktmp->pkey.ptr = NULL;
+ EVP_PKEY_free(pktmp);
+ return ret;
+}
+
+#ifndef OPENSSL_NO_DH
+DH *ossl_d2i_DH_PUBKEY(DH **a, const unsigned char **pp, long length)
+{
+ EVP_PKEY *pkey;
+ DH *key = NULL;
+ const unsigned char *q;
+
+ q = *pp;
+ pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
+ if (pkey == NULL)
+ return NULL;
+ if (EVP_PKEY_get_id(pkey) == EVP_PKEY_DH)
+ key = EVP_PKEY_get1_DH(pkey);
+ EVP_PKEY_free(pkey);
+ if (key == NULL)
+ return NULL;
+ *pp = q;
+ if (a != NULL) {
+ DH_free(*a);
+ *a = key;
+ }
+ return key;
+}
+
+int ossl_i2d_DH_PUBKEY(const DH *a, unsigned char **pp)
+{
+ EVP_PKEY *pktmp;
+ int ret;
+ if (!a)
+ return 0;
+ pktmp = EVP_PKEY_new();
+ if (pktmp == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ (void)EVP_PKEY_assign_DH(pktmp, (DH *)a);
+ ret = i2d_PUBKEY(pktmp, pp);
+ pktmp->pkey.ptr = NULL;
+ EVP_PKEY_free(pktmp);
+ return ret;
+}
+
+DH *ossl_d2i_DHx_PUBKEY(DH **a, const unsigned char **pp, long length)
+{
+ EVP_PKEY *pkey;
+ DH *key = NULL;
+ const unsigned char *q;
+
+ q = *pp;
+ pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
+ if (pkey == NULL)
+ return NULL;
+ if (EVP_PKEY_get_id(pkey) == EVP_PKEY_DHX)
+ key = EVP_PKEY_get1_DH(pkey);
+ EVP_PKEY_free(pkey);
+ if (key == NULL)
+ return NULL;
+ *pp = q;
+ if (a != NULL) {
+ DH_free(*a);
+ *a = key;
+ }
+ return key;
+}
+
+int ossl_i2d_DHx_PUBKEY(const DH *a, unsigned char **pp)
+{
+ EVP_PKEY *pktmp;
+ int ret;
+ if (!a)
+ return 0;
+ pktmp = EVP_PKEY_new();
+ if (pktmp == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ (void)EVP_PKEY_assign(pktmp, EVP_PKEY_DHX, (DH *)a);
+ ret = i2d_PUBKEY(pktmp, pp);
+ pktmp->pkey.ptr = NULL;
EVP_PKEY_free(pktmp);
return ret;
}
@@ -263,25 +726,50 @@ int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp)
DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length)
{
EVP_PKEY *pkey;
- DSA *key;
+ DSA *key = NULL;
const unsigned char *q;
+
q = *pp;
- pkey = d2i_PUBKEY(NULL, &q, length);
- if (!pkey)
+ pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
+ if (pkey == NULL)
return NULL;
key = EVP_PKEY_get1_DSA(pkey);
EVP_PKEY_free(pkey);
- if (!key)
+ if (key == NULL)
return NULL;
*pp = q;
- if (a) {
+ if (a != NULL) {
+ DSA_free(*a);
+ *a = key;
+ }
+ return key;
+}
+
+/* Called from decoders; disallows provided DSA keys without parameters. */
+DSA *ossl_d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length)
+{
+ DSA *key = NULL;
+ const unsigned char *data;
+ const BIGNUM *p, *q, *g;
+
+ data = *pp;
+ key = d2i_DSA_PUBKEY(NULL, &data, length);
+ if (key == NULL)
+ return NULL;
+ DSA_get0_pqg(key, &p, &q, &g);
+ if (p == NULL || q == NULL || g == NULL) {
+ DSA_free(key);
+ return NULL;
+ }
+ *pp = data;
+ if (a != NULL) {
DSA_free(*a);
*a = key;
}
return key;
}
-int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp)
+int i2d_DSA_PUBKEY(const DSA *a, unsigned char **pp)
{
EVP_PKEY *pktmp;
int ret;
@@ -289,11 +777,12 @@ int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp)
return 0;
pktmp = EVP_PKEY_new();
if (pktmp == NULL) {
- ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
- EVP_PKEY_set1_DSA(pktmp, a);
+ (void)EVP_PKEY_assign_DSA(pktmp, (DSA *)a);
ret = i2d_PUBKEY(pktmp, pp);
+ pktmp->pkey.ptr = NULL;
EVP_PKEY_free(pktmp);
return ret;
}
@@ -303,39 +792,213 @@ int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp)
EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
{
EVP_PKEY *pkey;
- EC_KEY *key;
+ EC_KEY *key = NULL;
const unsigned char *q;
+ int type;
+
q = *pp;
- pkey = d2i_PUBKEY(NULL, &q, length);
- if (!pkey)
+ pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
+ if (pkey == NULL)
return NULL;
- key = EVP_PKEY_get1_EC_KEY(pkey);
+ type = EVP_PKEY_get_id(pkey);
+ if (type == EVP_PKEY_EC || type == EVP_PKEY_SM2)
+ key = EVP_PKEY_get1_EC_KEY(pkey);
EVP_PKEY_free(pkey);
- if (!key)
+ if (key == NULL)
return NULL;
*pp = q;
- if (a) {
+ if (a != NULL) {
EC_KEY_free(*a);
*a = key;
}
return key;
}
-int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp)
+int i2d_EC_PUBKEY(const EC_KEY *a, unsigned char **pp)
{
EVP_PKEY *pktmp;
int ret;
- if (!a)
+
+ if (a == NULL)
return 0;
if ((pktmp = EVP_PKEY_new()) == NULL) {
- ASN1err(ASN1_F_I2D_EC_PUBKEY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
- EVP_PKEY_set1_EC_KEY(pktmp, a);
+ (void)EVP_PKEY_assign_EC_KEY(pktmp, (EC_KEY *)a);
ret = i2d_PUBKEY(pktmp, pp);
+ pktmp->pkey.ptr = NULL;
EVP_PKEY_free(pktmp);
return ret;
}
+
+ECX_KEY *ossl_d2i_ED25519_PUBKEY(ECX_KEY **a,
+ const unsigned char **pp, long length)
+{
+ EVP_PKEY *pkey;
+ ECX_KEY *key = NULL;
+ const unsigned char *q;
+
+ q = *pp;
+ pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
+ if (pkey == NULL)
+ return NULL;
+ key = ossl_evp_pkey_get1_ED25519(pkey);
+ EVP_PKEY_free(pkey);
+ if (key == NULL)
+ return NULL;
+ *pp = q;
+ if (a != NULL) {
+ ossl_ecx_key_free(*a);
+ *a = key;
+ }
+ return key;
+}
+
+int ossl_i2d_ED25519_PUBKEY(const ECX_KEY *a, unsigned char **pp)
+{
+ EVP_PKEY *pktmp;
+ int ret;
+
+ if (a == NULL)
+ return 0;
+ if ((pktmp = EVP_PKEY_new()) == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ (void)EVP_PKEY_assign(pktmp, EVP_PKEY_ED25519, (ECX_KEY *)a);
+ ret = i2d_PUBKEY(pktmp, pp);
+ pktmp->pkey.ptr = NULL;
+ EVP_PKEY_free(pktmp);
+ return ret;
+}
+
+ECX_KEY *ossl_d2i_ED448_PUBKEY(ECX_KEY **a,
+ const unsigned char **pp, long length)
+{
+ EVP_PKEY *pkey;
+ ECX_KEY *key = NULL;
+ const unsigned char *q;
+
+ q = *pp;
+ pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
+ if (pkey == NULL)
+ return NULL;
+ if (EVP_PKEY_get_id(pkey) == EVP_PKEY_ED448)
+ key = ossl_evp_pkey_get1_ED448(pkey);
+ EVP_PKEY_free(pkey);
+ if (key == NULL)
+ return NULL;
+ *pp = q;
+ if (a != NULL) {
+ ossl_ecx_key_free(*a);
+ *a = key;
+ }
+ return key;
+}
+
+int ossl_i2d_ED448_PUBKEY(const ECX_KEY *a, unsigned char **pp)
+{
+ EVP_PKEY *pktmp;
+ int ret;
+
+ if (a == NULL)
+ return 0;
+ if ((pktmp = EVP_PKEY_new()) == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ (void)EVP_PKEY_assign(pktmp, EVP_PKEY_ED448, (ECX_KEY *)a);
+ ret = i2d_PUBKEY(pktmp, pp);
+ pktmp->pkey.ptr = NULL;
+ EVP_PKEY_free(pktmp);
+ return ret;
+}
+
+ECX_KEY *ossl_d2i_X25519_PUBKEY(ECX_KEY **a,
+ const unsigned char **pp, long length)
+{
+ EVP_PKEY *pkey;
+ ECX_KEY *key = NULL;
+ const unsigned char *q;
+
+ q = *pp;
+ pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
+ if (pkey == NULL)
+ return NULL;
+ if (EVP_PKEY_get_id(pkey) == EVP_PKEY_X25519)
+ key = ossl_evp_pkey_get1_X25519(pkey);
+ EVP_PKEY_free(pkey);
+ if (key == NULL)
+ return NULL;
+ *pp = q;
+ if (a != NULL) {
+ ossl_ecx_key_free(*a);
+ *a = key;
+ }
+ return key;
+}
+
+int ossl_i2d_X25519_PUBKEY(const ECX_KEY *a, unsigned char **pp)
+{
+ EVP_PKEY *pktmp;
+ int ret;
+
+ if (a == NULL)
+ return 0;
+ if ((pktmp = EVP_PKEY_new()) == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ (void)EVP_PKEY_assign(pktmp, EVP_PKEY_X25519, (ECX_KEY *)a);
+ ret = i2d_PUBKEY(pktmp, pp);
+ pktmp->pkey.ptr = NULL;
+ EVP_PKEY_free(pktmp);
+ return ret;
+}
+
+ECX_KEY *ossl_d2i_X448_PUBKEY(ECX_KEY **a,
+ const unsigned char **pp, long length)
+{
+ EVP_PKEY *pkey;
+ ECX_KEY *key = NULL;
+ const unsigned char *q;
+
+ q = *pp;
+ pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
+ if (pkey == NULL)
+ return NULL;
+ if (EVP_PKEY_get_id(pkey) == EVP_PKEY_X448)
+ key = ossl_evp_pkey_get1_X448(pkey);
+ EVP_PKEY_free(pkey);
+ if (key == NULL)
+ return NULL;
+ *pp = q;
+ if (a != NULL) {
+ ossl_ecx_key_free(*a);
+ *a = key;
+ }
+ return key;
+}
+
+int ossl_i2d_X448_PUBKEY(const ECX_KEY *a, unsigned char **pp)
+{
+ EVP_PKEY *pktmp;
+ int ret;
+
+ if (a == NULL)
+ return 0;
+ if ((pktmp = EVP_PKEY_new()) == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ (void)EVP_PKEY_assign(pktmp, EVP_PKEY_X448, (ECX_KEY *)a);
+ ret = i2d_PUBKEY(pktmp, pp);
+ pktmp->pkey.ptr = NULL;
+ EVP_PKEY_free(pktmp);
+ return ret;
+}
+
#endif
int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj,
@@ -357,7 +1020,7 @@ int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj,
int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg,
const unsigned char **pk, int *ppklen,
- X509_ALGOR **pa, X509_PUBKEY *pub)
+ X509_ALGOR **pa, const X509_PUBKEY *pub)
{
if (ppkalg)
*ppkalg = pub->algor->algorithm;
@@ -376,3 +1039,34 @@ ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x)
return NULL;
return x->cert_info.key->public_key;
}
+
+/* Returns 1 for equal, 0, for non-equal, < 0 on error */
+int X509_PUBKEY_eq(const X509_PUBKEY *a, const X509_PUBKEY *b)
+{
+ X509_ALGOR *algA, *algB;
+ EVP_PKEY *pA, *pB;
+
+ if (a == b)
+ return 1;
+ if (a == NULL || b == NULL)
+ return 0;
+ if (!X509_PUBKEY_get0_param(NULL, NULL, NULL, &algA, a) || algA == NULL
+ || !X509_PUBKEY_get0_param(NULL, NULL, NULL, &algB, b) || algB == NULL)
+ return -2;
+ if (X509_ALGOR_cmp(algA, algB) != 0)
+ return 0;
+ if ((pA = X509_PUBKEY_get0(a)) == NULL
+ || (pB = X509_PUBKEY_get0(b)) == NULL)
+ return -2;
+ return EVP_PKEY_eq(pA, pB);
+}
+
+int ossl_x509_PUBKEY_get0_libctx(OSSL_LIB_CTX **plibctx, const char **ppropq,
+ const X509_PUBKEY *key)
+{
+ if (plibctx)
+ *plibctx = key->libctx;
+ if (ppropq)
+ *ppropq = key->propq;
+ return 1;
+}
diff --git a/crypto/x509/x_req.c b/crypto/x509/x_req.c
index d2b02f6dae86..293d4be71335 100644
--- a/crypto/x509/x_req.c
+++ b/crypto/x509/x_req.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -45,6 +45,67 @@ static int rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
return 1;
}
+static int req_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ void *exarg)
+{
+ X509_REQ *ret = (X509_REQ *)*pval;
+
+ switch (operation) {
+ case ASN1_OP_D2I_PRE:
+ ASN1_OCTET_STRING_free(ret->distinguishing_id);
+ /* fall thru */
+ case ASN1_OP_NEW_POST:
+ ret->distinguishing_id = NULL;
+ break;
+
+ case ASN1_OP_FREE_POST:
+ ASN1_OCTET_STRING_free(ret->distinguishing_id);
+ OPENSSL_free(ret->propq);
+ break;
+ case ASN1_OP_DUP_POST:
+ {
+ X509_REQ *old = exarg;
+
+ if (!ossl_x509_req_set0_libctx(ret, old->libctx, old->propq))
+ return 0;
+ if (old->req_info.pubkey != NULL) {
+ EVP_PKEY *pkey = X509_PUBKEY_get0(old->req_info.pubkey);
+
+ if (pkey != NULL) {
+ pkey = EVP_PKEY_dup(pkey);
+ if (pkey == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (!X509_PUBKEY_set(&ret->req_info.pubkey, pkey)) {
+ EVP_PKEY_free(pkey);
+ ERR_raise(ERR_LIB_X509, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ EVP_PKEY_free(pkey);
+ }
+ }
+ }
+ break;
+ case ASN1_OP_GET0_LIBCTX:
+ {
+ OSSL_LIB_CTX **libctx = exarg;
+
+ *libctx = ret->libctx;
+ }
+ break;
+ case ASN1_OP_GET0_PROPQ:
+ {
+ const char **propq = exarg;
+
+ *propq = ret->propq;
+ }
+ break;
+ }
+
+ return 1;
+}
+
ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = {
ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER),
ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME),
@@ -57,7 +118,7 @@ ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = {
IMPLEMENT_ASN1_FUNCTIONS(X509_REQ_INFO)
-ASN1_SEQUENCE_ref(X509_REQ, 0) = {
+ASN1_SEQUENCE_ref(X509_REQ, req_cb) = {
ASN1_EMBED(X509_REQ, req_info, X509_REQ_INFO),
ASN1_EMBED(X509_REQ, sig_alg, X509_ALGOR),
ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING)
@@ -66,3 +127,47 @@ ASN1_SEQUENCE_ref(X509_REQ, 0) = {
IMPLEMENT_ASN1_FUNCTIONS(X509_REQ)
IMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ)
+
+void X509_REQ_set0_distinguishing_id(X509_REQ *x, ASN1_OCTET_STRING *d_id)
+{
+ ASN1_OCTET_STRING_free(x->distinguishing_id);
+ x->distinguishing_id = d_id;
+}
+
+ASN1_OCTET_STRING *X509_REQ_get0_distinguishing_id(X509_REQ *x)
+{
+ return x->distinguishing_id;
+}
+
+/*
+ * This should only be used if the X509_REQ object was embedded inside another
+ * asn1 object and it needs a libctx to operate.
+ * Use X509_REQ_new_ex() instead if possible.
+ */
+int ossl_x509_req_set0_libctx(X509_REQ *x, OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ if (x != NULL) {
+ x->libctx = libctx;
+ OPENSSL_free(x->propq);
+ x->propq = NULL;
+ if (propq != NULL) {
+ x->propq = OPENSSL_strdup(propq);
+ if (x->propq == NULL)
+ return 0;
+ }
+ }
+ return 1;
+}
+
+X509_REQ *X509_REQ_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
+{
+ X509_REQ *req = NULL;
+
+ req = (X509_REQ *)ASN1_item_new((X509_REQ_it()));
+ if (!ossl_x509_req_set0_libctx(req, libctx, propq)) {
+ X509_REQ_free(req);
+ req = NULL;
+ }
+ return req;
+}
diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c
index 7aa8b77ae73a..010578b19a31 100644
--- a/crypto/x509/x_x509.c
+++ b/crypto/x509/x_x509.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -31,7 +31,7 @@ ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = {
IMPLEMENT_ASN1_FUNCTIONS(X509_CINF)
/* X509 top level structure needs a bit of customisation */
-extern void policy_cache_free(X509_POLICY_CACHE *cache);
+extern void ossl_policy_cache_free(X509_POLICY_CACHE *cache);
static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
@@ -46,13 +46,14 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
ASN1_OCTET_STRING_free(ret->skid);
AUTHORITY_KEYID_free(ret->akid);
CRL_DIST_POINTS_free(ret->crldp);
- policy_cache_free(ret->policy_cache);
+ ossl_policy_cache_free(ret->policy_cache);
GENERAL_NAMES_free(ret->altname);
NAME_CONSTRAINTS_free(ret->nc);
#ifndef OPENSSL_NO_RFC3779
sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free);
ASIdentifiers_free(ret->rfc3779_asid);
#endif
+ ASN1_OCTET_STRING_free(ret->distinguishing_id);
/* fall thru */
@@ -73,6 +74,7 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
ret->rfc3779_addr = NULL;
ret->rfc3779_asid = NULL;
#endif
+ ret->distinguishing_id = NULL;
ret->aux = NULL;
ret->crldp = NULL;
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data))
@@ -85,19 +87,46 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
ASN1_OCTET_STRING_free(ret->skid);
AUTHORITY_KEYID_free(ret->akid);
CRL_DIST_POINTS_free(ret->crldp);
- policy_cache_free(ret->policy_cache);
+ ossl_policy_cache_free(ret->policy_cache);
GENERAL_NAMES_free(ret->altname);
NAME_CONSTRAINTS_free(ret->nc);
#ifndef OPENSSL_NO_RFC3779
sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free);
ASIdentifiers_free(ret->rfc3779_asid);
#endif
+ ASN1_OCTET_STRING_free(ret->distinguishing_id);
+ OPENSSL_free(ret->propq);
break;
+ case ASN1_OP_DUP_POST:
+ {
+ X509 *old = exarg;
+
+ if (!ossl_x509_set0_libctx(ret, old->libctx, old->propq))
+ return 0;
+ }
+ break;
+ case ASN1_OP_GET0_LIBCTX:
+ {
+ OSSL_LIB_CTX **libctx = exarg;
+
+ *libctx = ret->libctx;
+ }
+ break;
+
+ case ASN1_OP_GET0_PROPQ:
+ {
+ const char **propq = exarg;
+
+ *propq = ret->propq;
+ }
+ break;
+
+ default:
+ break;
}
return 1;
-
}
ASN1_SEQUENCE_ref(X509, x509_cb) = {
@@ -107,15 +136,46 @@ ASN1_SEQUENCE_ref(X509, x509_cb) = {
} ASN1_SEQUENCE_END_ref(X509, X509)
IMPLEMENT_ASN1_FUNCTIONS(X509)
-
IMPLEMENT_ASN1_DUP_FUNCTION(X509)
+/*
+ * This should only be used if the X509 object was embedded inside another
+ * asn1 object and it needs a libctx to operate.
+ * Use X509_new_ex() instead if possible.
+ */
+int ossl_x509_set0_libctx(X509 *x, OSSL_LIB_CTX *libctx, const char *propq)
+{
+ if (x != NULL) {
+ x->libctx = libctx;
+ OPENSSL_free(x->propq);
+ x->propq = NULL;
+ if (propq != NULL) {
+ x->propq = OPENSSL_strdup(propq);
+ if (x->propq == NULL)
+ return 0;
+ }
+ }
+ return 1;
+}
+
+X509 *X509_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
+{
+ X509 *cert = NULL;
+
+ cert = (X509 *)ASN1_item_new_ex(X509_it(), libctx, propq);
+ if (!ossl_x509_set0_libctx(cert, libctx, propq)) {
+ X509_free(cert);
+ cert = NULL;
+ }
+ return cert;
+}
+
int X509_set_ex_data(X509 *r, int idx, void *arg)
{
return CRYPTO_set_ex_data(&r->ex_data, idx, arg);
}
-void *X509_get_ex_data(X509 *r, int idx)
+void *X509_get_ex_data(const X509 *r, int idx)
{
return CRYPTO_get_ex_data(&r->ex_data, idx);
}
@@ -163,7 +223,7 @@ X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length)
* error path, but that depends on similar hygiene in lower-level functions.
* Here we avoid compounding the problem.
*/
-static int i2d_x509_aux_internal(X509 *a, unsigned char **pp)
+static int i2d_x509_aux_internal(const X509 *a, unsigned char **pp)
{
int length, tmplen;
unsigned char *start = pp != NULL ? *pp : NULL;
@@ -197,7 +257,7 @@ static int i2d_x509_aux_internal(X509 *a, unsigned char **pp)
* the allocation, nor can we allow i2d_X509_CERT_AUX() to increment the
* allocated buffer.
*/
-int i2d_X509_AUX(X509 *a, unsigned char **pp)
+int i2d_X509_AUX(const X509 *a, unsigned char **pp)
{
int length;
unsigned char *tmp;
@@ -213,7 +273,7 @@ int i2d_X509_AUX(X509 *a, unsigned char **pp)
/* Allocate requisite combined storage */
*pp = tmp = OPENSSL_malloc(length);
if (tmp == NULL) {
- X509err(X509_F_I2D_X509_AUX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return -1;
}
@@ -245,3 +305,14 @@ int X509_get_signature_nid(const X509 *x)
{
return OBJ_obj2nid(x->sig_alg.algorithm);
}
+
+void X509_set0_distinguishing_id(X509 *x, ASN1_OCTET_STRING *d_id)
+{
+ ASN1_OCTET_STRING_free(x->distinguishing_id);
+ x->distinguishing_id = d_id;
+}
+
+ASN1_OCTET_STRING *X509_get0_distinguishing_id(X509 *x)
+{
+ return x->distinguishing_id;
+}
diff --git a/crypto/x509/x_x509a.c b/crypto/x509/x_x509a.c
index c5175faef7af..f7953c269e7c 100644
--- a/crypto/x509/x_x509a.c
+++ b/crypto/x509/x_x509a.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -125,6 +125,8 @@ int X509_add1_reject_object(X509 *x, const ASN1_OBJECT *obj)
{
X509_CERT_AUX *aux;
ASN1_OBJECT *objtmp;
+ int res = 0;
+
if ((objtmp = OBJ_dup(obj)) == NULL)
return 0;
if ((aux = aux_get(x)) == NULL)
@@ -132,10 +134,13 @@ int X509_add1_reject_object(X509 *x, const ASN1_OBJECT *obj)
if (aux->reject == NULL
&& (aux->reject = sk_ASN1_OBJECT_new_null()) == NULL)
goto err;
- return sk_ASN1_OBJECT_push(aux->reject, objtmp);
+ if (sk_ASN1_OBJECT_push(aux->reject, objtmp) > 0)
+ res = 1;
+
err:
- ASN1_OBJECT_free(objtmp);
- return 0;
+ if (!res)
+ ASN1_OBJECT_free(objtmp);
+ return res;
}
void X509_trust_clear(X509 *x)
diff --git a/crypto/x509v3/build.info b/crypto/x509v3/build.info
deleted file mode 100644
index 4ab648849367..000000000000
--- a/crypto/x509v3/build.info
+++ /dev/null
@@ -1,8 +0,0 @@
-LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
- v3_bcons.c v3_bitst.c v3_conf.c v3_extku.c v3_ia5.c v3_lib.c \
- v3_prn.c v3_utl.c v3err.c v3_genn.c v3_alt.c v3_skey.c v3_akey.c v3_pku.c \
- v3_int.c v3_enum.c v3_sxnet.c v3_cpols.c v3_crld.c v3_purp.c v3_info.c \
- v3_akeya.c v3_pmaps.c v3_pcons.c v3_ncons.c v3_pcia.c v3_pci.c \
- pcy_cache.c pcy_node.c pcy_data.c pcy_map.c pcy_tree.c pcy_lib.c \
- v3_asid.c v3_addr.c v3_tlsf.c v3_admis.c
diff --git a/crypto/x509v3/ext_dat.h b/crypto/x509v3/ext_dat.h
deleted file mode 100644
index 762e264bb22d..000000000000
--- a/crypto/x509v3/ext_dat.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-int name_cmp(const char *name, const char *cmp);
-
-extern const X509V3_EXT_METHOD v3_bcons, v3_nscert, v3_key_usage, v3_ext_ku;
-extern const X509V3_EXT_METHOD v3_pkey_usage_period, v3_sxnet, v3_info, v3_sinfo;
-extern const X509V3_EXT_METHOD v3_ns_ia5_list[8], v3_alt[3], v3_skey_id, v3_akey_id;
-extern const X509V3_EXT_METHOD v3_crl_num, v3_crl_reason, v3_crl_invdate;
-extern const X509V3_EXT_METHOD v3_delta_crl, v3_cpols, v3_crld, v3_freshest_crl;
-extern const X509V3_EXT_METHOD v3_ocsp_nonce, v3_ocsp_accresp, v3_ocsp_acutoff;
-extern const X509V3_EXT_METHOD v3_ocsp_crlid, v3_ocsp_nocheck, v3_ocsp_serviceloc;
-extern const X509V3_EXT_METHOD v3_crl_hold, v3_pci;
-extern const X509V3_EXT_METHOD v3_policy_mappings, v3_policy_constraints;
-extern const X509V3_EXT_METHOD v3_name_constraints, v3_inhibit_anyp, v3_idp;
-extern const X509V3_EXT_METHOD v3_addr, v3_asid;
-extern const X509V3_EXT_METHOD v3_ct_scts[3];
-extern const X509V3_EXT_METHOD v3_tls_feature;
-extern const X509V3_EXT_METHOD v3_ext_admission;
diff --git a/crypto/x509v3/pcy_cache.c b/crypto/x509v3/pcy_cache.c
deleted file mode 100644
index 04401bace8c5..000000000000
--- a/crypto/x509v3/pcy_cache.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "internal/cryptlib.h"
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-#include "crypto/x509.h"
-
-#include "pcy_local.h"
-
-static int policy_data_cmp(const X509_POLICY_DATA *const *a,
- const X509_POLICY_DATA *const *b);
-static int policy_cache_set_int(long *out, ASN1_INTEGER *value);
-
-/*
- * Set cache entry according to CertificatePolicies extension. Note: this
- * destroys the passed CERTIFICATEPOLICIES structure.
- */
-
-static int policy_cache_create(X509 *x,
- CERTIFICATEPOLICIES *policies, int crit)
-{
- int i, num, ret = 0;
- X509_POLICY_CACHE *cache = x->policy_cache;
- X509_POLICY_DATA *data = NULL;
- POLICYINFO *policy;
-
- if ((num = sk_POLICYINFO_num(policies)) <= 0)
- goto bad_policy;
- cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp);
- if (cache->data == NULL) {
- X509V3err(X509V3_F_POLICY_CACHE_CREATE, ERR_R_MALLOC_FAILURE);
- goto just_cleanup;
- }
- for (i = 0; i < num; i++) {
- policy = sk_POLICYINFO_value(policies, i);
- data = policy_data_new(policy, NULL, crit);
- if (data == NULL) {
- X509V3err(X509V3_F_POLICY_CACHE_CREATE, ERR_R_MALLOC_FAILURE);
- goto just_cleanup;
- }
- /*
- * Duplicate policy OIDs are illegal: reject if matches found.
- */
- if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
- if (cache->anyPolicy) {
- ret = -1;
- goto bad_policy;
- }
- cache->anyPolicy = data;
- } else if (sk_X509_POLICY_DATA_find(cache->data, data) >=0 ) {
- ret = -1;
- goto bad_policy;
- } else if (!sk_X509_POLICY_DATA_push(cache->data, data)) {
- X509V3err(X509V3_F_POLICY_CACHE_CREATE, ERR_R_MALLOC_FAILURE);
- goto bad_policy;
- }
- data = NULL;
- }
- ret = 1;
-
- bad_policy:
- if (ret == -1)
- x->ex_flags |= EXFLAG_INVALID_POLICY;
- policy_data_free(data);
- just_cleanup:
- sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
- if (ret <= 0) {
- sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
- cache->data = NULL;
- }
- return ret;
-}
-
-static int policy_cache_new(X509 *x)
-{
- X509_POLICY_CACHE *cache;
- ASN1_INTEGER *ext_any = NULL;
- POLICY_CONSTRAINTS *ext_pcons = NULL;
- CERTIFICATEPOLICIES *ext_cpols = NULL;
- POLICY_MAPPINGS *ext_pmaps = NULL;
- int i;
-
- if (x->policy_cache != NULL)
- return 1;
- cache = OPENSSL_malloc(sizeof(*cache));
- if (cache == NULL) {
- X509V3err(X509V3_F_POLICY_CACHE_NEW, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- cache->anyPolicy = NULL;
- cache->data = NULL;
- cache->any_skip = -1;
- cache->explicit_skip = -1;
- cache->map_skip = -1;
-
- x->policy_cache = cache;
-
- /*
- * Handle requireExplicitPolicy *first*. Need to process this even if we
- * don't have any policies.
- */
- ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL);
-
- if (!ext_pcons) {
- if (i != -1)
- goto bad_cache;
- } else {
- if (!ext_pcons->requireExplicitPolicy
- && !ext_pcons->inhibitPolicyMapping)
- goto bad_cache;
- if (!policy_cache_set_int(&cache->explicit_skip,
- ext_pcons->requireExplicitPolicy))
- goto bad_cache;
- if (!policy_cache_set_int(&cache->map_skip,
- ext_pcons->inhibitPolicyMapping))
- goto bad_cache;
- }
-
- /* Process CertificatePolicies */
-
- ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL);
- /*
- * If no CertificatePolicies extension or problem decoding then there is
- * no point continuing because the valid policies will be NULL.
- */
- if (!ext_cpols) {
- /* If not absent some problem with extension */
- if (i != -1)
- goto bad_cache;
- return 1;
- }
-
- i = policy_cache_create(x, ext_cpols, i);
-
- /* NB: ext_cpols freed by policy_cache_set_policies */
-
- if (i <= 0)
- return i;
-
- ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL);
-
- if (!ext_pmaps) {
- /* If not absent some problem with extension */
- if (i != -1)
- goto bad_cache;
- } else {
- i = policy_cache_set_mapping(x, ext_pmaps);
- if (i <= 0)
- goto bad_cache;
- }
-
- ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL);
-
- if (!ext_any) {
- if (i != -1)
- goto bad_cache;
- } else if (!policy_cache_set_int(&cache->any_skip, ext_any))
- goto bad_cache;
- goto just_cleanup;
-
- bad_cache:
- x->ex_flags |= EXFLAG_INVALID_POLICY;
-
- just_cleanup:
- POLICY_CONSTRAINTS_free(ext_pcons);
- ASN1_INTEGER_free(ext_any);
- return 1;
-
-}
-
-void policy_cache_free(X509_POLICY_CACHE *cache)
-{
- if (!cache)
- return;
- policy_data_free(cache->anyPolicy);
- sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
- OPENSSL_free(cache);
-}
-
-const X509_POLICY_CACHE *policy_cache_set(X509 *x)
-{
-
- if (x->policy_cache == NULL) {
- CRYPTO_THREAD_write_lock(x->lock);
- policy_cache_new(x);
- CRYPTO_THREAD_unlock(x->lock);
- }
-
- return x->policy_cache;
-
-}
-
-X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache,
- const ASN1_OBJECT *id)
-{
- int idx;
- X509_POLICY_DATA tmp;
- tmp.valid_policy = (ASN1_OBJECT *)id;
- idx = sk_X509_POLICY_DATA_find(cache->data, &tmp);
- return sk_X509_POLICY_DATA_value(cache->data, idx);
-}
-
-static int policy_data_cmp(const X509_POLICY_DATA *const *a,
- const X509_POLICY_DATA *const *b)
-{
- return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy);
-}
-
-static int policy_cache_set_int(long *out, ASN1_INTEGER *value)
-{
- if (value == NULL)
- return 1;
- if (value->type == V_ASN1_NEG_INTEGER)
- return 0;
- *out = ASN1_INTEGER_get(value);
- return 1;
-}
diff --git a/crypto/x509v3/pcy_data.c b/crypto/x509v3/pcy_data.c
deleted file mode 100644
index 8c7bc69576a4..000000000000
--- a/crypto/x509v3/pcy_data.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "internal/cryptlib.h"
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-
-#include "pcy_local.h"
-
-/* Policy Node routines */
-
-void policy_data_free(X509_POLICY_DATA *data)
-{
- if (data == NULL)
- return;
- ASN1_OBJECT_free(data->valid_policy);
- /* Don't free qualifiers if shared */
- if (!(data->flags & POLICY_DATA_FLAG_SHARED_QUALIFIERS))
- sk_POLICYQUALINFO_pop_free(data->qualifier_set, POLICYQUALINFO_free);
- sk_ASN1_OBJECT_pop_free(data->expected_policy_set, ASN1_OBJECT_free);
- OPENSSL_free(data);
-}
-
-/*
- * Create a data based on an existing policy. If 'id' is NULL use the OID in
- * the policy, otherwise use 'id'. This behaviour covers the two types of
- * data in RFC3280: data with from a CertificatePolicies extension and
- * additional data with just the qualifiers of anyPolicy and ID from another
- * source.
- */
-
-X509_POLICY_DATA *policy_data_new(POLICYINFO *policy,
- const ASN1_OBJECT *cid, int crit)
-{
- X509_POLICY_DATA *ret;
- ASN1_OBJECT *id;
-
- if (policy == NULL && cid == NULL)
- return NULL;
- if (cid) {
- id = OBJ_dup(cid);
- if (id == NULL)
- return NULL;
- } else
- id = NULL;
- ret = OPENSSL_zalloc(sizeof(*ret));
- if (ret == NULL) {
- X509V3err(X509V3_F_POLICY_DATA_NEW, ERR_R_MALLOC_FAILURE);
- ASN1_OBJECT_free(id);
- return NULL;
- }
- ret->expected_policy_set = sk_ASN1_OBJECT_new_null();
- if (ret->expected_policy_set == NULL) {
- OPENSSL_free(ret);
- ASN1_OBJECT_free(id);
- X509V3err(X509V3_F_POLICY_DATA_NEW, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- if (crit)
- ret->flags = POLICY_DATA_FLAG_CRITICAL;
-
- if (id)
- ret->valid_policy = id;
- else {
- ret->valid_policy = policy->policyid;
- policy->policyid = NULL;
- }
-
- if (policy) {
- ret->qualifier_set = policy->qualifiers;
- policy->qualifiers = NULL;
- }
-
- return ret;
-}
diff --git a/crypto/x509v3/pcy_lib.c b/crypto/x509v3/pcy_lib.c
deleted file mode 100644
index 2e196b838ca2..000000000000
--- a/crypto/x509v3/pcy_lib.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "internal/cryptlib.h"
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-
-#include "pcy_local.h"
-
-/* accessor functions */
-
-/* X509_POLICY_TREE stuff */
-
-int X509_policy_tree_level_count(const X509_POLICY_TREE *tree)
-{
- if (!tree)
- return 0;
- return tree->nlevel;
-}
-
-X509_POLICY_LEVEL *X509_policy_tree_get0_level(const X509_POLICY_TREE *tree,
- int i)
-{
- if (!tree || (i < 0) || (i >= tree->nlevel))
- return NULL;
- return tree->levels + i;
-}
-
-STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_policies(const
- X509_POLICY_TREE
- *tree)
-{
- if (!tree)
- return NULL;
- return tree->auth_policies;
-}
-
-STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_user_policies(const
- X509_POLICY_TREE
- *tree)
-{
- if (!tree)
- return NULL;
- if (tree->flags & POLICY_FLAG_ANY_POLICY)
- return tree->auth_policies;
- else
- return tree->user_policies;
-}
-
-/* X509_POLICY_LEVEL stuff */
-
-int X509_policy_level_node_count(X509_POLICY_LEVEL *level)
-{
- int n;
- if (!level)
- return 0;
- if (level->anyPolicy)
- n = 1;
- else
- n = 0;
- if (level->nodes)
- n += sk_X509_POLICY_NODE_num(level->nodes);
- return n;
-}
-
-X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i)
-{
- if (!level)
- return NULL;
- if (level->anyPolicy) {
- if (i == 0)
- return level->anyPolicy;
- i--;
- }
- return sk_X509_POLICY_NODE_value(level->nodes, i);
-}
-
-/* X509_POLICY_NODE stuff */
-
-const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node)
-{
- if (!node)
- return NULL;
- return node->data->valid_policy;
-}
-
-STACK_OF(POLICYQUALINFO) *X509_policy_node_get0_qualifiers(const
- X509_POLICY_NODE
- *node)
-{
- if (!node)
- return NULL;
- return node->data->qualifier_set;
-}
-
-const X509_POLICY_NODE *X509_policy_node_get0_parent(const X509_POLICY_NODE
- *node)
-{
- if (!node)
- return NULL;
- return node->parent;
-}
diff --git a/crypto/x509v3/pcy_local.h b/crypto/x509v3/pcy_local.h
deleted file mode 100644
index 5daf78de4585..000000000000
--- a/crypto/x509v3/pcy_local.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-typedef struct X509_POLICY_DATA_st X509_POLICY_DATA;
-
-DEFINE_STACK_OF(X509_POLICY_DATA)
-
-/* Internal structures */
-
-/*
- * This structure and the field names correspond to the Policy 'node' of
- * RFC3280. NB this structure contains no pointers to parent or child data:
- * X509_POLICY_NODE contains that. This means that the main policy data can
- * be kept static and cached with the certificate.
- */
-
-struct X509_POLICY_DATA_st {
- unsigned int flags;
- /* Policy OID and qualifiers for this data */
- ASN1_OBJECT *valid_policy;
- STACK_OF(POLICYQUALINFO) *qualifier_set;
- STACK_OF(ASN1_OBJECT) *expected_policy_set;
-};
-
-/* X509_POLICY_DATA flags values */
-
-/*
- * This flag indicates the structure has been mapped using a policy mapping
- * extension. If policy mapping is not active its references get deleted.
- */
-
-#define POLICY_DATA_FLAG_MAPPED 0x1
-
-/*
- * This flag indicates the data doesn't correspond to a policy in Certificate
- * Policies: it has been mapped to any policy.
- */
-
-#define POLICY_DATA_FLAG_MAPPED_ANY 0x2
-
-/* AND with flags to see if any mapping has occurred */
-
-#define POLICY_DATA_FLAG_MAP_MASK 0x3
-
-/* qualifiers are shared and shouldn't be freed */
-
-#define POLICY_DATA_FLAG_SHARED_QUALIFIERS 0x4
-
-/* Parent node is an extra node and should be freed */
-
-#define POLICY_DATA_FLAG_EXTRA_NODE 0x8
-
-/* Corresponding CertificatePolicies is critical */
-
-#define POLICY_DATA_FLAG_CRITICAL 0x10
-
-/* This structure is cached with a certificate */
-
-struct X509_POLICY_CACHE_st {
- /* anyPolicy data or NULL if no anyPolicy */
- X509_POLICY_DATA *anyPolicy;
- /* other policy data */
- STACK_OF(X509_POLICY_DATA) *data;
- /* If InhibitAnyPolicy present this is its value or -1 if absent. */
- long any_skip;
- /*
- * If policyConstraints and requireExplicitPolicy present this is its
- * value or -1 if absent.
- */
- long explicit_skip;
- /*
- * If policyConstraints and policyMapping present this is its value or -1
- * if absent.
- */
- long map_skip;
-};
-
-/*
- * #define POLICY_CACHE_FLAG_CRITICAL POLICY_DATA_FLAG_CRITICAL
- */
-
-/* This structure represents the relationship between nodes */
-
-struct X509_POLICY_NODE_st {
- /* node data this refers to */
- const X509_POLICY_DATA *data;
- /* Parent node */
- X509_POLICY_NODE *parent;
- /* Number of child nodes */
- int nchild;
-};
-
-struct X509_POLICY_LEVEL_st {
- /* Cert for this level */
- X509 *cert;
- /* nodes at this level */
- STACK_OF(X509_POLICY_NODE) *nodes;
- /* anyPolicy node */
- X509_POLICY_NODE *anyPolicy;
- /* Extra data */
- /*
- * STACK_OF(X509_POLICY_DATA) *extra_data;
- */
- unsigned int flags;
-};
-
-struct X509_POLICY_TREE_st {
- /* This is the tree 'level' data */
- X509_POLICY_LEVEL *levels;
- int nlevel;
- /*
- * Extra policy data when additional nodes (not from the certificate) are
- * required.
- */
- STACK_OF(X509_POLICY_DATA) *extra_data;
- /* This is the authority constrained policy set */
- STACK_OF(X509_POLICY_NODE) *auth_policies;
- STACK_OF(X509_POLICY_NODE) *user_policies;
- unsigned int flags;
-};
-
-/* Set if anyPolicy present in user policies */
-#define POLICY_FLAG_ANY_POLICY 0x2
-
-/* Useful macros */
-
-#define node_data_critical(data) (data->flags & POLICY_DATA_FLAG_CRITICAL)
-#define node_critical(node) node_data_critical(node->data)
-
-/* Internal functions */
-
-X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *id,
- int crit);
-void policy_data_free(X509_POLICY_DATA *data);
-
-X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache,
- const ASN1_OBJECT *id);
-int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps);
-
-STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void);
-
-void policy_cache_init(void);
-
-void policy_cache_free(X509_POLICY_CACHE *cache);
-
-X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level,
- const X509_POLICY_NODE *parent,
- const ASN1_OBJECT *id);
-
-X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *sk,
- const ASN1_OBJECT *id);
-
-X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level,
- X509_POLICY_DATA *data,
- X509_POLICY_NODE *parent,
- X509_POLICY_TREE *tree);
-void policy_node_free(X509_POLICY_NODE *node);
-int policy_node_match(const X509_POLICY_LEVEL *lvl,
- const X509_POLICY_NODE *node, const ASN1_OBJECT *oid);
-
-const X509_POLICY_CACHE *policy_cache_set(X509 *x);
diff --git a/crypto/x509v3/pcy_map.c b/crypto/x509v3/pcy_map.c
deleted file mode 100644
index ae2a62c97787..000000000000
--- a/crypto/x509v3/pcy_map.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "internal/cryptlib.h"
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-#include "crypto/x509.h"
-
-#include "pcy_local.h"
-
-/*
- * Set policy mapping entries in cache. Note: this modifies the passed
- * POLICY_MAPPINGS structure
- */
-
-int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
-{
- POLICY_MAPPING *map;
- X509_POLICY_DATA *data;
- X509_POLICY_CACHE *cache = x->policy_cache;
- int i;
- int ret = 0;
- if (sk_POLICY_MAPPING_num(maps) == 0) {
- ret = -1;
- goto bad_mapping;
- }
- for (i = 0; i < sk_POLICY_MAPPING_num(maps); i++) {
- map = sk_POLICY_MAPPING_value(maps, i);
- /* Reject if map to or from anyPolicy */
- if ((OBJ_obj2nid(map->subjectDomainPolicy) == NID_any_policy)
- || (OBJ_obj2nid(map->issuerDomainPolicy) == NID_any_policy)) {
- ret = -1;
- goto bad_mapping;
- }
-
- /* Attempt to find matching policy data */
- data = policy_cache_find_data(cache, map->issuerDomainPolicy);
- /* If we don't have anyPolicy can't map */
- if (data == NULL && !cache->anyPolicy)
- continue;
-
- /* Create a NODE from anyPolicy */
- if (data == NULL) {
- data = policy_data_new(NULL, map->issuerDomainPolicy,
- cache->anyPolicy->flags
- & POLICY_DATA_FLAG_CRITICAL);
- if (data == NULL)
- goto bad_mapping;
- data->qualifier_set = cache->anyPolicy->qualifier_set;
- /*
- * map->issuerDomainPolicy = NULL;
- */
- data->flags |= POLICY_DATA_FLAG_MAPPED_ANY;
- data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
- if (!sk_X509_POLICY_DATA_push(cache->data, data)) {
- policy_data_free(data);
- goto bad_mapping;
- }
- } else
- data->flags |= POLICY_DATA_FLAG_MAPPED;
- if (!sk_ASN1_OBJECT_push(data->expected_policy_set,
- map->subjectDomainPolicy))
- goto bad_mapping;
- map->subjectDomainPolicy = NULL;
-
- }
-
- ret = 1;
- bad_mapping:
- if (ret == -1)
- x->ex_flags |= EXFLAG_INVALID_POLICY;
- sk_POLICY_MAPPING_pop_free(maps, POLICY_MAPPING_free);
- return ret;
-
-}
diff --git a/crypto/x509v3/pcy_node.c b/crypto/x509v3/pcy_node.c
deleted file mode 100644
index e2d7b1532236..000000000000
--- a/crypto/x509v3/pcy_node.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <openssl/asn1.h>
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-#include <openssl/err.h>
-
-#include "pcy_local.h"
-
-static int node_cmp(const X509_POLICY_NODE *const *a,
- const X509_POLICY_NODE *const *b)
-{
- return OBJ_cmp((*a)->data->valid_policy, (*b)->data->valid_policy);
-}
-
-STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void)
-{
- return sk_X509_POLICY_NODE_new(node_cmp);
-}
-
-X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *nodes,
- const ASN1_OBJECT *id)
-{
- X509_POLICY_DATA n;
- X509_POLICY_NODE l;
- int idx;
-
- n.valid_policy = (ASN1_OBJECT *)id;
- l.data = &n;
-
- idx = sk_X509_POLICY_NODE_find(nodes, &l);
- return sk_X509_POLICY_NODE_value(nodes, idx);
-
-}
-
-X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level,
- const X509_POLICY_NODE *parent,
- const ASN1_OBJECT *id)
-{
- X509_POLICY_NODE *node;
- int i;
- for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++) {
- node = sk_X509_POLICY_NODE_value(level->nodes, i);
- if (node->parent == parent) {
- if (!OBJ_cmp(node->data->valid_policy, id))
- return node;
- }
- }
- return NULL;
-}
-
-X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level,
- X509_POLICY_DATA *data,
- X509_POLICY_NODE *parent,
- X509_POLICY_TREE *tree)
-{
- X509_POLICY_NODE *node;
-
- node = OPENSSL_zalloc(sizeof(*node));
- if (node == NULL) {
- X509V3err(X509V3_F_LEVEL_ADD_NODE, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- node->data = data;
- node->parent = parent;
- if (level) {
- if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
- if (level->anyPolicy)
- goto node_error;
- level->anyPolicy = node;
- } else {
-
- if (level->nodes == NULL)
- level->nodes = policy_node_cmp_new();
- if (level->nodes == NULL) {
- X509V3err(X509V3_F_LEVEL_ADD_NODE, ERR_R_MALLOC_FAILURE);
- goto node_error;
- }
- if (!sk_X509_POLICY_NODE_push(level->nodes, node)) {
- X509V3err(X509V3_F_LEVEL_ADD_NODE, ERR_R_MALLOC_FAILURE);
- goto node_error;
- }
- }
- }
-
- if (tree) {
- if (tree->extra_data == NULL)
- tree->extra_data = sk_X509_POLICY_DATA_new_null();
- if (tree->extra_data == NULL){
- X509V3err(X509V3_F_LEVEL_ADD_NODE, ERR_R_MALLOC_FAILURE);
- goto node_error;
- }
- if (!sk_X509_POLICY_DATA_push(tree->extra_data, data)) {
- X509V3err(X509V3_F_LEVEL_ADD_NODE, ERR_R_MALLOC_FAILURE);
- goto node_error;
- }
- }
-
- if (parent)
- parent->nchild++;
-
- return node;
-
- node_error:
- policy_node_free(node);
- return NULL;
-}
-
-void policy_node_free(X509_POLICY_NODE *node)
-{
- OPENSSL_free(node);
-}
-
-/*
- * See if a policy node matches a policy OID. If mapping enabled look through
- * expected policy set otherwise just valid policy.
- */
-
-int policy_node_match(const X509_POLICY_LEVEL *lvl,
- const X509_POLICY_NODE *node, const ASN1_OBJECT *oid)
-{
- int i;
- ASN1_OBJECT *policy_oid;
- const X509_POLICY_DATA *x = node->data;
-
- if ((lvl->flags & X509_V_FLAG_INHIBIT_MAP)
- || !(x->flags & POLICY_DATA_FLAG_MAP_MASK)) {
- if (!OBJ_cmp(x->valid_policy, oid))
- return 1;
- return 0;
- }
-
- for (i = 0; i < sk_ASN1_OBJECT_num(x->expected_policy_set); i++) {
- policy_oid = sk_ASN1_OBJECT_value(x->expected_policy_set, i);
- if (!OBJ_cmp(policy_oid, oid))
- return 1;
- }
- return 0;
-
-}
diff --git a/crypto/x509v3/pcy_tree.c b/crypto/x509v3/pcy_tree.c
deleted file mode 100644
index 6e8322cbc5e3..000000000000
--- a/crypto/x509v3/pcy_tree.c
+++ /dev/null
@@ -1,703 +0,0 @@
-/*
- * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "internal/cryptlib.h"
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-
-#include "pcy_local.h"
-
-/*
- * Enable this to print out the complete policy tree at various point during
- * evaluation.
- */
-
-/*
- * #define OPENSSL_POLICY_DEBUG
- */
-
-#ifdef OPENSSL_POLICY_DEBUG
-
-static void expected_print(BIO *err, X509_POLICY_LEVEL *lev,
- X509_POLICY_NODE *node, int indent)
-{
- if ((lev->flags & X509_V_FLAG_INHIBIT_MAP)
- || !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
- BIO_puts(err, " Not Mapped\n");
- else {
- int i;
- STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
- ASN1_OBJECT *oid;
- BIO_puts(err, " Expected: ");
- for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++) {
- oid = sk_ASN1_OBJECT_value(pset, i);
- if (i)
- BIO_puts(err, ", ");
- i2a_ASN1_OBJECT(err, oid);
- }
- BIO_puts(err, "\n");
- }
-}
-
-static void tree_print(char *str, X509_POLICY_TREE *tree,
- X509_POLICY_LEVEL *curr)
-{
- BIO *err = BIO_new_fp(stderr, BIO_NOCLOSE);
- X509_POLICY_LEVEL *plev;
-
- if (err == NULL)
- return;
- if (!curr)
- curr = tree->levels + tree->nlevel;
- else
- curr++;
-
- BIO_printf(err, "Level print after %s\n", str);
- BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels);
- for (plev = tree->levels; plev != curr; plev++) {
- int i;
-
- BIO_printf(err, "Level %ld, flags = %x\n",
- (long)(plev - tree->levels), plev->flags);
- for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++) {
- X509_POLICY_NODE *node = sk_X509_POLICY_NODE_value(plev->nodes, i);
-
- X509_POLICY_NODE_print(err, node, 2);
- expected_print(err, plev, node, 2);
- BIO_printf(err, " Flags: %x\n", node->data->flags);
- }
- if (plev->anyPolicy)
- X509_POLICY_NODE_print(err, plev->anyPolicy, 2);
- }
- BIO_free(err);
-}
-#endif
-
-/*-
- * Return value: <= 0 on error, or positive bit mask:
- *
- * X509_PCY_TREE_VALID: valid tree
- * X509_PCY_TREE_EMPTY: empty tree (including bare TA case)
- * X509_PCY_TREE_EXPLICIT: explicit policy required
- */
-static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
- unsigned int flags)
-{
- X509_POLICY_TREE *tree;
- X509_POLICY_LEVEL *level;
- const X509_POLICY_CACHE *cache;
- X509_POLICY_DATA *data = NULL;
- int ret = X509_PCY_TREE_VALID;
- int n = sk_X509_num(certs) - 1; /* RFC5280 paths omit the TA */
- int explicit_policy = (flags & X509_V_FLAG_EXPLICIT_POLICY) ? 0 : n+1;
- int any_skip = (flags & X509_V_FLAG_INHIBIT_ANY) ? 0 : n+1;
- int map_skip = (flags & X509_V_FLAG_INHIBIT_MAP) ? 0 : n+1;
- int i;
-
- *ptree = NULL;
-
- /* Can't do anything with just a trust anchor */
- if (n == 0)
- return X509_PCY_TREE_EMPTY;
-
- /*
- * First setup the policy cache in all n non-TA certificates, this will be
- * used in X509_verify_cert() which will invoke the verify callback for all
- * certificates with invalid policy extensions.
- */
- for (i = n - 1; i >= 0; i--) {
- X509 *x = sk_X509_value(certs, i);
-
- /* Call for side-effect of computing hash and caching extensions */
- X509_check_purpose(x, -1, 0);
-
- /* If cache is NULL, likely ENOMEM: return immediately */
- if (policy_cache_set(x) == NULL)
- return X509_PCY_TREE_INTERNAL;
- }
-
- /*
- * At this point check for invalid policies and required explicit policy.
- * Note that the explicit_policy counter is a count-down to zero, with the
- * requirement kicking in if and once it does that. The counter is
- * decremented for every non-self-issued certificate in the path, but may
- * be further reduced by policy constraints in a non-leaf certificate.
- *
- * The ultimate policy set is the intersection of all the policies along
- * the path, if we hit a certificate with an empty policy set, and explicit
- * policy is required we're done.
- */
- for (i = n - 1;
- i >= 0 && (explicit_policy > 0 || (ret & X509_PCY_TREE_EMPTY) == 0);
- i--) {
- X509 *x = sk_X509_value(certs, i);
- uint32_t ex_flags = X509_get_extension_flags(x);
-
- /* All the policies are already cached, we can return early */
- if (ex_flags & EXFLAG_INVALID_POLICY)
- return X509_PCY_TREE_INVALID;
-
- /* Access the cache which we now know exists */
- cache = policy_cache_set(x);
-
- if ((ret & X509_PCY_TREE_VALID) && cache->data == NULL)
- ret = X509_PCY_TREE_EMPTY;
- if (explicit_policy > 0) {
- if (!(ex_flags & EXFLAG_SI))
- explicit_policy--;
- if ((cache->explicit_skip >= 0)
- && (cache->explicit_skip < explicit_policy))
- explicit_policy = cache->explicit_skip;
- }
- }
-
- if (explicit_policy == 0)
- ret |= X509_PCY_TREE_EXPLICIT;
- if ((ret & X509_PCY_TREE_VALID) == 0)
- return ret;
-
- /* If we get this far initialize the tree */
- if ((tree = OPENSSL_zalloc(sizeof(*tree))) == NULL) {
- X509V3err(X509V3_F_TREE_INIT, ERR_R_MALLOC_FAILURE);
- return X509_PCY_TREE_INTERNAL;
- }
-
- /*
- * http://tools.ietf.org/html/rfc5280#section-6.1.2, figure 3.
- *
- * The top level is implicitly for the trust anchor with valid expected
- * policies of anyPolicy. (RFC 5280 has the TA at depth 0 and the leaf at
- * depth n, we have the leaf at depth 0 and the TA at depth n).
- */
- if ((tree->levels = OPENSSL_zalloc(sizeof(*tree->levels)*(n+1))) == NULL) {
- OPENSSL_free(tree);
- X509V3err(X509V3_F_TREE_INIT, ERR_R_MALLOC_FAILURE);
- return X509_PCY_TREE_INTERNAL;
- }
- tree->nlevel = n+1;
- level = tree->levels;
- if ((data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0)) == NULL)
- goto bad_tree;
- if (level_add_node(level, data, NULL, tree) == NULL) {
- policy_data_free(data);
- goto bad_tree;
- }
-
- /*
- * In this pass initialize all the tree levels and whether anyPolicy and
- * policy mapping are inhibited at each level.
- */
- for (i = n - 1; i >= 0; i--) {
- X509 *x = sk_X509_value(certs, i);
- uint32_t ex_flags = X509_get_extension_flags(x);
-
- /* Access the cache which we now know exists */
- cache = policy_cache_set(x);
-
- X509_up_ref(x);
- (++level)->cert = x;
-
- if (!cache->anyPolicy)
- level->flags |= X509_V_FLAG_INHIBIT_ANY;
-
- /* Determine inhibit any and inhibit map flags */
- if (any_skip == 0) {
- /*
- * Any matching allowed only if certificate is self issued and not
- * the last in the chain.
- */
- if (!(ex_flags & EXFLAG_SI) || (i == 0))
- level->flags |= X509_V_FLAG_INHIBIT_ANY;
- } else {
- if (!(ex_flags & EXFLAG_SI))
- any_skip--;
- if ((cache->any_skip >= 0) && (cache->any_skip < any_skip))
- any_skip = cache->any_skip;
- }
-
- if (map_skip == 0)
- level->flags |= X509_V_FLAG_INHIBIT_MAP;
- else {
- if (!(ex_flags & EXFLAG_SI))
- map_skip--;
- if ((cache->map_skip >= 0) && (cache->map_skip < map_skip))
- map_skip = cache->map_skip;
- }
- }
-
- *ptree = tree;
- return ret;
-
- bad_tree:
- X509_policy_tree_free(tree);
- return X509_PCY_TREE_INTERNAL;
-}
-
-/*
- * Return value: 1 on success, 0 otherwise
- */
-static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
- X509_POLICY_DATA *data)
-{
- X509_POLICY_LEVEL *last = curr - 1;
- int i, matched = 0;
-
- /* Iterate through all in nodes linking matches */
- for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
- X509_POLICY_NODE *node = sk_X509_POLICY_NODE_value(last->nodes, i);
-
- if (policy_node_match(last, node, data->valid_policy)) {
- if (level_add_node(curr, data, node, NULL) == NULL)
- return 0;
- matched = 1;
- }
- }
- if (!matched && last->anyPolicy) {
- if (level_add_node(curr, data, last->anyPolicy, NULL) == NULL)
- return 0;
- }
- return 1;
-}
-
-/*
- * This corresponds to RFC3280 6.1.3(d)(1): link any data from
- * CertificatePolicies onto matching parent or anyPolicy if no match.
- *
- * Return value: 1 on success, 0 otherwise.
- */
-static int tree_link_nodes(X509_POLICY_LEVEL *curr,
- const X509_POLICY_CACHE *cache)
-{
- int i;
-
- for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) {
- X509_POLICY_DATA *data = sk_X509_POLICY_DATA_value(cache->data, i);
-
- /* Look for matching nodes in previous level */
- if (!tree_link_matching_nodes(curr, data))
- return 0;
- }
- return 1;
-}
-
-/*
- * This corresponds to RFC3280 6.1.3(d)(2): Create new data for any unmatched
- * policies in the parent and link to anyPolicy.
- *
- * Return value: 1 on success, 0 otherwise.
- */
-static int tree_add_unmatched(X509_POLICY_LEVEL *curr,
- const X509_POLICY_CACHE *cache,
- const ASN1_OBJECT *id,
- X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
-{
- X509_POLICY_DATA *data;
-
- if (id == NULL)
- id = node->data->valid_policy;
- /*
- * Create a new node with qualifiers from anyPolicy and id from unmatched
- * node.
- */
- if ((data = policy_data_new(NULL, id, node_critical(node))) == NULL)
- return 0;
-
- /* Curr may not have anyPolicy */
- data->qualifier_set = cache->anyPolicy->qualifier_set;
- data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
- if (level_add_node(curr, data, node, tree) == NULL) {
- policy_data_free(data);
- return 0;
- }
- return 1;
-}
-
-/*
- * Return value: 1 on success, 0 otherwise.
- */
-static int tree_link_unmatched(X509_POLICY_LEVEL *curr,
- const X509_POLICY_CACHE *cache,
- X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
-{
- const X509_POLICY_LEVEL *last = curr - 1;
- int i;
-
- if ((last->flags & X509_V_FLAG_INHIBIT_MAP)
- || !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) {
- /* If no policy mapping: matched if one child present */
- if (node->nchild)
- return 1;
- if (!tree_add_unmatched(curr, cache, NULL, node, tree))
- return 0;
- /* Add it */
- } else {
- /* If mapping: matched if one child per expected policy set */
- STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
- if (node->nchild == sk_ASN1_OBJECT_num(expset))
- return 1;
- /* Locate unmatched nodes */
- for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) {
- ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
- if (level_find_node(curr, node, oid))
- continue;
- if (!tree_add_unmatched(curr, cache, oid, node, tree))
- return 0;
- }
-
- }
- return 1;
-}
-
-/*
- * Return value: 1 on success, 0 otherwise
- */
-static int tree_link_any(X509_POLICY_LEVEL *curr,
- const X509_POLICY_CACHE *cache,
- X509_POLICY_TREE *tree)
-{
- int i;
- X509_POLICY_NODE *node;
- X509_POLICY_LEVEL *last = curr - 1;
-
- for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
- node = sk_X509_POLICY_NODE_value(last->nodes, i);
-
- if (!tree_link_unmatched(curr, cache, node, tree))
- return 0;
- }
- /* Finally add link to anyPolicy */
- if (last->anyPolicy &&
- level_add_node(curr, cache->anyPolicy, last->anyPolicy, NULL) == NULL)
- return 0;
- return 1;
-}
-
-/*-
- * Prune the tree: delete any child mapped child data on the current level then
- * proceed up the tree deleting any data with no children. If we ever have no
- * data on a level we can halt because the tree will be empty.
- *
- * Return value: <= 0 error, otherwise one of:
- *
- * X509_PCY_TREE_VALID: valid tree
- * X509_PCY_TREE_EMPTY: empty tree
- */
-static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
-{
- STACK_OF(X509_POLICY_NODE) *nodes;
- X509_POLICY_NODE *node;
- int i;
- nodes = curr->nodes;
- if (curr->flags & X509_V_FLAG_INHIBIT_MAP) {
- for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
- node = sk_X509_POLICY_NODE_value(nodes, i);
- /* Delete any mapped data: see RFC3280 XXXX */
- if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) {
- node->parent->nchild--;
- OPENSSL_free(node);
- (void)sk_X509_POLICY_NODE_delete(nodes, i);
- }
- }
- }
-
- for (;;) {
- --curr;
- nodes = curr->nodes;
- for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
- node = sk_X509_POLICY_NODE_value(nodes, i);
- if (node->nchild == 0) {
- node->parent->nchild--;
- OPENSSL_free(node);
- (void)sk_X509_POLICY_NODE_delete(nodes, i);
- }
- }
- if (curr->anyPolicy && !curr->anyPolicy->nchild) {
- if (curr->anyPolicy->parent)
- curr->anyPolicy->parent->nchild--;
- OPENSSL_free(curr->anyPolicy);
- curr->anyPolicy = NULL;
- }
- if (curr == tree->levels) {
- /* If we zapped anyPolicy at top then tree is empty */
- if (!curr->anyPolicy)
- return X509_PCY_TREE_EMPTY;
- break;
- }
- }
- return X509_PCY_TREE_VALID;
-}
-
-/*
- * Return value: 1 on success, 0 otherwise.
- */
-static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
- X509_POLICY_NODE *pcy)
-{
- if (*pnodes == NULL &&
- (*pnodes = policy_node_cmp_new()) == NULL)
- return 0;
- if (sk_X509_POLICY_NODE_find(*pnodes, pcy) >= 0)
- return 1;
- return sk_X509_POLICY_NODE_push(*pnodes, pcy) != 0;
-}
-
-#define TREE_CALC_FAILURE 0
-#define TREE_CALC_OK_NOFREE 1
-#define TREE_CALC_OK_DOFREE 2
-
-/*-
- * Calculate the authority set based on policy tree. The 'pnodes' parameter is
- * used as a store for the set of policy nodes used to calculate the user set.
- * If the authority set is not anyPolicy then pnodes will just point to the
- * authority set. If however the authority set is anyPolicy then the set of
- * valid policies (other than anyPolicy) is store in pnodes.
- *
- * Return value:
- * TREE_CALC_FAILURE on failure,
- * TREE_CALC_OK_NOFREE on success and pnodes need not be freed,
- * TREE_CALC_OK_DOFREE on success and pnodes needs to be freed
- */
-static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
- STACK_OF(X509_POLICY_NODE) **pnodes)
-{
- X509_POLICY_LEVEL *curr;
- X509_POLICY_NODE *node, *anyptr;
- STACK_OF(X509_POLICY_NODE) **addnodes;
- int i, j;
- curr = tree->levels + tree->nlevel - 1;
-
- /* If last level contains anyPolicy set is anyPolicy */
- if (curr->anyPolicy) {
- if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
- return TREE_CALC_FAILURE;
- addnodes = pnodes;
- } else
- /* Add policies to authority set */
- addnodes = &tree->auth_policies;
-
- curr = tree->levels;
- for (i = 1; i < tree->nlevel; i++) {
- /*
- * If no anyPolicy node on this this level it can't appear on lower
- * levels so end search.
- */
- if ((anyptr = curr->anyPolicy) == NULL)
- break;
- curr++;
- for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) {
- node = sk_X509_POLICY_NODE_value(curr->nodes, j);
- if ((node->parent == anyptr)
- && !tree_add_auth_node(addnodes, node)) {
- if (addnodes == pnodes) {
- sk_X509_POLICY_NODE_free(*pnodes);
- *pnodes = NULL;
- }
- return TREE_CALC_FAILURE;
- }
- }
- }
- if (addnodes == pnodes)
- return TREE_CALC_OK_DOFREE;
-
- *pnodes = tree->auth_policies;
- return TREE_CALC_OK_NOFREE;
-}
-
-/*
- * Return value: 1 on success, 0 otherwise.
- */
-static int tree_calculate_user_set(X509_POLICY_TREE *tree,
- STACK_OF(ASN1_OBJECT) *policy_oids,
- STACK_OF(X509_POLICY_NODE) *auth_nodes)
-{
- int i;
- X509_POLICY_NODE *node;
- ASN1_OBJECT *oid;
- X509_POLICY_NODE *anyPolicy;
- X509_POLICY_DATA *extra;
-
- /*
- * Check if anyPolicy present in authority constrained policy set: this
- * will happen if it is a leaf node.
- */
- if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
- return 1;
-
- anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
-
- for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
- oid = sk_ASN1_OBJECT_value(policy_oids, i);
- if (OBJ_obj2nid(oid) == NID_any_policy) {
- tree->flags |= POLICY_FLAG_ANY_POLICY;
- return 1;
- }
- }
-
- for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
- oid = sk_ASN1_OBJECT_value(policy_oids, i);
- node = tree_find_sk(auth_nodes, oid);
- if (!node) {
- if (!anyPolicy)
- continue;
- /*
- * Create a new node with policy ID from user set and qualifiers
- * from anyPolicy.
- */
- extra = policy_data_new(NULL, oid, node_critical(anyPolicy));
- if (extra == NULL)
- return 0;
- extra->qualifier_set = anyPolicy->data->qualifier_set;
- extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
- | POLICY_DATA_FLAG_EXTRA_NODE;
- node = level_add_node(NULL, extra, anyPolicy->parent, tree);
- }
- if (!tree->user_policies) {
- tree->user_policies = sk_X509_POLICY_NODE_new_null();
- if (!tree->user_policies)
- return 1;
- }
- if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
- return 0;
- }
- return 1;
-}
-
-/*-
- * Return value: <= 0 error, otherwise one of:
- * X509_PCY_TREE_VALID: valid tree
- * X509_PCY_TREE_EMPTY: empty tree
- * (see tree_prune()).
- */
-static int tree_evaluate(X509_POLICY_TREE *tree)
-{
- int ret, i;
- X509_POLICY_LEVEL *curr = tree->levels + 1;
- const X509_POLICY_CACHE *cache;
-
- for (i = 1; i < tree->nlevel; i++, curr++) {
- cache = policy_cache_set(curr->cert);
- if (!tree_link_nodes(curr, cache))
- return X509_PCY_TREE_INTERNAL;
-
- if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
- && !tree_link_any(curr, cache, tree))
- return X509_PCY_TREE_INTERNAL;
-#ifdef OPENSSL_POLICY_DEBUG
- tree_print("before tree_prune()", tree, curr);
-#endif
- ret = tree_prune(tree, curr);
- if (ret != X509_PCY_TREE_VALID)
- return ret;
- }
- return X509_PCY_TREE_VALID;
-}
-
-static void exnode_free(X509_POLICY_NODE *node)
-{
- if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
- OPENSSL_free(node);
-}
-
-void X509_policy_tree_free(X509_POLICY_TREE *tree)
-{
- X509_POLICY_LEVEL *curr;
- int i;
-
- if (!tree)
- return;
-
- sk_X509_POLICY_NODE_free(tree->auth_policies);
- sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
-
- for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) {
- X509_free(curr->cert);
- sk_X509_POLICY_NODE_pop_free(curr->nodes, policy_node_free);
- policy_node_free(curr->anyPolicy);
- }
-
- sk_X509_POLICY_DATA_pop_free(tree->extra_data, policy_data_free);
- OPENSSL_free(tree->levels);
- OPENSSL_free(tree);
-
-}
-
-/*-
- * Application policy checking function.
- * Return codes:
- * X509_PCY_TREE_FAILURE: Failure to satisfy explicit policy
- * X509_PCY_TREE_INVALID: Inconsistent or invalid extensions
- * X509_PCY_TREE_INTERNAL: Internal error, most likely malloc
- * X509_PCY_TREE_VALID: Success (null tree if empty or bare TA)
- */
-int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
- STACK_OF(X509) *certs,
- STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags)
-{
- int init_ret;
- int ret;
- int calc_ret;
- X509_POLICY_TREE *tree = NULL;
- STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
-
- *ptree = NULL;
- *pexplicit_policy = 0;
- init_ret = tree_init(&tree, certs, flags);
-
- if (init_ret <= 0)
- return init_ret;
-
- if ((init_ret & X509_PCY_TREE_EXPLICIT) == 0) {
- if (init_ret & X509_PCY_TREE_EMPTY) {
- X509_policy_tree_free(tree);
- return X509_PCY_TREE_VALID;
- }
- } else {
- *pexplicit_policy = 1;
- /* Tree empty and requireExplicit True: Error */
- if (init_ret & X509_PCY_TREE_EMPTY)
- return X509_PCY_TREE_FAILURE;
- }
-
- ret = tree_evaluate(tree);
-#ifdef OPENSSL_POLICY_DEBUG
- tree_print("tree_evaluate()", tree, NULL);
-#endif
- if (ret <= 0)
- goto error;
-
- if (ret == X509_PCY_TREE_EMPTY) {
- X509_policy_tree_free(tree);
- if (init_ret & X509_PCY_TREE_EXPLICIT)
- return X509_PCY_TREE_FAILURE;
- return X509_PCY_TREE_VALID;
- }
-
- /* Tree is not empty: continue */
-
- if ((calc_ret = tree_calculate_authority_set(tree, &auth_nodes)) == 0)
- goto error;
- ret = tree_calculate_user_set(tree, policy_oids, auth_nodes);
- if (calc_ret == TREE_CALC_OK_DOFREE)
- sk_X509_POLICY_NODE_free(auth_nodes);
- if (!ret)
- goto error;
-
- *ptree = tree;
-
- if (init_ret & X509_PCY_TREE_EXPLICIT) {
- nodes = X509_policy_tree_get0_user_policies(tree);
- if (sk_X509_POLICY_NODE_num(nodes) <= 0)
- return X509_PCY_TREE_FAILURE;
- }
- return X509_PCY_TREE_VALID;
-
- error:
- X509_policy_tree_free(tree);
- return X509_PCY_TREE_INTERNAL;
-}
diff --git a/crypto/x509v3/standard_exts.h b/crypto/x509v3/standard_exts.h
deleted file mode 100644
index 944f4de02eb5..000000000000
--- a/crypto/x509v3/standard_exts.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * This table will be searched using OBJ_bsearch so it *must* kept in order
- * of the ext_nid values.
- */
-
-static const X509V3_EXT_METHOD *standard_exts[] = {
- &v3_nscert,
- &v3_ns_ia5_list[0],
- &v3_ns_ia5_list[1],
- &v3_ns_ia5_list[2],
- &v3_ns_ia5_list[3],
- &v3_ns_ia5_list[4],
- &v3_ns_ia5_list[5],
- &v3_ns_ia5_list[6],
- &v3_skey_id,
- &v3_key_usage,
- &v3_pkey_usage_period,
- &v3_alt[0],
- &v3_alt[1],
- &v3_bcons,
- &v3_crl_num,
- &v3_cpols,
- &v3_akey_id,
- &v3_crld,
- &v3_ext_ku,
- &v3_delta_crl,
- &v3_crl_reason,
-#ifndef OPENSSL_NO_OCSP
- &v3_crl_invdate,
-#endif
- &v3_sxnet,
- &v3_info,
-#ifndef OPENSSL_NO_RFC3779
- &v3_addr,
- &v3_asid,
-#endif
-#ifndef OPENSSL_NO_OCSP
- &v3_ocsp_nonce,
- &v3_ocsp_crlid,
- &v3_ocsp_accresp,
- &v3_ocsp_nocheck,
- &v3_ocsp_acutoff,
- &v3_ocsp_serviceloc,
-#endif
- &v3_sinfo,
- &v3_policy_constraints,
-#ifndef OPENSSL_NO_OCSP
- &v3_crl_hold,
-#endif
- &v3_pci,
- &v3_name_constraints,
- &v3_policy_mappings,
- &v3_inhibit_anyp,
- &v3_idp,
- &v3_alt[2],
- &v3_freshest_crl,
-#ifndef OPENSSL_NO_CT
- &v3_ct_scts[0],
- &v3_ct_scts[1],
- &v3_ct_scts[2],
-#endif
- &v3_tls_feature,
- &v3_ext_admission
-};
-
-/* Number of standard extensions */
-
-#define STANDARD_EXTENSION_COUNT OSSL_NELEM(standard_exts)
-
diff --git a/crypto/x509v3/v3_addr.c b/crypto/x509v3/v3_addr.c
deleted file mode 100644
index f9c368bea405..000000000000
--- a/crypto/x509v3/v3_addr.c
+++ /dev/null
@@ -1,1332 +0,0 @@
-/*
- * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * Implementation of RFC 3779 section 2.2.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-
-#include "internal/cryptlib.h"
-#include <openssl/conf.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-#include <openssl/buffer.h>
-#include <openssl/x509v3.h>
-#include "crypto/x509.h"
-#include "ext_dat.h"
-
-#ifndef OPENSSL_NO_RFC3779
-
-/*
- * OpenSSL ASN.1 template translation of RFC 3779 2.2.3.
- */
-
-ASN1_SEQUENCE(IPAddressRange) = {
- ASN1_SIMPLE(IPAddressRange, min, ASN1_BIT_STRING),
- ASN1_SIMPLE(IPAddressRange, max, ASN1_BIT_STRING)
-} ASN1_SEQUENCE_END(IPAddressRange)
-
-ASN1_CHOICE(IPAddressOrRange) = {
- ASN1_SIMPLE(IPAddressOrRange, u.addressPrefix, ASN1_BIT_STRING),
- ASN1_SIMPLE(IPAddressOrRange, u.addressRange, IPAddressRange)
-} ASN1_CHOICE_END(IPAddressOrRange)
-
-ASN1_CHOICE(IPAddressChoice) = {
- ASN1_SIMPLE(IPAddressChoice, u.inherit, ASN1_NULL),
- ASN1_SEQUENCE_OF(IPAddressChoice, u.addressesOrRanges, IPAddressOrRange)
-} ASN1_CHOICE_END(IPAddressChoice)
-
-ASN1_SEQUENCE(IPAddressFamily) = {
- ASN1_SIMPLE(IPAddressFamily, addressFamily, ASN1_OCTET_STRING),
- ASN1_SIMPLE(IPAddressFamily, ipAddressChoice, IPAddressChoice)
-} ASN1_SEQUENCE_END(IPAddressFamily)
-
-ASN1_ITEM_TEMPLATE(IPAddrBlocks) =
- ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0,
- IPAddrBlocks, IPAddressFamily)
-static_ASN1_ITEM_TEMPLATE_END(IPAddrBlocks)
-
-IMPLEMENT_ASN1_FUNCTIONS(IPAddressRange)
-IMPLEMENT_ASN1_FUNCTIONS(IPAddressOrRange)
-IMPLEMENT_ASN1_FUNCTIONS(IPAddressChoice)
-IMPLEMENT_ASN1_FUNCTIONS(IPAddressFamily)
-
-/*
- * How much buffer space do we need for a raw address?
- */
-#define ADDR_RAW_BUF_LEN 16
-
-/*
- * What's the address length associated with this AFI?
- */
-static int length_from_afi(const unsigned afi)
-{
- switch (afi) {
- case IANA_AFI_IPV4:
- return 4;
- case IANA_AFI_IPV6:
- return 16;
- default:
- return 0;
- }
-}
-
-/*
- * Extract the AFI from an IPAddressFamily.
- */
-unsigned int X509v3_addr_get_afi(const IPAddressFamily *f)
-{
- if (f == NULL
- || f->addressFamily == NULL
- || f->addressFamily->data == NULL
- || f->addressFamily->length < 2)
- return 0;
- return (f->addressFamily->data[0] << 8) | f->addressFamily->data[1];
-}
-
-/*
- * Expand the bitstring form of an address into a raw byte array.
- * At the moment this is coded for simplicity, not speed.
- */
-static int addr_expand(unsigned char *addr,
- const ASN1_BIT_STRING *bs,
- const int length, const unsigned char fill)
-{
- if (bs->length < 0 || bs->length > length)
- return 0;
- if (bs->length > 0) {
- memcpy(addr, bs->data, bs->length);
- if ((bs->flags & 7) != 0) {
- unsigned char mask = 0xFF >> (8 - (bs->flags & 7));
- if (fill == 0)
- addr[bs->length - 1] &= ~mask;
- else
- addr[bs->length - 1] |= mask;
- }
- }
- memset(addr + bs->length, fill, length - bs->length);
- return 1;
-}
-
-/*
- * Extract the prefix length from a bitstring.
- */
-#define addr_prefixlen(bs) ((int) ((bs)->length * 8 - ((bs)->flags & 7)))
-
-/*
- * i2r handler for one address bitstring.
- */
-static int i2r_address(BIO *out,
- const unsigned afi,
- const unsigned char fill, const ASN1_BIT_STRING *bs)
-{
- unsigned char addr[ADDR_RAW_BUF_LEN];
- int i, n;
-
- if (bs->length < 0)
- return 0;
- switch (afi) {
- case IANA_AFI_IPV4:
- if (!addr_expand(addr, bs, 4, fill))
- return 0;
- BIO_printf(out, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
- break;
- case IANA_AFI_IPV6:
- if (!addr_expand(addr, bs, 16, fill))
- return 0;
- for (n = 16; n > 1 && addr[n - 1] == 0x00 && addr[n - 2] == 0x00;
- n -= 2) ;
- for (i = 0; i < n; i += 2)
- BIO_printf(out, "%x%s", (addr[i] << 8) | addr[i + 1],
- (i < 14 ? ":" : ""));
- if (i < 16)
- BIO_puts(out, ":");
- if (i == 0)
- BIO_puts(out, ":");
- break;
- default:
- for (i = 0; i < bs->length; i++)
- BIO_printf(out, "%s%02x", (i > 0 ? ":" : ""), bs->data[i]);
- BIO_printf(out, "[%d]", (int)(bs->flags & 7));
- break;
- }
- return 1;
-}
-
-/*
- * i2r handler for a sequence of addresses and ranges.
- */
-static int i2r_IPAddressOrRanges(BIO *out,
- const int indent,
- const IPAddressOrRanges *aors,
- const unsigned afi)
-{
- int i;
- for (i = 0; i < sk_IPAddressOrRange_num(aors); i++) {
- const IPAddressOrRange *aor = sk_IPAddressOrRange_value(aors, i);
- BIO_printf(out, "%*s", indent, "");
- switch (aor->type) {
- case IPAddressOrRange_addressPrefix:
- if (!i2r_address(out, afi, 0x00, aor->u.addressPrefix))
- return 0;
- BIO_printf(out, "/%d\n", addr_prefixlen(aor->u.addressPrefix));
- continue;
- case IPAddressOrRange_addressRange:
- if (!i2r_address(out, afi, 0x00, aor->u.addressRange->min))
- return 0;
- BIO_puts(out, "-");
- if (!i2r_address(out, afi, 0xFF, aor->u.addressRange->max))
- return 0;
- BIO_puts(out, "\n");
- continue;
- }
- }
- return 1;
-}
-
-/*
- * i2r handler for an IPAddrBlocks extension.
- */
-static int i2r_IPAddrBlocks(const X509V3_EXT_METHOD *method,
- void *ext, BIO *out, int indent)
-{
- const IPAddrBlocks *addr = ext;
- int i;
- for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
- IPAddressFamily *f = sk_IPAddressFamily_value(addr, i);
- const unsigned int afi = X509v3_addr_get_afi(f);
- switch (afi) {
- case IANA_AFI_IPV4:
- BIO_printf(out, "%*sIPv4", indent, "");
- break;
- case IANA_AFI_IPV6:
- BIO_printf(out, "%*sIPv6", indent, "");
- break;
- default:
- BIO_printf(out, "%*sUnknown AFI %u", indent, "", afi);
- break;
- }
- if (f->addressFamily->length > 2) {
- switch (f->addressFamily->data[2]) {
- case 1:
- BIO_puts(out, " (Unicast)");
- break;
- case 2:
- BIO_puts(out, " (Multicast)");
- break;
- case 3:
- BIO_puts(out, " (Unicast/Multicast)");
- break;
- case 4:
- BIO_puts(out, " (MPLS)");
- break;
- case 64:
- BIO_puts(out, " (Tunnel)");
- break;
- case 65:
- BIO_puts(out, " (VPLS)");
- break;
- case 66:
- BIO_puts(out, " (BGP MDT)");
- break;
- case 128:
- BIO_puts(out, " (MPLS-labeled VPN)");
- break;
- default:
- BIO_printf(out, " (Unknown SAFI %u)",
- (unsigned)f->addressFamily->data[2]);
- break;
- }
- }
- switch (f->ipAddressChoice->type) {
- case IPAddressChoice_inherit:
- BIO_puts(out, ": inherit\n");
- break;
- case IPAddressChoice_addressesOrRanges:
- BIO_puts(out, ":\n");
- if (!i2r_IPAddressOrRanges(out,
- indent + 2,
- f->ipAddressChoice->
- u.addressesOrRanges, afi))
- return 0;
- break;
- }
- }
- return 1;
-}
-
-/*
- * Sort comparison function for a sequence of IPAddressOrRange
- * elements.
- *
- * There's no sane answer we can give if addr_expand() fails, and an
- * assertion failure on externally supplied data is seriously uncool,
- * so we just arbitrarily declare that if given invalid inputs this
- * function returns -1. If this messes up your preferred sort order
- * for garbage input, tough noogies.
- */
-static int IPAddressOrRange_cmp(const IPAddressOrRange *a,
- const IPAddressOrRange *b, const int length)
-{
- unsigned char addr_a[ADDR_RAW_BUF_LEN], addr_b[ADDR_RAW_BUF_LEN];
- int prefixlen_a = 0, prefixlen_b = 0;
- int r;
-
- switch (a->type) {
- case IPAddressOrRange_addressPrefix:
- if (!addr_expand(addr_a, a->u.addressPrefix, length, 0x00))
- return -1;
- prefixlen_a = addr_prefixlen(a->u.addressPrefix);
- break;
- case IPAddressOrRange_addressRange:
- if (!addr_expand(addr_a, a->u.addressRange->min, length, 0x00))
- return -1;
- prefixlen_a = length * 8;
- break;
- }
-
- switch (b->type) {
- case IPAddressOrRange_addressPrefix:
- if (!addr_expand(addr_b, b->u.addressPrefix, length, 0x00))
- return -1;
- prefixlen_b = addr_prefixlen(b->u.addressPrefix);
- break;
- case IPAddressOrRange_addressRange:
- if (!addr_expand(addr_b, b->u.addressRange->min, length, 0x00))
- return -1;
- prefixlen_b = length * 8;
- break;
- }
-
- if ((r = memcmp(addr_a, addr_b, length)) != 0)
- return r;
- else
- return prefixlen_a - prefixlen_b;
-}
-
-/*
- * IPv4-specific closure over IPAddressOrRange_cmp, since sk_sort()
- * comparison routines are only allowed two arguments.
- */
-static int v4IPAddressOrRange_cmp(const IPAddressOrRange *const *a,
- const IPAddressOrRange *const *b)
-{
- return IPAddressOrRange_cmp(*a, *b, 4);
-}
-
-/*
- * IPv6-specific closure over IPAddressOrRange_cmp, since sk_sort()
- * comparison routines are only allowed two arguments.
- */
-static int v6IPAddressOrRange_cmp(const IPAddressOrRange *const *a,
- const IPAddressOrRange *const *b)
-{
- return IPAddressOrRange_cmp(*a, *b, 16);
-}
-
-/*
- * Calculate whether a range collapses to a prefix.
- * See last paragraph of RFC 3779 2.2.3.7.
- */
-static int range_should_be_prefix(const unsigned char *min,
- const unsigned char *max, const int length)
-{
- unsigned char mask;
- int i, j;
-
- /*
- * It is the responsibility of the caller to confirm min <= max. We don't
- * use ossl_assert() here since we have no way of signalling an error from
- * this function - so we just use a plain assert instead.
- */
- assert(memcmp(min, max, length) <= 0);
-
- for (i = 0; i < length && min[i] == max[i]; i++) ;
- for (j = length - 1; j >= 0 && min[j] == 0x00 && max[j] == 0xFF; j--) ;
- if (i < j)
- return -1;
- if (i > j)
- return i * 8;
- mask = min[i] ^ max[i];
- switch (mask) {
- case 0x01:
- j = 7;
- break;
- case 0x03:
- j = 6;
- break;
- case 0x07:
- j = 5;
- break;
- case 0x0F:
- j = 4;
- break;
- case 0x1F:
- j = 3;
- break;
- case 0x3F:
- j = 2;
- break;
- case 0x7F:
- j = 1;
- break;
- default:
- return -1;
- }
- if ((min[i] & mask) != 0 || (max[i] & mask) != mask)
- return -1;
- else
- return i * 8 + j;
-}
-
-/*
- * Construct a prefix.
- */
-static int make_addressPrefix(IPAddressOrRange **result, unsigned char *addr,
- const int prefixlen, const int afilen)
-{
- int bytelen = (prefixlen + 7) / 8, bitlen = prefixlen % 8;
- IPAddressOrRange *aor = IPAddressOrRange_new();
-
- if (prefixlen < 0 || prefixlen > (afilen * 8))
- return 0;
- if (aor == NULL)
- return 0;
- aor->type = IPAddressOrRange_addressPrefix;
- if (aor->u.addressPrefix == NULL &&
- (aor->u.addressPrefix = ASN1_BIT_STRING_new()) == NULL)
- goto err;
- if (!ASN1_BIT_STRING_set(aor->u.addressPrefix, addr, bytelen))
- goto err;
- aor->u.addressPrefix->flags &= ~7;
- aor->u.addressPrefix->flags |= ASN1_STRING_FLAG_BITS_LEFT;
- if (bitlen > 0) {
- aor->u.addressPrefix->data[bytelen - 1] &= ~(0xFF >> bitlen);
- aor->u.addressPrefix->flags |= 8 - bitlen;
- }
-
- *result = aor;
- return 1;
-
- err:
- IPAddressOrRange_free(aor);
- return 0;
-}
-
-/*
- * Construct a range. If it can be expressed as a prefix,
- * return a prefix instead. Doing this here simplifies
- * the rest of the code considerably.
- */
-static int make_addressRange(IPAddressOrRange **result,
- unsigned char *min,
- unsigned char *max, const int length)
-{
- IPAddressOrRange *aor;
- int i, prefixlen;
-
- if (memcmp(min, max, length) > 0)
- return 0;
-
- if ((prefixlen = range_should_be_prefix(min, max, length)) >= 0)
- return make_addressPrefix(result, min, prefixlen, length);
-
- if ((aor = IPAddressOrRange_new()) == NULL)
- return 0;
- aor->type = IPAddressOrRange_addressRange;
- if ((aor->u.addressRange = IPAddressRange_new()) == NULL)
- goto err;
- if (aor->u.addressRange->min == NULL &&
- (aor->u.addressRange->min = ASN1_BIT_STRING_new()) == NULL)
- goto err;
- if (aor->u.addressRange->max == NULL &&
- (aor->u.addressRange->max = ASN1_BIT_STRING_new()) == NULL)
- goto err;
-
- for (i = length; i > 0 && min[i - 1] == 0x00; --i) ;
- if (!ASN1_BIT_STRING_set(aor->u.addressRange->min, min, i))
- goto err;
- aor->u.addressRange->min->flags &= ~7;
- aor->u.addressRange->min->flags |= ASN1_STRING_FLAG_BITS_LEFT;
- if (i > 0) {
- unsigned char b = min[i - 1];
- int j = 1;
- while ((b & (0xFFU >> j)) != 0)
- ++j;
- aor->u.addressRange->min->flags |= 8 - j;
- }
-
- for (i = length; i > 0 && max[i - 1] == 0xFF; --i) ;
- if (!ASN1_BIT_STRING_set(aor->u.addressRange->max, max, i))
- goto err;
- aor->u.addressRange->max->flags &= ~7;
- aor->u.addressRange->max->flags |= ASN1_STRING_FLAG_BITS_LEFT;
- if (i > 0) {
- unsigned char b = max[i - 1];
- int j = 1;
- while ((b & (0xFFU >> j)) != (0xFFU >> j))
- ++j;
- aor->u.addressRange->max->flags |= 8 - j;
- }
-
- *result = aor;
- return 1;
-
- err:
- IPAddressOrRange_free(aor);
- return 0;
-}
-
-/*
- * Construct a new address family or find an existing one.
- */
-static IPAddressFamily *make_IPAddressFamily(IPAddrBlocks *addr,
- const unsigned afi,
- const unsigned *safi)
-{
- IPAddressFamily *f;
- unsigned char key[3];
- int keylen;
- int i;
-
- key[0] = (afi >> 8) & 0xFF;
- key[1] = afi & 0xFF;
- if (safi != NULL) {
- key[2] = *safi & 0xFF;
- keylen = 3;
- } else {
- keylen = 2;
- }
-
- for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
- f = sk_IPAddressFamily_value(addr, i);
- if (f->addressFamily->length == keylen &&
- !memcmp(f->addressFamily->data, key, keylen))
- return f;
- }
-
- if ((f = IPAddressFamily_new()) == NULL)
- goto err;
- if (f->ipAddressChoice == NULL &&
- (f->ipAddressChoice = IPAddressChoice_new()) == NULL)
- goto err;
- if (f->addressFamily == NULL &&
- (f->addressFamily = ASN1_OCTET_STRING_new()) == NULL)
- goto err;
- if (!ASN1_OCTET_STRING_set(f->addressFamily, key, keylen))
- goto err;
- if (!sk_IPAddressFamily_push(addr, f))
- goto err;
-
- return f;
-
- err:
- IPAddressFamily_free(f);
- return NULL;
-}
-
-/*
- * Add an inheritance element.
- */
-int X509v3_addr_add_inherit(IPAddrBlocks *addr,
- const unsigned afi, const unsigned *safi)
-{
- IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi);
- if (f == NULL ||
- f->ipAddressChoice == NULL ||
- (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges &&
- f->ipAddressChoice->u.addressesOrRanges != NULL))
- return 0;
- if (f->ipAddressChoice->type == IPAddressChoice_inherit &&
- f->ipAddressChoice->u.inherit != NULL)
- return 1;
- if (f->ipAddressChoice->u.inherit == NULL &&
- (f->ipAddressChoice->u.inherit = ASN1_NULL_new()) == NULL)
- return 0;
- f->ipAddressChoice->type = IPAddressChoice_inherit;
- return 1;
-}
-
-/*
- * Construct an IPAddressOrRange sequence, or return an existing one.
- */
-static IPAddressOrRanges *make_prefix_or_range(IPAddrBlocks *addr,
- const unsigned afi,
- const unsigned *safi)
-{
- IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi);
- IPAddressOrRanges *aors = NULL;
-
- if (f == NULL ||
- f->ipAddressChoice == NULL ||
- (f->ipAddressChoice->type == IPAddressChoice_inherit &&
- f->ipAddressChoice->u.inherit != NULL))
- return NULL;
- if (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges)
- aors = f->ipAddressChoice->u.addressesOrRanges;
- if (aors != NULL)
- return aors;
- if ((aors = sk_IPAddressOrRange_new_null()) == NULL)
- return NULL;
- switch (afi) {
- case IANA_AFI_IPV4:
- (void)sk_IPAddressOrRange_set_cmp_func(aors, v4IPAddressOrRange_cmp);
- break;
- case IANA_AFI_IPV6:
- (void)sk_IPAddressOrRange_set_cmp_func(aors, v6IPAddressOrRange_cmp);
- break;
- }
- f->ipAddressChoice->type = IPAddressChoice_addressesOrRanges;
- f->ipAddressChoice->u.addressesOrRanges = aors;
- return aors;
-}
-
-/*
- * Add a prefix.
- */
-int X509v3_addr_add_prefix(IPAddrBlocks *addr,
- const unsigned afi,
- const unsigned *safi,
- unsigned char *a, const int prefixlen)
-{
- IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi);
- IPAddressOrRange *aor;
-
- if (aors == NULL
- || !make_addressPrefix(&aor, a, prefixlen, length_from_afi(afi)))
- return 0;
- if (sk_IPAddressOrRange_push(aors, aor))
- return 1;
- IPAddressOrRange_free(aor);
- return 0;
-}
-
-/*
- * Add a range.
- */
-int X509v3_addr_add_range(IPAddrBlocks *addr,
- const unsigned afi,
- const unsigned *safi,
- unsigned char *min, unsigned char *max)
-{
- IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi);
- IPAddressOrRange *aor;
- int length = length_from_afi(afi);
- if (aors == NULL)
- return 0;
- if (!make_addressRange(&aor, min, max, length))
- return 0;
- if (sk_IPAddressOrRange_push(aors, aor))
- return 1;
- IPAddressOrRange_free(aor);
- return 0;
-}
-
-/*
- * Extract min and max values from an IPAddressOrRange.
- */
-static int extract_min_max(IPAddressOrRange *aor,
- unsigned char *min, unsigned char *max, int length)
-{
- if (aor == NULL || min == NULL || max == NULL)
- return 0;
- switch (aor->type) {
- case IPAddressOrRange_addressPrefix:
- return (addr_expand(min, aor->u.addressPrefix, length, 0x00) &&
- addr_expand(max, aor->u.addressPrefix, length, 0xFF));
- case IPAddressOrRange_addressRange:
- return (addr_expand(min, aor->u.addressRange->min, length, 0x00) &&
- addr_expand(max, aor->u.addressRange->max, length, 0xFF));
- }
- return 0;
-}
-
-/*
- * Public wrapper for extract_min_max().
- */
-int X509v3_addr_get_range(IPAddressOrRange *aor,
- const unsigned afi,
- unsigned char *min,
- unsigned char *max, const int length)
-{
- int afi_length = length_from_afi(afi);
- if (aor == NULL || min == NULL || max == NULL ||
- afi_length == 0 || length < afi_length ||
- (aor->type != IPAddressOrRange_addressPrefix &&
- aor->type != IPAddressOrRange_addressRange) ||
- !extract_min_max(aor, min, max, afi_length))
- return 0;
-
- return afi_length;
-}
-
-/*
- * Sort comparison function for a sequence of IPAddressFamily.
- *
- * The last paragraph of RFC 3779 2.2.3.3 is slightly ambiguous about
- * the ordering: I can read it as meaning that IPv6 without a SAFI
- * comes before IPv4 with a SAFI, which seems pretty weird. The
- * examples in appendix B suggest that the author intended the
- * null-SAFI rule to apply only within a single AFI, which is what I
- * would have expected and is what the following code implements.
- */
-static int IPAddressFamily_cmp(const IPAddressFamily *const *a_,
- const IPAddressFamily *const *b_)
-{
- const ASN1_OCTET_STRING *a = (*a_)->addressFamily;
- const ASN1_OCTET_STRING *b = (*b_)->addressFamily;
- int len = ((a->length <= b->length) ? a->length : b->length);
- int cmp = memcmp(a->data, b->data, len);
- return cmp ? cmp : a->length - b->length;
-}
-
-/*
- * Check whether an IPAddrBLocks is in canonical form.
- */
-int X509v3_addr_is_canonical(IPAddrBlocks *addr)
-{
- unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN];
- unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN];
- IPAddressOrRanges *aors;
- int i, j, k;
-
- /*
- * Empty extension is canonical.
- */
- if (addr == NULL)
- return 1;
-
- /*
- * Check whether the top-level list is in order.
- */
- for (i = 0; i < sk_IPAddressFamily_num(addr) - 1; i++) {
- const IPAddressFamily *a = sk_IPAddressFamily_value(addr, i);
- const IPAddressFamily *b = sk_IPAddressFamily_value(addr, i + 1);
- if (IPAddressFamily_cmp(&a, &b) >= 0)
- return 0;
- }
-
- /*
- * Top level's ok, now check each address family.
- */
- for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
- IPAddressFamily *f = sk_IPAddressFamily_value(addr, i);
- int length = length_from_afi(X509v3_addr_get_afi(f));
-
- /*
- * Inheritance is canonical. Anything other than inheritance or
- * a SEQUENCE OF IPAddressOrRange is an ASN.1 error or something.
- */
- if (f == NULL || f->ipAddressChoice == NULL)
- return 0;
- switch (f->ipAddressChoice->type) {
- case IPAddressChoice_inherit:
- continue;
- case IPAddressChoice_addressesOrRanges:
- break;
- default:
- return 0;
- }
-
- /*
- * It's an IPAddressOrRanges sequence, check it.
- */
- aors = f->ipAddressChoice->u.addressesOrRanges;
- if (sk_IPAddressOrRange_num(aors) == 0)
- return 0;
- for (j = 0; j < sk_IPAddressOrRange_num(aors) - 1; j++) {
- IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j);
- IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, j + 1);
-
- if (!extract_min_max(a, a_min, a_max, length) ||
- !extract_min_max(b, b_min, b_max, length))
- return 0;
-
- /*
- * Punt misordered list, overlapping start, or inverted range.
- */
- if (memcmp(a_min, b_min, length) >= 0 ||
- memcmp(a_min, a_max, length) > 0 ||
- memcmp(b_min, b_max, length) > 0)
- return 0;
-
- /*
- * Punt if adjacent or overlapping. Check for adjacency by
- * subtracting one from b_min first.
- */
- for (k = length - 1; k >= 0 && b_min[k]-- == 0x00; k--) ;
- if (memcmp(a_max, b_min, length) >= 0)
- return 0;
-
- /*
- * Check for range that should be expressed as a prefix.
- */
- if (a->type == IPAddressOrRange_addressRange &&
- range_should_be_prefix(a_min, a_max, length) >= 0)
- return 0;
- }
-
- /*
- * Check range to see if it's inverted or should be a
- * prefix.
- */
- j = sk_IPAddressOrRange_num(aors) - 1;
- {
- IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j);
- if (a != NULL && a->type == IPAddressOrRange_addressRange) {
- if (!extract_min_max(a, a_min, a_max, length))
- return 0;
- if (memcmp(a_min, a_max, length) > 0 ||
- range_should_be_prefix(a_min, a_max, length) >= 0)
- return 0;
- }
- }
- }
-
- /*
- * If we made it through all that, we're happy.
- */
- return 1;
-}
-
-/*
- * Whack an IPAddressOrRanges into canonical form.
- */
-static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors,
- const unsigned afi)
-{
- int i, j, length = length_from_afi(afi);
-
- /*
- * Sort the IPAddressOrRanges sequence.
- */
- sk_IPAddressOrRange_sort(aors);
-
- /*
- * Clean up representation issues, punt on duplicates or overlaps.
- */
- for (i = 0; i < sk_IPAddressOrRange_num(aors) - 1; i++) {
- IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, i);
- IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, i + 1);
- unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN];
- unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN];
-
- if (!extract_min_max(a, a_min, a_max, length) ||
- !extract_min_max(b, b_min, b_max, length))
- return 0;
-
- /*
- * Punt inverted ranges.
- */
- if (memcmp(a_min, a_max, length) > 0 ||
- memcmp(b_min, b_max, length) > 0)
- return 0;
-
- /*
- * Punt overlaps.
- */
- if (memcmp(a_max, b_min, length) >= 0)
- return 0;
-
- /*
- * Merge if a and b are adjacent. We check for
- * adjacency by subtracting one from b_min first.
- */
- for (j = length - 1; j >= 0 && b_min[j]-- == 0x00; j--) ;
- if (memcmp(a_max, b_min, length) == 0) {
- IPAddressOrRange *merged;
- if (!make_addressRange(&merged, a_min, b_max, length))
- return 0;
- (void)sk_IPAddressOrRange_set(aors, i, merged);
- (void)sk_IPAddressOrRange_delete(aors, i + 1);
- IPAddressOrRange_free(a);
- IPAddressOrRange_free(b);
- --i;
- continue;
- }
- }
-
- /*
- * Check for inverted final range.
- */
- j = sk_IPAddressOrRange_num(aors) - 1;
- {
- IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j);
- if (a != NULL && a->type == IPAddressOrRange_addressRange) {
- unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN];
- if (!extract_min_max(a, a_min, a_max, length))
- return 0;
- if (memcmp(a_min, a_max, length) > 0)
- return 0;
- }
- }
-
- return 1;
-}
-
-/*
- * Whack an IPAddrBlocks extension into canonical form.
- */
-int X509v3_addr_canonize(IPAddrBlocks *addr)
-{
- int i;
- for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
- IPAddressFamily *f = sk_IPAddressFamily_value(addr, i);
- if (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges &&
- !IPAddressOrRanges_canonize(f->ipAddressChoice->
- u.addressesOrRanges,
- X509v3_addr_get_afi(f)))
- return 0;
- }
- (void)sk_IPAddressFamily_set_cmp_func(addr, IPAddressFamily_cmp);
- sk_IPAddressFamily_sort(addr);
- if (!ossl_assert(X509v3_addr_is_canonical(addr)))
- return 0;
- return 1;
-}
-
-/*
- * v2i handler for the IPAddrBlocks extension.
- */
-static void *v2i_IPAddrBlocks(const struct v3_ext_method *method,
- struct v3_ext_ctx *ctx,
- STACK_OF(CONF_VALUE) *values)
-{
- static const char v4addr_chars[] = "0123456789.";
- static const char v6addr_chars[] = "0123456789.:abcdefABCDEF";
- IPAddrBlocks *addr = NULL;
- char *s = NULL, *t;
- int i;
-
- if ((addr = sk_IPAddressFamily_new(IPAddressFamily_cmp)) == NULL) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
- CONF_VALUE *val = sk_CONF_VALUE_value(values, i);
- unsigned char min[ADDR_RAW_BUF_LEN], max[ADDR_RAW_BUF_LEN];
- unsigned afi, *safi = NULL, safi_;
- const char *addr_chars = NULL;
- int prefixlen, i1, i2, delim, length;
-
- if (!name_cmp(val->name, "IPv4")) {
- afi = IANA_AFI_IPV4;
- } else if (!name_cmp(val->name, "IPv6")) {
- afi = IANA_AFI_IPV6;
- } else if (!name_cmp(val->name, "IPv4-SAFI")) {
- afi = IANA_AFI_IPV4;
- safi = &safi_;
- } else if (!name_cmp(val->name, "IPv6-SAFI")) {
- afi = IANA_AFI_IPV6;
- safi = &safi_;
- } else {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
- X509V3_R_EXTENSION_NAME_ERROR);
- X509V3_conf_err(val);
- goto err;
- }
-
- switch (afi) {
- case IANA_AFI_IPV4:
- addr_chars = v4addr_chars;
- break;
- case IANA_AFI_IPV6:
- addr_chars = v6addr_chars;
- break;
- }
-
- length = length_from_afi(afi);
-
- /*
- * Handle SAFI, if any, and OPENSSL_strdup() so we can null-terminate
- * the other input values.
- */
- if (safi != NULL) {
- *safi = strtoul(val->value, &t, 0);
- t += strspn(t, " \t");
- if (*safi > 0xFF || *t++ != ':') {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_INVALID_SAFI);
- X509V3_conf_err(val);
- goto err;
- }
- t += strspn(t, " \t");
- s = OPENSSL_strdup(t);
- } else {
- s = OPENSSL_strdup(val->value);
- }
- if (s == NULL) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /*
- * Check for inheritance. Not worth additional complexity to
- * optimize this (seldom-used) case.
- */
- if (strcmp(s, "inherit") == 0) {
- if (!X509v3_addr_add_inherit(addr, afi, safi)) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
- X509V3_R_INVALID_INHERITANCE);
- X509V3_conf_err(val);
- goto err;
- }
- OPENSSL_free(s);
- s = NULL;
- continue;
- }
-
- i1 = strspn(s, addr_chars);
- i2 = i1 + strspn(s + i1, " \t");
- delim = s[i2++];
- s[i1] = '\0';
-
- if (a2i_ipadd(min, s) != length) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_INVALID_IPADDRESS);
- X509V3_conf_err(val);
- goto err;
- }
-
- switch (delim) {
- case '/':
- prefixlen = (int)strtoul(s + i2, &t, 10);
- if (t == s + i2
- || *t != '\0'
- || prefixlen > (length * 8)
- || prefixlen < 0) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
- X509V3_R_EXTENSION_VALUE_ERROR);
- X509V3_conf_err(val);
- goto err;
- }
- if (!X509v3_addr_add_prefix(addr, afi, safi, min, prefixlen)) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- break;
- case '-':
- i1 = i2 + strspn(s + i2, " \t");
- i2 = i1 + strspn(s + i1, addr_chars);
- if (i1 == i2 || s[i2] != '\0') {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
- X509V3_R_EXTENSION_VALUE_ERROR);
- X509V3_conf_err(val);
- goto err;
- }
- if (a2i_ipadd(max, s + i1) != length) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
- X509V3_R_INVALID_IPADDRESS);
- X509V3_conf_err(val);
- goto err;
- }
- if (memcmp(min, max, length_from_afi(afi)) > 0) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
- X509V3_R_EXTENSION_VALUE_ERROR);
- X509V3_conf_err(val);
- goto err;
- }
- if (!X509v3_addr_add_range(addr, afi, safi, min, max)) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- break;
- case '\0':
- if (!X509v3_addr_add_prefix(addr, afi, safi, min, length * 8)) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- break;
- default:
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
- X509V3_R_EXTENSION_VALUE_ERROR);
- X509V3_conf_err(val);
- goto err;
- }
-
- OPENSSL_free(s);
- s = NULL;
- }
-
- /*
- * Canonize the result, then we're done.
- */
- if (!X509v3_addr_canonize(addr))
- goto err;
- return addr;
-
- err:
- OPENSSL_free(s);
- sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free);
- return NULL;
-}
-
-/*
- * OpenSSL dispatch
- */
-const X509V3_EXT_METHOD v3_addr = {
- NID_sbgp_ipAddrBlock, /* nid */
- 0, /* flags */
- ASN1_ITEM_ref(IPAddrBlocks), /* template */
- 0, 0, 0, 0, /* old functions, ignored */
- 0, /* i2s */
- 0, /* s2i */
- 0, /* i2v */
- v2i_IPAddrBlocks, /* v2i */
- i2r_IPAddrBlocks, /* i2r */
- 0, /* r2i */
- NULL /* extension-specific data */
-};
-
-/*
- * Figure out whether extension sues inheritance.
- */
-int X509v3_addr_inherits(IPAddrBlocks *addr)
-{
- int i;
- if (addr == NULL)
- return 0;
- for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
- IPAddressFamily *f = sk_IPAddressFamily_value(addr, i);
- if (f->ipAddressChoice->type == IPAddressChoice_inherit)
- return 1;
- }
- return 0;
-}
-
-/*
- * Figure out whether parent contains child.
- */
-static int addr_contains(IPAddressOrRanges *parent,
- IPAddressOrRanges *child, int length)
-{
- unsigned char p_min[ADDR_RAW_BUF_LEN], p_max[ADDR_RAW_BUF_LEN];
- unsigned char c_min[ADDR_RAW_BUF_LEN], c_max[ADDR_RAW_BUF_LEN];
- int p, c;
-
- if (child == NULL || parent == child)
- return 1;
- if (parent == NULL)
- return 0;
-
- p = 0;
- for (c = 0; c < sk_IPAddressOrRange_num(child); c++) {
- if (!extract_min_max(sk_IPAddressOrRange_value(child, c),
- c_min, c_max, length))
- return -1;
- for (;; p++) {
- if (p >= sk_IPAddressOrRange_num(parent))
- return 0;
- if (!extract_min_max(sk_IPAddressOrRange_value(parent, p),
- p_min, p_max, length))
- return 0;
- if (memcmp(p_max, c_max, length) < 0)
- continue;
- if (memcmp(p_min, c_min, length) > 0)
- return 0;
- break;
- }
- }
-
- return 1;
-}
-
-/*
- * Test whether a is a subset of b.
- */
-int X509v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b)
-{
- int i;
- if (a == NULL || a == b)
- return 1;
- if (b == NULL || X509v3_addr_inherits(a) || X509v3_addr_inherits(b))
- return 0;
- (void)sk_IPAddressFamily_set_cmp_func(b, IPAddressFamily_cmp);
- for (i = 0; i < sk_IPAddressFamily_num(a); i++) {
- IPAddressFamily *fa = sk_IPAddressFamily_value(a, i);
- int j = sk_IPAddressFamily_find(b, fa);
- IPAddressFamily *fb;
- fb = sk_IPAddressFamily_value(b, j);
- if (fb == NULL)
- return 0;
- if (!addr_contains(fb->ipAddressChoice->u.addressesOrRanges,
- fa->ipAddressChoice->u.addressesOrRanges,
- length_from_afi(X509v3_addr_get_afi(fb))))
- return 0;
- }
- return 1;
-}
-
-/*
- * Validation error handling via callback.
- */
-#define validation_err(_err_) \
- do { \
- if (ctx != NULL) { \
- ctx->error = _err_; \
- ctx->error_depth = i; \
- ctx->current_cert = x; \
- ret = ctx->verify_cb(0, ctx); \
- } else { \
- ret = 0; \
- } \
- if (!ret) \
- goto done; \
- } while (0)
-
-/*
- * Core code for RFC 3779 2.3 path validation.
- *
- * Returns 1 for success, 0 on error.
- *
- * When returning 0, ctx->error MUST be set to an appropriate value other than
- * X509_V_OK.
- */
-static int addr_validate_path_internal(X509_STORE_CTX *ctx,
- STACK_OF(X509) *chain,
- IPAddrBlocks *ext)
-{
- IPAddrBlocks *child = NULL;
- int i, j, ret = 1;
- X509 *x;
-
- if (!ossl_assert(chain != NULL && sk_X509_num(chain) > 0)
- || !ossl_assert(ctx != NULL || ext != NULL)
- || !ossl_assert(ctx == NULL || ctx->verify_cb != NULL)) {
- if (ctx != NULL)
- ctx->error = X509_V_ERR_UNSPECIFIED;
- return 0;
- }
-
- /*
- * Figure out where to start. If we don't have an extension to
- * check, we're done. Otherwise, check canonical form and
- * set up for walking up the chain.
- */
- if (ext != NULL) {
- i = -1;
- x = NULL;
- } else {
- i = 0;
- x = sk_X509_value(chain, i);
- if ((ext = x->rfc3779_addr) == NULL)
- goto done;
- }
- if (!X509v3_addr_is_canonical(ext))
- validation_err(X509_V_ERR_INVALID_EXTENSION);
- (void)sk_IPAddressFamily_set_cmp_func(ext, IPAddressFamily_cmp);
- if ((child = sk_IPAddressFamily_dup(ext)) == NULL) {
- X509V3err(X509V3_F_ADDR_VALIDATE_PATH_INTERNAL,
- ERR_R_MALLOC_FAILURE);
- if (ctx != NULL)
- ctx->error = X509_V_ERR_OUT_OF_MEM;
- ret = 0;
- goto done;
- }
-
- /*
- * Now walk up the chain. No cert may list resources that its
- * parent doesn't list.
- */
- for (i++; i < sk_X509_num(chain); i++) {
- x = sk_X509_value(chain, i);
- if (!X509v3_addr_is_canonical(x->rfc3779_addr))
- validation_err(X509_V_ERR_INVALID_EXTENSION);
- if (x->rfc3779_addr == NULL) {
- for (j = 0; j < sk_IPAddressFamily_num(child); j++) {
- IPAddressFamily *fc = sk_IPAddressFamily_value(child, j);
- if (fc->ipAddressChoice->type != IPAddressChoice_inherit) {
- validation_err(X509_V_ERR_UNNESTED_RESOURCE);
- break;
- }
- }
- continue;
- }
- (void)sk_IPAddressFamily_set_cmp_func(x->rfc3779_addr,
- IPAddressFamily_cmp);
- for (j = 0; j < sk_IPAddressFamily_num(child); j++) {
- IPAddressFamily *fc = sk_IPAddressFamily_value(child, j);
- int k = sk_IPAddressFamily_find(x->rfc3779_addr, fc);
- IPAddressFamily *fp =
- sk_IPAddressFamily_value(x->rfc3779_addr, k);
- if (fp == NULL) {
- if (fc->ipAddressChoice->type ==
- IPAddressChoice_addressesOrRanges) {
- validation_err(X509_V_ERR_UNNESTED_RESOURCE);
- break;
- }
- continue;
- }
- if (fp->ipAddressChoice->type ==
- IPAddressChoice_addressesOrRanges) {
- if (fc->ipAddressChoice->type == IPAddressChoice_inherit
- || addr_contains(fp->ipAddressChoice->u.addressesOrRanges,
- fc->ipAddressChoice->u.addressesOrRanges,
- length_from_afi(X509v3_addr_get_afi(fc))))
- sk_IPAddressFamily_set(child, j, fp);
- else
- validation_err(X509_V_ERR_UNNESTED_RESOURCE);
- }
- }
- }
-
- /*
- * Trust anchor can't inherit.
- */
- if (x->rfc3779_addr != NULL) {
- for (j = 0; j < sk_IPAddressFamily_num(x->rfc3779_addr); j++) {
- IPAddressFamily *fp =
- sk_IPAddressFamily_value(x->rfc3779_addr, j);
- if (fp->ipAddressChoice->type == IPAddressChoice_inherit
- && sk_IPAddressFamily_find(child, fp) >= 0)
- validation_err(X509_V_ERR_UNNESTED_RESOURCE);
- }
- }
-
- done:
- sk_IPAddressFamily_free(child);
- return ret;
-}
-
-#undef validation_err
-
-/*
- * RFC 3779 2.3 path validation -- called from X509_verify_cert().
- */
-int X509v3_addr_validate_path(X509_STORE_CTX *ctx)
-{
- if (ctx->chain == NULL
- || sk_X509_num(ctx->chain) == 0
- || ctx->verify_cb == NULL) {
- ctx->error = X509_V_ERR_UNSPECIFIED;
- return 0;
- }
- return addr_validate_path_internal(ctx, ctx->chain, NULL);
-}
-
-/*
- * RFC 3779 2.3 path validation of an extension.
- * Test whether chain covers extension.
- */
-int X509v3_addr_validate_resource_set(STACK_OF(X509) *chain,
- IPAddrBlocks *ext, int allow_inheritance)
-{
- if (ext == NULL)
- return 1;
- if (chain == NULL || sk_X509_num(chain) == 0)
- return 0;
- if (!allow_inheritance && X509v3_addr_inherits(ext))
- return 0;
- return addr_validate_path_internal(NULL, chain, ext);
-}
-
-#endif /* OPENSSL_NO_RFC3779 */
diff --git a/crypto/x509v3/v3_admis.c b/crypto/x509v3/v3_admis.c
deleted file mode 100644
index c8e75191bb3b..000000000000
--- a/crypto/x509v3/v3_admis.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/conf.h>
-#include <openssl/ossl_typ.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-
-#include <openssl/x509v3.h>
-
-#include <openssl/safestack.h>
-
-#include "v3_admis.h"
-#include "ext_dat.h"
-
-
-ASN1_SEQUENCE(NAMING_AUTHORITY) = {
- ASN1_OPT(NAMING_AUTHORITY, namingAuthorityId, ASN1_OBJECT),
- ASN1_OPT(NAMING_AUTHORITY, namingAuthorityUrl, ASN1_IA5STRING),
- ASN1_OPT(NAMING_AUTHORITY, namingAuthorityText, DIRECTORYSTRING),
-} ASN1_SEQUENCE_END(NAMING_AUTHORITY)
-
-ASN1_SEQUENCE(PROFESSION_INFO) = {
- ASN1_EXP_OPT(PROFESSION_INFO, namingAuthority, NAMING_AUTHORITY, 0),
- ASN1_SEQUENCE_OF(PROFESSION_INFO, professionItems, DIRECTORYSTRING),
- ASN1_SEQUENCE_OF_OPT(PROFESSION_INFO, professionOIDs, ASN1_OBJECT),
- ASN1_OPT(PROFESSION_INFO, registrationNumber, ASN1_PRINTABLESTRING),
- ASN1_OPT(PROFESSION_INFO, addProfessionInfo, ASN1_OCTET_STRING),
-} ASN1_SEQUENCE_END(PROFESSION_INFO)
-
-ASN1_SEQUENCE(ADMISSIONS) = {
- ASN1_EXP_OPT(ADMISSIONS, admissionAuthority, GENERAL_NAME, 0),
- ASN1_EXP_OPT(ADMISSIONS, namingAuthority, NAMING_AUTHORITY, 1),
- ASN1_SEQUENCE_OF(ADMISSIONS, professionInfos, PROFESSION_INFO),
-} ASN1_SEQUENCE_END(ADMISSIONS)
-
-ASN1_SEQUENCE(ADMISSION_SYNTAX) = {
- ASN1_OPT(ADMISSION_SYNTAX, admissionAuthority, GENERAL_NAME),
- ASN1_SEQUENCE_OF(ADMISSION_SYNTAX, contentsOfAdmissions, ADMISSIONS),
-} ASN1_SEQUENCE_END(ADMISSION_SYNTAX)
-
-IMPLEMENT_ASN1_FUNCTIONS(NAMING_AUTHORITY)
-IMPLEMENT_ASN1_FUNCTIONS(PROFESSION_INFO)
-IMPLEMENT_ASN1_FUNCTIONS(ADMISSIONS)
-IMPLEMENT_ASN1_FUNCTIONS(ADMISSION_SYNTAX)
-
-static int i2r_ADMISSION_SYNTAX(const struct v3_ext_method *method, void *in,
- BIO *bp, int ind);
-
-const X509V3_EXT_METHOD v3_ext_admission = {
- NID_x509ExtAdmission, /* .ext_nid = */
- 0, /* .ext_flags = */
- ASN1_ITEM_ref(ADMISSION_SYNTAX), /* .it = */
- NULL, NULL, NULL, NULL,
- NULL, /* .i2s = */
- NULL, /* .s2i = */
- NULL, /* .i2v = */
- NULL, /* .v2i = */
- &i2r_ADMISSION_SYNTAX, /* .i2r = */
- NULL, /* .r2i = */
- NULL /* extension-specific data */
-};
-
-
-static int i2r_NAMING_AUTHORITY(const struct v3_ext_method *method, void *in,
- BIO *bp, int ind)
-{
- NAMING_AUTHORITY * namingAuthority = (NAMING_AUTHORITY*) in;
-
- if (namingAuthority == NULL)
- return 0;
-
- if (namingAuthority->namingAuthorityId == NULL
- && namingAuthority->namingAuthorityText == NULL
- && namingAuthority->namingAuthorityUrl == NULL)
- return 0;
-
- if (BIO_printf(bp, "%*snamingAuthority: ", ind, "") <= 0)
- goto err;
-
- if (namingAuthority->namingAuthorityId != NULL) {
- char objbuf[128];
- const char *ln = OBJ_nid2ln(OBJ_obj2nid(namingAuthority->namingAuthorityId));
-
- if (BIO_printf(bp, "%*s admissionAuthorityId: ", ind, "") <= 0)
- goto err;
-
- OBJ_obj2txt(objbuf, sizeof(objbuf), namingAuthority->namingAuthorityId, 1);
-
- if (BIO_printf(bp, "%s%s%s%s\n", ln ? ln : "",
- ln ? " (" : "", objbuf, ln ? ")" : "") <= 0)
- goto err;
- }
- if (namingAuthority->namingAuthorityText != NULL) {
- if (BIO_printf(bp, "%*s namingAuthorityText: ", ind, "") <= 0
- || ASN1_STRING_print(bp, namingAuthority->namingAuthorityText) <= 0
- || BIO_printf(bp, "\n") <= 0)
- goto err;
- }
- if (namingAuthority->namingAuthorityUrl != NULL ) {
- if (BIO_printf(bp, "%*s namingAuthorityUrl: ", ind, "") <= 0
- || ASN1_STRING_print(bp, namingAuthority->namingAuthorityUrl) <= 0
- || BIO_printf(bp, "\n") <= 0)
- goto err;
- }
- return 1;
-
-err:
- return 0;
-}
-
-static int i2r_ADMISSION_SYNTAX(const struct v3_ext_method *method, void *in,
- BIO *bp, int ind)
-{
- ADMISSION_SYNTAX * admission = (ADMISSION_SYNTAX *)in;
- int i, j, k;
-
- if (admission->admissionAuthority != NULL) {
- if (BIO_printf(bp, "%*sadmissionAuthority:\n", ind, "") <= 0
- || BIO_printf(bp, "%*s ", ind, "") <= 0
- || GENERAL_NAME_print(bp, admission->admissionAuthority) <= 0
- || BIO_printf(bp, "\n") <= 0)
- goto err;
- }
-
- for (i = 0; i < sk_ADMISSIONS_num(admission->contentsOfAdmissions); i++) {
- ADMISSIONS* entry = sk_ADMISSIONS_value(admission->contentsOfAdmissions, i);
-
- if (BIO_printf(bp, "%*sEntry %0d:\n", ind, "", 1 + i) <= 0) goto err;
-
- if (entry->admissionAuthority != NULL) {
- if (BIO_printf(bp, "%*s admissionAuthority:\n", ind, "") <= 0
- || BIO_printf(bp, "%*s ", ind, "") <= 0
- || GENERAL_NAME_print(bp, entry->admissionAuthority) <= 0
- || BIO_printf(bp, "\n") <= 0)
- goto err;
- }
-
- if (entry->namingAuthority != NULL) {
- if (i2r_NAMING_AUTHORITY(method, entry->namingAuthority, bp, ind) <= 0)
- goto err;
- }
-
- for (j = 0; j < sk_PROFESSION_INFO_num(entry->professionInfos); j++) {
- PROFESSION_INFO* pinfo = sk_PROFESSION_INFO_value(entry->professionInfos, j);
-
- if (BIO_printf(bp, "%*s Profession Info Entry %0d:\n", ind, "", 1 + j) <= 0)
- goto err;
-
- if (pinfo->registrationNumber != NULL) {
- if (BIO_printf(bp, "%*s registrationNumber: ", ind, "") <= 0
- || ASN1_STRING_print(bp, pinfo->registrationNumber) <= 0
- || BIO_printf(bp, "\n") <= 0)
- goto err;
- }
-
- if (pinfo->namingAuthority != NULL) {
- if (i2r_NAMING_AUTHORITY(method, pinfo->namingAuthority, bp, ind + 2) <= 0)
- goto err;
- }
-
- if (pinfo->professionItems != NULL) {
-
- if (BIO_printf(bp, "%*s Info Entries:\n", ind, "") <= 0)
- goto err;
- for (k = 0; k < sk_ASN1_STRING_num(pinfo->professionItems); k++) {
- ASN1_STRING* val = sk_ASN1_STRING_value(pinfo->professionItems, k);
-
- if (BIO_printf(bp, "%*s ", ind, "") <= 0
- || ASN1_STRING_print(bp, val) <= 0
- || BIO_printf(bp, "\n") <= 0)
- goto err;
- }
- }
-
- if (pinfo->professionOIDs != NULL) {
- if (BIO_printf(bp, "%*s Profession OIDs:\n", ind, "") <= 0)
- goto err;
- for (k = 0; k < sk_ASN1_OBJECT_num(pinfo->professionOIDs); k++) {
- ASN1_OBJECT* obj = sk_ASN1_OBJECT_value(pinfo->professionOIDs, k);
- const char *ln = OBJ_nid2ln(OBJ_obj2nid(obj));
- char objbuf[128];
-
- OBJ_obj2txt(objbuf, sizeof(objbuf), obj, 1);
- if (BIO_printf(bp, "%*s %s%s%s%s\n", ind, "",
- ln ? ln : "", ln ? " (" : "",
- objbuf, ln ? ")" : "") <= 0)
- goto err;
- }
- }
- }
- }
- return 1;
-
-err:
- return -1;
-}
-
-const ASN1_OBJECT *NAMING_AUTHORITY_get0_authorityId(const NAMING_AUTHORITY *n)
-{
- return n->namingAuthorityId;
-}
-
-void NAMING_AUTHORITY_set0_authorityId(NAMING_AUTHORITY *n, ASN1_OBJECT* id)
-{
- ASN1_OBJECT_free(n->namingAuthorityId);
- n->namingAuthorityId = id;
-}
-
-const ASN1_IA5STRING *NAMING_AUTHORITY_get0_authorityURL(
- const NAMING_AUTHORITY *n)
-{
- return n->namingAuthorityUrl;
-}
-
-void NAMING_AUTHORITY_set0_authorityURL(NAMING_AUTHORITY *n, ASN1_IA5STRING* u)
-{
- ASN1_IA5STRING_free(n->namingAuthorityUrl);
- n->namingAuthorityUrl = u;
-}
-
-const ASN1_STRING *NAMING_AUTHORITY_get0_authorityText(
- const NAMING_AUTHORITY *n)
-{
- return n->namingAuthorityText;
-}
-
-void NAMING_AUTHORITY_set0_authorityText(NAMING_AUTHORITY *n, ASN1_STRING* t)
-{
- ASN1_IA5STRING_free(n->namingAuthorityText);
- n->namingAuthorityText = t;
-}
-
-const GENERAL_NAME *ADMISSION_SYNTAX_get0_admissionAuthority(const ADMISSION_SYNTAX *as)
-{
- return as->admissionAuthority;
-}
-
-void ADMISSION_SYNTAX_set0_admissionAuthority(ADMISSION_SYNTAX *as,
- GENERAL_NAME *aa)
-{
- GENERAL_NAME_free(as->admissionAuthority);
- as->admissionAuthority = aa;
-}
-
-const STACK_OF(ADMISSIONS) *ADMISSION_SYNTAX_get0_contentsOfAdmissions(const ADMISSION_SYNTAX *as)
-{
- return as->contentsOfAdmissions;
-}
-
-void ADMISSION_SYNTAX_set0_contentsOfAdmissions(ADMISSION_SYNTAX *as,
- STACK_OF(ADMISSIONS) *a)
-{
- sk_ADMISSIONS_pop_free(as->contentsOfAdmissions, ADMISSIONS_free);
- as->contentsOfAdmissions = a;
-}
-
-const GENERAL_NAME *ADMISSIONS_get0_admissionAuthority(const ADMISSIONS *a)
-{
- return a->admissionAuthority;
-}
-
-void ADMISSIONS_set0_admissionAuthority(ADMISSIONS *a, GENERAL_NAME *aa)
-{
- GENERAL_NAME_free(a->admissionAuthority);
- a->admissionAuthority = aa;
-}
-
-const NAMING_AUTHORITY *ADMISSIONS_get0_namingAuthority(const ADMISSIONS *a)
-{
- return a->namingAuthority;
-}
-
-void ADMISSIONS_set0_namingAuthority(ADMISSIONS *a, NAMING_AUTHORITY *na)
-{
- NAMING_AUTHORITY_free(a->namingAuthority);
- a->namingAuthority = na;
-}
-
-const PROFESSION_INFOS *ADMISSIONS_get0_professionInfos(const ADMISSIONS *a)
-{
- return a->professionInfos;
-}
-
-void ADMISSIONS_set0_professionInfos(ADMISSIONS *a, PROFESSION_INFOS *pi)
-{
- sk_PROFESSION_INFO_pop_free(a->professionInfos, PROFESSION_INFO_free);
- a->professionInfos = pi;
-}
-
-const ASN1_OCTET_STRING *PROFESSION_INFO_get0_addProfessionInfo(const PROFESSION_INFO *pi)
-{
- return pi->addProfessionInfo;
-}
-
-void PROFESSION_INFO_set0_addProfessionInfo(PROFESSION_INFO *pi,
- ASN1_OCTET_STRING *aos)
-{
- ASN1_OCTET_STRING_free(pi->addProfessionInfo);
- pi->addProfessionInfo = aos;
-}
-
-const NAMING_AUTHORITY *PROFESSION_INFO_get0_namingAuthority(const PROFESSION_INFO *pi)
-{
- return pi->namingAuthority;
-}
-
-void PROFESSION_INFO_set0_namingAuthority(PROFESSION_INFO *pi,
- NAMING_AUTHORITY *na)
-{
- NAMING_AUTHORITY_free(pi->namingAuthority);
- pi->namingAuthority = na;
-}
-
-const STACK_OF(ASN1_STRING) *PROFESSION_INFO_get0_professionItems(const PROFESSION_INFO *pi)
-{
- return pi->professionItems;
-}
-
-void PROFESSION_INFO_set0_professionItems(PROFESSION_INFO *pi,
- STACK_OF(ASN1_STRING) *as)
-{
- sk_ASN1_STRING_pop_free(pi->professionItems, ASN1_STRING_free);
- pi->professionItems = as;
-}
-
-const STACK_OF(ASN1_OBJECT) *PROFESSION_INFO_get0_professionOIDs(const PROFESSION_INFO *pi)
-{
- return pi->professionOIDs;
-}
-
-void PROFESSION_INFO_set0_professionOIDs(PROFESSION_INFO *pi,
- STACK_OF(ASN1_OBJECT) *po)
-{
- sk_ASN1_OBJECT_pop_free(pi->professionOIDs, ASN1_OBJECT_free);
- pi->professionOIDs = po;
-}
-
-const ASN1_PRINTABLESTRING *PROFESSION_INFO_get0_registrationNumber(const PROFESSION_INFO *pi)
-{
- return pi->registrationNumber;
-}
-
-void PROFESSION_INFO_set0_registrationNumber(PROFESSION_INFO *pi,
- ASN1_PRINTABLESTRING *rn)
-{
- ASN1_PRINTABLESTRING_free(pi->registrationNumber);
- pi->registrationNumber = rn;
-}
diff --git a/crypto/x509v3/v3_admis.h b/crypto/x509v3/v3_admis.h
deleted file mode 100644
index ea7632b3708d..000000000000
--- a/crypto/x509v3/v3_admis.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef OSSL_CRYPTO_X509V3_V3_ADMIS_H
-# define OSSL_CRYPTO_X509V3_V3_ADMIS_H
-
-struct NamingAuthority_st {
- ASN1_OBJECT* namingAuthorityId;
- ASN1_IA5STRING* namingAuthorityUrl;
- ASN1_STRING* namingAuthorityText; /* i.e. DIRECTORYSTRING */
-};
-
-struct ProfessionInfo_st {
- NAMING_AUTHORITY* namingAuthority;
- STACK_OF(ASN1_STRING)* professionItems; /* i.e. DIRECTORYSTRING */
- STACK_OF(ASN1_OBJECT)* professionOIDs;
- ASN1_PRINTABLESTRING* registrationNumber;
- ASN1_OCTET_STRING* addProfessionInfo;
-};
-
-struct Admissions_st {
- GENERAL_NAME* admissionAuthority;
- NAMING_AUTHORITY* namingAuthority;
- STACK_OF(PROFESSION_INFO)* professionInfos;
-};
-
-struct AdmissionSyntax_st {
- GENERAL_NAME* admissionAuthority;
- STACK_OF(ADMISSIONS)* contentsOfAdmissions;
-};
-
-#endif
diff --git a/crypto/x509v3/v3_akey.c b/crypto/x509v3/v3_akey.c
deleted file mode 100644
index 33b1933d7228..000000000000
--- a/crypto/x509v3/v3_akey.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/conf.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-#include <openssl/x509v3.h>
-#include "ext_dat.h"
-
-static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
- AUTHORITY_KEYID *akeyid,
- STACK_OF(CONF_VALUE)
- *extlist);
-static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *values);
-
-const X509V3_EXT_METHOD v3_akey_id = {
- NID_authority_key_identifier,
- X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_KEYID),
- 0, 0, 0, 0,
- 0, 0,
- (X509V3_EXT_I2V) i2v_AUTHORITY_KEYID,
- (X509V3_EXT_V2I)v2i_AUTHORITY_KEYID,
- 0, 0,
- NULL
-};
-
-static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
- AUTHORITY_KEYID *akeyid,
- STACK_OF(CONF_VALUE)
- *extlist)
-{
- char *tmp = NULL;
- STACK_OF(CONF_VALUE) *origextlist = extlist, *tmpextlist;
-
- if (akeyid->keyid) {
- tmp = OPENSSL_buf2hexstr(akeyid->keyid->data, akeyid->keyid->length);
- if (tmp == NULL) {
- X509V3err(X509V3_F_I2V_AUTHORITY_KEYID, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- if (!X509V3_add_value("keyid", tmp, &extlist)) {
- OPENSSL_free(tmp);
- X509V3err(X509V3_F_I2V_AUTHORITY_KEYID, ERR_R_X509_LIB);
- goto err;
- }
- OPENSSL_free(tmp);
- }
- if (akeyid->issuer) {
- tmpextlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist);
- if (tmpextlist == NULL) {
- X509V3err(X509V3_F_I2V_AUTHORITY_KEYID, ERR_R_X509_LIB);
- goto err;
- }
- extlist = tmpextlist;
- }
- if (akeyid->serial) {
- tmp = OPENSSL_buf2hexstr(akeyid->serial->data, akeyid->serial->length);
- if (tmp == NULL) {
- X509V3err(X509V3_F_I2V_AUTHORITY_KEYID, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if (!X509V3_add_value("serial", tmp, &extlist)) {
- OPENSSL_free(tmp);
- X509V3err(X509V3_F_I2V_AUTHORITY_KEYID, ERR_R_X509_LIB);
- goto err;
- }
- OPENSSL_free(tmp);
- }
- return extlist;
- err:
- if (origextlist == NULL)
- sk_CONF_VALUE_pop_free(extlist, X509V3_conf_free);
- return NULL;
-}
-
-/*-
- * Currently two options:
- * keyid: use the issuers subject keyid, the value 'always' means its is
- * an error if the issuer certificate doesn't have a key id.
- * issuer: use the issuers cert issuer and serial number. The default is
- * to only use this if keyid is not present. With the option 'always'
- * this is always included.
- */
-
-static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *values)
-{
- char keyid = 0, issuer = 0;
- int i;
- CONF_VALUE *cnf;
- ASN1_OCTET_STRING *ikeyid = NULL;
- X509_NAME *isname = NULL;
- GENERAL_NAMES *gens = NULL;
- GENERAL_NAME *gen = NULL;
- ASN1_INTEGER *serial = NULL;
- X509_EXTENSION *ext;
- X509 *cert;
- AUTHORITY_KEYID *akeyid;
-
- for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
- cnf = sk_CONF_VALUE_value(values, i);
- if (strcmp(cnf->name, "keyid") == 0) {
- keyid = 1;
- if (cnf->value && strcmp(cnf->value, "always") == 0)
- keyid = 2;
- } else if (strcmp(cnf->name, "issuer") == 0) {
- issuer = 1;
- if (cnf->value && strcmp(cnf->value, "always") == 0)
- issuer = 2;
- } else {
- X509V3err(X509V3_F_V2I_AUTHORITY_KEYID, X509V3_R_UNKNOWN_OPTION);
- ERR_add_error_data(2, "name=", cnf->name);
- return NULL;
- }
- }
-
- if (!ctx || !ctx->issuer_cert) {
- if (ctx && (ctx->flags == CTX_TEST))
- return AUTHORITY_KEYID_new();
- X509V3err(X509V3_F_V2I_AUTHORITY_KEYID,
- X509V3_R_NO_ISSUER_CERTIFICATE);
- return NULL;
- }
-
- cert = ctx->issuer_cert;
-
- if (keyid) {
- i = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1);
- if ((i >= 0) && (ext = X509_get_ext(cert, i)))
- ikeyid = X509V3_EXT_d2i(ext);
- if (keyid == 2 && !ikeyid) {
- X509V3err(X509V3_F_V2I_AUTHORITY_KEYID,
- X509V3_R_UNABLE_TO_GET_ISSUER_KEYID);
- return NULL;
- }
- }
-
- if ((issuer && !ikeyid) || (issuer == 2)) {
- isname = X509_NAME_dup(X509_get_issuer_name(cert));
- serial = ASN1_INTEGER_dup(X509_get_serialNumber(cert));
- if (!isname || !serial) {
- X509V3err(X509V3_F_V2I_AUTHORITY_KEYID,
- X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS);
- goto err;
- }
- }
-
- if ((akeyid = AUTHORITY_KEYID_new()) == NULL)
- goto err;
-
- if (isname) {
- if ((gens = sk_GENERAL_NAME_new_null()) == NULL
- || (gen = GENERAL_NAME_new()) == NULL
- || !sk_GENERAL_NAME_push(gens, gen)) {
- X509V3err(X509V3_F_V2I_AUTHORITY_KEYID, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- gen->type = GEN_DIRNAME;
- gen->d.dirn = isname;
- }
-
- akeyid->issuer = gens;
- gen = NULL;
- gens = NULL;
- akeyid->serial = serial;
- akeyid->keyid = ikeyid;
-
- return akeyid;
-
- err:
- sk_GENERAL_NAME_free(gens);
- GENERAL_NAME_free(gen);
- X509_NAME_free(isname);
- ASN1_INTEGER_free(serial);
- ASN1_OCTET_STRING_free(ikeyid);
- return NULL;
-}
diff --git a/crypto/x509v3/v3_akeya.c b/crypto/x509v3/v3_akeya.c
deleted file mode 100644
index d6dd6bcb9b96..000000000000
--- a/crypto/x509v3/v3_akeya.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/conf.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-#include <openssl/x509v3.h>
-
-ASN1_SEQUENCE(AUTHORITY_KEYID) = {
- ASN1_IMP_OPT(AUTHORITY_KEYID, keyid, ASN1_OCTET_STRING, 0),
- ASN1_IMP_SEQUENCE_OF_OPT(AUTHORITY_KEYID, issuer, GENERAL_NAME, 1),
- ASN1_IMP_OPT(AUTHORITY_KEYID, serial, ASN1_INTEGER, 2)
-} ASN1_SEQUENCE_END(AUTHORITY_KEYID)
-
-IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_KEYID)
diff --git a/crypto/x509v3/v3_alt.c b/crypto/x509v3/v3_alt.c
deleted file mode 100644
index 7c32d4031d11..000000000000
--- a/crypto/x509v3/v3_alt.c
+++ /dev/null
@@ -1,613 +0,0 @@
-/*
- * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include "crypto/x509.h"
-#include <openssl/conf.h>
-#include <openssl/x509v3.h>
-#include "ext_dat.h"
-
-static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval);
-static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval);
-static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
-static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
-static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
-static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
-
-const X509V3_EXT_METHOD v3_alt[3] = {
- {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
- 0, 0, 0, 0,
- 0, 0,
- (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
- (X509V3_EXT_V2I)v2i_subject_alt,
- NULL, NULL, NULL},
-
- {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
- 0, 0, 0, 0,
- 0, 0,
- (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
- (X509V3_EXT_V2I)v2i_issuer_alt,
- NULL, NULL, NULL},
-
- {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES),
- 0, 0, 0, 0,
- 0, 0,
- (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
- NULL, NULL, NULL, NULL},
-};
-
-STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
- GENERAL_NAMES *gens,
- STACK_OF(CONF_VALUE) *ret)
-{
- int i;
- GENERAL_NAME *gen;
- STACK_OF(CONF_VALUE) *tmpret = NULL, *origret = ret;
-
- for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
- gen = sk_GENERAL_NAME_value(gens, i);
- /*
- * i2v_GENERAL_NAME allocates ret if it is NULL. If something goes
- * wrong we need to free the stack - but only if it was empty when we
- * originally entered this function.
- */
- tmpret = i2v_GENERAL_NAME(method, gen, ret);
- if (tmpret == NULL) {
- if (origret == NULL)
- sk_CONF_VALUE_pop_free(ret, X509V3_conf_free);
- return NULL;
- }
- ret = tmpret;
- }
- if (ret == NULL)
- return sk_CONF_VALUE_new_null();
- return ret;
-}
-
-STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
- GENERAL_NAME *gen,
- STACK_OF(CONF_VALUE) *ret)
-{
- unsigned char *p;
- char oline[256], htmp[5];
- int i;
-
- switch (gen->type) {
- case GEN_OTHERNAME:
- if (!X509V3_add_value("othername", "<unsupported>", &ret))
- return NULL;
- break;
-
- case GEN_X400:
- if (!X509V3_add_value("X400Name", "<unsupported>", &ret))
- return NULL;
- break;
-
- case GEN_EDIPARTY:
- if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret))
- return NULL;
- break;
-
- case GEN_EMAIL:
- if (!x509v3_add_len_value_uchar("email", gen->d.ia5->data,
- gen->d.ia5->length, &ret))
- return NULL;
- break;
-
- case GEN_DNS:
- if (!x509v3_add_len_value_uchar("DNS", gen->d.ia5->data,
- gen->d.ia5->length, &ret))
- return NULL;
- break;
-
- case GEN_URI:
- if (!x509v3_add_len_value_uchar("URI", gen->d.ia5->data,
- gen->d.ia5->length, &ret))
- return NULL;
- break;
-
- case GEN_DIRNAME:
- if (X509_NAME_oneline(gen->d.dirn, oline, sizeof(oline)) == NULL
- || !X509V3_add_value("DirName", oline, &ret))
- return NULL;
- break;
-
- case GEN_IPADD:
- p = gen->d.ip->data;
- if (gen->d.ip->length == 4)
- BIO_snprintf(oline, sizeof(oline), "%d.%d.%d.%d",
- p[0], p[1], p[2], p[3]);
- else if (gen->d.ip->length == 16) {
- oline[0] = 0;
- for (i = 0; i < 8; i++) {
- BIO_snprintf(htmp, sizeof(htmp), "%X", p[0] << 8 | p[1]);
- p += 2;
- strcat(oline, htmp);
- if (i != 7)
- strcat(oline, ":");
- }
- } else {
- if (!X509V3_add_value("IP Address", "<invalid>", &ret))
- return NULL;
- break;
- }
- if (!X509V3_add_value("IP Address", oline, &ret))
- return NULL;
- break;
-
- case GEN_RID:
- i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
- if (!X509V3_add_value("Registered ID", oline, &ret))
- return NULL;
- break;
- }
- return ret;
-}
-
-int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
-{
- unsigned char *p;
- int i;
- switch (gen->type) {
- case GEN_OTHERNAME:
- BIO_printf(out, "othername:<unsupported>");
- break;
-
- case GEN_X400:
- BIO_printf(out, "X400Name:<unsupported>");
- break;
-
- case GEN_EDIPARTY:
- /* Maybe fix this: it is supported now */
- BIO_printf(out, "EdiPartyName:<unsupported>");
- break;
-
- case GEN_EMAIL:
- BIO_printf(out, "email:");
- ASN1_STRING_print(out, gen->d.ia5);
- break;
-
- case GEN_DNS:
- BIO_printf(out, "DNS:");
- ASN1_STRING_print(out, gen->d.ia5);
- break;
-
- case GEN_URI:
- BIO_printf(out, "URI:");
- ASN1_STRING_print(out, gen->d.ia5);
- break;
-
- case GEN_DIRNAME:
- BIO_printf(out, "DirName:");
- X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
- break;
-
- case GEN_IPADD:
- p = gen->d.ip->data;
- if (gen->d.ip->length == 4)
- BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
- else if (gen->d.ip->length == 16) {
- BIO_printf(out, "IP Address");
- for (i = 0; i < 8; i++) {
- BIO_printf(out, ":%X", p[0] << 8 | p[1]);
- p += 2;
- }
- BIO_puts(out, "\n");
- } else {
- BIO_printf(out, "IP Address:<invalid>");
- break;
- }
- break;
-
- case GEN_RID:
- BIO_printf(out, "Registered ID:");
- i2a_ASN1_OBJECT(out, gen->d.rid);
- break;
- }
- return 1;
-}
-
-static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval)
-{
- const int num = sk_CONF_VALUE_num(nval);
- GENERAL_NAMES *gens = sk_GENERAL_NAME_new_reserve(NULL, num);
- int i;
-
- if (gens == NULL) {
- X509V3err(X509V3_F_V2I_ISSUER_ALT, ERR_R_MALLOC_FAILURE);
- sk_GENERAL_NAME_free(gens);
- return NULL;
- }
- for (i = 0; i < num; i++) {
- CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
-
- if (!name_cmp(cnf->name, "issuer")
- && cnf->value && strcmp(cnf->value, "copy") == 0) {
- if (!copy_issuer(ctx, gens))
- goto err;
- } else {
- GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf);
-
- if (gen == NULL)
- goto err;
- sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
- }
- }
- return gens;
- err:
- sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
- return NULL;
-}
-
-/* Append subject altname of issuer to issuer alt name of subject */
-
-static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
-{
- GENERAL_NAMES *ialt;
- GENERAL_NAME *gen;
- X509_EXTENSION *ext;
- int i, num;
-
- if (ctx && (ctx->flags == CTX_TEST))
- return 1;
- if (!ctx || !ctx->issuer_cert) {
- X509V3err(X509V3_F_COPY_ISSUER, X509V3_R_NO_ISSUER_DETAILS);
- goto err;
- }
- i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
- if (i < 0)
- return 1;
- if ((ext = X509_get_ext(ctx->issuer_cert, i)) == NULL
- || (ialt = X509V3_EXT_d2i(ext)) == NULL) {
- X509V3err(X509V3_F_COPY_ISSUER, X509V3_R_ISSUER_DECODE_ERROR);
- goto err;
- }
-
- num = sk_GENERAL_NAME_num(ialt);
- if (!sk_GENERAL_NAME_reserve(gens, num)) {
- X509V3err(X509V3_F_COPY_ISSUER, ERR_R_MALLOC_FAILURE);
- sk_GENERAL_NAME_free(ialt);
- goto err;
- }
-
- for (i = 0; i < num; i++) {
- gen = sk_GENERAL_NAME_value(ialt, i);
- sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
- }
- sk_GENERAL_NAME_free(ialt);
-
- return 1;
-
- err:
- return 0;
-
-}
-
-static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval)
-{
- GENERAL_NAMES *gens;
- CONF_VALUE *cnf;
- const int num = sk_CONF_VALUE_num(nval);
- int i;
-
- gens = sk_GENERAL_NAME_new_reserve(NULL, num);
- if (gens == NULL) {
- X509V3err(X509V3_F_V2I_SUBJECT_ALT, ERR_R_MALLOC_FAILURE);
- sk_GENERAL_NAME_free(gens);
- return NULL;
- }
-
- for (i = 0; i < num; i++) {
- cnf = sk_CONF_VALUE_value(nval, i);
- if (!name_cmp(cnf->name, "email")
- && cnf->value && strcmp(cnf->value, "copy") == 0) {
- if (!copy_email(ctx, gens, 0))
- goto err;
- } else if (!name_cmp(cnf->name, "email")
- && cnf->value && strcmp(cnf->value, "move") == 0) {
- if (!copy_email(ctx, gens, 1))
- goto err;
- } else {
- GENERAL_NAME *gen;
- if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
- goto err;
- sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
- }
- }
- return gens;
- err:
- sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
- return NULL;
-}
-
-/*
- * Copy any email addresses in a certificate or request to GENERAL_NAMES
- */
-
-static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
-{
- X509_NAME *nm;
- ASN1_IA5STRING *email = NULL;
- X509_NAME_ENTRY *ne;
- GENERAL_NAME *gen = NULL;
- int i = -1;
-
- if (ctx != NULL && ctx->flags == CTX_TEST)
- return 1;
- if (ctx == NULL
- || (ctx->subject_cert == NULL && ctx->subject_req == NULL)) {
- X509V3err(X509V3_F_COPY_EMAIL, X509V3_R_NO_SUBJECT_DETAILS);
- goto err;
- }
- /* Find the subject name */
- if (ctx->subject_cert)
- nm = X509_get_subject_name(ctx->subject_cert);
- else
- nm = X509_REQ_get_subject_name(ctx->subject_req);
-
- /* Now add any email address(es) to STACK */
- while ((i = X509_NAME_get_index_by_NID(nm,
- NID_pkcs9_emailAddress, i)) >= 0) {
- ne = X509_NAME_get_entry(nm, i);
- email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne));
- if (move_p) {
- X509_NAME_delete_entry(nm, i);
- X509_NAME_ENTRY_free(ne);
- i--;
- }
- if (email == NULL || (gen = GENERAL_NAME_new()) == NULL) {
- X509V3err(X509V3_F_COPY_EMAIL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- gen->d.ia5 = email;
- email = NULL;
- gen->type = GEN_EMAIL;
- if (!sk_GENERAL_NAME_push(gens, gen)) {
- X509V3err(X509V3_F_COPY_EMAIL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- gen = NULL;
- }
-
- return 1;
-
- err:
- GENERAL_NAME_free(gen);
- ASN1_IA5STRING_free(email);
- return 0;
-
-}
-
-GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
-{
- GENERAL_NAME *gen;
- GENERAL_NAMES *gens;
- CONF_VALUE *cnf;
- const int num = sk_CONF_VALUE_num(nval);
- int i;
-
- gens = sk_GENERAL_NAME_new_reserve(NULL, num);
- if (gens == NULL) {
- X509V3err(X509V3_F_V2I_GENERAL_NAMES, ERR_R_MALLOC_FAILURE);
- sk_GENERAL_NAME_free(gens);
- return NULL;
- }
-
- for (i = 0; i < num; i++) {
- cnf = sk_CONF_VALUE_value(nval, i);
- if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
- goto err;
- sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
- }
- return gens;
- err:
- sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
- return NULL;
-}
-
-GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, CONF_VALUE *cnf)
-{
- return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
-}
-
-GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
- const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, int gen_type, const char *value,
- int is_nc)
-{
- char is_string = 0;
- GENERAL_NAME *gen = NULL;
-
- if (!value) {
- X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_MISSING_VALUE);
- return NULL;
- }
-
- if (out)
- gen = out;
- else {
- gen = GENERAL_NAME_new();
- if (gen == NULL) {
- X509V3err(X509V3_F_A2I_GENERAL_NAME, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- }
-
- switch (gen_type) {
- case GEN_URI:
- case GEN_EMAIL:
- case GEN_DNS:
- is_string = 1;
- break;
-
- case GEN_RID:
- {
- ASN1_OBJECT *obj;
- if ((obj = OBJ_txt2obj(value, 0)) == NULL) {
- X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_BAD_OBJECT);
- ERR_add_error_data(2, "value=", value);
- goto err;
- }
- gen->d.rid = obj;
- }
- break;
-
- case GEN_IPADD:
- if (is_nc)
- gen->d.ip = a2i_IPADDRESS_NC(value);
- else
- gen->d.ip = a2i_IPADDRESS(value);
- if (gen->d.ip == NULL) {
- X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_BAD_IP_ADDRESS);
- ERR_add_error_data(2, "value=", value);
- goto err;
- }
- break;
-
- case GEN_DIRNAME:
- if (!do_dirname(gen, value, ctx)) {
- X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_DIRNAME_ERROR);
- goto err;
- }
- break;
-
- case GEN_OTHERNAME:
- if (!do_othername(gen, value, ctx)) {
- X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_OTHERNAME_ERROR);
- goto err;
- }
- break;
- default:
- X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_UNSUPPORTED_TYPE);
- goto err;
- }
-
- if (is_string) {
- if ((gen->d.ia5 = ASN1_IA5STRING_new()) == NULL ||
- !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value,
- strlen(value))) {
- X509V3err(X509V3_F_A2I_GENERAL_NAME, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
-
- gen->type = gen_type;
-
- return gen;
-
- err:
- if (!out)
- GENERAL_NAME_free(gen);
- return NULL;
-}
-
-GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
- const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc)
-{
- int type;
-
- char *name, *value;
-
- name = cnf->name;
- value = cnf->value;
-
- if (!value) {
- X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_MISSING_VALUE);
- return NULL;
- }
-
- if (!name_cmp(name, "email"))
- type = GEN_EMAIL;
- else if (!name_cmp(name, "URI"))
- type = GEN_URI;
- else if (!name_cmp(name, "DNS"))
- type = GEN_DNS;
- else if (!name_cmp(name, "RID"))
- type = GEN_RID;
- else if (!name_cmp(name, "IP"))
- type = GEN_IPADD;
- else if (!name_cmp(name, "dirName"))
- type = GEN_DIRNAME;
- else if (!name_cmp(name, "otherName"))
- type = GEN_OTHERNAME;
- else {
- X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_UNSUPPORTED_OPTION);
- ERR_add_error_data(2, "name=", name);
- return NULL;
- }
-
- return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
-
-}
-
-static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
-{
- char *objtmp = NULL, *p;
- int objlen;
-
- if ((p = strchr(value, ';')) == NULL)
- return 0;
- if ((gen->d.otherName = OTHERNAME_new()) == NULL)
- return 0;
- /*
- * Free this up because we will overwrite it. no need to free type_id
- * because it is static
- */
- ASN1_TYPE_free(gen->d.otherName->value);
- if ((gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)) == NULL)
- return 0;
- objlen = p - value;
- objtmp = OPENSSL_strndup(value, objlen);
- if (objtmp == NULL)
- return 0;
- gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
- OPENSSL_free(objtmp);
- if (!gen->d.otherName->type_id)
- return 0;
- return 1;
-}
-
-static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
-{
- int ret = 0;
- STACK_OF(CONF_VALUE) *sk = NULL;
- X509_NAME *nm;
-
- if ((nm = X509_NAME_new()) == NULL)
- goto err;
- sk = X509V3_get_section(ctx, value);
- if (!sk) {
- X509V3err(X509V3_F_DO_DIRNAME, X509V3_R_SECTION_NOT_FOUND);
- ERR_add_error_data(2, "section=", value);
- goto err;
- }
- /* FIXME: should allow other character types... */
- ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
- if (!ret)
- goto err;
- gen->d.dirn = nm;
-
-err:
- if (ret == 0)
- X509_NAME_free(nm);
- X509V3_section_free(ctx, sk);
- return ret;
-}
diff --git a/crypto/x509v3/v3_asid.c b/crypto/x509v3/v3_asid.c
deleted file mode 100644
index 8e9e919804d0..000000000000
--- a/crypto/x509v3/v3_asid.c
+++ /dev/null
@@ -1,907 +0,0 @@
-/*
- * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * Implementation of RFC 3779 section 3.2.
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-#include "internal/cryptlib.h"
-#include <openssl/conf.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-#include <openssl/x509v3.h>
-#include <openssl/x509.h>
-#include "crypto/x509.h"
-#include <openssl/bn.h>
-#include "ext_dat.h"
-
-#ifndef OPENSSL_NO_RFC3779
-
-/*
- * OpenSSL ASN.1 template translation of RFC 3779 3.2.3.
- */
-
-ASN1_SEQUENCE(ASRange) = {
- ASN1_SIMPLE(ASRange, min, ASN1_INTEGER),
- ASN1_SIMPLE(ASRange, max, ASN1_INTEGER)
-} ASN1_SEQUENCE_END(ASRange)
-
-ASN1_CHOICE(ASIdOrRange) = {
- ASN1_SIMPLE(ASIdOrRange, u.id, ASN1_INTEGER),
- ASN1_SIMPLE(ASIdOrRange, u.range, ASRange)
-} ASN1_CHOICE_END(ASIdOrRange)
-
-ASN1_CHOICE(ASIdentifierChoice) = {
- ASN1_SIMPLE(ASIdentifierChoice, u.inherit, ASN1_NULL),
- ASN1_SEQUENCE_OF(ASIdentifierChoice, u.asIdsOrRanges, ASIdOrRange)
-} ASN1_CHOICE_END(ASIdentifierChoice)
-
-ASN1_SEQUENCE(ASIdentifiers) = {
- ASN1_EXP_OPT(ASIdentifiers, asnum, ASIdentifierChoice, 0),
- ASN1_EXP_OPT(ASIdentifiers, rdi, ASIdentifierChoice, 1)
-} ASN1_SEQUENCE_END(ASIdentifiers)
-
-IMPLEMENT_ASN1_FUNCTIONS(ASRange)
-IMPLEMENT_ASN1_FUNCTIONS(ASIdOrRange)
-IMPLEMENT_ASN1_FUNCTIONS(ASIdentifierChoice)
-IMPLEMENT_ASN1_FUNCTIONS(ASIdentifiers)
-
-/*
- * i2r method for an ASIdentifierChoice.
- */
-static int i2r_ASIdentifierChoice(BIO *out,
- ASIdentifierChoice *choice,
- int indent, const char *msg)
-{
- int i;
- char *s;
- if (choice == NULL)
- return 1;
- BIO_printf(out, "%*s%s:\n", indent, "", msg);
- switch (choice->type) {
- case ASIdentifierChoice_inherit:
- BIO_printf(out, "%*sinherit\n", indent + 2, "");
- break;
- case ASIdentifierChoice_asIdsOrRanges:
- for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges); i++) {
- ASIdOrRange *aor =
- sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
- switch (aor->type) {
- case ASIdOrRange_id:
- if ((s = i2s_ASN1_INTEGER(NULL, aor->u.id)) == NULL)
- return 0;
- BIO_printf(out, "%*s%s\n", indent + 2, "", s);
- OPENSSL_free(s);
- break;
- case ASIdOrRange_range:
- if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->min)) == NULL)
- return 0;
- BIO_printf(out, "%*s%s-", indent + 2, "", s);
- OPENSSL_free(s);
- if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->max)) == NULL)
- return 0;
- BIO_printf(out, "%s\n", s);
- OPENSSL_free(s);
- break;
- default:
- return 0;
- }
- }
- break;
- default:
- return 0;
- }
- return 1;
-}
-
-/*
- * i2r method for an ASIdentifier extension.
- */
-static int i2r_ASIdentifiers(const X509V3_EXT_METHOD *method,
- void *ext, BIO *out, int indent)
-{
- ASIdentifiers *asid = ext;
- return (i2r_ASIdentifierChoice(out, asid->asnum, indent,
- "Autonomous System Numbers") &&
- i2r_ASIdentifierChoice(out, asid->rdi, indent,
- "Routing Domain Identifiers"));
-}
-
-/*
- * Sort comparison function for a sequence of ASIdOrRange elements.
- */
-static int ASIdOrRange_cmp(const ASIdOrRange *const *a_,
- const ASIdOrRange *const *b_)
-{
- const ASIdOrRange *a = *a_, *b = *b_;
-
- assert((a->type == ASIdOrRange_id && a->u.id != NULL) ||
- (a->type == ASIdOrRange_range && a->u.range != NULL &&
- a->u.range->min != NULL && a->u.range->max != NULL));
-
- assert((b->type == ASIdOrRange_id && b->u.id != NULL) ||
- (b->type == ASIdOrRange_range && b->u.range != NULL &&
- b->u.range->min != NULL && b->u.range->max != NULL));
-
- if (a->type == ASIdOrRange_id && b->type == ASIdOrRange_id)
- return ASN1_INTEGER_cmp(a->u.id, b->u.id);
-
- if (a->type == ASIdOrRange_range && b->type == ASIdOrRange_range) {
- int r = ASN1_INTEGER_cmp(a->u.range->min, b->u.range->min);
- return r != 0 ? r : ASN1_INTEGER_cmp(a->u.range->max,
- b->u.range->max);
- }
-
- if (a->type == ASIdOrRange_id)
- return ASN1_INTEGER_cmp(a->u.id, b->u.range->min);
- else
- return ASN1_INTEGER_cmp(a->u.range->min, b->u.id);
-}
-
-/*
- * Add an inherit element.
- */
-int X509v3_asid_add_inherit(ASIdentifiers *asid, int which)
-{
- ASIdentifierChoice **choice;
- if (asid == NULL)
- return 0;
- switch (which) {
- case V3_ASID_ASNUM:
- choice = &asid->asnum;
- break;
- case V3_ASID_RDI:
- choice = &asid->rdi;
- break;
- default:
- return 0;
- }
- if (*choice == NULL) {
- if ((*choice = ASIdentifierChoice_new()) == NULL)
- return 0;
- if (((*choice)->u.inherit = ASN1_NULL_new()) == NULL)
- return 0;
- (*choice)->type = ASIdentifierChoice_inherit;
- }
- return (*choice)->type == ASIdentifierChoice_inherit;
-}
-
-/*
- * Add an ID or range to an ASIdentifierChoice.
- */
-int X509v3_asid_add_id_or_range(ASIdentifiers *asid,
- int which, ASN1_INTEGER *min, ASN1_INTEGER *max)
-{
- ASIdentifierChoice **choice;
- ASIdOrRange *aor;
- if (asid == NULL)
- return 0;
- switch (which) {
- case V3_ASID_ASNUM:
- choice = &asid->asnum;
- break;
- case V3_ASID_RDI:
- choice = &asid->rdi;
- break;
- default:
- return 0;
- }
- if (*choice != NULL && (*choice)->type == ASIdentifierChoice_inherit)
- return 0;
- if (*choice == NULL) {
- if ((*choice = ASIdentifierChoice_new()) == NULL)
- return 0;
- (*choice)->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp);
- if ((*choice)->u.asIdsOrRanges == NULL)
- return 0;
- (*choice)->type = ASIdentifierChoice_asIdsOrRanges;
- }
- if ((aor = ASIdOrRange_new()) == NULL)
- return 0;
- if (max == NULL) {
- aor->type = ASIdOrRange_id;
- aor->u.id = min;
- } else {
- aor->type = ASIdOrRange_range;
- if ((aor->u.range = ASRange_new()) == NULL)
- goto err;
- ASN1_INTEGER_free(aor->u.range->min);
- aor->u.range->min = min;
- ASN1_INTEGER_free(aor->u.range->max);
- aor->u.range->max = max;
- }
- if (!(sk_ASIdOrRange_push((*choice)->u.asIdsOrRanges, aor)))
- goto err;
- return 1;
-
- err:
- ASIdOrRange_free(aor);
- return 0;
-}
-
-/*
- * Extract min and max values from an ASIdOrRange.
- */
-static int extract_min_max(ASIdOrRange *aor,
- ASN1_INTEGER **min, ASN1_INTEGER **max)
-{
- if (!ossl_assert(aor != NULL))
- return 0;
- switch (aor->type) {
- case ASIdOrRange_id:
- *min = aor->u.id;
- *max = aor->u.id;
- return 1;
- case ASIdOrRange_range:
- *min = aor->u.range->min;
- *max = aor->u.range->max;
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Check whether an ASIdentifierChoice is in canonical form.
- */
-static int ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice)
-{
- ASN1_INTEGER *a_max_plus_one = NULL;
- ASN1_INTEGER *orig;
- BIGNUM *bn = NULL;
- int i, ret = 0;
-
- /*
- * Empty element or inheritance is canonical.
- */
- if (choice == NULL || choice->type == ASIdentifierChoice_inherit)
- return 1;
-
- /*
- * If not a list, or if empty list, it's broken.
- */
- if (choice->type != ASIdentifierChoice_asIdsOrRanges ||
- sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0)
- return 0;
-
- /*
- * It's a list, check it.
- */
- for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) {
- ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
- ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1);
- ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max =
- NULL;
-
- if (!extract_min_max(a, &a_min, &a_max)
- || !extract_min_max(b, &b_min, &b_max))
- goto done;
-
- /*
- * Punt misordered list, overlapping start, or inverted range.
- */
- if (ASN1_INTEGER_cmp(a_min, b_min) >= 0 ||
- ASN1_INTEGER_cmp(a_min, a_max) > 0 ||
- ASN1_INTEGER_cmp(b_min, b_max) > 0)
- goto done;
-
- /*
- * Calculate a_max + 1 to check for adjacency.
- */
- if ((bn == NULL && (bn = BN_new()) == NULL) ||
- ASN1_INTEGER_to_BN(a_max, bn) == NULL ||
- !BN_add_word(bn, 1)) {
- X509V3err(X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL,
- ERR_R_MALLOC_FAILURE);
- goto done;
- }
-
- if ((a_max_plus_one =
- BN_to_ASN1_INTEGER(bn, orig = a_max_plus_one)) == NULL) {
- a_max_plus_one = orig;
- X509V3err(X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL,
- ERR_R_MALLOC_FAILURE);
- goto done;
- }
-
- /*
- * Punt if adjacent or overlapping.
- */
- if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) >= 0)
- goto done;
- }
-
- /*
- * Check for inverted range.
- */
- i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1;
- {
- ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
- ASN1_INTEGER *a_min, *a_max;
- if (a != NULL && a->type == ASIdOrRange_range) {
- if (!extract_min_max(a, &a_min, &a_max)
- || ASN1_INTEGER_cmp(a_min, a_max) > 0)
- goto done;
- }
- }
-
- ret = 1;
-
- done:
- ASN1_INTEGER_free(a_max_plus_one);
- BN_free(bn);
- return ret;
-}
-
-/*
- * Check whether an ASIdentifier extension is in canonical form.
- */
-int X509v3_asid_is_canonical(ASIdentifiers *asid)
-{
- return (asid == NULL ||
- (ASIdentifierChoice_is_canonical(asid->asnum) &&
- ASIdentifierChoice_is_canonical(asid->rdi)));
-}
-
-/*
- * Whack an ASIdentifierChoice into canonical form.
- */
-static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice)
-{
- ASN1_INTEGER *a_max_plus_one = NULL;
- ASN1_INTEGER *orig;
- BIGNUM *bn = NULL;
- int i, ret = 0;
-
- /*
- * Nothing to do for empty element or inheritance.
- */
- if (choice == NULL || choice->type == ASIdentifierChoice_inherit)
- return 1;
-
- /*
- * If not a list, or if empty list, it's broken.
- */
- if (choice->type != ASIdentifierChoice_asIdsOrRanges ||
- sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) {
- X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
- X509V3_R_EXTENSION_VALUE_ERROR);
- return 0;
- }
-
- /*
- * We have a non-empty list. Sort it.
- */
- sk_ASIdOrRange_sort(choice->u.asIdsOrRanges);
-
- /*
- * Now check for errors and suboptimal encoding, rejecting the
- * former and fixing the latter.
- */
- for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) {
- ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
- ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1);
- ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max =
- NULL;
-
- if (!extract_min_max(a, &a_min, &a_max)
- || !extract_min_max(b, &b_min, &b_max))
- goto done;
-
- /*
- * Make sure we're properly sorted (paranoia).
- */
- if (!ossl_assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0))
- goto done;
-
- /*
- * Punt inverted ranges.
- */
- if (ASN1_INTEGER_cmp(a_min, a_max) > 0 ||
- ASN1_INTEGER_cmp(b_min, b_max) > 0)
- goto done;
-
- /*
- * Check for overlaps.
- */
- if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) {
- X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
- X509V3_R_EXTENSION_VALUE_ERROR);
- goto done;
- }
-
- /*
- * Calculate a_max + 1 to check for adjacency.
- */
- if ((bn == NULL && (bn = BN_new()) == NULL) ||
- ASN1_INTEGER_to_BN(a_max, bn) == NULL ||
- !BN_add_word(bn, 1)) {
- X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
- ERR_R_MALLOC_FAILURE);
- goto done;
- }
-
- if ((a_max_plus_one =
- BN_to_ASN1_INTEGER(bn, orig = a_max_plus_one)) == NULL) {
- a_max_plus_one = orig;
- X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
- ERR_R_MALLOC_FAILURE);
- goto done;
- }
-
- /*
- * If a and b are adjacent, merge them.
- */
- if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) {
- ASRange *r;
- switch (a->type) {
- case ASIdOrRange_id:
- if ((r = OPENSSL_malloc(sizeof(*r))) == NULL) {
- X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
- ERR_R_MALLOC_FAILURE);
- goto done;
- }
- r->min = a_min;
- r->max = b_max;
- a->type = ASIdOrRange_range;
- a->u.range = r;
- break;
- case ASIdOrRange_range:
- ASN1_INTEGER_free(a->u.range->max);
- a->u.range->max = b_max;
- break;
- }
- switch (b->type) {
- case ASIdOrRange_id:
- b->u.id = NULL;
- break;
- case ASIdOrRange_range:
- b->u.range->max = NULL;
- break;
- }
- ASIdOrRange_free(b);
- (void)sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1);
- i--;
- continue;
- }
- }
-
- /*
- * Check for final inverted range.
- */
- i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1;
- {
- ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
- ASN1_INTEGER *a_min, *a_max;
- if (a != NULL && a->type == ASIdOrRange_range) {
- if (!extract_min_max(a, &a_min, &a_max)
- || ASN1_INTEGER_cmp(a_min, a_max) > 0)
- goto done;
- }
- }
-
- /* Paranoia */
- if (!ossl_assert(ASIdentifierChoice_is_canonical(choice)))
- goto done;
-
- ret = 1;
-
- done:
- ASN1_INTEGER_free(a_max_plus_one);
- BN_free(bn);
- return ret;
-}
-
-/*
- * Whack an ASIdentifier extension into canonical form.
- */
-int X509v3_asid_canonize(ASIdentifiers *asid)
-{
- return (asid == NULL ||
- (ASIdentifierChoice_canonize(asid->asnum) &&
- ASIdentifierChoice_canonize(asid->rdi)));
-}
-
-/*
- * v2i method for an ASIdentifier extension.
- */
-static void *v2i_ASIdentifiers(const struct v3_ext_method *method,
- struct v3_ext_ctx *ctx,
- STACK_OF(CONF_VALUE) *values)
-{
- ASN1_INTEGER *min = NULL, *max = NULL;
- ASIdentifiers *asid = NULL;
- int i;
-
- if ((asid = ASIdentifiers_new()) == NULL) {
- X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
- CONF_VALUE *val = sk_CONF_VALUE_value(values, i);
- int i1 = 0, i2 = 0, i3 = 0, is_range = 0, which = 0;
-
- /*
- * Figure out whether this is an AS or an RDI.
- */
- if (!name_cmp(val->name, "AS")) {
- which = V3_ASID_ASNUM;
- } else if (!name_cmp(val->name, "RDI")) {
- which = V3_ASID_RDI;
- } else {
- X509V3err(X509V3_F_V2I_ASIDENTIFIERS,
- X509V3_R_EXTENSION_NAME_ERROR);
- X509V3_conf_err(val);
- goto err;
- }
-
- /*
- * Handle inheritance.
- */
- if (strcmp(val->value, "inherit") == 0) {
- if (X509v3_asid_add_inherit(asid, which))
- continue;
- X509V3err(X509V3_F_V2I_ASIDENTIFIERS,
- X509V3_R_INVALID_INHERITANCE);
- X509V3_conf_err(val);
- goto err;
- }
-
- /*
- * Number, range, or mistake, pick it apart and figure out which.
- */
- i1 = strspn(val->value, "0123456789");
- if (val->value[i1] == '\0') {
- is_range = 0;
- } else {
- is_range = 1;
- i2 = i1 + strspn(val->value + i1, " \t");
- if (val->value[i2] != '-') {
- X509V3err(X509V3_F_V2I_ASIDENTIFIERS,
- X509V3_R_INVALID_ASNUMBER);
- X509V3_conf_err(val);
- goto err;
- }
- i2++;
- i2 = i2 + strspn(val->value + i2, " \t");
- i3 = i2 + strspn(val->value + i2, "0123456789");
- if (val->value[i3] != '\0') {
- X509V3err(X509V3_F_V2I_ASIDENTIFIERS,
- X509V3_R_INVALID_ASRANGE);
- X509V3_conf_err(val);
- goto err;
- }
- }
-
- /*
- * Syntax is ok, read and add it.
- */
- if (!is_range) {
- if (!X509V3_get_value_int(val, &min)) {
- X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- } else {
- char *s = OPENSSL_strdup(val->value);
- if (s == NULL) {
- X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- s[i1] = '\0';
- min = s2i_ASN1_INTEGER(NULL, s);
- max = s2i_ASN1_INTEGER(NULL, s + i2);
- OPENSSL_free(s);
- if (min == NULL || max == NULL) {
- X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if (ASN1_INTEGER_cmp(min, max) > 0) {
- X509V3err(X509V3_F_V2I_ASIDENTIFIERS,
- X509V3_R_EXTENSION_VALUE_ERROR);
- goto err;
- }
- }
- if (!X509v3_asid_add_id_or_range(asid, which, min, max)) {
- X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- min = max = NULL;
- }
-
- /*
- * Canonize the result, then we're done.
- */
- if (!X509v3_asid_canonize(asid))
- goto err;
- return asid;
-
- err:
- ASIdentifiers_free(asid);
- ASN1_INTEGER_free(min);
- ASN1_INTEGER_free(max);
- return NULL;
-}
-
-/*
- * OpenSSL dispatch.
- */
-const X509V3_EXT_METHOD v3_asid = {
- NID_sbgp_autonomousSysNum, /* nid */
- 0, /* flags */
- ASN1_ITEM_ref(ASIdentifiers), /* template */
- 0, 0, 0, 0, /* old functions, ignored */
- 0, /* i2s */
- 0, /* s2i */
- 0, /* i2v */
- v2i_ASIdentifiers, /* v2i */
- i2r_ASIdentifiers, /* i2r */
- 0, /* r2i */
- NULL /* extension-specific data */
-};
-
-/*
- * Figure out whether extension uses inheritance.
- */
-int X509v3_asid_inherits(ASIdentifiers *asid)
-{
- return (asid != NULL &&
- ((asid->asnum != NULL &&
- asid->asnum->type == ASIdentifierChoice_inherit) ||
- (asid->rdi != NULL &&
- asid->rdi->type == ASIdentifierChoice_inherit)));
-}
-
-/*
- * Figure out whether parent contains child.
- */
-static int asid_contains(ASIdOrRanges *parent, ASIdOrRanges *child)
-{
- ASN1_INTEGER *p_min = NULL, *p_max = NULL, *c_min = NULL, *c_max = NULL;
- int p, c;
-
- if (child == NULL || parent == child)
- return 1;
- if (parent == NULL)
- return 0;
-
- p = 0;
- for (c = 0; c < sk_ASIdOrRange_num(child); c++) {
- if (!extract_min_max(sk_ASIdOrRange_value(child, c), &c_min, &c_max))
- return 0;
- for (;; p++) {
- if (p >= sk_ASIdOrRange_num(parent))
- return 0;
- if (!extract_min_max(sk_ASIdOrRange_value(parent, p), &p_min,
- &p_max))
- return 0;
- if (ASN1_INTEGER_cmp(p_max, c_max) < 0)
- continue;
- if (ASN1_INTEGER_cmp(p_min, c_min) > 0)
- return 0;
- break;
- }
- }
-
- return 1;
-}
-
-/*
- * Test whether a is a subset of b.
- */
-int X509v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b)
-{
- int subset;
-
- if (a == NULL || a == b)
- return 1;
-
- if (b == NULL)
- return 0;
-
- if (X509v3_asid_inherits(a) || X509v3_asid_inherits(b))
- return 0;
-
- subset = a->asnum == NULL
- || (b->asnum != NULL
- && asid_contains(b->asnum->u.asIdsOrRanges,
- a->asnum->u.asIdsOrRanges));
- if (!subset)
- return 0;
-
- return a->rdi == NULL
- || (b->rdi != NULL
- && asid_contains(b->rdi->u.asIdsOrRanges,
- a->rdi->u.asIdsOrRanges));
-}
-
-/*
- * Validation error handling via callback.
- */
-#define validation_err(_err_) \
- do { \
- if (ctx != NULL) { \
- ctx->error = _err_; \
- ctx->error_depth = i; \
- ctx->current_cert = x; \
- ret = ctx->verify_cb(0, ctx); \
- } else { \
- ret = 0; \
- } \
- if (!ret) \
- goto done; \
- } while (0)
-
-/*
- * Core code for RFC 3779 3.3 path validation.
- */
-static int asid_validate_path_internal(X509_STORE_CTX *ctx,
- STACK_OF(X509) *chain,
- ASIdentifiers *ext)
-{
- ASIdOrRanges *child_as = NULL, *child_rdi = NULL;
- int i, ret = 1, inherit_as = 0, inherit_rdi = 0;
- X509 *x;
-
- if (!ossl_assert(chain != NULL && sk_X509_num(chain) > 0)
- || !ossl_assert(ctx != NULL || ext != NULL)
- || !ossl_assert(ctx == NULL || ctx->verify_cb != NULL)) {
- if (ctx != NULL)
- ctx->error = X509_V_ERR_UNSPECIFIED;
- return 0;
- }
-
-
- /*
- * Figure out where to start. If we don't have an extension to
- * check, we're done. Otherwise, check canonical form and
- * set up for walking up the chain.
- */
- if (ext != NULL) {
- i = -1;
- x = NULL;
- } else {
- i = 0;
- x = sk_X509_value(chain, i);
- if ((ext = x->rfc3779_asid) == NULL)
- goto done;
- }
- if (!X509v3_asid_is_canonical(ext))
- validation_err(X509_V_ERR_INVALID_EXTENSION);
- if (ext->asnum != NULL) {
- switch (ext->asnum->type) {
- case ASIdentifierChoice_inherit:
- inherit_as = 1;
- break;
- case ASIdentifierChoice_asIdsOrRanges:
- child_as = ext->asnum->u.asIdsOrRanges;
- break;
- }
- }
- if (ext->rdi != NULL) {
- switch (ext->rdi->type) {
- case ASIdentifierChoice_inherit:
- inherit_rdi = 1;
- break;
- case ASIdentifierChoice_asIdsOrRanges:
- child_rdi = ext->rdi->u.asIdsOrRanges;
- break;
- }
- }
-
- /*
- * Now walk up the chain. Extensions must be in canonical form, no
- * cert may list resources that its parent doesn't list.
- */
- for (i++; i < sk_X509_num(chain); i++) {
- x = sk_X509_value(chain, i);
- if (!ossl_assert(x != NULL)) {
- if (ctx != NULL)
- ctx->error = X509_V_ERR_UNSPECIFIED;
- return 0;
- }
- if (x->rfc3779_asid == NULL) {
- if (child_as != NULL || child_rdi != NULL)
- validation_err(X509_V_ERR_UNNESTED_RESOURCE);
- continue;
- }
- if (!X509v3_asid_is_canonical(x->rfc3779_asid))
- validation_err(X509_V_ERR_INVALID_EXTENSION);
- if (x->rfc3779_asid->asnum == NULL && child_as != NULL) {
- validation_err(X509_V_ERR_UNNESTED_RESOURCE);
- child_as = NULL;
- inherit_as = 0;
- }
- if (x->rfc3779_asid->asnum != NULL &&
- x->rfc3779_asid->asnum->type ==
- ASIdentifierChoice_asIdsOrRanges) {
- if (inherit_as
- || asid_contains(x->rfc3779_asid->asnum->u.asIdsOrRanges,
- child_as)) {
- child_as = x->rfc3779_asid->asnum->u.asIdsOrRanges;
- inherit_as = 0;
- } else {
- validation_err(X509_V_ERR_UNNESTED_RESOURCE);
- }
- }
- if (x->rfc3779_asid->rdi == NULL && child_rdi != NULL) {
- validation_err(X509_V_ERR_UNNESTED_RESOURCE);
- child_rdi = NULL;
- inherit_rdi = 0;
- }
- if (x->rfc3779_asid->rdi != NULL &&
- x->rfc3779_asid->rdi->type == ASIdentifierChoice_asIdsOrRanges) {
- if (inherit_rdi ||
- asid_contains(x->rfc3779_asid->rdi->u.asIdsOrRanges,
- child_rdi)) {
- child_rdi = x->rfc3779_asid->rdi->u.asIdsOrRanges;
- inherit_rdi = 0;
- } else {
- validation_err(X509_V_ERR_UNNESTED_RESOURCE);
- }
- }
- }
-
- /*
- * Trust anchor can't inherit.
- */
- if (!ossl_assert(x != NULL)) {
- if (ctx != NULL)
- ctx->error = X509_V_ERR_UNSPECIFIED;
- return 0;
- }
- if (x->rfc3779_asid != NULL) {
- if (x->rfc3779_asid->asnum != NULL &&
- x->rfc3779_asid->asnum->type == ASIdentifierChoice_inherit)
- validation_err(X509_V_ERR_UNNESTED_RESOURCE);
- if (x->rfc3779_asid->rdi != NULL &&
- x->rfc3779_asid->rdi->type == ASIdentifierChoice_inherit)
- validation_err(X509_V_ERR_UNNESTED_RESOURCE);
- }
-
- done:
- return ret;
-}
-
-#undef validation_err
-
-/*
- * RFC 3779 3.3 path validation -- called from X509_verify_cert().
- */
-int X509v3_asid_validate_path(X509_STORE_CTX *ctx)
-{
- if (ctx->chain == NULL
- || sk_X509_num(ctx->chain) == 0
- || ctx->verify_cb == NULL) {
- ctx->error = X509_V_ERR_UNSPECIFIED;
- return 0;
- }
- return asid_validate_path_internal(ctx, ctx->chain, NULL);
-}
-
-/*
- * RFC 3779 3.3 path validation of an extension.
- * Test whether chain covers extension.
- */
-int X509v3_asid_validate_resource_set(STACK_OF(X509) *chain,
- ASIdentifiers *ext, int allow_inheritance)
-{
- if (ext == NULL)
- return 1;
- if (chain == NULL || sk_X509_num(chain) == 0)
- return 0;
- if (!allow_inheritance && X509v3_asid_inherits(ext))
- return 0;
- return asid_validate_path_internal(NULL, chain, ext);
-}
-
-#endif /* OPENSSL_NO_RFC3779 */
diff --git a/crypto/x509v3/v3_bcons.c b/crypto/x509v3/v3_bcons.c
deleted file mode 100644
index 3bbf15550d32..000000000000
--- a/crypto/x509v3/v3_bcons.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-#include <openssl/conf.h>
-#include <openssl/x509v3.h>
-#include "ext_dat.h"
-
-static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
- BASIC_CONSTRAINTS *bcons,
- STACK_OF(CONF_VALUE)
- *extlist);
-static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *values);
-
-const X509V3_EXT_METHOD v3_bcons = {
- NID_basic_constraints, 0,
- ASN1_ITEM_ref(BASIC_CONSTRAINTS),
- 0, 0, 0, 0,
- 0, 0,
- (X509V3_EXT_I2V) i2v_BASIC_CONSTRAINTS,
- (X509V3_EXT_V2I)v2i_BASIC_CONSTRAINTS,
- NULL, NULL,
- NULL
-};
-
-ASN1_SEQUENCE(BASIC_CONSTRAINTS) = {
- ASN1_OPT(BASIC_CONSTRAINTS, ca, ASN1_FBOOLEAN),
- ASN1_OPT(BASIC_CONSTRAINTS, pathlen, ASN1_INTEGER)
-} ASN1_SEQUENCE_END(BASIC_CONSTRAINTS)
-
-IMPLEMENT_ASN1_FUNCTIONS(BASIC_CONSTRAINTS)
-
-static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
- BASIC_CONSTRAINTS *bcons,
- STACK_OF(CONF_VALUE)
- *extlist)
-{
- X509V3_add_value_bool("CA", bcons->ca, &extlist);
- X509V3_add_value_int("pathlen", bcons->pathlen, &extlist);
- return extlist;
-}
-
-static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *values)
-{
- BASIC_CONSTRAINTS *bcons = NULL;
- CONF_VALUE *val;
- int i;
-
- if ((bcons = BASIC_CONSTRAINTS_new()) == NULL) {
- X509V3err(X509V3_F_V2I_BASIC_CONSTRAINTS, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
- val = sk_CONF_VALUE_value(values, i);
- if (strcmp(val->name, "CA") == 0) {
- if (!X509V3_get_value_bool(val, &bcons->ca))
- goto err;
- } else if (strcmp(val->name, "pathlen") == 0) {
- if (!X509V3_get_value_int(val, &bcons->pathlen))
- goto err;
- } else {
- X509V3err(X509V3_F_V2I_BASIC_CONSTRAINTS, X509V3_R_INVALID_NAME);
- X509V3_conf_err(val);
- goto err;
- }
- }
- return bcons;
- err:
- BASIC_CONSTRAINTS_free(bcons);
- return NULL;
-}
diff --git a/crypto/x509v3/v3_bitst.c b/crypto/x509v3/v3_bitst.c
deleted file mode 100644
index 4802116ba0d4..000000000000
--- a/crypto/x509v3/v3_bitst.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/conf.h>
-#include <openssl/x509v3.h>
-#include "ext_dat.h"
-
-static BIT_STRING_BITNAME ns_cert_type_table[] = {
- {0, "SSL Client", "client"},
- {1, "SSL Server", "server"},
- {2, "S/MIME", "email"},
- {3, "Object Signing", "objsign"},
- {4, "Unused", "reserved"},
- {5, "SSL CA", "sslCA"},
- {6, "S/MIME CA", "emailCA"},
- {7, "Object Signing CA", "objCA"},
- {-1, NULL, NULL}
-};
-
-static BIT_STRING_BITNAME key_usage_type_table[] = {
- {0, "Digital Signature", "digitalSignature"},
- {1, "Non Repudiation", "nonRepudiation"},
- {2, "Key Encipherment", "keyEncipherment"},
- {3, "Data Encipherment", "dataEncipherment"},
- {4, "Key Agreement", "keyAgreement"},
- {5, "Certificate Sign", "keyCertSign"},
- {6, "CRL Sign", "cRLSign"},
- {7, "Encipher Only", "encipherOnly"},
- {8, "Decipher Only", "decipherOnly"},
- {-1, NULL, NULL}
-};
-
-const X509V3_EXT_METHOD v3_nscert =
-EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table);
-const X509V3_EXT_METHOD v3_key_usage =
-EXT_BITSTRING(NID_key_usage, key_usage_type_table);
-
-STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
- ASN1_BIT_STRING *bits,
- STACK_OF(CONF_VALUE) *ret)
-{
- BIT_STRING_BITNAME *bnam;
- for (bnam = method->usr_data; bnam->lname; bnam++) {
- if (ASN1_BIT_STRING_get_bit(bits, bnam->bitnum))
- X509V3_add_value(bnam->lname, NULL, &ret);
- }
- return ret;
-}
-
-ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval)
-{
- CONF_VALUE *val;
- ASN1_BIT_STRING *bs;
- int i;
- BIT_STRING_BITNAME *bnam;
- if ((bs = ASN1_BIT_STRING_new()) == NULL) {
- X509V3err(X509V3_F_V2I_ASN1_BIT_STRING, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
- val = sk_CONF_VALUE_value(nval, i);
- for (bnam = method->usr_data; bnam->lname; bnam++) {
- if (strcmp(bnam->sname, val->name) == 0
- || strcmp(bnam->lname, val->name) == 0) {
- if (!ASN1_BIT_STRING_set_bit(bs, bnam->bitnum, 1)) {
- X509V3err(X509V3_F_V2I_ASN1_BIT_STRING,
- ERR_R_MALLOC_FAILURE);
- ASN1_BIT_STRING_free(bs);
- return NULL;
- }
- break;
- }
- }
- if (!bnam->lname) {
- X509V3err(X509V3_F_V2I_ASN1_BIT_STRING,
- X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT);
- X509V3_conf_err(val);
- ASN1_BIT_STRING_free(bs);
- return NULL;
- }
- }
- return bs;
-}
diff --git a/crypto/x509v3/v3_conf.c b/crypto/x509v3/v3_conf.c
deleted file mode 100644
index e93de3454604..000000000000
--- a/crypto/x509v3/v3_conf.c
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/* extension creation utilities */
-
-#include <stdio.h>
-#include "crypto/ctype.h"
-#include "internal/cryptlib.h"
-#include <openssl/conf.h>
-#include <openssl/x509.h>
-#include "crypto/x509.h"
-#include <openssl/x509v3.h>
-
-static int v3_check_critical(const char **value);
-static int v3_check_generic(const char **value);
-static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
- int crit, const char *value);
-static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value,
- int crit, int type,
- X509V3_CTX *ctx);
-static char *conf_lhash_get_string(void *db, const char *section, const char *value);
-static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, const char *section);
-static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method,
- int ext_nid, int crit, void *ext_struc);
-static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx,
- long *ext_len);
-/* CONF *conf: Config file */
-/* char *name: Name */
-/* char *value: Value */
-X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, const char *name,
- const char *value)
-{
- int crit;
- int ext_type;
- X509_EXTENSION *ret;
- crit = v3_check_critical(&value);
- if ((ext_type = v3_check_generic(&value)))
- return v3_generic_extension(name, value, crit, ext_type, ctx);
- ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value);
- if (!ret) {
- X509V3err(X509V3_F_X509V3_EXT_NCONF, X509V3_R_ERROR_IN_EXTENSION);
- ERR_add_error_data(4, "name=", name, ", value=", value);
- }
- return ret;
-}
-
-/* CONF *conf: Config file */
-/* char *value: Value */
-X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
- const char *value)
-{
- int crit;
- int ext_type;
- crit = v3_check_critical(&value);
- if ((ext_type = v3_check_generic(&value)))
- return v3_generic_extension(OBJ_nid2sn(ext_nid),
- value, crit, ext_type, ctx);
- return do_ext_nconf(conf, ctx, ext_nid, crit, value);
-}
-
-/* CONF *conf: Config file */
-/* char *value: Value */
-static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
- int crit, const char *value)
-{
- const X509V3_EXT_METHOD *method;
- X509_EXTENSION *ext;
- STACK_OF(CONF_VALUE) *nval;
- void *ext_struc;
-
- if (ext_nid == NID_undef) {
- X509V3err(X509V3_F_DO_EXT_NCONF, X509V3_R_UNKNOWN_EXTENSION_NAME);
- return NULL;
- }
- if ((method = X509V3_EXT_get_nid(ext_nid)) == NULL) {
- X509V3err(X509V3_F_DO_EXT_NCONF, X509V3_R_UNKNOWN_EXTENSION);
- return NULL;
- }
- /* Now get internal extension representation based on type */
- if (method->v2i) {
- if (*value == '@')
- nval = NCONF_get_section(conf, value + 1);
- else
- nval = X509V3_parse_list(value);
- if (nval == NULL || sk_CONF_VALUE_num(nval) <= 0) {
- X509V3err(X509V3_F_DO_EXT_NCONF,
- X509V3_R_INVALID_EXTENSION_STRING);
- ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=",
- value);
- if (*value != '@')
- sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
- return NULL;
- }
- ext_struc = method->v2i(method, ctx, nval);
- if (*value != '@')
- sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
- if (!ext_struc)
- return NULL;
- } else if (method->s2i) {
- if ((ext_struc = method->s2i(method, ctx, value)) == NULL)
- return NULL;
- } else if (method->r2i) {
- if (!ctx->db || !ctx->db_meth) {
- X509V3err(X509V3_F_DO_EXT_NCONF, X509V3_R_NO_CONFIG_DATABASE);
- return NULL;
- }
- if ((ext_struc = method->r2i(method, ctx, value)) == NULL)
- return NULL;
- } else {
- X509V3err(X509V3_F_DO_EXT_NCONF,
- X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED);
- ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid));
- return NULL;
- }
-
- ext = do_ext_i2d(method, ext_nid, crit, ext_struc);
- if (method->it)
- ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it));
- else
- method->ext_free(ext_struc);
- return ext;
-
-}
-
-static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method,
- int ext_nid, int crit, void *ext_struc)
-{
- unsigned char *ext_der = NULL;
- int ext_len;
- ASN1_OCTET_STRING *ext_oct = NULL;
- X509_EXTENSION *ext;
- /* Convert internal representation to DER */
- if (method->it) {
- ext_der = NULL;
- ext_len =
- ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it));
- if (ext_len < 0)
- goto merr;
- } else {
- unsigned char *p;
-
- ext_len = method->i2d(ext_struc, NULL);
- if ((ext_der = OPENSSL_malloc(ext_len)) == NULL)
- goto merr;
- p = ext_der;
- method->i2d(ext_struc, &p);
- }
- if ((ext_oct = ASN1_OCTET_STRING_new()) == NULL)
- goto merr;
- ext_oct->data = ext_der;
- ext_der = NULL;
- ext_oct->length = ext_len;
-
- ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct);
- if (!ext)
- goto merr;
- ASN1_OCTET_STRING_free(ext_oct);
-
- return ext;
-
- merr:
- X509V3err(X509V3_F_DO_EXT_I2D, ERR_R_MALLOC_FAILURE);
- OPENSSL_free(ext_der);
- ASN1_OCTET_STRING_free(ext_oct);
- return NULL;
-
-}
-
-/* Given an internal structure, nid and critical flag create an extension */
-
-X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc)
-{
- const X509V3_EXT_METHOD *method;
-
- if ((method = X509V3_EXT_get_nid(ext_nid)) == NULL) {
- X509V3err(X509V3_F_X509V3_EXT_I2D, X509V3_R_UNKNOWN_EXTENSION);
- return NULL;
- }
- return do_ext_i2d(method, ext_nid, crit, ext_struc);
-}
-
-/* Check the extension string for critical flag */
-static int v3_check_critical(const char **value)
-{
- const char *p = *value;
- if ((strlen(p) < 9) || strncmp(p, "critical,", 9))
- return 0;
- p += 9;
- while (ossl_isspace(*p))
- p++;
- *value = p;
- return 1;
-}
-
-/* Check extension string for generic extension and return the type */
-static int v3_check_generic(const char **value)
-{
- int gen_type = 0;
- const char *p = *value;
- if ((strlen(p) >= 4) && strncmp(p, "DER:", 4) == 0) {
- p += 4;
- gen_type = 1;
- } else if ((strlen(p) >= 5) && strncmp(p, "ASN1:", 5) == 0) {
- p += 5;
- gen_type = 2;
- } else
- return 0;
-
- while (ossl_isspace(*p))
- p++;
- *value = p;
- return gen_type;
-}
-
-/* Create a generic extension: for now just handle DER type */
-static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value,
- int crit, int gen_type,
- X509V3_CTX *ctx)
-{
- unsigned char *ext_der = NULL;
- long ext_len = 0;
- ASN1_OBJECT *obj = NULL;
- ASN1_OCTET_STRING *oct = NULL;
- X509_EXTENSION *extension = NULL;
-
- if ((obj = OBJ_txt2obj(ext, 0)) == NULL) {
- X509V3err(X509V3_F_V3_GENERIC_EXTENSION,
- X509V3_R_EXTENSION_NAME_ERROR);
- ERR_add_error_data(2, "name=", ext);
- goto err;
- }
-
- if (gen_type == 1)
- ext_der = OPENSSL_hexstr2buf(value, &ext_len);
- else if (gen_type == 2)
- ext_der = generic_asn1(value, ctx, &ext_len);
-
- if (ext_der == NULL) {
- X509V3err(X509V3_F_V3_GENERIC_EXTENSION,
- X509V3_R_EXTENSION_VALUE_ERROR);
- ERR_add_error_data(2, "value=", value);
- goto err;
- }
-
- if ((oct = ASN1_OCTET_STRING_new()) == NULL) {
- X509V3err(X509V3_F_V3_GENERIC_EXTENSION, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- oct->data = ext_der;
- oct->length = ext_len;
- ext_der = NULL;
-
- extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct);
-
- err:
- ASN1_OBJECT_free(obj);
- ASN1_OCTET_STRING_free(oct);
- OPENSSL_free(ext_der);
- return extension;
-
-}
-
-static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx,
- long *ext_len)
-{
- ASN1_TYPE *typ;
- unsigned char *ext_der = NULL;
- typ = ASN1_generate_v3(value, ctx);
- if (typ == NULL)
- return NULL;
- *ext_len = i2d_ASN1_TYPE(typ, &ext_der);
- ASN1_TYPE_free(typ);
- return ext_der;
-}
-
-static void delete_ext(STACK_OF(X509_EXTENSION) *sk, X509_EXTENSION *dext)
-{
- int idx;
- ASN1_OBJECT *obj;
- obj = X509_EXTENSION_get_object(dext);
- while ((idx = X509v3_get_ext_by_OBJ(sk, obj, -1)) >= 0) {
- X509_EXTENSION *tmpext = X509v3_get_ext(sk, idx);
- X509v3_delete_ext(sk, idx);
- X509_EXTENSION_free(tmpext);
- }
-}
-
-/*
- * This is the main function: add a bunch of extensions based on a config
- * file section to an extension STACK.
- */
-
-int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section,
- STACK_OF(X509_EXTENSION) **sk)
-{
- X509_EXTENSION *ext;
- STACK_OF(CONF_VALUE) *nval;
- CONF_VALUE *val;
- int i;
-
- if ((nval = NCONF_get_section(conf, section)) == NULL)
- return 0;
- for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
- val = sk_CONF_VALUE_value(nval, i);
- if ((ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value)) == NULL)
- return 0;
- if (ctx->flags == X509V3_CTX_REPLACE)
- delete_ext(*sk, ext);
- if (sk != NULL) {
- if (X509v3_add_ext(sk, ext, -1) == NULL) {
- X509_EXTENSION_free(ext);
- return 0;
- }
- }
- X509_EXTENSION_free(ext);
- }
- return 1;
-}
-
-/*
- * Convenience functions to add extensions to a certificate, CRL and request
- */
-
-int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
- X509 *cert)
-{
- STACK_OF(X509_EXTENSION) **sk = NULL;
- if (cert)
- sk = &cert->cert_info.extensions;
- return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
-}
-
-/* Same as above but for a CRL */
-
-int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
- X509_CRL *crl)
-{
- STACK_OF(X509_EXTENSION) **sk = NULL;
- if (crl)
- sk = &crl->crl.extensions;
- return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
-}
-
-/* Add extensions to certificate request */
-
-int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
- X509_REQ *req)
-{
- STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL;
- int i;
- if (req)
- sk = &extlist;
- i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
- if (!i || !sk)
- return i;
- i = X509_REQ_add_extensions(req, extlist);
- sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);
- return i;
-}
-
-/* Config database functions */
-
-char *X509V3_get_string(X509V3_CTX *ctx, const char *name, const char *section)
-{
- if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string) {
- X509V3err(X509V3_F_X509V3_GET_STRING, X509V3_R_OPERATION_NOT_DEFINED);
- return NULL;
- }
- if (ctx->db_meth->get_string)
- return ctx->db_meth->get_string(ctx->db, name, section);
- return NULL;
-}
-
-STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, const char *section)
-{
- if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section) {
- X509V3err(X509V3_F_X509V3_GET_SECTION,
- X509V3_R_OPERATION_NOT_DEFINED);
- return NULL;
- }
- if (ctx->db_meth->get_section)
- return ctx->db_meth->get_section(ctx->db, section);
- return NULL;
-}
-
-void X509V3_string_free(X509V3_CTX *ctx, char *str)
-{
- if (!str)
- return;
- if (ctx->db_meth->free_string)
- ctx->db_meth->free_string(ctx->db, str);
-}
-
-void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section)
-{
- if (!section)
- return;
- if (ctx->db_meth->free_section)
- ctx->db_meth->free_section(ctx->db, section);
-}
-
-static char *nconf_get_string(void *db, const char *section, const char *value)
-{
- return NCONF_get_string(db, section, value);
-}
-
-static STACK_OF(CONF_VALUE) *nconf_get_section(void *db, const char *section)
-{
- return NCONF_get_section(db, section);
-}
-
-static X509V3_CONF_METHOD nconf_method = {
- nconf_get_string,
- nconf_get_section,
- NULL,
- NULL
-};
-
-void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf)
-{
- ctx->db_meth = &nconf_method;
- ctx->db = conf;
-}
-
-void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req,
- X509_CRL *crl, int flags)
-{
- ctx->issuer_cert = issuer;
- ctx->subject_cert = subj;
- ctx->crl = crl;
- ctx->subject_req = req;
- ctx->flags = flags;
-}
-
-/* Old conf compatibility functions */
-
-X509_EXTENSION *X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
- const char *name, const char *value)
-{
- CONF ctmp;
- CONF_set_nconf(&ctmp, conf);
- return X509V3_EXT_nconf(&ctmp, ctx, name, value);
-}
-
-/* LHASH *conf: Config file */
-/* char *value: Value */
-X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf,
- X509V3_CTX *ctx, int ext_nid, const char *value)
-{
- CONF ctmp;
- CONF_set_nconf(&ctmp, conf);
- return X509V3_EXT_nconf_nid(&ctmp, ctx, ext_nid, value);
-}
-
-static char *conf_lhash_get_string(void *db, const char *section, const char *value)
-{
- return CONF_get_string(db, section, value);
-}
-
-static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, const char *section)
-{
- return CONF_get_section(db, section);
-}
-
-static X509V3_CONF_METHOD conf_lhash_method = {
- conf_lhash_get_string,
- conf_lhash_get_section,
- NULL,
- NULL
-};
-
-void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash)
-{
- ctx->db_meth = &conf_lhash_method;
- ctx->db = lhash;
-}
-
-int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
- const char *section, X509 *cert)
-{
- CONF ctmp;
- CONF_set_nconf(&ctmp, conf);
- return X509V3_EXT_add_nconf(&ctmp, ctx, section, cert);
-}
-
-/* Same as above but for a CRL */
-
-int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
- const char *section, X509_CRL *crl)
-{
- CONF ctmp;
- CONF_set_nconf(&ctmp, conf);
- return X509V3_EXT_CRL_add_nconf(&ctmp, ctx, section, crl);
-}
-
-/* Add extensions to certificate request */
-
-int X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
- const char *section, X509_REQ *req)
-{
- CONF ctmp;
- CONF_set_nconf(&ctmp, conf);
- return X509V3_EXT_REQ_add_nconf(&ctmp, ctx, section, req);
-}
diff --git a/crypto/x509v3/v3_cpols.c b/crypto/x509v3/v3_cpols.c
deleted file mode 100644
index 09804b58482c..000000000000
--- a/crypto/x509v3/v3_cpols.c
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/conf.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-#include <openssl/x509v3.h>
-
-#include "pcy_local.h"
-#include "ext_dat.h"
-
-/* Certificate policies extension support: this one is a bit complex... */
-
-static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
- BIO *out, int indent);
-static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, const char *value);
-static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
- int indent);
-static void print_notice(BIO *out, USERNOTICE *notice, int indent);
-static POLICYINFO *policy_section(X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *polstrs, int ia5org);
-static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *unot, int ia5org);
-static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos);
-static int displaytext_str2tag(const char *tagstr, unsigned int *tag_len);
-static int displaytext_get_tag_len(const char *tagstr);
-
-const X509V3_EXT_METHOD v3_cpols = {
- NID_certificate_policies, 0, ASN1_ITEM_ref(CERTIFICATEPOLICIES),
- 0, 0, 0, 0,
- 0, 0,
- 0, 0,
- (X509V3_EXT_I2R)i2r_certpol,
- (X509V3_EXT_R2I)r2i_certpol,
- NULL
-};
-
-ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) =
- ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO)
-ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES)
-
-IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
-
-ASN1_SEQUENCE(POLICYINFO) = {
- ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT),
- ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO)
-} ASN1_SEQUENCE_END(POLICYINFO)
-
-IMPLEMENT_ASN1_FUNCTIONS(POLICYINFO)
-
-ASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, ASN1_ANY);
-
-ASN1_ADB(POLICYQUALINFO) = {
- ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)),
- ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE))
-} ASN1_ADB_END(POLICYQUALINFO, 0, pqualid, 0, &policydefault_tt, NULL);
-
-ASN1_SEQUENCE(POLICYQUALINFO) = {
- ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT),
- ASN1_ADB_OBJECT(POLICYQUALINFO)
-} ASN1_SEQUENCE_END(POLICYQUALINFO)
-
-IMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO)
-
-ASN1_SEQUENCE(USERNOTICE) = {
- ASN1_OPT(USERNOTICE, noticeref, NOTICEREF),
- ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT)
-} ASN1_SEQUENCE_END(USERNOTICE)
-
-IMPLEMENT_ASN1_FUNCTIONS(USERNOTICE)
-
-ASN1_SEQUENCE(NOTICEREF) = {
- ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT),
- ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER)
-} ASN1_SEQUENCE_END(NOTICEREF)
-
-IMPLEMENT_ASN1_FUNCTIONS(NOTICEREF)
-
-static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, const char *value)
-{
- STACK_OF(POLICYINFO) *pols;
- char *pstr;
- POLICYINFO *pol;
- ASN1_OBJECT *pobj;
- STACK_OF(CONF_VALUE) *vals = X509V3_parse_list(value);
- CONF_VALUE *cnf;
- const int num = sk_CONF_VALUE_num(vals);
- int i, ia5org;
-
- if (vals == NULL) {
- X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_X509V3_LIB);
- return NULL;
- }
-
- pols = sk_POLICYINFO_new_reserve(NULL, num);
- if (pols == NULL) {
- X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- ia5org = 0;
- for (i = 0; i < num; i++) {
- cnf = sk_CONF_VALUE_value(vals, i);
-
- if (cnf->value || !cnf->name) {
- X509V3err(X509V3_F_R2I_CERTPOL,
- X509V3_R_INVALID_POLICY_IDENTIFIER);
- X509V3_conf_err(cnf);
- goto err;
- }
- pstr = cnf->name;
- if (strcmp(pstr, "ia5org") == 0) {
- ia5org = 1;
- continue;
- } else if (*pstr == '@') {
- STACK_OF(CONF_VALUE) *polsect;
- polsect = X509V3_get_section(ctx, pstr + 1);
- if (!polsect) {
- X509V3err(X509V3_F_R2I_CERTPOL, X509V3_R_INVALID_SECTION);
-
- X509V3_conf_err(cnf);
- goto err;
- }
- pol = policy_section(ctx, polsect, ia5org);
- X509V3_section_free(ctx, polsect);
- if (pol == NULL)
- goto err;
- } else {
- if ((pobj = OBJ_txt2obj(cnf->name, 0)) == NULL) {
- X509V3err(X509V3_F_R2I_CERTPOL,
- X509V3_R_INVALID_OBJECT_IDENTIFIER);
- X509V3_conf_err(cnf);
- goto err;
- }
- pol = POLICYINFO_new();
- if (pol == NULL) {
- ASN1_OBJECT_free(pobj);
- X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- pol->policyid = pobj;
- }
- if (!sk_POLICYINFO_push(pols, pol)) {
- POLICYINFO_free(pol);
- X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
- sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
- return pols;
- err:
- sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
- sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
- return NULL;
-}
-
-static POLICYINFO *policy_section(X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *polstrs, int ia5org)
-{
- int i;
- CONF_VALUE *cnf;
- POLICYINFO *pol;
- POLICYQUALINFO *qual;
-
- if ((pol = POLICYINFO_new()) == NULL)
- goto merr;
- for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) {
- cnf = sk_CONF_VALUE_value(polstrs, i);
- if (strcmp(cnf->name, "policyIdentifier") == 0) {
- ASN1_OBJECT *pobj;
- if ((pobj = OBJ_txt2obj(cnf->value, 0)) == NULL) {
- X509V3err(X509V3_F_POLICY_SECTION,
- X509V3_R_INVALID_OBJECT_IDENTIFIER);
- X509V3_conf_err(cnf);
- goto err;
- }
- pol->policyid = pobj;
-
- } else if (!name_cmp(cnf->name, "CPS")) {
- if (pol->qualifiers == NULL)
- pol->qualifiers = sk_POLICYQUALINFO_new_null();
- if ((qual = POLICYQUALINFO_new()) == NULL)
- goto merr;
- if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
- goto merr;
- if ((qual->pqualid = OBJ_nid2obj(NID_id_qt_cps)) == NULL) {
- X509V3err(X509V3_F_POLICY_SECTION, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- if ((qual->d.cpsuri = ASN1_IA5STRING_new()) == NULL)
- goto merr;
- if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value,
- strlen(cnf->value)))
- goto merr;
- } else if (!name_cmp(cnf->name, "userNotice")) {
- STACK_OF(CONF_VALUE) *unot;
- if (*cnf->value != '@') {
- X509V3err(X509V3_F_POLICY_SECTION,
- X509V3_R_EXPECTED_A_SECTION_NAME);
- X509V3_conf_err(cnf);
- goto err;
- }
- unot = X509V3_get_section(ctx, cnf->value + 1);
- if (!unot) {
- X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_SECTION);
-
- X509V3_conf_err(cnf);
- goto err;
- }
- qual = notice_section(ctx, unot, ia5org);
- X509V3_section_free(ctx, unot);
- if (!qual)
- goto err;
- if (!pol->qualifiers)
- pol->qualifiers = sk_POLICYQUALINFO_new_null();
- if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
- goto merr;
- } else {
- X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_OPTION);
-
- X509V3_conf_err(cnf);
- goto err;
- }
- }
- if (!pol->policyid) {
- X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_NO_POLICY_IDENTIFIER);
- goto err;
- }
-
- return pol;
-
- merr:
- X509V3err(X509V3_F_POLICY_SECTION, ERR_R_MALLOC_FAILURE);
-
- err:
- POLICYINFO_free(pol);
- return NULL;
-}
-
-static int displaytext_get_tag_len(const char *tagstr)
-{
- char *colon = strchr(tagstr, ':');
-
- return (colon == NULL) ? -1 : colon - tagstr;
-}
-
-static int displaytext_str2tag(const char *tagstr, unsigned int *tag_len)
-{
- int len;
-
- *tag_len = 0;
- len = displaytext_get_tag_len(tagstr);
-
- if (len == -1)
- return V_ASN1_VISIBLESTRING;
- *tag_len = len;
- if (len == sizeof("UTF8") - 1 && strncmp(tagstr, "UTF8", len) == 0)
- return V_ASN1_UTF8STRING;
- if (len == sizeof("UTF8String") - 1 && strncmp(tagstr, "UTF8String", len) == 0)
- return V_ASN1_UTF8STRING;
- if (len == sizeof("BMP") - 1 && strncmp(tagstr, "BMP", len) == 0)
- return V_ASN1_BMPSTRING;
- if (len == sizeof("BMPSTRING") - 1 && strncmp(tagstr, "BMPSTRING", len) == 0)
- return V_ASN1_BMPSTRING;
- if (len == sizeof("VISIBLE") - 1 && strncmp(tagstr, "VISIBLE", len) == 0)
- return V_ASN1_VISIBLESTRING;
- if (len == sizeof("VISIBLESTRING") - 1 && strncmp(tagstr, "VISIBLESTRING", len) == 0)
- return V_ASN1_VISIBLESTRING;
- *tag_len = 0;
- return V_ASN1_VISIBLESTRING;
-}
-
-static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *unot, int ia5org)
-{
- int i, ret, len, tag;
- unsigned int tag_len;
- CONF_VALUE *cnf;
- USERNOTICE *not;
- POLICYQUALINFO *qual;
- char *value = NULL;
-
- if ((qual = POLICYQUALINFO_new()) == NULL)
- goto merr;
- if ((qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice)) == NULL) {
- X509V3err(X509V3_F_NOTICE_SECTION, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- if ((not = USERNOTICE_new()) == NULL)
- goto merr;
- qual->d.usernotice = not;
- for (i = 0; i < sk_CONF_VALUE_num(unot); i++) {
- cnf = sk_CONF_VALUE_value(unot, i);
- value = cnf->value;
- if (strcmp(cnf->name, "explicitText") == 0) {
- tag = displaytext_str2tag(value, &tag_len);
- if ((not->exptext = ASN1_STRING_type_new(tag)) == NULL)
- goto merr;
- if (tag_len != 0)
- value += tag_len + 1;
- len = strlen(value);
- if (!ASN1_STRING_set(not->exptext, value, len))
- goto merr;
- } else if (strcmp(cnf->name, "organization") == 0) {
- NOTICEREF *nref;
- if (!not->noticeref) {
- if ((nref = NOTICEREF_new()) == NULL)
- goto merr;
- not->noticeref = nref;
- } else
- nref = not->noticeref;
- if (ia5org)
- nref->organization->type = V_ASN1_IA5STRING;
- else
- nref->organization->type = V_ASN1_VISIBLESTRING;
- if (!ASN1_STRING_set(nref->organization, cnf->value,
- strlen(cnf->value)))
- goto merr;
- } else if (strcmp(cnf->name, "noticeNumbers") == 0) {
- NOTICEREF *nref;
- STACK_OF(CONF_VALUE) *nos;
- if (!not->noticeref) {
- if ((nref = NOTICEREF_new()) == NULL)
- goto merr;
- not->noticeref = nref;
- } else
- nref = not->noticeref;
- nos = X509V3_parse_list(cnf->value);
- if (!nos || !sk_CONF_VALUE_num(nos)) {
- X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_NUMBERS);
- X509V3_conf_err(cnf);
- sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
- goto err;
- }
- ret = nref_nos(nref->noticenos, nos);
- sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
- if (!ret)
- goto err;
- } else {
- X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_OPTION);
- X509V3_conf_err(cnf);
- goto err;
- }
- }
-
- if (not->noticeref &&
- (!not->noticeref->noticenos || !not->noticeref->organization)) {
- X509V3err(X509V3_F_NOTICE_SECTION,
- X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
- goto err;
- }
-
- return qual;
-
- merr:
- X509V3err(X509V3_F_NOTICE_SECTION, ERR_R_MALLOC_FAILURE);
-
- err:
- POLICYQUALINFO_free(qual);
- return NULL;
-}
-
-static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos)
-{
- CONF_VALUE *cnf;
- ASN1_INTEGER *aint;
-
- int i;
-
- for (i = 0; i < sk_CONF_VALUE_num(nos); i++) {
- cnf = sk_CONF_VALUE_value(nos, i);
- if ((aint = s2i_ASN1_INTEGER(NULL, cnf->name)) == NULL) {
- X509V3err(X509V3_F_NREF_NOS, X509V3_R_INVALID_NUMBER);
- goto err;
- }
- if (!sk_ASN1_INTEGER_push(nnums, aint))
- goto merr;
- }
- return 1;
-
- merr:
- ASN1_INTEGER_free(aint);
- X509V3err(X509V3_F_NREF_NOS, ERR_R_MALLOC_FAILURE);
-
- err:
- return 0;
-}
-
-static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
- BIO *out, int indent)
-{
- int i;
- POLICYINFO *pinfo;
- /* First print out the policy OIDs */
- for (i = 0; i < sk_POLICYINFO_num(pol); i++) {
- pinfo = sk_POLICYINFO_value(pol, i);
- BIO_printf(out, "%*sPolicy: ", indent, "");
- i2a_ASN1_OBJECT(out, pinfo->policyid);
- BIO_puts(out, "\n");
- if (pinfo->qualifiers)
- print_qualifiers(out, pinfo->qualifiers, indent + 2);
- }
- return 1;
-}
-
-static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
- int indent)
-{
- POLICYQUALINFO *qualinfo;
- int i;
- for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
- qualinfo = sk_POLICYQUALINFO_value(quals, i);
- switch (OBJ_obj2nid(qualinfo->pqualid)) {
- case NID_id_qt_cps:
- BIO_printf(out, "%*sCPS: %.*s\n", indent, "",
- qualinfo->d.cpsuri->length,
- qualinfo->d.cpsuri->data);
- break;
-
- case NID_id_qt_unotice:
- BIO_printf(out, "%*sUser Notice:\n", indent, "");
- print_notice(out, qualinfo->d.usernotice, indent + 2);
- break;
-
- default:
- BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, "");
-
- i2a_ASN1_OBJECT(out, qualinfo->pqualid);
- BIO_puts(out, "\n");
- break;
- }
- }
-}
-
-static void print_notice(BIO *out, USERNOTICE *notice, int indent)
-{
- int i;
- if (notice->noticeref) {
- NOTICEREF *ref;
- ref = notice->noticeref;
- BIO_printf(out, "%*sOrganization: %.*s\n", indent, "",
- ref->organization->length,
- ref->organization->data);
- BIO_printf(out, "%*sNumber%s: ", indent, "",
- sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : "");
- for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) {
- ASN1_INTEGER *num;
- char *tmp;
- num = sk_ASN1_INTEGER_value(ref->noticenos, i);
- if (i)
- BIO_puts(out, ", ");
- if (num == NULL)
- BIO_puts(out, "(null)");
- else {
- tmp = i2s_ASN1_INTEGER(NULL, num);
- if (tmp == NULL)
- return;
- BIO_puts(out, tmp);
- OPENSSL_free(tmp);
- }
- }
- BIO_puts(out, "\n");
- }
- if (notice->exptext)
- BIO_printf(out, "%*sExplicit Text: %.*s\n", indent, "",
- notice->exptext->length,
- notice->exptext->data);
-}
-
-void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent)
-{
- const X509_POLICY_DATA *dat = node->data;
-
- BIO_printf(out, "%*sPolicy: ", indent, "");
-
- i2a_ASN1_OBJECT(out, dat->valid_policy);
- BIO_puts(out, "\n");
- BIO_printf(out, "%*s%s\n", indent + 2, "",
- node_data_critical(dat) ? "Critical" : "Non Critical");
- if (dat->qualifier_set)
- print_qualifiers(out, dat->qualifier_set, indent + 2);
- else
- BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
-}
diff --git a/crypto/x509v3/v3_crld.c b/crypto/x509v3/v3_crld.c
deleted file mode 100644
index 4854748ffb51..000000000000
--- a/crypto/x509v3/v3_crld.c
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/conf.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-#include <openssl/x509v3.h>
-
-#include "crypto/x509.h"
-#include "ext_dat.h"
-
-static void *v2i_crld(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
-static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
- int indent);
-
-const X509V3_EXT_METHOD v3_crld = {
- NID_crl_distribution_points, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
- 0, 0, 0, 0,
- 0, 0,
- 0,
- v2i_crld,
- i2r_crldp, 0,
- NULL
-};
-
-const X509V3_EXT_METHOD v3_freshest_crl = {
- NID_freshest_crl, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
- 0, 0, 0, 0,
- 0, 0,
- 0,
- v2i_crld,
- i2r_crldp, 0,
- NULL
-};
-
-static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx,
- char *sect)
-{
- STACK_OF(CONF_VALUE) *gnsect;
- STACK_OF(GENERAL_NAME) *gens;
- if (*sect == '@')
- gnsect = X509V3_get_section(ctx, sect + 1);
- else
- gnsect = X509V3_parse_list(sect);
- if (!gnsect) {
- X509V3err(X509V3_F_GNAMES_FROM_SECTNAME, X509V3_R_SECTION_NOT_FOUND);
- return NULL;
- }
- gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect);
- if (*sect == '@')
- X509V3_section_free(ctx, gnsect);
- else
- sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free);
- return gens;
-}
-
-static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx,
- CONF_VALUE *cnf)
-{
- STACK_OF(GENERAL_NAME) *fnm = NULL;
- STACK_OF(X509_NAME_ENTRY) *rnm = NULL;
-
- if (strncmp(cnf->name, "fullname", 9) == 0) {
- fnm = gnames_from_sectname(ctx, cnf->value);
- if (!fnm)
- goto err;
- } else if (strcmp(cnf->name, "relativename") == 0) {
- int ret;
- STACK_OF(CONF_VALUE) *dnsect;
- X509_NAME *nm;
- nm = X509_NAME_new();
- if (nm == NULL)
- return -1;
- dnsect = X509V3_get_section(ctx, cnf->value);
- if (!dnsect) {
- X509V3err(X509V3_F_SET_DIST_POINT_NAME,
- X509V3_R_SECTION_NOT_FOUND);
- return -1;
- }
- ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC);
- X509V3_section_free(ctx, dnsect);
- rnm = nm->entries;
- nm->entries = NULL;
- X509_NAME_free(nm);
- if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0)
- goto err;
- /*
- * Since its a name fragment can't have more than one RDNSequence
- */
- if (sk_X509_NAME_ENTRY_value(rnm,
- sk_X509_NAME_ENTRY_num(rnm) - 1)->set) {
- X509V3err(X509V3_F_SET_DIST_POINT_NAME,
- X509V3_R_INVALID_MULTIPLE_RDNS);
- goto err;
- }
- } else
- return 0;
-
- if (*pdp) {
- X509V3err(X509V3_F_SET_DIST_POINT_NAME,
- X509V3_R_DISTPOINT_ALREADY_SET);
- goto err;
- }
-
- *pdp = DIST_POINT_NAME_new();
- if (*pdp == NULL)
- goto err;
- if (fnm) {
- (*pdp)->type = 0;
- (*pdp)->name.fullname = fnm;
- } else {
- (*pdp)->type = 1;
- (*pdp)->name.relativename = rnm;
- }
-
- return 1;
-
- err:
- sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free);
- sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free);
- return -1;
-}
-
-static const BIT_STRING_BITNAME reason_flags[] = {
- {0, "Unused", "unused"},
- {1, "Key Compromise", "keyCompromise"},
- {2, "CA Compromise", "CACompromise"},
- {3, "Affiliation Changed", "affiliationChanged"},
- {4, "Superseded", "superseded"},
- {5, "Cessation Of Operation", "cessationOfOperation"},
- {6, "Certificate Hold", "certificateHold"},
- {7, "Privilege Withdrawn", "privilegeWithdrawn"},
- {8, "AA Compromise", "AACompromise"},
- {-1, NULL, NULL}
-};
-
-static int set_reasons(ASN1_BIT_STRING **preas, char *value)
-{
- STACK_OF(CONF_VALUE) *rsk = NULL;
- const BIT_STRING_BITNAME *pbn;
- const char *bnam;
- int i, ret = 0;
- rsk = X509V3_parse_list(value);
- if (rsk == NULL)
- return 0;
- if (*preas != NULL)
- goto err;
- for (i = 0; i < sk_CONF_VALUE_num(rsk); i++) {
- bnam = sk_CONF_VALUE_value(rsk, i)->name;
- if (*preas == NULL) {
- *preas = ASN1_BIT_STRING_new();
- if (*preas == NULL)
- goto err;
- }
- for (pbn = reason_flags; pbn->lname; pbn++) {
- if (strcmp(pbn->sname, bnam) == 0) {
- if (!ASN1_BIT_STRING_set_bit(*preas, pbn->bitnum, 1))
- goto err;
- break;
- }
- }
- if (!pbn->lname)
- goto err;
- }
- ret = 1;
-
- err:
- sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free);
- return ret;
-}
-
-static int print_reasons(BIO *out, const char *rname,
- ASN1_BIT_STRING *rflags, int indent)
-{
- int first = 1;
- const BIT_STRING_BITNAME *pbn;
- BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, "");
- for (pbn = reason_flags; pbn->lname; pbn++) {
- if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum)) {
- if (first)
- first = 0;
- else
- BIO_puts(out, ", ");
- BIO_puts(out, pbn->lname);
- }
- }
- if (first)
- BIO_puts(out, "<EMPTY>\n");
- else
- BIO_puts(out, "\n");
- return 1;
-}
-
-static DIST_POINT *crldp_from_section(X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval)
-{
- int i;
- CONF_VALUE *cnf;
- DIST_POINT *point = DIST_POINT_new();
-
- if (point == NULL)
- goto err;
- for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
- int ret;
- cnf = sk_CONF_VALUE_value(nval, i);
- ret = set_dist_point_name(&point->distpoint, ctx, cnf);
- if (ret > 0)
- continue;
- if (ret < 0)
- goto err;
- if (strcmp(cnf->name, "reasons") == 0) {
- if (!set_reasons(&point->reasons, cnf->value))
- goto err;
- } else if (strcmp(cnf->name, "CRLissuer") == 0) {
- point->CRLissuer = gnames_from_sectname(ctx, cnf->value);
- if (!point->CRLissuer)
- goto err;
- }
- }
-
- return point;
-
- err:
- DIST_POINT_free(point);
- return NULL;
-}
-
-static void *v2i_crld(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
-{
- STACK_OF(DIST_POINT) *crld;
- GENERAL_NAMES *gens = NULL;
- GENERAL_NAME *gen = NULL;
- CONF_VALUE *cnf;
- const int num = sk_CONF_VALUE_num(nval);
- int i;
-
- crld = sk_DIST_POINT_new_reserve(NULL, num);
- if (crld == NULL)
- goto merr;
- for (i = 0; i < num; i++) {
- DIST_POINT *point;
-
- cnf = sk_CONF_VALUE_value(nval, i);
- if (!cnf->value) {
- STACK_OF(CONF_VALUE) *dpsect;
- dpsect = X509V3_get_section(ctx, cnf->name);
- if (!dpsect)
- goto err;
- point = crldp_from_section(ctx, dpsect);
- X509V3_section_free(ctx, dpsect);
- if (!point)
- goto err;
- sk_DIST_POINT_push(crld, point); /* no failure as it was reserved */
- } else {
- if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
- goto err;
- if ((gens = GENERAL_NAMES_new()) == NULL)
- goto merr;
- if (!sk_GENERAL_NAME_push(gens, gen))
- goto merr;
- gen = NULL;
- if ((point = DIST_POINT_new()) == NULL)
- goto merr;
- sk_DIST_POINT_push(crld, point); /* no failure as it was reserved */
- if ((point->distpoint = DIST_POINT_NAME_new()) == NULL)
- goto merr;
- point->distpoint->name.fullname = gens;
- point->distpoint->type = 0;
- gens = NULL;
- }
- }
- return crld;
-
- merr:
- X509V3err(X509V3_F_V2I_CRLD, ERR_R_MALLOC_FAILURE);
- err:
- GENERAL_NAME_free(gen);
- GENERAL_NAMES_free(gens);
- sk_DIST_POINT_pop_free(crld, DIST_POINT_free);
- return NULL;
-}
-
-static int dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
- void *exarg)
-{
- DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval;
-
- switch (operation) {
- case ASN1_OP_NEW_POST:
- dpn->dpname = NULL;
- break;
-
- case ASN1_OP_FREE_POST:
- X509_NAME_free(dpn->dpname);
- break;
- }
- return 1;
-}
-
-
-ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = {
- ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0),
- ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1)
-} ASN1_CHOICE_END_cb(DIST_POINT_NAME, DIST_POINT_NAME, type)
-
-
-IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME)
-
-ASN1_SEQUENCE(DIST_POINT) = {
- ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0),
- ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1),
- ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2)
-} ASN1_SEQUENCE_END(DIST_POINT)
-
-IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT)
-
-ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) =
- ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT)
-ASN1_ITEM_TEMPLATE_END(CRL_DIST_POINTS)
-
-IMPLEMENT_ASN1_FUNCTIONS(CRL_DIST_POINTS)
-
-ASN1_SEQUENCE(ISSUING_DIST_POINT) = {
- ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0),
- ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1),
- ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2),
- ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3),
- ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4),
- ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5)
-} ASN1_SEQUENCE_END(ISSUING_DIST_POINT)
-
-IMPLEMENT_ASN1_FUNCTIONS(ISSUING_DIST_POINT)
-
-static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
- int indent);
-static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval);
-
-const X509V3_EXT_METHOD v3_idp = {
- NID_issuing_distribution_point, X509V3_EXT_MULTILINE,
- ASN1_ITEM_ref(ISSUING_DIST_POINT),
- 0, 0, 0, 0,
- 0, 0,
- 0,
- v2i_idp,
- i2r_idp, 0,
- NULL
-};
-
-static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval)
-{
- ISSUING_DIST_POINT *idp = NULL;
- CONF_VALUE *cnf;
- char *name, *val;
- int i, ret;
- idp = ISSUING_DIST_POINT_new();
- if (idp == NULL)
- goto merr;
- for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
- cnf = sk_CONF_VALUE_value(nval, i);
- name = cnf->name;
- val = cnf->value;
- ret = set_dist_point_name(&idp->distpoint, ctx, cnf);
- if (ret > 0)
- continue;
- if (ret < 0)
- goto err;
- if (strcmp(name, "onlyuser") == 0) {
- if (!X509V3_get_value_bool(cnf, &idp->onlyuser))
- goto err;
- } else if (strcmp(name, "onlyCA") == 0) {
- if (!X509V3_get_value_bool(cnf, &idp->onlyCA))
- goto err;
- } else if (strcmp(name, "onlyAA") == 0) {
- if (!X509V3_get_value_bool(cnf, &idp->onlyattr))
- goto err;
- } else if (strcmp(name, "indirectCRL") == 0) {
- if (!X509V3_get_value_bool(cnf, &idp->indirectCRL))
- goto err;
- } else if (strcmp(name, "onlysomereasons") == 0) {
- if (!set_reasons(&idp->onlysomereasons, val))
- goto err;
- } else {
- X509V3err(X509V3_F_V2I_IDP, X509V3_R_INVALID_NAME);
- X509V3_conf_err(cnf);
- goto err;
- }
- }
- return idp;
-
- merr:
- X509V3err(X509V3_F_V2I_IDP, ERR_R_MALLOC_FAILURE);
- err:
- ISSUING_DIST_POINT_free(idp);
- return NULL;
-}
-
-static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent)
-{
- int i;
- for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
- BIO_printf(out, "%*s", indent + 2, "");
- GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i));
- BIO_puts(out, "\n");
- }
- return 1;
-}
-
-static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent)
-{
- if (dpn->type == 0) {
- BIO_printf(out, "%*sFull Name:\n", indent, "");
- print_gens(out, dpn->name.fullname, indent);
- } else {
- X509_NAME ntmp;
- ntmp.entries = dpn->name.relativename;
- BIO_printf(out, "%*sRelative Name:\n%*s", indent, "", indent + 2, "");
- X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE);
- BIO_puts(out, "\n");
- }
- return 1;
-}
-
-static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
- int indent)
-{
- ISSUING_DIST_POINT *idp = pidp;
- if (idp->distpoint)
- print_distpoint(out, idp->distpoint, indent);
- if (idp->onlyuser > 0)
- BIO_printf(out, "%*sOnly User Certificates\n", indent, "");
- if (idp->onlyCA > 0)
- BIO_printf(out, "%*sOnly CA Certificates\n", indent, "");
- if (idp->indirectCRL > 0)
- BIO_printf(out, "%*sIndirect CRL\n", indent, "");
- if (idp->onlysomereasons)
- print_reasons(out, "Only Some Reasons", idp->onlysomereasons, indent);
- if (idp->onlyattr > 0)
- BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, "");
- if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0)
- && (idp->indirectCRL <= 0) && !idp->onlysomereasons
- && (idp->onlyattr <= 0))
- BIO_printf(out, "%*s<EMPTY>\n", indent, "");
-
- return 1;
-}
-
-static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
- int indent)
-{
- STACK_OF(DIST_POINT) *crld = pcrldp;
- DIST_POINT *point;
- int i;
- for (i = 0; i < sk_DIST_POINT_num(crld); i++) {
- BIO_puts(out, "\n");
- point = sk_DIST_POINT_value(crld, i);
- if (point->distpoint)
- print_distpoint(out, point->distpoint, indent);
- if (point->reasons)
- print_reasons(out, "Reasons", point->reasons, indent);
- if (point->CRLissuer) {
- BIO_printf(out, "%*sCRL Issuer:\n", indent, "");
- print_gens(out, point->CRLissuer, indent);
- }
- }
- return 1;
-}
-
-int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname)
-{
- int i;
- STACK_OF(X509_NAME_ENTRY) *frag;
- X509_NAME_ENTRY *ne;
- if (!dpn || (dpn->type != 1))
- return 1;
- frag = dpn->name.relativename;
- dpn->dpname = X509_NAME_dup(iname);
- if (!dpn->dpname)
- return 0;
- for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) {
- ne = sk_X509_NAME_ENTRY_value(frag, i);
- if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1)) {
- X509_NAME_free(dpn->dpname);
- dpn->dpname = NULL;
- return 0;
- }
- }
- /* generate cached encoding of name */
- if (i2d_X509_NAME(dpn->dpname, NULL) < 0) {
- X509_NAME_free(dpn->dpname);
- dpn->dpname = NULL;
- return 0;
- }
- return 1;
-}
diff --git a/crypto/x509v3/v3_enum.c b/crypto/x509v3/v3_enum.c
deleted file mode 100644
index 3b0f197444af..000000000000
--- a/crypto/x509v3/v3_enum.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/x509v3.h>
-#include "ext_dat.h"
-
-static ENUMERATED_NAMES crl_reasons[] = {
- {CRL_REASON_UNSPECIFIED, "Unspecified", "unspecified"},
- {CRL_REASON_KEY_COMPROMISE, "Key Compromise", "keyCompromise"},
- {CRL_REASON_CA_COMPROMISE, "CA Compromise", "CACompromise"},
- {CRL_REASON_AFFILIATION_CHANGED, "Affiliation Changed",
- "affiliationChanged"},
- {CRL_REASON_SUPERSEDED, "Superseded", "superseded"},
- {CRL_REASON_CESSATION_OF_OPERATION,
- "Cessation Of Operation", "cessationOfOperation"},
- {CRL_REASON_CERTIFICATE_HOLD, "Certificate Hold", "certificateHold"},
- {CRL_REASON_REMOVE_FROM_CRL, "Remove From CRL", "removeFromCRL"},
- {CRL_REASON_PRIVILEGE_WITHDRAWN, "Privilege Withdrawn",
- "privilegeWithdrawn"},
- {CRL_REASON_AA_COMPROMISE, "AA Compromise", "AACompromise"},
- {-1, NULL, NULL}
-};
-
-const X509V3_EXT_METHOD v3_crl_reason = {
- NID_crl_reason, 0, ASN1_ITEM_ref(ASN1_ENUMERATED),
- 0, 0, 0, 0,
- (X509V3_EXT_I2S)i2s_ASN1_ENUMERATED_TABLE,
- 0,
- 0, 0, 0, 0,
- crl_reasons
-};
-
-char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method,
- const ASN1_ENUMERATED *e)
-{
- ENUMERATED_NAMES *enam;
- long strval;
-
- strval = ASN1_ENUMERATED_get(e);
- for (enam = method->usr_data; enam->lname; enam++) {
- if (strval == enam->bitnum)
- return OPENSSL_strdup(enam->lname);
- }
- return i2s_ASN1_ENUMERATED(method, e);
-}
diff --git a/crypto/x509v3/v3_extku.c b/crypto/x509v3/v3_extku.c
deleted file mode 100644
index 91b24376ed8a..000000000000
--- a/crypto/x509v3/v3_extku.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/asn1t.h>
-#include <openssl/conf.h>
-#include <openssl/x509v3.h>
-#include "ext_dat.h"
-
-static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval);
-static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD
- *method, void *eku, STACK_OF(CONF_VALUE)
- *extlist);
-
-const X509V3_EXT_METHOD v3_ext_ku = {
- NID_ext_key_usage, 0,
- ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
- 0, 0, 0, 0,
- 0, 0,
- i2v_EXTENDED_KEY_USAGE,
- v2i_EXTENDED_KEY_USAGE,
- 0, 0,
- NULL
-};
-
-/* NB OCSP acceptable responses also is a SEQUENCE OF OBJECT */
-const X509V3_EXT_METHOD v3_ocsp_accresp = {
- NID_id_pkix_OCSP_acceptableResponses, 0,
- ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
- 0, 0, 0, 0,
- 0, 0,
- i2v_EXTENDED_KEY_USAGE,
- v2i_EXTENDED_KEY_USAGE,
- 0, 0,
- NULL
-};
-
-ASN1_ITEM_TEMPLATE(EXTENDED_KEY_USAGE) =
- ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, EXTENDED_KEY_USAGE, ASN1_OBJECT)
-ASN1_ITEM_TEMPLATE_END(EXTENDED_KEY_USAGE)
-
-IMPLEMENT_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE)
-
-static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD
- *method, void *a, STACK_OF(CONF_VALUE)
- *ext_list)
-{
- EXTENDED_KEY_USAGE *eku = a;
- int i;
- ASN1_OBJECT *obj;
- char obj_tmp[80];
- for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
- obj = sk_ASN1_OBJECT_value(eku, i);
- i2t_ASN1_OBJECT(obj_tmp, 80, obj);
- X509V3_add_value(NULL, obj_tmp, &ext_list);
- }
- return ext_list;
-}
-
-static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval)
-{
- EXTENDED_KEY_USAGE *extku;
- char *extval;
- ASN1_OBJECT *objtmp;
- CONF_VALUE *val;
- const int num = sk_CONF_VALUE_num(nval);
- int i;
-
- extku = sk_ASN1_OBJECT_new_reserve(NULL, num);
- if (extku == NULL) {
- X509V3err(X509V3_F_V2I_EXTENDED_KEY_USAGE, ERR_R_MALLOC_FAILURE);
- sk_ASN1_OBJECT_free(extku);
- return NULL;
- }
-
- for (i = 0; i < num; i++) {
- val = sk_CONF_VALUE_value(nval, i);
- if (val->value)
- extval = val->value;
- else
- extval = val->name;
- if ((objtmp = OBJ_txt2obj(extval, 0)) == NULL) {
- sk_ASN1_OBJECT_pop_free(extku, ASN1_OBJECT_free);
- X509V3err(X509V3_F_V2I_EXTENDED_KEY_USAGE,
- X509V3_R_INVALID_OBJECT_IDENTIFIER);
- X509V3_conf_err(val);
- return NULL;
- }
- sk_ASN1_OBJECT_push(extku, objtmp); /* no failure as it was reserved */
- }
- return extku;
-}
diff --git a/crypto/x509v3/v3_genn.c b/crypto/x509v3/v3_genn.c
deleted file mode 100644
index fd307c43cf20..000000000000
--- a/crypto/x509v3/v3_genn.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/asn1t.h>
-#include <openssl/conf.h>
-#include <openssl/x509v3.h>
-
-ASN1_SEQUENCE(OTHERNAME) = {
- ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT),
- /* Maybe have a true ANY DEFINED BY later */
- ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0)
-} ASN1_SEQUENCE_END(OTHERNAME)
-
-IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME)
-
-ASN1_SEQUENCE(EDIPARTYNAME) = {
- /* DirectoryString is a CHOICE type so use explicit tagging */
- ASN1_EXP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0),
- ASN1_EXP(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1)
-} ASN1_SEQUENCE_END(EDIPARTYNAME)
-
-IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME)
-
-ASN1_CHOICE(GENERAL_NAME) = {
- ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME),
- ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL),
- ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS),
- /* Don't decode this */
- ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400),
- /* X509_NAME is a CHOICE type so use EXPLICIT */
- ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME),
- ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY),
- ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, GEN_URI),
- ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD),
- ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID)
-} ASN1_CHOICE_END(GENERAL_NAME)
-
-IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAME)
-
-ASN1_ITEM_TEMPLATE(GENERAL_NAMES) =
- ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME)
-ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES)
-
-IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES)
-
-GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a)
-{
- return (GENERAL_NAME *)ASN1_dup((i2d_of_void *)i2d_GENERAL_NAME,
- (d2i_of_void *)d2i_GENERAL_NAME,
- (char *)a);
-}
-
-static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b)
-{
- int res;
-
- if (a == NULL || b == NULL) {
- /*
- * Shouldn't be possible in a valid GENERAL_NAME, but we handle it
- * anyway. OTHERNAME_cmp treats NULL != NULL so we do the same here
- */
- return -1;
- }
- if (a->nameAssigner == NULL && b->nameAssigner != NULL)
- return -1;
- if (a->nameAssigner != NULL && b->nameAssigner == NULL)
- return 1;
- /* If we get here then both have nameAssigner set, or both unset */
- if (a->nameAssigner != NULL) {
- res = ASN1_STRING_cmp(a->nameAssigner, b->nameAssigner);
- if (res != 0)
- return res;
- }
- /*
- * partyName is required, so these should never be NULL. We treat it in
- * the same way as the a == NULL || b == NULL case above
- */
- if (a->partyName == NULL || b->partyName == NULL)
- return -1;
-
- return ASN1_STRING_cmp(a->partyName, b->partyName);
-}
-
-/* Returns 0 if they are equal, != 0 otherwise. */
-int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b)
-{
- int result = -1;
-
- if (!a || !b || a->type != b->type)
- return -1;
- switch (a->type) {
- case GEN_X400:
- result = ASN1_STRING_cmp(a->d.x400Address, b->d.x400Address);
- break;
-
- case GEN_EDIPARTY:
- result = edipartyname_cmp(a->d.ediPartyName, b->d.ediPartyName);
- break;
-
- case GEN_OTHERNAME:
- result = OTHERNAME_cmp(a->d.otherName, b->d.otherName);
- break;
-
- case GEN_EMAIL:
- case GEN_DNS:
- case GEN_URI:
- result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5);
- break;
-
- case GEN_DIRNAME:
- result = X509_NAME_cmp(a->d.dirn, b->d.dirn);
- break;
-
- case GEN_IPADD:
- result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip);
- break;
-
- case GEN_RID:
- result = OBJ_cmp(a->d.rid, b->d.rid);
- break;
- }
- return result;
-}
-
-/* Returns 0 if they are equal, != 0 otherwise. */
-int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b)
-{
- int result = -1;
-
- if (!a || !b)
- return -1;
- /* Check their type first. */
- if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0)
- return result;
- /* Check the value. */
- result = ASN1_TYPE_cmp(a->value, b->value);
- return result;
-}
-
-void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
-{
- switch (type) {
- case GEN_X400:
- a->d.x400Address = value;
- break;
-
- case GEN_EDIPARTY:
- a->d.ediPartyName = value;
- break;
-
- case GEN_OTHERNAME:
- a->d.otherName = value;
- break;
-
- case GEN_EMAIL:
- case GEN_DNS:
- case GEN_URI:
- a->d.ia5 = value;
- break;
-
- case GEN_DIRNAME:
- a->d.dirn = value;
- break;
-
- case GEN_IPADD:
- a->d.ip = value;
- break;
-
- case GEN_RID:
- a->d.rid = value;
- break;
- }
- a->type = type;
-}
-
-void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype)
-{
- if (ptype)
- *ptype = a->type;
- switch (a->type) {
- case GEN_X400:
- return a->d.x400Address;
-
- case GEN_EDIPARTY:
- return a->d.ediPartyName;
-
- case GEN_OTHERNAME:
- return a->d.otherName;
-
- case GEN_EMAIL:
- case GEN_DNS:
- case GEN_URI:
- return a->d.ia5;
-
- case GEN_DIRNAME:
- return a->d.dirn;
-
- case GEN_IPADD:
- return a->d.ip;
-
- case GEN_RID:
- return a->d.rid;
-
- default:
- return NULL;
- }
-}
-
-int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
- ASN1_OBJECT *oid, ASN1_TYPE *value)
-{
- OTHERNAME *oth;
- oth = OTHERNAME_new();
- if (oth == NULL)
- return 0;
- ASN1_TYPE_free(oth->value);
- oth->type_id = oid;
- oth->value = value;
- GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
- return 1;
-}
-
-int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen,
- ASN1_OBJECT **poid, ASN1_TYPE **pvalue)
-{
- if (gen->type != GEN_OTHERNAME)
- return 0;
- if (poid)
- *poid = gen->d.otherName->type_id;
- if (pvalue)
- *pvalue = gen->d.otherName->value;
- return 1;
-}
diff --git a/crypto/x509v3/v3_ia5.c b/crypto/x509v3/v3_ia5.c
deleted file mode 100644
index c1170d46161e..000000000000
--- a/crypto/x509v3/v3_ia5.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/asn1.h>
-#include <openssl/conf.h>
-#include <openssl/x509v3.h>
-#include "ext_dat.h"
-
-const X509V3_EXT_METHOD v3_ns_ia5_list[8] = {
- EXT_IA5STRING(NID_netscape_base_url),
- EXT_IA5STRING(NID_netscape_revocation_url),
- EXT_IA5STRING(NID_netscape_ca_revocation_url),
- EXT_IA5STRING(NID_netscape_renewal_url),
- EXT_IA5STRING(NID_netscape_ca_policy_url),
- EXT_IA5STRING(NID_netscape_ssl_server_name),
- EXT_IA5STRING(NID_netscape_comment),
- EXT_END
-};
-
-char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5)
-{
- char *tmp;
-
- if (!ia5 || !ia5->length)
- return NULL;
- if ((tmp = OPENSSL_malloc(ia5->length + 1)) == NULL) {
- X509V3err(X509V3_F_I2S_ASN1_IA5STRING, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- memcpy(tmp, ia5->data, ia5->length);
- tmp[ia5->length] = 0;
- return tmp;
-}
-
-ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, const char *str)
-{
- ASN1_IA5STRING *ia5;
- if (!str) {
- X509V3err(X509V3_F_S2I_ASN1_IA5STRING,
- X509V3_R_INVALID_NULL_ARGUMENT);
- return NULL;
- }
- if ((ia5 = ASN1_IA5STRING_new()) == NULL)
- goto err;
- if (!ASN1_STRING_set((ASN1_STRING *)ia5, str, strlen(str))) {
- ASN1_IA5STRING_free(ia5);
- return NULL;
- }
-#ifdef CHARSET_EBCDIC
- ebcdic2ascii(ia5->data, ia5->data, ia5->length);
-#endif /* CHARSET_EBCDIC */
- return ia5;
- err:
- X509V3err(X509V3_F_S2I_ASN1_IA5STRING, ERR_R_MALLOC_FAILURE);
- return NULL;
-}
diff --git a/crypto/x509v3/v3_info.c b/crypto/x509v3/v3_info.c
deleted file mode 100644
index 7af9e23ae8c9..000000000000
--- a/crypto/x509v3/v3_info.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/conf.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-#include <openssl/x509v3.h>
-#include "ext_dat.h"
-
-static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
- *method, AUTHORITY_INFO_ACCESS
- *ainfo, STACK_OF(CONF_VALUE)
- *ret);
-static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
- *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE)
- *nval);
-
-const X509V3_EXT_METHOD v3_info = { NID_info_access, X509V3_EXT_MULTILINE,
- ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
- 0, 0, 0, 0,
- 0, 0,
- (X509V3_EXT_I2V) i2v_AUTHORITY_INFO_ACCESS,
- (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS,
- 0, 0,
- NULL
-};
-
-const X509V3_EXT_METHOD v3_sinfo = { NID_sinfo_access, X509V3_EXT_MULTILINE,
- ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
- 0, 0, 0, 0,
- 0, 0,
- (X509V3_EXT_I2V) i2v_AUTHORITY_INFO_ACCESS,
- (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS,
- 0, 0,
- NULL
-};
-
-ASN1_SEQUENCE(ACCESS_DESCRIPTION) = {
- ASN1_SIMPLE(ACCESS_DESCRIPTION, method, ASN1_OBJECT),
- ASN1_SIMPLE(ACCESS_DESCRIPTION, location, GENERAL_NAME)
-} ASN1_SEQUENCE_END(ACCESS_DESCRIPTION)
-
-IMPLEMENT_ASN1_FUNCTIONS(ACCESS_DESCRIPTION)
-
-ASN1_ITEM_TEMPLATE(AUTHORITY_INFO_ACCESS) =
- ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, ACCESS_DESCRIPTION)
-ASN1_ITEM_TEMPLATE_END(AUTHORITY_INFO_ACCESS)
-
-IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS)
-
-static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(
- X509V3_EXT_METHOD *method, AUTHORITY_INFO_ACCESS *ainfo,
- STACK_OF(CONF_VALUE) *ret)
-{
- ACCESS_DESCRIPTION *desc;
- int i, nlen;
- char objtmp[80], *ntmp;
- CONF_VALUE *vtmp;
- STACK_OF(CONF_VALUE) *tret = ret;
-
- for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ainfo); i++) {
- STACK_OF(CONF_VALUE) *tmp;
-
- desc = sk_ACCESS_DESCRIPTION_value(ainfo, i);
- tmp = i2v_GENERAL_NAME(method, desc->location, tret);
- if (tmp == NULL)
- goto err;
- tret = tmp;
- vtmp = sk_CONF_VALUE_value(tret, i);
- i2t_ASN1_OBJECT(objtmp, sizeof(objtmp), desc->method);
- nlen = strlen(objtmp) + 3 + strlen(vtmp->name) + 1;
- ntmp = OPENSSL_malloc(nlen);
- if (ntmp == NULL)
- goto err;
- BIO_snprintf(ntmp, nlen, "%s - %s", objtmp, vtmp->name);
- OPENSSL_free(vtmp->name);
- vtmp->name = ntmp;
- }
- if (ret == NULL && tret == NULL)
- return sk_CONF_VALUE_new_null();
-
- return tret;
- err:
- X509V3err(X509V3_F_I2V_AUTHORITY_INFO_ACCESS, ERR_R_MALLOC_FAILURE);
- if (ret == NULL && tret != NULL)
- sk_CONF_VALUE_pop_free(tret, X509V3_conf_free);
- return NULL;
-}
-
-static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
- *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE)
- *nval)
-{
- AUTHORITY_INFO_ACCESS *ainfo = NULL;
- CONF_VALUE *cnf, ctmp;
- ACCESS_DESCRIPTION *acc;
- int i, objlen;
- const int num = sk_CONF_VALUE_num(nval);
- char *objtmp, *ptmp;
-
- if ((ainfo = sk_ACCESS_DESCRIPTION_new_reserve(NULL, num)) == NULL) {
- X509V3err(X509V3_F_V2I_AUTHORITY_INFO_ACCESS, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- for (i = 0; i < num; i++) {
- cnf = sk_CONF_VALUE_value(nval, i);
- if ((acc = ACCESS_DESCRIPTION_new()) == NULL) {
- X509V3err(X509V3_F_V2I_AUTHORITY_INFO_ACCESS,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
- sk_ACCESS_DESCRIPTION_push(ainfo, acc); /* Cannot fail due to reserve */
- ptmp = strchr(cnf->name, ';');
- if (!ptmp) {
- X509V3err(X509V3_F_V2I_AUTHORITY_INFO_ACCESS,
- X509V3_R_INVALID_SYNTAX);
- goto err;
- }
- objlen = ptmp - cnf->name;
- ctmp.name = ptmp + 1;
- ctmp.value = cnf->value;
- if (!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0))
- goto err;
- if ((objtmp = OPENSSL_strndup(cnf->name, objlen)) == NULL) {
- X509V3err(X509V3_F_V2I_AUTHORITY_INFO_ACCESS,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
- acc->method = OBJ_txt2obj(objtmp, 0);
- if (!acc->method) {
- X509V3err(X509V3_F_V2I_AUTHORITY_INFO_ACCESS,
- X509V3_R_BAD_OBJECT);
- ERR_add_error_data(2, "value=", objtmp);
- OPENSSL_free(objtmp);
- goto err;
- }
- OPENSSL_free(objtmp);
-
- }
- return ainfo;
- err:
- sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free);
- return NULL;
-}
-
-int i2a_ACCESS_DESCRIPTION(BIO *bp, const ACCESS_DESCRIPTION *a)
-{
- i2a_ASN1_OBJECT(bp, a->method);
- return 2;
-}
diff --git a/crypto/x509v3/v3_int.c b/crypto/x509v3/v3_int.c
deleted file mode 100644
index 690c90e8f96e..000000000000
--- a/crypto/x509v3/v3_int.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/x509v3.h>
-#include "ext_dat.h"
-
-const X509V3_EXT_METHOD v3_crl_num = {
- NID_crl_number, 0, ASN1_ITEM_ref(ASN1_INTEGER),
- 0, 0, 0, 0,
- (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
- 0,
- 0, 0, 0, 0, NULL
-};
-
-const X509V3_EXT_METHOD v3_delta_crl = {
- NID_delta_crl, 0, ASN1_ITEM_ref(ASN1_INTEGER),
- 0, 0, 0, 0,
- (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
- 0,
- 0, 0, 0, 0, NULL
-};
-
-static void *s2i_asn1_int(X509V3_EXT_METHOD *meth, X509V3_CTX *ctx,
- const char *value)
-{
- return s2i_ASN1_INTEGER(meth, value);
-}
-
-const X509V3_EXT_METHOD v3_inhibit_anyp = {
- NID_inhibit_any_policy, 0, ASN1_ITEM_ref(ASN1_INTEGER),
- 0, 0, 0, 0,
- (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
- (X509V3_EXT_S2I)s2i_asn1_int,
- 0, 0, 0, 0, NULL
-};
diff --git a/crypto/x509v3/v3_lib.c b/crypto/x509v3/v3_lib.c
deleted file mode 100644
index ea88ff2acd22..000000000000
--- a/crypto/x509v3/v3_lib.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/* X509 v3 extension utilities */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/conf.h>
-#include <openssl/x509v3.h>
-
-#include "ext_dat.h"
-
-static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL;
-
-static int ext_cmp(const X509V3_EXT_METHOD *const *a,
- const X509V3_EXT_METHOD *const *b);
-static void ext_list_free(X509V3_EXT_METHOD *ext);
-
-int X509V3_EXT_add(X509V3_EXT_METHOD *ext)
-{
- if (ext_list == NULL
- && (ext_list = sk_X509V3_EXT_METHOD_new(ext_cmp)) == NULL) {
- X509V3err(X509V3_F_X509V3_EXT_ADD, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) {
- X509V3err(X509V3_F_X509V3_EXT_ADD, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- return 1;
-}
-
-static int ext_cmp(const X509V3_EXT_METHOD *const *a,
- const X509V3_EXT_METHOD *const *b)
-{
- return ((*a)->ext_nid - (*b)->ext_nid);
-}
-
-DECLARE_OBJ_BSEARCH_CMP_FN(const X509V3_EXT_METHOD *,
- const X509V3_EXT_METHOD *, ext);
-IMPLEMENT_OBJ_BSEARCH_CMP_FN(const X509V3_EXT_METHOD *,
- const X509V3_EXT_METHOD *, ext);
-
-#include "standard_exts.h"
-
-const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid)
-{
- X509V3_EXT_METHOD tmp;
- const X509V3_EXT_METHOD *t = &tmp, *const *ret;
- int idx;
-
- if (nid < 0)
- return NULL;
- tmp.ext_nid = nid;
- ret = OBJ_bsearch_ext(&t, standard_exts, STANDARD_EXTENSION_COUNT);
- if (ret)
- return *ret;
- if (!ext_list)
- return NULL;
- idx = sk_X509V3_EXT_METHOD_find(ext_list, &tmp);
- return sk_X509V3_EXT_METHOD_value(ext_list, idx);
-}
-
-const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext)
-{
- int nid;
- if ((nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext))) == NID_undef)
- return NULL;
- return X509V3_EXT_get_nid(nid);
-}
-
-int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist)
-{
- for (; extlist->ext_nid != -1; extlist++)
- if (!X509V3_EXT_add(extlist))
- return 0;
- return 1;
-}
-
-int X509V3_EXT_add_alias(int nid_to, int nid_from)
-{
- const X509V3_EXT_METHOD *ext;
- X509V3_EXT_METHOD *tmpext;
-
- if ((ext = X509V3_EXT_get_nid(nid_from)) == NULL) {
- X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS, X509V3_R_EXTENSION_NOT_FOUND);
- return 0;
- }
- if ((tmpext = OPENSSL_malloc(sizeof(*tmpext))) == NULL) {
- X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- *tmpext = *ext;
- tmpext->ext_nid = nid_to;
- tmpext->ext_flags |= X509V3_EXT_DYNAMIC;
- return X509V3_EXT_add(tmpext);
-}
-
-void X509V3_EXT_cleanup(void)
-{
- sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free);
- ext_list = NULL;
-}
-
-static void ext_list_free(X509V3_EXT_METHOD *ext)
-{
- if (ext->ext_flags & X509V3_EXT_DYNAMIC)
- OPENSSL_free(ext);
-}
-
-/*
- * Legacy function: we don't need to add standard extensions any more because
- * they are now kept in ext_dat.h.
- */
-
-int X509V3_add_standard_extensions(void)
-{
- return 1;
-}
-
-/* Return an extension internal structure */
-
-void *X509V3_EXT_d2i(X509_EXTENSION *ext)
-{
- const X509V3_EXT_METHOD *method;
- const unsigned char *p;
- ASN1_STRING *extvalue;
- int extlen;
-
- if ((method = X509V3_EXT_get(ext)) == NULL)
- return NULL;
- extvalue = X509_EXTENSION_get_data(ext);
- p = ASN1_STRING_get0_data(extvalue);
- extlen = ASN1_STRING_length(extvalue);
- if (method->it)
- return ASN1_item_d2i(NULL, &p, extlen, ASN1_ITEM_ptr(method->it));
- return method->d2i(NULL, &p, extlen);
-}
-
-/*-
- * Get critical flag and decoded version of extension from a NID.
- * The "idx" variable returns the last found extension and can
- * be used to retrieve multiple extensions of the same NID.
- * However multiple extensions with the same NID is usually
- * due to a badly encoded certificate so if idx is NULL we
- * choke if multiple extensions exist.
- * The "crit" variable is set to the critical value.
- * The return value is the decoded extension or NULL on
- * error. The actual error can have several different causes,
- * the value of *crit reflects the cause:
- * >= 0, extension found but not decoded (reflects critical value).
- * -1 extension not found.
- * -2 extension occurs more than once.
- */
-
-void *X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *x, int nid, int *crit,
- int *idx)
-{
- int lastpos, i;
- X509_EXTENSION *ex, *found_ex = NULL;
-
- if (!x) {
- if (idx)
- *idx = -1;
- if (crit)
- *crit = -1;
- return NULL;
- }
- if (idx)
- lastpos = *idx + 1;
- else
- lastpos = 0;
- if (lastpos < 0)
- lastpos = 0;
- for (i = lastpos; i < sk_X509_EXTENSION_num(x); i++) {
- ex = sk_X509_EXTENSION_value(x, i);
- if (OBJ_obj2nid(X509_EXTENSION_get_object(ex)) == nid) {
- if (idx) {
- *idx = i;
- found_ex = ex;
- break;
- } else if (found_ex) {
- /* Found more than one */
- if (crit)
- *crit = -2;
- return NULL;
- }
- found_ex = ex;
- }
- }
- if (found_ex) {
- /* Found it */
- if (crit)
- *crit = X509_EXTENSION_get_critical(found_ex);
- return X509V3_EXT_d2i(found_ex);
- }
-
- /* Extension not found */
- if (idx)
- *idx = -1;
- if (crit)
- *crit = -1;
- return NULL;
-}
-
-/*
- * This function is a general extension append, replace and delete utility.
- * The precise operation is governed by the 'flags' value. The 'crit' and
- * 'value' arguments (if relevant) are the extensions internal structure.
- */
-
-int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
- int crit, unsigned long flags)
-{
- int errcode, extidx = -1;
- X509_EXTENSION *ext = NULL, *extmp;
- STACK_OF(X509_EXTENSION) *ret = NULL;
- unsigned long ext_op = flags & X509V3_ADD_OP_MASK;
-
- /*
- * If appending we don't care if it exists, otherwise look for existing
- * extension.
- */
- if (ext_op != X509V3_ADD_APPEND)
- extidx = X509v3_get_ext_by_NID(*x, nid, -1);
-
- /* See if extension exists */
- if (extidx >= 0) {
- /* If keep existing, nothing to do */
- if (ext_op == X509V3_ADD_KEEP_EXISTING)
- return 1;
- /* If default then its an error */
- if (ext_op == X509V3_ADD_DEFAULT) {
- errcode = X509V3_R_EXTENSION_EXISTS;
- goto err;
- }
- /* If delete, just delete it */
- if (ext_op == X509V3_ADD_DELETE) {
- extmp = sk_X509_EXTENSION_delete(*x, extidx);
- if (extmp == NULL)
- return -1;
- X509_EXTENSION_free(extmp);
- return 1;
- }
- } else {
- /*
- * If replace existing or delete, error since extension must exist
- */
- if ((ext_op == X509V3_ADD_REPLACE_EXISTING) ||
- (ext_op == X509V3_ADD_DELETE)) {
- errcode = X509V3_R_EXTENSION_NOT_FOUND;
- goto err;
- }
- }
-
- /*
- * If we get this far then we have to create an extension: could have
- * some flags for alternative encoding schemes...
- */
-
- ext = X509V3_EXT_i2d(nid, crit, value);
-
- if (!ext) {
- X509V3err(X509V3_F_X509V3_ADD1_I2D,
- X509V3_R_ERROR_CREATING_EXTENSION);
- return 0;
- }
-
- /* If extension exists replace it.. */
- if (extidx >= 0) {
- extmp = sk_X509_EXTENSION_value(*x, extidx);
- X509_EXTENSION_free(extmp);
- if (!sk_X509_EXTENSION_set(*x, extidx, ext))
- return -1;
- return 1;
- }
-
- ret = *x;
- if (*x == NULL
- && (ret = sk_X509_EXTENSION_new_null()) == NULL)
- goto m_fail;
- if (!sk_X509_EXTENSION_push(ret, ext))
- goto m_fail;
-
- *x = ret;
- return 1;
-
- m_fail:
- /* X509V3err(X509V3_F_X509V3_ADD1_I2D, ERR_R_MALLOC_FAILURE); */
- if (ret != *x)
- sk_X509_EXTENSION_free(ret);
- X509_EXTENSION_free(ext);
- return -1;
-
- err:
- if (!(flags & X509V3_ADD_SILENT))
- X509V3err(X509V3_F_X509V3_ADD1_I2D, errcode);
- return 0;
-}
diff --git a/crypto/x509v3/v3_ncons.c b/crypto/x509v3/v3_ncons.c
deleted file mode 100644
index 60cb4ceaa8f8..000000000000
--- a/crypto/x509v3/v3_ncons.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * Copyright 2003-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "internal/cryptlib.h"
-#include "internal/numbers.h"
-#include <stdio.h>
-#include "crypto/asn1.h"
-#include <openssl/asn1t.h>
-#include <openssl/conf.h>
-#include <openssl/x509v3.h>
-
-#include "crypto/x509.h"
-#include "ext_dat.h"
-
-static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval);
-static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a,
- BIO *bp, int ind);
-static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method,
- STACK_OF(GENERAL_SUBTREE) *trees, BIO *bp,
- int ind, const char *name);
-static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip);
-
-static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc);
-static int nc_match_single(GENERAL_NAME *sub, GENERAL_NAME *gen);
-static int nc_dn(X509_NAME *sub, X509_NAME *nm);
-static int nc_dns(ASN1_IA5STRING *sub, ASN1_IA5STRING *dns);
-static int nc_email(ASN1_IA5STRING *sub, ASN1_IA5STRING *eml);
-static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base);
-static int nc_ip(ASN1_OCTET_STRING *ip, ASN1_OCTET_STRING *base);
-
-const X509V3_EXT_METHOD v3_name_constraints = {
- NID_name_constraints, 0,
- ASN1_ITEM_ref(NAME_CONSTRAINTS),
- 0, 0, 0, 0,
- 0, 0,
- 0, v2i_NAME_CONSTRAINTS,
- i2r_NAME_CONSTRAINTS, 0,
- NULL
-};
-
-ASN1_SEQUENCE(GENERAL_SUBTREE) = {
- ASN1_SIMPLE(GENERAL_SUBTREE, base, GENERAL_NAME),
- ASN1_IMP_OPT(GENERAL_SUBTREE, minimum, ASN1_INTEGER, 0),
- ASN1_IMP_OPT(GENERAL_SUBTREE, maximum, ASN1_INTEGER, 1)
-} ASN1_SEQUENCE_END(GENERAL_SUBTREE)
-
-ASN1_SEQUENCE(NAME_CONSTRAINTS) = {
- ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, permittedSubtrees,
- GENERAL_SUBTREE, 0),
- ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, excludedSubtrees,
- GENERAL_SUBTREE, 1),
-} ASN1_SEQUENCE_END(NAME_CONSTRAINTS)
-
-
-IMPLEMENT_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
-IMPLEMENT_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
-
-
-#define IA5_OFFSET_LEN(ia5base, offset) \
- ((ia5base)->length - ((unsigned char *)(offset) - (ia5base)->data))
-
-/* Like memchr but for ASN1_IA5STRING. Additionally you can specify the
- * starting point to search from
- */
-# define ia5memchr(str, start, c) memchr(start, c, IA5_OFFSET_LEN(str, start))
-
-/* Like memrrchr but for ASN1_IA5STRING */
-static char *ia5memrchr(ASN1_IA5STRING *str, int c)
-{
- int i;
-
- for (i = str->length; i > 0 && str->data[i - 1] != c; i--);
-
- if (i == 0)
- return NULL;
-
- return (char *)&str->data[i - 1];
-}
-
-/*
- * We cannot use strncasecmp here because that applies locale specific rules. It
- * also doesn't work with ASN1_STRINGs that may have embedded NUL characters.
- * For example in Turkish 'I' is not the uppercase character for 'i'. We need to
- * do a simple ASCII case comparison ignoring the locale (that is why we use
- * numeric constants below).
- */
-static int ia5ncasecmp(const char *s1, const char *s2, size_t n)
-{
- for (; n > 0; n--, s1++, s2++) {
- if (*s1 != *s2) {
- unsigned char c1 = (unsigned char)*s1, c2 = (unsigned char)*s2;
-
- /* Convert to lower case */
- if (c1 >= 0x41 /* A */ && c1 <= 0x5A /* Z */)
- c1 += 0x20;
- if (c2 >= 0x41 /* A */ && c2 <= 0x5A /* Z */)
- c2 += 0x20;
-
- if (c1 == c2)
- continue;
-
- if (c1 < c2)
- return -1;
-
- /* c1 > c2 */
- return 1;
- }
- }
-
- return 0;
-}
-
-static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
-{
- int i;
- CONF_VALUE tval, *val;
- STACK_OF(GENERAL_SUBTREE) **ptree = NULL;
- NAME_CONSTRAINTS *ncons = NULL;
- GENERAL_SUBTREE *sub = NULL;
-
- ncons = NAME_CONSTRAINTS_new();
- if (ncons == NULL)
- goto memerr;
- for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
- val = sk_CONF_VALUE_value(nval, i);
- if (strncmp(val->name, "permitted", 9) == 0 && val->name[9]) {
- ptree = &ncons->permittedSubtrees;
- tval.name = val->name + 10;
- } else if (strncmp(val->name, "excluded", 8) == 0 && val->name[8]) {
- ptree = &ncons->excludedSubtrees;
- tval.name = val->name + 9;
- } else {
- X509V3err(X509V3_F_V2I_NAME_CONSTRAINTS, X509V3_R_INVALID_SYNTAX);
- goto err;
- }
- tval.value = val->value;
- sub = GENERAL_SUBTREE_new();
- if (sub == NULL)
- goto memerr;
- if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1))
- goto err;
- if (*ptree == NULL)
- *ptree = sk_GENERAL_SUBTREE_new_null();
- if (*ptree == NULL || !sk_GENERAL_SUBTREE_push(*ptree, sub))
- goto memerr;
- sub = NULL;
- }
-
- return ncons;
-
- memerr:
- X509V3err(X509V3_F_V2I_NAME_CONSTRAINTS, ERR_R_MALLOC_FAILURE);
- err:
- NAME_CONSTRAINTS_free(ncons);
- GENERAL_SUBTREE_free(sub);
-
- return NULL;
-}
-
-static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a,
- BIO *bp, int ind)
-{
- NAME_CONSTRAINTS *ncons = a;
- do_i2r_name_constraints(method, ncons->permittedSubtrees,
- bp, ind, "Permitted");
- do_i2r_name_constraints(method, ncons->excludedSubtrees,
- bp, ind, "Excluded");
- return 1;
-}
-
-static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method,
- STACK_OF(GENERAL_SUBTREE) *trees,
- BIO *bp, int ind, const char *name)
-{
- GENERAL_SUBTREE *tree;
- int i;
- if (sk_GENERAL_SUBTREE_num(trees) > 0)
- BIO_printf(bp, "%*s%s:\n", ind, "", name);
- for (i = 0; i < sk_GENERAL_SUBTREE_num(trees); i++) {
- tree = sk_GENERAL_SUBTREE_value(trees, i);
- BIO_printf(bp, "%*s", ind + 2, "");
- if (tree->base->type == GEN_IPADD)
- print_nc_ipadd(bp, tree->base->d.ip);
- else
- GENERAL_NAME_print(bp, tree->base);
- BIO_puts(bp, "\n");
- }
- return 1;
-}
-
-static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip)
-{
- int i, len;
- unsigned char *p;
- p = ip->data;
- len = ip->length;
- BIO_puts(bp, "IP:");
- if (len == 8) {
- BIO_printf(bp, "%d.%d.%d.%d/%d.%d.%d.%d",
- p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
- } else if (len == 32) {
- for (i = 0; i < 16; i++) {
- BIO_printf(bp, "%X", p[0] << 8 | p[1]);
- p += 2;
- if (i == 7)
- BIO_puts(bp, "/");
- else if (i != 15)
- BIO_puts(bp, ":");
- }
- } else
- BIO_printf(bp, "IP Address:<invalid>");
- return 1;
-}
-
-#define NAME_CHECK_MAX (1 << 20)
-
-static int add_lengths(int *out, int a, int b)
-{
- /* sk_FOO_num(NULL) returns -1 but is effectively 0 when iterating. */
- if (a < 0)
- a = 0;
- if (b < 0)
- b = 0;
-
- if (a > INT_MAX - b)
- return 0;
- *out = a + b;
- return 1;
-}
-
-/*-
- * Check a certificate conforms to a specified set of constraints.
- * Return values:
- * X509_V_OK: All constraints obeyed.
- * X509_V_ERR_PERMITTED_VIOLATION: Permitted subtree violation.
- * X509_V_ERR_EXCLUDED_VIOLATION: Excluded subtree violation.
- * X509_V_ERR_SUBTREE_MINMAX: Min or max values present and matching type.
- * X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: Unsupported constraint type.
- * X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: bad unsupported constraint syntax.
- * X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: bad or unsupported syntax of name
- */
-
-int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc)
-{
- int r, i, name_count, constraint_count;
- X509_NAME *nm;
-
- nm = X509_get_subject_name(x);
-
- /*
- * Guard against certificates with an excessive number of names or
- * constraints causing a computationally expensive name constraints check.
- */
- if (!add_lengths(&name_count, X509_NAME_entry_count(nm),
- sk_GENERAL_NAME_num(x->altname))
- || !add_lengths(&constraint_count,
- sk_GENERAL_SUBTREE_num(nc->permittedSubtrees),
- sk_GENERAL_SUBTREE_num(nc->excludedSubtrees))
- || (name_count > 0 && constraint_count > NAME_CHECK_MAX / name_count))
- return X509_V_ERR_UNSPECIFIED;
-
- if (X509_NAME_entry_count(nm) > 0) {
- GENERAL_NAME gntmp;
- gntmp.type = GEN_DIRNAME;
- gntmp.d.directoryName = nm;
-
- r = nc_match(&gntmp, nc);
-
- if (r != X509_V_OK)
- return r;
-
- gntmp.type = GEN_EMAIL;
-
- /* Process any email address attributes in subject name */
-
- for (i = -1;;) {
- const X509_NAME_ENTRY *ne;
-
- i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i);
- if (i == -1)
- break;
- ne = X509_NAME_get_entry(nm, i);
- gntmp.d.rfc822Name = X509_NAME_ENTRY_get_data(ne);
- if (gntmp.d.rfc822Name->type != V_ASN1_IA5STRING)
- return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
-
- r = nc_match(&gntmp, nc);
-
- if (r != X509_V_OK)
- return r;
- }
-
- }
-
- for (i = 0; i < sk_GENERAL_NAME_num(x->altname); i++) {
- GENERAL_NAME *gen = sk_GENERAL_NAME_value(x->altname, i);
- r = nc_match(gen, nc);
- if (r != X509_V_OK)
- return r;
- }
-
- return X509_V_OK;
-
-}
-
-static int cn2dnsid(ASN1_STRING *cn, unsigned char **dnsid, size_t *idlen)
-{
- int utf8_length;
- unsigned char *utf8_value;
- int i;
- int isdnsname = 0;
-
- /* Don't leave outputs uninitialized */
- *dnsid = NULL;
- *idlen = 0;
-
- /*-
- * Per RFC 6125, DNS-IDs representing internationalized domain names appear
- * in certificates in A-label encoded form:
- *
- * https://tools.ietf.org/html/rfc6125#section-6.4.2
- *
- * The same applies to CNs which are intended to represent DNS names.
- * However, while in the SAN DNS-IDs are IA5Strings, as CNs they may be
- * needlessly encoded in 16-bit Unicode. We perform a conversion to UTF-8
- * to ensure that we get an ASCII representation of any CNs that are
- * representable as ASCII, but just not encoded as ASCII. The UTF-8 form
- * may contain some non-ASCII octets, and that's fine, such CNs are not
- * valid legacy DNS names.
- *
- * Note, 'int' is the return type of ASN1_STRING_to_UTF8() so that's what
- * we must use for 'utf8_length'.
- */
- if ((utf8_length = ASN1_STRING_to_UTF8(&utf8_value, cn)) < 0)
- return X509_V_ERR_OUT_OF_MEM;
-
- /*
- * Some certificates have had names that include a *trailing* NUL byte.
- * Remove these harmless NUL characters. They would otherwise yield false
- * alarms with the following embedded NUL check.
- */
- while (utf8_length > 0 && utf8_value[utf8_length - 1] == '\0')
- --utf8_length;
-
- /* Reject *embedded* NULs */
- if (memchr(utf8_value, 0, utf8_length) != NULL) {
- OPENSSL_free(utf8_value);
- return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
- }
-
- /*
- * XXX: Deviation from strict DNS name syntax, also check names with '_'
- * Check DNS name syntax, any '-' or '.' must be internal,
- * and on either side of each '.' we can't have a '-' or '.'.
- *
- * If the name has just one label, we don't consider it a DNS name. This
- * means that "CN=sometld" cannot be precluded by DNS name constraints, but
- * that is not a problem.
- */
- for (i = 0; i < utf8_length; ++i) {
- unsigned char c = utf8_value[i];
-
- if ((c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z')
- || (c >= '0' && c <= '9')
- || c == '_')
- continue;
-
- /* Dot and hyphen cannot be first or last. */
- if (i > 0 && i < utf8_length - 1) {
- if (c == '-')
- continue;
- /*
- * Next to a dot the preceding and following characters must not be
- * another dot or a hyphen. Otherwise, record that the name is
- * plausible, since it has two or more labels.
- */
- if (c == '.'
- && utf8_value[i + 1] != '.'
- && utf8_value[i - 1] != '-'
- && utf8_value[i + 1] != '-') {
- isdnsname = 1;
- continue;
- }
- }
- isdnsname = 0;
- break;
- }
-
- if (isdnsname) {
- *dnsid = utf8_value;
- *idlen = (size_t)utf8_length;
- return X509_V_OK;
- }
- OPENSSL_free(utf8_value);
- return X509_V_OK;
-}
-
-/*
- * Check CN against DNS-ID name constraints.
- */
-int NAME_CONSTRAINTS_check_CN(X509 *x, NAME_CONSTRAINTS *nc)
-{
- int r, i;
- X509_NAME *nm = X509_get_subject_name(x);
- ASN1_STRING stmp;
- GENERAL_NAME gntmp;
-
- stmp.flags = 0;
- stmp.type = V_ASN1_IA5STRING;
- gntmp.type = GEN_DNS;
- gntmp.d.dNSName = &stmp;
-
- /* Process any commonName attributes in subject name */
-
- for (i = -1;;) {
- X509_NAME_ENTRY *ne;
- ASN1_STRING *cn;
- unsigned char *idval;
- size_t idlen;
-
- i = X509_NAME_get_index_by_NID(nm, NID_commonName, i);
- if (i == -1)
- break;
- ne = X509_NAME_get_entry(nm, i);
- cn = X509_NAME_ENTRY_get_data(ne);
-
- /* Only process attributes that look like host names */
- if ((r = cn2dnsid(cn, &idval, &idlen)) != X509_V_OK)
- return r;
- if (idlen == 0)
- continue;
-
- stmp.length = idlen;
- stmp.data = idval;
- r = nc_match(&gntmp, nc);
- OPENSSL_free(idval);
- if (r != X509_V_OK)
- return r;
- }
- return X509_V_OK;
-}
-
-static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc)
-{
- GENERAL_SUBTREE *sub;
- int i, r, match = 0;
-
- /*
- * Permitted subtrees: if any subtrees exist of matching the type at
- * least one subtree must match.
- */
-
- for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++) {
- sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i);
- if (gen->type != sub->base->type)
- continue;
- if (sub->minimum || sub->maximum)
- return X509_V_ERR_SUBTREE_MINMAX;
- /* If we already have a match don't bother trying any more */
- if (match == 2)
- continue;
- if (match == 0)
- match = 1;
- r = nc_match_single(gen, sub->base);
- if (r == X509_V_OK)
- match = 2;
- else if (r != X509_V_ERR_PERMITTED_VIOLATION)
- return r;
- }
-
- if (match == 1)
- return X509_V_ERR_PERMITTED_VIOLATION;
-
- /* Excluded subtrees: must not match any of these */
-
- for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++) {
- sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i);
- if (gen->type != sub->base->type)
- continue;
- if (sub->minimum || sub->maximum)
- return X509_V_ERR_SUBTREE_MINMAX;
-
- r = nc_match_single(gen, sub->base);
- if (r == X509_V_OK)
- return X509_V_ERR_EXCLUDED_VIOLATION;
- else if (r != X509_V_ERR_PERMITTED_VIOLATION)
- return r;
-
- }
-
- return X509_V_OK;
-
-}
-
-static int nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base)
-{
- switch (base->type) {
- case GEN_DIRNAME:
- return nc_dn(gen->d.directoryName, base->d.directoryName);
-
- case GEN_DNS:
- return nc_dns(gen->d.dNSName, base->d.dNSName);
-
- case GEN_EMAIL:
- return nc_email(gen->d.rfc822Name, base->d.rfc822Name);
-
- case GEN_URI:
- return nc_uri(gen->d.uniformResourceIdentifier,
- base->d.uniformResourceIdentifier);
-
- case GEN_IPADD:
- return nc_ip(gen->d.iPAddress, base->d.iPAddress);
-
- default:
- return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE;
- }
-
-}
-
-/*
- * directoryName name constraint matching. The canonical encoding of
- * X509_NAME makes this comparison easy. It is matched if the subtree is a
- * subset of the name.
- */
-
-static int nc_dn(X509_NAME *nm, X509_NAME *base)
-{
- /* Ensure canonical encodings are up to date. */
- if (nm->modified && i2d_X509_NAME(nm, NULL) < 0)
- return X509_V_ERR_OUT_OF_MEM;
- if (base->modified && i2d_X509_NAME(base, NULL) < 0)
- return X509_V_ERR_OUT_OF_MEM;
- if (base->canon_enclen > nm->canon_enclen)
- return X509_V_ERR_PERMITTED_VIOLATION;
- if (memcmp(base->canon_enc, nm->canon_enc, base->canon_enclen))
- return X509_V_ERR_PERMITTED_VIOLATION;
- return X509_V_OK;
-}
-
-static int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base)
-{
- char *baseptr = (char *)base->data;
- char *dnsptr = (char *)dns->data;
-
- /* Empty matches everything */
- if (base->length == 0)
- return X509_V_OK;
-
- if (dns->length < base->length)
- return X509_V_ERR_PERMITTED_VIOLATION;
-
- /*
- * Otherwise can add zero or more components on the left so compare RHS
- * and if dns is longer and expect '.' as preceding character.
- */
- if (dns->length > base->length) {
- dnsptr += dns->length - base->length;
- if (*baseptr != '.' && dnsptr[-1] != '.')
- return X509_V_ERR_PERMITTED_VIOLATION;
- }
-
- if (ia5ncasecmp(baseptr, dnsptr, base->length))
- return X509_V_ERR_PERMITTED_VIOLATION;
-
- return X509_V_OK;
-
-}
-
-static int nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base)
-{
- const char *baseptr = (char *)base->data;
- const char *emlptr = (char *)eml->data;
- const char *baseat = ia5memrchr(base, '@');
- const char *emlat = ia5memrchr(eml, '@');
- size_t basehostlen, emlhostlen;
-
- if (!emlat)
- return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
- /* Special case: initial '.' is RHS match */
- if (!baseat && base->length > 0 && (*baseptr == '.')) {
- if (eml->length > base->length) {
- emlptr += eml->length - base->length;
- if (ia5ncasecmp(baseptr, emlptr, base->length) == 0)
- return X509_V_OK;
- }
- return X509_V_ERR_PERMITTED_VIOLATION;
- }
-
- /* If we have anything before '@' match local part */
-
- if (baseat) {
- if (baseat != baseptr) {
- if ((baseat - baseptr) != (emlat - emlptr))
- return X509_V_ERR_PERMITTED_VIOLATION;
- if (memchr(baseptr, 0, baseat - baseptr) ||
- memchr(emlptr, 0, emlat - emlptr))
- return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
- /* Case sensitive match of local part */
- if (strncmp(baseptr, emlptr, emlat - emlptr))
- return X509_V_ERR_PERMITTED_VIOLATION;
- }
- /* Position base after '@' */
- baseptr = baseat + 1;
- }
- emlptr = emlat + 1;
- basehostlen = IA5_OFFSET_LEN(base, baseptr);
- emlhostlen = IA5_OFFSET_LEN(eml, emlptr);
- /* Just have hostname left to match: case insensitive */
- if (basehostlen != emlhostlen || ia5ncasecmp(baseptr, emlptr, emlhostlen))
- return X509_V_ERR_PERMITTED_VIOLATION;
-
- return X509_V_OK;
-
-}
-
-static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base)
-{
- const char *baseptr = (char *)base->data;
- const char *hostptr = (char *)uri->data;
- const char *p = ia5memchr(uri, (char *)uri->data, ':');
- int hostlen;
-
- /* Check for foo:// and skip past it */
- if (p == NULL
- || IA5_OFFSET_LEN(uri, p) < 3
- || p[1] != '/'
- || p[2] != '/')
- return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
- hostptr = p + 3;
-
- /* Determine length of hostname part of URI */
-
- /* Look for a port indicator as end of hostname first */
-
- p = ia5memchr(uri, hostptr, ':');
- /* Otherwise look for trailing slash */
- if (p == NULL)
- p = ia5memchr(uri, hostptr, '/');
-
- if (p == NULL)
- hostlen = IA5_OFFSET_LEN(uri, hostptr);
- else
- hostlen = p - hostptr;
-
- if (hostlen == 0)
- return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
-
- /* Special case: initial '.' is RHS match */
- if (base->length > 0 && *baseptr == '.') {
- if (hostlen > base->length) {
- p = hostptr + hostlen - base->length;
- if (ia5ncasecmp(p, baseptr, base->length) == 0)
- return X509_V_OK;
- }
- return X509_V_ERR_PERMITTED_VIOLATION;
- }
-
- if ((base->length != (int)hostlen)
- || ia5ncasecmp(hostptr, baseptr, hostlen))
- return X509_V_ERR_PERMITTED_VIOLATION;
-
- return X509_V_OK;
-
-}
-
-static int nc_ip(ASN1_OCTET_STRING *ip, ASN1_OCTET_STRING *base)
-{
- int hostlen, baselen, i;
- unsigned char *hostptr, *baseptr, *maskptr;
- hostptr = ip->data;
- hostlen = ip->length;
- baseptr = base->data;
- baselen = base->length;
-
- /* Invalid if not IPv4 or IPv6 */
- if (!((hostlen == 4) || (hostlen == 16)))
- return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
- if (!((baselen == 8) || (baselen == 32)))
- return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
-
- /* Do not match IPv4 with IPv6 */
- if (hostlen * 2 != baselen)
- return X509_V_ERR_PERMITTED_VIOLATION;
-
- maskptr = base->data + hostlen;
-
- /* Considering possible not aligned base ipAddress */
- /* Not checking for wrong mask definition: i.e.: 255.0.255.0 */
- for (i = 0; i < hostlen; i++)
- if ((hostptr[i] & maskptr[i]) != (baseptr[i] & maskptr[i]))
- return X509_V_ERR_PERMITTED_VIOLATION;
-
- return X509_V_OK;
-
-}
diff --git a/crypto/x509v3/v3_pci.c b/crypto/x509v3/v3_pci.c
deleted file mode 100644
index 532d4e192fec..000000000000
--- a/crypto/x509v3/v3_pci.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * This file is dual-licensed and is also available under the following
- * terms:
- *
- * Copyright (c) 2004 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/conf.h>
-#include <openssl/x509v3.h>
-#include "ext_dat.h"
-
-static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *ext,
- BIO *out, int indent);
-static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, char *str);
-
-const X509V3_EXT_METHOD v3_pci =
- { NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION),
- 0, 0, 0, 0,
- 0, 0,
- NULL, NULL,
- (X509V3_EXT_I2R)i2r_pci,
- (X509V3_EXT_R2I)r2i_pci,
- NULL,
-};
-
-static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *pci,
- BIO *out, int indent)
-{
- BIO_printf(out, "%*sPath Length Constraint: ", indent, "");
- if (pci->pcPathLengthConstraint)
- i2a_ASN1_INTEGER(out, pci->pcPathLengthConstraint);
- else
- BIO_printf(out, "infinite");
- BIO_puts(out, "\n");
- BIO_printf(out, "%*sPolicy Language: ", indent, "");
- i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage);
- BIO_puts(out, "\n");
- if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data)
- BIO_printf(out, "%*sPolicy Text: %.*s\n", indent, "",
- pci->proxyPolicy->policy->length,
- pci->proxyPolicy->policy->data);
- return 1;
-}
-
-static int process_pci_value(CONF_VALUE *val,
- ASN1_OBJECT **language, ASN1_INTEGER **pathlen,
- ASN1_OCTET_STRING **policy)
-{
- int free_policy = 0;
-
- if (strcmp(val->name, "language") == 0) {
- if (*language) {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE,
- X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED);
- X509V3_conf_err(val);
- return 0;
- }
- if ((*language = OBJ_txt2obj(val->value, 0)) == NULL) {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE,
- X509V3_R_INVALID_OBJECT_IDENTIFIER);
- X509V3_conf_err(val);
- return 0;
- }
- } else if (strcmp(val->name, "pathlen") == 0) {
- if (*pathlen) {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE,
- X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED);
- X509V3_conf_err(val);
- return 0;
- }
- if (!X509V3_get_value_int(val, pathlen)) {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE,
- X509V3_R_POLICY_PATH_LENGTH);
- X509V3_conf_err(val);
- return 0;
- }
- } else if (strcmp(val->name, "policy") == 0) {
- unsigned char *tmp_data = NULL;
- long val_len;
- if (!*policy) {
- *policy = ASN1_OCTET_STRING_new();
- if (*policy == NULL) {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_MALLOC_FAILURE);
- X509V3_conf_err(val);
- return 0;
- }
- free_policy = 1;
- }
- if (strncmp(val->value, "hex:", 4) == 0) {
- unsigned char *tmp_data2 =
- OPENSSL_hexstr2buf(val->value + 4, &val_len);
-
- if (!tmp_data2) {
- X509V3_conf_err(val);
- goto err;
- }
-
- tmp_data = OPENSSL_realloc((*policy)->data,
- (*policy)->length + val_len + 1);
- if (tmp_data) {
- (*policy)->data = tmp_data;
- memcpy(&(*policy)->data[(*policy)->length],
- tmp_data2, val_len);
- (*policy)->length += val_len;
- (*policy)->data[(*policy)->length] = '\0';
- } else {
- OPENSSL_free(tmp_data2);
- /*
- * realloc failure implies the original data space is b0rked
- * too!
- */
- OPENSSL_free((*policy)->data);
- (*policy)->data = NULL;
- (*policy)->length = 0;
- X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_MALLOC_FAILURE);
- X509V3_conf_err(val);
- goto err;
- }
- OPENSSL_free(tmp_data2);
- } else if (strncmp(val->value, "file:", 5) == 0) {
- unsigned char buf[2048];
- int n;
- BIO *b = BIO_new_file(val->value + 5, "r");
- if (!b) {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_BIO_LIB);
- X509V3_conf_err(val);
- goto err;
- }
- while ((n = BIO_read(b, buf, sizeof(buf))) > 0
- || (n == 0 && BIO_should_retry(b))) {
- if (!n)
- continue;
-
- tmp_data = OPENSSL_realloc((*policy)->data,
- (*policy)->length + n + 1);
-
- if (!tmp_data) {
- OPENSSL_free((*policy)->data);
- (*policy)->data = NULL;
- (*policy)->length = 0;
- X509V3err(X509V3_F_PROCESS_PCI_VALUE,
- ERR_R_MALLOC_FAILURE);
- X509V3_conf_err(val);
- BIO_free_all(b);
- goto err;
- }
-
- (*policy)->data = tmp_data;
- memcpy(&(*policy)->data[(*policy)->length], buf, n);
- (*policy)->length += n;
- (*policy)->data[(*policy)->length] = '\0';
- }
- BIO_free_all(b);
-
- if (n < 0) {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_BIO_LIB);
- X509V3_conf_err(val);
- goto err;
- }
- } else if (strncmp(val->value, "text:", 5) == 0) {
- val_len = strlen(val->value + 5);
- tmp_data = OPENSSL_realloc((*policy)->data,
- (*policy)->length + val_len + 1);
- if (tmp_data) {
- (*policy)->data = tmp_data;
- memcpy(&(*policy)->data[(*policy)->length],
- val->value + 5, val_len);
- (*policy)->length += val_len;
- (*policy)->data[(*policy)->length] = '\0';
- } else {
- /*
- * realloc failure implies the original data space is b0rked
- * too!
- */
- OPENSSL_free((*policy)->data);
- (*policy)->data = NULL;
- (*policy)->length = 0;
- X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_MALLOC_FAILURE);
- X509V3_conf_err(val);
- goto err;
- }
- } else {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE,
- X509V3_R_INCORRECT_POLICY_SYNTAX_TAG);
- X509V3_conf_err(val);
- goto err;
- }
- if (!tmp_data) {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_MALLOC_FAILURE);
- X509V3_conf_err(val);
- goto err;
- }
- }
- return 1;
- err:
- if (free_policy) {
- ASN1_OCTET_STRING_free(*policy);
- *policy = NULL;
- }
- return 0;
-}
-
-static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, char *value)
-{
- PROXY_CERT_INFO_EXTENSION *pci = NULL;
- STACK_OF(CONF_VALUE) *vals;
- ASN1_OBJECT *language = NULL;
- ASN1_INTEGER *pathlen = NULL;
- ASN1_OCTET_STRING *policy = NULL;
- int i, j;
-
- vals = X509V3_parse_list(value);
- for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
- CONF_VALUE *cnf = sk_CONF_VALUE_value(vals, i);
- if (!cnf->name || (*cnf->name != '@' && !cnf->value)) {
- X509V3err(X509V3_F_R2I_PCI,
- X509V3_R_INVALID_PROXY_POLICY_SETTING);
- X509V3_conf_err(cnf);
- goto err;
- }
- if (*cnf->name == '@') {
- STACK_OF(CONF_VALUE) *sect;
- int success_p = 1;
-
- sect = X509V3_get_section(ctx, cnf->name + 1);
- if (!sect) {
- X509V3err(X509V3_F_R2I_PCI, X509V3_R_INVALID_SECTION);
- X509V3_conf_err(cnf);
- goto err;
- }
- for (j = 0; success_p && j < sk_CONF_VALUE_num(sect); j++) {
- success_p =
- process_pci_value(sk_CONF_VALUE_value(sect, j),
- &language, &pathlen, &policy);
- }
- X509V3_section_free(ctx, sect);
- if (!success_p)
- goto err;
- } else {
- if (!process_pci_value(cnf, &language, &pathlen, &policy)) {
- X509V3_conf_err(cnf);
- goto err;
- }
- }
- }
-
- /* Language is mandatory */
- if (!language) {
- X509V3err(X509V3_F_R2I_PCI,
- X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED);
- goto err;
- }
- i = OBJ_obj2nid(language);
- if ((i == NID_Independent || i == NID_id_ppl_inheritAll) && policy) {
- X509V3err(X509V3_F_R2I_PCI,
- X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY);
- goto err;
- }
-
- pci = PROXY_CERT_INFO_EXTENSION_new();
- if (pci == NULL) {
- X509V3err(X509V3_F_R2I_PCI, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- pci->proxyPolicy->policyLanguage = language;
- language = NULL;
- pci->proxyPolicy->policy = policy;
- policy = NULL;
- pci->pcPathLengthConstraint = pathlen;
- pathlen = NULL;
- goto end;
- err:
- ASN1_OBJECT_free(language);
- ASN1_INTEGER_free(pathlen);
- pathlen = NULL;
- ASN1_OCTET_STRING_free(policy);
- policy = NULL;
- PROXY_CERT_INFO_EXTENSION_free(pci);
- pci = NULL;
- end:
- sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
- return pci;
-}
diff --git a/crypto/x509v3/v3_pcia.c b/crypto/x509v3/v3_pcia.c
deleted file mode 100644
index 8d6af60e5da6..000000000000
--- a/crypto/x509v3/v3_pcia.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * This file is dual-licensed and is also available under the following
- * terms:
- *
- * Copyright (c) 2004 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-#include <openssl/x509v3.h>
-
-ASN1_SEQUENCE(PROXY_POLICY) =
- {
- ASN1_SIMPLE(PROXY_POLICY,policyLanguage,ASN1_OBJECT),
- ASN1_OPT(PROXY_POLICY,policy,ASN1_OCTET_STRING)
-} ASN1_SEQUENCE_END(PROXY_POLICY)
-
-IMPLEMENT_ASN1_FUNCTIONS(PROXY_POLICY)
-
-ASN1_SEQUENCE(PROXY_CERT_INFO_EXTENSION) =
- {
- ASN1_OPT(PROXY_CERT_INFO_EXTENSION,pcPathLengthConstraint,ASN1_INTEGER),
- ASN1_SIMPLE(PROXY_CERT_INFO_EXTENSION,proxyPolicy,PROXY_POLICY)
-} ASN1_SEQUENCE_END(PROXY_CERT_INFO_EXTENSION)
-
-IMPLEMENT_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION)
diff --git a/crypto/x509v3/v3_pcons.c b/crypto/x509v3/v3_pcons.c
deleted file mode 100644
index 24f7ff49e57c..000000000000
--- a/crypto/x509v3/v3_pcons.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2003-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-#include <openssl/conf.h>
-#include <openssl/x509v3.h>
-#include "ext_dat.h"
-
-static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD
- *method, void *bcons, STACK_OF(CONF_VALUE)
- *extlist);
-static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *values);
-
-const X509V3_EXT_METHOD v3_policy_constraints = {
- NID_policy_constraints, 0,
- ASN1_ITEM_ref(POLICY_CONSTRAINTS),
- 0, 0, 0, 0,
- 0, 0,
- i2v_POLICY_CONSTRAINTS,
- v2i_POLICY_CONSTRAINTS,
- NULL, NULL,
- NULL
-};
-
-ASN1_SEQUENCE(POLICY_CONSTRAINTS) = {
- ASN1_IMP_OPT(POLICY_CONSTRAINTS, requireExplicitPolicy, ASN1_INTEGER,0),
- ASN1_IMP_OPT(POLICY_CONSTRAINTS, inhibitPolicyMapping, ASN1_INTEGER,1)
-} ASN1_SEQUENCE_END(POLICY_CONSTRAINTS)
-
-IMPLEMENT_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS)
-
-static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD
- *method, void *a, STACK_OF(CONF_VALUE)
- *extlist)
-{
- POLICY_CONSTRAINTS *pcons = a;
- X509V3_add_value_int("Require Explicit Policy",
- pcons->requireExplicitPolicy, &extlist);
- X509V3_add_value_int("Inhibit Policy Mapping",
- pcons->inhibitPolicyMapping, &extlist);
- return extlist;
-}
-
-static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *values)
-{
- POLICY_CONSTRAINTS *pcons = NULL;
- CONF_VALUE *val;
- int i;
-
- if ((pcons = POLICY_CONSTRAINTS_new()) == NULL) {
- X509V3err(X509V3_F_V2I_POLICY_CONSTRAINTS, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
- val = sk_CONF_VALUE_value(values, i);
- if (strcmp(val->name, "requireExplicitPolicy") == 0) {
- if (!X509V3_get_value_int(val, &pcons->requireExplicitPolicy))
- goto err;
- } else if (strcmp(val->name, "inhibitPolicyMapping") == 0) {
- if (!X509V3_get_value_int(val, &pcons->inhibitPolicyMapping))
- goto err;
- } else {
- X509V3err(X509V3_F_V2I_POLICY_CONSTRAINTS, X509V3_R_INVALID_NAME);
- X509V3_conf_err(val);
- goto err;
- }
- }
- if (!pcons->inhibitPolicyMapping && !pcons->requireExplicitPolicy) {
- X509V3err(X509V3_F_V2I_POLICY_CONSTRAINTS,
- X509V3_R_ILLEGAL_EMPTY_EXTENSION);
- goto err;
- }
-
- return pcons;
- err:
- POLICY_CONSTRAINTS_free(pcons);
- return NULL;
-}
diff --git a/crypto/x509v3/v3_pku.c b/crypto/x509v3/v3_pku.c
deleted file mode 100644
index 5a7e7d972516..000000000000
--- a/crypto/x509v3/v3_pku.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-#include <openssl/x509v3.h>
-#include "ext_dat.h"
-
-static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method,
- PKEY_USAGE_PERIOD *usage, BIO *out,
- int indent);
-
-const X509V3_EXT_METHOD v3_pkey_usage_period = {
- NID_private_key_usage_period, 0, ASN1_ITEM_ref(PKEY_USAGE_PERIOD),
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- (X509V3_EXT_I2R)i2r_PKEY_USAGE_PERIOD, NULL,
- NULL
-};
-
-ASN1_SEQUENCE(PKEY_USAGE_PERIOD) = {
- ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notBefore, ASN1_GENERALIZEDTIME, 0),
- ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notAfter, ASN1_GENERALIZEDTIME, 1)
-} ASN1_SEQUENCE_END(PKEY_USAGE_PERIOD)
-
-IMPLEMENT_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD)
-
-static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method,
- PKEY_USAGE_PERIOD *usage, BIO *out,
- int indent)
-{
- BIO_printf(out, "%*s", indent, "");
- if (usage->notBefore) {
- BIO_write(out, "Not Before: ", 12);
- ASN1_GENERALIZEDTIME_print(out, usage->notBefore);
- if (usage->notAfter)
- BIO_write(out, ", ", 2);
- }
- if (usage->notAfter) {
- BIO_write(out, "Not After: ", 11);
- ASN1_GENERALIZEDTIME_print(out, usage->notAfter);
- }
- return 1;
-}
diff --git a/crypto/x509v3/v3_pmaps.c b/crypto/x509v3/v3_pmaps.c
deleted file mode 100644
index 5b6a2af0fbf6..000000000000
--- a/crypto/x509v3/v3_pmaps.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2003-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/asn1t.h>
-#include <openssl/conf.h>
-#include <openssl/x509v3.h>
-#include "ext_dat.h"
-
-static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
-static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD
- *method, void *pmps, STACK_OF(CONF_VALUE)
- *extlist);
-
-const X509V3_EXT_METHOD v3_policy_mappings = {
- NID_policy_mappings, 0,
- ASN1_ITEM_ref(POLICY_MAPPINGS),
- 0, 0, 0, 0,
- 0, 0,
- i2v_POLICY_MAPPINGS,
- v2i_POLICY_MAPPINGS,
- 0, 0,
- NULL
-};
-
-ASN1_SEQUENCE(POLICY_MAPPING) = {
- ASN1_SIMPLE(POLICY_MAPPING, issuerDomainPolicy, ASN1_OBJECT),
- ASN1_SIMPLE(POLICY_MAPPING, subjectDomainPolicy, ASN1_OBJECT)
-} ASN1_SEQUENCE_END(POLICY_MAPPING)
-
-ASN1_ITEM_TEMPLATE(POLICY_MAPPINGS) =
- ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, POLICY_MAPPINGS,
- POLICY_MAPPING)
-ASN1_ITEM_TEMPLATE_END(POLICY_MAPPINGS)
-
-IMPLEMENT_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING)
-
-static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD
- *method, void *a, STACK_OF(CONF_VALUE)
- *ext_list)
-{
- POLICY_MAPPINGS *pmaps = a;
- POLICY_MAPPING *pmap;
- int i;
- char obj_tmp1[80];
- char obj_tmp2[80];
-
- for (i = 0; i < sk_POLICY_MAPPING_num(pmaps); i++) {
- pmap = sk_POLICY_MAPPING_value(pmaps, i);
- i2t_ASN1_OBJECT(obj_tmp1, 80, pmap->issuerDomainPolicy);
- i2t_ASN1_OBJECT(obj_tmp2, 80, pmap->subjectDomainPolicy);
- X509V3_add_value(obj_tmp1, obj_tmp2, &ext_list);
- }
- return ext_list;
-}
-
-static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
-{
- POLICY_MAPPING *pmap = NULL;
- ASN1_OBJECT *obj1 = NULL, *obj2 = NULL;
- CONF_VALUE *val;
- POLICY_MAPPINGS *pmaps;
- const int num = sk_CONF_VALUE_num(nval);
- int i;
-
- if ((pmaps = sk_POLICY_MAPPING_new_reserve(NULL, num)) == NULL) {
- X509V3err(X509V3_F_V2I_POLICY_MAPPINGS, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- for (i = 0; i < num; i++) {
- val = sk_CONF_VALUE_value(nval, i);
- if (!val->value || !val->name) {
- X509V3err(X509V3_F_V2I_POLICY_MAPPINGS,
- X509V3_R_INVALID_OBJECT_IDENTIFIER);
- X509V3_conf_err(val);
- goto err;
- }
- obj1 = OBJ_txt2obj(val->name, 0);
- obj2 = OBJ_txt2obj(val->value, 0);
- if (!obj1 || !obj2) {
- X509V3err(X509V3_F_V2I_POLICY_MAPPINGS,
- X509V3_R_INVALID_OBJECT_IDENTIFIER);
- X509V3_conf_err(val);
- goto err;
- }
- pmap = POLICY_MAPPING_new();
- if (pmap == NULL) {
- X509V3err(X509V3_F_V2I_POLICY_MAPPINGS, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- pmap->issuerDomainPolicy = obj1;
- pmap->subjectDomainPolicy = obj2;
- obj1 = obj2 = NULL;
- sk_POLICY_MAPPING_push(pmaps, pmap); /* no failure as it was reserved */
- }
- return pmaps;
- err:
- ASN1_OBJECT_free(obj1);
- ASN1_OBJECT_free(obj2);
- sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
- return NULL;
-}
diff --git a/crypto/x509v3/v3_prn.c b/crypto/x509v3/v3_prn.c
deleted file mode 100644
index f384c342acc0..000000000000
--- a/crypto/x509v3/v3_prn.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/* X509 v3 extension utilities */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/conf.h>
-#include <openssl/x509v3.h>
-
-/* Extension printing routines */
-
-static int unknown_ext_print(BIO *out, const unsigned char *ext, int extlen,
- unsigned long flag, int indent, int supported);
-
-/* Print out a name+value stack */
-
-void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
- int ml)
-{
- int i;
- CONF_VALUE *nval;
- if (!val)
- return;
- if (!ml || !sk_CONF_VALUE_num(val)) {
- BIO_printf(out, "%*s", indent, "");
- if (!sk_CONF_VALUE_num(val))
- BIO_puts(out, "<EMPTY>\n");
- }
- for (i = 0; i < sk_CONF_VALUE_num(val); i++) {
- if (ml)
- BIO_printf(out, "%*s", indent, "");
- else if (i > 0)
- BIO_printf(out, ", ");
- nval = sk_CONF_VALUE_value(val, i);
- if (!nval->name)
- BIO_puts(out, nval->value);
- else if (!nval->value)
- BIO_puts(out, nval->name);
-#ifndef CHARSET_EBCDIC
- else
- BIO_printf(out, "%s:%s", nval->name, nval->value);
-#else
- else {
- int len;
- char *tmp;
- len = strlen(nval->value) + 1;
- tmp = OPENSSL_malloc(len);
- if (tmp != NULL) {
- ascii2ebcdic(tmp, nval->value, len);
- BIO_printf(out, "%s:%s", nval->name, tmp);
- OPENSSL_free(tmp);
- }
- }
-#endif
- if (ml)
- BIO_puts(out, "\n");
- }
-}
-
-/* Main routine: print out a general extension */
-
-int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag,
- int indent)
-{
- void *ext_str = NULL;
- char *value = NULL;
- ASN1_OCTET_STRING *extoct;
- const unsigned char *p;
- int extlen;
- const X509V3_EXT_METHOD *method;
- STACK_OF(CONF_VALUE) *nval = NULL;
- int ok = 1;
-
- extoct = X509_EXTENSION_get_data(ext);
- p = ASN1_STRING_get0_data(extoct);
- extlen = ASN1_STRING_length(extoct);
-
- if ((method = X509V3_EXT_get(ext)) == NULL)
- return unknown_ext_print(out, p, extlen, flag, indent, 0);
- if (method->it)
- ext_str = ASN1_item_d2i(NULL, &p, extlen, ASN1_ITEM_ptr(method->it));
- else
- ext_str = method->d2i(NULL, &p, extlen);
-
- if (!ext_str)
- return unknown_ext_print(out, p, extlen, flag, indent, 1);
-
- if (method->i2s) {
- if ((value = method->i2s(method, ext_str)) == NULL) {
- ok = 0;
- goto err;
- }
-#ifndef CHARSET_EBCDIC
- BIO_printf(out, "%*s%s", indent, "", value);
-#else
- {
- int len;
- char *tmp;
- len = strlen(value) + 1;
- tmp = OPENSSL_malloc(len);
- if (tmp != NULL) {
- ascii2ebcdic(tmp, value, len);
- BIO_printf(out, "%*s%s", indent, "", tmp);
- OPENSSL_free(tmp);
- }
- }
-#endif
- } else if (method->i2v) {
- if ((nval = method->i2v(method, ext_str, NULL)) == NULL) {
- ok = 0;
- goto err;
- }
- X509V3_EXT_val_prn(out, nval, indent,
- method->ext_flags & X509V3_EXT_MULTILINE);
- } else if (method->i2r) {
- if (!method->i2r(method, ext_str, out, indent))
- ok = 0;
- } else
- ok = 0;
-
- err:
- sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
- OPENSSL_free(value);
- if (method->it)
- ASN1_item_free(ext_str, ASN1_ITEM_ptr(method->it));
- else
- method->ext_free(ext_str);
- return ok;
-}
-
-int X509V3_extensions_print(BIO *bp, const char *title,
- const STACK_OF(X509_EXTENSION) *exts,
- unsigned long flag, int indent)
-{
- int i, j;
-
- if (sk_X509_EXTENSION_num(exts) <= 0)
- return 1;
-
- if (title) {
- BIO_printf(bp, "%*s%s:\n", indent, "", title);
- indent += 4;
- }
-
- for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
- ASN1_OBJECT *obj;
- X509_EXTENSION *ex;
- ex = sk_X509_EXTENSION_value(exts, i);
- if (indent && BIO_printf(bp, "%*s", indent, "") <= 0)
- return 0;
- obj = X509_EXTENSION_get_object(ex);
- i2a_ASN1_OBJECT(bp, obj);
- j = X509_EXTENSION_get_critical(ex);
- if (BIO_printf(bp, ": %s\n", j ? "critical" : "") <= 0)
- return 0;
- if (!X509V3_EXT_print(bp, ex, flag, indent + 4)) {
- BIO_printf(bp, "%*s", indent + 4, "");
- ASN1_STRING_print(bp, X509_EXTENSION_get_data(ex));
- }
- if (BIO_write(bp, "\n", 1) <= 0)
- return 0;
- }
- return 1;
-}
-
-static int unknown_ext_print(BIO *out, const unsigned char *ext, int extlen,
- unsigned long flag, int indent, int supported)
-{
- switch (flag & X509V3_EXT_UNKNOWN_MASK) {
-
- case X509V3_EXT_DEFAULT:
- return 0;
-
- case X509V3_EXT_ERROR_UNKNOWN:
- if (supported)
- BIO_printf(out, "%*s<Parse Error>", indent, "");
- else
- BIO_printf(out, "%*s<Not Supported>", indent, "");
- return 1;
-
- case X509V3_EXT_PARSE_UNKNOWN:
- return ASN1_parse_dump(out, ext, extlen, indent, -1);
- case X509V3_EXT_DUMP_UNKNOWN:
- return BIO_dump_indent(out, (const char *)ext, extlen, indent);
-
- default:
- return 1;
- }
-}
-
-#ifndef OPENSSL_NO_STDIO
-int X509V3_EXT_print_fp(FILE *fp, X509_EXTENSION *ext, int flag, int indent)
-{
- BIO *bio_tmp;
- int ret;
-
- if ((bio_tmp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL)
- return 0;
- ret = X509V3_EXT_print(bio_tmp, ext, flag, indent);
- BIO_free(bio_tmp);
- return ret;
-}
-#endif
diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c
deleted file mode 100644
index a1aeb4e4c60b..000000000000
--- a/crypto/x509v3/v3_purp.c
+++ /dev/null
@@ -1,993 +0,0 @@
-/*
- * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include "internal/numbers.h"
-#include <openssl/x509v3.h>
-#include <openssl/x509_vfy.h>
-#include "crypto/x509.h"
-#include "../x509/x509_local.h" /* for x509_signing_allowed() */
-#include "internal/tsan_assist.h"
-
-static void x509v3_cache_extensions(X509 *x);
-
-static int check_ssl_ca(const X509 *x);
-static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
- int ca);
-static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
- int ca);
-static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
- int ca);
-static int purpose_smime(const X509 *x, int ca);
-static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x,
- int ca);
-static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
- int ca);
-static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
- int ca);
-static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
- int ca);
-static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca);
-static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca);
-
-static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b);
-static void xptable_free(X509_PURPOSE *p);
-
-static X509_PURPOSE xstandard[] = {
- {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0,
- check_purpose_ssl_client, "SSL client", "sslclient", NULL},
- {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0,
- check_purpose_ssl_server, "SSL server", "sslserver", NULL},
- {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0,
- check_purpose_ns_ssl_server, "Netscape SSL server", "nssslserver", NULL},
- {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign,
- "S/MIME signing", "smimesign", NULL},
- {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0,
- check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL},
- {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign,
- "CRL signing", "crlsign", NULL},
- {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, "Any Purpose", "any",
- NULL},
- {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper,
- "OCSP helper", "ocsphelper", NULL},
- {X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0,
- check_purpose_timestamp_sign, "Time Stamp signing", "timestampsign",
- NULL},
-};
-
-#define X509_PURPOSE_COUNT OSSL_NELEM(xstandard)
-
-static STACK_OF(X509_PURPOSE) *xptable = NULL;
-
-static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b)
-{
- return (*a)->purpose - (*b)->purpose;
-}
-
-/*
- * As much as I'd like to make X509_check_purpose use a "const" X509* I
- * really can't because it does recalculate hashes and do other non-const
- * things.
- */
-int X509_check_purpose(X509 *x, int id, int ca)
-{
- int idx;
- const X509_PURPOSE *pt;
-
- x509v3_cache_extensions(x);
- if (x->ex_flags & EXFLAG_INVALID)
- return -1;
-
- /* Return if side-effect only call */
- if (id == -1)
- return 1;
- idx = X509_PURPOSE_get_by_id(id);
- if (idx == -1)
- return -1;
- pt = X509_PURPOSE_get0(idx);
- return pt->check_purpose(pt, x, ca);
-}
-
-int X509_PURPOSE_set(int *p, int purpose)
-{
- if (X509_PURPOSE_get_by_id(purpose) == -1) {
- X509V3err(X509V3_F_X509_PURPOSE_SET, X509V3_R_INVALID_PURPOSE);
- return 0;
- }
- *p = purpose;
- return 1;
-}
-
-int X509_PURPOSE_get_count(void)
-{
- if (!xptable)
- return X509_PURPOSE_COUNT;
- return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT;
-}
-
-X509_PURPOSE *X509_PURPOSE_get0(int idx)
-{
- if (idx < 0)
- return NULL;
- if (idx < (int)X509_PURPOSE_COUNT)
- return xstandard + idx;
- return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT);
-}
-
-int X509_PURPOSE_get_by_sname(const char *sname)
-{
- int i;
- X509_PURPOSE *xptmp;
- for (i = 0; i < X509_PURPOSE_get_count(); i++) {
- xptmp = X509_PURPOSE_get0(i);
- if (strcmp(xptmp->sname, sname) == 0)
- return i;
- }
- return -1;
-}
-
-int X509_PURPOSE_get_by_id(int purpose)
-{
- X509_PURPOSE tmp;
- int idx;
-
- if ((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX))
- return purpose - X509_PURPOSE_MIN;
- if (xptable == NULL)
- return -1;
- tmp.purpose = purpose;
- idx = sk_X509_PURPOSE_find(xptable, &tmp);
- if (idx < 0)
- return -1;
- return idx + X509_PURPOSE_COUNT;
-}
-
-int X509_PURPOSE_add(int id, int trust, int flags,
- int (*ck) (const X509_PURPOSE *, const X509 *, int),
- const char *name, const char *sname, void *arg)
-{
- int idx;
- X509_PURPOSE *ptmp;
- /*
- * This is set according to what we change: application can't set it
- */
- flags &= ~X509_PURPOSE_DYNAMIC;
- /* This will always be set for application modified trust entries */
- flags |= X509_PURPOSE_DYNAMIC_NAME;
- /* Get existing entry if any */
- idx = X509_PURPOSE_get_by_id(id);
- /* Need a new entry */
- if (idx == -1) {
- if ((ptmp = OPENSSL_malloc(sizeof(*ptmp))) == NULL) {
- X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- ptmp->flags = X509_PURPOSE_DYNAMIC;
- } else
- ptmp = X509_PURPOSE_get0(idx);
-
- /* OPENSSL_free existing name if dynamic */
- if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) {
- OPENSSL_free(ptmp->name);
- OPENSSL_free(ptmp->sname);
- }
- /* dup supplied name */
- ptmp->name = OPENSSL_strdup(name);
- ptmp->sname = OPENSSL_strdup(sname);
- if (!ptmp->name || !ptmp->sname) {
- X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- /* Keep the dynamic flag of existing entry */
- ptmp->flags &= X509_PURPOSE_DYNAMIC;
- /* Set all other flags */
- ptmp->flags |= flags;
-
- ptmp->purpose = id;
- ptmp->trust = trust;
- ptmp->check_purpose = ck;
- ptmp->usr_data = arg;
-
- /* If its a new entry manage the dynamic table */
- if (idx == -1) {
- if (xptable == NULL
- && (xptable = sk_X509_PURPOSE_new(xp_cmp)) == NULL) {
- X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if (!sk_X509_PURPOSE_push(xptable, ptmp)) {
- X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
- return 1;
- err:
- if (idx == -1) {
- OPENSSL_free(ptmp->name);
- OPENSSL_free(ptmp->sname);
- OPENSSL_free(ptmp);
- }
- return 0;
-}
-
-static void xptable_free(X509_PURPOSE *p)
-{
- if (!p)
- return;
- if (p->flags & X509_PURPOSE_DYNAMIC) {
- if (p->flags & X509_PURPOSE_DYNAMIC_NAME) {
- OPENSSL_free(p->name);
- OPENSSL_free(p->sname);
- }
- OPENSSL_free(p);
- }
-}
-
-void X509_PURPOSE_cleanup(void)
-{
- sk_X509_PURPOSE_pop_free(xptable, xptable_free);
- xptable = NULL;
-}
-
-int X509_PURPOSE_get_id(const X509_PURPOSE *xp)
-{
- return xp->purpose;
-}
-
-char *X509_PURPOSE_get0_name(const X509_PURPOSE *xp)
-{
- return xp->name;
-}
-
-char *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp)
-{
- return xp->sname;
-}
-
-int X509_PURPOSE_get_trust(const X509_PURPOSE *xp)
-{
- return xp->trust;
-}
-
-static int nid_cmp(const int *a, const int *b)
-{
- return *a - *b;
-}
-
-DECLARE_OBJ_BSEARCH_CMP_FN(int, int, nid);
-IMPLEMENT_OBJ_BSEARCH_CMP_FN(int, int, nid);
-
-int X509_supported_extension(X509_EXTENSION *ex)
-{
- /*
- * This table is a list of the NIDs of supported extensions: that is
- * those which are used by the verify process. If an extension is
- * critical and doesn't appear in this list then the verify process will
- * normally reject the certificate. The list must be kept in numerical
- * order because it will be searched using bsearch.
- */
-
- static const int supported_nids[] = {
- NID_netscape_cert_type, /* 71 */
- NID_key_usage, /* 83 */
- NID_subject_alt_name, /* 85 */
- NID_basic_constraints, /* 87 */
- NID_certificate_policies, /* 89 */
- NID_crl_distribution_points, /* 103 */
- NID_ext_key_usage, /* 126 */
-#ifndef OPENSSL_NO_RFC3779
- NID_sbgp_ipAddrBlock, /* 290 */
- NID_sbgp_autonomousSysNum, /* 291 */
-#endif
- NID_policy_constraints, /* 401 */
- NID_proxyCertInfo, /* 663 */
- NID_name_constraints, /* 666 */
- NID_policy_mappings, /* 747 */
- NID_inhibit_any_policy /* 748 */
- };
-
- int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
-
- if (ex_nid == NID_undef)
- return 0;
-
- if (OBJ_bsearch_nid(&ex_nid, supported_nids, OSSL_NELEM(supported_nids)))
- return 1;
- return 0;
-}
-
-static int setup_dp(X509 *x, DIST_POINT *dp)
-{
- X509_NAME *iname = NULL;
- int i;
-
- if (dp->reasons) {
- if (dp->reasons->length > 0)
- dp->dp_reasons = dp->reasons->data[0];
- if (dp->reasons->length > 1)
- dp->dp_reasons |= (dp->reasons->data[1] << 8);
- dp->dp_reasons &= CRLDP_ALL_REASONS;
- } else
- dp->dp_reasons = CRLDP_ALL_REASONS;
- if (!dp->distpoint || (dp->distpoint->type != 1))
- return 1;
- for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) {
- GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
- if (gen->type == GEN_DIRNAME) {
- iname = gen->d.directoryName;
- break;
- }
- }
- if (!iname)
- iname = X509_get_issuer_name(x);
-
- return DIST_POINT_set_dpname(dp->distpoint, iname);
-}
-
-static int setup_crldp(X509 *x)
-{
- int i;
-
- x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, &i, NULL);
- if (x->crldp == NULL && i != -1)
- return 0;
- for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) {
- if (!setup_dp(x, sk_DIST_POINT_value(x->crldp, i)))
- return 0;
- }
- return 1;
-}
-
-/* Check that issuer public key algorithm matches subject signature algorithm */
-static int check_sig_alg_match(const EVP_PKEY *pkey, const X509 *subject)
-{
- int pkey_sig_nid, subj_sig_nid;
-
- if (pkey == NULL)
- return X509_V_ERR_NO_ISSUER_PUBLIC_KEY;
- if (OBJ_find_sigid_algs(EVP_PKEY_base_id(pkey),
- NULL, &pkey_sig_nid) == 0)
- pkey_sig_nid = EVP_PKEY_base_id(pkey);
- if (OBJ_find_sigid_algs(OBJ_obj2nid(subject->cert_info.signature.algorithm),
- NULL, &subj_sig_nid) == 0)
- return X509_V_ERR_UNSUPPORTED_SIGNATURE_ALGORITHM;
- if (pkey_sig_nid != EVP_PKEY_type(subj_sig_nid))
- return X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH;
- return X509_V_OK;
-}
-
-#define V1_ROOT (EXFLAG_V1|EXFLAG_SS)
-#define ku_reject(x, usage) \
- (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
-#define xku_reject(x, usage) \
- (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage)))
-#define ns_reject(x, usage) \
- (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage)))
-
-static void x509v3_cache_extensions(X509 *x)
-{
- BASIC_CONSTRAINTS *bs;
- PROXY_CERT_INFO_EXTENSION *pci;
- ASN1_BIT_STRING *usage;
- ASN1_BIT_STRING *ns;
- EXTENDED_KEY_USAGE *extusage;
- X509_EXTENSION *ex;
- int i;
-
-#ifdef tsan_ld_acq
- /* fast lock-free check, see end of the function for details. */
- if (tsan_ld_acq((TSAN_QUALIFIER int *)&x->ex_cached))
- return;
-#endif
-
- CRYPTO_THREAD_write_lock(x->lock);
- if (x->ex_flags & EXFLAG_SET) {
- CRYPTO_THREAD_unlock(x->lock);
- return;
- }
-
- if (!X509_digest(x, EVP_sha1(), x->sha1_hash, NULL))
- x->ex_flags |= (EXFLAG_NO_FINGERPRINT | EXFLAG_INVALID);
-
- /* V1 should mean no extensions ... */
- if (!X509_get_version(x))
- x->ex_flags |= EXFLAG_V1;
- /* Handle basic constraints */
- if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, &i, NULL))) {
- if (bs->ca)
- x->ex_flags |= EXFLAG_CA;
- if (bs->pathlen) {
- if (bs->pathlen->type == V_ASN1_NEG_INTEGER) {
- x->ex_flags |= EXFLAG_INVALID;
- x->ex_pathlen = 0;
- } else {
- x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen);
- if (!bs->ca && x->ex_pathlen != 0) {
- x->ex_flags |= EXFLAG_INVALID;
- x->ex_pathlen = 0;
- }
- }
- } else
- x->ex_pathlen = -1;
- BASIC_CONSTRAINTS_free(bs);
- x->ex_flags |= EXFLAG_BCONS;
- } else if (i != -1) {
- x->ex_flags |= EXFLAG_INVALID;
- }
- /* Handle proxy certificates */
- if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, &i, NULL))) {
- if (x->ex_flags & EXFLAG_CA
- || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0
- || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) {
- x->ex_flags |= EXFLAG_INVALID;
- }
- if (pci->pcPathLengthConstraint) {
- x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint);
- } else
- x->ex_pcpathlen = -1;
- PROXY_CERT_INFO_EXTENSION_free(pci);
- x->ex_flags |= EXFLAG_PROXY;
- } else if (i != -1) {
- x->ex_flags |= EXFLAG_INVALID;
- }
- /* Handle key usage */
- if ((usage = X509_get_ext_d2i(x, NID_key_usage, &i, NULL))) {
- if (usage->length > 0) {
- x->ex_kusage = usage->data[0];
- if (usage->length > 1)
- x->ex_kusage |= usage->data[1] << 8;
- } else
- x->ex_kusage = 0;
- x->ex_flags |= EXFLAG_KUSAGE;
- ASN1_BIT_STRING_free(usage);
- } else if (i != -1) {
- x->ex_flags |= EXFLAG_INVALID;
- }
- x->ex_xkusage = 0;
- if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, &i, NULL))) {
- x->ex_flags |= EXFLAG_XKUSAGE;
- for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) {
- switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) {
- case NID_server_auth:
- x->ex_xkusage |= XKU_SSL_SERVER;
- break;
-
- case NID_client_auth:
- x->ex_xkusage |= XKU_SSL_CLIENT;
- break;
-
- case NID_email_protect:
- x->ex_xkusage |= XKU_SMIME;
- break;
-
- case NID_code_sign:
- x->ex_xkusage |= XKU_CODE_SIGN;
- break;
-
- case NID_ms_sgc:
- case NID_ns_sgc:
- x->ex_xkusage |= XKU_SGC;
- break;
-
- case NID_OCSP_sign:
- x->ex_xkusage |= XKU_OCSP_SIGN;
- break;
-
- case NID_time_stamp:
- x->ex_xkusage |= XKU_TIMESTAMP;
- break;
-
- case NID_dvcs:
- x->ex_xkusage |= XKU_DVCS;
- break;
-
- case NID_anyExtendedKeyUsage:
- x->ex_xkusage |= XKU_ANYEKU;
- break;
- }
- }
- sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
- } else if (i != -1) {
- x->ex_flags |= EXFLAG_INVALID;
- }
-
- if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, &i, NULL))) {
- if (ns->length > 0)
- x->ex_nscert = ns->data[0];
- else
- x->ex_nscert = 0;
- x->ex_flags |= EXFLAG_NSCERT;
- ASN1_BIT_STRING_free(ns);
- } else if (i != -1) {
- x->ex_flags |= EXFLAG_INVALID;
- }
- x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, &i, NULL);
- if (x->skid == NULL && i != -1)
- x->ex_flags |= EXFLAG_INVALID;
- x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, &i, NULL);
- if (x->akid == NULL && i != -1)
- x->ex_flags |= EXFLAG_INVALID;
- /* Does subject name match issuer ? */
- if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) {
- x->ex_flags |= EXFLAG_SI; /* cert is self-issued */
- if (X509_check_akid(x, x->akid) == X509_V_OK /* SKID matches AKID */
- /* .. and the signature alg matches the PUBKEY alg: */
- && check_sig_alg_match(X509_get0_pubkey(x), x) == X509_V_OK)
- x->ex_flags |= EXFLAG_SS; /* indicate self-signed */
- }
- x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, &i, NULL);
- if (x->altname == NULL && i != -1)
- x->ex_flags |= EXFLAG_INVALID;
- x->nc = X509_get_ext_d2i(x, NID_name_constraints, &i, NULL);
- if (x->nc == NULL && i != -1)
- x->ex_flags |= EXFLAG_INVALID;
- if (!setup_crldp(x))
- x->ex_flags |= EXFLAG_INVALID;
-
-#ifndef OPENSSL_NO_RFC3779
- x->rfc3779_addr = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, &i, NULL);
- if (x->rfc3779_addr == NULL && i != -1)
- x->ex_flags |= EXFLAG_INVALID;
- x->rfc3779_asid = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, &i, NULL);
- if (x->rfc3779_asid == NULL && i != -1)
- x->ex_flags |= EXFLAG_INVALID;
-#endif
- for (i = 0; i < X509_get_ext_count(x); i++) {
- ex = X509_get_ext(x, i);
- if (OBJ_obj2nid(X509_EXTENSION_get_object(ex))
- == NID_freshest_crl)
- x->ex_flags |= EXFLAG_FRESHEST;
- if (!X509_EXTENSION_get_critical(ex))
- continue;
- if (!X509_supported_extension(ex)) {
- x->ex_flags |= EXFLAG_CRITICAL;
- break;
- }
- }
- x509_init_sig_info(x);
- x->ex_flags |= EXFLAG_SET;
-#ifdef tsan_st_rel
- tsan_st_rel((TSAN_QUALIFIER int *)&x->ex_cached, 1);
- /*
- * Above store triggers fast lock-free check in the beginning of the
- * function. But one has to ensure that the structure is "stable", i.e.
- * all stores are visible on all processors. Hence the release fence.
- */
-#endif
- CRYPTO_THREAD_unlock(x->lock);
-}
-
-/*-
- * CA checks common to all purposes
- * return codes:
- * 0 not a CA
- * 1 is a CA
- * 2 Only possible in older versions of openSSL when basicConstraints are absent
- * new versions will not return this value. May be a CA
- * 3 basicConstraints absent but self signed V1.
- * 4 basicConstraints absent but keyUsage present and keyCertSign asserted.
- * 5 Netscape specific CA Flags present
- */
-
-static int check_ca(const X509 *x)
-{
- /* keyUsage if present should allow cert signing */
- if (ku_reject(x, KU_KEY_CERT_SIGN))
- return 0;
- if (x->ex_flags & EXFLAG_BCONS) {
- if (x->ex_flags & EXFLAG_CA)
- return 1;
- /* If basicConstraints says not a CA then say so */
- else
- return 0;
- } else {
- /* we support V1 roots for... uh, I don't really know why. */
- if ((x->ex_flags & V1_ROOT) == V1_ROOT)
- return 3;
- /*
- * If key usage present it must have certSign so tolerate it
- */
- else if (x->ex_flags & EXFLAG_KUSAGE)
- return 4;
- /* Older certificates could have Netscape-specific CA types */
- else if (x->ex_flags & EXFLAG_NSCERT && x->ex_nscert & NS_ANY_CA)
- return 5;
- /* can this still be regarded a CA certificate? I doubt it */
- return 0;
- }
-}
-
-void X509_set_proxy_flag(X509 *x)
-{
- x->ex_flags |= EXFLAG_PROXY;
-}
-
-void X509_set_proxy_pathlen(X509 *x, long l)
-{
- x->ex_pcpathlen = l;
-}
-
-int X509_check_ca(X509 *x)
-{
- x509v3_cache_extensions(x);
-
- return check_ca(x);
-}
-
-/* Check SSL CA: common checks for SSL client and server */
-static int check_ssl_ca(const X509 *x)
-{
- int ca_ret;
- ca_ret = check_ca(x);
- if (!ca_ret)
- return 0;
- /* check nsCertType if present */
- if (ca_ret != 5 || x->ex_nscert & NS_SSL_CA)
- return ca_ret;
- else
- return 0;
-}
-
-static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
- int ca)
-{
- if (xku_reject(x, XKU_SSL_CLIENT))
- return 0;
- if (ca)
- return check_ssl_ca(x);
- /* We need to do digital signatures or key agreement */
- if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT))
- return 0;
- /* nsCertType if present should allow SSL client use */
- if (ns_reject(x, NS_SSL_CLIENT))
- return 0;
- return 1;
-}
-
-/*
- * Key usage needed for TLS/SSL server: digital signature, encipherment or
- * key agreement. The ssl code can check this more thoroughly for individual
- * key types.
- */
-#define KU_TLS \
- KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT
-
-static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
- int ca)
-{
- if (xku_reject(x, XKU_SSL_SERVER | XKU_SGC))
- return 0;
- if (ca)
- return check_ssl_ca(x);
-
- if (ns_reject(x, NS_SSL_SERVER))
- return 0;
- if (ku_reject(x, KU_TLS))
- return 0;
-
- return 1;
-
-}
-
-static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
- int ca)
-{
- int ret;
- ret = check_purpose_ssl_server(xp, x, ca);
- if (!ret || ca)
- return ret;
- /* We need to encipher or Netscape complains */
- if (ku_reject(x, KU_KEY_ENCIPHERMENT))
- return 0;
- return ret;
-}
-
-/* common S/MIME checks */
-static int purpose_smime(const X509 *x, int ca)
-{
- if (xku_reject(x, XKU_SMIME))
- return 0;
- if (ca) {
- int ca_ret;
- ca_ret = check_ca(x);
- if (!ca_ret)
- return 0;
- /* check nsCertType if present */
- if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA)
- return ca_ret;
- else
- return 0;
- }
- if (x->ex_flags & EXFLAG_NSCERT) {
- if (x->ex_nscert & NS_SMIME)
- return 1;
- /* Workaround for some buggy certificates */
- if (x->ex_nscert & NS_SSL_CLIENT)
- return 2;
- return 0;
- }
- return 1;
-}
-
-static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x,
- int ca)
-{
- int ret;
- ret = purpose_smime(x, ca);
- if (!ret || ca)
- return ret;
- if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION))
- return 0;
- return ret;
-}
-
-static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
- int ca)
-{
- int ret;
- ret = purpose_smime(x, ca);
- if (!ret || ca)
- return ret;
- if (ku_reject(x, KU_KEY_ENCIPHERMENT))
- return 0;
- return ret;
-}
-
-static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
- int ca)
-{
- if (ca) {
- int ca_ret;
- if ((ca_ret = check_ca(x)) != 2)
- return ca_ret;
- else
- return 0;
- }
- if (ku_reject(x, KU_CRL_SIGN))
- return 0;
- return 1;
-}
-
-/*
- * OCSP helper: this is *not* a full OCSP check. It just checks that each CA
- * is valid. Additional checks must be made on the chain.
- */
-
-static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca)
-{
- /*
- * Must be a valid CA. Should we really support the "I don't know" value
- * (2)?
- */
- if (ca)
- return check_ca(x);
- /* leaf certificate is checked in OCSP_verify() */
- return 1;
-}
-
-static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
- int ca)
-{
- int i_ext;
-
- /* If ca is true we must return if this is a valid CA certificate. */
- if (ca)
- return check_ca(x);
-
- /*
- * Check the optional key usage field:
- * if Key Usage is present, it must be one of digitalSignature
- * and/or nonRepudiation (other values are not consistent and shall
- * be rejected).
- */
- if ((x->ex_flags & EXFLAG_KUSAGE)
- && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) ||
- !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE))))
- return 0;
-
- /* Only time stamp key usage is permitted and it's required. */
- if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP)
- return 0;
-
- /* Extended Key Usage MUST be critical */
- i_ext = X509_get_ext_by_NID(x, NID_ext_key_usage, -1);
- if (i_ext >= 0) {
- X509_EXTENSION *ext = X509_get_ext((X509 *)x, i_ext);
- if (!X509_EXTENSION_get_critical(ext))
- return 0;
- }
-
- return 1;
-}
-
-static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca)
-{
- return 1;
-}
-
-/*-
- * Check if certificate I<issuer> is allowed to issue certificate I<subject>
- * according to the B<keyUsage> field of I<issuer> if present
- * depending on any proxyCertInfo extension of I<subject>.
- * Returns 0 for OK, or positive for reason for rejection
- * where reason codes match those for X509_verify_cert().
- */
-int x509_signing_allowed(const X509 *issuer, const X509 *subject)
-{
- if (subject->ex_flags & EXFLAG_PROXY) {
- if (ku_reject(issuer, KU_DIGITAL_SIGNATURE))
- return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE;
- } else if (ku_reject(issuer, KU_KEY_CERT_SIGN))
- return X509_V_ERR_KEYUSAGE_NO_CERTSIGN;
- return X509_V_OK;
-}
-
-/*-
- * Various checks to see if one certificate issued the second.
- * This can be used to prune a set of possible issuer certificates
- * which have been looked up using some simple method such as by
- * subject name.
- * These are:
- * 1. Check issuer_name(subject) == subject_name(issuer)
- * 2. If akid(subject) exists check it matches issuer
- * 3. Check that issuer public key algorithm matches subject signature algorithm
- * 4. If key_usage(issuer) exists check it supports certificate signing
- * returns 0 for OK, positive for reason for mismatch, reasons match
- * codes for X509_verify_cert()
- */
-
-int X509_check_issued(X509 *issuer, X509 *subject)
-{
- int ret;
-
- if ((ret = x509_likely_issued(issuer, subject)) != X509_V_OK)
- return ret;
- return x509_signing_allowed(issuer, subject);
-}
-
-/* do the checks 1., 2., and 3. as described above for X509_check_issued() */
-int x509_likely_issued(X509 *issuer, X509 *subject)
-{
- if (X509_NAME_cmp(X509_get_subject_name(issuer),
- X509_get_issuer_name(subject)))
- return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
-
- x509v3_cache_extensions(issuer);
- if (issuer->ex_flags & EXFLAG_INVALID)
- return X509_V_ERR_UNSPECIFIED;
- x509v3_cache_extensions(subject);
- if (subject->ex_flags & EXFLAG_INVALID)
- return X509_V_ERR_UNSPECIFIED;
-
- if (subject->akid) {
- int ret = X509_check_akid(issuer, subject->akid);
- if (ret != X509_V_OK)
- return ret;
- }
-
- /* check if the subject signature alg matches the issuer's PUBKEY alg */
- return check_sig_alg_match(X509_get0_pubkey(issuer), subject);
-}
-
-int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid)
-{
-
- if (!akid)
- return X509_V_OK;
-
- /* Check key ids (if present) */
- if (akid->keyid && issuer->skid &&
- ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid))
- return X509_V_ERR_AKID_SKID_MISMATCH;
- /* Check serial number */
- if (akid->serial &&
- ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial))
- return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
- /* Check issuer name */
- if (akid->issuer) {
- /*
- * Ugh, for some peculiar reason AKID includes SEQUENCE OF
- * GeneralName. So look for a DirName. There may be more than one but
- * we only take any notice of the first.
- */
- GENERAL_NAMES *gens;
- GENERAL_NAME *gen;
- X509_NAME *nm = NULL;
- int i;
- gens = akid->issuer;
- for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
- gen = sk_GENERAL_NAME_value(gens, i);
- if (gen->type == GEN_DIRNAME) {
- nm = gen->d.dirn;
- break;
- }
- }
- if (nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer)))
- return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
- }
- return X509_V_OK;
-}
-
-uint32_t X509_get_extension_flags(X509 *x)
-{
- /* Call for side-effect of computing hash and caching extensions */
- X509_check_purpose(x, -1, -1);
- return x->ex_flags;
-}
-
-uint32_t X509_get_key_usage(X509 *x)
-{
- /* Call for side-effect of computing hash and caching extensions */
- if (X509_check_purpose(x, -1, -1) != 1)
- return 0;
- if (x->ex_flags & EXFLAG_KUSAGE)
- return x->ex_kusage;
- return UINT32_MAX;
-}
-
-uint32_t X509_get_extended_key_usage(X509 *x)
-{
- /* Call for side-effect of computing hash and caching extensions */
- if (X509_check_purpose(x, -1, -1) != 1)
- return 0;
- if (x->ex_flags & EXFLAG_XKUSAGE)
- return x->ex_xkusage;
- return UINT32_MAX;
-}
-
-const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x)
-{
- /* Call for side-effect of computing hash and caching extensions */
- if (X509_check_purpose(x, -1, -1) != 1)
- return NULL;
- return x->skid;
-}
-
-const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x)
-{
- /* Call for side-effect of computing hash and caching extensions */
- if (X509_check_purpose(x, -1, -1) != 1)
- return NULL;
- return (x->akid != NULL ? x->akid->keyid : NULL);
-}
-
-const GENERAL_NAMES *X509_get0_authority_issuer(X509 *x)
-{
- /* Call for side-effect of computing hash and caching extensions */
- if (X509_check_purpose(x, -1, -1) != 1)
- return NULL;
- return (x->akid != NULL ? x->akid->issuer : NULL);
-}
-
-const ASN1_INTEGER *X509_get0_authority_serial(X509 *x)
-{
- /* Call for side-effect of computing hash and caching extensions */
- if (X509_check_purpose(x, -1, -1) != 1)
- return NULL;
- return (x->akid != NULL ? x->akid->serial : NULL);
-}
-
-long X509_get_pathlen(X509 *x)
-{
- /* Called for side effect of caching extensions */
- if (X509_check_purpose(x, -1, -1) != 1
- || (x->ex_flags & EXFLAG_BCONS) == 0)
- return -1;
- return x->ex_pathlen;
-}
-
-long X509_get_proxy_pathlen(X509 *x)
-{
- /* Called for side effect of caching extensions */
- if (X509_check_purpose(x, -1, -1) != 1
- || (x->ex_flags & EXFLAG_PROXY) == 0)
- return -1;
- return x->ex_pcpathlen;
-}
diff --git a/crypto/x509v3/v3_skey.c b/crypto/x509v3/v3_skey.c
deleted file mode 100644
index c2e82045682a..000000000000
--- a/crypto/x509v3/v3_skey.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/x509v3.h>
-#include "crypto/x509.h"
-#include "ext_dat.h"
-
-static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, char *str);
-const X509V3_EXT_METHOD v3_skey_id = {
- NID_subject_key_identifier, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING),
- 0, 0, 0, 0,
- (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING,
- (X509V3_EXT_S2I)s2i_skey_id,
- 0, 0, 0, 0,
- NULL
-};
-
-char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
- const ASN1_OCTET_STRING *oct)
-{
- return OPENSSL_buf2hexstr(oct->data, oct->length);
-}
-
-ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, const char *str)
-{
- ASN1_OCTET_STRING *oct;
- long length;
-
- if ((oct = ASN1_OCTET_STRING_new()) == NULL) {
- X509V3err(X509V3_F_S2I_ASN1_OCTET_STRING, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- if ((oct->data = OPENSSL_hexstr2buf(str, &length)) == NULL) {
- ASN1_OCTET_STRING_free(oct);
- return NULL;
- }
-
- oct->length = length;
-
- return oct;
-
-}
-
-static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, char *str)
-{
- ASN1_OCTET_STRING *oct;
- X509_PUBKEY *pubkey;
- const unsigned char *pk;
- int pklen;
- unsigned char pkey_dig[EVP_MAX_MD_SIZE];
- unsigned int diglen;
-
- if (strcmp(str, "hash"))
- return s2i_ASN1_OCTET_STRING(method, ctx, str);
-
- if ((oct = ASN1_OCTET_STRING_new()) == NULL) {
- X509V3err(X509V3_F_S2I_SKEY_ID, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- if (ctx && (ctx->flags == CTX_TEST))
- return oct;
-
- if (!ctx || (!ctx->subject_req && !ctx->subject_cert)) {
- X509V3err(X509V3_F_S2I_SKEY_ID, X509V3_R_NO_PUBLIC_KEY);
- goto err;
- }
-
- if (ctx->subject_req)
- pubkey = ctx->subject_req->req_info.pubkey;
- else
- pubkey = ctx->subject_cert->cert_info.key;
-
- if (pubkey == NULL) {
- X509V3err(X509V3_F_S2I_SKEY_ID, X509V3_R_NO_PUBLIC_KEY);
- goto err;
- }
-
- X509_PUBKEY_get0_param(NULL, &pk, &pklen, NULL, pubkey);
-
- if (!EVP_Digest(pk, pklen, pkey_dig, &diglen, EVP_sha1(), NULL))
- goto err;
-
- if (!ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) {
- X509V3err(X509V3_F_S2I_SKEY_ID, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- return oct;
-
- err:
- ASN1_OCTET_STRING_free(oct);
- return NULL;
-}
diff --git a/crypto/x509v3/v3_sxnet.c b/crypto/x509v3/v3_sxnet.c
deleted file mode 100644
index 3c5508f9416c..000000000000
--- a/crypto/x509v3/v3_sxnet.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/conf.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-#include <openssl/x509v3.h>
-#include "ext_dat.h"
-
-/* Support for Thawte strong extranet extension */
-
-#define SXNET_TEST
-
-static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out,
- int indent);
-#ifdef SXNET_TEST
-static SXNET *sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval);
-#endif
-const X509V3_EXT_METHOD v3_sxnet = {
- NID_sxnet, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(SXNET),
- 0, 0, 0, 0,
- 0, 0,
- 0,
-#ifdef SXNET_TEST
- (X509V3_EXT_V2I)sxnet_v2i,
-#else
- 0,
-#endif
- (X509V3_EXT_I2R)sxnet_i2r,
- 0,
- NULL
-};
-
-ASN1_SEQUENCE(SXNETID) = {
- ASN1_SIMPLE(SXNETID, zone, ASN1_INTEGER),
- ASN1_SIMPLE(SXNETID, user, ASN1_OCTET_STRING)
-} ASN1_SEQUENCE_END(SXNETID)
-
-IMPLEMENT_ASN1_FUNCTIONS(SXNETID)
-
-ASN1_SEQUENCE(SXNET) = {
- ASN1_SIMPLE(SXNET, version, ASN1_INTEGER),
- ASN1_SEQUENCE_OF(SXNET, ids, SXNETID)
-} ASN1_SEQUENCE_END(SXNET)
-
-IMPLEMENT_ASN1_FUNCTIONS(SXNET)
-
-static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out,
- int indent)
-{
- int64_t v;
- char *tmp;
- SXNETID *id;
- int i;
-
- /*
- * Since we add 1 to the version number to display it, we don't support
- * LONG_MAX since that would cause on overflow.
- */
- if (!ASN1_INTEGER_get_int64(&v, sx->version)
- || v >= LONG_MAX
- || v < LONG_MIN) {
- BIO_printf(out, "%*sVersion: <unsupported>", indent, "");
- } else {
- long vl = (long)v;
-
- BIO_printf(out, "%*sVersion: %ld (0x%lX)", indent, "", vl + 1, vl);
- }
- for (i = 0; i < sk_SXNETID_num(sx->ids); i++) {
- id = sk_SXNETID_value(sx->ids, i);
- tmp = i2s_ASN1_INTEGER(NULL, id->zone);
- if (tmp == NULL)
- return 0;
- BIO_printf(out, "\n%*sZone: %s, User: ", indent, "", tmp);
- OPENSSL_free(tmp);
- ASN1_STRING_print(out, id->user);
- }
- return 1;
-}
-
-#ifdef SXNET_TEST
-
-/*
- * NBB: this is used for testing only. It should *not* be used for anything
- * else because it will just take static IDs from the configuration file and
- * they should really be separate values for each user.
- */
-
-static SXNET *sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval)
-{
- CONF_VALUE *cnf;
- SXNET *sx = NULL;
- int i;
- for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
- cnf = sk_CONF_VALUE_value(nval, i);
- if (!SXNET_add_id_asc(&sx, cnf->name, cnf->value, -1))
- return NULL;
- }
- return sx;
-}
-
-#endif
-
-/* Strong Extranet utility functions */
-
-/* Add an id given the zone as an ASCII number */
-
-int SXNET_add_id_asc(SXNET **psx, const char *zone, const char *user, int userlen)
-{
- ASN1_INTEGER *izone;
-
- if ((izone = s2i_ASN1_INTEGER(NULL, zone)) == NULL) {
- X509V3err(X509V3_F_SXNET_ADD_ID_ASC, X509V3_R_ERROR_CONVERTING_ZONE);
- return 0;
- }
- return SXNET_add_id_INTEGER(psx, izone, user, userlen);
-}
-
-/* Add an id given the zone as an unsigned long */
-
-int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, const char *user,
- int userlen)
-{
- ASN1_INTEGER *izone;
-
- if ((izone = ASN1_INTEGER_new()) == NULL
- || !ASN1_INTEGER_set(izone, lzone)) {
- X509V3err(X509V3_F_SXNET_ADD_ID_ULONG, ERR_R_MALLOC_FAILURE);
- ASN1_INTEGER_free(izone);
- return 0;
- }
- return SXNET_add_id_INTEGER(psx, izone, user, userlen);
-
-}
-
-/*
- * Add an id given the zone as an ASN1_INTEGER. Note this version uses the
- * passed integer and doesn't make a copy so don't free it up afterwards.
- */
-
-int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *zone, const char *user,
- int userlen)
-{
- SXNET *sx = NULL;
- SXNETID *id = NULL;
- if (!psx || !zone || !user) {
- X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER,
- X509V3_R_INVALID_NULL_ARGUMENT);
- return 0;
- }
- if (userlen == -1)
- userlen = strlen(user);
- if (userlen > 64) {
- X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER, X509V3_R_USER_TOO_LONG);
- return 0;
- }
- if (*psx == NULL) {
- if ((sx = SXNET_new()) == NULL)
- goto err;
- if (!ASN1_INTEGER_set(sx->version, 0))
- goto err;
- *psx = sx;
- } else
- sx = *psx;
- if (SXNET_get_id_INTEGER(sx, zone)) {
- X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER, X509V3_R_DUPLICATE_ZONE_ID);
- return 0;
- }
-
- if ((id = SXNETID_new()) == NULL)
- goto err;
- if (userlen == -1)
- userlen = strlen(user);
-
- if (!ASN1_OCTET_STRING_set(id->user, (const unsigned char *)user, userlen))
- goto err;
- if (!sk_SXNETID_push(sx->ids, id))
- goto err;
- id->zone = zone;
- return 1;
-
- err:
- X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER, ERR_R_MALLOC_FAILURE);
- SXNETID_free(id);
- SXNET_free(sx);
- *psx = NULL;
- return 0;
-}
-
-ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, const char *zone)
-{
- ASN1_INTEGER *izone;
- ASN1_OCTET_STRING *oct;
-
- if ((izone = s2i_ASN1_INTEGER(NULL, zone)) == NULL) {
- X509V3err(X509V3_F_SXNET_GET_ID_ASC, X509V3_R_ERROR_CONVERTING_ZONE);
- return NULL;
- }
- oct = SXNET_get_id_INTEGER(sx, izone);
- ASN1_INTEGER_free(izone);
- return oct;
-}
-
-ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone)
-{
- ASN1_INTEGER *izone;
- ASN1_OCTET_STRING *oct;
-
- if ((izone = ASN1_INTEGER_new()) == NULL
- || !ASN1_INTEGER_set(izone, lzone)) {
- X509V3err(X509V3_F_SXNET_GET_ID_ULONG, ERR_R_MALLOC_FAILURE);
- ASN1_INTEGER_free(izone);
- return NULL;
- }
- oct = SXNET_get_id_INTEGER(sx, izone);
- ASN1_INTEGER_free(izone);
- return oct;
-}
-
-ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone)
-{
- SXNETID *id;
- int i;
- for (i = 0; i < sk_SXNETID_num(sx->ids); i++) {
- id = sk_SXNETID_value(sx->ids, i);
- if (!ASN1_INTEGER_cmp(id->zone, zone))
- return id->user;
- }
- return NULL;
-}
diff --git a/crypto/x509v3/v3_tlsf.c b/crypto/x509v3/v3_tlsf.c
deleted file mode 100644
index 7fd6ef17dbee..000000000000
--- a/crypto/x509v3/v3_tlsf.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "e_os.h"
-#include "internal/cryptlib.h"
-#include <stdio.h>
-#include "internal/o_str.h"
-#include <openssl/asn1t.h>
-#include <openssl/conf.h>
-#include <openssl/x509v3.h>
-#include "ext_dat.h"
-
-static STACK_OF(CONF_VALUE) *i2v_TLS_FEATURE(const X509V3_EXT_METHOD *method,
- TLS_FEATURE *tls_feature,
- STACK_OF(CONF_VALUE) *ext_list);
-static TLS_FEATURE *v2i_TLS_FEATURE(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval);
-
-ASN1_ITEM_TEMPLATE(TLS_FEATURE) =
- ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, TLS_FEATURE, ASN1_INTEGER)
-static_ASN1_ITEM_TEMPLATE_END(TLS_FEATURE)
-
-IMPLEMENT_ASN1_ALLOC_FUNCTIONS(TLS_FEATURE)
-
-const X509V3_EXT_METHOD v3_tls_feature = {
- NID_tlsfeature, 0,
- ASN1_ITEM_ref(TLS_FEATURE),
- 0, 0, 0, 0,
- 0, 0,
- (X509V3_EXT_I2V)i2v_TLS_FEATURE,
- (X509V3_EXT_V2I)v2i_TLS_FEATURE,
- 0, 0,
- NULL
-};
-
-
-typedef struct {
- long num;
- const char *name;
-} TLS_FEATURE_NAME;
-
-static TLS_FEATURE_NAME tls_feature_tbl[] = {
- { 5, "status_request" },
- { 17, "status_request_v2" }
-};
-
-/*
- * i2v_TLS_FEATURE converts the TLS_FEATURE structure tls_feature into the
- * STACK_OF(CONF_VALUE) structure ext_list. STACK_OF(CONF_VALUE) is the format
- * used by the CONF library to represent a multi-valued extension. ext_list is
- * returned.
- */
-static STACK_OF(CONF_VALUE) *i2v_TLS_FEATURE(const X509V3_EXT_METHOD *method,
- TLS_FEATURE *tls_feature,
- STACK_OF(CONF_VALUE) *ext_list)
-{
- int i;
- size_t j;
- ASN1_INTEGER *ai;
- long tlsextid;
- for (i = 0; i < sk_ASN1_INTEGER_num(tls_feature); i++) {
- ai = sk_ASN1_INTEGER_value(tls_feature, i);
- tlsextid = ASN1_INTEGER_get(ai);
- for (j = 0; j < OSSL_NELEM(tls_feature_tbl); j++)
- if (tlsextid == tls_feature_tbl[j].num)
- break;
- if (j < OSSL_NELEM(tls_feature_tbl))
- X509V3_add_value(NULL, tls_feature_tbl[j].name, &ext_list);
- else
- X509V3_add_value_int(NULL, ai, &ext_list);
- }
- return ext_list;
-}
-
-/*
- * v2i_TLS_FEATURE converts the multi-valued extension nval into a TLS_FEATURE
- * structure, which is returned if the conversion is successful. In case of
- * error, NULL is returned.
- */
-static TLS_FEATURE *v2i_TLS_FEATURE(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
-{
- TLS_FEATURE *tlsf;
- char *extval, *endptr;
- ASN1_INTEGER *ai;
- CONF_VALUE *val;
- int i;
- size_t j;
- long tlsextid;
-
- if ((tlsf = sk_ASN1_INTEGER_new_null()) == NULL) {
- X509V3err(X509V3_F_V2I_TLS_FEATURE, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
- val = sk_CONF_VALUE_value(nval, i);
- if (val->value)
- extval = val->value;
- else
- extval = val->name;
-
- for (j = 0; j < OSSL_NELEM(tls_feature_tbl); j++)
- if (strcasecmp(extval, tls_feature_tbl[j].name) == 0)
- break;
- if (j < OSSL_NELEM(tls_feature_tbl))
- tlsextid = tls_feature_tbl[j].num;
- else {
- tlsextid = strtol(extval, &endptr, 10);
- if (((*endptr) != '\0') || (extval == endptr) || (tlsextid < 0) ||
- (tlsextid > 65535)) {
- X509V3err(X509V3_F_V2I_TLS_FEATURE, X509V3_R_INVALID_SYNTAX);
- X509V3_conf_err(val);
- goto err;
- }
- }
-
- if ((ai = ASN1_INTEGER_new()) == NULL
- || !ASN1_INTEGER_set(ai, tlsextid)
- || sk_ASN1_INTEGER_push(tlsf, ai) <= 0) {
- X509V3err(X509V3_F_V2I_TLS_FEATURE, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
- return tlsf;
-
- err:
- sk_ASN1_INTEGER_pop_free(tlsf, ASN1_INTEGER_free);
- return NULL;
-}
diff --git a/crypto/x509v3/v3_utl.c b/crypto/x509v3/v3_utl.c
deleted file mode 100644
index eac78259fc82..000000000000
--- a/crypto/x509v3/v3_utl.c
+++ /dev/null
@@ -1,1289 +0,0 @@
-/*
- * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/* X509 v3 extension utilities */
-
-#include "e_os.h"
-#include "internal/cryptlib.h"
-#include <stdio.h>
-#include <string.h>
-#include "crypto/ctype.h"
-#include <openssl/conf.h>
-#include <openssl/crypto.h>
-#include <openssl/x509v3.h>
-#include "crypto/x509.h"
-#include <openssl/bn.h>
-#include "ext_dat.h"
-
-static char *strip_spaces(char *name);
-static int sk_strcmp(const char *const *a, const char *const *b);
-static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
- GENERAL_NAMES *gens);
-static void str_free(OPENSSL_STRING str);
-static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, const ASN1_IA5STRING *email);
-
-static int ipv4_from_asc(unsigned char *v4, const char *in);
-static int ipv6_from_asc(unsigned char *v6, const char *in);
-static int ipv6_cb(const char *elem, int len, void *usr);
-static int ipv6_hex(unsigned char *out, const char *in, int inlen);
-
-/* Add a CONF_VALUE name value pair to stack */
-
-static int x509v3_add_len_value(const char *name, const char *value,
- size_t vallen, STACK_OF(CONF_VALUE) **extlist)
-{
- CONF_VALUE *vtmp = NULL;
- char *tname = NULL, *tvalue = NULL;
- int sk_allocated = (*extlist == NULL);
-
- if (name != NULL && (tname = OPENSSL_strdup(name)) == NULL)
- goto err;
- if (value != NULL && vallen > 0) {
- /*
- * We tolerate a single trailing NUL character, but otherwise no
- * embedded NULs
- */
- if (memchr(value, 0, vallen - 1) != NULL)
- goto err;
- tvalue = OPENSSL_strndup(value, vallen);
- if (tvalue == NULL)
- goto err;
- }
- if ((vtmp = OPENSSL_malloc(sizeof(*vtmp))) == NULL)
- goto err;
- if (sk_allocated && (*extlist = sk_CONF_VALUE_new_null()) == NULL)
- goto err;
- vtmp->section = NULL;
- vtmp->name = tname;
- vtmp->value = tvalue;
- if (!sk_CONF_VALUE_push(*extlist, vtmp))
- goto err;
- return 1;
- err:
- X509V3err(X509V3_F_X509V3_ADD_LEN_VALUE, ERR_R_MALLOC_FAILURE);
- if (sk_allocated) {
- sk_CONF_VALUE_free(*extlist);
- *extlist = NULL;
- }
- OPENSSL_free(vtmp);
- OPENSSL_free(tname);
- OPENSSL_free(tvalue);
- return 0;
-}
-
-int X509V3_add_value(const char *name, const char *value,
- STACK_OF(CONF_VALUE) **extlist)
-{
- return x509v3_add_len_value(name, value,
- value != NULL ? strlen((const char *)value) : 0,
- extlist);
-}
-
-int X509V3_add_value_uchar(const char *name, const unsigned char *value,
- STACK_OF(CONF_VALUE) **extlist)
-{
- return x509v3_add_len_value(name, (const char *)value,
- value != NULL ? strlen((const char *)value) : 0,
- extlist);
-}
-
-int x509v3_add_len_value_uchar(const char *name, const unsigned char *value,
- size_t vallen, STACK_OF(CONF_VALUE) **extlist)
-{
- return x509v3_add_len_value(name, (const char *)value, vallen, extlist);
-}
-
-/* Free function for STACK_OF(CONF_VALUE) */
-
-void X509V3_conf_free(CONF_VALUE *conf)
-{
- if (!conf)
- return;
- OPENSSL_free(conf->name);
- OPENSSL_free(conf->value);
- OPENSSL_free(conf->section);
- OPENSSL_free(conf);
-}
-
-int X509V3_add_value_bool(const char *name, int asn1_bool,
- STACK_OF(CONF_VALUE) **extlist)
-{
- if (asn1_bool)
- return X509V3_add_value(name, "TRUE", extlist);
- return X509V3_add_value(name, "FALSE", extlist);
-}
-
-int X509V3_add_value_bool_nf(const char *name, int asn1_bool,
- STACK_OF(CONF_VALUE) **extlist)
-{
- if (asn1_bool)
- return X509V3_add_value(name, "TRUE", extlist);
- return 1;
-}
-
-static char *bignum_to_string(const BIGNUM *bn)
-{
- char *tmp, *ret;
- size_t len;
-
- /*
- * Display large numbers in hex and small numbers in decimal. Converting to
- * decimal takes quadratic time and is no more useful than hex for large
- * numbers.
- */
- if (BN_num_bits(bn) < 128)
- return BN_bn2dec(bn);
-
- tmp = BN_bn2hex(bn);
- if (tmp == NULL)
- return NULL;
-
- len = strlen(tmp) + 3;
- ret = OPENSSL_malloc(len);
- if (ret == NULL) {
- X509V3err(X509V3_F_BIGNUM_TO_STRING, ERR_R_MALLOC_FAILURE);
- OPENSSL_free(tmp);
- return NULL;
- }
-
- /* Prepend "0x", but place it after the "-" if negative. */
- if (tmp[0] == '-') {
- OPENSSL_strlcpy(ret, "-0x", len);
- OPENSSL_strlcat(ret, tmp + 1, len);
- } else {
- OPENSSL_strlcpy(ret, "0x", len);
- OPENSSL_strlcat(ret, tmp, len);
- }
- OPENSSL_free(tmp);
- return ret;
-}
-
-char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *a)
-{
- BIGNUM *bntmp = NULL;
- char *strtmp = NULL;
-
- if (!a)
- return NULL;
- if ((bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) == NULL
- || (strtmp = bignum_to_string(bntmp)) == NULL)
- X509V3err(X509V3_F_I2S_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE);
- BN_free(bntmp);
- return strtmp;
-}
-
-char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, const ASN1_INTEGER *a)
-{
- BIGNUM *bntmp = NULL;
- char *strtmp = NULL;
-
- if (!a)
- return NULL;
- if ((bntmp = ASN1_INTEGER_to_BN(a, NULL)) == NULL
- || (strtmp = bignum_to_string(bntmp)) == NULL)
- X509V3err(X509V3_F_I2S_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
- BN_free(bntmp);
- return strtmp;
-}
-
-ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value)
-{
- BIGNUM *bn = NULL;
- ASN1_INTEGER *aint;
- int isneg, ishex;
- int ret;
- if (value == NULL) {
- X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_INVALID_NULL_VALUE);
- return NULL;
- }
- bn = BN_new();
- if (bn == NULL) {
- X509V3err(X509V3_F_S2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- if (value[0] == '-') {
- value++;
- isneg = 1;
- } else
- isneg = 0;
-
- if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
- value += 2;
- ishex = 1;
- } else
- ishex = 0;
-
- if (ishex)
- ret = BN_hex2bn(&bn, value);
- else
- ret = BN_dec2bn(&bn, value);
-
- if (!ret || value[ret]) {
- BN_free(bn);
- X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_BN_DEC2BN_ERROR);
- return NULL;
- }
-
- if (isneg && BN_is_zero(bn))
- isneg = 0;
-
- aint = BN_to_ASN1_INTEGER(bn, NULL);
- BN_free(bn);
- if (!aint) {
- X509V3err(X509V3_F_S2I_ASN1_INTEGER,
- X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
- return NULL;
- }
- if (isneg)
- aint->type |= V_ASN1_NEG;
- return aint;
-}
-
-int X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint,
- STACK_OF(CONF_VALUE) **extlist)
-{
- char *strtmp;
- int ret;
-
- if (!aint)
- return 1;
- if ((strtmp = i2s_ASN1_INTEGER(NULL, aint)) == NULL)
- return 0;
- ret = X509V3_add_value(name, strtmp, extlist);
- OPENSSL_free(strtmp);
- return ret;
-}
-
-int X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool)
-{
- const char *btmp;
-
- if ((btmp = value->value) == NULL)
- goto err;
- if (strcmp(btmp, "TRUE") == 0
- || strcmp(btmp, "true") == 0
- || strcmp(btmp, "Y") == 0
- || strcmp(btmp, "y") == 0
- || strcmp(btmp, "YES") == 0
- || strcmp(btmp, "yes") == 0) {
- *asn1_bool = 0xff;
- return 1;
- }
- if (strcmp(btmp, "FALSE") == 0
- || strcmp(btmp, "false") == 0
- || strcmp(btmp, "N") == 0
- || strcmp(btmp, "n") == 0
- || strcmp(btmp, "NO") == 0
- || strcmp(btmp, "no") == 0) {
- *asn1_bool = 0;
- return 1;
- }
- err:
- X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,
- X509V3_R_INVALID_BOOLEAN_STRING);
- X509V3_conf_err(value);
- return 0;
-}
-
-int X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint)
-{
- ASN1_INTEGER *itmp;
-
- if ((itmp = s2i_ASN1_INTEGER(NULL, value->value)) == NULL) {
- X509V3_conf_err(value);
- return 0;
- }
- *aint = itmp;
- return 1;
-}
-
-#define HDR_NAME 1
-#define HDR_VALUE 2
-
-/*
- * #define DEBUG
- */
-
-STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
-{
- char *p, *q, c;
- char *ntmp, *vtmp;
- STACK_OF(CONF_VALUE) *values = NULL;
- char *linebuf;
- int state;
- /* We are going to modify the line so copy it first */
- linebuf = OPENSSL_strdup(line);
- if (linebuf == NULL) {
- X509V3err(X509V3_F_X509V3_PARSE_LIST, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- state = HDR_NAME;
- ntmp = NULL;
- /* Go through all characters */
- for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n');
- p++) {
-
- switch (state) {
- case HDR_NAME:
- if (c == ':') {
- state = HDR_VALUE;
- *p = 0;
- ntmp = strip_spaces(q);
- if (!ntmp) {
- X509V3err(X509V3_F_X509V3_PARSE_LIST,
- X509V3_R_INVALID_NULL_NAME);
- goto err;
- }
- q = p + 1;
- } else if (c == ',') {
- *p = 0;
- ntmp = strip_spaces(q);
- q = p + 1;
- if (!ntmp) {
- X509V3err(X509V3_F_X509V3_PARSE_LIST,
- X509V3_R_INVALID_NULL_NAME);
- goto err;
- }
- X509V3_add_value(ntmp, NULL, &values);
- }
- break;
-
- case HDR_VALUE:
- if (c == ',') {
- state = HDR_NAME;
- *p = 0;
- vtmp = strip_spaces(q);
- if (!vtmp) {
- X509V3err(X509V3_F_X509V3_PARSE_LIST,
- X509V3_R_INVALID_NULL_VALUE);
- goto err;
- }
- X509V3_add_value(ntmp, vtmp, &values);
- ntmp = NULL;
- q = p + 1;
- }
-
- }
- }
-
- if (state == HDR_VALUE) {
- vtmp = strip_spaces(q);
- if (!vtmp) {
- X509V3err(X509V3_F_X509V3_PARSE_LIST,
- X509V3_R_INVALID_NULL_VALUE);
- goto err;
- }
- X509V3_add_value(ntmp, vtmp, &values);
- } else {
- ntmp = strip_spaces(q);
- if (!ntmp) {
- X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
- goto err;
- }
- X509V3_add_value(ntmp, NULL, &values);
- }
- OPENSSL_free(linebuf);
- return values;
-
- err:
- OPENSSL_free(linebuf);
- sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
- return NULL;
-
-}
-
-/* Delete leading and trailing spaces from a string */
-static char *strip_spaces(char *name)
-{
- char *p, *q;
- /* Skip over leading spaces */
- p = name;
- while (*p && ossl_isspace(*p))
- p++;
- if (!*p)
- return NULL;
- q = p + strlen(p) - 1;
- while ((q != p) && ossl_isspace(*q))
- q--;
- if (p != q)
- q[1] = 0;
- if (!*p)
- return NULL;
- return p;
-}
-
-
-/*
- * V2I name comparison function: returns zero if 'name' matches cmp or cmp.*
- */
-
-int name_cmp(const char *name, const char *cmp)
-{
- int len, ret;
- char c;
- len = strlen(cmp);
- if ((ret = strncmp(name, cmp, len)))
- return ret;
- c = name[len];
- if (!c || (c == '.'))
- return 0;
- return 1;
-}
-
-static int sk_strcmp(const char *const *a, const char *const *b)
-{
- return strcmp(*a, *b);
-}
-
-STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x)
-{
- GENERAL_NAMES *gens;
- STACK_OF(OPENSSL_STRING) *ret;
-
- gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
- ret = get_email(X509_get_subject_name(x), gens);
- sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
- return ret;
-}
-
-STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x)
-{
- AUTHORITY_INFO_ACCESS *info;
- STACK_OF(OPENSSL_STRING) *ret = NULL;
- int i;
-
- info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
- if (!info)
- return NULL;
- for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
- ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
- if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) {
- if (ad->location->type == GEN_URI) {
- if (!append_ia5
- (&ret, ad->location->d.uniformResourceIdentifier))
- break;
- }
- }
- }
- AUTHORITY_INFO_ACCESS_free(info);
- return ret;
-}
-
-STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x)
-{
- GENERAL_NAMES *gens;
- STACK_OF(X509_EXTENSION) *exts;
- STACK_OF(OPENSSL_STRING) *ret;
-
- exts = X509_REQ_get_extensions(x);
- gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
- ret = get_email(X509_REQ_get_subject_name(x), gens);
- sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
- sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
- return ret;
-}
-
-static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
- GENERAL_NAMES *gens)
-{
- STACK_OF(OPENSSL_STRING) *ret = NULL;
- X509_NAME_ENTRY *ne;
- const ASN1_IA5STRING *email;
- GENERAL_NAME *gen;
- int i = -1;
-
- /* Now add any email address(es) to STACK */
- /* First supplied X509_NAME */
- while ((i = X509_NAME_get_index_by_NID(name,
- NID_pkcs9_emailAddress, i)) >= 0) {
- ne = X509_NAME_get_entry(name, i);
- email = X509_NAME_ENTRY_get_data(ne);
- if (!append_ia5(&ret, email))
- return NULL;
- }
- for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
- gen = sk_GENERAL_NAME_value(gens, i);
- if (gen->type != GEN_EMAIL)
- continue;
- if (!append_ia5(&ret, gen->d.ia5))
- return NULL;
- }
- return ret;
-}
-
-static void str_free(OPENSSL_STRING str)
-{
- OPENSSL_free(str);
-}
-
-static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, const ASN1_IA5STRING *email)
-{
- char *emtmp;
- /* First some sanity checks */
- if (email->type != V_ASN1_IA5STRING)
- return 1;
- if (email->data == NULL || email->length == 0)
- return 1;
- if (memchr(email->data, 0, email->length) != NULL)
- return 1;
- if (*sk == NULL)
- *sk = sk_OPENSSL_STRING_new(sk_strcmp);
- if (*sk == NULL)
- return 0;
-
- emtmp = OPENSSL_strndup((char *)email->data, email->length);
- if (emtmp == NULL) {
- X509_email_free(*sk);
- *sk = NULL;
- return 0;
- }
-
- /* Don't add duplicates */
- if (sk_OPENSSL_STRING_find(*sk, emtmp) != -1) {
- OPENSSL_free(emtmp);
- return 1;
- }
- if (!sk_OPENSSL_STRING_push(*sk, emtmp)) {
- OPENSSL_free(emtmp); /* free on push failure */
- X509_email_free(*sk);
- *sk = NULL;
- return 0;
- }
- return 1;
-}
-
-void X509_email_free(STACK_OF(OPENSSL_STRING) *sk)
-{
- sk_OPENSSL_STRING_pop_free(sk, str_free);
-}
-
-typedef int (*equal_fn) (const unsigned char *pattern, size_t pattern_len,
- const unsigned char *subject, size_t subject_len,
- unsigned int flags);
-
-/* Skip pattern prefix to match "wildcard" subject */
-static void skip_prefix(const unsigned char **p, size_t *plen,
- size_t subject_len,
- unsigned int flags)
-{
- const unsigned char *pattern = *p;
- size_t pattern_len = *plen;
-
- /*
- * If subject starts with a leading '.' followed by more octets, and
- * pattern is longer, compare just an equal-length suffix with the
- * full subject (starting at the '.'), provided the prefix contains
- * no NULs.
- */
- if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0)
- return;
-
- while (pattern_len > subject_len && *pattern) {
- if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) &&
- *pattern == '.')
- break;
- ++pattern;
- --pattern_len;
- }
-
- /* Skip if entire prefix acceptable */
- if (pattern_len == subject_len) {
- *p = pattern;
- *plen = pattern_len;
- }
-}
-
-/* Compare while ASCII ignoring case. */
-static int equal_nocase(const unsigned char *pattern, size_t pattern_len,
- const unsigned char *subject, size_t subject_len,
- unsigned int flags)
-{
- skip_prefix(&pattern, &pattern_len, subject_len, flags);
- if (pattern_len != subject_len)
- return 0;
- while (pattern_len) {
- unsigned char l = *pattern;
- unsigned char r = *subject;
- /* The pattern must not contain NUL characters. */
- if (l == 0)
- return 0;
- if (l != r) {
- if ('A' <= l && l <= 'Z')
- l = (l - 'A') + 'a';
- if ('A' <= r && r <= 'Z')
- r = (r - 'A') + 'a';
- if (l != r)
- return 0;
- }
- ++pattern;
- ++subject;
- --pattern_len;
- }
- return 1;
-}
-
-/* Compare using memcmp. */
-static int equal_case(const unsigned char *pattern, size_t pattern_len,
- const unsigned char *subject, size_t subject_len,
- unsigned int flags)
-{
- skip_prefix(&pattern, &pattern_len, subject_len, flags);
- if (pattern_len != subject_len)
- return 0;
- return !memcmp(pattern, subject, pattern_len);
-}
-
-/*
- * RFC 5280, section 7.5, requires that only the domain is compared in a
- * case-insensitive manner.
- */
-static int equal_email(const unsigned char *a, size_t a_len,
- const unsigned char *b, size_t b_len,
- unsigned int unused_flags)
-{
- size_t i = a_len;
- if (a_len != b_len)
- return 0;
- /*
- * We search backwards for the '@' character, so that we do not have to
- * deal with quoted local-parts. The domain part is compared in a
- * case-insensitive manner.
- */
- while (i > 0) {
- --i;
- if (a[i] == '@' || b[i] == '@') {
- if (!equal_nocase(a + i, a_len - i, b + i, a_len - i, 0))
- return 0;
- break;
- }
- }
- if (i == 0)
- i = a_len;
- return equal_case(a, i, b, i, 0);
-}
-
-/*
- * Compare the prefix and suffix with the subject, and check that the
- * characters in-between are valid.
- */
-static int wildcard_match(const unsigned char *prefix, size_t prefix_len,
- const unsigned char *suffix, size_t suffix_len,
- const unsigned char *subject, size_t subject_len,
- unsigned int flags)
-{
- const unsigned char *wildcard_start;
- const unsigned char *wildcard_end;
- const unsigned char *p;
- int allow_multi = 0;
- int allow_idna = 0;
-
- if (subject_len < prefix_len + suffix_len)
- return 0;
- if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags))
- return 0;
- wildcard_start = subject + prefix_len;
- wildcard_end = subject + (subject_len - suffix_len);
- if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags))
- return 0;
- /*
- * If the wildcard makes up the entire first label, it must match at
- * least one character.
- */
- if (prefix_len == 0 && *suffix == '.') {
- if (wildcard_start == wildcard_end)
- return 0;
- allow_idna = 1;
- if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS)
- allow_multi = 1;
- }
- /* IDNA labels cannot match partial wildcards */
- if (!allow_idna &&
- subject_len >= 4 && strncasecmp((char *)subject, "xn--", 4) == 0)
- return 0;
- /* The wildcard may match a literal '*' */
- if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*')
- return 1;
- /*
- * Check that the part matched by the wildcard contains only
- * permitted characters and only matches a single label unless
- * allow_multi is set.
- */
- for (p = wildcard_start; p != wildcard_end; ++p)
- if (!(('0' <= *p && *p <= '9') ||
- ('A' <= *p && *p <= 'Z') ||
- ('a' <= *p && *p <= 'z') ||
- *p == '-' || (allow_multi && *p == '.')))
- return 0;
- return 1;
-}
-
-#define LABEL_START (1 << 0)
-#define LABEL_END (1 << 1)
-#define LABEL_HYPHEN (1 << 2)
-#define LABEL_IDNA (1 << 3)
-
-static const unsigned char *valid_star(const unsigned char *p, size_t len,
- unsigned int flags)
-{
- const unsigned char *star = 0;
- size_t i;
- int state = LABEL_START;
- int dots = 0;
- for (i = 0; i < len; ++i) {
- /*
- * Locate first and only legal wildcard, either at the start
- * or end of a non-IDNA first and not final label.
- */
- if (p[i] == '*') {
- int atstart = (state & LABEL_START);
- int atend = (i == len - 1 || p[i + 1] == '.');
- /*-
- * At most one wildcard per pattern.
- * No wildcards in IDNA labels.
- * No wildcards after the first label.
- */
- if (star != NULL || (state & LABEL_IDNA) != 0 || dots)
- return NULL;
- /* Only full-label '*.example.com' wildcards? */
- if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS)
- && (!atstart || !atend))
- return NULL;
- /* No 'foo*bar' wildcards */
- if (!atstart && !atend)
- return NULL;
- star = &p[i];
- state &= ~LABEL_START;
- } else if (('a' <= p[i] && p[i] <= 'z')
- || ('A' <= p[i] && p[i] <= 'Z')
- || ('0' <= p[i] && p[i] <= '9')) {
- if ((state & LABEL_START) != 0
- && len - i >= 4 && strncasecmp((char *)&p[i], "xn--", 4) == 0)
- state |= LABEL_IDNA;
- state &= ~(LABEL_HYPHEN | LABEL_START);
- } else if (p[i] == '.') {
- if ((state & (LABEL_HYPHEN | LABEL_START)) != 0)
- return NULL;
- state = LABEL_START;
- ++dots;
- } else if (p[i] == '-') {
- /* no domain/subdomain starts with '-' */
- if ((state & LABEL_START) != 0)
- return NULL;
- state |= LABEL_HYPHEN;
- } else
- return NULL;
- }
-
- /*
- * The final label must not end in a hyphen or ".", and
- * there must be at least two dots after the star.
- */
- if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2)
- return NULL;
- return star;
-}
-
-/* Compare using wildcards. */
-static int equal_wildcard(const unsigned char *pattern, size_t pattern_len,
- const unsigned char *subject, size_t subject_len,
- unsigned int flags)
-{
- const unsigned char *star = NULL;
-
- /*
- * Subject names starting with '.' can only match a wildcard pattern
- * via a subject sub-domain pattern suffix match.
- */
- if (!(subject_len > 1 && subject[0] == '.'))
- star = valid_star(pattern, pattern_len, flags);
- if (star == NULL)
- return equal_nocase(pattern, pattern_len,
- subject, subject_len, flags);
- return wildcard_match(pattern, star - pattern,
- star + 1, (pattern + pattern_len) - star - 1,
- subject, subject_len, flags);
-}
-
-/*
- * Compare an ASN1_STRING to a supplied string. If they match return 1. If
- * cmp_type > 0 only compare if string matches the type, otherwise convert it
- * to UTF8.
- */
-
-static int do_check_string(const ASN1_STRING *a, int cmp_type, equal_fn equal,
- unsigned int flags, const char *b, size_t blen,
- char **peername)
-{
- int rv = 0;
-
- if (!a->data || !a->length)
- return 0;
- if (cmp_type > 0) {
- if (cmp_type != a->type)
- return 0;
- if (cmp_type == V_ASN1_IA5STRING)
- rv = equal(a->data, a->length, (unsigned char *)b, blen, flags);
- else if (a->length == (int)blen && !memcmp(a->data, b, blen))
- rv = 1;
- if (rv > 0 && peername != NULL) {
- *peername = OPENSSL_strndup((char *)a->data, a->length);
- if (*peername == NULL)
- return -1;
- }
- } else {
- int astrlen;
- unsigned char *astr;
- astrlen = ASN1_STRING_to_UTF8(&astr, a);
- if (astrlen < 0) {
- /*
- * -1 could be an internal malloc failure or a decoding error from
- * malformed input; we can't distinguish.
- */
- return -1;
- }
- rv = equal(astr, astrlen, (unsigned char *)b, blen, flags);
- if (rv > 0 && peername != NULL) {
- *peername = OPENSSL_strndup((char *)astr, astrlen);
- if (*peername == NULL) {
- OPENSSL_free(astr);
- return -1;
- }
- }
- OPENSSL_free(astr);
- }
- return rv;
-}
-
-static int do_x509_check(X509 *x, const char *chk, size_t chklen,
- unsigned int flags, int check_type, char **peername)
-{
- GENERAL_NAMES *gens = NULL;
- X509_NAME *name = NULL;
- int i;
- int cnid = NID_undef;
- int alt_type;
- int san_present = 0;
- int rv = 0;
- equal_fn equal;
-
- /* See below, this flag is internal-only */
- flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS;
- if (check_type == GEN_EMAIL) {
- cnid = NID_pkcs9_emailAddress;
- alt_type = V_ASN1_IA5STRING;
- equal = equal_email;
- } else if (check_type == GEN_DNS) {
- cnid = NID_commonName;
- /* Implicit client-side DNS sub-domain pattern */
- if (chklen > 1 && chk[0] == '.')
- flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS;
- alt_type = V_ASN1_IA5STRING;
- if (flags & X509_CHECK_FLAG_NO_WILDCARDS)
- equal = equal_nocase;
- else
- equal = equal_wildcard;
- } else {
- alt_type = V_ASN1_OCTET_STRING;
- equal = equal_case;
- }
-
- if (chklen == 0)
- chklen = strlen(chk);
-
- gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
- if (gens) {
- for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
- GENERAL_NAME *gen;
- ASN1_STRING *cstr;
- gen = sk_GENERAL_NAME_value(gens, i);
- if (gen->type != check_type)
- continue;
- san_present = 1;
- if (check_type == GEN_EMAIL)
- cstr = gen->d.rfc822Name;
- else if (check_type == GEN_DNS)
- cstr = gen->d.dNSName;
- else
- cstr = gen->d.iPAddress;
- /* Positive on success, negative on error! */
- if ((rv = do_check_string(cstr, alt_type, equal, flags,
- chk, chklen, peername)) != 0)
- break;
- }
- GENERAL_NAMES_free(gens);
- if (rv != 0)
- return rv;
- if (san_present && !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT))
- return 0;
- }
-
- /* We're done if CN-ID is not pertinent */
- if (cnid == NID_undef || (flags & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT))
- return 0;
-
- i = -1;
- name = X509_get_subject_name(x);
- while ((i = X509_NAME_get_index_by_NID(name, cnid, i)) >= 0) {
- const X509_NAME_ENTRY *ne = X509_NAME_get_entry(name, i);
- const ASN1_STRING *str = X509_NAME_ENTRY_get_data(ne);
-
- /* Positive on success, negative on error! */
- if ((rv = do_check_string(str, -1, equal, flags,
- chk, chklen, peername)) != 0)
- return rv;
- }
- return 0;
-}
-
-int X509_check_host(X509 *x, const char *chk, size_t chklen,
- unsigned int flags, char **peername)
-{
- if (chk == NULL)
- return -2;
- /*
- * Embedded NULs are disallowed, except as the last character of a
- * string of length 2 or more (tolerate caller including terminating
- * NUL in string length).
- */
- if (chklen == 0)
- chklen = strlen(chk);
- else if (memchr(chk, '\0', chklen > 1 ? chklen - 1 : chklen))
- return -2;
- if (chklen > 1 && chk[chklen - 1] == '\0')
- --chklen;
- return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername);
-}
-
-int X509_check_email(X509 *x, const char *chk, size_t chklen,
- unsigned int flags)
-{
- if (chk == NULL)
- return -2;
- /*
- * Embedded NULs are disallowed, except as the last character of a
- * string of length 2 or more (tolerate caller including terminating
- * NUL in string length).
- */
- if (chklen == 0)
- chklen = strlen((char *)chk);
- else if (memchr(chk, '\0', chklen > 1 ? chklen - 1 : chklen))
- return -2;
- if (chklen > 1 && chk[chklen - 1] == '\0')
- --chklen;
- return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL);
-}
-
-int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
- unsigned int flags)
-{
- if (chk == NULL)
- return -2;
- return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL);
-}
-
-int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
-{
- unsigned char ipout[16];
- size_t iplen;
-
- if (ipasc == NULL)
- return -2;
- iplen = (size_t)a2i_ipadd(ipout, ipasc);
- if (iplen == 0)
- return -2;
- return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
-}
-
-/*
- * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible
- * with RFC3280.
- */
-
-ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
-{
- unsigned char ipout[16];
- ASN1_OCTET_STRING *ret;
- int iplen;
-
- /* If string contains a ':' assume IPv6 */
-
- iplen = a2i_ipadd(ipout, ipasc);
-
- if (!iplen)
- return NULL;
-
- ret = ASN1_OCTET_STRING_new();
- if (ret == NULL)
- return NULL;
- if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) {
- ASN1_OCTET_STRING_free(ret);
- return NULL;
- }
- return ret;
-}
-
-ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
-{
- ASN1_OCTET_STRING *ret = NULL;
- unsigned char ipout[32];
- char *iptmp = NULL, *p;
- int iplen1, iplen2;
- p = strchr(ipasc, '/');
- if (!p)
- return NULL;
- iptmp = OPENSSL_strdup(ipasc);
- if (!iptmp)
- return NULL;
- p = iptmp + (p - ipasc);
- *p++ = 0;
-
- iplen1 = a2i_ipadd(ipout, iptmp);
-
- if (!iplen1)
- goto err;
-
- iplen2 = a2i_ipadd(ipout + iplen1, p);
-
- OPENSSL_free(iptmp);
- iptmp = NULL;
-
- if (!iplen2 || (iplen1 != iplen2))
- goto err;
-
- ret = ASN1_OCTET_STRING_new();
- if (ret == NULL)
- goto err;
- if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
- goto err;
-
- return ret;
-
- err:
- OPENSSL_free(iptmp);
- ASN1_OCTET_STRING_free(ret);
- return NULL;
-}
-
-int a2i_ipadd(unsigned char *ipout, const char *ipasc)
-{
- /* If string contains a ':' assume IPv6 */
-
- if (strchr(ipasc, ':')) {
- if (!ipv6_from_asc(ipout, ipasc))
- return 0;
- return 16;
- } else {
- if (!ipv4_from_asc(ipout, ipasc))
- return 0;
- return 4;
- }
-}
-
-static int ipv4_from_asc(unsigned char *v4, const char *in)
-{
- const char *p;
- int a0, a1, a2, a3, n;
-
- if (sscanf(in, "%d.%d.%d.%d%n", &a0, &a1, &a2, &a3, &n) != 4)
- return 0;
- if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
- || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
- return 0;
- p = in + n;
- if (!(*p == '\0' || ossl_isspace(*p)))
- return 0;
- v4[0] = a0;
- v4[1] = a1;
- v4[2] = a2;
- v4[3] = a3;
- return 1;
-}
-
-typedef struct {
- /* Temporary store for IPV6 output */
- unsigned char tmp[16];
- /* Total number of bytes in tmp */
- int total;
- /* The position of a zero (corresponding to '::') */
- int zero_pos;
- /* Number of zeroes */
- int zero_cnt;
-} IPV6_STAT;
-
-static int ipv6_from_asc(unsigned char *v6, const char *in)
-{
- IPV6_STAT v6stat;
- v6stat.total = 0;
- v6stat.zero_pos = -1;
- v6stat.zero_cnt = 0;
- /*
- * Treat the IPv6 representation as a list of values separated by ':'.
- * The presence of a '::' will parse as one, two or three zero length
- * elements.
- */
- if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
- return 0;
-
- /* Now for some sanity checks */
-
- if (v6stat.zero_pos == -1) {
- /* If no '::' must have exactly 16 bytes */
- if (v6stat.total != 16)
- return 0;
- } else {
- /* If '::' must have less than 16 bytes */
- if (v6stat.total == 16)
- return 0;
- /* More than three zeroes is an error */
- if (v6stat.zero_cnt > 3)
- return 0;
- /* Can only have three zeroes if nothing else present */
- else if (v6stat.zero_cnt == 3) {
- if (v6stat.total > 0)
- return 0;
- }
- /* Can only have two zeroes if at start or end */
- else if (v6stat.zero_cnt == 2) {
- if ((v6stat.zero_pos != 0)
- && (v6stat.zero_pos != v6stat.total))
- return 0;
- } else
- /* Can only have one zero if *not* start or end */
- {
- if ((v6stat.zero_pos == 0)
- || (v6stat.zero_pos == v6stat.total))
- return 0;
- }
- }
-
- /* Format result */
-
- if (v6stat.zero_pos >= 0) {
- /* Copy initial part */
- memcpy(v6, v6stat.tmp, v6stat.zero_pos);
- /* Zero middle */
- memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
- /* Copy final part */
- if (v6stat.total != v6stat.zero_pos)
- memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
- v6stat.tmp + v6stat.zero_pos,
- v6stat.total - v6stat.zero_pos);
- } else
- memcpy(v6, v6stat.tmp, 16);
-
- return 1;
-}
-
-static int ipv6_cb(const char *elem, int len, void *usr)
-{
- IPV6_STAT *s = usr;
- /* Error if 16 bytes written */
- if (s->total == 16)
- return 0;
- if (len == 0) {
- /* Zero length element, corresponds to '::' */
- if (s->zero_pos == -1)
- s->zero_pos = s->total;
- /* If we've already got a :: its an error */
- else if (s->zero_pos != s->total)
- return 0;
- s->zero_cnt++;
- } else {
- /* If more than 4 characters could be final a.b.c.d form */
- if (len > 4) {
- /* Need at least 4 bytes left */
- if (s->total > 12)
- return 0;
- /* Must be end of string */
- if (elem[len])
- return 0;
- if (!ipv4_from_asc(s->tmp + s->total, elem))
- return 0;
- s->total += 4;
- } else {
- if (!ipv6_hex(s->tmp + s->total, elem, len))
- return 0;
- s->total += 2;
- }
- }
- return 1;
-}
-
-/*
- * Convert a string of up to 4 hex digits into the corresponding IPv6 form.
- */
-
-static int ipv6_hex(unsigned char *out, const char *in, int inlen)
-{
- unsigned char c;
- unsigned int num = 0;
- int x;
-
- if (inlen > 4)
- return 0;
- while (inlen--) {
- c = *in++;
- num <<= 4;
- x = OPENSSL_hexchar2int(c);
- if (x < 0)
- return 0;
- num |= (char)x;
- }
- out[0] = num >> 8;
- out[1] = num & 0xff;
- return 1;
-}
-
-int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
- unsigned long chtype)
-{
- CONF_VALUE *v;
- int i, mval, spec_char, plus_char;
- char *p, *type;
- if (!nm)
- return 0;
-
- for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
- v = sk_CONF_VALUE_value(dn_sk, i);
- type = v->name;
- /*
- * Skip past any leading X. X: X, etc to allow for multiple instances
- */
- for (p = type; *p; p++) {
-#ifndef CHARSET_EBCDIC
- spec_char = ((*p == ':') || (*p == ',') || (*p == '.'));
-#else
- spec_char = ((*p == os_toascii[':']) || (*p == os_toascii[','])
- || (*p == os_toascii['.']));
-#endif
- if (spec_char) {
- p++;
- if (*p)
- type = p;
- break;
- }
- }
-#ifndef CHARSET_EBCDIC
- plus_char = (*type == '+');
-#else
- plus_char = (*type == os_toascii['+']);
-#endif
- if (plus_char) {
- mval = -1;
- type++;
- } else
- mval = 0;
- if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
- (unsigned char *)v->value, -1, -1,
- mval))
- return 0;
-
- }
- return 1;
-}
diff --git a/crypto/x509v3/v3err.c b/crypto/x509v3/v3err.c
deleted file mode 100644
index 8b2918a64fff..000000000000
--- a/crypto/x509v3/v3err.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <openssl/err.h>
-#include <openssl/x509v3err.h>
-
-#ifndef OPENSSL_NO_ERR
-
-static const ERR_STRING_DATA X509V3_str_functs[] = {
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_A2I_GENERAL_NAME, 0),
- "a2i_GENERAL_NAME"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_ADDR_VALIDATE_PATH_INTERNAL, 0),
- "addr_validate_path_internal"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, 0),
- "ASIdentifierChoice_canonize"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL, 0),
- "ASIdentifierChoice_is_canonical"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_BIGNUM_TO_STRING, 0),
- "bignum_to_string"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_COPY_EMAIL, 0), "copy_email"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_COPY_ISSUER, 0), "copy_issuer"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_DO_DIRNAME, 0), "do_dirname"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_DO_EXT_I2D, 0), "do_ext_i2d"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_DO_EXT_NCONF, 0), "do_ext_nconf"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_GNAMES_FROM_SECTNAME, 0),
- "gnames_from_sectname"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_I2S_ASN1_ENUMERATED, 0),
- "i2s_ASN1_ENUMERATED"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_I2S_ASN1_IA5STRING, 0),
- "i2s_ASN1_IA5STRING"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_I2S_ASN1_INTEGER, 0),
- "i2s_ASN1_INTEGER"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_I2V_AUTHORITY_INFO_ACCESS, 0),
- "i2v_AUTHORITY_INFO_ACCESS"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_I2V_AUTHORITY_KEYID, 0),
- "i2v_AUTHORITY_KEYID"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_LEVEL_ADD_NODE, 0), "level_add_node"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_NOTICE_SECTION, 0), "notice_section"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_NREF_NOS, 0), "nref_nos"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_POLICY_CACHE_CREATE, 0),
- "policy_cache_create"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_POLICY_CACHE_NEW, 0),
- "policy_cache_new"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_POLICY_DATA_NEW, 0), "policy_data_new"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_POLICY_SECTION, 0), "policy_section"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_PROCESS_PCI_VALUE, 0),
- "process_pci_value"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_R2I_CERTPOL, 0), "r2i_certpol"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_R2I_PCI, 0), "r2i_pci"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_S2I_ASN1_IA5STRING, 0),
- "s2i_ASN1_IA5STRING"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_S2I_ASN1_INTEGER, 0),
- "s2i_ASN1_INTEGER"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_S2I_ASN1_OCTET_STRING, 0),
- "s2i_ASN1_OCTET_STRING"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_S2I_SKEY_ID, 0), "s2i_skey_id"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SET_DIST_POINT_NAME, 0),
- "set_dist_point_name"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_ADD_ID_ASC, 0),
- "SXNET_add_id_asc"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_ADD_ID_INTEGER, 0),
- "SXNET_add_id_INTEGER"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_ADD_ID_ULONG, 0),
- "SXNET_add_id_ulong"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_GET_ID_ASC, 0),
- "SXNET_get_id_asc"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_GET_ID_ULONG, 0),
- "SXNET_get_id_ulong"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_TREE_INIT, 0), "tree_init"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_ASIDENTIFIERS, 0),
- "v2i_ASIdentifiers"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_ASN1_BIT_STRING, 0),
- "v2i_ASN1_BIT_STRING"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_AUTHORITY_INFO_ACCESS, 0),
- "v2i_AUTHORITY_INFO_ACCESS"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_AUTHORITY_KEYID, 0),
- "v2i_AUTHORITY_KEYID"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_BASIC_CONSTRAINTS, 0),
- "v2i_BASIC_CONSTRAINTS"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_CRLD, 0), "v2i_crld"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_EXTENDED_KEY_USAGE, 0),
- "v2i_EXTENDED_KEY_USAGE"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_GENERAL_NAMES, 0),
- "v2i_GENERAL_NAMES"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_GENERAL_NAME_EX, 0),
- "v2i_GENERAL_NAME_ex"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_IDP, 0), "v2i_idp"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_IPADDRBLOCKS, 0),
- "v2i_IPAddrBlocks"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_ISSUER_ALT, 0), "v2i_issuer_alt"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_NAME_CONSTRAINTS, 0),
- "v2i_NAME_CONSTRAINTS"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_POLICY_CONSTRAINTS, 0),
- "v2i_POLICY_CONSTRAINTS"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_POLICY_MAPPINGS, 0),
- "v2i_POLICY_MAPPINGS"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_SUBJECT_ALT, 0), "v2i_subject_alt"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_TLS_FEATURE, 0), "v2i_TLS_FEATURE"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V3_GENERIC_EXTENSION, 0),
- "v3_generic_extension"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_ADD1_I2D, 0), "X509V3_add1_i2d"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_ADD_LEN_VALUE, 0),
- "x509v3_add_len_value"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_ADD_VALUE, 0),
- "X509V3_add_value"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_ADD, 0), "X509V3_EXT_add"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_ADD_ALIAS, 0),
- "X509V3_EXT_add_alias"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_I2D, 0), "X509V3_EXT_i2d"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_NCONF, 0),
- "X509V3_EXT_nconf"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_GET_SECTION, 0),
- "X509V3_get_section"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_GET_STRING, 0),
- "X509V3_get_string"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_GET_VALUE_BOOL, 0),
- "X509V3_get_value_bool"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_PARSE_LIST, 0),
- "X509V3_parse_list"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509_PURPOSE_ADD, 0),
- "X509_PURPOSE_add"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509_PURPOSE_SET, 0),
- "X509_PURPOSE_set"},
- {0, NULL}
-};
-
-static const ERR_STRING_DATA X509V3_str_reasons[] = {
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BAD_IP_ADDRESS), "bad ip address"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BAD_OBJECT), "bad object"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BN_DEC2BN_ERROR), "bn dec2bn error"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BN_TO_ASN1_INTEGER_ERROR),
- "bn to asn1 integer error"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DIRNAME_ERROR), "dirname error"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DISTPOINT_ALREADY_SET),
- "distpoint already set"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DUPLICATE_ZONE_ID),
- "duplicate zone id"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_CONVERTING_ZONE),
- "error converting zone"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_CREATING_EXTENSION),
- "error creating extension"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_IN_EXTENSION),
- "error in extension"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXPECTED_A_SECTION_NAME),
- "expected a section name"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_EXISTS),
- "extension exists"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_NAME_ERROR),
- "extension name error"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_NOT_FOUND),
- "extension not found"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED),
- "extension setting not supported"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_VALUE_ERROR),
- "extension value error"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ILLEGAL_EMPTY_EXTENSION),
- "illegal empty extension"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG),
- "incorrect policy syntax tag"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_ASNUMBER),
- "invalid asnumber"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_ASRANGE), "invalid asrange"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_BOOLEAN_STRING),
- "invalid boolean string"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_EXTENSION_STRING),
- "invalid extension string"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_INHERITANCE),
- "invalid inheritance"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_IPADDRESS),
- "invalid ipaddress"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_MULTIPLE_RDNS),
- "invalid multiple rdns"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NAME), "invalid name"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_ARGUMENT),
- "invalid null argument"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_NAME),
- "invalid null name"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_VALUE),
- "invalid null value"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NUMBER), "invalid number"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NUMBERS), "invalid numbers"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_OBJECT_IDENTIFIER),
- "invalid object identifier"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_OPTION), "invalid option"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_POLICY_IDENTIFIER),
- "invalid policy identifier"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_PROXY_POLICY_SETTING),
- "invalid proxy policy setting"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_PURPOSE), "invalid purpose"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SAFI), "invalid safi"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SECTION), "invalid section"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SYNTAX), "invalid syntax"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ISSUER_DECODE_ERROR),
- "issuer decode error"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_MISSING_VALUE), "missing value"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS),
- "need organization and numbers"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_CONFIG_DATABASE),
- "no config database"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_ISSUER_CERTIFICATE),
- "no issuer certificate"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_ISSUER_DETAILS),
- "no issuer details"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_POLICY_IDENTIFIER),
- "no policy identifier"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED),
- "no proxy cert policy language defined"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_PUBLIC_KEY), "no public key"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_SUBJECT_DETAILS),
- "no subject details"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_OPERATION_NOT_DEFINED),
- "operation not defined"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_OTHERNAME_ERROR), "othername error"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED),
- "policy language already defined"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_PATH_LENGTH),
- "policy path length"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED),
- "policy path length already defined"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY),
- "policy when proxy language requires no policy"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_SECTION_NOT_FOUND),
- "section not found"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS),
- "unable to get issuer details"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID),
- "unable to get issuer keyid"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT),
- "unknown bit string argument"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_EXTENSION),
- "unknown extension"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_EXTENSION_NAME),
- "unknown extension name"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_OPTION), "unknown option"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNSUPPORTED_OPTION),
- "unsupported option"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNSUPPORTED_TYPE),
- "unsupported type"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_USER_TOO_LONG), "user too long"},
- {0, NULL}
-};
-
-#endif
-
-int ERR_load_X509V3_strings(void)
-{
-#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(X509V3_str_functs[0].error) == NULL) {
- ERR_load_strings_const(X509V3_str_functs);
- ERR_load_strings_const(X509V3_str_reasons);
- }
-#endif
- return 1;
-}
diff --git a/crypto/x86_64cpuid.pl b/crypto/x86_64cpuid.pl
index d9536d65768f..53685ec26390 100644
--- a/crypto/x86_64cpuid.pl
+++ b/crypto/x86_64cpuid.pl
@@ -1,15 +1,16 @@
#! /usr/bin/env perl
-# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -18,7 +19,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
($arg1,$arg2,$arg3,$arg4)=$win64?("%rcx","%rdx","%r8", "%r9") : # Win64 order
@@ -40,6 +42,7 @@ print<<___;
.align 16
OPENSSL_atomic_add:
.cfi_startproc
+ endbranch
movl ($arg1),%eax
.Lspin: leaq ($arg2,%rax),%r8
.byte 0xf0 # lock
@@ -56,6 +59,7 @@ OPENSSL_atomic_add:
.align 16
OPENSSL_rdtsc:
.cfi_startproc
+ endbranch
rdtsc
shl \$32,%rdx
or %rdx,%rax
@@ -68,6 +72,7 @@ OPENSSL_rdtsc:
.align 16
OPENSSL_ia32_cpuid:
.cfi_startproc
+ endbranch
mov %rbx,%r8 # save %rbx
.cfi_register %rbx,%r8
@@ -210,7 +215,7 @@ OPENSSL_ia32_cpuid:
cmp \$0xe6,%eax
je .Ldone
andl \$0x3fdeffff,8(%rdi) # ~(1<<31|1<<30|1<<21|1<<16)
- # clear AVX512F+BW+VL+FIMA, all of
+ # clear AVX512F+BW+VL+IFMA, all of
# them are EVEX-encoded, which requires
# ZMM state support even if one uses
# only XMM and YMM :-(
@@ -237,6 +242,7 @@ OPENSSL_ia32_cpuid:
.align 16
OPENSSL_cleanse:
.cfi_startproc
+ endbranch
xor %rax,%rax
cmp \$15,$arg2
jae .Lot
@@ -274,6 +280,7 @@ OPENSSL_cleanse:
.align 16
CRYPTO_memcmp:
.cfi_startproc
+ endbranch
xor %rax,%rax
xor %r10,%r10
cmp \$0,$arg3
@@ -312,6 +319,7 @@ print<<___ if (!$win64);
.align 16
OPENSSL_wipe_cpu:
.cfi_startproc
+ endbranch
pxor %xmm0,%xmm0
pxor %xmm1,%xmm1
pxor %xmm2,%xmm2
@@ -376,6 +384,7 @@ print<<___;
.align 16
OPENSSL_instrument_bus:
.cfi_startproc
+ endbranch
mov $arg1,$out # tribute to Win64
mov $arg2,$cnt
mov $arg2,$max
@@ -410,6 +419,7 @@ OPENSSL_instrument_bus:
.align 16
OPENSSL_instrument_bus2:
.cfi_startproc
+ endbranch
mov $arg1,$out # tribute to Win64
mov $arg2,$cnt
mov $arg3,$max
@@ -465,6 +475,7 @@ print<<___;
.align 16
OPENSSL_ia32_${rdop}_bytes:
.cfi_startproc
+ endbranch
xor %rax, %rax # return value
cmp \$0,$arg2
je .Ldone_${rdop}_bytes
diff --git a/crypto/x86cpuid.pl b/crypto/x86cpuid.pl
index ba4fd80fb32e..a7bcb27e262d 100644
--- a/crypto/x86cpuid.pl
+++ b/crypto/x86cpuid.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -10,9 +10,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC, "${dir}perlasm", "perlasm");
require "x86asm.pl";
-$output = pop;
-open OUT,">$output";
-*STDOUT=*OUT;
+$output = pop and open STDOUT,">$output";
&asm_init($ARGV[0]);
diff --git a/doc/HOWTO/certificates.txt b/doc/HOWTO/certificates.txt
index cfd2bdabb130..78ab97b41928 100644
--- a/doc/HOWTO/certificates.txt
+++ b/doc/HOWTO/certificates.txt
@@ -30,7 +30,7 @@ keys, so before you create a certificate or a certificate request, you
need to create a private key.
Private keys are generated with 'openssl genrsa -out privkey.pem' if
-you want a RSA private key, or if you want a DSA private key:
+you want an RSA private key, or if you want a DSA private key:
'openssl dsaparam -out dsaparam.pem 2048; openssl gendsa -out privkey.pem dsaparam.pem'.
The private keys created by these commands are not passphrase protected;
diff --git a/doc/HOWTO/keys.txt b/doc/HOWTO/keys.txt
index 9f0967cf5577..c4a74c54fcb8 100644
--- a/doc/HOWTO/keys.txt
+++ b/doc/HOWTO/keys.txt
@@ -14,9 +14,9 @@ algorithms. The most popular ones associated with certificates are
RSA and DSA, and this HOWTO will show how to generate each of them.
-2. To generate a RSA key
+2. To generate an RSA key
-A RSA key can be used both for encryption and for signing.
+An RSA key can be used both for encryption and for signing.
Generating a key for the RSA algorithm is quite easy, all you have to
do is the following:
diff --git a/doc/README b/doc/README
deleted file mode 100644
index 964d8798100b..000000000000
--- a/doc/README
+++ /dev/null
@@ -1,27 +0,0 @@
-
-README This file
-
-fingerprints.txt
- PGP fingerprints of authorised release signers
-
-standards.txt
- Moved to the web, https://www.openssl.org/docs/standards.html
-
-HOWTO/
- A few how-to documents; not necessarily up-to-date
-
-man1/
- The openssl command-line tools; start with openssl.pod
-
-man3/
- The SSL library and the crypto library
-
-man5/
- File formats
-
-man7/
- Overviews; start with crypto.pod and ssl.pod, for example
- Algorithm specific EVP_PKEY documentation.
-
-Formatted versions of the manpages (apps,ssl,crypto) can be found at
- https://www.openssl.org/docs/manpages.html
diff --git a/doc/README.md b/doc/README.md
new file mode 100644
index 000000000000..12bb37ddb8fc
--- /dev/null
+++ b/doc/README.md
@@ -0,0 +1,30 @@
+OpenSSL Documentation
+=====================
+
+README.md This file
+
+[fingerprints.txt](fingerprints.txt)
+ PGP fingerprints of authorised release signers
+
+standards.txt
+standards.txt
+ Moved to the web, <https://www.openssl.org/docs/standards.html>
+
+[HOWTO/](HOWTO/)
+ A few how-to documents; not necessarily up-to-date
+
+[man1/](man1/)
+ The openssl command-line tools; start with openssl.pod
+
+[man3/](man3/)
+ The SSL library and the crypto library
+
+[man5/](man5/)
+ File formats
+
+[man7/](man7/)
+ Overviews; start with crypto.pod and ssl.pod, for example
+ Algorithm specific EVP_PKEY documentation.
+
+Formatted versions of the manpages (apps,ssl,crypto) can be found at
+ <https://www.openssl.org/docs/manpages.html>
diff --git a/doc/build.info b/doc/build.info
new file mode 100644
index 000000000000..ec8778f2ac69
--- /dev/null
+++ b/doc/build.info
@@ -0,0 +1,4860 @@
+SUBDIRS = man1
+
+DEPEND[html/man1/CA.pl.html]=man1/CA.pl.pod
+GENERATE[html/man1/CA.pl.html]=man1/CA.pl.pod
+DEPEND[man/man1/CA.pl.1]=man1/CA.pl.pod
+GENERATE[man/man1/CA.pl.1]=man1/CA.pl.pod
+DEPEND[html/man1/openssl-asn1parse.html]=man1/openssl-asn1parse.pod
+GENERATE[html/man1/openssl-asn1parse.html]=man1/openssl-asn1parse.pod
+DEPEND[man/man1/openssl-asn1parse.1]=man1/openssl-asn1parse.pod
+GENERATE[man/man1/openssl-asn1parse.1]=man1/openssl-asn1parse.pod
+DEPEND[man1/openssl-asn1parse.pod]{pod}=man1/openssl-asn1parse.pod.in
+GENERATE[man1/openssl-asn1parse.pod]=man1/openssl-asn1parse.pod.in
+DEPEND[html/man1/openssl-ca.html]=man1/openssl-ca.pod
+GENERATE[html/man1/openssl-ca.html]=man1/openssl-ca.pod
+DEPEND[man/man1/openssl-ca.1]=man1/openssl-ca.pod
+GENERATE[man/man1/openssl-ca.1]=man1/openssl-ca.pod
+DEPEND[man1/openssl-ca.pod]{pod}=man1/openssl-ca.pod.in
+GENERATE[man1/openssl-ca.pod]=man1/openssl-ca.pod.in
+DEPEND[html/man1/openssl-ciphers.html]=man1/openssl-ciphers.pod
+GENERATE[html/man1/openssl-ciphers.html]=man1/openssl-ciphers.pod
+DEPEND[man/man1/openssl-ciphers.1]=man1/openssl-ciphers.pod
+GENERATE[man/man1/openssl-ciphers.1]=man1/openssl-ciphers.pod
+DEPEND[man1/openssl-ciphers.pod]{pod}=man1/openssl-ciphers.pod.in
+GENERATE[man1/openssl-ciphers.pod]=man1/openssl-ciphers.pod.in
+DEPEND[html/man1/openssl-cmds.html]=man1/openssl-cmds.pod
+GENERATE[html/man1/openssl-cmds.html]=man1/openssl-cmds.pod
+DEPEND[man/man1/openssl-cmds.1]=man1/openssl-cmds.pod
+GENERATE[man/man1/openssl-cmds.1]=man1/openssl-cmds.pod
+DEPEND[man1/openssl-cmds.pod]{pod}=man1/openssl-cmds.pod.in
+GENERATE[man1/openssl-cmds.pod]=man1/openssl-cmds.pod.in
+DEPEND[html/man1/openssl-cmp.html]=man1/openssl-cmp.pod
+GENERATE[html/man1/openssl-cmp.html]=man1/openssl-cmp.pod
+DEPEND[man/man1/openssl-cmp.1]=man1/openssl-cmp.pod
+GENERATE[man/man1/openssl-cmp.1]=man1/openssl-cmp.pod
+DEPEND[man1/openssl-cmp.pod]{pod}=man1/openssl-cmp.pod.in
+GENERATE[man1/openssl-cmp.pod]=man1/openssl-cmp.pod.in
+DEPEND[html/man1/openssl-cms.html]=man1/openssl-cms.pod
+GENERATE[html/man1/openssl-cms.html]=man1/openssl-cms.pod
+DEPEND[man/man1/openssl-cms.1]=man1/openssl-cms.pod
+GENERATE[man/man1/openssl-cms.1]=man1/openssl-cms.pod
+DEPEND[man1/openssl-cms.pod]{pod}=man1/openssl-cms.pod.in
+GENERATE[man1/openssl-cms.pod]=man1/openssl-cms.pod.in
+DEPEND[html/man1/openssl-crl.html]=man1/openssl-crl.pod
+GENERATE[html/man1/openssl-crl.html]=man1/openssl-crl.pod
+DEPEND[man/man1/openssl-crl.1]=man1/openssl-crl.pod
+GENERATE[man/man1/openssl-crl.1]=man1/openssl-crl.pod
+DEPEND[man1/openssl-crl.pod]{pod}=man1/openssl-crl.pod.in
+GENERATE[man1/openssl-crl.pod]=man1/openssl-crl.pod.in
+DEPEND[html/man1/openssl-crl2pkcs7.html]=man1/openssl-crl2pkcs7.pod
+GENERATE[html/man1/openssl-crl2pkcs7.html]=man1/openssl-crl2pkcs7.pod
+DEPEND[man/man1/openssl-crl2pkcs7.1]=man1/openssl-crl2pkcs7.pod
+GENERATE[man/man1/openssl-crl2pkcs7.1]=man1/openssl-crl2pkcs7.pod
+DEPEND[man1/openssl-crl2pkcs7.pod]{pod}=man1/openssl-crl2pkcs7.pod.in
+GENERATE[man1/openssl-crl2pkcs7.pod]=man1/openssl-crl2pkcs7.pod.in
+DEPEND[html/man1/openssl-dgst.html]=man1/openssl-dgst.pod
+GENERATE[html/man1/openssl-dgst.html]=man1/openssl-dgst.pod
+DEPEND[man/man1/openssl-dgst.1]=man1/openssl-dgst.pod
+GENERATE[man/man1/openssl-dgst.1]=man1/openssl-dgst.pod
+DEPEND[man1/openssl-dgst.pod]{pod}=man1/openssl-dgst.pod.in
+GENERATE[man1/openssl-dgst.pod]=man1/openssl-dgst.pod.in
+DEPEND[html/man1/openssl-dhparam.html]=man1/openssl-dhparam.pod
+GENERATE[html/man1/openssl-dhparam.html]=man1/openssl-dhparam.pod
+DEPEND[man/man1/openssl-dhparam.1]=man1/openssl-dhparam.pod
+GENERATE[man/man1/openssl-dhparam.1]=man1/openssl-dhparam.pod
+DEPEND[man1/openssl-dhparam.pod]{pod}=man1/openssl-dhparam.pod.in
+GENERATE[man1/openssl-dhparam.pod]=man1/openssl-dhparam.pod.in
+DEPEND[html/man1/openssl-dsa.html]=man1/openssl-dsa.pod
+GENERATE[html/man1/openssl-dsa.html]=man1/openssl-dsa.pod
+DEPEND[man/man1/openssl-dsa.1]=man1/openssl-dsa.pod
+GENERATE[man/man1/openssl-dsa.1]=man1/openssl-dsa.pod
+DEPEND[man1/openssl-dsa.pod]{pod}=man1/openssl-dsa.pod.in
+GENERATE[man1/openssl-dsa.pod]=man1/openssl-dsa.pod.in
+DEPEND[html/man1/openssl-dsaparam.html]=man1/openssl-dsaparam.pod
+GENERATE[html/man1/openssl-dsaparam.html]=man1/openssl-dsaparam.pod
+DEPEND[man/man1/openssl-dsaparam.1]=man1/openssl-dsaparam.pod
+GENERATE[man/man1/openssl-dsaparam.1]=man1/openssl-dsaparam.pod
+DEPEND[man1/openssl-dsaparam.pod]{pod}=man1/openssl-dsaparam.pod.in
+GENERATE[man1/openssl-dsaparam.pod]=man1/openssl-dsaparam.pod.in
+DEPEND[html/man1/openssl-ec.html]=man1/openssl-ec.pod
+GENERATE[html/man1/openssl-ec.html]=man1/openssl-ec.pod
+DEPEND[man/man1/openssl-ec.1]=man1/openssl-ec.pod
+GENERATE[man/man1/openssl-ec.1]=man1/openssl-ec.pod
+DEPEND[man1/openssl-ec.pod]{pod}=man1/openssl-ec.pod.in
+GENERATE[man1/openssl-ec.pod]=man1/openssl-ec.pod.in
+DEPEND[html/man1/openssl-ecparam.html]=man1/openssl-ecparam.pod
+GENERATE[html/man1/openssl-ecparam.html]=man1/openssl-ecparam.pod
+DEPEND[man/man1/openssl-ecparam.1]=man1/openssl-ecparam.pod
+GENERATE[man/man1/openssl-ecparam.1]=man1/openssl-ecparam.pod
+DEPEND[man1/openssl-ecparam.pod]{pod}=man1/openssl-ecparam.pod.in
+GENERATE[man1/openssl-ecparam.pod]=man1/openssl-ecparam.pod.in
+DEPEND[html/man1/openssl-enc.html]=man1/openssl-enc.pod
+GENERATE[html/man1/openssl-enc.html]=man1/openssl-enc.pod
+DEPEND[man/man1/openssl-enc.1]=man1/openssl-enc.pod
+GENERATE[man/man1/openssl-enc.1]=man1/openssl-enc.pod
+DEPEND[man1/openssl-enc.pod]{pod}=man1/openssl-enc.pod.in
+GENERATE[man1/openssl-enc.pod]=man1/openssl-enc.pod.in
+DEPEND[html/man1/openssl-engine.html]=man1/openssl-engine.pod
+GENERATE[html/man1/openssl-engine.html]=man1/openssl-engine.pod
+DEPEND[man/man1/openssl-engine.1]=man1/openssl-engine.pod
+GENERATE[man/man1/openssl-engine.1]=man1/openssl-engine.pod
+DEPEND[man1/openssl-engine.pod]{pod}=man1/openssl-engine.pod.in
+GENERATE[man1/openssl-engine.pod]=man1/openssl-engine.pod.in
+DEPEND[html/man1/openssl-errstr.html]=man1/openssl-errstr.pod
+GENERATE[html/man1/openssl-errstr.html]=man1/openssl-errstr.pod
+DEPEND[man/man1/openssl-errstr.1]=man1/openssl-errstr.pod
+GENERATE[man/man1/openssl-errstr.1]=man1/openssl-errstr.pod
+DEPEND[man1/openssl-errstr.pod]{pod}=man1/openssl-errstr.pod.in
+GENERATE[man1/openssl-errstr.pod]=man1/openssl-errstr.pod.in
+DEPEND[html/man1/openssl-fipsinstall.html]=man1/openssl-fipsinstall.pod
+GENERATE[html/man1/openssl-fipsinstall.html]=man1/openssl-fipsinstall.pod
+DEPEND[man/man1/openssl-fipsinstall.1]=man1/openssl-fipsinstall.pod
+GENERATE[man/man1/openssl-fipsinstall.1]=man1/openssl-fipsinstall.pod
+DEPEND[man1/openssl-fipsinstall.pod]{pod}=man1/openssl-fipsinstall.pod.in
+GENERATE[man1/openssl-fipsinstall.pod]=man1/openssl-fipsinstall.pod.in
+DEPEND[html/man1/openssl-format-options.html]=man1/openssl-format-options.pod
+GENERATE[html/man1/openssl-format-options.html]=man1/openssl-format-options.pod
+DEPEND[man/man1/openssl-format-options.1]=man1/openssl-format-options.pod
+GENERATE[man/man1/openssl-format-options.1]=man1/openssl-format-options.pod
+DEPEND[html/man1/openssl-gendsa.html]=man1/openssl-gendsa.pod
+GENERATE[html/man1/openssl-gendsa.html]=man1/openssl-gendsa.pod
+DEPEND[man/man1/openssl-gendsa.1]=man1/openssl-gendsa.pod
+GENERATE[man/man1/openssl-gendsa.1]=man1/openssl-gendsa.pod
+DEPEND[man1/openssl-gendsa.pod]{pod}=man1/openssl-gendsa.pod.in
+GENERATE[man1/openssl-gendsa.pod]=man1/openssl-gendsa.pod.in
+DEPEND[html/man1/openssl-genpkey.html]=man1/openssl-genpkey.pod
+GENERATE[html/man1/openssl-genpkey.html]=man1/openssl-genpkey.pod
+DEPEND[man/man1/openssl-genpkey.1]=man1/openssl-genpkey.pod
+GENERATE[man/man1/openssl-genpkey.1]=man1/openssl-genpkey.pod
+DEPEND[man1/openssl-genpkey.pod]{pod}=man1/openssl-genpkey.pod.in
+GENERATE[man1/openssl-genpkey.pod]=man1/openssl-genpkey.pod.in
+DEPEND[html/man1/openssl-genrsa.html]=man1/openssl-genrsa.pod
+GENERATE[html/man1/openssl-genrsa.html]=man1/openssl-genrsa.pod
+DEPEND[man/man1/openssl-genrsa.1]=man1/openssl-genrsa.pod
+GENERATE[man/man1/openssl-genrsa.1]=man1/openssl-genrsa.pod
+DEPEND[man1/openssl-genrsa.pod]{pod}=man1/openssl-genrsa.pod.in
+GENERATE[man1/openssl-genrsa.pod]=man1/openssl-genrsa.pod.in
+DEPEND[html/man1/openssl-info.html]=man1/openssl-info.pod
+GENERATE[html/man1/openssl-info.html]=man1/openssl-info.pod
+DEPEND[man/man1/openssl-info.1]=man1/openssl-info.pod
+GENERATE[man/man1/openssl-info.1]=man1/openssl-info.pod
+DEPEND[man1/openssl-info.pod]{pod}=man1/openssl-info.pod.in
+GENERATE[man1/openssl-info.pod]=man1/openssl-info.pod.in
+DEPEND[html/man1/openssl-kdf.html]=man1/openssl-kdf.pod
+GENERATE[html/man1/openssl-kdf.html]=man1/openssl-kdf.pod
+DEPEND[man/man1/openssl-kdf.1]=man1/openssl-kdf.pod
+GENERATE[man/man1/openssl-kdf.1]=man1/openssl-kdf.pod
+DEPEND[man1/openssl-kdf.pod]{pod}=man1/openssl-kdf.pod.in
+GENERATE[man1/openssl-kdf.pod]=man1/openssl-kdf.pod.in
+DEPEND[html/man1/openssl-list.html]=man1/openssl-list.pod
+GENERATE[html/man1/openssl-list.html]=man1/openssl-list.pod
+DEPEND[man/man1/openssl-list.1]=man1/openssl-list.pod
+GENERATE[man/man1/openssl-list.1]=man1/openssl-list.pod
+DEPEND[man1/openssl-list.pod]{pod}=man1/openssl-list.pod.in
+GENERATE[man1/openssl-list.pod]=man1/openssl-list.pod.in
+DEPEND[html/man1/openssl-mac.html]=man1/openssl-mac.pod
+GENERATE[html/man1/openssl-mac.html]=man1/openssl-mac.pod
+DEPEND[man/man1/openssl-mac.1]=man1/openssl-mac.pod
+GENERATE[man/man1/openssl-mac.1]=man1/openssl-mac.pod
+DEPEND[man1/openssl-mac.pod]{pod}=man1/openssl-mac.pod.in
+GENERATE[man1/openssl-mac.pod]=man1/openssl-mac.pod.in
+DEPEND[html/man1/openssl-namedisplay-options.html]=man1/openssl-namedisplay-options.pod
+GENERATE[html/man1/openssl-namedisplay-options.html]=man1/openssl-namedisplay-options.pod
+DEPEND[man/man1/openssl-namedisplay-options.1]=man1/openssl-namedisplay-options.pod
+GENERATE[man/man1/openssl-namedisplay-options.1]=man1/openssl-namedisplay-options.pod
+DEPEND[html/man1/openssl-nseq.html]=man1/openssl-nseq.pod
+GENERATE[html/man1/openssl-nseq.html]=man1/openssl-nseq.pod
+DEPEND[man/man1/openssl-nseq.1]=man1/openssl-nseq.pod
+GENERATE[man/man1/openssl-nseq.1]=man1/openssl-nseq.pod
+DEPEND[man1/openssl-nseq.pod]{pod}=man1/openssl-nseq.pod.in
+GENERATE[man1/openssl-nseq.pod]=man1/openssl-nseq.pod.in
+DEPEND[html/man1/openssl-ocsp.html]=man1/openssl-ocsp.pod
+GENERATE[html/man1/openssl-ocsp.html]=man1/openssl-ocsp.pod
+DEPEND[man/man1/openssl-ocsp.1]=man1/openssl-ocsp.pod
+GENERATE[man/man1/openssl-ocsp.1]=man1/openssl-ocsp.pod
+DEPEND[man1/openssl-ocsp.pod]{pod}=man1/openssl-ocsp.pod.in
+GENERATE[man1/openssl-ocsp.pod]=man1/openssl-ocsp.pod.in
+DEPEND[html/man1/openssl-passphrase-options.html]=man1/openssl-passphrase-options.pod
+GENERATE[html/man1/openssl-passphrase-options.html]=man1/openssl-passphrase-options.pod
+DEPEND[man/man1/openssl-passphrase-options.1]=man1/openssl-passphrase-options.pod
+GENERATE[man/man1/openssl-passphrase-options.1]=man1/openssl-passphrase-options.pod
+DEPEND[html/man1/openssl-passwd.html]=man1/openssl-passwd.pod
+GENERATE[html/man1/openssl-passwd.html]=man1/openssl-passwd.pod
+DEPEND[man/man1/openssl-passwd.1]=man1/openssl-passwd.pod
+GENERATE[man/man1/openssl-passwd.1]=man1/openssl-passwd.pod
+DEPEND[man1/openssl-passwd.pod]{pod}=man1/openssl-passwd.pod.in
+GENERATE[man1/openssl-passwd.pod]=man1/openssl-passwd.pod.in
+DEPEND[html/man1/openssl-pkcs12.html]=man1/openssl-pkcs12.pod
+GENERATE[html/man1/openssl-pkcs12.html]=man1/openssl-pkcs12.pod
+DEPEND[man/man1/openssl-pkcs12.1]=man1/openssl-pkcs12.pod
+GENERATE[man/man1/openssl-pkcs12.1]=man1/openssl-pkcs12.pod
+DEPEND[man1/openssl-pkcs12.pod]{pod}=man1/openssl-pkcs12.pod.in
+GENERATE[man1/openssl-pkcs12.pod]=man1/openssl-pkcs12.pod.in
+DEPEND[html/man1/openssl-pkcs7.html]=man1/openssl-pkcs7.pod
+GENERATE[html/man1/openssl-pkcs7.html]=man1/openssl-pkcs7.pod
+DEPEND[man/man1/openssl-pkcs7.1]=man1/openssl-pkcs7.pod
+GENERATE[man/man1/openssl-pkcs7.1]=man1/openssl-pkcs7.pod
+DEPEND[man1/openssl-pkcs7.pod]{pod}=man1/openssl-pkcs7.pod.in
+GENERATE[man1/openssl-pkcs7.pod]=man1/openssl-pkcs7.pod.in
+DEPEND[html/man1/openssl-pkcs8.html]=man1/openssl-pkcs8.pod
+GENERATE[html/man1/openssl-pkcs8.html]=man1/openssl-pkcs8.pod
+DEPEND[man/man1/openssl-pkcs8.1]=man1/openssl-pkcs8.pod
+GENERATE[man/man1/openssl-pkcs8.1]=man1/openssl-pkcs8.pod
+DEPEND[man1/openssl-pkcs8.pod]{pod}=man1/openssl-pkcs8.pod.in
+GENERATE[man1/openssl-pkcs8.pod]=man1/openssl-pkcs8.pod.in
+DEPEND[html/man1/openssl-pkey.html]=man1/openssl-pkey.pod
+GENERATE[html/man1/openssl-pkey.html]=man1/openssl-pkey.pod
+DEPEND[man/man1/openssl-pkey.1]=man1/openssl-pkey.pod
+GENERATE[man/man1/openssl-pkey.1]=man1/openssl-pkey.pod
+DEPEND[man1/openssl-pkey.pod]{pod}=man1/openssl-pkey.pod.in
+GENERATE[man1/openssl-pkey.pod]=man1/openssl-pkey.pod.in
+DEPEND[html/man1/openssl-pkeyparam.html]=man1/openssl-pkeyparam.pod
+GENERATE[html/man1/openssl-pkeyparam.html]=man1/openssl-pkeyparam.pod
+DEPEND[man/man1/openssl-pkeyparam.1]=man1/openssl-pkeyparam.pod
+GENERATE[man/man1/openssl-pkeyparam.1]=man1/openssl-pkeyparam.pod
+DEPEND[man1/openssl-pkeyparam.pod]{pod}=man1/openssl-pkeyparam.pod.in
+GENERATE[man1/openssl-pkeyparam.pod]=man1/openssl-pkeyparam.pod.in
+DEPEND[html/man1/openssl-pkeyutl.html]=man1/openssl-pkeyutl.pod
+GENERATE[html/man1/openssl-pkeyutl.html]=man1/openssl-pkeyutl.pod
+DEPEND[man/man1/openssl-pkeyutl.1]=man1/openssl-pkeyutl.pod
+GENERATE[man/man1/openssl-pkeyutl.1]=man1/openssl-pkeyutl.pod
+DEPEND[man1/openssl-pkeyutl.pod]{pod}=man1/openssl-pkeyutl.pod.in
+GENERATE[man1/openssl-pkeyutl.pod]=man1/openssl-pkeyutl.pod.in
+DEPEND[html/man1/openssl-prime.html]=man1/openssl-prime.pod
+GENERATE[html/man1/openssl-prime.html]=man1/openssl-prime.pod
+DEPEND[man/man1/openssl-prime.1]=man1/openssl-prime.pod
+GENERATE[man/man1/openssl-prime.1]=man1/openssl-prime.pod
+DEPEND[man1/openssl-prime.pod]{pod}=man1/openssl-prime.pod.in
+GENERATE[man1/openssl-prime.pod]=man1/openssl-prime.pod.in
+DEPEND[html/man1/openssl-rand.html]=man1/openssl-rand.pod
+GENERATE[html/man1/openssl-rand.html]=man1/openssl-rand.pod
+DEPEND[man/man1/openssl-rand.1]=man1/openssl-rand.pod
+GENERATE[man/man1/openssl-rand.1]=man1/openssl-rand.pod
+DEPEND[man1/openssl-rand.pod]{pod}=man1/openssl-rand.pod.in
+GENERATE[man1/openssl-rand.pod]=man1/openssl-rand.pod.in
+DEPEND[html/man1/openssl-rehash.html]=man1/openssl-rehash.pod
+GENERATE[html/man1/openssl-rehash.html]=man1/openssl-rehash.pod
+DEPEND[man/man1/openssl-rehash.1]=man1/openssl-rehash.pod
+GENERATE[man/man1/openssl-rehash.1]=man1/openssl-rehash.pod
+DEPEND[man1/openssl-rehash.pod]{pod}=man1/openssl-rehash.pod.in
+GENERATE[man1/openssl-rehash.pod]=man1/openssl-rehash.pod.in
+DEPEND[html/man1/openssl-req.html]=man1/openssl-req.pod
+GENERATE[html/man1/openssl-req.html]=man1/openssl-req.pod
+DEPEND[man/man1/openssl-req.1]=man1/openssl-req.pod
+GENERATE[man/man1/openssl-req.1]=man1/openssl-req.pod
+DEPEND[man1/openssl-req.pod]{pod}=man1/openssl-req.pod.in
+GENERATE[man1/openssl-req.pod]=man1/openssl-req.pod.in
+DEPEND[html/man1/openssl-rsa.html]=man1/openssl-rsa.pod
+GENERATE[html/man1/openssl-rsa.html]=man1/openssl-rsa.pod
+DEPEND[man/man1/openssl-rsa.1]=man1/openssl-rsa.pod
+GENERATE[man/man1/openssl-rsa.1]=man1/openssl-rsa.pod
+DEPEND[man1/openssl-rsa.pod]{pod}=man1/openssl-rsa.pod.in
+GENERATE[man1/openssl-rsa.pod]=man1/openssl-rsa.pod.in
+DEPEND[html/man1/openssl-rsautl.html]=man1/openssl-rsautl.pod
+GENERATE[html/man1/openssl-rsautl.html]=man1/openssl-rsautl.pod
+DEPEND[man/man1/openssl-rsautl.1]=man1/openssl-rsautl.pod
+GENERATE[man/man1/openssl-rsautl.1]=man1/openssl-rsautl.pod
+DEPEND[man1/openssl-rsautl.pod]{pod}=man1/openssl-rsautl.pod.in
+GENERATE[man1/openssl-rsautl.pod]=man1/openssl-rsautl.pod.in
+DEPEND[html/man1/openssl-s_client.html]=man1/openssl-s_client.pod
+GENERATE[html/man1/openssl-s_client.html]=man1/openssl-s_client.pod
+DEPEND[man/man1/openssl-s_client.1]=man1/openssl-s_client.pod
+GENERATE[man/man1/openssl-s_client.1]=man1/openssl-s_client.pod
+DEPEND[man1/openssl-s_client.pod]{pod}=man1/openssl-s_client.pod.in
+GENERATE[man1/openssl-s_client.pod]=man1/openssl-s_client.pod.in
+DEPEND[html/man1/openssl-s_server.html]=man1/openssl-s_server.pod
+GENERATE[html/man1/openssl-s_server.html]=man1/openssl-s_server.pod
+DEPEND[man/man1/openssl-s_server.1]=man1/openssl-s_server.pod
+GENERATE[man/man1/openssl-s_server.1]=man1/openssl-s_server.pod
+DEPEND[man1/openssl-s_server.pod]{pod}=man1/openssl-s_server.pod.in
+GENERATE[man1/openssl-s_server.pod]=man1/openssl-s_server.pod.in
+DEPEND[html/man1/openssl-s_time.html]=man1/openssl-s_time.pod
+GENERATE[html/man1/openssl-s_time.html]=man1/openssl-s_time.pod
+DEPEND[man/man1/openssl-s_time.1]=man1/openssl-s_time.pod
+GENERATE[man/man1/openssl-s_time.1]=man1/openssl-s_time.pod
+DEPEND[man1/openssl-s_time.pod]{pod}=man1/openssl-s_time.pod.in
+GENERATE[man1/openssl-s_time.pod]=man1/openssl-s_time.pod.in
+DEPEND[html/man1/openssl-sess_id.html]=man1/openssl-sess_id.pod
+GENERATE[html/man1/openssl-sess_id.html]=man1/openssl-sess_id.pod
+DEPEND[man/man1/openssl-sess_id.1]=man1/openssl-sess_id.pod
+GENERATE[man/man1/openssl-sess_id.1]=man1/openssl-sess_id.pod
+DEPEND[man1/openssl-sess_id.pod]{pod}=man1/openssl-sess_id.pod.in
+GENERATE[man1/openssl-sess_id.pod]=man1/openssl-sess_id.pod.in
+DEPEND[html/man1/openssl-smime.html]=man1/openssl-smime.pod
+GENERATE[html/man1/openssl-smime.html]=man1/openssl-smime.pod
+DEPEND[man/man1/openssl-smime.1]=man1/openssl-smime.pod
+GENERATE[man/man1/openssl-smime.1]=man1/openssl-smime.pod
+DEPEND[man1/openssl-smime.pod]{pod}=man1/openssl-smime.pod.in
+GENERATE[man1/openssl-smime.pod]=man1/openssl-smime.pod.in
+DEPEND[html/man1/openssl-speed.html]=man1/openssl-speed.pod
+GENERATE[html/man1/openssl-speed.html]=man1/openssl-speed.pod
+DEPEND[man/man1/openssl-speed.1]=man1/openssl-speed.pod
+GENERATE[man/man1/openssl-speed.1]=man1/openssl-speed.pod
+DEPEND[man1/openssl-speed.pod]{pod}=man1/openssl-speed.pod.in
+GENERATE[man1/openssl-speed.pod]=man1/openssl-speed.pod.in
+DEPEND[html/man1/openssl-spkac.html]=man1/openssl-spkac.pod
+GENERATE[html/man1/openssl-spkac.html]=man1/openssl-spkac.pod
+DEPEND[man/man1/openssl-spkac.1]=man1/openssl-spkac.pod
+GENERATE[man/man1/openssl-spkac.1]=man1/openssl-spkac.pod
+DEPEND[man1/openssl-spkac.pod]{pod}=man1/openssl-spkac.pod.in
+GENERATE[man1/openssl-spkac.pod]=man1/openssl-spkac.pod.in
+DEPEND[html/man1/openssl-srp.html]=man1/openssl-srp.pod
+GENERATE[html/man1/openssl-srp.html]=man1/openssl-srp.pod
+DEPEND[man/man1/openssl-srp.1]=man1/openssl-srp.pod
+GENERATE[man/man1/openssl-srp.1]=man1/openssl-srp.pod
+DEPEND[man1/openssl-srp.pod]{pod}=man1/openssl-srp.pod.in
+GENERATE[man1/openssl-srp.pod]=man1/openssl-srp.pod.in
+DEPEND[html/man1/openssl-storeutl.html]=man1/openssl-storeutl.pod
+GENERATE[html/man1/openssl-storeutl.html]=man1/openssl-storeutl.pod
+DEPEND[man/man1/openssl-storeutl.1]=man1/openssl-storeutl.pod
+GENERATE[man/man1/openssl-storeutl.1]=man1/openssl-storeutl.pod
+DEPEND[man1/openssl-storeutl.pod]{pod}=man1/openssl-storeutl.pod.in
+GENERATE[man1/openssl-storeutl.pod]=man1/openssl-storeutl.pod.in
+DEPEND[html/man1/openssl-ts.html]=man1/openssl-ts.pod
+GENERATE[html/man1/openssl-ts.html]=man1/openssl-ts.pod
+DEPEND[man/man1/openssl-ts.1]=man1/openssl-ts.pod
+GENERATE[man/man1/openssl-ts.1]=man1/openssl-ts.pod
+DEPEND[man1/openssl-ts.pod]{pod}=man1/openssl-ts.pod.in
+GENERATE[man1/openssl-ts.pod]=man1/openssl-ts.pod.in
+DEPEND[html/man1/openssl-verification-options.html]=man1/openssl-verification-options.pod
+GENERATE[html/man1/openssl-verification-options.html]=man1/openssl-verification-options.pod
+DEPEND[man/man1/openssl-verification-options.1]=man1/openssl-verification-options.pod
+GENERATE[man/man1/openssl-verification-options.1]=man1/openssl-verification-options.pod
+DEPEND[html/man1/openssl-verify.html]=man1/openssl-verify.pod
+GENERATE[html/man1/openssl-verify.html]=man1/openssl-verify.pod
+DEPEND[man/man1/openssl-verify.1]=man1/openssl-verify.pod
+GENERATE[man/man1/openssl-verify.1]=man1/openssl-verify.pod
+DEPEND[man1/openssl-verify.pod]{pod}=man1/openssl-verify.pod.in
+GENERATE[man1/openssl-verify.pod]=man1/openssl-verify.pod.in
+DEPEND[html/man1/openssl-version.html]=man1/openssl-version.pod
+GENERATE[html/man1/openssl-version.html]=man1/openssl-version.pod
+DEPEND[man/man1/openssl-version.1]=man1/openssl-version.pod
+GENERATE[man/man1/openssl-version.1]=man1/openssl-version.pod
+DEPEND[man1/openssl-version.pod]{pod}=man1/openssl-version.pod.in
+GENERATE[man1/openssl-version.pod]=man1/openssl-version.pod.in
+DEPEND[html/man1/openssl-x509.html]=man1/openssl-x509.pod
+GENERATE[html/man1/openssl-x509.html]=man1/openssl-x509.pod
+DEPEND[man/man1/openssl-x509.1]=man1/openssl-x509.pod
+GENERATE[man/man1/openssl-x509.1]=man1/openssl-x509.pod
+DEPEND[man1/openssl-x509.pod]{pod}=man1/openssl-x509.pod.in
+GENERATE[man1/openssl-x509.pod]=man1/openssl-x509.pod.in
+DEPEND[html/man1/openssl.html]=man1/openssl.pod
+GENERATE[html/man1/openssl.html]=man1/openssl.pod
+DEPEND[man/man1/openssl.1]=man1/openssl.pod
+GENERATE[man/man1/openssl.1]=man1/openssl.pod
+DEPEND[html/man1/tsget.html]=man1/tsget.pod
+GENERATE[html/man1/tsget.html]=man1/tsget.pod
+DEPEND[man/man1/tsget.1]=man1/tsget.pod
+GENERATE[man/man1/tsget.1]=man1/tsget.pod
+IMAGEDOCS[man1]=
+HTMLDOCS[man1]=html/man1/CA.pl.html \
+html/man1/openssl-asn1parse.html \
+html/man1/openssl-ca.html \
+html/man1/openssl-ciphers.html \
+html/man1/openssl-cmds.html \
+html/man1/openssl-cmp.html \
+html/man1/openssl-cms.html \
+html/man1/openssl-crl.html \
+html/man1/openssl-crl2pkcs7.html \
+html/man1/openssl-dgst.html \
+html/man1/openssl-dhparam.html \
+html/man1/openssl-dsa.html \
+html/man1/openssl-dsaparam.html \
+html/man1/openssl-ec.html \
+html/man1/openssl-ecparam.html \
+html/man1/openssl-enc.html \
+html/man1/openssl-engine.html \
+html/man1/openssl-errstr.html \
+html/man1/openssl-fipsinstall.html \
+html/man1/openssl-format-options.html \
+html/man1/openssl-gendsa.html \
+html/man1/openssl-genpkey.html \
+html/man1/openssl-genrsa.html \
+html/man1/openssl-info.html \
+html/man1/openssl-kdf.html \
+html/man1/openssl-list.html \
+html/man1/openssl-mac.html \
+html/man1/openssl-namedisplay-options.html \
+html/man1/openssl-nseq.html \
+html/man1/openssl-ocsp.html \
+html/man1/openssl-passphrase-options.html \
+html/man1/openssl-passwd.html \
+html/man1/openssl-pkcs12.html \
+html/man1/openssl-pkcs7.html \
+html/man1/openssl-pkcs8.html \
+html/man1/openssl-pkey.html \
+html/man1/openssl-pkeyparam.html \
+html/man1/openssl-pkeyutl.html \
+html/man1/openssl-prime.html \
+html/man1/openssl-rand.html \
+html/man1/openssl-rehash.html \
+html/man1/openssl-req.html \
+html/man1/openssl-rsa.html \
+html/man1/openssl-rsautl.html \
+html/man1/openssl-s_client.html \
+html/man1/openssl-s_server.html \
+html/man1/openssl-s_time.html \
+html/man1/openssl-sess_id.html \
+html/man1/openssl-smime.html \
+html/man1/openssl-speed.html \
+html/man1/openssl-spkac.html \
+html/man1/openssl-srp.html \
+html/man1/openssl-storeutl.html \
+html/man1/openssl-ts.html \
+html/man1/openssl-verification-options.html \
+html/man1/openssl-verify.html \
+html/man1/openssl-version.html \
+html/man1/openssl-x509.html \
+html/man1/openssl.html \
+html/man1/tsget.html
+MANDOCS[man1]=man/man1/CA.pl.1 \
+man/man1/openssl-asn1parse.1 \
+man/man1/openssl-ca.1 \
+man/man1/openssl-ciphers.1 \
+man/man1/openssl-cmds.1 \
+man/man1/openssl-cmp.1 \
+man/man1/openssl-cms.1 \
+man/man1/openssl-crl.1 \
+man/man1/openssl-crl2pkcs7.1 \
+man/man1/openssl-dgst.1 \
+man/man1/openssl-dhparam.1 \
+man/man1/openssl-dsa.1 \
+man/man1/openssl-dsaparam.1 \
+man/man1/openssl-ec.1 \
+man/man1/openssl-ecparam.1 \
+man/man1/openssl-enc.1 \
+man/man1/openssl-engine.1 \
+man/man1/openssl-errstr.1 \
+man/man1/openssl-fipsinstall.1 \
+man/man1/openssl-format-options.1 \
+man/man1/openssl-gendsa.1 \
+man/man1/openssl-genpkey.1 \
+man/man1/openssl-genrsa.1 \
+man/man1/openssl-info.1 \
+man/man1/openssl-kdf.1 \
+man/man1/openssl-list.1 \
+man/man1/openssl-mac.1 \
+man/man1/openssl-namedisplay-options.1 \
+man/man1/openssl-nseq.1 \
+man/man1/openssl-ocsp.1 \
+man/man1/openssl-passphrase-options.1 \
+man/man1/openssl-passwd.1 \
+man/man1/openssl-pkcs12.1 \
+man/man1/openssl-pkcs7.1 \
+man/man1/openssl-pkcs8.1 \
+man/man1/openssl-pkey.1 \
+man/man1/openssl-pkeyparam.1 \
+man/man1/openssl-pkeyutl.1 \
+man/man1/openssl-prime.1 \
+man/man1/openssl-rand.1 \
+man/man1/openssl-rehash.1 \
+man/man1/openssl-req.1 \
+man/man1/openssl-rsa.1 \
+man/man1/openssl-rsautl.1 \
+man/man1/openssl-s_client.1 \
+man/man1/openssl-s_server.1 \
+man/man1/openssl-s_time.1 \
+man/man1/openssl-sess_id.1 \
+man/man1/openssl-smime.1 \
+man/man1/openssl-speed.1 \
+man/man1/openssl-spkac.1 \
+man/man1/openssl-srp.1 \
+man/man1/openssl-storeutl.1 \
+man/man1/openssl-ts.1 \
+man/man1/openssl-verification-options.1 \
+man/man1/openssl-verify.1 \
+man/man1/openssl-version.1 \
+man/man1/openssl-x509.1 \
+man/man1/openssl.1 \
+man/man1/tsget.1
+DEPEND[html/man3/ADMISSIONS.html]=man3/ADMISSIONS.pod
+GENERATE[html/man3/ADMISSIONS.html]=man3/ADMISSIONS.pod
+DEPEND[man/man3/ADMISSIONS.3]=man3/ADMISSIONS.pod
+GENERATE[man/man3/ADMISSIONS.3]=man3/ADMISSIONS.pod
+DEPEND[html/man3/ASN1_EXTERN_FUNCS.html]=man3/ASN1_EXTERN_FUNCS.pod
+GENERATE[html/man3/ASN1_EXTERN_FUNCS.html]=man3/ASN1_EXTERN_FUNCS.pod
+DEPEND[man/man3/ASN1_EXTERN_FUNCS.3]=man3/ASN1_EXTERN_FUNCS.pod
+GENERATE[man/man3/ASN1_EXTERN_FUNCS.3]=man3/ASN1_EXTERN_FUNCS.pod
+DEPEND[html/man3/ASN1_INTEGER_get_int64.html]=man3/ASN1_INTEGER_get_int64.pod
+GENERATE[html/man3/ASN1_INTEGER_get_int64.html]=man3/ASN1_INTEGER_get_int64.pod
+DEPEND[man/man3/ASN1_INTEGER_get_int64.3]=man3/ASN1_INTEGER_get_int64.pod
+GENERATE[man/man3/ASN1_INTEGER_get_int64.3]=man3/ASN1_INTEGER_get_int64.pod
+DEPEND[html/man3/ASN1_INTEGER_new.html]=man3/ASN1_INTEGER_new.pod
+GENERATE[html/man3/ASN1_INTEGER_new.html]=man3/ASN1_INTEGER_new.pod
+DEPEND[man/man3/ASN1_INTEGER_new.3]=man3/ASN1_INTEGER_new.pod
+GENERATE[man/man3/ASN1_INTEGER_new.3]=man3/ASN1_INTEGER_new.pod
+DEPEND[html/man3/ASN1_ITEM_lookup.html]=man3/ASN1_ITEM_lookup.pod
+GENERATE[html/man3/ASN1_ITEM_lookup.html]=man3/ASN1_ITEM_lookup.pod
+DEPEND[man/man3/ASN1_ITEM_lookup.3]=man3/ASN1_ITEM_lookup.pod
+GENERATE[man/man3/ASN1_ITEM_lookup.3]=man3/ASN1_ITEM_lookup.pod
+DEPEND[html/man3/ASN1_OBJECT_new.html]=man3/ASN1_OBJECT_new.pod
+GENERATE[html/man3/ASN1_OBJECT_new.html]=man3/ASN1_OBJECT_new.pod
+DEPEND[man/man3/ASN1_OBJECT_new.3]=man3/ASN1_OBJECT_new.pod
+GENERATE[man/man3/ASN1_OBJECT_new.3]=man3/ASN1_OBJECT_new.pod
+DEPEND[html/man3/ASN1_STRING_TABLE_add.html]=man3/ASN1_STRING_TABLE_add.pod
+GENERATE[html/man3/ASN1_STRING_TABLE_add.html]=man3/ASN1_STRING_TABLE_add.pod
+DEPEND[man/man3/ASN1_STRING_TABLE_add.3]=man3/ASN1_STRING_TABLE_add.pod
+GENERATE[man/man3/ASN1_STRING_TABLE_add.3]=man3/ASN1_STRING_TABLE_add.pod
+DEPEND[html/man3/ASN1_STRING_length.html]=man3/ASN1_STRING_length.pod
+GENERATE[html/man3/ASN1_STRING_length.html]=man3/ASN1_STRING_length.pod
+DEPEND[man/man3/ASN1_STRING_length.3]=man3/ASN1_STRING_length.pod
+GENERATE[man/man3/ASN1_STRING_length.3]=man3/ASN1_STRING_length.pod
+DEPEND[html/man3/ASN1_STRING_new.html]=man3/ASN1_STRING_new.pod
+GENERATE[html/man3/ASN1_STRING_new.html]=man3/ASN1_STRING_new.pod
+DEPEND[man/man3/ASN1_STRING_new.3]=man3/ASN1_STRING_new.pod
+GENERATE[man/man3/ASN1_STRING_new.3]=man3/ASN1_STRING_new.pod
+DEPEND[html/man3/ASN1_STRING_print_ex.html]=man3/ASN1_STRING_print_ex.pod
+GENERATE[html/man3/ASN1_STRING_print_ex.html]=man3/ASN1_STRING_print_ex.pod
+DEPEND[man/man3/ASN1_STRING_print_ex.3]=man3/ASN1_STRING_print_ex.pod
+GENERATE[man/man3/ASN1_STRING_print_ex.3]=man3/ASN1_STRING_print_ex.pod
+DEPEND[html/man3/ASN1_TIME_set.html]=man3/ASN1_TIME_set.pod
+GENERATE[html/man3/ASN1_TIME_set.html]=man3/ASN1_TIME_set.pod
+DEPEND[man/man3/ASN1_TIME_set.3]=man3/ASN1_TIME_set.pod
+GENERATE[man/man3/ASN1_TIME_set.3]=man3/ASN1_TIME_set.pod
+DEPEND[html/man3/ASN1_TYPE_get.html]=man3/ASN1_TYPE_get.pod
+GENERATE[html/man3/ASN1_TYPE_get.html]=man3/ASN1_TYPE_get.pod
+DEPEND[man/man3/ASN1_TYPE_get.3]=man3/ASN1_TYPE_get.pod
+GENERATE[man/man3/ASN1_TYPE_get.3]=man3/ASN1_TYPE_get.pod
+DEPEND[html/man3/ASN1_aux_cb.html]=man3/ASN1_aux_cb.pod
+GENERATE[html/man3/ASN1_aux_cb.html]=man3/ASN1_aux_cb.pod
+DEPEND[man/man3/ASN1_aux_cb.3]=man3/ASN1_aux_cb.pod
+GENERATE[man/man3/ASN1_aux_cb.3]=man3/ASN1_aux_cb.pod
+DEPEND[html/man3/ASN1_generate_nconf.html]=man3/ASN1_generate_nconf.pod
+GENERATE[html/man3/ASN1_generate_nconf.html]=man3/ASN1_generate_nconf.pod
+DEPEND[man/man3/ASN1_generate_nconf.3]=man3/ASN1_generate_nconf.pod
+GENERATE[man/man3/ASN1_generate_nconf.3]=man3/ASN1_generate_nconf.pod
+DEPEND[html/man3/ASN1_item_d2i_bio.html]=man3/ASN1_item_d2i_bio.pod
+GENERATE[html/man3/ASN1_item_d2i_bio.html]=man3/ASN1_item_d2i_bio.pod
+DEPEND[man/man3/ASN1_item_d2i_bio.3]=man3/ASN1_item_d2i_bio.pod
+GENERATE[man/man3/ASN1_item_d2i_bio.3]=man3/ASN1_item_d2i_bio.pod
+DEPEND[html/man3/ASN1_item_new.html]=man3/ASN1_item_new.pod
+GENERATE[html/man3/ASN1_item_new.html]=man3/ASN1_item_new.pod
+DEPEND[man/man3/ASN1_item_new.3]=man3/ASN1_item_new.pod
+GENERATE[man/man3/ASN1_item_new.3]=man3/ASN1_item_new.pod
+DEPEND[html/man3/ASN1_item_sign.html]=man3/ASN1_item_sign.pod
+GENERATE[html/man3/ASN1_item_sign.html]=man3/ASN1_item_sign.pod
+DEPEND[man/man3/ASN1_item_sign.3]=man3/ASN1_item_sign.pod
+GENERATE[man/man3/ASN1_item_sign.3]=man3/ASN1_item_sign.pod
+DEPEND[html/man3/ASYNC_WAIT_CTX_new.html]=man3/ASYNC_WAIT_CTX_new.pod
+GENERATE[html/man3/ASYNC_WAIT_CTX_new.html]=man3/ASYNC_WAIT_CTX_new.pod
+DEPEND[man/man3/ASYNC_WAIT_CTX_new.3]=man3/ASYNC_WAIT_CTX_new.pod
+GENERATE[man/man3/ASYNC_WAIT_CTX_new.3]=man3/ASYNC_WAIT_CTX_new.pod
+DEPEND[html/man3/ASYNC_start_job.html]=man3/ASYNC_start_job.pod
+GENERATE[html/man3/ASYNC_start_job.html]=man3/ASYNC_start_job.pod
+DEPEND[man/man3/ASYNC_start_job.3]=man3/ASYNC_start_job.pod
+GENERATE[man/man3/ASYNC_start_job.3]=man3/ASYNC_start_job.pod
+DEPEND[html/man3/BF_encrypt.html]=man3/BF_encrypt.pod
+GENERATE[html/man3/BF_encrypt.html]=man3/BF_encrypt.pod
+DEPEND[man/man3/BF_encrypt.3]=man3/BF_encrypt.pod
+GENERATE[man/man3/BF_encrypt.3]=man3/BF_encrypt.pod
+DEPEND[html/man3/BIO_ADDR.html]=man3/BIO_ADDR.pod
+GENERATE[html/man3/BIO_ADDR.html]=man3/BIO_ADDR.pod
+DEPEND[man/man3/BIO_ADDR.3]=man3/BIO_ADDR.pod
+GENERATE[man/man3/BIO_ADDR.3]=man3/BIO_ADDR.pod
+DEPEND[html/man3/BIO_ADDRINFO.html]=man3/BIO_ADDRINFO.pod
+GENERATE[html/man3/BIO_ADDRINFO.html]=man3/BIO_ADDRINFO.pod
+DEPEND[man/man3/BIO_ADDRINFO.3]=man3/BIO_ADDRINFO.pod
+GENERATE[man/man3/BIO_ADDRINFO.3]=man3/BIO_ADDRINFO.pod
+DEPEND[html/man3/BIO_connect.html]=man3/BIO_connect.pod
+GENERATE[html/man3/BIO_connect.html]=man3/BIO_connect.pod
+DEPEND[man/man3/BIO_connect.3]=man3/BIO_connect.pod
+GENERATE[man/man3/BIO_connect.3]=man3/BIO_connect.pod
+DEPEND[html/man3/BIO_ctrl.html]=man3/BIO_ctrl.pod
+GENERATE[html/man3/BIO_ctrl.html]=man3/BIO_ctrl.pod
+DEPEND[man/man3/BIO_ctrl.3]=man3/BIO_ctrl.pod
+GENERATE[man/man3/BIO_ctrl.3]=man3/BIO_ctrl.pod
+DEPEND[html/man3/BIO_f_base64.html]=man3/BIO_f_base64.pod
+GENERATE[html/man3/BIO_f_base64.html]=man3/BIO_f_base64.pod
+DEPEND[man/man3/BIO_f_base64.3]=man3/BIO_f_base64.pod
+GENERATE[man/man3/BIO_f_base64.3]=man3/BIO_f_base64.pod
+DEPEND[html/man3/BIO_f_buffer.html]=man3/BIO_f_buffer.pod
+GENERATE[html/man3/BIO_f_buffer.html]=man3/BIO_f_buffer.pod
+DEPEND[man/man3/BIO_f_buffer.3]=man3/BIO_f_buffer.pod
+GENERATE[man/man3/BIO_f_buffer.3]=man3/BIO_f_buffer.pod
+DEPEND[html/man3/BIO_f_cipher.html]=man3/BIO_f_cipher.pod
+GENERATE[html/man3/BIO_f_cipher.html]=man3/BIO_f_cipher.pod
+DEPEND[man/man3/BIO_f_cipher.3]=man3/BIO_f_cipher.pod
+GENERATE[man/man3/BIO_f_cipher.3]=man3/BIO_f_cipher.pod
+DEPEND[html/man3/BIO_f_md.html]=man3/BIO_f_md.pod
+GENERATE[html/man3/BIO_f_md.html]=man3/BIO_f_md.pod
+DEPEND[man/man3/BIO_f_md.3]=man3/BIO_f_md.pod
+GENERATE[man/man3/BIO_f_md.3]=man3/BIO_f_md.pod
+DEPEND[html/man3/BIO_f_null.html]=man3/BIO_f_null.pod
+GENERATE[html/man3/BIO_f_null.html]=man3/BIO_f_null.pod
+DEPEND[man/man3/BIO_f_null.3]=man3/BIO_f_null.pod
+GENERATE[man/man3/BIO_f_null.3]=man3/BIO_f_null.pod
+DEPEND[html/man3/BIO_f_prefix.html]=man3/BIO_f_prefix.pod
+GENERATE[html/man3/BIO_f_prefix.html]=man3/BIO_f_prefix.pod
+DEPEND[man/man3/BIO_f_prefix.3]=man3/BIO_f_prefix.pod
+GENERATE[man/man3/BIO_f_prefix.3]=man3/BIO_f_prefix.pod
+DEPEND[html/man3/BIO_f_readbuffer.html]=man3/BIO_f_readbuffer.pod
+GENERATE[html/man3/BIO_f_readbuffer.html]=man3/BIO_f_readbuffer.pod
+DEPEND[man/man3/BIO_f_readbuffer.3]=man3/BIO_f_readbuffer.pod
+GENERATE[man/man3/BIO_f_readbuffer.3]=man3/BIO_f_readbuffer.pod
+DEPEND[html/man3/BIO_f_ssl.html]=man3/BIO_f_ssl.pod
+GENERATE[html/man3/BIO_f_ssl.html]=man3/BIO_f_ssl.pod
+DEPEND[man/man3/BIO_f_ssl.3]=man3/BIO_f_ssl.pod
+GENERATE[man/man3/BIO_f_ssl.3]=man3/BIO_f_ssl.pod
+DEPEND[html/man3/BIO_find_type.html]=man3/BIO_find_type.pod
+GENERATE[html/man3/BIO_find_type.html]=man3/BIO_find_type.pod
+DEPEND[man/man3/BIO_find_type.3]=man3/BIO_find_type.pod
+GENERATE[man/man3/BIO_find_type.3]=man3/BIO_find_type.pod
+DEPEND[html/man3/BIO_get_data.html]=man3/BIO_get_data.pod
+GENERATE[html/man3/BIO_get_data.html]=man3/BIO_get_data.pod
+DEPEND[man/man3/BIO_get_data.3]=man3/BIO_get_data.pod
+GENERATE[man/man3/BIO_get_data.3]=man3/BIO_get_data.pod
+DEPEND[html/man3/BIO_get_ex_new_index.html]=man3/BIO_get_ex_new_index.pod
+GENERATE[html/man3/BIO_get_ex_new_index.html]=man3/BIO_get_ex_new_index.pod
+DEPEND[man/man3/BIO_get_ex_new_index.3]=man3/BIO_get_ex_new_index.pod
+GENERATE[man/man3/BIO_get_ex_new_index.3]=man3/BIO_get_ex_new_index.pod
+DEPEND[html/man3/BIO_meth_new.html]=man3/BIO_meth_new.pod
+GENERATE[html/man3/BIO_meth_new.html]=man3/BIO_meth_new.pod
+DEPEND[man/man3/BIO_meth_new.3]=man3/BIO_meth_new.pod
+GENERATE[man/man3/BIO_meth_new.3]=man3/BIO_meth_new.pod
+DEPEND[html/man3/BIO_new.html]=man3/BIO_new.pod
+GENERATE[html/man3/BIO_new.html]=man3/BIO_new.pod
+DEPEND[man/man3/BIO_new.3]=man3/BIO_new.pod
+GENERATE[man/man3/BIO_new.3]=man3/BIO_new.pod
+DEPEND[html/man3/BIO_new_CMS.html]=man3/BIO_new_CMS.pod
+GENERATE[html/man3/BIO_new_CMS.html]=man3/BIO_new_CMS.pod
+DEPEND[man/man3/BIO_new_CMS.3]=man3/BIO_new_CMS.pod
+GENERATE[man/man3/BIO_new_CMS.3]=man3/BIO_new_CMS.pod
+DEPEND[html/man3/BIO_parse_hostserv.html]=man3/BIO_parse_hostserv.pod
+GENERATE[html/man3/BIO_parse_hostserv.html]=man3/BIO_parse_hostserv.pod
+DEPEND[man/man3/BIO_parse_hostserv.3]=man3/BIO_parse_hostserv.pod
+GENERATE[man/man3/BIO_parse_hostserv.3]=man3/BIO_parse_hostserv.pod
+DEPEND[html/man3/BIO_printf.html]=man3/BIO_printf.pod
+GENERATE[html/man3/BIO_printf.html]=man3/BIO_printf.pod
+DEPEND[man/man3/BIO_printf.3]=man3/BIO_printf.pod
+GENERATE[man/man3/BIO_printf.3]=man3/BIO_printf.pod
+DEPEND[html/man3/BIO_push.html]=man3/BIO_push.pod
+GENERATE[html/man3/BIO_push.html]=man3/BIO_push.pod
+DEPEND[man/man3/BIO_push.3]=man3/BIO_push.pod
+GENERATE[man/man3/BIO_push.3]=man3/BIO_push.pod
+DEPEND[html/man3/BIO_read.html]=man3/BIO_read.pod
+GENERATE[html/man3/BIO_read.html]=man3/BIO_read.pod
+DEPEND[man/man3/BIO_read.3]=man3/BIO_read.pod
+GENERATE[man/man3/BIO_read.3]=man3/BIO_read.pod
+DEPEND[html/man3/BIO_s_accept.html]=man3/BIO_s_accept.pod
+GENERATE[html/man3/BIO_s_accept.html]=man3/BIO_s_accept.pod
+DEPEND[man/man3/BIO_s_accept.3]=man3/BIO_s_accept.pod
+GENERATE[man/man3/BIO_s_accept.3]=man3/BIO_s_accept.pod
+DEPEND[html/man3/BIO_s_bio.html]=man3/BIO_s_bio.pod
+GENERATE[html/man3/BIO_s_bio.html]=man3/BIO_s_bio.pod
+DEPEND[man/man3/BIO_s_bio.3]=man3/BIO_s_bio.pod
+GENERATE[man/man3/BIO_s_bio.3]=man3/BIO_s_bio.pod
+DEPEND[html/man3/BIO_s_connect.html]=man3/BIO_s_connect.pod
+GENERATE[html/man3/BIO_s_connect.html]=man3/BIO_s_connect.pod
+DEPEND[man/man3/BIO_s_connect.3]=man3/BIO_s_connect.pod
+GENERATE[man/man3/BIO_s_connect.3]=man3/BIO_s_connect.pod
+DEPEND[html/man3/BIO_s_core.html]=man3/BIO_s_core.pod
+GENERATE[html/man3/BIO_s_core.html]=man3/BIO_s_core.pod
+DEPEND[man/man3/BIO_s_core.3]=man3/BIO_s_core.pod
+GENERATE[man/man3/BIO_s_core.3]=man3/BIO_s_core.pod
+DEPEND[html/man3/BIO_s_datagram.html]=man3/BIO_s_datagram.pod
+GENERATE[html/man3/BIO_s_datagram.html]=man3/BIO_s_datagram.pod
+DEPEND[man/man3/BIO_s_datagram.3]=man3/BIO_s_datagram.pod
+GENERATE[man/man3/BIO_s_datagram.3]=man3/BIO_s_datagram.pod
+DEPEND[html/man3/BIO_s_fd.html]=man3/BIO_s_fd.pod
+GENERATE[html/man3/BIO_s_fd.html]=man3/BIO_s_fd.pod
+DEPEND[man/man3/BIO_s_fd.3]=man3/BIO_s_fd.pod
+GENERATE[man/man3/BIO_s_fd.3]=man3/BIO_s_fd.pod
+DEPEND[html/man3/BIO_s_file.html]=man3/BIO_s_file.pod
+GENERATE[html/man3/BIO_s_file.html]=man3/BIO_s_file.pod
+DEPEND[man/man3/BIO_s_file.3]=man3/BIO_s_file.pod
+GENERATE[man/man3/BIO_s_file.3]=man3/BIO_s_file.pod
+DEPEND[html/man3/BIO_s_mem.html]=man3/BIO_s_mem.pod
+GENERATE[html/man3/BIO_s_mem.html]=man3/BIO_s_mem.pod
+DEPEND[man/man3/BIO_s_mem.3]=man3/BIO_s_mem.pod
+GENERATE[man/man3/BIO_s_mem.3]=man3/BIO_s_mem.pod
+DEPEND[html/man3/BIO_s_null.html]=man3/BIO_s_null.pod
+GENERATE[html/man3/BIO_s_null.html]=man3/BIO_s_null.pod
+DEPEND[man/man3/BIO_s_null.3]=man3/BIO_s_null.pod
+GENERATE[man/man3/BIO_s_null.3]=man3/BIO_s_null.pod
+DEPEND[html/man3/BIO_s_socket.html]=man3/BIO_s_socket.pod
+GENERATE[html/man3/BIO_s_socket.html]=man3/BIO_s_socket.pod
+DEPEND[man/man3/BIO_s_socket.3]=man3/BIO_s_socket.pod
+GENERATE[man/man3/BIO_s_socket.3]=man3/BIO_s_socket.pod
+DEPEND[html/man3/BIO_set_callback.html]=man3/BIO_set_callback.pod
+GENERATE[html/man3/BIO_set_callback.html]=man3/BIO_set_callback.pod
+DEPEND[man/man3/BIO_set_callback.3]=man3/BIO_set_callback.pod
+GENERATE[man/man3/BIO_set_callback.3]=man3/BIO_set_callback.pod
+DEPEND[html/man3/BIO_should_retry.html]=man3/BIO_should_retry.pod
+GENERATE[html/man3/BIO_should_retry.html]=man3/BIO_should_retry.pod
+DEPEND[man/man3/BIO_should_retry.3]=man3/BIO_should_retry.pod
+GENERATE[man/man3/BIO_should_retry.3]=man3/BIO_should_retry.pod
+DEPEND[html/man3/BIO_socket_wait.html]=man3/BIO_socket_wait.pod
+GENERATE[html/man3/BIO_socket_wait.html]=man3/BIO_socket_wait.pod
+DEPEND[man/man3/BIO_socket_wait.3]=man3/BIO_socket_wait.pod
+GENERATE[man/man3/BIO_socket_wait.3]=man3/BIO_socket_wait.pod
+DEPEND[html/man3/BN_BLINDING_new.html]=man3/BN_BLINDING_new.pod
+GENERATE[html/man3/BN_BLINDING_new.html]=man3/BN_BLINDING_new.pod
+DEPEND[man/man3/BN_BLINDING_new.3]=man3/BN_BLINDING_new.pod
+GENERATE[man/man3/BN_BLINDING_new.3]=man3/BN_BLINDING_new.pod
+DEPEND[html/man3/BN_CTX_new.html]=man3/BN_CTX_new.pod
+GENERATE[html/man3/BN_CTX_new.html]=man3/BN_CTX_new.pod
+DEPEND[man/man3/BN_CTX_new.3]=man3/BN_CTX_new.pod
+GENERATE[man/man3/BN_CTX_new.3]=man3/BN_CTX_new.pod
+DEPEND[html/man3/BN_CTX_start.html]=man3/BN_CTX_start.pod
+GENERATE[html/man3/BN_CTX_start.html]=man3/BN_CTX_start.pod
+DEPEND[man/man3/BN_CTX_start.3]=man3/BN_CTX_start.pod
+GENERATE[man/man3/BN_CTX_start.3]=man3/BN_CTX_start.pod
+DEPEND[html/man3/BN_add.html]=man3/BN_add.pod
+GENERATE[html/man3/BN_add.html]=man3/BN_add.pod
+DEPEND[man/man3/BN_add.3]=man3/BN_add.pod
+GENERATE[man/man3/BN_add.3]=man3/BN_add.pod
+DEPEND[html/man3/BN_add_word.html]=man3/BN_add_word.pod
+GENERATE[html/man3/BN_add_word.html]=man3/BN_add_word.pod
+DEPEND[man/man3/BN_add_word.3]=man3/BN_add_word.pod
+GENERATE[man/man3/BN_add_word.3]=man3/BN_add_word.pod
+DEPEND[html/man3/BN_bn2bin.html]=man3/BN_bn2bin.pod
+GENERATE[html/man3/BN_bn2bin.html]=man3/BN_bn2bin.pod
+DEPEND[man/man3/BN_bn2bin.3]=man3/BN_bn2bin.pod
+GENERATE[man/man3/BN_bn2bin.3]=man3/BN_bn2bin.pod
+DEPEND[html/man3/BN_cmp.html]=man3/BN_cmp.pod
+GENERATE[html/man3/BN_cmp.html]=man3/BN_cmp.pod
+DEPEND[man/man3/BN_cmp.3]=man3/BN_cmp.pod
+GENERATE[man/man3/BN_cmp.3]=man3/BN_cmp.pod
+DEPEND[html/man3/BN_copy.html]=man3/BN_copy.pod
+GENERATE[html/man3/BN_copy.html]=man3/BN_copy.pod
+DEPEND[man/man3/BN_copy.3]=man3/BN_copy.pod
+GENERATE[man/man3/BN_copy.3]=man3/BN_copy.pod
+DEPEND[html/man3/BN_generate_prime.html]=man3/BN_generate_prime.pod
+GENERATE[html/man3/BN_generate_prime.html]=man3/BN_generate_prime.pod
+DEPEND[man/man3/BN_generate_prime.3]=man3/BN_generate_prime.pod
+GENERATE[man/man3/BN_generate_prime.3]=man3/BN_generate_prime.pod
+DEPEND[html/man3/BN_mod_exp_mont.html]=man3/BN_mod_exp_mont.pod
+GENERATE[html/man3/BN_mod_exp_mont.html]=man3/BN_mod_exp_mont.pod
+DEPEND[man/man3/BN_mod_exp_mont.3]=man3/BN_mod_exp_mont.pod
+GENERATE[man/man3/BN_mod_exp_mont.3]=man3/BN_mod_exp_mont.pod
+DEPEND[html/man3/BN_mod_inverse.html]=man3/BN_mod_inverse.pod
+GENERATE[html/man3/BN_mod_inverse.html]=man3/BN_mod_inverse.pod
+DEPEND[man/man3/BN_mod_inverse.3]=man3/BN_mod_inverse.pod
+GENERATE[man/man3/BN_mod_inverse.3]=man3/BN_mod_inverse.pod
+DEPEND[html/man3/BN_mod_mul_montgomery.html]=man3/BN_mod_mul_montgomery.pod
+GENERATE[html/man3/BN_mod_mul_montgomery.html]=man3/BN_mod_mul_montgomery.pod
+DEPEND[man/man3/BN_mod_mul_montgomery.3]=man3/BN_mod_mul_montgomery.pod
+GENERATE[man/man3/BN_mod_mul_montgomery.3]=man3/BN_mod_mul_montgomery.pod
+DEPEND[html/man3/BN_mod_mul_reciprocal.html]=man3/BN_mod_mul_reciprocal.pod
+GENERATE[html/man3/BN_mod_mul_reciprocal.html]=man3/BN_mod_mul_reciprocal.pod
+DEPEND[man/man3/BN_mod_mul_reciprocal.3]=man3/BN_mod_mul_reciprocal.pod
+GENERATE[man/man3/BN_mod_mul_reciprocal.3]=man3/BN_mod_mul_reciprocal.pod
+DEPEND[html/man3/BN_new.html]=man3/BN_new.pod
+GENERATE[html/man3/BN_new.html]=man3/BN_new.pod
+DEPEND[man/man3/BN_new.3]=man3/BN_new.pod
+GENERATE[man/man3/BN_new.3]=man3/BN_new.pod
+DEPEND[html/man3/BN_num_bytes.html]=man3/BN_num_bytes.pod
+GENERATE[html/man3/BN_num_bytes.html]=man3/BN_num_bytes.pod
+DEPEND[man/man3/BN_num_bytes.3]=man3/BN_num_bytes.pod
+GENERATE[man/man3/BN_num_bytes.3]=man3/BN_num_bytes.pod
+DEPEND[html/man3/BN_rand.html]=man3/BN_rand.pod
+GENERATE[html/man3/BN_rand.html]=man3/BN_rand.pod
+DEPEND[man/man3/BN_rand.3]=man3/BN_rand.pod
+GENERATE[man/man3/BN_rand.3]=man3/BN_rand.pod
+DEPEND[html/man3/BN_security_bits.html]=man3/BN_security_bits.pod
+GENERATE[html/man3/BN_security_bits.html]=man3/BN_security_bits.pod
+DEPEND[man/man3/BN_security_bits.3]=man3/BN_security_bits.pod
+GENERATE[man/man3/BN_security_bits.3]=man3/BN_security_bits.pod
+DEPEND[html/man3/BN_set_bit.html]=man3/BN_set_bit.pod
+GENERATE[html/man3/BN_set_bit.html]=man3/BN_set_bit.pod
+DEPEND[man/man3/BN_set_bit.3]=man3/BN_set_bit.pod
+GENERATE[man/man3/BN_set_bit.3]=man3/BN_set_bit.pod
+DEPEND[html/man3/BN_swap.html]=man3/BN_swap.pod
+GENERATE[html/man3/BN_swap.html]=man3/BN_swap.pod
+DEPEND[man/man3/BN_swap.3]=man3/BN_swap.pod
+GENERATE[man/man3/BN_swap.3]=man3/BN_swap.pod
+DEPEND[html/man3/BN_zero.html]=man3/BN_zero.pod
+GENERATE[html/man3/BN_zero.html]=man3/BN_zero.pod
+DEPEND[man/man3/BN_zero.3]=man3/BN_zero.pod
+GENERATE[man/man3/BN_zero.3]=man3/BN_zero.pod
+DEPEND[html/man3/BUF_MEM_new.html]=man3/BUF_MEM_new.pod
+GENERATE[html/man3/BUF_MEM_new.html]=man3/BUF_MEM_new.pod
+DEPEND[man/man3/BUF_MEM_new.3]=man3/BUF_MEM_new.pod
+GENERATE[man/man3/BUF_MEM_new.3]=man3/BUF_MEM_new.pod
+DEPEND[html/man3/CMS_EncryptedData_decrypt.html]=man3/CMS_EncryptedData_decrypt.pod
+GENERATE[html/man3/CMS_EncryptedData_decrypt.html]=man3/CMS_EncryptedData_decrypt.pod
+DEPEND[man/man3/CMS_EncryptedData_decrypt.3]=man3/CMS_EncryptedData_decrypt.pod
+GENERATE[man/man3/CMS_EncryptedData_decrypt.3]=man3/CMS_EncryptedData_decrypt.pod
+DEPEND[html/man3/CMS_EncryptedData_encrypt.html]=man3/CMS_EncryptedData_encrypt.pod
+GENERATE[html/man3/CMS_EncryptedData_encrypt.html]=man3/CMS_EncryptedData_encrypt.pod
+DEPEND[man/man3/CMS_EncryptedData_encrypt.3]=man3/CMS_EncryptedData_encrypt.pod
+GENERATE[man/man3/CMS_EncryptedData_encrypt.3]=man3/CMS_EncryptedData_encrypt.pod
+DEPEND[html/man3/CMS_EnvelopedData_create.html]=man3/CMS_EnvelopedData_create.pod
+GENERATE[html/man3/CMS_EnvelopedData_create.html]=man3/CMS_EnvelopedData_create.pod
+DEPEND[man/man3/CMS_EnvelopedData_create.3]=man3/CMS_EnvelopedData_create.pod
+GENERATE[man/man3/CMS_EnvelopedData_create.3]=man3/CMS_EnvelopedData_create.pod
+DEPEND[html/man3/CMS_add0_cert.html]=man3/CMS_add0_cert.pod
+GENERATE[html/man3/CMS_add0_cert.html]=man3/CMS_add0_cert.pod
+DEPEND[man/man3/CMS_add0_cert.3]=man3/CMS_add0_cert.pod
+GENERATE[man/man3/CMS_add0_cert.3]=man3/CMS_add0_cert.pod
+DEPEND[html/man3/CMS_add1_recipient_cert.html]=man3/CMS_add1_recipient_cert.pod
+GENERATE[html/man3/CMS_add1_recipient_cert.html]=man3/CMS_add1_recipient_cert.pod
+DEPEND[man/man3/CMS_add1_recipient_cert.3]=man3/CMS_add1_recipient_cert.pod
+GENERATE[man/man3/CMS_add1_recipient_cert.3]=man3/CMS_add1_recipient_cert.pod
+DEPEND[html/man3/CMS_add1_signer.html]=man3/CMS_add1_signer.pod
+GENERATE[html/man3/CMS_add1_signer.html]=man3/CMS_add1_signer.pod
+DEPEND[man/man3/CMS_add1_signer.3]=man3/CMS_add1_signer.pod
+GENERATE[man/man3/CMS_add1_signer.3]=man3/CMS_add1_signer.pod
+DEPEND[html/man3/CMS_compress.html]=man3/CMS_compress.pod
+GENERATE[html/man3/CMS_compress.html]=man3/CMS_compress.pod
+DEPEND[man/man3/CMS_compress.3]=man3/CMS_compress.pod
+GENERATE[man/man3/CMS_compress.3]=man3/CMS_compress.pod
+DEPEND[html/man3/CMS_data_create.html]=man3/CMS_data_create.pod
+GENERATE[html/man3/CMS_data_create.html]=man3/CMS_data_create.pod
+DEPEND[man/man3/CMS_data_create.3]=man3/CMS_data_create.pod
+GENERATE[man/man3/CMS_data_create.3]=man3/CMS_data_create.pod
+DEPEND[html/man3/CMS_decrypt.html]=man3/CMS_decrypt.pod
+GENERATE[html/man3/CMS_decrypt.html]=man3/CMS_decrypt.pod
+DEPEND[man/man3/CMS_decrypt.3]=man3/CMS_decrypt.pod
+GENERATE[man/man3/CMS_decrypt.3]=man3/CMS_decrypt.pod
+DEPEND[html/man3/CMS_digest_create.html]=man3/CMS_digest_create.pod
+GENERATE[html/man3/CMS_digest_create.html]=man3/CMS_digest_create.pod
+DEPEND[man/man3/CMS_digest_create.3]=man3/CMS_digest_create.pod
+GENERATE[man/man3/CMS_digest_create.3]=man3/CMS_digest_create.pod
+DEPEND[html/man3/CMS_encrypt.html]=man3/CMS_encrypt.pod
+GENERATE[html/man3/CMS_encrypt.html]=man3/CMS_encrypt.pod
+DEPEND[man/man3/CMS_encrypt.3]=man3/CMS_encrypt.pod
+GENERATE[man/man3/CMS_encrypt.3]=man3/CMS_encrypt.pod
+DEPEND[html/man3/CMS_final.html]=man3/CMS_final.pod
+GENERATE[html/man3/CMS_final.html]=man3/CMS_final.pod
+DEPEND[man/man3/CMS_final.3]=man3/CMS_final.pod
+GENERATE[man/man3/CMS_final.3]=man3/CMS_final.pod
+DEPEND[html/man3/CMS_get0_RecipientInfos.html]=man3/CMS_get0_RecipientInfos.pod
+GENERATE[html/man3/CMS_get0_RecipientInfos.html]=man3/CMS_get0_RecipientInfos.pod
+DEPEND[man/man3/CMS_get0_RecipientInfos.3]=man3/CMS_get0_RecipientInfos.pod
+GENERATE[man/man3/CMS_get0_RecipientInfos.3]=man3/CMS_get0_RecipientInfos.pod
+DEPEND[html/man3/CMS_get0_SignerInfos.html]=man3/CMS_get0_SignerInfos.pod
+GENERATE[html/man3/CMS_get0_SignerInfos.html]=man3/CMS_get0_SignerInfos.pod
+DEPEND[man/man3/CMS_get0_SignerInfos.3]=man3/CMS_get0_SignerInfos.pod
+GENERATE[man/man3/CMS_get0_SignerInfos.3]=man3/CMS_get0_SignerInfos.pod
+DEPEND[html/man3/CMS_get0_type.html]=man3/CMS_get0_type.pod
+GENERATE[html/man3/CMS_get0_type.html]=man3/CMS_get0_type.pod
+DEPEND[man/man3/CMS_get0_type.3]=man3/CMS_get0_type.pod
+GENERATE[man/man3/CMS_get0_type.3]=man3/CMS_get0_type.pod
+DEPEND[html/man3/CMS_get1_ReceiptRequest.html]=man3/CMS_get1_ReceiptRequest.pod
+GENERATE[html/man3/CMS_get1_ReceiptRequest.html]=man3/CMS_get1_ReceiptRequest.pod
+DEPEND[man/man3/CMS_get1_ReceiptRequest.3]=man3/CMS_get1_ReceiptRequest.pod
+GENERATE[man/man3/CMS_get1_ReceiptRequest.3]=man3/CMS_get1_ReceiptRequest.pod
+DEPEND[html/man3/CMS_sign.html]=man3/CMS_sign.pod
+GENERATE[html/man3/CMS_sign.html]=man3/CMS_sign.pod
+DEPEND[man/man3/CMS_sign.3]=man3/CMS_sign.pod
+GENERATE[man/man3/CMS_sign.3]=man3/CMS_sign.pod
+DEPEND[html/man3/CMS_sign_receipt.html]=man3/CMS_sign_receipt.pod
+GENERATE[html/man3/CMS_sign_receipt.html]=man3/CMS_sign_receipt.pod
+DEPEND[man/man3/CMS_sign_receipt.3]=man3/CMS_sign_receipt.pod
+GENERATE[man/man3/CMS_sign_receipt.3]=man3/CMS_sign_receipt.pod
+DEPEND[html/man3/CMS_uncompress.html]=man3/CMS_uncompress.pod
+GENERATE[html/man3/CMS_uncompress.html]=man3/CMS_uncompress.pod
+DEPEND[man/man3/CMS_uncompress.3]=man3/CMS_uncompress.pod
+GENERATE[man/man3/CMS_uncompress.3]=man3/CMS_uncompress.pod
+DEPEND[html/man3/CMS_verify.html]=man3/CMS_verify.pod
+GENERATE[html/man3/CMS_verify.html]=man3/CMS_verify.pod
+DEPEND[man/man3/CMS_verify.3]=man3/CMS_verify.pod
+GENERATE[man/man3/CMS_verify.3]=man3/CMS_verify.pod
+DEPEND[html/man3/CMS_verify_receipt.html]=man3/CMS_verify_receipt.pod
+GENERATE[html/man3/CMS_verify_receipt.html]=man3/CMS_verify_receipt.pod
+DEPEND[man/man3/CMS_verify_receipt.3]=man3/CMS_verify_receipt.pod
+GENERATE[man/man3/CMS_verify_receipt.3]=man3/CMS_verify_receipt.pod
+DEPEND[html/man3/CONF_modules_free.html]=man3/CONF_modules_free.pod
+GENERATE[html/man3/CONF_modules_free.html]=man3/CONF_modules_free.pod
+DEPEND[man/man3/CONF_modules_free.3]=man3/CONF_modules_free.pod
+GENERATE[man/man3/CONF_modules_free.3]=man3/CONF_modules_free.pod
+DEPEND[html/man3/CONF_modules_load_file.html]=man3/CONF_modules_load_file.pod
+GENERATE[html/man3/CONF_modules_load_file.html]=man3/CONF_modules_load_file.pod
+DEPEND[man/man3/CONF_modules_load_file.3]=man3/CONF_modules_load_file.pod
+GENERATE[man/man3/CONF_modules_load_file.3]=man3/CONF_modules_load_file.pod
+DEPEND[html/man3/CRYPTO_THREAD_run_once.html]=man3/CRYPTO_THREAD_run_once.pod
+GENERATE[html/man3/CRYPTO_THREAD_run_once.html]=man3/CRYPTO_THREAD_run_once.pod
+DEPEND[man/man3/CRYPTO_THREAD_run_once.3]=man3/CRYPTO_THREAD_run_once.pod
+GENERATE[man/man3/CRYPTO_THREAD_run_once.3]=man3/CRYPTO_THREAD_run_once.pod
+DEPEND[html/man3/CRYPTO_get_ex_new_index.html]=man3/CRYPTO_get_ex_new_index.pod
+GENERATE[html/man3/CRYPTO_get_ex_new_index.html]=man3/CRYPTO_get_ex_new_index.pod
+DEPEND[man/man3/CRYPTO_get_ex_new_index.3]=man3/CRYPTO_get_ex_new_index.pod
+GENERATE[man/man3/CRYPTO_get_ex_new_index.3]=man3/CRYPTO_get_ex_new_index.pod
+DEPEND[html/man3/CRYPTO_memcmp.html]=man3/CRYPTO_memcmp.pod
+GENERATE[html/man3/CRYPTO_memcmp.html]=man3/CRYPTO_memcmp.pod
+DEPEND[man/man3/CRYPTO_memcmp.3]=man3/CRYPTO_memcmp.pod
+GENERATE[man/man3/CRYPTO_memcmp.3]=man3/CRYPTO_memcmp.pod
+DEPEND[html/man3/CTLOG_STORE_get0_log_by_id.html]=man3/CTLOG_STORE_get0_log_by_id.pod
+GENERATE[html/man3/CTLOG_STORE_get0_log_by_id.html]=man3/CTLOG_STORE_get0_log_by_id.pod
+DEPEND[man/man3/CTLOG_STORE_get0_log_by_id.3]=man3/CTLOG_STORE_get0_log_by_id.pod
+GENERATE[man/man3/CTLOG_STORE_get0_log_by_id.3]=man3/CTLOG_STORE_get0_log_by_id.pod
+DEPEND[html/man3/CTLOG_STORE_new.html]=man3/CTLOG_STORE_new.pod
+GENERATE[html/man3/CTLOG_STORE_new.html]=man3/CTLOG_STORE_new.pod
+DEPEND[man/man3/CTLOG_STORE_new.3]=man3/CTLOG_STORE_new.pod
+GENERATE[man/man3/CTLOG_STORE_new.3]=man3/CTLOG_STORE_new.pod
+DEPEND[html/man3/CTLOG_new.html]=man3/CTLOG_new.pod
+GENERATE[html/man3/CTLOG_new.html]=man3/CTLOG_new.pod
+DEPEND[man/man3/CTLOG_new.3]=man3/CTLOG_new.pod
+GENERATE[man/man3/CTLOG_new.3]=man3/CTLOG_new.pod
+DEPEND[html/man3/CT_POLICY_EVAL_CTX_new.html]=man3/CT_POLICY_EVAL_CTX_new.pod
+GENERATE[html/man3/CT_POLICY_EVAL_CTX_new.html]=man3/CT_POLICY_EVAL_CTX_new.pod
+DEPEND[man/man3/CT_POLICY_EVAL_CTX_new.3]=man3/CT_POLICY_EVAL_CTX_new.pod
+GENERATE[man/man3/CT_POLICY_EVAL_CTX_new.3]=man3/CT_POLICY_EVAL_CTX_new.pod
+DEPEND[html/man3/DEFINE_STACK_OF.html]=man3/DEFINE_STACK_OF.pod
+GENERATE[html/man3/DEFINE_STACK_OF.html]=man3/DEFINE_STACK_OF.pod
+DEPEND[man/man3/DEFINE_STACK_OF.3]=man3/DEFINE_STACK_OF.pod
+GENERATE[man/man3/DEFINE_STACK_OF.3]=man3/DEFINE_STACK_OF.pod
+DEPEND[html/man3/DES_random_key.html]=man3/DES_random_key.pod
+GENERATE[html/man3/DES_random_key.html]=man3/DES_random_key.pod
+DEPEND[man/man3/DES_random_key.3]=man3/DES_random_key.pod
+GENERATE[man/man3/DES_random_key.3]=man3/DES_random_key.pod
+DEPEND[html/man3/DH_generate_key.html]=man3/DH_generate_key.pod
+GENERATE[html/man3/DH_generate_key.html]=man3/DH_generate_key.pod
+DEPEND[man/man3/DH_generate_key.3]=man3/DH_generate_key.pod
+GENERATE[man/man3/DH_generate_key.3]=man3/DH_generate_key.pod
+DEPEND[html/man3/DH_generate_parameters.html]=man3/DH_generate_parameters.pod
+GENERATE[html/man3/DH_generate_parameters.html]=man3/DH_generate_parameters.pod
+DEPEND[man/man3/DH_generate_parameters.3]=man3/DH_generate_parameters.pod
+GENERATE[man/man3/DH_generate_parameters.3]=man3/DH_generate_parameters.pod
+DEPEND[html/man3/DH_get0_pqg.html]=man3/DH_get0_pqg.pod
+GENERATE[html/man3/DH_get0_pqg.html]=man3/DH_get0_pqg.pod
+DEPEND[man/man3/DH_get0_pqg.3]=man3/DH_get0_pqg.pod
+GENERATE[man/man3/DH_get0_pqg.3]=man3/DH_get0_pqg.pod
+DEPEND[html/man3/DH_get_1024_160.html]=man3/DH_get_1024_160.pod
+GENERATE[html/man3/DH_get_1024_160.html]=man3/DH_get_1024_160.pod
+DEPEND[man/man3/DH_get_1024_160.3]=man3/DH_get_1024_160.pod
+GENERATE[man/man3/DH_get_1024_160.3]=man3/DH_get_1024_160.pod
+DEPEND[html/man3/DH_meth_new.html]=man3/DH_meth_new.pod
+GENERATE[html/man3/DH_meth_new.html]=man3/DH_meth_new.pod
+DEPEND[man/man3/DH_meth_new.3]=man3/DH_meth_new.pod
+GENERATE[man/man3/DH_meth_new.3]=man3/DH_meth_new.pod
+DEPEND[html/man3/DH_new.html]=man3/DH_new.pod
+GENERATE[html/man3/DH_new.html]=man3/DH_new.pod
+DEPEND[man/man3/DH_new.3]=man3/DH_new.pod
+GENERATE[man/man3/DH_new.3]=man3/DH_new.pod
+DEPEND[html/man3/DH_new_by_nid.html]=man3/DH_new_by_nid.pod
+GENERATE[html/man3/DH_new_by_nid.html]=man3/DH_new_by_nid.pod
+DEPEND[man/man3/DH_new_by_nid.3]=man3/DH_new_by_nid.pod
+GENERATE[man/man3/DH_new_by_nid.3]=man3/DH_new_by_nid.pod
+DEPEND[html/man3/DH_set_method.html]=man3/DH_set_method.pod
+GENERATE[html/man3/DH_set_method.html]=man3/DH_set_method.pod
+DEPEND[man/man3/DH_set_method.3]=man3/DH_set_method.pod
+GENERATE[man/man3/DH_set_method.3]=man3/DH_set_method.pod
+DEPEND[html/man3/DH_size.html]=man3/DH_size.pod
+GENERATE[html/man3/DH_size.html]=man3/DH_size.pod
+DEPEND[man/man3/DH_size.3]=man3/DH_size.pod
+GENERATE[man/man3/DH_size.3]=man3/DH_size.pod
+DEPEND[html/man3/DSA_SIG_new.html]=man3/DSA_SIG_new.pod
+GENERATE[html/man3/DSA_SIG_new.html]=man3/DSA_SIG_new.pod
+DEPEND[man/man3/DSA_SIG_new.3]=man3/DSA_SIG_new.pod
+GENERATE[man/man3/DSA_SIG_new.3]=man3/DSA_SIG_new.pod
+DEPEND[html/man3/DSA_do_sign.html]=man3/DSA_do_sign.pod
+GENERATE[html/man3/DSA_do_sign.html]=man3/DSA_do_sign.pod
+DEPEND[man/man3/DSA_do_sign.3]=man3/DSA_do_sign.pod
+GENERATE[man/man3/DSA_do_sign.3]=man3/DSA_do_sign.pod
+DEPEND[html/man3/DSA_dup_DH.html]=man3/DSA_dup_DH.pod
+GENERATE[html/man3/DSA_dup_DH.html]=man3/DSA_dup_DH.pod
+DEPEND[man/man3/DSA_dup_DH.3]=man3/DSA_dup_DH.pod
+GENERATE[man/man3/DSA_dup_DH.3]=man3/DSA_dup_DH.pod
+DEPEND[html/man3/DSA_generate_key.html]=man3/DSA_generate_key.pod
+GENERATE[html/man3/DSA_generate_key.html]=man3/DSA_generate_key.pod
+DEPEND[man/man3/DSA_generate_key.3]=man3/DSA_generate_key.pod
+GENERATE[man/man3/DSA_generate_key.3]=man3/DSA_generate_key.pod
+DEPEND[html/man3/DSA_generate_parameters.html]=man3/DSA_generate_parameters.pod
+GENERATE[html/man3/DSA_generate_parameters.html]=man3/DSA_generate_parameters.pod
+DEPEND[man/man3/DSA_generate_parameters.3]=man3/DSA_generate_parameters.pod
+GENERATE[man/man3/DSA_generate_parameters.3]=man3/DSA_generate_parameters.pod
+DEPEND[html/man3/DSA_get0_pqg.html]=man3/DSA_get0_pqg.pod
+GENERATE[html/man3/DSA_get0_pqg.html]=man3/DSA_get0_pqg.pod
+DEPEND[man/man3/DSA_get0_pqg.3]=man3/DSA_get0_pqg.pod
+GENERATE[man/man3/DSA_get0_pqg.3]=man3/DSA_get0_pqg.pod
+DEPEND[html/man3/DSA_meth_new.html]=man3/DSA_meth_new.pod
+GENERATE[html/man3/DSA_meth_new.html]=man3/DSA_meth_new.pod
+DEPEND[man/man3/DSA_meth_new.3]=man3/DSA_meth_new.pod
+GENERATE[man/man3/DSA_meth_new.3]=man3/DSA_meth_new.pod
+DEPEND[html/man3/DSA_new.html]=man3/DSA_new.pod
+GENERATE[html/man3/DSA_new.html]=man3/DSA_new.pod
+DEPEND[man/man3/DSA_new.3]=man3/DSA_new.pod
+GENERATE[man/man3/DSA_new.3]=man3/DSA_new.pod
+DEPEND[html/man3/DSA_set_method.html]=man3/DSA_set_method.pod
+GENERATE[html/man3/DSA_set_method.html]=man3/DSA_set_method.pod
+DEPEND[man/man3/DSA_set_method.3]=man3/DSA_set_method.pod
+GENERATE[man/man3/DSA_set_method.3]=man3/DSA_set_method.pod
+DEPEND[html/man3/DSA_sign.html]=man3/DSA_sign.pod
+GENERATE[html/man3/DSA_sign.html]=man3/DSA_sign.pod
+DEPEND[man/man3/DSA_sign.3]=man3/DSA_sign.pod
+GENERATE[man/man3/DSA_sign.3]=man3/DSA_sign.pod
+DEPEND[html/man3/DSA_size.html]=man3/DSA_size.pod
+GENERATE[html/man3/DSA_size.html]=man3/DSA_size.pod
+DEPEND[man/man3/DSA_size.3]=man3/DSA_size.pod
+GENERATE[man/man3/DSA_size.3]=man3/DSA_size.pod
+DEPEND[html/man3/DTLS_get_data_mtu.html]=man3/DTLS_get_data_mtu.pod
+GENERATE[html/man3/DTLS_get_data_mtu.html]=man3/DTLS_get_data_mtu.pod
+DEPEND[man/man3/DTLS_get_data_mtu.3]=man3/DTLS_get_data_mtu.pod
+GENERATE[man/man3/DTLS_get_data_mtu.3]=man3/DTLS_get_data_mtu.pod
+DEPEND[html/man3/DTLS_set_timer_cb.html]=man3/DTLS_set_timer_cb.pod
+GENERATE[html/man3/DTLS_set_timer_cb.html]=man3/DTLS_set_timer_cb.pod
+DEPEND[man/man3/DTLS_set_timer_cb.3]=man3/DTLS_set_timer_cb.pod
+GENERATE[man/man3/DTLS_set_timer_cb.3]=man3/DTLS_set_timer_cb.pod
+DEPEND[html/man3/DTLSv1_listen.html]=man3/DTLSv1_listen.pod
+GENERATE[html/man3/DTLSv1_listen.html]=man3/DTLSv1_listen.pod
+DEPEND[man/man3/DTLSv1_listen.3]=man3/DTLSv1_listen.pod
+GENERATE[man/man3/DTLSv1_listen.3]=man3/DTLSv1_listen.pod
+DEPEND[html/man3/ECDSA_SIG_new.html]=man3/ECDSA_SIG_new.pod
+GENERATE[html/man3/ECDSA_SIG_new.html]=man3/ECDSA_SIG_new.pod
+DEPEND[man/man3/ECDSA_SIG_new.3]=man3/ECDSA_SIG_new.pod
+GENERATE[man/man3/ECDSA_SIG_new.3]=man3/ECDSA_SIG_new.pod
+DEPEND[html/man3/ECDSA_sign.html]=man3/ECDSA_sign.pod
+GENERATE[html/man3/ECDSA_sign.html]=man3/ECDSA_sign.pod
+DEPEND[man/man3/ECDSA_sign.3]=man3/ECDSA_sign.pod
+GENERATE[man/man3/ECDSA_sign.3]=man3/ECDSA_sign.pod
+DEPEND[html/man3/ECPKParameters_print.html]=man3/ECPKParameters_print.pod
+GENERATE[html/man3/ECPKParameters_print.html]=man3/ECPKParameters_print.pod
+DEPEND[man/man3/ECPKParameters_print.3]=man3/ECPKParameters_print.pod
+GENERATE[man/man3/ECPKParameters_print.3]=man3/ECPKParameters_print.pod
+DEPEND[html/man3/EC_GFp_simple_method.html]=man3/EC_GFp_simple_method.pod
+GENERATE[html/man3/EC_GFp_simple_method.html]=man3/EC_GFp_simple_method.pod
+DEPEND[man/man3/EC_GFp_simple_method.3]=man3/EC_GFp_simple_method.pod
+GENERATE[man/man3/EC_GFp_simple_method.3]=man3/EC_GFp_simple_method.pod
+DEPEND[html/man3/EC_GROUP_copy.html]=man3/EC_GROUP_copy.pod
+GENERATE[html/man3/EC_GROUP_copy.html]=man3/EC_GROUP_copy.pod
+DEPEND[man/man3/EC_GROUP_copy.3]=man3/EC_GROUP_copy.pod
+GENERATE[man/man3/EC_GROUP_copy.3]=man3/EC_GROUP_copy.pod
+DEPEND[html/man3/EC_GROUP_new.html]=man3/EC_GROUP_new.pod
+GENERATE[html/man3/EC_GROUP_new.html]=man3/EC_GROUP_new.pod
+DEPEND[man/man3/EC_GROUP_new.3]=man3/EC_GROUP_new.pod
+GENERATE[man/man3/EC_GROUP_new.3]=man3/EC_GROUP_new.pod
+DEPEND[html/man3/EC_KEY_get_enc_flags.html]=man3/EC_KEY_get_enc_flags.pod
+GENERATE[html/man3/EC_KEY_get_enc_flags.html]=man3/EC_KEY_get_enc_flags.pod
+DEPEND[man/man3/EC_KEY_get_enc_flags.3]=man3/EC_KEY_get_enc_flags.pod
+GENERATE[man/man3/EC_KEY_get_enc_flags.3]=man3/EC_KEY_get_enc_flags.pod
+DEPEND[html/man3/EC_KEY_new.html]=man3/EC_KEY_new.pod
+GENERATE[html/man3/EC_KEY_new.html]=man3/EC_KEY_new.pod
+DEPEND[man/man3/EC_KEY_new.3]=man3/EC_KEY_new.pod
+GENERATE[man/man3/EC_KEY_new.3]=man3/EC_KEY_new.pod
+DEPEND[html/man3/EC_POINT_add.html]=man3/EC_POINT_add.pod
+GENERATE[html/man3/EC_POINT_add.html]=man3/EC_POINT_add.pod
+DEPEND[man/man3/EC_POINT_add.3]=man3/EC_POINT_add.pod
+GENERATE[man/man3/EC_POINT_add.3]=man3/EC_POINT_add.pod
+DEPEND[html/man3/EC_POINT_new.html]=man3/EC_POINT_new.pod
+GENERATE[html/man3/EC_POINT_new.html]=man3/EC_POINT_new.pod
+DEPEND[man/man3/EC_POINT_new.3]=man3/EC_POINT_new.pod
+GENERATE[man/man3/EC_POINT_new.3]=man3/EC_POINT_new.pod
+DEPEND[html/man3/ENGINE_add.html]=man3/ENGINE_add.pod
+GENERATE[html/man3/ENGINE_add.html]=man3/ENGINE_add.pod
+DEPEND[man/man3/ENGINE_add.3]=man3/ENGINE_add.pod
+GENERATE[man/man3/ENGINE_add.3]=man3/ENGINE_add.pod
+DEPEND[html/man3/ERR_GET_LIB.html]=man3/ERR_GET_LIB.pod
+GENERATE[html/man3/ERR_GET_LIB.html]=man3/ERR_GET_LIB.pod
+DEPEND[man/man3/ERR_GET_LIB.3]=man3/ERR_GET_LIB.pod
+GENERATE[man/man3/ERR_GET_LIB.3]=man3/ERR_GET_LIB.pod
+DEPEND[html/man3/ERR_clear_error.html]=man3/ERR_clear_error.pod
+GENERATE[html/man3/ERR_clear_error.html]=man3/ERR_clear_error.pod
+DEPEND[man/man3/ERR_clear_error.3]=man3/ERR_clear_error.pod
+GENERATE[man/man3/ERR_clear_error.3]=man3/ERR_clear_error.pod
+DEPEND[html/man3/ERR_error_string.html]=man3/ERR_error_string.pod
+GENERATE[html/man3/ERR_error_string.html]=man3/ERR_error_string.pod
+DEPEND[man/man3/ERR_error_string.3]=man3/ERR_error_string.pod
+GENERATE[man/man3/ERR_error_string.3]=man3/ERR_error_string.pod
+DEPEND[html/man3/ERR_get_error.html]=man3/ERR_get_error.pod
+GENERATE[html/man3/ERR_get_error.html]=man3/ERR_get_error.pod
+DEPEND[man/man3/ERR_get_error.3]=man3/ERR_get_error.pod
+GENERATE[man/man3/ERR_get_error.3]=man3/ERR_get_error.pod
+DEPEND[html/man3/ERR_load_crypto_strings.html]=man3/ERR_load_crypto_strings.pod
+GENERATE[html/man3/ERR_load_crypto_strings.html]=man3/ERR_load_crypto_strings.pod
+DEPEND[man/man3/ERR_load_crypto_strings.3]=man3/ERR_load_crypto_strings.pod
+GENERATE[man/man3/ERR_load_crypto_strings.3]=man3/ERR_load_crypto_strings.pod
+DEPEND[html/man3/ERR_load_strings.html]=man3/ERR_load_strings.pod
+GENERATE[html/man3/ERR_load_strings.html]=man3/ERR_load_strings.pod
+DEPEND[man/man3/ERR_load_strings.3]=man3/ERR_load_strings.pod
+GENERATE[man/man3/ERR_load_strings.3]=man3/ERR_load_strings.pod
+DEPEND[html/man3/ERR_new.html]=man3/ERR_new.pod
+GENERATE[html/man3/ERR_new.html]=man3/ERR_new.pod
+DEPEND[man/man3/ERR_new.3]=man3/ERR_new.pod
+GENERATE[man/man3/ERR_new.3]=man3/ERR_new.pod
+DEPEND[html/man3/ERR_print_errors.html]=man3/ERR_print_errors.pod
+GENERATE[html/man3/ERR_print_errors.html]=man3/ERR_print_errors.pod
+DEPEND[man/man3/ERR_print_errors.3]=man3/ERR_print_errors.pod
+GENERATE[man/man3/ERR_print_errors.3]=man3/ERR_print_errors.pod
+DEPEND[html/man3/ERR_put_error.html]=man3/ERR_put_error.pod
+GENERATE[html/man3/ERR_put_error.html]=man3/ERR_put_error.pod
+DEPEND[man/man3/ERR_put_error.3]=man3/ERR_put_error.pod
+GENERATE[man/man3/ERR_put_error.3]=man3/ERR_put_error.pod
+DEPEND[html/man3/ERR_remove_state.html]=man3/ERR_remove_state.pod
+GENERATE[html/man3/ERR_remove_state.html]=man3/ERR_remove_state.pod
+DEPEND[man/man3/ERR_remove_state.3]=man3/ERR_remove_state.pod
+GENERATE[man/man3/ERR_remove_state.3]=man3/ERR_remove_state.pod
+DEPEND[html/man3/ERR_set_mark.html]=man3/ERR_set_mark.pod
+GENERATE[html/man3/ERR_set_mark.html]=man3/ERR_set_mark.pod
+DEPEND[man/man3/ERR_set_mark.3]=man3/ERR_set_mark.pod
+GENERATE[man/man3/ERR_set_mark.3]=man3/ERR_set_mark.pod
+DEPEND[html/man3/EVP_ASYM_CIPHER_free.html]=man3/EVP_ASYM_CIPHER_free.pod
+GENERATE[html/man3/EVP_ASYM_CIPHER_free.html]=man3/EVP_ASYM_CIPHER_free.pod
+DEPEND[man/man3/EVP_ASYM_CIPHER_free.3]=man3/EVP_ASYM_CIPHER_free.pod
+GENERATE[man/man3/EVP_ASYM_CIPHER_free.3]=man3/EVP_ASYM_CIPHER_free.pod
+DEPEND[html/man3/EVP_BytesToKey.html]=man3/EVP_BytesToKey.pod
+GENERATE[html/man3/EVP_BytesToKey.html]=man3/EVP_BytesToKey.pod
+DEPEND[man/man3/EVP_BytesToKey.3]=man3/EVP_BytesToKey.pod
+GENERATE[man/man3/EVP_BytesToKey.3]=man3/EVP_BytesToKey.pod
+DEPEND[html/man3/EVP_CIPHER_CTX_get_cipher_data.html]=man3/EVP_CIPHER_CTX_get_cipher_data.pod
+GENERATE[html/man3/EVP_CIPHER_CTX_get_cipher_data.html]=man3/EVP_CIPHER_CTX_get_cipher_data.pod
+DEPEND[man/man3/EVP_CIPHER_CTX_get_cipher_data.3]=man3/EVP_CIPHER_CTX_get_cipher_data.pod
+GENERATE[man/man3/EVP_CIPHER_CTX_get_cipher_data.3]=man3/EVP_CIPHER_CTX_get_cipher_data.pod
+DEPEND[html/man3/EVP_CIPHER_CTX_get_original_iv.html]=man3/EVP_CIPHER_CTX_get_original_iv.pod
+GENERATE[html/man3/EVP_CIPHER_CTX_get_original_iv.html]=man3/EVP_CIPHER_CTX_get_original_iv.pod
+DEPEND[man/man3/EVP_CIPHER_CTX_get_original_iv.3]=man3/EVP_CIPHER_CTX_get_original_iv.pod
+GENERATE[man/man3/EVP_CIPHER_CTX_get_original_iv.3]=man3/EVP_CIPHER_CTX_get_original_iv.pod
+DEPEND[html/man3/EVP_CIPHER_meth_new.html]=man3/EVP_CIPHER_meth_new.pod
+GENERATE[html/man3/EVP_CIPHER_meth_new.html]=man3/EVP_CIPHER_meth_new.pod
+DEPEND[man/man3/EVP_CIPHER_meth_new.3]=man3/EVP_CIPHER_meth_new.pod
+GENERATE[man/man3/EVP_CIPHER_meth_new.3]=man3/EVP_CIPHER_meth_new.pod
+DEPEND[html/man3/EVP_DigestInit.html]=man3/EVP_DigestInit.pod
+GENERATE[html/man3/EVP_DigestInit.html]=man3/EVP_DigestInit.pod
+DEPEND[man/man3/EVP_DigestInit.3]=man3/EVP_DigestInit.pod
+GENERATE[man/man3/EVP_DigestInit.3]=man3/EVP_DigestInit.pod
+DEPEND[html/man3/EVP_DigestSignInit.html]=man3/EVP_DigestSignInit.pod
+GENERATE[html/man3/EVP_DigestSignInit.html]=man3/EVP_DigestSignInit.pod
+DEPEND[man/man3/EVP_DigestSignInit.3]=man3/EVP_DigestSignInit.pod
+GENERATE[man/man3/EVP_DigestSignInit.3]=man3/EVP_DigestSignInit.pod
+DEPEND[html/man3/EVP_DigestVerifyInit.html]=man3/EVP_DigestVerifyInit.pod
+GENERATE[html/man3/EVP_DigestVerifyInit.html]=man3/EVP_DigestVerifyInit.pod
+DEPEND[man/man3/EVP_DigestVerifyInit.3]=man3/EVP_DigestVerifyInit.pod
+GENERATE[man/man3/EVP_DigestVerifyInit.3]=man3/EVP_DigestVerifyInit.pod
+DEPEND[html/man3/EVP_EncodeInit.html]=man3/EVP_EncodeInit.pod
+GENERATE[html/man3/EVP_EncodeInit.html]=man3/EVP_EncodeInit.pod
+DEPEND[man/man3/EVP_EncodeInit.3]=man3/EVP_EncodeInit.pod
+GENERATE[man/man3/EVP_EncodeInit.3]=man3/EVP_EncodeInit.pod
+DEPEND[html/man3/EVP_EncryptInit.html]=man3/EVP_EncryptInit.pod
+GENERATE[html/man3/EVP_EncryptInit.html]=man3/EVP_EncryptInit.pod
+DEPEND[man/man3/EVP_EncryptInit.3]=man3/EVP_EncryptInit.pod
+GENERATE[man/man3/EVP_EncryptInit.3]=man3/EVP_EncryptInit.pod
+DEPEND[html/man3/EVP_KDF.html]=man3/EVP_KDF.pod
+GENERATE[html/man3/EVP_KDF.html]=man3/EVP_KDF.pod
+DEPEND[man/man3/EVP_KDF.3]=man3/EVP_KDF.pod
+GENERATE[man/man3/EVP_KDF.3]=man3/EVP_KDF.pod
+DEPEND[html/man3/EVP_KEM_free.html]=man3/EVP_KEM_free.pod
+GENERATE[html/man3/EVP_KEM_free.html]=man3/EVP_KEM_free.pod
+DEPEND[man/man3/EVP_KEM_free.3]=man3/EVP_KEM_free.pod
+GENERATE[man/man3/EVP_KEM_free.3]=man3/EVP_KEM_free.pod
+DEPEND[html/man3/EVP_KEYEXCH_free.html]=man3/EVP_KEYEXCH_free.pod
+GENERATE[html/man3/EVP_KEYEXCH_free.html]=man3/EVP_KEYEXCH_free.pod
+DEPEND[man/man3/EVP_KEYEXCH_free.3]=man3/EVP_KEYEXCH_free.pod
+GENERATE[man/man3/EVP_KEYEXCH_free.3]=man3/EVP_KEYEXCH_free.pod
+DEPEND[html/man3/EVP_KEYMGMT.html]=man3/EVP_KEYMGMT.pod
+GENERATE[html/man3/EVP_KEYMGMT.html]=man3/EVP_KEYMGMT.pod
+DEPEND[man/man3/EVP_KEYMGMT.3]=man3/EVP_KEYMGMT.pod
+GENERATE[man/man3/EVP_KEYMGMT.3]=man3/EVP_KEYMGMT.pod
+DEPEND[html/man3/EVP_MAC.html]=man3/EVP_MAC.pod
+GENERATE[html/man3/EVP_MAC.html]=man3/EVP_MAC.pod
+DEPEND[man/man3/EVP_MAC.3]=man3/EVP_MAC.pod
+GENERATE[man/man3/EVP_MAC.3]=man3/EVP_MAC.pod
+DEPEND[html/man3/EVP_MD_meth_new.html]=man3/EVP_MD_meth_new.pod
+GENERATE[html/man3/EVP_MD_meth_new.html]=man3/EVP_MD_meth_new.pod
+DEPEND[man/man3/EVP_MD_meth_new.3]=man3/EVP_MD_meth_new.pod
+GENERATE[man/man3/EVP_MD_meth_new.3]=man3/EVP_MD_meth_new.pod
+DEPEND[html/man3/EVP_OpenInit.html]=man3/EVP_OpenInit.pod
+GENERATE[html/man3/EVP_OpenInit.html]=man3/EVP_OpenInit.pod
+DEPEND[man/man3/EVP_OpenInit.3]=man3/EVP_OpenInit.pod
+GENERATE[man/man3/EVP_OpenInit.3]=man3/EVP_OpenInit.pod
+DEPEND[html/man3/EVP_PBE_CipherInit.html]=man3/EVP_PBE_CipherInit.pod
+GENERATE[html/man3/EVP_PBE_CipherInit.html]=man3/EVP_PBE_CipherInit.pod
+DEPEND[man/man3/EVP_PBE_CipherInit.3]=man3/EVP_PBE_CipherInit.pod
+GENERATE[man/man3/EVP_PBE_CipherInit.3]=man3/EVP_PBE_CipherInit.pod
+DEPEND[html/man3/EVP_PKEY2PKCS8.html]=man3/EVP_PKEY2PKCS8.pod
+GENERATE[html/man3/EVP_PKEY2PKCS8.html]=man3/EVP_PKEY2PKCS8.pod
+DEPEND[man/man3/EVP_PKEY2PKCS8.3]=man3/EVP_PKEY2PKCS8.pod
+GENERATE[man/man3/EVP_PKEY2PKCS8.3]=man3/EVP_PKEY2PKCS8.pod
+DEPEND[html/man3/EVP_PKEY_ASN1_METHOD.html]=man3/EVP_PKEY_ASN1_METHOD.pod
+GENERATE[html/man3/EVP_PKEY_ASN1_METHOD.html]=man3/EVP_PKEY_ASN1_METHOD.pod
+DEPEND[man/man3/EVP_PKEY_ASN1_METHOD.3]=man3/EVP_PKEY_ASN1_METHOD.pod
+GENERATE[man/man3/EVP_PKEY_ASN1_METHOD.3]=man3/EVP_PKEY_ASN1_METHOD.pod
+DEPEND[html/man3/EVP_PKEY_CTX_ctrl.html]=man3/EVP_PKEY_CTX_ctrl.pod
+GENERATE[html/man3/EVP_PKEY_CTX_ctrl.html]=man3/EVP_PKEY_CTX_ctrl.pod
+DEPEND[man/man3/EVP_PKEY_CTX_ctrl.3]=man3/EVP_PKEY_CTX_ctrl.pod
+GENERATE[man/man3/EVP_PKEY_CTX_ctrl.3]=man3/EVP_PKEY_CTX_ctrl.pod
+DEPEND[html/man3/EVP_PKEY_CTX_get0_libctx.html]=man3/EVP_PKEY_CTX_get0_libctx.pod
+GENERATE[html/man3/EVP_PKEY_CTX_get0_libctx.html]=man3/EVP_PKEY_CTX_get0_libctx.pod
+DEPEND[man/man3/EVP_PKEY_CTX_get0_libctx.3]=man3/EVP_PKEY_CTX_get0_libctx.pod
+GENERATE[man/man3/EVP_PKEY_CTX_get0_libctx.3]=man3/EVP_PKEY_CTX_get0_libctx.pod
+DEPEND[html/man3/EVP_PKEY_CTX_get0_pkey.html]=man3/EVP_PKEY_CTX_get0_pkey.pod
+GENERATE[html/man3/EVP_PKEY_CTX_get0_pkey.html]=man3/EVP_PKEY_CTX_get0_pkey.pod
+DEPEND[man/man3/EVP_PKEY_CTX_get0_pkey.3]=man3/EVP_PKEY_CTX_get0_pkey.pod
+GENERATE[man/man3/EVP_PKEY_CTX_get0_pkey.3]=man3/EVP_PKEY_CTX_get0_pkey.pod
+DEPEND[html/man3/EVP_PKEY_CTX_new.html]=man3/EVP_PKEY_CTX_new.pod
+GENERATE[html/man3/EVP_PKEY_CTX_new.html]=man3/EVP_PKEY_CTX_new.pod
+DEPEND[man/man3/EVP_PKEY_CTX_new.3]=man3/EVP_PKEY_CTX_new.pod
+GENERATE[man/man3/EVP_PKEY_CTX_new.3]=man3/EVP_PKEY_CTX_new.pod
+DEPEND[html/man3/EVP_PKEY_CTX_set1_pbe_pass.html]=man3/EVP_PKEY_CTX_set1_pbe_pass.pod
+GENERATE[html/man3/EVP_PKEY_CTX_set1_pbe_pass.html]=man3/EVP_PKEY_CTX_set1_pbe_pass.pod
+DEPEND[man/man3/EVP_PKEY_CTX_set1_pbe_pass.3]=man3/EVP_PKEY_CTX_set1_pbe_pass.pod
+GENERATE[man/man3/EVP_PKEY_CTX_set1_pbe_pass.3]=man3/EVP_PKEY_CTX_set1_pbe_pass.pod
+DEPEND[html/man3/EVP_PKEY_CTX_set_hkdf_md.html]=man3/EVP_PKEY_CTX_set_hkdf_md.pod
+GENERATE[html/man3/EVP_PKEY_CTX_set_hkdf_md.html]=man3/EVP_PKEY_CTX_set_hkdf_md.pod
+DEPEND[man/man3/EVP_PKEY_CTX_set_hkdf_md.3]=man3/EVP_PKEY_CTX_set_hkdf_md.pod
+GENERATE[man/man3/EVP_PKEY_CTX_set_hkdf_md.3]=man3/EVP_PKEY_CTX_set_hkdf_md.pod
+DEPEND[html/man3/EVP_PKEY_CTX_set_params.html]=man3/EVP_PKEY_CTX_set_params.pod
+GENERATE[html/man3/EVP_PKEY_CTX_set_params.html]=man3/EVP_PKEY_CTX_set_params.pod
+DEPEND[man/man3/EVP_PKEY_CTX_set_params.3]=man3/EVP_PKEY_CTX_set_params.pod
+GENERATE[man/man3/EVP_PKEY_CTX_set_params.3]=man3/EVP_PKEY_CTX_set_params.pod
+DEPEND[html/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.html]=man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod
+GENERATE[html/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.html]=man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod
+DEPEND[man/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.3]=man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod
+GENERATE[man/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.3]=man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod
+DEPEND[html/man3/EVP_PKEY_CTX_set_scrypt_N.html]=man3/EVP_PKEY_CTX_set_scrypt_N.pod
+GENERATE[html/man3/EVP_PKEY_CTX_set_scrypt_N.html]=man3/EVP_PKEY_CTX_set_scrypt_N.pod
+DEPEND[man/man3/EVP_PKEY_CTX_set_scrypt_N.3]=man3/EVP_PKEY_CTX_set_scrypt_N.pod
+GENERATE[man/man3/EVP_PKEY_CTX_set_scrypt_N.3]=man3/EVP_PKEY_CTX_set_scrypt_N.pod
+DEPEND[html/man3/EVP_PKEY_CTX_set_tls1_prf_md.html]=man3/EVP_PKEY_CTX_set_tls1_prf_md.pod
+GENERATE[html/man3/EVP_PKEY_CTX_set_tls1_prf_md.html]=man3/EVP_PKEY_CTX_set_tls1_prf_md.pod
+DEPEND[man/man3/EVP_PKEY_CTX_set_tls1_prf_md.3]=man3/EVP_PKEY_CTX_set_tls1_prf_md.pod
+GENERATE[man/man3/EVP_PKEY_CTX_set_tls1_prf_md.3]=man3/EVP_PKEY_CTX_set_tls1_prf_md.pod
+DEPEND[html/man3/EVP_PKEY_asn1_get_count.html]=man3/EVP_PKEY_asn1_get_count.pod
+GENERATE[html/man3/EVP_PKEY_asn1_get_count.html]=man3/EVP_PKEY_asn1_get_count.pod
+DEPEND[man/man3/EVP_PKEY_asn1_get_count.3]=man3/EVP_PKEY_asn1_get_count.pod
+GENERATE[man/man3/EVP_PKEY_asn1_get_count.3]=man3/EVP_PKEY_asn1_get_count.pod
+DEPEND[html/man3/EVP_PKEY_check.html]=man3/EVP_PKEY_check.pod
+GENERATE[html/man3/EVP_PKEY_check.html]=man3/EVP_PKEY_check.pod
+DEPEND[man/man3/EVP_PKEY_check.3]=man3/EVP_PKEY_check.pod
+GENERATE[man/man3/EVP_PKEY_check.3]=man3/EVP_PKEY_check.pod
+DEPEND[html/man3/EVP_PKEY_copy_parameters.html]=man3/EVP_PKEY_copy_parameters.pod
+GENERATE[html/man3/EVP_PKEY_copy_parameters.html]=man3/EVP_PKEY_copy_parameters.pod
+DEPEND[man/man3/EVP_PKEY_copy_parameters.3]=man3/EVP_PKEY_copy_parameters.pod
+GENERATE[man/man3/EVP_PKEY_copy_parameters.3]=man3/EVP_PKEY_copy_parameters.pod
+DEPEND[html/man3/EVP_PKEY_decapsulate.html]=man3/EVP_PKEY_decapsulate.pod
+GENERATE[html/man3/EVP_PKEY_decapsulate.html]=man3/EVP_PKEY_decapsulate.pod
+DEPEND[man/man3/EVP_PKEY_decapsulate.3]=man3/EVP_PKEY_decapsulate.pod
+GENERATE[man/man3/EVP_PKEY_decapsulate.3]=man3/EVP_PKEY_decapsulate.pod
+DEPEND[html/man3/EVP_PKEY_decrypt.html]=man3/EVP_PKEY_decrypt.pod
+GENERATE[html/man3/EVP_PKEY_decrypt.html]=man3/EVP_PKEY_decrypt.pod
+DEPEND[man/man3/EVP_PKEY_decrypt.3]=man3/EVP_PKEY_decrypt.pod
+GENERATE[man/man3/EVP_PKEY_decrypt.3]=man3/EVP_PKEY_decrypt.pod
+DEPEND[html/man3/EVP_PKEY_derive.html]=man3/EVP_PKEY_derive.pod
+GENERATE[html/man3/EVP_PKEY_derive.html]=man3/EVP_PKEY_derive.pod
+DEPEND[man/man3/EVP_PKEY_derive.3]=man3/EVP_PKEY_derive.pod
+GENERATE[man/man3/EVP_PKEY_derive.3]=man3/EVP_PKEY_derive.pod
+DEPEND[html/man3/EVP_PKEY_digestsign_supports_digest.html]=man3/EVP_PKEY_digestsign_supports_digest.pod
+GENERATE[html/man3/EVP_PKEY_digestsign_supports_digest.html]=man3/EVP_PKEY_digestsign_supports_digest.pod
+DEPEND[man/man3/EVP_PKEY_digestsign_supports_digest.3]=man3/EVP_PKEY_digestsign_supports_digest.pod
+GENERATE[man/man3/EVP_PKEY_digestsign_supports_digest.3]=man3/EVP_PKEY_digestsign_supports_digest.pod
+DEPEND[html/man3/EVP_PKEY_encapsulate.html]=man3/EVP_PKEY_encapsulate.pod
+GENERATE[html/man3/EVP_PKEY_encapsulate.html]=man3/EVP_PKEY_encapsulate.pod
+DEPEND[man/man3/EVP_PKEY_encapsulate.3]=man3/EVP_PKEY_encapsulate.pod
+GENERATE[man/man3/EVP_PKEY_encapsulate.3]=man3/EVP_PKEY_encapsulate.pod
+DEPEND[html/man3/EVP_PKEY_encrypt.html]=man3/EVP_PKEY_encrypt.pod
+GENERATE[html/man3/EVP_PKEY_encrypt.html]=man3/EVP_PKEY_encrypt.pod
+DEPEND[man/man3/EVP_PKEY_encrypt.3]=man3/EVP_PKEY_encrypt.pod
+GENERATE[man/man3/EVP_PKEY_encrypt.3]=man3/EVP_PKEY_encrypt.pod
+DEPEND[html/man3/EVP_PKEY_fromdata.html]=man3/EVP_PKEY_fromdata.pod
+GENERATE[html/man3/EVP_PKEY_fromdata.html]=man3/EVP_PKEY_fromdata.pod
+DEPEND[man/man3/EVP_PKEY_fromdata.3]=man3/EVP_PKEY_fromdata.pod
+GENERATE[man/man3/EVP_PKEY_fromdata.3]=man3/EVP_PKEY_fromdata.pod
+DEPEND[html/man3/EVP_PKEY_get_default_digest_nid.html]=man3/EVP_PKEY_get_default_digest_nid.pod
+GENERATE[html/man3/EVP_PKEY_get_default_digest_nid.html]=man3/EVP_PKEY_get_default_digest_nid.pod
+DEPEND[man/man3/EVP_PKEY_get_default_digest_nid.3]=man3/EVP_PKEY_get_default_digest_nid.pod
+GENERATE[man/man3/EVP_PKEY_get_default_digest_nid.3]=man3/EVP_PKEY_get_default_digest_nid.pod
+DEPEND[html/man3/EVP_PKEY_get_field_type.html]=man3/EVP_PKEY_get_field_type.pod
+GENERATE[html/man3/EVP_PKEY_get_field_type.html]=man3/EVP_PKEY_get_field_type.pod
+DEPEND[man/man3/EVP_PKEY_get_field_type.3]=man3/EVP_PKEY_get_field_type.pod
+GENERATE[man/man3/EVP_PKEY_get_field_type.3]=man3/EVP_PKEY_get_field_type.pod
+DEPEND[html/man3/EVP_PKEY_get_group_name.html]=man3/EVP_PKEY_get_group_name.pod
+GENERATE[html/man3/EVP_PKEY_get_group_name.html]=man3/EVP_PKEY_get_group_name.pod
+DEPEND[man/man3/EVP_PKEY_get_group_name.3]=man3/EVP_PKEY_get_group_name.pod
+GENERATE[man/man3/EVP_PKEY_get_group_name.3]=man3/EVP_PKEY_get_group_name.pod
+DEPEND[html/man3/EVP_PKEY_get_size.html]=man3/EVP_PKEY_get_size.pod
+GENERATE[html/man3/EVP_PKEY_get_size.html]=man3/EVP_PKEY_get_size.pod
+DEPEND[man/man3/EVP_PKEY_get_size.3]=man3/EVP_PKEY_get_size.pod
+GENERATE[man/man3/EVP_PKEY_get_size.3]=man3/EVP_PKEY_get_size.pod
+DEPEND[html/man3/EVP_PKEY_gettable_params.html]=man3/EVP_PKEY_gettable_params.pod
+GENERATE[html/man3/EVP_PKEY_gettable_params.html]=man3/EVP_PKEY_gettable_params.pod
+DEPEND[man/man3/EVP_PKEY_gettable_params.3]=man3/EVP_PKEY_gettable_params.pod
+GENERATE[man/man3/EVP_PKEY_gettable_params.3]=man3/EVP_PKEY_gettable_params.pod
+DEPEND[html/man3/EVP_PKEY_is_a.html]=man3/EVP_PKEY_is_a.pod
+GENERATE[html/man3/EVP_PKEY_is_a.html]=man3/EVP_PKEY_is_a.pod
+DEPEND[man/man3/EVP_PKEY_is_a.3]=man3/EVP_PKEY_is_a.pod
+GENERATE[man/man3/EVP_PKEY_is_a.3]=man3/EVP_PKEY_is_a.pod
+DEPEND[html/man3/EVP_PKEY_keygen.html]=man3/EVP_PKEY_keygen.pod
+GENERATE[html/man3/EVP_PKEY_keygen.html]=man3/EVP_PKEY_keygen.pod
+DEPEND[man/man3/EVP_PKEY_keygen.3]=man3/EVP_PKEY_keygen.pod
+GENERATE[man/man3/EVP_PKEY_keygen.3]=man3/EVP_PKEY_keygen.pod
+DEPEND[html/man3/EVP_PKEY_meth_get_count.html]=man3/EVP_PKEY_meth_get_count.pod
+GENERATE[html/man3/EVP_PKEY_meth_get_count.html]=man3/EVP_PKEY_meth_get_count.pod
+DEPEND[man/man3/EVP_PKEY_meth_get_count.3]=man3/EVP_PKEY_meth_get_count.pod
+GENERATE[man/man3/EVP_PKEY_meth_get_count.3]=man3/EVP_PKEY_meth_get_count.pod
+DEPEND[html/man3/EVP_PKEY_meth_new.html]=man3/EVP_PKEY_meth_new.pod
+GENERATE[html/man3/EVP_PKEY_meth_new.html]=man3/EVP_PKEY_meth_new.pod
+DEPEND[man/man3/EVP_PKEY_meth_new.3]=man3/EVP_PKEY_meth_new.pod
+GENERATE[man/man3/EVP_PKEY_meth_new.3]=man3/EVP_PKEY_meth_new.pod
+DEPEND[html/man3/EVP_PKEY_new.html]=man3/EVP_PKEY_new.pod
+GENERATE[html/man3/EVP_PKEY_new.html]=man3/EVP_PKEY_new.pod
+DEPEND[man/man3/EVP_PKEY_new.3]=man3/EVP_PKEY_new.pod
+GENERATE[man/man3/EVP_PKEY_new.3]=man3/EVP_PKEY_new.pod
+DEPEND[html/man3/EVP_PKEY_print_private.html]=man3/EVP_PKEY_print_private.pod
+GENERATE[html/man3/EVP_PKEY_print_private.html]=man3/EVP_PKEY_print_private.pod
+DEPEND[man/man3/EVP_PKEY_print_private.3]=man3/EVP_PKEY_print_private.pod
+GENERATE[man/man3/EVP_PKEY_print_private.3]=man3/EVP_PKEY_print_private.pod
+DEPEND[html/man3/EVP_PKEY_set1_RSA.html]=man3/EVP_PKEY_set1_RSA.pod
+GENERATE[html/man3/EVP_PKEY_set1_RSA.html]=man3/EVP_PKEY_set1_RSA.pod
+DEPEND[man/man3/EVP_PKEY_set1_RSA.3]=man3/EVP_PKEY_set1_RSA.pod
+GENERATE[man/man3/EVP_PKEY_set1_RSA.3]=man3/EVP_PKEY_set1_RSA.pod
+DEPEND[html/man3/EVP_PKEY_set1_encoded_public_key.html]=man3/EVP_PKEY_set1_encoded_public_key.pod
+GENERATE[html/man3/EVP_PKEY_set1_encoded_public_key.html]=man3/EVP_PKEY_set1_encoded_public_key.pod
+DEPEND[man/man3/EVP_PKEY_set1_encoded_public_key.3]=man3/EVP_PKEY_set1_encoded_public_key.pod
+GENERATE[man/man3/EVP_PKEY_set1_encoded_public_key.3]=man3/EVP_PKEY_set1_encoded_public_key.pod
+DEPEND[html/man3/EVP_PKEY_set_type.html]=man3/EVP_PKEY_set_type.pod
+GENERATE[html/man3/EVP_PKEY_set_type.html]=man3/EVP_PKEY_set_type.pod
+DEPEND[man/man3/EVP_PKEY_set_type.3]=man3/EVP_PKEY_set_type.pod
+GENERATE[man/man3/EVP_PKEY_set_type.3]=man3/EVP_PKEY_set_type.pod
+DEPEND[html/man3/EVP_PKEY_settable_params.html]=man3/EVP_PKEY_settable_params.pod
+GENERATE[html/man3/EVP_PKEY_settable_params.html]=man3/EVP_PKEY_settable_params.pod
+DEPEND[man/man3/EVP_PKEY_settable_params.3]=man3/EVP_PKEY_settable_params.pod
+GENERATE[man/man3/EVP_PKEY_settable_params.3]=man3/EVP_PKEY_settable_params.pod
+DEPEND[html/man3/EVP_PKEY_sign.html]=man3/EVP_PKEY_sign.pod
+GENERATE[html/man3/EVP_PKEY_sign.html]=man3/EVP_PKEY_sign.pod
+DEPEND[man/man3/EVP_PKEY_sign.3]=man3/EVP_PKEY_sign.pod
+GENERATE[man/man3/EVP_PKEY_sign.3]=man3/EVP_PKEY_sign.pod
+DEPEND[html/man3/EVP_PKEY_todata.html]=man3/EVP_PKEY_todata.pod
+GENERATE[html/man3/EVP_PKEY_todata.html]=man3/EVP_PKEY_todata.pod
+DEPEND[man/man3/EVP_PKEY_todata.3]=man3/EVP_PKEY_todata.pod
+GENERATE[man/man3/EVP_PKEY_todata.3]=man3/EVP_PKEY_todata.pod
+DEPEND[html/man3/EVP_PKEY_verify.html]=man3/EVP_PKEY_verify.pod
+GENERATE[html/man3/EVP_PKEY_verify.html]=man3/EVP_PKEY_verify.pod
+DEPEND[man/man3/EVP_PKEY_verify.3]=man3/EVP_PKEY_verify.pod
+GENERATE[man/man3/EVP_PKEY_verify.3]=man3/EVP_PKEY_verify.pod
+DEPEND[html/man3/EVP_PKEY_verify_recover.html]=man3/EVP_PKEY_verify_recover.pod
+GENERATE[html/man3/EVP_PKEY_verify_recover.html]=man3/EVP_PKEY_verify_recover.pod
+DEPEND[man/man3/EVP_PKEY_verify_recover.3]=man3/EVP_PKEY_verify_recover.pod
+GENERATE[man/man3/EVP_PKEY_verify_recover.3]=man3/EVP_PKEY_verify_recover.pod
+DEPEND[html/man3/EVP_RAND.html]=man3/EVP_RAND.pod
+GENERATE[html/man3/EVP_RAND.html]=man3/EVP_RAND.pod
+DEPEND[man/man3/EVP_RAND.3]=man3/EVP_RAND.pod
+GENERATE[man/man3/EVP_RAND.3]=man3/EVP_RAND.pod
+DEPEND[html/man3/EVP_SIGNATURE.html]=man3/EVP_SIGNATURE.pod
+GENERATE[html/man3/EVP_SIGNATURE.html]=man3/EVP_SIGNATURE.pod
+DEPEND[man/man3/EVP_SIGNATURE.3]=man3/EVP_SIGNATURE.pod
+GENERATE[man/man3/EVP_SIGNATURE.3]=man3/EVP_SIGNATURE.pod
+DEPEND[html/man3/EVP_SealInit.html]=man3/EVP_SealInit.pod
+GENERATE[html/man3/EVP_SealInit.html]=man3/EVP_SealInit.pod
+DEPEND[man/man3/EVP_SealInit.3]=man3/EVP_SealInit.pod
+GENERATE[man/man3/EVP_SealInit.3]=man3/EVP_SealInit.pod
+DEPEND[html/man3/EVP_SignInit.html]=man3/EVP_SignInit.pod
+GENERATE[html/man3/EVP_SignInit.html]=man3/EVP_SignInit.pod
+DEPEND[man/man3/EVP_SignInit.3]=man3/EVP_SignInit.pod
+GENERATE[man/man3/EVP_SignInit.3]=man3/EVP_SignInit.pod
+DEPEND[html/man3/EVP_VerifyInit.html]=man3/EVP_VerifyInit.pod
+GENERATE[html/man3/EVP_VerifyInit.html]=man3/EVP_VerifyInit.pod
+DEPEND[man/man3/EVP_VerifyInit.3]=man3/EVP_VerifyInit.pod
+GENERATE[man/man3/EVP_VerifyInit.3]=man3/EVP_VerifyInit.pod
+DEPEND[html/man3/EVP_aes_128_gcm.html]=man3/EVP_aes_128_gcm.pod
+GENERATE[html/man3/EVP_aes_128_gcm.html]=man3/EVP_aes_128_gcm.pod
+DEPEND[man/man3/EVP_aes_128_gcm.3]=man3/EVP_aes_128_gcm.pod
+GENERATE[man/man3/EVP_aes_128_gcm.3]=man3/EVP_aes_128_gcm.pod
+DEPEND[html/man3/EVP_aria_128_gcm.html]=man3/EVP_aria_128_gcm.pod
+GENERATE[html/man3/EVP_aria_128_gcm.html]=man3/EVP_aria_128_gcm.pod
+DEPEND[man/man3/EVP_aria_128_gcm.3]=man3/EVP_aria_128_gcm.pod
+GENERATE[man/man3/EVP_aria_128_gcm.3]=man3/EVP_aria_128_gcm.pod
+DEPEND[html/man3/EVP_bf_cbc.html]=man3/EVP_bf_cbc.pod
+GENERATE[html/man3/EVP_bf_cbc.html]=man3/EVP_bf_cbc.pod
+DEPEND[man/man3/EVP_bf_cbc.3]=man3/EVP_bf_cbc.pod
+GENERATE[man/man3/EVP_bf_cbc.3]=man3/EVP_bf_cbc.pod
+DEPEND[html/man3/EVP_blake2b512.html]=man3/EVP_blake2b512.pod
+GENERATE[html/man3/EVP_blake2b512.html]=man3/EVP_blake2b512.pod
+DEPEND[man/man3/EVP_blake2b512.3]=man3/EVP_blake2b512.pod
+GENERATE[man/man3/EVP_blake2b512.3]=man3/EVP_blake2b512.pod
+DEPEND[html/man3/EVP_camellia_128_ecb.html]=man3/EVP_camellia_128_ecb.pod
+GENERATE[html/man3/EVP_camellia_128_ecb.html]=man3/EVP_camellia_128_ecb.pod
+DEPEND[man/man3/EVP_camellia_128_ecb.3]=man3/EVP_camellia_128_ecb.pod
+GENERATE[man/man3/EVP_camellia_128_ecb.3]=man3/EVP_camellia_128_ecb.pod
+DEPEND[html/man3/EVP_cast5_cbc.html]=man3/EVP_cast5_cbc.pod
+GENERATE[html/man3/EVP_cast5_cbc.html]=man3/EVP_cast5_cbc.pod
+DEPEND[man/man3/EVP_cast5_cbc.3]=man3/EVP_cast5_cbc.pod
+GENERATE[man/man3/EVP_cast5_cbc.3]=man3/EVP_cast5_cbc.pod
+DEPEND[html/man3/EVP_chacha20.html]=man3/EVP_chacha20.pod
+GENERATE[html/man3/EVP_chacha20.html]=man3/EVP_chacha20.pod
+DEPEND[man/man3/EVP_chacha20.3]=man3/EVP_chacha20.pod
+GENERATE[man/man3/EVP_chacha20.3]=man3/EVP_chacha20.pod
+DEPEND[html/man3/EVP_des_cbc.html]=man3/EVP_des_cbc.pod
+GENERATE[html/man3/EVP_des_cbc.html]=man3/EVP_des_cbc.pod
+DEPEND[man/man3/EVP_des_cbc.3]=man3/EVP_des_cbc.pod
+GENERATE[man/man3/EVP_des_cbc.3]=man3/EVP_des_cbc.pod
+DEPEND[html/man3/EVP_desx_cbc.html]=man3/EVP_desx_cbc.pod
+GENERATE[html/man3/EVP_desx_cbc.html]=man3/EVP_desx_cbc.pod
+DEPEND[man/man3/EVP_desx_cbc.3]=man3/EVP_desx_cbc.pod
+GENERATE[man/man3/EVP_desx_cbc.3]=man3/EVP_desx_cbc.pod
+DEPEND[html/man3/EVP_idea_cbc.html]=man3/EVP_idea_cbc.pod
+GENERATE[html/man3/EVP_idea_cbc.html]=man3/EVP_idea_cbc.pod
+DEPEND[man/man3/EVP_idea_cbc.3]=man3/EVP_idea_cbc.pod
+GENERATE[man/man3/EVP_idea_cbc.3]=man3/EVP_idea_cbc.pod
+DEPEND[html/man3/EVP_md2.html]=man3/EVP_md2.pod
+GENERATE[html/man3/EVP_md2.html]=man3/EVP_md2.pod
+DEPEND[man/man3/EVP_md2.3]=man3/EVP_md2.pod
+GENERATE[man/man3/EVP_md2.3]=man3/EVP_md2.pod
+DEPEND[html/man3/EVP_md4.html]=man3/EVP_md4.pod
+GENERATE[html/man3/EVP_md4.html]=man3/EVP_md4.pod
+DEPEND[man/man3/EVP_md4.3]=man3/EVP_md4.pod
+GENERATE[man/man3/EVP_md4.3]=man3/EVP_md4.pod
+DEPEND[html/man3/EVP_md5.html]=man3/EVP_md5.pod
+GENERATE[html/man3/EVP_md5.html]=man3/EVP_md5.pod
+DEPEND[man/man3/EVP_md5.3]=man3/EVP_md5.pod
+GENERATE[man/man3/EVP_md5.3]=man3/EVP_md5.pod
+DEPEND[html/man3/EVP_mdc2.html]=man3/EVP_mdc2.pod
+GENERATE[html/man3/EVP_mdc2.html]=man3/EVP_mdc2.pod
+DEPEND[man/man3/EVP_mdc2.3]=man3/EVP_mdc2.pod
+GENERATE[man/man3/EVP_mdc2.3]=man3/EVP_mdc2.pod
+DEPEND[html/man3/EVP_rc2_cbc.html]=man3/EVP_rc2_cbc.pod
+GENERATE[html/man3/EVP_rc2_cbc.html]=man3/EVP_rc2_cbc.pod
+DEPEND[man/man3/EVP_rc2_cbc.3]=man3/EVP_rc2_cbc.pod
+GENERATE[man/man3/EVP_rc2_cbc.3]=man3/EVP_rc2_cbc.pod
+DEPEND[html/man3/EVP_rc4.html]=man3/EVP_rc4.pod
+GENERATE[html/man3/EVP_rc4.html]=man3/EVP_rc4.pod
+DEPEND[man/man3/EVP_rc4.3]=man3/EVP_rc4.pod
+GENERATE[man/man3/EVP_rc4.3]=man3/EVP_rc4.pod
+DEPEND[html/man3/EVP_rc5_32_12_16_cbc.html]=man3/EVP_rc5_32_12_16_cbc.pod
+GENERATE[html/man3/EVP_rc5_32_12_16_cbc.html]=man3/EVP_rc5_32_12_16_cbc.pod
+DEPEND[man/man3/EVP_rc5_32_12_16_cbc.3]=man3/EVP_rc5_32_12_16_cbc.pod
+GENERATE[man/man3/EVP_rc5_32_12_16_cbc.3]=man3/EVP_rc5_32_12_16_cbc.pod
+DEPEND[html/man3/EVP_ripemd160.html]=man3/EVP_ripemd160.pod
+GENERATE[html/man3/EVP_ripemd160.html]=man3/EVP_ripemd160.pod
+DEPEND[man/man3/EVP_ripemd160.3]=man3/EVP_ripemd160.pod
+GENERATE[man/man3/EVP_ripemd160.3]=man3/EVP_ripemd160.pod
+DEPEND[html/man3/EVP_seed_cbc.html]=man3/EVP_seed_cbc.pod
+GENERATE[html/man3/EVP_seed_cbc.html]=man3/EVP_seed_cbc.pod
+DEPEND[man/man3/EVP_seed_cbc.3]=man3/EVP_seed_cbc.pod
+GENERATE[man/man3/EVP_seed_cbc.3]=man3/EVP_seed_cbc.pod
+DEPEND[html/man3/EVP_set_default_properties.html]=man3/EVP_set_default_properties.pod
+GENERATE[html/man3/EVP_set_default_properties.html]=man3/EVP_set_default_properties.pod
+DEPEND[man/man3/EVP_set_default_properties.3]=man3/EVP_set_default_properties.pod
+GENERATE[man/man3/EVP_set_default_properties.3]=man3/EVP_set_default_properties.pod
+DEPEND[html/man3/EVP_sha1.html]=man3/EVP_sha1.pod
+GENERATE[html/man3/EVP_sha1.html]=man3/EVP_sha1.pod
+DEPEND[man/man3/EVP_sha1.3]=man3/EVP_sha1.pod
+GENERATE[man/man3/EVP_sha1.3]=man3/EVP_sha1.pod
+DEPEND[html/man3/EVP_sha224.html]=man3/EVP_sha224.pod
+GENERATE[html/man3/EVP_sha224.html]=man3/EVP_sha224.pod
+DEPEND[man/man3/EVP_sha224.3]=man3/EVP_sha224.pod
+GENERATE[man/man3/EVP_sha224.3]=man3/EVP_sha224.pod
+DEPEND[html/man3/EVP_sha3_224.html]=man3/EVP_sha3_224.pod
+GENERATE[html/man3/EVP_sha3_224.html]=man3/EVP_sha3_224.pod
+DEPEND[man/man3/EVP_sha3_224.3]=man3/EVP_sha3_224.pod
+GENERATE[man/man3/EVP_sha3_224.3]=man3/EVP_sha3_224.pod
+DEPEND[html/man3/EVP_sm3.html]=man3/EVP_sm3.pod
+GENERATE[html/man3/EVP_sm3.html]=man3/EVP_sm3.pod
+DEPEND[man/man3/EVP_sm3.3]=man3/EVP_sm3.pod
+GENERATE[man/man3/EVP_sm3.3]=man3/EVP_sm3.pod
+DEPEND[html/man3/EVP_sm4_cbc.html]=man3/EVP_sm4_cbc.pod
+GENERATE[html/man3/EVP_sm4_cbc.html]=man3/EVP_sm4_cbc.pod
+DEPEND[man/man3/EVP_sm4_cbc.3]=man3/EVP_sm4_cbc.pod
+GENERATE[man/man3/EVP_sm4_cbc.3]=man3/EVP_sm4_cbc.pod
+DEPEND[html/man3/EVP_whirlpool.html]=man3/EVP_whirlpool.pod
+GENERATE[html/man3/EVP_whirlpool.html]=man3/EVP_whirlpool.pod
+DEPEND[man/man3/EVP_whirlpool.3]=man3/EVP_whirlpool.pod
+GENERATE[man/man3/EVP_whirlpool.3]=man3/EVP_whirlpool.pod
+DEPEND[html/man3/HMAC.html]=man3/HMAC.pod
+GENERATE[html/man3/HMAC.html]=man3/HMAC.pod
+DEPEND[man/man3/HMAC.3]=man3/HMAC.pod
+GENERATE[man/man3/HMAC.3]=man3/HMAC.pod
+DEPEND[html/man3/MD5.html]=man3/MD5.pod
+GENERATE[html/man3/MD5.html]=man3/MD5.pod
+DEPEND[man/man3/MD5.3]=man3/MD5.pod
+GENERATE[man/man3/MD5.3]=man3/MD5.pod
+DEPEND[html/man3/MDC2_Init.html]=man3/MDC2_Init.pod
+GENERATE[html/man3/MDC2_Init.html]=man3/MDC2_Init.pod
+DEPEND[man/man3/MDC2_Init.3]=man3/MDC2_Init.pod
+GENERATE[man/man3/MDC2_Init.3]=man3/MDC2_Init.pod
+DEPEND[html/man3/NCONF_new_ex.html]=man3/NCONF_new_ex.pod
+GENERATE[html/man3/NCONF_new_ex.html]=man3/NCONF_new_ex.pod
+DEPEND[man/man3/NCONF_new_ex.3]=man3/NCONF_new_ex.pod
+GENERATE[man/man3/NCONF_new_ex.3]=man3/NCONF_new_ex.pod
+DEPEND[html/man3/OBJ_nid2obj.html]=man3/OBJ_nid2obj.pod
+GENERATE[html/man3/OBJ_nid2obj.html]=man3/OBJ_nid2obj.pod
+DEPEND[man/man3/OBJ_nid2obj.3]=man3/OBJ_nid2obj.pod
+GENERATE[man/man3/OBJ_nid2obj.3]=man3/OBJ_nid2obj.pod
+DEPEND[html/man3/OCSP_REQUEST_new.html]=man3/OCSP_REQUEST_new.pod
+GENERATE[html/man3/OCSP_REQUEST_new.html]=man3/OCSP_REQUEST_new.pod
+DEPEND[man/man3/OCSP_REQUEST_new.3]=man3/OCSP_REQUEST_new.pod
+GENERATE[man/man3/OCSP_REQUEST_new.3]=man3/OCSP_REQUEST_new.pod
+DEPEND[html/man3/OCSP_cert_to_id.html]=man3/OCSP_cert_to_id.pod
+GENERATE[html/man3/OCSP_cert_to_id.html]=man3/OCSP_cert_to_id.pod
+DEPEND[man/man3/OCSP_cert_to_id.3]=man3/OCSP_cert_to_id.pod
+GENERATE[man/man3/OCSP_cert_to_id.3]=man3/OCSP_cert_to_id.pod
+DEPEND[html/man3/OCSP_request_add1_nonce.html]=man3/OCSP_request_add1_nonce.pod
+GENERATE[html/man3/OCSP_request_add1_nonce.html]=man3/OCSP_request_add1_nonce.pod
+DEPEND[man/man3/OCSP_request_add1_nonce.3]=man3/OCSP_request_add1_nonce.pod
+GENERATE[man/man3/OCSP_request_add1_nonce.3]=man3/OCSP_request_add1_nonce.pod
+DEPEND[html/man3/OCSP_resp_find_status.html]=man3/OCSP_resp_find_status.pod
+GENERATE[html/man3/OCSP_resp_find_status.html]=man3/OCSP_resp_find_status.pod
+DEPEND[man/man3/OCSP_resp_find_status.3]=man3/OCSP_resp_find_status.pod
+GENERATE[man/man3/OCSP_resp_find_status.3]=man3/OCSP_resp_find_status.pod
+DEPEND[html/man3/OCSP_response_status.html]=man3/OCSP_response_status.pod
+GENERATE[html/man3/OCSP_response_status.html]=man3/OCSP_response_status.pod
+DEPEND[man/man3/OCSP_response_status.3]=man3/OCSP_response_status.pod
+GENERATE[man/man3/OCSP_response_status.3]=man3/OCSP_response_status.pod
+DEPEND[html/man3/OCSP_sendreq_new.html]=man3/OCSP_sendreq_new.pod
+GENERATE[html/man3/OCSP_sendreq_new.html]=man3/OCSP_sendreq_new.pod
+DEPEND[man/man3/OCSP_sendreq_new.3]=man3/OCSP_sendreq_new.pod
+GENERATE[man/man3/OCSP_sendreq_new.3]=man3/OCSP_sendreq_new.pod
+DEPEND[html/man3/OPENSSL_Applink.html]=man3/OPENSSL_Applink.pod
+GENERATE[html/man3/OPENSSL_Applink.html]=man3/OPENSSL_Applink.pod
+DEPEND[man/man3/OPENSSL_Applink.3]=man3/OPENSSL_Applink.pod
+GENERATE[man/man3/OPENSSL_Applink.3]=man3/OPENSSL_Applink.pod
+DEPEND[html/man3/OPENSSL_FILE.html]=man3/OPENSSL_FILE.pod
+GENERATE[html/man3/OPENSSL_FILE.html]=man3/OPENSSL_FILE.pod
+DEPEND[man/man3/OPENSSL_FILE.3]=man3/OPENSSL_FILE.pod
+GENERATE[man/man3/OPENSSL_FILE.3]=man3/OPENSSL_FILE.pod
+DEPEND[html/man3/OPENSSL_LH_COMPFUNC.html]=man3/OPENSSL_LH_COMPFUNC.pod
+GENERATE[html/man3/OPENSSL_LH_COMPFUNC.html]=man3/OPENSSL_LH_COMPFUNC.pod
+DEPEND[man/man3/OPENSSL_LH_COMPFUNC.3]=man3/OPENSSL_LH_COMPFUNC.pod
+GENERATE[man/man3/OPENSSL_LH_COMPFUNC.3]=man3/OPENSSL_LH_COMPFUNC.pod
+DEPEND[html/man3/OPENSSL_LH_stats.html]=man3/OPENSSL_LH_stats.pod
+GENERATE[html/man3/OPENSSL_LH_stats.html]=man3/OPENSSL_LH_stats.pod
+DEPEND[man/man3/OPENSSL_LH_stats.3]=man3/OPENSSL_LH_stats.pod
+GENERATE[man/man3/OPENSSL_LH_stats.3]=man3/OPENSSL_LH_stats.pod
+DEPEND[html/man3/OPENSSL_config.html]=man3/OPENSSL_config.pod
+GENERATE[html/man3/OPENSSL_config.html]=man3/OPENSSL_config.pod
+DEPEND[man/man3/OPENSSL_config.3]=man3/OPENSSL_config.pod
+GENERATE[man/man3/OPENSSL_config.3]=man3/OPENSSL_config.pod
+DEPEND[html/man3/OPENSSL_fork_prepare.html]=man3/OPENSSL_fork_prepare.pod
+GENERATE[html/man3/OPENSSL_fork_prepare.html]=man3/OPENSSL_fork_prepare.pod
+DEPEND[man/man3/OPENSSL_fork_prepare.3]=man3/OPENSSL_fork_prepare.pod
+GENERATE[man/man3/OPENSSL_fork_prepare.3]=man3/OPENSSL_fork_prepare.pod
+DEPEND[html/man3/OPENSSL_gmtime.html]=man3/OPENSSL_gmtime.pod
+GENERATE[html/man3/OPENSSL_gmtime.html]=man3/OPENSSL_gmtime.pod
+DEPEND[man/man3/OPENSSL_gmtime.3]=man3/OPENSSL_gmtime.pod
+GENERATE[man/man3/OPENSSL_gmtime.3]=man3/OPENSSL_gmtime.pod
+DEPEND[html/man3/OPENSSL_hexchar2int.html]=man3/OPENSSL_hexchar2int.pod
+GENERATE[html/man3/OPENSSL_hexchar2int.html]=man3/OPENSSL_hexchar2int.pod
+DEPEND[man/man3/OPENSSL_hexchar2int.3]=man3/OPENSSL_hexchar2int.pod
+GENERATE[man/man3/OPENSSL_hexchar2int.3]=man3/OPENSSL_hexchar2int.pod
+DEPEND[html/man3/OPENSSL_ia32cap.html]=man3/OPENSSL_ia32cap.pod
+GENERATE[html/man3/OPENSSL_ia32cap.html]=man3/OPENSSL_ia32cap.pod
+DEPEND[man/man3/OPENSSL_ia32cap.3]=man3/OPENSSL_ia32cap.pod
+GENERATE[man/man3/OPENSSL_ia32cap.3]=man3/OPENSSL_ia32cap.pod
+DEPEND[html/man3/OPENSSL_init_crypto.html]=man3/OPENSSL_init_crypto.pod
+GENERATE[html/man3/OPENSSL_init_crypto.html]=man3/OPENSSL_init_crypto.pod
+DEPEND[man/man3/OPENSSL_init_crypto.3]=man3/OPENSSL_init_crypto.pod
+GENERATE[man/man3/OPENSSL_init_crypto.3]=man3/OPENSSL_init_crypto.pod
+DEPEND[html/man3/OPENSSL_init_ssl.html]=man3/OPENSSL_init_ssl.pod
+GENERATE[html/man3/OPENSSL_init_ssl.html]=man3/OPENSSL_init_ssl.pod
+DEPEND[man/man3/OPENSSL_init_ssl.3]=man3/OPENSSL_init_ssl.pod
+GENERATE[man/man3/OPENSSL_init_ssl.3]=man3/OPENSSL_init_ssl.pod
+DEPEND[html/man3/OPENSSL_instrument_bus.html]=man3/OPENSSL_instrument_bus.pod
+GENERATE[html/man3/OPENSSL_instrument_bus.html]=man3/OPENSSL_instrument_bus.pod
+DEPEND[man/man3/OPENSSL_instrument_bus.3]=man3/OPENSSL_instrument_bus.pod
+GENERATE[man/man3/OPENSSL_instrument_bus.3]=man3/OPENSSL_instrument_bus.pod
+DEPEND[html/man3/OPENSSL_load_builtin_modules.html]=man3/OPENSSL_load_builtin_modules.pod
+GENERATE[html/man3/OPENSSL_load_builtin_modules.html]=man3/OPENSSL_load_builtin_modules.pod
+DEPEND[man/man3/OPENSSL_load_builtin_modules.3]=man3/OPENSSL_load_builtin_modules.pod
+GENERATE[man/man3/OPENSSL_load_builtin_modules.3]=man3/OPENSSL_load_builtin_modules.pod
+DEPEND[html/man3/OPENSSL_malloc.html]=man3/OPENSSL_malloc.pod
+GENERATE[html/man3/OPENSSL_malloc.html]=man3/OPENSSL_malloc.pod
+DEPEND[man/man3/OPENSSL_malloc.3]=man3/OPENSSL_malloc.pod
+GENERATE[man/man3/OPENSSL_malloc.3]=man3/OPENSSL_malloc.pod
+DEPEND[html/man3/OPENSSL_s390xcap.html]=man3/OPENSSL_s390xcap.pod
+GENERATE[html/man3/OPENSSL_s390xcap.html]=man3/OPENSSL_s390xcap.pod
+DEPEND[man/man3/OPENSSL_s390xcap.3]=man3/OPENSSL_s390xcap.pod
+GENERATE[man/man3/OPENSSL_s390xcap.3]=man3/OPENSSL_s390xcap.pod
+DEPEND[html/man3/OPENSSL_secure_malloc.html]=man3/OPENSSL_secure_malloc.pod
+GENERATE[html/man3/OPENSSL_secure_malloc.html]=man3/OPENSSL_secure_malloc.pod
+DEPEND[man/man3/OPENSSL_secure_malloc.3]=man3/OPENSSL_secure_malloc.pod
+GENERATE[man/man3/OPENSSL_secure_malloc.3]=man3/OPENSSL_secure_malloc.pod
+DEPEND[html/man3/OPENSSL_strcasecmp.html]=man3/OPENSSL_strcasecmp.pod
+GENERATE[html/man3/OPENSSL_strcasecmp.html]=man3/OPENSSL_strcasecmp.pod
+DEPEND[man/man3/OPENSSL_strcasecmp.3]=man3/OPENSSL_strcasecmp.pod
+GENERATE[man/man3/OPENSSL_strcasecmp.3]=man3/OPENSSL_strcasecmp.pod
+DEPEND[html/man3/OSSL_ALGORITHM.html]=man3/OSSL_ALGORITHM.pod
+GENERATE[html/man3/OSSL_ALGORITHM.html]=man3/OSSL_ALGORITHM.pod
+DEPEND[man/man3/OSSL_ALGORITHM.3]=man3/OSSL_ALGORITHM.pod
+GENERATE[man/man3/OSSL_ALGORITHM.3]=man3/OSSL_ALGORITHM.pod
+DEPEND[html/man3/OSSL_CALLBACK.html]=man3/OSSL_CALLBACK.pod
+GENERATE[html/man3/OSSL_CALLBACK.html]=man3/OSSL_CALLBACK.pod
+DEPEND[man/man3/OSSL_CALLBACK.3]=man3/OSSL_CALLBACK.pod
+GENERATE[man/man3/OSSL_CALLBACK.3]=man3/OSSL_CALLBACK.pod
+DEPEND[html/man3/OSSL_CMP_CTX_new.html]=man3/OSSL_CMP_CTX_new.pod
+GENERATE[html/man3/OSSL_CMP_CTX_new.html]=man3/OSSL_CMP_CTX_new.pod
+DEPEND[man/man3/OSSL_CMP_CTX_new.3]=man3/OSSL_CMP_CTX_new.pod
+GENERATE[man/man3/OSSL_CMP_CTX_new.3]=man3/OSSL_CMP_CTX_new.pod
+DEPEND[html/man3/OSSL_CMP_HDR_get0_transactionID.html]=man3/OSSL_CMP_HDR_get0_transactionID.pod
+GENERATE[html/man3/OSSL_CMP_HDR_get0_transactionID.html]=man3/OSSL_CMP_HDR_get0_transactionID.pod
+DEPEND[man/man3/OSSL_CMP_HDR_get0_transactionID.3]=man3/OSSL_CMP_HDR_get0_transactionID.pod
+GENERATE[man/man3/OSSL_CMP_HDR_get0_transactionID.3]=man3/OSSL_CMP_HDR_get0_transactionID.pod
+DEPEND[html/man3/OSSL_CMP_ITAV_set0.html]=man3/OSSL_CMP_ITAV_set0.pod
+GENERATE[html/man3/OSSL_CMP_ITAV_set0.html]=man3/OSSL_CMP_ITAV_set0.pod
+DEPEND[man/man3/OSSL_CMP_ITAV_set0.3]=man3/OSSL_CMP_ITAV_set0.pod
+GENERATE[man/man3/OSSL_CMP_ITAV_set0.3]=man3/OSSL_CMP_ITAV_set0.pod
+DEPEND[html/man3/OSSL_CMP_MSG_get0_header.html]=man3/OSSL_CMP_MSG_get0_header.pod
+GENERATE[html/man3/OSSL_CMP_MSG_get0_header.html]=man3/OSSL_CMP_MSG_get0_header.pod
+DEPEND[man/man3/OSSL_CMP_MSG_get0_header.3]=man3/OSSL_CMP_MSG_get0_header.pod
+GENERATE[man/man3/OSSL_CMP_MSG_get0_header.3]=man3/OSSL_CMP_MSG_get0_header.pod
+DEPEND[html/man3/OSSL_CMP_MSG_http_perform.html]=man3/OSSL_CMP_MSG_http_perform.pod
+GENERATE[html/man3/OSSL_CMP_MSG_http_perform.html]=man3/OSSL_CMP_MSG_http_perform.pod
+DEPEND[man/man3/OSSL_CMP_MSG_http_perform.3]=man3/OSSL_CMP_MSG_http_perform.pod
+GENERATE[man/man3/OSSL_CMP_MSG_http_perform.3]=man3/OSSL_CMP_MSG_http_perform.pod
+DEPEND[html/man3/OSSL_CMP_SRV_CTX_new.html]=man3/OSSL_CMP_SRV_CTX_new.pod
+GENERATE[html/man3/OSSL_CMP_SRV_CTX_new.html]=man3/OSSL_CMP_SRV_CTX_new.pod
+DEPEND[man/man3/OSSL_CMP_SRV_CTX_new.3]=man3/OSSL_CMP_SRV_CTX_new.pod
+GENERATE[man/man3/OSSL_CMP_SRV_CTX_new.3]=man3/OSSL_CMP_SRV_CTX_new.pod
+DEPEND[html/man3/OSSL_CMP_STATUSINFO_new.html]=man3/OSSL_CMP_STATUSINFO_new.pod
+GENERATE[html/man3/OSSL_CMP_STATUSINFO_new.html]=man3/OSSL_CMP_STATUSINFO_new.pod
+DEPEND[man/man3/OSSL_CMP_STATUSINFO_new.3]=man3/OSSL_CMP_STATUSINFO_new.pod
+GENERATE[man/man3/OSSL_CMP_STATUSINFO_new.3]=man3/OSSL_CMP_STATUSINFO_new.pod
+DEPEND[html/man3/OSSL_CMP_exec_certreq.html]=man3/OSSL_CMP_exec_certreq.pod
+GENERATE[html/man3/OSSL_CMP_exec_certreq.html]=man3/OSSL_CMP_exec_certreq.pod
+DEPEND[man/man3/OSSL_CMP_exec_certreq.3]=man3/OSSL_CMP_exec_certreq.pod
+GENERATE[man/man3/OSSL_CMP_exec_certreq.3]=man3/OSSL_CMP_exec_certreq.pod
+DEPEND[html/man3/OSSL_CMP_log_open.html]=man3/OSSL_CMP_log_open.pod
+GENERATE[html/man3/OSSL_CMP_log_open.html]=man3/OSSL_CMP_log_open.pod
+DEPEND[man/man3/OSSL_CMP_log_open.3]=man3/OSSL_CMP_log_open.pod
+GENERATE[man/man3/OSSL_CMP_log_open.3]=man3/OSSL_CMP_log_open.pod
+DEPEND[html/man3/OSSL_CMP_validate_msg.html]=man3/OSSL_CMP_validate_msg.pod
+GENERATE[html/man3/OSSL_CMP_validate_msg.html]=man3/OSSL_CMP_validate_msg.pod
+DEPEND[man/man3/OSSL_CMP_validate_msg.3]=man3/OSSL_CMP_validate_msg.pod
+GENERATE[man/man3/OSSL_CMP_validate_msg.3]=man3/OSSL_CMP_validate_msg.pod
+DEPEND[html/man3/OSSL_CORE_MAKE_FUNC.html]=man3/OSSL_CORE_MAKE_FUNC.pod
+GENERATE[html/man3/OSSL_CORE_MAKE_FUNC.html]=man3/OSSL_CORE_MAKE_FUNC.pod
+DEPEND[man/man3/OSSL_CORE_MAKE_FUNC.3]=man3/OSSL_CORE_MAKE_FUNC.pod
+GENERATE[man/man3/OSSL_CORE_MAKE_FUNC.3]=man3/OSSL_CORE_MAKE_FUNC.pod
+DEPEND[html/man3/OSSL_CRMF_MSG_get0_tmpl.html]=man3/OSSL_CRMF_MSG_get0_tmpl.pod
+GENERATE[html/man3/OSSL_CRMF_MSG_get0_tmpl.html]=man3/OSSL_CRMF_MSG_get0_tmpl.pod
+DEPEND[man/man3/OSSL_CRMF_MSG_get0_tmpl.3]=man3/OSSL_CRMF_MSG_get0_tmpl.pod
+GENERATE[man/man3/OSSL_CRMF_MSG_get0_tmpl.3]=man3/OSSL_CRMF_MSG_get0_tmpl.pod
+DEPEND[html/man3/OSSL_CRMF_MSG_set0_validity.html]=man3/OSSL_CRMF_MSG_set0_validity.pod
+GENERATE[html/man3/OSSL_CRMF_MSG_set0_validity.html]=man3/OSSL_CRMF_MSG_set0_validity.pod
+DEPEND[man/man3/OSSL_CRMF_MSG_set0_validity.3]=man3/OSSL_CRMF_MSG_set0_validity.pod
+GENERATE[man/man3/OSSL_CRMF_MSG_set0_validity.3]=man3/OSSL_CRMF_MSG_set0_validity.pod
+DEPEND[html/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.html]=man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod
+GENERATE[html/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.html]=man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod
+DEPEND[man/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.3]=man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod
+GENERATE[man/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.3]=man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod
+DEPEND[html/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.html]=man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod
+GENERATE[html/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.html]=man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod
+DEPEND[man/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.3]=man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod
+GENERATE[man/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.3]=man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod
+DEPEND[html/man3/OSSL_CRMF_pbmp_new.html]=man3/OSSL_CRMF_pbmp_new.pod
+GENERATE[html/man3/OSSL_CRMF_pbmp_new.html]=man3/OSSL_CRMF_pbmp_new.pod
+DEPEND[man/man3/OSSL_CRMF_pbmp_new.3]=man3/OSSL_CRMF_pbmp_new.pod
+GENERATE[man/man3/OSSL_CRMF_pbmp_new.3]=man3/OSSL_CRMF_pbmp_new.pod
+DEPEND[html/man3/OSSL_DECODER.html]=man3/OSSL_DECODER.pod
+GENERATE[html/man3/OSSL_DECODER.html]=man3/OSSL_DECODER.pod
+DEPEND[man/man3/OSSL_DECODER.3]=man3/OSSL_DECODER.pod
+GENERATE[man/man3/OSSL_DECODER.3]=man3/OSSL_DECODER.pod
+DEPEND[html/man3/OSSL_DECODER_CTX.html]=man3/OSSL_DECODER_CTX.pod
+GENERATE[html/man3/OSSL_DECODER_CTX.html]=man3/OSSL_DECODER_CTX.pod
+DEPEND[man/man3/OSSL_DECODER_CTX.3]=man3/OSSL_DECODER_CTX.pod
+GENERATE[man/man3/OSSL_DECODER_CTX.3]=man3/OSSL_DECODER_CTX.pod
+DEPEND[html/man3/OSSL_DECODER_CTX_new_for_pkey.html]=man3/OSSL_DECODER_CTX_new_for_pkey.pod
+GENERATE[html/man3/OSSL_DECODER_CTX_new_for_pkey.html]=man3/OSSL_DECODER_CTX_new_for_pkey.pod
+DEPEND[man/man3/OSSL_DECODER_CTX_new_for_pkey.3]=man3/OSSL_DECODER_CTX_new_for_pkey.pod
+GENERATE[man/man3/OSSL_DECODER_CTX_new_for_pkey.3]=man3/OSSL_DECODER_CTX_new_for_pkey.pod
+DEPEND[html/man3/OSSL_DECODER_from_bio.html]=man3/OSSL_DECODER_from_bio.pod
+GENERATE[html/man3/OSSL_DECODER_from_bio.html]=man3/OSSL_DECODER_from_bio.pod
+DEPEND[man/man3/OSSL_DECODER_from_bio.3]=man3/OSSL_DECODER_from_bio.pod
+GENERATE[man/man3/OSSL_DECODER_from_bio.3]=man3/OSSL_DECODER_from_bio.pod
+DEPEND[html/man3/OSSL_DISPATCH.html]=man3/OSSL_DISPATCH.pod
+GENERATE[html/man3/OSSL_DISPATCH.html]=man3/OSSL_DISPATCH.pod
+DEPEND[man/man3/OSSL_DISPATCH.3]=man3/OSSL_DISPATCH.pod
+GENERATE[man/man3/OSSL_DISPATCH.3]=man3/OSSL_DISPATCH.pod
+DEPEND[html/man3/OSSL_ENCODER.html]=man3/OSSL_ENCODER.pod
+GENERATE[html/man3/OSSL_ENCODER.html]=man3/OSSL_ENCODER.pod
+DEPEND[man/man3/OSSL_ENCODER.3]=man3/OSSL_ENCODER.pod
+GENERATE[man/man3/OSSL_ENCODER.3]=man3/OSSL_ENCODER.pod
+DEPEND[html/man3/OSSL_ENCODER_CTX.html]=man3/OSSL_ENCODER_CTX.pod
+GENERATE[html/man3/OSSL_ENCODER_CTX.html]=man3/OSSL_ENCODER_CTX.pod
+DEPEND[man/man3/OSSL_ENCODER_CTX.3]=man3/OSSL_ENCODER_CTX.pod
+GENERATE[man/man3/OSSL_ENCODER_CTX.3]=man3/OSSL_ENCODER_CTX.pod
+DEPEND[html/man3/OSSL_ENCODER_CTX_new_for_pkey.html]=man3/OSSL_ENCODER_CTX_new_for_pkey.pod
+GENERATE[html/man3/OSSL_ENCODER_CTX_new_for_pkey.html]=man3/OSSL_ENCODER_CTX_new_for_pkey.pod
+DEPEND[man/man3/OSSL_ENCODER_CTX_new_for_pkey.3]=man3/OSSL_ENCODER_CTX_new_for_pkey.pod
+GENERATE[man/man3/OSSL_ENCODER_CTX_new_for_pkey.3]=man3/OSSL_ENCODER_CTX_new_for_pkey.pod
+DEPEND[html/man3/OSSL_ENCODER_to_bio.html]=man3/OSSL_ENCODER_to_bio.pod
+GENERATE[html/man3/OSSL_ENCODER_to_bio.html]=man3/OSSL_ENCODER_to_bio.pod
+DEPEND[man/man3/OSSL_ENCODER_to_bio.3]=man3/OSSL_ENCODER_to_bio.pod
+GENERATE[man/man3/OSSL_ENCODER_to_bio.3]=man3/OSSL_ENCODER_to_bio.pod
+DEPEND[html/man3/OSSL_ESS_check_signing_certs.html]=man3/OSSL_ESS_check_signing_certs.pod
+GENERATE[html/man3/OSSL_ESS_check_signing_certs.html]=man3/OSSL_ESS_check_signing_certs.pod
+DEPEND[man/man3/OSSL_ESS_check_signing_certs.3]=man3/OSSL_ESS_check_signing_certs.pod
+GENERATE[man/man3/OSSL_ESS_check_signing_certs.3]=man3/OSSL_ESS_check_signing_certs.pod
+DEPEND[html/man3/OSSL_HTTP_REQ_CTX.html]=man3/OSSL_HTTP_REQ_CTX.pod
+GENERATE[html/man3/OSSL_HTTP_REQ_CTX.html]=man3/OSSL_HTTP_REQ_CTX.pod
+DEPEND[man/man3/OSSL_HTTP_REQ_CTX.3]=man3/OSSL_HTTP_REQ_CTX.pod
+GENERATE[man/man3/OSSL_HTTP_REQ_CTX.3]=man3/OSSL_HTTP_REQ_CTX.pod
+DEPEND[html/man3/OSSL_HTTP_parse_url.html]=man3/OSSL_HTTP_parse_url.pod
+GENERATE[html/man3/OSSL_HTTP_parse_url.html]=man3/OSSL_HTTP_parse_url.pod
+DEPEND[man/man3/OSSL_HTTP_parse_url.3]=man3/OSSL_HTTP_parse_url.pod
+GENERATE[man/man3/OSSL_HTTP_parse_url.3]=man3/OSSL_HTTP_parse_url.pod
+DEPEND[html/man3/OSSL_HTTP_transfer.html]=man3/OSSL_HTTP_transfer.pod
+GENERATE[html/man3/OSSL_HTTP_transfer.html]=man3/OSSL_HTTP_transfer.pod
+DEPEND[man/man3/OSSL_HTTP_transfer.3]=man3/OSSL_HTTP_transfer.pod
+GENERATE[man/man3/OSSL_HTTP_transfer.3]=man3/OSSL_HTTP_transfer.pod
+DEPEND[html/man3/OSSL_ITEM.html]=man3/OSSL_ITEM.pod
+GENERATE[html/man3/OSSL_ITEM.html]=man3/OSSL_ITEM.pod
+DEPEND[man/man3/OSSL_ITEM.3]=man3/OSSL_ITEM.pod
+GENERATE[man/man3/OSSL_ITEM.3]=man3/OSSL_ITEM.pod
+DEPEND[html/man3/OSSL_LIB_CTX.html]=man3/OSSL_LIB_CTX.pod
+GENERATE[html/man3/OSSL_LIB_CTX.html]=man3/OSSL_LIB_CTX.pod
+DEPEND[man/man3/OSSL_LIB_CTX.3]=man3/OSSL_LIB_CTX.pod
+GENERATE[man/man3/OSSL_LIB_CTX.3]=man3/OSSL_LIB_CTX.pod
+DEPEND[html/man3/OSSL_PARAM.html]=man3/OSSL_PARAM.pod
+GENERATE[html/man3/OSSL_PARAM.html]=man3/OSSL_PARAM.pod
+DEPEND[man/man3/OSSL_PARAM.3]=man3/OSSL_PARAM.pod
+GENERATE[man/man3/OSSL_PARAM.3]=man3/OSSL_PARAM.pod
+DEPEND[html/man3/OSSL_PARAM_BLD.html]=man3/OSSL_PARAM_BLD.pod
+GENERATE[html/man3/OSSL_PARAM_BLD.html]=man3/OSSL_PARAM_BLD.pod
+DEPEND[man/man3/OSSL_PARAM_BLD.3]=man3/OSSL_PARAM_BLD.pod
+GENERATE[man/man3/OSSL_PARAM_BLD.3]=man3/OSSL_PARAM_BLD.pod
+DEPEND[html/man3/OSSL_PARAM_allocate_from_text.html]=man3/OSSL_PARAM_allocate_from_text.pod
+GENERATE[html/man3/OSSL_PARAM_allocate_from_text.html]=man3/OSSL_PARAM_allocate_from_text.pod
+DEPEND[man/man3/OSSL_PARAM_allocate_from_text.3]=man3/OSSL_PARAM_allocate_from_text.pod
+GENERATE[man/man3/OSSL_PARAM_allocate_from_text.3]=man3/OSSL_PARAM_allocate_from_text.pod
+DEPEND[html/man3/OSSL_PARAM_dup.html]=man3/OSSL_PARAM_dup.pod
+GENERATE[html/man3/OSSL_PARAM_dup.html]=man3/OSSL_PARAM_dup.pod
+DEPEND[man/man3/OSSL_PARAM_dup.3]=man3/OSSL_PARAM_dup.pod
+GENERATE[man/man3/OSSL_PARAM_dup.3]=man3/OSSL_PARAM_dup.pod
+DEPEND[html/man3/OSSL_PARAM_int.html]=man3/OSSL_PARAM_int.pod
+GENERATE[html/man3/OSSL_PARAM_int.html]=man3/OSSL_PARAM_int.pod
+DEPEND[man/man3/OSSL_PARAM_int.3]=man3/OSSL_PARAM_int.pod
+GENERATE[man/man3/OSSL_PARAM_int.3]=man3/OSSL_PARAM_int.pod
+DEPEND[html/man3/OSSL_PROVIDER.html]=man3/OSSL_PROVIDER.pod
+GENERATE[html/man3/OSSL_PROVIDER.html]=man3/OSSL_PROVIDER.pod
+DEPEND[man/man3/OSSL_PROVIDER.3]=man3/OSSL_PROVIDER.pod
+GENERATE[man/man3/OSSL_PROVIDER.3]=man3/OSSL_PROVIDER.pod
+DEPEND[html/man3/OSSL_SELF_TEST_new.html]=man3/OSSL_SELF_TEST_new.pod
+GENERATE[html/man3/OSSL_SELF_TEST_new.html]=man3/OSSL_SELF_TEST_new.pod
+DEPEND[man/man3/OSSL_SELF_TEST_new.3]=man3/OSSL_SELF_TEST_new.pod
+GENERATE[man/man3/OSSL_SELF_TEST_new.3]=man3/OSSL_SELF_TEST_new.pod
+DEPEND[html/man3/OSSL_SELF_TEST_set_callback.html]=man3/OSSL_SELF_TEST_set_callback.pod
+GENERATE[html/man3/OSSL_SELF_TEST_set_callback.html]=man3/OSSL_SELF_TEST_set_callback.pod
+DEPEND[man/man3/OSSL_SELF_TEST_set_callback.3]=man3/OSSL_SELF_TEST_set_callback.pod
+GENERATE[man/man3/OSSL_SELF_TEST_set_callback.3]=man3/OSSL_SELF_TEST_set_callback.pod
+DEPEND[html/man3/OSSL_STORE_INFO.html]=man3/OSSL_STORE_INFO.pod
+GENERATE[html/man3/OSSL_STORE_INFO.html]=man3/OSSL_STORE_INFO.pod
+DEPEND[man/man3/OSSL_STORE_INFO.3]=man3/OSSL_STORE_INFO.pod
+GENERATE[man/man3/OSSL_STORE_INFO.3]=man3/OSSL_STORE_INFO.pod
+DEPEND[html/man3/OSSL_STORE_LOADER.html]=man3/OSSL_STORE_LOADER.pod
+GENERATE[html/man3/OSSL_STORE_LOADER.html]=man3/OSSL_STORE_LOADER.pod
+DEPEND[man/man3/OSSL_STORE_LOADER.3]=man3/OSSL_STORE_LOADER.pod
+GENERATE[man/man3/OSSL_STORE_LOADER.3]=man3/OSSL_STORE_LOADER.pod
+DEPEND[html/man3/OSSL_STORE_SEARCH.html]=man3/OSSL_STORE_SEARCH.pod
+GENERATE[html/man3/OSSL_STORE_SEARCH.html]=man3/OSSL_STORE_SEARCH.pod
+DEPEND[man/man3/OSSL_STORE_SEARCH.3]=man3/OSSL_STORE_SEARCH.pod
+GENERATE[man/man3/OSSL_STORE_SEARCH.3]=man3/OSSL_STORE_SEARCH.pod
+DEPEND[html/man3/OSSL_STORE_attach.html]=man3/OSSL_STORE_attach.pod
+GENERATE[html/man3/OSSL_STORE_attach.html]=man3/OSSL_STORE_attach.pod
+DEPEND[man/man3/OSSL_STORE_attach.3]=man3/OSSL_STORE_attach.pod
+GENERATE[man/man3/OSSL_STORE_attach.3]=man3/OSSL_STORE_attach.pod
+DEPEND[html/man3/OSSL_STORE_expect.html]=man3/OSSL_STORE_expect.pod
+GENERATE[html/man3/OSSL_STORE_expect.html]=man3/OSSL_STORE_expect.pod
+DEPEND[man/man3/OSSL_STORE_expect.3]=man3/OSSL_STORE_expect.pod
+GENERATE[man/man3/OSSL_STORE_expect.3]=man3/OSSL_STORE_expect.pod
+DEPEND[html/man3/OSSL_STORE_open.html]=man3/OSSL_STORE_open.pod
+GENERATE[html/man3/OSSL_STORE_open.html]=man3/OSSL_STORE_open.pod
+DEPEND[man/man3/OSSL_STORE_open.3]=man3/OSSL_STORE_open.pod
+GENERATE[man/man3/OSSL_STORE_open.3]=man3/OSSL_STORE_open.pod
+DEPEND[html/man3/OSSL_trace_enabled.html]=man3/OSSL_trace_enabled.pod
+GENERATE[html/man3/OSSL_trace_enabled.html]=man3/OSSL_trace_enabled.pod
+DEPEND[man/man3/OSSL_trace_enabled.3]=man3/OSSL_trace_enabled.pod
+GENERATE[man/man3/OSSL_trace_enabled.3]=man3/OSSL_trace_enabled.pod
+DEPEND[html/man3/OSSL_trace_get_category_num.html]=man3/OSSL_trace_get_category_num.pod
+GENERATE[html/man3/OSSL_trace_get_category_num.html]=man3/OSSL_trace_get_category_num.pod
+DEPEND[man/man3/OSSL_trace_get_category_num.3]=man3/OSSL_trace_get_category_num.pod
+GENERATE[man/man3/OSSL_trace_get_category_num.3]=man3/OSSL_trace_get_category_num.pod
+DEPEND[html/man3/OSSL_trace_set_channel.html]=man3/OSSL_trace_set_channel.pod
+GENERATE[html/man3/OSSL_trace_set_channel.html]=man3/OSSL_trace_set_channel.pod
+DEPEND[man/man3/OSSL_trace_set_channel.3]=man3/OSSL_trace_set_channel.pod
+GENERATE[man/man3/OSSL_trace_set_channel.3]=man3/OSSL_trace_set_channel.pod
+DEPEND[html/man3/OpenSSL_add_all_algorithms.html]=man3/OpenSSL_add_all_algorithms.pod
+GENERATE[html/man3/OpenSSL_add_all_algorithms.html]=man3/OpenSSL_add_all_algorithms.pod
+DEPEND[man/man3/OpenSSL_add_all_algorithms.3]=man3/OpenSSL_add_all_algorithms.pod
+GENERATE[man/man3/OpenSSL_add_all_algorithms.3]=man3/OpenSSL_add_all_algorithms.pod
+DEPEND[html/man3/OpenSSL_version.html]=man3/OpenSSL_version.pod
+GENERATE[html/man3/OpenSSL_version.html]=man3/OpenSSL_version.pod
+DEPEND[man/man3/OpenSSL_version.3]=man3/OpenSSL_version.pod
+GENERATE[man/man3/OpenSSL_version.3]=man3/OpenSSL_version.pod
+DEPEND[html/man3/PEM_X509_INFO_read_bio_ex.html]=man3/PEM_X509_INFO_read_bio_ex.pod
+GENERATE[html/man3/PEM_X509_INFO_read_bio_ex.html]=man3/PEM_X509_INFO_read_bio_ex.pod
+DEPEND[man/man3/PEM_X509_INFO_read_bio_ex.3]=man3/PEM_X509_INFO_read_bio_ex.pod
+GENERATE[man/man3/PEM_X509_INFO_read_bio_ex.3]=man3/PEM_X509_INFO_read_bio_ex.pod
+DEPEND[html/man3/PEM_bytes_read_bio.html]=man3/PEM_bytes_read_bio.pod
+GENERATE[html/man3/PEM_bytes_read_bio.html]=man3/PEM_bytes_read_bio.pod
+DEPEND[man/man3/PEM_bytes_read_bio.3]=man3/PEM_bytes_read_bio.pod
+GENERATE[man/man3/PEM_bytes_read_bio.3]=man3/PEM_bytes_read_bio.pod
+DEPEND[html/man3/PEM_read.html]=man3/PEM_read.pod
+GENERATE[html/man3/PEM_read.html]=man3/PEM_read.pod
+DEPEND[man/man3/PEM_read.3]=man3/PEM_read.pod
+GENERATE[man/man3/PEM_read.3]=man3/PEM_read.pod
+DEPEND[html/man3/PEM_read_CMS.html]=man3/PEM_read_CMS.pod
+GENERATE[html/man3/PEM_read_CMS.html]=man3/PEM_read_CMS.pod
+DEPEND[man/man3/PEM_read_CMS.3]=man3/PEM_read_CMS.pod
+GENERATE[man/man3/PEM_read_CMS.3]=man3/PEM_read_CMS.pod
+DEPEND[html/man3/PEM_read_bio_PrivateKey.html]=man3/PEM_read_bio_PrivateKey.pod
+GENERATE[html/man3/PEM_read_bio_PrivateKey.html]=man3/PEM_read_bio_PrivateKey.pod
+DEPEND[man/man3/PEM_read_bio_PrivateKey.3]=man3/PEM_read_bio_PrivateKey.pod
+GENERATE[man/man3/PEM_read_bio_PrivateKey.3]=man3/PEM_read_bio_PrivateKey.pod
+DEPEND[html/man3/PEM_read_bio_ex.html]=man3/PEM_read_bio_ex.pod
+GENERATE[html/man3/PEM_read_bio_ex.html]=man3/PEM_read_bio_ex.pod
+DEPEND[man/man3/PEM_read_bio_ex.3]=man3/PEM_read_bio_ex.pod
+GENERATE[man/man3/PEM_read_bio_ex.3]=man3/PEM_read_bio_ex.pod
+DEPEND[html/man3/PEM_write_bio_CMS_stream.html]=man3/PEM_write_bio_CMS_stream.pod
+GENERATE[html/man3/PEM_write_bio_CMS_stream.html]=man3/PEM_write_bio_CMS_stream.pod
+DEPEND[man/man3/PEM_write_bio_CMS_stream.3]=man3/PEM_write_bio_CMS_stream.pod
+GENERATE[man/man3/PEM_write_bio_CMS_stream.3]=man3/PEM_write_bio_CMS_stream.pod
+DEPEND[html/man3/PEM_write_bio_PKCS7_stream.html]=man3/PEM_write_bio_PKCS7_stream.pod
+GENERATE[html/man3/PEM_write_bio_PKCS7_stream.html]=man3/PEM_write_bio_PKCS7_stream.pod
+DEPEND[man/man3/PEM_write_bio_PKCS7_stream.3]=man3/PEM_write_bio_PKCS7_stream.pod
+GENERATE[man/man3/PEM_write_bio_PKCS7_stream.3]=man3/PEM_write_bio_PKCS7_stream.pod
+DEPEND[html/man3/PKCS12_PBE_keyivgen.html]=man3/PKCS12_PBE_keyivgen.pod
+GENERATE[html/man3/PKCS12_PBE_keyivgen.html]=man3/PKCS12_PBE_keyivgen.pod
+DEPEND[man/man3/PKCS12_PBE_keyivgen.3]=man3/PKCS12_PBE_keyivgen.pod
+GENERATE[man/man3/PKCS12_PBE_keyivgen.3]=man3/PKCS12_PBE_keyivgen.pod
+DEPEND[html/man3/PKCS12_SAFEBAG_create_cert.html]=man3/PKCS12_SAFEBAG_create_cert.pod
+GENERATE[html/man3/PKCS12_SAFEBAG_create_cert.html]=man3/PKCS12_SAFEBAG_create_cert.pod
+DEPEND[man/man3/PKCS12_SAFEBAG_create_cert.3]=man3/PKCS12_SAFEBAG_create_cert.pod
+GENERATE[man/man3/PKCS12_SAFEBAG_create_cert.3]=man3/PKCS12_SAFEBAG_create_cert.pod
+DEPEND[html/man3/PKCS12_SAFEBAG_get0_attrs.html]=man3/PKCS12_SAFEBAG_get0_attrs.pod
+GENERATE[html/man3/PKCS12_SAFEBAG_get0_attrs.html]=man3/PKCS12_SAFEBAG_get0_attrs.pod
+DEPEND[man/man3/PKCS12_SAFEBAG_get0_attrs.3]=man3/PKCS12_SAFEBAG_get0_attrs.pod
+GENERATE[man/man3/PKCS12_SAFEBAG_get0_attrs.3]=man3/PKCS12_SAFEBAG_get0_attrs.pod
+DEPEND[html/man3/PKCS12_SAFEBAG_get1_cert.html]=man3/PKCS12_SAFEBAG_get1_cert.pod
+GENERATE[html/man3/PKCS12_SAFEBAG_get1_cert.html]=man3/PKCS12_SAFEBAG_get1_cert.pod
+DEPEND[man/man3/PKCS12_SAFEBAG_get1_cert.3]=man3/PKCS12_SAFEBAG_get1_cert.pod
+GENERATE[man/man3/PKCS12_SAFEBAG_get1_cert.3]=man3/PKCS12_SAFEBAG_get1_cert.pod
+DEPEND[html/man3/PKCS12_add1_attr_by_NID.html]=man3/PKCS12_add1_attr_by_NID.pod
+GENERATE[html/man3/PKCS12_add1_attr_by_NID.html]=man3/PKCS12_add1_attr_by_NID.pod
+DEPEND[man/man3/PKCS12_add1_attr_by_NID.3]=man3/PKCS12_add1_attr_by_NID.pod
+GENERATE[man/man3/PKCS12_add1_attr_by_NID.3]=man3/PKCS12_add1_attr_by_NID.pod
+DEPEND[html/man3/PKCS12_add_CSPName_asc.html]=man3/PKCS12_add_CSPName_asc.pod
+GENERATE[html/man3/PKCS12_add_CSPName_asc.html]=man3/PKCS12_add_CSPName_asc.pod
+DEPEND[man/man3/PKCS12_add_CSPName_asc.3]=man3/PKCS12_add_CSPName_asc.pod
+GENERATE[man/man3/PKCS12_add_CSPName_asc.3]=man3/PKCS12_add_CSPName_asc.pod
+DEPEND[html/man3/PKCS12_add_cert.html]=man3/PKCS12_add_cert.pod
+GENERATE[html/man3/PKCS12_add_cert.html]=man3/PKCS12_add_cert.pod
+DEPEND[man/man3/PKCS12_add_cert.3]=man3/PKCS12_add_cert.pod
+GENERATE[man/man3/PKCS12_add_cert.3]=man3/PKCS12_add_cert.pod
+DEPEND[html/man3/PKCS12_add_friendlyname_asc.html]=man3/PKCS12_add_friendlyname_asc.pod
+GENERATE[html/man3/PKCS12_add_friendlyname_asc.html]=man3/PKCS12_add_friendlyname_asc.pod
+DEPEND[man/man3/PKCS12_add_friendlyname_asc.3]=man3/PKCS12_add_friendlyname_asc.pod
+GENERATE[man/man3/PKCS12_add_friendlyname_asc.3]=man3/PKCS12_add_friendlyname_asc.pod
+DEPEND[html/man3/PKCS12_add_localkeyid.html]=man3/PKCS12_add_localkeyid.pod
+GENERATE[html/man3/PKCS12_add_localkeyid.html]=man3/PKCS12_add_localkeyid.pod
+DEPEND[man/man3/PKCS12_add_localkeyid.3]=man3/PKCS12_add_localkeyid.pod
+GENERATE[man/man3/PKCS12_add_localkeyid.3]=man3/PKCS12_add_localkeyid.pod
+DEPEND[html/man3/PKCS12_add_safe.html]=man3/PKCS12_add_safe.pod
+GENERATE[html/man3/PKCS12_add_safe.html]=man3/PKCS12_add_safe.pod
+DEPEND[man/man3/PKCS12_add_safe.3]=man3/PKCS12_add_safe.pod
+GENERATE[man/man3/PKCS12_add_safe.3]=man3/PKCS12_add_safe.pod
+DEPEND[html/man3/PKCS12_create.html]=man3/PKCS12_create.pod
+GENERATE[html/man3/PKCS12_create.html]=man3/PKCS12_create.pod
+DEPEND[man/man3/PKCS12_create.3]=man3/PKCS12_create.pod
+GENERATE[man/man3/PKCS12_create.3]=man3/PKCS12_create.pod
+DEPEND[html/man3/PKCS12_decrypt_skey.html]=man3/PKCS12_decrypt_skey.pod
+GENERATE[html/man3/PKCS12_decrypt_skey.html]=man3/PKCS12_decrypt_skey.pod
+DEPEND[man/man3/PKCS12_decrypt_skey.3]=man3/PKCS12_decrypt_skey.pod
+GENERATE[man/man3/PKCS12_decrypt_skey.3]=man3/PKCS12_decrypt_skey.pod
+DEPEND[html/man3/PKCS12_gen_mac.html]=man3/PKCS12_gen_mac.pod
+GENERATE[html/man3/PKCS12_gen_mac.html]=man3/PKCS12_gen_mac.pod
+DEPEND[man/man3/PKCS12_gen_mac.3]=man3/PKCS12_gen_mac.pod
+GENERATE[man/man3/PKCS12_gen_mac.3]=man3/PKCS12_gen_mac.pod
+DEPEND[html/man3/PKCS12_get_friendlyname.html]=man3/PKCS12_get_friendlyname.pod
+GENERATE[html/man3/PKCS12_get_friendlyname.html]=man3/PKCS12_get_friendlyname.pod
+DEPEND[man/man3/PKCS12_get_friendlyname.3]=man3/PKCS12_get_friendlyname.pod
+GENERATE[man/man3/PKCS12_get_friendlyname.3]=man3/PKCS12_get_friendlyname.pod
+DEPEND[html/man3/PKCS12_init.html]=man3/PKCS12_init.pod
+GENERATE[html/man3/PKCS12_init.html]=man3/PKCS12_init.pod
+DEPEND[man/man3/PKCS12_init.3]=man3/PKCS12_init.pod
+GENERATE[man/man3/PKCS12_init.3]=man3/PKCS12_init.pod
+DEPEND[html/man3/PKCS12_item_decrypt_d2i.html]=man3/PKCS12_item_decrypt_d2i.pod
+GENERATE[html/man3/PKCS12_item_decrypt_d2i.html]=man3/PKCS12_item_decrypt_d2i.pod
+DEPEND[man/man3/PKCS12_item_decrypt_d2i.3]=man3/PKCS12_item_decrypt_d2i.pod
+GENERATE[man/man3/PKCS12_item_decrypt_d2i.3]=man3/PKCS12_item_decrypt_d2i.pod
+DEPEND[html/man3/PKCS12_key_gen_utf8_ex.html]=man3/PKCS12_key_gen_utf8_ex.pod
+GENERATE[html/man3/PKCS12_key_gen_utf8_ex.html]=man3/PKCS12_key_gen_utf8_ex.pod
+DEPEND[man/man3/PKCS12_key_gen_utf8_ex.3]=man3/PKCS12_key_gen_utf8_ex.pod
+GENERATE[man/man3/PKCS12_key_gen_utf8_ex.3]=man3/PKCS12_key_gen_utf8_ex.pod
+DEPEND[html/man3/PKCS12_newpass.html]=man3/PKCS12_newpass.pod
+GENERATE[html/man3/PKCS12_newpass.html]=man3/PKCS12_newpass.pod
+DEPEND[man/man3/PKCS12_newpass.3]=man3/PKCS12_newpass.pod
+GENERATE[man/man3/PKCS12_newpass.3]=man3/PKCS12_newpass.pod
+DEPEND[html/man3/PKCS12_pack_p7encdata.html]=man3/PKCS12_pack_p7encdata.pod
+GENERATE[html/man3/PKCS12_pack_p7encdata.html]=man3/PKCS12_pack_p7encdata.pod
+DEPEND[man/man3/PKCS12_pack_p7encdata.3]=man3/PKCS12_pack_p7encdata.pod
+GENERATE[man/man3/PKCS12_pack_p7encdata.3]=man3/PKCS12_pack_p7encdata.pod
+DEPEND[html/man3/PKCS12_parse.html]=man3/PKCS12_parse.pod
+GENERATE[html/man3/PKCS12_parse.html]=man3/PKCS12_parse.pod
+DEPEND[man/man3/PKCS12_parse.3]=man3/PKCS12_parse.pod
+GENERATE[man/man3/PKCS12_parse.3]=man3/PKCS12_parse.pod
+DEPEND[html/man3/PKCS5_PBE_keyivgen.html]=man3/PKCS5_PBE_keyivgen.pod
+GENERATE[html/man3/PKCS5_PBE_keyivgen.html]=man3/PKCS5_PBE_keyivgen.pod
+DEPEND[man/man3/PKCS5_PBE_keyivgen.3]=man3/PKCS5_PBE_keyivgen.pod
+GENERATE[man/man3/PKCS5_PBE_keyivgen.3]=man3/PKCS5_PBE_keyivgen.pod
+DEPEND[html/man3/PKCS5_PBKDF2_HMAC.html]=man3/PKCS5_PBKDF2_HMAC.pod
+GENERATE[html/man3/PKCS5_PBKDF2_HMAC.html]=man3/PKCS5_PBKDF2_HMAC.pod
+DEPEND[man/man3/PKCS5_PBKDF2_HMAC.3]=man3/PKCS5_PBKDF2_HMAC.pod
+GENERATE[man/man3/PKCS5_PBKDF2_HMAC.3]=man3/PKCS5_PBKDF2_HMAC.pod
+DEPEND[html/man3/PKCS7_decrypt.html]=man3/PKCS7_decrypt.pod
+GENERATE[html/man3/PKCS7_decrypt.html]=man3/PKCS7_decrypt.pod
+DEPEND[man/man3/PKCS7_decrypt.3]=man3/PKCS7_decrypt.pod
+GENERATE[man/man3/PKCS7_decrypt.3]=man3/PKCS7_decrypt.pod
+DEPEND[html/man3/PKCS7_encrypt.html]=man3/PKCS7_encrypt.pod
+GENERATE[html/man3/PKCS7_encrypt.html]=man3/PKCS7_encrypt.pod
+DEPEND[man/man3/PKCS7_encrypt.3]=man3/PKCS7_encrypt.pod
+GENERATE[man/man3/PKCS7_encrypt.3]=man3/PKCS7_encrypt.pod
+DEPEND[html/man3/PKCS7_get_octet_string.html]=man3/PKCS7_get_octet_string.pod
+GENERATE[html/man3/PKCS7_get_octet_string.html]=man3/PKCS7_get_octet_string.pod
+DEPEND[man/man3/PKCS7_get_octet_string.3]=man3/PKCS7_get_octet_string.pod
+GENERATE[man/man3/PKCS7_get_octet_string.3]=man3/PKCS7_get_octet_string.pod
+DEPEND[html/man3/PKCS7_sign.html]=man3/PKCS7_sign.pod
+GENERATE[html/man3/PKCS7_sign.html]=man3/PKCS7_sign.pod
+DEPEND[man/man3/PKCS7_sign.3]=man3/PKCS7_sign.pod
+GENERATE[man/man3/PKCS7_sign.3]=man3/PKCS7_sign.pod
+DEPEND[html/man3/PKCS7_sign_add_signer.html]=man3/PKCS7_sign_add_signer.pod
+GENERATE[html/man3/PKCS7_sign_add_signer.html]=man3/PKCS7_sign_add_signer.pod
+DEPEND[man/man3/PKCS7_sign_add_signer.3]=man3/PKCS7_sign_add_signer.pod
+GENERATE[man/man3/PKCS7_sign_add_signer.3]=man3/PKCS7_sign_add_signer.pod
+DEPEND[html/man3/PKCS7_type_is_other.html]=man3/PKCS7_type_is_other.pod
+GENERATE[html/man3/PKCS7_type_is_other.html]=man3/PKCS7_type_is_other.pod
+DEPEND[man/man3/PKCS7_type_is_other.3]=man3/PKCS7_type_is_other.pod
+GENERATE[man/man3/PKCS7_type_is_other.3]=man3/PKCS7_type_is_other.pod
+DEPEND[html/man3/PKCS7_verify.html]=man3/PKCS7_verify.pod
+GENERATE[html/man3/PKCS7_verify.html]=man3/PKCS7_verify.pod
+DEPEND[man/man3/PKCS7_verify.3]=man3/PKCS7_verify.pod
+GENERATE[man/man3/PKCS7_verify.3]=man3/PKCS7_verify.pod
+DEPEND[html/man3/PKCS8_encrypt.html]=man3/PKCS8_encrypt.pod
+GENERATE[html/man3/PKCS8_encrypt.html]=man3/PKCS8_encrypt.pod
+DEPEND[man/man3/PKCS8_encrypt.3]=man3/PKCS8_encrypt.pod
+GENERATE[man/man3/PKCS8_encrypt.3]=man3/PKCS8_encrypt.pod
+DEPEND[html/man3/PKCS8_pkey_add1_attr.html]=man3/PKCS8_pkey_add1_attr.pod
+GENERATE[html/man3/PKCS8_pkey_add1_attr.html]=man3/PKCS8_pkey_add1_attr.pod
+DEPEND[man/man3/PKCS8_pkey_add1_attr.3]=man3/PKCS8_pkey_add1_attr.pod
+GENERATE[man/man3/PKCS8_pkey_add1_attr.3]=man3/PKCS8_pkey_add1_attr.pod
+DEPEND[html/man3/RAND_add.html]=man3/RAND_add.pod
+GENERATE[html/man3/RAND_add.html]=man3/RAND_add.pod
+DEPEND[man/man3/RAND_add.3]=man3/RAND_add.pod
+GENERATE[man/man3/RAND_add.3]=man3/RAND_add.pod
+DEPEND[html/man3/RAND_bytes.html]=man3/RAND_bytes.pod
+GENERATE[html/man3/RAND_bytes.html]=man3/RAND_bytes.pod
+DEPEND[man/man3/RAND_bytes.3]=man3/RAND_bytes.pod
+GENERATE[man/man3/RAND_bytes.3]=man3/RAND_bytes.pod
+DEPEND[html/man3/RAND_cleanup.html]=man3/RAND_cleanup.pod
+GENERATE[html/man3/RAND_cleanup.html]=man3/RAND_cleanup.pod
+DEPEND[man/man3/RAND_cleanup.3]=man3/RAND_cleanup.pod
+GENERATE[man/man3/RAND_cleanup.3]=man3/RAND_cleanup.pod
+DEPEND[html/man3/RAND_egd.html]=man3/RAND_egd.pod
+GENERATE[html/man3/RAND_egd.html]=man3/RAND_egd.pod
+DEPEND[man/man3/RAND_egd.3]=man3/RAND_egd.pod
+GENERATE[man/man3/RAND_egd.3]=man3/RAND_egd.pod
+DEPEND[html/man3/RAND_get0_primary.html]=man3/RAND_get0_primary.pod
+GENERATE[html/man3/RAND_get0_primary.html]=man3/RAND_get0_primary.pod
+DEPEND[man/man3/RAND_get0_primary.3]=man3/RAND_get0_primary.pod
+GENERATE[man/man3/RAND_get0_primary.3]=man3/RAND_get0_primary.pod
+DEPEND[html/man3/RAND_load_file.html]=man3/RAND_load_file.pod
+GENERATE[html/man3/RAND_load_file.html]=man3/RAND_load_file.pod
+DEPEND[man/man3/RAND_load_file.3]=man3/RAND_load_file.pod
+GENERATE[man/man3/RAND_load_file.3]=man3/RAND_load_file.pod
+DEPEND[html/man3/RAND_set_DRBG_type.html]=man3/RAND_set_DRBG_type.pod
+GENERATE[html/man3/RAND_set_DRBG_type.html]=man3/RAND_set_DRBG_type.pod
+DEPEND[man/man3/RAND_set_DRBG_type.3]=man3/RAND_set_DRBG_type.pod
+GENERATE[man/man3/RAND_set_DRBG_type.3]=man3/RAND_set_DRBG_type.pod
+DEPEND[html/man3/RAND_set_rand_method.html]=man3/RAND_set_rand_method.pod
+GENERATE[html/man3/RAND_set_rand_method.html]=man3/RAND_set_rand_method.pod
+DEPEND[man/man3/RAND_set_rand_method.3]=man3/RAND_set_rand_method.pod
+GENERATE[man/man3/RAND_set_rand_method.3]=man3/RAND_set_rand_method.pod
+DEPEND[html/man3/RC4_set_key.html]=man3/RC4_set_key.pod
+GENERATE[html/man3/RC4_set_key.html]=man3/RC4_set_key.pod
+DEPEND[man/man3/RC4_set_key.3]=man3/RC4_set_key.pod
+GENERATE[man/man3/RC4_set_key.3]=man3/RC4_set_key.pod
+DEPEND[html/man3/RIPEMD160_Init.html]=man3/RIPEMD160_Init.pod
+GENERATE[html/man3/RIPEMD160_Init.html]=man3/RIPEMD160_Init.pod
+DEPEND[man/man3/RIPEMD160_Init.3]=man3/RIPEMD160_Init.pod
+GENERATE[man/man3/RIPEMD160_Init.3]=man3/RIPEMD160_Init.pod
+DEPEND[html/man3/RSA_blinding_on.html]=man3/RSA_blinding_on.pod
+GENERATE[html/man3/RSA_blinding_on.html]=man3/RSA_blinding_on.pod
+DEPEND[man/man3/RSA_blinding_on.3]=man3/RSA_blinding_on.pod
+GENERATE[man/man3/RSA_blinding_on.3]=man3/RSA_blinding_on.pod
+DEPEND[html/man3/RSA_check_key.html]=man3/RSA_check_key.pod
+GENERATE[html/man3/RSA_check_key.html]=man3/RSA_check_key.pod
+DEPEND[man/man3/RSA_check_key.3]=man3/RSA_check_key.pod
+GENERATE[man/man3/RSA_check_key.3]=man3/RSA_check_key.pod
+DEPEND[html/man3/RSA_generate_key.html]=man3/RSA_generate_key.pod
+GENERATE[html/man3/RSA_generate_key.html]=man3/RSA_generate_key.pod
+DEPEND[man/man3/RSA_generate_key.3]=man3/RSA_generate_key.pod
+GENERATE[man/man3/RSA_generate_key.3]=man3/RSA_generate_key.pod
+DEPEND[html/man3/RSA_get0_key.html]=man3/RSA_get0_key.pod
+GENERATE[html/man3/RSA_get0_key.html]=man3/RSA_get0_key.pod
+DEPEND[man/man3/RSA_get0_key.3]=man3/RSA_get0_key.pod
+GENERATE[man/man3/RSA_get0_key.3]=man3/RSA_get0_key.pod
+DEPEND[html/man3/RSA_meth_new.html]=man3/RSA_meth_new.pod
+GENERATE[html/man3/RSA_meth_new.html]=man3/RSA_meth_new.pod
+DEPEND[man/man3/RSA_meth_new.3]=man3/RSA_meth_new.pod
+GENERATE[man/man3/RSA_meth_new.3]=man3/RSA_meth_new.pod
+DEPEND[html/man3/RSA_new.html]=man3/RSA_new.pod
+GENERATE[html/man3/RSA_new.html]=man3/RSA_new.pod
+DEPEND[man/man3/RSA_new.3]=man3/RSA_new.pod
+GENERATE[man/man3/RSA_new.3]=man3/RSA_new.pod
+DEPEND[html/man3/RSA_padding_add_PKCS1_type_1.html]=man3/RSA_padding_add_PKCS1_type_1.pod
+GENERATE[html/man3/RSA_padding_add_PKCS1_type_1.html]=man3/RSA_padding_add_PKCS1_type_1.pod
+DEPEND[man/man3/RSA_padding_add_PKCS1_type_1.3]=man3/RSA_padding_add_PKCS1_type_1.pod
+GENERATE[man/man3/RSA_padding_add_PKCS1_type_1.3]=man3/RSA_padding_add_PKCS1_type_1.pod
+DEPEND[html/man3/RSA_print.html]=man3/RSA_print.pod
+GENERATE[html/man3/RSA_print.html]=man3/RSA_print.pod
+DEPEND[man/man3/RSA_print.3]=man3/RSA_print.pod
+GENERATE[man/man3/RSA_print.3]=man3/RSA_print.pod
+DEPEND[html/man3/RSA_private_encrypt.html]=man3/RSA_private_encrypt.pod
+GENERATE[html/man3/RSA_private_encrypt.html]=man3/RSA_private_encrypt.pod
+DEPEND[man/man3/RSA_private_encrypt.3]=man3/RSA_private_encrypt.pod
+GENERATE[man/man3/RSA_private_encrypt.3]=man3/RSA_private_encrypt.pod
+DEPEND[html/man3/RSA_public_encrypt.html]=man3/RSA_public_encrypt.pod
+GENERATE[html/man3/RSA_public_encrypt.html]=man3/RSA_public_encrypt.pod
+DEPEND[man/man3/RSA_public_encrypt.3]=man3/RSA_public_encrypt.pod
+GENERATE[man/man3/RSA_public_encrypt.3]=man3/RSA_public_encrypt.pod
+DEPEND[html/man3/RSA_set_method.html]=man3/RSA_set_method.pod
+GENERATE[html/man3/RSA_set_method.html]=man3/RSA_set_method.pod
+DEPEND[man/man3/RSA_set_method.3]=man3/RSA_set_method.pod
+GENERATE[man/man3/RSA_set_method.3]=man3/RSA_set_method.pod
+DEPEND[html/man3/RSA_sign.html]=man3/RSA_sign.pod
+GENERATE[html/man3/RSA_sign.html]=man3/RSA_sign.pod
+DEPEND[man/man3/RSA_sign.3]=man3/RSA_sign.pod
+GENERATE[man/man3/RSA_sign.3]=man3/RSA_sign.pod
+DEPEND[html/man3/RSA_sign_ASN1_OCTET_STRING.html]=man3/RSA_sign_ASN1_OCTET_STRING.pod
+GENERATE[html/man3/RSA_sign_ASN1_OCTET_STRING.html]=man3/RSA_sign_ASN1_OCTET_STRING.pod
+DEPEND[man/man3/RSA_sign_ASN1_OCTET_STRING.3]=man3/RSA_sign_ASN1_OCTET_STRING.pod
+GENERATE[man/man3/RSA_sign_ASN1_OCTET_STRING.3]=man3/RSA_sign_ASN1_OCTET_STRING.pod
+DEPEND[html/man3/RSA_size.html]=man3/RSA_size.pod
+GENERATE[html/man3/RSA_size.html]=man3/RSA_size.pod
+DEPEND[man/man3/RSA_size.3]=man3/RSA_size.pod
+GENERATE[man/man3/RSA_size.3]=man3/RSA_size.pod
+DEPEND[html/man3/SCT_new.html]=man3/SCT_new.pod
+GENERATE[html/man3/SCT_new.html]=man3/SCT_new.pod
+DEPEND[man/man3/SCT_new.3]=man3/SCT_new.pod
+GENERATE[man/man3/SCT_new.3]=man3/SCT_new.pod
+DEPEND[html/man3/SCT_print.html]=man3/SCT_print.pod
+GENERATE[html/man3/SCT_print.html]=man3/SCT_print.pod
+DEPEND[man/man3/SCT_print.3]=man3/SCT_print.pod
+GENERATE[man/man3/SCT_print.3]=man3/SCT_print.pod
+DEPEND[html/man3/SCT_validate.html]=man3/SCT_validate.pod
+GENERATE[html/man3/SCT_validate.html]=man3/SCT_validate.pod
+DEPEND[man/man3/SCT_validate.3]=man3/SCT_validate.pod
+GENERATE[man/man3/SCT_validate.3]=man3/SCT_validate.pod
+DEPEND[html/man3/SHA256_Init.html]=man3/SHA256_Init.pod
+GENERATE[html/man3/SHA256_Init.html]=man3/SHA256_Init.pod
+DEPEND[man/man3/SHA256_Init.3]=man3/SHA256_Init.pod
+GENERATE[man/man3/SHA256_Init.3]=man3/SHA256_Init.pod
+DEPEND[html/man3/SMIME_read_ASN1.html]=man3/SMIME_read_ASN1.pod
+GENERATE[html/man3/SMIME_read_ASN1.html]=man3/SMIME_read_ASN1.pod
+DEPEND[man/man3/SMIME_read_ASN1.3]=man3/SMIME_read_ASN1.pod
+GENERATE[man/man3/SMIME_read_ASN1.3]=man3/SMIME_read_ASN1.pod
+DEPEND[html/man3/SMIME_read_CMS.html]=man3/SMIME_read_CMS.pod
+GENERATE[html/man3/SMIME_read_CMS.html]=man3/SMIME_read_CMS.pod
+DEPEND[man/man3/SMIME_read_CMS.3]=man3/SMIME_read_CMS.pod
+GENERATE[man/man3/SMIME_read_CMS.3]=man3/SMIME_read_CMS.pod
+DEPEND[html/man3/SMIME_read_PKCS7.html]=man3/SMIME_read_PKCS7.pod
+GENERATE[html/man3/SMIME_read_PKCS7.html]=man3/SMIME_read_PKCS7.pod
+DEPEND[man/man3/SMIME_read_PKCS7.3]=man3/SMIME_read_PKCS7.pod
+GENERATE[man/man3/SMIME_read_PKCS7.3]=man3/SMIME_read_PKCS7.pod
+DEPEND[html/man3/SMIME_write_ASN1.html]=man3/SMIME_write_ASN1.pod
+GENERATE[html/man3/SMIME_write_ASN1.html]=man3/SMIME_write_ASN1.pod
+DEPEND[man/man3/SMIME_write_ASN1.3]=man3/SMIME_write_ASN1.pod
+GENERATE[man/man3/SMIME_write_ASN1.3]=man3/SMIME_write_ASN1.pod
+DEPEND[html/man3/SMIME_write_CMS.html]=man3/SMIME_write_CMS.pod
+GENERATE[html/man3/SMIME_write_CMS.html]=man3/SMIME_write_CMS.pod
+DEPEND[man/man3/SMIME_write_CMS.3]=man3/SMIME_write_CMS.pod
+GENERATE[man/man3/SMIME_write_CMS.3]=man3/SMIME_write_CMS.pod
+DEPEND[html/man3/SMIME_write_PKCS7.html]=man3/SMIME_write_PKCS7.pod
+GENERATE[html/man3/SMIME_write_PKCS7.html]=man3/SMIME_write_PKCS7.pod
+DEPEND[man/man3/SMIME_write_PKCS7.3]=man3/SMIME_write_PKCS7.pod
+GENERATE[man/man3/SMIME_write_PKCS7.3]=man3/SMIME_write_PKCS7.pod
+DEPEND[html/man3/SRP_Calc_B.html]=man3/SRP_Calc_B.pod
+GENERATE[html/man3/SRP_Calc_B.html]=man3/SRP_Calc_B.pod
+DEPEND[man/man3/SRP_Calc_B.3]=man3/SRP_Calc_B.pod
+GENERATE[man/man3/SRP_Calc_B.3]=man3/SRP_Calc_B.pod
+DEPEND[html/man3/SRP_VBASE_new.html]=man3/SRP_VBASE_new.pod
+GENERATE[html/man3/SRP_VBASE_new.html]=man3/SRP_VBASE_new.pod
+DEPEND[man/man3/SRP_VBASE_new.3]=man3/SRP_VBASE_new.pod
+GENERATE[man/man3/SRP_VBASE_new.3]=man3/SRP_VBASE_new.pod
+DEPEND[html/man3/SRP_create_verifier.html]=man3/SRP_create_verifier.pod
+GENERATE[html/man3/SRP_create_verifier.html]=man3/SRP_create_verifier.pod
+DEPEND[man/man3/SRP_create_verifier.3]=man3/SRP_create_verifier.pod
+GENERATE[man/man3/SRP_create_verifier.3]=man3/SRP_create_verifier.pod
+DEPEND[html/man3/SRP_user_pwd_new.html]=man3/SRP_user_pwd_new.pod
+GENERATE[html/man3/SRP_user_pwd_new.html]=man3/SRP_user_pwd_new.pod
+DEPEND[man/man3/SRP_user_pwd_new.3]=man3/SRP_user_pwd_new.pod
+GENERATE[man/man3/SRP_user_pwd_new.3]=man3/SRP_user_pwd_new.pod
+DEPEND[html/man3/SSL_CIPHER_get_name.html]=man3/SSL_CIPHER_get_name.pod
+GENERATE[html/man3/SSL_CIPHER_get_name.html]=man3/SSL_CIPHER_get_name.pod
+DEPEND[man/man3/SSL_CIPHER_get_name.3]=man3/SSL_CIPHER_get_name.pod
+GENERATE[man/man3/SSL_CIPHER_get_name.3]=man3/SSL_CIPHER_get_name.pod
+DEPEND[html/man3/SSL_COMP_add_compression_method.html]=man3/SSL_COMP_add_compression_method.pod
+GENERATE[html/man3/SSL_COMP_add_compression_method.html]=man3/SSL_COMP_add_compression_method.pod
+DEPEND[man/man3/SSL_COMP_add_compression_method.3]=man3/SSL_COMP_add_compression_method.pod
+GENERATE[man/man3/SSL_COMP_add_compression_method.3]=man3/SSL_COMP_add_compression_method.pod
+DEPEND[html/man3/SSL_CONF_CTX_new.html]=man3/SSL_CONF_CTX_new.pod
+GENERATE[html/man3/SSL_CONF_CTX_new.html]=man3/SSL_CONF_CTX_new.pod
+DEPEND[man/man3/SSL_CONF_CTX_new.3]=man3/SSL_CONF_CTX_new.pod
+GENERATE[man/man3/SSL_CONF_CTX_new.3]=man3/SSL_CONF_CTX_new.pod
+DEPEND[html/man3/SSL_CONF_CTX_set1_prefix.html]=man3/SSL_CONF_CTX_set1_prefix.pod
+GENERATE[html/man3/SSL_CONF_CTX_set1_prefix.html]=man3/SSL_CONF_CTX_set1_prefix.pod
+DEPEND[man/man3/SSL_CONF_CTX_set1_prefix.3]=man3/SSL_CONF_CTX_set1_prefix.pod
+GENERATE[man/man3/SSL_CONF_CTX_set1_prefix.3]=man3/SSL_CONF_CTX_set1_prefix.pod
+DEPEND[html/man3/SSL_CONF_CTX_set_flags.html]=man3/SSL_CONF_CTX_set_flags.pod
+GENERATE[html/man3/SSL_CONF_CTX_set_flags.html]=man3/SSL_CONF_CTX_set_flags.pod
+DEPEND[man/man3/SSL_CONF_CTX_set_flags.3]=man3/SSL_CONF_CTX_set_flags.pod
+GENERATE[man/man3/SSL_CONF_CTX_set_flags.3]=man3/SSL_CONF_CTX_set_flags.pod
+DEPEND[html/man3/SSL_CONF_CTX_set_ssl_ctx.html]=man3/SSL_CONF_CTX_set_ssl_ctx.pod
+GENERATE[html/man3/SSL_CONF_CTX_set_ssl_ctx.html]=man3/SSL_CONF_CTX_set_ssl_ctx.pod
+DEPEND[man/man3/SSL_CONF_CTX_set_ssl_ctx.3]=man3/SSL_CONF_CTX_set_ssl_ctx.pod
+GENERATE[man/man3/SSL_CONF_CTX_set_ssl_ctx.3]=man3/SSL_CONF_CTX_set_ssl_ctx.pod
+DEPEND[html/man3/SSL_CONF_cmd.html]=man3/SSL_CONF_cmd.pod
+GENERATE[html/man3/SSL_CONF_cmd.html]=man3/SSL_CONF_cmd.pod
+DEPEND[man/man3/SSL_CONF_cmd.3]=man3/SSL_CONF_cmd.pod
+GENERATE[man/man3/SSL_CONF_cmd.3]=man3/SSL_CONF_cmd.pod
+DEPEND[html/man3/SSL_CONF_cmd_argv.html]=man3/SSL_CONF_cmd_argv.pod
+GENERATE[html/man3/SSL_CONF_cmd_argv.html]=man3/SSL_CONF_cmd_argv.pod
+DEPEND[man/man3/SSL_CONF_cmd_argv.3]=man3/SSL_CONF_cmd_argv.pod
+GENERATE[man/man3/SSL_CONF_cmd_argv.3]=man3/SSL_CONF_cmd_argv.pod
+DEPEND[html/man3/SSL_CTX_add1_chain_cert.html]=man3/SSL_CTX_add1_chain_cert.pod
+GENERATE[html/man3/SSL_CTX_add1_chain_cert.html]=man3/SSL_CTX_add1_chain_cert.pod
+DEPEND[man/man3/SSL_CTX_add1_chain_cert.3]=man3/SSL_CTX_add1_chain_cert.pod
+GENERATE[man/man3/SSL_CTX_add1_chain_cert.3]=man3/SSL_CTX_add1_chain_cert.pod
+DEPEND[html/man3/SSL_CTX_add_extra_chain_cert.html]=man3/SSL_CTX_add_extra_chain_cert.pod
+GENERATE[html/man3/SSL_CTX_add_extra_chain_cert.html]=man3/SSL_CTX_add_extra_chain_cert.pod
+DEPEND[man/man3/SSL_CTX_add_extra_chain_cert.3]=man3/SSL_CTX_add_extra_chain_cert.pod
+GENERATE[man/man3/SSL_CTX_add_extra_chain_cert.3]=man3/SSL_CTX_add_extra_chain_cert.pod
+DEPEND[html/man3/SSL_CTX_add_session.html]=man3/SSL_CTX_add_session.pod
+GENERATE[html/man3/SSL_CTX_add_session.html]=man3/SSL_CTX_add_session.pod
+DEPEND[man/man3/SSL_CTX_add_session.3]=man3/SSL_CTX_add_session.pod
+GENERATE[man/man3/SSL_CTX_add_session.3]=man3/SSL_CTX_add_session.pod
+DEPEND[html/man3/SSL_CTX_config.html]=man3/SSL_CTX_config.pod
+GENERATE[html/man3/SSL_CTX_config.html]=man3/SSL_CTX_config.pod
+DEPEND[man/man3/SSL_CTX_config.3]=man3/SSL_CTX_config.pod
+GENERATE[man/man3/SSL_CTX_config.3]=man3/SSL_CTX_config.pod
+DEPEND[html/man3/SSL_CTX_ctrl.html]=man3/SSL_CTX_ctrl.pod
+GENERATE[html/man3/SSL_CTX_ctrl.html]=man3/SSL_CTX_ctrl.pod
+DEPEND[man/man3/SSL_CTX_ctrl.3]=man3/SSL_CTX_ctrl.pod
+GENERATE[man/man3/SSL_CTX_ctrl.3]=man3/SSL_CTX_ctrl.pod
+DEPEND[html/man3/SSL_CTX_dane_enable.html]=man3/SSL_CTX_dane_enable.pod
+GENERATE[html/man3/SSL_CTX_dane_enable.html]=man3/SSL_CTX_dane_enable.pod
+DEPEND[man/man3/SSL_CTX_dane_enable.3]=man3/SSL_CTX_dane_enable.pod
+GENERATE[man/man3/SSL_CTX_dane_enable.3]=man3/SSL_CTX_dane_enable.pod
+DEPEND[html/man3/SSL_CTX_flush_sessions.html]=man3/SSL_CTX_flush_sessions.pod
+GENERATE[html/man3/SSL_CTX_flush_sessions.html]=man3/SSL_CTX_flush_sessions.pod
+DEPEND[man/man3/SSL_CTX_flush_sessions.3]=man3/SSL_CTX_flush_sessions.pod
+GENERATE[man/man3/SSL_CTX_flush_sessions.3]=man3/SSL_CTX_flush_sessions.pod
+DEPEND[html/man3/SSL_CTX_free.html]=man3/SSL_CTX_free.pod
+GENERATE[html/man3/SSL_CTX_free.html]=man3/SSL_CTX_free.pod
+DEPEND[man/man3/SSL_CTX_free.3]=man3/SSL_CTX_free.pod
+GENERATE[man/man3/SSL_CTX_free.3]=man3/SSL_CTX_free.pod
+DEPEND[html/man3/SSL_CTX_get0_param.html]=man3/SSL_CTX_get0_param.pod
+GENERATE[html/man3/SSL_CTX_get0_param.html]=man3/SSL_CTX_get0_param.pod
+DEPEND[man/man3/SSL_CTX_get0_param.3]=man3/SSL_CTX_get0_param.pod
+GENERATE[man/man3/SSL_CTX_get0_param.3]=man3/SSL_CTX_get0_param.pod
+DEPEND[html/man3/SSL_CTX_get_verify_mode.html]=man3/SSL_CTX_get_verify_mode.pod
+GENERATE[html/man3/SSL_CTX_get_verify_mode.html]=man3/SSL_CTX_get_verify_mode.pod
+DEPEND[man/man3/SSL_CTX_get_verify_mode.3]=man3/SSL_CTX_get_verify_mode.pod
+GENERATE[man/man3/SSL_CTX_get_verify_mode.3]=man3/SSL_CTX_get_verify_mode.pod
+DEPEND[html/man3/SSL_CTX_has_client_custom_ext.html]=man3/SSL_CTX_has_client_custom_ext.pod
+GENERATE[html/man3/SSL_CTX_has_client_custom_ext.html]=man3/SSL_CTX_has_client_custom_ext.pod
+DEPEND[man/man3/SSL_CTX_has_client_custom_ext.3]=man3/SSL_CTX_has_client_custom_ext.pod
+GENERATE[man/man3/SSL_CTX_has_client_custom_ext.3]=man3/SSL_CTX_has_client_custom_ext.pod
+DEPEND[html/man3/SSL_CTX_load_verify_locations.html]=man3/SSL_CTX_load_verify_locations.pod
+GENERATE[html/man3/SSL_CTX_load_verify_locations.html]=man3/SSL_CTX_load_verify_locations.pod
+DEPEND[man/man3/SSL_CTX_load_verify_locations.3]=man3/SSL_CTX_load_verify_locations.pod
+GENERATE[man/man3/SSL_CTX_load_verify_locations.3]=man3/SSL_CTX_load_verify_locations.pod
+DEPEND[html/man3/SSL_CTX_new.html]=man3/SSL_CTX_new.pod
+GENERATE[html/man3/SSL_CTX_new.html]=man3/SSL_CTX_new.pod
+DEPEND[man/man3/SSL_CTX_new.3]=man3/SSL_CTX_new.pod
+GENERATE[man/man3/SSL_CTX_new.3]=man3/SSL_CTX_new.pod
+DEPEND[html/man3/SSL_CTX_sess_number.html]=man3/SSL_CTX_sess_number.pod
+GENERATE[html/man3/SSL_CTX_sess_number.html]=man3/SSL_CTX_sess_number.pod
+DEPEND[man/man3/SSL_CTX_sess_number.3]=man3/SSL_CTX_sess_number.pod
+GENERATE[man/man3/SSL_CTX_sess_number.3]=man3/SSL_CTX_sess_number.pod
+DEPEND[html/man3/SSL_CTX_sess_set_cache_size.html]=man3/SSL_CTX_sess_set_cache_size.pod
+GENERATE[html/man3/SSL_CTX_sess_set_cache_size.html]=man3/SSL_CTX_sess_set_cache_size.pod
+DEPEND[man/man3/SSL_CTX_sess_set_cache_size.3]=man3/SSL_CTX_sess_set_cache_size.pod
+GENERATE[man/man3/SSL_CTX_sess_set_cache_size.3]=man3/SSL_CTX_sess_set_cache_size.pod
+DEPEND[html/man3/SSL_CTX_sess_set_get_cb.html]=man3/SSL_CTX_sess_set_get_cb.pod
+GENERATE[html/man3/SSL_CTX_sess_set_get_cb.html]=man3/SSL_CTX_sess_set_get_cb.pod
+DEPEND[man/man3/SSL_CTX_sess_set_get_cb.3]=man3/SSL_CTX_sess_set_get_cb.pod
+GENERATE[man/man3/SSL_CTX_sess_set_get_cb.3]=man3/SSL_CTX_sess_set_get_cb.pod
+DEPEND[html/man3/SSL_CTX_sessions.html]=man3/SSL_CTX_sessions.pod
+GENERATE[html/man3/SSL_CTX_sessions.html]=man3/SSL_CTX_sessions.pod
+DEPEND[man/man3/SSL_CTX_sessions.3]=man3/SSL_CTX_sessions.pod
+GENERATE[man/man3/SSL_CTX_sessions.3]=man3/SSL_CTX_sessions.pod
+DEPEND[html/man3/SSL_CTX_set0_CA_list.html]=man3/SSL_CTX_set0_CA_list.pod
+GENERATE[html/man3/SSL_CTX_set0_CA_list.html]=man3/SSL_CTX_set0_CA_list.pod
+DEPEND[man/man3/SSL_CTX_set0_CA_list.3]=man3/SSL_CTX_set0_CA_list.pod
+GENERATE[man/man3/SSL_CTX_set0_CA_list.3]=man3/SSL_CTX_set0_CA_list.pod
+DEPEND[html/man3/SSL_CTX_set1_curves.html]=man3/SSL_CTX_set1_curves.pod
+GENERATE[html/man3/SSL_CTX_set1_curves.html]=man3/SSL_CTX_set1_curves.pod
+DEPEND[man/man3/SSL_CTX_set1_curves.3]=man3/SSL_CTX_set1_curves.pod
+GENERATE[man/man3/SSL_CTX_set1_curves.3]=man3/SSL_CTX_set1_curves.pod
+DEPEND[html/man3/SSL_CTX_set1_sigalgs.html]=man3/SSL_CTX_set1_sigalgs.pod
+GENERATE[html/man3/SSL_CTX_set1_sigalgs.html]=man3/SSL_CTX_set1_sigalgs.pod
+DEPEND[man/man3/SSL_CTX_set1_sigalgs.3]=man3/SSL_CTX_set1_sigalgs.pod
+GENERATE[man/man3/SSL_CTX_set1_sigalgs.3]=man3/SSL_CTX_set1_sigalgs.pod
+DEPEND[html/man3/SSL_CTX_set1_verify_cert_store.html]=man3/SSL_CTX_set1_verify_cert_store.pod
+GENERATE[html/man3/SSL_CTX_set1_verify_cert_store.html]=man3/SSL_CTX_set1_verify_cert_store.pod
+DEPEND[man/man3/SSL_CTX_set1_verify_cert_store.3]=man3/SSL_CTX_set1_verify_cert_store.pod
+GENERATE[man/man3/SSL_CTX_set1_verify_cert_store.3]=man3/SSL_CTX_set1_verify_cert_store.pod
+DEPEND[html/man3/SSL_CTX_set_alpn_select_cb.html]=man3/SSL_CTX_set_alpn_select_cb.pod
+GENERATE[html/man3/SSL_CTX_set_alpn_select_cb.html]=man3/SSL_CTX_set_alpn_select_cb.pod
+DEPEND[man/man3/SSL_CTX_set_alpn_select_cb.3]=man3/SSL_CTX_set_alpn_select_cb.pod
+GENERATE[man/man3/SSL_CTX_set_alpn_select_cb.3]=man3/SSL_CTX_set_alpn_select_cb.pod
+DEPEND[html/man3/SSL_CTX_set_cert_cb.html]=man3/SSL_CTX_set_cert_cb.pod
+GENERATE[html/man3/SSL_CTX_set_cert_cb.html]=man3/SSL_CTX_set_cert_cb.pod
+DEPEND[man/man3/SSL_CTX_set_cert_cb.3]=man3/SSL_CTX_set_cert_cb.pod
+GENERATE[man/man3/SSL_CTX_set_cert_cb.3]=man3/SSL_CTX_set_cert_cb.pod
+DEPEND[html/man3/SSL_CTX_set_cert_store.html]=man3/SSL_CTX_set_cert_store.pod
+GENERATE[html/man3/SSL_CTX_set_cert_store.html]=man3/SSL_CTX_set_cert_store.pod
+DEPEND[man/man3/SSL_CTX_set_cert_store.3]=man3/SSL_CTX_set_cert_store.pod
+GENERATE[man/man3/SSL_CTX_set_cert_store.3]=man3/SSL_CTX_set_cert_store.pod
+DEPEND[html/man3/SSL_CTX_set_cert_verify_callback.html]=man3/SSL_CTX_set_cert_verify_callback.pod
+GENERATE[html/man3/SSL_CTX_set_cert_verify_callback.html]=man3/SSL_CTX_set_cert_verify_callback.pod
+DEPEND[man/man3/SSL_CTX_set_cert_verify_callback.3]=man3/SSL_CTX_set_cert_verify_callback.pod
+GENERATE[man/man3/SSL_CTX_set_cert_verify_callback.3]=man3/SSL_CTX_set_cert_verify_callback.pod
+DEPEND[html/man3/SSL_CTX_set_cipher_list.html]=man3/SSL_CTX_set_cipher_list.pod
+GENERATE[html/man3/SSL_CTX_set_cipher_list.html]=man3/SSL_CTX_set_cipher_list.pod
+DEPEND[man/man3/SSL_CTX_set_cipher_list.3]=man3/SSL_CTX_set_cipher_list.pod
+GENERATE[man/man3/SSL_CTX_set_cipher_list.3]=man3/SSL_CTX_set_cipher_list.pod
+DEPEND[html/man3/SSL_CTX_set_client_cert_cb.html]=man3/SSL_CTX_set_client_cert_cb.pod
+GENERATE[html/man3/SSL_CTX_set_client_cert_cb.html]=man3/SSL_CTX_set_client_cert_cb.pod
+DEPEND[man/man3/SSL_CTX_set_client_cert_cb.3]=man3/SSL_CTX_set_client_cert_cb.pod
+GENERATE[man/man3/SSL_CTX_set_client_cert_cb.3]=man3/SSL_CTX_set_client_cert_cb.pod
+DEPEND[html/man3/SSL_CTX_set_client_hello_cb.html]=man3/SSL_CTX_set_client_hello_cb.pod
+GENERATE[html/man3/SSL_CTX_set_client_hello_cb.html]=man3/SSL_CTX_set_client_hello_cb.pod
+DEPEND[man/man3/SSL_CTX_set_client_hello_cb.3]=man3/SSL_CTX_set_client_hello_cb.pod
+GENERATE[man/man3/SSL_CTX_set_client_hello_cb.3]=man3/SSL_CTX_set_client_hello_cb.pod
+DEPEND[html/man3/SSL_CTX_set_ct_validation_callback.html]=man3/SSL_CTX_set_ct_validation_callback.pod
+GENERATE[html/man3/SSL_CTX_set_ct_validation_callback.html]=man3/SSL_CTX_set_ct_validation_callback.pod
+DEPEND[man/man3/SSL_CTX_set_ct_validation_callback.3]=man3/SSL_CTX_set_ct_validation_callback.pod
+GENERATE[man/man3/SSL_CTX_set_ct_validation_callback.3]=man3/SSL_CTX_set_ct_validation_callback.pod
+DEPEND[html/man3/SSL_CTX_set_ctlog_list_file.html]=man3/SSL_CTX_set_ctlog_list_file.pod
+GENERATE[html/man3/SSL_CTX_set_ctlog_list_file.html]=man3/SSL_CTX_set_ctlog_list_file.pod
+DEPEND[man/man3/SSL_CTX_set_ctlog_list_file.3]=man3/SSL_CTX_set_ctlog_list_file.pod
+GENERATE[man/man3/SSL_CTX_set_ctlog_list_file.3]=man3/SSL_CTX_set_ctlog_list_file.pod
+DEPEND[html/man3/SSL_CTX_set_default_passwd_cb.html]=man3/SSL_CTX_set_default_passwd_cb.pod
+GENERATE[html/man3/SSL_CTX_set_default_passwd_cb.html]=man3/SSL_CTX_set_default_passwd_cb.pod
+DEPEND[man/man3/SSL_CTX_set_default_passwd_cb.3]=man3/SSL_CTX_set_default_passwd_cb.pod
+GENERATE[man/man3/SSL_CTX_set_default_passwd_cb.3]=man3/SSL_CTX_set_default_passwd_cb.pod
+DEPEND[html/man3/SSL_CTX_set_generate_session_id.html]=man3/SSL_CTX_set_generate_session_id.pod
+GENERATE[html/man3/SSL_CTX_set_generate_session_id.html]=man3/SSL_CTX_set_generate_session_id.pod
+DEPEND[man/man3/SSL_CTX_set_generate_session_id.3]=man3/SSL_CTX_set_generate_session_id.pod
+GENERATE[man/man3/SSL_CTX_set_generate_session_id.3]=man3/SSL_CTX_set_generate_session_id.pod
+DEPEND[html/man3/SSL_CTX_set_info_callback.html]=man3/SSL_CTX_set_info_callback.pod
+GENERATE[html/man3/SSL_CTX_set_info_callback.html]=man3/SSL_CTX_set_info_callback.pod
+DEPEND[man/man3/SSL_CTX_set_info_callback.3]=man3/SSL_CTX_set_info_callback.pod
+GENERATE[man/man3/SSL_CTX_set_info_callback.3]=man3/SSL_CTX_set_info_callback.pod
+DEPEND[html/man3/SSL_CTX_set_keylog_callback.html]=man3/SSL_CTX_set_keylog_callback.pod
+GENERATE[html/man3/SSL_CTX_set_keylog_callback.html]=man3/SSL_CTX_set_keylog_callback.pod
+DEPEND[man/man3/SSL_CTX_set_keylog_callback.3]=man3/SSL_CTX_set_keylog_callback.pod
+GENERATE[man/man3/SSL_CTX_set_keylog_callback.3]=man3/SSL_CTX_set_keylog_callback.pod
+DEPEND[html/man3/SSL_CTX_set_max_cert_list.html]=man3/SSL_CTX_set_max_cert_list.pod
+GENERATE[html/man3/SSL_CTX_set_max_cert_list.html]=man3/SSL_CTX_set_max_cert_list.pod
+DEPEND[man/man3/SSL_CTX_set_max_cert_list.3]=man3/SSL_CTX_set_max_cert_list.pod
+GENERATE[man/man3/SSL_CTX_set_max_cert_list.3]=man3/SSL_CTX_set_max_cert_list.pod
+DEPEND[html/man3/SSL_CTX_set_min_proto_version.html]=man3/SSL_CTX_set_min_proto_version.pod
+GENERATE[html/man3/SSL_CTX_set_min_proto_version.html]=man3/SSL_CTX_set_min_proto_version.pod
+DEPEND[man/man3/SSL_CTX_set_min_proto_version.3]=man3/SSL_CTX_set_min_proto_version.pod
+GENERATE[man/man3/SSL_CTX_set_min_proto_version.3]=man3/SSL_CTX_set_min_proto_version.pod
+DEPEND[html/man3/SSL_CTX_set_mode.html]=man3/SSL_CTX_set_mode.pod
+GENERATE[html/man3/SSL_CTX_set_mode.html]=man3/SSL_CTX_set_mode.pod
+DEPEND[man/man3/SSL_CTX_set_mode.3]=man3/SSL_CTX_set_mode.pod
+GENERATE[man/man3/SSL_CTX_set_mode.3]=man3/SSL_CTX_set_mode.pod
+DEPEND[html/man3/SSL_CTX_set_msg_callback.html]=man3/SSL_CTX_set_msg_callback.pod
+GENERATE[html/man3/SSL_CTX_set_msg_callback.html]=man3/SSL_CTX_set_msg_callback.pod
+DEPEND[man/man3/SSL_CTX_set_msg_callback.3]=man3/SSL_CTX_set_msg_callback.pod
+GENERATE[man/man3/SSL_CTX_set_msg_callback.3]=man3/SSL_CTX_set_msg_callback.pod
+DEPEND[html/man3/SSL_CTX_set_num_tickets.html]=man3/SSL_CTX_set_num_tickets.pod
+GENERATE[html/man3/SSL_CTX_set_num_tickets.html]=man3/SSL_CTX_set_num_tickets.pod
+DEPEND[man/man3/SSL_CTX_set_num_tickets.3]=man3/SSL_CTX_set_num_tickets.pod
+GENERATE[man/man3/SSL_CTX_set_num_tickets.3]=man3/SSL_CTX_set_num_tickets.pod
+DEPEND[html/man3/SSL_CTX_set_options.html]=man3/SSL_CTX_set_options.pod
+GENERATE[html/man3/SSL_CTX_set_options.html]=man3/SSL_CTX_set_options.pod
+DEPEND[man/man3/SSL_CTX_set_options.3]=man3/SSL_CTX_set_options.pod
+GENERATE[man/man3/SSL_CTX_set_options.3]=man3/SSL_CTX_set_options.pod
+DEPEND[html/man3/SSL_CTX_set_psk_client_callback.html]=man3/SSL_CTX_set_psk_client_callback.pod
+GENERATE[html/man3/SSL_CTX_set_psk_client_callback.html]=man3/SSL_CTX_set_psk_client_callback.pod
+DEPEND[man/man3/SSL_CTX_set_psk_client_callback.3]=man3/SSL_CTX_set_psk_client_callback.pod
+GENERATE[man/man3/SSL_CTX_set_psk_client_callback.3]=man3/SSL_CTX_set_psk_client_callback.pod
+DEPEND[html/man3/SSL_CTX_set_quiet_shutdown.html]=man3/SSL_CTX_set_quiet_shutdown.pod
+GENERATE[html/man3/SSL_CTX_set_quiet_shutdown.html]=man3/SSL_CTX_set_quiet_shutdown.pod
+DEPEND[man/man3/SSL_CTX_set_quiet_shutdown.3]=man3/SSL_CTX_set_quiet_shutdown.pod
+GENERATE[man/man3/SSL_CTX_set_quiet_shutdown.3]=man3/SSL_CTX_set_quiet_shutdown.pod
+DEPEND[html/man3/SSL_CTX_set_read_ahead.html]=man3/SSL_CTX_set_read_ahead.pod
+GENERATE[html/man3/SSL_CTX_set_read_ahead.html]=man3/SSL_CTX_set_read_ahead.pod
+DEPEND[man/man3/SSL_CTX_set_read_ahead.3]=man3/SSL_CTX_set_read_ahead.pod
+GENERATE[man/man3/SSL_CTX_set_read_ahead.3]=man3/SSL_CTX_set_read_ahead.pod
+DEPEND[html/man3/SSL_CTX_set_record_padding_callback.html]=man3/SSL_CTX_set_record_padding_callback.pod
+GENERATE[html/man3/SSL_CTX_set_record_padding_callback.html]=man3/SSL_CTX_set_record_padding_callback.pod
+DEPEND[man/man3/SSL_CTX_set_record_padding_callback.3]=man3/SSL_CTX_set_record_padding_callback.pod
+GENERATE[man/man3/SSL_CTX_set_record_padding_callback.3]=man3/SSL_CTX_set_record_padding_callback.pod
+DEPEND[html/man3/SSL_CTX_set_security_level.html]=man3/SSL_CTX_set_security_level.pod
+GENERATE[html/man3/SSL_CTX_set_security_level.html]=man3/SSL_CTX_set_security_level.pod
+DEPEND[man/man3/SSL_CTX_set_security_level.3]=man3/SSL_CTX_set_security_level.pod
+GENERATE[man/man3/SSL_CTX_set_security_level.3]=man3/SSL_CTX_set_security_level.pod
+DEPEND[html/man3/SSL_CTX_set_session_cache_mode.html]=man3/SSL_CTX_set_session_cache_mode.pod
+GENERATE[html/man3/SSL_CTX_set_session_cache_mode.html]=man3/SSL_CTX_set_session_cache_mode.pod
+DEPEND[man/man3/SSL_CTX_set_session_cache_mode.3]=man3/SSL_CTX_set_session_cache_mode.pod
+GENERATE[man/man3/SSL_CTX_set_session_cache_mode.3]=man3/SSL_CTX_set_session_cache_mode.pod
+DEPEND[html/man3/SSL_CTX_set_session_id_context.html]=man3/SSL_CTX_set_session_id_context.pod
+GENERATE[html/man3/SSL_CTX_set_session_id_context.html]=man3/SSL_CTX_set_session_id_context.pod
+DEPEND[man/man3/SSL_CTX_set_session_id_context.3]=man3/SSL_CTX_set_session_id_context.pod
+GENERATE[man/man3/SSL_CTX_set_session_id_context.3]=man3/SSL_CTX_set_session_id_context.pod
+DEPEND[html/man3/SSL_CTX_set_session_ticket_cb.html]=man3/SSL_CTX_set_session_ticket_cb.pod
+GENERATE[html/man3/SSL_CTX_set_session_ticket_cb.html]=man3/SSL_CTX_set_session_ticket_cb.pod
+DEPEND[man/man3/SSL_CTX_set_session_ticket_cb.3]=man3/SSL_CTX_set_session_ticket_cb.pod
+GENERATE[man/man3/SSL_CTX_set_session_ticket_cb.3]=man3/SSL_CTX_set_session_ticket_cb.pod
+DEPEND[html/man3/SSL_CTX_set_split_send_fragment.html]=man3/SSL_CTX_set_split_send_fragment.pod
+GENERATE[html/man3/SSL_CTX_set_split_send_fragment.html]=man3/SSL_CTX_set_split_send_fragment.pod
+DEPEND[man/man3/SSL_CTX_set_split_send_fragment.3]=man3/SSL_CTX_set_split_send_fragment.pod
+GENERATE[man/man3/SSL_CTX_set_split_send_fragment.3]=man3/SSL_CTX_set_split_send_fragment.pod
+DEPEND[html/man3/SSL_CTX_set_srp_password.html]=man3/SSL_CTX_set_srp_password.pod
+GENERATE[html/man3/SSL_CTX_set_srp_password.html]=man3/SSL_CTX_set_srp_password.pod
+DEPEND[man/man3/SSL_CTX_set_srp_password.3]=man3/SSL_CTX_set_srp_password.pod
+GENERATE[man/man3/SSL_CTX_set_srp_password.3]=man3/SSL_CTX_set_srp_password.pod
+DEPEND[html/man3/SSL_CTX_set_ssl_version.html]=man3/SSL_CTX_set_ssl_version.pod
+GENERATE[html/man3/SSL_CTX_set_ssl_version.html]=man3/SSL_CTX_set_ssl_version.pod
+DEPEND[man/man3/SSL_CTX_set_ssl_version.3]=man3/SSL_CTX_set_ssl_version.pod
+GENERATE[man/man3/SSL_CTX_set_ssl_version.3]=man3/SSL_CTX_set_ssl_version.pod
+DEPEND[html/man3/SSL_CTX_set_stateless_cookie_generate_cb.html]=man3/SSL_CTX_set_stateless_cookie_generate_cb.pod
+GENERATE[html/man3/SSL_CTX_set_stateless_cookie_generate_cb.html]=man3/SSL_CTX_set_stateless_cookie_generate_cb.pod
+DEPEND[man/man3/SSL_CTX_set_stateless_cookie_generate_cb.3]=man3/SSL_CTX_set_stateless_cookie_generate_cb.pod
+GENERATE[man/man3/SSL_CTX_set_stateless_cookie_generate_cb.3]=man3/SSL_CTX_set_stateless_cookie_generate_cb.pod
+DEPEND[html/man3/SSL_CTX_set_timeout.html]=man3/SSL_CTX_set_timeout.pod
+GENERATE[html/man3/SSL_CTX_set_timeout.html]=man3/SSL_CTX_set_timeout.pod
+DEPEND[man/man3/SSL_CTX_set_timeout.3]=man3/SSL_CTX_set_timeout.pod
+GENERATE[man/man3/SSL_CTX_set_timeout.3]=man3/SSL_CTX_set_timeout.pod
+DEPEND[html/man3/SSL_CTX_set_tlsext_servername_callback.html]=man3/SSL_CTX_set_tlsext_servername_callback.pod
+GENERATE[html/man3/SSL_CTX_set_tlsext_servername_callback.html]=man3/SSL_CTX_set_tlsext_servername_callback.pod
+DEPEND[man/man3/SSL_CTX_set_tlsext_servername_callback.3]=man3/SSL_CTX_set_tlsext_servername_callback.pod
+GENERATE[man/man3/SSL_CTX_set_tlsext_servername_callback.3]=man3/SSL_CTX_set_tlsext_servername_callback.pod
+DEPEND[html/man3/SSL_CTX_set_tlsext_status_cb.html]=man3/SSL_CTX_set_tlsext_status_cb.pod
+GENERATE[html/man3/SSL_CTX_set_tlsext_status_cb.html]=man3/SSL_CTX_set_tlsext_status_cb.pod
+DEPEND[man/man3/SSL_CTX_set_tlsext_status_cb.3]=man3/SSL_CTX_set_tlsext_status_cb.pod
+GENERATE[man/man3/SSL_CTX_set_tlsext_status_cb.3]=man3/SSL_CTX_set_tlsext_status_cb.pod
+DEPEND[html/man3/SSL_CTX_set_tlsext_ticket_key_cb.html]=man3/SSL_CTX_set_tlsext_ticket_key_cb.pod
+GENERATE[html/man3/SSL_CTX_set_tlsext_ticket_key_cb.html]=man3/SSL_CTX_set_tlsext_ticket_key_cb.pod
+DEPEND[man/man3/SSL_CTX_set_tlsext_ticket_key_cb.3]=man3/SSL_CTX_set_tlsext_ticket_key_cb.pod
+GENERATE[man/man3/SSL_CTX_set_tlsext_ticket_key_cb.3]=man3/SSL_CTX_set_tlsext_ticket_key_cb.pod
+DEPEND[html/man3/SSL_CTX_set_tlsext_use_srtp.html]=man3/SSL_CTX_set_tlsext_use_srtp.pod
+GENERATE[html/man3/SSL_CTX_set_tlsext_use_srtp.html]=man3/SSL_CTX_set_tlsext_use_srtp.pod
+DEPEND[man/man3/SSL_CTX_set_tlsext_use_srtp.3]=man3/SSL_CTX_set_tlsext_use_srtp.pod
+GENERATE[man/man3/SSL_CTX_set_tlsext_use_srtp.3]=man3/SSL_CTX_set_tlsext_use_srtp.pod
+DEPEND[html/man3/SSL_CTX_set_tmp_dh_callback.html]=man3/SSL_CTX_set_tmp_dh_callback.pod
+GENERATE[html/man3/SSL_CTX_set_tmp_dh_callback.html]=man3/SSL_CTX_set_tmp_dh_callback.pod
+DEPEND[man/man3/SSL_CTX_set_tmp_dh_callback.3]=man3/SSL_CTX_set_tmp_dh_callback.pod
+GENERATE[man/man3/SSL_CTX_set_tmp_dh_callback.3]=man3/SSL_CTX_set_tmp_dh_callback.pod
+DEPEND[html/man3/SSL_CTX_set_tmp_ecdh.html]=man3/SSL_CTX_set_tmp_ecdh.pod
+GENERATE[html/man3/SSL_CTX_set_tmp_ecdh.html]=man3/SSL_CTX_set_tmp_ecdh.pod
+DEPEND[man/man3/SSL_CTX_set_tmp_ecdh.3]=man3/SSL_CTX_set_tmp_ecdh.pod
+GENERATE[man/man3/SSL_CTX_set_tmp_ecdh.3]=man3/SSL_CTX_set_tmp_ecdh.pod
+DEPEND[html/man3/SSL_CTX_set_verify.html]=man3/SSL_CTX_set_verify.pod
+GENERATE[html/man3/SSL_CTX_set_verify.html]=man3/SSL_CTX_set_verify.pod
+DEPEND[man/man3/SSL_CTX_set_verify.3]=man3/SSL_CTX_set_verify.pod
+GENERATE[man/man3/SSL_CTX_set_verify.3]=man3/SSL_CTX_set_verify.pod
+DEPEND[html/man3/SSL_CTX_use_certificate.html]=man3/SSL_CTX_use_certificate.pod
+GENERATE[html/man3/SSL_CTX_use_certificate.html]=man3/SSL_CTX_use_certificate.pod
+DEPEND[man/man3/SSL_CTX_use_certificate.3]=man3/SSL_CTX_use_certificate.pod
+GENERATE[man/man3/SSL_CTX_use_certificate.3]=man3/SSL_CTX_use_certificate.pod
+DEPEND[html/man3/SSL_CTX_use_psk_identity_hint.html]=man3/SSL_CTX_use_psk_identity_hint.pod
+GENERATE[html/man3/SSL_CTX_use_psk_identity_hint.html]=man3/SSL_CTX_use_psk_identity_hint.pod
+DEPEND[man/man3/SSL_CTX_use_psk_identity_hint.3]=man3/SSL_CTX_use_psk_identity_hint.pod
+GENERATE[man/man3/SSL_CTX_use_psk_identity_hint.3]=man3/SSL_CTX_use_psk_identity_hint.pod
+DEPEND[html/man3/SSL_CTX_use_serverinfo.html]=man3/SSL_CTX_use_serverinfo.pod
+GENERATE[html/man3/SSL_CTX_use_serverinfo.html]=man3/SSL_CTX_use_serverinfo.pod
+DEPEND[man/man3/SSL_CTX_use_serverinfo.3]=man3/SSL_CTX_use_serverinfo.pod
+GENERATE[man/man3/SSL_CTX_use_serverinfo.3]=man3/SSL_CTX_use_serverinfo.pod
+DEPEND[html/man3/SSL_SESSION_free.html]=man3/SSL_SESSION_free.pod
+GENERATE[html/man3/SSL_SESSION_free.html]=man3/SSL_SESSION_free.pod
+DEPEND[man/man3/SSL_SESSION_free.3]=man3/SSL_SESSION_free.pod
+GENERATE[man/man3/SSL_SESSION_free.3]=man3/SSL_SESSION_free.pod
+DEPEND[html/man3/SSL_SESSION_get0_cipher.html]=man3/SSL_SESSION_get0_cipher.pod
+GENERATE[html/man3/SSL_SESSION_get0_cipher.html]=man3/SSL_SESSION_get0_cipher.pod
+DEPEND[man/man3/SSL_SESSION_get0_cipher.3]=man3/SSL_SESSION_get0_cipher.pod
+GENERATE[man/man3/SSL_SESSION_get0_cipher.3]=man3/SSL_SESSION_get0_cipher.pod
+DEPEND[html/man3/SSL_SESSION_get0_hostname.html]=man3/SSL_SESSION_get0_hostname.pod
+GENERATE[html/man3/SSL_SESSION_get0_hostname.html]=man3/SSL_SESSION_get0_hostname.pod
+DEPEND[man/man3/SSL_SESSION_get0_hostname.3]=man3/SSL_SESSION_get0_hostname.pod
+GENERATE[man/man3/SSL_SESSION_get0_hostname.3]=man3/SSL_SESSION_get0_hostname.pod
+DEPEND[html/man3/SSL_SESSION_get0_id_context.html]=man3/SSL_SESSION_get0_id_context.pod
+GENERATE[html/man3/SSL_SESSION_get0_id_context.html]=man3/SSL_SESSION_get0_id_context.pod
+DEPEND[man/man3/SSL_SESSION_get0_id_context.3]=man3/SSL_SESSION_get0_id_context.pod
+GENERATE[man/man3/SSL_SESSION_get0_id_context.3]=man3/SSL_SESSION_get0_id_context.pod
+DEPEND[html/man3/SSL_SESSION_get0_peer.html]=man3/SSL_SESSION_get0_peer.pod
+GENERATE[html/man3/SSL_SESSION_get0_peer.html]=man3/SSL_SESSION_get0_peer.pod
+DEPEND[man/man3/SSL_SESSION_get0_peer.3]=man3/SSL_SESSION_get0_peer.pod
+GENERATE[man/man3/SSL_SESSION_get0_peer.3]=man3/SSL_SESSION_get0_peer.pod
+DEPEND[html/man3/SSL_SESSION_get_compress_id.html]=man3/SSL_SESSION_get_compress_id.pod
+GENERATE[html/man3/SSL_SESSION_get_compress_id.html]=man3/SSL_SESSION_get_compress_id.pod
+DEPEND[man/man3/SSL_SESSION_get_compress_id.3]=man3/SSL_SESSION_get_compress_id.pod
+GENERATE[man/man3/SSL_SESSION_get_compress_id.3]=man3/SSL_SESSION_get_compress_id.pod
+DEPEND[html/man3/SSL_SESSION_get_protocol_version.html]=man3/SSL_SESSION_get_protocol_version.pod
+GENERATE[html/man3/SSL_SESSION_get_protocol_version.html]=man3/SSL_SESSION_get_protocol_version.pod
+DEPEND[man/man3/SSL_SESSION_get_protocol_version.3]=man3/SSL_SESSION_get_protocol_version.pod
+GENERATE[man/man3/SSL_SESSION_get_protocol_version.3]=man3/SSL_SESSION_get_protocol_version.pod
+DEPEND[html/man3/SSL_SESSION_get_time.html]=man3/SSL_SESSION_get_time.pod
+GENERATE[html/man3/SSL_SESSION_get_time.html]=man3/SSL_SESSION_get_time.pod
+DEPEND[man/man3/SSL_SESSION_get_time.3]=man3/SSL_SESSION_get_time.pod
+GENERATE[man/man3/SSL_SESSION_get_time.3]=man3/SSL_SESSION_get_time.pod
+DEPEND[html/man3/SSL_SESSION_has_ticket.html]=man3/SSL_SESSION_has_ticket.pod
+GENERATE[html/man3/SSL_SESSION_has_ticket.html]=man3/SSL_SESSION_has_ticket.pod
+DEPEND[man/man3/SSL_SESSION_has_ticket.3]=man3/SSL_SESSION_has_ticket.pod
+GENERATE[man/man3/SSL_SESSION_has_ticket.3]=man3/SSL_SESSION_has_ticket.pod
+DEPEND[html/man3/SSL_SESSION_is_resumable.html]=man3/SSL_SESSION_is_resumable.pod
+GENERATE[html/man3/SSL_SESSION_is_resumable.html]=man3/SSL_SESSION_is_resumable.pod
+DEPEND[man/man3/SSL_SESSION_is_resumable.3]=man3/SSL_SESSION_is_resumable.pod
+GENERATE[man/man3/SSL_SESSION_is_resumable.3]=man3/SSL_SESSION_is_resumable.pod
+DEPEND[html/man3/SSL_SESSION_print.html]=man3/SSL_SESSION_print.pod
+GENERATE[html/man3/SSL_SESSION_print.html]=man3/SSL_SESSION_print.pod
+DEPEND[man/man3/SSL_SESSION_print.3]=man3/SSL_SESSION_print.pod
+GENERATE[man/man3/SSL_SESSION_print.3]=man3/SSL_SESSION_print.pod
+DEPEND[html/man3/SSL_SESSION_set1_id.html]=man3/SSL_SESSION_set1_id.pod
+GENERATE[html/man3/SSL_SESSION_set1_id.html]=man3/SSL_SESSION_set1_id.pod
+DEPEND[man/man3/SSL_SESSION_set1_id.3]=man3/SSL_SESSION_set1_id.pod
+GENERATE[man/man3/SSL_SESSION_set1_id.3]=man3/SSL_SESSION_set1_id.pod
+DEPEND[html/man3/SSL_accept.html]=man3/SSL_accept.pod
+GENERATE[html/man3/SSL_accept.html]=man3/SSL_accept.pod
+DEPEND[man/man3/SSL_accept.3]=man3/SSL_accept.pod
+GENERATE[man/man3/SSL_accept.3]=man3/SSL_accept.pod
+DEPEND[html/man3/SSL_alert_type_string.html]=man3/SSL_alert_type_string.pod
+GENERATE[html/man3/SSL_alert_type_string.html]=man3/SSL_alert_type_string.pod
+DEPEND[man/man3/SSL_alert_type_string.3]=man3/SSL_alert_type_string.pod
+GENERATE[man/man3/SSL_alert_type_string.3]=man3/SSL_alert_type_string.pod
+DEPEND[html/man3/SSL_alloc_buffers.html]=man3/SSL_alloc_buffers.pod
+GENERATE[html/man3/SSL_alloc_buffers.html]=man3/SSL_alloc_buffers.pod
+DEPEND[man/man3/SSL_alloc_buffers.3]=man3/SSL_alloc_buffers.pod
+GENERATE[man/man3/SSL_alloc_buffers.3]=man3/SSL_alloc_buffers.pod
+DEPEND[html/man3/SSL_check_chain.html]=man3/SSL_check_chain.pod
+GENERATE[html/man3/SSL_check_chain.html]=man3/SSL_check_chain.pod
+DEPEND[man/man3/SSL_check_chain.3]=man3/SSL_check_chain.pod
+GENERATE[man/man3/SSL_check_chain.3]=man3/SSL_check_chain.pod
+DEPEND[html/man3/SSL_clear.html]=man3/SSL_clear.pod
+GENERATE[html/man3/SSL_clear.html]=man3/SSL_clear.pod
+DEPEND[man/man3/SSL_clear.3]=man3/SSL_clear.pod
+GENERATE[man/man3/SSL_clear.3]=man3/SSL_clear.pod
+DEPEND[html/man3/SSL_connect.html]=man3/SSL_connect.pod
+GENERATE[html/man3/SSL_connect.html]=man3/SSL_connect.pod
+DEPEND[man/man3/SSL_connect.3]=man3/SSL_connect.pod
+GENERATE[man/man3/SSL_connect.3]=man3/SSL_connect.pod
+DEPEND[html/man3/SSL_do_handshake.html]=man3/SSL_do_handshake.pod
+GENERATE[html/man3/SSL_do_handshake.html]=man3/SSL_do_handshake.pod
+DEPEND[man/man3/SSL_do_handshake.3]=man3/SSL_do_handshake.pod
+GENERATE[man/man3/SSL_do_handshake.3]=man3/SSL_do_handshake.pod
+DEPEND[html/man3/SSL_export_keying_material.html]=man3/SSL_export_keying_material.pod
+GENERATE[html/man3/SSL_export_keying_material.html]=man3/SSL_export_keying_material.pod
+DEPEND[man/man3/SSL_export_keying_material.3]=man3/SSL_export_keying_material.pod
+GENERATE[man/man3/SSL_export_keying_material.3]=man3/SSL_export_keying_material.pod
+DEPEND[html/man3/SSL_extension_supported.html]=man3/SSL_extension_supported.pod
+GENERATE[html/man3/SSL_extension_supported.html]=man3/SSL_extension_supported.pod
+DEPEND[man/man3/SSL_extension_supported.3]=man3/SSL_extension_supported.pod
+GENERATE[man/man3/SSL_extension_supported.3]=man3/SSL_extension_supported.pod
+DEPEND[html/man3/SSL_free.html]=man3/SSL_free.pod
+GENERATE[html/man3/SSL_free.html]=man3/SSL_free.pod
+DEPEND[man/man3/SSL_free.3]=man3/SSL_free.pod
+GENERATE[man/man3/SSL_free.3]=man3/SSL_free.pod
+DEPEND[html/man3/SSL_get0_peer_scts.html]=man3/SSL_get0_peer_scts.pod
+GENERATE[html/man3/SSL_get0_peer_scts.html]=man3/SSL_get0_peer_scts.pod
+DEPEND[man/man3/SSL_get0_peer_scts.3]=man3/SSL_get0_peer_scts.pod
+GENERATE[man/man3/SSL_get0_peer_scts.3]=man3/SSL_get0_peer_scts.pod
+DEPEND[html/man3/SSL_get_SSL_CTX.html]=man3/SSL_get_SSL_CTX.pod
+GENERATE[html/man3/SSL_get_SSL_CTX.html]=man3/SSL_get_SSL_CTX.pod
+DEPEND[man/man3/SSL_get_SSL_CTX.3]=man3/SSL_get_SSL_CTX.pod
+GENERATE[man/man3/SSL_get_SSL_CTX.3]=man3/SSL_get_SSL_CTX.pod
+DEPEND[html/man3/SSL_get_all_async_fds.html]=man3/SSL_get_all_async_fds.pod
+GENERATE[html/man3/SSL_get_all_async_fds.html]=man3/SSL_get_all_async_fds.pod
+DEPEND[man/man3/SSL_get_all_async_fds.3]=man3/SSL_get_all_async_fds.pod
+GENERATE[man/man3/SSL_get_all_async_fds.3]=man3/SSL_get_all_async_fds.pod
+DEPEND[html/man3/SSL_get_certificate.html]=man3/SSL_get_certificate.pod
+GENERATE[html/man3/SSL_get_certificate.html]=man3/SSL_get_certificate.pod
+DEPEND[man/man3/SSL_get_certificate.3]=man3/SSL_get_certificate.pod
+GENERATE[man/man3/SSL_get_certificate.3]=man3/SSL_get_certificate.pod
+DEPEND[html/man3/SSL_get_ciphers.html]=man3/SSL_get_ciphers.pod
+GENERATE[html/man3/SSL_get_ciphers.html]=man3/SSL_get_ciphers.pod
+DEPEND[man/man3/SSL_get_ciphers.3]=man3/SSL_get_ciphers.pod
+GENERATE[man/man3/SSL_get_ciphers.3]=man3/SSL_get_ciphers.pod
+DEPEND[html/man3/SSL_get_client_random.html]=man3/SSL_get_client_random.pod
+GENERATE[html/man3/SSL_get_client_random.html]=man3/SSL_get_client_random.pod
+DEPEND[man/man3/SSL_get_client_random.3]=man3/SSL_get_client_random.pod
+GENERATE[man/man3/SSL_get_client_random.3]=man3/SSL_get_client_random.pod
+DEPEND[html/man3/SSL_get_current_cipher.html]=man3/SSL_get_current_cipher.pod
+GENERATE[html/man3/SSL_get_current_cipher.html]=man3/SSL_get_current_cipher.pod
+DEPEND[man/man3/SSL_get_current_cipher.3]=man3/SSL_get_current_cipher.pod
+GENERATE[man/man3/SSL_get_current_cipher.3]=man3/SSL_get_current_cipher.pod
+DEPEND[html/man3/SSL_get_default_timeout.html]=man3/SSL_get_default_timeout.pod
+GENERATE[html/man3/SSL_get_default_timeout.html]=man3/SSL_get_default_timeout.pod
+DEPEND[man/man3/SSL_get_default_timeout.3]=man3/SSL_get_default_timeout.pod
+GENERATE[man/man3/SSL_get_default_timeout.3]=man3/SSL_get_default_timeout.pod
+DEPEND[html/man3/SSL_get_error.html]=man3/SSL_get_error.pod
+GENERATE[html/man3/SSL_get_error.html]=man3/SSL_get_error.pod
+DEPEND[man/man3/SSL_get_error.3]=man3/SSL_get_error.pod
+GENERATE[man/man3/SSL_get_error.3]=man3/SSL_get_error.pod
+DEPEND[html/man3/SSL_get_extms_support.html]=man3/SSL_get_extms_support.pod
+GENERATE[html/man3/SSL_get_extms_support.html]=man3/SSL_get_extms_support.pod
+DEPEND[man/man3/SSL_get_extms_support.3]=man3/SSL_get_extms_support.pod
+GENERATE[man/man3/SSL_get_extms_support.3]=man3/SSL_get_extms_support.pod
+DEPEND[html/man3/SSL_get_fd.html]=man3/SSL_get_fd.pod
+GENERATE[html/man3/SSL_get_fd.html]=man3/SSL_get_fd.pod
+DEPEND[man/man3/SSL_get_fd.3]=man3/SSL_get_fd.pod
+GENERATE[man/man3/SSL_get_fd.3]=man3/SSL_get_fd.pod
+DEPEND[html/man3/SSL_get_peer_cert_chain.html]=man3/SSL_get_peer_cert_chain.pod
+GENERATE[html/man3/SSL_get_peer_cert_chain.html]=man3/SSL_get_peer_cert_chain.pod
+DEPEND[man/man3/SSL_get_peer_cert_chain.3]=man3/SSL_get_peer_cert_chain.pod
+GENERATE[man/man3/SSL_get_peer_cert_chain.3]=man3/SSL_get_peer_cert_chain.pod
+DEPEND[html/man3/SSL_get_peer_certificate.html]=man3/SSL_get_peer_certificate.pod
+GENERATE[html/man3/SSL_get_peer_certificate.html]=man3/SSL_get_peer_certificate.pod
+DEPEND[man/man3/SSL_get_peer_certificate.3]=man3/SSL_get_peer_certificate.pod
+GENERATE[man/man3/SSL_get_peer_certificate.3]=man3/SSL_get_peer_certificate.pod
+DEPEND[html/man3/SSL_get_peer_signature_nid.html]=man3/SSL_get_peer_signature_nid.pod
+GENERATE[html/man3/SSL_get_peer_signature_nid.html]=man3/SSL_get_peer_signature_nid.pod
+DEPEND[man/man3/SSL_get_peer_signature_nid.3]=man3/SSL_get_peer_signature_nid.pod
+GENERATE[man/man3/SSL_get_peer_signature_nid.3]=man3/SSL_get_peer_signature_nid.pod
+DEPEND[html/man3/SSL_get_peer_tmp_key.html]=man3/SSL_get_peer_tmp_key.pod
+GENERATE[html/man3/SSL_get_peer_tmp_key.html]=man3/SSL_get_peer_tmp_key.pod
+DEPEND[man/man3/SSL_get_peer_tmp_key.3]=man3/SSL_get_peer_tmp_key.pod
+GENERATE[man/man3/SSL_get_peer_tmp_key.3]=man3/SSL_get_peer_tmp_key.pod
+DEPEND[html/man3/SSL_get_psk_identity.html]=man3/SSL_get_psk_identity.pod
+GENERATE[html/man3/SSL_get_psk_identity.html]=man3/SSL_get_psk_identity.pod
+DEPEND[man/man3/SSL_get_psk_identity.3]=man3/SSL_get_psk_identity.pod
+GENERATE[man/man3/SSL_get_psk_identity.3]=man3/SSL_get_psk_identity.pod
+DEPEND[html/man3/SSL_get_rbio.html]=man3/SSL_get_rbio.pod
+GENERATE[html/man3/SSL_get_rbio.html]=man3/SSL_get_rbio.pod
+DEPEND[man/man3/SSL_get_rbio.3]=man3/SSL_get_rbio.pod
+GENERATE[man/man3/SSL_get_rbio.3]=man3/SSL_get_rbio.pod
+DEPEND[html/man3/SSL_get_session.html]=man3/SSL_get_session.pod
+GENERATE[html/man3/SSL_get_session.html]=man3/SSL_get_session.pod
+DEPEND[man/man3/SSL_get_session.3]=man3/SSL_get_session.pod
+GENERATE[man/man3/SSL_get_session.3]=man3/SSL_get_session.pod
+DEPEND[html/man3/SSL_get_shared_sigalgs.html]=man3/SSL_get_shared_sigalgs.pod
+GENERATE[html/man3/SSL_get_shared_sigalgs.html]=man3/SSL_get_shared_sigalgs.pod
+DEPEND[man/man3/SSL_get_shared_sigalgs.3]=man3/SSL_get_shared_sigalgs.pod
+GENERATE[man/man3/SSL_get_shared_sigalgs.3]=man3/SSL_get_shared_sigalgs.pod
+DEPEND[html/man3/SSL_get_verify_result.html]=man3/SSL_get_verify_result.pod
+GENERATE[html/man3/SSL_get_verify_result.html]=man3/SSL_get_verify_result.pod
+DEPEND[man/man3/SSL_get_verify_result.3]=man3/SSL_get_verify_result.pod
+GENERATE[man/man3/SSL_get_verify_result.3]=man3/SSL_get_verify_result.pod
+DEPEND[html/man3/SSL_get_version.html]=man3/SSL_get_version.pod
+GENERATE[html/man3/SSL_get_version.html]=man3/SSL_get_version.pod
+DEPEND[man/man3/SSL_get_version.3]=man3/SSL_get_version.pod
+GENERATE[man/man3/SSL_get_version.3]=man3/SSL_get_version.pod
+DEPEND[html/man3/SSL_group_to_name.html]=man3/SSL_group_to_name.pod
+GENERATE[html/man3/SSL_group_to_name.html]=man3/SSL_group_to_name.pod
+DEPEND[man/man3/SSL_group_to_name.3]=man3/SSL_group_to_name.pod
+GENERATE[man/man3/SSL_group_to_name.3]=man3/SSL_group_to_name.pod
+DEPEND[html/man3/SSL_in_init.html]=man3/SSL_in_init.pod
+GENERATE[html/man3/SSL_in_init.html]=man3/SSL_in_init.pod
+DEPEND[man/man3/SSL_in_init.3]=man3/SSL_in_init.pod
+GENERATE[man/man3/SSL_in_init.3]=man3/SSL_in_init.pod
+DEPEND[html/man3/SSL_key_update.html]=man3/SSL_key_update.pod
+GENERATE[html/man3/SSL_key_update.html]=man3/SSL_key_update.pod
+DEPEND[man/man3/SSL_key_update.3]=man3/SSL_key_update.pod
+GENERATE[man/man3/SSL_key_update.3]=man3/SSL_key_update.pod
+DEPEND[html/man3/SSL_library_init.html]=man3/SSL_library_init.pod
+GENERATE[html/man3/SSL_library_init.html]=man3/SSL_library_init.pod
+DEPEND[man/man3/SSL_library_init.3]=man3/SSL_library_init.pod
+GENERATE[man/man3/SSL_library_init.3]=man3/SSL_library_init.pod
+DEPEND[html/man3/SSL_load_client_CA_file.html]=man3/SSL_load_client_CA_file.pod
+GENERATE[html/man3/SSL_load_client_CA_file.html]=man3/SSL_load_client_CA_file.pod
+DEPEND[man/man3/SSL_load_client_CA_file.3]=man3/SSL_load_client_CA_file.pod
+GENERATE[man/man3/SSL_load_client_CA_file.3]=man3/SSL_load_client_CA_file.pod
+DEPEND[html/man3/SSL_new.html]=man3/SSL_new.pod
+GENERATE[html/man3/SSL_new.html]=man3/SSL_new.pod
+DEPEND[man/man3/SSL_new.3]=man3/SSL_new.pod
+GENERATE[man/man3/SSL_new.3]=man3/SSL_new.pod
+DEPEND[html/man3/SSL_pending.html]=man3/SSL_pending.pod
+GENERATE[html/man3/SSL_pending.html]=man3/SSL_pending.pod
+DEPEND[man/man3/SSL_pending.3]=man3/SSL_pending.pod
+GENERATE[man/man3/SSL_pending.3]=man3/SSL_pending.pod
+DEPEND[html/man3/SSL_read.html]=man3/SSL_read.pod
+GENERATE[html/man3/SSL_read.html]=man3/SSL_read.pod
+DEPEND[man/man3/SSL_read.3]=man3/SSL_read.pod
+GENERATE[man/man3/SSL_read.3]=man3/SSL_read.pod
+DEPEND[html/man3/SSL_read_early_data.html]=man3/SSL_read_early_data.pod
+GENERATE[html/man3/SSL_read_early_data.html]=man3/SSL_read_early_data.pod
+DEPEND[man/man3/SSL_read_early_data.3]=man3/SSL_read_early_data.pod
+GENERATE[man/man3/SSL_read_early_data.3]=man3/SSL_read_early_data.pod
+DEPEND[html/man3/SSL_rstate_string.html]=man3/SSL_rstate_string.pod
+GENERATE[html/man3/SSL_rstate_string.html]=man3/SSL_rstate_string.pod
+DEPEND[man/man3/SSL_rstate_string.3]=man3/SSL_rstate_string.pod
+GENERATE[man/man3/SSL_rstate_string.3]=man3/SSL_rstate_string.pod
+DEPEND[html/man3/SSL_session_reused.html]=man3/SSL_session_reused.pod
+GENERATE[html/man3/SSL_session_reused.html]=man3/SSL_session_reused.pod
+DEPEND[man/man3/SSL_session_reused.3]=man3/SSL_session_reused.pod
+GENERATE[man/man3/SSL_session_reused.3]=man3/SSL_session_reused.pod
+DEPEND[html/man3/SSL_set1_host.html]=man3/SSL_set1_host.pod
+GENERATE[html/man3/SSL_set1_host.html]=man3/SSL_set1_host.pod
+DEPEND[man/man3/SSL_set1_host.3]=man3/SSL_set1_host.pod
+GENERATE[man/man3/SSL_set1_host.3]=man3/SSL_set1_host.pod
+DEPEND[html/man3/SSL_set_async_callback.html]=man3/SSL_set_async_callback.pod
+GENERATE[html/man3/SSL_set_async_callback.html]=man3/SSL_set_async_callback.pod
+DEPEND[man/man3/SSL_set_async_callback.3]=man3/SSL_set_async_callback.pod
+GENERATE[man/man3/SSL_set_async_callback.3]=man3/SSL_set_async_callback.pod
+DEPEND[html/man3/SSL_set_bio.html]=man3/SSL_set_bio.pod
+GENERATE[html/man3/SSL_set_bio.html]=man3/SSL_set_bio.pod
+DEPEND[man/man3/SSL_set_bio.3]=man3/SSL_set_bio.pod
+GENERATE[man/man3/SSL_set_bio.3]=man3/SSL_set_bio.pod
+DEPEND[html/man3/SSL_set_connect_state.html]=man3/SSL_set_connect_state.pod
+GENERATE[html/man3/SSL_set_connect_state.html]=man3/SSL_set_connect_state.pod
+DEPEND[man/man3/SSL_set_connect_state.3]=man3/SSL_set_connect_state.pod
+GENERATE[man/man3/SSL_set_connect_state.3]=man3/SSL_set_connect_state.pod
+DEPEND[html/man3/SSL_set_fd.html]=man3/SSL_set_fd.pod
+GENERATE[html/man3/SSL_set_fd.html]=man3/SSL_set_fd.pod
+DEPEND[man/man3/SSL_set_fd.3]=man3/SSL_set_fd.pod
+GENERATE[man/man3/SSL_set_fd.3]=man3/SSL_set_fd.pod
+DEPEND[html/man3/SSL_set_retry_verify.html]=man3/SSL_set_retry_verify.pod
+GENERATE[html/man3/SSL_set_retry_verify.html]=man3/SSL_set_retry_verify.pod
+DEPEND[man/man3/SSL_set_retry_verify.3]=man3/SSL_set_retry_verify.pod
+GENERATE[man/man3/SSL_set_retry_verify.3]=man3/SSL_set_retry_verify.pod
+DEPEND[html/man3/SSL_set_session.html]=man3/SSL_set_session.pod
+GENERATE[html/man3/SSL_set_session.html]=man3/SSL_set_session.pod
+DEPEND[man/man3/SSL_set_session.3]=man3/SSL_set_session.pod
+GENERATE[man/man3/SSL_set_session.3]=man3/SSL_set_session.pod
+DEPEND[html/man3/SSL_set_shutdown.html]=man3/SSL_set_shutdown.pod
+GENERATE[html/man3/SSL_set_shutdown.html]=man3/SSL_set_shutdown.pod
+DEPEND[man/man3/SSL_set_shutdown.3]=man3/SSL_set_shutdown.pod
+GENERATE[man/man3/SSL_set_shutdown.3]=man3/SSL_set_shutdown.pod
+DEPEND[html/man3/SSL_set_verify_result.html]=man3/SSL_set_verify_result.pod
+GENERATE[html/man3/SSL_set_verify_result.html]=man3/SSL_set_verify_result.pod
+DEPEND[man/man3/SSL_set_verify_result.3]=man3/SSL_set_verify_result.pod
+GENERATE[man/man3/SSL_set_verify_result.3]=man3/SSL_set_verify_result.pod
+DEPEND[html/man3/SSL_shutdown.html]=man3/SSL_shutdown.pod
+GENERATE[html/man3/SSL_shutdown.html]=man3/SSL_shutdown.pod
+DEPEND[man/man3/SSL_shutdown.3]=man3/SSL_shutdown.pod
+GENERATE[man/man3/SSL_shutdown.3]=man3/SSL_shutdown.pod
+DEPEND[html/man3/SSL_state_string.html]=man3/SSL_state_string.pod
+GENERATE[html/man3/SSL_state_string.html]=man3/SSL_state_string.pod
+DEPEND[man/man3/SSL_state_string.3]=man3/SSL_state_string.pod
+GENERATE[man/man3/SSL_state_string.3]=man3/SSL_state_string.pod
+DEPEND[html/man3/SSL_want.html]=man3/SSL_want.pod
+GENERATE[html/man3/SSL_want.html]=man3/SSL_want.pod
+DEPEND[man/man3/SSL_want.3]=man3/SSL_want.pod
+GENERATE[man/man3/SSL_want.3]=man3/SSL_want.pod
+DEPEND[html/man3/SSL_write.html]=man3/SSL_write.pod
+GENERATE[html/man3/SSL_write.html]=man3/SSL_write.pod
+DEPEND[man/man3/SSL_write.3]=man3/SSL_write.pod
+GENERATE[man/man3/SSL_write.3]=man3/SSL_write.pod
+DEPEND[html/man3/TS_RESP_CTX_new.html]=man3/TS_RESP_CTX_new.pod
+GENERATE[html/man3/TS_RESP_CTX_new.html]=man3/TS_RESP_CTX_new.pod
+DEPEND[man/man3/TS_RESP_CTX_new.3]=man3/TS_RESP_CTX_new.pod
+GENERATE[man/man3/TS_RESP_CTX_new.3]=man3/TS_RESP_CTX_new.pod
+DEPEND[html/man3/TS_VERIFY_CTX_set_certs.html]=man3/TS_VERIFY_CTX_set_certs.pod
+GENERATE[html/man3/TS_VERIFY_CTX_set_certs.html]=man3/TS_VERIFY_CTX_set_certs.pod
+DEPEND[man/man3/TS_VERIFY_CTX_set_certs.3]=man3/TS_VERIFY_CTX_set_certs.pod
+GENERATE[man/man3/TS_VERIFY_CTX_set_certs.3]=man3/TS_VERIFY_CTX_set_certs.pod
+DEPEND[html/man3/UI_STRING.html]=man3/UI_STRING.pod
+GENERATE[html/man3/UI_STRING.html]=man3/UI_STRING.pod
+DEPEND[man/man3/UI_STRING.3]=man3/UI_STRING.pod
+GENERATE[man/man3/UI_STRING.3]=man3/UI_STRING.pod
+DEPEND[html/man3/UI_UTIL_read_pw.html]=man3/UI_UTIL_read_pw.pod
+GENERATE[html/man3/UI_UTIL_read_pw.html]=man3/UI_UTIL_read_pw.pod
+DEPEND[man/man3/UI_UTIL_read_pw.3]=man3/UI_UTIL_read_pw.pod
+GENERATE[man/man3/UI_UTIL_read_pw.3]=man3/UI_UTIL_read_pw.pod
+DEPEND[html/man3/UI_create_method.html]=man3/UI_create_method.pod
+GENERATE[html/man3/UI_create_method.html]=man3/UI_create_method.pod
+DEPEND[man/man3/UI_create_method.3]=man3/UI_create_method.pod
+GENERATE[man/man3/UI_create_method.3]=man3/UI_create_method.pod
+DEPEND[html/man3/UI_new.html]=man3/UI_new.pod
+GENERATE[html/man3/UI_new.html]=man3/UI_new.pod
+DEPEND[man/man3/UI_new.3]=man3/UI_new.pod
+GENERATE[man/man3/UI_new.3]=man3/UI_new.pod
+DEPEND[html/man3/X509V3_get_d2i.html]=man3/X509V3_get_d2i.pod
+GENERATE[html/man3/X509V3_get_d2i.html]=man3/X509V3_get_d2i.pod
+DEPEND[man/man3/X509V3_get_d2i.3]=man3/X509V3_get_d2i.pod
+GENERATE[man/man3/X509V3_get_d2i.3]=man3/X509V3_get_d2i.pod
+DEPEND[html/man3/X509V3_set_ctx.html]=man3/X509V3_set_ctx.pod
+GENERATE[html/man3/X509V3_set_ctx.html]=man3/X509V3_set_ctx.pod
+DEPEND[man/man3/X509V3_set_ctx.3]=man3/X509V3_set_ctx.pod
+GENERATE[man/man3/X509V3_set_ctx.3]=man3/X509V3_set_ctx.pod
+DEPEND[html/man3/X509_ALGOR_dup.html]=man3/X509_ALGOR_dup.pod
+GENERATE[html/man3/X509_ALGOR_dup.html]=man3/X509_ALGOR_dup.pod
+DEPEND[man/man3/X509_ALGOR_dup.3]=man3/X509_ALGOR_dup.pod
+GENERATE[man/man3/X509_ALGOR_dup.3]=man3/X509_ALGOR_dup.pod
+DEPEND[html/man3/X509_CRL_get0_by_serial.html]=man3/X509_CRL_get0_by_serial.pod
+GENERATE[html/man3/X509_CRL_get0_by_serial.html]=man3/X509_CRL_get0_by_serial.pod
+DEPEND[man/man3/X509_CRL_get0_by_serial.3]=man3/X509_CRL_get0_by_serial.pod
+GENERATE[man/man3/X509_CRL_get0_by_serial.3]=man3/X509_CRL_get0_by_serial.pod
+DEPEND[html/man3/X509_EXTENSION_set_object.html]=man3/X509_EXTENSION_set_object.pod
+GENERATE[html/man3/X509_EXTENSION_set_object.html]=man3/X509_EXTENSION_set_object.pod
+DEPEND[man/man3/X509_EXTENSION_set_object.3]=man3/X509_EXTENSION_set_object.pod
+GENERATE[man/man3/X509_EXTENSION_set_object.3]=man3/X509_EXTENSION_set_object.pod
+DEPEND[html/man3/X509_LOOKUP.html]=man3/X509_LOOKUP.pod
+GENERATE[html/man3/X509_LOOKUP.html]=man3/X509_LOOKUP.pod
+DEPEND[man/man3/X509_LOOKUP.3]=man3/X509_LOOKUP.pod
+GENERATE[man/man3/X509_LOOKUP.3]=man3/X509_LOOKUP.pod
+DEPEND[html/man3/X509_LOOKUP_hash_dir.html]=man3/X509_LOOKUP_hash_dir.pod
+GENERATE[html/man3/X509_LOOKUP_hash_dir.html]=man3/X509_LOOKUP_hash_dir.pod
+DEPEND[man/man3/X509_LOOKUP_hash_dir.3]=man3/X509_LOOKUP_hash_dir.pod
+GENERATE[man/man3/X509_LOOKUP_hash_dir.3]=man3/X509_LOOKUP_hash_dir.pod
+DEPEND[html/man3/X509_LOOKUP_meth_new.html]=man3/X509_LOOKUP_meth_new.pod
+GENERATE[html/man3/X509_LOOKUP_meth_new.html]=man3/X509_LOOKUP_meth_new.pod
+DEPEND[man/man3/X509_LOOKUP_meth_new.3]=man3/X509_LOOKUP_meth_new.pod
+GENERATE[man/man3/X509_LOOKUP_meth_new.3]=man3/X509_LOOKUP_meth_new.pod
+DEPEND[html/man3/X509_NAME_ENTRY_get_object.html]=man3/X509_NAME_ENTRY_get_object.pod
+GENERATE[html/man3/X509_NAME_ENTRY_get_object.html]=man3/X509_NAME_ENTRY_get_object.pod
+DEPEND[man/man3/X509_NAME_ENTRY_get_object.3]=man3/X509_NAME_ENTRY_get_object.pod
+GENERATE[man/man3/X509_NAME_ENTRY_get_object.3]=man3/X509_NAME_ENTRY_get_object.pod
+DEPEND[html/man3/X509_NAME_add_entry_by_txt.html]=man3/X509_NAME_add_entry_by_txt.pod
+GENERATE[html/man3/X509_NAME_add_entry_by_txt.html]=man3/X509_NAME_add_entry_by_txt.pod
+DEPEND[man/man3/X509_NAME_add_entry_by_txt.3]=man3/X509_NAME_add_entry_by_txt.pod
+GENERATE[man/man3/X509_NAME_add_entry_by_txt.3]=man3/X509_NAME_add_entry_by_txt.pod
+DEPEND[html/man3/X509_NAME_get0_der.html]=man3/X509_NAME_get0_der.pod
+GENERATE[html/man3/X509_NAME_get0_der.html]=man3/X509_NAME_get0_der.pod
+DEPEND[man/man3/X509_NAME_get0_der.3]=man3/X509_NAME_get0_der.pod
+GENERATE[man/man3/X509_NAME_get0_der.3]=man3/X509_NAME_get0_der.pod
+DEPEND[html/man3/X509_NAME_get_index_by_NID.html]=man3/X509_NAME_get_index_by_NID.pod
+GENERATE[html/man3/X509_NAME_get_index_by_NID.html]=man3/X509_NAME_get_index_by_NID.pod
+DEPEND[man/man3/X509_NAME_get_index_by_NID.3]=man3/X509_NAME_get_index_by_NID.pod
+GENERATE[man/man3/X509_NAME_get_index_by_NID.3]=man3/X509_NAME_get_index_by_NID.pod
+DEPEND[html/man3/X509_NAME_print_ex.html]=man3/X509_NAME_print_ex.pod
+GENERATE[html/man3/X509_NAME_print_ex.html]=man3/X509_NAME_print_ex.pod
+DEPEND[man/man3/X509_NAME_print_ex.3]=man3/X509_NAME_print_ex.pod
+GENERATE[man/man3/X509_NAME_print_ex.3]=man3/X509_NAME_print_ex.pod
+DEPEND[html/man3/X509_PUBKEY_new.html]=man3/X509_PUBKEY_new.pod
+GENERATE[html/man3/X509_PUBKEY_new.html]=man3/X509_PUBKEY_new.pod
+DEPEND[man/man3/X509_PUBKEY_new.3]=man3/X509_PUBKEY_new.pod
+GENERATE[man/man3/X509_PUBKEY_new.3]=man3/X509_PUBKEY_new.pod
+DEPEND[html/man3/X509_SIG_get0.html]=man3/X509_SIG_get0.pod
+GENERATE[html/man3/X509_SIG_get0.html]=man3/X509_SIG_get0.pod
+DEPEND[man/man3/X509_SIG_get0.3]=man3/X509_SIG_get0.pod
+GENERATE[man/man3/X509_SIG_get0.3]=man3/X509_SIG_get0.pod
+DEPEND[html/man3/X509_STORE_CTX_get_error.html]=man3/X509_STORE_CTX_get_error.pod
+GENERATE[html/man3/X509_STORE_CTX_get_error.html]=man3/X509_STORE_CTX_get_error.pod
+DEPEND[man/man3/X509_STORE_CTX_get_error.3]=man3/X509_STORE_CTX_get_error.pod
+GENERATE[man/man3/X509_STORE_CTX_get_error.3]=man3/X509_STORE_CTX_get_error.pod
+DEPEND[html/man3/X509_STORE_CTX_new.html]=man3/X509_STORE_CTX_new.pod
+GENERATE[html/man3/X509_STORE_CTX_new.html]=man3/X509_STORE_CTX_new.pod
+DEPEND[man/man3/X509_STORE_CTX_new.3]=man3/X509_STORE_CTX_new.pod
+GENERATE[man/man3/X509_STORE_CTX_new.3]=man3/X509_STORE_CTX_new.pod
+DEPEND[html/man3/X509_STORE_CTX_set_verify_cb.html]=man3/X509_STORE_CTX_set_verify_cb.pod
+GENERATE[html/man3/X509_STORE_CTX_set_verify_cb.html]=man3/X509_STORE_CTX_set_verify_cb.pod
+DEPEND[man/man3/X509_STORE_CTX_set_verify_cb.3]=man3/X509_STORE_CTX_set_verify_cb.pod
+GENERATE[man/man3/X509_STORE_CTX_set_verify_cb.3]=man3/X509_STORE_CTX_set_verify_cb.pod
+DEPEND[html/man3/X509_STORE_add_cert.html]=man3/X509_STORE_add_cert.pod
+GENERATE[html/man3/X509_STORE_add_cert.html]=man3/X509_STORE_add_cert.pod
+DEPEND[man/man3/X509_STORE_add_cert.3]=man3/X509_STORE_add_cert.pod
+GENERATE[man/man3/X509_STORE_add_cert.3]=man3/X509_STORE_add_cert.pod
+DEPEND[html/man3/X509_STORE_get0_param.html]=man3/X509_STORE_get0_param.pod
+GENERATE[html/man3/X509_STORE_get0_param.html]=man3/X509_STORE_get0_param.pod
+DEPEND[man/man3/X509_STORE_get0_param.3]=man3/X509_STORE_get0_param.pod
+GENERATE[man/man3/X509_STORE_get0_param.3]=man3/X509_STORE_get0_param.pod
+DEPEND[html/man3/X509_STORE_new.html]=man3/X509_STORE_new.pod
+GENERATE[html/man3/X509_STORE_new.html]=man3/X509_STORE_new.pod
+DEPEND[man/man3/X509_STORE_new.3]=man3/X509_STORE_new.pod
+GENERATE[man/man3/X509_STORE_new.3]=man3/X509_STORE_new.pod
+DEPEND[html/man3/X509_STORE_set_verify_cb_func.html]=man3/X509_STORE_set_verify_cb_func.pod
+GENERATE[html/man3/X509_STORE_set_verify_cb_func.html]=man3/X509_STORE_set_verify_cb_func.pod
+DEPEND[man/man3/X509_STORE_set_verify_cb_func.3]=man3/X509_STORE_set_verify_cb_func.pod
+GENERATE[man/man3/X509_STORE_set_verify_cb_func.3]=man3/X509_STORE_set_verify_cb_func.pod
+DEPEND[html/man3/X509_VERIFY_PARAM_set_flags.html]=man3/X509_VERIFY_PARAM_set_flags.pod
+GENERATE[html/man3/X509_VERIFY_PARAM_set_flags.html]=man3/X509_VERIFY_PARAM_set_flags.pod
+DEPEND[man/man3/X509_VERIFY_PARAM_set_flags.3]=man3/X509_VERIFY_PARAM_set_flags.pod
+GENERATE[man/man3/X509_VERIFY_PARAM_set_flags.3]=man3/X509_VERIFY_PARAM_set_flags.pod
+DEPEND[html/man3/X509_add_cert.html]=man3/X509_add_cert.pod
+GENERATE[html/man3/X509_add_cert.html]=man3/X509_add_cert.pod
+DEPEND[man/man3/X509_add_cert.3]=man3/X509_add_cert.pod
+GENERATE[man/man3/X509_add_cert.3]=man3/X509_add_cert.pod
+DEPEND[html/man3/X509_check_ca.html]=man3/X509_check_ca.pod
+GENERATE[html/man3/X509_check_ca.html]=man3/X509_check_ca.pod
+DEPEND[man/man3/X509_check_ca.3]=man3/X509_check_ca.pod
+GENERATE[man/man3/X509_check_ca.3]=man3/X509_check_ca.pod
+DEPEND[html/man3/X509_check_host.html]=man3/X509_check_host.pod
+GENERATE[html/man3/X509_check_host.html]=man3/X509_check_host.pod
+DEPEND[man/man3/X509_check_host.3]=man3/X509_check_host.pod
+GENERATE[man/man3/X509_check_host.3]=man3/X509_check_host.pod
+DEPEND[html/man3/X509_check_issued.html]=man3/X509_check_issued.pod
+GENERATE[html/man3/X509_check_issued.html]=man3/X509_check_issued.pod
+DEPEND[man/man3/X509_check_issued.3]=man3/X509_check_issued.pod
+GENERATE[man/man3/X509_check_issued.3]=man3/X509_check_issued.pod
+DEPEND[html/man3/X509_check_private_key.html]=man3/X509_check_private_key.pod
+GENERATE[html/man3/X509_check_private_key.html]=man3/X509_check_private_key.pod
+DEPEND[man/man3/X509_check_private_key.3]=man3/X509_check_private_key.pod
+GENERATE[man/man3/X509_check_private_key.3]=man3/X509_check_private_key.pod
+DEPEND[html/man3/X509_check_purpose.html]=man3/X509_check_purpose.pod
+GENERATE[html/man3/X509_check_purpose.html]=man3/X509_check_purpose.pod
+DEPEND[man/man3/X509_check_purpose.3]=man3/X509_check_purpose.pod
+GENERATE[man/man3/X509_check_purpose.3]=man3/X509_check_purpose.pod
+DEPEND[html/man3/X509_cmp.html]=man3/X509_cmp.pod
+GENERATE[html/man3/X509_cmp.html]=man3/X509_cmp.pod
+DEPEND[man/man3/X509_cmp.3]=man3/X509_cmp.pod
+GENERATE[man/man3/X509_cmp.3]=man3/X509_cmp.pod
+DEPEND[html/man3/X509_cmp_time.html]=man3/X509_cmp_time.pod
+GENERATE[html/man3/X509_cmp_time.html]=man3/X509_cmp_time.pod
+DEPEND[man/man3/X509_cmp_time.3]=man3/X509_cmp_time.pod
+GENERATE[man/man3/X509_cmp_time.3]=man3/X509_cmp_time.pod
+DEPEND[html/man3/X509_digest.html]=man3/X509_digest.pod
+GENERATE[html/man3/X509_digest.html]=man3/X509_digest.pod
+DEPEND[man/man3/X509_digest.3]=man3/X509_digest.pod
+GENERATE[man/man3/X509_digest.3]=man3/X509_digest.pod
+DEPEND[html/man3/X509_dup.html]=man3/X509_dup.pod
+GENERATE[html/man3/X509_dup.html]=man3/X509_dup.pod
+DEPEND[man/man3/X509_dup.3]=man3/X509_dup.pod
+GENERATE[man/man3/X509_dup.3]=man3/X509_dup.pod
+DEPEND[html/man3/X509_get0_distinguishing_id.html]=man3/X509_get0_distinguishing_id.pod
+GENERATE[html/man3/X509_get0_distinguishing_id.html]=man3/X509_get0_distinguishing_id.pod
+DEPEND[man/man3/X509_get0_distinguishing_id.3]=man3/X509_get0_distinguishing_id.pod
+GENERATE[man/man3/X509_get0_distinguishing_id.3]=man3/X509_get0_distinguishing_id.pod
+DEPEND[html/man3/X509_get0_notBefore.html]=man3/X509_get0_notBefore.pod
+GENERATE[html/man3/X509_get0_notBefore.html]=man3/X509_get0_notBefore.pod
+DEPEND[man/man3/X509_get0_notBefore.3]=man3/X509_get0_notBefore.pod
+GENERATE[man/man3/X509_get0_notBefore.3]=man3/X509_get0_notBefore.pod
+DEPEND[html/man3/X509_get0_signature.html]=man3/X509_get0_signature.pod
+GENERATE[html/man3/X509_get0_signature.html]=man3/X509_get0_signature.pod
+DEPEND[man/man3/X509_get0_signature.3]=man3/X509_get0_signature.pod
+GENERATE[man/man3/X509_get0_signature.3]=man3/X509_get0_signature.pod
+DEPEND[html/man3/X509_get0_uids.html]=man3/X509_get0_uids.pod
+GENERATE[html/man3/X509_get0_uids.html]=man3/X509_get0_uids.pod
+DEPEND[man/man3/X509_get0_uids.3]=man3/X509_get0_uids.pod
+GENERATE[man/man3/X509_get0_uids.3]=man3/X509_get0_uids.pod
+DEPEND[html/man3/X509_get_extension_flags.html]=man3/X509_get_extension_flags.pod
+GENERATE[html/man3/X509_get_extension_flags.html]=man3/X509_get_extension_flags.pod
+DEPEND[man/man3/X509_get_extension_flags.3]=man3/X509_get_extension_flags.pod
+GENERATE[man/man3/X509_get_extension_flags.3]=man3/X509_get_extension_flags.pod
+DEPEND[html/man3/X509_get_pubkey.html]=man3/X509_get_pubkey.pod
+GENERATE[html/man3/X509_get_pubkey.html]=man3/X509_get_pubkey.pod
+DEPEND[man/man3/X509_get_pubkey.3]=man3/X509_get_pubkey.pod
+GENERATE[man/man3/X509_get_pubkey.3]=man3/X509_get_pubkey.pod
+DEPEND[html/man3/X509_get_serialNumber.html]=man3/X509_get_serialNumber.pod
+GENERATE[html/man3/X509_get_serialNumber.html]=man3/X509_get_serialNumber.pod
+DEPEND[man/man3/X509_get_serialNumber.3]=man3/X509_get_serialNumber.pod
+GENERATE[man/man3/X509_get_serialNumber.3]=man3/X509_get_serialNumber.pod
+DEPEND[html/man3/X509_get_subject_name.html]=man3/X509_get_subject_name.pod
+GENERATE[html/man3/X509_get_subject_name.html]=man3/X509_get_subject_name.pod
+DEPEND[man/man3/X509_get_subject_name.3]=man3/X509_get_subject_name.pod
+GENERATE[man/man3/X509_get_subject_name.3]=man3/X509_get_subject_name.pod
+DEPEND[html/man3/X509_get_version.html]=man3/X509_get_version.pod
+GENERATE[html/man3/X509_get_version.html]=man3/X509_get_version.pod
+DEPEND[man/man3/X509_get_version.3]=man3/X509_get_version.pod
+GENERATE[man/man3/X509_get_version.3]=man3/X509_get_version.pod
+DEPEND[html/man3/X509_load_http.html]=man3/X509_load_http.pod
+GENERATE[html/man3/X509_load_http.html]=man3/X509_load_http.pod
+DEPEND[man/man3/X509_load_http.3]=man3/X509_load_http.pod
+GENERATE[man/man3/X509_load_http.3]=man3/X509_load_http.pod
+DEPEND[html/man3/X509_new.html]=man3/X509_new.pod
+GENERATE[html/man3/X509_new.html]=man3/X509_new.pod
+DEPEND[man/man3/X509_new.3]=man3/X509_new.pod
+GENERATE[man/man3/X509_new.3]=man3/X509_new.pod
+DEPEND[html/man3/X509_sign.html]=man3/X509_sign.pod
+GENERATE[html/man3/X509_sign.html]=man3/X509_sign.pod
+DEPEND[man/man3/X509_sign.3]=man3/X509_sign.pod
+GENERATE[man/man3/X509_sign.3]=man3/X509_sign.pod
+DEPEND[html/man3/X509_verify.html]=man3/X509_verify.pod
+GENERATE[html/man3/X509_verify.html]=man3/X509_verify.pod
+DEPEND[man/man3/X509_verify.3]=man3/X509_verify.pod
+GENERATE[man/man3/X509_verify.3]=man3/X509_verify.pod
+DEPEND[html/man3/X509_verify_cert.html]=man3/X509_verify_cert.pod
+GENERATE[html/man3/X509_verify_cert.html]=man3/X509_verify_cert.pod
+DEPEND[man/man3/X509_verify_cert.3]=man3/X509_verify_cert.pod
+GENERATE[man/man3/X509_verify_cert.3]=man3/X509_verify_cert.pod
+DEPEND[html/man3/X509v3_get_ext_by_NID.html]=man3/X509v3_get_ext_by_NID.pod
+GENERATE[html/man3/X509v3_get_ext_by_NID.html]=man3/X509v3_get_ext_by_NID.pod
+DEPEND[man/man3/X509v3_get_ext_by_NID.3]=man3/X509v3_get_ext_by_NID.pod
+GENERATE[man/man3/X509v3_get_ext_by_NID.3]=man3/X509v3_get_ext_by_NID.pod
+DEPEND[html/man3/b2i_PVK_bio_ex.html]=man3/b2i_PVK_bio_ex.pod
+GENERATE[html/man3/b2i_PVK_bio_ex.html]=man3/b2i_PVK_bio_ex.pod
+DEPEND[man/man3/b2i_PVK_bio_ex.3]=man3/b2i_PVK_bio_ex.pod
+GENERATE[man/man3/b2i_PVK_bio_ex.3]=man3/b2i_PVK_bio_ex.pod
+DEPEND[html/man3/d2i_PKCS8PrivateKey_bio.html]=man3/d2i_PKCS8PrivateKey_bio.pod
+GENERATE[html/man3/d2i_PKCS8PrivateKey_bio.html]=man3/d2i_PKCS8PrivateKey_bio.pod
+DEPEND[man/man3/d2i_PKCS8PrivateKey_bio.3]=man3/d2i_PKCS8PrivateKey_bio.pod
+GENERATE[man/man3/d2i_PKCS8PrivateKey_bio.3]=man3/d2i_PKCS8PrivateKey_bio.pod
+DEPEND[html/man3/d2i_PrivateKey.html]=man3/d2i_PrivateKey.pod
+GENERATE[html/man3/d2i_PrivateKey.html]=man3/d2i_PrivateKey.pod
+DEPEND[man/man3/d2i_PrivateKey.3]=man3/d2i_PrivateKey.pod
+GENERATE[man/man3/d2i_PrivateKey.3]=man3/d2i_PrivateKey.pod
+DEPEND[html/man3/d2i_RSAPrivateKey.html]=man3/d2i_RSAPrivateKey.pod
+GENERATE[html/man3/d2i_RSAPrivateKey.html]=man3/d2i_RSAPrivateKey.pod
+DEPEND[man/man3/d2i_RSAPrivateKey.3]=man3/d2i_RSAPrivateKey.pod
+GENERATE[man/man3/d2i_RSAPrivateKey.3]=man3/d2i_RSAPrivateKey.pod
+DEPEND[html/man3/d2i_SSL_SESSION.html]=man3/d2i_SSL_SESSION.pod
+GENERATE[html/man3/d2i_SSL_SESSION.html]=man3/d2i_SSL_SESSION.pod
+DEPEND[man/man3/d2i_SSL_SESSION.3]=man3/d2i_SSL_SESSION.pod
+GENERATE[man/man3/d2i_SSL_SESSION.3]=man3/d2i_SSL_SESSION.pod
+DEPEND[html/man3/d2i_X509.html]=man3/d2i_X509.pod
+GENERATE[html/man3/d2i_X509.html]=man3/d2i_X509.pod
+DEPEND[man/man3/d2i_X509.3]=man3/d2i_X509.pod
+GENERATE[man/man3/d2i_X509.3]=man3/d2i_X509.pod
+DEPEND[html/man3/i2d_CMS_bio_stream.html]=man3/i2d_CMS_bio_stream.pod
+GENERATE[html/man3/i2d_CMS_bio_stream.html]=man3/i2d_CMS_bio_stream.pod
+DEPEND[man/man3/i2d_CMS_bio_stream.3]=man3/i2d_CMS_bio_stream.pod
+GENERATE[man/man3/i2d_CMS_bio_stream.3]=man3/i2d_CMS_bio_stream.pod
+DEPEND[html/man3/i2d_PKCS7_bio_stream.html]=man3/i2d_PKCS7_bio_stream.pod
+GENERATE[html/man3/i2d_PKCS7_bio_stream.html]=man3/i2d_PKCS7_bio_stream.pod
+DEPEND[man/man3/i2d_PKCS7_bio_stream.3]=man3/i2d_PKCS7_bio_stream.pod
+GENERATE[man/man3/i2d_PKCS7_bio_stream.3]=man3/i2d_PKCS7_bio_stream.pod
+DEPEND[html/man3/i2d_re_X509_tbs.html]=man3/i2d_re_X509_tbs.pod
+GENERATE[html/man3/i2d_re_X509_tbs.html]=man3/i2d_re_X509_tbs.pod
+DEPEND[man/man3/i2d_re_X509_tbs.3]=man3/i2d_re_X509_tbs.pod
+GENERATE[man/man3/i2d_re_X509_tbs.3]=man3/i2d_re_X509_tbs.pod
+DEPEND[html/man3/o2i_SCT_LIST.html]=man3/o2i_SCT_LIST.pod
+GENERATE[html/man3/o2i_SCT_LIST.html]=man3/o2i_SCT_LIST.pod
+DEPEND[man/man3/o2i_SCT_LIST.3]=man3/o2i_SCT_LIST.pod
+GENERATE[man/man3/o2i_SCT_LIST.3]=man3/o2i_SCT_LIST.pod
+DEPEND[html/man3/s2i_ASN1_IA5STRING.html]=man3/s2i_ASN1_IA5STRING.pod
+GENERATE[html/man3/s2i_ASN1_IA5STRING.html]=man3/s2i_ASN1_IA5STRING.pod
+DEPEND[man/man3/s2i_ASN1_IA5STRING.3]=man3/s2i_ASN1_IA5STRING.pod
+GENERATE[man/man3/s2i_ASN1_IA5STRING.3]=man3/s2i_ASN1_IA5STRING.pod
+IMAGEDOCS[man3]=
+HTMLDOCS[man3]=html/man3/ADMISSIONS.html \
+html/man3/ASN1_EXTERN_FUNCS.html \
+html/man3/ASN1_INTEGER_get_int64.html \
+html/man3/ASN1_INTEGER_new.html \
+html/man3/ASN1_ITEM_lookup.html \
+html/man3/ASN1_OBJECT_new.html \
+html/man3/ASN1_STRING_TABLE_add.html \
+html/man3/ASN1_STRING_length.html \
+html/man3/ASN1_STRING_new.html \
+html/man3/ASN1_STRING_print_ex.html \
+html/man3/ASN1_TIME_set.html \
+html/man3/ASN1_TYPE_get.html \
+html/man3/ASN1_aux_cb.html \
+html/man3/ASN1_generate_nconf.html \
+html/man3/ASN1_item_d2i_bio.html \
+html/man3/ASN1_item_new.html \
+html/man3/ASN1_item_sign.html \
+html/man3/ASYNC_WAIT_CTX_new.html \
+html/man3/ASYNC_start_job.html \
+html/man3/BF_encrypt.html \
+html/man3/BIO_ADDR.html \
+html/man3/BIO_ADDRINFO.html \
+html/man3/BIO_connect.html \
+html/man3/BIO_ctrl.html \
+html/man3/BIO_f_base64.html \
+html/man3/BIO_f_buffer.html \
+html/man3/BIO_f_cipher.html \
+html/man3/BIO_f_md.html \
+html/man3/BIO_f_null.html \
+html/man3/BIO_f_prefix.html \
+html/man3/BIO_f_readbuffer.html \
+html/man3/BIO_f_ssl.html \
+html/man3/BIO_find_type.html \
+html/man3/BIO_get_data.html \
+html/man3/BIO_get_ex_new_index.html \
+html/man3/BIO_meth_new.html \
+html/man3/BIO_new.html \
+html/man3/BIO_new_CMS.html \
+html/man3/BIO_parse_hostserv.html \
+html/man3/BIO_printf.html \
+html/man3/BIO_push.html \
+html/man3/BIO_read.html \
+html/man3/BIO_s_accept.html \
+html/man3/BIO_s_bio.html \
+html/man3/BIO_s_connect.html \
+html/man3/BIO_s_core.html \
+html/man3/BIO_s_datagram.html \
+html/man3/BIO_s_fd.html \
+html/man3/BIO_s_file.html \
+html/man3/BIO_s_mem.html \
+html/man3/BIO_s_null.html \
+html/man3/BIO_s_socket.html \
+html/man3/BIO_set_callback.html \
+html/man3/BIO_should_retry.html \
+html/man3/BIO_socket_wait.html \
+html/man3/BN_BLINDING_new.html \
+html/man3/BN_CTX_new.html \
+html/man3/BN_CTX_start.html \
+html/man3/BN_add.html \
+html/man3/BN_add_word.html \
+html/man3/BN_bn2bin.html \
+html/man3/BN_cmp.html \
+html/man3/BN_copy.html \
+html/man3/BN_generate_prime.html \
+html/man3/BN_mod_exp_mont.html \
+html/man3/BN_mod_inverse.html \
+html/man3/BN_mod_mul_montgomery.html \
+html/man3/BN_mod_mul_reciprocal.html \
+html/man3/BN_new.html \
+html/man3/BN_num_bytes.html \
+html/man3/BN_rand.html \
+html/man3/BN_security_bits.html \
+html/man3/BN_set_bit.html \
+html/man3/BN_swap.html \
+html/man3/BN_zero.html \
+html/man3/BUF_MEM_new.html \
+html/man3/CMS_EncryptedData_decrypt.html \
+html/man3/CMS_EncryptedData_encrypt.html \
+html/man3/CMS_EnvelopedData_create.html \
+html/man3/CMS_add0_cert.html \
+html/man3/CMS_add1_recipient_cert.html \
+html/man3/CMS_add1_signer.html \
+html/man3/CMS_compress.html \
+html/man3/CMS_data_create.html \
+html/man3/CMS_decrypt.html \
+html/man3/CMS_digest_create.html \
+html/man3/CMS_encrypt.html \
+html/man3/CMS_final.html \
+html/man3/CMS_get0_RecipientInfos.html \
+html/man3/CMS_get0_SignerInfos.html \
+html/man3/CMS_get0_type.html \
+html/man3/CMS_get1_ReceiptRequest.html \
+html/man3/CMS_sign.html \
+html/man3/CMS_sign_receipt.html \
+html/man3/CMS_uncompress.html \
+html/man3/CMS_verify.html \
+html/man3/CMS_verify_receipt.html \
+html/man3/CONF_modules_free.html \
+html/man3/CONF_modules_load_file.html \
+html/man3/CRYPTO_THREAD_run_once.html \
+html/man3/CRYPTO_get_ex_new_index.html \
+html/man3/CRYPTO_memcmp.html \
+html/man3/CTLOG_STORE_get0_log_by_id.html \
+html/man3/CTLOG_STORE_new.html \
+html/man3/CTLOG_new.html \
+html/man3/CT_POLICY_EVAL_CTX_new.html \
+html/man3/DEFINE_STACK_OF.html \
+html/man3/DES_random_key.html \
+html/man3/DH_generate_key.html \
+html/man3/DH_generate_parameters.html \
+html/man3/DH_get0_pqg.html \
+html/man3/DH_get_1024_160.html \
+html/man3/DH_meth_new.html \
+html/man3/DH_new.html \
+html/man3/DH_new_by_nid.html \
+html/man3/DH_set_method.html \
+html/man3/DH_size.html \
+html/man3/DSA_SIG_new.html \
+html/man3/DSA_do_sign.html \
+html/man3/DSA_dup_DH.html \
+html/man3/DSA_generate_key.html \
+html/man3/DSA_generate_parameters.html \
+html/man3/DSA_get0_pqg.html \
+html/man3/DSA_meth_new.html \
+html/man3/DSA_new.html \
+html/man3/DSA_set_method.html \
+html/man3/DSA_sign.html \
+html/man3/DSA_size.html \
+html/man3/DTLS_get_data_mtu.html \
+html/man3/DTLS_set_timer_cb.html \
+html/man3/DTLSv1_listen.html \
+html/man3/ECDSA_SIG_new.html \
+html/man3/ECDSA_sign.html \
+html/man3/ECPKParameters_print.html \
+html/man3/EC_GFp_simple_method.html \
+html/man3/EC_GROUP_copy.html \
+html/man3/EC_GROUP_new.html \
+html/man3/EC_KEY_get_enc_flags.html \
+html/man3/EC_KEY_new.html \
+html/man3/EC_POINT_add.html \
+html/man3/EC_POINT_new.html \
+html/man3/ENGINE_add.html \
+html/man3/ERR_GET_LIB.html \
+html/man3/ERR_clear_error.html \
+html/man3/ERR_error_string.html \
+html/man3/ERR_get_error.html \
+html/man3/ERR_load_crypto_strings.html \
+html/man3/ERR_load_strings.html \
+html/man3/ERR_new.html \
+html/man3/ERR_print_errors.html \
+html/man3/ERR_put_error.html \
+html/man3/ERR_remove_state.html \
+html/man3/ERR_set_mark.html \
+html/man3/EVP_ASYM_CIPHER_free.html \
+html/man3/EVP_BytesToKey.html \
+html/man3/EVP_CIPHER_CTX_get_cipher_data.html \
+html/man3/EVP_CIPHER_CTX_get_original_iv.html \
+html/man3/EVP_CIPHER_meth_new.html \
+html/man3/EVP_DigestInit.html \
+html/man3/EVP_DigestSignInit.html \
+html/man3/EVP_DigestVerifyInit.html \
+html/man3/EVP_EncodeInit.html \
+html/man3/EVP_EncryptInit.html \
+html/man3/EVP_KDF.html \
+html/man3/EVP_KEM_free.html \
+html/man3/EVP_KEYEXCH_free.html \
+html/man3/EVP_KEYMGMT.html \
+html/man3/EVP_MAC.html \
+html/man3/EVP_MD_meth_new.html \
+html/man3/EVP_OpenInit.html \
+html/man3/EVP_PBE_CipherInit.html \
+html/man3/EVP_PKEY2PKCS8.html \
+html/man3/EVP_PKEY_ASN1_METHOD.html \
+html/man3/EVP_PKEY_CTX_ctrl.html \
+html/man3/EVP_PKEY_CTX_get0_libctx.html \
+html/man3/EVP_PKEY_CTX_get0_pkey.html \
+html/man3/EVP_PKEY_CTX_new.html \
+html/man3/EVP_PKEY_CTX_set1_pbe_pass.html \
+html/man3/EVP_PKEY_CTX_set_hkdf_md.html \
+html/man3/EVP_PKEY_CTX_set_params.html \
+html/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.html \
+html/man3/EVP_PKEY_CTX_set_scrypt_N.html \
+html/man3/EVP_PKEY_CTX_set_tls1_prf_md.html \
+html/man3/EVP_PKEY_asn1_get_count.html \
+html/man3/EVP_PKEY_check.html \
+html/man3/EVP_PKEY_copy_parameters.html \
+html/man3/EVP_PKEY_decapsulate.html \
+html/man3/EVP_PKEY_decrypt.html \
+html/man3/EVP_PKEY_derive.html \
+html/man3/EVP_PKEY_digestsign_supports_digest.html \
+html/man3/EVP_PKEY_encapsulate.html \
+html/man3/EVP_PKEY_encrypt.html \
+html/man3/EVP_PKEY_fromdata.html \
+html/man3/EVP_PKEY_get_default_digest_nid.html \
+html/man3/EVP_PKEY_get_field_type.html \
+html/man3/EVP_PKEY_get_group_name.html \
+html/man3/EVP_PKEY_get_size.html \
+html/man3/EVP_PKEY_gettable_params.html \
+html/man3/EVP_PKEY_is_a.html \
+html/man3/EVP_PKEY_keygen.html \
+html/man3/EVP_PKEY_meth_get_count.html \
+html/man3/EVP_PKEY_meth_new.html \
+html/man3/EVP_PKEY_new.html \
+html/man3/EVP_PKEY_print_private.html \
+html/man3/EVP_PKEY_set1_RSA.html \
+html/man3/EVP_PKEY_set1_encoded_public_key.html \
+html/man3/EVP_PKEY_set_type.html \
+html/man3/EVP_PKEY_settable_params.html \
+html/man3/EVP_PKEY_sign.html \
+html/man3/EVP_PKEY_todata.html \
+html/man3/EVP_PKEY_verify.html \
+html/man3/EVP_PKEY_verify_recover.html \
+html/man3/EVP_RAND.html \
+html/man3/EVP_SIGNATURE.html \
+html/man3/EVP_SealInit.html \
+html/man3/EVP_SignInit.html \
+html/man3/EVP_VerifyInit.html \
+html/man3/EVP_aes_128_gcm.html \
+html/man3/EVP_aria_128_gcm.html \
+html/man3/EVP_bf_cbc.html \
+html/man3/EVP_blake2b512.html \
+html/man3/EVP_camellia_128_ecb.html \
+html/man3/EVP_cast5_cbc.html \
+html/man3/EVP_chacha20.html \
+html/man3/EVP_des_cbc.html \
+html/man3/EVP_desx_cbc.html \
+html/man3/EVP_idea_cbc.html \
+html/man3/EVP_md2.html \
+html/man3/EVP_md4.html \
+html/man3/EVP_md5.html \
+html/man3/EVP_mdc2.html \
+html/man3/EVP_rc2_cbc.html \
+html/man3/EVP_rc4.html \
+html/man3/EVP_rc5_32_12_16_cbc.html \
+html/man3/EVP_ripemd160.html \
+html/man3/EVP_seed_cbc.html \
+html/man3/EVP_set_default_properties.html \
+html/man3/EVP_sha1.html \
+html/man3/EVP_sha224.html \
+html/man3/EVP_sha3_224.html \
+html/man3/EVP_sm3.html \
+html/man3/EVP_sm4_cbc.html \
+html/man3/EVP_whirlpool.html \
+html/man3/HMAC.html \
+html/man3/MD5.html \
+html/man3/MDC2_Init.html \
+html/man3/NCONF_new_ex.html \
+html/man3/OBJ_nid2obj.html \
+html/man3/OCSP_REQUEST_new.html \
+html/man3/OCSP_cert_to_id.html \
+html/man3/OCSP_request_add1_nonce.html \
+html/man3/OCSP_resp_find_status.html \
+html/man3/OCSP_response_status.html \
+html/man3/OCSP_sendreq_new.html \
+html/man3/OPENSSL_Applink.html \
+html/man3/OPENSSL_FILE.html \
+html/man3/OPENSSL_LH_COMPFUNC.html \
+html/man3/OPENSSL_LH_stats.html \
+html/man3/OPENSSL_config.html \
+html/man3/OPENSSL_fork_prepare.html \
+html/man3/OPENSSL_gmtime.html \
+html/man3/OPENSSL_hexchar2int.html \
+html/man3/OPENSSL_ia32cap.html \
+html/man3/OPENSSL_init_crypto.html \
+html/man3/OPENSSL_init_ssl.html \
+html/man3/OPENSSL_instrument_bus.html \
+html/man3/OPENSSL_load_builtin_modules.html \
+html/man3/OPENSSL_malloc.html \
+html/man3/OPENSSL_s390xcap.html \
+html/man3/OPENSSL_secure_malloc.html \
+html/man3/OPENSSL_strcasecmp.html \
+html/man3/OSSL_ALGORITHM.html \
+html/man3/OSSL_CALLBACK.html \
+html/man3/OSSL_CMP_CTX_new.html \
+html/man3/OSSL_CMP_HDR_get0_transactionID.html \
+html/man3/OSSL_CMP_ITAV_set0.html \
+html/man3/OSSL_CMP_MSG_get0_header.html \
+html/man3/OSSL_CMP_MSG_http_perform.html \
+html/man3/OSSL_CMP_SRV_CTX_new.html \
+html/man3/OSSL_CMP_STATUSINFO_new.html \
+html/man3/OSSL_CMP_exec_certreq.html \
+html/man3/OSSL_CMP_log_open.html \
+html/man3/OSSL_CMP_validate_msg.html \
+html/man3/OSSL_CORE_MAKE_FUNC.html \
+html/man3/OSSL_CRMF_MSG_get0_tmpl.html \
+html/man3/OSSL_CRMF_MSG_set0_validity.html \
+html/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.html \
+html/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.html \
+html/man3/OSSL_CRMF_pbmp_new.html \
+html/man3/OSSL_DECODER.html \
+html/man3/OSSL_DECODER_CTX.html \
+html/man3/OSSL_DECODER_CTX_new_for_pkey.html \
+html/man3/OSSL_DECODER_from_bio.html \
+html/man3/OSSL_DISPATCH.html \
+html/man3/OSSL_ENCODER.html \
+html/man3/OSSL_ENCODER_CTX.html \
+html/man3/OSSL_ENCODER_CTX_new_for_pkey.html \
+html/man3/OSSL_ENCODER_to_bio.html \
+html/man3/OSSL_ESS_check_signing_certs.html \
+html/man3/OSSL_HTTP_REQ_CTX.html \
+html/man3/OSSL_HTTP_parse_url.html \
+html/man3/OSSL_HTTP_transfer.html \
+html/man3/OSSL_ITEM.html \
+html/man3/OSSL_LIB_CTX.html \
+html/man3/OSSL_PARAM.html \
+html/man3/OSSL_PARAM_BLD.html \
+html/man3/OSSL_PARAM_allocate_from_text.html \
+html/man3/OSSL_PARAM_dup.html \
+html/man3/OSSL_PARAM_int.html \
+html/man3/OSSL_PROVIDER.html \
+html/man3/OSSL_SELF_TEST_new.html \
+html/man3/OSSL_SELF_TEST_set_callback.html \
+html/man3/OSSL_STORE_INFO.html \
+html/man3/OSSL_STORE_LOADER.html \
+html/man3/OSSL_STORE_SEARCH.html \
+html/man3/OSSL_STORE_attach.html \
+html/man3/OSSL_STORE_expect.html \
+html/man3/OSSL_STORE_open.html \
+html/man3/OSSL_trace_enabled.html \
+html/man3/OSSL_trace_get_category_num.html \
+html/man3/OSSL_trace_set_channel.html \
+html/man3/OpenSSL_add_all_algorithms.html \
+html/man3/OpenSSL_version.html \
+html/man3/PEM_X509_INFO_read_bio_ex.html \
+html/man3/PEM_bytes_read_bio.html \
+html/man3/PEM_read.html \
+html/man3/PEM_read_CMS.html \
+html/man3/PEM_read_bio_PrivateKey.html \
+html/man3/PEM_read_bio_ex.html \
+html/man3/PEM_write_bio_CMS_stream.html \
+html/man3/PEM_write_bio_PKCS7_stream.html \
+html/man3/PKCS12_PBE_keyivgen.html \
+html/man3/PKCS12_SAFEBAG_create_cert.html \
+html/man3/PKCS12_SAFEBAG_get0_attrs.html \
+html/man3/PKCS12_SAFEBAG_get1_cert.html \
+html/man3/PKCS12_add1_attr_by_NID.html \
+html/man3/PKCS12_add_CSPName_asc.html \
+html/man3/PKCS12_add_cert.html \
+html/man3/PKCS12_add_friendlyname_asc.html \
+html/man3/PKCS12_add_localkeyid.html \
+html/man3/PKCS12_add_safe.html \
+html/man3/PKCS12_create.html \
+html/man3/PKCS12_decrypt_skey.html \
+html/man3/PKCS12_gen_mac.html \
+html/man3/PKCS12_get_friendlyname.html \
+html/man3/PKCS12_init.html \
+html/man3/PKCS12_item_decrypt_d2i.html \
+html/man3/PKCS12_key_gen_utf8_ex.html \
+html/man3/PKCS12_newpass.html \
+html/man3/PKCS12_pack_p7encdata.html \
+html/man3/PKCS12_parse.html \
+html/man3/PKCS5_PBE_keyivgen.html \
+html/man3/PKCS5_PBKDF2_HMAC.html \
+html/man3/PKCS7_decrypt.html \
+html/man3/PKCS7_encrypt.html \
+html/man3/PKCS7_get_octet_string.html \
+html/man3/PKCS7_sign.html \
+html/man3/PKCS7_sign_add_signer.html \
+html/man3/PKCS7_type_is_other.html \
+html/man3/PKCS7_verify.html \
+html/man3/PKCS8_encrypt.html \
+html/man3/PKCS8_pkey_add1_attr.html \
+html/man3/RAND_add.html \
+html/man3/RAND_bytes.html \
+html/man3/RAND_cleanup.html \
+html/man3/RAND_egd.html \
+html/man3/RAND_get0_primary.html \
+html/man3/RAND_load_file.html \
+html/man3/RAND_set_DRBG_type.html \
+html/man3/RAND_set_rand_method.html \
+html/man3/RC4_set_key.html \
+html/man3/RIPEMD160_Init.html \
+html/man3/RSA_blinding_on.html \
+html/man3/RSA_check_key.html \
+html/man3/RSA_generate_key.html \
+html/man3/RSA_get0_key.html \
+html/man3/RSA_meth_new.html \
+html/man3/RSA_new.html \
+html/man3/RSA_padding_add_PKCS1_type_1.html \
+html/man3/RSA_print.html \
+html/man3/RSA_private_encrypt.html \
+html/man3/RSA_public_encrypt.html \
+html/man3/RSA_set_method.html \
+html/man3/RSA_sign.html \
+html/man3/RSA_sign_ASN1_OCTET_STRING.html \
+html/man3/RSA_size.html \
+html/man3/SCT_new.html \
+html/man3/SCT_print.html \
+html/man3/SCT_validate.html \
+html/man3/SHA256_Init.html \
+html/man3/SMIME_read_ASN1.html \
+html/man3/SMIME_read_CMS.html \
+html/man3/SMIME_read_PKCS7.html \
+html/man3/SMIME_write_ASN1.html \
+html/man3/SMIME_write_CMS.html \
+html/man3/SMIME_write_PKCS7.html \
+html/man3/SRP_Calc_B.html \
+html/man3/SRP_VBASE_new.html \
+html/man3/SRP_create_verifier.html \
+html/man3/SRP_user_pwd_new.html \
+html/man3/SSL_CIPHER_get_name.html \
+html/man3/SSL_COMP_add_compression_method.html \
+html/man3/SSL_CONF_CTX_new.html \
+html/man3/SSL_CONF_CTX_set1_prefix.html \
+html/man3/SSL_CONF_CTX_set_flags.html \
+html/man3/SSL_CONF_CTX_set_ssl_ctx.html \
+html/man3/SSL_CONF_cmd.html \
+html/man3/SSL_CONF_cmd_argv.html \
+html/man3/SSL_CTX_add1_chain_cert.html \
+html/man3/SSL_CTX_add_extra_chain_cert.html \
+html/man3/SSL_CTX_add_session.html \
+html/man3/SSL_CTX_config.html \
+html/man3/SSL_CTX_ctrl.html \
+html/man3/SSL_CTX_dane_enable.html \
+html/man3/SSL_CTX_flush_sessions.html \
+html/man3/SSL_CTX_free.html \
+html/man3/SSL_CTX_get0_param.html \
+html/man3/SSL_CTX_get_verify_mode.html \
+html/man3/SSL_CTX_has_client_custom_ext.html \
+html/man3/SSL_CTX_load_verify_locations.html \
+html/man3/SSL_CTX_new.html \
+html/man3/SSL_CTX_sess_number.html \
+html/man3/SSL_CTX_sess_set_cache_size.html \
+html/man3/SSL_CTX_sess_set_get_cb.html \
+html/man3/SSL_CTX_sessions.html \
+html/man3/SSL_CTX_set0_CA_list.html \
+html/man3/SSL_CTX_set1_curves.html \
+html/man3/SSL_CTX_set1_sigalgs.html \
+html/man3/SSL_CTX_set1_verify_cert_store.html \
+html/man3/SSL_CTX_set_alpn_select_cb.html \
+html/man3/SSL_CTX_set_cert_cb.html \
+html/man3/SSL_CTX_set_cert_store.html \
+html/man3/SSL_CTX_set_cert_verify_callback.html \
+html/man3/SSL_CTX_set_cipher_list.html \
+html/man3/SSL_CTX_set_client_cert_cb.html \
+html/man3/SSL_CTX_set_client_hello_cb.html \
+html/man3/SSL_CTX_set_ct_validation_callback.html \
+html/man3/SSL_CTX_set_ctlog_list_file.html \
+html/man3/SSL_CTX_set_default_passwd_cb.html \
+html/man3/SSL_CTX_set_generate_session_id.html \
+html/man3/SSL_CTX_set_info_callback.html \
+html/man3/SSL_CTX_set_keylog_callback.html \
+html/man3/SSL_CTX_set_max_cert_list.html \
+html/man3/SSL_CTX_set_min_proto_version.html \
+html/man3/SSL_CTX_set_mode.html \
+html/man3/SSL_CTX_set_msg_callback.html \
+html/man3/SSL_CTX_set_num_tickets.html \
+html/man3/SSL_CTX_set_options.html \
+html/man3/SSL_CTX_set_psk_client_callback.html \
+html/man3/SSL_CTX_set_quiet_shutdown.html \
+html/man3/SSL_CTX_set_read_ahead.html \
+html/man3/SSL_CTX_set_record_padding_callback.html \
+html/man3/SSL_CTX_set_security_level.html \
+html/man3/SSL_CTX_set_session_cache_mode.html \
+html/man3/SSL_CTX_set_session_id_context.html \
+html/man3/SSL_CTX_set_session_ticket_cb.html \
+html/man3/SSL_CTX_set_split_send_fragment.html \
+html/man3/SSL_CTX_set_srp_password.html \
+html/man3/SSL_CTX_set_ssl_version.html \
+html/man3/SSL_CTX_set_stateless_cookie_generate_cb.html \
+html/man3/SSL_CTX_set_timeout.html \
+html/man3/SSL_CTX_set_tlsext_servername_callback.html \
+html/man3/SSL_CTX_set_tlsext_status_cb.html \
+html/man3/SSL_CTX_set_tlsext_ticket_key_cb.html \
+html/man3/SSL_CTX_set_tlsext_use_srtp.html \
+html/man3/SSL_CTX_set_tmp_dh_callback.html \
+html/man3/SSL_CTX_set_tmp_ecdh.html \
+html/man3/SSL_CTX_set_verify.html \
+html/man3/SSL_CTX_use_certificate.html \
+html/man3/SSL_CTX_use_psk_identity_hint.html \
+html/man3/SSL_CTX_use_serverinfo.html \
+html/man3/SSL_SESSION_free.html \
+html/man3/SSL_SESSION_get0_cipher.html \
+html/man3/SSL_SESSION_get0_hostname.html \
+html/man3/SSL_SESSION_get0_id_context.html \
+html/man3/SSL_SESSION_get0_peer.html \
+html/man3/SSL_SESSION_get_compress_id.html \
+html/man3/SSL_SESSION_get_protocol_version.html \
+html/man3/SSL_SESSION_get_time.html \
+html/man3/SSL_SESSION_has_ticket.html \
+html/man3/SSL_SESSION_is_resumable.html \
+html/man3/SSL_SESSION_print.html \
+html/man3/SSL_SESSION_set1_id.html \
+html/man3/SSL_accept.html \
+html/man3/SSL_alert_type_string.html \
+html/man3/SSL_alloc_buffers.html \
+html/man3/SSL_check_chain.html \
+html/man3/SSL_clear.html \
+html/man3/SSL_connect.html \
+html/man3/SSL_do_handshake.html \
+html/man3/SSL_export_keying_material.html \
+html/man3/SSL_extension_supported.html \
+html/man3/SSL_free.html \
+html/man3/SSL_get0_peer_scts.html \
+html/man3/SSL_get_SSL_CTX.html \
+html/man3/SSL_get_all_async_fds.html \
+html/man3/SSL_get_certificate.html \
+html/man3/SSL_get_ciphers.html \
+html/man3/SSL_get_client_random.html \
+html/man3/SSL_get_current_cipher.html \
+html/man3/SSL_get_default_timeout.html \
+html/man3/SSL_get_error.html \
+html/man3/SSL_get_extms_support.html \
+html/man3/SSL_get_fd.html \
+html/man3/SSL_get_peer_cert_chain.html \
+html/man3/SSL_get_peer_certificate.html \
+html/man3/SSL_get_peer_signature_nid.html \
+html/man3/SSL_get_peer_tmp_key.html \
+html/man3/SSL_get_psk_identity.html \
+html/man3/SSL_get_rbio.html \
+html/man3/SSL_get_session.html \
+html/man3/SSL_get_shared_sigalgs.html \
+html/man3/SSL_get_verify_result.html \
+html/man3/SSL_get_version.html \
+html/man3/SSL_group_to_name.html \
+html/man3/SSL_in_init.html \
+html/man3/SSL_key_update.html \
+html/man3/SSL_library_init.html \
+html/man3/SSL_load_client_CA_file.html \
+html/man3/SSL_new.html \
+html/man3/SSL_pending.html \
+html/man3/SSL_read.html \
+html/man3/SSL_read_early_data.html \
+html/man3/SSL_rstate_string.html \
+html/man3/SSL_session_reused.html \
+html/man3/SSL_set1_host.html \
+html/man3/SSL_set_async_callback.html \
+html/man3/SSL_set_bio.html \
+html/man3/SSL_set_connect_state.html \
+html/man3/SSL_set_fd.html \
+html/man3/SSL_set_retry_verify.html \
+html/man3/SSL_set_session.html \
+html/man3/SSL_set_shutdown.html \
+html/man3/SSL_set_verify_result.html \
+html/man3/SSL_shutdown.html \
+html/man3/SSL_state_string.html \
+html/man3/SSL_want.html \
+html/man3/SSL_write.html \
+html/man3/TS_RESP_CTX_new.html \
+html/man3/TS_VERIFY_CTX_set_certs.html \
+html/man3/UI_STRING.html \
+html/man3/UI_UTIL_read_pw.html \
+html/man3/UI_create_method.html \
+html/man3/UI_new.html \
+html/man3/X509V3_get_d2i.html \
+html/man3/X509V3_set_ctx.html \
+html/man3/X509_ALGOR_dup.html \
+html/man3/X509_CRL_get0_by_serial.html \
+html/man3/X509_EXTENSION_set_object.html \
+html/man3/X509_LOOKUP.html \
+html/man3/X509_LOOKUP_hash_dir.html \
+html/man3/X509_LOOKUP_meth_new.html \
+html/man3/X509_NAME_ENTRY_get_object.html \
+html/man3/X509_NAME_add_entry_by_txt.html \
+html/man3/X509_NAME_get0_der.html \
+html/man3/X509_NAME_get_index_by_NID.html \
+html/man3/X509_NAME_print_ex.html \
+html/man3/X509_PUBKEY_new.html \
+html/man3/X509_SIG_get0.html \
+html/man3/X509_STORE_CTX_get_error.html \
+html/man3/X509_STORE_CTX_new.html \
+html/man3/X509_STORE_CTX_set_verify_cb.html \
+html/man3/X509_STORE_add_cert.html \
+html/man3/X509_STORE_get0_param.html \
+html/man3/X509_STORE_new.html \
+html/man3/X509_STORE_set_verify_cb_func.html \
+html/man3/X509_VERIFY_PARAM_set_flags.html \
+html/man3/X509_add_cert.html \
+html/man3/X509_check_ca.html \
+html/man3/X509_check_host.html \
+html/man3/X509_check_issued.html \
+html/man3/X509_check_private_key.html \
+html/man3/X509_check_purpose.html \
+html/man3/X509_cmp.html \
+html/man3/X509_cmp_time.html \
+html/man3/X509_digest.html \
+html/man3/X509_dup.html \
+html/man3/X509_get0_distinguishing_id.html \
+html/man3/X509_get0_notBefore.html \
+html/man3/X509_get0_signature.html \
+html/man3/X509_get0_uids.html \
+html/man3/X509_get_extension_flags.html \
+html/man3/X509_get_pubkey.html \
+html/man3/X509_get_serialNumber.html \
+html/man3/X509_get_subject_name.html \
+html/man3/X509_get_version.html \
+html/man3/X509_load_http.html \
+html/man3/X509_new.html \
+html/man3/X509_sign.html \
+html/man3/X509_verify.html \
+html/man3/X509_verify_cert.html \
+html/man3/X509v3_get_ext_by_NID.html \
+html/man3/b2i_PVK_bio_ex.html \
+html/man3/d2i_PKCS8PrivateKey_bio.html \
+html/man3/d2i_PrivateKey.html \
+html/man3/d2i_RSAPrivateKey.html \
+html/man3/d2i_SSL_SESSION.html \
+html/man3/d2i_X509.html \
+html/man3/i2d_CMS_bio_stream.html \
+html/man3/i2d_PKCS7_bio_stream.html \
+html/man3/i2d_re_X509_tbs.html \
+html/man3/o2i_SCT_LIST.html \
+html/man3/s2i_ASN1_IA5STRING.html
+MANDOCS[man3]=man/man3/ADMISSIONS.3 \
+man/man3/ASN1_EXTERN_FUNCS.3 \
+man/man3/ASN1_INTEGER_get_int64.3 \
+man/man3/ASN1_INTEGER_new.3 \
+man/man3/ASN1_ITEM_lookup.3 \
+man/man3/ASN1_OBJECT_new.3 \
+man/man3/ASN1_STRING_TABLE_add.3 \
+man/man3/ASN1_STRING_length.3 \
+man/man3/ASN1_STRING_new.3 \
+man/man3/ASN1_STRING_print_ex.3 \
+man/man3/ASN1_TIME_set.3 \
+man/man3/ASN1_TYPE_get.3 \
+man/man3/ASN1_aux_cb.3 \
+man/man3/ASN1_generate_nconf.3 \
+man/man3/ASN1_item_d2i_bio.3 \
+man/man3/ASN1_item_new.3 \
+man/man3/ASN1_item_sign.3 \
+man/man3/ASYNC_WAIT_CTX_new.3 \
+man/man3/ASYNC_start_job.3 \
+man/man3/BF_encrypt.3 \
+man/man3/BIO_ADDR.3 \
+man/man3/BIO_ADDRINFO.3 \
+man/man3/BIO_connect.3 \
+man/man3/BIO_ctrl.3 \
+man/man3/BIO_f_base64.3 \
+man/man3/BIO_f_buffer.3 \
+man/man3/BIO_f_cipher.3 \
+man/man3/BIO_f_md.3 \
+man/man3/BIO_f_null.3 \
+man/man3/BIO_f_prefix.3 \
+man/man3/BIO_f_readbuffer.3 \
+man/man3/BIO_f_ssl.3 \
+man/man3/BIO_find_type.3 \
+man/man3/BIO_get_data.3 \
+man/man3/BIO_get_ex_new_index.3 \
+man/man3/BIO_meth_new.3 \
+man/man3/BIO_new.3 \
+man/man3/BIO_new_CMS.3 \
+man/man3/BIO_parse_hostserv.3 \
+man/man3/BIO_printf.3 \
+man/man3/BIO_push.3 \
+man/man3/BIO_read.3 \
+man/man3/BIO_s_accept.3 \
+man/man3/BIO_s_bio.3 \
+man/man3/BIO_s_connect.3 \
+man/man3/BIO_s_core.3 \
+man/man3/BIO_s_datagram.3 \
+man/man3/BIO_s_fd.3 \
+man/man3/BIO_s_file.3 \
+man/man3/BIO_s_mem.3 \
+man/man3/BIO_s_null.3 \
+man/man3/BIO_s_socket.3 \
+man/man3/BIO_set_callback.3 \
+man/man3/BIO_should_retry.3 \
+man/man3/BIO_socket_wait.3 \
+man/man3/BN_BLINDING_new.3 \
+man/man3/BN_CTX_new.3 \
+man/man3/BN_CTX_start.3 \
+man/man3/BN_add.3 \
+man/man3/BN_add_word.3 \
+man/man3/BN_bn2bin.3 \
+man/man3/BN_cmp.3 \
+man/man3/BN_copy.3 \
+man/man3/BN_generate_prime.3 \
+man/man3/BN_mod_exp_mont.3 \
+man/man3/BN_mod_inverse.3 \
+man/man3/BN_mod_mul_montgomery.3 \
+man/man3/BN_mod_mul_reciprocal.3 \
+man/man3/BN_new.3 \
+man/man3/BN_num_bytes.3 \
+man/man3/BN_rand.3 \
+man/man3/BN_security_bits.3 \
+man/man3/BN_set_bit.3 \
+man/man3/BN_swap.3 \
+man/man3/BN_zero.3 \
+man/man3/BUF_MEM_new.3 \
+man/man3/CMS_EncryptedData_decrypt.3 \
+man/man3/CMS_EncryptedData_encrypt.3 \
+man/man3/CMS_EnvelopedData_create.3 \
+man/man3/CMS_add0_cert.3 \
+man/man3/CMS_add1_recipient_cert.3 \
+man/man3/CMS_add1_signer.3 \
+man/man3/CMS_compress.3 \
+man/man3/CMS_data_create.3 \
+man/man3/CMS_decrypt.3 \
+man/man3/CMS_digest_create.3 \
+man/man3/CMS_encrypt.3 \
+man/man3/CMS_final.3 \
+man/man3/CMS_get0_RecipientInfos.3 \
+man/man3/CMS_get0_SignerInfos.3 \
+man/man3/CMS_get0_type.3 \
+man/man3/CMS_get1_ReceiptRequest.3 \
+man/man3/CMS_sign.3 \
+man/man3/CMS_sign_receipt.3 \
+man/man3/CMS_uncompress.3 \
+man/man3/CMS_verify.3 \
+man/man3/CMS_verify_receipt.3 \
+man/man3/CONF_modules_free.3 \
+man/man3/CONF_modules_load_file.3 \
+man/man3/CRYPTO_THREAD_run_once.3 \
+man/man3/CRYPTO_get_ex_new_index.3 \
+man/man3/CRYPTO_memcmp.3 \
+man/man3/CTLOG_STORE_get0_log_by_id.3 \
+man/man3/CTLOG_STORE_new.3 \
+man/man3/CTLOG_new.3 \
+man/man3/CT_POLICY_EVAL_CTX_new.3 \
+man/man3/DEFINE_STACK_OF.3 \
+man/man3/DES_random_key.3 \
+man/man3/DH_generate_key.3 \
+man/man3/DH_generate_parameters.3 \
+man/man3/DH_get0_pqg.3 \
+man/man3/DH_get_1024_160.3 \
+man/man3/DH_meth_new.3 \
+man/man3/DH_new.3 \
+man/man3/DH_new_by_nid.3 \
+man/man3/DH_set_method.3 \
+man/man3/DH_size.3 \
+man/man3/DSA_SIG_new.3 \
+man/man3/DSA_do_sign.3 \
+man/man3/DSA_dup_DH.3 \
+man/man3/DSA_generate_key.3 \
+man/man3/DSA_generate_parameters.3 \
+man/man3/DSA_get0_pqg.3 \
+man/man3/DSA_meth_new.3 \
+man/man3/DSA_new.3 \
+man/man3/DSA_set_method.3 \
+man/man3/DSA_sign.3 \
+man/man3/DSA_size.3 \
+man/man3/DTLS_get_data_mtu.3 \
+man/man3/DTLS_set_timer_cb.3 \
+man/man3/DTLSv1_listen.3 \
+man/man3/ECDSA_SIG_new.3 \
+man/man3/ECDSA_sign.3 \
+man/man3/ECPKParameters_print.3 \
+man/man3/EC_GFp_simple_method.3 \
+man/man3/EC_GROUP_copy.3 \
+man/man3/EC_GROUP_new.3 \
+man/man3/EC_KEY_get_enc_flags.3 \
+man/man3/EC_KEY_new.3 \
+man/man3/EC_POINT_add.3 \
+man/man3/EC_POINT_new.3 \
+man/man3/ENGINE_add.3 \
+man/man3/ERR_GET_LIB.3 \
+man/man3/ERR_clear_error.3 \
+man/man3/ERR_error_string.3 \
+man/man3/ERR_get_error.3 \
+man/man3/ERR_load_crypto_strings.3 \
+man/man3/ERR_load_strings.3 \
+man/man3/ERR_new.3 \
+man/man3/ERR_print_errors.3 \
+man/man3/ERR_put_error.3 \
+man/man3/ERR_remove_state.3 \
+man/man3/ERR_set_mark.3 \
+man/man3/EVP_ASYM_CIPHER_free.3 \
+man/man3/EVP_BytesToKey.3 \
+man/man3/EVP_CIPHER_CTX_get_cipher_data.3 \
+man/man3/EVP_CIPHER_CTX_get_original_iv.3 \
+man/man3/EVP_CIPHER_meth_new.3 \
+man/man3/EVP_DigestInit.3 \
+man/man3/EVP_DigestSignInit.3 \
+man/man3/EVP_DigestVerifyInit.3 \
+man/man3/EVP_EncodeInit.3 \
+man/man3/EVP_EncryptInit.3 \
+man/man3/EVP_KDF.3 \
+man/man3/EVP_KEM_free.3 \
+man/man3/EVP_KEYEXCH_free.3 \
+man/man3/EVP_KEYMGMT.3 \
+man/man3/EVP_MAC.3 \
+man/man3/EVP_MD_meth_new.3 \
+man/man3/EVP_OpenInit.3 \
+man/man3/EVP_PBE_CipherInit.3 \
+man/man3/EVP_PKEY2PKCS8.3 \
+man/man3/EVP_PKEY_ASN1_METHOD.3 \
+man/man3/EVP_PKEY_CTX_ctrl.3 \
+man/man3/EVP_PKEY_CTX_get0_libctx.3 \
+man/man3/EVP_PKEY_CTX_get0_pkey.3 \
+man/man3/EVP_PKEY_CTX_new.3 \
+man/man3/EVP_PKEY_CTX_set1_pbe_pass.3 \
+man/man3/EVP_PKEY_CTX_set_hkdf_md.3 \
+man/man3/EVP_PKEY_CTX_set_params.3 \
+man/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.3 \
+man/man3/EVP_PKEY_CTX_set_scrypt_N.3 \
+man/man3/EVP_PKEY_CTX_set_tls1_prf_md.3 \
+man/man3/EVP_PKEY_asn1_get_count.3 \
+man/man3/EVP_PKEY_check.3 \
+man/man3/EVP_PKEY_copy_parameters.3 \
+man/man3/EVP_PKEY_decapsulate.3 \
+man/man3/EVP_PKEY_decrypt.3 \
+man/man3/EVP_PKEY_derive.3 \
+man/man3/EVP_PKEY_digestsign_supports_digest.3 \
+man/man3/EVP_PKEY_encapsulate.3 \
+man/man3/EVP_PKEY_encrypt.3 \
+man/man3/EVP_PKEY_fromdata.3 \
+man/man3/EVP_PKEY_get_default_digest_nid.3 \
+man/man3/EVP_PKEY_get_field_type.3 \
+man/man3/EVP_PKEY_get_group_name.3 \
+man/man3/EVP_PKEY_get_size.3 \
+man/man3/EVP_PKEY_gettable_params.3 \
+man/man3/EVP_PKEY_is_a.3 \
+man/man3/EVP_PKEY_keygen.3 \
+man/man3/EVP_PKEY_meth_get_count.3 \
+man/man3/EVP_PKEY_meth_new.3 \
+man/man3/EVP_PKEY_new.3 \
+man/man3/EVP_PKEY_print_private.3 \
+man/man3/EVP_PKEY_set1_RSA.3 \
+man/man3/EVP_PKEY_set1_encoded_public_key.3 \
+man/man3/EVP_PKEY_set_type.3 \
+man/man3/EVP_PKEY_settable_params.3 \
+man/man3/EVP_PKEY_sign.3 \
+man/man3/EVP_PKEY_todata.3 \
+man/man3/EVP_PKEY_verify.3 \
+man/man3/EVP_PKEY_verify_recover.3 \
+man/man3/EVP_RAND.3 \
+man/man3/EVP_SIGNATURE.3 \
+man/man3/EVP_SealInit.3 \
+man/man3/EVP_SignInit.3 \
+man/man3/EVP_VerifyInit.3 \
+man/man3/EVP_aes_128_gcm.3 \
+man/man3/EVP_aria_128_gcm.3 \
+man/man3/EVP_bf_cbc.3 \
+man/man3/EVP_blake2b512.3 \
+man/man3/EVP_camellia_128_ecb.3 \
+man/man3/EVP_cast5_cbc.3 \
+man/man3/EVP_chacha20.3 \
+man/man3/EVP_des_cbc.3 \
+man/man3/EVP_desx_cbc.3 \
+man/man3/EVP_idea_cbc.3 \
+man/man3/EVP_md2.3 \
+man/man3/EVP_md4.3 \
+man/man3/EVP_md5.3 \
+man/man3/EVP_mdc2.3 \
+man/man3/EVP_rc2_cbc.3 \
+man/man3/EVP_rc4.3 \
+man/man3/EVP_rc5_32_12_16_cbc.3 \
+man/man3/EVP_ripemd160.3 \
+man/man3/EVP_seed_cbc.3 \
+man/man3/EVP_set_default_properties.3 \
+man/man3/EVP_sha1.3 \
+man/man3/EVP_sha224.3 \
+man/man3/EVP_sha3_224.3 \
+man/man3/EVP_sm3.3 \
+man/man3/EVP_sm4_cbc.3 \
+man/man3/EVP_whirlpool.3 \
+man/man3/HMAC.3 \
+man/man3/MD5.3 \
+man/man3/MDC2_Init.3 \
+man/man3/NCONF_new_ex.3 \
+man/man3/OBJ_nid2obj.3 \
+man/man3/OCSP_REQUEST_new.3 \
+man/man3/OCSP_cert_to_id.3 \
+man/man3/OCSP_request_add1_nonce.3 \
+man/man3/OCSP_resp_find_status.3 \
+man/man3/OCSP_response_status.3 \
+man/man3/OCSP_sendreq_new.3 \
+man/man3/OPENSSL_Applink.3 \
+man/man3/OPENSSL_FILE.3 \
+man/man3/OPENSSL_LH_COMPFUNC.3 \
+man/man3/OPENSSL_LH_stats.3 \
+man/man3/OPENSSL_config.3 \
+man/man3/OPENSSL_fork_prepare.3 \
+man/man3/OPENSSL_gmtime.3 \
+man/man3/OPENSSL_hexchar2int.3 \
+man/man3/OPENSSL_ia32cap.3 \
+man/man3/OPENSSL_init_crypto.3 \
+man/man3/OPENSSL_init_ssl.3 \
+man/man3/OPENSSL_instrument_bus.3 \
+man/man3/OPENSSL_load_builtin_modules.3 \
+man/man3/OPENSSL_malloc.3 \
+man/man3/OPENSSL_s390xcap.3 \
+man/man3/OPENSSL_secure_malloc.3 \
+man/man3/OPENSSL_strcasecmp.3 \
+man/man3/OSSL_ALGORITHM.3 \
+man/man3/OSSL_CALLBACK.3 \
+man/man3/OSSL_CMP_CTX_new.3 \
+man/man3/OSSL_CMP_HDR_get0_transactionID.3 \
+man/man3/OSSL_CMP_ITAV_set0.3 \
+man/man3/OSSL_CMP_MSG_get0_header.3 \
+man/man3/OSSL_CMP_MSG_http_perform.3 \
+man/man3/OSSL_CMP_SRV_CTX_new.3 \
+man/man3/OSSL_CMP_STATUSINFO_new.3 \
+man/man3/OSSL_CMP_exec_certreq.3 \
+man/man3/OSSL_CMP_log_open.3 \
+man/man3/OSSL_CMP_validate_msg.3 \
+man/man3/OSSL_CORE_MAKE_FUNC.3 \
+man/man3/OSSL_CRMF_MSG_get0_tmpl.3 \
+man/man3/OSSL_CRMF_MSG_set0_validity.3 \
+man/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.3 \
+man/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.3 \
+man/man3/OSSL_CRMF_pbmp_new.3 \
+man/man3/OSSL_DECODER.3 \
+man/man3/OSSL_DECODER_CTX.3 \
+man/man3/OSSL_DECODER_CTX_new_for_pkey.3 \
+man/man3/OSSL_DECODER_from_bio.3 \
+man/man3/OSSL_DISPATCH.3 \
+man/man3/OSSL_ENCODER.3 \
+man/man3/OSSL_ENCODER_CTX.3 \
+man/man3/OSSL_ENCODER_CTX_new_for_pkey.3 \
+man/man3/OSSL_ENCODER_to_bio.3 \
+man/man3/OSSL_ESS_check_signing_certs.3 \
+man/man3/OSSL_HTTP_REQ_CTX.3 \
+man/man3/OSSL_HTTP_parse_url.3 \
+man/man3/OSSL_HTTP_transfer.3 \
+man/man3/OSSL_ITEM.3 \
+man/man3/OSSL_LIB_CTX.3 \
+man/man3/OSSL_PARAM.3 \
+man/man3/OSSL_PARAM_BLD.3 \
+man/man3/OSSL_PARAM_allocate_from_text.3 \
+man/man3/OSSL_PARAM_dup.3 \
+man/man3/OSSL_PARAM_int.3 \
+man/man3/OSSL_PROVIDER.3 \
+man/man3/OSSL_SELF_TEST_new.3 \
+man/man3/OSSL_SELF_TEST_set_callback.3 \
+man/man3/OSSL_STORE_INFO.3 \
+man/man3/OSSL_STORE_LOADER.3 \
+man/man3/OSSL_STORE_SEARCH.3 \
+man/man3/OSSL_STORE_attach.3 \
+man/man3/OSSL_STORE_expect.3 \
+man/man3/OSSL_STORE_open.3 \
+man/man3/OSSL_trace_enabled.3 \
+man/man3/OSSL_trace_get_category_num.3 \
+man/man3/OSSL_trace_set_channel.3 \
+man/man3/OpenSSL_add_all_algorithms.3 \
+man/man3/OpenSSL_version.3 \
+man/man3/PEM_X509_INFO_read_bio_ex.3 \
+man/man3/PEM_bytes_read_bio.3 \
+man/man3/PEM_read.3 \
+man/man3/PEM_read_CMS.3 \
+man/man3/PEM_read_bio_PrivateKey.3 \
+man/man3/PEM_read_bio_ex.3 \
+man/man3/PEM_write_bio_CMS_stream.3 \
+man/man3/PEM_write_bio_PKCS7_stream.3 \
+man/man3/PKCS12_PBE_keyivgen.3 \
+man/man3/PKCS12_SAFEBAG_create_cert.3 \
+man/man3/PKCS12_SAFEBAG_get0_attrs.3 \
+man/man3/PKCS12_SAFEBAG_get1_cert.3 \
+man/man3/PKCS12_add1_attr_by_NID.3 \
+man/man3/PKCS12_add_CSPName_asc.3 \
+man/man3/PKCS12_add_cert.3 \
+man/man3/PKCS12_add_friendlyname_asc.3 \
+man/man3/PKCS12_add_localkeyid.3 \
+man/man3/PKCS12_add_safe.3 \
+man/man3/PKCS12_create.3 \
+man/man3/PKCS12_decrypt_skey.3 \
+man/man3/PKCS12_gen_mac.3 \
+man/man3/PKCS12_get_friendlyname.3 \
+man/man3/PKCS12_init.3 \
+man/man3/PKCS12_item_decrypt_d2i.3 \
+man/man3/PKCS12_key_gen_utf8_ex.3 \
+man/man3/PKCS12_newpass.3 \
+man/man3/PKCS12_pack_p7encdata.3 \
+man/man3/PKCS12_parse.3 \
+man/man3/PKCS5_PBE_keyivgen.3 \
+man/man3/PKCS5_PBKDF2_HMAC.3 \
+man/man3/PKCS7_decrypt.3 \
+man/man3/PKCS7_encrypt.3 \
+man/man3/PKCS7_get_octet_string.3 \
+man/man3/PKCS7_sign.3 \
+man/man3/PKCS7_sign_add_signer.3 \
+man/man3/PKCS7_type_is_other.3 \
+man/man3/PKCS7_verify.3 \
+man/man3/PKCS8_encrypt.3 \
+man/man3/PKCS8_pkey_add1_attr.3 \
+man/man3/RAND_add.3 \
+man/man3/RAND_bytes.3 \
+man/man3/RAND_cleanup.3 \
+man/man3/RAND_egd.3 \
+man/man3/RAND_get0_primary.3 \
+man/man3/RAND_load_file.3 \
+man/man3/RAND_set_DRBG_type.3 \
+man/man3/RAND_set_rand_method.3 \
+man/man3/RC4_set_key.3 \
+man/man3/RIPEMD160_Init.3 \
+man/man3/RSA_blinding_on.3 \
+man/man3/RSA_check_key.3 \
+man/man3/RSA_generate_key.3 \
+man/man3/RSA_get0_key.3 \
+man/man3/RSA_meth_new.3 \
+man/man3/RSA_new.3 \
+man/man3/RSA_padding_add_PKCS1_type_1.3 \
+man/man3/RSA_print.3 \
+man/man3/RSA_private_encrypt.3 \
+man/man3/RSA_public_encrypt.3 \
+man/man3/RSA_set_method.3 \
+man/man3/RSA_sign.3 \
+man/man3/RSA_sign_ASN1_OCTET_STRING.3 \
+man/man3/RSA_size.3 \
+man/man3/SCT_new.3 \
+man/man3/SCT_print.3 \
+man/man3/SCT_validate.3 \
+man/man3/SHA256_Init.3 \
+man/man3/SMIME_read_ASN1.3 \
+man/man3/SMIME_read_CMS.3 \
+man/man3/SMIME_read_PKCS7.3 \
+man/man3/SMIME_write_ASN1.3 \
+man/man3/SMIME_write_CMS.3 \
+man/man3/SMIME_write_PKCS7.3 \
+man/man3/SRP_Calc_B.3 \
+man/man3/SRP_VBASE_new.3 \
+man/man3/SRP_create_verifier.3 \
+man/man3/SRP_user_pwd_new.3 \
+man/man3/SSL_CIPHER_get_name.3 \
+man/man3/SSL_COMP_add_compression_method.3 \
+man/man3/SSL_CONF_CTX_new.3 \
+man/man3/SSL_CONF_CTX_set1_prefix.3 \
+man/man3/SSL_CONF_CTX_set_flags.3 \
+man/man3/SSL_CONF_CTX_set_ssl_ctx.3 \
+man/man3/SSL_CONF_cmd.3 \
+man/man3/SSL_CONF_cmd_argv.3 \
+man/man3/SSL_CTX_add1_chain_cert.3 \
+man/man3/SSL_CTX_add_extra_chain_cert.3 \
+man/man3/SSL_CTX_add_session.3 \
+man/man3/SSL_CTX_config.3 \
+man/man3/SSL_CTX_ctrl.3 \
+man/man3/SSL_CTX_dane_enable.3 \
+man/man3/SSL_CTX_flush_sessions.3 \
+man/man3/SSL_CTX_free.3 \
+man/man3/SSL_CTX_get0_param.3 \
+man/man3/SSL_CTX_get_verify_mode.3 \
+man/man3/SSL_CTX_has_client_custom_ext.3 \
+man/man3/SSL_CTX_load_verify_locations.3 \
+man/man3/SSL_CTX_new.3 \
+man/man3/SSL_CTX_sess_number.3 \
+man/man3/SSL_CTX_sess_set_cache_size.3 \
+man/man3/SSL_CTX_sess_set_get_cb.3 \
+man/man3/SSL_CTX_sessions.3 \
+man/man3/SSL_CTX_set0_CA_list.3 \
+man/man3/SSL_CTX_set1_curves.3 \
+man/man3/SSL_CTX_set1_sigalgs.3 \
+man/man3/SSL_CTX_set1_verify_cert_store.3 \
+man/man3/SSL_CTX_set_alpn_select_cb.3 \
+man/man3/SSL_CTX_set_cert_cb.3 \
+man/man3/SSL_CTX_set_cert_store.3 \
+man/man3/SSL_CTX_set_cert_verify_callback.3 \
+man/man3/SSL_CTX_set_cipher_list.3 \
+man/man3/SSL_CTX_set_client_cert_cb.3 \
+man/man3/SSL_CTX_set_client_hello_cb.3 \
+man/man3/SSL_CTX_set_ct_validation_callback.3 \
+man/man3/SSL_CTX_set_ctlog_list_file.3 \
+man/man3/SSL_CTX_set_default_passwd_cb.3 \
+man/man3/SSL_CTX_set_generate_session_id.3 \
+man/man3/SSL_CTX_set_info_callback.3 \
+man/man3/SSL_CTX_set_keylog_callback.3 \
+man/man3/SSL_CTX_set_max_cert_list.3 \
+man/man3/SSL_CTX_set_min_proto_version.3 \
+man/man3/SSL_CTX_set_mode.3 \
+man/man3/SSL_CTX_set_msg_callback.3 \
+man/man3/SSL_CTX_set_num_tickets.3 \
+man/man3/SSL_CTX_set_options.3 \
+man/man3/SSL_CTX_set_psk_client_callback.3 \
+man/man3/SSL_CTX_set_quiet_shutdown.3 \
+man/man3/SSL_CTX_set_read_ahead.3 \
+man/man3/SSL_CTX_set_record_padding_callback.3 \
+man/man3/SSL_CTX_set_security_level.3 \
+man/man3/SSL_CTX_set_session_cache_mode.3 \
+man/man3/SSL_CTX_set_session_id_context.3 \
+man/man3/SSL_CTX_set_session_ticket_cb.3 \
+man/man3/SSL_CTX_set_split_send_fragment.3 \
+man/man3/SSL_CTX_set_srp_password.3 \
+man/man3/SSL_CTX_set_ssl_version.3 \
+man/man3/SSL_CTX_set_stateless_cookie_generate_cb.3 \
+man/man3/SSL_CTX_set_timeout.3 \
+man/man3/SSL_CTX_set_tlsext_servername_callback.3 \
+man/man3/SSL_CTX_set_tlsext_status_cb.3 \
+man/man3/SSL_CTX_set_tlsext_ticket_key_cb.3 \
+man/man3/SSL_CTX_set_tlsext_use_srtp.3 \
+man/man3/SSL_CTX_set_tmp_dh_callback.3 \
+man/man3/SSL_CTX_set_tmp_ecdh.3 \
+man/man3/SSL_CTX_set_verify.3 \
+man/man3/SSL_CTX_use_certificate.3 \
+man/man3/SSL_CTX_use_psk_identity_hint.3 \
+man/man3/SSL_CTX_use_serverinfo.3 \
+man/man3/SSL_SESSION_free.3 \
+man/man3/SSL_SESSION_get0_cipher.3 \
+man/man3/SSL_SESSION_get0_hostname.3 \
+man/man3/SSL_SESSION_get0_id_context.3 \
+man/man3/SSL_SESSION_get0_peer.3 \
+man/man3/SSL_SESSION_get_compress_id.3 \
+man/man3/SSL_SESSION_get_protocol_version.3 \
+man/man3/SSL_SESSION_get_time.3 \
+man/man3/SSL_SESSION_has_ticket.3 \
+man/man3/SSL_SESSION_is_resumable.3 \
+man/man3/SSL_SESSION_print.3 \
+man/man3/SSL_SESSION_set1_id.3 \
+man/man3/SSL_accept.3 \
+man/man3/SSL_alert_type_string.3 \
+man/man3/SSL_alloc_buffers.3 \
+man/man3/SSL_check_chain.3 \
+man/man3/SSL_clear.3 \
+man/man3/SSL_connect.3 \
+man/man3/SSL_do_handshake.3 \
+man/man3/SSL_export_keying_material.3 \
+man/man3/SSL_extension_supported.3 \
+man/man3/SSL_free.3 \
+man/man3/SSL_get0_peer_scts.3 \
+man/man3/SSL_get_SSL_CTX.3 \
+man/man3/SSL_get_all_async_fds.3 \
+man/man3/SSL_get_certificate.3 \
+man/man3/SSL_get_ciphers.3 \
+man/man3/SSL_get_client_random.3 \
+man/man3/SSL_get_current_cipher.3 \
+man/man3/SSL_get_default_timeout.3 \
+man/man3/SSL_get_error.3 \
+man/man3/SSL_get_extms_support.3 \
+man/man3/SSL_get_fd.3 \
+man/man3/SSL_get_peer_cert_chain.3 \
+man/man3/SSL_get_peer_certificate.3 \
+man/man3/SSL_get_peer_signature_nid.3 \
+man/man3/SSL_get_peer_tmp_key.3 \
+man/man3/SSL_get_psk_identity.3 \
+man/man3/SSL_get_rbio.3 \
+man/man3/SSL_get_session.3 \
+man/man3/SSL_get_shared_sigalgs.3 \
+man/man3/SSL_get_verify_result.3 \
+man/man3/SSL_get_version.3 \
+man/man3/SSL_group_to_name.3 \
+man/man3/SSL_in_init.3 \
+man/man3/SSL_key_update.3 \
+man/man3/SSL_library_init.3 \
+man/man3/SSL_load_client_CA_file.3 \
+man/man3/SSL_new.3 \
+man/man3/SSL_pending.3 \
+man/man3/SSL_read.3 \
+man/man3/SSL_read_early_data.3 \
+man/man3/SSL_rstate_string.3 \
+man/man3/SSL_session_reused.3 \
+man/man3/SSL_set1_host.3 \
+man/man3/SSL_set_async_callback.3 \
+man/man3/SSL_set_bio.3 \
+man/man3/SSL_set_connect_state.3 \
+man/man3/SSL_set_fd.3 \
+man/man3/SSL_set_retry_verify.3 \
+man/man3/SSL_set_session.3 \
+man/man3/SSL_set_shutdown.3 \
+man/man3/SSL_set_verify_result.3 \
+man/man3/SSL_shutdown.3 \
+man/man3/SSL_state_string.3 \
+man/man3/SSL_want.3 \
+man/man3/SSL_write.3 \
+man/man3/TS_RESP_CTX_new.3 \
+man/man3/TS_VERIFY_CTX_set_certs.3 \
+man/man3/UI_STRING.3 \
+man/man3/UI_UTIL_read_pw.3 \
+man/man3/UI_create_method.3 \
+man/man3/UI_new.3 \
+man/man3/X509V3_get_d2i.3 \
+man/man3/X509V3_set_ctx.3 \
+man/man3/X509_ALGOR_dup.3 \
+man/man3/X509_CRL_get0_by_serial.3 \
+man/man3/X509_EXTENSION_set_object.3 \
+man/man3/X509_LOOKUP.3 \
+man/man3/X509_LOOKUP_hash_dir.3 \
+man/man3/X509_LOOKUP_meth_new.3 \
+man/man3/X509_NAME_ENTRY_get_object.3 \
+man/man3/X509_NAME_add_entry_by_txt.3 \
+man/man3/X509_NAME_get0_der.3 \
+man/man3/X509_NAME_get_index_by_NID.3 \
+man/man3/X509_NAME_print_ex.3 \
+man/man3/X509_PUBKEY_new.3 \
+man/man3/X509_SIG_get0.3 \
+man/man3/X509_STORE_CTX_get_error.3 \
+man/man3/X509_STORE_CTX_new.3 \
+man/man3/X509_STORE_CTX_set_verify_cb.3 \
+man/man3/X509_STORE_add_cert.3 \
+man/man3/X509_STORE_get0_param.3 \
+man/man3/X509_STORE_new.3 \
+man/man3/X509_STORE_set_verify_cb_func.3 \
+man/man3/X509_VERIFY_PARAM_set_flags.3 \
+man/man3/X509_add_cert.3 \
+man/man3/X509_check_ca.3 \
+man/man3/X509_check_host.3 \
+man/man3/X509_check_issued.3 \
+man/man3/X509_check_private_key.3 \
+man/man3/X509_check_purpose.3 \
+man/man3/X509_cmp.3 \
+man/man3/X509_cmp_time.3 \
+man/man3/X509_digest.3 \
+man/man3/X509_dup.3 \
+man/man3/X509_get0_distinguishing_id.3 \
+man/man3/X509_get0_notBefore.3 \
+man/man3/X509_get0_signature.3 \
+man/man3/X509_get0_uids.3 \
+man/man3/X509_get_extension_flags.3 \
+man/man3/X509_get_pubkey.3 \
+man/man3/X509_get_serialNumber.3 \
+man/man3/X509_get_subject_name.3 \
+man/man3/X509_get_version.3 \
+man/man3/X509_load_http.3 \
+man/man3/X509_new.3 \
+man/man3/X509_sign.3 \
+man/man3/X509_verify.3 \
+man/man3/X509_verify_cert.3 \
+man/man3/X509v3_get_ext_by_NID.3 \
+man/man3/b2i_PVK_bio_ex.3 \
+man/man3/d2i_PKCS8PrivateKey_bio.3 \
+man/man3/d2i_PrivateKey.3 \
+man/man3/d2i_RSAPrivateKey.3 \
+man/man3/d2i_SSL_SESSION.3 \
+man/man3/d2i_X509.3 \
+man/man3/i2d_CMS_bio_stream.3 \
+man/man3/i2d_PKCS7_bio_stream.3 \
+man/man3/i2d_re_X509_tbs.3 \
+man/man3/o2i_SCT_LIST.3 \
+man/man3/s2i_ASN1_IA5STRING.3
+DEPEND[html/man5/config.html]=man5/config.pod
+GENERATE[html/man5/config.html]=man5/config.pod
+DEPEND[man/man5/config.5]=man5/config.pod
+GENERATE[man/man5/config.5]=man5/config.pod
+DEPEND[html/man5/fips_config.html]=man5/fips_config.pod
+GENERATE[html/man5/fips_config.html]=man5/fips_config.pod
+DEPEND[man/man5/fips_config.5]=man5/fips_config.pod
+GENERATE[man/man5/fips_config.5]=man5/fips_config.pod
+DEPEND[html/man5/x509v3_config.html]=man5/x509v3_config.pod
+GENERATE[html/man5/x509v3_config.html]=man5/x509v3_config.pod
+DEPEND[man/man5/x509v3_config.5]=man5/x509v3_config.pod
+GENERATE[man/man5/x509v3_config.5]=man5/x509v3_config.pod
+IMAGEDOCS[man5]=
+HTMLDOCS[man5]=html/man5/config.html \
+html/man5/fips_config.html \
+html/man5/x509v3_config.html
+MANDOCS[man5]=man/man5/config.5 \
+man/man5/fips_config.5 \
+man/man5/x509v3_config.5
+DEPEND[html/man7/EVP_ASYM_CIPHER-RSA.html]=man7/EVP_ASYM_CIPHER-RSA.pod
+GENERATE[html/man7/EVP_ASYM_CIPHER-RSA.html]=man7/EVP_ASYM_CIPHER-RSA.pod
+DEPEND[man/man7/EVP_ASYM_CIPHER-RSA.7]=man7/EVP_ASYM_CIPHER-RSA.pod
+GENERATE[man/man7/EVP_ASYM_CIPHER-RSA.7]=man7/EVP_ASYM_CIPHER-RSA.pod
+DEPEND[html/man7/EVP_ASYM_CIPHER-SM2.html]=man7/EVP_ASYM_CIPHER-SM2.pod
+GENERATE[html/man7/EVP_ASYM_CIPHER-SM2.html]=man7/EVP_ASYM_CIPHER-SM2.pod
+DEPEND[man/man7/EVP_ASYM_CIPHER-SM2.7]=man7/EVP_ASYM_CIPHER-SM2.pod
+GENERATE[man/man7/EVP_ASYM_CIPHER-SM2.7]=man7/EVP_ASYM_CIPHER-SM2.pod
+DEPEND[html/man7/EVP_CIPHER-AES.html]=man7/EVP_CIPHER-AES.pod
+GENERATE[html/man7/EVP_CIPHER-AES.html]=man7/EVP_CIPHER-AES.pod
+DEPEND[man/man7/EVP_CIPHER-AES.7]=man7/EVP_CIPHER-AES.pod
+GENERATE[man/man7/EVP_CIPHER-AES.7]=man7/EVP_CIPHER-AES.pod
+DEPEND[html/man7/EVP_CIPHER-ARIA.html]=man7/EVP_CIPHER-ARIA.pod
+GENERATE[html/man7/EVP_CIPHER-ARIA.html]=man7/EVP_CIPHER-ARIA.pod
+DEPEND[man/man7/EVP_CIPHER-ARIA.7]=man7/EVP_CIPHER-ARIA.pod
+GENERATE[man/man7/EVP_CIPHER-ARIA.7]=man7/EVP_CIPHER-ARIA.pod
+DEPEND[html/man7/EVP_CIPHER-BLOWFISH.html]=man7/EVP_CIPHER-BLOWFISH.pod
+GENERATE[html/man7/EVP_CIPHER-BLOWFISH.html]=man7/EVP_CIPHER-BLOWFISH.pod
+DEPEND[man/man7/EVP_CIPHER-BLOWFISH.7]=man7/EVP_CIPHER-BLOWFISH.pod
+GENERATE[man/man7/EVP_CIPHER-BLOWFISH.7]=man7/EVP_CIPHER-BLOWFISH.pod
+DEPEND[html/man7/EVP_CIPHER-CAMELLIA.html]=man7/EVP_CIPHER-CAMELLIA.pod
+GENERATE[html/man7/EVP_CIPHER-CAMELLIA.html]=man7/EVP_CIPHER-CAMELLIA.pod
+DEPEND[man/man7/EVP_CIPHER-CAMELLIA.7]=man7/EVP_CIPHER-CAMELLIA.pod
+GENERATE[man/man7/EVP_CIPHER-CAMELLIA.7]=man7/EVP_CIPHER-CAMELLIA.pod
+DEPEND[html/man7/EVP_CIPHER-CAST.html]=man7/EVP_CIPHER-CAST.pod
+GENERATE[html/man7/EVP_CIPHER-CAST.html]=man7/EVP_CIPHER-CAST.pod
+DEPEND[man/man7/EVP_CIPHER-CAST.7]=man7/EVP_CIPHER-CAST.pod
+GENERATE[man/man7/EVP_CIPHER-CAST.7]=man7/EVP_CIPHER-CAST.pod
+DEPEND[html/man7/EVP_CIPHER-CHACHA.html]=man7/EVP_CIPHER-CHACHA.pod
+GENERATE[html/man7/EVP_CIPHER-CHACHA.html]=man7/EVP_CIPHER-CHACHA.pod
+DEPEND[man/man7/EVP_CIPHER-CHACHA.7]=man7/EVP_CIPHER-CHACHA.pod
+GENERATE[man/man7/EVP_CIPHER-CHACHA.7]=man7/EVP_CIPHER-CHACHA.pod
+DEPEND[html/man7/EVP_CIPHER-DES.html]=man7/EVP_CIPHER-DES.pod
+GENERATE[html/man7/EVP_CIPHER-DES.html]=man7/EVP_CIPHER-DES.pod
+DEPEND[man/man7/EVP_CIPHER-DES.7]=man7/EVP_CIPHER-DES.pod
+GENERATE[man/man7/EVP_CIPHER-DES.7]=man7/EVP_CIPHER-DES.pod
+DEPEND[html/man7/EVP_CIPHER-IDEA.html]=man7/EVP_CIPHER-IDEA.pod
+GENERATE[html/man7/EVP_CIPHER-IDEA.html]=man7/EVP_CIPHER-IDEA.pod
+DEPEND[man/man7/EVP_CIPHER-IDEA.7]=man7/EVP_CIPHER-IDEA.pod
+GENERATE[man/man7/EVP_CIPHER-IDEA.7]=man7/EVP_CIPHER-IDEA.pod
+DEPEND[html/man7/EVP_CIPHER-RC2.html]=man7/EVP_CIPHER-RC2.pod
+GENERATE[html/man7/EVP_CIPHER-RC2.html]=man7/EVP_CIPHER-RC2.pod
+DEPEND[man/man7/EVP_CIPHER-RC2.7]=man7/EVP_CIPHER-RC2.pod
+GENERATE[man/man7/EVP_CIPHER-RC2.7]=man7/EVP_CIPHER-RC2.pod
+DEPEND[html/man7/EVP_CIPHER-RC4.html]=man7/EVP_CIPHER-RC4.pod
+GENERATE[html/man7/EVP_CIPHER-RC4.html]=man7/EVP_CIPHER-RC4.pod
+DEPEND[man/man7/EVP_CIPHER-RC4.7]=man7/EVP_CIPHER-RC4.pod
+GENERATE[man/man7/EVP_CIPHER-RC4.7]=man7/EVP_CIPHER-RC4.pod
+DEPEND[html/man7/EVP_CIPHER-RC5.html]=man7/EVP_CIPHER-RC5.pod
+GENERATE[html/man7/EVP_CIPHER-RC5.html]=man7/EVP_CIPHER-RC5.pod
+DEPEND[man/man7/EVP_CIPHER-RC5.7]=man7/EVP_CIPHER-RC5.pod
+GENERATE[man/man7/EVP_CIPHER-RC5.7]=man7/EVP_CIPHER-RC5.pod
+DEPEND[html/man7/EVP_CIPHER-SEED.html]=man7/EVP_CIPHER-SEED.pod
+GENERATE[html/man7/EVP_CIPHER-SEED.html]=man7/EVP_CIPHER-SEED.pod
+DEPEND[man/man7/EVP_CIPHER-SEED.7]=man7/EVP_CIPHER-SEED.pod
+GENERATE[man/man7/EVP_CIPHER-SEED.7]=man7/EVP_CIPHER-SEED.pod
+DEPEND[html/man7/EVP_CIPHER-SM4.html]=man7/EVP_CIPHER-SM4.pod
+GENERATE[html/man7/EVP_CIPHER-SM4.html]=man7/EVP_CIPHER-SM4.pod
+DEPEND[man/man7/EVP_CIPHER-SM4.7]=man7/EVP_CIPHER-SM4.pod
+GENERATE[man/man7/EVP_CIPHER-SM4.7]=man7/EVP_CIPHER-SM4.pod
+DEPEND[html/man7/EVP_KDF-HKDF.html]=man7/EVP_KDF-HKDF.pod
+GENERATE[html/man7/EVP_KDF-HKDF.html]=man7/EVP_KDF-HKDF.pod
+DEPEND[man/man7/EVP_KDF-HKDF.7]=man7/EVP_KDF-HKDF.pod
+GENERATE[man/man7/EVP_KDF-HKDF.7]=man7/EVP_KDF-HKDF.pod
+DEPEND[html/man7/EVP_KDF-KB.html]=man7/EVP_KDF-KB.pod
+GENERATE[html/man7/EVP_KDF-KB.html]=man7/EVP_KDF-KB.pod
+DEPEND[man/man7/EVP_KDF-KB.7]=man7/EVP_KDF-KB.pod
+GENERATE[man/man7/EVP_KDF-KB.7]=man7/EVP_KDF-KB.pod
+DEPEND[html/man7/EVP_KDF-KRB5KDF.html]=man7/EVP_KDF-KRB5KDF.pod
+GENERATE[html/man7/EVP_KDF-KRB5KDF.html]=man7/EVP_KDF-KRB5KDF.pod
+DEPEND[man/man7/EVP_KDF-KRB5KDF.7]=man7/EVP_KDF-KRB5KDF.pod
+GENERATE[man/man7/EVP_KDF-KRB5KDF.7]=man7/EVP_KDF-KRB5KDF.pod
+DEPEND[html/man7/EVP_KDF-PBKDF1.html]=man7/EVP_KDF-PBKDF1.pod
+GENERATE[html/man7/EVP_KDF-PBKDF1.html]=man7/EVP_KDF-PBKDF1.pod
+DEPEND[man/man7/EVP_KDF-PBKDF1.7]=man7/EVP_KDF-PBKDF1.pod
+GENERATE[man/man7/EVP_KDF-PBKDF1.7]=man7/EVP_KDF-PBKDF1.pod
+DEPEND[html/man7/EVP_KDF-PBKDF2.html]=man7/EVP_KDF-PBKDF2.pod
+GENERATE[html/man7/EVP_KDF-PBKDF2.html]=man7/EVP_KDF-PBKDF2.pod
+DEPEND[man/man7/EVP_KDF-PBKDF2.7]=man7/EVP_KDF-PBKDF2.pod
+GENERATE[man/man7/EVP_KDF-PBKDF2.7]=man7/EVP_KDF-PBKDF2.pod
+DEPEND[html/man7/EVP_KDF-PKCS12KDF.html]=man7/EVP_KDF-PKCS12KDF.pod
+GENERATE[html/man7/EVP_KDF-PKCS12KDF.html]=man7/EVP_KDF-PKCS12KDF.pod
+DEPEND[man/man7/EVP_KDF-PKCS12KDF.7]=man7/EVP_KDF-PKCS12KDF.pod
+GENERATE[man/man7/EVP_KDF-PKCS12KDF.7]=man7/EVP_KDF-PKCS12KDF.pod
+DEPEND[html/man7/EVP_KDF-SCRYPT.html]=man7/EVP_KDF-SCRYPT.pod
+GENERATE[html/man7/EVP_KDF-SCRYPT.html]=man7/EVP_KDF-SCRYPT.pod
+DEPEND[man/man7/EVP_KDF-SCRYPT.7]=man7/EVP_KDF-SCRYPT.pod
+GENERATE[man/man7/EVP_KDF-SCRYPT.7]=man7/EVP_KDF-SCRYPT.pod
+DEPEND[html/man7/EVP_KDF-SS.html]=man7/EVP_KDF-SS.pod
+GENERATE[html/man7/EVP_KDF-SS.html]=man7/EVP_KDF-SS.pod
+DEPEND[man/man7/EVP_KDF-SS.7]=man7/EVP_KDF-SS.pod
+GENERATE[man/man7/EVP_KDF-SS.7]=man7/EVP_KDF-SS.pod
+DEPEND[html/man7/EVP_KDF-SSHKDF.html]=man7/EVP_KDF-SSHKDF.pod
+GENERATE[html/man7/EVP_KDF-SSHKDF.html]=man7/EVP_KDF-SSHKDF.pod
+DEPEND[man/man7/EVP_KDF-SSHKDF.7]=man7/EVP_KDF-SSHKDF.pod
+GENERATE[man/man7/EVP_KDF-SSHKDF.7]=man7/EVP_KDF-SSHKDF.pod
+DEPEND[html/man7/EVP_KDF-TLS13_KDF.html]=man7/EVP_KDF-TLS13_KDF.pod
+GENERATE[html/man7/EVP_KDF-TLS13_KDF.html]=man7/EVP_KDF-TLS13_KDF.pod
+DEPEND[man/man7/EVP_KDF-TLS13_KDF.7]=man7/EVP_KDF-TLS13_KDF.pod
+GENERATE[man/man7/EVP_KDF-TLS13_KDF.7]=man7/EVP_KDF-TLS13_KDF.pod
+DEPEND[html/man7/EVP_KDF-TLS1_PRF.html]=man7/EVP_KDF-TLS1_PRF.pod
+GENERATE[html/man7/EVP_KDF-TLS1_PRF.html]=man7/EVP_KDF-TLS1_PRF.pod
+DEPEND[man/man7/EVP_KDF-TLS1_PRF.7]=man7/EVP_KDF-TLS1_PRF.pod
+GENERATE[man/man7/EVP_KDF-TLS1_PRF.7]=man7/EVP_KDF-TLS1_PRF.pod
+DEPEND[html/man7/EVP_KDF-X942-ASN1.html]=man7/EVP_KDF-X942-ASN1.pod
+GENERATE[html/man7/EVP_KDF-X942-ASN1.html]=man7/EVP_KDF-X942-ASN1.pod
+DEPEND[man/man7/EVP_KDF-X942-ASN1.7]=man7/EVP_KDF-X942-ASN1.pod
+GENERATE[man/man7/EVP_KDF-X942-ASN1.7]=man7/EVP_KDF-X942-ASN1.pod
+DEPEND[html/man7/EVP_KDF-X942-CONCAT.html]=man7/EVP_KDF-X942-CONCAT.pod
+GENERATE[html/man7/EVP_KDF-X942-CONCAT.html]=man7/EVP_KDF-X942-CONCAT.pod
+DEPEND[man/man7/EVP_KDF-X942-CONCAT.7]=man7/EVP_KDF-X942-CONCAT.pod
+GENERATE[man/man7/EVP_KDF-X942-CONCAT.7]=man7/EVP_KDF-X942-CONCAT.pod
+DEPEND[html/man7/EVP_KDF-X963.html]=man7/EVP_KDF-X963.pod
+GENERATE[html/man7/EVP_KDF-X963.html]=man7/EVP_KDF-X963.pod
+DEPEND[man/man7/EVP_KDF-X963.7]=man7/EVP_KDF-X963.pod
+GENERATE[man/man7/EVP_KDF-X963.7]=man7/EVP_KDF-X963.pod
+DEPEND[html/man7/EVP_KEM-RSA.html]=man7/EVP_KEM-RSA.pod
+GENERATE[html/man7/EVP_KEM-RSA.html]=man7/EVP_KEM-RSA.pod
+DEPEND[man/man7/EVP_KEM-RSA.7]=man7/EVP_KEM-RSA.pod
+GENERATE[man/man7/EVP_KEM-RSA.7]=man7/EVP_KEM-RSA.pod
+DEPEND[html/man7/EVP_KEYEXCH-DH.html]=man7/EVP_KEYEXCH-DH.pod
+GENERATE[html/man7/EVP_KEYEXCH-DH.html]=man7/EVP_KEYEXCH-DH.pod
+DEPEND[man/man7/EVP_KEYEXCH-DH.7]=man7/EVP_KEYEXCH-DH.pod
+GENERATE[man/man7/EVP_KEYEXCH-DH.7]=man7/EVP_KEYEXCH-DH.pod
+DEPEND[html/man7/EVP_KEYEXCH-ECDH.html]=man7/EVP_KEYEXCH-ECDH.pod
+GENERATE[html/man7/EVP_KEYEXCH-ECDH.html]=man7/EVP_KEYEXCH-ECDH.pod
+DEPEND[man/man7/EVP_KEYEXCH-ECDH.7]=man7/EVP_KEYEXCH-ECDH.pod
+GENERATE[man/man7/EVP_KEYEXCH-ECDH.7]=man7/EVP_KEYEXCH-ECDH.pod
+DEPEND[html/man7/EVP_KEYEXCH-X25519.html]=man7/EVP_KEYEXCH-X25519.pod
+GENERATE[html/man7/EVP_KEYEXCH-X25519.html]=man7/EVP_KEYEXCH-X25519.pod
+DEPEND[man/man7/EVP_KEYEXCH-X25519.7]=man7/EVP_KEYEXCH-X25519.pod
+GENERATE[man/man7/EVP_KEYEXCH-X25519.7]=man7/EVP_KEYEXCH-X25519.pod
+DEPEND[html/man7/EVP_MAC-BLAKE2.html]=man7/EVP_MAC-BLAKE2.pod
+GENERATE[html/man7/EVP_MAC-BLAKE2.html]=man7/EVP_MAC-BLAKE2.pod
+DEPEND[man/man7/EVP_MAC-BLAKE2.7]=man7/EVP_MAC-BLAKE2.pod
+GENERATE[man/man7/EVP_MAC-BLAKE2.7]=man7/EVP_MAC-BLAKE2.pod
+DEPEND[html/man7/EVP_MAC-CMAC.html]=man7/EVP_MAC-CMAC.pod
+GENERATE[html/man7/EVP_MAC-CMAC.html]=man7/EVP_MAC-CMAC.pod
+DEPEND[man/man7/EVP_MAC-CMAC.7]=man7/EVP_MAC-CMAC.pod
+GENERATE[man/man7/EVP_MAC-CMAC.7]=man7/EVP_MAC-CMAC.pod
+DEPEND[html/man7/EVP_MAC-GMAC.html]=man7/EVP_MAC-GMAC.pod
+GENERATE[html/man7/EVP_MAC-GMAC.html]=man7/EVP_MAC-GMAC.pod
+DEPEND[man/man7/EVP_MAC-GMAC.7]=man7/EVP_MAC-GMAC.pod
+GENERATE[man/man7/EVP_MAC-GMAC.7]=man7/EVP_MAC-GMAC.pod
+DEPEND[html/man7/EVP_MAC-HMAC.html]=man7/EVP_MAC-HMAC.pod
+GENERATE[html/man7/EVP_MAC-HMAC.html]=man7/EVP_MAC-HMAC.pod
+DEPEND[man/man7/EVP_MAC-HMAC.7]=man7/EVP_MAC-HMAC.pod
+GENERATE[man/man7/EVP_MAC-HMAC.7]=man7/EVP_MAC-HMAC.pod
+DEPEND[html/man7/EVP_MAC-KMAC.html]=man7/EVP_MAC-KMAC.pod
+GENERATE[html/man7/EVP_MAC-KMAC.html]=man7/EVP_MAC-KMAC.pod
+DEPEND[man/man7/EVP_MAC-KMAC.7]=man7/EVP_MAC-KMAC.pod
+GENERATE[man/man7/EVP_MAC-KMAC.7]=man7/EVP_MAC-KMAC.pod
+DEPEND[html/man7/EVP_MAC-Poly1305.html]=man7/EVP_MAC-Poly1305.pod
+GENERATE[html/man7/EVP_MAC-Poly1305.html]=man7/EVP_MAC-Poly1305.pod
+DEPEND[man/man7/EVP_MAC-Poly1305.7]=man7/EVP_MAC-Poly1305.pod
+GENERATE[man/man7/EVP_MAC-Poly1305.7]=man7/EVP_MAC-Poly1305.pod
+DEPEND[html/man7/EVP_MAC-Siphash.html]=man7/EVP_MAC-Siphash.pod
+GENERATE[html/man7/EVP_MAC-Siphash.html]=man7/EVP_MAC-Siphash.pod
+DEPEND[man/man7/EVP_MAC-Siphash.7]=man7/EVP_MAC-Siphash.pod
+GENERATE[man/man7/EVP_MAC-Siphash.7]=man7/EVP_MAC-Siphash.pod
+DEPEND[html/man7/EVP_MD-BLAKE2.html]=man7/EVP_MD-BLAKE2.pod
+GENERATE[html/man7/EVP_MD-BLAKE2.html]=man7/EVP_MD-BLAKE2.pod
+DEPEND[man/man7/EVP_MD-BLAKE2.7]=man7/EVP_MD-BLAKE2.pod
+GENERATE[man/man7/EVP_MD-BLAKE2.7]=man7/EVP_MD-BLAKE2.pod
+DEPEND[html/man7/EVP_MD-MD2.html]=man7/EVP_MD-MD2.pod
+GENERATE[html/man7/EVP_MD-MD2.html]=man7/EVP_MD-MD2.pod
+DEPEND[man/man7/EVP_MD-MD2.7]=man7/EVP_MD-MD2.pod
+GENERATE[man/man7/EVP_MD-MD2.7]=man7/EVP_MD-MD2.pod
+DEPEND[html/man7/EVP_MD-MD4.html]=man7/EVP_MD-MD4.pod
+GENERATE[html/man7/EVP_MD-MD4.html]=man7/EVP_MD-MD4.pod
+DEPEND[man/man7/EVP_MD-MD4.7]=man7/EVP_MD-MD4.pod
+GENERATE[man/man7/EVP_MD-MD4.7]=man7/EVP_MD-MD4.pod
+DEPEND[html/man7/EVP_MD-MD5-SHA1.html]=man7/EVP_MD-MD5-SHA1.pod
+GENERATE[html/man7/EVP_MD-MD5-SHA1.html]=man7/EVP_MD-MD5-SHA1.pod
+DEPEND[man/man7/EVP_MD-MD5-SHA1.7]=man7/EVP_MD-MD5-SHA1.pod
+GENERATE[man/man7/EVP_MD-MD5-SHA1.7]=man7/EVP_MD-MD5-SHA1.pod
+DEPEND[html/man7/EVP_MD-MD5.html]=man7/EVP_MD-MD5.pod
+GENERATE[html/man7/EVP_MD-MD5.html]=man7/EVP_MD-MD5.pod
+DEPEND[man/man7/EVP_MD-MD5.7]=man7/EVP_MD-MD5.pod
+GENERATE[man/man7/EVP_MD-MD5.7]=man7/EVP_MD-MD5.pod
+DEPEND[html/man7/EVP_MD-MDC2.html]=man7/EVP_MD-MDC2.pod
+GENERATE[html/man7/EVP_MD-MDC2.html]=man7/EVP_MD-MDC2.pod
+DEPEND[man/man7/EVP_MD-MDC2.7]=man7/EVP_MD-MDC2.pod
+GENERATE[man/man7/EVP_MD-MDC2.7]=man7/EVP_MD-MDC2.pod
+DEPEND[html/man7/EVP_MD-RIPEMD160.html]=man7/EVP_MD-RIPEMD160.pod
+GENERATE[html/man7/EVP_MD-RIPEMD160.html]=man7/EVP_MD-RIPEMD160.pod
+DEPEND[man/man7/EVP_MD-RIPEMD160.7]=man7/EVP_MD-RIPEMD160.pod
+GENERATE[man/man7/EVP_MD-RIPEMD160.7]=man7/EVP_MD-RIPEMD160.pod
+DEPEND[html/man7/EVP_MD-SHA1.html]=man7/EVP_MD-SHA1.pod
+GENERATE[html/man7/EVP_MD-SHA1.html]=man7/EVP_MD-SHA1.pod
+DEPEND[man/man7/EVP_MD-SHA1.7]=man7/EVP_MD-SHA1.pod
+GENERATE[man/man7/EVP_MD-SHA1.7]=man7/EVP_MD-SHA1.pod
+DEPEND[html/man7/EVP_MD-SHA2.html]=man7/EVP_MD-SHA2.pod
+GENERATE[html/man7/EVP_MD-SHA2.html]=man7/EVP_MD-SHA2.pod
+DEPEND[man/man7/EVP_MD-SHA2.7]=man7/EVP_MD-SHA2.pod
+GENERATE[man/man7/EVP_MD-SHA2.7]=man7/EVP_MD-SHA2.pod
+DEPEND[html/man7/EVP_MD-SHA3.html]=man7/EVP_MD-SHA3.pod
+GENERATE[html/man7/EVP_MD-SHA3.html]=man7/EVP_MD-SHA3.pod
+DEPEND[man/man7/EVP_MD-SHA3.7]=man7/EVP_MD-SHA3.pod
+GENERATE[man/man7/EVP_MD-SHA3.7]=man7/EVP_MD-SHA3.pod
+DEPEND[html/man7/EVP_MD-SHAKE.html]=man7/EVP_MD-SHAKE.pod
+GENERATE[html/man7/EVP_MD-SHAKE.html]=man7/EVP_MD-SHAKE.pod
+DEPEND[man/man7/EVP_MD-SHAKE.7]=man7/EVP_MD-SHAKE.pod
+GENERATE[man/man7/EVP_MD-SHAKE.7]=man7/EVP_MD-SHAKE.pod
+DEPEND[html/man7/EVP_MD-SM3.html]=man7/EVP_MD-SM3.pod
+GENERATE[html/man7/EVP_MD-SM3.html]=man7/EVP_MD-SM3.pod
+DEPEND[man/man7/EVP_MD-SM3.7]=man7/EVP_MD-SM3.pod
+GENERATE[man/man7/EVP_MD-SM3.7]=man7/EVP_MD-SM3.pod
+DEPEND[html/man7/EVP_MD-WHIRLPOOL.html]=man7/EVP_MD-WHIRLPOOL.pod
+GENERATE[html/man7/EVP_MD-WHIRLPOOL.html]=man7/EVP_MD-WHIRLPOOL.pod
+DEPEND[man/man7/EVP_MD-WHIRLPOOL.7]=man7/EVP_MD-WHIRLPOOL.pod
+GENERATE[man/man7/EVP_MD-WHIRLPOOL.7]=man7/EVP_MD-WHIRLPOOL.pod
+DEPEND[html/man7/EVP_MD-common.html]=man7/EVP_MD-common.pod
+GENERATE[html/man7/EVP_MD-common.html]=man7/EVP_MD-common.pod
+DEPEND[man/man7/EVP_MD-common.7]=man7/EVP_MD-common.pod
+GENERATE[man/man7/EVP_MD-common.7]=man7/EVP_MD-common.pod
+DEPEND[html/man7/EVP_PKEY-DH.html]=man7/EVP_PKEY-DH.pod
+GENERATE[html/man7/EVP_PKEY-DH.html]=man7/EVP_PKEY-DH.pod
+DEPEND[man/man7/EVP_PKEY-DH.7]=man7/EVP_PKEY-DH.pod
+GENERATE[man/man7/EVP_PKEY-DH.7]=man7/EVP_PKEY-DH.pod
+DEPEND[html/man7/EVP_PKEY-DSA.html]=man7/EVP_PKEY-DSA.pod
+GENERATE[html/man7/EVP_PKEY-DSA.html]=man7/EVP_PKEY-DSA.pod
+DEPEND[man/man7/EVP_PKEY-DSA.7]=man7/EVP_PKEY-DSA.pod
+GENERATE[man/man7/EVP_PKEY-DSA.7]=man7/EVP_PKEY-DSA.pod
+DEPEND[html/man7/EVP_PKEY-EC.html]=man7/EVP_PKEY-EC.pod
+GENERATE[html/man7/EVP_PKEY-EC.html]=man7/EVP_PKEY-EC.pod
+DEPEND[man/man7/EVP_PKEY-EC.7]=man7/EVP_PKEY-EC.pod
+GENERATE[man/man7/EVP_PKEY-EC.7]=man7/EVP_PKEY-EC.pod
+DEPEND[html/man7/EVP_PKEY-FFC.html]=man7/EVP_PKEY-FFC.pod
+GENERATE[html/man7/EVP_PKEY-FFC.html]=man7/EVP_PKEY-FFC.pod
+DEPEND[man/man7/EVP_PKEY-FFC.7]=man7/EVP_PKEY-FFC.pod
+GENERATE[man/man7/EVP_PKEY-FFC.7]=man7/EVP_PKEY-FFC.pod
+DEPEND[html/man7/EVP_PKEY-HMAC.html]=man7/EVP_PKEY-HMAC.pod
+GENERATE[html/man7/EVP_PKEY-HMAC.html]=man7/EVP_PKEY-HMAC.pod
+DEPEND[man/man7/EVP_PKEY-HMAC.7]=man7/EVP_PKEY-HMAC.pod
+GENERATE[man/man7/EVP_PKEY-HMAC.7]=man7/EVP_PKEY-HMAC.pod
+DEPEND[html/man7/EVP_PKEY-RSA.html]=man7/EVP_PKEY-RSA.pod
+GENERATE[html/man7/EVP_PKEY-RSA.html]=man7/EVP_PKEY-RSA.pod
+DEPEND[man/man7/EVP_PKEY-RSA.7]=man7/EVP_PKEY-RSA.pod
+GENERATE[man/man7/EVP_PKEY-RSA.7]=man7/EVP_PKEY-RSA.pod
+DEPEND[html/man7/EVP_PKEY-SM2.html]=man7/EVP_PKEY-SM2.pod
+GENERATE[html/man7/EVP_PKEY-SM2.html]=man7/EVP_PKEY-SM2.pod
+DEPEND[man/man7/EVP_PKEY-SM2.7]=man7/EVP_PKEY-SM2.pod
+GENERATE[man/man7/EVP_PKEY-SM2.7]=man7/EVP_PKEY-SM2.pod
+DEPEND[html/man7/EVP_PKEY-X25519.html]=man7/EVP_PKEY-X25519.pod
+GENERATE[html/man7/EVP_PKEY-X25519.html]=man7/EVP_PKEY-X25519.pod
+DEPEND[man/man7/EVP_PKEY-X25519.7]=man7/EVP_PKEY-X25519.pod
+GENERATE[man/man7/EVP_PKEY-X25519.7]=man7/EVP_PKEY-X25519.pod
+DEPEND[html/man7/EVP_RAND-CTR-DRBG.html]=man7/EVP_RAND-CTR-DRBG.pod
+GENERATE[html/man7/EVP_RAND-CTR-DRBG.html]=man7/EVP_RAND-CTR-DRBG.pod
+DEPEND[man/man7/EVP_RAND-CTR-DRBG.7]=man7/EVP_RAND-CTR-DRBG.pod
+GENERATE[man/man7/EVP_RAND-CTR-DRBG.7]=man7/EVP_RAND-CTR-DRBG.pod
+DEPEND[html/man7/EVP_RAND-HASH-DRBG.html]=man7/EVP_RAND-HASH-DRBG.pod
+GENERATE[html/man7/EVP_RAND-HASH-DRBG.html]=man7/EVP_RAND-HASH-DRBG.pod
+DEPEND[man/man7/EVP_RAND-HASH-DRBG.7]=man7/EVP_RAND-HASH-DRBG.pod
+GENERATE[man/man7/EVP_RAND-HASH-DRBG.7]=man7/EVP_RAND-HASH-DRBG.pod
+DEPEND[html/man7/EVP_RAND-HMAC-DRBG.html]=man7/EVP_RAND-HMAC-DRBG.pod
+GENERATE[html/man7/EVP_RAND-HMAC-DRBG.html]=man7/EVP_RAND-HMAC-DRBG.pod
+DEPEND[man/man7/EVP_RAND-HMAC-DRBG.7]=man7/EVP_RAND-HMAC-DRBG.pod
+GENERATE[man/man7/EVP_RAND-HMAC-DRBG.7]=man7/EVP_RAND-HMAC-DRBG.pod
+DEPEND[html/man7/EVP_RAND-SEED-SRC.html]=man7/EVP_RAND-SEED-SRC.pod
+GENERATE[html/man7/EVP_RAND-SEED-SRC.html]=man7/EVP_RAND-SEED-SRC.pod
+DEPEND[man/man7/EVP_RAND-SEED-SRC.7]=man7/EVP_RAND-SEED-SRC.pod
+GENERATE[man/man7/EVP_RAND-SEED-SRC.7]=man7/EVP_RAND-SEED-SRC.pod
+DEPEND[html/man7/EVP_RAND-TEST-RAND.html]=man7/EVP_RAND-TEST-RAND.pod
+GENERATE[html/man7/EVP_RAND-TEST-RAND.html]=man7/EVP_RAND-TEST-RAND.pod
+DEPEND[man/man7/EVP_RAND-TEST-RAND.7]=man7/EVP_RAND-TEST-RAND.pod
+GENERATE[man/man7/EVP_RAND-TEST-RAND.7]=man7/EVP_RAND-TEST-RAND.pod
+DEPEND[html/man7/EVP_RAND.html]=man7/EVP_RAND.pod
+GENERATE[html/man7/EVP_RAND.html]=man7/EVP_RAND.pod
+DEPEND[man/man7/EVP_RAND.7]=man7/EVP_RAND.pod
+GENERATE[man/man7/EVP_RAND.7]=man7/EVP_RAND.pod
+DEPEND[html/man7/EVP_SIGNATURE-DSA.html]=man7/EVP_SIGNATURE-DSA.pod
+GENERATE[html/man7/EVP_SIGNATURE-DSA.html]=man7/EVP_SIGNATURE-DSA.pod
+DEPEND[man/man7/EVP_SIGNATURE-DSA.7]=man7/EVP_SIGNATURE-DSA.pod
+GENERATE[man/man7/EVP_SIGNATURE-DSA.7]=man7/EVP_SIGNATURE-DSA.pod
+DEPEND[html/man7/EVP_SIGNATURE-ECDSA.html]=man7/EVP_SIGNATURE-ECDSA.pod
+GENERATE[html/man7/EVP_SIGNATURE-ECDSA.html]=man7/EVP_SIGNATURE-ECDSA.pod
+DEPEND[man/man7/EVP_SIGNATURE-ECDSA.7]=man7/EVP_SIGNATURE-ECDSA.pod
+GENERATE[man/man7/EVP_SIGNATURE-ECDSA.7]=man7/EVP_SIGNATURE-ECDSA.pod
+DEPEND[html/man7/EVP_SIGNATURE-ED25519.html]=man7/EVP_SIGNATURE-ED25519.pod
+GENERATE[html/man7/EVP_SIGNATURE-ED25519.html]=man7/EVP_SIGNATURE-ED25519.pod
+DEPEND[man/man7/EVP_SIGNATURE-ED25519.7]=man7/EVP_SIGNATURE-ED25519.pod
+GENERATE[man/man7/EVP_SIGNATURE-ED25519.7]=man7/EVP_SIGNATURE-ED25519.pod
+DEPEND[html/man7/EVP_SIGNATURE-HMAC.html]=man7/EVP_SIGNATURE-HMAC.pod
+GENERATE[html/man7/EVP_SIGNATURE-HMAC.html]=man7/EVP_SIGNATURE-HMAC.pod
+DEPEND[man/man7/EVP_SIGNATURE-HMAC.7]=man7/EVP_SIGNATURE-HMAC.pod
+GENERATE[man/man7/EVP_SIGNATURE-HMAC.7]=man7/EVP_SIGNATURE-HMAC.pod
+DEPEND[html/man7/EVP_SIGNATURE-RSA.html]=man7/EVP_SIGNATURE-RSA.pod
+GENERATE[html/man7/EVP_SIGNATURE-RSA.html]=man7/EVP_SIGNATURE-RSA.pod
+DEPEND[man/man7/EVP_SIGNATURE-RSA.7]=man7/EVP_SIGNATURE-RSA.pod
+GENERATE[man/man7/EVP_SIGNATURE-RSA.7]=man7/EVP_SIGNATURE-RSA.pod
+DEPEND[html/man7/OSSL_PROVIDER-FIPS.html]=man7/OSSL_PROVIDER-FIPS.pod
+GENERATE[html/man7/OSSL_PROVIDER-FIPS.html]=man7/OSSL_PROVIDER-FIPS.pod
+DEPEND[man/man7/OSSL_PROVIDER-FIPS.7]=man7/OSSL_PROVIDER-FIPS.pod
+GENERATE[man/man7/OSSL_PROVIDER-FIPS.7]=man7/OSSL_PROVIDER-FIPS.pod
+DEPEND[html/man7/OSSL_PROVIDER-base.html]=man7/OSSL_PROVIDER-base.pod
+GENERATE[html/man7/OSSL_PROVIDER-base.html]=man7/OSSL_PROVIDER-base.pod
+DEPEND[man/man7/OSSL_PROVIDER-base.7]=man7/OSSL_PROVIDER-base.pod
+GENERATE[man/man7/OSSL_PROVIDER-base.7]=man7/OSSL_PROVIDER-base.pod
+DEPEND[html/man7/OSSL_PROVIDER-default.html]=man7/OSSL_PROVIDER-default.pod
+GENERATE[html/man7/OSSL_PROVIDER-default.html]=man7/OSSL_PROVIDER-default.pod
+DEPEND[man/man7/OSSL_PROVIDER-default.7]=man7/OSSL_PROVIDER-default.pod
+GENERATE[man/man7/OSSL_PROVIDER-default.7]=man7/OSSL_PROVIDER-default.pod
+DEPEND[html/man7/OSSL_PROVIDER-legacy.html]=man7/OSSL_PROVIDER-legacy.pod
+GENERATE[html/man7/OSSL_PROVIDER-legacy.html]=man7/OSSL_PROVIDER-legacy.pod
+DEPEND[man/man7/OSSL_PROVIDER-legacy.7]=man7/OSSL_PROVIDER-legacy.pod
+GENERATE[man/man7/OSSL_PROVIDER-legacy.7]=man7/OSSL_PROVIDER-legacy.pod
+DEPEND[html/man7/OSSL_PROVIDER-null.html]=man7/OSSL_PROVIDER-null.pod
+GENERATE[html/man7/OSSL_PROVIDER-null.html]=man7/OSSL_PROVIDER-null.pod
+DEPEND[man/man7/OSSL_PROVIDER-null.7]=man7/OSSL_PROVIDER-null.pod
+GENERATE[man/man7/OSSL_PROVIDER-null.7]=man7/OSSL_PROVIDER-null.pod
+DEPEND[html/man7/RAND.html]=man7/RAND.pod
+GENERATE[html/man7/RAND.html]=man7/RAND.pod
+DEPEND[man/man7/RAND.7]=man7/RAND.pod
+GENERATE[man/man7/RAND.7]=man7/RAND.pod
+DEPEND[html/man7/RSA-PSS.html]=man7/RSA-PSS.pod
+GENERATE[html/man7/RSA-PSS.html]=man7/RSA-PSS.pod
+DEPEND[man/man7/RSA-PSS.7]=man7/RSA-PSS.pod
+GENERATE[man/man7/RSA-PSS.7]=man7/RSA-PSS.pod
+DEPEND[html/man7/X25519.html]=man7/X25519.pod
+GENERATE[html/man7/X25519.html]=man7/X25519.pod
+DEPEND[man/man7/X25519.7]=man7/X25519.pod
+GENERATE[man/man7/X25519.7]=man7/X25519.pod
+DEPEND[html/man7/bio.html]=man7/bio.pod
+GENERATE[html/man7/bio.html]=man7/bio.pod
+DEPEND[man/man7/bio.7]=man7/bio.pod
+GENERATE[man/man7/bio.7]=man7/bio.pod
+DEPEND[html/man7/crypto.html]=man7/crypto.pod
+GENERATE[html/man7/crypto.html]=man7/crypto.pod
+DEPEND[man/man7/crypto.7]=man7/crypto.pod
+GENERATE[man/man7/crypto.7]=man7/crypto.pod
+DEPEND[html/man7/ct.html]=man7/ct.pod
+GENERATE[html/man7/ct.html]=man7/ct.pod
+DEPEND[man/man7/ct.7]=man7/ct.pod
+GENERATE[man/man7/ct.7]=man7/ct.pod
+DEPEND[html/man7/des_modes.html]=man7/des_modes.pod
+GENERATE[html/man7/des_modes.html]=man7/des_modes.pod
+DEPEND[man/man7/des_modes.7]=man7/des_modes.pod
+GENERATE[man/man7/des_modes.7]=man7/des_modes.pod
+DEPEND[html/man7/evp.html]=man7/evp.pod
+GENERATE[html/man7/evp.html]=man7/evp.pod
+DEPEND[man/man7/evp.7]=man7/evp.pod
+GENERATE[man/man7/evp.7]=man7/evp.pod
+DEPEND[html/man7/fips_module.html]=man7/fips_module.pod
+GENERATE[html/man7/fips_module.html]=man7/fips_module.pod
+DEPEND[man/man7/fips_module.7]=man7/fips_module.pod
+GENERATE[man/man7/fips_module.7]=man7/fips_module.pod
+DEPEND[html/man7/life_cycle-cipher.html]=man7/life_cycle-cipher.pod
+GENERATE[html/man7/life_cycle-cipher.html]=man7/life_cycle-cipher.pod
+DEPEND[man/man7/life_cycle-cipher.7]=man7/life_cycle-cipher.pod
+GENERATE[man/man7/life_cycle-cipher.7]=man7/life_cycle-cipher.pod
+DEPEND[html/man7/life_cycle-digest.html]=man7/life_cycle-digest.pod
+GENERATE[html/man7/life_cycle-digest.html]=man7/life_cycle-digest.pod
+DEPEND[man/man7/life_cycle-digest.7]=man7/life_cycle-digest.pod
+GENERATE[man/man7/life_cycle-digest.7]=man7/life_cycle-digest.pod
+DEPEND[html/man7/life_cycle-kdf.html]=man7/life_cycle-kdf.pod
+GENERATE[html/man7/life_cycle-kdf.html]=man7/life_cycle-kdf.pod
+DEPEND[man/man7/life_cycle-kdf.7]=man7/life_cycle-kdf.pod
+GENERATE[man/man7/life_cycle-kdf.7]=man7/life_cycle-kdf.pod
+DEPEND[html/man7/life_cycle-mac.html]=man7/life_cycle-mac.pod
+GENERATE[html/man7/life_cycle-mac.html]=man7/life_cycle-mac.pod
+DEPEND[man/man7/life_cycle-mac.7]=man7/life_cycle-mac.pod
+GENERATE[man/man7/life_cycle-mac.7]=man7/life_cycle-mac.pod
+DEPEND[html/man7/life_cycle-pkey.html]=man7/life_cycle-pkey.pod
+GENERATE[html/man7/life_cycle-pkey.html]=man7/life_cycle-pkey.pod
+DEPEND[man/man7/life_cycle-pkey.7]=man7/life_cycle-pkey.pod
+GENERATE[man/man7/life_cycle-pkey.7]=man7/life_cycle-pkey.pod
+DEPEND[html/man7/life_cycle-rand.html]=man7/life_cycle-rand.pod
+GENERATE[html/man7/life_cycle-rand.html]=man7/life_cycle-rand.pod
+DEPEND[man/man7/life_cycle-rand.7]=man7/life_cycle-rand.pod
+GENERATE[man/man7/life_cycle-rand.7]=man7/life_cycle-rand.pod
+DEPEND[html/man7/migration_guide.html]=man7/migration_guide.pod
+GENERATE[html/man7/migration_guide.html]=man7/migration_guide.pod
+DEPEND[man/man7/migration_guide.7]=man7/migration_guide.pod
+GENERATE[man/man7/migration_guide.7]=man7/migration_guide.pod
+DEPEND[html/man7/openssl-core.h.html]=man7/openssl-core.h.pod
+GENERATE[html/man7/openssl-core.h.html]=man7/openssl-core.h.pod
+DEPEND[man/man7/openssl-core.h.7]=man7/openssl-core.h.pod
+GENERATE[man/man7/openssl-core.h.7]=man7/openssl-core.h.pod
+DEPEND[html/man7/openssl-core_dispatch.h.html]=man7/openssl-core_dispatch.h.pod
+GENERATE[html/man7/openssl-core_dispatch.h.html]=man7/openssl-core_dispatch.h.pod
+DEPEND[man/man7/openssl-core_dispatch.h.7]=man7/openssl-core_dispatch.h.pod
+GENERATE[man/man7/openssl-core_dispatch.h.7]=man7/openssl-core_dispatch.h.pod
+DEPEND[html/man7/openssl-core_names.h.html]=man7/openssl-core_names.h.pod
+GENERATE[html/man7/openssl-core_names.h.html]=man7/openssl-core_names.h.pod
+DEPEND[man/man7/openssl-core_names.h.7]=man7/openssl-core_names.h.pod
+GENERATE[man/man7/openssl-core_names.h.7]=man7/openssl-core_names.h.pod
+DEPEND[html/man7/openssl-env.html]=man7/openssl-env.pod
+GENERATE[html/man7/openssl-env.html]=man7/openssl-env.pod
+DEPEND[man/man7/openssl-env.7]=man7/openssl-env.pod
+GENERATE[man/man7/openssl-env.7]=man7/openssl-env.pod
+DEPEND[html/man7/openssl-glossary.html]=man7/openssl-glossary.pod
+GENERATE[html/man7/openssl-glossary.html]=man7/openssl-glossary.pod
+DEPEND[man/man7/openssl-glossary.7]=man7/openssl-glossary.pod
+GENERATE[man/man7/openssl-glossary.7]=man7/openssl-glossary.pod
+DEPEND[html/man7/openssl-threads.html]=man7/openssl-threads.pod
+GENERATE[html/man7/openssl-threads.html]=man7/openssl-threads.pod
+DEPEND[man/man7/openssl-threads.7]=man7/openssl-threads.pod
+GENERATE[man/man7/openssl-threads.7]=man7/openssl-threads.pod
+DEPEND[html/man7/openssl_user_macros.html]=man7/openssl_user_macros.pod
+GENERATE[html/man7/openssl_user_macros.html]=man7/openssl_user_macros.pod
+DEPEND[man/man7/openssl_user_macros.7]=man7/openssl_user_macros.pod
+GENERATE[man/man7/openssl_user_macros.7]=man7/openssl_user_macros.pod
+DEPEND[man7/openssl_user_macros.pod]{pod}=man7/openssl_user_macros.pod.in
+GENERATE[man7/openssl_user_macros.pod]=man7/openssl_user_macros.pod.in
+DEPEND[html/man7/ossl_store-file.html]=man7/ossl_store-file.pod
+GENERATE[html/man7/ossl_store-file.html]=man7/ossl_store-file.pod
+DEPEND[man/man7/ossl_store-file.7]=man7/ossl_store-file.pod
+GENERATE[man/man7/ossl_store-file.7]=man7/ossl_store-file.pod
+DEPEND[html/man7/ossl_store.html]=man7/ossl_store.pod
+GENERATE[html/man7/ossl_store.html]=man7/ossl_store.pod
+DEPEND[man/man7/ossl_store.7]=man7/ossl_store.pod
+GENERATE[man/man7/ossl_store.7]=man7/ossl_store.pod
+DEPEND[html/man7/passphrase-encoding.html]=man7/passphrase-encoding.pod
+GENERATE[html/man7/passphrase-encoding.html]=man7/passphrase-encoding.pod
+DEPEND[man/man7/passphrase-encoding.7]=man7/passphrase-encoding.pod
+GENERATE[man/man7/passphrase-encoding.7]=man7/passphrase-encoding.pod
+DEPEND[html/man7/property.html]=man7/property.pod
+GENERATE[html/man7/property.html]=man7/property.pod
+DEPEND[man/man7/property.7]=man7/property.pod
+GENERATE[man/man7/property.7]=man7/property.pod
+DEPEND[html/man7/provider-asym_cipher.html]=man7/provider-asym_cipher.pod
+GENERATE[html/man7/provider-asym_cipher.html]=man7/provider-asym_cipher.pod
+DEPEND[man/man7/provider-asym_cipher.7]=man7/provider-asym_cipher.pod
+GENERATE[man/man7/provider-asym_cipher.7]=man7/provider-asym_cipher.pod
+DEPEND[html/man7/provider-base.html]=man7/provider-base.pod
+GENERATE[html/man7/provider-base.html]=man7/provider-base.pod
+DEPEND[man/man7/provider-base.7]=man7/provider-base.pod
+GENERATE[man/man7/provider-base.7]=man7/provider-base.pod
+DEPEND[html/man7/provider-cipher.html]=man7/provider-cipher.pod
+GENERATE[html/man7/provider-cipher.html]=man7/provider-cipher.pod
+DEPEND[man/man7/provider-cipher.7]=man7/provider-cipher.pod
+GENERATE[man/man7/provider-cipher.7]=man7/provider-cipher.pod
+DEPEND[html/man7/provider-decoder.html]=man7/provider-decoder.pod
+GENERATE[html/man7/provider-decoder.html]=man7/provider-decoder.pod
+DEPEND[man/man7/provider-decoder.7]=man7/provider-decoder.pod
+GENERATE[man/man7/provider-decoder.7]=man7/provider-decoder.pod
+DEPEND[html/man7/provider-digest.html]=man7/provider-digest.pod
+GENERATE[html/man7/provider-digest.html]=man7/provider-digest.pod
+DEPEND[man/man7/provider-digest.7]=man7/provider-digest.pod
+GENERATE[man/man7/provider-digest.7]=man7/provider-digest.pod
+DEPEND[html/man7/provider-encoder.html]=man7/provider-encoder.pod
+GENERATE[html/man7/provider-encoder.html]=man7/provider-encoder.pod
+DEPEND[man/man7/provider-encoder.7]=man7/provider-encoder.pod
+GENERATE[man/man7/provider-encoder.7]=man7/provider-encoder.pod
+DEPEND[html/man7/provider-kdf.html]=man7/provider-kdf.pod
+GENERATE[html/man7/provider-kdf.html]=man7/provider-kdf.pod
+DEPEND[man/man7/provider-kdf.7]=man7/provider-kdf.pod
+GENERATE[man/man7/provider-kdf.7]=man7/provider-kdf.pod
+DEPEND[html/man7/provider-kem.html]=man7/provider-kem.pod
+GENERATE[html/man7/provider-kem.html]=man7/provider-kem.pod
+DEPEND[man/man7/provider-kem.7]=man7/provider-kem.pod
+GENERATE[man/man7/provider-kem.7]=man7/provider-kem.pod
+DEPEND[html/man7/provider-keyexch.html]=man7/provider-keyexch.pod
+GENERATE[html/man7/provider-keyexch.html]=man7/provider-keyexch.pod
+DEPEND[man/man7/provider-keyexch.7]=man7/provider-keyexch.pod
+GENERATE[man/man7/provider-keyexch.7]=man7/provider-keyexch.pod
+DEPEND[html/man7/provider-keymgmt.html]=man7/provider-keymgmt.pod
+GENERATE[html/man7/provider-keymgmt.html]=man7/provider-keymgmt.pod
+DEPEND[man/man7/provider-keymgmt.7]=man7/provider-keymgmt.pod
+GENERATE[man/man7/provider-keymgmt.7]=man7/provider-keymgmt.pod
+DEPEND[html/man7/provider-mac.html]=man7/provider-mac.pod
+GENERATE[html/man7/provider-mac.html]=man7/provider-mac.pod
+DEPEND[man/man7/provider-mac.7]=man7/provider-mac.pod
+GENERATE[man/man7/provider-mac.7]=man7/provider-mac.pod
+DEPEND[html/man7/provider-object.html]=man7/provider-object.pod
+GENERATE[html/man7/provider-object.html]=man7/provider-object.pod
+DEPEND[man/man7/provider-object.7]=man7/provider-object.pod
+GENERATE[man/man7/provider-object.7]=man7/provider-object.pod
+DEPEND[html/man7/provider-rand.html]=man7/provider-rand.pod
+GENERATE[html/man7/provider-rand.html]=man7/provider-rand.pod
+DEPEND[man/man7/provider-rand.7]=man7/provider-rand.pod
+GENERATE[man/man7/provider-rand.7]=man7/provider-rand.pod
+DEPEND[html/man7/provider-signature.html]=man7/provider-signature.pod
+GENERATE[html/man7/provider-signature.html]=man7/provider-signature.pod
+DEPEND[man/man7/provider-signature.7]=man7/provider-signature.pod
+GENERATE[man/man7/provider-signature.7]=man7/provider-signature.pod
+DEPEND[html/man7/provider-storemgmt.html]=man7/provider-storemgmt.pod
+GENERATE[html/man7/provider-storemgmt.html]=man7/provider-storemgmt.pod
+DEPEND[man/man7/provider-storemgmt.7]=man7/provider-storemgmt.pod
+GENERATE[man/man7/provider-storemgmt.7]=man7/provider-storemgmt.pod
+DEPEND[html/man7/provider.html]=man7/provider.pod
+GENERATE[html/man7/provider.html]=man7/provider.pod
+DEPEND[man/man7/provider.7]=man7/provider.pod
+GENERATE[man/man7/provider.7]=man7/provider.pod
+DEPEND[html/man7/proxy-certificates.html]=man7/proxy-certificates.pod
+GENERATE[html/man7/proxy-certificates.html]=man7/proxy-certificates.pod
+DEPEND[man/man7/proxy-certificates.7]=man7/proxy-certificates.pod
+GENERATE[man/man7/proxy-certificates.7]=man7/proxy-certificates.pod
+DEPEND[html/man7/ssl.html]=man7/ssl.pod
+GENERATE[html/man7/ssl.html]=man7/ssl.pod
+DEPEND[man/man7/ssl.7]=man7/ssl.pod
+GENERATE[man/man7/ssl.7]=man7/ssl.pod
+DEPEND[html/man7/x509.html]=man7/x509.pod
+GENERATE[html/man7/x509.html]=man7/x509.pod
+DEPEND[man/man7/x509.7]=man7/x509.pod
+GENERATE[man/man7/x509.7]=man7/x509.pod
+IMAGEDOCS[man7]=man7/img/cipher.png \
+man7/img/digest.png \
+man7/img/kdf.png \
+man7/img/mac.png \
+man7/img/pkey.png \
+man7/img/rand.png
+HTMLDOCS[man7]=html/man7/EVP_ASYM_CIPHER-RSA.html \
+html/man7/EVP_ASYM_CIPHER-SM2.html \
+html/man7/EVP_CIPHER-AES.html \
+html/man7/EVP_CIPHER-ARIA.html \
+html/man7/EVP_CIPHER-BLOWFISH.html \
+html/man7/EVP_CIPHER-CAMELLIA.html \
+html/man7/EVP_CIPHER-CAST.html \
+html/man7/EVP_CIPHER-CHACHA.html \
+html/man7/EVP_CIPHER-DES.html \
+html/man7/EVP_CIPHER-IDEA.html \
+html/man7/EVP_CIPHER-RC2.html \
+html/man7/EVP_CIPHER-RC4.html \
+html/man7/EVP_CIPHER-RC5.html \
+html/man7/EVP_CIPHER-SEED.html \
+html/man7/EVP_CIPHER-SM4.html \
+html/man7/EVP_KDF-HKDF.html \
+html/man7/EVP_KDF-KB.html \
+html/man7/EVP_KDF-KRB5KDF.html \
+html/man7/EVP_KDF-PBKDF1.html \
+html/man7/EVP_KDF-PBKDF2.html \
+html/man7/EVP_KDF-PKCS12KDF.html \
+html/man7/EVP_KDF-SCRYPT.html \
+html/man7/EVP_KDF-SS.html \
+html/man7/EVP_KDF-SSHKDF.html \
+html/man7/EVP_KDF-TLS13_KDF.html \
+html/man7/EVP_KDF-TLS1_PRF.html \
+html/man7/EVP_KDF-X942-ASN1.html \
+html/man7/EVP_KDF-X942-CONCAT.html \
+html/man7/EVP_KDF-X963.html \
+html/man7/EVP_KEM-RSA.html \
+html/man7/EVP_KEYEXCH-DH.html \
+html/man7/EVP_KEYEXCH-ECDH.html \
+html/man7/EVP_KEYEXCH-X25519.html \
+html/man7/EVP_MAC-BLAKE2.html \
+html/man7/EVP_MAC-CMAC.html \
+html/man7/EVP_MAC-GMAC.html \
+html/man7/EVP_MAC-HMAC.html \
+html/man7/EVP_MAC-KMAC.html \
+html/man7/EVP_MAC-Poly1305.html \
+html/man7/EVP_MAC-Siphash.html \
+html/man7/EVP_MD-BLAKE2.html \
+html/man7/EVP_MD-MD2.html \
+html/man7/EVP_MD-MD4.html \
+html/man7/EVP_MD-MD5-SHA1.html \
+html/man7/EVP_MD-MD5.html \
+html/man7/EVP_MD-MDC2.html \
+html/man7/EVP_MD-RIPEMD160.html \
+html/man7/EVP_MD-SHA1.html \
+html/man7/EVP_MD-SHA2.html \
+html/man7/EVP_MD-SHA3.html \
+html/man7/EVP_MD-SHAKE.html \
+html/man7/EVP_MD-SM3.html \
+html/man7/EVP_MD-WHIRLPOOL.html \
+html/man7/EVP_MD-common.html \
+html/man7/EVP_PKEY-DH.html \
+html/man7/EVP_PKEY-DSA.html \
+html/man7/EVP_PKEY-EC.html \
+html/man7/EVP_PKEY-FFC.html \
+html/man7/EVP_PKEY-HMAC.html \
+html/man7/EVP_PKEY-RSA.html \
+html/man7/EVP_PKEY-SM2.html \
+html/man7/EVP_PKEY-X25519.html \
+html/man7/EVP_RAND-CTR-DRBG.html \
+html/man7/EVP_RAND-HASH-DRBG.html \
+html/man7/EVP_RAND-HMAC-DRBG.html \
+html/man7/EVP_RAND-SEED-SRC.html \
+html/man7/EVP_RAND-TEST-RAND.html \
+html/man7/EVP_RAND.html \
+html/man7/EVP_SIGNATURE-DSA.html \
+html/man7/EVP_SIGNATURE-ECDSA.html \
+html/man7/EVP_SIGNATURE-ED25519.html \
+html/man7/EVP_SIGNATURE-HMAC.html \
+html/man7/EVP_SIGNATURE-RSA.html \
+html/man7/OSSL_PROVIDER-FIPS.html \
+html/man7/OSSL_PROVIDER-base.html \
+html/man7/OSSL_PROVIDER-default.html \
+html/man7/OSSL_PROVIDER-legacy.html \
+html/man7/OSSL_PROVIDER-null.html \
+html/man7/RAND.html \
+html/man7/RSA-PSS.html \
+html/man7/X25519.html \
+html/man7/bio.html \
+html/man7/crypto.html \
+html/man7/ct.html \
+html/man7/des_modes.html \
+html/man7/evp.html \
+html/man7/fips_module.html \
+html/man7/life_cycle-cipher.html \
+html/man7/life_cycle-digest.html \
+html/man7/life_cycle-kdf.html \
+html/man7/life_cycle-mac.html \
+html/man7/life_cycle-pkey.html \
+html/man7/life_cycle-rand.html \
+html/man7/migration_guide.html \
+html/man7/openssl-core.h.html \
+html/man7/openssl-core_dispatch.h.html \
+html/man7/openssl-core_names.h.html \
+html/man7/openssl-env.html \
+html/man7/openssl-glossary.html \
+html/man7/openssl-threads.html \
+html/man7/openssl_user_macros.html \
+html/man7/ossl_store-file.html \
+html/man7/ossl_store.html \
+html/man7/passphrase-encoding.html \
+html/man7/property.html \
+html/man7/provider-asym_cipher.html \
+html/man7/provider-base.html \
+html/man7/provider-cipher.html \
+html/man7/provider-decoder.html \
+html/man7/provider-digest.html \
+html/man7/provider-encoder.html \
+html/man7/provider-kdf.html \
+html/man7/provider-kem.html \
+html/man7/provider-keyexch.html \
+html/man7/provider-keymgmt.html \
+html/man7/provider-mac.html \
+html/man7/provider-object.html \
+html/man7/provider-rand.html \
+html/man7/provider-signature.html \
+html/man7/provider-storemgmt.html \
+html/man7/provider.html \
+html/man7/proxy-certificates.html \
+html/man7/ssl.html \
+html/man7/x509.html
+MANDOCS[man7]=man/man7/EVP_ASYM_CIPHER-RSA.7 \
+man/man7/EVP_ASYM_CIPHER-SM2.7 \
+man/man7/EVP_CIPHER-AES.7 \
+man/man7/EVP_CIPHER-ARIA.7 \
+man/man7/EVP_CIPHER-BLOWFISH.7 \
+man/man7/EVP_CIPHER-CAMELLIA.7 \
+man/man7/EVP_CIPHER-CAST.7 \
+man/man7/EVP_CIPHER-CHACHA.7 \
+man/man7/EVP_CIPHER-DES.7 \
+man/man7/EVP_CIPHER-IDEA.7 \
+man/man7/EVP_CIPHER-RC2.7 \
+man/man7/EVP_CIPHER-RC4.7 \
+man/man7/EVP_CIPHER-RC5.7 \
+man/man7/EVP_CIPHER-SEED.7 \
+man/man7/EVP_CIPHER-SM4.7 \
+man/man7/EVP_KDF-HKDF.7 \
+man/man7/EVP_KDF-KB.7 \
+man/man7/EVP_KDF-KRB5KDF.7 \
+man/man7/EVP_KDF-PBKDF1.7 \
+man/man7/EVP_KDF-PBKDF2.7 \
+man/man7/EVP_KDF-PKCS12KDF.7 \
+man/man7/EVP_KDF-SCRYPT.7 \
+man/man7/EVP_KDF-SS.7 \
+man/man7/EVP_KDF-SSHKDF.7 \
+man/man7/EVP_KDF-TLS13_KDF.7 \
+man/man7/EVP_KDF-TLS1_PRF.7 \
+man/man7/EVP_KDF-X942-ASN1.7 \
+man/man7/EVP_KDF-X942-CONCAT.7 \
+man/man7/EVP_KDF-X963.7 \
+man/man7/EVP_KEM-RSA.7 \
+man/man7/EVP_KEYEXCH-DH.7 \
+man/man7/EVP_KEYEXCH-ECDH.7 \
+man/man7/EVP_KEYEXCH-X25519.7 \
+man/man7/EVP_MAC-BLAKE2.7 \
+man/man7/EVP_MAC-CMAC.7 \
+man/man7/EVP_MAC-GMAC.7 \
+man/man7/EVP_MAC-HMAC.7 \
+man/man7/EVP_MAC-KMAC.7 \
+man/man7/EVP_MAC-Poly1305.7 \
+man/man7/EVP_MAC-Siphash.7 \
+man/man7/EVP_MD-BLAKE2.7 \
+man/man7/EVP_MD-MD2.7 \
+man/man7/EVP_MD-MD4.7 \
+man/man7/EVP_MD-MD5-SHA1.7 \
+man/man7/EVP_MD-MD5.7 \
+man/man7/EVP_MD-MDC2.7 \
+man/man7/EVP_MD-RIPEMD160.7 \
+man/man7/EVP_MD-SHA1.7 \
+man/man7/EVP_MD-SHA2.7 \
+man/man7/EVP_MD-SHA3.7 \
+man/man7/EVP_MD-SHAKE.7 \
+man/man7/EVP_MD-SM3.7 \
+man/man7/EVP_MD-WHIRLPOOL.7 \
+man/man7/EVP_MD-common.7 \
+man/man7/EVP_PKEY-DH.7 \
+man/man7/EVP_PKEY-DSA.7 \
+man/man7/EVP_PKEY-EC.7 \
+man/man7/EVP_PKEY-FFC.7 \
+man/man7/EVP_PKEY-HMAC.7 \
+man/man7/EVP_PKEY-RSA.7 \
+man/man7/EVP_PKEY-SM2.7 \
+man/man7/EVP_PKEY-X25519.7 \
+man/man7/EVP_RAND-CTR-DRBG.7 \
+man/man7/EVP_RAND-HASH-DRBG.7 \
+man/man7/EVP_RAND-HMAC-DRBG.7 \
+man/man7/EVP_RAND-SEED-SRC.7 \
+man/man7/EVP_RAND-TEST-RAND.7 \
+man/man7/EVP_RAND.7 \
+man/man7/EVP_SIGNATURE-DSA.7 \
+man/man7/EVP_SIGNATURE-ECDSA.7 \
+man/man7/EVP_SIGNATURE-ED25519.7 \
+man/man7/EVP_SIGNATURE-HMAC.7 \
+man/man7/EVP_SIGNATURE-RSA.7 \
+man/man7/OSSL_PROVIDER-FIPS.7 \
+man/man7/OSSL_PROVIDER-base.7 \
+man/man7/OSSL_PROVIDER-default.7 \
+man/man7/OSSL_PROVIDER-legacy.7 \
+man/man7/OSSL_PROVIDER-null.7 \
+man/man7/RAND.7 \
+man/man7/RSA-PSS.7 \
+man/man7/X25519.7 \
+man/man7/bio.7 \
+man/man7/crypto.7 \
+man/man7/ct.7 \
+man/man7/des_modes.7 \
+man/man7/evp.7 \
+man/man7/fips_module.7 \
+man/man7/life_cycle-cipher.7 \
+man/man7/life_cycle-digest.7 \
+man/man7/life_cycle-kdf.7 \
+man/man7/life_cycle-mac.7 \
+man/man7/life_cycle-pkey.7 \
+man/man7/life_cycle-rand.7 \
+man/man7/migration_guide.7 \
+man/man7/openssl-core.h.7 \
+man/man7/openssl-core_dispatch.h.7 \
+man/man7/openssl-core_names.h.7 \
+man/man7/openssl-env.7 \
+man/man7/openssl-glossary.7 \
+man/man7/openssl-threads.7 \
+man/man7/openssl_user_macros.7 \
+man/man7/ossl_store-file.7 \
+man/man7/ossl_store.7 \
+man/man7/passphrase-encoding.7 \
+man/man7/property.7 \
+man/man7/provider-asym_cipher.7 \
+man/man7/provider-base.7 \
+man/man7/provider-cipher.7 \
+man/man7/provider-decoder.7 \
+man/man7/provider-digest.7 \
+man/man7/provider-encoder.7 \
+man/man7/provider-kdf.7 \
+man/man7/provider-kem.7 \
+man/man7/provider-keyexch.7 \
+man/man7/provider-keymgmt.7 \
+man/man7/provider-mac.7 \
+man/man7/provider-object.7 \
+man/man7/provider-rand.7 \
+man/man7/provider-signature.7 \
+man/man7/provider-storemgmt.7 \
+man/man7/provider.7 \
+man/man7/proxy-certificates.7 \
+man/man7/ssl.7 \
+man/man7/x509.7
+
diff --git a/doc/build.info.in b/doc/build.info.in
new file mode 100644
index 000000000000..e8dae7058a6e
--- /dev/null
+++ b/doc/build.info.in
@@ -0,0 +1,80 @@
+SUBDIRS = man1
+
+{-
+ use File::Spec::Functions qw(:DEFAULT abs2rel rel2abs);
+ use File::Basename;
+
+ my $sourcedir = catdir($config{sourcedir}, 'doc');
+
+ foreach my $section ((1, 3, 5, 7)) {
+ my @imagefiles = ();
+ my @htmlfiles = ();
+ my @manfiles = ();
+ my %pngfiles =
+ map { $_ => 1 } glob catfile($sourcedir, "man$section", "img", "*.png");
+ my %podfiles =
+ map { $_ => 1 } glob catfile($sourcedir, "man$section", "*.pod");
+ my %podinfiles =
+ map { $_ => 1 } glob catfile($sourcedir, "man$section", "*.pod.in");
+
+ foreach (keys %podinfiles) {
+ (my $p = $_) =~ s|\.in$||i;
+ $podfiles{$p} = 1;
+ }
+
+ foreach my $p (sort keys %podfiles) {
+ my $podfile = abs2rel($p, $sourcedir);
+ my $podname = basename($podfile, '.pod');
+ my $podinfile = $podinfiles{"$p.in"} ? "$podfile.in" : undef;
+
+ my $podname = basename($podfile, ".pod");
+
+ my $htmlfile = abs2rel(catfile($buildtop, "doc", "html", "man$section",
+ "$podname.html"),
+ catdir($buildtop, "doc"));
+ my $manfile = abs2rel(catfile($buildtop, "doc", "man", "man$section",
+ "$podname.$section"),
+ catdir($buildtop, "doc"));
+
+ # The build.info format requires file specs to be in Unix format.
+ # Especially, since VMS file specs use [ and ], the build.info parser
+ # will otherwise get terribly confused.
+ if ($^O eq 'VMS') {
+ $htmlfile = VMS::Filespec::unixify($htmlfile);
+ $manfile = VMS::Filespec::unixify($manfile);
+ $podfile = VMS::Filespec::unixify($podfile);
+ $podinfile = VMS::Filespec::unixify($podinfile)
+ if defined $podinfile;
+ } elsif ($^O eq 'MSWin32') {
+ $htmlfile =~ s|\\|/|g;
+ $manfile =~ s|\\|/|g;
+ $podfile =~ s|\\|/|g;
+ $podinfile =~ s|\\|/|g
+ if defined $podinfile;
+ }
+ push @htmlfiles, $htmlfile;
+ push @manfiles, $manfile;
+ $OUT .= << "_____";
+DEPEND[$htmlfile]=$podfile
+GENERATE[$htmlfile]=$podfile
+DEPEND[$manfile]=$podfile
+GENERATE[$manfile]=$podfile
+_____
+ $OUT .= << "_____" if $podinfile;
+DEPEND[$podfile]{pod}=$podinfile
+GENERATE[$podfile]=$podinfile
+_____
+ }
+
+ foreach my $p (sort keys %pngfiles) {
+ my $relpath = abs2rel($p, $sourcedir);
+ my $imagefile = abs2rel(catfile($buildtop, "doc", "$relpath"),
+ catdir($buildtop, "doc"));
+ push @imagefiles, $imagefile;
+ }
+
+ $OUT .= "IMAGEDOCS[man$section]=" . join(" \\\n", @imagefiles) . "\n";
+ $OUT .= "HTMLDOCS[man$section]=" . join(" \\\n", @htmlfiles) . "\n";
+ $OUT .= "MANDOCS[man$section]=" . join(" \\\n", @manfiles) . "\n";
+ }
+ -}
diff --git a/doc/fingerprints.txt b/doc/fingerprints.txt
index 3604fbdc658c..4f95f2beaec8 100644
--- a/doc/fingerprints.txt
+++ b/doc/fingerprints.txt
@@ -12,23 +12,14 @@ in the file named openssl-1.0.1h.tar.gz.asc.
The following is the list of fingerprints for the keys that are
currently in use to sign OpenSSL distributions:
-pub 4096R/7DF9EE8C 2014-10-04
- Key fingerprint = 7953 AC1F BC3D C8B3 B292 393E D5E9 E43F 7DF9 EE8C
-uid Richard Levitte <richard@opensslfoundation.com>
-uid Richard Levitte <levitte@openssl.org>
-uid Richard Levitte <richard@openssl.com>
+Richard Levitte:
+7953 AC1F BC3D C8B3 B292 393E D5E9 E43F 7DF9 EE8C
-pub 2048R/0E604491 2013-04-30
- Key fingerprint = 8657 ABB2 60F0 56B1 E519 0839 D9C4 D26D 0E60 4491
-uid Matt Caswell <matt@openssl.org>
-uid Matt Caswell <frodo@baggins.org>
+Matt Caswell:
+8657 ABB2 60F0 56B1 E519 0839 D9C4 D26D 0E60 4491
-pub rsa4096 2021-02-14
- B7C1 C143 60F3 53A3 6862 E4D5 231C 84CD DCC6 9C45
-uid Paul Dale <pauli@openssl.org>
+Paul Dale:
+B7C1 C143 60F3 53A3 6862 E4D5 231C 84CD DCC6 9C45
-pub rsa4096 2021-07-16
- A21F AB74 B008 8AA3 6115 2586 B8EF 1A6B A9DA 2D5C
-uid Tomáš Mráz <tm@t8m.info>
-uid Tomáš Mráz <tomas@arleto.cz>
-uid Tomáš Mráz <tomas@openssl.org>
+Tomáš Mráz:
+A21F AB74 B008 8AA3 6115 2586 B8EF 1A6B A9DA 2D5C
diff --git a/doc/images/openssl.svg b/doc/images/openssl.svg
new file mode 100644
index 000000000000..9cd6794fbdcf
--- /dev/null
+++ b/doc/images/openssl.svg
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ id="svg2"
+ viewBox="0 0 973.70528 248.96588"
+ height="70.263748mm"
+ width="274.80124mm">
+ <defs
+ id="defs4" />
+ <g
+ transform="translate(60.758696,-843.33549)"
+ id="layer1">
+ <text
+ id="text3336"
+ y="1012.3623"
+ x="3.8487569e-06"
+ style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ xml:space="preserve"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:180px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'"
+ y="1012.3623"
+ x="3.8487569e-06"
+ id="tspan3338"><tspan
+ id="tspan3340"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:180px;font-family:sans-serif;-inkscape-font-specification:sans-serif;fill:#480e0c;fill-opacity:1">Open</tspan>SSL</tspan></text>
+ <text
+ id="text817"
+ y="1049.0681"
+ x="176.75166"
+ style="font-style:normal;font-weight:normal;font-size:17.49999619px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.93749976"
+ xml:space="preserve"><tspan
+ style="font-size:37.49998856px;stroke-width:0.93749976"
+ y="1049.0681"
+ x="176.75166"
+ id="tspan815">Cryptography and SSL/TLS Toolkit</tspan></text>
+ </g>
+</svg>
diff --git a/doc/internal/man3/OPENSSL_SA.pod b/doc/internal/man3/OPENSSL_SA.pod
new file mode 100644
index 000000000000..8124003d77a6
--- /dev/null
+++ b/doc/internal/man3/OPENSSL_SA.pod
@@ -0,0 +1,131 @@
+=pod
+
+=head1 NAME
+
+OPENSSL_SA, ossl_sa_TYPE_new, ossl_sa_TYPE_free,
+ossl_sa_TYPE_free_leaves, ossl_sa_TYPE_num, ossl_sa_TYPE_doall,
+ossl_sa_TYPE_doall_arg, ossl_sa_TYPE_get, ossl_sa_TYPE_set
+- sparse array container
+
+=head1 SYNOPSIS
+
+ #include "crypto/sparse_array.h"
+
+ typedef struct sparse_array_st OPENSSL_SA;
+
+ SPARSE_ARRAY_OF(TYPE)
+ DEFINE_SPARSE_ARRAY_OF(TYPE)
+
+ SPARSE_ARRAY_OF(TYPE) *ossl_sa_TYPE_new(void);
+ void ossl_sa_TYPE_free(const SPARSE_ARRAY_OF(TYPE) *sa);
+ void ossl_sa_TYPE_free_leaves(const SPARSE_ARRAY_OF(TYPE) *sa);
+ size_t ossl_sa_TYPE_num(const SPARSE_ARRAY_OF(TYPE) *sa);
+ void ossl_sa_TYPE_doall(const OPENSSL_SA *sa, void (*leaf)(ossl_uintmax_t,
+ void *));
+ void ossl_sa_TYPE_doall_arg(const OPENSSL_SA *sa,
+ void (*leaf)(ossl_uintmax_t, void *, void *),
+ void *arg);
+ TYPE *ossl_sa_TYPE_get(const SPARSE_ARRAY_OF(TYPE) *sa, ossl_uintmax_t idx);
+ int ossl_sa_TYPE_set(SPARSE_ARRAY_OF(TYPE) *sa, ossl_uintmax_t idx,
+ TYPE *value);
+
+=head1 DESCRIPTION
+
+=begin comment
+
+POD is pretty good at recognising function names and making them appropriately
+bold... however, when part of the function name is variable, we have to help
+the processor along
+
+=end comment
+
+SPARSE_ARRAY_OF() returns the name for a sparse array of the specified
+B<I<TYPE>>. DEFINE_SPARSE_ARRAY_OF() creates set of functions for a sparse
+array of B<I<TYPE>>. This will mean that a pointer to type B<I<TYPE>>
+is stored in each element of a sparse array, the type is referenced by
+B<SPARSE_ARRAY_OF>(B<I<TYPE>>) and each function name begins with
+B<ossl_sa_I<TYPE>_>. For example:
+
+ TYPE *ossl_sa_TYPE_get(SPARSE_ARRAY_OF(TYPE) *sa, ossl_uintmax_t idx);
+
+B<ossl_sa_I<TYPE>_num>() returns the number of elements in I<sa> or 0 if I<sa>
+is NULL.
+
+B<ossl_sa_I<TYPE>_get>() returns element I<idx> in I<sa>, where I<idx> starts
+at zero. If I<idx> refers to a value that has not been set then NULL is
+returned.
+
+B<ossl_sa_I<TYPE>_set>() sets element I<idx> in I<sa> to I<value>, where I<idx>
+starts at zero. The sparse array will be resized as required.
+
+B<ossl_sa_I<TYPE>_new>() allocates a new empty sparse array.
+
+B<ossl_sa_I<TYPE>_free>() frees up the I<sa> structure. It does I<not> free up any
+elements of I<sa>. After this call I<sa> is no longer valid.
+
+B<ossl_sa_I<TYPE>_free_leaves>() frees up the I<sa> structure and all of its
+elements. After this call I<sa> is no longer valid.
+
+B<ossl_sa_I<TYPE>_doall>() calls the function I<leaf> for each element in I<sa>
+in ascending index order. The index position, within the sparse array,
+of each item is passed as the first argument to the leaf function and a
+pointer to the associated value is passed as the second argument.
+
+B<ossl_sa_I<TYPE>_doall_arg>() calls the function I<leaf> for each element in
+I<sa> in ascending index order. The index position, within the sparse
+array, of each item is passed as the first argument to the leaf function,
+a pointer to the associated value is passed as the second argument and
+the third argument is the user supplied I<arg>.
+
+
+=head1 NOTES
+
+Sparse arrays are an internal data structure and should B<not> be used by user
+applications.
+
+Care should be taken when accessing sparse arrays in multi-threaded
+environments. The B<ossl_sa_I<TYPE>_set>() operation can cause the internal
+structure of the sparse array to change which causes race conditions if the
+sparse array is accessed in a different thread.
+
+SPARSE_ARRAY_OF() and DEFINE_SPARSE_ARRAY_OF() are implemented as macros.
+
+The underlying utility B<OPENSSL_SA_> API should not be used directly. It
+defines these functions: OPENSSL_SA_doall, OPENSSL_SA_doall_arg,
+OPENSSL_SA_free, OPENSSL_SA_free_leaves, OPENSSL_SA_get, OPENSSL_SA_new,
+OPENSSL_SA_num and OPENSSL_SA_set.
+
+=head1 RETURN VALUES
+
+B<ossl_sa_I<TYPE>_num>() returns the number of elements in the sparse array or
+B<0> if the passed sparse array is NULL.
+
+B<ossl_sa_I<TYPE>_get>() returns a pointer to a sparse array element or NULL if
+the element has not be set.
+
+B<ossl_sa_I<TYPE>_set>() return B<1> on success and B<0> on error. In the latter
+case, the elements of the sparse array remain unchanged, although the internal
+structures might have.
+
+B<ossl_sa_I<TYPE>_new>() returns an empty sparse array or NULL if an error
+occurs.
+
+B<ossl_sa_I<TYPE>_doall>(), B<ossl_sa_I<TYPE>_doall_arg>(),
+B<ossl_sa_I<TYPE>_free>() and B<ossl_sa_I<TYPE>_free_leaves>()
+do not return values.
+
+=head1 HISTORY
+
+This functionality was added to OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. Copyright
+(c) 2019, Oracle and/or its affiliates. All rights reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use this
+file except in compliance with the License. You can obtain a copy in the file
+LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/OPTIONS.pod b/doc/internal/man3/OPTIONS.pod
new file mode 100644
index 000000000000..90593ca46f6f
--- /dev/null
+++ b/doc/internal/man3/OPTIONS.pod
@@ -0,0 +1,343 @@
+=pod
+
+=head1 NAME
+
+OPTIONS, OPT_PAIR, OPT_COMMON, OPT_ERR, OPT_EOF, OPT_HELP,
+opt_init, opt_progname, opt_appname, opt_getprog, opt_help,
+opt_begin, opt_next, opt_flag, opt_arg, opt_unknown, opt_cipher,
+opt_cipher_any, opt_cipher_silent, opt_md,
+opt_int, opt_int_arg, opt_long, opt_ulong, opt_intmax, opt_uintmax,
+opt_format, opt_isdir, opt_string, opt_pair,
+opt_num_rest, opt_rest, opt_legacy_okay
+- Option parsing for commands and tests
+
+=head1 SYNOPSIS
+
+ #include "opt.h"
+
+ typedef struct { ... } OPTIONS;
+ typedef struct { ... } OPT_PAIR;
+ #define OPT_COMMON
+ #define OPT_ERR
+ #define OPT_EOF
+ #define OPT_HELP
+
+ char *opt_init(int argc, char **argv, const OPTIONS *o);
+ char *opt_progname(const char *argv0);
+ char *opt_appname(const char *argv0);
+ char *opt_getprog(void);
+ void opt_help(const OPTIONS *list);
+
+ void opt_begin(void);
+ int opt_next(void);
+ char *opt_flag(void);
+ char *opt_arg(void);
+ char *opt_unknown(void);
+ int opt_cipher(const char *name, EVP_CIPHER **cipherp);
+ int opt_cipher_any(const char *name, EVP_CIPHER **cipherp);
+ int opt_cipher_silent(const char *name, EVP_CIPHER **cipherp);
+ int opt_md(const char *name, EVP_MD **mdp);
+
+ int opt_int(const char *value, int *result);
+ int opt_int_arg(void);
+ int opt_long(const char *value, long *result);
+ int opt_ulong(const char *value, unsigned long *result);
+ int opt_intmax(const char *value, intmax_t *result);
+ int opt_uintmax(const char *value, uintmax_t *result);
+
+ int opt_format(const char *s, unsigned long flags, int *result);
+ int opt_isdir(const char *name);
+ int opt_string(const char *name, const char **options);
+ int opt_pair(const char *name, const OPT_PAIR* pairs, int *result);
+
+ int opt_num_rest(void);
+ char **opt_rest(void);
+
+ int opt_legacy_okay(void);
+
+=head1 DESCRIPTION
+
+The functions on this page provide a common set of option-parsing for
+the OpenSSL command and the internal test programs.
+It is intended to be used like the standard getopt(3) routine, except
+that multi-character flag names are supported, and a variety of parsing
+and other utility functions are also provided.
+
+Programs that use this should make sure to set the appropriate C<-I>
+flag.
+
+These routines expect a global B<BIO> named B<bio_err> to point to
+the equivalent of B<stderr>. This is already done in the OpenSSL
+application.
+
+=head2 Data Types
+
+Each program should define, near the main() routine, an enumeration
+that is the set of options the program accepts. For example:
+
+ typedef enum OPTION_choice {
+ OPT_COMMON,
+ OPT_YES, OPT_NAME, OPT_COUNT, OPT_OFILE,
+ ...
+ } OPTION_CHOICE;
+
+The first two lines must appear exactly as shown.
+OPT_COMMON is a macro that expands to C<OPT_ERR = -1, OPT_EOF = 0, OPT_HELP>.
+In addition to defining symbolic names for the constants that opt_next()
+returns, it also helps guarantee that every command has a C<-help> option.
+The third line is a sample
+set of flags, and the closing C<typedef> name is used for error-checking
+as discussed below.
+By declaring the variable as an C<OPTION_CHOICE>, with the right warning
+flags, the compiler could check that all specified options are handled.
+
+The B<OPTIONS> C<typedef> specifies an option: what type of argument
+it takes (if any), and an optional "help" string. It is a C<struct>
+containing these fields:
+
+ const char *name;
+ int retval;
+ int valtype;
+ const char *helpstr;
+
+The B<name> is the name of the option that the user would type. Options
+are words prefaced with a minus sign. If the user uses two minus signs,
+this is also accepted for compatibility with other GNU software. Some
+names are special, and are described below.
+
+The B<retval> is the value to return if the option is found. It should be
+one of the choices in the enumeration above.
+
+The B<valtype> defines what the option's parameter must be. It should
+be chosen from the following set:
+
+ \0 No value
+ '-' No value
+ 's' A text string
+ '/' A directory
+ '<' Name of file to open for input
+ '>' Name of file to open for output
+ 'n' A signed number that fits in the C<int> type
+ 'p' A positive number that fits in the C<int> type
+ 'N' A nonnegative number that fits in the C<int> type
+ 'M' A signed number that fits in the C<intmax_t> type
+ 'U' An unsigned number that fits in the C<uintmax_t> type
+ 'l' A signed number that fits in the C<long> type
+ 'u' An unsigned number that fits in the C<unsigned long> type
+ 'c' File in PEM, DER, or S/MIME format
+ 'F' A file in PEM or DER format
+ 'E' Like 'F' but also allows ENGINE
+ 'f' Any file format
+
+The B<helpstr> is what to display when the user uses the help option,
+which should be C<"help">.
+
+A program should declare its options right after the enumeration,
+and should follow the ordering of the enumeration as this helps
+readability and maintainability:
+
+ static OPTIONS my_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"yes", OPT_YES, '-', "Print an affirmative reply"},
+ {"count", OPT_COUNT, 'p', "Repeat count"},
+ {"output" OPT_OFILE, '>', "Output file; default is stdout"},
+ {NULL}
+ };
+
+Note that the B<OPT_HELP> option is explicitly listed, and the list ends with
+an entry of all-null's. The other two special options, B<OPT_ERR> and B<OPT_EOF>
+should not appear in the array.
+
+If the help string is too long to fit into one line, it may be continued
+on multiple lines; each entry should use B<OPT_MORE_STR>, like this:
+
+ {"output" OPT_OFILE, '>', "Output file; default is stdout"},
+ {OPT_MORE_STR, 0, 0,
+ "This flag is not really needed on Unix systems"},
+ {OPT_MORE_STR, 0, 0,
+ "(Unix and descendents for ths win!)"}
+
+Each subsequent line will be indented the correct amount.
+
+By default, the help display will include a standard prolog:
+
+ Usage: PROGRAM [options]
+ Valid options are:
+ ...detailed list of options...
+
+Sometimes there are parameters that should appear in the synopsis.
+Use B<OPT_HELP_STR> as the first entry in your array:
+
+ {OPT_HELP_STR, 1, '-', Usage: %s [options] [text...]\n"}
+
+The B<retval> and B<valtype> are ignored, and the B<helpstr> should
+follow the general construction as shown. The C<%s> will get the program
+name.
+
+If a command has a large set of options, it can be useful to break them
+into sections. Use the macro B<OPT_SECTION> or B<OPT_SECTION_STR>
+to indicate this. The two lines below are equivalent:
+
+ OPT_SECTION("Validation"),
+ {OPT_SECTION_STR, 1, '-', "Validation options:\n"},
+
+In addition to providing help about options, you can provide a description
+of the parameters a command takes. These should appear at the end of
+the options and are indicated by using B<OPT_PARAM_STR> or the
+B<OPT_PARAMETERS> macro:
+
+ OPT_PARAMETERS()
+ {OPT_PARAM_STR, 1, '-', "Parameters:\n"}
+
+Every "option" after after this should contain the parameter and
+the help string:
+
+ {"text", 0, 0, "Words to display (optional)"},
+
+=head2 Functions
+
+The opt_init() function takes the I<argc> and I<argv> arguments given to main()
+and a pointer I<o> to the list of options. It returns the simple program
+name, as defined by opt_progname().
+
+The opt_progname() function takes the full pathname C<argv[0]> in its I<arg0>
+parameter and returns
+the simple short name of the executable, to be used for error messages and
+the like.
+
+The opt_appname() function takes in its I<argv0> parameter
+the "application" name (such
+as the specific command from L<openssl(1)> and appends it to the program
+name. This function should only be called once.
+
+The opt_getprog() function returns the value set by opt_appname().
+
+The opt_help() function takes a list of option definitions and prints a
+nicely-formatted output.
+
+The opt_begin() function, which is called automatically by opt_init(),
+can be used to reset the option parsing loop.
+
+The opt_next() function is called, once opt_init() has been called,
+in a loop to fetch each option in turn. It returns -1, or B<OPT_EOF> when the
+end of arguments has been reached. This is typically done like this:
+
+ prog = opt_init(argc, argv, my_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ fprintf(stderr, "%s: Use -help for summary\n", prog);
+ exit(1);
+ case OPT_HELP:
+ opt_help(my_options);
+ exit(0);
+ ...other options...
+ }
+ }
+
+Within the option parsing loop, the following functions may be called.
+
+The opt_flag() function returns the most recent option name
+including the preceding C<->.
+
+The opt_arg() function returns the option's argument value, if there is one.
+
+The opt_unknown() function returns the unknown option.
+In an option list, there can be at most one option with the empty string.
+This is a "wildcard" or "unknown" option. For example, it allows an
+option to be be taken as digest algorithm, like C<-sha1>. The function
+opt_md() takes the specified I<name> and fills in the digest into I<mdp>.
+The functions opt_cipher(), opt_cipher_any() and opt_cipher_silent()
+each takes the specified I<name> and fills in the cipher into I<cipherp>.
+The function opt_cipher() only accepts ciphers which are not
+AEAD and are not using XTS mode. The functions opt_cipher_any() and
+opt_cipher_silent() accept any cipher, the latter not emitting an error
+if the cipher is not located.
+
+There are a several useful functions for parsing numbers. These are
+opt_int(), opt_long(), opt_ulong(), opt_intmax(), and opt_uintmax(). They all
+take C<0x> to mean hexadecimal and C<0> to mean octal, and will do the
+necessary range-checking. They return 1 if successful and fill in the
+C<result> pointer with the value, or 0 on error. Note that opt_next()
+will also do range-check on the argument if the appropriate B<valtype>
+field is specified for the option. This means that error-checking inside
+the C<switch> C<case> can often be elided.
+
+The opt_int_arg() function is a convenience abbreviation to opt_int().
+It parses and returns an integer, assuming its range has been checked before.
+
+The opt_format() function takes a string value,
+such as used with the B<-informat> or similar option, and fills
+the value from the constants in F<fmt.h> file.
+
+The opt_isdir() function returns 1 if the specified I<name> is
+a directory, or 0 if not.
+
+The opt_string() function checks that I<name> appears in the
+NULL-terminated array of strings. It returns 1 if found,
+or prints a diagnostic and returns 0 if not.
+
+The opt_pair() function takes a list of I<pairs>, each of which
+has a text name and an integer. The specified I<name> is
+found on the list, it puts the index in I<*result>, and returns
+1. If not found, it returns 0.
+
+The following functions can be used after processing all the options.
+
+The opt_num_rest() function returns what is left.
+
+The opt_rest() function returns a pointer to the first non-option.
+If there were no parameters, it will point to the NULL that is
+at the end of the standard I<argv> array.
+
+The opt_legacy_okay() function returns true if no options have been
+specified that would preclude using legacy code paths. Currently,
+the various provider options preclude legacy operation. This means,
+for example, that specifying both B<-provider> and B<-engine> in the
+same command line will not work as expected.
+
+=head2 Common Options
+
+There are a few groups of options that are common to many OpenSSL programs.
+These are handled with sets of macros that define common option names
+and common code to handle them. The categories are identified by a
+letter:
+
+ V Validation
+ X Extended certificate
+ S TLS/SSL
+ R Random state
+
+The B<OPT_x_ENUM> macro is used to define the numeration values, where B<x>
+is one of the letters above. The B<OPT_x_OPTIONS> macro is used to
+list the set of common options, and the B<OPT_x_CASES> is used in
+the C<switch> statement.
+
+The common options are used throughout the sources for the OpenSSL commands.
+They are also used with common descriptions when generating the
+manpages, in the file F<doc/perlvars.pm>, which follow a similar naming
+convention.
+
+=head1 RETURN VALUES
+
+Detailed above.
+
+=head1 EXAMPLES
+
+The best examples can be found in sources for the commands in the F<apps>
+directory of the source tree.
+A notable exception is F<apps/cmp.c> which uses this API, but does
+things very differently.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use this
+file except in compliance with the License. You can obtain a copy in the file
+LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/OSSL_DEPRECATED.pod b/doc/internal/man3/OSSL_DEPRECATED.pod
new file mode 100644
index 000000000000..8370d60f18fb
--- /dev/null
+++ b/doc/internal/man3/OSSL_DEPRECATED.pod
@@ -0,0 +1,54 @@
+=pod
+
+=head1 NAME
+
+OSSL_DEPRECATED, OSSL_DEPRECATED_FOR - General deprecation macros
+
+=head1 SYNOPSIS
+
+ #include <openssl/macros.h>
+
+ #define OSSL_DEPRECATED(since)
+ #define OSSL_DEPRECATED_FOR(since, msg)
+
+=head1 DESCRIPTION
+
+OSSL_DEPRECATED() implements the deprecated attribute if the compiler
+supports it, otherwise it expands to nothing. It takes one argument
+I<since> that should be set to the OpenSSL version where the symbol was
+deprecated, and will be displayed with the deprecation warning message,
+for compilers that support user specified deprecation messages.
+
+OSSL_DEPRECATED_FOR() does the same as OSSL_DEPRECATED(), but also takes a
+second argument I<msg>, which is an additional text messages to be displayed
+with the deprecation warning along with the OpenSSL version number, for
+compilers that support user specified deprecation messages.
+
+These macros are used to define the version specific deprecation macros
+described in L<deprecation(7)>.
+
+=begin comment
+
+[RETURN VALUES isn't relevant for these macros, but find-doc-nits demands
+the presence of this section]
+
+=head1 RETURN VALUES
+
+[podchecker doesn't like empty sections]
+
+=end comment
+
+=head1 SEE ALSO
+
+L<deprecation(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/OSSL_METHOD_STORE.pod b/doc/internal/man3/OSSL_METHOD_STORE.pod
new file mode 100644
index 000000000000..70f6eb520ff3
--- /dev/null
+++ b/doc/internal/man3/OSSL_METHOD_STORE.pod
@@ -0,0 +1,144 @@
+=pod
+
+=head1 NAME
+
+OSSL_METHOD_STORE, ossl_method_store_new, ossl_method_store_free,
+ossl_method_store_init, ossl_method_store_cleanup,
+ossl_method_store_add, ossl_method_store_fetch,
+ossl_method_store_remove, ossl_method_store_remove_all_provided,
+ossl_method_store_cache_get, ossl_method_store_cache_set,
+ossl_method_store_cache_flush_all
+- implementation method store and query
+
+=head1 SYNOPSIS
+
+ #include "internal/property.h"
+
+ typedef struct ossl_method_store_st OSSL_METHOD_STORE;
+
+ OSSL_METHOD_STORE *ossl_method_store_new(OSSL_LIB_CTX *ctx);
+ void ossl_method_store_free(OSSL_METHOD_STORE *store);
+ int ossl_method_store_init(OSSL_LIB_CTX *ctx);
+ void ossl_method_store_cleanup(OSSL_LIB_CTX *ctx);
+ int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov,
+ int nid, const char *properties, void *method,
+ int (*method_up_ref)(void *),
+ void (*method_destruct)(void *));
+ int ossl_method_store_remove(OSSL_METHOD_STORE *store,
+ int nid, const void *method);
+ int ossl_method_store_fetch(OSSL_METHOD_STORE *store,
+ int nid, const char *properties,
+ void **method, const OSSL_PROVIDER **prov_rw);
+ int ossl_method_store_remove_all_provided(OSSL_METHOD_STORE *store,
+ const OSSL_PROVIDER *prov);
+
+ int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
+ int nid, const char *prop_query, void **method);
+ int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
+ int nid, const char *prop_query, void *method,
+ int (*method_up_ref)(void *),
+ void (*method_destruct)(void *));
+ void ossl_method_store_cache_flush_all(OSSL_METHOD_STORE *store);
+
+=head1 DESCRIPTION
+
+OSSL_METHOD_STORE stores methods that can be queried using properties and a
+numeric identity (nid).
+
+Methods are expected to be library internal structures.
+It's left to the caller to define the exact contents.
+
+Numeric identities are expected to be an algorithm identity for the methods.
+It's left to the caller to define exactly what an algorithm is, and to allocate
+these numeric identities accordingly.
+
+The B<OSSL_METHOD_STORE> also holds an internal query cache, which is accessed
+separately (see L</Cache Functions> below).
+
+=head2 Store Functions
+
+ossl_method_store_init() initialises the method store subsystem in the scope of
+the library context I<ctx>.
+
+ossl_method_store_cleanup() cleans up and shuts down the implementation method
+store subsystem in the scope of the library context I<ctx>.
+
+ossl_method_store_new() create a new empty method store using the supplied
+I<ctx> to allow access to the required underlying property data.
+
+ossl_method_store_free() frees resources allocated to I<store>.
+
+ossl_method_store_add() adds the I<method> constructed from an implementation in
+the provider I<prov> to the I<store> as an instance of an algorithm indicated by
+I<nid> and the property definition I<properties>, unless the I<store> already
+has a method from the same provider with the same I<nid> and I<properties>.
+If the I<method_up_ref> function is given, it's called to increment the
+reference count of the method.
+If the I<method_destruct> function is given, it's called when this function
+fails to add the method to the store, or later on when it is being released from
+the I<store>.
+
+ossl_method_store_remove() removes the I<method> identified by I<nid> from the
+I<store>.
+
+ossl_method_store_fetch() queries I<store> for a method identified by I<nid>
+that matches the property query I<prop_query>.
+I<*prop> may be a pointer to a provider, which will narrow the search
+to methods from that provider.
+The result, if any, is returned in I<*method>, and its provider in I<*prov>.
+
+ossl_method_store_remove_all_provided() removes all methods from I<store>
+that are provided by I<prov>.
+When doing so, it also flushes the corresponding cache entries.
+
+=head2 Cache Functions
+
+ossl_method_store_cache_get() queries the cache associated with the I<store>
+for a method identified by I<nid> that matches the property query
+I<prop_query>.
+Additionally, if I<prov> isn't NULL, it will be used to narrow the search
+to only include methods from that provider.
+The result, if any, is returned in I<method>.
+
+ossl_method_store_cache_set() sets a cache entry identified by I<nid> from the
+provider I<prov>, with the property query I<prop_query> in the I<store>.
+Future calls to ossl_method_store_cache_get() will return the specified I<method>.
+The I<method_up_ref> function is called to increment the
+reference count of the method and the I<method_destruct> function is called
+to decrement it.
+
+ossl_method_store_cache_flush_all() flushes all cached entries associated with
+I<store>.
+
+=head1 NOTES
+
+The I<prop_query> argument to ossl_method_store_cache_get() and
+ossl_method_store_cache_set() is not allowed to be NULL. Use "" for an
+empty property definition or query.
+
+=head1 RETURN VALUES
+
+ossl_method_store_new() returns a new method store object or NULL on failure.
+
+ossl_method_store_free(), ossl_method_store_add(),
+ossl_method_store_remove(), ossl_method_store_fetch(),
+ossl_method_store_cache_get(), ossl_method_store_cache_set() and
+ossl_method_store_flush_cache() return B<1> on success and B<0> on error.
+
+ossl_method_store_free() and ossl_method_store_cleanup() do not return any value.
+
+=head1 HISTORY
+
+This functionality was added to OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use this
+file except in compliance with the License. You can obtain a copy in the file
+LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/cms_add1_signing_cert.pod b/doc/internal/man3/cms_add1_signing_cert.pod
new file mode 100644
index 000000000000..cc2747dcde6e
--- /dev/null
+++ b/doc/internal/man3/cms_add1_signing_cert.pod
@@ -0,0 +1,46 @@
+=pod
+
+=head1 NAME
+
+cms_add1_signing_cert, cms_add1_signing_cert_v2
+- add ESS signing-certificate signed attribute to a
+CMS_SignerInfo data structure
+
+=head1 SYNOPSIS
+
+ #include <openssl/cms.h>
+
+ int cms_add1_signing_cert(CMS_SignerInfo *si, ESS_SIGNING_CERT *sc);
+
+ int cms_add1_signing_cert_v2(CMS_SignerInfo *si, ESS_SIGNING_CERT_V2 *sc2);
+
+=head1 DESCRIPTION
+
+cms_add1_signing_cert() adds an ESS Signing Certificate I<sc> (version 1) signed
+attribute to the CMS_SignerInfo I<si>.
+cms_add1_signing_cert_v2() adds an ESS Signing Certificate I<sc2> (version 2) signed
+attribute to the CMS_SignerInfo I<si>.
+The ESS Signing Certificate attributes version 1 and 2 are defined in RFC 5035
+which updates Section 5.4 of RFC 2634.
+
+=head1 NOTES
+
+This attribute is mandatory to make a CMS compliant with CAdES-BES
+(European Standard ETSI EN 319 122-1 V1.1.1).
+For a fuller description see L<openssl-cms(1)>).
+
+=head1 RETURN VALUES
+
+cms_add1_signing_cert() and cms_add1_signing_cert_v2() return 1 if attribute
+is added or 0 if an error occurred.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/evp_generic_fetch.pod b/doc/internal/man3/evp_generic_fetch.pod
new file mode 100644
index 000000000000..b23d2ec0eaa2
--- /dev/null
+++ b/doc/internal/man3/evp_generic_fetch.pod
@@ -0,0 +1,285 @@
+=pod
+
+=head1 NAME
+
+evp_generic_fetch, evp_generic_fetch_by_number, evp_generic_fetch_from_prov
+- generic algorithm fetchers and method creators for EVP
+
+=head1 SYNOPSIS
+
+ /* Only for EVP source */
+ #include "evp_local.h"
+
+ void *evp_generic_fetch(OSSL_LIB_CTX *libctx, int operation_id,
+ const char *name, const char *properties,
+ void *(*new_method)(int name_id,
+ const OSSL_DISPATCH *fns,
+ OSSL_PROVIDER *prov,
+ void *method_data),
+ void *method_data,
+ int (*up_ref_method)(void *),
+ void (*free_method)(void *));
+
+ void *evp_generic_fetch_by_number(OSSL_LIB_CTX *ctx, int operation_id,
+ int name_id, const char *properties,
+ void *(*new_method)(int name_id,
+ const OSSL_DISPATCH *fns,
+ OSSL_PROVIDER *prov,
+ void *method_data),
+ void *method_data,
+ int (*up_ref_method)(void *),
+ void (*free_method)(void *));
+ void *evp_generic_fetch_from_prov(OSSL_PROVIDER *prov, int operation_id,
+ int name_id, const char *properties,
+ void *(*new_method)(int name_id,
+ const OSSL_DISPATCH *fns,
+ OSSL_PROVIDER *prov,
+ void *method_data),
+ void *method_data,
+ int (*up_ref_method)(void *),
+ void (*free_method)(void *));
+
+=head1 DESCRIPTION
+
+evp_generic_fetch() calls ossl_method_construct() with the given
+I<libctx>, I<operation_id>, I<name>, and I<properties> and uses
+it to create an EVP method with the help of the functions
+I<new_method>, I<up_ref_method>, and I<free_method>.
+
+evp_generic_fetch_by_number() does the same thing as evp_generic_fetch(),
+but takes a numeric I<name_id> instead of a name.
+I<name_id> must always be nonzero; as a matter of fact, it being zero
+is considered a programming error.
+This is meant to be used when one method needs to fetch an associated
+method, and is typically called from inside the given function
+I<new_method>.
+
+evp_generic_fetch_from_prov() does the same thing as evp_generic_fetch(),
+but limits the search of methods to the provider given with I<prov>.
+This is meant to be used when one method needs to fetch an associated
+method in the same provider.
+
+The three functions I<new_method>, I<up_ref_method>, and
+I<free_method> are supposed to:
+
+=over 4
+
+=item new_method()
+
+creates an internal method from function pointers found in the
+dispatch table I<fns>, with name identity I<name_id>.
+The provider I<prov> and I<method_data> are also passed to be used as
+new_method() sees fit.
+
+=item up_ref_method()
+
+increments the reference counter for the given method, if there is
+one.
+
+=item free_method()
+
+frees the given method.
+
+=back
+
+=head1 RETURN VALUES
+
+evp_generic_fetch() returns a method on success, or NULL on error.
+
+=head1 EXAMPLES
+
+This is a short example of the fictitious EVP API and operation called
+B<EVP_FOO>.
+
+To begin with, let's assume something like this in
+F<include/openssl/core_dispatch.h>:
+
+ #define OSSL_OP_FOO 100
+
+ #define OSSL_FUNC_FOO_NEWCTX_FUNC 2001
+ #define OSSL_FUNC_FOO_INIT 2002
+ #define OSSL_FUNC_FOO_OPERATE 2003
+ #define OSSL_FUNC_FOO_CLEANCTX_FUNC 2004
+ #define OSSL_FUNC_FOO_FREECTX_FUNC 2005
+
+ OSSL_CORE_MAKE_FUNC(void *, foo_newctx, (void))
+ OSSL_CORE_MAKE_FUNC(int, foo_init, (void *vctx))
+ OSSL_CORE_MAKE_FUNC(int, foo_operate, (void *vctx,
+ unsigned char *out, size_t *out_l,
+ unsigned char *in, size_t in_l))
+ OSSL_CORE_MAKE_FUNC(void, foo_cleanctx, (void *vctx))
+ OSSL_CORE_MAKE_FUNC(void, foo_freectx, (void *vctx))
+
+And here's the implementation of the FOO method fetcher:
+
+ /* typedef struct evp_foo_st EVP_FOO */
+ struct evp_foo_st {
+ OSSL_PROVIDER *prov;
+ int name_id;
+ CRYPTO_REF_COUNT refcnt;
+ OSSL_FUNC_foo_newctx_fn *newctx;
+ OSSL_FUNC_foo_init_fn *init;
+ OSSL_FUNC_foo_operate_fn *operate;
+ OSSL_FUNC_foo_cleanctx_fn *cleanctx;
+ OSSL_FUNC_foo_freectx_fn *freectx;
+ };
+
+ /*
+ * In this example, we have a public method creator and destructor.
+ * It's not absolutely necessary, but is in the spirit of OpenSSL.
+ */
+ EVP_FOO *EVP_FOO_meth_from_algorithm(int name_id,
+ const OSSL_DISPATCH *fns,
+ OSSL_PROVIDER *prov,
+ void *data)
+ {
+ EVP_FOO *foo = NULL;
+
+ if ((foo = OPENSSL_zalloc(sizeof(*foo))) == NULL)
+ return NULL;
+
+ foo->name_id = name_id;
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_FOO_NEWCTX:
+ foo->newctx = OSSL_FUNC_foo_newctx(fns);
+ break;
+ case OSSL_FUNC_FOO_INIT:
+ foo->init = OSSL_FUNC_foo_init(fns);
+ break;
+ case OSSL_FUNC_FOO_OPERATE:
+ foo->operate = OSSL_FUNC_foo_operate(fns);
+ break;
+ case OSSL_FUNC_FOO_CLEANCTX:
+ foo->cleanctx = OSSL_FUNC_foo_cleanctx(fns);
+ break;
+ case OSSL_FUNC_FOO_FREECTX:
+ foo->freectx = OSSL_FUNC_foo_freectx(fns);
+ break;
+ }
+ }
+ foo->prov = prov;
+ if (prov)
+ ossl_provider_up_ref(prov);
+
+ return foo;
+ }
+
+ EVP_FOO_meth_free(EVP_FOO *foo)
+ {
+ if (foo != NULL) {
+ OSSL_PROVIDER *prov = foo->prov;
+
+ OPENSSL_free(foo);
+ ossl_provider_free(prov);
+ }
+ }
+
+ static void *foo_from_algorithm(const OSSL_DISPATCH *fns,
+ OSSL_PROVIDER *prov)
+ {
+ return EVP_FOO_meth_from_algorithm(fns, prov);
+ }
+
+ static int foo_up_ref(void *vfoo)
+ {
+ EVP_FOO *foo = vfoo;
+ int ref = 0;
+
+ CRYPTO_UP_REF(&foo->refcnt, &ref, foo_lock);
+ return 1;
+ }
+
+ static void foo_free(void *vfoo)
+ {
+ EVP_FOO_meth_free(vfoo);
+ }
+
+ EVP_FOO *EVP_FOO_fetch(OSSL_LIB_CTX *ctx,
+ const char *name,
+ const char *properties)
+ {
+ EVP_FOO *foo =
+ evp_generic_fetch(ctx, OSSL_OP_FOO, name, properties,
+ foo_from_algorithm, foo_up_ref, foo_free);
+
+ /*
+ * If this method exists in legacy form, with a constant NID for the
+ * given |name|, this is the spot to find that NID and set it in
+ * the newly constructed EVP_FOO instance.
+ */
+
+ return foo;
+
+ }
+
+And finally, the library functions:
+
+ /* typedef struct evp_foo_st EVP_FOO_CTX */
+ struct evp_foo_ctx_st {
+ const EVP_FOO *foo;
+ void *provctx; /* corresponding provider context */
+ };
+
+ int EVP_FOO_CTX_reset(EVP_FOO_CTX *c)
+ {
+ if (c == NULL)
+ return 1;
+ if (c->foo != NULL && c->foo->cleanctx != NULL)
+ c->foo->cleanctx(c->provctx);
+ return 1;
+ }
+
+ EVP_FOO_CTX *EVP_FOO_CTX_new(void)
+ {
+ return OPENSSL_zalloc(sizeof(EVP_FOO_CTX));
+ }
+
+ void EVP_FOO_CTX_free(EVP_FOO_CTX *c)
+ {
+ EVP_FOO_CTX_reset(c);
+ c->foo->freectx(c->provctx);
+ OPENSSL_free(c);
+ }
+
+ int EVP_FooInit(EVP_FOO_CTX *c, const EVP_FOO *foo)
+ {
+ int ok = 1;
+
+ c->foo = foo;
+ if (c->provctx == NULL)
+ c->provctx = c->foo->newctx();
+
+ ok = c->foo->init(c->provctx);
+
+ return ok;
+ }
+
+ int EVP_FooOperate(EVP_FOO_CTX *c, unsigned char *out, size_t *outl,
+ const unsigned char *in, size_t inl)
+ {
+ int ok = 1;
+
+ ok = c->foo->update(c->provctx, out, inl, &outl, in, inl);
+ return ok;
+ }
+
+=head1 SEE ALSO
+
+L<ossl_method_construct(3)>
+
+=head1 HISTORY
+
+The functions described here were all added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/evp_keymgmt_newdata.pod b/doc/internal/man3/evp_keymgmt_newdata.pod
new file mode 100644
index 000000000000..9b3f2c55f160
--- /dev/null
+++ b/doc/internal/man3/evp_keymgmt_newdata.pod
@@ -0,0 +1,88 @@
+=pod
+
+=head1 NAME
+
+evp_keymgmt_newdata, evp_keymgmt_freedata,
+evp_keymgmt_get_params,
+evp_keymgmt_has, evp_keymgmt_validate,
+evp_keymgmt_import, evp_keymgmt_import_types,
+evp_keymgmt_export, evp_keymgmt_export_types
+- internal KEYMGMT interface functions
+
+=head1 SYNOPSIS
+
+ #include "crypto/evp.h"
+
+ void *evp_keymgmt_newdata(const EVP_KEYMGMT *keymgmt);
+ void evp_keymgmt_freedata(const EVP_KEYMGMT *keymgmt, void *keyddata);
+ int evp_keymgmt_get_params(const EVP_KEYMGMT *keymgmt,
+ void *keydata, OSSL_PARAM params[]);
+
+ int evp_keymgmt_has(const EVP_KEYMGMT *keymgmt, void *keyddata, int selection);
+ int evp_keymgmt_validate(const EVP_KEYMGMT *keymgmt, void *keydata,
+ int selection);
+
+ int evp_keymgmt_import(const EVP_KEYMGMT *keymgmt, void *keydata,
+ int selection, const OSSL_PARAM params[]);
+ const OSSL_PARAM *evp_keymgmt_import_types(const EVP_KEYMGMT *keymgmt,
+ int selection);
+ int evp_keymgmt_export(const EVP_KEYMGMT *keymgmt, void *keydata,
+ int selection, OSSL_CALLBACK *param_cb, void *cbarg);
+ const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt,
+ int selection);
+
+=head1 DESCRIPTION
+
+All these functions are helpers to call the provider's corresponding
+function. They all have in common that they take a B<EVP_KEYMGMT> as
+first argument, which they also retrieve a provider context from when
+needed. The rest of the arguments are simply passed on to the
+function they wrap around.
+
+evp_keymgmt_newdata() calls the method's new() function.
+
+evp_keymgmt_freedata() calls the method's free() function.
+
+(the name evp_keymgmt_freedata() was chosen to avoid a clash with
+EVP_KEYMGMT_free() on case insensitive systems, the name
+evp_keymgmt_newdata() was chosen for consistency)
+
+evp_keymgmt_get_params() calls the method's get_params() function.
+
+evp_keymgmt_has() calls the method's has() function.
+
+evp_keymgmt_validate() calls the method's validate() function.
+
+evp_keymgmt_import() calls the method's import() function.
+
+evp_keymgmt_import_types() calls the method's import_types() function.
+
+evp_keymgmt_export() calls the method's export() function.
+
+evp_keymgmt_export_types() calls the method's export_types() function.
+
+=head1 RETURN VALUES
+
+evp_keymgmt_newdata() returns a pointer to a provider side key object,
+or NULL on error.
+
+evp_keymgmt_import_types(), and evp_keymgmt_export_types() return a parameter
+descriptor for importing and exporting key data, or NULL if there are no such
+descriptors.
+
+All other functions return 1 on success and 0 on error.
+
+=head1 HISTORY
+
+The functions described here were all added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/evp_keymgmt_util_export_to_provider.pod b/doc/internal/man3/evp_keymgmt_util_export_to_provider.pod
new file mode 100644
index 000000000000..7099e4496473
--- /dev/null
+++ b/doc/internal/man3/evp_keymgmt_util_export_to_provider.pod
@@ -0,0 +1,106 @@
+=pod
+
+=head1 NAME
+
+evp_keymgmt_util_export,
+evp_keymgmt_util_export_to_provider,
+evp_keymgmt_util_find_operation_cache,
+evp_keymgmt_util_clear_operation_cache,
+evp_keymgmt_util_cache_keydata,
+evp_keymgmt_util_cache_keyinfo,
+evp_keymgmt_util_fromdata,
+OP_CACHE_ELEM
+- internal KEYMGMT utility functions
+
+=head1 SYNOPSIS
+
+ #include "crypto/evp.h"
+
+ typedef struct OP_CACHE_ELEM;
+
+ int evp_keymgmt_util_export(const EVP_PKEY *pk, int selection,
+ OSSL_CALLBACK *export_cb, void *export_cbarg);
+ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
+ int selection);
+ OP_CACHE_ELEM *evp_keymgmt_util_find_operation_cache(EVP_PKEY *pk,
+ EVP_KEYMGMT *keymgmt,
+ int selection);
+ int evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk, int locking);
+ int evp_keymgmt_util_cache_keydata(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
+ void *keydata, int selection);
+ void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk);
+ void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
+ int selection, const OSSL_PARAM params[]);
+
+=head1 DESCRIPTION
+
+evp_keymgmt_util_export() calls L<evp_keymgmt_export(3)> with the
+I<keymgmt> and I<keydata> from I<pk>. This is used as a
+helper for L<EVP_PKEY_todata(3)>.
+
+evp_keymgmt_util_export_to_provider() exports cached key material
+(provider side key material) from the given key I<pk> to a provider
+via a B<EVP_KEYMGMT> interface, if this hasn't already been done.
+It maintains a cache of provider key references in I<pk> to keep track
+of all provider side keys.
+
+To export a legacy key, use L<evp_pkey_export_to_provider(3)> instead,
+as this function ignores any legacy key data.
+
+evp_keymgmt_util_find_operation_cache() finds
+I<keymgmt> in I<pk>'s cache of provided keys for operations.
+It should only be called while holding I<pk>'s lock (read or write).
+
+evp_keymgmt_util_clear_operation_cache() can be used to explicitly
+clear the cache of operation key references. If I<locking> is set to 1 then
+then I<pk>'s lock will be obtained while doing the clear. Otherwise it will be
+assumed that the lock has already been obtained or is not required.
+
+evp_keymgmt_util_cache_keydata() can be used to add a provider key
+object to a B<PKEY>.
+
+evp_keymgmt_util_cache_keyinfo() can be used to get all kinds of
+information from the provvider "origin" and save it in I<pk>'s
+information cache.
+
+evp_keymgmt_util_fromdata() can be used to add key object data to a
+given key I<target> via a B<EVP_KEYMGMT> interface. This is used as a
+helper for L<EVP_PKEY_fromdata(3)>.
+
+In all functions that take a I<selection> argument, the selection is used to
+constraint the information requested on export. It is also used in the cache
+so that key data is guaranteed to contain all the information requested in
+the selection.
+
+=head1 RETURN VALUES
+
+evp_keymgmt_export_to_provider() and evp_keymgmt_util_fromdata()
+return a pointer to the appropriate provider side key (created or
+found again), or NULL on error.
+
+evp_keymgmt_util_find_operation_cache() returns a pointer to the
+operation cache slot. If I<keymgmt> is NULL, or if there is no slot
+with a match for I<keymgmt>, NULL is returned.
+
+evp_keymgmt_util_cache_keydata() and evp_keymgmt_util_clear_operation_cache()
+return 1 on success or 0 otherwise.
+
+=head1 NOTES
+
+"Legacy key" is the term used for any key that has been assigned to an
+B<EVP_PKEY> with EVP_PKEY_assign_RSA() and similar functions.
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_ASN1_METHOD(3)>, L<EVP_PKEY_assign_RSA(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/evp_md_get_number.pod b/doc/internal/man3/evp_md_get_number.pod
new file mode 100644
index 000000000000..1f913551aad6
--- /dev/null
+++ b/doc/internal/man3/evp_md_get_number.pod
@@ -0,0 +1,112 @@
+=pod
+
+=head1 NAME
+
+ossl_decoder_get_number, evp_md_get_number, evp_cipher_get_number,
+evp_mac_get_number, evp_rand_get_number, evp_keymgmt_get_number,
+evp_signature_get_number, evp_asym_cipher_get_number, evp_kem_get_number,
+evp_keyexch_get_number, evp_kdf_get_number, ossl_encoder_get_number,
+ossl_store_loader_get_number - EVP get internal identification numbers
+
+=head1 SYNOPSIS
+
+ #include "crypto/evp.h"
+
+ int evp_asym_cipher_get_number(const EVP_ASYM_CIPHER *cipher);
+ int evp_cipher_get_number(const EVP_CIPHER *e);
+ int evp_kdf_get_number(const EVP_KDF *kdf);
+ int evp_kem_get_number(const EVP_KEM *kem);
+ int evp_keyexch_get_number(const EVP_KEYEXCH *exchange);
+ int evp_keymgmt_get_number(const EVP_KEYMGMT *keymgmt);
+ int evp_mac_get_number(const EVP_MAC *mac);
+ int evp_md_get_number(const EVP_MD *md);
+ int evp_rand_get_number(const EVP_RAND *rand);
+ int evp_signature_get_number(const EVP_SIGNATURE *signature);
+ int ossl_decoder_get_number(const OSSL_DECODER *decoder);
+ int ossl_encoder_get_number(const OSSL_ENCODER *encoder);
+ int ossl_store_loader_get_number(const OSSL_STORE_LOADER *loader);
+
+=head1 DESCRIPTION
+
+All provided algorithms get an associated integer identification number.
+This number is dynamic and should be expected to vary from run to run.
+These numbers should only be considered to be unique per provider per
+library context.
+
+=over 4
+
+=item evp_asym_cipher_get_number()
+
+Returns the internal dynamic number assigned to I<cipher>.
+
+=item evp_cipher_get_number()
+
+Returns the internal dynamic number assigned to the I<cipher>. This is only
+useful with fetched B<EVP_CIPHER>s.
+
+=item evp_kdf_get_number()
+
+Keturns the internal dynamic number assigned to I<kdf>.
+
+=item evp_kem_get_number()
+
+Returns the internal dynamic number assigned to I<kem>.
+
+=item evp_keyexch_get_number()
+
+Returns the internal dynamic number assigned to the I<exchange>.
+
+=item evp_keymgmt_get_number()
+
+Returns the internal dynamic number assigned to the I<keymgmt>.
+
+=item evp_mac_get_number()
+
+Returns the internal dynamic number assigned to I<mac>.
+
+=item evp_md_get_number()
+
+Returns the internal dynamic number assigned to the I<md>. This is
+only useful with fetched B<EVP_MD>s.
+
+=item evp_rand_get_number()
+
+Returns the internal dynamic number assigned to I<rand>.
+
+=item evp_signature_get_number()
+
+Returns the internal dynamic number assigned to I<signature>.
+
+=item ossl_decoder_get_number()
+
+Returns the internal dynamic number assigned to the given I<decoder>.
+
+=item ossl_encoder_get_number()
+
+Returns the internal dynamic number assigned to the given I<encoder>.
+
+=item ossl_store_loader_get_number()
+
+Returns the internal dynamic number assigned to the given I<loader>.
+
+=back
+
+=head1 RETURN VALUES
+
+All of these functions return the provider specific identification number
+for the specified algorithm.
+
+=head1 HISTORY
+
+This functionality was added to OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/evp_pkey_export_to_provider.pod b/doc/internal/man3/evp_pkey_export_to_provider.pod
new file mode 100644
index 000000000000..44efbbe2668f
--- /dev/null
+++ b/doc/internal/man3/evp_pkey_export_to_provider.pod
@@ -0,0 +1,80 @@
+=pod
+
+=head1 NAME
+
+evp_pkey_export_to_provider, evp_pkey_copy_downgraded, evp_pkey_get_legacy
+- internal EVP_PKEY support functions for providers
+
+=head1 SYNOPSIS
+
+ /* Only for EVP source */
+ #include "evp_local.h"
+
+ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OSSL_LIB_CTX *libctx,
+ EVP_KEYMGMT **keymgmt,
+ const char *propquery);
+ int evp_pkey_copy_downgraded(EVP_PKEY **dest, const EVP_PKEY *src);
+ void *evp_pkey_get_legacy(EVP_PKEY *pk);
+
+=head1 DESCRIPTION
+
+This manual uses the term "origin", which is explained in internal
+L<EVP_PKEY(7)>.
+
+evp_pkey_export_to_provider() exports the "origin" key contained in I<pk>
+to its operation cache to make it suitable for an B<EVP_KEYMGMT> given either
+with I<*keymgmt> or with an implicit fetch using I<libctx> (NULL means the
+default context), the name of the legacy type of I<pk>, and the I<propquery>
+(NULL means the default property query settings).
+
+If I<keymgmt> isn't NULL but I<*keymgmt> is, and the "origin" was successfully
+exported, then I<*keymgmt> is assigned the implicitly fetched B<EVP_KEYMGMT>.
+
+evp_pkey_copy_downgraded() makes a copy of I<src> in legacy form into I<*dest>,
+if there's a corresponding legacy implementation. This should be used if the
+use of a downgraded key is temporary.
+For example, L<PEM_write_bio_PrivateKey_traditional(3)> uses this to try its
+best to get "traditional" PEM output even if the input B<EVP_PKEY> has a
+provider-native internal key.
+
+evp_pkey_get_legacy() obtains and returns a legacy key structure. If the
+EVP_PKEY already contains a legacy key then it is simply returned. If it is a
+provider based key, then a new legacy key is constructed based on the provider
+key. The legacy key is cached inside the EVP_PKEY and its value returned from
+this function. Subsequent calls to evp_pkey_get_legacy() will return the cached
+key. Subsequent changes to the provider key are not reflected back in the
+legacy key. Similarly changes to the legacy key are not reflected back in the
+provider key.
+
+=head1 RETURN VALUES
+
+evp_pkey_export_to_provider() returns the provider key data if there was any
+allocated. It also either sets I<*keymgmt> to the B<EVP_KEYMGMT> associated
+with the returned key data, or NULL on error.
+
+evp_pkey_get_legacy() returns the legacy key or NULL on error.
+
+=head1 NOTES
+
+Some functions calling evp_pkey_export_to_provider() may have received a const
+key, and may therefore have to cast the key to non-const form to call this
+function. Since B<EVP_PKEY> is always dynamically allocated, this is OK.
+
+=head1 SEE ALSO
+
+L<OSSL_LIB_CTX(3)>, L<EVP_KEYMGMT(3)>
+
+=head1 HISTORY
+
+The functions described here were all added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/evp_pkey_get1_ED25519.pod b/doc/internal/man3/evp_pkey_get1_ED25519.pod
new file mode 100644
index 000000000000..37b41e459166
--- /dev/null
+++ b/doc/internal/man3/evp_pkey_get1_ED25519.pod
@@ -0,0 +1,43 @@
+=pod
+
+=head1 NAME
+
+evp_pkey_get1_ED25519, evp_pkey_get1_ED448,
+evp_pkey_get1_X25519, evp_pkey_get1_X448
+- internal ECX from EVP_PKEY getter functions
+
+=head1 SYNOPSIS
+
+ #include "internal/evp.h"
+
+ ECX_KEY *evp_pkey_get1_ED25519(EVP_PKEY *pkey);
+ ECX_KEY *evp_pkey_get1_ED448(EVP_PKEY *pkey);
+ ECX_KEY *evp_pkey_get1_X25519(EVP_PKEY *pkey);
+ ECX_KEY *evp_pkey_get1_X448(EVP_PKEY *pkey);
+
+=head1 DESCRIPTION
+
+evp_pkey_get1_ED25519(), evp_pkey_get1_ED448(), evp_pkey_get1_X25519() and
+evp_pkey_get1_X448() return the referenced key in I<pkey> or NULL if the key
+is not of the correct type. The returned key must be freed after use.
+
+=head1 RETURN VALUES
+
+evp_pkey_get1_ED25519(), evp_pkey_get1_ED448(), evp_pkey_get1_X25519() and
+evp_pkey_get1_X448() return the referenced key or NULL if an error
+occurred.
+
+=head1 HISTORY
+
+This functionality was added to OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use this
+file except in compliance with the License. You can obtain a copy in the file
+LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_DER_w_begin_sequence.pod b/doc/internal/man3/ossl_DER_w_begin_sequence.pod
new file mode 100644
index 000000000000..b78056f6e121
--- /dev/null
+++ b/doc/internal/man3/ossl_DER_w_begin_sequence.pod
@@ -0,0 +1,48 @@
+=pod
+
+=head1 NAME
+
+ossl_DER_w_begin_sequence, ossl_DER_w_end_sequence
+- internal DER writers for DER constructed elements
+
+=head1 SYNOPSIS
+
+ #include "internal/der.h"
+
+ int ossl_DER_w_begin_sequence(WPACKET *pkt, int tag);
+ int ossl_DER_w_end_sequence(WPACKET *pkt, int tag);
+
+=head1 DESCRIPTION
+
+All functions described here are wrappers for constructed structures,
+i.e. the ASN.1 SEQUENCE, SET and CHOICE specifications. They all come
+in pairs, as noted by the function names containing the words C<begin>
+and B<end>.
+
+When using these, special care must be taken to ensure that the ASN.1 tag
+value I<tag> is the same in the matching C<begin> and C<end> function calls.
+
+ossl_DER_w_begin_sequence() and ossl_DER_w_end_sequence() begins and ends a
+SEQUENCE.
+
+=head1 RETURN VALUES
+
+All the functions return 1 on success and 0 on failure. Failure may
+mean that the buffer held by the I<pkt> is too small, but may also
+mean that the values given to the functions are invalid, such as the provided
+I<tag> value being too large for the implementation.
+
+=head1 SEE ALSO
+
+L<DERlib(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_DER_w_bn.pod b/doc/internal/man3/ossl_DER_w_bn.pod
new file mode 100644
index 000000000000..49644ffd058f
--- /dev/null
+++ b/doc/internal/man3/ossl_DER_w_bn.pod
@@ -0,0 +1,66 @@
+=pod
+
+=head1 NAME
+
+ossl_DER_w_boolean, ossl_DER_w_uint32, ossl_DER_w_bn, ossl_DER_w_null,
+ossl_DER_w_octet_string, ossl_DER_w_octet_string_uint32
+- internal DER writers for DER primitives
+
+=head1 SYNOPSIS
+
+ #include "internal/der.h"
+
+ int ossl_DER_w_boolean(WPACKET *pkt, int tag, int b);
+ int ossl_DER_w_uint32(WPACKET *pkt, int tag, uint32_t v);
+ int ossl_DER_w_bn(WPACKET *pkt, int tag, const BIGNUM *v);
+ int ossl_DER_w_null(WPACKET *pkt, int tag);
+ int ossl_DER_w_octet_string(WPACKET *pkt, int tag,
+ const unsigned char *data, size_t data_n);
+ int ossl_DER_w_octet_string_uint32(WPACKET *pkt, int tag, uint32_t value);
+
+=head1 DESCRIPTION
+
+All functions described here behave the same way, they prepend
+(remember that DER writers are used backwards) the DER encoding of
+their respective value to the already written output buffer held by
+I<pkt>.
+
+ossl_DER_w_boolean() writes the primitive BOOLEAN using the value I<b>.
+Any value that evaluates as true will render a B<true> BOOLEAN,
+otherwise a B<false> BOOLEAN.
+
+ossl_DER_w_uint32() and ossl_DER_w_bn() both write the primitive INTEGER using
+the value I<v>.
+
+=for comment Other similar functions for diverse C integers should be
+added.
+
+ossl_DER_w_null() writes the primitive NULL.
+
+ossl_DER_w_octet_string() writes the primitive OCTET STRING using the bytes
+from I<data> with a length of I<data_n>.
+
+ossl_DER_w_octet_string_uint32() writes the primitive OCTET STRING using a
+32 bit value in I<value>.
+
+=head1 RETURN VALUES
+
+All the functions return 1 on success and 0 on failure. Failure may
+mean that the buffer held by the I<pkt> is too small, but may also
+mean that the values given to the functions are invalid, such as the provided
+I<tag> value being too large for the implementation.
+
+=head1 SEE ALSO
+
+L<DERlib(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_DER_w_precompiled.pod b/doc/internal/man3/ossl_DER_w_precompiled.pod
new file mode 100644
index 000000000000..aa7fa3930f89
--- /dev/null
+++ b/doc/internal/man3/ossl_DER_w_precompiled.pod
@@ -0,0 +1,48 @@
+=pod
+
+=head1 NAME
+
+ossl_DER_w_precompiled
+- internal DER writers for precompiled DER blobs
+
+=head1 SYNOPSIS
+
+ #include "internal/der.h"
+
+ int ossl_DER_w_precompiled(WPACKET *pkt, int tag,
+ const unsigned char *precompiled,
+ size_t precompiled_n);
+
+=head1 DESCRIPTION
+
+There may be already existing DER blobs that can simply be copied to
+the buffer held by I<pkt>. For example, precompiled values, such as
+OIDs (for example, C<id-sha256>) or complete AlgorithmIdentifiers
+(for example, C<sha256Identifier>). To add those as an element in a
+structure being DER encoded, use ossl_DER_w_precompiled().
+
+ossl_DER_w_precompiled() will simply take the DER encoded blob given as
+I<precompiled> with length I<precompiled_n> and add it to the buffer
+held by I<pkt>.
+
+=head1 RETURN VALUES
+
+ossl_DER_w_precompiled() returns 1 on success and 0 on failure. Failure
+may mean that the buffer held by the I<pkt> is too small, but may also
+mean that the values given to the functions are invalid, such as the provided
+I<tag> value being too large for the implementation.
+
+=head1 SEE ALSO
+
+L<DERlib(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_algorithm_do_all.pod b/doc/internal/man3/ossl_algorithm_do_all.pod
new file mode 100644
index 000000000000..7a321d492a04
--- /dev/null
+++ b/doc/internal/man3/ossl_algorithm_do_all.pod
@@ -0,0 +1,63 @@
+=pod
+
+=head1 NAME
+
+ossl_algorithm_do_all - generic algorithm implementation iterator
+
+=head1 SYNOPSIS
+
+ void ossl_algorithm_do_all(OSSL_LIB_CTX *libctx, int operation_id,
+ OSSL_PROVIDER *provider,
+ void (*fn)(OSSL_PROVIDER *provider,
+ const OSSL_ALGORITHM *algo,
+ int no_store, void *data),
+ void *data);
+
+=head1 DESCRIPTION
+
+ossl_algorithm_do_all() looks up every algorithm it can find, given a
+library context I<libctx>, an operation identity I<operation_id> and a
+provider I<provider>.
+I<libctx> may be NULL to signify that the default library context should
+be used.
+I<operation_id> may be zero to signify that all kinds of operations
+will be looked up.
+I<provider> may be NULL to signify that all loaded providers will be
+queried.
+
+For each implementation found, the function I<fn> is called with the
+I<provider> for the implementation, the algorithm descriptor I<algo>,
+the flag I<no_store> indicating whether the algorithm descriptor may
+be remembered or not, and the caller I<data> that was passed to
+ossl_algorithm_do_all().
+
+=head1 RETURN VALUES
+
+ossl_algorithm_do_all() doesn't return any value.
+
+=head1 NOTES
+
+The function described here are mainly useful for discovery, and
+possibly display of what has been discovered, for example an
+application that wants to display the loaded providers and what they
+may offer, but also for constructors, such as
+L<ossl_method_construct(3)>.
+
+=head1 SEE ALSO
+
+L<ossl_method_construct(3)>, L<EVP_MAC_do_all_provided(3)>
+
+=head1 HISTORY
+
+This functionality was added to OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use this
+file except in compliance with the License. You can obtain a copy in the file
+LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_cmp_X509_STORE_add1_certs.pod b/doc/internal/man3/ossl_cmp_X509_STORE_add1_certs.pod
new file mode 100644
index 000000000000..97304ee40d92
--- /dev/null
+++ b/doc/internal/man3/ossl_cmp_X509_STORE_add1_certs.pod
@@ -0,0 +1,44 @@
+=pod
+
+=head1 NAME
+
+ossl_cmp_X509_STORE_add1_certs,
+ossl_cmp_X509_STORE_get1_certs
+- functions manipulating stores of certificates
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp_util.h>
+
+ int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
+ int only_self_signed);
+ STACK_OF(X509) *ossl_cmp_X509_STORE_get1_certs(X509_STORE *store);
+
+=head1 DESCRIPTION
+
+ossl_cmp_X509_STORE_add1_certs() adds all or only self-signed certificates from
+the given stack to given store. The I<certs> parameter may be NULL.
+
+ossl_cmp_X509_STORE_get1_certs() retrieves a copy of all certificates in the
+given store.
+
+=head1 RETURN VALUES
+
+ossl_cmp_X509_STORE_add1_certs() returns 1 on success, 0 on error.
+
+ossl_cmp_X509_STORE_get1_certs() returns a list of certificates, NULL on error.
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_cmp_asn1_octet_string_set1.pod b/doc/internal/man3/ossl_cmp_asn1_octet_string_set1.pod
new file mode 100644
index 000000000000..a154cda1c989
--- /dev/null
+++ b/doc/internal/man3/ossl_cmp_asn1_octet_string_set1.pod
@@ -0,0 +1,45 @@
+=pod
+
+=head1 NAME
+
+ossl_cmp_asn1_octet_string_set1,
+ossl_cmp_asn1_octet_string_set1_bytes
+- ASN.1 octet string utility functions
+
+=head1 SYNOPSIS
+
+ #include "cmp_local.h"
+
+ int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt,
+ const ASN1_OCTET_STRING *src);
+ int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING **tgt,
+ const unsigned char *bytes, int len);
+
+=head1 DESCRIPTION
+
+ossl_cmp_asn1_octet_string_set1() frees any previous value of the variable
+referenced via the I<tgt> argument and assigns either a copy of
+the ASN1_OCTET_STRING given as the I<src> argument or NULL.
+
+ossl_cmp_asn1_octet_string_set1_bytes() frees any previous value of the variable
+referenced via the I<tgt> argument and assigns either a copy of the given byte
+string (with the given length) or NULL.
+
+=head1 RETURN VALUES
+
+All functions return 1 on success, 0 on error.
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_cmp_certreq_new.pod b/doc/internal/man3/ossl_cmp_certreq_new.pod
new file mode 100644
index 000000000000..068e1b29b977
--- /dev/null
+++ b/doc/internal/man3/ossl_cmp_certreq_new.pod
@@ -0,0 +1,177 @@
+=pod
+
+=head1 NAME
+
+ossl_cmp_certreq_new,
+ossl_cmp_certrep_new,
+ossl_cmp_rr_new,
+ossl_cmp_rp_new,
+ossl_cmp_certConf_new,
+ossl_cmp_pkiconf_new,
+ossl_cmp_pollReq_new,
+ossl_cmp_pollRep_new,
+ossl_cmp_genm_new,
+ossl_cmp_genp_new,
+ossl_cmp_error_new
+- functions for generating CMP messages
+
+=head1 SYNOPSIS
+
+ #include "cmp_local.h"
+
+ OSSL_ossl_cmp_MSG *ossl_cmp_certreq_new(OSSL_CMP_CTX *ctx, int bodytype,
+ const OSSL_CRMF_MSG *crm);
+ OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype,
+ int certReqId, const OSSL_CMP_PKISI *si,
+ X509 *cert, const X509 *encryption_recip,
+ STACK_OF(X509) *chain, STACK_OF(X509) *caPubs,
+ int unprotectedErrors);
+ OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx);
+ OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si,
+ const OSSL_CRMF_CERTID *cid,
+ int unprotectedErrors);
+ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
+ const char *text);
+ OSSL_CMP_MSG *ossl_cmp_pkiconf_new(OSSL_CMP_CTX *ctx);
+ OSSL_CMP_MSG *ossl_cmp_pollReq_new(OSSL_CMP_CTX *ctx, int crid);
+ OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid, int poll_after);
+ OSSL_CMP_MSG *ossl_cmp_genm_new(OSSL_CMP_CTX *ctx);
+ OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx);
+ OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si,
+ int64_t errorCode, const char *details,
+ int unprotected);
+
+=head1 DESCRIPTION
+
+This is the internal API for creating various CMP PKIMESSAGES.
+All functions are based on L<ossl_cmp_msg_create(3)>.
+The allocate a new message, fill it with the relevant data derived from
+the given B<OSSL_CMP_CTX>, and create the applicable protection.
+
+ossl_cmp_certreq_new() creates a PKIMessage for requesting a certificate,
+which can be either of IR/CR/KUR/P10CR, depending on the given I<bodytype>.
+The CRMF message to use may be given explicitly via a non-NULL I<crm> argument,
+otherwise it is created from the information in the I<ctx>.
+
+Available CMP certificate request PKIMessage I<bodytype>s are:
+
+=over 4
+
+=item * B<OSSL_CMP_PKIBODY_IR> - Initialization Request
+
+=item * B<OSSL_CMP_PKIBODY_CR> - Certification Request
+
+=item * B<OSSL_CMP_PKIBODY_P10CR> - PKCS#10 Certification Request
+
+=item * B<OSSL_CMP_PKIBODY_KUR> - Key Update Request
+
+=back
+
+ossl_cmp_certrep_new() creates a PKIMessage for certificate response,
+which can be either of IP/CP/KUP, depending on the given I<bodytype>,
+with the given I<certReqId> and I<si> values and optionally with I<cert>,
+I<chain>, and I<caPubs>. The I<cert>, I<chain>, and I<caPubs> arguments
+are not consumed if present but their internal reference counter is increased.
+The I<encryption_recip> is currently unsupported.
+The function does not protect the message if the B<status> value in I<si>
+is B<rejected> and I<unprotectedErrors> is nonzero.
+
+Available CMP certificate response PKIMessage I<bodytype>s are:
+
+=over 4
+
+=item * B<OSSL_CMP_PKIBODY_IP> - Initialization Response
+
+=item * B<OSSL_CMP_PKIBODY_CP> - Certification Response
+
+=item * B<OSSL_CMP_PKIBODY_KUP> - Key Update Response
+
+=back
+
+The list of all CMP PKIMessage I<bodytype>s is:
+
+ #define OSSL_CMP_PKIBODY_IR 0
+ #define OSSL_CMP_PKIBODY_IP 1
+ #define OSSL_CMP_PKIBODY_CR 2
+ #define OSSL_CMP_PKIBODY_CP 3
+ #define OSSL_CMP_PKIBODY_P10CR 4
+ #define OSSL_CMP_PKIBODY_POPDECC 5
+ #define OSSL_CMP_PKIBODY_POPDECR 6
+ #define OSSL_CMP_PKIBODY_KRR 9
+ #define OSSL_CMP_PKIBODY_KRP 10
+ #define OSSL_CMP_PKIBODY_RR 11
+ #define OSSL_CMP_PKIBODY_RP 12
+ #define OSSL_CMP_PKIBODY_CCR 13
+ #define OSSL_CMP_PKIBODY_CCP 14
+ #define OSSL_CMP_PKIBODY_CKUANN 15
+ #define OSSL_CMP_PKIBODY_CANN 16
+ #define OSSL_CMP_PKIBODY_RANN 17
+ #define OSSL_CMP_PKIBODY_CRLANN 18
+ #define OSSL_CMP_PKIBODY_PKICONF 19
+ #define OSSL_CMP_PKIBODY_NESTED 20
+ #define OSSL_CMP_PKIBODY_GENM 21
+ #define OSSL_CMP_PKIBODY_GENP 22
+ #define OSSL_CMP_PKIBODY_ERROR 23
+ #define OSSL_CMP_PKIBODY_CERTCONF 24
+ #define OSSL_CMP_PKIBODY_POLLREQ 25
+ #define OSSL_CMP_PKIBODY_POLLREP 26
+
+ossl_cmp_rr_new() creates a Revocation Request message from the
+information set via OSSL_CMP_CTX_set1_oldClCert().
+
+ossl_cmp_rp_new() creates a Revocation Response message with I<si> and I<cid>.
+It does not protect the message if the B<status> value in I<si> is B<rejected>
+and I<unprotectedErrors> is nonzero.
+
+ossl_cmp_certConf_new() creates a Certificate Confirmation message for the last
+received certificate. PKIStatus defaults to B<accepted> if the I<fail_info> bit
+field is 0. Else it is taken as the failInfo of the PKIStatusInfo, PKIStatus is
+set to B<rejected>, and I<text> is copied to statusString unless it is NULL.
+
+ossl_cmp_pkiconf_new() creates a PKI Confirmation message.
+
+ossl_cmp_pollReq_new() creates a Polling Request message with certReqId set to
+I<crid>.
+
+ossl_cmp_pollRep_new() creates a Polling Response message with certReqId set to
+I<crid> and pollAfter to I<poll_after>.
+
+ossl_cmp_genm_new() creates a new General Message with an empty ITAV stack.
+
+ossl_cmp_genp_new() creates a new General Response with an empty ITAV stack.
+
+ossl_cmp_error_new() creates a new Error Message with the given contents
+I<si>, I<errorCode>, and optional I<details>.
+If I<errorCode> is positive and in the range of an OpenSSL error code,
+the library and reason strings are included in the B<errorDetails> field.
+If given, the I<details> are added to the contents of the B<errorDetails> field.
+The function does not protect the message if I<unprotectedErrors> is nonzero.
+
+=head1 NOTES
+
+CMP is specified in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+All of the functions return a new OSSL_CMP_MSG structure containing
+the generated message on success, or NULL on error.
+
+=head1 SEE ALSO
+
+L<ossl_cmp_msg_create(3)>,
+L<OSSL_CMP_CTX_new(3)>, L<ERR_load_strings(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_cmp_ctx_set1_caPubs.pod b/doc/internal/man3/ossl_cmp_ctx_set1_caPubs.pod
new file mode 100644
index 000000000000..f3c45ed56c65
--- /dev/null
+++ b/doc/internal/man3/ossl_cmp_ctx_set1_caPubs.pod
@@ -0,0 +1,76 @@
+=pod
+
+=head1 NAME
+
+ossl_cmp_ctx_set1_caPubs,
+ossl_cmp_ctx_set0_validatedSrvCert,
+ossl_cmp_ctx_set_status,
+ossl_cmp_ctx_set0_statusString,
+ossl_cmp_ctx_set_failInfoCode,
+ossl_cmp_ctx_set0_newCert,
+ossl_cmp_ctx_set1_extraCertsIn,
+ossl_cmp_ctx_set1_recipNonce
+- internal functions for managing the CMP client context datastructure
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+
+ int ossl_cmp_ctx_set1_caPubs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *caPubs);
+ int ossl_cmp_ctx_set0_validatedSrvCert(OSSL_CMP_CTX *ctx, X509 *cert);
+ int ossl_cmp_ctx_set_status(OSSL_CMP_CTX *ctx, int status);
+ int ossl_cmp_ctx_set0_statusString(OSSL_CMP_CTX *ctx,
+ OSSL_CMP_PKIFREETEXT *text);
+ int ossl_cmp_ctx_set_failInfoCode(OSSL_CMP_CTX *ctx, int fail_info);
+ int ossl_cmp_ctx_set0_newCert(OSSL_CMP_CTX *ctx, X509 *cert);
+ int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx,
+ STACK_OF(X509) *extraCertsIn);
+ int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
+ const ASN1_OCTET_STRING *nonce);
+
+=head1 DESCRIPTION
+
+ossl_cmp_ctx_set1_caPubs() copies the given stack of CA certificates
+to the caPubs field of the context.
+The reference counts of those certificates handled successfully are increased.
+
+ossl_cmp_ctx_set0_validatedSrvCert() sets the validatedSrvCert of the context,
+which caches any already validated server cert, or NULL if not available.
+
+ossl_cmp_ctx_set_status() sets the status field of the context.
+
+ossl_cmp_ctx_set0_statusString() sets the statusString field of the context.
+
+ossl_cmp_ctx_set_failInfoCode() sets the error code bits in the failInfoCode
+field of the context based on the given OSSL_CMP_PKIFAILUREINFO structure.
+
+ossl_cmp_ctx_set0_newCert() sets the given (newly enrolled) certificate
+in the context.
+
+ossl_cmp_ctx_set1_extraCertsIn() sets the extraCertsIn field of the context.
+The reference counts of those certificates handled successfully are increased.
+
+ossl_cmp_ctx_set1_recipNonce() sets the given recipient nonce in the context.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+All functions return 1 on success, 0 on error.
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_cmp_hdr_init.pod b/doc/internal/man3/ossl_cmp_hdr_init.pod
new file mode 100644
index 000000000000..a0804aa4cf2a
--- /dev/null
+++ b/doc/internal/man3/ossl_cmp_hdr_init.pod
@@ -0,0 +1,151 @@
+=pod
+
+=head1 NAME
+
+ossl_cmp_hdr_set_pvno,
+ossl_cmp_hdr_get_pvno,
+ossl_cmp_hdr_get_protection_nid,
+ossl_cmp_hdr_get0_sendernonce,
+ossl_cmp_general_name_is_NULL_DN,
+ossl_cmp_hdr_set1_sender,
+ossl_cmp_hdr_set1_recipient,
+ossl_cmp_hdr_update_messagetime,
+ossl_cmp_hdr_set1_senderKID,
+ossl_cmp_hdr_push0_freeText,
+ossl_cmp_hdr_push1_freeText,
+ossl_cmp_hdr_generalinfo_item_push0,
+ossl_cmp_hdr_generalinfo_items_push1,
+ossl_cmp_hdr_set_implicitConfirm,
+ossl_cmp_hdr_has_implicitConfirm,
+ossl_cmp_hdr_set_transactionID,
+ossl_cmp_hdr_init
+- functions handling CMP message headers
+
+=head1 SYNOPSIS
+
+ #include "cmp_local.h"
+
+ int ossl_cmp_hdr_set_pvno(OSSL_CMP_PKIHEADER *hdr, int pvno);
+ int ossl_cmp_hdr_get_pvno(const OSSL_CMP_PKIHEADER *hdr);
+ int ossl_cmp_hdr_get_protection_nid(const OSSL_CMP_PKIHEADER *hdr);
+ ASN1_OCTET_STRING
+ *ossl_cmp_hdr_get0_sendernonce(const OSSL_CMP_PKIHEADER *hdr);
+ int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name);
+
+ int ossl_cmp_hdr_set1_sender(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm);
+ int ossl_cmp_hdr_set1_recipient(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm);
+ int ossl_cmp_hdr_update_messagetime(OSSL_CMP_PKIHEADER *hdr);
+ int ossl_cmp_hdr_set1_senderKID(OSSL_CMP_PKIHEADER *hdr,
+ const ASN1_OCTET_STRING *senderKID);
+ int ossl_cmp_hdr_generalinfo_item_push0(OSSL_CMP_PKIHEADER *hdr,
+ OSSL_CMP_ITAV *itav);
+ int ossl_cmp_hdr_generalinfo_items_push1(OSSL_CMP_PKIHEADER *hdr,
+ STACK_OF(OSSL_CMP_ITAV) *itavs);
+ int ossl_cmp_hdr_push0_freeText(OSSL_CMP_PKIHEADER *hdr,
+ ASN1_UTF8STRING *text);
+ int ossl_cmp_hdr_push1_freeText(OSSL_CMP_PKIHEADER *hdr,
+ ASN1_UTF8STRING *text);
+ int ossl_cmp_hdr_set_implicitConfirm(OSSL_CMP_PKIHEADER *hdr);
+ int ossl_cmp_hdr_has_implicitConfirm(OSSL_CMP_PKIHEADER *hdr);
+ int ossl_cmp_hdr_set_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr);
+ int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr);
+
+=head1 DESCRIPTION
+
+ossl_cmp_hdr_set_pvno() sets hdr->pvno to the given B<pvno>.
+
+ossl_cmp_hdr_get_pvno() returns the pvno of the given B<hdr> or -1 on error.
+
+ossl_cmp_hdr_get_protection_nid returns the NID of the protection algorithm
+in B<hdr> or NID_undef on error.
+
+ossl_cmp_hdr_get0_sendernonce() returns the sender nonce of the given PKIHeader.
+
+ossl_cmp_general_name_is_NULL_DN() determines if the given GENERAL_NAME
+is the NULL-DN.
+
+ossl_cmp_hdr_set1_sender() sets the sender field in the given PKIHeader
+to the given X509 Name value, without consuming the pointer.
+
+ossl_cmp_hdr_set1_recipient() sets the recipient field in the given
+PKIHeader to the given X509 Name value, without consuming the pointer.
+If B<nm> is NULL, recipient is set to the NULL DN (the empty list of strings).
+
+ossl_cmp_hdr_update_messagetime() (re-)sets the messageTime to the current
+system time. As written in RFC 4210, section 5.1.1:
+The messageTime field contains the time at which the sender created the message.
+This may be useful to allow end entities to correct/check their local time for
+consistency with the time on a central system.
+
+ossl_cmp_hdr_set1_senderKID() Sets hdr->senderKID to the given string.
+In an PBMAC-protected IR this usually is a reference number issued by the CA,
+else the subject key ID of the sender's protecting certificate.
+
+ossl_cmp_hdr_push0_freeText() pushes an ASN1_UTF8STRING to
+hdr->freeText and consumes the given pointer.
+
+ossl_cmp_hdr_push1_freeText() pushes an ASN1_UTF8STRING to
+hdr->freeText and does not consume the pointer.
+
+ossl_cmp_hdr_generalinfo_item_push0() adds the given InfoTypeAndValue
+item to the hdr->generalInfo stack. Consumes the B<itav> pointer.
+
+ossl_cmp_hdr_generalinfo_items_push1() adds a copy of the B<itavs> stack to
+the generalInfo field of PKIheader of the B<hdr>. Does not consume the B<itavs>
+pointer.
+
+ossl_cmp_hdr_set_implicitConfirm() sets implicitConfirm in the generalInfo field
+of the PKIMessage header.
+
+ossl_cmp_hdr_has_implicitConfirm() returns 1 if implicitConfirm is
+set int generalInfo field of the given PKIMessage header, 0 if not.
+
+ossl_cmp_hdr_set_transactionID() sets the B<transactionID> field in C<hdr>.
+In case ctx->transactionID is NULL, it starts a new transaction
+by creating and storing a new random valuee with 128 bits length.
+
+ossl_cmp_hdr_init() initializes a PKIHeader structure based on the
+values in the given OSSL_CMP_CTX structure.
+This starts a new transaction in case ctx->transactionID is NULL.
+The sender name is copied from the subject of the client cert, if any,
+or else from the subject name provided for certification requests.
+As required by RFC 4210 section 5.1.1., if the sender name is not known
+to the client it set to the NULL-DN. In this case for identification at least
+the senderKID must be set, which we take from any referenceValue provided.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+ossl_cmp_hdr_get_pvno() returns the pvno of the given B<hdr> or -1 on error.
+
+ossl_cmp_hdr_get_protection_nid returns the respective NID, NID_undef on error.
+
+ossl_cmp_hdr_get0_sendernonce() returns the respective nonce, or NULL.
+
+ossl_cmp_general_name_is_NULL_DN() returns 1 given a NULL-DN, else 0.
+
+All other functions return 1 on success, 0 on error.
+
+See the individual functions above.
+
+=head1 SEE ALSO
+
+L<ossl_cmp_msg_create(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_cmp_mock_srv_new.pod b/doc/internal/man3/ossl_cmp_mock_srv_new.pod
new file mode 100644
index 000000000000..837ca06bb34c
--- /dev/null
+++ b/doc/internal/man3/ossl_cmp_mock_srv_new.pod
@@ -0,0 +1,87 @@
+=pod
+
+=head1 NAME
+
+ossl_cmp_mock_srv_new,
+ossl_cmp_mock_srv_free,
+ossl_cmp_mock_srv_set1_certOut,
+ossl_cmp_mock_srv_set1_chainOut,
+ossl_cmp_mock_srv_set1_caPubsOut,
+ossl_cmp_mock_srv_set_statusInfo,
+ossl_cmp_mock_srv_set_send_error,
+ossl_cmp_mock_srv_set_pollCount,
+ossl_cmp_mock_srv_set_checkAfterTime
+- functions used for testing with CMP mock server
+
+=head1 SYNOPSIS
+
+ #include "apps/cmp_mock_srv.h"
+
+ OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, const char *propq);
+ void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx);
+
+ int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert);
+ int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
+ STACK_OF(X509) *chain);
+ int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx,
+ STACK_OF(X509) *caPubs);
+ int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status,
+ int fail_info, const char *text);
+ int ossl_cmp_mock_srv_set_send_error(OSSL_CMP_SRV_CTX *srv_ctx, int val);
+ int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX *srv_ctx, int count);
+ int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec);
+
+=head1 DESCRIPTION
+
+ossl_cmp_mock_srv_new() allocates the contexts for the CMP mock server
+associated with the library context I<libctx> and property query string
+I<propq>, both of which may be NULL to select the defaults.
+
+ossl_cmp_mock_srv_free() deallocates the contexts for the CMP mock server.
+
+OSSL_CMP_SRV_CTX_set1_certOut() sets the certificate to be returned in
+cp/ip/kup.
+
+OSSL_CMP_SRV_CTX_set1_chainOut() sets the certificate chain to be added to
+the extraCerts in a cp/ip/kup.
+It should to useful to validate B<certOut>.
+
+OSSL_CMP_SRV_CTX_set1_caPubsOut() sets the caPubs to be returned in an ip.
+
+OSSL_CMP_SRV_CTX_set_statusInfo() sets the status info to be returned.
+
+OSSL_CMP_SRV_CTX_set_send_error() enables enforcement of error responses.
+
+OSSL_CMP_SRV_CTX_set_pollCount() sets the number of polls before cert response.
+
+OSSL_CMP_SRV_CTX_set_checkAfterTime() sets the number of seconds
+the client should wait for the next poll.
+
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+ossl_cmp_mock_srv() returns a B<OSSL_CMP_SRV_CTX> structure on success,
+NULL on error.
+
+ossl_cmp_mock_srv_free() does not return a value.
+
+All other functions return 1 on success, 0 on error.
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_cmp_msg_check_update.pod b/doc/internal/man3/ossl_cmp_msg_check_update.pod
new file mode 100644
index 000000000000..4e7a9224afdd
--- /dev/null
+++ b/doc/internal/man3/ossl_cmp_msg_check_update.pod
@@ -0,0 +1,95 @@
+=pod
+
+=head1 NAME
+
+ossl_cmp_allow_unprotected_cb_t,
+ossl_cmp_msg_check_update
+- generic checks on a received CMP message, updating the context
+
+=head1 SYNOPSIS
+
+ #include "cmp_local.h"
+
+ typedef int (*ossl_cmp_allow_unprotected_cb_t)(const OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *msg,
+ int invalid_protection, int arg);
+
+ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
+ ossl_cmp_allow_unprotected_cb_t cb, int cb_arg);
+
+=head1 DESCRIPTION
+
+ossl_cmp_msg_check_update() does all generic checks on the given message B<msg>,
+which may be a server response or a request by some client,
+and updates the B<ctx> accordingly.
+
+The B<msg> is checked for the following:
+
+=over 4
+
+=item its sender is of appropriate type (currently only B<X509_NAME>)
+ and matches any expected sender or srvCert subject given in B<ctx>,
+
+=item its protection is present and valid (or a callback function B<cb>
+is present and indicates that a missing or invalid protection is acceptable),
+
+=item its CMP protocol version is acceptable, namely B<OSSL_CMP_PVNO>,
+
+=item its body type is valid,
+
+=item its transaction ID matches any transaction ID given in B<ctx>, and
+
+=item its recipNonce matches any senderNonce given in B<ctx>.
+
+=back
+
+In case no protection is present and B<cb> is not NULL then this callback
+function is called with its B<invalid_protection> parameter being 0, while in
+case an invalid protection is present the B<invalid_protection> parameter is 1.
+The callback is passed also the arguments B<ctx>, B<msg>, and <cb_arg>
+(which typically contains the expected message type).
+The callback should return 1 on acceptance, 0 on rejection, or -1 on error.
+It should not put an error on the error stack since this could be misleading.
+
+ossl_cmp_msg_check_update() adds all extraCerts contained in the <msg> to
+the list of untrusted certificates in B<ctx> such that they are already usable
+for OSSL_CMP_validate_msg(), which is called internally, and for future use.
+Thus they are available also to the certificate confirmation callback, and the
+peer does not need to send them again (at least not in the same transaction).
+Note that it does not help validating the message before storing the extraCerts
+because they are not part of the protected portion of the message anyway.
+For efficiency, the extraCerts are prepended to the list so they get used first.
+
+If all checks pass then ossl_cmp_msg_check_update()
+records in B<ctx> the senderNonce of the received message as the new recipNonce
+and learns the transaction ID if none is currently present in B<ctx>.
+
+Moreover, according to RFC 4210 section 5.3.2, if the message protection is
+PBM-based then any certificates in the caPubs field are added to the list of
+trusted certificates (if set via L<OSSL_CMP_CTX_set0_trustedStore(3)>).
+This way these certs are available for validating subsequent messages in the
+same context and could apply to any Polling Response (pollRep), error, or PKI
+Confirmation (PKIConf) messages following in the same or future transactions.
+
+=head1 RETURN VALUES
+
+ossl_cmp_msg_check_update() returns 1 on success, -1 on error.
+
+=head1 SEE ALSO
+
+L<OSSL_CMP_validate_msg(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_cmp_msg_create.pod b/doc/internal/man3/ossl_cmp_msg_create.pod
new file mode 100644
index 000000000000..d4294d3e9fa6
--- /dev/null
+++ b/doc/internal/man3/ossl_cmp_msg_create.pod
@@ -0,0 +1,134 @@
+=pod
+
+=head1 NAME
+
+OSSL_CMP_PKIBODY_IR,
+OSSL_CMP_PKIBODY_IP,
+OSSL_CMP_PKIBODY_CR,
+OSSL_CMP_PKIBODY_CP,
+OSSL_CMP_PKIBODY_P10CR,
+OSSL_CMP_PKIBODY_POPDECC,
+OSSL_CMP_PKIBODY_POPDECR,
+OSSL_CMP_PKIBODY_KUR,
+OSSL_CMP_PKIBODY_KUP,
+OSSL_CMP_PKIBODY_KRR,
+OSSL_CMP_PKIBODY_KRP,
+OSSL_CMP_PKIBODY_RR,
+OSSL_CMP_PKIBODY_RP,
+OSSL_CMP_PKIBODY_CCR,
+OSSL_CMP_PKIBODY_CCP,
+OSSL_CMP_PKIBODY_CKUANN,
+OSSL_CMP_PKIBODY_CANN,
+OSSL_CMP_PKIBODY_RANN,
+OSSL_CMP_PKIBODY_CRLANN,
+OSSL_CMP_PKIBODY_PKICONF,
+OSSL_CMP_PKIBODY_NESTED,
+OSSL_CMP_PKIBODY_GENM,
+OSSL_CMP_PKIBODY_GENP,
+OSSL_CMP_PKIBODY_ERROR,
+OSSL_CMP_PKIBODY_CERTCONF,
+OSSL_CMP_PKIBODY_POLLREQ,
+OSSL_CMP_PKIBODY_POLLREP,
+ossl_cmp_bodytype_to_string,
+ossl_cmp_msg_get_bodytype,
+ossl_cmp_msg_set_bodytype,
+ossl_cmp_msg_create,
+ossl_cmp_msg_gen_ITAV_push0,
+ossl_cmp_msg_gen_ITAVs_push1
+- functions handling CMP messages
+
+=head1 SYNOPSIS
+
+ #include "cmp_local.h"
+
+ #define OSSL_CMP_PKIBODY_IR 0
+ #define OSSL_CMP_PKIBODY_IP 1
+ #define OSSL_CMP_PKIBODY_CR 2
+ #define OSSL_CMP_PKIBODY_CP 3
+ #define OSSL_CMP_PKIBODY_P10CR 4
+ #define OSSL_CMP_PKIBODY_POPDECC 5
+ #define OSSL_CMP_PKIBODY_POPDECR 6
+ #define OSSL_CMP_PKIBODY_KUR 7
+ #define OSSL_CMP_PKIBODY_KUP 8
+ #define OSSL_CMP_PKIBODY_KRR 9
+ #define OSSL_CMP_PKIBODY_KRP 10
+ #define OSSL_CMP_PKIBODY_RR 11
+ #define OSSL_CMP_PKIBODY_RP 12
+ #define OSSL_CMP_PKIBODY_CCR 13
+ #define OSSL_CMP_PKIBODY_CCP 14
+ #define OSSL_CMP_PKIBODY_CKUANN 15
+ #define OSSL_CMP_PKIBODY_CANN 16
+ #define OSSL_CMP_PKIBODY_RANN 17
+ #define OSSL_CMP_PKIBODY_CRLANN 18
+ #define OSSL_CMP_PKIBODY_PKICONF 19
+ #define OSSL_CMP_PKIBODY_NESTED 20
+ #define OSSL_CMP_PKIBODY_GENM 21
+ #define OSSL_CMP_PKIBODY_GENP 22
+ #define OSSL_CMP_PKIBODY_ERROR 23
+ #define OSSL_CMP_PKIBODY_CERTCONF 24
+ #define OSSL_CMP_PKIBODY_POLLREQ 25
+ #define OSSL_CMP_PKIBODY_POLLREP 26
+
+ const char *ossl_cmp_bodytype_to_string(int type);
+ int ossl_cmp_msg_get_bodytype(const OSSL_CMP_MSG *msg);
+ int ossl_cmp_msg_set_bodytype( OSSL_CMP_MSG *msg, int type);
+ OSSL_CMP_MSG *ossl_cmp_msg_create(OSSL_CMP_CTX *ctx, int bodytype);
+ int ossl_cmp_msg_gen_ITAV_push0(OSSL_CMP_MSG *msg, OSSL_CMP_ITAV *itav);
+ int ossl_cmp_msg_gen_ITAVs_push1(OSSL_CMP_MSG *msg,
+ STACK_OF(OSSL_CMP_ITAV) *itavs);
+
+=head1 DESCRIPTION
+
+ossl_cmp_bodytype_to_string() returns the name of the given body type as string,
+or "illegal body type" on error.
+
+ossl_cmp_msg_get_bodytype() returns the body type of the given PKIMessage,
+or -1 on error.
+
+ossl_cmp_msg_set_bodytype() sets the type of the message contained in
+the PKIMessage body field.
+Returns 1 on success, 0 on error.
+
+ossl_cmp_msg_create() creates and initializes an B<OSSL_CMP_MSG> structure,
+using fields of B<ctx> for the header and B<bodytype> for the body.
+If the current B<transactionID> field in I<ctx> indicates that there is no
+current transaction, it creates and stores a random one with 128 bits length.
+Thus, the I<ctx> may be modified by this and related ossl_cmp_*_new() functions.
+Returns pointer to created B<OSSL_CMP_MSG> on success, NULL on error.
+
+ossl_cmp_msg_gen_ITAV_push0() pushes the B<itav> to the body of the
+PKIMessage B<msg> of GenMsg or GenRep type. Consumes the B<itavs> pointer.
+Returns 1 on success, 0 on error.
+
+ossl_cmp_msg_gen_ITAVs_push1() adds a copy of the B<itavs> stack to the body
+of the PKIMessage B<msg> of GenMsg or GenRep type.
+Does not consume the B<itavs> pointer nor its elements.
+Returns 1 on success, 0 on error.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+See the individual functions above.
+
+=head1 SEE ALSO
+
+L<ossl_cmp_hdr_init(3)>,
+L<OSSL_CMP_CTX_new(3)>, L<OSSL_CMP_exec_certreq(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_cmp_msg_protect.pod b/doc/internal/man3/ossl_cmp_msg_protect.pod
new file mode 100644
index 000000000000..ae7771280763
--- /dev/null
+++ b/doc/internal/man3/ossl_cmp_msg_protect.pod
@@ -0,0 +1,62 @@
+=pod
+
+=head1 NAME
+
+ossl_cmp_calc_protection,
+ossl_cmp_msg_protect,
+ossl_cmp_msg_add_extraCerts
+- functions for producing CMP message protection
+
+=head1 SYNOPSIS
+
+ #include "cmp_local.h"
+
+ ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *msg);
+ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
+ int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
+
+=head1 DESCRIPTION
+
+ossl_cmp_calc_protection() calculates the protection for the given I<msg>
+according to the algorithm and parameters in the message header's protectionAlg
+using the credentials, library context, and property criteria in the I<ctx>.
+
+ossl_cmp_msg_protect() (re-)protects the given message I<msg> using an algorithm
+depending on the available context information given in the I<ctx>.
+If there is a secretValue it selects PBMAC, else if there is a protection cert
+it selects Signature and uses L<ossl_cmp_msg_add_extraCerts(3)>.
+It also sets the protectionAlg field in the message header accordingly.
+
+ossl_cmp_msg_add_extraCerts() adds elements to the extraCerts field in I<msg>.
+If signature-based message protection is used it adds first the CMP signer cert
+ctx->cert and then its chain ctx->chain. If this chain is not present in I<ctx>
+tries to build it using ctx->untrusted and caches the result in ctx->chain.
+In any case all the certificates explicitly specified to be sent out (i.e.,
+I<ctx->extraCertsOut>) are added. Note that it will NOT add the root certificate
+of the chain, i.e, the trust anchor (unless it is part of extraCertsOut).
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+ossl_cmp_calc_protection() returns the protection on success, else NULL.
+
+All other functions return 1 on success, 0 on error.
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_cmp_pkisi_get_status.pod b/doc/internal/man3/ossl_cmp_pkisi_get_status.pod
new file mode 100644
index 000000000000..21f6f90b39d3
--- /dev/null
+++ b/doc/internal/man3/ossl_cmp_pkisi_get_status.pod
@@ -0,0 +1,99 @@
+=pod
+
+=head1 NAME
+
+ossl_cmp_certresponse_get1_cert,
+ossl_cmp_pkisi_get_status,
+ossl_cmp_PKIStatus_to_string,
+ossl_cmp_pkisi_get0_statusString,
+ossl_cmp_pkisi_get_pkifailureinfo,
+ossl_cmp_pkisi_check_pkifailureinfo
+- functions for managing PKI status information
+
+=head1 SYNOPSIS
+
+ #include "cmp.h"
+
+# define OSSL_CMP_PKIFAILUREINFO_badAlg 0
+# define OSSL_CMP_PKIFAILUREINFO_badMessageCheck 1
+# define OSSL_CMP_PKIFAILUREINFO_badRequest 2
+# define OSSL_CMP_PKIFAILUREINFO_badTime 3
+# define OSSL_CMP_PKIFAILUREINFO_badCertId 4
+# define OSSL_CMP_PKIFAILUREINFO_badDataFormat 5
+# define OSSL_CMP_PKIFAILUREINFO_wrongAuthority 6
+# define OSSL_CMP_PKIFAILUREINFO_incorrectData 7
+# define OSSL_CMP_PKIFAILUREINFO_missingTimeStamp 8
+# define OSSL_CMP_PKIFAILUREINFO_badPOP 9
+# define OSSL_CMP_PKIFAILUREINFO_certRevoked 10
+# define OSSL_CMP_PKIFAILUREINFO_certConfirmed 11
+# define OSSL_CMP_PKIFAILUREINFO_wrongIntegrity 12
+# define OSSL_CMP_PKIFAILUREINFO_badRecipientNonce 13
+# define OSSL_CMP_PKIFAILUREINFO_timeNotAvailable 14
+# define OSSL_CMP_PKIFAILUREINFO_unacceptedPolicy 15
+# define OSSL_CMP_PKIFAILUREINFO_unacceptedExtension 16
+# define OSSL_CMP_PKIFAILUREINFO_addInfoNotAvailable 17
+# define OSSL_CMP_PKIFAILUREINFO_badSenderNonce 18
+# define OSSL_CMP_PKIFAILUREINFO_badCertTemplate 19
+# define OSSL_CMP_PKIFAILUREINFO_signerNotTrusted 20
+# define OSSL_CMP_PKIFAILUREINFO_transactionIdInUse 21
+# define OSSL_CMP_PKIFAILUREINFO_unsupportedVersion 22
+# define OSSL_CMP_PKIFAILUREINFO_notAuthorized 23
+# define OSSL_CMP_PKIFAILUREINFO_systemUnavail 24
+# define OSSL_CMP_PKIFAILUREINFO_systemFailure 25
+# define OSSL_CMP_PKIFAILUREINFO_duplicateCertReq 26
+# define OSSL_CMP_PKIFAILUREINFO_MAX 26
+
+ X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CERTRESPONSE *crep,
+ const OSSL_CMP_CTX *ctx, EVP_PKEY *pkey);
+ int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si);
+ const char *ossl_cmp_PKIStatus_to_string(int status);
+ OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusString(const OSSL_CMP_PKISI *si);
+ int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si);
+ int ossl_cmp_pkisi_check_pkifailureinfo(const OSSL_CMP_PKISI *si, int index);
+
+=head1 DESCRIPTION
+
+ossl_cmp_certresponse_get1_cert() returns a pointer to a copy of the newly
+enrolled certificate from the given certResponse I<crep>, or NULL on error.
+In case of indirect POPO uses data from the I<ctx> and the private key I<pkey>.
+
+ossl_cmp_pkisi_get_status() returns the PKIStatus of I<si>, or -1 on error.
+
+ossl_cmp_PKIStatus_to_string() returns a human-readable string representing
+the PKIStatus values as specified in RFC 4210, Appendix F.
+
+ossl_cmp_pkisi_get0_statusString() returns a direct pointer to the statusString
+field contained in I<si>.
+
+ossl_cmp_pkisi_get_pkifailureinfo() returns the PKIFailureInfo bits
+of I<si>, encoded as integer, or -1 on error.
+
+ossl_cmp_pkisi_check_pkifailureinfo() returns the state of the bit (0 or 1)
+with index I<index> in the PKIFailureInfo of the I<si>, or -1 on error.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+See the individual functions above.
+
+=head1 SEE ALSO
+
+L<OSSL_CMP_CTX_new(3)>, L<ossl_cmp_certreq_new(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_cmp_print_log.pod b/doc/internal/man3/ossl_cmp_print_log.pod
new file mode 100644
index 000000000000..f4384402e584
--- /dev/null
+++ b/doc/internal/man3/ossl_cmp_print_log.pod
@@ -0,0 +1,108 @@
+=pod
+
+=head1 NAME
+
+ossl_cmp_print_log,
+ossl_cmp_alert,
+ossl_cmp_err,
+ossl_cmp_warn,
+ossl_cmp_info,
+ossl_cmp_debug,
+ossl_cmp_log,
+ossl_cmp_log1,
+ossl_cmp_log2,
+ossl_cmp_log3,
+ossl_cmp_log4,
+ossl_cmp_log_parse_metadata,
+ossl_cmp_add_error_data,
+ossl_cmp_add_error_line
+- logging and error reporting support for CMP
+
+=head1 SYNOPSIS
+
+ #include "cmp_local.h"
+
+ int ossl_cmp_print_log(OSSL_CMP_severity level, const OSSL_CMP_CTX *ctx,
+ const char *func, const char *file, int line,
+ const char *level_str, const char *format, ...);
+ #define ossl_cmp_alert(ctx, msg)
+ #define ossl_cmp_err(ctx, msg)
+ #define ossl_cmp_warn(ctx, msg)
+ #define ossl_cmp_info(ctx, msg)
+ #define ossl_cmp_debug(ctx, (msg)
+ #define ossl_cmp_log(level, ctx, msg)
+ #define ossl_cmp_log1(level, ctx, fmt, arg1)
+ #define ossl_cmp_log2(level, ctx, fmt, arg1, arg2)
+ #define ossl_cmp_log3(level, ctx, fmt, arg1, arg2, arg3)
+ #define ossl_cmp_log4(level, ctx, fmt, arg1, arg2, arg3, arg4)
+ const char *ossl_cmp_log_parse_metadata(const char *buf,
+ OSSL_CMP_severity *level, char **func,
+ char **file, int *line);
+
+ #define ossl_cmp_add_error_data(txt)
+ #define ossl_cmp_add_error_line(txt)
+
+=head1 DESCRIPTION
+
+ossl_cmp_print_log() prints CMP log messages (i.e., diagnostic info) via the
+log callback of the B<ctx> if present and the severity level is sufficient.
+If the trace API if enabled the function uses it, prepending the function name,
+filename, line number, and severity information to the message being output.
+In any case the B<level>, B<func>, B<file>, and B<line> parameters
+and the message constructed using the given B<format> and variable further
+argument list are passed to the log callback function (unless it is NULL).
+The B<ctx>, B<func>, B<file>, and B<level_str> arguments may be NULL.
+
+ossl_cmp_alert(), ossl_cmp_err(), ossl_cmp_warn(), ossl_cmp_info(), and
+ossl_cmp_debug() output a simple alert/error/warning/info/debug message
+via ossl_cmp_print_log().
+
+ossl_cmp_log(), ossl_cmp_log1(), ossl_cmp_log2(), ossl_cmp_log3(), and
+ossl_cmp_log4() output a log message with the given severity,
+constructing the message text from the given format and arguments.
+
+ossl_cmp_log_parse_metadata() parses the given message buffer I<buf> populated
+by ossl_cmp_log() etc.
+according to the pattern OSSL_CMP_LOG_START#level ": %s\n", filling in
+the variable pointed to by I<level> with the severity level or -1,
+the variable pointed to by I<func> with the function name string or NULL,
+the variable pointed to by I<file> with the filename string or NULL, and
+the variable pointed to by I<line> with the line number or -1.
+Any string returned via I<*func> and I<*file> must be freed by the caller.
+
+ossl_cmp_add_error_data() is a macro calling
+L<ERR_add_error_txt(3)> with the separator being ":".
+
+ossl_cmp_add_error_line() is a macro calling
+L<ERR_add_error_txt(3)> with the separator being "\n".
+
+=head1 RETURN VALUES
+
+ossl_cmp_log_parse_metadata() returns the pointer to the actual message text
+after the OSSL_CMP_LOG_PREFIX and level and ':' if found in the buffer,
+else the beginning of the buffer.
+
+ossl_cmp_add_error_data() and
+ossl_cmp_add_error_line()
+do not return anything.
+
+All other functions return 1 on success, 0 on error.
+
+=head1 SEE ALSO
+
+L<ERR_add_error_txt(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_ends_with_dirsep.pod b/doc/internal/man3/ossl_ends_with_dirsep.pod
new file mode 100644
index 000000000000..d19ce7a3b97c
--- /dev/null
+++ b/doc/internal/man3/ossl_ends_with_dirsep.pod
@@ -0,0 +1,45 @@
+=pod
+
+=head1 NAME
+
+ossl_ends_with_dirsep, ossl_is_absolute_path
+- internal functions to work with paths
+
+=head1 SYNOPSIS
+
+ #include "internal/cryptlib.h"
+
+ int ossl_ends_with_dirsep(const char *path);
+
+ int ossl_is_absolute_path(const char *path);
+
+=head1 DESCRIPTION
+
+ossl_ends_with_dirsep() detects whether the I<path> ends with a directory
+separator in a platform agnostic way.
+
+ossl_is_absolute_path() detects whether the I<path> is absolute path in
+a platform agnostic way.
+
+=head1 RETURN VALUES
+
+ossl_ends_with_dirsep() returns 1 if the I<path> ends with a directory
+separator, 0 otherwise.
+
+ossl_is_absolute_path() returns 1 if the I<path> is absolute, 0 otherwise.
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
+
diff --git a/doc/internal/man3/ossl_global_properties_no_mirrored.pod b/doc/internal/man3/ossl_global_properties_no_mirrored.pod
new file mode 100644
index 000000000000..6c39ccbc0ffe
--- /dev/null
+++ b/doc/internal/man3/ossl_global_properties_no_mirrored.pod
@@ -0,0 +1,56 @@
+=pod
+
+=head1 NAME
+
+ossl_property_list_to_string, ossl_global_properties_no_mirrored
+- internal property routines
+
+=head1 SYNOPSIS
+
+ #include "internal/property.h"
+
+ size_t ossl_property_list_to_string(OSSL_LIB_CTX *ctx,
+ const OSSL_PROPERTY_LIST *list, char *buf,
+ size_t bufsize);
+
+ int ossl_global_properties_no_mirrored(OSSL_LIB_CTX *libctx);
+ void ossl_global_properties_no_mirrored(OSSL_LIB_CTX *libctx);
+
+
+=head1 DESCRIPTION
+
+ossl_property_list_to_string() takes a given OSSL_PROPERTY_LIST in I<list> and
+converts it to a string. If I<buf> is non NULL then the string will be stored
+in I<buf>. The size of the buffer is provided in I<bufsize>. If I<bufsize> is
+too short then the string will be truncated. If I<buf> is NULL then the length
+of the string is still calculated and returned. If the property list has no
+properties in it then the empty string will be stored in I<buf>.
+
+ossl_global_properties_no_mirrored() checks whether mirroring of global
+properties from a parent library context is allowed for the current library
+context.
+
+ossl_global_properties_no_mirrored() prevents future mirroring of global
+properties from a parent library context for the current library context.
+
+=head1 RETURN VALUES
+
+ossl_property_list_to_string() returns the length of the string, or 0 on error.
+
+ossl_global_properties_no_mirrored() returns 1 if mirroring of global properties
+is not allowed, or 0 otherwise.
+
+=head1 HISTORY
+
+The functions described here were all added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_init_thread_deregister.pod b/doc/internal/man3/ossl_init_thread_deregister.pod
new file mode 100644
index 000000000000..6c9e0b5b8998
--- /dev/null
+++ b/doc/internal/man3/ossl_init_thread_deregister.pod
@@ -0,0 +1,66 @@
+=pod
+
+=head1 NAME
+
+OSSL_thread_stop_handler_fn,
+ossl_init_thread_start,
+ossl_init_thread_deregister
+- internal thread routines
+
+=head1 SYNOPSIS
+
+ #include "crypto/cryptlib.h"
+ #include <openssl/core.h>
+
+ typedef void (*OSSL_thread_stop_handler_fn)(void *arg);
+
+ int ossl_init_thread_start(const void *index, void *arg,
+ OSSL_thread_stop_handler_fn handfn);
+ int ossl_init_thread_deregister(void *index);
+
+=head1 DESCRIPTION
+
+Thread aware code may be informed about when a thread is stopping, typically to
+perform some cleanup operation.
+Thread stop events may be detected by OpenSSL either automatically (using the
+capabilities of the underlying threading library) where possible or explicitly
+by the application calling OPENSSL_thread_stop() or OPENSSL_thread_stop_ex().
+
+Thread aware code registers a "stop handler" for each new thread that it uses.
+Typically, when a new thread is being used, code will add a new value to some
+thread local variable and then register a stop handler. When the thread is
+stopping the stop handler is called (while on that thread) and the code can
+clean up the value stored in the thread local variable.
+
+A new stop handler is registered using the function ossl_init_thread_start().
+The I<index> parameter should be a unique value that can be used to identify a
+set of common stop handlers and is passed in a later call to
+ossl_init_thread_deregister. If no later call to ossl_init_thread_deregister is
+made then NULL can be passed for this parameter. The I<arg> parameter is passed
+back as an argument to the stop handler when it is later invoked. Finally the
+I<handfn> is a function pointer to the stop handler itself.
+
+In the event that previously registered stop handlers need to be deregistered
+then this can be done using the function ossl_init_thread_deregister().
+This will deregister all stop handlers (no matter which thread they were
+registered for) which the same I<index> value.
+
+=head1 RETURN VALUES
+
+ossl_init_thread_start() and ossl_init_thread_deregister() return 1 for success
+or 0 on error.
+
+=head1 HISTORY
+
+The functions described here were all added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_lib_ctx_get_data.pod b/doc/internal/man3/ossl_lib_ctx_get_data.pod
new file mode 100644
index 000000000000..faedf7275f08
--- /dev/null
+++ b/doc/internal/man3/ossl_lib_ctx_get_data.pod
@@ -0,0 +1,154 @@
+=pod
+
+=head1 NAME
+
+ossl_lib_ctx_get_data, ossl_lib_ctx_run_once, ossl_lib_ctx_onfree,
+ossl_lib_ctx_is_child
+- internal OSSL_LIB_CTX routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/types.h>
+ #include "internal/cryptlib.h"
+
+ typedef struct ossl_lib_ctx_method {
+ int priority;
+ void *(*new_func)(OSSL_LIB_CTX *ctx);
+ void (*free_func)(void *);
+ } OSSL_LIB_CTX_METHOD;
+
+ void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index,
+ const OSSL_LIB_CTX_METHOD *meth);
+
+ int ossl_lib_ctx_run_once(OSSL_LIB_CTX *ctx, unsigned int idx,
+ ossl_lib_ctx_run_once_fn run_once_fn);
+ int ossl_lib_ctx_onfree(OSSL_LIB_CTX *ctx, ossl_lib_ctx_onfree_fn onfreefn);
+
+ int ossl_lib_ctx_is_child(OSSL_LIB_CTX *ctx);
+
+=head1 DESCRIPTION
+
+Internally, the OpenSSL library context B<OSSL_LIB_CTX> is implemented
+as a B<CRYPTO_EX_DATA>, which allows data from diverse parts of the
+library to be added and removed dynamically.
+Each such data item must have a corresponding CRYPTO_EX_DATA index
+associated with it. Unlike normal CRYPTO_EX_DATA objects we use static indexes
+to identify data items. These are mapped transparently to CRYPTO_EX_DATA dynamic
+indexes internally to the implementation.
+See the example further down to see how that's done.
+
+ossl_lib_ctx_get_data() is used to retrieve a pointer to the data in
+the library context I<ctx> associated with the given I<index>. An
+OSSL_LIB_CTX_METHOD must be defined and given in the I<meth> parameter. The index
+for it should be defined in cryptlib.h. The functions through the method are
+used to create or free items that are stored at that index whenever a library
+context is created or freed, meaning that the code that use a data item of that
+index doesn't have to worry about that, just use the data available.
+
+Deallocation of an index happens automatically when the library
+context is freed.
+
+ossl_lib_ctx_run_once is used to run some initialisation routine I<run_once_fn>
+exactly once per library context I<ctx> object. Each initialisation routine
+should be allocate a unique run once index in cryptlib.h.
+
+Any resources allocated via a run once initialisation routine can be cleaned up
+using ossl_lib_ctx_onfree. This associates an "on free" routine I<onfreefn> with
+the library context I<ctx>. When I<ctx> is freed all associated "on free"
+routines are called.
+
+ossl_lib_ctx_is_child() returns 1 if this library context is a child and 0
+otherwise.
+
+=head1 RETURN VALUES
+
+ossl_lib_ctx_get_data() returns a pointer on success, or NULL on
+failure.
+
+=head1 EXAMPLES
+
+=head2 Initialization
+
+For a type C<FOO> that should end up in the OpenSSL library context, a
+small bit of initialization is needed, i.e. to associate a constructor
+and a destructor to an index.
+
+ typedef struct foo_st {
+ int i;
+ void *data;
+ } FOO;
+
+ static void *foo_new(OSSL_LIB_CTX *ctx)
+ {
+ FOO *ptr = OPENSSL_zalloc(sizeof(*foo));
+ if (ptr != NULL)
+ ptr->i = 42;
+ return ptr;
+ }
+ static void foo_free(void *ptr)
+ {
+ OPENSSL_free(ptr);
+ }
+
+ /*
+ * Include a reference to this in the methods table in context.c
+ * OSSL_LIB_CTX_FOO_INDEX should be added to internal/cryptlib.h
+ * Priorities can be OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
+ * OSSL_LIB_CTX_METHOD_PRIORITY_1, OSSL_LIB_CTX_METHOD_PRIORITY_2, etc.
+ * Default priority is low (0). The higher the priority the earlier the
+ * method's destructor will be called when the library context is cleaned up.
+ */
+ const OSSL_LIB_CTX_METHOD foo_method = {
+ OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
+ foo_new,
+ foo_free
+ };
+
+=head2 Usage
+
+To get and use the data stored in the library context, simply do this:
+
+ /*
+ * ctx is received from a caller,
+ */
+ FOO *data = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_FOO_INDEX, &foo_method);
+
+=head2 Run Once
+
+ void foo_cleanup(OSSL_LIB_CTX *ctx)
+ {
+ /* Free foo resources associated with ctx */
+ }
+
+ static ossl_lib_ctx_run_once_fn do_foo_init;
+ static int do_foo_init(OSSL_LIB_CTX *ctx)
+ {
+ /* Allocate and initialise some foo resources and associated with ctx */
+ return ossl_lib_ctx_onfree(ctx, &foo_cleanup)
+ }
+
+ int foo_some_function(OSSL_LIB_CTX *ctx)
+ {
+ if (!ossl_lib_ctx_run_once(ctx,
+ OSSL_LIB_CTX_FOO_RUN_ONCE_INDEX,
+ do_foo_init))
+ return 0;
+
+ /* Do some work using foo resources in ctx */
+ }
+
+
+=head1 SEE ALSO
+
+L<OSSL_LIB_CTX(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_method_construct.pod b/doc/internal/man3/ossl_method_construct.pod
new file mode 100644
index 000000000000..3683798b06b4
--- /dev/null
+++ b/doc/internal/man3/ossl_method_construct.pod
@@ -0,0 +1,158 @@
+=pod
+
+=head1 NAME
+
+OSSL_METHOD_CONSTRUCT_METHOD, ossl_method_construct
+- generic method constructor
+
+=head1 SYNOPSIS
+
+ #include "internal/core.h"
+
+ struct ossl_method_construct_method_st {
+ /* Get a temporary store */
+ void *(*get_tmp_store)(void *data);
+ /* Get an already existing method from a store */
+ void *(*get)(void *store, const OSSL_PROVIDER *prov, void *data);
+ /* Store a method in a store */
+ int (*put)(void *store, void *method, const OSSL_PROVIDER *prov,
+ const char *name, const char *propdef, void *data);
+ /* Construct a new method */
+ void *(*construct)(const OSSL_ALGORITHM *algodef, OSSL_PROVIDER *prov,
+ void *data);
+ /* Destruct a method */
+ void (*destruct)(void *method, void *data);
+ };
+ typedef struct ossl_method_construct_method OSSL_METHOD_CONSTRUCT_METHOD;
+
+ void *ossl_method_construct(OSSL_LIB_CTX *ctx, int operation_id,
+ OSSL_PROVIDER *prov, int force_cache,
+ OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data);
+
+
+=head1 DESCRIPTION
+
+All libcrypto subsystems that want to create their own methods based
+on provider dispatch tables need to do so in exactly the same way.
+ossl_method_construct() does this while leaving it to the subsystems
+to define more precisely how the methods are created, stored, etc.
+
+It's important to keep in mind that a method is identified by three things:
+
+=over 4
+
+=item The operation identity
+
+=item The name of the algorithm
+
+=item The properties associated with the algorithm implementation
+
+=back
+
+=head2 Functions
+
+ossl_method_construct() creates a method by asking all available
+providers for a dispatch table given an I<operation_id>, and then
+calling the appropriate functions given by the subsystem specific
+method creator through I<mcm> and the data in I<mcm_data> (which is
+passed by ossl_method_construct()).
+If I<prov> is not NULL, only that provider is considered, which is
+useful in the case a method must be found in that particular
+provider.
+
+This function assumes that the subsystem method creator implements
+reference counting and acts accordingly (i.e. it will call the
+subsystem destruct() method to decrement the reference count when
+appropriate).
+
+=head2 Structures
+
+A central part of constructing a subsystem specific method is to give
+ossl_method_construct a set of functions, all in the
+B<OSSL_METHOD_CONSTRUCT_METHOD> structure, which holds the following
+function pointers:
+
+=over 4
+
+=item get_tmp_store()
+
+Create a temporary method store in the scope of the library context I<ctx>.
+This store is used to temporarily store methods for easier lookup, for
+when the provider doesn't want its dispatch table stored in a longer
+term cache.
+
+=item get()
+
+Look up an already existing method from a store by name.
+
+The store may be given with I<store>.
+NULL is a valid value and means that a subsystem default store
+must be used.
+This default store should be stored in the library context I<libctx>.
+
+The method to be looked up should be identified with data found in I<data>
+(which is the I<mcm_data> that was passed to ossl_construct_method()).
+In other words, the ossl_method_construct() caller is entirely responsible
+for ensuring the necesssary data is made available.
+
+Optionally, I<prov> may be given as a search criterion, to narrow down the
+search of a method belonging to just one provider.
+
+This function is expected to increment the resulting method's reference count.
+
+=item put()
+
+Places the I<method> created by the construct() function (see below)
+in a store.
+
+The store may be given with I<store>.
+NULL is a valid value and means that a subsystem default store
+must be used.
+This default store should be stored in the library context I<libctx>.
+
+The method should be associated with the given provider I<prov>,
+I<name> and property definition I<propdef> as well as any
+identification data given through I<data> (which is the I<mcm_data>
+that was passed to ossl_construct_method()).
+
+This function is expected to increment the I<method>'s reference count.
+
+=item construct()
+
+Constructs a subsystem method for the given I<name> and the given
+dispatch table I<fns>.
+
+The associated provider object I<prov> is passed as well, to make
+it possible for the subsystem constructor to keep a reference, which
+is recommended.
+If such a reference is kept, the I<provider object> reference counter
+must be incremented, using ossl_provider_up_ref().
+
+This function is expected to set the method's reference count to 1.
+
+=item destruct()
+
+Decrement the I<method>'s reference count, and destruct it when
+the reference count reaches zero.
+
+=back
+
+=head1 RETURN VALUES
+
+ossl_method_construct() returns a constructed method on success, or
+NULL on error.
+
+=head1 HISTORY
+
+This functionality was added to OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use this
+file except in compliance with the License. You can obtain a copy in the file
+LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_namemap_new.pod b/doc/internal/man3/ossl_namemap_new.pod
new file mode 100644
index 000000000000..ff247e87b03c
--- /dev/null
+++ b/doc/internal/man3/ossl_namemap_new.pod
@@ -0,0 +1,129 @@
+=pod
+
+=head1 NAME
+
+ossl_namemap_new, ossl_namemap_free, ossl_namemap_stored, ossl_namemap_empty,
+ossl_namemap_add_name, ossl_namemap_add_name_n, ossl_namemap_add_names,
+ossl_namemap_name2num, ossl_namemap_name2num_n,
+ossl_namemap_doall_names
+- internal number E<lt>-E<gt> name map
+
+=head1 SYNOPSIS
+
+ #include "internal/cryptlib.h"
+
+ OSSL_NAMEMAP *ossl_namemap_stored(OSSL_LIB_CTX *libctx);
+
+ OSSL_NAMEMAP *ossl_namemap_new(void);
+ void ossl_namemap_free(OSSL_NAMEMAP *namemap);
+ int ossl_namemap_empty(OSSL_NAMEMAP *namemap);
+
+ int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number, const char *name);
+ int ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number,
+ const char *name, size_t name_len);
+
+ int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name);
+ int ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap,
+ const char *name, size_t name_len);
+ int ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number,
+ void (*fn)(const char *name, void *data),
+ void *data);
+
+ int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number,
+ const char *names, const char separator);
+
+=head1 DESCRIPTION
+
+A B<OSSL_NAMEMAP> is a one-to-many number E<lt>-E<gt> names map, which
+can be used to give any arbitrary set of names (any string) a unique
+dynamic identity that is valid throughout the lifetime of the associated
+library context.
+
+ossl_namemap_new() and ossl_namemap_free() construct and destruct a
+new B<OSSL_NAMEMAP>.
+This is suitable to use when the B<OSSL_NAMEMAP> is embedded in other
+structures, or should be independent for any reason.
+
+ossl_namemap_empty() checks if the given B<OSSL_NAMEMAP> is empty or
+not.
+
+ossl_namemap_stored() finds or auto-creates the default namemap in the
+given library context.
+The returned B<OSSL_NAMEMAP> can't be destructed using
+ossl_namemap_free().
+
+ossl_namemap_add_name() adds a new name to the namemap if it's not already
+present.
+If the given I<number> is zero, a new number will be allocated to
+identify this I<name>.
+If the given I<number> is nonzero, the I<name> is added to the set of
+names already associated with that number.
+
+ossl_namemap_name2num() finds the number corresponding to the given
+I<name>.
+
+ossl_namemap_add_name_n() and ossl_namemap_name2num_n() do the same thing
+as ossl_namemap_add_name() and ossl_namemap_name2num(), but take a string
+length I<name_len> as well, allowing the caller to use a fragment of
+a string as a name.
+
+ossl_namemap_doall_names() walks through all names associated with
+I<number> in the given I<namemap> and calls the function I<fn> for
+each of them.
+I<fn> is also passed the I<data> argument, which allows any caller to
+pass extra data for that function to use.
+
+ossl_namemap_add_names() divides up a set of names given in I<names>,
+separated by I<separator>, and adds each to the I<namemap>, all with
+the same number. If some of them already exist in the I<namemap>,
+they must all have the same associated number, which will be adopted
+for any name that doesn't exist yet.
+
+=head1 RETURN VALUES
+
+ossl_namemap_new() and ossl_namemap_stored() return the pointer to a
+B<OSSL_NAMEMAP>, or NULL on error.
+
+ossl_namemap_empty() returns 1 if the B<OSSL_NAMEMAP> is NULL or
+empty, 0 if it's not empty, or -1 on internal error (such as inability
+to lock).
+
+ossl_namemap_add_name() and ossl_namemap_add_name_n() return the number
+associated with the added string, or zero on error.
+
+ossl_namemap_num2names() returns a pointer to a NULL-terminated list of
+pointers to the names corresponding to the given number, or NULL if
+it's undefined in the given B<OSSL_NAMEMAP>.
+
+ossl_namemap_name2num() and ossl_namemap_name2num_n() return the number
+corresponding to the given name, or 0 if it's undefined in the given
+B<OSSL_NAMEMAP>.
+
+ossl_namemap_doall_names() returns 1 if the callback was called for all names. A
+return value of 0 means that the callback was not called for any names.
+
+ossl_namemap_add_names() returns the number associated with the added
+names, or zero on error.
+
+=head1 NOTES
+
+The result from ossl_namemap_num2names() isn't thread safe, other threads
+dealing with the same namemap may cause the list of names to change
+location.
+It is therefore strongly recommended to only use the result in code
+guarded by a thread lock.
+
+=head1 HISTORY
+
+The functions described here were all added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_provider_add_conf_module.pod b/doc/internal/man3/ossl_provider_add_conf_module.pod
new file mode 100644
index 000000000000..7e4d5097f634
--- /dev/null
+++ b/doc/internal/man3/ossl_provider_add_conf_module.pod
@@ -0,0 +1,41 @@
+=pod
+
+=head1 NAME
+
+ossl_provider_add_conf_module - internal standard configuration module
+
+=head1 SYNOPSIS
+
+ #include "internal/provider.h"
+
+ /* Configuration */
+ void ossl_provider_add_conf_module(void);
+
+=head1 DESCRIPTION
+
+ossl_provider_add_conf_module() adds the standard configuration module
+for providers.
+This allows providers to be configured with an OpenSSL L<config(5)> file.
+
+=head1 RETURN VALUES
+
+ossl_provider_add_conf_module() doesn't return any value.
+
+=head1 SEE ALSO
+
+L<OSSL_PROVIDER(3)>, L<ossl_provider_new(3)>
+
+=head1 HISTORY
+
+The functions described here were all added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_provider_new.pod b/doc/internal/man3/ossl_provider_new.pod
new file mode 100644
index 000000000000..8bd5594c484c
--- /dev/null
+++ b/doc/internal/man3/ossl_provider_new.pod
@@ -0,0 +1,400 @@
+=pod
+
+=head1 NAME
+
+ossl_provider_find, ossl_provider_new, ossl_provider_up_ref,
+ossl_provider_free,
+ossl_provider_set_fallback, ossl_provider_set_module_path,
+ossl_provider_add_parameter, ossl_provider_set_child, ossl_provider_get_parent,
+ossl_provider_up_ref_parent, ossl_provider_free_parent,
+ossl_provider_default_props_update, ossl_provider_get0_dispatch,
+ossl_provider_init_as_child, ossl_provider_deinit_child,
+ossl_provider_activate, ossl_provider_deactivate, ossl_provider_add_to_store,
+ossl_provider_ctx,
+ossl_provider_doall_activated,
+ossl_provider_name, ossl_provider_dso,
+ossl_provider_module_name, ossl_provider_module_path,
+ossl_provider_libctx,
+ossl_provider_teardown, ossl_provider_gettable_params,
+ossl_provider_get_params,
+ossl_provider_query_operation, ossl_provider_unquery_operation,
+ossl_provider_set_operation_bit, ossl_provider_test_operation_bit,
+ossl_provider_get_capabilities
+- internal provider routines
+
+=head1 SYNOPSIS
+
+ #include "internal/provider.h"
+
+ OSSL_PROVIDER *ossl_provider_find(OSSL_LIB_CTX *libctx, const char *name,
+ int noconfig);
+ OSSL_PROVIDER *ossl_provider_new(OSSL_LIB_CTX *libctx, const char *name,
+ ossl_provider_init_fn *init_function
+ int noconfig);
+ int ossl_provider_up_ref(OSSL_PROVIDER *prov);
+ void ossl_provider_free(OSSL_PROVIDER *prov);
+
+ /* Setters */
+ int ossl_provider_set_fallback(OSSL_PROVIDER *prov);
+ int ossl_provider_set_module_path(OSSL_PROVIDER *prov, const char *path);
+ int ossl_provider_add_parameter(OSSL_PROVIDER *prov, const char *name,
+ const char *value);
+
+ /* Child Providers */
+ int ossl_provider_set_child(OSSL_PROVIDER *prov,
+ const OSSL_CORE_HANDLE *handle);
+ const OSSL_CORE_HANDLE *ossl_provider_get_parent(OSSL_PROVIDER *prov);
+ int ossl_provider_up_ref_parent(OSSL_PROVIDER *prov, int activate);
+ int ossl_provider_free_parent(OSSL_PROVIDER *prov, int deactivate);
+ int ossl_provider_default_props_update(OSSL_LIB_CTX *libctx,
+ const char *props);
+
+ /*
+ * Activate the Provider
+ * If the Provider is a module, the module will be loaded
+ */
+ int ossl_provider_activate(OSSL_PROVIDER *prov, int upcalls, int aschild);
+ int ossl_provider_deactivate(OSSL_PROVIDER *prov, int removechildren);
+ int ossl_provider_add_to_store(OSSL_PROVIDER *prov, OSSL_PROVIDER **actualprov,
+ int retain_fallbacks);
+
+ /* Return pointer to the provider's context */
+ void *ossl_provider_ctx(const OSSL_PROVIDER *prov);
+
+ const OSSL_DISPATCH *ossl_provider_get0_dispatch(const OSSL_PROVIDER *prov);
+
+ /* Iterate over all loaded providers */
+ int ossl_provider_doall_activated(OSSL_LIB_CTX *,
+ int (*cb)(OSSL_PROVIDER *provider,
+ void *cbdata),
+ void *cbdata);
+
+ /* Getters for other library functions */
+ const char *ossl_provider_name(OSSL_PROVIDER *prov);
+ const DSO *ossl_provider_dso(OSSL_PROVIDER *prov);
+ const char *ossl_provider_module_name(OSSL_PROVIDER *prov);
+ const char *ossl_provider_module_path(OSSL_PROVIDER *prov);
+ OSSL_LIB_CTX *ossl_provider_libctx(const OSSL_PROVIDER *prov);
+
+ /* Thin wrappers around calls to the provider */
+ void ossl_provider_teardown(const OSSL_PROVIDER *prov);
+ const OSSL_PARAM *ossl_provider_gettable_params(const OSSL_PROVIDER *prov);
+ int ossl_provider_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[]);
+ int ossl_provider_get_capabilities(const OSSL_PROVIDER *prov,
+ const char *capability,
+ OSSL_CALLBACK *cb,
+ void *arg);
+ const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov,
+ int operation_id,
+ int *no_cache);
+ void ossl_provider_unquery_operation(const OSSL_PROVIDER *prov,
+ int operation_id,
+ const OSSL_ALGORITHM *algs);
+
+ int ossl_provider_set_operation_bit(OSSL_PROVIDER *provider, size_t bitnum);
+ int ossl_provider_test_operation_bit(OSSL_PROVIDER *provider, size_t bitnum,
+ int *result);
+
+ int ossl_provider_init_as_child(OSSL_LIB_CTX *ctx,
+ const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in);
+ void ossl_provider_deinit_child(OSSL_LIB_CTX *ctx);
+
+=head1 DESCRIPTION
+
+I<OSSL_PROVIDER> is a type that holds all the necessary information
+to handle a provider, regardless of if it's built in to the
+application or the OpenSSL libraries, or if it's a loadable provider
+module.
+Instances of this type are commonly referred to as "provider objects".
+
+A provider object is always stored in a set of provider objects
+in the library context.
+
+Provider objects are reference counted.
+
+Provider objects are initially inactive, i.e. they are only recorded
+in the store, but are not used.
+They are activated with the first call to ossl_provider_activate(),
+and are deactivated with the last call to ossl_provider_deactivate().
+Activation affects a separate counter.
+
+=head2 Functions
+
+ossl_provider_find() finds an existing provider object in the provider
+object store by I<name>.
+The config file will be automatically loaded unless I<noconfig> is set.
+Typically I<noconfig> should be 0.
+We set I<noconfig> to 1 only when calling these functions while processing a
+config file in order to avoid recursively attempting to load the file.
+The provider object it finds has its reference count incremented.
+
+ossl_provider_new() creates a new provider object named I<name> and
+stores it in the provider object store, unless there already is one
+there with the same name.
+If there already is one with the same name, it's returned with its
+reference count incremented.
+The config file will be automatically loaded unless I<noconfig> is set.
+Typically I<noconfig> should be 0.
+We set I<noconfig> to 1 only when calling these functions while processing a
+config file in order to avoid recursively attempting to load the file.
+The reference count of a newly created provider object will always
+be 2; one for being added to the store, and one for the returned
+reference.
+If I<init_function> is NULL, the provider is assumed to be a
+dynamically loadable module, with the symbol B<OSSL_provider_init> as
+its initialisation function.
+If I<init_function> isn't NULL, the provider is assumed to be built
+in, with I<init_function> being the pointer to its initialisation
+function.
+For further description of the initialisation function, see the
+description of ossl_provider_activate() below.
+
+ossl_provider_up_ref() increments the provider object I<prov>'s
+reference count.
+
+ossl_provider_free() decrements the provider object I<prov>'s
+reference count; when it drops to zero, the provider object is assumed
+to have fallen out of use and will be deinitialized (its I<teardown>
+function is called), and the associated module will be unloaded if one
+was loaded, and I<prov> itself will be freed.
+
+ossl_provider_set_fallback() marks an available provider I<prov> as
+fallback.
+Note that after this call, the provider object pointer that was
+used can simply be dropped, but not freed.
+
+ossl_provider_set_module_path() sets the module path to load the
+provider module given the provider object I<prov>.
+This will be used in preference to automatically trying to figure out
+the path from the provider name and the default module directory (more
+on this in L</NOTES>).
+
+ossl_provider_libctx() returns the library context the given
+provider I<prov> is registered in.
+
+ossl_provider_add_parameter() adds a global parameter for the provider
+to retrieve as it sees fit.
+The parameters are a combination of I<name> and I<value>, and the
+provider will use the name to find the value it wants.
+Only text parameters can be given, and it's up to the provider to
+interpret them.
+
+ossl_provider_set_child() marks this provider as a child of a provider in the
+parent library context. I<handle> is the B<OSSL_CORE_HANDLE> object passed to
+the provider's B<OSSL_provider_init> function.
+
+ossl_provider_get_parent() obtains the handle on the parent provider.
+
+ossl_provider_up_ref_parent() increases the reference count on the parent
+provider. If I<activate> is nonzero then the parent provider is also activated.
+
+ossl_provider_free_parent() decreases the reference count on the parent
+provider. If I<deactivate> is nonzero then the parent provider is also
+deactivated.
+
+ossl_provider_default_props_update() is responsible for informing any child
+providers of an update to the default properties. The new properties are
+supplied in the I<props> string.
+
+ossl_provider_activate() "activates" the provider for the given
+provider object I<prov> by incrementing its activation count, flagging
+it as activated, and initializing it if it isn't already initialized.
+Initializing means one of the following:
+
+=over 4
+
+=item *
+
+If an initialization function was given with ossl_provider_new(), that
+function will get called.
+
+=item *
+
+If no initialization function was given with ossl_provider_new(), a
+loadable module with the I<name> that was given to ossl_provider_new()
+will be located and loaded, then the symbol B<OSSL_provider_init> will
+be located in that module, and called.
+
+=back
+
+If I<upcalls> is nonzero then, if this is a child provider, upcalls to the
+parent libctx will be made to inform it of an up-ref. If I<aschild> is nonzero
+then the provider will only be activated if it is a child provider. Otherwise
+no action is taken and ossl_provider_activate() returns success.
+
+ossl_provider_deactivate() "deactivates" the provider for the given
+provider object I<prov> by decrementing its activation count. When
+that count reaches zero, the activation flag is cleared. If the
+I<removechildren> parameter is 0 then no attempt is made to remove any
+associated child providers.
+
+ossl_provider_add_to_store() adds the provider I<prov> to the provider store and
+makes it available to other threads. This will prevent future automatic loading
+of fallback providers, unless I<retain_fallbacks> is true. If a provider of the
+same name already exists in the store then it is not added but this function
+still returns success. On success the I<actualprov> value is populated with a
+pointer to the provider of the given name that is now in the store. The
+reference passed in the I<prov> argument is consumed by this function. A
+reference to the provider that should be used is passed back in the
+I<actualprov> argument.
+
+ossl_provider_ctx() returns a context created by the provider.
+Outside of the provider, it's completely opaque, but it needs to be
+passed back to some of the provider functions.
+
+ossl_provider_get0_dispatch() returns the dispatch table that the provider
+initially returned in the I<out> parameter of its B<OSSL_provider_init>
+function.
+
+ossl_provider_doall_activated() iterates over all the currently
+"activated" providers, and calls I<cb> for each of them.
+If no providers have been "activated" yet, it tries to activate all
+available fallback providers before iterating over them.
+
+ossl_provider_name() returns the name that was given with
+ossl_provider_new().
+
+ossl_provider_dso() returns a reference to the module, for providers
+that come in the form of loadable modules.
+
+ossl_provider_module_name() returns the filename of the module, for
+providers that come in the form of loadable modules.
+
+ossl_provider_module_path() returns the full path of the module file,
+for providers that come in the form of loadable modules.
+
+ossl_provider_teardown() calls the provider's I<teardown> function, if
+the provider has one.
+
+ossl_provider_gettable_params() calls the provider's I<gettable_params>
+function, if the provider has one.
+It should return an array of I<OSSL_PARAM> to describe all the
+parameters that the provider has for the provider object.
+
+ossl_provider_get_params() calls the provider's parameter request
+responder.
+It should treat the given I<OSSL_PARAM> array as described in
+L<OSSL_PARAM(3)>.
+
+ossl_provider_get_capabilities() calls the provider's I<get_capabilities> function,
+if the provider has one. It provides the name of the I<capability> and a
+callback I<cb> parameter to call for each capability that has a matching name in
+the provider. The callback gets passed OSSL_PARAM details about the capability as
+well as the caller supplied argument I<arg>.
+
+ossl_provider_query_operation() calls the provider's
+I<query_operation> function, if the provider has one.
+It should return an array of I<OSSL_ALGORITHM> for the given
+I<operation_id>.
+
+ossl_provider_unquery_operation() informs the provider that the result of
+ossl_provider_query_operation() is no longer going to be directly accessed and
+that all relevant information has been copied.
+
+ossl_provider_set_operation_bit() registers a 1 for operation I<bitnum>
+in a bitstring that's internal to I<provider>.
+
+ossl_provider_test_operation_bit() checks if the bit operation I<bitnum>
+is set (1) or not (0) in the internal I<provider> bitstring, and sets
+I<*result> to 1 or 0 accorddingly.
+
+ossl_provider_init_as_child() stores in the library context I<ctx> references to
+the necessary upcalls for managing child providers. The I<handle> and I<in>
+parameters are the B<OSSL_CORE_HANDLE> and L<OSSL_DISPATCH(3)> pointers that were
+passed to the provider's B<OSSL_provider_init> function.
+
+ossl_provider_deinit_child() deregisters callbacks from the parent library
+context about provider creation or removal events for the child library context
+I<ctx>. Must only be called if I<ctx> is a child library context.
+
+=head1 NOTES
+
+Locating a provider module happens as follows:
+
+=over 4
+
+=item 1.
+
+If a path was given with ossl_provider_set_module_path(), use that as
+module path.
+Otherwise, use the provider object's name as module path, with
+platform specific standard extensions added.
+
+=item 2.
+
+If the environment variable B<OPENSSL_MODULES> is defined, assume its
+value is a directory specification and merge it with the module path.
+Otherwise, merge the value of the OpenSSL built in macro B<MODULESDIR>
+with the module path.
+
+=back
+
+When this process is done, the result is used when trying to load the
+provider module.
+
+The command C<openssl version -m> can be used to find out the value
+of the built in macro B<MODULESDIR>.
+
+=head1 RETURN VALUES
+
+ossl_provider_find() and ossl_provider_new() return a pointer to a
+provider object (I<OSSL_PROVIDER>) on success, or NULL on error.
+
+ossl_provider_up_ref() returns the value of the reference count after
+it has been incremented.
+
+ossl_provider_free() doesn't return any value.
+
+ossl_provider_doall_activated() returns 1 if the callback was called for all
+activated providers. A return value of 0 means that the callback was not
+called for any activated providers.
+
+ossl_provider_set_module_path(), ossl_provider_set_fallback(),
+ossl_provider_activate(), ossl_provider_activate_leave_fallbacks() and
+ossl_provider_deactivate(), ossl_provider_add_to_store(),
+ossl_provider_default_props_update() return 1 on success, or 0 on error.
+
+ossl_provider_name(), ossl_provider_dso(),
+ossl_provider_module_name(), and ossl_provider_module_path() return a
+pointer to their respective data if it's available, otherwise NULL
+is returned.
+
+ossl_provider_libctx() return a pointer to the library context.
+This may be NULL, and is perfectly valid, as it denotes the default
+global library context.
+
+ossl_provider_teardown() doesn't return any value.
+
+ossl_provider_gettable_params() returns a pointer to a constant
+I<OSSL_PARAM> array if this function is available in the provider,
+otherwise NULL.
+
+ossl_provider_get_params() returns 1 on success, or 0 on error.
+If this function isn't available in the provider, 0 is returned.
+
+ossl_provider_set_operation_bit() and ossl_provider_test_operation_bit()
+return 1 on success, or 0 on error.
+
+ossl_provider_get_capabilities() returns 1 on success, or 0 on error.
+If this function isn't available in the provider or the provider does not
+support the requested capability then 0 is returned.
+
+=head1 SEE ALSO
+
+L<OSSL_PROVIDER(3)>, L<provider(7)>, L<openssl(1)>
+
+=head1 HISTORY
+
+The functions described here were all added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_punycode_decode.pod b/doc/internal/man3/ossl_punycode_decode.pod
new file mode 100644
index 000000000000..652626159e3a
--- /dev/null
+++ b/doc/internal/man3/ossl_punycode_decode.pod
@@ -0,0 +1,60 @@
+=pod
+
+=head1 NAME
+
+ossl_punycode_decode, ossl_a2ulabel, ossl_a2ucompare
+- internal punycode-related functions
+
+=head1 SYNOPSIS
+
+ #include "crypto/punycode.h"
+
+ int ossl_punycode_decode(const char *pEncoded, const size_t enc_len,
+ unsigned int *pDecoded, unsigned int *pout_length);
+
+ int ossl_a2ulabel(const char *in, char *out, size_t *outlen);
+
+ int ossl_a2ucompare(const char *a, const char *u);
+
+=head1 DESCRIPTION
+
+PUNYCODE encoding introduced in RFCs 3490-3492 is widely used for
+representation of host names in ASCII-only format. Some specifications,
+such as RFC 8398, require comparison of host names encoded in UTF-8 charset.
+
+ossl_a2ulabel() decodes NUL-terminated hostname from PUNYCODE to UTF-8,
+using a provided buffer for output.
+
+ossl_a2ucompare() accepts two NUL-terminated hostnames, decodes the 1st
+from PUNYCODE to UTF-8 and compares it with the 2nd one as is.
+
+ossl_punycode_decode() decodes one label (one dot-separated part) from
+a hostname, with stripped PUNYCODE marker I<xn-->.
+
+=head1 RETURN VALUES
+
+ossl_a2ulabel() returns 1 on success, 0 on not enough buf passed,
+-1 on invalid PUNYCODE string passed. When valid string is provided, it sets the
+I<*outlen> to the length of required buffer to perform correct decoding.
+
+ossl_a2ucompare() returns 1 on non-equal strings, 0 on equal strings,
+-1 when invalid PUNYCODE string passed.
+
+ossl_punycode_decode() returns 1 on success, 0 on error. On success,
+*pout_length contains the number of codepoints decoded.
+
+=head1 HISTORY
+
+The functions described here were all added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
+
diff --git a/doc/internal/man3/ossl_rand_get_entropy.pod b/doc/internal/man3/ossl_rand_get_entropy.pod
new file mode 100644
index 000000000000..4da3f1f4d9db
--- /dev/null
+++ b/doc/internal/man3/ossl_rand_get_entropy.pod
@@ -0,0 +1,66 @@
+=pod
+
+=head1 NAME
+
+ossl_rand_get_entropy, ossl_rand_cleanup_entropy,
+ossl_rand_get_nonce, ossl_rand_cleanup_nonce
+- get seed material from the operating system
+
+=head1 SYNOPSIS
+
+ #include "crypto/rand.h"
+
+ size_t ossl_rand_get_entropy(OSSL_CORE_HANDLE *handle,
+ unsigned char **pout, int entropy,
+ size_t min_len, size_t max_len);
+ void ossl_rand_cleanup_entropy(OSSL_CORE_HANDLE *handle,
+ unsigned char *buf, size_t len);
+ size_t ossl_rand_get_nonce(OSSL_CORE_HANDLE *handle,
+ unsigned char **pout, size_t min_len,
+ size_t max_len, const void *salt, size_t salt_len);
+ void ossl_rand_cleanup_nonce(OSSL_CORE_HANDLE *handle,
+ unsigned char *buf, size_t len);
+
+=head1 DESCRIPTION
+
+ossl_rand_get_entropy() retrieves seeding material from the operating system.
+The seeding material will have at least I<entropy> bytes of randomness and is
+stored in a buffer which contains at least I<min_len> and at most I<max_len>
+bytes. The buffer address is stored in I<*pout> and the buffer length is
+returned to the caller.
+
+ossl_rand_cleanup_entropy() cleanses and frees any storage allocated by
+ossl_rand_get_entropy(). The seeding buffer is pointed to by I<buf> and is
+of length I<len> bytes.
+
+ossl_rand_get_nonce() retrieves a nonce using the passed I<salt> parameter
+of length I<salt_len> and operating system specific information.
+The I<salt> should contain uniquely identifying information and this is
+included, in an unspecified manner, as part of the output.
+The output is stored in a buffer which contains at least I<min_len> and at
+most I<max_len> bytes. The buffer address is stored in I<*pout> and the
+buffer length returned to the caller.
+
+ossl_rand_cleanup_nonce() cleanses and frees any storage allocated by
+ossl_rand_get_nonce(). The nonce buffer is pointed to by I<buf> and is
+of length I<len> bytes.
+
+=head1 RETURN VALUES
+
+ossl_rand_get_entropy() and ossl_rand_get_nonce() return the number of bytes
+in I<*pout> or 0 on error.
+
+=head1 HISTORY
+
+The functions described here were all added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_random_add_conf_module.pod b/doc/internal/man3/ossl_random_add_conf_module.pod
new file mode 100644
index 000000000000..6d4f5810dcdd
--- /dev/null
+++ b/doc/internal/man3/ossl_random_add_conf_module.pod
@@ -0,0 +1,42 @@
+=pod
+
+=head1 NAME
+
+ossl_random_add_conf_module - internal random configuration module
+
+=head1 SYNOPSIS
+
+ #include "crypto/rand.h"
+
+ /* Configuration */
+ void ossl_random_add_conf_module(void);
+
+=head1 DESCRIPTION
+
+ossl_random_add_conf_module() adds the random configuration module
+for providers.
+This allows the type and parameters of the stardard setup of random number
+generators to be configured with an OpenSSL L<config(5)> file.
+
+=head1 RETURN VALUES
+
+ossl_random_add_conf_module() doesn't return any value.
+
+=head1 SEE ALSO
+
+L<OSSL_PROVIDER(3)>, L<ossl_provider_new(3)>, L<provider-rand(7)>
+
+=head1 HISTORY
+
+The functions described here were all added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_rsa_get0_all_params.pod b/doc/internal/man3/ossl_rsa_get0_all_params.pod
new file mode 100644
index 000000000000..a7ebb613bb02
--- /dev/null
+++ b/doc/internal/man3/ossl_rsa_get0_all_params.pod
@@ -0,0 +1,75 @@
+=pod
+
+=head1 NAME
+
+ossl_rsa_set0_all_params, ossl_rsa_get0_all_params
+- Internal routines for getting and setting data in an RSA object
+
+=head1 SYNOPSIS
+
+ #include "crypto/rsa.h"
+
+ int ossl_rsa_get0_all_params(RSA *r, STACK_OF(BIGNUM_const) *primes,
+ STACK_OF(BIGNUM_const) *exps,
+ STACK_OF(BIGNUM_const) *coeffs);
+ int ossl_rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes,
+ const STACK_OF(BIGNUM) *exps,
+ const STACK_OF(BIGNUM) *coeffs);
+
+=head1 DESCRIPTION
+
+ossl_rsa_set0_all_params() sets all primes, CRT exponents and CRT coefficients
+in the B<RSA> object I<r> to the contents of the stacks of BIGNUMs I<primes>,
+I<exps> and I<coeffs>. The B<RSA> object takes ownership of the BIGNUMs,
+but not of the stacks.
+
+ossl_rsa_get0_all_params() gets all primes, CRT exponents and CRT coefficients
+in the B<RSA> object I<r> and pushes them on the stacks of constant BIGNUMs
+I<primes>, I<exps> and I<coeffs>. The B<RSA> object retains ownership of the
+BIGNUMs, but not of the stacks.
+
+=head1 NOTES
+
+For RSA_set0_all_params() and RSA_get0_all_params():
+
+=over 4
+
+=item *
+
+the I<primes> stack contains I<p>, I<q>, and then the rest of the primes
+if the B<RSA> object is a multi-prime RSA key.
+
+=item *
+
+the I<exps> stack contains I<dP>, I<dQ>, and then the rest of the exponents
+if the B<RSA> object is a multi-prime RSA key.
+
+=item *
+
+the I<coeffs> stack contains I<qInv>, and then the rest of the coefficients
+if the B<RSA> object is a multi-prime RSA key.
+
+=back
+
+The number of primes must always be equal to the number of exponents, and
+the number of coefficients must be one less than the number of primes.
+
+=head1 RETURN VALUES
+
+ossl_rsa_get0_all_params() and ossl_rsa_set0_all_params() return 1 on success,
+or 0 on failure.
+
+=head1 SEE ALSO
+
+L<RSA_set0_multi_prime_params(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/x509v3_cache_extensions.pod b/doc/internal/man3/x509v3_cache_extensions.pod
new file mode 100644
index 000000000000..cc0aeb6079a8
--- /dev/null
+++ b/doc/internal/man3/x509v3_cache_extensions.pod
@@ -0,0 +1,41 @@
+=pod
+
+=head1 NAME
+
+x509v3_cache_extensions
+- cache info on various X.509v3 extensions and further derived certificate data
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509v3.h>
+
+ int x509v3_cache_extensions(X509 *x, OSSL_LIB_CTX *libctx, const char *propq);
+
+=head1 DESCRIPTION
+
+This function processes any X509v3 extensions present in an X509 object I<x>
+and caches the result of that processing as well as further derived info,
+for instance whether the certificate is self-issued or has version X.509v1.
+It computes the SHA1 digest of the certificate using the default library context
+and property query string and stores the result in x->sha1_hash,
+or on failure sets B<EXFLAG_NO_FINGERPRINT> in x->flags.
+It sets B<X509_SIG_INFO_VALID> in x->flags if x->siginf was filled successfully,
+which may not be possible if a referenced algorithm is unknown or not available.
+Many OpenSSL functions that use an X509 object call this function implicitly.
+
+=head1 RETURN VALUES
+
+This function returns 0 if the extensions or other portions of the certificate
+are invalid or an error occurred.
+Otherwise it returns 1.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man7/DERlib.pod b/doc/internal/man7/DERlib.pod
new file mode 100644
index 000000000000..24280b976b34
--- /dev/null
+++ b/doc/internal/man7/DERlib.pod
@@ -0,0 +1,149 @@
+=pod
+
+=head1 NAME
+
+DERlib - internal OpenSSL DER library
+
+=head1 DESCRIPTION
+
+OpenSSL contains an internal small DER reading and writing library,
+as an alternative to the publicly known i2d and d2i functions. It's
+solely constituted of functions that work as building blocks to create
+more similar functions to encode and decode larger structures.
+
+All these functions have similar function signatures (C<something>
+will vary depending on what the function will encode):
+
+ int DER_w_something(WPACKET *pkt, int tag, ...);
+
+=begin comment
+
+When readers are added, add this:
+
+ int DER_r_something(PACKET *pkt, int tag, ...);
+
+=end comment
+
+I<pkt> is the packet context used, and I<tag> should be the
+context-specific tag value of the element being handled, or -1 if there
+is no tag number for that element (you may use the convenience macro
+B<DER_NO_CONTEXT> instead of -1). Any argument following is the C
+variable that's being encoded or decoded.
+
+=head2 DER writers / encoders
+
+DER writers are based in L<WPACKET(3)>, a generic packet writing
+library, so before using any of them, I<pkt> must be initialized
+using L<WPACKET_init_der(3)> or L<WPACKET_init_null_der(3)>
+
+DER writers must be used in reverse order, except for the wrapping
+functions that implement a constructed element. The latter are easily
+recognised by their function name including the words C<begin> and
+C<end>. As an example, we can look at the DSA signature structure,
+which is defined like this in ASN.1 terms:
+
+ -- Copied from RFC 3279, section 2.2.2
+ Dss-Sig-Value ::= SEQUENCE {
+ r INTEGER,
+ s INTEGER }
+
+With the DER library, this is the corresponding code, given two OpenSSL
+B<BIGNUM>s I<r> and I<s>:
+
+ int ok = ossl_DER_w_begin_sequence(pkt, -1)
+ && ossl_DER_w_bn(pkg, -1, s)
+ && ossl_DER_w_bn(pkg, -1, r)
+ && ossl_DER_w_end_sequence(pkt, -1);
+
+As an example of the use of I<tag>, an ASN.1 element like this:
+
+ v [1] INTEGER OPTIONAL
+
+Would be encoded like this:
+
+ ossl_DER_w_bn(pkt, 1, v)
+
+=begin comment
+
+=head2 DER readers / decoders
+
+TBA
+
+=end comment
+
+=head1 EXAMPLES
+
+A more complex example, encoding the AlgorithmIdentifier with
+RSASSA-PSS values.
+
+As a reminder, the AlgorithmIdentifier is specified like this:
+
+ -- From RFC 3280, section 4.1.1.2
+ AlgorithmIdentifier ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER,
+ parameters ANY DEFINED BY algorithm OPTIONAL }
+
+And the RSASSA-PSS OID and parameters are specified like this:
+
+ -- From RFC 3279, section 3.1
+ id-RSASSA-PSS OBJECT IDENTIFIER ::= { pkcs-1 10 }
+
+ RSASSA-PSS-params ::= SEQUENCE {
+ hashAlgorithm [0] HashAlgorithm DEFAULT
+ sha1Identifier,
+ maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT
+ mgf1SHA1Identifier,
+ saltLength [2] INTEGER DEFAULT 20,
+ trailerField [3] INTEGER DEFAULT 1 }
+
+The value we want to encode, written in ASN.1 syntax:
+
+ {
+ algorithm id-RSASSA-PSS,
+ parameters {
+ hashAlgorithm sha256Identifier,
+ maskGenAlgorithm mgf1SHA256Identifier,
+ saltLength 20 -- unnecessarily explicit
+ }
+ }
+
+Assuming that we have precompiled constants for C<id-RSASSA-PSS>,
+C<sha256Identifier> and C<mgf1SHA256Identifier>, the DER writing code
+looks as follows. This is a complete function to write that specific
+value:
+
+ int DER_w_AlgorithmIdentifier_RSASSA_PSS_special(WPACKET *pkt,
+ int tag,
+ RSA *rsa)
+ {
+ return ossl_DER_w_begin_sequence(pkt, tag)
+ && (ossl_DER_w_begin_sequence(pkt, DER_NO_CONTEXT)
+ && ossl_DER_w_uint32(pkt, 2, 20)
+ && ossl_DER_w_precompiled(pkt, 1,
+ der_mgf1SHA256Identifier,
+ sizeof(der_mgf1SHA256Identifier))
+ && ossl_DER_w_precompiled(pkt, 0,
+ der_sha256Identifier,
+ sizeof(der_sha256Identifier))
+ && ossl_DER_w_end_sequence(pkt, DER_NO_CONTEXT))
+ && ossl_DER_w_precompiled(pkt, DER_NO_CONTEXT,
+ der_id_RSASSA_PSS,
+ sizeof(der_id_RSASSA_PSS))
+ && ossl_DER_w_end_sequence(pkt, tag);
+ }
+
+=head1 SEE ALSO
+
+L<ossl_DER_w_bn(3)>, L<ossl_DER_w_begin_sequence(3)>,
+L<ossl_DER_w_precompiled(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man7/EVP_PKEY.pod b/doc/internal/man7/EVP_PKEY.pod
new file mode 100644
index 000000000000..cc738b9c28eb
--- /dev/null
+++ b/doc/internal/man7/EVP_PKEY.pod
@@ -0,0 +1,212 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY - an internal description
+
+=head1 SYNOPSIS
+
+ #include "crypto/evp.h"
+
+ typedef struct evp_pkey_st EVP_PKEY;
+
+=head1 DESCRIPTION
+
+I<This is not a complete description yet>
+
+B<EVP_PKEY> is a complex type that's essentially a container for
+private/public key pairs, but has had other uses as well.
+
+=for comment "uses" could as well be "abuses"...
+
+The private/public key pair that an B<EVP_PKEY> contains is refered to
+as its "internal key" or "origin" (the reason for "origin" is
+explained further down, in L</Export cache for provider operations>),
+and it can take one of the following forms:
+
+=over 4
+
+=item legacy origin
+
+This is the form that an B<EVP_PKEY> in OpenSSL prior to 3.0 had. The
+internal key in the B<EVP_PKEY> is a pointer to the low-level key
+types, such as B<RSA>, B<DSA> and B<EC>, or an engine driven
+structure, and is governed by an associated L<EVP_PKEY_METHOD(3)> and
+an L<EVP_PKEY_ASN1_METHOD(3)>.
+
+The functions available through those two method structures get full
+access to the B<EVP_PKEY> and therefore have a lot of freedom to
+modify whatever they want. This also means that an B<EVP_PKEY> is a
+shared structure between libcrypto and any ENGINE that serves such
+methods.
+
+=item provider-native origin
+
+This is a new form in OpenSSL 3.0, which permits providers to hold the
+key data (see L<provider-keymgmt(7)>). The internal key in the
+B<EVP_PKEY> is a pointer to that key data held by the provider, and
+is governed by an associated L<EVP_KEYMGMT(3)> method structure.
+
+The functions available through the L<EVP_KEYMGMT(3)> have no access
+to the B<EVP_PKEY>, and can therefore not make any direct changes.
+Similarly, the key data that the B<EVP_PKEY> points at is only known
+to the functions pointed at in the L<EVP_KEYMGMT(3)>.
+
+=back
+
+These two forms can never co-exist in the same B<EVP_PKEY>, the main
+reason being that having both at the same time will create problems
+with synchronising between the two forms, and potentially make it
+confusing which one of the two is the origin.
+
+=head2 Key mutability
+
+The B<EVP_PKEY> internal keys are mutable.
+
+This is especially visible with internal legacy keys, since they can
+be extracted with functions like L<EVP_PKEY_get0_RSA(3)> and then
+modified at will with functions like L<RSA_set0_key(3)>. Note that if the
+internal key is a provider key then the return value from functions such as
+L<EVP_PKEY_get0_RSA(3)> is a cached copy of the key. Changes to the cached
+copy are not reflected back in the provider key.
+
+Internal provider native keys are also possible to be modified, if the
+associated L<EVP_KEYMGMT(3)> implementation allows it. This is done
+with L<EVP_PKEY_set_params(3)> and its specialised derivatives. The
+OpenSSL providers allow it for the following:
+
+=over 4
+
+=item DH, EC, X25519, X448:
+
+It's possible to set the encoded public key. This is supported in
+particular through L<EVP_PKEY_set1_encoded_public_key(3)>.
+
+=item EC:
+
+It's possible to flip the ECDH cofactor mode.
+
+=back
+
+Every time the B<EVP_PKEY> internal key mutates, an internal dirty
+count is incremented. The need for a dirty count is explained further
+in L</Export cache for provider operations>.
+
+For provider native origin keys, this doesn't require any help from
+the L<EVP_KEYMGMT(3)>, the dirty count is maintained in the B<EVP_PKEY>
+itself, and is incremented every time L<EVP_PKEY_set_params(3)> or its
+specialised derivatives are called.
+For legacy origin keys, this requires the associated
+L<EVP_PKEY_ASN1_METHOD(3)> to implement the dirty_cnt() function. All
+of OpenSSL's built-in L<EVP_PKEY_ASN1_METHOD(3)> implement this
+function.
+
+=head2 Export cache for provider operations
+
+OpenSSL 3.0 can handle operations such as signing, encrypting, etc in
+diverse providers, potentially others than the provider of the
+L<EVP_KEYMGMT(3)>. Two providers, possibly from different vendors,
+can't be expected to share internal key structures. There are
+therefore instances where key data will need to be exported to the
+provider that is going to perform the operation (this also implies
+that every provider that implements a key pair based operation must
+also implement an L<EVP_KEYMGMT(3)>).
+
+For performance reasons, libcrypto tries to minimize the need to
+perform such an export, so it maintains a cache of such exports in the
+B<EVP_PKEY>. Each cache entry has two items, a pointer to the
+provider side key data and the associated L<EVP_KEYMGMT(3)>.
+
+I<This cache is often referred to as the "operation key cache", and
+the key data that the cached keys came from is the "origin", and since
+there are two forms of the latter, we have the "legacy origin" and the
+"provider native origin".>
+
+The export to the operation key cache can be performed independent of
+what form the origin has.
+For a legacy origin, this requires that the associated
+L<EVP_PKEY_ASN1_METHOD(3)> implements the functions export_to() and
+dirty_cnt().
+For a provider native origin, this requires that the associated
+L<EVP_KEYMGMT(3)> implements the OSSL_FUNC_keymgmt_export() function
+(see L<provider-keymgmt(7)>).
+In all cases, the receiving L<EVP_KEYMGMT(3)> (the one associated with
+the exported key data) must implement OSSL_FUNC_keymgmt_import().
+
+If such caching isn't supported, the operations that can be performed
+with that key are limited to the same backend as the origin key
+(ENGINE for legacy origin keys, provider for provider side origin
+keys).
+
+=head3 Exporting implementation details
+
+
+Exporting a key to the operation cache involves the following:
+
+=over 4
+
+=item 1.
+
+Check if the dirty count for the internal origin key has changed since
+the previous time. This is done by comparing it with a copy of the
+dirty count, which is maintained by the export function.
+
+If the dirty count has changed, the export cache is cleared.
+
+=item 2.
+
+Check if there's an entry in the export cache with the same
+L<EVP_KEYMGMT(3)> that's the same provider that an export is to be
+made to (which is the provider that's going to perform an operation
+for which the current B<EVP_PKEY> is going to be used).
+
+If such an entry is found, nothing more is done, the key data and
+L<EVP_KEYMGMT(3)> found in that export cache entry will be used for
+the operation to be performed.
+
+=item 3.
+
+Export the internal origin key to the provider, using the appropriate
+method.
+
+For legacy origin keys, that's done with the help of the
+L<EVP_PKEY_ASN1_METHOD(3)> export_to() function.
+
+For provider native origin keys, that's done by retrieving the key
+data in L<OSSL_PARAM(3)> form from the origin keys, using the
+OSSL_FUNC_keymgmt_export() functions of the associated
+L<EVP_KEYMGMT(3)>, and sending that data to the L<EVP_KEYMGMT(3)> of
+the provider that's to perform the operation, using its
+OSSL_FUNC_keymgmt_import() function.
+
+=back
+
+=head2 Changing a key origin
+
+It is never possible to change the origin of a key. An B<EVP_PKEY> with a legacy
+origin will I<never> be upgraded to become an B<EVP_PKEY> with a provider
+native origin. Instead, we have the operation cache as described above, that
+takes care of the needs of the diverse operation the application may want to
+perform.
+
+Similarly an B<EVP_PKEY> with a provider native origin, will I<never> be
+I<transformed> into an B<EVP_PKEY> with a legacy origin. Instead we may have a
+cached copy of the provider key in legacy form. Once the cached copy is created
+it is never updated. Changes made to the provider key are not reflected back in
+the cached legacy copy. Similarly changes made to the cached legacy copy are not
+reflected back in the provider key.
+
+=head1 SEE ALSO
+
+L<provider-keymgmt(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man7/VERSION.pod b/doc/internal/man7/VERSION.pod
new file mode 100644
index 000000000000..4bc8ba6b9327
--- /dev/null
+++ b/doc/internal/man7/VERSION.pod
@@ -0,0 +1,149 @@
+=pod
+
+=head1 NAME
+
+VERSION - OpenSSL version information
+
+=head1 SYNOPSIS
+
+ MAJOR=3
+ MINOR=0
+ PATCH=0
+ PRE_RELEASE_TAG=dev
+ BUILD_METADATA=
+ RELEASE_DATE=
+ SHLIB_VERSION=3
+
+=head1 DESCRIPTION
+
+This file is a set of keyed information looking like simple variable
+assignments. When given an empty value, they are seen as unassigned.
+The keys that are recognised are:
+
+=over 4
+
+=item B<MAJOR>, B<MINOR>, B<PATCH>
+
+The three parts of OpenSSL's 3 numbered version number, MAJOR.MINOR.PATCH.
+These are used to compose the values for the C macros B<OPENSSL_VERSION_MAJOR>,
+B<OPENSSL_VERSION_MINOR>, B<OPENSSL_VERSION_PACTH>.
+
+=item B<PRE_RELEASE_TAG>
+
+This is the added pre-release tag, which is added to the version separated by
+a dash. For a value C<foo>, the C macro B<OPENSSL_VERSION_PRE_RELEASE> gets
+the string C<-foo> (dash added).
+
+=item B<BUILD_METADATA>
+
+Extra metadata to be used by anyone for their own purposes. This is added to
+the version and possible pre-release tag, separated by a plus sign. For a
+value C<bar>, the C macro B<OPENSSL_VERSION_BUILD_METADATA> gets the string
+C<+bar>.
+
+=item B<RELEASE_DATE>
+
+Defined in releases. When not set, it gets the value C<xx XXX xxxx>.
+
+=item B<SHLIB_VERSION>
+
+The shared library version, which is something other than the project version.
+
+=back
+
+It is a configuration error if B<MAJOR>, B<MINOR>, B<PATCH> and B<SHLIB_VERSION>
+don't have values. Configuration will stop in that case.
+
+=head2 Affected configuration data
+
+The following items in %config from F<configdata.pm> are affected:
+
+=over 4
+
+=item $config{major}, $config{minor}, $config{patch}, $config{shlib_version}
+
+These items get their values from B<MAJOR>, B<MINOR>, B<PATCH>, and
+B<SHLIB_VERSION>, respectively.
+
+=item $config{prerelease}
+
+If B<PRERELEASE> is assigned a value, $config{prerelease} gets that same value,
+prefixed by a dash, otherwise the empty string.
+
+=item $config{build_metadata}
+
+If B<BUILD_METADATA> is assigned a value, $config{build_metadata} gets that same
+value, prefixed by a plus sign, otherwise the empty string.
+
+=item $config{release_date}
+
+If B<RELEASE_DATE> is assigned a value, $config{release_date} gets that same
+value, otherwise the string C<xx XXX yyyy>.
+
+=item $config{version}
+
+The minimal version number, a string composed from B<MAJOR>, B<MINOR> and
+B<PATCH>, separated by periods. For C<MAJOR=3>, C<MINOR=0> and C<PATCH=0>,
+the string will be C<3.0.0>.
+
+=item $config{full_version}
+
+The fully loaded version number, a string composed from $config{version},
+$config{prerelease} and $config{build_metadata}. See See L</EXAMPLES> for
+a few examples.
+
+=back
+
+=head1 EXAMPLES
+
+=over 4
+
+=item 1.
+
+ MAJOR=3
+ MINOR=0
+ PATCH=0
+ PRE_RELEASE_TAG=dev
+ BUILD_METADATA=
+
+The fully loaded version number ($config{full_version}) will be
+C<3.0.0-dev>.
+
+=item 2.
+
+ MAJOR=3
+ MINOR=0
+ PATCH=0
+ PRE_RELEASE_TAG=
+ BUILD_METADATA=something
+
+The fully loaded version number ($config{full_version}) will be
+C<3.0.0+something>.
+
+=item 3.
+
+ MAJOR=3
+ MINOR=0
+ PATCH=0
+ PRE_RELEASE_TAG=alpha3
+ BUILD_METADATA=something
+
+The fully loaded version number ($config{full_version}) will be
+C<3.0.0-alpha3+something>.
+
+=back
+
+=head1 SEE ALSO
+
+L<OpenSSL_version(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man7/build.info.pod b/doc/internal/man7/build.info.pod
new file mode 100644
index 000000000000..080c9e444eea
--- /dev/null
+++ b/doc/internal/man7/build.info.pod
@@ -0,0 +1,644 @@
+=pod
+
+=head1 NAME
+
+build.info - Building information files
+
+=head1 SYNOPSIS
+
+B<IF[>0|1B<]>
+
+B<ELSIF[>0|1B<]>
+
+B<ELSE>
+
+B<ENDIF>
+
+B<SUBDIRS=> I<dir> ...
+
+B<PROGRAMS=> I<name> ...
+
+B<LIBS=> I<name> ...
+
+B<MODULES=> I<name> ...
+
+B<SCRIPTS=> I<name> ...
+
+B<DEPEND[>I<items>B<]=> I<otheritem> ...
+
+B<GENERATE[>I<item>B<]=> I<generator> I<generator-args> ...
+
+B<SOURCE[>I<item>B<]=> I<file> ...
+
+B<SHARED_SOURCE[>I<item>B<]=> I<file> ...
+
+B<DEFINE[>I<items>B<]=> I<name>[B<=>I<value>] ...
+
+B<INCLUDE[>I<items>B<]=> I<dir> ...
+
+B<$>I<VARIABLE>B<=>I<value>
+
+=head1 DESCRIPTION
+
+OpenSSL's build system revolves around three questions:
+
+=over 4
+
+=item What to build for?
+
+This is about choice of platform (combination of hardware, operating
+system, and toolchain).
+
+=item What to build?
+
+This is about having all the information on what needs to be built and
+from what.
+
+=item How to build it?
+
+This is about build file generation.
+
+=back
+
+This document is all about the second item, "What to build?", and most
+of all, how to specify that information.
+
+For some terms used in this document, please see the L</GLOSSARY> at
+the end.
+
+=head2 F<build.info> files
+
+F<build.info> files are meta data files for OpenSSL's built file
+generators, and are used to specify exactly what end product files
+(programs, libraries, modules or scripts) are to be produced, and from
+what sources.
+
+Intermediate files, such as object files, are seldom referred to at
+all. They sometimes can be, if there's a need, but this should happen
+very rarely, and support for that sort of thing is added on as-needed
+basis.
+
+Any time a directory or file is expected in a statement value, Unix
+syntax must be used, which means that the slash C</> must be used as
+the directory separator.
+
+=head2 General syntax
+
+=head3 Comments
+
+Comments are any line that start with a hash sign (C<#>). The hash
+sign may be preceded by any number of horizontal spaces.
+
+=head3 Filenames
+
+F<build.info> files are platform agnostic. This means that there is
+some information in them that is representative rather than specific.
+
+This is particularly visible with end product names, they work more
+like a tag than as the actual filename that's going to be produced.
+This is because different platforms have different decorations on
+different types of files.
+
+For example, if we say that we want to produce a program C<foo>, it
+would look like this:
+
+ PROGRAM=foo
+
+However, the program filename may end up being just C<foo> (typical
+for Unix), or C<foo.exe> (typical for Windows), or even C<BLAH$FOO.EXE>
+(possible on VMS, depending on policy).
+
+These platform specific decorations are not the concern of
+F<build.info> files. The build file generators are responsible for
+transforming these platform agnostic names to their platform specific
+counterparts.
+
+=head3 Statements
+
+With the exception of variables and conditions, the general statement
+syntax is one of:
+
+=over 4
+
+=item B<I<KEYWORD>> B<=> I<value> ...
+
+=item B<I<KEYWORD>[>I<items>B<]> B<=> I<value> ...
+
+=back
+
+Every B<I<KEYWORD>> represents some particular type of information.
+
+The first form (sometimes called "plain statement") is used to specify
+information on what end products need to be built, for example:
+
+ PROGRAMS=foo bar
+ LIBS=libpoly libcookie
+ MODULES=awesome-plugin
+ SCRIPTS=tool1 tool2
+ SUBDIRS=dir1 dir2
+
+This says that we want to build programs C<foo> and C<bar>, the
+libraries C<libpoly> and C<libcookie>, an awesome plugin module
+C<awesome-plugin>, a couple of scripts C<tool1> and C<tool2>, and
+finally that there are more F<build.info> files in subdirectories
+C<dir1> and C<dir2>.
+
+The second form (sometimes called "indexed statement") is used to
+specify further details for existing items, for example:
+
+ SOURCE[foo]=foo.c details.c
+ DEPEND[foo]=libcookie
+
+This says that the program C<foo> is built from the source files
+F<foo.c> and F<details.c>, and that it depends on the library
+C<libcookie> (in other words, the library will be included when
+linking that program together).
+
+Multiple space separated items are allowed too:
+
+ SOURCE[foo]=foo.c
+ SOURCE[details]=details.c
+ DEPEND[foo details]=libcookie
+
+For any indexed statement for which the items haven't been specified
+through any plain statement, or where the items exists but the indexed
+statement does not apply, the value is simply ignored by the build
+file generators.
+
+=head3 Statement attributes
+
+Some statements can have attributes added to them, to allow for
+variations on how they are treated.
+
+=over 4
+
+=item B<I<KEYWORD>{> I<attrib> | I<attrib>B<=>I<attrib-value> [,...]B<}>
+B<=> I<value> ...
+
+=item B<I<KEYWORD>[>I<items>B<]{> I<attrib> | I<attrib>B<=>I<attrib-value>
+[,...]B<}> B<=> I<value> ...
+
+=back
+
+Attributes are passed as they are to the build file generators, and
+the exact interpretation of those attributes is entirely up to them
+(see L</Known attributes> below for details).
+
+A current example:
+
+ LIBS{noinst,has_main}=libtestutil.a
+
+This says that the static library C<libtestutil.a> should not be
+installed (C<noinst>), and that it includes an object file that has
+the C<main> symbol (C<has_main>). Most platforms don't need to know
+the latter, but there are some where the program linker will not look
+for C<main> in libraries unless it's explicitly told so, so this is
+way to tell the build file generator to emit the necessary command
+options to make that happen.
+
+Attributes are accumulated globally. This means that a library could
+be given like this in different places:
+
+ # Location 1
+ LIBS=libwhatever
+
+ # Location 2
+ LIBS{noinst}=libwhatever
+
+ # Location 3
+ LIBS{has_main}=libwhatever
+
+The end result is that the library C<libwhatever> will have the
+attributes C<noinst> and C<has_main> attached to it.
+
+=head3 Quoting and tokens
+
+Statement values are normally split into a list of tokens, separated
+by spaces.
+
+To avoid having a value split up into several tokens, they may be
+quoted with double (C<">) or single (C<'>) quotes.
+
+For example:
+
+ PROGRAMS=foo "space cadet" bar
+
+This says that we sant to build three programs, C<foo>, C<space cadet>
+and C<bar>.
+
+=head3 Conditionals
+
+F<build.info> files include a very simple condition system, involving
+the following keywords:
+
+=over 4
+
+=item B<IF[>0|1B<]>
+
+=item B<ELSIF[>0|1B<]>
+
+=item B<ELSE>
+
+=item B<ENDIF>
+
+=back
+
+This works like any condition system with similar syntax, and the
+condition value in B<IF> and B<ELSIF> can really be any literal value
+that perl can interpret as true or false.
+
+Conditional statements are nesting.
+
+In itself, this is not very powerful, but together with L</Perl nuggets>,
+it can be.
+
+=head3 Variables
+
+F<build.info> handles simple variables. They are defined by
+assignment:
+
+=over 4
+
+=item B<$>I<NAME> B<=> I<value>
+
+=back
+
+These variables can then be used as part of any statement value or
+indexed statement item. This should be used with some care, as
+I<variables are expanded into their values before the value they are
+part of is tokenized>.
+
+I<Variable assignment values are not tokenized.>
+
+Variable references can be one of:
+
+=over 4
+
+=item B<$>I<NAME> or B<${>I<NAME>B<}>
+
+Simple reference; the variable reference is replaced with its value,
+verbatim.
+
+=item B<${>I<NAME>B</>I<str>B</>I<subst>B<}>
+
+Substitution reference; the variable reference is replaced with its
+value, modified by replacing all occurrences of I<str> with I<subst>.
+
+=back
+
+=head2 Scope
+
+Most of the statement values are accumulated globally from all the
+F<build.info> files that are digested. There are two exceptions,
+F<build.info> variables and B<SUBDIRS> statement, for which the scope
+is the F<build.info> file they are in.
+
+=head2 Perl nuggets
+
+Whenever a F<build.info> file is read, it is passed through the Perl
+template processor L<OpenSSL::Template>, which is a small extension of
+L<Text::Template>.
+
+Perl nuggets are anything between C<{-> and C<-}>, and whatever the
+result from such a nugget is, that value will replace the nugget in
+text form. This is useful to get dynamically generated F<build.info>
+statements, and is most often seen used together with the B<IF> and
+B<ELSIF> conditional statements.
+
+For example:
+
+ IF[{- $disabled{something} -}]
+ # do whatever's needed when "something" is disabled
+ ELSIF[{- $somethingelse eq 'blah' -}]
+ # do whatever's needed to satisfy this condition
+ ELSE
+ # fallback
+ ENDIF
+
+Normal Perl scope applies, so it's possible to have an initial perl
+nugget that sets diverse global variables that are used in later
+nuggets. Each nugget is a Perl block of its own, so B<my> definitions
+are only in scope within the same nugget, while B<our> definitions are
+in scope within the whole F<build.info> file.
+
+=head1 REFERENCE
+
+=head2 Conditionals
+
+=over 4
+
+=item B<IF[>0|1B<]>
+
+If the condition is true (represented as C<1> here), everything
+between this B<IF> and the next corresponding B<ELSIF> or B<ELSE>
+applies, and the rest until the corresponding B<ENDIF> is skipped
+over.
+
+If the condition is false (represented as C<0> here), everything
+from this B<IF> is skipped over until the next corresponding B<ELSIF>
+or B<ELSE>, at which point processing continues.
+
+=item B<ELSE>
+
+If F<build.info> statements have been skipped over to this point since
+the corresponding B<IF> or B<ELSIF>, F<build.info> processing starts
+again following this line.
+
+=item B<ELSIF[>0|1B<]>
+
+This is B<ELSE> and B<IF> combined.
+
+=item B<ENDIF>
+
+Marks the end of a conditional.
+
+=back
+
+=head2 Plain statements
+
+=over 4
+
+=item B<SUBDIRS=> I<dir> ...
+
+This instructs the F<build.info> reader to also read the F<build.info>
+file in every specified directory. All directories should be given
+relative to the location of the current F<build.info> file.
+
+=item B<PROGRAMS=> I<name> ...
+
+Collects names of programs that should be built.
+
+B<PROGRAMS> statements may have attributes, which apply to all the
+programs given in such a statement. For example:
+
+ PROGRAMS=foo
+ PROGRAMS{noinst}=bar
+
+With those two lines, the program C<foo> will not have the attribute
+C<noinst>, while the program C<bar> will.
+
+=item B<LIBS=> I<name> ...
+
+Collects names of libraries that should be built.
+
+The normal case is that libraries are built in both static and shared
+form. However, if a name ends with C<.a>, only the static form will
+be produced.
+
+Similarly, libraries may be referred in indexed statements as just the
+plain name, or the name including the ending C<.a>. If given without
+the ending C<.a>, any form available will be used, but if given with
+the ending C<.a>, the static library form is used unconditionally.
+
+B<LIBS> statements may have attributes, which apply to all the
+libraries given in such a statement. For example:
+
+ LIBS=libfoo
+ LIBS{noinst}=libbar
+
+With those two lines, the library C<libfoo> will not have the
+attribute C<noinst>, while the library C<libbar> will.
+
+=item B<MODULES=> I<name>
+
+Collects names of dynamically loadable modules that should be built.
+
+B<MODULES> statements may have attributes, which apply to all the
+modules given in such a statement. For example:
+
+ MODULES=foo
+ MODULES{noinst}=bar
+
+With those two lines, the module C<foo> will not have the attribute
+C<noinst>, while the module C<bar> will.
+
+=item B<SCRIPTS=> I<name>
+
+Collects names of scripts that should be built, or that just exist.
+That is how they differ from programs, as programs are always expected
+to be compiled from multiple sources.
+
+B<SCRIPTS> statements may have attributes, which apply to all the
+scripts given in such a statement. For example:
+
+ SCRIPTS=foo
+ SCRIPTS{noinst}=bar
+
+With those two lines, the script C<foo> will not have the attribute
+C<noinst>, while the script C<bar> will.
+
+=back
+
+=head2 Indexed statements
+
+=over 4
+
+=item B<DEPEND[>I<items>B<]> B<=> I<file> ...
+
+Collects dependencies, where I<items> depend on the given I<file>s.
+
+As a special case, the I<items> may be empty, for which the build file
+generators should make the whole build depend on the given I<file>s,
+rather than the specific I<items>.
+
+The I<items> may be any program, library, module, script, or any
+filename used as a value anywhere.
+
+The I<items> may also be literal build file targets. Those are
+recognised by being surrounded be vertical bars (also known as the
+"pipe" character), C<|>. For example:
+
+ DEPEND[|tests|]=fipsmodule.cnf
+
+B<DEPEND> statements may have attributes, which apply to each
+individual dependency in such a statement. For example:
+
+ DEPEND[libfoo.a]=libmandatory.a
+ DEPEND[libfoo.a]{weak}=libbar.a libcookie.a
+
+With those statements, the dependency between C<libfoo.a> and
+C<libmandatory.a> is strong, while the dependency between C<libfoo.a>
+and C<libbar.a> and C<libcookie.a> is weak. See the description of
+B<weak> in L</Known attributes> for more information.
+
+=item B<GENERATE[>I<item>B<]> B<=> I<generator> I<generator-arg> ...
+
+This specifies that the I<item> is generated using the I<generator>
+with the I<generator-arg>s as arguments, plus the name of the output
+file as last argument.
+
+For I<generator>s where this is applicable, any B<INCLUDE> statement
+for the same I<item> will be given to the I<generator> as its
+inclusion directories. Likewise, any B<DEPEND> statement for the same
+I<item> will be given to the I<generator> as an extra file or module
+to load, where this is applicable.
+
+The build file generators must be able to recognise the I<generator>.
+Currently, they at least recognise files ending in C<.pl>, and will
+execute them to generate the I<item>, and files ending in C<.in>,
+which will be used as input for L<OpenSSL::Template> to generate
+I<item> (in other words, we use the exact same style of
+L</Perl nuggets> mechanism that is used to read F<build.info> files).
+
+=item B<SOURCE[>I<item>B<]> B<=> I<file> ...
+
+Collects filenames that will be used as source files for I<item>.
+
+The I<item> must be a singular item, and may be any program, library,
+module or script given with B<PROGRAMS>, B<LIBS>, B<MODULES> and
+B<SCRIPTS>.
+
+Static libraries may be sources. In that case, its object files are
+used directly when building I<item> instead of relying on library
+dependency and symbol resolution (through B<DEPEND> statements).
+
+B<SOURCE> statements may have attributes, which apply to each
+individual dependency in such a statement. For example:
+
+ SOURCE[prog]=prog_a.c
+ SOURCE[prog]{check}=prog_b.c prog_c.c
+
+With those statements, the association between C<prog> and C<prog_a.c>
+comes with no extra attributes, while the association between C<prog>
+and C<prog_b.c> as well as C<prog_c.c> comes with the extra attribute
+C<check>.
+
+=item B<SHARED_SOURCE[>I<item>B<]> B<=> I<file> ...
+
+Collects filenames that will be used as source files for I<item>.
+
+The I<item> must be a singular item, and may be any library or module
+given with B<LIBS> or B<MODULES>. For libraries, the given filenames
+are only used for their shared form, so if the item is a library name
+ending with C<.a>, the filenames will be ignored.
+
+B<SHARED_SOURCE> statements may have attributes, just as B<SOURCE>
+statements.
+
+=item B<DEFINE[>I<items>B<]> B<=> I<name>[B<=>I<value>] ...
+
+Collects I<name> / I<value> pairs (or just I<name> with no defined
+value if no I<value> is given) associated with I<items>.
+
+The build file generators will decide what to do with them. For
+example, these pairs should become C macro definitions whenever a
+C<.c> file is built into an object file.
+
+=item B<INCLUDE[>I<items>B<]> B<=> I<dir> ...
+
+Collects inclusion directories that will be used when building the
+I<items> components (object files and whatever else). This is used at
+the discretion of the build file generators.
+
+=back
+
+=head2 Known attributes
+
+Note: this will never be a complete list of attributes.
+
+=over 4
+
+=item B<noinst>
+
+This is used to specify that the end products this is set for should
+not be installed, that they are only internal. This is applicable on
+internal static libraries, or on test programs.
+
+=item B<misc>
+
+This is used with B<SCRIPTS>, to specify that some scripts should be
+installed in the "misc" directory rather than the normal program
+directory.
+
+=item B<engine>
+
+This is used with B<MODULES>, to specify what modules are engines and
+should be installed in the engines directory instead of the modules
+directory.
+
+=item B<weak>
+
+This is used with B<DEPEND> where libraries are involved, to specify
+that the dependency between two libraries is weak and is only there to
+infer order.
+
+Without this attribute, a dependency between two libraries, expressed
+like this, means that if C<libfoo.a> appears in a linking command
+line, so will C<libmandatory.a>:
+
+ DEPEND[libfoo.a]=libmandatory.a
+
+With this attribute, a dependency between two libraries, expressed
+like this, means that if I<both> C<libfoo.a> and C<libmandatory.a>
+appear in a linking command line (because of recursive dependencies
+through other libraries), they will be ordered in such a way that this
+dependency is maintained:
+
+ DEPEND[libfoo.a]{weak}=libfoo.a libcookie.a
+
+This is useful in complex dependency trees where two libraries can be
+used as alternatives for each other. In this example, C<lib1.a> and
+C<lib2.a> have alternative implementations of the same thing, and
+C<libmandatory.a> has unresolved references to that same thing, and is
+therefore depending on either of them, but not both at the same time:
+
+ DEPEND[program1]=libmandatory.a lib1.a
+ DEPEND[program2]=libmandatory.a lib2.a
+ DEPEND[libmandatory]{weak}=lib1.a lib2.a
+
+=back
+
+=head1 GLOSSARY
+
+=over 4
+
+=item "build file"
+
+This is any platform specific file that describes the complete build,
+with platform specific commands. On Unix, this is typically
+F<Makefile>; on VMS, this is typically F<descrip.mms>.
+
+=item "build file generator"
+
+Perl code that generates build files, given configuration data and
+data collected from F<build.info> files.
+
+=item "plain statement"
+
+Any F<build.info> statement of the form B<I<KEYWORD>>=I<values>, with
+the exception of conditional statements and variable assignments.
+
+=item "indexed statement"
+
+Any F<build.info> statement of the form B<I<KEYWORD>[>I<items>B<]=>I<values>,
+with the exception of conditional statements.
+
+=item "intermediate file"
+
+Any file that's an intermediate between a source file and an end
+product.
+
+=item "end product"
+
+Any file that is mentioned in the B<PROGRAMS>, B<LIBS>, B<MODULES> or
+B<SCRIPTS>.
+
+=back
+
+=head1 SEE ALSO
+
+For OpenSSL::Template documentation,
+C<perldoc -o man util/perl/OpenSSL/Template.pm>
+
+L<Text::Template|https://metacpan.org/pod/Text::Template>
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use this
+file except in compliance with the License. You can obtain a copy in the file
+LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man7/deprecation.pod b/doc/internal/man7/deprecation.pod
new file mode 100644
index 000000000000..13a4b059a04c
--- /dev/null
+++ b/doc/internal/man7/deprecation.pod
@@ -0,0 +1,140 @@
+=pod
+
+=head1 NAME
+
+OPENSSL_NO_DEPRECATED_3_0, OSSL_DEPRECATEDIN_3_0,
+OPENSSL_NO_DEPRECATED_1_1_1, OSSL_DEPRECATEDIN_1_1_1,
+OPENSSL_NO_DEPRECATED_1_1_0, OSSL_DEPRECATEDIN_1_1_0,
+OPENSSL_NO_DEPRECATED_1_0_2, OSSL_DEPRECATEDIN_1_0_2,
+OPENSSL_NO_DEPRECATED_1_0_1, OSSL_DEPRECATEDIN_1_0_1,
+OPENSSL_NO_DEPRECATED_1_0_0, OSSL_DEPRECATEDIN_1_0_0,
+OPENSSL_NO_DEPRECATED_0_9_8, OSSL_DEPRECATEDIN_0_9_8,
+deprecation - How to do deprecation
+
+=head1 DESCRIPTION
+
+Deprecation of a symbol is adding an attribute to the declaration of that
+symbol (function, type, variable, but we currently only do that for
+functions in our public header files, F<< <openssl/*.h> >>).
+
+Removal of a symbol is not the same thing as deprecation, as it actually
+explicitly removes the symbol from public view.
+
+OpenSSL configuration supports deprecation as well as simulating removal of
+symbols from public view (with the configuration option C<no-deprecated>, or
+if the user chooses to do so, with L<OPENSSL_NO_DEPRECATED(7)>), and also
+supports doing this in terms of a specified OpenSSL version (with the
+configuration option C<--api>, or if the user chooses to do so, with
+L<OPENSSL_API_COMPAT(7)>).
+
+Deprecation is done using attribute macros named
+B<OSSL_DEPRECATEDIN_I<version>>, used with any declaration it applies to.
+
+Simulating removal is done with C<#ifndef> preprocessor guards using macros
+named B<OPENSSL_NO_DEPRECATED_I<version>>.
+
+B<OSSL_DEPRECATEDIN_I<version>> and B<OPENSSL_NO_DEPRECATED_I<version>> are
+defined in F<< <openssl/macros.h> >>.
+
+In those macro names, B<I<version>> corresponds to the OpenSSL release since
+which the deprecation applies, with underscores instead of periods. Because
+of the change in version scheme with OpenSSL 3.0, the B<I<version>> for
+versions before that are three numbers (such as C<1_1_0>), while they are
+two numbers (such as C<3_0>) from 3.0 and on.
+
+The implementation of a deprecated symbol is kept for one of two reasons:
+
+=over 4
+
+=item Planned to be removed
+
+The symbol and its implementation are planned to be removed some time in the
+future, but needs to remain available until that time.
+Such an implementation needs to be guarded appropriately, as shown in
+L</Implementations to be removed> below.
+
+=item Planned to remain internally
+
+The symbol is planned to be removed from public view, but will otherwise
+remain for internal purposes. In this case, the implementation doesn't need
+to change or be guarded.
+
+However, it's necessary to ensure that the declaration remains available for
+the translation unit where the symbol is used or implemented, even when the
+symbol is publicly unavailable through simulated removal. That's done by
+including an internal header file very early in the affected translation
+units. See L</Implementations to remain internally> below.
+
+In the future, when the deprecated declaration is to actually be removed
+from public view, it should be moved to an internal header file, with the
+deprecation attribute removed, and the translation units that implement or
+use that symbol should adjust their header inclusions accordingly.
+
+=back
+
+=head1 EXAMPLES
+
+=head2 Header files
+
+In public header files (F<< <openssl/*.h> >>), this is what a deprecation is
+expected to look like, including the preprocessor wrapping for simulated
+removal:
+
+ # ifndef OPENSSL_NO_DEPRECATED_3_0
+ /* ... */
+
+ OSSL_DEPRECATEDIN_3_0 RSA *RSA_new_method(ENGINE *engine);
+
+ /* ... */
+ # endif
+
+=head2 Implementations to be removed
+
+For a deprecated function that we plan to remove in the future, for example
+RSA_new_method(), the following should be found very early (before including
+any OpenSSL header file) in the translation unit that implements it and in
+any translation unit that uses it:
+
+ /*
+ * Suppress deprecation warnings for RSA low level implementations that are
+ * kept until removal.
+ */
+ #define OPENSSL_SUPPRESS_DEPRECATED
+
+The RSA_new_method() implementation itself must be guarded the same way as
+its declaration in the public header file is:
+
+ #ifndef OPENSSL_NO_DEPRECATED_3_0
+ RSA *RSA_new_method(ENGINE *engine)
+ {
+ /* ... */
+ }
+ #endif
+
+=head2 Implementations to remain internally
+
+For a deprecated function that we plan to keep internally, for example
+RSA_size(), the following should be found very early (before including any
+other OpenSSL header file) in the translation unit that implements it and in
+any translation unit that uses it:
+
+ /*
+ * RSA low level APIs are deprecated for public use, but are kept for
+ * internal use.
+ */
+ #include "internal/deprecated.h"
+
+=head1 SEE ALSO
+
+L<openssl_user_macros(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/life-cycles/Makefile b/doc/life-cycles/Makefile
new file mode 100644
index 000000000000..4c12558e63df
--- /dev/null
+++ b/doc/life-cycles/Makefile
@@ -0,0 +1,26 @@
+GRAPHS=cipher.dot digest.dot kdf.dot mac.dot pkey.dot rand.dot
+IMAGES=
+
+all: png txt
+png: $(subst .dot,.png,$(GRAPHS))
+txt: $(subst .dot,.txt,$(GRAPHS))
+ @echo
+ @echo Remember to check and manually fix the mistakes before merging
+ @echo into the man pages.
+ @echo
+
+# for the dot program:
+# sudo apt install graphviz
+%.png: %.dot
+ dot -Tpng -O $<
+ @mv $<.png $@
+
+# for the graph-easy program:
+# sudo apt install cpanminus
+# sudo cpanm Graph::Easy
+%.txt: %.dot
+ graph-easy --from=dot --as_ascii < $< > $@
+
+clean:
+ rm -f $(wildcard *.png) $(wildcard *.txt)
+
diff --git a/doc/life-cycles/README.md b/doc/life-cycles/README.md
new file mode 100644
index 000000000000..e65c3d3435fc
--- /dev/null
+++ b/doc/life-cycles/README.md
@@ -0,0 +1,20 @@
+Algorithm Life-Cycle Diagrams
+=============================
+
+This directory contains the algorithm life-cycle diagram sources.
+
+The canonical life-cycles are in the spreadsheet.
+
+The various .dot files are graph descriptions for the
+[GraphViz](https://www.graphviz.org/) tool. These omit edges and should
+be used for guidance only.
+
+To generate the rendered images, you need to install the following packages:
+
+ sudo apt install graphviz cpanminus
+ sudo cpanm Graph::Easy
+
+Running `make` will produce a number of `.txt` and `.png` files.
+These are the rendered `.dot` files. The `.txt` files require
+additional editing before they can be added to the manual pages in
+`internal/man7/life_cycle-*.pod`.
diff --git a/doc/life-cycles/cipher.dot b/doc/life-cycles/cipher.dot
new file mode 100644
index 000000000000..c1d5b8346890
--- /dev/null
+++ b/doc/life-cycles/cipher.dot
@@ -0,0 +1,72 @@
+digraph cipher {
+ bgcolor="transparent";
+
+ begin [label=start, color="#deeaee", style="filled"];
+ newed [fontcolor="#c94c4c", style="solid"];
+
+ initialised [fontcolor="#c94c4c"];
+ updated [fontcolor="#c94c4c"];
+ finaled [fontcolor="#c94c4c"];
+ end [label="freed", color="#deeaee", style="filled"];
+
+ d_initialised [label="initialised\n(decryption)", fontcolor="#c94c4c"];
+ d_updated [label="updated\n(decryption)", fontcolor="#c94c4c"];
+ e_initialised [label="initialised\n(encryption)", fontcolor="#c94c4c"];
+ e_updated [label="updated\n(encryption)", fontcolor="#c94c4c"];
+
+ begin -> newed [label="EVP_CIPHER_CTX_new"];
+ newed -> initialised [label="EVP_CipherInit"];
+ initialised -> initialised [label="EVP_CipherInit\n(not required but allowed)",
+ style=dashed];
+ initialised -> updated [label="EVP_CipherUpdate", weight=2];
+ updated -> updated [label="EVP_CipherUpdate"];
+ updated -> finaled [label="EVP_CipherFinal"];
+ finaled -> finaled [label="EVP_CIPHER_CTX_get_params\n(AEAD encryption)",
+ style=dashed];
+ finaled -> end [label="EVP_CIPHER_CTX_free"];
+ newed -> d_initialised [label="EVP_DecryptInit"];
+ d_initialised -> d_initialised [label="EVP_DecryptInit\n(not required but allowed)",
+ style=dashed];
+ d_initialised -> d_updated [label="EVP_DecryptUpdate", weight=2];
+ d_updated -> d_updated [label="EVP_DecryptUpdate"];
+ d_updated -> finaled [label="EVP_DecryptFinal"];
+ newed -> e_initialised [label="EVP_EncryptInit"];
+ e_initialised -> e_initialised [label="EVP_EncryptInit\n(not required but allowed)",
+ style=dashed];
+ e_initialised -> e_updated [label="EVP_EncryptUpdate", weight=2];
+ e_updated -> e_updated [label="EVP_EncryptUpdate"];
+ e_updated -> finaled [label="EVP_EncryptFinal"];
+ most -> newed [label="EVP_CIPHER_CTX_reset", style=dashed,
+ color="#034f84", fontcolor="#034f84"];
+ most [label="any of the initialised\nupdated or finaled states", style=dashed,
+ color="#034f84", fontcolor="#034f84"];
+}
+
+/* This is a version with a single flavour which is easier to comprehend
+digraph cipher {
+ bgcolor="transparent";
+
+ begin [label=start, color="#deeaee", style="filled"];
+ newed [fontcolor="#c94c4c", style="solid"];
+ initialised [fontcolor="#c94c4c"];
+ updated [fontcolor="#c94c4c"];
+ finaled [fontcolor="#c94c4c"];
+ end [label="freed", color="#deeaee", style="filled"];
+
+ begin -> newed [label="EVP_CIPHER_CTX_new"];
+ newed -> initialised [label="EVP_CipherInit"];
+ initialised -> initialised [label="EVP_CipherInit\n(not required but allowed)",
+ style=dashed];
+ initialised -> updated [label="EVP_CipherUpdate", weight=2];
+ updated -> updated [label="EVP_CipherUpdate"];
+ updated -> finaled [label="EVP_CipherFinal"];
+ finaled -> finaled [label="EVP_CIPHER_CTX_get_params\n(AEAD encryption)",
+ style=dashed];
+ finaled -> end [label="EVP_CIPHER_CTX_free"];
+ finaled -> newed [label="EVP_CIPHER_CTX_reset", style=dashed,
+ color="#034f84", fontcolor="#034f84"];
+ updated -> newed [label="EVP_CIPHER_CTX_reset", style=dashed,
+ color="#034f84", fontcolor="#034f84"];
+}
+*/
+
diff --git a/doc/life-cycles/digest.dot b/doc/life-cycles/digest.dot
new file mode 100644
index 000000000000..8d4d72480c9a
--- /dev/null
+++ b/doc/life-cycles/digest.dot
@@ -0,0 +1,33 @@
+digraph digest {
+ bgcolor="transparent";
+
+ begin [label=start, color="#deeaee", style="filled"];
+ newed [label=newed, fontcolor="#c94c4c", style="solid"];
+ initialised [label=initialised, fontcolor="#c94c4c"];
+ updated [label=updated, fontcolor="#c94c4c"];
+ finaled [label="finaled", fontcolor="#c94c4c"];
+ end [label="freed", color="#deeaee", style="filled"];
+
+ begin -> newed [label="EVP_MD_CTX_new"];
+ newed -> initialised [label="EVP_DigestInit"];
+ initialised -> updated [label="EVP_DigestUpdate", weight=3];
+ updated -> updated [label="EVP_DigestUpdate"];
+ updated -> finaled [label="EVP_DigestFinal"];
+ updated -> finaled [label="EVP_DigestFinalXOF",
+ fontcolor="#808080", color="#808080"];
+ /* Once this works it should go back in:
+ finaled -> finaled [taillabel="EVP_DigestFinalXOF",
+ labeldistance=9, labelangle=345,
+ labelfontcolor="#808080", color="#808080"];
+ */
+ finaled -> end [label="EVP_MD_CTX_free"];
+ finaled -> newed [label="EVP_MD_CTX_reset", style=dashed, weight=2,
+ color="#034f84", fontcolor="#034f84"];
+ updated -> newed [label="EVP_MD_CTX_reset", style=dashed,
+ color="#034f84", fontcolor="#034f84"];
+ updated -> initialised [label="EVP_DigestInit", weight=0, style=dashed,
+ color="#034f84", fontcolor="#034f84"];
+ finaled -> initialised [label="EVP_DigestInit", style=dashed,
+ color="#034f84", fontcolor="#034f84"];
+}
+
diff --git a/doc/life-cycles/kdf.dot b/doc/life-cycles/kdf.dot
new file mode 100644
index 000000000000..2dce34377db6
--- /dev/null
+++ b/doc/life-cycles/kdf.dot
@@ -0,0 +1,16 @@
+strict digraph kdf {
+ bgcolor="transparent";
+
+ begin [label=start, color="#deeaee", style="filled"];
+ newed [label="newed", fontcolor="#c94c4c", style="solid"];
+ deriving [label="deriving", fontcolor="#c94c4c"];
+ end [label="freed", color="#deeaee", style="filled"];
+
+ begin -> newed [label="EVP_KDF_CTX_new"];
+ newed -> deriving [label="EVP_KDF_derive"];
+ deriving -> deriving [label="EVP_KDF_derive", style=dashed];
+ deriving -> end [label="EVP_KDF_CTX_free"];
+ deriving -> newed [label="EVP_KDF_CTX_reset", style=dashed,
+ color="#034f84", fontcolor="#034f84"];
+}
+
diff --git a/doc/life-cycles/lifecycles.ods b/doc/life-cycles/lifecycles.ods
new file mode 100644
index 000000000000..6cc2030a9efa
--- /dev/null
+++ b/doc/life-cycles/lifecycles.ods
Binary files differ
diff --git a/doc/life-cycles/mac.dot b/doc/life-cycles/mac.dot
new file mode 100644
index 000000000000..fe277f8328e6
--- /dev/null
+++ b/doc/life-cycles/mac.dot
@@ -0,0 +1,28 @@
+digraph mac {
+ bgcolor="transparent";
+
+ begin [label=start, color="#deeaee", style="filled"];
+ newed [fontcolor="#c94c4c", style="solid"];
+ initialised [fontcolor="#c94c4c"];
+ updated [fontcolor="#c94c4c"];
+ finaled [fontcolor="#c94c4c"];
+ end [label=freed, color="#deeaee", style="filled"];
+
+ begin -> newed [label="EVP_MAC_CTX_new"];
+ newed -> initialised [label="EVP_MAC_init"];
+ initialised -> updated [label="EVP_MAC_update"];
+ updated -> updated [label="EVP_MAC_update"];
+ updated -> finaled [label="EVP_MAC_final"];
+ updated -> finaled [label="EVP_MAC_finalXOF",
+ fontcolor="#808080", color="#808080"];
+ /* Once this works it should go back in:
+ finaled -> finaled [label="EVP_MAC_final_XOF",
+ fontcolor="#808080", color="#808080"];
+ */
+ finaled -> end [label="EVP_MAC_CTX_free"];
+ updated -> initialised [label="EVP_MAC_init", style=dashed,
+ color="#034f84", fontcolor="#034f84"];
+ finaled -> initialised [label="EVP_MAC_init", style=dashed,
+ color="#034f84", fontcolor="#034f84"];
+}
+
diff --git a/doc/life-cycles/pkey.dot b/doc/life-cycles/pkey.dot
new file mode 100644
index 000000000000..58b3a0c5bb77
--- /dev/null
+++ b/doc/life-cycles/pkey.dot
@@ -0,0 +1,49 @@
+strict digraph pkey {
+ bgcolor="transparent";
+ layout=circo
+
+ begin [label=start, color="#deeaee", style="filled"];
+ newed [fontcolor="#c94c4c", style="solid"];
+ digestsign [label="digest sign", fontcolor="#AB3910", color="#AB3910"]
+ verify [fontcolor="#F8CF2C", color="#F8CF2C"]
+ verifyrecover [label="verify recover", fontcolor="#B19FF9", color="#B19FF9"]
+ encrypt [fontcolor="#63AAC0", color="#63AAC0"]
+ decrypt [fontcolor="#425F06", color="#425F06"]
+ derive [fontcolor="#FEA303", color="#FEA303"]
+ encapsulate [fontcolor="#D95980", color="#D95980"]
+ decapsulate [fontcolor="#A16AE8", color="#A16AE8"]
+ paramgen [label="parameter\ngeneration", fontcolor="#2879C0", color="#2879C0"]
+ keygen [label="key\ngeneration", fontcolor="#2F7604", color="#2F7604"]
+
+ begin -> newed [label="EVP_PKEY_CTX_new"];
+
+ newed -> digestsign [label="EVP_PKEY_sign_init", color="#AB3910", fontcolor="#AB3910"];
+ digestsign -> digestsign [label="EVP_PKEY_sign", color="#AB3910", fontcolor="#AB3910"];
+
+ newed -> verify [label="EVP_PKEY_verify_init", fontcolor="#F8CF2C", color="#F8CF2C"];
+ verify -> verify [label="EVP_PKEY_verify", fontcolor="#F8CF2C", color="#F8CF2C"];
+
+ newed -> verifyrecover [label="EVP_PKEY_verify_recover_init", fontcolor="#B19FF9", color="#B19FF9"];
+ verifyrecover -> verifyrecover [label="EVP_PKEY_verify_recover", fontcolor="#B19FF9", color="#B19FF9"];
+
+ newed -> encrypt [label="EVP_PKEY_encrypt_init", fontcolor="#63AAC0", color="#63AAC0"];
+ encrypt -> encrypt [label="EVP_PKEY_encrypt", fontcolor="#63AAC0", color="#63AAC0"];
+
+ newed -> decrypt [label="EVP_PKEY_decrypt_init", fontcolor="#425F06", color="#425F06"];
+ decrypt -> decrypt [label="EVP_PKEY_decrypt", fontcolor="#425F06", color="#425F06"];
+
+ newed -> derive [label="EVP_PKEY_derive_init", fontcolor="#FEA303", color="#FEA303"];
+ derive -> derive [label="EVP_PKEY_derive\nEVP_PKEY_derive_set_peer", fontcolor="#FEA303", color="#FEA303"];
+
+ newed -> encapsulate [label="EVP_PKEY_encapsulate_init", fontcolor="#D95980", color="#D95980"];
+ encapsulate -> encapsulate [label="EVP_PKEY_encapsulate", fontcolor="#D95980", color="#D95980"];
+
+ newed -> decapsulate [label="EVP_PKEY_decapsulate_init", fontcolor="#A16AE8", color="#A16AE8"];
+ decapsulate -> decapsulate [label="EVP_PKEY_decapsulate", fontcolor="#A16AE8", color="#A16AE8"];
+
+ newed -> paramgen [label="EVP_PKEY_paramgen_init", fontcolor="#2879C0", color="#2879C0"];
+ paramgen -> paramgen [label="EVP_PKEY_paramgen\nEVP_PKEY_gen", fontcolor="#2879C0", color="#2879C0"];
+
+ newed -> keygen [label="EVP_PKEY_keygen_init", fontcolor="#2F7604", color="#2F7604"];
+ keygen -> keygen [label="EVP_PKEY_keygen\nEVP_PKEY_gen", fontcolor="#2F7604", color="#2F7604"];
+}
diff --git a/doc/life-cycles/rand.dot b/doc/life-cycles/rand.dot
new file mode 100644
index 000000000000..a57cf710c75d
--- /dev/null
+++ b/doc/life-cycles/rand.dot
@@ -0,0 +1,17 @@
+strict digraph rand {
+ bgcolor="transparent";
+
+ begin [label=start, color="#deeaee", style="filled"];
+ newed [fontcolor="#c94c4c", style="solid"];
+ instantiated [fontcolor="#c94c4c"];
+ uninstantiated [fontcolor="#c94c4c"];
+ end [label="freed", color="#deeaee", style="filled"];
+
+ begin -> newed [label="EVP_RAND_CTX_new"];
+ newed -> instantiated [label="EVP_RAND_instantiate"];
+ instantiated -> instantiated [label="EVP_RAND_generate"];
+ instantiated -> uninstantiated [label="EVP_RAND_uninstantiate"];
+ uninstantiated -> end [label="EVP_RAND_CTX_free"];
+ uninstantiated -> instantiated [label="EVP_RAND_instantiate", style=dashed, color="#034f84", fontcolor="#034f84"];
+}
+
diff --git a/doc/man1/CA.pl.pod b/doc/man1/CA.pl.pod
index 4e8958e554dd..e05775cdca66 100644
--- a/doc/man1/CA.pl.pod
+++ b/doc/man1/CA.pl.pod
@@ -21,45 +21,62 @@ B<-signCA> |
B<-signcert> |
B<-crl> |
B<-newca>
-[B<-extra-cmd> extra-params]
+[B<-extra-I<cmd>> I<parameter>]
-B<CA.pl> B<-pkcs12> [B<-extra-pkcs12> extra-params] [B<certname>]
+B<CA.pl> B<-pkcs12> [I<certname>]
-B<CA.pl> B<-verify> [B<-extra-verify> extra-params] B<certfile>...
+B<CA.pl> B<-verify> I<certfile> ...
-B<CA.pl> B<-revoke> [B<-extra-ca> extra-params] B<certfile> [B<reason>]
+B<CA.pl> B<-revoke> I<certfile> [I<reason>]
=head1 DESCRIPTION
The B<CA.pl> script is a perl script that supplies the relevant command line
-arguments to the B<openssl> command for some common certificate operations.
+arguments to the L<openssl(1)> command for some common certificate operations.
It is intended to simplify the process of certificate creation and management
by the use of some simple options.
+The script is intended as a simple front end for the L<openssl(1)> program for
+use by a beginner. Its behaviour isn't always what is wanted. For more control
+over the behaviour of the certificate commands call the L<openssl(1)> command
+directly.
+
+Most of the filenames mentioned below can be modified by editing the
+B<CA.pl> script.
+
+Under some environments it may not be possible to run the B<CA.pl> script
+directly (for example Win32) and the default configuration file location may
+be wrong. In this case the command:
+
+ perl -S CA.pl
+
+can be used and the B<OPENSSL_CONF> environment variable can be set to point to
+the correct path of the configuration file.
+
=head1 OPTIONS
=over 4
-=item B<?>, B<-h>, B<-help>
+=item B<-?>, B<-h>, B<-help>
Prints a usage message.
=item B<-newcert>
Creates a new self signed certificate. The private key is written to the file
-"newkey.pem" and the request written to the file "newreq.pem".
-This argument invokes B<openssl req> command.
+F<newkey.pem> and the request written to the file F<newreq.pem>.
+Invokes L<openssl-req(1)>.
=item B<-newreq>
Creates a new certificate request. The private key is written to the file
-"newkey.pem" and the request written to the file "newreq.pem".
-Executes B<openssl req> command below the hood.
+F<newkey.pem> and the request written to the file F<newreq.pem>.
+Executes L<openssl-req(1)> under the hood.
=item B<-newreq-nodes>
Is like B<-newreq> except that the private key will not be encrypted.
-Uses B<openssl req> command.
+Uses L<openssl-req(1)>.
=item B<-newca>
@@ -67,68 +84,73 @@ Creates a new CA hierarchy for use with the B<ca> program (or the B<-signcert>
and B<-xsign> options). The user is prompted to enter the filename of the CA
certificates (which should also contain the private key) or by hitting ENTER
details of the CA will be prompted for. The relevant files and directories
-are created in a directory called "demoCA" in the current directory.
-B<openssl req> and B<openssl ca> commands are get invoked.
+are created in a directory called F<demoCA> in the current directory.
+Uses L<openssl-req(1)> and L<openssl-ca(1)>.
+
+If the F<demoCA> directory already exists then the B<-newca> command will not
+overwrite it and will do nothing. This can happen if a previous call using
+the B<-newca> option terminated abnormally. To get the correct behaviour
+delete the directory if it already exists.
=item B<-pkcs12>
Create a PKCS#12 file containing the user certificate, private key and CA
certificate. It expects the user certificate and private key to be in the
-file "newcert.pem" and the CA certificate to be in the file demoCA/cacert.pem,
-it creates a file "newcert.p12". This command can thus be called after the
+file F<newcert.pem> and the CA certificate to be in the file F<demoCA/cacert.pem>,
+it creates a file F<newcert.p12>. This command can thus be called after the
B<-sign> option. The PKCS#12 file can be imported directly into a browser.
If there is an additional argument on the command line it will be used as the
"friendly name" for the certificate (which is typically displayed in the browser
list box), otherwise the name "My Certificate" is used.
-Delegates work to B<openssl pkcs12> command.
+Delegates work to L<openssl-pkcs12(1)>.
=item B<-sign>, B<-signcert>, B<-xsign>
-Calls the B<ca> program to sign a certificate request. It expects the request
-to be in the file "newreq.pem". The new certificate is written to the file
-"newcert.pem" except in the case of the B<-xsign> option when it is written
-to standard output. Leverages B<openssl ca> command.
+Calls the L<openssl-ca(1)> command to sign a certificate request. It expects the
+request to be in the file F<newreq.pem>. The new certificate is written to the
+file F<newcert.pem> except in the case of the B<-xsign> option when it is
+written to standard output.
=item B<-signCA>
This option is the same as the B<-sign> option except it uses the
configuration file section B<v3_ca> and so makes the signed request a
valid CA certificate. This is useful when creating intermediate CA from
-a root CA. Extra params are passed on to B<openssl ca> command.
+a root CA. Extra params are passed to L<openssl-ca(1)>.
=item B<-signcert>
This option is the same as B<-sign> except it expects a self signed certificate
-to be present in the file "newreq.pem".
-Extra params are passed on to B<openssl x509> and B<openssl ca> commands.
+to be present in the file F<newreq.pem>.
+Extra params are passed to L<openssl-x509(1)> and L<openssl-ca(1)>.
=item B<-crl>
-Generate a CRL. Executes B<openssl ca> command.
+Generate a CRL. Executes L<openssl-ca(1)>.
-=item B<-revoke certfile [reason]>
+=item B<-revoke> I<certfile> [I<reason>]
Revoke the certificate contained in the specified B<certfile>. An optional
reason may be specified, and must be one of: B<unspecified>,
B<keyCompromise>, B<CACompromise>, B<affiliationChanged>, B<superseded>,
B<cessationOfOperation>, B<certificateHold>, or B<removeFromCRL>.
-Leverages B<openssl ca> command.
+Leverages L<openssl-ca(1)>.
=item B<-verify>
-Verifies certificates against the CA certificate for "demoCA". If no
+Verifies certificates against the CA certificate for F<demoCA>. If no
certificates are specified on the command line it tries to verify the file
-"newcert.pem". Invokes B<openssl verify> command.
+F<newcert.pem>. Invokes L<openssl-verify(1)>.
-=item B<-extra-req> | B<-extra-ca> | B<-extra-pkcs12> | B<-extra-x509> | B<-extra-verify> <extra-params>
+=item B<-extra-I<cmd>> I<parameter>
-The purpose of these parameters is to allow optional parameters to be supplied
-to B<openssl> that this command executes. The B<-extra-cmd> are specific to the
-option being used and the B<openssl> command getting invoked. For example
-when this command invokes B<openssl req> extra parameters can be passed on
-with the B<-extra-req> parameter. The
-B<openssl> commands being invoked per option are documented below.
-Users should consult B<openssl> command documentation for more information.
+For each option B<extra-I<cmd>>, pass I<parameter> to the L<openssl(1)>
+sub-command with the same name as I<cmd>, if that sub-command is invoked.
+For example, if L<openssl-req(1)> is invoked, the I<parameter> given with
+B<-extra-req> will be passed to it.
+For multi-word parameters, either repeat the option or quote the I<parameters>
+so it looks like one word to your shell.
+See the individual command documentation for more information.
=back
@@ -146,67 +168,30 @@ the request and finally create a PKCS#12 file containing it.
CA.pl -sign
CA.pl -pkcs12 "My Test Certificate"
-=head1 DSA CERTIFICATES
-
-Although the B<CA.pl> creates RSA CAs and requests it is still possible to
-use it with DSA certificates and requests using the L<req(1)> command
-directly. The following example shows the steps that would typically be taken.
-
-Create some DSA parameters:
+=head1 ENVIRONMENT
- openssl dsaparam -out dsap.pem 1024
-
-Create a DSA CA certificate and private key:
-
- openssl req -x509 -newkey dsa:dsap.pem -keyout cacert.pem -out cacert.pem
-
-Create the CA directories and files:
-
- CA.pl -newca
-
-enter cacert.pem when prompted for the CA filename.
-
-Create a DSA certificate request and private key (a different set of parameters
-can optionally be created first):
-
- openssl req -out newreq.pem -newkey dsa:dsap.pem
-
-Sign the request:
-
- CA.pl -sign
-
-=head1 NOTES
-
-Most of the filenames mentioned can be modified by editing the B<CA.pl> script.
-
-If the demoCA directory already exists then the B<-newca> command will not
-overwrite it and will do nothing. This can happen if a previous call using
-the B<-newca> option terminated abnormally. To get the correct behaviour
-delete the demoCA directory if it already exists.
-
-Under some environments it may not be possible to run the B<CA.pl> script
-directly (for example Win32) and the default configuration file location may
-be wrong. In this case the command:
-
- perl -S CA.pl
-
-can be used and the B<OPENSSL_CONF> environment variable changed to point to
-the correct path of the configuration file.
+The environment variable B<OPENSSL> may be used to specify the name of
+the OpenSSL program. It can be a full pathname, or a relative one.
-The script is intended as a simple front end for the B<openssl> program for use
-by a beginner. Its behaviour isn't always what is wanted. For more control over the
-behaviour of the certificate commands call the B<openssl> command directly.
+The environment variable B<OPENSSL_CONFIG> may be used to specify a
+configuration option and value to the B<req> and B<ca> commands invoked by
+this script. It's value should be the option and pathname, as in
+C<-config /path/to/conf-file>.
=head1 SEE ALSO
-L<x509(1)>, L<ca(1)>, L<req(1)>, L<pkcs12(1)>,
+L<openssl(1)>,
+L<openssl-x509(1)>,
+L<openssl-ca(1)>,
+L<openssl-req(1)>,
+L<openssl-pkcs12(1)>,
L<config(5)>
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man1/asn1parse.pod b/doc/man1/asn1parse.pod
deleted file mode 100644
index 0e1fcc686f6c..000000000000
--- a/doc/man1/asn1parse.pod
+++ /dev/null
@@ -1,215 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-asn1parse,
-asn1parse - ASN.1 parsing tool
-
-=head1 SYNOPSIS
-
-B<openssl> B<asn1parse>
-[B<-help>]
-[B<-inform PEM|DER>]
-[B<-in filename>]
-[B<-out filename>]
-[B<-noout>]
-[B<-offset number>]
-[B<-length number>]
-[B<-i>]
-[B<-oid filename>]
-[B<-dump>]
-[B<-dlimit num>]
-[B<-strparse offset>]
-[B<-genstr string>]
-[B<-genconf file>]
-[B<-strictpem>]
-[B<-item name>]
-
-=head1 DESCRIPTION
-
-The B<asn1parse> command is a diagnostic utility that can parse ASN.1
-structures. It can also be used to extract data from ASN.1 formatted data.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-inform> B<DER|PEM>
-
-The input format. B<DER> is binary format and B<PEM> (the default) is base64
-encoded.
-
-=item B<-in filename>
-
-The input file, default is standard input.
-
-=item B<-out filename>
-
-Output file to place the DER encoded data into. If this
-option is not present then no data will be output. This is most useful when
-combined with the B<-strparse> option.
-
-=item B<-noout>
-
-Don't output the parsed version of the input file.
-
-=item B<-offset number>
-
-Starting offset to begin parsing, default is start of file.
-
-=item B<-length number>
-
-Number of bytes to parse, default is until end of file.
-
-=item B<-i>
-
-Indents the output according to the "depth" of the structures.
-
-=item B<-oid filename>
-
-A file containing additional OBJECT IDENTIFIERs (OIDs). The format of this
-file is described in the NOTES section below.
-
-=item B<-dump>
-
-Dump unknown data in hex format.
-
-=item B<-dlimit num>
-
-Like B<-dump>, but only the first B<num> bytes are output.
-
-=item B<-strparse offset>
-
-Parse the contents octets of the ASN.1 object starting at B<offset>. This
-option can be used multiple times to "drill down" into a nested structure.
-
-=item B<-genstr string>, B<-genconf file>
-
-Generate encoded data based on B<string>, B<file> or both using
-L<ASN1_generate_nconf(3)> format. If B<file> only is
-present then the string is obtained from the default section using the name
-B<asn1>. The encoded data is passed through the ASN1 parser and printed out as
-though it came from a file, the contents can thus be examined and written to a
-file using the B<out> option.
-
-=item B<-strictpem>
-
-If this option is used then B<-inform> will be ignored. Without this option any
-data in a PEM format input file will be treated as being base64 encoded and
-processed whether it has the normal PEM BEGIN and END markers or not. This
-option will ignore any data prior to the start of the BEGIN marker, or after an
-END marker in a PEM file.
-
-=item B<-item name>
-
-Attempt to decode and print the data as B<ASN1_ITEM name>. This can be used to
-print out the fields of any supported ASN.1 structure if the type is known.
-
-=back
-
-=head2 Output
-
-The output will typically contain lines like this:
-
- 0:d=0 hl=4 l= 681 cons: SEQUENCE
-
-.....
-
- 229:d=3 hl=3 l= 141 prim: BIT STRING
- 373:d=2 hl=3 l= 162 cons: cont [ 3 ]
- 376:d=3 hl=3 l= 159 cons: SEQUENCE
- 379:d=4 hl=2 l= 29 cons: SEQUENCE
- 381:d=5 hl=2 l= 3 prim: OBJECT :X509v3 Subject Key Identifier
- 386:d=5 hl=2 l= 22 prim: OCTET STRING
- 410:d=4 hl=2 l= 112 cons: SEQUENCE
- 412:d=5 hl=2 l= 3 prim: OBJECT :X509v3 Authority Key Identifier
- 417:d=5 hl=2 l= 105 prim: OCTET STRING
- 524:d=4 hl=2 l= 12 cons: SEQUENCE
-
-.....
-
-This example is part of a self-signed certificate. Each line starts with the
-offset in decimal. B<d=XX> specifies the current depth. The depth is increased
-within the scope of any SET or SEQUENCE. B<hl=XX> gives the header length
-(tag and length octets) of the current type. B<l=XX> gives the length of
-the contents octets.
-
-The B<-i> option can be used to make the output more readable.
-
-Some knowledge of the ASN.1 structure is needed to interpret the output.
-
-In this example the BIT STRING at offset 229 is the certificate public key.
-The contents octets of this will contain the public key information. This can
-be examined using the option B<-strparse 229> to yield:
-
- 0:d=0 hl=3 l= 137 cons: SEQUENCE
- 3:d=1 hl=3 l= 129 prim: INTEGER :E5D21E1F5C8D208EA7A2166C7FAF9F6BDF2059669C60876DDB70840F1A5AAFA59699FE471F379F1DD6A487E7D5409AB6A88D4A9746E24B91D8CF55DB3521015460C8EDE44EE8A4189F7A7BE77D6CD3A9AF2696F486855CF58BF0EDF2B4068058C7A947F52548DDF7E15E96B385F86422BEA9064A3EE9E1158A56E4A6F47E5897
- 135:d=1 hl=2 l= 3 prim: INTEGER :010001
-
-=head1 NOTES
-
-If an OID is not part of OpenSSL's internal table it will be represented in
-numerical form (for example 1.2.3.4). The file passed to the B<-oid> option
-allows additional OIDs to be included. Each line consists of three columns,
-the first column is the OID in numerical format and should be followed by white
-space. The second column is the "short name" which is a single word followed
-by white space. The final column is the rest of the line and is the
-"long name". B<asn1parse> displays the long name. Example:
-
-C<1.2.3.4 shortName A long name>
-
-=head1 EXAMPLES
-
-Parse a file:
-
- openssl asn1parse -in file.pem
-
-Parse a DER file:
-
- openssl asn1parse -inform DER -in file.der
-
-Generate a simple UTF8String:
-
- openssl asn1parse -genstr 'UTF8:Hello World'
-
-Generate and write out a UTF8String, don't print parsed output:
-
- openssl asn1parse -genstr 'UTF8:Hello World' -noout -out utf8.der
-
-Generate using a config file:
-
- openssl asn1parse -genconf asn1.cnf -noout -out asn1.der
-
-Example config file:
-
- asn1=SEQUENCE:seq_sect
-
- [seq_sect]
-
- field1=BOOL:TRUE
- field2=EXP:0, UTF8:some random string
-
-
-=head1 BUGS
-
-There should be options to change the format of output lines. The output of some
-ASN.1 types is not well handled (if at all).
-
-=head1 SEE ALSO
-
-L<ASN1_generate_nconf(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/build.info b/doc/man1/build.info
new file mode 100644
index 000000000000..b796fce42fdd
--- /dev/null
+++ b/doc/man1/build.info
@@ -0,0 +1,57 @@
+# All .pod.in files are detected by build.info in the parent directory, and
+# turned into appropriate DEPEND and GENERATE lines. All we need here are
+# the additional dependencies on ../perlvars.pm.
+
+DEPEND[openssl-asn1parse.pod]=../perlvars.pm
+DEPEND[openssl-ca.pod]=../perlvars.pm
+DEPEND[openssl-ciphers.pod]=../perlvars.pm
+DEPEND[openssl-cmds.pod]=../perlvars.pm
+DEPEND[openssl-cmp.pod]=../perlvars.pm
+DEPEND[openssl-cms.pod]=../perlvars.pm
+DEPEND[openssl-crl2pkcs7.pod]=../perlvars.pm
+DEPEND[openssl-crl.pod]=../perlvars.pm
+DEPEND[openssl-dgst.pod]=../perlvars.pm
+DEPEND[openssl-dhparam.pod]=../perlvars.pm
+DEPEND[openssl-dsaparam.pod]=../perlvars.pm
+DEPEND[openssl-dsa.pod]=../perlvars.pm
+DEPEND[openssl-ecparam.pod]=../perlvars.pm
+DEPEND[openssl-ec.pod]=../perlvars.pm
+DEPEND[openssl-enc.pod]=../perlvars.pm
+DEPEND[openssl-engine.pod]=../perlvars.pm
+DEPEND[openssl-errstr.pod]=../perlvars.pm
+DEPEND[openssl-fipsinstall.pod]=../perlvars.pm
+DEPEND[openssl-gendsa.pod]=../perlvars.pm
+DEPEND[openssl-genpkey.pod]=../perlvars.pm
+DEPEND[openssl-genrsa.pod]=../perlvars.pm
+DEPEND[openssl-info.pod]=../perlvars.pm
+DEPEND[openssl-kdf.pod]=../perlvars.pm
+DEPEND[openssl-list.pod]=../perlvars.pm
+DEPEND[openssl-mac.pod]=../perlvars.pm
+DEPEND[openssl-nseq.pod]=../perlvars.pm
+DEPEND[openssl-ocsp.pod]=../perlvars.pm
+DEPEND[openssl-passwd.pod]=../perlvars.pm
+DEPEND[openssl-pkcs12.pod]=../perlvars.pm
+DEPEND[openssl-pkcs7.pod]=../perlvars.pm
+DEPEND[openssl-pkcs8.pod]=../perlvars.pm
+DEPEND[openssl-pkeyparam.pod]=../perlvars.pm
+DEPEND[openssl-pkey.pod]=../perlvars.pm
+DEPEND[openssl-pkeyutl.pod]=../perlvars.pm
+DEPEND[openssl-prime.pod]=../perlvars.pm
+DEPEND[openssl-rand.pod]=../perlvars.pm
+DEPEND[openssl-rehash.pod]=../perlvars.pm
+DEPEND[openssl-req.pod]=../perlvars.pm
+DEPEND[openssl-rsa.pod]=../perlvars.pm
+DEPEND[openssl-rsautl.pod]=../perlvars.pm
+DEPEND[openssl-s_client.pod]=../perlvars.pm
+DEPEND[openssl-sess_id.pod]=../perlvars.pm
+DEPEND[openssl-smime.pod]=../perlvars.pm
+DEPEND[openssl-speed.pod]=../perlvars.pm
+DEPEND[openssl-spkac.pod]=../perlvars.pm
+DEPEND[openssl-srp.pod]=../perlvars.pm
+DEPEND[openssl-s_server.pod]=../perlvars.pm
+DEPEND[openssl-s_time.pod]=../perlvars.pm
+DEPEND[openssl-storeutl.pod]=../perlvars.pm
+DEPEND[openssl-ts.pod]=../perlvars.pm
+DEPEND[openssl-verify.pod]=../perlvars.pm
+DEPEND[openssl-version.pod]=../perlvars.pm
+DEPEND[openssl-x509.pod]=../perlvars.pm
diff --git a/doc/man1/ca.pod b/doc/man1/ca.pod
deleted file mode 100644
index 4380d869eaa7..000000000000
--- a/doc/man1/ca.pod
+++ /dev/null
@@ -1,769 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-ca,
-ca - sample minimal CA application
-
-=head1 SYNOPSIS
-
-B<openssl> B<ca>
-[B<-help>]
-[B<-verbose>]
-[B<-config filename>]
-[B<-name section>]
-[B<-gencrl>]
-[B<-revoke file>]
-[B<-valid file>]
-[B<-status serial>]
-[B<-updatedb>]
-[B<-crl_reason reason>]
-[B<-crl_hold instruction>]
-[B<-crl_compromise time>]
-[B<-crl_CA_compromise time>]
-[B<-crldays days>]
-[B<-crlhours hours>]
-[B<-crlexts section>]
-[B<-startdate date>]
-[B<-enddate date>]
-[B<-days arg>]
-[B<-md arg>]
-[B<-policy arg>]
-[B<-keyfile arg>]
-[B<-keyform PEM|DER>]
-[B<-key arg>]
-[B<-passin arg>]
-[B<-cert file>]
-[B<-selfsign>]
-[B<-in file>]
-[B<-out file>]
-[B<-notext>]
-[B<-outdir dir>]
-[B<-infiles>]
-[B<-spkac file>]
-[B<-ss_cert file>]
-[B<-preserveDN>]
-[B<-noemailDN>]
-[B<-batch>]
-[B<-msie_hack>]
-[B<-extensions section>]
-[B<-extfile section>]
-[B<-engine id>]
-[B<-subj arg>]
-[B<-utf8>]
-[B<-sigopt nm:v>]
-[B<-create_serial>]
-[B<-rand_serial>]
-[B<-multivalue-rdn>]
-[B<-rand file...>]
-[B<-writerand file>]
-
-=head1 DESCRIPTION
-
-The B<ca> command is a minimal CA application. It can be used
-to sign certificate requests in a variety of forms and generate
-CRLs it also maintains a text database of issued certificates
-and their status.
-
-The options descriptions will be divided into each purpose.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-verbose>
-
-This prints extra details about the operations being performed.
-
-=item B<-config filename>
-
-Specifies the configuration file to use.
-Optional; for a description of the default value,
-see L<openssl(1)/COMMAND SUMMARY>.
-
-=item B<-name section>
-
-Specifies the configuration file section to use (overrides
-B<default_ca> in the B<ca> section).
-
-=item B<-in filename>
-
-An input filename containing a single certificate request to be
-signed by the CA.
-
-=item B<-ss_cert filename>
-
-A single self-signed certificate to be signed by the CA.
-
-=item B<-spkac filename>
-
-A file containing a single Netscape signed public key and challenge
-and additional field values to be signed by the CA. See the B<SPKAC FORMAT>
-section for information on the required input and output format.
-
-=item B<-infiles>
-
-If present this should be the last option, all subsequent arguments
-are taken as the names of files containing certificate requests.
-
-=item B<-out filename>
-
-The output file to output certificates to. The default is standard
-output. The certificate details will also be printed out to this
-file in PEM format (except that B<-spkac> outputs DER format).
-
-=item B<-outdir directory>
-
-The directory to output certificates to. The certificate will be
-written to a filename consisting of the serial number in hex with
-".pem" appended.
-
-=item B<-cert>
-
-The CA certificate file.
-
-=item B<-keyfile filename>
-
-The private key to sign requests with.
-
-=item B<-keyform PEM|DER>
-
-The format of the data in the private key file.
-The default is PEM.
-
-=item B<-sigopt nm:v>
-
-Pass options to the signature algorithm during sign or verify operations.
-Names and values of these options are algorithm-specific.
-
-=item B<-key password>
-
-The password used to encrypt the private key. Since on some
-systems the command line arguments are visible (e.g. Unix with
-the 'ps' utility) this option should be used with caution.
-
-=item B<-selfsign>
-
-Indicates the issued certificates are to be signed with the key
-the certificate requests were signed with (given with B<-keyfile>).
-Certificate requests signed with a different key are ignored. If
-B<-spkac>, B<-ss_cert> or B<-gencrl> are given, B<-selfsign> is
-ignored.
-
-A consequence of using B<-selfsign> is that the self-signed
-certificate appears among the entries in the certificate database
-(see the configuration option B<database>), and uses the same
-serial number counter as all other certificates sign with the
-self-signed certificate.
-
-=item B<-passin arg>
-
-The key password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-notext>
-
-Don't output the text form of a certificate to the output file.
-
-=item B<-startdate date>
-
-This allows the start date to be explicitly set. The format of the
-date is YYMMDDHHMMSSZ (the same as an ASN1 UTCTime structure), or
-YYYYMMDDHHMMSSZ (the same as an ASN1 GeneralizedTime structure). In
-both formats, seconds SS and timezone Z must be present.
-
-=item B<-enddate date>
-
-This allows the expiry date to be explicitly set. The format of the
-date is YYMMDDHHMMSSZ (the same as an ASN1 UTCTime structure), or
-YYYYMMDDHHMMSSZ (the same as an ASN1 GeneralizedTime structure). In
-both formats, seconds SS and timezone Z must be present.
-
-=item B<-days arg>
-
-The number of days to certify the certificate for.
-
-=item B<-md alg>
-
-The message digest to use.
-Any digest supported by the OpenSSL B<dgst> command can be used. For signing
-algorithms that do not support a digest (i.e. Ed25519 and Ed448) any message
-digest that is set is ignored. This option also applies to CRLs.
-
-=item B<-policy arg>
-
-This option defines the CA "policy" to use. This is a section in
-the configuration file which decides which fields should be mandatory
-or match the CA certificate. Check out the B<POLICY FORMAT> section
-for more information.
-
-=item B<-msie_hack>
-
-This is a deprecated option to make B<ca> work with very old versions of
-the IE certificate enrollment control "certenr3". It used UniversalStrings
-for almost everything. Since the old control has various security bugs
-its use is strongly discouraged.
-
-=item B<-preserveDN>
-
-Normally the DN order of a certificate is the same as the order of the
-fields in the relevant policy section. When this option is set the order
-is the same as the request. This is largely for compatibility with the
-older IE enrollment control which would only accept certificates if their
-DNs match the order of the request. This is not needed for Xenroll.
-
-=item B<-noemailDN>
-
-The DN of a certificate can contain the EMAIL field if present in the
-request DN, however, it is good policy just having the e-mail set into
-the altName extension of the certificate. When this option is set the
-EMAIL field is removed from the certificate' subject and set only in
-the, eventually present, extensions. The B<email_in_dn> keyword can be
-used in the configuration file to enable this behaviour.
-
-=item B<-batch>
-
-This sets the batch mode. In this mode no questions will be asked
-and all certificates will be certified automatically.
-
-=item B<-extensions section>
-
-The section of the configuration file containing certificate extensions
-to be added when a certificate is issued (defaults to B<x509_extensions>
-unless the B<-extfile> option is used). If no extension section is
-present then, a V1 certificate is created. If the extension section
-is present (even if it is empty), then a V3 certificate is created. See the
-L<x509v3_config(5)> manual page for details of the
-extension section format.
-
-=item B<-extfile file>
-
-An additional configuration file to read certificate extensions from
-(using the default section unless the B<-extensions> option is also
-used).
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<ca>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=item B<-subj arg>
-
-Supersedes subject name given in the request.
-The arg must be formatted as I</type0=value0/type1=value1/type2=...>.
-Keyword characters may be escaped by \ (backslash), and whitespace is retained.
-Empty values are permitted, but the corresponding type will not be included
-in the resulting certificate.
-
-=item B<-utf8>
-
-This option causes field values to be interpreted as UTF8 strings, by
-default they are interpreted as ASCII. This means that the field
-values, whether prompted from a terminal or obtained from a
-configuration file, must be valid UTF8 strings.
-
-=item B<-create_serial>
-
-If reading serial from the text file as specified in the configuration
-fails, specifying this option creates a new random serial to be used as next
-serial number.
-To get random serial numbers, use the B<-rand_serial> flag instead; this
-should only be used for simple error-recovery.
-
-=item B<-rand_serial>
-
-Generate a large random number to use as the serial number.
-This overrides any option or configuration to use a serial number file.
-
-=item B<-multivalue-rdn>
-
-This option causes the -subj argument to be interpreted with full
-support for multivalued RDNs. Example:
-
-I</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
-
-If -multi-rdn is not used then the UID value is I<123456+CN=John Doe>.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=back
-
-=head1 CRL OPTIONS
-
-=over 4
-
-=item B<-gencrl>
-
-This option generates a CRL based on information in the index file.
-
-=item B<-crldays num>
-
-The number of days before the next CRL is due. That is the days from
-now to place in the CRL nextUpdate field.
-
-=item B<-crlhours num>
-
-The number of hours before the next CRL is due.
-
-=item B<-revoke filename>
-
-A filename containing a certificate to revoke.
-
-=item B<-valid filename>
-
-A filename containing a certificate to add a Valid certificate entry.
-
-=item B<-status serial>
-
-Displays the revocation status of the certificate with the specified
-serial number and exits.
-
-=item B<-updatedb>
-
-Updates the database index to purge expired certificates.
-
-=item B<-crl_reason reason>
-
-Revocation reason, where B<reason> is one of: B<unspecified>, B<keyCompromise>,
-B<CACompromise>, B<affiliationChanged>, B<superseded>, B<cessationOfOperation>,
-B<certificateHold> or B<removeFromCRL>. The matching of B<reason> is case
-insensitive. Setting any revocation reason will make the CRL v2.
-
-In practice B<removeFromCRL> is not particularly useful because it is only used
-in delta CRLs which are not currently implemented.
-
-=item B<-crl_hold instruction>
-
-This sets the CRL revocation reason code to B<certificateHold> and the hold
-instruction to B<instruction> which must be an OID. Although any OID can be
-used only B<holdInstructionNone> (the use of which is discouraged by RFC2459)
-B<holdInstructionCallIssuer> or B<holdInstructionReject> will normally be used.
-
-=item B<-crl_compromise time>
-
-This sets the revocation reason to B<keyCompromise> and the compromise time to
-B<time>. B<time> should be in GeneralizedTime format that is B<YYYYMMDDHHMMSSZ>.
-
-=item B<-crl_CA_compromise time>
-
-This is the same as B<crl_compromise> except the revocation reason is set to
-B<CACompromise>.
-
-=item B<-crlexts section>
-
-The section of the configuration file containing CRL extensions to
-include. If no CRL extension section is present then a V1 CRL is
-created, if the CRL extension section is present (even if it is
-empty) then a V2 CRL is created. The CRL extensions specified are
-CRL extensions and B<not> CRL entry extensions. It should be noted
-that some software (for example Netscape) can't handle V2 CRLs. See
-L<x509v3_config(5)> manual page for details of the
-extension section format.
-
-=back
-
-=head1 CONFIGURATION FILE OPTIONS
-
-The section of the configuration file containing options for B<ca>
-is found as follows: If the B<-name> command line option is used,
-then it names the section to be used. Otherwise the section to
-be used must be named in the B<default_ca> option of the B<ca> section
-of the configuration file (or in the default section of the
-configuration file). Besides B<default_ca>, the following options are
-read directly from the B<ca> section:
- RANDFILE
- preserve
- msie_hack
-With the exception of B<RANDFILE>, this is probably a bug and may
-change in future releases.
-
-Many of the configuration file options are identical to command line
-options. Where the option is present in the configuration file
-and the command line the command line value is used. Where an
-option is described as mandatory then it must be present in
-the configuration file or the command line equivalent (if
-any) used.
-
-=over 4
-
-=item B<oid_file>
-
-This specifies a file containing additional B<OBJECT IDENTIFIERS>.
-Each line of the file should consist of the numerical form of the
-object identifier followed by white space then the short name followed
-by white space and finally the long name.
-
-=item B<oid_section>
-
-This specifies a section in the configuration file containing extra
-object identifiers. Each line should consist of the short name of the
-object identifier followed by B<=> and the numerical form. The short
-and long names are the same when this option is used.
-
-=item B<new_certs_dir>
-
-The same as the B<-outdir> command line option. It specifies
-the directory where new certificates will be placed. Mandatory.
-
-=item B<certificate>
-
-The same as B<-cert>. It gives the file containing the CA
-certificate. Mandatory.
-
-=item B<private_key>
-
-Same as the B<-keyfile> option. The file containing the
-CA private key. Mandatory.
-
-=item B<RANDFILE>
-
-At startup the specified file is loaded into the random number generator,
-and at exit 256 bytes will be written to it.
-
-=item B<default_days>
-
-The same as the B<-days> option. The number of days to certify
-a certificate for.
-
-=item B<default_startdate>
-
-The same as the B<-startdate> option. The start date to certify
-a certificate for. If not set the current time is used.
-
-=item B<default_enddate>
-
-The same as the B<-enddate> option. Either this option or
-B<default_days> (or the command line equivalents) must be
-present.
-
-=item B<default_crl_hours default_crl_days>
-
-The same as the B<-crlhours> and the B<-crldays> options. These
-will only be used if neither command line option is present. At
-least one of these must be present to generate a CRL.
-
-=item B<default_md>
-
-The same as the B<-md> option. Mandatory except where the signing algorithm does
-not require a digest (i.e. Ed25519 and Ed448).
-
-=item B<database>
-
-The text database file to use. Mandatory. This file must be present
-though initially it will be empty.
-
-=item B<unique_subject>
-
-If the value B<yes> is given, the valid certificate entries in the
-database must have unique subjects. if the value B<no> is given,
-several valid certificate entries may have the exact same subject.
-The default value is B<yes>, to be compatible with older (pre 0.9.8)
-versions of OpenSSL. However, to make CA certificate roll-over easier,
-it's recommended to use the value B<no>, especially if combined with
-the B<-selfsign> command line option.
-
-Note that it is valid in some circumstances for certificates to be created
-without any subject. In the case where there are multiple certificates without
-subjects this does not count as a duplicate.
-
-=item B<serial>
-
-A text file containing the next serial number to use in hex. Mandatory.
-This file must be present and contain a valid serial number.
-
-=item B<crlnumber>
-
-A text file containing the next CRL number to use in hex. The crl number
-will be inserted in the CRLs only if this file exists. If this file is
-present, it must contain a valid CRL number.
-
-=item B<x509_extensions>
-
-The same as B<-extensions>.
-
-=item B<crl_extensions>
-
-The same as B<-crlexts>.
-
-=item B<preserve>
-
-The same as B<-preserveDN>
-
-=item B<email_in_dn>
-
-The same as B<-noemailDN>. If you want the EMAIL field to be removed
-from the DN of the certificate simply set this to 'no'. If not present
-the default is to allow for the EMAIL filed in the certificate's DN.
-
-=item B<msie_hack>
-
-The same as B<-msie_hack>
-
-=item B<policy>
-
-The same as B<-policy>. Mandatory. See the B<POLICY FORMAT> section
-for more information.
-
-=item B<name_opt>, B<cert_opt>
-
-These options allow the format used to display the certificate details
-when asking the user to confirm signing. All the options supported by
-the B<x509> utilities B<-nameopt> and B<-certopt> switches can be used
-here, except the B<no_signame> and B<no_sigdump> are permanently set
-and cannot be disabled (this is because the certificate signature cannot
-be displayed because the certificate has not been signed at this point).
-
-For convenience the values B<ca_default> are accepted by both to produce
-a reasonable output.
-
-If neither option is present the format used in earlier versions of
-OpenSSL is used. Use of the old format is B<strongly> discouraged because
-it only displays fields mentioned in the B<policy> section, mishandles
-multicharacter string types and does not display extensions.
-
-=item B<copy_extensions>
-
-Determines how extensions in certificate requests should be handled.
-If set to B<none> or this option is not present then extensions are
-ignored and not copied to the certificate. If set to B<copy> then any
-extensions present in the request that are not already present are copied
-to the certificate. If set to B<copyall> then all extensions in the
-request are copied to the certificate: if the extension is already present
-in the certificate it is deleted first. See the B<WARNINGS> section before
-using this option.
-
-The main use of this option is to allow a certificate request to supply
-values for certain extensions such as subjectAltName.
-
-=back
-
-=head1 POLICY FORMAT
-
-The policy section consists of a set of variables corresponding to
-certificate DN fields. If the value is "match" then the field value
-must match the same field in the CA certificate. If the value is
-"supplied" then it must be present. If the value is "optional" then
-it may be present. Any fields not mentioned in the policy section
-are silently deleted, unless the B<-preserveDN> option is set but
-this can be regarded more of a quirk than intended behaviour.
-
-=head1 SPKAC FORMAT
-
-The input to the B<-spkac> command line option is a Netscape
-signed public key and challenge. This will usually come from
-the B<KEYGEN> tag in an HTML form to create a new private key.
-It is however possible to create SPKACs using the B<spkac> utility.
-
-The file should contain the variable SPKAC set to the value of
-the SPKAC and also the required DN components as name value pairs.
-If you need to include the same component twice then it can be
-preceded by a number and a '.'.
-
-When processing SPKAC format, the output is DER if the B<-out>
-flag is used, but PEM format if sending to stdout or the B<-outdir>
-flag is used.
-
-=head1 EXAMPLES
-
-Note: these examples assume that the B<ca> directory structure is
-already set up and the relevant files already exist. This usually
-involves creating a CA certificate and private key with B<req>, a
-serial number file and an empty index file and placing them in
-the relevant directories.
-
-To use the sample configuration file below the directories demoCA,
-demoCA/private and demoCA/newcerts would be created. The CA
-certificate would be copied to demoCA/cacert.pem and its private
-key to demoCA/private/cakey.pem. A file demoCA/serial would be
-created containing for example "01" and the empty index file
-demoCA/index.txt.
-
-
-Sign a certificate request:
-
- openssl ca -in req.pem -out newcert.pem
-
-Sign a certificate request, using CA extensions:
-
- openssl ca -in req.pem -extensions v3_ca -out newcert.pem
-
-Generate a CRL
-
- openssl ca -gencrl -out crl.pem
-
-Sign several requests:
-
- openssl ca -infiles req1.pem req2.pem req3.pem
-
-Certify a Netscape SPKAC:
-
- openssl ca -spkac spkac.txt
-
-A sample SPKAC file (the SPKAC line has been truncated for clarity):
-
- SPKAC=MIG0MGAwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAn7PDhCeV/xIxUg8V70YRxK2A5
- CN=Steve Test
- emailAddress=steve@openssl.org
- 0.OU=OpenSSL Group
- 1.OU=Another Group
-
-A sample configuration file with the relevant sections for B<ca>:
-
- [ ca ]
- default_ca = CA_default # The default ca section
-
- [ CA_default ]
-
- dir = ./demoCA # top dir
- database = $dir/index.txt # index file.
- new_certs_dir = $dir/newcerts # new certs dir
-
- certificate = $dir/cacert.pem # The CA cert
- serial = $dir/serial # serial no file
- #rand_serial = yes # for random serial#'s
- private_key = $dir/private/cakey.pem# CA private key
- RANDFILE = $dir/private/.rand # random number file
-
- default_days = 365 # how long to certify for
- default_crl_days= 30 # how long before next CRL
- default_md = md5 # md to use
-
- policy = policy_any # default policy
- email_in_dn = no # Don't add the email into cert DN
-
- name_opt = ca_default # Subject name display option
- cert_opt = ca_default # Certificate display option
- copy_extensions = none # Don't copy extensions from request
-
- [ policy_any ]
- countryName = supplied
- stateOrProvinceName = optional
- organizationName = optional
- organizationalUnitName = optional
- commonName = supplied
- emailAddress = optional
-
-=head1 FILES
-
-Note: the location of all files can change either by compile time options,
-configuration file entries, environment variables or command line options.
-The values below reflect the default values.
-
- /usr/local/ssl/lib/openssl.cnf - master configuration file
- ./demoCA - main CA directory
- ./demoCA/cacert.pem - CA certificate
- ./demoCA/private/cakey.pem - CA private key
- ./demoCA/serial - CA serial number file
- ./demoCA/serial.old - CA serial number backup file
- ./demoCA/index.txt - CA text database file
- ./demoCA/index.txt.old - CA text database backup file
- ./demoCA/certs - certificate output file
- ./demoCA/.rnd - CA random seed information
-
-=head1 RESTRICTIONS
-
-The text database index file is a critical part of the process and
-if corrupted it can be difficult to fix. It is theoretically possible
-to rebuild the index file from all the issued certificates and a current
-CRL: however there is no option to do this.
-
-V2 CRL features like delta CRLs are not currently supported.
-
-Although several requests can be input and handled at once it is only
-possible to include one SPKAC or self-signed certificate.
-
-=head1 BUGS
-
-The use of an in-memory text database can cause problems when large
-numbers of certificates are present because, as the name implies
-the database has to be kept in memory.
-
-The B<ca> command really needs rewriting or the required functionality
-exposed at either a command or interface level so a more friendly utility
-(perl script or GUI) can handle things properly. The script
-B<CA.pl> helps a little but not very much.
-
-Any fields in a request that are not present in a policy are silently
-deleted. This does not happen if the B<-preserveDN> option is used. To
-enforce the absence of the EMAIL field within the DN, as suggested by
-RFCs, regardless the contents of the request' subject the B<-noemailDN>
-option can be used. The behaviour should be more friendly and
-configurable.
-
-Canceling some commands by refusing to certify a certificate can
-create an empty file.
-
-=head1 WARNINGS
-
-The B<ca> command is quirky and at times downright unfriendly.
-
-The B<ca> utility was originally meant as an example of how to do things
-in a CA. It was not supposed to be used as a full blown CA itself:
-nevertheless some people are using it for this purpose.
-
-The B<ca> command is effectively a single user command: no locking is
-done on the various files and attempts to run more than one B<ca> command
-on the same database can have unpredictable results.
-
-The B<copy_extensions> option should be used with caution. If care is
-not taken then it can be a security risk. For example if a certificate
-request contains a basicConstraints extension with CA:TRUE and the
-B<copy_extensions> value is set to B<copyall> and the user does not spot
-this when the certificate is displayed then this will hand the requester
-a valid CA certificate.
-
-This situation can be avoided by setting B<copy_extensions> to B<copy>
-and including basicConstraints with CA:FALSE in the configuration file.
-Then if the request contains a basicConstraints extension it will be
-ignored.
-
-It is advisable to also include values for other extensions such
-as B<keyUsage> to prevent a request supplying its own values.
-
-Additional restrictions can be placed on the CA certificate itself.
-For example if the CA certificate has:
-
- basicConstraints = CA:TRUE, pathlen:0
-
-then even if a certificate is issued with CA:TRUE it will not be valid.
-
-=head1 HISTORY
-
-Since OpenSSL 1.1.1, the program follows RFC5280. Specifically,
-certificate validity period (specified by any of B<-startdate>,
-B<-enddate> and B<-days>) will be encoded as UTCTime if the dates are
-earlier than year 2049 (included), and as GeneralizedTime if the dates
-are in year 2050 or later.
-
-=head1 SEE ALSO
-
-L<req(1)>, L<spkac(1)>, L<x509(1)>, L<CA.pl(1)>,
-L<config(5)>, L<x509v3_config(5)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/ciphers.pod b/doc/man1/ciphers.pod
deleted file mode 100644
index faf9e538146a..000000000000
--- a/doc/man1/ciphers.pod
+++ /dev/null
@@ -1,776 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-ciphers,
-ciphers - SSL cipher display and cipher list tool
-
-=head1 SYNOPSIS
-
-B<openssl> B<ciphers>
-[B<-help>]
-[B<-s>]
-[B<-v>]
-[B<-V>]
-[B<-ssl3>]
-[B<-tls1>]
-[B<-tls1_1>]
-[B<-tls1_2>]
-[B<-tls1_3>]
-[B<-s>]
-[B<-psk>]
-[B<-srp>]
-[B<-stdname>]
-[B<-convert name>]
-[B<-ciphersuites val>]
-[B<cipherlist>]
-
-=head1 DESCRIPTION
-
-The B<ciphers> command converts textual OpenSSL cipher lists into ordered
-SSL cipher preference lists. It can be used as a test tool to determine
-the appropriate cipherlist.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print a usage message.
-
-=item B<-s>
-
-Only list supported ciphers: those consistent with the security level, and
-minimum and maximum protocol version. This is closer to the actual cipher list
-an application will support.
-
-PSK and SRP ciphers are not enabled by default: they require B<-psk> or B<-srp>
-to enable them.
-
-It also does not change the default list of supported signature algorithms.
-
-On a server the list of supported ciphers might also exclude other ciphers
-depending on the configured certificates and presence of DH parameters.
-
-If this option is not used then all ciphers that match the cipherlist will be
-listed.
-
-=item B<-psk>
-
-When combined with B<-s> includes cipher suites which require PSK.
-
-=item B<-srp>
-
-When combined with B<-s> includes cipher suites which require SRP.
-
-=item B<-v>
-
-Verbose output: For each cipher suite, list details as provided by
-L<SSL_CIPHER_description(3)>.
-
-=item B<-V>
-
-Like B<-v>, but include the official cipher suite values in hex.
-
-=item B<-tls1_3>, B<-tls1_2>, B<-tls1_1>, B<-tls1>, B<-ssl3>
-
-In combination with the B<-s> option, list the ciphers which could be used if
-the specified protocol were negotiated.
-Note that not all protocols and flags may be available, depending on how
-OpenSSL was built.
-
-=item B<-stdname>
-
-Precede each cipher suite by its standard name.
-
-=item B<-convert name>
-
-Convert a standard cipher B<name> to its OpenSSL name.
-
-=item B<-ciphersuites val>
-
-Sets the list of TLSv1.3 ciphersuites. This list will be combined with any
-TLSv1.2 and below ciphersuites that have been configured. The format for this
-list is a simple colon (":") separated list of TLSv1.3 ciphersuite names. By
-default this value is:
-
- TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
-
-=item B<cipherlist>
-
-A cipher list of TLSv1.2 and below ciphersuites to convert to a cipher
-preference list. This list will be combined with any TLSv1.3 ciphersuites that
-have been configured. If it is not included then the default cipher list will be
-used. The format is described below.
-
-=back
-
-=head1 CIPHER LIST FORMAT
-
-The cipher list consists of one or more I<cipher strings> separated by colons.
-Commas or spaces are also acceptable separators but colons are normally used.
-
-The actual cipher string can take several different forms.
-
-It can consist of a single cipher suite such as B<RC4-SHA>.
-
-It can represent a list of cipher suites containing a certain algorithm, or
-cipher suites of a certain type. For example B<SHA1> represents all ciphers
-suites using the digest algorithm SHA1 and B<SSLv3> represents all SSL v3
-algorithms.
-
-Lists of cipher suites can be combined in a single cipher string using the
-B<+> character. This is used as a logical B<and> operation. For example
-B<SHA1+DES> represents all cipher suites containing the SHA1 B<and> the DES
-algorithms.
-
-Each cipher string can be optionally preceded by the characters B<!>,
-B<-> or B<+>.
-
-If B<!> is used then the ciphers are permanently deleted from the list.
-The ciphers deleted can never reappear in the list even if they are
-explicitly stated.
-
-If B<-> is used then the ciphers are deleted from the list, but some or
-all of the ciphers can be added again by later options.
-
-If B<+> is used then the ciphers are moved to the end of the list. This
-option doesn't add any new ciphers it just moves matching existing ones.
-
-If none of these characters is present then the string is just interpreted
-as a list of ciphers to be appended to the current preference list. If the
-list includes any ciphers already present they will be ignored: that is they
-will not moved to the end of the list.
-
-The cipher string B<@STRENGTH> can be used at any point to sort the current
-cipher list in order of encryption algorithm key length.
-
-The cipher string B<@SECLEVEL=n> can be used at any point to set the security
-level to B<n>, which should be a number between zero and five, inclusive.
-See L<SSL_CTX_set_security_level> for a description of what each level means.
-
-The cipher list can be prefixed with the B<DEFAULT> keyword, which enables
-the default cipher list as defined below. Unlike cipher strings,
-this prefix may not be combined with other strings using B<+> character.
-For example, B<DEFAULT+DES> is not valid.
-
-The content of the default list is determined at compile time and normally
-corresponds to B<ALL:!COMPLEMENTOFDEFAULT:!eNULL>.
-
-=head1 CIPHER STRINGS
-
-The following is a list of all permitted cipher strings and their meanings.
-
-=over 4
-
-=item B<COMPLEMENTOFDEFAULT>
-
-The ciphers included in B<ALL>, but not enabled by default. Currently
-this includes all RC4 and anonymous ciphers. Note that this rule does
-not cover B<eNULL>, which is not included by B<ALL> (use B<COMPLEMENTOFALL> if
-necessary). Note that RC4 based cipher suites are not built into OpenSSL by
-default (see the enable-weak-ssl-ciphers option to Configure).
-
-=item B<ALL>
-
-All cipher suites except the B<eNULL> ciphers (which must be explicitly enabled
-if needed).
-As of OpenSSL 1.0.0, the B<ALL> cipher suites are sensibly ordered by default.
-
-=item B<COMPLEMENTOFALL>
-
-The cipher suites not enabled by B<ALL>, currently B<eNULL>.
-
-=item B<HIGH>
-
-"High" encryption cipher suites. This currently means those with key lengths
-larger than 128 bits, and some cipher suites with 128-bit keys.
-
-=item B<MEDIUM>
-
-"Medium" encryption cipher suites, currently some of those using 128 bit
-encryption.
-
-=item B<LOW>
-
-"Low" encryption cipher suites, currently those using 64 or 56 bit
-encryption algorithms but excluding export cipher suites. All these
-cipher suites have been removed as of OpenSSL 1.1.0.
-
-=item B<eNULL>, B<NULL>
-
-The "NULL" ciphers that is those offering no encryption. Because these offer no
-encryption at all and are a security risk they are not enabled via either the
-B<DEFAULT> or B<ALL> cipher strings.
-Be careful when building cipherlists out of lower-level primitives such as
-B<kRSA> or B<aECDSA> as these do overlap with the B<eNULL> ciphers. When in
-doubt, include B<!eNULL> in your cipherlist.
-
-=item B<aNULL>
-
-The cipher suites offering no authentication. This is currently the anonymous
-DH algorithms and anonymous ECDH algorithms. These cipher suites are vulnerable
-to "man in the middle" attacks and so their use is discouraged.
-These are excluded from the B<DEFAULT> ciphers, but included in the B<ALL>
-ciphers.
-Be careful when building cipherlists out of lower-level primitives such as
-B<kDHE> or B<AES> as these do overlap with the B<aNULL> ciphers.
-When in doubt, include B<!aNULL> in your cipherlist.
-
-=item B<kRSA>, B<aRSA>, B<RSA>
-
-Cipher suites using RSA key exchange or authentication. B<RSA> is an alias for
-B<kRSA>.
-
-=item B<kDHr>, B<kDHd>, B<kDH>
-
-Cipher suites using static DH key agreement and DH certificates signed by CAs
-with RSA and DSS keys or either respectively.
-All these cipher suites have been removed in OpenSSL 1.1.0.
-
-=item B<kDHE>, B<kEDH>, B<DH>
-
-Cipher suites using ephemeral DH key agreement, including anonymous cipher
-suites.
-
-=item B<DHE>, B<EDH>
-
-Cipher suites using authenticated ephemeral DH key agreement.
-
-=item B<ADH>
-
-Anonymous DH cipher suites, note that this does not include anonymous Elliptic
-Curve DH (ECDH) cipher suites.
-
-=item B<kEECDH>, B<kECDHE>, B<ECDH>
-
-Cipher suites using ephemeral ECDH key agreement, including anonymous
-cipher suites.
-
-=item B<ECDHE>, B<EECDH>
-
-Cipher suites using authenticated ephemeral ECDH key agreement.
-
-=item B<AECDH>
-
-Anonymous Elliptic Curve Diffie-Hellman cipher suites.
-
-=item B<aDSS>, B<DSS>
-
-Cipher suites using DSS authentication, i.e. the certificates carry DSS keys.
-
-=item B<aDH>
-
-Cipher suites effectively using DH authentication, i.e. the certificates carry
-DH keys.
-All these cipher suites have been removed in OpenSSL 1.1.0.
-
-=item B<aECDSA>, B<ECDSA>
-
-Cipher suites using ECDSA authentication, i.e. the certificates carry ECDSA
-keys.
-
-=item B<TLSv1.2>, B<TLSv1.0>, B<SSLv3>
-
-Lists cipher suites which are only supported in at least TLS v1.2, TLS v1.0 or
-SSL v3.0 respectively.
-Note: there are no cipher suites specific to TLS v1.1.
-Since this is only the minimum version, if, for example, TLSv1.0 is negotiated
-then both TLSv1.0 and SSLv3.0 cipher suites are available.
-
-Note: these cipher strings B<do not> change the negotiated version of SSL or
-TLS, they only affect the list of available cipher suites.
-
-=item B<AES128>, B<AES256>, B<AES>
-
-cipher suites using 128 bit AES, 256 bit AES or either 128 or 256 bit AES.
-
-=item B<AESGCM>
-
-AES in Galois Counter Mode (GCM): these cipher suites are only supported
-in TLS v1.2.
-
-=item B<AESCCM>, B<AESCCM8>
-
-AES in Cipher Block Chaining - Message Authentication Mode (CCM): these
-cipher suites are only supported in TLS v1.2. B<AESCCM> references CCM
-cipher suites using both 16 and 8 octet Integrity Check Value (ICV)
-while B<AESCCM8> only references 8 octet ICV.
-
-=item B<ARIA128>, B<ARIA256>, B<ARIA>
-
-Cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit
-ARIA.
-
-=item B<CAMELLIA128>, B<CAMELLIA256>, B<CAMELLIA>
-
-Cipher suites using 128 bit CAMELLIA, 256 bit CAMELLIA or either 128 or 256 bit
-CAMELLIA.
-
-=item B<CHACHA20>
-
-Cipher suites using ChaCha20.
-
-=item B<3DES>
-
-Cipher suites using triple DES.
-
-=item B<DES>
-
-Cipher suites using DES (not triple DES).
-All these cipher suites have been removed in OpenSSL 1.1.0.
-
-=item B<RC4>
-
-Cipher suites using RC4.
-
-=item B<RC2>
-
-Cipher suites using RC2.
-
-=item B<IDEA>
-
-Cipher suites using IDEA.
-
-=item B<SEED>
-
-Cipher suites using SEED.
-
-=item B<MD5>
-
-Cipher suites using MD5.
-
-=item B<SHA1>, B<SHA>
-
-Cipher suites using SHA1.
-
-=item B<SHA256>, B<SHA384>
-
-Cipher suites using SHA256 or SHA384.
-
-=item B<aGOST>
-
-Cipher suites using GOST R 34.10 (either 2001 or 94) for authentication
-(needs an engine supporting GOST algorithms).
-
-=item B<aGOST01>
-
-Cipher suites using GOST R 34.10-2001 authentication.
-
-=item B<kGOST>
-
-Cipher suites, using VKO 34.10 key exchange, specified in the RFC 4357.
-
-=item B<GOST94>
-
-Cipher suites, using HMAC based on GOST R 34.11-94.
-
-=item B<GOST89MAC>
-
-Cipher suites using GOST 28147-89 MAC B<instead of> HMAC.
-
-=item B<PSK>
-
-All cipher suites using pre-shared keys (PSK).
-
-=item B<kPSK>, B<kECDHEPSK>, B<kDHEPSK>, B<kRSAPSK>
-
-Cipher suites using PSK key exchange, ECDHE_PSK, DHE_PSK or RSA_PSK.
-
-=item B<aPSK>
-
-Cipher suites using PSK authentication (currently all PSK modes apart from
-RSA_PSK).
-
-=item B<SUITEB128>, B<SUITEB128ONLY>, B<SUITEB192>
-
-Enables suite B mode of operation using 128 (permitting 192 bit mode by peer)
-128 bit (not permitting 192 bit by peer) or 192 bit level of security
-respectively.
-If used these cipherstrings should appear first in the cipher
-list and anything after them is ignored.
-Setting Suite B mode has additional consequences required to comply with
-RFC6460.
-In particular the supported signature algorithms is reduced to support only
-ECDSA and SHA256 or SHA384, only the elliptic curves P-256 and P-384 can be
-used and only the two suite B compliant cipher suites
-(ECDHE-ECDSA-AES128-GCM-SHA256 and ECDHE-ECDSA-AES256-GCM-SHA384) are
-permissible.
-
-=back
-
-=head1 CIPHER SUITE NAMES
-
-The following lists give the SSL or TLS cipher suites names from the
-relevant specification and their OpenSSL equivalents. It should be noted,
-that several cipher suite names do not include the authentication used,
-e.g. DES-CBC3-SHA. In these cases, RSA authentication is used.
-
-=head2 SSL v3.0 cipher suites
-
- SSL_RSA_WITH_NULL_MD5 NULL-MD5
- SSL_RSA_WITH_NULL_SHA NULL-SHA
- SSL_RSA_WITH_RC4_128_MD5 RC4-MD5
- SSL_RSA_WITH_RC4_128_SHA RC4-SHA
- SSL_RSA_WITH_IDEA_CBC_SHA IDEA-CBC-SHA
- SSL_RSA_WITH_3DES_EDE_CBC_SHA DES-CBC3-SHA
-
- SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA DH-DSS-DES-CBC3-SHA
- SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA DH-RSA-DES-CBC3-SHA
- SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA DHE-DSS-DES-CBC3-SHA
- SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA DHE-RSA-DES-CBC3-SHA
-
- SSL_DH_anon_WITH_RC4_128_MD5 ADH-RC4-MD5
- SSL_DH_anon_WITH_3DES_EDE_CBC_SHA ADH-DES-CBC3-SHA
-
- SSL_FORTEZZA_KEA_WITH_NULL_SHA Not implemented.
- SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA Not implemented.
- SSL_FORTEZZA_KEA_WITH_RC4_128_SHA Not implemented.
-
-=head2 TLS v1.0 cipher suites
-
- TLS_RSA_WITH_NULL_MD5 NULL-MD5
- TLS_RSA_WITH_NULL_SHA NULL-SHA
- TLS_RSA_WITH_RC4_128_MD5 RC4-MD5
- TLS_RSA_WITH_RC4_128_SHA RC4-SHA
- TLS_RSA_WITH_IDEA_CBC_SHA IDEA-CBC-SHA
- TLS_RSA_WITH_3DES_EDE_CBC_SHA DES-CBC3-SHA
-
- TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA Not implemented.
- TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA Not implemented.
- TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA DHE-DSS-DES-CBC3-SHA
- TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA DHE-RSA-DES-CBC3-SHA
-
- TLS_DH_anon_WITH_RC4_128_MD5 ADH-RC4-MD5
- TLS_DH_anon_WITH_3DES_EDE_CBC_SHA ADH-DES-CBC3-SHA
-
-=head2 AES cipher suites from RFC3268, extending TLS v1.0
-
- TLS_RSA_WITH_AES_128_CBC_SHA AES128-SHA
- TLS_RSA_WITH_AES_256_CBC_SHA AES256-SHA
-
- TLS_DH_DSS_WITH_AES_128_CBC_SHA DH-DSS-AES128-SHA
- TLS_DH_DSS_WITH_AES_256_CBC_SHA DH-DSS-AES256-SHA
- TLS_DH_RSA_WITH_AES_128_CBC_SHA DH-RSA-AES128-SHA
- TLS_DH_RSA_WITH_AES_256_CBC_SHA DH-RSA-AES256-SHA
-
- TLS_DHE_DSS_WITH_AES_128_CBC_SHA DHE-DSS-AES128-SHA
- TLS_DHE_DSS_WITH_AES_256_CBC_SHA DHE-DSS-AES256-SHA
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA DHE-RSA-AES128-SHA
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA DHE-RSA-AES256-SHA
-
- TLS_DH_anon_WITH_AES_128_CBC_SHA ADH-AES128-SHA
- TLS_DH_anon_WITH_AES_256_CBC_SHA ADH-AES256-SHA
-
-=head2 Camellia cipher suites from RFC4132, extending TLS v1.0
-
- TLS_RSA_WITH_CAMELLIA_128_CBC_SHA CAMELLIA128-SHA
- TLS_RSA_WITH_CAMELLIA_256_CBC_SHA CAMELLIA256-SHA
-
- TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA DH-DSS-CAMELLIA128-SHA
- TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA DH-DSS-CAMELLIA256-SHA
- TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA DH-RSA-CAMELLIA128-SHA
- TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA DH-RSA-CAMELLIA256-SHA
-
- TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA DHE-DSS-CAMELLIA128-SHA
- TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA DHE-DSS-CAMELLIA256-SHA
- TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA DHE-RSA-CAMELLIA128-SHA
- TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA DHE-RSA-CAMELLIA256-SHA
-
- TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA ADH-CAMELLIA128-SHA
- TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA ADH-CAMELLIA256-SHA
-
-=head2 SEED cipher suites from RFC4162, extending TLS v1.0
-
- TLS_RSA_WITH_SEED_CBC_SHA SEED-SHA
-
- TLS_DH_DSS_WITH_SEED_CBC_SHA DH-DSS-SEED-SHA
- TLS_DH_RSA_WITH_SEED_CBC_SHA DH-RSA-SEED-SHA
-
- TLS_DHE_DSS_WITH_SEED_CBC_SHA DHE-DSS-SEED-SHA
- TLS_DHE_RSA_WITH_SEED_CBC_SHA DHE-RSA-SEED-SHA
-
- TLS_DH_anon_WITH_SEED_CBC_SHA ADH-SEED-SHA
-
-=head2 GOST cipher suites from draft-chudov-cryptopro-cptls, extending TLS v1.0
-
-Note: these ciphers require an engine which including GOST cryptographic
-algorithms, such as the B<ccgost> engine, included in the OpenSSL distribution.
-
- TLS_GOSTR341094_WITH_28147_CNT_IMIT GOST94-GOST89-GOST89
- TLS_GOSTR341001_WITH_28147_CNT_IMIT GOST2001-GOST89-GOST89
- TLS_GOSTR341094_WITH_NULL_GOSTR3411 GOST94-NULL-GOST94
- TLS_GOSTR341001_WITH_NULL_GOSTR3411 GOST2001-NULL-GOST94
-
-=head2 Additional Export 1024 and other cipher suites
-
-Note: these ciphers can also be used in SSL v3.
-
- TLS_DHE_DSS_WITH_RC4_128_SHA DHE-DSS-RC4-SHA
-
-=head2 Elliptic curve cipher suites.
-
- TLS_ECDHE_RSA_WITH_NULL_SHA ECDHE-RSA-NULL-SHA
- TLS_ECDHE_RSA_WITH_RC4_128_SHA ECDHE-RSA-RC4-SHA
- TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA ECDHE-RSA-DES-CBC3-SHA
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA ECDHE-RSA-AES128-SHA
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA ECDHE-RSA-AES256-SHA
-
- TLS_ECDHE_ECDSA_WITH_NULL_SHA ECDHE-ECDSA-NULL-SHA
- TLS_ECDHE_ECDSA_WITH_RC4_128_SHA ECDHE-ECDSA-RC4-SHA
- TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA ECDHE-ECDSA-DES-CBC3-SHA
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA ECDHE-ECDSA-AES128-SHA
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA ECDHE-ECDSA-AES256-SHA
-
- TLS_ECDH_anon_WITH_NULL_SHA AECDH-NULL-SHA
- TLS_ECDH_anon_WITH_RC4_128_SHA AECDH-RC4-SHA
- TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA AECDH-DES-CBC3-SHA
- TLS_ECDH_anon_WITH_AES_128_CBC_SHA AECDH-AES128-SHA
- TLS_ECDH_anon_WITH_AES_256_CBC_SHA AECDH-AES256-SHA
-
-=head2 TLS v1.2 cipher suites
-
- TLS_RSA_WITH_NULL_SHA256 NULL-SHA256
-
- TLS_RSA_WITH_AES_128_CBC_SHA256 AES128-SHA256
- TLS_RSA_WITH_AES_256_CBC_SHA256 AES256-SHA256
- TLS_RSA_WITH_AES_128_GCM_SHA256 AES128-GCM-SHA256
- TLS_RSA_WITH_AES_256_GCM_SHA384 AES256-GCM-SHA384
-
- TLS_DH_RSA_WITH_AES_128_CBC_SHA256 DH-RSA-AES128-SHA256
- TLS_DH_RSA_WITH_AES_256_CBC_SHA256 DH-RSA-AES256-SHA256
- TLS_DH_RSA_WITH_AES_128_GCM_SHA256 DH-RSA-AES128-GCM-SHA256
- TLS_DH_RSA_WITH_AES_256_GCM_SHA384 DH-RSA-AES256-GCM-SHA384
-
- TLS_DH_DSS_WITH_AES_128_CBC_SHA256 DH-DSS-AES128-SHA256
- TLS_DH_DSS_WITH_AES_256_CBC_SHA256 DH-DSS-AES256-SHA256
- TLS_DH_DSS_WITH_AES_128_GCM_SHA256 DH-DSS-AES128-GCM-SHA256
- TLS_DH_DSS_WITH_AES_256_GCM_SHA384 DH-DSS-AES256-GCM-SHA384
-
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 DHE-RSA-AES128-SHA256
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 DHE-RSA-AES256-SHA256
- TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 DHE-RSA-AES128-GCM-SHA256
- TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 DHE-RSA-AES256-GCM-SHA384
-
- TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 DHE-DSS-AES128-SHA256
- TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 DHE-DSS-AES256-SHA256
- TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 DHE-DSS-AES128-GCM-SHA256
- TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 DHE-DSS-AES256-GCM-SHA384
-
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 ECDHE-RSA-AES128-SHA256
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 ECDHE-RSA-AES256-SHA384
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ECDHE-RSA-AES128-GCM-SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ECDHE-RSA-AES256-GCM-SHA384
-
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 ECDHE-ECDSA-AES128-SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 ECDHE-ECDSA-AES256-SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ECDHE-ECDSA-AES128-GCM-SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ECDHE-ECDSA-AES256-GCM-SHA384
-
- TLS_DH_anon_WITH_AES_128_CBC_SHA256 ADH-AES128-SHA256
- TLS_DH_anon_WITH_AES_256_CBC_SHA256 ADH-AES256-SHA256
- TLS_DH_anon_WITH_AES_128_GCM_SHA256 ADH-AES128-GCM-SHA256
- TLS_DH_anon_WITH_AES_256_GCM_SHA384 ADH-AES256-GCM-SHA384
-
- RSA_WITH_AES_128_CCM AES128-CCM
- RSA_WITH_AES_256_CCM AES256-CCM
- DHE_RSA_WITH_AES_128_CCM DHE-RSA-AES128-CCM
- DHE_RSA_WITH_AES_256_CCM DHE-RSA-AES256-CCM
- RSA_WITH_AES_128_CCM_8 AES128-CCM8
- RSA_WITH_AES_256_CCM_8 AES256-CCM8
- DHE_RSA_WITH_AES_128_CCM_8 DHE-RSA-AES128-CCM8
- DHE_RSA_WITH_AES_256_CCM_8 DHE-RSA-AES256-CCM8
- ECDHE_ECDSA_WITH_AES_128_CCM ECDHE-ECDSA-AES128-CCM
- ECDHE_ECDSA_WITH_AES_256_CCM ECDHE-ECDSA-AES256-CCM
- ECDHE_ECDSA_WITH_AES_128_CCM_8 ECDHE-ECDSA-AES128-CCM8
- ECDHE_ECDSA_WITH_AES_256_CCM_8 ECDHE-ECDSA-AES256-CCM8
-
-=head2 ARIA cipher suites from RFC6209, extending TLS v1.2
-
-Note: the CBC modes mentioned in this RFC are not supported.
-
- TLS_RSA_WITH_ARIA_128_GCM_SHA256 ARIA128-GCM-SHA256
- TLS_RSA_WITH_ARIA_256_GCM_SHA384 ARIA256-GCM-SHA384
- TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 DHE-RSA-ARIA128-GCM-SHA256
- TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 DHE-RSA-ARIA256-GCM-SHA384
- TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 DHE-DSS-ARIA128-GCM-SHA256
- TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 DHE-DSS-ARIA256-GCM-SHA384
- TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 ECDHE-ECDSA-ARIA128-GCM-SHA256
- TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 ECDHE-ECDSA-ARIA256-GCM-SHA384
- TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 ECDHE-ARIA128-GCM-SHA256
- TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 ECDHE-ARIA256-GCM-SHA384
- TLS_PSK_WITH_ARIA_128_GCM_SHA256 PSK-ARIA128-GCM-SHA256
- TLS_PSK_WITH_ARIA_256_GCM_SHA384 PSK-ARIA256-GCM-SHA384
- TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 DHE-PSK-ARIA128-GCM-SHA256
- TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 DHE-PSK-ARIA256-GCM-SHA384
- TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 RSA-PSK-ARIA128-GCM-SHA256
- TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 RSA-PSK-ARIA256-GCM-SHA384
-
-=head2 Camellia HMAC-Based cipher suites from RFC6367, extending TLS v1.2
-
- TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 ECDHE-ECDSA-CAMELLIA128-SHA256
- TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 ECDHE-ECDSA-CAMELLIA256-SHA384
- TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 ECDHE-RSA-CAMELLIA128-SHA256
- TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 ECDHE-RSA-CAMELLIA256-SHA384
-
-=head2 Pre-shared keying (PSK) cipher suites
-
- PSK_WITH_NULL_SHA PSK-NULL-SHA
- DHE_PSK_WITH_NULL_SHA DHE-PSK-NULL-SHA
- RSA_PSK_WITH_NULL_SHA RSA-PSK-NULL-SHA
-
- PSK_WITH_RC4_128_SHA PSK-RC4-SHA
- PSK_WITH_3DES_EDE_CBC_SHA PSK-3DES-EDE-CBC-SHA
- PSK_WITH_AES_128_CBC_SHA PSK-AES128-CBC-SHA
- PSK_WITH_AES_256_CBC_SHA PSK-AES256-CBC-SHA
-
- DHE_PSK_WITH_RC4_128_SHA DHE-PSK-RC4-SHA
- DHE_PSK_WITH_3DES_EDE_CBC_SHA DHE-PSK-3DES-EDE-CBC-SHA
- DHE_PSK_WITH_AES_128_CBC_SHA DHE-PSK-AES128-CBC-SHA
- DHE_PSK_WITH_AES_256_CBC_SHA DHE-PSK-AES256-CBC-SHA
-
- RSA_PSK_WITH_RC4_128_SHA RSA-PSK-RC4-SHA
- RSA_PSK_WITH_3DES_EDE_CBC_SHA RSA-PSK-3DES-EDE-CBC-SHA
- RSA_PSK_WITH_AES_128_CBC_SHA RSA-PSK-AES128-CBC-SHA
- RSA_PSK_WITH_AES_256_CBC_SHA RSA-PSK-AES256-CBC-SHA
-
- PSK_WITH_AES_128_GCM_SHA256 PSK-AES128-GCM-SHA256
- PSK_WITH_AES_256_GCM_SHA384 PSK-AES256-GCM-SHA384
- DHE_PSK_WITH_AES_128_GCM_SHA256 DHE-PSK-AES128-GCM-SHA256
- DHE_PSK_WITH_AES_256_GCM_SHA384 DHE-PSK-AES256-GCM-SHA384
- RSA_PSK_WITH_AES_128_GCM_SHA256 RSA-PSK-AES128-GCM-SHA256
- RSA_PSK_WITH_AES_256_GCM_SHA384 RSA-PSK-AES256-GCM-SHA384
-
- PSK_WITH_AES_128_CBC_SHA256 PSK-AES128-CBC-SHA256
- PSK_WITH_AES_256_CBC_SHA384 PSK-AES256-CBC-SHA384
- PSK_WITH_NULL_SHA256 PSK-NULL-SHA256
- PSK_WITH_NULL_SHA384 PSK-NULL-SHA384
- DHE_PSK_WITH_AES_128_CBC_SHA256 DHE-PSK-AES128-CBC-SHA256
- DHE_PSK_WITH_AES_256_CBC_SHA384 DHE-PSK-AES256-CBC-SHA384
- DHE_PSK_WITH_NULL_SHA256 DHE-PSK-NULL-SHA256
- DHE_PSK_WITH_NULL_SHA384 DHE-PSK-NULL-SHA384
- RSA_PSK_WITH_AES_128_CBC_SHA256 RSA-PSK-AES128-CBC-SHA256
- RSA_PSK_WITH_AES_256_CBC_SHA384 RSA-PSK-AES256-CBC-SHA384
- RSA_PSK_WITH_NULL_SHA256 RSA-PSK-NULL-SHA256
- RSA_PSK_WITH_NULL_SHA384 RSA-PSK-NULL-SHA384
- PSK_WITH_AES_128_GCM_SHA256 PSK-AES128-GCM-SHA256
- PSK_WITH_AES_256_GCM_SHA384 PSK-AES256-GCM-SHA384
-
- ECDHE_PSK_WITH_RC4_128_SHA ECDHE-PSK-RC4-SHA
- ECDHE_PSK_WITH_3DES_EDE_CBC_SHA ECDHE-PSK-3DES-EDE-CBC-SHA
- ECDHE_PSK_WITH_AES_128_CBC_SHA ECDHE-PSK-AES128-CBC-SHA
- ECDHE_PSK_WITH_AES_256_CBC_SHA ECDHE-PSK-AES256-CBC-SHA
- ECDHE_PSK_WITH_AES_128_CBC_SHA256 ECDHE-PSK-AES128-CBC-SHA256
- ECDHE_PSK_WITH_AES_256_CBC_SHA384 ECDHE-PSK-AES256-CBC-SHA384
- ECDHE_PSK_WITH_NULL_SHA ECDHE-PSK-NULL-SHA
- ECDHE_PSK_WITH_NULL_SHA256 ECDHE-PSK-NULL-SHA256
- ECDHE_PSK_WITH_NULL_SHA384 ECDHE-PSK-NULL-SHA384
-
- PSK_WITH_CAMELLIA_128_CBC_SHA256 PSK-CAMELLIA128-SHA256
- PSK_WITH_CAMELLIA_256_CBC_SHA384 PSK-CAMELLIA256-SHA384
-
- DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 DHE-PSK-CAMELLIA128-SHA256
- DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 DHE-PSK-CAMELLIA256-SHA384
-
- RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 RSA-PSK-CAMELLIA128-SHA256
- RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 RSA-PSK-CAMELLIA256-SHA384
-
- ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 ECDHE-PSK-CAMELLIA128-SHA256
- ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 ECDHE-PSK-CAMELLIA256-SHA384
-
- PSK_WITH_AES_128_CCM PSK-AES128-CCM
- PSK_WITH_AES_256_CCM PSK-AES256-CCM
- DHE_PSK_WITH_AES_128_CCM DHE-PSK-AES128-CCM
- DHE_PSK_WITH_AES_256_CCM DHE-PSK-AES256-CCM
- PSK_WITH_AES_128_CCM_8 PSK-AES128-CCM8
- PSK_WITH_AES_256_CCM_8 PSK-AES256-CCM8
- DHE_PSK_WITH_AES_128_CCM_8 DHE-PSK-AES128-CCM8
- DHE_PSK_WITH_AES_256_CCM_8 DHE-PSK-AES256-CCM8
-
-=head2 ChaCha20-Poly1305 cipher suites, extending TLS v1.2
-
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 ECDHE-RSA-CHACHA20-POLY1305
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 ECDHE-ECDSA-CHACHA20-POLY1305
- TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 DHE-RSA-CHACHA20-POLY1305
- TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 PSK-CHACHA20-POLY1305
- TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 ECDHE-PSK-CHACHA20-POLY1305
- TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 DHE-PSK-CHACHA20-POLY1305
- TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 RSA-PSK-CHACHA20-POLY1305
-
-=head2 TLS v1.3 cipher suites
-
- TLS_AES_128_GCM_SHA256 TLS_AES_128_GCM_SHA256
- TLS_AES_256_GCM_SHA384 TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256 TLS_CHACHA20_POLY1305_SHA256
- TLS_AES_128_CCM_SHA256 TLS_AES_128_CCM_SHA256
- TLS_AES_128_CCM_8_SHA256 TLS_AES_128_CCM_8_SHA256
-
-=head2 Older names used by OpenSSL
-
-The following names are accepted by older releases:
-
- SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA EDH-RSA-DES-CBC3-SHA (DHE-RSA-DES-CBC3-SHA)
- SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA EDH-DSS-DES-CBC3-SHA (DHE-DSS-DES-CBC3-SHA)
-
-=head1 NOTES
-
-Some compiled versions of OpenSSL may not include all the ciphers
-listed here because some ciphers were excluded at compile time.
-
-=head1 EXAMPLES
-
-Verbose listing of all OpenSSL ciphers including NULL ciphers:
-
- openssl ciphers -v 'ALL:eNULL'
-
-Include all ciphers except NULL and anonymous DH then sort by
-strength:
-
- openssl ciphers -v 'ALL:!ADH:@STRENGTH'
-
-Include all ciphers except ones with no encryption (eNULL) or no
-authentication (aNULL):
-
- openssl ciphers -v 'ALL:!aNULL'
-
-Include only 3DES ciphers and then place RSA ciphers last:
-
- openssl ciphers -v '3DES:+RSA'
-
-Include all RC4 ciphers but leave out those without authentication:
-
- openssl ciphers -v 'RC4:!COMPLEMENTOFDEFAULT'
-
-Include all ciphers with RSA authentication but leave out ciphers without
-encryption.
-
- openssl ciphers -v 'RSA:!COMPLEMENTOFALL'
-
-Set security level to 2 and display all ciphers consistent with level 2:
-
- openssl ciphers -s -v 'ALL:@SECLEVEL=2'
-
-=head1 SEE ALSO
-
-L<s_client(1)>, L<s_server(1)>, L<ssl(7)>
-
-=head1 HISTORY
-
-The B<-V> option for the B<ciphers> command was added in OpenSSL 1.0.0.
-
-The B<-stdname> is only available if OpenSSL is built with tracing enabled
-(B<enable-ssl-trace> argument to Configure) before OpenSSL 1.1.1.
-
-The B<-convert> option was added in OpenSSL 1.1.1.
-
-=head1 COPYRIGHT
-
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/cms.pod b/doc/man1/cms.pod
deleted file mode 100644
index c30e834cfae7..000000000000
--- a/doc/man1/cms.pod
+++ /dev/null
@@ -1,748 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-cms,
-cms - CMS utility
-
-=head1 SYNOPSIS
-
-B<openssl> B<cms>
-[B<-help>]
-[B<-encrypt>]
-[B<-decrypt>]
-[B<-sign>]
-[B<-verify>]
-[B<-cmsout>]
-[B<-resign>]
-[B<-data_create>]
-[B<-data_out>]
-[B<-digest_create>]
-[B<-digest_verify>]
-[B<-compress>]
-[B<-uncompress>]
-[B<-EncryptedData_encrypt>]
-[B<-sign_receipt>]
-[B<-verify_receipt receipt>]
-[B<-in filename>]
-[B<-inform SMIME|PEM|DER>]
-[B<-rctform SMIME|PEM|DER>]
-[B<-out filename>]
-[B<-outform SMIME|PEM|DER>]
-[B<-stream -indef -noindef>]
-[B<-noindef>]
-[B<-content filename>]
-[B<-text>]
-[B<-noout>]
-[B<-print>]
-[B<-CAfile file>]
-[B<-CApath dir>]
-[B<-no-CAfile>]
-[B<-no-CApath>]
-[B<-attime timestamp>]
-[B<-check_ss_sig>]
-[B<-crl_check>]
-[B<-crl_check_all>]
-[B<-explicit_policy>]
-[B<-extended_crl>]
-[B<-ignore_critical>]
-[B<-inhibit_any>]
-[B<-inhibit_map>]
-[B<-no_check_time>]
-[B<-partial_chain>]
-[B<-policy arg>]
-[B<-policy_check>]
-[B<-policy_print>]
-[B<-purpose purpose>]
-[B<-suiteB_128>]
-[B<-suiteB_128_only>]
-[B<-suiteB_192>]
-[B<-trusted_first>]
-[B<-no_alt_chains>]
-[B<-use_deltas>]
-[B<-auth_level num>]
-[B<-verify_depth num>]
-[B<-verify_email email>]
-[B<-verify_hostname hostname>]
-[B<-verify_ip ip>]
-[B<-verify_name name>]
-[B<-x509_strict>]
-[B<-md digest>]
-[B<-I<cipher>>]
-[B<-nointern>]
-[B<-noverify>]
-[B<-nocerts>]
-[B<-noattr>]
-[B<-nosmimecap>]
-[B<-binary>]
-[B<-crlfeol>]
-[B<-asciicrlf>]
-[B<-nodetach>]
-[B<-certfile file>]
-[B<-certsout file>]
-[B<-signer file>]
-[B<-recip file>]
-[B<-keyid>]
-[B<-receipt_request_all>]
-[B<-receipt_request_first>]
-[B<-receipt_request_from emailaddress>]
-[B<-receipt_request_to emailaddress>]
-[B<-receipt_request_print>]
-[B<-secretkey key>]
-[B<-secretkeyid id>]
-[B<-econtent_type type>]
-[B<-inkey file>]
-[B<-keyopt name:parameter>]
-[B<-passin arg>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<cert.pem...>]
-[B<-to addr>]
-[B<-from addr>]
-[B<-subject subj>]
-[cert.pem]...
-
-=head1 DESCRIPTION
-
-The B<cms> command handles S/MIME v3.1 mail. It can encrypt, decrypt, sign and
-verify, compress and uncompress S/MIME messages.
-
-=head1 OPTIONS
-
-There are fourteen operation options that set the type of operation to be
-performed. The meaning of the other options varies according to the operation
-type.
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-encrypt>
-
-Encrypt mail for the given recipient certificates. Input file is the message
-to be encrypted. The output file is the encrypted mail in MIME format. The
-actual CMS type is <B>EnvelopedData<B>.
-
-Note that no revocation check is done for the recipient cert, so if that
-key has been compromised, others may be able to decrypt the text.
-
-=item B<-decrypt>
-
-Decrypt mail using the supplied certificate and private key. Expects an
-encrypted mail message in MIME format for the input file. The decrypted mail
-is written to the output file.
-
-=item B<-debug_decrypt>
-
-This option sets the B<CMS_DEBUG_DECRYPT> flag. This option should be used
-with caution: see the notes section below.
-
-=item B<-sign>
-
-Sign mail using the supplied certificate and private key. Input file is
-the message to be signed. The signed message in MIME format is written
-to the output file.
-
-=item B<-verify>
-
-Verify signed mail. Expects a signed mail message on input and outputs
-the signed data. Both clear text and opaque signing is supported.
-
-=item B<-cmsout>
-
-Takes an input message and writes out a PEM encoded CMS structure.
-
-=item B<-resign>
-
-Resign a message: take an existing message and one or more new signers.
-
-=item B<-data_create>
-
-Create a CMS B<Data> type.
-
-=item B<-data_out>
-
-B<Data> type and output the content.
-
-=item B<-digest_create>
-
-Create a CMS B<DigestedData> type.
-
-=item B<-digest_verify>
-
-Verify a CMS B<DigestedData> type and output the content.
-
-=item B<-compress>
-
-Create a CMS B<CompressedData> type. OpenSSL must be compiled with B<zlib>
-support for this option to work, otherwise it will output an error.
-
-=item B<-uncompress>
-
-Uncompress a CMS B<CompressedData> type and output the content. OpenSSL must be
-compiled with B<zlib> support for this option to work, otherwise it will
-output an error.
-
-=item B<-EncryptedData_encrypt>
-
-Encrypt content using supplied symmetric key and algorithm using a CMS
-B<EncryptedData> type and output the content.
-
-=item B<-sign_receipt>
-
-Generate and output a signed receipt for the supplied message. The input
-message B<must> contain a signed receipt request. Functionality is otherwise
-similar to the B<-sign> operation.
-
-=item B<-verify_receipt receipt>
-
-Verify a signed receipt in filename B<receipt>. The input message B<must>
-contain the original receipt request. Functionality is otherwise similar
-to the B<-verify> operation.
-
-=item B<-in filename>
-
-The input message to be encrypted or signed or the message to be decrypted
-or verified.
-
-=item B<-inform SMIME|PEM|DER>
-
-This specifies the input format for the CMS structure. The default
-is B<SMIME> which reads an S/MIME format message. B<PEM> and B<DER>
-format change this to expect PEM and DER format CMS structures
-instead. This currently only affects the input format of the CMS
-structure, if no CMS structure is being input (for example with
-B<-encrypt> or B<-sign>) this option has no effect.
-
-=item B<-rctform SMIME|PEM|DER>
-
-Specify the format for a signed receipt for use with the B<-receipt_verify>
-operation.
-
-=item B<-out filename>
-
-The message text that has been decrypted or verified or the output MIME
-format message that has been signed or verified.
-
-=item B<-outform SMIME|PEM|DER>
-
-This specifies the output format for the CMS structure. The default
-is B<SMIME> which writes an S/MIME format message. B<PEM> and B<DER>
-format change this to write PEM and DER format CMS structures
-instead. This currently only affects the output format of the CMS
-structure, if no CMS structure is being output (for example with
-B<-verify> or B<-decrypt>) this option has no effect.
-
-=item B<-stream -indef -noindef>
-
-The B<-stream> and B<-indef> options are equivalent and enable streaming I/O
-for encoding operations. This permits single pass processing of data without
-the need to hold the entire contents in memory, potentially supporting very
-large files. Streaming is automatically set for S/MIME signing with detached
-data if the output format is B<SMIME> it is currently off by default for all
-other operations.
-
-=item B<-noindef>
-
-Disable streaming I/O where it would produce and indefinite length constructed
-encoding. This option currently has no effect. In future streaming will be
-enabled by default on all relevant operations and this option will disable it.
-
-=item B<-content filename>
-
-This specifies a file containing the detached content, this is only
-useful with the B<-verify> command. This is only usable if the CMS
-structure is using the detached signature form where the content is
-not included. This option will override any content if the input format
-is S/MIME and it uses the multipart/signed MIME content type.
-
-=item B<-text>
-
-This option adds plain text (text/plain) MIME headers to the supplied
-message if encrypting or signing. If decrypting or verifying it strips
-off text headers: if the decrypted or verified message is not of MIME
-type text/plain then an error occurs.
-
-=item B<-noout>
-
-For the B<-cmsout> operation do not output the parsed CMS structure. This
-is useful when combined with the B<-print> option or if the syntax of the CMS
-structure is being checked.
-
-=item B<-print>
-
-For the B<-cmsout> operation print out all fields of the CMS structure. This
-is mainly useful for testing purposes.
-
-=item B<-CAfile file>
-
-A file containing trusted CA certificates, only used with B<-verify>.
-
-=item B<-CApath dir>
-
-A directory containing trusted CA certificates, only used with
-B<-verify>. This directory must be a standard certificate directory: that
-is a hash of each subject name (using B<x509 -hash>) should be linked
-to each certificate.
-
-=item B<-no-CAfile>
-
-Do not load the trusted CA certificates from the default file location
-
-=item B<-no-CApath>
-
-Do not load the trusted CA certificates from the default directory location
-
-=item B<-md digest>
-
-Digest algorithm to use when signing or resigning. If not present then the
-default digest algorithm for the signing key will be used (usually SHA1).
-
-=item B<-I<cipher>>
-
-The encryption algorithm to use. For example triple DES (168 bits) - B<-des3>
-or 256 bit AES - B<-aes256>. Any standard algorithm name (as used by the
-EVP_get_cipherbyname() function) can also be used preceded by a dash, for
-example B<-aes-128-cbc>. See L<enc(1)> for a list of ciphers
-supported by your version of OpenSSL.
-
-If not specified triple DES is used. Only used with B<-encrypt> and
-B<-EncryptedData_create> commands.
-
-=item B<-nointern>
-
-When verifying a message normally certificates (if any) included in
-the message are searched for the signing certificate. With this option
-only the certificates specified in the B<-certfile> option are used.
-The supplied certificates can still be used as untrusted CAs however.
-
-=item B<-noverify>
-
-Do not verify the signers certificate of a signed message.
-
-=item B<-nocerts>
-
-When signing a message the signer's certificate is normally included
-with this option it is excluded. This will reduce the size of the
-signed message but the verifier must have a copy of the signers certificate
-available locally (passed using the B<-certfile> option for example).
-
-=item B<-noattr>
-
-Normally when a message is signed a set of attributes are included which
-include the signing time and supported symmetric algorithms. With this
-option they are not included.
-
-=item B<-nosmimecap>
-
-Exclude the list of supported algorithms from signed attributes, other options
-such as signing time and content type are still included.
-
-=item B<-binary>
-
-Normally the input message is converted to "canonical" format which is
-effectively using CR and LF as end of line: as required by the S/MIME
-specification. When this option is present no translation occurs. This
-is useful when handling binary data which may not be in MIME format.
-
-=item B<-crlfeol>
-
-Normally the output file uses a single B<LF> as end of line. When this
-option is present B<CRLF> is used instead.
-
-=item B<-asciicrlf>
-
-When signing use ASCII CRLF format canonicalisation. This strips trailing
-whitespace from all lines, deletes trailing blank lines at EOF and sets
-the encapsulated content type. This option is normally used with detached
-content and an output signature format of DER. This option is not normally
-needed when verifying as it is enabled automatically if the encapsulated
-content format is detected.
-
-=item B<-nodetach>
-
-When signing a message use opaque signing: this form is more resistant
-to translation by mail relays but it cannot be read by mail agents that
-do not support S/MIME. Without this option cleartext signing with
-the MIME type multipart/signed is used.
-
-=item B<-certfile file>
-
-Allows additional certificates to be specified. When signing these will
-be included with the message. When verifying these will be searched for
-the signers certificates. The certificates should be in PEM format.
-
-=item B<-certsout file>
-
-Any certificates contained in the message are written to B<file>.
-
-=item B<-signer file>
-
-A signing certificate when signing or resigning a message, this option can be
-used multiple times if more than one signer is required. If a message is being
-verified then the signers certificates will be written to this file if the
-verification was successful.
-
-=item B<-recip file>
-
-When decrypting a message this specifies the recipients certificate. The
-certificate must match one of the recipients of the message or an error
-occurs.
-
-When encrypting a message this option may be used multiple times to specify
-each recipient. This form B<must> be used if customised parameters are
-required (for example to specify RSA-OAEP).
-
-Only certificates carrying RSA, Diffie-Hellman or EC keys are supported by this
-option.
-
-=item B<-keyid>
-
-Use subject key identifier to identify certificates instead of issuer name and
-serial number. The supplied certificate B<must> include a subject key
-identifier extension. Supported by B<-sign> and B<-encrypt> options.
-
-=item B<-receipt_request_all>, B<-receipt_request_first>
-
-For B<-sign> option include a signed receipt request. Indicate requests should
-be provided by all recipient or first tier recipients (those mailed directly
-and not from a mailing list). Ignored it B<-receipt_request_from> is included.
-
-=item B<-receipt_request_from emailaddress>
-
-For B<-sign> option include a signed receipt request. Add an explicit email
-address where receipts should be supplied.
-
-=item B<-receipt_request_to emailaddress>
-
-Add an explicit email address where signed receipts should be sent to. This
-option B<must> but supplied if a signed receipt it requested.
-
-=item B<-receipt_request_print>
-
-For the B<-verify> operation print out the contents of any signed receipt
-requests.
-
-=item B<-secretkey key>
-
-Specify symmetric key to use. The key must be supplied in hex format and be
-consistent with the algorithm used. Supported by the B<-EncryptedData_encrypt>
-B<-EncryptedData_decrypt>, B<-encrypt> and B<-decrypt> options. When used
-with B<-encrypt> or B<-decrypt> the supplied key is used to wrap or unwrap the
-content encryption key using an AES key in the B<KEKRecipientInfo> type.
-
-=item B<-secretkeyid id>
-
-The key identifier for the supplied symmetric key for B<KEKRecipientInfo> type.
-This option B<must> be present if the B<-secretkey> option is used with
-B<-encrypt>. With B<-decrypt> operations the B<id> is used to locate the
-relevant key if it is not supplied then an attempt is used to decrypt any
-B<KEKRecipientInfo> structures.
-
-=item B<-econtent_type type>
-
-Set the encapsulated content type to B<type> if not supplied the B<Data> type
-is used. The B<type> argument can be any valid OID name in either text or
-numerical format.
-
-=item B<-inkey file>
-
-The private key to use when signing or decrypting. This must match the
-corresponding certificate. If this option is not specified then the
-private key must be included in the certificate file specified with
-the B<-recip> or B<-signer> file. When signing this option can be used
-multiple times to specify successive keys.
-
-=item B<-keyopt name:opt>
-
-For signing and encryption this option can be used multiple times to
-set customised parameters for the preceding key or certificate. It can
-currently be used to set RSA-PSS for signing, RSA-OAEP for encryption
-or to modify default parameters for ECDH.
-
-=item B<-passin arg>
-
-The private key password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<cert.pem...>
-
-One or more certificates of message recipients: used when encrypting
-a message.
-
-=item B<-to, -from, -subject>
-
-The relevant mail headers. These are included outside the signed
-portion of a message so they may be included manually. If signing
-then many S/MIME mail clients check the signers certificate's email
-address matches that specified in the From: address.
-
-=item B<-attime>, B<-check_ss_sig>, B<-crl_check>, B<-crl_check_all>,
-B<-explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,
-B<-inhibit_map>, B<-no_alt_chains>, B<-no_check_time>, B<-partial_chain>, B<-policy>,
-B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,
-B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,
-B<-auth_level>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
-B<-verify_ip>, B<-verify_name>, B<-x509_strict>
-
-Set various certificate chain validation options. See the
-L<verify(1)> manual page for details.
-
-=back
-
-=head1 NOTES
-
-The MIME message must be sent without any blank lines between the
-headers and the output. Some mail programs will automatically add
-a blank line. Piping the mail directly to sendmail is one way to
-achieve the correct format.
-
-The supplied message to be signed or encrypted must include the
-necessary MIME headers or many S/MIME clients won't display it
-properly (if at all). You can use the B<-text> option to automatically
-add plain text headers.
-
-A "signed and encrypted" message is one where a signed message is
-then encrypted. This can be produced by encrypting an already signed
-message: see the examples section.
-
-This version of the program only allows one signer per message but it
-will verify multiple signers on received messages. Some S/MIME clients
-choke if a message contains multiple signers. It is possible to sign
-messages "in parallel" by signing an already signed message.
-
-The options B<-encrypt> and B<-decrypt> reflect common usage in S/MIME
-clients. Strictly speaking these process CMS enveloped data: CMS
-encrypted data is used for other purposes.
-
-The B<-resign> option uses an existing message digest when adding a new
-signer. This means that attributes must be present in at least one existing
-signer using the same message digest or this operation will fail.
-
-The B<-stream> and B<-indef> options enable streaming I/O support.
-As a result the encoding is BER using indefinite length constructed encoding
-and no longer DER. Streaming is supported for the B<-encrypt> operation and the
-B<-sign> operation if the content is not detached.
-
-Streaming is always used for the B<-sign> operation with detached data but
-since the content is no longer part of the CMS structure the encoding
-remains DER.
-
-If the B<-decrypt> option is used without a recipient certificate then an
-attempt is made to locate the recipient by trying each potential recipient
-in turn using the supplied private key. To thwart the MMA attack
-(Bleichenbacher's attack on PKCS #1 v1.5 RSA padding) all recipients are
-tried whether they succeed or not and if no recipients match the message
-is "decrypted" using a random key which will typically output garbage.
-The B<-debug_decrypt> option can be used to disable the MMA attack protection
-and return an error if no recipient can be found: this option should be used
-with caution. For a fuller description see L<CMS_decrypt(3)>).
-
-=head1 EXIT CODES
-
-=over 4
-
-=item Z<>0
-
-The operation was completely successfully.
-
-=item Z<>1
-
-An error occurred parsing the command options.
-
-=item Z<>2
-
-One of the input files could not be read.
-
-=item Z<>3
-
-An error occurred creating the CMS file or when reading the MIME
-message.
-
-=item Z<>4
-
-An error occurred decrypting or verifying the message.
-
-=item Z<>5
-
-The message was verified correctly but an error occurred writing out
-the signers certificates.
-
-=back
-
-=head1 COMPATIBILITY WITH PKCS#7 format.
-
-The B<smime> utility can only process the older B<PKCS#7> format. The B<cms>
-utility supports Cryptographic Message Syntax format. Use of some features
-will result in messages which cannot be processed by applications which only
-support the older format. These are detailed below.
-
-The use of the B<-keyid> option with B<-sign> or B<-encrypt>.
-
-The B<-outform PEM> option uses different headers.
-
-The B<-compress> option.
-
-The B<-secretkey> option when used with B<-encrypt>.
-
-The use of PSS with B<-sign>.
-
-The use of OAEP or non-RSA keys with B<-encrypt>.
-
-Additionally the B<-EncryptedData_create> and B<-data_create> type cannot
-be processed by the older B<smime> command.
-
-=head1 EXAMPLES
-
-Create a cleartext signed message:
-
- openssl cms -sign -in message.txt -text -out mail.msg \
- -signer mycert.pem
-
-Create an opaque signed message
-
- openssl cms -sign -in message.txt -text -out mail.msg -nodetach \
- -signer mycert.pem
-
-Create a signed message, include some additional certificates and
-read the private key from another file:
-
- openssl cms -sign -in in.txt -text -out mail.msg \
- -signer mycert.pem -inkey mykey.pem -certfile mycerts.pem
-
-Create a signed message with two signers, use key identifier:
-
- openssl cms -sign -in message.txt -text -out mail.msg \
- -signer mycert.pem -signer othercert.pem -keyid
-
-Send a signed message under Unix directly to sendmail, including headers:
-
- openssl cms -sign -in in.txt -text -signer mycert.pem \
- -from steve@openssl.org -to someone@somewhere \
- -subject "Signed message" | sendmail someone@somewhere
-
-Verify a message and extract the signer's certificate if successful:
-
- openssl cms -verify -in mail.msg -signer user.pem -out signedtext.txt
-
-Send encrypted mail using triple DES:
-
- openssl cms -encrypt -in in.txt -from steve@openssl.org \
- -to someone@somewhere -subject "Encrypted message" \
- -des3 user.pem -out mail.msg
-
-Sign and encrypt mail:
-
- openssl cms -sign -in ml.txt -signer my.pem -text \
- | openssl cms -encrypt -out mail.msg \
- -from steve@openssl.org -to someone@somewhere \
- -subject "Signed and Encrypted message" -des3 user.pem
-
-Note: the encryption command does not include the B<-text> option because the
-message being encrypted already has MIME headers.
-
-Decrypt mail:
-
- openssl cms -decrypt -in mail.msg -recip mycert.pem -inkey key.pem
-
-The output from Netscape form signing is a PKCS#7 structure with the
-detached signature format. You can use this program to verify the
-signature by line wrapping the base64 encoded structure and surrounding
-it with:
-
- -----BEGIN PKCS7-----
- -----END PKCS7-----
-
-and using the command,
-
- openssl cms -verify -inform PEM -in signature.pem -content content.txt
-
-alternatively you can base64 decode the signature and use
-
- openssl cms -verify -inform DER -in signature.der -content content.txt
-
-Create an encrypted message using 128 bit Camellia:
-
- openssl cms -encrypt -in plain.txt -camellia128 -out mail.msg cert.pem
-
-Add a signer to an existing message:
-
- openssl cms -resign -in mail.msg -signer newsign.pem -out mail2.msg
-
-Sign mail using RSA-PSS:
-
- openssl cms -sign -in message.txt -text -out mail.msg \
- -signer mycert.pem -keyopt rsa_padding_mode:pss
-
-Create encrypted mail using RSA-OAEP:
-
- openssl cms -encrypt -in plain.txt -out mail.msg \
- -recip cert.pem -keyopt rsa_padding_mode:oaep
-
-Use SHA256 KDF with an ECDH certificate:
-
- openssl cms -encrypt -in plain.txt -out mail.msg \
- -recip ecdhcert.pem -keyopt ecdh_kdf_md:sha256
-
-=head1 BUGS
-
-The MIME parser isn't very clever: it seems to handle most messages that I've
-thrown at it but it may choke on others.
-
-The code currently will only write out the signer's certificate to a file: if
-the signer has a separate encryption certificate this must be manually
-extracted. There should be some heuristic that determines the correct
-encryption certificate.
-
-Ideally a database should be maintained of a certificates for each email
-address.
-
-The code doesn't currently take note of the permitted symmetric encryption
-algorithms as supplied in the SMIMECapabilities signed attribute. this means the
-user has to manually include the correct encryption algorithm. It should store
-the list of permitted ciphers in a database and only use those.
-
-No revocation checking is done on the signer's certificate.
-
-The B<-binary> option does not work correctly when processing text input which
-(contrary to the S/MIME specification) uses LF rather than CRLF line endings.
-
-=head1 HISTORY
-
-The use of multiple B<-signer> options and the B<-resign> command were first
-added in OpenSSL 1.0.0.
-
-The B<keyopt> option was added in OpenSSL 1.0.2.
-
-Support for RSA-OAEP and RSA-PSS was added in OpenSSL 1.0.2.
-
-The use of non-RSA keys with B<-encrypt> and B<-decrypt>
-was added in OpenSSL 1.0.2.
-
-The -no_alt_chains option was added in OpenSSL 1.0.2b.
-
-=head1 COPYRIGHT
-
-Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/crl.pod b/doc/man1/crl.pod
deleted file mode 100644
index 58f2bf62ddf3..000000000000
--- a/doc/man1/crl.pod
+++ /dev/null
@@ -1,143 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-crl,
-crl - CRL utility
-
-=head1 SYNOPSIS
-
-B<openssl> B<crl>
-[B<-help>]
-[B<-inform PEM|DER>]
-[B<-outform PEM|DER>]
-[B<-text>]
-[B<-in filename>]
-[B<-out filename>]
-[B<-nameopt option>]
-[B<-noout>]
-[B<-hash>]
-[B<-issuer>]
-[B<-lastupdate>]
-[B<-nextupdate>]
-[B<-CAfile file>]
-[B<-CApath dir>]
-
-=head1 DESCRIPTION
-
-The B<crl> command processes CRL files in DER or PEM format.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-inform DER|PEM>
-
-This specifies the input format. B<DER> format is DER encoded CRL
-structure. B<PEM> (the default) is a base64 encoded version of
-the DER form with header and footer lines.
-
-=item B<-outform DER|PEM>
-
-This specifies the output format, the options have the same meaning and default
-as the B<-inform> option.
-
-=item B<-in filename>
-
-This specifies the input filename to read from or standard input if this
-option is not specified.
-
-=item B<-out filename>
-
-Specifies the output filename to write to or standard output by
-default.
-
-=item B<-text>
-
-Print out the CRL in text form.
-
-=item B<-nameopt option>
-
-Option which determines how the subject or issuer names are displayed. See
-the description of B<-nameopt> in L<x509(1)>.
-
-=item B<-noout>
-
-Don't output the encoded version of the CRL.
-
-=item B<-hash>
-
-Output a hash of the issuer name. This can be use to lookup CRLs in
-a directory by issuer name.
-
-=item B<-hash_old>
-
-Outputs the "hash" of the CRL issuer name using the older algorithm
-as used by OpenSSL before version 1.0.0.
-
-=item B<-issuer>
-
-Output the issuer name.
-
-=item B<-lastupdate>
-
-Output the lastUpdate field.
-
-=item B<-nextupdate>
-
-Output the nextUpdate field.
-
-=item B<-CAfile file>
-
-Verify the signature on a CRL by looking up the issuing certificate in
-B<file>.
-
-=item B<-CApath dir>
-
-Verify the signature on a CRL by looking up the issuing certificate in
-B<dir>. This directory must be a standard certificate directory: that
-is a hash of each subject name (using B<x509 -hash>) should be linked
-to each certificate.
-
-=back
-
-=head1 NOTES
-
-The PEM CRL format uses the header and footer lines:
-
- -----BEGIN X509 CRL-----
- -----END X509 CRL-----
-
-=head1 EXAMPLES
-
-Convert a CRL file from PEM to DER:
-
- openssl crl -in crl.pem -outform DER -out crl.der
-
-Output the text form of a DER encoded certificate:
-
- openssl crl -in crl.der -inform DER -text -noout
-
-=head1 BUGS
-
-Ideally it should be possible to create a CRL using appropriate options
-and files too.
-
-=head1 SEE ALSO
-
-L<crl2pkcs7(1)>, L<ca(1)>, L<x509(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/crl2pkcs7.pod b/doc/man1/crl2pkcs7.pod
deleted file mode 100644
index 3fcb737b7070..000000000000
--- a/doc/man1/crl2pkcs7.pod
+++ /dev/null
@@ -1,106 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-crl2pkcs7,
-crl2pkcs7 - Create a PKCS#7 structure from a CRL and certificates
-
-=head1 SYNOPSIS
-
-B<openssl> B<crl2pkcs7>
-[B<-help>]
-[B<-inform PEM|DER>]
-[B<-outform PEM|DER>]
-[B<-in filename>]
-[B<-out filename>]
-[B<-certfile filename>]
-[B<-nocrl>]
-
-=head1 DESCRIPTION
-
-The B<crl2pkcs7> command takes an optional CRL and one or more
-certificates and converts them into a PKCS#7 degenerate "certificates
-only" structure.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-inform DER|PEM>
-
-This specifies the CRL input format. B<DER> format is DER encoded CRL
-structure.B<PEM> (the default) is a base64 encoded version of
-the DER form with header and footer lines. The default format is PEM.
-
-=item B<-outform DER|PEM>
-
-This specifies the PKCS#7 structure output format. B<DER> format is DER
-encoded PKCS#7 structure.B<PEM> (the default) is a base64 encoded version of
-the DER form with header and footer lines. The default format is PEM.
-
-=item B<-in filename>
-
-This specifies the input filename to read a CRL from or standard input if this
-option is not specified.
-
-=item B<-out filename>
-
-Specifies the output filename to write the PKCS#7 structure to or standard
-output by default.
-
-=item B<-certfile filename>
-
-Specifies a filename containing one or more certificates in B<PEM> format.
-All certificates in the file will be added to the PKCS#7 structure. This
-option can be used more than once to read certificates from multiple
-files.
-
-=item B<-nocrl>
-
-Normally a CRL is included in the output file. With this option no CRL is
-included in the output file and a CRL is not read from the input file.
-
-=back
-
-=head1 EXAMPLES
-
-Create a PKCS#7 structure from a certificate and CRL:
-
- openssl crl2pkcs7 -in crl.pem -certfile cert.pem -out p7.pem
-
-Creates a PKCS#7 structure in DER format with no CRL from several
-different certificates:
-
- openssl crl2pkcs7 -nocrl -certfile newcert.pem
- -certfile demoCA/cacert.pem -outform DER -out p7.der
-
-=head1 NOTES
-
-The output file is a PKCS#7 signed data structure containing no signers and
-just certificates and an optional CRL.
-
-This utility can be used to send certificates and CAs to Netscape as part of
-the certificate enrollment process. This involves sending the DER encoded output
-as MIME type application/x-x509-user-cert.
-
-The B<PEM> encoded form with the header and footer lines removed can be used to
-install user certificates and CAs in MSIE using the Xenroll control.
-
-=head1 SEE ALSO
-
-L<pkcs7(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/dgst.pod b/doc/man1/dgst.pod
deleted file mode 100644
index 8d48c9aed6d6..000000000000
--- a/doc/man1/dgst.pod
+++ /dev/null
@@ -1,251 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-dgst,
-dgst - perform digest operations
-
-=head1 SYNOPSIS
-
-B<openssl dgst>
-[B<-I<digest>>]
-[B<-help>]
-[B<-c>]
-[B<-d>]
-[B<-list>]
-[B<-hex>]
-[B<-binary>]
-[B<-r>]
-[B<-out filename>]
-[B<-sign filename>]
-[B<-keyform arg>]
-[B<-passin arg>]
-[B<-verify filename>]
-[B<-prverify filename>]
-[B<-signature filename>]
-[B<-sigopt nm:v>]
-[B<-hmac key>]
-[B<-fips-fingerprint>]
-[B<-rand file...>]
-[B<-engine id>]
-[B<-engine_impl>]
-[B<file...>]
-
-B<openssl> I<digest> [B<...>]
-
-=head1 DESCRIPTION
-
-The digest functions output the message digest of a supplied file or files
-in hexadecimal. The digest functions also generate and verify digital
-signatures using message digests.
-
-The generic name, B<dgst>, may be used with an option specifying the
-algorithm to be used.
-The default digest is I<sha256>.
-A supported I<digest> name may also be used as the command name.
-To see the list of supported algorithms, use the I<list --digest-commands>
-command.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-I<digest>>
-
-Specifies name of a supported digest to be used. To see the list of
-supported digests, use the command I<list --digest-commands>.
-
-=item B<-c>
-
-Print out the digest in two digit groups separated by colons, only relevant if
-B<hex> format output is used.
-
-=item B<-d>
-
-Print out BIO debugging information.
-
-=item B<-list>
-
-Prints out a list of supported message digests.
-
-=item B<-hex>
-
-Digest is to be output as a hex dump. This is the default case for a "normal"
-digest as opposed to a digital signature. See NOTES below for digital
-signatures using B<-hex>.
-
-=item B<-binary>
-
-Output the digest or signature in binary form.
-
-=item B<-r>
-
-Output the digest in the "coreutils" format, including newlines.
-Used by programs like B<sha1sum>.
-
-=item B<-out filename>
-
-Filename to output to, or standard output by default.
-
-=item B<-sign filename>
-
-Digitally sign the digest using the private key in "filename". Note this option
-does not support Ed25519 or Ed448 private keys.
-
-=item B<-keyform arg>
-
-Specifies the key format to sign digest with. The DER, PEM, P12,
-and ENGINE formats are supported.
-
-=item B<-sigopt nm:v>
-
-Pass options to the signature algorithm during sign or verify operations.
-Names and values of these options are algorithm-specific.
-
-=item B<-passin arg>
-
-The private key password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-verify filename>
-
-Verify the signature using the public key in "filename".
-The output is either "Verification OK" or "Verification Failure".
-
-=item B<-prverify filename>
-
-Verify the signature using the private key in "filename".
-
-=item B<-signature filename>
-
-The actual signature to verify.
-
-=item B<-hmac key>
-
-Create a hashed MAC using "key".
-
-=item B<-mac alg>
-
-Create MAC (keyed Message Authentication Code). The most popular MAC
-algorithm is HMAC (hash-based MAC), but there are other MAC algorithms
-which are not based on hash, for instance B<gost-mac> algorithm,
-supported by B<ccgost> engine. MAC keys and other options should be set
-via B<-macopt> parameter.
-
-=item B<-macopt nm:v>
-
-Passes options to MAC algorithm, specified by B<-mac> key.
-Following options are supported by both by B<HMAC> and B<gost-mac>:
-
-=over 4
-
-=item B<key:string>
-
-Specifies MAC key as alphanumeric string (use if key contain printable
-characters only). String length must conform to any restrictions of
-the MAC algorithm for example exactly 32 chars for gost-mac.
-
-=item B<hexkey:string>
-
-Specifies MAC key in hexadecimal form (two hex digits per byte).
-Key length must conform to any restrictions of the MAC algorithm
-for example exactly 32 chars for gost-mac.
-
-=back
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<-fips-fingerprint>
-
-Compute HMAC using a specific key for certain OpenSSL-FIPS operations.
-
-=item B<-engine id>
-
-Use engine B<id> for operations (including private key storage).
-This engine is not used as source for digest algorithms, unless it is
-also specified in the configuration file or B<-engine_impl> is also
-specified.
-
-=item B<-engine_impl>
-
-When used with the B<-engine> option, it specifies to also use
-engine B<id> for digest operations.
-
-=item B<file...>
-
-File or files to digest. If no files are specified then standard input is
-used.
-
-=back
-
-
-=head1 EXAMPLES
-
-To create a hex-encoded message digest of a file:
- openssl dgst -md5 -hex file.txt
-
-To sign a file using SHA-256 with binary file output:
- openssl dgst -sha256 -sign privatekey.pem -out signature.sign file.txt
-
-To verify a signature:
- openssl dgst -sha256 -verify publickey.pem \
- -signature signature.sign \
- file.txt
-
-
-=head1 NOTES
-
-The digest mechanisms that are available will depend on the options
-used when building OpenSSL.
-The B<list digest-commands> command can be used to list them.
-
-New or agile applications should use probably use SHA-256. Other digests,
-particularly SHA-1 and MD5, are still widely used for interoperating
-with existing formats and protocols.
-
-When signing a file, B<dgst> will automatically determine the algorithm
-(RSA, ECC, etc) to use for signing based on the private key's ASN.1 info.
-When verifying signatures, it only handles the RSA, DSA, or ECDSA signature
-itself, not the related data to identify the signer and algorithm used in
-formats such as x.509, CMS, and S/MIME.
-
-A source of random numbers is required for certain signing algorithms, in
-particular ECDSA and DSA.
-
-The signing and verify options should only be used if a single file is
-being signed or verified.
-
-Hex signatures cannot be verified using B<openssl>. Instead, use "xxd -r"
-or similar program to transform the hex signature into a binary signature
-prior to verification.
-
-=head1 HISTORY
-
-The default digest was changed from MD5 to SHA256 in OpenSSL 1.1.0.
-The FIPS-related options were removed in OpenSSL 1.1.0.
-
-=head1 COPYRIGHT
-
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/dhparam.pod b/doc/man1/dhparam.pod
deleted file mode 100644
index 1b43b3231083..000000000000
--- a/doc/man1/dhparam.pod
+++ /dev/null
@@ -1,166 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-dhparam,
-dhparam - DH parameter manipulation and generation
-
-=head1 SYNOPSIS
-
-B<openssl dhparam>
-[B<-help>]
-[B<-inform DER|PEM>]
-[B<-outform DER|PEM>]
-[B<-in> I<filename>]
-[B<-out> I<filename>]
-[B<-dsaparam>]
-[B<-check>]
-[B<-noout>]
-[B<-text>]
-[B<-C>]
-[B<-2>]
-[B<-5>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-engine id>]
-[I<numbits>]
-
-=head1 DESCRIPTION
-
-This command is used to manipulate DH parameter files.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-inform DER|PEM>
-
-This specifies the input format. The B<DER> option uses an ASN1 DER encoded
-form compatible with the PKCS#3 DHparameter structure. The PEM form is the
-default format: it consists of the B<DER> format base64 encoded with
-additional header and footer lines.
-
-=item B<-outform DER|PEM>
-
-This specifies the output format, the options have the same meaning and default
-as the B<-inform> option.
-
-=item B<-in> I<filename>
-
-This specifies the input filename to read parameters from or standard input if
-this option is not specified.
-
-=item B<-out> I<filename>
-
-This specifies the output filename parameters to. Standard output is used
-if this option is not present. The output filename should B<not> be the same
-as the input filename.
-
-=item B<-dsaparam>
-
-If this option is used, DSA rather than DH parameters are read or created;
-they are converted to DH format. Otherwise, "strong" primes (such
-that (p-1)/2 is also prime) will be used for DH parameter generation.
-
-DH parameter generation with the B<-dsaparam> option is much faster,
-and the recommended exponent length is shorter, which makes DH key
-exchange more efficient. Beware that with such DSA-style DH
-parameters, a fresh DH key should be created for each use to
-avoid small-subgroup attacks that may be possible otherwise.
-
-=item B<-check>
-
-Performs numerous checks to see if the supplied parameters are valid and
-displays a warning if not.
-
-=item B<-2>, B<-5>
-
-The generator to use, either 2 or 5. If present then the
-input file is ignored and parameters are generated instead. If not
-present but B<numbits> is present, parameters are generated with the
-default generator 2.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item I<numbits>
-
-This option specifies that a parameter set should be generated of size
-I<numbits>. It must be the last option. If this option is present then
-the input file is ignored and parameters are generated instead. If
-this option is not present but a generator (B<-2> or B<-5>) is
-present, parameters are generated with a default length of 2048 bits.
-
-=item B<-noout>
-
-This option inhibits the output of the encoded version of the parameters.
-
-=item B<-text>
-
-This option prints out the DH parameters in human readable form.
-
-=item B<-C>
-
-This option converts the parameters into C code. The parameters can then
-be loaded by calling the get_dhNNNN() function.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<dhparam>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=back
-
-=head1 WARNINGS
-
-The program B<dhparam> combines the functionality of the programs B<dh> and
-B<gendh> in previous versions of OpenSSL. The B<dh> and B<gendh>
-programs are retained for now but may have different purposes in future
-versions of OpenSSL.
-
-=head1 NOTES
-
-PEM format DH parameters use the header and footer lines:
-
- -----BEGIN DH PARAMETERS-----
- -----END DH PARAMETERS-----
-
-OpenSSL currently only supports the older PKCS#3 DH, not the newer X9.42
-DH.
-
-This program manipulates DH parameters not keys.
-
-=head1 BUGS
-
-There should be a way to generate and manipulate DH keys.
-
-=head1 SEE ALSO
-
-L<dsaparam(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/dsa.pod b/doc/man1/dsa.pod
deleted file mode 100644
index 752c22063e9c..000000000000
--- a/doc/man1/dsa.pod
+++ /dev/null
@@ -1,182 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-dsa,
-dsa - DSA key processing
-
-=head1 SYNOPSIS
-
-B<openssl> B<dsa>
-[B<-help>]
-[B<-inform PEM|DER>]
-[B<-outform PEM|DER>]
-[B<-in filename>]
-[B<-passin arg>]
-[B<-out filename>]
-[B<-passout arg>]
-[B<-aes128>]
-[B<-aes192>]
-[B<-aes256>]
-[B<-aria128>]
-[B<-aria192>]
-[B<-aria256>]
-[B<-camellia128>]
-[B<-camellia192>]
-[B<-camellia256>]
-[B<-des>]
-[B<-des3>]
-[B<-idea>]
-[B<-text>]
-[B<-noout>]
-[B<-modulus>]
-[B<-pubin>]
-[B<-pubout>]
-[B<-engine id>]
-
-=head1 DESCRIPTION
-
-The B<dsa> command processes DSA keys. They can be converted between various
-forms and their components printed out. B<Note> This command uses the
-traditional SSLeay compatible format for private key encryption: newer
-applications should use the more secure PKCS#8 format using the B<pkcs8>
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-inform DER|PEM>
-
-This specifies the input format. The B<DER> option with a private key uses
-an ASN1 DER encoded form of an ASN.1 SEQUENCE consisting of the values of
-version (currently zero), p, q, g, the public and private key components
-respectively as ASN.1 INTEGERs. When used with a public key it uses a
-SubjectPublicKeyInfo structure: it is an error if the key is not DSA.
-
-The B<PEM> form is the default format: it consists of the B<DER> format base64
-encoded with additional header and footer lines. In the case of a private key
-PKCS#8 format is also accepted.
-
-=item B<-outform DER|PEM>
-
-This specifies the output format, the options have the same meaning and default
-as the B<-inform> option.
-
-=item B<-in filename>
-
-This specifies the input filename to read a key from or standard input if this
-option is not specified. If the key is encrypted a pass phrase will be
-prompted for.
-
-=item B<-passin arg>
-
-The input file password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-out filename>
-
-This specifies the output filename to write a key to or standard output by
-is not specified. If any encryption options are set then a pass phrase will be
-prompted for. The output filename should B<not> be the same as the input
-filename.
-
-=item B<-passout arg>
-
-The output file password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-aes128>, B<-aes192>, B<-aes256>, B<-aria128>, B<-aria192>, B<-aria256>, B<-camellia128>, B<-camellia192>, B<-camellia256>, B<-des>, B<-des3>, B<-idea>
-
-These options encrypt the private key with the specified
-cipher before outputting it. A pass phrase is prompted for.
-If none of these options is specified the key is written in plain text. This
-means that using the B<dsa> utility to read in an encrypted key with no
-encryption option can be used to remove the pass phrase from a key, or by
-setting the encryption options it can be use to add or change the pass phrase.
-These options can only be used with PEM format output files.
-
-=item B<-text>
-
-Prints out the public, private key components and parameters.
-
-=item B<-noout>
-
-This option prevents output of the encoded version of the key.
-
-=item B<-modulus>
-
-This option prints out the value of the public key component of the key.
-
-=item B<-pubin>
-
-By default, a private key is read from the input file. With this option a
-public key is read instead.
-
-=item B<-pubout>
-
-By default, a private key is output. With this option a public
-key will be output instead. This option is automatically set if the input is
-a public key.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<dsa>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=back
-
-=head1 NOTES
-
-The PEM private key format uses the header and footer lines:
-
- -----BEGIN DSA PRIVATE KEY-----
- -----END DSA PRIVATE KEY-----
-
-The PEM public key format uses the header and footer lines:
-
- -----BEGIN PUBLIC KEY-----
- -----END PUBLIC KEY-----
-
-=head1 EXAMPLES
-
-To remove the pass phrase on a DSA private key:
-
- openssl dsa -in key.pem -out keyout.pem
-
-To encrypt a private key using triple DES:
-
- openssl dsa -in key.pem -des3 -out keyout.pem
-
-To convert a private key from PEM to DER format:
-
- openssl dsa -in key.pem -outform DER -out keyout.der
-
-To print out the components of a private key to standard output:
-
- openssl dsa -in key.pem -text -noout
-
-To just output the public part of a private key:
-
- openssl dsa -in key.pem -pubout -out pubkey.pem
-
-=head1 SEE ALSO
-
-L<dsaparam(1)>, L<gendsa(1)>, L<rsa(1)>,
-L<genrsa(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/dsaparam.pod b/doc/man1/dsaparam.pod
deleted file mode 100644
index 94ea435cceb8..000000000000
--- a/doc/man1/dsaparam.pod
+++ /dev/null
@@ -1,131 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-dsaparam,
-dsaparam - DSA parameter manipulation and generation
-
-=head1 SYNOPSIS
-
-B<openssl dsaparam>
-[B<-help>]
-[B<-inform DER|PEM>]
-[B<-outform DER|PEM>]
-[B<-in filename>]
-[B<-out filename>]
-[B<-noout>]
-[B<-text>]
-[B<-C>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-genkey>]
-[B<-engine id>]
-[B<numbits>]
-
-=head1 DESCRIPTION
-
-This command is used to manipulate or generate DSA parameter files.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-inform DER|PEM>
-
-This specifies the input format. The B<DER> option uses an ASN1 DER encoded
-form compatible with RFC2459 (PKIX) DSS-Parms that is a SEQUENCE consisting
-of p, q and g respectively. The PEM form is the default format: it consists
-of the B<DER> format base64 encoded with additional header and footer lines.
-
-=item B<-outform DER|PEM>
-
-This specifies the output format, the options have the same meaning and default
-as the B<-inform> option.
-
-=item B<-in filename>
-
-This specifies the input filename to read parameters from or standard input if
-this option is not specified. If the B<numbits> parameter is included then
-this option will be ignored.
-
-=item B<-out filename>
-
-This specifies the output filename parameters to. Standard output is used
-if this option is not present. The output filename should B<not> be the same
-as the input filename.
-
-=item B<-noout>
-
-This option inhibits the output of the encoded version of the parameters.
-
-=item B<-text>
-
-This option prints out the DSA parameters in human readable form.
-
-=item B<-C>
-
-This option converts the parameters into C code. The parameters can then
-be loaded by calling the get_dsaXXX() function.
-
-=item B<-genkey>
-
-This option will generate a DSA either using the specified or generated
-parameters.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<numbits>
-
-This option specifies that a parameter set should be generated of size
-B<numbits>. It must be the last option. If this option is included then
-the input file (if any) is ignored.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<dsaparam>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=back
-
-=head1 NOTES
-
-PEM format DSA parameters use the header and footer lines:
-
- -----BEGIN DSA PARAMETERS-----
- -----END DSA PARAMETERS-----
-
-DSA parameter generation is a slow process and as a result the same set of
-DSA parameters is often used to generate several distinct keys.
-
-=head1 SEE ALSO
-
-L<gendsa(1)>, L<dsa(1)>, L<genrsa(1)>,
-L<rsa(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/ec.pod b/doc/man1/ec.pod
deleted file mode 100644
index 41ffc6cb6379..000000000000
--- a/doc/man1/ec.pod
+++ /dev/null
@@ -1,203 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-ec,
-ec - EC key processing
-
-=head1 SYNOPSIS
-
-B<openssl> B<ec>
-[B<-help>]
-[B<-inform PEM|DER>]
-[B<-outform PEM|DER>]
-[B<-in filename>]
-[B<-passin arg>]
-[B<-out filename>]
-[B<-passout arg>]
-[B<-des>]
-[B<-des3>]
-[B<-idea>]
-[B<-text>]
-[B<-noout>]
-[B<-param_out>]
-[B<-pubin>]
-[B<-pubout>]
-[B<-conv_form arg>]
-[B<-param_enc arg>]
-[B<-no_public>]
-[B<-check>]
-[B<-engine id>]
-
-=head1 DESCRIPTION
-
-The B<ec> command processes EC keys. They can be converted between various
-forms and their components printed out. B<Note> OpenSSL uses the
-private key format specified in 'SEC 1: Elliptic Curve Cryptography'
-(http://www.secg.org/). To convert an OpenSSL EC private key into the
-PKCS#8 private key format use the B<pkcs8> command.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-inform DER|PEM>
-
-This specifies the input format. The B<DER> option with a private key uses
-an ASN.1 DER encoded SEC1 private key. When used with a public key it
-uses the SubjectPublicKeyInfo structure as specified in RFC 3280.
-The B<PEM> form is the default format: it consists of the B<DER> format base64
-encoded with additional header and footer lines. In the case of a private key
-PKCS#8 format is also accepted.
-
-=item B<-outform DER|PEM>
-
-This specifies the output format, the options have the same meaning and default
-as the B<-inform> option.
-
-=item B<-in filename>
-
-This specifies the input filename to read a key from or standard input if this
-option is not specified. If the key is encrypted a pass phrase will be
-prompted for.
-
-=item B<-passin arg>
-
-The input file password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-out filename>
-
-This specifies the output filename to write a key to or standard output by
-is not specified. If any encryption options are set then a pass phrase will be
-prompted for. The output filename should B<not> be the same as the input
-filename.
-
-=item B<-passout arg>
-
-The output file password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-des|-des3|-idea>
-
-These options encrypt the private key with the DES, triple DES, IDEA or
-any other cipher supported by OpenSSL before outputting it. A pass phrase is
-prompted for.
-If none of these options is specified the key is written in plain text. This
-means that using the B<ec> utility to read in an encrypted key with no
-encryption option can be used to remove the pass phrase from a key, or by
-setting the encryption options it can be use to add or change the pass phrase.
-These options can only be used with PEM format output files.
-
-=item B<-text>
-
-Prints out the public, private key components and parameters.
-
-=item B<-noout>
-
-This option prevents output of the encoded version of the key.
-
-=item B<-pubin>
-
-By default, a private key is read from the input file. With this option a
-public key is read instead.
-
-=item B<-pubout>
-
-By default a private key is output. With this option a public
-key will be output instead. This option is automatically set if the input is
-a public key.
-
-=item B<-conv_form>
-
-This specifies how the points on the elliptic curve are converted
-into octet strings. Possible values are: B<compressed> (the default
-value), B<uncompressed> and B<hybrid>. For more information regarding
-the point conversion forms please read the X9.62 standard.
-B<Note> Due to patent issues the B<compressed> option is disabled
-by default for binary curves and can be enabled by defining
-the preprocessor macro B<OPENSSL_EC_BIN_PT_COMP> at compile time.
-
-=item B<-param_enc arg>
-
-This specifies how the elliptic curve parameters are encoded.
-Possible value are: B<named_curve>, i.e. the ec parameters are
-specified by an OID, or B<explicit> where the ec parameters are
-explicitly given (see RFC 3279 for the definition of the
-EC parameters structures). The default value is B<named_curve>.
-B<Note> the B<implicitlyCA> alternative, as specified in RFC 3279,
-is currently not implemented in OpenSSL.
-
-=item B<-no_public>
-
-This option omits the public key components from the private key output.
-
-=item B<-check>
-
-This option checks the consistency of an EC private or public key.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<ec>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=back
-
-=head1 NOTES
-
-The PEM private key format uses the header and footer lines:
-
- -----BEGIN EC PRIVATE KEY-----
- -----END EC PRIVATE KEY-----
-
-The PEM public key format uses the header and footer lines:
-
- -----BEGIN PUBLIC KEY-----
- -----END PUBLIC KEY-----
-
-=head1 EXAMPLES
-
-To encrypt a private key using triple DES:
-
- openssl ec -in key.pem -des3 -out keyout.pem
-
-To convert a private key from PEM to DER format:
-
- openssl ec -in key.pem -outform DER -out keyout.der
-
-To print out the components of a private key to standard output:
-
- openssl ec -in key.pem -text -noout
-
-To just output the public part of a private key:
-
- openssl ec -in key.pem -pubout -out pubkey.pem
-
-To change the parameters encoding to B<explicit>:
-
- openssl ec -in key.pem -param_enc explicit -out keyout.pem
-
-To change the point conversion form to B<compressed>:
-
- openssl ec -in key.pem -conv_form compressed -out keyout.pem
-
-=head1 SEE ALSO
-
-L<ecparam(1)>, L<dsa(1)>, L<rsa(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2003-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/ecparam.pod b/doc/man1/ecparam.pod
deleted file mode 100644
index 0633f8cda480..000000000000
--- a/doc/man1/ecparam.pod
+++ /dev/null
@@ -1,192 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-ecparam,
-ecparam - EC parameter manipulation and generation
-
-=head1 SYNOPSIS
-
-B<openssl ecparam>
-[B<-help>]
-[B<-inform DER|PEM>]
-[B<-outform DER|PEM>]
-[B<-in filename>]
-[B<-out filename>]
-[B<-noout>]
-[B<-text>]
-[B<-C>]
-[B<-check>]
-[B<-name arg>]
-[B<-list_curves>]
-[B<-conv_form arg>]
-[B<-param_enc arg>]
-[B<-no_seed>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-genkey>]
-[B<-engine id>]
-
-=head1 DESCRIPTION
-
-This command is used to manipulate or generate EC parameter files.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-inform DER|PEM>
-
-This specifies the input format. The B<DER> option uses an ASN.1 DER encoded
-form compatible with RFC 3279 EcpkParameters. The PEM form is the default
-format: it consists of the B<DER> format base64 encoded with additional
-header and footer lines.
-
-=item B<-outform DER|PEM>
-
-This specifies the output format, the options have the same meaning and default
-as the B<-inform> option.
-
-=item B<-in filename>
-
-This specifies the input filename to read parameters from or standard input if
-this option is not specified.
-
-=item B<-out filename>
-
-This specifies the output filename parameters to. Standard output is used
-if this option is not present. The output filename should B<not> be the same
-as the input filename.
-
-=item B<-noout>
-
-This option inhibits the output of the encoded version of the parameters.
-
-=item B<-text>
-
-This option prints out the EC parameters in human readable form.
-
-=item B<-C>
-
-This option converts the EC parameters into C code. The parameters can then
-be loaded by calling the get_ec_group_XXX() function.
-
-=item B<-check>
-
-Validate the elliptic curve parameters.
-
-=item B<-name arg>
-
-Use the EC parameters with the specified 'short' name. Use B<-list_curves>
-to get a list of all currently implemented EC parameters.
-
-=item B<-list_curves>
-
-If this options is specified B<ecparam> will print out a list of all
-currently implemented EC parameters names and exit.
-
-=item B<-conv_form>
-
-This specifies how the points on the elliptic curve are converted
-into octet strings. Possible values are: B<compressed>, B<uncompressed> (the
-default value) and B<hybrid>. For more information regarding
-the point conversion forms please read the X9.62 standard.
-B<Note> Due to patent issues the B<compressed> option is disabled
-by default for binary curves and can be enabled by defining
-the preprocessor macro B<OPENSSL_EC_BIN_PT_COMP> at compile time.
-
-=item B<-param_enc arg>
-
-This specifies how the elliptic curve parameters are encoded.
-Possible value are: B<named_curve>, i.e. the ec parameters are
-specified by an OID, or B<explicit> where the ec parameters are
-explicitly given (see RFC 3279 for the definition of the
-EC parameters structures). The default value is B<named_curve>.
-B<Note> the B<implicitlyCA> alternative, as specified in RFC 3279,
-is currently not implemented in OpenSSL.
-
-=item B<-no_seed>
-
-This option inhibits that the 'seed' for the parameter generation
-is included in the ECParameters structure (see RFC 3279).
-
-=item B<-genkey>
-
-This option will generate an EC private key using the specified parameters.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<ecparam>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=back
-
-=head1 NOTES
-
-PEM format EC parameters use the header and footer lines:
-
- -----BEGIN EC PARAMETERS-----
- -----END EC PARAMETERS-----
-
-OpenSSL is currently not able to generate new groups and therefore
-B<ecparam> can only create EC parameters from known (named) curves.
-
-=head1 EXAMPLES
-
-To create EC parameters with the group 'prime192v1':
-
- openssl ecparam -out ec_param.pem -name prime192v1
-
-To create EC parameters with explicit parameters:
-
- openssl ecparam -out ec_param.pem -name prime192v1 -param_enc explicit
-
-To validate given EC parameters:
-
- openssl ecparam -in ec_param.pem -check
-
-To create EC parameters and a private key:
-
- openssl ecparam -out ec_key.pem -name prime192v1 -genkey
-
-To change the point encoding to 'compressed':
-
- openssl ecparam -in ec_in.pem -out ec_out.pem -conv_form compressed
-
-To print out the EC parameters to standard output:
-
- openssl ecparam -in ec_param.pem -noout -text
-
-=head1 SEE ALSO
-
-L<ec(1)>, L<dsaparam(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2003-2018 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/enc.pod b/doc/man1/enc.pod
deleted file mode 100644
index 9068282db543..000000000000
--- a/doc/man1/enc.pod
+++ /dev/null
@@ -1,438 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-enc,
-enc - symmetric cipher routines
-
-=head1 SYNOPSIS
-
-B<openssl enc -I<cipher>>
-[B<-help>]
-[B<-list>]
-[B<-ciphers>]
-[B<-in filename>]
-[B<-out filename>]
-[B<-pass arg>]
-[B<-e>]
-[B<-d>]
-[B<-a>]
-[B<-base64>]
-[B<-A>]
-[B<-k password>]
-[B<-kfile filename>]
-[B<-K key>]
-[B<-iv IV>]
-[B<-S salt>]
-[B<-salt>]
-[B<-nosalt>]
-[B<-z>]
-[B<-md digest>]
-[B<-iter count>]
-[B<-pbkdf2>]
-[B<-p>]
-[B<-P>]
-[B<-bufsize number>]
-[B<-nopad>]
-[B<-debug>]
-[B<-none>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-engine id>]
-
-B<openssl> I<[cipher]> [B<...>]
-
-=head1 DESCRIPTION
-
-The symmetric cipher commands allow data to be encrypted or decrypted
-using various block and stream ciphers using keys based on passwords
-or explicitly provided. Base64 encoding or decoding can also be performed
-either by itself or in addition to the encryption or decryption.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-list>
-
-List all supported ciphers.
-
-=item B<-ciphers>
-
-Alias of -list to display all supported ciphers.
-
-=item B<-in filename>
-
-The input filename, standard input by default.
-
-=item B<-out filename>
-
-The output filename, standard output by default.
-
-=item B<-pass arg>
-
-The password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-e>
-
-Encrypt the input data: this is the default.
-
-=item B<-d>
-
-Decrypt the input data.
-
-=item B<-a>
-
-Base64 process the data. This means that if encryption is taking place
-the data is base64 encoded after encryption. If decryption is set then
-the input data is base64 decoded before being decrypted.
-
-=item B<-base64>
-
-Same as B<-a>
-
-=item B<-A>
-
-If the B<-a> option is set then base64 process the data on one line.
-
-=item B<-k password>
-
-The password to derive the key from. This is for compatibility with previous
-versions of OpenSSL. Superseded by the B<-pass> argument.
-
-=item B<-kfile filename>
-
-Read the password to derive the key from the first line of B<filename>.
-This is for compatibility with previous versions of OpenSSL. Superseded by
-the B<-pass> argument.
-
-=item B<-md digest>
-
-Use the specified digest to create the key from the passphrase.
-The default algorithm is sha-256.
-
-=item B<-iter count>
-
-Use a given number of iterations on the password in deriving the encryption key.
-High values increase the time required to brute-force the resulting file.
-This option enables the use of PBKDF2 algorithm to derive the key.
-
-=item B<-pbkdf2>
-
-Use PBKDF2 algorithm with default iteration count unless otherwise specified.
-
-=item B<-nosalt>
-
-Don't use a salt in the key derivation routines. This option B<SHOULD NOT> be
-used except for test purposes or compatibility with ancient versions of
-OpenSSL.
-
-=item B<-salt>
-
-Use salt (randomly generated or provide with B<-S> option) when
-encrypting, this is the default.
-
-=item B<-S salt>
-
-The actual salt to use: this must be represented as a string of hex digits.
-
-=item B<-K key>
-
-The actual key to use: this must be represented as a string comprised only
-of hex digits. If only the key is specified, the IV must additionally specified
-using the B<-iv> option. When both a key and a password are specified, the
-key given with the B<-K> option will be used and the IV generated from the
-password will be taken. It does not make much sense to specify both key
-and password.
-
-=item B<-iv IV>
-
-The actual IV to use: this must be represented as a string comprised only
-of hex digits. When only the key is specified using the B<-K> option, the
-IV must explicitly be defined. When a password is being specified using
-one of the other options, the IV is generated from this password.
-
-=item B<-p>
-
-Print out the key and IV used.
-
-=item B<-P>
-
-Print out the key and IV used then immediately exit: don't do any encryption
-or decryption.
-
-=item B<-bufsize number>
-
-Set the buffer size for I/O.
-
-=item B<-nopad>
-
-Disable standard block padding.
-
-=item B<-debug>
-
-Debug the BIOs used for I/O.
-
-=item B<-z>
-
-Compress or decompress encrypted data using zlib after encryption or before
-decryption. This option exists only if OpenSSL was compiled with the zlib
-or zlib-dynamic option.
-
-=item B<-none>
-
-Use NULL cipher (no encryption or decryption of input).
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=back
-
-=head1 NOTES
-
-The program can be called either as B<openssl cipher> or
-B<openssl enc -cipher>. The first form doesn't work with
-engine-provided ciphers, because this form is processed before the
-configuration file is read and any ENGINEs loaded.
-Use the B<list> command to get a list of supported ciphers.
-
-Engines which provide entirely new encryption algorithms (such as the ccgost
-engine which provides gost89 algorithm) should be configured in the
-configuration file. Engines specified on the command line using -engine
-options can only be used for hardware-assisted implementations of
-ciphers which are supported by the OpenSSL core or another engine specified
-in the configuration file.
-
-When the enc command lists supported ciphers, ciphers provided by engines,
-specified in the configuration files are listed too.
-
-A password will be prompted for to derive the key and IV if necessary.
-
-The B<-salt> option should B<ALWAYS> be used if the key is being derived
-from a password unless you want compatibility with previous versions of
-OpenSSL.
-
-Without the B<-salt> option it is possible to perform efficient dictionary
-attacks on the password and to attack stream cipher encrypted data. The reason
-for this is that without the salt the same password always generates the same
-encryption key. When the salt is being used the first eight bytes of the
-encrypted data are reserved for the salt: it is generated at random when
-encrypting a file and read from the encrypted file when it is decrypted.
-
-Some of the ciphers do not have large keys and others have security
-implications if not used correctly. A beginner is advised to just use
-a strong block cipher, such as AES, in CBC mode.
-
-All the block ciphers normally use PKCS#5 padding, also known as standard
-block padding. This allows a rudimentary integrity or password check to
-be performed. However, since the chance of random data passing the test
-is better than 1 in 256 it isn't a very good test.
-
-If padding is disabled then the input data must be a multiple of the cipher
-block length.
-
-All RC2 ciphers have the same key and effective key length.
-
-Blowfish and RC5 algorithms use a 128 bit key.
-
-=head1 SUPPORTED CIPHERS
-
-Note that some of these ciphers can be disabled at compile time
-and some are available only if an appropriate engine is configured
-in the configuration file. The output of the B<enc> command run with
-the B<-ciphers> option (that is B<openssl enc -ciphers>) produces a
-list of ciphers, supported by your version of OpenSSL, including
-ones provided by configured engines.
-
-The B<enc> program does not support authenticated encryption modes
-like CCM and GCM, and will not support such modes in the future.
-The B<enc> interface by necessity must begin streaming output (e.g.,
-to standard output when B<-out> is not used) before the authentication
-tag could be validated, leading to the usage of B<enc> in pipelines
-that begin processing untrusted data and are not capable of rolling
-back upon authentication failure. The AEAD modes currently in common
-use also suffer from catastrophic failure of confidentiality and/or
-integrity upon reuse of key/iv/nonce, and since B<enc> places the
-entire burden of key/iv/nonce management upon the user, the risk of
-exposing AEAD modes is too great to allow. These key/iv/nonce
-management issues also affect other modes currently exposed in B<enc>,
-but the failure modes are less extreme in these cases, and the
-functionality cannot be removed with a stable release branch.
-For bulk encryption of data, whether using authenticated encryption
-modes or other modes, L<cms(1)> is recommended, as it provides a
-standard data format and performs the needed key/iv/nonce management.
-
-
- base64 Base 64
-
- bf-cbc Blowfish in CBC mode
- bf Alias for bf-cbc
- blowfish Alias for bf-cbc
- bf-cfb Blowfish in CFB mode
- bf-ecb Blowfish in ECB mode
- bf-ofb Blowfish in OFB mode
-
- cast-cbc CAST in CBC mode
- cast Alias for cast-cbc
- cast5-cbc CAST5 in CBC mode
- cast5-cfb CAST5 in CFB mode
- cast5-ecb CAST5 in ECB mode
- cast5-ofb CAST5 in OFB mode
-
- chacha20 ChaCha20 algorithm
-
- des-cbc DES in CBC mode
- des Alias for des-cbc
- des-cfb DES in CFB mode
- des-ofb DES in OFB mode
- des-ecb DES in ECB mode
-
- des-ede-cbc Two key triple DES EDE in CBC mode
- des-ede Two key triple DES EDE in ECB mode
- des-ede-cfb Two key triple DES EDE in CFB mode
- des-ede-ofb Two key triple DES EDE in OFB mode
-
- des-ede3-cbc Three key triple DES EDE in CBC mode
- des-ede3 Three key triple DES EDE in ECB mode
- des3 Alias for des-ede3-cbc
- des-ede3-cfb Three key triple DES EDE CFB mode
- des-ede3-ofb Three key triple DES EDE in OFB mode
-
- desx DESX algorithm.
-
- gost89 GOST 28147-89 in CFB mode (provided by ccgost engine)
- gost89-cnt `GOST 28147-89 in CNT mode (provided by ccgost engine)
-
- idea-cbc IDEA algorithm in CBC mode
- idea same as idea-cbc
- idea-cfb IDEA in CFB mode
- idea-ecb IDEA in ECB mode
- idea-ofb IDEA in OFB mode
-
- rc2-cbc 128 bit RC2 in CBC mode
- rc2 Alias for rc2-cbc
- rc2-cfb 128 bit RC2 in CFB mode
- rc2-ecb 128 bit RC2 in ECB mode
- rc2-ofb 128 bit RC2 in OFB mode
- rc2-64-cbc 64 bit RC2 in CBC mode
- rc2-40-cbc 40 bit RC2 in CBC mode
-
- rc4 128 bit RC4
- rc4-64 64 bit RC4
- rc4-40 40 bit RC4
-
- rc5-cbc RC5 cipher in CBC mode
- rc5 Alias for rc5-cbc
- rc5-cfb RC5 cipher in CFB mode
- rc5-ecb RC5 cipher in ECB mode
- rc5-ofb RC5 cipher in OFB mode
-
- seed-cbc SEED cipher in CBC mode
- seed Alias for seed-cbc
- seed-cfb SEED cipher in CFB mode
- seed-ecb SEED cipher in ECB mode
- seed-ofb SEED cipher in OFB mode
-
- sm4-cbc SM4 cipher in CBC mode
- sm4 Alias for sm4-cbc
- sm4-cfb SM4 cipher in CFB mode
- sm4-ctr SM4 cipher in CTR mode
- sm4-ecb SM4 cipher in ECB mode
- sm4-ofb SM4 cipher in OFB mode
-
- aes-[128|192|256]-cbc 128/192/256 bit AES in CBC mode
- aes[128|192|256] Alias for aes-[128|192|256]-cbc
- aes-[128|192|256]-cfb 128/192/256 bit AES in 128 bit CFB mode
- aes-[128|192|256]-cfb1 128/192/256 bit AES in 1 bit CFB mode
- aes-[128|192|256]-cfb8 128/192/256 bit AES in 8 bit CFB mode
- aes-[128|192|256]-ctr 128/192/256 bit AES in CTR mode
- aes-[128|192|256]-ecb 128/192/256 bit AES in ECB mode
- aes-[128|192|256]-ofb 128/192/256 bit AES in OFB mode
-
- aria-[128|192|256]-cbc 128/192/256 bit ARIA in CBC mode
- aria[128|192|256] Alias for aria-[128|192|256]-cbc
- aria-[128|192|256]-cfb 128/192/256 bit ARIA in 128 bit CFB mode
- aria-[128|192|256]-cfb1 128/192/256 bit ARIA in 1 bit CFB mode
- aria-[128|192|256]-cfb8 128/192/256 bit ARIA in 8 bit CFB mode
- aria-[128|192|256]-ctr 128/192/256 bit ARIA in CTR mode
- aria-[128|192|256]-ecb 128/192/256 bit ARIA in ECB mode
- aria-[128|192|256]-ofb 128/192/256 bit ARIA in OFB mode
-
- camellia-[128|192|256]-cbc 128/192/256 bit Camellia in CBC mode
- camellia[128|192|256] Alias for camellia-[128|192|256]-cbc
- camellia-[128|192|256]-cfb 128/192/256 bit Camellia in 128 bit CFB mode
- camellia-[128|192|256]-cfb1 128/192/256 bit Camellia in 1 bit CFB mode
- camellia-[128|192|256]-cfb8 128/192/256 bit Camellia in 8 bit CFB mode
- camellia-[128|192|256]-ctr 128/192/256 bit Camellia in CTR mode
- camellia-[128|192|256]-ecb 128/192/256 bit Camellia in ECB mode
- camellia-[128|192|256]-ofb 128/192/256 bit Camellia in OFB mode
-
-=head1 EXAMPLES
-
-Just base64 encode a binary file:
-
- openssl base64 -in file.bin -out file.b64
-
-Decode the same file
-
- openssl base64 -d -in file.b64 -out file.bin
-
-Encrypt a file using AES-128 using a prompted password
-and PBKDF2 key derivation:
-
- openssl enc -aes128 -pbkdf2 -in file.txt -out file.aes128
-
-Decrypt a file using a supplied password:
-
- openssl enc -aes128 -pbkdf2 -d -in file.aes128 -out file.txt \
- -pass pass:<password>
-
-Encrypt a file then base64 encode it (so it can be sent via mail for example)
-using AES-256 in CTR mode and PBKDF2 key derivation:
-
- openssl enc -aes-256-ctr -pbkdf2 -a -in file.txt -out file.aes256
-
-Base64 decode a file then decrypt it using a password supplied in a file:
-
- openssl enc -aes-256-ctr -pbkdf2 -d -a -in file.aes256 -out file.txt \
- -pass file:<passfile>
-
-=head1 BUGS
-
-The B<-A> option when used with large files doesn't work properly.
-
-The B<enc> program only supports a fixed number of algorithms with
-certain parameters. So if, for example, you want to use RC2 with a
-76 bit key or RC4 with an 84 bit key you can't use this program.
-
-=head1 HISTORY
-
-The default digest was changed from MD5 to SHA256 in OpenSSL 1.1.0.
-
-The B<-list> option was added in OpenSSL 1.1.1e.
-
-=head1 COPYRIGHT
-
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/engine.pod b/doc/man1/engine.pod
deleted file mode 100644
index d49f04292bfb..000000000000
--- a/doc/man1/engine.pod
+++ /dev/null
@@ -1,119 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-engine,
-engine - load and query engines
-
-=head1 SYNOPSIS
-
-B<openssl engine>
-[ I<engine...> ]
-[B<-v>]
-[B<-vv>]
-[B<-vvv>]
-[B<-vvv>]
-[B<-vvv>]
-[B<-c>]
-[B<-t>]
-[B<-tt>]
-[B<-pre> I<command>]
-[B<-post> I<command>]
-[ I<engine...> ]
-
-=head1 DESCRIPTION
-
-The B<engine> command is used to query the status and capabilities
-of the specified B<engine>'s.
-Engines may be specified before and after all other command-line flags.
-Only those specified are queried.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-v> B<-vv> B<-vvv> B<-vvvv>
-
-Provides information about each specified engine. The first flag lists
-all the possible run-time control commands; the second adds a
-description of each command; the third adds the input flags, and the
-final option adds the internal input flags.
-
-=item B<-c>
-
-Lists the capabilities of each engine.
-
-=item B<-t>
-
-Tests if each specified engine is available, and displays the answer.
-
-=item B<-tt>
-
-Displays an error trace for any unavailable engine.
-
-=item B<-pre> I<command>
-
-=item B<-post> I<command>
-
-Command-line configuration of engines.
-The B<-pre> command is given to the engine before it is loaded and
-the B<-post> command is given after the engine is loaded.
-The I<command> is of the form I<cmd:val> where I<cmd> is the command,
-and I<val> is the value for the command.
-See the example below.
-
-=back
-
-=head1 EXAMPLES
-
-To list all the commands available to a dynamic engine:
-
- $ openssl engine -t -tt -vvvv dynamic
- (dynamic) Dynamic engine loading support
- [ unavailable ]
- SO_PATH: Specifies the path to the new ENGINE shared library
- (input flags): STRING
- NO_VCHECK: Specifies to continue even if version checking fails (boolean)
- (input flags): NUMERIC
- ID: Specifies an ENGINE id name for loading
- (input flags): STRING
- LIST_ADD: Whether to add a loaded ENGINE to the internal list (0=no,1=yes,2=mandatory)
- (input flags): NUMERIC
- DIR_LOAD: Specifies whether to load from 'DIR_ADD' directories (0=no,1=yes,2=mandatory)
- (input flags): NUMERIC
- DIR_ADD: Adds a directory from which ENGINEs can be loaded
- (input flags): STRING
- LOAD: Load up the ENGINE specified by other settings
- (input flags): NO_INPUT
-
-To list the capabilities of the I<rsax> engine:
-
- $ openssl engine -c
- (rsax) RSAX engine support
- [RSA]
- (dynamic) Dynamic engine loading support
-
-=head1 ENVIRONMENT
-
-=over 4
-
-=item B<OPENSSL_ENGINES>
-
-The path to the engines directory.
-
-=back
-
-=head1 SEE ALSO
-
-L<config(5)>
-
-=head1 COPYRIGHT
-
-Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/errstr.pod b/doc/man1/errstr.pod
deleted file mode 100644
index 94198c123ea6..000000000000
--- a/doc/man1/errstr.pod
+++ /dev/null
@@ -1,46 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-errstr,
-errstr - lookup error codes
-
-=head1 SYNOPSIS
-
-B<openssl errstr error_code>
-
-=head1 DESCRIPTION
-
-Sometimes an application will not load error message and only
-numerical forms will be available. The B<errstr> utility can be used to
-display the meaning of the hex code. The hex code is the hex digits after the
-second colon.
-
-=head1 OPTIONS
-
-None.
-
-=head1 EXAMPLES
-
-The error code:
-
- 27594:error:2006D080:lib(32):func(109):reason(128):bss_file.c:107:
-
-can be displayed with:
-
- openssl errstr 2006D080
-
-to produce the error message:
-
- error:2006D080:BIO routines:BIO_new_file:no such file
-
-=head1 COPYRIGHT
-
-Copyright 2004-2019 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/gendsa.pod b/doc/man1/gendsa.pod
deleted file mode 100644
index b2580b4f0378..000000000000
--- a/doc/man1/gendsa.pod
+++ /dev/null
@@ -1,101 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-gendsa,
-gendsa - generate a DSA private key from a set of parameters
-
-=head1 SYNOPSIS
-
-B<openssl> B<gendsa>
-[B<-help>]
-[B<-out filename>]
-[B<-aes128>]
-[B<-aes192>]
-[B<-aes256>]
-[B<-aria128>]
-[B<-aria192>]
-[B<-aria256>]
-[B<-camellia128>]
-[B<-camellia192>]
-[B<-camellia256>]
-[B<-des>]
-[B<-des3>]
-[B<-idea>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-engine id>]
-[B<paramfile>]
-
-=head1 DESCRIPTION
-
-The B<gendsa> command generates a DSA private key from a DSA parameter file
-(which will be typically generated by the B<openssl dsaparam> command).
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-out filename>
-
-Output the key to the specified file. If this argument is not specified then
-standard output is used.
-
-=item B<-aes128>, B<-aes192>, B<-aes256>, B<-aria128>, B<-aria192>, B<-aria256>, B<-camellia128>, B<-camellia192>, B<-camellia256>, B<-des>, B<-des3>, B<-idea>
-
-These options encrypt the private key with specified
-cipher before outputting it. A pass phrase is prompted for.
-If none of these options is specified no encryption is used.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<gendsa>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=item B<paramfile>
-
-This option specifies the DSA parameter file to use. The parameters in this
-file determine the size of the private key. DSA parameters can be generated
-and examined using the B<openssl dsaparam> command.
-
-=back
-
-=head1 NOTES
-
-DSA key generation is little more than random number generation so it is
-much quicker that RSA key generation for example.
-
-=head1 SEE ALSO
-
-L<dsaparam(1)>, L<dsa(1)>, L<genrsa(1)>,
-L<rsa(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/genpkey.pod b/doc/man1/genpkey.pod
deleted file mode 100644
index 6a681ef3d219..000000000000
--- a/doc/man1/genpkey.pod
+++ /dev/null
@@ -1,335 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-genpkey,
-genpkey - generate a private key
-
-=head1 SYNOPSIS
-
-B<openssl> B<genpkey>
-[B<-help>]
-[B<-out filename>]
-[B<-outform PEM|DER>]
-[B<-pass arg>]
-[B<-I<cipher>>]
-[B<-engine id>]
-[B<-paramfile file>]
-[B<-algorithm alg>]
-[B<-pkeyopt opt:value>]
-[B<-genparam>]
-[B<-text>]
-
-=head1 DESCRIPTION
-
-The B<genpkey> command generates a private key.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-out filename>
-
-Output the key to the specified file. If this argument is not specified then
-standard output is used.
-
-=item B<-outform DER|PEM>
-
-This specifies the output format DER or PEM. The default format is PEM.
-
-=item B<-pass arg>
-
-The output file password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-I<cipher>>
-
-This option encrypts the private key with the supplied cipher. Any algorithm
-name accepted by EVP_get_cipherbyname() is acceptable such as B<des3>.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<genpkey>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms. If used this option should precede all other
-options.
-
-=item B<-algorithm alg>
-
-Public key algorithm to use such as RSA, DSA or DH. If used this option must
-precede any B<-pkeyopt> options. The options B<-paramfile> and B<-algorithm>
-are mutually exclusive. Engines may add algorithms in addition to the standard
-built-in ones.
-
-Valid built-in algorithm names for private key generation are RSA, RSA-PSS, EC,
-X25519, X448, ED25519 and ED448.
-
-Valid built-in algorithm names for parameter generation (see the B<-genparam>
-option) are DH, DSA and EC.
-
-Note that the algorithm name X9.42 DH may be used as a synonym for the DH
-algorithm. These are identical and do not indicate the type of parameters that
-will be generated. Use the B<dh_paramgen_type> option to indicate whether PKCS#3
-or X9.42 DH parameters are required. See L<DH Parameter Generation Options>
-below for more details.
-
-=item B<-pkeyopt opt:value>
-
-Set the public key algorithm option B<opt> to B<value>. The precise set of
-options supported depends on the public key algorithm used and its
-implementation. See L<KEY GENERATION OPTIONS> and
-L<PARAMETER GENERATION OPTIONS> below for more details.
-
-=item B<-genparam>
-
-Generate a set of parameters instead of a private key. If used this option must
-precede any B<-algorithm>, B<-paramfile> or B<-pkeyopt> options.
-
-=item B<-paramfile filename>
-
-Some public key algorithms generate a private key based on a set of parameters.
-They can be supplied using this option. If this option is used the public key
-algorithm used is determined by the parameters. If used this option must
-precede any B<-pkeyopt> options. The options B<-paramfile> and B<-algorithm>
-are mutually exclusive.
-
-=item B<-text>
-
-Print an (unencrypted) text representation of private and public keys and
-parameters along with the PEM or DER structure.
-
-=back
-
-=head1 KEY GENERATION OPTIONS
-
-The options supported by each algorithm and indeed each implementation of an
-algorithm can vary. The options for the OpenSSL implementations are detailed
-below. There are no key generation options defined for the X25519, X448, ED25519
-or ED448 algorithms.
-
-=head2 RSA Key Generation Options
-
-=over 4
-
-=item B<rsa_keygen_bits:numbits>
-
-The number of bits in the generated key. If not specified 2048 is used.
-
-=item B<rsa_keygen_primes:numprimes>
-
-The number of primes in the generated key. If not specified 2 is used.
-
-=item B<rsa_keygen_pubexp:value>
-
-The RSA public exponent value. This can be a large decimal or
-hexadecimal value if preceded by B<0x>. Default value is 65537.
-
-=back
-
-=head2 RSA-PSS Key Generation Options
-
-Note: by default an B<RSA-PSS> key has no parameter restrictions.
-
-=over 4
-
-=item B<rsa_keygen_bits:numbits>, B<rsa_keygen_primes:numprimes>, B<rsa_keygen_pubexp:value>
-
-These options have the same meaning as the B<RSA> algorithm.
-
-=item B<rsa_pss_keygen_md:digest>
-
-If set the key is restricted and can only use B<digest> for signing.
-
-=item B<rsa_pss_keygen_mgf1_md:digest>
-
-If set the key is restricted and can only use B<digest> as it's MGF1
-parameter.
-
-=item B<rsa_pss_keygen_saltlen:len>
-
-If set the key is restricted and B<len> specifies the minimum salt length.
-
-=back
-
-=head2 EC Key Generation Options
-
-The EC key generation options can also be used for parameter generation.
-
-=over 4
-
-=item B<ec_paramgen_curve:curve>
-
-The EC curve to use. OpenSSL supports NIST curve names such as "P-256".
-
-=item B<ec_param_enc:encoding>
-
-The encoding to use for parameters. The "encoding" parameter must be either
-"named_curve" or "explicit". The default value is "named_curve".
-
-=back
-
-=head1 PARAMETER GENERATION OPTIONS
-
-The options supported by each algorithm and indeed each implementation of an
-algorithm can vary. The options for the OpenSSL implementations are detailed
-below.
-
-=head2 DSA Parameter Generation Options
-
-=over 4
-
-=item B<dsa_paramgen_bits:numbits>
-
-The number of bits in the generated prime. If not specified 2048 is used.
-
-=item B<dsa_paramgen_q_bits:numbits>
-
-The number of bits in the q parameter. Must be one of 160, 224 or 256. If not
-specified 224 is used.
-
-=item B<dsa_paramgen_md:digest>
-
-The digest to use during parameter generation. Must be one of B<sha1>, B<sha224>
-or B<sha256>. If set, then the number of bits in B<q> will match the output size
-of the specified digest and the B<dsa_paramgen_q_bits> parameter will be
-ignored. If not set, then a digest will be used that gives an output matching
-the number of bits in B<q>, i.e. B<sha1> if q length is 160, B<sha224> if it 224
-or B<sha256> if it is 256.
-
-=back
-
-=head2 DH Parameter Generation Options
-
-=over 4
-
-=item B<dh_paramgen_prime_len:numbits>
-
-The number of bits in the prime parameter B<p>. The default is 2048.
-
-=item B<dh_paramgen_subprime_len:numbits>
-
-The number of bits in the sub prime parameter B<q>. The default is 256 if the
-prime is at least 2048 bits long or 160 otherwise. Only relevant if used in
-conjunction with the B<dh_paramgen_type> option to generate X9.42 DH parameters.
-
-=item B<dh_paramgen_generator:value>
-
-The value to use for the generator B<g>. The default is 2.
-
-=item B<dh_paramgen_type:value>
-
-The type of DH parameters to generate. Use 0 for PKCS#3 DH and 1 for X9.42 DH.
-The default is 0.
-
-=item B<dh_rfc5114:num>
-
-If this option is set, then the appropriate RFC5114 parameters are used
-instead of generating new parameters. The value B<num> can take the
-values 1, 2 or 3 corresponding to RFC5114 DH parameters consisting of
-1024 bit group with 160 bit subgroup, 2048 bit group with 224 bit subgroup
-and 2048 bit group with 256 bit subgroup as mentioned in RFC5114 sections
-2.1, 2.2 and 2.3 respectively. If present this overrides all other DH parameter
-options.
-
-=back
-
-=head2 EC Parameter Generation Options
-
-The EC parameter generation options are the same as for key generation. See
-L<EC Key Generation Options> above.
-
-=head1 NOTES
-
-The use of the genpkey program is encouraged over the algorithm specific
-utilities because additional algorithm options and ENGINE provided algorithms
-can be used.
-
-=head1 EXAMPLES
-
-Generate an RSA private key using default parameters:
-
- openssl genpkey -algorithm RSA -out key.pem
-
-Encrypt output private key using 128 bit AES and the passphrase "hello":
-
- openssl genpkey -algorithm RSA -out key.pem -aes-128-cbc -pass pass:hello
-
-Generate a 2048 bit RSA key using 3 as the public exponent:
-
- openssl genpkey -algorithm RSA -out key.pem \
- -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:3
-
-Generate 2048 bit DSA parameters:
-
- openssl genpkey -genparam -algorithm DSA -out dsap.pem \
- -pkeyopt dsa_paramgen_bits:2048
-
-Generate DSA key from parameters:
-
- openssl genpkey -paramfile dsap.pem -out dsakey.pem
-
-Generate 2048 bit DH parameters:
-
- openssl genpkey -genparam -algorithm DH -out dhp.pem \
- -pkeyopt dh_paramgen_prime_len:2048
-
-Generate 2048 bit X9.42 DH parameters:
-
- openssl genpkey -genparam -algorithm DH -out dhpx.pem \
- -pkeyopt dh_paramgen_prime_len:2048 \
- -pkeyopt dh_paramgen_type:1
-
-Output RFC5114 2048 bit DH parameters with 224 bit subgroup:
-
- openssl genpkey -genparam -algorithm DH -out dhp.pem -pkeyopt dh_rfc5114:2
-
-Generate DH key from parameters:
-
- openssl genpkey -paramfile dhp.pem -out dhkey.pem
-
-Generate EC parameters:
-
- openssl genpkey -genparam -algorithm EC -out ecp.pem \
- -pkeyopt ec_paramgen_curve:secp384r1 \
- -pkeyopt ec_param_enc:named_curve
-
-Generate EC key from parameters:
-
- openssl genpkey -paramfile ecp.pem -out eckey.pem
-
-Generate EC key directly:
-
- openssl genpkey -algorithm EC -out eckey.pem \
- -pkeyopt ec_paramgen_curve:P-384 \
- -pkeyopt ec_param_enc:named_curve
-
-Generate an X25519 private key:
-
- openssl genpkey -algorithm X25519 -out xkey.pem
-
-Generate an ED448 private key:
-
- openssl genpkey -algorithm ED448 -out xkey.pem
-
-=head1 HISTORY
-
-The ability to use NIST curve names, and to generate an EC key directly,
-were added in OpenSSL 1.0.2.
-The ability to generate X25519 keys was added in OpenSSL 1.1.0.
-The ability to generate X448, ED25519 and ED448 keys was added in OpenSSL 1.1.1.
-
-=head1 COPYRIGHT
-
-Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/genrsa.pod b/doc/man1/genrsa.pod
deleted file mode 100644
index 8bd3799ea926..000000000000
--- a/doc/man1/genrsa.pod
+++ /dev/null
@@ -1,128 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-genrsa,
-genrsa - generate an RSA private key
-
-=head1 SYNOPSIS
-
-B<openssl> B<genrsa>
-[B<-help>]
-[B<-out filename>]
-[B<-passout arg>]
-[B<-aes128>]
-[B<-aes192>]
-[B<-aes256>]
-[B<-aria128>]
-[B<-aria192>]
-[B<-aria256>]
-[B<-camellia128>]
-[B<-camellia192>]
-[B<-camellia256>]
-[B<-des>]
-[B<-des3>]
-[B<-idea>]
-[B<-f4>]
-[B<-3>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-engine id>]
-[B<-primes num>]
-[B<numbits>]
-
-=head1 DESCRIPTION
-
-The B<genrsa> command generates an RSA private key.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-out filename>
-
-Output the key to the specified file. If this argument is not specified then
-standard output is used.
-
-=item B<-passout arg>
-
-The output file password source. For more information about the format
-of B<arg> see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-aes128>, B<-aes192>, B<-aes256>, B<-aria128>, B<-aria192>, B<-aria256>, B<-camellia128>, B<-camellia192>, B<-camellia256>, B<-des>, B<-des3>, B<-idea>
-
-These options encrypt the private key with specified
-cipher before outputting it. If none of these options is
-specified no encryption is used. If encryption is used a pass phrase is prompted
-for if it is not supplied via the B<-passout> argument.
-
-=item B<-F4|-3>
-
-The public exponent to use, either 65537 or 3. The default is 65537.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<genrsa>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=item B<-primes num>
-
-Specify the number of primes to use while generating the RSA key. The B<num>
-parameter must be a positive integer that is greater than 1 and less than 16.
-If B<num> is greater than 2, then the generated key is called a 'multi-prime'
-RSA key, which is defined in RFC 8017.
-
-=item B<numbits>
-
-The size of the private key to generate in bits. This must be the last option
-specified. The default is 2048 and values less than 512 are not allowed.
-
-=back
-
-=head1 NOTES
-
-RSA private key generation essentially involves the generation of two or more
-prime numbers. When generating a private key various symbols will be output to
-indicate the progress of the generation. A B<.> represents each number which
-has passed an initial sieve test, B<+> means a number has passed a single
-round of the Miller-Rabin primality test, B<*> means the current prime starts
-a regenerating progress due to some failed tests. A newline means that the number
-has passed all the prime tests (the actual number depends on the key size).
-
-Because key generation is a random process the time taken to generate a key
-may vary somewhat. But in general, more primes lead to less generation time
-of a key.
-
-=head1 SEE ALSO
-
-L<gendsa(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/list.pod b/doc/man1/list.pod
deleted file mode 100644
index bed39b0c7c93..000000000000
--- a/doc/man1/list.pod
+++ /dev/null
@@ -1,94 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-list,
-list - list algorithms and features
-
-=head1 SYNOPSIS
-
-B<openssl list>
-[B<-help>]
-[B<-1>]
-[B<-commands>]
-[B<-digest-commands>]
-[B<-digest-algorithms>]
-[B<-cipher-commands>]
-[B<-cipher-algorithms>]
-[B<-public-key-algorithms>]
-[B<-public-key-methods>]
-[B<-disabled>]
-
-=head1 DESCRIPTION
-
-This command is used to generate list of algorithms or disabled
-features.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Display a usage message.
-
-=item B<-1>
-
-List the commands, digest-commands, or cipher-commands in a single column.
-If used, this option must be given first.
-
-=item B<-commands>
-
-Display a list of standard commands.
-
-=item B<-digest-commands>
-
-Display a list of message digest commands, which are typically used
-as input to the L<dgst(1)> or L<speed(1)> commands.
-
-=item B<-digest-algorithms>
-
-Display a list of message digest algorithms.
-If a line is of the form
- foo => bar
-then B<foo> is an alias for the official algorithm name, B<bar>.
-
-=item B<-cipher-commands>
-
-Display a list of cipher commands, which are typically used as input
-to the L<dgst(1)> or L<speed(1)> commands.
-
-=item B<-cipher-algorithms>
-
-Display a list of cipher algorithms.
-If a line is of the form
- foo => bar
-then B<foo> is an alias for the official algorithm name, B<bar>.
-
-=item B<-public-key-algorithms>
-
-Display a list of public key algorithms, with each algorithm as
-a block of multiple lines, all but the first are indented.
-
-=item B<-public-key-methods>
-
-Display a list of public key method OIDs: this also includes public key methods
-without an associated ASN.1 method, for example, KDF algorithms.
-
-=item B<-disabled>
-
-Display a list of disabled features, those that were compiled out
-of the installation.
-
-=back
-
-=head1 COPYRIGHT
-
-Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/nseq.pod b/doc/man1/nseq.pod
deleted file mode 100644
index 7d5f009aa21b..000000000000
--- a/doc/man1/nseq.pod
+++ /dev/null
@@ -1,85 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-nseq,
-nseq - create or examine a Netscape certificate sequence
-
-=head1 SYNOPSIS
-
-B<openssl> B<nseq>
-[B<-help>]
-[B<-in filename>]
-[B<-out filename>]
-[B<-toseq>]
-
-=head1 DESCRIPTION
-
-The B<nseq> command takes a file containing a Netscape certificate
-sequence and prints out the certificates contained in it or takes a
-file of certificates and converts it into a Netscape certificate
-sequence.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-in filename>
-
-This specifies the input filename to read or standard input if this
-option is not specified.
-
-=item B<-out filename>
-
-Specifies the output filename or standard output by default.
-
-=item B<-toseq>
-
-Normally a Netscape certificate sequence will be input and the output
-is the certificates contained in it. With the B<-toseq> option the
-situation is reversed: a Netscape certificate sequence is created from
-a file of certificates.
-
-=back
-
-=head1 EXAMPLES
-
-Output the certificates in a Netscape certificate sequence
-
- openssl nseq -in nseq.pem -out certs.pem
-
-Create a Netscape certificate sequence
-
- openssl nseq -in certs.pem -toseq -out nseq.pem
-
-=head1 NOTES
-
-The B<PEM> encoded form uses the same headers and footers as a certificate:
-
- -----BEGIN CERTIFICATE-----
- -----END CERTIFICATE-----
-
-A Netscape certificate sequence is a Netscape specific format that can be sent
-to browsers as an alternative to the standard PKCS#7 format when several
-certificates are sent to the browser: for example during certificate enrollment.
-It is used by Netscape certificate server for example.
-
-=head1 BUGS
-
-This program needs a few more options: like allowing DER or PEM input and
-output files and allowing multiple certificate files to be used.
-
-=head1 COPYRIGHT
-
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/ocsp.pod b/doc/man1/ocsp.pod
deleted file mode 100644
index 1f724b42bde4..000000000000
--- a/doc/man1/ocsp.pod
+++ /dev/null
@@ -1,500 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-ocsp,
-ocsp - Online Certificate Status Protocol utility
-
-=head1 SYNOPSIS
-
-B<openssl> B<ocsp>
-[B<-help>]
-[B<-out file>]
-[B<-issuer file>]
-[B<-cert file>]
-[B<-serial n>]
-[B<-signer file>]
-[B<-signkey file>]
-[B<-sign_other file>]
-[B<-no_certs>]
-[B<-req_text>]
-[B<-resp_text>]
-[B<-text>]
-[B<-reqout file>]
-[B<-respout file>]
-[B<-reqin file>]
-[B<-respin file>]
-[B<-nonce>]
-[B<-no_nonce>]
-[B<-url URL>]
-[B<-host host:port>]
-[B<-multi process-count>]
-[B<-header>]
-[B<-path>]
-[B<-CApath dir>]
-[B<-CAfile file>]
-[B<-no-CAfile>]
-[B<-no-CApath>]
-[B<-attime timestamp>]
-[B<-check_ss_sig>]
-[B<-crl_check>]
-[B<-crl_check_all>]
-[B<-explicit_policy>]
-[B<-extended_crl>]
-[B<-ignore_critical>]
-[B<-inhibit_any>]
-[B<-inhibit_map>]
-[B<-no_check_time>]
-[B<-partial_chain>]
-[B<-policy arg>]
-[B<-policy_check>]
-[B<-policy_print>]
-[B<-purpose purpose>]
-[B<-suiteB_128>]
-[B<-suiteB_128_only>]
-[B<-suiteB_192>]
-[B<-trusted_first>]
-[B<-no_alt_chains>]
-[B<-use_deltas>]
-[B<-auth_level num>]
-[B<-verify_depth num>]
-[B<-verify_email email>]
-[B<-verify_hostname hostname>]
-[B<-verify_ip ip>]
-[B<-verify_name name>]
-[B<-x509_strict>]
-[B<-VAfile file>]
-[B<-validity_period n>]
-[B<-status_age n>]
-[B<-noverify>]
-[B<-verify_other file>]
-[B<-trust_other>]
-[B<-no_intern>]
-[B<-no_signature_verify>]
-[B<-no_cert_verify>]
-[B<-no_chain>]
-[B<-no_cert_checks>]
-[B<-no_explicit>]
-[B<-port num>]
-[B<-ignore_err>]
-[B<-index file>]
-[B<-CA file>]
-[B<-rsigner file>]
-[B<-rkey file>]
-[B<-rother file>]
-[B<-rsigopt nm:v>]
-[B<-resp_no_certs>]
-[B<-nmin n>]
-[B<-ndays n>]
-[B<-resp_key_id>]
-[B<-nrequest n>]
-[B<-I<digest>>]
-
-=head1 DESCRIPTION
-
-The Online Certificate Status Protocol (OCSP) enables applications to
-determine the (revocation) state of an identified certificate (RFC 2560).
-
-The B<ocsp> command performs many common OCSP tasks. It can be used
-to print out requests and responses, create requests and send queries
-to an OCSP responder and behave like a mini OCSP server itself.
-
-=head1 OPTIONS
-
-This command operates as either a client or a server.
-The options are described below, divided into those two modes.
-
-=head2 OCSP Client Options
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-out filename>
-
-specify output filename, default is standard output.
-
-=item B<-issuer filename>
-
-This specifies the current issuer certificate. This option can be used
-multiple times. The certificate specified in B<filename> must be in
-PEM format. This option B<MUST> come before any B<-cert> options.
-
-=item B<-cert filename>
-
-Add the certificate B<filename> to the request. The issuer certificate
-is taken from the previous B<issuer> option, or an error occurs if no
-issuer certificate is specified.
-
-=item B<-serial num>
-
-Same as the B<cert> option except the certificate with serial number
-B<num> is added to the request. The serial number is interpreted as a
-decimal integer unless preceded by B<0x>. Negative integers can also
-be specified by preceding the value by a B<-> sign.
-
-=item B<-signer filename>, B<-signkey filename>
-
-Sign the OCSP request using the certificate specified in the B<signer>
-option and the private key specified by the B<signkey> option. If
-the B<signkey> option is not present then the private key is read
-from the same file as the certificate. If neither option is specified then
-the OCSP request is not signed.
-
-=item B<-sign_other filename>
-
-Additional certificates to include in the signed request.
-
-=item B<-nonce>, B<-no_nonce>
-
-Add an OCSP nonce extension to a request or disable OCSP nonce addition.
-Normally if an OCSP request is input using the B<reqin> option no
-nonce is added: using the B<nonce> option will force addition of a nonce.
-If an OCSP request is being created (using B<cert> and B<serial> options)
-a nonce is automatically added specifying B<no_nonce> overrides this.
-
-=item B<-req_text>, B<-resp_text>, B<-text>
-
-Print out the text form of the OCSP request, response or both respectively.
-
-=item B<-reqout file>, B<-respout file>
-
-Write out the DER encoded certificate request or response to B<file>.
-
-=item B<-reqin file>, B<-respin file>
-
-Read OCSP request or response file from B<file>. These option are ignored
-if OCSP request or response creation is implied by other options (for example
-with B<serial>, B<cert> and B<host> options).
-
-=item B<-url responder_url>
-
-Specify the responder URL. Both HTTP and HTTPS (SSL/TLS) URLs can be specified.
-
-=item B<-host hostname:port>, B<-path pathname>
-
-If the B<host> option is present then the OCSP request is sent to the host
-B<hostname> on port B<port>. B<path> specifies the HTTP pathname to use
-or "/" by default. This is equivalent to specifying B<-url> with scheme
-http:// and the given hostname, port, and pathname.
-
-=item B<-header name=value>
-
-Adds the header B<name> with the specified B<value> to the OCSP request
-that is sent to the responder.
-This may be repeated.
-
-=item B<-timeout seconds>
-
-Connection timeout to the OCSP responder in seconds.
-On POSIX systems, when running as an OCSP responder, this option also limits
-the time that the responder is willing to wait for the client request.
-This time is measured from the time the responder accepts the connection until
-the complete request is received.
-
-=item B<-multi process-count>
-
-Run the specified number of OCSP responder child processes, with the parent
-process respawning child processes as needed.
-Child processes will detect changes in the CA index file and automatically
-reload it.
-When running as a responder B<-timeout> option is recommended to limit the time
-each child is willing to wait for the client's OCSP response.
-This option is available on POSIX systems (that support the fork() and other
-required unix system-calls).
-
-=item B<-CAfile file>, B<-CApath pathname>
-
-File or pathname containing trusted CA certificates. These are used to verify
-the signature on the OCSP response.
-
-=item B<-no-CAfile>
-
-Do not load the trusted CA certificates from the default file location
-
-=item B<-no-CApath>
-
-Do not load the trusted CA certificates from the default directory location
-
-=item B<-attime>, B<-check_ss_sig>, B<-crl_check>, B<-crl_check_all>,
-B<-explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,
-B<-inhibit_map>, B<-no_alt_chains>, B<-no_check_time>, B<-partial_chain>, B<-policy>,
-B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,
-B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,
-B<-auth_level>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
-B<-verify_ip>, B<-verify_name>, B<-x509_strict>
-
-Set different certificate verification options.
-See L<verify(1)> manual page for details.
-
-=item B<-verify_other file>
-
-File containing additional certificates to search when attempting to locate
-the OCSP response signing certificate. Some responders omit the actual signer's
-certificate from the response: this option can be used to supply the necessary
-certificate in such cases.
-
-=item B<-trust_other>
-
-The certificates specified by the B<-verify_other> option should be explicitly
-trusted and no additional checks will be performed on them. This is useful
-when the complete responder certificate chain is not available or trusting a
-root CA is not appropriate.
-
-=item B<-VAfile file>
-
-File containing explicitly trusted responder certificates. Equivalent to the
-B<-verify_other> and B<-trust_other> options.
-
-=item B<-noverify>
-
-Don't attempt to verify the OCSP response signature or the nonce
-values. This option will normally only be used for debugging since it
-disables all verification of the responders certificate.
-
-=item B<-no_intern>
-
-Ignore certificates contained in the OCSP response when searching for the
-signers certificate. With this option the signers certificate must be specified
-with either the B<-verify_other> or B<-VAfile> options.
-
-=item B<-no_signature_verify>
-
-Don't check the signature on the OCSP response. Since this option
-tolerates invalid signatures on OCSP responses it will normally only be
-used for testing purposes.
-
-=item B<-no_cert_verify>
-
-Don't verify the OCSP response signers certificate at all. Since this
-option allows the OCSP response to be signed by any certificate it should
-only be used for testing purposes.
-
-=item B<-no_chain>
-
-Do not use certificates in the response as additional untrusted CA
-certificates.
-
-=item B<-no_explicit>
-
-Do not explicitly trust the root CA if it is set to be trusted for OCSP signing.
-
-=item B<-no_cert_checks>
-
-Don't perform any additional checks on the OCSP response signers certificate.
-That is do not make any checks to see if the signers certificate is authorised
-to provide the necessary status information: as a result this option should
-only be used for testing purposes.
-
-=item B<-validity_period nsec>, B<-status_age age>
-
-These options specify the range of times, in seconds, which will be tolerated
-in an OCSP response. Each certificate status response includes a B<notBefore>
-time and an optional B<notAfter> time. The current time should fall between
-these two values, but the interval between the two times may be only a few
-seconds. In practice the OCSP responder and clients clocks may not be precisely
-synchronised and so such a check may fail. To avoid this the
-B<-validity_period> option can be used to specify an acceptable error range in
-seconds, the default value is 5 minutes.
-
-If the B<notAfter> time is omitted from a response then this means that new
-status information is immediately available. In this case the age of the
-B<notBefore> field is checked to see it is not older than B<age> seconds old.
-By default this additional check is not performed.
-
-=item B<-I<digest>>
-
-This option sets digest algorithm to use for certificate identification in the
-OCSP request. Any digest supported by the OpenSSL B<dgst> command can be used.
-The default is SHA-1. This option may be used multiple times to specify the
-digest used by subsequent certificate identifiers.
-
-=back
-
-=head2 OCSP Server Options
-
-=over 4
-
-=item B<-index indexfile>
-
-The B<indexfile> parameter is the name of a text index file in B<ca>
-format containing certificate revocation information.
-
-If the B<index> option is specified the B<ocsp> utility is in responder
-mode, otherwise it is in client mode. The request(s) the responder
-processes can be either specified on the command line (using B<issuer>
-and B<serial> options), supplied in a file (using the B<reqin> option)
-or via external OCSP clients (if B<port> or B<url> is specified).
-
-If the B<index> option is present then the B<CA> and B<rsigner> options
-must also be present.
-
-=item B<-CA file>
-
-CA certificate corresponding to the revocation information in B<indexfile>.
-
-=item B<-rsigner file>
-
-The certificate to sign OCSP responses with.
-
-=item B<-rother file>
-
-Additional certificates to include in the OCSP response.
-
-=item B<-resp_no_certs>
-
-Don't include any certificates in the OCSP response.
-
-=item B<-resp_key_id>
-
-Identify the signer certificate using the key ID, default is to use the
-subject name.
-
-=item B<-rkey file>
-
-The private key to sign OCSP responses with: if not present the file
-specified in the B<rsigner> option is used.
-
-=item B<-rsigopt nm:v>
-
-Pass options to the signature algorithm when signing OCSP responses.
-Names and values of these options are algorithm-specific.
-
-=item B<-port portnum>
-
-Port to listen for OCSP requests on. The port may also be specified
-using the B<url> option.
-
-=item B<-ignore_err>
-
-Ignore malformed requests or responses: When acting as an OCSP client, retry if
-a malformed response is received. When acting as an OCSP responder, continue
-running instead of terminating upon receiving a malformed request.
-
-=item B<-nrequest number>
-
-The OCSP server will exit after receiving B<number> requests, default unlimited.
-
-=item B<-nmin minutes>, B<-ndays days>
-
-Number of minutes or days when fresh revocation information is available:
-used in the B<nextUpdate> field. If neither option is present then the
-B<nextUpdate> field is omitted meaning fresh revocation information is
-immediately available.
-
-=back
-
-=head1 OCSP Response verification.
-
-OCSP Response follows the rules specified in RFC2560.
-
-Initially the OCSP responder certificate is located and the signature on
-the OCSP request checked using the responder certificate's public key.
-
-Then a normal certificate verify is performed on the OCSP responder certificate
-building up a certificate chain in the process. The locations of the trusted
-certificates used to build the chain can be specified by the B<CAfile>
-and B<CApath> options or they will be looked for in the standard OpenSSL
-certificates directory.
-
-If the initial verify fails then the OCSP verify process halts with an
-error.
-
-Otherwise the issuing CA certificate in the request is compared to the OCSP
-responder certificate: if there is a match then the OCSP verify succeeds.
-
-Otherwise the OCSP responder certificate's CA is checked against the issuing
-CA certificate in the request. If there is a match and the OCSPSigning
-extended key usage is present in the OCSP responder certificate then the
-OCSP verify succeeds.
-
-Otherwise, if B<-no_explicit> is B<not> set the root CA of the OCSP responders
-CA is checked to see if it is trusted for OCSP signing. If it is the OCSP
-verify succeeds.
-
-If none of these checks is successful then the OCSP verify fails.
-
-What this effectively means if that if the OCSP responder certificate is
-authorised directly by the CA it is issuing revocation information about
-(and it is correctly configured) then verification will succeed.
-
-If the OCSP responder is a "global responder" which can give details about
-multiple CAs and has its own separate certificate chain then its root
-CA can be trusted for OCSP signing. For example:
-
- openssl x509 -in ocspCA.pem -addtrust OCSPSigning -out trustedCA.pem
-
-Alternatively the responder certificate itself can be explicitly trusted
-with the B<-VAfile> option.
-
-=head1 NOTES
-
-As noted, most of the verify options are for testing or debugging purposes.
-Normally only the B<-CApath>, B<-CAfile> and (if the responder is a 'global
-VA') B<-VAfile> options need to be used.
-
-The OCSP server is only useful for test and demonstration purposes: it is
-not really usable as a full OCSP responder. It contains only a very
-simple HTTP request handling and can only handle the POST form of OCSP
-queries. It also handles requests serially meaning it cannot respond to
-new requests until it has processed the current one. The text index file
-format of revocation is also inefficient for large quantities of revocation
-data.
-
-It is possible to run the B<ocsp> application in responder mode via a CGI
-script using the B<reqin> and B<respout> options.
-
-=head1 EXAMPLES
-
-Create an OCSP request and write it to a file:
-
- openssl ocsp -issuer issuer.pem -cert c1.pem -cert c2.pem -reqout req.der
-
-Send a query to an OCSP responder with URL http://ocsp.myhost.com/ save the
-response to a file, print it out in text form, and verify the response:
-
- openssl ocsp -issuer issuer.pem -cert c1.pem -cert c2.pem \
- -url http://ocsp.myhost.com/ -resp_text -respout resp.der
-
-Read in an OCSP response and print out text form:
-
- openssl ocsp -respin resp.der -text -noverify
-
-OCSP server on port 8888 using a standard B<ca> configuration, and a separate
-responder certificate. All requests and responses are printed to a file.
-
- openssl ocsp -index demoCA/index.txt -port 8888 -rsigner rcert.pem -CA demoCA/cacert.pem
- -text -out log.txt
-
-As above but exit after processing one request:
-
- openssl ocsp -index demoCA/index.txt -port 8888 -rsigner rcert.pem -CA demoCA/cacert.pem
- -nrequest 1
-
-Query status information using an internally generated request:
-
- openssl ocsp -index demoCA/index.txt -rsigner rcert.pem -CA demoCA/cacert.pem
- -issuer demoCA/cacert.pem -serial 1
-
-Query status information using request read from a file, and write the response
-to a second file.
-
- openssl ocsp -index demoCA/index.txt -rsigner rcert.pem -CA demoCA/cacert.pem
- -reqin req.der -respout resp.der
-
-=head1 HISTORY
-
-The -no_alt_chains option was added in OpenSSL 1.1.0.
-
-=head1 COPYRIGHT
-
-Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/openssl-asn1parse.pod.in b/doc/man1/openssl-asn1parse.pod.in
new file mode 100644
index 000000000000..f098c89c3382
--- /dev/null
+++ b/doc/man1/openssl-asn1parse.pod.in
@@ -0,0 +1,220 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-asn1parse - ASN.1 parsing command
+
+=head1 SYNOPSIS
+
+B<openssl> B<asn1parse>
+[B<-help>]
+[B<-inform> B<DER>|B<PEM>]
+[B<-in> I<filename>]
+[B<-out> I<filename>]
+[B<-noout>]
+[B<-offset> I<number>]
+[B<-length> I<number>]
+[B<-i>]
+[B<-oid> I<filename>]
+[B<-dump>]
+[B<-dlimit> I<num>]
+[B<-strparse> I<offset>]
+[B<-genstr> I<string>]
+[B<-genconf> I<file>]
+[B<-strictpem>]
+[B<-item> I<name>]
+
+=head1 DESCRIPTION
+
+This command is a diagnostic utility that can parse ASN.1 structures.
+It can also be used to extract data from ASN.1 formatted data.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-inform> B<DER>|B<PEM>
+
+The input format; the default is B<PEM>.
+See L<openssl-format-options(1)> for details.
+
+=item B<-in> I<filename>
+
+The input file, default is standard input.
+
+=item B<-out> I<filename>
+
+Output file to place the DER encoded data into. If this
+option is not present then no data will be output. This is most useful when
+combined with the B<-strparse> option.
+
+=item B<-noout>
+
+Don't output the parsed version of the input file.
+
+=item B<-offset> I<number>
+
+Starting offset to begin parsing, default is start of file.
+
+=item B<-length> I<number>
+
+Number of bytes to parse, default is until end of file.
+
+=item B<-i>
+
+Indents the output according to the "depth" of the structures.
+
+=item B<-oid> I<filename>
+
+A file containing additional OBJECT IDENTIFIERs (OIDs). The format of this
+file is described in the NOTES section below.
+
+=item B<-dump>
+
+Dump unknown data in hex format.
+
+=item B<-dlimit> I<num>
+
+Like B<-dump>, but only the first B<num> bytes are output.
+
+=item B<-strparse> I<offset>
+
+Parse the contents octets of the ASN.1 object starting at B<offset>. This
+option can be used multiple times to "drill down" into a nested structure.
+
+=item B<-genstr> I<string>, B<-genconf> I<file>
+
+Generate encoded data based on I<string>, I<file> or both using
+L<ASN1_generate_nconf(3)> format. If I<file> only is
+present then the string is obtained from the default section using the name
+B<asn1>. The encoded data is passed through the ASN1 parser and printed out as
+though it came from a file, the contents can thus be examined and written to a
+file using the B<-out> option.
+
+=item B<-strictpem>
+
+If this option is used then B<-inform> will be ignored. Without this option any
+data in a PEM format input file will be treated as being base64 encoded and
+processed whether it has the normal PEM BEGIN and END markers or not. This
+option will ignore any data prior to the start of the BEGIN marker, or after an
+END marker in a PEM file.
+
+=item B<-item> I<name>
+
+Attempt to decode and print the data as an B<ASN1_ITEM> I<name>. This can be
+used to print out the fields of any supported ASN.1 structure if the type is
+known.
+
+=back
+
+=head2 Output
+
+The output will typically contain lines like this:
+
+ 0:d=0 hl=4 l= 681 cons: SEQUENCE
+
+.....
+
+ 229:d=3 hl=3 l= 141 prim: BIT STRING
+ 373:d=2 hl=3 l= 162 cons: cont [ 3 ]
+ 376:d=3 hl=3 l= 159 cons: SEQUENCE
+ 379:d=4 hl=2 l= 29 cons: SEQUENCE
+ 381:d=5 hl=2 l= 3 prim: OBJECT :X509v3 Subject Key Identifier
+ 386:d=5 hl=2 l= 22 prim: OCTET STRING
+ 410:d=4 hl=2 l= 112 cons: SEQUENCE
+ 412:d=5 hl=2 l= 3 prim: OBJECT :X509v3 Authority Key Identifier
+ 417:d=5 hl=2 l= 105 prim: OCTET STRING
+ 524:d=4 hl=2 l= 12 cons: SEQUENCE
+
+.....
+
+This example is part of a self-signed certificate. Each line starts with the
+offset in decimal. C<d=XX> specifies the current depth. The depth is increased
+within the scope of any SET or SEQUENCE. C<hl=XX> gives the header length
+(tag and length octets) of the current type. C<l=XX> gives the length of
+the contents octets.
+
+The B<-i> option can be used to make the output more readable.
+
+Some knowledge of the ASN.1 structure is needed to interpret the output.
+
+In this example the BIT STRING at offset 229 is the certificate public key.
+The contents octets of this will contain the public key information. This can
+be examined using the option C<-strparse 229> to yield:
+
+ 0:d=0 hl=3 l= 137 cons: SEQUENCE
+ 3:d=1 hl=3 l= 129 prim: INTEGER :E5D21E1F5C8D208EA7A2166C7FAF9F6BDF2059669C60876DDB70840F1A5AAFA59699FE471F379F1DD6A487E7D5409AB6A88D4A9746E24B91D8CF55DB3521015460C8EDE44EE8A4189F7A7BE77D6CD3A9AF2696F486855CF58BF0EDF2B4068058C7A947F52548DDF7E15E96B385F86422BEA9064A3EE9E1158A56E4A6F47E5897
+ 135:d=1 hl=2 l= 3 prim: INTEGER :010001
+
+=head1 NOTES
+
+If an OID is not part of OpenSSL's internal table it will be represented in
+numerical form (for example 1.2.3.4). The file passed to the B<-oid> option
+allows additional OIDs to be included. Each line consists of three columns,
+the first column is the OID in numerical format and should be followed by white
+space. The second column is the "short name" which is a single word followed
+by whitespace. The final column is the rest of the line and is the
+"long name". Example:
+
+C<1.2.3.4 shortName A long name>
+
+For any OID with an associated short and long name, this command will display
+the long name.
+
+=head1 EXAMPLES
+
+Parse a file:
+
+ openssl asn1parse -in file.pem
+
+Parse a DER file:
+
+ openssl asn1parse -inform DER -in file.der
+
+Generate a simple UTF8String:
+
+ openssl asn1parse -genstr 'UTF8:Hello World'
+
+Generate and write out a UTF8String, don't print parsed output:
+
+ openssl asn1parse -genstr 'UTF8:Hello World' -noout -out utf8.der
+
+Generate using a config file:
+
+ openssl asn1parse -genconf asn1.cnf -noout -out asn1.der
+
+Example config file:
+
+ asn1=SEQUENCE:seq_sect
+
+ [seq_sect]
+
+ field1=BOOL:TRUE
+ field2=EXP:0, UTF8:some random string
+
+
+=head1 BUGS
+
+There should be options to change the format of output lines. The output of some
+ASN.1 types is not well handled (if at all).
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<ASN1_generate_nconf(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-ca.pod.in b/doc/man1/openssl-ca.pod.in
new file mode 100644
index 000000000000..1d497e848e79
--- /dev/null
+++ b/doc/man1/openssl-ca.pod.in
@@ -0,0 +1,849 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-ca - sample minimal CA application
+
+=head1 SYNOPSIS
+
+B<openssl> B<ca>
+[B<-help>]
+[B<-verbose>]
+[B<-config> I<filename>]
+[B<-name> I<section>]
+[B<-section> I<section>]
+[B<-gencrl>]
+[B<-revoke> I<file>]
+[B<-valid> I<file>]
+[B<-status> I<serial>]
+[B<-updatedb>]
+[B<-crl_reason> I<reason>]
+[B<-crl_hold> I<instruction>]
+[B<-crl_compromise> I<time>]
+[B<-crl_CA_compromise> I<time>]
+[B<-crl_lastupdate> I<date>]
+[B<-crl_nextupdate> I<date>]
+[B<-crldays> I<days>]
+[B<-crlhours> I<hours>]
+[B<-crlsec> I<seconds>]
+[B<-crlexts> I<section>]
+[B<-startdate> I<date>]
+[B<-enddate> I<date>]
+[B<-days> I<arg>]
+[B<-md> I<arg>]
+[B<-policy> I<arg>]
+[B<-keyfile> I<filename>|I<uri>]
+[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-key> I<arg>]
+[B<-passin> I<arg>]
+[B<-cert> I<file>]
+[B<-certform> B<DER>|B<PEM>|B<P12>]
+[B<-selfsign>]
+[B<-in> I<file>]
+[B<-inform> B<DER>|<PEM>]
+[B<-out> I<file>]
+[B<-notext>]
+[B<-dateopt>]
+[B<-outdir> I<dir>]
+[B<-infiles>]
+[B<-spkac> I<file>]
+[B<-ss_cert> I<file>]
+[B<-preserveDN>]
+[B<-noemailDN>]
+[B<-batch>]
+[B<-msie_hack>]
+[B<-extensions> I<section>]
+[B<-extfile> I<section>]
+[B<-subj> I<arg>]
+[B<-utf8>]
+[B<-sigopt> I<nm>:I<v>]
+[B<-vfyopt> I<nm>:I<v>]
+[B<-create_serial>]
+[B<-rand_serial>]
+[B<-multivalue-rdn>]
+{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+[I<certreq>...]
+
+=head1 DESCRIPTION
+
+This command emulates a CA application.
+See the B<WARNINGS> especially when considering to use it productively.
+It can be used to sign certificate requests (CSRs) in a variety of forms
+and generate certificate revocation lists (CRLs).
+It also maintains a text database of issued certificates and their status.
+When signing certificates, a single request can be specified
+with the B<-in> option, or multiple requests can be processed by
+specifying a set of B<certreq> files after all options.
+
+Note that there are also very lean ways of generating certificates:
+the B<req> and B<x509> commands can be used for directly creating certificates.
+See L<openssl-req(1)> and L<openssl-x509(1)> for details.
+
+The descriptions of the B<ca> command options are divided into each purpose.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-verbose>
+
+This prints extra details about the operations being performed.
+
+=item B<-config> I<filename>
+
+Specifies the configuration file to use.
+Optional; for a description of the default value,
+see L<openssl(1)/COMMAND SUMMARY>.
+
+=item B<-name> I<section>, B<-section> I<section>
+
+Specifies the configuration file section to use (overrides
+B<default_ca> in the B<ca> section).
+
+=item B<-in> I<filename>
+
+An input filename containing a single certificate request (CSR) to be
+signed by the CA.
+
+=item B<-inform> B<DER>|B<PEM>
+
+The format of the data in certificate request input files;
+unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-ss_cert> I<filename>
+
+A single self-signed certificate to be signed by the CA.
+
+=item B<-spkac> I<filename>
+
+A file containing a single Netscape signed public key and challenge
+and additional field values to be signed by the CA. See the B<SPKAC FORMAT>
+section for information on the required input and output format.
+
+=item B<-infiles>
+
+If present this should be the last option, all subsequent arguments
+are taken as the names of files containing certificate requests.
+
+=item B<-out> I<filename>
+
+The output file to output certificates to. The default is standard
+output. The certificate details will also be printed out to this
+file in PEM format (except that B<-spkac> outputs DER format).
+
+=item B<-outdir> I<directory>
+
+The directory to output certificates to. The certificate will be
+written to a filename consisting of the serial number in hex with
+F<.pem> appended.
+
+=item B<-cert> I<filename>
+
+The CA certificate, which must match with B<-keyfile>.
+
+=item B<-certform> B<DER>|B<PEM>|B<P12>
+
+The format of the data in certificate input files; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-keyfile> I<filename>|I<uri>
+
+The CA private key to sign certificate requests with.
+This must match with B<-cert>.
+
+=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The format of the private key input file; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-sigopt> I<nm>:I<v>
+
+Pass options to the signature algorithm during sign operations.
+Names and values of these options are algorithm-specific.
+
+=item B<-vfyopt> I<nm>:I<v>
+
+Pass options to the signature algorithm during verify operations.
+Names and values of these options are algorithm-specific.
+
+This often needs to be given while signing too, because the self-signature of
+a certificate signing request (CSR) is verified against the included public key,
+and that verification may need its own set of options.
+
+=item B<-key> I<password>
+
+=for openssl foreign manual ps(1)
+
+The password used to encrypt the private key. Since on some
+systems the command line arguments are visible (e.g., when using
+L<ps(1)> on Unix),
+this option should be used with caution.
+Better use B<-passin>.
+
+=item B<-passin> I<arg>
+
+The key password source for key files and certificate PKCS#12 files.
+For more information about the format of B<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-selfsign>
+
+Indicates the issued certificates are to be signed with the key
+the certificate requests were signed with (given with B<-keyfile>).
+Certificate requests signed with a different key are ignored.
+If B<-spkac>, B<-ss_cert> or B<-gencrl> are given, B<-selfsign> is ignored.
+
+A consequence of using B<-selfsign> is that the self-signed
+certificate appears among the entries in the certificate database
+(see the configuration option B<database>), and uses the same
+serial number counter as all other certificates sign with the
+self-signed certificate.
+
+=item B<-notext>
+
+Don't output the text form of a certificate to the output file.
+
+=item B<-dateopt>
+
+Specify the date output format. Values are: rfc_822 and iso_8601.
+Defaults to rfc_822.
+
+=item B<-startdate> I<date>
+
+This allows the start date to be explicitly set. The format of the
+date is YYMMDDHHMMSSZ (the same as an ASN1 UTCTime structure), or
+YYYYMMDDHHMMSSZ (the same as an ASN1 GeneralizedTime structure). In
+both formats, seconds SS and timezone Z must be present.
+
+=item B<-enddate> I<date>
+
+This allows the expiry date to be explicitly set. The format of the
+date is YYMMDDHHMMSSZ (the same as an ASN1 UTCTime structure), or
+YYYYMMDDHHMMSSZ (the same as an ASN1 GeneralizedTime structure). In
+both formats, seconds SS and timezone Z must be present.
+
+=item B<-days> I<arg>
+
+The number of days to certify the certificate for.
+
+=item B<-md> I<alg>
+
+The message digest to use.
+Any digest supported by the L<openssl-dgst(1)> command can be used. For signing
+algorithms that do not support a digest (i.e. Ed25519 and Ed448) any message
+digest that is set is ignored. This option also applies to CRLs.
+
+=item B<-policy> I<arg>
+
+This option defines the CA "policy" to use. This is a section in
+the configuration file which decides which fields should be mandatory
+or match the CA certificate. Check out the B<POLICY FORMAT> section
+for more information.
+
+=item B<-msie_hack>
+
+This is a deprecated option to make this command work with very old versions
+of the IE certificate enrollment control "certenr3". It used UniversalStrings
+for almost everything. Since the old control has various security bugs
+its use is strongly discouraged.
+
+=item B<-preserveDN>
+
+Normally the DN order of a certificate is the same as the order of the
+fields in the relevant policy section. When this option is set the order
+is the same as the request. This is largely for compatibility with the
+older IE enrollment control which would only accept certificates if their
+DNs match the order of the request. This is not needed for Xenroll.
+
+=item B<-noemailDN>
+
+The DN of a certificate can contain the EMAIL field if present in the
+request DN, however, it is good policy just having the e-mail set into
+the altName extension of the certificate. When this option is set the
+EMAIL field is removed from the certificate' subject and set only in
+the, eventually present, extensions. The B<email_in_dn> keyword can be
+used in the configuration file to enable this behaviour.
+
+=item B<-batch>
+
+This sets the batch mode. In this mode no questions will be asked
+and all certificates will be certified automatically.
+
+=item B<-extensions> I<section>
+
+The section of the configuration file containing certificate extensions
+to be added when a certificate is issued (defaults to B<x509_extensions>
+unless the B<-extfile> option is used).
+If no X.509 extensions are specified then a V1 certificate is created,
+else a V3 certificate is created.
+See the L<x509v3_config(5)> manual page for details of the
+extension section format.
+
+=item B<-extfile> I<file>
+
+An additional configuration file to read certificate extensions from
+(using the default section unless the B<-extensions> option is also
+used).
+
+=item B<-subj> I<arg>
+
+Supersedes subject name given in the request.
+
+The arg must be formatted as C</type0=value0/type1=value1/type2=...>.
+Special characters may be escaped by C<\> (backslash), whitespace is retained.
+Empty values are permitted, but the corresponding type will not be included
+in the resulting certificate.
+Giving a single C</> will lead to an empty sequence of RDNs (a NULL-DN).
+Multi-valued RDNs can be formed by placing a C<+> character instead of a C</>
+between the AttributeValueAssertions (AVAs) that specify the members of the set.
+Example:
+
+C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
+
+=item B<-utf8>
+
+This option causes field values to be interpreted as UTF8 strings, by
+default they are interpreted as ASCII. This means that the field
+values, whether prompted from a terminal or obtained from a
+configuration file, must be valid UTF8 strings.
+
+=item B<-create_serial>
+
+If reading serial from the text file as specified in the configuration
+fails, specifying this option creates a new random serial to be used as next
+serial number.
+To get random serial numbers, use the B<-rand_serial> flag instead; this
+should only be used for simple error-recovery.
+
+=item B<-rand_serial>
+
+Generate a large random number to use as the serial number.
+This overrides any option or configuration to use a serial number file.
+
+=item B<-multivalue-rdn>
+
+This option has been deprecated and has no effect.
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 CRL OPTIONS
+
+=over 4
+
+=item B<-gencrl>
+
+This option generates a CRL based on information in the index file.
+
+=item B<-crl_lastupdate> I<time>
+
+Allows the value of the CRL's lastUpdate field to be explicitly set; if
+this option is not present, the current time is used. Accepts times in
+YYMMDDHHMMSSZ format (the same as an ASN1 UTCTime structure) or
+YYYYMMDDHHMMSSZ format (the same as an ASN1 GeneralizedTime structure).
+
+=item B<-crl_nextupdate> I<time>
+
+Allows the value of the CRL's nextUpdate field to be explicitly set; if
+this option is present, any values given for B<-crldays>, B<-crlhours>
+and B<-crlsec> are ignored. Accepts times in the same formats as
+B<-crl_lastupdate>.
+
+=item B<-crldays> I<num>
+
+The number of days before the next CRL is due. That is the days from
+now to place in the CRL nextUpdate field.
+
+=item B<-crlhours> I<num>
+
+The number of hours before the next CRL is due.
+
+=item B<-crlsec> I<num>
+
+The number of seconds before the next CRL is due.
+
+=item B<-revoke> I<filename>
+
+A filename containing a certificate to revoke.
+
+=item B<-valid> I<filename>
+
+A filename containing a certificate to add a Valid certificate entry.
+
+=item B<-status> I<serial>
+
+Displays the revocation status of the certificate with the specified
+serial number and exits.
+
+=item B<-updatedb>
+
+Updates the database index to purge expired certificates.
+
+=item B<-crl_reason> I<reason>
+
+Revocation reason, where I<reason> is one of: B<unspecified>, B<keyCompromise>,
+B<CACompromise>, B<affiliationChanged>, B<superseded>, B<cessationOfOperation>,
+B<certificateHold> or B<removeFromCRL>. The matching of I<reason> is case
+insensitive. Setting any revocation reason will make the CRL v2.
+
+In practice B<removeFromCRL> is not particularly useful because it is only used
+in delta CRLs which are not currently implemented.
+
+=item B<-crl_hold> I<instruction>
+
+This sets the CRL revocation reason code to B<certificateHold> and the hold
+instruction to I<instruction> which must be an OID. Although any OID can be
+used only B<holdInstructionNone> (the use of which is discouraged by RFC2459)
+B<holdInstructionCallIssuer> or B<holdInstructionReject> will normally be used.
+
+=item B<-crl_compromise> I<time>
+
+This sets the revocation reason to B<keyCompromise> and the compromise time to
+I<time>. I<time> should be in GeneralizedTime format that is I<YYYYMMDDHHMMSSZ>.
+
+=item B<-crl_CA_compromise> I<time>
+
+This is the same as B<crl_compromise> except the revocation reason is set to
+B<CACompromise>.
+
+=item B<-crlexts> I<section>
+
+The section of the configuration file containing CRL extensions to
+include. If no CRL extension section is present then a V1 CRL is
+created, if the CRL extension section is present (even if it is
+empty) then a V2 CRL is created. The CRL extensions specified are
+CRL extensions and B<not> CRL entry extensions. It should be noted
+that some software (for example Netscape) can't handle V2 CRLs. See
+L<x509v3_config(5)> manual page for details of the
+extension section format.
+
+=back
+
+=head1 CONFIGURATION FILE OPTIONS
+
+The section of the configuration file containing options for this command
+is found as follows: If the B<-name> command line option is used,
+then it names the section to be used. Otherwise the section to
+be used must be named in the B<default_ca> option of the B<ca> section
+of the configuration file (or in the default section of the
+configuration file). Besides B<default_ca>, the following options are
+read directly from the B<ca> section:
+ RANDFILE
+ preserve
+ msie_hack
+With the exception of B<RANDFILE>, this is probably a bug and may
+change in future releases.
+
+Many of the configuration file options are identical to command line
+options. Where the option is present in the configuration file
+and the command line the command line value is used. Where an
+option is described as mandatory then it must be present in
+the configuration file or the command line equivalent (if
+any) used.
+
+=over 4
+
+=item B<oid_file>
+
+This specifies a file containing additional B<OBJECT IDENTIFIERS>.
+Each line of the file should consist of the numerical form of the
+object identifier followed by whitespace then the short name followed
+by whitespace and finally the long name.
+
+=item B<oid_section>
+
+This specifies a section in the configuration file containing extra
+object identifiers. Each line should consist of the short name of the
+object identifier followed by B<=> and the numerical form. The short
+and long names are the same when this option is used.
+
+=item B<new_certs_dir>
+
+The same as the B<-outdir> command line option. It specifies
+the directory where new certificates will be placed. Mandatory.
+
+=item B<certificate>
+
+The same as B<-cert>. It gives the file containing the CA
+certificate. Mandatory.
+
+=item B<private_key>
+
+Same as the B<-keyfile> option. The file containing the
+CA private key. Mandatory.
+
+=item B<RANDFILE>
+
+At startup the specified file is loaded into the random number generator,
+and at exit 256 bytes will be written to it. (Note: Using a RANDFILE is
+not necessary anymore, see the L</HISTORY> section.
+
+=item B<default_days>
+
+The same as the B<-days> option. The number of days to certify
+a certificate for.
+
+=item B<default_startdate>
+
+The same as the B<-startdate> option. The start date to certify
+a certificate for. If not set the current time is used.
+
+=item B<default_enddate>
+
+The same as the B<-enddate> option. Either this option or
+B<default_days> (or the command line equivalents) must be
+present.
+
+=item B<default_crl_hours default_crl_days>
+
+The same as the B<-crlhours> and the B<-crldays> options. These
+will only be used if neither command line option is present. At
+least one of these must be present to generate a CRL.
+
+=item B<default_md>
+
+The same as the B<-md> option. Mandatory except where the signing algorithm does
+not require a digest (i.e. Ed25519 and Ed448).
+
+=item B<database>
+
+The text database file to use. Mandatory. This file must be present
+though initially it will be empty.
+
+=item B<unique_subject>
+
+If the value B<yes> is given, the valid certificate entries in the
+database must have unique subjects. if the value B<no> is given,
+several valid certificate entries may have the exact same subject.
+The default value is B<yes>, to be compatible with older (pre 0.9.8)
+versions of OpenSSL. However, to make CA certificate roll-over easier,
+it's recommended to use the value B<no>, especially if combined with
+the B<-selfsign> command line option.
+
+Note that it is valid in some circumstances for certificates to be created
+without any subject. In the case where there are multiple certificates without
+subjects this does not count as a duplicate.
+
+=item B<serial>
+
+A text file containing the next serial number to use in hex. Mandatory.
+This file must be present and contain a valid serial number.
+
+=item B<crlnumber>
+
+A text file containing the next CRL number to use in hex. The crl number
+will be inserted in the CRLs only if this file exists. If this file is
+present, it must contain a valid CRL number.
+
+=item B<x509_extensions>
+
+A fallback to the B<-extensions> option.
+
+=item B<crl_extensions>
+
+A fallback to the B<-crlexts> option.
+
+=item B<preserve>
+
+The same as B<-preserveDN>
+
+=item B<email_in_dn>
+
+The same as B<-noemailDN>. If you want the EMAIL field to be removed
+from the DN of the certificate simply set this to 'no'. If not present
+the default is to allow for the EMAIL filed in the certificate's DN.
+
+=item B<msie_hack>
+
+The same as B<-msie_hack>
+
+=item B<policy>
+
+The same as B<-policy>. Mandatory. See the B<POLICY FORMAT> section
+for more information.
+
+=item B<name_opt>, B<cert_opt>
+
+These options allow the format used to display the certificate details
+when asking the user to confirm signing. All the options supported by
+the B<x509> utilities B<-nameopt> and B<-certopt> switches can be used
+here, except the B<no_signame> and B<no_sigdump> are permanently set
+and cannot be disabled (this is because the certificate signature cannot
+be displayed because the certificate has not been signed at this point).
+
+For convenience the values B<ca_default> are accepted by both to produce
+a reasonable output.
+
+If neither option is present the format used in earlier versions of
+OpenSSL is used. Use of the old format is B<strongly> discouraged because
+it only displays fields mentioned in the B<policy> section, mishandles
+multicharacter string types and does not display extensions.
+
+=item B<copy_extensions>
+
+Determines how extensions in certificate requests should be handled.
+If set to B<none> or this option is not present then extensions are
+ignored and not copied to the certificate. If set to B<copy> then any
+extensions present in the request that are not already present are copied
+to the certificate. If set to B<copyall> then all extensions in the
+request are copied to the certificate: if the extension is already present
+in the certificate it is deleted first. See the B<WARNINGS> section before
+using this option.
+
+The main use of this option is to allow a certificate request to supply
+values for certain extensions such as subjectAltName.
+
+=back
+
+=head1 POLICY FORMAT
+
+The policy section consists of a set of variables corresponding to
+certificate DN fields. If the value is "match" then the field value
+must match the same field in the CA certificate. If the value is
+"supplied" then it must be present. If the value is "optional" then
+it may be present. Any fields not mentioned in the policy section
+are silently deleted, unless the B<-preserveDN> option is set but
+this can be regarded more of a quirk than intended behaviour.
+
+=head1 SPKAC FORMAT
+
+The input to the B<-spkac> command line option is a Netscape
+signed public key and challenge. This will usually come from
+the B<KEYGEN> tag in an HTML form to create a new private key.
+It is however possible to create SPKACs using L<openssl-spkac(1)>.
+
+The file should contain the variable SPKAC set to the value of
+the SPKAC and also the required DN components as name value pairs.
+If you need to include the same component twice then it can be
+preceded by a number and a '.'.
+
+When processing SPKAC format, the output is DER if the B<-out>
+flag is used, but PEM format if sending to stdout or the B<-outdir>
+flag is used.
+
+=head1 EXAMPLES
+
+Note: these examples assume that the directory structure this command
+assumes is already set up and the relevant files already exist. This
+usually involves creating a CA certificate and private key with
+L<openssl-req(1)>, a serial number file and an empty index file and
+placing them in the relevant directories.
+
+To use the sample configuration file below the directories F<demoCA>,
+F<demoCA/private> and F<demoCA/newcerts> would be created. The CA
+certificate would be copied to F<demoCA/cacert.pem> and its private
+key to F<demoCA/private/cakey.pem>. A file F<demoCA/serial> would be
+created containing for example "01" and the empty index file
+F<demoCA/index.txt>.
+
+
+Sign a certificate request:
+
+ openssl ca -in req.pem -out newcert.pem
+
+Sign an SM2 certificate request:
+
+ openssl ca -in sm2.csr -out sm2.crt -md sm3 \
+ -sigopt "distid:1234567812345678" \
+ -vfyopt "distid:1234567812345678"
+
+Sign a certificate request, using CA extensions:
+
+ openssl ca -in req.pem -extensions v3_ca -out newcert.pem
+
+Generate a CRL
+
+ openssl ca -gencrl -out crl.pem
+
+Sign several requests:
+
+ openssl ca -infiles req1.pem req2.pem req3.pem
+
+Certify a Netscape SPKAC:
+
+ openssl ca -spkac spkac.txt
+
+A sample SPKAC file (the SPKAC line has been truncated for clarity):
+
+ SPKAC=MIG0MGAwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAn7PDhCeV/xIxUg8V70YRxK2A5
+ CN=Steve Test
+ emailAddress=steve@openssl.org
+ 0.OU=OpenSSL Group
+ 1.OU=Another Group
+
+A sample configuration file with the relevant sections for this command:
+
+ [ ca ]
+ default_ca = CA_default # The default ca section
+
+ [ CA_default ]
+
+ dir = ./demoCA # top dir
+ database = $dir/index.txt # index file.
+ new_certs_dir = $dir/newcerts # new certs dir
+
+ certificate = $dir/cacert.pem # The CA cert
+ serial = $dir/serial # serial no file
+ #rand_serial = yes # for random serial#'s
+ private_key = $dir/private/cakey.pem# CA private key
+
+ default_days = 365 # how long to certify for
+ default_crl_days= 30 # how long before next CRL
+ default_md = md5 # md to use
+
+ policy = policy_any # default policy
+ email_in_dn = no # Don't add the email into cert DN
+
+ name_opt = ca_default # Subject name display option
+ cert_opt = ca_default # Certificate display option
+ copy_extensions = none # Don't copy extensions from request
+
+ [ policy_any ]
+ countryName = supplied
+ stateOrProvinceName = optional
+ organizationName = optional
+ organizationalUnitName = optional
+ commonName = supplied
+ emailAddress = optional
+
+=head1 FILES
+
+Note: the location of all files can change either by compile time options,
+configuration file entries, environment variables or command line options.
+The values below reflect the default values.
+
+ /usr/local/ssl/lib/openssl.cnf - master configuration file
+ ./demoCA - main CA directory
+ ./demoCA/cacert.pem - CA certificate
+ ./demoCA/private/cakey.pem - CA private key
+ ./demoCA/serial - CA serial number file
+ ./demoCA/serial.old - CA serial number backup file
+ ./demoCA/index.txt - CA text database file
+ ./demoCA/index.txt.old - CA text database backup file
+ ./demoCA/certs - certificate output file
+
+=head1 RESTRICTIONS
+
+The text database index file is a critical part of the process and
+if corrupted it can be difficult to fix. It is theoretically possible
+to rebuild the index file from all the issued certificates and a current
+CRL: however there is no option to do this.
+
+V2 CRL features like delta CRLs are not currently supported.
+
+Although several requests can be input and handled at once it is only
+possible to include one SPKAC or self-signed certificate.
+
+=head1 BUGS
+
+This command is quirky and at times downright unfriendly.
+
+The use of an in-memory text database can cause problems when large
+numbers of certificates are present because, as the name implies
+the database has to be kept in memory.
+
+This command really needs rewriting or the required functionality
+exposed at either a command or interface level so that a more user-friendly
+replacement could handle things properly. The script
+B<CA.pl> helps a little but not very much.
+
+Any fields in a request that are not present in a policy are silently
+deleted. This does not happen if the B<-preserveDN> option is used. To
+enforce the absence of the EMAIL field within the DN, as suggested by
+RFCs, regardless the contents of the request' subject the B<-noemailDN>
+option can be used. The behaviour should be more friendly and
+configurable.
+
+Canceling some commands by refusing to certify a certificate can
+create an empty file.
+
+=head1 WARNINGS
+
+This command was originally meant as an example of how to do things in a CA.
+Its code does not have production quality.
+It was not supposed to be used as a full blown CA itself,
+nevertheless some people are using it for this purpose at least internally.
+When doing so, specific care should be taken to
+properly secure the private key(s) used for signing certificates.
+It is advisable to keep them in a secure HW storage such as a smart card or HSM
+and access them via a suitable engine or crypto provider.
+
+This command command is effectively a single user command: no locking
+is done on the various files and attempts to run more than one B<openssl ca>
+command on the same database can have unpredictable results.
+
+The B<copy_extensions> option should be used with caution. If care is
+not taken then it can be a security risk. For example if a certificate
+request contains a basicConstraints extension with CA:TRUE and the
+B<copy_extensions> value is set to B<copyall> and the user does not spot
+this when the certificate is displayed then this will hand the requester
+a valid CA certificate.
+This situation can be avoided by setting B<copy_extensions> to B<copy>
+and including basicConstraints with CA:FALSE in the configuration file.
+Then if the request contains a basicConstraints extension it will be
+ignored.
+
+It is advisable to also include values for other extensions such
+as B<keyUsage> to prevent a request supplying its own values.
+
+Additional restrictions can be placed on the CA certificate itself.
+For example if the CA certificate has:
+
+ basicConstraints = CA:TRUE, pathlen:0
+
+then even if a certificate is issued with CA:TRUE it will not be valid.
+
+=head1 HISTORY
+
+Since OpenSSL 1.1.1, the program follows RFC5280. Specifically,
+certificate validity period (specified by any of B<-startdate>,
+B<-enddate> and B<-days>) and CRL last/next update time (specified by
+any of B<-crl_lastupdate>, B<-crl_nextupdate>, B<-crldays>, B<-crlhours>
+and B<-crlsec>) will be encoded as UTCTime if the dates are
+earlier than year 2049 (included), and as GeneralizedTime if the dates
+are in year 2050 or later.
+
+OpenSSL 1.1.1 introduced a new random generator (CSPRNG) with an improved
+seeding mechanism. The new seeding mechanism makes it unnecessary to
+define a RANDFILE for saving and restoring randomness. This option is
+retained mainly for compatibility reasons.
+
+The B<-section> option was added in OpenSSL 3.0.0.
+
+The B<-multivalue-rdn> option has become obsolete in OpenSSL 3.0.0 and
+has no effect.
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-req(1)>,
+L<openssl-spkac(1)>,
+L<openssl-x509(1)>,
+L<CA.pl(1)>,
+L<config(5)>,
+L<x509v3_config(5)>
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-ciphers.pod.in b/doc/man1/openssl-ciphers.pod.in
new file mode 100644
index 000000000000..658730ec5382
--- /dev/null
+++ b/doc/man1/openssl-ciphers.pod.in
@@ -0,0 +1,804 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-ciphers - SSL cipher display and cipher list command
+
+=head1 SYNOPSIS
+
+B<openssl> B<ciphers>
+[B<-help>]
+[B<-s>]
+[B<-v>]
+[B<-V>]
+[B<-ssl3>]
+[B<-tls1>]
+[B<-tls1_1>]
+[B<-tls1_2>]
+[B<-tls1_3>]
+[B<-s>]
+[B<-psk>]
+[B<-srp>]
+[B<-stdname>]
+[B<-convert> I<name>]
+[B<-ciphersuites> I<val>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
+[I<cipherlist>]
+
+=head1 DESCRIPTION
+
+This command converts textual OpenSSL cipher lists into
+ordered SSL cipher preference lists. It can be used to
+determine the appropriate cipherlist.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print a usage message.
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=item B<-s>
+
+Only list supported ciphers: those consistent with the security level, and
+minimum and maximum protocol version. This is closer to the actual cipher list
+an application will support.
+
+PSK and SRP ciphers are not enabled by default: they require B<-psk> or B<-srp>
+to enable them.
+
+It also does not change the default list of supported signature algorithms.
+
+On a server the list of supported ciphers might also exclude other ciphers
+depending on the configured certificates and presence of DH parameters.
+
+If this option is not used then all ciphers that match the cipherlist will be
+listed.
+
+=item B<-psk>
+
+When combined with B<-s> includes cipher suites which require PSK.
+
+=item B<-srp>
+
+When combined with B<-s> includes cipher suites which require SRP. This option
+is deprecated.
+
+=item B<-v>
+
+Verbose output: For each cipher suite, list details as provided by
+L<SSL_CIPHER_description(3)>.
+
+=item B<-V>
+
+Like B<-v>, but include the official cipher suite values in hex.
+
+=item B<-tls1_3>, B<-tls1_2>, B<-tls1_1>, B<-tls1>, B<-ssl3>
+
+In combination with the B<-s> option, list the ciphers which could be used if
+the specified protocol were negotiated.
+Note that not all protocols and flags may be available, depending on how
+OpenSSL was built.
+
+=item B<-stdname>
+
+Precede each cipher suite by its standard name.
+
+=item B<-convert> I<name>
+
+Convert a standard cipher I<name> to its OpenSSL name.
+
+=item B<-ciphersuites> I<val>
+
+Sets the list of TLSv1.3 ciphersuites. This list will be combined with any
+TLSv1.2 and below ciphersuites that have been configured. The format for this
+list is a simple colon (":") separated list of TLSv1.3 ciphersuite names. By
+default this value is:
+
+ TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
+
+=item B<cipherlist>
+
+A cipher list of TLSv1.2 and below ciphersuites to convert to a cipher
+preference list. This list will be combined with any TLSv1.3 ciphersuites that
+have been configured. If it is not included then the default cipher list will be
+used. The format is described below.
+
+=back
+
+=head1 CIPHER LIST FORMAT
+
+The cipher list consists of one or more I<cipher strings> separated by colons.
+Commas or spaces are also acceptable separators but colons are normally used.
+
+The actual cipher string can take several different forms.
+
+It can consist of a single cipher suite such as B<RC4-SHA>.
+
+It can represent a list of cipher suites containing a certain algorithm, or
+cipher suites of a certain type. For example B<SHA1> represents all ciphers
+suites using the digest algorithm SHA1 and B<SSLv3> represents all SSL v3
+algorithms.
+
+Lists of cipher suites can be combined in a single cipher string using the
+B<+> character. This is used as a logical B<and> operation. For example
+B<SHA1+DES> represents all cipher suites containing the SHA1 B<and> the DES
+algorithms.
+
+Each cipher string can be optionally preceded by the characters B<!>,
+B<-> or B<+>.
+
+If B<!> is used then the ciphers are permanently deleted from the list.
+The ciphers deleted can never reappear in the list even if they are
+explicitly stated.
+
+If B<-> is used then the ciphers are deleted from the list, but some or
+all of the ciphers can be added again by later options.
+
+If B<+> is used then the ciphers are moved to the end of the list. This
+option doesn't add any new ciphers it just moves matching existing ones.
+
+If none of these characters is present then the string is just interpreted
+as a list of ciphers to be appended to the current preference list. If the
+list includes any ciphers already present they will be ignored: that is they
+will not moved to the end of the list.
+
+The cipher string B<@STRENGTH> can be used at any point to sort the current
+cipher list in order of encryption algorithm key length.
+
+The cipher string B<@SECLEVEL>=I<n> can be used at any point to set the security
+level to I<n>, which should be a number between zero and five, inclusive.
+See L<SSL_CTX_set_security_level(3)> for a description of what each level means.
+
+The cipher list can be prefixed with the B<DEFAULT> keyword, which enables
+the default cipher list as defined below. Unlike cipher strings,
+this prefix may not be combined with other strings using B<+> character.
+For example, B<DEFAULT+DES> is not valid.
+
+The content of the default list is determined at compile time and normally
+corresponds to B<ALL:!COMPLEMENTOFDEFAULT:!eNULL>.
+
+=head1 CIPHER STRINGS
+
+The following is a list of all permitted cipher strings and their meanings.
+
+=over 4
+
+=item B<COMPLEMENTOFDEFAULT>
+
+The ciphers included in B<ALL>, but not enabled by default. Currently
+this includes all RC4 and anonymous ciphers. Note that this rule does
+not cover B<eNULL>, which is not included by B<ALL> (use B<COMPLEMENTOFALL> if
+necessary). Note that RC4 based cipher suites are not built into OpenSSL by
+default (see the enable-weak-ssl-ciphers option to Configure).
+
+=item B<ALL>
+
+All cipher suites except the B<eNULL> ciphers (which must be explicitly enabled
+if needed).
+As of OpenSSL 1.0.0, the B<ALL> cipher suites are sensibly ordered by default.
+
+=item B<COMPLEMENTOFALL>
+
+The cipher suites not enabled by B<ALL>, currently B<eNULL>.
+
+=item B<HIGH>
+
+"High" encryption cipher suites. This currently means those with key lengths
+larger than 128 bits, and some cipher suites with 128-bit keys.
+
+=item B<MEDIUM>
+
+"Medium" encryption cipher suites, currently some of those using 128 bit
+encryption.
+
+=item B<LOW>
+
+"Low" encryption cipher suites, currently those using 64 or 56 bit
+encryption algorithms but excluding export cipher suites. All these
+cipher suites have been removed as of OpenSSL 1.1.0.
+
+=item B<eNULL>, B<NULL>
+
+The "NULL" ciphers that is those offering no encryption. Because these offer no
+encryption at all and are a security risk they are not enabled via either the
+B<DEFAULT> or B<ALL> cipher strings.
+Be careful when building cipherlists out of lower-level primitives such as
+B<kRSA> or B<aECDSA> as these do overlap with the B<eNULL> ciphers. When in
+doubt, include B<!eNULL> in your cipherlist.
+
+=item B<aNULL>
+
+The cipher suites offering no authentication. This is currently the anonymous
+DH algorithms and anonymous ECDH algorithms. These cipher suites are vulnerable
+to "man in the middle" attacks and so their use is discouraged.
+These are excluded from the B<DEFAULT> ciphers, but included in the B<ALL>
+ciphers.
+Be careful when building cipherlists out of lower-level primitives such as
+B<kDHE> or B<AES> as these do overlap with the B<aNULL> ciphers.
+When in doubt, include B<!aNULL> in your cipherlist.
+
+=item B<kRSA>, B<aRSA>, B<RSA>
+
+Cipher suites using RSA key exchange or authentication. B<RSA> is an alias for
+B<kRSA>.
+
+=item B<kDHr>, B<kDHd>, B<kDH>
+
+Cipher suites using static DH key agreement and DH certificates signed by CAs
+with RSA and DSS keys or either respectively.
+All these cipher suites have been removed in OpenSSL 1.1.0.
+
+=item B<kDHE>, B<kEDH>, B<DH>
+
+Cipher suites using ephemeral DH key agreement, including anonymous cipher
+suites.
+
+=item B<DHE>, B<EDH>
+
+Cipher suites using authenticated ephemeral DH key agreement.
+
+=item B<ADH>
+
+Anonymous DH cipher suites, note that this does not include anonymous Elliptic
+Curve DH (ECDH) cipher suites.
+
+=item B<kEECDH>, B<kECDHE>, B<ECDH>
+
+Cipher suites using ephemeral ECDH key agreement, including anonymous
+cipher suites.
+
+=item B<ECDHE>, B<EECDH>
+
+Cipher suites using authenticated ephemeral ECDH key agreement.
+
+=item B<AECDH>
+
+Anonymous Elliptic Curve Diffie-Hellman cipher suites.
+
+=item B<aDSS>, B<DSS>
+
+Cipher suites using DSS authentication, i.e. the certificates carry DSS keys.
+
+=item B<aDH>
+
+Cipher suites effectively using DH authentication, i.e. the certificates carry
+DH keys.
+All these cipher suites have been removed in OpenSSL 1.1.0.
+
+=item B<aECDSA>, B<ECDSA>
+
+Cipher suites using ECDSA authentication, i.e. the certificates carry ECDSA
+keys.
+
+=item B<TLSv1.2>, B<TLSv1.0>, B<SSLv3>
+
+Lists cipher suites which are only supported in at least TLS v1.2, TLS v1.0 or
+SSL v3.0 respectively.
+Note: there are no cipher suites specific to TLS v1.1.
+Since this is only the minimum version, if, for example, TLSv1.0 is negotiated
+then both TLSv1.0 and SSLv3.0 cipher suites are available.
+
+Note: these cipher strings B<do not> change the negotiated version of SSL or
+TLS, they only affect the list of available cipher suites.
+
+=item B<AES128>, B<AES256>, B<AES>
+
+cipher suites using 128 bit AES, 256 bit AES or either 128 or 256 bit AES.
+
+=item B<AESGCM>
+
+AES in Galois Counter Mode (GCM): these cipher suites are only supported
+in TLS v1.2.
+
+=item B<AESCCM>, B<AESCCM8>
+
+AES in Cipher Block Chaining - Message Authentication Mode (CCM): these
+cipher suites are only supported in TLS v1.2. B<AESCCM> references CCM
+cipher suites using both 16 and 8 octet Integrity Check Value (ICV)
+while B<AESCCM8> only references 8 octet ICV.
+
+=item B<ARIA128>, B<ARIA256>, B<ARIA>
+
+Cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit
+ARIA.
+
+=item B<CAMELLIA128>, B<CAMELLIA256>, B<CAMELLIA>
+
+Cipher suites using 128 bit CAMELLIA, 256 bit CAMELLIA or either 128 or 256 bit
+CAMELLIA.
+
+=item B<CHACHA20>
+
+Cipher suites using ChaCha20.
+
+=item B<3DES>
+
+Cipher suites using triple DES.
+
+=item B<DES>
+
+Cipher suites using DES (not triple DES).
+All these cipher suites have been removed in OpenSSL 1.1.0.
+
+=item B<RC4>
+
+Cipher suites using RC4.
+
+=item B<RC2>
+
+Cipher suites using RC2.
+
+=item B<IDEA>
+
+Cipher suites using IDEA.
+
+=item B<SEED>
+
+Cipher suites using SEED.
+
+=item B<MD5>
+
+Cipher suites using MD5.
+
+=item B<SHA1>, B<SHA>
+
+Cipher suites using SHA1.
+
+=item B<SHA256>, B<SHA384>
+
+Cipher suites using SHA256 or SHA384.
+
+=item B<aGOST>
+
+Cipher suites using GOST R 34.10 (either 2001 or 94) for authentication
+(needs an engine supporting GOST algorithms).
+
+=item B<aGOST01>
+
+Cipher suites using GOST R 34.10-2001 authentication.
+
+=item B<kGOST>
+
+Cipher suites, using VKO 34.10 key exchange, specified in the RFC 4357.
+
+=item B<GOST94>
+
+Cipher suites, using HMAC based on GOST R 34.11-94.
+
+=item B<GOST89MAC>
+
+Cipher suites using GOST 28147-89 MAC B<instead of> HMAC.
+
+=item B<PSK>
+
+All cipher suites using pre-shared keys (PSK).
+
+=item B<kPSK>, B<kECDHEPSK>, B<kDHEPSK>, B<kRSAPSK>
+
+Cipher suites using PSK key exchange, ECDHE_PSK, DHE_PSK or RSA_PSK.
+
+=item B<aPSK>
+
+Cipher suites using PSK authentication (currently all PSK modes apart from
+RSA_PSK).
+
+=item B<SUITEB128>, B<SUITEB128ONLY>, B<SUITEB192>
+
+Enables suite B mode of operation using 128 (permitting 192 bit mode by peer)
+128 bit (not permitting 192 bit by peer) or 192 bit level of security
+respectively.
+If used these cipherstrings should appear first in the cipher
+list and anything after them is ignored.
+Setting Suite B mode has additional consequences required to comply with
+RFC6460.
+In particular the supported signature algorithms is reduced to support only
+ECDSA and SHA256 or SHA384, only the elliptic curves P-256 and P-384 can be
+used and only the two suite B compliant cipher suites
+(ECDHE-ECDSA-AES128-GCM-SHA256 and ECDHE-ECDSA-AES256-GCM-SHA384) are
+permissible.
+
+=item B<CBC>
+
+All cipher suites using encryption algorithm in Cipher Block Chaining (CBC)
+mode. These cipher suites are only supported in TLS v1.2 and earlier. Currently
+it's an alias for the following cipherstrings: B<SSL_DES>, B<SSL_3DES>, B<SSL_RC2>,
+B<SSL_IDEA>, B<SSL_AES128>, B<SSL_AES256>, B<SSL_CAMELLIA128>, B<SSL_CAMELLIA256>, B<SSL_SEED>.
+
+=back
+
+=head1 CIPHER SUITE NAMES
+
+The following lists give the SSL or TLS cipher suites names from the
+relevant specification and their OpenSSL equivalents. It should be noted,
+that several cipher suite names do not include the authentication used,
+e.g. DES-CBC3-SHA. In these cases, RSA authentication is used.
+
+=head2 SSL v3.0 cipher suites
+
+ SSL_RSA_WITH_NULL_MD5 NULL-MD5
+ SSL_RSA_WITH_NULL_SHA NULL-SHA
+ SSL_RSA_WITH_RC4_128_MD5 RC4-MD5
+ SSL_RSA_WITH_RC4_128_SHA RC4-SHA
+ SSL_RSA_WITH_IDEA_CBC_SHA IDEA-CBC-SHA
+ SSL_RSA_WITH_3DES_EDE_CBC_SHA DES-CBC3-SHA
+
+ SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA DH-DSS-DES-CBC3-SHA
+ SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA DH-RSA-DES-CBC3-SHA
+ SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA DHE-DSS-DES-CBC3-SHA
+ SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA DHE-RSA-DES-CBC3-SHA
+
+ SSL_DH_anon_WITH_RC4_128_MD5 ADH-RC4-MD5
+ SSL_DH_anon_WITH_3DES_EDE_CBC_SHA ADH-DES-CBC3-SHA
+
+ SSL_FORTEZZA_KEA_WITH_NULL_SHA Not implemented.
+ SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA Not implemented.
+ SSL_FORTEZZA_KEA_WITH_RC4_128_SHA Not implemented.
+
+=head2 TLS v1.0 cipher suites
+
+ TLS_RSA_WITH_NULL_MD5 NULL-MD5
+ TLS_RSA_WITH_NULL_SHA NULL-SHA
+ TLS_RSA_WITH_RC4_128_MD5 RC4-MD5
+ TLS_RSA_WITH_RC4_128_SHA RC4-SHA
+ TLS_RSA_WITH_IDEA_CBC_SHA IDEA-CBC-SHA
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA DES-CBC3-SHA
+
+ TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA Not implemented.
+ TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA Not implemented.
+ TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA DHE-DSS-DES-CBC3-SHA
+ TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA DHE-RSA-DES-CBC3-SHA
+
+ TLS_DH_anon_WITH_RC4_128_MD5 ADH-RC4-MD5
+ TLS_DH_anon_WITH_3DES_EDE_CBC_SHA ADH-DES-CBC3-SHA
+
+=head2 AES cipher suites from RFC3268, extending TLS v1.0
+
+ TLS_RSA_WITH_AES_128_CBC_SHA AES128-SHA
+ TLS_RSA_WITH_AES_256_CBC_SHA AES256-SHA
+
+ TLS_DH_DSS_WITH_AES_128_CBC_SHA DH-DSS-AES128-SHA
+ TLS_DH_DSS_WITH_AES_256_CBC_SHA DH-DSS-AES256-SHA
+ TLS_DH_RSA_WITH_AES_128_CBC_SHA DH-RSA-AES128-SHA
+ TLS_DH_RSA_WITH_AES_256_CBC_SHA DH-RSA-AES256-SHA
+
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA DHE-DSS-AES128-SHA
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA DHE-DSS-AES256-SHA
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA DHE-RSA-AES128-SHA
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA DHE-RSA-AES256-SHA
+
+ TLS_DH_anon_WITH_AES_128_CBC_SHA ADH-AES128-SHA
+ TLS_DH_anon_WITH_AES_256_CBC_SHA ADH-AES256-SHA
+
+=head2 Camellia cipher suites from RFC4132, extending TLS v1.0
+
+ TLS_RSA_WITH_CAMELLIA_128_CBC_SHA CAMELLIA128-SHA
+ TLS_RSA_WITH_CAMELLIA_256_CBC_SHA CAMELLIA256-SHA
+
+ TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA DH-DSS-CAMELLIA128-SHA
+ TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA DH-DSS-CAMELLIA256-SHA
+ TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA DH-RSA-CAMELLIA128-SHA
+ TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA DH-RSA-CAMELLIA256-SHA
+
+ TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA DHE-DSS-CAMELLIA128-SHA
+ TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA DHE-DSS-CAMELLIA256-SHA
+ TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA DHE-RSA-CAMELLIA128-SHA
+ TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA DHE-RSA-CAMELLIA256-SHA
+
+ TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA ADH-CAMELLIA128-SHA
+ TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA ADH-CAMELLIA256-SHA
+
+=head2 SEED cipher suites from RFC4162, extending TLS v1.0
+
+ TLS_RSA_WITH_SEED_CBC_SHA SEED-SHA
+
+ TLS_DH_DSS_WITH_SEED_CBC_SHA DH-DSS-SEED-SHA
+ TLS_DH_RSA_WITH_SEED_CBC_SHA DH-RSA-SEED-SHA
+
+ TLS_DHE_DSS_WITH_SEED_CBC_SHA DHE-DSS-SEED-SHA
+ TLS_DHE_RSA_WITH_SEED_CBC_SHA DHE-RSA-SEED-SHA
+
+ TLS_DH_anon_WITH_SEED_CBC_SHA ADH-SEED-SHA
+
+=head2 GOST cipher suites from draft-chudov-cryptopro-cptls, extending TLS v1.0
+
+Note: these ciphers require an engine which including GOST cryptographic
+algorithms, such as the B<gost> engine, which isn't part of the OpenSSL
+distribution.
+
+ TLS_GOSTR341094_WITH_28147_CNT_IMIT GOST94-GOST89-GOST89
+ TLS_GOSTR341001_WITH_28147_CNT_IMIT GOST2001-GOST89-GOST89
+ TLS_GOSTR341094_WITH_NULL_GOSTR3411 GOST94-NULL-GOST94
+ TLS_GOSTR341001_WITH_NULL_GOSTR3411 GOST2001-NULL-GOST94
+
+=head2 GOST cipher suites, extending TLS v1.2
+
+Note: these ciphers require an engine which including GOST cryptographic
+algorithms, such as the B<gost> engine, which isn't part of the OpenSSL
+distribution.
+
+ TLS_GOSTR341112_256_WITH_28147_CNT_IMIT GOST2012-GOST8912-GOST8912
+ TLS_GOSTR341112_256_WITH_NULL_GOSTR3411 GOST2012-NULL-GOST12
+
+Note: GOST2012-GOST8912-GOST8912 is an alias for two ciphers ID
+old LEGACY-GOST2012-GOST8912-GOST8912 and new IANA-GOST2012-GOST8912-GOST8912
+
+
+=head2 Additional Export 1024 and other cipher suites
+
+Note: these ciphers can also be used in SSL v3.
+
+ TLS_DHE_DSS_WITH_RC4_128_SHA DHE-DSS-RC4-SHA
+
+=head2 Elliptic curve cipher suites
+
+ TLS_ECDHE_RSA_WITH_NULL_SHA ECDHE-RSA-NULL-SHA
+ TLS_ECDHE_RSA_WITH_RC4_128_SHA ECDHE-RSA-RC4-SHA
+ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA ECDHE-RSA-DES-CBC3-SHA
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA ECDHE-RSA-AES128-SHA
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA ECDHE-RSA-AES256-SHA
+
+ TLS_ECDHE_ECDSA_WITH_NULL_SHA ECDHE-ECDSA-NULL-SHA
+ TLS_ECDHE_ECDSA_WITH_RC4_128_SHA ECDHE-ECDSA-RC4-SHA
+ TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA ECDHE-ECDSA-DES-CBC3-SHA
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA ECDHE-ECDSA-AES128-SHA
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA ECDHE-ECDSA-AES256-SHA
+
+ TLS_ECDH_anon_WITH_NULL_SHA AECDH-NULL-SHA
+ TLS_ECDH_anon_WITH_RC4_128_SHA AECDH-RC4-SHA
+ TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA AECDH-DES-CBC3-SHA
+ TLS_ECDH_anon_WITH_AES_128_CBC_SHA AECDH-AES128-SHA
+ TLS_ECDH_anon_WITH_AES_256_CBC_SHA AECDH-AES256-SHA
+
+=head2 TLS v1.2 cipher suites
+
+ TLS_RSA_WITH_NULL_SHA256 NULL-SHA256
+
+ TLS_RSA_WITH_AES_128_CBC_SHA256 AES128-SHA256
+ TLS_RSA_WITH_AES_256_CBC_SHA256 AES256-SHA256
+ TLS_RSA_WITH_AES_128_GCM_SHA256 AES128-GCM-SHA256
+ TLS_RSA_WITH_AES_256_GCM_SHA384 AES256-GCM-SHA384
+
+ TLS_DH_RSA_WITH_AES_128_CBC_SHA256 DH-RSA-AES128-SHA256
+ TLS_DH_RSA_WITH_AES_256_CBC_SHA256 DH-RSA-AES256-SHA256
+ TLS_DH_RSA_WITH_AES_128_GCM_SHA256 DH-RSA-AES128-GCM-SHA256
+ TLS_DH_RSA_WITH_AES_256_GCM_SHA384 DH-RSA-AES256-GCM-SHA384
+
+ TLS_DH_DSS_WITH_AES_128_CBC_SHA256 DH-DSS-AES128-SHA256
+ TLS_DH_DSS_WITH_AES_256_CBC_SHA256 DH-DSS-AES256-SHA256
+ TLS_DH_DSS_WITH_AES_128_GCM_SHA256 DH-DSS-AES128-GCM-SHA256
+ TLS_DH_DSS_WITH_AES_256_GCM_SHA384 DH-DSS-AES256-GCM-SHA384
+
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 DHE-RSA-AES128-SHA256
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 DHE-RSA-AES256-SHA256
+ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 DHE-RSA-AES128-GCM-SHA256
+ TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 DHE-RSA-AES256-GCM-SHA384
+
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 DHE-DSS-AES128-SHA256
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 DHE-DSS-AES256-SHA256
+ TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 DHE-DSS-AES128-GCM-SHA256
+ TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 DHE-DSS-AES256-GCM-SHA384
+
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 ECDHE-RSA-AES128-SHA256
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 ECDHE-RSA-AES256-SHA384
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ECDHE-RSA-AES128-GCM-SHA256
+ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ECDHE-RSA-AES256-GCM-SHA384
+
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 ECDHE-ECDSA-AES128-SHA256
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 ECDHE-ECDSA-AES256-SHA384
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ECDHE-ECDSA-AES128-GCM-SHA256
+ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ECDHE-ECDSA-AES256-GCM-SHA384
+
+ TLS_DH_anon_WITH_AES_128_CBC_SHA256 ADH-AES128-SHA256
+ TLS_DH_anon_WITH_AES_256_CBC_SHA256 ADH-AES256-SHA256
+ TLS_DH_anon_WITH_AES_128_GCM_SHA256 ADH-AES128-GCM-SHA256
+ TLS_DH_anon_WITH_AES_256_GCM_SHA384 ADH-AES256-GCM-SHA384
+
+ RSA_WITH_AES_128_CCM AES128-CCM
+ RSA_WITH_AES_256_CCM AES256-CCM
+ DHE_RSA_WITH_AES_128_CCM DHE-RSA-AES128-CCM
+ DHE_RSA_WITH_AES_256_CCM DHE-RSA-AES256-CCM
+ RSA_WITH_AES_128_CCM_8 AES128-CCM8
+ RSA_WITH_AES_256_CCM_8 AES256-CCM8
+ DHE_RSA_WITH_AES_128_CCM_8 DHE-RSA-AES128-CCM8
+ DHE_RSA_WITH_AES_256_CCM_8 DHE-RSA-AES256-CCM8
+ ECDHE_ECDSA_WITH_AES_128_CCM ECDHE-ECDSA-AES128-CCM
+ ECDHE_ECDSA_WITH_AES_256_CCM ECDHE-ECDSA-AES256-CCM
+ ECDHE_ECDSA_WITH_AES_128_CCM_8 ECDHE-ECDSA-AES128-CCM8
+ ECDHE_ECDSA_WITH_AES_256_CCM_8 ECDHE-ECDSA-AES256-CCM8
+
+=head2 ARIA cipher suites from RFC6209, extending TLS v1.2
+
+Note: the CBC modes mentioned in this RFC are not supported.
+
+ TLS_RSA_WITH_ARIA_128_GCM_SHA256 ARIA128-GCM-SHA256
+ TLS_RSA_WITH_ARIA_256_GCM_SHA384 ARIA256-GCM-SHA384
+ TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 DHE-RSA-ARIA128-GCM-SHA256
+ TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 DHE-RSA-ARIA256-GCM-SHA384
+ TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 DHE-DSS-ARIA128-GCM-SHA256
+ TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 DHE-DSS-ARIA256-GCM-SHA384
+ TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 ECDHE-ECDSA-ARIA128-GCM-SHA256
+ TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 ECDHE-ECDSA-ARIA256-GCM-SHA384
+ TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 ECDHE-ARIA128-GCM-SHA256
+ TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 ECDHE-ARIA256-GCM-SHA384
+ TLS_PSK_WITH_ARIA_128_GCM_SHA256 PSK-ARIA128-GCM-SHA256
+ TLS_PSK_WITH_ARIA_256_GCM_SHA384 PSK-ARIA256-GCM-SHA384
+ TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 DHE-PSK-ARIA128-GCM-SHA256
+ TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 DHE-PSK-ARIA256-GCM-SHA384
+ TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 RSA-PSK-ARIA128-GCM-SHA256
+ TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 RSA-PSK-ARIA256-GCM-SHA384
+
+=head2 Camellia HMAC-Based cipher suites from RFC6367, extending TLS v1.2
+
+ TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 ECDHE-ECDSA-CAMELLIA128-SHA256
+ TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 ECDHE-ECDSA-CAMELLIA256-SHA384
+ TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 ECDHE-RSA-CAMELLIA128-SHA256
+ TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 ECDHE-RSA-CAMELLIA256-SHA384
+
+=head2 Pre-shared keying (PSK) cipher suites
+
+ PSK_WITH_NULL_SHA PSK-NULL-SHA
+ DHE_PSK_WITH_NULL_SHA DHE-PSK-NULL-SHA
+ RSA_PSK_WITH_NULL_SHA RSA-PSK-NULL-SHA
+
+ PSK_WITH_RC4_128_SHA PSK-RC4-SHA
+ PSK_WITH_3DES_EDE_CBC_SHA PSK-3DES-EDE-CBC-SHA
+ PSK_WITH_AES_128_CBC_SHA PSK-AES128-CBC-SHA
+ PSK_WITH_AES_256_CBC_SHA PSK-AES256-CBC-SHA
+
+ DHE_PSK_WITH_RC4_128_SHA DHE-PSK-RC4-SHA
+ DHE_PSK_WITH_3DES_EDE_CBC_SHA DHE-PSK-3DES-EDE-CBC-SHA
+ DHE_PSK_WITH_AES_128_CBC_SHA DHE-PSK-AES128-CBC-SHA
+ DHE_PSK_WITH_AES_256_CBC_SHA DHE-PSK-AES256-CBC-SHA
+
+ RSA_PSK_WITH_RC4_128_SHA RSA-PSK-RC4-SHA
+ RSA_PSK_WITH_3DES_EDE_CBC_SHA RSA-PSK-3DES-EDE-CBC-SHA
+ RSA_PSK_WITH_AES_128_CBC_SHA RSA-PSK-AES128-CBC-SHA
+ RSA_PSK_WITH_AES_256_CBC_SHA RSA-PSK-AES256-CBC-SHA
+
+ PSK_WITH_AES_128_GCM_SHA256 PSK-AES128-GCM-SHA256
+ PSK_WITH_AES_256_GCM_SHA384 PSK-AES256-GCM-SHA384
+ DHE_PSK_WITH_AES_128_GCM_SHA256 DHE-PSK-AES128-GCM-SHA256
+ DHE_PSK_WITH_AES_256_GCM_SHA384 DHE-PSK-AES256-GCM-SHA384
+ RSA_PSK_WITH_AES_128_GCM_SHA256 RSA-PSK-AES128-GCM-SHA256
+ RSA_PSK_WITH_AES_256_GCM_SHA384 RSA-PSK-AES256-GCM-SHA384
+
+ PSK_WITH_AES_128_CBC_SHA256 PSK-AES128-CBC-SHA256
+ PSK_WITH_AES_256_CBC_SHA384 PSK-AES256-CBC-SHA384
+ PSK_WITH_NULL_SHA256 PSK-NULL-SHA256
+ PSK_WITH_NULL_SHA384 PSK-NULL-SHA384
+ DHE_PSK_WITH_AES_128_CBC_SHA256 DHE-PSK-AES128-CBC-SHA256
+ DHE_PSK_WITH_AES_256_CBC_SHA384 DHE-PSK-AES256-CBC-SHA384
+ DHE_PSK_WITH_NULL_SHA256 DHE-PSK-NULL-SHA256
+ DHE_PSK_WITH_NULL_SHA384 DHE-PSK-NULL-SHA384
+ RSA_PSK_WITH_AES_128_CBC_SHA256 RSA-PSK-AES128-CBC-SHA256
+ RSA_PSK_WITH_AES_256_CBC_SHA384 RSA-PSK-AES256-CBC-SHA384
+ RSA_PSK_WITH_NULL_SHA256 RSA-PSK-NULL-SHA256
+ RSA_PSK_WITH_NULL_SHA384 RSA-PSK-NULL-SHA384
+ PSK_WITH_AES_128_GCM_SHA256 PSK-AES128-GCM-SHA256
+ PSK_WITH_AES_256_GCM_SHA384 PSK-AES256-GCM-SHA384
+
+ ECDHE_PSK_WITH_RC4_128_SHA ECDHE-PSK-RC4-SHA
+ ECDHE_PSK_WITH_3DES_EDE_CBC_SHA ECDHE-PSK-3DES-EDE-CBC-SHA
+ ECDHE_PSK_WITH_AES_128_CBC_SHA ECDHE-PSK-AES128-CBC-SHA
+ ECDHE_PSK_WITH_AES_256_CBC_SHA ECDHE-PSK-AES256-CBC-SHA
+ ECDHE_PSK_WITH_AES_128_CBC_SHA256 ECDHE-PSK-AES128-CBC-SHA256
+ ECDHE_PSK_WITH_AES_256_CBC_SHA384 ECDHE-PSK-AES256-CBC-SHA384
+ ECDHE_PSK_WITH_NULL_SHA ECDHE-PSK-NULL-SHA
+ ECDHE_PSK_WITH_NULL_SHA256 ECDHE-PSK-NULL-SHA256
+ ECDHE_PSK_WITH_NULL_SHA384 ECDHE-PSK-NULL-SHA384
+
+ PSK_WITH_CAMELLIA_128_CBC_SHA256 PSK-CAMELLIA128-SHA256
+ PSK_WITH_CAMELLIA_256_CBC_SHA384 PSK-CAMELLIA256-SHA384
+
+ DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 DHE-PSK-CAMELLIA128-SHA256
+ DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 DHE-PSK-CAMELLIA256-SHA384
+
+ RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 RSA-PSK-CAMELLIA128-SHA256
+ RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 RSA-PSK-CAMELLIA256-SHA384
+
+ ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 ECDHE-PSK-CAMELLIA128-SHA256
+ ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 ECDHE-PSK-CAMELLIA256-SHA384
+
+ PSK_WITH_AES_128_CCM PSK-AES128-CCM
+ PSK_WITH_AES_256_CCM PSK-AES256-CCM
+ DHE_PSK_WITH_AES_128_CCM DHE-PSK-AES128-CCM
+ DHE_PSK_WITH_AES_256_CCM DHE-PSK-AES256-CCM
+ PSK_WITH_AES_128_CCM_8 PSK-AES128-CCM8
+ PSK_WITH_AES_256_CCM_8 PSK-AES256-CCM8
+ DHE_PSK_WITH_AES_128_CCM_8 DHE-PSK-AES128-CCM8
+ DHE_PSK_WITH_AES_256_CCM_8 DHE-PSK-AES256-CCM8
+
+=head2 ChaCha20-Poly1305 cipher suites, extending TLS v1.2
+
+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 ECDHE-RSA-CHACHA20-POLY1305
+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 ECDHE-ECDSA-CHACHA20-POLY1305
+ TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 DHE-RSA-CHACHA20-POLY1305
+ TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 PSK-CHACHA20-POLY1305
+ TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 ECDHE-PSK-CHACHA20-POLY1305
+ TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 DHE-PSK-CHACHA20-POLY1305
+ TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 RSA-PSK-CHACHA20-POLY1305
+
+=head2 TLS v1.3 cipher suites
+
+ TLS_AES_128_GCM_SHA256 TLS_AES_128_GCM_SHA256
+ TLS_AES_256_GCM_SHA384 TLS_AES_256_GCM_SHA384
+ TLS_CHACHA20_POLY1305_SHA256 TLS_CHACHA20_POLY1305_SHA256
+ TLS_AES_128_CCM_SHA256 TLS_AES_128_CCM_SHA256
+ TLS_AES_128_CCM_8_SHA256 TLS_AES_128_CCM_8_SHA256
+
+=head2 Older names used by OpenSSL
+
+The following names are accepted by older releases:
+
+ SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA EDH-RSA-DES-CBC3-SHA (DHE-RSA-DES-CBC3-SHA)
+ SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA EDH-DSS-DES-CBC3-SHA (DHE-DSS-DES-CBC3-SHA)
+
+=head1 NOTES
+
+Some compiled versions of OpenSSL may not include all the ciphers
+listed here because some ciphers were excluded at compile time.
+
+=head1 EXAMPLES
+
+Verbose listing of all OpenSSL ciphers including NULL ciphers:
+
+ openssl ciphers -v 'ALL:eNULL'
+
+Include all ciphers except NULL and anonymous DH then sort by
+strength:
+
+ openssl ciphers -v 'ALL:!ADH:@STRENGTH'
+
+Include all ciphers except ones with no encryption (eNULL) or no
+authentication (aNULL):
+
+ openssl ciphers -v 'ALL:!aNULL'
+
+Include only 3DES ciphers and then place RSA ciphers last:
+
+ openssl ciphers -v '3DES:+RSA'
+
+Include all RC4 ciphers but leave out those without authentication:
+
+ openssl ciphers -v 'RC4:!COMPLEMENTOFDEFAULT'
+
+Include all ciphers with RSA authentication but leave out ciphers without
+encryption.
+
+ openssl ciphers -v 'RSA:!COMPLEMENTOFALL'
+
+Set security level to 2 and display all ciphers consistent with level 2:
+
+ openssl ciphers -s -v 'ALL:@SECLEVEL=2'
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-s_client(1)>,
+L<openssl-s_server(1)>,
+L<ssl(7)>
+
+=head1 HISTORY
+
+The B<-V> option was added in OpenSSL 1.0.0.
+
+The B<-stdname> is only available if OpenSSL is built with tracing enabled
+(B<enable-ssl-trace> argument to Configure) before OpenSSL 1.1.1.
+
+The B<-convert> option was added in OpenSSL 1.1.1.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-cmds.pod.in b/doc/man1/openssl-cmds.pod.in
new file mode 100644
index 000000000000..a8b158123239
--- /dev/null
+++ b/doc/man1/openssl-cmds.pod.in
@@ -0,0 +1,162 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+=for openssl names: openssl-cmds
+
+asn1parse,
+ca,
+ciphers,
+cmp,
+cms,
+crl,
+crl2pkcs7,
+dgst,
+dhparam,
+dsa,
+dsaparam,
+ec,
+ecparam,
+enc,
+engine,
+errstr,
+gendsa,
+genpkey,
+genrsa,
+info,
+kdf,
+mac,
+nseq,
+ocsp,
+passwd,
+pkcs12,
+pkcs7,
+pkcs8,
+pkey,
+pkeyparam,
+pkeyutl,
+prime,
+rand,
+rehash,
+req,
+rsa,
+rsautl,
+s_client,
+s_server,
+s_time,
+sess_id,
+smime,
+speed,
+spkac,
+srp,
+storeutl,
+ts,
+verify,
+version,
+x509
+- OpenSSL application commands
+
+=for openssl foreign manual apropos(1)
+
+=head1 SYNOPSIS
+
+=for openssl generic
+
+B<openssl> I<cmd> B<-help> | [I<-option> | I<-option> I<arg>] ... [I<arg>] ...
+
+=head1 DESCRIPTION
+
+Every I<cmd> listed above is a (sub-)command of the L<openssl(1)> application.
+It has its own detailed manual page at B<openssl-I<cmd>>(1). For example, to
+view the manual page for the B<openssl dgst> command, type C<man openssl-dgst>.
+
+=head1 OPTIONS
+
+Among others, every subcommand has a help option.
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message for the subcommand.
+
+=back
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-asn1parse(1)>,
+L<openssl-ca(1)>,
+L<openssl-ciphers(1)>,
+L<openssl-cmp(1)>,
+L<openssl-cms(1)>,
+L<openssl-crl(1)>,
+L<openssl-crl2pkcs7(1)>,
+L<openssl-dgst(1)>,
+L<openssl-dhparam(1)>,
+L<openssl-dsa(1)>,
+L<openssl-dsaparam(1)>,
+L<openssl-ec(1)>,
+L<openssl-ecparam(1)>,
+L<openssl-enc(1)>,
+L<openssl-engine(1)>,
+L<openssl-errstr(1)>,
+L<openssl-gendsa(1)>,
+L<openssl-genpkey(1)>,
+L<openssl-genrsa(1)>,
+L<openssl-info(1)>,
+L<openssl-kdf(1)>,
+L<openssl-mac(1)>,
+L<openssl-nseq(1)>,
+L<openssl-ocsp(1)>,
+L<openssl-passwd(1)>,
+L<openssl-pkcs12(1)>,
+L<openssl-pkcs7(1)>,
+L<openssl-pkcs8(1)>,
+L<openssl-pkey(1)>,
+L<openssl-pkeyparam(1)>,
+L<openssl-pkeyutl(1)>,
+L<openssl-prime(1)>,
+L<openssl-rand(1)>,
+L<openssl-rehash(1)>,
+L<openssl-req(1)>,
+L<openssl-rsa(1)>,
+L<openssl-rsautl(1)>,
+L<openssl-s_client(1)>,
+L<openssl-s_server(1)>,
+L<openssl-s_time(1)>,
+L<openssl-sess_id(1)>,
+L<openssl-smime(1)>,
+L<openssl-speed(1)>,
+L<openssl-spkac(1)>,
+L<openssl-srp(1)>,
+L<openssl-storeutl(1)>,
+L<openssl-ts(1)>,
+L<openssl-verify(1)>,
+L<openssl-version(1)>,
+L<openssl-x509(1)>,
+
+=head1 HISTORY
+
+=for openssl foreign manual apropos(1)
+
+Initially, the manual page entry for the C<openssl I<cmd>> command used
+to be available at I<cmd>(1). Later, the alias B<openssl-I<cmd>>(1) was
+introduced, which made it easier to group the openssl commands using
+the L<apropos(1)> command or the shell's tab completion.
+
+In order to reduce cluttering of the global manual page namespace,
+the manual page entries without the 'openssl-' prefix have been
+deprecated in OpenSSL 3.0 and will be removed in OpenSSL 4.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-cmp.pod.in b/doc/man1/openssl-cmp.pod.in
new file mode 100644
index 000000000000..77e82091413b
--- /dev/null
+++ b/doc/man1/openssl-cmp.pod.in
@@ -0,0 +1,1244 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-cmp - Certificate Management Protocol (CMP, RFC 4210) application
+
+=head1 SYNOPSIS
+
+B<openssl> B<cmp>
+[B<-help>]
+[B<-config> I<filename>]
+[B<-section> I<names>]
+[B<-verbosity> I<level>]
+
+Generic message options:
+
+[B<-cmd> I<ir|cr|kur|p10cr|rr|genm>]
+[B<-infotype> I<name>]
+[B<-geninfo> I<OID:int:N>]
+
+Certificate enrollment options:
+
+[B<-newkey> I<filename>|I<uri>]
+[B<-newkeypass> I<arg>]
+[B<-subject> I<name>]
+[B<-issuer> I<name>]
+[B<-days> I<number>]
+[B<-reqexts> I<name>]
+[B<-sans> I<spec>]
+[B<-san_nodefault>]
+[B<-policies> I<name>]
+[B<-policy_oids> I<names>]
+[B<-policy_oids_critical>]
+[B<-popo> I<number>]
+[B<-csr> I<filename>]
+[B<-out_trusted> I<filenames>|I<uris>]
+[B<-implicit_confirm>]
+[B<-disable_confirm>]
+[B<-certout> I<filename>]
+[B<-chainout> I<filename>]
+
+Certificate enrollment and revocation options:
+
+[B<-oldcert> I<filename>|I<uri>]
+[B<-revreason> I<number>]
+
+Message transfer options:
+
+[B<-server> I<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]>]
+[B<-proxy> I<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]>]
+[B<-no_proxy> I<addresses>]
+[B<-recipient> I<name>]
+[B<-path> I<remote_path>]
+[B<-keep_alive> I<value>]
+[B<-msg_timeout> I<seconds>]
+[B<-total_timeout> I<seconds>]
+
+Server authentication options:
+
+[B<-trusted> I<filenames>|I<uris>]
+[B<-untrusted> I<filenames>|I<uris>]
+[B<-srvcert> I<filename>|I<uri>]
+[B<-expect_sender> I<name>]
+[B<-ignore_keyusage>]
+[B<-unprotected_errors>]
+[B<-extracertsout> I<filename>]
+[B<-cacertsout> I<filename>]
+
+Client authentication and protection options:
+
+[B<-ref> I<value>]
+[B<-secret> I<arg>]
+[B<-cert> I<filename>|I<uri>]
+[B<-own_trusted> I<filenames>|I<uris>]
+[B<-key> I<filename>|I<uri>]
+[B<-keypass> I<arg>]
+[B<-digest> I<name>]
+[B<-mac> I<name>]
+[B<-extracerts> I<filenames>|I<uris>]
+[B<-unprotected_requests>]
+
+Credentials format options:
+
+[B<-certform> I<PEM|DER>]
+[B<-keyform> I<PEM|DER|P12|ENGINE>]
+[B<-otherpass> I<arg>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+
+Random state options:
+
+{- $OpenSSL::safe::opt_r_synopsis -}
+
+TLS connection options:
+
+[B<-tls_used>]
+[B<-tls_cert> I<filename>|I<uri>]
+[B<-tls_key> I<filename>|I<uri>]
+[B<-tls_keypass> I<arg>]
+[B<-tls_extra> I<filenames>|I<uris>]
+[B<-tls_trusted> I<filenames>|I<uris>]
+[B<-tls_host> I<name>]
+
+Client-side debugging options:
+
+[B<-batch>]
+[B<-repeat> I<number>]
+[B<-reqin> I<filenames>]
+[B<-reqin_new_tid>]
+[B<-reqout> I<filenames>]
+[B<-rspin> I<filenames>]
+[B<-rspout> I<filenames>]
+[B<-use_mock_srv>]
+
+Mock server options:
+
+[B<-port> I<number>]
+[B<-max_msgs> I<number>]
+[B<-srv_ref> I<value>]
+[B<-srv_secret> I<arg>]
+[B<-srv_cert> I<filename>|I<uri>]
+[B<-srv_key> I<filename>|I<uri>]
+[B<-srv_keypass> I<arg>]
+[B<-srv_trusted> I<filenames>|I<uris>]
+[B<-srv_untrusted> I<filenames>|I<uris>]
+[B<-rsp_cert> I<filename>|I<uri>]
+[B<-rsp_extracerts> I<filenames>|I<uris>]
+[B<-rsp_capubs> I<filenames>|I<uris>]
+[B<-poll_count> I<number>]
+[B<-check_after> I<number>]
+[B<-grant_implicitconf>]
+[B<-pkistatus> I<number>]
+[B<-failure> I<number>]
+[B<-failurebits> I<number>]
+[B<-statusstring> I<arg>]
+[B<-send_error>]
+[B<-send_unprotected>]
+[B<-send_unprot_err>]
+[B<-accept_unprotected>]
+[B<-accept_unprot_err>]
+[B<-accept_raverified>]
+
+Certificate verification options, for both CMP and TLS:
+
+{- $OpenSSL::safe::opt_v_synopsis -}
+
+=head1 DESCRIPTION
+
+The B<cmp> command is a client implementation for the Certificate
+Management Protocol (CMP) as defined in RFC4210.
+It can be used to request certificates from a CA server,
+update their certificates,
+request certificates to be revoked, and perform other types of CMP requests.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Display a summary of all options
+
+=item B<-config> I<filename>
+
+Configuration file to use.
+An empty string C<""> means none.
+Default filename is from the environment variable C<OPENSSL_CONF>.
+
+=item B<-section> I<names>
+
+Section(s) to use within config file defining CMP options.
+An empty string C<""> means no specific section.
+Default is C<cmp>.
+
+Multiple section names may be given, separated by commas and/or whitespace
+(where in the latter case the whole argument must be enclosed in "...").
+Contents of sections named later may override contents of sections named before.
+In any case, as usual, the C<[default]> section and finally the unnamed
+section (as far as present) can provide per-option fallback values.
+
+=item B<-verbosity> I<level>
+
+Level of verbosity for logging, error output, etc.
+0 = EMERG, 1 = ALERT, 2 = CRIT, 3 = ERR, 4 = WARN, 5 = NOTE,
+6 = INFO, 7 = DEBUG, 8 = TRACE.
+Defaults to 6 = INFO.
+
+=back
+
+=head2 Generic message options
+
+=over 4
+
+=item B<-cmd> I<ir|cr|kur|p10cr|rr|genm>
+
+CMP command to execute.
+Currently implemented commands are:
+
+=over 8
+
+=item ir E<nbsp> - Initialization Request
+
+=item cr E<nbsp> - Certificate Request
+
+=item p10cr - PKCS#10 Certification Request (for legacy support)
+
+=item kur E<nbsp>E<nbsp>- Key Update Request
+
+=item rr E<nbsp> - Revocation Request
+
+=item genm - General Message
+
+=back
+
+B<ir> requests initialization of an end entity into a PKI hierarchy
+by issuing a first certificate.
+
+B<cr> requests issuing an additional certificate for an end entity already
+initialized to the PKI hierarchy.
+
+B<p10cr> requests issuing an additional certificate similarly to B<cr>
+but using legacy PKCS#10 CSR format.
+
+B<kur> requests a (key) update for an existing certificate.
+
+B<rr> requests revocation of an existing certificate.
+
+B<genm> requests information using a General Message, where optionally
+included B<InfoTypeAndValue>s may be used to state which info is of interest.
+Upon receipt of the General Response, information about all received
+ITAV B<infoType>s is printed to stdout.
+
+=item B<-infotype> I<name>
+
+Set InfoType name to use for requesting specific info in B<genm>,
+e.g., C<signKeyPairTypes>.
+
+=item B<-geninfo> I<OID:int:N>
+
+generalInfo integer values to place in request PKIHeader with given OID,
+e.g., C<1.2.3.4:int:56789>.
+
+=back
+
+=head2 Certificate enrollment options
+
+=over 4
+
+=item B<-newkey> I<filename>|I<uri>
+
+The source of the private or public key for the certificate requested
+in Initialization Request (IR), Certification Request(CR), or
+Key Update Request (KUR).
+Defaults to the public key in the PKCS#10 CSR given with the B<-csr> option,
+the public key of the reference certificate, or the current client key.
+
+=item B<-newkeypass> I<arg>
+
+Pass phrase source for the key given with the B<-newkey> option.
+If not given here, the password will be prompted for if needed.
+
+For more information about the format of I<arg> see
+L<openssl-passphrase-options(1)>.
+
+=item B<-subject> I<name>
+
+X509 Distinguished Name (DN) of subject to use in the requested certificate
+template.
+If the NULL-DN (C<"/">) is given then no subject is placed in the template.
+Default is the subject DN of any PKCS#10 CSR given with the B<-csr> option.
+For KUR, a further fallback is the subject DN
+of the reference certificate (see B<-oldcert>) if provided.
+This fallback is used for IR and CR only if no SANs are set.
+
+If provided and neither B<-cert> nor B<-oldcert> is given,
+the subject DN is used as fallback sender of outgoing CMP messages.
+
+The argument must be formatted as I</type0=value0/type1=value1/type2=...>.
+Special characters may be escaped by C<\> (backslash); whitespace is retained.
+Empty values are permitted, but the corresponding type will not be included.
+Giving a single C</> will lead to an empty sequence of RDNs (a NULL-DN).
+Multi-valued RDNs can be formed by placing a C<+> character instead of a C</>
+between the AttributeValueAssertions (AVAs) that specify the members of the set.
+Example:
+
+C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
+
+=item B<-issuer> I<name>
+
+X509 issuer Distinguished Name (DN) of the CA server
+to place in the requested certificate template in IR/CR/KUR.
+If the NULL-DN (C<"/">) is given then no issuer is placed in the template.
+
+If provided and neither B<-recipient> nor B<-srvcert> is given,
+the issuer DN is used as fallback recipient of outgoing CMP messages.
+
+The argument must be formatted as I</type0=value0/type1=value1/type2=...>.
+For details see the description of the B<-subject> option.
+
+=item B<-days> I<number>
+
+Number of days the new certificate is requested to be valid for, counting from
+the current time of the host.
+Also triggers the explicit request that the
+validity period starts from the current time (as seen by the host).
+
+=item B<-reqexts> I<name>
+
+Name of section in OpenSSL config file defining certificate request extensions.
+If the B<-csr> option is present, these extensions augment the extensions
+contained the given PKCS#10 CSR, overriding any extensions with same OIDs.
+
+=item B<-sans> I<spec>
+
+One or more IP addresses, DNS names, or URIs separated by commas or whitespace
+(where in the latter case the whole argument must be enclosed in "...")
+to add as Subject Alternative Name(s) (SAN) certificate request extension.
+If the special element "critical" is given the SANs are flagged as critical.
+Cannot be used if any Subject Alternative Name extension is set via B<-reqexts>.
+
+=item B<-san_nodefault>
+
+When Subject Alternative Names are not given via B<-sans>
+nor defined via B<-reqexts>,
+they are copied by default from the reference certificate (see B<-oldcert>).
+This can be disabled by giving the B<-san_nodefault> option.
+
+=item B<-policies> I<name>
+
+Name of section in OpenSSL config file defining policies to be set
+as certificate request extension.
+This option cannot be used together with B<-policy_oids>.
+
+=item B<-policy_oids> I<names>
+
+One or more OID(s), separated by commas and/or whitespace
+(where in the latter case the whole argument must be enclosed in "...")
+to add as certificate policies request extension.
+This option cannot be used together with B<-policies>.
+
+=item B<-policy_oids_critical>
+
+Flag the policies given with B<-policy_oids> as critical.
+
+=item B<-popo> I<number>
+
+Proof-of-Possession (POPO) method to use for IR/CR/KUR; values: C<-1>..<2> where
+C<-1> = NONE, C<0> = RAVERIFIED, C<1> = SIGNATURE (default), C<2> = KEYENC.
+
+Note that a signature-based POPO can only be produced if a private key
+is provided via the B<-newkey> or B<-key> options.
+
+=item B<-csr> I<filename>
+
+PKCS#10 CSR in PEM or DER format containing a certificate request.
+With B<-cmd> I<p10cr> it is used directly in a legacy P10CR message.
+When used with B<-cmd> I<ir>, I<cr>, or I<kur>,
+it is transformed into the respective regular CMP request,
+while its public key is ignored if I<-newkey> is given.
+It may also be used with B<-cmd> I<rr> to specify the certificate to be revoked
+via the included subject name and public key.
+
+=item B<-out_trusted> I<filenames>|I<uris>
+
+Trusted certificate(s) to use for validating the newly enrolled certificate.
+
+Multiple sources may be given, separated by commas and/or whitespace
+(where in the latter case the whole argument must be enclosed in "...").
+Each source may contain multiple certificates.
+
+The certificate verification options
+B<-verify_hostname>, B<-verify_ip>, and B<-verify_email>
+only affect the certificate verification enabled via this option.
+
+=item B<-implicit_confirm>
+
+Request implicit confirmation of newly enrolled certificates.
+
+=item B<-disable_confirm>
+
+Do not send certificate confirmation message for newly enrolled certificate
+without requesting implicit confirmation
+to cope with broken servers not supporting implicit confirmation correctly.
+B<WARNING:> This leads to behavior violating RFC 4210.
+
+=item B<-certout> I<filename>
+
+The file where the newly enrolled certificate should be saved.
+
+=item B<-chainout> I<filename>
+
+The file where the chain of the newly enrolled certificate should be saved.
+
+=back
+
+=head2 Certificate enrollment and revocation options
+
+=over 4
+
+=item B<-oldcert> I<filename>|I<uri>
+
+The certificate to be updated (i.e., renewed or re-keyed) in Key Update Request
+(KUR) messages or to be revoked in Revocation Request (RR) messages.
+For KUR the certificate to be updated defaults to B<-cert>,
+and the resulting certificate is called I<reference certificate>.
+For RR the certificate to be revoked can also be specified using B<-csr>.
+
+The reference certificate, if any, is also used for
+deriving default subject DN and Subject Alternative Names and the
+default issuer entry in the requested certificate template of an IR/CR/KUR.
+Its subject is used as sender of outgoing messages if B<-cert> is not given.
+Its issuer is used as default recipient in CMP message headers
+if neither B<-recipient>, B<-srvcert>, nor B<-issuer> is given.
+
+=item B<-revreason> I<number>
+
+Set CRLReason to be included in revocation request (RR); values: C<0>..C<10>
+or C<-1> for none (which is the default).
+
+Reason numbers defined in RFC 5280 are:
+
+ CRLReason ::= ENUMERATED {
+ unspecified (0),
+ keyCompromise (1),
+ cACompromise (2),
+ affiliationChanged (3),
+ superseded (4),
+ cessationOfOperation (5),
+ certificateHold (6),
+ -- value 7 is not used
+ removeFromCRL (8),
+ privilegeWithdrawn (9),
+ aACompromise (10)
+ }
+
+=back
+
+=head2 Message transfer options
+
+=over 4
+
+=item B<-server> I<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]>
+
+The DNS hostname or IP address and optionally port
+of the CMP server to connect to using HTTP(S).
+This excludes I<-port> and I<-use_mock_srv> and is ignored with I<-rspin>.
+
+The scheme C<https> may be given only if the B<-tls_used> option is used.
+In this case the default port is 443, else 80.
+The optional userinfo and fragment components are ignored.
+Any given query component is handled as part of the path component.
+If a path is included it provides the default value for the B<-path> option.
+
+=item B<-proxy> I<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]>
+
+The HTTP(S) proxy server to use for reaching the CMP server unless B<-no_proxy>
+applies, see below.
+The proxy port defaults to 80 or 443 if the scheme is C<https>; apart from that
+the optional C<http://> or C<https://> prefix is ignored (note that TLS may be
+selected by B<-tls_used>), as well as any path, userinfo, and query, and fragment
+components.
+Defaults to the environment variable C<http_proxy> if set, else C<HTTP_PROXY>
+in case no TLS is used, otherwise C<https_proxy> if set, else C<HTTPS_PROXY>.
+This option is ignored if I<-server> is not given.
+
+=item B<-no_proxy> I<addresses>
+
+List of IP addresses and/or DNS names of servers
+not to use an HTTP(S) proxy for, separated by commas and/or whitespace
+(where in the latter case the whole argument must be enclosed in "...").
+Default is from the environment variable C<no_proxy> if set, else C<NO_PROXY>.
+This option is ignored if I<-server> is not given.
+
+=item B<-recipient> I<name>
+
+Distinguished Name (DN) to use in the recipient field of CMP request message
+headers, i.e., the CMP server (usually the addressed CA).
+
+The recipient field in the header of a CMP message is mandatory.
+If not given explicitly the recipient is determined in the following order:
+the subject of the CMP server certificate given with the B<-srvcert> option,
+the B<-issuer> option,
+the issuer of the certificate given with the B<-oldcert> option,
+the issuer of the CMP client certificate (B<-cert> option),
+as far as any of those is present, else the NULL-DN as last resort.
+
+The argument must be formatted as I</type0=value0/type1=value1/type2=...>.
+For details see the description of the B<-subject> option.
+
+=item B<-path> I<remote_path>
+
+HTTP path at the CMP server (aka CMP alias) to use for POST requests.
+Defaults to any path given with B<-server>, else C<"/">.
+
+=item B<-keep_alive> I<value>
+
+If the given value is 0 then HTTP connections are not kept open
+after receiving a response, which is the default behavior for HTTP 1.0.
+If the value is 1 or 2 then persistent connections are requested.
+If the value is 2 then persistent connections are required,
+i.e., in case the server does not grant them an error occurs.
+The default value is 1, which means preferring to keep the connection open.
+
+=item B<-msg_timeout> I<seconds>
+
+Number of seconds a CMP request-response message round trip
+is allowed to take before a timeout error is returned.
+A value <= 0 means no limitation (waiting indefinitely).
+Default is to use the B<-total_timeout> setting.
+
+=item B<-total_timeout> I<seconds>
+
+Maximum total number of seconds a transaction may take,
+including polling etc.
+A value <= 0 means no limitation (waiting indefinitely).
+Default is 0.
+
+=back
+
+=head2 Server authentication options
+
+=over 4
+
+=item B<-trusted> I<filenames>|I<uris>
+
+When validating signature-based protection of CMP response messages,
+these are the CA certificate(s) to trust while checking certificate chains
+during CMP server authentication.
+This option gives more flexibility than the B<-srvcert> option because the
+server-side CMP signer certificate is not pinned but may be any certificate
+for which a chain to one of the given trusted certificates can be constructed.
+
+If no B<-trusted>, B<-srvcert>, and B<-secret> option is given
+then protected response messages from the server are not authenticated.
+
+Multiple sources may be given, separated by commas and/or whitespace
+(where in the latter case the whole argument must be enclosed in "...").
+Each source may contain multiple certificates.
+
+The certificate verification options
+B<-verify_hostname>, B<-verify_ip>, and B<-verify_email>
+have no effect on the certificate verification enabled via this option.
+
+=item B<-untrusted> I<filenames>|I<uris>
+
+Non-trusted intermediate CA certificate(s).
+Any extra certificates given with the B<-cert> option are appended to it.
+All these certificates may be useful for cert path construction
+for the CMP client certificate (to include in the extraCerts field of outgoing
+messages) and for the TLS client certificate (if TLS is enabled)
+as well as for chain building
+when validating the CMP server certificate (checking signature-based
+CMP message protection) and when validating newly enrolled certificates.
+
+Multiple sources may be given, separated by commas and/or whitespace.
+Each file may contain multiple certificates.
+
+=item B<-srvcert> I<filename>|I<uri>
+
+The specific CMP server certificate to expect and directly trust (even if it is
+expired) when validating signature-based protection of CMP response messages.
+May be set alternatively to the B<-trusted> option to pin the accepted server.
+
+If set, the subject of the certificate is also used
+as default value for the recipient of CMP requests
+and as default value for the expected sender of incoming CMP messages.
+
+=item B<-expect_sender> I<name>
+
+Distinguished Name (DN) expected in the sender field of incoming CMP messages.
+Defaults to the subject DN of the pinned B<-srvcert>, if any.
+
+This can be used to make sure that only a particular entity is accepted as
+CMP message signer, and attackers are not able to use arbitrary certificates
+of a trusted PKI hierarchy to fraudulently pose as a CMP server.
+Note that this option gives slightly more freedom than setting the B<-srvcert>,
+which pins the server to the holder of a particular certificate, while the
+expected sender name will continue to match after updates of the server cert.
+
+The argument must be formatted as I</type0=value0/type1=value1/type2=...>.
+For details see the description of the B<-subject> option.
+
+=item B<-ignore_keyusage>
+
+Ignore key usage restrictions in CMP signer certificates when validating
+signature-based protection of incoming CMP messages,
+else C<digitalSignature> must be allowed for signer certificate.
+
+=item B<-unprotected_errors>
+
+Accept missing or invalid protection of negative responses from the server.
+This applies to the following message types and contents:
+
+=over 4
+
+=item * error messages
+
+=item * negative certificate responses (IP/CP/KUP)
+
+=item * negative revocation responses (RP)
+
+=item * negative PKIConf messages
+
+=back
+
+B<WARNING:> This setting leads to unspecified behavior and it is meant
+exclusively to allow interoperability with server implementations violating
+RFC 4210, e.g.:
+
+=over 4
+
+=item * section 5.1.3.1 allows exceptions from protecting only for special
+cases:
+"There MAY be cases in which the PKIProtection BIT STRING is deliberately not
+used to protect a message [...] because other protection, external to PKIX, will
+be applied instead."
+
+=item * section 5.3.21 is clear on ErrMsgContent: "The CA MUST always sign it
+with a signature key."
+
+=item * appendix D.4 shows PKIConf message having protection
+
+=back
+
+=item B<-extracertsout> I<filename>
+
+The file where to save all certificates contained in the extraCerts field
+of the last received response message (except for pollRep and PKIConf).
+
+=item B<-cacertsout> I<filename>
+
+The file where to save any CA certificates contained in the caPubs field of
+the last received certificate response (i.e., IP, CP, or KUP) message.
+
+=back
+
+=head2 Client authentication options
+
+=over 4
+
+=item B<-ref> I<value>
+
+Reference number/string/value to use as fallback senderKID; this is required
+if no sender name can be determined from the B<-cert> or <-subject> options and
+is typically used when authenticating with pre-shared key (password-based MAC).
+
+=item B<-secret> I<arg>
+
+Prefer PBM-based message protection with given source of a secret value.
+The secret is used for creating PBM-based protection of outgoing messages
+and (as far as needed) for validating PBM-based protection of incoming messages.
+PBM stands for Password-Based Message Authentication Code.
+This takes precedence over the B<-cert> and B<-key> options.
+
+For more information about the format of I<arg> see
+L<openssl-passphrase-options(1)>.
+
+=item B<-cert> I<filename>|I<uri>
+
+The client's current CMP signer certificate.
+Requires the corresponding key to be given with B<-key>.
+The subject of this certificate will be used as sender of outgoing CMP messages,
+while the subject of B<-oldcert> or B<-subjectName> may provide fallback values.
+The issuer of this certificate is used as one of the recipient fallback values
+and as fallback issuer entry in the certificate template of IR/CR/KUR.
+When using signature-based message protection, this "protection certificate"
+will be included first in the extraCerts field of outgoing messages
+and the signature is done with the corresponding key.
+In Initialization Request (IR) messages this can be used for authenticating
+using an external entity certificate as defined in appendix E.7 of RFC 4210.
+For Key Update Request (KUR) messages this is also used as
+the certificate to be updated if the B<-oldcert> option is not given.
+If the file includes further certs, they are appended to the untrusted certs
+because they typically constitute the chain of the client certificate, which
+is included in the extraCerts field in signature-protected request messages.
+
+=item B<-own_trusted> I<filenames>|I<uris>
+
+If this list of certificates is provided then the chain built for
+the client-side CMP signer certificate given with the B<-cert> option
+is verified using the given certificates as trust anchors.
+
+Multiple sources may be given, separated by commas and/or whitespace
+(where in the latter case the whole argument must be enclosed in "...").
+Each source may contain multiple certificates.
+
+The certificate verification options
+B<-verify_hostname>, B<-verify_ip>, and B<-verify_email>
+have no effect on the certificate verification enabled via this option.
+
+=item B<-key> I<filename>|I<uri>
+
+The corresponding private key file for the client's current certificate given in
+the B<-cert> option.
+This will be used for signature-based message protection unless
+the B<-secret> option indicating PBM or B<-unprotected_requests> is given.
+
+=item B<-keypass> I<arg>
+
+Pass phrase source for the private key given with the B<-key> option.
+Also used for B<-cert> and B<-oldcert> in case it is an encrypted PKCS#12 file.
+If not given here, the password will be prompted for if needed.
+
+For more information about the format of I<arg> see
+L<openssl-passphrase-options(1)>.
+
+=item B<-digest> I<name>
+
+Specifies name of supported digest to use in RFC 4210's MSG_SIG_ALG
+and as the one-way function (OWF) in MSG_MAC_ALG.
+If applicable, this is used for message protection and
+Proof-of-Possession (POPO) signatures.
+To see the list of supported digests, use C<openssl list -digest-commands>.
+Defaults to C<sha256>.
+
+=item B<-mac> I<name>
+
+Specifies the name of the MAC algorithm in MSG_MAC_ALG.
+To get the names of supported MAC algorithms use C<openssl list -mac-algorithms>
+and possibly combine such a name with the name of a supported digest algorithm,
+e.g., hmacWithSHA256.
+Defaults to C<hmac-sha1> as per RFC 4210.
+
+=item B<-extracerts> I<filenames>|I<uris>
+
+Certificates to append in the extraCerts field when sending messages.
+They can be used as the default CMP signer certificate chain to include.
+
+Multiple sources may be given, separated by commas and/or whitespace
+(where in the latter case the whole argument must be enclosed in "...").
+Each source may contain multiple certificates.
+
+=item B<-unprotected_requests>
+
+Send messages without CMP-level protection.
+
+=back
+
+=head2 Credentials format options
+
+=over 4
+
+=item B<-certform> I<PEM|DER>
+
+File format to use when saving a certificate to a file.
+Default value is PEM.
+
+=item B<-keyform> I<PEM|DER|P12|ENGINE>
+
+The format of the key input; unspecified by default.
+See L<openssl(1)/Format Options> for details.
+
+=item B<-otherpass> I<arg>
+
+Pass phrase source for certificate given with the B<-trusted>, B<-untrusted>,
+B<-own_trusted>, B<-srvcert>, B<-out_trusted>, B<-extracerts>,
+B<-srv_trusted>, B<-srv_untrusted>, B<-rsp_extracerts>, B<-rsp_capubs>,
+B<-tls_extra>, and B<-tls_trusted> options.
+If not given here, the password will be prompted for if needed.
+
+For more information about the format of I<arg> see
+L<openssl-passphrase-options(1)>.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- output_off() if $disabled{"deprecated-3.0"}; "" -}
+As an alternative to using this combination:
+
+ -engine {engineid} -key {keyid} -keyform ENGINE
+
+... it's also possible to just give the key ID in URI form to B<-key>,
+like this:
+
+ -key org.openssl.engine:{engineid}:{keyid}
+
+This applies to all options specifying keys: B<-key>, B<-newkey>, and
+B<-tls_key>.
+{- output_on() if $disabled{"deprecated-3.0"}; "" -}
+
+=back
+
+=head2 Provider options
+
+=over 4
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head2 Random state options
+
+=over 4
+
+{- $OpenSSL::safe::opt_r_item -}
+
+=back
+
+=head2 TLS connection options
+
+=over 4
+
+=item B<-tls_used>
+
+Enable using TLS (even when other TLS_related options are not set)
+when connecting to CMP server via HTTP.
+This option is not supported with the I<-port> option
+and is ignored with the I<-use_mock_srv> and I<-rspin> options
+or if the I<-server> option is not given.
+
+=item B<-tls_cert> I<filename>|I<uri>
+
+Client's TLS certificate.
+If the source includes further certs they are used (along with B<-untrusted>
+certs) for constructing the client cert chain provided to the TLS server.
+
+=item B<-tls_key> I<filename>|I<uri>
+
+Private key for the client's TLS certificate.
+
+=item B<-tls_keypass> I<arg>
+
+Pass phrase source for client's private TLS key B<-tls_key>.
+Also used for B<-tls_cert> in case it is an encrypted PKCS#12 file.
+If not given here, the password will be prompted for if needed.
+
+For more information about the format of I<arg> see
+L<openssl-passphrase-options(1)>.
+
+=item B<-tls_extra> I<filenames>|I<uris>
+
+Extra certificates to provide to TLS server during TLS handshake
+
+=item B<-tls_trusted> I<filenames>|I<uris>
+
+Trusted certificate(s) to use for validating the TLS server certificate.
+This implies hostname validation.
+
+Multiple sources may be given, separated by commas and/or whitespace
+(where in the latter case the whole argument must be enclosed in "...").
+Each source may contain multiple certificates.
+
+The certificate verification options
+B<-verify_hostname>, B<-verify_ip>, and B<-verify_email>
+have no effect on the certificate verification enabled via this option.
+
+=item B<-tls_host> I<name>
+
+Address to be checked during hostname validation.
+This may be a DNS name or an IP address.
+If not given it defaults to the B<-server> address.
+
+=back
+
+=head2 Client-side debugging options
+
+=over 4
+
+=item B<-batch>
+
+Do not interactively prompt for input, for instance when a password is needed.
+This can be useful for batch processing and testing.
+
+=item B<-repeat> I<number>
+
+Invoke the command the given positive number of times with the same parameters.
+Default is one invocation.
+
+=item B<-reqin> I<filenames>
+
+Take sequence of CMP requests from file(s).
+
+Multiple filenames may be given, separated by commas and/or whitespace
+(where in the latter case the whole argument must be enclosed in "...").
+As many files are read as needed for a complete transaction.
+
+=item B<-reqin_new_tid>
+
+Use a fresh transactionID for CMP request messages read using B<-reqin>,
+which requires re-protecting them as far as they were protected before.
+This may be needed in case the sequence of requests is reused
+and the CMP server complains that the transaction ID has already been used.
+
+=item B<-reqout> I<filenames>
+
+Save sequence of CMP requests to file(s).
+
+Multiple filenames may be given, separated by commas and/or whitespace.
+As many files are written as needed to store the complete transaction.
+
+=item B<-rspin> I<filenames>
+
+Process sequence of CMP responses provided in file(s), skipping server.
+This excludes I<-server>, I<-port>, and I<-use_mock_srv>.
+
+Multiple filenames may be given, separated by commas and/or whitespace.
+As many files are read as needed for the complete transaction.
+
+=item B<-rspout> I<filenames>
+
+Save sequence of CMP responses to file(s).
+
+Multiple filenames may be given, separated by commas and/or whitespace.
+As many files are written as needed to store the complete transaction.
+
+=item B<-use_mock_srv>
+
+Test the client using the internal CMP server mock-up at API level,
+bypassing socket-based transfer via HTTP.
+This excludes I<-server>, I<-port>, and I<-rspin>.
+
+=back
+
+=head2 Mock server options
+
+=over 4
+
+=item B<-port> I<number>
+
+Act as HTTP-based CMP server mock-up listening on the given port.
+This excludes I<-server>, I<-rspin>, and I<-use_mock_srv>.
+
+=item B<-max_msgs> I<number>
+
+Maximum number of CMP (request) messages the CMP HTTP server mock-up
+should handle, which must be nonnegative.
+The default value is 0, which means that no limit is imposed.
+In any case the server terminates on internal errors, but not when it
+detects a CMP-level error that it can successfully answer with an error message.
+
+=item B<-srv_ref> I<value>
+
+Reference value to use as senderKID of server in case no B<-srv_cert> is given.
+
+=item B<-srv_secret> I<arg>
+
+Password source for server authentication with a pre-shared key (secret).
+
+=item B<-srv_cert> I<filename>|I<uri>
+
+Certificate of the server.
+
+=item B<-srv_key> I<filename>|I<uri>
+
+Private key used by the server for signing messages.
+
+=item B<-srv_keypass> I<arg>
+
+Server private key (and cert) file pass phrase source.
+
+=item B<-srv_trusted> I<filenames>|I<uris>
+
+Trusted certificates for client authentication.
+
+The certificate verification options
+B<-verify_hostname>, B<-verify_ip>, and B<-verify_email>
+have no effect on the certificate verification enabled via this option.
+
+=item B<-srv_untrusted> I<filenames>|I<uris>
+
+Intermediate CA certs that may be useful when validating client certificates.
+
+=item B<-rsp_cert> I<filename>|I<uri>
+
+Certificate to be returned as mock enrollment result.
+
+=item B<-rsp_extracerts> I<filenames>|I<uris>
+
+Extra certificates to be included in mock certification responses.
+
+=item B<-rsp_capubs> I<filenames>|I<uris>
+
+CA certificates to be included in mock Initialization Response (IP) message.
+
+=item B<-poll_count> I<number>
+
+Number of times the client must poll before receiving a certificate.
+
+=item B<-check_after> I<number>
+
+The checkAfter value (number of seconds to wait) to include in poll response.
+
+=item B<-grant_implicitconf>
+
+Grant implicit confirmation of newly enrolled certificate.
+
+=item B<-pkistatus> I<number>
+
+PKIStatus to be included in server response.
+Valid range is 0 (accepted) .. 6 (keyUpdateWarning).
+
+=item B<-failure> I<number>
+
+A single failure info bit number to be included in server response.
+Valid range is 0 (badAlg) .. 26 (duplicateCertReq).
+
+=item B<-failurebits> I<number>
+Number representing failure bits to be included in server response.
+Valid range is 0 .. 2^27 - 1.
+
+=item B<-statusstring> I<arg>
+
+Text to be included as status string in server response.
+
+=item B<-send_error>
+
+Force server to reply with error message.
+
+=item B<-send_unprotected>
+
+Send response messages without CMP-level protection.
+
+=item B<-send_unprot_err>
+
+In case of negative responses, server shall send unprotected error messages,
+certificate responses (IP/CP/KUP), and revocation responses (RP).
+WARNING: This setting leads to behavior violating RFC 4210.
+
+=item B<-accept_unprotected>
+
+Accept missing or invalid protection of requests.
+
+=item B<-accept_unprot_err>
+
+Accept unprotected error messages from client.
+
+=item B<-accept_raverified>
+
+Accept RAVERIFED as proof-of-possession (POPO).
+
+=back
+
+=head2 Certificate verification options, for both CMP and TLS
+
+=over 4
+
+{- $OpenSSL::safe::opt_v_item -}
+
+The certificate verification options
+B<-verify_hostname>, B<-verify_ip>, and B<-verify_email>
+only affect the certificate verification enabled via the B<-out_trusted> option.
+
+=back
+
+=head1 NOTES
+
+When setting up CMP configurations and experimenting with enrollment options
+typically various errors occur until the configuration is correct and complete.
+When the CMP server reports an error the client will by default
+check the protection of the CMP response message.
+Yet some CMP services tend not to protect negative responses.
+In this case the client will reject them, and thus their contents are not shown
+although they usually contain hints that would be helpful for diagnostics.
+For assisting in such cases the CMP client offers a workaround via the
+B<-unprotected_errors> option, which allows accepting such negative messages.
+
+=head1 EXAMPLES
+
+=head2 Simple examples using the default OpenSSL configuration file
+
+This CMP client implementation comes with demonstrative CMP sections
+in the example configuration file F<openssl/apps/openssl.cnf>,
+which can be used to interact conveniently with the Insta Demo CA.
+
+In order to enroll an initial certificate from that CA it is sufficient
+to issue the following shell commands.
+
+ export OPENSSL_CONF=/path/to/openssl/apps/openssl.cnf
+
+=begin comment
+
+ wget 'http://pki.certificate.fi:8081/install-ca-cert.html/ca-certificate.crt\
+ ?ca-id=632&download-certificate=1' -O insta.ca.crt
+
+=end comment
+
+ openssl genrsa -out insta.priv.pem
+ openssl cmp -section insta
+
+This should produce the file F<insta.cert.pem> containing a new certificate
+for the private key held in F<insta.priv.pem>.
+It can be viewed using, e.g.,
+
+ openssl x509 -noout -text -in insta.cert.pem
+
+In case the network setup requires using an HTTP proxy it may be given as usual
+via the environment variable B<http_proxy> or via the B<-proxy> option in the
+configuration file or the CMP command-line argument B<-proxy>, for example
+
+ -proxy http://192.168.1.1:8080
+
+In the Insta Demo CA scenario both clients and the server may use the pre-shared
+secret I<insta> and the reference value I<3078> to authenticate to each other.
+
+Alternatively, CMP messages may be protected in signature-based manner,
+where the trust anchor in this case is F<insta.ca.crt>
+and the client may use any certificate already obtained from that CA,
+as specified in the B<[signature]> section of the example configuration.
+This can be used in combination with the B<[insta]> section simply by
+
+ openssl cmp -section insta,signature
+
+By default the CMP IR message type is used, yet CR works equally here.
+This may be specified directly at the command line:
+
+ openssl cmp -section insta -cmd cr
+
+or by referencing in addition the B<[cr]> section of the example configuration:
+
+ openssl cmp -section insta,cr
+
+In order to update the enrolled certificate one may call
+
+ openssl cmp -section insta,kur
+
+using with PBM-based protection or
+
+ openssl cmp -section insta,kur,signature
+
+using signature-based protection.
+
+In a similar way any previously enrolled certificate may be revoked by
+
+ openssl cmp -section insta,rr -trusted insta.ca.crt
+
+or
+
+ openssl cmp -section insta,rr,signature
+
+Many more options can be given in the configuration file
+and/or on the command line.
+For instance, the B<-reqexts> CLI option may refer to a section in the
+configuration file defining X.509 extensions to use in certificate requests,
+such as C<v3_req> in F<openssl/apps/openssl.cnf>:
+
+ openssl cmp -section insta,cr -reqexts v3_req
+
+=head2 Certificate enrollment
+
+The following examples do not make use of a configuration file at first.
+They assume that a CMP server can be contacted on the local TCP port 80
+and accepts requests under the alias I</pkix/>.
+
+For enrolling its very first certificate the client generates a client key
+and sends an initial request message to the local CMP server
+using a pre-shared secret key for mutual authentication.
+In this example the client does not have the CA certificate yet,
+so we specify the name of the CA with the B<-recipient> option
+and save any CA certificates that we may receive in the C<capubs.pem> file.
+
+In below command line usage examples the C<\> at line ends is used just
+for formatting; each of the command invocations should be on a single line.
+
+ openssl genrsa -out cl_key.pem
+ openssl cmp -cmd ir -server 127.0.0.1:80/pkix/ -recipient "/CN=CMPserver" \
+ -ref 1234 -secret pass:1234-5678 \
+ -newkey cl_key.pem -subject "/CN=MyName" \
+ -cacertsout capubs.pem -certout cl_cert.pem
+
+=head2 Certificate update
+
+Then, when the client certificate and its related key pair needs to be updated,
+the client can send a key update request taking the certs in C<capubs.pem>
+as trusted for authenticating the server and using the previous cert and key
+for its own authentication.
+Then it can start using the new cert and key.
+
+ openssl genrsa -out cl_key_new.pem
+ openssl cmp -cmd kur -server 127.0.0.1:80/pkix/ \
+ -trusted capubs.pem \
+ -cert cl_cert.pem -key cl_key.pem \
+ -newkey cl_key_new.pem -certout cl_cert.pem
+ cp cl_key_new.pem cl_key.pem
+
+This command sequence can be repated as often as needed.
+
+=head2 Requesting information from CMP server
+
+Requesting "all relevant information" with an empty General Message.
+This prints information about all received ITAV B<infoType>s to stdout.
+
+ openssl cmp -cmd genm -server 127.0.0.1/pkix/ -recipient "/CN=CMPserver" \
+ -ref 1234 -secret pass:1234-5678
+
+=head2 Using a custom configuration file
+
+For CMP client invocations, in particular for certificate enrollment,
+usually many parameters need to be set, which is tedious and error-prone to do
+on the command line.
+Therefore, the client offers the possibility to read
+options from sections of the OpenSSL config file, usually called F<openssl.cnf>.
+The values found there can still be extended and even overridden by any
+subsequently loaded sections and on the command line.
+
+After including in the configuration file the following sections:
+
+ [cmp]
+ server = 127.0.0.1
+ path = pkix/
+ trusted = capubs.pem
+ cert = cl_cert.pem
+ key = cl_key.pem
+ newkey = cl_key.pem
+ certout = cl_cert.pem
+
+ [init]
+ recipient = "/CN=CMPserver"
+ trusted =
+ cert =
+ key =
+ ref = 1234
+ secret = pass:1234-5678-1234-567
+ subject = "/CN=MyName"
+ cacertsout = capubs.pem
+
+the above enrollment transactions reduce to
+
+ openssl cmp -section cmp,init
+ openssl cmp -cmd kur -newkey cl_key_new.pem
+
+and the above transaction using a general message reduces to
+
+ openssl cmp -section cmp,init -cmd genm
+
+=head1 SEE ALSO
+
+L<openssl-genrsa(1)>, L<openssl-ecparam(1)>, L<openssl-list(1)>,
+L<openssl-req(1)>, L<openssl-x509(1)>, L<x509v3_config(5)>
+
+=head1 HISTORY
+
+The B<cmp> application was added in OpenSSL 3.0.
+
+The B<-engine option> was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-cms.pod.in b/doc/man1/openssl-cms.pod.in
new file mode 100644
index 000000000000..c63a7f330ba6
--- /dev/null
+++ b/doc/man1/openssl-cms.pod.in
@@ -0,0 +1,912 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-cms - CMS command
+
+=head1 SYNOPSIS
+
+B<openssl> B<cms>
+[B<-help>]
+
+General options:
+
+[B<-in> I<filename>]
+[B<-out> I<filename>]
+{- $OpenSSL::safe::opt_config_synopsis -}
+
+Operation options:
+
+[B<-encrypt>]
+[B<-decrypt>]
+[B<-sign>]
+[B<-verify>]
+[B<-resign>]
+[B<-sign_receipt>]
+[B<-verify_receipt> I<receipt>]
+[B<-digest_create>]
+[B<-digest_verify>]
+[B<-compress>]
+[B<-uncompress>]
+[B<-EncryptedData_encrypt>]
+[B<-EncryptedData_decrypt>]
+[B<-data_create>]
+[B<-data_out>]
+[B<-cmsout>]
+
+File format options:
+
+[B<-inform> B<DER>|B<PEM>|B<SMIME>]
+[B<-outform> B<DER>|B<PEM>|B<SMIME>]
+[B<-rctform> B<DER>|B<PEM>|B<SMIME>]
+[B<-stream>]
+[B<-indef>]
+[B<-noindef>]
+[B<-binary>]
+[B<-crlfeol>]
+[B<-asciicrlf>]
+
+Keys and password options:
+
+[B<-pwri_password> I<password>]
+[B<-secretkey> I<key>]
+[B<-secretkeyid> I<id>]
+[B<-inkey> I<filename>|I<uri>]
+[B<-passin> I<arg>]
+[B<-keyopt> I<name>:I<parameter>]
+[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+{- $OpenSSL::safe::opt_r_synopsis -}
+
+Encryption options:
+
+[B<-originator> I<file>]
+[B<-recip> I<file>]
+[I<recipient-cert> ...]
+[B<-I<cipher>>]
+[B<-wrap> I<cipher>]
+[B<-aes128-wrap>]
+[B<-aes192-wrap>]
+[B<-aes256-wrap>]
+[B<-des3-wrap>]
+[B<-debug_decrypt>]
+
+Signing options:
+
+[B<-md> I<digest>]
+[B<-signer> I<file>]
+[B<-certfile> I<file>]
+[B<-cades>]
+[B<-nodetach>]
+[B<-nocerts>]
+[B<-noattr>]
+[B<-nosmimecap>]
+[B<-receipt_request_all>]
+[B<-receipt_request_first>]
+[B<-receipt_request_from> I<emailaddress>]
+[B<-receipt_request_to> I<emailaddress>]
+
+Verification options:
+
+[B<-signer> I<file>]
+[B<-content> I<filename>]
+[B<-no_content_verify>]
+[B<-no_attr_verify>]
+[B<-nosigs>]
+[B<-noverify>]
+[B<-nointern>]
+[B<-cades>]
+[B<-verify_retcode>]
+{- $OpenSSL::safe::opt_trust_synopsis -}
+
+Output options:
+
+[B<-keyid>]
+[B<-econtent_type> I<type>]
+[B<-text>]
+[B<-certsout> I<file>]
+[B<-to> I<addr>]
+[B<-from> I<addr>]
+[B<-subject> I<subj>]
+
+Printing options:
+
+[B<-noout>]
+[B<-print>]
+[B<-nameopt> I<option>]
+[B<-receipt_request_print>]
+
+Validation options:
+
+{- $OpenSSL::safe::opt_v_synopsis -}
+
+=head1 DESCRIPTION
+
+This command handles data in CMS format such as S/MIME v3.1 email messages.
+It can encrypt, decrypt, sign, verify, compress, uncompress, and print messages.
+
+=head1 OPTIONS
+
+There are a number of operation options that set the type of operation to be
+performed: encrypt, decrypt, sign, verify, resign, sign_receipt, verify_receipt,
+digest_create, digest_verify, compress, uncompress,
+EncryptedData_encrypt, EncryptedData_decrypt, data_create, data_out, or cmsout.
+The relevance of the other options depends on the operation type
+and their meaning may vary according to it.
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=back
+
+=head2 General options
+
+=over 4
+
+=item B<-in> I<filename>
+
+The input message to be encrypted or signed or the message to be decrypted
+or verified.
+
+=item B<-out> I<filename>
+
+The message text that has been decrypted or verified or the output MIME
+format message that has been signed or verified.
+
+{- $OpenSSL::safe::opt_config_item -}
+
+=back
+
+=head2 Operation options
+
+=over 4
+
+=item B<-encrypt>
+
+Encrypt data for the given recipient certificates. Input file is the message
+to be encrypted. The output file is the encrypted data in MIME format. The
+actual CMS type is B<EnvelopedData>.
+
+Note that no revocation check is done for the recipient cert, so if that
+key has been compromised, others may be able to decrypt the text.
+
+=item B<-decrypt>
+
+Decrypt data using the supplied certificate and private key. Expects
+encrypted datain MIME format for the input file. The decrypted data
+is written to the output file.
+
+=item B<-sign>
+
+Sign data using the supplied certificate and private key. Input file is
+the message to be signed. The signed data in MIME format is written
+to the output file.
+
+=item B<-verify>
+
+Verify signed data. Expects a signed data on input and outputs
+the signed data. Both clear text and opaque signing is supported.
+
+=item B<-resign>
+
+Resign a message: take an existing message and one or more new signers.
+
+=item B<-sign_receipt>
+
+Generate and output a signed receipt for the supplied message. The input
+message B<must> contain a signed receipt request. Functionality is otherwise
+similar to the B<-sign> operation.
+
+=item B<-verify_receipt> I<receipt>
+
+Verify a signed receipt in filename B<receipt>. The input message B<must>
+contain the original receipt request. Functionality is otherwise similar
+to the B<-verify> operation.
+
+=item B<-digest_create>
+
+Create a CMS B<DigestedData> type.
+
+=item B<-digest_verify>
+
+Verify a CMS B<DigestedData> type and output the content.
+
+=item B<-compress>
+
+Create a CMS B<CompressedData> type. OpenSSL must be compiled with B<zlib>
+support for this option to work, otherwise it will output an error.
+
+=item B<-uncompress>
+
+Uncompress a CMS B<CompressedData> type and output the content. OpenSSL must be
+compiled with B<zlib> support for this option to work, otherwise it will
+output an error.
+
+=item B<-EncryptedData_encrypt>
+
+Encrypt content using supplied symmetric key and algorithm using a CMS
+B<EncryptedData> type and output the content.
+
+=item B<-EncryptedData_decrypt>
+
+Decrypt content using supplied symmetric key and algorithm using a CMS
+B<EncryptedData> type and output the content.
+
+=item B<-data_create>
+
+Create a CMS B<Data> type.
+
+=item B<-data_out>
+
+B<Data> type and output the content.
+
+=item B<-cmsout>
+
+Takes an input message and writes out a PEM encoded CMS structure.
+
+=back
+
+=head2 File format options
+
+=over 4
+
+=item B<-inform> B<DER>|B<PEM>|B<SMIME>
+
+The input format of the CMS structure (if one is being read);
+the default is B<SMIME>.
+See L<openssl-format-options(1)> for details.
+
+=item B<-outform> B<DER>|B<PEM>|B<SMIME>
+
+The output format of the CMS structure (if one is being written);
+the default is B<SMIME>.
+See L<openssl-format-options(1)> for details.
+
+=item B<-rctform> B<DER>|B<PEM>|B<SMIME>
+
+The signed receipt format for use with the B<-receipt_verify>; the default
+is B<SMIME>.
+See L<openssl-format-options(1)> for details.
+
+=item B<-stream>, B<-indef>
+
+The B<-stream> and B<-indef> options are equivalent and enable streaming I/O
+for encoding operations. This permits single pass processing of data without
+the need to hold the entire contents in memory, potentially supporting very
+large files. Streaming is automatically set for S/MIME signing with detached
+data if the output format is B<SMIME> it is currently off by default for all
+other operations.
+
+=item B<-noindef>
+
+Disable streaming I/O where it would produce and indefinite length constructed
+encoding. This option currently has no effect. In future streaming will be
+enabled by default on all relevant operations and this option will disable it.
+
+=item B<-binary>
+
+Normally the input message is converted to "canonical" format which is
+effectively using CR and LF as end of line: as required by the S/MIME
+specification. When this option is present no translation occurs. This
+is useful when handling binary data which may not be in MIME format.
+
+=item B<-crlfeol>
+
+Normally the output file uses a single B<LF> as end of line. When this
+option is present B<CRLF> is used instead.
+
+=item B<-asciicrlf>
+
+When signing use ASCII CRLF format canonicalisation. This strips trailing
+whitespace from all lines, deletes trailing blank lines at EOF and sets
+the encapsulated content type. This option is normally used with detached
+content and an output signature format of DER. This option is not normally
+needed when verifying as it is enabled automatically if the encapsulated
+content format is detected.
+
+=back
+
+=head2 Keys and password options
+
+=over 4
+
+=item B<-pwri_password> I<password>
+
+Specify password for recipient.
+
+=item B<-secretkey> I<key>
+
+Specify symmetric key to use. The key must be supplied in hex format and be
+consistent with the algorithm used. Supported by the B<-EncryptedData_encrypt>
+B<-EncryptedData_decrypt>, B<-encrypt> and B<-decrypt> options. When used
+with B<-encrypt> or B<-decrypt> the supplied key is used to wrap or unwrap the
+content encryption key using an AES key in the B<KEKRecipientInfo> type.
+
+=item B<-secretkeyid> I<id>
+
+The key identifier for the supplied symmetric key for B<KEKRecipientInfo> type.
+This option B<must> be present if the B<-secretkey> option is used with
+B<-encrypt>. With B<-decrypt> operations the I<id> is used to locate the
+relevant key if it is not supplied then an attempt is used to decrypt any
+B<KEKRecipientInfo> structures.
+
+=item B<-inkey> I<filename>|I<uri>
+
+The private key to use when signing or decrypting. This must match the
+corresponding certificate. If this option is not specified then the
+private key must be included in the certificate file specified with
+the B<-recip> or B<-signer> file. When signing this option can be used
+multiple times to specify successive keys.
+
+=item B<-passin> I<arg>
+
+The private key password source. For more information about the format of B<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-keyopt> I<name>:I<parameter>
+
+For signing and encryption this option can be used multiple times to
+set customised parameters for the preceding key or certificate. It can
+currently be used to set RSA-PSS for signing, RSA-OAEP for encryption
+or to modify default parameters for ECDH.
+
+=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The format of the private key file; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+{- $OpenSSL::safe::opt_r_item -}
+
+=back
+
+=head2 Encryption and decryption options
+
+=over 4
+
+=item B<-originator> I<file>
+
+A certificate of the originator of the encrypted message. Necessary for
+decryption when Key Agreement is in use for a shared key.
+
+=item B<-recip> I<file>
+
+When decrypting a message this specifies the certificate of the recipient.
+The certificate must match one of the recipients of the message.
+
+When encrypting a message this option may be used multiple times to specify
+each recipient. This form B<must> be used if customised parameters are
+required (for example to specify RSA-OAEP).
+
+Only certificates carrying RSA, Diffie-Hellman or EC keys are supported by this
+option.
+
+=item I<recipient-cert> ...
+
+This is an alternative to using the B<-recip> option when encrypting a message.
+One or more certificate filennames may be given.
+
+=item B<-I<cipher>>
+
+The encryption algorithm to use. For example triple DES (168 bits) - B<-des3>
+or 256 bit AES - B<-aes256>. Any standard algorithm name (as used by the
+EVP_get_cipherbyname() function) can also be used preceded by a dash, for
+example B<-aes-128-cbc>. See L<openssl-enc(1)> for a list of ciphers
+supported by your version of OpenSSL.
+
+Currently the AES variants with GCM mode are the only supported AEAD
+algorithms.
+
+If not specified triple DES is used. Only used with B<-encrypt> and
+B<-EncryptedData_create> commands.
+
+=item B<-wrap> I<cipher>
+
+Cipher algorithm to use for key wrap when encrypting the message using Key
+Agreement for key transport. The algorithm specified should be suitable for key
+wrap.
+
+=item B<-aes128-wrap>, B<-aes192-wrap>, B<-aes256-wrap>, B<-des3-wrap>
+
+Use AES128, AES192, AES256, or 3DES-EDE, respectively, to wrap key.
+Depending on the OpenSSL build options used, B<-des3-wrap> may not be supported.
+
+=item B<-debug_decrypt>
+
+This option sets the B<CMS_DEBUG_DECRYPT> flag. This option should be used
+with caution: see the notes section below.
+
+=back
+
+=head2 Signing options
+
+=over 4
+
+=item B<-md> I<digest>
+
+Digest algorithm to use when signing or resigning. If not present then the
+default digest algorithm for the signing key will be used (usually SHA1).
+
+=item B<-signer> I<file>
+
+A signing certificate. When signing or resigning a message, this option can be
+used multiple times if more than one signer is required.
+
+=item B<-certfile> I<file>
+
+Allows additional certificates to be specified. When signing these will
+be included with the message. When verifying these will be searched for
+the signers certificates.
+The input can be in PEM, DER, or PKCS#12 format.
+
+=item B<-cades>
+
+When used with B<-sign>,
+add an ESS signingCertificate or ESS signingCertificateV2 signed-attribute
+to the SignerInfo, in order to make the signature comply with the requirements
+for a CAdES Basic Electronic Signature (CAdES-BES).
+
+=item B<-nodetach>
+
+When signing a message use opaque signing: this form is more resistant
+to translation by mail relays but it cannot be read by mail agents that
+do not support S/MIME. Without this option cleartext signing with
+the MIME type multipart/signed is used.
+
+=item B<-nocerts>
+
+When signing a message the signer's certificate is normally included
+with this option it is excluded. This will reduce the size of the
+signed message but the verifier must have a copy of the signers certificate
+available locally (passed using the B<-certfile> option for example).
+
+=item B<-noattr>
+
+Normally when a message is signed a set of attributes are included which
+include the signing time and supported symmetric algorithms. With this
+option they are not included.
+
+=item B<-nosmimecap>
+
+Exclude the list of supported algorithms from signed attributes, other options
+such as signing time and content type are still included.
+
+=item B<-receipt_request_all>, B<-receipt_request_first>
+
+For B<-sign> option include a signed receipt request. Indicate requests should
+be provided by all recipient or first tier recipients (those mailed directly
+and not from a mailing list). Ignored it B<-receipt_request_from> is included.
+
+=item B<-receipt_request_from> I<emailaddress>
+
+For B<-sign> option include a signed receipt request. Add an explicit email
+address where receipts should be supplied.
+
+=item B<-receipt_request_to> I<emailaddress>
+
+Add an explicit email address where signed receipts should be sent to. This
+option B<must> but supplied if a signed receipt is requested.
+
+=back
+
+=head2 Verification options
+
+=over 4
+
+=item B<-signer> I<file>
+
+If a message has been verified successfully then the signers certificate(s)
+will be written to this file if the verification was successful.
+
+=item B<-content> I<filename>
+
+This specifies a file containing the detached content for operations taking
+S/MIME input, such as the B<-verify> command. This is only usable if the CMS
+structure is using the detached signature form where the content is
+not included. This option will override any content if the input format
+is S/MIME and it uses the multipart/signed MIME content type.
+
+=item B<-no_content_verify>
+
+Do not verify signed content signatures.
+
+=item B<-no_attr_verify>
+
+Do not verify signed attribute signatures.
+
+=item B<-nosigs>
+
+Don't verify message signature.
+
+=item B<-noverify>
+
+Do not verify the signers certificate of a signed message.
+
+=item B<-nointern>
+
+When verifying a message normally certificates (if any) included in
+the message are searched for the signing certificate. With this option
+only the certificates specified in the B<-certfile> option are used.
+The supplied certificates can still be used as untrusted CAs however.
+
+=item B<-cades>
+
+When used with B<-verify>, require and check signer certificate digest.
+See the NOTES section for more details.
+
+=item B<-verify_retcode>
+
+Exit nonzero on verification failure.
+
+{- $OpenSSL::safe::opt_trust_item -}
+
+=back
+
+=head2 Output options
+
+=over 4
+
+=item B<-keyid>
+
+Use subject key identifier to identify certificates instead of issuer name and
+serial number. The supplied certificate B<must> include a subject key
+identifier extension. Supported by B<-sign> and B<-encrypt> options.
+
+=item B<-econtent_type> I<type>
+
+Set the encapsulated content type to I<type> if not supplied the B<Data> type
+is used. The I<type> argument can be any valid OID name in either text or
+numerical format.
+
+=item B<-text>
+
+This option adds plain text (text/plain) MIME headers to the supplied
+message if encrypting or signing. If decrypting or verifying it strips
+off text headers: if the decrypted or verified message is not of MIME
+type text/plain then an error occurs.
+
+=item B<-certsout> I<file>
+
+Any certificates contained in the input message are written to I<file>.
+
+=item B<-to>, B<-from>, B<-subject>
+
+The relevant email headers. These are included outside the signed
+portion of a message so they may be included manually. If signing
+then many S/MIME mail clients check the signers certificate's email
+address matches that specified in the From: address.
+
+=back
+
+=head2 Printing options
+
+=over 4
+
+=item B<-noout>
+
+For the B<-cmsout> operation do not output the parsed CMS structure.
+This is useful if the syntax of the CMS structure is being checked.
+
+=item B<-print>
+
+For the B<-cmsout> operation print out all fields of the CMS structure.
+This implies B<-noout>.
+This is mainly useful for testing purposes.
+
+=item B<-nameopt> I<option>
+
+For the B<-cmsout> operation when B<-print> option is in use, specifies
+printing options for string fields. For most cases B<utf8> is reasonable value.
+See L<openssl-namedisplay-options(1)> for details.
+
+=item B<-receipt_request_print>
+
+For the B<-verify> operation print out the contents of any signed receipt
+requests.
+
+=back
+
+=head2 Validation options
+
+=over 4
+
+{- $OpenSSL::safe::opt_v_item -}
+
+Any validation errors cause the command to exit.
+
+=back
+
+=head1 NOTES
+
+The MIME message must be sent without any blank lines between the
+headers and the output. Some mail programs will automatically add
+a blank line. Piping the mail directly to sendmail is one way to
+achieve the correct format.
+
+The supplied message to be signed or encrypted must include the
+necessary MIME headers or many S/MIME clients won't display it
+properly (if at all). You can use the B<-text> option to automatically
+add plain text headers.
+
+A "signed and encrypted" message is one where a signed message is
+then encrypted. This can be produced by encrypting an already signed
+message: see the examples section.
+
+This version of the program only allows one signer per message but it
+will verify multiple signers on received messages. Some S/MIME clients
+choke if a message contains multiple signers. It is possible to sign
+messages "in parallel" by signing an already signed message.
+
+The options B<-encrypt> and B<-decrypt> reflect common usage in S/MIME
+clients. Strictly speaking these process CMS enveloped data: CMS
+encrypted data is used for other purposes.
+
+The B<-resign> option uses an existing message digest when adding a new
+signer. This means that attributes must be present in at least one existing
+signer using the same message digest or this operation will fail.
+
+The B<-stream> and B<-indef> options enable streaming I/O support.
+As a result the encoding is BER using indefinite length constructed encoding
+and no longer DER. Streaming is supported for the B<-encrypt> operation and the
+B<-sign> operation if the content is not detached.
+
+Streaming is always used for the B<-sign> operation with detached data but
+since the content is no longer part of the CMS structure the encoding
+remains DER.
+
+If the B<-decrypt> option is used without a recipient certificate then an
+attempt is made to locate the recipient by trying each potential recipient
+in turn using the supplied private key. To thwart the MMA attack
+(Bleichenbacher's attack on PKCS #1 v1.5 RSA padding) all recipients are
+tried whether they succeed or not and if no recipients match the message
+is "decrypted" using a random key which will typically output garbage.
+The B<-debug_decrypt> option can be used to disable the MMA attack protection
+and return an error if no recipient can be found: this option should be used
+with caution. For a fuller description see L<CMS_decrypt(3)>).
+
+=head1 CADES BASIC ELECTRONIC SIGNATURE (CADES-BES)
+
+A CAdES Basic Electronic Signature (CAdES-BES),
+as defined in the European Standard ETSI EN 319 122-1 V1.1.1, contains:
+
+=over 4
+
+=item *
+
+The signed user data as defined in CMS (RFC 3852);
+
+=item *
+
+Content-type of the EncapsulatedContentInfo value being signed;
+
+=item *
+
+Message-digest of the eContent OCTET STRING within encapContentInfo being signed;
+
+=item *
+
+An ESS signingCertificate or ESS signingCertificateV2 attribute,
+as defined in Enhanced Security Services (ESS), RFC 2634 and RFC 5035.
+An ESS signingCertificate attribute only allows for SHA-1 as digest algorithm.
+An ESS signingCertificateV2 attribute allows for any digest algorithm.
+
+=item *
+
+The digital signature value computed on the user data and, when present, on the signed attributes.
+
+NOTE that the B<-cades> option applies to the B<-sign> or B<-verify> operations.
+With this option, the B<-verify> operation also requires that the
+signingCertificate attribute is present and checks that the given identifiers
+match the verification trust chain built during the verification process.
+
+=back
+
+=head1 EXIT CODES
+
+=over 4
+
+=item Z<>0
+
+The operation was completely successfully.
+
+=item Z<>1
+
+An error occurred parsing the command options.
+
+=item Z<>2
+
+One of the input files could not be read.
+
+=item Z<>3
+
+An error occurred creating the CMS file or when reading the MIME
+message.
+
+=item Z<>4
+
+An error occurred decrypting or verifying the message.
+
+=item Z<>5
+
+The message was verified correctly but an error occurred writing out
+the signers certificates.
+
+=back
+
+=head1 COMPATIBILITY WITH PKCS#7 FORMAT
+
+L<openssl-smime(1)> can only process the older B<PKCS#7> format.
+B<openssl cms> supports Cryptographic Message Syntax format.
+Use of some features will result in messages which cannot be processed by
+applications which only support the older format. These are detailed below.
+
+The use of the B<-keyid> option with B<-sign> or B<-encrypt>.
+
+The B<-outform> I<PEM> option uses different headers.
+
+The B<-compress> option.
+
+The B<-secretkey> option when used with B<-encrypt>.
+
+The use of PSS with B<-sign>.
+
+The use of OAEP or non-RSA keys with B<-encrypt>.
+
+Additionally the B<-EncryptedData_create> and B<-data_create> type cannot
+be processed by the older L<openssl-smime(1)> command.
+
+=head1 EXAMPLES
+
+Create a cleartext signed message:
+
+ openssl cms -sign -in message.txt -text -out mail.msg \
+ -signer mycert.pem
+
+Create an opaque signed message
+
+ openssl cms -sign -in message.txt -text -out mail.msg -nodetach \
+ -signer mycert.pem
+
+Create a signed message, include some additional certificates and
+read the private key from another file:
+
+ openssl cms -sign -in in.txt -text -out mail.msg \
+ -signer mycert.pem -inkey mykey.pem -certfile mycerts.pem
+
+Create a signed message with two signers, use key identifier:
+
+ openssl cms -sign -in message.txt -text -out mail.msg \
+ -signer mycert.pem -signer othercert.pem -keyid
+
+Send a signed message under Unix directly to sendmail, including headers:
+
+ openssl cms -sign -in in.txt -text -signer mycert.pem \
+ -from steve@openssl.org -to someone@somewhere \
+ -subject "Signed message" | sendmail someone@somewhere
+
+Verify a message and extract the signer's certificate if successful:
+
+ openssl cms -verify -in mail.msg -signer user.pem -out signedtext.txt
+
+Send encrypted mail using triple DES:
+
+ openssl cms -encrypt -in in.txt -from steve@openssl.org \
+ -to someone@somewhere -subject "Encrypted message" \
+ -des3 user.pem -out mail.msg
+
+Sign and encrypt mail:
+
+ openssl cms -sign -in ml.txt -signer my.pem -text \
+ | openssl cms -encrypt -out mail.msg \
+ -from steve@openssl.org -to someone@somewhere \
+ -subject "Signed and Encrypted message" -des3 user.pem
+
+Note: the encryption command does not include the B<-text> option because the
+message being encrypted already has MIME headers.
+
+Decrypt a message:
+
+ openssl cms -decrypt -in mail.msg -recip mycert.pem -inkey key.pem
+
+The output from Netscape form signing is a PKCS#7 structure with the
+detached signature format. You can use this program to verify the
+signature by line wrapping the base64 encoded structure and surrounding
+it with:
+
+ -----BEGIN PKCS7-----
+ -----END PKCS7-----
+
+and using the command,
+
+ openssl cms -verify -inform PEM -in signature.pem -content content.txt
+
+alternatively you can base64 decode the signature and use
+
+ openssl cms -verify -inform DER -in signature.der -content content.txt
+
+Create an encrypted message using 128 bit Camellia:
+
+ openssl cms -encrypt -in plain.txt -camellia128 -out mail.msg cert.pem
+
+Add a signer to an existing message:
+
+ openssl cms -resign -in mail.msg -signer newsign.pem -out mail2.msg
+
+Sign a message using RSA-PSS:
+
+ openssl cms -sign -in message.txt -text -out mail.msg \
+ -signer mycert.pem -keyopt rsa_padding_mode:pss
+
+Create an encrypted message using RSA-OAEP:
+
+ openssl cms -encrypt -in plain.txt -out mail.msg \
+ -recip cert.pem -keyopt rsa_padding_mode:oaep
+
+Use SHA256 KDF with an ECDH certificate:
+
+ openssl cms -encrypt -in plain.txt -out mail.msg \
+ -recip ecdhcert.pem -keyopt ecdh_kdf_md:sha256
+
+Print CMS signed binary data in human-readable form:
+
+openssl cms -in signed.cms -binary -inform DER -cmsout -print
+
+=head1 BUGS
+
+The MIME parser isn't very clever: it seems to handle most messages that I've
+thrown at it but it may choke on others.
+
+The code currently will only write out the signer's certificate to a file: if
+the signer has a separate encryption certificate this must be manually
+extracted. There should be some heuristic that determines the correct
+encryption certificate.
+
+Ideally a database should be maintained of a certificates for each email
+address.
+
+The code doesn't currently take note of the permitted symmetric encryption
+algorithms as supplied in the SMIMECapabilities signed attribute. this means the
+user has to manually include the correct encryption algorithm. It should store
+the list of permitted ciphers in a database and only use those.
+
+No revocation checking is done on the signer's certificate.
+
+=head1 SEE ALSO
+
+L<ossl_store-file(7)>
+
+=head1 HISTORY
+
+The use of multiple B<-signer> options and the B<-resign> command were first
+added in OpenSSL 1.0.0.
+
+The B<-keyopt> option was added in OpenSSL 1.0.2.
+
+Support for RSA-OAEP and RSA-PSS was added in OpenSSL 1.0.2.
+
+The use of non-RSA keys with B<-encrypt> and B<-decrypt>
+was added in OpenSSL 1.0.2.
+
+The -no_alt_chains option was added in OpenSSL 1.0.2b.
+
+The B<-nameopt> option was added in OpenSSL 3.0.0.
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-crl.pod.in b/doc/man1/openssl-crl.pod.in
new file mode 100644
index 000000000000..7e15f6445a6f
--- /dev/null
+++ b/doc/man1/openssl-crl.pod.in
@@ -0,0 +1,172 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-crl - CRL command
+
+=head1 SYNOPSIS
+
+B<openssl> B<crl>
+[B<-help>]
+[B<-inform> B<DER>|B<PEM>]
+[B<-outform> B<DER>|B<PEM>]
+[B<-key> I<filename>]
+[B<-keyform> B<DER>|B<PEM>|B<P12>]
+[B<-dateopt>]
+[B<-text>]
+[B<-in> I<filename>]
+[B<-out> I<filename>]
+[B<-gendelta> I<filename>]
+[B<-badsig>]
+[B<-verify>]
+[B<-noout>]
+[B<-hash>]
+[B<-hash_old>]
+[B<-fingerprint>]
+[B<-crlnumber>]
+[B<-issuer>]
+[B<-lastupdate>]
+[B<-nextupdate>]
+{- $OpenSSL::safe::opt_name_synopsis -}
+{- $OpenSSL::safe::opt_trust_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command processes CRL files in DER or PEM format.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-inform> B<DER>|B<PEM>
+
+The CRL input format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-outform> B<DER>|B<PEM>
+
+The CRL output format; the default is B<PEM>.
+See L<openssl-format-options(1)> for details.
+
+=item B<-key> I<filename>
+
+The private key to be used to sign the CRL.
+
+=item B<-keyform> B<DER>|B<PEM>|B<P12>
+
+The format of the private key file; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-in> I<filename>
+
+This specifies the input filename to read from or standard input if this
+option is not specified.
+
+=item B<-out> I<filename>
+
+Specifies the output filename to write to or standard output by
+default.
+
+=item B<-gendelta> I<filename>
+
+Output a comparison of the main CRL and the one specified here.
+
+=item B<-badsig>
+
+Corrupt the signature before writing it; this can be useful
+for testing.
+
+=item B<-dateopt>
+
+Specify the date output format. Values are: rfc_822 and iso_8601.
+Defaults to rfc_822.
+
+=item B<-text>
+
+Print out the CRL in text form.
+
+=item B<-verify>
+
+Verify the signature in the CRL.
+
+=item B<-noout>
+
+Don't output the encoded version of the CRL.
+
+=item B<-fingerprint>
+
+Output the fingerprint of the CRL.
+
+=item B<-crlnumber>
+
+Output the number of the CRL.
+
+=item B<-hash>
+
+Output a hash of the issuer name. This can be use to lookup CRLs in
+a directory by issuer name.
+
+=item B<-hash_old>
+
+Outputs the "hash" of the CRL issuer name using the older algorithm
+as used by OpenSSL before version 1.0.0.
+
+=item B<-issuer>
+
+Output the issuer name.
+
+=item B<-lastupdate>
+
+Output the lastUpdate field.
+
+=item B<-nextupdate>
+
+Output the nextUpdate field.
+
+{- $OpenSSL::safe::opt_name_item -}
+
+{- $OpenSSL::safe::opt_trust_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 EXAMPLES
+
+Convert a CRL file from PEM to DER:
+
+ openssl crl -in crl.pem -outform DER -out crl.der
+
+Output the text form of a DER encoded certificate:
+
+ openssl crl -in crl.der -text -noout
+
+=head1 BUGS
+
+Ideally it should be possible to create a CRL using appropriate options
+and files too.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-crl2pkcs7(1)>,
+L<openssl-ca(1)>,
+L<openssl-x509(1)>,
+L<ossl_store-file(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-crl2pkcs7.pod.in b/doc/man1/openssl-crl2pkcs7.pod.in
new file mode 100644
index 000000000000..684c9b006f17
--- /dev/null
+++ b/doc/man1/openssl-crl2pkcs7.pod.in
@@ -0,0 +1,108 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-crl2pkcs7 - Create a PKCS#7 structure from a CRL and certificates
+
+=head1 SYNOPSIS
+
+B<openssl> B<crl2pkcs7>
+[B<-help>]
+[B<-inform> B<DER>|B<PEM>]
+[B<-outform> B<DER>|B<PEM>]
+[B<-in> I<filename>]
+[B<-out> I<filename>]
+[B<-certfile> I<filename>]
+[B<-nocrl>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command takes an optional CRL and one or more
+certificates and converts them into a PKCS#7 degenerate "certificates
+only" structure.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-inform> B<DER>|B<PEM>
+
+The input format of the CRL; the default is B<PEM>.
+See L<openssl-format-options(1)> for details.
+
+=item B<-outform> B<DER>|B<PEM>
+
+The output format of the PKCS#7 object; the default is B<PEM>.
+See L<openssl-format-options(1)> for details.
+
+=item B<-in> I<filename>
+
+This specifies the input filename to read a CRL from or standard input if this
+option is not specified.
+
+=item B<-out> I<filename>
+
+Specifies the output filename to write the PKCS#7 structure to or standard
+output by default.
+
+=item B<-certfile> I<filename>
+
+Specifies a filename containing one or more certificates in B<PEM> format.
+All certificates in the file will be added to the PKCS#7 structure. This
+option can be used more than once to read certificates from multiple
+files.
+
+=item B<-nocrl>
+
+Normally a CRL is included in the output file. With this option no CRL is
+included in the output file and a CRL is not read from the input file.
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 EXAMPLES
+
+Create a PKCS#7 structure from a certificate and CRL:
+
+ openssl crl2pkcs7 -in crl.pem -certfile cert.pem -out p7.pem
+
+Creates a PKCS#7 structure in DER format with no CRL from several
+different certificates:
+
+ openssl crl2pkcs7 -nocrl -certfile newcert.pem
+ -certfile demoCA/cacert.pem -outform DER -out p7.der
+
+=head1 NOTES
+
+The output file is a PKCS#7 signed data structure containing no signers and
+just certificates and an optional CRL.
+
+This command can be used to send certificates and CAs to Netscape as part of
+the certificate enrollment process. This involves sending the DER encoded output
+as MIME type application/x-x509-user-cert.
+
+The B<PEM> encoded form with the header and footer lines removed can be used to
+install user certificates and CAs in MSIE using the Xenroll control.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-pkcs7(1)>
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-dgst.pod.in b/doc/man1/openssl-dgst.pod.in
new file mode 100644
index 000000000000..5dcdbe548e69
--- /dev/null
+++ b/doc/man1/openssl-dgst.pod.in
@@ -0,0 +1,288 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-dgst - perform digest operations
+
+=head1 SYNOPSIS
+
+B<openssl> B<dgst>|I<digest>
+[B<-I<digest>>]
+[B<-list>]
+[B<-help>]
+[B<-c>]
+[B<-d>]
+[B<-debug>]
+[B<-hex>]
+[B<-binary>]
+[B<-xoflen> I<length>]
+[B<-r>]
+[B<-out> I<filename>]
+[B<-sign> I<filename>|I<uri>]
+[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-passin> I<arg>]
+[B<-verify> I<filename>]
+[B<-prverify> I<filename>]
+[B<-signature> I<filename>]
+[B<-sigopt> I<nm>:I<v>]
+[B<-hmac> I<key>]
+[B<-mac> I<alg>]
+[B<-macopt> I<nm>:I<v>]
+[B<-fips-fingerprint>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- output_off() if $disabled{"deprecated-3.0"}; ""
+-}[B<-engine_impl> I<id>]{-
+ output_on() if $disabled{"deprecated-3.0"}; "" -}
+{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+[I<file> ...]
+
+=head1 DESCRIPTION
+
+This command output the message digest of a supplied file or files
+in hexadecimal, and also generates and verifies digital
+signatures using message digests.
+
+The generic name, B<openssl dgst>, may be used with an option specifying the
+algorithm to be used.
+The default digest is B<sha256>.
+A supported I<digest> name may also be used as the sub-command name.
+To see the list of supported algorithms, use C<openssl list -digest-algorithms>
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-I<digest>>
+
+Specifies name of a supported digest to be used. See option B<-list> below :
+
+=item B<-list>
+
+Prints out a list of supported message digests.
+
+=item B<-c>
+
+Print out the digest in two digit groups separated by colons, only relevant if
+the B<-hex> option is given as well.
+
+=item B<-d>, B<-debug>
+
+Print out BIO debugging information.
+
+=item B<-hex>
+
+Digest is to be output as a hex dump. This is the default case for a "normal"
+digest as opposed to a digital signature. See NOTES below for digital
+signatures using B<-hex>.
+
+=item B<-binary>
+
+Output the digest or signature in binary form.
+
+=item B<-xoflen> I<length>
+
+Set the output length for XOF algorithms, such as B<shake128> and B<shake256>.
+This option is not supported for signing operations.
+
+For OpenSSL providers it is recommended to set this value for shake algorithms,
+since the default values are set to only supply half of the maximum security
+strength.
+
+For backwards compatibility reasons the default xoflen length for B<shake128> is
+16 (bytes) which results in a security strength of only 64 bits. To ensure the
+maximum security strength of 128 bits, the xoflen should be set to at least 32.
+
+For backwards compatibility reasons the default xoflen length for B<shake256> is
+32 (bytes) which results in a security strength of only 128 bits. To ensure the
+maximum security strength of 256 bits, the xoflen should be set to at least 64.
+
+=item B<-r>
+
+=for openssl foreign manual sha1sum(1)
+
+Output the digest in the "coreutils" format, including newlines.
+Used by programs like L<sha1sum(1)>.
+
+=item B<-out> I<filename>
+
+Filename to output to, or standard output by default.
+
+=item B<-sign> I<filename>|I<uri>
+
+Digitally sign the digest using the given private key. Note this option
+does not support Ed25519 or Ed448 private keys. Use the L<openssl-pkeyutl(1)>
+command instead for this.
+
+=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The format of the key to sign with; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-sigopt> I<nm>:I<v>
+
+Pass options to the signature algorithm during sign or verify operations.
+Names and values of these options are algorithm-specific.
+
+=item B<-passin> I<arg>
+
+The private key password source. For more information about the format of I<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-verify> I<filename>
+
+Verify the signature using the public key in "filename".
+The output is either "Verified OK" or "Verification Failure".
+
+=item B<-prverify> I<filename>
+
+Verify the signature using the private key in "filename".
+
+=item B<-signature> I<filename>
+
+The actual signature to verify.
+
+=item B<-hmac> I<key>
+
+Create a hashed MAC using "key".
+
+The L<openssl-mac(1)> command should be preferred to using this command line
+option.
+
+=item B<-mac> I<alg>
+
+Create MAC (keyed Message Authentication Code). The most popular MAC
+algorithm is HMAC (hash-based MAC), but there are other MAC algorithms
+which are not based on hash, for instance B<gost-mac> algorithm,
+supported by the B<gost> engine. MAC keys and other options should be set
+via B<-macopt> parameter.
+
+The L<openssl-mac(1)> command should be preferred to using this command line
+option.
+
+=item B<-macopt> I<nm>:I<v>
+
+Passes options to MAC algorithm, specified by B<-mac> key.
+Following options are supported by both by B<HMAC> and B<gost-mac>:
+
+=over 4
+
+=item B<key>:I<string>
+
+Specifies MAC key as alphanumeric string (use if key contain printable
+characters only). String length must conform to any restrictions of
+the MAC algorithm for example exactly 32 chars for gost-mac.
+
+=item B<hexkey>:I<string>
+
+Specifies MAC key in hexadecimal form (two hex digits per byte).
+Key length must conform to any restrictions of the MAC algorithm
+for example exactly 32 chars for gost-mac.
+
+=back
+
+The L<openssl-mac(1)> command should be preferred to using this command line
+option.
+
+=item B<-fips-fingerprint>
+
+Compute HMAC using a specific key for certain OpenSSL-FIPS operations.
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_engine_item -}
+{- output_off() if $disabled{"deprecated-3.0"}; "" -}
+The engine is not used for digests unless the B<-engine_impl> option is
+used or it is configured to do so, see L<config(5)/Engine Configuration Module>.
+
+=item B<-engine_impl> I<id>
+
+When used with the B<-engine> option, it specifies to also use
+engine I<id> for digest operations.
+
+{- output_on() if $disabled{"deprecated-3.0"}; "" -}
+{- $OpenSSL::safe::opt_provider_item -}
+
+=item I<file> ...
+
+File or files to digest. If no files are specified then standard input is
+used.
+
+=back
+
+
+=head1 EXAMPLES
+
+To create a hex-encoded message digest of a file:
+
+ openssl dgst -md5 -hex file.txt
+ or
+ openssl md5 file.txt
+
+To sign a file using SHA-256 with binary file output:
+
+ openssl dgst -sha256 -sign privatekey.pem -out signature.sign file.txt
+ or
+ openssl sha256 -sign privatekey.pem -out signature.sign file.txt
+
+To verify a signature:
+
+ openssl dgst -sha256 -verify publickey.pem \
+ -signature signature.sign \
+ file.txt
+
+
+=head1 NOTES
+
+The digest mechanisms that are available will depend on the options
+used when building OpenSSL.
+The C<openssl list -digest-algorithms> command can be used to list them.
+
+New or agile applications should use probably use SHA-256. Other digests,
+particularly SHA-1 and MD5, are still widely used for interoperating
+with existing formats and protocols.
+
+When signing a file, this command will automatically determine the algorithm
+(RSA, ECC, etc) to use for signing based on the private key's ASN.1 info.
+When verifying signatures, it only handles the RSA, DSA, or ECDSA signature
+itself, not the related data to identify the signer and algorithm used in
+formats such as x.509, CMS, and S/MIME.
+
+A source of random numbers is required for certain signing algorithms, in
+particular ECDSA and DSA.
+
+The signing and verify options should only be used if a single file is
+being signed or verified.
+
+Hex signatures cannot be verified using B<openssl>. Instead, use "xxd -r"
+or similar program to transform the hex signature into a binary signature
+prior to verification.
+
+The L<openssl-mac(1)> command is preferred over the B<-hmac>, B<-mac> and
+B<-macopt> command line options.
+
+=head1 SEE ALSO
+
+L<openssl-mac(1)>
+
+=head1 HISTORY
+
+The default digest was changed from MD5 to SHA256 in OpenSSL 1.1.0.
+The FIPS-related options were removed in OpenSSL 1.1.0.
+
+The B<-engine> and B<-engine_impl> options were deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-dhparam.pod.in b/doc/man1/openssl-dhparam.pod.in
new file mode 100644
index 000000000000..d358ba95dcf3
--- /dev/null
+++ b/doc/man1/openssl-dhparam.pod.in
@@ -0,0 +1,136 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-dhparam - DH parameter manipulation and generation
+
+=head1 SYNOPSIS
+
+B<openssl dhparam>
+[B<-help>]
+[B<-inform> B<DER>|B<PEM>]
+[B<-outform> B<DER>|B<PEM>]
+[B<-in> I<filename>]
+[B<-out> I<filename>]
+[B<-dsaparam>]
+[B<-check>]
+[B<-noout>]
+[B<-text>]
+[B<-2>]
+[B<-3>]
+[B<-5>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+[I<numbits>]
+
+=head1 DESCRIPTION
+
+This command is used to manipulate DH parameter files.
+
+See L<openssl-genpkey(1)/EXAMPLES> for examples on how to generate
+a key using a named safe prime group without generating intermediate
+parameters.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-inform> B<DER>|B<PEM>, B<-outform> B<DER>|B<PEM>
+
+The input format and output format; the default is B<PEM>.
+The object is compatible with the PKCS#3 B<DHparameter> structure.
+See L<openssl-format-options(1)> for details.
+
+=item B<-in> I<filename>
+
+This specifies the input filename to read parameters from or standard input if
+this option is not specified.
+
+=item B<-out> I<filename>
+
+This specifies the output filename parameters to. Standard output is used
+if this option is not present. The output filename should B<not> be the same
+as the input filename.
+
+=item B<-dsaparam>
+
+If this option is used, DSA rather than DH parameters are read or created;
+they are converted to DH format. Otherwise, "strong" primes (such
+that (p-1)/2 is also prime) will be used for DH parameter generation.
+
+DH parameter generation with the B<-dsaparam> option is much faster,
+and the recommended exponent length is shorter, which makes DH key
+exchange more efficient. Beware that with such DSA-style DH
+parameters, a fresh DH key should be created for each use to
+avoid small-subgroup attacks that may be possible otherwise.
+
+=item B<-check>
+
+Performs numerous checks to see if the supplied parameters are valid and
+displays a warning if not.
+
+=item B<-2>, B<-3>, B<-5>
+
+The generator to use, either 2, 3 or 5. If present then the
+input file is ignored and parameters are generated instead. If not
+present but I<numbits> is present, parameters are generated with the
+default generator 2.
+
+=item I<numbits>
+
+This option specifies that a parameter set should be generated of size
+I<numbits>. It must be the last option. If this option is present then
+the input file is ignored and parameters are generated instead. If
+this option is not present but a generator (B<-2>, B<-3> or B<-5>) is
+present, parameters are generated with a default length of 2048 bits.
+The minimim length is 512 bits. The maximum length is 10000 bits.
+
+=item B<-noout>
+
+This option inhibits the output of the encoded version of the parameters.
+
+=item B<-text>
+
+This option prints out the DH parameters in human readable form.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 NOTES
+
+This command replaces the B<dh> and B<gendh> commands of previous
+releases.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-pkeyparam(1)>,
+L<openssl-dsaparam(1)>,
+L<openssl-genpkey(1)>.
+
+=head1 HISTORY
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+The B<-C> option was removed in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-dsa.pod.in b/doc/man1/openssl-dsa.pod.in
new file mode 100644
index 000000000000..6d15e950b935
--- /dev/null
+++ b/doc/man1/openssl-dsa.pod.in
@@ -0,0 +1,195 @@
+=pod
+
+=begin comment
+{- join("\n", @autowarntext) -}
+
+=end comment
+
+=head1 NAME
+
+openssl-dsa - DSA key processing
+
+=head1 SYNOPSIS
+
+B<openssl> B<dsa>
+[B<-help>]
+[B<-inform> B<DER>|B<PEM>]
+[B<-outform> B<DER>|B<PEM>]
+[B<-in> I<filename>]
+[B<-passin> I<arg>]
+[B<-out> I<filename>]
+[B<-passout> I<arg>]
+[B<-aes128>]
+[B<-aes192>]
+[B<-aes256>]
+[B<-aria128>]
+[B<-aria192>]
+[B<-aria256>]
+[B<-camellia128>]
+[B<-camellia192>]
+[B<-camellia256>]
+[B<-des>]
+[B<-des3>]
+[B<-idea>]
+[B<-text>]
+[B<-noout>]
+[B<-modulus>]
+[B<-pubin>]
+[B<-pubout>]
+[B<-pvk-strong>]
+[B<-pvk-weak>]
+[B<-pvk-none>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command processes DSA keys. They can be converted between various
+forms and their components printed out. B<Note> This command uses the
+traditional SSLeay compatible format for private key encryption: newer
+applications should use the more secure PKCS#8 format using the B<pkcs8>
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-inform> B<DER>|B<PEM>
+
+The key input format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-outform> B<DER>|B<PEM>
+
+The key output format; the default is B<PEM>.
+See L<openssl-format-options(1)> for details.
+
+Private keys are a sequence of B<ASN.1 INTEGERS>: the version (zero), B<p>,
+B<q>, B<g>, and the public and private key components. Public keys
+are a B<SubjectPublicKeyInfo> structure with the B<DSA> type.
+
+The B<PEM> format also accepts PKCS#8 data.
+
+=item B<-in> I<filename>
+
+This specifies the input filename to read a key from or standard input if this
+option is not specified. If the key is encrypted a pass phrase will be
+prompted for.
+
+=item B<-out> I<filename>
+
+This specifies the output filename to write a key to or standard output by
+is not specified. If any encryption options are set then a pass phrase will be
+prompted for. The output filename should B<not> be the same as the input
+filename.
+
+=item B<-passin> I<arg>, B<-passout> I<arg>
+
+The password source for the input and output file.
+For more information about the format of B<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-aes128>, B<-aes192>, B<-aes256>, B<-aria128>, B<-aria192>, B<-aria256>, B<-camellia128>, B<-camellia192>, B<-camellia256>, B<-des>, B<-des3>, B<-idea>
+
+These options encrypt the private key with the specified
+cipher before outputting it. A pass phrase is prompted for.
+If none of these options is specified the key is written in plain text. This
+means that this command can be used to remove the pass phrase from a key
+by not giving any encryption option is given, or to add or change the pass
+phrase by setting them.
+These options can only be used with PEM format output files.
+
+=item B<-text>
+
+Prints out the public, private key components and parameters.
+
+=item B<-noout>
+
+This option prevents output of the encoded version of the key.
+
+=item B<-modulus>
+
+This option prints out the value of the public key component of the key.
+
+=item B<-pubin>
+
+By default, a private key is read from the input file. With this option a
+public key is read instead.
+
+=item B<-pubout>
+
+By default, a private key is output. With this option a public
+key will be output instead. This option is automatically set if the input is
+a public key.
+
+=item B<-pvk-strong>
+
+Enable 'Strong' PVK encoding level (default).
+
+=item B<-pvk-weak>
+
+Enable 'Weak' PVK encoding level.
+
+=item B<-pvk-none>
+
+Don't enforce PVK encoding.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+The L<openssl-pkey(1)> command is capable of performing all the operations
+this command can, as well as supporting other public key types.
+
+=head1 EXAMPLES
+
+The documentation for the L<openssl-pkey(1)> command contains examples
+equivalent to the ones listed here.
+
+To remove the pass phrase on a DSA private key:
+
+ openssl dsa -in key.pem -out keyout.pem
+
+To encrypt a private key using triple DES:
+
+ openssl dsa -in key.pem -des3 -out keyout.pem
+
+To convert a private key from PEM to DER format:
+
+ openssl dsa -in key.pem -outform DER -out keyout.der
+
+To print out the components of a private key to standard output:
+
+ openssl dsa -in key.pem -text -noout
+
+To just output the public part of a private key:
+
+ openssl dsa -in key.pem -pubout -out pubkey.pem
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-pkey(1)>,
+L<openssl-dsaparam(1)>,
+L<openssl-gendsa(1)>,
+L<openssl-rsa(1)>,
+L<openssl-genrsa(1)>
+
+=head1 HISTORY
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-dsaparam.pod.in b/doc/man1/openssl-dsaparam.pod.in
new file mode 100644
index 000000000000..c88e11f3cf5a
--- /dev/null
+++ b/doc/man1/openssl-dsaparam.pod.in
@@ -0,0 +1,120 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-dsaparam - DSA parameter manipulation and generation
+
+=head1 SYNOPSIS
+
+B<openssl dsaparam>
+[B<-help>]
+[B<-inform> B<DER>|B<PEM>]
+[B<-outform> B<DER>|B<PEM>]
+[B<-in> I<filename>]
+[B<-out> I<filename>]
+[B<-noout>]
+[B<-text>]
+[B<-genkey>]
+[B<-verbose>]
+{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+[I<numbits>]
+
+=head1 DESCRIPTION
+
+This command is used to manipulate or generate DSA parameter files.
+
+DSA parameter generation can be a slow process and as a result the same set of
+DSA parameters is often used to generate several distinct keys.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-inform> B<DER>|B<PEM>
+
+The DSA parameters input format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-outform> B<DER>|B<PEM>
+
+The DSA parameters output format; the default is B<PEM>.
+See L<openssl-format-options(1)> for details.
+
+Parameters are a sequence of B<ASN.1 INTEGER>s: B<p>, B<q>, and B<g>.
+This is compatible with RFC 2459 B<DSS-Parms> structure.
+
+=item B<-in> I<filename>
+
+This specifies the input filename to read parameters from or standard input if
+this option is not specified. If the I<numbits> parameter is included then
+this option will be ignored.
+
+=item B<-out> I<filename>
+
+This specifies the output filename parameters to. Standard output is used
+if this option is not present. The output filename should B<not> be the same
+as the input filename.
+
+=item B<-noout>
+
+This option inhibits the output of the encoded version of the parameters.
+
+=item B<-text>
+
+This option prints out the DSA parameters in human readable form.
+
+=item B<-genkey>
+
+This option will generate a DSA either using the specified or generated
+parameters.
+
+
+=item B<-verbose>
+
+Print extra details about the operations being performed.
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+=item I<numbits>
+
+This option specifies that a parameter set should be generated of size
+I<numbits>. It must be the last option. If this option is included then
+the input file (if any) is ignored.
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-pkeyparam(1)>,
+L<openssl-gendsa(1)>,
+L<openssl-dsa(1)>,
+L<openssl-genrsa(1)>,
+L<openssl-rsa(1)>
+
+=head1 HISTORY
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+The B<-C> option was removed in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-ec.pod.in b/doc/man1/openssl-ec.pod.in
new file mode 100644
index 000000000000..27de8ebaf6de
--- /dev/null
+++ b/doc/man1/openssl-ec.pod.in
@@ -0,0 +1,208 @@
+=pod
+
+=begin comment
+{- join("\n", @autowarntext) -}
+
+=end comment
+
+=head1 NAME
+
+openssl-ec - EC key processing
+
+=head1 SYNOPSIS
+
+B<openssl> B<ec>
+[B<-help>]
+[B<-inform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-outform> B<DER>|B<PEM>]
+[B<-in> I<filename>|I<uri>]
+[B<-passin> I<arg>]
+[B<-out> I<filename>]
+[B<-passout> I<arg>]
+[B<-des>]
+[B<-des3>]
+[B<-idea>]
+[B<-text>]
+[B<-noout>]
+[B<-param_out>]
+[B<-pubin>]
+[B<-pubout>]
+[B<-conv_form> I<arg>]
+[B<-param_enc> I<arg>]
+[B<-no_public>]
+[B<-check>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+The L<openssl-ec(1)> command processes EC keys. They can be converted between
+various forms and their components printed out. B<Note> OpenSSL uses the
+private key format specified in 'SEC 1: Elliptic Curve Cryptography'
+(http://www.secg.org/). To convert an OpenSSL EC private key into the
+PKCS#8 private key format use the L<openssl-pkcs8(1)> command.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-inform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The key input format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-outform> B<DER>|B<PEM>
+
+The key output format; the default is B<PEM>.
+See L<openssl-format-options(1)> for details.
+
+Private keys are an SEC1 private key or PKCS#8 format.
+Public keys are a B<SubjectPublicKeyInfo> as specified in IETF RFC 3280.
+
+=item B<-in> I<filename>|I<uri>
+
+This specifies the input to read a key from or standard input if this
+option is not specified. If the key is encrypted a pass phrase will be
+prompted for.
+
+=item B<-out> I<filename>
+
+This specifies the output filename to write a key to or standard output by
+is not specified. If any encryption options are set then a pass phrase will be
+prompted for. The output filename should B<not> be the same as the input
+filename.
+
+=item B<-passin> I<arg>, B<-passout> I<arg>
+
+The password source for the input and output file.
+For more information about the format of B<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-des>|B<-des3>|B<-idea>
+
+These options encrypt the private key with the DES, triple DES, IDEA or
+any other cipher supported by OpenSSL before outputting it. A pass phrase is
+prompted for.
+If none of these options is specified the key is written in plain text. This
+means that using this command to read in an encrypted key with no
+encryption option can be used to remove the pass phrase from a key, or by
+setting the encryption options it can be use to add or change the pass phrase.
+These options can only be used with PEM format output files.
+
+=item B<-text>
+
+Prints out the public, private key components and parameters.
+
+=item B<-noout>
+
+This option prevents output of the encoded version of the key.
+
+=item B<-param_out>
+
+Print the elliptic curve parameters.
+
+=item B<-pubin>
+
+By default, a private key is read from the input file. With this option a
+public key is read instead.
+
+=item B<-pubout>
+
+By default a private key is output. With this option a public
+key will be output instead. This option is automatically set if the input is
+a public key.
+
+=item B<-conv_form> I<arg>
+
+This specifies how the points on the elliptic curve are converted
+into octet strings. Possible values are: B<compressed>, B<uncompressed> (the
+default value) and B<hybrid>. For more information regarding
+the point conversion forms please read the X9.62 standard.
+B<Note> Due to patent issues the B<compressed> option is disabled
+by default for binary curves and can be enabled by defining
+the preprocessor macro B<OPENSSL_EC_BIN_PT_COMP> at compile time.
+
+=item B<-param_enc> I<arg>
+
+This specifies how the elliptic curve parameters are encoded.
+Possible value are: B<named_curve>, i.e. the ec parameters are
+specified by an OID, or B<explicit> where the ec parameters are
+explicitly given (see RFC 3279 for the definition of the
+EC parameters structures). The default value is B<named_curve>.
+B<Note> the B<implicitlyCA> alternative, as specified in RFC 3279,
+is currently not implemented in OpenSSL.
+
+=item B<-no_public>
+
+This option omits the public key components from the private key output.
+
+=item B<-check>
+
+This option checks the consistency of an EC private or public key.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+The L<openssl-pkey(1)> command is capable of performing all the operations
+this command can, as well as supporting other public key types.
+
+=head1 EXAMPLES
+
+The documentation for the L<openssl-pkey(1)> command contains examples
+equivalent to the ones listed here.
+
+To encrypt a private key using triple DES:
+
+ openssl ec -in key.pem -des3 -out keyout.pem
+
+To convert a private key from PEM to DER format:
+
+ openssl ec -in key.pem -outform DER -out keyout.der
+
+To print out the components of a private key to standard output:
+
+ openssl ec -in key.pem -text -noout
+
+To just output the public part of a private key:
+
+ openssl ec -in key.pem -pubout -out pubkey.pem
+
+To change the parameters encoding to B<explicit>:
+
+ openssl ec -in key.pem -param_enc explicit -out keyout.pem
+
+To change the point conversion form to B<compressed>:
+
+ openssl ec -in key.pem -conv_form compressed -out keyout.pem
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-pkey(1)>,
+L<openssl-ecparam(1)>,
+L<openssl-dsa(1)>,
+L<openssl-rsa(1)>
+
+=head1 HISTORY
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+The B<-conv_form> and B<-no_public> options are no longer supported
+with keys loaded from an engine in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2003-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-ecparam.pod.in b/doc/man1/openssl-ecparam.pod.in
new file mode 100644
index 000000000000..458505051493
--- /dev/null
+++ b/doc/man1/openssl-ecparam.pod.in
@@ -0,0 +1,186 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-ecparam - EC parameter manipulation and generation
+
+=head1 SYNOPSIS
+
+B<openssl ecparam>
+[B<-help>]
+[B<-inform> B<DER>|B<PEM>]
+[B<-outform> B<DER>|B<PEM>]
+[B<-in> I<filename>]
+[B<-out> I<filename>]
+[B<-noout>]
+[B<-text>]
+[B<-check>]
+[B<-check_named>]
+[B<-name> I<arg>]
+[B<-list_curves>]
+[B<-conv_form> I<arg>]
+[B<-param_enc> I<arg>]
+[B<-no_seed>]
+[B<-genkey>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command is used to manipulate or generate EC parameter files.
+
+OpenSSL is currently not able to generate new groups and therefore
+this command can only create EC parameters from known (named) curves.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-inform> B<DER>|B<PEM>
+
+The EC parameters input format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-outform> B<DER>|B<PEM>
+
+The EC parameters output format; the default is B<PEM>.
+See L<openssl-format-options(1)> for details.
+
+Parameters are encoded as B<EcpkParameters> as specified in IETF RFC 3279.
+
+=item B<-in> I<filename>
+
+This specifies the input filename to read parameters from or standard input if
+this option is not specified.
+
+=item B<-out> I<filename>
+
+This specifies the output filename parameters to. Standard output is used
+if this option is not present. The output filename should B<not> be the same
+as the input filename.
+
+=item B<-noout>
+
+This option inhibits the output of the encoded version of the parameters.
+
+=item B<-text>
+
+This option prints out the EC parameters in human readable form.
+
+=item B<-check>
+
+Validate the elliptic curve parameters.
+
+=item B<-check_named>
+
+Validate the elliptic name curve parameters by checking if the curve parameters
+match any built-in curves.
+
+=item B<-name> I<arg>
+
+Use the EC parameters with the specified 'short' name. Use B<-list_curves>
+to get a list of all currently implemented EC parameters.
+
+=item B<-list_curves>
+
+Print out a list of all currently implemented EC parameters names and exit.
+
+=item B<-conv_form> I<arg>
+
+This specifies how the points on the elliptic curve are converted
+into octet strings. Possible values are: B<compressed>, B<uncompressed> (the
+default value) and B<hybrid>. For more information regarding
+the point conversion forms please read the X9.62 standard.
+B<Note> Due to patent issues the B<compressed> option is disabled
+by default for binary curves and can be enabled by defining
+the preprocessor macro B<OPENSSL_EC_BIN_PT_COMP> at compile time.
+
+=item B<-param_enc> I<arg>
+
+This specifies how the elliptic curve parameters are encoded.
+Possible value are: B<named_curve>, i.e. the ec parameters are
+specified by an OID, or B<explicit> where the ec parameters are
+explicitly given (see RFC 3279 for the definition of the
+EC parameters structures). The default value is B<named_curve>.
+B<Note> the B<implicitlyCA> alternative, as specified in RFC 3279,
+is currently not implemented in OpenSSL.
+
+=item B<-no_seed>
+
+This option inhibits that the 'seed' for the parameter generation
+is included in the ECParameters structure (see RFC 3279).
+
+=item B<-genkey>
+
+This option will generate an EC private key using the specified parameters.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+The L<openssl-genpkey(1)> and L<openssl-pkeyparam(1)> commands are capable
+of performing all the operations this command can, as well as supporting
+other public key types.
+
+=head1 EXAMPLES
+
+The documentation for the L<openssl-genpkey(1)> and L<openssl-pkeyparam(1)>
+commands contains examples equivalent to the ones listed here.
+
+To create EC parameters with the group 'prime192v1':
+
+ openssl ecparam -out ec_param.pem -name prime192v1
+
+To create EC parameters with explicit parameters:
+
+ openssl ecparam -out ec_param.pem -name prime192v1 -param_enc explicit
+
+To validate given EC parameters:
+
+ openssl ecparam -in ec_param.pem -check
+
+To create EC parameters and a private key:
+
+ openssl ecparam -out ec_key.pem -name prime192v1 -genkey
+
+To change the point encoding to 'compressed':
+
+ openssl ecparam -in ec_in.pem -out ec_out.pem -conv_form compressed
+
+To print out the EC parameters to standard output:
+
+ openssl ecparam -in ec_param.pem -noout -text
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-pkeyparam(1)>,
+L<openssl-genpkey(1)>,
+L<openssl-ec(1)>,
+L<openssl-dsaparam(1)>
+
+=head1 HISTORY
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+The B<-C> option was removed in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2003-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-enc.pod.in b/doc/man1/openssl-enc.pod.in
new file mode 100644
index 000000000000..fdfa7f67d3ee
--- /dev/null
+++ b/doc/man1/openssl-enc.pod.in
@@ -0,0 +1,458 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-enc - symmetric cipher routines
+
+=head1 SYNOPSIS
+
+B<openssl> B<enc>|I<cipher>
+[B<-I<cipher>>]
+[B<-help>]
+[B<-list>]
+[B<-ciphers>]
+[B<-in> I<filename>]
+[B<-out> I<filename>]
+[B<-pass> I<arg>]
+[B<-e>]
+[B<-d>]
+[B<-a>]
+[B<-base64>]
+[B<-A>]
+[B<-k> I<password>]
+[B<-kfile> I<filename>]
+[B<-K> I<key>]
+[B<-iv> I<IV>]
+[B<-S> I<salt>]
+[B<-salt>]
+[B<-nosalt>]
+[B<-z>]
+[B<-md> I<digest>]
+[B<-iter> I<count>]
+[B<-pbkdf2>]
+[B<-p>]
+[B<-P>]
+[B<-bufsize> I<number>]
+[B<-nopad>]
+[B<-v>]
+[B<-debug>]
+[B<-none>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+
+B<openssl> I<cipher> [B<...>]
+
+=head1 DESCRIPTION
+
+The symmetric cipher commands allow data to be encrypted or decrypted
+using various block and stream ciphers using keys based on passwords
+or explicitly provided. Base64 encoding or decoding can also be performed
+either by itself or in addition to the encryption or decryption.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-I<cipher>>
+
+The cipher to use.
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-list>
+
+List all supported ciphers.
+
+=item B<-ciphers>
+
+Alias of -list to display all supported ciphers.
+
+=item B<-in> I<filename>
+
+The input filename, standard input by default.
+
+=item B<-out> I<filename>
+
+The output filename, standard output by default.
+
+=item B<-pass> I<arg>
+
+The password source. For more information about the format of I<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-e>
+
+Encrypt the input data: this is the default.
+
+=item B<-d>
+
+Decrypt the input data.
+
+=item B<-a>
+
+Base64 process the data. This means that if encryption is taking place
+the data is base64 encoded after encryption. If decryption is set then
+the input data is base64 decoded before being decrypted.
+
+=item B<-base64>
+
+Same as B<-a>
+
+=item B<-A>
+
+If the B<-a> option is set then base64 process the data on one line.
+
+=item B<-k> I<password>
+
+The password to derive the key from. This is for compatibility with previous
+versions of OpenSSL. Superseded by the B<-pass> argument.
+
+=item B<-kfile> I<filename>
+
+Read the password to derive the key from the first line of I<filename>.
+This is for compatibility with previous versions of OpenSSL. Superseded by
+the B<-pass> argument.
+
+=item B<-md> I<digest>
+
+Use the specified digest to create the key from the passphrase.
+The default algorithm is sha-256.
+
+=item B<-iter> I<count>
+
+Use a given number of iterations on the password in deriving the encryption key.
+High values increase the time required to brute-force the resulting file.
+This option enables the use of PBKDF2 algorithm to derive the key.
+
+=item B<-pbkdf2>
+
+Use PBKDF2 algorithm with default iteration count unless otherwise specified.
+
+=item B<-nosalt>
+
+Don't use a salt in the key derivation routines. This option B<SHOULD NOT> be
+used except for test purposes or compatibility with ancient versions of
+OpenSSL.
+
+=item B<-salt>
+
+Use salt (randomly generated or provide with B<-S> option) when
+encrypting, this is the default.
+
+=item B<-S> I<salt>
+
+The actual salt to use: this must be represented as a string of hex digits.
+If this option is used while encrypting, the same exact value will be needed
+again during decryption.
+
+=item B<-K> I<key>
+
+The actual key to use: this must be represented as a string comprised only
+of hex digits. If only the key is specified, the IV must additionally specified
+using the B<-iv> option. When both a key and a password are specified, the
+key given with the B<-K> option will be used and the IV generated from the
+password will be taken. It does not make much sense to specify both key
+and password.
+
+=item B<-iv> I<IV>
+
+The actual IV to use: this must be represented as a string comprised only
+of hex digits. When only the key is specified using the B<-K> option, the
+IV must explicitly be defined. When a password is being specified using
+one of the other options, the IV is generated from this password.
+
+=item B<-p>
+
+Print out the key and IV used.
+
+=item B<-P>
+
+Print out the key and IV used then immediately exit: don't do any encryption
+or decryption.
+
+=item B<-bufsize> I<number>
+
+Set the buffer size for I/O.
+
+=item B<-nopad>
+
+Disable standard block padding.
+
+=item B<-v>
+
+Verbose print; display some statistics about I/O and buffer sizes.
+
+=item B<-debug>
+
+Debug the BIOs used for I/O.
+
+=item B<-z>
+
+Compress or decompress encrypted data using zlib after encryption or before
+decryption. This option exists only if OpenSSL was compiled with the zlib
+or zlib-dynamic option.
+
+=item B<-none>
+
+Use NULL cipher (no encryption or decryption of input).
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+=back
+
+=head1 NOTES
+
+The program can be called either as C<openssl I<cipher>> or
+C<openssl enc -I<cipher>>. The first form doesn't work with
+engine-provided ciphers, because this form is processed before the
+configuration file is read and any ENGINEs loaded.
+Use the L<openssl-list(1)> command to get a list of supported ciphers.
+
+Engines which provide entirely new encryption algorithms (such as the ccgost
+engine which provides gost89 algorithm) should be configured in the
+configuration file. Engines specified on the command line using B<-engine>
+option can only be used for hardware-assisted implementations of
+ciphers which are supported by the OpenSSL core or another engine specified
+in the configuration file.
+
+When the enc command lists supported ciphers, ciphers provided by engines,
+specified in the configuration files are listed too.
+
+A password will be prompted for to derive the key and IV if necessary.
+
+The B<-salt> option should B<ALWAYS> be used if the key is being derived
+from a password unless you want compatibility with previous versions of
+OpenSSL.
+
+Without the B<-salt> option it is possible to perform efficient dictionary
+attacks on the password and to attack stream cipher encrypted data. The reason
+for this is that without the salt the same password always generates the same
+encryption key.
+
+When the salt is generated at random (that means when encrypting using a
+passphrase without explicit salt given using B<-S> option), the first bytes
+of the encrypted data are reserved to store the salt for later decrypting.
+
+Some of the ciphers do not have large keys and others have security
+implications if not used correctly. A beginner is advised to just use
+a strong block cipher, such as AES, in CBC mode.
+
+All the block ciphers normally use PKCS#5 padding, also known as standard
+block padding. This allows a rudimentary integrity or password check to
+be performed. However, since the chance of random data passing the test
+is better than 1 in 256 it isn't a very good test.
+
+If padding is disabled then the input data must be a multiple of the cipher
+block length.
+
+All RC2 ciphers have the same key and effective key length.
+
+Blowfish and RC5 algorithms use a 128 bit key.
+
+Please note that OpenSSL 3.0 changed the effect of the B<-S> option.
+Any explicit salt value specified via this option is no longer prepended to the
+ciphertext when encrypting, and must again be explicitly provided when decrypting.
+Conversely, when the B<-S> option is used during decryption, the ciphertext
+is expected to not have a prepended salt value.
+
+When using OpenSSL 3.0 or later to decrypt data that was encrypted with an
+explicit salt under OpenSSL 1.1.1 do not use the B<-S> option, the salt will
+then be read from the ciphertext.
+To generate ciphertext that can be decrypted with OpenSSL 1.1.1 do not use
+the B<-S> option, the salt will be then be generated randomly and prepended
+to the output.
+
+=head1 SUPPORTED CIPHERS
+
+Note that some of these ciphers can be disabled at compile time
+and some are available only if an appropriate engine is configured
+in the configuration file. The output when invoking this command
+with the B<-list> option (that is C<openssl enc -list>) is
+a list of ciphers, supported by your version of OpenSSL, including
+ones provided by configured engines.
+
+This command does not support authenticated encryption modes
+like CCM and GCM, and will not support such modes in the future.
+This is due to having to begin streaming output (e.g., to standard output
+when B<-out> is not used) before the authentication tag could be validated.
+When this command is used in a pipeline, the receiving end will not be
+able to roll back upon authentication failure. The AEAD modes currently in
+common use also suffer from catastrophic failure of confidentiality and/or
+integrity upon reuse of key/iv/nonce, and since B<openssl enc> places the
+entire burden of key/iv/nonce management upon the user, the risk of
+exposing AEAD modes is too great to allow. These key/iv/nonce
+management issues also affect other modes currently exposed in this command,
+but the failure modes are less extreme in these cases, and the
+functionality cannot be removed with a stable release branch.
+For bulk encryption of data, whether using authenticated encryption
+modes or other modes, L<openssl-cms(1)> is recommended, as it provides a
+standard data format and performs the needed key/iv/nonce management.
+
+
+ base64 Base 64
+
+ bf-cbc Blowfish in CBC mode
+ bf Alias for bf-cbc
+ blowfish Alias for bf-cbc
+ bf-cfb Blowfish in CFB mode
+ bf-ecb Blowfish in ECB mode
+ bf-ofb Blowfish in OFB mode
+
+ cast-cbc CAST in CBC mode
+ cast Alias for cast-cbc
+ cast5-cbc CAST5 in CBC mode
+ cast5-cfb CAST5 in CFB mode
+ cast5-ecb CAST5 in ECB mode
+ cast5-ofb CAST5 in OFB mode
+
+ chacha20 ChaCha20 algorithm
+
+ des-cbc DES in CBC mode
+ des Alias for des-cbc
+ des-cfb DES in CFB mode
+ des-ofb DES in OFB mode
+ des-ecb DES in ECB mode
+
+ des-ede-cbc Two key triple DES EDE in CBC mode
+ des-ede Two key triple DES EDE in ECB mode
+ des-ede-cfb Two key triple DES EDE in CFB mode
+ des-ede-ofb Two key triple DES EDE in OFB mode
+
+ des-ede3-cbc Three key triple DES EDE in CBC mode
+ des-ede3 Three key triple DES EDE in ECB mode
+ des3 Alias for des-ede3-cbc
+ des-ede3-cfb Three key triple DES EDE CFB mode
+ des-ede3-ofb Three key triple DES EDE in OFB mode
+
+ desx DESX algorithm.
+
+ gost89 GOST 28147-89 in CFB mode (provided by ccgost engine)
+ gost89-cnt GOST 28147-89 in CNT mode (provided by ccgost engine)
+
+ idea-cbc IDEA algorithm in CBC mode
+ idea same as idea-cbc
+ idea-cfb IDEA in CFB mode
+ idea-ecb IDEA in ECB mode
+ idea-ofb IDEA in OFB mode
+
+ rc2-cbc 128 bit RC2 in CBC mode
+ rc2 Alias for rc2-cbc
+ rc2-cfb 128 bit RC2 in CFB mode
+ rc2-ecb 128 bit RC2 in ECB mode
+ rc2-ofb 128 bit RC2 in OFB mode
+ rc2-64-cbc 64 bit RC2 in CBC mode
+ rc2-40-cbc 40 bit RC2 in CBC mode
+
+ rc4 128 bit RC4
+ rc4-64 64 bit RC4
+ rc4-40 40 bit RC4
+
+ rc5-cbc RC5 cipher in CBC mode
+ rc5 Alias for rc5-cbc
+ rc5-cfb RC5 cipher in CFB mode
+ rc5-ecb RC5 cipher in ECB mode
+ rc5-ofb RC5 cipher in OFB mode
+
+ seed-cbc SEED cipher in CBC mode
+ seed Alias for seed-cbc
+ seed-cfb SEED cipher in CFB mode
+ seed-ecb SEED cipher in ECB mode
+ seed-ofb SEED cipher in OFB mode
+
+ sm4-cbc SM4 cipher in CBC mode
+ sm4 Alias for sm4-cbc
+ sm4-cfb SM4 cipher in CFB mode
+ sm4-ctr SM4 cipher in CTR mode
+ sm4-ecb SM4 cipher in ECB mode
+ sm4-ofb SM4 cipher in OFB mode
+
+ aes-[128|192|256]-cbc 128/192/256 bit AES in CBC mode
+ aes[128|192|256] Alias for aes-[128|192|256]-cbc
+ aes-[128|192|256]-cfb 128/192/256 bit AES in 128 bit CFB mode
+ aes-[128|192|256]-cfb1 128/192/256 bit AES in 1 bit CFB mode
+ aes-[128|192|256]-cfb8 128/192/256 bit AES in 8 bit CFB mode
+ aes-[128|192|256]-ctr 128/192/256 bit AES in CTR mode
+ aes-[128|192|256]-ecb 128/192/256 bit AES in ECB mode
+ aes-[128|192|256]-ofb 128/192/256 bit AES in OFB mode
+
+ aria-[128|192|256]-cbc 128/192/256 bit ARIA in CBC mode
+ aria[128|192|256] Alias for aria-[128|192|256]-cbc
+ aria-[128|192|256]-cfb 128/192/256 bit ARIA in 128 bit CFB mode
+ aria-[128|192|256]-cfb1 128/192/256 bit ARIA in 1 bit CFB mode
+ aria-[128|192|256]-cfb8 128/192/256 bit ARIA in 8 bit CFB mode
+ aria-[128|192|256]-ctr 128/192/256 bit ARIA in CTR mode
+ aria-[128|192|256]-ecb 128/192/256 bit ARIA in ECB mode
+ aria-[128|192|256]-ofb 128/192/256 bit ARIA in OFB mode
+
+ camellia-[128|192|256]-cbc 128/192/256 bit Camellia in CBC mode
+ camellia[128|192|256] Alias for camellia-[128|192|256]-cbc
+ camellia-[128|192|256]-cfb 128/192/256 bit Camellia in 128 bit CFB mode
+ camellia-[128|192|256]-cfb1 128/192/256 bit Camellia in 1 bit CFB mode
+ camellia-[128|192|256]-cfb8 128/192/256 bit Camellia in 8 bit CFB mode
+ camellia-[128|192|256]-ctr 128/192/256 bit Camellia in CTR mode
+ camellia-[128|192|256]-ecb 128/192/256 bit Camellia in ECB mode
+ camellia-[128|192|256]-ofb 128/192/256 bit Camellia in OFB mode
+
+=head1 EXAMPLES
+
+Just base64 encode a binary file:
+
+ openssl base64 -in file.bin -out file.b64
+
+Decode the same file
+
+ openssl base64 -d -in file.b64 -out file.bin
+
+Encrypt a file using AES-128 using a prompted password
+and PBKDF2 key derivation:
+
+ openssl enc -aes128 -pbkdf2 -in file.txt -out file.aes128
+
+Decrypt a file using a supplied password:
+
+ openssl enc -aes128 -pbkdf2 -d -in file.aes128 -out file.txt \
+ -pass pass:<password>
+
+Encrypt a file then base64 encode it (so it can be sent via mail for example)
+using AES-256 in CTR mode and PBKDF2 key derivation:
+
+ openssl enc -aes-256-ctr -pbkdf2 -a -in file.txt -out file.aes256
+
+Base64 decode a file then decrypt it using a password supplied in a file:
+
+ openssl enc -aes-256-ctr -pbkdf2 -d -a -in file.aes256 -out file.txt \
+ -pass file:<passfile>
+
+=head1 BUGS
+
+The B<-A> option when used with large files doesn't work properly.
+
+The B<openssl enc> command only supports a fixed number of algorithms with
+certain parameters. So if, for example, you want to use RC2 with a
+76 bit key or RC4 with an 84 bit key you can't use this program.
+
+=head1 HISTORY
+
+The default digest was changed from MD5 to SHA256 in OpenSSL 1.1.0.
+
+The B<-list> option was added in OpenSSL 1.1.1e.
+
+The B<-ciphers> and B<-engine> options were deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-engine.pod.in b/doc/man1/openssl-engine.pod.in
new file mode 100644
index 000000000000..bcc31ebad190
--- /dev/null
+++ b/doc/man1/openssl-engine.pod.in
@@ -0,0 +1,132 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-engine - load and query engines
+
+=head1 SYNOPSIS
+
+B<openssl engine>
+[B<-help>]
+[B<-v>]
+[B<-vv>]
+[B<-vvv>]
+[B<-vvvv>]
+[B<-c>]
+[B<-t>]
+[B<-tt>]
+[B<-pre> I<command>] ...
+[B<-post> I<command>] ...
+[I<engine> ...]
+
+=head1 DESCRIPTION
+
+This command has been deprecated. Providers should be used instead of engines.
+
+This command is used to query the status and capabilities
+of the specified I<engine>s.
+Engines may be specified before and after all other command-line flags.
+Only those specified are queried.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Display an option summary.
+
+=item B<-v> B<-vv> B<-vvv> B<-vvvv>
+
+Provides information about each specified engine. The first flag lists
+all the possible run-time control commands; the second adds a
+description of each command; the third adds the input flags, and the
+final option adds the internal input flags.
+
+=item B<-c>
+
+Lists the capabilities of each engine.
+
+=item B<-t>
+
+Tests if each specified engine is available, and displays the answer.
+
+=item B<-tt>
+
+Displays an error trace for any unavailable engine.
+
+=item B<-pre> I<command>
+
+=item B<-post> I<command>
+
+Command-line configuration of engines.
+The B<-pre> command is given to the engine before it is loaded and
+the B<-post> command is given after the engine is loaded.
+The I<command> is of the form I<cmd>:I<val> where I<cmd> is the command,
+and I<val> is the value for the command.
+See the example below.
+
+These two options are cumulative, so they may be given more than once in the
+same command.
+
+=back
+
+=head1 EXAMPLES
+
+To list all the commands available to a dynamic engine:
+
+ $ openssl engine -t -tt -vvvv dynamic
+ (dynamic) Dynamic engine loading support
+ [ unavailable ]
+ SO_PATH: Specifies the path to the new ENGINE shared library
+ (input flags): STRING
+ NO_VCHECK: Specifies to continue even if version checking fails (boolean)
+ (input flags): NUMERIC
+ ID: Specifies an ENGINE id name for loading
+ (input flags): STRING
+ LIST_ADD: Whether to add a loaded ENGINE to the internal list (0=no,1=yes,2=mandatory)
+ (input flags): NUMERIC
+ DIR_LOAD: Specifies whether to load from 'DIR_ADD' directories (0=no,1=yes,2=mandatory)
+ (input flags): NUMERIC
+ DIR_ADD: Adds a directory from which ENGINEs can be loaded
+ (input flags): STRING
+ LOAD: Load up the ENGINE specified by other settings
+ (input flags): NO_INPUT
+
+To list the capabilities of the B<rsax> engine:
+
+ $ openssl engine -c
+ (rsax) RSAX engine support
+ [RSA]
+ (dynamic) Dynamic engine loading support
+
+=head1 ENVIRONMENT
+
+=over 4
+
+=item B<OPENSSL_ENGINES>
+
+The path to the engines directory.
+
+=back
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<config(5)>
+
+=head1 HISTORY
+
+This command was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-errstr.pod.in b/doc/man1/openssl-errstr.pod.in
new file mode 100644
index 000000000000..49a50adc192f
--- /dev/null
+++ b/doc/man1/openssl-errstr.pod.in
@@ -0,0 +1,54 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-errstr - lookup error codes
+
+=head1 SYNOPSIS
+
+B<openssl errstr>
+[B<-help>]
+I<error_code...>
+
+=head1 DESCRIPTION
+
+Sometimes an application will not load error message texts and only
+numerical forms will be available. This command can be
+used to display the meaning of the hex code. The hex code is the hex digits
+after the second colon.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Display a usage message.
+
+=back
+
+=head1 EXAMPLES
+
+The error code:
+
+ 27594:error:2006D080:lib(32)::reason(128)::107:
+
+can be displayed with:
+
+ openssl errstr 2006D080
+
+to produce the error message:
+
+ error:2006D080:BIO routines::no such file
+
+=head1 COPYRIGHT
+
+Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-fipsinstall.pod.in b/doc/man1/openssl-fipsinstall.pod.in
new file mode 100644
index 000000000000..97e2ae910c17
--- /dev/null
+++ b/doc/man1/openssl-fipsinstall.pod.in
@@ -0,0 +1,251 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-fipsinstall - perform FIPS configuration installation
+
+=head1 SYNOPSIS
+
+B<openssl fipsinstall>
+[B<-help>]
+[B<-in> I<configfilename>]
+[B<-out> I<configfilename>]
+[B<-module> I<modulefilename>]
+[B<-provider_name> I<providername>]
+[B<-section_name> I<sectionname>]
+[B<-verify>]
+[B<-mac_name> I<macname>]
+[B<-macopt> I<nm>:I<v>]
+[B<-noout>]
+[B<-quiet>]
+[B<-no_conditional_errors>]
+[B<-no_security_checks>]
+[B<-self_test_onload>]
+[B<-corrupt_desc> I<selftest_description>]
+[B<-corrupt_type> I<selftest_type>]
+[B<-config> I<parent_config>]
+
+=head1 DESCRIPTION
+
+This command is used to generate a FIPS module configuration file.
+This configuration file can be used each time a FIPS module is loaded
+in order to pass data to the FIPS module self tests. The FIPS module always
+verifies its MAC, but optionally only needs to run the KAT's once,
+at installation.
+
+The generated configuration file consists of:
+
+=over 4
+
+=item - A MAC of the FIPS module file.
+
+=item - A test status indicator.
+
+This indicates if the Known Answer Self Tests (KAT's) have successfully run.
+
+=item - A MAC of the status indicator.
+
+=item - A control for conditional self tests errors.
+
+By default if a continuous test (e.g a key pair test) fails then the FIPS module
+will enter an error state, and no services or cryptographic algorithms will be
+able to be accessed after this point.
+The default value of '1' will cause the fips module error state to be entered.
+If the value is '0' then the module error state will not be entered.
+Regardless of whether the error state is entered or not, the current operation
+(e.g. key generation) will return an error. The user is responsible for retrying
+the operation if the module error state is not entered.
+
+=item - A control to indicate whether run-time security checks are done.
+
+This indicates if run-time checks related to enforcement of security parameters
+such as minimum security strength of keys and approved curve names are used.
+The default value of '1' will perform the checks.
+If the value is '0' the checks are not performed and FIPS compliance must
+be done by procedures documented in the relevant Security Policy.
+
+=back
+
+This file is described in L<fips_config(5)>.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print a usage message.
+
+=item B<-module> I<filename>
+
+Filename of the FIPS module to perform an integrity check on.
+The path provided in the filename is used to load the module when it is
+activated, and this overrides the environment variable B<OPENSSL_MODULES>.
+
+=item B<-out> I<configfilename>
+
+Filename to output the configuration data to; the default is standard output.
+
+=item B<-in> I<configfilename>
+
+Input filename to load configuration data from.
+Must be used if the B<-verify> option is specified.
+
+=item B<-verify>
+
+Verify that the input configuration file contains the correct information.
+
+=item B<-provider_name> I<providername>
+
+Name of the provider inside the configuration file.
+The default value is C<fips>.
+
+=item B<-section_name> I<sectionname>
+
+Name of the section inside the configuration file.
+The default value is C<fips_sect>.
+
+=item B<-mac_name> I<name>
+
+Specifies the name of a supported MAC algorithm which will be used.
+The MAC mechanisms that are available will depend on the options
+used when building OpenSSL.
+To see the list of supported MAC's use the command
+C<openssl list -mac-algorithms>. The default is B<HMAC>.
+
+=item B<-macopt> I<nm>:I<v>
+
+Passes options to the MAC algorithm.
+A comprehensive list of controls can be found in the EVP_MAC implementation
+documentation.
+Common control strings used for this command are:
+
+=over 4
+
+=item B<key>:I<string>
+
+Specifies the MAC key as an alphanumeric string (use if the key contains
+printable characters only).
+The string length must conform to any restrictions of the MAC algorithm.
+A key must be specified for every MAC algorithm.
+If no key is provided, the default that was specified when OpenSSL was
+configured is used.
+
+=item B<hexkey>:I<string>
+
+Specifies the MAC key in hexadecimal form (two hex digits per byte).
+The key length must conform to any restrictions of the MAC algorithm.
+A key must be specified for every MAC algorithm.
+If no key is provided, the default that was specified when OpenSSL was
+configured is used.
+
+=item B<digest>:I<string>
+
+Used by HMAC as an alphanumeric string (use if the key contains printable
+characters only).
+The string length must conform to any restrictions of the MAC algorithm.
+To see the list of supported digests, use the command
+C<openssl list -digest-commands>.
+The default digest is SHA-256.
+
+=back
+
+=item B<-noout>
+
+Disable logging of the self tests.
+
+=item B<-no_conditional_errors>
+
+Configure the module to not enter an error state if a conditional self test
+fails as described above.
+
+=item B<-no_security_checks>
+
+Configure the module to not perform run-time security checks as described above.
+
+=item B<-self_test_onload>
+
+Do not write the two fields related to the "test status indicator" and
+"MAC status indicator" to the output configuration file. Without these fields
+the self tests KATS will run each time the module is loaded. This option could be
+used for cross compiling, since the self tests need to run at least once on each
+target machine. Once the self tests have run on the target machine the user
+could possibly then add the 2 fields into the configuration using some other
+mechanism.
+
+=item B<-quiet>
+
+Do not output pass/fail messages. Implies B<-noout>.
+
+=item B<-corrupt_desc> I<selftest_description>,
+B<-corrupt_type> I<selftest_type>
+
+The corrupt options can be used to test failure of one or more self tests by
+name.
+Either option or both may be used to select the tests to corrupt.
+Refer to the entries for B<st-desc> and B<st-type> in L<OSSL_PROVIDER-FIPS(7)> for
+values that can be used.
+
+=item B<-config> I<parent_config>
+
+Test that a FIPS provider can be loaded from the specified configuration file.
+A previous call to this application needs to generate the extra configuration
+data that is included by the base C<parent_config> configuration file.
+See L<config(5)> for further information on how to set up a provider section.
+All other options are ignored if '-config' is used.
+
+=back
+
+=head1 NOTES
+
+Self tests results are logged by default if the options B<-quiet> and B<-noout>
+are not specified, or if either of the options B<-corrupt_desc> or
+B<-corrupt_type> are used.
+If the base configuration file is set up to autoload the fips module, then the
+fips module will be loaded and self tested BEFORE the fipsinstall application
+has a chance to set up its own self test callback. As a result of this the self
+test output and the options B<-corrupt_desc> and B<-corrupt_type> will be ignored.
+For normal usage the base configuration file should use the default provider
+when generating the fips configuration file.
+
+=head1 EXAMPLES
+
+Calculate the mac of a FIPS module F<fips.so> and run a FIPS self test
+for the module, and save the F<fips.cnf> configuration file:
+
+ openssl fipsinstall -module ./fips.so -out fips.cnf -provider_name fips
+
+Verify that the configuration file F<fips.cnf> contains the correct info:
+
+ openssl fipsinstall -module ./fips.so -in fips.cnf -provider_name fips -verify
+
+Corrupt any self tests which have the description C<SHA1>:
+
+ openssl fipsinstall -module ./fips.so -out fips.cnf -provider_name fips \
+ -corrupt_desc 'SHA1'
+
+Validate that the fips module can be loaded from a base configuration file:
+
+ export OPENSSL_CONF_INCLUDE=<path of configuration files>
+ export OPENSSL_MODULES=<provider-path>
+ openssl fipsinstall -config' 'default.cnf'
+
+
+=head1 SEE ALSO
+
+L<config(5)>,
+L<fips_config(5)>,
+L<OSSL_PROVIDER-FIPS(7)>,
+L<EVP_MAC(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-format-options.pod b/doc/man1/openssl-format-options.pod
new file mode 100644
index 000000000000..a9bd1d6971e0
--- /dev/null
+++ b/doc/man1/openssl-format-options.pod
@@ -0,0 +1,145 @@
+=pod
+
+=head1 NAME
+
+openssl-format-options - OpenSSL command input and output format options
+
+=head1 SYNOPSIS
+
+B<openssl>
+I<command>
+[ I<options> ... ]
+[ I<parameters> ... ]
+
+=head1 DESCRIPTION
+
+Several OpenSSL commands can take input or generate output in a variety
+of formats.
+
+Since OpenSSL 3.0 keys, single certificates, and CRLs can be read from
+files in any of the B<DER>, B<PEM> or B<P12> formats. Specifying their input
+format is no more needed and the openssl commands will automatically try all
+the possible formats. However if the B<DER> or B<PEM> input format is specified
+it will be enforced.
+
+In order to access a key via an engine the input format B<ENGINE> may be used;
+alternatively the key identifier in the <uri> argument of the respective key
+option may be preceded by C<org.openssl.engine:>.
+See L<openssl(1)/Engine Options> for an example usage of the latter.
+
+=head1 OPTIONS
+
+=head2 Format Options
+
+The options to specify the format are as follows.
+Refer to the individual man page to see which options are accepted.
+
+=over 4
+
+=item B<-inform> I<format>, B<-outform> I<format>
+
+The format of the input or output streams.
+
+=item B<-keyform> I<format>
+
+Format of a private key input source.
+
+=item B<-CRLform> I<format>
+
+Format of a CRL input source.
+
+=back
+
+=head2 Format Option Arguments
+
+The possible format arguments are described below.
+Both uppercase and lowercase are accepted.
+
+The list of acceptable format arguments, and the default,
+is described in each command documentation.
+
+=over 4
+
+=item B<DER>
+
+A binary format, encoded or parsed according to Distinguished Encoding Rules
+(DER) of the ASN.1 data language.
+
+=item B<ENGINE>
+
+Used to specify that the cryptographic material is in an OpenSSL B<engine>.
+An engine must be configured or specified using the B<-engine> option.
+A password or PIN may be supplied to the engine using the B<-passin> option.
+
+=item B<P12>
+
+A DER-encoded file containing a PKCS#12 object.
+It might be necessary to provide a decryption password to retrieve
+the private key.
+
+=item B<PEM>
+
+A text format defined in IETF RFC 1421 and IETF RFC 7468. Briefly, this is
+a block of base-64 encoding (defined in IETF RFC 4648), with specific
+lines used to mark the start and end:
+
+ Text before the BEGIN line is ignored.
+ ----- BEGIN object-type -----
+ OT43gQKBgQC/2OHZoko6iRlNOAQ/tMVFNq7fL81GivoQ9F1U0Qr+DH3ZfaH8eIkX
+ xT0ToMPJUzWAn8pZv0snA0um6SIgvkCuxO84OkANCVbttzXImIsL7pFzfcwV/ERK
+ UM6j0ZuSMFOCr/lGPAoOQU0fskidGEHi1/kW+suSr28TqsyYZpwBDQ==
+ ----- END object-type -----
+ Text after the END line is also ignored
+
+The I<object-type> must match the type of object that is expected.
+For example a C<BEGIN X509 CERTIFICATE> will not match if the command
+is trying to read a private key. The types supported include:
+
+ ANY PRIVATE KEY
+ CERTIFICATE
+ CERTIFICATE REQUEST
+ CMS
+ DH PARAMETERS
+ DSA PARAMETERS
+ DSA PUBLIC KEY
+ EC PARAMETERS
+ EC PRIVATE KEY
+ ECDSA PUBLIC KEY
+ ENCRYPTED PRIVATE KEY
+ PARAMETERS
+ PKCS #7 SIGNED DATA
+ PKCS7
+ PRIVATE KEY
+ PUBLIC KEY
+ RSA PRIVATE KEY
+ SSL SESSION PARAMETERS
+ TRUSTED CERTIFICATE
+ X509 CRL
+ X9.42 DH PARAMETERS
+
+The following legacy I<object-type>'s are also supported for compatibility
+with earlier releases:
+
+ DSA PRIVATE KEY
+ NEW CERTIFICATE REQUEST
+ RSA PUBLIC KEY
+ X509 CERTIFICATE
+
+=item B<SMIME>
+
+An S/MIME object as described in IETF RFC 8551.
+Earlier versions were known as CMS and are compatible.
+Note that the parsing is simple and might fail to parse some legal data.
+
+=back
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-gendsa.pod.in b/doc/man1/openssl-gendsa.pod.in
new file mode 100644
index 000000000000..b6d37c576d3a
--- /dev/null
+++ b/doc/man1/openssl-gendsa.pod.in
@@ -0,0 +1,108 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-gendsa - generate a DSA private key from a set of parameters
+
+=head1 SYNOPSIS
+
+B<openssl> B<gendsa>
+[B<-help>]
+[B<-out> I<filename>]
+[B<-passout> I<arg>]
+[B<-aes128>]
+[B<-aes192>]
+[B<-aes256>]
+[B<-aria128>]
+[B<-aria192>]
+[B<-aria256>]
+[B<-camellia128>]
+[B<-camellia192>]
+[B<-camellia256>]
+[B<-des>]
+[B<-des3>]
+[B<-idea>]
+[B<-verbose>]
+{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+[I<paramfile>]
+
+=head1 DESCRIPTION
+
+This command generates a DSA private key from a DSA parameter file
+(which will be typically generated by the L<openssl-dsaparam(1)> command).
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-out> I<filename>
+
+Output the key to the specified file. If this argument is not specified then
+standard output is used.
+
+=item B<-passout> I<arg>
+
+The passphrase used for the output file.
+See L<openssl-passphrase-options(1)>.
+
+=item B<-aes128>, B<-aes192>, B<-aes256>, B<-aria128>, B<-aria192>, B<-aria256>, B<-camellia128>, B<-camellia192>, B<-camellia256>, B<-des>, B<-des3>, B<-idea>
+
+These options encrypt the private key with specified
+cipher before outputting it. A pass phrase is prompted for.
+If none of these options is specified no encryption is used.
+
+Note that all options must be given before the I<paramfile> argument.
+Otherwise they are ignored.
+
+=item B<-verbose>
+
+Print extra details about the operations being performed.
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+=item I<paramfile>
+
+The DSA parameter file to use. The parameters in this file determine
+the size of the private key. DSA parameters can be generated and
+examined using the L<openssl-dsaparam(1)> command.
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 NOTES
+
+DSA key generation is little more than random number generation so it is
+much quicker that RSA key generation for example.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-genpkey(1)>,
+L<openssl-dsaparam(1)>,
+L<openssl-dsa(1)>,
+L<openssl-genrsa(1)>,
+L<openssl-rsa(1)>
+
+=head1 HISTORY
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-genpkey.pod.in b/doc/man1/openssl-genpkey.pod.in
new file mode 100644
index 000000000000..181530670836
--- /dev/null
+++ b/doc/man1/openssl-genpkey.pod.in
@@ -0,0 +1,504 @@
+=pod
+
+=begin comment
+{- join("\n", @autowarntext) -}
+
+=end comment
+
+=head1 NAME
+
+openssl-genpkey - generate a private key
+
+=head1 SYNOPSIS
+
+B<openssl> B<genpkey>
+[B<-help>]
+[B<-out> I<filename>]
+[B<-outform> B<DER>|B<PEM>]
+[B<-quiet>]
+[B<-pass> I<arg>]
+[B<-I<cipher>>]
+[B<-paramfile> I<file>]
+[B<-algorithm> I<alg>]
+[B<-pkeyopt> I<opt>:I<value>]
+[B<-genparam>]
+[B<-text>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+{- $OpenSSL::safe::opt_config_synopsis -}
+
+=head1 DESCRIPTION
+
+This command generates a private key.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-out> I<filename>
+
+Output the key to the specified file. If this argument is not specified then
+standard output is used.
+
+=item B<-outform> B<DER>|B<PEM>
+
+The output format, except when B<-genparam> is given; the default is B<PEM>.
+See L<openssl-format-options(1)> for details.
+
+When B<-genparam> is given, B<-outform> is ignored.
+
+=item B<-quiet>
+
+Do not output "status dots" while generating keys.
+
+=item B<-pass> I<arg>
+
+The output file password source. For more information about the format of I<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-I<cipher>>
+
+This option encrypts the private key with the supplied cipher. Any algorithm
+name accepted by EVP_get_cipherbyname() is acceptable such as B<des3>.
+
+=item B<-algorithm> I<alg>
+
+Public key algorithm to use such as RSA, DSA, DH or DHX. If used this option must
+precede any B<-pkeyopt> options. The options B<-paramfile> and B<-algorithm>
+are mutually exclusive. Engines may add algorithms in addition to the standard
+built-in ones.
+
+Valid built-in algorithm names for private key generation are RSA, RSA-PSS, EC,
+X25519, X448, ED25519 and ED448.
+
+Valid built-in algorithm names for parameter generation (see the B<-genparam>
+option) are DH, DSA and EC.
+
+Note that the algorithm name X9.42 DH may be used as a synonym for DHX keys and
+PKCS#3 refers to DH Keys. Some options are not shared between DH and DHX keys.
+
+=item B<-pkeyopt> I<opt>:I<value>
+
+Set the public key algorithm option I<opt> to I<value>. The precise set of
+options supported depends on the public key algorithm used and its
+implementation. See L</KEY GENERATION OPTIONS> and
+L</PARAMETER GENERATION OPTIONS> below for more details.
+
+=item B<-genparam>
+
+Generate a set of parameters instead of a private key. If used this option must
+precede any B<-algorithm>, B<-paramfile> or B<-pkeyopt> options.
+
+=item B<-paramfile> I<filename>
+
+Some public key algorithms generate a private key based on a set of parameters.
+They can be supplied using this option. If this option is used the public key
+algorithm used is determined by the parameters. If used this option must
+precede any B<-pkeyopt> options. The options B<-paramfile> and B<-algorithm>
+are mutually exclusive.
+
+=item B<-text>
+
+Print an (unencrypted) text representation of private and public keys and
+parameters along with the PEM or DER structure.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+{- $OpenSSL::safe::opt_config_item -}
+
+=back
+
+=head1 KEY GENERATION OPTIONS
+
+The options supported by each algorithm and indeed each implementation of an
+algorithm can vary. The options for the OpenSSL implementations are detailed
+below. There are no key generation options defined for the X25519, X448, ED25519
+or ED448 algorithms.
+
+=head2 RSA Key Generation Options
+
+=over 4
+
+=item B<rsa_keygen_bits:numbits>
+
+The number of bits in the generated key. If not specified 2048 is used.
+
+=item B<rsa_keygen_primes:numprimes>
+
+The number of primes in the generated key. If not specified 2 is used.
+
+=item B<rsa_keygen_pubexp:value>
+
+The RSA public exponent value. This can be a large decimal or
+hexadecimal value if preceded by C<0x>. Default value is 65537.
+
+=back
+
+=head2 RSA-PSS Key Generation Options
+
+Note: by default an B<RSA-PSS> key has no parameter restrictions.
+
+=over 4
+
+=item B<rsa_keygen_bits>:I<numbits>, B<rsa_keygen_primes>:I<numprimes>,
+B<rsa_keygen_pubexp>:I<value>
+
+These options have the same meaning as the B<RSA> algorithm.
+
+=item B<rsa_pss_keygen_md>:I<digest>
+
+If set the key is restricted and can only use I<digest> for signing.
+
+=item B<rsa_pss_keygen_mgf1_md>:I<digest>
+
+If set the key is restricted and can only use I<digest> as it's MGF1
+parameter.
+
+=item B<rsa_pss_keygen_saltlen>:I<len>
+
+If set the key is restricted and I<len> specifies the minimum salt length.
+
+=back
+
+=head2 EC Key Generation Options
+
+The EC key generation options can also be used for parameter generation.
+
+=over 4
+
+=item B<ec_paramgen_curve>:I<curve>
+
+The EC curve to use. OpenSSL supports NIST curve names such as "P-256".
+
+=item B<ec_param_enc>:I<encoding>
+
+The encoding to use for parameters. The I<encoding> parameter must be either
+B<named_curve> or B<explicit>. The default value is B<named_curve>.
+
+=back
+
+=head2 DH Key Generation Options
+
+=over 4
+
+=item B<group>:I<name>
+
+The B<paramfile> option is not required if a named group is used here.
+See the L</DH Parameter Generation Options> section below.
+
+=back
+
+
+=head1 PARAMETER GENERATION OPTIONS
+
+The options supported by each algorithm and indeed each implementation of an
+algorithm can vary. The options for the OpenSSL implementations are detailed
+below.
+
+=head2 DSA Parameter Generation Options
+
+=over 4
+
+=item B<dsa_paramgen_bits>:I<numbits>
+
+The number of bits in the generated prime. If not specified 2048 is used.
+
+=item B<dsa_paramgen_q_bits>:I<numbits>
+
+=item B<qbits>:I<numbits>
+
+The number of bits in the q parameter. Must be one of 160, 224 or 256. If not
+specified 224 is used.
+
+=item B<dsa_paramgen_md>:I<digest>
+
+=item B<digest>:I<digest>
+
+The digest to use during parameter generation. Must be one of B<sha1>, B<sha224>
+or B<sha256>. If set, then the number of bits in B<q> will match the output size
+of the specified digest and the B<dsa_paramgen_q_bits> parameter will be
+ignored. If not set, then a digest will be used that gives an output matching
+the number of bits in B<q>, i.e. B<sha1> if q length is 160, B<sha224> if it 224
+or B<sha256> if it is 256.
+
+=item B<properties>:I<query>
+
+The I<digest> property I<query> string to use when fetching a digest from a provider.
+
+=item B<type>:I<type>
+
+The type of generation to use. Set this to 1 to use legacy FIPS186-2 parameter
+generation. The default of 0 uses FIPS186-4 parameter generation.
+
+=item B<gindex>:I<index>
+
+The index to use for canonical generation and verification of the generator g.
+Set this to a positive value ranging from 0..255 to use this mode. Larger values
+will only use the bottom byte.
+This I<index> must then be reused during key validation to verify the value of g.
+If this value is not set then g is not verifiable. The default value is -1.
+
+=item B<hexseed>:I<seed>
+
+The seed I<seed> data to use instead of generating a random seed internally.
+This should be used for testing purposes only. This will either produced fixed
+values for the generated parameters OR it will fail if the seed did not
+generate valid primes.
+
+=back
+
+=head2 DH Parameter Generation Options
+
+For most use cases it is recommended to use the B<group> option rather than
+the B<type> options. Note that the B<group> option is not used by default if
+no parameter generation options are specified.
+
+=over 4
+
+=item B<group>:I<name>
+
+=item B<dh_param>:I<name>
+
+Use a named DH group to select constant values for the DH parameters.
+All other options will be ignored if this value is set.
+
+Valid values that are associated with the B<algorithm> of B<"DH"> are:
+"ffdhe2048", "ffdhe3072", "ffdhe4096", "ffdhe6144", "ffdhe8192",
+"modp_1536", "modp_2048", "modp_3072", "modp_4096", "modp_6144", "modp_8192".
+
+Valid values that are associated with the B<algorithm> of B<"DHX"> are the
+RFC5114 names "dh_1024_160", "dh_2048_224", "dh_2048_256".
+
+=item B<dh_rfc5114>:I<num>
+
+If this option is set, then the appropriate RFC5114 parameters are used
+instead of generating new parameters. The value I<num> can be one of
+1, 2 or 3 that are equivalant to using the option B<group> with one of
+"dh_1024_160", "dh_2048_224" or "dh_2048_256".
+All other options will be ignored if this value is set.
+
+=item B<pbits>:I<numbits>
+
+=item B<dh_paramgen_prime_len>:I<numbits>
+
+The number of bits in the prime parameter I<p>. The default is 2048.
+
+=item B<qbits>:I<numbits>
+
+=item B<dh_paramgen_subprime_len>:I<numbits>
+
+The number of bits in the sub prime parameter I<q>. The default is 224.
+Only relevant if used in conjunction with the B<dh_paramgen_type> option to
+generate DHX parameters.
+
+=item B<safeprime-generator>:I<value>
+
+=item B<dh_paramgen_generator>:I<value>
+
+The value to use for the generator I<g>. The default is 2.
+The B<algorithm> option must be B<"DH"> for this parameter to be used.
+
+=item B<type>:I<string>
+
+The type name of DH parameters to generate. Valid values are:
+
+=over 4
+
+=item "generator"
+
+Use a safe prime generator with the option B<safeprime_generator>
+The B<algorithm> option must be B<"DH">.
+
+=item "fips186_4"
+
+FIPS186-4 parameter generation.
+The B<algorithm> option must be B<"DHX">.
+
+=item "fips186_2"
+
+FIPS186-4 parameter generation.
+The B<algorithm> option must be B<"DHX">.
+
+=item "group"
+
+Can be used with the option B<pbits> to select one of
+"ffdhe2048", "ffdhe3072", "ffdhe4096", "ffdhe6144" or "ffdhe8192".
+The B<algorithm> option must be B<"DH">.
+
+=item "default"
+
+Selects a default type based on the B<algorithm>. This is used by the
+OpenSSL default provider to set the type for backwards compatability.
+If B<algorithm> is B<"DH"> then B<"generator"> is used.
+If B<algorithm> is B<"DHX"> then B<"fips186_2"> is used.
+
+=back
+
+=item B<dh_paramgen_type>:I<value>
+
+The type of DH parameters to generate. Valid values are 0, 1, 2 or 3
+which correspond to setting the option B<type> to
+"generator", "fips186_2", "fips186_4" or "group".
+
+=item B<digest>:I<digest>
+
+The digest to use during parameter generation. Must be one of B<sha1>, B<sha224>
+or B<sha256>. If set, then the number of bits in B<qbits> will match the output
+size of the specified digest and the B<qbits> parameter will be
+ignored. If not set, then a digest will be used that gives an output matching
+the number of bits in B<q>, i.e. B<sha1> if q length is 160, B<sha224> if it is
+224 or B<sha256> if it is 256.
+This is only used by "fips186_4" and "fips186_2" key generation.
+
+=item B<properties>:I<query>
+
+The I<digest> property I<query> string to use when fetching a digest from a provider.
+This is only used by "fips186_4" and "fips186_2" key generation.
+
+=item B<gindex>:I<index>
+
+The index to use for canonical generation and verification of the generator g.
+Set this to a positive value ranging from 0..255 to use this mode. Larger values
+will only use the bottom byte.
+This I<index> must then be reused during key validation to verify the value of g.
+If this value is not set then g is not verifiable. The default value is -1.
+This is only used by "fips186_4" and "fips186_2" key generation.
+
+=item B<hexseed>:I<seed>
+
+The seed I<seed> data to use instead of generating a random seed internally.
+This should be used for testing purposes only. This will either produced fixed
+values for the generated parameters OR it will fail if the seed did not
+generate valid primes.
+This is only used by "fips186_4" and "fips186_2" key generation.
+
+=back
+
+=head2 EC Parameter Generation Options
+
+The EC parameter generation options are the same as for key generation. See
+L</EC Key Generation Options> above.
+
+=head1 NOTES
+
+The use of the genpkey program is encouraged over the algorithm specific
+utilities because additional algorithm options and ENGINE provided algorithms
+can be used.
+
+=head1 EXAMPLES
+
+Generate an RSA private key using default parameters:
+
+ openssl genpkey -algorithm RSA -out key.pem
+
+Encrypt output private key using 128 bit AES and the passphrase "hello":
+
+ openssl genpkey -algorithm RSA -out key.pem -aes-128-cbc -pass pass:hello
+
+Generate a 2048 bit RSA key using 3 as the public exponent:
+
+ openssl genpkey -algorithm RSA -out key.pem \
+ -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:3
+
+Generate 2048 bit DSA parameters that can be validated: The output values for
+gindex and seed are required for key validation purposes and are not saved to
+the output pem file).
+
+ openssl genpkey -genparam -algorithm DSA -out dsap.pem -pkeyopt pbits:2048 \
+ -pkeyopt qbits:224 -pkeyopt digest:SHA256 -pkeyopt gindex:1 -text
+
+Generate DSA key from parameters:
+
+ openssl genpkey -paramfile dsap.pem -out dsakey.pem
+
+Generate 4096 bit DH Key using safe prime group ffdhe4096:
+
+ openssl genpkey -algorithm DH -out dhkey.pem -pkeyopt group:ffdhe4096
+
+Generate 2048 bit X9.42 DH key with 256 bit subgroup using RFC5114 group3:
+
+ openssl genpkey -algorithm DHX -out dhkey.pem -pkeyopt dh_rfc5114:3
+
+Generate a DH key using a DH parameters file:
+
+ openssl genpkey -paramfile dhp.pem -out dhkey.pem
+
+Output DH parameters for safe prime group ffdhe2048:
+
+ openssl genpkey -genparam -algorithm DH -out dhp.pem -pkeyopt group:ffdhe2048
+
+Output 2048 bit X9.42 DH parameters with 224 bit subgroup using RFC5114 group2:
+
+ openssl genpkey -genparam -algorithm DHX -out dhp.pem -pkeyopt dh_rfc5114:2
+
+Output 2048 bit X9.42 DH parameters with 224 bit subgroup using FIP186-4 keygen:
+
+ openssl genpkey -genparam -algorithm DHX -out dhp.pem -text \
+ -pkeyopt pbits:2048 -pkeyopt qbits:224 -pkeyopt digest:SHA256 \
+ -pkeyopt gindex:1 -pkeyopt dh_paramgen_type:2
+
+Output 1024 bit X9.42 DH parameters with 160 bit subgroup using FIP186-2 keygen:
+
+ openssl genpkey -genparam -algorithm DHX -out dhp.pem -text \
+ -pkeyopt pbits:1024 -pkeyopt qbits:160 -pkeyopt digest:SHA1 \
+ -pkeyopt gindex:1 -pkeyopt dh_paramgen_type:1
+
+Output 2048 bit DH parameters:
+
+ openssl genpkey -genparam -algorithm DH -out dhp.pem \
+ -pkeyopt dh_paramgen_prime_len:2048
+
+Output 2048 bit DH parameters using a generator:
+
+ openssl genpkey -genparam -algorithm DH -out dhpx.pem \
+ -pkeyopt dh_paramgen_prime_len:2048 \
+ -pkeyopt dh_paramgen_type:1
+
+Generate EC parameters:
+
+ openssl genpkey -genparam -algorithm EC -out ecp.pem \
+ -pkeyopt ec_paramgen_curve:secp384r1 \
+ -pkeyopt ec_param_enc:named_curve
+
+Generate EC key from parameters:
+
+ openssl genpkey -paramfile ecp.pem -out eckey.pem
+
+Generate EC key directly:
+
+ openssl genpkey -algorithm EC -out eckey.pem \
+ -pkeyopt ec_paramgen_curve:P-384 \
+ -pkeyopt ec_param_enc:named_curve
+
+Generate an X25519 private key:
+
+ openssl genpkey -algorithm X25519 -out xkey.pem
+
+Generate an ED448 private key:
+
+ openssl genpkey -algorithm ED448 -out xkey.pem
+
+=head1 HISTORY
+
+The ability to use NIST curve names, and to generate an EC key directly,
+were added in OpenSSL 1.0.2.
+The ability to generate X25519 keys was added in OpenSSL 1.1.0.
+The ability to generate X448, ED25519 and ED448 keys was added in OpenSSL 1.1.1.
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-genrsa.pod.in b/doc/man1/openssl-genrsa.pod.in
new file mode 100644
index 000000000000..629640961517
--- /dev/null
+++ b/doc/man1/openssl-genrsa.pod.in
@@ -0,0 +1,134 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-genrsa - generate an RSA private key
+
+=head1 SYNOPSIS
+
+B<openssl> B<genrsa>
+[B<-help>]
+[B<-out> I<filename>]
+[B<-passout> I<arg>]
+[B<-aes128>]
+[B<-aes192>]
+[B<-aes256>]
+[B<-aria128>]
+[B<-aria192>]
+[B<-aria256>]
+[B<-camellia128>]
+[B<-camellia192>]
+[B<-camellia256>]
+[B<-des>]
+[B<-des3>]
+[B<-idea>]
+[B<-F4>]
+[B<-f4>]
+[B<-3>]
+[B<-primes> I<num>]
+[B<-verbose>]
+[B<-traditional>]
+{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+[B<numbits>]
+
+=head1 DESCRIPTION
+
+This command has been deprecated.
+The L<openssl-genpkey(1)> command should be used instead.
+
+This command generates an RSA private key.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-out> I<filename>
+
+Output the key to the specified file. If this argument is not specified then
+standard output is used.
+
+=item B<-passout> I<arg>
+
+The output file password source. For more information about the format
+see L<openssl-passphrase-options(1)>.
+
+=item B<-aes128>, B<-aes192>, B<-aes256>, B<-aria128>, B<-aria192>, B<-aria256>, B<-camellia128>, B<-camellia192>, B<-camellia256>, B<-des>, B<-des3>, B<-idea>
+
+These options encrypt the private key with specified
+cipher before outputting it. If none of these options is
+specified no encryption is used. If encryption is used a pass phrase is prompted
+for if it is not supplied via the B<-passout> argument.
+
+=item B<-F4>, B<-f4>, B<-3>
+
+The public exponent to use, either 65537 or 3. The default is 65537.
+The B<-3> option has been deprecated.
+
+=item B<-primes> I<num>
+
+Specify the number of primes to use while generating the RSA key. The I<num>
+parameter must be a positive integer that is greater than 1 and less than 16.
+If I<num> is greater than 2, then the generated key is called a 'multi-prime'
+RSA key, which is defined in RFC 8017.
+
+=item B<-verbose>
+
+Print extra details about the operations being performed.
+
+=item B<-traditional>
+
+Write the key using the traditional PKCS#1 format instead of the PKCS#8 format.
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=item B<numbits>
+
+The size of the private key to generate in bits. This must be the last option
+specified. The default is 2048 and values less than 512 are not allowed.
+
+=back
+
+=head1 NOTES
+
+RSA private key generation essentially involves the generation of two or more
+prime numbers. When generating a private key various symbols will be output to
+indicate the progress of the generation. A B<.> represents each number which
+has passed an initial sieve test, B<+> means a number has passed a single
+round of the Miller-Rabin primality test, B<*> means the current prime starts
+a regenerating progress due to some failed tests. A newline means that the number
+has passed all the prime tests (the actual number depends on the key size).
+
+Because key generation is a random process the time taken to generate a key
+may vary somewhat. But in general, more primes lead to less generation time
+of a key.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-genpkey(1)>,
+L<openssl-gendsa(1)>
+
+=head1 HISTORY
+
+This command was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-info.pod.in b/doc/man1/openssl-info.pod.in
new file mode 100644
index 000000000000..0e91bb28ee10
--- /dev/null
+++ b/doc/man1/openssl-info.pod.in
@@ -0,0 +1,91 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-info - print OpenSSL built-in information
+
+=head1 SYNOPSIS
+
+B<openssl info>
+[B<-help>]
+[B<-configdir>]
+[B<-enginesdir>]
+[B<-modulesdir> ]
+[B<-dsoext>]
+[B<-dirnamesep>]
+[B<-listsep>]
+[B<-seeds>]
+[B<-cpusettings>]
+
+=head1 DESCRIPTION
+
+This command is used to print out information about OpenSSL.
+The information is written exactly as it is with no extra text, which
+makes useful for scripts.
+
+As a consequence, only one item may be chosen for each run of this
+command.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-configdir>
+
+Outputs the default directory for OpenSSL configuration files.
+
+=item B<-enginesdir>
+
+Outputs the default directory for OpenSSL engine modules.
+
+=item B<-modulesdir>
+
+Outputs the default directory for OpenSSL dynamically loadable modules
+other than engine modules.
+
+=item B<-dsoext>
+
+Outputs the DSO extension OpenSSL uses.
+
+=item B<-dirnamesep>
+
+Outputs the separator character between a directory specification and
+a filename.
+Note that on some operating systems, this is not the same as the
+separator between directory elements.
+
+=item B<-listsep>
+
+Outputs the OpenSSL list separator character.
+This is typically used to construct C<$PATH> (C<%PATH%> on Windows)
+style lists.
+
+=item B<-seeds>
+
+Outputs the randomness seed sources.
+
+=item B<-cpusettings>
+
+Outputs the OpenSSL CPU settings info.
+
+=back
+
+=head1 HISTORY
+
+This command was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-kdf.pod.in b/doc/man1/openssl-kdf.pod.in
new file mode 100644
index 000000000000..23776378a1be
--- /dev/null
+++ b/doc/man1/openssl-kdf.pod.in
@@ -0,0 +1,205 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-kdf - perform Key Derivation Function operations
+
+=head1 SYNOPSIS
+
+B<openssl kdf>
+[B<-help>]
+[B<-cipher>]
+[B<-digest>]
+[B<-mac>]
+[B<-kdfopt> I<nm>:I<v>]
+[B<-keylen> I<num>]
+[B<-out> I<filename>]
+[B<-binary>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
+I<kdf_name>
+
+=head1 DESCRIPTION
+
+The key derivation functions generate a derived key from either a secret or
+password.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print a usage message.
+
+=item B<-keylen> I<num>
+
+The output size of the derived key. This field is required.
+
+=item B<-out> I<filename>
+
+Filename to output to, or standard output by default.
+
+=item B<-binary>
+
+Output the derived key in binary form. Uses hexadecimal text format if not specified.
+
+=item B<-cipher> I<name>
+
+Specify the cipher to be used by the KDF.
+Not all KDFs require a cipher and it is an error to use this option in such
+cases.
+
+=item B<-digest> I<name>
+
+Specify the digest to be used by the KDF.
+Not all KDFs require a digest and it is an error to use this option in such
+cases.
+To see the list of supported digests, use C<openssl list -digest-commands>.
+
+=item B<-mac> I<name>
+
+Specify the MAC to be used by the KDF.
+Not all KDFs require a MAC and it is an error to use this option in such
+cases.
+
+=item B<-kdfopt> I<nm>:I<v>
+
+Passes options to the KDF algorithm.
+A comprehensive list of parameters can be found in the EVP_KDF_CTX
+implementation documentation.
+Common parameter names used by EVP_KDF_CTX_set_params() are:
+
+=over 4
+
+=item B<key:>I<string>
+
+Specifies the secret key as an alphanumeric string (use if the key contains
+printable characters only).
+The string length must conform to any restrictions of the KDF algorithm.
+A key must be specified for most KDF algorithms.
+
+=item B<hexkey:>I<string>
+
+Specifies the secret key in hexadecimal form (two hex digits per byte).
+The key length must conform to any restrictions of the KDF algorithm.
+A key must be specified for most KDF algorithms.
+
+=item B<pass:>I<string>
+
+Specifies the password as an alphanumeric string (use if the password contains
+printable characters only).
+The password must be specified for PBKDF2 and scrypt.
+
+=item B<hexpass:>I<string>
+
+Specifies the password in hexadecimal form (two hex digits per byte).
+The password must be specified for PBKDF2 and scrypt.
+
+=item B<digest:>I<string>
+
+This option is identical to the B<-digest> option.
+
+=item B<cipher:>I<string>
+
+This option is identical to the B<-cipher> option.
+
+=item B<mac:>I<string>
+
+This option is identical to the B<-mac> option.
+
+=back
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=item I<kdf_name>
+
+Specifies the name of a supported KDF algorithm which will be used.
+The supported algorithms names include TLS1-PRF, HKDF, SSKDF, PBKDF2,
+SSHKDF, X942KDF-ASN1, X942KDF-CONCAT, X963KDF and SCRYPT.
+
+=back
+
+=head1 EXAMPLES
+
+Use TLS1-PRF to create a hex-encoded derived key from a secret key and seed:
+
+ openssl kdf -keylen 16 -kdfopt digest:SHA2-256 -kdfopt key:secret \
+ -kdfopt seed:seed TLS1-PRF
+
+Use HKDF to create a hex-encoded derived key from a secret key, salt and info:
+
+ openssl kdf -keylen 10 -kdfopt digest:SHA2-256 -kdfopt key:secret \
+ -kdfopt salt:salt -kdfopt info:label HKDF
+
+Use SSKDF with KMAC to create a hex-encoded derived key from a secret key, salt and info:
+
+ openssl kdf -keylen 64 -kdfopt mac:KMAC-128 -kdfopt maclen:20 \
+ -kdfopt hexkey:b74a149a161545 -kdfopt hexinfo:348a37a2 \
+ -kdfopt hexsalt:3638271ccd68a2 SSKDF
+
+Use SSKDF with HMAC to create a hex-encoded derived key from a secret key, salt and info:
+
+ openssl kdf -keylen 16 -kdfopt mac:HMAC -kdfopt digest:SHA2-256 \
+ -kdfopt hexkey:b74a149a -kdfopt hexinfo:348a37a2 \
+ -kdfopt hexsalt:3638271c SSKDF
+
+Use SSKDF with Hash to create a hex-encoded derived key from a secret key, salt and info:
+
+ openssl kdf -keylen 14 -kdfopt digest:SHA2-256 \
+ -kdfopt hexkey:6dbdc23f045488 \
+ -kdfopt hexinfo:a1b2c3d4 SSKDF
+
+Use SSHKDF to create a hex-encoded derived key from a secret key, hash and session_id:
+
+ openssl kdf -keylen 16 -kdfopt digest:SHA2-256 \
+ -kdfopt hexkey:0102030405 \
+ -kdfopt hexxcghash:06090A \
+ -kdfopt hexsession_id:01020304 \
+ -kdfopt type:A SSHKDF
+
+Use PBKDF2 to create a hex-encoded derived key from a password and salt:
+
+ openssl kdf -keylen 32 -kdfopt digest:SHA256 -kdfopt pass:password \
+ -kdfopt salt:salt -kdfopt iter:2 PBKDF2
+
+Use scrypt to create a hex-encoded derived key from a password and salt:
+
+ openssl kdf -keylen 64 -kdfopt pass:password -kdfopt salt:NaCl \
+ -kdfopt n:1024 -kdfopt r:8 -kdfopt p:16 \
+ -kdfopt maxmem_bytes:10485760 SCRYPT
+
+=head1 NOTES
+
+The KDF mechanisms that are available will depend on the options
+used when building OpenSSL.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-pkeyutl(1)>,
+L<EVP_KDF(3)>,
+L<EVP_KDF-SCRYPT(7)>,
+L<EVP_KDF-TLS1_PRF(7)>,
+L<EVP_KDF-PBKDF2(7)>,
+L<EVP_KDF-HKDF(7)>,
+L<EVP_KDF-SS(7)>,
+L<EVP_KDF-SSHKDF(7)>,
+L<EVP_KDF-X942-ASN1(7)>,
+L<EVP_KDF-X942-CONCAT(7)>,
+L<EVP_KDF-X963(7)>
+
+=head1 HISTORY
+
+Added in OpenSSL 3.0
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-list.pod.in b/doc/man1/openssl-list.pod.in
new file mode 100644
index 000000000000..784dcb89b11d
--- /dev/null
+++ b/doc/man1/openssl-list.pod.in
@@ -0,0 +1,247 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-list - list algorithms and features
+
+=head1 SYNOPSIS
+
+B<openssl list>
+[B<-help>]
+[B<-verbose>]
+[B<-select> I<name>]
+[B<-1>]
+[B<-commands>]
+[B<-standard-commands>]
+[B<-digest-algorithms>]
+{- output_off() if $disabled{"deprecated-3.0"}; ""
+-}[B<-digest-commands>]
+{- output_on() if $disabled{"deprecated-3.0"}; ""
+-}[B<-kdf-algorithms>]
+[B<-mac-algorithms>]
+[B<-random-instances>]
+[B<-random-generators>]
+[B<-cipher-algorithms>]
+{- output_off() if $disabled{"deprecated-3.0"}; ""
+-}[B<-cipher-commands>]
+{- output_on() if $disabled{"deprecated-3.0"}; ""
+-}[B<-encoders>]
+[B<-decoders>]
+[B<-key-managers>]
+[B<-key-exchange-algorithms>]
+[B<-kem-algorithms>]
+[B<-signature-algorithms>]
+[B<-asymcipher-algorithms>]
+[B<-public-key-algorithms>]
+[B<-public-key-methods>]
+[B<-store-loaders>]
+[B<-providers>]
+{- output_off() if $disabled{"deprecated-3.0"}; ""
+-}[B<-engines>]
+{- output_on() if $disabled{"deprecated-3.0"}; ""
+-}[B<-disabled>]
+[B<-objects>]
+[B<-options> I<command>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command is used to generate list of algorithms or disabled
+features.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Display a usage message.
+
+=item B<-verbose>
+
+Displays extra information.
+The options below where verbosity applies say a bit more about what that means.
+
+=item B<-select> I<name>
+
+Only list algorithms that match this name.
+
+=item B<-1>
+
+List the commands, digest-commands, or cipher-commands in a single column.
+If used, this option must be given first.
+
+=item B<-commands>
+
+Display a list of standard commands.
+
+=item B<-standard-commands>
+
+List of standard commands.
+
+=item B<-digest-commands>
+
+This option is deprecated. Use B<digest-algorithms> instead.
+
+Display a list of message digest commands, which are typically used
+as input to the L<openssl-dgst(1)> or L<openssl-speed(1)> commands.
+
+=item B<-cipher-commands>
+
+This option is deprecated. Use B<cipher-algorithms> instead.
+
+Display a list of cipher commands, which are typically used as input
+to the L<openssl-enc(1)> or L<openssl-speed(1)> commands.
+
+=item B<-cipher-algorithms>, B<-digest-algorithms>, B<-kdf-algorithms>,
+B<-mac-algorithms>,
+
+Display a list of symmetric cipher, digest, kdf and mac algorithms.
+See L</Display of algorithm names> for a description of how names are
+displayed.
+
+In verbose mode, the algorithms provided by a provider will get additional
+information on what parameters each implementation supports.
+
+=item B<-random-instances>
+
+List the primary, public and private random number generator details.
+
+=item B<-random-generators>
+
+Display a list of random number generators.
+See L</Display of algorithm names> for a description of how names are
+displayed.
+
+=item B<-encoders>
+
+Display a list of encoders.
+See L</Display of algorithm names> for a description of how names are
+displayed.
+
+In verbose mode, the algorithms provided by a provider will get additional
+information on what parameters each implementation supports.
+
+=item B<-decoders>
+
+Display a list of decoders.
+See L</Display of algorithm names> for a description of how names are
+displayed.
+
+In verbose mode, the algorithms provided by a provider will get additional
+information on what parameters each implementation supports.
+
+=item B<-public-key-algorithms>
+
+Display a list of public key algorithms, with each algorithm as
+a block of multiple lines, all but the first are indented.
+The options B<key-exchange-algorithms>, B<kem-algorithms>,
+B<signature-algorithms>, and B<asymcipher-algorithms> will display similar info.
+
+=item B<-public-key-methods>
+
+Display a list of public key methods.
+
+=item B<-key-managers>
+
+Display a list of key managers.
+
+=item B<-key-exchange-algorithms>
+
+Display a list of key exchange algorithms.
+
+=item B<-kem-algorithms>
+
+Display a list of key encapsulation algorithms.
+
+=item B<-signature-algorithms>
+
+Display a list of signature algorithms.
+
+=item B<-asymcipher-algorithms>
+
+Display a list of asymmetric cipher algorithms.
+
+=item B<-store-loaders>
+
+Display a list of store loaders.
+
+=item B<-providers>
+
+Display a list of all loaded providers with their names, version and status.
+
+In verbose mode, the full version and all provider parameters will additionally
+be displayed.
+
+
+=item B<-engines>
+
+This option is deprecated.
+
+Display a list of loaded engines.
+
+=item B<-disabled>
+
+Display a list of disabled features, those that were compiled out
+of the installation.
+
+=item B<-objects>
+
+Display a list of built in objects, i.e. OIDs with names. They're listed in the
+format described in L<config(5)/ASN1 Object Configuration Module>.
+
+=item B<-options> I<command>
+
+Output a two-column list of the options accepted by the specified I<command>.
+The first is the option name, and the second is a one-character indication
+of what type of parameter it takes, if any.
+This is an internal option, used for checking that the documentation
+is complete.
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head2 Display of algorithm names
+
+Algorithm names may be displayed in one of two manners:
+
+=over 4
+
+=item Legacy implementations
+
+Legacy implementations will simply display the main name of the
+algorithm on a line of its own, or in the form C<<foo > bar>> to show
+that C<foo> is an alias for the main name, C<bar>
+
+=item Provided implementations
+
+Implementations from a provider are displayed like this if the
+implementation is labeled with a single name:
+
+ foo @ bar
+
+or like this if it's labeled with multiple names:
+
+ { foo1, foo2 } @bar
+
+In both cases, C<bar> is the name of the provider.
+
+=back
+
+=head1 HISTORY
+
+The B<-engines>, B<-digest-commands>, and B<-cipher-commands> options
+were deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-mac.pod.in b/doc/man1/openssl-mac.pod.in
new file mode 100644
index 000000000000..563974799109
--- /dev/null
+++ b/doc/man1/openssl-mac.pod.in
@@ -0,0 +1,175 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-mac - perform Message Authentication Code operations
+
+=head1 SYNOPSIS
+
+B<openssl mac>
+[B<-help>]
+[B<-cipher>]
+[B<-digest>]
+[B<-macopt>]
+[B<-in> I<filename>]
+[B<-out> I<filename>]
+[B<-binary>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
+I<mac_name>
+
+=head1 DESCRIPTION
+
+The message authentication code functions output the MAC of a supplied input
+file.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print a usage message.
+
+=item B<-in> I<filename>
+
+Input filename to calculate a MAC for, or standard input by default.
+Standard input is used if the filename is '-'.
+Files and standard input are expected to be in binary format.
+
+=item B<-out> I<filename>
+
+Filename to output to, or standard output by default.
+
+=item B<-binary>
+
+Output the MAC in binary form. Uses hexadecimal text format if not specified.
+
+=item B<-cipher> I<name>
+
+Used by CMAC and GMAC to specify the cipher algorithm.
+For CMAC it must be one of AES-128-CBC, AES-192-CBC, AES-256-CBC or
+DES-EDE3-CBC.
+For GMAC it should be a GCM mode cipher e.g. AES-128-GCM.
+
+=item B<-digest> I<name>
+
+Used by HMAC as an alphanumeric string (use if the key contains printable
+characters only).
+The string length must conform to any restrictions of the MAC algorithm.
+To see the list of supported digests, use C<openssl list -digest-commands>.
+
+=item B<-macopt> I<nm>:I<v>
+
+Passes options to the MAC algorithm.
+A comprehensive list of controls can be found in the EVP_MAC implementation
+documentation.
+Common parameter names used by EVP_MAC_CTX_get_params() are:
+
+=over 4
+
+=item B<key:>I<string>
+
+Specifies the MAC key as an alphanumeric string (use if the key contains
+printable characters only).
+The string length must conform to any restrictions of the MAC algorithm.
+A key must be specified for every MAC algorithm.
+
+=item B<hexkey:>I<string>
+
+Specifies the MAC key in hexadecimal form (two hex digits per byte).
+The key length must conform to any restrictions of the MAC algorithm.
+A key must be specified for every MAC algorithm.
+
+=item B<iv:>I<string>
+
+Used by GMAC to specify an IV as an alphanumeric string (use if the IV contains
+printable characters only).
+
+=item B<hexiv:>I<string>
+
+Used by GMAC to specify an IV in hexadecimal form (two hex digits per byte).
+
+=item B<size:>I<int>
+
+Used by KMAC128 or KMAC256 to specify an output length.
+The default sizes are 32 or 64 bytes respectively.
+
+=item B<custom:>I<string>
+
+Used by KMAC128 or KMAC256 to specify a customization string.
+The default is the empty string "".
+
+=item B<digest:>I<string>
+
+This option is identical to the B<-digest> option.
+
+=item B<cipher:>I<string>
+
+This option is identical to the B<-cipher> option.
+
+=back
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=item I<mac_name>
+
+Specifies the name of a supported MAC algorithm which will be used.
+To see the list of supported MAC's use the command C<openssl list
+-mac-algorithms>.
+
+=back
+
+
+=head1 EXAMPLES
+
+To create a hex-encoded HMAC-SHA1 MAC of a file and write to stdout: \
+ openssl mac -digest SHA1 \
+ -macopt hexkey:000102030405060708090A0B0C0D0E0F10111213 \
+ -in msg.bin HMAC
+
+To create a SipHash MAC from a file with a binary file output: \
+ openssl mac -macopt hexkey:000102030405060708090A0B0C0D0E0F \
+ -in msg.bin -out out.bin -binary SipHash
+
+To create a hex-encoded CMAC-AES-128-CBC MAC from a file:\
+ openssl mac -cipher AES-128-CBC \
+ -macopt hexkey:77A77FAF290C1FA30C683DF16BA7A77B \
+ -in msg.bin CMAC
+
+To create a hex-encoded KMAC128 MAC from a file with a Customisation String
+'Tag' and output length of 16: \
+ openssl mac -macopt custom:Tag -macopt hexkey:40414243444546 \
+ -macopt size:16 -in msg.bin KMAC128
+
+To create a hex-encoded GMAC-AES-128-GCM with a IV from a file: \
+ openssl mac -cipher AES-128-GCM -macopt hexiv:E0E00F19FED7BA0136A797F3 \
+ -macopt hexkey:77A77FAF290C1FA30C683DF16BA7A77B -in msg.bin GMAC
+
+=head1 NOTES
+
+The MAC mechanisms that are available will depend on the options
+used when building OpenSSL.
+Use C<openssl list -mac-algorithms> to list them.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<EVP_MAC(3)>,
+L<EVP_MAC-CMAC(7)>,
+L<EVP_MAC-GMAC(7)>,
+L<EVP_MAC-HMAC(7)>,
+L<EVP_MAC-KMAC(7)>,
+L<EVP_MAC-Siphash(7)>,
+L<EVP_MAC-Poly1305(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-namedisplay-options.pod b/doc/man1/openssl-namedisplay-options.pod
new file mode 100644
index 000000000000..ff6ed1f4b470
--- /dev/null
+++ b/doc/man1/openssl-namedisplay-options.pod
@@ -0,0 +1,179 @@
+=pod
+
+=head1 NAME
+
+openssl-namedisplay-options - Distinguished name display options
+
+=head1 SYNOPSIS
+
+B<openssl>
+I<command>
+[ I<options> ... ]
+[ I<parameters> ... ]
+
+=head1 DESCRIPTION
+
+OpenSSL provides fine-grain control over how the subject and issuer DN's are
+displayed.
+This is specified by using the B<-nameopt> option, which takes a
+comma-separated list of options from the following set.
+An option may be preceded by a minus sign, C<->, to turn it off.
+The default value is C<oneline>.
+The first four are the most commonly used.
+
+=head1 OPTIONS
+
+=head2 Name Format Option Arguments
+
+The DN output format can be fine tuned with the following flags.
+
+=over 4
+
+=item B<compat>
+
+Display the name using an old format from previous OpenSSL versions.
+
+=item B<RFC2253>
+
+Display the name using the format defined in RFC 2253.
+It is equivalent to B<esc_2253>, B<esc_ctrl>, B<esc_msb>, B<utf8>,
+B<dump_nostr>, B<dump_unknown>, B<dump_der>, B<sep_comma_plus>, B<dn_rev>
+and B<sname>.
+
+=item B<oneline>
+
+Display the name in one line, using a format that is more readable
+RFC 2253.
+It is equivalent to B<esc_2253>, B<esc_ctrl>, B<esc_msb>, B<utf8>,
+B<dump_nostr>, B<dump_der>, B<use_quote>, B<sep_comma_plus_space>,
+B<space_eq> and B<sname> options.
+
+=item B<multiline>
+
+Display the name using multiple lines.
+It is equivalent to B<esc_ctrl>, B<esc_msb>, B<sep_multiline>, B<space_eq>,
+B<lname> and B<align>.
+
+=item B<esc_2253>
+
+Escape the "special" characters in a field, as required by RFC 2253.
+That is, any of the characters C<,+"E<lt>E<gt>;>, C<#> at the beginning of
+a string and leading or trailing spaces.
+
+=item B<esc_2254>
+
+Escape the "special" characters in a field as required by RFC 2254 in a field.
+That is, the B<NUL> character and of C<()*>.
+
+=item B<esc_ctrl>
+
+Escape non-printable ASCII characters, codes less than 0x20 (space)
+or greater than 0x7F (DELETE). They are displayed using RFC 2253 C<\XX>
+notation where B<XX> are the two hex digits representing the character value.
+
+=item B<esc_msb>
+
+Escape any characters with the most significant bit set, that is with
+values larger than 127, as described in B<esc_ctrl>.
+
+=item B<use_quote>
+
+Escapes some characters by surrounding the entire string with quotation
+marks, C<">.
+Without this option, individual special characters are preceded with
+a backslash character, C<\>.
+
+=item B<utf8>
+
+Convert all strings to UTF-8 format first as required by RFC 2253.
+If the output device is UTF-8 compatible, then using this option (and
+not setting B<esc_msb>) may give the correct display of multibyte
+characters.
+If this option is not set, then multibyte characters larger than 0xFF
+will be output as C<\UXXXX> for 16 bits or C<\WXXXXXXXX> for 32 bits.
+In addition, any UTF8Strings will be converted to their character form first.
+
+=item B<ignore_type>
+
+This option does not attempt to interpret multibyte characters in any
+way. That is, the content octets are merely dumped as though one octet
+represents each character. This is useful for diagnostic purposes but
+will result in rather odd looking output.
+
+=item B<show_type>
+
+Display the type of the ASN1 character string before the value,
+such as C<BMPSTRING: Hello World>.
+
+=item B<dump_der>
+
+Any fields that would be output in hex format are displayed using
+the DER encoding of the field.
+If not set, just the content octets are displayed.
+Either way, the B<#XXXX...> format of RFC 2253 is used.
+
+=item B<dump_nostr>
+
+Dump non-character strings, such as ASN.1 B<OCTET STRING>.
+If this option is not set, then non character string types will be displayed
+as though each content octet represents a single character.
+
+=item B<dump_all>
+
+Dump all fields. When this used with B<dump_der>, this allows the
+DER encoding of the structure to be unambiguously determined.
+
+=item B<dump_unknown>
+
+Dump any field whose OID is not recognised by OpenSSL.
+
+=item B<sep_comma_plus>, B<sep_comma_plus_space>, B<sep_semi_plus_space>,
+B<sep_multiline>
+
+Specify the field separators. The first word is used between the
+Relative Distinguished Names (RDNs) and the second is between
+multiple Attribute Value Assertions (AVAs). Multiple AVAs are
+very rare and their use is discouraged.
+The options ending in "space" additionally place a space after the separator to make it more readable.
+The B<sep_multiline> starts each field on its own line, and uses "plus space"
+for the AVA separator.
+It also indents the fields by four characters.
+The default value is B<sep_comma_plus_space>.
+
+=item B<dn_rev>
+
+Reverse the fields of the DN as required by RFC 2253.
+This also reverses the order of multiple AVAs in a field, but this is
+permissible as there is no ordering on values.
+
+=item B<nofname>, B<sname>, B<lname>, B<oid>
+
+Specify how the field name is displayed.
+B<nofname> does not display the field at all.
+B<sname> uses the "short name" form (CN for commonName for example).
+B<lname> uses the long form.
+B<oid> represents the OID in numerical form and is useful for
+diagnostic purpose.
+
+=item B<align>
+
+Align field values for a more readable output. Only usable with
+B<sep_multiline>.
+
+=item B<space_eq>
+
+Places spaces round the equal sign, C<=>, character which follows the field
+name.
+
+=back
+
+=head1 COPYRIGHT
+
+Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-nseq.pod.in b/doc/man1/openssl-nseq.pod.in
new file mode 100644
index 000000000000..eb131168ceaf
--- /dev/null
+++ b/doc/man1/openssl-nseq.pod.in
@@ -0,0 +1,76 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-nseq - create or examine a Netscape certificate sequence
+
+=head1 SYNOPSIS
+
+B<openssl> B<nseq>
+[B<-help>]
+[B<-in> I<filename>]
+[B<-out> I<filename>]
+[B<-toseq>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command takes a file containing a Netscape certificate
+sequence and prints out the certificates contained in it or takes a
+file of certificates and converts it into a Netscape certificate
+sequence.
+
+A Netscape certificate sequence is an old Netscape-specific format that
+can be sometimes be sent to browsers as an alternative to the standard PKCS#7
+format when several certificates are sent to the browser, for example during
+certificate enrollment. It was also used by Netscape certificate server.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-in> I<filename>
+
+This specifies the input filename to read or standard input if this
+option is not specified.
+
+=item B<-out> I<filename>
+
+Specifies the output filename or standard output by default.
+
+=item B<-toseq>
+
+Normally a Netscape certificate sequence will be input and the output
+is the certificates contained in it. With the B<-toseq> option the
+situation is reversed: a Netscape certificate sequence is created from
+a file of certificates.
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 EXAMPLES
+
+Output the certificates in a Netscape certificate sequence
+
+ openssl nseq -in nseq.pem -out certs.pem
+
+Create a Netscape certificate sequence
+
+ openssl nseq -in certs.pem -toseq -out nseq.pem
+
+=head1 COPYRIGHT
+
+Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-ocsp.pod.in b/doc/man1/openssl-ocsp.pod.in
new file mode 100644
index 000000000000..fbad5079af67
--- /dev/null
+++ b/doc/man1/openssl-ocsp.pod.in
@@ -0,0 +1,517 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-ocsp - Online Certificate Status Protocol command
+
+=head1 SYNOPSIS
+
+=head2 OCSP Client
+
+B<openssl> B<ocsp>
+[B<-help>]
+[B<-out> I<file>]
+[B<-issuer> I<file>]
+[B<-cert> I<file>]
+[B<-no_certs>]
+[B<-serial> I<n>]
+[B<-signer> I<file>]
+[B<-signkey> I<file>]
+[B<-sign_other> I<file>]
+[B<-nonce>]
+[B<-no_nonce>]
+[B<-req_text>]
+[B<-resp_text>]
+[B<-text>]
+[B<-reqout> I<file>]
+[B<-respout> I<file>]
+[B<-reqin> I<file>]
+[B<-respin> I<file>]
+[B<-url> I<URL>]
+[B<-host> I<host>:I<port>]
+[B<-path>]
+[B<-proxy> I<[http[s]://][userinfo@]host[:port][/path]>]
+[B<-no_proxy> I<addresses>]
+[B<-header>]
+[B<-timeout> I<seconds>]
+[B<-VAfile> I<file>]
+[B<-validity_period> I<n>]
+[B<-status_age> I<n>]
+[B<-noverify>]
+[B<-verify_other> I<file>]
+[B<-trust_other>]
+[B<-no_intern>]
+[B<-no_signature_verify>]
+[B<-no_cert_verify>]
+[B<-no_chain>]
+[B<-no_cert_checks>]
+[B<-no_explicit>]
+[B<-port> I<num>]
+[B<-ignore_err>]
+
+=head2 OCSP Server
+
+B<openssl> B<ocsp>
+[B<-index> I<file>]
+[B<-CA> I<file>]
+[B<-rsigner> I<file>]
+[B<-rkey> I<file>]
+[B<-passin> I<arg>]
+[B<-rother> I<file>]
+[B<-rsigopt> I<nm>:I<v>]
+[B<-rmd> I<digest>]
+[B<-badsig>]
+[B<-resp_no_certs>]
+[B<-nmin> I<n>]
+[B<-ndays> I<n>]
+[B<-resp_key_id>]
+[B<-nrequest> I<n>]
+[B<-multi> I<process-count>]
+[B<-rcid> I<digest>]
+[B<-I<digest>>]
+{- $OpenSSL::safe::opt_trust_synopsis -}
+{- $OpenSSL::safe::opt_v_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+The Online Certificate Status Protocol (OCSP) enables applications to
+determine the (revocation) state of an identified certificate (RFC 2560).
+
+This command performs many common OCSP tasks. It can be used
+to print out requests and responses, create requests and send queries
+to an OCSP responder and behave like a mini OCSP server itself.
+
+=head1 OPTIONS
+
+This command operates as either a client or a server.
+The options are described below, divided into those two modes.
+
+=head2 OCSP Client Options
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-out> I<filename>
+
+specify output filename, default is standard output.
+
+=item B<-issuer> I<filename>
+
+This specifies the current issuer certificate. This option can be used
+multiple times.
+This option B<MUST> come before any B<-cert> options.
+
+=item B<-cert> I<filename>
+
+Add the certificate I<filename> to the request. The issuer certificate
+is taken from the previous B<-issuer> option, or an error occurs if no
+issuer certificate is specified.
+
+=item B<-no_certs>
+
+Don't include any certificates in signed request.
+
+=item B<-serial> I<num>
+
+Same as the B<-cert> option except the certificate with serial number
+B<num> is added to the request. The serial number is interpreted as a
+decimal integer unless preceded by C<0x>. Negative integers can also
+be specified by preceding the value by a C<-> sign.
+
+=item B<-signer> I<filename>, B<-signkey> I<filename>
+
+Sign the OCSP request using the certificate specified in the B<-signer>
+option and the private key specified by the B<-signkey> option. If
+the B<-signkey> option is not present then the private key is read
+from the same file as the certificate. If neither option is specified then
+the OCSP request is not signed.
+
+=item B<-sign_other> I<filename>
+
+Additional certificates to include in the signed request.
+The input can be in PEM, DER, or PKCS#12 format.
+
+=item B<-nonce>, B<-no_nonce>
+
+Add an OCSP nonce extension to a request or disable OCSP nonce addition.
+Normally if an OCSP request is input using the B<-reqin> option no
+nonce is added: using the B<-nonce> option will force addition of a nonce.
+If an OCSP request is being created (using B<-cert> and B<-serial> options)
+a nonce is automatically added specifying B<-no_nonce> overrides this.
+
+=item B<-req_text>, B<-resp_text>, B<-text>
+
+Print out the text form of the OCSP request, response or both respectively.
+
+=item B<-reqout> I<file>, B<-respout> I<file>
+
+Write out the DER encoded certificate request or response to I<file>.
+
+=item B<-reqin> I<file>, B<-respin> I<file>
+
+Read OCSP request or response file from I<file>. These option are ignored
+if OCSP request or response creation is implied by other options (for example
+with B<-serial>, B<-cert> and B<-host> options).
+
+=item B<-url> I<responder_url>
+
+Specify the responder URL. Both HTTP and HTTPS (SSL/TLS) URLs can be specified.
+The optional userinfo and fragment components are ignored.
+Any given query component is handled as part of the path component.
+
+=item B<-host> I<hostname>:I<port>, B<-path> I<pathname>
+
+If the B<-host> option is present then the OCSP request is sent to the host
+I<hostname> on port I<port>. The B<-path> option specifies the HTTP pathname
+to use or "/" by default. This is equivalent to specifying B<-url> with scheme
+http:// and the given hostname, port, and pathname.
+
+=item B<-proxy> I<[http[s]://][userinfo@]host[:port][/path]>
+
+The HTTP(S) proxy server to use for reaching the OCSP server unless B<-no_proxy>
+applies, see below.
+The proxy port defaults to 80 or 443 if the scheme is C<https>; apart from that
+the optional C<http://> or C<https://> prefix is ignored,
+as well as any userinfo and path components.
+Defaults to the environment variable C<http_proxy> if set, else C<HTTP_PROXY>
+in case no TLS is used, otherwise C<https_proxy> if set, else C<HTTPS_PROXY>.
+
+=item B<-no_proxy> I<addresses>
+
+List of IP addresses and/or DNS names of servers
+not to use an HTTP(S) proxy for, separated by commas and/or whitespace
+(where in the latter case the whole argument must be enclosed in "...").
+Default is from the environment variable C<no_proxy> if set, else C<NO_PROXY>.
+
+=item B<-header> I<name>=I<value>
+
+Adds the header I<name> with the specified I<value> to the OCSP request
+that is sent to the responder.
+This may be repeated.
+
+=item B<-timeout> I<seconds>
+
+Connection timeout to the OCSP responder in seconds.
+On POSIX systems, when running as an OCSP responder, this option also limits
+the time that the responder is willing to wait for the client request.
+This time is measured from the time the responder accepts the connection until
+the complete request is received.
+
+=item B<-verify_other> I<file>
+
+File or URI containing additional certificates to search
+when attempting to locate
+the OCSP response signing certificate. Some responders omit the actual signer's
+certificate from the response: this option can be used to supply the necessary
+certificate in such cases.
+The input can be in PEM, DER, or PKCS#12 format.
+
+=item B<-trust_other>
+
+The certificates specified by the B<-verify_other> option should be explicitly
+trusted and no additional checks will be performed on them. This is useful
+when the complete responder certificate chain is not available or trusting a
+root CA is not appropriate.
+
+=item B<-VAfile> I<file>
+
+File or URI containing explicitly trusted responder certificates.
+Equivalent to the B<-verify_other> and B<-trust_other> options.
+The input can be in PEM, DER, or PKCS#12 format.
+
+=item B<-noverify>
+
+Don't attempt to verify the OCSP response signature or the nonce
+values. This option will normally only be used for debugging since it
+disables all verification of the responders certificate.
+
+=item B<-no_intern>
+
+Ignore certificates contained in the OCSP response when searching for the
+signers certificate. With this option the signers certificate must be specified
+with either the B<-verify_other> or B<-VAfile> options.
+
+=item B<-no_signature_verify>
+
+Don't check the signature on the OCSP response. Since this option
+tolerates invalid signatures on OCSP responses it will normally only be
+used for testing purposes.
+
+=item B<-no_cert_verify>
+
+Don't verify the OCSP response signers certificate at all. Since this
+option allows the OCSP response to be signed by any certificate it should
+only be used for testing purposes.
+
+=item B<-no_chain>
+
+Do not use certificates in the response as additional untrusted CA
+certificates.
+
+=item B<-no_explicit>
+
+Do not explicitly trust the root CA if it is set to be trusted for OCSP signing.
+
+=item B<-no_cert_checks>
+
+Don't perform any additional checks on the OCSP response signers certificate.
+That is do not make any checks to see if the signers certificate is authorised
+to provide the necessary status information: as a result this option should
+only be used for testing purposes.
+
+=item B<-validity_period> I<nsec>, B<-status_age> I<age>
+
+These options specify the range of times, in seconds, which will be tolerated
+in an OCSP response. Each certificate status response includes a B<notBefore>
+time and an optional B<notAfter> time. The current time should fall between
+these two values, but the interval between the two times may be only a few
+seconds. In practice the OCSP responder and clients clocks may not be precisely
+synchronised and so such a check may fail. To avoid this the
+B<-validity_period> option can be used to specify an acceptable error range in
+seconds, the default value is 5 minutes.
+
+If the B<notAfter> time is omitted from a response then this means that new
+status information is immediately available. In this case the age of the
+B<notBefore> field is checked to see it is not older than I<age> seconds old.
+By default this additional check is not performed.
+
+=item B<-rcid> I<digest>
+
+This option sets the digest algorithm to use for certificate identification
+in the OCSP response. Any digest supported by the L<openssl-dgst(1)> command can
+be used. The default is the same digest algorithm used in the request.
+
+=item B<-I<digest>>
+
+This option sets digest algorithm to use for certificate identification in the
+OCSP request. Any digest supported by the OpenSSL B<dgst> command can be used.
+The default is SHA-1. This option may be used multiple times to specify the
+digest used by subsequent certificate identifiers.
+
+{- $OpenSSL::safe::opt_trust_item -}
+
+{- $OpenSSL::safe::opt_v_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head2 OCSP Server Options
+
+=over 4
+
+=item B<-index> I<indexfile>
+
+The I<indexfile> parameter is the name of a text index file in B<ca>
+format containing certificate revocation information.
+
+If the B<-index> option is specified then this command switches to
+responder mode, otherwise it is in client mode. The request(s) the responder
+processes can be either specified on the command line (using B<-issuer>
+and B<-serial> options), supplied in a file (using the B<-reqin> option)
+or via external OCSP clients (if B<-port> or B<-url> is specified).
+
+If the B<-index> option is present then the B<-CA> and B<-rsigner> options
+must also be present.
+
+=item B<-CA> I<file>
+
+CA certificate corresponding to the revocation information in the index
+file given with B<-index>.
+The input can be in PEM, DER, or PKCS#12 format.
+
+=item B<-rsigner> I<file>
+
+The certificate to sign OCSP responses with.
+
+=item B<-rkey> I<file>
+
+The private key to sign OCSP responses with: if not present the file
+specified in the B<-rsigner> option is used.
+
+=item B<-passin> I<arg>
+
+The private key password source. For more information about the format of I<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-rother> I<file>
+
+Additional certificates to include in the OCSP response.
+The input can be in PEM, DER, or PKCS#12 format.
+
+=item B<-rsigopt> I<nm>:I<v>
+
+Pass options to the signature algorithm when signing OCSP responses.
+Names and values of these options are algorithm-specific.
+
+=item B<-rmd> I<digest>
+
+The digest to use when signing the response.
+
+=item B<-badsig>
+
+Corrupt the response signature before writing it; this can be useful
+for testing.
+
+=item B<-resp_no_certs>
+
+Don't include any certificates in the OCSP response.
+
+=item B<-resp_key_id>
+
+Identify the signer certificate using the key ID, default is to use the
+subject name.
+
+=item B<-port> I<portnum>
+
+Port to listen for OCSP requests on. The port may also be specified
+using the B<url> option.
+A C<0> argument indicates that any available port shall be chosen automatically.
+
+=item B<-ignore_err>
+
+Ignore malformed requests or responses: When acting as an OCSP client, retry if
+a malformed response is received. When acting as an OCSP responder, continue
+running instead of terminating upon receiving a malformed request.
+
+=item B<-nrequest> I<number>
+
+The OCSP server will exit after receiving I<number> requests, default unlimited.
+
+=item B<-multi> I<process-count>
+
+Run the specified number of OCSP responder child processes, with the parent
+process respawning child processes as needed.
+Child processes will detect changes in the CA index file and automatically
+reload it.
+When running as a responder B<-timeout> option is recommended to limit the time
+each child is willing to wait for the client's OCSP response.
+This option is available on POSIX systems (that support the fork() and other
+required unix system-calls).
+
+=item B<-nmin> I<minutes>, B<-ndays> I<days>
+
+Number of minutes or days when fresh revocation information is available:
+used in the B<nextUpdate> field. If neither option is present then the
+B<nextUpdate> field is omitted meaning fresh revocation information is
+immediately available.
+
+=back
+
+=head1 OCSP RESPONSE VERIFICATION
+
+OCSP Response follows the rules specified in RFC2560.
+
+Initially the OCSP responder certificate is located and the signature on
+the OCSP request checked using the responder certificate's public key.
+
+Then a normal certificate verify is performed on the OCSP responder certificate
+building up a certificate chain in the process. The locations of the trusted
+certificates used to build the chain can be specified by the B<-CAfile>,
+B<-CApath> or B<-CAstore> options or they will be looked for in the
+standard OpenSSL certificates directory.
+
+If the initial verify fails then the OCSP verify process halts with an
+error.
+
+Otherwise the issuing CA certificate in the request is compared to the OCSP
+responder certificate: if there is a match then the OCSP verify succeeds.
+
+Otherwise the OCSP responder certificate's CA is checked against the issuing
+CA certificate in the request. If there is a match and the OCSPSigning
+extended key usage is present in the OCSP responder certificate then the
+OCSP verify succeeds.
+
+Otherwise, if B<-no_explicit> is B<not> set the root CA of the OCSP responders
+CA is checked to see if it is trusted for OCSP signing. If it is the OCSP
+verify succeeds.
+
+If none of these checks is successful then the OCSP verify fails.
+
+What this effectively means if that if the OCSP responder certificate is
+authorised directly by the CA it is issuing revocation information about
+(and it is correctly configured) then verification will succeed.
+
+If the OCSP responder is a "global responder" which can give details about
+multiple CAs and has its own separate certificate chain then its root
+CA can be trusted for OCSP signing. For example:
+
+ openssl x509 -in ocspCA.pem -addtrust OCSPSigning -out trustedCA.pem
+
+Alternatively the responder certificate itself can be explicitly trusted
+with the B<-VAfile> option.
+
+=head1 NOTES
+
+As noted, most of the verify options are for testing or debugging purposes.
+Normally only the B<-CApath>, B<-CAfile>, B<-CAstore> and (if the responder
+is a 'global VA') B<-VAfile> options need to be used.
+
+The OCSP server is only useful for test and demonstration purposes: it is
+not really usable as a full OCSP responder. It contains only a very
+simple HTTP request handling and can only handle the POST form of OCSP
+queries. It also handles requests serially meaning it cannot respond to
+new requests until it has processed the current one. The text index file
+format of revocation is also inefficient for large quantities of revocation
+data.
+
+It is possible to run this command in responder mode via a CGI
+script using the B<-reqin> and B<-respout> options.
+
+=head1 EXAMPLES
+
+Create an OCSP request and write it to a file:
+
+ openssl ocsp -issuer issuer.pem -cert c1.pem -cert c2.pem -reqout req.der
+
+Send a query to an OCSP responder with URL http://ocsp.myhost.com/ save the
+response to a file, print it out in text form, and verify the response:
+
+ openssl ocsp -issuer issuer.pem -cert c1.pem -cert c2.pem \
+ -url http://ocsp.myhost.com/ -resp_text -respout resp.der
+
+Read in an OCSP response and print out text form:
+
+ openssl ocsp -respin resp.der -text -noverify
+
+OCSP server on port 8888 using a standard B<ca> configuration, and a separate
+responder certificate. All requests and responses are printed to a file.
+
+ openssl ocsp -index demoCA/index.txt -port 8888 -rsigner rcert.pem -CA demoCA/cacert.pem
+ -text -out log.txt
+
+As above but exit after processing one request:
+
+ openssl ocsp -index demoCA/index.txt -port 8888 -rsigner rcert.pem -CA demoCA/cacert.pem
+ -nrequest 1
+
+Query status information using an internally generated request:
+
+ openssl ocsp -index demoCA/index.txt -rsigner rcert.pem -CA demoCA/cacert.pem
+ -issuer demoCA/cacert.pem -serial 1
+
+Query status information using request read from a file, and write the response
+to a second file.
+
+ openssl ocsp -index demoCA/index.txt -rsigner rcert.pem -CA demoCA/cacert.pem
+ -reqin req.der -respout resp.der
+
+=head1 HISTORY
+
+The -no_alt_chains option was added in OpenSSL 1.1.0.
+
+=head1 COPYRIGHT
+
+Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-passphrase-options.pod b/doc/man1/openssl-passphrase-options.pod
new file mode 100644
index 000000000000..abc43fb41e6f
--- /dev/null
+++ b/doc/man1/openssl-passphrase-options.pod
@@ -0,0 +1,75 @@
+=pod
+
+=head1 NAME
+
+openssl-passphrase-options - Pass phrase options
+
+=head1 SYNOPSIS
+
+B<openssl>
+I<command>
+[ I<options> ... ]
+[ I<parameters> ... ]
+
+=head1 DESCRIPTION
+
+Several OpenSSL commands accept password arguments, typically using B<-passin>
+and B<-passout> for input and output passwords respectively. These allow
+the password to be obtained from a variety of sources. Both of these
+options take a single argument whose format is described below. If no
+password argument is given and a password is required then the user is
+prompted to enter one: this will typically be read from the current
+terminal with echoing turned off.
+
+Note that character encoding may be relevant, please see
+L<passphrase-encoding(7)>.
+
+=head1 OPTIONS
+
+=head2 Pass Phrase Option Arguments
+
+Pass phrase arguments can be formatted as follows.
+
+=over 4
+
+=item B<pass:>I<password>
+
+The actual password is I<password>. Since the password is visible
+to utilities (like 'ps' under Unix) this form should only be used
+where security is not important.
+
+=item B<env:>I<var>
+
+Obtain the password from the environment variable I<var>. Since
+the environment of other processes is visible on certain platforms
+(e.g. ps under certain Unix OSes) this option should be used with caution.
+
+=item B<file:>I<pathname>
+
+The first line of I<pathname> is the password. If the same I<pathname>
+argument is supplied to B<-passin> and B<-passout> arguments then the first
+line will be used for the input password and the next line for the output
+password. I<pathname> need not refer to a regular file: it could for example
+refer to a device or named pipe.
+
+=item B<fd:>I<number>
+
+Read the password from the file descriptor I<number>. This can be used to
+send the data via a pipe for example.
+
+=item B<stdin>
+
+Read the password from standard input.
+
+=back
+
+=head1 COPYRIGHT
+
+Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-passwd.pod.in b/doc/man1/openssl-passwd.pod.in
new file mode 100644
index 000000000000..314fe4fe7248
--- /dev/null
+++ b/doc/man1/openssl-passwd.pod.in
@@ -0,0 +1,122 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-passwd - compute password hashes
+
+=head1 SYNOPSIS
+
+B<openssl passwd>
+[B<-help>]
+[B<-1>]
+[B<-apr1>]
+[B<-aixmd5>]
+[B<-5>]
+[B<-6>]
+[B<-salt> I<string>]
+[B<-in> I<file>]
+[B<-stdin>]
+[B<-noverify>]
+[B<-quiet>]
+[B<-table>]
+[B<-reverse>]
+{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+[I<password>]
+
+=head1 DESCRIPTION
+
+This command computes the hash of a password typed at
+run-time or the hash of each password in a list. The password list is
+taken from the named file for option B<-in>, from stdin for
+option B<-stdin>, or from the command line, or from the terminal otherwise.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-1>
+
+Use the MD5 based BSD password algorithm B<1> (default).
+
+=item B<-apr1>
+
+Use the B<apr1> algorithm (Apache variant of the BSD algorithm).
+
+=item B<-aixmd5>
+
+Use the B<AIX MD5> algorithm (AIX variant of the BSD algorithm).
+
+=item B<-5>
+
+=item B<-6>
+
+Use the B<SHA256> / B<SHA512> based algorithms defined by Ulrich Drepper.
+See L<https://www.akkadia.org/drepper/SHA-crypt.txt>.
+
+=item B<-salt> I<string>
+
+Use the specified salt.
+When reading a password from the terminal, this implies B<-noverify>.
+
+=item B<-in> I<file>
+
+Read passwords from I<file>.
+
+=item B<-stdin>
+
+Read passwords from B<stdin>.
+
+=item B<-noverify>
+
+Don't verify when reading a password from the terminal.
+
+=item B<-quiet>
+
+Don't output warnings when passwords given at the command line are truncated.
+
+=item B<-table>
+
+In the output list, prepend the cleartext password and a TAB character
+to each password hash.
+
+=item B<-reverse>
+
+When the B<-table> option is used, reverse the order of cleartext and hash.
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 EXAMPLES
+
+ % openssl passwd -1 -salt xxxxxxxx password
+ $1$xxxxxxxx$UYCIxa628.9qXjpQCjM4a.
+
+ % openssl passwd -apr1 -salt xxxxxxxx password
+ $apr1$xxxxxxxx$dxHfLAsjHkDRmG83UXe8K0
+
+ % openssl passwd -aixmd5 -salt xxxxxxxx password
+ xxxxxxxx$8Oaipk/GPKhC64w/YVeFD/
+
+=head1 HISTORY
+
+The B<-crypt> option was removed in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-pkcs12.pod.in b/doc/man1/openssl-pkcs12.pod.in
new file mode 100644
index 000000000000..929bf60fd2c8
--- /dev/null
+++ b/doc/man1/openssl-pkcs12.pod.in
@@ -0,0 +1,470 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-pkcs12 - PKCS#12 file command
+
+=head1 SYNOPSIS
+
+B<openssl> B<pkcs12>
+[B<-help>]
+[B<-passin> I<arg>]
+[B<-passout> I<arg>]
+[B<-password> I<arg>]
+[B<-twopass>]
+[B<-in> I<filename>|I<uri>]
+[B<-out> I<filename>]
+[B<-nokeys>]
+[B<-nocerts>]
+[B<-noout>]
+[B<-legacy>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+{- $OpenSSL::safe::opt_r_synopsis -}
+
+PKCS#12 input (parsing) options:
+[B<-info>]
+[B<-nomacver>]
+[B<-clcerts>]
+[B<-cacerts>]
+
+[B<-aes128>]
+[B<-aes192>]
+[B<-aes256>]
+[B<-aria128>]
+[B<-aria192>]
+[B<-aria256>]
+[B<-camellia128>]
+[B<-camellia192>]
+[B<-camellia256>]
+[B<-des>]
+[B<-des3>]
+[B<-idea>]
+[B<-noenc>]
+[B<-nodes>]
+
+PKCS#12 output (export) options:
+
+[B<-export>]
+[B<-inkey> I<filename>|I<uri>]
+[B<-certfile> I<filename>]
+[B<-passcerts> I<arg>]
+[B<-chain>]
+[B<-untrusted> I<filename>]
+{- $OpenSSL::safe::opt_trust_synopsis -}
+[B<-name> I<name>]
+[B<-caname> I<name>]
+[B<-CSP> I<name>]
+[B<-LMK>]
+[B<-keyex>]
+[B<-keysig>]
+[B<-keypbe> I<cipher>]
+[B<-certpbe> I<cipher>]
+[B<-descert>]
+[B<-macalg> I<digest>]
+[B<-iter> I<count>]
+[B<-noiter>]
+[B<-nomaciter>]
+[B<-maciter>]
+[B<-nomac>]
+
+=head1 DESCRIPTION
+
+This command allows PKCS#12 files (sometimes referred to as
+PFX files) to be created and parsed. PKCS#12 files are used by several
+programs including Netscape, MSIE and MS Outlook.
+
+=head1 OPTIONS
+
+There are a lot of options the meaning of some depends of whether a PKCS#12 file
+is being created or parsed. By default a PKCS#12 file is parsed.
+A PKCS#12 file can be created by using the B<-export> option (see below).
+The PKCS#12 export encryption and MAC options such as B<-certpbe> and B<-iter>
+and many further options such as B<-chain> are relevant only with B<-export>.
+Conversely, the options regarding encryption of private keys when outputting
+PKCS#12 input are relevant only when the B<-export> option is not given.
+
+The default encryption algorithm is AES-256-CBC with PBKDF2 for key derivation.
+
+When encountering problems loading legacy PKCS#12 files that involve,
+for example, RC2-40-CBC,
+try using the B<-legacy> option and, if needed, the B<-provider-path> option.
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-passin> I<arg>
+
+The password source for the input, and for encrypting any private keys that
+are output.
+For more information about the format of B<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-passout> I<arg>
+
+The password source for output files.
+
+=item B<-password> I<arg>
+
+With B<-export>, B<-password> is equivalent to B<-passout>,
+otherwise it is equivalent to B<-passin>.
+
+=item B<-twopass>
+
+Prompt for separate integrity and encryption passwords: most software
+always assumes these are the same so this option will render such
+PKCS#12 files unreadable. Cannot be used in combination with the options
+B<-password>, B<-passin> if importing from PKCS#12, or B<-passout> if exporting.
+
+=item B<-nokeys>
+
+No private keys will be output.
+
+=item B<-nocerts>
+
+No certificates will be output.
+
+=item B<-noout>
+
+This option inhibits all credentials output,
+and so the input is just verified.
+
+=item B<-legacy>
+
+Use legacy mode of operation and automatically load the legacy provider.
+If OpenSSL is not installed system-wide,
+it is necessary to also use, for example, C<-provider-path ./providers>
+or to set the environment variable B<OPENSSL_MODULES>
+to point to the directory where the providers can be found.
+
+In the legacy mode, the default algorithm for certificate encryption
+is RC2_CBC or 3DES_CBC depending on whether the RC2 cipher is enabled
+in the build. The default algorithm for private key encryption is 3DES_CBC.
+If the legacy option is not specified, then the legacy provider is not loaded
+and the default encryption algorithm for both certificates and private keys is
+AES_256_CBC with PBKDF2 for key derivation.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+{- $OpenSSL::safe::opt_r_item -}
+
+=back
+
+=head2 PKCS#12 input (parsing) options
+
+=over 4
+
+=item B<-in> I<filename>|I<uri>
+
+This specifies the input filename or URI.
+Standard input is used by default.
+Without the B<-export> option this must be PKCS#12 file to be parsed.
+For use with the B<-export> option
+see the L</PKCS#12 output (export) options> section.
+
+=item B<-out> I<filename>
+
+The filename to write certificates and private keys to, standard output by
+default. They are all written in PEM format.
+
+=item B<-info>
+
+Output additional information about the PKCS#12 file structure, algorithms
+used and iteration counts.
+
+=item B<-nomacver>
+
+Don't attempt to verify the integrity MAC.
+
+=item B<-clcerts>
+
+Only output client certificates (not CA certificates).
+
+=item B<-cacerts>
+
+Only output CA certificates (not client certificates).
+
+=item B<-aes128>, B<-aes192>, B<-aes256>
+
+Use AES to encrypt private keys before outputting.
+
+=item B<-aria128>, B<-aria192>, B<-aria256>
+
+Use ARIA to encrypt private keys before outputting.
+
+=item B<-camellia128>, B<-camellia192>, B<-camellia256>
+
+Use Camellia to encrypt private keys before outputting.
+
+=item B<-des>
+
+Use DES to encrypt private keys before outputting.
+
+=item B<-des3>
+
+Use triple DES to encrypt private keys before outputting.
+
+=item B<-idea>
+
+Use IDEA to encrypt private keys before outputting.
+
+=item B<-noenc>
+
+Don't encrypt private keys at all.
+
+=item B<-nodes>
+
+This option is deprecated since OpenSSL 3.0; use B<-noenc> instead.
+
+=back
+
+=head2 PKCS#12 output (export) options
+
+=over 4
+
+=item B<-export>
+
+This option specifies that a PKCS#12 file will be created rather than
+parsed.
+
+=item B<-out> I<filename>
+
+This specifies filename to write the PKCS#12 file to. Standard output is used
+by default.
+
+=item B<-in> I<filename>|I<uri>
+
+This specifies the input filename or URI.
+Standard input is used by default.
+With the B<-export> option this is a file with certificates and a key,
+or a URI that refers to a key accessed via an engine.
+The order of credentials in a file doesn't matter but one private key and
+its corresponding certificate should be present. If additional
+certificates are present they will also be included in the PKCS#12 output file.
+
+=item B<-inkey> I<filename>|I<uri>
+
+The private key input for PKCS12 output.
+If this option is not specified then the input file (B<-in> argument) must
+contain a private key.
+If no engine is used, the argument is taken as a file.
+If the B<-engine> option is used or the URI has prefix C<org.openssl.engine:>
+then the rest of the URI is taken as key identifier for the given engine.
+
+=item B<-certfile> I<filename>
+
+An input file with extra certificates to be added to the PKCS#12 output
+if the B<-export> option is given.
+
+=item B<-passcerts> I<arg>
+
+The password source for certificate input such as B<-certfile>
+and B<-untrusted>.
+For more information about the format of B<arg> see
+L<openssl-passphrase-options(1)>.
+
+=item B<-chain>
+
+If this option is present then the certificate chain of the end entity
+certificate is built and included in the PKCS#12 output file.
+The end entity certificate is the first one read from the B<-in> file
+if no key is given, else the first certificate matching the given key.
+The standard CA trust store is used for chain building,
+as well as any untrusted CA certificates given with the B<-untrusted> option.
+
+=item B<-untrusted> I<filename>
+
+An input file of untrusted certificates that may be used
+for chain building, which is relevant only when a PKCS#12 file is created
+with the B<-export> option and the B<-chain> option is given as well.
+Any certificates that are actually part of the chain are added to the output.
+
+{- $OpenSSL::safe::opt_trust_item -}
+
+=item B<-name> I<friendlyname>
+
+This specifies the "friendly name" for the certificates and private key. This
+name is typically displayed in list boxes by software importing the file.
+
+=item B<-caname> I<friendlyname>
+
+This specifies the "friendly name" for other certificates. This option may be
+used multiple times to specify names for all certificates in the order they
+appear. Netscape ignores friendly names on other certificates whereas MSIE
+displays them.
+
+=item B<-CSP> I<name>
+
+Write I<name> as a Microsoft CSP name.
+The password source for the input, and for encrypting any private keys that
+are output.
+For more information about the format of B<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-LMK>
+
+Add the "Local Key Set" identifier to the attributes.
+
+=item B<-keyex>|B<-keysig>
+
+Specifies that the private key is to be used for key exchange or just signing.
+This option is only interpreted by MSIE and similar MS software. Normally
+"export grade" software will only allow 512 bit RSA keys to be used for
+encryption purposes but arbitrary length keys for signing. The B<-keysig>
+option marks the key for signing only. Signing only keys can be used for
+S/MIME signing, authenticode (ActiveX control signing) and SSL client
+authentication, however, due to a bug only MSIE 5.0 and later support
+the use of signing only keys for SSL client authentication.
+
+=item B<-keypbe> I<alg>, B<-certpbe> I<alg>
+
+These options allow the algorithm used to encrypt the private key and
+certificates to be selected. Any PKCS#5 v1.5 or PKCS#12 PBE algorithm name
+can be used (see L</NOTES> section for more information). If a cipher name
+(as output by C<openssl list -cipher-algorithms>) is specified then it
+is used with PKCS#5 v2.0. For interoperability reasons it is advisable to only
+use PKCS#12 algorithms.
+
+Special value C<NONE> disables encryption of the private key and certificates.
+
+=item B<-descert>
+
+Encrypt the certificates using triple DES. By default the private
+key and the certificates are encrypted using AES-256-CBC unless
+the '-legacy' option is used. If '-descert' is used with the '-legacy'
+then both, the private key and the certificates are encrypted using triple DES.
+
+=item B<-macalg> I<digest>
+
+Specify the MAC digest algorithm. If not included SHA256 will be used.
+
+=item B<-iter> I<count>
+
+This option specifies the iteration count for the encryption key and MAC. The
+default value is 2048.
+
+To discourage attacks by using large dictionaries of common passwords the
+algorithm that derives keys from passwords can have an iteration count applied
+to it: this causes a certain part of the algorithm to be repeated and slows it
+down. The MAC is used to check the file integrity but since it will normally
+have the same password as the keys and certificates it could also be attacked.
+
+=item B<-noiter>, B<-nomaciter>
+
+By default both encryption and MAC iteration counts are set to 2048, using
+these options the MAC and encryption iteration counts can be set to 1, since
+this reduces the file security you should not use these options unless you
+really have to. Most software supports both MAC and encryption iteration counts.
+MSIE 4.0 doesn't support MAC iteration counts so it needs the B<-nomaciter>
+option.
+
+=item B<-maciter>
+
+This option is included for compatibility with previous versions, it used
+to be needed to use MAC iterations counts but they are now used by default.
+
+=item B<-nomac>
+
+Do not attempt to provide the MAC integrity. This can be useful with the FIPS
+provider as the PKCS12 MAC requires PKCS12KDF which is not an approved FIPS
+algorithm and cannot be supported by the FIPS provider.
+
+=back
+
+=head1 NOTES
+
+Although there are a large number of options most of them are very rarely
+used. For PKCS#12 file parsing only B<-in> and B<-out> need to be used
+for PKCS#12 file creation B<-export> and B<-name> are also used.
+
+If none of the B<-clcerts>, B<-cacerts> or B<-nocerts> options are present
+then all certificates will be output in the order they appear in the input
+PKCS#12 files. There is no guarantee that the first certificate present is
+the one corresponding to the private key.
+Certain software which tries to get a private key and the corresponding
+certificate might assume that the first certificate in the file is the one
+corresponding to the private key, but that may not always be the case.
+Using the B<-clcerts> option will solve this problem by only
+outputting the certificate corresponding to the private key. If the CA
+certificates are required then they can be output to a separate file using
+the B<-nokeys> B<-cacerts> options to just output CA certificates.
+
+The B<-keypbe> and B<-certpbe> algorithms allow the precise encryption
+algorithms for private keys and certificates to be specified. Normally
+the defaults are fine but occasionally software can't handle triple DES
+encrypted private keys, then the option B<-keypbe> I<PBE-SHA1-RC2-40> can
+be used to reduce the private key encryption to 40 bit RC2. A complete
+description of all algorithms is contained in L<openssl-pkcs8(1)>.
+
+Prior 1.1 release passwords containing non-ASCII characters were encoded
+in non-compliant manner, which limited interoperability, in first hand
+with Windows. But switching to standard-compliant password encoding
+poses problem accessing old data protected with broken encoding. For
+this reason even legacy encodings is attempted when reading the
+data. If you use PKCS#12 files in production application you are advised
+to convert the data, because implemented heuristic approach is not
+MT-safe, its sole goal is to facilitate the data upgrade with this
+command.
+
+=head1 EXAMPLES
+
+Parse a PKCS#12 file and output it to a PEM file:
+
+ openssl pkcs12 -in file.p12 -out file.pem
+
+Output only client certificates to a file:
+
+ openssl pkcs12 -in file.p12 -clcerts -out file.pem
+
+Don't encrypt the private key:
+
+ openssl pkcs12 -in file.p12 -out file.pem -noenc
+
+Print some info about a PKCS#12 file:
+
+ openssl pkcs12 -in file.p12 -info -noout
+
+Print some info about a PKCS#12 file in legacy mode:
+
+ openssl pkcs12 -in file.p12 -info -noout -legacy
+
+Create a PKCS#12 file from a PEM file that may contain a key and certificates:
+
+ openssl pkcs12 -export -in file.pem -out file.p12 -name "My PSE"
+
+Include some extra certificates:
+
+ openssl pkcs12 -export -in file.pem -out file.p12 -name "My PSE" \
+ -certfile othercerts.pem
+
+Export a PKCS#12 file with data from a certificate PEM file and from a further
+PEM file containing a key, with default algorithms as in the legacy provider:
+
+ openssl pkcs12 -export -in cert.pem -inkey key.pem -out file.p12 -legacy
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-pkcs8(1)>,
+L<ossl_store-file(7)>
+
+=head1 HISTORY
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+The B<-nodes> option was deprecated in OpenSSL 3.0, too; use B<-noenc> instead.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-pkcs7.pod.in b/doc/man1/openssl-pkcs7.pod.in
new file mode 100644
index 000000000000..efd772d1d438
--- /dev/null
+++ b/doc/man1/openssl-pkcs7.pod.in
@@ -0,0 +1,110 @@
+=pod
+
+=begin comment
+{- join("\n", @autowarntext) -}
+
+=end comment
+
+=head1 NAME
+
+openssl-pkcs7 - PKCS#7 command
+
+=head1 SYNOPSIS
+
+B<openssl> B<pkcs7>
+[B<-help>]
+[B<-inform> B<DER>|B<PEM>]
+[B<-outform> B<DER>|B<PEM>]
+[B<-in> I<filename>]
+[B<-out> I<filename>]
+[B<-print>]
+[B<-print_certs>]
+[B<-text>]
+[B<-noout>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command processes PKCS#7 files. Note that it only understands PKCS#7
+v 1.5 as specified in IETF RFC 2315. It cannot currently parse CMS as
+described in IETF RFC 2630.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-inform> B<DER>|B<PEM>, B<-outform> B<DER>|B<PEM>
+
+The input and formats; the default is B<PEM>.
+See L<openssl-format-options(1)> for details.
+
+The data is a PKCS#7 Version 1.5 structure.
+
+=item B<-in> I<filename>
+
+This specifies the input filename to read from or standard input if this
+option is not specified.
+
+=item B<-out> I<filename>
+
+Specifies the output filename to write to or standard output by
+default.
+
+=item B<-print>
+
+Print out the full PKCS7 object.
+
+=item B<-print_certs>
+
+Prints out any certificates or CRLs contained in the file. They are
+preceded by their subject and issuer names in one line format.
+
+=item B<-text>
+
+Prints out certificate details in full rather than just subject and
+issuer names.
+
+=item B<-noout>
+
+Don't output the encoded version of the PKCS#7 structure (or certificates
+if B<-print_certs> is set).
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 EXAMPLES
+
+Convert a PKCS#7 file from PEM to DER:
+
+ openssl pkcs7 -in file.pem -outform DER -out file.der
+
+Output all certificates in a file:
+
+ openssl pkcs7 -in file.pem -print_certs -out certs.pem
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-crl2pkcs7(1)>
+
+=head1 HISTORY
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-pkcs8.pod.in b/doc/man1/openssl-pkcs8.pod.in
new file mode 100644
index 000000000000..2af61203e9a7
--- /dev/null
+++ b/doc/man1/openssl-pkcs8.pod.in
@@ -0,0 +1,288 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-pkcs8 - PKCS#8 format private key conversion command
+
+=head1 SYNOPSIS
+
+B<openssl> B<pkcs8>
+[B<-help>]
+[B<-topk8>]
+[B<-inform> B<DER>|B<PEM>]
+[B<-outform> B<DER>|B<PEM>]
+[B<-in> I<filename>]
+[B<-passin> I<arg>]
+[B<-out> I<filename>]
+[B<-passout> I<arg>]
+[B<-iter> I<count>]
+[B<-noiter>]
+[B<-nocrypt>]
+[B<-traditional>]
+[B<-v2> I<alg>]
+[B<-v2prf> I<alg>]
+[B<-v1> I<alg>]
+[B<-scrypt>]
+[B<-scrypt_N> I<N>]
+[B<-scrypt_r> I<r>]
+[B<-scrypt_p> I<p>]
+{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command processes private keys in PKCS#8 format. It can handle
+both unencrypted PKCS#8 PrivateKeyInfo format and EncryptedPrivateKeyInfo
+format with a variety of PKCS#5 (v1.5 and v2.0) and PKCS#12 algorithms.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-topk8>
+
+Normally a PKCS#8 private key is expected on input and a private key will be
+written to the output file. With the B<-topk8> option the situation is
+reversed: it reads a private key and writes a PKCS#8 format key.
+
+=item B<-inform> B<DER>|B<PEM>, B<-outform> B<DER>|B<PEM>
+
+The input and formats; the default is B<PEM>.
+See L<openssl-format-options(1)> for details.
+
+If a key is being converted from PKCS#8 form (i.e. the B<-topk8> option is
+not used) then the input file must be in PKCS#8 format. An encrypted
+key is expected unless B<-nocrypt> is included.
+
+If B<-topk8> is not used and B<PEM> mode is set the output file will be an
+unencrypted private key in PKCS#8 format. If the B<-traditional> option is
+used then a traditional format private key is written instead.
+
+If B<-topk8> is not used and B<DER> mode is set the output file will be an
+unencrypted private key in traditional DER format.
+
+If B<-topk8> is used then any supported private key can be used for the input
+file in a format specified by B<-inform>. The output file will be encrypted
+PKCS#8 format using the specified encryption parameters unless B<-nocrypt>
+is included.
+
+=item B<-traditional>
+
+When this option is present and B<-topk8> is not a traditional format private
+key is written.
+
+=item B<-in> I<filename>
+
+This specifies the input filename to read a key from or standard input if this
+option is not specified. If the key is encrypted a pass phrase will be
+prompted for.
+
+=item B<-passin> I<arg>, B<-passout> I<arg>
+
+The password source for the input and output file.
+For more information about the format of B<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-out> I<filename>
+
+This specifies the output filename to write a key to or standard output by
+default. If any encryption options are set then a pass phrase will be
+prompted for. The output filename should B<not> be the same as the input
+filename.
+
+=item B<-iter> I<count>
+
+When creating new PKCS#8 containers, use a given number of iterations on
+the password in deriving the encryption key for the PKCS#8 output.
+High values increase the time required to brute-force a PKCS#8 container.
+
+=item B<-noiter>
+
+When creating new PKCS#8 containers, use 1 as iteration count.
+
+=item B<-nocrypt>
+
+PKCS#8 keys generated or input are normally PKCS#8 EncryptedPrivateKeyInfo
+structures using an appropriate password based encryption algorithm. With
+this option an unencrypted PrivateKeyInfo structure is expected or output.
+This option does not encrypt private keys at all and should only be used
+when absolutely necessary. Certain software such as some versions of Java
+code signing software used unencrypted private keys.
+
+=item B<-v2> I<alg>
+
+This option sets the PKCS#5 v2.0 algorithm.
+
+The I<alg> argument is the encryption algorithm to use, valid values include
+B<aes128>, B<aes256> and B<des3>. If this option isn't specified then B<aes256>
+is used.
+
+=item B<-v2prf> I<alg>
+
+This option sets the PRF algorithm to use with PKCS#5 v2.0. A typical value
+value would be B<hmacWithSHA256>. If this option isn't set then the default
+for the cipher is used or B<hmacWithSHA256> if there is no default.
+
+Some implementations may not support custom PRF algorithms and may require
+the B<hmacWithSHA1> option to work.
+
+=item B<-v1> I<alg>
+
+This option indicates a PKCS#5 v1.5 or PKCS#12 algorithm should be used. Some
+older implementations may not support PKCS#5 v2.0 and may require this option.
+If not specified PKCS#5 v2.0 form is used.
+
+=item B<-scrypt>
+
+Uses the B<scrypt> algorithm for private key encryption using default
+parameters: currently N=16384, r=8 and p=1 and AES in CBC mode with a 256 bit
+key. These parameters can be modified using the B<-scrypt_N>, B<-scrypt_r>,
+B<-scrypt_p> and B<-v2> options.
+
+=item B<-scrypt_N> I<N>, B<-scrypt_r> I<r>, B<-scrypt_p> I<p>
+
+Sets the scrypt I<N>, I<r> or I<p> parameters.
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 NOTES
+
+By default, when converting a key to PKCS#8 format, PKCS#5 v2.0 using 256 bit
+AES with HMAC and SHA256 is used.
+
+Some older implementations do not support PKCS#5 v2.0 format and require
+the older PKCS#5 v1.5 form instead, possibly also requiring insecure weak
+encryption algorithms such as 56 bit DES.
+
+Private keys encrypted using PKCS#5 v2.0 algorithms and high iteration
+counts are more secure that those encrypted using the traditional
+SSLeay compatible formats. So if additional security is considered
+important the keys should be converted.
+
+It is possible to write out DER encoded encrypted private keys in
+PKCS#8 format because the encryption details are included at an ASN1
+level whereas the traditional format includes them at a PEM level.
+
+=head1 PKCS#5 V1.5 AND PKCS#12 ALGORITHMS
+
+Various algorithms can be used with the B<-v1> command line option,
+including PKCS#5 v1.5 and PKCS#12. These are described in more detail
+below.
+
+=over 4
+
+=item B<PBE-MD2-DES PBE-MD5-DES>
+
+These algorithms were included in the original PKCS#5 v1.5 specification.
+They only offer 56 bits of protection since they both use DES.
+
+=item B<PBE-SHA1-RC2-64>, B<PBE-MD2-RC2-64>, B<PBE-MD5-RC2-64>, B<PBE-SHA1-DES>
+
+These algorithms are not mentioned in the original PKCS#5 v1.5 specification
+but they use the same key derivation algorithm and are supported by some
+software. They are mentioned in PKCS#5 v2.0. They use either 64 bit RC2 or
+56 bit DES.
+
+=item B<PBE-SHA1-RC4-128>, B<PBE-SHA1-RC4-40>, B<PBE-SHA1-3DES>, B<PBE-SHA1-2DES>, B<PBE-SHA1-RC2-128>, B<PBE-SHA1-RC2-40>
+
+These algorithms use the PKCS#12 password based encryption algorithm and
+allow strong encryption algorithms like triple DES or 128 bit RC2 to be used.
+
+=back
+
+=head1 EXAMPLES
+
+Convert a private key to PKCS#8 format using default parameters (AES with
+256 bit key and B<hmacWithSHA256>):
+
+ openssl pkcs8 -in key.pem -topk8 -out enckey.pem
+
+Convert a private key to PKCS#8 unencrypted format:
+
+ openssl pkcs8 -in key.pem -topk8 -nocrypt -out enckey.pem
+
+Convert a private key to PKCS#5 v2.0 format using triple DES:
+
+ openssl pkcs8 -in key.pem -topk8 -v2 des3 -out enckey.pem
+
+Convert a private key to PKCS#5 v2.0 format using AES with 256 bits in CBC
+mode and B<hmacWithSHA512> PRF:
+
+ openssl pkcs8 -in key.pem -topk8 -v2 aes-256-cbc -v2prf hmacWithSHA512 -out enckey.pem
+
+Convert a private key to PKCS#8 using a PKCS#5 1.5 compatible algorithm
+(DES):
+
+ openssl pkcs8 -in key.pem -topk8 -v1 PBE-MD5-DES -out enckey.pem
+
+Convert a private key to PKCS#8 using a PKCS#12 compatible algorithm
+(3DES):
+
+ openssl pkcs8 -in key.pem -topk8 -out enckey.pem -v1 PBE-SHA1-3DES
+
+Read a DER unencrypted PKCS#8 format private key:
+
+ openssl pkcs8 -inform DER -nocrypt -in key.der -out key.pem
+
+Convert a private key from any PKCS#8 encrypted format to traditional format:
+
+ openssl pkcs8 -in pk8.pem -traditional -out key.pem
+
+Convert a private key to PKCS#8 format, encrypting with AES-256 and with
+one million iterations of the password:
+
+ openssl pkcs8 -in key.pem -topk8 -v2 aes-256-cbc -iter 1000000 -out pk8.pem
+
+=head1 STANDARDS
+
+Test vectors from this PKCS#5 v2.0 implementation were posted to the
+pkcs-tng mailing list using triple DES, DES and RC2 with high iteration
+counts, several people confirmed that they could decrypt the private
+keys produced and therefore, it can be assumed that the PKCS#5 v2.0
+implementation is reasonably accurate at least as far as these
+algorithms are concerned.
+
+The format of PKCS#8 DSA (and other) private keys is not well documented:
+it is hidden away in PKCS#11 v2.01, section 11.9. OpenSSL's default DSA
+PKCS#8 private key format complies with this standard.
+
+=head1 BUGS
+
+There should be an option that prints out the encryption algorithm
+in use and other details such as the iteration count.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-dsa(1)>,
+L<openssl-rsa(1)>,
+L<openssl-genrsa(1)>,
+L<openssl-gendsa(1)>
+
+=head1 HISTORY
+
+The B<-iter> option was added in OpenSSL 1.1.0.
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-pkey.pod.in b/doc/man1/openssl-pkey.pod.in
new file mode 100644
index 000000000000..34d57f7d1422
--- /dev/null
+++ b/doc/man1/openssl-pkey.pod.in
@@ -0,0 +1,238 @@
+=pod
+
+=begin comment
+{- join("\n", @autowarntext) -}
+
+=end comment
+
+=head1 NAME
+
+openssl-pkey - public or private key processing command
+
+=head1 SYNOPSIS
+
+B<openssl> B<pkey>
+[B<-help>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+[B<-check>]
+[B<-pubcheck>]
+[B<-in> I<filename>|I<uri>]
+[B<-inform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-passin> I<arg>]
+[B<-pubin>]
+[B<-out> I<filename>]
+[B<-outform> B<DER>|B<PEM>]
+[B<-I<cipher>>]
+[B<-passout> I<arg>]
+[B<-traditional>]
+[B<-pubout>]
+[B<-noout>]
+[B<-text>]
+[B<-text_pub>]
+[B<-ec_conv_form> I<arg>]
+[B<-ec_param_enc> I<arg>]
+
+=head1 DESCRIPTION
+
+This command processes public or private keys. They can be
+converted between various forms and their components printed.
+
+=head1 OPTIONS
+
+=head2 General options
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=item B<-check>
+
+This option checks the consistency of a key pair for both public and private
+components.
+
+=item B<-pubcheck>
+
+This option checks the correctness of either a public key
+or the public component of a key pair.
+
+=back
+
+=head2 Input options
+
+=over 4
+
+=item B<-in> I<filename>|I<uri>
+
+This specifies the input to read a key from
+or standard input if this option is not specified.
+If the key input is encrypted and B<-passin> is not given
+a pass phrase will be prompted for.
+
+=item B<-inform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The key input format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-passin> I<arg>
+
+The password source for the key input.
+
+For more information about the format of B<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-pubin>
+
+By default a private key is read from the input.
+With this option only the public components are read.
+
+=back
+
+=head2 Output options
+
+=over 4
+
+=item B<-out> I<filename>
+
+This specifies the output filename to save the encoded and/or text output of key
+or standard output if this option is not specified.
+If any cipher option is set but no B<-passout> is given
+then a pass phrase will be prompted for.
+The output filename should B<not> be the same as the input filename.
+
+=item B<-outform> B<DER>|B<PEM>
+
+The key output format; the default is B<PEM>.
+See L<openssl-format-options(1)> for details.
+
+=item B<-I<cipher>>
+
+Encrypt the PEM encoded private key with the supplied cipher. Any algorithm
+name accepted by EVP_get_cipherbyname() is acceptable such as B<aes128>.
+Encryption is not supported for DER output.
+
+=item B<-passout> I<arg>
+
+The password source for the output file.
+
+For more information about the format of B<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-traditional>
+
+Normally a private key is written using standard format: this is PKCS#8 form
+with the appropriate encryption algorithm (if any). If the B<-traditional>
+option is specified then the older "traditional" format is used instead.
+
+=item B<-pubout>
+
+By default the private and public key is output;
+this option restricts the output to the public components.
+This option is automatically set if the input is a public key.
+
+When combined with B<-text>, this is equivalent to B<-text_pub>.
+
+=item B<-noout>
+
+Do not output the key in encoded form.
+
+=item B<-text>
+
+Output the various key components in plain text
+(possibly in addition to the PEM encoded form).
+This cannot be combined with encoded output in DER format.
+
+=item B<-text_pub>
+
+Output in text form only the public key components (also for private keys).
+This cannot be combined with encoded output in DER format.
+
+=item B<-ec_conv_form> I<arg>
+
+This option only applies to elliptic-curve based keys.
+
+This specifies how the points on the elliptic curve are converted
+into octet strings. Possible values are: B<compressed> (the default
+value), B<uncompressed> and B<hybrid>. For more information regarding
+the point conversion forms please read the X9.62 standard.
+B<Note> Due to patent issues the B<compressed> option is disabled
+by default for binary curves and can be enabled by defining
+the preprocessor macro B<OPENSSL_EC_BIN_PT_COMP> at compile time.
+
+=item B<-ec_param_enc> I<arg>
+
+This option only applies to elliptic curve based public and private keys.
+
+This specifies how the elliptic curve parameters are encoded.
+Possible value are: B<named_curve>, i.e. the ec parameters are
+specified by an OID, or B<explicit> where the ec parameters are
+explicitly given (see RFC 3279 for the definition of the
+EC parameters structures). The default value is B<named_curve>.
+B<Note> the B<implicitlyCA> alternative, as specified in RFC 3279,
+is currently not implemented in OpenSSL.
+
+=back
+
+=head1 EXAMPLES
+
+To remove the pass phrase on a private key:
+
+ openssl pkey -in key.pem -out keyout.pem
+
+To encrypt a private key using triple DES:
+
+ openssl pkey -in key.pem -des3 -out keyout.pem
+
+To convert a private key from PEM to DER format:
+
+ openssl pkey -in key.pem -outform DER -out keyout.der
+
+To print out the components of a private key to standard output:
+
+ openssl pkey -in key.pem -text -noout
+
+To print out the public components of a private key to standard output:
+
+ openssl pkey -in key.pem -text_pub -noout
+
+To just output the public part of a private key:
+
+ openssl pkey -in key.pem -pubout -out pubkey.pem
+
+To change the EC parameters encoding to B<explicit>:
+
+ openssl pkey -in key.pem -ec_param_enc explicit -out keyout.pem
+
+To change the EC point conversion form to B<compressed>:
+
+ openssl pkey -in key.pem -ec_conv_form compressed -out keyout.pem
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-genpkey(1)>,
+L<openssl-rsa(1)>,
+L<openssl-pkcs8(1)>,
+L<openssl-dsa(1)>,
+L<openssl-genrsa(1)>,
+L<openssl-gendsa(1)>
+
+=head1 HISTORY
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-pkeyparam.pod.in b/doc/man1/openssl-pkeyparam.pod.in
new file mode 100644
index 000000000000..5053316c6880
--- /dev/null
+++ b/doc/man1/openssl-pkeyparam.pod.in
@@ -0,0 +1,98 @@
+=pod
+
+=begin comment
+{- join("\n", @autowarntext) -}
+
+=end comment
+
+=head1 NAME
+
+openssl-pkeyparam - public key algorithm parameter processing command
+
+=head1 SYNOPSIS
+
+B<openssl> B<pkeyparam>
+[B<-help>]
+[B<-in> I<filename>]
+[B<-out> I<filename>]
+[B<-text>]
+[B<-noout>]
+[B<-check>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command processes public key algorithm parameters.
+They can be checked for correctness and their components printed out.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-in> I<filename>
+
+This specifies the input filename to read parameters from or standard input if
+this option is not specified.
+
+=item B<-out> I<filename>
+
+This specifies the output filename to write parameters to or standard output if
+this option is not specified.
+
+=item B<-text>
+
+Prints out the parameters in plain text in addition to the encoded version.
+
+=item B<-noout>
+
+Do not output the encoded version of the parameters.
+
+=item B<-check>
+
+This option checks the correctness of parameters.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 EXAMPLES
+
+Print out text version of parameters:
+
+ openssl pkeyparam -in param.pem -text
+
+=head1 NOTES
+
+There are no B<-inform> or B<-outform> options for this command because only
+PEM format is supported because the key type is determined by the PEM headers.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-genpkey(1)>,
+L<openssl-rsa(1)>,
+L<openssl-pkcs8(1)>,
+L<openssl-dsa(1)>,
+L<openssl-genrsa(1)>,
+L<openssl-gendsa(1)>
+
+=head1 HISTORY
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-pkeyutl.pod.in b/doc/man1/openssl-pkeyutl.pod.in
new file mode 100644
index 000000000000..b0054ead66f3
--- /dev/null
+++ b/doc/man1/openssl-pkeyutl.pod.in
@@ -0,0 +1,430 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-pkeyutl - public key algorithm command
+
+=head1 SYNOPSIS
+
+B<openssl> B<pkeyutl>
+[B<-help>]
+[B<-in> I<file>]
+[B<-rawin>]
+[B<-digest> I<algorithm>]
+[B<-out> I<file>]
+[B<-sigfile> I<file>]
+[B<-inkey> I<filename>|I<uri>]
+[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-passin> I<arg>]
+[B<-peerkey> I<file>]
+[B<-peerform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-pubin>]
+[B<-certin>]
+[B<-rev>]
+[B<-sign>]
+[B<-verify>]
+[B<-verifyrecover>]
+[B<-encrypt>]
+[B<-decrypt>]
+[B<-derive>]
+[B<-kdf> I<algorithm>]
+[B<-kdflen> I<length>]
+[B<-pkeyopt> I<opt>:I<value>]
+[B<-pkeyopt_passin> I<opt>[:I<passarg>]]
+[B<-hexdump>]
+[B<-asn1parse>]
+{- $OpenSSL::safe::opt_engine_synopsis -}[B<-engine_impl>]
+{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+{- $OpenSSL::safe::opt_config_synopsis -}
+
+=head1 DESCRIPTION
+
+This command can be used to perform low-level public key
+operations using any supported algorithm.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-in> I<filename>
+
+This specifies the input filename to read data from or standard input
+if this option is not specified.
+
+=item B<-rawin>
+
+This indicates that the input data is raw data, which is not hashed by any
+message digest algorithm. The user can specify a digest algorithm by using
+the B<-digest> option. This option can only be used with B<-sign> and
+B<-verify> and must be used with the Ed25519 and Ed448 algorithms.
+
+=item B<-digest> I<algorithm>
+
+This specifies the digest algorithm which is used to hash the input data before
+signing or verifying it with the input key. This option could be omitted if the
+signature algorithm does not require one (for instance, EdDSA). If this option
+is omitted but the signature algorithm requires one, a default value will be
+used. For signature algorithms like RSA, DSA and ECDSA, SHA-256 will be the
+default digest algorithm. For SM2, it will be SM3. If this option is present,
+then the B<-rawin> option must be also specified.
+
+=item B<-out> I<filename>
+
+Specifies the output filename to write to or standard output by
+default.
+
+=item B<-sigfile> I<file>
+
+Signature file, required for B<-verify> operations only
+
+=item B<-inkey> I<filename>|I<uri>
+
+The input key, by default it should be a private key.
+
+=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The key format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-passin> I<arg>
+
+The input key password source. For more information about the format of I<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-peerkey> I<file>
+
+The peer key file, used by key derivation (agreement) operations.
+
+=item B<-peerform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The peer key format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-pubin>
+
+The input file is a public key.
+
+=item B<-certin>
+
+The input is a certificate containing a public key.
+
+=item B<-rev>
+
+Reverse the order of the input buffer. This is useful for some libraries
+(such as CryptoAPI) which represent the buffer in little endian format.
+
+=item B<-sign>
+
+Sign the input data (which must be a hash) and output the signed result. This
+requires a private key.
+
+=item B<-verify>
+
+Verify the input data (which must be a hash) against the signature file and
+indicate if the verification succeeded or failed.
+
+=item B<-verifyrecover>
+
+Verify the input data (which must be a hash) and output the recovered data.
+
+=item B<-encrypt>
+
+Encrypt the input data using a public key.
+
+=item B<-decrypt>
+
+Decrypt the input data using a private key.
+
+=item B<-derive>
+
+Derive a shared secret using the peer key.
+
+=item B<-kdf> I<algorithm>
+
+Use key derivation function I<algorithm>. The supported algorithms are
+at present B<TLS1-PRF> and B<HKDF>.
+Note: additional parameters and the KDF output length will normally have to be
+set for this to work.
+See L<EVP_PKEY_CTX_set_hkdf_md(3)> and L<EVP_PKEY_CTX_set_tls1_prf_md(3)>
+for the supported string parameters of each algorithm.
+
+=item B<-kdflen> I<length>
+
+Set the output length for KDF.
+
+=item B<-pkeyopt> I<opt>:I<value>
+
+Public key options specified as opt:value. See NOTES below for more details.
+
+=item B<-pkeyopt_passin> I<opt>[:I<passarg>]
+
+Allows reading a public key option I<opt> from stdin or a password source.
+If only I<opt> is specified, the user will be prompted to enter a password on
+stdin. Alternatively, I<passarg> can be specified which can be any value
+supported by L<openssl-passphrase-options(1)>.
+
+=item B<-hexdump>
+
+hex dump the output data.
+
+=item B<-asn1parse>
+
+Parse the ASN.1 output data, this is useful when combined with the
+B<-verifyrecover> option when an ASN1 structure is signed.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- output_off() if $disabled{"deprecated-3.0"}; "" -}
+=item B<-engine_impl>
+
+When used with the B<-engine> option, it specifies to also use
+engine I<id> for crypto operations.
+{- output_on() if $disabled{"deprecated-3.0"}; "" -}
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+{- $OpenSSL::safe::opt_config_item -}
+
+=back
+
+=head1 NOTES
+
+The operations and options supported vary according to the key algorithm
+and its implementation. The OpenSSL operations and options are indicated below.
+
+Unless otherwise mentioned all algorithms support the B<digest:>I<alg> option
+which specifies the digest in use for sign, verify and verifyrecover operations.
+The value I<alg> should represent a digest name as used in the
+EVP_get_digestbyname() function for example B<sha1>. This value is not used to
+hash the input data. It is used (by some algorithms) for sanity-checking the
+lengths of data passed in and for creating the structures that make up the
+signature (e.g. B<DigestInfo> in RSASSA PKCS#1 v1.5 signatures).
+
+This command does not hash the input data (except where -rawin is used) but
+rather it will use the data directly as input to the signature algorithm.
+Depending on the key type, signature type, and mode of padding, the maximum
+acceptable lengths of input data differ. The signed data can't be longer than
+the key modulus with RSA. In case of ECDSA and DSA the data shouldn't be longer
+than the field size, otherwise it will be silently truncated to the field size.
+In any event the input size must not be larger than the largest supported digest
+size.
+
+In other words, if the value of digest is B<sha1> the input should be the 20
+bytes long binary encoding of the SHA-1 hash function output.
+
+=head1 RSA ALGORITHM
+
+The RSA algorithm generally supports the encrypt, decrypt, sign,
+verify and verifyrecover operations. However, some padding modes
+support only a subset of these operations. The following additional
+B<pkeyopt> values are supported:
+
+=over 4
+
+=item B<rsa_padding_mode:>I<mode>
+
+This sets the RSA padding mode. Acceptable values for I<mode> are B<pkcs1> for
+PKCS#1 padding, B<none> for no padding, B<oaep>
+for B<OAEP> mode, B<x931> for X9.31 mode and B<pss> for PSS.
+
+In PKCS#1 padding if the message digest is not set then the supplied data is
+signed or verified directly instead of using a B<DigestInfo> structure. If a
+digest is set then the a B<DigestInfo> structure is used and its the length
+must correspond to the digest type.
+
+For B<oaep> mode only encryption and decryption is supported.
+
+For B<x931> if the digest type is set it is used to format the block data
+otherwise the first byte is used to specify the X9.31 digest ID. Sign,
+verify and verifyrecover are can be performed in this mode.
+
+For B<pss> mode only sign and verify are supported and the digest type must be
+specified.
+
+=item B<rsa_pss_saltlen:>I<len>
+
+For B<pss> mode only this option specifies the salt length. Three special
+values are supported: B<digest> sets the salt length to the digest length,
+B<max> sets the salt length to the maximum permissible value. When verifying
+B<auto> causes the salt length to be automatically determined based on the
+B<PSS> block structure.
+
+=item B<rsa_mgf1_md:>I<digest>
+
+For PSS and OAEP padding sets the MGF1 digest. If the MGF1 digest is not
+explicitly set in PSS mode then the signing digest is used.
+
+=item B<rsa_oaep_md:>I<digest>
+
+Sets the digest used for the OAEP hash function. If not explicitly set then
+SHA1 is used.
+
+=back
+
+=head1 RSA-PSS ALGORITHM
+
+The RSA-PSS algorithm is a restricted version of the RSA algorithm which only
+supports the sign and verify operations with PSS padding. The following
+additional B<-pkeyopt> values are supported:
+
+=over 4
+
+=item B<rsa_padding_mode:>I<mode>, B<rsa_pss_saltlen:>I<len>,
+B<rsa_mgf1_md:>I<digest>
+
+These have the same meaning as the B<RSA> algorithm with some additional
+restrictions. The padding mode can only be set to B<pss> which is the
+default value.
+
+If the key has parameter restrictions than the digest, MGF1
+digest and salt length are set to the values specified in the parameters.
+The digest and MG cannot be changed and the salt length cannot be set to a
+value less than the minimum restriction.
+
+=back
+
+=head1 DSA ALGORITHM
+
+The DSA algorithm supports signing and verification operations only. Currently
+there are no additional B<-pkeyopt> options other than B<digest>. The SHA1
+digest is assumed by default.
+
+=head1 DH ALGORITHM
+
+The DH algorithm only supports the derivation operation and no additional
+B<-pkeyopt> options.
+
+=head1 EC ALGORITHM
+
+The EC algorithm supports sign, verify and derive operations. The sign and
+verify operations use ECDSA and derive uses ECDH. SHA1 is assumed by default for
+the B<-pkeyopt> B<digest> option.
+
+=head1 X25519 AND X448 ALGORITHMS
+
+The X25519 and X448 algorithms support key derivation only. Currently there are
+no additional options.
+
+=head1 ED25519 AND ED448 ALGORITHMS
+
+These algorithms only support signing and verifying. OpenSSL only implements the
+"pure" variants of these algorithms so raw data can be passed directly to them
+without hashing them first. The option B<-rawin> must be used with these
+algorithms with no B<-digest> specified. Additionally OpenSSL only supports
+"oneshot" operation with these algorithms. This means that the entire file to
+be signed/verified must be read into memory before processing it. Signing or
+Verifying very large files should be avoided. Additionally the size of the file
+must be known for this to work. If the size of the file cannot be determined
+(for example if the input is stdin) then the sign or verify operation will fail.
+
+=head1 SM2
+
+The SM2 algorithm supports sign, verify, encrypt and decrypt operations. For
+the sign and verify operations, SM2 requires an Distinguishing ID string to
+be passed in. The following B<-pkeyopt> value is supported:
+
+=over 4
+
+=item B<distid:>I<string>
+
+This sets the ID string used in SM2 sign or verify operations. While verifying
+an SM2 signature, the ID string must be the same one used when signing the data.
+Otherwise the verification will fail.
+
+=item B<hexdistid:>I<hex_string>
+
+This sets the ID string used in SM2 sign or verify operations. While verifying
+an SM2 signature, the ID string must be the same one used when signing the data.
+Otherwise the verification will fail. The ID string provided with this option
+should be a valid hexadecimal value.
+
+=back
+
+=head1 EXAMPLES
+
+Sign some data using a private key:
+
+ openssl pkeyutl -sign -in file -inkey key.pem -out sig
+
+Recover the signed data (e.g. if an RSA key is used):
+
+ openssl pkeyutl -verifyrecover -in sig -inkey key.pem
+
+Verify the signature (e.g. a DSA key):
+
+ openssl pkeyutl -verify -in file -sigfile sig -inkey key.pem
+
+Sign data using a message digest value (this is currently only valid for RSA):
+
+ openssl pkeyutl -sign -in file -inkey key.pem -out sig -pkeyopt digest:sha256
+
+Derive a shared secret value:
+
+ openssl pkeyutl -derive -inkey key.pem -peerkey pubkey.pem -out secret
+
+Hexdump 48 bytes of TLS1 PRF using digest B<SHA256> and shared secret and
+seed consisting of the single byte 0xFF:
+
+ openssl pkeyutl -kdf TLS1-PRF -kdflen 48 -pkeyopt md:SHA256 \
+ -pkeyopt hexsecret:ff -pkeyopt hexseed:ff -hexdump
+
+Derive a key using B<scrypt> where the password is read from command line:
+
+ openssl pkeyutl -kdf scrypt -kdflen 16 -pkeyopt_passin pass \
+ -pkeyopt hexsalt:aabbcc -pkeyopt N:16384 -pkeyopt r:8 -pkeyopt p:1
+
+Derive using the same algorithm, but read key from environment variable MYPASS:
+
+ openssl pkeyutl -kdf scrypt -kdflen 16 -pkeyopt_passin pass:env:MYPASS \
+ -pkeyopt hexsalt:aabbcc -pkeyopt N:16384 -pkeyopt r:8 -pkeyopt p:1
+
+Sign some data using an L<SM2(7)> private key and a specific ID:
+
+ openssl pkeyutl -sign -in file -inkey sm2.key -out sig -rawin -digest sm3 \
+ -pkeyopt distid:someid
+
+Verify some data using an L<SM2(7)> certificate and a specific ID:
+
+ openssl pkeyutl -verify -certin -in file -inkey sm2.cert -sigfile sig \
+ -rawin -digest sm3 -pkeyopt distid:someid
+
+Decrypt some data using a private key with OAEP padding using SHA256:
+
+ openssl pkeyutl -decrypt -in file -inkey key.pem -out secret \
+ -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-genpkey(1)>,
+L<openssl-pkey(1)>,
+L<openssl-rsautl(1)>
+L<openssl-dgst(1)>,
+L<openssl-rsa(1)>,
+L<openssl-genrsa(1)>,
+L<openssl-kdf(1)>
+L<EVP_PKEY_CTX_set_hkdf_md(3)>,
+L<EVP_PKEY_CTX_set_tls1_prf_md(3)>,
+
+=head1 HISTORY
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-prime.pod.in b/doc/man1/openssl-prime.pod.in
new file mode 100644
index 000000000000..7ed13bb4c387
--- /dev/null
+++ b/doc/man1/openssl-prime.pod.in
@@ -0,0 +1,70 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-prime - compute prime numbers
+
+=head1 SYNOPSIS
+
+B<openssl prime>
+[B<-help>]
+[B<-hex>]
+[B<-generate>]
+[B<-bits> I<num>]
+[B<-safe>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
+[B<-checks> I<num>]
+[I<number> ...]
+
+=head1 DESCRIPTION
+
+This command checks if the specified numbers are prime.
+
+If no numbers are given on the command line, the B<-generate> flag should
+be used to generate primes according to the requirements specified by the
+rest of the flags.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Display an option summary.
+
+=item B<-hex>
+
+Generate hex output.
+
+=item B<-generate>
+
+Generate a prime number.
+
+=item B<-bits> I<num>
+
+Generate a prime with I<num> bits.
+
+=item B<-safe>
+
+When used with B<-generate>, generates a "safe" prime. If the number
+generated is I<n>, then check that C<(I<n>-1)/2> is also prime.
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=item B<-checks> I<num>
+
+This parameter is ignored.
+
+=back
+
+=head1 COPYRIGHT
+
+Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-rand.pod.in b/doc/man1/openssl-rand.pod.in
new file mode 100644
index 000000000000..af2c24ae4b0f
--- /dev/null
+++ b/doc/man1/openssl-rand.pod.in
@@ -0,0 +1,78 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-rand - generate pseudo-random bytes
+
+=head1 SYNOPSIS
+
+B<openssl rand>
+[B<-help>]
+[B<-out> I<file>]
+[B<-base64>]
+[B<-hex>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+I<num>
+
+=head1 DESCRIPTION
+
+This command generates I<num> random bytes using a cryptographically
+secure pseudo random number generator (CSPRNG).
+
+The random bytes are generated using the L<RAND_bytes(3)> function,
+which provides a security level of 256 bits, provided it managed to
+seed itself successfully from a trusted operating system entropy source.
+Otherwise, the command will fail with a nonzero error code.
+For more details, see L<RAND_bytes(3)>, L<RAND(7)>, and L<EVP_RAND(7)>.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-out> I<file>
+
+Write to I<file> instead of standard output.
+
+=item B<-base64>
+
+Perform base64 encoding on the output.
+
+=item B<-hex>
+
+Show the output as a hex string.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<RAND_bytes(3)>,
+L<RAND(7)>,
+L<EVP_RAND(7)>
+
+=head1 HISTORY
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-rehash.pod.in b/doc/man1/openssl-rehash.pod.in
new file mode 100644
index 000000000000..380ad6dd2a46
--- /dev/null
+++ b/doc/man1/openssl-rehash.pod.in
@@ -0,0 +1,157 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=for comment
+Original text by James Westby.
+
+=head1 NAME
+
+openssl-rehash, c_rehash - Create symbolic links to files named by the hash
+values
+
+=head1 SYNOPSIS
+
+B<openssl>
+B<rehash>
+[B<-h>]
+[B<-help>]
+[B<-old>]
+[B<-compat>]
+[B<-n>]
+[B<-v>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
+[I<directory>] ...
+
+B<c_rehash>
+[B<-h>]
+[B<-help>]
+[B<-old>]
+[B<-n>]
+[B<-v>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
+[I<directory>] ...
+
+=head1 DESCRIPTION
+
+This command is generally equivalent to the external
+script B<c_rehash>,
+except for minor differences noted below.
+
+B<openssl rehash> scans directories and calculates a hash value of
+each F<.pem>, F<.crt>, F<.cer>, or F<.crl>
+file in the specified directory list and creates symbolic links
+for each file, where the name of the link is the hash value.
+(If the platform does not support symbolic links, a copy is made.)
+This command is useful as many programs that use OpenSSL require
+directories to be set up like this in order to find certificates.
+
+If any directories are named on the command line, then those are
+processed in turn. If not, then the B<SSL_CERT_DIR> environment variable
+is consulted; this should be a colon-separated list of directories,
+like the Unix B<PATH> variable.
+If that is not set then the default directory (installation-specific
+but often F</usr/local/ssl/certs>) is processed.
+
+In order for a directory to be processed, the user must have write
+permissions on that directory, otherwise an error will be generated.
+
+The links created are of the form I<HHHHHHHH.D>, where each I<H>
+is a hexadecimal character and I<D> is a single decimal digit.
+When a directory is processed, all links in it that have a name
+in that syntax are first removed, even if they are being used for
+some other purpose.
+To skip the removal step, use the B<-n> flag.
+Hashes for CRL's look similar except the letter B<r> appears after
+the period, like this: I<HHHHHHHH.>B<r>I<D>.
+
+Multiple objects may have the same hash; they will be indicated by
+incrementing the I<D> value. Duplicates are found by comparing the
+full SHA-1 fingerprint. A warning will be displayed if a duplicate
+is found.
+
+A warning will also be displayed if there are files that
+cannot be parsed as either a certificate or a CRL or if
+more than one such object appears in the file.
+
+=head2 Script Configuration
+
+The B<c_rehash> script
+uses the B<openssl> program to compute the hashes and
+fingerprints. If not found in the user's B<PATH>, then set the
+B<OPENSSL> environment variable to the full pathname.
+Any program can be used, it will be invoked as follows for either
+a certificate or CRL:
+
+ $OPENSSL x509 -hash -fingerprint -noout -in FILENAME
+ $OPENSSL crl -hash -fingerprint -noout -in FILENAME
+
+where I<FILENAME> is the filename. It must output the hash of the
+file on the first line, and the fingerprint on the second,
+optionally prefixed with some text and an equals sign.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help> B<-h>
+
+Display a brief usage message.
+
+=item B<-old>
+
+Use old-style hashing (MD5, as opposed to SHA-1) for generating
+links to be used for releases before 1.0.0.
+Note that current versions will not use the old style.
+
+=item B<-n>
+
+Do not remove existing links.
+This is needed when keeping new and old-style links in the same directory.
+
+=item B<-compat>
+
+Generate links for both old-style (MD5) and new-style (SHA1) hashing.
+This allows releases before 1.0.0 to use these links along-side newer
+releases.
+
+=item B<-v>
+
+Print messages about old links removed and new links created.
+By default, this command only lists each directory as it is processed.
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 ENVIRONMENT
+
+=over 4
+
+=item B<OPENSSL>
+
+The path to an executable to use to generate hashes and
+fingerprints (see above).
+
+=item B<SSL_CERT_DIR>
+
+Colon separated list of directories to operate on.
+Ignored if directories are listed on the command line.
+
+=back
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-crl(1)>,
+L<openssl-x509(1)>
+
+=head1 COPYRIGHT
+
+Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-req.pod.in b/doc/man1/openssl-req.pod.in
new file mode 100644
index 000000000000..a21c30ba47fe
--- /dev/null
+++ b/doc/man1/openssl-req.pod.in
@@ -0,0 +1,775 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-req - PKCS#10 certificate request and certificate generating command
+
+=head1 SYNOPSIS
+
+B<openssl> B<req>
+[B<-help>]
+[B<-inform> B<DER>|B<PEM>]
+[B<-outform> B<DER>|B<PEM>]
+[B<-in> I<filename>]
+[B<-passin> I<arg>]
+[B<-out> I<filename>]
+[B<-passout> I<arg>]
+[B<-text>]
+[B<-pubkey>]
+[B<-noout>]
+[B<-verify>]
+[B<-modulus>]
+[B<-new>]
+[B<-newkey> I<arg>]
+[B<-pkeyopt> I<opt>:I<value>]
+[B<-noenc>]
+[B<-nodes>]
+[B<-key> I<filename>|I<uri>]
+[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-keyout> I<filename>]
+[B<-keygen_engine> I<id>]
+[B<-I<digest>>]
+[B<-config> I<filename>]
+[B<-section> I<name>]
+[B<-x509>]
+[B<-CA> I<filename>|I<uri>]
+[B<-CAkey> I<filename>|I<uri>]
+[B<-days> I<n>]
+[B<-set_serial> I<n>]
+[B<-newhdr>]
+[B<-copy_extensions> I<arg>]
+[B<-addext> I<ext>]
+[B<-extensions> I<section>]
+[B<-reqexts> I<section>]
+[B<-precert>]
+[B<-utf8>]
+[B<-reqopt>]
+[B<-subject>]
+[B<-subj> I<arg>]
+[B<-multivalue-rdn>]
+[B<-sigopt> I<nm>:I<v>]
+[B<-vfyopt> I<nm>:I<v>]
+[B<-batch>]
+[B<-verbose>]
+{- $OpenSSL::safe::opt_name_synopsis -}
+{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command primarily creates and processes certificate requests (CSRs)
+in PKCS#10 format. It can additionally create self-signed certificates
+for use as root CAs for example.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-inform> B<DER>|B<PEM>, B<-outform> B<DER>|B<PEM>
+
+The input and output formats; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+The data is a PKCS#10 object.
+
+=item B<-in> I<filename>
+
+This specifies the input filename to read a request from.
+This defaults to standard input unless B<-x509> or B<-CA> is specified.
+A request is only read if the creation options
+(B<-new> or B<-newkey> or B<-precert>) are not specified.
+
+=item B<-sigopt> I<nm>:I<v>
+
+Pass options to the signature algorithm during sign operations.
+Names and values of these options are algorithm-specific.
+
+=item B<-vfyopt> I<nm>:I<v>
+
+Pass options to the signature algorithm during verify operations.
+Names and values of these options are algorithm-specific.
+
+=begin comment
+
+Maybe it would be preferable to only have -opts instead of -sigopt and
+-vfyopt? They are both present here to be compatible with L<openssl-ca(1)>,
+which supports both options for good reasons.
+
+=end comment
+
+=item B<-passin> I<arg>
+
+The password source for private key and certificate input.
+For more information about the format of B<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-passout> I<arg>
+
+The password source for the output file.
+For more information about the format of B<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-out> I<filename>
+
+This specifies the output filename to write to or standard output by default.
+
+=item B<-text>
+
+Prints out the certificate request in text form.
+
+=item B<-subject>
+
+Prints out the certificate request subject
+(or certificate subject if B<-x509> is in use).
+
+=item B<-pubkey>
+
+Prints out the public key.
+
+=item B<-noout>
+
+This option prevents output of the encoded version of the certificate request.
+
+=item B<-modulus>
+
+Prints out the value of the modulus of the public key contained in the request.
+
+=item B<-verify>
+
+Verifies the self-signature on the request.
+
+=item B<-new>
+
+This option generates a new certificate request. It will prompt
+the user for the relevant field values. The actual fields
+prompted for and their maximum and minimum sizes are specified
+in the configuration file and any requested extensions.
+
+If the B<-key> option is not given it will generate a new private key
+using information specified in the configuration file or given with
+the B<-newkey> and B<-pkeyopt> options,
+else by default an RSA key with 2048 bits length.
+
+=item B<-newkey> I<arg>
+
+This option is used to generate a new private key unless B<-key> is given.
+It is subsequently used as if it was given using the B<-key> option.
+
+This option implies the B<-new> flag to create a new certificate request
+or a new certificate in case B<-x509> is given.
+
+The argument takes one of several forms.
+
+[B<rsa:>]I<nbits> generates an RSA key I<nbits> in size.
+If I<nbits> is omitted, i.e., B<-newkey> B<rsa> is specified,
+the default key size specified in the configuration file
+with the B<default_bits> option is used if present, else 2048.
+
+All other algorithms support the B<-newkey> I<algname>:I<file> form, where
+I<file> is an algorithm parameter file, created with C<openssl genpkey -genparam>
+or an X.509 certificate for a key with appropriate algorithm.
+
+B<param:>I<file> generates a key using the parameter file or certificate
+I<file>, the algorithm is determined by the parameters.
+
+I<algname>[:I<file>] generates a key using the given algorithm I<algname>.
+If a parameter file I<file> is given then the parameters specified there
+are used, where the algorithm parameters must match I<algname>.
+If algorithm parameters are not given,
+any necessary parameters should be specified via the B<-pkeyopt> option.
+
+B<dsa:>I<filename> generates a DSA key using the parameters
+in the file I<filename>. B<ec:>I<filename> generates EC key (usable both with
+ECDSA or ECDH algorithms), B<gost2001:>I<filename> generates GOST R
+34.10-2001 key (requires B<gost> engine configured in the configuration
+file). If just B<gost2001> is specified a parameter set should be
+specified by B<-pkeyopt> I<paramset:X>
+
+=item B<-pkeyopt> I<opt>:I<value>
+
+Set the public key algorithm option I<opt> to I<value>. The precise set of
+options supported depends on the public key algorithm used and its
+implementation.
+See L<openssl-genpkey(1)/KEY GENERATION OPTIONS> for more details.
+
+=item B<-key> I<filename>|I<uri>
+
+This option provides the private key for signing a new certificate or
+certificate request.
+Unless B<-in> is given, the corresponding public key is placed in
+the new certificate or certificate request, resulting in a self-signature.
+
+For certificate signing this option is overridden by the B<-CA> option.
+
+This option also accepts PKCS#8 format private keys for PEM format files.
+
+=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The format of the private key; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-keyout> I<filename>
+
+This gives the filename to write any private key to that has been newly created
+or read from B<-key>. If neither the B<-keyout> option nor the B<-key> option
+are given then the filename specified in the configuration file with the
+B<default_keyfile> option is used, if present. Thus, if you want to write the
+private key and the B<-key> option is provided, you should provide the
+B<-keyout> option explicitly. If a new key is generated and no filename is
+specified the key is written to standard output.
+
+=item B<-noenc>
+
+If this option is specified then if a private key is created it
+will not be encrypted.
+
+=item B<-nodes>
+
+This option is deprecated since OpenSSL 3.0; use B<-noenc> instead.
+
+=item B<-I<digest>>
+
+This specifies the message digest to sign the request.
+Any digest supported by the OpenSSL B<dgst> command can be used.
+This overrides the digest algorithm specified in
+the configuration file.
+
+Some public key algorithms may override this choice. For instance, DSA
+signatures always use SHA1, GOST R 34.10 signatures always use
+GOST R 34.11-94 (B<-md_gost94>), Ed25519 and Ed448 never use any digest.
+
+=item B<-config> I<filename>
+
+This allows an alternative configuration file to be specified.
+Optional; for a description of the default value,
+see L<openssl(1)/COMMAND SUMMARY>.
+
+=item B<-section> I<name>
+
+Specifies the name of the section to use; the default is B<req>.
+
+=item B<-subj> I<arg>
+
+Sets subject name for new request or supersedes the subject name
+when processing a certificate request.
+
+The arg must be formatted as C</type0=value0/type1=value1/type2=...>.
+Special characters may be escaped by C<\> (backslash), whitespace is retained.
+Empty values are permitted, but the corresponding type will not be included
+in the request.
+Giving a single C</> will lead to an empty sequence of RDNs (a NULL-DN).
+Multi-valued RDNs can be formed by placing a C<+> character instead of a C</>
+between the AttributeValueAssertions (AVAs) that specify the members of the set.
+Example:
+
+C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
+
+=item B<-multivalue-rdn>
+
+This option has been deprecated and has no effect.
+
+=item B<-x509>
+
+This option outputs a certificate instead of a certificate request.
+This is typically used to generate test certificates.
+It is implied by the B<-CA> option.
+
+This option implies the B<-new> flag if B<-in> is not given.
+
+If an existing request is specified with the B<-in> option, it is converted
+to the a certificate; otherwise a request is created from scratch.
+
+Unless specified using the B<-set_serial> option,
+a large random number will be used for the serial number.
+
+Unless the B<-copy_extensions> option is used,
+X.509 extensions are not copied from any provided request input file.
+
+X.509 extensions to be added can be specified in the configuration file
+or using the B<-addext> option.
+
+=item B<-CA> I<filename>|I<uri>
+
+Specifies the "CA" certificate to be used for signing a new certificate
+and implies use of B<-x509>.
+When present, this behaves like a "micro CA" as follows:
+The subject name of the "CA" certificate is placed as issuer name in the new
+certificate, which is then signed using the "CA" key given as specified below.
+
+=item B<-CAkey> I<filename>|I<uri>
+
+Sets the "CA" private key to sign a certificate with.
+The private key must match the public key of the certificate given with B<-CA>.
+If this option is not provided then the key must be present in the B<-CA> input.
+
+=item B<-days> I<n>
+
+When B<-x509> is in use this specifies the number of
+days to certify the certificate for, otherwise it is ignored. I<n> should
+be a positive integer. The default is 30 days.
+
+=item B<-set_serial> I<n>
+
+Serial number to use when outputting a self-signed certificate.
+This may be specified as a decimal value or a hex value if preceded by C<0x>.
+If not given, a large random number will be used.
+
+=item B<-copy_extensions> I<arg>
+
+Determines how X.509 extensions in certificate requests should be handled
+when B<-x509> is in use.
+If I<arg> is B<none> or this option is not present then extensions are ignored.
+If I<arg> is B<copy> or B<copyall> then
+all extensions in the request are copied to the certificate.
+
+The main use of this option is to allow a certificate request to supply
+values for certain extensions such as subjectAltName.
+
+=item B<-addext> I<ext>
+
+Add a specific extension to the certificate (if B<-x509> is in use)
+or certificate request. The argument must have the form of
+a key=value pair as it would appear in a config file.
+
+This option can be given multiple times.
+
+=item B<-extensions> I<section>
+
+=item B<-reqexts> I<section>
+
+These options specify alternative sections to include certificate
+extensions (if B<-x509> is in use) or certificate request extensions.
+This allows several different sections to
+be used in the same configuration file to specify requests for
+a variety of purposes.
+
+=item B<-precert>
+
+A poison extension will be added to the certificate, making it a
+"pre-certificate" (see RFC6962). This can be submitted to Certificate
+Transparency logs in order to obtain signed certificate timestamps (SCTs).
+These SCTs can then be embedded into the pre-certificate as an extension, before
+removing the poison and signing the certificate.
+
+This implies the B<-new> flag.
+
+=item B<-utf8>
+
+This option causes field values to be interpreted as UTF8 strings, by
+default they are interpreted as ASCII. This means that the field
+values, whether prompted from a terminal or obtained from a
+configuration file, must be valid UTF8 strings.
+
+=item B<-reqopt> I<option>
+
+Customise the printing format used with B<-text>. The I<option> argument can be
+a single option or multiple options separated by commas.
+
+See discussion of the B<-certopt> parameter in the L<openssl-x509(1)>
+command.
+
+=item B<-newhdr>
+
+Adds the word B<NEW> to the PEM file header and footer lines on the outputted
+request. Some software (Netscape certificate server) and some CAs need this.
+
+=item B<-batch>
+
+Non-interactive mode.
+
+=item B<-verbose>
+
+Print extra details about the operations being performed.
+
+=item B<-keygen_engine> I<id>
+
+Specifies an engine (by its unique I<id> string) which would be used
+for key generation operations.
+
+{- $OpenSSL::safe::opt_name_item -}
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 CONFIGURATION FILE FORMAT
+
+The configuration options are specified in the B<req> section of
+the configuration file. An alternate name be specified by using the
+B<-section> option.
+As with all configuration files, if no
+value is specified in the specific section then
+the initial unnamed or B<default> section is searched too.
+
+The options available are described in detail below.
+
+=over 4
+
+=item B<input_password>, B<output_password>
+
+The passwords for the input private key file (if present) and
+the output private key file (if one will be created). The
+command line options B<passin> and B<passout> override the
+configuration file values.
+
+=item B<default_bits>
+
+Specifies the default key size in bits.
+
+This option is used in conjunction with the B<-new> option to generate
+a new key. It can be overridden by specifying an explicit key size in
+the B<-newkey> option. The smallest accepted key size is 512 bits. If
+no key size is specified then 2048 bits is used.
+
+=item B<default_keyfile>
+
+This is the default filename to write a private key to. If not
+specified the key is written to standard output. This can be
+overridden by the B<-keyout> option.
+
+=item B<oid_file>
+
+This specifies a file containing additional B<OBJECT IDENTIFIERS>.
+Each line of the file should consist of the numerical form of the
+object identifier followed by whitespace then the short name followed
+by whitespace and finally the long name.
+
+=item B<oid_section>
+
+This specifies a section in the configuration file containing extra
+object identifiers. Each line should consist of the short name of the
+object identifier followed by B<=> and the numerical form. The short
+and long names are the same when this option is used.
+
+=item B<RANDFILE>
+
+At startup the specified file is loaded into the random number generator,
+and at exit 256 bytes will be written to it.
+It is used for private key generation.
+
+=item B<encrypt_key>
+
+If this is set to B<no> then if a private key is generated it is
+B<not> encrypted. This is equivalent to the B<-noenc> command line
+option. For compatibility B<encrypt_rsa_key> is an equivalent option.
+
+=item B<default_md>
+
+This option specifies the digest algorithm to use. Any digest supported by the
+OpenSSL B<dgst> command can be used. This option can be overridden on the
+command line. Certain signing algorithms (i.e. Ed25519 and Ed448) will ignore
+any digest that has been set.
+
+=item B<string_mask>
+
+This option masks out the use of certain string types in certain
+fields. Most users will not need to change this option.
+
+It can be set to several values B<default> which is also the default
+option uses PrintableStrings, T61Strings and BMPStrings if the
+B<pkix> value is used then only PrintableStrings and BMPStrings will
+be used. This follows the PKIX recommendation in RFC2459. If the
+B<utf8only> option is used then only UTF8Strings will be used: this
+is the PKIX recommendation in RFC2459 after 2003. Finally the B<nombstr>
+option just uses PrintableStrings and T61Strings: certain software has
+problems with BMPStrings and UTF8Strings: in particular Netscape.
+
+=item B<req_extensions>
+
+This specifies the configuration file section containing a list of
+extensions to add to the certificate request. It can be overridden
+by the B<-reqexts> command line switch. See the
+L<x509v3_config(5)> manual page for details of the
+extension section format.
+
+=item B<x509_extensions>
+
+This specifies the configuration file section containing a list of
+extensions to add to certificate generated when B<-x509> is in use.
+It can be overridden by the B<-extensions> command line switch.
+
+=item B<prompt>
+
+If set to the value B<no> this disables prompting of certificate fields
+and just takes values from the config file directly. It also changes the
+expected format of the B<distinguished_name> and B<attributes> sections.
+
+=item B<utf8>
+
+If set to the value B<yes> then field values to be interpreted as UTF8
+strings, by default they are interpreted as ASCII. This means that
+the field values, whether prompted from a terminal or obtained from a
+configuration file, must be valid UTF8 strings.
+
+=item B<attributes>
+
+This specifies the section containing any request attributes: its format
+is the same as B<distinguished_name>. Typically these may contain the
+challengePassword or unstructuredName types. They are currently ignored
+by OpenSSL's request signing utilities but some CAs might want them.
+
+=item B<distinguished_name>
+
+This specifies the section containing the distinguished name fields to
+prompt for when generating a certificate or certificate request. The format
+is described in the next section.
+
+=back
+
+=head1 DISTINGUISHED NAME AND ATTRIBUTE SECTION FORMAT
+
+There are two separate formats for the distinguished name and attribute
+sections. If the B<prompt> option is set to B<no> then these sections
+just consist of field names and values: for example,
+
+ CN=My Name
+ OU=My Organization
+ emailAddress=someone@somewhere.org
+
+This allows external programs (e.g. GUI based) to generate a template file with
+all the field names and values and just pass it to this command. An example
+of this kind of configuration file is contained in the B<EXAMPLES> section.
+
+Alternatively if the B<prompt> option is absent or not set to B<no> then the
+file contains field prompting information. It consists of lines of the form:
+
+ fieldName="prompt"
+ fieldName_default="default field value"
+ fieldName_min= 2
+ fieldName_max= 4
+
+"fieldName" is the field name being used, for example commonName (or CN).
+The "prompt" string is used to ask the user to enter the relevant
+details. If the user enters nothing then the default value is used if no
+default value is present then the field is omitted. A field can
+still be omitted if a default value is present if the user just
+enters the '.' character.
+
+The number of characters entered must be between the fieldName_min and
+fieldName_max limits: there may be additional restrictions based
+on the field being used (for example countryName can only ever be
+two characters long and must fit in a PrintableString).
+
+Some fields (such as organizationName) can be used more than once
+in a DN. This presents a problem because configuration files will
+not recognize the same name occurring twice. To avoid this problem
+if the fieldName contains some characters followed by a full stop
+they will be ignored. So for example a second organizationName can
+be input by calling it "1.organizationName".
+
+The actual permitted field names are any object identifier short or
+long names. These are compiled into OpenSSL and include the usual
+values such as commonName, countryName, localityName, organizationName,
+organizationalUnitName, stateOrProvinceName. Additionally emailAddress
+is included as well as name, surname, givenName, initials, and dnQualifier.
+
+Additional object identifiers can be defined with the B<oid_file> or
+B<oid_section> options in the configuration file. Any additional fields
+will be treated as though they were a DirectoryString.
+
+
+=head1 EXAMPLES
+
+Examine and verify certificate request:
+
+ openssl req -in req.pem -text -verify -noout
+
+Create a private key and then generate a certificate request from it:
+
+ openssl genrsa -out key.pem 2048
+ openssl req -new -key key.pem -out req.pem
+
+The same but just using req:
+
+ openssl req -newkey rsa:2048 -keyout key.pem -out req.pem
+
+Generate a self-signed root certificate:
+
+ openssl req -x509 -newkey rsa:2048 -keyout key.pem -out req.pem
+
+Create an SM2 private key and then generate a certificate request from it:
+
+ openssl ecparam -genkey -name SM2 -out sm2.key
+ openssl req -new -key sm2.key -out sm2.csr -sm3 -sigopt "distid:1234567812345678"
+
+Examine and verify an SM2 certificate request:
+
+ openssl req -verify -in sm2.csr -sm3 -vfyopt "distid:1234567812345678"
+
+Example of a file pointed to by the B<oid_file> option:
+
+ 1.2.3.4 shortName A longer Name
+ 1.2.3.6 otherName Other longer Name
+
+Example of a section pointed to by B<oid_section> making use of variable
+expansion:
+
+ testoid1=1.2.3.5
+ testoid2=${testoid1}.6
+
+Sample configuration file prompting for field values:
+
+ [ req ]
+ default_bits = 2048
+ default_keyfile = privkey.pem
+ distinguished_name = req_distinguished_name
+ attributes = req_attributes
+ req_extensions = v3_ca
+
+ dirstring_type = nobmp
+
+ [ req_distinguished_name ]
+ countryName = Country Name (2 letter code)
+ countryName_default = AU
+ countryName_min = 2
+ countryName_max = 2
+
+ localityName = Locality Name (eg, city)
+
+ organizationalUnitName = Organizational Unit Name (eg, section)
+
+ commonName = Common Name (eg, YOUR name)
+ commonName_max = 64
+
+ emailAddress = Email Address
+ emailAddress_max = 40
+
+ [ req_attributes ]
+ challengePassword = A challenge password
+ challengePassword_min = 4
+ challengePassword_max = 20
+
+ [ v3_ca ]
+
+ subjectKeyIdentifier=hash
+ authorityKeyIdentifier=keyid:always,issuer:always
+ basicConstraints = critical, CA:true
+
+Sample configuration containing all field values:
+
+
+ [ req ]
+ default_bits = 2048
+ default_keyfile = keyfile.pem
+ distinguished_name = req_distinguished_name
+ attributes = req_attributes
+ prompt = no
+ output_password = mypass
+
+ [ req_distinguished_name ]
+ C = GB
+ ST = Test State or Province
+ L = Test Locality
+ O = Organization Name
+ OU = Organizational Unit Name
+ CN = Common Name
+ emailAddress = test@email.address
+
+ [ req_attributes ]
+ challengePassword = A challenge password
+
+Example of giving the most common attributes (subject and extensions)
+on the command line:
+
+ openssl req -new -subj "/C=GB/CN=foo" \
+ -addext "subjectAltName = DNS:foo.co.uk" \
+ -addext "certificatePolicies = 1.2.3.4" \
+ -newkey rsa:2048 -keyout key.pem -out req.pem
+
+
+=head1 NOTES
+
+The certificate requests generated by B<Xenroll> with MSIE have extensions
+added. It includes the B<keyUsage> extension which determines the type of
+key (signature only or general purpose) and any additional OIDs entered
+by the script in an B<extendedKeyUsage> extension.
+
+=head1 DIAGNOSTICS
+
+The following messages are frequently asked about:
+
+ Using configuration from /some/path/openssl.cnf
+ Unable to load config info
+
+This is followed some time later by:
+
+ unable to find 'distinguished_name' in config
+ problems making Certificate Request
+
+The first error message is the clue: it can't find the configuration
+file! Certain operations (like examining a certificate request) don't
+need a configuration file so its use isn't enforced. Generation of
+certificates or requests however does need a configuration file. This
+could be regarded as a bug.
+
+Another puzzling message is this:
+
+ Attributes:
+ a0:00
+
+this is displayed when no attributes are present and the request includes
+the correct empty B<SET OF> structure (the DER encoding of which is 0xa0
+0x00). If you just see:
+
+ Attributes:
+
+then the B<SET OF> is missing and the encoding is technically invalid (but
+it is tolerated). See the description of the command line option B<-asn1-kludge>
+for more information.
+
+=head1 BUGS
+
+OpenSSL's handling of T61Strings (aka TeletexStrings) is broken: it effectively
+treats them as ISO-8859-1 (Latin 1), Netscape and MSIE have similar behaviour.
+This can cause problems if you need characters that aren't available in
+PrintableStrings and you don't want to or can't use BMPStrings.
+
+As a consequence of the T61String handling the only correct way to represent
+accented characters in OpenSSL is to use a BMPString: unfortunately Netscape
+currently chokes on these. If you have to use accented characters with Netscape
+and MSIE then you currently need to use the invalid T61String form.
+
+The current prompting is not very friendly. It doesn't allow you to confirm what
+you've just entered. Other things like extensions in certificate requests are
+statically defined in the configuration file. Some of these: like an email
+address in subjectAltName should be input by the user.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-x509(1)>,
+L<openssl-ca(1)>,
+L<openssl-genrsa(1)>,
+L<openssl-gendsa(1)>,
+L<config(5)>,
+L<x509v3_config(5)>
+
+=head1 HISTORY
+
+The B<-section> option was added in OpenSSL 3.0.0.
+
+The B<-multivalue-rdn> option has become obsolete in OpenSSL 3.0.0 and
+has no effect.
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+The <-nodes> option was deprecated in OpenSSL 3.0, too; use B<-noenc> instead.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-rsa.pod.in b/doc/man1/openssl-rsa.pod.in
new file mode 100644
index 000000000000..35bd30042907
--- /dev/null
+++ b/doc/man1/openssl-rsa.pod.in
@@ -0,0 +1,216 @@
+=pod
+
+=begin comment
+{- join("\n", @autowarntext) -}
+
+=end comment
+
+=head1 NAME
+
+openssl-rsa - RSA key processing command
+
+=head1 SYNOPSIS
+
+B<openssl> B<rsa>
+[B<-help>]
+[B<-inform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-outform> B<DER>|B<PEM>]
+[B<-in> I<filename>|I<uri>]
+[B<-passin> I<arg>]
+[B<-out> I<filename>]
+[B<-passout> I<arg>]
+[B<-aes128>]
+[B<-aes192>]
+[B<-aes256>]
+[B<-aria128>]
+[B<-aria192>]
+[B<-aria256>]
+[B<-camellia128>]
+[B<-camellia192>]
+[B<-camellia256>]
+[B<-des>]
+[B<-des3>]
+[B<-idea>]
+[B<-text>]
+[B<-noout>]
+[B<-modulus>]
+[B<-traditional>]
+[B<-check>]
+[B<-pubin>]
+[B<-pubout>]
+[B<-RSAPublicKey_in>]
+[B<-RSAPublicKey_out>]
+[B<-pvk-strong>]
+[B<-pvk-weak>]
+[B<-pvk-none>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command processes RSA keys. They can be converted between
+various forms and their components printed out.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-inform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The key input format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-outform> B<DER>|B<PEM>
+
+The key output format; the default is B<PEM>.
+See L<openssl-format-options(1)> for details.
+
+=item B<-traditional>
+
+When writing a private key, use the traditional PKCS#1 format
+instead of the PKCS#8 format.
+
+=item B<-in> I<filename>|I<uri>
+
+This specifies the input to read a key from or standard input if this
+option is not specified. If the key is encrypted a pass phrase will be
+prompted for.
+
+=item B<-passin> I<arg>, B<-passout> I<arg>
+
+The password source for the input and output file.
+For more information about the format of B<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-out> I<filename>
+
+This specifies the output filename to write a key to or standard output if this
+option is not specified. If any encryption options are set then a pass phrase
+will be prompted for. The output filename should B<not> be the same as the input
+filename.
+
+=item B<-aes128>, B<-aes192>, B<-aes256>, B<-aria128>, B<-aria192>, B<-aria256>, B<-camellia128>, B<-camellia192>, B<-camellia256>, B<-des>, B<-des3>, B<-idea>
+
+These options encrypt the private key with the specified
+cipher before outputting it. A pass phrase is prompted for.
+If none of these options is specified the key is written in plain text. This
+means that this command can be used to remove the pass phrase from a key
+by not giving any encryption option is given, or to add or change the pass
+phrase by setting them.
+These options can only be used with PEM format output files.
+
+=item B<-text>
+
+Prints out the various public or private key components in
+plain text in addition to the encoded version.
+
+=item B<-noout>
+
+This option prevents output of the encoded version of the key.
+
+=item B<-modulus>
+
+This option prints out the value of the modulus of the key.
+
+=item B<-check>
+
+This option checks the consistency of an RSA private key.
+
+=item B<-pubin>
+
+By default a private key is read from the input file: with this
+option a public key is read instead.
+
+=item B<-pubout>
+
+By default a private key is output: with this option a public
+key will be output instead. This option is automatically set if
+the input is a public key.
+
+=item B<-RSAPublicKey_in>, B<-RSAPublicKey_out>
+
+Like B<-pubin> and B<-pubout> except B<RSAPublicKey> format is used instead.
+
+=item B<-pvk-strong>
+
+Enable 'Strong' PVK encoding level (default).
+
+=item B<-pvk-weak>
+
+Enable 'Weak' PVK encoding level.
+
+=item B<-pvk-none>
+
+Don't enforce PVK encoding.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 NOTES
+
+The L<openssl-pkey(1)> command is capable of performing all the operations
+this command can, as well as supporting other public key types.
+
+=head1 EXAMPLES
+
+The documentation for the L<openssl-pkey(1)> command contains examples
+equivalent to the ones listed here.
+
+To remove the pass phrase on an RSA private key:
+
+ openssl rsa -in key.pem -out keyout.pem
+
+To encrypt a private key using triple DES:
+
+ openssl rsa -in key.pem -des3 -out keyout.pem
+
+To convert a private key from PEM to DER format:
+
+ openssl rsa -in key.pem -outform DER -out keyout.der
+
+To print out the components of a private key to standard output:
+
+ openssl rsa -in key.pem -text -noout
+
+To just output the public part of a private key:
+
+ openssl rsa -in key.pem -pubout -out pubkey.pem
+
+Output the public part of a private key in B<RSAPublicKey> format:
+
+ openssl rsa -in key.pem -RSAPublicKey_out -out pubkey.pem
+
+=head1 BUGS
+
+There should be an option that automatically handles F<.key> files,
+without having to manually edit them.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-pkey(1)>,
+L<openssl-pkcs8(1)>,
+L<openssl-dsa(1)>,
+L<openssl-genrsa(1)>,
+L<openssl-gendsa(1)>
+
+=head1 HISTORY
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-rsautl.pod.in b/doc/man1/openssl-rsautl.pod.in
new file mode 100644
index 000000000000..186e49e5e49b
--- /dev/null
+++ b/doc/man1/openssl-rsautl.pod.in
@@ -0,0 +1,242 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-rsautl - RSA command
+
+=head1 SYNOPSIS
+
+B<openssl> B<rsautl>
+[B<-help>]
+[B<-in> I<file>]
+[B<-passin> I<arg>]
+[B<-rev>]
+[B<-out> I<file>]
+[B<-inkey> I<filename>|I<uri>]
+[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-pubin>]
+[B<-certin>]
+[B<-sign>]
+[B<-verify>]
+[B<-encrypt>]
+[B<-decrypt>]
+[B<-pkcs>]
+[B<-x931>]
+[B<-oaep>]
+[B<-raw>]
+[B<-hexdump>]
+[B<-asn1parse>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command has been deprecated.
+The L<openssl-pkeyutl(1)> command should be used instead.
+
+This command can be used to sign, verify, encrypt and decrypt
+data using the RSA algorithm.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-in> I<filename>
+
+This specifies the input filename to read data from or standard input
+if this option is not specified.
+
+=item B<-passin> I<arg>
+
+The passphrase used in the output file.
+See see L<openssl-passphrase-options(1)>.
+
+=item B<-rev>
+
+Reverse the order of the input.
+
+=item B<-out> I<filename>
+
+Specifies the output filename to write to or standard output by
+default.
+
+=item B<-inkey> I<filename>|I<uri>
+
+The input key, by default it should be an RSA private key.
+
+=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The key format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-pubin>
+
+The input file is an RSA public key.
+
+=item B<-certin>
+
+The input is a certificate containing an RSA public key.
+
+=item B<-sign>
+
+Sign the input data and output the signed result. This requires
+an RSA private key.
+
+=item B<-verify>
+
+Verify the input data and output the recovered data.
+
+=item B<-encrypt>
+
+Encrypt the input data using an RSA public key.
+
+=item B<-decrypt>
+
+Decrypt the input data using an RSA private key.
+
+=item B<-pkcs>, B<-oaep>, B<-x931> B<-raw>
+
+The padding to use: PKCS#1 v1.5 (the default), PKCS#1 OAEP,
+ANSI X9.31, or no padding, respectively.
+For signatures, only B<-pkcs> and B<-raw> can be used.
+
+=item B<-hexdump>
+
+Hex dump the output data.
+
+=item B<-asn1parse>
+
+Parse the ASN.1 output data, this is useful when combined with the
+B<-verify> option.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 NOTES
+
+Since this command uses the RSA algorithm directly, it can only be
+used to sign or verify small pieces of data.
+
+=head1 EXAMPLES
+
+Examples equivalent to these can be found in the documentation for the
+non-deprecated L<openssl-pkeyutl(1)> command.
+
+Sign some data using a private key:
+
+ openssl rsautl -sign -in file -inkey key.pem -out sig
+
+Recover the signed data
+
+ openssl rsautl -verify -in sig -inkey key.pem
+
+Examine the raw signed data:
+
+ openssl rsautl -verify -in sig -inkey key.pem -raw -hexdump
+
+ 0000 - 00 01 ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
+ 0010 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
+ 0020 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
+ 0030 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
+ 0040 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
+ 0050 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
+ 0060 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
+ 0070 - ff ff ff ff 00 68 65 6c-6c 6f 20 77 6f 72 6c 64 .....hello world
+
+The PKCS#1 block formatting is evident from this. If this was done using
+encrypt and decrypt the block would have been of type 2 (the second byte)
+and random padding data visible instead of the 0xff bytes.
+
+It is possible to analyse the signature of certificates using this
+command in conjunction with L<openssl-asn1parse(1)>. Consider the self signed
+example in F<certs/pca-cert.pem>. Running L<openssl-asn1parse(1)> as follows
+yields:
+
+ openssl asn1parse -in pca-cert.pem
+
+ 0:d=0 hl=4 l= 742 cons: SEQUENCE
+ 4:d=1 hl=4 l= 591 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :md5WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 92 cons: SEQUENCE
+ 33:d=3 hl=2 l= 11 cons: SET
+ 35:d=4 hl=2 l= 9 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :countryName
+ 42:d=5 hl=2 l= 2 prim: PRINTABLESTRING :AU
+ ....
+ 599:d=1 hl=2 l= 13 cons: SEQUENCE
+ 601:d=2 hl=2 l= 9 prim: OBJECT :md5WithRSAEncryption
+ 612:d=2 hl=2 l= 0 prim: NULL
+ 614:d=1 hl=3 l= 129 prim: BIT STRING
+
+
+The final BIT STRING contains the actual signature. It can be extracted with:
+
+ openssl asn1parse -in pca-cert.pem -out sig -noout -strparse 614
+
+The certificate public key can be extracted with:
+
+ openssl x509 -in test/testx509.pem -pubkey -noout >pubkey.pem
+
+The signature can be analysed with:
+
+ openssl rsautl -in sig -verify -asn1parse -inkey pubkey.pem -pubin
+
+ 0:d=0 hl=2 l= 32 cons: SEQUENCE
+ 2:d=1 hl=2 l= 12 cons: SEQUENCE
+ 4:d=2 hl=2 l= 8 prim: OBJECT :md5
+ 14:d=2 hl=2 l= 0 prim: NULL
+ 16:d=1 hl=2 l= 16 prim: OCTET STRING
+ 0000 - f3 46 9e aa 1a 4a 73 c9-37 ea 93 00 48 25 08 b5 .F...Js.7...H%..
+
+This is the parsed version of an ASN1 DigestInfo structure. It can be seen that
+the digest used was md5. The actual part of the certificate that was signed can
+be extracted with:
+
+ openssl asn1parse -in pca-cert.pem -out tbs -noout -strparse 4
+
+and its digest computed with:
+
+ openssl md5 -c tbs
+ MD5(tbs)= f3:46:9e:aa:1a:4a:73:c9:37:ea:93:00:48:25:08:b5
+
+which it can be seen agrees with the recovered value above.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-pkeyutl(1)>,
+L<openssl-dgst(1)>,
+L<openssl-rsa(1)>,
+L<openssl-genrsa(1)>
+
+=head1 HISTORY
+
+This command was deprecated in OpenSSL 3.0.
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-s_client.pod.in b/doc/man1/openssl-s_client.pod.in
new file mode 100644
index 000000000000..c921e3b4a25f
--- /dev/null
+++ b/doc/man1/openssl-s_client.pod.in
@@ -0,0 +1,920 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-s_client - SSL/TLS client program
+
+=head1 SYNOPSIS
+
+B<openssl> B<s_client>
+[B<-help>]
+[B<-ssl_config> I<section>]
+[B<-connect> I<host:port>]
+[B<-host> I<hostname>]
+[B<-port> I<port>]
+[B<-bind> I<host:port>]
+[B<-proxy> I<host:port>]
+[B<-proxy_user> I<userid>]
+[B<-proxy_pass> I<arg>]
+[B<-unix> I<path>]
+[B<-4>]
+[B<-6>]
+[B<-servername> I<name>]
+[B<-noservername>]
+[B<-verify> I<depth>]
+[B<-verify_return_error>]
+[B<-verify_quiet>]
+[B<-verifyCAfile> I<filename>]
+[B<-verifyCApath> I<dir>]
+[B<-verifyCAstore> I<uri>]
+[B<-cert> I<filename>]
+[B<-certform> B<DER>|B<PEM>|B<P12>]
+[B<-cert_chain> I<filename>]
+[B<-build_chain>]
+[B<-CRL> I<filename>]
+[B<-CRLform> B<DER>|B<PEM>]
+[B<-crl_download>]
+[B<-key> I<filename>|I<uri>]
+[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-pass> I<arg>]
+[B<-chainCAfile> I<filename>]
+[B<-chainCApath> I<directory>]
+[B<-chainCAstore> I<uri>]
+[B<-requestCAfile> I<filename>]
+[B<-dane_tlsa_domain> I<domain>]
+[B<-dane_tlsa_rrdata> I<rrdata>]
+[B<-dane_ee_no_namechecks>]
+[B<-reconnect>]
+[B<-showcerts>]
+[B<-prexit>]
+[B<-debug>]
+[B<-trace>]
+[B<-nocommands>]
+[B<-security_debug>]
+[B<-security_debug_verbose>]
+[B<-msg>]
+[B<-timeout>]
+[B<-mtu> I<size>]
+[B<-no_etm>]
+[B<-keymatexport> I<label>]
+[B<-keymatexportlen> I<len>]
+[B<-msgfile> I<filename>]
+[B<-nbio_test>]
+[B<-state>]
+[B<-nbio>]
+[B<-crlf>]
+[B<-ign_eof>]
+[B<-no_ign_eof>]
+[B<-psk_identity> I<identity>]
+[B<-psk> I<key>]
+[B<-psk_session> I<file>]
+[B<-quiet>]
+[B<-sctp>]
+[B<-sctp_label_bug>]
+[B<-fallback_scsv>]
+[B<-async>]
+[B<-maxfraglen> I<len>]
+[B<-max_send_frag>]
+[B<-split_send_frag>]
+[B<-max_pipelines>]
+[B<-read_buf>]
+[B<-ignore_unexpected_eof>]
+[B<-bugs>]
+[B<-comp>]
+[B<-no_comp>]
+[B<-brief>]
+[B<-legacy_server_connect>]
+[B<-no_legacy_server_connect>]
+[B<-allow_no_dhe_kex>]
+[B<-sigalgs> I<sigalglist>]
+[B<-curves> I<curvelist>]
+[B<-cipher> I<cipherlist>]
+[B<-ciphersuites> I<val>]
+[B<-serverpref>]
+[B<-starttls> I<protocol>]
+[B<-name> I<hostname>]
+[B<-xmpphost> I<hostname>]
+[B<-name> I<hostname>]
+[B<-tlsextdebug>]
+[B<-no_ticket>]
+[B<-sess_out> I<filename>]
+[B<-serverinfo> I<types>]
+[B<-sess_in> I<filename>]
+[B<-serverinfo> I<types>]
+[B<-status>]
+[B<-alpn> I<protocols>]
+[B<-nextprotoneg> I<protocols>]
+[B<-ct>]
+[B<-noct>]
+[B<-ctlogfile>]
+[B<-keylogfile> I<file>]
+[B<-early_data> I<file>]
+[B<-enable_pha>]
+[B<-use_srtp> I<value>]
+[B<-srpuser> I<value>]
+[B<-srppass> I<value>]
+[B<-srp_lateuser>]
+[B<-srp_moregroups>]
+[B<-srp_strength> I<number>]
+{- $OpenSSL::safe::opt_name_synopsis -}
+{- $OpenSSL::safe::opt_version_synopsis -}
+{- $OpenSSL::safe::opt_x_synopsis -}
+{- $OpenSSL::safe::opt_trust_synopsis -}
+{- $OpenSSL::safe::opt_s_synopsis -}
+{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+{- $OpenSSL::safe::opt_engine_synopsis -}[B<-ssl_client_engine> I<id>]
+{- $OpenSSL::safe::opt_v_synopsis -}
+[I<host>:I<port>]
+
+=head1 DESCRIPTION
+
+This command implements a generic SSL/TLS client which
+connects to a remote host using SSL/TLS. It is a I<very> useful diagnostic
+tool for SSL servers.
+
+=head1 OPTIONS
+
+In addition to the options below, this command also supports the
+common and client only options documented
+in the "Supported Command Line Commands" section of the L<SSL_CONF_cmd(3)>
+manual page.
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-ssl_config> I<section>
+
+Use the specified section of the configuration file to configure the B<SSL_CTX> object.
+
+=item B<-connect> I<host>:I<port>
+
+This specifies the host and optional port to connect to. It is possible to
+select the host and port using the optional target positional argument instead.
+If neither this nor the target positional argument are specified then an attempt
+is made to connect to the local host on port 4433.
+
+=item B<-host> I<hostname>
+
+Host to connect to; use B<-connect> instead.
+
+=item B<-port> I<port>
+
+Connect to the specified port; use B<-connect> instead.
+
+=item B<-bind> I<host:port>
+
+This specifies the host address and or port to bind as the source for the
+connection. For Unix-domain sockets the port is ignored and the host is
+used as the source socket address.
+
+=item B<-proxy> I<host:port>
+
+When used with the B<-connect> flag, the program uses the host and port
+specified with this flag and issues an HTTP CONNECT command to connect
+to the desired server.
+
+=item B<-proxy_user> I<userid>
+
+When used with the B<-proxy> flag, the program will attempt to authenticate
+with the specified proxy using basic (base64) authentication.
+NB: Basic authentication is insecure; the credentials are sent to the proxy
+in easily reversible base64 encoding before any TLS/SSL session is established.
+Therefore, these credentials are easily recovered by anyone able to sniff/trace
+the network. Use with caution.
+
+=item B<-proxy_pass> I<arg>
+
+The proxy password source, used with the B<-proxy_user> flag.
+For more information about the format of B<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-unix> I<path>
+
+Connect over the specified Unix-domain socket.
+
+=item B<-4>
+
+Use IPv4 only.
+
+=item B<-6>
+
+Use IPv6 only.
+
+=item B<-servername> I<name>
+
+Set the TLS SNI (Server Name Indication) extension in the ClientHello message to
+the given value.
+If B<-servername> is not provided, the TLS SNI extension will be populated with
+the name given to B<-connect> if it follows a DNS name format. If B<-connect> is
+not provided either, the SNI is set to "localhost".
+This is the default since OpenSSL 1.1.1.
+
+Even though SNI should normally be a DNS name and not an IP address, if
+B<-servername> is provided then that name will be sent, regardless of whether
+it is a DNS name or not.
+
+This option cannot be used in conjunction with B<-noservername>.
+
+=item B<-noservername>
+
+Suppresses sending of the SNI (Server Name Indication) extension in the
+ClientHello message. Cannot be used in conjunction with the B<-servername> or
+B<-dane_tlsa_domain> options.
+
+=item B<-cert> I<filename>
+
+The client certificate to use, if one is requested by the server.
+The default is not to use a certificate.
+
+The chain for the client certificate may be specified using B<-cert_chain>.
+
+=item B<-certform> B<DER>|B<PEM>|B<P12>
+
+The client certificate file format to use; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-cert_chain>
+
+A file or URI of untrusted certificates to use when attempting to build the
+certificate chain related to the certificate specified via the B<-cert> option.
+The input can be in PEM, DER, or PKCS#12 format.
+
+=item B<-build_chain>
+
+Specify whether the application should build the client certificate chain to be
+provided to the server.
+
+=item B<-CRL> I<filename>
+
+CRL file to use to check the server's certificate.
+
+=item B<-CRLform> B<DER>|B<PEM>
+
+The CRL file format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-crl_download>
+
+Download CRL from distribution points in the certificate.
+
+=item B<-key> I<filename>|I<uri>
+
+The client private key to use.
+If not specified then the certificate file will be used to read also the key.
+
+=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The key format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-pass> I<arg>
+
+the private key and certifiate file password source.
+For more information about the format of I<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-verify> I<depth>
+
+The verify depth to use. This specifies the maximum length of the
+server certificate chain and turns on server certificate verification.
+Currently the verify operation continues after errors so all the problems
+with a certificate chain can be seen. As a side effect the connection
+will never fail due to a server certificate verify failure.
+
+=item B<-verify_return_error>
+
+Return verification errors instead of continuing. This will typically
+abort the handshake with a fatal error.
+
+=item B<-verify_quiet>
+
+Limit verify output to only errors.
+
+=item B<-verifyCAfile> I<filename>
+
+A file in PEM format containing trusted certificates to use
+for verifying the server's certificate.
+
+=item B<-verifyCApath> I<dir>
+
+A directory containing trusted certificates to use
+for verifying the server's certificate.
+This directory must be in "hash format",
+see L<openssl-verify(1)> for more information.
+
+=item B<-verifyCAstore> I<uri>
+
+The URI of a store containing trusted certificates to use
+for verifying the server's certificate.
+
+=item B<-chainCAfile> I<file>
+
+A file in PEM format containing trusted certificates to use
+when attempting to build the client certificate chain.
+
+=item B<-chainCApath> I<directory>
+
+A directory containing trusted certificates to use
+for building the client certificate chain provided to the server.
+This directory must be in "hash format",
+see L<openssl-verify(1)> for more information.
+
+=item B<-chainCAstore> I<uri>
+
+The URI of a store containing trusted certificates to use
+when attempting to build the client certificate chain.
+The URI may indicate a single certificate, as well as a collection of them.
+With URIs in the C<file:> scheme, this acts as B<-chainCAfile> or
+B<-chainCApath>, depending on if the URI indicates a directory or a
+single file.
+See L<ossl_store-file(7)> for more information on the C<file:> scheme.
+
+=item B<-requestCAfile> I<file>
+
+A file containing a list of certificates whose subject names will be sent
+to the server in the B<certificate_authorities> extension. Only supported
+for TLS 1.3
+
+=item B<-dane_tlsa_domain> I<domain>
+
+Enable RFC6698/RFC7671 DANE TLSA authentication and specify the
+TLSA base domain which becomes the default SNI hint and the primary
+reference identifier for hostname checks. This must be used in
+combination with at least one instance of the B<-dane_tlsa_rrdata>
+option below.
+
+When DANE authentication succeeds, the diagnostic output will include
+the lowest (closest to 0) depth at which a TLSA record authenticated
+a chain certificate. When that TLSA record is a "2 1 0" trust
+anchor public key that signed (rather than matched) the top-most
+certificate of the chain, the result is reported as "TA public key
+verified". Otherwise, either the TLSA record "matched TA certificate"
+at a positive depth or else "matched EE certificate" at depth 0.
+
+=item B<-dane_tlsa_rrdata> I<rrdata>
+
+Use one or more times to specify the RRDATA fields of the DANE TLSA
+RRset associated with the target service. The I<rrdata> value is
+specified in "presentation form", that is four whitespace separated
+fields that specify the usage, selector, matching type and associated
+data, with the last of these encoded in hexadecimal. Optional
+whitespace is ignored in the associated data field. For example:
+
+ $ openssl s_client -brief -starttls smtp \
+ -connect smtp.example.com:25 \
+ -dane_tlsa_domain smtp.example.com \
+ -dane_tlsa_rrdata "2 1 1
+ B111DD8A1C2091A89BD4FD60C57F0716CCE50FEEFF8137CDBEE0326E 02CF362B" \
+ -dane_tlsa_rrdata "2 1 1
+ 60B87575447DCBA2A36B7D11AC09FB24A9DB406FEE12D2CC90180517 616E8A18"
+ ...
+ Verification: OK
+ Verified peername: smtp.example.com
+ DANE TLSA 2 1 1 ...ee12d2cc90180517616e8a18 matched TA certificate at depth 1
+ ...
+
+=item B<-dane_ee_no_namechecks>
+
+This disables server name checks when authenticating via DANE-EE(3) TLSA
+records.
+For some applications, primarily web browsers, it is not safe to disable name
+checks due to "unknown key share" attacks, in which a malicious server can
+convince a client that a connection to a victim server is instead a secure
+connection to the malicious server.
+The malicious server may then be able to violate cross-origin scripting
+restrictions.
+Thus, despite the text of RFC7671, name checks are by default enabled for
+DANE-EE(3) TLSA records, and can be disabled in applications where it is safe
+to do so.
+In particular, SMTP and XMPP clients should set this option as SRV and MX
+records already make it possible for a remote domain to redirect client
+connections to any server of its choice, and in any case SMTP and XMPP clients
+do not execute scripts downloaded from remote servers.
+
+=item B<-reconnect>
+
+Reconnects to the same server 5 times using the same session ID, this can
+be used as a test that session caching is working.
+
+=item B<-showcerts>
+
+Displays the server certificate list as sent by the server: it only consists of
+certificates the server has sent (in the order the server has sent them). It is
+B<not> a verified chain.
+
+=item B<-prexit>
+
+Print session information when the program exits. This will always attempt
+to print out information even if the connection fails. Normally information
+will only be printed out once if the connection succeeds. This option is useful
+because the cipher in use may be renegotiated or the connection may fail
+because a client certificate is required or is requested only after an
+attempt is made to access a certain URL. Note: the output produced by this
+option is not always accurate because a connection might never have been
+established.
+
+=item B<-state>
+
+Prints out the SSL session states.
+
+=item B<-debug>
+
+Print extensive debugging information including a hex dump of all traffic.
+
+=item B<-nocommands>
+
+Do not use interactive command letters.
+
+=item B<-security_debug>
+
+Enable security debug messages.
+
+=item B<-security_debug_verbose>
+
+Output more security debug output.
+
+=item B<-msg>
+
+Show protocol messages.
+
+=item B<-timeout>
+
+Enable send/receive timeout on DTLS connections.
+
+=item B<-mtu> I<size>
+
+Set MTU of the link layer to the specified size.
+
+=item B<-no_etm>
+
+Disable Encrypt-then-MAC negotiation.
+
+=item B<-keymatexport> I<label>
+
+Export keying material using the specified label.
+
+=item B<-keymatexportlen> I<len>
+
+Export the specified number of bytes of keying material; default is 20.
+
+Show all protocol messages with hex dump.
+
+=item B<-trace>
+
+Show verbose trace output of protocol messages.
+
+=item B<-msgfile> I<filename>
+
+File to send output of B<-msg> or B<-trace> to, default standard output.
+
+=item B<-nbio_test>
+
+Tests nonblocking I/O
+
+=item B<-nbio>
+
+Turns on nonblocking I/O
+
+=item B<-crlf>
+
+This option translated a line feed from the terminal into CR+LF as required
+by some servers.
+
+=item B<-ign_eof>
+
+Inhibit shutting down the connection when end of file is reached in the
+input.
+
+=item B<-quiet>
+
+Inhibit printing of session and certificate information. This implicitly
+turns on B<-ign_eof> as well.
+
+=item B<-no_ign_eof>
+
+Shut down the connection when end of file is reached in the input.
+Can be used to override the implicit B<-ign_eof> after B<-quiet>.
+
+=item B<-psk_identity> I<identity>
+
+Use the PSK identity I<identity> when using a PSK cipher suite.
+The default value is "Client_identity" (without the quotes).
+
+=item B<-psk> I<key>
+
+Use the PSK key I<key> when using a PSK cipher suite. The key is
+given as a hexadecimal number without leading 0x, for example -psk
+1a2b3c4d.
+This option must be provided in order to use a PSK cipher.
+
+=item B<-psk_session> I<file>
+
+Use the pem encoded SSL_SESSION data stored in I<file> as the basis of a PSK.
+Note that this will only work if TLSv1.3 is negotiated.
+
+=item B<-sctp>
+
+Use SCTP for the transport protocol instead of UDP in DTLS. Must be used in
+conjunction with B<-dtls>, B<-dtls1> or B<-dtls1_2>. This option is only
+available where OpenSSL has support for SCTP enabled.
+
+=item B<-sctp_label_bug>
+
+Use the incorrect behaviour of older OpenSSL implementations when computing
+endpoint-pair shared secrets for DTLS/SCTP. This allows communication with
+older broken implementations but breaks interoperability with correct
+implementations. Must be used in conjunction with B<-sctp>. This option is only
+available where OpenSSL has support for SCTP enabled.
+
+=item B<-fallback_scsv>
+
+Send TLS_FALLBACK_SCSV in the ClientHello.
+
+=item B<-async>
+
+Switch on asynchronous mode. Cryptographic operations will be performed
+asynchronously. This will only have an effect if an asynchronous capable engine
+is also used via the B<-engine> option. For test purposes the dummy async engine
+(dasync) can be used (if available).
+
+=item B<-maxfraglen> I<len>
+
+Enable Maximum Fragment Length Negotiation; allowed values are
+C<512>, C<1024>, C<2048>, and C<4096>.
+
+=item B<-max_send_frag> I<int>
+
+The maximum size of data fragment to send.
+See L<SSL_CTX_set_max_send_fragment(3)> for further information.
+
+=item B<-split_send_frag> I<int>
+
+The size used to split data for encrypt pipelines. If more data is written in
+one go than this value then it will be split into multiple pipelines, up to the
+maximum number of pipelines defined by max_pipelines. This only has an effect if
+a suitable cipher suite has been negotiated, an engine that supports pipelining
+has been loaded, and max_pipelines is greater than 1. See
+L<SSL_CTX_set_split_send_fragment(3)> for further information.
+
+=item B<-max_pipelines> I<int>
+
+The maximum number of encrypt/decrypt pipelines to be used. This will only have
+an effect if an engine has been loaded that supports pipelining (e.g. the dasync
+engine) and a suitable cipher suite has been negotiated. The default value is 1.
+See L<SSL_CTX_set_max_pipelines(3)> for further information.
+
+=item B<-read_buf> I<int>
+
+The default read buffer size to be used for connections. This will only have an
+effect if the buffer size is larger than the size that would otherwise be used
+and pipelining is in use (see L<SSL_CTX_set_default_read_buffer_len(3)> for
+further information).
+
+=item B<-ignore_unexpected_eof>
+
+Some TLS implementations do not send the mandatory close_notify alert on
+shutdown. If the application tries to wait for the close_notify alert but the
+peer closes the connection without sending it, an error is generated. When this
+option is enabled the peer does not need to send the close_notify alert and a
+closed connection will be treated as if the close_notify alert was received.
+For more information on shutting down a connection, see L<SSL_shutdown(3)>.
+
+=item B<-bugs>
+
+There are several known bugs in SSL and TLS implementations. Adding this
+option enables various workarounds.
+
+=item B<-comp>
+
+Enables support for SSL/TLS compression.
+This option was introduced in OpenSSL 1.1.0.
+TLS compression is not recommended and is off by default as of
+OpenSSL 1.1.0.
+
+=item B<-no_comp>
+
+Disables support for SSL/TLS compression.
+TLS compression is not recommended and is off by default as of
+OpenSSL 1.1.0.
+
+=item B<-brief>
+
+Only provide a brief summary of connection parameters instead of the
+normal verbose output.
+
+=item B<-sigalgs> I<sigalglist>
+
+Specifies the list of signature algorithms that are sent by the client.
+The server selects one entry in the list based on its preferences.
+For example strings, see L<SSL_CTX_set1_sigalgs(3)>
+
+=item B<-curves> I<curvelist>
+
+Specifies the list of supported curves to be sent by the client. The curve is
+ultimately selected by the server. For a list of all curves, use:
+
+ $ openssl ecparam -list_curves
+
+=item B<-cipher> I<cipherlist>
+
+This allows the TLSv1.2 and below cipher list sent by the client to be modified.
+This list will be combined with any TLSv1.3 ciphersuites that have been
+configured. Although the server determines which ciphersuite is used it should
+take the first supported cipher in the list sent by the client. See
+L<openssl-ciphers(1)> for more information.
+
+=item B<-ciphersuites> I<val>
+
+This allows the TLSv1.3 ciphersuites sent by the client to be modified. This
+list will be combined with any TLSv1.2 and below ciphersuites that have been
+configured. Although the server determines which cipher suite is used it should
+take the first supported cipher in the list sent by the client. See
+L<openssl-ciphers(1)> for more information. The format for this list is a simple
+colon (":") separated list of TLSv1.3 ciphersuite names.
+
+=item B<-starttls> I<protocol>
+
+Send the protocol-specific message(s) to switch to TLS for communication.
+I<protocol> is a keyword for the intended protocol. Currently, the only
+supported keywords are "smtp", "pop3", "imap", "ftp", "xmpp", "xmpp-server",
+"irc", "postgres", "mysql", "lmtp", "nntp", "sieve" and "ldap".
+
+=item B<-xmpphost> I<hostname>
+
+This option, when used with "-starttls xmpp" or "-starttls xmpp-server",
+specifies the host for the "to" attribute of the stream element.
+If this option is not specified, then the host specified with "-connect"
+will be used.
+
+This option is an alias of the B<-name> option for "xmpp" and "xmpp-server".
+
+=item B<-name> I<hostname>
+
+This option is used to specify hostname information for various protocols
+used with B<-starttls> option. Currently only "xmpp", "xmpp-server",
+"smtp" and "lmtp" can utilize this B<-name> option.
+
+If this option is used with "-starttls xmpp" or "-starttls xmpp-server",
+if specifies the host for the "to" attribute of the stream element. If this
+option is not specified, then the host specified with "-connect" will be used.
+
+If this option is used with "-starttls lmtp" or "-starttls smtp", it specifies
+the name to use in the "LMTP LHLO" or "SMTP EHLO" message, respectively. If
+this option is not specified, then "mail.example.com" will be used.
+
+=item B<-tlsextdebug>
+
+Print out a hex dump of any TLS extensions received from the server.
+
+=item B<-no_ticket>
+
+Disable RFC4507bis session ticket support.
+
+=item B<-sess_out> I<filename>
+
+Output SSL session to I<filename>.
+
+=item B<-sess_in> I<filename>
+
+Load SSL session from I<filename>. The client will attempt to resume a
+connection from this session.
+
+=item B<-serverinfo> I<types>
+
+A list of comma-separated TLS Extension Types (numbers between 0 and
+65535). Each type will be sent as an empty ClientHello TLS Extension.
+The server's response (if any) will be encoded and displayed as a PEM
+file.
+
+=item B<-status>
+
+Sends a certificate status request to the server (OCSP stapling). The server
+response (if any) is printed out.
+
+=item B<-alpn> I<protocols>, B<-nextprotoneg> I<protocols>
+
+These flags enable the Enable the Application-Layer Protocol Negotiation
+or Next Protocol Negotiation (NPN) extension, respectively. ALPN is the
+IETF standard and replaces NPN.
+The I<protocols> list is a comma-separated list of protocol names that
+the client should advertise support for. The list should contain the most
+desirable protocols first. Protocol names are printable ASCII strings,
+for example "http/1.1" or "spdy/3".
+An empty list of protocols is treated specially and will cause the
+client to advertise support for the TLS extension but disconnect just
+after receiving ServerHello with a list of server supported protocols.
+The flag B<-nextprotoneg> cannot be specified if B<-tls1_3> is used.
+
+=item B<-ct>, B<-noct>
+
+Use one of these two options to control whether Certificate Transparency (CT)
+is enabled (B<-ct>) or disabled (B<-noct>).
+If CT is enabled, signed certificate timestamps (SCTs) will be requested from
+the server and reported at handshake completion.
+
+Enabling CT also enables OCSP stapling, as this is one possible delivery method
+for SCTs.
+
+=item B<-ctlogfile>
+
+A file containing a list of known Certificate Transparency logs. See
+L<SSL_CTX_set_ctlog_list_file(3)> for the expected file format.
+
+=item B<-keylogfile> I<file>
+
+Appends TLS secrets to the specified keylog file such that external programs
+(like Wireshark) can decrypt TLS connections.
+
+=item B<-early_data> I<file>
+
+Reads the contents of the specified file and attempts to send it as early data
+to the server. This will only work with resumed sessions that support early
+data and when the server accepts the early data.
+
+=item B<-enable_pha>
+
+For TLSv1.3 only, send the Post-Handshake Authentication extension. This will
+happen whether or not a certificate has been provided via B<-cert>.
+
+=item B<-use_srtp> I<value>
+
+Offer SRTP key management, where B<value> is a colon-separated profile list.
+
+=item B<-srpuser> I<value>
+
+Set the SRP username to the specified value. This option is deprecated.
+
+=item B<-srppass> I<value>
+
+Set the SRP password to the specified value. This option is deprecated.
+
+=item B<-srp_lateuser>
+
+SRP username for the second ClientHello message. This option is deprecated.
+
+=item B<-srp_moregroups> This option is deprecated.
+
+Tolerate other than the known B<g> and B<N> values.
+
+=item B<-srp_strength> I<number>
+
+Set the minimal acceptable length, in bits, for B<N>. This option is
+deprecated.
+
+{- $OpenSSL::safe::opt_version_item -}
+
+{- $OpenSSL::safe::opt_name_item -}
+
+{- $OpenSSL::safe::opt_x_item -}
+
+{- $OpenSSL::safe::opt_trust_item -}
+
+{- $OpenSSL::safe::opt_s_item -}
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- output_off() if $disabled{"deprecated-3.0"}; "" -}
+=item B<-ssl_client_engine> I<id>
+
+Specify engine to be used for client certificate operations.
+{- output_on() if $disabled{"deprecated-3.0"}; "" -}
+
+{- $OpenSSL::safe::opt_v_item -}
+
+Verification errors are displayed, for debugging, but the command will
+proceed unless the B<-verify_return_error> option is used.
+
+=item I<host>:I<port>
+
+Rather than providing B<-connect>, the target hostname and optional port may
+be provided as a single positional argument after all options. If neither this
+nor B<-connect> are provided, falls back to attempting to connect to
+I<localhost> on port I<4433>.
+
+=back
+
+=head1 CONNECTED COMMANDS
+
+If a connection is established with an SSL server then any data received
+from the server is displayed and any key presses will be sent to the
+server. If end of file is reached then the connection will be closed down. When
+used interactively (which means neither B<-quiet> nor B<-ign_eof> have been
+given), then certain commands are also recognized which perform special
+operations. These commands are a letter which must appear at the start of a
+line. They are listed below.
+
+=over 4
+
+=item B<Q>
+
+End the current SSL connection and exit.
+
+=item B<R>
+
+Renegotiate the SSL session (TLSv1.2 and below only).
+
+=item B<k>
+
+Send a key update message to the server (TLSv1.3 only)
+
+=item B<K>
+
+Send a key update message to the server and request one back (TLSv1.3 only)
+
+=back
+
+=head1 NOTES
+
+This command can be used to debug SSL servers. To connect to an SSL HTTP
+server the command:
+
+ openssl s_client -connect servername:443
+
+would typically be used (https uses port 443). If the connection succeeds
+then an HTTP command can be given such as "GET /" to retrieve a web page.
+
+If the handshake fails then there are several possible causes, if it is
+nothing obvious like no client certificate then the B<-bugs>,
+B<-ssl3>, B<-tls1>, B<-no_ssl3>, B<-no_tls1> options can be tried
+in case it is a buggy server. In particular you should play with these
+options B<before> submitting a bug report to an OpenSSL mailing list.
+
+A frequent problem when attempting to get client certificates working
+is that a web client complains it has no certificates or gives an empty
+list to choose from. This is normally because the server is not sending
+the clients certificate authority in its "acceptable CA list" when it
+requests a certificate. By using this command, the CA list can be viewed
+and checked. However, some servers only request client authentication
+after a specific URL is requested. To obtain the list in this case it
+is necessary to use the B<-prexit> option and send an HTTP request
+for an appropriate page.
+
+If a certificate is specified on the command line using the B<-cert>
+option it will not be used unless the server specifically requests
+a client certificate. Therefore, merely including a client certificate
+on the command line is no guarantee that the certificate works.
+
+If there are problems verifying a server certificate then the
+B<-showcerts> option can be used to show all the certificates sent by the
+server.
+
+This command is a test tool and is designed to continue the
+handshake after any certificate verification errors. As a result it will
+accept any certificate chain (trusted or not) sent by the peer. Non-test
+applications should B<not> do this as it makes them vulnerable to a MITM
+attack. This behaviour can be changed by with the B<-verify_return_error>
+option: any verify errors are then returned aborting the handshake.
+
+The B<-bind> option may be useful if the server or a firewall requires
+connections to come from some particular address and or port.
+
+=head1 BUGS
+
+Because this program has a lot of options and also because some of the
+techniques used are rather old, the C source for this command is rather
+hard to read and not a model of how things should be done.
+A typical SSL client program would be much simpler.
+
+The B<-prexit> option is a bit of a hack. We should really report
+information whenever a session is renegotiated.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-sess_id(1)>,
+L<openssl-s_server(1)>,
+L<openssl-ciphers(1)>,
+L<SSL_CONF_cmd(3)>,
+L<SSL_CTX_set_max_send_fragment(3)>,
+L<SSL_CTX_set_split_send_fragment(3)>,
+L<SSL_CTX_set_max_pipelines(3)>,
+L<ossl_store-file(7)>
+
+=head1 HISTORY
+
+The B<-no_alt_chains> option was added in OpenSSL 1.1.0.
+The B<-name> option was added in OpenSSL 1.1.1.
+
+The B<-certform> option has become obsolete in OpenSSL 3.0.0 and has no effect.
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-s_server.pod.in b/doc/man1/openssl-s_server.pod.in
new file mode 100644
index 000000000000..319f1e342b48
--- /dev/null
+++ b/doc/man1/openssl-s_server.pod.in
@@ -0,0 +1,940 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-s_server - SSL/TLS server program
+
+=head1 SYNOPSIS
+
+B<openssl> B<s_server>
+[B<-help>]
+[B<-port> I<+int>]
+[B<-accept> I<val>]
+[B<-unix> I<val>]
+[B<-4>]
+[B<-6>]
+[B<-unlink>]
+[B<-context> I<val>]
+[B<-verify> I<int>]
+[B<-Verify> I<int>]
+[B<-cert> I<infile>]
+[B<-cert2> I<infile>]
+[B<-certform> B<DER>|B<PEM>|B<P12>]
+[B<-cert_chain> I<infile>]
+[B<-build_chain>]
+[B<-serverinfo> I<val>]
+[B<-key> I<filename>|I<uri>]
+[B<-key2> I<filename>|I<uri>]
+[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-pass> I<val>]
+[B<-dcert> I<infile>]
+[B<-dcertform> B<DER>|B<PEM>|B<P12>]
+[B<-dcert_chain> I<infile>]
+[B<-dkey> I<filename>|I<uri>]
+[B<-dkeyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-dpass> I<val>]
+[B<-nbio_test>]
+[B<-crlf>]
+[B<-debug>]
+[B<-msg>]
+[B<-msgfile> I<outfile>]
+[B<-state>]
+[B<-nocert>]
+[B<-quiet>]
+[B<-no_resume_ephemeral>]
+[B<-www>]
+[B<-WWW>]
+[B<-http_server_binmode>]
+[B<-no_ca_names>]
+[B<-ignore_unexpected_eof>]
+[B<-servername>]
+[B<-servername_fatal>]
+[B<-tlsextdebug>]
+[B<-HTTP>]
+[B<-id_prefix> I<val>]
+[B<-keymatexport> I<val>]
+[B<-keymatexportlen> I<+int>]
+[B<-CRL> I<infile>]
+[B<-CRLform> B<DER>|B<PEM>]
+[B<-crl_download>]
+[B<-chainCAfile> I<infile>]
+[B<-chainCApath> I<dir>]
+[B<-chainCAstore> I<uri>]
+[B<-verifyCAfile> I<infile>]
+[B<-verifyCApath> I<dir>]
+[B<-verifyCAstore> I<uri>]
+[B<-no_cache>]
+[B<-ext_cache>]
+[B<-verify_return_error>]
+[B<-verify_quiet>]
+[B<-ign_eof>]
+[B<-no_ign_eof>]
+[B<-no_etm>]
+[B<-status>]
+[B<-status_verbose>]
+[B<-status_timeout> I<int>]
+[B<-proxy> I<[http[s]://][userinfo@]host[:port][/path]>]
+[B<-no_proxy> I<addresses>]
+[B<-status_url> I<val>]
+[B<-status_file> I<infile>]
+[B<-ssl_config> I<val>]
+[B<-trace>]
+[B<-security_debug>]
+[B<-security_debug_verbose>]
+[B<-brief>]
+[B<-rev>]
+[B<-async>]
+[B<-max_send_frag> I<+int>]
+[B<-split_send_frag> I<+int>]
+[B<-max_pipelines> I<+int>]
+[B<-naccept> I<+int>]
+[B<-read_buf> I<+int>]
+[B<-bugs>]
+[B<-no_comp>]
+[B<-comp>]
+[B<-no_ticket>]
+[B<-serverpref>]
+[B<-legacy_renegotiation>]
+[B<-no_renegotiation>]
+[B<-no_resumption_on_reneg>]
+[B<-allow_no_dhe_kex>]
+[B<-prioritize_chacha>]
+[B<-strict>]
+[B<-sigalgs> I<val>]
+[B<-client_sigalgs> I<val>]
+[B<-groups> I<val>]
+[B<-curves> I<val>]
+[B<-named_curve> I<val>]
+[B<-cipher> I<val>]
+[B<-ciphersuites> I<val>]
+[B<-dhparam> I<infile>]
+[B<-record_padding> I<val>]
+[B<-debug_broken_protocol>]
+[B<-nbio>]
+[B<-psk_identity> I<val>]
+[B<-psk_hint> I<val>]
+[B<-psk> I<val>]
+[B<-psk_session> I<file>]
+[B<-srpvfile> I<infile>]
+[B<-srpuserseed> I<val>]
+[B<-timeout>]
+[B<-mtu> I<+int>]
+[B<-listen>]
+[B<-sctp>]
+[B<-sctp_label_bug>]
+[B<-use_srtp> I<val>]
+[B<-no_dhe>]
+[B<-nextprotoneg> I<val>]
+[B<-alpn> I<val>]
+[B<-sendfile>]
+[B<-keylogfile> I<outfile>]
+[B<-recv_max_early_data> I<int>]
+[B<-max_early_data> I<int>]
+[B<-early_data>]
+[B<-stateless>]
+[B<-anti_replay>]
+[B<-no_anti_replay>]
+[B<-num_tickets>]
+{- $OpenSSL::safe::opt_name_synopsis -}
+{- $OpenSSL::safe::opt_version_synopsis -}
+{- $OpenSSL::safe::opt_v_synopsis -}
+{- $OpenSSL::safe::opt_s_synopsis -}
+{- $OpenSSL::safe::opt_x_synopsis -}
+{- $OpenSSL::safe::opt_trust_synopsis -}
+{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command implements a generic SSL/TLS server which
+listens for connections on a given port using SSL/TLS.
+
+=head1 OPTIONS
+
+In addition to the options below, this command also supports
+the common and server only options documented
+L<SSL_CONF_cmd(3)/Supported Command Line Commands>
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-port> I<+int>
+
+The TCP port to listen on for connections. If not specified 4433 is used.
+
+=item B<-accept> I<val>
+
+The optional TCP host and port to listen on for connections. If not specified, *:4433 is used.
+
+=item B<-unix> I<val>
+
+Unix domain socket to accept on.
+
+=item B<-4>
+
+Use IPv4 only.
+
+=item B<-6>
+
+Use IPv6 only.
+
+=item B<-unlink>
+
+For -unix, unlink any existing socket first.
+
+=item B<-context> I<val>
+
+Sets the SSL context id. It can be given any string value. If this option
+is not present a default value will be used.
+
+=item B<-verify> I<int>, B<-Verify> I<int>
+
+The verify depth to use. This specifies the maximum length of the
+client certificate chain and makes the server request a certificate from
+the client. With the B<-verify> option a certificate is requested but the
+client does not have to send one, with the B<-Verify> option the client
+must supply a certificate or an error occurs.
+
+If the cipher suite cannot request a client certificate (for example an
+anonymous cipher suite or PSK) this option has no effect.
+
+=item B<-cert> I<infile>
+
+The certificate to use, most servers cipher suites require the use of a
+certificate and some require a certificate with a certain public key type:
+for example the DSS cipher suites require a certificate containing a DSS
+(DSA) key. If not specified then the filename F<server.pem> will be used.
+
+=item B<-cert2> I<infile>
+
+The certificate file to use for servername; default is C<server2.pem>.
+
+=item B<-certform> B<DER>|B<PEM>|B<P12>
+
+The server certificate file format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-cert_chain>
+
+A file or URI of untrusted certificates to use when attempting to build the
+certificate chain related to the certificate specified via the B<-cert> option.
+The input can be in PEM, DER, or PKCS#12 format.
+
+=item B<-build_chain>
+
+Specify whether the application should build the server certificate chain to be
+provided to the client.
+
+=item B<-serverinfo> I<val>
+
+A file containing one or more blocks of PEM data. Each PEM block
+must encode a TLS ServerHello extension (2 bytes type, 2 bytes length,
+followed by "length" bytes of extension data). If the client sends
+an empty TLS ClientHello extension matching the type, the corresponding
+ServerHello extension will be returned.
+
+=item B<-key> I<filename>|I<uri>
+
+The private key to use. If not specified then the certificate file will
+be used.
+
+=item B<-key2> I<filename>|I<uri>
+
+The private Key file to use for servername if not given via B<-cert2>.
+
+=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The key format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-pass> I<val>
+
+The private key and certificate file password source.
+For more information about the format of I<val>,
+see L<openssl-passphrase-options(1)>.
+
+=item B<-dcert> I<infile>, B<-dkey> I<filename>|I<uri>
+
+Specify an additional certificate and private key, these behave in the
+same manner as the B<-cert> and B<-key> options except there is no default
+if they are not specified (no additional certificate and key is used). As
+noted above some cipher suites require a certificate containing a key of
+a certain type. Some cipher suites need a certificate carrying an RSA key
+and some a DSS (DSA) key. By using RSA and DSS certificates and keys
+a server can support clients which only support RSA or DSS cipher suites
+by using an appropriate certificate.
+
+=item B<-dcert_chain>
+
+A file or URI of untrusted certificates to use when attempting to build the
+server certificate chain when a certificate specified via the B<-dcert> option
+is in use.
+The input can be in PEM, DER, or PKCS#12 format.
+
+=item B<-dcertform> B<DER>|B<PEM>|B<P12>
+
+The format of the additional certificate file; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-dkeyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The format of the additional private key; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-dpass> I<val>
+
+The passphrase for the additional private key and certificate.
+For more information about the format of I<val>,
+see L<openssl-passphrase-options(1)>.
+
+=item B<-nbio_test>
+
+Tests non blocking I/O.
+
+=item B<-crlf>
+
+This option translated a line feed from the terminal into CR+LF.
+
+=item B<-debug>
+
+Print extensive debugging information including a hex dump of all traffic.
+
+=item B<-security_debug>
+
+Print output from SSL/TLS security framework.
+
+=item B<-security_debug_verbose>
+
+Print more output from SSL/TLS security framework
+
+=item B<-msg>
+
+Show all protocol messages with hex dump.
+
+=item B<-msgfile> I<outfile>
+
+File to send output of B<-msg> or B<-trace> to, default standard output.
+
+=item B<-state>
+
+Prints the SSL session states.
+
+=item B<-CRL> I<infile>
+
+The CRL file to use.
+
+=item B<-CRLform> B<DER>|B<PEM>
+
+The CRL file format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-crl_download>
+
+Download CRLs from distribution points given in CDP extensions of certificates
+
+=item B<-verifyCAfile> I<filename>
+
+A file in PEM format CA containing trusted certificates to use
+for verifying client certificates.
+
+=item B<-verifyCApath> I<dir>
+
+A directory containing trusted certificates to use
+for verifying client certificates.
+This directory must be in "hash format",
+see L<openssl-verify(1)> for more information.
+
+=item B<-verifyCAstore> I<uri>
+
+The URI of a store containing trusted certificates to use
+for verifying client certificates.
+
+=item B<-chainCAfile> I<file>
+
+A file in PEM format containing trusted certificates to use
+when attempting to build the server certificate chain.
+
+=item B<-chainCApath> I<dir>
+
+A directory containing trusted certificates to use
+for building the server certificate chain provided to the client.
+This directory must be in "hash format",
+see L<openssl-verify(1)> for more information.
+
+=item B<-chainCAstore> I<uri>
+
+The URI of a store containing trusted certificates to use
+for building the server certificate chain provided to the client.
+The URI may indicate a single certificate, as well as a collection of them.
+With URIs in the C<file:> scheme, this acts as B<-chainCAfile> or
+B<-chainCApath>, depending on if the URI indicates a directory or a
+single file.
+See L<ossl_store-file(7)> for more information on the C<file:> scheme.
+
+=item B<-nocert>
+
+If this option is set then no certificate is used. This restricts the
+cipher suites available to the anonymous ones (currently just anonymous
+DH).
+
+=item B<-quiet>
+
+Inhibit printing of session and certificate information.
+
+=item B<-no_resume_ephemeral>
+
+Disable caching and tickets if ephemeral (EC)DH is used.
+
+=item B<-tlsextdebug>
+
+Print a hex dump of any TLS extensions received from the server.
+
+=item B<-www>
+
+Sends a status message back to the client when it connects. This includes
+information about the ciphers used and various session parameters.
+The output is in HTML format so this option can be used with a web browser.
+The special URL C</renegcert> turns on client cert validation, and C</reneg>
+tells the server to request renegotiation.
+The B<-early_data> option cannot be used with this option.
+
+=item B<-WWW>, B<-HTTP>
+
+Emulates a simple web server. Pages will be resolved relative to the
+current directory, for example if the URL C<https://myhost/page.html> is
+requested the file F<./page.html> will be sent.
+If the B<-HTTP> flag is used, the files are sent directly, and should contain
+any HTTP response headers (including status response line).
+If the B<-WWW> option is used,
+the response headers are generated by the server, and the file extension is
+examined to determine the B<Content-Type> header.
+Extensions of C<html>, C<htm>, and C<php> are C<text/html> and all others are
+C<text/plain>.
+In addition, the special URL C</stats> will return status
+information like the B<-www> option.
+Neither of these options can be used in conjunction with B<-early_data>.
+
+=item B<-http_server_binmode>
+
+When acting as web-server (using option B<-WWW> or B<-HTTP>) open files requested
+by the client in binary mode.
+
+=item B<-no_ca_names>
+
+Disable TLS Extension CA Names. You may want to disable it for security reasons
+or for compatibility with some Windows TLS implementations crashing when this
+extension is larger than 1024 bytes.
+
+=item B<-ignore_unexpected_eof>
+
+Some TLS implementations do not send the mandatory close_notify alert on
+shutdown. If the application tries to wait for the close_notify alert but the
+peer closes the connection without sending it, an error is generated. When this
+option is enabled the peer does not need to send the close_notify alert and a
+closed connection will be treated as if the close_notify alert was received.
+For more information on shutting down a connection, see L<SSL_shutdown(3)>.
+
+=item B<-servername>
+
+Servername for HostName TLS extension.
+
+=item B<-servername_fatal>
+
+On servername mismatch send fatal alert (default: warning alert).
+
+=item B<-id_prefix> I<val>
+
+Generate SSL/TLS session IDs prefixed by I<val>. This is mostly useful
+for testing any SSL/TLS code (e.g. proxies) that wish to deal with multiple
+servers, when each of which might be generating a unique range of session
+IDs (e.g. with a certain prefix).
+
+=item B<-keymatexport>
+
+Export keying material using label.
+
+=item B<-keymatexportlen>
+
+Export the given number of bytes of keying material; default 20.
+
+=item B<-no_cache>
+
+Disable session cache.
+
+=item B<-ext_cache>.
+
+Disable internal cache, set up and use external cache.
+
+=item B<-verify_return_error>
+
+Verification errors normally just print a message but allow the
+connection to continue, for debugging purposes.
+If this option is used, then verification errors close the connection.
+
+=item B<-verify_quiet>
+
+No verify output except verify errors.
+
+=item B<-ign_eof>
+
+Ignore input EOF (default: when B<-quiet>).
+
+=item B<-no_ign_eof>
+
+Do not ignore input EOF.
+
+=item B<-no_etm>
+
+Disable Encrypt-then-MAC negotiation.
+
+=item B<-status>
+
+Enables certificate status request support (aka OCSP stapling).
+
+=item B<-status_verbose>
+
+Enables certificate status request support (aka OCSP stapling) and gives
+a verbose printout of the OCSP response.
+
+=item B<-status_timeout> I<int>
+
+Sets the timeout for OCSP response to I<int> seconds.
+
+=item B<-proxy> I<[http[s]://][userinfo@]host[:port][/path]>
+
+The HTTP(S) proxy server to use for reaching the OCSP server unless B<-no_proxy>
+applies, see below.
+The proxy port defaults to 80 or 443 if the scheme is C<https>; apart from that
+the optional C<http://> or C<https://> prefix is ignored,
+as well as any userinfo and path components.
+Defaults to the environment variable C<http_proxy> if set, else C<HTTP_PROXY>
+in case no TLS is used, otherwise C<https_proxy> if set, else C<HTTPS_PROXY>.
+
+=item B<-no_proxy> I<addresses>
+
+List of IP addresses and/or DNS names of servers
+not to use an HTTP(S) proxy for, separated by commas and/or whitespace
+(where in the latter case the whole argument must be enclosed in "...").
+Default is from the environment variable C<no_proxy> if set, else C<NO_PROXY>.
+
+=item B<-status_url> I<val>
+
+Sets a fallback responder URL to use if no responder URL is present in the
+server certificate. Without this option an error is returned if the server
+certificate does not contain a responder address.
+The optional userinfo and fragment URL components are ignored.
+Any given query component is handled as part of the path component.
+
+=item B<-status_file> I<infile>
+
+Overrides any OCSP responder URLs from the certificate and always provides the
+OCSP Response stored in the file. The file must be in DER format.
+
+=item B<-ssl_config> I<val>
+
+Configure SSL_CTX using the given configuration value.
+
+=item B<-trace>
+
+Show verbose trace output of protocol messages.
+
+=item B<-brief>
+
+Provide a brief summary of connection parameters instead of the normal verbose
+output.
+
+=item B<-rev>
+
+Simple echo server that sends back received text reversed. Also sets B<-brief>.
+Cannot be used in conjunction with B<-early_data>.
+
+=item B<-async>
+
+Switch on asynchronous mode. Cryptographic operations will be performed
+asynchronously. This will only have an effect if an asynchronous capable engine
+is also used via the B<-engine> option. For test purposes the dummy async engine
+(dasync) can be used (if available).
+
+=item B<-max_send_frag> I<+int>
+
+The maximum size of data fragment to send.
+See L<SSL_CTX_set_max_send_fragment(3)> for further information.
+
+=item B<-split_send_frag> I<+int>
+
+The size used to split data for encrypt pipelines. If more data is written in
+one go than this value then it will be split into multiple pipelines, up to the
+maximum number of pipelines defined by max_pipelines. This only has an effect if
+a suitable cipher suite has been negotiated, an engine that supports pipelining
+has been loaded, and max_pipelines is greater than 1. See
+L<SSL_CTX_set_split_send_fragment(3)> for further information.
+
+=item B<-max_pipelines> I<+int>
+
+The maximum number of encrypt/decrypt pipelines to be used. This will only have
+an effect if an engine has been loaded that supports pipelining (e.g. the dasync
+engine) and a suitable cipher suite has been negotiated. The default value is 1.
+See L<SSL_CTX_set_max_pipelines(3)> for further information.
+
+=item B<-naccept> I<+int>
+
+The server will exit after receiving the specified number of connections,
+default unlimited.
+
+=item B<-read_buf> I<+int>
+
+The default read buffer size to be used for connections. This will only have an
+effect if the buffer size is larger than the size that would otherwise be used
+and pipelining is in use (see L<SSL_CTX_set_default_read_buffer_len(3)> for
+further information).
+
+=item B<-bugs>
+
+There are several known bugs in SSL and TLS implementations. Adding this
+option enables various workarounds.
+
+=item B<-no_comp>
+
+Disable negotiation of TLS compression.
+TLS compression is not recommended and is off by default as of
+OpenSSL 1.1.0.
+
+=item B<-comp>
+
+Enable negotiation of TLS compression.
+This option was introduced in OpenSSL 1.1.0.
+TLS compression is not recommended and is off by default as of
+OpenSSL 1.1.0.
+
+=item B<-no_ticket>
+
+Disable RFC4507bis session ticket support. This option has no effect if TLSv1.3
+is negotiated. See B<-num_tickets>.
+
+=item B<-num_tickets>
+
+Control the number of tickets that will be sent to the client after a full
+handshake in TLSv1.3. The default number of tickets is 2. This option does not
+affect the number of tickets sent after a resumption handshake.
+
+=item B<-serverpref>
+
+Use the server's cipher preferences, rather than the client's preferences.
+
+=item B<-prioritize_chacha>
+
+Prioritize ChaCha ciphers when preferred by clients. Requires B<-serverpref>.
+
+=item B<-no_resumption_on_reneg>
+
+Set the B<SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION> option.
+
+=item B<-client_sigalgs> I<val>
+
+Signature algorithms to support for client certificate authentication
+(colon-separated list).
+
+=item B<-named_curve> I<val>
+
+Specifies the elliptic curve to use. NOTE: this is single curve, not a list.
+For a list of all possible curves, use:
+
+ $ openssl ecparam -list_curves
+
+=item B<-cipher> I<val>
+
+This allows the list of TLSv1.2 and below ciphersuites used by the server to be
+modified. This list is combined with any TLSv1.3 ciphersuites that have been
+configured. When the client sends a list of supported ciphers the first client
+cipher also included in the server list is used. Because the client specifies
+the preference order, the order of the server cipherlist is irrelevant. See
+L<openssl-ciphers(1)> for more information.
+
+=item B<-ciphersuites> I<val>
+
+This allows the list of TLSv1.3 ciphersuites used by the server to be modified.
+This list is combined with any TLSv1.2 and below ciphersuites that have been
+configured. When the client sends a list of supported ciphers the first client
+cipher also included in the server list is used. Because the client specifies
+the preference order, the order of the server cipherlist is irrelevant. See
+L<openssl-ciphers(1)> command for more information. The format for this list is
+a simple colon (":") separated list of TLSv1.3 ciphersuite names.
+
+=item B<-dhparam> I<infile>
+
+The DH parameter file to use. The ephemeral DH cipher suites generate keys
+using a set of DH parameters. If not specified then an attempt is made to
+load the parameters from the server certificate file.
+If this fails then a static set of parameters hard coded into this command
+will be used.
+
+=item B<-nbio>
+
+Turns on non blocking I/O.
+
+=item B<-timeout>
+
+Enable timeouts.
+
+=item B<-mtu>
+
+Set link-layer MTU.
+
+=item B<-psk_identity> I<val>
+
+Expect the client to send PSK identity I<val> when using a PSK
+cipher suite, and warn if they do not. By default, the expected PSK
+identity is the string "Client_identity".
+
+=item B<-psk_hint> I<val>
+
+Use the PSK identity hint I<val> when using a PSK cipher suite.
+
+=item B<-psk> I<val>
+
+Use the PSK key I<val> when using a PSK cipher suite. The key is
+given as a hexadecimal number without leading 0x, for example -psk
+1a2b3c4d.
+This option must be provided in order to use a PSK cipher.
+
+=item B<-psk_session> I<file>
+
+Use the pem encoded SSL_SESSION data stored in I<file> as the basis of a PSK.
+Note that this will only work if TLSv1.3 is negotiated.
+
+=item B<-srpvfile>
+
+The verifier file for SRP.
+This option is deprecated.
+
+=item B<-srpuserseed>
+
+A seed string for a default user salt.
+This option is deprecated.
+
+=item B<-listen>
+
+This option can only be used in conjunction with one of the DTLS options above.
+With this option, this command will listen on a UDP port for incoming
+connections.
+Any ClientHellos that arrive will be checked to see if they have a cookie in
+them or not.
+Any without a cookie will be responded to with a HelloVerifyRequest.
+If a ClientHello with a cookie is received then this command will
+connect to that peer and complete the handshake.
+
+=item B<-sctp>
+
+Use SCTP for the transport protocol instead of UDP in DTLS. Must be used in
+conjunction with B<-dtls>, B<-dtls1> or B<-dtls1_2>. This option is only
+available where OpenSSL has support for SCTP enabled.
+
+=item B<-sctp_label_bug>
+
+Use the incorrect behaviour of older OpenSSL implementations when computing
+endpoint-pair shared secrets for DTLS/SCTP. This allows communication with
+older broken implementations but breaks interoperability with correct
+implementations. Must be used in conjunction with B<-sctp>. This option is only
+available where OpenSSL has support for SCTP enabled.
+
+=item B<-use_srtp>
+
+Offer SRTP key management with a colon-separated profile list.
+
+=item B<-no_dhe>
+
+If this option is set then no DH parameters will be loaded effectively
+disabling the ephemeral DH cipher suites.
+
+=item B<-alpn> I<val>, B<-nextprotoneg> I<val>
+
+These flags enable the Application-Layer Protocol Negotiation
+or Next Protocol Negotiation (NPN) extension, respectively. ALPN is the
+IETF standard and replaces NPN.
+The I<val> list is a comma-separated list of supported protocol
+names. The list should contain the most desirable protocols first.
+Protocol names are printable ASCII strings, for example "http/1.1" or
+"spdy/3".
+The flag B<-nextprotoneg> cannot be specified if B<-tls1_3> is used.
+
+=item B<-sendfile>
+
+If this option is set and KTLS is enabled, SSL_sendfile() will be used
+instead of BIO_write() to send the HTTP response requested by a client.
+This option is only valid if B<-WWW> or B<-HTTP> is specified.
+
+=item B<-keylogfile> I<outfile>
+
+Appends TLS secrets to the specified keylog file such that external programs
+(like Wireshark) can decrypt TLS connections.
+
+=item B<-max_early_data> I<int>
+
+Change the default maximum early data bytes that are specified for new sessions
+and any incoming early data (when used in conjunction with the B<-early_data>
+flag). The default value is approximately 16k. The argument must be an integer
+greater than or equal to 0.
+
+=item B<-recv_max_early_data> I<int>
+
+Specify the hard limit on the maximum number of early data bytes that will
+be accepted.
+
+=item B<-early_data>
+
+Accept early data where possible. Cannot be used in conjunction with B<-www>,
+B<-WWW>, B<-HTTP> or B<-rev>.
+
+=item B<-stateless>
+
+Require TLSv1.3 cookies.
+
+=item B<-anti_replay>, B<-no_anti_replay>
+
+Switches replay protection on or off, respectively. Replay protection is on by
+default unless overridden by a configuration file. When it is on, OpenSSL will
+automatically detect if a session ticket has been used more than once, TLSv1.3
+has been negotiated, and early data is enabled on the server. A full handshake
+is forced if a session ticket is used a second or subsequent time. Any early
+data that was sent will be rejected.
+
+{- $OpenSSL::safe::opt_name_item -}
+
+{- $OpenSSL::safe::opt_version_item -}
+
+{- $OpenSSL::safe::opt_s_item -}
+
+{- $OpenSSL::safe::opt_x_item -}
+
+{- $OpenSSL::safe::opt_trust_item -}
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+{- $OpenSSL::safe::opt_v_item -}
+
+If the server requests a client certificate, then
+verification errors are displayed, for debugging, but the command will
+proceed unless the B<-verify_return_error> option is used.
+
+=back
+
+=head1 CONNECTED COMMANDS
+
+If a connection request is established with an SSL client and neither the
+B<-www> nor the B<-WWW> option has been used then normally any data received
+from the client is displayed and any key presses will be sent to the client.
+
+Certain commands are also recognized which perform special operations. These
+commands are a letter which must appear at the start of a line. They are listed
+below.
+
+=over 4
+
+=item B<q>
+
+End the current SSL connection but still accept new connections.
+
+=item B<Q>
+
+End the current SSL connection and exit.
+
+=item B<r>
+
+Renegotiate the SSL session (TLSv1.2 and below only).
+
+=item B<R>
+
+Renegotiate the SSL session and request a client certificate (TLSv1.2 and below
+only).
+
+=item B<P>
+
+Send some plain text down the underlying TCP connection: this should
+cause the client to disconnect due to a protocol violation.
+
+=item B<S>
+
+Print out some session cache status information.
+
+=item B<k>
+
+Send a key update message to the client (TLSv1.3 only)
+
+=item B<K>
+
+Send a key update message to the client and request one back (TLSv1.3 only)
+
+=item B<c>
+
+Send a certificate request to the client (TLSv1.3 only)
+
+=back
+
+=head1 NOTES
+
+This command can be used to debug SSL clients. To accept connections
+from a web browser the command:
+
+ openssl s_server -accept 443 -www
+
+can be used for example.
+
+Although specifying an empty list of CAs when requesting a client certificate
+is strictly speaking a protocol violation, some SSL clients interpret this to
+mean any CA is acceptable. This is useful for debugging purposes.
+
+The session parameters can printed out using the L<openssl-sess_id(1)> command.
+
+=head1 BUGS
+
+Because this program has a lot of options and also because some of the
+techniques used are rather old, the C source for this command is rather
+hard to read and not a model of how things should be done.
+A typical SSL server program would be much simpler.
+
+The output of common ciphers is wrong: it just gives the list of ciphers that
+OpenSSL recognizes and the client supports.
+
+There should be a way for this command to print out details
+of any unknown cipher suites a client says it supports.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-sess_id(1)>,
+L<openssl-s_client(1)>,
+L<openssl-ciphers(1)>,
+L<SSL_CONF_cmd(3)>,
+L<SSL_CTX_set_max_send_fragment(3)>,
+L<SSL_CTX_set_split_send_fragment(3)>,
+L<SSL_CTX_set_max_pipelines(3)>,
+L<ossl_store-file(7)>
+
+=head1 HISTORY
+
+The -no_alt_chains option was added in OpenSSL 1.1.0.
+
+The
+-allow-no-dhe-kex and -prioritize_chacha options were added in OpenSSL 1.1.1.
+
+The B<-srpvfile>, B<-srpuserseed>, and B<-engine>
+option were deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-s_time.pod.in b/doc/man1/openssl-s_time.pod.in
new file mode 100644
index 000000000000..2b82cf1e9837
--- /dev/null
+++ b/doc/man1/openssl-s_time.pod.in
@@ -0,0 +1,198 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-s_time - SSL/TLS performance timing program
+
+=head1 SYNOPSIS
+
+B<openssl> B<s_time>
+[B<-help>]
+[B<-connect> I<host>:I<port>]
+[B<-www> I<page>]
+[B<-cert> I<filename>]
+[B<-key> I<filename>]
+[B<-reuse>]
+[B<-new>]
+[B<-verify> I<depth>]
+[B<-time> I<seconds>]
+[B<-ssl3>]
+[B<-tls1>]
+[B<-tls1_1>]
+[B<-tls1_2>]
+[B<-tls1_3>]
+[B<-bugs>]
+[B<-cipher> I<cipherlist>]
+[B<-ciphersuites> I<val>]
+{- $OpenSSL::safe::opt_name_synopsis -}
+[B<-cafile> I<file>]
+{- $OpenSSL::safe::opt_trust_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command implements a generic SSL/TLS client which
+connects to a remote host using SSL/TLS. It can request a page from the server
+and includes the time to transfer the payload data in its timing measurements.
+It measures the number of connections within a given timeframe, the amount of
+data transferred (if any), and calculates the average time spent for one
+connection.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-connect> I<host>:I<port>
+
+This specifies the host and optional port to connect to.
+
+=item B<-www> I<page>
+
+This specifies the page to GET from the server. A value of '/' gets the
+F<index.html> page. If this parameter is not specified, then this command
+will only perform the handshake to establish SSL connections but not transfer
+any payload data.
+
+=item B<-cert> I<certname>
+
+The certificate to use, if one is requested by the server. The default is
+not to use a certificate. The file is in PEM format.
+
+=item B<-key> I<keyfile>
+
+The private key to use. If not specified then the certificate file will
+be used. The file is in PEM format.
+
+=item B<-verify> I<depth>
+
+The verify depth to use. This specifies the maximum length of the
+server certificate chain and turns on server certificate verification.
+Currently the verify operation continues after errors so all the problems
+with a certificate chain can be seen. As a side effect the connection
+will never fail due to a server certificate verify failure.
+
+=item B<-new>
+
+Performs the timing test using a new session ID for each connection.
+If neither B<-new> nor B<-reuse> are specified, they are both on by default
+and executed in sequence.
+
+=item B<-reuse>
+
+Performs the timing test using the same session ID; this can be used as a test
+that session caching is working. If neither B<-new> nor B<-reuse> are
+specified, they are both on by default and executed in sequence.
+
+=item B<-bugs>
+
+There are several known bugs in SSL and TLS implementations. Adding this
+option enables various workarounds.
+
+=item B<-cipher> I<cipherlist>
+
+This allows the TLSv1.2 and below cipher list sent by the client to be modified.
+This list will be combined with any TLSv1.3 ciphersuites that have been
+configured. Although the server determines which cipher suite is used it should
+take the first supported cipher in the list sent by the client. See
+L<openssl-ciphers(1)> for more information.
+
+=item B<-ciphersuites> I<val>
+
+This allows the TLSv1.3 ciphersuites sent by the client to be modified. This
+list will be combined with any TLSv1.2 and below ciphersuites that have been
+configured. Although the server determines which cipher suite is used it should
+take the first supported cipher in the list sent by the client. See
+L<openssl-ciphers(1)> for more information. The format for this list is a
+simple colon (":") separated list of TLSv1.3 ciphersuite names.
+
+=item B<-time> I<length>
+
+Specifies how long (in seconds) this command should establish connections
+and optionally transfer payload data from a server. Server and client
+performance and the link speed determine how many connections it
+can establish.
+
+{- $OpenSSL::safe::opt_name_item -}
+
+{- $OpenSSL::safe::opt_trust_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=item B<-cafile> I<file>
+
+This is an obsolete synonym for B<-CAfile>.
+
+=item B<-ssl3>, B<-tls1>, B<-tls1_1>, B<-tls1_2>, B<-tls1_3>
+
+See L<openssl(1)/TLS Version Options>.
+
+=back
+
+=head1 NOTES
+
+This command can be used to measure the performance of an SSL connection.
+To connect to an SSL HTTP server and get the default page the command
+
+ openssl s_time -connect servername:443 -www / -CApath yourdir -CAfile yourfile.pem -cipher commoncipher [-ssl3]
+
+would typically be used (https uses port 443). I<commoncipher> is a cipher to
+which both client and server can agree, see the L<openssl-ciphers(1)> command
+for details.
+
+If the handshake fails then there are several possible causes, if it is
+nothing obvious like no client certificate then the B<-bugs> and
+B<-ssl3> options can be tried
+in case it is a buggy server. In particular you should play with these
+options B<before> submitting a bug report to an OpenSSL mailing list.
+
+A frequent problem when attempting to get client certificates working
+is that a web client complains it has no certificates or gives an empty
+list to choose from. This is normally because the server is not sending
+the clients certificate authority in its "acceptable CA list" when it
+requests a certificate. By using L<openssl-s_client(1)> the CA list can be
+viewed and checked. However, some servers only request client authentication
+after a specific URL is requested. To obtain the list in this case it
+is necessary to use the B<-prexit> option of L<openssl-s_client(1)> and
+send an HTTP request for an appropriate page.
+
+If a certificate is specified on the command line using the B<-cert>
+option it will not be used unless the server specifically requests
+a client certificate. Therefore, merely including a client certificate
+on the command line is no guarantee that the certificate works.
+
+=head1 BUGS
+
+Because this program does not have all the options of the
+L<openssl-s_client(1)> program to turn protocols on and off, you may not
+be able to measure the performance of all protocols with all servers.
+
+The B<-verify> option should really exit if the server verification
+fails.
+
+=head1 HISTORY
+
+The B<-cafile> option was deprecated in OpenSSL 3.0.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-s_client(1)>,
+L<openssl-s_server(1)>,
+L<openssl-ciphers(1)>,
+L<ossl_store-file(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-sess_id.pod.in b/doc/man1/openssl-sess_id.pod.in
new file mode 100644
index 000000000000..92d7500f4f56
--- /dev/null
+++ b/doc/man1/openssl-sess_id.pod.in
@@ -0,0 +1,162 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-sess_id - SSL/TLS session handling command
+
+=head1 SYNOPSIS
+
+B<openssl> B<sess_id>
+[B<-help>]
+[B<-inform> B<DER>|B<PEM>]
+[B<-outform> B<DER>|B<PEM>|B<NSS>]
+[B<-in> I<filename>]
+[B<-out> I<filename>]
+[B<-text>]
+[B<-cert>]
+[B<-noout>]
+[B<-context> I<ID>]
+
+=head1 DESCRIPTION
+
+This command processes the encoded version of the SSL session
+structure and optionally prints out SSL session details (for example
+the SSL session master key) in human readable format. Since this is a
+diagnostic tool that needs some knowledge of the SSL protocol to use
+properly, most users will not need to use it.
+
+The precise format of the data can vary across OpenSSL versions and
+is not documented.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-inform> B<DER>|B<PEM>, B<-outform> B<DER>|B<PEM>|B<NSS>
+
+The input and output formats; the default is PEM.
+See L<openssl-format-options(1)> for details.
+
+For B<NSS> output, the session ID and master key are reported in NSS "keylog"
+format.
+
+=item B<-in> I<filename>
+
+This specifies the input filename to read session information from or standard
+input by default.
+
+=item B<-out> I<filename>
+
+This specifies the output filename to write session information to or standard
+output if this option is not specified.
+
+=item B<-text>
+
+Prints out the various public or private key components in
+plain text in addition to the encoded version.
+
+=item B<-cert>
+
+If a certificate is present in the session it will be output using this option,
+if the B<-text> option is also present then it will be printed out in text form.
+
+=item B<-noout>
+
+This option prevents output of the encoded version of the session.
+
+=item B<-context> I<ID>
+
+This option can set the session id so the output session information uses the
+supplied ID. The ID can be any string of characters. This option won't normally
+be used.
+
+=back
+
+=head1 OUTPUT
+
+Typical output:
+
+ SSL-Session:
+ Protocol : TLSv1
+ Cipher : 0016
+ Session-ID: 871E62626C554CE95488823752CBD5F3673A3EF3DCE9C67BD916C809914B40ED
+ Session-ID-ctx: 01000000
+ Master-Key: A7CEFC571974BE02CAC305269DC59F76EA9F0B180CB6642697A68251F2D2BB57E51DBBB4C7885573192AE9AEE220FACD
+ Key-Arg : None
+ Start Time: 948459261
+ Timeout : 300 (sec)
+ Verify return code 0 (ok)
+
+These are described below in more detail.
+
+=over 4
+
+=item B<Protocol>
+
+This is the protocol in use TLSv1.3, TLSv1.2, TLSv1.1, TLSv1 or SSLv3.
+
+=item B<Cipher>
+
+The cipher used this is the actual raw SSL or TLS cipher code, see the SSL
+or TLS specifications for more information.
+
+=item B<Session-ID>
+
+The SSL session ID in hex format.
+
+=item B<Session-ID-ctx>
+
+The session ID context in hex format.
+
+=item B<Master-Key>
+
+This is the SSL session master key.
+
+=item B<Start Time>
+
+This is the session start time represented as an integer in standard
+Unix format.
+
+=item B<Timeout>
+
+The timeout in seconds.
+
+=item B<Verify return code>
+
+This is the return code when an SSL client certificate is verified.
+
+=back
+
+=head1 NOTES
+
+Since the SSL session output contains the master key it is
+possible to read the contents of an encrypted session using this
+information. Therefore, appropriate security precautions should be taken if
+the information is being output by a "real" application. This is however
+strongly discouraged and should only be used for debugging purposes.
+
+=head1 BUGS
+
+The cipher and start time should be printed out in human readable form.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-ciphers(1)>,
+L<openssl-s_server(1)>
+
+=head1 COPYRIGHT
+
+Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-smime.pod.in b/doc/man1/openssl-smime.pod.in
new file mode 100644
index 000000000000..e438c866c383
--- /dev/null
+++ b/doc/man1/openssl-smime.pod.in
@@ -0,0 +1,492 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-smime - S/MIME command
+
+=head1 SYNOPSIS
+
+B<openssl> B<smime>
+[B<-help>]
+[B<-encrypt>]
+[B<-decrypt>]
+[B<-sign>]
+[B<-resign>]
+[B<-verify>]
+[B<-pk7out>]
+[B<-binary>]
+[B<-crlfeol>]
+[B<-I<cipher>>]
+[B<-in> I<file>]
+[B<-certfile> I<file>]
+[B<-signer> I<file>]
+[B<-nointern>]
+[B<-noverify>]
+[B<-nochain>]
+[B<-nosigs>]
+[B<-nocerts>]
+[B<-noattr>]
+[B<-nodetach>]
+[B<-nosmimecap>]
+[B<-recip> I< file>]
+[B<-inform> B<DER>|B<PEM>|B<SMIME>]
+[B<-outform> B<DER>|B<PEM>|B<SMIME>]
+[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-passin> I<arg>]
+[B<-inkey> I<filename>|I<uri>]
+[B<-out> I<file>]
+[B<-content> I<file>]
+[B<-to> I<addr>]
+[B<-from> I<ad>]
+[B<-subject> I<s>]
+[B<-text>]
+[B<-indef>]
+[B<-noindef>]
+[B<-stream>]
+[B<-md> I<digest>]
+{- $OpenSSL::safe::opt_trust_synopsis -}
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_v_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+{- $OpenSSL::safe::opt_config_synopsis -}
+I<recipcert> ...
+
+=head1 DESCRIPTION
+
+This command handles S/MIME mail. It can encrypt, decrypt, sign
+and verify S/MIME messages.
+
+=head1 OPTIONS
+
+There are six operation options that set the type of operation to be performed.
+The meaning of the other options varies according to the operation type.
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-encrypt>
+
+Encrypt mail for the given recipient certificates. Input file is the message
+to be encrypted. The output file is the encrypted mail in MIME format.
+
+Note that no revocation check is done for the recipient cert, so if that
+key has been compromised, others may be able to decrypt the text.
+
+=item B<-decrypt>
+
+Decrypt mail using the supplied certificate and private key. Expects an
+encrypted mail message in MIME format for the input file. The decrypted mail
+is written to the output file.
+
+=item B<-sign>
+
+Sign mail using the supplied certificate and private key. Input file is
+the message to be signed. The signed message in MIME format is written
+to the output file.
+
+=item B<-verify>
+
+Verify signed mail. Expects a signed mail message on input and outputs
+the signed data. Both clear text and opaque signing is supported.
+
+=item B<-pk7out>
+
+Takes an input message and writes out a PEM encoded PKCS#7 structure.
+
+=item B<-resign>
+
+Resign a message: take an existing message and one or more new signers.
+
+=item B<-in> I<filename>
+
+The input message to be encrypted or signed or the MIME message to
+be decrypted or verified.
+
+=item B<-out> I<filename>
+
+The message text that has been decrypted or verified or the output MIME
+format message that has been signed or verified.
+
+=item B<-inform> B<DER>|B<PEM>|B<SMIME>
+
+The input format of the PKCS#7 (S/MIME) structure (if one is being read);
+the default is B<SMIME>.
+See L<openssl-format-options(1)> for details.
+
+=item B<-outform> B<DER>|B<PEM>|B<SMIME>
+
+The output format of the PKCS#7 (S/MIME) structure (if one is being written);
+the default is B<SMIME>.
+See L<openssl-format-options(1)> for details.
+
+=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The key format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-stream>, B<-indef>, B<-noindef>
+
+The B<-stream> and B<-indef> options are equivalent and enable streaming I/O
+for encoding operations. This permits single pass processing of data without
+the need to hold the entire contents in memory, potentially supporting very
+large files. Streaming is automatically set for S/MIME signing with detached
+data if the output format is B<SMIME> it is currently off by default for all
+other operations.
+
+=item B<-noindef>
+
+Disable streaming I/O where it would produce and indefinite length constructed
+encoding. This option currently has no effect. In future streaming will be
+enabled by default on all relevant operations and this option will disable it.
+
+=item B<-content> I<filename>
+
+This specifies a file containing the detached content, this is only
+useful with the B<-verify> command. This is only usable if the PKCS#7
+structure is using the detached signature form where the content is
+not included. This option will override any content if the input format
+is S/MIME and it uses the multipart/signed MIME content type.
+
+=item B<-text>
+
+This option adds plain text (text/plain) MIME headers to the supplied
+message if encrypting or signing. If decrypting or verifying it strips
+off text headers: if the decrypted or verified message is not of MIME
+type text/plain then an error occurs.
+
+=item B<-md> I<digest>
+
+Digest algorithm to use when signing or resigning. If not present then the
+default digest algorithm for the signing key will be used (usually SHA1).
+
+=item B<-I<cipher>>
+
+The encryption algorithm to use. For example DES (56 bits) - B<-des>,
+triple DES (168 bits) - B<-des3>,
+EVP_get_cipherbyname() function) can also be used preceded by a dash, for
+example B<-aes-128-cbc>. See L<openssl-enc(1)> for list of ciphers
+supported by your version of OpenSSL.
+
+If not specified triple DES is used. Only used with B<-encrypt>.
+
+=item B<-nointern>
+
+When verifying a message normally certificates (if any) included in
+the message are searched for the signing certificate. With this option
+only the certificates specified in the B<-certfile> option are used.
+The supplied certificates can still be used as untrusted CAs however.
+
+=item B<-noverify>
+
+Do not verify the signers certificate of a signed message.
+
+=item B<-nochain>
+
+Do not do chain verification of signers certificates; that is, do not
+use the certificates in the signed message as untrusted CAs.
+
+=item B<-nosigs>
+
+Don't try to verify the signatures on the message.
+
+=item B<-nocerts>
+
+When signing a message the signer's certificate is normally included
+with this option it is excluded. This will reduce the size of the
+signed message but the verifier must have a copy of the signers certificate
+available locally (passed using the B<-certfile> option for example).
+
+=item B<-noattr>
+
+Normally when a message is signed a set of attributes are included which
+include the signing time and supported symmetric algorithms. With this
+option they are not included.
+
+=item B<-nodetach>
+
+When signing a message use opaque signing. This form is more resistant
+to translation by mail relays but it cannot be read by mail agents that
+do not support S/MIME. Without this option cleartext signing with
+the MIME type multipart/signed is used.
+
+=item B<-nosmimecap>
+
+When signing a message, do not include the B<SMIMECapabilities> attribute.
+
+=item B<-binary>
+
+Normally the input message is converted to "canonical" format which is
+effectively using CR and LF as end of line: as required by the S/MIME
+specification. When this option is present no translation occurs. This
+is useful when handling binary data which may not be in MIME format.
+
+=item B<-crlfeol>
+
+Normally the output file uses a single B<LF> as end of line. When this
+option is present B<CRLF> is used instead.
+
+=item B<-certfile> I<file>
+
+Allows additional certificates to be specified. When signing these will
+be included with the message. When verifying these will be searched for
+the signers certificates.
+The input can be in PEM, DER, or PKCS#12 format.
+
+=item B<-signer> I<file>
+
+A signing certificate when signing or resigning a message, this option can be
+used multiple times if more than one signer is required. If a message is being
+verified then the signers certificates will be written to this file if the
+verification was successful.
+
+=item B<-nocerts>
+
+Don't include signers certificate when signing.
+
+=item B<-noattr>
+
+Don't include any signed attributes when signing.
+
+=item B<-recip> I<file>
+
+The recipients certificate when decrypting a message. This certificate
+must match one of the recipients of the message or an error occurs.
+
+=item B<-inkey> I<filename>|I<uri>
+
+The private key to use when signing or decrypting. This must match the
+corresponding certificate. If this option is not specified then the
+private key must be included in the certificate file specified with
+the B<-recip> or B<-signer> file. When signing this option can be used
+multiple times to specify successive keys.
+
+=item B<-passin> I<arg>
+
+The private key password source. For more information about the format of I<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-to>, B<-from>, B<-subject>
+
+The relevant mail headers. These are included outside the signed
+portion of a message so they may be included manually. If signing
+then many S/MIME mail clients check the signers certificate's email
+address matches that specified in the From: address.
+
+{- $OpenSSL::safe::opt_v_item -}
+
+Any verification errors cause the command to exit.
+
+{- $OpenSSL::safe::opt_trust_item -}
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+{- $OpenSSL::safe::opt_config_item -}
+
+=item I<recipcert> ...
+
+One or more certificates of message recipients, used when encrypting
+a message.
+
+=back
+
+=head1 NOTES
+
+The MIME message must be sent without any blank lines between the
+headers and the output. Some mail programs will automatically add
+a blank line. Piping the mail directly to sendmail is one way to
+achieve the correct format.
+
+The supplied message to be signed or encrypted must include the
+necessary MIME headers or many S/MIME clients won't display it
+properly (if at all). You can use the B<-text> option to automatically
+add plain text headers.
+
+A "signed and encrypted" message is one where a signed message is
+then encrypted. This can be produced by encrypting an already signed
+message: see the examples section.
+
+This version of the program only allows one signer per message but it
+will verify multiple signers on received messages. Some S/MIME clients
+choke if a message contains multiple signers. It is possible to sign
+messages "in parallel" by signing an already signed message.
+
+The options B<-encrypt> and B<-decrypt> reflect common usage in S/MIME
+clients. Strictly speaking these process PKCS#7 enveloped data: PKCS#7
+encrypted data is used for other purposes.
+
+The B<-resign> option uses an existing message digest when adding a new
+signer. This means that attributes must be present in at least one existing
+signer using the same message digest or this operation will fail.
+
+The B<-stream> and B<-indef> options enable streaming I/O support.
+As a result the encoding is BER using indefinite length constructed encoding
+and no longer DER. Streaming is supported for the B<-encrypt> operation and the
+B<-sign> operation if the content is not detached.
+
+Streaming is always used for the B<-sign> operation with detached data but
+since the content is no longer part of the PKCS#7 structure the encoding
+remains DER.
+
+=head1 EXIT CODES
+
+=over 4
+
+=item Z<>0
+
+The operation was completely successfully.
+
+=item Z<>1
+
+An error occurred parsing the command options.
+
+=item Z<>2
+
+One of the input files could not be read.
+
+=item Z<>3
+
+An error occurred creating the PKCS#7 file or when reading the MIME
+message.
+
+=item Z<>4
+
+An error occurred decrypting or verifying the message.
+
+=item Z<>5
+
+The message was verified correctly but an error occurred writing out
+the signers certificates.
+
+=back
+
+=head1 EXAMPLES
+
+Create a cleartext signed message:
+
+ openssl smime -sign -in message.txt -text -out mail.msg \
+ -signer mycert.pem
+
+Create an opaque signed message:
+
+ openssl smime -sign -in message.txt -text -out mail.msg -nodetach \
+ -signer mycert.pem
+
+Create a signed message, include some additional certificates and
+read the private key from another file:
+
+ openssl smime -sign -in in.txt -text -out mail.msg \
+ -signer mycert.pem -inkey mykey.pem -certfile mycerts.pem
+
+Create a signed message with two signers:
+
+ openssl smime -sign -in message.txt -text -out mail.msg \
+ -signer mycert.pem -signer othercert.pem
+
+Send a signed message under Unix directly to sendmail, including headers:
+
+ openssl smime -sign -in in.txt -text -signer mycert.pem \
+ -from steve@openssl.org -to someone@somewhere \
+ -subject "Signed message" | sendmail someone@somewhere
+
+Verify a message and extract the signer's certificate if successful:
+
+ openssl smime -verify -in mail.msg -signer user.pem -out signedtext.txt
+
+Send encrypted mail using triple DES:
+
+ openssl smime -encrypt -in in.txt -from steve@openssl.org \
+ -to someone@somewhere -subject "Encrypted message" \
+ -des3 user.pem -out mail.msg
+
+Sign and encrypt mail:
+
+ openssl smime -sign -in ml.txt -signer my.pem -text \
+ | openssl smime -encrypt -out mail.msg \
+ -from steve@openssl.org -to someone@somewhere \
+ -subject "Signed and Encrypted message" -des3 user.pem
+
+Note: the encryption command does not include the B<-text> option because the
+message being encrypted already has MIME headers.
+
+Decrypt mail:
+
+ openssl smime -decrypt -in mail.msg -recip mycert.pem -inkey key.pem
+
+The output from Netscape form signing is a PKCS#7 structure with the
+detached signature format. You can use this program to verify the
+signature by line wrapping the base64 encoded structure and surrounding
+it with:
+
+ -----BEGIN PKCS7-----
+ -----END PKCS7-----
+
+and using the command:
+
+ openssl smime -verify -inform PEM -in signature.pem -content content.txt
+
+Alternatively you can base64 decode the signature and use:
+
+ openssl smime -verify -inform DER -in signature.der -content content.txt
+
+Create an encrypted message using 128 bit Camellia:
+
+ openssl smime -encrypt -in plain.txt -camellia128 -out mail.msg cert.pem
+
+Add a signer to an existing message:
+
+ openssl smime -resign -in mail.msg -signer newsign.pem -out mail2.msg
+
+=head1 BUGS
+
+The MIME parser isn't very clever: it seems to handle most messages that I've
+thrown at it but it may choke on others.
+
+The code currently will only write out the signer's certificate to a file: if
+the signer has a separate encryption certificate this must be manually
+extracted. There should be some heuristic that determines the correct
+encryption certificate.
+
+Ideally a database should be maintained of a certificates for each email
+address.
+
+The code doesn't currently take note of the permitted symmetric encryption
+algorithms as supplied in the SMIMECapabilities signed attribute. This means the
+user has to manually include the correct encryption algorithm. It should store
+the list of permitted ciphers in a database and only use those.
+
+No revocation checking is done on the signer's certificate.
+
+The current code can only handle S/MIME v2 messages, the more complex S/MIME v3
+structures may cause parsing errors.
+
+=head1 SEE ALSO
+
+L<ossl_store-file(7)>
+
+=head1 HISTORY
+
+The use of multiple B<-signer> options and the B<-resign> command were first
+added in OpenSSL 1.0.0
+
+The -no_alt_chains option was added in OpenSSL 1.1.0.
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-speed.pod.in b/doc/man1/openssl-speed.pod.in
new file mode 100644
index 000000000000..70ef38712ef9
--- /dev/null
+++ b/doc/man1/openssl-speed.pod.in
@@ -0,0 +1,146 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-speed - test library performance
+
+=head1 SYNOPSIS
+
+B<openssl speed>
+[B<-help>]
+[B<-elapsed>]
+[B<-evp> I<algo>]
+[B<-hmac> I<algo>]
+[B<-cmac> I<algo>]
+[B<-mb>]
+[B<-aead>]
+[B<-multi> I<num>]
+[B<-async_jobs> I<num>]
+[B<-misalign> I<num>]
+[B<-decrypt>]
+[B<-primes> I<num>]
+[B<-seconds> I<num>]
+[B<-bytes> I<num>]
+[B<-mr>]
+{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+[I<algorithm> ...]
+
+=head1 DESCRIPTION
+
+This command is used to test the performance of cryptographic algorithms.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-elapsed>
+
+When calculating operations- or bytes-per-second, use wall-clock time
+instead of CPU user time as divisor. It can be useful when testing speed
+of hardware engines.
+
+=item B<-evp> I<algo>
+
+Use the specified cipher or message digest algorithm via the EVP interface.
+If I<algo> is an AEAD cipher, then you can pass B<-aead> to benchmark a
+TLS-like sequence. And if I<algo> is a multi-buffer capable cipher, e.g.
+aes-128-cbc-hmac-sha1, then B<-mb> will time multi-buffer operation.
+
+To see the algorithms supported with this option, use
+C<openssl list -digest-algorithms> or C<openssl list -cipher-algorithms>
+command.
+
+=item B<-multi> I<num>
+
+Run multiple operations in parallel.
+
+=item B<-async_jobs> I<num>
+
+Enable async mode and start specified number of jobs.
+
+=item B<-misalign> I<num>
+
+Misalign the buffers by the specified number of bytes.
+
+=item B<-hmac> I<digest>
+
+Time the HMAC algorithm using the specified message digest.
+
+=item B<-cmac> I<cipher>
+
+Time the CMAC algorithm using the specified cipher e.g.
+C<openssl speed -cmac aes128>.
+
+=item B<-decrypt>
+
+Time the decryption instead of encryption. Affects only the EVP testing.
+
+=item B<-mb>
+
+Enable multi-block mode on EVP-named cipher.
+
+=item B<-aead>
+
+Benchmark EVP-named AEAD cipher in TLS-like sequence.
+
+=item B<-primes> I<num>
+
+Generate a I<num>-prime RSA key and use it to run the benchmarks. This option
+is only effective if RSA algorithm is specified to test.
+
+=item B<-seconds> I<num>
+
+Run benchmarks for I<num> seconds.
+
+=item B<-bytes> I<num>
+
+Run benchmarks on I<num>-byte buffers. Affects ciphers, digests and the CSPRNG.
+The limit on the size of the buffer is INT_MAX - 64 bytes, which for a 32-bit
+int would be 2147483583 bytes.
+
+=item B<-mr>
+
+Produce the summary in a mechanical, machine-readable, format.
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=item I<algorithm> ...
+
+If any I<algorithm> is given, then those algorithms are tested, otherwise a
+pre-compiled grand selection is tested.
+
+=back
+
+=head1 BUGS
+
+The I<algorithm> can be selected only from a pre-compiled subset of things
+that the C<openssl speed> command knows about. To test any additional digest
+or cipher algorithm supported by OpenSSL use the C<-evp> option.
+
+There is no way to test the speed of any additional public key algorithms
+supported by third party providers with the C<openssl speed> command.
+
+=head1 HISTORY
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-spkac.pod.in b/doc/man1/openssl-spkac.pod.in
new file mode 100644
index 000000000000..5e55a7498b67
--- /dev/null
+++ b/doc/man1/openssl-spkac.pod.in
@@ -0,0 +1,169 @@
+=pod
+
+=begin comment
+{- join("\n", @autowarntext) -}
+
+=end comment
+
+=head1 NAME
+
+openssl-spkac - SPKAC printing and generating command
+
+=head1 SYNOPSIS
+
+B<openssl> B<spkac>
+[B<-help>]
+[B<-in> I<filename>]
+[B<-out> I<filename>]
+[B<-digest> I<digest>]
+[B<-key> I<filename>|I<uri>]
+[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-passin> I<arg>]
+[B<-challenge> I<string>]
+[B<-pubkey>]
+[B<-spkac> I<spkacname>]
+[B<-spksect> I<section>]
+[B<-noout>]
+[B<-verify>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command processes Netscape signed public key and challenge
+(SPKAC) files. It can print out their contents, verify the signature and
+produce its own SPKACs from a supplied private key.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-in> I<filename>
+
+This specifies the input filename to read from or standard input if this
+option is not specified. Ignored if the B<-key> option is used.
+
+=item B<-out> I<filename>
+
+Specifies the output filename to write to or standard output by
+default.
+
+=item B<-digest> I<digest>
+
+Use the specified I<digest> to sign a created SPKAC file.
+The default digest algorithm is MD5.
+
+=item B<-key> I<filename>|I<uri>
+
+Create an SPKAC file using the private key specified by I<filename> or I<uri>.
+The B<-in>, B<-noout>, B<-spksect> and B<-verify> options are ignored if
+present.
+
+=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The key format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-passin> I<arg>
+
+The input file password source. For more information about the format of I<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-challenge> I<string>
+
+Specifies the challenge string if an SPKAC is being created.
+
+=item B<-spkac> I<spkacname>
+
+Allows an alternative name form the variable containing the
+SPKAC. The default is "SPKAC". This option affects both
+generated and input SPKAC files.
+
+=item B<-spksect> I<section>
+
+Allows an alternative name form the section containing the
+SPKAC. The default is the default section.
+
+=item B<-noout>
+
+Don't output the text version of the SPKAC (not used if an
+SPKAC is being created).
+
+=item B<-pubkey>
+
+Output the public key of an SPKAC (not used if an SPKAC is
+being created).
+
+=item B<-verify>
+
+Verifies the digital signature on the supplied SPKAC.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 EXAMPLES
+
+Print out the contents of an SPKAC:
+
+ openssl spkac -in spkac.cnf
+
+Verify the signature of an SPKAC:
+
+ openssl spkac -in spkac.cnf -noout -verify
+
+Create an SPKAC using the challenge string "hello":
+
+ openssl spkac -key key.pem -challenge hello -out spkac.cnf
+
+Example of an SPKAC, (long lines split up for clarity):
+
+ SPKAC=MIG5MGUwXDANBgkqhkiG9w0BAQEFAANLADBIAkEA\
+ 1cCoq2Wa3Ixs47uI7FPVwHVIPDx5yso105Y6zpozam135a\
+ 8R0CpoRvkkigIyXfcCjiVi5oWk+6FfPaD03uPFoQIDAQAB\
+ FgVoZWxsbzANBgkqhkiG9w0BAQQFAANBAFpQtY/FojdwkJ\
+ h1bEIYuc2EeM2KHTWPEepWYeawvHD0gQ3DngSC75YCWnnD\
+ dq+NQ3F+X4deMx9AaEglZtULwV4=
+
+=head1 NOTES
+
+A created SPKAC with suitable DN components appended can be fed to
+L<openssl-ca(1)>.
+
+SPKACs are typically generated by Netscape when a form is submitted
+containing the B<KEYGEN> tag as part of the certificate enrollment
+process.
+
+The challenge string permits a primitive form of proof of possession
+of private key. By checking the SPKAC signature and a random challenge
+string some guarantee is given that the user knows the private key
+corresponding to the public key being certified. This is important in
+some applications. Without this it is possible for a previous SPKAC
+to be used in a "replay attack".
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-ca(1)>
+
+=head1 HISTORY
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+The B<-digest> option was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-srp.pod.in b/doc/man1/openssl-srp.pod.in
new file mode 100644
index 000000000000..26f7ebcef9c5
--- /dev/null
+++ b/doc/man1/openssl-srp.pod.in
@@ -0,0 +1,118 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-srp - maintain SRP password file
+
+=head1 SYNOPSIS
+
+B<openssl srp>
+[B<-help>]
+[B<-verbose>]
+[B<-add>]
+[B<-modify>]
+[B<-delete>]
+[B<-list>]
+[B<-name> I<section>]
+[B<-srpvfile> I<file>]
+[B<-gn> I<identifier>]
+[B<-userinfo> I<text>]
+[B<-passin> I<arg>]
+[B<-passout> I<arg>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+{- $OpenSSL::safe::opt_config_synopsis -}
+[I<user> ...]
+
+=head1 DESCRIPTION
+
+This command is deprecated. It is used to maintain an SRP (secure remote
+password) file. At most one of the B<-add>, B<-modify>, B<-delete>, and B<-list>
+options can be specified.
+These options take zero or more usernames as parameters and perform the
+appropriate operation on the SRP file.
+For B<-list>, if no I<user> is given then all users are displayed.
+
+The configuration file to use, and the section within the file, can be
+specified with the B<-config> and B<-name> flags, respectively.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Display an option summary.
+
+=item B<-verbose>
+
+Generate verbose output while processing.
+
+=item B<-add>
+
+Add a user and SRP verifier.
+
+=item B<-modify>
+
+Modify the SRP verifier of an existing user.
+
+=item B<-delete>
+
+Delete user from verifier file.
+
+=item B<-list>
+
+List users.
+
+=item B<-name>
+
+The particular SRP definition to use.
+
+=item B<-srpvfile> I<file>
+
+If the config file is not specified,
+B<-srpvfile> can be used to specify the file to operate on.
+
+=item B<-gn>
+
+Specifies the B<g> and B<N> values, using one of
+the strengths defined in IETF RFC 5054.
+
+=item B<-userinfo>
+
+specifies additional information to add when
+adding or modifying a user.
+
+=item B<-passin> I<arg>, B<-passout> I<arg>
+
+The password source for the input and output file.
+For more information about the format of B<arg>
+see L<openssl-passphrase-options(1)>.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+{- $OpenSSL::safe::opt_config_item -}
+
+{- $OpenSSL::safe::opt_r_synopsis -}
+
+=back
+
+=head1 HISTORY
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-storeutl.pod.in b/doc/man1/openssl-storeutl.pod.in
new file mode 100644
index 000000000000..26d5ee28e647
--- /dev/null
+++ b/doc/man1/openssl-storeutl.pod.in
@@ -0,0 +1,147 @@
+=pod
+
+=begin comment
+{- join("\n", @autowarntext) -}
+
+=end comment
+
+=head1 NAME
+
+openssl-storeutl - STORE command
+
+=head1 SYNOPSIS
+
+B<openssl> B<storeutl>
+[B<-help>]
+[B<-out> I<file>]
+[B<-noout>]
+[B<-passin> I<arg>]
+[B<-text> I<arg>]
+[B<-r>]
+[B<-certs>]
+[B<-keys>]
+[B<-crls>]
+[B<-subject> I<arg>]
+[B<-issuer> I<arg>]
+[B<-serial> I<arg>]
+[B<-alias> I<arg>]
+[B<-fingerprint> I<arg>]
+[B<-I<digest>>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+I<uri>
+
+=head1 DESCRIPTION
+
+This command can be used to display the contents (after
+decryption as the case may be) fetched from the given URI.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-out> I<filename>
+
+specifies the output filename to write to or standard output by
+default.
+
+=item B<-noout>
+
+this option prevents output of the PEM data.
+
+=item B<-passin> I<arg>
+
+the key password source. For more information about the format of I<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-text>
+
+Prints out the objects in text form, similarly to the B<-text> output from
+L<openssl-x509(1)>, L<openssl-pkey(1)>, etc.
+
+=item B<-r>
+
+Fetch objects recursively when possible.
+
+=item B<-certs>
+
+=item B<-keys>
+
+=item B<-crls>
+
+Only select the certificates, keys or CRLs from the given URI.
+However, if this URI would return a set of names (URIs), those are always
+returned.
+
+Note that all options must be given before the I<uri> argument.
+Otherwise they are ignored.
+
+=item B<-subject> I<arg>
+
+Search for an object having the subject name I<arg>.
+
+The arg must be formatted as C</type0=value0/type1=value1/type2=...>.
+Special characters may be escaped by C<\> (backslash), whitespace is retained.
+Empty values are permitted but are ignored for the search. That is,
+a search with an empty value will have the same effect as not specifying
+the type at all.
+Giving a single C</> will lead to an empty sequence of RDNs (a NULL-DN).
+Multi-valued RDNs can be formed by placing a C<+> character instead of a C</>
+between the AttributeValueAssertions (AVAs) that specify the members of the set.
+
+Example:
+
+C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
+
+=item B<-issuer> I<arg>
+
+=item B<-serial> I<arg>
+
+Search for an object having the given issuer name and serial number.
+These two options I<must> be used together.
+The issuer arg must be formatted as C</type0=value0/type1=value1/type2=...>,
+characters may be escaped by \ (backslash), no spaces are skipped.
+The serial arg may be specified as a decimal value or a hex value if preceded
+by C<0x>.
+
+=item B<-alias> I<arg>
+
+Search for an object having the given alias.
+
+=item B<-fingerprint> I<arg>
+
+Search for an object having the given fingerprint.
+
+=item B<-I<digest>>
+
+The digest that was used to compute the fingerprint given with B<-fingerprint>.
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head1 SEE ALSO
+
+L<openssl(1)>
+
+=head1 HISTORY
+
+This command was added in OpenSSL 1.1.1.
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-ts.pod.in b/doc/man1/openssl-ts.pod.in
new file mode 100644
index 000000000000..6f7182020247
--- /dev/null
+++ b/doc/man1/openssl-ts.pod.in
@@ -0,0 +1,662 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-ts - Time Stamping Authority command
+
+=head1 SYNOPSIS
+
+B<openssl> B<ts>
+B<-help>
+
+B<openssl> B<ts>
+B<-query>
+[B<-config> I<configfile>]
+[B<-data> I<file_to_hash>]
+[B<-digest> I<digest_bytes>]
+[B<-I<digest>>]
+[B<-tspolicy> I<object_id>]
+[B<-no_nonce>]
+[B<-cert>]
+[B<-in> I<request.tsq>]
+[B<-out> I<request.tsq>]
+[B<-text>]
+{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+
+B<openssl> B<ts>
+B<-reply>
+[B<-config> I<configfile>]
+[B<-section> I<tsa_section>]
+[B<-queryfile> I<request.tsq>]
+[B<-passin> I<password_src>]
+[B<-signer> I<tsa_cert.pem>]
+[B<-inkey> I<filename>|I<uri>]
+[B<-I<digest>>]
+[B<-chain> I<certs_file.pem>]
+[B<-tspolicy> I<object_id>]
+[B<-in> I<response.tsr>]
+[B<-token_in>]
+[B<-out> I<response.tsr>]
+[B<-token_out>]
+[B<-text>]
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+
+B<openssl> B<ts>
+B<-verify>
+[B<-data> I<file_to_hash>]
+[B<-digest> I<digest_bytes>]
+[B<-queryfile> I<request.tsq>]
+[B<-in> I<response.tsr>]
+[B<-token_in>]
+[B<-untrusted> I<files>|I<uris>]
+[B<-CAfile> I<file>]
+[B<-CApath> I<dir>]
+[B<-CAstore> I<uri>]
+{- $OpenSSL::safe::opt_v_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command is a basic Time Stamping Authority (TSA) client and
+server application as specified in RFC 3161 (Time-Stamp Protocol, TSP). A
+TSA can be part of a PKI deployment and its role is to provide long
+term proof of the existence of a certain datum before a particular
+time. Here is a brief description of the protocol:
+
+=over 4
+
+=item 1.
+
+The TSA client computes a one-way hash value for a data file and sends
+the hash to the TSA.
+
+=item 2.
+
+The TSA attaches the current date and time to the received hash value,
+signs them and sends the timestamp token back to the client. By
+creating this token the TSA certifies the existence of the original
+data file at the time of response generation.
+
+=item 3.
+
+The TSA client receives the timestamp token and verifies the
+signature on it. It also checks if the token contains the same hash
+value that it had sent to the TSA.
+
+=back
+
+There is one DER encoded protocol data unit defined for transporting a
+timestamp request to the TSA and one for sending the timestamp response
+back to the client. This command has three main functions:
+creating a timestamp request based on a data file,
+creating a timestamp response based on a request, verifying if a
+response corresponds to a particular request or a data file.
+
+There is no support for sending the requests/responses automatically
+over HTTP or TCP yet as suggested in RFC 3161. The users must send the
+requests either by ftp or e-mail.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-query>
+
+Generate a TS query. For details see L</Timestamp Request generation>.
+
+=item B<-reply>
+
+Generate a TS reply. For details see L</Timestamp Response generation>.
+
+=item B<-verify>
+
+Verify a TS response. For details see L</Timestamp Response verification>.
+
+=back
+
+=head2 Timestamp Request generation
+
+The B<-query> command can be used for creating and printing a timestamp
+request with the following options:
+
+=over 4
+
+=item B<-config> I<configfile>
+
+The configuration file to use.
+Optional; for a description of the default value,
+see L<openssl(1)/COMMAND SUMMARY>.
+
+=item B<-data> I<file_to_hash>
+
+The data file for which the timestamp request needs to be
+created. stdin is the default if neither the B<-data> nor the B<-digest>
+parameter is specified. (Optional)
+
+=item B<-digest> I<digest_bytes>
+
+It is possible to specify the message imprint explicitly without the data
+file. The imprint must be specified in a hexadecimal format, two characters
+per byte, the bytes optionally separated by colons (e.g. 1A:F6:01:... or
+1AF601...). The number of bytes must match the message digest algorithm
+in use. (Optional)
+
+=item B<-I<digest>>
+
+The message digest to apply to the data file.
+Any digest supported by the L<openssl-dgst(1)> command can be used.
+The default is SHA-256. (Optional)
+
+=item B<-tspolicy> I<object_id>
+
+The policy that the client expects the TSA to use for creating the
+timestamp token. Either the dotted OID notation or OID names defined
+in the config file can be used. If no policy is requested the TSA will
+use its own default policy. (Optional)
+
+=item B<-no_nonce>
+
+No nonce is specified in the request if this option is
+given. Otherwise a 64 bit long pseudo-random none is
+included in the request. It is recommended to use nonce to
+protect against replay-attacks. (Optional)
+
+=item B<-cert>
+
+The TSA is expected to include its signing certificate in the
+response. (Optional)
+
+=item B<-in> I<request.tsq>
+
+This option specifies a previously created timestamp request in DER
+format that will be printed into the output file. Useful when you need
+to examine the content of a request in human-readable
+format. (Optional)
+
+=item B<-out> I<request.tsq>
+
+Name of the output file to which the request will be written. Default
+is stdout. (Optional)
+
+=item B<-text>
+
+If this option is specified the output is human-readable text format
+instead of DER. (Optional)
+
+{- $OpenSSL::safe::opt_r_item -}
+
+=back
+
+=head2 Timestamp Response generation
+
+A timestamp response (TimeStampResp) consists of a response status
+and the timestamp token itself (ContentInfo), if the token generation was
+successful. The B<-reply> command is for creating a timestamp
+response or timestamp token based on a request and printing the
+response/token in human-readable format. If B<-token_out> is not
+specified the output is always a timestamp response (TimeStampResp),
+otherwise it is a timestamp token (ContentInfo).
+
+=over 4
+
+=item B<-config> I<configfile>
+
+The configuration file to use.
+Optional; for a description of the default value,
+see L<openssl(1)/COMMAND SUMMARY>.
+See L</CONFIGURATION FILE OPTIONS> for configurable variables.
+
+=item B<-section> I<tsa_section>
+
+The name of the config file section containing the settings for the
+response generation. If not specified the default TSA section is
+used, see L</CONFIGURATION FILE OPTIONS> for details. (Optional)
+
+=item B<-queryfile> I<request.tsq>
+
+The name of the file containing a DER encoded timestamp request. (Optional)
+
+=item B<-passin> I<password_src>
+
+Specifies the password source for the private key of the TSA. See
+description in L<openssl(1)>. (Optional)
+
+=item B<-signer> I<tsa_cert.pem>
+
+The signer certificate of the TSA in PEM format. The TSA signing
+certificate must have exactly one extended key usage assigned to it:
+timeStamping. The extended key usage must also be critical, otherwise
+the certificate is going to be refused. Overrides the B<signer_cert>
+variable of the config file. (Optional)
+
+=item B<-inkey> I<filename>|I<uri>
+
+The signer private key of the TSA in PEM format. Overrides the
+B<signer_key> config file option. (Optional)
+
+=item B<-I<digest>>
+
+Signing digest to use. Overrides the B<signer_digest> config file
+option. (Mandatory unless specified in the config file)
+
+=item B<-chain> I<certs_file.pem>
+
+The collection of certificates in PEM format that will all
+be included in the response in addition to the signer certificate if
+the B<-cert> option was used for the request. This file is supposed to
+contain the certificate chain for the signer certificate from its
+issuer upwards. The B<-reply> command does not build a certificate
+chain automatically. (Optional)
+
+=item B<-tspolicy> I<object_id>
+
+The default policy to use for the response unless the client
+explicitly requires a particular TSA policy. The OID can be specified
+either in dotted notation or with its name. Overrides the
+B<default_policy> config file option. (Optional)
+
+=item B<-in> I<response.tsr>
+
+Specifies a previously created timestamp response or timestamp token
+(if B<-token_in> is also specified) in DER format that will be written
+to the output file. This option does not require a request, it is
+useful e.g. when you need to examine the content of a response or
+token or you want to extract the timestamp token from a response. If
+the input is a token and the output is a timestamp response a default
+'granted' status info is added to the token. (Optional)
+
+=item B<-token_in>
+
+This flag can be used together with the B<-in> option and indicates
+that the input is a DER encoded timestamp token (ContentInfo) instead
+of a timestamp response (TimeStampResp). (Optional)
+
+=item B<-out> I<response.tsr>
+
+The response is written to this file. The format and content of the
+file depends on other options (see B<-text>, B<-token_out>). The default is
+stdout. (Optional)
+
+=item B<-token_out>
+
+The output is a timestamp token (ContentInfo) instead of timestamp
+response (TimeStampResp). (Optional)
+
+=item B<-text>
+
+If this option is specified the output is human-readable text format
+instead of DER. (Optional)
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head2 Timestamp Response verification
+
+The B<-verify> command is for verifying if a timestamp response or
+timestamp token is valid and matches a particular timestamp request or
+data file. The B<-verify> command does not use the configuration file.
+
+=over 4
+
+=item B<-data> I<file_to_hash>
+
+The response or token must be verified against file_to_hash. The file
+is hashed with the message digest algorithm specified in the token.
+The B<-digest> and B<-queryfile> options must not be specified with this one.
+(Optional)
+
+=item B<-digest> I<digest_bytes>
+
+The response or token must be verified against the message digest specified
+with this option. The number of bytes must match the message digest algorithm
+specified in the token. The B<-data> and B<-queryfile> options must not be
+specified with this one. (Optional)
+
+=item B<-queryfile> I<request.tsq>
+
+The original timestamp request in DER format. The B<-data> and B<-digest>
+options must not be specified with this one. (Optional)
+
+=item B<-in> I<response.tsr>
+
+The timestamp response that needs to be verified in DER format. (Mandatory)
+
+=item B<-token_in>
+
+This flag can be used together with the B<-in> option and indicates
+that the input is a DER encoded timestamp token (ContentInfo) instead
+of a timestamp response (TimeStampResp). (Optional)
+
+=item B<-untrusted> I<files>|I<uris>
+
+A set of additional untrusted certificates which may be
+needed when building the certificate chain for the TSA's signing certificate.
+These do not need to contain the TSA signing certificate and intermediate CA
+certificates as far as the response already includes them.
+(Optional)
+
+Multiple sources may be given, separated by commas and/or whitespace.
+Each file may contain multiple certificates.
+
+=item B<-CAfile> I<file>, B<-CApath> I<dir>, B<-CAstore> I<uri>
+
+See L<openssl-verification-options(1)/Trusted Certificate Options> for details.
+At least one of B<-CAfile>, B<-CApath> or B<-CAstore> must be specified.
+
+{- $OpenSSL::safe::opt_v_item -}
+
+Any verification errors cause the command to exit.
+
+=back
+
+=head1 CONFIGURATION FILE OPTIONS
+
+The B<-query> and B<-reply> commands make use of a configuration file.
+See L<config(5)>
+for a general description of the syntax of the config file. The
+B<-query> command uses only the symbolic OID names section
+and it can work without it. However, the B<-reply> command needs the
+config file for its operation.
+
+When there is a command line switch equivalent of a variable the
+switch always overrides the settings in the config file.
+
+=over 4
+
+=item B<tsa> section, B<default_tsa>
+
+This is the main section and it specifies the name of another section
+that contains all the options for the B<-reply> command. This default
+section can be overridden with the B<-section> command line switch. (Optional)
+
+=item B<oid_file>
+
+This specifies a file containing additional B<OBJECT IDENTIFIERS>.
+Each line of the file should consist of the numerical form of the
+object identifier followed by whitespace then the short name followed
+by whitespace and finally the long name. (Optional)
+
+=item B<oid_section>
+
+This specifies a section in the configuration file containing extra
+object identifiers. Each line should consist of the short name of the
+object identifier followed by B<=> and the numerical form. The short
+and long names are the same when this option is used. (Optional)
+
+=item B<RANDFILE>
+
+At startup the specified file is loaded into the random number generator,
+and at exit 256 bytes will be written to it. (Note: Using a RANDFILE is
+not necessary anymore, see the L</HISTORY> section.
+
+=item B<serial>
+
+The name of the file containing the hexadecimal serial number of the
+last timestamp response created. This number is incremented by 1 for
+each response. If the file does not exist at the time of response
+generation a new file is created with serial number 1. (Mandatory)
+
+=item B<crypto_device>
+
+Specifies the OpenSSL engine that will be set as the default for
+all available algorithms. The default value is built-in, you can specify
+any other engines supported by OpenSSL (e.g. use chil for the NCipher HSM).
+(Optional)
+
+=item B<signer_cert>
+
+TSA signing certificate in PEM format. The same as the B<-signer>
+command line option. (Optional)
+
+=item B<certs>
+
+A file containing a set of PEM encoded certificates that need to be
+included in the response. The same as the B<-chain> command line
+option. (Optional)
+
+=item B<signer_key>
+
+The private key of the TSA in PEM format. The same as the B<-inkey>
+command line option. (Optional)
+
+=item B<signer_digest>
+
+Signing digest to use. The same as the
+B<-I<digest>> command line option. (Mandatory unless specified on the command
+line)
+
+=item B<default_policy>
+
+The default policy to use when the request does not mandate any
+policy. The same as the B<-tspolicy> command line option. (Optional)
+
+=item B<other_policies>
+
+Comma separated list of policies that are also acceptable by the TSA
+and used only if the request explicitly specifies one of them. (Optional)
+
+=item B<digests>
+
+The list of message digest algorithms that the TSA accepts. At least
+one algorithm must be specified. (Mandatory)
+
+=item B<accuracy>
+
+The accuracy of the time source of the TSA in seconds, milliseconds
+and microseconds. E.g. secs:1, millisecs:500, microsecs:100. If any of
+the components is missing zero is assumed for that field. (Optional)
+
+=item B<clock_precision_digits>
+
+Specifies the maximum number of digits, which represent the fraction of
+seconds, that need to be included in the time field. The trailing zeros
+must be removed from the time, so there might actually be fewer digits,
+or no fraction of seconds at all. Supported only on UNIX platforms.
+The maximum value is 6, default is 0.
+(Optional)
+
+=item B<ordering>
+
+If this option is yes the responses generated by this TSA can always
+be ordered, even if the time difference between two responses is less
+than the sum of their accuracies. Default is no. (Optional)
+
+=item B<tsa_name>
+
+Set this option to yes if the subject name of the TSA must be included in
+the TSA name field of the response. Default is no. (Optional)
+
+=item B<ess_cert_id_chain>
+
+The SignedData objects created by the TSA always contain the
+certificate identifier of the signing certificate in a signed
+attribute (see RFC 2634, Enhanced Security Services).
+If this variable is set to no, only this signing certificate identifier
+is included in the SigningCertificate signed attribute.
+If this variable is set to yes and the B<certs> variable or the B<-chain> option
+is specified then the certificate identifiers of the chain will also
+be included, where the B<-chain> option overrides the B<certs> variable.
+Default is no. (Optional)
+
+=item B<ess_cert_id_alg>
+
+This option specifies the hash function to be used to calculate the TSA's
+public key certificate identifier. Default is sha256. (Optional)
+
+=back
+
+=head1 EXAMPLES
+
+All the examples below presume that B<OPENSSL_CONF> is set to a proper
+configuration file, e.g. the example configuration file
+F<openssl/apps/openssl.cnf> will do.
+
+=head2 Timestamp Request
+
+To create a timestamp request for F<design1.txt> with SHA-256 digest,
+without nonce and policy, and without requirement for a certificate
+in the response:
+
+ openssl ts -query -data design1.txt -no_nonce \
+ -out design1.tsq
+
+To create a similar timestamp request with specifying the message imprint
+explicitly:
+
+ openssl ts -query -digest b7e5d3f93198b38379852f2c04e78d73abdd0f4b \
+ -no_nonce -out design1.tsq
+
+To print the content of the previous request in human readable format:
+
+ openssl ts -query -in design1.tsq -text
+
+To create a timestamp request which includes the SHA-512 digest
+of F<design2.txt>, requests the signer certificate and nonce, and
+specifies a policy id (assuming the tsa_policy1 name is defined in the
+OID section of the config file):
+
+ openssl ts -query -data design2.txt -sha512 \
+ -tspolicy tsa_policy1 -cert -out design2.tsq
+
+=head2 Timestamp Response
+
+Before generating a response a signing certificate must be created for
+the TSA that contains the B<timeStamping> critical extended key usage extension
+without any other key usage extensions. You can add this line to the
+user certificate section of the config file to generate a proper certificate;
+
+ extendedKeyUsage = critical,timeStamping
+
+See L<openssl-req(1)>, L<openssl-ca(1)>, and L<openssl-x509(1)> for
+instructions. The examples below assume that F<cacert.pem> contains the
+certificate of the CA, F<tsacert.pem> is the signing certificate issued
+by F<cacert.pem> and F<tsakey.pem> is the private key of the TSA.
+
+To create a timestamp response for a request:
+
+ openssl ts -reply -queryfile design1.tsq -inkey tsakey.pem \
+ -signer tsacert.pem -out design1.tsr
+
+If you want to use the settings in the config file you could just write:
+
+ openssl ts -reply -queryfile design1.tsq -out design1.tsr
+
+To print a timestamp reply to stdout in human readable format:
+
+ openssl ts -reply -in design1.tsr -text
+
+To create a timestamp token instead of timestamp response:
+
+ openssl ts -reply -queryfile design1.tsq -out design1_token.der -token_out
+
+To print a timestamp token to stdout in human readable format:
+
+ openssl ts -reply -in design1_token.der -token_in -text -token_out
+
+To extract the timestamp token from a response:
+
+ openssl ts -reply -in design1.tsr -out design1_token.der -token_out
+
+To add 'granted' status info to a timestamp token thereby creating a
+valid response:
+
+ openssl ts -reply -in design1_token.der -token_in -out design1.tsr
+
+=head2 Timestamp Verification
+
+To verify a timestamp reply against a request:
+
+ openssl ts -verify -queryfile design1.tsq -in design1.tsr \
+ -CAfile cacert.pem -untrusted tsacert.pem
+
+To verify a timestamp reply that includes the certificate chain:
+
+ openssl ts -verify -queryfile design2.tsq -in design2.tsr \
+ -CAfile cacert.pem
+
+To verify a timestamp token against the original data file:
+ openssl ts -verify -data design2.txt -in design2.tsr \
+ -CAfile cacert.pem
+
+To verify a timestamp token against a message imprint:
+ openssl ts -verify -digest b7e5d3f93198b38379852f2c04e78d73abdd0f4b \
+ -in design2.tsr -CAfile cacert.pem
+
+You could also look at the 'test' directory for more examples.
+
+=head1 BUGS
+
+=for openssl foreign manual procmail(1) perl(1)
+
+=over 2
+
+=item *
+
+No support for timestamps over SMTP, though it is quite easy
+to implement an automatic e-mail based TSA with L<procmail(1)>
+and L<perl(1)>. HTTP server support is provided in the form of
+a separate apache module. HTTP client support is provided by
+L<tsget(1)>. Pure TCP/IP protocol is not supported.
+
+=item *
+
+The file containing the last serial number of the TSA is not
+locked when being read or written. This is a problem if more than one
+instance of L<openssl(1)> is trying to create a timestamp
+response at the same time. This is not an issue when using the apache
+server module, it does proper locking.
+
+=item *
+
+Look for the FIXME word in the source files.
+
+=item *
+
+The source code should really be reviewed by somebody else, too.
+
+=item *
+
+More testing is needed, I have done only some basic tests (see
+test/testtsa).
+
+=back
+
+=head1 HISTORY
+
+OpenSSL 1.1.1 introduced a new random generator (CSPRNG) with an improved
+seeding mechanism. The new seeding mechanism makes it unnecessary to
+define a RANDFILE for saving and restoring randomness. This option is
+retained mainly for compatibility reasons.
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<tsget(1)>,
+L<openssl-req(1)>,
+L<openssl-x509(1)>,
+L<openssl-ca(1)>,
+L<openssl-genrsa(1)>,
+L<config(5)>,
+L<ossl_store-file(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-verification-options.pod b/doc/man1/openssl-verification-options.pod
new file mode 100644
index 000000000000..5fa3907c2801
--- /dev/null
+++ b/doc/man1/openssl-verification-options.pod
@@ -0,0 +1,696 @@
+=pod
+
+=head1 NAME
+
+openssl-verification-options - generic X.509 certificate verification options
+
+=head1 SYNOPSIS
+
+B<openssl>
+I<command>
+[ I<options> ... ]
+[ I<parameters> ... ]
+
+=head1 DESCRIPTION
+
+There are many situations where X.509 certificates are verified
+within the OpenSSL libraries and in various OpenSSL commands.
+
+Certificate verification is implemented by L<X509_verify_cert(3)>.
+It is a complicated process consisting of a number of steps
+and depending on numerous options.
+The most important of them are detailed in the following sections.
+
+In a nutshell, a valid chain of certificates needs to be built up and verified
+starting from the I<target certificate> that is to be verified
+and ending in a certificate that due to some policy is trusted.
+Verification is done relative to the given I<purpose>, which is the intended use
+of the target certificate, such as SSL server, or by default for any purpose.
+
+The details of how each OpenSSL command handles errors
+are documented on the specific command page.
+
+DANE support is documented in L<openssl-s_client(1)>,
+L<SSL_CTX_dane_enable(3)>, L<SSL_set1_host(3)>,
+L<X509_VERIFY_PARAM_set_flags(3)>, and L<X509_check_host(3)>.
+
+=head2 Trust Anchors
+
+In general, according to RFC 4158 and RFC 5280, a I<trust anchor> is
+any public key and related subject distinguished name (DN) that
+for some reason is considered trusted
+and thus is acceptable as the root of a chain of certificates.
+
+In practice, trust anchors are given in the form of certificates,
+where their essential fields are the public key and the subject DN.
+In addition to the requirements in RFC 5280,
+OpenSSL checks the validity period of such certificates
+and makes use of some further fields.
+In particular, the subject key identifier extension, if present,
+is used for matching trust anchors during chain building.
+
+In the most simple and common case, trust anchors are by default
+all self-signed "root" CA certificates that are placed in the I<trust store>,
+which is a collection of certificates that are trusted for certain uses.
+This is akin to what is used in the trust stores of Mozilla Firefox,
+or Apple's and Microsoft's certificate stores, ...
+
+From the OpenSSL perspective, a trust anchor is a certificate
+that should be augmented with an explicit designation for which
+uses of a target certificate the certificate may serve as a trust anchor.
+In PEM encoding, this is indicated by the C<TRUSTED CERTIFICATE> string.
+Such a designation provides a set of positive trust attributes
+explicitly stating trust for the listed purposes
+and/or a set of negative trust attributes
+explicitly rejecting the use for the listed purposes.
+The purposes are encoded using the values defined for the extended key usages
+(EKUs) that may be given in X.509 extensions of end-entity certificates.
+See also the L</Extended Key Usage> section below.
+
+The currently recognized uses are
+B<clientAuth> (SSL client use), B<serverAuth> (SSL server use),
+B<emailProtection> (S/MIME email use), B<codeSigning> (object signer use),
+B<OCSPSigning> (OCSP responder use), B<OCSP> (OCSP request use),
+B<timeStamping> (TSA server use), and B<anyExtendedKeyUsage>.
+As of OpenSSL 1.1.0, the last of these blocks all uses when rejected or
+enables all uses when trusted.
+
+A certificate, which may be CA certificate or an end-entity certificate,
+is considered a trust anchor for the given use
+if and only if all the following conditions hold:
+
+=over 4
+
+=item *
+
+It is an an element of the trust store.
+
+=item *
+
+It does not have a negative trust attribute rejecting the given use.
+
+=item *
+
+It has a positive trust attribute accepting the given use
+or (by default) one of the following compatibilty conditions apply:
+It is self-signed or the B<-partial_chain> option is given
+(which corresponds to the B<X509_V_FLAG_PARTIAL_CHAIN> flag being set).
+
+=back
+
+=head2 Certification Path Building
+
+First, a certificate chain is built up starting from the target certificate
+and ending in a trust anchor.
+
+The chain is built up iteratively, looking up in turn
+a certificate with suitable key usage that
+matches as an issuer of the current "subject" certificate as described below.
+If there is such a certificate, the first one found that is currently valid
+is taken, otherwise the one that expired most recently of all such certificates.
+For efficiency, no backtracking is performed, thus
+any further candidate issuer certificates that would match equally are ignored.
+
+When a self-signed certificate has been added, chain construction stops.
+In this case it must fully match a trust anchor, otherwise chain building fails.
+
+A candidate issuer certificate matches a subject certificate
+if all of the following conditions hold:
+
+=over 4
+
+=item *
+
+Its subject name matches the issuer name of the subject certificate.
+
+=item *
+
+If the subject certificate has an authority key identifier extension,
+each of its sub-fields equals the corresponding subject key identifier, serial
+number, and issuer field of the candidate issuer certificate,
+as far as the respective fields are present in both certificates.
+
+=item *
+
+The certificate signature algorithm used to sign the subject certificate
+is supported and
+equals the public key algorithm of the candidate issuer certificate.
+
+=back
+
+The lookup first searches for issuer certificates in the trust store.
+If it does not find a match there it consults
+the list of untrusted ("intermediate" CA) certificates, if provided.
+
+=head2 Certification Path Validation
+
+When the certificate chain building process was successful
+the chain components and their links are checked thoroughly.
+
+The first step is to check that each certificate is well-formed.
+Part of these checks are enabled only if the B<-x509_strict> option is given.
+
+The second step is to check the extensions of every untrusted certificate
+for consistency with the supplied purpose.
+If the B<-purpose> option is not given then no such checks are done
+except for SSL/TLS connection setup,
+where by default C<sslserver> or C<sslclient>, are checked.
+The target or "leaf" certificate, as well as any other untrusted certificates,
+must have extensions compatible with the specified purpose.
+All certificates except the target or "leaf" must also be valid CA certificates.
+The precise extensions required are described in more detail in
+L<openssl-x509(1)/CERTIFICATE EXTENSIONS>.
+
+The third step is to check the trust settings on the last certificate
+(which typically is a self-signed root CA certificate).
+It must be trusted for the given use.
+For compatibility with previous versions of OpenSSL, a self-signed certificate
+with no trust attributes is considered to be valid for all uses.
+
+The fourth, and final, step is to check the validity of the certificate chain.
+For each element in the chain, including the root CA certificate,
+the validity period as specified by the C<notBefore> and C<notAfter> fields
+is checked against the current system time.
+The B<-attime> flag may be used to use a reference time other than "now."
+The certificate signature is checked as well
+(except for the signature of the typically self-signed root CA certificate,
+which is verified only if the B<-check_ss_sig> option is given).
+When verifying a certificate signature
+the keyUsage extension (if present) of the candidate issuer certificate
+is checked to permit digitalSignature for signing proxy certificates
+or to permit keyCertSign for signing other certificates, respectively.
+If all operations complete successfully then certificate is considered
+valid. If any operation fails then the certificate is not valid.
+
+=head1 OPTIONS
+
+=head2 Trusted Certificate Options
+
+The following options specify how to supply the certificates
+that can be used as trust anchors for certain uses.
+As mentioned, a collection of such certificates is called a I<trust store>.
+
+Note that OpenSSL does not provide a default set of trust anchors. Many
+Linux distributions include a system default and configure OpenSSL to point
+to that. Mozilla maintains an influential trust store that can be found at
+L<https://www.mozilla.org/en-US/about/governance/policies/security-group/certs/>.
+
+The certificates to add to the trust store
+can be specified using following options.
+
+=over 4
+
+=item B<-CAfile> I<file>
+
+Load the specified file which contains a certificate
+or several of them in case the input is in PEM or PKCS#12 format.
+PEM-encoded certificates may also have trust attributes set.
+
+=item B<-no-CAfile>
+
+Do not load the default file of trusted certificates.
+
+=item B<-CApath> I<dir>
+
+Use the specified directory as a collection of trusted certificates,
+i.e., a trust store.
+Files should be named with the hash value of the X.509 SubjectName of each
+certificate. This is so that the library can extract the IssuerName,
+hash it, and directly lookup the file to get the issuer certificate.
+See L<openssl-rehash(1)> for information on creating this type of directory.
+
+=item B<-no-CApath>
+
+Do not use the default directory of trusted certificates.
+
+=item B<-CAstore> I<uri>
+
+Use I<uri> as a store of CA certificates.
+The URI may indicate a single certificate, as well as a collection of them.
+With URIs in the C<file:> scheme, this acts as B<-CAfile> or
+B<-CApath>, depending on if the URI indicates a single file or
+directory.
+See L<ossl_store-file(7)> for more information on the C<file:> scheme.
+
+These certificates are also used when building the server certificate
+chain (for example with L<openssl-s_server(1)>) or client certificate
+chain (for example with L<openssl-s_time(1)>).
+
+=item B<-no-CAstore>
+
+Do not use the default store of trusted CA certificates.
+
+=back
+
+=head2 Verification Options
+
+The certificate verification can be fine-tuned with the following flags.
+
+=over 4
+
+=item B<-verbose>
+
+Print extra information about the operations being performed.
+
+=item B<-attime> I<timestamp>
+
+Perform validation checks using time specified by I<timestamp> and not
+current system time. I<timestamp> is the number of seconds since
+January 1, 1970 (i.e., the Unix Epoch).
+
+=item B<-no_check_time>
+
+This option suppresses checking the validity period of certificates and CRLs
+against the current time. If option B<-attime> is used to specify
+a verification time, the check is not suppressed.
+
+=item B<-x509_strict>
+
+This disables non-compliant workarounds for broken certificates.
+Thus errors are thrown on certificates not compliant with RFC 5280.
+
+When this option is set,
+among others, the following certificate well-formedness conditions are checked:
+
+=over 4
+
+=item *
+
+The basicConstraints of CA certificates must be marked critical.
+
+=item *
+
+CA certificates must explicitly include the keyUsage extension.
+
+=item *
+
+If a pathlenConstraint is given the key usage keyCertSign must be allowed.
+
+=item *
+
+The pathlenConstraint must not be given for non-CA certificates.
+
+=item *
+
+The issuer name of any certificate must not be empty.
+
+=item *
+
+The subject name of CA certs, certs with keyUsage crlSign, and certs
+without subjectAlternativeName must not be empty.
+
+=item *
+
+If a subjectAlternativeName extension is given it must not be empty.
+
+=item *
+
+The signatureAlgorithm field and the cert signature must be consistent.
+
+=item *
+
+Any given authorityKeyIdentifier and any given subjectKeyIdentifier
+must not be marked critical.
+
+=item *
+
+The authorityKeyIdentifier must be given for X.509v3 certs unless they
+are self-signed.
+
+=item *
+
+The subjectKeyIdentifier must be given for all X.509v3 CA certs.
+
+=back
+
+=item B<-ignore_critical>
+
+Normally if an unhandled critical extension is present that is not
+supported by OpenSSL the certificate is rejected (as required by RFC5280).
+If this option is set critical extensions are ignored.
+
+=item B<-issuer_checks>
+
+Ignored.
+
+=item B<-crl_check>
+
+Checks end entity certificate validity by attempting to look up a valid CRL.
+If a valid CRL cannot be found an error occurs.
+
+=item B<-crl_check_all>
+
+Checks the validity of B<all> certificates in the chain by attempting
+to look up valid CRLs.
+
+=item B<-use_deltas>
+
+Enable support for delta CRLs.
+
+=item B<-extended_crl>
+
+Enable extended CRL features such as indirect CRLs and alternate CRL
+signing keys.
+
+=item B<-suiteB_128_only>, B<-suiteB_128>, B<-suiteB_192>
+
+Enable the Suite B mode operation at 128 bit Level of Security, 128 bit or
+192 bit, or only 192 bit Level of Security respectively.
+See RFC6460 for details. In particular the supported signature algorithms are
+reduced to support only ECDSA and SHA256 or SHA384 and only the elliptic curves
+P-256 and P-384.
+
+=item B<-auth_level> I<level>
+
+Set the certificate chain authentication security level to I<level>.
+The authentication security level determines the acceptable signature and
+public key strength when verifying certificate chains. For a certificate
+chain to validate, the public keys of all the certificates must meet the
+specified security I<level>. The signature algorithm security level is
+enforced for all the certificates in the chain except for the chain's
+I<trust anchor>, which is either directly trusted or validated by means
+other than its signature. See L<SSL_CTX_set_security_level(3)> for the
+definitions of the available levels. The default security level is -1,
+or "not set". At security level 0 or lower all algorithms are acceptable.
+Security level 1 requires at least 80-bit-equivalent security and is broadly
+interoperable, though it will, for example, reject MD5 signatures or RSA
+keys shorter than 1024 bits.
+
+=item B<-partial_chain>
+
+Allow verification to succeed if an incomplete chain can be built.
+That is, a chain ending in a certificate that normally would not be trusted
+(because it has no matching positive trust attributes and is not self-signed)
+but is an element of the trust store.
+This certificate may be self-issued or belong to an intermediate CA.
+
+=item B<-check_ss_sig>
+
+Verify the signature of
+the last certificate in a chain if the certificate is supposedly self-signed.
+This is prohibited and will result in an error if it is a non-conforming CA
+certificate with key usage restrictions not including the keyCertSign bit.
+This verification is disabled by default because it doesn't add any security.
+
+=item B<-allow_proxy_certs>
+
+Allow the verification of proxy certificates.
+
+=item B<-trusted_first>
+
+As of OpenSSL 1.1.0 this option is on by default and cannot be disabled.
+
+When constructing the certificate chain, the trusted certificates specified
+via B<-CAfile>, B<-CApath>, B<-CAstore> or B<-trusted> are always used
+before any certificates specified via B<-untrusted>.
+
+=item B<-no_alt_chains>
+
+As of OpenSSL 1.1.0, since B<-trusted_first> always on, this option has no
+effect.
+
+=item B<-trusted> I<file>
+
+Parse I<file> as a set of one or more certificates.
+Each of them qualifies as trusted if has a suitable positive trust attribute
+or it is self-signed or the B<-partial_chain> option is specified.
+This option implies the B<-no-CAfile>, B<-no-CApath>, and B<-no-CAstore> options
+and it cannot be used with the B<-CAfile>, B<-CApath> or B<-CAstore> options, so
+only certificates specified using the B<-trusted> option are trust anchors.
+This option may be used multiple times.
+
+=item B<-untrusted> I<file>
+
+Parse I<file> as a set of one or more certificates.
+All certificates (typically of intermediate CAs) are considered untrusted
+and may be used to
+construct a certificate chain from the target certificate to a trust anchor.
+This option may be used multiple times.
+
+=item B<-policy> I<arg>
+
+Enable policy processing and add I<arg> to the user-initial-policy-set (see
+RFC5280). The policy I<arg> can be an object name an OID in numeric form.
+This argument can appear more than once.
+
+=item B<-explicit_policy>
+
+Set policy variable require-explicit-policy (see RFC5280).
+
+=item B<-policy_check>
+
+Enables certificate policy processing.
+
+=item B<-policy_print>
+
+Print out diagnostics related to policy processing.
+
+=item B<-inhibit_any>
+
+Set policy variable inhibit-any-policy (see RFC5280).
+
+=item B<-inhibit_map>
+
+Set policy variable inhibit-policy-mapping (see RFC5280).
+
+=item B<-purpose> I<purpose>
+
+The intended use for the certificate.
+Currently defined purposes are C<sslclient>, C<sslserver>, C<nssslserver>,
+C<smimesign>, C<smimeencrypt>, C<crlsign>, C<ocsphelper>, C<timestampsign>,
+and C<any>.
+If peer certificate verification is enabled, by default the TLS implementation
+as well as the commands B<s_client> and B<s_server> check for consistency
+with TLS server or TLS client use, respectively.
+
+While IETF RFC 5280 says that B<id-kp-serverAuth> and B<id-kp-clientAuth>
+are only for WWW use, in practice they are used for all kinds of TLS clients
+and servers, and this is what OpenSSL assumes as well.
+
+=item B<-verify_depth> I<num>
+
+Limit the certificate chain to I<num> intermediate CA certificates.
+A maximal depth chain can have up to I<num>+2 certificates, since neither the
+end-entity certificate nor the trust-anchor certificate count against the
+B<-verify_depth> limit.
+
+=item B<-verify_email> I<email>
+
+Verify if I<email> matches the email address in Subject Alternative Name or
+the email in the subject Distinguished Name.
+
+=item B<-verify_hostname> I<hostname>
+
+Verify if I<hostname> matches DNS name in Subject Alternative Name or
+Common Name in the subject certificate.
+
+=item B<-verify_ip> I<ip>
+
+Verify if I<ip> matches the IP address in Subject Alternative Name of
+the subject certificate.
+
+=item B<-verify_name> I<name>
+
+Use default verification policies like trust model and required certificate
+policies identified by I<name>.
+The trust model determines which auxiliary trust or reject OIDs are applicable
+to verifying the given certificate chain.
+They can be given using the B<-addtrust> and B<-addreject> options
+for L<openssl-x509(1)>.
+Supported policy names include: B<default>, B<pkcs7>, B<smime_sign>,
+B<ssl_client>, B<ssl_server>.
+These mimics the combinations of purpose and trust settings used in SSL, CMS
+and S/MIME.
+As of OpenSSL 1.1.0, the trust model is inferred from the purpose when not
+specified, so the B<-verify_name> options are functionally equivalent to the
+corresponding B<-purpose> settings.
+
+=back
+
+=head2 Extended Verification Options
+
+Sometimes there may be more than one certificate chain leading to an
+end-entity certificate.
+This usually happens when a root or intermediate CA signs a certificate
+for another a CA in other organization.
+Another reason is when a CA might have intermediates that use two different
+signature formats, such as a SHA-1 and a SHA-256 digest.
+
+The following options can be used to provide data that will allow the
+OpenSSL command to generate an alternative chain.
+
+=over 4
+
+=item B<-xkey> I<infile>, B<-xcert> I<infile>, B<-xchain>
+
+Specify an extra certificate, private key and certificate chain. These behave
+in the same manner as the B<-cert>, B<-key> and B<-cert_chain> options. When
+specified, the callback returning the first valid chain will be in use by the
+client.
+
+=item B<-xchain_build>
+
+Specify whether the application should build the certificate chain to be
+provided to the server for the extra certificates via the B<-xkey>,
+B<-xcert>, and B<-xchain> options.
+
+=item B<-xcertform> B<DER>|B<PEM>|B<P12>
+
+The input format for the extra certificate.
+This option has no effect and is retained for backward compatibility only.
+
+=item B<-xkeyform> B<DER>|B<PEM>|B<P12>
+
+The input format for the extra key.
+This option has no effect and is retained for backward compatibility only.
+
+=back
+
+=head2 Certificate Extensions
+
+Options like B<-purpose> lead to checking the certificate extensions,
+which determine what the target certificate and intermediate CA certificates
+can be used for.
+
+=head3 Basic Constraints
+
+The basicConstraints extension CA flag is used to determine whether the
+certificate can be used as a CA. If the CA flag is true then it is a CA,
+if the CA flag is false then it is not a CA. B<All> CAs should have the
+CA flag set to true.
+
+If the basicConstraints extension is absent,
+which includes the case that it is an X.509v1 certificate,
+then the certificate is considered to be a "possible CA" and
+other extensions are checked according to the intended use of the certificate.
+The treatment of certificates without basicConstraints as a CA
+is presently supported, but this could change in the future.
+
+=head3 Key Usage
+
+If the keyUsage extension is present then additional restraints are
+made on the uses of the certificate. A CA certificate B<must> have the
+keyCertSign bit set if the keyUsage extension is present.
+
+=head3 Extended Key Usage
+
+The extKeyUsage (EKU) extension places additional restrictions on the
+certificate uses. If this extension is present (whether critical or not)
+the key can only be used for the purposes specified.
+
+A complete description of each check is given below. The comments about
+basicConstraints and keyUsage and X.509v1 certificates above apply to B<all>
+CA certificates.
+
+
+=over 4
+
+=item B<SSL Client>
+
+The extended key usage extension must be absent or include the "web client
+authentication" OID. The keyUsage extension must be absent or it must have the
+digitalSignature bit set. The Netscape certificate type must be absent
+or it must have the SSL client bit set.
+
+=item B<SSL Client CA>
+
+The extended key usage extension must be absent or include the "web client
+authentication" OID.
+The Netscape certificate type must be absent or it must have the SSL CA bit set.
+This is used as a work around if the basicConstraints extension is absent.
+
+=item B<SSL Server>
+
+The extended key usage extension must be absent or include the "web server
+authentication" and/or one of the SGC OIDs. The keyUsage extension must be
+absent or it
+must have the digitalSignature, the keyEncipherment set or both bits set.
+The Netscape certificate type must be absent or have the SSL server bit set.
+
+=item B<SSL Server CA>
+
+The extended key usage extension must be absent or include the "web server
+authentication" and/or one of the SGC OIDs. The Netscape certificate type must
+be absent or the SSL CA bit must be set.
+This is used as a work around if the basicConstraints extension is absent.
+
+=item B<Netscape SSL Server>
+
+For Netscape SSL clients to connect to an SSL server it must have the
+keyEncipherment bit set if the keyUsage extension is present. This isn't
+always valid because some cipher suites use the key for digital signing.
+Otherwise it is the same as a normal SSL server.
+
+=item B<Common S/MIME Client Tests>
+
+The extended key usage extension must be absent or include the "email
+protection" OID. The Netscape certificate type must be absent or should have the
+S/MIME bit set. If the S/MIME bit is not set in the Netscape certificate type
+then the SSL client bit is tolerated as an alternative but a warning is shown.
+This is because some Verisign certificates don't set the S/MIME bit.
+
+=item B<S/MIME Signing>
+
+In addition to the common S/MIME client tests the digitalSignature bit or
+the nonRepudiation bit must be set if the keyUsage extension is present.
+
+=item B<S/MIME Encryption>
+
+In addition to the common S/MIME tests the keyEncipherment bit must be set
+if the keyUsage extension is present.
+
+=item B<S/MIME CA>
+
+The extended key usage extension must be absent or include the "email
+protection" OID. The Netscape certificate type must be absent or must have the
+S/MIME CA bit set.
+This is used as a work around if the basicConstraints extension is absent.
+
+=item B<CRL Signing>
+
+The keyUsage extension must be absent or it must have the CRL signing bit
+set.
+
+=item B<CRL Signing CA>
+
+The normal CA tests apply. Except in this case the basicConstraints extension
+must be present.
+
+=back
+
+=head1 BUGS
+
+The issuer checks still suffer from limitations in the underlying X509_LOOKUP
+API. One consequence of this is that trusted certificates with matching
+subject name must appear in a file (as specified by the B<-CAfile> option),
+a directory (as specified by B<-CApath>),
+or a store (as specified by B<-CAstore>).
+If there are multiple such matches, possibly in multiple locations,
+only the first one (in the mentioned order of locations) is recognised.
+
+=head1 SEE ALSO
+
+L<X509_verify_cert(3)>,
+L<openssl-verify(1)>,
+L<openssl-ocsp(1)>,
+L<openssl-ts(1)>,
+L<openssl-s_client(1)>,
+L<openssl-s_server(1)>,
+L<openssl-smime(1)>,
+L<openssl-cmp(1)>,
+L<openssl-cms(1)>
+
+=head1 HISTORY
+
+The checks enabled by B<-x509_strict> have been extended in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-verify.pod.in b/doc/man1/openssl-verify.pod.in
new file mode 100644
index 000000000000..7e51af6eac15
--- /dev/null
+++ b/doc/man1/openssl-verify.pod.in
@@ -0,0 +1,150 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-verify - certificate verification command
+
+=head1 SYNOPSIS
+
+B<openssl> B<verify>
+[B<-help>]
+[B<-CRLfile> I<filename>|I<uri>]
+[B<-crl_download>]
+[B<-show_chain>]
+[B<-verbose>]
+[B<-trusted> I<filename>|I<uri>]
+[B<-untrusted> I<filename>|I<uri>]
+[B<-vfyopt> I<nm>:I<v>]
+{- $OpenSSL::safe::opt_name_synopsis -}
+{- $OpenSSL::safe::opt_trust_synopsis -}
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_v_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
+[B<-->]
+[I<certificate> ...]
+
+=head1 DESCRIPTION
+
+This command verifies certificate chains. If a certificate chain has multiple
+problems, this program attempts to display all of them.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-CRLfile> I<filename>|I<uri>
+
+The file or URI should contain one or more CRLs in PEM or DER format.
+This option can be specified more than once to include CRLs from multiple
+sources.
+
+=item B<-crl_download>
+
+Attempt to download CRL information for certificates via their CDP entries.
+
+=item B<-show_chain>
+
+Display information about the certificate chain that has been built (if
+successful). Certificates in the chain that came from the untrusted list will be
+flagged as "untrusted".
+
+=item B<-verbose>
+
+Print extra information about the operations being performed.
+
+=item B<-trusted> I<filename>|I<uri>
+
+A file or URI of (more or less) trusted certificates.
+See L<openssl-verification-options(1)> for more information on trust settings.
+
+This option can be specified more than once to load certificates from multiple
+sources.
+
+=item B<-untrusted> I<filename>|I<uri>
+
+A file or URI of untrusted certificates to use for chain building.
+This option can be specified more than once to load certificates from multiple
+sources.
+
+=item B<-vfyopt> I<nm>:I<v>
+
+Pass options to the signature algorithm during verify operations.
+Names and values of these options are algorithm-specific.
+
+{- $OpenSSL::safe::opt_name_item -}
+
+{- $OpenSSL::safe::opt_engine_item -}
+{- output_off() if $disabled{"deprecated-3.0"}; "" -}
+To load certificates or CRLs that require engine support, specify the
+B<-engine> option before any of the
+B<-trusted>, B<-untrusted> or B<-CRLfile> options.
+{- output_on() if $disabled{"deprecated-3.0"}; "" -}
+
+{- $OpenSSL::safe::opt_trust_item -}
+
+{- $OpenSSL::safe::opt_v_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=item B<-->
+
+Indicates the last option. All arguments following this are assumed to be
+certificate files. This is useful if the first certificate filename begins
+with a B<->.
+
+=item I<certificate> ...
+
+One or more target certificates to verify, one per file. If no certificates are
+given, this command will attempt to read a single certificate from standard
+input.
+
+=back
+
+=head1 DIAGNOSTICS
+
+When a verify operation fails the output messages can be somewhat cryptic. The
+general form of the error message is:
+
+ server.pem: /C=AU/ST=Queensland/O=CryptSoft Pty Ltd/CN=Test CA (1024 bit)
+ error 24 at 1 depth lookup:invalid CA certificate
+
+The first line contains the name of the certificate being verified followed by
+the subject name of the certificate. The second line contains the error number
+and the depth. The depth is number of the certificate being verified when a
+problem was detected starting with zero for the target ("leaf") certificate
+itself then 1 for the CA that signed the target certificate and so on.
+Finally a textual version of the error number is presented.
+
+A list of the error codes and messages can be found in
+L<X509_STORE_CTX_get_error(3)>; the full list is defined in the header file
+F<< <openssl/x509_vfy.h> >>.
+
+This command ignores many errors, in order to allow all the problems with a
+certificate chain to be determined.
+
+=head1 SEE ALSO
+
+L<openssl-verification-options(1)>,
+L<openssl-x509(1)>,
+L<ossl_store-file(7)>
+
+=head1 HISTORY
+
+The B<-show_chain> option was added in OpenSSL 1.1.0.
+
+The B<-engine option> was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-version.pod.in b/doc/man1/openssl-version.pod.in
new file mode 100644
index 000000000000..b2f09107242b
--- /dev/null
+++ b/doc/man1/openssl-version.pod.in
@@ -0,0 +1,96 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-version - print OpenSSL version information
+
+=head1 SYNOPSIS
+
+B<openssl version>
+[B<-help>]
+[B<-a>]
+[B<-v>]
+[B<-b>]
+[B<-o>]
+[B<-f>]
+[B<-p>]
+[B<-d>]
+[B<-e>]
+[B<-m>]
+[B<-r>]
+[B<-c>]
+
+=head1 DESCRIPTION
+
+This command is used to print out version information about OpenSSL.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-a>
+
+All information, this is the same as setting all the other flags.
+
+=item B<-v>
+
+The current OpenSSL version.
+
+=item B<-b>
+
+The date the current version of OpenSSL was built.
+
+=item B<-o>
+
+Option information: various options set when the library was built.
+
+=item B<-f>
+
+Compilation flags.
+
+=item B<-p>
+
+Platform setting.
+
+=item B<-d>
+
+OPENSSLDIR setting.
+
+=item B<-e>
+
+ENGINESDIR settings.
+
+=item B<-m>
+
+MODULESDIR settings.
+
+=item B<-r>
+
+The random number generator source settings.
+
+=item B<-c>
+
+The OpenSSL CPU settings info.
+
+=back
+
+=head1 NOTES
+
+The output of C<openssl version -a> would typically be used when sending
+in a bug report.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl-x509.pod.in b/doc/man1/openssl-x509.pod.in
new file mode 100644
index 000000000000..dd8f17154af9
--- /dev/null
+++ b/doc/man1/openssl-x509.pod.in
@@ -0,0 +1,794 @@
+=pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
+
+=head1 NAME
+
+openssl-x509 - Certificate display and signing command
+
+=head1 SYNOPSIS
+
+B<openssl> B<x509>
+[B<-help>]
+[B<-in> I<filename>|I<uri>]
+[B<-passin> I<arg>]
+[B<-new>]
+[B<-x509toreq>]
+[B<-req>]
+[B<-copy_extensions> I<arg>]
+[B<-inform> B<DER>|B<PEM>]
+[B<-vfyopt> I<nm>:I<v>]
+[B<-key> I<filename>|I<uri>]
+[B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-signkey> I<filename>|I<uri>]
+[B<-out> I<filename>]
+[B<-outform> B<DER>|B<PEM>]
+[B<-nocert>]
+[B<-noout>]
+[B<-dateopt>]
+[B<-text>]
+[B<-certopt> I<option>]
+[B<-fingerprint>]
+[B<-alias>]
+[B<-serial>]
+[B<-startdate>]
+[B<-enddate>]
+[B<-dates>]
+[B<-subject>]
+[B<-issuer>]
+{- $OpenSSL::safe::opt_name_synopsis -}
+[B<-email>]
+[B<-hash>]
+[B<-subject_hash>]
+[B<-subject_hash_old>]
+[B<-issuer_hash>]
+[B<-issuer_hash_old>]
+[B<-ext> I<extensions>]
+[B<-ocspid>]
+[B<-ocsp_uri>]
+[B<-purpose>]
+[B<-pubkey>]
+[B<-modulus>]
+[B<-checkend> I<num>]
+[B<-checkhost> I<host>]
+[B<-checkemail> I<host>]
+[B<-checkip> I<ipaddr>]
+[B<-set_serial> I<n>]
+[B<-next_serial>]
+[B<-days> I<arg>]
+[B<-preserve_dates>]
+[B<-subj> I<arg>]
+[B<-force_pubkey> I<filename>]
+[B<-clrext>]
+[B<-extfile> I<filename>]
+[B<-extensions> I<section>]
+[B<-sigopt> I<nm>:I<v>]
+[B<-badsig>]
+[B<-I<digest>>]
+[B<-CA> I<filename>|I<uri>]
+[B<-CAform> B<DER>|B<PEM>|B<P12>]
+[B<-CAkey> I<filename>|I<uri>]
+[B<-CAkeyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-CAserial> I<filename>]
+[B<-CAcreateserial>]
+[B<-trustout>]
+[B<-setalias> I<arg>]
+[B<-clrtrust>]
+[B<-addtrust> I<arg>]
+[B<-clrreject>]
+[B<-addreject> I<arg>]
+{- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
+
+=head1 DESCRIPTION
+
+This command is a multi-purposes certificate handling command.
+It can be used to print certificate information,
+convert certificates to various forms, edit certificate trust settings,
+generate certificates from scratch or from certificating requests
+and then self-signing them or signing them like a "micro CA".
+
+Since there are a large number of options they will split up into
+various sections.
+
+=head1 OPTIONS
+
+=head2 Input, Output, and General Purpose Options
+
+=over 4
+
+=item B<-help>
+
+Print out a usage message.
+
+=item B<-in> I<filename>|I<uri>
+
+This specifies the input to read a certificate from
+or the input file for reading a certificate request if the B<-req> flag is used.
+In both cases this defaults to standard input.
+
+This option cannot be combined with the B<-new> flag.
+
+=item B<-passin> I<arg>
+
+The key and certificate file password source.
+For more information about the format of I<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-new>
+
+Generate a certificate from scratch, not using an input certificate
+or certificate request. So the B<-in> option must not be used in this case.
+Instead, the B<-subj> option needs to be given.
+The public key to include can be given with the B<-force_pubkey> option
+and defaults to the key given with the B<-key> (or B<-signkey>) option,
+which implies self-signature.
+
+=item B<-x509toreq>
+
+Output a PKCS#10 certificate request (rather than a certificate).
+The B<-key> (or B<-signkey>) option must be used to provide the private key for
+self-signing; the corresponding public key is placed in the subjectPKInfo field.
+
+X.509 extensions included in a certificate input are not copied by default.
+X.509 extensions to be added can be specified using the B<-extfile> option.
+
+=item B<-req>
+
+By default a certificate is expected on input.
+With this option a PKCS#10 certificate request is expected instead,
+which must be correctly self-signed.
+
+X.509 extensions included in the request are not copied by default.
+X.509 extensions to be added can be specified using the B<-extfile> option.
+
+=item B<-copy_extensions> I<arg>
+
+Determines how to handle X.509 extensions
+when converting from a certificate to a request using the B<-x509toreq> option
+or converting from a request to a certificate using the B<-req> option.
+If I<arg> is B<none> or this option is not present then extensions are ignored.
+If I<arg> is B<copy> or B<copyall> then all extensions are copied,
+except that subject identifier and authority key identifier extensions
+are not taken over when producing a certificate request.
+
+The B<-ext> option can be used to further restrict which extensions to copy.
+
+=item B<-inform> B<DER>|B<PEM>
+
+The input file format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-vfyopt> I<nm>:I<v>
+
+Pass options to the signature algorithm during verify operations.
+Names and values of these options are algorithm-specific.
+
+=item B<-key> I<filename>|I<uri>
+
+This option provides the private key for signing a new certificate or
+certificate request.
+Unless B<-force_pubkey> is given, the corresponding public key is placed in
+the new certificate or certificate request, resulting in a self-signature.
+
+This option cannot be used in conjunction with the B<-CA> option.
+
+It sets the issuer name to the subject name (i.e., makes it self-issued)
+and changes the public key to the supplied value (unless overridden
+by B<-force_pubkey>).
+Unless the B<-preserve_dates> option is supplied,
+it sets the validity start date to the current time
+and the end date to a value determined by the B<-days> option.
+
+=item B<-signkey> I<filename>|I<uri>
+
+This option is an alias of B<-key>.
+
+=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The key input format; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-out> I<filename>
+
+This specifies the output filename to write to or standard output by default.
+
+=item B<-outform> B<DER>|B<PEM>
+
+The output format; the default is B<PEM>.
+See L<openssl-format-options(1)> for details.
+
+=item B<-nocert>
+
+Do not output a certificate (except for printing as requested by below options).
+
+=item B<-noout>
+
+This option prevents output except for printing as requested by below options.
+
+=back
+
+=head2 Certificate Printing Options
+
+Note: the B<-alias> and B<-purpose> options are also printing options
+but are described in the L</Trust Settings> section.
+
+=over 4
+
+=item B<-dateopt>
+
+Specify the date output format. Values are: rfc_822 and iso_8601.
+Defaults to rfc_822.
+
+=item B<-text>
+
+Prints out the certificate in text form. Full details are printed including the
+public key, signature algorithms, issuer and subject names, serial number
+any extensions present and any trust settings.
+
+=item B<-certopt> I<option>
+
+Customise the print format used with B<-text>. The I<option> argument
+can be a single option or multiple options separated by commas.
+The B<-certopt> switch may be also be used more than once to set multiple
+options. See the L</Text Printing Flags> section for more information.
+
+=item B<-fingerprint>
+
+Calculates and prints the digest of the DER encoded version of the entire
+certificate (see digest options).
+This is commonly called a "fingerprint". Because of the nature of message
+digests, the fingerprint of a certificate is unique to that certificate and
+two certificates with the same fingerprint can be considered to be the same.
+
+=item B<-alias>
+
+Prints the certificate "alias" (nickname), if any.
+
+=item B<-serial>
+
+Prints the certificate serial number.
+
+=item B<-startdate>
+
+Prints out the start date of the certificate, that is the notBefore date.
+
+=item B<-enddate>
+
+Prints out the expiry date of the certificate, that is the notAfter date.
+
+=item B<-dates>
+
+Prints out the start and expiry dates of a certificate.
+
+=item B<-subject>
+
+Prints the subject name.
+
+=item B<-issuer>
+
+Prints the issuer name.
+
+{- $OpenSSL::safe::opt_name_item -}
+
+=item B<-email>
+
+Prints the email address(es) if any.
+
+=item B<-hash>
+
+Synonym for "-subject_hash" for backward compatibility reasons.
+
+=item B<-subject_hash>
+
+Prints the "hash" of the certificate subject name. This is used in OpenSSL to
+form an index to allow certificates in a directory to be looked up by subject
+name.
+
+=item B<-subject_hash_old>
+
+Prints the "hash" of the certificate subject name using the older algorithm
+as used by OpenSSL before version 1.0.0.
+
+=item B<-issuer_hash>
+
+Prints the "hash" of the certificate issuer name.
+
+=item B<-issuer_hash_old>
+
+Prints the "hash" of the certificate issuer name using the older algorithm
+as used by OpenSSL before version 1.0.0.
+
+=item B<-ext> I<extensions>
+
+Prints out the certificate extensions in text form.
+Can also be used to restrict which extensions to copy.
+Extensions are specified
+with a comma separated string, e.g., "subjectAltName,subjectKeyIdentifier".
+See the L<x509v3_config(5)> manual page for the extension names.
+
+=item B<-ocspid>
+
+Prints the OCSP hash values for the subject name and public key.
+
+=item B<-ocsp_uri>
+
+Prints the OCSP responder address(es) if any.
+
+=item B<-purpose>
+
+This option performs tests on the certificate extensions and outputs
+the results. For a more complete description see
+L<openssl-verification-options(1)/Certificate Extensions>.
+
+=item B<-pubkey>
+
+Prints the certificate's SubjectPublicKeyInfo block in PEM format.
+
+=item B<-modulus>
+
+This option prints out the value of the modulus of the public key
+contained in the certificate.
+
+=back
+
+=head2 Certificate Checking Options
+
+=over 4
+
+=item B<-checkend> I<arg>
+
+Checks if the certificate expires within the next I<arg> seconds and exits
+nonzero if yes it will expire or zero if not.
+
+=item B<-checkhost> I<host>
+
+Check that the certificate matches the specified host.
+
+=item B<-checkemail> I<email>
+
+Check that the certificate matches the specified email address.
+
+=item B<-checkip> I<ipaddr>
+
+Check that the certificate matches the specified IP address.
+
+=back
+
+=head2 Certificate Output Options
+
+=over 4
+
+=item B<-set_serial> I<n>
+
+Specifies the serial number to use.
+This option can be used with the B<-key>, B<-signkey>, or B<-CA> options.
+If used in conjunction with the B<-CA> option
+the serial number file (as specified by the B<-CAserial> option) is not used.
+
+The serial number can be decimal or hex (if preceded by C<0x>).
+
+=item B<-next_serial>
+
+Set the serial to be one more than the number in the certificate.
+
+=item B<-days> I<arg>
+
+Specifies the number of days until a newly generated certificate expires.
+The default is 30.
+Cannot be used together with the B<-preserve_dates> option.
+
+=item B<-preserve_dates>
+
+When signing a certificate, preserve "notBefore" and "notAfter" dates of any
+input certificate instead of adjusting them to current time and duration.
+Cannot be used together with the B<-days> option.
+
+=item B<-subj> I<arg>
+
+When a certificate is created set its subject name to the given value.
+When the certificate is self-signed the issuer name is set to the same value.
+
+The arg must be formatted as C</type0=value0/type1=value1/type2=...>.
+Special characters may be escaped by C<\> (backslash), whitespace is retained.
+Empty values are permitted, but the corresponding type will not be included
+in the certificate.
+Giving a single C</> will lead to an empty sequence of RDNs (a NULL-DN).
+Multi-valued RDNs can be formed by placing a C<+> character instead of a C</>
+between the AttributeValueAssertions (AVAs) that specify the members of the set.
+Example:
+
+C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
+
+This option can be used in conjunction with the B<-force_pubkey> option
+to create a certificate even without providing an input certificate
+or certificate request.
+
+=item B<-force_pubkey> I<filename>
+
+When a certificate is created set its public key to the key in I<filename>
+instead of the key contained in the input
+or given with the B<-key> (or B<-signkey>) option.
+
+This option is useful for creating self-issued certificates that are not
+self-signed, for instance when the key cannot be used for signing, such as DH.
+It can also be used in conjunction with B<-new> and B<-subj> to directly
+generate a certificate containing any desired public key.
+
+=item B<-clrext>
+
+When transforming a certificate to a new certificate
+by default all certificate extensions are retained.
+
+When transforming a certificate or certificate request,
+the B<-clrext> option prevents taking over any extensions from the source.
+In any case, when producing a certificate request,
+neither subject identifier nor authority key identifier extensions are included.
+
+=item B<-extfile> I<filename>
+
+Configuration file containing certificate and request X.509 extensions to add.
+
+=item B<-extensions> I<section>
+
+The section in the extfile to add X.509 extensions from.
+If this option is not
+specified then the extensions should either be contained in the unnamed
+(default) section or the default section should contain a variable called
+"extensions" which contains the section to use.
+See the L<x509v3_config(5)> manual page for details of the
+extension section format.
+
+=item B<-sigopt> I<nm>:I<v>
+
+Pass options to the signature algorithm during sign operations.
+This option may be given multiple times.
+Names and values provided using this option are algorithm-specific.
+
+=item B<-badsig>
+
+Corrupt the signature before writing it; this can be useful
+for testing.
+
+=item B<-I<digest>>
+
+The digest to use.
+This affects any signing or printing option that uses a message
+digest, such as the B<-fingerprint>, B<-key>, and B<-CA> options.
+Any digest supported by the L<openssl-dgst(1)> command can be used.
+If not specified then SHA1 is used with B<-fingerprint> or
+the default digest for the signing algorithm is used, typically SHA256.
+
+=back
+
+=head2 Micro-CA Options
+
+=over 4
+
+=item B<-CA> I<filename>|I<uri>
+
+Specifies the "CA" certificate to be used for signing.
+When present, this behaves like a "micro CA" as follows:
+The subject name of the "CA" certificate is placed as issuer name in the new
+certificate, which is then signed using the "CA" key given as detailed below.
+
+This option cannot be used in conjunction with B<-key> (or B<-signkey>).
+This option is normally combined with the B<-req> option referencing a CSR.
+Without the B<-req> option the input must be an existing certificate
+unless the B<-new> option is given, which generates a certificate from scratch.
+
+=item B<-CAform> B<DER>|B<PEM>|B<P12>,
+
+The format for the CA certificate; unspecifed by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-CAkey> I<filename>|I<uri>
+
+Sets the CA private key to sign a certificate with.
+The private key must match the public key of the certificate given with B<-CA>.
+If this option is not provided then the key must be present in the B<-CA> input.
+
+=item B<-CAkeyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+
+The format for the CA key; unspecified by default.
+See L<openssl-format-options(1)> for details.
+
+=item B<-CAserial> I<filename>
+
+Sets the CA serial number file to use.
+
+When creating a certificate with this option and with the B<-CA> option,
+the certificate serial number is stored in the given file.
+This file consists of one line containing
+an even number of hex digits with the serial number used last time.
+After reading this number, it is incremented and used, and the file is updated.
+
+The default filename consists of the CA certificate file base name with
+F<.srl> appended. For example if the CA certificate file is called
+F<mycacert.pem> it expects to find a serial number file called
+F<mycacert.srl>.
+
+If the B<-CA> option is specified and neither <-CAserial> or <-CAcreateserial>
+is given and the default serial number file does not exist,
+a random number is generated; this is the recommended practice.
+
+=item B<-CAcreateserial>
+
+With this option and the B<-CA> option
+the CA serial number file is created if it does not exist.
+A random number is generated, used for the certificate,
+and saved into the serial number file determined as described above.
+
+=back
+
+=head2 Trust Settings
+
+A B<trusted certificate> is an ordinary certificate which has several
+additional pieces of information attached to it such as the permitted
+and prohibited uses of the certificate and possibly an "alias" (nickname).
+
+Normally when a certificate is being verified at least one certificate
+must be "trusted". By default a trusted certificate must be stored
+locally and must be a root CA: any certificate chain ending in this CA
+is then usable for any purpose.
+
+Trust settings currently are only used with a root CA.
+They allow a finer control over the purposes the root CA can be used for.
+For example, a CA may be trusted for SSL client but not SSL server use.
+
+See L<openssl-verification-options(1)> for more information
+on the meaning of trust settings.
+
+Future versions of OpenSSL will recognize trust settings on any
+certificate: not just root CAs.
+
+=over 4
+
+=item B<-trustout>
+
+Mark any certificate PEM output as <trusted> certificate rather than ordinary.
+An ordinary or trusted certificate can be input but by default an ordinary
+certificate is output and any trust settings are discarded.
+With the B<-trustout> option a trusted certificate is output. A trusted
+certificate is automatically output if any trust settings are modified.
+
+=item B<-setalias> I<arg>
+
+Sets the "alias" of the certificate. This will allow the certificate
+to be referred to using a nickname for example "Steve's Certificate".
+
+=item B<-clrtrust>
+
+Clears all the permitted or trusted uses of the certificate.
+
+=item B<-addtrust> I<arg>
+
+Adds a trusted certificate use.
+Any object name can be used here but currently only B<clientAuth>,
+B<serverAuth>, B<emailProtection>, and B<anyExtendedKeyUsage> are defined.
+As of OpenSSL 1.1.0, the last of these blocks all purposes when rejected or
+enables all purposes when trusted.
+Other OpenSSL applications may define additional uses.
+
+=item B<-clrreject>
+
+Clears all the prohibited or rejected uses of the certificate.
+
+=item B<-addreject> I<arg>
+
+Adds a prohibited trust anchor purpose.
+It accepts the same values as the B<-addtrust> option.
+
+=back
+
+=head2 Generic options
+
+=over 4
+
+{- $OpenSSL::safe::opt_r_item -}
+
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head2 Text Printing Flags
+
+As well as customising the name printing format, it is also possible to
+customise the actual fields printed using the B<certopt> option when
+the B<text> option is present. The default behaviour is to print all fields.
+
+=over 4
+
+=item B<compatible>
+
+Use the old format. This is equivalent to specifying no printing options at all.
+
+=item B<no_header>
+
+Don't print header information: that is the lines saying "Certificate"
+and "Data".
+
+=item B<no_version>
+
+Don't print out the version number.
+
+=item B<no_serial>
+
+Don't print out the serial number.
+
+=item B<no_signame>
+
+Don't print out the signature algorithm used.
+
+=item B<no_validity>
+
+Don't print the validity, that is the B<notBefore> and B<notAfter> fields.
+
+=item B<no_subject>
+
+Don't print out the subject name.
+
+=item B<no_issuer>
+
+Don't print out the issuer name.
+
+=item B<no_pubkey>
+
+Don't print out the public key.
+
+=item B<no_sigdump>
+
+Don't give a hexadecimal dump of the certificate signature.
+
+=item B<no_aux>
+
+Don't print out certificate trust information.
+
+=item B<no_extensions>
+
+Don't print out any X509V3 extensions.
+
+=item B<ext_default>
+
+Retain default extension behaviour: attempt to print out unsupported
+certificate extensions.
+
+=item B<ext_error>
+
+Print an error message for unsupported certificate extensions.
+
+=item B<ext_parse>
+
+ASN1 parse unsupported extensions.
+
+=item B<ext_dump>
+
+Hex dump unsupported extensions.
+
+=item B<ca_default>
+
+The value used by L<openssl-ca(1)>, equivalent to B<no_issuer>, B<no_pubkey>,
+B<no_header>, and B<no_version>.
+
+=back
+
+=head1 EXAMPLES
+
+Note: in these examples the '\' means the example should be all on one
+line.
+
+Print the contents of a certificate:
+
+ openssl x509 -in cert.pem -noout -text
+
+Print the "Subject Alternative Name" extension of a certificate:
+
+ openssl x509 -in cert.pem -noout -ext subjectAltName
+
+Print more extensions of a certificate:
+
+ openssl x509 -in cert.pem -noout -ext subjectAltName,nsCertType
+
+Print the certificate serial number:
+
+ openssl x509 -in cert.pem -noout -serial
+
+Print the certificate subject name:
+
+ openssl x509 -in cert.pem -noout -subject
+
+Print the certificate subject name in RFC2253 form:
+
+ openssl x509 -in cert.pem -noout -subject -nameopt RFC2253
+
+Print the certificate subject name in oneline form on a terminal
+supporting UTF8:
+
+ openssl x509 -in cert.pem -noout -subject -nameopt oneline,-esc_msb
+
+Print the certificate SHA1 fingerprint:
+
+ openssl x509 -sha1 -in cert.pem -noout -fingerprint
+
+Convert a certificate from PEM to DER format:
+
+ openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER
+
+Convert a certificate to a certificate request:
+
+ openssl x509 -x509toreq -in cert.pem -out req.pem -key key.pem
+
+Convert a certificate request into a self-signed certificate using
+extensions for a CA:
+
+ openssl x509 -req -in careq.pem -extfile openssl.cnf -extensions v3_ca \
+ -key key.pem -out cacert.pem
+
+Sign a certificate request using the CA certificate above and add user
+certificate extensions:
+
+ openssl x509 -req -in req.pem -extfile openssl.cnf -extensions v3_usr \
+ -CA cacert.pem -CAkey key.pem -CAcreateserial
+
+Set a certificate to be trusted for SSL client use and change set its alias to
+"Steve's Class 1 CA"
+
+ openssl x509 -in cert.pem -addtrust clientAuth \
+ -setalias "Steve's Class 1 CA" -out trust.pem
+
+=head1 NOTES
+
+The conversion to UTF8 format used with the name options assumes that
+T61Strings use the ISO8859-1 character set. This is wrong but Netscape
+and MSIE do this as do many certificates. So although this is incorrect
+it is more likely to print the majority of certificates correctly.
+
+The B<-email> option searches the subject name and the subject alternative
+name extension. Only unique email addresses will be printed out: it will
+not print the same address more than once.
+
+=head1 BUGS
+
+It is possible to produce invalid certificates or requests by specifying the
+wrong private key, using unsuitable X.509 extensions,
+or using inconsistent options in some cases: these should be checked.
+
+There should be options to explicitly set such things as start and end
+dates rather than an offset from the current time.
+
+=head1 SEE ALSO
+
+L<openssl(1)>,
+L<openssl-req(1)>,
+L<openssl-ca(1)>,
+L<openssl-genrsa(1)>,
+L<openssl-gendsa(1)>,
+L<openssl-verify(1)>,
+L<x509v3_config(5)>
+
+=head1 HISTORY
+
+The hash algorithm used in the B<-subject_hash> and B<-issuer_hash> options
+before OpenSSL 1.0.0 was based on the deprecated MD5 algorithm and the encoding
+of the distinguished name. In OpenSSL 1.0.0 and later it is based on a canonical
+version of the DN using SHA1. This means that any directories using the old
+form must have their links rebuilt using L<openssl-rehash(1)> or similar.
+
+The B<-signkey> option has been renamed to B<-key> in OpenSSL 3.0,
+keeping the old name as an alias.
+
+The B<-engine> option was deprecated in OpenSSL 3.0.
+
+The B<-C> option was removed in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/openssl.pod b/doc/man1/openssl.pod
index a39cf963d988..869e8e5ad8a1 100644
--- a/doc/man1/openssl.pod
+++ b/doc/man1/openssl.pod
@@ -2,18 +2,16 @@
=head1 NAME
-openssl - OpenSSL command line tool
+openssl - OpenSSL command line program
=head1 SYNOPSIS
B<openssl>
I<command>
-[ I<command_opts> ]
-[ I<command_args> ]
+[ I<options> ... ]
+[ I<parameters> ... ]
-B<openssl> B<list> [ B<standard-commands> | B<digest-commands> | B<cipher-commands> | B<cipher-algorithms> | B<digest-algorithms> | B<public-key-algorithms>]
-
-B<openssl> B<no->I<XXX> [ I<arbitrary options> ]
+B<openssl> B<no->I<XXX> [ I<options> ]
=head1 DESCRIPTION
@@ -21,49 +19,29 @@ OpenSSL is a cryptography toolkit implementing the Secure Sockets Layer (SSL
v2/v3) and Transport Layer Security (TLS v1) network protocols and related
cryptography standards required by them.
-The B<openssl> program is a command line tool for using the various
+The B<openssl> program is a command line program for using the various
cryptography functions of OpenSSL's B<crypto> library from the shell.
It can be used for
o Creation and management of private keys, public keys and parameters
o Public key cryptographic operations
o Creation of X.509 certificates, CSRs and CRLs
- o Calculation of Message Digests
+ o Calculation of Message Digests and Message Authentication Codes
o Encryption and Decryption with Ciphers
o SSL/TLS Client and Server Tests
o Handling of S/MIME signed or encrypted mail
- o Time Stamp requests, generation and verification
+ o Timestamp requests, generation and verification
=head1 COMMAND SUMMARY
-The B<openssl> program provides a rich variety of commands (I<command> in the
-SYNOPSIS above), each of which often has a wealth of options and arguments
-(I<command_opts> and I<command_args> in the SYNOPSIS).
+The B<openssl> program provides a rich variety of commands (I<command> in
+the L</SYNOPSIS> above).
+Each command can have many options and argument parameters, shown above as
+I<options> and I<parameters>.
Detailed documentation and use cases for most standard subcommands are available
-(e.g., L<x509(1)> or L<openssl-x509(1)>).
-
-Many commands use an external configuration file for some or all of their
-arguments and have a B<-config> option to specify that file.
-The environment variable B<OPENSSL_CONF> can be used to specify
-the location of the file.
-If the environment variable is not specified, then the file is named
-B<openssl.cnf> in the default certificate storage area, whose value
-depends on the configuration flags specified when the OpenSSL
-was built.
-
-The list parameters B<standard-commands>, B<digest-commands>,
-and B<cipher-commands> output a list (one entry per line) of the names
-of all standard commands, message digest commands, or cipher commands,
-respectively, that are available in the present B<openssl> utility.
-
-The list parameters B<cipher-algorithms> and
-B<digest-algorithms> list all cipher and message digest names, one entry per line. Aliases are listed as:
-
- from => to
-
-The list parameter B<public-key-algorithms> lists all supported public
-key algorithms.
+(e.g., L<openssl-x509(1)>). The subcommand L<openssl-list(1)> may be used to list
+subcommands.
The command B<no->I<XXX> tests whether a command of the
specified name is available. If no command named I<XXX> exists, it
@@ -76,6 +54,20 @@ availability of ciphers in the B<openssl> program. (B<no->I<XXX> is
not able to detect pseudo-commands such as B<quit>,
B<list>, or B<no->I<XXX> itself.)
+=head2 Configuration Option
+
+Many commands use an external configuration file for some or all of their
+arguments and have a B<-config> option to specify that file.
+The default name of the file is F<openssl.cnf> in the default certificate
+storage area, which can be determined from the L<openssl-version(1)>
+command using the B<-d> or B<-a> option.
+The environment variable B<OPENSSL_CONF> can be used to specify a different
+file location or to disable loading a configuration (using the empty string).
+
+Among others, the configuration file can be used to load modules
+and to specify parameters for generating certificates and random numbers.
+See L<config(5)> for details.
+
=head2 Standard Commands
=over 4
@@ -94,7 +86,7 @@ Cipher Suite Description Determination.
=item B<cms>
-CMS (Cryptographic Message Syntax) utility.
+CMS (Cryptographic Message Syntax) command.
=item B<crl>
@@ -106,17 +98,13 @@ CRL to PKCS#7 Conversion.
=item B<dgst>
-Message Digest Calculation.
-
-=item B<dh>
-
-Diffie-Hellman Parameter Management.
-Obsoleted by L<dhparam(1)>.
+Message Digest calculation. MAC calculations are superseded by
+L<openssl-mac(1)>.
=item B<dhparam>
Generation and Management of Diffie-Hellman Parameters. Superseded by
-L<genpkey(1)> and L<pkeyparam(1)>.
+L<openssl-genpkey(1)> and L<openssl-pkeyparam(1)>.
=item B<dsa>
@@ -125,7 +113,7 @@ DSA Data Management.
=item B<dsaparam>
DSA Parameter Generation and Management. Superseded by
-L<genpkey(1)> and L<pkeyparam(1)>.
+L<openssl-genpkey(1)> and L<openssl-pkeyparam(1)>.
=item B<ec>
@@ -137,7 +125,7 @@ EC parameter manipulation and generation.
=item B<enc>
-Encoding with Ciphers.
+Encryption, decryption, and encoding.
=item B<engine>
@@ -147,15 +135,14 @@ Engine (loadable module) information and manipulation.
Error Number to Error String Conversion.
-=item B<gendh>
+=item B<fipsinstall>
-Generation of Diffie-Hellman Parameters.
-Obsoleted by L<dhparam(1)>.
+FIPS configuration installation.
=item B<gendsa>
Generation of DSA Private Key from Parameters. Superseded by
-L<genpkey(1)> and L<pkey(1)>.
+L<openssl-genpkey(1)> and L<openssl-pkey(1)>.
=item B<genpkey>
@@ -163,7 +150,27 @@ Generation of Private Key or Parameters.
=item B<genrsa>
-Generation of RSA Private Key. Superseded by L<genpkey(1)>.
+Generation of RSA Private Key. Superseded by L<openssl-genpkey(1)>.
+
+=item B<help>
+
+Display information about a command's options.
+
+=item B<info>
+
+Display diverse information built into the OpenSSL libraries.
+
+=item B<kdf>
+
+Key Derivation Functions.
+
+=item B<list>
+
+List algorithms and features.
+
+=item B<mac>
+
+Message Authentication Code Calculation.
=item B<nseq>
@@ -171,7 +178,7 @@ Create or examine a Netscape certificate sequence.
=item B<ocsp>
-Online Certificate Status Protocol utility.
+Online Certificate Status Protocol command.
=item B<passwd>
@@ -187,7 +194,7 @@ PKCS#7 Data Management.
=item B<pkcs8>
-PKCS#8 format private key conversion tool.
+PKCS#8 format private key conversion command.
=item B<pkey>
@@ -199,7 +206,7 @@ Public key algorithm parameter management.
=item B<pkeyutl>
-Public key algorithm cryptographic operation utility.
+Public key algorithm cryptographic operation command.
=item B<prime>
@@ -223,8 +230,8 @@ RSA key management.
=item B<rsautl>
-RSA utility for signing, verification, encryption, and decryption. Superseded
-by L<pkeyutl(1)>.
+RSA command for signing, verification, encryption, and decryption. Superseded
+by L<openssl-pkeyutl(1)>.
=item B<s_client>
@@ -260,23 +267,24 @@ Algorithm Speed Measurement.
=item B<spkac>
-SPKAC printing and generating utility.
+SPKAC printing and generating command.
=item B<srp>
-Maintain SRP password file.
+Maintain SRP password file. This command is deprecated.
=item B<storeutl>
-Utility to list and display certificates, keys, CRLs, etc.
+Command to list and display certificates, keys, CRLs, etc.
=item B<ts>
-Time Stamping Authority tool (client/server).
+Time Stamping Authority command.
=item B<verify>
X.509 Certificate Verification.
+See also the L<openssl-verification-options(1)> manual page.
=item B<version>
@@ -370,13 +378,13 @@ SM3 Digest
=back
-=head2 Encoding and Cipher Commands
+=head2 Encryption, Decryption, and Encoding Commands
The following aliases provide convenient access to the most used encodings
and ciphers.
Depending on how OpenSSL was configured and built, not all ciphers listed
-here may be present. See L<enc(1)> for more information and command usage.
+here may be present. See L<openssl-enc(1)> for more information.
=over 4
@@ -482,85 +490,350 @@ This section describes some common options with common behavior.
=item B<-help>
Provides a terse summary of all options.
+If an option takes an argument, the "type" of argument is also given.
+
+=item B<-->
+
+This terminates the list of options. It is mostly useful if any filename
+parameters start with a minus sign:
+
+ openssl verify [flags...] -- -cert1.pem...
=back
+=head2 Format Options
+
+See L<openssl-format-options(1)> for manual page.
+
=head2 Pass Phrase Options
-Several commands accept password arguments, typically using B<-passin>
-and B<-passout> for input and output passwords respectively. These allow
-the password to be obtained from a variety of sources. Both of these
-options take a single argument whose format is described below. If no
-password argument is given and a password is required then the user is
-prompted to enter one: this will typically be read from the current
-terminal with echoing turned off.
+See the L<openssl-passphrase-options(1)> manual page.
+
+=head2 Random State Options
-Note that character encoding may be relevant, please see
-L<passphrase-encoding(7)>.
+Prior to OpenSSL 1.1.1, it was common for applications to store information
+about the state of the random-number generator in a file that was loaded
+at startup and rewritten upon exit. On modern operating systems, this is
+generally no longer necessary as OpenSSL will seed itself from a trusted
+entropy source provided by the operating system. These flags are still
+supported for special platforms or circumstances that might require them.
+
+It is generally an error to use the same seed file more than once and
+every use of B<-rand> should be paired with B<-writerand>.
+
+=over 4
+
+=item B<-rand> I<files>
+
+A file or files containing random data used to seed the random number
+generator.
+Multiple files can be specified separated by an OS-dependent character.
+The separator is C<;> for MS-Windows, C<,> for OpenVMS, and C<:> for
+all others. Another way to specify multiple files is to repeat this flag
+with different filenames.
+
+=item B<-writerand> I<file>
+
+Writes the seed data to the specified I<file> upon exit.
+This file can be used in a subsequent command invocation.
+
+=back
+
+=head2 Certificate Verification Options
+
+See the L<openssl-verification-options(1)> manual page.
+
+=head2 Name Format Options
+
+See the L<openssl-namedisplay-options(1)> manual page.
+
+=head2 TLS Version Options
+
+Several commands use SSL, TLS, or DTLS. By default, the commands use TLS and
+clients will offer the lowest and highest protocol version they support,
+and servers will pick the highest version that the client offers that is also
+supported by the server.
+
+The options below can be used to limit which protocol versions are used,
+and whether TCP (SSL and TLS) or UDP (DTLS) is used.
+Note that not all protocols and flags may be available, depending on how
+OpenSSL was built.
=over 4
-=item B<pass:password>
+=item B<-ssl3>, B<-tls1>, B<-tls1_1>, B<-tls1_2>, B<-tls1_3>, B<-no_ssl3>, B<-no_tls1>, B<-no_tls1_1>, B<-no_tls1_2>, B<-no_tls1_3>
+
+These options require or disable the use of the specified SSL or TLS protocols.
+When a specific TLS version is required, only that version will be offered or
+accepted.
+Only one specific protocol can be given and it cannot be combined with any of
+the B<no_> options.
-The actual password is B<password>. Since the password is visible
-to utilities (like 'ps' under Unix) this form should only be used
-where security is not important.
+=item B<-dtls>, B<-dtls1>, B<-dtls1_2>
-=item B<env:var>
+These options specify to use DTLS instead of DLTS.
+With B<-dtls>, clients will negotiate any supported DTLS protocol version.
+Use the B<-dtls1> or B<-dtls1_2> options to support only DTLS1.0 or DTLS1.2,
+respectively.
-Obtain the password from the environment variable B<var>. Since
-the environment of other processes is visible on certain platforms
-(e.g. ps under certain Unix OSes) this option should be used with caution.
+=back
-=item B<file:pathname>
+=head2 Engine Options
-The first line of B<pathname> is the password. If the same B<pathname>
-argument is supplied to B<-passin> and B<-passout> arguments then the first
-line will be used for the input password and the next line for the output
-password. B<pathname> need not refer to a regular file: it could for example
-refer to a device or named pipe.
+=over 4
-=item B<fd:number>
+=item B<-engine> I<id>
-Read the password from the file descriptor B<number>. This can be used to
-send the data via a pipe for example.
+Load the engine identified by I<id> and use all the methods it implements
+(algorithms, key storage, etc.), unless specified otherwise in the
+command-specific documentation or it is configured to do so, as described in
+L<config(5)/Engine Configuration>.
-=item B<stdin>
+The engine will be used for key ids specified with B<-key> and similar
+options when an option like B<-keyform engine> is given.
-Read the password from standard input.
+A special case is the C<loader_attic> engine, which
+is meant just for internal OpenSSL testing purposes and
+supports loading keys, parameters, certificates, and CRLs from files.
+When this engine is used, files with such credentials are read via this engine.
+Using the C<file:> schema is optional; a plain file (path) name will do.
+
+=back
+
+Options specifying keys, like B<-key> and similar, can use the generic
+OpenSSL engine key loading URI scheme C<org.openssl.engine:> to retrieve
+private keys and public keys. The URI syntax is as follows, in simplified
+form:
+
+ org.openssl.engine:{engineid}:{keyid}
+
+Where C<{engineid}> is the identity/name of the engine, and C<{keyid}> is a
+key identifier that's acceptable by that engine. For example, when using an
+engine that interfaces against a PKCS#11 implementation, the generic key URI
+would be something like this (this happens to be an example for the PKCS#11
+engine that's part of OpenSC):
+
+ -key org.openssl.engine:pkcs11:label_some-private-key
+
+As a third possibility, for engines and providers that have implemented
+their own L<OSSL_STORE_LOADER(3)>, C<org.openssl.engine:> should not be
+necessary. For a PKCS#11 implementation that has implemented such a loader,
+the PKCS#11 URI as defined in RFC 7512 should be possible to use directly:
+
+ -key pkcs11:object=some-private-key;pin-value=1234
+
+=head2 Provider Options
+
+=over 4
+
+=item B<-provider> I<name>
+
+Load and initialize the provider identified by I<name>. The I<name>
+can be also a path to the provider module. In that case the provider name
+will be the specified path and not just the provider module name.
+Interpretation of relative paths is platform specific. The configured
+"MODULESDIR" path, B<OPENSSL_MODULES> environment variable, or the path
+specified by B<-provider-path> is prepended to relative paths.
+See L<provider(7)> for a more detailed description.
+
+=item B<-provider-path> I<path>
+
+Specifies the search path that is to be used for looking for providers.
+Equivalently, the B<OPENSSL_MODULES> environment variable may be set.
+
+=item B<-propquery> I<propq>
+
+Specifies the I<property query clause> to be used when fetching algorithms
+from the loaded providers.
+See L<property(7)> for a more detailed description.
+
+=back
+
+=head1 ENVIRONMENT
+
+The OpenSSL library can be take some configuration parameters from the
+environment. Some of these variables are listed below. For information
+about specific commands, see L<openssl-engine(1)>,
+L<openssl-rehash(1)>, and L<tsget(1)>.
+
+For information about the use of environment variables in configuration,
+see L<config(5)/ENVIRONMENT>.
+
+For information about querying or specifying CPU architecture flags, see
+L<OPENSSL_ia32cap(3)>, and L<OPENSSL_s390xcap(3)>.
+
+For information about all environment variables used by the OpenSSL libraries,
+see L<openssl-env(7)>.
+
+=over 4
+
+=item B<OPENSSL_TRACE=>I<name>[,...]
+
+Enable tracing output of OpenSSL library, by name.
+This output will only make sense if you know OpenSSL internals well.
+Also, it might not give you any output at all, depending on how
+OpenSSL was built.
+
+The value is a comma separated list of names, with the following
+available:
+
+=over 4
+
+=item B<TRACE>
+
+Traces the OpenSSL trace API itself.
+
+=item B<INIT>
+
+Traces OpenSSL library initialization and cleanup.
+
+=item B<TLS>
+
+Traces the TLS/SSL protocol.
+
+=item B<TLS_CIPHER>
+
+Traces the ciphers used by the TLS/SSL protocol.
+
+=item B<CONF>
+
+Show details about provider and engine configuration.
+
+=item B<ENGINE_TABLE>
+
+The function that is used by RSA, DSA (etc) code to select registered
+ENGINEs, cache defaults and functional references (etc), will generate
+debugging summaries.
+
+=item B<ENGINE_REF_COUNT>
+
+Reference counts in the ENGINE structure will be monitored with a line
+of generated for each change.
+
+=item B<PKCS5V2>
+
+Traces PKCS#5 v2 key generation.
+
+=item B<PKCS12_KEYGEN>
+
+Traces PKCS#12 key generation.
+
+=item B<PKCS12_DECRYPT>
+
+Traces PKCS#12 decryption.
+
+=item B<X509V3_POLICY>
+
+Generates the complete policy tree at various points during X.509 v3
+policy evaluation.
+
+=item B<BN_CTX>
+
+Traces BIGNUM context operations.
+
+=item B<CMP>
+
+Traces CMP client and server activity.
+
+=item B<STORE>
+
+Traces STORE operations.
+
+=item B<DECODER>
+
+Traces decoder operations.
+
+=item B<ENCODER>
+
+Traces encoder operations.
+
+=item B<REF_COUNT>
+
+Traces decrementing certain ASN.1 structure references.
+
+=back
=back
=head1 SEE ALSO
-L<asn1parse(1)>, L<ca(1)>, L<ciphers(1)>, L<cms(1)>, L<config(5)>,
-L<crl(1)>, L<crl2pkcs7(1)>, L<dgst(1)>,
-L<dhparam(1)>, L<dsa(1)>, L<dsaparam(1)>,
-L<ec(1)>, L<ecparam(1)>,
-L<enc(1)>, L<engine(1)>, L<errstr(1)>, L<gendsa(1)>, L<genpkey(1)>,
-L<genrsa(1)>, L<nseq(1)>, L<ocsp(1)>,
-L<passwd(1)>,
-L<pkcs12(1)>, L<pkcs7(1)>, L<pkcs8(1)>,
-L<pkey(1)>, L<pkeyparam(1)>, L<pkeyutl(1)>, L<prime(1)>,
-L<rand(1)>, L<rehash(1)>, L<req(1)>, L<rsa(1)>,
-L<rsautl(1)>, L<s_client(1)>,
-L<s_server(1)>, L<s_time(1)>, L<sess_id(1)>,
-L<smime(1)>, L<speed(1)>, L<spkac(1)>, L<srp(1)>, L<storeutl(1)>,
-L<ts(1)>,
-L<verify(1)>, L<version(1)>, L<x509(1)>,
-L<crypto(7)>, L<ssl(7)>, L<x509v3_config(5)>
+L<openssl-asn1parse(1)>,
+L<openssl-ca(1)>,
+L<openssl-ciphers(1)>,
+L<openssl-cms(1)>,
+L<openssl-crl(1)>,
+L<openssl-crl2pkcs7(1)>,
+L<openssl-dgst(1)>,
+L<openssl-dhparam(1)>,
+L<openssl-dsa(1)>,
+L<openssl-dsaparam(1)>,
+L<openssl-ec(1)>,
+L<openssl-ecparam(1)>,
+L<openssl-enc(1)>,
+L<openssl-engine(1)>,
+L<openssl-errstr(1)>,
+L<openssl-gendsa(1)>,
+L<openssl-genpkey(1)>,
+L<openssl-genrsa(1)>,
+L<openssl-kdf(1)>,
+L<openssl-list(1)>,
+L<openssl-mac(1)>,
+L<openssl-nseq(1)>,
+L<openssl-ocsp(1)>,
+L<openssl-passwd(1)>,
+L<openssl-pkcs12(1)>,
+L<openssl-pkcs7(1)>,
+L<openssl-pkcs8(1)>,
+L<openssl-pkey(1)>,
+L<openssl-pkeyparam(1)>,
+L<openssl-pkeyutl(1)>,
+L<openssl-prime(1)>,
+L<openssl-rand(1)>,
+L<openssl-rehash(1)>,
+L<openssl-req(1)>,
+L<openssl-rsa(1)>,
+L<openssl-rsautl(1)>,
+L<openssl-s_client(1)>,
+L<openssl-s_server(1)>,
+L<openssl-s_time(1)>,
+L<openssl-sess_id(1)>,
+L<openssl-smime(1)>,
+L<openssl-speed(1)>,
+L<openssl-spkac(1)>,
+L<openssl-srp(1)>,
+L<openssl-storeutl(1)>,
+L<openssl-ts(1)>,
+L<openssl-verify(1)>,
+L<openssl-version(1)>,
+L<openssl-x509(1)>,
+L<config(5)>,
+L<crypto(7)>,
+L<openssl-env(7)>.
+L<ssl(7)>,
+L<x509v3_config(5)>
+
=head1 HISTORY
-The B<list->I<XXX>B<-algorithms> pseudo-commands were added in OpenSSL 1.0.0;
+The B<list> -I<XXX>B<-algorithms> options were added in OpenSSL 1.0.0;
For notes on the availability of other commands, see their individual
manual pages.
+The B<-issuer_checks> option is deprecated as of OpenSSL 1.1.0 and
+is silently ignored.
+
+The B<-xcertform> and B<-xkeyform> options
+are obsolete since OpenSSL 3.0 and have no effect.
+
+The interactive mode, which could be invoked by running C<openssl>
+with no further arguments, was removed in OpenSSL 3.0, and running
+that program with no arguments is now equivalent to C<openssl help>.
+
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man1/passwd.pod b/doc/man1/passwd.pod
deleted file mode 100644
index 26eb2ad35eaf..000000000000
--- a/doc/man1/passwd.pod
+++ /dev/null
@@ -1,130 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-passwd,
-passwd - compute password hashes
-
-=head1 SYNOPSIS
-
-B<openssl passwd>
-[B<-help>]
-[B<-crypt>]
-[B<-1>]
-[B<-apr1>]
-[B<-aixmd5>]
-[B<-5>]
-[B<-6>]
-[B<-salt> I<string>]
-[B<-in> I<file>]
-[B<-stdin>]
-[B<-noverify>]
-[B<-quiet>]
-[B<-table>]
-[B<-rand file...>]
-[B<-writerand file>]
-{I<password>}
-
-=head1 DESCRIPTION
-
-The B<passwd> command computes the hash of a password typed at
-run-time or the hash of each password in a list. The password list is
-taken from the named file for option B<-in file>, from stdin for
-option B<-stdin>, or from the command line, or from the terminal otherwise.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-crypt>
-
-Use the B<crypt> algorithm (default).
-
-=item B<-1>
-
-Use the MD5 based BSD password algorithm B<1>.
-
-=item B<-apr1>
-
-Use the B<apr1> algorithm (Apache variant of the BSD algorithm).
-
-=item B<-aixmd5>
-
-Use the B<AIX MD5> algorithm (AIX variant of the BSD algorithm).
-
-=item B<-5>
-
-=item B<-6>
-
-Use the B<SHA256> / B<SHA512> based algorithms defined by Ulrich Drepper.
-See L<https://www.akkadia.org/drepper/SHA-crypt.txt>.
-
-=item B<-salt> I<string>
-
-Use the specified salt.
-When reading a password from the terminal, this implies B<-noverify>.
-
-=item B<-in> I<file>
-
-Read passwords from I<file>.
-
-=item B<-stdin>
-
-Read passwords from B<stdin>.
-
-=item B<-noverify>
-
-Don't verify when reading a password from the terminal.
-
-=item B<-quiet>
-
-Don't output warnings when passwords given at the command line are truncated.
-
-=item B<-table>
-
-In the output list, prepend the cleartext password and a TAB character
-to each password hash.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=back
-
-=head1 EXAMPLES
-
- % openssl passwd -crypt -salt xx password
- xxj31ZMTZzkVA
-
- % openssl passwd -1 -salt xxxxxxxx password
- $1$xxxxxxxx$UYCIxa628.9qXjpQCjM4a.
-
- % openssl passwd -apr1 -salt xxxxxxxx password
- $apr1$xxxxxxxx$dxHfLAsjHkDRmG83UXe8K0
-
- % openssl passwd -aixmd5 -salt xxxxxxxx password
- xxxxxxxx$8Oaipk/GPKhC64w/YVeFD/
-
-=head1 COPYRIGHT
-
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/pkcs12.pod b/doc/man1/pkcs12.pod
deleted file mode 100644
index ac0397a945a9..000000000000
--- a/doc/man1/pkcs12.pod
+++ /dev/null
@@ -1,389 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-pkcs12,
-pkcs12 - PKCS#12 file utility
-
-=head1 SYNOPSIS
-
-B<openssl> B<pkcs12>
-[B<-help>]
-[B<-export>]
-[B<-chain>]
-[B<-inkey file_or_id>]
-[B<-certfile filename>]
-[B<-name name>]
-[B<-caname name>]
-[B<-in filename>]
-[B<-out filename>]
-[B<-noout>]
-[B<-nomacver>]
-[B<-nocerts>]
-[B<-clcerts>]
-[B<-cacerts>]
-[B<-nokeys>]
-[B<-info>]
-[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]
-[B<-noiter>]
-[B<-maciter | -nomaciter | -nomac>]
-[B<-twopass>]
-[B<-descert>]
-[B<-certpbe cipher>]
-[B<-keypbe cipher>]
-[B<-macalg digest>]
-[B<-keyex>]
-[B<-keysig>]
-[B<-password arg>]
-[B<-passin arg>]
-[B<-passout arg>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-CAfile file>]
-[B<-CApath dir>]
-[B<-no-CAfile>]
-[B<-no-CApath>]
-[B<-CSP name>]
-
-=head1 DESCRIPTION
-
-The B<pkcs12> command allows PKCS#12 files (sometimes referred to as
-PFX files) to be created and parsed. PKCS#12 files are used by several
-programs including Netscape, MSIE and MS Outlook.
-
-=head1 OPTIONS
-
-There are a lot of options the meaning of some depends of whether a PKCS#12 file
-is being created or parsed. By default a PKCS#12 file is parsed. A PKCS#12
-file can be created by using the B<-export> option (see below).
-
-=head1 PARSING OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-in filename>
-
-This specifies filename of the PKCS#12 file to be parsed. Standard input is used
-by default.
-
-=item B<-out filename>
-
-The filename to write certificates and private keys to, standard output by
-default. They are all written in PEM format.
-
-=item B<-passin arg>
-
-The PKCS#12 file (i.e. input file) password source. For more information about
-the format of B<arg> see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-passout arg>
-
-Pass phrase source to encrypt any outputted private keys with. For more
-information about the format of B<arg> see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-password arg>
-
-With -export, -password is equivalent to -passout.
-Otherwise, -password is equivalent to -passin.
-
-=item B<-noout>
-
-This option inhibits output of the keys and certificates to the output file
-version of the PKCS#12 file.
-
-=item B<-clcerts>
-
-Only output client certificates (not CA certificates).
-
-=item B<-cacerts>
-
-Only output CA certificates (not client certificates).
-
-=item B<-nocerts>
-
-No certificates at all will be output.
-
-=item B<-nokeys>
-
-No private keys will be output.
-
-=item B<-info>
-
-Output additional information about the PKCS#12 file structure, algorithms
-used and iteration counts.
-
-=item B<-des>
-
-Use DES to encrypt private keys before outputting.
-
-=item B<-des3>
-
-Use triple DES to encrypt private keys before outputting, this is the default.
-
-=item B<-idea>
-
-Use IDEA to encrypt private keys before outputting.
-
-=item B<-aes128>, B<-aes192>, B<-aes256>
-
-Use AES to encrypt private keys before outputting.
-
-=item B<-aria128>, B<-aria192>, B<-aria256>
-
-Use ARIA to encrypt private keys before outputting.
-
-=item B<-camellia128>, B<-camellia192>, B<-camellia256>
-
-Use Camellia to encrypt private keys before outputting.
-
-=item B<-nodes>
-
-Don't encrypt the private keys at all.
-
-=item B<-nomacver>
-
-Don't attempt to verify the integrity MAC before reading the file.
-
-=item B<-twopass>
-
-Prompt for separate integrity and encryption passwords: most software
-always assumes these are the same so this option will render such
-PKCS#12 files unreadable. Cannot be used in combination with the options
--password, -passin (if importing) or -passout (if exporting).
-
-=back
-
-=head1 FILE CREATION OPTIONS
-
-=over 4
-
-=item B<-export>
-
-This option specifies that a PKCS#12 file will be created rather than
-parsed.
-
-=item B<-out filename>
-
-This specifies filename to write the PKCS#12 file to. Standard output is used
-by default.
-
-=item B<-in filename>
-
-The filename to read certificates and private keys from, standard input by
-default. They must all be in PEM format. The order doesn't matter but one
-private key and its corresponding certificate should be present. If additional
-certificates are present they will also be included in the PKCS#12 file.
-
-=item B<-inkey file_or_id>
-
-File to read private key from. If not present then a private key must be present
-in the input file.
-If no engine is used, the argument is taken as a file; if an engine is
-specified, the argument is given to the engine as a key identifier.
-
-=item B<-name friendlyname>
-
-This specifies the "friendly name" for the certificate and private key. This
-name is typically displayed in list boxes by software importing the file.
-
-=item B<-certfile filename>
-
-A filename to read additional certificates from.
-
-=item B<-caname friendlyname>
-
-This specifies the "friendly name" for other certificates. This option may be
-used multiple times to specify names for all certificates in the order they
-appear. Netscape ignores friendly names on other certificates whereas MSIE
-displays them.
-
-=item B<-pass arg>, B<-passout arg>
-
-The PKCS#12 file (i.e. output file) password source. For more information about
-the format of B<arg> see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-passin password>
-
-Pass phrase source to decrypt any input private keys with. For more information
-about the format of B<arg> see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-chain>
-
-If this option is present then an attempt is made to include the entire
-certificate chain of the user certificate. The standard CA store is used
-for this search. If the search fails it is considered a fatal error.
-
-=item B<-descert>
-
-Encrypt the certificate using triple DES, this may render the PKCS#12
-file unreadable by some "export grade" software. By default the private
-key is encrypted using triple DES and the certificate using 40 bit RC2
-unless RC2 is disabled in which case triple DES is used.
-
-=item B<-keypbe alg>, B<-certpbe alg>
-
-These options allow the algorithm used to encrypt the private key and
-certificates to be selected. Any PKCS#5 v1.5 or PKCS#12 PBE algorithm name
-can be used (see B<NOTES> section for more information). If a cipher name
-(as output by the B<list-cipher-algorithms> command is specified then it
-is used with PKCS#5 v2.0. For interoperability reasons it is advisable to only
-use PKCS#12 algorithms.
-
-=item B<-keyex|-keysig>
-
-Specifies that the private key is to be used for key exchange or just signing.
-This option is only interpreted by MSIE and similar MS software. Normally
-"export grade" software will only allow 512 bit RSA keys to be used for
-encryption purposes but arbitrary length keys for signing. The B<-keysig>
-option marks the key for signing only. Signing only keys can be used for
-S/MIME signing, authenticode (ActiveX control signing) and SSL client
-authentication, however, due to a bug only MSIE 5.0 and later support
-the use of signing only keys for SSL client authentication.
-
-=item B<-macalg digest>
-
-Specify the MAC digest algorithm. If not included them SHA1 will be used.
-
-=item B<-nomaciter>, B<-noiter>
-
-These options affect the iteration counts on the MAC and key algorithms.
-Unless you wish to produce files compatible with MSIE 4.0 you should leave
-these options alone.
-
-To discourage attacks by using large dictionaries of common passwords the
-algorithm that derives keys from passwords can have an iteration count applied
-to it: this causes a certain part of the algorithm to be repeated and slows it
-down. The MAC is used to check the file integrity but since it will normally
-have the same password as the keys and certificates it could also be attacked.
-By default both MAC and encryption iteration counts are set to 2048, using
-these options the MAC and encryption iteration counts can be set to 1, since
-this reduces the file security you should not use these options unless you
-really have to. Most software supports both MAC and key iteration counts.
-MSIE 4.0 doesn't support MAC iteration counts so it needs the B<-nomaciter>
-option.
-
-=item B<-maciter>
-
-This option is included for compatibility with previous versions, it used
-to be needed to use MAC iterations counts but they are now used by default.
-
-=item B<-nomac>
-
-Don't attempt to provide the MAC integrity.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<-CAfile file>
-
-CA storage as a file.
-
-=item B<-CApath dir>
-
-CA storage as a directory. This directory must be a standard certificate
-directory: that is a hash of each subject name (using B<x509 -hash>) should be
-linked to each certificate.
-
-=item B<-no-CAfile>
-
-Do not load the trusted CA certificates from the default file location.
-
-=item B<-no-CApath>
-
-Do not load the trusted CA certificates from the default directory location.
-
-=item B<-CSP name>
-
-Write B<name> as a Microsoft CSP name.
-
-=back
-
-=head1 NOTES
-
-Although there are a large number of options most of them are very rarely
-used. For PKCS#12 file parsing only B<-in> and B<-out> need to be used
-for PKCS#12 file creation B<-export> and B<-name> are also used.
-
-If none of the B<-clcerts>, B<-cacerts> or B<-nocerts> options are present
-then all certificates will be output in the order they appear in the input
-PKCS#12 files. There is no guarantee that the first certificate present is
-the one corresponding to the private key. Certain software which requires
-a private key and certificate and assumes the first certificate in the
-file is the one corresponding to the private key: this may not always
-be the case. Using the B<-clcerts> option will solve this problem by only
-outputting the certificate corresponding to the private key. If the CA
-certificates are required then they can be output to a separate file using
-the B<-nokeys -cacerts> options to just output CA certificates.
-
-The B<-keypbe> and B<-certpbe> algorithms allow the precise encryption
-algorithms for private keys and certificates to be specified. Normally
-the defaults are fine but occasionally software can't handle triple DES
-encrypted private keys, then the option B<-keypbe PBE-SHA1-RC2-40> can
-be used to reduce the private key encryption to 40 bit RC2. A complete
-description of all algorithms is contained in the B<pkcs8> manual page.
-
-Prior 1.1 release passwords containing non-ASCII characters were encoded
-in non-compliant manner, which limited interoperability, in first hand
-with Windows. But switching to standard-compliant password encoding
-poses problem accessing old data protected with broken encoding. For
-this reason even legacy encodings is attempted when reading the
-data. If you use PKCS#12 files in production application you are advised
-to convert the data, because implemented heuristic approach is not
-MT-safe, its sole goal is to facilitate the data upgrade with this
-utility.
-
-=head1 EXAMPLES
-
-Parse a PKCS#12 file and output it to a file:
-
- openssl pkcs12 -in file.p12 -out file.pem
-
-Output only client certificates to a file:
-
- openssl pkcs12 -in file.p12 -clcerts -out file.pem
-
-Don't encrypt the private key:
-
- openssl pkcs12 -in file.p12 -out file.pem -nodes
-
-Print some info about a PKCS#12 file:
-
- openssl pkcs12 -in file.p12 -info -noout
-
-Create a PKCS#12 file:
-
- openssl pkcs12 -export -in file.pem -out file.p12 -name "My Certificate"
-
-Include some extra certificates:
-
- openssl pkcs12 -export -in file.pem -out file.p12 -name "My Certificate" \
- -certfile othercerts.pem
-
-=head1 SEE ALSO
-
-L<pkcs8(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/pkcs7.pod b/doc/man1/pkcs7.pod
deleted file mode 100644
index cf445b3dcd37..000000000000
--- a/doc/man1/pkcs7.pod
+++ /dev/null
@@ -1,120 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-pkcs7,
-pkcs7 - PKCS#7 utility
-
-=head1 SYNOPSIS
-
-B<openssl> B<pkcs7>
-[B<-help>]
-[B<-inform PEM|DER>]
-[B<-outform PEM|DER>]
-[B<-in filename>]
-[B<-out filename>]
-[B<-print_certs>]
-[B<-text>]
-[B<-noout>]
-[B<-engine id>]
-
-=head1 DESCRIPTION
-
-The B<pkcs7> command processes PKCS#7 files in DER or PEM format.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-inform DER|PEM>
-
-This specifies the input format. B<DER> format is DER encoded PKCS#7
-v1.5 structure.B<PEM> (the default) is a base64 encoded version of
-the DER form with header and footer lines.
-
-=item B<-outform DER|PEM>
-
-This specifies the output format, the options have the same meaning and default
-as the B<-inform> option.
-
-=item B<-in filename>
-
-This specifies the input filename to read from or standard input if this
-option is not specified.
-
-=item B<-out filename>
-
-Specifies the output filename to write to or standard output by
-default.
-
-=item B<-print_certs>
-
-Prints out any certificates or CRLs contained in the file. They are
-preceded by their subject and issuer names in one line format.
-
-=item B<-text>
-
-Prints out certificates details in full rather than just subject and
-issuer names.
-
-=item B<-noout>
-
-Don't output the encoded version of the PKCS#7 structure (or certificates
-is B<-print_certs> is set).
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<pkcs7>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=back
-
-=head1 EXAMPLES
-
-Convert a PKCS#7 file from PEM to DER:
-
- openssl pkcs7 -in file.pem -outform DER -out file.der
-
-Output all certificates in a file:
-
- openssl pkcs7 -in file.pem -print_certs -out certs.pem
-
-=head1 NOTES
-
-The PEM PKCS#7 format uses the header and footer lines:
-
- -----BEGIN PKCS7-----
- -----END PKCS7-----
-
-For compatibility with some CAs it will also accept:
-
- -----BEGIN CERTIFICATE-----
- -----END CERTIFICATE-----
-
-=head1 RESTRICTIONS
-
-There is no option to print out all the fields of a PKCS#7 file.
-
-This PKCS#7 routines only understand PKCS#7 v 1.5 as specified in RFC2315 they
-cannot currently parse, for example, the new CMS as described in RFC2630.
-
-=head1 SEE ALSO
-
-L<crl2pkcs7(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/pkcs8.pod b/doc/man1/pkcs8.pod
deleted file mode 100644
index dba75fc8d41d..000000000000
--- a/doc/man1/pkcs8.pod
+++ /dev/null
@@ -1,319 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-pkcs8,
-pkcs8 - PKCS#8 format private key conversion tool
-
-=head1 SYNOPSIS
-
-B<openssl> B<pkcs8>
-[B<-help>]
-[B<-topk8>]
-[B<-inform PEM|DER>]
-[B<-outform PEM|DER>]
-[B<-in filename>]
-[B<-passin arg>]
-[B<-out filename>]
-[B<-passout arg>]
-[B<-iter count>]
-[B<-noiter>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-nocrypt>]
-[B<-traditional>]
-[B<-v2 alg>]
-[B<-v2prf alg>]
-[B<-v1 alg>]
-[B<-engine id>]
-[B<-scrypt>]
-[B<-scrypt_N N>]
-[B<-scrypt_r r>]
-[B<-scrypt_p p>]
-
-=head1 DESCRIPTION
-
-The B<pkcs8> command processes private keys in PKCS#8 format. It can handle
-both unencrypted PKCS#8 PrivateKeyInfo format and EncryptedPrivateKeyInfo
-format with a variety of PKCS#5 (v1.5 and v2.0) and PKCS#12 algorithms.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-topk8>
-
-Normally a PKCS#8 private key is expected on input and a private key will be
-written to the output file. With the B<-topk8> option the situation is
-reversed: it reads a private key and writes a PKCS#8 format key.
-
-=item B<-inform DER|PEM>
-
-This specifies the input format: see L<KEY FORMATS> for more details. The default
-format is PEM.
-
-=item B<-outform DER|PEM>
-
-This specifies the output format: see L<KEY FORMATS> for more details. The default
-format is PEM.
-
-=item B<-traditional>
-
-When this option is present and B<-topk8> is not a traditional format private
-key is written.
-
-=item B<-in filename>
-
-This specifies the input filename to read a key from or standard input if this
-option is not specified. If the key is encrypted a pass phrase will be
-prompted for.
-
-=item B<-passin arg>
-
-The input file password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-out filename>
-
-This specifies the output filename to write a key to or standard output by
-default. If any encryption options are set then a pass phrase will be
-prompted for. The output filename should B<not> be the same as the input
-filename.
-
-=item B<-passout arg>
-
-The output file password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-iter count>
-
-When creating new PKCS#8 containers, use a given number of iterations on
-the password in deriving the encryption key for the PKCS#8 output.
-High values increase the time required to brute-force a PKCS#8 container.
-
-=item B<-nocrypt>
-
-PKCS#8 keys generated or input are normally PKCS#8 EncryptedPrivateKeyInfo
-structures using an appropriate password based encryption algorithm. With
-this option an unencrypted PrivateKeyInfo structure is expected or output.
-This option does not encrypt private keys at all and should only be used
-when absolutely necessary. Certain software such as some versions of Java
-code signing software used unencrypted private keys.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<-v2 alg>
-
-This option sets the PKCS#5 v2.0 algorithm.
-
-The B<alg> argument is the encryption algorithm to use, valid values include
-B<aes128>, B<aes256> and B<des3>. If this option isn't specified then B<aes256>
-is used.
-
-=item B<-v2prf alg>
-
-This option sets the PRF algorithm to use with PKCS#5 v2.0. A typical value
-value would be B<hmacWithSHA256>. If this option isn't set then the default
-for the cipher is used or B<hmacWithSHA256> if there is no default.
-
-Some implementations may not support custom PRF algorithms and may require
-the B<hmacWithSHA1> option to work.
-
-=item B<-v1 alg>
-
-This option indicates a PKCS#5 v1.5 or PKCS#12 algorithm should be used. Some
-older implementations may not support PKCS#5 v2.0 and may require this option.
-If not specified PKCS#5 v2.0 form is used.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<pkcs8>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=item B<-scrypt>
-
-Uses the B<scrypt> algorithm for private key encryption using default
-parameters: currently N=16384, r=8 and p=1 and AES in CBC mode with a 256 bit
-key. These parameters can be modified using the B<-scrypt_N>, B<-scrypt_r>,
-B<-scrypt_p> and B<-v2> options.
-
-=item B<-scrypt_N N> B<-scrypt_r r> B<-scrypt_p p>
-
-Sets the scrypt B<N>, B<r> or B<p> parameters.
-
-=back
-
-=head1 KEY FORMATS
-
-Various different formats are used by the pkcs8 utility. These are detailed
-below.
-
-If a key is being converted from PKCS#8 form (i.e. the B<-topk8> option is
-not used) then the input file must be in PKCS#8 format. An encrypted
-key is expected unless B<-nocrypt> is included.
-
-If B<-topk8> is not used and B<PEM> mode is set the output file will be an
-unencrypted private key in PKCS#8 format. If the B<-traditional> option is
-used then a traditional format private key is written instead.
-
-If B<-topk8> is not used and B<DER> mode is set the output file will be an
-unencrypted private key in traditional DER format.
-
-If B<-topk8> is used then any supported private key can be used for the input
-file in a format specified by B<-inform>. The output file will be encrypted
-PKCS#8 format using the specified encryption parameters unless B<-nocrypt>
-is included.
-
-=head1 NOTES
-
-By default, when converting a key to PKCS#8 format, PKCS#5 v2.0 using 256 bit
-AES with HMAC and SHA256 is used.
-
-Some older implementations do not support PKCS#5 v2.0 format and require
-the older PKCS#5 v1.5 form instead, possibly also requiring insecure weak
-encryption algorithms such as 56 bit DES.
-
-The encrypted form of a PEM encode PKCS#8 files uses the following
-headers and footers:
-
- -----BEGIN ENCRYPTED PRIVATE KEY-----
- -----END ENCRYPTED PRIVATE KEY-----
-
-The unencrypted form uses:
-
- -----BEGIN PRIVATE KEY-----
- -----END PRIVATE KEY-----
-
-Private keys encrypted using PKCS#5 v2.0 algorithms and high iteration
-counts are more secure that those encrypted using the traditional
-SSLeay compatible formats. So if additional security is considered
-important the keys should be converted.
-
-It is possible to write out DER encoded encrypted private keys in
-PKCS#8 format because the encryption details are included at an ASN1
-level whereas the traditional format includes them at a PEM level.
-
-=head1 PKCS#5 v1.5 and PKCS#12 algorithms.
-
-Various algorithms can be used with the B<-v1> command line option,
-including PKCS#5 v1.5 and PKCS#12. These are described in more detail
-below.
-
-=over 4
-
-=item B<PBE-MD2-DES PBE-MD5-DES>
-
-These algorithms were included in the original PKCS#5 v1.5 specification.
-They only offer 56 bits of protection since they both use DES.
-
-=item B<PBE-SHA1-RC2-64>, B<PBE-MD2-RC2-64>, B<PBE-MD5-RC2-64>, B<PBE-SHA1-DES>
-
-These algorithms are not mentioned in the original PKCS#5 v1.5 specification
-but they use the same key derivation algorithm and are supported by some
-software. They are mentioned in PKCS#5 v2.0. They use either 64 bit RC2 or
-56 bit DES.
-
-=item B<PBE-SHA1-RC4-128>, B<PBE-SHA1-RC4-40>, B<PBE-SHA1-3DES>, B<PBE-SHA1-2DES>, B<PBE-SHA1-RC2-128>, B<PBE-SHA1-RC2-40>
-
-These algorithms use the PKCS#12 password based encryption algorithm and
-allow strong encryption algorithms like triple DES or 128 bit RC2 to be used.
-
-=back
-
-=head1 EXAMPLES
-
-Convert a private key to PKCS#8 format using default parameters (AES with
-256 bit key and B<hmacWithSHA256>):
-
- openssl pkcs8 -in key.pem -topk8 -out enckey.pem
-
-Convert a private key to PKCS#8 unencrypted format:
-
- openssl pkcs8 -in key.pem -topk8 -nocrypt -out enckey.pem
-
-Convert a private key to PKCS#5 v2.0 format using triple DES:
-
- openssl pkcs8 -in key.pem -topk8 -v2 des3 -out enckey.pem
-
-Convert a private key to PKCS#5 v2.0 format using AES with 256 bits in CBC
-mode and B<hmacWithSHA512> PRF:
-
- openssl pkcs8 -in key.pem -topk8 -v2 aes-256-cbc -v2prf hmacWithSHA512 -out enckey.pem
-
-Convert a private key to PKCS#8 using a PKCS#5 1.5 compatible algorithm
-(DES):
-
- openssl pkcs8 -in key.pem -topk8 -v1 PBE-MD5-DES -out enckey.pem
-
-Convert a private key to PKCS#8 using a PKCS#12 compatible algorithm
-(3DES):
-
- openssl pkcs8 -in key.pem -topk8 -out enckey.pem -v1 PBE-SHA1-3DES
-
-Read a DER unencrypted PKCS#8 format private key:
-
- openssl pkcs8 -inform DER -nocrypt -in key.der -out key.pem
-
-Convert a private key from any PKCS#8 encrypted format to traditional format:
-
- openssl pkcs8 -in pk8.pem -traditional -out key.pem
-
-Convert a private key to PKCS#8 format, encrypting with AES-256 and with
-one million iterations of the password:
-
- openssl pkcs8 -in key.pem -topk8 -v2 aes-256-cbc -iter 1000000 -out pk8.pem
-
-=head1 STANDARDS
-
-Test vectors from this PKCS#5 v2.0 implementation were posted to the
-pkcs-tng mailing list using triple DES, DES and RC2 with high iteration
-counts, several people confirmed that they could decrypt the private
-keys produced and therefore, it can be assumed that the PKCS#5 v2.0
-implementation is reasonably accurate at least as far as these
-algorithms are concerned.
-
-The format of PKCS#8 DSA (and other) private keys is not well documented:
-it is hidden away in PKCS#11 v2.01, section 11.9. OpenSSL's default DSA
-PKCS#8 private key format complies with this standard.
-
-=head1 BUGS
-
-There should be an option that prints out the encryption algorithm
-in use and other details such as the iteration count.
-
-=head1 SEE ALSO
-
-L<dsa(1)>, L<rsa(1)>, L<genrsa(1)>,
-L<gendsa(1)>
-
-=head1 HISTORY
-
-The B<-iter> option was added in OpenSSL 1.1.0.
-
-=head1 COPYRIGHT
-
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/pkey.pod b/doc/man1/pkey.pod
deleted file mode 100644
index 1c29092793fd..000000000000
--- a/doc/man1/pkey.pod
+++ /dev/null
@@ -1,168 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-pkey,
-pkey - public or private key processing tool
-
-=head1 SYNOPSIS
-
-B<openssl> B<pkey>
-[B<-help>]
-[B<-inform PEM|DER>]
-[B<-outform PEM|DER>]
-[B<-in filename>]
-[B<-passin arg>]
-[B<-out filename>]
-[B<-passout arg>]
-[B<-traditional>]
-[B<-I<cipher>>]
-[B<-text>]
-[B<-text_pub>]
-[B<-noout>]
-[B<-pubin>]
-[B<-pubout>]
-[B<-engine id>]
-[B<-check>]
-[B<-pubcheck>]
-
-=head1 DESCRIPTION
-
-The B<pkey> command processes public or private keys. They can be converted
-between various forms and their components printed out.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-inform DER|PEM>
-
-This specifies the input format DER or PEM. The default format is PEM.
-
-=item B<-outform DER|PEM>
-
-This specifies the output format, the options have the same meaning and default
-as the B<-inform> option.
-
-=item B<-in filename>
-
-This specifies the input filename to read a key from or standard input if this
-option is not specified. If the key is encrypted a pass phrase will be
-prompted for.
-
-=item B<-passin arg>
-
-The input file password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-out filename>
-
-This specifies the output filename to write a key to or standard output if this
-option is not specified. If any encryption options are set then a pass phrase
-will be prompted for. The output filename should B<not> be the same as the input
-filename.
-
-=item B<-passout password>
-
-The output file password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-traditional>
-
-Normally a private key is written using standard format: this is PKCS#8 form
-with the appropriate encryption algorithm (if any). If the B<-traditional>
-option is specified then the older "traditional" format is used instead.
-
-=item B<-I<cipher>>
-
-These options encrypt the private key with the supplied cipher. Any algorithm
-name accepted by EVP_get_cipherbyname() is acceptable such as B<des3>.
-
-=item B<-text>
-
-Prints out the various public or private key components in
-plain text in addition to the encoded version.
-
-=item B<-text_pub>
-
-Print out only public key components even if a private key is being processed.
-
-=item B<-noout>
-
-Do not output the encoded version of the key.
-
-=item B<-pubin>
-
-By default a private key is read from the input file: with this
-option a public key is read instead.
-
-=item B<-pubout>
-
-By default a private key is output: with this option a public
-key will be output instead. This option is automatically set if
-the input is a public key.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<pkey>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=item B<-check>
-
-This option checks the consistency of a key pair for both public and private
-components.
-
-=item B<-pubcheck>
-
-This option checks the correctness of either a public key or the public component
-of a key pair.
-
-=back
-
-=head1 EXAMPLES
-
-To remove the pass phrase on an RSA private key:
-
- openssl pkey -in key.pem -out keyout.pem
-
-To encrypt a private key using triple DES:
-
- openssl pkey -in key.pem -des3 -out keyout.pem
-
-To convert a private key from PEM to DER format:
-
- openssl pkey -in key.pem -outform DER -out keyout.der
-
-To print out the components of a private key to standard output:
-
- openssl pkey -in key.pem -text -noout
-
-To print out the public components of a private key to standard output:
-
- openssl pkey -in key.pem -text_pub -noout
-
-To just output the public part of a private key:
-
- openssl pkey -in key.pem -pubout -out pubkey.pem
-
-=head1 SEE ALSO
-
-L<genpkey(1)>, L<rsa(1)>, L<pkcs8(1)>,
-L<dsa(1)>, L<genrsa(1)>, L<gendsa(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/pkeyparam.pod b/doc/man1/pkeyparam.pod
deleted file mode 100644
index bddabc2707e8..000000000000
--- a/doc/man1/pkeyparam.pod
+++ /dev/null
@@ -1,88 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-pkeyparam,
-pkeyparam - public key algorithm parameter processing tool
-
-=head1 SYNOPSIS
-
-B<openssl> B<pkeyparam>
-[B<-help>]
-[B<-in filename>]
-[B<-out filename>]
-[B<-text>]
-[B<-noout>]
-[B<-engine id>]
-[B<-check>]
-
-=head1 DESCRIPTION
-
-The B<pkeyparam> command processes public key algorithm parameters.
-They can be checked for correctness and their components printed out.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-in filename>
-
-This specifies the input filename to read parameters from or standard input if
-this option is not specified.
-
-=item B<-out filename>
-
-This specifies the output filename to write parameters to or standard output if
-this option is not specified.
-
-=item B<-text>
-
-Prints out the parameters in plain text in addition to the encoded version.
-
-=item B<-noout>
-
-Do not output the encoded version of the parameters.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<pkeyparam>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=item B<-check>
-
-This option checks the correctness of parameters.
-
-=back
-
-=head1 EXAMPLES
-
-Print out text version of parameters:
-
- openssl pkeyparam -in param.pem -text
-
-=head1 NOTES
-
-There are no B<-inform> or B<-outform> options for this command because only
-PEM format is supported because the key type is determined by the PEM headers.
-
-=head1 SEE ALSO
-
-L<genpkey(1)>, L<rsa(1)>, L<pkcs8(1)>,
-L<dsa(1)>, L<genrsa(1)>, L<gendsa(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/pkeyutl.pod b/doc/man1/pkeyutl.pod
deleted file mode 100644
index f6fd48d5b579..000000000000
--- a/doc/man1/pkeyutl.pod
+++ /dev/null
@@ -1,347 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-pkeyutl,
-pkeyutl - public key algorithm utility
-
-=head1 SYNOPSIS
-
-B<openssl> B<pkeyutl>
-[B<-help>]
-[B<-in file>]
-[B<-out file>]
-[B<-sigfile file>]
-[B<-inkey file>]
-[B<-keyform PEM|DER|ENGINE>]
-[B<-passin arg>]
-[B<-peerkey file>]
-[B<-peerform PEM|DER|ENGINE>]
-[B<-pubin>]
-[B<-certin>]
-[B<-rev>]
-[B<-sign>]
-[B<-verify>]
-[B<-verifyrecover>]
-[B<-encrypt>]
-[B<-decrypt>]
-[B<-derive>]
-[B<-kdf algorithm>]
-[B<-kdflen length>]
-[B<-pkeyopt opt:value>]
-[B<-hexdump>]
-[B<-asn1parse>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-engine id>]
-[B<-engine_impl>]
-
-=head1 DESCRIPTION
-
-The B<pkeyutl> command can be used to perform low-level public key operations
-using any supported algorithm.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-in filename>
-
-This specifies the input filename to read data from or standard input
-if this option is not specified.
-
-=item B<-out filename>
-
-Specifies the output filename to write to or standard output by
-default.
-
-=item B<-sigfile file>
-
-Signature file, required for B<verify> operations only
-
-=item B<-inkey file>
-
-The input key file, by default it should be a private key.
-
-=item B<-keyform PEM|DER|ENGINE>
-
-The key format PEM, DER or ENGINE. Default is PEM.
-
-=item B<-passin arg>
-
-The input key password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-peerkey file>
-
-The peer key file, used by key derivation (agreement) operations.
-
-=item B<-peerform PEM|DER|ENGINE>
-
-The peer key format PEM, DER or ENGINE. Default is PEM.
-
-=item B<-pubin>
-
-The input file is a public key.
-
-=item B<-certin>
-
-The input is a certificate containing a public key.
-
-=item B<-rev>
-
-Reverse the order of the input buffer. This is useful for some libraries
-(such as CryptoAPI) which represent the buffer in little endian format.
-
-=item B<-sign>
-
-Sign the input data (which must be a hash) and output the signed result. This
-requires a private key.
-
-=item B<-verify>
-
-Verify the input data (which must be a hash) against the signature file and
-indicate if the verification succeeded or failed.
-
-=item B<-verifyrecover>
-
-Verify the input data (which must be a hash) and output the recovered data.
-
-=item B<-encrypt>
-
-Encrypt the input data using a public key.
-
-=item B<-decrypt>
-
-Decrypt the input data using a private key.
-
-=item B<-derive>
-
-Derive a shared secret using the peer key.
-
-=item B<-kdf algorithm>
-
-Use key derivation function B<algorithm>. The supported algorithms are
-at present B<TLS1-PRF> and B<HKDF>.
-Note: additional parameters and the KDF output length will normally have to be
-set for this to work.
-See L<EVP_PKEY_CTX_set_hkdf_md(3)> and L<EVP_PKEY_CTX_set_tls1_prf_md(3)>
-for the supported string parameters of each algorithm.
-
-=item B<-kdflen length>
-
-Set the output length for KDF.
-
-=item B<-pkeyopt opt:value>
-
-Public key options specified as opt:value. See NOTES below for more details.
-
-=item B<-hexdump>
-
-hex dump the output data.
-
-=item B<-asn1parse>
-
-Parse the ASN.1 output data, this is useful when combined with the
-B<-verifyrecover> option when an ASN1 structure is signed.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<pkeyutl>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=item B<-engine_impl>
-
-When used with the B<-engine> option, it specifies to also use
-engine B<id> for crypto operations.
-
-=back
-
-=head1 NOTES
-
-The operations and options supported vary according to the key algorithm
-and its implementation. The OpenSSL operations and options are indicated below.
-
-Unless otherwise mentioned all algorithms support the B<digest:alg> option
-which specifies the digest in use for sign, verify and verifyrecover operations.
-The value B<alg> should represent a digest name as used in the
-EVP_get_digestbyname() function for example B<sha1>. This value is not used to
-hash the input data. It is used (by some algorithms) for sanity-checking the
-lengths of data passed in to the B<pkeyutl> and for creating the structures that
-make up the signature (e.g. B<DigestInfo> in RSASSA PKCS#1 v1.5 signatures).
-
-This utility does not hash the input data but rather it will use the data
-directly as input to the signature algorithm. Depending on the key type,
-signature type, and mode of padding, the maximum acceptable lengths of input
-data differ. The signed data can't be longer than the key modulus with RSA. In
-case of ECDSA and DSA the data shouldn't be longer than the field
-size, otherwise it will be silently truncated to the field size. In any event
-the input size must not be larger than the largest supported digest size.
-
-In other words, if the value of digest is B<sha1> the input should be the 20
-bytes long binary encoding of the SHA-1 hash function output.
-
-The Ed25519 and Ed448 signature algorithms are not supported by this utility.
-They accept non-hashed input, but this utility can only be used to sign hashed
-input.
-
-=head1 RSA ALGORITHM
-
-The RSA algorithm generally supports the encrypt, decrypt, sign,
-verify and verifyrecover operations. However, some padding modes
-support only a subset of these operations. The following additional
-B<pkeyopt> values are supported:
-
-=over 4
-
-=item B<rsa_padding_mode:mode>
-
-This sets the RSA padding mode. Acceptable values for B<mode> are B<pkcs1> for
-PKCS#1 padding, B<sslv23> for SSLv23 padding, B<none> for no padding, B<oaep>
-for B<OAEP> mode, B<x931> for X9.31 mode and B<pss> for PSS.
-
-In PKCS#1 padding if the message digest is not set then the supplied data is
-signed or verified directly instead of using a B<DigestInfo> structure. If a
-digest is set then the a B<DigestInfo> structure is used and its the length
-must correspond to the digest type.
-
-For B<oaep> mode only encryption and decryption is supported.
-
-For B<x931> if the digest type is set it is used to format the block data
-otherwise the first byte is used to specify the X9.31 digest ID. Sign,
-verify and verifyrecover are can be performed in this mode.
-
-For B<pss> mode only sign and verify are supported and the digest type must be
-specified.
-
-=item B<rsa_pss_saltlen:len>
-
-For B<pss> mode only this option specifies the salt length. Three special
-values are supported: "digest" sets the salt length to the digest length,
-"max" sets the salt length to the maximum permissible value. When verifying
-"auto" causes the salt length to be automatically determined based on the
-B<PSS> block structure.
-
-=item B<rsa_mgf1_md:digest>
-
-For PSS and OAEP padding sets the MGF1 digest. If the MGF1 digest is not
-explicitly set in PSS mode then the signing digest is used.
-
-=item B<rsa_oaep_md:>I<digest>
-
-Sets the digest used for the OAEP hash function. If not explicitly set then
-SHA1 is used.
-
-=back
-
-=head1 RSA-PSS ALGORITHM
-
-The RSA-PSS algorithm is a restricted version of the RSA algorithm which only
-supports the sign and verify operations with PSS padding. The following
-additional B<pkeyopt> values are supported:
-
-=over 4
-
-=item B<rsa_padding_mode:mode>, B<rsa_pss_saltlen:len>, B<rsa_mgf1_md:digest>
-
-These have the same meaning as the B<RSA> algorithm with some additional
-restrictions. The padding mode can only be set to B<pss> which is the
-default value.
-
-If the key has parameter restrictions than the digest, MGF1
-digest and salt length are set to the values specified in the parameters.
-The digest and MG cannot be changed and the salt length cannot be set to a
-value less than the minimum restriction.
-
-=back
-
-=head1 DSA ALGORITHM
-
-The DSA algorithm supports signing and verification operations only. Currently
-there are no additional B<-pkeyopt> options other than B<digest>. The SHA1
-digest is assumed by default.
-
-=head1 DH ALGORITHM
-
-The DH algorithm only supports the derivation operation and no additional
-B<-pkeyopt> options.
-
-=head1 EC ALGORITHM
-
-The EC algorithm supports sign, verify and derive operations. The sign and
-verify operations use ECDSA and derive uses ECDH. SHA1 is assumed by default for
-the B<-pkeyopt> B<digest> option.
-
-=head1 X25519 and X448 ALGORITHMS
-
-The X25519 and X448 algorithms support key derivation only. Currently there are
-no additional options.
-
-=head1 EXAMPLES
-
-Sign some data using a private key:
-
- openssl pkeyutl -sign -in file -inkey key.pem -out sig
-
-Recover the signed data (e.g. if an RSA key is used):
-
- openssl pkeyutl -verifyrecover -in sig -inkey key.pem
-
-Verify the signature (e.g. a DSA key):
-
- openssl pkeyutl -verify -in file -sigfile sig -inkey key.pem
-
-Sign data using a message digest value (this is currently only valid for RSA):
-
- openssl pkeyutl -sign -in file -inkey key.pem -out sig -pkeyopt digest:sha256
-
-Derive a shared secret value:
-
- openssl pkeyutl -derive -inkey key.pem -peerkey pubkey.pem -out secret
-
-Hexdump 48 bytes of TLS1 PRF using digest B<SHA256> and shared secret and
-seed consisting of the single byte 0xFF:
-
- openssl pkeyutl -kdf TLS1-PRF -kdflen 48 -pkeyopt md:SHA256 \
- -pkeyopt hexsecret:ff -pkeyopt hexseed:ff -hexdump
-
-Decrypt some data using a private key with OAEP padding using SHA256:
-
- openssl pkeyutl -decrypt -in file -inkey key.pem -out secret \
- -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256
-
-=head1 SEE ALSO
-
-L<genpkey(1)>, L<pkey(1)>, L<rsautl(1)>
-L<dgst(1)>, L<rsa(1)>, L<genrsa(1)>,
-L<EVP_PKEY_CTX_set_hkdf_md(3)>, L<EVP_PKEY_CTX_set_tls1_prf_md(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/prime.pod b/doc/man1/prime.pod
deleted file mode 100644
index 1d25954af19f..000000000000
--- a/doc/man1/prime.pod
+++ /dev/null
@@ -1,68 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-prime,
-prime - compute prime numbers
-
-=head1 SYNOPSIS
-
-B<openssl prime>
-[B<-help>]
-[B<-hex>]
-[B<-generate>]
-[B<-bits>]
-[B<-safe>]
-[B<-checks>]
-[I<number...>]
-
-=head1 DESCRIPTION
-
-The B<prime> command checks if the specified numbers are prime.
-
-If no numbers are given on the command line, the B<-generate> flag should
-be used to generate primes according to the requirements specified by the
-rest of the flags.
-
-=head1 OPTIONS
-
-=over 4
-
-=item [B<-help>]
-
-Display an option summary.
-
-=item [B<-hex>]
-
-Generate hex output.
-
-=item [B<-generate>]
-
-Generate a prime number.
-
-=item [B<-bits num>]
-
-Generate a prime with B<num> bits.
-
-=item [B<-safe>]
-
-When used with B<-generate>, generates a "safe" prime. If the number
-generated is B<n>, then check that B<(n-1)/2> is also prime.
-
-=item [B<-checks num>]
-
-Perform the checks B<num> times to see that the generated number
-is prime. The default is 20.
-
-=back
-
-=head1 COPYRIGHT
-
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/rand.pod b/doc/man1/rand.pod
deleted file mode 100644
index b5d45ab51cf0..000000000000
--- a/doc/man1/rand.pod
+++ /dev/null
@@ -1,95 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-rand,
-rand - generate pseudo-random bytes
-
-=head1 SYNOPSIS
-
-B<openssl rand>
-[B<-help>]
-[B<-out> I<file>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-base64>]
-[B<-hex>]
-I<num>
-
-=head1 DESCRIPTION
-
-This command generates I<num> random bytes using a cryptographically
-secure pseudo random number generator (CSPRNG).
-
-The random bytes are generated using the L<RAND_bytes(3)> function,
-which provides a security level of 256 bits, provided it managed to
-seed itself successfully from a trusted operating system entropy source.
-Otherwise, the command will fail with a nonzero error code.
-For more details, see L<RAND_bytes(3)>, L<RAND(7)>, and L<RAND_DRBG(7)>.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-out file>
-
-Write to I<file> instead of standard output.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-Explicitly specifying a seed file is in general not necessary, see the
-L</NOTES> section for more information.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<-base64>
-
-Perform base64 encoding on the output.
-
-=item B<-hex>
-
-Show the output as a hex string.
-
-=back
-
-=head1 NOTES
-
-Prior to OpenSSL 1.1.1, it was common for applications to store information
-about the state of the random-number generator in a file that was loaded
-at startup and rewritten upon exit. On modern operating systems, this is
-generally no longer necessary as OpenSSL will seed itself from a trusted
-entropy source provided by the operating system. The B<-rand> and
-B<-writerand> flags are still supported for special platforms or
-circumstances that might require them.
-
-It is generally an error to use the same seed file more than once and
-every use of B<-rand> should be paired with B<-writerand>.
-
-=head1 SEE ALSO
-
-L<RAND_bytes(3)>,
-L<RAND(7)>,
-L<RAND_DRBG(7)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/rehash.pod b/doc/man1/rehash.pod
deleted file mode 100644
index 22f3b7a40a6d..000000000000
--- a/doc/man1/rehash.pod
+++ /dev/null
@@ -1,146 +0,0 @@
-=pod
-
-=for comment
-Original text by James Westby, contributed under the OpenSSL license.
-
-=head1 NAME
-
-openssl-c_rehash, openssl-rehash,
-c_rehash, rehash - Create symbolic links to files named by the hash values
-
-=head1 SYNOPSIS
-
-B<openssl>
-B<rehash>
-B<[-h]>
-B<[-help]>
-B<[-old]>
-B<[-n]>
-B<[-v]>
-[ I<directory>...]
-
-B<c_rehash>
-I<flags...>
-
-=head1 DESCRIPTION
-
-On some platforms, the OpenSSL B<rehash> command is available as
-an external script called B<c_rehash>. They are functionally equivalent,
-except for minor differences noted below.
-
-B<rehash> scans directories and calculates a hash value of each
-C<.pem>, C<.crt>, C<.cer>, or C<.crl>
-file in the specified directory list and creates symbolic links
-for each file, where the name of the link is the hash value.
-(If the platform does not support symbolic links, a copy is made.)
-This utility is useful as many programs that use OpenSSL require
-directories to be set up like this in order to find certificates.
-
-If any directories are named on the command line, then those are
-processed in turn. If not, then the B<SSL_CERT_DIR> environment variable
-is consulted; this should be a colon-separated list of directories,
-like the Unix B<PATH> variable.
-If that is not set then the default directory (installation-specific
-but often B</usr/local/ssl/certs>) is processed.
-
-In order for a directory to be processed, the user must have write
-permissions on that directory, otherwise an error will be generated.
-
-The links created are of the form C<HHHHHHHH.D>, where each B<H>
-is a hexadecimal character and B<D> is a single decimal digit.
-When processing a directory, B<rehash> will first remove all links
-that have a name in that syntax, even if they are being used for some
-other purpose.
-To skip the removal step, use the B<-n> flag.
-Hashes for CRL's look similar except the letter B<r> appears after
-the period, like this: C<HHHHHHHH.rD>.
-
-Multiple objects may have the same hash; they will be indicated by
-incrementing the B<D> value. Duplicates are found by comparing the
-full SHA-1 fingerprint. A warning will be displayed if a duplicate
-is found.
-
-A warning will also be displayed if there are files that
-cannot be parsed as either a certificate or a CRL or if
-more than one such object appears in the file.
-
-=head2 Script Configuration
-
-The B<c_rehash> script
-uses the B<openssl> program to compute the hashes and
-fingerprints. If not found in the user's B<PATH>, then set the
-B<OPENSSL> environment variable to the full pathname.
-Any program can be used, it will be invoked as follows for either
-a certificate or CRL:
-
- $OPENSSL x509 -hash -fingerprint -noout -in FILENAME
- $OPENSSL crl -hash -fingerprint -noout -in FILENAME
-
-where B<FILENAME> is the filename. It must output the hash of the
-file on the first line, and the fingerprint on the second,
-optionally prefixed with some text and an equals sign.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help> B<-h>
-
-Display a brief usage message.
-
-=item B<-old>
-
-Use old-style hashing (MD5, as opposed to SHA-1) for generating
-links to be used for releases before 1.0.0.
-Note that current versions will not use the old style.
-
-=item B<-n>
-
-Do not remove existing links.
-This is needed when keeping new and old-style links in the same directory.
-
-=item B<-compat>
-
-Generate links for both old-style (MD5) and new-style (SHA1) hashing.
-This allows releases before 1.0.0 to use these links along-side newer
-releases.
-
-=item B<-v>
-
-Print messages about old links removed and new links created.
-By default, B<rehash> only lists each directory as it is processed.
-
-=back
-
-=head1 ENVIRONMENT
-
-=over 4
-
-=item B<OPENSSL>
-
-The path to an executable to use to generate hashes and
-fingerprints (see above).
-
-=item B<SSL_CERT_DIR>
-
-Colon separated list of directories to operate on.
-Ignored if directories are listed on the command line.
-
-=back
-
-=head1 SEE ALSO
-
-L<openssl(1)>,
-L<crl(1)>.
-L<x509(1)>.
-
-=head1 COPYRIGHT
-
-Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/req.pod b/doc/man1/req.pod
deleted file mode 100644
index 539b843803ed..000000000000
--- a/doc/man1/req.pod
+++ /dev/null
@@ -1,705 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-req,
-req - PKCS#10 certificate request and certificate generating utility
-
-=head1 SYNOPSIS
-
-B<openssl> B<req>
-[B<-help>]
-[B<-inform PEM|DER>]
-[B<-outform PEM|DER>]
-[B<-in filename>]
-[B<-passin arg>]
-[B<-out filename>]
-[B<-passout arg>]
-[B<-text>]
-[B<-pubkey>]
-[B<-noout>]
-[B<-verify>]
-[B<-modulus>]
-[B<-new>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-newkey rsa:bits>]
-[B<-newkey alg:file>]
-[B<-nodes>]
-[B<-key filename>]
-[B<-keyform PEM|DER>]
-[B<-keyout filename>]
-[B<-keygen_engine id>]
-[B<-I<digest>>]
-[B<-config filename>]
-[B<-multivalue-rdn>]
-[B<-x509>]
-[B<-days n>]
-[B<-set_serial n>]
-[B<-newhdr>]
-[B<-addext ext>]
-[B<-extensions section>]
-[B<-reqexts section>]
-[B<-precert>]
-[B<-utf8>]
-[B<-nameopt>]
-[B<-reqopt>]
-[B<-subject>]
-[B<-subj arg>]
-[B<-sigopt nm:v>]
-[B<-batch>]
-[B<-verbose>]
-[B<-engine id>]
-
-=head1 DESCRIPTION
-
-The B<req> command primarily creates and processes certificate requests
-in PKCS#10 format. It can additionally create self signed certificates
-for use as root CAs for example.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-inform DER|PEM>
-
-This specifies the input format. The B<DER> option uses an ASN1 DER encoded
-form compatible with the PKCS#10. The B<PEM> form is the default format: it
-consists of the B<DER> format base64 encoded with additional header and
-footer lines.
-
-=item B<-outform DER|PEM>
-
-This specifies the output format, the options have the same meaning and default
-as the B<-inform> option.
-
-=item B<-in filename>
-
-This specifies the input filename to read a request from or standard input
-if this option is not specified. A request is only read if the creation
-options (B<-new> and B<-newkey>) are not specified.
-
-=item B<-sigopt nm:v>
-
-Pass options to the signature algorithm during sign or verify operations.
-Names and values of these options are algorithm-specific.
-
-=item B<-passin arg>
-
-The input file password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-out filename>
-
-This specifies the output filename to write to or standard output by
-default.
-
-=item B<-passout arg>
-
-The output file password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-text>
-
-Prints out the certificate request in text form.
-
-=item B<-subject>
-
-Prints out the request subject (or certificate subject if B<-x509> is
-specified)
-
-=item B<-pubkey>
-
-Outputs the public key.
-
-=item B<-noout>
-
-This option prevents output of the encoded version of the request.
-
-=item B<-modulus>
-
-This option prints out the value of the modulus of the public key
-contained in the request.
-
-=item B<-verify>
-
-Verifies the signature on the request.
-
-=item B<-new>
-
-This option generates a new certificate request. It will prompt
-the user for the relevant field values. The actual fields
-prompted for and their maximum and minimum sizes are specified
-in the configuration file and any requested extensions.
-
-If the B<-key> option is not used it will generate a new RSA private
-key using information specified in the configuration file.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<-newkey arg>
-
-This option creates a new certificate request and a new private
-key. The argument takes one of several forms. B<rsa:nbits>, where
-B<nbits> is the number of bits, generates an RSA key B<nbits>
-in size. If B<nbits> is omitted, i.e. B<-newkey rsa> specified,
-the default key size, specified in the configuration file is used.
-
-All other algorithms support the B<-newkey alg:file> form, where file may be
-an algorithm parameter file, created by the B<genpkey -genparam> command
-or and X.509 certificate for a key with appropriate algorithm.
-
-B<param:file> generates a key using the parameter file or certificate B<file>,
-the algorithm is determined by the parameters. B<algname:file> use algorithm
-B<algname> and parameter file B<file>: the two algorithms must match or an
-error occurs. B<algname> just uses algorithm B<algname>, and parameters,
-if necessary should be specified via B<-pkeyopt> parameter.
-
-B<dsa:filename> generates a DSA key using the parameters
-in the file B<filename>. B<ec:filename> generates EC key (usable both with
-ECDSA or ECDH algorithms), B<gost2001:filename> generates GOST R
-34.10-2001 key (requires B<ccgost> engine configured in the configuration
-file). If just B<gost2001> is specified a parameter set should be
-specified by B<-pkeyopt paramset:X>
-
-
-=item B<-pkeyopt opt:value>
-
-Set the public key algorithm option B<opt> to B<value>. The precise set of
-options supported depends on the public key algorithm used and its
-implementation. See B<KEY GENERATION OPTIONS> in the B<genpkey> manual page
-for more details.
-
-=item B<-key filename>
-
-This specifies the file to read the private key from. It also
-accepts PKCS#8 format private keys for PEM format files.
-
-=item B<-keyform PEM|DER>
-
-The format of the private key file specified in the B<-key>
-argument. PEM is the default.
-
-=item B<-keyout filename>
-
-This gives the filename to write the newly created private key to.
-If this option is not specified then the filename present in the
-configuration file is used.
-
-=item B<-nodes>
-
-If this option is specified then if a private key is created it
-will not be encrypted.
-
-=item B<-I<digest>>
-
-This specifies the message digest to sign the request.
-Any digest supported by the OpenSSL B<dgst> command can be used.
-This overrides the digest algorithm specified in
-the configuration file.
-
-Some public key algorithms may override this choice. For instance, DSA
-signatures always use SHA1, GOST R 34.10 signatures always use
-GOST R 34.11-94 (B<-md_gost94>), Ed25519 and Ed448 never use any digest.
-
-=item B<-config filename>
-
-This allows an alternative configuration file to be specified.
-Optional; for a description of the default value,
-see L<openssl(1)/COMMAND SUMMARY>.
-
-=item B<-subj arg>
-
-Sets subject name for new request or supersedes the subject name
-when processing a request.
-The arg must be formatted as I</type0=value0/type1=value1/type2=...>.
-Keyword characters may be escaped by \ (backslash), and whitespace is retained.
-Empty values are permitted, but the corresponding type will not be included
-in the request.
-
-=item B<-multivalue-rdn>
-
-This option causes the -subj argument to be interpreted with full
-support for multivalued RDNs. Example:
-
-I</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
-
-If -multi-rdn is not used then the UID value is I<123456+CN=John Doe>.
-
-=item B<-x509>
-
-This option outputs a self signed certificate instead of a certificate
-request. This is typically used to generate a test certificate or
-a self signed root CA. The extensions added to the certificate
-(if any) are specified in the configuration file. Unless specified
-using the B<set_serial> option, a large random number will be used for
-the serial number.
-
-If existing request is specified with the B<-in> option, it is converted
-to the self signed certificate otherwise new request is created.
-
-=item B<-days n>
-
-When the B<-x509> option is being used this specifies the number of
-days to certify the certificate for, otherwise it is ignored. B<n> should
-be a positive integer. The default is 30 days.
-
-=item B<-set_serial n>
-
-Serial number to use when outputting a self signed certificate. This
-may be specified as a decimal value or a hex value if preceded by B<0x>.
-
-=item B<-addext ext>
-
-Add a specific extension to the certificate (if the B<-x509> option is
-present) or certificate request. The argument must have the form of
-a key=value pair as it would appear in a config file.
-
-This option can be given multiple times.
-
-=item B<-extensions section>
-
-=item B<-reqexts section>
-
-These options specify alternative sections to include certificate
-extensions (if the B<-x509> option is present) or certificate
-request extensions. This allows several different sections to
-be used in the same configuration file to specify requests for
-a variety of purposes.
-
-=item B<-precert>
-
-A poison extension will be added to the certificate, making it a
-"pre-certificate" (see RFC6962). This can be submitted to Certificate
-Transparency logs in order to obtain signed certificate timestamps (SCTs).
-These SCTs can then be embedded into the pre-certificate as an extension, before
-removing the poison and signing the certificate.
-
-This implies the B<-new> flag.
-
-=item B<-utf8>
-
-This option causes field values to be interpreted as UTF8 strings, by
-default they are interpreted as ASCII. This means that the field
-values, whether prompted from a terminal or obtained from a
-configuration file, must be valid UTF8 strings.
-
-=item B<-nameopt option>
-
-Option which determines how the subject or issuer names are displayed. The
-B<option> argument can be a single option or multiple options separated by
-commas. Alternatively the B<-nameopt> switch may be used more than once to
-set multiple options. See the L<x509(1)> manual page for details.
-
-=item B<-reqopt>
-
-Customise the output format used with B<-text>. The B<option> argument can be
-a single option or multiple options separated by commas.
-
-See discussion of the B<-certopt> parameter in the L<x509(1)>
-command.
-
-=item B<-newhdr>
-
-Adds the word B<NEW> to the PEM file header and footer lines on the outputted
-request. Some software (Netscape certificate server) and some CAs need this.
-
-=item B<-batch>
-
-Non-interactive mode.
-
-=item B<-verbose>
-
-Print extra details about the operations being performed.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<req>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=item B<-keygen_engine id>
-
-Specifies an engine (by its unique B<id> string) which would be used
-for key generation operations.
-
-=back
-
-=head1 CONFIGURATION FILE FORMAT
-
-The configuration options are specified in the B<req> section of
-the configuration file. As with all configuration files if no
-value is specified in the specific section (i.e. B<req>) then
-the initial unnamed or B<default> section is searched too.
-
-The options available are described in detail below.
-
-=over 4
-
-=item B<input_password output_password>
-
-The passwords for the input private key file (if present) and
-the output private key file (if one will be created). The
-command line options B<passin> and B<passout> override the
-configuration file values.
-
-=item B<default_bits>
-
-Specifies the default key size in bits.
-
-This option is used in conjunction with the B<-new> option to generate
-a new key. It can be overridden by specifying an explicit key size in
-the B<-newkey> option. The smallest accepted key size is 512 bits. If
-no key size is specified then 2048 bits is used.
-
-=item B<default_keyfile>
-
-This is the default filename to write a private key to. If not
-specified the key is written to standard output. This can be
-overridden by the B<-keyout> option.
-
-=item B<oid_file>
-
-This specifies a file containing additional B<OBJECT IDENTIFIERS>.
-Each line of the file should consist of the numerical form of the
-object identifier followed by white space then the short name followed
-by white space and finally the long name.
-
-=item B<oid_section>
-
-This specifies a section in the configuration file containing extra
-object identifiers. Each line should consist of the short name of the
-object identifier followed by B<=> and the numerical form. The short
-and long names are the same when this option is used.
-
-=item B<RANDFILE>
-
-At startup the specified file is loaded into the random number generator,
-and at exit 256 bytes will be written to it.
-It is used for private key generation.
-
-=item B<encrypt_key>
-
-If this is set to B<no> then if a private key is generated it is
-B<not> encrypted. This is equivalent to the B<-nodes> command line
-option. For compatibility B<encrypt_rsa_key> is an equivalent option.
-
-=item B<default_md>
-
-This option specifies the digest algorithm to use. Any digest supported by the
-OpenSSL B<dgst> command can be used. This option can be overridden on the
-command line. Certain signing algorithms (i.e. Ed25519 and Ed448) will ignore
-any digest that has been set.
-
-=item B<string_mask>
-
-This option masks out the use of certain string types in certain
-fields. Most users will not need to change this option.
-
-It can be set to several values B<default> which is also the default
-option uses PrintableStrings, T61Strings and BMPStrings if the
-B<pkix> value is used then only PrintableStrings and BMPStrings will
-be used. This follows the PKIX recommendation in RFC2459. If the
-B<utf8only> option is used then only UTF8Strings will be used: this
-is the PKIX recommendation in RFC2459 after 2003. Finally the B<nombstr>
-option just uses PrintableStrings and T61Strings: certain software has
-problems with BMPStrings and UTF8Strings: in particular Netscape.
-
-=item B<req_extensions>
-
-This specifies the configuration file section containing a list of
-extensions to add to the certificate request. It can be overridden
-by the B<-reqexts> command line switch. See the
-L<x509v3_config(5)> manual page for details of the
-extension section format.
-
-=item B<x509_extensions>
-
-This specifies the configuration file section containing a list of
-extensions to add to certificate generated when the B<-x509> switch
-is used. It can be overridden by the B<-extensions> command line switch.
-
-=item B<prompt>
-
-If set to the value B<no> this disables prompting of certificate fields
-and just takes values from the config file directly. It also changes the
-expected format of the B<distinguished_name> and B<attributes> sections.
-
-=item B<utf8>
-
-If set to the value B<yes> then field values to be interpreted as UTF8
-strings, by default they are interpreted as ASCII. This means that
-the field values, whether prompted from a terminal or obtained from a
-configuration file, must be valid UTF8 strings.
-
-=item B<attributes>
-
-This specifies the section containing any request attributes: its format
-is the same as B<distinguished_name>. Typically these may contain the
-challengePassword or unstructuredName types. They are currently ignored
-by OpenSSL's request signing utilities but some CAs might want them.
-
-=item B<distinguished_name>
-
-This specifies the section containing the distinguished name fields to
-prompt for when generating a certificate or certificate request. The format
-is described in the next section.
-
-=back
-
-=head1 DISTINGUISHED NAME AND ATTRIBUTE SECTION FORMAT
-
-There are two separate formats for the distinguished name and attribute
-sections. If the B<prompt> option is set to B<no> then these sections
-just consist of field names and values: for example,
-
- CN=My Name
- OU=My Organization
- emailAddress=someone@somewhere.org
-
-This allows external programs (e.g. GUI based) to generate a template file
-with all the field names and values and just pass it to B<req>. An example
-of this kind of configuration file is contained in the B<EXAMPLES> section.
-
-Alternatively if the B<prompt> option is absent or not set to B<no> then the
-file contains field prompting information. It consists of lines of the form:
-
- fieldName="prompt"
- fieldName_default="default field value"
- fieldName_min= 2
- fieldName_max= 4
-
-"fieldName" is the field name being used, for example commonName (or CN).
-The "prompt" string is used to ask the user to enter the relevant
-details. If the user enters nothing then the default value is used if no
-default value is present then the field is omitted. A field can
-still be omitted if a default value is present if the user just
-enters the '.' character.
-
-The number of characters entered must be between the fieldName_min and
-fieldName_max limits: there may be additional restrictions based
-on the field being used (for example countryName can only ever be
-two characters long and must fit in a PrintableString).
-
-Some fields (such as organizationName) can be used more than once
-in a DN. This presents a problem because configuration files will
-not recognize the same name occurring twice. To avoid this problem
-if the fieldName contains some characters followed by a full stop
-they will be ignored. So for example a second organizationName can
-be input by calling it "1.organizationName".
-
-The actual permitted field names are any object identifier short or
-long names. These are compiled into OpenSSL and include the usual
-values such as commonName, countryName, localityName, organizationName,
-organizationalUnitName, stateOrProvinceName. Additionally emailAddress
-is included as well as name, surname, givenName, initials, and dnQualifier.
-
-Additional object identifiers can be defined with the B<oid_file> or
-B<oid_section> options in the configuration file. Any additional fields
-will be treated as though they were a DirectoryString.
-
-
-=head1 EXAMPLES
-
-Examine and verify certificate request:
-
- openssl req -in req.pem -text -verify -noout
-
-Create a private key and then generate a certificate request from it:
-
- openssl genrsa -out key.pem 2048
- openssl req -new -key key.pem -out req.pem
-
-The same but just using req:
-
- openssl req -newkey rsa:2048 -keyout key.pem -out req.pem
-
-Generate a self signed root certificate:
-
- openssl req -x509 -newkey rsa:2048 -keyout key.pem -out req.pem
-
-Example of a file pointed to by the B<oid_file> option:
-
- 1.2.3.4 shortName A longer Name
- 1.2.3.6 otherName Other longer Name
-
-Example of a section pointed to by B<oid_section> making use of variable
-expansion:
-
- testoid1=1.2.3.5
- testoid2=${testoid1}.6
-
-Sample configuration file prompting for field values:
-
- [ req ]
- default_bits = 2048
- default_keyfile = privkey.pem
- distinguished_name = req_distinguished_name
- attributes = req_attributes
- req_extensions = v3_ca
-
- dirstring_type = nobmp
-
- [ req_distinguished_name ]
- countryName = Country Name (2 letter code)
- countryName_default = AU
- countryName_min = 2
- countryName_max = 2
-
- localityName = Locality Name (eg, city)
-
- organizationalUnitName = Organizational Unit Name (eg, section)
-
- commonName = Common Name (eg, YOUR name)
- commonName_max = 64
-
- emailAddress = Email Address
- emailAddress_max = 40
-
- [ req_attributes ]
- challengePassword = A challenge password
- challengePassword_min = 4
- challengePassword_max = 20
-
- [ v3_ca ]
-
- subjectKeyIdentifier=hash
- authorityKeyIdentifier=keyid:always,issuer:always
- basicConstraints = critical, CA:true
-
-Sample configuration containing all field values:
-
-
- RANDFILE = $ENV::HOME/.rnd
-
- [ req ]
- default_bits = 2048
- default_keyfile = keyfile.pem
- distinguished_name = req_distinguished_name
- attributes = req_attributes
- prompt = no
- output_password = mypass
-
- [ req_distinguished_name ]
- C = GB
- ST = Test State or Province
- L = Test Locality
- O = Organization Name
- OU = Organizational Unit Name
- CN = Common Name
- emailAddress = test@email.address
-
- [ req_attributes ]
- challengePassword = A challenge password
-
-Example of giving the most common attributes (subject and extensions)
-on the command line:
-
- openssl req -new -subj "/C=GB/CN=foo" \
- -addext "subjectAltName = DNS:foo.co.uk" \
- -addext "certificatePolicies = 1.2.3.4" \
- -newkey rsa:2048 -keyout key.pem -out req.pem
-
-
-=head1 NOTES
-
-The header and footer lines in the B<PEM> format are normally:
-
- -----BEGIN CERTIFICATE REQUEST-----
- -----END CERTIFICATE REQUEST-----
-
-some software (some versions of Netscape certificate server) instead needs:
-
- -----BEGIN NEW CERTIFICATE REQUEST-----
- -----END NEW CERTIFICATE REQUEST-----
-
-which is produced with the B<-newhdr> option but is otherwise compatible.
-Either form is accepted transparently on input.
-
-The certificate requests generated by B<Xenroll> with MSIE have extensions
-added. It includes the B<keyUsage> extension which determines the type of
-key (signature only or general purpose) and any additional OIDs entered
-by the script in an extendedKeyUsage extension.
-
-=head1 DIAGNOSTICS
-
-The following messages are frequently asked about:
-
- Using configuration from /some/path/openssl.cnf
- Unable to load config info
-
-This is followed some time later by...
-
- unable to find 'distinguished_name' in config
- problems making Certificate Request
-
-The first error message is the clue: it can't find the configuration
-file! Certain operations (like examining a certificate request) don't
-need a configuration file so its use isn't enforced. Generation of
-certificates or requests however does need a configuration file. This
-could be regarded as a bug.
-
-Another puzzling message is this:
-
- Attributes:
- a0:00
-
-this is displayed when no attributes are present and the request includes
-the correct empty B<SET OF> structure (the DER encoding of which is 0xa0
-0x00). If you just see:
-
- Attributes:
-
-then the B<SET OF> is missing and the encoding is technically invalid (but
-it is tolerated). See the description of the command line option B<-asn1-kludge>
-for more information.
-
-=head1 BUGS
-
-OpenSSL's handling of T61Strings (aka TeletexStrings) is broken: it effectively
-treats them as ISO-8859-1 (Latin 1), Netscape and MSIE have similar behaviour.
-This can cause problems if you need characters that aren't available in
-PrintableStrings and you don't want to or can't use BMPStrings.
-
-As a consequence of the T61String handling the only correct way to represent
-accented characters in OpenSSL is to use a BMPString: unfortunately Netscape
-currently chokes on these. If you have to use accented characters with Netscape
-and MSIE then you currently need to use the invalid T61String form.
-
-The current prompting is not very friendly. It doesn't allow you to confirm what
-you've just entered. Other things like extensions in certificate requests are
-statically defined in the configuration file. Some of these: like an email
-address in subjectAltName should be input by the user.
-
-=head1 SEE ALSO
-
-L<x509(1)>, L<ca(1)>, L<genrsa(1)>,
-L<gendsa(1)>, L<config(5)>,
-L<x509v3_config(5)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/rsa.pod b/doc/man1/rsa.pod
deleted file mode 100644
index fddd828b9fc4..000000000000
--- a/doc/man1/rsa.pod
+++ /dev/null
@@ -1,205 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-rsa,
-rsa - RSA key processing tool
-
-=head1 SYNOPSIS
-
-B<openssl> B<rsa>
-[B<-help>]
-[B<-inform PEM|DER>]
-[B<-outform PEM|DER>]
-[B<-in filename>]
-[B<-passin arg>]
-[B<-out filename>]
-[B<-passout arg>]
-[B<-aes128>]
-[B<-aes192>]
-[B<-aes256>]
-[B<-aria128>]
-[B<-aria192>]
-[B<-aria256>]
-[B<-camellia128>]
-[B<-camellia192>]
-[B<-camellia256>]
-[B<-des>]
-[B<-des3>]
-[B<-idea>]
-[B<-text>]
-[B<-noout>]
-[B<-modulus>]
-[B<-check>]
-[B<-pubin>]
-[B<-pubout>]
-[B<-RSAPublicKey_in>]
-[B<-RSAPublicKey_out>]
-[B<-engine id>]
-
-=head1 DESCRIPTION
-
-The B<rsa> command processes RSA keys. They can be converted between various
-forms and their components printed out. B<Note> this command uses the
-traditional SSLeay compatible format for private key encryption: newer
-applications should use the more secure PKCS#8 format using the B<pkcs8>
-utility.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-inform DER|PEM>
-
-This specifies the input format. The B<DER> option uses an ASN1 DER encoded
-form compatible with the PKCS#1 RSAPrivateKey or SubjectPublicKeyInfo format.
-The B<PEM> form is the default format: it consists of the B<DER> format base64
-encoded with additional header and footer lines. On input PKCS#8 format private
-keys are also accepted.
-
-=item B<-outform DER|PEM>
-
-This specifies the output format, the options have the same meaning and default
-as the B<-inform> option.
-
-=item B<-in filename>
-
-This specifies the input filename to read a key from or standard input if this
-option is not specified. If the key is encrypted a pass phrase will be
-prompted for.
-
-=item B<-passin arg>
-
-The input file password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-out filename>
-
-This specifies the output filename to write a key to or standard output if this
-option is not specified. If any encryption options are set then a pass phrase
-will be prompted for. The output filename should B<not> be the same as the input
-filename.
-
-=item B<-passout password>
-
-The output file password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-aes128>, B<-aes192>, B<-aes256>, B<-aria128>, B<-aria192>, B<-aria256>, B<-camellia128>, B<-camellia192>, B<-camellia256>, B<-des>, B<-des3>, B<-idea>
-
-These options encrypt the private key with the specified
-cipher before outputting it. A pass phrase is prompted for.
-If none of these options is specified the key is written in plain text. This
-means that using the B<rsa> utility to read in an encrypted key with no
-encryption option can be used to remove the pass phrase from a key, or by
-setting the encryption options it can be use to add or change the pass phrase.
-These options can only be used with PEM format output files.
-
-=item B<-text>
-
-Prints out the various public or private key components in
-plain text in addition to the encoded version.
-
-=item B<-noout>
-
-This option prevents output of the encoded version of the key.
-
-=item B<-modulus>
-
-This option prints out the value of the modulus of the key.
-
-=item B<-check>
-
-This option checks the consistency of an RSA private key.
-
-=item B<-pubin>
-
-By default a private key is read from the input file: with this
-option a public key is read instead.
-
-=item B<-pubout>
-
-By default a private key is output: with this option a public
-key will be output instead. This option is automatically set if
-the input is a public key.
-
-=item B<-RSAPublicKey_in>, B<-RSAPublicKey_out>
-
-Like B<-pubin> and B<-pubout> except B<RSAPublicKey> format is used instead.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<rsa>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=back
-
-=head1 NOTES
-
-The PEM private key format uses the header and footer lines:
-
- -----BEGIN RSA PRIVATE KEY-----
- -----END RSA PRIVATE KEY-----
-
-The PEM public key format uses the header and footer lines:
-
- -----BEGIN PUBLIC KEY-----
- -----END PUBLIC KEY-----
-
-The PEM B<RSAPublicKey> format uses the header and footer lines:
-
- -----BEGIN RSA PUBLIC KEY-----
- -----END RSA PUBLIC KEY-----
-
-=head1 EXAMPLES
-
-To remove the pass phrase on an RSA private key:
-
- openssl rsa -in key.pem -out keyout.pem
-
-To encrypt a private key using triple DES:
-
- openssl rsa -in key.pem -des3 -out keyout.pem
-
-To convert a private key from PEM to DER format:
-
- openssl rsa -in key.pem -outform DER -out keyout.der
-
-To print out the components of a private key to standard output:
-
- openssl rsa -in key.pem -text -noout
-
-To just output the public part of a private key:
-
- openssl rsa -in key.pem -pubout -out pubkey.pem
-
-Output the public part of a private key in B<RSAPublicKey> format:
-
- openssl rsa -in key.pem -RSAPublicKey_out -out pubkey.pem
-
-=head1 BUGS
-
-There should be an option that automatically handles .key files,
-without having to manually edit them.
-
-=head1 SEE ALSO
-
-L<pkcs8(1)>, L<dsa(1)>, L<genrsa(1)>,
-L<gendsa(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/rsautl.pod b/doc/man1/rsautl.pod
deleted file mode 100644
index fdc67432fbf1..000000000000
--- a/doc/man1/rsautl.pod
+++ /dev/null
@@ -1,220 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-rsautl,
-rsautl - RSA utility
-
-=head1 SYNOPSIS
-
-B<openssl> B<rsautl>
-[B<-help>]
-[B<-in file>]
-[B<-out file>]
-[B<-inkey file>]
-[B<-keyform PEM|DER|ENGINE>]
-[B<-pubin>]
-[B<-certin>]
-[B<-sign>]
-[B<-verify>]
-[B<-encrypt>]
-[B<-decrypt>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-pkcs>]
-[B<-ssl>]
-[B<-raw>]
-[B<-hexdump>]
-[B<-asn1parse>]
-
-=head1 DESCRIPTION
-
-The B<rsautl> command can be used to sign, verify, encrypt and decrypt
-data using the RSA algorithm.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-in filename>
-
-This specifies the input filename to read data from or standard input
-if this option is not specified.
-
-=item B<-out filename>
-
-Specifies the output filename to write to or standard output by
-default.
-
-=item B<-inkey file>
-
-The input key file, by default it should be an RSA private key.
-
-=item B<-keyform PEM|DER|ENGINE>
-
-The key format PEM, DER or ENGINE.
-
-=item B<-pubin>
-
-The input file is an RSA public key.
-
-=item B<-certin>
-
-The input is a certificate containing an RSA public key.
-
-=item B<-sign>
-
-Sign the input data and output the signed result. This requires
-an RSA private key.
-
-=item B<-verify>
-
-Verify the input data and output the recovered data.
-
-=item B<-encrypt>
-
-Encrypt the input data using an RSA public key.
-
-=item B<-decrypt>
-
-Decrypt the input data using an RSA private key.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<-pkcs, -oaep, -ssl, -raw>
-
-The padding to use: PKCS#1 v1.5 (the default), PKCS#1 OAEP,
-special padding used in SSL v2 backwards compatible handshakes,
-or no padding, respectively.
-For signatures, only B<-pkcs> and B<-raw> can be used.
-
-=item B<-hexdump>
-
-Hex dump the output data.
-
-=item B<-asn1parse>
-
-Parse the ASN.1 output data, this is useful when combined with the
-B<-verify> option.
-
-=back
-
-=head1 NOTES
-
-B<rsautl> because it uses the RSA algorithm directly can only be
-used to sign or verify small pieces of data.
-
-=head1 EXAMPLES
-
-Sign some data using a private key:
-
- openssl rsautl -sign -in file -inkey key.pem -out sig
-
-Recover the signed data
-
- openssl rsautl -verify -in sig -inkey key.pem
-
-Examine the raw signed data:
-
- openssl rsautl -verify -in sig -inkey key.pem -raw -hexdump
-
- 0000 - 00 01 ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
- 0010 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
- 0020 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
- 0030 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
- 0040 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
- 0050 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
- 0060 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
- 0070 - ff ff ff ff 00 68 65 6c-6c 6f 20 77 6f 72 6c 64 .....hello world
-
-The PKCS#1 block formatting is evident from this. If this was done using
-encrypt and decrypt the block would have been of type 2 (the second byte)
-and random padding data visible instead of the 0xff bytes.
-
-It is possible to analyse the signature of certificates using this
-utility in conjunction with B<asn1parse>. Consider the self signed
-example in certs/pca-cert.pem . Running B<asn1parse> as follows yields:
-
- openssl asn1parse -in pca-cert.pem
-
- 0:d=0 hl=4 l= 742 cons: SEQUENCE
- 4:d=1 hl=4 l= 591 cons: SEQUENCE
- 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
- 10:d=3 hl=2 l= 1 prim: INTEGER :02
- 13:d=2 hl=2 l= 1 prim: INTEGER :00
- 16:d=2 hl=2 l= 13 cons: SEQUENCE
- 18:d=3 hl=2 l= 9 prim: OBJECT :md5WithRSAEncryption
- 29:d=3 hl=2 l= 0 prim: NULL
- 31:d=2 hl=2 l= 92 cons: SEQUENCE
- 33:d=3 hl=2 l= 11 cons: SET
- 35:d=4 hl=2 l= 9 cons: SEQUENCE
- 37:d=5 hl=2 l= 3 prim: OBJECT :countryName
- 42:d=5 hl=2 l= 2 prim: PRINTABLESTRING :AU
- ....
- 599:d=1 hl=2 l= 13 cons: SEQUENCE
- 601:d=2 hl=2 l= 9 prim: OBJECT :md5WithRSAEncryption
- 612:d=2 hl=2 l= 0 prim: NULL
- 614:d=1 hl=3 l= 129 prim: BIT STRING
-
-
-The final BIT STRING contains the actual signature. It can be extracted with:
-
- openssl asn1parse -in pca-cert.pem -out sig -noout -strparse 614
-
-The certificate public key can be extracted with:
-
- openssl x509 -in test/testx509.pem -pubkey -noout >pubkey.pem
-
-The signature can be analysed with:
-
- openssl rsautl -in sig -verify -asn1parse -inkey pubkey.pem -pubin
-
- 0:d=0 hl=2 l= 32 cons: SEQUENCE
- 2:d=1 hl=2 l= 12 cons: SEQUENCE
- 4:d=2 hl=2 l= 8 prim: OBJECT :md5
- 14:d=2 hl=2 l= 0 prim: NULL
- 16:d=1 hl=2 l= 16 prim: OCTET STRING
- 0000 - f3 46 9e aa 1a 4a 73 c9-37 ea 93 00 48 25 08 b5 .F...Js.7...H%..
-
-This is the parsed version of an ASN1 DigestInfo structure. It can be seen that
-the digest used was md5. The actual part of the certificate that was signed can
-be extracted with:
-
- openssl asn1parse -in pca-cert.pem -out tbs -noout -strparse 4
-
-and its digest computed with:
-
- openssl md5 -c tbs
- MD5(tbs)= f3:46:9e:aa:1a:4a:73:c9:37:ea:93:00:48:25:08:b5
-
-which it can be seen agrees with the recovered value above.
-
-=head1 SEE ALSO
-
-L<dgst(1)>, L<rsa(1)>, L<genrsa(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/s_client.pod b/doc/man1/s_client.pod
deleted file mode 100644
index f1a2c4abdf53..000000000000
--- a/doc/man1/s_client.pod
+++ /dev/null
@@ -1,838 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-s_client,
-s_client - SSL/TLS client program
-
-=head1 SYNOPSIS
-
-B<openssl> B<s_client>
-[B<-help>]
-[B<-connect host:port>]
-[B<-bind host:port>]
-[B<-proxy host:port>]
-[B<-unix path>]
-[B<-4>]
-[B<-6>]
-[B<-servername name>]
-[B<-noservername>]
-[B<-verify depth>]
-[B<-verify_return_error>]
-[B<-cert filename>]
-[B<-certform DER|PEM>]
-[B<-key filename>]
-[B<-keyform DER|PEM>]
-[B<-cert_chain filename>]
-[B<-build_chain>]
-[B<-xkey>]
-[B<-xcert>]
-[B<-xchain>]
-[B<-xchain_build>]
-[B<-xcertform PEM|DER>]
-[B<-xkeyform PEM|DER>]
-[B<-pass arg>]
-[B<-CApath directory>]
-[B<-CAfile filename>]
-[B<-chainCApath directory>]
-[B<-chainCAfile filename>]
-[B<-no-CAfile>]
-[B<-no-CApath>]
-[B<-requestCAfile filename>]
-[B<-dane_tlsa_domain domain>]
-[B<-dane_tlsa_rrdata rrdata>]
-[B<-dane_ee_no_namechecks>]
-[B<-attime timestamp>]
-[B<-check_ss_sig>]
-[B<-crl_check>]
-[B<-crl_check_all>]
-[B<-explicit_policy>]
-[B<-extended_crl>]
-[B<-ignore_critical>]
-[B<-inhibit_any>]
-[B<-inhibit_map>]
-[B<-no_check_time>]
-[B<-partial_chain>]
-[B<-policy arg>]
-[B<-policy_check>]
-[B<-policy_print>]
-[B<-purpose purpose>]
-[B<-suiteB_128>]
-[B<-suiteB_128_only>]
-[B<-suiteB_192>]
-[B<-trusted_first>]
-[B<-no_alt_chains>]
-[B<-use_deltas>]
-[B<-auth_level num>]
-[B<-nameopt option>]
-[B<-verify_depth num>]
-[B<-verify_email email>]
-[B<-verify_hostname hostname>]
-[B<-verify_ip ip>]
-[B<-verify_name name>]
-[B<-build_chain>]
-[B<-x509_strict>]
-[B<-reconnect>]
-[B<-showcerts>]
-[B<-debug>]
-[B<-msg>]
-[B<-nbio_test>]
-[B<-state>]
-[B<-nbio>]
-[B<-crlf>]
-[B<-ign_eof>]
-[B<-no_ign_eof>]
-[B<-psk_identity identity>]
-[B<-psk key>]
-[B<-psk_session file>]
-[B<-quiet>]
-[B<-ssl3>]
-[B<-tls1>]
-[B<-tls1_1>]
-[B<-tls1_2>]
-[B<-tls1_3>]
-[B<-no_ssl3>]
-[B<-no_tls1>]
-[B<-no_tls1_1>]
-[B<-no_tls1_2>]
-[B<-no_tls1_3>]
-[B<-dtls>]
-[B<-dtls1>]
-[B<-dtls1_2>]
-[B<-sctp>]
-[B<-sctp_label_bug>]
-[B<-fallback_scsv>]
-[B<-async>]
-[B<-max_send_frag>]
-[B<-split_send_frag>]
-[B<-max_pipelines>]
-[B<-read_buf>]
-[B<-bugs>]
-[B<-comp>]
-[B<-no_comp>]
-[B<-allow_no_dhe_kex>]
-[B<-sigalgs sigalglist>]
-[B<-curves curvelist>]
-[B<-cipher cipherlist>]
-[B<-ciphersuites val>]
-[B<-serverpref>]
-[B<-starttls protocol>]
-[B<-xmpphost hostname>]
-[B<-name hostname>]
-[B<-engine id>]
-[B<-tlsextdebug>]
-[B<-no_ticket>]
-[B<-sess_out filename>]
-[B<-sess_in filename>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-serverinfo types>]
-[B<-status>]
-[B<-alpn protocols>]
-[B<-nextprotoneg protocols>]
-[B<-ct>]
-[B<-noct>]
-[B<-ctlogfile>]
-[B<-keylogfile file>]
-[B<-early_data file>]
-[B<-enable_pha>]
-[B<target>]
-
-=head1 DESCRIPTION
-
-The B<s_client> command implements a generic SSL/TLS client which connects
-to a remote host using SSL/TLS. It is a I<very> useful diagnostic tool for
-SSL servers.
-
-=head1 OPTIONS
-
-In addition to the options below the B<s_client> utility also supports the
-common and client only options documented
-in the "Supported Command Line Commands" section of the L<SSL_CONF_cmd(3)>
-manual page.
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-connect host:port>
-
-This specifies the host and optional port to connect to. It is possible to
-select the host and port using the optional target positional argument instead.
-If neither this nor the target positional argument are specified then an attempt
-is made to connect to the local host on port 4433.
-
-=item B<-bind host:port>]
-
-This specifies the host address and or port to bind as the source for the
-connection. For Unix-domain sockets the port is ignored and the host is
-used as the source socket address.
-
-=item B<-proxy host:port>
-
-When used with the B<-connect> flag, the program uses the host and port
-specified with this flag and issues an HTTP CONNECT command to connect
-to the desired server.
-
-=item B<-unix path>
-
-Connect over the specified Unix-domain socket.
-
-=item B<-4>
-
-Use IPv4 only.
-
-=item B<-6>
-
-Use IPv6 only.
-
-=item B<-servername name>
-
-Set the TLS SNI (Server Name Indication) extension in the ClientHello message to
-the given value.
-If B<-servername> is not provided, the TLS SNI extension will be populated with
-the name given to B<-connect> if it follows a DNS name format. If B<-connect> is
-not provided either, the SNI is set to "localhost".
-This is the default since OpenSSL 1.1.1.
-
-Even though SNI should normally be a DNS name and not an IP address, if
-B<-servername> is provided then that name will be sent, regardless of whether
-it is a DNS name or not.
-
-This option cannot be used in conjunction with B<-noservername>.
-
-=item B<-noservername>
-
-Suppresses sending of the SNI (Server Name Indication) extension in the
-ClientHello message. Cannot be used in conjunction with the B<-servername> or
-<-dane_tlsa_domain> options.
-
-=item B<-cert certname>
-
-The certificate to use, if one is requested by the server. The default is
-not to use a certificate.
-
-=item B<-certform format>
-
-The certificate format to use: DER or PEM. PEM is the default.
-
-=item B<-key keyfile>
-
-The private key to use. If not specified then the certificate file will
-be used.
-
-=item B<-keyform format>
-
-The private format to use: DER or PEM. PEM is the default.
-
-=item B<-cert_chain>
-
-A file containing trusted certificates to use when attempting to build the
-client/server certificate chain related to the certificate specified via the
-B<-cert> option.
-
-=item B<-build_chain>
-
-Specify whether the application should build the certificate chain to be
-provided to the server.
-
-=item B<-xkey infile>, B<-xcert infile>, B<-xchain>
-
-Specify an extra certificate, private key and certificate chain. These behave
-in the same manner as the B<-cert>, B<-key> and B<-cert_chain> options. When
-specified, the callback returning the first valid chain will be in use by the
-client.
-
-=item B<-xchain_build>
-
-Specify whether the application should build the certificate chain to be
-provided to the server for the extra certificates provided via B<-xkey infile>,
-B<-xcert infile>, B<-xchain> options.
-
-=item B<-xcertform PEM|DER>, B<-xkeyform PEM|DER>
-
-Extra certificate and private key format respectively.
-
-=item B<-pass arg>
-
-the private key password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-verify depth>
-
-The verify depth to use. This specifies the maximum length of the
-server certificate chain and turns on server certificate verification.
-Currently the verify operation continues after errors so all the problems
-with a certificate chain can be seen. As a side effect the connection
-will never fail due to a server certificate verify failure.
-
-=item B<-verify_return_error>
-
-Return verification errors instead of continuing. This will typically
-abort the handshake with a fatal error.
-
-=item B<-nameopt option>
-
-Option which determines how the subject or issuer names are displayed. The
-B<option> argument can be a single option or multiple options separated by
-commas. Alternatively the B<-nameopt> switch may be used more than once to
-set multiple options. See the L<x509(1)> manual page for details.
-
-=item B<-CApath directory>
-
-The directory to use for server certificate verification. This directory
-must be in "hash format", see L<verify(1)> for more information. These are
-also used when building the client certificate chain.
-
-=item B<-CAfile file>
-
-A file containing trusted certificates to use during server authentication
-and to use when attempting to build the client certificate chain.
-
-=item B<-chainCApath directory>
-
-The directory to use for building the chain provided to the server. This
-directory must be in "hash format", see L<verify(1)> for more information.
-
-=item B<-chainCAfile file>
-
-A file containing trusted certificates to use when attempting to build the
-client certificate chain.
-
-=item B<-no-CAfile>
-
-Do not load the trusted CA certificates from the default file location
-
-=item B<-no-CApath>
-
-Do not load the trusted CA certificates from the default directory location
-
-=item B<-requestCAfile file>
-
-A file containing a list of certificates whose subject names will be sent
-to the server in the B<certificate_authorities> extension. Only supported
-for TLS 1.3
-
-=item B<-dane_tlsa_domain domain>
-
-Enable RFC6698/RFC7671 DANE TLSA authentication and specify the
-TLSA base domain which becomes the default SNI hint and the primary
-reference identifier for hostname checks. This must be used in
-combination with at least one instance of the B<-dane_tlsa_rrdata>
-option below.
-
-When DANE authentication succeeds, the diagnostic output will include
-the lowest (closest to 0) depth at which a TLSA record authenticated
-a chain certificate. When that TLSA record is a "2 1 0" trust
-anchor public key that signed (rather than matched) the top-most
-certificate of the chain, the result is reported as "TA public key
-verified". Otherwise, either the TLSA record "matched TA certificate"
-at a positive depth or else "matched EE certificate" at depth 0.
-
-=item B<-dane_tlsa_rrdata rrdata>
-
-Use one or more times to specify the RRDATA fields of the DANE TLSA
-RRset associated with the target service. The B<rrdata> value is
-specified in "presentation form", that is four whitespace separated
-fields that specify the usage, selector, matching type and associated
-data, with the last of these encoded in hexadecimal. Optional
-whitespace is ignored in the associated data field. For example:
-
- $ openssl s_client -brief -starttls smtp \
- -connect smtp.example.com:25 \
- -dane_tlsa_domain smtp.example.com \
- -dane_tlsa_rrdata "2 1 1
- B111DD8A1C2091A89BD4FD60C57F0716CCE50FEEFF8137CDBEE0326E 02CF362B" \
- -dane_tlsa_rrdata "2 1 1
- 60B87575447DCBA2A36B7D11AC09FB24A9DB406FEE12D2CC90180517 616E8A18"
- ...
- Verification: OK
- Verified peername: smtp.example.com
- DANE TLSA 2 1 1 ...ee12d2cc90180517616e8a18 matched TA certificate at depth 1
- ...
-
-=item B<-dane_ee_no_namechecks>
-
-This disables server name checks when authenticating via DANE-EE(3) TLSA
-records.
-For some applications, primarily web browsers, it is not safe to disable name
-checks due to "unknown key share" attacks, in which a malicious server can
-convince a client that a connection to a victim server is instead a secure
-connection to the malicious server.
-The malicious server may then be able to violate cross-origin scripting
-restrictions.
-Thus, despite the text of RFC7671, name checks are by default enabled for
-DANE-EE(3) TLSA records, and can be disabled in applications where it is safe
-to do so.
-In particular, SMTP and XMPP clients should set this option as SRV and MX
-records already make it possible for a remote domain to redirect client
-connections to any server of its choice, and in any case SMTP and XMPP clients
-do not execute scripts downloaded from remote servers.
-
-=item B<-attime>, B<-check_ss_sig>, B<-crl_check>, B<-crl_check_all>,
-B<-explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,
-B<-inhibit_map>, B<-no_alt_chains>, B<-no_check_time>, B<-partial_chain>, B<-policy>,
-B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,
-B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,
-B<-auth_level>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
-B<-verify_ip>, B<-verify_name>, B<-x509_strict>
-
-Set various certificate chain validation options. See the
-L<verify(1)> manual page for details.
-
-=item B<-reconnect>
-
-Reconnects to the same server 5 times using the same session ID, this can
-be used as a test that session caching is working.
-
-=item B<-showcerts>
-
-Displays the server certificate list as sent by the server: it only consists of
-certificates the server has sent (in the order the server has sent them). It is
-B<not> a verified chain.
-
-=item B<-prexit>
-
-Print session information when the program exits. This will always attempt
-to print out information even if the connection fails. Normally information
-will only be printed out once if the connection succeeds. This option is useful
-because the cipher in use may be renegotiated or the connection may fail
-because a client certificate is required or is requested only after an
-attempt is made to access a certain URL. Note: the output produced by this
-option is not always accurate because a connection might never have been
-established.
-
-=item B<-state>
-
-Prints out the SSL session states.
-
-=item B<-debug>
-
-Print extensive debugging information including a hex dump of all traffic.
-
-=item B<-msg>
-
-Show all protocol messages with hex dump.
-
-=item B<-trace>
-
-Show verbose trace output of protocol messages. OpenSSL needs to be compiled
-with B<enable-ssl-trace> for this option to work.
-
-=item B<-msgfile>
-
-File to send output of B<-msg> or B<-trace> to, default standard output.
-
-=item B<-nbio_test>
-
-Tests nonblocking I/O
-
-=item B<-nbio>
-
-Turns on nonblocking I/O
-
-=item B<-crlf>
-
-This option translated a line feed from the terminal into CR+LF as required
-by some servers.
-
-=item B<-ign_eof>
-
-Inhibit shutting down the connection when end of file is reached in the
-input.
-
-=item B<-quiet>
-
-Inhibit printing of session and certificate information. This implicitly
-turns on B<-ign_eof> as well.
-
-=item B<-no_ign_eof>
-
-Shut down the connection when end of file is reached in the input.
-Can be used to override the implicit B<-ign_eof> after B<-quiet>.
-
-=item B<-psk_identity identity>
-
-Use the PSK identity B<identity> when using a PSK cipher suite.
-The default value is "Client_identity" (without the quotes).
-
-=item B<-psk key>
-
-Use the PSK key B<key> when using a PSK cipher suite. The key is
-given as a hexadecimal number without leading 0x, for example -psk
-1a2b3c4d.
-This option must be provided in order to use a PSK cipher.
-
-=item B<-psk_session file>
-
-Use the pem encoded SSL_SESSION data stored in B<file> as the basis of a PSK.
-Note that this will only work if TLSv1.3 is negotiated.
-
-=item B<-ssl3>, B<-tls1>, B<-tls1_1>, B<-tls1_2>, B<-tls1_3>, B<-no_ssl3>, B<-no_tls1>, B<-no_tls1_1>, B<-no_tls1_2>, B<-no_tls1_3>
-
-These options require or disable the use of the specified SSL or TLS protocols.
-By default B<s_client> will negotiate the highest mutually supported protocol
-version.
-When a specific TLS version is required, only that version will be offered to
-and accepted from the server.
-Note that not all protocols and flags may be available, depending on how
-OpenSSL was built.
-
-=item B<-dtls>, B<-dtls1>, B<-dtls1_2>
-
-These options make B<s_client> use DTLS protocols instead of TLS.
-With B<-dtls>, B<s_client> will negotiate any supported DTLS protocol version,
-whilst B<-dtls1> and B<-dtls1_2> will only support DTLS1.0 and DTLS1.2
-respectively.
-
-=item B<-sctp>
-
-Use SCTP for the transport protocol instead of UDP in DTLS. Must be used in
-conjunction with B<-dtls>, B<-dtls1> or B<-dtls1_2>. This option is only
-available where OpenSSL has support for SCTP enabled.
-
-=item B<-sctp_label_bug>
-
-Use the incorrect behaviour of older OpenSSL implementations when computing
-endpoint-pair shared secrets for DTLS/SCTP. This allows communication with
-older broken implementations but breaks interoperability with correct
-implementations. Must be used in conjunction with B<-sctp>. This option is only
-available where OpenSSL has support for SCTP enabled.
-
-=item B<-fallback_scsv>
-
-Send TLS_FALLBACK_SCSV in the ClientHello.
-
-=item B<-async>
-
-Switch on asynchronous mode. Cryptographic operations will be performed
-asynchronously. This will only have an effect if an asynchronous capable engine
-is also used via the B<-engine> option. For test purposes the dummy async engine
-(dasync) can be used (if available).
-
-=item B<-max_send_frag int>
-
-The maximum size of data fragment to send.
-See L<SSL_CTX_set_max_send_fragment(3)> for further information.
-
-=item B<-split_send_frag int>
-
-The size used to split data for encrypt pipelines. If more data is written in
-one go than this value then it will be split into multiple pipelines, up to the
-maximum number of pipelines defined by max_pipelines. This only has an effect if
-a suitable cipher suite has been negotiated, an engine that supports pipelining
-has been loaded, and max_pipelines is greater than 1. See
-L<SSL_CTX_set_split_send_fragment(3)> for further information.
-
-=item B<-max_pipelines int>
-
-The maximum number of encrypt/decrypt pipelines to be used. This will only have
-an effect if an engine has been loaded that supports pipelining (e.g. the dasync
-engine) and a suitable cipher suite has been negotiated. The default value is 1.
-See L<SSL_CTX_set_max_pipelines(3)> for further information.
-
-=item B<-read_buf int>
-
-The default read buffer size to be used for connections. This will only have an
-effect if the buffer size is larger than the size that would otherwise be used
-and pipelining is in use (see L<SSL_CTX_set_default_read_buffer_len(3)> for
-further information).
-
-=item B<-bugs>
-
-There are several known bugs in SSL and TLS implementations. Adding this
-option enables various workarounds.
-
-=item B<-comp>
-
-Enables support for SSL/TLS compression.
-This option was introduced in OpenSSL 1.1.0.
-TLS compression is not recommended and is off by default as of
-OpenSSL 1.1.0.
-
-=item B<-no_comp>
-
-Disables support for SSL/TLS compression.
-TLS compression is not recommended and is off by default as of
-OpenSSL 1.1.0.
-
-=item B<-brief>
-
-Only provide a brief summary of connection parameters instead of the
-normal verbose output.
-
-=item B<-sigalgs sigalglist>
-
-Specifies the list of signature algorithms that are sent by the client.
-The server selects one entry in the list based on its preferences.
-For example strings, see L<SSL_CTX_set1_sigalgs(3)>
-
-=item B<-curves curvelist>
-
-Specifies the list of supported curves to be sent by the client. The curve is
-ultimately selected by the server. For a list of all curves, use:
-
- $ openssl ecparam -list_curves
-
-=item B<-cipher cipherlist>
-
-This allows the TLSv1.2 and below cipher list sent by the client to be modified.
-This list will be combined with any TLSv1.3 ciphersuites that have been
-configured. Although the server determines which ciphersuite is used it should
-take the first supported cipher in the list sent by the client. See the
-B<ciphers> command for more information.
-
-=item B<-ciphersuites val>
-
-This allows the TLSv1.3 ciphersuites sent by the client to be modified. This
-list will be combined with any TLSv1.2 and below ciphersuites that have been
-configured. Although the server determines which cipher suite is used it should
-take the first supported cipher in the list sent by the client. See the
-B<ciphers> command for more information. The format for this list is a simple
-colon (":") separated list of TLSv1.3 ciphersuite names.
-
-=item B<-starttls protocol>
-
-Send the protocol-specific message(s) to switch to TLS for communication.
-B<protocol> is a keyword for the intended protocol. Currently, the only
-supported keywords are "smtp", "pop3", "imap", "ftp", "xmpp", "xmpp-server",
-"irc", "postgres", "mysql", "lmtp", "nntp", "sieve" and "ldap".
-
-=item B<-xmpphost hostname>
-
-This option, when used with "-starttls xmpp" or "-starttls xmpp-server",
-specifies the host for the "to" attribute of the stream element.
-If this option is not specified, then the host specified with "-connect"
-will be used.
-
-This option is an alias of the B<-name> option for "xmpp" and "xmpp-server".
-
-=item B<-name hostname>
-
-This option is used to specify hostname information for various protocols
-used with B<-starttls> option. Currently only "xmpp", "xmpp-server",
-"smtp" and "lmtp" can utilize this B<-name> option.
-
-If this option is used with "-starttls xmpp" or "-starttls xmpp-server",
-if specifies the host for the "to" attribute of the stream element. If this
-option is not specified, then the host specified with "-connect" will be used.
-
-If this option is used with "-starttls lmtp" or "-starttls smtp", it specifies
-the name to use in the "LMTP LHLO" or "SMTP EHLO" message, respectively. If
-this option is not specified, then "mail.example.com" will be used.
-
-=item B<-tlsextdebug>
-
-Print out a hex dump of any TLS extensions received from the server.
-
-=item B<-no_ticket>
-
-Disable RFC4507bis session ticket support.
-
-=item B<-sess_out filename>
-
-Output SSL session to B<filename>.
-
-=item B<-sess_in sess.pem>
-
-Load SSL session from B<filename>. The client will attempt to resume a
-connection from this session.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<s_client>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<-serverinfo types>
-
-A list of comma-separated TLS Extension Types (numbers between 0 and
-65535). Each type will be sent as an empty ClientHello TLS Extension.
-The server's response (if any) will be encoded and displayed as a PEM
-file.
-
-=item B<-status>
-
-Sends a certificate status request to the server (OCSP stapling). The server
-response (if any) is printed out.
-
-=item B<-alpn protocols>, B<-nextprotoneg protocols>
-
-These flags enable the Enable the Application-Layer Protocol Negotiation
-or Next Protocol Negotiation (NPN) extension, respectively. ALPN is the
-IETF standard and replaces NPN.
-The B<protocols> list is a comma-separated list of protocol names that
-the client should advertise support for. The list should contain the most
-desirable protocols first. Protocol names are printable ASCII strings,
-for example "http/1.1" or "spdy/3".
-An empty list of protocols is treated specially and will cause the
-client to advertise support for the TLS extension but disconnect just
-after receiving ServerHello with a list of server supported protocols.
-The flag B<-nextprotoneg> cannot be specified if B<-tls1_3> is used.
-
-=item B<-ct>, B<-noct>
-
-Use one of these two options to control whether Certificate Transparency (CT)
-is enabled (B<-ct>) or disabled (B<-noct>).
-If CT is enabled, signed certificate timestamps (SCTs) will be requested from
-the server and reported at handshake completion.
-
-Enabling CT also enables OCSP stapling, as this is one possible delivery method
-for SCTs.
-
-=item B<-ctlogfile>
-
-A file containing a list of known Certificate Transparency logs. See
-L<SSL_CTX_set_ctlog_list_file(3)> for the expected file format.
-
-=item B<-keylogfile file>
-
-Appends TLS secrets to the specified keylog file such that external programs
-(like Wireshark) can decrypt TLS connections.
-
-=item B<-early_data file>
-
-Reads the contents of the specified file and attempts to send it as early data
-to the server. This will only work with resumed sessions that support early
-data and when the server accepts the early data.
-
-=item B<-enable_pha>
-
-For TLSv1.3 only, send the Post-Handshake Authentication extension. This will
-happen whether or not a certificate has been provided via B<-cert>.
-
-=item B<[target]>
-
-Rather than providing B<-connect>, the target hostname and optional port may
-be provided as a single positional argument after all options. If neither this
-nor B<-connect> are provided, falls back to attempting to connect to localhost
-on port 4433.
-
-=back
-
-=head1 CONNECTED COMMANDS
-
-If a connection is established with an SSL server then any data received
-from the server is displayed and any key presses will be sent to the
-server. If end of file is reached then the connection will be closed down. When
-used interactively (which means neither B<-quiet> nor B<-ign_eof> have been
-given), then certain commands are also recognized which perform special
-operations. These commands are a letter which must appear at the start of a
-line. They are listed below.
-
-=over 4
-
-=item B<Q>
-
-End the current SSL connection and exit.
-
-=item B<R>
-
-Renegotiate the SSL session (TLSv1.2 and below only).
-
-=item B<B>
-
-Send a heartbeat message to the server (DTLS only)
-
-=item B<k>
-
-Send a key update message to the server (TLSv1.3 only)
-
-=item B<K>
-
-Send a key update message to the server and request one back (TLSv1.3 only)
-
-=back
-
-=head1 NOTES
-
-B<s_client> can be used to debug SSL servers. To connect to an SSL HTTP
-server the command:
-
- openssl s_client -connect servername:443
-
-would typically be used (https uses port 443). If the connection succeeds
-then an HTTP command can be given such as "GET /" to retrieve a web page.
-
-If the handshake fails then there are several possible causes, if it is
-nothing obvious like no client certificate then the B<-bugs>,
-B<-ssl3>, B<-tls1>, B<-no_ssl3>, B<-no_tls1> options can be tried
-in case it is a buggy server. In particular you should play with these
-options B<before> submitting a bug report to an OpenSSL mailing list.
-
-A frequent problem when attempting to get client certificates working
-is that a web client complains it has no certificates or gives an empty
-list to choose from. This is normally because the server is not sending
-the clients certificate authority in its "acceptable CA list" when it
-requests a certificate. By using B<s_client> the CA list can be viewed
-and checked. However, some servers only request client authentication
-after a specific URL is requested. To obtain the list in this case it
-is necessary to use the B<-prexit> option and send an HTTP request
-for an appropriate page.
-
-If a certificate is specified on the command line using the B<-cert>
-option it will not be used unless the server specifically requests
-a client certificate. Therefore, merely including a client certificate
-on the command line is no guarantee that the certificate works.
-
-If there are problems verifying a server certificate then the
-B<-showcerts> option can be used to show all the certificates sent by the
-server.
-
-The B<s_client> utility is a test tool and is designed to continue the
-handshake after any certificate verification errors. As a result it will
-accept any certificate chain (trusted or not) sent by the peer. Non-test
-applications should B<not> do this as it makes them vulnerable to a MITM
-attack. This behaviour can be changed by with the B<-verify_return_error>
-option: any verify errors are then returned aborting the handshake.
-
-The B<-bind> option may be useful if the server or a firewall requires
-connections to come from some particular address and or port.
-
-=head1 BUGS
-
-Because this program has a lot of options and also because some of the
-techniques used are rather old, the C source of B<s_client> is rather hard to
-read and not a model of how things should be done.
-A typical SSL client program would be much simpler.
-
-The B<-prexit> option is a bit of a hack. We should really report
-information whenever a session is renegotiated.
-
-=head1 SEE ALSO
-
-L<SSL_CONF_cmd(3)>, L<sess_id(1)>, L<s_server(1)>, L<ciphers(1)>,
-L<SSL_CTX_set_max_send_fragment(3)>, L<SSL_CTX_set_split_send_fragment(3)>,
-L<SSL_CTX_set_max_pipelines(3)>
-
-=head1 HISTORY
-
-The B<-no_alt_chains> option was added in OpenSSL 1.1.0.
-The B<-name> option was added in OpenSSL 1.1.1.
-
-=head1 COPYRIGHT
-
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/s_server.pod b/doc/man1/s_server.pod
deleted file mode 100644
index aa6c19d31f9a..000000000000
--- a/doc/man1/s_server.pod
+++ /dev/null
@@ -1,855 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-s_server,
-s_server - SSL/TLS server program
-
-=head1 SYNOPSIS
-
-B<openssl> B<s_server>
-[B<-help>]
-[B<-port +int>]
-[B<-accept val>]
-[B<-unix val>]
-[B<-4>]
-[B<-6>]
-[B<-unlink>]
-[B<-context val>]
-[B<-verify int>]
-[B<-Verify int>]
-[B<-cert infile>]
-[B<-nameopt val>]
-[B<-naccept +int>]
-[B<-serverinfo val>]
-[B<-certform PEM|DER>]
-[B<-key infile>]
-[B<-keyform format>]
-[B<-pass val>]
-[B<-dcert infile>]
-[B<-dcertform PEM|DER>]
-[B<-dkey infile>]
-[B<-dkeyform PEM|DER>]
-[B<-dpass val>]
-[B<-nbio_test>]
-[B<-crlf>]
-[B<-debug>]
-[B<-msg>]
-[B<-msgfile outfile>]
-[B<-state>]
-[B<-CAfile infile>]
-[B<-CApath dir>]
-[B<-no-CAfile>]
-[B<-no-CApath>]
-[B<-nocert>]
-[B<-quiet>]
-[B<-no_resume_ephemeral>]
-[B<-www>]
-[B<-WWW>]
-[B<-servername>]
-[B<-servername_fatal>]
-[B<-cert2 infile>]
-[B<-key2 infile>]
-[B<-tlsextdebug>]
-[B<-HTTP>]
-[B<-id_prefix val>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-keymatexport val>]
-[B<-keymatexportlen +int>]
-[B<-CRL infile>]
-[B<-crl_download>]
-[B<-cert_chain infile>]
-[B<-dcert_chain infile>]
-[B<-chainCApath dir>]
-[B<-verifyCApath dir>]
-[B<-no_cache>]
-[B<-ext_cache>]
-[B<-CRLform PEM|DER>]
-[B<-verify_return_error>]
-[B<-verify_quiet>]
-[B<-build_chain>]
-[B<-chainCAfile infile>]
-[B<-verifyCAfile infile>]
-[B<-ign_eof>]
-[B<-no_ign_eof>]
-[B<-status>]
-[B<-status_verbose>]
-[B<-status_timeout int>]
-[B<-status_url val>]
-[B<-status_file infile>]
-[B<-trace>]
-[B<-security_debug>]
-[B<-security_debug_verbose>]
-[B<-brief>]
-[B<-rev>]
-[B<-async>]
-[B<-ssl_config val>]
-[B<-max_send_frag +int>]
-[B<-split_send_frag +int>]
-[B<-max_pipelines +int>]
-[B<-read_buf +int>]
-[B<-no_ssl3>]
-[B<-no_tls1>]
-[B<-no_tls1_1>]
-[B<-no_tls1_2>]
-[B<-no_tls1_3>]
-[B<-bugs>]
-[B<-no_comp>]
-[B<-comp>]
-[B<-no_ticket>]
-[B<-num_tickets>]
-[B<-serverpref>]
-[B<-legacy_renegotiation>]
-[B<-no_renegotiation>]
-[B<-legacy_server_connect>]
-[B<-no_resumption_on_reneg>]
-[B<-no_legacy_server_connect>]
-[B<-allow_no_dhe_kex>]
-[B<-prioritize_chacha>]
-[B<-strict>]
-[B<-sigalgs val>]
-[B<-client_sigalgs val>]
-[B<-groups val>]
-[B<-curves val>]
-[B<-named_curve val>]
-[B<-cipher val>]
-[B<-ciphersuites val>]
-[B<-dhparam infile>]
-[B<-record_padding val>]
-[B<-debug_broken_protocol>]
-[B<-policy val>]
-[B<-purpose val>]
-[B<-verify_name val>]
-[B<-verify_depth int>]
-[B<-auth_level int>]
-[B<-attime intmax>]
-[B<-verify_hostname val>]
-[B<-verify_email val>]
-[B<-verify_ip>]
-[B<-ignore_critical>]
-[B<-issuer_checks>]
-[B<-crl_check>]
-[B<-crl_check_all>]
-[B<-policy_check>]
-[B<-explicit_policy>]
-[B<-inhibit_any>]
-[B<-inhibit_map>]
-[B<-x509_strict>]
-[B<-extended_crl>]
-[B<-use_deltas>]
-[B<-policy_print>]
-[B<-check_ss_sig>]
-[B<-trusted_first>]
-[B<-suiteB_128_only>]
-[B<-suiteB_128>]
-[B<-suiteB_192>]
-[B<-partial_chain>]
-[B<-no_alt_chains>]
-[B<-no_check_time>]
-[B<-allow_proxy_certs>]
-[B<-xkey>]
-[B<-xcert>]
-[B<-xchain>]
-[B<-xchain_build>]
-[B<-xcertform PEM|DER>]
-[B<-xkeyform PEM|DER>]
-[B<-nbio>]
-[B<-psk_identity val>]
-[B<-psk_hint val>]
-[B<-psk val>]
-[B<-psk_session file>]
-[B<-srpvfile infile>]
-[B<-srpuserseed val>]
-[B<-ssl3>]
-[B<-tls1>]
-[B<-tls1_1>]
-[B<-tls1_2>]
-[B<-tls1_3>]
-[B<-dtls>]
-[B<-timeout>]
-[B<-mtu +int>]
-[B<-listen>]
-[B<-dtls1>]
-[B<-dtls1_2>]
-[B<-sctp>]
-[B<-sctp_label_bug>]
-[B<-no_dhe>]
-[B<-nextprotoneg val>]
-[B<-use_srtp val>]
-[B<-alpn val>]
-[B<-engine val>]
-[B<-keylogfile outfile>]
-[B<-max_early_data int>]
-[B<-early_data>]
-[B<-anti_replay>]
-[B<-no_anti_replay>]
-
-=head1 DESCRIPTION
-
-The B<s_server> command implements a generic SSL/TLS server which listens
-for connections on a given port using SSL/TLS.
-
-=head1 OPTIONS
-
-In addition to the options below the B<s_server> utility also supports the
-common and server only options documented
-in the "Supported Command Line Commands" section of the L<SSL_CONF_cmd(3)>
-manual page.
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-port +int>
-
-The TCP port to listen on for connections. If not specified 4433 is used.
-
-=item B<-accept val>
-
-The optional TCP host and port to listen on for connections. If not specified, *:4433 is used.
-
-=item B<-unix val>
-
-Unix domain socket to accept on.
-
-=item B<-4>
-
-Use IPv4 only.
-
-=item B<-6>
-
-Use IPv6 only.
-
-=item B<-unlink>
-
-For -unix, unlink any existing socket first.
-
-=item B<-context val>
-
-Sets the SSL context id. It can be given any string value. If this option
-is not present a default value will be used.
-
-=item B<-verify int>, B<-Verify int>
-
-The verify depth to use. This specifies the maximum length of the
-client certificate chain and makes the server request a certificate from
-the client. With the B<-verify> option a certificate is requested but the
-client does not have to send one, with the B<-Verify> option the client
-must supply a certificate or an error occurs.
-
-If the cipher suite cannot request a client certificate (for example an
-anonymous cipher suite or PSK) this option has no effect.
-
-=item B<-cert infile>
-
-The certificate to use, most servers cipher suites require the use of a
-certificate and some require a certificate with a certain public key type:
-for example the DSS cipher suites require a certificate containing a DSS
-(DSA) key. If not specified then the filename "server.pem" will be used.
-
-=item B<-cert_chain>
-
-A file containing trusted certificates to use when attempting to build the
-client/server certificate chain related to the certificate specified via the
-B<-cert> option.
-
-=item B<-build_chain>
-
-Specify whether the application should build the certificate chain to be
-provided to the client.
-
-=item B<-nameopt val>
-
-Option which determines how the subject or issuer names are displayed. The
-B<val> argument can be a single option or multiple options separated by
-commas. Alternatively the B<-nameopt> switch may be used more than once to
-set multiple options. See the L<x509(1)> manual page for details.
-
-=item B<-naccept +int>
-
-The server will exit after receiving the specified number of connections,
-default unlimited.
-
-=item B<-serverinfo val>
-
-A file containing one or more blocks of PEM data. Each PEM block
-must encode a TLS ServerHello extension (2 bytes type, 2 bytes length,
-followed by "length" bytes of extension data). If the client sends
-an empty TLS ClientHello extension matching the type, the corresponding
-ServerHello extension will be returned.
-
-=item B<-certform PEM|DER>
-
-The certificate format to use: DER or PEM. PEM is the default.
-
-=item B<-key infile>
-
-The private key to use. If not specified then the certificate file will
-be used.
-
-=item B<-keyform format>
-
-The private format to use: DER or PEM. PEM is the default.
-
-=item B<-pass val>
-
-The private key password source. For more information about the format of B<val>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-dcert infile>, B<-dkey infile>
-
-Specify an additional certificate and private key, these behave in the
-same manner as the B<-cert> and B<-key> options except there is no default
-if they are not specified (no additional certificate and key is used). As
-noted above some cipher suites require a certificate containing a key of
-a certain type. Some cipher suites need a certificate carrying an RSA key
-and some a DSS (DSA) key. By using RSA and DSS certificates and keys
-a server can support clients which only support RSA or DSS cipher suites
-by using an appropriate certificate.
-
-=item B<-dcert_chain>
-
-A file containing trusted certificates to use when attempting to build the
-server certificate chain when a certificate specified via the B<-dcert> option
-is in use.
-
-=item B<-dcertform PEM|DER>, B<-dkeyform PEM|DER>, B<-dpass val>
-
-Additional certificate and private key format and passphrase respectively.
-
-=item B<-xkey infile>, B<-xcert infile>, B<-xchain>
-
-Specify an extra certificate, private key and certificate chain. These behave
-in the same manner as the B<-cert>, B<-key> and B<-cert_chain> options. When
-specified, the callback returning the first valid chain will be in use by
-the server.
-
-=item B<-xchain_build>
-
-Specify whether the application should build the certificate chain to be
-provided to the client for the extra certificates provided via B<-xkey infile>,
-B<-xcert infile>, B<-xchain> options.
-
-=item B<-xcertform PEM|DER>, B<-xkeyform PEM|DER>
-
-Extra certificate and private key format respectively.
-
-=item B<-nbio_test>
-
-Tests non blocking I/O.
-
-=item B<-crlf>
-
-This option translated a line feed from the terminal into CR+LF.
-
-=item B<-debug>
-
-Print extensive debugging information including a hex dump of all traffic.
-
-=item B<-msg>
-
-Show all protocol messages with hex dump.
-
-=item B<-msgfile outfile>
-
-File to send output of B<-msg> or B<-trace> to, default standard output.
-
-=item B<-state>
-
-Prints the SSL session states.
-
-=item B<-CAfile infile>
-
-A file containing trusted certificates to use during client authentication
-and to use when attempting to build the server certificate chain. The list
-is also used in the list of acceptable client CAs passed to the client when
-a certificate is requested.
-
-=item B<-CApath dir>
-
-The directory to use for client certificate verification. This directory
-must be in "hash format", see L<verify(1)> for more information. These are
-also used when building the server certificate chain.
-
-=item B<-chainCApath dir>
-
-The directory to use for building the chain provided to the client. This
-directory must be in "hash format", see L<verify(1)> for more information.
-
-=item B<-chainCAfile file>
-
-A file containing trusted certificates to use when attempting to build the
-server certificate chain.
-
-=item B<-no-CAfile>
-
-Do not load the trusted CA certificates from the default file location.
-
-=item B<-no-CApath>
-
-Do not load the trusted CA certificates from the default directory location.
-
-=item B<-nocert>
-
-If this option is set then no certificate is used. This restricts the
-cipher suites available to the anonymous ones (currently just anonymous
-DH).
-
-=item B<-quiet>
-
-Inhibit printing of session and certificate information.
-
-=item B<-www>
-
-Sends a status message back to the client when it connects. This includes
-information about the ciphers used and various session parameters.
-The output is in HTML format so this option will normally be used with a
-web browser. Cannot be used in conjunction with B<-early_data>.
-
-=item B<-WWW>
-
-Emulates a simple web server. Pages will be resolved relative to the
-current directory, for example if the URL https://myhost/page.html is
-requested the file ./page.html will be loaded. Cannot be used in conjunction
-with B<-early_data>.
-
-=item B<-tlsextdebug>
-
-Print a hex dump of any TLS extensions received from the server.
-
-=item B<-HTTP>
-
-Emulates a simple web server. Pages will be resolved relative to the
-current directory, for example if the URL https://myhost/page.html is
-requested the file ./page.html will be loaded. The files loaded are
-assumed to contain a complete and correct HTTP response (lines that
-are part of the HTTP response line and headers must end with CRLF). Cannot be
-used in conjunction with B<-early_data>.
-
-=item B<-id_prefix val>
-
-Generate SSL/TLS session IDs prefixed by B<val>. This is mostly useful
-for testing any SSL/TLS code (e.g. proxies) that wish to deal with multiple
-servers, when each of which might be generating a unique range of session
-IDs (e.g. with a certain prefix).
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<-verify_return_error>
-
-Verification errors normally just print a message but allow the
-connection to continue, for debugging purposes.
-If this option is used, then verification errors close the connection.
-
-=item B<-status>
-
-Enables certificate status request support (aka OCSP stapling).
-
-=item B<-status_verbose>
-
-Enables certificate status request support (aka OCSP stapling) and gives
-a verbose printout of the OCSP response.
-
-=item B<-status_timeout int>
-
-Sets the timeout for OCSP response to B<int> seconds.
-
-=item B<-status_url val>
-
-Sets a fallback responder URL to use if no responder URL is present in the
-server certificate. Without this option an error is returned if the server
-certificate does not contain a responder address.
-
-=item B<-status_file infile>
-
-Overrides any OCSP responder URLs from the certificate and always provides the
-OCSP Response stored in the file. The file must be in DER format.
-
-=item B<-trace>
-
-Show verbose trace output of protocol messages. OpenSSL needs to be compiled
-with B<enable-ssl-trace> for this option to work.
-
-=item B<-brief>
-
-Provide a brief summary of connection parameters instead of the normal verbose
-output.
-
-=item B<-rev>
-
-Simple test server which just reverses the text received from the client
-and sends it back to the server. Also sets B<-brief>. Cannot be used in
-conjunction with B<-early_data>.
-
-=item B<-async>
-
-Switch on asynchronous mode. Cryptographic operations will be performed
-asynchronously. This will only have an effect if an asynchronous capable engine
-is also used via the B<-engine> option. For test purposes the dummy async engine
-(dasync) can be used (if available).
-
-=item B<-max_send_frag +int>
-
-The maximum size of data fragment to send.
-See L<SSL_CTX_set_max_send_fragment(3)> for further information.
-
-=item B<-split_send_frag +int>
-
-The size used to split data for encrypt pipelines. If more data is written in
-one go than this value then it will be split into multiple pipelines, up to the
-maximum number of pipelines defined by max_pipelines. This only has an effect if
-a suitable cipher suite has been negotiated, an engine that supports pipelining
-has been loaded, and max_pipelines is greater than 1. See
-L<SSL_CTX_set_split_send_fragment(3)> for further information.
-
-=item B<-max_pipelines +int>
-
-The maximum number of encrypt/decrypt pipelines to be used. This will only have
-an effect if an engine has been loaded that supports pipelining (e.g. the dasync
-engine) and a suitable cipher suite has been negotiated. The default value is 1.
-See L<SSL_CTX_set_max_pipelines(3)> for further information.
-
-=item B<-read_buf +int>
-
-The default read buffer size to be used for connections. This will only have an
-effect if the buffer size is larger than the size that would otherwise be used
-and pipelining is in use (see L<SSL_CTX_set_default_read_buffer_len(3)> for
-further information).
-
-=item B<-ssl2>, B<-ssl3>, B<-tls1>, B<-tls1_1>, B<-tls1_2>, B<-tls1_3>, B<-no_ssl2>, B<-no_ssl3>, B<-no_tls1>, B<-no_tls1_1>, B<-no_tls1_2>, B<-no_tls1_3>
-
-These options require or disable the use of the specified SSL or TLS protocols.
-By default B<s_server> will negotiate the highest mutually supported protocol
-version.
-When a specific TLS version is required, only that version will be accepted
-from the client.
-Note that not all protocols and flags may be available, depending on how
-OpenSSL was built.
-
-=item B<-bugs>
-
-There are several known bugs in SSL and TLS implementations. Adding this
-option enables various workarounds.
-
-=item B<-no_comp>
-
-Disable negotiation of TLS compression.
-TLS compression is not recommended and is off by default as of
-OpenSSL 1.1.0.
-
-=item B<-comp>
-
-Enable negotiation of TLS compression.
-This option was introduced in OpenSSL 1.1.0.
-TLS compression is not recommended and is off by default as of
-OpenSSL 1.1.0.
-
-=item B<-no_ticket>
-
-Disable RFC4507bis session ticket support. This option has no effect if TLSv1.3
-is negotiated. See B<-num_tickets>.
-
-=item B<-num_tickets>
-
-Control the number of tickets that will be sent to the client after a full
-handshake in TLSv1.3. The default number of tickets is 2. This option does not
-affect the number of tickets sent after a resumption handshake.
-
-=item B<-serverpref>
-
-Use the server's cipher preferences, rather than the client's preferences.
-
-=item B<-prioritize_chacha>
-
-Prioritize ChaCha ciphers when preferred by clients. Requires B<-serverpref>.
-
-=item B<-no_resumption_on_reneg>
-
-Set the B<SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION> option.
-
-=item B<-client_sigalgs val>
-
-Signature algorithms to support for client certificate authentication
-(colon-separated list).
-
-=item B<-named_curve val>
-
-Specifies the elliptic curve to use. NOTE: this is single curve, not a list.
-For a list of all possible curves, use:
-
- $ openssl ecparam -list_curves
-
-=item B<-cipher val>
-
-This allows the list of TLSv1.2 and below ciphersuites used by the server to be
-modified. This list is combined with any TLSv1.3 ciphersuites that have been
-configured. When the client sends a list of supported ciphers the first client
-cipher also included in the server list is used. Because the client specifies
-the preference order, the order of the server cipherlist is irrelevant. See
-the B<ciphers> command for more information.
-
-=item B<-ciphersuites val>
-
-This allows the list of TLSv1.3 ciphersuites used by the server to be modified.
-This list is combined with any TLSv1.2 and below ciphersuites that have been
-configured. When the client sends a list of supported ciphers the first client
-cipher also included in the server list is used. Because the client specifies
-the preference order, the order of the server cipherlist is irrelevant. See
-the B<ciphers> command for more information. The format for this list is a
-simple colon (":") separated list of TLSv1.3 ciphersuite names.
-
-=item B<-dhparam infile>
-
-The DH parameter file to use. The ephemeral DH cipher suites generate keys
-using a set of DH parameters. If not specified then an attempt is made to
-load the parameters from the server certificate file.
-If this fails then a static set of parameters hard coded into the B<s_server>
-program will be used.
-
-=item B<-attime>, B<-check_ss_sig>, B<-crl_check>, B<-crl_check_all>,
-B<-explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,
-B<-inhibit_map>, B<-no_alt_chains>, B<-no_check_time>, B<-partial_chain>, B<-policy>,
-B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,
-B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,
-B<-auth_level>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
-B<-verify_ip>, B<-verify_name>, B<-x509_strict>
-
-Set different peer certificate verification options.
-See the L<verify(1)> manual page for details.
-
-=item B<-crl_check>, B<-crl_check_all>
-
-Check the peer certificate has not been revoked by its CA.
-The CRL(s) are appended to the certificate file. With the B<-crl_check_all>
-option all CRLs of all CAs in the chain are checked.
-
-=item B<-nbio>
-
-Turns on non blocking I/O.
-
-=item B<-psk_identity val>
-
-Expect the client to send PSK identity B<val> when using a PSK
-cipher suite, and warn if they do not. By default, the expected PSK
-identity is the string "Client_identity".
-
-=item B<-psk_hint val>
-
-Use the PSK identity hint B<val> when using a PSK cipher suite.
-
-=item B<-psk val>
-
-Use the PSK key B<val> when using a PSK cipher suite. The key is
-given as a hexadecimal number without leading 0x, for example -psk
-1a2b3c4d.
-This option must be provided in order to use a PSK cipher.
-
-=item B<-psk_session file>
-
-Use the pem encoded SSL_SESSION data stored in B<file> as the basis of a PSK.
-Note that this will only work if TLSv1.3 is negotiated.
-
-=item B<-listen>
-
-This option can only be used in conjunction with one of the DTLS options above.
-With this option B<s_server> will listen on a UDP port for incoming connections.
-Any ClientHellos that arrive will be checked to see if they have a cookie in
-them or not.
-Any without a cookie will be responded to with a HelloVerifyRequest.
-If a ClientHello with a cookie is received then B<s_server> will connect to
-that peer and complete the handshake.
-
-=item B<-dtls>, B<-dtls1>, B<-dtls1_2>
-
-These options make B<s_server> use DTLS protocols instead of TLS.
-With B<-dtls>, B<s_server> will negotiate any supported DTLS protocol version,
-whilst B<-dtls1> and B<-dtls1_2> will only support DTLSv1.0 and DTLSv1.2
-respectively.
-
-=item B<-sctp>
-
-Use SCTP for the transport protocol instead of UDP in DTLS. Must be used in
-conjunction with B<-dtls>, B<-dtls1> or B<-dtls1_2>. This option is only
-available where OpenSSL has support for SCTP enabled.
-
-=item B<-sctp_label_bug>
-
-Use the incorrect behaviour of older OpenSSL implementations when computing
-endpoint-pair shared secrets for DTLS/SCTP. This allows communication with
-older broken implementations but breaks interoperability with correct
-implementations. Must be used in conjunction with B<-sctp>. This option is only
-available where OpenSSL has support for SCTP enabled.
-
-=item B<-no_dhe>
-
-If this option is set then no DH parameters will be loaded effectively
-disabling the ephemeral DH cipher suites.
-
-=item B<-alpn val>, B<-nextprotoneg val>
-
-These flags enable the Application-Layer Protocol Negotiation
-or Next Protocol Negotiation (NPN) extension, respectively. ALPN is the
-IETF standard and replaces NPN.
-The B<val> list is a comma-separated list of supported protocol
-names. The list should contain the most desirable protocols first.
-Protocol names are printable ASCII strings, for example "http/1.1" or
-"spdy/3".
-The flag B<-nextprotoneg> cannot be specified if B<-tls1_3> is used.
-
-=item B<-engine val>
-
-Specifying an engine (by its unique id string in B<val>) will cause B<s_server>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=item B<-keylogfile outfile>
-
-Appends TLS secrets to the specified keylog file such that external programs
-(like Wireshark) can decrypt TLS connections.
-
-=item B<-max_early_data int>
-
-Change the default maximum early data bytes that are specified for new sessions
-and any incoming early data (when used in conjunction with the B<-early_data>
-flag). The default value is approximately 16k. The argument must be an integer
-greater than or equal to 0.
-
-=item B<-early_data>
-
-Accept early data where possible. Cannot be used in conjunction with B<-www>,
-B<-WWW>, B<-HTTP> or B<-rev>.
-
-=item B<-anti_replay>, B<-no_anti_replay>
-
-Switches replay protection on or off, respectively. Replay protection is on by
-default unless overridden by a configuration file. When it is on, OpenSSL will
-automatically detect if a session ticket has been used more than once, TLSv1.3
-has been negotiated, and early data is enabled on the server. A full handshake
-is forced if a session ticket is used a second or subsequent time. Any early
-data that was sent will be rejected.
-
-=back
-
-=head1 CONNECTED COMMANDS
-
-If a connection request is established with an SSL client and neither the
-B<-www> nor the B<-WWW> option has been used then normally any data received
-from the client is displayed and any key presses will be sent to the client.
-
-Certain commands are also recognized which perform special operations. These
-commands are a letter which must appear at the start of a line. They are listed
-below.
-
-=over 4
-
-=item B<q>
-
-End the current SSL connection but still accept new connections.
-
-=item B<Q>
-
-End the current SSL connection and exit.
-
-=item B<r>
-
-Renegotiate the SSL session (TLSv1.2 and below only).
-
-=item B<R>
-
-Renegotiate the SSL session and request a client certificate (TLSv1.2 and below
-only).
-
-=item B<P>
-
-Send some plain text down the underlying TCP connection: this should
-cause the client to disconnect due to a protocol violation.
-
-=item B<S>
-
-Print out some session cache status information.
-
-=item B<B>
-
-Send a heartbeat message to the client (DTLS only)
-
-=item B<k>
-
-Send a key update message to the client (TLSv1.3 only)
-
-=item B<K>
-
-Send a key update message to the client and request one back (TLSv1.3 only)
-
-=item B<c>
-
-Send a certificate request to the client (TLSv1.3 only)
-
-=back
-
-=head1 NOTES
-
-B<s_server> can be used to debug SSL clients. To accept connections from
-a web browser the command:
-
- openssl s_server -accept 443 -www
-
-can be used for example.
-
-Although specifying an empty list of CAs when requesting a client certificate
-is strictly speaking a protocol violation, some SSL clients interpret this to
-mean any CA is acceptable. This is useful for debugging purposes.
-
-The session parameters can printed out using the B<sess_id> program.
-
-=head1 BUGS
-
-Because this program has a lot of options and also because some of the
-techniques used are rather old, the C source of B<s_server> is rather hard to
-read and not a model of how things should be done.
-A typical SSL server program would be much simpler.
-
-The output of common ciphers is wrong: it just gives the list of ciphers that
-OpenSSL recognizes and the client supports.
-
-There should be a way for the B<s_server> program to print out details of any
-unknown cipher suites a client says it supports.
-
-=head1 SEE ALSO
-
-L<SSL_CONF_cmd(3)>, L<sess_id(1)>, L<s_client(1)>, L<ciphers(1)>
-L<SSL_CTX_set_max_send_fragment(3)>,
-L<SSL_CTX_set_split_send_fragment(3)>,
-L<SSL_CTX_set_max_pipelines(3)>
-
-=head1 HISTORY
-
-The -no_alt_chains option was added in OpenSSL 1.1.0.
-
-The
--allow-no-dhe-kex and -prioritize_chacha options were added in OpenSSL 1.1.1.
-
-=head1 COPYRIGHT
-
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/s_time.pod b/doc/man1/s_time.pod
deleted file mode 100644
index 1085bfbbb44b..000000000000
--- a/doc/man1/s_time.pod
+++ /dev/null
@@ -1,212 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-s_time,
-s_time - SSL/TLS performance timing program
-
-=head1 SYNOPSIS
-
-B<openssl> B<s_time>
-[B<-help>]
-[B<-connect host:port>]
-[B<-www page>]
-[B<-cert filename>]
-[B<-key filename>]
-[B<-CApath directory>]
-[B<-CAfile filename>]
-[B<-no-CAfile>]
-[B<-no-CApath>]
-[B<-reuse>]
-[B<-new>]
-[B<-verify depth>]
-[B<-nameopt option>]
-[B<-time seconds>]
-[B<-ssl3>]
-[B<-bugs>]
-[B<-cipher cipherlist>]
-[B<-ciphersuites val>]
-
-=head1 DESCRIPTION
-
-The B<s_time> command implements a generic SSL/TLS client which connects to a
-remote host using SSL/TLS. It can request a page from the server and includes
-the time to transfer the payload data in its timing measurements. It measures
-the number of connections within a given timeframe, the amount of data
-transferred (if any), and calculates the average time spent for one connection.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-connect host:port>
-
-This specifies the host and optional port to connect to.
-
-=item B<-www page>
-
-This specifies the page to GET from the server. A value of '/' gets the
-index.htm[l] page. If this parameter is not specified, then B<s_time> will only
-perform the handshake to establish SSL connections but not transfer any
-payload data.
-
-=item B<-cert certname>
-
-The certificate to use, if one is requested by the server. The default is
-not to use a certificate. The file is in PEM format.
-
-=item B<-key keyfile>
-
-The private key to use. If not specified then the certificate file will
-be used. The file is in PEM format.
-
-=item B<-verify depth>
-
-The verify depth to use. This specifies the maximum length of the
-server certificate chain and turns on server certificate verification.
-Currently the verify operation continues after errors so all the problems
-with a certificate chain can be seen. As a side effect the connection
-will never fail due to a server certificate verify failure.
-
-=item B<-nameopt option>
-
-Option which determines how the subject or issuer names are displayed. The
-B<option> argument can be a single option or multiple options separated by
-commas. Alternatively the B<-nameopt> switch may be used more than once to
-set multiple options. See the L<x509(1)> manual page for details.
-
-=item B<-CApath directory>
-
-The directory to use for server certificate verification. This directory
-must be in "hash format", see B<verify> for more information. These are
-also used when building the client certificate chain.
-
-=item B<-CAfile file>
-
-A file containing trusted certificates to use during server authentication
-and to use when attempting to build the client certificate chain.
-
-=item B<-no-CAfile>
-
-Do not load the trusted CA certificates from the default file location
-
-=item B<-no-CApath>
-
-Do not load the trusted CA certificates from the default directory location
-
-=item B<-new>
-
-Performs the timing test using a new session ID for each connection.
-If neither B<-new> nor B<-reuse> are specified, they are both on by default
-and executed in sequence.
-
-=item B<-reuse>
-
-Performs the timing test using the same session ID; this can be used as a test
-that session caching is working. If neither B<-new> nor B<-reuse> are
-specified, they are both on by default and executed in sequence.
-
-=item B<-ssl3>
-
-This option disables the use of SSL version 3. By default
-the initial handshake uses a method which should be compatible with all
-servers and permit them to use SSL v3 or TLS as appropriate.
-
-The timing program is not as rich in options to turn protocols on and off as
-the L<s_client(1)> program and may not connect to all servers.
-Unfortunately there are a lot of ancient and broken servers in use which
-cannot handle this technique and will fail to connect. Some servers only
-work if TLS is turned off with the B<-ssl3> option.
-
-Note that this option may not be available, depending on how
-OpenSSL was built.
-
-=item B<-bugs>
-
-There are several known bugs in SSL and TLS implementations. Adding this
-option enables various workarounds.
-
-=item B<-cipher cipherlist>
-
-This allows the TLSv1.2 and below cipher list sent by the client to be modified.
-This list will be combined with any TLSv1.3 ciphersuites that have been
-configured. Although the server determines which cipher suite is used it should
-take the first supported cipher in the list sent by the client. See
-L<ciphers(1)> for more information.
-
-=item B<-ciphersuites val>
-
-This allows the TLSv1.3 ciphersuites sent by the client to be modified. This
-list will be combined with any TLSv1.2 and below ciphersuites that have been
-configured. Although the server determines which cipher suite is used it should
-take the first supported cipher in the list sent by the client. See
-L<ciphers(1)> for more information. The format for this list is a simple
-colon (":") separated list of TLSv1.3 ciphersuite names.
-
-=item B<-time length>
-
-Specifies how long (in seconds) B<s_time> should establish connections and
-optionally transfer payload data from a server. Server and client performance
-and the link speed determine how many connections B<s_time> can establish.
-
-=back
-
-=head1 NOTES
-
-B<s_time> can be used to measure the performance of an SSL connection.
-To connect to an SSL HTTP server and get the default page the command
-
- openssl s_time -connect servername:443 -www / -CApath yourdir -CAfile yourfile.pem -cipher commoncipher [-ssl3]
-
-would typically be used (https uses port 443). 'commoncipher' is a cipher to
-which both client and server can agree, see the L<ciphers(1)> command
-for details.
-
-If the handshake fails then there are several possible causes, if it is
-nothing obvious like no client certificate then the B<-bugs> and
-B<-ssl3> options can be tried
-in case it is a buggy server. In particular you should play with these
-options B<before> submitting a bug report to an OpenSSL mailing list.
-
-A frequent problem when attempting to get client certificates working
-is that a web client complains it has no certificates or gives an empty
-list to choose from. This is normally because the server is not sending
-the clients certificate authority in its "acceptable CA list" when it
-requests a certificate. By using L<s_client(1)> the CA list can be
-viewed and checked. However, some servers only request client authentication
-after a specific URL is requested. To obtain the list in this case it
-is necessary to use the B<-prexit> option of L<s_client(1)> and
-send an HTTP request for an appropriate page.
-
-If a certificate is specified on the command line using the B<-cert>
-option it will not be used unless the server specifically requests
-a client certificate. Therefore, merely including a client certificate
-on the command line is no guarantee that the certificate works.
-
-=head1 BUGS
-
-Because this program does not have all the options of the
-L<s_client(1)> program to turn protocols on and off, you may not be
-able to measure the performance of all protocols with all servers.
-
-The B<-verify> option should really exit if the server verification
-fails.
-
-=head1 SEE ALSO
-
-L<s_client(1)>, L<s_server(1)>, L<ciphers(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/sess_id.pod b/doc/man1/sess_id.pod
deleted file mode 100644
index 543b5b7de7ff..000000000000
--- a/doc/man1/sess_id.pod
+++ /dev/null
@@ -1,166 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-sess_id,
-sess_id - SSL/TLS session handling utility
-
-=head1 SYNOPSIS
-
-B<openssl> B<sess_id>
-[B<-help>]
-[B<-inform PEM|DER>]
-[B<-outform PEM|DER|NSS>]
-[B<-in filename>]
-[B<-out filename>]
-[B<-text>]
-[B<-noout>]
-[B<-context ID>]
-
-=head1 DESCRIPTION
-
-The B<sess_id> process the encoded version of the SSL session structure
-and optionally prints out SSL session details (for example the SSL session
-master key) in human readable format. Since this is a diagnostic tool that
-needs some knowledge of the SSL protocol to use properly, most users will
-not need to use it.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-inform DER|PEM>
-
-This specifies the input format. The B<DER> option uses an ASN1 DER encoded
-format containing session details. The precise format can vary from one version
-to the next. The B<PEM> form is the default format: it consists of the B<DER>
-format base64 encoded with additional header and footer lines.
-
-=item B<-outform DER|PEM|NSS>
-
-This specifies the output format. The B<PEM> and B<DER> options have the same meaning
-and default as the B<-inform> option. The B<NSS> option outputs the session id and
-the master key in NSS keylog format.
-
-=item B<-in filename>
-
-This specifies the input filename to read session information from or standard
-input by default.
-
-=item B<-out filename>
-
-This specifies the output filename to write session information to or standard
-output if this option is not specified.
-
-=item B<-text>
-
-Prints out the various public or private key components in
-plain text in addition to the encoded version.
-
-=item B<-cert>
-
-If a certificate is present in the session it will be output using this option,
-if the B<-text> option is also present then it will be printed out in text form.
-
-=item B<-noout>
-
-This option prevents output of the encoded version of the session.
-
-=item B<-context ID>
-
-This option can set the session id so the output session information uses the
-supplied ID. The ID can be any string of characters. This option won't normally
-be used.
-
-=back
-
-=head1 OUTPUT
-
-Typical output:
-
- SSL-Session:
- Protocol : TLSv1
- Cipher : 0016
- Session-ID: 871E62626C554CE95488823752CBD5F3673A3EF3DCE9C67BD916C809914B40ED
- Session-ID-ctx: 01000000
- Master-Key: A7CEFC571974BE02CAC305269DC59F76EA9F0B180CB6642697A68251F2D2BB57E51DBBB4C7885573192AE9AEE220FACD
- Key-Arg : None
- Start Time: 948459261
- Timeout : 300 (sec)
- Verify return code 0 (ok)
-
-These are described below in more detail.
-
-=over 4
-
-=item B<Protocol>
-
-This is the protocol in use TLSv1.3, TLSv1.2, TLSv1.1, TLSv1 or SSLv3.
-
-=item B<Cipher>
-
-The cipher used this is the actual raw SSL or TLS cipher code, see the SSL
-or TLS specifications for more information.
-
-=item B<Session-ID>
-
-The SSL session ID in hex format.
-
-=item B<Session-ID-ctx>
-
-The session ID context in hex format.
-
-=item B<Master-Key>
-
-This is the SSL session master key.
-
-=item B<Start Time>
-
-This is the session start time represented as an integer in standard
-Unix format.
-
-=item B<Timeout>
-
-The timeout in seconds.
-
-=item B<Verify return code>
-
-This is the return code when an SSL client certificate is verified.
-
-=back
-
-=head1 NOTES
-
-The PEM encoded session format uses the header and footer lines:
-
- -----BEGIN SSL SESSION PARAMETERS-----
- -----END SSL SESSION PARAMETERS-----
-
-Since the SSL session output contains the master key it is
-possible to read the contents of an encrypted session using this
-information. Therefore, appropriate security precautions should be taken if
-the information is being output by a "real" application. This is however
-strongly discouraged and should only be used for debugging purposes.
-
-=head1 BUGS
-
-The cipher and start time should be printed out in human readable form.
-
-=head1 SEE ALSO
-
-L<ciphers(1)>, L<s_server(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/smime.pod b/doc/man1/smime.pod
deleted file mode 100644
index bf40d04cae4b..000000000000
--- a/doc/man1/smime.pod
+++ /dev/null
@@ -1,524 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-smime,
-smime - S/MIME utility
-
-=head1 SYNOPSIS
-
-B<openssl> B<smime>
-[B<-help>]
-[B<-encrypt>]
-[B<-decrypt>]
-[B<-sign>]
-[B<-resign>]
-[B<-verify>]
-[B<-pk7out>]
-[B<-binary>]
-[B<-crlfeol>]
-[B<-I<cipher>>]
-[B<-in file>]
-[B<-CAfile file>]
-[B<-CApath dir>]
-[B<-no-CAfile>]
-[B<-no-CApath>]
-[B<-attime timestamp>]
-[B<-check_ss_sig>]
-[B<-crl_check>]
-[B<-crl_check_all>]
-[B<-explicit_policy>]
-[B<-extended_crl>]
-[B<-ignore_critical>]
-[B<-inhibit_any>]
-[B<-inhibit_map>]
-[B<-partial_chain>]
-[B<-policy arg>]
-[B<-policy_check>]
-[B<-policy_print>]
-[B<-purpose purpose>]
-[B<-suiteB_128>]
-[B<-suiteB_128_only>]
-[B<-suiteB_192>]
-[B<-trusted_first>]
-[B<-no_alt_chains>]
-[B<-use_deltas>]
-[B<-auth_level num>]
-[B<-verify_depth num>]
-[B<-verify_email email>]
-[B<-verify_hostname hostname>]
-[B<-verify_ip ip>]
-[B<-verify_name name>]
-[B<-x509_strict>]
-[B<-certfile file>]
-[B<-signer file>]
-[B<-recip file>]
-[B<-inform SMIME|PEM|DER>]
-[B<-passin arg>]
-[B<-inkey file_or_id>]
-[B<-out file>]
-[B<-outform SMIME|PEM|DER>]
-[B<-content file>]
-[B<-to addr>]
-[B<-from ad>]
-[B<-subject s>]
-[B<-text>]
-[B<-indef>]
-[B<-noindef>]
-[B<-stream>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-md digest>]
-[cert.pem]...
-
-=head1 DESCRIPTION
-
-The B<smime> command handles S/MIME mail. It can encrypt, decrypt, sign and
-verify S/MIME messages.
-
-=head1 OPTIONS
-
-There are six operation options that set the type of operation to be performed.
-The meaning of the other options varies according to the operation type.
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-encrypt>
-
-Encrypt mail for the given recipient certificates. Input file is the message
-to be encrypted. The output file is the encrypted mail in MIME format.
-
-Note that no revocation check is done for the recipient cert, so if that
-key has been compromised, others may be able to decrypt the text.
-
-=item B<-decrypt>
-
-Decrypt mail using the supplied certificate and private key. Expects an
-encrypted mail message in MIME format for the input file. The decrypted mail
-is written to the output file.
-
-=item B<-sign>
-
-Sign mail using the supplied certificate and private key. Input file is
-the message to be signed. The signed message in MIME format is written
-to the output file.
-
-=item B<-verify>
-
-Verify signed mail. Expects a signed mail message on input and outputs
-the signed data. Both clear text and opaque signing is supported.
-
-=item B<-pk7out>
-
-Takes an input message and writes out a PEM encoded PKCS#7 structure.
-
-=item B<-resign>
-
-Resign a message: take an existing message and one or more new signers.
-
-=item B<-in filename>
-
-The input message to be encrypted or signed or the MIME message to
-be decrypted or verified.
-
-=item B<-inform SMIME|PEM|DER>
-
-This specifies the input format for the PKCS#7 structure. The default
-is B<SMIME> which reads an S/MIME format message. B<PEM> and B<DER>
-format change this to expect PEM and DER format PKCS#7 structures
-instead. This currently only affects the input format of the PKCS#7
-structure, if no PKCS#7 structure is being input (for example with
-B<-encrypt> or B<-sign>) this option has no effect.
-
-=item B<-out filename>
-
-The message text that has been decrypted or verified or the output MIME
-format message that has been signed or verified.
-
-=item B<-outform SMIME|PEM|DER>
-
-This specifies the output format for the PKCS#7 structure. The default
-is B<SMIME> which write an S/MIME format message. B<PEM> and B<DER>
-format change this to write PEM and DER format PKCS#7 structures
-instead. This currently only affects the output format of the PKCS#7
-structure, if no PKCS#7 structure is being output (for example with
-B<-verify> or B<-decrypt>) this option has no effect.
-
-=item B<-stream -indef -noindef>
-
-The B<-stream> and B<-indef> options are equivalent and enable streaming I/O
-for encoding operations. This permits single pass processing of data without
-the need to hold the entire contents in memory, potentially supporting very
-large files. Streaming is automatically set for S/MIME signing with detached
-data if the output format is B<SMIME> it is currently off by default for all
-other operations.
-
-=item B<-noindef>
-
-Disable streaming I/O where it would produce and indefinite length constructed
-encoding. This option currently has no effect. In future streaming will be
-enabled by default on all relevant operations and this option will disable it.
-
-=item B<-content filename>
-
-This specifies a file containing the detached content, this is only
-useful with the B<-verify> command. This is only usable if the PKCS#7
-structure is using the detached signature form where the content is
-not included. This option will override any content if the input format
-is S/MIME and it uses the multipart/signed MIME content type.
-
-=item B<-text>
-
-This option adds plain text (text/plain) MIME headers to the supplied
-message if encrypting or signing. If decrypting or verifying it strips
-off text headers: if the decrypted or verified message is not of MIME
-type text/plain then an error occurs.
-
-=item B<-CAfile file>
-
-A file containing trusted CA certificates, only used with B<-verify>.
-
-=item B<-CApath dir>
-
-A directory containing trusted CA certificates, only used with
-B<-verify>. This directory must be a standard certificate directory: that
-is a hash of each subject name (using B<x509 -hash>) should be linked
-to each certificate.
-
-=item B<-no-CAfile>
-
-Do not load the trusted CA certificates from the default file location.
-
-=item B<-no-CApath>
-
-Do not load the trusted CA certificates from the default directory location.
-
-=item B<-md digest>
-
-Digest algorithm to use when signing or resigning. If not present then the
-default digest algorithm for the signing key will be used (usually SHA1).
-
-=item B<-I<cipher>>
-
-The encryption algorithm to use. For example DES (56 bits) - B<-des>,
-triple DES (168 bits) - B<-des3>,
-EVP_get_cipherbyname() function) can also be used preceded by a dash, for
-example B<-aes-128-cbc>. See L<B<enc>|enc(1)> for list of ciphers
-supported by your version of OpenSSL.
-
-If not specified triple DES is used. Only used with B<-encrypt>.
-
-=item B<-nointern>
-
-When verifying a message normally certificates (if any) included in
-the message are searched for the signing certificate. With this option
-only the certificates specified in the B<-certfile> option are used.
-The supplied certificates can still be used as untrusted CAs however.
-
-=item B<-noverify>
-
-Do not verify the signers certificate of a signed message.
-
-=item B<-nochain>
-
-Do not do chain verification of signers certificates: that is don't
-use the certificates in the signed message as untrusted CAs.
-
-=item B<-nosigs>
-
-Don't try to verify the signatures on the message.
-
-=item B<-nocerts>
-
-When signing a message the signer's certificate is normally included
-with this option it is excluded. This will reduce the size of the
-signed message but the verifier must have a copy of the signers certificate
-available locally (passed using the B<-certfile> option for example).
-
-=item B<-noattr>
-
-Normally when a message is signed a set of attributes are included which
-include the signing time and supported symmetric algorithms. With this
-option they are not included.
-
-=item B<-binary>
-
-Normally the input message is converted to "canonical" format which is
-effectively using CR and LF as end of line: as required by the S/MIME
-specification. When this option is present no translation occurs. This
-is useful when handling binary data which may not be in MIME format.
-
-=item B<-crlfeol>
-
-Normally the output file uses a single B<LF> as end of line. When this
-option is present B<CRLF> is used instead.
-
-=item B<-nodetach>
-
-When signing a message use opaque signing: this form is more resistant
-to translation by mail relays but it cannot be read by mail agents that
-do not support S/MIME. Without this option cleartext signing with
-the MIME type multipart/signed is used.
-
-=item B<-certfile file>
-
-Allows additional certificates to be specified. When signing these will
-be included with the message. When verifying these will be searched for
-the signers certificates. The certificates should be in PEM format.
-
-=item B<-signer file>
-
-A signing certificate when signing or resigning a message, this option can be
-used multiple times if more than one signer is required. If a message is being
-verified then the signers certificates will be written to this file if the
-verification was successful.
-
-=item B<-recip file>
-
-The recipients certificate when decrypting a message. This certificate
-must match one of the recipients of the message or an error occurs.
-
-=item B<-inkey file_or_id>
-
-The private key to use when signing or decrypting. This must match the
-corresponding certificate. If this option is not specified then the
-private key must be included in the certificate file specified with
-the B<-recip> or B<-signer> file. When signing this option can be used
-multiple times to specify successive keys.
-If no engine is used, the argument is taken as a file; if an engine is
-specified, the argument is given to the engine as a key identifier.
-
-=item B<-passin arg>
-
-The private key password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<cert.pem...>
-
-One or more certificates of message recipients: used when encrypting
-a message.
-
-=item B<-to, -from, -subject>
-
-The relevant mail headers. These are included outside the signed
-portion of a message so they may be included manually. If signing
-then many S/MIME mail clients check the signers certificate's email
-address matches that specified in the From: address.
-
-=item B<-attime>, B<-check_ss_sig>, B<-crl_check>, B<-crl_check_all>,
-B<-explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,
-B<-inhibit_map>, B<-no_alt_chains>, B<-partial_chain>, B<-policy>,
-B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,
-B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,
-B<-auth_level>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
-B<-verify_ip>, B<-verify_name>, B<-x509_strict>
-
-Set various options of certificate chain verification. See
-L<verify(1)> manual page for details.
-
-=back
-
-=head1 NOTES
-
-The MIME message must be sent without any blank lines between the
-headers and the output. Some mail programs will automatically add
-a blank line. Piping the mail directly to sendmail is one way to
-achieve the correct format.
-
-The supplied message to be signed or encrypted must include the
-necessary MIME headers or many S/MIME clients won't display it
-properly (if at all). You can use the B<-text> option to automatically
-add plain text headers.
-
-A "signed and encrypted" message is one where a signed message is
-then encrypted. This can be produced by encrypting an already signed
-message: see the examples section.
-
-This version of the program only allows one signer per message but it
-will verify multiple signers on received messages. Some S/MIME clients
-choke if a message contains multiple signers. It is possible to sign
-messages "in parallel" by signing an already signed message.
-
-The options B<-encrypt> and B<-decrypt> reflect common usage in S/MIME
-clients. Strictly speaking these process PKCS#7 enveloped data: PKCS#7
-encrypted data is used for other purposes.
-
-The B<-resign> option uses an existing message digest when adding a new
-signer. This means that attributes must be present in at least one existing
-signer using the same message digest or this operation will fail.
-
-The B<-stream> and B<-indef> options enable streaming I/O support.
-As a result the encoding is BER using indefinite length constructed encoding
-and no longer DER. Streaming is supported for the B<-encrypt> operation and the
-B<-sign> operation if the content is not detached.
-
-Streaming is always used for the B<-sign> operation with detached data but
-since the content is no longer part of the PKCS#7 structure the encoding
-remains DER.
-
-=head1 EXIT CODES
-
-=over 4
-
-=item Z<>0
-
-The operation was completely successfully.
-
-=item Z<>1
-
-An error occurred parsing the command options.
-
-=item Z<>2
-
-One of the input files could not be read.
-
-=item Z<>3
-
-An error occurred creating the PKCS#7 file or when reading the MIME
-message.
-
-=item Z<>4
-
-An error occurred decrypting or verifying the message.
-
-=item Z<>5
-
-The message was verified correctly but an error occurred writing out
-the signers certificates.
-
-=back
-
-=head1 EXAMPLES
-
-Create a cleartext signed message:
-
- openssl smime -sign -in message.txt -text -out mail.msg \
- -signer mycert.pem
-
-Create an opaque signed message:
-
- openssl smime -sign -in message.txt -text -out mail.msg -nodetach \
- -signer mycert.pem
-
-Create a signed message, include some additional certificates and
-read the private key from another file:
-
- openssl smime -sign -in in.txt -text -out mail.msg \
- -signer mycert.pem -inkey mykey.pem -certfile mycerts.pem
-
-Create a signed message with two signers:
-
- openssl smime -sign -in message.txt -text -out mail.msg \
- -signer mycert.pem -signer othercert.pem
-
-Send a signed message under Unix directly to sendmail, including headers:
-
- openssl smime -sign -in in.txt -text -signer mycert.pem \
- -from steve@openssl.org -to someone@somewhere \
- -subject "Signed message" | sendmail someone@somewhere
-
-Verify a message and extract the signer's certificate if successful:
-
- openssl smime -verify -in mail.msg -signer user.pem -out signedtext.txt
-
-Send encrypted mail using triple DES:
-
- openssl smime -encrypt -in in.txt -from steve@openssl.org \
- -to someone@somewhere -subject "Encrypted message" \
- -des3 user.pem -out mail.msg
-
-Sign and encrypt mail:
-
- openssl smime -sign -in ml.txt -signer my.pem -text \
- | openssl smime -encrypt -out mail.msg \
- -from steve@openssl.org -to someone@somewhere \
- -subject "Signed and Encrypted message" -des3 user.pem
-
-Note: the encryption command does not include the B<-text> option because the
-message being encrypted already has MIME headers.
-
-Decrypt mail:
-
- openssl smime -decrypt -in mail.msg -recip mycert.pem -inkey key.pem
-
-The output from Netscape form signing is a PKCS#7 structure with the
-detached signature format. You can use this program to verify the
-signature by line wrapping the base64 encoded structure and surrounding
-it with:
-
- -----BEGIN PKCS7-----
- -----END PKCS7-----
-
-and using the command:
-
- openssl smime -verify -inform PEM -in signature.pem -content content.txt
-
-Alternatively you can base64 decode the signature and use:
-
- openssl smime -verify -inform DER -in signature.der -content content.txt
-
-Create an encrypted message using 128 bit Camellia:
-
- openssl smime -encrypt -in plain.txt -camellia128 -out mail.msg cert.pem
-
-Add a signer to an existing message:
-
- openssl smime -resign -in mail.msg -signer newsign.pem -out mail2.msg
-
-=head1 BUGS
-
-The MIME parser isn't very clever: it seems to handle most messages that I've
-thrown at it but it may choke on others.
-
-The code currently will only write out the signer's certificate to a file: if
-the signer has a separate encryption certificate this must be manually
-extracted. There should be some heuristic that determines the correct
-encryption certificate.
-
-Ideally a database should be maintained of a certificates for each email
-address.
-
-The code doesn't currently take note of the permitted symmetric encryption
-algorithms as supplied in the SMIMECapabilities signed attribute. This means the
-user has to manually include the correct encryption algorithm. It should store
-the list of permitted ciphers in a database and only use those.
-
-No revocation checking is done on the signer's certificate.
-
-The current code can only handle S/MIME v2 messages, the more complex S/MIME v3
-structures may cause parsing errors.
-
-=head1 HISTORY
-
-The use of multiple B<-signer> options and the B<-resign> command were first
-added in OpenSSL 1.0.0
-
-The -no_alt_chains option was added in OpenSSL 1.1.0.
-
-=head1 COPYRIGHT
-
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/speed.pod b/doc/man1/speed.pod
deleted file mode 100644
index 523da0d3b182..000000000000
--- a/doc/man1/speed.pod
+++ /dev/null
@@ -1,104 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-speed,
-speed - test library performance
-
-=head1 SYNOPSIS
-
-B<openssl speed>
-[B<-help>]
-[B<-engine id>]
-[B<-elapsed>]
-[B<-evp algo>]
-[B<-decrypt>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-primes num>]
-[B<-seconds num>]
-[B<-bytes num>]
-[B<algorithm...>]
-
-=head1 DESCRIPTION
-
-This command is used to test the performance of cryptographic algorithms.
-To see the list of supported algorithms, use the I<list --digest-commands>
-or I<list --cipher-commands> command. The global CSPRNG is denoted by
-the I<rand> algorithm name.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<speed>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=item B<-elapsed>
-
-When calculating operations- or bytes-per-second, use wall-clock time
-instead of CPU user time as divisor. It can be useful when testing speed
-of hardware engines.
-
-=item B<-evp algo>
-
-Use the specified cipher or message digest algorithm via the EVP interface.
-If B<algo> is an AEAD cipher, then you can pass <-aead> to benchmark a
-TLS-like sequence. And if B<algo> is a multi-buffer capable cipher, e.g.
-aes-128-cbc-hmac-sha1, then B<-mb> will time multi-buffer operation.
-
-=item B<-decrypt>
-
-Time the decryption instead of encryption. Affects only the EVP testing.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<-primes num>
-
-Generate a B<num>-prime RSA key and use it to run the benchmarks. This option
-is only effective if RSA algorithm is specified to test.
-
-=item B<-seconds num>
-
-Run benchmarks for B<num> seconds.
-
-=item B<-bytes num>
-
-Run benchmarks on B<num>-byte buffers. Affects ciphers, digests and the CSPRNG.
-
-=item B<[zero or more test algorithms]>
-
-If any options are given, B<speed> tests those algorithms, otherwise a
-pre-compiled grand selection is tested.
-
-=back
-
-=head1 COPYRIGHT
-
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/spkac.pod b/doc/man1/spkac.pod
deleted file mode 100644
index 87e1b4bbcaa8..000000000000
--- a/doc/man1/spkac.pod
+++ /dev/null
@@ -1,155 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-spkac,
-spkac - SPKAC printing and generating utility
-
-=head1 SYNOPSIS
-
-B<openssl> B<spkac>
-[B<-help>]
-[B<-in filename>]
-[B<-out filename>]
-[B<-key keyfile>]
-[B<-keyform PEM|DER|ENGINE>]
-[B<-passin arg>]
-[B<-challenge string>]
-[B<-pubkey>]
-[B<-spkac spkacname>]
-[B<-spksect section>]
-[B<-noout>]
-[B<-verify>]
-[B<-engine id>]
-
-=head1 DESCRIPTION
-
-The B<spkac> command processes Netscape signed public key and challenge
-(SPKAC) files. It can print out their contents, verify the signature and
-produce its own SPKACs from a supplied private key.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-in filename>
-
-This specifies the input filename to read from or standard input if this
-option is not specified. Ignored if the B<-key> option is used.
-
-=item B<-out filename>
-
-Specifies the output filename to write to or standard output by
-default.
-
-=item B<-key keyfile>
-
-Create an SPKAC file using the private key in B<keyfile>. The
-B<-in>, B<-noout>, B<-spksect> and B<-verify> options are ignored if
-present.
-
-=item B<-keyform PEM|DER|ENGINE>
-
-Whether the key format is PEM, DER, or an engine-backed key.
-The default is PEM.
-
-=item B<-passin password>
-
-The input file password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-challenge string>
-
-Specifies the challenge string if an SPKAC is being created.
-
-=item B<-spkac spkacname>
-
-Allows an alternative name form the variable containing the
-SPKAC. The default is "SPKAC". This option affects both
-generated and input SPKAC files.
-
-=item B<-spksect section>
-
-Allows an alternative name form the section containing the
-SPKAC. The default is the default section.
-
-=item B<-noout>
-
-Don't output the text version of the SPKAC (not used if an
-SPKAC is being created).
-
-=item B<-pubkey>
-
-Output the public key of an SPKAC (not used if an SPKAC is
-being created).
-
-=item B<-verify>
-
-Verifies the digital signature on the supplied SPKAC.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<spkac>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=back
-
-=head1 EXAMPLES
-
-Print out the contents of an SPKAC:
-
- openssl spkac -in spkac.cnf
-
-Verify the signature of an SPKAC:
-
- openssl spkac -in spkac.cnf -noout -verify
-
-Create an SPKAC using the challenge string "hello":
-
- openssl spkac -key key.pem -challenge hello -out spkac.cnf
-
-Example of an SPKAC, (long lines split up for clarity):
-
- SPKAC=MIG5MGUwXDANBgkqhkiG9w0BAQEFAANLADBIAkEA\
- 1cCoq2Wa3Ixs47uI7FPVwHVIPDx5yso105Y6zpozam135a\
- 8R0CpoRvkkigIyXfcCjiVi5oWk+6FfPaD03uPFoQIDAQAB\
- FgVoZWxsbzANBgkqhkiG9w0BAQQFAANBAFpQtY/FojdwkJ\
- h1bEIYuc2EeM2KHTWPEepWYeawvHD0gQ3DngSC75YCWnnD\
- dq+NQ3F+X4deMx9AaEglZtULwV4=
-
-=head1 NOTES
-
-A created SPKAC with suitable DN components appended can be fed into
-the B<ca> utility.
-
-SPKACs are typically generated by Netscape when a form is submitted
-containing the B<KEYGEN> tag as part of the certificate enrollment
-process.
-
-The challenge string permits a primitive form of proof of possession
-of private key. By checking the SPKAC signature and a random challenge
-string some guarantee is given that the user knows the private key
-corresponding to the public key being certified. This is important in
-some applications. Without this it is possible for a previous SPKAC
-to be used in a "replay attack".
-
-=head1 SEE ALSO
-
-L<ca(1)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/srp.pod b/doc/man1/srp.pod
deleted file mode 100644
index e858a2226017..000000000000
--- a/doc/man1/srp.pod
+++ /dev/null
@@ -1,73 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-srp,
-srp - maintain SRP password file
-
-=head1 SYNOPSIS
-
-B<openssl srp>
-[B<-help>]
-[B<-verbose>]
-[B<-add>]
-[B<-modify>]
-[B<-delete>]
-[B<-list>]
-[B<-name section>]
-[B<-config file>]
-[B<-srpvfile file>]
-[B<-gn identifier>]
-[B<-userinfo text...>]
-[B<-passin arg>]
-[B<-passout arg>]
-[I<user...>]
-
-=head1 DESCRIPTION
-
-The B<srp> command is user to maintain an SRP (secure remote password)
-file.
-At most one of the B<-add>, B<-modify>, B<-delete>, and B<-list> options
-can be specified.
-These options take zero or more usernames as parameters and perform the
-appropriate operation on the SRP file.
-For B<-list>, if no B<user> is given then all users are displayed.
-
-The configuration file to use, and the section within the file, can be
-specified with the B<-config> and B<-name> flags, respectively.
-If the config file is not specified, the B<-srpvfile> can be used to
-just specify the file to operate on.
-
-The B<-userinfo> option specifies additional information to add when
-adding or modifying a user.
-
-The B<-gn> flag specifies the B<g> and B<N> values, using one of
-the strengths defined in IETF RFC 5054.
-
-The B<-passin> and B<-passout> arguments are parsed as described in
-the L<openssl(1)> command.
-
-=head1 OPTIONS
-
-=over 4
-
-=item [B<-help>]
-
-Display an option summary.
-
-=item [B<-verbose>]
-
-Generate verbose output while processing.
-
-=back
-
-=head1 COPYRIGHT
-
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/storeutl.pod b/doc/man1/storeutl.pod
deleted file mode 100644
index 3d2cb60bdc13..000000000000
--- a/doc/man1/storeutl.pod
+++ /dev/null
@@ -1,133 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-storeutl,
-storeutl - STORE utility
-
-=head1 SYNOPSIS
-
-B<openssl> B<storeutl>
-[B<-help>]
-[B<-out file>]
-[B<-noout>]
-[B<-passin arg>]
-[B<-text arg>]
-[B<-engine id>]
-[B<-r>]
-[B<-certs>]
-[B<-keys>]
-[B<-crls>]
-[B<-subject arg>]
-[B<-issuer arg>]
-[B<-serial arg>]
-[B<-alias arg>]
-[B<-fingerprint arg>]
-[B<-I<digest>>]
-B<uri> ...
-
-=head1 DESCRIPTION
-
-The B<storeutl> command can be used to display the contents (after decryption
-as the case may be) fetched from the given URIs.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-out filename>
-
-specifies the output filename to write to or standard output by
-default.
-
-=item B<-noout>
-
-this option prevents output of the PEM data.
-
-=item B<-passin arg>
-
-the key password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-text>
-
-Prints out the objects in text form, similarly to the B<-text> output from
-B<openssl x509>, B<openssl pkey>, etc.
-
-=item B<-engine id>
-
-specifying an engine (by its unique B<id> string) will cause B<storeutl>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed.
-The engine will then be set as the default for all available algorithms.
-
-=item B<-r>
-
-Fetch objects recursively when possible.
-
-=item B<-certs>
-
-=item B<-keys>
-
-=item B<-crls>
-
-Only select the certificates, keys or CRLs from the given URI.
-However, if this URI would return a set of names (URIs), those are always
-returned.
-
-=item B<-subject arg>
-
-Search for an object having the subject name B<arg>.
-The arg must be formatted as I</type0=value0/type1=value1/type2=...>.
-Keyword characters may be escaped by \ (backslash), and whitespace is retained.
-Empty values are permitted but are ignored for the search. That is,
-a search with an empty value will have the same effect as not specifying
-the type at all.
-
-=item B<-issuer arg>
-
-=item B<-serial arg>
-
-Search for an object having the given issuer name and serial number.
-These two options I<must> be used together.
-The issuer arg must be formatted as I</type0=value0/type1=value1/type2=...>,
-characters may be escaped by \ (backslash), no spaces are skipped.
-The serial arg may be specified as a decimal value or a hex value if preceded
-by B<0x>.
-
-=item B<-alias arg>
-
-Search for an object having the given alias.
-
-=item B<-fingerprint arg>
-
-Search for an object having the given fingerprint.
-
-=item B<-I<digest>>
-
-The digest that was used to compute the fingerprint given with B<-fingerprint>.
-
-=back
-
-=head1 SEE ALSO
-
-L<openssl(1)>
-
-=head1 HISTORY
-
-The B<openssl> B<storeutl> app was added in OpenSSL 1.1.1.
-
-=head1 COPYRIGHT
-
-Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/ts.pod b/doc/man1/ts.pod
deleted file mode 100644
index 9e1ffd5d083d..000000000000
--- a/doc/man1/ts.pod
+++ /dev/null
@@ -1,675 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-ts,
-ts - Time Stamping Authority tool (client/server)
-
-=head1 SYNOPSIS
-
-B<openssl> B<ts>
-B<-query>
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-config> configfile]
-[B<-data> file_to_hash]
-[B<-digest> digest_bytes]
-[B<-I<digest>>]
-[B<-tspolicy> object_id]
-[B<-no_nonce>]
-[B<-cert>]
-[B<-in> request.tsq]
-[B<-out> request.tsq]
-[B<-text>]
-
-B<openssl> B<ts>
-B<-reply>
-[B<-config> configfile]
-[B<-section> tsa_section]
-[B<-queryfile> request.tsq]
-[B<-passin> password_src]
-[B<-signer> tsa_cert.pem]
-[B<-inkey> file_or_id]
-[B<-I<digest>>]
-[B<-chain> certs_file.pem]
-[B<-tspolicy> object_id]
-[B<-in> response.tsr]
-[B<-token_in>]
-[B<-out> response.tsr]
-[B<-token_out>]
-[B<-text>]
-[B<-engine> id]
-
-B<openssl> B<ts>
-B<-verify>
-[B<-data> file_to_hash]
-[B<-digest> digest_bytes]
-[B<-queryfile> request.tsq]
-[B<-in> response.tsr]
-[B<-token_in>]
-[B<-CApath> trusted_cert_path]
-[B<-CAfile> trusted_certs.pem]
-[B<-untrusted> cert_file.pem]
-[I<verify options>]
-
-I<verify options:>
-[-attime timestamp]
-[-check_ss_sig]
-[-crl_check]
-[-crl_check_all]
-[-explicit_policy]
-[-extended_crl]
-[-ignore_critical]
-[-inhibit_any]
-[-inhibit_map]
-[-issuer_checks]
-[-no_alt_chains]
-[-no_check_time]
-[-partial_chain]
-[-policy arg]
-[-policy_check]
-[-policy_print]
-[-purpose purpose]
-[-suiteB_128]
-[-suiteB_128_only]
-[-suiteB_192]
-[-trusted_first]
-[-use_deltas]
-[-auth_level num]
-[-verify_depth num]
-[-verify_email email]
-[-verify_hostname hostname]
-[-verify_ip ip]
-[-verify_name name]
-[-x509_strict]
-
-=head1 DESCRIPTION
-
-The B<ts> command is a basic Time Stamping Authority (TSA) client and server
-application as specified in RFC 3161 (Time-Stamp Protocol, TSP). A
-TSA can be part of a PKI deployment and its role is to provide long
-term proof of the existence of a certain datum before a particular
-time. Here is a brief description of the protocol:
-
-=over 4
-
-=item 1.
-
-The TSA client computes a one-way hash value for a data file and sends
-the hash to the TSA.
-
-=item 2.
-
-The TSA attaches the current date and time to the received hash value,
-signs them and sends the timestamp token back to the client. By
-creating this token the TSA certifies the existence of the original
-data file at the time of response generation.
-
-=item 3.
-
-The TSA client receives the timestamp token and verifies the
-signature on it. It also checks if the token contains the same hash
-value that it had sent to the TSA.
-
-=back
-
-There is one DER encoded protocol data unit defined for transporting
-a timestamp request to the TSA and one for sending the timestamp response
-back to the client. The B<ts> command has three main functions:
-creating a timestamp request based on a data file,
-creating a timestamp response based on a request, verifying if a
-response corresponds to a particular request or a data file.
-
-There is no support for sending the requests/responses automatically
-over HTTP or TCP yet as suggested in RFC 3161. The users must send the
-requests either by ftp or e-mail.
-
-=head1 OPTIONS
-
-=head2 Time Stamp Request generation
-
-The B<-query> switch can be used for creating and printing a timestamp
-request with the following options:
-
-=over 4
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<-config> configfile
-
-The configuration file to use.
-Optional; for a description of the default value,
-see L<openssl(1)/COMMAND SUMMARY>.
-
-=item B<-data> file_to_hash
-
-The data file for which the timestamp request needs to be
-created. stdin is the default if neither the B<-data> nor the B<-digest>
-parameter is specified. (Optional)
-
-=item B<-digest> digest_bytes
-
-It is possible to specify the message imprint explicitly without the data
-file. The imprint must be specified in a hexadecimal format, two characters
-per byte, the bytes optionally separated by colons (e.g. 1A:F6:01:... or
-1AF601...). The number of bytes must match the message digest algorithm
-in use. (Optional)
-
-=item B<-I<digest>>
-
-The message digest to apply to the data file.
-Any digest supported by the OpenSSL B<dgst> command can be used.
-The default is SHA-1. (Optional)
-
-=item B<-tspolicy> object_id
-
-The policy that the client expects the TSA to use for creating the
-timestamp token. Either the dotted OID notation or OID names defined
-in the config file can be used. If no policy is requested the TSA will
-use its own default policy. (Optional)
-
-=item B<-no_nonce>
-
-No nonce is specified in the request if this option is
-given. Otherwise a 64 bit long pseudo-random none is
-included in the request. It is recommended to use nonce to
-protect against replay-attacks. (Optional)
-
-=item B<-cert>
-
-The TSA is expected to include its signing certificate in the
-response. (Optional)
-
-=item B<-in> request.tsq
-
-This option specifies a previously created timestamp request in DER
-format that will be printed into the output file. Useful when you need
-to examine the content of a request in human-readable
-format. (Optional)
-
-=item B<-out> request.tsq
-
-Name of the output file to which the request will be written. Default
-is stdout. (Optional)
-
-=item B<-text>
-
-If this option is specified the output is human-readable text format
-instead of DER. (Optional)
-
-=back
-
-=head2 Time Stamp Response generation
-
-A timestamp response (TimeStampResp) consists of a response status
-and the timestamp token itself (ContentInfo), if the token generation was
-successful. The B<-reply> command is for creating a timestamp
-response or timestamp token based on a request and printing the
-response/token in human-readable format. If B<-token_out> is not
-specified the output is always a timestamp response (TimeStampResp),
-otherwise it is a timestamp token (ContentInfo).
-
-=over 4
-
-=item B<-config> configfile
-
-The configuration file to use.
-Optional; for a description of the default value,
-see L<openssl(1)/COMMAND SUMMARY>.
-See B<CONFIGURATION FILE OPTIONS> for configurable variables.
-
-=item B<-section> tsa_section
-
-The name of the config file section containing the settings for the
-response generation. If not specified the default TSA section is
-used, see B<CONFIGURATION FILE OPTIONS> for details. (Optional)
-
-=item B<-queryfile> request.tsq
-
-The name of the file containing a DER encoded timestamp request. (Optional)
-
-=item B<-passin> password_src
-
-Specifies the password source for the private key of the TSA. See
-L<openssl(1)/Pass Phrase Options>. (Optional)
-
-=item B<-signer> tsa_cert.pem
-
-The signer certificate of the TSA in PEM format. The TSA signing
-certificate must have exactly one extended key usage assigned to it:
-timeStamping. The extended key usage must also be critical, otherwise
-the certificate is going to be refused. Overrides the B<signer_cert>
-variable of the config file. (Optional)
-
-=item B<-inkey> file_or_id
-
-The signer private key of the TSA in PEM format. Overrides the
-B<signer_key> config file option. (Optional)
-If no engine is used, the argument is taken as a file; if an engine is
-specified, the argument is given to the engine as a key identifier.
-
-=item B<-I<digest>>
-
-Signing digest to use. Overrides the B<signer_digest> config file
-option. (Mandatory unless specified in the config file)
-
-=item B<-chain> certs_file.pem
-
-The collection of certificates in PEM format that will all
-be included in the response in addition to the signer certificate if
-the B<-cert> option was used for the request. This file is supposed to
-contain the certificate chain for the signer certificate from its
-issuer upwards. The B<-reply> command does not build a certificate
-chain automatically. (Optional)
-
-=item B<-tspolicy> object_id
-
-The default policy to use for the response unless the client
-explicitly requires a particular TSA policy. The OID can be specified
-either in dotted notation or with its name. Overrides the
-B<default_policy> config file option. (Optional)
-
-=item B<-in> response.tsr
-
-Specifies a previously created timestamp response or timestamp token
-(if B<-token_in> is also specified) in DER format that will be written
-to the output file. This option does not require a request, it is
-useful e.g. when you need to examine the content of a response or
-token or you want to extract the timestamp token from a response. If
-the input is a token and the output is a timestamp response a default
-'granted' status info is added to the token. (Optional)
-
-=item B<-token_in>
-
-This flag can be used together with the B<-in> option and indicates
-that the input is a DER encoded timestamp token (ContentInfo) instead
-of a timestamp response (TimeStampResp). (Optional)
-
-=item B<-out> response.tsr
-
-The response is written to this file. The format and content of the
-file depends on other options (see B<-text>, B<-token_out>). The default is
-stdout. (Optional)
-
-=item B<-token_out>
-
-The output is a timestamp token (ContentInfo) instead of timestamp
-response (TimeStampResp). (Optional)
-
-=item B<-text>
-
-If this option is specified the output is human-readable text format
-instead of DER. (Optional)
-
-=item B<-engine> id
-
-Specifying an engine (by its unique B<id> string) will cause B<ts>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms. Default is builtin. (Optional)
-
-=back
-
-=head2 Time Stamp Response verification
-
-The B<-verify> command is for verifying if a timestamp response or
-timestamp token is valid and matches a particular timestamp request or
-data file. The B<-verify> command does not use the configuration file.
-
-=over 4
-
-=item B<-data> file_to_hash
-
-The response or token must be verified against file_to_hash. The file
-is hashed with the message digest algorithm specified in the token.
-The B<-digest> and B<-queryfile> options must not be specified with this one.
-(Optional)
-
-=item B<-digest> digest_bytes
-
-The response or token must be verified against the message digest specified
-with this option. The number of bytes must match the message digest algorithm
-specified in the token. The B<-data> and B<-queryfile> options must not be
-specified with this one. (Optional)
-
-=item B<-queryfile> request.tsq
-
-The original timestamp request in DER format. The B<-data> and B<-digest>
-options must not be specified with this one. (Optional)
-
-=item B<-in> response.tsr
-
-The timestamp response that needs to be verified in DER format. (Mandatory)
-
-=item B<-token_in>
-
-This flag can be used together with the B<-in> option and indicates
-that the input is a DER encoded timestamp token (ContentInfo) instead
-of a timestamp response (TimeStampResp). (Optional)
-
-=item B<-CApath> trusted_cert_path
-
-The name of the directory containing the trusted CA certificates of the
-client. See the similar option of L<verify(1)> for additional
-details. Either this option or B<-CAfile> must be specified. (Optional)
-
-
-=item B<-CAfile> trusted_certs.pem
-
-The name of the file containing a set of trusted self-signed CA
-certificates in PEM format. See the similar option of
-L<verify(1)> for additional details. Either this option
-or B<-CApath> must be specified.
-(Optional)
-
-=item B<-untrusted> cert_file.pem
-
-Set of additional untrusted certificates in PEM format which may be
-needed when building the certificate chain for the TSA's signing
-certificate. This file must contain the TSA signing certificate and
-all intermediate CA certificates unless the response includes them.
-(Optional)
-
-=item I<verify options>
-
-The options B<-attime timestamp>, B<-check_ss_sig>, B<-crl_check>,
-B<-crl_check_all>, B<-explicit_policy>, B<-extended_crl>, B<-ignore_critical>,
-B<-inhibit_any>, B<-inhibit_map>, B<-issuer_checks>, B<-no_alt_chains>,
-B<-no_check_time>, B<-partial_chain>, B<-policy>, B<-policy_check>,
-B<-policy_print>, B<-purpose>, B<-suiteB_128>, B<-suiteB_128_only>,
-B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>, B<-auth_level>,
-B<-verify_depth>, B<-verify_email>, B<-verify_hostname>, B<-verify_ip>,
-B<-verify_name>, and B<-x509_strict> can be used to control timestamp
-verification. See L<verify(1)>.
-
-=back
-
-=head1 CONFIGURATION FILE OPTIONS
-
-The B<-query> and B<-reply> commands make use of a configuration file.
-See L<config(5)>
-for a general description of the syntax of the config file. The
-B<-query> command uses only the symbolic OID names section
-and it can work without it. However, the B<-reply> command needs the
-config file for its operation.
-
-When there is a command line switch equivalent of a variable the
-switch always overrides the settings in the config file.
-
-=over 4
-
-=item B<tsa> section, B<default_tsa>
-
-This is the main section and it specifies the name of another section
-that contains all the options for the B<-reply> command. This default
-section can be overridden with the B<-section> command line switch. (Optional)
-
-=item B<oid_file>
-
-See L<ca(1)> for description. (Optional)
-
-=item B<oid_section>
-
-See L<ca(1)> for description. (Optional)
-
-=item B<RANDFILE>
-
-See L<ca(1)> for description. (Optional)
-
-=item B<serial>
-
-The name of the file containing the hexadecimal serial number of the
-last timestamp response created. This number is incremented by 1 for
-each response. If the file does not exist at the time of response
-generation a new file is created with serial number 1. (Mandatory)
-
-=item B<crypto_device>
-
-Specifies the OpenSSL engine that will be set as the default for
-all available algorithms. The default value is builtin, you can specify
-any other engines supported by OpenSSL (e.g. use chil for the NCipher HSM).
-(Optional)
-
-=item B<signer_cert>
-
-TSA signing certificate in PEM format. The same as the B<-signer>
-command line option. (Optional)
-
-=item B<certs>
-
-A file containing a set of PEM encoded certificates that need to be
-included in the response. The same as the B<-chain> command line
-option. (Optional)
-
-=item B<signer_key>
-
-The private key of the TSA in PEM format. The same as the B<-inkey>
-command line option. (Optional)
-
-=item B<signer_digest>
-
-Signing digest to use. The same as the
-B<-I<digest>> command line option. (Mandatory unless specified on the command
-line)
-
-=item B<default_policy>
-
-The default policy to use when the request does not mandate any
-policy. The same as the B<-tspolicy> command line option. (Optional)
-
-=item B<other_policies>
-
-Comma separated list of policies that are also acceptable by the TSA
-and used only if the request explicitly specifies one of them. (Optional)
-
-=item B<digests>
-
-The list of message digest algorithms that the TSA accepts. At least
-one algorithm must be specified. (Mandatory)
-
-=item B<accuracy>
-
-The accuracy of the time source of the TSA in seconds, milliseconds
-and microseconds. E.g. secs:1, millisecs:500, microsecs:100. If any of
-the components is missing zero is assumed for that field. (Optional)
-
-=item B<clock_precision_digits>
-
-Specifies the maximum number of digits, which represent the fraction of
-seconds, that need to be included in the time field. The trailing zeros
-must be removed from the time, so there might actually be fewer digits,
-or no fraction of seconds at all. Supported only on UNIX platforms.
-The maximum value is 6, default is 0.
-(Optional)
-
-=item B<ordering>
-
-If this option is yes the responses generated by this TSA can always
-be ordered, even if the time difference between two responses is less
-than the sum of their accuracies. Default is no. (Optional)
-
-=item B<tsa_name>
-
-Set this option to yes if the subject name of the TSA must be included in
-the TSA name field of the response. Default is no. (Optional)
-
-=item B<ess_cert_id_chain>
-
-The SignedData objects created by the TSA always contain the
-certificate identifier of the signing certificate in a signed
-attribute (see RFC 2634, Enhanced Security Services). If this option
-is set to yes and either the B<certs> variable or the B<-chain> option
-is specified then the certificate identifiers of the chain will also
-be included in the SigningCertificate signed attribute. If this
-variable is set to no, only the signing certificate identifier is
-included. Default is no. (Optional)
-
-=item B<ess_cert_id_alg>
-
-This option specifies the hash function to be used to calculate the TSA's
-public key certificate identifier. Default is sha1. (Optional)
-
-=back
-
-=head1 EXAMPLES
-
-All the examples below presume that B<OPENSSL_CONF> is set to a proper
-configuration file, e.g. the example configuration file
-openssl/apps/openssl.cnf will do.
-
-=head2 Time Stamp Request
-
-To create a timestamp request for design1.txt with SHA-1
-without nonce and policy and no certificate is required in the response:
-
- openssl ts -query -data design1.txt -no_nonce \
- -out design1.tsq
-
-To create a similar timestamp request with specifying the message imprint
-explicitly:
-
- openssl ts -query -digest b7e5d3f93198b38379852f2c04e78d73abdd0f4b \
- -no_nonce -out design1.tsq
-
-To print the content of the previous request in human readable format:
-
- openssl ts -query -in design1.tsq -text
-
-To create a timestamp request which includes the MD-5 digest
-of design2.txt, requests the signer certificate and nonce,
-specifies a policy id (assuming the tsa_policy1 name is defined in the
-OID section of the config file):
-
- openssl ts -query -data design2.txt -md5 \
- -tspolicy tsa_policy1 -cert -out design2.tsq
-
-=head2 Time Stamp Response
-
-Before generating a response a signing certificate must be created for
-the TSA that contains the B<timeStamping> critical extended key usage extension
-without any other key usage extensions. You can add this line to the
-user certificate section of the config file to generate a proper certificate;
-
- extendedKeyUsage = critical,timeStamping
-
-See L<req(1)>, L<ca(1)>, and L<x509(1)> for instructions. The examples
-below assume that cacert.pem contains the certificate of the CA,
-tsacert.pem is the signing certificate issued by cacert.pem and
-tsakey.pem is the private key of the TSA.
-
-To create a timestamp response for a request:
-
- openssl ts -reply -queryfile design1.tsq -inkey tsakey.pem \
- -signer tsacert.pem -out design1.tsr
-
-If you want to use the settings in the config file you could just write:
-
- openssl ts -reply -queryfile design1.tsq -out design1.tsr
-
-To print a timestamp reply to stdout in human readable format:
-
- openssl ts -reply -in design1.tsr -text
-
-To create a timestamp token instead of timestamp response:
-
- openssl ts -reply -queryfile design1.tsq -out design1_token.der -token_out
-
-To print a timestamp token to stdout in human readable format:
-
- openssl ts -reply -in design1_token.der -token_in -text -token_out
-
-To extract the timestamp token from a response:
-
- openssl ts -reply -in design1.tsr -out design1_token.der -token_out
-
-To add 'granted' status info to a timestamp token thereby creating a
-valid response:
-
- openssl ts -reply -in design1_token.der -token_in -out design1.tsr
-
-=head2 Time Stamp Verification
-
-To verify a timestamp reply against a request:
-
- openssl ts -verify -queryfile design1.tsq -in design1.tsr \
- -CAfile cacert.pem -untrusted tsacert.pem
-
-To verify a timestamp reply that includes the certificate chain:
-
- openssl ts -verify -queryfile design2.tsq -in design2.tsr \
- -CAfile cacert.pem
-
-To verify a timestamp token against the original data file:
- openssl ts -verify -data design2.txt -in design2.tsr \
- -CAfile cacert.pem
-
-To verify a timestamp token against a message imprint:
- openssl ts -verify -digest b7e5d3f93198b38379852f2c04e78d73abdd0f4b \
- -in design2.tsr -CAfile cacert.pem
-
-You could also look at the 'test' directory for more examples.
-
-=head1 BUGS
-
-=for comment foreign manuals: procmail(1), perl(1)
-
-=over 2
-
-=item *
-
-No support for timestamps over SMTP, though it is quite easy
-to implement an automatic e-mail based TSA with L<procmail(1)>
-and L<perl(1)>. HTTP server support is provided in the form of
-a separate apache module. HTTP client support is provided by
-L<tsget(1)>. Pure TCP/IP protocol is not supported.
-
-=item *
-
-The file containing the last serial number of the TSA is not
-locked when being read or written. This is a problem if more than one
-instance of L<openssl(1)> is trying to create a timestamp
-response at the same time. This is not an issue when using the apache
-server module, it does proper locking.
-
-=item *
-
-Look for the FIXME word in the source files.
-
-=item *
-
-The source code should really be reviewed by somebody else, too.
-
-=item *
-
-More testing is needed, I have done only some basic tests (see
-test/testtsa).
-
-=back
-
-=head1 SEE ALSO
-
-L<tsget(1)>, L<openssl(1)>, L<req(1)>,
-L<x509(1)>, L<ca(1)>, L<genrsa(1)>,
-L<config(5)>
-
-=head1 COPYRIGHT
-
-Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/tsget.pod b/doc/man1/tsget.pod
index 8fe417f2a06f..66c0ba6299f3 100644
--- a/doc/man1/tsget.pod
+++ b/doc/man1/tsget.pod
@@ -2,37 +2,35 @@
=head1 NAME
-openssl-tsget,
tsget - Time Stamping HTTP/HTTPS client
=head1 SYNOPSIS
B<tsget>
-B<-h> server_url
-[B<-e> extension]
-[B<-o> output]
+B<-h> I<server_url>
+[B<-e> I<extension>]
+[B<-o> I<output>]
[B<-v>]
[B<-d>]
-[B<-k> private_key.pem]
-[B<-p> key_password]
-[B<-c> client_cert.pem]
-[B<-C> CA_certs.pem]
-[B<-P> CA_path]
-[B<-r> file:file...]
-[B<-g> EGD_socket]
-[request]...
+[B<-k> I<private_key.pem>]
+[B<-p> I<key_password>]
+[B<-c> I<client_cert.pem>]
+[B<-C> I<CA_certs.pem>]
+[B<-P> I<CA_path>]
+[B<-r> I<files>]
+[B<-g> I<EGD_socket>]
+[I<request> ...]
=head1 DESCRIPTION
-The B<tsget> command can be used for sending a timestamp request, as
-specified in B<RFC 3161>, to a timestamp server over HTTP or HTTPS and storing
-the timestamp response in a file. This tool cannot be used for creating the
-requests and verifying responses, you can use the OpenSSL B<ts(1)> command to
-do that. B<tsget> can send several requests to the server without closing
-the TCP connection if more than one requests are specified on the command
-line.
+This command can be used for sending a timestamp request, as specified
+in RFC 3161, to a timestamp server over HTTP or HTTPS and storing the
+timestamp response in a file. It cannot be used for creating the requests
+and verifying responses, you have to use L<openssl-ts(1)> to do that. This
+command can send several requests to the server without closing the TCP
+connection if more than one requests are specified on the command line.
-The tool sends the following HTTP request for each timestamp request:
+This command sends the following HTTP request for each timestamp request:
POST url HTTP/1.1
User-Agent: OpenTSA tsget.pl/<version>
@@ -44,24 +42,24 @@ The tool sends the following HTTP request for each timestamp request:
...binary request specified by the user...
-B<tsget> expects a response of type application/timestamp-reply, which is
+It expects a response of type application/timestamp-reply, which is
written to a file without any interpretation.
=head1 OPTIONS
=over 4
-=item B<-h> server_url
+=item B<-h> I<server_url>
The URL of the HTTP/HTTPS server listening for timestamp requests.
-=item B<-e> extension
+=item B<-e> I<extension>
If the B<-o> option is not given this argument specifies the extension of the
output files. The base name of the output file will be the same as those of
-the input files. Default extension is '.tsr'. (Optional)
+the input files. Default extension is F<.tsr>. (Optional)
-=item B<-o> output
+=item B<-o> I<output>
This option can be specified only when just one request is sent to the
server. The timestamp response will be written to the given output file. '-'
@@ -76,57 +74,57 @@ error. (Optional)
=item B<-d>
-Switches on verbose mode for the underlying B<curl> library. You can see
-detailed debug messages for the connection. (Optional)
+=for comment perlpodstyle(1) says to refer to modules without section
-=item B<-k> private_key.pem
+Switches on verbose mode for the underlying perl module L<WWW::Curl::Easy>.
+You can see detailed debug messages for the connection. (Optional)
+
+=item B<-k> I<private_key.pem>
(HTTPS) In case of certificate-based client authentication over HTTPS
-<private_key.pem> must contain the private key of the user. The private key
+I<private_key.pem> must contain the private key of the user. The private key
file can optionally be protected by a passphrase. The B<-c> option must also
be specified. (Optional)
-=item B<-p> key_password
+=item B<-p> I<key_password>
(HTTPS) Specifies the passphrase for the private key specified by the B<-k>
-argument. If this option is omitted and the key is passphrase protected B<tsget>
-will ask for it. (Optional)
+argument. If this option is omitted and the key is passphrase protected,
+it will be prompted for. (Optional)
-=item B<-c> client_cert.pem
+=item B<-c> I<client_cert.pem>
(HTTPS) In case of certificate-based client authentication over HTTPS
-<client_cert.pem> must contain the X.509 certificate of the user. The B<-k>
+I<client_cert.pem> must contain the X.509 certificate of the user. The B<-k>
option must also be specified. If this option is not specified no
certificate-based client authentication will take place. (Optional)
-=item B<-C> CA_certs.pem
+=item B<-C> I<CA_certs.pem>
(HTTPS) The trusted CA certificate store. The certificate chain of the peer's
certificate must include one of the CA certificates specified in this file.
Either option B<-C> or option B<-P> must be given in case of HTTPS. (Optional)
-=item B<-P> CA_path
+=item B<-P> I<CA_path>
(HTTPS) The path containing the trusted CA certificates to verify the peer's
-certificate. The directory must be prepared with the B<c_rehash>
-OpenSSL utility. Either option B<-C> or option B<-P> must be given in case of
-HTTPS. (Optional)
+certificate. The directory must be prepared with L<openssl-rehash(1)>. Either
+option B<-C> or option B<-P> must be given in case of HTTPS. (Optional)
-=item B<-rand> file:file...
+=item B<-r> I<files>
-The files containing random data for seeding the random number
-generator. Multiple files can be specified, the separator is B<;> for
-MS-Windows, B<,> for VMS and B<:> for all other platforms. (Optional)
+See L<openssl(1)/Random State Options> for more information.
-=item B<-g> EGD_socket
+=item B<-g> I<EGD_socket>
The name of an EGD socket to get random data from. (Optional)
-=item [request]...
+=item I<request> ...
-List of files containing B<RFC 3161> DER-encoded timestamp requests. If no
-requests are specified only one request will be sent to the server and it will be
-read from the standard input. (Optional)
+List of files containing RFC 3161 DER-encoded timestamp requests. If no
+requests are specified only one request will be sent to the server and it will
+be read from the standard input.
+(Optional)
=back
@@ -138,37 +136,37 @@ arguments.
=head1 EXAMPLES
-The examples below presume that B<file1.tsq> and B<file2.tsq> contain valid
+The examples below presume that F<file1.tsq> and F<file2.tsq> contain valid
timestamp requests, tsa.opentsa.org listens at port 8080 for HTTP requests
and at port 8443 for HTTPS requests, the TSA service is available at the /tsa
absolute path.
-Get a timestamp response for file1.tsq over HTTP, output is written to
-file1.tsr:
+Get a timestamp response for F<file1.tsq> over HTTP, output is written to
+F<file1.tsr>:
tsget -h http://tsa.opentsa.org:8080/tsa file1.tsq
-Get a timestamp response for file1.tsq and file2.tsq over HTTP showing
-progress, output is written to file1.reply and file2.reply respectively:
+Get a timestamp response for F<file1.tsq> and F<file2.tsq> over HTTP showing
+progress, output is written to F<file1.reply> and F<file2.reply> respectively:
tsget -h http://tsa.opentsa.org:8080/tsa -v -e .reply \
file1.tsq file2.tsq
-Create a timestamp request, write it to file3.tsq, send it to the server and
-write the response to file3.tsr:
+Create a timestamp request, write it to F<file3.tsq>, send it to the server and
+write the response to F<file3.tsr>:
openssl ts -query -data file3.txt -cert | tee file3.tsq \
| tsget -h http://tsa.opentsa.org:8080/tsa \
-o file3.tsr
-Get a timestamp response for file1.tsq over HTTPS without client
+Get a timestamp response for F<file1.tsq> over HTTPS without client
authentication:
tsget -h https://tsa.opentsa.org:8443/tsa \
-C cacerts.pem file1.tsq
-Get a timestamp response for file1.tsq over HTTPS with certificate-based
-client authentication (it will ask for the passphrase if client_key.pem is
+Get a timestamp response for F<file1.tsq> over HTTPS with certificate-based
+client authentication (it will ask for the passphrase if F<client_key.pem> is
protected):
tsget -h https://tsa.opentsa.org:8443/tsa -C cacerts.pem \
@@ -185,16 +183,18 @@ example:
=head1 SEE ALSO
-=for comment foreign manuals: curl(1)
+=for openssl foreign manual WWW::Curl::Easy
-L<openssl(1)>, L<ts(1)>, L<curl(1)>,
-B<RFC 3161>
+L<openssl(1)>,
+L<openssl-ts(1)>,
+L<WWW::Curl::Easy>,
+L<https://www.rfc-editor.org/rfc/rfc3161.html>
=head1 COPYRIGHT
Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man1/verify.pod b/doc/man1/verify.pod
deleted file mode 100644
index da2b7024821d..000000000000
--- a/doc/man1/verify.pod
+++ /dev/null
@@ -1,786 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-verify,
-verify - Utility to verify certificates
-
-=head1 SYNOPSIS
-
-B<openssl> B<verify>
-[B<-help>]
-[B<-CAfile file>]
-[B<-CApath directory>]
-[B<-no-CAfile>]
-[B<-no-CApath>]
-[B<-allow_proxy_certs>]
-[B<-attime timestamp>]
-[B<-check_ss_sig>]
-[B<-CRLfile file>]
-[B<-crl_download>]
-[B<-crl_check>]
-[B<-crl_check_all>]
-[B<-engine id>]
-[B<-explicit_policy>]
-[B<-extended_crl>]
-[B<-ignore_critical>]
-[B<-inhibit_any>]
-[B<-inhibit_map>]
-[B<-nameopt option>]
-[B<-no_check_time>]
-[B<-partial_chain>]
-[B<-policy arg>]
-[B<-policy_check>]
-[B<-policy_print>]
-[B<-purpose purpose>]
-[B<-suiteB_128>]
-[B<-suiteB_128_only>]
-[B<-suiteB_192>]
-[B<-trusted_first>]
-[B<-no_alt_chains>]
-[B<-untrusted file>]
-[B<-trusted file>]
-[B<-use_deltas>]
-[B<-verbose>]
-[B<-auth_level level>]
-[B<-verify_depth num>]
-[B<-verify_email email>]
-[B<-verify_hostname hostname>]
-[B<-verify_ip ip>]
-[B<-verify_name name>]
-[B<-x509_strict>]
-[B<-show_chain>]
-[B<->]
-[certificates]
-
-=head1 DESCRIPTION
-
-The B<verify> command verifies certificate chains.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-CAfile file>
-
-A B<file> of trusted certificates.
-The file should contain one or more certificates in PEM format.
-
-=item B<-CApath directory>
-
-A directory of trusted certificates. The certificates should have names
-of the form: hash.0 or have symbolic links to them of this
-form ("hash" is the hashed certificate subject name: see the B<-hash> option
-of the B<x509> utility). Under Unix the B<c_rehash> script will automatically
-create symbolic links to a directory of certificates.
-
-=item B<-no-CAfile>
-
-Do not load the trusted CA certificates from the default file location.
-
-=item B<-no-CApath>
-
-Do not load the trusted CA certificates from the default directory location.
-
-=item B<-allow_proxy_certs>
-
-Allow the verification of proxy certificates.
-
-=item B<-attime timestamp>
-
-Perform validation checks using time specified by B<timestamp> and not
-current system time. B<timestamp> is the number of seconds since
-01.01.1970 (UNIX time).
-
-=item B<-check_ss_sig>
-
-Verify the signature of
-the last certificate in a chain if the certificate is supposedly self-signed.
-This is prohibited and will result in an error if it is a non-conforming CA
-certificate with key usage restrictions not including the keyCertSign bit.
-This verification is disabled by default because it doesn't add any security.
-
-=item B<-CRLfile file>
-
-The B<file> should contain one or more CRLs in PEM format.
-This option can be specified more than once to include CRLs from multiple
-B<files>.
-
-=item B<-crl_download>
-
-Attempt to download CRL information for this certificate.
-
-=item B<-crl_check>
-
-Checks end entity certificate validity by attempting to look up a valid CRL.
-If a valid CRL cannot be found an error occurs.
-
-=item B<-crl_check_all>
-
-Checks the validity of B<all> certificates in the chain by attempting
-to look up valid CRLs.
-
-=item B<-engine id>
-
-Specifying an engine B<id> will cause L<verify(1)> to attempt to load the
-specified engine.
-The engine will then be set as the default for all its supported algorithms.
-If you want to load certificates or CRLs that require engine support via any of
-the B<-trusted>, B<-untrusted> or B<-CRLfile> options, the B<-engine> option
-must be specified before those options.
-
-=item B<-explicit_policy>
-
-Set policy variable require-explicit-policy (see RFC5280).
-
-=item B<-extended_crl>
-
-Enable extended CRL features such as indirect CRLs and alternate CRL
-signing keys.
-
-=item B<-ignore_critical>
-
-Normally if an unhandled critical extension is present which is not
-supported by OpenSSL the certificate is rejected (as required by RFC5280).
-If this option is set critical extensions are ignored.
-
-=item B<-inhibit_any>
-
-Set policy variable inhibit-any-policy (see RFC5280).
-
-=item B<-inhibit_map>
-
-Set policy variable inhibit-policy-mapping (see RFC5280).
-
-=item B<-nameopt option>
-
-Option which determines how the subject or issuer names are displayed. The
-B<option> argument can be a single option or multiple options separated by
-commas. Alternatively the B<-nameopt> switch may be used more than once to
-set multiple options. See the L<x509(1)> manual page for details.
-
-=item B<-no_check_time>
-
-This option suppresses checking the validity period of certificates and CRLs
-against the current time. If option B<-attime timestamp> is used to specify
-a verification time, the check is not suppressed.
-
-=item B<-partial_chain>
-
-Allow verification to succeed even if a I<complete> chain cannot be built to a
-self-signed trust-anchor, provided it is possible to construct a chain to a
-trusted certificate that might not be self-signed.
-
-=item B<-policy arg>
-
-Enable policy processing and add B<arg> to the user-initial-policy-set (see
-RFC5280). The policy B<arg> can be an object name an OID in numeric form.
-This argument can appear more than once.
-
-=item B<-policy_check>
-
-Enables certificate policy processing.
-
-=item B<-policy_print>
-
-Print out diagnostics related to policy processing.
-
-=item B<-purpose purpose>
-
-The intended use for the certificate. If this option is not specified,
-B<verify> will not consider certificate purpose during chain verification.
-Currently accepted uses are B<sslclient>, B<sslserver>, B<nssslserver>,
-B<smimesign>, B<smimeencrypt>. See the B<VERIFY OPERATION> section for more
-information.
-
-=item B<-suiteB_128_only>, B<-suiteB_128>, B<-suiteB_192>
-
-Enable the Suite B mode operation at 128 bit Level of Security, 128 bit or
-192 bit, or only 192 bit Level of Security respectively.
-See RFC6460 for details. In particular the supported signature algorithms are
-reduced to support only ECDSA and SHA256 or SHA384 and only the elliptic curves
-P-256 and P-384.
-
-=item B<-trusted_first>
-
-When constructing the certificate chain, use the trusted certificates specified
-via B<-CAfile>, B<-CApath> or B<-trusted> before any certificates specified via
-B<-untrusted>.
-This can be useful in environments with Bridge or Cross-Certified CAs.
-As of OpenSSL 1.1.0 this option is on by default and cannot be disabled.
-
-=item B<-no_alt_chains>
-
-By default, unless B<-trusted_first> is specified, when building a certificate
-chain, if the first certificate chain found is not trusted, then OpenSSL will
-attempt to replace untrusted issuer certificates with certificates from the
-trust store to see if an alternative chain can be found that is trusted.
-As of OpenSSL 1.1.0, with B<-trusted_first> always on, this option has no
-effect.
-
-=item B<-untrusted file>
-
-A B<file> of additional untrusted certificates (intermediate issuer CAs) used
-to construct a certificate chain from the subject certificate to a trust-anchor.
-The B<file> should contain one or more certificates in PEM format.
-This option can be specified more than once to include untrusted certificates
-from multiple B<files>.
-
-=item B<-trusted file>
-
-A B<file> of trusted certificates, which must be self-signed, unless the
-B<-partial_chain> option is specified.
-The B<file> contains one or more certificates in PEM format.
-With this option, no additional (e.g., default) certificate lists are
-consulted.
-That is, the only trust-anchors are those listed in B<file>.
-This option can be specified more than once to include trusted certificates
-from multiple B<files>.
-This option implies the B<-no-CAfile> and B<-no-CApath> options.
-This option cannot be used in combination with either of the B<-CAfile> or
-B<-CApath> options.
-
-=item B<-use_deltas>
-
-Enable support for delta CRLs.
-
-=item B<-verbose>
-
-Print extra information about the operations being performed.
-
-=item B<-auth_level level>
-
-Set the certificate chain authentication security level to B<level>.
-The authentication security level determines the acceptable signature and
-public key strength when verifying certificate chains.
-For a certificate chain to validate, the public keys of all the certificates
-must meet the specified security B<level>.
-The signature algorithm security level is enforced for all the certificates in
-the chain except for the chain's I<trust anchor>, which is either directly
-trusted or validated by means other than its signature.
-See L<SSL_CTX_set_security_level(3)> for the definitions of the available
-levels.
-The default security level is -1, or "not set".
-At security level 0 or lower all algorithms are acceptable.
-Security level 1 requires at least 80-bit-equivalent security and is broadly
-interoperable, though it will, for example, reject MD5 signatures or RSA keys
-shorter than 1024 bits.
-
-=item B<-verify_depth num>
-
-Limit the certificate chain to B<num> intermediate CA certificates.
-A maximal depth chain can have up to B<num+2> certificates, since neither the
-end-entity certificate nor the trust-anchor certificate count against the
-B<-verify_depth> limit.
-
-=item B<-verify_email email>
-
-Verify if the B<email> matches the email address in Subject Alternative Name or
-the email in the subject Distinguished Name.
-
-=item B<-verify_hostname hostname>
-
-Verify if the B<hostname> matches DNS name in Subject Alternative Name or
-Common Name in the subject certificate.
-
-=item B<-verify_ip ip>
-
-Verify if the B<ip> matches the IP address in Subject Alternative Name of
-the subject certificate.
-
-=item B<-verify_name name>
-
-Use default verification policies like trust model and required certificate
-policies identified by B<name>.
-The trust model determines which auxiliary trust or reject OIDs are applicable
-to verifying the given certificate chain.
-See the B<-addtrust> and B<-addreject> options of the L<x509(1)> command-line
-utility.
-Supported policy names include: B<default>, B<pkcs7>, B<smime_sign>,
-B<ssl_client>, B<ssl_server>.
-These mimics the combinations of purpose and trust settings used in SSL, CMS
-and S/MIME.
-As of OpenSSL 1.1.0, the trust model is inferred from the purpose when not
-specified, so the B<-verify_name> options are functionally equivalent to the
-corresponding B<-purpose> settings.
-
-=item B<-x509_strict>
-
-For strict X.509 compliance, disable non-compliant workarounds for broken
-certificates.
-
-=item B<-show_chain>
-
-Display information about the certificate chain that has been built (if
-successful). Certificates in the chain that came from the untrusted list will be
-flagged as "untrusted".
-
-=item B<->
-
-Indicates the last option. All arguments following this are assumed to be
-certificate files. This is useful if the first certificate filename begins
-with a B<->.
-
-=item B<certificates>
-
-One or more certificates to verify. If no certificates are given, B<verify>
-will attempt to read a certificate from standard input. Certificates must be
-in PEM format.
-
-=back
-
-=head1 VERIFY OPERATION
-
-The B<verify> program uses the same functions as the internal SSL and S/MIME
-verification, therefore, this description applies to these verify operations
-too.
-
-There is one crucial difference between the verify operations performed
-by the B<verify> program: wherever possible an attempt is made to continue
-after an error whereas normally the verify operation would halt on the
-first error. This allows all the problems with a certificate chain to be
-determined.
-
-The verify operation consists of a number of separate steps.
-
-Firstly a certificate chain is built up starting from the supplied certificate
-and ending in the root CA.
-It is an error if the whole chain cannot be built up.
-The chain is built up by looking up the issuers certificate of the current
-certificate.
-If a certificate is found which is its own issuer it is assumed to be the root
-CA.
-
-The process of 'looking up the issuers certificate' itself involves a number of
-steps.
-After all certificates whose subject name matches the issuer name of the current
-certificate are subject to further tests.
-The relevant authority key identifier components of the current certificate (if
-present) must match the subject key identifier (if present) and issuer and
-serial number of the candidate issuer, in addition the keyUsage extension of
-the candidate issuer (if present) must permit certificate signing.
-
-The lookup first looks in the list of untrusted certificates and if no match
-is found the remaining lookups are from the trusted certificates. The root CA
-is always looked up in the trusted certificate list: if the certificate to
-verify is a root certificate then an exact match must be found in the trusted
-list.
-
-The second operation is to check every untrusted certificate's extensions for
-consistency with the supplied purpose. If the B<-purpose> option is not included
-then no checks are done. The supplied or "leaf" certificate must have extensions
-compatible with the supplied purpose and all other certificates must also be valid
-CA certificates. The precise extensions required are described in more detail in
-the B<CERTIFICATE EXTENSIONS> section of the B<x509> utility.
-
-The third operation is to check the trust settings on the root CA. The root CA
-should be trusted for the supplied purpose.
-For compatibility with previous versions of OpenSSL, a certificate with no
-trust settings is considered to be valid for all purposes.
-
-The final operation is to check the validity of the certificate chain.
-For each element in the chain, including the root CA certificate,
-the validity period as specified by the C<notBefore> and C<notAfter> fields
-is checked against the current system time.
-The B<-attime> flag may be used to use a reference time other than "now."
-The certificate signature is checked as well
-(except for the signature of the typically self-signed root CA certificate,
-which is verified only if the B<-check_ss_sig> option is given).
-
-If all operations complete successfully then certificate is considered valid. If
-any operation fails then the certificate is not valid.
-
-=head1 DIAGNOSTICS
-
-When a verify operation fails the output messages can be somewhat cryptic. The
-general form of the error message is:
-
- server.pem: /C=AU/ST=Queensland/O=CryptSoft Pty Ltd/CN=Test CA (1024 bit)
- error 24 at 1 depth lookup:invalid CA certificate
-
-The first line contains the name of the certificate being verified followed by
-the subject name of the certificate. The second line contains the error number
-and the depth. The depth is number of the certificate being verified when a
-problem was detected starting with zero for the certificate being verified itself
-then 1 for the CA that signed the certificate and so on. Finally a text version
-of the error number is presented.
-
-A partial list of the error codes and messages is shown below, this also
-includes the name of the error code as defined in the header file x509_vfy.h
-Some of the error codes are defined but never returned: these are described
-as "unused".
-
-=over 4
-
-=item B<X509_V_OK>
-
-The operation was successful.
-
-=item B<X509_V_ERR_UNSPECIFIED>
-
-Unspecified error; should not happen.
-
-=item B<X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT>
-
-The issuer certificate of a looked up certificate could not be found. This
-normally means the list of trusted certificates is not complete.
-
-=item B<X509_V_ERR_UNABLE_TO_GET_CRL>
-
-The CRL of a certificate could not be found.
-
-=item B<X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE>
-
-The certificate signature could not be decrypted. This means that the
-actual signature value could not be determined rather than it not matching
-the expected value, this is only meaningful for RSA keys.
-
-=item B<X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE>
-
-The CRL signature could not be decrypted: this means that the actual
-signature value could not be determined rather than it not matching the
-expected value. Unused.
-
-=item B<X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY>
-
-The public key in the certificate SubjectPublicKeyInfo could not be read.
-
-=item B<X509_V_ERR_CERT_SIGNATURE_FAILURE>
-
-The signature of the certificate is invalid.
-
-=item B<X509_V_ERR_CRL_SIGNATURE_FAILURE>
-
-The signature of the certificate is invalid.
-
-=item B<X509_V_ERR_CERT_NOT_YET_VALID>
-
-The certificate is not yet valid: the notBefore date is after the
-current time.
-
-=item B<X509_V_ERR_CERT_HAS_EXPIRED>
-
-The certificate has expired: that is the notAfter date is before the
-current time.
-
-=item B<X509_V_ERR_CRL_NOT_YET_VALID>
-
-The CRL is not yet valid.
-
-=item B<X509_V_ERR_CRL_HAS_EXPIRED>
-
-The CRL has expired.
-
-=item B<X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD>
-
-The certificate notBefore field contains an invalid time.
-
-=item B<X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD>
-
-The certificate notAfter field contains an invalid time.
-
-=item B<X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD>
-
-The CRL lastUpdate field contains an invalid time.
-
-=item B<X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD>
-
-The CRL nextUpdate field contains an invalid time.
-
-=item B<X509_V_ERR_OUT_OF_MEM>
-
-An error occurred trying to allocate memory. This should never happen.
-
-=item B<X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT>
-
-The passed certificate is self-signed and the same certificate cannot
-be found in the list of trusted certificates.
-
-=item B<X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN>
-
-The certificate chain could be built up using the untrusted certificates
-but the root could not be found locally.
-
-=item B<X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY>
-
-The issuer certificate could not be found: this occurs if the issuer
-certificate of an untrusted certificate cannot be found.
-
-=item B<X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE>
-
-No signatures could be verified because the chain contains only one
-certificate and it is not self signed.
-
-=item B<X509_V_ERR_CERT_CHAIN_TOO_LONG>
-
-The certificate chain length is greater than the supplied maximum
-depth. Unused.
-
-=item B<X509_V_ERR_CERT_REVOKED>
-
-The certificate has been revoked.
-
-=item B<X509_V_ERR_INVALID_CA>
-
-A CA certificate is invalid. Either it is not a CA or its extensions
-are not consistent with the supplied purpose.
-
-=item B<X509_V_ERR_PATH_LENGTH_EXCEEDED>
-
-The basicConstraints pathlength parameter has been exceeded.
-
-=item B<X509_V_ERR_INVALID_PURPOSE>
-
-The supplied certificate cannot be used for the specified purpose.
-
-=item B<X509_V_ERR_CERT_UNTRUSTED>
-
-The root CA is not marked as trusted for the specified purpose.
-
-=item B<X509_V_ERR_CERT_REJECTED>
-
-The root CA is marked to reject the specified purpose.
-
-=item B<X509_V_ERR_SUBJECT_ISSUER_MISMATCH>
-
-Not used as of OpenSSL 1.1.0 as a result of the deprecation of the
-B<-issuer_checks> option.
-
-=item B<X509_V_ERR_AKID_SKID_MISMATCH>
-
-Not used as of OpenSSL 1.1.0 as a result of the deprecation of the
-B<-issuer_checks> option.
-
-=item B<X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH>
-
-Not used as of OpenSSL 1.1.0 as a result of the deprecation of the
-B<-issuer_checks> option.
-
-=item B<X509_V_ERR_KEYUSAGE_NO_CERTSIGN>
-
-Not used as of OpenSSL 1.1.0 as a result of the deprecation of the
-B<-issuer_checks> option.
-
-=item B<X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER>
-
-Unable to get CRL issuer certificate.
-
-=item B<X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION>
-
-Unhandled critical extension.
-
-=item B<X509_V_ERR_KEYUSAGE_NO_CRL_SIGN>
-
-Key usage does not include CRL signing.
-
-=item B<X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION>
-
-Unhandled critical CRL extension.
-
-=item B<X509_V_ERR_INVALID_NON_CA>
-
-Invalid non-CA certificate has CA markings.
-
-=item B<X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED>
-
-Proxy path length constraint exceeded.
-
-=item B<X509_V_ERR_PROXY_SUBJECT_INVALID>
-
-Proxy certificate subject is invalid. It MUST be the same as the issuer
-with a single CN component added.
-
-=item B<X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE>
-
-Key usage does not include digital signature.
-
-=item B<X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED>
-
-Proxy certificates not allowed, please use B<-allow_proxy_certs>.
-
-=item B<X509_V_ERR_INVALID_EXTENSION>
-
-Invalid or inconsistent certificate extension.
-
-=item B<X509_V_ERR_INVALID_POLICY_EXTENSION>
-
-Invalid or inconsistent certificate policy extension.
-
-=item B<X509_V_ERR_NO_EXPLICIT_POLICY>
-
-No explicit policy.
-
-=item B<X509_V_ERR_DIFFERENT_CRL_SCOPE>
-
-Different CRL scope.
-
-=item B<X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE>
-
-Unsupported extension feature.
-
-=item B<X509_V_ERR_UNNESTED_RESOURCE>
-
-RFC 3779 resource not subset of parent's resources.
-
-=item B<X509_V_ERR_PERMITTED_VIOLATION>
-
-Permitted subtree violation.
-
-=item B<X509_V_ERR_EXCLUDED_VIOLATION>
-
-Excluded subtree violation.
-
-=item B<X509_V_ERR_SUBTREE_MINMAX>
-
-Name constraints minimum and maximum not supported.
-
-=item B<X509_V_ERR_APPLICATION_VERIFICATION>
-
-Application verification failure. Unused.
-
-=item B<X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE>
-
-Unsupported name constraint type.
-
-=item B<X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX>
-
-Unsupported or invalid name constraint syntax.
-
-=item B<X509_V_ERR_UNSUPPORTED_NAME_SYNTAX>
-
-Unsupported or invalid name syntax.
-
-=item B<X509_V_ERR_CRL_PATH_VALIDATION_ERROR>
-
-CRL path validation error.
-
-=item B<X509_V_ERR_PATH_LOOP>
-
-Path loop.
-
-=item B<X509_V_ERR_SUITE_B_INVALID_VERSION>
-
-Suite B: certificate version invalid.
-
-=item B<X509_V_ERR_SUITE_B_INVALID_ALGORITHM>
-
-Suite B: invalid public key algorithm.
-
-=item B<X509_V_ERR_SUITE_B_INVALID_CURVE>
-
-Suite B: invalid ECC curve.
-
-=item B<X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM>
-
-Suite B: invalid signature algorithm.
-
-=item B<X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED>
-
-Suite B: curve not allowed for this LOS.
-
-=item B<X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256>
-
-Suite B: cannot sign P-384 with P-256.
-
-=item B<X509_V_ERR_HOSTNAME_MISMATCH>
-
-Hostname mismatch.
-
-=item B<X509_V_ERR_EMAIL_MISMATCH>
-
-Email address mismatch.
-
-=item B<X509_V_ERR_IP_ADDRESS_MISMATCH>
-
-IP address mismatch.
-
-=item B<X509_V_ERR_DANE_NO_MATCH>
-
-DANE TLSA authentication is enabled, but no TLSA records matched the
-certificate chain.
-This error is only possible in L<s_client(1)>.
-
-=item B<X509_V_ERR_EE_KEY_TOO_SMALL>
-
-EE certificate key too weak.
-
-=item B<X509_ERR_CA_KEY_TOO_SMALL>
-
-CA certificate key too weak.
-
-=item B<X509_ERR_CA_MD_TOO_WEAK>
-
-CA signature digest algorithm too weak.
-
-=item B<X509_V_ERR_INVALID_CALL>
-
-nvalid certificate verification context.
-
-=item B<X509_V_ERR_STORE_LOOKUP>
-
-Issuer certificate lookup error.
-
-=item B<X509_V_ERR_NO_VALID_SCTS>
-
-Certificate Transparency required, but no valid SCTs found.
-
-=item B<X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION>
-
-Proxy subject name violation.
-
-=item B<X509_V_ERR_OCSP_VERIFY_NEEDED>
-
-Returned by the verify callback to indicate an OCSP verification is needed.
-
-=item B<X509_V_ERR_OCSP_VERIFY_FAILED>
-
-Returned by the verify callback to indicate OCSP verification failed.
-
-=item B<X509_V_ERR_OCSP_CERT_UNKNOWN>
-
-Returned by the verify callback to indicate that the certificate is not recognized
-by the OCSP responder.
-
-=back
-
-=head1 BUGS
-
-Although the issuer checks are a considerable improvement over the old
-technique they still suffer from limitations in the underlying X509_LOOKUP
-API. One consequence of this is that trusted certificates with matching
-subject name must either appear in a file (as specified by the B<-CAfile>
-option) or a directory (as specified by B<-CApath>). If they occur in
-both then only the certificates in the file will be recognised.
-
-Previous versions of OpenSSL assume certificates with matching subject
-name are identical and mishandled them.
-
-Previous versions of this documentation swapped the meaning of the
-B<X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT> and
-B<X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY> error codes.
-
-=head1 SEE ALSO
-
-L<x509(1)>
-
-=head1 HISTORY
-
-The B<-show_chain> option was added in OpenSSL 1.1.0.
-
-The B<-issuer_checks> option is deprecated as of OpenSSL 1.1.0 and
-is silently ignored.
-
-=head1 COPYRIGHT
-
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/version.pod b/doc/man1/version.pod
deleted file mode 100644
index 757b55b55c12..000000000000
--- a/doc/man1/version.pod
+++ /dev/null
@@ -1,81 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-version,
-version - print OpenSSL version information
-
-=head1 SYNOPSIS
-
-B<openssl version>
-[B<-help>]
-[B<-a>]
-[B<-v>]
-[B<-b>]
-[B<-o>]
-[B<-f>]
-[B<-p>]
-[B<-d>]
-[B<-e>]
-
-=head1 DESCRIPTION
-
-This command is used to print out version information about OpenSSL.
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-a>
-
-All information, this is the same as setting all the other flags.
-
-=item B<-v>
-
-The current OpenSSL version.
-
-=item B<-b>
-
-The date the current version of OpenSSL was built.
-
-=item B<-o>
-
-Option information: various options set when the library was built.
-
-=item B<-f>
-
-Compilation flags.
-
-=item B<-p>
-
-Platform setting.
-
-=item B<-d>
-
-OPENSSLDIR setting.
-
-=item B<-e>
-
-ENGINESDIR setting.
-
-=back
-
-=head1 NOTES
-
-The output of B<openssl version -a> would typically be used when sending
-in a bug report.
-
-=head1 COPYRIGHT
-
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man1/x509.pod b/doc/man1/x509.pod
deleted file mode 100644
index a94f099b3565..000000000000
--- a/doc/man1/x509.pod
+++ /dev/null
@@ -1,946 +0,0 @@
-=pod
-
-=head1 NAME
-
-openssl-x509,
-x509 - Certificate display and signing utility
-
-=head1 SYNOPSIS
-
-B<openssl> B<x509>
-[B<-help>]
-[B<-inform DER|PEM>]
-[B<-outform DER|PEM>]
-[B<-keyform DER|PEM|ENGINE>]
-[B<-CAform DER|PEM>]
-[B<-CAkeyform DER|PEM>]
-[B<-in filename>]
-[B<-out filename>]
-[B<-serial>]
-[B<-hash>]
-[B<-subject_hash>]
-[B<-issuer_hash>]
-[B<-ocspid>]
-[B<-subject>]
-[B<-issuer>]
-[B<-nameopt option>]
-[B<-email>]
-[B<-ocsp_uri>]
-[B<-startdate>]
-[B<-enddate>]
-[B<-purpose>]
-[B<-dates>]
-[B<-checkend num>]
-[B<-modulus>]
-[B<-pubkey>]
-[B<-fingerprint>]
-[B<-alias>]
-[B<-noout>]
-[B<-trustout>]
-[B<-clrtrust>]
-[B<-clrreject>]
-[B<-addtrust arg>]
-[B<-addreject arg>]
-[B<-setalias arg>]
-[B<-days arg>]
-[B<-set_serial n>]
-[B<-signkey arg>]
-[B<-passin arg>]
-[B<-x509toreq>]
-[B<-req>]
-[B<-CA filename>]
-[B<-CAkey filename>]
-[B<-CAcreateserial>]
-[B<-CAserial filename>]
-[B<-force_pubkey key>]
-[B<-text>]
-[B<-ext extensions>]
-[B<-certopt option>]
-[B<-C>]
-[B<-I<digest>>]
-[B<-clrext>]
-[B<-extfile filename>]
-[B<-extensions section>]
-[B<-sigopt nm:v>]
-[B<-rand file...>]
-[B<-writerand file>]
-[B<-engine id>]
-[B<-preserve_dates>]
-
-=head1 DESCRIPTION
-
-The B<x509> command is a multi purpose certificate utility. It can be
-used to display certificate information, convert certificates to
-various forms, sign certificate requests like a "mini CA" or edit
-certificate trust settings.
-
-Since there are a large number of options they will split up into
-various sections.
-
-=head1 OPTIONS
-
-=head2 Input, Output, and General Purpose Options
-
-=over 4
-
-=item B<-help>
-
-Print out a usage message.
-
-=item B<-inform DER|PEM>
-
-This specifies the input format normally the command will expect an X509
-certificate but this can change if other options such as B<-req> are
-present. The DER format is the DER encoding of the certificate and PEM
-is the base64 encoding of the DER encoding with header and footer lines
-added. The default format is PEM.
-
-=item B<-outform DER|PEM>
-
-This specifies the output format, the options have the same meaning and default
-as the B<-inform> option.
-
-=item B<-in filename>
-
-This specifies the input filename to read a certificate from or standard input
-if this option is not specified.
-
-=item B<-out filename>
-
-This specifies the output filename to write to or standard output by
-default.
-
-=item B<-I<digest>>
-
-The digest to use.
-This affects any signing or display option that uses a message
-digest, such as the B<-fingerprint>, B<-signkey> and B<-CA> options.
-Any digest supported by the OpenSSL B<dgst> command can be used.
-If not specified then SHA1 is used with B<-fingerprint> or
-the default digest for the signing algorithm is used, typically SHA256.
-
-=item B<-rand file...>
-
-A file or files containing random data used to seed the random number
-generator.
-Multiple files can be specified separated by an OS-dependent character.
-The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
-all others.
-
-=item [B<-writerand file>]
-
-Writes random data to the specified I<file> upon exit.
-This can be used with a subsequent B<-rand> flag.
-
-=item B<-engine id>
-
-Specifying an engine (by its unique B<id> string) will cause B<x509>
-to attempt to obtain a functional reference to the specified engine,
-thus initialising it if needed. The engine will then be set as the default
-for all available algorithms.
-
-=item B<-preserve_dates>
-
-When signing a certificate, preserve the "notBefore" and "notAfter" dates instead
-of adjusting them to current time and duration. Cannot be used with the B<-days> option.
-
-=back
-
-=head2 Display Options
-
-Note: the B<-alias> and B<-purpose> options are also display options
-but are described in the B<TRUST SETTINGS> section.
-
-=over 4
-
-=item B<-text>
-
-Prints out the certificate in text form. Full details are output including the
-public key, signature algorithms, issuer and subject names, serial number
-any extensions present and any trust settings.
-
-=item B<-ext extensions>
-
-Prints out the certificate extensions in text form. Extensions are specified
-with a comma separated string, e.g., "subjectAltName,subjectKeyIdentifier".
-See the L<x509v3_config(5)> manual page for the extension names.
-
-=item B<-certopt option>
-
-Customise the output format used with B<-text>. The B<option> argument
-can be a single option or multiple options separated by commas. The
-B<-certopt> switch may be also be used more than once to set multiple
-options. See the B<TEXT OPTIONS> section for more information.
-
-=item B<-noout>
-
-This option prevents output of the encoded version of the certificate.
-
-=item B<-pubkey>
-
-Outputs the certificate's SubjectPublicKeyInfo block in PEM format.
-
-=item B<-modulus>
-
-This option prints out the value of the modulus of the public key
-contained in the certificate.
-
-=item B<-serial>
-
-Outputs the certificate serial number.
-
-=item B<-subject_hash>
-
-Outputs the "hash" of the certificate subject name. This is used in OpenSSL to
-form an index to allow certificates in a directory to be looked up by subject
-name.
-
-=item B<-issuer_hash>
-
-Outputs the "hash" of the certificate issuer name.
-
-=item B<-ocspid>
-
-Outputs the OCSP hash values for the subject name and public key.
-
-=item B<-hash>
-
-Synonym for "-subject_hash" for backward compatibility reasons.
-
-=item B<-subject_hash_old>
-
-Outputs the "hash" of the certificate subject name using the older algorithm
-as used by OpenSSL before version 1.0.0.
-
-=item B<-issuer_hash_old>
-
-Outputs the "hash" of the certificate issuer name using the older algorithm
-as used by OpenSSL before version 1.0.0.
-
-=item B<-subject>
-
-Outputs the subject name.
-
-=item B<-issuer>
-
-Outputs the issuer name.
-
-=item B<-nameopt option>
-
-Option which determines how the subject or issuer names are displayed. The
-B<option> argument can be a single option or multiple options separated by
-commas. Alternatively the B<-nameopt> switch may be used more than once to
-set multiple options. See the B<NAME OPTIONS> section for more information.
-
-=item B<-email>
-
-Outputs the email address(es) if any.
-
-=item B<-ocsp_uri>
-
-Outputs the OCSP responder address(es) if any.
-
-=item B<-startdate>
-
-Prints out the start date of the certificate, that is the notBefore date.
-
-=item B<-enddate>
-
-Prints out the expiry date of the certificate, that is the notAfter date.
-
-=item B<-dates>
-
-Prints out the start and expiry dates of a certificate.
-
-=item B<-checkend arg>
-
-Checks if the certificate expires within the next B<arg> seconds and exits
-nonzero if yes it will expire or zero if not.
-
-=item B<-fingerprint>
-
-Calculates and outputs the digest of the DER encoded version of the entire
-certificate (see digest options).
-This is commonly called a "fingerprint". Because of the nature of message
-digests, the fingerprint of a certificate is unique to that certificate and
-two certificates with the same fingerprint can be considered to be the same.
-
-=item B<-C>
-
-This outputs the certificate in the form of a C source file.
-
-=back
-
-=head2 Trust Settings
-
-A B<trusted certificate> is an ordinary certificate which has several
-additional pieces of information attached to it such as the permitted
-and prohibited uses of the certificate and an "alias".
-
-Normally when a certificate is being verified at least one certificate
-must be "trusted". By default a trusted certificate must be stored
-locally and must be a root CA: any certificate chain ending in this CA
-is then usable for any purpose.
-
-Trust settings currently are only used with a root CA. They allow a finer
-control over the purposes the root CA can be used for. For example a CA
-may be trusted for SSL client but not SSL server use.
-
-See the description of the B<verify> utility for more information on the
-meaning of trust settings.
-
-Future versions of OpenSSL will recognize trust settings on any
-certificate: not just root CAs.
-
-
-=over 4
-
-=item B<-trustout>
-
-This causes B<x509> to output a B<trusted> certificate. An ordinary
-or trusted certificate can be input but by default an ordinary
-certificate is output and any trust settings are discarded. With the
-B<-trustout> option a trusted certificate is output. A trusted
-certificate is automatically output if any trust settings are modified.
-
-=item B<-setalias arg>
-
-Sets the alias of the certificate. This will allow the certificate
-to be referred to using a nickname for example "Steve's Certificate".
-
-=item B<-alias>
-
-Outputs the certificate alias, if any.
-
-=item B<-clrtrust>
-
-Clears all the permitted or trusted uses of the certificate.
-
-=item B<-clrreject>
-
-Clears all the prohibited or rejected uses of the certificate.
-
-=item B<-addtrust arg>
-
-Adds a trusted certificate use.
-Any object name can be used here but currently only B<clientAuth> (SSL client
-use), B<serverAuth> (SSL server use), B<emailProtection> (S/MIME email) and
-B<anyExtendedKeyUsage> are used.
-As of OpenSSL 1.1.0, the last of these blocks all purposes when rejected or
-enables all purposes when trusted.
-Other OpenSSL applications may define additional uses.
-
-=item B<-addreject arg>
-
-Adds a prohibited use. It accepts the same values as the B<-addtrust>
-option.
-
-=item B<-purpose>
-
-This option performs tests on the certificate extensions and outputs
-the results. For a more complete description see the B<CERTIFICATE
-EXTENSIONS> section.
-
-=back
-
-=head2 Signing Options
-
-The B<x509> utility can be used to sign certificates and requests: it
-can thus behave like a "mini CA".
-
-=over 4
-
-=item B<-signkey arg>
-
-This option causes the input file to be self signed using the supplied
-private key or engine. The private key's format is specified with the
-B<-keyform> option.
-
-If the input file is a certificate it sets the issuer name to the
-subject name (i.e. makes it self signed) changes the public key to the
-supplied value and changes the start and end dates. The start date is
-set to the current time and the end date is set to a value determined
-by the B<-days> option. Any certificate extensions are retained unless
-the B<-clrext> option is supplied; this includes, for example, any existing
-key identifier extensions.
-
-If the input is a certificate request then a self signed certificate
-is created using the supplied private key using the subject name in
-the request.
-
-=item B<-sigopt nm:v>
-
-Pass options to the signature algorithm during sign or verify operations.
-Names and values of these options are algorithm-specific.
-
-=item B<-passin arg>
-
-The key password source. For more information about the format of B<arg>
-see L<openssl(1)/Pass Phrase Options>.
-
-=item B<-clrext>
-
-Delete any extensions from a certificate. This option is used when a
-certificate is being created from another certificate (for example with
-the B<-signkey> or the B<-CA> options). Normally all extensions are
-retained.
-
-=item B<-keyform PEM|DER|ENGINE>
-
-Specifies the format (DER or PEM) of the private key file used in the
-B<-signkey> option.
-
-=item B<-days arg>
-
-Specifies the number of days to make a certificate valid for. The default
-is 30 days. Cannot be used with the B<-preserve_dates> option.
-
-=item B<-x509toreq>
-
-Converts a certificate into a certificate request. The B<-signkey> option
-is used to pass the required private key.
-
-=item B<-req>
-
-By default a certificate is expected on input. With this option a
-certificate request is expected instead.
-
-=item B<-set_serial n>
-
-Specifies the serial number to use. This option can be used with either
-the B<-signkey> or B<-CA> options. If used in conjunction with the B<-CA>
-option the serial number file (as specified by the B<-CAserial> or
-B<-CAcreateserial> options) is not used.
-
-The serial number can be decimal or hex (if preceded by B<0x>).
-
-=item B<-CA filename>
-
-Specifies the CA certificate to be used for signing. When this option is
-present B<x509> behaves like a "mini CA". The input file is signed by this
-CA using this option: that is its issuer name is set to the subject name
-of the CA and it is digitally signed using the CAs private key.
-
-This option is normally combined with the B<-req> option. Without the
-B<-req> option the input is a certificate which must be self signed.
-
-=item B<-CAkey filename>
-
-Sets the CA private key to sign a certificate with. If this option is
-not specified then it is assumed that the CA private key is present in
-the CA certificate file.
-
-=item B<-CAserial filename>
-
-Sets the CA serial number file to use.
-
-When creating a certificate with this option, and with the B<-CA> option,
-the certificate serial number is stored in the given file.
-This file consists of one line containing
-an even number of hex digits with the serial number used last time.
-After reading this number, it is incremented and used, and the file is updated.
-
-The default filename consists of the CA certificate file base name with
-".srl" appended. For example if the CA certificate file is called
-"mycacert.pem" it expects to find a serial number file called "mycacert.srl".
-
-If the B<-CA> option is specified and neither <-CAserial> or <-CAcreateserial>
-is given and the default serial number file does not exist,
-a random number is generated; this is the recommended practice.
-
-=item B<-CAcreateserial>
-
-With this option and the B<-CA> option
-the CA serial number file is created if it does not exist.
-A random number is generated, used for the certificate,
-and saved into the serial number file determined as described above.
-
-=item B<-extfile filename>
-
-File containing certificate extensions to use. If not specified then
-no extensions are added to the certificate.
-
-=item B<-extensions section>
-
-The section to add certificate extensions from. If this option is not
-specified then the extensions should either be contained in the unnamed
-(default) section or the default section should contain a variable called
-"extensions" which contains the section to use. See the
-L<x509v3_config(5)> manual page for details of the
-extension section format.
-
-=item B<-force_pubkey key>
-
-When a certificate is created set its public key to B<key> instead of the
-key in the certificate or certificate request. This option is useful for
-creating certificates where the algorithm can't normally sign requests, for
-example DH.
-
-The format or B<key> can be specified using the B<-keyform> option.
-
-=back
-
-=head2 Name Options
-
-The B<nameopt> command line switch determines how the subject and issuer
-names are displayed. If no B<nameopt> switch is present the default "oneline"
-format is used which is compatible with previous versions of OpenSSL.
-Each option is described in detail below, all options can be preceded by
-a B<-> to turn the option off. Only the first four will normally be used.
-
-=over 4
-
-=item B<compat>
-
-Use the old format.
-
-=item B<RFC2253>
-
-Displays names compatible with RFC2253 equivalent to B<esc_2253>, B<esc_ctrl>,
-B<esc_msb>, B<utf8>, B<dump_nostr>, B<dump_unknown>, B<dump_der>,
-B<sep_comma_plus>, B<dn_rev> and B<sname>.
-
-=item B<oneline>
-
-A oneline format which is more readable than RFC2253. It is equivalent to
-specifying the B<esc_2253>, B<esc_ctrl>, B<esc_msb>, B<utf8>, B<dump_nostr>,
-B<dump_der>, B<use_quote>, B<sep_comma_plus_space>, B<space_eq> and B<sname>
-options. This is the I<default> of no name options are given explicitly.
-
-=item B<multiline>
-
-A multiline format. It is equivalent B<esc_ctrl>, B<esc_msb>, B<sep_multiline>,
-B<space_eq>, B<lname> and B<align>.
-
-=item B<esc_2253>
-
-Escape the "special" characters required by RFC2253 in a field. That is
-B<,+"E<lt>E<gt>;>. Additionally B<#> is escaped at the beginning of a string
-and a space character at the beginning or end of a string.
-
-=item B<esc_2254>
-
-Escape the "special" characters required by RFC2254 in a field. That is
-the B<NUL> character as well as and B<()*>.
-
-=item B<esc_ctrl>
-
-Escape control characters. That is those with ASCII values less than
-0x20 (space) and the delete (0x7f) character. They are escaped using the
-RFC2253 \XX notation (where XX are two hex digits representing the
-character value).
-
-=item B<esc_msb>
-
-Escape characters with the MSB set, that is with ASCII values larger than
-127.
-
-=item B<use_quote>
-
-Escapes some characters by surrounding the whole string with B<"> characters,
-without the option all escaping is done with the B<\> character.
-
-=item B<utf8>
-
-Convert all strings to UTF8 format first. This is required by RFC2253. If
-you are lucky enough to have a UTF8 compatible terminal then the use
-of this option (and B<not> setting B<esc_msb>) may result in the correct
-display of multibyte (international) characters. Is this option is not
-present then multibyte characters larger than 0xff will be represented
-using the format \UXXXX for 16 bits and \WXXXXXXXX for 32 bits.
-Also if this option is off any UTF8Strings will be converted to their
-character form first.
-
-=item B<ignore_type>
-
-This option does not attempt to interpret multibyte characters in any
-way. That is their content octets are merely dumped as though one octet
-represents each character. This is useful for diagnostic purposes but
-will result in rather odd looking output.
-
-=item B<show_type>
-
-Show the type of the ASN1 character string. The type precedes the
-field contents. For example "BMPSTRING: Hello World".
-
-=item B<dump_der>
-
-When this option is set any fields that need to be hexdumped will
-be dumped using the DER encoding of the field. Otherwise just the
-content octets will be displayed. Both options use the RFC2253
-B<#XXXX...> format.
-
-=item B<dump_nostr>
-
-Dump non character string types (for example OCTET STRING) if this
-option is not set then non character string types will be displayed
-as though each content octet represents a single character.
-
-=item B<dump_all>
-
-Dump all fields. This option when used with B<dump_der> allows the
-DER encoding of the structure to be unambiguously determined.
-
-=item B<dump_unknown>
-
-Dump any field whose OID is not recognised by OpenSSL.
-
-=item B<sep_comma_plus>, B<sep_comma_plus_space>, B<sep_semi_plus_space>,
-B<sep_multiline>
-
-These options determine the field separators. The first character is
-between RDNs and the second between multiple AVAs (multiple AVAs are
-very rare and their use is discouraged). The options ending in
-"space" additionally place a space after the separator to make it
-more readable. The B<sep_multiline> uses a linefeed character for
-the RDN separator and a spaced B<+> for the AVA separator. It also
-indents the fields by four characters. If no field separator is specified
-then B<sep_comma_plus_space> is used by default.
-
-=item B<dn_rev>
-
-Reverse the fields of the DN. This is required by RFC2253. As a side
-effect this also reverses the order of multiple AVAs but this is
-permissible.
-
-=item B<nofname>, B<sname>, B<lname>, B<oid>
-
-These options alter how the field name is displayed. B<nofname> does
-not display the field at all. B<sname> uses the "short name" form
-(CN for commonName for example). B<lname> uses the long form.
-B<oid> represents the OID in numerical form and is useful for
-diagnostic purpose.
-
-=item B<align>
-
-Align field values for a more readable output. Only usable with
-B<sep_multiline>.
-
-=item B<space_eq>
-
-Places spaces round the B<=> character which follows the field
-name.
-
-=back
-
-=head2 Text Options
-
-As well as customising the name output format, it is also possible to
-customise the actual fields printed using the B<certopt> options when
-the B<text> option is present. The default behaviour is to print all fields.
-
-=over 4
-
-=item B<compatible>
-
-Use the old format. This is equivalent to specifying no output options at all.
-
-=item B<no_header>
-
-Don't print header information: that is the lines saying "Certificate"
-and "Data".
-
-=item B<no_version>
-
-Don't print out the version number.
-
-=item B<no_serial>
-
-Don't print out the serial number.
-
-=item B<no_signame>
-
-Don't print out the signature algorithm used.
-
-=item B<no_validity>
-
-Don't print the validity, that is the B<notBefore> and B<notAfter> fields.
-
-=item B<no_subject>
-
-Don't print out the subject name.
-
-=item B<no_issuer>
-
-Don't print out the issuer name.
-
-=item B<no_pubkey>
-
-Don't print out the public key.
-
-=item B<no_sigdump>
-
-Don't give a hexadecimal dump of the certificate signature.
-
-=item B<no_aux>
-
-Don't print out certificate trust information.
-
-=item B<no_extensions>
-
-Don't print out any X509V3 extensions.
-
-=item B<ext_default>
-
-Retain default extension behaviour: attempt to print out unsupported
-certificate extensions.
-
-=item B<ext_error>
-
-Print an error message for unsupported certificate extensions.
-
-=item B<ext_parse>
-
-ASN1 parse unsupported extensions.
-
-=item B<ext_dump>
-
-Hex dump unsupported extensions.
-
-=item B<ca_default>
-
-The value used by the B<ca> utility, equivalent to B<no_issuer>, B<no_pubkey>,
-B<no_header>, and B<no_version>.
-
-=back
-
-=head1 EXAMPLES
-
-Note: in these examples the '\' means the example should be all on one
-line.
-
-Display the contents of a certificate:
-
- openssl x509 -in cert.pem -noout -text
-
-Display the "Subject Alternative Name" extension of a certificate:
-
- openssl x509 -in cert.pem -noout -ext subjectAltName
-
-Display more extensions of a certificate:
-
- openssl x509 -in cert.pem -noout -ext subjectAltName,nsCertType
-
-Display the certificate serial number:
-
- openssl x509 -in cert.pem -noout -serial
-
-Display the certificate subject name:
-
- openssl x509 -in cert.pem -noout -subject
-
-Display the certificate subject name in RFC2253 form:
-
- openssl x509 -in cert.pem -noout -subject -nameopt RFC2253
-
-Display the certificate subject name in oneline form on a terminal
-supporting UTF8:
-
- openssl x509 -in cert.pem -noout -subject -nameopt oneline,-esc_msb
-
-Display the certificate SHA1 fingerprint:
-
- openssl x509 -sha1 -in cert.pem -noout -fingerprint
-
-Convert a certificate from PEM to DER format:
-
- openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER
-
-Convert a certificate to a certificate request:
-
- openssl x509 -x509toreq -in cert.pem -out req.pem -signkey key.pem
-
-Convert a certificate request into a self signed certificate using
-extensions for a CA:
-
- openssl x509 -req -in careq.pem -extfile openssl.cnf -extensions v3_ca \
- -signkey key.pem -out cacert.pem
-
-Sign a certificate request using the CA certificate above and add user
-certificate extensions:
-
- openssl x509 -req -in req.pem -extfile openssl.cnf -extensions v3_usr \
- -CA cacert.pem -CAkey key.pem -CAcreateserial
-
-
-Set a certificate to be trusted for SSL client use and change set its alias to
-"Steve's Class 1 CA"
-
- openssl x509 -in cert.pem -addtrust clientAuth \
- -setalias "Steve's Class 1 CA" -out trust.pem
-
-=head1 NOTES
-
-The PEM format uses the header and footer lines:
-
- -----BEGIN CERTIFICATE-----
- -----END CERTIFICATE-----
-
-it will also handle files containing:
-
- -----BEGIN X509 CERTIFICATE-----
- -----END X509 CERTIFICATE-----
-
-Trusted certificates have the lines
-
- -----BEGIN TRUSTED CERTIFICATE-----
- -----END TRUSTED CERTIFICATE-----
-
-The conversion to UTF8 format used with the name options assumes that
-T61Strings use the ISO8859-1 character set. This is wrong but Netscape
-and MSIE do this as do many certificates. So although this is incorrect
-it is more likely to display the majority of certificates correctly.
-
-The B<-email> option searches the subject name and the subject alternative
-name extension. Only unique email addresses will be printed out: it will
-not print the same address more than once.
-
-=head1 CERTIFICATE EXTENSIONS
-
-The B<-purpose> option checks the certificate extensions and determines
-what the certificate can be used for. The actual checks done are rather
-complex and include various hacks and workarounds to handle broken
-certificates and software.
-
-The same code is used when verifying untrusted certificates in chains
-so this section is useful if a chain is rejected by the verify code.
-
-The basicConstraints extension CA flag is used to determine whether the
-certificate can be used as a CA. If the CA flag is true then it is a CA,
-if the CA flag is false then it is not a CA. B<All> CAs should have the
-CA flag set to true.
-
-If the basicConstraints extension is absent then the certificate is
-considered to be a "possible CA" other extensions are checked according
-to the intended use of the certificate. A warning is given in this case
-because the certificate should really not be regarded as a CA: however
-it is allowed to be a CA to work around some broken software.
-
-If the certificate is a V1 certificate (and thus has no extensions) and
-it is self signed it is also assumed to be a CA but a warning is again
-given: this is to work around the problem of Verisign roots which are V1
-self signed certificates.
-
-If the keyUsage extension is present then additional restraints are
-made on the uses of the certificate. A CA certificate B<must> have the
-keyCertSign bit set if the keyUsage extension is present.
-
-The extended key usage extension places additional restrictions on the
-certificate uses. If this extension is present (whether critical or not)
-the key can only be used for the purposes specified.
-
-A complete description of each test is given below. The comments about
-basicConstraints and keyUsage and V1 certificates above apply to B<all>
-CA certificates.
-
-
-=over 4
-
-=item B<SSL Client>
-
-The extended key usage extension must be absent or include the "web client
-authentication" OID. keyUsage must be absent or it must have the
-digitalSignature bit set. Netscape certificate type must be absent or it must
-have the SSL client bit set.
-
-=item B<SSL Client CA>
-
-The extended key usage extension must be absent or include the "web client
-authentication" OID. Netscape certificate type must be absent or it must have
-the SSL CA bit set: this is used as a work around if the basicConstraints
-extension is absent.
-
-=item B<SSL Server>
-
-The extended key usage extension must be absent or include the "web server
-authentication" and/or one of the SGC OIDs. keyUsage must be absent or it
-must have the digitalSignature, the keyEncipherment set or both bits set.
-Netscape certificate type must be absent or have the SSL server bit set.
-
-=item B<SSL Server CA>
-
-The extended key usage extension must be absent or include the "web server
-authentication" and/or one of the SGC OIDs. Netscape certificate type must
-be absent or the SSL CA bit must be set: this is used as a work around if the
-basicConstraints extension is absent.
-
-=item B<Netscape SSL Server>
-
-For Netscape SSL clients to connect to an SSL server it must have the
-keyEncipherment bit set if the keyUsage extension is present. This isn't
-always valid because some cipher suites use the key for digital signing.
-Otherwise it is the same as a normal SSL server.
-
-=item B<Common S/MIME Client Tests>
-
-The extended key usage extension must be absent or include the "email
-protection" OID. Netscape certificate type must be absent or should have the
-S/MIME bit set. If the S/MIME bit is not set in Netscape certificate type
-then the SSL client bit is tolerated as an alternative but a warning is shown:
-this is because some Verisign certificates don't set the S/MIME bit.
-
-=item B<S/MIME Signing>
-
-In addition to the common S/MIME client tests the digitalSignature bit or
-the nonRepudiation bit must be set if the keyUsage extension is present.
-
-=item B<S/MIME Encryption>
-
-In addition to the common S/MIME tests the keyEncipherment bit must be set
-if the keyUsage extension is present.
-
-=item B<S/MIME CA>
-
-The extended key usage extension must be absent or include the "email
-protection" OID. Netscape certificate type must be absent or must have the
-S/MIME CA bit set: this is used as a work around if the basicConstraints
-extension is absent.
-
-=item B<CRL Signing>
-
-The keyUsage extension must be absent or it must have the CRL signing bit
-set.
-
-=item B<CRL Signing CA>
-
-The normal CA tests apply. Except in this case the basicConstraints extension
-must be present.
-
-=back
-
-=head1 BUGS
-
-Extensions in certificates are not transferred to certificate requests and
-vice versa.
-
-It is possible to produce invalid certificates or requests by specifying the
-wrong private key or using inconsistent options in some cases: these should
-be checked.
-
-There should be options to explicitly set such things as start and end
-dates rather than an offset from the current time.
-
-=head1 SEE ALSO
-
-L<req(1)>, L<ca(1)>, L<genrsa(1)>,
-L<gendsa(1)>, L<verify(1)>,
-L<x509v3_config(5)>
-
-=head1 HISTORY
-
-The hash algorithm used in the B<-subject_hash> and B<-issuer_hash> options
-before OpenSSL 1.0.0 was based on the deprecated MD5 algorithm and the encoding
-of the distinguished name. In OpenSSL 1.0.0 and later it is based on a
-canonical version of the DN using SHA1. This means that any directories using
-the old form must have their links rebuilt using B<c_rehash> or similar.
-
-=head1 COPYRIGHT
-
-Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man3/ADMISSIONS.pod b/doc/man3/ADMISSIONS.pod
index eaf63b219783..f86aac922aa0 100644
--- a/doc/man3/ADMISSIONS.pod
+++ b/doc/man3/ADMISSIONS.pod
@@ -169,9 +169,9 @@ L<d2i_X509(3)>,
=head1 COPYRIGHT
-Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ASN1_EXTERN_FUNCS.pod b/doc/man3/ASN1_EXTERN_FUNCS.pod
new file mode 100644
index 000000000000..800cc500eac9
--- /dev/null
+++ b/doc/man3/ASN1_EXTERN_FUNCS.pod
@@ -0,0 +1,181 @@
+=pod
+
+=head1 NAME
+
+ASN1_EXTERN_FUNCS, ASN1_ex_d2i, ASN1_ex_d2i_ex, ASN1_ex_i2d, ASN1_ex_new_func,
+ASN1_ex_new_ex_func, ASN1_ex_free_func, ASN1_ex_print_func,
+IMPLEMENT_EXTERN_ASN1
+- ASN.1 external function support
+
+=head1 SYNOPSIS
+
+ #include <openssl/asn1t.h>
+
+ typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
+ const ASN1_ITEM *it, int tag, int aclass, char opt,
+ ASN1_TLC *ctx);
+ typedef int ASN1_ex_d2i_ex(ASN1_VALUE **pval, const unsigned char **in, long len,
+ const ASN1_ITEM *it, int tag, int aclass, char opt,
+ ASN1_TLC *ctx, OSSL_LIB_CTX *libctx,
+ const char *propq);
+ typedef int ASN1_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
+ const ASN1_ITEM *it, int tag, int aclass);
+ typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
+ typedef int ASN1_ex_new_ex_func(ASN1_VALUE **pval, const ASN1_ITEM *it,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
+ typedef int ASN1_ex_print_func(BIO *out, const ASN1_VALUE **pval,
+ int indent, const char *fname,
+ const ASN1_PCTX *pctx);
+
+ struct ASN1_EXTERN_FUNCS_st {
+ void *app_data;
+ ASN1_ex_new_func *asn1_ex_new;
+ ASN1_ex_free_func *asn1_ex_free;
+ ASN1_ex_free_func *asn1_ex_clear;
+ ASN1_ex_d2i *asn1_ex_d2i;
+ ASN1_ex_i2d *asn1_ex_i2d;
+ ASN1_ex_print_func *asn1_ex_print;
+ ASN1_ex_new_ex_func *asn1_ex_new_ex;
+ ASN1_ex_d2i_ex *asn1_ex_d2i_ex;
+ };
+ typedef struct ASN1_EXTERN_FUNCS_st ASN1_EXTERN_FUNCS;
+
+ #define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs)
+
+=head1 DESCRIPTION
+
+ASN.1 data structures templates are typically defined in OpenSSL using a series
+of macros such as ASN1_SEQUENCE(), ASN1_SEQUENCE_END() and so on. Instead
+templates can also be defined based entirely on external functions. These
+external functions are called to perform operations such as creating a new
+B<ASN1_VALUE> or converting an B<ASN1_VALUE> to or from DER encoding.
+
+The macro IMPLEMENT_EXTERN_ASN1() can be used to create such an externally
+defined structure. The name of the structure should be supplied in the I<sname>
+parameter. The tag for the structure (e.g. typically B<V_ASN1_SEQUENCE>) should
+be supplied in the I<tag> parameter. Finally a pointer to an
+B<ASN1_EXTERN_FUNCS> structure should be supplied in the I<fptrs> parameter.
+
+The B<ASN1_EXTERN_FUNCS> structure has the following entries.
+
+=over 4
+
+=item I<app_data>
+
+A pointer to arbitrary application specific data.
+
+=item I<asn1_ex_new>
+
+A "new" function responsible for constructing a new B<ASN1_VALUE> object. The
+newly constructed value should be stored in I<*pval>. The I<it> parameter is a
+pointer to the B<ASN1_ITEM> template object created via the
+IMPLEMENT_EXTERN_ASN1() macro.
+
+Returns a positive value on success or 0 on error.
+
+=item I<asn1_ex_free>
+
+A "free" function responsible for freeing the B<ASN1_VALUE> passed in I<*pval>
+that was previously allocated via a "new" function. The I<it> parameter is a
+pointer to the B<ASN1_ITEM> template object created via the
+IMPLEMENT_EXTERN_ASN1() macro.
+
+=item I<asn1_ex_clear>
+
+A "clear" function responsible for clearing any data in the B<ASN1_VALUE> passed
+in I<*pval> and making it suitable for reuse. The I<it> parameter is a pointer
+to the B<ASN1_ITEM> template object created via the IMPLEMENT_EXTERN_ASN1()
+macro.
+
+=item I<asn1_ex_d2i>
+
+A "d2i" function responsible for converting DER data with the tag I<tag> and
+class I<class> into an B<ASN1_VALUE>. If I<*pval> is non-NULL then the
+B<ASN_VALUE> it points to should be reused. Otherwise a new B<ASN1_VALUE>
+should be allocated and stored in I<*pval>. I<*in> points to the DER data to be
+decoded and I<len> is the length of that data. After decoding I<*in> should be
+updated to point at the next byte after the decoded data. If the B<ASN1_VALUE>
+is considered optional in this context then I<opt> will be nonzero. Otherwise
+it will be zero. The I<it> parameter is a pointer to the B<ASN1_ITEM> template
+object created via the IMPLEMENT_EXTERN_ASN1() macro. A pointer to the current
+B<ASN1_TLC> context (which may be required for other ASN1 function calls) is
+passed in the I<ctx> parameter.
+
+The I<asn1_ex_d2i> entry may be NULL if I<asn1_ex_d2i_ex> has been specified
+instead.
+
+Returns <= 0 on error or a positive value on success.
+
+=item I<asn1_ex_i2d>
+
+An "i2d" function responsible for converting an B<ASN1_VALUE> into DER encoding.
+On entry I<*pval> will contain the B<ASN1_VALUE> to be encoded. If default
+tagging is to be used then I<tag> will be -1 on entry. Otherwise if implicit
+tagging should be used then I<tag> and I<aclass> will be the tag and associated
+class.
+
+If I<out> is not NULL then this function should write the DER encoded data to
+the buffer in I<*out>, and then increment I<*out> to point to immediately after
+the data just written.
+
+If I<out> is NULL then no data should be written but the length calculated and
+returned as if it were.
+
+The I<asn1_ex_i2d> entry may be NULL if I<asn1_ex_i2d_ex> has been specified
+instead.
+
+The return value should be negative if a fatal error occurred, or 0 if a
+non-fatal error occurred. Otherwise it should return the length of the encoded
+data.
+
+=item I<asn1_ex_print>
+
+A "print" function. I<out> is the BIO to print the output to. I<*pval> is the
+B<ASN1_VALUE> to be printed. I<indent> is the number of spaces of indenting to
+be printed before any data is printed. I<fname> is currently unused and is
+always "". I<pctx> is a pointer to the B<ASN1_PCTX> for the print operation.
+
+Returns 0 on error or a positive value on success. If the return value is 2 then
+an additional newline will be printed after the data printed by this function.
+
+=item I<asn1_ex_new_ex>
+
+This is the same as I<asn1_ex_new> except that it is additionally passed the
+OSSL_LIB_CTX to be used in I<libctx> and any property query string to be used
+for algorithm fetching in the I<propq> parameter. See
+L<crypto(7)/ALGORITHM FETCHING> for further details. If I<asn1_ex_new_ex> is
+non NULL, then it will always be called in preference to I<asn1_ex_new>.
+
+=item I<asn1_ex_d2i_ex>
+
+This is the same as I<asn1_ex_d2i> except that it is additionally passed the
+OSSL_LIB_CTX to be used in I<libctx> and any property query string to be used
+for algorithm fetching in the I<propq> parameter. See
+L<crypto(7)/ALGORITHM FETCHING> for further details. If I<asn1_ex_d2i_ex> is
+non NULL, then it will always be called in preference to I<asn1_ex_d2i>.
+
+=back
+
+=head1 RETURN VALUES
+
+Return values for the various callbacks are as described above.
+
+=head1 SEE ALSO
+
+L<ASN1_item_new_ex(3)>
+
+=head1 HISTORY
+
+The I<asn1_ex_new_ex> and I<asn1_ex_d2i_ex> callbacks were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/ASN1_INTEGER_get_int64.pod b/doc/man3/ASN1_INTEGER_get_int64.pod
index faf34eb18637..3bde0b20e686 100644
--- a/doc/man3/ASN1_INTEGER_get_int64.pod
+++ b/doc/man3/ASN1_INTEGER_get_int64.pod
@@ -14,7 +14,7 @@ ASN1_INTEGER_get_int64, ASN1_INTEGER_get, ASN1_INTEGER_set_int64, ASN1_INTEGER_s
long ASN1_INTEGER_get(const ASN1_INTEGER *a);
int ASN1_INTEGER_set_int64(ASN1_INTEGER *a, int64_t r);
- int ASN1_INTEGER_set(const ASN1_INTEGER *a, long v);
+ int ASN1_INTEGER_set(ASN1_INTEGER *a, long v);
int ASN1_INTEGER_get_uint64(uint64_t *pr, const ASN1_INTEGER *a);
int ASN1_INTEGER_set_uint64(ASN1_INTEGER *a, uint64_t r);
@@ -28,8 +28,8 @@ ASN1_INTEGER_get_int64, ASN1_INTEGER_get, ASN1_INTEGER_set_int64, ASN1_INTEGER_s
int ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *a, int64_t r);
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v);
- ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai);
- BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn);
+ ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai);
+ BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn);
=head1 DESCRIPTION
@@ -37,7 +37,7 @@ These functions convert to and from B<ASN1_INTEGER> and B<ASN1_ENUMERATED>
structures.
ASN1_INTEGER_get_int64() converts an B<ASN1_INTEGER> into an B<int64_t> type
-If successful it returns 1 and sets B<*pr> to the value of B<a>. If it fails
+If successful it returns 1 and sets I<*pr> to the value of I<a>. If it fails
(due to invalid type or the value being too big to fit into an B<int64_t> type)
it returns 0.
@@ -45,26 +45,26 @@ ASN1_INTEGER_get_uint64() is similar to ASN1_INTEGER_get_int64_t() except it
converts to a B<uint64_t> type and an error is returned if the passed integer
is negative.
-ASN1_INTEGER_get() also returns the value of B<a> but it returns 0 if B<a> is
+ASN1_INTEGER_get() also returns the value of I<a> but it returns 0 if I<a> is
NULL and -1 on error (which is ambiguous because -1 is a legitimate value for
an B<ASN1_INTEGER>). New applications should use ASN1_INTEGER_get_int64()
instead.
-ASN1_INTEGER_set_int64() sets the value of B<ASN1_INTEGER> B<a> to the
-B<int64_t> value B<r>.
+ASN1_INTEGER_set_int64() sets the value of B<ASN1_INTEGER> I<a> to the
+B<int64_t> value I<r>.
-ASN1_INTEGER_set_uint64() sets the value of B<ASN1_INTEGER> B<a> to the
-B<uint64_t> value B<r>.
+ASN1_INTEGER_set_uint64() sets the value of B<ASN1_INTEGER> I<a> to the
+B<uint64_t> value I<r>.
-ASN1_INTEGER_set() sets the value of B<ASN1_INTEGER> B<a> to the B<long> value
-B<v>.
+ASN1_INTEGER_set() sets the value of B<ASN1_INTEGER> I<a> to the I<long> value
+I<v>.
-BN_to_ASN1_INTEGER() converts B<BIGNUM> B<bn> to an B<ASN1_INTEGER>. If B<ai>
-is NULL a new B<ASN1_INTEGER> structure is returned. If B<ai> is not NULL then
+BN_to_ASN1_INTEGER() converts B<BIGNUM> I<bn> to an B<ASN1_INTEGER>. If I<ai>
+is NULL a new B<ASN1_INTEGER> structure is returned. If I<ai> is not NULL then
the existing structure will be used instead.
-ASN1_INTEGER_to_BN() converts ASN1_INTEGER B<ai> into a B<BIGNUM>. If B<bn> is
-NULL a new B<BIGNUM> structure is returned. If B<bn> is not NULL then the
+ASN1_INTEGER_to_BN() converts ASN1_INTEGER I<ai> into a B<BIGNUM>. If I<bn> is
+NULL a new B<BIGNUM> structure is returned. If I<bn> is not NULL then the
existing structure will be used instead.
ASN1_ENUMERATED_get_int64(), ASN1_ENUMERATED_set_int64(),
@@ -72,8 +72,8 @@ ASN1_ENUMERATED_set(), BN_to_ASN1_ENUMERATED() and ASN1_ENUMERATED_to_BN()
behave in an identical way to their ASN1_INTEGER counterparts except they
operate on an B<ASN1_ENUMERATED> value.
-ASN1_ENUMERATED_get() returns the value of B<a> in a similar way to
-ASN1_INTEGER_get() but it returns B<0xffffffffL> if the value of B<a> will not
+ASN1_ENUMERATED_get() returns the value of I<a> in a similar way to
+ASN1_INTEGER_get() but it returns B<0xffffffffL> if the value of I<a> will not
fit in a long type. New applications should use ASN1_ENUMERATED_get_int64()
instead.
@@ -123,9 +123,9 @@ were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ASN1_INTEGER_new.pod b/doc/man3/ASN1_INTEGER_new.pod
new file mode 100644
index 000000000000..4722f880c0b2
--- /dev/null
+++ b/doc/man3/ASN1_INTEGER_new.pod
@@ -0,0 +1,44 @@
+=pod
+
+=head1 NAME
+
+ASN1_INTEGER_new, ASN1_INTEGER_free - ASN1_INTEGER allocation functions
+
+=head1 SYNOPSIS
+
+=for openssl generic
+
+ #include <openssl/asn1.h>
+
+ ASN1_INTEGER *ASN1_INTEGER_new(void);
+ void ASN1_INTEGER_free(ASN1_INTEGER *a);
+
+=head1 DESCRIPTION
+
+ASN1_INTEGER_new() returns an allocated B<ASN1_INTEGER> structure.
+
+ASN1_INTEGER_free() frees up a single B<ASN1_INTEGER> object.
+
+B<ASN1_INTEGER> structure representing the ASN.1 INTEGER type
+
+=head1 RETURN VALUES
+
+ASN1_INTEGER_new() return a valid B<ASN1_INTEGER> structure or NULL
+if an error occurred.
+
+ASN1_INTEGER_free() does not return a value.
+
+=head1 SEE ALSO
+
+L<ERR_get_error(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/ASN1_ITEM_lookup.pod b/doc/man3/ASN1_ITEM_lookup.pod
index 9ba69c9d34dd..e5bba3d5e614 100644
--- a/doc/man3/ASN1_ITEM_lookup.pod
+++ b/doc/man3/ASN1_ITEM_lookup.pod
@@ -13,15 +13,15 @@ ASN1_ITEM_lookup, ASN1_ITEM_get - lookup ASN.1 structures
=head1 DESCRIPTION
-ASN1_ITEM_lookup() returns the B<ASN1_ITEM name>.
+ASN1_ITEM_lookup() returns the B<ASN1_ITEM> named I<name>.
-ASN1_ITEM_get() returns the B<ASN1_ITEM> with index B<i>. This function
-returns B<NULL> if the index B<i> is out of range.
+ASN1_ITEM_get() returns the B<ASN1_ITEM> with index I<i>. This function
+returns NULL if the index I<i> is out of range.
=head1 RETURN VALUES
ASN1_ITEM_lookup() and ASN1_ITEM_get() return a valid B<ASN1_ITEM> structure
-or B<NULL> if an error occurred.
+or NULL if an error occurred.
=head1 SEE ALSO
@@ -31,7 +31,7 @@ L<ERR_get_error(3)>
Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ASN1_OBJECT_new.pod b/doc/man3/ASN1_OBJECT_new.pod
index 4c018efffd56..4e1a3740eac8 100644
--- a/doc/man3/ASN1_OBJECT_new.pod
+++ b/doc/man3/ASN1_OBJECT_new.pod
@@ -13,23 +13,23 @@ ASN1_OBJECT_new, ASN1_OBJECT_free - object allocation functions
=head1 DESCRIPTION
-The ASN1_OBJECT allocation routines, allocate and free an
-ASN1_OBJECT structure, which represents an ASN1 OBJECT IDENTIFIER.
+The B<ASN1_OBJECT> allocation routines, allocate and free an
+B<ASN1_OBJECT> structure, which represents an ASN1 OBJECT IDENTIFIER.
-ASN1_OBJECT_new() allocates and initializes an ASN1_OBJECT structure.
+ASN1_OBJECT_new() allocates and initializes an B<ASN1_OBJECT> structure.
-ASN1_OBJECT_free() frees up the B<ASN1_OBJECT> structure B<a>.
-If B<a> is NULL, nothing is done.
+ASN1_OBJECT_free() frees up the B<ASN1_OBJECT> structure I<a>.
+If I<a> is NULL, nothing is done.
=head1 NOTES
-Although ASN1_OBJECT_new() allocates a new ASN1_OBJECT structure it
+Although ASN1_OBJECT_new() allocates a new B<ASN1_OBJECT> structure it
is almost never used in applications. The ASN1 object utility functions
such as OBJ_nid2obj() are used instead.
=head1 RETURN VALUES
-If the allocation fails, ASN1_OBJECT_new() returns B<NULL> and sets an error
+If the allocation fails, ASN1_OBJECT_new() returns NULL and sets an error
code that can be obtained by L<ERR_get_error(3)>.
Otherwise it returns a pointer to the newly allocated structure.
@@ -43,7 +43,7 @@ L<ERR_get_error(3)>, L<d2i_ASN1_OBJECT(3)>
Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ASN1_STRING_TABLE_add.pod b/doc/man3/ASN1_STRING_TABLE_add.pod
index e1786bf085c6..243da826f729 100644
--- a/doc/man3/ASN1_STRING_TABLE_add.pod
+++ b/doc/man3/ASN1_STRING_TABLE_add.pod
@@ -13,7 +13,7 @@ ASN1_STRING_TABLE_cleanup - ASN1_STRING_TABLE manipulation functions
int ASN1_STRING_TABLE_add(int nid, long minsize, long maxsize,
unsigned long mask, unsigned long flags);
- ASN1_STRING_TABLE * ASN1_STRING_TABLE_get(int nid);
+ ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid);
void ASN1_STRING_TABLE_cleanup(void);
=head1 DESCRIPTION
@@ -26,16 +26,16 @@ B<ASN1_STRING_TABLE> is a table which holds string information
=head2 Functions
ASN1_STRING_TABLE_add() adds a new B<ASN1_STRING_TABLE> item into the
-local ASN1 string table based on the B<nid> along with other parameters.
+local ASN1 string table based on the I<nid> along with other parameters.
If the item is already in the table, fields of B<ASN1_STRING_TABLE> are
-updated (depending on the values of those parameters, e.g., B<minsize>
-and B<maxsize> >= 0, B<mask> and B<flags> != 0). If the B<nid> is standard,
+updated (depending on the values of those parameters, e.g., I<minsize>
+and I<maxsize> >= 0, I<mask> and I<flags> != 0). If the I<nid> is standard,
a copy of the standard B<ASN1_STRING_TABLE> is created and updated with
other parameters.
ASN1_STRING_TABLE_get() searches for an B<ASN1_STRING_TABLE> item based
-on B<nid>. It will search the local table first, then the standard one.
+on I<nid>. It will search the local table first, then the standard one.
ASN1_STRING_TABLE_cleanup() frees all B<ASN1_STRING_TABLE> items added
by ASN1_STRING_TABLE_add().
@@ -45,7 +45,7 @@ by ASN1_STRING_TABLE_add().
ASN1_STRING_TABLE_add() returns 1 on success, 0 if an error occurred.
ASN1_STRING_TABLE_get() returns a valid B<ASN1_STRING_TABLE> structure
-or B<NULL> if nothing is found.
+or NULL if nothing is found.
ASN1_STRING_TABLE_cleanup() does not return a value.
@@ -55,9 +55,9 @@ L<ERR_get_error(3)>
=head1 COPYRIGHT
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ASN1_STRING_length.pod b/doc/man3/ASN1_STRING_length.pod
index ab109c2ede78..909a3af1cad3 100644
--- a/doc/man3/ASN1_STRING_length.pod
+++ b/doc/man3/ASN1_STRING_length.pod
@@ -11,10 +11,10 @@ ASN1_STRING_to_UTF8 - ASN1_STRING utility functions
#include <openssl/asn1.h>
int ASN1_STRING_length(ASN1_STRING *x);
- const unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x);
- unsigned char * ASN1_STRING_data(ASN1_STRING *x);
+ const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x);
+ unsigned char *ASN1_STRING_data(ASN1_STRING *x);
- ASN1_STRING * ASN1_STRING_dup(ASN1_STRING *a);
+ ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *a);
int ASN1_STRING_cmp(ASN1_STRING *a, ASN1_STRING *b);
@@ -28,9 +28,9 @@ ASN1_STRING_to_UTF8 - ASN1_STRING utility functions
These functions allow an B<ASN1_STRING> structure to be manipulated.
-ASN1_STRING_length() returns the length of the content of B<x>.
+ASN1_STRING_length() returns the length of the content of I<x>.
-ASN1_STRING_get0_data() returns an internal pointer to the data of B<x>.
+ASN1_STRING_get0_data() returns an internal pointer to the data of I<x>.
Since this is an internal pointer it should B<not> be freed or
modified in any way.
@@ -38,21 +38,21 @@ ASN1_STRING_data() is similar to ASN1_STRING_get0_data() except the
returned value is not constant. This function is deprecated:
applications should use ASN1_STRING_get0_data() instead.
-ASN1_STRING_dup() returns a copy of the structure B<a>.
+ASN1_STRING_dup() returns a copy of the structure I<a>.
-ASN1_STRING_cmp() compares B<a> and B<b> returning 0 if the two
+ASN1_STRING_cmp() compares I<a> and I<b> returning 0 if the two
are identical. The string types and content are compared.
-ASN1_STRING_set() sets the data of string B<str> to the buffer
-B<data> or length B<len>. The supplied data is copied. If B<len>
+ASN1_STRING_set() sets the data of string I<str> to the buffer
+I<data> or length I<len>. The supplied data is copied. If I<len>
is -1 then the length is determined by strlen(data).
-ASN1_STRING_type() returns the type of B<x>, using standard constants
+ASN1_STRING_type() returns the type of I<x>, using standard constants
such as B<V_ASN1_OCTET_STRING>.
-ASN1_STRING_to_UTF8() converts the string B<in> to UTF8 format, the
-converted data is allocated in a buffer in B<*out>. The length of
-B<out> is returned or a negative error code. The buffer B<*out>
+ASN1_STRING_to_UTF8() converts the string I<in> to UTF8 format, the
+converted data is allocated in a buffer in I<*out>. The length of
+I<out> is returned or a negative error code. The buffer I<*out>
should be freed using OPENSSL_free().
=head1 NOTES
@@ -79,22 +79,22 @@ when calling ASN1_STRING_set().
=head1 RETURN VALUES
-ASN1_STRING_length() returns the length of the content of B<x>.
+ASN1_STRING_length() returns the length of the content of I<x>.
ASN1_STRING_get0_data() and ASN1_STRING_data() return an internal pointer to
-the data of B<x>.
+the data of I<x>.
-ASN1_STRING_dup() returns a valid B<ASN1_STRING> structure or B<NULL> if an
+ASN1_STRING_dup() returns a valid B<ASN1_STRING> structure or NULL if an
error occurred.
ASN1_STRING_cmp() returns an integer greater than, equal to, or less than 0,
-according to whether B<a> is greater than, equal to, or less than B<b>.
+according to whether I<a> is greater than, equal to, or less than I<b>.
ASN1_STRING_set() returns 1 on success or 0 on error.
-ASN1_STRING_type() returns the type of B<x>.
+ASN1_STRING_type() returns the type of I<x>.
-ASN1_STRING_to_UTF8() returns the number of bytes in output string B<out> or a
+ASN1_STRING_to_UTF8() returns the number of bytes in output string I<out> or a
negative value if an error occurred.
=head1 SEE ALSO
@@ -105,7 +105,7 @@ L<ERR_get_error(3)>
Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ASN1_STRING_new.pod b/doc/man3/ASN1_STRING_new.pod
index 7bd2fc19210b..ff20de73b7b9 100644
--- a/doc/man3/ASN1_STRING_new.pod
+++ b/doc/man3/ASN1_STRING_new.pod
@@ -9,8 +9,8 @@ ASN1_STRING allocation functions
#include <openssl/asn1.h>
- ASN1_STRING * ASN1_STRING_new(void);
- ASN1_STRING * ASN1_STRING_type_new(int type);
+ ASN1_STRING *ASN1_STRING_new(void);
+ ASN1_STRING *ASN1_STRING_type_new(int type);
void ASN1_STRING_free(ASN1_STRING *a);
=head1 DESCRIPTION
@@ -19,10 +19,10 @@ ASN1_STRING_new() returns an allocated B<ASN1_STRING> structure. Its type
is undefined.
ASN1_STRING_type_new() returns an allocated B<ASN1_STRING> structure of
-type B<type>.
+type I<type>.
-ASN1_STRING_free() frees up B<a>.
-If B<a> is NULL nothing is done.
+ASN1_STRING_free() frees up I<a>.
+If I<a> is NULL nothing is done.
=head1 NOTES
@@ -32,7 +32,7 @@ ASN1_OCTET_STRING_new() calls ASN1_STRING_type(V_ASN1_OCTET_STRING).
=head1 RETURN VALUES
ASN1_STRING_new() and ASN1_STRING_type_new() return a valid
-ASN1_STRING structure or B<NULL> if an error occurred.
+B<ASN1_STRING> structure or NULL if an error occurred.
ASN1_STRING_free() does not return a value.
@@ -42,9 +42,9 @@ L<ERR_get_error(3)>
=head1 COPYRIGHT
-Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ASN1_STRING_print_ex.pod b/doc/man3/ASN1_STRING_print_ex.pod
index f0b70e836e9d..0ff03d798d24 100644
--- a/doc/man3/ASN1_STRING_print_ex.pod
+++ b/doc/man3/ASN1_STRING_print_ex.pod
@@ -20,15 +20,15 @@ ASN1_tag2str, ASN1_STRING_print_ex, ASN1_STRING_print_ex_fp, ASN1_STRING_print
These functions output an B<ASN1_STRING> structure. B<ASN1_STRING> is used to
represent all the ASN1 string types.
-ASN1_STRING_print_ex() outputs B<str> to B<out>, the format is determined by
-the options B<flags>. ASN1_STRING_print_ex_fp() is identical except it outputs
-to B<fp> instead.
+ASN1_STRING_print_ex() outputs I<str> to I<out>, the format is determined by
+the options I<flags>. ASN1_STRING_print_ex_fp() is identical except it outputs
+to I<fp> instead.
-ASN1_STRING_print() prints B<str> to B<out> but using a different format to
+ASN1_STRING_print() prints I<str> to I<out> but using a different format to
ASN1_STRING_print_ex(). It replaces unprintable characters (other than CR, LF)
with '.'.
-ASN1_tag2str() returns a human-readable name of the specified ASN.1 B<tag>.
+ASN1_tag2str() returns a human-readable name of the specified ASN.1 I<tag>.
=head1 NOTES
@@ -38,7 +38,7 @@ ASN1_STRING_print_ex() instead.
Although there are a large number of options frequently B<ASN1_STRFLGS_RFC2253> is
suitable, or on UTF8 terminals B<ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB>.
-The complete set of supported options for B<flags> is listed below.
+The complete set of supported options for I<flags> is listed below.
Various characters can be escaped. If B<ASN1_STRFLGS_ESC_2253> is set the characters
determined by RFC2253 are escaped. If B<ASN1_STRFLGS_ESC_CTRL> is set control
@@ -96,7 +96,7 @@ characters written or -1 if an error occurred.
ASN1_STRING_print() returns 1 on success or 0 on error.
-ASN1_tag2str() returns a human-readable name of the specified ASN.1 B<tag>.
+ASN1_tag2str() returns a human-readable name of the specified ASN.1 I<tag>.
=head1 SEE ALSO
@@ -107,7 +107,7 @@ L<ASN1_tag2str(3)>
Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ASN1_TIME_set.pod b/doc/man3/ASN1_TIME_set.pod
index 584ae232acf6..66d9fefe1af6 100644
--- a/doc/man3/ASN1_TIME_set.pod
+++ b/doc/man3/ASN1_TIME_set.pod
@@ -9,11 +9,12 @@ ASN1_TIME_set_string, ASN1_UTCTIME_set_string, ASN1_GENERALIZEDTIME_set_string,
ASN1_TIME_set_string_X509,
ASN1_TIME_normalize,
ASN1_TIME_to_tm,
-ASN1_TIME_print, ASN1_UTCTIME_print, ASN1_GENERALIZEDTIME_print,
+ASN1_TIME_print, ASN1_TIME_print_ex, ASN1_UTCTIME_print, ASN1_GENERALIZEDTIME_print,
ASN1_TIME_diff,
ASN1_TIME_cmp_time_t, ASN1_UTCTIME_cmp_time_t,
ASN1_TIME_compare,
-ASN1_TIME_to_generalizedtime - ASN.1 Time functions
+ASN1_TIME_to_generalizedtime,
+ASN1_TIME_dup, ASN1_UTCTIME_dup, ASN1_GENERALIZEDTIME_dup - ASN.1 Time functions
=head1 SYNOPSIS
@@ -43,6 +44,7 @@ ASN1_TIME_to_generalizedtime - ASN.1 Time functions
int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *t);
int ASN1_TIME_print(BIO *b, const ASN1_TIME *s);
+ int ASN1_TIME_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags);
int ASN1_UTCTIME_print(BIO *b, const ASN1_UTCTIME *s);
int ASN1_GENERALIZEDTIME_print(BIO *b, const ASN1_GENERALIZEDTIME *s);
@@ -58,138 +60,156 @@ ASN1_TIME_to_generalizedtime - ASN.1 Time functions
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
ASN1_GENERALIZEDTIME **out);
+ ASN1_TIME *ASN1_TIME_dup(const ASN1_TIME *t);
+ ASN1_UTCTIME *ASN1_UTCTIME_dup(const ASN1_UTCTIME *t);
+ ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_dup(const ASN1_GENERALIZEDTIME *t);
+
=head1 DESCRIPTION
The ASN1_TIME_set(), ASN1_UTCTIME_set() and ASN1_GENERALIZEDTIME_set()
-functions set the structure B<s> to the time represented by the time_t
-value B<t>. If B<s> is NULL a new time structure is allocated and returned.
+functions set the structure I<s> to the time represented by the time_t
+value I<t>. If I<s> is NULL a new time structure is allocated and returned.
The ASN1_TIME_adj(), ASN1_UTCTIME_adj() and ASN1_GENERALIZEDTIME_adj()
-functions set the time structure B<s> to the time represented
-by the time B<offset_day> and B<offset_sec> after the time_t value B<t>.
-The values of B<offset_day> or B<offset_sec> can be negative to set a
-time before B<t>. The B<offset_sec> value can also exceed the number of
-seconds in a day. If B<s> is NULL a new structure is allocated
+functions set the time structure I<s> to the time represented
+by the time I<offset_day> and I<offset_sec> after the time_t value I<t>.
+The values of I<offset_day> or I<offset_sec> can be negative to set a
+time before I<t>. The I<offset_sec> value can also exceed the number of
+seconds in a day. If I<s> is NULL a new structure is allocated
and returned.
The ASN1_TIME_set_string(), ASN1_UTCTIME_set_string() and
-ASN1_GENERALIZEDTIME_set_string() functions set the time structure B<s>
-to the time represented by string B<str> which must be in appropriate ASN.1
-time format (for example YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ). If B<s> is NULL
-this function performs a format check on B<str> only. The string B<str>
-is copied into B<s>.
-
-ASN1_TIME_set_string_X509() sets ASN1_TIME structure B<s> to the time
-represented by string B<str> which must be in appropriate time format
+ASN1_GENERALIZEDTIME_set_string() functions set the time structure I<s>
+to the time represented by string I<str> which must be in appropriate ASN.1
+time format (for example YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ). If I<s> is NULL
+this function performs a format check on I<str> only. The string I<str>
+is copied into I<s>.
+
+ASN1_TIME_set_string_X509() sets B<ASN1_TIME> structure I<s> to the time
+represented by string I<str> which must be in appropriate time format
that RFC 5280 requires, which means it only allows YYMMDDHHMMSSZ and
YYYYMMDDHHMMSSZ (leap second is rejected), all other ASN.1 time format
-are not allowed. If B<s> is NULL this function performs a format check
-on B<str> only.
+are not allowed. If I<s> is NULL this function performs a format check
+on I<str> only.
-The ASN1_TIME_normalize() function converts an ASN1_GENERALIZEDTIME or
-ASN1_UTCTIME into a time value that can be used in a certificate. It
+The ASN1_TIME_normalize() function converts an B<ASN1_GENERALIZEDTIME> or
+B<ASN1_UTCTIME> into a time value that can be used in a certificate. It
should be used after the ASN1_TIME_set_string() functions and before
ASN1_TIME_print() functions to get consistent (i.e. GMT) results.
The ASN1_TIME_check(), ASN1_UTCTIME_check() and ASN1_GENERALIZEDTIME_check()
-functions check the syntax of the time structure B<s>.
+functions check the syntax of the time structure I<s>.
The ASN1_TIME_print(), ASN1_UTCTIME_print() and ASN1_GENERALIZEDTIME_print()
-functions print the time structure B<s> to BIO B<b> in human readable
+functions print the time structure I<s> to BIO I<b> in human readable
format. It will be of the format MMM DD HH:MM:SS YYYY [GMT], for example
-"Feb 3 00:55:52 2015 GMT" it does not include a newline. If the time
-structure has invalid format it prints out "Bad time value" and returns
-an error. The output for generalized time may include a fractional part
+"Feb 3 00:55:52 2015 GMT", which does not include a newline.
+If the time structure has invalid format it prints out "Bad time value" and
+returns an error. The output for generalized time may include a fractional part
following the second.
-ASN1_TIME_to_tm() converts the time B<s> to the standard B<tm> structure.
-If B<s> is NULL, then the current time is converted. The output time is GMT.
-The B<tm_sec>, B<tm_min>, B<tm_hour>, B<tm_mday>, B<tm_wday>, B<tm_yday>,
-B<tm_mon> and B<tm_year> fields of B<tm> structure are set to proper values,
-whereas all other fields are set to 0. If B<tm> is NULL this function performs
-a format check on B<s> only. If B<s> is in Generalized format with fractional
+ASN1_TIME_print_ex() provides I<flags> to specify the output format of the
+datetime. This can be either B<ASN1_DTFLGS_RFC822> or B<ASN1_DTFLGS_ISO8601>.
+
+ASN1_TIME_to_tm() converts the time I<s> to the standard I<tm> structure.
+If I<s> is NULL, then the current time is converted. The output time is GMT.
+The I<tm_sec>, I<tm_min>, I<tm_hour>, I<tm_mday>, I<tm_wday>, I<tm_yday>,
+I<tm_mon> and I<tm_year> fields of I<tm> structure are set to proper values,
+whereas all other fields are set to 0. If I<tm> is NULL this function performs
+a format check on I<s> only. If I<s> is in Generalized format with fractional
seconds, e.g. YYYYMMDDHHMMSS.SSSZ, the fractional seconds will be lost while
-converting B<s> to B<tm> structure.
-
-ASN1_TIME_diff() sets B<*pday> and B<*psec> to the time difference between
-B<from> and B<to>. If B<to> represents a time later than B<from> then
-one or both (depending on the time difference) of B<*pday> and B<*psec>
-will be positive. If B<to> represents a time earlier than B<from> then
-one or both of B<*pday> and B<*psec> will be negative. If B<to> and B<from>
-represent the same time then B<*pday> and B<*psec> will both be zero.
-If both B<*pday> and B<*psec> are nonzero they will always have the same
-sign. The value of B<*psec> will always be less than the number of seconds
-in a day. If B<from> or B<to> is NULL the current time is used.
+converting I<s> to I<tm> structure.
+
+ASN1_TIME_diff() sets I<*pday> and I<*psec> to the time difference between
+I<from> and I<to>. If I<to> represents a time later than I<from> then
+one or both (depending on the time difference) of I<*pday> and I<*psec>
+will be positive. If I<to> represents a time earlier than I<from> then
+one or both of I<*pday> and I<*psec> will be negative. If I<to> and I<from>
+represent the same time then I<*pday> and I<*psec> will both be zero.
+If both I<*pday> and I<*psec> are nonzero they will always have the same
+sign. The value of I<*psec> will always be less than the number of seconds
+in a day. If I<from> or I<to> is NULL the current time is used.
The ASN1_TIME_cmp_time_t() and ASN1_UTCTIME_cmp_time_t() functions compare
-the two times represented by the time structure B<s> and the time_t B<t>.
+the two times represented by the time structure I<s> and the time_t I<t>.
The ASN1_TIME_compare() function compares the two times represented by the
-time structures B<a> and B<b>.
+time structures I<a> and I<b>.
-The ASN1_TIME_to_generalizedtime() function converts an ASN1_TIME to an
-ASN1_GENERALIZEDTIME, regardless of year. If either B<out> or
-B<*out> are NULL, then a new object is allocated and must be freed after use.
+The ASN1_TIME_to_generalizedtime() function converts an B<ASN1_TIME> to an
+B<ASN1_GENERALIZEDTIME>, regardless of year. If either I<out> or
+I<*out> are NULL, then a new object is allocated and must be freed after use.
+
+The ASN1_TIME_dup(), ASN1_UTCTIME_dup() and ASN1_GENERALIZEDTIME_dup() functions
+duplicate the time structure I<t> and return the duplicated result
+correspondingly.
=head1 NOTES
-The ASN1_TIME structure corresponds to the ASN.1 structure B<Time>
+The B<ASN1_TIME> structure corresponds to the ASN.1 structure B<Time>
defined in RFC5280 et al. The time setting functions obey the rules outlined
in RFC5280: if the date can be represented by UTCTime it is used, else
GeneralizedTime is used.
-The ASN1_TIME, ASN1_UTCTIME and ASN1_GENERALIZEDTIME structures are represented
-as an ASN1_STRING internally and can be freed up using ASN1_STRING_free().
+The B<ASN1_TIME>, B<ASN1_UTCTIME> and B<ASN1_GENERALIZEDTIME> structures are
+represented as an B<ASN1_STRING> internally and can be freed up using
+ASN1_STRING_free().
-The ASN1_TIME structure can represent years from 0000 to 9999 but no attempt
+The B<ASN1_TIME> structure can represent years from 0000 to 9999 but no attempt
is made to correct ancient calendar changes (for example from Julian to
Gregorian calendars).
-ASN1_UTCTIME is limited to a year range of 1950 through 2049.
+B<ASN1_UTCTIME> is limited to a year range of 1950 through 2049.
Some applications add offset times directly to a time_t value and pass the
results to ASN1_TIME_set() (or equivalent). This can cause problems as the
time_t value can overflow on some systems resulting in unexpected results.
New applications should use ASN1_TIME_adj() instead and pass the offset value
-in the B<offset_sec> and B<offset_day> parameters instead of directly
+in the I<offset_sec> and I<offset_day> parameters instead of directly
manipulating a time_t value.
-ASN1_TIME_adj() may change the type from ASN1_GENERALIZEDTIME to ASN1_UTCTIME,
-or vice versa, based on the resulting year. The ASN1_GENERALIZEDTIME_adj() and
-ASN1_UTCTIME_adj() functions will not modify the type of the return structure.
+ASN1_TIME_adj() may change the type from B<ASN1_GENERALIZEDTIME> to
+B<ASN1_UTCTIME>, or vice versa, based on the resulting year.
+ASN1_GENERALIZEDTIME_adj() and ASN1_UTCTIME_adj() will not modify the type
+of the return structure.
-It is recommended that functions starting with ASN1_TIME be used instead of
-those starting with ASN1_UTCTIME or ASN1_GENERALIZEDTIME. The functions
-starting with ASN1_UTCTIME and ASN1_GENERALIZEDTIME act only on that specific
-time format. The functions starting with ASN1_TIME will operate on either
-format.
+It is recommended that functions starting with B<ASN1_TIME> be used instead of
+those starting with B<ASN1_UTCTIME> or B<ASN1_GENERALIZEDTIME>. The functions
+starting with B<ASN1_UTCTIME> and B<ASN1_GENERALIZEDTIME> act only on that
+specific time format. The functions starting with B<ASN1_TIME> will operate on
+either format.
=head1 BUGS
-ASN1_TIME_print(), ASN1_UTCTIME_print() and ASN1_GENERALIZEDTIME_print()
-do not print out the timezone: it either prints out "GMT" or nothing. But all
+ASN1_TIME_print(), ASN1_UTCTIME_print() and ASN1_GENERALIZEDTIME_print() do
+not print out the timezone: it either prints out "GMT" or nothing. But all
certificates complying with RFC5280 et al use GMT anyway.
+ASN1_TIME_print(), ASN1_TIME_print_ex(), ASN1_UTCTIME_print() and
+ASN1_GENERALIZEDTIME_print() do not distinguish if they fail because
+of an I/O error or invalid time format.
+
Use the ASN1_TIME_normalize() function to normalize the time value before
printing to get GMT results.
=head1 RETURN VALUES
-ASN1_TIME_set(), ASN1_UTCTIME_set(), ASN1_GENERALIZEDTIME_set(), ASN1_TIME_adj(),
-ASN1_UTCTIME_adj and ASN1_GENERALIZEDTIME_set return a pointer to a time structure
-or NULL if an error occurred.
+ASN1_TIME_set(), ASN1_UTCTIME_set(), ASN1_GENERALIZEDTIME_set(),
+ASN1_TIME_adj(), ASN1_UTCTIME_adj() and ASN1_GENERALIZEDTIME_set() return
+a pointer to a time structure or NULL if an error occurred.
-ASN1_TIME_set_string(), ASN1_UTCTIME_set_string(), ASN1_GENERALIZEDTIME_set_string()
-ASN1_TIME_set_string_X509() return 1 if the time value is successfully set and 0 otherwise.
+ASN1_TIME_set_string(), ASN1_UTCTIME_set_string(),
+ASN1_GENERALIZEDTIME_set_string() and ASN1_TIME_set_string_X509() return
+1 if the time value is successfully set and 0 otherwise.
ASN1_TIME_normalize() returns 1 on success, and 0 on error.
ASN1_TIME_check(), ASN1_UTCTIME_check and ASN1_GENERALIZEDTIME_check() return 1
if the structure is syntactically correct and 0 otherwise.
-ASN1_TIME_print(), ASN1_UTCTIME_print() and ASN1_GENERALIZEDTIME_print() return 1
-if the time is successfully printed out and 0 if an error occurred (I/O error or
-invalid time format).
+ASN1_TIME_print(), ASN1_UTCTIME_print() and ASN1_GENERALIZEDTIME_print()
+return 1 if the time is successfully printed out and
+0 if an I/O error occurred an error occurred (I/O error or invalid time format).
ASN1_TIME_to_tm() returns 1 if the time is successfully parsed and 0 if an
error occurred (invalid time format).
@@ -197,14 +217,18 @@ error occurred (invalid time format).
ASN1_TIME_diff() returns 1 for success and 0 for failure. It can fail if the
passed-in time structure has invalid syntax, for example.
-ASN1_TIME_cmp_time_t() and ASN1_UTCTIME_cmp_time_t() return -1 if B<s> is
-before B<t>, 0 if B<s> equals B<t>, or 1 if B<s> is after B<t>. -2 is returned
+ASN1_TIME_cmp_time_t() and ASN1_UTCTIME_cmp_time_t() return -1 if I<s> is
+before I<t>, 0 if I<s> equals I<t>, or 1 if I<s> is after I<t>. -2 is returned
on error.
-ASN1_TIME_compare() returns -1 if B<a> is before B<b>, 0 if B<a> equals B<b>, or 1 if B<a> is after B<b>. -2 is returned on error.
+ASN1_TIME_compare() returns -1 if I<a> is before I<b>, 0 if I<a> equals I<b>,
+or 1 if I<a> is after I<b>. -2 is returned on error.
+
+ASN1_TIME_to_generalizedtime() returns a pointer to the appropriate time
+structure on success or NULL if an error occurred.
-ASN1_TIME_to_generalizedtime() returns a pointer to
-the appropriate time structure on success or NULL if an error occurred.
+ASN1_TIME_dup(), ASN1_UTCTIME_dup() and ASN1_GENERALIZEDTIME_dup() return a
+pointer to a time structure or NULL if an error occurred.
=head1 EXAMPLES
@@ -248,9 +272,9 @@ The ASN1_TIME_compare() function was added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ASN1_TYPE_get.pod b/doc/man3/ASN1_TYPE_get.pod
index f14850b39f59..9bfb5a76d479 100644
--- a/doc/man3/ASN1_TYPE_get.pod
+++ b/doc/man3/ASN1_TYPE_get.pod
@@ -20,44 +20,45 @@ functions
=head1 DESCRIPTION
-These functions allow an ASN1_TYPE structure to be manipulated. The
-ASN1_TYPE structure can contain any ASN.1 type or constructed type
+These functions allow an B<ASN1_TYPE> structure to be manipulated. The
+B<ASN1_TYPE> structure can contain any ASN.1 type or constructed type
such as a SEQUENCE: it is effectively equivalent to the ASN.1 ANY type.
-ASN1_TYPE_get() returns the type of B<a>.
+ASN1_TYPE_get() returns the type of I<a> or 0 if it fails.
-ASN1_TYPE_set() sets the value of B<a> to B<type> and B<value>. This
-function uses the pointer B<value> internally so it must B<not> be freed
+ASN1_TYPE_set() sets the value of I<a> to I<type> and I<value>. This
+function uses the pointer I<value> internally so it must B<not> be freed
up after the call.
-ASN1_TYPE_set1() sets the value of B<a> to B<type> a copy of B<value>.
+ASN1_TYPE_set1() sets the value of I<a> to I<type> a copy of I<value>.
-ASN1_TYPE_cmp() compares ASN.1 types B<a> and B<b> and returns 0 if
+ASN1_TYPE_cmp() compares ASN.1 types I<a> and I<b> and returns 0 if
they are identical and nonzero otherwise.
ASN1_TYPE_unpack_sequence() attempts to parse the SEQUENCE present in
-B<t> using the ASN.1 structure B<it>. If successful it returns a pointer
-to the ASN.1 structure corresponding to B<it> which must be freed by the
+I<t> using the ASN.1 structure I<it>. If successful it returns a pointer
+to the ASN.1 structure corresponding to I<it> which must be freed by the
caller. If it fails it return NULL.
-ASN1_TYPE_pack_sequence() attempts to encode the ASN.1 structure B<s>
-corresponding to B<it> into an ASN1_TYPE. If successful the encoded
-ASN1_TYPE is returned. If B<t> and B<*t> are not NULL the encoded type
-is written to B<t> overwriting any existing data. If B<t> is not NULL
-but B<*t> is NULL the returned ASN1_TYPE is written to B<*t>.
+ASN1_TYPE_pack_sequence() attempts to encode the ASN.1 structure I<s>
+corresponding to I<it> into an B<ASN1_TYPE>. If successful the encoded
+B<ASN1_TYPE> is returned. If I<t> and I<*t> are not NULL the encoded type
+is written to I<t> overwriting any existing data. If I<t> is not NULL
+but I<*t> is NULL the returned B<ASN1_TYPE> is written to I<*t>.
=head1 NOTES
-The type and meaning of the B<value> parameter for ASN1_TYPE_set() and
-ASN1_TYPE_set1() is determined by the B<type> parameter.
-If B<type> is V_ASN1_NULL B<value> is ignored. If B<type> is V_ASN1_BOOLEAN
-then the boolean is set to TRUE if B<value> is not NULL. If B<type> is
-V_ASN1_OBJECT then value is an ASN1_OBJECT structure. Otherwise B<type>
-is and ASN1_STRING structure. If B<type> corresponds to a primitive type
-(or a string type) then the contents of the ASN1_STRING contain the content
-octets of the type. If B<type> corresponds to a constructed type or
-a tagged type (V_ASN1_SEQUENCE, V_ASN1_SET or V_ASN1_OTHER) then the
-ASN1_STRING contains the entire ASN.1 encoding verbatim (including tag and
+The type and meaning of the I<value> parameter for ASN1_TYPE_set() and
+ASN1_TYPE_set1() is determined by the I<type> parameter.
+If I<type> is B<V_ASN1_NULL> I<value> is ignored. If I<type> is
+B<V_ASN1_BOOLEAN>
+then the boolean is set to TRUE if I<value> is not NULL. If I<type> is
+B<V_ASN1_OBJECT> then value is an B<ASN1_OBJECT> structure. Otherwise I<type>
+is and B<ASN1_STRING> structure. If I<type> corresponds to a primitive type
+(or a string type) then the contents of the B<ASN1_STRING> contain the content
+octets of the type. If I<type> corresponds to a constructed type or
+a tagged type (B<V_ASN1_SEQUENCE>, B<V_ASN1_SET> or B<V_ASN1_OTHER>) then the
+B<ASN1_STRING> contains the entire ASN.1 encoding verbatim (including tag and
length octets).
ASN1_TYPE_cmp() may not return zero if two types are equivalent but have
@@ -74,7 +75,7 @@ applications should handle the case of two absent values separately.
=head1 RETURN VALUES
-ASN1_TYPE_get() returns the type of the ASN1_TYPE argument.
+ASN1_TYPE_get() returns the type of the B<ASN1_TYPE> argument.
ASN1_TYPE_set() does not return a value.
@@ -85,14 +86,14 @@ ASN1_TYPE_cmp() returns 0 if the types are identical and nonzero otherwise.
ASN1_TYPE_unpack_sequence() returns a pointer to an ASN.1 structure or
NULL on failure.
-ASN1_TYPE_pack_sequence() return an ASN1_TYPE structure if it succeeds or
+ASN1_TYPE_pack_sequence() return an B<ASN1_TYPE> structure if it succeeds or
NULL on failure.
=head1 COPYRIGHT
-Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ASN1_aux_cb.pod b/doc/man3/ASN1_aux_cb.pod
new file mode 100644
index 000000000000..12f7ddf82d64
--- /dev/null
+++ b/doc/man3/ASN1_aux_cb.pod
@@ -0,0 +1,284 @@
+=pod
+
+=head1 NAME
+
+ASN1_AUX, ASN1_PRINT_ARG, ASN1_STREAM_ARG, ASN1_aux_cb, ASN1_aux_const_cb
+- ASN.1 auxilliary data
+
+=head1 SYNOPSIS
+
+ #include <openssl/asn1t.h>
+
+ struct ASN1_AUX_st {
+ void *app_data;
+ int flags;
+ int ref_offset; /* Offset of reference value */
+ int ref_lock; /* Offset to an CRYPTO_RWLOCK */
+ ASN1_aux_cb *asn1_cb;
+ int enc_offset; /* Offset of ASN1_ENCODING structure */
+ ASN1_aux_const_cb *asn1_const_cb; /* for ASN1_OP_I2D_ and ASN1_OP_PRINT_ */
+ };
+ typedef struct ASN1_AUX_st ASN1_AUX;
+
+ struct ASN1_PRINT_ARG_st {
+ BIO *out;
+ int indent;
+ const ASN1_PCTX *pctx;
+ };
+ typedef struct ASN1_PRINT_ARG_st ASN1_PRINT_ARG;
+
+ struct ASN1_STREAM_ARG_st {
+ BIO *out;
+ BIO *ndef_bio;
+ unsigned char **boundary;
+ };
+ typedef struct ASN1_STREAM_ARG_st ASN1_STREAM_ARG;
+
+ typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it,
+ void *exarg);
+ typedef int ASN1_aux_const_cb(int operation, const ASN1_VALUE **in,
+ const ASN1_ITEM *it, void *exarg);
+
+=head1 DESCRIPTION
+
+ASN.1 data structures can be associated with an B<ASN1_AUX> object to supply
+additional information about the ASN.1 structure. An B<ASN1_AUX> structure is
+associated with the structure during the definition of the ASN.1 template. For
+example an B<ASN1_AUX> structure will be associated by using one of the various
+ASN.1 template definition macros that supply auxilliary information such as
+ASN1_SEQUENCE_enc(), ASN1_SEQUENCE_ref(), ASN1_SEQUENCE_cb_const_cb(),
+ASN1_SEQUENCE_const_cb(), ASN1_SEQUENCE_cb() or ASN1_NDEF_SEQUENCE_cb().
+
+An B<ASN1_AUX> structure contains the following information.
+
+=over 4
+
+=item I<app_data>
+
+Arbitrary application data
+
+=item I<flags>
+
+Flags which indicate the auxiliarly functionality supported.
+
+The B<ASN1_AFLG_REFCOUNT> flag indicates that objects support reference counting.
+
+The B<ASN1_AFLG_ENCODING> flag indicates that the original encoding of the
+object will be saved.
+
+The B<ASN1_AFLG_BROKEN> flag is a work around for broken encoders where the
+sequence length value may not be correct. This should generally not be used.
+
+The B<ASN1_AFLG_CONST_CB> flag indicates that the "const" form of the
+B<ASN1_AUX> callback should be used in preference to the non-const form.
+
+=item I<ref_offset>
+
+If the B<ASN1_AFLG_REFCOUNT> flag is set then this value is assumed to be an
+offset into the B<ASN1_VALUE> structure where a B<CRYPTO_REF_COUNT> may be
+found for the purposes of reference counting.
+
+=item I<ref_lock>
+
+If the B<ASN1_AFLG_REFCOUNT> flag is set then this value is assumed to be an
+offset into the B<ASN1_VALUE> structure where a B<CRYPTO_RWLOCK> may be
+found for the purposes of reference counting.
+
+=item I<asn1_cb>
+
+A callback that will be invoked at various points during the processing of
+the the B<ASN1_VALLUE>. See below for further details.
+
+=item I<enc_offset>
+
+Offset into the B<ASN1_VALUE> object where the original encoding of the object
+will be saved if the B<ASN1_AFLG_ENCODING> flag has been set.
+
+=item I<asn1_const_cb>
+
+A callback that will be invoked at various points during the processing of
+the the B<ASN1_VALLUE>. This is used in preference to the I<asn1_cb> callback if
+the B<ASN1_AFLG_CONST_CB> flag is set. See below for further details.
+
+=back
+
+During the processing of an B<ASN1_VALUE> object the callbacks set via
+I<asn1_cb> or I<asn1_const_cb> will be invoked as a result of various events
+indicated via the I<operation> parameter. The value of I<*in> will be the
+B<ASN1_VALUE> object being processed based on the template in I<it>. An
+additional operation specific parameter may be passed in I<exarg>. The currently
+supported operations are as follows. The callbacks should return a positive
+value on success or zero on error, unless otherwise noted below.
+
+=over 4
+
+=item B<ASN1_OP_NEW_PRE>
+
+Invoked when processing a B<CHOICE>, B<SEQUENCE> or B<NDEF_SEQUENCE> structure
+prior to an B<ASN1_VALUE> object being allocated. The callback may allocate the
+B<ASN1_VALUE> itself and store it in I<*pval>. If it does so it should return 2
+from the callback. On error it should return 0.
+
+=item B<ASN1_OP_NEW_POST>
+
+Invoked when processing a B<CHOICE>, B<SEQUENCE> or B<NDEF_SEQUENCE> structure
+after an B<ASN1_VALUE> object has been allocated. The allocated object is in
+I<*pval>.
+
+=item B<ASN1_OP_FREE_PRE>
+
+Invoked when processing a B<CHOICE>, B<SEQUENCE> or B<NDEF_SEQUENCE> structure
+immediately before an B<ASN1_VALUE> is freed. If the callback originally
+constructed the B<ASN1_VALUE> via B<ASN1_OP_NEW_PRE> then it should free it at
+this point and return 2 from the callback. Otherwise it should return 1 for
+success or 0 on error.
+
+=item B<ASN1_OP_FREE_POST>
+
+Invoked when processing a B<CHOICE>, B<SEQUENCE> or B<NDEF_SEQUENCE> structure
+immediately after B<ASN1_VALUE> sub-structures are freed.
+
+=item B<ASN1_OP_D2I_PRE>
+
+Invoked when processing a B<CHOICE>, B<SEQUENCE> or B<NDEF_SEQUENCE> structure
+immediately before a "d2i" operation for the B<ASN1_VALUE>.
+
+=item B<ASN1_OP_D2I_POST>
+
+Invoked when processing a B<CHOICE>, B<SEQUENCE> or B<NDEF_SEQUENCE> structure
+immediately after a "d2i" operation for the B<ASN1_VALUE>.
+
+=item B<ASN1_OP_I2D_PRE>
+
+Invoked when processing a B<CHOICE>, B<SEQUENCE> or B<NDEF_SEQUENCE> structure
+immediately before a "i2d" operation for the B<ASN1_VALUE>.
+
+=item B<ASN1_OP_I2D_POST>
+
+Invoked when processing a B<CHOICE>, B<SEQUENCE> or B<NDEF_SEQUENCE> structure
+immediately after a "i2d" operation for the B<ASN1_VALUE>.
+
+=item B<ASN1_OP_PRINT_PRE>
+
+Invoked when processing a B<SEQUENCE> or B<NDEF_SEQUENCE> structure immediately
+before printing the B<ASN1_VALUE>. The I<exarg> argument will be a pointer to an
+B<ASN1_PRINT_ARG> structure (see below).
+
+=item B<ASN1_OP_PRINT_POST>
+
+Invoked when processing a B<SEQUENCE> or B<NDEF_SEQUENCE> structure immediately
+after printing the B<ASN1_VALUE>. The I<exarg> argument will be a pointer to an
+B<ASN1_PRINT_ARG> structure (see below).
+
+=item B<ASN1_OP_STREAM_PRE>
+
+Invoked immediately prior to streaming the B<ASN1_VALUE> data using indefinite
+length encoding. The I<exarg> argument will be a pointer to a B<ASN1_STREAM_ARG>
+structure (see below).
+
+=item B<ASN1_OP_STREAM_POST>
+
+Invoked immediately after streaming the B<ASN1_VALUE> data using indefinite
+length encoding. The I<exarg> argument will be a pointer to a B<ASN1_STREAM_ARG>
+structure (see below).
+
+=item B<ASN1_OP_DETACHED_PRE>
+
+Invoked immediately prior to processing the B<ASN1_VALUE> data as a "detached"
+value (as used in CMS and PKCS7). The I<exarg> argument will be a pointer to a
+B<ASN1_STREAM_ARG> structure (see below).
+
+=item B<ASN1_OP_DETACHED_POST>
+
+Invoked immediately after processing the B<ASN1_VALUE> data as a "detached"
+value (as used in CMS and PKCS7). The I<exarg> argument will be a pointer to a
+B<ASN1_STREAM_ARG> structure (see below).
+
+=item B<ASN1_OP_DUP_PRE>
+
+Invoked immediate prior to an ASN1_VALUE being duplicated via a call to
+ASN1_item_dup().
+
+=item B<ASN1_OP_DUP_POST>
+
+Invoked immediate after to an ASN1_VALUE has been duplicated via a call to
+ASN1_item_dup().
+
+=item B<ASN1_OP_GET0_LIBCTX>
+
+Invoked in order to obtain the B<OSSL_LIB_CTX> associated with an B<ASN1_VALUE>
+if any. A pointer to an B<OSSL_LIB_CTX> should be stored in I<*exarg> if such
+a value exists.
+
+=item B<ASN1_OP_GET0_PROPQ>
+
+Invoked in order to obtain the property query string associated with an
+B<ASN1_VALUE> if any. A pointer to the property query string should be stored in
+I<*exarg> if such a value exists.
+
+=back
+
+An B<ASN1_PRINT_ARG> object is used during processing of B<ASN1_OP_PRINT_PRE>
+and B<ASN1_OP_PRINT_POST> callback operations. It contains the following
+information.
+
+=over 4
+
+=item I<out>
+
+The B<BIO> being used to print the data out.
+
+=item I<ndef_bio>
+
+The current number of indent spaces that should be used for printing this data.
+
+=item I<pctx>
+
+The context for the B<ASN1_PCTX> operation.
+
+=back
+
+An B<ASN1_STREAM_ARG> object is used during processing of B<ASN1_OP_STREAM_PRE>,
+B<ASN1_OP_STREAM_POST>, B<ASN1_OP_DETACHED_PRE> and B<ASN1_OP_DETACHED_POST>
+callback operations. It contains the following information.
+
+=over 4
+
+=item I<out>
+
+The B<BIO> to stream through
+
+=item I<ndef_bio>
+
+The B<BIO> with filters appended
+
+=item I<boundary>
+
+The streaming I/O boundary.
+
+=back
+
+=head1 RETURN VALUES
+
+The callbacks return 0 on error and a positive value on success. Some operations
+require specific positive success values as noted above.
+
+=head1 SEE ALSO
+
+L<ASN1_item_new_ex(3)>
+
+=head1 HISTORY
+
+The ASN1_aux_const_cb() callback and the B<ASN1_OP_GET0_LIBCTX> and
+B<ASN1_OP_GET0_PROPQ> operation types were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/ASN1_generate_nconf.pod b/doc/man3/ASN1_generate_nconf.pod
index 422bf7b7ed3d..256ed9f99c3f 100644
--- a/doc/man3/ASN1_generate_nconf.pod
+++ b/doc/man3/ASN1_generate_nconf.pod
@@ -2,7 +2,7 @@
=head1 NAME
-ASN1_generate_nconf, ASN1_generate_v3 - ASN1 generation functions
+ASN1_generate_nconf, ASN1_generate_v3 - ASN1 string generation functions
=head1 SYNOPSIS
@@ -16,51 +16,52 @@ ASN1_generate_nconf, ASN1_generate_v3 - ASN1 generation functions
These functions generate the ASN1 encoding of a string
in an B<ASN1_TYPE> structure.
-B<str> contains the string to encode B<nconf> or B<cnf> contains
+I<str> contains the string to encode. I<nconf> or I<cnf> contains
the optional configuration information where additional strings
-will be read from. B<nconf> will typically come from a config
-file whereas B<cnf> is obtained from an B<X509V3_CTX> structure
+will be read from. I<nconf> will typically come from a config
+file whereas I<cnf> is obtained from an B<X509V3_CTX> structure,
which will typically be used by X509 v3 certificate extension
-functions. B<cnf> or B<nconf> can be set to B<NULL> if no additional
+functions. I<cnf> or I<nconf> can be set to NULL if no additional
configuration will be used.
=head1 GENERATION STRING FORMAT
-The actual data encoded is determined by the string B<str> and
+The actual data encoded is determined by the string I<str> and
the configuration information. The general format of the string
is:
=over 4
-=item B<[modifier,]type[:value]>
+=item [I<modifier>,]I<type>[:I<value>]
=back
That is zero or more comma separated modifiers followed by a type
-followed by an optional colon and a value. The formats of B<type>,
-B<value> and B<modifier> are explained below.
+followed by an optional colon and a value. The formats of I<type>,
+I<value> and I<modifier> are explained below.
=head2 Supported Types
-The supported types are listed below. Unless otherwise specified
-only the B<ASCII> format is permissible.
+The supported types are listed below.
+Case is not significant in the type names.
+Unless otherwise specified only the B<ASCII> format is permissible.
=over 4
=item B<BOOLEAN>, B<BOOL>
-This encodes a boolean type. The B<value> string is mandatory and
+This encodes a boolean type. The I<value> string is mandatory and
should be B<TRUE> or B<FALSE>. Additionally B<TRUE>, B<true>, B<Y>,
B<y>, B<YES>, B<yes>, B<FALSE>, B<false>, B<N>, B<n>, B<NO> and B<no>
are acceptable.
=item B<NULL>
-Encode the B<NULL> type, the B<value> string must not be present.
+Encode the B<NULL> type, the I<value> string must not be present.
=item B<INTEGER>, B<INT>
-Encodes an ASN1 B<INTEGER> type. The B<value> string represents
+Encodes an ASN1 B<INTEGER> type. The I<value> string represents
the value of the integer, it can be prefaced by a minus sign and
is normally interpreted as a decimal value unless the prefix B<0x>
is included.
@@ -72,7 +73,7 @@ B<INTEGER>.
=item B<OBJECT>, B<OID>
-Encodes an ASN1 B<OBJECT IDENTIFIER>, the B<value> string can be
+Encodes an ASN1 B<OBJECT IDENTIFIER>, the I<value> string can be
a short name, a long name or numerical format.
=item B<UTCTIME>, B<UTC>
@@ -87,15 +88,15 @@ the format B<YYYYMMDDHHMMSSZ>.
=item B<OCTETSTRING>, B<OCT>
-Encodes an ASN1 B<OCTET STRING>. B<value> represents the contents
+Encodes an ASN1 B<OCTET STRING>. I<value> represents the contents
of this structure, the format strings B<ASCII> and B<HEX> can be
-used to specify the format of B<value>.
+used to specify the format of I<value>.
=item B<BITSTRING>, B<BITSTR>
-Encodes an ASN1 B<BIT STRING>. B<value> represents the contents
+Encodes an ASN1 B<BIT STRING>. I<value> represents the contents
of this structure, the format strings B<ASCII>, B<HEX> and B<BITLIST>
-can be used to specify the format of B<value>.
+can be used to specify the format of I<value>.
If the format is anything other than B<BITLIST> the number of unused
bits is set to zero.
@@ -106,15 +107,15 @@ B<VISIBLE>, B<PRINTABLESTRING>, B<PRINTABLE>, B<T61>,
B<T61STRING>, B<TELETEXSTRING>, B<GeneralString>, B<NUMERICSTRING>,
B<NUMERIC>
-These encode the corresponding string types. B<value> represents the
+These encode the corresponding string types. I<value> represents the
contents of this structure. The format can be B<ASCII> or B<UTF8>.
=item B<SEQUENCE>, B<SEQ>, B<SET>
-Formats the result as an ASN1 B<SEQUENCE> or B<SET> type. B<value>
+Formats the result as an ASN1 B<SEQUENCE> or B<SET> type. I<value>
should be a section name which will contain the contents. The
field names in the section are ignored and the values are in the
-generated string format. If B<value> is absent then an empty SEQUENCE
+generated string format. If I<value> is absent then an empty SEQUENCE
will be encoded.
=back
@@ -165,7 +166,7 @@ bits are zero.
=head1 RETURN VALUES
ASN1_generate_nconf() and ASN1_generate_v3() return the encoded
-data as an B<ASN1_TYPE> structure or B<NULL> if an error occurred.
+data as an B<ASN1_TYPE> structure or NULL if an error occurred.
The error codes that can be obtained by L<ERR_get_error(3)>.
@@ -260,9 +261,9 @@ L<ERR_get_error(3)>
=head1 COPYRIGHT
-Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ASN1_item_d2i_bio.pod b/doc/man3/ASN1_item_d2i_bio.pod
new file mode 100644
index 000000000000..bdf5c48096ab
--- /dev/null
+++ b/doc/man3/ASN1_item_d2i_bio.pod
@@ -0,0 +1,88 @@
+=pod
+
+=head1 NAME
+
+ASN1_item_d2i_ex, ASN1_item_d2i, ASN1_item_d2i_bio_ex, ASN1_item_d2i_bio,
+ASN1_item_d2i_fp_ex, ASN1_item_d2i_fp, ASN1_item_i2d_mem_bio
+- decode and encode DER-encoded ASN.1 structures
+
+=head1 SYNOPSIS
+
+ #include <openssl/asn1.h>
+
+ ASN1_VALUE *ASN1_item_d2i_ex(ASN1_VALUE **pval, const unsigned char **in,
+ long len, const ASN1_ITEM *it,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in,
+ long len, const ASN1_ITEM *it);
+
+ void *ASN1_item_d2i_bio_ex(const ASN1_ITEM *it, BIO *in, void *x,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x);
+
+ void *ASN1_item_d2i_fp_ex(const ASN1_ITEM *it, FILE *in, void *x,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);
+
+ BIO *ASN1_item_i2d_mem_bio(const ASN1_ITEM *it, const ASN1_VALUE *val);
+
+=head1 DESCRIPTION
+
+ASN1_item_d2i_ex() decodes the contents of the data stored in I<*in> of length
+I<len> which must be a DER-encoded ASN.1 structure, using the ASN.1 template
+I<it>. It places the result in I<*pval> unless I<pval> is NULL. If I<*pval> is
+non-NULL on entry then the B<ASN1_VALUE> present there will be reused. Otherwise
+a new B<ASN1_VALUE> will be allocated. If any algorithm fetches are required
+during the process then they will use the B<OSSL_LIB_CTX>provided in the
+I<libctx> parameter and the property query string in I<propq>. See
+L<crypto(7)/ALGORITHM FETCHING> for more information about algorithm fetching.
+On exit I<*in> will be updated to point to the next byte in the buffer after the
+decoded structure.
+
+ASN1_item_d2i() is the same as ASN1_item_d2i_ex() except that the default
+OSSL_LIB_CTX is used (i.e. NULL) and with a NULL property query string.
+
+ASN1_item_d2i_bio_ex() decodes the contents of its input BIO I<in>,
+which must be a DER-encoded ASN.1 structure, using the ASN.1 template I<it>
+and places the result in I<*pval> unless I<pval> is NULL.
+If I<in> is NULL it returns NULL, else a pointer to the parsed structure. If any
+algorithm fetches are required during the process then they will use the
+B<OSSL_LIB_CTX> provided in the I<libctx> parameter and the property query
+string in I<propq>. See L<crypto(7)/ALGORITHM FETCHING> for more information
+about algorithm fetching.
+
+ASN1_item_d2i_bio() is the same as ASN1_item_d2i_bio_ex() except that the
+default B<OSSL_LIB_CTX> is used (i.e. NULL) and with a NULL property query
+string.
+
+ASN1_item_d2i_fp_ex() is the same as ASN1_item_d2i_bio_ex() except that a FILE
+pointer is provided instead of a BIO.
+
+ASN1_item_d2i_fp() is the same as ASN1_item_d2i_fp_ex() except that the
+default B<OSSL_LIB_CTX> is used (i.e. NULL) and with a NULL property query
+string.
+
+ASN1_item_i2d_mem_bio() encodes the given ASN.1 value I<val>
+using the ASN.1 template I<it> and returns the result in a memory BIO.
+
+=head1 RETURN VALUES
+
+ASN1_item_d2i_bio() returns a pointer to an B<ASN1_VALUE> or NULL.
+
+ASN1_item_i2d_mem_bio() returns a pointer to a memory BIO or NULL on error.
+
+=head1 HISTORY
+
+The functions ASN1_item_d2i_ex(), ASN1_item_d2i_bio_ex(), ASN1_item_d2i_fp_ex()
+and ASN1_item_i2d_mem_bio() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/ASN1_item_new.pod b/doc/man3/ASN1_item_new.pod
new file mode 100644
index 000000000000..4a495604d486
--- /dev/null
+++ b/doc/man3/ASN1_item_new.pod
@@ -0,0 +1,45 @@
+=pod
+
+=head1 NAME
+
+ASN1_item_new_ex, ASN1_item_new
+- create new ASN.1 values
+
+=head1 SYNOPSIS
+
+ #include <openssl/asn1.h>
+
+ ASN1_VALUE *ASN1_item_new_ex(const ASN1_ITEM *it, OSSL_LIB_CTX *libctx,
+ const char *propq);
+ ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it);
+
+=head1 DESCRIPTION
+
+ASN1_item_new_ex() creates a new B<ASN1_VALUE> structure based on the
+B<ASN1_ITEM> template given in the I<it> parameter. If any algorithm fetches are
+required during the process then they will use the B<OSSL_LIB_CTX> provided in
+the I<libctx> parameter and the property query string in I<propq>. See
+L<crypto(7)/ALGORITHM FETCHING> for more information about algorithm fetching.
+
+ASN1_item_new() is the same as ASN1_item_new_ex() except that the default
+B<OSSL_LIB_CTX> is used (i.e. NULL) and with a NULL property query string.
+
+=head1 RETURN VALUES
+
+ASN1_item_new_ex() and ASN1_item_new() return a pointer to the newly created
+B<ASN1_VALUE> or NULL on error.
+
+=head1 HISTORY
+
+The function ASN1_item_new_ex() was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/ASN1_item_sign.pod b/doc/man3/ASN1_item_sign.pod
new file mode 100644
index 000000000000..407268bf1779
--- /dev/null
+++ b/doc/man3/ASN1_item_sign.pod
@@ -0,0 +1,226 @@
+=pod
+
+=head1 NAME
+
+ASN1_item_sign, ASN1_item_sign_ex, ASN1_item_sign_ctx,
+ASN1_item_verify, ASN1_item_verify_ex, ASN1_item_verify_ctx -
+ASN1 sign and verify
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509.h>
+
+ int ASN1_item_sign_ex(const ASN1_ITEM *it, X509_ALGOR *algor1,
+ X509_ALGOR *algor2, ASN1_BIT_STRING *signature,
+ const void *data, const ASN1_OCTET_STRING *id,
+ EVP_PKEY *pkey, const EVP_MD *md, OSSL_LIB_CTX *libctx,
+ const char *propq);
+
+ int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
+ ASN1_BIT_STRING *signature, const void *data,
+ EVP_PKEY *pkey, const EVP_MD *md);
+
+ int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1,
+ X509_ALGOR *algor2, ASN1_BIT_STRING *signature,
+ const void *data, EVP_MD_CTX *ctx);
+
+ int ASN1_item_verify_ex(const ASN1_ITEM *it, const X509_ALGOR *alg,
+ const ASN1_BIT_STRING *signature, const void *data,
+ const ASN1_OCTET_STRING *id, EVP_PKEY *pkey,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+ int ASN1_item_verify(const ASN1_ITEM *it, const X509_ALGOR *alg,
+ const ASN1_BIT_STRING *signature, const void *data,
+ EVP_PKEY *pkey);
+
+ int ASN1_item_verify_ctx(const ASN1_ITEM *it, const X509_ALGOR *alg,
+ const ASN1_BIT_STRING *signature, const void *data,
+ EVP_MD_CTX *ctx);
+
+=head1 DESCRIPTION
+
+ASN1_item_sign_ex() is used to sign arbitrary ASN1 data using a data object
+I<data>, the ASN.1 structure I<it>, private key I<pkey> and message digest I<md>.
+The data that is signed is formed by taking the data object in I<data> and
+converting it to der format using the ASN.1 structure I<it>.
+The I<data> that will be signed, and a structure containing the signature may
+both have a copy of the B<X509_ALGOR>. The ASN1_item_sign_ex() function will
+write the correct B<X509_ALGOR> to the structs based on the algorithms and
+parameters that have been set up. If one of I<algor1> or I<algor2> points to the
+B<X509_ALGOR> of the I<data> to be signed, then that B<X509_ALGOR> will first be
+written before the signature is generated.
+Examples of valid values that can be used by the ASN.1 structure I<it> are
+ASN1_ITEM_rptr(X509_CINF), ASN1_ITEM_rptr(X509_REQ_INFO) and
+ASN1_ITEM_rptr(X509_CRL_INFO).
+The B<OSSL_LIB_CTX> specified in I<libctx> and the property query string
+specified in I<props> are used when searching for algorithms in providers.
+The generated signature is set into I<signature>.
+The optional parameter I<id> can be NULL, but can be set for special key types.
+See EVP_PKEY_CTX_set1_id() for further info. The output parameters <algor1> and
+I<algor2> are ignored if they are NULL.
+
+ASN1_item_sign() is similar to ASN1_item_sign_ex() but uses default values of
+NULL for the I<id>, I<libctx> and I<propq>.
+
+ASN1_item_sign_ctx() is similiar to ASN1_item_sign() but uses the parameters
+contained in digest context I<ctx>.
+
+ASN1_item_verify_ex() is used to verify the signature I<signature> of internal
+data I<data> using the public key I<pkey> and algorithm identifier I<alg>.
+The data that is verified is formed by taking the data object in I<data> and
+converting it to der format using the ASN.1 structure I<it>.
+The B<OSSL_LIB_CTX> specified in I<libctx> and the property query string
+specified in I<props> are used when searching for algorithms in providers.
+The optional parameter I<id> can be NULL, but can be set for special key types.
+See EVP_PKEY_CTX_set1_id() for further info.
+
+ASN1_item_verify() is similar to ASN1_item_verify_ex() but uses default values of
+NULL for the I<id>, I<libctx> and I<propq>.
+
+ASN1_item_verify_ctx() is similiar to ASN1_item_verify() but uses the parameters
+contained in digest context I<ctx>.
+
+
+=head1 RETURN VALUES
+
+All sign functions return the size of the signature in bytes for success and
+zero for failure.
+
+All verify functions return 1 if the signature is valid and 0 if the signature
+check fails. If the signature could not be checked at all because it was
+ill-formed or some other error occurred then -1 is returned.
+
+=head1 EXAMPLES
+
+In the following example a 'MyObject' object is signed using the key contained
+in an EVP_MD_CTX. The signature is written to MyObject.signature. The object is
+then output in DER format and then loaded back in and verified.
+
+ #include <openssl/x509.h>
+ #include <openssl/asn1t.h>
+
+ /* An object used to store the ASN1 data fields that will be signed */
+ typedef struct MySignInfoObject_st
+ {
+ ASN1_INTEGER *version;
+ X509_ALGOR sig_alg;
+ } MySignInfoObject;
+
+ DECLARE_ASN1_FUNCTIONS(MySignInfoObject)
+ /*
+ * A higher level object containing the ASN1 fields, signature alg and
+ * output signature.
+ */
+ typedef struct MyObject_st
+ {
+ MySignInfoObject info;
+ X509_ALGOR sig_alg;
+ ASN1_BIT_STRING *signature;
+ } MyObject;
+
+ DECLARE_ASN1_FUNCTIONS(MyObject)
+
+ /* The ASN1 definition of MySignInfoObject */
+ ASN1_SEQUENCE_cb(MySignInfoObject, NULL) = {
+ ASN1_SIMPLE(MySignInfoObject, version, ASN1_INTEGER)
+ ASN1_EMBED(MySignInfoObject, sig_alg, X509_ALGOR),
+ } ASN1_SEQUENCE_END_cb(MySignInfoObject, MySignInfoObject)
+
+ /* new, free, d2i & i2d functions for MySignInfoObject */
+ IMPLEMENT_ASN1_FUNCTIONS(MySignInfoObject)
+
+ /* The ASN1 definition of MyObject */
+ ASN1_SEQUENCE_cb(MyObject, NULL) = {
+ ASN1_EMBED(MyObject, info, MySignInfoObject),
+ ASN1_EMBED(MyObject, sig_alg, X509_ALGOR),
+ ASN1_SIMPLE(MyObject, signature, ASN1_BIT_STRING)
+ } ASN1_SEQUENCE_END_cb(MyObject, MyObject)
+
+ /* new, free, d2i & i2d functions for MyObject */
+ IMPLEMENT_ASN1_FUNCTIONS(MyObject)
+
+ int test_asn1_item_sign_verify(const char *mdname, EVP_PKEY *pkey, long version)
+ {
+ int ret = 0;
+ unsigned char *obj_der = NULL;
+ const unsigned char *p = NULL;
+ MyObject *obj = NULL, *loaded_obj = NULL;
+ const ASN1_ITEM *it = ASN1_ITEM_rptr(MySignInfoObject);
+ EVP_MD_CTX *sctx = NULL, *vctx = NULL;
+ int len;
+
+ /* Create MyObject and set its version */
+ obj = MyObject_new();
+ if (obj == NULL)
+ goto err;
+ if (!ASN1_INTEGER_set(obj->info.version, version))
+ goto err;
+
+ /* Set the key and digest used for signing */
+ sctx = EVP_MD_CTX_new();
+ if (sctx == NULL
+ || !EVP_DigestSignInit_ex(sctx, NULL, mdname, NULL, NULL, pkey))
+ goto err;
+
+ /*
+ * it contains the mapping between ASN.1 data and an object MySignInfoObject
+ * obj->info is the 'MySignInfoObject' object that will be
+ * converted into DER data and then signed.
+ * obj->signature will contain the output signature.
+ * obj->sig_alg is filled with the private key's signing algorithm id.
+ * obj->info.sig_alg is another copy of the signing algorithm id that sits
+ * within MyObject.
+ */
+ len = ASN1_item_sign_ctx(it, &obj->sig_alg, &obj->info.sig_alg,
+ obj->signature, &obj->info, sctx);
+ if (len <= 0
+ || X509_ALGOR_cmp(&obj->sig_alg, &obj->info.sig_alg) != 0)
+ goto err;
+
+ /* Output MyObject in der form */
+ len = i2d_MyObject(obj, &obj_der);
+ if (len <= 0)
+ goto err;
+
+ /* Set the key and digest used for verifying */
+ vctx = EVP_MD_CTX_new();
+ if (vctx == NULL
+ || !EVP_DigestVerifyInit_ex(vctx, NULL, mdname, NULL, NULL, pkey))
+ goto err;
+
+ /* Load the der data back into an object */
+ p = obj_der;
+ loaded_obj = d2i_MyObject(NULL, &p, len);
+ if (loaded_obj == NULL)
+ goto err;
+ /* Verify the loaded object */
+ ret = ASN1_item_verify_ctx(it, &loaded_obj->sig_alg, loaded_obj->signature,
+ &loaded_obj->info, vctx);
+err:
+ OPENSSL_free(obj_der);
+ MyObject_free(loaded_obj);
+ MyObject_free(obj);
+ EVP_MD_CTX_free(sctx);
+ EVP_MD_CTX_free(vctx);
+ return ret;
+ }
+
+=head1 SEE ALSO
+
+L<X509_sign(3)>,
+L<X509_verify(3)>
+
+=head1 HISTORY
+
+ASN1_item_sign_ex() and ASN1_item_verify_ex() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/ASYNC_WAIT_CTX_new.pod b/doc/man3/ASYNC_WAIT_CTX_new.pod
index 0e8c1d8010a2..328af9e53a64 100644
--- a/doc/man3/ASYNC_WAIT_CTX_new.pod
+++ b/doc/man3/ASYNC_WAIT_CTX_new.pod
@@ -4,13 +4,22 @@
ASYNC_WAIT_CTX_new, ASYNC_WAIT_CTX_free, ASYNC_WAIT_CTX_set_wait_fd,
ASYNC_WAIT_CTX_get_fd, ASYNC_WAIT_CTX_get_all_fds,
-ASYNC_WAIT_CTX_get_changed_fds, ASYNC_WAIT_CTX_clear_fd - functions to manage
-waiting for asynchronous jobs to complete
+ASYNC_WAIT_CTX_get_changed_fds, ASYNC_WAIT_CTX_clear_fd,
+ASYNC_WAIT_CTX_set_callback, ASYNC_WAIT_CTX_get_callback,
+ASYNC_WAIT_CTX_set_status, ASYNC_WAIT_CTX_get_status, ASYNC_callback_fn,
+ASYNC_STATUS_UNSUPPORTED, ASYNC_STATUS_ERR, ASYNC_STATUS_OK,
+ASYNC_STATUS_EAGAIN
+- functions to manage waiting for asynchronous jobs to complete
=head1 SYNOPSIS
#include <openssl/async.h>
+ #define ASYNC_STATUS_UNSUPPORTED 0
+ #define ASYNC_STATUS_ERR 1
+ #define ASYNC_STATUS_OK 2
+ #define ASYNC_STATUS_EAGAIN 3
+ typedef int (*ASYNC_callback_fn)(void *arg);
ASYNC_WAIT_CTX *ASYNC_WAIT_CTX_new(void);
void ASYNC_WAIT_CTX_free(ASYNC_WAIT_CTX *ctx);
int ASYNC_WAIT_CTX_set_wait_fd(ASYNC_WAIT_CTX *ctx, const void *key,
@@ -26,50 +35,58 @@ waiting for asynchronous jobs to complete
size_t *numaddfds, OSSL_ASYNC_FD *delfd,
size_t *numdelfds);
int ASYNC_WAIT_CTX_clear_fd(ASYNC_WAIT_CTX *ctx, const void *key);
+ int ASYNC_WAIT_CTX_set_callback(ASYNC_WAIT_CTX *ctx,
+ ASYNC_callback_fn callback,
+ void *callback_arg);
+ int ASYNC_WAIT_CTX_get_callback(ASYNC_WAIT_CTX *ctx,
+ ASYNC_callback_fn *callback,
+ void **callback_arg);
+ int ASYNC_WAIT_CTX_set_status(ASYNC_WAIT_CTX *ctx, int status);
+ int ASYNC_WAIT_CTX_get_status(ASYNC_WAIT_CTX *ctx);
=head1 DESCRIPTION
For an overview of how asynchronous operations are implemented in OpenSSL see
-L<ASYNC_start_job(3)>. An ASYNC_WAIT_CTX object represents an asynchronous
+L<ASYNC_start_job(3)>. An B<ASYNC_WAIT_CTX> object represents an asynchronous
"session", i.e. a related set of crypto operations. For example in SSL terms
this would have a one-to-one correspondence with an SSL connection.
-Application code must create an ASYNC_WAIT_CTX using the ASYNC_WAIT_CTX_new()
+Application code must create an B<ASYNC_WAIT_CTX> using the ASYNC_WAIT_CTX_new()
function prior to calling ASYNC_start_job() (see L<ASYNC_start_job(3)>). When
-the job is started it is associated with the ASYNC_WAIT_CTX for the duration of
-that job. An ASYNC_WAIT_CTX should only be used for one ASYNC_JOB at any one
-time, but can be reused after an ASYNC_JOB has finished for a subsequent
-ASYNC_JOB. When the session is complete (e.g. the SSL connection is closed),
-application code cleans up with ASYNC_WAIT_CTX_free().
-
-ASYNC_WAIT_CTXs can have "wait" file descriptors associated with them. Calling
-ASYNC_WAIT_CTX_get_all_fds() and passing in a pointer to an ASYNC_WAIT_CTX in
-the B<ctx> parameter will return the wait file descriptors associated with that
-job in B<*fd>. The number of file descriptors returned will be stored in
-B<*numfds>. It is the caller's responsibility to ensure that sufficient memory
-has been allocated in B<*fd> to receive all the file descriptors. Calling
-ASYNC_WAIT_CTX_get_all_fds() with a NULL B<fd> value will return no file
-descriptors but will still populate B<*numfds>. Therefore, application code is
-typically expected to call this function twice: once to get the number of fds,
-and then again when sufficient memory has been allocated. If only one
-asynchronous engine is being used then normally this call will only ever return
-one fd. If multiple asynchronous engines are being used then more could be
-returned.
+the job is started it is associated with the B<ASYNC_WAIT_CTX> for the duration
+of that job. An B<ASYNC_WAIT_CTX> should only be used for one B<ASYNC_JOB> at
+any one time, but can be reused after an B<ASYNC_JOB> has finished for a
+subsequent B<ASYNC_JOB>. When the session is complete (e.g. the SSL connection
+is closed), application code cleans up with ASYNC_WAIT_CTX_free().
+
+B<ASYNC_WAIT_CTX>s can have "wait" file descriptors associated with them.
+Calling ASYNC_WAIT_CTX_get_all_fds() and passing in a pointer to an
+B<ASYNC_WAIT_CTX> in the I<ctx> parameter will return the wait file descriptors
+associated with that job in I<*fd>. The number of file descriptors returned will
+be stored in I<*numfds>. It is the caller's responsibility to ensure that
+sufficient memory has been allocated in I<*fd> to receive all the file
+descriptors. Calling ASYNC_WAIT_CTX_get_all_fds() with a NULL I<fd> value will
+return no file descriptors but will still populate I<*numfds>. Therefore,
+application code is typically expected to call this function twice: once to get
+the number of fds, and then again when sufficient memory has been allocated. If
+only one asynchronous engine is being used then normally this call will only
+ever return one fd. If multiple asynchronous engines are being used then more
+could be returned.
The function ASYNC_WAIT_CTX_get_changed_fds() can be used to detect if any fds
-have changed since the last call time ASYNC_start_job() returned an ASYNC_PAUSE
-result (or since the ASYNC_WAIT_CTX was created if no ASYNC_PAUSE result has
-been received). The B<numaddfds> and B<numdelfds> parameters will be populated
-with the number of fds added or deleted respectively. B<*addfd> and B<*delfd>
+have changed since the last call time ASYNC_start_job() returned B<ASYNC_PAUSE>
+(or since the B<ASYNC_WAIT_CTX> was created if no B<ASYNC_PAUSE> result has
+been received). The I<numaddfds> and I<numdelfds> parameters will be populated
+with the number of fds added or deleted respectively. I<*addfd> and I<*delfd>
will be populated with the list of added and deleted fds respectively. Similarly
to ASYNC_WAIT_CTX_get_all_fds() either of these can be NULL, but if they are not
NULL then the caller is responsible for ensuring sufficient memory is allocated.
Implementors of async aware code (e.g. engines) are encouraged to return a
-stable fd for the lifetime of the ASYNC_WAIT_CTX in order to reduce the "churn"
-of regularly changing fds - although no guarantees of this are provided to
-applications.
+stable fd for the lifetime of the B<ASYNC_WAIT_CTX> in order to reduce the
+"churn" of regularly changing fds - although no guarantees of this are provided
+to applications.
Applications can wait for the file descriptor to be ready for "read" using a
system function call such as select or poll (being ready for "read" indicates
@@ -77,21 +94,21 @@ that the job should be resumed). If no file descriptor is made available then an
application will have to periodically "poll" the job by attempting to restart it
to see if it is ready to continue.
-Async aware code (e.g. engines) can get the current ASYNC_WAIT_CTX from the job
-via L<ASYNC_get_wait_ctx(3)> and provide a file descriptor to use for waiting
-on by calling ASYNC_WAIT_CTX_set_wait_fd(). Typically this would be done by an
-engine immediately prior to calling ASYNC_pause_job() and not by end user code.
-An existing association with a file descriptor can be obtained using
+Async aware code (e.g. engines) can get the current B<ASYNC_WAIT_CTX> from the
+job via L<ASYNC_get_wait_ctx(3)> and provide a file descriptor to use for
+waiting on by calling ASYNC_WAIT_CTX_set_wait_fd(). Typically this would be done
+by an engine immediately prior to calling ASYNC_pause_job() and not by end user
+code. An existing association with a file descriptor can be obtained using
ASYNC_WAIT_CTX_get_fd() and cleared using ASYNC_WAIT_CTX_clear_fd(). Both of
-these functions requires a B<key> value which is unique to the async aware
+these functions requires a I<key> value which is unique to the async aware
code. This could be any unique value but a good candidate might be the
-B<ENGINE *> for the engine. The B<custom_data> parameter can be any value, and
+B<ENGINE *> for the engine. The I<custom_data> parameter can be any value, and
will be returned in a subsequent call to ASYNC_WAIT_CTX_get_fd(). The
ASYNC_WAIT_CTX_set_wait_fd() function also expects a pointer to a "cleanup"
routine. This can be NULL but if provided will automatically get called when
-the ASYNC_WAIT_CTX is freed, and gives the engine the opportunity to close the
-fd or any other resources. Note: The "cleanup" routine does not get called if
-the fd is cleared directly via a call to ASYNC_WAIT_CTX_clear_fd().
+the B<ASYNC_WAIT_CTX> is freed, and gives the engine the opportunity to close
+the fd or any other resources. Note: The "cleanup" routine does not get called
+if the fd is cleared directly via a call to ASYNC_WAIT_CTX_clear_fd().
An example of typical usage might be an async capable engine. User code would
initiate cryptographic operations. The engine would initiate those operations
@@ -103,23 +120,84 @@ code that the job should be resumed by making the wait file descriptor
"readable". Once resumed the engine should clear the wake signal on the wait
file descriptor.
+As well as a file descriptor, user code may also be notified via a callback. The
+callback and data pointers are stored within the B<ASYNC_WAIT_CTX> along with an
+additional status field that can be used for the notification of retries from an
+engine. This additional method can be used when the user thinks that a file
+descriptor is too costly in terms of CPU cycles or in some context where a file
+descriptor is not appropriate.
+
+ASYNC_WAIT_CTX_set_callback() sets the callback and the callback argument. The
+callback will be called to notify user code when an engine completes a
+cryptography operation. It is a requirement that the callback function is small
+and nonblocking as it will be run in the context of a polling mechanism or an
+interrupt.
+
+ASYNC_WAIT_CTX_get_callback() returns the callback set in the B<ASYNC_WAIT_CTX>
+structure.
+
+ASYNC_WAIT_CTX_set_status() allows an engine to set the current engine status.
+The possible status values are the following:
+
+=over 4
+
+=item B<ASYNC_STATUS_UNSUPPORTED>
+
+The engine does not support the callback mechanism. This is the default value.
+The engine must call ASYNC_WAIT_CTX_set_status() to set the status to some value
+other than B<ASYNC_STATUS_UNSUPPORTED> if it intends to enable the callback
+mechanism.
+
+=item B<ASYNC_STATUS_ERR>
+
+The engine has a fatal problem with this request. The user code should clean up
+this session.
+
+=item B<ASYNC_STATUS_OK>
+
+The request has been successfully submitted.
+
+=item B<ASYNC_STATUS_EAGAIN>
+
+The engine has some problem which will be recovered soon, such as a buffer is
+full, so user code should resume the job.
+
+=back
+
+ASYNC_WAIT_CTX_get_status() allows user code to obtain the current status value.
+If the status is any value other than B<ASYNC_STATUS_OK> then the user code
+should not expect to receive a callback from the engine even if one has been
+set.
+
+An example of the usage of the callback method might be the following. User
+code would initiate cryptographic operations, and the engine code would dispatch
+this operation to hardware, and if the dispatch is successful, then the engine
+code would call ASYNC_pause_job() to return control to the user code. After
+that, user code can perform other tasks. When the hardware completes the
+operation, normally it is detected by a polling function or an interrupt, as the
+user code set a callback by calling ASYNC_WAIT_CTX_set_callback() previously,
+then the registered callback will be called.
+
=head1 RETURN VALUES
-ASYNC_WAIT_CTX_new() returns a pointer to the newly allocated ASYNC_WAIT_CTX or
-NULL on error.
+ASYNC_WAIT_CTX_new() returns a pointer to the newly allocated B<ASYNC_WAIT_CTX>
+or NULL on error.
ASYNC_WAIT_CTX_set_wait_fd, ASYNC_WAIT_CTX_get_fd, ASYNC_WAIT_CTX_get_all_fds,
-ASYNC_WAIT_CTX_get_changed_fds and ASYNC_WAIT_CTX_clear_fd all return 1 on
-success or 0 on error.
+ASYNC_WAIT_CTX_get_changed_fds, ASYNC_WAIT_CTX_clear_fd,
+ASYNC_WAIT_CTX_set_callback, ASYNC_WAIT_CTX_get_callback and
+ASYNC_WAIT_CTX_set_status all return 1 on success or 0 on error.
+ASYNC_WAIT_CTX_get_status() returns the engine status.
+
=head1 NOTES
-On Windows platforms the openssl/async.h header is dependent on some
-of the types customarily made available by including windows.h. The
+On Windows platforms the F<< <openssl/async.h> >> header is dependent on some
+of the types customarily made available by including F<< <windows.h> >>. The
application developer is likely to require control over when the latter
is included, commonly as one of the first included headers. Therefore,
it is defined as an application developer's responsibility to include
-windows.h prior to async.h.
+F<< <windows.h> >> prior to F<< <openssl/async.h> >>.
=head1 SEE ALSO
@@ -132,11 +210,15 @@ ASYNC_WAIT_CTX_get_fd(), ASYNC_WAIT_CTX_get_all_fds(),
ASYNC_WAIT_CTX_get_changed_fds() and ASYNC_WAIT_CTX_clear_fd()
were added in OpenSSL 1.1.0.
+ASYNC_WAIT_CTX_set_callback(), ASYNC_WAIT_CTX_get_callback(),
+ASYNC_WAIT_CTX_set_status(), and ASYNC_WAIT_CTX_get_status()
+were added in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ASYNC_start_job.pod b/doc/man3/ASYNC_start_job.pod
index 810b9678731f..b2e7a583d4e9 100644
--- a/doc/man3/ASYNC_start_job.pod
+++ b/doc/man3/ASYNC_start_job.pod
@@ -27,40 +27,40 @@ ASYNC_get_current_job, ASYNC_block_pause, ASYNC_unblock_pause, ASYNC_is_capable
=head1 DESCRIPTION
-OpenSSL implements asynchronous capabilities through an ASYNC_JOB. This
+OpenSSL implements asynchronous capabilities through an B<ASYNC_JOB>. This
represents code that can be started and executes until some event occurs. At
that point the code can be paused and control returns to user code until some
subsequent event indicates that the job can be resumed.
-The creation of an ASYNC_JOB is a relatively expensive operation. Therefore, for
-efficiency reasons, jobs can be created up front and reused many times. They are
-held in a pool until they are needed, at which point they are removed from the
-pool, used, and then returned to the pool when the job completes. If the user
-application is multi-threaded, then ASYNC_init_thread() may be called for each
-thread that will initiate asynchronous jobs. Before
+The creation of an B<ASYNC_JOB> is a relatively expensive operation. Therefore,
+for efficiency reasons, jobs can be created up front and reused many times. They
+are held in a pool until they are needed, at which point they are removed from
+the pool, used, and then returned to the pool when the job completes. If the
+user application is multi-threaded, then ASYNC_init_thread() may be called for
+each thread that will initiate asynchronous jobs. Before
user code exits per-thread resources need to be cleaned up. This will normally
occur automatically (see L<OPENSSL_init_crypto(3)>) but may be explicitly
initiated by using ASYNC_cleanup_thread(). No asynchronous jobs must be
outstanding for the thread when ASYNC_cleanup_thread() is called. Failing to
ensure this will result in memory leaks.
-The B<max_size> argument limits the number of ASYNC_JOBs that will be held in
-the pool. If B<max_size> is set to 0 then no upper limit is set. When an
-ASYNC_JOB is needed but there are none available in the pool already then one
-will be automatically created, as long as the total of ASYNC_JOBs managed by the
-pool does not exceed B<max_size>. When the pool is first initialised
-B<init_size> ASYNC_JOBs will be created immediately. If ASYNC_init_thread() is
-not called before the pool is first used then it will be called automatically
-with a B<max_size> of 0 (no upper limit) and an B<init_size> of 0 (no ASYNC_JOBs
-created up front).
+The I<max_size> argument limits the number of B<ASYNC_JOB>s that will be held in
+the pool. If I<max_size> is set to 0 then no upper limit is set. When an
+B<ASYNC_JOB> is needed but there are none available in the pool already then one
+will be automatically created, as long as the total of B<ASYNC_JOB>s managed by
+the pool does not exceed I<max_size>. When the pool is first initialised
+I<init_size> B<ASYNC_JOB>s will be created immediately. If ASYNC_init_thread()
+is not called before the pool is first used then it will be called automatically
+with a I<max_size> of 0 (no upper limit) and an I<init_size> of 0 (no
+B<ASYNC_JOB>s created up front).
An asynchronous job is started by calling the ASYNC_start_job() function.
-Initially B<*job> should be NULL. B<ctx> should point to an ASYNC_WAIT_CTX
-object created through the L<ASYNC_WAIT_CTX_new(3)> function. B<ret> should
+Initially I<*job> should be NULL. I<ctx> should point to an B<ASYNC_WAIT_CTX>
+object created through the L<ASYNC_WAIT_CTX_new(3)> function. I<ret> should
point to a location where the return value of the asynchronous function should
-be stored on completion of the job. B<func> represents the function that should
-be started asynchronously. The data pointed to by B<args> and of size B<size>
-will be copied and then passed as an argument to B<func> when the job starts.
+be stored on completion of the job. I<func> represents the function that should
+be started asynchronously. The data pointed to by I<args> and of size I<size>
+will be copied and then passed as an argument to I<func> when the job starts.
ASYNC_start_job will return one of the following values:
=over 4
@@ -78,51 +78,55 @@ again at a later time.
=item B<ASYNC_PAUSE>
The job was successfully started but was "paused" before it completed (see
-ASYNC_pause_job() below). A handle to the job is placed in B<*job>. Other work
+ASYNC_pause_job() below). A handle to the job is placed in I<*job>. Other work
can be performed (if desired) and the job restarted at a later time. To restart
-a job call ASYNC_start_job() again passing the job handle in B<*job>. The
-B<func>, B<args> and B<size> parameters will be ignored when restarting a job.
+a job call ASYNC_start_job() again passing the job handle in I<*job>. The
+I<func>, I<args> and I<size> parameters will be ignored when restarting a job.
When restarting a job ASYNC_start_job() B<must> be called from the same thread
that the job was originally started from.
=item B<ASYNC_FINISH>
-The job completed. B<*job> will be NULL and the return value from B<func> will
-be placed in B<*ret>.
+The job completed. I<*job> will be NULL and the return value from I<func> will
+be placed in I<*ret>.
=back
At any one time there can be a maximum of one job actively running per thread
(you can have many that are paused). ASYNC_get_current_job() can be used to get
-a pointer to the currently executing ASYNC_JOB. If no job is currently executing
-then this will return NULL.
+a pointer to the currently executing B<ASYNC_JOB>. If no job is currently
+executing then this will return NULL.
If executing within the context of a job (i.e. having been called directly or
indirectly by the function "func" passed as an argument to ASYNC_start_job())
then ASYNC_pause_job() will immediately return control to the calling
-application with ASYNC_PAUSE returned from the ASYNC_start_job() call. A
-subsequent call to ASYNC_start_job passing in the relevant ASYNC_JOB in the
-B<*job> parameter will resume execution from the ASYNC_pause_job() call. If
+application with B<ASYNC_PAUSE> returned from the ASYNC_start_job() call. A
+subsequent call to ASYNC_start_job passing in the relevant B<ASYNC_JOB> in the
+I<*job> parameter will resume execution from the ASYNC_pause_job() call. If
ASYNC_pause_job() is called whilst not within the context of a job then no
action is taken and ASYNC_pause_job() returns immediately.
-ASYNC_get_wait_ctx() can be used to get a pointer to the ASYNC_WAIT_CTX
-for the B<job>. ASYNC_WAIT_CTXs can have a "wait" file descriptor associated
-with them. Applications can wait for the file descriptor to be ready for "read"
-using a system function call such as select or poll (being ready for "read"
-indicates that the job should be resumed). If no file descriptor is made
-available then an application will have to periodically "poll" the job by
-attempting to restart it to see if it is ready to continue.
-
-An example of typical usage might be an async capable engine. User code would
-initiate cryptographic operations. The engine would initiate those operations
-asynchronously and then call L<ASYNC_WAIT_CTX_set_wait_fd(3)> followed by
-ASYNC_pause_job() to return control to the user code. The user code can then
-perform other tasks or wait for the job to be ready by calling "select" or other
-similar function on the wait file descriptor. The engine can signal to the user
-code that the job should be resumed by making the wait file descriptor
-"readable". Once resumed the engine should clear the wake signal on the wait
-file descriptor.
+ASYNC_get_wait_ctx() can be used to get a pointer to the B<ASYNC_WAIT_CTX>
+for the I<job>. B<ASYNC_WAIT_CTX>s contain two different ways to notify
+applications that a job is ready to be resumed. One is a "wait" file
+descriptor, and the other is a "callback" mechanism.
+
+The "wait" file descriptor associated with B<ASYNC_WAIT_CTX> is used for
+applications to wait for the file descriptor to be ready for "read" using a
+system function call such as select or poll (being ready for "read" indicates
+that the job should be resumed). If no file descriptor is made available then
+an application will have to periodically "poll" the job by attempting to restart
+it to see if it is ready to continue.
+
+B<ASYNC_WAIT_CTX>s also have a "callback" mechanism to notify applications. The
+callback is set by an application, and it will be automatically called when an
+engine completes a cryptography operation, so that the application can resume
+the paused work flow without polling. An engine could be written to look whether
+the callback has been set. If it has then it would use the callback mechanism
+in preference to the file descriptor notifications. If a callback is not set
+then the engine may use file descriptor based notifications. Please note that
+not all engines may support the callback mechanism, so the callback may not be
+used even if it has been set. See ASYNC_WAIT_CTX_new() for more details.
The ASYNC_block_pause() function will prevent the currently active job from
pausing. The block will remain in place until a subsequent call to
@@ -130,10 +134,10 @@ ASYNC_unblock_pause(). These functions can be nested, e.g. if you call
ASYNC_block_pause() twice then you must call ASYNC_unblock_pause() twice in
order to re-enable pausing. If these functions are called while there is no
currently active job then they have no effect. This functionality can be useful
-to avoid deadlock scenarios. For example during the execution of an ASYNC_JOB an
-application acquires a lock. It then calls some cryptographic function which
+to avoid deadlock scenarios. For example during the execution of an B<ASYNC_JOB>
+an application acquires a lock. It then calls some cryptographic function which
invokes ASYNC_pause_job(). This returns control back to the code that created
-the ASYNC_JOB. If that code then attempts to acquire the same lock before
+the B<ASYNC_JOB>. If that code then attempts to acquire the same lock before
resuming the original job then a deadlock can occur. By calling
ASYNC_block_pause() immediately after acquiring the lock and
ASYNC_unblock_pause() immediately before releasing it then this situation cannot
@@ -146,29 +150,29 @@ can be used to detect whether the current platform is async capable or not.
ASYNC_init_thread returns 1 on success or 0 otherwise.
-ASYNC_start_job returns one of ASYNC_ERR, ASYNC_NO_JOBS, ASYNC_PAUSE or
-ASYNC_FINISH as described above.
+ASYNC_start_job returns one of B<ASYNC_ERR>, B<ASYNC_NO_JOBS>, B<ASYNC_PAUSE> or
+B<ASYNC_FINISH> as described above.
ASYNC_pause_job returns 0 if an error occurred or 1 on success. If called when
-not within the context of an ASYNC_JOB then this is counted as success so 1 is
-returned.
+not within the context of an B<ASYNC_JOB> then this is counted as success so 1
+is returned.
-ASYNC_get_current_job returns a pointer to the currently executing ASYNC_JOB or
-NULL if not within the context of a job.
+ASYNC_get_current_job returns a pointer to the currently executing B<ASYNC_JOB>
+or NULL if not within the context of a job.
-ASYNC_get_wait_ctx() returns a pointer to the ASYNC_WAIT_CTX for the job.
+ASYNC_get_wait_ctx() returns a pointer to the B<ASYNC_WAIT_CTX> for the job.
ASYNC_is_capable() returns 1 if the current platform is async capable or 0
otherwise.
=head1 NOTES
-On Windows platforms the openssl/async.h header is dependent on some
-of the types customarily made available by including windows.h. The
+On Windows platforms the F<< <openssl/async.h> >> header is dependent on some
+of the types customarily made available by including F<< <windows.h> >>. The
application developer is likely to require control over when the latter
is included, commonly as one of the first included headers. Therefore,
it is defined as an application developer's responsibility to include
-windows.h prior to async.h.
+F<< <windows.h> >> prior to F<< <openssl/async.h> >>.
=head1 EXAMPLES
@@ -321,9 +325,9 @@ added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BF_encrypt.pod b/doc/man3/BF_encrypt.pod
index 02e04b7f34cb..509dd22c63fb 100644
--- a/doc/man3/BF_encrypt.pod
+++ b/doc/man3/BF_encrypt.pod
@@ -9,6 +9,10 @@ BF_cfb64_encrypt, BF_ofb64_encrypt, BF_options - Blowfish encryption
#include <openssl/blowfish.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
void BF_set_key(BF_KEY *key, int len, const unsigned char *data);
void BF_ecb_encrypt(const unsigned char *in, unsigned char *out,
@@ -29,6 +33,10 @@ BF_cfb64_encrypt, BF_ofb64_encrypt, BF_options - Blowfish encryption
=head1 DESCRIPTION
+All of the functions described on this page are deprecated. Applications should
+instead use L<EVP_EncryptInit_ex(3)>, L<EVP_EncryptUpdate(3)> and
+L<EVP_EncryptFinal_ex(3)> or the equivalently named decrypt functions.
+
This library implements the Blowfish cipher, which was invented and described
by Counterpane (see http://www.counterpane.com/blowfish.html ).
@@ -107,11 +115,15 @@ functions directly.
L<EVP_EncryptInit(3)>,
L<des_modes(7)>
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_ADDR.pod b/doc/man3/BIO_ADDR.pod
index e9652ed550e2..5ab88622cee0 100644
--- a/doc/man3/BIO_ADDR.pod
+++ b/doc/man3/BIO_ADDR.pod
@@ -50,7 +50,7 @@ therefore ignored) and populates the given B<BIO_ADDR> with them.
In case this creates a B<AF_UNIX> B<BIO_ADDR>, B<wherelen> is expected
to be the length of the path string (not including the terminating
NUL, such as the result of a call to strlen()).
-I<Read on about the addresses in L</RAW ADDRESSES> below>.
+Read on about the addresses in L</RAW ADDRESSES> below.
BIO_ADDR_family() returns the protocol family of the given
B<BIO_ADDR>. The possible non-error results are one of the
@@ -67,7 +67,7 @@ order, most significant byte first.
In case this is a B<AF_UNIX> B<BIO_ADDR>, B<l> gets the length of the
path string (not including the terminating NUL, such as the result of
a call to strlen()).
-I<Read on about the addresses in L</RAW ADDRESSES> below>.
+Read on about the addresses in L</RAW ADDRESSES> below.
BIO_ADDR_rawport() returns the raw port of the given B<BIO_ADDR>.
The raw port will be in network byte order.
@@ -117,7 +117,7 @@ L<BIO_connect(3)>, L<BIO_s_connect(3)>
Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_ADDRINFO.pod b/doc/man3/BIO_ADDRINFO.pod
index 37609666fdbf..626052e7f8b9 100644
--- a/doc/man3/BIO_ADDRINFO.pod
+++ b/doc/man3/BIO_ADDRINFO.pod
@@ -23,7 +23,7 @@ BIO_lookup
int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
int family, int socktype, int protocol, BIO_ADDRINFO **res);
- int BIO_lookup(const char *node, const char *service,
+ int BIO_lookup(const char *host, const char *service,
enum BIO_lookup_type lookup_type,
int family, int socktype, BIO_ADDRINFO **res);
@@ -54,8 +54,7 @@ used. B<res> points at a pointer to hold the start of a B<BIO_ADDRINFO>
chain.
For the family B<AF_UNIX>, BIO_lookup_ex() will ignore the B<service>
-parameter and expects the B<node> parameter to hold the path to the
-socket file.
+parameter and expects the B<host> parameter to hold the path to the socket file.
BIO_lookup() does the same as BIO_lookup_ex() but does not provide the ability
to select based on the protocol (any protocol may be returned).
@@ -104,9 +103,9 @@ The BIO_lookup_ex() function was added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_connect.pod b/doc/man3/BIO_connect.pod
index 0ebf17cacf47..3134ccb8c304 100644
--- a/doc/man3/BIO_connect.pod
+++ b/doc/man3/BIO_connect.pod
@@ -109,7 +109,7 @@ Use the functions described above instead.
Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_ctrl.pod b/doc/man3/BIO_ctrl.pod
index cf6ba135dfe9..ce31b2254cf7 100644
--- a/doc/man3/BIO_ctrl.pod
+++ b/doc/man3/BIO_ctrl.pod
@@ -5,7 +5,8 @@
BIO_ctrl, BIO_callback_ctrl, BIO_ptr_ctrl, BIO_int_ctrl, BIO_reset,
BIO_seek, BIO_tell, BIO_flush, BIO_eof, BIO_set_close, BIO_get_close,
BIO_pending, BIO_wpending, BIO_ctrl_pending, BIO_ctrl_wpending,
-BIO_get_info_callback, BIO_set_info_callback, BIO_info_cb
+BIO_get_info_callback, BIO_set_info_callback, BIO_info_cb, BIO_get_ktls_send,
+BIO_get_ktls_recv
- BIO control operations
=head1 SYNOPSIS
@@ -34,6 +35,9 @@ BIO_get_info_callback, BIO_set_info_callback, BIO_info_cb
int BIO_get_info_callback(BIO *b, BIO_info_cb **cbp);
int BIO_set_info_callback(BIO *b, BIO_info_cb *cb);
+ int BIO_get_ktls_send(BIO *b);
+ int BIO_get_ktls_recv(BIO *b);
+
=head1 DESCRIPTION
BIO_ctrl(), BIO_callback_ctrl(), BIO_ptr_ctrl() and BIO_int_ctrl()
@@ -72,25 +76,38 @@ Not all BIOs support these calls. BIO_ctrl_pending() and BIO_ctrl_wpending()
return a size_t type and are functions, BIO_pending() and BIO_wpending() are
macros which call BIO_ctrl().
+BIO_get_ktls_send() returns 1 if the BIO is using the Kernel TLS data-path for
+sending. Otherwise, it returns zero.
+BIO_get_ktls_recv() returns 1 if the BIO is using the Kernel TLS data-path for
+receiving. Otherwise, it returns zero.
+
=head1 RETURN VALUES
-BIO_reset() normally returns 1 for success and 0 or -1 for failure. File
+BIO_reset() normally returns 1 for success and <=0 for failure. File
BIOs are an exception, they return 0 for success and -1 for failure.
BIO_seek() and BIO_tell() both return the current file position on success
and -1 for failure, except file BIOs which for BIO_seek() always return 0
for success and -1 for failure.
-BIO_flush() returns 1 for success and 0 or -1 for failure.
+BIO_flush() returns 1 for success and <=0 for failure.
-BIO_eof() returns 1 if EOF has been reached 0 otherwise.
+BIO_eof() returns 1 if EOF has been reached, 0 if not, or negative values for failure.
-BIO_set_close() always returns 1.
+BIO_set_close() returns 1 on success or <=0 for failure.
-BIO_get_close() returns the close flag value: BIO_CLOSE or BIO_NOCLOSE.
+BIO_get_close() returns the close flag value: BIO_CLOSE or BIO_NOCLOSE. It also
+returns other negative values if an error occurs.
BIO_pending(), BIO_ctrl_pending(), BIO_wpending() and BIO_ctrl_wpending()
-return the amount of pending data.
+return the amount of pending data. BIO_pending() and BIO_wpending() return
+negative value or 0 on error. BIO_ctrl_pending() and BIO_ctrl_wpending() return
+0 on error.
+
+BIO_get_ktls_send() returns 1 if the BIO is using the Kernel TLS data-path for
+sending. Otherwise, it returns zero.
+BIO_get_ktls_recv() returns 1 if the BIO is using the Kernel TLS data-path for
+receiving. Otherwise, it returns zero.
=head1 NOTES
@@ -124,11 +141,19 @@ particular a return value of 0 can be returned if an operation is not
supported, if an error occurred, if EOF has not been reached and in
the case of BIO_seek() on a file BIO for a successful operation.
+In older versions of OpenSSL the BIO_ctrl_pending() and
+BIO_ctrl_wpending() could return values greater than INT_MAX on error.
+
+=head1 HISTORY
+
+The BIO_get_ktls_send() and BIO_get_ktls_recv() macros were added in
+OpenSSL 3.0. They were modified to never return -1 in OpenSSL 3.0.4.
+
=head1 COPYRIGHT
Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_f_base64.pod b/doc/man3/BIO_f_base64.pod
index 55ca5d4de30f..c865f0a17ac1 100644
--- a/doc/man3/BIO_f_base64.pod
+++ b/doc/man3/BIO_f_base64.pod
@@ -6,7 +6,7 @@ BIO_f_base64 - base64 BIO filter
=head1 SYNOPSIS
-=for comment multiple includes
+=for openssl multiple includes
#include <openssl/bio.h>
#include <openssl/evp.h>
@@ -95,7 +95,7 @@ to reliably determine EOF (for example a MIME boundary).
Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_f_buffer.pod b/doc/man3/BIO_f_buffer.pod
index 047a11d2407c..9a1d5b4b33fa 100644
--- a/doc/man3/BIO_f_buffer.pod
+++ b/doc/man3/BIO_f_buffer.pod
@@ -74,12 +74,13 @@ source/sink BIO is non blocking.
BIO_f_buffer() returns the buffering BIO method.
-BIO_get_buffer_num_lines() returns the number of lines buffered (may be 0).
+BIO_get_buffer_num_lines() returns the number of lines buffered (may be 0) or
+a negative value in case of errors.
BIO_set_read_buffer_size(), BIO_set_write_buffer_size() and BIO_set_buffer_size()
-return 1 if the buffer was successfully resized or 0 for failure.
+return 1 if the buffer was successfully resized or <=0 for failure.
-BIO_set_buffer_read_data() returns 1 if the data was set correctly or 0 if
+BIO_set_buffer_read_data() returns 1 if the data was set correctly or <=0 if
there was an error.
=head1 SEE ALSO
@@ -92,9 +93,9 @@ L<BIO_ctrl(3)>.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_f_cipher.pod b/doc/man3/BIO_f_cipher.pod
index 65c3d0b1f52e..3a11cabd3c4c 100644
--- a/doc/man3/BIO_f_cipher.pod
+++ b/doc/man3/BIO_f_cipher.pod
@@ -6,16 +6,16 @@ BIO_f_cipher, BIO_set_cipher, BIO_get_cipher_status, BIO_get_cipher_ctx - cipher
=head1 SYNOPSIS
-=for comment multiple includes
+=for openssl multiple includes
#include <openssl/bio.h>
#include <openssl/evp.h>
const BIO_METHOD *BIO_f_cipher(void);
- void BIO_set_cipher(BIO *b, const EVP_CIPHER *cipher,
- unsigned char *key, unsigned char *iv, int enc);
- int BIO_get_cipher_status(BIO *b)
- int BIO_get_cipher_ctx(BIO *b, EVP_CIPHER_CTX **pctx)
+ int BIO_set_cipher(BIO *b, const EVP_CIPHER *cipher,
+ const unsigned char *key, const unsigned char *iv, int enc);
+ int BIO_get_cipher_status(BIO *b);
+ int BIO_get_cipher_ctx(BIO *b, EVP_CIPHER_CTX **pctx);
=head1 DESCRIPTION
@@ -62,18 +62,18 @@ be achieved by preceding the cipher BIO with a buffering BIO.
BIO_f_cipher() returns the cipher BIO method.
-BIO_set_cipher() does not return a value.
+BIO_set_cipher() returns 1 for success and 0 for failure.
-BIO_get_cipher_status() returns 1 for a successful decrypt and 0
+BIO_get_cipher_status() returns 1 for a successful decrypt and <=0
for failure.
-BIO_get_cipher_ctx() currently always returns 1.
+BIO_get_cipher_ctx() returns 1 for success and <=0 for failure.
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_f_md.pod b/doc/man3/BIO_f_md.pod
index 7074202a5676..c2b825e35272 100644
--- a/doc/man3/BIO_f_md.pod
+++ b/doc/man3/BIO_f_md.pod
@@ -6,7 +6,7 @@ BIO_f_md, BIO_set_md, BIO_get_md, BIO_get_md_ctx - message digest BIO filter
=head1 SYNOPSIS
-=for comment multiple includes
+=for openssl multiple includes
#include <openssl/bio.h>
#include <openssl/evp.h>
@@ -69,7 +69,7 @@ if the standard calls such as BIO_set_md() are not sufficiently flexible.
BIO_f_md() returns the digest BIO method.
BIO_set_md(), BIO_get_md() and BIO_md_ctx() return 1 for success and
-0 for failure.
+<=0 for failure.
=head1 EXAMPLES
@@ -128,7 +128,7 @@ outputs them. This could be used with the examples above.
if (!mdtmp)
break;
BIO_get_md(mdtmp, &md);
- printf("%s digest", OBJ_nid2sn(EVP_MD_type(md)));
+ printf("%s digest", OBJ_nid2sn(EVP_MD_get_type(md)));
mdlen = BIO_gets(mdtmp, mdbuf, EVP_MAX_MD_SIZE);
for (i = 0; i < mdlen; i++) printf(":%02X", mdbuf[i]);
printf("\n");
@@ -152,9 +152,9 @@ BIO was initialized first.
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_f_null.pod b/doc/man3/BIO_f_null.pod
index 53069b497a92..c11041922418 100644
--- a/doc/man3/BIO_f_null.pod
+++ b/doc/man3/BIO_f_null.pod
@@ -31,7 +31,7 @@ BIO_f_null() returns the null filter BIO method.
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_f_prefix.pod b/doc/man3/BIO_f_prefix.pod
new file mode 100644
index 000000000000..3c98ef311bb5
--- /dev/null
+++ b/doc/man3/BIO_f_prefix.pod
@@ -0,0 +1,70 @@
+=pod
+
+=head1 NAME
+
+BIO_f_prefix, BIO_set_prefix, BIO_set_indent, BIO_get_indent
+- prefix BIO filter
+
+=head1 SYNOPSIS
+
+ #include <openssl/bio.h>
+
+ const BIO_METHOD *BIO_f_prefix(void);
+ long BIO_set_prefix(BIO *b, const char *prefix);
+ long BIO_set_indent(BIO *b, long indent);
+ long BIO_get_indent(BIO *b);
+
+=head1 DESCRIPTION
+
+BIO_f_cipher() returns the prefix BIO method. This is a filter for
+text output, where each line gets automatically prefixed and indented
+according to user input.
+
+The prefix and the indentation are combined. For each line of output
+going through this filter, the prefix is output first, then the amount
+of additional spaces indicated by the indentation, and then the line
+itself.
+
+By default, there is no prefix, and indentation is set to 0.
+
+BIO_set_prefix() sets the prefix to be used for future lines of
+text, using I<prefix>. I<prefix> may be NULL, signifying that there
+should be no prefix. If I<prefix> isn't NULL, this function makes a
+copy of it.
+
+BIO_set_indent() sets the indentation to be used for future lines of
+text, using I<indent>. Negative values are not allowed.
+
+BIO_get_indent() gets the current indentation.
+
+=head1 NOTES
+
+BIO_set_prefix(), BIO_set_indent() and BIO_get_indent() are
+implemented as macros.
+
+=head1 RETURN VALUES
+
+BIO_f_prefix() returns the prefix BIO method.
+
+BIO_set_prefix() returns 1 if the prefix was correctly set, or <=0 on
+failure.
+
+BIO_set_indent() returns 1 if the prefix was correctly set, or <=0 on
+failure.
+
+BIO_get_indent() returns the current indentation, or a negative value for failure.
+
+=head1 SEE ALSO
+
+L<bio(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/BIO_f_readbuffer.pod b/doc/man3/BIO_f_readbuffer.pod
new file mode 100644
index 000000000000..35e708f9ad62
--- /dev/null
+++ b/doc/man3/BIO_f_readbuffer.pod
@@ -0,0 +1,61 @@
+=pod
+
+=head1 NAME
+
+BIO_f_readbuffer
+- read only buffering BIO that supports BIO_tell() and BIO_seek()
+
+=head1 SYNOPSIS
+
+ #include <openssl/bio.h>
+
+ const BIO_METHOD *BIO_f_readbuffer(void);
+
+=head1 DESCRIPTION
+
+BIO_f_readbuffer() returns the read buffering BIO method.
+
+This BIO filter can be inserted on top of BIO's that do not support BIO_tell()
+or BIO_seek() (e.g. A file BIO that uses stdin).
+
+Data read from a read buffering BIO comes from an internal buffer which is
+filled from the next BIO in the chain.
+
+BIO_gets() is supported for read buffering BIOs.
+Writing data to a read buffering BIO is not supported.
+
+Calling BIO_reset() on a read buffering BIO does not clear any buffered data.
+
+=head1 NOTES
+
+Read buffering BIOs implement BIO_read_ex() by using BIO_read_ex() operations
+on the next BIO (e.g. a file BIO) in the chain and storing the result in an
+internal buffer, from which bytes are given back to the caller as appropriate
+for the call. BIO_read_ex() is guaranteed to give the caller the number of bytes
+it asks for, unless there's an error or end of communication is reached in the
+next BIO. The internal buffer can grow to cache the entire contents of the next
+BIO in the chain. BIO_seek() uses the internal buffer, so that it can only seek
+into data that is already read.
+
+=head1 RETURN VALUES
+
+BIO_f_readbuffer() returns the read buffering BIO method.
+
+=head1 SEE ALSO
+
+L<bio(7)>,
+L<BIO_read(3)>,
+L<BIO_gets(3)>,
+L<BIO_reset(3)>,
+L<BIO_ctrl(3)>.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/BIO_f_ssl.pod b/doc/man3/BIO_f_ssl.pod
index 8866785cfe1d..11c1bd35eb57 100644
--- a/doc/man3/BIO_f_ssl.pod
+++ b/doc/man3/BIO_f_ssl.pod
@@ -11,7 +11,7 @@ BIO_ssl_shutdown - SSL BIO
=head1 SYNOPSIS
-=for comment multiple includes
+=for openssl multiple includes
#include <openssl/bio.h>
#include <openssl/ssl.h>
@@ -95,12 +95,15 @@ chain and calling SSL_shutdown() on its internal SSL
pointer.
BIO_do_handshake() attempts to complete an SSL handshake on the
-supplied BIO and establish the SSL connection. It returns 1
-if the connection was established successfully. A zero or negative
-value is returned if the connection could not be established, the
-call BIO_should_retry() should be used for non blocking connect BIOs
-to determine if the call should be retried. If an SSL connection has
-already been established this call has no effect.
+supplied BIO and establish the SSL connection.
+For non-SSL BIOs the connection is done typically at TCP level.
+If domain name resolution yields multiple IP addresses all of them are tried
+after connect() failures.
+The function returns 1 if the connection was established successfully.
+A zero or negative value is returned if the connection could not be established.
+The call BIO_should_retry() should be used for nonblocking connect BIOs
+to determine if the call should be retried.
+If a connection has already been established this call has no effect.
=head1 NOTES
@@ -170,9 +173,6 @@ unencrypted example in L<BIO_s_connect(3)>.
exit(1);
}
- /* Don't want any retries */
- SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
-
/* XXX We might want to do other things with ssl here */
/* An empty host part means the loopback address */
@@ -230,7 +230,6 @@ a client and also echoes the request to standard output.
exit(1);
}
- SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
bbio = BIO_new(BIO_f_buffer());
sbio = BIO_push(bbio, sbio);
acpt = BIO_new_accept("4433");
@@ -244,13 +243,20 @@ a client and also echoes the request to standard output.
BIO_set_accept_bios(acpt, sbio);
out = BIO_new_fp(stdout, BIO_NOCLOSE);
- /* Setup accept BIO */
+ /* First call to BIO_do_accept() sets up accept BIO */
if (BIO_do_accept(acpt) <= 0) {
fprintf(stderr, "Error setting up accept BIO\n");
ERR_print_errors_fp(stderr);
exit(1);
}
+/* Second call to BIO_do_accept() waits for incoming connection */
+ if (BIO_do_accept(acpt) <= 0) {
+ fprintf(stderr, "Error accepting connection\n");
+ ERR_print_errors_fp(stderr);
+ exit(1);
+ }
+
/* We only want one connection so remove and free accept BIO */
sbio = BIO_pop(acpt);
BIO_free_all(acpt);
@@ -292,9 +298,9 @@ be modified to handle this fix or they may free up an already freed BIO.
=head1 COPYRIGHT
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_find_type.pod b/doc/man3/BIO_find_type.pod
index b18b615a33d2..99bab8cce85c 100644
--- a/doc/man3/BIO_find_type.pod
+++ b/doc/man3/BIO_find_type.pod
@@ -24,7 +24,7 @@ found.
The following general types are defined:
B<BIO_TYPE_DESCRIPTOR>, B<BIO_TYPE_FILTER>, and B<BIO_TYPE_SOURCE_SINK>.
-For a list of the specific types, see the B<openssl/bio.h> header file.
+For a list of the specific types, see the F<< <openssl/bio.h> >> header file.
BIO_next() returns the next BIO in a chain. It can be used to traverse all BIOs
in a chain or used in conjunction with BIO_find_type() to find all BIOs of a
@@ -60,9 +60,9 @@ Traverse a chain looking for digest BIOs:
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_get_data.pod b/doc/man3/BIO_get_data.pod
index da1651c7576f..aeb6b1c7e9ba 100644
--- a/doc/man3/BIO_get_data.pod
+++ b/doc/man3/BIO_get_data.pod
@@ -47,7 +47,7 @@ BIO_get_shutdown() returns the stat of the BIO's shutdown (i.e. BIO_CLOSE) flag.
=head1 SEE ALSO
-L<bio>, L<BIO_meth_new>
+L<bio(7)>, L<BIO_meth_new(3)>
=head1 HISTORY
@@ -55,9 +55,9 @@ The functions described here were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_get_ex_new_index.pod b/doc/man3/BIO_get_ex_new_index.pod
index 89008531d381..f26b573350d9 100644
--- a/doc/man3/BIO_get_ex_new_index.pod
+++ b/doc/man3/BIO_get_ex_new_index.pod
@@ -3,21 +3,31 @@
=head1 NAME
BIO_get_ex_new_index, BIO_set_ex_data, BIO_get_ex_data,
-ENGINE_get_ex_new_index, ENGINE_set_ex_data, ENGINE_get_ex_data,
-UI_get_ex_new_index, UI_set_ex_data, UI_get_ex_data,
-X509_get_ex_new_index, X509_set_ex_data, X509_get_ex_data,
-X509_STORE_get_ex_new_index, X509_STORE_set_ex_data, X509_STORE_get_ex_data,
-X509_STORE_CTX_get_ex_new_index, X509_STORE_CTX_set_ex_data, X509_STORE_CTX_get_ex_data,
+BIO_set_app_data, BIO_get_app_data,
DH_get_ex_new_index, DH_set_ex_data, DH_get_ex_data,
DSA_get_ex_new_index, DSA_set_ex_data, DSA_get_ex_data,
-ECDH_get_ex_new_index, ECDH_set_ex_data, ECDH_get_ex_data,
EC_KEY_get_ex_new_index, EC_KEY_set_ex_data, EC_KEY_get_ex_data,
-RSA_get_ex_new_index, RSA_set_ex_data, RSA_get_ex_data
+ENGINE_get_ex_new_index, ENGINE_set_ex_data, ENGINE_get_ex_data,
+EVP_PKEY_get_ex_new_index, EVP_PKEY_set_ex_data, EVP_PKEY_get_ex_data,
+RSA_get_ex_new_index, RSA_set_ex_data, RSA_get_ex_data,
+RSA_set_app_data, RSA_get_app_data,
+SSL_get_ex_new_index, SSL_set_ex_data, SSL_get_ex_data,
+SSL_set_app_data, SSL_get_app_data,
+SSL_CTX_get_ex_new_index, SSL_CTX_set_ex_data, SSL_CTX_get_ex_data,
+SSL_CTX_set_app_data, SSL_CTX_get_app_data,
+SSL_SESSION_get_ex_new_index, SSL_SESSION_set_ex_data, SSL_SESSION_get_ex_data,
+SSL_SESSION_set_app_data, SSL_SESSION_get_app_data,
+UI_get_ex_new_index, UI_set_ex_data, UI_get_ex_data,
+UI_set_app_data, UI_get_app_data,
+X509_STORE_CTX_get_ex_new_index, X509_STORE_CTX_set_ex_data, X509_STORE_CTX_get_ex_data,
+X509_STORE_CTX_set_app_data, X509_STORE_CTX_get_app_data,
+X509_STORE_get_ex_new_index, X509_STORE_set_ex_data, X509_STORE_get_ex_data,
+X509_get_ex_new_index, X509_set_ex_data, X509_get_ex_data
- application-specific data
=head1 SYNOPSIS
-=for comment generic
+=for openssl generic
#include <openssl/x509.h>
@@ -28,13 +38,49 @@ RSA_get_ex_new_index, RSA_set_ex_data, RSA_get_ex_data
int TYPE_set_ex_data(TYPE *d, int idx, void *arg);
- void *TYPE_get_ex_data(TYPE *d, int idx);
+ void *TYPE_get_ex_data(const TYPE *d, int idx);
+
+ #define TYPE_set_app_data(TYPE *d, void *arg)
+ #define TYPE_get_app_data(TYPE *d)
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+ int DH_set_ex_data(DH *type, int idx, void *arg);
+ void *DH_get_ex_data(DH *type, int idx);
+ int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+ int DSA_set_ex_data(DSA *type, int idx, void *arg);
+ void *DSA_get_ex_data(DSA *type, int idx);
+ int EC_KEY_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+ int EC_KEY_set_ex_data(EC_KEY *type, int idx, void *arg);
+ void *EC_KEY_get_ex_data(EC_KEY *type, int idx);
+ int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+ int RSA_set_ex_data(RSA *type, int idx, void *arg);
+ void *RSA_get_ex_data(RSA *type, int idx);
+ int RSA_set_app_data(RSA *type, void *arg);
+ void *RSA_get_app_data(RSA *type);
+ int ENGINE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+ int ENGINE_set_ex_data(ENGINE *type, int idx, void *arg);
+ void *ENGINE_get_ex_data(ENGINE *type, int idx);
=head1 DESCRIPTION
In the description here, I<TYPE> is used a placeholder
-for any of the OpenSSL datatypes listed in
-L<CRYPTO_get_ex_new_index(3)>.
+for any of the OpenSSL datatypes listed in L<CRYPTO_get_ex_new_index(3)>.
+
+All functions with a I<TYPE> of B<DH>, B<DSA>, B<RSA> and B<EC_KEY> are deprecated.
+Applications should instead use EVP_PKEY_set_ex_data(),
+EVP_PKEY_get_ex_data() and EVP_PKEY_get_ex_new_index().
+
+All functions with a I<TYPE> of B<ENGINE> are deprecated.
+Applications using engines should be replaced by providers.
These functions handle application-specific data for OpenSSL data
structures.
@@ -48,6 +94,14 @@ an offset into the opaque exdata part of the TYPE object.
TYPE_get_ex_data() is a function that calls CRYPTO_get_ex_data() with
an offset into the opaque exdata part of the TYPE object.
+For compatibility with previous releases, the exdata index of zero is
+reserved for "application data." There are two convenience functions for
+this.
+TYPE_set_app_data() is a macro that invokes TYPE_set_ex_data() with
+B<idx> set to zero.
+TYPE_get_app_data() is a macro that invokes TYPE_get_ex_data() with
+B<idx> set to zero.
+
=head1 RETURN VALUES
TYPE_get_ex_new_index() returns a new index on success or -1 on error.
@@ -60,11 +114,20 @@ TYPE_get_ex_data() returns the application data or NULL if an error occurred.
L<CRYPTO_get_ex_new_index(3)>.
+=head1 HISTORY
+
+The functions DH_get_ex_new_index(), DH_set_ex_data(), DH_get_ex_data(),
+DSA_get_ex_new_index(), DSA_set_ex_data(), DSA_get_ex_data(),
+EC_KEY_get_ex_new_index(), EC_KEY_set_ex_data(), EC_KEY_get_ex_data(),
+ENGINE_get_ex_new_index(), ENGINE_set_ex_data(), ENGINE_get_ex_data(),
+RSA_get_ex_new_index(), RSA_set_ex_data(), RSA_get_ex_data(),
+RSA_set_app_data() and RSA_get_app_data() were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_meth_new.pod b/doc/man3/BIO_meth_new.pod
index 7a1e72d4fc6c..86301b97189f 100644
--- a/doc/man3/BIO_meth_new.pod
+++ b/doc/man3/BIO_meth_new.pod
@@ -60,20 +60,20 @@ BIO_meth_set_callback_ctrl - Routines to build up BIO methods
The B<BIO_METHOD> type is a structure used for the implementation of new BIO
types. It provides a set of functions used by OpenSSL for the implementation
-of the various BIO capabilities. See the L<bio> page for more information.
+of the various BIO capabilities. See the L<bio(7)> page for more information.
BIO_meth_new() creates a new B<BIO_METHOD> structure. It should be given a
unique integer B<type> and a string that represents its B<name>.
Use BIO_get_new_index() to get the value for B<type>.
The set of
-standard OpenSSL provided BIO types is provided in B<bio.h>. Some examples
-include B<BIO_TYPE_BUFFER> and B<BIO_TYPE_CIPHER>. Filter BIOs should have a
-type which have the "filter" bit set (B<BIO_TYPE_FILTER>). Source/sink BIOs
-should have the "source/sink" bit set (B<BIO_TYPE_SOURCE_SINK>). File descriptor
-based BIOs (e.g. socket, fd, connect, accept etc) should additionally have the
-"descriptor" bit set (B<BIO_TYPE_DESCRIPTOR>). See the L<BIO_find_type> page for
-more information.
+standard OpenSSL provided BIO types is provided in F<< <openssl/bio.h> >>.
+Some examples include B<BIO_TYPE_BUFFER> and B<BIO_TYPE_CIPHER>. Filter BIOs
+should have a type which have the "filter" bit set (B<BIO_TYPE_FILTER>).
+Source/sink BIOs should have the "source/sink" bit set (B<BIO_TYPE_SOURCE_SINK>).
+File descriptor based BIOs (e.g. socket, fd, connect, accept etc) should
+additionally have the "descriptor" bit set (B<BIO_TYPE_DESCRIPTOR>). See the
+L<BIO_find_type(3)> page for more information.
BIO_meth_free() destroys a B<BIO_METHOD> structure and frees up any memory
associated with it.
@@ -108,7 +108,7 @@ application calling BIO_gets(). The parameters for the function have the same
meaning as for BIO_gets().
BIO_meth_get_ctrl() and BIO_meth_set_ctrl() get and set the function used for
-processing ctrl messages in the BIO respectively. See the L<BIO_ctrl> page for
+processing ctrl messages in the BIO respectively. See the L<BIO_ctrl(3)> page for
more information. This function will be called in response to the application
calling BIO_ctrl(). The parameters for the function have the same meaning as for
BIO_ctrl().
@@ -118,7 +118,10 @@ for creating a new instance of the BIO respectively. This function will be
called in response to the application calling BIO_new() and passing
in a pointer to the current BIO_METHOD. The BIO_new() function will allocate the
memory for the new BIO, and a pointer to this newly allocated structure will
-be passed as a parameter to the function.
+be passed as a parameter to the function. If a create function is set,
+BIO_new() will not mark the BIO as initialised on allocation.
+L<BIO_set_init(3)> must then be called either by the create function, or later,
+by a BIO ctrl function, once BIO initialisation is complete.
BIO_meth_get_destroy() and BIO_meth_set_destroy() get and set the function used
for destroying an instance of a BIO respectively. This function will be
@@ -146,7 +149,7 @@ The B<BIO_meth_get> functions return the corresponding function pointers.
=head1 SEE ALSO
-L<bio>, L<BIO_find_type>, L<BIO_ctrl>, L<BIO_read_ex>, L<BIO_new>
+L<bio(7)>, L<BIO_find_type(3)>, L<BIO_ctrl(3)>, L<BIO_read_ex(3)>, L<BIO_new(3)>
=head1 HISTORY
@@ -154,9 +157,9 @@ The functions described here were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_new.pod b/doc/man3/BIO_new.pod
index c33eb9d02e6a..282da275eebe 100644
--- a/doc/man3/BIO_new.pod
+++ b/doc/man3/BIO_new.pod
@@ -2,22 +2,28 @@
=head1 NAME
-BIO_new, BIO_up_ref, BIO_free, BIO_vfree, BIO_free_all
+BIO_new_ex, BIO_new, BIO_up_ref, BIO_free, BIO_vfree, BIO_free_all
- BIO allocation and freeing functions
=head1 SYNOPSIS
#include <openssl/bio.h>
- BIO * BIO_new(const BIO_METHOD *type);
- int BIO_up_ref(BIO *a);
- int BIO_free(BIO *a);
- void BIO_vfree(BIO *a);
- void BIO_free_all(BIO *a);
+ BIO *BIO_new_ex(OSSL_LIB_CTX *libctx, const BIO_METHOD *type);
+ BIO *BIO_new(const BIO_METHOD *type);
+ int BIO_up_ref(BIO *a);
+ int BIO_free(BIO *a);
+ void BIO_vfree(BIO *a);
+ void BIO_free_all(BIO *a);
=head1 DESCRIPTION
-The BIO_new() function returns a new BIO using method B<type>.
+The BIO_new_ex() function returns a new BIO using method B<type> associated with
+the library context I<libctx> (see OSSL_LIB_CTX(3)). The library context may be
+NULL to indicate the default library context.
+
+The BIO_new() is the same as BIO_new_ex() except the default library context is
+always used.
BIO_up_ref() increments the reference count associated with the BIO object.
@@ -35,7 +41,7 @@ If B<a> is NULL nothing is done.
=head1 RETURN VALUES
-BIO_new() returns a newly created BIO or NULL if the call fails.
+BIO_new_ex() and BIO_new() return a newly created BIO or NULL if the call fails.
BIO_up_ref() and BIO_free() return 1 for success and 0 for failure.
@@ -53,6 +59,8 @@ on it other than the discarded return value.
BIO_set() was removed in OpenSSL 1.1.0 as BIO type is now opaque.
+BIO_new_ex() was added in OpenSSL 3.0.
+
=head1 EXAMPLES
Create a memory BIO:
@@ -61,9 +69,9 @@ Create a memory BIO:
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_new_CMS.pod b/doc/man3/BIO_new_CMS.pod
index f8d4c3bde6ee..4872b56ee4e3 100644
--- a/doc/man3/BIO_new_CMS.pod
+++ b/doc/man3/BIO_new_CMS.pod
@@ -67,7 +67,7 @@ The BIO_new_CMS() function was added in OpenSSL 1.0.0.
Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_parse_hostserv.pod b/doc/man3/BIO_parse_hostserv.pod
index 35c14d1bc1c9..8898ae2266d2 100644
--- a/doc/man3/BIO_parse_hostserv.pod
+++ b/doc/man3/BIO_parse_hostserv.pod
@@ -38,7 +38,8 @@ The syntax the BIO_parse_hostserv() recognises is:
The host part can be a name or an IP address. If it's a IPv6
address, it MUST be enclosed in brackets, such as '[::1]'.
-The service part can be a service name or its port number.
+The service part can be a service name or its port number. A service name
+will be mapped to a port number using the system function getservbyname().
The returned values will depend on the given B<hostserv> string
and B<hostserv_prio>, as follows:
@@ -68,9 +69,9 @@ L<BIO_ADDRINFO(3)>
=head1 COPYRIGHT
-Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_printf.pod b/doc/man3/BIO_printf.pod
index 8045b645cbf2..221881d123ca 100644
--- a/doc/man3/BIO_printf.pod
+++ b/doc/man3/BIO_printf.pod
@@ -9,25 +9,25 @@ BIO_printf, BIO_vprintf, BIO_snprintf, BIO_vsnprintf
#include <openssl/bio.h>
- int BIO_printf(BIO *bio, const char *format, ...)
- int BIO_vprintf(BIO *bio, const char *format, va_list args)
+ int BIO_printf(BIO *bio, const char *format, ...);
+ int BIO_vprintf(BIO *bio, const char *format, va_list args);
- int BIO_snprintf(char *buf, size_t n, const char *format, ...)
- int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
+ int BIO_snprintf(char *buf, size_t n, const char *format, ...);
+ int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args);
=head1 DESCRIPTION
BIO_printf() is similar to the standard C printf() function, except that
-the output is sent to the specified BIO, B<bio>, rather than standard
+the output is sent to the specified BIO, I<bio>, rather than standard
output. All common format specifiers are supported.
BIO_vprintf() is similar to the vprintf() function found on many platforms,
-the output is sent to the specified BIO, B<bio>, rather than standard
+the output is sent to the specified BIO, I<bio>, rather than standard
output. All common format specifiers are supported. The argument
-list B<args> is a stdarg argument list.
+list I<args> is a stdarg argument list.
BIO_snprintf() is for platforms that do not have the common snprintf()
-function. It is like sprintf() except that the size parameter, B<n>,
+function. It is like sprintf() except that the size parameter, I<n>,
specifies the size of the output buffer.
BIO_vsnprintf() is to BIO_snprintf() as BIO_vprintf() is to BIO_printf().
@@ -38,11 +38,18 @@ All functions return the number of bytes written, or -1 on error.
For BIO_snprintf() and BIO_vsnprintf() this includes when the output
buffer is too small.
+=head1 NOTES
+
+Except when I<n> is 0, both BIO_snprintf() and BIO_vsnprintf() always
+terminate their output with C<'\0'>. This includes cases where -1 is
+returned, such as when there is insufficient space to output the whole
+string.
+
=head1 COPYRIGHT
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_push.pod b/doc/man3/BIO_push.pod
index e16daafe8822..84ce3f042d1e 100644
--- a/doc/man3/BIO_push.pod
+++ b/doc/man3/BIO_push.pod
@@ -80,7 +80,7 @@ except that I<md2> will no more be applied.
=head1 SEE ALSO
-L<bio>
+L<bio(7)>
=head1 HISTORY
@@ -90,7 +90,7 @@ The BIO_set_next() function was added in OpenSSL 1.1.0.
Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_read.pod b/doc/man3/BIO_read.pod
index d0ebf32caace..f337aab353bb 100644
--- a/doc/man3/BIO_read.pod
+++ b/doc/man3/BIO_read.pod
@@ -2,7 +2,8 @@
=head1 NAME
-BIO_read_ex, BIO_write_ex, BIO_read, BIO_write, BIO_gets, BIO_puts
+BIO_read_ex, BIO_write_ex, BIO_read, BIO_write,
+BIO_gets, BIO_get_line, BIO_puts
- BIO I/O functions
=head1 SYNOPSIS
@@ -14,43 +15,69 @@ BIO_read_ex, BIO_write_ex, BIO_read, BIO_write, BIO_gets, BIO_puts
int BIO_read(BIO *b, void *data, int dlen);
int BIO_gets(BIO *b, char *buf, int size);
+ int BIO_get_line(BIO *b, char *buf, int size);
int BIO_write(BIO *b, const void *data, int dlen);
int BIO_puts(BIO *b, const char *buf);
=head1 DESCRIPTION
-BIO_read_ex() attempts to read B<dlen> bytes from BIO B<b> and places the data
-in B<data>. If any bytes were successfully read then the number of bytes read is
-stored in B<*readbytes>.
+BIO_read_ex() attempts to read I<dlen> bytes from BIO I<b> and places the data
+in I<data>. If any bytes were successfully read then the number of bytes read is
+stored in I<*readbytes>.
-BIO_write_ex() attempts to write B<dlen> bytes from B<data> to BIO B<b>. If
-successful then the number of bytes written is stored in B<*written>.
+BIO_write_ex() attempts to write I<dlen> bytes from I<data> to BIO I<b>.
+If successful then the number of bytes written is stored in I<*written>
+unless I<written> is NULL.
-BIO_read() attempts to read B<len> bytes from BIO B<b> and places
-the data in B<buf>.
+BIO_read() attempts to read I<len> bytes from BIO I<b> and places
+the data in I<buf>.
BIO_gets() performs the BIOs "gets" operation and places the data
-in B<buf>. Usually this operation will attempt to read a line of data
-from the BIO of maximum length B<size-1>. There are exceptions to this,
+in I<buf>. Usually this operation will attempt to read a line of data
+from the BIO of maximum length I<size-1>. There are exceptions to this,
however; for example, BIO_gets() on a digest BIO will calculate and
return the digest and other BIOs may not support BIO_gets() at all.
The returned string is always NUL-terminated and the '\n' is preserved
if present in the input data.
+On binary input there may be NUL characters within the string;
+in this case the return value (if nonnegative) may give an incorrect length.
-BIO_write() attempts to write B<len> bytes from B<buf> to BIO B<b>.
+BIO_get_line() attempts to read from BIO I<b> a line of data up to the next '\n'
+or the maximum length I<size-1> is reached and places the data in I<buf>.
+The returned string is always NUL-terminated and the '\n' is preserved
+if present in the input data.
+On binary input there may be NUL characters within the string;
+in this case the return value (if nonnegative) gives the actual length read.
+For implementing this, unfortunately the data needs to be read byte-by-byte.
-BIO_puts() attempts to write a NUL-terminated string B<buf> to BIO B<b>.
+BIO_write() attempts to write I<len> bytes from I<buf> to BIO I<b>.
+
+BIO_puts() attempts to write a NUL-terminated string I<buf> to BIO I<b>.
=head1 RETURN VALUES
-BIO_read_ex() and BIO_write_ex() return 1 if data was successfully read or
-written, and 0 otherwise.
+BIO_read_ex() returns 1 if data was successfully read, and 0 otherwise.
+
+BIO_write_ex() returns 1 if no error was encountered writing data, 0 otherwise.
+Requesting to write 0 bytes is not considered an error.
+
+BIO_write() returns -2 if the "write" operation is not implemented by the BIO
+or -1 on other errors.
+Otherwise it returns the number of bytes written.
+This may be 0 if the BIO I<b> is NULL or I<dlen <= 0>.
+
+BIO_gets() returns -2 if the "gets" operation is not implemented by the BIO
+or -1 on other errors.
+Otherwise it typically returns the amount of data read,
+but depending on the implementation it may return only the length up to
+the first NUL character contained in the data read.
+In any case the trailing NUL that is added after the data read
+is not included in the length returned.
All other functions return either the amount of data successfully read or
written (if the return value is positive) or that no data was successfully
read or written if the result is 0 or -1. If the return value is -2 then
-the operation is not implemented in the specific BIO type. The trailing
-NUL is not included in the length returned by BIO_gets().
+the operation is not implemented in the specific BIO type.
=head1 NOTES
@@ -72,9 +99,9 @@ a retry instead of blocking.
See L<BIO_should_retry(3)> for details of how to
determine the cause of a retry and other I/O issues.
-If the BIO_gets() function is not supported by a BIO then it possible to
-work around this by adding a buffering BIO L<BIO_f_buffer(3)>
-to the chain.
+If the "gets" method is not supported by a BIO then BIO_get_line() can be used.
+It is also possible to make BIO_gets() usable even if the "gets" method is not
+supported by adding a buffering BIO L<BIO_f_buffer(3)> to the chain.
=head1 SEE ALSO
@@ -82,14 +109,19 @@ L<BIO_should_retry(3)>
=head1 HISTORY
-BIO_gets() on 1.1.0 and older when called on BIO_fd() based BIO does not
+BIO_gets() on 1.1.0 and older when called on BIO_fd() based BIO did not
keep the '\n' at the end of the line in the buffer.
+BIO_get_line() was added in OpenSSL 3.0.
+
+BIO_write_ex() returns 1 if the size of the data to write is 0 and the
+I<written> parameter of the function can be NULL since OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_s_accept.pod b/doc/man3/BIO_s_accept.pod
index 312c881bbc49..25a752998cae 100644
--- a/doc/man3/BIO_s_accept.pod
+++ b/doc/man3/BIO_s_accept.pod
@@ -73,10 +73,12 @@ connect BIOs, that is it can be a numerical port string or a
string to lookup using getservbyname() and a string table.
BIO_set_accept_port() uses the string B<port> to set the accept
-port. "port" has the same syntax as the port specified in
+port of BIO I<b>. "port" has the same syntax as the port specified in
BIO_set_conn_port() for connect BIOs, that is it can be a numerical
port string or a string to lookup using getservbyname() and a string
table.
+If the given port is C<0> then a random available port is chosen.
+It may be queried using BIO_sock_info() and L<BIO_ADDR_service_string(3)>.
BIO_new_accept() combines BIO_new() and BIO_set_accept_name() into
a single call: that is it creates a new accept BIO with port
@@ -92,6 +94,12 @@ buffering or SSL BIO is required for each connection. The
chain of BIOs must not be freed after this call, they will
be automatically freed when the accept BIO is freed.
+BIO_get_accept_ip_family() returns the IP family accepted by the BIO I<b>,
+which may be B<BIO_FAMILY_IPV4>, B<BIO_FAMILY_IPV6>, or B<BIO_FAMILY_IPANY>.
+
+BIO_set_accept_ip_family() sets the IP family I<family> accepted by BIO I<b>.
+The default is B<BIO_FAMILY_IPANY>.
+
BIO_set_bind_mode() and BIO_get_bind_mode() set and retrieve
the current bind mode. If B<BIO_BIND_NORMAL> (the default) is set
then another socket cannot be bound to the same port. If
@@ -161,16 +169,16 @@ BIO_set_bind_mode(), BIO_get_bind_mode() and BIO_do_accept() are macros.
BIO_do_accept(),
BIO_set_accept_name(), BIO_set_accept_port(), BIO_set_nbio_accept(),
BIO_set_accept_bios(), BIO_set_accept_ip_family(), and BIO_set_bind_mode()
-return 1 for success and 0 or -1 for failure.
+return 1 for success and <=0 for failure.
BIO_get_accept_name() returns the accept name or NULL on error.
BIO_get_peer_name() returns the peer name or NULL on error.
BIO_get_accept_port() returns the accept port as a string or NULL on error.
BIO_get_peer_port() returns the peer port as a string or NULL on error.
-BIO_get_accept_ip_family() returns the IP family or -1 on error.
+BIO_get_accept_ip_family() returns the IP family or <=0 on error.
-BIO_get_bind_mode() returns the set of B<BIO_BIND> flags, or -1 on failure.
+BIO_get_bind_mode() returns the set of B<BIO_BIND> flags, or <=0 on failure.
BIO_new_accept() returns a BIO or NULL on error.
@@ -181,7 +189,7 @@ down each and finally closes both down.
BIO *abio, *cbio, *cbio2;
- /* First call to BIO_accept() sets up accept BIO */
+ /* First call to BIO_do_accept() sets up accept BIO */
abio = BIO_new_accept("4444");
if (BIO_do_accept(abio) <= 0) {
fprintf(stderr, "Error setting up accept\n");
@@ -224,9 +232,9 @@ down each and finally closes both down.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_s_bio.pod b/doc/man3/BIO_s_bio.pod
index 4837d19440bb..653fe4785a49 100644
--- a/doc/man3/BIO_s_bio.pod
+++ b/doc/man3/BIO_s_bio.pod
@@ -193,7 +193,7 @@ L<BIO_should_retry(3)>, L<BIO_read_ex(3)>
Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_s_connect.pod b/doc/man3/BIO_s_connect.pod
index 1223fad831cb..ab813b32d031 100644
--- a/doc/man3/BIO_s_connect.pod
+++ b/doc/man3/BIO_s_connect.pod
@@ -2,19 +2,20 @@
=head1 NAME
-BIO_set_conn_address, BIO_get_conn_address,
-BIO_s_connect, BIO_new_connect, BIO_set_conn_hostname, BIO_set_conn_port,
-BIO_set_conn_ip_family, BIO_get_conn_ip_family,
+BIO_s_connect, BIO_new_connect,
+BIO_set_conn_hostname, BIO_set_conn_port,
+BIO_set_conn_address, BIO_set_conn_ip_family,
BIO_get_conn_hostname, BIO_get_conn_port,
+BIO_get_conn_address, BIO_get_conn_ip_family,
BIO_set_nbio, BIO_do_connect - connect BIO
=head1 SYNOPSIS
#include <openssl/bio.h>
- const BIO_METHOD * BIO_s_connect(void);
+ const BIO_METHOD *BIO_s_connect(void);
- BIO *BIO_new_connect(char *name);
+ BIO *BIO_new_connect(const char *name);
long BIO_set_conn_hostname(BIO *b, char *name);
long BIO_set_conn_port(BIO *b, char *port);
@@ -27,7 +28,7 @@ BIO_set_nbio, BIO_do_connect - connect BIO
long BIO_set_nbio(BIO *b, long n);
- int BIO_do_connect(BIO *b);
+ long BIO_do_connect(BIO *b);
=head1 DESCRIPTION
@@ -53,20 +54,18 @@ Calling BIO_reset() on a connect BIO will close any active
connection and reset the BIO into a state where it can connect
to the same host again.
-BIO_get_fd() places the underlying socket in B<c> if it is not NULL,
-it also returns the socket . If B<c> is not NULL it should be of
-type (int *).
+BIO_new_connect() combines BIO_new() and BIO_set_conn_hostname() into
+a single call: that is it creates a new connect BIO with hostname B<name>.
BIO_set_conn_hostname() uses the string B<name> to set the hostname.
The hostname can be an IP address; if the address is an IPv6 one, it
-must be enclosed with brackets. The hostname can also include the
-port in the form hostname:port.
+must be enclosed with brackets C<[> and C<]>.
+The hostname can also include the port in the form hostname:port;
+see L<BIO_parse_hostserv(3)> and BIO_set_conn_port() for details.
BIO_set_conn_port() sets the port to B<port>. B<port> can be the
-numerical form or a string such as "http". A string will be looked
-up first using getservbyname() on the host platform but if that
-fails a standard table of port names will be used. This internal
-list is http, telnet, socks, https, ssl, ftp, and gopher.
+numerical form or a service string such as "http", which
+will be mapped to a port number using the system function getservbyname().
BIO_set_conn_address() sets the address and port information using
a BIO_ADDR(3ssl).
@@ -91,14 +90,16 @@ is set. Blocking I/O is the default. The call to BIO_set_nbio()
should be made before the connection is established because
non blocking I/O is set during the connect process.
-BIO_new_connect() combines BIO_new() and BIO_set_conn_hostname() into
-a single call: that is it creates a new connect BIO with B<name>.
-
-BIO_do_connect() attempts to connect the supplied BIO. It returns 1
-if the connection was established successfully. A zero or negative
-value is returned if the connection could not be established, the
-call BIO_should_retry() should be used for non blocking connect BIOs
+BIO_do_connect() attempts to connect the supplied BIO.
+This performs an SSL/TLS handshake as far as supported by the BIO.
+For non-SSL BIOs the connection is done typically at TCP level.
+If domain name resolution yields multiple IP addresses all of them are tried
+after connect() failures.
+The function returns 1 if the connection was established successfully.
+A zero or negative value is returned if the connection could not be established.
+The call BIO_should_retry() should be used for non blocking connect BIOs
to determine if the call should be retried.
+If a connection has already been established this call has no effect.
=head1 NOTES
@@ -139,13 +140,10 @@ BIO_set_nbio(), and BIO_do_connect() are macros.
BIO_s_connect() returns the connect BIO method.
-BIO_get_fd() returns the socket or -1 if the BIO has not
-been initialized.
-
BIO_set_conn_address(), BIO_set_conn_port(), and BIO_set_conn_ip_family()
-always return 1.
+return 1 or <=0 if an error occurs.
-BIO_set_conn_hostname() returns 1 on success and 0 on failure.
+BIO_set_conn_hostname() returns 1 on success and <=0 on failure.
BIO_get_conn_address() returns the address information or NULL if none
was set.
@@ -158,10 +156,10 @@ BIO_get_conn_ip_family() returns the address family or -1 if none was set.
BIO_get_conn_port() returns a string representing the connected
port or NULL if not set.
-BIO_set_nbio() always returns 1.
+BIO_set_nbio() returns 1 or <=0 if an error occurs.
BIO_do_connect() returns 1 if the connection was successfully
-established and 0 or -1 if the connection failed.
+established and <=0 if the connection failed.
=head1 EXAMPLES
@@ -193,7 +191,7 @@ to retrieve a page and copy the result to standard output.
=head1 SEE ALSO
-L<BIO_ADDR(3)>
+L<BIO_ADDR(3)>, L<BIO_parse_hostserv(3)>
=head1 HISTORY
@@ -203,9 +201,9 @@ Use BIO_set_conn_address() and BIO_get_conn_address() instead.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_s_core.pod b/doc/man3/BIO_s_core.pod
new file mode 100644
index 000000000000..fbcd0b5c9c07
--- /dev/null
+++ b/doc/man3/BIO_s_core.pod
@@ -0,0 +1,72 @@
+=pod
+
+=head1 NAME
+
+BIO_s_core, BIO_new_from_core_bio - OSSL_CORE_BIO functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/bio.h>
+
+ const BIO_METHOD *BIO_s_core(void);
+
+ BIO *BIO_new_from_core_bio(OSSL_LIB_CTX *libctx, OSSL_CORE_BIO *corebio);
+
+=head1 DESCRIPTION
+
+BIO_s_core() returns the core BIO method function.
+
+A core BIO is treated as source/sink BIO which communicates to some external
+BIO. This is primarily useful to provider authors. A number of calls from
+libcrypto into a provider supply an OSSL_CORE_BIO parameter. This represents
+a BIO within libcrypto, but cannot be used directly by a provider. Instead it
+should be wrapped using a BIO_s_core().
+
+Once a BIO is contructed based on BIO_s_core(), the associated OSSL_CORE_BIO
+object should be set on it using BIO_set_data(3). Note that the BIO will only
+operate correctly if it is associated with a library context constructed using
+OSSL_LIB_CTX_new_from_dispatch(3). To associate the BIO with a library context
+construct it using BIO_new_ex(3).
+
+BIO_new_from_core_bio() is a convenience function that constructs a new BIO
+based on BIO_s_core() and that is associated with the given library context. It
+then also sets the OSSL_CORE_BIO object on the BIO using BIO_set_data(3).
+
+=head1 RETURN VALUES
+
+BIO_s_core() return a core BIO B<BIO_METHOD> structure.
+
+BIO_new_from_core_bio() returns a BIO structure on success or NULL on failure.
+A failure will most commonly be because the library context was not constructed
+using OSSL_LIB_CTX_new_from_dispatch(3).
+
+=head1 HISTORY
+
+BIO_s_core() and BIO_new_from_core_bio() were added in OpenSSL 3.0.
+
+=head1 EXAMPLES
+
+Create a core BIO and write some data to it:
+
+ int some_function(OSSL_LIB_CTX *libctx, OSSL_CORE_BIO *corebio) {
+ BIO *cbio = BIO_new_from_core_bio(libctx, corebio);
+
+ if (cbio == NULL)
+ return 0;
+
+ BIO_puts(cbio, "Hello World\n");
+
+ BIO_free(cbio);
+ return 1;
+ }
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/BIO_s_datagram.pod b/doc/man3/BIO_s_datagram.pod
new file mode 100644
index 000000000000..f5bdd831cfe1
--- /dev/null
+++ b/doc/man3/BIO_s_datagram.pod
@@ -0,0 +1,234 @@
+=pod
+
+=head1 NAME
+
+BIO_s_datagram, BIO_new_dgram,
+BIO_ctrl_dgram_connect,
+BIO_ctrl_set_connected,
+BIO_dgram_recv_timedout,
+BIO_dgram_send_timedout,
+BIO_dgram_get_peer,
+BIO_dgram_set_peer,
+BIO_dgram_get_mtu_overhead - Network BIO with datagram semantics
+
+=head1 SYNOPSIS
+
+ #include <openssl/bio.h>
+
+ BIO_METHOD *BIO_s_datagram(void);
+ BIO *BIO_new_dgram(int fd, int close_flag);
+
+ int BIO_ctrl_dgram_connect(BIO *bio, const BIO_ADDR *peer);
+ int BIO_ctrl_set_connected(BIO *bio, const BIO_ADDR *peer);
+ int BIO_dgram_recv_timedout(BIO *bio);
+ int BIO_dgram_send_timedout(BIO *bio);
+ int BIO_dgram_get_peer(BIO *bio, BIO_ADDR *peer);
+ int BIO_dgram_set_peer(BIO *bio, const BIO_ADDR *peer);
+ int BIO_dgram_get_mtu_overhead(BIO *bio);
+
+=head1 DESCRIPTION
+
+BIO_s_datagram() is a BIO implementation designed for use with network sockets
+which provide datagram semantics, such as UDP sockets. It is suitable for use
+with DTLSv1.
+
+Because BIO_s_datagram() has datagram semantics, a single BIO_write() call sends
+a single datagram and a single BIO_read() call receives a single datagram. If
+the size of the buffer passed to BIO_read() is inadequate, the datagram is
+silently truncated.
+
+When using BIO_s_datagram(), it is important to note that:
+
+=over 4
+
+=item
+
+This BIO can be used with either a connected or unconnected network socket. A
+connected socket is a network socket which has had L<BIO_connect(3)> or a
+similar OS-specific function called on it. Such a socket can only receive
+datagrams from the specified peer. Any other socket is an unconnected socket and
+can receive datagrams from any host.
+
+=item
+
+Despite their naming,
+neither BIO_ctrl_dgram_connect() nor BIO_ctrl_set_connected() cause a socket
+to become connected. These controls are provided to indicate to the BIO how
+the underlying socket is configured and how it is to be used; see below.
+
+=item
+
+Use of BIO_s_datagram() with an unconnected network socket is hazardous hecause
+any successful call to BIO_read() results in the peer address used for any
+subsequent call to BIO_write() being set to the source address of the datagram
+received by that call to BIO_read(). Thus, unless the caller calls
+BIO_dgram_set_peer() immediately prior to every call to BIO_write(), or never
+calls BIO_read(), any host on the network may cause future datagrams written to
+be redirected to that host. Therefore, it is recommended that users use
+BIO_s_dgram() only with a connected socket. An exception is where
+L<DTLSv1_listen(3)> must be used; see L<DTLSv1_listen(3)> for further
+discussion.
+
+=back
+
+Various controls are available for configuring the BIO_s_datagram() using
+L<BIO_ctrl(3)>:
+
+=over 4
+
+=item BIO_ctrl_dgram_connect (BIO_CTRL_DGRAM_CONNECT)
+
+This is equivalent to calling L<BIO_dgram_set_peer(3)>.
+
+Despite its name, this function does not cause the underlying socket to become
+connected.
+
+=item BIO_ctrl_set_connected (BIO_CTRL_SET_CONNECTED)
+
+This informs the BIO_s_datagram() whether the underlying socket has been
+connected, and therefore how the BIO_s_datagram() should attempt to use the
+socket.
+
+If the I<peer> argument is non-NULL, BIO_s_datagram() assumes that the
+underlying socket has been connected and will attempt to use the socket using OS
+APIs which do not specify peer addresses (for example, send(3) and recv(3) or
+similar). The I<peer> argument should specify the peer address to which the socket
+is connected.
+
+If the I<peer> argument is NULL, BIO_s_datagram() assumes that the underlying
+socket is not connected and will attempt to use the socket using an OS APIs
+which specify peer addresses (for example, sendto(3) and recvfrom(3)).
+
+=item BIO_dgram_get_peer (BIO_CTRL_DGRAM_GET_PEER)
+
+This outputs a B<BIO_ADDR> which specifies one of the following values,
+whichever happened most recently:
+
+=over 4
+
+=item
+
+The peer address last passed to BIO_dgram_set_peer(), BIO_ctrl_dgram_connect()
+or BIO_ctrl_set_connected().
+
+=item
+
+The peer address of the datagram last received by a call to BIO_read().
+
+=back
+
+=item BIO_dgram_set_peer (BIO_CTRL_DGRAM_SET_PEER)
+
+Sets the peer address to be used for subsequent writes to this BIO.
+
+Warning: When used with an unconnected network socket, the value set may be
+modified by future calls to L<BIO_read(3)>, making use of BIO_s_datagram()
+hazardous when used with unconnected network sockets; see above.
+
+=item BIO_dgram_recv_timeout (BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP)
+
+Returns 1 if the last I/O operation performed on the BIO (for example, via a
+call to L<BIO_read(3)>) may have been caused by a receive timeout.
+
+=item BIO_dgram_send_timedout (BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP)
+
+Returns 1 if the last I/O operation performed on the BIO (for example, via a
+call to L<BIO_write(3)>) may have been caused by a send timeout.
+
+=item BIO_dgram_get_mtu_overhead (BIO_CTRL_DGRAM_GET_MTU_OVERHEAD)
+
+Returns a quantity in bytes which is a rough estimate of the number of bytes of
+overhead which should typically be added to a datagram payload size in order to
+estimate the final size of the Layer 3 (e.g. IP) packet which will contain the
+datagram. In most cases, the maximum datagram payload size which can be
+transmitted can be determined by determining the link MTU in bytes and
+subtracting the value returned by this call.
+
+The value returned by this call depends on the network layer protocol being
+used.
+
+The value returned is not fully reliable because datagram overheads can be
+higher in atypical network configurations, for example where IPv6 extension
+headers or IPv4 options are used.
+
+=item BIO_CTRL_DGRAM_SET_DONT_FRAG
+
+If I<num> is nonzero, configures the underlying network socket to enable Don't
+Fragment mode, in which datagrams will be set with the IP Don't Fragment (DF)
+bit set. If I<num> is zero, Don't Fragment mode is disabled.
+
+=item BIO_CTRL_DGRAM_QUERY_MTU
+
+Queries the OS for its assessment of the Path MTU for the destination to which
+the underlying network socket, and returns that Path MTU in bytes. This control
+can only be used with a connected socket.
+
+This is not supported on all platforms and depends on OS support being
+available. Returns 0 on failure.
+
+=item BIO_CTRL_DGRAM_MTU_DISCOVER
+
+This control requests that Path MTU discovery be enabled on the underlying
+network socket.
+
+=item BIO_CTRL_DGRAM_GET_FALLBACK_MTU
+
+Returns the estimated minimum size of datagram payload which should always be
+supported on the BIO. This size is determined by the minimum MTU required to be
+supported by the applicable underlying network layer. Use of datagrams of this
+size may lead to suboptimal performance, but should be routable in all
+circumstances. The value returned is the datagram payload size in bytes and does
+not include the size of layer 3 or layer 4 protocol headers.
+
+=item BIO_CTRL_DGRAM_MTU_EXCEEDED
+
+Returns 1 if the last attempted write to the BIO failed due to the size of the
+attempted write exceeding the applicable MTU.
+
+=item BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT
+
+Accepts a pointer to a B<struct timeval>. If the time specified is zero,
+disables receive timeouts. Otherwise, configures the specified time interval as
+the receive timeout for the socket for the purposes of future L<BIO_read(3)>
+calls.
+
+=item BIO_CTRL_DGRAM_SET_PEEK_MODE
+
+If B<num> is nonzero, enables peek mode; otherwise, disables peek mode. Where
+peek mode is enabled, calls to L<BIO_read(3)> read datagrams from the underlying
+network socket in peek mode, meaning that a future call to L<BIO_read(3)> will
+yield the same datagram until peek mode is disabled.
+
+=back
+
+BIO_new_dgram() is a helper function which instantiates a BIO_s_datagram() and
+sets the BIO to use the socket given in I<fd> by calling BIO_set_fd().
+
+=head1 RETURN VALUES
+
+BIO_s_datagram() returns a BIO method.
+
+BIO_new_dgram() returns a BIO on success and NULL on failure.
+
+BIO_ctrl_dgram_connect(), BIO_ctrl_set_connected(),
+BIO_dgram_get_peer(), BIO_dgram_set_peer() return 1 on success and 0 on failure.
+
+BIO_dgram_recv_timedout() and BIO_dgram_send_timedout() return 0 or 1 depending
+on the circumstance; see discussion above.
+
+BIO_dgram_get_mtu_overhead() returns a value in bytes.
+
+=head1 SEE ALSO
+
+L<DTLSv1_listen(3)>, L<bio(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/BIO_s_fd.pod b/doc/man3/BIO_s_fd.pod
index 6291373cf34d..10aea50d4640 100644
--- a/doc/man3/BIO_s_fd.pod
+++ b/doc/man3/BIO_s_fd.pod
@@ -38,8 +38,8 @@ B<lseek(fd, 0, 1)>.
BIO_set_fd() sets the file descriptor of BIO B<b> to B<fd> and the close
flag to B<c>.
-BIO_get_fd() places the file descriptor in B<c> if it is not NULL, it also
-returns the file descriptor.
+BIO_get_fd() places the file descriptor of BIO B<b> in B<c> if it is not NULL.
+It also returns the file descriptor.
BIO_new_fd() returns a file descriptor BIO using B<fd> and B<close_flag>.
@@ -60,10 +60,10 @@ BIO_set_fd() and BIO_get_fd() are implemented as macros.
BIO_s_fd() returns the file descriptor BIO method.
-BIO_set_fd() always returns 1.
+BIO_set_fd() returns 1 on success or <=0 for failure.
BIO_get_fd() returns the file descriptor or -1 if the BIO has not
-been initialized.
+been initialized. It also returns zero and negative values if other error occurs.
BIO_new_fd() returns the newly allocated BIO or NULL is an error
occurred.
@@ -88,9 +88,9 @@ L<BIO_set_close(3)>, L<BIO_get_close(3)>
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_s_file.pod b/doc/man3/BIO_s_file.pod
index f1a75f7c627a..60e68dba1c3d 100644
--- a/doc/man3/BIO_s_file.pod
+++ b/doc/man3/BIO_s_file.pod
@@ -17,10 +17,10 @@ BIO_rw_filename - FILE bio
BIO_set_fp(BIO *b, FILE *fp, int flags);
BIO_get_fp(BIO *b, FILE **fpp);
- int BIO_read_filename(BIO *b, char *name)
- int BIO_write_filename(BIO *b, char *name)
- int BIO_append_filename(BIO *b, char *name)
- int BIO_rw_filename(BIO *b, char *name)
+ int BIO_read_filename(BIO *b, char *name);
+ int BIO_write_filename(BIO *b, char *name);
+ int BIO_append_filename(BIO *b, char *name);
+ int BIO_rw_filename(BIO *b, char *name);
=head1 DESCRIPTION
@@ -87,16 +87,15 @@ BIO_s_file() returns the file BIO method.
BIO_new_file() and BIO_new_fp() return a file BIO or NULL if an error
occurred.
-BIO_set_fp() and BIO_get_fp() return 1 for success or 0 for failure
+BIO_set_fp() and BIO_get_fp() return 1 for success or <=0 for failure
(although the current implementation never return 0).
-BIO_seek() returns the same value as the underlying fseek() function:
-0 for success or -1 for failure.
+BIO_seek() returns 0 for success or negative values for failure.
-BIO_tell() returns the current file position.
+BIO_tell() returns the current file position or negative values for failure.
BIO_read_filename(), BIO_write_filename(), BIO_append_filename() and
-BIO_rw_filename() return 1 for success or 0 for failure.
+BIO_rw_filename() return 1 for success or <=0 for failure.
=head1 EXAMPLES
@@ -114,7 +113,7 @@ Alternative technique:
bio_out = BIO_new(BIO_s_file());
if (bio_out == NULL)
/* Error */
- if (!BIO_set_fp(bio_out, stdout, BIO_NOCLOSE))
+ if (BIO_set_fp(bio_out, stdout, BIO_NOCLOSE) <= 0)
/* Error */
BIO_printf(bio_out, "Hello World\n");
@@ -135,7 +134,7 @@ Alternative technique:
out = BIO_new(BIO_s_file());
if (out == NULL)
/* Error */
- if (!BIO_write_filename(out, "filename.txt"))
+ if (BIO_write_filename(out, "filename.txt") <= 0)
/* Error */
BIO_printf(out, "Hello World\n");
BIO_free(out);
@@ -158,9 +157,9 @@ L<BIO_set_close(3)>, L<BIO_get_close(3)>
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_s_mem.pod b/doc/man3/BIO_s_mem.pod
index 9d3ae216158a..6b3cc6a2dae9 100644
--- a/doc/man3/BIO_s_mem.pod
+++ b/doc/man3/BIO_s_mem.pod
@@ -13,10 +13,10 @@ BIO_get_mem_ptr, BIO_new_mem_buf - memory BIO
const BIO_METHOD *BIO_s_mem(void);
const BIO_METHOD *BIO_s_secmem(void);
- BIO_set_mem_eof_return(BIO *b, int v)
- long BIO_get_mem_data(BIO *b, char **pp)
- BIO_set_mem_buf(BIO *b, BUF_MEM *bm, int c)
- BIO_get_mem_ptr(BIO *b, BUF_MEM **pp)
+ BIO_set_mem_eof_return(BIO *b, int v);
+ long BIO_get_mem_data(BIO *b, char **pp);
+ BIO_set_mem_buf(BIO *b, BUF_MEM *bm, int c);
+ BIO_get_mem_ptr(BIO *b, BUF_MEM **pp);
BIO *BIO_new_mem_buf(const void *buf, int len);
@@ -154,9 +154,9 @@ Extract the BUF_MEM structure from a memory BIO and then free up the BIO:
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_s_null.pod b/doc/man3/BIO_s_null.pod
index dd39423db1d7..c8951c0a80b9 100644
--- a/doc/man3/BIO_s_null.pod
+++ b/doc/man3/BIO_s_null.pod
@@ -36,7 +36,7 @@ BIO_s_null() returns the null sink BIO method.
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_s_socket.pod b/doc/man3/BIO_s_socket.pod
index 781ff247b25d..d8b1647fbe32 100644
--- a/doc/man3/BIO_s_socket.pod
+++ b/doc/man3/BIO_s_socket.pod
@@ -46,7 +46,7 @@ occurred.
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_set_callback.pod b/doc/man3/BIO_set_callback.pod
index f7ee104c2855..b98c0929cb16 100644
--- a/doc/man3/BIO_set_callback.pod
+++ b/doc/man3/BIO_set_callback.pod
@@ -4,7 +4,7 @@
BIO_set_callback_ex, BIO_get_callback_ex, BIO_set_callback, BIO_get_callback,
BIO_set_callback_arg, BIO_get_callback_arg, BIO_debug_callback,
-BIO_callback_fn_ex, BIO_callback_fn
+BIO_debug_callback_ex, BIO_callback_fn_ex, BIO_callback_fn
- BIO callback functions
=head1 SYNOPSIS
@@ -14,17 +14,24 @@ BIO_callback_fn_ex, BIO_callback_fn
typedef long (*BIO_callback_fn_ex)(BIO *b, int oper, const char *argp,
size_t len, int argi,
long argl, int ret, size_t *processed);
- typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi,
- long argl, long ret);
void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex callback);
BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b);
- void BIO_set_callback(BIO *b, BIO_callback_fn cb);
- BIO_callback_fn BIO_get_callback(BIO *b);
void BIO_set_callback_arg(BIO *b, char *arg);
char *BIO_get_callback_arg(const BIO *b);
+ long BIO_debug_callback_ex(BIO *bio, int oper, const char *argp, size_t len,
+ int argi, long argl, int ret, size_t *processed);
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi,
+ long argl, long ret);
+ void BIO_set_callback(BIO *b, BIO_callback_fn cb);
+ BIO_callback_fn BIO_get_callback(const BIO *b);
long BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi,
long argl, long ret);
@@ -43,12 +50,14 @@ called in preference to any set by BIO_set_callback().
BIO_set_callback_arg() and BIO_get_callback_arg() are macros which can be
used to set and retrieve an argument for use in the callback.
-BIO_debug_callback() is a standard debugging callback which prints
+BIO_debug_callback_ex() is a standard debugging callback which prints
out information relating to each BIO operation. If the callback
argument is set it is interpreted as a BIO to send the information
-to, otherwise stderr is used.
+to, otherwise stderr is used. The BIO_debug_callback() function is the
+deprecated version of the same callback for use with the old callback
+format BIO_set_callback() function.
-BIO_callback_fn_ex() is the type of the callback function and BIO_callback_fn()
+BIO_callback_fn_ex is the type of the callback function and BIO_callback_fn
is the type of the old format callback function. The meaning of each argument
is described below:
@@ -225,14 +234,21 @@ operations.
=head1 EXAMPLES
-The BIO_debug_callback() function is a good example, its source is
+The BIO_debug_callback_ex() function is an example, its source is
in crypto/bio/bio_cb.c
+=head1 HISTORY
+
+The BIO_debug_callback_ex() function was added in OpenSSL 3.0.
+
+BIO_set_callback(), BIO_get_callback(), and BIO_debug_callback() were
+deprecated in OpenSSL 3.0. Use the non-deprecated _ex functions instead.
+
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_should_retry.pod b/doc/man3/BIO_should_retry.pod
index 7a9ce8ccbbe0..25d3f2e23072 100644
--- a/doc/man3/BIO_should_retry.pod
+++ b/doc/man3/BIO_should_retry.pod
@@ -128,7 +128,7 @@ BIO_get_retry_reason() returns the reason for a special condition.
=head1 SEE ALSO
-L<bio>
+L<bio(7)>
=head1 HISTORY
@@ -139,7 +139,7 @@ OpenSSL 1.1.0.
Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BIO_socket_wait.pod b/doc/man3/BIO_socket_wait.pod
new file mode 100644
index 000000000000..f1050f80fb7e
--- /dev/null
+++ b/doc/man3/BIO_socket_wait.pod
@@ -0,0 +1,69 @@
+=pod
+
+=head1 NAME
+
+BIO_socket_wait,
+BIO_wait,
+BIO_do_connect_retry
+- BIO connection utility functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/bio.h>
+
+ #ifndef OPENSSL_NO_SOCK
+ int BIO_socket_wait(int fd, int for_read, time_t max_time);
+ #endif
+ int BIO_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds);
+ int BIO_do_connect_retry(BIO *bio, int timeout, int nap_milliseconds);
+
+=head1 DESCRIPTION
+
+BIO_socket_wait() waits on the socket B<fd> for reading if B<for_read> is not 0,
+else for writing, at most until B<max_time>.
+It succeeds immediately if B<max_time> == 0 (which means no timeout given).
+
+BIO_wait() waits at most until B<max_time> on the given (typically socket-based)
+B<bio>, for reading if B<bio> is supposed to read, else for writing.
+It is used by BIO_do_connect_retry() and can be used together L<BIO_read(3)>.
+It succeeds immediately if B<max_time> == 0 (which means no timeout given).
+If sockets are not available it supports polling by succeeding after sleeping
+at most the given B<nap_milliseconds> in order to avoid a tight busy loop.
+Via B<nap_milliseconds> the caller determines the polling granularity.
+
+BIO_do_connect_retry() connects via the given B<bio>.
+It retries BIO_do_connect() as far as needed to reach a definite outcome,
+i.e., connection succeeded, timeout has been reached, or an error occurred.
+For nonblocking and potentially even non-socket BIOs it polls
+every B<nap_milliseconds> and sleeps in between using BIO_wait().
+If B<nap_milliseconds> is < 0 then a default value of 100 ms is used.
+If the B<timeout> parameter is > 0 this indicates the maximum number of seconds
+to wait until the connection is established or a definite error occurred.
+A value of 0 enables waiting indefinitely (i.e, no timeout),
+while a value < 0 means that BIO_do_connect() is tried only once.
+The function may, directly or indirectly, invoke ERR_clear_error().
+
+=head1 RETURN VALUES
+
+BIO_socket_wait(), BIO_wait(), and BIO_do_connect_retry()
+return -1 on error, 0 on timeout, and 1 on success.
+
+=head1 SEE ALSO
+
+L<BIO_do_connect(3)>, L<BIO_read(3)>
+
+=head1 HISTORY
+
+BIO_socket_wait(), BIO_wait(), and BIO_do_connect_retry()
+were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/BN_BLINDING_new.pod b/doc/man3/BN_BLINDING_new.pod
index 68b3cbaf815c..210fad709c0b 100644
--- a/doc/man3/BN_BLINDING_new.pod
+++ b/doc/man3/BN_BLINDING_new.pod
@@ -26,8 +26,8 @@ BN_BLINDING_set_flags, BN_BLINDING_create_param - blinding related BIGNUM functi
void BN_BLINDING_set_current_thread(BN_BLINDING *b);
int BN_BLINDING_lock(BN_BLINDING *b);
int BN_BLINDING_unlock(BN_BLINDING *b);
- unsigned long BN_BLINDING_get_flags(const BN_BLINDING *);
- void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long);
+ unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b);
+ void BN_BLINDING_set_flags(BN_BLINDING *b, unsigned long flags);
BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
int (*bn_mod_exp)(BIGNUM *r,
@@ -116,9 +116,9 @@ deprecates BN_BLINDING_set_thread_id() and BN_BLINDING_get_thread_id().
=head1 COPYRIGHT
-Copyright 2005-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_CTX_new.pod b/doc/man3/BN_CTX_new.pod
index 7fba72e1082a..1d93c8b55e87 100644
--- a/doc/man3/BN_CTX_new.pod
+++ b/doc/man3/BN_CTX_new.pod
@@ -2,14 +2,17 @@
=head1 NAME
-BN_CTX_new, BN_CTX_secure_new, BN_CTX_free - allocate and free BN_CTX structures
+BN_CTX_new_ex, BN_CTX_new, BN_CTX_secure_new_ex, BN_CTX_secure_new, BN_CTX_free
+- allocate and free BN_CTX structures
=head1 SYNOPSIS
#include <openssl/bn.h>
+ BN_CTX *BN_CTX_new_ex(OSSL_LIB_CTX *ctx);
BN_CTX *BN_CTX_new(void);
+ BN_CTX *BN_CTX_secure_new_ex(OSSL_LIB_CTX *ctx);
BN_CTX *BN_CTX_secure_new(void);
void BN_CTX_free(BN_CTX *c);
@@ -21,10 +24,17 @@ library functions. Since dynamic memory allocation to create B<BIGNUM>s
is rather expensive when used in conjunction with repeated subroutine
calls, the B<BN_CTX> structure is used.
-BN_CTX_new() allocates and initializes a B<BN_CTX> structure.
-BN_CTX_secure_new() allocates and initializes a B<BN_CTX> structure
+BN_CTX_new_ex() allocates and initializes a B<BN_CTX> structure for the given
+library context B<ctx>. The <ctx> value may be NULL in which case the default
+library context will be used. BN_CTX_new() is the same as BN_CTX_new_ex() except
+that the default library context is always used.
+
+BN_CTX_secure_new_ex() allocates and initializes a B<BN_CTX> structure
but uses the secure heap (see L<CRYPTO_secure_malloc(3)>) to hold the
-B<BIGNUM>s.
+B<BIGNUM>s for the given library context B<ctx>. The <ctx> value may be NULL in
+which case the default library context will be used. BN_CTX_secure_new() is the
+same as BN_CTX_secure_new_ex() except that the default library context is always
+used.
BN_CTX_free() frees the components of the B<BN_CTX> and the structure itself.
Since BN_CTX_start() is required in order to obtain B<BIGNUM>s from the
@@ -69,9 +79,9 @@ BN_CTX_init() was removed in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_CTX_start.pod b/doc/man3/BN_CTX_start.pod
index bb039e5539cd..d4780fe9cdc1 100644
--- a/doc/man3/BN_CTX_start.pod
+++ b/doc/man3/BN_CTX_start.pod
@@ -48,9 +48,9 @@ L<BN_CTX_new(3)>
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_add.pod b/doc/man3/BN_add.pod
index a4912fbab1d5..9561d554318f 100644
--- a/doc/man3/BN_add.pod
+++ b/doc/man3/BN_add.pod
@@ -132,7 +132,7 @@ L<BN_add_word(3)>, L<BN_set_bit(3)>
Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_add_word.pod b/doc/man3/BN_add_word.pod
index 6c69bc485f2e..266a17471a10 100644
--- a/doc/man3/BN_add_word.pod
+++ b/doc/man3/BN_add_word.pod
@@ -53,7 +53,7 @@ L<ERR_get_error(3)>, L<BN_add(3)>
Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_bn2bin.pod b/doc/man3/BN_bn2bin.pod
index 67595e05b85a..92cb7d74f101 100644
--- a/doc/man3/BN_bn2bin.pod
+++ b/doc/man3/BN_bn2bin.pod
@@ -3,9 +3,9 @@
=head1 NAME
BN_bn2binpad,
-BN_bn2bin, BN_bin2bn, BN_bn2lebinpad, BN_lebin2bn, BN_bn2hex, BN_bn2dec,
-BN_hex2bn, BN_dec2bn, BN_print, BN_print_fp, BN_bn2mpi,
-BN_mpi2bn - format conversions
+BN_bn2bin, BN_bin2bn, BN_bn2lebinpad, BN_lebin2bn,
+BN_bn2nativepad, BN_native2bn, BN_bn2hex, BN_bn2dec, BN_hex2bn, BN_dec2bn,
+BN_print, BN_print_fp, BN_bn2mpi, BN_mpi2bn - format conversions
=head1 SYNOPSIS
@@ -18,6 +18,9 @@ BN_mpi2bn - format conversions
int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen);
BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret);
+ int BN_bn2nativepad(const BIGNUM *a, unsigned char *to, int tolen);
+ BIGNUM *BN_native2bn(const unsigned char *s, int len, BIGNUM *ret);
+
char *BN_bn2hex(const BIGNUM *a);
char *BN_bn2dec(const BIGNUM *a);
int BN_hex2bn(BIGNUM **a, const char *str);
@@ -47,6 +50,11 @@ NULL, a new B<BIGNUM> is created.
BN_bn2lebinpad() and BN_lebin2bn() are identical to BN_bn2binpad() and
BN_bin2bn() except the buffer is in little-endian format.
+BN_bn2nativepad() and BN_native2bn() are identical to BN_bn2binpad() and
+BN_bin2bn() except the buffer is in native format, i.e. most significant
+byte first on big-endian platforms, and least significant byte first on
+little-endian platforms.
+
BN_bn2hex() and BN_bn2dec() return printable strings containing the
hexadecimal and decimal encoding of B<a> respectively. For negative
numbers, the string is prefaced with a leading '-'. The string must be
@@ -83,10 +91,10 @@ if B<ret> is NULL.
BN_bn2bin() returns the length of the big-endian number placed at B<to>.
BN_bin2bn() returns the B<BIGNUM>, NULL on error.
-BN_bn2binpad() returns the number of bytes written or -1 if the supplied
+BN_bn2binpad(), BN_bn2lebinpad(), and BN_bn2nativepad() return the number of bytes written or -1 if the supplied
buffer is too small.
-BN_bn2hex() and BN_bn2dec() return a null-terminated string, or NULL
+BN_bn2hex() and BN_bn2dec() return a NUL-terminated string, or NULL
on error. BN_hex2bn() and BN_dec2bn() return the number of characters
used in parsing, or 0 on error, in which
case no new B<BIGNUM> will be created.
@@ -106,9 +114,9 @@ L<BN_num_bytes(3)>
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_cmp.pod b/doc/man3/BN_cmp.pod
index 261619c512ab..f302818f215e 100644
--- a/doc/man3/BN_cmp.pod
+++ b/doc/man3/BN_cmp.pod
@@ -44,7 +44,7 @@ BN_abs_is_word() and BN_is_odd() were macros.
Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_copy.pod b/doc/man3/BN_copy.pod
index 46de54428663..9bdec64b8c33 100644
--- a/doc/man3/BN_copy.pod
+++ b/doc/man3/BN_copy.pod
@@ -61,7 +61,7 @@ L<ERR_get_error(3)>
Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_generate_prime.pod b/doc/man3/BN_generate_prime.pod
index 25674d0348f7..b536bcb3b781 100644
--- a/doc/man3/BN_generate_prime.pod
+++ b/doc/man3/BN_generate_prime.pod
@@ -2,22 +2,23 @@
=head1 NAME
-BN_generate_prime_ex, BN_is_prime_ex, BN_is_prime_fasttest_ex, BN_GENCB_call,
-BN_GENCB_new, BN_GENCB_free, BN_GENCB_set_old, BN_GENCB_set, BN_GENCB_get_arg,
-BN_generate_prime, BN_is_prime, BN_is_prime_fasttest - generate primes and test
-for primality
+BN_generate_prime_ex2, BN_generate_prime_ex, BN_is_prime_ex, BN_check_prime,
+BN_is_prime_fasttest_ex, BN_GENCB_call, BN_GENCB_new, BN_GENCB_free,
+BN_GENCB_set_old, BN_GENCB_set, BN_GENCB_get_arg, BN_generate_prime,
+BN_is_prime, BN_is_prime_fasttest - generate primes and test for primality
=head1 SYNOPSIS
#include <openssl/bn.h>
+ int BN_generate_prime_ex2(BIGNUM *ret, int bits, int safe,
+ const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb,
+ BN_CTX *ctx);
+
int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add,
const BIGNUM *rem, BN_GENCB *cb);
- int BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, BN_GENCB *cb);
-
- int BN_is_prime_fasttest_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx,
- int do_trial_division, BN_GENCB *cb);
+ int BN_check_prime(const BIGNUM *p, BN_CTX *ctx, BN_GENCB *cb);
int BN_GENCB_call(BN_GENCB *cb, int a, int b);
@@ -33,28 +34,44 @@ for primality
void *BN_GENCB_get_arg(BN_GENCB *cb);
-Deprecated:
+The following functions have been deprecated since OpenSSL 0.9.8, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
- #if OPENSSL_API_COMPAT < 0x00908000L
BIGNUM *BN_generate_prime(BIGNUM *ret, int num, int safe, BIGNUM *add,
BIGNUM *rem, void (*callback)(int, int, void *),
void *cb_arg);
- int BN_is_prime(const BIGNUM *a, int checks,
+ int BN_is_prime(const BIGNUM *p, int nchecks,
void (*callback)(int, int, void *), BN_CTX *ctx, void *cb_arg);
- int BN_is_prime_fasttest(const BIGNUM *a, int checks,
+ int BN_is_prime_fasttest(const BIGNUM *p, int nchecks,
void (*callback)(int, int, void *), BN_CTX *ctx,
void *cb_arg, int do_trial_division);
- #endif
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ int BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, BN_GENCB *cb);
+
+ int BN_is_prime_fasttest_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx,
+ int do_trial_division, BN_GENCB *cb);
=head1 DESCRIPTION
-BN_generate_prime_ex() generates a pseudo-random prime number of
-at least bit length B<bits>. The returned number is probably prime
-with a negligible error. If B<add> is B<NULL> the returned prime
-number will have exact bit length B<bits> with the top most two
-bits set.
+BN_generate_prime_ex2() generates a pseudo-random prime number of
+at least bit length B<bits> using the BN_CTX provided in B<ctx>. The value of
+B<ctx> must not be NULL.
+
+The returned number is probably prime with a negligible error.
+The maximum error rate is 2^-128.
+It's 2^-287 for a 512 bit prime, 2^-435 for a 1024 bit prime,
+2^-648 for a 2048 bit prime, and lower than 2^-882 for primes larger
+than 2048 bit.
+
+If B<add> is B<NULL> the returned prime number will have exact bit
+length B<bits> with the top most two bits set.
If B<ret> is not B<NULL>, it will be used to store the number.
@@ -98,38 +115,51 @@ It is recommended that B<add> is a multiple of 4.
The random generator must be seeded prior to calling BN_generate_prime_ex().
If the automatic seeding or reseeding of the OpenSSL CSPRNG fails due to
external circumstances (see L<RAND(7)>), the operation will fail.
+The random number generator configured for the OSSL_LIB_CTX associated with
+B<ctx> will be used.
-BN_is_prime_ex() and BN_is_prime_fasttest_ex() test if the number B<p> is
-prime. The following tests are performed until one of them shows that
-B<p> is composite; if B<p> passes all these tests, it is considered
-prime.
-
-BN_is_prime_fasttest_ex(), when called with B<do_trial_division == 1>,
-first attempts trial division by a number of small primes;
-if no divisors are found by this test and B<cb> is not B<NULL>,
-B<BN_GENCB_call(cb, 1, -1)> is called.
-If B<do_trial_division == 0>, this test is skipped.
-
-Both BN_is_prime_ex() and BN_is_prime_fasttest_ex() perform a Miller-Rabin
-probabilistic primality test with B<nchecks> iterations. If
-B<nchecks == BN_prime_checks>, a number of iterations is used that
-yields a false positive rate of at most 2^-64 for random input.
-The error rate depends on the size of the prime and goes down for bigger primes.
-The rate is 2^-80 starting at 308 bits, 2^-112 at 852 bits, 2^-128 at 1080 bits,
-2^-192 at 3747 bits and 2^-256 at 6394 bits.
-
-When the source of the prime is not random or not trusted, the number
-of checks needs to be much higher to reach the same level of assurance:
-It should equal half of the targeted security level in bits (rounded up to the
-next integer if necessary).
-For instance, to reach the 128 bit security level, B<nchecks> should be set to
-64.
-
-If B<cb> is not B<NULL>, B<BN_GENCB_call(cb, 1, j)> is called
-after the j-th iteration (j = 0, 1, ...). B<ctx> is a
-preallocated B<BN_CTX> (to save the overhead of allocating and
+BN_generate_prime_ex() is the same as BN_generate_prime_ex2() except that no
+B<ctx> parameter is passed.
+In this case the random number generator associated with the default OSSL_LIB_CTX
+will be used.
+
+BN_check_prime(), BN_is_prime_ex(), BN_is_prime_fasttest_ex(), BN_is_prime()
+and BN_is_prime_fasttest() test if the number B<p> is prime.
+The functions tests until one of the tests shows that B<p> is composite,
+or all the tests passed.
+If B<p> passes all these tests, it is considered a probable prime.
+
+The test performed on B<p> are trial division by a number of small primes
+and rounds of the of the Miller-Rabin probabilistic primality test.
+
+The functions do at least 64 rounds of the Miller-Rabin test giving a maximum
+false positive rate of 2^-128.
+If the size of B<p> is more than 2048 bits, they do at least 128 rounds
+giving a maximum false positive rate of 2^-256.
+
+If B<nchecks> is larger than the minimum above (64 or 128), B<nchecks>
+rounds of the Miller-Rabin test will be done.
+
+If B<do_trial_division> set to B<0>, the trial division will be skipped.
+BN_is_prime_ex() and BN_is_prime() always skip the trial division.
+
+BN_is_prime_ex(), BN_is_prime_fasttest_ex(), BN_is_prime()
+and BN_is_prime_fasttest() are deprecated.
+
+BN_is_prime_fasttest() and BN_is_prime() behave just like
+BN_is_prime_fasttest_ex() and BN_is_prime_ex() respectively, but with the old
+style call back.
+
+B<ctx> is a preallocated B<BN_CTX> (to save the overhead of allocating and
freeing the structure in a loop), or B<NULL>.
+If the trial division is done, and no divisors are found and B<cb>
+is not B<NULL>, B<BN_GENCB_call(cb, 1, -1)> is called.
+
+After each round of the Miller-Rabin probabilistic primality test,
+if B<cb> is not B<NULL>, B<BN_GENCB_call(cb, 1, j)> is called
+with B<j> the iteration (j = 0, 1, ...).
+
BN_GENCB_call() calls the callback function held in the B<BN_GENCB> structure
and passes the ints B<a> and B<b> as arguments. There are two types of
B<BN_GENCB> structure that are supported: "new" style and "old" style. New
@@ -164,9 +194,9 @@ BN_is_prime_fasttest_ex(), respectively.
BN_generate_prime_ex() return 1 on success or 0 on error.
-BN_is_prime_ex(), BN_is_prime_fasttest_ex(), BN_is_prime() and
-BN_is_prime_fasttest() return 0 if the number is composite, 1 if it is
-prime with an error probability of less than 0.25^B<nchecks>, and
+BN_is_prime_ex(), BN_is_prime_fasttest_ex(), BN_is_prime(),
+BN_is_prime_fasttest() and BN_check_prime return 0 if the number is composite,
+1 if it is prime with an error probability of less than 0.25^B<nchecks>, and
-1 on error.
BN_generate_prime() returns the prime number on success, B<NULL> otherwise.
@@ -205,14 +235,19 @@ L<RAND(7)>
=head1 HISTORY
+The BN_is_prime_ex() and BN_is_prime_fasttest_ex() functions were
+deprecated in OpenSSL 3.0.
+
The BN_GENCB_new(), BN_GENCB_free(),
and BN_GENCB_get_arg() functions were added in OpenSSL 1.1.0.
+BN_check_prime() was added in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_mod_exp_mont.pod b/doc/man3/BN_mod_exp_mont.pod
new file mode 100644
index 000000000000..686c0b9e62ee
--- /dev/null
+++ b/doc/man3/BN_mod_exp_mont.pod
@@ -0,0 +1,65 @@
+=pod
+
+=head1 NAME
+
+BN_mod_exp_mont, BN_mod_exp_mont_consttime, BN_mod_exp_mont_consttime_x2 -
+Montgomery exponentiation
+
+=head1 SYNOPSIS
+
+ #include <openssl/bn.h>
+
+ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont);
+
+ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *in_mont);
+
+ int BN_mod_exp_mont_consttime_x2(BIGNUM *rr1, const BIGNUM *a1,
+ const BIGNUM *p1, const BIGNUM *m1,
+ BN_MONT_CTX *in_mont1, BIGNUM *rr2,
+ const BIGNUM *a2, const BIGNUM *p2,
+ const BIGNUM *m2, BN_MONT_CTX *in_mont2,
+ BN_CTX *ctx);
+
+=head1 DESCRIPTION
+
+BN_mod_exp_mont() computes I<a> to the I<p>-th power modulo I<m> (C<rr=a^p % m>)
+using Montgomery multiplication. I<in_mont> is a Montgomery context and can be
+NULL. In the case I<in_mont> is NULL, it will be initialized within the
+function, so you can save time on initialization if you provide it in advance.
+
+BN_mod_exp_mont_consttime() computes I<a> to the I<p>-th power modulo I<m>
+(C<rr=a^p % m>) using Montgomery multiplication. It is a variant of
+L<BN_mod_exp_mont(3)> that uses fixed windows and the special precomputation
+memory layout to limit data-dependency to a minimum to protect secret exponents.
+It is called automatically when L<BN_mod_exp_mont(3)> is called with parameters
+I<a>, I<p>, I<m>, any of which have B<BN_FLG_CONSTTIME> flag.
+
+BN_mod_exp_mont_consttime_x2() computes two independent exponentiations I<a1> to
+the I<p1>-th power modulo I<m1> (C<rr1=a1^p1 % m1>) and I<a2> to the I<p2>-th
+power modulo I<m2> (C<rr2=a2^p2 % m2>) using Montgomery multiplication. For some
+fixed and equal modulus sizes I<m1> and I<m2> it uses optimizations that allow
+to speedup two exponentiations. In all other cases the function reduces to two
+calls of L<BN_mod_exp_mont_consttime(3)>.
+
+=head1 RETURN VALUES
+
+For all functions 1 is returned for success, 0 on error.
+The error codes can be obtained by L<ERR_get_error(3)>.
+
+=head1 SEE ALSO
+
+L<ERR_get_error(3)>, L<BN_mod_exp_mont(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/BN_mod_inverse.pod b/doc/man3/BN_mod_inverse.pod
index 5c09aacbe589..5dbb5c3cc2d6 100644
--- a/doc/man3/BN_mod_inverse.pod
+++ b/doc/man3/BN_mod_inverse.pod
@@ -33,7 +33,7 @@ L<ERR_get_error(3)>, L<BN_add(3)>
Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_mod_mul_montgomery.pod b/doc/man3/BN_mod_mul_montgomery.pod
index 911945fd9dba..82db19308ef8 100644
--- a/doc/man3/BN_mod_mul_montgomery.pod
+++ b/doc/man3/BN_mod_mul_montgomery.pod
@@ -82,7 +82,7 @@ BN_MONT_CTX_init() was removed in OpenSSL 1.1.0
Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_mod_mul_reciprocal.pod b/doc/man3/BN_mod_mul_reciprocal.pod
index 07f93baf60f8..28d5f1131d73 100644
--- a/doc/man3/BN_mod_mul_reciprocal.pod
+++ b/doc/man3/BN_mod_mul_reciprocal.pod
@@ -15,10 +15,10 @@ reciprocal
int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *m, BN_CTX *ctx);
- int BN_div_recp(BIGNUM *dv, BIGNUM *rem, BIGNUM *a, BN_RECP_CTX *recp,
+ int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *a, BN_RECP_CTX *recp,
BN_CTX *ctx);
- int BN_mod_mul_reciprocal(BIGNUM *r, BIGNUM *a, BIGNUM *b,
+ int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
BN_RECP_CTX *recp, BN_CTX *ctx);
=head1 DESCRIPTION
@@ -66,9 +66,9 @@ BN_RECP_CTX_init() was removed in OpenSSL 1.1.0
=head1 COPYRIGHT
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_new.pod b/doc/man3/BN_new.pod
index 7f0f6514bc4a..7e9da8fe87ee 100644
--- a/doc/man3/BN_new.pod
+++ b/doc/man3/BN_new.pod
@@ -54,9 +54,9 @@ BN_init() was removed in OpenSSL 1.1.0; use BN_new() instead.
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_num_bytes.pod b/doc/man3/BN_num_bytes.pod
index 9e0465de5473..eb9be4d15f0a 100644
--- a/doc/man3/BN_num_bytes.pod
+++ b/doc/man3/BN_num_bytes.pod
@@ -53,7 +53,7 @@ L<RSA_size(3)>
Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_rand.pod b/doc/man3/BN_rand.pod
index 5ed14a926fcc..aebad1e72eb2 100644
--- a/doc/man3/BN_rand.pod
+++ b/doc/man3/BN_rand.pod
@@ -2,49 +2,74 @@
=head1 NAME
-BN_rand, BN_priv_rand, BN_pseudo_rand,
-BN_rand_range, BN_priv_rand_range, BN_pseudo_rand_range
+BN_rand_ex, BN_rand, BN_priv_rand_ex, BN_priv_rand, BN_pseudo_rand,
+BN_rand_range_ex, BN_rand_range, BN_priv_rand_range_ex, BN_priv_rand_range,
+BN_pseudo_rand_range
- generate pseudo-random number
=head1 SYNOPSIS
#include <openssl/bn.h>
+ int BN_rand_ex(BIGNUM *rnd, int bits, int top, int bottom,
+ unsigned int strength, BN_CTX *ctx);
int BN_rand(BIGNUM *rnd, int bits, int top, int bottom);
+ int BN_priv_rand_ex(BIGNUM *rnd, int bits, int top, int bottom,
+ unsigned int strength, BN_CTX *ctx);
int BN_priv_rand(BIGNUM *rnd, int bits, int top, int bottom);
- int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom);
+ int BN_rand_range_ex(BIGNUM *rnd, const BIGNUM *range, unsigned int strength,
+ BN_CTX *ctx);
+ int BN_rand_range(BIGNUM *rnd, const BIGNUM *range);
- int BN_rand_range(BIGNUM *rnd, BIGNUM *range);
+ int BN_priv_rand_range_ex(BIGNUM *rnd, const BIGNUM *range, unsigned int strength,
+ BN_CTX *ctx);
+ int BN_priv_rand_range(BIGNUM *rnd, const BIGNUM *range);
- int BN_priv_rand_range(BIGNUM *rnd, BIGNUM *range);
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
- int BN_pseudo_rand_range(BIGNUM *rnd, BIGNUM *range);
+ int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom);
+ int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range);
=head1 DESCRIPTION
-BN_rand() generates a cryptographically strong pseudo-random number of
-B<bits> in length and stores it in B<rnd>.
-If B<bits> is less than zero, or too small to
-accommodate the requirements specified by the B<top> and B<bottom>
+BN_rand_ex() generates a cryptographically strong pseudo-random
+number of I<bits> in length and security strength at least I<strength> bits
+using the random number generator for the library context associated with
+I<ctx>. The function stores the generated data in I<rnd>. The parameter I<ctx>
+may be NULL in which case the default library context is used.
+If I<bits> is less than zero, or too small to
+accommodate the requirements specified by the I<top> and I<bottom>
parameters, an error is returned.
-The B<top> parameters specifies
+The I<top> parameters specifies
requirements on the most significant bit of the generated number.
If it is B<BN_RAND_TOP_ANY>, there is no constraint.
If it is B<BN_RAND_TOP_ONE>, the top bit must be one.
If it is B<BN_RAND_TOP_TWO>, the two most significant bits of
the number will be set to 1, so that the product of two such random
-numbers will always have 2*B<bits> length.
-If B<bottom> is B<BN_RAND_BOTTOM_ODD>, the number will be odd; if it
+numbers will always have 2*I<bits> length.
+If I<bottom> is B<BN_RAND_BOTTOM_ODD>, the number will be odd; if it
is B<BN_RAND_BOTTOM_ANY> it can be odd or even.
-If B<bits> is 1 then B<top> cannot also be B<BN_RAND_TOP_TWO>.
+If I<bits> is 1 then I<top> cannot also be B<BN_RAND_TOP_TWO>.
+
+BN_rand() is the same as BN_rand_ex() except that the default library context
+is always used.
+
+BN_rand_range_ex() generates a cryptographically strong pseudo-random
+number I<rnd>, of security stength at least I<strength> bits,
+in the range 0 E<lt>= I<rnd> E<lt> I<range> using the random number
+generator for the library context associated with I<ctx>. The parameter I<ctx>
+may be NULL in which case the default library context is used.
-BN_rand_range() generates a cryptographically strong pseudo-random
-number B<rnd> in the range 0 E<lt>= B<rnd> E<lt> B<range>.
+BN_rand_range() is the same as BN_rand_range_ex() except that the default
+library context is always used.
-BN_priv_rand() and BN_priv_rand_range() have the same semantics as
-BN_rand() and BN_rand_range() respectively. They are intended to be
+BN_priv_rand_ex(), BN_priv_rand(), BN_priv_rand_rand_ex() and
+BN_priv_rand_range() have the same semantics as BN_rand_ex(), BN_rand(),
+BN_rand_range_ex() and BN_rand_range() respectively. They are intended to be
used for generating values that should remain private, and mirror the
same difference between L<RAND_bytes(3)> and L<RAND_priv_bytes(3)>.
@@ -66,7 +91,7 @@ L<RAND_add(3)>,
L<RAND_bytes(3)>,
L<RAND_priv_bytes(3)>,
L<RAND(7)>,
-L<RAND_DRBG(7)>
+L<EVP_RAND(7)>
=head1 HISTORY
@@ -77,13 +102,18 @@ L<RAND_DRBG(7)>
Starting with OpenSSL release 1.1.0, BN_pseudo_rand() has been identical
to BN_rand() and BN_pseudo_rand_range() has been identical to
BN_rand_range().
-The "pseudo" functions should not be used and may be deprecated in
-a future release.
+The BN_pseudo_rand() and BN_pseudo_rand_range() functions were
+deprecated in OpenSSL 3.0.
+
+=item *
+
+The BN_priv_rand() and BN_priv_rand_range() functions were added in
+OpenSSL 1.1.1.
=item *
-The
-BN_priv_rand() and BN_priv_rand_range() functions were added in OpenSSL 1.1.1.
+The BN_rand_ex(), BN_priv_rand_ex(), BN_rand_range_ex() and
+BN_priv_rand_range_ex() functions were added in OpenSSL 3.0.
=back
@@ -91,7 +121,7 @@ BN_priv_rand() and BN_priv_rand_range() functions were added in OpenSSL 1.1.1.
Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_security_bits.pod b/doc/man3/BN_security_bits.pod
index acf59027ba24..f02bf2e0551d 100644
--- a/doc/man3/BN_security_bits.pod
+++ b/doc/man3/BN_security_bits.pod
@@ -43,7 +43,7 @@ The BN_security_bits() function was added in OpenSSL 1.1.0.
Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_set_bit.pod b/doc/man3/BN_set_bit.pod
index 6e0a11a24b89..349ef9e0562c 100644
--- a/doc/man3/BN_set_bit.pod
+++ b/doc/man3/BN_set_bit.pod
@@ -61,7 +61,7 @@ L<BN_num_bytes(3)>, L<BN_add(3)>
Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_swap.pod b/doc/man3/BN_swap.pod
index 7d097a3e1cc6..013b3884f95b 100644
--- a/doc/man3/BN_swap.pod
+++ b/doc/man3/BN_swap.pod
@@ -22,7 +22,7 @@ BN_swap() does not return a value.
Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BN_zero.pod b/doc/man3/BN_zero.pod
index 1d7744bf2ae6..ca8d7b5dc6ef 100644
--- a/doc/man3/BN_zero.pod
+++ b/doc/man3/BN_zero.pod
@@ -60,7 +60,7 @@ versions returned an int.
Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/BUF_MEM_new.pod b/doc/man3/BUF_MEM_new.pod
index 0c68f3776f7c..262e18f31bfe 100644
--- a/doc/man3/BUF_MEM_new.pod
+++ b/doc/man3/BUF_MEM_new.pod
@@ -67,7 +67,7 @@ The BUF_MEM_new_ex() function was added in OpenSSL 1.1.0.
Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CMS_EncryptedData_decrypt.pod b/doc/man3/CMS_EncryptedData_decrypt.pod
new file mode 100644
index 000000000000..17850a98af3f
--- /dev/null
+++ b/doc/man3/CMS_EncryptedData_decrypt.pod
@@ -0,0 +1,49 @@
+=pod
+
+=head1 NAME
+
+CMS_EncryptedData_decrypt
+- Decrypt CMS EncryptedData
+
+=head1 SYNOPSIS
+
+ #include <openssl/cms.h>
+
+ int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
+ const unsigned char *key, size_t keylen,
+ BIO *dcont, BIO *out, unsigned int flags);
+
+=head1 DESCRIPTION
+
+CMS_EncryptedData_decrypt() decrypts a I<cms> EncryptedData object using the
+symmetric I<key> of size I<keylen> bytes. I<out> is a BIO to write the content
+to and I<flags> is an optional set of flags.
+I<dcont> is used in the rare case where the encrypted content is detached. It
+will normally be set to NULL.
+
+The following flags can be passed in the B<flags> parameter.
+
+If the B<CMS_TEXT> flag is set MIME headers for type B<text/plain> are deleted
+from the content. If the content is not of type B<text/plain> then an error is
+returned.
+
+=head1 RETURN VALUES
+
+CMS_EncryptedData_decrypt() returns 0 if an error occurred otherwise it
+returns 1.
+
+=head1 SEE ALSO
+
+L<ERR_get_error(3)>, L<CMS_EncryptedData_encrypt(3)>
+
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/CMS_EncryptedData_encrypt.pod b/doc/man3/CMS_EncryptedData_encrypt.pod
new file mode 100644
index 000000000000..d3c3b254be03
--- /dev/null
+++ b/doc/man3/CMS_EncryptedData_encrypt.pod
@@ -0,0 +1,69 @@
+=pod
+
+=head1 NAME
+
+CMS_EncryptedData_encrypt_ex, CMS_EncryptedData_encrypt
+- Create CMS EncryptedData
+
+=head1 SYNOPSIS
+
+ #include <openssl/cms.h>
+
+ CMS_ContentInfo *CMS_EncryptedData_encrypt_ex(BIO *in,
+ const EVP_CIPHER *cipher,
+ const unsigned char *key,
+ size_t keylen,
+ unsigned int flags,
+ OSSL_LIB_CTX *ctx,
+ const char *propq);
+
+ CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in,
+ const EVP_CIPHER *cipher, const unsigned char *key, size_t keylen,
+ unsigned int flags);
+
+=head1 DESCRIPTION
+
+CMS_EncryptedData_encrypt_ex() creates a B<CMS_ContentInfo> structure
+with a type B<NID_pkcs7_encrypted>. I<in> is a BIO containing the data to
+encrypt using I<cipher> and the encryption key I<key> of size I<keylen> bytes.
+The library context I<libctx> and the property query I<propq> are used when
+retrieving algorithms from providers. I<flags> is a set of optional flags.
+
+The I<flags> field supports the options B<CMS_DETACHED>, B<CMS_STREAM> and
+B<CMS_PARTIAL>. Internally CMS_final() is called unless B<CMS_STREAM> and/or
+B<CMS_PARTIAL> is specified.
+
+The algorithm passed in the I<cipher> parameter must support ASN1 encoding of
+its parameters.
+
+The B<CMS_ContentInfo> structure can be freed using L<CMS_ContentInfo_free(3)>.
+
+CMS_EncryptedData_encrypt() is similar to CMS_EncryptedData_encrypt_ex()
+but uses default values of NULL for the library context I<libctx> and the
+property query I<propq>.
+
+=head1 RETURN VALUES
+
+If the allocation fails, CMS_EncryptedData_encrypt_ex() and
+CMS_EncryptedData_encrypt() return NULL and set an error code that can be
+obtained by L<ERR_get_error(3)>. Otherwise they return a pointer to the newly
+allocated structure.
+
+=head1 SEE ALSO
+
+L<ERR_get_error(3)>, L<CMS_final(3)>, L<CMS_EncryptedData_decrypt(3)>
+
+=head1 HISTORY
+
+The CMS_EncryptedData_encrypt_ex() method was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/CMS_EnvelopedData_create.pod b/doc/man3/CMS_EnvelopedData_create.pod
new file mode 100644
index 000000000000..e5ff269e47be
--- /dev/null
+++ b/doc/man3/CMS_EnvelopedData_create.pod
@@ -0,0 +1,80 @@
+=pod
+
+=head1 NAME
+
+CMS_EnvelopedData_create_ex, CMS_EnvelopedData_create,
+CMS_AuthEnvelopedData_create, CMS_AuthEnvelopedData_create_ex
+- Create CMS envelope
+
+=head1 SYNOPSIS
+
+ #include <openssl/cms.h>
+
+ CMS_ContentInfo *
+ CMS_EnvelopedData_create_ex(const EVP_CIPHER *cipher, OSSL_LIB_CTX *libctx,
+ const char *propq);
+ CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher);
+
+ CMS_ContentInfo *
+ CMS_AuthEnvelopedData_create_ex(const EVP_CIPHER *cipher, OSSL_LIB_CTX *libctx,
+ const char *propq);
+ CMS_ContentInfo *CMS_AuthEnvelopedData_create(const EVP_CIPHER *cipher);
+
+=head1 DESCRIPTION
+
+CMS_EnvelopedData_create_ex() creates a B<CMS_ContentInfo> structure
+with a type B<NID_pkcs7_enveloped>. I<cipher> is the symmetric cipher to use.
+The library context I<libctx> and the property query I<propq> are used when
+retrieving algorithms from providers.
+
+CMS_AuthEnvelopedData_create_ex() creates a B<CMS_ContentInfo>
+structure with a type B<NID_id_smime_ct_authEnvelopedData>. B<cipher> is the
+symmetric AEAD cipher to use. Currently only AES variants with GCM mode are
+supported. The library context I<libctx> and the property query I<propq> are
+used when retrieving algorithms from providers.
+
+The algorithm passed in the I<cipher> parameter must support ASN1 encoding of
+its parameters.
+
+The recipients can be added later using L<CMS_add1_recipient_cert(3)> or
+L<CMS_add0_recipient_key(3)>.
+
+The B<CMS_ContentInfo> structure needs to be finalized using L<CMS_final(3)>
+and then freed using L<CMS_ContentInfo_free(3)>.
+
+CMS_EnvelopedData_create() and CMS_AuthEnvelopedData_create are similar to
+CMS_EnvelopedData_create_ex() and
+CMS_AuthEnvelopedData_create_ex() but use default values of NULL for
+the library context I<libctx> and the property query I<propq>.
+
+=head1 NOTES
+
+Although CMS_EnvelopedData_create() and CMS_AuthEnvelopedData_create() allocate
+a new B<CMS_ContentInfo> structure, they are not usually used in applications.
+The wrappers L<CMS_encrypt(3)> and L<CMS_decrypt(3)> are often used instead.
+
+=head1 RETURN VALUES
+
+If the allocation fails, CMS_EnvelopedData_create() and
+CMS_AuthEnvelopedData_create() return NULL and set an error code that can be
+obtained by L<ERR_get_error(3)>. Otherwise they return a pointer to the newly
+allocated structure.
+
+=head1 SEE ALSO
+
+L<ERR_get_error(3)>, L<CMS_encrypt(3)>, L<CMS_decrypt(3)>, L<CMS_final(3)>
+
+=head1 HISTORY
+
+The CMS_EnvelopedData_create_ex() method was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/CMS_add0_cert.pod b/doc/man3/CMS_add0_cert.pod
index 944f998746a4..734db9f7b972 100644
--- a/doc/man3/CMS_add0_cert.pod
+++ b/doc/man3/CMS_add0_cert.pod
@@ -70,7 +70,7 @@ L<CMS_encrypt(3)>
Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CMS_add1_recipient_cert.pod b/doc/man3/CMS_add1_recipient_cert.pod
index 56399f92895b..e1fc34303be0 100644
--- a/doc/man3/CMS_add1_recipient_cert.pod
+++ b/doc/man3/CMS_add1_recipient_cert.pod
@@ -2,12 +2,16 @@
=head1 NAME
-CMS_add1_recipient_cert, CMS_add0_recipient_key - add recipients to a CMS enveloped data structure
+CMS_add1_recipient, CMS_add1_recipient_cert, CMS_add0_recipient_key - add recipients to a CMS enveloped data structure
=head1 SYNOPSIS
#include <openssl/cms.h>
+ CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip,
+ EVP_PKEY *originatorPrivKey,
+ X509 *originator, unsigned int flags);
+
CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
X509 *recip, unsigned int flags);
@@ -20,6 +24,11 @@ CMS_add1_recipient_cert, CMS_add0_recipient_key - add recipients to a CMS envelo
=head1 DESCRIPTION
+CMS_add1_recipient() adds recipient B<recip> and provides the originator pkey
+B<originatorPrivKey> and originator certificate B<originator> to CMS_ContentInfo.
+The originator-related fields are relevant only in case when the keyAgreement
+method of providing of the shared key is in use.
+
CMS_add1_recipient_cert() adds recipient B<recip> to CMS_ContentInfo enveloped
data structure B<cms> as a KeyTransRecipientInfo structure.
@@ -60,11 +69,16 @@ occurs.
L<ERR_get_error(3)>, L<CMS_decrypt(3)>,
L<CMS_final(3)>,
+=head1 HISTORY
+
+B<CMS_add1_recipient_cert> and B<CMS_add0_recipient_key> were added in
+OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CMS_add1_signer.pod b/doc/man3/CMS_add1_signer.pod
index 48d0154e41c9..800085b7b86a 100644
--- a/doc/man3/CMS_add1_signer.pod
+++ b/doc/man3/CMS_add1_signer.pod
@@ -99,7 +99,7 @@ L<CMS_final(3)>,
Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CMS_compress.pod b/doc/man3/CMS_compress.pod
index e40510831fce..312484610e68 100644
--- a/doc/man3/CMS_compress.pod
+++ b/doc/man3/CMS_compress.pod
@@ -17,8 +17,6 @@ is the compression algorithm to use or B<NID_undef> to use the default
algorithm (zlib compression). B<in> is the content to be compressed.
B<flags> is an optional set of flags.
-=head1 NOTES
-
The only currently supported compression algorithm is zlib using the NID
NID_zlib_compression.
@@ -41,8 +39,6 @@ The compressed data is included in the CMS_ContentInfo structure, unless
B<CMS_DETACHED> is set in which case it is omitted. This is rarely used in
practice and is not supported by SMIME_write_CMS().
-=head1 NOTES
-
If the flag B<CMS_STREAM> is set the returned B<CMS_ContentInfo> structure is
B<not> complete and outputting its contents via a function that does not
properly finalize the B<CMS_ContentInfo> structure will give unpredictable
@@ -73,7 +69,7 @@ The B<CMS_STREAM> flag was added in OpenSSL 1.0.0.
Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CMS_data_create.pod b/doc/man3/CMS_data_create.pod
new file mode 100644
index 000000000000..558e70b5e0e0
--- /dev/null
+++ b/doc/man3/CMS_data_create.pod
@@ -0,0 +1,54 @@
+=pod
+
+=head1 NAME
+
+CMS_data_create_ex, CMS_data_create
+- Create CMS Data object
+
+=head1 SYNOPSIS
+
+ #include <openssl/cms.h>
+
+ CMS_ContentInfo *CMS_data_create_ex(BIO *in, unsigned int flags,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags);
+
+=head1 DESCRIPTION
+
+CMS_data_create_ex() creates a B<CMS_ContentInfo> structure
+with a type B<NID_pkcs7_data>. The data is supplied via the I<in> BIO.
+The library context I<libctx> and the property query I<propq> are used when
+retrieving algorithms from providers. The I<flags> field supports the
+B<CMS_STREAM> flag. Internally CMS_final() is called unless B<CMS_STREAM> is
+specified.
+
+The B<CMS_ContentInfo> structure can be freed using L<CMS_ContentInfo_free(3)>.
+
+CMS_data_create() is similar to CMS_data_create_ex()
+but uses default values of NULL for the library context I<libctx> and the
+property query I<propq>.
+
+=head1 RETURN VALUES
+
+If the allocation fails, CMS_data_create_ex() and CMS_data_create()
+return NULL and set an error code that can be obtained by L<ERR_get_error(3)>.
+Otherwise they return a pointer to the newly allocated structure.
+
+=head1 SEE ALSO
+
+L<ERR_get_error(3)>, L<CMS_final(3)>
+
+=head1 HISTORY
+
+The CMS_data_create_ex() method was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/CMS_decrypt.pod b/doc/man3/CMS_decrypt.pod
index b9f2c28447c6..4f8d32fbbb24 100644
--- a/doc/man3/CMS_decrypt.pod
+++ b/doc/man3/CMS_decrypt.pod
@@ -2,7 +2,8 @@
=head1 NAME
-CMS_decrypt - decrypt content from a CMS envelopedData structure
+CMS_decrypt, CMS_decrypt_set1_pkey_and_peer, CMS_decrypt_set1_pkey - decrypt
+content from a CMS envelopedData structure
=head1 SYNOPSIS
@@ -10,17 +11,27 @@ CMS_decrypt - decrypt content from a CMS envelopedData structure
int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert,
BIO *dcont, BIO *out, unsigned int flags);
+ int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms,
+ EVP_PKEY *pk, X509 *cert, X509 *peer);
+ int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert);
=head1 DESCRIPTION
CMS_decrypt() extracts and decrypts the content from a CMS EnvelopedData
-structure. B<pkey> is the private key of the recipient, B<cert> is the
-recipient's certificate, B<out> is a BIO to write the content to and
-B<flags> is an optional set of flags.
+or AuthEnvelopedData structure. B<pkey> is the private key of the recipient,
+B<cert> is the recipient's certificate, B<out> is a BIO to write the content to
+and B<flags> is an optional set of flags.
The B<dcont> parameter is used in the rare case where the encrypted content
is detached. It will normally be set to NULL.
+CMS_decrypt_set1_pkey_and_peer() associates the private key B<pkey>, the
+corresponding certificate B<cert> and the originator certificate B<peer> with
+the CMS_ContentInfo structure B<cms>.
+
+CMS_decrypt_set1_pkey() associates the private key B<pkey>, corresponding
+certificate B<cert> with the CMS_ContentInfo structure B<cms>.
+
=head1 NOTES
Although the recipients certificate is not needed to decrypt the data it is
@@ -70,11 +81,15 @@ mentioned in CMS_verify() also applies to CMS_decrypt().
L<ERR_get_error(3)>, L<CMS_encrypt(3)>
+=head1 HISTORY
+
+B<CMS_decrypt_set1_pkey_and_peer> was added in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CMS_digest_create.pod b/doc/man3/CMS_digest_create.pod
new file mode 100644
index 000000000000..bd83e2aa6fa3
--- /dev/null
+++ b/doc/man3/CMS_digest_create.pod
@@ -0,0 +1,58 @@
+=pod
+
+=head1 NAME
+
+CMS_digest_create_ex, CMS_digest_create
+- Create CMS DigestedData object
+
+=head1 SYNOPSIS
+
+ #include <openssl/cms.h>
+
+ CMS_ContentInfo *CMS_digest_create_ex(BIO *in, const EVP_MD *md,
+ unsigned int flags, OSSL_LIB_CTX *ctx,
+ const char *propq);
+
+ CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
+ unsigned int flags);
+
+=head1 DESCRIPTION
+
+CMS_digest_create_ex() creates a B<CMS_ContentInfo> structure
+with a type B<NID_pkcs7_digest>. The data supplied via the I<in> BIO is digested
+using I<md>. The library context I<libctx> and the property query I<propq> are
+used when retrieving algorithms from providers.
+The I<flags> field supports the B<CMS_DETACHED> and B<CMS_STREAM> flags,
+Internally CMS_final() is called unless B<CMS_STREAM> is specified.
+
+The B<CMS_ContentInfo> structure can be freed using L<CMS_ContentInfo_free(3)>.
+
+CMS_digest_create() is similar to CMS_digest_create_ex()
+but uses default values of NULL for the library context I<libctx> and the
+property query I<propq>.
+
+
+=head1 RETURN VALUES
+
+If the allocation fails, CMS_digest_create_ex() and CMS_digest_create()
+return NULL and set an error code that can be obtained by L<ERR_get_error(3)>.
+Otherwise they return a pointer to the newly allocated structure.
+
+=head1 SEE ALSO
+
+L<ERR_get_error(3)>, L<CMS_final(3)>>
+
+=head1 HISTORY
+
+The CMS_digest_create_ex() method was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/CMS_encrypt.pod b/doc/man3/CMS_encrypt.pod
index 2fc8084bf441..cddd89447b47 100644
--- a/doc/man3/CMS_encrypt.pod
+++ b/doc/man3/CMS_encrypt.pod
@@ -2,22 +2,26 @@
=head1 NAME
-CMS_encrypt - create a CMS envelopedData structure
+CMS_encrypt_ex, CMS_encrypt - create a CMS envelopedData structure
=head1 SYNOPSIS
#include <openssl/cms.h>
+ CMS_ContentInfo *CMS_encrypt_ex(STACK_OF(X509) *certs, BIO *in,
+ const EVP_CIPHER *cipher, unsigned int flags,
+ OSSL_LIB_CTX *libctx, const char *propq);
CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in,
const EVP_CIPHER *cipher, unsigned int flags);
=head1 DESCRIPTION
-CMS_encrypt() creates and returns a CMS EnvelopedData structure. B<certs>
-is a list of recipient certificates. B<in> is the content to be encrypted.
-B<cipher> is the symmetric cipher to use. B<flags> is an optional set of flags.
-
-=head1 NOTES
+CMS_encrypt_ex() creates and returns a CMS EnvelopedData or
+AuthEnvelopedData structure. I<certs> is a list of recipient certificates.
+I<in> is the content to be encrypted. I<cipher> is the symmetric cipher to use.
+I<flags> is an optional set of flags. The library context I<libctx> and the
+property query I<propq> are used internally when retrieving algorithms from
+providers.
Only certificates carrying RSA, Diffie-Hellman or EC keys are supported by this
function.
@@ -26,7 +30,9 @@ EVP_des_ede3_cbc() (triple DES) is the algorithm of choice for S/MIME use
because most clients will support it.
The algorithm passed in the B<cipher> parameter must support ASN1 encoding of
-its parameters.
+its parameters. If the cipher mode is GCM, then an AuthEnvelopedData structure
+containing MAC is used. Otherwise an EnvelopedData structure is used. Currently
+the AES variants with GCM mode are the only supported AEAD algorithms.
Many browsers implement a "sign and encrypt" option which is simply an S/MIME
envelopedData containing an S/MIME signed message. This can be readily produced
@@ -60,8 +66,6 @@ The data being encrypted is included in the CMS_ContentInfo structure, unless
B<CMS_DETACHED> is set in which case it is omitted. This is rarely used in
practice and is not supported by SMIME_write_CMS().
-=head1 NOTES
-
If the flag B<CMS_STREAM> is set the returned B<CMS_ContentInfo> structure is
B<not> complete and outputting its contents via a function that does not
properly finalize the B<CMS_ContentInfo> structure will give unpredictable
@@ -79,10 +83,14 @@ and CMS_add0_recipient_key().
The parameter B<certs> may be NULL if B<CMS_PARTIAL> is set and recipients
added later using CMS_add1_recipient_cert() or CMS_add0_recipient_key().
+CMS_encrypt() is similar to CMS_encrypt_ex() but uses default values
+of NULL for the library context I<libctx> and the property query I<propq>.
+
=head1 RETURN VALUES
-CMS_encrypt() returns either a CMS_ContentInfo structure or NULL if an error
-occurred. The error can be obtained from ERR_get_error(3).
+CMS_encrypt_ex() and CMS_encrypt() return either a CMS_ContentInfo
+structure or NULL if an error occurred. The error can be obtained from
+ERR_get_error(3).
=head1 SEE ALSO
@@ -90,13 +98,15 @@ L<ERR_get_error(3)>, L<CMS_decrypt(3)>
=head1 HISTORY
+The function CMS_encrypt_ex() was added in OpenSSL 3.0.
+
The B<CMS_STREAM> flag was first supported in OpenSSL 1.0.0.
=head1 COPYRIGHT
-Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CMS_final.pod b/doc/man3/CMS_final.pod
index 15fd15a68c0d..8270d53bc712 100644
--- a/doc/man3/CMS_final.pod
+++ b/doc/man3/CMS_final.pod
@@ -36,9 +36,9 @@ L<CMS_encrypt(3)>
=head1 COPYRIGHT
-Copyright 2008-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CMS_get0_RecipientInfos.pod b/doc/man3/CMS_get0_RecipientInfos.pod
index ba4a60ad05ff..8f4593538d19 100644
--- a/doc/man3/CMS_get0_RecipientInfos.pod
+++ b/doc/man3/CMS_get0_RecipientInfos.pod
@@ -5,6 +5,8 @@
CMS_get0_RecipientInfos, CMS_RecipientInfo_type,
CMS_RecipientInfo_ktri_get0_signer_id, CMS_RecipientInfo_ktri_cert_cmp,
CMS_RecipientInfo_set0_pkey, CMS_RecipientInfo_kekri_get0_id,
+CMS_RecipientInfo_kari_set0_pkey_and_peer,
+CMS_RecipientInfo_kari_set0_pkey,
CMS_RecipientInfo_kekri_id_cmp, CMS_RecipientInfo_set0_key,
CMS_RecipientInfo_decrypt, CMS_RecipientInfo_encrypt
- CMS envelopedData RecipientInfo routines
@@ -22,7 +24,9 @@ CMS_RecipientInfo_decrypt, CMS_RecipientInfo_encrypt
ASN1_INTEGER **sno);
int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert);
int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey);
-
+ int CMS_RecipientInfo_kari_set0_pkey_and_peer(CMS_RecipientInfo *ri,
+ EVP_PKEY *pk, X509 *peer);
+ int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk);
int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri, X509_ALGOR **palg,
ASN1_OCTET_STRING **pid,
ASN1_GENERALIZEDTIME **pdate,
@@ -58,6 +62,13 @@ CMS_RecipientInfo_set0_pkey() associates the private key B<pkey> with
the CMS_RecipientInfo structure B<ri>, which must be of type
CMS_RECIPINFO_TRANS.
+CMS_RecipientInfo_kari_set0_pkey_and_peer() associates the private key B<pkey>
+and peer certificate B<peer> with the CMS_RecipientInfo structure B<ri>, which
+must be of type CMS_RECIPINFO_AGREE.
+
+CMS_RecipientInfo_kari_set0_pkey() associates the private key B<pkey> with the
+CMS_RecipientInfo structure B<ri>, which must be of type CMS_RECIPINFO_AGREE.
+
CMS_RecipientInfo_kekri_get0_id() retrieves the key information from the
CMS_RecipientInfo structure B<ri> which must be of type CMS_RECIPINFO_KEK. Any
of the remaining parameters can be NULL if the application is not interested in
@@ -127,11 +138,16 @@ Any error can be obtained from L<ERR_get_error(3)>.
L<ERR_get_error(3)>, L<CMS_decrypt(3)>
+=head1 HISTORY
+
+B<CMS_RecipientInfo_kari_set0_pkey_and_peer> and B<CMS_RecipientInfo_kari_set0_pkey>
+were added in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CMS_get0_SignerInfos.pod b/doc/man3/CMS_get0_SignerInfos.pod
index 694b614b481d..385726ced35f 100644
--- a/doc/man3/CMS_get0_SignerInfos.pod
+++ b/doc/man3/CMS_get0_SignerInfos.pod
@@ -82,7 +82,7 @@ L<ERR_get_error(3)>, L<CMS_verify(3)>
Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CMS_get0_type.pod b/doc/man3/CMS_get0_type.pod
index bc38a09bdcbc..12c2e650a820 100644
--- a/doc/man3/CMS_get0_type.pod
+++ b/doc/man3/CMS_get0_type.pod
@@ -20,7 +20,8 @@ an ASN1_OBJECT pointer. An application can then decide how to process the
CMS_ContentInfo structure based on this value.
CMS_set1_eContentType() sets the embedded content type of a CMS_ContentInfo
-structure. It should be called with CMS functions (such as L<CMS_sign>, L<CMS_encrypt>)
+structure. It should be called with CMS functions (such as L<CMS_sign(3)>,
+L<CMS_encrypt(3)>)
with the B<CMS_PARTIAL>
flag and B<before> the structure is finalised, otherwise the results are
undefined.
@@ -72,9 +73,9 @@ L<ERR_get_error(3)>
=head1 COPYRIGHT
-Copyright 2008-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CMS_get1_ReceiptRequest.pod b/doc/man3/CMS_get1_ReceiptRequest.pod
index 30a3626e1e78..b821103a59fd 100644
--- a/doc/man3/CMS_get1_ReceiptRequest.pod
+++ b/doc/man3/CMS_get1_ReceiptRequest.pod
@@ -2,16 +2,21 @@
=head1 NAME
-CMS_ReceiptRequest_create0, CMS_add1_ReceiptRequest, CMS_get1_ReceiptRequest, CMS_ReceiptRequest_get0_values - CMS signed receipt request functions
+CMS_ReceiptRequest_create0_ex, CMS_ReceiptRequest_create0,
+CMS_add1_ReceiptRequest, CMS_get1_ReceiptRequest, CMS_ReceiptRequest_get0_values
+- CMS signed receipt request functions
=head1 SYNOPSIS
#include <openssl/cms.h>
- CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
- int allorfirst,
- STACK_OF(GENERAL_NAMES) *receiptList,
- STACK_OF(GENERAL_NAMES) *receiptsTo);
+ CMS_ReceiptRequest *CMS_ReceiptRequest_create0_ex(
+ unsigned char *id, int idlen, int allorfirst,
+ STACK_OF(GENERAL_NAMES) *receiptList, STACK_OF(GENERAL_NAMES) *receiptsTo,
+ OSSL_LIB_CTX *libctx);
+ CMS_ReceiptRequest *CMS_ReceiptRequest_create0(
+ unsigned char *id, int idlen, int allorfirst,
+ STACK_OF(GENERAL_NAMES) *receiptList, STACK_OF(GENERAL_NAMES) *receiptsTo);
int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr);
int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr);
void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr, ASN1_STRING **pcid,
@@ -21,13 +26,18 @@ CMS_ReceiptRequest_create0, CMS_add1_ReceiptRequest, CMS_get1_ReceiptRequest, CM
=head1 DESCRIPTION
-CMS_ReceiptRequest_create0() creates a signed receipt request structure. The
-B<signedContentIdentifier> field is set using B<id> and B<idlen>, or it is set
-to 32 bytes of pseudo random data if B<id> is NULL. If B<receiptList> is NULL
-the allOrFirstTier option in B<receiptsFrom> is used and set to the value of
-the B<allorfirst> parameter. If B<receiptList> is not NULL the B<receiptList>
-option in B<receiptsFrom> is used. The B<receiptsTo> parameter specifies the
-B<receiptsTo> field value.
+CMS_ReceiptRequest_create0_ex() creates a signed receipt request
+structure. The B<signedContentIdentifier> field is set using I<id> and I<idlen>,
+or it is set to 32 bytes of pseudo random data if I<id> is NULL.
+If I<receiptList> is NULL the allOrFirstTier option in I<receiptsFrom> is used
+and set to the value of the I<allorfirst> parameter. If I<receiptList> is not
+NULL the I<receiptList> option in I<receiptsFrom> is used. The I<receiptsTo>
+parameter specifies the I<receiptsTo> field value. The library context I<libctx>
+is used to find the public random generator.
+
+CMS_ReceiptRequest_create0() is similar to
+CMS_ReceiptRequest_create0_ex() but uses default values of NULL for the
+library context I<libctx>.
The CMS_add1_ReceiptRequest() function adds a signed receipt request B<rr>
to SignerInfo structure B<si>.
@@ -51,8 +61,8 @@ CMS_verify().
=head1 RETURN VALUES
-CMS_ReceiptRequest_create0() returns a signed receipt request structure or
-NULL if an error occurred.
+CMS_ReceiptRequest_create0_ex() and CMS_ReceiptRequest_create0() return
+a signed receipt request structure or NULL if an error occurred.
CMS_add1_ReceiptRequest() returns 1 for success or 0 if an error occurred.
@@ -66,11 +76,15 @@ L<ERR_get_error(3)>, L<CMS_sign(3)>,
L<CMS_sign_receipt(3)>, L<CMS_verify(3)>
L<CMS_verify_receipt(3)>
+=head1 HISTORY
+
+The function CMS_ReceiptRequest_create0_ex() was added in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CMS_sign.pod b/doc/man3/CMS_sign.pod
index 79446b129889..0d812756aef5 100644
--- a/doc/man3/CMS_sign.pod
+++ b/doc/man3/CMS_sign.pod
@@ -2,27 +2,36 @@
=head1 NAME
-CMS_sign - create a CMS SignedData structure
+CMS_sign, CMS_sign_ex - create a CMS SignedData structure
=head1 SYNOPSIS
#include <openssl/cms.h>
+ CMS_ContentInfo *CMS_sign_ex(X509 *signcert, EVP_PKEY *pkey,
+ STACK_OF(X509) *certs, BIO *data,
+ unsigned int flags, OSSL_LIB_CTX *ctx,
+ const char *propq);
CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
BIO *data, unsigned int flags);
=head1 DESCRIPTION
-CMS_sign() creates and returns a CMS SignedData structure. B<signcert> is
-the certificate to sign with, B<pkey> is the corresponding private key.
-B<certs> is an optional additional set of certificates to include in the CMS
-structure (for example any intermediate CAs in the chain). Any or all of
-these parameters can be B<NULL>, see B<NOTES> below.
+CMS_sign_ex() creates and returns a CMS SignedData structure.
+I<signcert> is the certificate to sign with, I<pkey> is the corresponding
+private key. I<certs> is an optional additional set of certificates to include
+in the CMS structure (for example any intermediate CAs in the chain). The
+library context I<libctx> and the property query I<propq> are used when
+retrieving algorithms from providers. Any or all of these parameters can be
+B<NULL>, see B<NOTES> below.
The data to be signed is read from BIO B<data>.
B<flags> is an optional set of flags.
+CMS_sign() is similar to CMS_sign_ex() but uses default values of NULL
+for the library context I<libctx> and the property query I<propq>.
+
=head1 NOTES
Any of the following flags (ored together) can be passed in the B<flags>
@@ -57,7 +66,8 @@ omitted.
If present the SMIMECapabilities attribute indicates support for the following
algorithms in preference order: 256 bit AES, Gost R3411-94, Gost 28147-89, 192
bit AES, 128 bit AES, triple DES, 128 bit RC2, 64 bit RC2, DES and 40 bit RC2.
-If any of these algorithms is not available then it will not be included: for example the GOST algorithms will not be included if the GOST ENGINE is
+If any of these algorithms is not available then it will not be included:
+for example the GOST algorithms will not be included if the GOST ENGINE is
not loaded.
OpenSSL will by default identify signing certificates using issuer name
@@ -105,8 +115,9 @@ Some attributes such as counter signatures are not supported.
=head1 RETURN VALUES
-CMS_sign() returns either a valid CMS_ContentInfo structure or NULL if an error
-occurred. The error can be obtained from ERR_get_error(3).
+CMS_sign_ex() and CMS_sign() return either a valid CMS_ContentInfo
+structure or NULL if an error occurred. The error can be obtained from
+ERR_get_error(3).
=head1 SEE ALSO
@@ -117,11 +128,13 @@ L<ERR_get_error(3)>, L<CMS_verify(3)>
The B<CMS_STREAM> flag is only supported for detached data in OpenSSL 0.9.8,
it is supported for embedded data in OpenSSL 1.0.0 and later.
+The CMS_sign_ex() method was added in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CMS_sign_receipt.pod b/doc/man3/CMS_sign_receipt.pod
index d65a2081e2ff..2d3542a99107 100644
--- a/doc/man3/CMS_sign_receipt.pod
+++ b/doc/man3/CMS_sign_receipt.pod
@@ -44,7 +44,7 @@ L<CMS_sign(3)>
Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CMS_uncompress.pod b/doc/man3/CMS_uncompress.pod
index 80f9c0d168bf..32bc81c080fc 100644
--- a/doc/man3/CMS_uncompress.pod
+++ b/doc/man3/CMS_uncompress.pod
@@ -51,7 +51,7 @@ L<ERR_get_error(3)>, L<CMS_compress(3)>
Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CMS_verify.pod b/doc/man3/CMS_verify.pod
index d7a423c30b29..70c8eb212d6b 100644
--- a/doc/man3/CMS_verify.pod
+++ b/doc/man3/CMS_verify.pod
@@ -74,10 +74,14 @@ from the content. If the content is not of type B<text/plain> then an error is
returned.
If B<CMS_NO_SIGNER_CERT_VERIFY> is set the signing certificates are not
-chain verified.
+chain verified, unless B<CMS_CADES> flag is also set.
If B<CMS_NO_ATTR_VERIFY> is set the signed attributes signature is not
-verified.
+verified, unless CMS_CADES flag is also set.
+
+If B<CMS_CADES> is set, each signer certificate is checked against the
+ESS signingCertificate or ESS signingCertificateV2 extension
+that is required in the signed attributes of the signature.
If B<CMS_NO_CONTENT_VERIFY> is set then the content digest is not checked.
@@ -133,7 +137,7 @@ L<ERR_get_error(3)>, L<CMS_sign(3)>
Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CMS_verify_receipt.pod b/doc/man3/CMS_verify_receipt.pod
index 67735299695d..bf3019ae72fc 100644
--- a/doc/man3/CMS_verify_receipt.pod
+++ b/doc/man3/CMS_verify_receipt.pod
@@ -46,7 +46,7 @@ L<CMS_verify(3)>,
Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CONF_modules_free.pod b/doc/man3/CONF_modules_free.pod
index 5c3debb48dce..81b10ebc3bbe 100644
--- a/doc/man3/CONF_modules_free.pod
+++ b/doc/man3/CONF_modules_free.pod
@@ -12,11 +12,11 @@ OpenSSL configuration cleanup functions
void CONF_modules_finish(void);
void CONF_modules_unload(int all);
-Deprecated:
+The following functions have been deprecated since OpenSSL 1.1.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
- #if OPENSSL_API_COMPAT < 0x10100000L
- void CONF_modules_free(void)
- #endif
+ void CONF_modules_free(void);
=head1 DESCRIPTION
@@ -30,7 +30,7 @@ to free up any configuration that module may have performed.
CONF_modules_unload() finishes and unloads configuration modules. If
B<all> is set to B<0> only modules loaded from DSOs will be unloads. If
-B<all> is B<1> all modules, including builtin modules will be unloaded.
+B<all> is B<1> all modules, including built-in modules will be unloaded.
=head1 RETURN VALUES
@@ -39,7 +39,7 @@ None of the functions return a value.
=head1 SEE ALSO
L<config(5)>, L<OPENSSL_config(3)>,
-L<CONF_modules_load_file(3)>
+L<CONF_modules_load_file_ex(3)>
=head1 HISTORY
@@ -48,9 +48,9 @@ For more information see L<OPENSSL_init_crypto(3)>.
=head1 COPYRIGHT
-Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CONF_modules_load_file.pod b/doc/man3/CONF_modules_load_file.pod
index 04fbd60f40b7..f96d9a12938a 100644
--- a/doc/man3/CONF_modules_load_file.pod
+++ b/doc/man3/CONF_modules_load_file.pod
@@ -2,12 +2,17 @@
=head1 NAME
-CONF_modules_load_file, CONF_modules_load - OpenSSL configuration functions
+CONF_get1_default_config_file,
+CONF_modules_load_file_ex, CONF_modules_load_file, CONF_modules_load
+- OpenSSL configuration functions
=head1 SYNOPSIS
#include <openssl/conf.h>
+ char *CONF_get1_default_config_file(void);
+ int CONF_modules_load_file_ex(OSSL_LIB_CTX *libctx, const char *filename,
+ const char *appname, unsigned long flags);
int CONF_modules_load_file(const char *filename, const char *appname,
unsigned long flags);
int CONF_modules_load(const CONF *cnf, const char *appname,
@@ -15,11 +20,24 @@ CONF_modules_load_file, CONF_modules_load - OpenSSL configuration functions
=head1 DESCRIPTION
-The function CONF_modules_load_file() configures OpenSSL using file
-B<filename> and application name B<appname>. If B<filename> is NULL
-the standard OpenSSL configuration file is used. If B<appname> is
-NULL the standard OpenSSL application name B<openssl_conf> is used.
-The behaviour can be customized using B<flags>.
+The function CONF_get1_default_config_file() determines the default
+configuration file pathname as follows.
+If the B<OPENSSL_CONF> environment variable is set its value is returned.
+Else the function returns the path obtained using
+L<X509_get_default_cert_area(3)> with the filename C<"openssl.cnf"> appended.
+The caller is responsible for freeing any string returned.
+
+The function CONF_modules_load_file_ex() configures OpenSSL using
+library context B<libctx> file B<filename> and application name B<appname>.
+If B<filename> is NULL the standard OpenSSL configuration file is used
+as determined by calling CONF_get1_default_config_file().
+If B<appname> is NULL the standard OpenSSL application name B<openssl_conf> is
+used.
+The behaviour can be customized using B<flags>. Note that, the error suppressing
+can be overriden by B<config_diagnostics> as described in L<config(5)>.
+
+CONF_modules_load_file() is the same as CONF_modules_load_file_ex() but
+has a NULL library context.
CONF_modules_load() is identical to CONF_modules_load_file() except it
reads configuration information from B<cnf>.
@@ -40,8 +58,8 @@ returns success.
This is used by default in L<OPENSSL_init_crypto(3)> to ignore any errors in
the default system-wide configuration file, as having all OpenSSL applications
fail to start when there are potentially minor issues in the file is too risky.
-Applications calling B<CONF_modules_load_file> explicitly should not generally
-set this flag.
+Applications calling B<CONF_modules_load_file_ex> explicitly should not
+generally set this flag.
If B<CONF_MFLAGS_NO_DSO> is set configuration module loading from DSOs is
disabled.
@@ -53,10 +71,10 @@ return an error.
B<CONF_MFLAGS_DEFAULT_SECTION> if set and B<appname> is not NULL will use the
default section pointed to by B<openssl_conf> if B<appname> does not exist.
-By using CONF_modules_load_file() with appropriate flags an application can
-customise application configuration to best suit its needs. In some cases the
-use of a configuration file is optional and its absence is not an error: in
-this case B<CONF_MFLAGS_IGNORE_MISSING_FILE> would be set.
+By using CONF_modules_load_file_ex() with appropriate flags an
+application can customise application configuration to best suit its needs.
+In some cases the use of a configuration file is optional and its absence is not
+an error: in this case B<CONF_MFLAGS_IGNORE_MISSING_FILE> would be set.
Errors during configuration may also be handled differently by different
applications. For example in some cases an error may simply print out a warning
@@ -78,7 +96,7 @@ return value of the failing module (this will always be zero or negative).
Load a configuration file and print out any errors and exit (missing file
considered fatal):
- if (CONF_modules_load_file(NULL, NULL, 0) <= 0) {
+ if (CONF_modules_load_file_ex(libctx, NULL, NULL, 0) <= 0) {
fprintf(stderr, "FATAL: error loading configuration file\n");
ERR_print_errors_fp(stderr);
exit(1);
@@ -87,8 +105,8 @@ considered fatal):
Load default configuration file using the section indicated by "myapp",
tolerate missing files, but exit on other errors:
- if (CONF_modules_load_file(NULL, "myapp",
- CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) {
+ if (CONF_modules_load_file_ex(NULL, NULL, "myapp",
+ CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) {
fprintf(stderr, "FATAL: error loading configuration file\n");
ERR_print_errors_fp(stderr);
exit(1);
@@ -97,8 +115,8 @@ tolerate missing files, but exit on other errors:
Load custom configuration file and section, only print warnings on error,
missing configuration file ignored:
- if (CONF_modules_load_file("/something/app.cnf", "myapp",
- CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) {
+ if (CONF_modules_load_file_ex(NULL, "/something/app.cnf", "myapp",
+ CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) {
fprintf(stderr, "WARNING: error loading configuration file\n");
ERR_print_errors_fp(stderr);
}
@@ -114,7 +132,7 @@ Load and parse configuration file manually, custom error handling:
fprintf(stderr, "Error opening configuration file\n");
/* Other missing configuration file behaviour */
} else {
- cnf = NCONF_new(NULL);
+ cnf = NCONF_new_ex(libctx, NULL);
if (NCONF_load_fp(cnf, fp, &eline) == 0) {
fprintf(stderr, "Error on line %ld of configuration file\n", eline);
ERR_print_errors_fp(stderr);
@@ -130,13 +148,15 @@ Load and parse configuration file manually, custom error handling:
=head1 SEE ALSO
-L<config(5)>, L<OPENSSL_config(3)>
+L<config(5)>,
+L<OPENSSL_config(3)>,
+L<NCONF_new_ex(3)>
=head1 COPYRIGHT
-Copyright 2004-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CRYPTO_THREAD_run_once.pod b/doc/man3/CRYPTO_THREAD_run_once.pod
index 946147e5d24e..a51679b97edd 100644
--- a/doc/man3/CRYPTO_THREAD_run_once.pod
+++ b/doc/man3/CRYPTO_THREAD_run_once.pod
@@ -5,7 +5,7 @@
CRYPTO_THREAD_run_once,
CRYPTO_THREAD_lock_new, CRYPTO_THREAD_read_lock, CRYPTO_THREAD_write_lock,
CRYPTO_THREAD_unlock, CRYPTO_THREAD_lock_free,
-CRYPTO_atomic_add - OpenSSL thread support
+CRYPTO_atomic_add, CRYPTO_atomic_or, CRYPTO_atomic_load - OpenSSL thread support
=head1 SYNOPSIS
@@ -21,6 +21,9 @@ CRYPTO_atomic_add - OpenSSL thread support
void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock);
int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock);
+ int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret,
+ CRYPTO_RWLOCK *lock);
+ int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock);
=head1 DESCRIPTION
@@ -38,10 +41,10 @@ The following multi-threading function are provided:
=item *
CRYPTO_THREAD_run_once() can be used to perform one-time initialization.
-The B<once> argument must be a pointer to a static object of type
+The I<once> argument must be a pointer to a static object of type
B<CRYPTO_ONCE> that was statically initialized to the value
B<CRYPTO_ONCE_STATIC_INIT>.
-The B<init> argument is a pointer to a function that performs the desired
+The I<init> argument is a pointer to a function that performs the desired
exactly once initialization.
In particular, this can be used to allocate locks in a thread-safe manner,
which can then be used with the locking functions below.
@@ -53,27 +56,47 @@ lock.
=item *
-CRYPTO_THREAD_read_lock() locks the provided B<lock> for reading.
+CRYPTO_THREAD_read_lock() locks the provided I<lock> for reading.
=item *
-CRYPTO_THREAD_write_lock() locks the provided B<lock> for writing.
+CRYPTO_THREAD_write_lock() locks the provided I<lock> for writing.
=item *
-CRYPTO_THREAD_unlock() unlocks the previously locked B<lock>.
+CRYPTO_THREAD_unlock() unlocks the previously locked I<lock>.
=item *
-CRYPTO_THREAD_lock_free() frees the provided B<lock>.
+CRYPTO_THREAD_lock_free() frees the provided I<lock>.
=item *
-CRYPTO_atomic_add() atomically adds B<amount> to B<val> and returns the
-result of the operation in B<ret>. B<lock> will be locked, unless atomic
+CRYPTO_atomic_add() atomically adds I<amount> to I<*val> and returns the
+result of the operation in I<*ret>. I<lock> will be locked, unless atomic
operations are supported on the specific platform. Because of this, if a
variable is modified by CRYPTO_atomic_add() then CRYPTO_atomic_add() must
-be the only way that the variable is modified.
+be the only way that the variable is modified. If atomic operations are not
+supported and I<lock> is NULL, then the function will fail.
+
+=item *
+
+CRYPTO_atomic_or() performs an atomic bitwise or of I<op> and I<*val> and stores
+the result back in I<*val>. It also returns the result of the operation in
+I<*ret>. I<lock> will be locked, unless atomic operations are supported on the
+specific platform. Because of this, if a variable is modified by
+CRYPTO_atomic_or() or read by CRYPTO_atomic_load() then CRYPTO_atomic_or() must
+be the only way that the variable is modified. If atomic operations are not
+supported and I<lock> is NULL, then the function will fail.
+
+=item *
+
+CRYPTO_atomic_load() atomically loads the contents of I<*val> into I<*ret>.
+I<lock> will be locked, unless atomic operations are supported on the specific
+platform. Because of this, if a variable is modified by CRYPTO_atomic_or() or
+read by CRYPTO_atomic_load() then CRYPTO_atomic_load() must be the only way that
+the variable is read. If atomic operations are not supported and I<lock> is
+NULL, then the function will fail.
=back
@@ -90,15 +113,25 @@ The other functions return 1 on success, or 0 on error.
=head1 NOTES
On Windows platforms the CRYPTO_THREAD_* types and functions in the
-openssl/crypto.h header are dependent on some of the types customarily
-made available by including windows.h. The application developer is
-likely to require control over when the latter is included, commonly as
-one of the first included headers. Therefore, it is defined as an
-application developer's responsibility to include windows.h prior to
-crypto.h where use of CRYPTO_THREAD_* types and functions is required.
+F<< <openssl/crypto.h> >> header are dependent on some of the types
+customarily made available by including F<< <windows.h> >>. The application
+developer is likely to require control over when the latter is included,
+commonly as one of the first included headers. Therefore, it is defined as an
+application developer's responsibility to include F<< <windows.h> >> prior to
+F<< <openssl/crypto.h> >> where use of CRYPTO_THREAD_* types and functions is
+required.
=head1 EXAMPLES
+You can find out if OpenSSL was configured with thread support:
+
+ #include <openssl/opensslconf.h>
+ #if defined(OPENSSL_THREADS)
+ /* thread support enabled */
+ #else
+ /* no thread support */
+ #endif
+
This example safely initializes and uses a lock.
#ifdef _WIN32
@@ -144,26 +177,15 @@ no longer in use and is unloaded.
The simplest solution is to just "leak" the lock in applications and not
repeatedly load/unload shared libraries that allocate locks.
-=head1 NOTES
-
-You can find out if OpenSSL was configured with thread support:
-
- #include <openssl/opensslconf.h>
- #if defined(OPENSSL_THREADS)
- /* thread support enabled */
- #else
- /* no thread support */
- #endif
-
=head1 SEE ALSO
-L<crypto(7)>
+L<crypto(7)>, L<openssl-threads(7)>.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CRYPTO_get_ex_new_index.pod b/doc/man3/CRYPTO_get_ex_new_index.pod
index b2d33ef90d9e..d2b44fd69431 100644
--- a/doc/man3/CRYPTO_get_ex_new_index.pod
+++ b/doc/man3/CRYPTO_get_ex_new_index.pod
@@ -3,8 +3,9 @@
=head1 NAME
CRYPTO_EX_new, CRYPTO_EX_free, CRYPTO_EX_dup,
-CRYPTO_free_ex_index, CRYPTO_get_ex_new_index, CRYPTO_set_ex_data,
-CRYPTO_get_ex_data, CRYPTO_free_ex_data, CRYPTO_new_ex_data
+CRYPTO_free_ex_index, CRYPTO_get_ex_new_index,
+CRYPTO_alloc_ex_data, CRYPTO_set_ex_data, CRYPTO_get_ex_data,
+CRYPTO_free_ex_data, CRYPTO_new_ex_data
- functions supporting application-specific data
=head1 SYNOPSIS
@@ -22,13 +23,16 @@ CRYPTO_get_ex_data, CRYPTO_free_ex_data, CRYPTO_new_ex_data
typedef void CRYPTO_EX_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
int idx, long argl, void *argp);
typedef int CRYPTO_EX_dup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from,
- void *from_d, int idx, long argl, void *argp);
+ void **from_d, int idx, long argl, void *argp);
- int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
+ int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad);
+
+ int CRYPTO_alloc_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad,
+ int idx);
int CRYPTO_set_ex_data(CRYPTO_EX_DATA *r, int idx, void *arg);
- void *CRYPTO_get_ex_data(CRYPTO_EX_DATA *r, int idx);
+ void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *r, int idx);
void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *r);
@@ -40,13 +44,12 @@ Several OpenSSL structures can have application-specific data attached to them,
known as "exdata."
The specific structures are:
- APP
BIO
DH
- DRBG
DSA
EC_KEY
ENGINE
+ EVP_PKEY
RSA
SSL
SSL_CTX
@@ -57,8 +60,10 @@ The specific structures are:
X509_STORE
X509_STORE_CTX
-Each is identified by an B<CRYPTO_EX_INDEX_xxx> define in the B<crypto.h>
-header file. In addition, B<CRYPTO_EX_INDEX_APP> is reserved for
+In addition, the B<APP> name is reserved for use by application code.
+
+Each is identified by an B<CRYPTO_EX_INDEX_xxx> define in the header file
+F<< <openssl/crypto.h> >>. In addition, B<CRYPTO_EX_INDEX_APP> is reserved for
applications to use this facility for their own structures.
The API described here is used by OpenSSL to manipulate exdata for specific
@@ -114,7 +119,8 @@ new_func() is called for every defined index. There is no requirement
that the entire parent, or containing, structure has been set up.
The new_func() is typically used only to allocate memory to store the
exdata, and perhaps an "initialized" flag within that memory.
-The exdata value should be set by calling CRYPTO_set_ex_data().
+The exdata value may be allocated later on with CRYPTO_alloc_ex_data(),
+or may be set by calling CRYPTO_set_ex_data().
When a structure is free'd (such as SSL_CTX_free()) then the
free_func() is called for every defined index. Again, the state of the
@@ -133,10 +139,8 @@ dup_func() is called when a structure is being copied. This is only done
for B<SSL>, B<SSL_SESSION>, B<EC_KEY> objects and B<BIO> chains via
BIO_dup_chain(). The B<to> and B<from> parameters
are pointers to the destination and source B<CRYPTO_EX_DATA> structures,
-respectively. The B<from_d> parameter needs to be cast to a B<void **pptr>
-as the API has currently the wrong signature; that will be changed in a
-future version. The B<*pptr> is a pointer to the source exdata.
-When the dup_func() returns, the value in B<*pptr> is copied to the
+respectively. The B<*from_d> parameter is a pointer to the source exdata.
+When the dup_func() returns, the value in B<*from_d> is copied to the
destination ex_data. If the pointer contained in B<*pptr> is not modified
by the dup_func(), then both B<to> and B<from> will point to the same data.
The B<idx>, B<argl> and B<argp> parameters are as described for the other
@@ -147,19 +151,28 @@ will fail.
CRYPTO_get_ex_new_index() returns a new index or -1 on failure.
-CRYPTO_free_ex_index() and
-CRYPTO_set_ex_data() return 1 on success or 0 on failure.
+CRYPTO_free_ex_index(), CRYPTO_alloc_ex_data() and CRYPTO_set_ex_data()
+return 1 on success or 0 on failure.
CRYPTO_get_ex_data() returns the application data or NULL on failure;
note that NULL may be a valid value.
dup_func() should return 0 for failure and 1 for success.
+=head1 HISTORY
+
+CRYPTO_alloc_ex_data() was added in OpenSSL 3.0.
+
+The signature of the dup_func() callback was changed in OpenSSL 3.0 to use the
+type B<void **> for B<from_d>. Previously this parameter was of type B<void *>.
+
+Support for ENGINE "exdata" was deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CRYPTO_memcmp.pod b/doc/man3/CRYPTO_memcmp.pod
index 20578c557b9e..a65a41fdcf06 100644
--- a/doc/man3/CRYPTO_memcmp.pod
+++ b/doc/man3/CRYPTO_memcmp.pod
@@ -29,7 +29,7 @@ as the return value when they differ is undefined, other than being nonzero.
=head1 COPYRIGHT
-Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
diff --git a/doc/man3/CTLOG_STORE_get0_log_by_id.pod b/doc/man3/CTLOG_STORE_get0_log_by_id.pod
index 86696a559462..813b9d978829 100644
--- a/doc/man3/CTLOG_STORE_get0_log_by_id.pod
+++ b/doc/man3/CTLOG_STORE_get0_log_by_id.pod
@@ -41,7 +41,7 @@ The CTLOG_STORE_get0_log_by_id() function was added in OpenSSL 1.1.0.
Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CTLOG_STORE_new.pod b/doc/man3/CTLOG_STORE_new.pod
index 9816e328e3d8..801b1447e155 100644
--- a/doc/man3/CTLOG_STORE_new.pod
+++ b/doc/man3/CTLOG_STORE_new.pod
@@ -2,6 +2,7 @@
=head1 NAME
+CTLOG_STORE_new_ex,
CTLOG_STORE_new, CTLOG_STORE_free,
CTLOG_STORE_load_default_file, CTLOG_STORE_load_file -
Create and populate a Certificate Transparency log list
@@ -10,6 +11,7 @@ Create and populate a Certificate Transparency log list
#include <openssl/ct.h>
+ CTLOG_STORE *CTLOG_STORE_new_ex(OSSL_LIB_CTX *libctx, const char *propq);
CTLOG_STORE *CTLOG_STORE_new(void);
void CTLOG_STORE_free(CTLOG_STORE *store);
@@ -22,13 +24,19 @@ A CTLOG_STORE is a container for a list of CTLOGs (Certificate Transparency
logs). The list can be loaded from one or more files and then searched by LogID
(see RFC 6962, Section 3.2, for the definition of a LogID).
-CTLOG_STORE_new() creates an empty list of CT logs. This is then populated
-by CTLOG_STORE_load_default_file() or CTLOG_STORE_load_file().
-CTLOG_STORE_load_default_file() loads from the default file, which is named
-"ct_log_list.cnf" in OPENSSLDIR (see the output of L<version>). This can be
-overridden using an environment variable named "CTLOG_FILE".
-CTLOG_STORE_load_file() loads from a caller-specified file path instead.
-Both of these functions append any loaded CT logs to the CTLOG_STORE.
+CTLOG_STORE_new_ex() creates an empty list of CT logs associated with
+the library context I<libctx> and the property query string I<propq>.
+
+CTLOG_STORE_new() does the same thing as CTLOG_STORE_new_ex() but with
+the default library context and property query string.
+
+The CTLOG_STORE is then populated by CTLOG_STORE_load_default_file() or
+CTLOG_STORE_load_file(). CTLOG_STORE_load_default_file() loads from the default
+file, which is named F<ct_log_list.cnf> in OPENSSLDIR (see the output of
+L<openssl-version(1)>). This can be overridden using an environment variable
+named B<CTLOG_FILE>. CTLOG_STORE_load_file() loads from a caller-specified file
+path instead. Both of these functions append any loaded CT logs to the
+CTLOG_STORE.
The expected format of the file is:
@@ -65,13 +73,14 @@ L<SSL_CTX_set_ctlog_list_file(3)>
=head1 HISTORY
-These functions were added in OpenSSL 1.1.0.
+CTLOG_STORE_new_ex was added in OpenSSL 3.0. All other functions were
+added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CTLOG_new.pod b/doc/man3/CTLOG_new.pod
index 5570cbcd562e..30b806824966 100644
--- a/doc/man3/CTLOG_new.pod
+++ b/doc/man3/CTLOG_new.pod
@@ -2,7 +2,8 @@
=head1 NAME
-CTLOG_new, CTLOG_new_from_base64, CTLOG_free,
+CTLOG_new_ex, CTLOG_new, CTLOG_new_from_base64,
+CTLOG_new_from_base64_ex, CTLOG_free,
CTLOG_get0_name, CTLOG_get0_log_id, CTLOG_get0_public_key -
encapsulates information about a Certificate Transparency log
@@ -10,7 +11,13 @@ encapsulates information about a Certificate Transparency log
#include <openssl/ct.h>
+ CTLOG *CTLOG_new_ex(EVP_PKEY *public_key, const char *name,
+ OSSL_LIB_CTX *libctx, const char *propq);
CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name);
+
+ int CTLOG_new_from_base64_ex(CTLOG **ct_log, const char *pkey_base64,
+ const char *name, OSSL_LIB_CTX *libctx,
+ const char *propq);
int CTLOG_new_from_base64(CTLOG ** ct_log,
const char *pkey_base64, const char *name);
void CTLOG_free(CTLOG *log);
@@ -21,14 +28,24 @@ encapsulates information about a Certificate Transparency log
=head1 DESCRIPTION
-CTLOG_new() returns a new CTLOG that represents the Certificate Transparency
-(CT) log with the given public key. A name must also be provided that can be
-used to help users identify this log. Ownership of the public key is
-transferred.
+CTLOG_new_ex() returns a new CTLOG that represents the Certificate
+Transparency (CT) log with the given public key and associates it with the
+library context I<libctx> and property query string I<propq>. A name must also
+be provided that can be used to help users identify this log. Ownership of the
+public key is transferred.
+
+CTLOG_new() does the same thing as CTLOG_new_ex() but with the default
+library context and the default property query string.
+
+CTLOG_new_from_base64_ex() also creates a new CTLOG, but takes the
+public key in base64-encoded DER form and sets the ct_log pointer to point to
+the new CTLOG. The base64 will be decoded and the public key parsed. The CTLOG
+will be associated with the given library context I<libctx> and property query
+string I<propq>.
-CTLOG_new_from_base64() also creates a new CTLOG, but takes the public key in
-base64-encoded DER form and sets the ct_log pointer to point to the new CTLOG.
-The base64 will be decoded and the public key parsed.
+CTLOG_new_from_base64() does the same thing as
+CTLOG_new_from_base64_ex() except that the default library context and
+property query string are used.
Regardless of whether CTLOG_new() or CTLOG_new_from_base64() is used, it is the
caller's responsibility to pass the CTLOG to CTLOG_free() once it is no longer
@@ -58,13 +75,14 @@ L<ct(7)>
=head1 HISTORY
-These functions were added in OpenSSL 1.1.0.
+The functions CTLOG_new_ex() and CTLOG_new_from_base64_ex()
+were added in OpenSSL 3.0. All other functions were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/CT_POLICY_EVAL_CTX_new.pod b/doc/man3/CT_POLICY_EVAL_CTX_new.pod
index f068fde62684..bba6778d2deb 100644
--- a/doc/man3/CT_POLICY_EVAL_CTX_new.pod
+++ b/doc/man3/CT_POLICY_EVAL_CTX_new.pod
@@ -2,6 +2,7 @@
=head1 NAME
+CT_POLICY_EVAL_CTX_new_ex,
CT_POLICY_EVAL_CTX_new, CT_POLICY_EVAL_CTX_free,
CT_POLICY_EVAL_CTX_get0_cert, CT_POLICY_EVAL_CTX_set1_cert,
CT_POLICY_EVAL_CTX_get0_issuer, CT_POLICY_EVAL_CTX_set1_issuer,
@@ -13,6 +14,8 @@ Encapsulates the data required to evaluate whether SCTs meet a Certificate Trans
#include <openssl/ct.h>
+ CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new_ex(OSSL_LIB_CTX *libctx,
+ const char *propq);
CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void);
void CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx);
X509* CT_POLICY_EVAL_CTX_get0_cert(const CT_POLICY_EVAL_CTX *ctx);
@@ -55,8 +58,15 @@ the current time
The above requirements are met using the setters described below.
-CT_POLICY_EVAL_CTX_new() creates an empty policy evaluation context. This
-should then be populated using:
+CT_POLICY_EVAL_CTX_new_ex() creates an empty policy evaluation context
+and associates it with the given library context I<libctx> and property query
+string I<propq>.
+
+CT_POLICY_EVAL_CTX_new() does the same thing as
+CT_POLICY_EVAL_CTX_new_ex() except that it uses the default library
+context and property query string.
+
+The CT_POLICY_EVAL_CTX should then be populated using:
=over 2
@@ -88,7 +98,7 @@ issued in the future. RFC6962 states that "TLS clients MUST reject SCTs whose
timestamp is in the future". By default, this will be set to 5 minutes in the
future (e.g. (time() + 300) * 1000), to allow for clock drift.
-The time should be in milliseconds since the Unix epoch.
+The time should be in milliseconds since the Unix Epoch.
=back
@@ -106,7 +116,8 @@ found in the TLS SCT extension or OCSP response.
=head1 RETURN VALUES
-CT_POLICY_EVAL_CTX_new() will return NULL if malloc fails.
+CT_POLICY_EVAL_CTX_new_ex() and CT_POLICY_EVAL_CTX_new() will return
+NULL if malloc fails.
=head1 SEE ALSO
@@ -114,13 +125,14 @@ L<ct(7)>
=head1 HISTORY
-These functions were added in OpenSSL 1.1.0.
+CT_POLICY_EVAL_CTX_new_ex was added in OpenSSL 3.0. All other
+functions were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DEFINE_STACK_OF.pod b/doc/man3/DEFINE_STACK_OF.pod
index 6f4ac7ec0ef0..0775214fb5d7 100644
--- a/doc/man3/DEFINE_STACK_OF.pod
+++ b/doc/man3/DEFINE_STACK_OF.pod
@@ -8,13 +8,21 @@ sk_TYPE_num, sk_TYPE_value, sk_TYPE_new, sk_TYPE_new_null,
sk_TYPE_reserve, sk_TYPE_free, sk_TYPE_zero, sk_TYPE_delete,
sk_TYPE_delete_ptr, sk_TYPE_push, sk_TYPE_unshift, sk_TYPE_pop,
sk_TYPE_shift, sk_TYPE_pop_free, sk_TYPE_insert, sk_TYPE_set,
-sk_TYPE_find, sk_TYPE_find_ex, sk_TYPE_sort, sk_TYPE_is_sorted,
-sk_TYPE_dup, sk_TYPE_deep_copy, sk_TYPE_set_cmp_func, sk_TYPE_new_reserve
+sk_TYPE_find, sk_TYPE_find_ex, sk_TYPE_find_all, sk_TYPE_sort,
+sk_TYPE_is_sorted, sk_TYPE_dup, sk_TYPE_deep_copy, sk_TYPE_set_cmp_func,
+sk_TYPE_new_reserve,
+OPENSSL_sk_deep_copy, OPENSSL_sk_delete, OPENSSL_sk_delete_ptr,
+OPENSSL_sk_dup, OPENSSL_sk_find, OPENSSL_sk_find_ex, OPENSSL_sk_find_all,
+OPENSSL_sk_free, OPENSSL_sk_insert, OPENSSL_sk_is_sorted, OPENSSL_sk_new,
+OPENSSL_sk_new_null, OPENSSL_sk_new_reserve, OPENSSL_sk_num, OPENSSL_sk_pop,
+OPENSSL_sk_pop_free, OPENSSL_sk_push, OPENSSL_sk_reserve, OPENSSL_sk_set,
+OPENSSL_sk_set_cmp_func, OPENSSL_sk_shift, OPENSSL_sk_sort,
+OPENSSL_sk_unshift, OPENSSL_sk_value, OPENSSL_sk_zero
- stack container
=head1 SYNOPSIS
-=for comment generic
+=for openssl generic
#include <openssl/safestack.h>
@@ -46,6 +54,7 @@ sk_TYPE_dup, sk_TYPE_deep_copy, sk_TYPE_set_cmp_func, sk_TYPE_new_reserve
TYPE *sk_TYPE_set(STACK_OF(TYPE) *sk, int idx, const TYPE *ptr);
int sk_TYPE_find(STACK_OF(TYPE) *sk, TYPE *ptr);
int sk_TYPE_find_ex(STACK_OF(TYPE) *sk, TYPE *ptr);
+ int sk_TYPE_find_all(STACK_OF(TYPE) *sk, TYPE *ptr, int *pnum);
void sk_TYPE_sort(const STACK_OF(TYPE) *sk);
int sk_TYPE_is_sorted(const STACK_OF(TYPE) *sk);
STACK_OF(TYPE) *sk_TYPE_dup(const STACK_OF(TYPE) *sk);
@@ -61,210 +70,236 @@ sk_TYPE_dup, sk_TYPE_deep_copy, sk_TYPE_set_cmp_func, sk_TYPE_new_reserve
Applications can create and use their own stacks by placing any of the macros
described below in a header file. These macros define typesafe inline
functions that wrap around the utility B<OPENSSL_sk_> API.
-In the description here, I<TYPE> is used
-as a placeholder for any of the OpenSSL datatypes, such as I<X509>.
-
-STACK_OF() returns the name for a stack of the specified B<TYPE>.
-DEFINE_STACK_OF() creates set of functions for a stack of B<TYPE>. This
-will mean that type B<TYPE> is stored in each stack, the type is referenced by
-STACK_OF(TYPE) and each function name begins with I<sk_TYPE_>. For example:
-
- TYPE *sk_TYPE_value(STACK_OF(TYPE) *sk, int idx);
-
+In the description here, B<I<TYPE>> is used
+as a placeholder for any of the OpenSSL datatypes, such as B<X509>.
+
+The STACK_OF() macro returns the name for a stack of the specified B<I<TYPE>>.
+This is an opaque pointer to a structure declaration.
+This can be used in every header file that references the stack.
+There are several B<DEFINE...> macros that create static inline functions
+for all of the functions described on this page.
+This should normally be used in one source file, and the stack manipulation
+is wrapped with application-specific functions.
+
+DEFINE_STACK_OF() creates set of functions for a stack of B<I<TYPE>> elements.
+The type is referenced by
+B<STACK_OF>(B<I<TYPE>>) and each function name begins with B<sk_I<TYPE>_>.
DEFINE_STACK_OF_CONST() is identical to DEFINE_STACK_OF() except
-each element is constant. For example:
+each element is constant.
+ /* DEFINE_STACK_OF(TYPE) */
+ TYPE *sk_TYPE_value(STACK_OF(TYPE) *sk, int idx);
+ /* DEFINE_STACK_OF_CONST(TYPE) */
const TYPE *sk_TYPE_value(STACK_OF(TYPE) *sk, int idx);
-DEFINE_SPECIAL_STACK_OF() defines a stack of B<TYPE> but
-each function uses B<FUNCNAME> in the function name. For example:
+DEFINE_SPECIAL_STACK_OF() and DEFINE_SPECIAL_STACK_OF_CONST() are similar
+except B<FUNCNAME> is used in the function names:
+ /* DEFINE_SPECIAL_STACK_OF(TYPE, FUNCNAME) */
TYPE *sk_FUNCNAME_value(STACK_OF(TYPE) *sk, int idx);
-
-DEFINE_SPECIAL_STACK_OF_CONST() is similar except that each element is
-constant:
-
+ /* DEFINE_SPECIAL_STACK_OF(TYPE, FUNCNAME) */
const TYPE *sk_FUNCNAME_value(STACK_OF(TYPE) *sk, int idx);
-sk_TYPE_num() returns the number of elements in B<sk> or -1 if B<sk> is
-B<NULL>.
+B<sk_I<TYPE>_num>() returns the number of elements in I<sk> or -1 if I<sk> is
+NULL.
-sk_TYPE_value() returns element B<idx> in B<sk>, where B<idx> starts at
-zero. If B<idx> is out of range then B<NULL> is returned.
+B<sk_I<TYPE>_value>() returns element I<idx> in I<sk>, where I<idx> starts at
+zero. If I<idx> is out of range then NULL is returned.
-sk_TYPE_new() allocates a new empty stack using comparison function B<compare>.
-If B<compare> is B<NULL> then no comparison function is used. This function is
-equivalent to sk_TYPE_new_reserve(compare, 0).
+B<sk_I<TYPE>_new>() allocates a new empty stack using comparison function
+I<compare>. If I<compare> is NULL then no comparison function is used. This
+function is equivalent to B<sk_I<TYPE>_new_reserve>(I<compare>, 0).
-sk_TYPE_new_null() allocates a new empty stack with no comparison function. This
-function is equivalent to sk_TYPE_new_reserve(NULL, 0).
+B<sk_I<TYPE>_new_null>() allocates a new empty stack with no comparison
+function. This function is equivalent to B<sk_I<TYPE>_new_reserve>(NULL, 0).
-sk_TYPE_reserve() allocates additional memory in the B<sk> structure
-such that the next B<n> calls to sk_TYPE_insert(), sk_TYPE_push()
-or sk_TYPE_unshift() will not fail or cause memory to be allocated
-or reallocated. If B<n> is zero, any excess space allocated in the
-B<sk> structure is freed. On error B<sk> is unchanged.
+B<sk_I<TYPE>_reserve>() allocates additional memory in the I<sk> structure
+such that the next I<n> calls to B<sk_I<TYPE>_insert>(), B<sk_I<TYPE>_push>()
+or B<sk_I<TYPE>_unshift>() will not fail or cause memory to be allocated
+or reallocated. If I<n> is zero, any excess space allocated in the
+I<sk> structure is freed. On error I<sk> is unchanged.
-sk_TYPE_new_reserve() allocates a new stack. The new stack will have additional
-memory allocated to hold B<n> elements if B<n> is positive. The next B<n> calls
-to sk_TYPE_insert(), sk_TYPE_push() or sk_TYPE_unshift() will not fail or cause
-memory to be allocated or reallocated. If B<n> is zero or less than zero, no
-memory is allocated. sk_TYPE_new_reserve() also sets the comparison function
-B<compare> to the newly created stack. If B<compare> is B<NULL> then no
-comparison function is used.
+B<sk_I<TYPE>_new_reserve>() allocates a new stack. The new stack will have
+additional memory allocated to hold I<n> elements if I<n> is positive.
+The next I<n> calls to B<sk_I<TYPE>_insert>(), B<sk_I<TYPE>_push>() or
+B<sk_I<TYPE>_unshift>() will not fail or cause memory to be allocated or
+reallocated. If I<n> is zero or less than zero, no memory is allocated.
+B<sk_I<TYPE>_new_reserve>() also sets the comparison function I<compare>
+to the newly created stack. If I<compare> is NULL then no comparison
+function is used.
-sk_TYPE_set_cmp_func() sets the comparison function of B<sk> to B<compare>.
-The previous comparison function is returned or B<NULL> if there was
-no previous comparison function.
+B<sk_I<TYPE>_set_cmp_func>() sets the comparison function of I<sk> to
+I<compare>. The previous comparison function is returned or NULL if there
+was no previous comparison function.
-sk_TYPE_free() frees up the B<sk> structure. It does B<not> free up any
-elements of B<sk>. After this call B<sk> is no longer valid.
+B<sk_I<TYPE>_free>() frees up the I<sk> structure. It does I<not> free up any
+elements of I<sk>. After this call I<sk> is no longer valid.
-sk_TYPE_zero() sets the number of elements in B<sk> to zero. It does not free
-B<sk> so after this call B<sk> is still valid.
+B<sk_I<TYPE>_zero>() sets the number of elements in I<sk> to zero. It does not
+free I<sk> so after this call I<sk> is still valid.
-sk_TYPE_pop_free() frees up all elements of B<sk> and B<sk> itself. The
+B<sk_I<TYPE>_pop_free>() frees up all elements of I<sk> and I<sk> itself. The
free function freefunc() is called on each element to free it.
-sk_TYPE_delete() deletes element B<i> from B<sk>. It returns the deleted
-element or B<NULL> if B<i> is out of range.
+B<sk_I<TYPE>_delete>() deletes element I<i> from I<sk>. It returns the deleted
+element or NULL if I<i> is out of range.
-sk_TYPE_delete_ptr() deletes element matching B<ptr> from B<sk>. It returns
-the deleted element or B<NULL> if no element matching B<ptr> was found.
+B<sk_I<TYPE>_delete_ptr>() deletes element matching I<ptr> from I<sk>. It
+returns the deleted element or NULL if no element matching I<ptr> was found.
-sk_TYPE_insert() inserts B<ptr> into B<sk> at position B<idx>. Any existing
-elements at or after B<idx> are moved downwards. If B<idx> is out of range
-the new element is appended to B<sk>. sk_TYPE_insert() either returns the
-number of elements in B<sk> after the new element is inserted or zero if
-an error (such as memory allocation failure) occurred.
+B<sk_I<TYPE>_insert>() inserts I<ptr> into I<sk> at position I<idx>. Any
+existing elements at or after I<idx> are moved downwards. If I<idx> is out
+of range the new element is appended to I<sk>. B<sk_I<TYPE>_insert>() either
+returns the number of elements in I<sk> after the new element is inserted or
+zero if an error (such as memory allocation failure) occurred.
-sk_TYPE_push() appends B<ptr> to B<sk> it is equivalent to:
+B<sk_I<TYPE>_push>() appends I<ptr> to I<sk> it is equivalent to:
sk_TYPE_insert(sk, ptr, -1);
-sk_TYPE_unshift() inserts B<ptr> at the start of B<sk> it is equivalent to:
+B<sk_I<TYPE>_unshift>() inserts I<ptr> at the start of I<sk> it is equivalent
+to:
sk_TYPE_insert(sk, ptr, 0);
-sk_TYPE_pop() returns and removes the last element from B<sk>.
+B<sk_I<TYPE>_pop>() returns and removes the last element from I<sk>.
-sk_TYPE_shift() returns and removes the first element from B<sk>.
+B<sk_I<TYPE>_shift>() returns and removes the first element from I<sk>.
-sk_TYPE_set() sets element B<idx> of B<sk> to B<ptr> replacing the current
-element. The new element value is returned or B<NULL> if an error occurred:
-this will only happen if B<sk> is B<NULL> or B<idx> is out of range.
+B<sk_I<TYPE>_set>() sets element I<idx> of I<sk> to I<ptr> replacing the current
+element. The new element value is returned or NULL if an error occurred:
+this will only happen if I<sk> is NULL or I<idx> is out of range.
-sk_TYPE_find() searches B<sk> for the element B<ptr>. In the case
+B<sk_I<TYPE>_find>() searches I<sk> for the element I<ptr>. In the case
where no comparison function has been specified, the function performs
-a linear search for a pointer equal to B<ptr>. The index of the first
+a linear search for a pointer equal to I<ptr>. The index of the first
matching element is returned or B<-1> if there is no match. In the case
-where a comparison function has been specified, B<sk> is sorted then
-sk_TYPE_find() returns the index of a matching element or B<-1> if there
-is no match. Note that, in this case, the matching element returned is
-not guaranteed to be the first; the comparison function will usually
+where a comparison function has been specified, I<sk> is sorted and
+B<sk_I<TYPE>_find>() returns the index of a matching element or B<-1> if there
+is no match. Note that, in this case the comparison function will usually
compare the values pointed to rather than the pointers themselves and
-the order of elements in B<sk> could change.
+the order of elements in I<sk> can change. Note that because the stack may be
+sorted as the result of a B<sk_I<TYPE>_find>() call, if a lock is being used to
+synchronise access to the stack across multiple threads, then that lock must be
+a "write" lock.
-sk_TYPE_find_ex() operates like sk_TYPE_find() except when a comparison
-function has been specified and no matching element is found. Instead
-of returning B<-1>, sk_TYPE_find_ex() returns the index of the element
-either before or after the location where B<ptr> would be if it were
-present in B<sk>.
+B<sk_I<TYPE>_find_ex>() operates like B<sk_I<TYPE>_find>() except when a
+comparison function has been specified and no matching element is found.
+Instead of returning B<-1>, B<sk_I<TYPE>_find_ex>() returns the index of the
+element either before or after the location where I<ptr> would be if it were
+present in I<sk>. The function also does not guarantee that the first matching
+element in the sorted stack is returned.
-sk_TYPE_sort() sorts B<sk> using the supplied comparison function.
+B<sk_I<TYPE>_find_all>() operates like B<sk_I<TYPE>_find>() but it also
+sets the I<*pnum> to number of matching elements in the stack. In case
+no comparison function has been specified the I<*pnum> will be always set
+to 1 if matching element was found, 0 otherwise.
-sk_TYPE_is_sorted() returns B<1> if B<sk> is sorted and B<0> otherwise.
+B<sk_I<TYPE>_sort>() sorts I<sk> using the supplied comparison function.
-sk_TYPE_dup() returns a copy of B<sk>. Note the pointers in the copy
-are identical to the original.
+B<sk_I<TYPE>_is_sorted>() returns B<1> if I<sk> is sorted and B<0> otherwise.
-sk_TYPE_deep_copy() returns a new stack where each element has been copied.
-Copying is performed by the supplied copyfunc() and freeing by freefunc(). The
-function freefunc() is only called if an error occurs.
+B<sk_I<TYPE>_dup>() returns a shallow copy of I<sk>
+or an empty stack if the passed stack is NULL.
+Note the pointers in the copy are identical to the original.
+
+B<sk_I<TYPE>_deep_copy>() returns a new stack where each element has been
+copied or an empty stack if the passed stack is NULL.
+Copying is performed by the supplied copyfunc() and freeing by freefunc().
+The function freefunc() is only called if an error occurs.
=head1 NOTES
Care should be taken when accessing stacks in multi-threaded environments.
-Any operation which increases the size of a stack such as sk_TYPE_insert() or
-sk_push() can "grow" the size of an internal array and cause race conditions
-if the same stack is accessed in a different thread. Operations such as
-sk_find() and sk_sort() can also reorder the stack.
+Any operation which increases the size of a stack such as B<sk_I<TYPE>_insert>()
+or B<sk_I<TYPE>_push>() can "grow" the size of an internal array and cause race
+conditions if the same stack is accessed in a different thread. Operations such
+as B<sk_I<TYPE>_find>() and B<sk_I<TYPE>_sort>() can also reorder the stack.
Any comparison function supplied should use a metric suitable
for use in a binary search operation. That is it should return zero, a
-positive or negative value if B<a> is equal to, greater than
-or less than B<b> respectively.
+positive or negative value if I<a> is equal to, greater than
+or less than I<b> respectively.
Care should be taken when checking the return values of the functions
-sk_TYPE_find() and sk_TYPE_find_ex(). They return an index to the
+B<sk_I<TYPE>_find>() and B<sk_I<TYPE>_find_ex>(). They return an index to the
matching element. In particular B<0> indicates a matching first element.
A failed search is indicated by a B<-1> return value.
STACK_OF(), DEFINE_STACK_OF(), DEFINE_STACK_OF_CONST(), and
DEFINE_SPECIAL_STACK_OF() are implemented as macros.
+It is not an error to call B<sk_I<TYPE>_num>(), B<sk_I<TYPE>_value>(),
+B<sk_I<TYPE>_free>(), B<sk_I<TYPE>_zero>(), B<sk_I<TYPE>_pop_free>(),
+B<sk_I<TYPE>_delete>(), B<sk_I<TYPE>_delete_ptr>(), B<sk_I<TYPE>_pop>(),
+B<sk_I<TYPE>_shift>(), B<sk_I<TYPE>_find>(), B<sk_I<TYPE>_find_ex>(),
+and B<sk_I<TYPE>_find_all>() on a NULL stack, empty stack, or with
+an invalid index. An error is not raised in these conditions.
+
The underlying utility B<OPENSSL_sk_> API should not be used directly.
It defines these functions: OPENSSL_sk_deep_copy(),
OPENSSL_sk_delete(), OPENSSL_sk_delete_ptr(), OPENSSL_sk_dup(),
-OPENSSL_sk_find(), OPENSSL_sk_find_ex(), OPENSSL_sk_free(),
-OPENSSL_sk_insert(), OPENSSL_sk_is_sorted(), OPENSSL_sk_new(),
-OPENSSL_sk_new_null(), OPENSSL_sk_num(), OPENSSL_sk_pop(),
-OPENSSL_sk_pop_free(), OPENSSL_sk_push(), OPENSSL_sk_reserve(),
-OPENSSL_sk_set(), OPENSSL_sk_set_cmp_func(), OPENSSL_sk_shift(),
-OPENSSL_sk_sort(), OPENSSL_sk_unshift(), OPENSSL_sk_value(),
-OPENSSL_sk_zero().
+OPENSSL_sk_find(), OPENSSL_sk_find_ex(), OPENSSL_sk_find_all(),
+OPENSSL_sk_free(), OPENSSL_sk_insert(), OPENSSL_sk_is_sorted(),
+OPENSSL_sk_new(), OPENSSL_sk_new_null(), OPENSSL_sk_new_reserve(),
+OPENSSL_sk_num(), OPENSSL_sk_pop(), OPENSSL_sk_pop_free(), OPENSSL_sk_push(),
+OPENSSL_sk_reserve(), OPENSSL_sk_set(), OPENSSL_sk_set_cmp_func(),
+OPENSSL_sk_shift(), OPENSSL_sk_sort(), OPENSSL_sk_unshift(),
+OPENSSL_sk_value(), OPENSSL_sk_zero().
=head1 RETURN VALUES
-sk_TYPE_num() returns the number of elements in the stack or B<-1> if the
-passed stack is B<NULL>.
+B<sk_I<TYPE>_num>() returns the number of elements in the stack or B<-1> if the
+passed stack is NULL.
-sk_TYPE_value() returns a pointer to a stack element or B<NULL> if the
+B<sk_I<TYPE>_value>() returns a pointer to a stack element or NULL if the
index is out of range.
-sk_TYPE_new(), sk_TYPE_new_null() and sk_TYPE_new_reserve() return an empty
-stack or B<NULL> if an error occurs.
+B<sk_I<TYPE>_new>(), B<sk_I<TYPE>_new_null>() and B<sk_I<TYPE>_new_reserve>()
+return an empty stack or NULL if an error occurs.
-sk_TYPE_reserve() returns B<1> on successful allocation of the required memory
-or B<0> on error.
+B<sk_I<TYPE>_reserve>() returns B<1> on successful allocation of the required
+memory or B<0> on error.
-sk_TYPE_set_cmp_func() returns the old comparison function or B<NULL> if
+B<sk_I<TYPE>_set_cmp_func>() returns the old comparison function or NULL if
there was no old comparison function.
-sk_TYPE_free(), sk_TYPE_zero(), sk_TYPE_pop_free() and sk_TYPE_sort() do
-not return values.
+B<sk_I<TYPE>_free>(), B<sk_I<TYPE>_zero>(), B<sk_I<TYPE>_pop_free>() and
+B<sk_I<TYPE>_sort>() do not return values.
-sk_TYPE_pop(), sk_TYPE_shift(), sk_TYPE_delete() and sk_TYPE_delete_ptr()
-return a pointer to the deleted element or B<NULL> on error.
+B<sk_I<TYPE>_pop>(), B<sk_I<TYPE>_shift>(), B<sk_I<TYPE>_delete>() and
+B<sk_I<TYPE>_delete_ptr>() return a pointer to the deleted element or NULL
+on error.
-sk_TYPE_insert(), sk_TYPE_push() and sk_TYPE_unshift() return the total
-number of elements in the stack and 0 if an error occurred. sk_TYPE_push()
-further returns -1 if B<sk> is B<NULL>.
+B<sk_I<TYPE>_insert>(), B<sk_I<TYPE>_push>() and B<sk_I<TYPE>_unshift>() return
+the total number of elements in the stack and 0 if an error occurred.
+B<sk_I<TYPE>_push>() further returns -1 if I<sk> is NULL.
-sk_TYPE_set() returns a pointer to the replacement element or B<NULL> on
+B<sk_I<TYPE>_set>() returns a pointer to the replacement element or NULL on
error.
-sk_TYPE_find() and sk_TYPE_find_ex() return an index to the found element
-or B<-1> on error.
+B<sk_I<TYPE>_find>() and B<sk_I<TYPE>_find_ex>() return an index to the found
+element or B<-1> on error.
-sk_TYPE_is_sorted() returns B<1> if the stack is sorted and B<0> if it is
+B<sk_I<TYPE>_is_sorted>() returns B<1> if the stack is sorted and B<0> if it is
not.
-sk_TYPE_dup() and sk_TYPE_deep_copy() return a pointer to the copy of the
-stack.
+B<sk_I<TYPE>_dup>() and B<sk_I<TYPE>_deep_copy>() return a pointer to the copy
+of the stack or NULL on error.
=head1 HISTORY
Before OpenSSL 1.1.0, this was implemented via macros and not inline functions
and was not a public API.
-sk_TYPE_reserve() and sk_TYPE_new_reserve() were added in OpenSSL 1.1.1.
+B<sk_I<TYPE>_reserve>() and B<sk_I<TYPE>_new_reserve>() were added in OpenSSL
+1.1.1.
=head1 COPYRIGHT
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DES_random_key.pod b/doc/man3/DES_random_key.pod
index a52099053ec8..ff16961ea92a 100644
--- a/doc/man3/DES_random_key.pod
+++ b/doc/man3/DES_random_key.pod
@@ -16,6 +16,10 @@ DES_fcrypt, DES_crypt - DES encryption
#include <openssl/des.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
void DES_random_key(DES_cblock *ret);
int DES_set_key(const_DES_cblock *key, DES_key_schedule *schedule);
@@ -94,6 +98,10 @@ DES_fcrypt, DES_crypt - DES encryption
=head1 DESCRIPTION
+All of the functions described on this page are deprecated. Applications should
+instead use L<EVP_EncryptInit_ex(3)>, L<EVP_EncryptUpdate(3)> and
+L<EVP_EncryptFinal_ex(3)> or the equivalently named decrypt functions.
+
This library contains a fast implementation of the DES encryption
algorithm.
@@ -119,11 +127,8 @@ and is not a weak or semi-weak key. If the parity is wrong, then -1
is returned. If the key is a weak key, then -2 is returned. If an
error is returned, the key schedule is not generated.
-DES_set_key() works like
-DES_set_key_checked() if the I<DES_check_key> flag is nonzero,
-otherwise like DES_set_key_unchecked(). These functions are available
-for compatibility; it is recommended to use a function that does not
-depend on a global variable.
+DES_set_key() works like DES_set_key_checked() and remains for
+backward compatibility.
DES_set_odd_parity() sets the parity of the passed I<key> to odd.
@@ -289,9 +294,12 @@ not suitable for most applications; see L<des_modes(7)>.
=head1 RETURN VALUES
-DES_set_key(), DES_key_sched(), DES_set_key_checked() and DES_is_weak_key()
+DES_set_key(), DES_key_sched(), and DES_set_key_checked()
return 0 on success or negative values on error.
+DES_is_weak_key() returns 1 if the passed key is a weak key, 0 if it
+is ok.
+
DES_cbc_cksum() and DES_quad_cksum() return 4-byte integer representing the
last 4 bytes of the checksum of the input.
@@ -305,6 +313,8 @@ L<EVP_EncryptInit(3)>
=head1 HISTORY
+All of these functions were deprecated in OpenSSL 3.0.
+
The requirement that the B<salt> parameter to DES_crypt() and DES_fcrypt()
be two ASCII characters was first enforced in
OpenSSL 1.1.0. Previous versions tried to use the letter uppercase B<A>
@@ -313,9 +323,9 @@ on some platforms.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DH_generate_key.pod b/doc/man3/DH_generate_key.pod
index 72726661a1d7..2b14f2ad2762 100644
--- a/doc/man3/DH_generate_key.pod
+++ b/doc/man3/DH_generate_key.pod
@@ -9,6 +9,10 @@ Diffie-Hellman key exchange
#include <openssl/dh.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int DH_generate_key(DH *dh);
int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh);
@@ -17,6 +21,10 @@ Diffie-Hellman key exchange
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_derive_init(3)>
+and L<EVP_PKEY_derive(3)>.
+
DH_generate_key() performs the first step of a Diffie-Hellman key
exchange by generating private and public DH values. By calling
DH_compute_key() or DH_compute_key_padded(), these are combined with
@@ -53,17 +61,20 @@ The error codes can be obtained by L<ERR_get_error(3)>.
=head1 SEE ALSO
+L<EVP_PKEY_derive(3)>,
L<DH_new(3)>, L<ERR_get_error(3)>, L<RAND_bytes(3)>, L<DH_size(3)>
=head1 HISTORY
DH_compute_key_padded() was added in OpenSSL 1.0.2.
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DH_generate_parameters.pod b/doc/man3/DH_generate_parameters.pod
index 3c847104327a..1098a161ea63 100644
--- a/doc/man3/DH_generate_parameters.pod
+++ b/doc/man3/DH_generate_parameters.pod
@@ -12,6 +12,10 @@ parameters
#include <openssl/dh.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int DH_generate_parameters_ex(DH *dh, int prime_len, int generator, BN_GENCB *cb);
int DH_check(DH *dh, int *codes);
@@ -21,15 +25,20 @@ parameters
int DH_check_params_ex(const DH *dh);
int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key);
-Deprecated:
+The following functions have been deprecated since OpenSSL 0.9.8, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
- #if OPENSSL_API_COMPAT < 0x00908000L
DH *DH_generate_parameters(int prime_len, int generator,
void (*callback)(int, int, void *), void *cb_arg);
- #endif
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_check(3)>,
+L<EVP_PKEY_public_check(3)>, L<EVP_PKEY_private_check(3)> and
+L<EVP_PKEY_param_check(3)>.
+
DH_generate_parameters_ex() generates Diffie-Hellman parameters that can
be shared among a group of users, and stores them in the provided B<DH>
structure. The pseudo-random number generator must be
@@ -73,6 +82,14 @@ The generator B<g> is not suitable.
Note that the lack of this bit doesn't guarantee that B<g> is
suitable, unless B<p> is known to be a strong prime.
+=item DH_MODULUS_TOO_SMALL
+
+The modulus is too small.
+
+=item DH_MODULUS_TOO_LARGE
+
+The modulus is too large.
+
=back
DH_check() confirms that the Diffie-Hellman parameters B<dh> are valid. The
@@ -136,14 +153,16 @@ L<DH_free(3)>
=head1 HISTORY
+All of these functions were deprecated in OpenSSL 3.0.
+
DH_generate_parameters() was deprecated in OpenSSL 0.9.8; use
DH_generate_parameters_ex() instead.
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DH_get0_pqg.pod b/doc/man3/DH_get0_pqg.pod
index 6b5e843e4832..2afc35c77f86 100644
--- a/doc/man3/DH_get0_pqg.pod
+++ b/doc/man3/DH_get0_pqg.pod
@@ -12,6 +12,10 @@ DH_get_length, DH_set_length - Routines for getting and setting data in a DH obj
#include <openssl/dh.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
void DH_get0_pqg(const DH *dh,
const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
@@ -26,37 +30,48 @@ DH_get_length, DH_set_length - Routines for getting and setting data in a DH obj
void DH_clear_flags(DH *dh, int flags);
int DH_test_flags(const DH *dh, int flags);
void DH_set_flags(DH *dh, int flags);
- ENGINE *DH_get0_engine(DH *d);
+
long DH_get_length(const DH *dh);
int DH_set_length(DH *dh, long length);
+ ENGINE *DH_get0_engine(DH *d);
+
=head1 DESCRIPTION
-A DH object contains the parameters B<p>, B<q> and B<g>. Note that the B<q>
-parameter is optional. It also contains a public key (B<pub_key>) and
-(optionally) a private key (B<priv_key>).
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_get_bn_param(3)> for any methods that
+return a B<BIGNUM>. Refer to L<EVP_PKEY-DH(7)> for more infomation.
+
+A DH object contains the parameters I<p>, I<q> and I<g>. Note that the I<q>
+parameter is optional. It also contains a public key (I<pub_key>) and
+(optionally) a private key (I<priv_key>).
-The B<p>, B<q> and B<g> parameters can be obtained by calling DH_get0_pqg().
-If the parameters have not yet been set then B<*p>, B<*q> and B<*g> will be set
+The I<p>, I<q> and I<g> parameters can be obtained by calling DH_get0_pqg().
+If the parameters have not yet been set then I<*p>, I<*q> and I<*g> will be set
to NULL. Otherwise they are set to pointers to their respective values. These
point directly to the internal representations of the values and therefore
should not be freed directly.
-Any of the out parameters B<p>, B<q>, and B<g> can be NULL, in which case no
+Any of the out parameters I<p>, I<q>, and I<g> can be NULL, in which case no
value will be returned for that parameter.
-The B<p>, B<q> and B<g> values can be set by calling DH_set0_pqg() and passing
-the new values for B<p>, B<q> and B<g> as parameters to the function. Calling
+The I<p>, I<q> and I<g> values can be set by calling DH_set0_pqg() and passing
+the new values for I<p>, I<q> and I<g> as parameters to the function. Calling
this function transfers the memory management of the values to the DH object,
and therefore the values that have been passed in should not be freed directly
-after this function has been called. The B<q> parameter may be NULL.
+after this function has been called. The I<q> parameter may be NULL.
+DH_set0_pqg() also checks if the parameters associated with I<p> and I<g> and
+optionally I<q> are associated with known safe prime groups. If it is a safe
+prime group then the value of I<q> will be set to q = (p - 1) / 2 if I<q> is
+NULL. The optional length parameter will be set to BN_num_bits(I<q>) if I<q>
+is not NULL.
To get the public and private key values use the DH_get0_key() function. A
-pointer to the public key will be stored in B<*pub_key>, and a pointer to the
-private key will be stored in B<*priv_key>. Either may be NULL if they have not
+pointer to the public key will be stored in I<*pub_key>, and a pointer to the
+private key will be stored in I<*priv_key>. Either may be NULL if they have not
been set yet, although if the private key has been set then the public key must
be. The values point to the internal representation of the public key and
private key values. This memory should not be freed directly.
-Any of the out parameters B<pub_key> and B<priv_key> can be NULL, in which case
+Any of the out parameters I<pub_key> and I<priv_key> can be NULL, in which case
no value will be returned for that parameter.
The public and private key values can be set using DH_set0_key(). Either
@@ -65,25 +80,31 @@ untouched. As with DH_set0_pqg() this function transfers the memory management
of the key values to the DH object, and therefore they should not be freed
directly after this function has been called.
-Any of the values B<p>, B<q>, B<g>, B<priv_key>, and B<pub_key> can also be
+Any of the values I<p>, I<q>, I<g>, I<priv_key>, and I<pub_key> can also be
retrieved separately by the corresponding function DH_get0_p(), DH_get0_q(),
DH_get0_g(), DH_get0_priv_key(), and DH_get0_pub_key(), respectively.
-DH_set_flags() sets the flags in the B<flags> parameter on the DH object.
+DH_set_flags() sets the flags in the I<flags> parameter on the DH object.
Multiple flags can be passed in one go (bitwise ORed together). Any flags that
are already set are left set. DH_test_flags() tests to see whether the flags
-passed in the B<flags> parameter are currently set in the DH object. Multiple
+passed in the I<flags> parameter are currently set in the DH object. Multiple
flags can be tested in one go. All flags that are currently set are returned, or
zero if none of the flags are set. DH_clear_flags() clears the specified flags
within the DH object.
DH_get0_engine() returns a handle to the ENGINE that has been set for this DH
-object, or NULL if no such ENGINE has been set.
+object, or NULL if no such ENGINE has been set. This function is deprecated. All
+engines should be replaced by providers.
The DH_get_length() and DH_set_length() functions get and set the optional
length parameter associated with this DH object. If the length is nonzero then
-it is used, otherwise it is ignored. The B<length> parameter indicates the
-length of the secret exponent (private key) in bits.
+it is used, otherwise it is ignored. The I<length> parameter indicates the
+length of the secret exponent (private key) in bits. For safe prime groups the optional length parameter I<length> can be
+set to a value greater or equal to 2 * maximum_target_security_strength(BN_num_bits(I<p>))
+as listed in SP800-56Ar3 Table(s) 25 & 26.
+These functions are deprecated and should be replaced with
+EVP_PKEY_CTX_set_params() and EVP_PKEY_get_int_param() using the parameter key
+B<OSSL_PKEY_PARAM_DH_PRIV_LEN> as described in L<EVP_PKEY-DH(7)>.
=head1 NOTES
@@ -116,11 +137,13 @@ L<DH_set_method(3)>, L<DH_size(3)>, L<DH_meth_new(3)>
The functions described here were added in OpenSSL 1.1.0.
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DH_get_1024_160.pod b/doc/man3/DH_get_1024_160.pod
index 4044f1041857..af2fc8c205c6 100644
--- a/doc/man3/DH_get_1024_160.pod
+++ b/doc/man3/DH_get_1024_160.pod
@@ -23,29 +23,41 @@ BN_get_rfc3526_prime_8192
=head1 SYNOPSIS
#include <openssl/dh.h>
- DH *DH_get_1024_160(void)
- DH *DH_get_2048_224(void)
- DH *DH_get_2048_256(void)
-
- const BIGNUM *BN_get0_nist_prime_192(void)
- const BIGNUM *BN_get0_nist_prime_224(void)
- const BIGNUM *BN_get0_nist_prime_256(void)
- const BIGNUM *BN_get0_nist_prime_384(void)
- const BIGNUM *BN_get0_nist_prime_521(void)
-
- BIGNUM *BN_get_rfc2409_prime_768(BIGNUM *bn)
- BIGNUM *BN_get_rfc2409_prime_1024(BIGNUM *bn)
- BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *bn)
- BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *bn)
- BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *bn)
- BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *bn)
- BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *bn)
- BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *bn)
+
+ const BIGNUM *BN_get0_nist_prime_192(void);
+ const BIGNUM *BN_get0_nist_prime_224(void);
+ const BIGNUM *BN_get0_nist_prime_256(void);
+ const BIGNUM *BN_get0_nist_prime_384(void);
+ const BIGNUM *BN_get0_nist_prime_521(void);
+
+ BIGNUM *BN_get_rfc2409_prime_768(BIGNUM *bn);
+ BIGNUM *BN_get_rfc2409_prime_1024(BIGNUM *bn);
+ BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *bn);
+ BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *bn);
+ BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *bn);
+ BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *bn);
+ BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *bn);
+ BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *bn);
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ #include <openssl/dh.h>
+
+ DH *DH_get_1024_160(void);
+ DH *DH_get_2048_224(void);
+ DH *DH_get_2048_256(void);
=head1 DESCRIPTION
DH_get_1024_160(), DH_get_2048_224(), and DH_get_2048_256() each return
-a DH object for the IETF RFC 5114 value.
+a DH object for the IETF RFC 5114 value. These functions are deprecated.
+Applications should instead use EVP_PKEY_CTX_set_dh_rfc5114() and
+EVP_PKEY_CTX_set_dhx_rfc5114() as described in L<EVP_PKEY_CTX_ctrl(3)> or
+by setting the B<OSSL_PKEY_PARAM_GROUP_NAME> as specified in
+L<EVP_PKEY-DH(7)/DH parameters>) to one of "dh_1024_160", "dh_2048_224" or
+"dh_2048_256".
BN_get0_nist_prime_192(), BN_get0_nist_prime_224(), BN_get0_nist_prime_256(),
BN_get0_nist_prime_384(), and BN_get0_nist_prime_521() functions return
@@ -62,11 +74,16 @@ is not NULL, the BIGNUM will be set into that location as well.
Defined above.
+=head1 HISTORY
+
+The functions DH_get_1024_160(), DH_get_2048_224() and DH_get_2048_256() were
+deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DH_meth_new.pod b/doc/man3/DH_meth_new.pod
index 63aa6513403a..43827f55ef8c 100644
--- a/doc/man3/DH_meth_new.pod
+++ b/doc/man3/DH_meth_new.pod
@@ -14,6 +14,10 @@ DH_meth_set_generate_params - Routines to build up DH methods
#include <openssl/dh.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
DH_METHOD *DH_meth_new(const char *name, int flags);
void DH_meth_free(DH_METHOD *dhm);
@@ -58,6 +62,9 @@ DH_meth_set_generate_params - Routines to build up DH methods
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use the provider APIs.
+
The B<DH_METHOD> type is a structure used for the provision of custom DH
implementations. It provides a set of functions used by OpenSSL for the
implementation of the various DH capabilities.
@@ -153,13 +160,15 @@ L<DH_set_method(3)>, L<DH_size(3)>, L<DH_get0_pqg(3)>
=head1 HISTORY
+All of these functions were deprecated in OpenSSL 3.0.
+
The functions described here were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DH_new.pod b/doc/man3/DH_new.pod
index 7e60c9a569c1..5c8bcdce5c36 100644
--- a/doc/man3/DH_new.pod
+++ b/doc/man3/DH_new.pod
@@ -8,6 +8,10 @@ DH_new, DH_free - allocate and free DH objects
#include <openssl/dh.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
DH* DH_new(void);
void DH_free(DH *dh);
@@ -32,13 +36,20 @@ DH_free() returns no value.
L<DH_new(3)>, L<ERR_get_error(3)>,
L<DH_generate_parameters(3)>,
-L<DH_generate_key(3)>
+L<DH_generate_key(3)>,
+L<EVP_PKEY-DH(7)>
+
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
+For replacement see EVP_PKEY-DH(7).
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DH_new_by_nid.pod b/doc/man3/DH_new_by_nid.pod
index 73636c5d1e9b..5703440e9201 100644
--- a/doc/man3/DH_new_by_nid.pod
+++ b/doc/man3/DH_new_by_nid.pod
@@ -2,36 +2,49 @@
=head1 NAME
-DH_new_by_nid, DH_get_nid - get or find DH named parameters
+DH_new_by_nid, DH_get_nid - create or get DH named parameters
=head1 SYNOPSIS
#include <openssl/dh.h>
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
DH *DH_new_by_nid(int nid);
- int *DH_get_nid(const DH *dh);
+
+ int DH_get_nid(const DH *dh);
=head1 DESCRIPTION
DH_new_by_nid() creates and returns a DH structure containing named parameters
B<nid>. Currently B<nid> must be B<NID_ffdhe2048>, B<NID_ffdhe3072>,
-B<NID_ffdhe4096>, B<NID_ffdhe6144> or B<NID_ffdhe8192>.
+B<NID_ffdhe4096>, B<NID_ffdhe6144>, B<NID_ffdhe8192>,
+B<NID_modp_1536>, B<NID_modp_2048>, B<NID_modp_3072>,
+B<NID_modp_4096>, B<NID_modp_6144> or B<NID_modp_8192>.
DH_get_nid() determines if the parameters contained in B<dh> match
-any named set. It returns the NID corresponding to the matching parameters or
-B<NID_undef> if there is no match.
+any named safe prime group. It returns the NID corresponding to the matching
+parameters or B<NID_undef> if there is no match.
+This function is deprecated.
=head1 RETURN VALUES
DH_new_by_nid() returns a set of DH parameters or B<NULL> if an error occurred.
-DH_get_nid() returns the NID of the matching set of parameters or
-B<NID_undef> if there is no match.
+DH_get_nid() returns the NID of the matching set of parameters for p and g
+and optionally q, otherwise it returns B<NID_undef> if there is no match.
+
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DH_set_method.pod b/doc/man3/DH_set_method.pod
index b36011d627f3..88dffab26c0c 100644
--- a/doc/man3/DH_set_method.pod
+++ b/doc/man3/DH_set_method.pod
@@ -9,6 +9,10 @@ DH_set_method, DH_new_method, DH_OpenSSL - select DH method
#include <openssl/dh.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
void DH_set_default_method(const DH_METHOD *meth);
const DH_METHOD *DH_get_default_method(void);
@@ -21,6 +25,9 @@ DH_set_method, DH_new_method, DH_OpenSSL - select DH method
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use the provider APIs.
+
A B<DH_METHOD> specifies the functions that OpenSSL uses for Diffie-Hellman
operations. By modifying the method, alternative implementations
such as hardware accelerators may be used. IMPORTANT: See the NOTES section for
@@ -76,11 +83,15 @@ returns a pointer to the newly allocated structure.
L<DH_new(3)>, L<DH_new(3)>, L<DH_meth_new(3)>
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DH_size.pod b/doc/man3/DH_size.pod
index 3cbdbc67da1c..81b73a8c6647 100644
--- a/doc/man3/DH_size.pod
+++ b/doc/man3/DH_size.pod
@@ -9,47 +9,59 @@ security bits
#include <openssl/dh.h>
- int DH_size(const DH *dh);
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
int DH_bits(const DH *dh);
+ int DH_size(const DH *dh);
+
int DH_security_bits(const DH *dh);
=head1 DESCRIPTION
-DH_size() returns the Diffie-Hellman prime size in bytes. It can be used
-to determine how much memory must be allocated for the shared secret
-computed by L<DH_compute_key(3)>.
+The functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_get_bits(3)>,
+L<EVP_PKEY_get_security_bits(3)> and L<EVP_PKEY_get_size(3)>.
DH_bits() returns the number of significant bits.
B<dh> and B<dh-E<gt>p> must not be B<NULL>.
+DH_size() returns the Diffie-Hellman prime size in bytes. It can be used
+to determine how much memory must be allocated for the shared secret
+computed by L<DH_compute_key(3)>.
+
DH_security_bits() returns the number of security bits of the given B<dh>
key. See L<BN_security_bits(3)>.
=head1 RETURN VALUES
-DH_size() returns the prime size of Diffie-Hellman in bytes.
+DH_bits() returns the number of bits in the key, or -1 if
+B<dh> doesn't hold any key parameters.
-DH_bits() returns the number of bits in the key.
+DH_size() returns the prime size of Diffie-Hellman in bytes, or -1 if
+B<dh> doesn't hold any key parameters.
-DH_security_bits() returns the number of security bits.
+DH_security_bits() returns the number of security bits, or -1 if
+B<dh> doesn't hold any key parameters.
=head1 SEE ALSO
+L<EVP_PKEY_get_bits(3)>,
L<DH_new(3)>, L<DH_generate_key(3)>,
L<BN_num_bits(3)>
=head1 HISTORY
-The DH_bits() function was added in OpenSSL 1.1.0.
+All functions were deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DSA_SIG_new.pod b/doc/man3/DSA_SIG_new.pod
index 92c7bfdf505e..1f532d300065 100644
--- a/doc/man3/DSA_SIG_new.pod
+++ b/doc/man3/DSA_SIG_new.pod
@@ -43,14 +43,14 @@ DSA_SIG_set0() returns 1 on success or 0 on failure.
=head1 SEE ALSO
-L<DSA_new(3)>, L<ERR_get_error(3)>,
-L<DSA_do_sign(3)>
+L<EVP_PKEY_new(3)>, L<EVP_PKEY_free(3)>, L<EVP_PKEY_get_bn_param(3)>,
+L<ERR_get_error(3)>
=head1 COPYRIGHT
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DSA_do_sign.pod b/doc/man3/DSA_do_sign.pod
index a0dd8bb2f60d..756843b57761 100644
--- a/doc/man3/DSA_do_sign.pod
+++ b/doc/man3/DSA_do_sign.pod
@@ -8,6 +8,10 @@ DSA_do_sign, DSA_do_verify - raw DSA signature operations
#include <openssl/dsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
DSA_SIG *DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
int DSA_do_verify(const unsigned char *dgst, int dgst_len,
@@ -15,6 +19,10 @@ DSA_do_sign, DSA_do_verify - raw DSA signature operations
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_sign_init(3)>, L<EVP_PKEY_sign(3)>,
+L<EVP_PKEY_verify_init(3)> and L<EVP_PKEY_verify(3)>.
+
DSA_do_sign() computes a digital signature on the B<len> byte message
digest B<dgst> using the private key B<dsa> and returns it in a
newly allocated B<DSA_SIG> structure.
@@ -40,11 +48,15 @@ L<DSA_new(3)>, L<ERR_get_error(3)>, L<RAND_bytes(3)>,
L<DSA_SIG_new(3)>,
L<DSA_sign(3)>
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DSA_dup_DH.pod b/doc/man3/DSA_dup_DH.pod
index 09cbf4b3a9cc..b2a1529ac867 100644
--- a/doc/man3/DSA_dup_DH.pod
+++ b/doc/man3/DSA_dup_DH.pod
@@ -8,10 +8,18 @@ DSA_dup_DH - create a DH structure out of DSA structure
#include <openssl/dsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
DH *DSA_dup_DH(const DSA *r);
=head1 DESCRIPTION
+The function described on this page is deprecated. There is no direct
+replacement, applications should use the EVP_PKEY APIs for Diffie-Hellman
+operations.
+
DSA_dup_DH() duplicates DSA parameters/keys as DH parameters/keys. q
is lost during that conversion, but the resulting DH parameters
contain its length.
@@ -29,11 +37,15 @@ Be careful to avoid small subgroup attacks when using this.
L<DH_new(3)>, L<DSA_new(3)>, L<ERR_get_error(3)>
+=head1 HISTORY
+
+This function was deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DSA_generate_key.pod b/doc/man3/DSA_generate_key.pod
index bb1bb3669095..c8f123be009c 100644
--- a/doc/man3/DSA_generate_key.pod
+++ b/doc/man3/DSA_generate_key.pod
@@ -8,10 +8,18 @@ DSA_generate_key - generate DSA key pair
#include <openssl/dsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int DSA_generate_key(DSA *a);
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_keygen_init(3)> and
+L<EVP_PKEY_keygen(3)> as described in L<EVP_PKEY-DSA(7)>.
+
DSA_generate_key() expects B<a> to contain DSA parameters. It generates
a new key pair and stores it in B<a-E<gt>pub_key> and B<a-E<gt>priv_key>.
@@ -29,11 +37,15 @@ The error codes can be obtained by L<ERR_get_error(3)>.
L<DSA_new(3)>, L<ERR_get_error(3)>, L<RAND_bytes(3)>,
L<DSA_generate_parameters_ex(3)>
+=head1 HISTORY
+
+This function was deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DSA_generate_parameters.pod b/doc/man3/DSA_generate_parameters.pod
index 970f6a6b08af..415c4c8b82ce 100644
--- a/doc/man3/DSA_generate_parameters.pod
+++ b/doc/man3/DSA_generate_parameters.pod
@@ -8,21 +8,29 @@ DSA_generate_parameters_ex, DSA_generate_parameters - generate DSA parameters
#include <openssl/dsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int DSA_generate_parameters_ex(DSA *dsa, int bits,
const unsigned char *seed, int seed_len,
int *counter_ret, unsigned long *h_ret,
BN_GENCB *cb);
-Deprecated:
+The following functions have been deprecated since OpenSSL 0.9.8, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
- #if OPENSSL_API_COMPAT < 0x00908000L
DSA *DSA_generate_parameters(int bits, unsigned char *seed, int seed_len,
int *counter_ret, unsigned long *h_ret,
void (*callback)(int, int, void *), void *cb_arg);
- #endif
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_paramgen_init(3)> and
+L<EVP_PKEY_keygen(3)> as described in L<EVP_PKEY-DSA(7)>.
+
DSA_generate_parameters_ex() generates primes p and q and a generator g
for use in the DSA and stores the result in B<dsa>.
@@ -111,14 +119,16 @@ L<DSA_free(3)>, L<BN_generate_prime(3)>
=head1 HISTORY
+DSA_generate_parameters_ex() was deprecated in OpenSSL 3.0.
+
DSA_generate_parameters() was deprecated in OpenSSL 0.9.8; use
DSA_generate_parameters_ex() instead.
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DSA_get0_pqg.pod b/doc/man3/DSA_get0_pqg.pod
index 793c9bc56357..7b2f132a99b2 100644
--- a/doc/man3/DSA_get0_pqg.pod
+++ b/doc/man3/DSA_get0_pqg.pod
@@ -13,6 +13,10 @@ setting data in a DSA object
#include <openssl/dsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
void DSA_get0_pqg(const DSA *d,
const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);
@@ -31,6 +35,9 @@ setting data in a DSA object
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_get_bn_param(3)>.
+
A DSA object contains the parameters B<p>, B<q> and B<g>. It also contains a
public key (B<pub_key>) and (optionally) a private key (B<priv_key>).
@@ -94,19 +101,21 @@ has been set.
=head1 SEE ALSO
+L<EVP_PKEY_get_bn_param(3)>,
L<DSA_new(3)>, L<DSA_new(3)>, L<DSA_generate_parameters(3)>, L<DSA_generate_key(3)>,
L<DSA_dup_DH(3)>, L<DSA_do_sign(3)>, L<DSA_set_method(3)>, L<DSA_SIG_new(3)>,
L<DSA_sign(3)>, L<DSA_size(3)>, L<DSA_meth_new(3)>
=head1 HISTORY
-The functions described here were added in OpenSSL 1.1.0.
+The functions described here were added in OpenSSL 1.1.0 and deprecated in
+OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DSA_meth_new.pod b/doc/man3/DSA_meth_new.pod
index faf86ef9dafc..c00747cfc448 100644
--- a/doc/man3/DSA_meth_new.pod
+++ b/doc/man3/DSA_meth_new.pod
@@ -16,6 +16,10 @@ DSA_meth_set_keygen - Routines to build up DSA methods
#include <openssl/dsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
DSA_METHOD *DSA_meth_new(const char *name, int flags);
void DSA_meth_free(DSA_METHOD *dsam);
@@ -86,10 +90,13 @@ DSA_meth_set_keygen - Routines to build up DSA methods
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications and extension implementations should instead use the
+OSSL_PROVIDER APIs.
+
The B<DSA_METHOD> type is a structure used for the provision of custom DSA
implementations. It provides a set of functions used by OpenSSL for the
-implementation of the various DSA capabilities. See the L<dsa> page for more
-information.
+implementation of the various DSA capabilities.
DSA_meth_new() creates a new B<DSA_METHOD> structure. It should be given a
unique B<name> and a set of B<flags>. The B<name> should be a NULL terminated
@@ -201,13 +208,15 @@ L<DSA_sign(3)>, L<DSA_size(3)>, L<DSA_get0_pqg(3)>
=head1 HISTORY
+The functions described here were deprecated in OpenSSL 3.0.
+
The functions described here were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DSA_new.pod b/doc/man3/DSA_new.pod
index 22474251f2b7..60b3d50dfa01 100644
--- a/doc/man3/DSA_new.pod
+++ b/doc/man3/DSA_new.pod
@@ -8,12 +8,19 @@ DSA_new, DSA_free - allocate and free DSA objects
#include <openssl/dsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
DSA* DSA_new(void);
void DSA_free(DSA *dsa);
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_new(3)> and L<EVP_PKEY_free(3)>.
+
DSA_new() allocates and initializes a B<DSA> structure. It is equivalent to
calling DSA_new_method(NULL).
@@ -32,15 +39,20 @@ DSA_free() returns no value.
=head1 SEE ALSO
+L<EVP_PKEY_new(3)>, L<EVP_PKEY_free(3)>,
L<DSA_new(3)>, L<ERR_get_error(3)>,
L<DSA_generate_parameters(3)>,
L<DSA_generate_key(3)>
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DSA_set_method.pod b/doc/man3/DSA_set_method.pod
index f6eb260c316c..6275859b2c54 100644
--- a/doc/man3/DSA_set_method.pod
+++ b/doc/man3/DSA_set_method.pod
@@ -9,6 +9,10 @@ DSA_set_method, DSA_new_method, DSA_OpenSSL - select DSA method
#include <openssl/dsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
void DSA_set_default_method(const DSA_METHOD *meth);
const DSA_METHOD *DSA_get_default_method(void);
@@ -17,10 +21,13 @@ DSA_set_method, DSA_new_method, DSA_OpenSSL - select DSA method
DSA *DSA_new_method(ENGINE *engine);
- DSA_METHOD *DSA_OpenSSL(void);
+ const DSA_METHOD *DSA_OpenSSL(void);
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should providers instead of method overrides.
+
A B<DSA_METHOD> specifies the functions that OpenSSL uses for DSA
operations. By modifying the method, alternative implementations
such as hardware accelerators may be used. IMPORTANT: See the NOTES section for
@@ -49,7 +56,7 @@ be released during the change. It is possible to have DSA keys that only
work with certain DSA_METHOD implementations (e.g. from an ENGINE module
that supports embedded hardware-protected keys), and in such cases
attempting to change the DSA_METHOD for the key can have unexpected
-results. See L<DSA_meth_new> for information on constructing custom DSA_METHOD
+results. See L<DSA_meth_new(3)> for information on constructing custom DSA_METHOD
objects;
DSA_new_method() allocates and initializes a DSA structure so that B<engine>
@@ -76,11 +83,15 @@ fails. Otherwise it returns a pointer to the newly allocated structure.
L<DSA_new(3)>, L<DSA_new(3)>, L<DSA_meth_new(3)>
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DSA_sign.pod b/doc/man3/DSA_sign.pod
index 0d76b8c3f928..0d20f0f6809c 100644
--- a/doc/man3/DSA_sign.pod
+++ b/doc/man3/DSA_sign.pod
@@ -8,6 +8,10 @@ DSA_sign, DSA_sign_setup, DSA_verify - DSA signatures
#include <openssl/dsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int DSA_sign(int type, const unsigned char *dgst, int len,
unsigned char *sigret, unsigned int *siglen, DSA *dsa);
@@ -18,6 +22,10 @@ DSA_sign, DSA_sign_setup, DSA_verify - DSA signatures
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_sign_init(3)>, L<EVP_PKEY_sign(3)>,
+L<EVP_PKEY_verify_init(3)> and L<EVP_PKEY_verify(3)>.
+
DSA_sign() computes a digital signature on the B<len> byte message
digest B<dgst> using the private key B<dsa> and places its ASN.1 DER
encoding at B<sigret>. The length of the signature is places in
@@ -50,7 +58,7 @@ L<ERR_get_error(3)>.
=head1 CONFORMING TO
-US Federal Information Processing Standard FIPS 186 (Digital Signature
+US Federal Information Processing Standard FIPS186-4 (Digital Signature
Standard, DSS), ANSI X9.30
=head1 SEE ALSO
@@ -59,11 +67,15 @@ L<DSA_new(3)>, L<ERR_get_error(3)>, L<RAND_bytes(3)>,
L<DSA_do_sign(3)>,
L<RAND(7)>
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DSA_size.pod b/doc/man3/DSA_size.pod
index ff7df3d296ee..57fc4a63eee9 100644
--- a/doc/man3/DSA_size.pod
+++ b/doc/man3/DSA_size.pod
@@ -8,39 +8,59 @@ DSA_size, DSA_bits, DSA_security_bits - get DSA signature size, key bits or secu
#include <openssl/dsa.h>
- int DSA_size(const DSA *dsa);
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int DSA_bits(const DSA *dsa);
+
+ int DSA_size(const DSA *dsa);
+
int DSA_security_bits(const DSA *dsa);
=head1 DESCRIPTION
-DSA_size() returns the maximum size of an ASN.1 encoded DSA signature
-for key B<dsa> in bytes. It can be used to determine how much memory must
-be allocated for a DSA signature.
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_get_bits(3)>,
+L<EVP_PKEY_get_security_bits(3)> and L<EVP_PKEY_get_size(3)>.
-B<dsa-E<gt>q> must not be B<NULL>.
+DSA_bits() returns the number of bits in key I<dsa>: this is the number
+of bits in the I<p> parameter.
-DSA_bits() returns the number of bits in key B<dsa>: this is the number
-of bits in the B<p> parameter.
+DSA_size() returns the maximum size of an ASN.1 encoded DSA signature
+for key I<dsa> in bytes. It can be used to determine how much memory must
+be allocated for a DSA signature.
-DSA_security_bits() returns the number of security bits of the given B<dsa>
+DSA_security_bits() returns the number of security bits of the given I<dsa>
key. See L<BN_security_bits(3)>.
=head1 RETURN VALUES
-DSA_size() returns the signature size in bytes.
+DSA_security_bits() returns the number of security bits in the key, or -1 if
+I<dsa> doesn't hold any key parameters.
-DSA_bits() returns the number of bits in the key.
+DSA_bits() returns the number of bits in the key, or -1 if I<dsa> doesn't
+hold any key parameters.
+
+DSA_size() returns the signature size in bytes, or -1 if I<dsa> doesn't
+hold any key parameters.
=head1 SEE ALSO
+L<EVP_PKEY_get_bits(3)>,
+L<EVP_PKEY_get_security_bits(3)>,
+L<EVP_PKEY_get_size(3)>,
L<DSA_new(3)>, L<DSA_sign(3)>
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DTLS_get_data_mtu.pod b/doc/man3/DTLS_get_data_mtu.pod
index 81b945f134a6..ee74fa1704bf 100644
--- a/doc/man3/DTLS_get_data_mtu.pod
+++ b/doc/man3/DTLS_get_data_mtu.pod
@@ -28,7 +28,7 @@ The DTLS_get_data_mtu() function was added in OpenSSL 1.1.1.
Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DTLS_set_timer_cb.pod b/doc/man3/DTLS_set_timer_cb.pod
index c5154dca3570..5014e77d0fc8 100644
--- a/doc/man3/DTLS_set_timer_cb.pod
+++ b/doc/man3/DTLS_set_timer_cb.pod
@@ -32,7 +32,7 @@ The DTLS_set_timer_cb() function was added in OpenSSL 1.1.1.
Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/DTLSv1_listen.pod b/doc/man3/DTLSv1_listen.pod
index 272a8c2ee099..26f34e33acf5 100644
--- a/doc/man3/DTLSv1_listen.pod
+++ b/doc/man3/DTLSv1_listen.pod
@@ -64,6 +64,23 @@ does not support this), then B<*peer> will be cleared and the family set to
AF_UNSPEC. Typically user code is expected to "connect" the underlying socket to
the peer and continue the handshake in a connected state.
+Warning: It is essential that the calling code connects the underlying socket to
+the peer after making use of DTLSv1_listen(). In the typical case where
+L<BIO_s_datagram(3)> is used, the peer address is updated when receiving a
+datagram on an unconnected socket. If the socket is not connected, it can
+receive datagrams from any host on the network, which will cause subsequent
+outgoing datagrams transmitted by DTLS to be transmitted to that host. In other
+words, failing to call BIO_connect() or a similar OS-specific function on a
+socket means that any host on the network can cause outgoing DTLS traffic to be
+redirected to it by sending a datagram to the socket in question. This does not
+break the cryptographic protections of DTLS but may facilitate a
+denial-of-service attack or allow unencrypted information in the DTLS handshake
+to be learned by an attacker. This is due to the historical design of
+L<BIO_s_datagram(3)>; see L<BIO_s_datagram(3)> for details on this issue.
+
+Once a socket has been connected, L<BIO_ctrl_set_connected(3)> should be used to
+inform the BIO that the socket is to be used in connected mode.
+
Prior to calling DTLSv1_listen() user code must ensure that cookie generation
and verification callbacks have been set up using
L<SSL_CTX_set_cookie_generate_cb(3)> and L<SSL_CTX_set_cookie_verify_cb(3)>
@@ -126,9 +143,9 @@ The type of "peer" also changed in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ECDSA_SIG_new.pod b/doc/man3/ECDSA_SIG_new.pod
index 010c163c414a..3266c43b550c 100644
--- a/doc/man3/ECDSA_SIG_new.pod
+++ b/doc/man3/ECDSA_SIG_new.pod
@@ -2,11 +2,9 @@
=head1 NAME
-ECDSA_SIG_get0, ECDSA_SIG_get0_r, ECDSA_SIG_get0_s, ECDSA_SIG_set0,
-ECDSA_SIG_new, ECDSA_SIG_free, ECDSA_size, ECDSA_sign, ECDSA_do_sign,
-ECDSA_verify, ECDSA_do_verify, ECDSA_sign_setup, ECDSA_sign_ex,
-ECDSA_do_sign_ex - low-level elliptic curve digital signature algorithm (ECDSA)
-functions
+ECDSA_SIG_new, ECDSA_SIG_free,
+ECDSA_SIG_get0, ECDSA_SIG_get0_r, ECDSA_SIG_get0_s, ECDSA_SIG_set0
+- Functions for creating, destroying and manipulating ECDSA_SIG objects
=head1 SYNOPSIS
@@ -18,98 +16,38 @@ functions
const BIGNUM *ECDSA_SIG_get0_r(const ECDSA_SIG *sig);
const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig);
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
- int ECDSA_size(const EC_KEY *eckey);
-
- int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen,
- unsigned char *sig, unsigned int *siglen, EC_KEY *eckey);
- ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len,
- EC_KEY *eckey);
-
- int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen,
- const unsigned char *sig, int siglen, EC_KEY *eckey);
- int ECDSA_do_verify(const unsigned char *dgst, int dgst_len,
- const ECDSA_SIG *sig, EC_KEY* eckey);
-
- ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen,
- const BIGNUM *kinv, const BIGNUM *rp,
- EC_KEY *eckey);
- int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp);
- int ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen,
- unsigned char *sig, unsigned int *siglen,
- const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey);
=head1 DESCRIPTION
-Note: these functions provide a low-level interface to ECDSA. Most
-applications should use the higher level B<EVP> interface such as
-L<EVP_DigestSignInit(3)> or L<EVP_DigestVerifyInit(3)> instead.
-
B<ECDSA_SIG> is an opaque structure consisting of two BIGNUMs for the
-B<r> and B<s> value of an ECDSA signature (see X9.62 or FIPS 186-2).
+I<r> and I<s> value of an Elliptic Curve Digital Signature Algorithm (ECDSA) signature
+(see FIPS186-4 or X9.62).
+The B<ECDSA_SIG> object was mainly used by the deprecated low level functions described in
+L<ECDSA_sign(3)>, it is still required in order to be able to set or get the values of
+I<r> and I<s> into or from a signature. This is mainly used for testing purposes as shown
+in the L</EXAMPLES>.
-ECDSA_SIG_new() allocates an empty B<ECDSA_SIG> structure. Note: before
-OpenSSL 1.1.0 the: the B<r> and B<s> components were initialised.
+ECDSA_SIG_new() allocates an empty B<ECDSA_SIG> structure.
+Note: before OpenSSL 1.1.0, the I<r> and I<s> components were initialised.
-ECDSA_SIG_free() frees the B<ECDSA_SIG> structure B<sig>.
+ECDSA_SIG_free() frees the B<ECDSA_SIG> structure I<sig>.
-ECDSA_SIG_get0() returns internal pointers the B<r> and B<s> values contained
-in B<sig> and stores them in B<*pr> and B<*ps>, respectively.
-The pointer B<pr> or B<ps> can be NULL, in which case the corresponding value
+ECDSA_SIG_get0() returns internal pointers the I<r> and I<s> values contained
+in I<sig> and stores them in I<*pr> and I<*ps>, respectively.
+The pointer I<pr> or I<ps> can be NULL, in which case the corresponding value
is not returned.
-The values B<r>, B<s> can also be retrieved separately by the corresponding
+The values I<r>, I<s> can also be retrieved separately by the corresponding
function ECDSA_SIG_get0_r() and ECDSA_SIG_get0_s(), respectively.
-The B<r> and B<s> values can be set by calling ECDSA_SIG_set0() and passing the
-new values for B<r> and B<s> as parameters to the function. Calling this
-function transfers the memory management of the values to the ECDSA_SIG object,
-and therefore the values that have been passed in should not be freed directly
-after this function has been called.
+Non-NULL I<r> and I<s> values can be set on the I<sig> by calling
+ECDSA_SIG_set0(). Calling this function transfers the memory management of the
+values to the B<ECDSA_SIG> object, and therefore the values that have been
+passed in should not be freed by the caller.
See L<i2d_ECDSA_SIG(3)> and L<d2i_ECDSA_SIG(3)> for information about encoding
and decoding ECDSA signatures to/from DER.
-ECDSA_size() returns the maximum length of a DER encoded ECDSA signature
-created with the private EC key B<eckey>.
-
-ECDSA_sign() computes a digital signature of the B<dgstlen> bytes hash value
-B<dgst> using the private EC key B<eckey>. The DER encoded signatures is
-stored in B<sig> and its length is returned in B<sig_len>. Note: B<sig> must
-point to ECDSA_size(eckey) bytes of memory. The parameter B<type> is currently
-ignored. ECDSA_sign() is wrapper function for ECDSA_sign_ex() with B<kinv>
-and B<rp> set to NULL.
-
-ECDSA_do_sign() is similar to ECDSA_sign() except the signature is returned
-as a newly allocated B<ECDSA_SIG> structure (or NULL on error). ECDSA_do_sign()
-is a wrapper function for ECDSA_do_sign_ex() with B<kinv> and B<rp> set to
-NULL.
-
-ECDSA_verify() verifies that the signature in B<sig> of size B<siglen> is a
-valid ECDSA signature of the hash value B<dgst> of size B<dgstlen> using the
-public key B<eckey>. The parameter B<type> is ignored.
-
-ECDSA_do_verify() is similar to ECDSA_verify() except the signature is
-presented in the form of a pointer to an B<ECDSA_SIG> structure.
-
-The remaining functions utilise the internal B<kinv> and B<r> values used
-during signature computation. Most applications will never need to call these
-and some external ECDSA ENGINE implementations may not support them at all if
-either B<kinv> or B<r> is not B<NULL>.
-
-ECDSA_sign_setup() may be used to precompute parts of the signing operation.
-B<eckey> is the private EC key and B<ctx> is a pointer to B<BN_CTX> structure
-(or NULL). The precomputed values or returned in B<kinv> and B<rp> and can be
-used in a later call to ECDSA_sign_ex() or ECDSA_do_sign_ex().
-
-ECDSA_sign_ex() computes a digital signature of the B<dgstlen> bytes hash value
-B<dgst> using the private EC key B<eckey> and the optional pre-computed values
-B<kinv> and B<rp>. The DER encoded signature is stored in B<sig> and its
-length is returned in B<sig_len>. Note: B<sig> must point to ECDSA_size(eckey)
-bytes of memory. The parameter B<type> is ignored.
-
-ECDSA_do_sign_ex() is similar to ECDSA_sign_ex() except the signature is
-returned as a newly allocated B<ECDSA_SIG> structure (or NULL on error).
-
=head1 RETURN VALUES
ECDSA_SIG_new() returns NULL if the allocation fails.
@@ -119,74 +57,71 @@ ECDSA_SIG_set0() returns 1 on success or 0 on failure.
ECDSA_SIG_get0_r() and ECDSA_SIG_get0_s() return the corresponding value,
or NULL if it is unset.
-ECDSA_size() returns the maximum length signature or 0 on error.
-
-ECDSA_sign(), ECDSA_sign_ex() and ECDSA_sign_setup() return 1 if successful
-or 0 on error.
-
-ECDSA_do_sign() and ECDSA_do_sign_ex() return a pointer to an allocated
-B<ECDSA_SIG> structure or NULL on error.
-
-ECDSA_verify() and ECDSA_do_verify() return 1 for a valid
-signature, 0 for an invalid signature and -1 on error.
-The error codes can be obtained by L<ERR_get_error(3)>.
-
=head1 EXAMPLES
-Creating an ECDSA signature of a given SHA-256 hash value using the
-named curve prime256v1 (aka P-256).
-
-First step: create an EC_KEY object (note: this part is B<not> ECDSA
-specific)
+Extract signature I<r> and I<s> values from a ECDSA I<signature>
+of size I<signaturelen>:
- int ret;
- ECDSA_SIG *sig;
- EC_KEY *eckey;
+ ECDSA_SIG *obj;
+ const BIGNUM *r, *s;
- eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
- if (eckey == NULL)
+ /* Load a signature into the ECDSA_SIG object */
+ obj = d2i_ECDSA_SIG(NULL, &signature, signaturelen);
+ if (obj == NULL)
/* error */
- if (EC_KEY_generate_key(eckey) == 0)
- /* error */
-
-Second step: compute the ECDSA signature of a SHA-256 hash value
-using ECDSA_do_sign():
- sig = ECDSA_do_sign(digest, 32, eckey);
- if (sig == NULL)
+ r = ECDSA_SIG_get0_r(obj);
+ s = ECDSA_SIG_get0_s(obj);
+ if (r == NULL || s == NULL)
/* error */
-or using ECDSA_sign():
+ /* Use BN_bn2binpad() here to convert to r and s into byte arrays */
- unsigned char *buffer, *pp;
- int buf_len;
+ /*
+ * Do not try to access I<r> or I<s> after calling ECDSA_SIG_free(),
+ * as they are both freed by this call.
+ */
+ ECDSA_SIG_free(obj);
- buf_len = ECDSA_size(eckey);
- buffer = OPENSSL_malloc(buf_len);
- pp = buffer;
- if (ECDSA_sign(0, dgst, dgstlen, pp, &buf_len, eckey) == 0)
- /* error */
+Convert I<r> and I<s> byte arrays into an ECDSA_SIG I<signature> of
+size I<signaturelen>:
-Third step: verify the created ECDSA signature using ECDSA_do_verify():
+ ECDSA_SIG *obj = NULL;
+ unsigned char *signature = NULL;
+ size_t signaturelen;
+ BIGNUM *rbn = NULL, *sbn = NULL;
- ret = ECDSA_do_verify(digest, 32, sig, eckey);
+ obj = ECDSA_SIG_new();
+ if (obj == NULL)
+ /* error */
+ rbn = BN_bin2bn(r, rlen, NULL);
+ sbn = BN_bin2bn(s, slen, NULL);
+ if (rbn == NULL || sbn == NULL)
+ /* error */
-or using ECDSA_verify():
+ if (!ECDSA_SIG_set0(obj, rbn, sbn))
+ /* error */
+ /* Set these to NULL since they are now owned by obj */
+ rbn = sbn = NULL;
- ret = ECDSA_verify(0, digest, 32, buffer, buf_len, eckey);
+ signaturelen = i2d_ECDSA_SIG(obj, &signature);
+ if (signaturelen <= 0)
+ /* error */
-and finally evaluate the return value:
+ /*
+ * This signature could now be passed to L<EVP_DigestVerify(3)>
+ * or L<EVP_DigestVerifyFinal(3)>
+ */
- if (ret == 1)
- /* signature ok */
- else if (ret == 0)
- /* incorrect signature */
- else
- /* error */
+ BN_free(rbn);
+ BN_free(sbn);
+ OPENSSL_free(signature);
+ ECDSA_SIG_free(obj);
=head1 CONFORMING TO
-ANSI X9.62, US Federal Information Processing Standard FIPS 186-2
+ANSI X9.62,
+US Federal Information Processing Standard FIPS186-4
(Digital Signature Standard, DSS)
=head1 SEE ALSO
@@ -194,14 +129,16 @@ ANSI X9.62, US Federal Information Processing Standard FIPS 186-2
L<EC_KEY_new(3)>,
L<EVP_DigestSignInit(3)>,
L<EVP_DigestVerifyInit(3)>,
+L<EVP_PKEY_sign(3)>
L<i2d_ECDSA_SIG(3)>,
-L<d2i_ECDSA_SIG(3)>
+L<d2i_ECDSA_SIG(3)>,
+L<ECDSA_sign(3)>
=head1 COPYRIGHT
-Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ECDSA_sign.pod b/doc/man3/ECDSA_sign.pod
new file mode 100644
index 000000000000..7e5646665335
--- /dev/null
+++ b/doc/man3/ECDSA_sign.pod
@@ -0,0 +1,186 @@
+=pod
+
+=head1 NAME
+
+ECDSA_size, ECDSA_sign, ECDSA_do_sign,
+ECDSA_verify, ECDSA_do_verify, ECDSA_sign_setup, ECDSA_sign_ex,
+ECDSA_do_sign_ex - deprecated low-level elliptic curve digital signature algorithm
+(ECDSA) functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/ecdsa.h>
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ int ECDSA_size(const EC_KEY *eckey);
+
+ int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen,
+ unsigned char *sig, unsigned int *siglen, EC_KEY *eckey);
+ ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len,
+ EC_KEY *eckey);
+
+ int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen,
+ const unsigned char *sig, int siglen, EC_KEY *eckey);
+ int ECDSA_do_verify(const unsigned char *dgst, int dgst_len,
+ const ECDSA_SIG *sig, EC_KEY* eckey);
+
+ ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen,
+ const BIGNUM *kinv, const BIGNUM *rp,
+ EC_KEY *eckey);
+ int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp);
+ int ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen,
+ unsigned char *sig, unsigned int *siglen,
+ const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey);
+
+=head1 DESCRIPTION
+
+See L<ECDSA_SIG_new(3)> for a description of the B<ECDSA_SIG> object.
+
+See L<i2d_ECDSA_SIG(3)> and L<d2i_ECDSA_SIG(3)> for information about encoding
+and decoding ECDSA signatures to/from DER.
+
+All of the functions described below are deprecated. Applications should
+use the higher level B<EVP> interface such as L<EVP_DigestSignInit(3)>
+or L<EVP_DigestVerifyInit(3)> instead.
+
+ECDSA_size() returns the maximum length of a DER encoded ECDSA signature
+created with the private EC key I<eckey>. To obtain the actual signature
+size use L<EVP_PKEY_sign(3)> with a NULL I<sig> parameter.
+
+ECDSA_sign() computes a digital signature of the I<dgstlen> bytes hash value
+I<dgst> using the private EC key I<eckey>. The DER encoded signatures is
+stored in I<sig> and its length is returned in I<sig_len>. Note: I<sig> must
+point to ECDSA_size(eckey) bytes of memory. The parameter I<type> is currently
+ignored. ECDSA_sign() is wrapper function for ECDSA_sign_ex() with I<kinv>
+and I<rp> set to NULL.
+
+ECDSA_do_sign() is similar to ECDSA_sign() except the signature is returned
+as a newly allocated B<ECDSA_SIG> structure (or NULL on error). ECDSA_do_sign()
+is a wrapper function for ECDSA_do_sign_ex() with I<kinv> and I<rp> set to
+NULL.
+
+ECDSA_verify() verifies that the signature in I<sig> of size I<siglen> is a
+valid ECDSA signature of the hash value I<dgst> of size I<dgstlen> using the
+public key I<eckey>. The parameter I<type> is ignored.
+
+ECDSA_do_verify() is similar to ECDSA_verify() except the signature is
+presented in the form of a pointer to an B<ECDSA_SIG> structure.
+
+The remaining functions utilise the internal I<kinv> and I<r> values used
+during signature computation. Most applications will never need to call these
+and some external ECDSA ENGINE implementations may not support them at all if
+either I<kinv> or I<r> is not NULL.
+
+ECDSA_sign_setup() may be used to precompute parts of the signing operation.
+I<eckey> is the private EC key and I<ctx> is a pointer to B<BN_CTX> structure
+(or NULL). The precomputed values or returned in I<kinv> and I<rp> and can be
+used in a later call to ECDSA_sign_ex() or ECDSA_do_sign_ex().
+
+ECDSA_sign_ex() computes a digital signature of the I<dgstlen> bytes hash value
+I<dgst> using the private EC key I<eckey> and the optional pre-computed values
+I<kinv> and I<rp>. The DER encoded signature is stored in I<sig> and its
+length is returned in I<sig_len>. Note: I<sig> must point to ECDSA_size(eckey)
+bytes of memory. The parameter I<type> is ignored.
+
+ECDSA_do_sign_ex() is similar to ECDSA_sign_ex() except the signature is
+returned as a newly allocated B<ECDSA_SIG> structure (or NULL on error).
+
+=head1 RETURN VALUES
+
+ECDSA_size() returns the maximum length signature or 0 on error.
+
+ECDSA_sign(), ECDSA_sign_ex() and ECDSA_sign_setup() return 1 if successful
+or 0 on error.
+
+ECDSA_do_sign() and ECDSA_do_sign_ex() return a pointer to an allocated
+B<ECDSA_SIG> structure or NULL on error.
+
+ECDSA_verify() and ECDSA_do_verify() return 1 for a valid
+signature, 0 for an invalid signature and -1 on error.
+The error codes can be obtained by L<ERR_get_error(3)>.
+
+=head1 EXAMPLES
+
+Creating an ECDSA signature of a given SHA-256 hash value using the
+named curve prime256v1 (aka P-256).
+This example uses deprecated functionality. See L</DESCRIPTION>.
+
+First step: create an EC_KEY object (note: this part is B<not> ECDSA
+specific)
+
+ int ret;
+ ECDSA_SIG *sig;
+ EC_KEY *eckey;
+
+ eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+ if (eckey == NULL)
+ /* error */
+ if (EC_KEY_generate_key(eckey) == 0)
+ /* error */
+
+Second step: compute the ECDSA signature of a SHA-256 hash value
+using ECDSA_do_sign():
+
+ sig = ECDSA_do_sign(digest, 32, eckey);
+ if (sig == NULL)
+ /* error */
+
+or using ECDSA_sign():
+
+ unsigned char *buffer, *pp;
+ int buf_len;
+
+ buf_len = ECDSA_size(eckey);
+ buffer = OPENSSL_malloc(buf_len);
+ pp = buffer;
+ if (ECDSA_sign(0, dgst, dgstlen, pp, &buf_len, eckey) == 0)
+ /* error */
+
+Third step: verify the created ECDSA signature using ECDSA_do_verify():
+
+ ret = ECDSA_do_verify(digest, 32, sig, eckey);
+
+or using ECDSA_verify():
+
+ ret = ECDSA_verify(0, digest, 32, buffer, buf_len, eckey);
+
+and finally evaluate the return value:
+
+ if (ret == 1)
+ /* signature ok */
+ else if (ret == 0)
+ /* incorrect signature */
+ else
+ /* error */
+
+=head1 CONFORMING TO
+
+ANSI X9.62, US Federal Information Processing Standard FIPS186-2
+(Digital Signature Standard, DSS)
+
+=head1 SEE ALSO
+
+L<EC_KEY_new(3)>,
+L<EVP_DigestSignInit(3)>,
+L<EVP_DigestVerifyInit(3)>,
+L<EVP_PKEY_sign(3)>
+L<i2d_ECDSA_SIG(3)>,
+L<d2i_ECDSA_SIG(3)>
+
+=head1 HISTORY
+
+All functionality described here was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/ECPKParameters_print.pod b/doc/man3/ECPKParameters_print.pod
index 24b6bb9e04db..70e435b09096 100644
--- a/doc/man3/ECPKParameters_print.pod
+++ b/doc/man3/ECPKParameters_print.pod
@@ -9,11 +9,18 @@ encoding ASN1 representations of elliptic curve entities
#include <openssl/ec.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off);
int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off);
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_print_params(3)>
+
The ECPKParameters represent the public parameters for an
B<EC_GROUP> structure, which represents a curve.
@@ -32,11 +39,15 @@ L<crypto(7)>, L<EC_GROUP_new(3)>, L<EC_GROUP_copy(3)>,
L<EC_POINT_new(3)>, L<EC_POINT_add(3)>, L<EC_KEY_new(3)>,
L<EC_GFp_simple_method(3)>,
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2013-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EC_GFp_simple_method.pod b/doc/man3/EC_GFp_simple_method.pod
index f283d8e71ec5..8c4acd28e0b0 100644
--- a/doc/man3/EC_GFp_simple_method.pod
+++ b/doc/man3/EC_GFp_simple_method.pod
@@ -8,6 +8,10 @@ EC_GFp_simple_method, EC_GFp_mont_method, EC_GFp_nist_method, EC_GFp_nistp224_me
#include <openssl/ec.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
const EC_METHOD *EC_GFp_simple_method(void);
const EC_METHOD *EC_GFp_mont_method(void);
const EC_METHOD *EC_GFp_nist_method(void);
@@ -21,6 +25,10 @@ EC_GFp_simple_method, EC_GFp_mont_method, EC_GFp_nist_method, EC_GFp_nistp224_me
=head1 DESCRIPTION
+
+All const EC_METHOD *EC_GF* functions were deprecated in OpenSSL 3.0, since
+EC_METHOD is no longer a public concept.
+
The Elliptic Curve library provides a number of different implementations through a single common interface.
When constructing a curve using EC_GROUP_new (see L<EC_GROUP_new(3)>) an
implementation method must be provided. The functions described here all return a const pointer to an
@@ -39,10 +47,8 @@ The functions EC_GFp_nistp224_method, EC_GFp_nistp256_method and EC_GFp_nistp521
optimised implementations for the NIST P224, P256 and P521 curves respectively. Note, however, that these
implementations are not available on all platforms.
-EC_METHOD_get_field_type identifies what type of field the EC_METHOD structure supports, which will be either
-F2^m or Fp. If the field type is Fp then the value B<NID_X9_62_prime_field> is returned. If the field type is
-F2^m then the value B<NID_X9_62_characteristic_two_field> is returned. These values are defined in the
-obj_mac.h header file.
+EC_METHOD_get_field_type() was deprecated in OpenSSL 3.0.
+Applications should use EC_GROUP_get_field_type() as a replacement (see L<EC_GROUP_copy(3)>).
=head1 RETURN VALUES
@@ -57,11 +63,19 @@ L<EC_POINT_new(3)>, L<EC_POINT_add(3)>, L<EC_KEY_new(3)>,
L<d2i_ECPKParameters(3)>,
L<BN_mod_mul_montgomery(3)>
+=head1 HISTORY
+
+EC_GFp_simple_method(), EC_GFp_mont_method(void),
+EC_GFp_nist_method(), EC_GFp_nistp224_method(),
+EC_GFp_nistp256_method(), EC_GFp_nistp521_method(),
+EC_GF2m_simple_method(), and EC_METHOD_get_field_type()
+were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2013-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EC_GROUP_copy.pod b/doc/man3/EC_GROUP_copy.pod
index 0d50fdc0c74f..651f059d4fd5 100644
--- a/doc/man3/EC_GROUP_copy.pod
+++ b/doc/man3/EC_GROUP_copy.pod
@@ -9,9 +9,11 @@ EC_GROUP_set_curve_name, EC_GROUP_get_curve_name, EC_GROUP_set_asn1_flag,
EC_GROUP_get_asn1_flag, EC_GROUP_set_point_conversion_form,
EC_GROUP_get_point_conversion_form, EC_GROUP_get0_seed,
EC_GROUP_get_seed_len, EC_GROUP_set_seed, EC_GROUP_get_degree,
-EC_GROUP_check, EC_GROUP_check_discriminant, EC_GROUP_cmp,
+EC_GROUP_check, EC_GROUP_check_named_curve,
+EC_GROUP_check_discriminant, EC_GROUP_cmp,
EC_GROUP_get_basis_type, EC_GROUP_get_trinomial_basis,
-EC_GROUP_get_pentanomial_basis
+EC_GROUP_get_pentanomial_basis, EC_GROUP_get0_field,
+EC_GROUP_get_field_type
- Functions for manipulating EC_GROUP objects
=head1 SYNOPSIS
@@ -21,8 +23,6 @@ EC_GROUP_get_pentanomial_basis
int EC_GROUP_copy(EC_GROUP *dst, const EC_GROUP *src);
EC_GROUP *EC_GROUP_dup(const EC_GROUP *src);
- const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group);
-
int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
const BIGNUM *order, const BIGNUM *cofactor);
const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group);
@@ -32,6 +32,7 @@ EC_GROUP_get_pentanomial_basis
int EC_GROUP_order_bits(const EC_GROUP *group);
int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx);
const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group);
+ const BIGNUM *EC_GROUP_get0_field(const EC_GROUP *group);
void EC_GROUP_set_curve_name(EC_GROUP *group, int nid);
int EC_GROUP_get_curve_name(const EC_GROUP *group);
@@ -42,23 +43,33 @@ EC_GROUP_get_pentanomial_basis
void EC_GROUP_set_point_conversion_form(EC_GROUP *group, point_conversion_form_t form);
point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *group);
- unsigned char *EC_GROUP_get0_seed(const EC_GROUP *x);
- size_t EC_GROUP_get_seed_len(const EC_GROUP *);
- size_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len);
+ unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group);
+ size_t EC_GROUP_get_seed_len(const EC_GROUP *group);
+ size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *, size_t len);
int EC_GROUP_get_degree(const EC_GROUP *group);
int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx);
+ int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only,
+ BN_CTX *ctx);
int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx);
int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx);
- int EC_GROUP_get_basis_type(const EC_GROUP *);
- int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k);
- int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1,
+ int EC_GROUP_get_basis_type(const EC_GROUP *group);
+ int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k);
+ int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,
unsigned int *k2, unsigned int *k3);
+ int EC_GROUP_get_field_type(const EC_GROUP *group);
+
+The following function has been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group);
+
=head1 DESCRIPTION
EC_GROUP_copy() copies the curve B<src> into B<dst>. Both B<src> and B<dst> must use the same EC_METHOD.
@@ -67,6 +78,7 @@ EC_GROUP_dup() creates a new EC_GROUP object and copies the content from B<src>
EC_GROUP object.
EC_GROUP_method_of() obtains the EC_METHOD of B<group>.
+This function was deprecated in OpenSSL 3.0, since EC_METHOD is no longer a public concept.
EC_GROUP_set_generator() sets curve parameters that must be agreed by all participants using the curve. These
parameters include the B<generator>, the B<order> and the B<cofactor>. The B<generator> is a well defined point on the
@@ -136,16 +148,31 @@ built-in curves within the library provide seed values that can be obtained. It
EC_GROUP_set_seed() and passing a pointer to a memory block, along with the length of the seed. Again, the EC library will not use
this seed value, although it will be preserved in any ASN1 based communications.
-EC_GROUP_get_degree() gets the degree of the field. For Fp fields this will be the number of bits in p. For F2^m fields this will be
-the value m.
+EC_GROUP_get_degree() gets the degree of the field.
+For Fp fields this will be the number of bits in p.
+For F2^m fields this will be the value m.
+
+EC_GROUP_get_field_type() identifies what type of field the EC_GROUP structure supports,
+which will be either F2^m or Fp.
The function EC_GROUP_check_discriminant() calculates the discriminant for the curve and verifies that it is valid.
For a curve defined over Fp the discriminant is given by the formula 4*a^3 + 27*b^2 whilst for F2^m curves the discriminant is
simply b. In either case for the curve to be valid the discriminant must be non zero.
-The function EC_GROUP_check() performs a number of checks on a curve to verify that it is valid. Checks performed include
+The function EC_GROUP_check() behaves in the following way:
+For the OpenSSL default provider it performs a number of checks on a curve to verify that it is valid. Checks performed include
verifying that the discriminant is non zero; that a generator has been defined; that the generator is on the curve and has
-the correct order.
+the correct order. For the OpenSSL FIPS provider it uses EC_GROUP_check_named_curve() to conform to SP800-56Ar3.
+
+The function EC_GROUP_check_named_curve() determines if the group's domain parameters match one of the built-in curves supported by the library.
+The curve name is returned as a B<NID> if it matches. If the group's domain parameters have been modified then no match will be found.
+If the curve name of the given group is B<NID_undef> (e.g. it has been created by using explicit parameters with no curve name),
+then this method can be used to lookup the name of the curve that matches the group domain parameters. The built-in curves contain
+aliases, so that multiple NID's can map to the same domain parameters. For such curves it is unspecified which of the aliases will be
+returned if the curve name of the given group is NID_undef.
+If B<nist_only> is 1 it will only look for NIST approved curves, otherwise it searches all built-in curves.
+This function may be passed a BN_CTX object in the B<ctx> parameter.
+The B<ctx> parameter may be NULL.
EC_GROUP_cmp() compares B<a> and B<b> to determine whether they represent the same curve or not.
@@ -188,9 +215,17 @@ EC_GROUP_get_point_conversion_form() returns the point_conversion_form for B<gro
EC_GROUP_get_degree() returns the degree for B<group> or 0 if the operation is not supported by the underlying group implementation.
+EC_GROUP_get_field_type() returns either B<NID_X9_62_prime_field> for prime curves
+or B<NID_X9_62_characteristic_two_field> for binary curves;
+these values are defined in the F<< <openssl/obj_mac.h> >> header file.
+
+EC_GROUP_check_named_curve() returns the nid of the matching named curve, otherwise it returns 0 for no match, or -1 on error.
+
EC_GROUP_get0_order() returns an internal pointer to the group order.
EC_GROUP_order_bits() returns the number of bits in the group order.
EC_GROUP_get0_cofactor() returns an internal pointer to the group cofactor.
+EC_GROUP_get0_field() returns an internal pointer to the group field. For curves over GF(p), this is the modulus; for curves
+over GF(2^m), this is the irreducible polynomial defining the field.
EC_GROUP_get0_seed() returns a pointer to the seed that was used to generate the parameter b, or NULL if the seed is not
specified. EC_GROUP_get_seed_len() returns the length of the seed or 0 if the seed is not specified.
@@ -200,7 +235,7 @@ EC_GROUP_set_seed() returns the length of the seed that has been set. If the sup
EC_GROUP_cmp() returns 0 if the curves are equal, 1 if they are not equal, or -1 on error.
-EC_GROUP_get_basis_type() returns the values NID_X9_62_tpBasis or NID_X9_62_ppBasis (as defined in <openssl/obj_mac.h>) for a
+EC_GROUP_get_basis_type() returns the values NID_X9_62_tpBasis or NID_X9_62_ppBasis (as defined in F<< <openssl/obj_mac.h> >>) for a
trinomial or pentanomial respectively. Alternatively in the event of an error a 0 is returned.
=head1 SEE ALSO
@@ -209,11 +244,17 @@ L<crypto(7)>, L<EC_GROUP_new(3)>,
L<EC_POINT_new(3)>, L<EC_POINT_add(3)>, L<EC_KEY_new(3)>,
L<EC_GFp_simple_method(3)>, L<d2i_ECPKParameters(3)>
+=head1 HISTORY
+
+EC_GROUP_method_of() was deprecated in OpenSSL 3.0.
+EC_GROUP_get0_field(), EC_GROUP_check_named_curve() and EC_GROUP_get_field_type() were added in OpenSSL 3.0.
+EC_GROUP_get0_order(), EC_GROUP_order_bits() and EC_GROUP_get0_cofactor() were added in OpenSSL 1.1.0.
+
=head1 COPYRIGHT
-Copyright 2013-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2013-2023 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EC_GROUP_new.pod b/doc/man3/EC_GROUP_new.pod
index b1141a077739..b6d67b617642 100644
--- a/doc/man3/EC_GROUP_new.pod
+++ b/doc/man3/EC_GROUP_new.pod
@@ -4,13 +4,15 @@
EC_GROUP_get_ecparameters,
EC_GROUP_get_ecpkparameters,
-EC_GROUP_new,
+EC_GROUP_new_from_params,
EC_GROUP_new_from_ecparameters,
EC_GROUP_new_from_ecpkparameters,
+EC_GROUP_new,
EC_GROUP_free,
EC_GROUP_clear_free,
EC_GROUP_new_curve_GFp,
EC_GROUP_new_curve_GF2m,
+EC_GROUP_new_by_curve_name_ex,
EC_GROUP_new_by_curve_name,
EC_GROUP_set_curve,
EC_GROUP_get_curve,
@@ -18,29 +20,48 @@ EC_GROUP_set_curve_GFp,
EC_GROUP_get_curve_GFp,
EC_GROUP_set_curve_GF2m,
EC_GROUP_get_curve_GF2m,
-EC_get_builtin_curves - Functions for creating and destroying EC_GROUP
-objects
+EC_get_builtin_curves,
+OSSL_EC_curve_nid2name -
+Functions for creating and destroying EC_GROUP objects
=head1 SYNOPSIS
#include <openssl/ec.h>
- EC_GROUP *EC_GROUP_new(const EC_METHOD *meth);
- EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
- EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params)
+ EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[],
+ OSSL_LIB_CTX *libctx, const char *propq);
+ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params);
+ EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params);
void EC_GROUP_free(EC_GROUP *group);
- void EC_GROUP_clear_free(EC_GROUP *group);
EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx);
EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx);
+ EC_GROUP *EC_GROUP_new_by_curve_name_ex(OSSL_LIB_CTX *libctx, const char *propq,
+ int nid);
EC_GROUP *EC_GROUP_new_by_curve_name(int nid);
int EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx);
int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b,
BN_CTX *ctx);
+
+ ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group,
+ ECPARAMETERS *params);
+ ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group,
+ ECPKPARAMETERS *params);
+
+ size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems);
+ const char *OSSL_EC_curve_nid2name(int nid);
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ EC_GROUP *EC_GROUP_new(const EC_METHOD *meth);
+ void EC_GROUP_clear_free(EC_GROUP *group);
+
int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p,
const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p,
@@ -50,11 +71,6 @@ objects
int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p,
BIGNUM *a, BIGNUM *b, BN_CTX *ctx);
- ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group, ECPARAMETERS *params)
- ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group, ECPKPARAMETERS *params)
-
- size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems);
-
=head1 DESCRIPTION
Within the library there are two forms of elliptic curve that are of interest.
@@ -70,23 +86,38 @@ curve equation is modified to:
y^2 + xy = x^3 + ax^2 + b (where b != 0)
-Operations in a binary field are performed relative to an B<irreducible
-polynomial>. All such curves with OpenSSL use a trinomial or a pentanomial for
-this parameter.
-
-A new curve can be constructed by calling EC_GROUP_new(), using the
-implementation provided by B<meth> (see L<EC_GFp_simple_method(3)>). It is then
-necessary to call EC_GROUP_set_curve() to set the curve parameters.
-EC_GROUP_new_from_ecparameters() will create a group from the specified
-B<params> and EC_GROUP_new_from_ecpkparameters() will create a group from the
-specific PK B<params>.
-
-EC_GROUP_set_curve() sets the curve parameters B<p>, B<a> and B<b>. For a curve
-over Fp B<p> is the prime for the field. For a curve over F2^m B<p> represents
+Operations in a binary field are performed relative to an
+B<irreducible polynomial>. All such curves with OpenSSL use a trinomial or a
+pentanomial for this parameter.
+
+Although deprecated since OpenSSL 3.0 and should no longer be used,
+a new curve can be constructed by calling EC_GROUP_new(), using the
+implementation provided by I<meth> (see L<EC_GFp_simple_method(3)>) and
+associated with the library context I<ctx> (see L<OSSL_LIB_CTX(3)>).
+The I<ctx> parameter may be NULL in which case the default library context is
+used.
+It is then necessary to call EC_GROUP_set_curve() to set the curve parameters.
+Applications should instead use one of the other EC_GROUP_new_* constructors.
+
+EC_GROUP_new_from_params() creates a group with parameters specified by I<params>.
+The library context I<libctx> (see L<OSSL_LIB_CTX(3)>) and property query string
+I<propq> are used to fetch algorithms from providers.
+I<params> may be either a list of explicit params or a named group,
+The values for I<ctx> and I<propq> may be NULL.
+The I<params> that can be used are described in
+L<B<EVP_PKEY-EC>(7)|EVP_PKEY-EC(7)/Common EC parameters>.
+
+EC_GROUP_new_from_ecparameters() will create a group from the
+specified I<params> and
+EC_GROUP_new_from_ecpkparameters() will create a group from the specific PK
+I<params>.
+
+EC_GROUP_set_curve() sets the curve parameters I<p>, I<a> and I<b>. For a curve
+over Fp I<p> is the prime for the field. For a curve over F2^m I<p> represents
the irreducible polynomial - each bit represents a term in the polynomial.
Therefore, there will either be three or five bits set dependent on whether the
polynomial is a trinomial or a pentanomial.
-In either case, B<a> and B<b> represents the coefficients a and b from the
+In either case, I<a> and I<b> represents the coefficients a and b from the
relevant equation introduced above.
EC_group_get_curve() obtains the previously set curve parameters.
@@ -106,13 +137,13 @@ An appropriate default implementation method will be used.
Whilst the library can be used to create any curve using the functions described
above, there are also a number of predefined curves that are available. In order
to obtain a list of all of the predefined curves, call the function
-EC_get_builtin_curves(). The parameter B<r> should be an array of
-EC_builtin_curve structures of size B<nitems>. The function will populate the
-B<r> array with information about the builtin curves. If B<nitems> is less than
-the total number of curves available, then the first B<nitems> curves will be
+EC_get_builtin_curves(). The parameter I<r> should be an array of
+EC_builtin_curve structures of size I<nitems>. The function will populate the
+I<r> array with information about the built-in curves. If I<nitems> is less than
+the total number of curves available, then the first I<nitems> curves will be
returned. Otherwise the total number of curves will be provided. The return
value is the total number of curves available (whether that number has been
-populated in B<r> or not). Passing a NULL B<r>, or setting B<nitems> to 0 will
+populated in I<r> or not). Passing a NULL I<r>, or setting I<nitems> to 0 will
do nothing other than return the total number of curves available.
The EC_builtin_curve structure is defined as follows:
@@ -121,40 +152,80 @@ The EC_builtin_curve structure is defined as follows:
const char *comment;
} EC_builtin_curve;
-Each EC_builtin_curve item has a unique integer id (B<nid>), and a human
+Each EC_builtin_curve item has a unique integer id (I<nid>), and a human
readable comment string describing the curve.
-In order to construct a builtin curve use the function
-EC_GROUP_new_by_curve_name() and provide the B<nid> of the curve to
-be constructed.
+In order to construct a built-in curve use the function
+EC_GROUP_new_by_curve_name_ex() and provide the I<nid> of the curve to
+be constructed, the associated library context to be used in I<ctx> (see
+L<OSSL_LIB_CTX(3)>) and any property query string in I<propq>. The I<ctx> value
+may be NULL in which case the default library context is used. The I<propq>
+value may also be NULL.
+
+EC_GROUP_new_by_curve_name() is the same as
+EC_GROUP_new_by_curve_name_ex() except that the default library context
+is always used along with a NULL property query string.
EC_GROUP_free() frees the memory associated with the EC_GROUP.
-If B<group> is NULL nothing is done.
+If I<group> is NULL nothing is done.
+
+EC_GROUP_clear_free() is deprecated: it was meant to destroy any sensitive data
+held within the EC_GROUP and then free its memory, but since all the data stored
+in the EC_GROUP is public anyway, this function is unnecessary.
+Its use can be safely replaced with EC_GROUP_free().
+If I<group> is NULL nothing is done.
-EC_GROUP_clear_free() destroys any sensitive data held within the EC_GROUP and
-then frees its memory. If B<group> is NULL nothing is done.
+OSSL_EC_curve_nid2name() converts a curve I<nid> into the corresponding name.
=head1 RETURN VALUES
All EC_GROUP_new* functions return a pointer to the newly constructed group, or
NULL on error.
-EC_get_builtin_curves() returns the number of builtin curves that are available.
+EC_get_builtin_curves() returns the number of built-in curves that are
+available.
EC_GROUP_set_curve_GFp(), EC_GROUP_get_curve_GFp(), EC_GROUP_set_curve_GF2m(),
EC_GROUP_get_curve_GF2m() return 1 on success or 0 on error.
+OSSL_EC_curve_nid2name() returns a character string constant, or NULL on error.
+
=head1 SEE ALSO
L<crypto(7)>, L<EC_GROUP_copy(3)>,
L<EC_POINT_new(3)>, L<EC_POINT_add(3)>, L<EC_KEY_new(3)>,
-L<EC_GFp_simple_method(3)>, L<d2i_ECPKParameters(3)>
+L<EC_GFp_simple_method(3)>, L<d2i_ECPKParameters(3)>,
+L<OSSL_LIB_CTX(3)>, L<EVP_PKEY-EC(7)>
+
+=head1 HISTORY
+
+=over 2
+
+=item *
+
+EC_GROUP_new() was deprecated in OpenSSL 3.0.
+
+EC_GROUP_new_by_curve_name_ex() and EC_GROUP_new_from_params() were
+added in OpenSSL 3.0.
+
+=item *
+
+EC_GROUP_clear_free() was deprecated in OpenSSL 3.0; use EC_GROUP_free()
+instead.
+
+=item *
+
+ EC_GROUP_set_curve_GFp(), EC_GROUP_get_curve_GFp(),
+ EC_GROUP_set_curve_GF2m() and EC_GROUP_get_curve_GF2m() were deprecated in
+ OpenSSL 3.0; use EC_GROUP_set_curve() and EC_GROUP_get_curve() instead.
+
+=back
=head1 COPYRIGHT
-Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EC_KEY_get_enc_flags.pod b/doc/man3/EC_KEY_get_enc_flags.pod
index 4f73a1d59d04..d545c1bf701d 100644
--- a/doc/man3/EC_KEY_get_enc_flags.pod
+++ b/doc/man3/EC_KEY_get_enc_flags.pod
@@ -51,7 +51,7 @@ L<d2i_ECPrivateKey(3)>
Copyright 2015-2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EC_KEY_new.pod b/doc/man3/EC_KEY_new.pod
index 2fdb4659b673..e611b4d691f1 100644
--- a/doc/man3/EC_KEY_new.pod
+++ b/doc/man3/EC_KEY_new.pod
@@ -2,10 +2,11 @@
=head1 NAME
-EC_KEY_get_method, EC_KEY_set_method,
+EVP_EC_gen,
+EC_KEY_get_method, EC_KEY_set_method, EC_KEY_new_ex,
EC_KEY_new, EC_KEY_get_flags, EC_KEY_set_flags, EC_KEY_clear_flags,
-EC_KEY_new_by_curve_name, EC_KEY_free, EC_KEY_copy, EC_KEY_dup, EC_KEY_up_ref,
-EC_KEY_get0_engine,
+EC_KEY_new_by_curve_name_ex, EC_KEY_new_by_curve_name, EC_KEY_free,
+EC_KEY_copy, EC_KEY_dup, EC_KEY_up_ref, EC_KEY_get0_engine,
EC_KEY_get0_group, EC_KEY_set_group, EC_KEY_get0_private_key,
EC_KEY_set_private_key, EC_KEY_get0_public_key, EC_KEY_set_public_key,
EC_KEY_get_conv_form,
@@ -20,10 +21,19 @@ EC_KEY objects
#include <openssl/ec.h>
+ EVP_PKEY *EVP_EC_gen(const char *curve);
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ EC_KEY *EC_KEY_new_ex(OSSL_LIB_CTX *ctx, const char *propq);
EC_KEY *EC_KEY_new(void);
int EC_KEY_get_flags(const EC_KEY *key);
void EC_KEY_set_flags(EC_KEY *key, int flags);
void EC_KEY_clear_flags(EC_KEY *key, int flags);
+ EC_KEY *EC_KEY_new_by_curve_name_ex(OSSL_LIB_CTX *ctx, const char *propq,
+ int nid);
EC_KEY *EC_KEY_new_by_curve_name(int nid);
void EC_KEY_free(EC_KEY *key);
EC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src);
@@ -40,7 +50,6 @@ EC_KEY objects
void EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform);
void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag);
int EC_KEY_decoded_from_explicit_params(const EC_KEY *key);
- int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx);
int EC_KEY_generate_key(EC_KEY *key);
int EC_KEY_check_key(const EC_KEY *key);
int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y);
@@ -55,27 +64,52 @@ EC_KEY objects
size_t EC_KEY_priv2oct(const EC_KEY *eckey, unsigned char *buf, size_t len);
size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf);
+ int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx);
=head1 DESCRIPTION
+EVP_EC_gen() generates a new EC key pair on the given I<curve>.
+
+All of the functions described below are deprecated.
+Applications should instead use EVP_EC_gen(), L<EVP_PKEY_Q_keygen(3)>, or
+L<EVP_PKEY_keygen_init(3)> and L<EVP_PKEY_keygen(3)>.
+
An EC_KEY represents a public key and, optionally, the associated private
-key. A new EC_KEY with no associated curve can be constructed by calling
-EC_KEY_new(). The reference count for the newly created EC_KEY is initially
-set to 1. A curve can be associated with the EC_KEY by calling
+key.
+A new EC_KEY with no associated curve can be constructed by calling
+EC_KEY_new_ex() and specifying the associated library context in I<ctx>
+(see L<OSSL_LIB_CTX(3)>) and property query string I<propq>.
+The I<ctx> parameter may be NULL in which case the default library context is
+used.
+The reference count for the newly created EC_KEY is initially
+set to 1.
+A curve can be associated with the EC_KEY by calling
EC_KEY_set_group().
+EC_KEY_new() is the same as EC_KEY_new_ex() except that the default library
+context is always used.
+
Alternatively a new EC_KEY can be constructed by calling
-EC_KEY_new_by_curve_name() and supplying the nid of the associated curve. See
-L<EC_GROUP_new(3)> for a description of curve names. This function simply
-wraps calls to EC_KEY_new() and EC_GROUP_new_by_curve_name().
+EC_KEY_new_by_curve_name_ex() and supplying the nid of the associated
+curve, the library context to be used I<ctx> (see L<OSSL_LIB_CTX(3)>) and any
+property query string I<propq>.
+The I<ctx> parameter may be NULL in which case the default library context is
+used. The I<propq> value may also be NULL.
+See L<EC_GROUP_new(3)> for a description of curve names.
+This function simply wraps calls to EC_KEY_new_ex() and
+EC_GROUP_new_by_curve_name_ex().
+
+EC_KEY_new_by_curve_name() is the same as EC_KEY_new_by_curve_name_ex()
+except that the default library context is always used and a NULL property query
+string.
Calling EC_KEY_free() decrements the reference count for the EC_KEY object,
and if it has dropped to zero then frees the memory associated with it. If
-B<key> is NULL nothing is done.
+I<key> is NULL nothing is done.
-EC_KEY_copy() copies the contents of the EC_KEY in B<src> into B<dest>.
+EC_KEY_copy() copies the contents of the EC_KEY in I<src> into I<dest>.
-EC_KEY_dup() creates a new EC_KEY object and copies B<ec_key> into it.
+EC_KEY_dup() creates a new EC_KEY object and copies I<ec_key> into it.
EC_KEY_up_ref() increments the reference count associated with the EC_KEY
object.
@@ -84,7 +118,7 @@ EC_KEY_get0_engine() returns a handle to the ENGINE that has been set for
this EC_KEY object.
EC_KEY_generate_key() generates a new public and private key for the supplied
-B<eckey> object. B<eckey> must have an EC_GROUP object associated with it
+I<eckey> object. I<eckey> must have an EC_GROUP object associated with it
before calling this function. The private key is a random integer (0 < priv_key
< order, where I<order> is the order of the EC_GROUP object). The public key is
an EC_POINT on the curve calculated by multiplying the generator for the
@@ -93,9 +127,9 @@ curve by the private key.
EC_KEY_check_key() performs various sanity checks on the EC_KEY object to
confirm that it is valid.
-EC_KEY_set_public_key_affine_coordinates() sets the public key for B<key> based
+EC_KEY_set_public_key_affine_coordinates() sets the public key for I<key> based
on its affine co-ordinates; i.e., it constructs an EC_POINT object based on
-the supplied B<x> and B<y> values and sets the public key to be this
+the supplied I<x> and I<y> values and sets the public key to be this
EC_POINT. It also performs certain sanity checks on the key to confirm
that it is valid.
@@ -107,15 +141,15 @@ EC_KEY_set_private_key() accepts NULL as the priv_key argument to securely clear
the private key component from the EC_KEY.
The functions EC_KEY_get_conv_form() and EC_KEY_set_conv_form() get and set the
-point_conversion_form for the B<key>. For a description of
+point_conversion_form for the I<key>. For a description of
point_conversion_forms please see L<EC_POINT_new(3)>.
-EC_KEY_set_flags() sets the flags in the B<flags> parameter on the EC_KEY
+EC_KEY_set_flags() sets the flags in the I<flags> parameter on the EC_KEY
object. Any flags that are already set are left set. The flags currently
defined are EC_FLAG_NON_FIPS_ALLOW and EC_FLAG_FIPS_CHECKED. In
addition there is the flag EC_FLAG_COFACTOR_ECDH which is specific to ECDH.
EC_KEY_get_flags() returns the current flags that are set for this EC_KEY.
-EC_KEY_clear_flags() clears the flags indicated by the B<flags> parameter; all
+EC_KEY_clear_flags() clears the flags indicated by the I<flags> parameter; all
other flags are left in their existing state.
EC_KEY_set_asn1_flag() sets the asn1_flag on the underlying EC_GROUP object
@@ -128,14 +162,16 @@ is NULL or the group parameters are missing, and 0 otherwise.
EC_KEY_precompute_mult() stores multiples of the underlying EC_GROUP generator
for faster point multiplication. See also L<EC_POINT_add(3)>.
+Modern versions should instead switch to named curves which OpenSSL has
+hardcoded lookup tables for.
EC_KEY_oct2key() and EC_KEY_key2buf() are identical to the functions
EC_POINT_oct2point() and EC_POINT_point2buf() except they use the public key
-EC_POINT in B<eckey>.
+EC_POINT in I<eckey>.
EC_KEY_oct2priv() and EC_KEY_priv2oct() convert between the private key
-component of B<eckey> and octet form. The octet form consists of the content
-octets of the B<privateKey> OCTET STRING in an B<ECPrivateKey> ASN.1 structure.
+component of I<eckey> and octet form. The octet form consists of the content
+octets of the I<privateKey> OCTET STRING in an I<ECPrivateKey> ASN.1 structure.
The function EC_KEY_priv2oct() must be supplied with a buffer long enough to
store the octet form. The return value provides the number of octets stored.
@@ -143,17 +179,18 @@ Calling the function with a NULL buffer will not perform the conversion but
will just return the required buffer length.
The function EC_KEY_priv2buf() allocates a buffer of suitable length and writes
-an EC_KEY to it in octet format. The allocated buffer is written to B<*pbuf>
+an EC_KEY to it in octet format. The allocated buffer is written to I<*pbuf>
and its length is returned. The caller must free up the allocated buffer with a
-call to OPENSSL_free(). Since the allocated buffer value is written to B<*pbuf>
-the B<pbuf> parameter B<MUST NOT> be B<NULL>.
+call to OPENSSL_free(). Since the allocated buffer value is written to I<*pbuf>
+the I<pbuf> parameter B<MUST NOT> be B<NULL>.
EC_KEY_priv2buf() converts an EC_KEY private key into an allocated buffer.
=head1 RETURN VALUES
-EC_KEY_new(), EC_KEY_new_by_curve_name() and EC_KEY_dup() return a pointer to
-the newly created EC_KEY object, or NULL on error.
+EC_KEY_new_ex(), EC_KEY_new(), EC_KEY_new_by_curve_name_ex(),
+EC_KEY_new_by_curve_name() and EC_KEY_dup() return a pointer to the newly
+created EC_KEY object, or NULL on error.
EC_KEY_get_flags() returns the flags associated with the EC_KEY object as an
integer.
@@ -182,17 +219,25 @@ of the buffer or 0 on error.
=head1 SEE ALSO
+L<EVP_PKEY_Q_keygen(3)>
L<crypto(7)>, L<EC_GROUP_new(3)>,
L<EC_GROUP_copy(3)>, L<EC_POINT_new(3)>,
L<EC_POINT_add(3)>,
L<EC_GFp_simple_method(3)>,
-L<d2i_ECPKParameters(3)>
+L<d2i_ECPKParameters(3)>,
+L<OSSL_LIB_CTX(3)>
+
+=head1 HISTORY
+
+EVP_EC_gen() was added in OpenSSL 3.0.
+All other functions described here were deprecated in OpenSSL 3.0.
+For replacement see L<EVP_PKEY-EC(7)>.
=head1 COPYRIGHT
Copyright 2013-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EC_POINT_add.pod b/doc/man3/EC_POINT_add.pod
index dc530757046f..97bd34c3932e 100644
--- a/doc/man3/EC_POINT_add.pod
+++ b/doc/man3/EC_POINT_add.pod
@@ -15,17 +15,21 @@ EC_POINT_add, EC_POINT_dbl, EC_POINT_invert, EC_POINT_is_at_infinity, EC_POINT_i
int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *p);
int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx);
int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx);
+ int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n,
+ const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx);
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx);
int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
EC_POINT *points[], BN_CTX *ctx);
int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, size_t num,
const EC_POINT *p[], const BIGNUM *m[], BN_CTX *ctx);
- int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n,
- const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx);
int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
int EC_GROUP_have_precompute_mult(const EC_GROUP *group);
-
=head1 DESCRIPTION
EC_POINT_add adds the two points B<a> and B<b> and places the result in B<r>. Similarly EC_POINT_dbl doubles the point B<a> and places the
@@ -41,19 +45,23 @@ EC_POINT_cmp compares the two supplied points and tests whether or not they are
The functions EC_POINT_make_affine and EC_POINTs_make_affine force the internal representation of the EC_POINT(s) into the affine
co-ordinate system. In the case of EC_POINTs_make_affine the value B<num> provides the number of points in the array B<points> to be
-forced.
+forced. These functions were deprecated in OpenSSL 3.0 and should no longer be used.
+Modern versions automatically perform this conversion when needed.
-EC_POINT_mul is a convenient interface to EC_POINTs_mul: it calculates the value generator * B<n> + B<q> * B<m> and stores the result in B<r>.
+EC_POINT_mul calculates the value generator * B<n> + B<q> * B<m> and stores the result in B<r>.
The value B<n> may be NULL in which case the result is just B<q> * B<m> (variable point multiplication). Alternatively, both B<q> and B<m> may be NULL, and B<n> non-NULL, in which case the result is just generator * B<n> (fixed point multiplication).
When performing a single fixed or variable point multiplication, the underlying implementation uses a constant time algorithm, when the input scalar (either B<n> or B<m>) is in the range [0, ec_group_order).
+Although deprecated in OpenSSL 3.0 and should no longer be used,
EC_POINTs_mul calculates the value generator * B<n> + B<q[0]> * B<m[0]> + ... + B<q[num-1]> * B<m[num-1]>. As for EC_POINT_mul the value B<n> may be NULL or B<num> may be zero.
When performing a fixed point multiplication (B<n> is non-NULL and B<num> is 0) or a variable point multiplication (B<n> is NULL and B<num> is 1), the underlying implementation uses a constant time algorithm, when the input scalar (either B<n> or B<m[0]>) is in the range [0, ec_group_order).
+Modern versions should instead use EC_POINT_mul(), combined (if needed) with EC_POINT_add() in such rare circumstances.
The function EC_GROUP_precompute_mult stores multiples of the generator for faster point multiplication, whilst
EC_GROUP_have_precompute_mult tests whether precomputation has already been done. See L<EC_GROUP_copy(3)> for information
-about the generator.
-
+about the generator. Precomputation functionality was deprecated in OpenSSL 3.0.
+Users of EC_GROUP_precompute_mult() and EC_GROUP_have_precompute_mult() should
+switch to named curves which OpenSSL has hardcoded lookup tables for.
=head1 RETURN VALUES
@@ -74,11 +82,17 @@ L<crypto(7)>, L<EC_GROUP_new(3)>, L<EC_GROUP_copy(3)>,
L<EC_POINT_new(3)>, L<EC_KEY_new(3)>,
L<EC_GFp_simple_method(3)>, L<d2i_ECPKParameters(3)>
+=head1 HISTORY
+
+EC_POINT_make_affine(), EC_POINTs_make_affine(), EC_POINTs_mul(),
+EC_GROUP_precompute_mult(), and EC_GROUP_have_precompute_mult()
+were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2013-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EC_POINT_new.pod b/doc/man3/EC_POINT_new.pod
index 5d2c3f2e9b22..f92cc2c8e229 100644
--- a/doc/man3/EC_POINT_new.pod
+++ b/doc/man3/EC_POINT_new.pod
@@ -38,16 +38,7 @@ EC_POINT_hex2point
void EC_POINT_clear_free(EC_POINT *point);
int EC_POINT_copy(EC_POINT *dst, const EC_POINT *src);
EC_POINT *EC_POINT_dup(const EC_POINT *src, const EC_GROUP *group);
- const EC_METHOD *EC_POINT_method_of(const EC_POINT *point);
int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point);
- int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
- EC_POINT *p,
- const BIGNUM *x, const BIGNUM *y,
- const BIGNUM *z, BN_CTX *ctx);
- int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
- const EC_POINT *p,
- BIGNUM *x, BIGNUM *y, BIGNUM *z,
- BN_CTX *ctx);
int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *p,
const BIGNUM *x, const BIGNUM *y,
BN_CTX *ctx);
@@ -56,6 +47,32 @@ EC_POINT_hex2point
int EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *p,
const BIGNUM *x, int y_bit,
BN_CTX *ctx);
+ size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *p,
+ point_conversion_form_t form,
+ unsigned char *buf, size_t len, BN_CTX *ctx);
+ size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point,
+ point_conversion_form_t form,
+ unsigned char **pbuf, BN_CTX *ctx);
+ int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *p,
+ const unsigned char *buf, size_t len, BN_CTX *ctx);
+ char *EC_POINT_point2hex(const EC_GROUP *group, const EC_POINT *p,
+ point_conversion_form_t form, BN_CTX *ctx);
+ EC_POINT *EC_POINT_hex2point(const EC_GROUP *group, const char *hex,
+ EC_POINT *p, BN_CTX *ctx);
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ const EC_METHOD *EC_POINT_method_of(const EC_POINT *point);
+ int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
+ EC_POINT *p,
+ const BIGNUM *x, const BIGNUM *y,
+ const BIGNUM *z, BN_CTX *ctx);
+ int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
+ const EC_POINT *p,
+ BIGNUM *x, BIGNUM *y, BIGNUM *z,
+ BN_CTX *ctx);
int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *p,
const BIGNUM *x, const BIGNUM *y,
BN_CTX *ctx);
@@ -76,24 +93,11 @@ EC_POINT_hex2point
EC_POINT *p,
const BIGNUM *x, int y_bit,
BN_CTX *ctx);
- size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *p,
- point_conversion_form_t form,
- unsigned char *buf, size_t len, BN_CTX *ctx);
- size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point,
- point_conversion_form_t form,
- unsigned char **pbuf, BN_CTX *ctx);
- int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *p,
- const unsigned char *buf, size_t len, BN_CTX *ctx);
BIGNUM *EC_POINT_point2bn(const EC_GROUP *group, const EC_POINT *p,
point_conversion_form_t form, BIGNUM *bn,
BN_CTX *ctx);
EC_POINT *EC_POINT_bn2point(const EC_GROUP *group, const BIGNUM *bn,
EC_POINT *p, BN_CTX *ctx);
- char *EC_POINT_point2hex(const EC_GROUP *group, const EC_POINT *p,
- point_conversion_form_t form, BN_CTX *ctx);
- EC_POINT *EC_POINT_hex2point(const EC_GROUP *group, const char *hex,
- EC_POINT *p, BN_CTX *ctx);
-
=head1 DESCRIPTION
@@ -114,6 +118,8 @@ EC_POINT_dup() creates a new B<EC_POINT> object and copies the content from
B<src> to the newly created B<EC_POINT> object.
EC_POINT_method_of() obtains the B<EC_METHOD> associated with B<point>.
+This function was deprecated in OpenSSL 3.0, since EC_METHOD is no longer a
+public concept.
A valid point on a curve is the special point at infinity. A point is set to
be at infinity by calling EC_POINT_set_to_infinity().
@@ -142,9 +148,13 @@ operations. A mapping exists between Jacobian projective co-ordinates and
affine co-ordinates. A Jacobian projective co-ordinate (x, y, z) can be written
as an affine co-ordinate as (x/(z^2), y/(z^3)). Conversion to Jacobian
projective from affine co-ordinates is simple. The co-ordinate (x, y) is mapped
-to (x, y, 1). To set or get the projective co-ordinates use
+to (x, y, 1). Although deprecated in OpenSSL 3.0 and should no longer be used,
+to set or get the projective co-ordinates in older versions use
EC_POINT_set_Jprojective_coordinates_GFp() and
EC_POINT_get_Jprojective_coordinates_GFp() respectively.
+Modern versions should instead use EC_POINT_set_affine_coordinates() and
+EC_POINT_get_affine_coordinates(), performing the conversion manually using the
+above maps in such rare circumstances.
Points can also be described in terms of their compressed co-ordinates. For a
point (x, y), for any given value for x such that the point is on the curve
@@ -241,11 +251,27 @@ L<crypto(7)>, L<EC_GROUP_new(3)>, L<EC_GROUP_copy(3)>,
L<EC_POINT_add(3)>, L<EC_KEY_new(3)>,
L<EC_GFp_simple_method(3)>, L<d2i_ECPKParameters(3)>
+=head1 HISTORY
+
+EC_POINT_method_of(),
+EC_POINT_set_Jprojective_coordinates_GFp(),
+EC_POINT_get_Jprojective_coordinates_GFp(),
+EC_POINT_set_affine_coordinates_GFp(), EC_POINT_get_affine_coordinates_GFp(),
+EC_POINT_set_compressed_coordinates_GFp(),
+EC_POINT_set_affine_coordinates_GF2m(), EC_POINT_get_affine_coordinates_GF2m(),
+EC_POINT_set_compressed_coordinates_GF2m(),
+EC_POINT_point2bn(), and EC_POINT_bn2point() were deprecated in OpenSSL 3.0.
+
+
+B<EC_POINT_set_affine_coordinates>, B<EC_POINT_get_affine_coordinates>,
+and B<EC_POINT_set_compressed_coordinates> were
+added in OpenSSL 1.1.1.
+
=head1 COPYRIGHT
-Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ENGINE_add.pod b/doc/man3/ENGINE_add.pod
index 34a640d20553..55e5d76fcdb8 100644
--- a/doc/man3/ENGINE_add.pod
+++ b/doc/man3/ENGINE_add.pod
@@ -46,6 +46,10 @@ ENGINE_unregister_digests
#include <openssl/engine.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
ENGINE *ENGINE_get_first(void);
ENGINE *ENGINE_get_last(void);
ENGINE *ENGINE_get_next(ENGINE *e);
@@ -154,14 +158,17 @@ ENGINE_unregister_digests
EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id,
UI_METHOD *ui_method, void *callback_data);
-Deprecated:
+The following function has been deprecated since OpenSSL 1.1.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
- #if OPENSSL_API_COMPAT < 0x10100000L
- void ENGINE_cleanup(void)
- #endif
+ void ENGINE_cleanup(void);
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use the provider APIs.
+
These functions create, manipulate, and use cryptographic modules in the
form of B<ENGINE> objects. These objects act as containers for
implementations of cryptographic algorithms, and support a
@@ -240,7 +247,7 @@ released on behalf of the caller.
To clarify a particular function's handling of references, one should
always consult that function's documentation "man" page, or failing that
-the openssl/engine.h header file includes some hints.
+the F<< <openssl/engine.h> >> header file includes some hints.
I<Functional references>
@@ -333,7 +340,7 @@ acceleration hardware attached to the machine or some such thing. There are
probably numerous other ways in which applications may prefer to handle
things, so we will simply illustrate the consequences as they apply to a
couple of simple cases and leave developers to consider these and the
-source code to openssl's builtin utilities as guides.
+source code to openssl's built-in utilities as guides.
If no ENGINE API functions are called within an application, then OpenSSL
will not allocate any internal resources. Prior to OpenSSL 1.1.0, however,
@@ -346,7 +353,7 @@ Here we'll assume an application has been configured by its user or admin
to want to use the "ACME" ENGINE if it is available in the version of
OpenSSL the application was compiled with. If it is available, it should be
used by default for all RSA, DSA, and symmetric cipher operations, otherwise
-OpenSSL should use its builtin software as per usual. The following code
+OpenSSL should use its built-in software as per usual. The following code
illustrates how to approach this;
ENGINE *e;
@@ -374,7 +381,7 @@ illustrates how to approach this;
/* Release the structural reference from ENGINE_by_id() */
ENGINE_free(e);
-I<Automatically using builtin ENGINE implementations>
+I<Automatically using built-in ENGINE implementations>
Here we'll assume we want to load and register all ENGINE implementations
bundled with OpenSSL, such that for any cryptographic algorithm required by
@@ -422,7 +429,7 @@ calling ENGINE_init(). The other class of commands consist of settings or
operations that tweak certain behaviour or cause certain operations to take
place, and these commands may work either before or after ENGINE_init(), or
in some cases both. ENGINE implementations should provide indications of
-this in the descriptions attached to builtin control commands and/or in
+this in the descriptions attached to built-in control commands and/or in
external product documentation.
I<Issuing control commands to an ENGINE>
@@ -491,10 +498,10 @@ and input parameters of the control commands supported by an ENGINE using a
structural reference. Note that some control commands are defined by OpenSSL
itself and it will intercept and handle these control commands on behalf of the
ENGINE, i.e. the ENGINE's ctrl() handler is not used for the control command.
-openssl/engine.h defines an index, ENGINE_CMD_BASE, that all control commands
-implemented by ENGINEs should be numbered from. Any command value lower than
-this symbol is considered a "generic" command is handled directly by the
-OpenSSL core routines.
+F<< <openssl/engine.h> >> defines an index, ENGINE_CMD_BASE, that all control
+commands implemented by ENGINEs should be numbered from. Any command value
+lower than this symbol is considered a "generic" command is handled directly
+by the OpenSSL core routines.
It is using these "core" control commands that one can discover the control
commands implemented by a given ENGINE, specifically the commands:
@@ -650,6 +657,8 @@ L<RAND_bytes(3)>, L<config(5)>
=head1 HISTORY
+All of these functions were deprecated in OpenSSL 3.0.
+
ENGINE_cleanup() was deprecated in OpenSSL 1.1.0 by the automatic cleanup
done by OPENSSL_cleanup()
and should not be used.
@@ -658,7 +667,7 @@ and should not be used.
Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ERR_GET_LIB.pod b/doc/man3/ERR_GET_LIB.pod
index 5602a8e75424..1d7fa587f9df 100644
--- a/doc/man3/ERR_GET_LIB.pod
+++ b/doc/man3/ERR_GET_LIB.pod
@@ -2,7 +2,7 @@
=head1 NAME
-ERR_GET_LIB, ERR_GET_FUNC, ERR_GET_REASON, ERR_FATAL_ERROR
+ERR_GET_LIB, ERR_GET_REASON, ERR_FATAL_ERROR
- get information from error codes
=head1 SYNOPSIS
@@ -11,8 +11,6 @@ ERR_GET_LIB, ERR_GET_FUNC, ERR_GET_REASON, ERR_FATAL_ERROR
int ERR_GET_LIB(unsigned long e);
- int ERR_GET_FUNC(unsigned long e);
-
int ERR_GET_REASON(unsigned long e);
int ERR_FATAL_ERROR(unsigned long e);
@@ -20,30 +18,37 @@ ERR_GET_LIB, ERR_GET_FUNC, ERR_GET_REASON, ERR_FATAL_ERROR
=head1 DESCRIPTION
The error code returned by ERR_get_error() consists of a library
-number, function code and reason code. ERR_GET_LIB(), ERR_GET_FUNC()
+number and reason code. ERR_GET_LIB()
and ERR_GET_REASON() can be used to extract these.
ERR_FATAL_ERROR() indicates whether a given error code is a fatal error.
-The library number and function code describe where the error
+The library number describes where the error
occurred, the reason code is the information about what went wrong.
-Each sub-library of OpenSSL has a unique library number; function and
-reason codes are unique within each sub-library. Note that different
-libraries may use the same value to signal different functions and
-reasons.
+Each sub-library of OpenSSL has a unique library number; the
+reason code is unique within each sub-library. Note that different
+libraries may use the same value to signal different reasons.
B<ERR_R_...> reason codes such as B<ERR_R_MALLOC_FAILURE> are globally
unique. However, when checking for sub-library specific reason codes,
be sure to also compare the library number.
-ERR_GET_LIB(), ERR_GET_FUNC(), ERR_GET_REASON(), and ERR_FATAL_ERROR()
- are macros.
+ERR_GET_LIB(), ERR_GET_REASON(), and ERR_FATAL_ERROR() are macros.
=head1 RETURN VALUES
-The library number, function code, reason code, and whether the error
+The library number, reason code, and whether the error
is fatal, respectively.
+Starting with OpenSSL 3.0.0, the function code is always set to zero.
+
+=head1 NOTES
+
+Applications should not make control flow decisions based on specific error
+codes. Error codes are subject to change at any time (even in patch releases of
+OpenSSL). A particular error code can only be considered meaningful for control
+flow decisions if it is explicitly documented as such. New failure codes may
+still appear at any time.
=head1 SEE ALSO
@@ -51,14 +56,15 @@ L<ERR_get_error(3)>
=head1 HISTORY
-ERR_GET_LIB(), ERR_GET_FUNC() and ERR_GET_REASON() are available in
-all versions of OpenSSL.
+ERR_GET_LIB() and ERR_GET_REASON() are available in all versions of OpenSSL.
+
+ERR_GET_FUNC() was removed in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ERR_clear_error.pod b/doc/man3/ERR_clear_error.pod
index c8766158c269..5abbba8768de 100644
--- a/doc/man3/ERR_clear_error.pod
+++ b/doc/man3/ERR_clear_error.pod
@@ -26,7 +26,7 @@ L<ERR_get_error(3)>
Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ERR_error_string.pod b/doc/man3/ERR_error_string.pod
index 695eaf20f02e..42b192178a0a 100644
--- a/doc/man3/ERR_error_string.pod
+++ b/doc/man3/ERR_error_string.pod
@@ -14,9 +14,12 @@ error message
void ERR_error_string_n(unsigned long e, char *buf, size_t len);
const char *ERR_lib_error_string(unsigned long e);
- const char *ERR_func_error_string(unsigned long e);
const char *ERR_reason_error_string(unsigned long e);
+Deprecated in OpenSSL 3.0:
+
+ const char *ERR_func_error_string(unsigned long e);
+
=head1 DESCRIPTION
ERR_error_string() generates a human-readable string representing the
@@ -33,13 +36,12 @@ For ERR_error_string_n(), I<buf> may not be B<NULL>.
The string will have the following format:
- error:[error code]:[library name]:[function name]:[reason string]
+ error:[error code]:[library name]::[reason string]
-I<error code> is an 8 digit hexadecimal number, I<library name>,
-I<function name> and I<reason string> are ASCII text.
+I<error code> is an 8 digit hexadecimal number, I<library name> and
+I<reason string> are ASCII text.
-ERR_lib_error_string(), ERR_func_error_string() and
-ERR_reason_error_string() return the library name, function
+ERR_lib_error_string() and ERR_reason_error_string() return the library
name and reason string respectively.
If there is no text string registered for the given error code,
@@ -53,20 +55,25 @@ all error codes currently in the queue.
ERR_error_string() returns a pointer to a static buffer containing the
string if I<buf> B<== NULL>, I<buf> otherwise.
-ERR_lib_error_string(), ERR_func_error_string() and
-ERR_reason_error_string() return the strings, and B<NULL> if
-none is registered for the error code.
+ERR_lib_error_string() and ERR_reason_error_string() return the strings,
+and B<NULL> if none is registered for the error code.
+
+ERR_func_error_string() returns NULL.
=head1 SEE ALSO
L<ERR_get_error(3)>,
L<ERR_print_errors(3)>
+=head1 HISTORY
+
+ERR_func_error_string() became deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ERR_get_error.pod b/doc/man3/ERR_get_error.pod
index fc155ad08199..038296ac64cc 100644
--- a/doc/man3/ERR_get_error.pod
+++ b/doc/man3/ERR_get_error.pod
@@ -4,8 +4,11 @@
ERR_get_error, ERR_peek_error, ERR_peek_last_error,
ERR_get_error_line, ERR_peek_error_line, ERR_peek_last_error_line,
-ERR_get_error_line_data, ERR_peek_error_line_data,
-ERR_peek_last_error_line_data - obtain error code and data
+ERR_peek_error_func, ERR_peek_last_error_func,
+ERR_peek_error_data, ERR_peek_last_error_data,
+ERR_get_error_all, ERR_peek_error_all, ERR_peek_last_error_all,
+ERR_get_error_line_data, ERR_peek_error_line_data, ERR_peek_last_error_line_data
+- obtain error code and data
=head1 SYNOPSIS
@@ -15,10 +18,30 @@ ERR_peek_last_error_line_data - obtain error code and data
unsigned long ERR_peek_error(void);
unsigned long ERR_peek_last_error(void);
- unsigned long ERR_get_error_line(const char **file, int *line);
unsigned long ERR_peek_error_line(const char **file, int *line);
unsigned long ERR_peek_last_error_line(const char **file, int *line);
+ unsigned long ERR_peek_error_func(const char **func);
+ unsigned long ERR_peek_last_error_func(const char **func);
+
+ unsigned long ERR_peek_error_data(const char **data, int *flags);
+ unsigned long ERR_peek_last_error_data(const char **data, int *flags);
+
+ unsigned long ERR_get_error_all(const char **file, int *line,
+ const char **func,
+ const char **data, int *flags);
+ unsigned long ERR_peek_error_all(const char **file, int *line,
+ const char **func,
+ const char **data, int *flags);
+ unsigned long ERR_peek_last_error_all(const char **file, int *line,
+ const char *func,
+ const char **data, int *flags);
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ unsigned long ERR_get_error_line(const char **file, int *line);
unsigned long ERR_get_error_line_data(const char **file, int *line,
const char **data, int *flags);
unsigned long ERR_peek_error_line_data(const char **file, int *line,
@@ -29,7 +52,7 @@ ERR_peek_last_error_line_data - obtain error code and data
=head1 DESCRIPTION
ERR_get_error() returns the earliest error code from the thread's error
-queue and removes the entry. This function can be called repeatedly
+queue and removes the entry. This function can be called repeatedly
until there are no more error codes to return.
ERR_peek_error() returns the earliest error code from the thread's
@@ -38,23 +61,52 @@ error queue without modifying it.
ERR_peek_last_error() returns the latest error code from the thread's
error queue without modifying it.
-See L<ERR_GET_LIB(3)> for obtaining information about
-location and reason of the error, and
-L<ERR_error_string(3)> for human-readable error
-messages.
-
-ERR_get_error_line(), ERR_peek_error_line() and
-ERR_peek_last_error_line() are the same as the above, but they
-additionally store the filename and line number where
-the error occurred in *B<file> and *B<line>, unless these are B<NULL>.
-
-ERR_get_error_line_data(), ERR_peek_error_line_data() and
-ERR_peek_last_error_line_data() store additional data and flags
-associated with the error code in *B<data>
-and *B<flags>, unless these are B<NULL>. *B<data> contains a string
-if *B<flags>&B<ERR_TXT_STRING> is true.
-
-An application B<MUST NOT> free the *B<data> pointer (or any other pointers
+See L<ERR_GET_LIB(3)> for obtaining further specific information
+such as the reason of the error,
+and L<ERR_error_string(3)> for human-readable error messages.
+
+ERR_get_error_all() is the same as ERR_get_error(), but on success it
+additionally stores the filename, line number and function where the error
+occurred in *I<file>, *I<line> and *I<func>, and also extra text and flags
+in *I<data>, *I<flags>. If any of those parameters are NULL, it will not
+be changed.
+An unset filename is indicated as "", i.e. an empty string.
+An unset line number is indicated as 0.
+An unset function name is indicated as "", i.e. an empty string.
+
+A pointer returned this way by these functions and the ones below
+is valid until the respective entry is overwritten in the error queue.
+
+ERR_peek_error_line() and ERR_peek_last_error_line() are the same as
+ERR_peek_error() and ERR_peek_last_error(), but on success they additionally
+store the filename and line number where the error occurred in *I<file> and
+*I<line>, as far as they are not NULL.
+An unset filename is indicated as "", i.e., an empty string.
+An unset line number is indicated as 0.
+
+ERR_peek_error_func() and ERR_peek_last_error_func() are the same as
+ERR_peek_error() and ERR_peek_last_error(), but on success they additionally
+store the name of the function where the error occurred in *I<func>, unless
+it is NULL.
+An unset function name is indicated as "".
+
+ERR_peek_error_data() and ERR_peek_last_error_data() are the same as
+ERR_peek_error() and ERR_peek_last_error(), but on success they additionally
+store additional data and flags associated with the error code in *I<data>
+and *I<flags>, as far as they are not NULL.
+Unset data is indicated as "".
+In this case the value given for the flag is irrelevant (and equals 0).
+*I<data> contains a string if *I<flags>&B<ERR_TXT_STRING> is true.
+
+ERR_peek_error_all() and ERR_peek_last_error_all() are combinations of all
+of the above.
+
+ERR_get_error_line(), ERR_get_error_line_data(), ERR_peek_error_line_data()
+and ERR_peek_last_error_line_data() are older variants of ERR_get_error_all(),
+ERR_peek_error_all() and ERR_peek_last_error_all(), and may give confusing
+results. They should no longer be used and are therefore deprecated.
+
+An application B<MUST NOT> free the *I<data> pointer (or any other pointers
returned by these functions) with OPENSSL_free() as freeing is handled
automatically by the error library.
@@ -67,11 +119,22 @@ The error code, or 0 if there is no error in the queue.
L<ERR_error_string(3)>,
L<ERR_GET_LIB(3)>
+=head1 HISTORY
+
+ERR_peek_error_func(), ERR_peek_last_error_func(),
+ERR_peek_error_data(), ERR_peek_last_error_data(),
+ERR_peek_error_all() and ERR_peek_last_error_all()
+were added in OpenSSL 3.0.
+
+ERR_get_error_line(), ERR_get_error_line_data(), ERR_peek_error_line_data()
+and ERR_peek_last_error_line_data() became deprecated in OpenSSL 3.0.
+
+
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ERR_load_crypto_strings.pod b/doc/man3/ERR_load_crypto_strings.pod
index c503241d16c4..ef871896494c 100644
--- a/doc/man3/ERR_load_crypto_strings.pod
+++ b/doc/man3/ERR_load_crypto_strings.pod
@@ -7,20 +7,18 @@ load and free error strings
=head1 SYNOPSIS
-Deprecated:
+The following functions have been deprecated since OpenSSL 1.1.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
#include <openssl/err.h>
- #if OPENSSL_API_COMPAT < 0x10100000L
void ERR_load_crypto_strings(void);
void ERR_free_strings(void);
- #endif
#include <openssl/ssl.h>
- #if OPENSSL_API_COMPAT < 0x10100000L
void SSL_load_error_strings(void);
- #endif
=head1 DESCRIPTION
@@ -48,9 +46,9 @@ OPENSSL_init_crypto() and OPENSSL_init_ssl() and should not be used.
=head1 COPYRIGHT
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ERR_load_strings.pod b/doc/man3/ERR_load_strings.pod
index 2b21a3bc6d96..f291644bb361 100644
--- a/doc/man3/ERR_load_strings.pod
+++ b/doc/man3/ERR_load_strings.pod
@@ -34,7 +34,7 @@ ERR_PACK() is a macro.
The last entry in the array is {0,0}.
ERR_get_next_error_library() can be used to assign library numbers
-to user libraries at runtime.
+to user libraries at run time.
=head1 RETURN VALUES
@@ -50,7 +50,7 @@ L<ERR_load_strings(3)>
Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ERR_new.pod b/doc/man3/ERR_new.pod
new file mode 100644
index 000000000000..4c18f76ef396
--- /dev/null
+++ b/doc/man3/ERR_new.pod
@@ -0,0 +1,78 @@
+=pod
+
+=head1 NAME
+
+ERR_new, ERR_set_debug, ERR_set_error, ERR_vset_error
+- Error recording building blocks
+
+=head1 SYNOPSIS
+
+ #include <openssl/err.h>
+
+ void ERR_new(void);
+ void ERR_set_debug(const char *file, int line, const char *func);
+ void ERR_set_error(int lib, int reason, const char *fmt, ...);
+ void ERR_vset_error(int lib, int reason, const char *fmt, va_list args);
+
+=head1 DESCRIPTION
+
+The functions described here are generally not used directly, but
+rather through macros such as L<ERR_raise(3)>.
+They can still be useful for anyone that wants to make their own
+macros.
+
+ERR_new() allocates a new slot in the thread's error queue.
+
+ERR_set_debug() sets the debug information related to the current
+error in the thread's error queue.
+The values that can be given are the filename I<file>, line in the
+file I<line> and the name of the function I<func> where the error
+occurred.
+The names must be constant, this function will only save away the
+pointers, not copy the strings.
+
+ERR_set_error() sets the error information, which are the library
+number I<lib> and the reason code I<reason>, and additional data as a
+format string I<fmt> and an arbitrary number of arguments.
+The additional data is processed with L<BIO_snprintf(3)> to form the
+additional data string, which is allocated and store in the error
+record.
+
+ERR_vset_error() works like ERR_set_error(), but takes a B<va_list>
+argument instead of a variable number of arguments.
+
+=head1 RETURN VALUES
+
+ERR_new, ERR_set_debug, ERR_set_error and ERR_vset_error
+do not return any values.
+
+=head1 NOTES
+
+The library number is unique to each unit that records errors.
+OpenSSL has a number of preallocated ones for its own uses, but
+others may allocate their own library number dynamically with
+L<ERR_get_next_error_library(3)>.
+
+Reason codes are unique within each library, and may have an
+associated set of strings as a short description of the reason.
+For dynamically allocated library numbers, reason strings are recorded
+with L<ERR_load_strings(3)>.
+
+Provider authors are supplied with core versions of these functions,
+see L<provider-base(7)>.
+
+=head1 SEE ALSO
+
+L<ERR_raise(3)>, L<ERR_get_next_error_library(3)>,
+L<ERR_load_strings(3)>, L<BIO_snprintf(3)>, L<provider-base(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/ERR_print_errors.pod b/doc/man3/ERR_print_errors.pod
index 78a4b6a8d910..b09c09838955 100644
--- a/doc/man3/ERR_print_errors.pod
+++ b/doc/man3/ERR_print_errors.pod
@@ -11,8 +11,8 @@ ERR_print_errors, ERR_print_errors_fp, ERR_print_errors_cb
void ERR_print_errors(BIO *bp);
void ERR_print_errors_fp(FILE *fp);
- void ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u), void *u)
-
+ void ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u),
+ void *u);
=head1 DESCRIPTION
@@ -51,7 +51,7 @@ L<ERR_get_error(3)>
Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ERR_put_error.pod b/doc/man3/ERR_put_error.pod
index ee6a61ffe2c2..1078c31b636a 100644
--- a/doc/man3/ERR_put_error.pod
+++ b/doc/man3/ERR_put_error.pod
@@ -1,28 +1,67 @@
=pod
+=for openssl foreign manual errno(3)
+
=head1 NAME
-ERR_put_error, ERR_add_error_data, ERR_add_error_vdata - record an error
+ERR_raise, ERR_raise_data,
+ERR_put_error, ERR_add_error_data, ERR_add_error_vdata,
+ERR_add_error_txt, ERR_add_error_mem_bio
+- record an error
=head1 SYNOPSIS
#include <openssl/err.h>
- void ERR_put_error(int lib, int func, int reason, const char *file, int line);
+ void ERR_raise(int lib, int reason);
+ void ERR_raise_data(int lib, int reason, const char *fmt, ...);
void ERR_add_error_data(int num, ...);
void ERR_add_error_vdata(int num, va_list arg);
+ void ERR_add_error_txt(const char *sep, const char *txt);
+ void ERR_add_error_mem_bio(const char *sep, BIO *bio);
+
+The following function has been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ void ERR_put_error(int lib, int func, int reason, const char *file, int line);
=head1 DESCRIPTION
+ERR_raise() adds a new error to the thread's error queue. The
+error occurred in the library B<lib> for the reason given by the
+B<reason> code. Furthermore, the name of the file, the line, and name
+of the function where the error occurred is saved with the error
+record.
+
+ERR_raise_data() does the same thing as ERR_raise(), but also lets the
+caller specify additional information as a format string B<fmt> and an
+arbitrary number of values, which are processed with L<BIO_snprintf(3)>.
+
ERR_put_error() adds an error code to the thread's error queue. It
signals that the error of reason code B<reason> occurred in function
B<func> of library B<lib>, in line number B<line> of B<file>.
This function is usually called by a macro.
ERR_add_error_data() associates the concatenation of its B<num> string
-arguments with the error code added last.
+arguments as additional data with the error code added last.
ERR_add_error_vdata() is similar except the argument is a B<va_list>.
+Multiple calls to these functions append to the current top of the error queue.
+The total length of the string data per error is limited to 4096 characters.
+
+ERR_add_error_txt() appends the given text string as additional data to the
+last error queue entry, after inserting the optional separator string if it is
+not NULL and the top error entry does not yet have additional data.
+In case the separator is at the end of the text it is not appended to the data.
+The B<sep> argument may be for instance "\n" to insert a line break when needed.
+If the associated data would become more than 4096 characters long
+(which is the limit given above)
+it is split over sufficiently many new copies of the last error queue entry.
+
+ERR_add_error_mem_bio() is the same as ERR_add_error_txt() except that
+the text string is taken from the given memory BIO.
+It appends '\0' to the BIO contents if not already NUL-terminated.
L<ERR_load_strings(3)> can be used to register
error strings so that the application can a generate human-readable
@@ -30,44 +69,119 @@ error messages for the error code.
=head2 Reporting errors
-Each sub-library has a specific macro XXXerr() that is used to report
-errors. Its first argument is a function code B<XXX_F_...>, the second
-argument is a reason code B<XXX_R_...>. Function codes are derived
-from the function names; reason codes consist of textual error
+=head3 OpenSSL library reports
+
+Each OpenSSL sub-library has library code B<ERR_LIB_XXX> and has its own set
+of reason codes B<XXX_R_...>. These are both passed in combination to
+ERR_raise() and ERR_raise_data(), and the combination ultimately produces
+the correct error text for the reported error.
+
+All these macros and the numbers they have as values are specific to
+OpenSSL's libraries. OpenSSL reason codes normally consist of textual error
descriptions. For example, the function ssl3_read_bytes() reports a
"handshake failure" as follows:
- SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
+
+There are two exceptions:
+
+=over 4
+
+=item B<ERR_LIB_SYS>
+
+This "library code" indicates that a system error is being reported. In
+this case, the reason code given to ERR_raise() and ERR_raise_data() I<must>
+be L<errno(3)>.
+
+ ERR_raise(ERR_LIB_SYS, errno);
+
+=item B<ERR_R_XXX>
+
+This set of error codes is considered global, and may be used in combination
+with any sub-library code.
+
+ ERR_raise(ERR_LIB_RSA, ERR_R_PASSED_INVALID_ARGUMENT);
+
+=back
+
+=head3 Other pieces of software
-Function and reason codes should consist of uppercase characters,
-numbers and underscores only. The error file generation script translates
-function codes into function names by looking in the header files
-for an appropriate function name, if none is found it just uses
-the capitalized form such as "SSL3_READ_BYTES" in the above example.
+Other pieces of software that may want to use OpenSSL's error reporting
+system, such as engines or applications, must normally get their own
+numbers.
-The trailing section of a reason code (after the "_R_") is translated
-into lowercase and underscores changed to spaces.
+=over 4
+
+=item *
+
+To get a "library" code, call L<ERR_get_next_error_library(3)>; this gives
+the calling code a dynamic number, usable for the duration of the process.
+
+=item *
+
+Reason codes for each such "library" are determined or generated by the
+authors of that code. They must be numbers in the range 1 to 524287 (in
+other words, they must be nonzero unsigned 18 bit integers).
+
+=back
+
+The exceptions mentioned in L</OpenSSL library reports> above are valid for
+other pieces of software, i.e. they may use B<ERR_LIB_SYS> to report system
+errors:
+
+ ERR_raise(ERR_LIB_SYS, errno);
+
+... and they may use B<ERR_R_XXX> macros together with their own "library"
+code.
+
+ int app_lib_code = ERR_get_next_error_library();
+
+ /* ... */
+
+ ERR_raise(app_lib_code, ERR_R_PASSED_INVALID_ARGUMENT);
+
+=begin comment
+
+[These are OpenSSL specific recommendations]
+
+Reason codes should consist of uppercase characters, numbers and underscores
+only. The error file generation script translates the trailing section of a
+reason code (after the "_R_") into lowercase with underscores changed to
+spaces.
Although a library will normally report errors using its own specific
-XXXerr macro, another library's macro can be used. This is normally
-only done when a library wants to include ASN1 code which must use
-the ASN1err() macro.
+B<ERR_LIB_XXX> macro, another library's macro can be used, together with
+that other library's reason codes. This is normally only done when a library
+wants to include ASN1 code which must be combined with B<ERR_LIB_ASN1>
+macro.
+=end comment
=head1 RETURN VALUES
-ERR_put_error() and ERR_add_error_data() return
-no values.
+ERR_raise(), ERR_raise_data(), ERR_put_error(),
+ERR_add_error_data(), ERR_add_error_vdata()
+ERR_add_error_txt(), and ERR_add_error_mem_bio()
+return no values.
+
+=head1 NOTES
+
+ERR_raise(), ERR_raise() and ERR_put_error() are implemented as macros.
=head1 SEE ALSO
-L<ERR_load_strings(3)>
+L<ERR_load_strings(3)>, L<ERR_get_next_error_library(3)>
+
+=head1 HISTORY
+
+ERR_raise, ERR_raise_data, ERR_add_error_txt() and ERR_add_error_mem_bio()
+were added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ERR_remove_state.pod b/doc/man3/ERR_remove_state.pod
index 8f4d3fcafa4e..f5f6ffbb49bb 100644
--- a/doc/man3/ERR_remove_state.pod
+++ b/doc/man3/ERR_remove_state.pod
@@ -6,15 +6,17 @@ ERR_remove_thread_state, ERR_remove_state - DEPRECATED
=head1 SYNOPSIS
-Deprecated:
+The following function has been deprecated since OpenSSL 1.0.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
- #if OPENSSL_API_COMPAT < 0x10000000L
void ERR_remove_state(unsigned long tid);
- #endif
- #if OPENSSL_API_COMPAT < 0x10100000L
+The following function has been deprecated since OpenSSL 1.1.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
void ERR_remove_thread_state(void *tid);
- #endif
=head1 DESCRIPTION
@@ -39,9 +41,9 @@ and should not be used.
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/ERR_set_mark.pod b/doc/man3/ERR_set_mark.pod
index b3afea81e402..e61d5c61edd4 100644
--- a/doc/man3/ERR_set_mark.pod
+++ b/doc/man3/ERR_set_mark.pod
@@ -2,15 +2,16 @@
=head1 NAME
-ERR_set_mark, ERR_pop_to_mark - set marks and pop errors until mark
+ERR_set_mark, ERR_clear_last_mark, ERR_pop_to_mark
+- set mark, clear mark and pop errors until mark
=head1 SYNOPSIS
#include <openssl/err.h>
int ERR_set_mark(void);
-
int ERR_pop_to_mark(void);
+ int ERR_clear_last_mark(void);
=head1 DESCRIPTION
@@ -20,18 +21,20 @@ is one.
ERR_pop_to_mark() will pop the top of the error stack until a mark is found.
The mark is then removed. If there is no mark, the whole stack is removed.
+ERR_clear_last_mark() removes the last mark added if there is one.
+
=head1 RETURN VALUES
ERR_set_mark() returns 0 if the error stack is empty, otherwise 1.
-ERR_pop_to_mark() returns 0 if there was no mark in the error stack, which
-implies that the stack became empty, otherwise 1.
+ERR_clear_last_mark() and ERR_pop_to_mark() return 0 if there was no mark in the
+error stack, which implies that the stack became empty, otherwise 1.
=head1 COPYRIGHT
-Copyright 2003-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2003-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_ASYM_CIPHER_free.pod b/doc/man3/EVP_ASYM_CIPHER_free.pod
new file mode 100644
index 000000000000..c158ec1ae74a
--- /dev/null
+++ b/doc/man3/EVP_ASYM_CIPHER_free.pod
@@ -0,0 +1,112 @@
+=pod
+
+=head1 NAME
+
+EVP_ASYM_CIPHER_fetch, EVP_ASYM_CIPHER_free, EVP_ASYM_CIPHER_up_ref,
+EVP_ASYM_CIPHER_is_a, EVP_ASYM_CIPHER_get0_provider,
+EVP_ASYM_CIPHER_do_all_provided, EVP_ASYM_CIPHER_names_do_all,
+EVP_ASYM_CIPHER_get0_name, EVP_ASYM_CIPHER_get0_description,
+EVP_ASYM_CIPHER_gettable_ctx_params, EVP_ASYM_CIPHER_settable_ctx_params
+- Functions to manage EVP_ASYM_CIPHER algorithm objects
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ EVP_ASYM_CIPHER *EVP_ASYM_CIPHER_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties);
+ void EVP_ASYM_CIPHER_free(EVP_ASYM_CIPHER *cipher);
+ int EVP_ASYM_CIPHER_up_ref(EVP_ASYM_CIPHER *cipher);
+ const char *EVP_ASYM_CIPHER_get0_name(const EVP_ASYM_CIPHER *cipher);
+ int EVP_ASYM_CIPHER_is_a(const EVP_ASYM_CIPHER *cipher, const char *name);
+ OSSL_PROVIDER *EVP_ASYM_CIPHER_get0_provider(const EVP_ASYM_CIPHER *cipher);
+ void EVP_ASYM_CIPHER_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_ASYM_CIPHER *cipher,
+ void *arg),
+ void *arg);
+ int EVP_ASYM_CIPHER_names_do_all(const EVP_ASYM_CIPHER *cipher,
+ void (*fn)(const char *name, void *data),
+ void *data);
+ const char *EVP_ASYM_CIPHER_get0_description(const EVP_ASYM_CIPHER *cipher);
+ const OSSL_PARAM *EVP_ASYM_CIPHER_gettable_ctx_params(const EVP_ASYM_CIPHER *cip);
+ const OSSL_PARAM *EVP_ASYM_CIPHER_settable_ctx_params(const EVP_ASYM_CIPHER *cip);
+
+=head1 DESCRIPTION
+
+EVP_ASYM_CIPHER_fetch() fetches the implementation for the given
+B<algorithm> from any provider offering it, within the criteria given
+by the B<properties> and in the scope of the given library context B<ctx> (see
+L<OSSL_LIB_CTX(3)>). The algorithm will be one offering functions for performing
+asymmetric cipher related tasks such as asymmetric encryption and decryption.
+See L<crypto(7)/ALGORITHM FETCHING> for further information.
+
+The returned value must eventually be freed with EVP_ASYM_CIPHER_free().
+
+EVP_ASYM_CIPHER_free() decrements the reference count for the B<EVP_ASYM_CIPHER>
+structure. Typically this structure will have been obtained from an earlier call
+to EVP_ASYM_CIPHER_fetch(). If the reference count drops to 0 then the
+structure is freed.
+
+EVP_ASYM_CIPHER_up_ref() increments the reference count for an
+B<EVP_ASYM_CIPHER> structure.
+
+EVP_ASYM_CIPHER_is_a() returns 1 if I<cipher> is an implementation of an
+algorithm that's identifiable with I<name>, otherwise 0.
+
+EVP_ASYM_CIPHER_get0_provider() returns the provider that I<cipher> was
+fetched from.
+
+EVP_ASYM_CIPHER_do_all_provided() traverses all EVP_ASYM_CIPHERs implemented by
+all activated providers in the given library context I<libctx>, and for each of
+the implementations, calls the given function I<fn> with the implementation
+method and the given I<arg> as argument.
+
+EVP_ASYM_CIPHER_get0_name() returns the algorithm name from the provided
+implementation for the given I<cipher>. Note that the I<cipher> may have
+multiple synonyms associated with it. In this case the first name from the
+algorithm definition is returned. Ownership of the returned string is retained
+by the I<cipher> object and should not be freed by the caller.
+
+EVP_ASYM_CIPHER_names_do_all() traverses all names for I<cipher>, and calls
+I<fn> with each name and I<data>.
+
+EVP_ASYM_CIPHER_get0_description() returns a description of the I<cipher>,
+meant for display and human consumption. The description is at the
+discretion of the I<cipher> implementation.
+
+EVP_ASYM_CIPHER_gettable_ctx_params() and EVP_ASYM_CIPHER_settable_ctx_params()
+return a constant L<OSSL_PARAM(3)> array that describes the names and types of key
+parameters that can be retrieved or set by a key encryption algorithm using
+L<EVP_PKEY_CTX_get_params(3)> and L<EVP_PKEY_CTX_set_params(3)>.
+
+=head1 RETURN VALUES
+
+EVP_ASYM_CIPHER_fetch() returns a pointer to an B<EVP_ASYM_CIPHER> for success
+or B<NULL> for failure.
+
+EVP_ASYM_CIPHER_up_ref() returns 1 for success or 0 otherwise.
+
+EVP_ASYM_CIPHER_names_do_all() returns 1 if the callback was called for all
+names. A return value of 0 means that the callback was not called for any names.
+
+EVP_ASYM_CIPHER_gettable_ctx_params() and EVP_ASYM_CIPHER_settable_ctx_params()
+return a constant L<OSSL_PARAM(3)> array or NULL on error.
+
+=head1 SEE ALSO
+
+L<crypto(7)/ALGORITHM FETCHING>, L<OSSL_PROVIDER(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_BytesToKey.pod b/doc/man3/EVP_BytesToKey.pod
index 8d49648f1fe4..002af0eebee7 100644
--- a/doc/man3/EVP_BytesToKey.pod
+++ b/doc/man3/EVP_BytesToKey.pod
@@ -70,7 +70,7 @@ L<EVP_EncryptInit(3)>
Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_CIPHER_CTX_get_cipher_data.pod b/doc/man3/EVP_CIPHER_CTX_get_cipher_data.pod
index 3a57fcdb677a..efb2aca1b959 100644
--- a/doc/man3/EVP_CIPHER_CTX_get_cipher_data.pod
+++ b/doc/man3/EVP_CIPHER_CTX_get_cipher_data.pod
@@ -43,7 +43,7 @@ functions were added in OpenSSL 1.1.0.
Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_CIPHER_CTX_get_original_iv.pod b/doc/man3/EVP_CIPHER_CTX_get_original_iv.pod
new file mode 100644
index 000000000000..393930cf388e
--- /dev/null
+++ b/doc/man3/EVP_CIPHER_CTX_get_original_iv.pod
@@ -0,0 +1,74 @@
+=pod
+
+=head1 NAME
+
+EVP_CIPHER_CTX_get_original_iv, EVP_CIPHER_CTX_get_updated_iv,
+EVP_CIPHER_CTX_iv, EVP_CIPHER_CTX_original_iv,
+EVP_CIPHER_CTX_iv_noconst - Routines to inspect EVP_CIPHER_CTX IV data
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_CIPHER_CTX_get_original_iv(EVP_CIPHER_CTX *ctx, void *buf, size_t len);
+ int EVP_CIPHER_CTX_get_updated_iv(EVP_CIPHER_CTX *ctx, void *buf, size_t len);
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx);
+ const unsigned char *EVP_CIPHER_CTX_original_iv(const EVP_CIPHER_CTX *ctx);
+ unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx);
+
+=head1 DESCRIPTION
+
+EVP_CIPHER_CTX_get_original_iv() and EVP_CIPHER_CTX_get_updated_iv() copy
+initialization vector (IV) information from the B<EVP_CIPHER_CTX> into the
+caller-supplied buffer. L<EVP_CIPHER_CTX_get_iv_length(3)> can be used to
+determine an appropriate buffer size, and if the supplied buffer is too small,
+an error will be returned (and no data copied).
+EVP_CIPHER_CTX_get_original_iv() accesses the ("original") IV that was
+supplied when the B<EVP_CIPHER_CTX> was initialized, and
+EVP_CIPHER_CTX_get_updated_iv() accesses the current "IV state"
+of the cipher, which is updated during cipher operation for certain cipher modes
+(e.g., CBC and OFB).
+
+The functions EVP_CIPHER_CTX_iv(), EVP_CIPHER_CTX_original_iv(), and
+EVP_CIPHER_CTX_iv_noconst() are deprecated functions that provide similar (at
+a conceptual level) functionality. EVP_CIPHER_CTX_iv() returns a pointer to
+the beginning of the "IV state" as maintained internally in the
+B<EVP_CIPHER_CTX>; EVP_CIPHER_CTX_original_iv() returns a pointer to the
+beginning of the ("original") IV, as maintained by the B<EVP_CIPHER_CTX>, that
+was provided when the B<EVP_CIPHER_CTX> was initialized; and
+EVP_CIPHER_CTX_get_iv_noconst() is the same as EVP_CIPHER_CTX_iv() but has a
+different return type for the pointer.
+
+=head1 RETURN VALUES
+
+EVP_CIPHER_CTX_get_original_iv() and EVP_CIPHER_CTX_get_updated_iv() return 1
+on success and 0 on failure.
+
+The functions EVP_CIPHER_CTX_iv(), EVP_CIPHER_CTX_original_iv(), and
+EVP_CIPHER_CTX_iv_noconst() return a pointer to an IV as an array of bytes on
+success, and NULL on failure.
+
+=head1 HISTORY
+
+EVP_CIPHER_CTX_get_original_iv() and EVP_CIPHER_CTX_get_updated_iv() were added
+in OpenSSL 3.0.0.
+
+EVP_CIPHER_CTX_iv(), EVP_CIPHER_CTX_original_iv(), and
+EVP_CIPHER_CTX_iv_noconst() were added in OpenSSL 1.1.0, and were deprecated
+in OpenSSL 3.0.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_CIPHER_meth_new.pod b/doc/man3/EVP_CIPHER_meth_new.pod
index 437e8bd8b1aa..8b862d9d99c8 100644
--- a/doc/man3/EVP_CIPHER_meth_new.pod
+++ b/doc/man3/EVP_CIPHER_meth_new.pod
@@ -10,12 +10,17 @@ EVP_CIPHER_meth_set_set_asn1_params, EVP_CIPHER_meth_set_get_asn1_params,
EVP_CIPHER_meth_set_ctrl, EVP_CIPHER_meth_get_init,
EVP_CIPHER_meth_get_do_cipher, EVP_CIPHER_meth_get_cleanup,
EVP_CIPHER_meth_get_set_asn1_params, EVP_CIPHER_meth_get_get_asn1_params,
-EVP_CIPHER_meth_get_ctrl - Routines to build up EVP_CIPHER methods
+EVP_CIPHER_meth_get_ctrl
+- Routines to build up EVP_CIPHER methods
=head1 SYNOPSIS
#include <openssl/evp.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len);
EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher);
void EVP_CIPHER_meth_free(EVP_CIPHER *cipher);
@@ -64,6 +69,9 @@ EVP_CIPHER_meth_get_ctrl - Routines to build up EVP_CIPHER methods
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use the OSSL_PROVIDER APIs.
+
The B<EVP_CIPHER> type is a structure for symmetric cipher method
implementation.
@@ -87,7 +95,7 @@ The available flags are:
=item EVP_CIPH_STREAM_CIPHER, EVP_CIPH_ECB_MODE EVP_CIPH_CBC_MODE,
EVP_CIPH_CFB_MODE, EVP_CIPH_OFB_MODE, EVP_CIPH_CTR_MODE, EVP_CIPH_GCM_MODE,
EVP_CIPH_CCM_MODE, EVP_CIPH_XTS_MODE, EVP_CIPH_WRAP_MODE,
-EVP_CIPH_OCB_MODE
+EVP_CIPH_OCB_MODE, EVP_CIPH_SIV_MODE
The cipher mode.
@@ -152,15 +160,11 @@ decryption is to be understood as the number of bits instead of
bytes for this implementation.
This is only useful for CFB1 ciphers.
-=begin comment
-The FIPS flags seem to be unused, so I'm hiding them until I get an
-explanation or they get removed. /RL
-
-=item EVP_CIPH_FLAG_FIPS
+=item EVP_CIPH_FLAG_CTS
-=item EVP_CIPH_FLAG_NON_FIPS_ALLOW
-
-=end comment
+Indicates that the cipher uses ciphertext stealing. This is currently
+used to indicate that the cipher is a one shot that only allows a single call to
+EVP_CipherUpdate().
=item EVP_CIPH_FLAG_CUSTOM_CIPHER
@@ -233,17 +237,21 @@ respective B<cipher> function.
=head1 SEE ALSO
-L<EVP_EncryptInit>
+L<EVP_EncryptInit(3)>
=head1 HISTORY
+All of these functions were deprecated in OpenSSL 3.0.
+
The functions described here were added in OpenSSL 1.1.0.
+The B<EVP_CIPHER> structure created with these functions became reference
+counted in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_DigestInit.pod b/doc/man3/EVP_DigestInit.pod
index a0ed943a3f60..1953df3c5e8d 100644
--- a/doc/man3/EVP_DigestInit.pod
+++ b/doc/man3/EVP_DigestInit.pod
@@ -2,32 +2,62 @@
=head1 NAME
+EVP_MD_fetch, EVP_MD_up_ref, EVP_MD_free,
+EVP_MD_get_params, EVP_MD_gettable_params,
EVP_MD_CTX_new, EVP_MD_CTX_reset, EVP_MD_CTX_free, EVP_MD_CTX_copy,
-EVP_MD_CTX_copy_ex, EVP_MD_CTX_ctrl, EVP_MD_CTX_set_flags,
-EVP_MD_CTX_clear_flags, EVP_MD_CTX_test_flags,
-EVP_Digest, EVP_DigestInit_ex, EVP_DigestInit, EVP_DigestUpdate,
-EVP_DigestFinal_ex, EVP_DigestFinalXOF, EVP_DigestFinal,
-EVP_MD_type, EVP_MD_pkey_type, EVP_MD_size, EVP_MD_block_size, EVP_MD_flags,
-EVP_MD_CTX_md, EVP_MD_CTX_type, EVP_MD_CTX_size, EVP_MD_CTX_block_size,
-EVP_MD_CTX_md_data, EVP_MD_CTX_update_fn, EVP_MD_CTX_set_update_fn,
+EVP_MD_CTX_copy_ex, EVP_MD_CTX_ctrl,
+EVP_MD_CTX_set_params, EVP_MD_CTX_get_params,
+EVP_MD_settable_ctx_params, EVP_MD_gettable_ctx_params,
+EVP_MD_CTX_settable_params, EVP_MD_CTX_gettable_params,
+EVP_MD_CTX_set_flags, EVP_MD_CTX_clear_flags, EVP_MD_CTX_test_flags,
+EVP_Q_digest, EVP_Digest, EVP_DigestInit_ex2, EVP_DigestInit_ex, EVP_DigestInit,
+EVP_DigestUpdate, EVP_DigestFinal_ex, EVP_DigestFinalXOF, EVP_DigestFinal,
+EVP_MD_is_a, EVP_MD_get0_name, EVP_MD_get0_description,
+EVP_MD_names_do_all, EVP_MD_get0_provider, EVP_MD_get_type,
+EVP_MD_get_pkey_type, EVP_MD_get_size, EVP_MD_get_block_size, EVP_MD_get_flags,
+EVP_MD_CTX_get0_name, EVP_MD_CTX_md, EVP_MD_CTX_get0_md, EVP_MD_CTX_get1_md,
+EVP_MD_CTX_get_type, EVP_MD_CTX_get_size, EVP_MD_CTX_get_block_size,
+EVP_MD_CTX_get0_md_data, EVP_MD_CTX_update_fn, EVP_MD_CTX_set_update_fn,
EVP_md_null,
EVP_get_digestbyname, EVP_get_digestbynid, EVP_get_digestbyobj,
-EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_set_pkey_ctx - EVP digest routines
+EVP_MD_CTX_get_pkey_ctx, EVP_MD_CTX_set_pkey_ctx,
+EVP_MD_do_all_provided,
+EVP_MD_type, EVP_MD_nid, EVP_MD_name, EVP_MD_pkey_type, EVP_MD_size,
+EVP_MD_block_size, EVP_MD_flags, EVP_MD_CTX_size, EVP_MD_CTX_block_size,
+EVP_MD_CTX_type, EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_md_data
+- EVP digest routines
=head1 SYNOPSIS
#include <openssl/evp.h>
+ EVP_MD *EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties);
+ int EVP_MD_up_ref(EVP_MD *md);
+ void EVP_MD_free(EVP_MD *md);
+ int EVP_MD_get_params(const EVP_MD *digest, OSSL_PARAM params[]);
+ const OSSL_PARAM *EVP_MD_gettable_params(const EVP_MD *digest);
EVP_MD_CTX *EVP_MD_CTX_new(void);
int EVP_MD_CTX_reset(EVP_MD_CTX *ctx);
void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
void EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void* p2);
+ int EVP_MD_CTX_get_params(EVP_MD_CTX *ctx, OSSL_PARAM params[]);
+ int EVP_MD_CTX_set_params(EVP_MD_CTX *ctx, const OSSL_PARAM params[]);
+ const OSSL_PARAM *EVP_MD_settable_ctx_params(const EVP_MD *md);
+ const OSSL_PARAM *EVP_MD_gettable_ctx_params(const EVP_MD *md);
+ const OSSL_PARAM *EVP_MD_CTX_settable_params(EVP_MD_CTX *ctx);
+ const OSSL_PARAM *EVP_MD_CTX_gettable_params(EVP_MD_CTX *ctx);
void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags);
void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags);
int EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, int flags);
+ int EVP_Q_digest(OSSL_LIB_CTX *libctx, const char *name, const char *propq,
+ const void *data, size_t datalen,
+ unsigned char *md, size_t *mdlen);
int EVP_Digest(const void *data, size_t count, unsigned char *md,
unsigned int *size, const EVP_MD *type, ENGINE *impl);
+ int EVP_DigestInit_ex2(EVP_MD_CTX *ctx, const EVP_MD *type,
+ const OSSL_PARAM params[]);
int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);
int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s);
@@ -40,22 +70,26 @@ EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_set_pkey_ctx - EVP digest routines
int EVP_MD_CTX_copy(EVP_MD_CTX *out, EVP_MD_CTX *in);
- int EVP_MD_type(const EVP_MD *md);
- int EVP_MD_pkey_type(const EVP_MD *md);
- int EVP_MD_size(const EVP_MD *md);
- int EVP_MD_block_size(const EVP_MD *md);
- unsigned long EVP_MD_flags(const EVP_MD *md);
-
- const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
- int EVP_MD_CTX_size(const EVP_MD_CTX *ctx);
- int EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx);
- int EVP_MD_CTX_type(const EVP_MD_CTX *ctx);
- void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx);
- int (*EVP_MD_CTX_update_fn(EVP_MD_CTX *ctx))(EVP_MD_CTX *ctx,
- const void *data, size_t count);
- void EVP_MD_CTX_set_update_fn(EVP_MD_CTX *ctx,
- int (*update)(EVP_MD_CTX *ctx,
- const void *data, size_t count));
+ const char *EVP_MD_get0_name(const EVP_MD *md);
+ const char *EVP_MD_get0_description(const EVP_MD *md);
+ int EVP_MD_is_a(const EVP_MD *md, const char *name);
+ int EVP_MD_names_do_all(const EVP_MD *md,
+ void (*fn)(const char *name, void *data),
+ void *data);
+ const OSSL_PROVIDER *EVP_MD_get0_provider(const EVP_MD *md);
+ int EVP_MD_get_type(const EVP_MD *md);
+ int EVP_MD_get_pkey_type(const EVP_MD *md);
+ int EVP_MD_get_size(const EVP_MD *md);
+ int EVP_MD_get_block_size(const EVP_MD *md);
+ unsigned long EVP_MD_get_flags(const EVP_MD *md);
+
+ const EVP_MD *EVP_MD_CTX_get0_md(const EVP_MD_CTX *ctx);
+ EVP_MD *EVP_MD_CTX_get1_md(EVP_MD_CTX *ctx);
+ const char *EVP_MD_CTX_get0_name(const EVP_MD_CTX *ctx);
+ int EVP_MD_CTX_get_size(const EVP_MD_CTX *ctx);
+ int EVP_MD_CTX_get_block_size(const EVP_MD_CTX *ctx);
+ int EVP_MD_CTX_get_type(const EVP_MD_CTX *ctx);
+ void *EVP_MD_CTX_get0_md_data(const EVP_MD_CTX *ctx);
const EVP_MD *EVP_md_null(void);
@@ -63,143 +97,308 @@ EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_set_pkey_ctx - EVP digest routines
const EVP_MD *EVP_get_digestbynid(int type);
const EVP_MD *EVP_get_digestbyobj(const ASN1_OBJECT *o);
- EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx);
+ EVP_PKEY_CTX *EVP_MD_CTX_get_pkey_ctx(const EVP_MD_CTX *ctx);
void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx);
+ void EVP_MD_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_MD *mac, void *arg),
+ void *arg);
+
+ #define EVP_MD_type EVP_MD_get_type
+ #define EVP_MD_nid EVP_MD_get_type
+ #define EVP_MD_name EVP_MD_get0_name
+ #define EVP_MD_pkey_type EVP_MD_get_pkey_type
+ #define EVP_MD_size EVP_MD_get_size
+ #define EVP_MD_block_size EVP_MD_get_block_size
+ #define EVP_MD_flags EVP_MD_get_flags
+ #define EVP_MD_CTX_size EVP_MD_CTX_get_size
+ #define EVP_MD_CTX_block_size EVP_MD_CTX_get_block_size
+ #define EVP_MD_CTX_type EVP_MD_CTX_get_type
+ #define EVP_MD_CTX_pkey_ctx EVP_MD_CTX_get_pkey_ctx
+ #define EVP_MD_CTX_md_data EVP_MD_CTX_get0_md_data
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
+
+ int (*EVP_MD_CTX_update_fn(EVP_MD_CTX *ctx))(EVP_MD_CTX *ctx,
+ const void *data, size_t count);
+
+ void EVP_MD_CTX_set_update_fn(EVP_MD_CTX *ctx,
+ int (*update)(EVP_MD_CTX *ctx,
+ const void *data, size_t count));
+
=head1 DESCRIPTION
The EVP digest routines are a high-level interface to message digests,
-and should be used instead of the cipher-specific functions.
+and should be used instead of the digest-specific functions.
+
+The B<EVP_MD> type is a structure for digest method implementation.
=over 4
+=item EVP_MD_fetch()
+
+Fetches the digest implementation for the given I<algorithm> from any
+provider offering it, within the criteria given by the I<properties>.
+See L<crypto(7)/ALGORITHM FETCHING> for further information.
+
+The returned value must eventually be freed with EVP_MD_free().
+
+Fetched B<EVP_MD> structures are reference counted.
+
+=item EVP_MD_up_ref()
+
+Increments the reference count for an B<EVP_MD> structure.
+
+=item EVP_MD_free()
+
+Decrements the reference count for the fetched B<EVP_MD> structure.
+If the reference count drops to 0 then the structure is freed.
+
=item EVP_MD_CTX_new()
Allocates and returns a digest context.
=item EVP_MD_CTX_reset()
-Resets the digest context B<ctx>. This can be used to reuse an already
+Resets the digest context I<ctx>. This can be used to reuse an already
existing context.
=item EVP_MD_CTX_free()
-Cleans up digest context B<ctx> and frees up the space allocated to it.
+Cleans up digest context I<ctx> and frees up the space allocated to it.
=item EVP_MD_CTX_ctrl()
-Performs digest-specific control actions on context B<ctx>. The control command
-is indicated in B<cmd> and any additional arguments in B<p1> and B<p2>.
-EVP_MD_CTX_ctrl() must be called after EVP_DigestInit_ex(). Other restrictions
+I<This is a legacy method. EVP_MD_CTX_set_params() and EVP_MD_CTX_get_params()
+is the mechanism that should be used to set and get parameters that are used by
+providers.>
+
+Performs digest-specific control actions on context I<ctx>. The control command
+is indicated in I<cmd> and any additional arguments in I<p1> and I<p2>.
+EVP_MD_CTX_ctrl() must be called after EVP_DigestInit_ex2(). Other restrictions
may apply depending on the control type and digest implementation.
-See L</CONTROLS> below for more information.
+
+If this function happens to be used with a fetched B<EVP_MD>, it will
+translate the controls that are known to OpenSSL into L<OSSL_PARAM(3)>
+parameters with keys defined by OpenSSL and call EVP_MD_CTX_get_params() or
+EVP_MD_CTX_set_params() as is appropriate for each control command.
+
+See L</CONTROLS> below for more information, including what translations are
+being done.
+
+=item EVP_MD_get_params()
+
+Retrieves the requested list of I<params> from a MD I<md>.
+See L</PARAMETERS> below for more information.
+
+=item EVP_MD_CTX_get_params()
+
+Retrieves the requested list of I<params> from a MD context I<ctx>.
+See L</PARAMETERS> below for more information.
+
+=item EVP_MD_CTX_set_params()
+
+Sets the list of I<params> into a MD context I<ctx>.
+See L</PARAMETERS> below for more information.
+
+=item EVP_MD_gettable_params()
+
+Get a constant L<OSSL_PARAM(3)> array that describes the retrievable parameters
+that can be used with EVP_MD_get_params().
+
+=item EVP_MD_gettable_ctx_params(), EVP_MD_CTX_gettable_params()
+
+Get a constant L<OSSL_PARAM(3)> array that describes the retrievable parameters
+that can be used with EVP_MD_CTX_get_params(). EVP_MD_gettable_ctx_params()
+returns the parameters that can be retrieved from the algorithm, whereas
+EVP_MD_CTX_gettable_params() returns the parameters that can be retrieved
+in the context's current state.
+
+=item EVP_MD_settable_ctx_params(), EVP_MD_CTX_settable_params()
+
+Get a constant L<OSSL_PARAM(3)> array that describes the settable parameters
+that can be used with EVP_MD_CTX_set_params(). EVP_MD_settable_ctx_params()
+returns the parameters that can be set from the algorithm, whereas
+EVP_MD_CTX_settable_params() returns the parameters that can be set in the
+context's current state.
=item EVP_MD_CTX_set_flags(), EVP_MD_CTX_clear_flags(), EVP_MD_CTX_test_flags()
-Sets, clears and tests B<ctx> flags. See L</FLAGS> below for more information.
+Sets, clears and tests I<ctx> flags. See L</FLAGS> below for more information.
+
+=item EVP_Q_digest() is a quick one-shot digest function.
+
+It hashes I<datalen> bytes of data at I<data> using the digest algorithm
+I<name>, which is fetched using the optional I<libctx> and I<propq> parameters.
+The digest value is placed in I<md> and its length is written at I<mdlen>
+if the pointer is not NULL. At most B<EVP_MAX_MD_SIZE> bytes will be written.
=item EVP_Digest()
A wrapper around the Digest Init_ex, Update and Final_ex functions.
-Hashes B<count> bytes of data at B<data> using a digest B<type> from ENGINE
-B<impl>. The digest value is placed in B<md> and its length is written at B<size>
+Hashes I<count> bytes of data at I<data> using a digest I<type> from ENGINE
+I<impl>. The digest value is placed in I<md> and its length is written at I<size>
if the pointer is not NULL. At most B<EVP_MAX_MD_SIZE> bytes will be written.
-If B<impl> is NULL the default implementation of digest B<type> is used.
+If I<impl> is NULL the default implementation of digest I<type> is used.
+
+=item EVP_DigestInit_ex2()
+
+Sets up digest context I<ctx> to use a digest I<type>.
+I<type> is typically supplied by a function such as EVP_sha1(), or a
+value explicitly fetched with EVP_MD_fetch().
+
+The parameters B<params> are set on the context after initialisation.
+
+The I<type> parameter can be NULL if I<ctx> has been already initialized
+with another EVP_DigestInit_ex() call and has not been reset with
+EVP_MD_CTX_reset().
=item EVP_DigestInit_ex()
-Sets up digest context B<ctx> to use a digest B<type> from ENGINE B<impl>.
-B<type> will typically be supplied by a function such as EVP_sha1(). If
-B<impl> is NULL then the default implementation of digest B<type> is used.
+Sets up digest context I<ctx> to use a digest I<type>.
+I<type> is typically supplied by a function such as EVP_sha1(), or a
+value explicitly fetched with EVP_MD_fetch().
+
+If I<impl> is non-NULL, its implementation of the digest I<type> is used if
+there is one, and if not, the default implementation is used.
+
+The I<type> parameter can be NULL if I<ctx> has been already initialized
+with another EVP_DigestInit_ex() call and has not been reset with
+EVP_MD_CTX_reset().
=item EVP_DigestUpdate()
-Hashes B<cnt> bytes of data at B<d> into the digest context B<ctx>. This
-function can be called several times on the same B<ctx> to hash additional
+Hashes I<cnt> bytes of data at I<d> into the digest context I<ctx>. This
+function can be called several times on the same I<ctx> to hash additional
data.
=item EVP_DigestFinal_ex()
-Retrieves the digest value from B<ctx> and places it in B<md>. If the B<s>
+Retrieves the digest value from I<ctx> and places it in I<md>. If the I<s>
parameter is not NULL then the number of bytes of data written (i.e. the
-length of the digest) will be written to the integer at B<s>, at most
+length of the digest) will be written to the integer at I<s>, at most
B<EVP_MAX_MD_SIZE> bytes will be written. After calling EVP_DigestFinal_ex()
no additional calls to EVP_DigestUpdate() can be made, but
-EVP_DigestInit_ex() can be called to initialize a new digest operation.
+EVP_DigestInit_ex2() can be called to initialize a new digest operation.
=item EVP_DigestFinalXOF()
Interfaces to extendable-output functions, XOFs, such as SHAKE128 and SHAKE256.
-It retrieves the digest value from B<ctx> and places it in B<len>-sized <B>md.
+It retrieves the digest value from I<ctx> and places it in I<len>-sized I<md>.
After calling this function no additional calls to EVP_DigestUpdate() can be
-made, but EVP_DigestInit_ex() can be called to initialize a new operation.
+made, but EVP_DigestInit_ex2() can be called to initialize a new operation.
=item EVP_MD_CTX_copy_ex()
-Can be used to copy the message digest state from B<in> to B<out>. This is
+Can be used to copy the message digest state from I<in> to I<out>. This is
useful if large amounts of data are to be hashed which only differ in the last
few bytes.
=item EVP_DigestInit()
-Behaves in the same way as EVP_DigestInit_ex() except it always uses the
-default digest implementation and calls EVP_MD_CTX_reset().
+Behaves in the same way as EVP_DigestInit_ex2() except it doesn't set any
+parameters and calls EVP_MD_CTX_reset() so it cannot be used with an I<type>
+of NULL.
=item EVP_DigestFinal()
-Similar to EVP_DigestFinal_ex() except the digest context B<ctx> is
-automatically cleaned up.
+Similar to EVP_DigestFinal_ex() except after computing the digest
+the digest context I<ctx> is automatically cleaned up with EVP_MD_CTX_reset().
=item EVP_MD_CTX_copy()
-Similar to EVP_MD_CTX_copy_ex() except the destination B<out> does not have to
+Similar to EVP_MD_CTX_copy_ex() except the destination I<out> does not have to
be initialized.
-=item EVP_MD_size(),
-EVP_MD_CTX_size()
+=item EVP_MD_is_a()
+
+Returns 1 if I<md> is an implementation of an algorithm that's
+identifiable with I<name>, otherwise 0.
+
+If I<md> is a legacy digest (it's the return value from the likes of
+EVP_sha256() rather than the result of an EVP_MD_fetch()), only cipher
+names registered with the default library context (see
+L<OSSL_LIB_CTX(3)>) will be considered.
+
+=item EVP_MD_get0_name(),
+EVP_MD_CTX_get0_name()
+
+Return the name of the given message digest. For fetched message
+digests with multiple names, only one of them is returned; it's
+recommended to use EVP_MD_names_do_all() instead.
+
+=item EVP_MD_names_do_all()
+
+Traverses all names for the I<md>, and calls I<fn> with each name and
+I<data>. This is only useful with fetched B<EVP_MD>s.
+
+=item EVP_MD_get0_description()
+
+Returns a description of the digest, meant for display and human consumption.
+The description is at the discretion of the digest implementation.
+
+=item EVP_MD_get0_provider()
+
+Returns an B<OSSL_PROVIDER> pointer to the provider that implements the given
+B<EVP_MD>.
+
+=item EVP_MD_get_size(),
+EVP_MD_CTX_get_size()
Return the size of the message digest when passed an B<EVP_MD> or an
B<EVP_MD_CTX> structure, i.e. the size of the hash.
-=item EVP_MD_block_size(),
-EVP_MD_CTX_block_size()
+=item EVP_MD_get_block_size(),
+EVP_MD_CTX_get_block_size()
Return the block size of the message digest when passed an B<EVP_MD> or an
B<EVP_MD_CTX> structure.
-=item EVP_MD_type(),
-EVP_MD_CTX_type()
+=item EVP_MD_get_type(),
+EVP_MD_CTX_get_type()
Return the NID of the OBJECT IDENTIFIER representing the given message digest
-when passed an B<EVP_MD> structure. For example, C<EVP_MD_type(EVP_sha1())>
+when passed an B<EVP_MD> structure. For example, C<EVP_MD_get_type(EVP_sha1())>
returns B<NID_sha1>. This function is normally used when setting ASN1 OIDs.
-=item EVP_MD_CTX_md_data()
+=item EVP_MD_CTX_get0_md_data()
Return the digest method private data for the passed B<EVP_MD_CTX>.
The space is allocated by OpenSSL and has the size originally set with
EVP_MD_meth_set_app_datasize().
-=item EVP_MD_CTX_md()
+=item EVP_MD_CTX_get0_md(), EVP_MD_CTX_get1_md()
-Returns the B<EVP_MD> structure corresponding to the passed B<EVP_MD_CTX>.
+EVP_MD_CTX_get0_md() returns
+the B<EVP_MD> structure corresponding to the passed B<EVP_MD_CTX>. This
+will be the same B<EVP_MD> object originally passed to EVP_DigestInit_ex2() (or
+other similar function) when the EVP_MD_CTX was first initialised. Note that
+where explicit fetch is in use (see L<EVP_MD_fetch(3)>) the value returned from
+this function will not have its reference count incremented and therefore it
+should not be used after the EVP_MD_CTX is freed.
+EVP_MD_CTX_get1_md() is the same except the ownership is passed to the
+caller and is from the passed B<EVP_MD_CTX>.
=item EVP_MD_CTX_set_update_fn()
-Sets the update function for B<ctx> to B<update>.
-This is the function that is called by EVP_DigestUpdate. If not set, the
+Sets the update function for I<ctx> to I<update>.
+This is the function that is called by EVP_DigestUpdate(). If not set, the
update function from the B<EVP_MD> type specified at initialization is used.
=item EVP_MD_CTX_update_fn()
-Returns the update function for B<ctx>.
+Returns the update function for I<ctx>.
-=item EVP_MD_flags()
+=item EVP_MD_get_flags()
-Returns the B<md> flags. Note that these are different from the B<EVP_MD_CTX>
+Returns the I<md> flags. Note that these are different from the B<EVP_MD_CTX>
ones. See L<EVP_MD_meth_set_flags(3)> for more information.
-=item EVP_MD_pkey_type()
+=item EVP_MD_get_pkey_type()
Returns the NID of the public key signing algorithm associated with this
digest. For example EVP_sha1() is associated with RSA so this will return
@@ -218,20 +417,78 @@ EVP_get_digestbyobj()
Returns an B<EVP_MD> structure when passed a digest name, a digest B<NID> or an
B<ASN1_OBJECT> structure respectively.
-=item EVP_MD_CTX_pkey_ctx()
+The EVP_get_digestbyname() function is present for backwards compatibility with
+OpenSSL prior to version 3 and is different to the EVP_MD_fetch() function
+since it does not attempt to "fetch" an implementation of the cipher.
+Additionally, it only knows about digests that are built-in to OpenSSL and have
+an associated NID. Similarly EVP_get_digestbynid() and EVP_get_digestbyobj()
+also return objects without an associated implementation.
+
+When the digest objects returned by these functions are used (such as in a call
+to EVP_DigestInit_ex()) an implementation of the digest will be implicitly
+fetched from the loaded providers. This fetch could fail if no suitable
+implementation is available. Use EVP_MD_fetch() instead to explicitly fetch
+the algorithm and an associated implementation from a provider.
+
+See L<crypto(7)/ALGORITHM FETCHING> for more information about fetching.
-Returns the B<EVP_PKEY_CTX> assigned to B<ctx>. The returned pointer should not
+The digest objects returned from these functions do not need to be freed with
+EVP_MD_free().
+
+=item EVP_MD_CTX_get_pkey_ctx()
+
+Returns the B<EVP_PKEY_CTX> assigned to I<ctx>. The returned pointer should not
be freed by the caller.
=item EVP_MD_CTX_set_pkey_ctx()
Assigns an B<EVP_PKEY_CTX> to B<EVP_MD_CTX>. This is usually used to provide
a customized B<EVP_PKEY_CTX> to L<EVP_DigestSignInit(3)> or
-L<EVP_DigestVerifyInit(3)>. The B<pctx> passed to this function should be freed
-by the caller. A NULL B<pctx> pointer is also allowed to clear the B<EVP_PKEY_CTX>
-assigned to B<ctx>. In such case, freeing the cleared B<EVP_PKEY_CTX> or not
+L<EVP_DigestVerifyInit(3)>. The I<pctx> passed to this function should be freed
+by the caller. A NULL I<pctx> pointer is also allowed to clear the B<EVP_PKEY_CTX>
+assigned to I<ctx>. In such case, freeing the cleared B<EVP_PKEY_CTX> or not
depends on how the B<EVP_PKEY_CTX> is created.
+=item EVP_MD_do_all_provided()
+
+Traverses all messages digests implemented by all activated providers
+in the given library context I<libctx>, and for each of the implementations,
+calls the given function I<fn> with the implementation method and the given
+I<arg> as argument.
+
+=back
+
+=head1 PARAMETERS
+
+See L<OSSL_PARAM(3)> for information about passing parameters.
+
+EVP_MD_CTX_set_params() can be used with the following OSSL_PARAM keys:
+
+=over 4
+
+=item "xoflen" (B<OSSL_DIGEST_PARAM_XOFLEN>) <unsigned integer>
+
+Sets the digest length for extendable output functions.
+It is used by the SHAKE algorithm and should not exceed what can be given
+using a B<size_t>.
+
+=item "pad-type" (B<OSSL_DIGEST_PARAM_PAD_TYPE>) <unsigned integer>
+
+Sets the padding type.
+It is used by the MDC2 algorithm.
+
+=back
+
+EVP_MD_CTX_get_params() can be used with the following OSSL_PARAM keys:
+
+=over 4
+
+=item "micalg" (B<OSSL_PARAM_DIGEST_KEY_MICALG>) <UTF8 string>.
+
+Gets the digest Message Integrity Check algorithm string. This is used when
+creating S/MIME multipart/signed messages, as specified in RFC 3851.
+It may be used by external engines or providers.
+
=back
=head1 CONTROLS
@@ -244,15 +501,21 @@ EVP_MD_CTX_ctrl() can be used to send the following standard controls:
Gets the digest Message Integrity Check algorithm string. This is used when
creating S/MIME multipart/signed messages, as specified in RFC 3851.
-The string value is written to B<p2>.
+The string value is written to I<p2>.
+
+When used with a fetched B<EVP_MD>, EVP_MD_CTX_get_params() gets called with
+an L<OSSL_PARAM(3)> item with the key "micalg" (B<OSSL_DIGEST_PARAM_MICALG>).
=item EVP_MD_CTRL_XOF_LEN
-This control sets the digest length for extendable output functions to B<p1>.
+This control sets the digest length for extendable output functions to I<p1>.
Sending this control directly should not be necessary, the use of
-C<EVP_DigestFinalXOF()> is preferred.
+EVP_DigestFinalXOF() is preferred.
Currently used by SHAKE.
+When used with a fetched B<EVP_MD>, EVP_MD_CTX_get_params() gets called with
+an L<OSSL_PARAM(3)> item with the key "xoflen" (B<OSSL_DIGEST_PARAM_XOFLEN>).
+
=back
=head1 FLAGS
@@ -291,33 +554,58 @@ disabled with this flag.
=over 4
-=item EVP_DigestInit_ex(),
+=item EVP_MD_fetch()
+
+Returns a pointer to a B<EVP_MD> for success or NULL for failure.
+
+=item EVP_MD_up_ref()
+
+Returns 1 for success or 0 for failure.
+
+=item EVP_Q_digest(),
+EVP_Digest(),
+EVP_DigestInit_ex2(),
+EVP_DigestInit_ex(),
+EVP_DigestInit(),
EVP_DigestUpdate(),
-EVP_DigestFinal_ex()
+EVP_DigestFinal_ex(),
+EVP_DigestFinalXOF(), and
+EVP_DigestFinal()
-Returns 1 for
+return 1 for
success and 0 for failure.
=item EVP_MD_CTX_ctrl()
Returns 1 if successful or 0 for failure.
+=item EVP_MD_CTX_set_params(),
+EVP_MD_CTX_get_params()
+
+Returns 1 if successful or 0 for failure.
+
+=item EVP_MD_CTX_settable_params(),
+EVP_MD_CTX_gettable_params()
+
+Return an array of constant L<OSSL_PARAM(3)>s, or NULL if there is none
+to get.
+
=item EVP_MD_CTX_copy_ex()
Returns 1 if successful or 0 for failure.
-=item EVP_MD_type(),
-EVP_MD_pkey_type()
+=item EVP_MD_get_type(),
+EVP_MD_get_pkey_type()
Returns the NID of the corresponding OBJECT IDENTIFIER or NID_undef if none
exists.
-=item EVP_MD_size(),
-EVP_MD_block_size(),
-EVP_MD_CTX_size(),
-EVP_MD_CTX_block_size()
+=item EVP_MD_get_size(),
+EVP_MD_get_block_size(),
+EVP_MD_CTX_get_size(),
+EVP_MD_CTX_get_block_size()
-Returns the digest or block size in bytes.
+Returns the digest or block size in bytes or -1 for failure.
=item EVP_md_null()
@@ -333,6 +621,11 @@ Returns either an B<EVP_MD> structure or NULL if an error occurs.
This function has no return value.
+=item EVP_MD_names_do_all()
+
+Returns 1 if the callback was called for all names. A return value of 0 means
+that the callback was not called for any names.
+
=back
=head1 NOTES
@@ -345,9 +638,16 @@ New applications should use the SHA-2 (such as L<EVP_sha256(3)>) or the SHA-3
digest algorithms (such as L<EVP_sha3_512(3)>). The other digest algorithms
are still in common use.
-For most applications the B<impl> parameter to EVP_DigestInit_ex() will be
+For most applications the I<impl> parameter to EVP_DigestInit_ex() will be
set to NULL to use the default digest implementation.
+Ignoring failure returns of EVP_DigestInit_ex(), EVP_DigestInit_ex2(), or
+EVP_DigestInit() can lead to undefined behavior on subsequent calls
+updating or finalizing the B<EVP_MD_CTX> such as the EVP_DigestUpdate() or
+EVP_DigestFinal() functions. The only valid calls on the B<EVP_MD_CTX>
+when initialization fails are calls that attempt another initialization of
+the context or release the context.
+
The functions EVP_DigestInit(), EVP_DigestFinal() and EVP_MD_CTX_copy() are
obsolete but are retained to maintain compatibility with existing code. New
applications should use EVP_DigestInit_ex(), EVP_DigestFinal_ex() and
@@ -358,9 +658,9 @@ implementations of digests to be specified.
If digest contexts are not cleaned up after use,
memory leaks will occur.
-EVP_MD_CTX_size(), EVP_MD_CTX_block_size(), EVP_MD_CTX_type(),
-EVP_get_digestbynid() and EVP_get_digestbyobj() are defined as
-macros.
+EVP_MD_CTX_get0_name(), EVP_MD_CTX_get_size(), EVP_MD_CTX_get_block_size(),
+EVP_MD_CTX_get_type(), EVP_get_digestbynid() and EVP_get_digestbyobj() are
+defined as macros.
EVP_MD_CTX_ctrl() sends commands to message digests for additional configuration
or control.
@@ -395,10 +695,26 @@ digest name passed on the command line.
}
mdctx = EVP_MD_CTX_new();
- EVP_DigestInit_ex(mdctx, md, NULL);
- EVP_DigestUpdate(mdctx, mess1, strlen(mess1));
- EVP_DigestUpdate(mdctx, mess2, strlen(mess2));
- EVP_DigestFinal_ex(mdctx, md_value, &md_len);
+ if (!EVP_DigestInit_ex2(mdctx, md, NULL)) {
+ printf("Message digest initialization failed.\n");
+ EVP_MD_CTX_free(mdctx);
+ exit(1);
+ }
+ if (!EVP_DigestUpdate(mdctx, mess1, strlen(mess1))) {
+ printf("Message digest update failed.\n");
+ EVP_MD_CTX_free(mdctx);
+ exit(1);
+ }
+ if (!EVP_DigestUpdate(mdctx, mess2, strlen(mess2))) {
+ printf("Message digest update failed.\n");
+ EVP_MD_CTX_free(mdctx);
+ exit(1);
+ }
+ if (!EVP_DigestFinal_ex(mdctx, md_value, &md_len)) {
+ printf("Message digest finalization failed.\n");
+ EVP_MD_CTX_free(mdctx);
+ exit(1);
+ }
EVP_MD_CTX_free(mdctx);
printf("Digest is: ");
@@ -412,8 +728,14 @@ digest name passed on the command line.
=head1 SEE ALSO
L<EVP_MD_meth_new(3)>,
-L<dgst(1)>,
-L<evp(7)>
+L<openssl-dgst(1)>,
+L<evp(7)>,
+L<OSSL_PROVIDER(3)>,
+L<OSSL_PARAM(3)>,
+L<property(7)>,
+L<crypto(7)/ALGORITHM FETCHING>,
+L<provider-digest(7)>,
+L<life_cycle-digest(7)>
The full list of digest algorithms are provided below.
@@ -439,13 +761,32 @@ later, so now EVP_sha1() can be used with RSA and DSA.
The EVP_dss1() function was removed in OpenSSL 1.1.0.
-The EVP_MD_CTX_set_pkey_ctx() function was added in 1.1.1.
+The EVP_MD_CTX_set_pkey_ctx() function was added in OpenSSL 1.1.1.
+
+The EVP_Q_digest(), EVP_DigestInit_ex2(),
+EVP_MD_fetch(), EVP_MD_free(), EVP_MD_up_ref(),
+EVP_MD_get_params(), EVP_MD_CTX_set_params(), EVP_MD_CTX_get_params(),
+EVP_MD_gettable_params(), EVP_MD_gettable_ctx_params(),
+EVP_MD_settable_ctx_params(), EVP_MD_CTX_settable_params() and
+EVP_MD_CTX_gettable_params() functions were added in OpenSSL 3.0.
+
+The EVP_MD_type(), EVP_MD_nid(), EVP_MD_name(), EVP_MD_pkey_type(),
+EVP_MD_size(), EVP_MD_block_size(), EVP_MD_flags(), EVP_MD_CTX_size(),
+EVP_MD_CTX_block_size(), EVP_MD_CTX_type(), and EVP_MD_CTX_md_data()
+functions were renamed to include C<get> or C<get0> in their names in
+OpenSSL 3.0, respectively. The old names are kept as non-deprecated
+alias macros.
+
+The EVP_MD_CTX_md() function was deprecated in OpenSSL 3.0; use
+EVP_MD_CTX_get0_md() instead.
+EVP_MD_CTX_update_fn() and EVP_MD_CTX_set_update_fn() were deprecated
+in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_DigestSignInit.pod b/doc/man3/EVP_DigestSignInit.pod
index 4efc8a497491..7232e9786026 100644
--- a/doc/man3/EVP_DigestSignInit.pod
+++ b/doc/man3/EVP_DigestSignInit.pod
@@ -2,13 +2,17 @@
=head1 NAME
-EVP_DigestSignInit, EVP_DigestSignUpdate, EVP_DigestSignFinal,
-EVP_DigestSign - EVP signing functions
+EVP_DigestSignInit_ex, EVP_DigestSignInit, EVP_DigestSignUpdate,
+EVP_DigestSignFinal, EVP_DigestSign - EVP signing functions
=head1 SYNOPSIS
#include <openssl/evp.h>
+ int EVP_DigestSignInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+ const char *mdname, OSSL_LIB_CTX *libctx,
+ const char *props, EVP_PKEY *pkey,
+ const OSSL_PARAM params[]);
int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey);
int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);
@@ -21,22 +25,45 @@ EVP_DigestSign - EVP signing functions
=head1 DESCRIPTION
The EVP signature routines are a high-level interface to digital signatures.
-
-EVP_DigestSignInit() sets up signing context B<ctx> to use digest B<type> from
-ENGINE B<e> and private key B<pkey>. B<ctx> must be created with
-EVP_MD_CTX_new() before calling this function. If B<pctx> is not NULL, the
-EVP_PKEY_CTX of the signing operation will be written to B<*pctx>: this can
-be used to set alternative signing options. Note that any existing value in
-B<*pctx> is overwritten. The EVP_PKEY_CTX value returned must not be freed
-directly by the application if B<ctx> is not assigned an EVP_PKEY_CTX value before
-being passed to EVP_DigestSignInit() (which means the EVP_PKEY_CTX is created
-inside EVP_DigestSignInit() and it will be freed automatically when the
-EVP_MD_CTX is freed).
-
-The digest B<type> may be NULL if the signing algorithm supports it.
-
-No B<EVP_PKEY_CTX> will be created by EVP_DigestSignInit() if the passed B<ctx>
-has already been assigned one via L<EVP_MD_CTX_set_pkey_ctx(3)>. See also L<SM2(7)>.
+Input data is digested first before the signing takes place.
+
+EVP_DigestSignInit_ex() sets up signing context I<ctx> to use a digest
+with the name I<mdname> and private key I<pkey>. The name of the digest to be
+used is passed to the provider of the signature algorithm in use. How that
+provider interprets the digest name is provider specific. The provider may
+implement that digest directly itself or it may (optionally) choose to fetch it
+(which could result in a digest from a different provider being selected). If the
+provider supports fetching the digest then it may use the I<props> argument for
+the properties to be used during the fetch. Finally, the passed parameters
+I<params>, if not NULL, are set on the context before returning.
+
+The I<pkey> algorithm is used to fetch a B<EVP_SIGNATURE> method implicitly, to
+be used for the actual signing. See L<provider(7)/Implicit fetch> for
+more information about implicit fetches.
+
+The OpenSSL default and legacy providers support fetching digests and can fetch
+those digests from any available provider. The OpenSSL FIPS provider also
+supports fetching digests but will only fetch digests that are themselves
+implemented inside the FIPS provider.
+
+I<ctx> must be created with EVP_MD_CTX_new() before calling this function. If
+I<pctx> is not NULL, the EVP_PKEY_CTX of the signing operation will be written
+to I<*pctx>: this can be used to set alternative signing options. Note that any
+existing value in I<*pctx> is overwritten. The EVP_PKEY_CTX value returned must
+not be freed directly by the application if I<ctx> is not assigned an
+EVP_PKEY_CTX value before being passed to EVP_DigestSignInit_ex()
+(which means the EVP_PKEY_CTX is created inside EVP_DigestSignInit_ex()
+and it will be freed automatically when the EVP_MD_CTX is freed). If the
+EVP_PKEY_CTX to be used is created by EVP_DigestSignInit_ex then it
+will use the B<OSSL_LIB_CTX> specified in I<libctx> and the property query string
+specified in I<props>.
+
+The digest I<mdname> may be NULL if the signing algorithm supports it. The
+I<props> argument can always be NULL.
+
+No B<EVP_PKEY_CTX> will be created by EVP_DigestSignInit_ex() if the
+passed I<ctx> has already been assigned one via L<EVP_MD_CTX_set_pkey_ctx(3)>.
+See also L<SM2(7)>.
Only EVP_PKEY types that support signing can be used with these functions. This
includes MAC algorithms where the MAC generation is considered as a form of
@@ -57,7 +84,7 @@ Supports SHA1, SHA224, SHA256, SHA384, SHA512 and SM3
=item RSA with no padding
-Supports no digests (the digest B<type> must be NULL)
+Supports no digests (the digest I<type> must be NULL)
=item RSA with X931 padding
@@ -70,7 +97,7 @@ SHA3-224, SHA3-256, SHA3-384, SHA3-512
=item Ed25519 and Ed448
-Support no digests (the digest B<type> must be NULL)
+Support no digests (the digest I<type> must be NULL)
=item HMAC
@@ -84,21 +111,30 @@ Will ignore any digest provided.
If RSA-PSS is used and restrictions apply then the digest must match.
-EVP_DigestSignUpdate() hashes B<cnt> bytes of data at B<d> into the
-signature context B<ctx>. This function can be called several times on the
-same B<ctx> to include additional data. This function is currently implemented
-using a macro.
-
-EVP_DigestSignFinal() signs the data in B<ctx> and places the signature in B<sig>.
-If B<sig> is B<NULL> then the maximum size of the output buffer is written to
-the B<siglen> parameter. If B<sig> is not B<NULL> then before the call the
-B<siglen> parameter should contain the length of the B<sig> buffer. If the
-call is successful the signature is written to B<sig> and the amount of data
-written to B<siglen>.
-
-EVP_DigestSign() signs B<tbslen> bytes of data at B<tbs> and places the
-signature in B<sig> and its length in B<siglen> in a similar way to
-EVP_DigestSignFinal().
+EVP_DigestSignInit() works in the same way as EVP_DigestSignInit_ex()
+except that the I<mdname> parameter will be inferred from the supplied
+digest I<type>, and I<props> will be NULL. Where supplied the ENGINE I<e> will
+be used for the signing and digest algorithm implementations. I<e> may be NULL.
+
+EVP_DigestSignUpdate() hashes I<cnt> bytes of data at I<d> into the
+signature context I<ctx>. This function can be called several times on the
+same I<ctx> to include additional data.
+
+Unless I<sig> is NULL EVP_DigestSignFinal() signs the data in I<ctx>
+and places the signature in I<sig>.
+Otherwise the maximum necessary size of the output buffer is written to
+the I<siglen> parameter. If I<sig> is not NULL then before the call the
+I<siglen> parameter should contain the length of the I<sig> buffer. If the
+call is successful the signature is written to I<sig> and the amount of data
+written to I<siglen>.
+
+EVP_DigestSign() signs I<tbslen> bytes of data at I<tbs> and places the
+signature in I<sig> and its length in I<siglen> in a similar way to
+EVP_DigestSignFinal(). In the event of a failure EVP_DigestSign() cannot be
+called again without reinitialising the EVP_MD_CTX. If I<sig> is NULL before the
+call then I<siglen> will be populated with the required size for the I<sig>
+buffer. If I<sig> is non-NULL before the call then I<siglen> should contain the
+length of the I<sig> buffer.
=head1 RETURN VALUES
@@ -131,13 +167,18 @@ The call to EVP_DigestSignFinal() internally finalizes a copy of the digest
context. This means that calls to EVP_DigestSignUpdate() and
EVP_DigestSignFinal() can be called later to digest and sign additional data.
-Since only a copy of the digest context is ever finalized, the context must
-be cleaned up after use by calling EVP_MD_CTX_free() or a memory leak
-will occur.
+EVP_DigestSignInit() and EVP_DigestSignInit_ex() functions can be called
+multiple times on a context and the parameters set by previous calls should be
+preserved if the I<pkey> parameter is NULL. The call then just resets the state
+of the I<ctx>.
+
+Ignoring failure returns of EVP_DigestSignInit() and EVP_DigestSignInit_ex()
+functions can lead to subsequent undefined behavior when calling
+EVP_DigestSignUpdate(), EVP_DigestSignFinal(), or EVP_DigestSign().
-The use of EVP_PKEY_size() with these functions is discouraged because some
+The use of EVP_PKEY_get_size() with these functions is discouraged because some
signature operations may have a signature length which depends on the
-parameters set. As a result EVP_PKEY_size() would have to return a value
+parameters set. As a result EVP_PKEY_get_size() would have to return a value
which indicates the maximum possible signature for any set of parameters.
=head1 SEE ALSO
@@ -146,7 +187,7 @@ L<EVP_DigestVerifyInit(3)>,
L<EVP_DigestInit(3)>,
L<evp(7)>, L<HMAC(3)>, L<MD2(3)>,
L<MD5(3)>, L<MDC2(3)>, L<RIPEMD160(3)>,
-L<SHA1(3)>, L<dgst(1)>,
+L<SHA1(3)>, L<openssl-dgst(1)>,
L<RAND(7)>
=head1 HISTORY
@@ -154,11 +195,15 @@ L<RAND(7)>
EVP_DigestSignInit(), EVP_DigestSignUpdate() and EVP_DigestSignFinal()
were added in OpenSSL 1.0.0.
+EVP_DigestSignInit_ex() was added in OpenSSL 3.0.
+
+EVP_DigestSignUpdate() was converted from a macro to a function in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_DigestVerifyInit.pod b/doc/man3/EVP_DigestVerifyInit.pod
index e7d8c8318445..55826fe16bd5 100644
--- a/doc/man3/EVP_DigestVerifyInit.pod
+++ b/doc/man3/EVP_DigestVerifyInit.pod
@@ -2,13 +2,17 @@
=head1 NAME
-EVP_DigestVerifyInit, EVP_DigestVerifyUpdate, EVP_DigestVerifyFinal,
-EVP_DigestVerify - EVP signature verification functions
+EVP_DigestVerifyInit_ex, EVP_DigestVerifyInit, EVP_DigestVerifyUpdate,
+EVP_DigestVerifyFinal, EVP_DigestVerify - EVP signature verification functions
=head1 SYNOPSIS
#include <openssl/evp.h>
+ int EVP_DigestVerifyInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+ const char *mdname, OSSL_LIB_CTX *libctx,
+ const char *props, EVP_PKEY *pkey,
+ const OSSL_PARAM params[]);
int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey);
int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);
@@ -20,25 +24,93 @@ EVP_DigestVerify - EVP signature verification functions
=head1 DESCRIPTION
The EVP signature routines are a high-level interface to digital signatures.
+Input data is digested first before the signature verification takes place.
-EVP_DigestVerifyInit() sets up verification context B<ctx> to use digest
-B<type> from ENGINE B<e> and public key B<pkey>. B<ctx> must be created
-with EVP_MD_CTX_new() before calling this function. If B<pctx> is not NULL, the
-EVP_PKEY_CTX of the verification operation will be written to B<*pctx>: this
-can be used to set alternative verification options. Note that any existing
-value in B<*pctx> is overwritten. The EVP_PKEY_CTX value returned must not be freed
-directly by the application if B<ctx> is not assigned an EVP_PKEY_CTX value before
-being passed to EVP_DigestVerifyInit() (which means the EVP_PKEY_CTX is created
-inside EVP_DigestVerifyInit() and it will be freed automatically when the
-EVP_MD_CTX is freed).
+EVP_DigestVerifyInit_ex() sets up verification context B<ctx> to use a
+digest with the name B<mdname> and public key B<pkey>. The name of the digest to
+be used is passed to the provider of the signature algorithm in use. How that
+provider interprets the digest name is provider specific. The provider may
+implement that digest directly itself or it may (optionally) choose to fetch it
+(which could result in a digest from a different provider being selected). If
+the provider supports fetching the digest then it may use the B<props> argument
+for the properties to be used during the fetch. Finally, the passed parameters
+I<params>, if not NULL, are set on the context before returning.
-No B<EVP_PKEY_CTX> will be created by EVP_DigestSignInit() if the passed B<ctx>
-has already been assigned one via L<EVP_MD_CTX_set_pkey_ctx(3)>. See also L<SM2(7)>.
+The I<pkey> algorithm is used to fetch a B<EVP_SIGNATURE> method implicitly, to
+be used for the actual signing. See L<provider(7)/Implicit fetch> for
+more information about implicit fetches.
+
+The OpenSSL default and legacy providers support fetching digests and can fetch
+those digests from any available provider. The OpenSSL FIPS provider also
+supports fetching digests but will only fetch digests that are themselves
+implemented inside the FIPS provider.
+
+B<ctx> must be created with EVP_MD_CTX_new() before calling this function. If
+B<pctx> is not NULL, the EVP_PKEY_CTX of the verification operation will be
+written to B<*pctx>: this can be used to set alternative verification options.
+Note that any existing value in B<*pctx> is overwritten. The EVP_PKEY_CTX value
+returned must not be freed directly by the application if B<ctx> is not assigned
+an EVP_PKEY_CTX value before being passed to EVP_DigestVerifyInit_ex()
+(which means the EVP_PKEY_CTX is created inside
+EVP_DigestVerifyInit_ex() and it will be freed automatically when the
+EVP_MD_CTX is freed). If the EVP_PKEY_CTX to be used is created by
+EVP_DigestVerifyInit_ex then it will use the B<OSSL_LIB_CTX> specified
+in I<libctx> and the property query string specified in I<props>.
+
+No B<EVP_PKEY_CTX> will be created by EVP_DigestVerifyInit_ex() if the
+passed B<ctx> has already been assigned one via L<EVP_MD_CTX_set_pkey_ctx(3)>.
+See also L<SM2(7)>.
+
+Not all digests can be used for all key types. The following combinations apply.
+
+=over 4
+
+=item DSA
+
+Supports SHA1, SHA224, SHA256, SHA384 and SHA512
+
+=item ECDSA
+
+Supports SHA1, SHA224, SHA256, SHA384, SHA512 and SM3
+
+=item RSA with no padding
+
+Supports no digests (the digest B<type> must be NULL)
+
+=item RSA with X931 padding
+
+Supports SHA1, SHA256, SHA384 and SHA512
+
+=item All other RSA padding types
+
+Support SHA1, SHA224, SHA256, SHA384, SHA512, MD5, MD5_SHA1, MD2, MD4, MDC2,
+SHA3-224, SHA3-256, SHA3-384, SHA3-512
+
+=item Ed25519 and Ed448
+
+Support no digests (the digest B<type> must be NULL)
+
+=item HMAC
+
+Supports any digest
+
+=item CMAC, Poly1305 and Siphash
+
+Will ignore any digest provided.
+
+=back
+
+If RSA-PSS is used and restrictions apply then the digest must match.
+
+EVP_DigestVerifyInit() works in the same way as
+EVP_DigestVerifyInit_ex() except that the B<mdname> parameter will be
+inferred from the supplied digest B<type>, and B<props> will be NULL. Where
+supplied the ENGINE B<e> will be used for the signature verification and digest
+algorithm implementations. B<e> may be NULL.
EVP_DigestVerifyUpdate() hashes B<cnt> bytes of data at B<d> into the
verification context B<ctx>. This function can be called several times on the
-same B<ctx> to include additional data. This function is currently implemented
-using a macro.
+same B<ctx> to include additional data.
EVP_DigestVerifyFinal() verifies the data in B<ctx> against the signature in
B<sig> of length B<siglen>.
@@ -84,9 +156,14 @@ The call to EVP_DigestVerifyFinal() internally finalizes a copy of the digest
context. This means that EVP_VerifyUpdate() and EVP_VerifyFinal() can
be called later to digest and verify additional data.
-Since only a copy of the digest context is ever finalized, the context must
-be cleaned up after use by calling EVP_MD_CTX_free() or a memory leak
-will occur.
+EVP_DigestVerifyInit() and EVP_DigestVerifyInit_ex() functions can be called
+multiple times on a context and the parameters set by previous calls should be
+preserved if the I<pkey> parameter is NULL. The call then just resets the state
+of the I<ctx>.
+
+Ignoring failure returns of EVP_DigestVerifyInit() and EVP_DigestVerifyInit_ex()
+functions can lead to subsequent undefined behavior when calling
+EVP_DigestVerifyUpdate(), EVP_DigestVerifyFinal(), or EVP_DigestVerify().
=head1 SEE ALSO
@@ -94,7 +171,7 @@ L<EVP_DigestSignInit(3)>,
L<EVP_DigestInit(3)>,
L<evp(7)>, L<HMAC(3)>, L<MD2(3)>,
L<MD5(3)>, L<MDC2(3)>, L<RIPEMD160(3)>,
-L<SHA1(3)>, L<dgst(1)>,
+L<SHA1(3)>, L<openssl-dgst(1)>,
L<RAND(7)>
=head1 HISTORY
@@ -102,11 +179,16 @@ L<RAND(7)>
EVP_DigestVerifyInit(), EVP_DigestVerifyUpdate() and EVP_DigestVerifyFinal()
were added in OpenSSL 1.0.0.
+EVP_DigestVerifyInit_ex() was added in OpenSSL 3.0.
+
+EVP_DigestVerifyUpdate() was converted from a macro to a function in OpenSSL
+3.0.
+
=head1 COPYRIGHT
-Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_EncodeInit.pod b/doc/man3/EVP_EncodeInit.pod
index e8b65d381890..2b9e02e02d79 100644
--- a/doc/man3/EVP_EncodeInit.pod
+++ b/doc/man3/EVP_EncodeInit.pod
@@ -153,7 +153,7 @@ L<evp(7)>
Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_EncryptInit.pod b/doc/man3/EVP_EncryptInit.pod
index a17459a06e03..7d7db3c9f708 100644
--- a/doc/man3/EVP_EncryptInit.pod
+++ b/doc/man3/EVP_EncryptInit.pod
@@ -2,16 +2,22 @@
=head1 NAME
+EVP_CIPHER_fetch,
+EVP_CIPHER_up_ref,
+EVP_CIPHER_free,
EVP_CIPHER_CTX_new,
EVP_CIPHER_CTX_reset,
EVP_CIPHER_CTX_free,
EVP_EncryptInit_ex,
+EVP_EncryptInit_ex2,
EVP_EncryptUpdate,
EVP_EncryptFinal_ex,
EVP_DecryptInit_ex,
+EVP_DecryptInit_ex2,
EVP_DecryptUpdate,
EVP_DecryptFinal_ex,
EVP_CipherInit_ex,
+EVP_CipherInit_ex2,
EVP_CipherUpdate,
EVP_CipherFinal_ex,
EVP_CIPHER_CTX_set_key_length,
@@ -22,56 +28,111 @@ EVP_DecryptInit,
EVP_DecryptFinal,
EVP_CipherInit,
EVP_CipherFinal,
+EVP_Cipher,
EVP_get_cipherbyname,
EVP_get_cipherbynid,
EVP_get_cipherbyobj,
+EVP_CIPHER_is_a,
+EVP_CIPHER_get0_name,
+EVP_CIPHER_get0_description,
+EVP_CIPHER_names_do_all,
+EVP_CIPHER_get0_provider,
+EVP_CIPHER_get_nid,
+EVP_CIPHER_get_params,
+EVP_CIPHER_gettable_params,
+EVP_CIPHER_get_block_size,
+EVP_CIPHER_get_key_length,
+EVP_CIPHER_get_iv_length,
+EVP_CIPHER_get_flags,
+EVP_CIPHER_get_mode,
+EVP_CIPHER_get_type,
+EVP_CIPHER_CTX_cipher,
+EVP_CIPHER_CTX_get0_cipher,
+EVP_CIPHER_CTX_get1_cipher,
+EVP_CIPHER_CTX_get0_name,
+EVP_CIPHER_CTX_get_nid,
+EVP_CIPHER_CTX_get_params,
+EVP_CIPHER_gettable_ctx_params,
+EVP_CIPHER_CTX_gettable_params,
+EVP_CIPHER_CTX_set_params,
+EVP_CIPHER_settable_ctx_params,
+EVP_CIPHER_CTX_settable_params,
+EVP_CIPHER_CTX_get_block_size,
+EVP_CIPHER_CTX_get_key_length,
+EVP_CIPHER_CTX_get_iv_length,
+EVP_CIPHER_CTX_get_tag_length,
+EVP_CIPHER_CTX_get_app_data,
+EVP_CIPHER_CTX_set_app_data,
+EVP_CIPHER_CTX_flags,
+EVP_CIPHER_CTX_set_flags,
+EVP_CIPHER_CTX_clear_flags,
+EVP_CIPHER_CTX_test_flags,
+EVP_CIPHER_CTX_get_type,
+EVP_CIPHER_CTX_get_mode,
+EVP_CIPHER_CTX_get_num,
+EVP_CIPHER_CTX_set_num,
+EVP_CIPHER_CTX_is_encrypting,
+EVP_CIPHER_param_to_asn1,
+EVP_CIPHER_asn1_to_param,
+EVP_CIPHER_CTX_set_padding,
+EVP_enc_null,
+EVP_CIPHER_do_all_provided,
EVP_CIPHER_nid,
+EVP_CIPHER_name,
EVP_CIPHER_block_size,
EVP_CIPHER_key_length,
EVP_CIPHER_iv_length,
EVP_CIPHER_flags,
EVP_CIPHER_mode,
EVP_CIPHER_type,
-EVP_CIPHER_CTX_cipher,
+EVP_CIPHER_CTX_encrypting,
EVP_CIPHER_CTX_nid,
EVP_CIPHER_CTX_block_size,
EVP_CIPHER_CTX_key_length,
EVP_CIPHER_CTX_iv_length,
-EVP_CIPHER_CTX_get_app_data,
-EVP_CIPHER_CTX_set_app_data,
+EVP_CIPHER_CTX_tag_length,
+EVP_CIPHER_CTX_num,
EVP_CIPHER_CTX_type,
-EVP_CIPHER_CTX_flags,
-EVP_CIPHER_CTX_mode,
-EVP_CIPHER_param_to_asn1,
-EVP_CIPHER_asn1_to_param,
-EVP_CIPHER_CTX_set_padding,
-EVP_enc_null
+EVP_CIPHER_CTX_mode
- EVP cipher routines
=head1 SYNOPSIS
-=for comment generic
+=for openssl generic
#include <openssl/evp.h>
+ EVP_CIPHER *EVP_CIPHER_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties);
+ int EVP_CIPHER_up_ref(EVP_CIPHER *cipher);
+ void EVP_CIPHER_free(EVP_CIPHER *cipher);
EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx);
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx);
int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
ENGINE *impl, const unsigned char *key, const unsigned char *iv);
+ int EVP_EncryptInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
+ const unsigned char *key, const unsigned char *iv,
+ const OSSL_PARAM params[]);
int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
ENGINE *impl, const unsigned char *key, const unsigned char *iv);
+ int EVP_DecryptInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
+ const unsigned char *key, const unsigned char *iv,
+ const OSSL_PARAM params[]);
int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc);
+ int EVP_CipherInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
+ const unsigned char *key, const unsigned char *iv,
+ int enc, const OSSL_PARAM params[]);
int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
@@ -88,82 +149,236 @@ EVP_enc_null
const unsigned char *key, const unsigned char *iv, int enc);
int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+ int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, unsigned int inl);
+
int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *x, int padding);
int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
- int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
+ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int cmd, int p1, void *p2);
int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key);
+ void EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags);
+ void EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags);
+ int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags);
const EVP_CIPHER *EVP_get_cipherbyname(const char *name);
const EVP_CIPHER *EVP_get_cipherbynid(int nid);
const EVP_CIPHER *EVP_get_cipherbyobj(const ASN1_OBJECT *a);
- int EVP_CIPHER_nid(const EVP_CIPHER *e);
- int EVP_CIPHER_block_size(const EVP_CIPHER *e);
- int EVP_CIPHER_key_length(const EVP_CIPHER *e);
- int EVP_CIPHER_iv_length(const EVP_CIPHER *e);
- unsigned long EVP_CIPHER_flags(const EVP_CIPHER *e);
- unsigned long EVP_CIPHER_mode(const EVP_CIPHER *e);
- int EVP_CIPHER_type(const EVP_CIPHER *ctx);
-
- const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx);
- int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx);
- int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx);
- int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx);
- int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx);
+ int EVP_CIPHER_get_nid(const EVP_CIPHER *e);
+ int EVP_CIPHER_is_a(const EVP_CIPHER *cipher, const char *name);
+ int EVP_CIPHER_names_do_all(const EVP_CIPHER *cipher,
+ void (*fn)(const char *name, void *data),
+ void *data);
+ const char *EVP_CIPHER_get0_name(const EVP_CIPHER *cipher);
+ const char *EVP_CIPHER_get0_description(const EVP_CIPHER *cipher);
+ const OSSL_PROVIDER *EVP_CIPHER_get0_provider(const EVP_CIPHER *cipher);
+ int EVP_CIPHER_get_block_size(const EVP_CIPHER *e);
+ int EVP_CIPHER_get_key_length(const EVP_CIPHER *e);
+ int EVP_CIPHER_get_iv_length(const EVP_CIPHER *e);
+ unsigned long EVP_CIPHER_get_flags(const EVP_CIPHER *e);
+ unsigned long EVP_CIPHER_get_mode(const EVP_CIPHER *e);
+ int EVP_CIPHER_get_type(const EVP_CIPHER *cipher);
+
+ const EVP_CIPHER *EVP_CIPHER_CTX_get0_cipher(const EVP_CIPHER_CTX *ctx);
+ EVP_CIPHER *EVP_CIPHER_CTX_get1_cipher(const EVP_CIPHER_CTX *ctx);
+ int EVP_CIPHER_CTX_get_nid(const EVP_CIPHER_CTX *ctx);
+ const char *EVP_CIPHER_CTX_get0_name(const EVP_CIPHER_CTX *ctx);
+
+ int EVP_CIPHER_get_params(EVP_CIPHER *cipher, OSSL_PARAM params[]);
+ int EVP_CIPHER_CTX_set_params(EVP_CIPHER_CTX *ctx, const OSSL_PARAM params[]);
+ int EVP_CIPHER_CTX_get_params(EVP_CIPHER_CTX *ctx, OSSL_PARAM params[]);
+ const OSSL_PARAM *EVP_CIPHER_gettable_params(const EVP_CIPHER *cipher);
+ const OSSL_PARAM *EVP_CIPHER_settable_ctx_params(const EVP_CIPHER *cipher);
+ const OSSL_PARAM *EVP_CIPHER_gettable_ctx_params(const EVP_CIPHER *cipher);
+ const OSSL_PARAM *EVP_CIPHER_CTX_settable_params(EVP_CIPHER_CTX *ctx);
+ const OSSL_PARAM *EVP_CIPHER_CTX_gettable_params(EVP_CIPHER_CTX *ctx);
+ int EVP_CIPHER_CTX_get_block_size(const EVP_CIPHER_CTX *ctx);
+ int EVP_CIPHER_CTX_get_key_length(const EVP_CIPHER_CTX *ctx);
+ int EVP_CIPHER_CTX_get_iv_length(const EVP_CIPHER_CTX *ctx);
+ int EVP_CIPHER_CTX_get_tag_length(const EVP_CIPHER_CTX *ctx);
void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx);
void EVP_CIPHER_CTX_set_app_data(const EVP_CIPHER_CTX *ctx, void *data);
- int EVP_CIPHER_CTX_type(const EVP_CIPHER_CTX *ctx);
- int EVP_CIPHER_CTX_mode(const EVP_CIPHER_CTX *ctx);
+ int EVP_CIPHER_CTX_get_type(const EVP_CIPHER_CTX *ctx);
+ int EVP_CIPHER_CTX_get_mode(const EVP_CIPHER_CTX *ctx);
+ int EVP_CIPHER_CTX_get_num(const EVP_CIPHER_CTX *ctx);
+ int EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num);
+ int EVP_CIPHER_CTX_is_encrypting(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
+ void EVP_CIPHER_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_CIPHER *cipher, void *arg),
+ void *arg);
+
+ #define EVP_CIPHER_nid EVP_CIPHER_get_nid
+ #define EVP_CIPHER_name EVP_CIPHER_get0_name
+ #define EVP_CIPHER_block_size EVP_CIPHER_get_block_size
+ #define EVP_CIPHER_key_length EVP_CIPHER_get_key_length
+ #define EVP_CIPHER_iv_length EVP_CIPHER_get_iv_length
+ #define EVP_CIPHER_flags EVP_CIPHER_get_flags
+ #define EVP_CIPHER_mode EVP_CIPHER_get_mode
+ #define EVP_CIPHER_type EVP_CIPHER_get_type
+ #define EVP_CIPHER_CTX_encrypting EVP_CIPHER_CTX_is_encrypting
+ #define EVP_CIPHER_CTX_nid EVP_CIPHER_CTX_get_nid
+ #define EVP_CIPHER_CTX_block_size EVP_CIPHER_CTX_get_block_size
+ #define EVP_CIPHER_CTX_key_length EVP_CIPHER_CTX_get_key_length
+ #define EVP_CIPHER_CTX_iv_length EVP_CIPHER_CTX_get_iv_length
+ #define EVP_CIPHER_CTX_tag_length EVP_CIPHER_CTX_get_tag_length
+ #define EVP_CIPHER_CTX_num EVP_CIPHER_CTX_get_num
+ #define EVP_CIPHER_CTX_type EVP_CIPHER_CTX_get_type
+ #define EVP_CIPHER_CTX_mode EVP_CIPHER_CTX_get_mode
+
+The following function has been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx);
+
+The following function has been deprecated since OpenSSL 1.1.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ int EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx);
+
=head1 DESCRIPTION
The EVP cipher routines are a high-level interface to certain
symmetric ciphers.
-EVP_CIPHER_CTX_new() creates a cipher context.
-
-EVP_CIPHER_CTX_free() clears all information from a cipher context
-and free up any allocated memory associate with it, including B<ctx>
-itself. This function should be called after all operations using a
-cipher are complete so sensitive information does not remain in
-memory.
-
-EVP_EncryptInit_ex() sets up cipher context B<ctx> for encryption
-with cipher B<type> from ENGINE B<impl>. B<ctx> must be created
-before calling this function. B<type> is normally supplied
-by a function such as EVP_aes_256_cbc(). If B<impl> is NULL then the
-default implementation is used. B<key> is the symmetric key to use
-and B<iv> is the IV to use (if necessary), the actual number of bytes
-used for the key and IV depends on the cipher. It is possible to set
-all parameters to NULL except B<type> in an initial call and supply
-the remaining parameters in subsequent calls, all of which have B<type>
-set to NULL. This is done when the default cipher parameters are not
-appropriate.
-
-EVP_EncryptUpdate() encrypts B<inl> bytes from the buffer B<in> and
-writes the encrypted version to B<out>. This function can be called
-multiple times to encrypt successive blocks of data. The amount
-of data written depends on the block alignment of the encrypted data.
+The B<EVP_CIPHER> type is a structure for cipher method implementation.
+
+=over 4
+
+=item EVP_CIPHER_fetch()
+
+Fetches the cipher implementation for the given I<algorithm> from any provider
+offering it, within the criteria given by the I<properties>.
+See L<crypto(7)/ALGORITHM FETCHING> for further information.
+
+The returned value must eventually be freed with EVP_CIPHER_free().
+
+Fetched B<EVP_CIPHER> structures are reference counted.
+
+=item EVP_CIPHER_up_ref()
+
+Increments the reference count for an B<EVP_CIPHER> structure.
+
+=item EVP_CIPHER_free()
+
+Decrements the reference count for the fetched B<EVP_CIPHER> structure.
+If the reference count drops to 0 then the structure is freed.
+
+=item EVP_CIPHER_CTX_new()
+
+Allocates and returns a cipher context.
+
+=item EVP_CIPHER_CTX_free()
+
+Clears all information from a cipher context and frees any allocated memory
+associated with it, including I<ctx> itself. This function should be called after
+all operations using a cipher are complete so sensitive information does not
+remain in memory.
+
+=item EVP_CIPHER_CTX_ctrl()
+
+I<This is a legacy method.> EVP_CIPHER_CTX_set_params() and
+EVP_CIPHER_CTX_get_params() is the mechanism that should be used to set and get
+parameters that are used by providers.
+
+Performs cipher-specific control actions on context I<ctx>. The control command
+is indicated in I<cmd> and any additional arguments in I<p1> and I<p2>.
+EVP_CIPHER_CTX_ctrl() must be called after EVP_CipherInit_ex2(). Other restrictions
+may apply depending on the control type and cipher implementation.
+
+If this function happens to be used with a fetched B<EVP_CIPHER>, it will
+translate the controls that are known to OpenSSL into L<OSSL_PARAM(3)>
+parameters with keys defined by OpenSSL and call EVP_CIPHER_CTX_get_params() or
+EVP_CIPHER_CTX_set_params() as is appropriate for each control command.
+
+See L</CONTROLS> below for more information, including what translations are
+being done.
+
+=item EVP_CIPHER_get_params()
+
+Retrieves the requested list of algorithm I<params> from a CIPHER I<cipher>.
+See L</PARAMETERS> below for more information.
+
+=item EVP_CIPHER_CTX_get_params()
+
+Retrieves the requested list of I<params> from CIPHER context I<ctx>.
+See L</PARAMETERS> below for more information.
+
+=item EVP_CIPHER_CTX_set_params()
+
+Sets the list of I<params> into a CIPHER context I<ctx>.
+See L</PARAMETERS> below for more information.
+
+=item EVP_CIPHER_gettable_params()
+
+Get a constant L<OSSL_PARAM(3)> array that describes the retrievable parameters
+that can be used with EVP_CIPHER_get_params().
+
+=item EVP_CIPHER_gettable_ctx_params() and EVP_CIPHER_CTX_gettable_params()
+
+Get a constant L<OSSL_PARAM(3)> array that describes the retrievable parameters
+that can be used with EVP_CIPHER_CTX_get_params().
+EVP_CIPHER_gettable_ctx_params() returns the parameters that can be retrieved
+from the algorithm, whereas EVP_CIPHER_CTX_gettable_params() returns the
+parameters that can be retrieved in the context's current state.
+
+=item EVP_CIPHER_settable_ctx_params() and EVP_CIPHER_CTX_settable_params()
+
+Get a constant L<OSSL_PARAM(3)> array that describes the settable parameters
+that can be used with EVP_CIPHER_CTX_set_params().
+EVP_CIPHER_settable_ctx_params() returns the parameters that can be set from the
+algorithm, whereas EVP_CIPHER_CTX_settable_params() returns the parameters that
+can be set in the context's current state.
+
+=item EVP_EncryptInit_ex2()
+
+Sets up cipher context I<ctx> for encryption with cipher I<type>. I<type> is
+typically supplied by calling EVP_CIPHER_fetch(). I<type> may also be set
+using legacy functions such as EVP_aes_256_cbc(), but this is not recommended
+for new applications. I<key> is the symmetric key to use and I<iv> is the IV to
+use (if necessary), the actual number of bytes used for the key and IV depends
+on the cipher. The parameters I<params> will be set on the context after
+initialisation. It is possible to set all parameters to NULL except I<type> in
+an initial call and supply the remaining parameters in subsequent calls, all of
+which have I<type> set to NULL. This is done when the default cipher parameters
+are not appropriate.
+For B<EVP_CIPH_GCM_MODE> the IV will be generated internally if it is not
+specified.
+
+=item EVP_EncryptInit_ex()
+
+This legacy function is similar to EVP_EncryptInit_ex2() when I<impl> is NULL.
+The implementation of the I<type> from the I<impl> engine will be used if it
+exists.
+
+=item EVP_EncryptUpdate()
+
+Encrypts I<inl> bytes from the buffer I<in> and writes the encrypted version to
+I<out>. This function can be called multiple times to encrypt successive blocks
+of data. The amount of data written depends on the block alignment of the
+encrypted data.
For most ciphers and modes, the amount of data written can be anything
from zero bytes to (inl + cipher_block_size - 1) bytes.
For wrap cipher modes, the amount of data written can be anything
from zero bytes to (inl + cipher_block_size) bytes.
For stream ciphers, the amount of data written can be anything from zero
bytes to inl bytes.
-Thus, B<out> should contain sufficient room for the operation being performed.
-The actual number of bytes written is placed in B<outl>. It also
-checks if B<in> and B<out> are partially overlapping, and if they are
+Thus, I<out> should contain sufficient room for the operation being performed.
+The actual number of bytes written is placed in I<outl>. It also
+checks if I<in> and I<out> are partially overlapping, and if they are
0 is returned to indicate failure.
If padding is enabled (the default) then EVP_EncryptFinal_ex() encrypts
the "final" data, that is any data that remains in a partial block.
It uses standard block padding (aka PKCS padding) as described in
the NOTES section, below. The encrypted
-final data is written to B<out> which should have sufficient space for
-one cipher block. The number of bytes written is placed in B<outl>. After
+final data is written to I<out> which should have sufficient space for
+one cipher block. The number of bytes written is placed in I<outl>. After
this function is called the encryption operation is finished and no further
calls to EVP_EncryptUpdate() should be made.
@@ -171,102 +386,225 @@ If padding is disabled then EVP_EncryptFinal_ex() will not encrypt any more
data and it will return an error if any data remains in a partial block:
that is if the total data length is not a multiple of the block size.
-EVP_DecryptInit_ex(), EVP_DecryptUpdate() and EVP_DecryptFinal_ex() are the
-corresponding decryption operations. EVP_DecryptFinal() will return an
-error code if padding is enabled and the final block is not correctly
-formatted. The parameters and restrictions are identical to the encryption
-operations except that if padding is enabled the decrypted data buffer B<out>
-passed to EVP_DecryptUpdate() should have sufficient room for
-(B<inl> + cipher_block_size) bytes unless the cipher block size is 1 in
-which case B<inl> bytes is sufficient.
-
-EVP_CipherInit_ex(), EVP_CipherUpdate() and EVP_CipherFinal_ex() are
-functions that can be used for decryption or encryption. The operation
-performed depends on the value of the B<enc> parameter. It should be set
-to 1 for encryption, 0 for decryption and -1 to leave the value unchanged
+=item EVP_DecryptInit_ex2(), EVP_DecryptInit_ex(), EVP_DecryptUpdate()
+and EVP_DecryptFinal_ex()
+
+These functions are the corresponding decryption operations.
+EVP_DecryptFinal() will return an error code if padding is enabled and the
+final block is not correctly formatted. The parameters and restrictions are
+identical to the encryption operations except that if padding is enabled the
+decrypted data buffer I<out> passed to EVP_DecryptUpdate() should have
+sufficient room for (I<inl> + cipher_block_size) bytes unless the cipher block
+size is 1 in which case I<inl> bytes is sufficient.
+
+=item EVP_CipherInit_ex2(), EVP_CipherInit_ex(), EVP_CipherUpdate() and
+EVP_CipherFinal_ex()
+
+These functions can be used for decryption or encryption. The operation
+performed depends on the value of the I<enc> parameter. It should be set to 1
+for encryption, 0 for decryption and -1 to leave the value unchanged
(the actual value of 'enc' being supplied in a previous call).
-EVP_CIPHER_CTX_reset() clears all information from a cipher context
-and free up any allocated memory associate with it, except the B<ctx>
-itself. This function should be called anytime B<ctx> is to be reused
-for another EVP_CipherInit() / EVP_CipherUpdate() / EVP_CipherFinal()
-series of calls.
+=item EVP_CIPHER_CTX_reset()
+
+Clears all information from a cipher context and free up any allocated memory
+associated with it, except the I<ctx> itself. This function should be called
+anytime I<ctx> is reused by another
+EVP_CipherInit() / EVP_CipherUpdate() / EVP_CipherFinal() series of calls.
+
+=item EVP_EncryptInit(), EVP_DecryptInit() and EVP_CipherInit()
+
+Behave in a similar way to EVP_EncryptInit_ex(), EVP_DecryptInit_ex() and
+EVP_CipherInit_ex() except if the I<type> is not a fetched cipher they use the
+default implementation of the I<type>.
-EVP_EncryptInit(), EVP_DecryptInit() and EVP_CipherInit() behave in a
-similar way to EVP_EncryptInit_ex(), EVP_DecryptInit_ex() and
-EVP_CipherInit_ex() except they always use the default cipher implementation.
+=item EVP_EncryptFinal(), EVP_DecryptFinal() and EVP_CipherFinal()
-EVP_EncryptFinal(), EVP_DecryptFinal() and EVP_CipherFinal() are
-identical to EVP_EncryptFinal_ex(), EVP_DecryptFinal_ex() and
+Identical to EVP_EncryptFinal_ex(), EVP_DecryptFinal_ex() and
EVP_CipherFinal_ex(). In previous releases they also cleaned up
-the B<ctx>, but this is no longer done and EVP_CIPHER_CTX_clean()
+the I<ctx>, but this is no longer done and EVP_CIPHER_CTX_cleanup()
must be called to free any context resources.
-EVP_get_cipherbyname(), EVP_get_cipherbynid() and EVP_get_cipherbyobj()
-return an EVP_CIPHER structure when passed a cipher name, a NID or an
-ASN1_OBJECT structure.
-
-EVP_CIPHER_nid() and EVP_CIPHER_CTX_nid() return the NID of a cipher when
-passed an B<EVP_CIPHER> or B<EVP_CIPHER_CTX> structure. The actual NID
-value is an internal value which may not have a corresponding OBJECT
-IDENTIFIER.
-
-EVP_CIPHER_CTX_set_padding() enables or disables padding. This
-function should be called after the context is set up for encryption
-or decryption with EVP_EncryptInit_ex(), EVP_DecryptInit_ex() or
-EVP_CipherInit_ex(). By default encryption operations are padded using
-standard block padding and the padding is checked and removed when
-decrypting. If the B<pad> parameter is zero then no padding is
+=item EVP_Cipher()
+
+Encrypts or decrypts a maximum I<inl> amount of bytes from I<in> and leaves the
+result in I<out>.
+
+For legacy ciphers - If the cipher doesn't have the flag
+B<EVP_CIPH_FLAG_CUSTOM_CIPHER> set, then I<inl> must be a multiple of
+EVP_CIPHER_get_block_size(). If it isn't, the result is undefined. If the cipher
+has that flag set, then I<inl> can be any size.
+
+Due to the constraints of the API contract of this function it shouldn't be used
+in applications, please consider using EVP_CipherUpdate() and
+EVP_CipherFinal_ex() instead.
+
+=item EVP_get_cipherbyname(), EVP_get_cipherbynid() and EVP_get_cipherbyobj()
+
+Returns an B<EVP_CIPHER> structure when passed a cipher name, a cipher B<NID> or
+an B<ASN1_OBJECT> structure respectively.
+
+EVP_get_cipherbyname() will return NULL for algorithms such as "AES-128-SIV",
+"AES-128-CBC-CTS" and "CAMELLIA-128-CBC-CTS" which were previously only
+accessible via low level interfaces.
+
+The EVP_get_cipherbyname() function is present for backwards compatibility with
+OpenSSL prior to version 3 and is different to the EVP_CIPHER_fetch() function
+since it does not attempt to "fetch" an implementation of the cipher.
+Additionally, it only knows about ciphers that are built-in to OpenSSL and have
+an associated NID. Similarly EVP_get_cipherbynid() and EVP_get_cipherbyobj()
+also return objects without an associated implementation.
+
+When the cipher objects returned by these functions are used (such as in a call
+to EVP_EncryptInit_ex()) an implementation of the cipher will be implicitly
+fetched from the loaded providers. This fetch could fail if no suitable
+implementation is available. Use EVP_CIPHER_fetch() instead to explicitly fetch
+the algorithm and an associated implementation from a provider.
+
+See L<crypto(7)/ALGORITHM FETCHING> for more information about fetching.
+
+The cipher objects returned from these functions do not need to be freed with
+EVP_CIPHER_free().
+
+=item EVP_CIPHER_get_nid() and EVP_CIPHER_CTX_get_nid()
+
+Return the NID of a cipher when passed an B<EVP_CIPHER> or B<EVP_CIPHER_CTX>
+structure. The actual NID value is an internal value which may not have a
+corresponding OBJECT IDENTIFIER.
+
+=item EVP_CIPHER_CTX_set_flags(), EVP_CIPHER_CTX_clear_flags() and EVP_CIPHER_CTX_test_flags()
+
+Sets, clears and tests I<ctx> flags. See L</FLAGS> below for more information.
+
+For provided ciphers EVP_CIPHER_CTX_set_flags() should be called only after the
+fetched cipher has been assigned to the I<ctx>. It is recommended to use
+L</PARAMETERS> instead.
+
+=item EVP_CIPHER_CTX_set_padding()
+
+Enables or disables padding. This function should be called after the context
+is set up for encryption or decryption with EVP_EncryptInit_ex2(),
+EVP_DecryptInit_ex2() or EVP_CipherInit_ex2(). By default encryption operations
+are padded using standard block padding and the padding is checked and removed
+when decrypting. If the I<pad> parameter is zero then no padding is
performed, the total amount of data encrypted or decrypted must then
be a multiple of the block size or an error will occur.
-EVP_CIPHER_key_length() and EVP_CIPHER_CTX_key_length() return the key
-length of a cipher when passed an B<EVP_CIPHER> or B<EVP_CIPHER_CTX>
-structure. The constant B<EVP_MAX_KEY_LENGTH> is the maximum key length
-for all ciphers. Note: although EVP_CIPHER_key_length() is fixed for a
-given cipher, the value of EVP_CIPHER_CTX_key_length() may be different
-for variable key length ciphers.
+=item EVP_CIPHER_get_key_length() and EVP_CIPHER_CTX_get_key_length()
-EVP_CIPHER_CTX_set_key_length() sets the key length of the cipher ctx.
+Return the key length of a cipher when passed an B<EVP_CIPHER> or
+B<EVP_CIPHER_CTX> structure. The constant B<EVP_MAX_KEY_LENGTH> is the maximum
+key length for all ciphers. Note: although EVP_CIPHER_get_key_length() is fixed for
+a given cipher, the value of EVP_CIPHER_CTX_get_key_length() may be different for
+variable key length ciphers.
+
+=item EVP_CIPHER_CTX_set_key_length()
+
+Sets the key length of the cipher context.
If the cipher is a fixed length cipher then attempting to set the key
length to any value other than the fixed value is an error.
-EVP_CIPHER_iv_length() and EVP_CIPHER_CTX_iv_length() return the IV
-length of a cipher when passed an B<EVP_CIPHER> or B<EVP_CIPHER_CTX>.
-It will return zero if the cipher does not use an IV. The constant
-B<EVP_MAX_IV_LENGTH> is the maximum IV length for all ciphers.
-
-EVP_CIPHER_block_size() and EVP_CIPHER_CTX_block_size() return the block
-size of a cipher when passed an B<EVP_CIPHER> or B<EVP_CIPHER_CTX>
-structure. The constant B<EVP_MAX_BLOCK_LENGTH> is also the maximum block
-length for all ciphers.
-
-EVP_CIPHER_type() and EVP_CIPHER_CTX_type() return the type of the passed
-cipher or context. This "type" is the actual NID of the cipher OBJECT
-IDENTIFIER as such it ignores the cipher parameters and 40 bit RC2 and
-128 bit RC2 have the same NID. If the cipher does not have an object
-identifier or does not have ASN1 support this function will return
+=item EVP_CIPHER_get_iv_length() and EVP_CIPHER_CTX_get_iv_length()
+
+Return the IV length of a cipher when passed an B<EVP_CIPHER> or
+B<EVP_CIPHER_CTX>. It will return zero if the cipher does not use an IV.
+The constant B<EVP_MAX_IV_LENGTH> is the maximum IV length for all ciphers.
+
+=item EVP_CIPHER_CTX_get_tag_length()
+
+Returns the tag length of an AEAD cipher when passed a B<EVP_CIPHER_CTX>. It will
+return zero if the cipher does not support a tag. It returns a default value if
+the tag length has not been set.
+
+=item EVP_CIPHER_get_block_size() and EVP_CIPHER_CTX_get_block_size()
+
+Return the block size of a cipher when passed an B<EVP_CIPHER> or
+B<EVP_CIPHER_CTX> structure. The constant B<EVP_MAX_BLOCK_LENGTH> is also the
+maximum block length for all ciphers.
+
+=item EVP_CIPHER_get_type() and EVP_CIPHER_CTX_get_type()
+
+Return the type of the passed cipher or context. This "type" is the actual NID
+of the cipher OBJECT IDENTIFIER and as such it ignores the cipher parameters
+(40 bit RC2 and 128 bit RC2 have the same NID). If the cipher does not have an
+object identifier or does not have ASN1 support this function will return
B<NID_undef>.
-EVP_CIPHER_CTX_cipher() returns the B<EVP_CIPHER> structure when passed
-an B<EVP_CIPHER_CTX> structure.
+=item EVP_CIPHER_is_a()
+
+Returns 1 if I<cipher> is an implementation of an algorithm that's identifiable
+with I<name>, otherwise 0. If I<cipher> is a legacy cipher (it's the return
+value from the likes of EVP_aes128() rather than the result of an
+EVP_CIPHER_fetch()), only cipher names registered with the default library
+context (see L<OSSL_LIB_CTX(3)>) will be considered.
+
+=item EVP_CIPHER_get0_name() and EVP_CIPHER_CTX_get0_name()
-EVP_CIPHER_mode() and EVP_CIPHER_CTX_mode() return the block cipher mode:
+Return the name of the passed cipher or context. For fetched ciphers with
+multiple names, only one of them is returned. See also EVP_CIPHER_names_do_all().
+
+=item EVP_CIPHER_names_do_all()
+
+Traverses all names for the I<cipher>, and calls I<fn> with each name and
+I<data>. This is only useful with fetched B<EVP_CIPHER>s.
+
+=item EVP_CIPHER_get0_description()
+
+Returns a description of the cipher, meant for display and human consumption.
+The description is at the discretion of the cipher implementation.
+
+=item EVP_CIPHER_get0_provider()
+
+Returns an B<OSSL_PROVIDER> pointer to the provider that implements the given
+B<EVP_CIPHER>.
+
+=item EVP_CIPHER_CTX_get0_cipher()
+
+Returns the B<EVP_CIPHER> structure when passed an B<EVP_CIPHER_CTX> structure.
+EVP_CIPHER_CTX_get1_cipher() is the same except the ownership is passed to
+the caller.
+
+=item EVP_CIPHER_get_mode() and EVP_CIPHER_CTX_get_mode()
+
+Return the block cipher mode:
EVP_CIPH_ECB_MODE, EVP_CIPH_CBC_MODE, EVP_CIPH_CFB_MODE, EVP_CIPH_OFB_MODE,
EVP_CIPH_CTR_MODE, EVP_CIPH_GCM_MODE, EVP_CIPH_CCM_MODE, EVP_CIPH_XTS_MODE,
-EVP_CIPH_WRAP_MODE or EVP_CIPH_OCB_MODE. If the cipher is a stream cipher then
-EVP_CIPH_STREAM_CIPHER is returned.
-
-EVP_CIPHER_param_to_asn1() sets the AlgorithmIdentifier "parameter" based
-on the passed cipher. This will typically include any parameters and an
-IV. The cipher IV (if any) must be set when this call is made. This call
-should be made before the cipher is actually "used" (before any
-EVP_EncryptUpdate(), EVP_DecryptUpdate() calls for example). This function
-may fail if the cipher does not have any ASN1 support.
-
-EVP_CIPHER_asn1_to_param() sets the cipher parameters based on an ASN1
-AlgorithmIdentifier "parameter". The precise effect depends on the cipher
-In the case of RC2, for example, it will set the IV and effective key length.
+EVP_CIPH_WRAP_MODE, EVP_CIPH_OCB_MODE or EVP_CIPH_SIV_MODE.
+If the cipher is a stream cipher then EVP_CIPH_STREAM_CIPHER is returned.
+
+=item EVP_CIPHER_get_flags()
+
+Returns any flags associated with the cipher. See L</FLAGS>
+for a list of currently defined flags.
+
+=item EVP_CIPHER_CTX_get_num() and EVP_CIPHER_CTX_set_num()
+
+Gets or sets the cipher specific "num" parameter for the associated I<ctx>.
+Built-in ciphers typically use this to track how much of the current underlying block
+has been "used" already.
+
+=item EVP_CIPHER_CTX_is_encrypting()
+
+Reports whether the I<ctx> is being used for encryption or decryption.
+
+=item EVP_CIPHER_CTX_flags()
+
+A deprecated macro calling C<EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx))>.
+Do not use.
+
+=item EVP_CIPHER_param_to_asn1()
+
+Sets the AlgorithmIdentifier "parameter" based on the passed cipher. This will
+typically include any parameters and an IV. The cipher IV (if any) must be set
+when this call is made. This call should be made before the cipher is actually
+"used" (before any EVP_EncryptUpdate(), EVP_DecryptUpdate() calls for example).
+This function may fail if the cipher does not have any ASN1 support.
+
+=item EVP_CIPHER_asn1_to_param()
+
+Sets the cipher parameters based on an ASN1 AlgorithmIdentifier "parameter".
+The precise effect depends on the cipher. In the case of B<RC2>, for example,
+it will set the IV and effective key length.
This function should be called after the base cipher type is set but before
the key is set. For example EVP_CipherInit() will be called with the IV and
key set to NULL, EVP_CIPHER_asn1_to_param() will be called and finally
@@ -275,61 +613,641 @@ possible for this function to fail if the cipher does not have any ASN1 support
or the parameters cannot be set (for example the RC2 effective key length
is not supported.
-EVP_CIPHER_CTX_ctrl() allows various cipher specific parameters to be determined
-and set.
+=item EVP_CIPHER_CTX_rand_key()
+
+Generates a random key of the appropriate length based on the cipher context.
+The B<EVP_CIPHER> can provide its own random key generation routine to support
+keys of a specific form. I<key> must point to a buffer at least as big as the
+value returned by EVP_CIPHER_CTX_get_key_length().
+
+=item EVP_CIPHER_do_all_provided()
+
+Traverses all ciphers implemented by all activated providers in the given
+library context I<libctx>, and for each of the implementations, calls the given
+function I<fn> with the implementation method and the given I<arg> as argument.
+
+=back
+
+=head1 PARAMETERS
+
+See L<OSSL_PARAM(3)> for information about passing parameters.
+
+=head2 Gettable EVP_CIPHER parameters
+
+When EVP_CIPHER_fetch() is called it internally calls EVP_CIPHER_get_params()
+and caches the results.
+
+EVP_CIPHER_get_params() can be used with the following L<OSSL_PARAM(3)> keys:
+
+=over 4
+
+=item "mode" (B<OSSL_CIPHER_PARAM_MODE>) <unsigned integer>
+
+Gets the mode for the associated cipher algorithm I<cipher>.
+See L</EVP_CIPHER_get_mode() and EVP_CIPHER_CTX_get_mode()> for a list of valid modes.
+Use EVP_CIPHER_get_mode() to retrieve the cached value.
+
+=item "keylen" (B<OSSL_CIPHER_PARAM_KEYLEN>) <unsigned integer>
+
+Gets the key length for the associated cipher algorithm I<cipher>.
+Use EVP_CIPHER_get_key_length() to retrieve the cached value.
+
+=item "ivlen" (B<OSSL_CIPHER_PARAM_IVLEN>) <unsigned integer>
+
+Gets the IV length for the associated cipher algorithm I<cipher>.
+Use EVP_CIPHER_get_iv_length() to retrieve the cached value.
+
+=item "blocksize" (B<OSSL_CIPHER_PARAM_BLOCK_SIZE>) <unsigned integer>
+
+Gets the block size for the associated cipher algorithm I<cipher>.
+The block size should be 1 for stream ciphers.
+Note that the block size for a cipher may be different to the block size for
+the underlying encryption/decryption primitive.
+For example AES in CTR mode has a block size of 1 (because it operates like a
+stream cipher), even though AES has a block size of 16.
+Use EVP_CIPHER_get_block_size() to retreive the cached value.
+
+=item "aead" (B<OSSL_CIPHER_PARAM_AEAD>) <integer>
+
+Gets 1 if this is an AEAD cipher algorithm, otherwise it gets 0.
+Use (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) to retrieve the
+cached value.
+
+=item "custom-iv" (B<OSSL_CIPHER_PARAM_CUSTOM_IV>) <integer>
+
+Gets 1 if the cipher algorithm I<cipher> has a custom IV, otherwise it gets 0.
+Storing and initializing the IV is left entirely to the implementation, if a
+custom IV is used.
+Use (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_CUSTOM_IV) to retrieve the
+cached value.
+
+=item "cts" (B<OSSL_CIPHER_PARAM_CTS>) <integer>
+
+Gets 1 if the cipher algorithm I<cipher> uses ciphertext stealing,
+otherwise it gets 0.
+This is currently used to indicate that the cipher is a one shot that only
+allows a single call to EVP_CipherUpdate().
+Use (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_CTS) to retrieve the
+cached value.
+
+=item "tls-multi" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK>) <integer>
+
+Gets 1 if the cipher algorithm I<cipher> supports interleaving of crypto blocks,
+otherwise it gets 0. The interleaving is an optimization only applicable to certain
+TLS ciphers.
+Use (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) to retrieve the
+cached value.
+
+=item "has-randkey" (B<OSSL_CIPHER_PARAM_HAS_RANDKEY>) <integer>
+
+Gets 1 if the cipher algorithm I<cipher> supports the gettable EVP_CIPHER_CTX
+parameter B<OSSL_CIPHER_PARAM_RANDOM_KEY>. Only DES and 3DES set this to 1,
+all other OpenSSL ciphers return 0.
+
+=back
+
+=head2 Gettable and Settable EVP_CIPHER_CTX parameters
+
+The following L<OSSL_PARAM(3)> keys can be used with both EVP_CIPHER_CTX_get_params()
+and EVP_CIPHER_CTX_set_params().
+
+=over 4
+
+=item "padding" (B<OSSL_CIPHER_PARAM_PADDING>) <unsigned integer>
+
+Gets or sets the padding mode for the cipher context I<ctx>.
+Padding is enabled if the value is 1, and disabled if the value is 0.
+See also EVP_CIPHER_CTX_set_padding().
+
+=item "num" (B<OSSL_CIPHER_PARAM_NUM>) <unsigned integer>
+
+Gets or sets the cipher specific "num" parameter for the cipher context I<ctx>.
+Built-in ciphers typically use this to track how much of the current underlying
+block has been "used" already.
+See also EVP_CIPHER_CTX_get_num() and EVP_CIPHER_CTX_set_num().
+
+=item "keylen" (B<OSSL_CIPHER_PARAM_KEYLEN>) <unsigned integer>
+
+Gets or sets the key length for the cipher context I<ctx>.
+The length of the "keylen" parameter should not exceed that of a B<size_t>.
+See also EVP_CIPHER_CTX_get_key_length() and EVP_CIPHER_CTX_set_key_length().
+
+=item "tag" (B<OSSL_CIPHER_PARAM_AEAD_TAG>) <octet string>
+
+Gets or sets the AEAD tag for the associated cipher context I<ctx>.
+See L<EVP_EncryptInit(3)/AEAD Interface>.
+
+=item "keybits" (B<OSSL_CIPHER_PARAM_RC2_KEYBITS>) <unsigned integer>
+
+Gets or sets the effective keybits used for a RC2 cipher.
+The length of the "keybits" parameter should not exceed that of a B<size_t>.
+
+=item "rounds" (B<OSSL_CIPHER_PARAM_ROUNDS>) <unsigned integer>
+
+Gets or sets the number of rounds to be used for a cipher.
+This is used by the RC5 cipher.
+
+=item "alg_id_param" (B<OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS>) <octet string>
+
+Used to pass the DER encoded AlgorithmIdentifier parameter to or from
+the cipher implementation. Functions like L<EVP_CIPHER_param_to_asn1(3)>
+and L<EVP_CIPHER_asn1_to_param(3)> use this parameter for any implementation
+that has the flag B<EVP_CIPH_FLAG_CUSTOM_ASN1> set.
+
+=item "cts_mode" (B<OSSL_CIPHER_PARAM_CTS_MODE>) <UTF8 string>
+
+Gets or sets the cipher text stealing mode. For all modes the output size is the
+same as the input size. The input length must be greater than or equal to the
+block size. (The block size for AES and CAMELLIA is 16 bytes).
+
+Valid values for the mode are:
+
+=over 4
+
+=item "CS1"
+
+The NIST variant of cipher text stealing.
+For input lengths that are multiples of the block size it is equivalent to
+using a "AES-XXX-CBC" or "CAMELLIA-XXX-CBC" cipher otherwise the second last
+cipher text block is a partial block.
+
+=item "CS2"
+
+For input lengths that are multiples of the block size it is equivalent to
+using a "AES-XXX-CBC" or "CAMELLIA-XXX-CBC" cipher, otherwise it is the same as
+"CS3" mode.
+
+=item "CS3"
+
+The Kerberos5 variant of cipher text stealing which always swaps the last
+cipher text block with the previous block (which may be a partial or full block
+depending on the input length). If the input length is exactly one full block
+then this is equivalent to using a "AES-XXX-CBC" or "CAMELLIA-XXX-CBC" cipher.
+
+=back
+
+The default is "CS1".
+This is only supported for "AES-128-CBC-CTS", "AES-192-CBC-CTS", "AES-256-CBC-CTS",
+"CAMELLIA-128-CBC-CTS", "CAMELLIA-192-CBC-CTS" and "CAMELLIA-256-CBC-CTS".
+
+=item "tls1multi_interleave" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE>) <unsigned integer>
+
+Sets or gets the number of records being sent in one go for a tls1 multiblock
+cipher operation (either 4 or 8 records).
+
+=back
+
+=head2 Gettable EVP_CIPHER_CTX parameters
+
+The following L<OSSL_PARAM(3)> keys can be used with EVP_CIPHER_CTX_get_params():
+
+=over 4
-EVP_CIPHER_CTX_rand_key() generates a random key of the appropriate length
-based on the cipher context. The EVP_CIPHER can provide its own random key
-generation routine to support keys of a specific form. B<Key> must point to a
-buffer at least as big as the value returned by EVP_CIPHER_CTX_key_length().
+=item "ivlen" (B<OSSL_CIPHER_PARAM_IVLEN> and <B<OSSL_CIPHER_PARAM_AEAD_IVLEN>) <unsigned integer>
+
+Gets the IV length for the cipher context I<ctx>.
+The length of the "ivlen" parameter should not exceed that of a B<size_t>.
+See also EVP_CIPHER_CTX_get_iv_length().
+
+=item "iv" (B<OSSL_CIPHER_PARAM_IV>) <octet string OR octet ptr>
+
+Gets the IV used to initialize the associated cipher context I<ctx>.
+See also EVP_CIPHER_CTX_get_original_iv().
+
+=item "updated-iv" (B<OSSL_CIPHER_PARAM_UPDATED_IV>) <octet string OR octet ptr>
+
+Gets the updated pseudo-IV state for the associated cipher context, e.g.,
+the previous ciphertext block for CBC mode or the iteratively encrypted IV
+value for OFB mode. Note that octet pointer access is deprecated and is
+provided only for backwards compatibility with historical libcrypto APIs.
+See also EVP_CIPHER_CTX_get_updated_iv().
+
+=item "randkey" (B<OSSL_CIPHER_PARAM_RANDOM_KEY>) <octet string>
+
+Gets an implementation specific randomly generated key for the associated
+cipher context I<ctx>. This is currently only supported by DES and 3DES (which set
+the key to odd parity).
+
+=item "taglen" (B<OSSL_CIPHER_PARAM_AEAD_TAGLEN>) <unsigned integer>
+
+Gets the tag length to be used for an AEAD cipher for the associated cipher
+context I<ctx>. It gets a default value if it has not been set.
+The length of the "taglen" parameter should not exceed that of a B<size_t>.
+See also EVP_CIPHER_CTX_get_tag_length().
+
+=item "tlsaadpad" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD>) <unsigned integer>
+
+Gets the length of the tag that will be added to a TLS record for the AEAD
+tag for the associated cipher context I<ctx>.
+The length of the "tlsaadpad" parameter should not exceed that of a B<size_t>.
+
+=item "tlsivgen" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN>) <octet string>
+
+Gets the invocation field generated for encryption.
+Can only be called after "tlsivfixed" is set.
+This is only used for GCM mode.
+
+=item "tls1multi_enclen" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN>) <unsigned integer>
+
+Get the total length of the record returned from the "tls1multi_enc" operation.
+
+=item "tls1multi_maxbufsz" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE>) <unsigned integer>
+
+Gets the maximum record length for a TLS1 multiblock cipher operation.
+The length of the "tls1multi_maxbufsz" parameter should not exceed that of a B<size_t>.
+
+=item "tls1multi_aadpacklen" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN>) <unsigned integer>
+
+Gets the result of running the "tls1multi_aad" operation.
+
+=item "tls-mac" (B<OSSL_CIPHER_PARAM_TLS_MAC>) <octet ptr>
+
+Used to pass the TLS MAC data.
+
+=back
+
+=head2 Settable EVP_CIPHER_CTX parameters
+
+The following L<OSSL_PARAM(3)> keys can be used with EVP_CIPHER_CTX_set_params():
+
+=over 4
+
+=item "mackey" (B<OSSL_CIPHER_PARAM_AEAD_MAC_KEY>) <octet string>
+
+Sets the MAC key used by composite AEAD ciphers such as AES-CBC-HMAC-SHA256.
+
+=item "speed" (B<OSSL_CIPHER_PARAM_SPEED>) <unsigned integer>
+
+Sets the speed option for the associated cipher context. This is only supported
+by AES SIV ciphers which disallow multiple operations by default.
+Setting "speed" to 1 allows another encrypt or decrypt operation to be
+performed. This is used for performance testing.
+
+=item "use-bits" (B<OSSL_CIPHER_PARAM_USE_BITS>) <unsigned integer>
+
+Determines if the input length I<inl> passed to EVP_EncryptUpdate(),
+EVP_DecryptUpdate() and EVP_CipherUpdate() is the number of bits or number of bytes.
+Setting "use-bits" to 1 uses bits. The default is in bytes.
+This is only used for B<CFB1> ciphers.
+
+This can be set using EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS).
+
+=item "tls-version" (B<OSSL_CIPHER_PARAM_TLS_VERSION>) <integer>
+
+Sets the TLS version.
+
+=item "tls-mac-size" (B<OSSL_CIPHER_PARAM_TLS_MAC_SIZE>) <unsigned integer>
+
+Set the TLS MAC size.
+
+=item "tlsaad" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_AAD>) <octet string>
+
+Sets TLSv1.2 AAD information for the associated cipher context I<ctx>.
+TLSv1.2 AAD information is always 13 bytes in length and is as defined for the
+"additional_data" field described in section 6.2.3.3 of RFC5246.
+
+=item "tlsivfixed" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED>) <octet string>
+
+Sets the fixed portion of an IV for an AEAD cipher used in a TLS record
+encryption/ decryption for the associated cipher context.
+TLS record encryption/decryption always occurs "in place" so that the input and
+output buffers are always the same memory location.
+AEAD IVs in TLSv1.2 consist of an implicit "fixed" part and an explicit part
+that varies with every record.
+Setting a TLS fixed IV changes a cipher to encrypt/decrypt TLS records.
+TLS records are encrypted/decrypted using a single OSSL_FUNC_cipher_cipher call per
+record.
+For a record decryption the first bytes of the input buffer will be the explicit
+part of the IV and the final bytes of the input buffer will be the AEAD tag.
+The length of the explicit part of the IV and the tag length will depend on the
+cipher in use and will be defined in the RFC for the relevant ciphersuite.
+In order to allow for "in place" decryption the plaintext output should be
+written to the same location in the output buffer that the ciphertext payload
+was read from, i.e. immediately after the explicit IV.
+
+When encrypting a record the first bytes of the input buffer should be empty to
+allow space for the explicit IV, as will the final bytes where the tag will
+be written.
+The length of the input buffer will include the length of the explicit IV, the
+payload, and the tag bytes.
+The cipher implementation should generate the explicit IV and write it to the
+beginning of the output buffer, do "in place" encryption of the payload and
+write that to the output buffer, and finally add the tag onto the end of the
+output buffer.
+
+Whether encrypting or decrypting the value written to I<*outl> in the
+OSSL_FUNC_cipher_cipher call should be the length of the payload excluding the explicit
+IV length and the tag length.
+
+=item "tlsivinv" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV>) <octet string>
+
+Sets the invocation field used for decryption.
+Can only be called after "tlsivfixed" is set.
+This is only used for GCM mode.
+
+=item "tls1multi_enc" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC>) <octet string>
+
+Triggers a multiblock TLS1 encrypt operation for a TLS1 aware cipher that
+supports sending 4 or 8 records in one go.
+The cipher performs both the MAC and encrypt stages and constructs the record
+headers itself.
+"tls1multi_enc" supplies the output buffer for the encrypt operation,
+"tls1multi_encin" & "tls1multi_interleave" must also be set in order to supply
+values to the encrypt operation.
+
+=item "tls1multi_encin" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN>) <octet string>
+
+Supplies the data to encrypt for a TLS1 multiblock cipher operation.
+
+=item "tls1multi_maxsndfrag" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT>) <unsigned integer>
+
+Sets the maximum send fragment size for a TLS1 multiblock cipher operation.
+It must be set before using "tls1multi_maxbufsz".
+The length of the "tls1multi_maxsndfrag" parameter should not exceed that of a B<size_t>.
+
+=item "tls1multi_aad" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD>) <octet string>
+
+Sets the authenticated additional data used by a TLS1 multiblock cipher operation.
+The supplied data consists of 13 bytes of record data containing:
+Bytes 0-7: The sequence number of the first record
+Byte 8: The record type
+Byte 9-10: The protocol version
+Byte 11-12: Input length (Always 0)
+
+"tls1multi_interleave" must also be set for this operation.
+
+=back
+
+=head1 CONTROLS
+
+The Mappings from EVP_CIPHER_CTX_ctrl() identifiers to PARAMETERS are listed
+in the following section. See the L</PARAMETERS> section for more details.
+
+EVP_CIPHER_CTX_ctrl() can be used to send the following standard controls:
+
+=over 4
+
+=item EVP_CTRL_AEAD_SET_IVLEN and EVP_CTRL_GET_IVLEN
+
+When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() and
+EVP_CIPHER_CTX_get_params() get called with an L<OSSL_PARAM(3)> item with the
+key "ivlen" (B<OSSL_CIPHER_PARAM_IVLEN>).
+
+=item EVP_CTRL_AEAD_SET_IV_FIXED
+
+When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
+with an L<OSSL_PARAM(3)> item with the key "tlsivfixed"
+(B<OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED>).
+
+=item EVP_CTRL_AEAD_SET_MAC_KEY
+
+When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
+with an L<OSSL_PARAM(3)> item with the key "mackey"
+(B<OSSL_CIPHER_PARAM_AEAD_MAC_KEY>).
+
+=item EVP_CTRL_AEAD_SET_TAG and EVP_CTRL_AEAD_GET_TAG
+
+When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() and
+EVP_CIPHER_CTX_get_params() get called with an L<OSSL_PARAM(3)> item with the
+key "tag" (B<OSSL_CIPHER_PARAM_AEAD_TAG>).
+
+=item EVP_CTRL_CCM_SET_L
+
+When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
+with an L<OSSL_PARAM(3)> item with the key "ivlen" (B<OSSL_CIPHER_PARAM_IVLEN>)
+with a value of (15 - L)
+
+=item EVP_CTRL_COPY
+
+There is no OSSL_PARAM mapping for this. Use EVP_CIPHER_CTX_copy() instead.
+
+=item EVP_CTRL_GCM_SET_IV_INV
+
+When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
+with an L<OSSL_PARAM(3)> item with the key "tlsivinv"
+(B<OSSL_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV>).
+
+=item EVP_CTRL_RAND_KEY
+
+When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
+with an L<OSSL_PARAM(3)> item with the key "randkey"
+(B<OSSL_CIPHER_PARAM_RANDOM_KEY>).
+
+=item EVP_CTRL_SET_KEY_LENGTH
+
+When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
+with an L<OSSL_PARAM(3)> item with the key "keylen" (B<OSSL_CIPHER_PARAM_KEYLEN>).
+
+=item EVP_CTRL_SET_RC2_KEY_BITS and EVP_CTRL_GET_RC2_KEY_BITS
+
+When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() and
+EVP_CIPHER_CTX_get_params() get called with an L<OSSL_PARAM(3)> item with the
+key "keybits" (B<OSSL_CIPHER_PARAM_RC2_KEYBITS>).
+
+=item EVP_CTRL_SET_RC5_ROUNDS and EVP_CTRL_GET_RC5_ROUNDS
+
+When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() and
+EVP_CIPHER_CTX_get_params() get called with an L<OSSL_PARAM(3)> item with the
+key "rounds" (B<OSSL_CIPHER_PARAM_ROUNDS>).
+
+=item EVP_CTRL_SET_SPEED
+
+When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
+with an L<OSSL_PARAM(3)> item with the key "speed" (B<OSSL_CIPHER_PARAM_SPEED>).
+
+=item EVP_CTRL_GCM_IV_GEN
+
+When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_get_params() gets called
+with an L<OSSL_PARAM(3)> item with the key
+"tlsivgen" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN>).
+
+=item EVP_CTRL_AEAD_TLS1_AAD
+
+When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() get called
+with an L<OSSL_PARAM(3)> item with the key
+"tlsaadpad" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_AAD>)
+followed by EVP_CIPHER_CTX_get_params() with a key of
+"tlsaadpad" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD>).
+
+=item EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE
+
+When used with a fetched B<EVP_CIPHER>,
+EVP_CIPHER_CTX_set_params() gets called with an L<OSSL_PARAM(3)> item with the
+key OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT
+followed by EVP_CIPHER_CTX_get_params() with a key of
+"tls1multi_maxbufsz" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE>).
+
+=item EVP_CTRL_TLS1_1_MULTIBLOCK_AAD
+
+When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
+with L<OSSL_PARAM(3)> items with the keys
+"tls1multi_aad" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD>) and
+"tls1multi_interleave" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE>)
+followed by EVP_CIPHER_CTX_get_params() with keys of
+"tls1multi_aadpacklen" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN>) and
+"tls1multi_interleave" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE>).
+
+=item EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT
+
+When used with a fetched B<EVP_CIPHER>, EVP_CIPHER_CTX_set_params() gets called
+with L<OSSL_PARAM(3)> items with the keys
+"tls1multi_enc" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC>),
+"tls1multi_encin" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN>) and
+"tls1multi_interleave" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE>),
+followed by EVP_CIPHER_CTX_get_params() with a key of
+"tls1multi_enclen" (B<OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN>).
+
+=back
+
+=head1 FLAGS
+
+EVP_CIPHER_CTX_set_flags(), EVP_CIPHER_CTX_clear_flags() and EVP_CIPHER_CTX_test_flags().
+can be used to manipulate and test these B<EVP_CIPHER_CTX> flags:
+
+=over 4
+
+=item EVP_CIPH_NO_PADDING
+
+Used by EVP_CIPHER_CTX_set_padding().
+
+See also L</Gettable and Settable EVP_CIPHER_CTX parameters> "padding"
+
+=item EVP_CIPH_FLAG_LENGTH_BITS
+
+See L</Settable EVP_CIPHER_CTX parameters> "use-bits".
+
+=item EVP_CIPHER_CTX_FLAG_WRAP_ALLOW
+
+Used for Legacy purposes only. This flag needed to be set to indicate the
+cipher handled wrapping.
+
+=back
+
+EVP_CIPHER_flags() uses the following flags that
+have mappings to L</Gettable EVP_CIPHER parameters>:
+
+=over 4
+
+=item EVP_CIPH_FLAG_AEAD_CIPHER
+
+See L</Gettable EVP_CIPHER parameters> "aead".
+
+=item EVP_CIPH_CUSTOM_IV
+
+See L</Gettable EVP_CIPHER parameters> "custom-iv".
+
+=item EVP_CIPH_FLAG_CTS
+
+See L</Gettable EVP_CIPHER parameters> "cts".
+
+=item EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK;
+
+See L</Gettable EVP_CIPHER parameters> "tls-multi".
+
+=item EVP_CIPH_RAND_KEY
+
+See L</Gettable EVP_CIPHER parameters> "has-randkey".
+
+=back
+
+EVP_CIPHER_flags() uses the following flags for legacy purposes only:
+
+=over 4
+
+=item EVP_CIPH_VARIABLE_LENGTH
+
+=item EVP_CIPH_FLAG_CUSTOM_CIPHER
+
+=item EVP_CIPH_ALWAYS_CALL_INIT
+
+=item EVP_CIPH_CTRL_INIT
+
+=item EVP_CIPH_CUSTOM_KEY_LENGTH
+
+=item EVP_CIPH_CUSTOM_COPY
+
+=item EVP_CIPH_FLAG_DEFAULT_ASN1
+
+See L<EVP_CIPHER_meth_set_flags(3)> for further information related to the above
+flags.
+
+=back
=head1 RETURN VALUES
+EVP_CIPHER_fetch() returns a pointer to a B<EVP_CIPHER> for success
+and B<NULL> for failure.
+
+EVP_CIPHER_up_ref() returns 1 for success or 0 otherwise.
+
EVP_CIPHER_CTX_new() returns a pointer to a newly created
B<EVP_CIPHER_CTX> for success and B<NULL> for failure.
-EVP_EncryptInit_ex(), EVP_EncryptUpdate() and EVP_EncryptFinal_ex()
+EVP_EncryptInit_ex2(), EVP_EncryptUpdate() and EVP_EncryptFinal_ex()
return 1 for success and 0 for failure.
-EVP_DecryptInit_ex() and EVP_DecryptUpdate() return 1 for success and 0 for failure.
+EVP_DecryptInit_ex2() and EVP_DecryptUpdate() return 1 for success and 0 for failure.
EVP_DecryptFinal_ex() returns 0 if the decrypt failed or 1 for success.
-EVP_CipherInit_ex() and EVP_CipherUpdate() return 1 for success and 0 for failure.
+EVP_CipherInit_ex2() and EVP_CipherUpdate() return 1 for success and 0 for failure.
EVP_CipherFinal_ex() returns 0 for a decryption failure or 1 for success.
+EVP_Cipher() returns the amount of encrypted / decrypted bytes, or -1
+on failure if the flag B<EVP_CIPH_FLAG_CUSTOM_CIPHER> is set for the
+cipher. EVP_Cipher() returns 1 on success or 0 on failure, if the flag
+B<EVP_CIPH_FLAG_CUSTOM_CIPHER> is not set for the cipher.
+
EVP_CIPHER_CTX_reset() returns 1 for success and 0 for failure.
EVP_get_cipherbyname(), EVP_get_cipherbynid() and EVP_get_cipherbyobj()
return an B<EVP_CIPHER> structure or NULL on error.
-EVP_CIPHER_nid() and EVP_CIPHER_CTX_nid() return a NID.
+EVP_CIPHER_get_nid() and EVP_CIPHER_CTX_get_nid() return a NID.
-EVP_CIPHER_block_size() and EVP_CIPHER_CTX_block_size() return the block
-size.
+EVP_CIPHER_get_block_size() and EVP_CIPHER_CTX_get_block_size() return the
+block size.
-EVP_CIPHER_key_length() and EVP_CIPHER_CTX_key_length() return the key
+EVP_CIPHER_get_key_length() and EVP_CIPHER_CTX_get_key_length() return the key
length.
EVP_CIPHER_CTX_set_padding() always returns 1.
-EVP_CIPHER_iv_length() and EVP_CIPHER_CTX_iv_length() return the IV
-length, zero if the cipher does not use an IV and a negative value on error.
+EVP_CIPHER_get_iv_length() and EVP_CIPHER_CTX_get_iv_length() return the IV
+length or zero if the cipher does not use an IV.
+
+EVP_CIPHER_CTX_get_tag_length() return the tag length or zero if the cipher
+does not use a tag.
-EVP_CIPHER_type() and EVP_CIPHER_CTX_type() return the NID of the cipher's
-OBJECT IDENTIFIER or NID_undef if it has no defined OBJECT IDENTIFIER.
+EVP_CIPHER_get_type() and EVP_CIPHER_CTX_get_type() return the NID of the
+cipher's OBJECT IDENTIFIER or NID_undef if it has no defined
+OBJECT IDENTIFIER.
EVP_CIPHER_CTX_cipher() returns an B<EVP_CIPHER> structure.
+EVP_CIPHER_CTX_get_num() returns a nonnegative num value or
+B<EVP_CTRL_RET_UNSUPPORTED> if the implementation does not support the call
+or on any other error.
+
+EVP_CIPHER_CTX_set_num() returns 1 on success and 0 if the implementation
+does not support the call or on any other error.
+
+EVP_CIPHER_CTX_is_encrypting() returns 1 if the I<ctx> is set up for encryption
+0 otherwise.
+
EVP_CIPHER_param_to_asn1() and EVP_CIPHER_asn1_to_param() return greater
than zero for success and zero or a negative number on failure.
-EVP_CIPHER_CTX_rand_key() returns 1 for success.
+EVP_CIPHER_CTX_rand_key() returns 1 for success and zero or a negative number
+for failure.
+
+EVP_CIPHER_names_do_all() returns 1 if the callback was called for all names.
+A return value of 0 means that the callback was not called for any names.
=head1 CIPHER LISTING
All algorithms have a fixed key length unless otherwise stated.
-Refer to L<SEE ALSO> for the full list of ciphers available through the EVP
+Refer to L</SEE ALSO> for the full list of ciphers available through the EVP
interface.
=over 4
@@ -340,7 +1258,7 @@ Null cipher: does nothing.
=back
-=head1 AEAD Interface
+=head1 AEAD INTERFACE
The EVP interface for Authenticated Encryption with Associated Data (AEAD)
modes are subtly altered and several additional I<ctrl> operations are supported
@@ -348,7 +1266,7 @@ depending on the mode specified.
To specify additional authenticated data (AAD), a call to EVP_CipherUpdate(),
EVP_EncryptUpdate() or EVP_DecryptUpdate() should be made with the output
-parameter B<out> set to B<NULL>.
+parameter I<out> set to B<NULL>.
When decrypting, the return value of EVP_DecryptFinal() or EVP_CipherFinal()
indicates whether the operation was successful. If it does not indicate success,
@@ -407,8 +1325,8 @@ few additional requirements and different I<ctrl> values.
For CCM mode, the total plaintext or ciphertext length B<MUST> be passed to
EVP_CipherUpdate(), EVP_EncryptUpdate() or EVP_DecryptUpdate() with the output
-and input parameters (B<in> and B<out>) set to B<NULL> and the length passed in
-the B<inl> parameter.
+and input parameters (I<in> and I<out>) set to B<NULL> and the length passed in
+the I<inl> parameter.
The following I<ctrl>s are supported in CCM mode.
@@ -421,7 +1339,7 @@ the length of the tag (with the C<tag> parameter set to NULL) when encrypting.
The tag length is often referred to as B<M>. If not set a default value is
used (12 for AES). When decrypting, the tag needs to be set before passing
in data to be decrypted, but as in GCM and OCB mode, it can be set after
-passing additional authenticated data (see L<AEAD Interface>).
+passing additional authenticated data (see L</AEAD INTERFACE>).
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, ivlen, NULL)
@@ -429,12 +1347,66 @@ Sets the CCM B<L> value. If not set a default is used (8 for AES).
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL)
-Sets the CCM nonce (IV) length. This call can only be made before specifying
-a nonce value. The nonce length is given by B<15 - L> so it is 7 by default for
+Sets the CCM nonce (IV) length. This call can only be made before specifying a
+nonce value. The nonce length is given by B<15 - L> so it is 7 by default for
AES.
=back
+=head2 SIV Mode
+
+For SIV mode ciphers the behaviour of the EVP interface is subtly
+altered and several additional ctrl operations are supported.
+
+To specify any additional authenticated data (AAD) and/or a Nonce, a call to
+EVP_CipherUpdate(), EVP_EncryptUpdate() or EVP_DecryptUpdate() should be made
+with the output parameter I<out> set to B<NULL>.
+
+RFC5297 states that the Nonce is the last piece of AAD before the actual
+encrypt/decrypt takes place. The API does not differentiate the Nonce from
+other AAD.
+
+When decrypting the return value of EVP_DecryptFinal() or EVP_CipherFinal()
+indicates if the operation was successful. If it does not indicate success
+the authentication operation has failed and any output data B<MUST NOT>
+be used as it is corrupted.
+
+The API does not store the the SIV (Synthetic Initialization Vector) in
+the cipher text. Instead, it is stored as the tag within the EVP_CIPHER_CTX.
+The SIV must be retrieved from the context after encryption, and set into
+the context before decryption.
+
+This differs from RFC5297 in that the cipher output from encryption, and
+the cipher input to decryption, does not contain the SIV. This also means
+that the plain text and cipher text lengths are identical.
+
+The following ctrls are supported in SIV mode, and are used to get and set
+the Synthetic Initialization Vector:
+
+=over 4
+
+=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen, tag);
+
+Writes I<taglen> bytes of the tag value (the Synthetic Initialization Vector)
+to the buffer indicated by I<tag>. This call can only be made when encrypting
+data and B<after> all data has been processed (e.g. after an EVP_EncryptFinal()
+call). For SIV mode the taglen must be 16.
+
+=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen, tag);
+
+Sets the expected tag (the Synthetic Initialization Vector) to I<taglen>
+bytes from I<tag>. This call is only legal when decrypting data and must be
+made B<before> any data is processed (e.g. before any EVP_DecryptUpdate()
+calls). For SIV mode the taglen must be 16.
+
+=back
+
+SIV mode makes two passes over the input data, thus, only one call to
+EVP_CipherUpdate(), EVP_EncryptUpdate() or EVP_DecryptUpdate() should be made
+with I<out> set to a non-B<NULL> value. A call to EVP_DecryptFinal() or
+EVP_CipherFinal() is not required, but will indicate if the update
+operation succeeded.
+
=head2 ChaCha20-Poly1305
The following I<ctrl>s are supported for the ChaCha20-Poly1305 AEAD algorithm.
@@ -443,11 +1415,10 @@ The following I<ctrl>s are supported for the ChaCha20-Poly1305 AEAD algorithm.
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL)
-Sets the nonce length. This call can only be made before specifying the nonce.
-If not called a default nonce length of 12 (i.e. 96 bits) is used. The maximum
-nonce length is 12 bytes (i.e. 96-bits). If a nonce of less than 12 bytes is set
-then the nonce is automatically padded with leading 0 bytes to make it 12 bytes
-in length.
+Sets the nonce length. This call is now redundant since the only valid value
+is the default length of 12 (i.e. 96 bits).
+Prior to OpenSSL 3.0 a nonce of less than 12 bytes could be used to automatically
+pad the iv with leading 0 bytes to make it 12 bytes in length.
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen, tag)
@@ -492,12 +1463,14 @@ the input data earlier on will not produce a final decrypt error.
If padding is disabled then the decryption operation will always succeed if
the total amount of data decrypted is a multiple of the block size.
-The functions EVP_EncryptInit(), EVP_EncryptFinal(), EVP_DecryptInit(),
-EVP_CipherInit() and EVP_CipherFinal() are obsolete but are retained for
-compatibility with existing code. New code should use EVP_EncryptInit_ex(),
-EVP_EncryptFinal_ex(), EVP_DecryptInit_ex(), EVP_DecryptFinal_ex(),
-EVP_CipherInit_ex() and EVP_CipherFinal_ex() because they can reuse an
-existing context without allocating and freeing it up on each call.
+The functions EVP_EncryptInit(), EVP_EncryptInit_ex(),
+EVP_EncryptFinal(), EVP_DecryptInit(), EVP_DecryptInit_ex(),
+EVP_CipherInit(), EVP_CipherInit_ex() and EVP_CipherFinal() are obsolete
+but are retained for compatibility with existing code. New code should
+use EVP_EncryptInit_ex2(), EVP_EncryptFinal_ex(), EVP_DecryptInit_ex2(),
+EVP_DecryptFinal_ex(), EVP_CipherInit_ex2() and EVP_CipherFinal_ex()
+because they can reuse an existing context without allocating and freeing
+it up on each call.
There are some differences between functions EVP_CipherInit() and
EVP_CipherInit_ex(), significant in some circumstances. EVP_CipherInit() fills
@@ -508,6 +1481,12 @@ removed, and it is especially important for the
B<EVP_CIPHER_CTX_FLAG_WRAP_ALLOW> flag treated specially in
EVP_CipherInit_ex().
+Ignoring failure returns of the B<EVP_CIPHER_CTX> initialization functions can
+lead to subsequent undefined behavior when calling the functions that update or
+finalize the context. The only valid calls on the B<EVP_CIPHER_CTX> when
+initialization fails are calls that attempt another initialization of the
+context or release the context.
+
EVP_get_cipherbynid(), and EVP_get_cipherbyobj() are implemented as macros.
=head1 BUGS
@@ -540,7 +1519,11 @@ Encrypt a string using IDEA:
FILE *out;
ctx = EVP_CIPHER_CTX_new();
- EVP_EncryptInit_ex(ctx, EVP_idea_cbc(), NULL, key, iv);
+ if (!EVP_EncryptInit_ex2(ctx, EVP_idea_cbc(), key, iv, NULL)) {
+ /* Error */
+ EVP_CIPHER_CTX_free(ctx);
+ return 0;
+ }
if (!EVP_EncryptUpdate(ctx, outbuf, &outlen, intext, strlen(intext))) {
/* Error */
@@ -598,13 +1581,21 @@ with a 128-bit key:
/* Don't set key or IV right away; we want to check lengths */
ctx = EVP_CIPHER_CTX_new();
- EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, NULL, NULL,
- do_encrypt);
- OPENSSL_assert(EVP_CIPHER_CTX_key_length(ctx) == 16);
- OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == 16);
+ if (!EVP_CipherInit_ex2(ctx, EVP_aes_128_cbc(), NULL, NULL,
+ do_encrypt, NULL)) {
+ /* Error */
+ EVP_CIPHER_CTX_free(ctx);
+ return 0;
+ }
+ OPENSSL_assert(EVP_CIPHER_CTX_get_key_length(ctx) == 16);
+ OPENSSL_assert(EVP_CIPHER_CTX_get_iv_length(ctx) == 16);
/* Now we can set key and IV */
- EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, do_encrypt);
+ if (!EVP_CipherInit_ex2(ctx, NULL, key, iv, do_encrypt, NULL)) {
+ /* Error */
+ EVP_CIPHER_CTX_free(ctx);
+ return 0;
+ }
for (;;) {
inlen = fread(inbuf, 1, 1024, in);
@@ -628,27 +1619,74 @@ with a 128-bit key:
return 1;
}
+Encryption using AES-CBC with a 256-bit key with "CS1" ciphertext stealing.
+
+ int encrypt(const unsigned char *key, const unsigned char *iv,
+ const unsigned char *msg, size_t msg_len, unsigned char *out)
+ {
+ /*
+ * This assumes that key size is 32 bytes and the iv is 16 bytes.
+ * For ciphertext stealing mode the length of the ciphertext "out" will be
+ * the same size as the plaintext size "msg_len".
+ * The "msg_len" can be any size >= 16.
+ */
+ int ret = 0, encrypt = 1, outlen, len;
+ EVP_CIPHER_CTX *ctx = NULL;
+ EVP_CIPHER *cipher = NULL;
+ OSSL_PARAM params[2];
+
+ ctx = EVP_CIPHER_CTX_new();
+ cipher = EVP_CIPHER_fetch(NULL, "AES-256-CBC-CTS", NULL);
+ if (ctx == NULL || cipher == NULL)
+ goto err;
+
+ /*
+ * The default is "CS1" so this is not really needed,
+ * but would be needed to set either "CS2" or "CS3".
+ */
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_CIPHER_PARAM_CTS_MODE,
+ "CS1", 0);
+ params[1] = OSSL_PARAM_construct_end();
+
+ if (!EVP_CipherInit_ex2(ctx, cipher, key, iv, encrypt, params))
+ goto err;
+
+ /* NOTE: CTS mode does not support multiple calls to EVP_CipherUpdate() */
+ if (!EVP_CipherUpdate(ctx, out, &outlen, msg, msg_len))
+ goto err;
+ if (!EVP_CipherFinal_ex(ctx, out + outlen, &len))
+ goto err;
+ ret = 1;
+ err:
+ EVP_CIPHER_free(cipher);
+ EVP_CIPHER_CTX_free(ctx);
+ return ret;
+ }
=head1 SEE ALSO
-L<evp(7)>
+L<evp(7)>,
+L<property(7)>,
+L<crypto(7)/ALGORITHM FETCHING>,
+L<provider-cipher(7)>,
+L<life_cycle-cipher(7)>
Supported ciphers are listed in:
-L<EVP_aes(3)>,
-L<EVP_aria(3)>,
-L<EVP_bf(3)>,
-L<EVP_camellia(3)>,
-L<EVP_cast5(3)>,
+L<EVP_aes_128_gcm(3)>,
+L<EVP_aria_128_gcm(3)>,
+L<EVP_bf_cbc(3)>,
+L<EVP_camellia_128_ecb(3)>,
+L<EVP_cast5_cbc(3)>,
L<EVP_chacha20(3)>,
-L<EVP_des(3)>,
-L<EVP_desx(3)>,
-L<EVP_idea(3)>,
-L<EVP_rc2(3)>,
+L<EVP_des_cbc(3)>,
+L<EVP_desx_cbc(3)>,
+L<EVP_idea_cbc(3)>,
+L<EVP_rc2_cbc(3)>,
L<EVP_rc4(3)>,
-L<EVP_rc5(3)>,
-L<EVP_seed(3)>,
-L<EVP_sm4(3)>
+L<EVP_rc5_32_12_16_cbc(3)>,
+L<EVP_seed_cbc(3)>,
+L<EVP_sm4_cbc(3)>,
=head1 HISTORY
@@ -659,11 +1697,39 @@ EVP_CIPHER_CTX_reset() appeared and EVP_CIPHER_CTX_cleanup()
disappeared. EVP_CIPHER_CTX_init() remains as an alias for
EVP_CIPHER_CTX_reset().
+The EVP_CIPHER_CTX_cipher() function was deprecated in OpenSSL 3.0; use
+EVP_CIPHER_CTX_get0_cipher() instead.
+
+The EVP_EncryptInit_ex2(), EVP_DecryptInit_ex2(), EVP_CipherInit_ex2(),
+EVP_CIPHER_fetch(), EVP_CIPHER_free(), EVP_CIPHER_up_ref(),
+EVP_CIPHER_CTX_get0_cipher(), EVP_CIPHER_CTX_get1_cipher(),
+EVP_CIPHER_get_params(), EVP_CIPHER_CTX_set_params(),
+EVP_CIPHER_CTX_get_params(), EVP_CIPHER_gettable_params(),
+EVP_CIPHER_settable_ctx_params(), EVP_CIPHER_gettable_ctx_params(),
+EVP_CIPHER_CTX_settable_params() and EVP_CIPHER_CTX_gettable_params()
+functions were added in 3.0.
+
+The EVP_CIPHER_nid(), EVP_CIPHER_name(), EVP_CIPHER_block_size(),
+EVP_CIPHER_key_length(), EVP_CIPHER_iv_length(), EVP_CIPHER_flags(),
+EVP_CIPHER_mode(), EVP_CIPHER_type(), EVP_CIPHER_CTX_nid(),
+EVP_CIPHER_CTX_block_size(), EVP_CIPHER_CTX_key_length(),
+EVP_CIPHER_CTX_iv_length(), EVP_CIPHER_CTX_tag_length(),
+EVP_CIPHER_CTX_num(), EVP_CIPHER_CTX_type(), and EVP_CIPHER_CTX_mode()
+functions were renamed to include C<get> or C<get0> in their names in
+OpenSSL 3.0, respectively. The old names are kept as non-deprecated
+alias macros.
+
+The EVP_CIPHER_CTX_encrypting() function was renamed to
+EVP_CIPHER_CTX_is_encrypting() in OpenSSL 3.0. The old name is kept as
+non-deprecated alias macro.
+
+The EVP_CIPHER_CTX_flags() macro was deprecated in OpenSSL 1.1.0.
+
=head1 COPYRIGHT
-Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_KDF.pod b/doc/man3/EVP_KDF.pod
new file mode 100644
index 000000000000..3b4e2b79aa14
--- /dev/null
+++ b/doc/man3/EVP_KDF.pod
@@ -0,0 +1,305 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF, EVP_KDF_fetch, EVP_KDF_free, EVP_KDF_up_ref,
+EVP_KDF_CTX, EVP_KDF_CTX_new, EVP_KDF_CTX_free, EVP_KDF_CTX_dup,
+EVP_KDF_CTX_reset, EVP_KDF_derive,
+EVP_KDF_CTX_get_kdf_size,
+EVP_KDF_get0_provider, EVP_KDF_CTX_kdf, EVP_KDF_is_a,
+EVP_KDF_get0_name, EVP_KDF_names_do_all, EVP_KDF_get0_description,
+EVP_KDF_CTX_get_params, EVP_KDF_CTX_set_params, EVP_KDF_do_all_provided,
+EVP_KDF_get_params, EVP_KDF_gettable_params,
+EVP_KDF_gettable_ctx_params, EVP_KDF_settable_ctx_params,
+EVP_KDF_CTX_gettable_params, EVP_KDF_CTX_settable_params - EVP KDF routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/kdf.h>
+
+ typedef struct evp_kdf_st EVP_KDF;
+ typedef struct evp_kdf_ctx_st EVP_KDF_CTX;
+
+ EVP_KDF_CTX *EVP_KDF_CTX_new(const EVP_KDF *kdf);
+ const EVP_KDF *EVP_KDF_CTX_kdf(EVP_KDF_CTX *ctx);
+ void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx);
+ EVP_KDF_CTX *EVP_KDF_CTX_dup(const EVP_KDF_CTX *src);
+ void EVP_KDF_CTX_reset(EVP_KDF_CTX *ctx);
+ size_t EVP_KDF_CTX_get_kdf_size(EVP_KDF_CTX *ctx);
+ int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[]);
+ int EVP_KDF_up_ref(EVP_KDF *kdf);
+ void EVP_KDF_free(EVP_KDF *kdf);
+ EVP_KDF *EVP_KDF_fetch(OSSL_LIB_CTX *libctx, const char *algorithm,
+ const char *properties);
+ int EVP_KDF_is_a(const EVP_KDF *kdf, const char *name);
+ const char *EVP_KDF_get0_name(const EVP_KDF *kdf);
+ const char *EVP_KDF_get0_description(const EVP_KDF *kdf);
+ const OSSL_PROVIDER *EVP_KDF_get0_provider(const EVP_KDF *kdf);
+ void EVP_KDF_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_KDF *kdf, void *arg),
+ void *arg);
+ int EVP_KDF_names_do_all(const EVP_KDF *kdf,
+ void (*fn)(const char *name, void *data),
+ void *data);
+ int EVP_KDF_get_params(EVP_KDF *kdf, OSSL_PARAM params[]);
+ int EVP_KDF_CTX_get_params(EVP_KDF_CTX *ctx, OSSL_PARAM params[]);
+ int EVP_KDF_CTX_set_params(EVP_KDF_CTX *ctx, const OSSL_PARAM params[]);
+ const OSSL_PARAM *EVP_KDF_gettable_params(const EVP_KDF *kdf);
+ const OSSL_PARAM *EVP_KDF_gettable_ctx_params(const EVP_KDF *kdf);
+ const OSSL_PARAM *EVP_KDF_settable_ctx_params(const EVP_KDF *kdf);
+ const OSSL_PARAM *EVP_KDF_CTX_gettable_params(const EVP_KDF *kdf);
+ const OSSL_PARAM *EVP_KDF_CTX_settable_params(const EVP_KDF *kdf);
+ const OSSL_PROVIDER *EVP_KDF_get0_provider(const EVP_KDF *kdf);
+
+=head1 DESCRIPTION
+
+The EVP KDF routines are a high-level interface to Key Derivation Function
+algorithms and should be used instead of algorithm-specific functions.
+
+After creating a B<EVP_KDF_CTX> for the required algorithm using
+EVP_KDF_CTX_new(), inputs to the algorithm are supplied either by
+passing them as part of the EVP_KDF_derive() call or using calls
+to EVP_KDF_CTX_set_params() before calling EVP_KDF_derive() to derive
+the key.
+
+=head2 Types
+
+B<EVP_KDF> is a type that holds the implementation of a KDF.
+
+B<EVP_KDF_CTX> is a context type that holds the algorithm inputs.
+
+=head2 Algorithm implementation fetching
+
+EVP_KDF_fetch() fetches an implementation of a KDF I<algorithm>, given
+a library context I<libctx> and a set of I<properties>.
+See L<crypto(7)/ALGORITHM FETCHING> for further information.
+
+See L<OSSL_PROVIDER-default(7)/Key Derivation Function (KDF)> for the lists of
+algorithms supported by the default provider.
+
+The returned value must eventually be freed with
+L<EVP_KDF_free(3)>.
+
+EVP_KDF_up_ref() increments the reference count of an already fetched
+KDF.
+
+EVP_KDF_free() frees a fetched algorithm.
+NULL is a valid parameter, for which this function is a no-op.
+
+=head2 Context manipulation functions
+
+EVP_KDF_CTX_new() creates a new context for the KDF implementation I<kdf>.
+
+EVP_KDF_CTX_free() frees up the context I<ctx>. If I<ctx> is NULL, nothing
+is done.
+
+EVP_KDF_CTX_kdf() returns the B<EVP_KDF> associated with the context
+I<ctx>.
+
+=head2 Computing functions
+
+EVP_KDF_CTX_reset() resets the context to the default state as if the context
+had just been created.
+
+EVP_KDF_derive() processes any parameters in I<Params> and then derives
+I<keylen> bytes of key material and places it in the I<key> buffer.
+If the algorithm produces a fixed amount of output then an error will
+occur unless the I<keylen> parameter is equal to that output size,
+as returned by EVP_KDF_CTX_get_kdf_size().
+
+EVP_KDF_get_params() retrieves details about the implementation
+I<kdf>.
+The set of parameters given with I<params> determine exactly what
+parameters should be retrieved.
+Note that a parameter that is unknown in the underlying context is
+simply ignored.
+
+EVP_KDF_CTX_get_params() retrieves chosen parameters, given the
+context I<ctx> and its underlying context.
+The set of parameters given with I<params> determine exactly what
+parameters should be retrieved.
+Note that a parameter that is unknown in the underlying context is
+simply ignored.
+
+EVP_KDF_CTX_set_params() passes chosen parameters to the underlying
+context, given a context I<ctx>.
+The set of parameters given with I<params> determine exactly what
+parameters are passed down.
+Note that a parameter that is unknown in the underlying context is
+simply ignored.
+Also, what happens when a needed parameter isn't passed down is
+defined by the implementation.
+
+EVP_KDF_gettable_params() returns an L<OSSL_PARAM(3)> array that describes
+the retrievable and settable parameters. EVP_KDF_gettable_params()
+returns parameters that can be used with EVP_KDF_get_params().
+
+EVP_KDF_gettable_ctx_params() and EVP_KDF_CTX_gettable_params()
+return constant L<OSSL_PARAM(3)> arrays that describe the retrievable
+parameters that can be used with EVP_KDF_CTX_get_params().
+EVP_KDF_gettable_ctx_params() returns the parameters that can be retrieved
+from the algorithm, whereas EVP_KDF_CTX_gettable_params() returns
+the parameters that can be retrieved in the context's current state.
+
+EVP_KDF_settable_ctx_params() and EVP_KDF_CTX_settable_params() return
+constant L<OSSL_PARAM(3)> arrays that describe the settable parameters that
+can be used with EVP_KDF_CTX_set_params(). EVP_KDF_settable_ctx_params()
+returns the parameters that can be retrieved from the algorithm,
+whereas EVP_KDF_CTX_settable_params() returns the parameters that can
+be retrieved in the context's current state.
+
+=head2 Information functions
+
+EVP_KDF_CTX_get_kdf_size() returns the output size if the algorithm produces a fixed amount
+of output and B<SIZE_MAX> otherwise. If an error occurs then 0 is returned.
+For some algorithms an error may result if input parameters necessary to
+calculate a fixed output size have not yet been supplied.
+
+EVP_KDF_is_a() returns 1 if I<kdf> is an implementation of an
+algorithm that's identifiable with I<name>, otherwise 0.
+
+EVP_KDF_get0_provider() returns the provider that holds the implementation
+of the given I<kdf>.
+
+EVP_KDF_do_all_provided() traverses all KDF implemented by all activated
+providers in the given library context I<libctx>, and for each of the
+implementations, calls the given function I<fn> with the implementation method
+and the given I<arg> as argument.
+
+EVP_KDF_get0_name() return the name of the given KDF. For fetched KDFs
+with multiple names, only one of them is returned; it's
+recommended to use EVP_KDF_names_do_all() instead.
+
+EVP_KDF_names_do_all() traverses all names for I<kdf>, and calls
+I<fn> with each name and I<data>.
+
+EVP_KDF_get0_description() returns a description of the I<kdf>, meant for
+display and human consumption. The description is at the discretion of
+the I<kdf> implementation.
+
+=head1 PARAMETERS
+
+The standard parameter names are:
+
+=over 4
+
+=item "pass" (B<OSSL_KDF_PARAM_PASSWORD>) <octet string>
+
+Some KDF implementations require a password.
+For those KDF implementations that support it, this parameter sets the password.
+
+=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string>
+
+Some KDF implementations can take a salt.
+For those KDF implementations that support it, this parameter sets the salt.
+
+The default value, if any, is implementation dependent.
+
+=item "iter" (B<OSSL_KDF_PARAM_ITER>) <unsigned integer>
+
+Some KDF implementations require an iteration count.
+For those KDF implementations that support it, this parameter sets the
+iteration count.
+
+The default value, if any, is implementation dependent.
+
+=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "mac" (B<OSSL_KDF_PARAM_MAC>) <UTF8 string>
+
+=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
+
+=item "cipher" (B<OSSL_KDF_PARAM_CIPHER>) <UTF8 string>
+
+For KDF implementations that use an underlying computation MAC, digest or
+cipher, these parameters set what the algorithm should be.
+
+The value is always the name of the intended algorithm,
+or the properties.
+
+Note that not all algorithms may support all possible underlying
+implementations.
+
+=item "key" (B<OSSL_KDF_PARAM_KEY>) <octet string>
+
+Some KDF implementations require a key.
+For those KDF implementations that support it, this octet string parameter
+sets the key.
+
+=item "maclen" (B<OSSL_KDF_PARAM_MAC_SIZE>) <unsigned integer>
+
+Used by implementations that use a MAC with a variable output size (KMAC).
+For those KDF implementations that support it, this parameter
+sets the MAC output size.
+
+The default value, if any, is implementation dependent.
+The length must never exceed what can be given with a B<size_t>.
+
+=item "maxmem_bytes" (B<OSSL_KDF_PARAM_SCRYPT_MAXMEM>) <unsigned integer>
+
+Memory-hard password-based KDF algorithms, such as scrypt, use an amount of
+memory that depends on the load factors provided as input.
+For those KDF implementations that support it, this B<uint64_t> parameter sets
+an upper limit on the amount of memory that may be consumed while performing
+a key derivation.
+If this memory usage limit is exceeded because the load factors are chosen
+too high, the key derivation will fail.
+
+The default value is implementation dependent.
+The memory size must never exceed what can be given with a B<size_t>.
+
+=back
+
+=head1 RETURN VALUES
+
+EVP_KDF_fetch() returns a pointer to a newly fetched B<EVP_KDF>, or
+NULL if allocation failed.
+
+EVP_KDF_get0_provider() returns a pointer to the provider for the KDF, or
+NULL on error.
+
+EVP_KDF_up_ref() returns 1 on success, 0 on error.
+
+EVP_KDF_CTX_new() returns either the newly allocated
+B<EVP_KDF_CTX> structure or NULL if an error occurred.
+
+EVP_KDF_CTX_free() and EVP_KDF_CTX_reset() do not return a value.
+
+EVP_KDF_CTX_get_kdf_size() returns the output size. B<SIZE_MAX> is returned to indicate
+that the algorithm produces a variable amount of output; 0 to indicate failure.
+
+EVP_KDF_get0_name() returns the name of the KDF, or NULL on error.
+
+EVP_KDF_names_do_all() returns 1 if the callback was called for all names. A
+return value of 0 means that the callback was not called for any names.
+
+The remaining functions return 1 for success and 0 or a negative value for
+failure. In particular, a return value of -2 indicates the operation is not
+supported by the KDF algorithm.
+
+=head1 NOTES
+
+The KDF life-cycle is described in L<life_cycle-kdf(7)>. In the future,
+the transitions described there will be enforced. When this is done, it will
+not be considered a breaking change to the API.
+
+=head1 SEE ALSO
+
+L<OSSL_PROVIDER-default(7)/Key Derivation Function (KDF)>,
+L<life_cycle-kdf(7)>.
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_KEM_free.pod b/doc/man3/EVP_KEM_free.pod
new file mode 100644
index 000000000000..575abc5f5798
--- /dev/null
+++ b/doc/man3/EVP_KEM_free.pod
@@ -0,0 +1,105 @@
+=pod
+
+=head1 NAME
+
+EVP_KEM_fetch, EVP_KEM_free, EVP_KEM_up_ref,
+EVP_KEM_get0_name, EVP_KEM_is_a, EVP_KEM_get0_provider,
+EVP_KEM_do_all_provided, EVP_KEM_names_do_all, EVP_KEM_get0_description,
+EVP_KEM_gettable_ctx_params, EVP_KEM_settable_ctx_params
+- Functions to manage EVP_KEM algorithm objects
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ EVP_KEM *EVP_KEM_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties);
+ void EVP_KEM_free(EVP_KEM *kem);
+ int EVP_KEM_up_ref(EVP_KEM *kem);
+ const char *EVP_KEM_get0_name(const EVP_KEM *kem);
+ int EVP_KEM_is_a(const EVP_KEM *kem, const char *name);
+ OSSL_PROVIDER *EVP_KEM_get0_provider(const EVP_KEM *kem);
+ void EVP_KEM_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_KEM *kem, void *arg), void *arg);
+ int EVP_KEM_names_do_all(const EVP_KEM *kem,
+ void (*fn)(const char *name, void *data), void *data);
+ const char *EVP_KEM_get0_description(const EVP_KEM *kem);
+ const OSSL_PARAM *EVP_KEM_gettable_ctx_params(const EVP_KEM *kem);
+ const OSSL_PARAM *EVP_KEM_settable_ctx_params(const EVP_KEM *kem);
+
+=head1 DESCRIPTION
+
+EVP_KEM_fetch() fetches the implementation for the given B<algorithm> from any
+provider offering it, within the criteria given by the B<properties> and in the
+scope of the given library context B<ctx> (see L<OSSL_LIB_CTX(3)>). The algorithm
+will be one offering functions for performing asymmetric kem related tasks such
+as key encapsulation and decapsulation.
+See L<crypto(7)/ALGORITHM FETCHING> for further information.
+
+The returned value must eventually be freed with EVP_KEM_free().
+
+EVP_KEM_free() decrements the reference count for the B<EVP_KEM> structure.
+Typically this structure will have been obtained from an earlier call to
+EVP_KEM_fetch(). If the reference count drops to 0 then the structure is freed.
+
+EVP_KEM_up_ref() increments the reference count for an B<EVP_KEM> structure.
+
+EVP_KEM_is_a() returns 1 if I<kem> is an implementation of an
+algorithm that's identifiable with I<name>, otherwise 0.
+
+EVP_KEM_get0_provider() returns the provider that I<kem> was fetched from.
+
+EVP_KEM_do_all_provided() traverses all EVP_KEMs implemented by all activated
+providers in the given library context I<libctx>, and for each of the
+implementations, calls the given function I<fn> with the implementation method
+and the given I<arg> as argument.
+
+EVP_KEM_get0_name() returns the algorithm name from the provided
+implementation for the given I<kem>. Note that the I<kem> may have
+multiple synonyms associated with it. In this case the first name from the
+algorithm definition is returned. Ownership of the returned string is retained
+by the I<kem> object and should not be freed by the caller.
+
+EVP_KEM_names_do_all() traverses all names for I<kem>, and calls I<fn> with
+each name and I<data>.
+
+EVP_KEM_get0_description() returns a description of the I<kem>, meant for
+display and human consumption. The description is at the discretion of
+the I<kem> implementation.
+
+EVP_KEM_gettable_ctx_params() and EVP_KEM_settable_ctx_params() return
+a constant L<OSSL_PARAM(3)> array that describes the names and types of key
+parameters that can be retrieved or set by a key encapsulation algorithm using
+L<EVP_PKEY_CTX_get_params(3)> and L<EVP_PKEY_CTX_set_params(3)>.
+
+=head1 RETURN VALUES
+
+EVP_KEM_fetch() returns a pointer to an B<EVP_KEM> for success or B<NULL> for
+failure.
+
+EVP_KEM_up_ref() returns 1 for success or 0 otherwise.
+
+EVP_KEM_names_do_all() returns 1 if the callback was called for all names. A
+return value of 0 means that the callback was not called for any names.
+
+EVP_KEM_gettable_ctx_params() and EVP_KEM_settable_ctx_params() return
+a constant L<OSSL_PARAM(3)> array or NULL on error.
+
+=head1 SEE ALSO
+
+L<crypto(7)/ALGORITHM FETCHING>, L<OSSL_PROVIDER(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_KEYEXCH_free.pod b/doc/man3/EVP_KEYEXCH_free.pod
new file mode 100644
index 000000000000..272855ccb3dd
--- /dev/null
+++ b/doc/man3/EVP_KEYEXCH_free.pod
@@ -0,0 +1,111 @@
+=pod
+
+=head1 NAME
+
+EVP_KEYEXCH_fetch, EVP_KEYEXCH_free, EVP_KEYEXCH_up_ref,
+EVP_KEYEXCH_get0_provider, EVP_KEYEXCH_is_a, EVP_KEYEXCH_do_all_provided,
+EVP_KEYEXCH_names_do_all, EVP_KEYEXCH_get0_name, EVP_KEYEXCH_get0_description,
+EVP_KEYEXCH_gettable_ctx_params, EVP_KEYEXCH_settable_ctx_params
+- Functions to manage EVP_KEYEXCH algorithm objects
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ EVP_KEYEXCH *EVP_KEYEXCH_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties);
+ void EVP_KEYEXCH_free(EVP_KEYEXCH *exchange);
+ int EVP_KEYEXCH_up_ref(EVP_KEYEXCH *exchange);
+ OSSL_PROVIDER *EVP_KEYEXCH_get0_provider(const EVP_KEYEXCH *exchange);
+ int EVP_KEYEXCH_is_a(const EVP_KEYEXCH *exchange, const char *name);
+ const char *EVP_KEYEXCH_get0_name(const EVP_KEYEXCH *exchange);
+ void EVP_KEYEXCH_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_KEYEXCH *exchange, void *arg),
+ void *arg);
+ int EVP_KEYEXCH_names_do_all(const EVP_KEYEXCH *exchange,
+ void (*fn)(const char *name, void *data),
+ void *data);
+ const char *EVP_KEYEXCH_get0_description(const EVP_KEYEXCH *keyexch);
+ const OSSL_PARAM *EVP_KEYEXCH_gettable_ctx_params(const EVP_KEYEXCH *keyexch);
+ const OSSL_PARAM *EVP_KEYEXCH_settable_ctx_params(const EVP_KEYEXCH *keyexch);
+
+=head1 DESCRIPTION
+
+EVP_KEYEXCH_fetch() fetches the key exchange implementation for the given
+I<algorithm> from any provider offering it, within the criteria given
+by the I<properties>.
+See L<crypto(7)/ALGORITHM FETCHING> for further information.
+
+The returned value must eventually be freed with EVP_KEYEXCH_free().
+
+EVP_KEYEXCH_free() decrements the reference count for the B<EVP_KEYEXCH>
+structure. Typically this structure will have been obtained from an earlier call
+to EVP_KEYEXCH_fetch(). If the reference count drops to 0 then the
+structure is freed.
+
+EVP_KEYEXCH_up_ref() increments the reference count for an B<EVP_KEYEXCH>
+structure.
+
+EVP_KEYEXCH_get0_provider() returns the provider that I<exchange> was
+fetched from.
+
+EVP_KEYEXCH_is_a() checks if I<exchange> is an implementation of an
+algorithm that's identifiable with I<name>.
+
+EVP_KEYEXCH_get0_name() returns the algorithm name from the provided
+implementation for the given I<exchange>. Note that the I<exchange> may have
+multiple synonyms associated with it. In this case the first name from the
+algorithm definition is returned. Ownership of the returned string is retained
+by the I<exchange> object and should not be freed by the caller.
+
+EVP_KEYEXCH_names_do_all() traverses all names for the I<exchange>, and
+calls I<fn> with each name and I<data>.
+
+EVP_KEYEXCH_get0_description() returns a description of the I<keyexch>, meant
+for display and human consumption. The description is at the discretion of
+the I<keyexch> implementation.
+
+EVP_KEYEXCH_do_all_provided() traverses all key exchange implementations by
+all activated providers in the library context I<libctx>, and for each
+of the implementations, calls I<fn> with the implementation method and
+I<data> as arguments.
+
+EVP_KEYEXCH_gettable_ctx_params() and EVP_KEYEXCH_settable_ctx_params() return
+a constant L<OSSL_PARAM(3)> array that describes the names and types of key
+parameters that can be retrieved or set by a key exchange algorithm using
+L<EVP_PKEY_CTX_get_params(3)> and L<EVP_PKEY_CTX_set_params(3)>.
+
+=head1 RETURN VALUES
+
+EVP_KEYEXCH_fetch() returns a pointer to a B<EVP_KEYEXCH> for success
+or NULL for failure.
+
+EVP_KEYEXCH_up_ref() returns 1 for success or 0 otherwise.
+
+EVP_KEYEXCH_names_do_all() returns 1 if the callback was called for all
+names. A return value of 0 means that the callback was not called for any names.
+
+EVP_KEYEXCH_is_a() returns 1 of I<exchange> was identifiable,
+otherwise 0.
+
+EVP_KEYEXCH_gettable_ctx_params() and EVP_KEYEXCH_settable_ctx_params() return
+a constant L<OSSL_PARAM(3)> array or NULL on error.
+
+=head1 SEE ALSO
+
+L<crypto(7)/ALGORITHM FETCHING>, L<OSSL_PROVIDER(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_KEYMGMT.pod b/doc/man3/EVP_KEYMGMT.pod
new file mode 100644
index 000000000000..f81fc9efb00b
--- /dev/null
+++ b/doc/man3/EVP_KEYMGMT.pod
@@ -0,0 +1,150 @@
+=pod
+
+=head1 NAME
+
+EVP_KEYMGMT,
+EVP_KEYMGMT_fetch,
+EVP_KEYMGMT_up_ref,
+EVP_KEYMGMT_free,
+EVP_KEYMGMT_get0_provider,
+EVP_KEYMGMT_is_a,
+EVP_KEYMGMT_get0_description,
+EVP_KEYMGMT_get0_name,
+EVP_KEYMGMT_do_all_provided,
+EVP_KEYMGMT_names_do_all,
+EVP_KEYMGMT_gettable_params,
+EVP_KEYMGMT_settable_params,
+EVP_KEYMGMT_gen_settable_params
+- EVP key management routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ typedef struct evp_keymgmt_st EVP_KEYMGMT;
+
+ EVP_KEYMGMT *EVP_KEYMGMT_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties);
+ int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt);
+ void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt);
+ const OSSL_PROVIDER *EVP_KEYMGMT_get0_provider(const EVP_KEYMGMT *keymgmt);
+ int EVP_KEYMGMT_is_a(const EVP_KEYMGMT *keymgmt, const char *name);
+ const char *EVP_KEYMGMT_get0_name(const EVP_KEYMGMT *keymgmt);
+ const char *EVP_KEYMGMT_get0_description(const EVP_KEYMGMT *keymgmt);
+
+ void EVP_KEYMGMT_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_KEYMGMT *keymgmt, void *arg),
+ void *arg);
+ int EVP_KEYMGMT_names_do_all(const EVP_KEYMGMT *keymgmt,
+ void (*fn)(const char *name, void *data),
+ void *data);
+ const OSSL_PARAM *EVP_KEYMGMT_gettable_params(const EVP_KEYMGMT *keymgmt);
+ const OSSL_PARAM *EVP_KEYMGMT_settable_params(const EVP_KEYMGMT *keymgmt);
+ const OSSL_PARAM *EVP_KEYMGMT_gen_settable_params(const EVP_KEYMGMT *keymgmt);
+
+=head1 DESCRIPTION
+
+B<EVP_KEYMGMT> is a method object that represents key management
+implementations for different cryptographic algorithms.
+This method object provides functionality to have providers import key
+material from the outside, as well as export key material to the
+outside.
+Most of the functionality can only be used internally and has no
+public interface, this object is simply passed into other functions
+when needed.
+
+EVP_KEYMGMT_fetch() looks for an algorithm within the provider that
+has been loaded into the B<OSSL_LIB_CTX> given by I<ctx>, having the
+name given by I<algorithm> and the properties given by I<properties>.
+
+EVP_KEYMGMT_up_ref() increments the reference count for the given
+B<EVP_KEYMGMT> I<keymgmt>.
+
+EVP_KEYMGMT_free() decrements the reference count for the given
+B<EVP_KEYMGMT> I<keymgmt>, and when the count reaches zero, frees it.
+
+EVP_KEYMGMT_get0_provider() returns the provider that has this particular
+implementation.
+
+EVP_KEYMGMT_is_a() checks if I<keymgmt> is an implementation of an
+algorithm that's identifiable with I<name>.
+
+EVP_KEYMGMT_get0_name() returns the algorithm name from the provided
+implementation for the given I<keymgmt>. Note that the I<keymgmt> may have
+multiple synonyms associated with it. In this case the first name from the
+algorithm definition is returned. Ownership of the returned string is
+retained by the I<keymgmt> object and should not be freed by the caller.
+
+EVP_KEYMGMT_names_do_all() traverses all names for the I<keymgmt>, and
+calls I<fn> with each name and I<data>.
+
+EVP_KEYMGMT_get0_description() returns a description of the I<keymgmt>, meant
+for display and human consumption. The description is at the discretion
+of the I<keymgmt> implementation.
+
+EVP_KEYMGMT_do_all_provided() traverses all key keymgmt implementations by
+all activated providers in the library context I<libctx>, and for each
+of the implementations, calls I<fn> with the implementation method and
+I<data> as arguments.
+
+EVP_KEYMGMT_gettable_params() and EVP_KEYMGMT_settable_params() return a
+constant L<OSSL_PARAM(3)> array that describes the names and types of key
+parameters that can be retrieved or set.
+EVP_KEYMGMT_gettable_params() is used by L<EVP_PKEY_gettable_params(3)>.
+
+EVP_KEYMGMT_gen_settable_params() returns a constant L<OSSL_PARAM(3)> array that
+describes the names and types of key generation parameters that can be set via
+L<EVP_PKEY_CTX_set_params(3)>.
+
+=head1 NOTES
+
+EVP_KEYMGMT_fetch() may be called implicitly by other fetching
+functions, using the same library context and properties.
+Any other API that uses keys will typically do this.
+
+=head1 RETURN VALUES
+
+EVP_KEYMGMT_fetch() returns a pointer to the key management
+implementation represented by an EVP_KEYMGMT object, or NULL on
+error.
+
+EVP_KEYMGMT_up_ref() returns 1 on success, or 0 on error.
+
+EVP_KEYMGMT_names_do_all() returns 1 if the callback was called for all
+names. A return value of 0 means that the callback was not called for any names.
+
+EVP_KEYMGMT_free() doesn't return any value.
+
+EVP_KEYMGMT_get0_provider() returns a pointer to a provider object, or NULL
+on error.
+
+EVP_KEYMGMT_is_a() returns 1 of I<keymgmt> was identifiable,
+otherwise 0.
+
+EVP_KEYMGMT_get0_name() returns the algorithm name, or NULL on error.
+
+EVP_KEYMGMT_get0_description() returns a pointer to a decription, or NULL if
+there isn't one.
+
+EVP_KEYMGMT_gettable_params(), EVP_KEYMGMT_settable_params() and
+EVP_KEYMGMT_gen_settable_params() return a constant L<OSSL_PARAM(3)> array or
+NULL on error.
+
+=head1 SEE ALSO
+
+L<EVP_MD_fetch(3)>, L<OSSL_LIB_CTX(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_MAC.pod b/doc/man3/EVP_MAC.pod
new file mode 100644
index 000000000000..13482ac5e188
--- /dev/null
+++ b/doc/man3/EVP_MAC.pod
@@ -0,0 +1,491 @@
+=pod
+
+=head1 NAME
+
+EVP_MAC, EVP_MAC_fetch, EVP_MAC_up_ref, EVP_MAC_free, EVP_MAC_is_a,
+EVP_MAC_get0_name, EVP_MAC_names_do_all, EVP_MAC_get0_description,
+EVP_MAC_get0_provider, EVP_MAC_get_params, EVP_MAC_gettable_params,
+EVP_MAC_CTX, EVP_MAC_CTX_new, EVP_MAC_CTX_free, EVP_MAC_CTX_dup,
+EVP_MAC_CTX_get0_mac, EVP_MAC_CTX_get_params, EVP_MAC_CTX_set_params,
+EVP_MAC_CTX_get_mac_size, EVP_MAC_CTX_get_block_size, EVP_Q_mac,
+EVP_MAC_init, EVP_MAC_update, EVP_MAC_final, EVP_MAC_finalXOF,
+EVP_MAC_gettable_ctx_params, EVP_MAC_settable_ctx_params,
+EVP_MAC_CTX_gettable_params, EVP_MAC_CTX_settable_params,
+EVP_MAC_do_all_provided - EVP MAC routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ typedef struct evp_mac_st EVP_MAC;
+ typedef struct evp_mac_ctx_st EVP_MAC_CTX;
+
+ EVP_MAC *EVP_MAC_fetch(OSSL_LIB_CTX *libctx, const char *algorithm,
+ const char *properties);
+ int EVP_MAC_up_ref(EVP_MAC *mac);
+ void EVP_MAC_free(EVP_MAC *mac);
+ int EVP_MAC_is_a(const EVP_MAC *mac, const char *name);
+ const char *EVP_MAC_get0_name(const EVP_MAC *mac);
+ int EVP_MAC_names_do_all(const EVP_MAC *mac,
+ void (*fn)(const char *name, void *data),
+ void *data);
+ const char *EVP_MAC_get0_description(const EVP_MAC *mac);
+ const OSSL_PROVIDER *EVP_MAC_get0_provider(const EVP_MAC *mac);
+ int EVP_MAC_get_params(EVP_MAC *mac, OSSL_PARAM params[]);
+
+ EVP_MAC_CTX *EVP_MAC_CTX_new(EVP_MAC *mac);
+ void EVP_MAC_CTX_free(EVP_MAC_CTX *ctx);
+ EVP_MAC_CTX *EVP_MAC_CTX_dup(const EVP_MAC_CTX *src);
+ EVP_MAC *EVP_MAC_CTX_get0_mac(EVP_MAC_CTX *ctx);
+ int EVP_MAC_CTX_get_params(EVP_MAC_CTX *ctx, OSSL_PARAM params[]);
+ int EVP_MAC_CTX_set_params(EVP_MAC_CTX *ctx, const OSSL_PARAM params[]);
+
+ size_t EVP_MAC_CTX_get_mac_size(EVP_MAC_CTX *ctx);
+ size_t EVP_MAC_CTX_get_block_size(EVP_MAC_CTX *ctx);
+ unsigned char *EVP_Q_mac(OSSL_LIB_CTX *libctx, const char *name, const char *propq,
+ const char *subalg, const OSSL_PARAM *params,
+ const void *key, size_t keylen,
+ const unsigned char *data, size_t datalen,
+ unsigned char *out, size_t outsize, size_t *outlen);
+ int EVP_MAC_init(EVP_MAC_CTX *ctx, const unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[]);
+ int EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen);
+ int EVP_MAC_final(EVP_MAC_CTX *ctx,
+ unsigned char *out, size_t *outl, size_t outsize);
+ int EVP_MAC_finalXOF(EVP_MAC_CTX *ctx, unsigned char *out, size_t outsize);
+
+ const OSSL_PARAM *EVP_MAC_gettable_params(const EVP_MAC *mac);
+ const OSSL_PARAM *EVP_MAC_gettable_ctx_params(const EVP_MAC *mac);
+ const OSSL_PARAM *EVP_MAC_settable_ctx_params(const EVP_MAC *mac);
+ const OSSL_PARAM *EVP_MAC_CTX_gettable_params(EVP_MAC_CTX *ctx);
+ const OSSL_PARAM *EVP_MAC_CTX_settable_params(EVP_MAC_CTX *ctx);
+
+ void EVP_MAC_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_MAC *mac, void *arg),
+ void *arg);
+
+=head1 DESCRIPTION
+
+These types and functions help the application to calculate MACs of
+different types and with different underlying algorithms if there are
+any.
+
+MACs are a bit complex insofar that some of them use other algorithms
+for actual computation. HMAC uses a digest, and CMAC uses a cipher.
+Therefore, there are sometimes two contexts to keep track of, one for
+the MAC algorithm itself and one for the underlying computation
+algorithm if there is one.
+
+To make things less ambiguous, this manual talks about a "context" or
+"MAC context", which is to denote the MAC level context, and about a
+"underlying context", or "computation context", which is to denote the
+context for the underlying computation algorithm if there is one.
+
+=head2 Types
+
+B<EVP_MAC> is a type that holds the implementation of a MAC.
+
+B<EVP_MAC_CTX> is a context type that holds internal MAC information
+as well as a reference to a computation context, for those MACs that
+rely on an underlying computation algorithm.
+
+=head2 Algorithm implementation fetching
+
+EVP_MAC_fetch() fetches an implementation of a MAC I<algorithm>, given
+a library context I<libctx> and a set of I<properties>.
+See L<crypto(7)/ALGORITHM FETCHING> for further information.
+
+See L<OSSL_PROVIDER-default(7)/Message Authentication Code (MAC)> for the list
+of algorithms supported by the default provider.
+
+The returned value must eventually be freed with
+L<EVP_MAC_free(3)>.
+
+EVP_MAC_up_ref() increments the reference count of an already fetched
+MAC.
+
+EVP_MAC_free() frees a fetched algorithm.
+NULL is a valid parameter, for which this function is a no-op.
+
+=head2 Context manipulation functions
+
+EVP_MAC_CTX_new() creates a new context for the MAC type I<mac>.
+The created context can then be used with most other functions
+described here.
+
+EVP_MAC_CTX_free() frees the contents of the context, including an
+underlying context if there is one, as well as the context itself.
+NULL is a valid parameter, for which this function is a no-op.
+
+EVP_MAC_CTX_dup() duplicates the I<src> context and returns a newly allocated
+context.
+
+EVP_MAC_CTX_get0_mac() returns the B<EVP_MAC> associated with the context
+I<ctx>.
+
+=head2 Computing functions
+
+EVP_Q_mac() computes the message authentication code
+of I<data> with length I<datalen>
+using the MAC algorithm I<name> and the key I<key> with length I<keylen>.
+The MAC algorithm is fetched using any given I<libctx> and property query
+string I<propq>. It takes parameters I<subalg> and further I<params>,
+both of which may be NULL if not needed.
+If I<out> is not NULL, it places the result in the memory pointed at by I<out>,
+but only if I<outsize> is sufficient (otherwise no computation is made).
+If I<out> is NULL, it allocates and uses a buffer of suitable length,
+which will be returned on success and must be freed by the caller.
+In either case, also on error,
+it assigns the number of bytes written to I<*outlen> unless I<outlen> is NULL.
+
+EVP_MAC_init() sets up the underlying context I<ctx> with information given
+via the I<key> and I<params> arguments. The MAC I<key> has a length of
+I<keylen> and the parameters in I<params> are processed before setting
+the key. If I<key> is NULL, the key must be set via I<params> either
+as part of this call or separately using EVP_MAC_CTX_set_params().
+Providing non-NULL I<params> to this function is equivalent to calling
+EVP_MAC_CTX_set_params() with those I<params> for the same I<ctx> beforehand.
+
+EVP_MAC_init() should be called before EVP_MAC_update() and EVP_MAC_final().
+
+EVP_MAC_update() adds I<datalen> bytes from I<data> to the MAC input.
+
+EVP_MAC_final() does the final computation and stores the result in
+the memory pointed at by I<out> of size I<outsize>, and sets the number
+of bytes written in I<*outl> at.
+If I<out> is NULL or I<outsize> is too small, then no computation
+is made.
+To figure out what the output length will be and allocate space for it
+dynamically, simply call with I<out> being NULL and I<outl>
+pointing at a valid location, then allocate space and make a second
+call with I<out> pointing at the allocated space.
+
+EVP_MAC_finalXOF() does the final computation for an XOF based MAC and stores
+the result in the memory pointed at by I<out> of size I<outsize>.
+
+EVP_MAC_get_params() retrieves details about the implementation
+I<mac>.
+The set of parameters given with I<params> determine exactly what
+parameters should be retrieved.
+Note that a parameter that is unknown in the underlying context is
+simply ignored.
+
+EVP_MAC_CTX_get_params() retrieves chosen parameters, given the
+context I<ctx> and its underlying context.
+The set of parameters given with I<params> determine exactly what
+parameters should be retrieved.
+Note that a parameter that is unknown in the underlying context is
+simply ignored.
+
+EVP_MAC_CTX_set_params() passes chosen parameters to the underlying
+context, given a context I<ctx>.
+The set of parameters given with I<params> determine exactly what
+parameters are passed down.
+If I<params> are NULL, the unterlying context should do nothing and return 1.
+Note that a parameter that is unknown in the underlying context is
+simply ignored.
+Also, what happens when a needed parameter isn't passed down is
+defined by the implementation.
+
+EVP_MAC_gettable_params() returns an L<OSSL_PARAM(3)> array that describes
+the retrievable and settable parameters. EVP_MAC_gettable_params()
+returns parameters that can be used with EVP_MAC_get_params().
+
+EVP_MAC_gettable_ctx_params() and EVP_MAC_CTX_gettable_params()
+return constant L<OSSL_PARAM(3)> arrays that describe the retrievable
+parameters that can be used with EVP_MAC_CTX_get_params().
+EVP_MAC_gettable_ctx_params() returns the parameters that can be retrieved
+from the algorithm, whereas EVP_MAC_CTX_gettable_params() returns
+the parameters that can be retrieved in the context's current state.
+
+EVP_MAC_settable_ctx_params() and EVP_MAC_CTX_settable_params() return
+constant L<OSSL_PARAM(3)> arrays that describe the settable parameters that
+can be used with EVP_MAC_CTX_set_params(). EVP_MAC_settable_ctx_params()
+returns the parameters that can be retrieved from the algorithm,
+whereas EVP_MAC_CTX_settable_params() returns the parameters that can
+be retrieved in the context's current state.
+
+=head2 Information functions
+
+EVP_MAC_CTX_get_mac_size() returns the MAC output size for the given context.
+
+EVP_MAC_CTX_get_block_size() returns the MAC block size for the given context.
+Not all MAC algorithms support this.
+
+EVP_MAC_is_a() checks if the given I<mac> is an implementation of an
+algorithm that's identifiable with I<name>.
+
+EVP_MAC_get0_provider() returns the provider that holds the implementation
+of the given I<mac>.
+
+EVP_MAC_do_all_provided() traverses all MAC implemented by all activated
+providers in the given library context I<libctx>, and for each of the
+implementations, calls the given function I<fn> with the implementation method
+and the given I<arg> as argument.
+
+EVP_MAC_get0_name() return the name of the given MAC. For fetched MACs
+with multiple names, only one of them is returned; it's
+recommended to use EVP_MAC_names_do_all() instead.
+
+EVP_MAC_names_do_all() traverses all names for I<mac>, and calls
+I<fn> with each name and I<data>.
+
+EVP_MAC_get0_description() returns a description of the I<mac>, meant
+for display and human consumption. The description is at the discretion
+of the mac implementation.
+
+=head1 PARAMETERS
+
+Parameters are identified by name as strings, and have an expected
+data type and maximum size.
+OpenSSL has a set of macros for parameter names it expects to see in
+its own MAC implementations.
+Here, we show all three, the OpenSSL macro for the parameter name, the
+name in string form, and a type description.
+
+The standard parameter names are:
+
+=over 4
+
+=item "key" (B<OSSL_MAC_PARAM_KEY>) <octet string>
+
+Its value is the MAC key as an array of bytes.
+
+For MACs that use an underlying computation algorithm, the algorithm
+must be set first, see parameter names "algorithm" below.
+
+=item "iv" (B<OSSL_MAC_PARAM_IV>) <octet string>
+
+Some MAC implementations (GMAC) require an IV, this parameter sets the IV.
+
+=item "custom" (B<OSSL_MAC_PARAM_CUSTOM>) <octet string>
+
+Some MAC implementations (KMAC, BLAKE2) accept a Customization String,
+this parameter sets the Customization String. The default value is the
+empty string.
+
+=item "salt" (B<OSSL_MAC_PARAM_SALT>) <octet string>
+
+This option is used by BLAKE2 MAC.
+
+=item "xof" (B<OSSL_MAC_PARAM_XOF>) <integer>
+
+It's a simple flag, the value 0 or 1 are expected.
+
+This option is used by KMAC.
+
+=item "digest-noinit" (B<OSSL_MAC_PARAM_DIGEST_NOINIT>) <integer>
+
+A simple flag to set the MAC digest to not initialise the
+implementation specific data. The value 0 or 1 is expected.
+
+This option is used by HMAC.
+
+=item "digest-oneshot" (B<OSSL_MAC_PARAM_DIGEST_ONESHOT>) <integer>
+
+A simple flag to set the MAC digest to be a oneshot operation.
+The value 0 or 1 is expected.
+
+This option is used by HMAC.
+
+=item "properties" (B<OSSL_MAC_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "digest" (B<OSSL_MAC_PARAM_DIGEST>) <UTF8 string>
+
+=item "cipher" (B<OSSL_MAC_PARAM_CIPHER>) <UTF8 string>
+
+For MAC implementations that use an underlying computation cipher or
+digest, these parameters set what the algorithm should be.
+
+The value is always the name of the intended algorithm,
+or the properties.
+
+Note that not all algorithms may support all digests.
+HMAC does not support variable output length digests such as SHAKE128
+or SHAKE256.
+
+=item "size" (B<OSSL_MAC_PARAM_SIZE>) <unsigned integer>
+
+For MAC implementations that support it, set the output size that
+EVP_MAC_final() should produce.
+The allowed sizes vary between MAC implementations, but must never exceed
+what can be given with a B<size_t>.
+
+=item "tls-data-size" (B<OSSL_MAC_PARAM_TLS_DATA_SIZE>) <unsigned integer>
+
+This parameter is only supported by HMAC. If set then special handling is
+activated for calculating the MAC of a received mac-then-encrypt TLS record
+where variable length record padding has been used (as in the case of CBC mode
+ciphersuites). The value represents the total length of the record that is
+having the MAC calculated including the received MAC and the record padding.
+
+When used EVP_MAC_update must be called precisely twice. The first time with
+the 13 bytes of TLS "header" data, and the second time with the entire record
+including the MAC itself and any padding. The entire record length must equal
+the value passed in the "tls-data-size" parameter. The length passed in the
+B<datalen> parameter to EVP_MAC_update() should be equal to the length of the
+record after the MAC and any padding has been removed.
+
+=back
+
+All these parameters should be used before the calls to any of
+EVP_MAC_init(), EVP_MAC_update() and EVP_MAC_final() for a full
+computation.
+Anything else may give undefined results.
+
+=head1 NOTES
+
+The MAC life-cycle is described in L<life_cycle-mac(7)>. In the future,
+the transitions described there will be enforced. When this is done, it will
+not be considered a breaking change to the API.
+
+The usage of the parameter names "custom", "iv" and "salt" correspond to
+the names used in the standard where the algorithm was defined.
+
+=head1 RETURN VALUES
+
+EVP_MAC_fetch() returns a pointer to a newly fetched B<EVP_MAC>, or
+NULL if allocation failed.
+
+EVP_MAC_up_ref() returns 1 on success, 0 on error.
+
+EVP_MAC_names_do_all() returns 1 if the callback was called for all names. A
+return value of 0 means that the callback was not called for any names.
+
+EVP_MAC_free() returns nothing at all.
+
+EVP_MAC_is_a() returns 1 if the given method can be identified with
+the given name, otherwise 0.
+
+EVP_MAC_get0_name() returns a name of the MAC, or NULL on error.
+
+EVP_MAC_get0_provider() returns a pointer to the provider for the MAC, or
+NULL on error.
+
+EVP_MAC_CTX_new() and EVP_MAC_CTX_dup() return a pointer to a newly
+created EVP_MAC_CTX, or NULL if allocation failed.
+
+EVP_MAC_CTX_free() returns nothing at all.
+
+EVP_MAC_CTX_get_params() and EVP_MAC_CTX_set_params() return 1 on
+success, 0 on error.
+
+EVP_Q_mac() returns a pointer to the computed MAC value, or NULL on error.
+
+EVP_MAC_init(), EVP_MAC_update(), EVP_MAC_final(), and EVP_MAC_finalXOF()
+return 1 on success, 0 on error.
+
+EVP_MAC_CTX_get_mac_size() returns the expected output size, or 0 if it isn't
+set. If it isn't set, a call to EVP_MAC_init() will set it.
+
+EVP_MAC_CTX_get_block_size() returns the block size, or 0 if it isn't set.
+If it isn't set, a call to EVP_MAC_init() will set it.
+
+EVP_MAC_do_all_provided() returns nothing at all.
+
+=head1 EXAMPLES
+
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdarg.h>
+ #include <unistd.h>
+
+ #include <openssl/evp.h>
+ #include <openssl/err.h>
+ #include <openssl/params.h>
+
+ int main() {
+ EVP_MAC *mac = EVP_MAC_fetch(NULL, getenv("MY_MAC"), NULL);
+ const char *cipher = getenv("MY_MAC_CIPHER");
+ const char *digest = getenv("MY_MAC_DIGEST");
+ const char *key = getenv("MY_KEY");
+ EVP_MAC_CTX *ctx = NULL;
+
+ unsigned char buf[4096];
+ size_t read_l;
+ size_t final_l;
+
+ size_t i;
+
+ OSSL_PARAM params[3];
+ size_t params_n = 0;
+
+ if (cipher != NULL)
+ params[params_n++] =
+ OSSL_PARAM_construct_utf8_string("cipher", (char*)cipher, 0);
+ if (digest != NULL)
+ params[params_n++] =
+ OSSL_PARAM_construct_utf8_string("digest", (char*)digest, 0);
+ params[params_n] = OSSL_PARAM_construct_end();
+
+ if (mac == NULL
+ || key == NULL
+ || (ctx = EVP_MAC_CTX_new(mac)) == NULL
+ || !EVP_MAC_init(ctx, (const unsigned char *)key, strlen(key),
+ params))
+ goto err;
+
+ while ( (read_l = read(STDIN_FILENO, buf, sizeof(buf))) > 0) {
+ if (!EVP_MAC_update(ctx, buf, read_l))
+ goto err;
+ }
+
+ if (!EVP_MAC_final(ctx, buf, &final_l, sizeof(buf)))
+ goto err;
+
+ printf("Result: ");
+ for (i = 0; i < final_l; i++)
+ printf("%02X", buf[i]);
+ printf("\n");
+
+ EVP_MAC_CTX_free(ctx);
+ EVP_MAC_free(mac);
+ exit(0);
+
+ err:
+ EVP_MAC_CTX_free(ctx);
+ EVP_MAC_free(mac);
+ fprintf(stderr, "Something went wrong\n");
+ ERR_print_errors_fp(stderr);
+ exit (1);
+ }
+
+A run of this program, called with correct environment variables, can
+look like this:
+
+ $ MY_MAC=cmac MY_KEY=secret0123456789 MY_MAC_CIPHER=aes-128-cbc \
+ LD_LIBRARY_PATH=. ./foo < foo.c
+ Result: C5C06683CD9DDEF904D754505C560A4E
+
+(in this example, that program was stored in F<foo.c> and compiled to
+F<./foo>)
+
+=head1 SEE ALSO
+
+L<property(7)>
+L<OSSL_PARAM(3)>,
+L<EVP_MAC-BLAKE2(7)>,
+L<EVP_MAC-CMAC(7)>,
+L<EVP_MAC-GMAC(7)>,
+L<EVP_MAC-HMAC(7)>,
+L<EVP_MAC-KMAC(7)>,
+L<EVP_MAC-Siphash(7)>,
+L<EVP_MAC-Poly1305(7)>,
+L<provider-mac(7)>,
+L<life_cycle-mac(7)>
+
+=head1 HISTORY
+
+These functions were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_MD_meth_new.pod b/doc/man3/EVP_MD_meth_new.pod
index e17a4cd519ab..a553c378f3d7 100644
--- a/doc/man3/EVP_MD_meth_new.pod
+++ b/doc/man3/EVP_MD_meth_new.pod
@@ -2,8 +2,8 @@
=head1 NAME
-EVP_MD_meth_dup,
-EVP_MD_meth_new, EVP_MD_meth_free, EVP_MD_meth_set_input_blocksize,
+EVP_MD_meth_new, EVP_MD_meth_dup, EVP_MD_meth_free,
+EVP_MD_meth_set_input_blocksize,
EVP_MD_meth_set_result_size, EVP_MD_meth_set_app_datasize,
EVP_MD_meth_set_flags, EVP_MD_meth_set_init, EVP_MD_meth_set_update,
EVP_MD_meth_set_final, EVP_MD_meth_set_copy, EVP_MD_meth_set_cleanup,
@@ -12,12 +12,16 @@ EVP_MD_meth_get_result_size, EVP_MD_meth_get_app_datasize,
EVP_MD_meth_get_flags, EVP_MD_meth_get_init, EVP_MD_meth_get_update,
EVP_MD_meth_get_final, EVP_MD_meth_get_copy, EVP_MD_meth_get_cleanup,
EVP_MD_meth_get_ctrl
-- Routines to build up EVP_MD methods
+- Routines to build up legacy EVP_MD methods
=head1 SYNOPSIS
#include <openssl/evp.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type);
void EVP_MD_meth_free(EVP_MD *md);
EVP_MD *EVP_MD_meth_dup(const EVP_MD *md);
@@ -56,15 +60,20 @@ EVP_MD_meth_get_ctrl
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use the OSSL_PROVIDER APIs.
+
The B<EVP_MD> type is a structure for digest method implementation.
It can also have associated public/private key signing and verifying
routines.
EVP_MD_meth_new() creates a new B<EVP_MD> structure.
+These B<EVP_MD> structures are reference counted.
EVP_MD_meth_dup() creates a copy of B<md>.
-EVP_MD_meth_free() destroys a B<EVP_MD> structure.
+EVP_MD_meth_free() decrements the reference count for the B<EVP_MD> structure.
+If the reference count drops to 0 then the structure is freed.
EVP_MD_meth_set_input_blocksize() sets the internal input block size
for the method B<md> to B<blocksize> bytes.
@@ -135,7 +144,7 @@ computations after the method's private data structure has been copied
from one B<EVP_MD_CTX> to another. If all that's needed is to copy
the data, there is no need for this copy function.
Note that the copy function is passed two B<EVP_MD_CTX *>, the private
-data structure is then available with EVP_MD_CTX_md_data().
+data structure is then available with EVP_MD_CTX_get0_md_data().
This copy function is called by EVP_MD_CTX_copy() and
EVP_MD_CTX_copy_ex().
@@ -143,7 +152,7 @@ EVP_MD_meth_set_cleanup() sets the function for B<md> to do extra
cleanup before the method's private data structure is cleaned out and
freed.
Note that the cleanup function is passed a B<EVP_MD_CTX *>, the
-private data structure is then available with EVP_MD_CTX_md_data().
+private data structure is then available with EVP_MD_CTX_get0_md_data().
This cleanup function is called by EVP_MD_CTX_reset() and
EVP_MD_CTX_free().
@@ -175,14 +184,19 @@ L<EVP_DigestInit(3)>, L<EVP_SignInit(3)>, L<EVP_VerifyInit(3)>
=head1 HISTORY
+All of these functions were deprecated in OpenSSL 3.0.
+
The B<EVP_MD> structure was openly available in OpenSSL before version
-1.1. The functions described here were added in OpenSSL 1.1.
+1.1.
+The functions described here were added in OpenSSL 1.1.
+The B<EVP_MD> structure created with these functions became reference
+counted in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_OpenInit.pod b/doc/man3/EVP_OpenInit.pod
index 37223c8abf4c..baa7ad52f011 100644
--- a/doc/man3/EVP_OpenInit.pod
+++ b/doc/man3/EVP_OpenInit.pod
@@ -61,7 +61,7 @@ L<EVP_SealInit(3)>
Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PBE_CipherInit.pod b/doc/man3/EVP_PBE_CipherInit.pod
new file mode 100644
index 000000000000..c6191a945347
--- /dev/null
+++ b/doc/man3/EVP_PBE_CipherInit.pod
@@ -0,0 +1,111 @@
+=pod
+
+=head1 NAME
+
+EVP_PBE_CipherInit, EVP_PBE_CipherInit_ex,
+EVP_PBE_find, EVP_PBE_find_ex,
+EVP_PBE_alg_add_type, EVP_PBE_alg_add - Password based encryption routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
+ ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de);
+ int EVP_PBE_CipherInit_ex(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
+ ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+ int EVP_PBE_find(int type, int pbe_nid, int *pcnid, int *pmnid,
+ EVP_PBE_KEYGEN **pkeygen);
+ int EVP_PBE_find_ex(int type, int pbe_nid, int *pcnid, int *pmnid,
+ EVP_PBE_KEYGEN **pkeygen, EVP_PBE_KEYGEN_EX **keygen_ex);
+
+ int EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid,
+ int md_nid, EVP_PBE_KEYGEN *keygen);
+ int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
+ EVP_PBE_KEYGEN *keygen);
+
+=head1 DESCRIPTION
+
+=head2 PBE operations
+
+EVP_PBE_CipherInit() and EVP_PBE_CipherInit_ex() initialise an B<EVP_CIPHER_CTX>
+I<ctx> for encryption (I<en_de>=1) or decryption (I<en_de>=0) using the password
+I<pass> of length I<passlen>. The PBE algorithm type and parameters are extracted
+from an OID I<pbe_obj> and parameters I<param>.
+
+EVP_PBE_CipherInit_ex() also allows the application to specify a library context
+I<libctx> and property query I<propq> to select appropriate algorithm
+implementations.
+
+=head2 PBE algorithm search
+
+EVP_PBE_find() and EVP_PBE_find_ex() search for a matching algorithm using two parameters:
+
+1. An algorithm type I<type> which can be:
+
+=over 4
+
+=item *
+
+EVP_PBE_TYPE_OUTER - A PBE algorithm
+
+=item *
+
+EVP_PBE_TYPE_PRF - A pseudo-random function
+
+=item *
+
+EVP_PBE_TYPE_KDF - A key derivation function
+
+=back
+
+2. A I<pbe_nid> which can represent the algorithm identifier with parameters e.g.
+B<NID_pbeWithSHA1AndRC2_CBC> or an algorithm class e.g. B<NID_pbes2>.
+
+They return the algorithm's cipher ID I<pcnid>, digest ID I<pmnid> and a key
+generation function for the algorithm I<pkeygen>. EVP_PBE_CipherInit_ex() also
+returns an extended key generation function I<keygen_ex> which takes a library
+context and property query.
+
+If a NULL is supplied for any of I<pcnid>, I<pmnid>, I<pkeygen> or I<pkeygen_ex>
+then this parameter is not returned.
+
+=head2 PBE algorithm add
+
+EVP_PBE_alg_add_type() and EVP_PBE_alg_add() add an algorithm to the list
+of known algorithms. Their parameters have the same meaning as for
+EVP_PBE_find() and EVP_PBE_find_ex() functions.
+
+=head1 NOTES
+
+The arguments I<pbe_obj> and I<param> to EVP_PBE_CipherInit() and EVP_PBE_CipherInit_ex()
+together form an B<X509_ALGOR> and can often be extracted directly from this structure.
+
+=head1 RETURN VALUES
+
+Return value is 1 for success and 0 if an error occurred.
+
+=head1 SEE ALSO
+
+L<PKCS5_PBE_keyivgen(3)>,
+L<PKCS12_PBE_keyivgen_ex(3)>,
+L<PKCS5_v2_PBE_keyivgen_ex(3)>,
+L<PKCS12_pbe_crypt_ex(3)>,
+L<PKCS12_create_ex(3)>
+
+=head1 HISTORY
+
+EVP_PBE_CipherInit_ex() and EVP_PBE_find_ex() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_PKEY2PKCS8.pod b/doc/man3/EVP_PKEY2PKCS8.pod
new file mode 100644
index 000000000000..290a3ba3593e
--- /dev/null
+++ b/doc/man3/EVP_PKEY2PKCS8.pod
@@ -0,0 +1,47 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY2PKCS8, EVP_PKCS82PKEY_ex, EVP_PKCS82PKEY
+- Convert a private key to/from PKCS8
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509.h>
+
+ PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(const EVP_PKEY *pkey);
+ EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8);
+ EVP_PKEY *EVP_PKCS82PKEY_ex(const PKCS8_PRIV_KEY_INFO *p8, OSSL_LIB_CTX *libctx,
+ const char *propq);
+
+=head1 DESCRIPTION
+
+EVP_PKEY2PKCS8() converts a private key I<pkey> into a returned PKCS8 object.
+
+EVP_PKCS82PKEY_ex() converts a PKCS8 object I<p8> into a returned private key.
+It uses I<libctx> and I<propq> when fetching algorithms.
+
+EVP_PKCS82PKEY() is similiar to EVP_PKCS82PKEY_ex() but uses default values of
+NULL for the I<libctx> and I<propq>.
+
+=head1 RETURN VALUES
+
+EVP_PKEY2PKCS8() returns a PKCS8 object on success.
+EVP_PKCS82PKEY() and EVP_PKCS82PKEY_ex() return a private key on success.
+
+All functions return NULL if the operation fails.
+
+=head1 SEE ALSO
+
+L<PKCS8_pkey_add1_attr(3)>,
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_PKEY_ASN1_METHOD.pod b/doc/man3/EVP_PKEY_ASN1_METHOD.pod
index 3c2ffd94e872..cc50d363daf1 100644
--- a/doc/man3/EVP_PKEY_ASN1_METHOD.pod
+++ b/doc/man3/EVP_PKEY_ASN1_METHOD.pod
@@ -43,7 +43,7 @@ EVP_PKEY_get0_asn1
void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
int (*pub_decode) (EVP_PKEY *pk,
- X509_PUBKEY *pub),
+ const X509_PUBKEY *pub),
int (*pub_encode) (X509_PUBKEY *pub,
const EVP_PKEY *pk),
int (*pub_cmp) (const EVP_PKEY *a,
@@ -156,7 +156,7 @@ L<EVP_PKEY_asn1_add0(3)>.
The methods are the underlying implementations of a particular public
key algorithm present by the B<EVP_PKEY> object.
- int (*pub_decode) (EVP_PKEY *pk, X509_PUBKEY *pub);
+ int (*pub_decode) (EVP_PKEY *pk, const X509_PUBKEY *pub);
int (*pub_encode) (X509_PUBKEY *pub, const EVP_PKEY *pk);
int (*pub_cmp) (const EVP_PKEY *a, const EVP_PKEY *b);
int (*pub_print) (BIO *out, const EVP_PKEY *pkey, int indent,
@@ -170,7 +170,7 @@ They're called by L<X509_PUBKEY_get0(3)> and L<X509_PUBKEY_set(3)>.
The pub_cmp() method is called when two public keys are to be
compared.
It MUST return 1 when the keys are equal, 0 otherwise.
-It's called by L<EVP_PKEY_cmp(3)>.
+It's called by L<EVP_PKEY_eq(3)>.
The pub_print() method is called to print a public key in humanly
readable text to B<out>, indented B<indent> spaces.
@@ -197,10 +197,10 @@ It's called by L<EVP_PKEY_print_private(3)>.
int (*pkey_security_bits) (const EVP_PKEY *pk);
The pkey_size() method returns the key size in bytes.
-It's called by L<EVP_PKEY_size(3)>.
+It's called by L<EVP_PKEY_get_size(3)>.
The pkey_bits() method returns the key size in bits.
-It's called by L<EVP_PKEY_bits(3)>.
+It's called by L<EVP_PKEY_get_bits(3)>.
int (*param_decode) (EVP_PKEY *pkey,
const unsigned char **pder, int derlen);
@@ -228,7 +228,7 @@ It's called by L<EVP_PKEY_copy_parameters(3)>.
The param_cmp() method compares the parameters of keys B<a> and B<b>.
It MUST return 1 when the keys are equal, 0 when not equal, or a
negative number on error.
-It's called by L<EVP_PKEY_cmp_parameters(3)>.
+It's called by L<EVP_PKEY_parameters_eq(3)>.
The param_print() method prints the private key parameters in humanly
readable text to B<out>, indented B<indent> spaces.
@@ -257,8 +257,8 @@ L<EVP_PKEY_set_type_str(3)>, and L<EVP_PKEY_assign(3)>.
The pkey_ctrl() method adds extra algorithm specific control.
It's called by L<EVP_PKEY_get_default_digest_nid(3)>,
-L<EVP_PKEY_set1_tls_encodedpoint(3)>,
-L<EVP_PKEY_get1_tls_encodedpoint(3)>, L<PKCS7_SIGNER_INFO_set(3)>,
+L<EVP_PKEY_set1_encoded_public_key(3)>,
+L<EVP_PKEY_get1_encoded_public_key(3)>, L<PKCS7_SIGNER_INFO_set(3)>,
L<PKCS7_RECIP_INFO_set(3)>, ...
int (*old_priv_decode) (EVP_PKEY *pkey,
@@ -360,6 +360,16 @@ public key data for an EVP_PKEY. They MUST return 0 on error, or 1 on success.
They are called by L<EVP_PKEY_new_raw_private_key(3)>, and
L<EVP_PKEY_new_raw_public_key(3)> respectively.
+ size_t (*dirty) (const EVP_PKEY *pk);
+ void *(*export_to) (const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt);
+
+dirty_cnt() returns the internal key's dirty count.
+This can be used to synchronise different copies of the same keys.
+
+The export_to() method exports the key material from the given key to
+a provider, through the L<EVP_KEYMGMT(3)> interface, if that provider
+supports importing key material.
+
=head2 Functions
EVP_PKEY_asn1_new() creates and returns a new B<EVP_PKEY_ASN1_METHOD>
@@ -421,11 +431,17 @@ or 1 on success.
EVP_PKEY_get0_asn1() returns NULL on error, or a pointer to a constant
B<EVP_PKEY_ASN1_METHOD> object otherwise.
+=head1 HISTORY
+
+The signature of the I<pub_decode> functional argument of
+EVP_PKEY_asn1_set_public() has changed in OpenSSL 3.0 so its I<pub>
+parameter is now constified.
+
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_CTX_ctrl.pod b/doc/man3/EVP_PKEY_CTX_ctrl.pod
index e4753168abf7..3075eaafd677 100644
--- a/doc/man3/EVP_PKEY_CTX_ctrl.pod
+++ b/doc/man3/EVP_PKEY_CTX_ctrl.pod
@@ -9,26 +9,39 @@ EVP_PKEY_CTX_md,
EVP_PKEY_CTX_set_signature_md,
EVP_PKEY_CTX_get_signature_md,
EVP_PKEY_CTX_set_mac_key,
+EVP_PKEY_CTX_set_group_name,
+EVP_PKEY_CTX_get_group_name,
EVP_PKEY_CTX_set_rsa_padding,
EVP_PKEY_CTX_get_rsa_padding,
EVP_PKEY_CTX_set_rsa_pss_saltlen,
EVP_PKEY_CTX_get_rsa_pss_saltlen,
EVP_PKEY_CTX_set_rsa_keygen_bits,
EVP_PKEY_CTX_set_rsa_keygen_pubexp,
+EVP_PKEY_CTX_set1_rsa_keygen_pubexp,
EVP_PKEY_CTX_set_rsa_keygen_primes,
+EVP_PKEY_CTX_set_rsa_mgf1_md_name,
EVP_PKEY_CTX_set_rsa_mgf1_md,
EVP_PKEY_CTX_get_rsa_mgf1_md,
+EVP_PKEY_CTX_get_rsa_mgf1_md_name,
+EVP_PKEY_CTX_set_rsa_oaep_md_name,
EVP_PKEY_CTX_set_rsa_oaep_md,
EVP_PKEY_CTX_get_rsa_oaep_md,
+EVP_PKEY_CTX_get_rsa_oaep_md_name,
EVP_PKEY_CTX_set0_rsa_oaep_label,
EVP_PKEY_CTX_get0_rsa_oaep_label,
EVP_PKEY_CTX_set_dsa_paramgen_bits,
EVP_PKEY_CTX_set_dsa_paramgen_q_bits,
EVP_PKEY_CTX_set_dsa_paramgen_md,
+EVP_PKEY_CTX_set_dsa_paramgen_md_props,
+EVP_PKEY_CTX_set_dsa_paramgen_gindex,
+EVP_PKEY_CTX_set_dsa_paramgen_type,
+EVP_PKEY_CTX_set_dsa_paramgen_seed,
EVP_PKEY_CTX_set_dh_paramgen_prime_len,
EVP_PKEY_CTX_set_dh_paramgen_subprime_len,
EVP_PKEY_CTX_set_dh_paramgen_generator,
EVP_PKEY_CTX_set_dh_paramgen_type,
+EVP_PKEY_CTX_set_dh_paramgen_gindex,
+EVP_PKEY_CTX_set_dh_paramgen_seed,
EVP_PKEY_CTX_set_dh_rfc5114,
EVP_PKEY_CTX_set_dhx_rfc5114,
EVP_PKEY_CTX_set_dh_pad,
@@ -55,7 +68,8 @@ EVP_PKEY_CTX_set_ecdh_kdf_outlen,
EVP_PKEY_CTX_get_ecdh_kdf_outlen,
EVP_PKEY_CTX_set0_ecdh_kdf_ukm,
EVP_PKEY_CTX_get0_ecdh_kdf_ukm,
-EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len
+EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len,
+EVP_PKEY_CTX_set_kem_op
- algorithm specific control operations
=head1 SYNOPSIS
@@ -74,22 +88,36 @@ EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len
int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd);
- int EVP_PKEY_CTX_set_mac_key(EVP_PKEY_CTX *ctx, unsigned char *key, int len);
+ int EVP_PKEY_CTX_set_mac_key(EVP_PKEY_CTX *ctx, const unsigned char *key,
+ int len);
+ int EVP_PKEY_CTX_set_group_name(EVP_PKEY_CTX *ctx, const char *name);
+ int EVP_PKEY_CTX_get_group_name(EVP_PKEY_CTX *ctx, char *name, size_t namelen);
+
+ int EVP_PKEY_CTX_set_kem_op(EVP_PKEY_CTX *ctx, const char *op);
#include <openssl/rsa.h>
int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad);
int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad);
- int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int len);
- int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *len);
+ int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int saltlen);
+ int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen);
int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int mbits);
- int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp);
+ int EVP_PKEY_CTX_set1_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp);
int EVP_PKEY_CTX_set_rsa_keygen_primes(EVP_PKEY_CTX *ctx, int primes);
+ int EVP_PKEY_CTX_set_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, const char *mdname,
+ const char *mdprops);
int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
+ int EVP_PKEY_CTX_get_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, char *name,
+ size_t namelen);
+ int EVP_PKEY_CTX_set_rsa_oaep_md_name(EVP_PKEY_CTX *ctx, const char *mdname,
+ const char *mdprops);
int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
- int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char *label, int len);
+ int EVP_PKEY_CTX_get_rsa_oaep_md_name(EVP_PKEY_CTX *ctx, char *name,
+ size_t namelen);
+ int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, void *label,
+ int len);
int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char **label);
#include <openssl/dsa.h>
@@ -97,6 +125,14 @@ EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len
int EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX *ctx, int nbits);
int EVP_PKEY_CTX_set_dsa_paramgen_q_bits(EVP_PKEY_CTX *ctx, int qbits);
int EVP_PKEY_CTX_set_dsa_paramgen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
+ int EVP_PKEY_CTX_set_dsa_paramgen_md_props(EVP_PKEY_CTX *ctx,
+ const char *md_name,
+ const char *md_properties);
+ int EVP_PKEY_CTX_set_dsa_paramgen_type(EVP_PKEY_CTX *ctx, const char *name);
+ int EVP_PKEY_CTX_set_dsa_paramgen_gindex(EVP_PKEY_CTX *ctx, int gindex);
+ int EVP_PKEY_CTX_set_dsa_paramgen_seed(EVP_PKEY_CTX *ctx,
+ const unsigned char *seed,
+ size_t seedlen);
#include <openssl/dh.h>
@@ -108,6 +144,10 @@ EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len
int EVP_PKEY_CTX_set_dh_nid(EVP_PKEY_CTX *ctx, int nid);
int EVP_PKEY_CTX_set_dh_rfc5114(EVP_PKEY_CTX *ctx, int rfc5114);
int EVP_PKEY_CTX_set_dhx_rfc5114(EVP_PKEY_CTX *ctx, int rfc5114);
+ int EVP_PKEY_CTX_set_dh_paramgen_gindex(EVP_PKEY_CTX *ctx, int gindex);
+ int EVP_PKEY_CTX_set_dh_paramgen_seed(EVP_PKEY_CTX *ctx,
+ const unsigned char *seed,
+ size_t seedlen);
int EVP_PKEY_CTX_set_dh_kdf_type(EVP_PKEY_CTX *ctx, int kdf);
int EVP_PKEY_CTX_get_dh_kdf_type(EVP_PKEY_CTX *ctx);
int EVP_PKEY_CTX_set0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT *oid);
@@ -117,7 +157,6 @@ EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len
int EVP_PKEY_CTX_set_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int len);
int EVP_PKEY_CTX_get_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int *len);
int EVP_PKEY_CTX_set0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len);
- int EVP_PKEY_CTX_get0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **ukm);
#include <openssl/ec.h>
@@ -132,69 +171,93 @@ EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len
int EVP_PKEY_CTX_set_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int len);
int EVP_PKEY_CTX_get_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int *len);
int EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len);
- int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **ukm);
int EVP_PKEY_CTX_set1_id(EVP_PKEY_CTX *ctx, void *id, size_t id_len);
int EVP_PKEY_CTX_get1_id(EVP_PKEY_CTX *ctx, void *id);
int EVP_PKEY_CTX_get1_id_len(EVP_PKEY_CTX *ctx, size_t *id_len);
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ #include <openssl/rsa.h>
+
+ int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp);
+
+ #include <openssl/dh.h>
+
+ int EVP_PKEY_CTX_get0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **ukm);
+
+ #include <openssl/ec.h>
+
+ int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **ukm);
+
=head1 DESCRIPTION
-The function EVP_PKEY_CTX_ctrl() sends a control operation to the context
-B<ctx>. The key type used must match B<keytype> if it is not -1. The parameter
-B<optype> is a mask indicating which operations the control can be applied to.
-The control command is indicated in B<cmd> and any additional arguments in
-B<p1> and B<p2>.
+EVP_PKEY_CTX_ctrl() sends a control operation to the context I<ctx>. The key
+type used must match I<keytype> if it is not -1. The parameter I<optype> is a
+mask indicating which operations the control can be applied to.
+The control command is indicated in I<cmd> and any additional arguments in
+I<p1> and I<p2>.
-For B<cmd> = B<EVP_PKEY_CTRL_SET_MAC_KEY>, B<p1> is the length of the MAC key,
-and B<p2> is MAC key. This is used by Poly1305, SipHash, HMAC and CMAC.
+For I<cmd> = B<EVP_PKEY_CTRL_SET_MAC_KEY>, I<p1> is the length of the MAC key,
+and I<p2> is the MAC key. This is used by Poly1305, SipHash, HMAC and CMAC.
Applications will not normally call EVP_PKEY_CTX_ctrl() directly but will
-instead call one of the algorithm specific macros below.
+instead call one of the algorithm specific functions below.
-The function EVP_PKEY_CTX_ctrl_uint64() is a wrapper that directly passes a
-uint64 value as B<p2> to EVP_PKEY_CTX_ctrl().
+EVP_PKEY_CTX_ctrl_uint64() is a wrapper that directly passes a
+uint64 value as I<p2> to EVP_PKEY_CTX_ctrl().
-The function EVP_PKEY_CTX_ctrl_str() allows an application to send an algorithm
-specific control operation to a context B<ctx> in string form. This is
+EVP_PKEY_CTX_ctrl_str() allows an application to send an algorithm
+specific control operation to a context I<ctx> in string form. This is
intended to be used for options specified on the command line or in text
files. The commands supported are documented in the openssl utility
-command line pages for the option B<-pkeyopt> which is supported by the
-B<pkeyutl>, B<genpkey> and B<req> commands.
-
-The function EVP_PKEY_CTX_md() sends a message digest control operation
-to the context B<ctx>. The message digest is specified by its name B<md>.
+command line pages for the option I<-pkeyopt> which is supported by the
+I<pkeyutl>, I<genpkey> and I<req> commands.
-All the remaining "functions" are implemented as macros.
+EVP_PKEY_CTX_md() sends a message digest control operation to the context
+I<ctx>. The message digest is specified by its name I<md>.
-The EVP_PKEY_CTX_set_signature_md() macro sets the message digest type used
+EVP_PKEY_CTX_set_signature_md() sets the message digest type used
in a signature. It can be used in the RSA, DSA and ECDSA algorithms.
-The EVP_PKEY_CTX_get_signature_md() macro gets the message digest type used in a
-signature. It can be used in the RSA, DSA and ECDSA algorithms.
+EVP_PKEY_CTX_get_signature_md()gets the message digest type used
+in a signature. It can be used in the RSA, DSA and ECDSA algorithms.
Key generation typically involves setting up parameters to be used and
generating the private and public key data. Some algorithm implementations
-allow private key data to be set explicitly using the EVP_PKEY_CTX_set_mac_key()
-macro. In this case key generation is simply the process of setting up the
-parameters for the key and then setting the raw key data to the value explicitly
-provided by that macro. Normally applications would call
-L<EVP_PKEY_new_raw_private_key(3)> or similar functions instead of this macro.
+allow private key data to be set explicitly using EVP_PKEY_CTX_set_mac_key().
+In this case key generation is simply the process of setting up the
+parameters for the key and then setting the raw key data to the value explicitly.
+Normally applications would call L<EVP_PKEY_new_raw_private_key(3)> or similar
+functions instead.
+
+EVP_PKEY_CTX_set_mac_key() can be used with any of the algorithms supported by
+the L<EVP_PKEY_new_raw_private_key(3)> function.
+
+EVP_PKEY_CTX_set_group_name() sets the group name to I<name> for parameter and
+key generation. For example for EC keys this will set the curve name and for
+DH keys it will set the name of the finite field group.
-The EVP_PKEY_CTX_set_mac_key() macro can be used with any of the algorithms
-supported by the L<EVP_PKEY_new_raw_private_key(3)> function.
+EVP_PKEY_CTX_get_group_name() finds the group name that's currently
+set with I<ctx>, and writes it to the location that I<name> points at, as long
+as its size I<namelen> is large enough to store that name, including a
+terminating NUL byte.
=head2 RSA parameters
-The EVP_PKEY_CTX_set_rsa_padding() macro sets the RSA padding mode for B<ctx>.
-The B<pad> parameter can take the value B<RSA_PKCS1_PADDING> for PKCS#1
-padding, B<RSA_SSLV23_PADDING> for SSLv23 padding, B<RSA_NO_PADDING> for
+EVP_PKEY_CTX_set_rsa_padding() sets the RSA padding mode for I<ctx>.
+The I<pad> parameter can take the value B<RSA_PKCS1_PADDING> for PKCS#1
+padding, B<RSA_NO_PADDING> for
no padding, B<RSA_PKCS1_OAEP_PADDING> for OAEP padding (encrypt and
decrypt only), B<RSA_X931_PADDING> for X9.31 padding (signature operations
-only) and B<RSA_PKCS1_PSS_PADDING> (sign and verify only).
+only), B<RSA_PKCS1_PSS_PADDING> (sign and verify only) and
+B<RSA_PKCS1_WITH_TLS_PADDING> for TLS RSA ClientKeyExchange message padding
+(decryption only).
Two RSA padding modes behave differently if EVP_PKEY_CTX_set_signature_md()
-is used. If this macro is called for PKCS#1 padding the plaintext buffer is
+is used. If this function is called for PKCS#1 padding the plaintext buffer is
an actual digest value and is encapsulated in a DigestInfo structure according
to PKCS#1 when signing and this structure is expected (and stripped off) when
verifying. If this control is not used with RSA and PKCS#1 padding then the
@@ -203,173 +266,309 @@ padding for RSA the algorithm identifier byte is added or checked and removed
if this control is called. If it is not called then the first byte of the plaintext
buffer is expected to be the algorithm identifier byte.
-The EVP_PKEY_CTX_get_rsa_padding() macro gets the RSA padding mode for B<ctx>.
+EVP_PKEY_CTX_get_rsa_padding() gets the RSA padding mode for I<ctx>.
-The EVP_PKEY_CTX_set_rsa_pss_saltlen() macro sets the RSA PSS salt length to
-B<len>. As its name implies it is only supported for PSS padding. Three special
-values are supported: B<RSA_PSS_SALTLEN_DIGEST> sets the salt length to the
-digest length, B<RSA_PSS_SALTLEN_MAX> sets the salt length to the maximum
-permissible value. When verifying B<RSA_PSS_SALTLEN_AUTO> causes the salt length
-to be automatically determined based on the B<PSS> block structure. If this
-macro is not called maximum salt length is used when signing and auto detection
-when verifying is used by default.
+EVP_PKEY_CTX_set_rsa_pss_saltlen() sets the RSA PSS salt length to I<saltlen>.
+As its name implies it is only supported for PSS padding. If this function is
+not called then the maximum salt length is used when signing and auto detection
+when verifying. Three special values are supported:
-The EVP_PKEY_CTX_get_rsa_pss_saltlen() macro gets the RSA PSS salt length
-for B<ctx>. The padding mode must have been set to B<RSA_PKCS1_PSS_PADDING>.
+=over 4
-The EVP_PKEY_CTX_set_rsa_keygen_bits() macro sets the RSA key length for
-RSA key generation to B<bits>. If not specified 1024 bits is used.
+=item B<RSA_PSS_SALTLEN_DIGEST>
-The EVP_PKEY_CTX_set_rsa_keygen_pubexp() macro sets the public exponent value
-for RSA key generation to B<pubexp>. Currently it should be an odd integer. The
-B<pubexp> pointer is used internally by this function so it should not be
-modified or freed after the call. If not specified 65537 is used.
+sets the salt length to the digest length.
-The EVP_PKEY_CTX_set_rsa_keygen_primes() macro sets the number of primes for
-RSA key generation to B<primes>. If not specified 2 is used.
+=item B<RSA_PSS_SALTLEN_MAX>
-The EVP_PKEY_CTX_set_rsa_mgf1_md() macro sets the MGF1 digest for RSA padding
-schemes to B<md>. If not explicitly set the signing digest is used. The
-padding mode must have been set to B<RSA_PKCS1_OAEP_PADDING>
-or B<RSA_PKCS1_PSS_PADDING>.
+sets the salt length to the maximum permissible value.
-The EVP_PKEY_CTX_get_rsa_mgf1_md() macro gets the MGF1 digest for B<ctx>.
-If not explicitly set the signing digest is used. The padding mode must have
-been set to B<RSA_PKCS1_OAEP_PADDING> or B<RSA_PKCS1_PSS_PADDING>.
+=item B<RSA_PSS_SALTLEN_AUTO>
-The EVP_PKEY_CTX_set_rsa_oaep_md() macro sets the message digest type used
-in RSA OAEP to B<md>. The padding mode must have been set to
-B<RSA_PKCS1_OAEP_PADDING>.
+causes the salt length to be automatically determined based on the
+B<PSS> block structure when verifying. When signing, it has the same
+meaning as B<RSA_PSS_SALTLEN_MAX>.
+
+=back
+
+EVP_PKEY_CTX_get_rsa_pss_saltlen() gets the RSA PSS salt length for I<ctx>.
+The padding mode must already have been set to B<RSA_PKCS1_PSS_PADDING>.
+
+EVP_PKEY_CTX_set_rsa_keygen_bits() sets the RSA key length for
+RSA key generation to I<bits>. If not specified 2048 bits is used.
+
+EVP_PKEY_CTX_set1_rsa_keygen_pubexp() sets the public exponent value for RSA key
+generation to the value stored in I<pubexp>. Currently it should be an odd
+integer. In accordance with the OpenSSL naming convention, the I<pubexp> pointer
+must be freed independently of the EVP_PKEY_CTX (ie, it is internally copied).
+If not specified 65537 is used.
-The EVP_PKEY_CTX_get_rsa_oaep_md() macro gets the message digest type used
-in RSA OAEP to B<md>. The padding mode must have been set to
+EVP_PKEY_CTX_set_rsa_keygen_pubexp() does the same as
+EVP_PKEY_CTX_set1_rsa_keygen_pubexp() except that there is no internal copy and
+therefore I<pubexp> should not be modified or freed after the call.
+
+EVP_PKEY_CTX_set_rsa_keygen_primes() sets the number of primes for
+RSA key generation to I<primes>. If not specified 2 is used.
+
+EVP_PKEY_CTX_set_rsa_mgf1_md_name() sets the MGF1 digest for RSA
+padding schemes to the digest named I<mdname>. If the RSA algorithm
+implementation for the selected provider supports it then the digest will be
+fetched using the properties I<mdprops>. If not explicitly set the signing
+digest is used. The padding mode must have been set to B<RSA_PKCS1_OAEP_PADDING>
+or B<RSA_PKCS1_PSS_PADDING>.
+
+EVP_PKEY_CTX_set_rsa_mgf1_md() does the same as
+EVP_PKEY_CTX_set_rsa_mgf1_md_name() except that the name of the digest is
+inferred from the supplied I<md> and it is not possible to specify any
+properties.
+
+EVP_PKEY_CTX_get_rsa_mgf1_md_name() gets the name of the MGF1
+digest algorithm for I<ctx>. If not explicitly set the signing digest is used.
+The padding mode must have been set to B<RSA_PKCS1_OAEP_PADDING> or
+B<RSA_PKCS1_PSS_PADDING>.
+
+EVP_PKEY_CTX_get_rsa_mgf1_md() does the same as
+EVP_PKEY_CTX_get_rsa_mgf1_md_name() except that it returns a pointer to an
+EVP_MD object instead. Note that only known, built-in EVP_MD objects will be
+returned. The EVP_MD object may be NULL if the digest is not one of these (such
+as a digest only implemented in a third party provider).
+
+EVP_PKEY_CTX_set_rsa_oaep_md_name() sets the message digest type
+used in RSA OAEP to the digest named I<mdname>. If the RSA algorithm
+implementation for the selected provider supports it then the digest will be
+fetched using the properties I<mdprops>. The padding mode must have been set to
B<RSA_PKCS1_OAEP_PADDING>.
-The EVP_PKEY_CTX_set0_rsa_oaep_label() macro sets the RSA OAEP label to
-B<label> and its length to B<len>. If B<label> is NULL or B<len> is 0,
+EVP_PKEY_CTX_set_rsa_oaep_md() does the same as
+EVP_PKEY_CTX_set_rsa_oaep_md_name() except that the name of the digest is
+inferred from the supplied I<md> and it is not possible to specify any
+properties.
+
+EVP_PKEY_CTX_get_rsa_oaep_md_name() gets the message digest
+algorithm name used in RSA OAEP and stores it in the buffer I<name> which is of
+size I<namelen>. The padding mode must have been set to
+B<RSA_PKCS1_OAEP_PADDING>. The buffer should be sufficiently large for any
+expected digest algorithm names or the function will fail.
+
+EVP_PKEY_CTX_get_rsa_oaep_md() does the same as
+EVP_PKEY_CTX_get_rsa_oaep_md_name() except that it returns a pointer to an
+EVP_MD object instead. Note that only known, built-in EVP_MD objects will be
+returned. The EVP_MD object may be NULL if the digest is not one of these (such
+as a digest only implemented in a third party provider).
+
+EVP_PKEY_CTX_set0_rsa_oaep_label() sets the RSA OAEP label to binary data
+I<label> and its length in bytes to I<len>. If I<label> is NULL or I<len> is 0,
the label is cleared. The library takes ownership of the label so the
-caller should not free the original memory pointed to by B<label>.
+caller should not free the original memory pointed to by I<label>.
The padding mode must have been set to B<RSA_PKCS1_OAEP_PADDING>.
-The EVP_PKEY_CTX_get0_rsa_oaep_label() macro gets the RSA OAEP label to
-B<label>. The return value is the label length. The padding mode
+EVP_PKEY_CTX_get0_rsa_oaep_label() gets the RSA OAEP label to
+I<label>. The return value is the label length. The padding mode
must have been set to B<RSA_PKCS1_OAEP_PADDING>. The resulting pointer is owned
by the library and should not be freed by the caller.
+B<RSA_PKCS1_WITH_TLS_PADDING> is used when decrypting an RSA encrypted TLS
+pre-master secret in a TLS ClientKeyExchange message. It is the same as
+RSA_PKCS1_PADDING except that it additionally verifies that the result is the
+correct length and the first two bytes are the protocol version initially
+requested by the client. If the encrypted content is publicly invalid then the
+decryption will fail. However, if the padding checks fail then decryption will
+still appear to succeed but a random TLS premaster secret will be returned
+instead. This padding mode accepts two parameters which can be set using the
+L<EVP_PKEY_CTX_set_params(3)> function. These are
+OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION and
+OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, both of which are expected to be
+unsigned integers. Normally only the first of these will be set and represents
+the TLS protocol version that was first requested by the client (e.g. 0x0303 for
+TLSv1.2, 0x0302 for TLSv1.1 etc). Historically some buggy clients would use the
+negotiated protocol version instead of the protocol version first requested. If
+this behaviour should be tolerated then
+OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION should be set to the actual
+negotiated protocol version. Otherwise it should be left unset.
+
=head2 DSA parameters
-The EVP_PKEY_CTX_set_dsa_paramgen_bits() macro sets the number of bits used
-for DSA parameter generation to B<nbits>. If not specified, 1024 is used.
+EVP_PKEY_CTX_set_dsa_paramgen_bits() sets the number of bits used for DSA
+parameter generation to B<nbits>. If not specified, 2048 is used.
+
+EVP_PKEY_CTX_set_dsa_paramgen_q_bits() sets the number of bits in the subprime
+parameter I<q> for DSA parameter generation to I<qbits>. If not specified, 224
+is used. If a digest function is specified below, this parameter is ignored and
+instead, the number of bits in I<q> matches the size of the digest.
+
+EVP_PKEY_CTX_set_dsa_paramgen_md() sets the digest function used for DSA
+parameter generation to I<md>. If not specified, one of SHA-1, SHA-224, or
+SHA-256 is selected to match the bit length of I<q> above.
+
+EVP_PKEY_CTX_set_dsa_paramgen_md_props() sets the digest function used for DSA
+parameter generation using I<md_name> and I<md_properties> to retrieve the
+digest from a provider.
+If not specified, I<md_name> will be set to one of SHA-1, SHA-224, or
+SHA-256 depending on the bit length of I<q> above. I<md_properties> is a
+property query string that has a default value of '' if not specified.
+
+EVP_PKEY_CTX_set_dsa_paramgen_gindex() sets the I<gindex> used by the generator
+G. The default value is -1 which uses unverifiable g, otherwise a positive value
+uses verifiable g. This value must be saved if key validation of g is required,
+since it is not part of a persisted key.
+
+EVP_PKEY_CTX_set_dsa_paramgen_seed() sets the I<seed> to use for generation
+rather than using a randomly generated value for the seed. This is useful for
+testing purposes only and can fail if the seed does not produce primes for both
+p & q on its first iteration. This value must be saved if key validation of
+p, q, and verifiable g are required, since it is not part of a persisted key.
+
+EVP_PKEY_CTX_set_dsa_paramgen_type() sets the generation type to use FIPS186-4
+generation if I<name> is "fips186_4", or FIPS186-2 generation if I<name> is
+"fips186_2". The default value for the default provider is "fips186_2". The
+default value for the FIPS provider is "fips186_4".
-The EVP_PKEY_CTX_set_dsa_paramgen_q_bits() macro sets the number of bits in the
-subprime parameter B<q> for DSA parameter generation to B<qbits>. If not
-specified, 160 is used. If a digest function is specified below, this parameter
-is ignored and instead, the number of bits in B<q> matches the size of the
-digest.
+=head2 DH parameters
-The EVP_PKEY_CTX_set_dsa_paramgen_md() macro sets the digest function used for
-DSA parameter generation to B<md>. If not specified, one of SHA-1, SHA-224, or
-SHA-256 is selected to match the bit length of B<q> above.
+EVP_PKEY_CTX_set_dh_paramgen_prime_len() sets the length of the DH prime
+parameter I<p> for DH parameter generation. If this function is not called then
+2048 is used. Only accepts lengths greater than or equal to 256.
-=head2 DH parameters
+EVP_PKEY_CTX_set_dh_paramgen_subprime_len() sets the length of the DH
+optional subprime parameter I<q> for DH parameter generation. The default is
+256 if the prime is at least 2048 bits long or 160 otherwise. The DH paramgen
+type must have been set to "fips186_4".
+
+EVP_PKEY_CTX_set_dh_paramgen_generator() sets DH generator to I<gen> for DH
+parameter generation. If not specified 2 is used.
+
+EVP_PKEY_CTX_set_dh_paramgen_type() sets the key type for DH parameter
+generation. The supported parameters are:
+
+=over 4
+
+=item B<DH_PARAMGEN_TYPE_GROUP>
+
+Use a named group. If only the safe prime parameter I<p> is set this can be
+used to select a ffdhe safe prime group of the correct size.
+
+=item B<DH_PARAMGEN_TYPE_FIPS_186_4>
-The EVP_PKEY_CTX_set_dh_paramgen_prime_len() macro sets the length of the DH
-prime parameter B<p> for DH parameter generation. If this macro is not called
-then 1024 is used. Only accepts lengths greater than or equal to 256.
+FIPS186-4 FFC parameter generator.
-The EVP_PKEY_CTX_set_dh_paramgen_subprime_len() macro sets the length of the DH
-optional subprime parameter B<q> for DH parameter generation. The default is
-256 if the prime is at least 2048 bits long or 160 otherwise. The DH
-paramgen type must have been set to x9.42.
+=item B<DH_PARAMGEN_TYPE_FIPS_186_2>
-The EVP_PKEY_CTX_set_dh_paramgen_generator() macro sets DH generator to B<gen>
-for DH parameter generation. If not specified 2 is used.
+FIPS186-2 FFC parameter generator (X9.42 DH).
-The EVP_PKEY_CTX_set_dh_paramgen_type() macro sets the key type for DH
-parameter generation. Use 0 for PKCS#3 DH and 1 for X9.42 DH.
-The default is 0.
+=item B<DH_PARAMGEN_TYPE_GENERATOR>
-The EVP_PKEY_CTX_set_dh_pad() macro sets the DH padding mode. If B<pad> is
-1 the shared secret is padded with zeros up to the size of the DH prime B<p>.
-If B<pad> is zero (the default) then no padding is performed.
+Uses a safe prime generator g (PKCS#3 format).
+
+=back
+
+The default in the default provider is B<DH_PARAMGEN_TYPE_GENERATOR> for the
+"DH" keytype, and B<DH_PARAMGEN_TYPE_FIPS_186_2> for the "DHX" keytype. In the
+FIPS provider the default value is B<DH_PARAMGEN_TYPE_GROUP> for the "DH"
+keytype and <B<DH_PARAMGEN_TYPE_FIPS_186_4> for the "DHX" keytype.
+
+EVP_PKEY_CTX_set_dh_paramgen_gindex() sets the I<gindex> used by the generator G.
+The default value is -1 which uses unverifiable g, otherwise a positive value
+uses verifiable g. This value must be saved if key validation of g is required,
+since it is not part of a persisted key.
+
+EVP_PKEY_CTX_set_dh_paramgen_seed() sets the I<seed> to use for generation
+rather than using a randomly generated value for the seed. This is useful for
+testing purposes only and can fail if the seed does not produce primes for both
+p & q on its first iteration. This value must be saved if key validation of p, q,
+and verifiable g are required, since it is not part of a persisted key.
+
+EVP_PKEY_CTX_set_dh_pad() sets the DH padding mode.
+If I<pad> is 1 the shared secret is padded with zeros up to the size of the DH
+prime I<p>.
+If I<pad> is zero (the default) then no padding is performed.
EVP_PKEY_CTX_set_dh_nid() sets the DH parameters to values corresponding to
-B<nid> as defined in RFC7919. The B<nid> parameter must be B<NID_ffdhe2048>,
-B<NID_ffdhe3072>, B<NID_ffdhe4096>, B<NID_ffdhe6144>, B<NID_ffdhe8192>
-or B<NID_undef> to clear the stored value. This macro can be called during
-parameter or key generation.
+I<nid> as defined in RFC7919 or RFC3526. The I<nid> parameter must be
+B<NID_ffdhe2048>, B<NID_ffdhe3072>, B<NID_ffdhe4096>, B<NID_ffdhe6144>,
+B<NID_ffdhe8192>, B<NID_modp_1536>, B<NID_modp_2048>, B<NID_modp_3072>,
+B<NID_modp_4096>, B<NID_modp_6144>, B<NID_modp_8192> or B<NID_undef> to clear
+the stored value. This function can be called during parameter or key generation.
The nid parameter and the rfc5114 parameter are mutually exclusive.
-The EVP_PKEY_CTX_set_dh_rfc5114() and EVP_PKEY_CTX_set_dhx_rfc5114() macros are
-synonymous. They set the DH parameters to the values defined in RFC5114. The
-B<rfc5114> parameter must be 1, 2 or 3 corresponding to RFC5114 sections
-2.1, 2.2 and 2.3. or 0 to clear the stored value. This macro can be called
-during parameter generation. The B<ctx> must have a key type of
-B<EVP_PKEY_DHX>.
+EVP_PKEY_CTX_set_dh_rfc5114() and EVP_PKEY_CTX_set_dhx_rfc5114() both set the
+DH parameters to the values defined in RFC5114. The I<rfc5114> parameter must
+be 1, 2 or 3 corresponding to RFC5114 sections 2.1, 2.2 and 2.3. or 0 to clear
+the stored value. This macro can be called during parameter generation. The
+I<ctx> must have a key type of B<EVP_PKEY_DHX>.
The rfc5114 parameter and the nid parameter are mutually exclusive.
=head2 DH key derivation function parameters
-Note that all of the following functions require that the B<ctx> parameter has
+Note that all of the following functions require that the I<ctx> parameter has
a private key type of B<EVP_PKEY_DHX>. When using key derivation, the output of
EVP_PKEY_derive() is the output of the KDF instead of the DH shared secret.
The KDF output is typically used as a Key Encryption Key (KEK) that in turn
encrypts a Content Encryption Key (CEK).
-The EVP_PKEY_CTX_set_dh_kdf_type() macro sets the key derivation function type
-to B<kdf> for DH key derivation. Possible values are B<EVP_PKEY_DH_KDF_NONE>
-and B<EVP_PKEY_DH_KDF_X9_42> which uses the key derivation specified in RFC2631
+EVP_PKEY_CTX_set_dh_kdf_type() sets the key derivation function type to I<kdf>
+for DH key derivation. Possible values are B<EVP_PKEY_DH_KDF_NONE> and
+B<EVP_PKEY_DH_KDF_X9_42> which uses the key derivation specified in RFC2631
(based on the keying algorithm described in X9.42). When using key derivation,
-the B<kdf_oid>, B<kdf_md> and B<kdf_outlen> parameters must also be specified.
+the I<kdf_oid>, I<kdf_md> and I<kdf_outlen> parameters must also be specified.
-The EVP_PKEY_CTX_get_dh_kdf_type() macro gets the key derivation function type
-for B<ctx> used for DH key derivation. Possible values are B<EVP_PKEY_DH_KDF_NONE>
-and B<EVP_PKEY_DH_KDF_X9_42>.
+EVP_PKEY_CTX_get_dh_kdf_type() gets the key derivation function type for I<ctx>
+used for DH key derivation. Possible values are B<EVP_PKEY_DH_KDF_NONE> and
+B<EVP_PKEY_DH_KDF_X9_42>.
-The EVP_PKEY_CTX_set0_dh_kdf_oid() macro sets the key derivation function
-object identifier to B<oid> for DH key derivation. This OID should identify
-the algorithm to be used with the Content Encryption Key.
+EVP_PKEY_CTX_set0_dh_kdf_oid() sets the key derivation function object
+identifier to I<oid> for DH key derivation. This OID should identify the
+algorithm to be used with the Content Encryption Key.
The library takes ownership of the object identifier so the caller should not
-free the original memory pointed to by B<oid>.
+free the original memory pointed to by I<oid>.
-The EVP_PKEY_CTX_get0_dh_kdf_oid() macro gets the key derivation function oid
-for B<ctx> used for DH key derivation. The resulting pointer is owned by the
-library and should not be freed by the caller.
+EVP_PKEY_CTX_get0_dh_kdf_oid() gets the key derivation function oid for I<ctx>
+used for DH key derivation. The resulting pointer is owned by the library and
+should not be freed by the caller.
-The EVP_PKEY_CTX_set_dh_kdf_md() macro sets the key derivation function
-message digest to B<md> for DH key derivation. Note that RFC2631 specifies
-that this digest should be SHA1 but OpenSSL tolerates other digests.
+EVP_PKEY_CTX_set_dh_kdf_md() sets the key derivation function message digest to
+I<md> for DH key derivation. Note that RFC2631 specifies that this digest should
+be SHA1 but OpenSSL tolerates other digests.
-The EVP_PKEY_CTX_get_dh_kdf_md() macro gets the key derivation function
-message digest for B<ctx> used for DH key derivation.
+EVP_PKEY_CTX_get_dh_kdf_md() gets the key derivation function message digest for
+I<ctx> used for DH key derivation.
-The EVP_PKEY_CTX_set_dh_kdf_outlen() macro sets the key derivation function
-output length to B<len> for DH key derivation.
+EVP_PKEY_CTX_set_dh_kdf_outlen() sets the key derivation function output length
+to I<len> for DH key derivation.
-The EVP_PKEY_CTX_get_dh_kdf_outlen() macro gets the key derivation function
-output length for B<ctx> used for DH key derivation.
+EVP_PKEY_CTX_get_dh_kdf_outlen() gets the key derivation function output length
+for I<ctx> used for DH key derivation.
-The EVP_PKEY_CTX_set0_dh_kdf_ukm() macro sets the user key material to
-B<ukm> and its length to B<len> for DH key derivation. This parameter is optional
-and corresponds to the partyAInfo field in RFC2631 terms. The specification
+EVP_PKEY_CTX_set0_dh_kdf_ukm() sets the user key material to I<ukm> and its
+length to I<len> for DH key derivation. This parameter is optional and
+corresponds to the partyAInfo field in RFC2631 terms. The specification
requires that it is 512 bits long but this is not enforced by OpenSSL.
The library takes ownership of the user key material so the caller should not
-free the original memory pointed to by B<ukm>.
+free the original memory pointed to by I<ukm>.
-The EVP_PKEY_CTX_get0_dh_kdf_ukm() macro gets the user key material for B<ctx>.
+EVP_PKEY_CTX_get0_dh_kdf_ukm() gets the user key material for I<ctx>.
The return value is the user key material length. The resulting pointer is owned
by the library and should not be freed by the caller.
=head2 EC parameters
-The EVP_PKEY_CTX_set_ec_paramgen_curve_nid() sets the EC curve for EC parameter
-generation to B<nid>. For EC parameter generation this macro must be called
-or an error occurs because there is no default curve.
-This function can also be called to set the curve explicitly when
+Use EVP_PKEY_CTX_set_group_name() (described above) to set the curve name to
+I<name> for parameter and key generation.
+
+EVP_PKEY_CTX_set_ec_paramgen_curve_nid() does the same as
+EVP_PKEY_CTX_set_group_name(), but is specific to EC and uses a I<nid> rather
+than a name string.
+
+For EC parameter generation, one of EVP_PKEY_CTX_set_group_name()
+or EVP_PKEY_CTX_set_ec_paramgen_curve_nid() must be called or an error occurs
+because there is no default curve.
+These function can also be called to set the curve explicitly when
generating an EC key.
-The EVP_PKEY_CTX_set_ec_param_enc() macro sets the EC parameter encoding to
-B<param_enc> when generating EC parameters or an EC key. The encoding can be
+EVP_PKEY_CTX_get_group_name() (described above) can be used to obtain the curve
+name that's currently set with I<ctx>.
+
+EVP_PKEY_CTX_set_ec_param_enc() sets the EC parameter encoding to I<param_enc>
+when generating EC parameters or an EC key. The encoding can be
B<OPENSSL_EC_EXPLICIT_CURVE> for explicit parameters (the default in versions
of OpenSSL before 1.1.0) or B<OPENSSL_EC_NAMED_CURVE> to use named curve form.
For maximum compatibility the named curve form should be used. Note: the
@@ -378,70 +577,77 @@ versions should use 0 instead.
=head2 ECDH parameters
-The EVP_PKEY_CTX_set_ecdh_cofactor_mode() macro sets the cofactor mode to
-B<cofactor_mode> for ECDH key derivation. Possible values are 1 to enable
-cofactor key derivation, 0 to disable it and -1 to clear the stored cofactor
-mode and fallback to the private key cofactor mode.
+EVP_PKEY_CTX_set_ecdh_cofactor_mode() sets the cofactor mode to I<cofactor_mode>
+for ECDH key derivation. Possible values are 1 to enable cofactor
+key derivation, 0 to disable it and -1 to clear the stored cofactor mode and
+fallback to the private key cofactor mode.
-The EVP_PKEY_CTX_get_ecdh_cofactor_mode() macro returns the cofactor mode for
-B<ctx> used for ECDH key derivation. Possible values are 1 when cofactor key
-derivation is enabled and 0 otherwise.
+EVP_PKEY_CTX_get_ecdh_cofactor_mode() returns the cofactor mode for I<ctx> used
+for ECDH key derivation. Possible values are 1 when cofactor key derivation is
+enabled and 0 otherwise.
=head2 ECDH key derivation function parameters
-The EVP_PKEY_CTX_set_ecdh_kdf_type() macro sets the key derivation function type
-to B<kdf> for ECDH key derivation. Possible values are B<EVP_PKEY_ECDH_KDF_NONE>
+EVP_PKEY_CTX_set_ecdh_kdf_type() sets the key derivation function type to
+I<kdf> for ECDH key derivation. Possible values are B<EVP_PKEY_ECDH_KDF_NONE>
and B<EVP_PKEY_ECDH_KDF_X9_63> which uses the key derivation specified in X9.63.
-When using key derivation, the B<kdf_md> and B<kdf_outlen> parameters must
+When using key derivation, the I<kdf_md> and I<kdf_outlen> parameters must
also be specified.
-The EVP_PKEY_CTX_get_ecdh_kdf_type() macro returns the key derivation function
-type for B<ctx> used for ECDH key derivation. Possible values are
+EVP_PKEY_CTX_get_ecdh_kdf_type() returns the key derivation function type for
+I<ctx> used for ECDH key derivation. Possible values are
B<EVP_PKEY_ECDH_KDF_NONE> and B<EVP_PKEY_ECDH_KDF_X9_63>.
-The EVP_PKEY_CTX_set_ecdh_kdf_md() macro sets the key derivation function
-message digest to B<md> for ECDH key derivation. Note that X9.63 specifies
-that this digest should be SHA1 but OpenSSL tolerates other digests.
+EVP_PKEY_CTX_set_ecdh_kdf_md() sets the key derivation function message digest
+to I<md> for ECDH key derivation. Note that X9.63 specifies that this digest
+should be SHA1 but OpenSSL tolerates other digests.
-The EVP_PKEY_CTX_get_ecdh_kdf_md() macro gets the key derivation function
-message digest for B<ctx> used for ECDH key derivation.
+EVP_PKEY_CTX_get_ecdh_kdf_md() gets the key derivation function message digest
+for I<ctx> used for ECDH key derivation.
-The EVP_PKEY_CTX_set_ecdh_kdf_outlen() macro sets the key derivation function
-output length to B<len> for ECDH key derivation.
+EVP_PKEY_CTX_set_ecdh_kdf_outlen() sets the key derivation function output
+length to I<len> for ECDH key derivation.
-The EVP_PKEY_CTX_get_ecdh_kdf_outlen() macro gets the key derivation function
-output length for B<ctx> used for ECDH key derivation.
+EVP_PKEY_CTX_get_ecdh_kdf_outlen() gets the key derivation function output
+length for I<ctx> used for ECDH key derivation.
-The EVP_PKEY_CTX_set0_ecdh_kdf_ukm() macro sets the user key material to B<ukm>
-for ECDH key derivation. This parameter is optional and corresponds to the
-shared info in X9.63 terms. The library takes ownership of the user key material
-so the caller should not free the original memory pointed to by B<ukm>.
+EVP_PKEY_CTX_set0_ecdh_kdf_ukm() sets the user key material to I<ukm> for ECDH
+key derivation. This parameter is optional and corresponds to the shared info in
+X9.63 terms. The library takes ownership of the user key material so the caller
+should not free the original memory pointed to by I<ukm>.
-The EVP_PKEY_CTX_get0_ecdh_kdf_ukm() macro gets the user key material for B<ctx>.
+EVP_PKEY_CTX_get0_ecdh_kdf_ukm() gets the user key material for I<ctx>.
The return value is the user key material length. The resulting pointer is owned
by the library and should not be freed by the caller.
=head2 Other parameters
-The EVP_PKEY_CTX_set1_id(), EVP_PKEY_CTX_get1_id() and EVP_PKEY_CTX_get1_id_len()
-macros are used to manipulate the special identifier field for specific signature
-algorithms such as SM2. The EVP_PKEY_CTX_set1_id() sets an ID pointed by B<id> with
-the length B<id_len> to the library. The library takes a copy of the id so that
-the caller can safely free the original memory pointed to by B<id>. The
-EVP_PKEY_CTX_get1_id_len() macro returns the length of the ID set via a previous
-call to EVP_PKEY_CTX_set1_id(). The length is usually used to allocate adequate
-memory for further calls to EVP_PKEY_CTX_get1_id(). The EVP_PKEY_CTX_get1_id()
-macro returns the previously set ID value to caller in B<id>. The caller should
-allocate adequate memory space for the B<id> before calling EVP_PKEY_CTX_get1_id().
+EVP_PKEY_CTX_set1_id(), EVP_PKEY_CTX_get1_id() and EVP_PKEY_CTX_get1_id_len()
+are used to manipulate the special identifier field for specific signature
+algorithms such as SM2. The EVP_PKEY_CTX_set1_id() sets an ID pointed by I<id> with
+the length I<id_len> to the library. The library takes a copy of the id so that
+the caller can safely free the original memory pointed to by I<id>.
+EVP_PKEY_CTX_get1_id_len() returns the length of the ID set via a previous call
+to EVP_PKEY_CTX_set1_id(). The length is usually used to allocate adequate
+memory for further calls to EVP_PKEY_CTX_get1_id(). EVP_PKEY_CTX_get1_id()
+returns the previously set ID value to caller in I<id>. The caller should
+allocate adequate memory space for the I<id> before calling EVP_PKEY_CTX_get1_id().
+
+EVP_PKEY_CTX_set_kem_op() sets the KEM operation to run. This can be set after
+EVP_PKEY_encapsulate_init() or EVP_PKEY_decapsulate_init() to select the
+kem operation. RSA is the only key type that supports encapsulation currently,
+and as there is no default operation for the RSA type, this function must be
+called before EVP_PKEY_encapsulate() or EVP_PKEY_decapsulate().
=head1 RETURN VALUES
-EVP_PKEY_CTX_ctrl() and its macros return a positive value for success and 0
-or a negative value for failure. In particular a return value of -2
+All other functions described on this page return a positive value for success
+and 0 or a negative value for failure. In particular a return value of -2
indicates the operation is not supported by the public key algorithm.
=head1 SEE ALSO
+L<EVP_PKEY_CTX_set_params(3)>,
L<EVP_PKEY_CTX_new(3)>,
L<EVP_PKEY_encrypt(3)>,
L<EVP_PKEY_decrypt(3)>,
@@ -450,18 +656,33 @@ L<EVP_PKEY_verify(3)>,
L<EVP_PKEY_verify_recover(3)>,
L<EVP_PKEY_derive(3)>,
L<EVP_PKEY_keygen(3)>
+L<EVP_PKEY_encapsulate(3)>
+L<EVP_PKEY_decapsulate(3)>
=head1 HISTORY
-The
-EVP_PKEY_CTX_set1_id(), EVP_PKEY_CTX_get1_id() and EVP_PKEY_CTX_get1_id_len()
-macros were added in 1.1.1, other functions were added in OpenSSL 1.0.0.
+EVP_PKEY_CTX_get_rsa_oaep_md_name(), EVP_PKEY_CTX_get_rsa_mgf1_md_name(),
+EVP_PKEY_CTX_set_rsa_mgf1_md_name(), EVP_PKEY_CTX_set_rsa_oaep_md_name(),
+EVP_PKEY_CTX_set_dsa_paramgen_md_props(), EVP_PKEY_CTX_set_dsa_paramgen_gindex(),
+EVP_PKEY_CTX_set_dsa_paramgen_type(), EVP_PKEY_CTX_set_dsa_paramgen_seed(),
+EVP_PKEY_CTX_set_group_name() and EVP_PKEY_CTX_get_group_name()
+were added in OpenSSL 3.0.
+
+The EVP_PKEY_CTX_set1_id(), EVP_PKEY_CTX_get1_id() and
+EVP_PKEY_CTX_get1_id_len() macros were added in 1.1.1, other functions were
+added in OpenSSL 1.0.0.
+
+In OpenSSL 1.1.1 and below the functions were mostly macros.
+From OpenSSL 3.0 they are all functions.
+
+EVP_PKEY_CTX_set_rsa_keygen_pubexp(), EVP_PKEY_CTX_get0_dh_kdf_ukm(),
+and EVP_PKEY_CTX_get0_ecdh_kdf_ukm() were deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_CTX_get0_libctx.pod b/doc/man3/EVP_PKEY_CTX_get0_libctx.pod
new file mode 100644
index 000000000000..81332b8c704f
--- /dev/null
+++ b/doc/man3/EVP_PKEY_CTX_get0_libctx.pod
@@ -0,0 +1,54 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_CTX_get0_libctx,
+EVP_PKEY_CTX_get0_propq,
+EVP_PKEY_CTX_get0_provider
+- functions for getting diverse information from an EVP_PKEY_CTX
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ OSSL_LIB_CTX *EVP_PKEY_CTX_get0_libctx(EVP_PKEY_CTX *ctx);
+ const char *EVP_PKEY_CTX_get0_propq(const EVP_PKEY_CTX *ctx);
+ const OSSL_PROVIDER *EVP_PKEY_CTX_get0_provider(const EVP_PKEY_CTX *ctx);
+
+=head1 DESCRIPTION
+
+EVP_PKEY_CTX_get0_libctx() and EVP_PKEY_CTX_get0_propq() obtain the
+OSSL_LIB_CTX and property query string values respectively that were
+associated with the EVP_PKEY_CTX when it was constructed.
+
+EVP_PKEY_CTX_get0_provider() returns the provider associated with the
+ongoing B<EVP_PKEY_CTX> operation. If the operation is performed by
+en B<ENGINE>, this function returns NULL.
+
+=head1 RETURN VALUES
+
+EVP_PKEY_CTX_get0_libctx() and EVP_PKEY_CTX_get0_propq() functions return the
+OSSL_LIB_CTX and property query string associated with the EVP_PKEY_CTX or NULL
+if they are not set. The returned values should not be freed by the caller.
+
+EVP_PKEY_CTX_get0_provider() returns a provider if an operation performed by
+a provider is ongoing, otherwise NULL.
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_new(3)>
+
+=head1 HISTORY
+
+All functions were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_PKEY_CTX_get0_pkey.pod b/doc/man3/EVP_PKEY_CTX_get0_pkey.pod
new file mode 100644
index 000000000000..8db726127ec6
--- /dev/null
+++ b/doc/man3/EVP_PKEY_CTX_get0_pkey.pod
@@ -0,0 +1,56 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_CTX_get0_pkey,
+EVP_PKEY_CTX_get0_peerkey
+- functions for accessing the EVP_PKEY associated with an EVP_PKEY_CTX
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx);
+ EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx);
+
+=head1 DESCRIPTION
+
+EVP_PKEY_CTX_get0_pkey() is used to access the B<EVP_PKEY>
+associated with the given B<EVP_PKEY_CTX> I<ctx>.
+The B<EVP_PKEY> obtained is the one used for creating the B<EVP_PKEY_CTX>
+using either L<EVP_PKEY_CTX_new(3)> or L<EVP_PKEY_CTX_new_from_pkey(3)>.
+
+EVP_PKEY_CTX_get0_peerkey() is used to access the peer B<EVP_PKEY>
+associated with the given B<EVP_PKEY_CTX> I<ctx>.
+The peer B<EVP_PKEY> obtained is the one set using
+either L<EVP_PKEY_derive_set_peer(3)> or L<EVP_PKEY_derive_set_peer_ex(3)>.
+
+=head1 RETURN VALUES
+
+EVP_PKEY_CTX_get0_pkey() returns the B<EVP_PKEY> associated with the
+EVP_PKEY_CTX or NULL if it is not set.
+
+EVP_PKEY_CTX_get0_peerkey() returns the peer B<EVP_PKEY> associated with the
+EVP_PKEY_CTX or NULL if it is not set.
+
+The returned EVP_PKEY objects are owned by the EVP_PKEY_CTX,
+and therefore should not explicitly be freed by the caller.
+
+These functions do not affect the EVP_PKEY reference count.
+They merely act as getter functions, and should be treated as such.
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_new(3)>, L<EVP_PKEY_CTX_new_from_pkey(3)>,
+L<EVP_PKEY_derive_set_peer(3)>, L<EVP_PKEY_derive_set_peer_ex(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").
+You may not use this file except in compliance with the License.
+You can obtain a copy in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_PKEY_CTX_new.pod b/doc/man3/EVP_PKEY_CTX_new.pod
index 8c3c796f6fdd..d7ac221f7c19 100644
--- a/doc/man3/EVP_PKEY_CTX_new.pod
+++ b/doc/man3/EVP_PKEY_CTX_new.pod
@@ -2,7 +2,10 @@
=head1 NAME
-EVP_PKEY_CTX_new, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_dup, EVP_PKEY_CTX_free - public key algorithm context functions
+EVP_PKEY_CTX_new, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_new_from_name,
+EVP_PKEY_CTX_new_from_pkey, EVP_PKEY_CTX_dup, EVP_PKEY_CTX_free,
+EVP_PKEY_CTX_is_a
+- public key algorithm context functions
=head1 SYNOPSIS
@@ -10,51 +13,118 @@ EVP_PKEY_CTX_new, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_dup, EVP_PKEY_CTX_free - pub
EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e);
- EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx);
+ EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name(OSSL_LIB_CTX *libctx,
+ const char *name,
+ const char *propquery);
+ EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OSSL_LIB_CTX *libctx,
+ EVP_PKEY *pkey,
+ const char *propquery);
+ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *ctx);
void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_CTX_is_a(EVP_PKEY_CTX *ctx, const char *keytype);
=head1 DESCRIPTION
The EVP_PKEY_CTX_new() function allocates public key algorithm context using
-the algorithm specified in B<pkey> and ENGINE B<e>.
+the I<pkey> key type and ENGINE I<e>.
The EVP_PKEY_CTX_new_id() function allocates public key algorithm context
-using the algorithm specified by B<id> and ENGINE B<e>. It is normally used
-when no B<EVP_PKEY> structure is associated with the operations, for example
-during parameter generation of key generation for some algorithms.
+using the key type specified by I<id> and ENGINE I<e>.
-EVP_PKEY_CTX_dup() duplicates the context B<ctx>.
+The EVP_PKEY_CTX_new_from_name() function allocates a public key algorithm
+context using the library context I<libctx> (see L<OSSL_LIB_CTX(3)>), the
+key type specified by I<name> and the property query I<propquery>. None
+of the arguments are duplicated, so they must remain unchanged for the
+lifetime of the returned B<EVP_PKEY_CTX> or of any of its duplicates. Read
+further about the possible names in L</NOTES> below.
-EVP_PKEY_CTX_free() frees up the context B<ctx>.
-If B<ctx> is NULL, nothing is done.
+The EVP_PKEY_CTX_new_from_pkey() function allocates a public key algorithm
+context using the library context I<libctx> (see L<OSSL_LIB_CTX(3)>) and the
+algorithm specified by I<pkey> and the property query I<propquery>. None of the
+arguments are duplicated, so they must remain unchanged for the lifetime of the
+returned B<EVP_PKEY_CTX> or any of its duplicates.
+
+EVP_PKEY_CTX_new_id() and EVP_PKEY_CTX_new_from_name() are normally
+used when no B<EVP_PKEY> structure is associated with the operations,
+for example during parameter generation or key generation for some
+algorithms.
+
+EVP_PKEY_CTX_dup() duplicates the context I<ctx>. It is not supported for a
+keygen operation.
+
+EVP_PKEY_CTX_free() frees up the context I<ctx>.
+If I<ctx> is NULL, nothing is done.
+
+EVP_PKEY_is_a() checks if the key type associated with I<ctx> is I<keytype>.
=head1 NOTES
+=head2 On B<EVP_PKEY_CTX>
+
The B<EVP_PKEY_CTX> structure is an opaque public key algorithm context used
by the OpenSSL high-level public key API. Contexts B<MUST NOT> be shared between
threads: that is it is not permissible to use the same context simultaneously
in two threads.
+=head2 On Key Types
+
+We mention "key type" in this manual, which is the same
+as "algorithm" in most cases, allowing either term to be used
+interchangeably. There are algorithms where the I<key type> and the
+I<algorithm> of the operations that use the keys are not the same,
+such as EC keys being used for ECDSA and ECDH operations.
+
+Key types are given in two different manners:
+
+=over 4
+
+=item Legacy NID or EVP_PKEY type
+
+This is the I<id> used with EVP_PKEY_CTX_new_id().
+
+These are B<EVP_PKEY_RSA>, B<EVP_PKEY_RSA_PSS>, B<EVP_PKEY_DSA>,
+B<EVP_PKEY_DH>, B<EVP_PKEY_EC>, B<EVP_PKEY_SM2>, B<EVP_PKEY_X25519>,
+B<EVP_PKEY_X448>, and are used by legacy methods.
+
+=item Name strings
+
+This is the I<name> used with EVP_PKEY_CTX_new_from_name().
+
+These are names like "RSA", "DSA", and what's available depends on what
+providers are currently accessible.
+
+The OpenSSL providers offer a set of key types available this way, please
+see L<OSSL_PROVIDER-FIPS(7)> and L<OSSL_PROVIDER-default(7)> and related
+documentation for more information.
+
+=back
+
=head1 RETURN VALUES
-EVP_PKEY_CTX_new(), EVP_PKEY_CTX_new_id(), EVP_PKEY_CTX_dup() returns either
-the newly allocated B<EVP_PKEY_CTX> structure of B<NULL> if an error occurred.
+EVP_PKEY_CTX_new(), EVP_PKEY_CTX_new_id() and EVP_PKEY_CTX_dup() return either
+the newly allocated B<EVP_PKEY_CTX> structure or B<NULL> if an error occurred.
EVP_PKEY_CTX_free() does not return a value.
+EVP_PKEY_CTX_is_a() returns 1 for true and 0 for false.
+
=head1 SEE ALSO
L<EVP_PKEY_new(3)>
=head1 HISTORY
-These functions were added in OpenSSL 1.0.0.
+The EVP_PKEY_CTX_new(), EVP_PKEY_CTX_new_id(), EVP_PKEY_CTX_dup() and
+EVP_PKEY_CTX_free() functions were added in OpenSSL 1.0.0.
+
+The EVP_PKEY_CTX_new_from_name() and EVP_PKEY_CTX_new_from_pkey() functions were
+added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_CTX_set1_pbe_pass.pod b/doc/man3/EVP_PKEY_CTX_set1_pbe_pass.pod
index 1e740f40d144..991b6a9d815d 100644
--- a/doc/man3/EVP_PKEY_CTX_set1_pbe_pass.pod
+++ b/doc/man3/EVP_PKEY_CTX_set1_pbe_pass.pod
@@ -42,10 +42,6 @@ supported by the algorithms that use them.
=end comment
-=head1 NOTES
-
-All these functions are implemented as macros.
-
=head1 RETURN VALUES
All these functions return 1 for success and 0 or a negative value for failure.
@@ -58,11 +54,16 @@ L<EVP_PKEY_CTX_new(3)>,
L<EVP_PKEY_CTX_ctrl_str(3)>,
L<EVP_PKEY_derive(3)>
+=head1 HISTORY
+
+EVP_PKEY_CTX_set1_pbe_pass() was converted from a macro to a function in
+OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod b/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod
index 974bbed9b9f2..66fe3dc8fa27 100644
--- a/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod
+++ b/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod
@@ -4,14 +4,14 @@
EVP_PKEY_CTX_set_hkdf_md, EVP_PKEY_CTX_set1_hkdf_salt,
EVP_PKEY_CTX_set1_hkdf_key, EVP_PKEY_CTX_add1_hkdf_info,
-EVP_PKEY_CTX_hkdf_mode -
+EVP_PKEY_CTX_set_hkdf_mode -
HMAC-based Extract-and-Expand key derivation algorithm
=head1 SYNOPSIS
#include <openssl/kdf.h>
- int EVP_PKEY_CTX_hkdf_mode(EVP_PKEY_CTX *pctx, int mode);
+ int EVP_PKEY_CTX_set_hkdf_mode(EVP_PKEY_CTX *pctx, int mode);
int EVP_PKEY_CTX_set_hkdf_md(EVP_PKEY_CTX *pctx, const EVP_MD *md);
@@ -33,8 +33,8 @@ and "extracts" from it a fixed-length pseudorandom key K. The second stage
"expands" the key K into several additional pseudorandom keys (the output
of the KDF).
-EVP_PKEY_CTX_hkdf_mode() sets the mode for the HKDF operation. There are three
-modes that are currently defined:
+EVP_PKEY_CTX_set_hkdf_mode() sets the mode for the HKDF operation. There
+are three modes that are currently defined:
=over 4
@@ -95,13 +95,11 @@ string which is converted to binary.
=head1 NOTES
-All these functions are implemented as macros.
-
A context for HKDF can be obtained by calling:
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
-The total length of the info buffer cannot exceed 1024 bytes in length: this
+The total length of the info buffer cannot exceed 2048 bytes in length: this
should be more than enough for any normal use of HKDF.
The output length of an HKDF expand operation is specified via the length
@@ -154,11 +152,16 @@ L<EVP_PKEY_CTX_new(3)>,
L<EVP_PKEY_CTX_ctrl_str(3)>,
L<EVP_PKEY_derive(3)>
+=head1 HISTORY
+
+All of the functions described here were converted from macros to functions in
+OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_CTX_set_params.pod b/doc/man3/EVP_PKEY_CTX_set_params.pod
new file mode 100644
index 000000000000..c02151654c3a
--- /dev/null
+++ b/doc/man3/EVP_PKEY_CTX_set_params.pod
@@ -0,0 +1,94 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_CTX_set_params,
+EVP_PKEY_CTX_settable_params,
+EVP_PKEY_CTX_get_params,
+EVP_PKEY_CTX_gettable_params
+- provider parameter passing operations
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, const OSSL_PARAM *params);
+ const OSSL_PARAM *EVP_PKEY_CTX_settable_params(const EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_CTX_get_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params);
+ const OSSL_PARAM *EVP_PKEY_CTX_gettable_params(const EVP_PKEY_CTX *ctx);
+
+=head1 DESCRIPTION
+
+The EVP_PKEY_CTX_get_params() and EVP_PKEY_CTX_set_params() functions allow
+transfer of arbitrary key parameters to and from providers.
+Not all parameters may be supported by all providers.
+See L<OSSL_PROVIDER(3)> for more information on providers.
+See L<OSSL_PARAM(3)> for more information on parameters.
+These functions must only be called after the EVP_PKEY_CTX has been initialised
+for use in an operation.
+These methods replace the EVP_PKEY_CTX_ctrl() mechanism. (EVP_PKEY_CTX_ctrl now
+calls these methods internally to interact with providers).
+
+EVP_PKEY_CTX_gettable_params() and EVP_PKEY_CTX_settable_params() get a
+constant L<OSSL_PARAM(3)> array that describes the gettable and
+settable parameters for the current algorithm implementation, i.e. parameters
+that can be used with EVP_PKEY_CTX_get_params() and EVP_PKEY_CTX_set_params()
+respectively.
+These functions must only be called after the EVP_PKEY_CTX has been initialised
+for use in an operation.
+
+=head2 Parameters
+
+Examples of EVP_PKEY parameters include the following:
+
+L<provider-keymgmt(7)/Common parameters>
+L<provider-keyexch(7)/Key Exchange parameters>
+L<provider-signature(7)/Signature parameters>
+
+L<EVP_PKEY-RSA(7)/Common RSA parameters>
+L<EVP_PKEY-RSA(7)/RSA key generation parameters>
+L<EVP_PKEY-FFC(7)/FFC parameters>
+L<EVP_PKEY-FFC(7)/FFC key generation parameters>
+L<EVP_PKEY-DSA(7)/DSA parameters>
+L<EVP_PKEY-DSA(7)/DSA key generation parameters>
+L<EVP_PKEY-DH(7)/DH parameters>
+L<EVP_PKEY-DH(7)/DH key generation parameters>
+L<EVP_PKEY-EC(7)/Common EC parameters>
+L<EVP_PKEY-X25519(7)/Common X25519, X448, ED25519 and ED448 parameters>
+
+=head1 RETURN VALUES
+
+EVP_PKEY_CTX_set_params() returns 1 for success or 0 otherwise.
+EVP_PKEY_CTX_settable_params() returns an OSSL_PARAM array on success or NULL on
+error.
+It may also return NULL if there are no settable parameters available.
+
+All other functions and macros described on this page return a positive value
+for success and 0 or a negative value for failure. In particular a return value
+of -2 indicates the operation is not supported by the public key algorithm.
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_new(3)>,
+L<EVP_PKEY_encrypt(3)>,
+L<EVP_PKEY_decrypt(3)>,
+L<EVP_PKEY_sign(3)>,
+L<EVP_PKEY_verify(3)>,
+L<EVP_PKEY_verify_recover(3)>,
+L<EVP_PKEY_derive(3)>,
+L<EVP_PKEY_keygen(3)>
+
+=head1 HISTORY
+
+All functions were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod b/doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod
index 7578278a6cfc..96610e4e720b 100644
--- a/doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod
+++ b/doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod
@@ -3,7 +3,9 @@
=head1 NAME
EVP_PKEY_CTX_set_rsa_pss_keygen_md,
+EVP_PKEY_CTX_set_rsa_pss_keygen_md_name,
EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md,
+EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md_name,
EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen
- EVP_PKEY RSA-PSS algorithm support functions
@@ -13,8 +15,13 @@ EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen
int EVP_PKEY_CTX_set_rsa_pss_keygen_md(EVP_PKEY_CTX *pctx,
const EVP_MD *md);
+ int EVP_PKEY_CTX_set_rsa_pss_keygen_md_name(EVP_PKEY_CTX *ctx,
+ const char *mdname,
+ const char *mdprops);
int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(EVP_PKEY_CTX *pctx,
const EVP_MD *md);
+ int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md_name(EVP_PKEY_CTX *pctx,
+ const char *mdname);
int EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(EVP_PKEY_CTX *pctx,
int saltlen);
@@ -35,10 +42,10 @@ to the B<RSA> operation except detection of the salt length (using
RSA_PSS_SALTLEN_AUTO) is not supported for verification if the key has
usage restrictions.
-The EVP_PKEY_CTX_set_signature_md() and EVP_PKEY_CTX_set_rsa_mgf1_md() macros
-are used to set the digest and MGF1 algorithms respectively. If the key has
-usage restrictions then an error is returned if an attempt is made to set the
-digest to anything other than the restricted value. Otherwise these are
+The L<EVP_PKEY_CTX_set_signature_md(3)> and L<EVP_PKEY_CTX_set_rsa_mgf1_md(3)>
+functions are used to set the digest and MGF1 algorithms respectively. If the
+key has usage restrictions then an error is returned if an attempt is made to
+set the digest to anything other than the restricted value. Otherwise these are
similar to the B<RSA> versions.
=head2 Key Generation
@@ -55,13 +62,17 @@ then they are reflected in the corresponding parameters of the public key
when (for example) a certificate request is signed.
EVP_PKEY_CTX_set_rsa_pss_keygen_md() restricts the digest algorithm the
-generated key can use to B<md>.
+generated key can use to I<md>.
+EVP_PKEY_CTX_set_rsa_pss_keygen_md_name() does the same thing, but
+passes the algorithm by name rather than by B<EVP_MD>.
EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md() restricts the MGF1 algorithm the
-generated key can use to B<md>.
+generated key can use to I<md>.
+EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md_name() does the same thing, but
+passes the algorithm by name rather than by B<EVP_MD>.
EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen() restricts the minimum salt length
-to B<saltlen>.
+to I<saltlen>.
=head1 NOTES
@@ -84,9 +95,9 @@ L<EVP_PKEY_derive(3)>
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_CTX_set_scrypt_N.pod b/doc/man3/EVP_PKEY_CTX_set_scrypt_N.pod
index 4e2a4ea6b3fd..1057f41e6ab1 100644
--- a/doc/man3/EVP_PKEY_CTX_set_scrypt_N.pod
+++ b/doc/man3/EVP_PKEY_CTX_set_scrypt_N.pod
@@ -29,7 +29,7 @@ EVP_PKEY_CTX_set_scrypt_maxmem_bytes
These functions are used to set up the necessary data to use the
scrypt KDF.
-For more information on scrypt, see L<scrypt(7)>.
+For more information on scrypt, see L<EVP_KDF-SCRYPT(7)>.
EVP_PKEY_CTX_set1_scrypt_salt() sets the B<saltlen> bytes long salt
value.
@@ -54,12 +54,13 @@ respectively.
=head1 NOTES
+There is a newer generic API for KDFs, L<EVP_KDF(3)>, which is
+preferred over the EVP_PKEY method.
+
The scrypt KDF also uses EVP_PKEY_CTX_set1_pbe_pass() as well as
the value from the string controls "pass" and "hexpass".
See L<EVP_PKEY_CTX_set1_pbe_pass(3)>.
-All the functions described here are implemented as macros.
-
=head1 RETURN VALUES
All these functions return 1 for success and 0 or a negative value for
@@ -69,16 +70,21 @@ supported by the public key algorithm.
=head1 SEE ALSO
-L<scrypt(7)>,
+L<EVP_KDF(3)>
L<EVP_PKEY_CTX_new(3)>,
L<EVP_PKEY_CTX_ctrl_str(3)>,
L<EVP_PKEY_derive(3)>
+=head1 HISTORY
+
+All of the functions described here were converted from macros to functions in
+OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_CTX_set_tls1_prf_md.pod b/doc/man3/EVP_PKEY_CTX_set_tls1_prf_md.pod
index 9a8d7a887552..9c204b8b3289 100644
--- a/doc/man3/EVP_PKEY_CTX_set_tls1_prf_md.pod
+++ b/doc/man3/EVP_PKEY_CTX_set_tls1_prf_md.pod
@@ -46,8 +46,6 @@ which is converted to binary.
=head1 NOTES
-All these functions are implemented as macros.
-
A context for the TLS PRF can be obtained by calling:
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL);
@@ -97,11 +95,16 @@ L<EVP_PKEY_CTX_new(3)>,
L<EVP_PKEY_CTX_ctrl_str(3)>,
L<EVP_PKEY_derive(3)>
+=head1 HISTORY
+
+All of the functions described here were converted from macros to functions in
+OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_asn1_get_count.pod b/doc/man3/EVP_PKEY_asn1_get_count.pod
index cd99e4d75786..19d1e36454b2 100644
--- a/doc/man3/EVP_PKEY_asn1_get_count.pod
+++ b/doc/man3/EVP_PKEY_asn1_get_count.pod
@@ -70,9 +70,9 @@ L<EVP_PKEY_asn1_new(3)>, L<EVP_PKEY_asn1_add0(3)>
=head1 COPYRIGHT
-Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_check.pod b/doc/man3/EVP_PKEY_check.pod
new file mode 100644
index 000000000000..a16fdbbd508f
--- /dev/null
+++ b/doc/man3/EVP_PKEY_check.pod
@@ -0,0 +1,96 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_check, EVP_PKEY_param_check, EVP_PKEY_param_check_quick,
+EVP_PKEY_public_check, EVP_PKEY_public_check_quick, EVP_PKEY_private_check,
+EVP_PKEY_pairwise_check
+- key and parameter validation functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_PKEY_check(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_param_check_quick(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_public_check_quick(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_pairwise_check(EVP_PKEY_CTX *ctx);
+
+=head1 DESCRIPTION
+
+EVP_PKEY_param_check() validates the parameters component of the key
+given by B<ctx>. This check will always succeed for key types that do not have
+parameters.
+
+EVP_PKEY_param_check_quick() validates the parameters component of the key
+given by B<ctx> like EVP_PKEY_param_check() does. However some algorithm
+implementations may offer a quicker form of validation that omits some checks in
+order to perform a lightweight sanity check of the key. If a quicker form is not
+provided then this function call does the same thing as EVP_PKEY_param_check().
+
+EVP_PKEY_public_check() validates the public component of the key given by B<ctx>.
+
+EVP_PKEY_public_check_quick() validates the public component of the key
+given by B<ctx> like EVP_PKEY_public_check() does. However some algorithm
+implementations may offer a quicker form of validation that omits some checks in
+order to perform a lightweight sanity check of the key. If a quicker form is not
+provided then this function call does the same thing as EVP_PKEY_public_check().
+
+EVP_PKEY_private_check() validates the private component of the key given by B<ctx>.
+
+EVP_PKEY_pairwise_check() validates that the public and private components have
+the correct mathematical relationship to each other for the key given by B<ctx>.
+
+EVP_PKEY_check() is an alias for the EVP_PKEY_pairwise_check() function.
+
+=head1 NOTES
+
+Key validation used by the OpenSSL FIPS provider complies with the rules
+within SP800-56A and SP800-56B. For backwards compatibility reasons the OpenSSL
+default provider may use checks that are not as restrictive for certain key types.
+For further information see L<EVP_PKEY-DSA(7)/DSA key validation>,
+L<EVP_PKEY-DH(7)/DH key validation>, L<EVP_PKEY-EC(7)/EC key validation> and
+L<EVP_PKEY-RSA(7)/RSA key validation>.
+
+Refer to SP800-56A and SP800-56B for rules relating to when these functions
+should be called during key establishment.
+It is not necessary to call these functions after locally calling an approved key
+generation method, but may be required for assurance purposes when receiving
+keys from a third party.
+
+=head1 RETURN VALUES
+
+All functions return 1 for success or others for failure.
+They return -2 if the operation is not supported for the specific algorithm.
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_new(3)>,
+L<EVP_PKEY_fromdata(3)>,
+L<EVP_PKEY-DH(7)>,
+L<EVP_PKEY-FFC(7)>,
+L<EVP_PKEY-DSA(7)>,
+L<EVP_PKEY-EC(7)>,
+L<EVP_PKEY-RSA(7)>,
+
+=head1 HISTORY
+
+EVP_PKEY_check(), EVP_PKEY_public_check() and EVP_PKEY_param_check() were added
+in OpenSSL 1.1.1.
+
+EVP_PKEY_param_check_quick(), EVP_PKEY_public_check_quick(),
+EVP_PKEY_private_check() and EVP_PKEY_pairwise_check() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_PKEY_cmp.pod b/doc/man3/EVP_PKEY_cmp.pod
deleted file mode 100644
index 270d635ce2ab..000000000000
--- a/doc/man3/EVP_PKEY_cmp.pod
+++ /dev/null
@@ -1,73 +0,0 @@
-=pod
-
-=head1 NAME
-
-EVP_PKEY_copy_parameters, EVP_PKEY_missing_parameters, EVP_PKEY_cmp_parameters,
-EVP_PKEY_cmp - public key parameter and comparison functions
-
-=head1 SYNOPSIS
-
- #include <openssl/evp.h>
-
- int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey);
- int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from);
-
- int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b);
- int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b);
-
-=head1 DESCRIPTION
-
-The function EVP_PKEY_missing_parameters() returns 1 if the public key
-parameters of B<pkey> are missing and 0 if they are present or the algorithm
-doesn't use parameters.
-
-The function EVP_PKEY_copy_parameters() copies the parameters from key
-B<from> to key B<to>. An error is returned if the parameters are missing in
-B<from> or present in both B<from> and B<to> and mismatch. If the parameters
-in B<from> and B<to> are both present and match this function has no effect.
-
-The function EVP_PKEY_cmp_parameters() compares the parameters of keys
-B<a> and B<b>.
-
-The function EVP_PKEY_cmp() compares the public key components and parameters
-(if present) of keys B<a> and B<b>.
-
-=head1 NOTES
-
-The main purpose of the functions EVP_PKEY_missing_parameters() and
-EVP_PKEY_copy_parameters() is to handle public keys in certificates where the
-parameters are sometimes omitted from a public key if they are inherited from
-the CA that signed it.
-
-Since OpenSSL private keys contain public key components too the function
-EVP_PKEY_cmp() can also be used to determine if a private key matches
-a public key.
-
-=head1 RETURN VALUES
-
-The function EVP_PKEY_missing_parameters() returns 1 if the public key
-parameters of B<pkey> are missing and 0 if they are present or the algorithm
-doesn't use parameters.
-
-These functions EVP_PKEY_copy_parameters() returns 1 for success and 0 for
-failure.
-
-The function EVP_PKEY_cmp_parameters() and EVP_PKEY_cmp() return 1 if the
-keys match, 0 if they don't match, -1 if the key types are different and
--2 if the operation is not supported.
-
-=head1 SEE ALSO
-
-L<EVP_PKEY_CTX_new(3)>,
-L<EVP_PKEY_keygen(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man3/EVP_PKEY_copy_parameters.pod b/doc/man3/EVP_PKEY_copy_parameters.pod
new file mode 100644
index 000000000000..adb5c2084e3c
--- /dev/null
+++ b/doc/man3/EVP_PKEY_copy_parameters.pod
@@ -0,0 +1,120 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_missing_parameters, EVP_PKEY_copy_parameters, EVP_PKEY_parameters_eq,
+EVP_PKEY_cmp_parameters, EVP_PKEY_eq,
+EVP_PKEY_cmp - public key parameter and comparison functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey);
+ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from);
+
+ int EVP_PKEY_parameters_eq(const EVP_PKEY *a, const EVP_PKEY *b);
+ int EVP_PKEY_eq(const EVP_PKEY *a, const EVP_PKEY *b);
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b);
+ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b);
+
+=head1 DESCRIPTION
+
+The function EVP_PKEY_missing_parameters() returns 1 if the public key
+parameters of B<pkey> are missing and 0 if they are present or the algorithm
+doesn't use parameters.
+
+The function EVP_PKEY_copy_parameters() copies the parameters from key
+B<from> to key B<to>. An error is returned if the parameters are missing in
+B<from> or present in both B<from> and B<to> and mismatch. If the parameters
+in B<from> and B<to> are both present and match this function has no effect.
+
+The function EVP_PKEY_parameters_eq() checks the parameters of keys
+B<a> and B<b> for equality.
+
+The function EVP_PKEY_eq() checks the keys B<a> and B<b> for equality,
+including their parameters if they are available.
+
+=head1 NOTES
+
+The main purpose of the functions EVP_PKEY_missing_parameters() and
+EVP_PKEY_copy_parameters() is to handle public keys in certificates where the
+parameters are sometimes omitted from a public key if they are inherited from
+the CA that signed it.
+
+The deprecated functions EVP_PKEY_cmp() and EVP_PKEY_cmp_parameters() differ in
+their return values compared to other _cmp() functions. They are aliases for
+EVP_PKEY_eq() and EVP_PKEY_parameters_eq().
+
+The function EVP_PKEY_cmp() previously only checked the key parameters
+(if there are any) and the public key, assuming that there always was
+a public key and that private key equality could be derived from that.
+Because it's no longer assumed that the private key in an L<EVP_PKEY(3)> is
+always accompanied by a public key, the comparison can not rely on public
+key comparison alone.
+
+Instead, EVP_PKEY_eq() (and therefore also EVP_PKEY_cmp()) now compares:
+
+=over 4
+
+=item 1.
+
+the key parameters (if there are any)
+
+=item 2.
+
+the public keys or the private keys of the two B<EVP_PKEY>s, depending on
+what they both contain.
+
+=back
+
+=begin comment
+
+Exactly what is compared is ultimately at the discretion of the provider
+that holds the key, as they will compare what makes sense to them that fits
+the selector bits they are passed.
+
+=end comment
+
+=head1 RETURN VALUES
+
+The function EVP_PKEY_missing_parameters() returns 1 if the public key
+parameters of B<pkey> are missing and 0 if they are present or the algorithm
+doesn't use parameters.
+
+These functions EVP_PKEY_copy_parameters() returns 1 for success and 0 for
+failure.
+
+The functions EVP_PKEY_cmp_parameters(), EVP_PKEY_parameters_eq(),
+EVP_PKEY_cmp() and EVP_PKEY_eq() return 1 if their
+inputs match, 0 if they don't match, -1 if the key types are different and
+-2 if the operation is not supported.
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_new(3)>,
+L<EVP_PKEY_keygen(3)>
+
+=head1 HISTORY
+
+The EVP_PKEY_cmp() and EVP_PKEY_cmp_parameters() functions were deprecated in
+OpenSSL 3.0.
+
+The EVP_PKEY_eq() and EVP_PKEY_parameters_eq() were added in OpenSSL 3.0 to
+replace EVP_PKEY_cmp() and EVP_PKEY_cmp_parameters().
+
+=head1 COPYRIGHT
+
+Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_PKEY_decapsulate.pod b/doc/man3/EVP_PKEY_decapsulate.pod
new file mode 100644
index 000000000000..529e318f9eba
--- /dev/null
+++ b/doc/man3/EVP_PKEY_decapsulate.pod
@@ -0,0 +1,99 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_decapsulate_init, EVP_PKEY_decapsulate
+- Key decapsulation using a private key algorithm
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_PKEY_decapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
+ int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx,
+ unsigned char *secret, size_t *secretlen,
+ const unsigned char *wrapped, size_t wrappedlen);
+
+=head1 DESCRIPTION
+
+The EVP_PKEY_decapsulate_init() function initializes a private key algorithm
+context I<ctx> for a decapsulation operation and then sets the I<params>
+on the context in the same way as calling L<EVP_PKEY_CTX_set_params(3)>.
+
+The EVP_PKEY_decapsulate() function performs a private key decapsulation
+operation using I<ctx>. The data to be decapsulated is specified using the
+I<wrapped> and I<wrappedlen> parameters.
+If I<secret> is I<NULL> then the maximum size of the output secret buffer
+is written to the I<*secretlen> parameter. If I<secret> is not B<NULL> and the
+call is successful then the decapsulated secret data is written to I<secret> and
+the amount of data written to I<secretlen>.
+
+=head1 NOTES
+
+After the call to EVP_PKEY_decapsulate_init() algorithm specific parameters
+for the operation may be set or modified using L<EVP_PKEY_CTX_set_params(3)>.
+
+=head1 RETURN VALUES
+
+EVP_PKEY_decapsulate_init() and EVP_PKEY_decapsulate() return 1 for
+success and 0 or a negative value for failure. In particular a return value of -2
+indicates the operation is not supported by the private key algorithm.
+
+=head1 EXAMPLES
+
+Decapsulate data using RSA:
+
+ #include <openssl/evp.h>
+
+ /*
+ * NB: assumes rsa_priv_key is an RSA private key,
+ * and that in, inlen are already set up to contain encapsulated data.
+ */
+
+ EVP_PKEY_CTX *ctx = NULL;
+ size_t secretlen = 0;
+ unsigned char *secret = NULL;;
+
+ ctx = EVP_PKEY_CTX_new_from_pkey(libctx, rsa_priv_key, NULL);
+ if (ctx = NULL)
+ /* Error */
+ if (EVP_PKEY_decapsulate_init(ctx, NULL) <= 0)
+ /* Error */
+
+ /* Set the mode - only 'RSASVE' is currently supported */
+ if (EVP_PKEY_CTX_set_kem_op(ctx, "RSASVE") <= 0)
+ /* Error */
+
+ /* Determine buffer length */
+ if (EVP_PKEY_decapsulate(ctx, NULL, &secretlen, in, inlen) <= 0)
+ /* Error */
+
+ secret = OPENSSL_malloc(secretlen);
+ if (secret == NULL)
+ /* malloc failure */
+
+ /* Decapsulated secret data is secretlen bytes long */
+ if (EVP_PKEY_decapsulaterctx, secret, &secretlen, in, inlen) <= 0)
+ /* Error */
+
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_new(3)>,
+L<EVP_PKEY_encapsulate(3)>,
+L<EVP_KEM-RSA(7)>,
+
+=head1 HISTORY
+
+These functions were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_PKEY_decrypt.pod b/doc/man3/EVP_PKEY_decrypt.pod
index 08d0ec32bdb3..b6f9bad5f18a 100644
--- a/doc/man3/EVP_PKEY_decrypt.pod
+++ b/doc/man3/EVP_PKEY_decrypt.pod
@@ -2,13 +2,15 @@
=head1 NAME
-EVP_PKEY_decrypt_init, EVP_PKEY_decrypt - decrypt using a public key algorithm
+EVP_PKEY_decrypt_init, EVP_PKEY_decrypt_init_ex,
+EVP_PKEY_decrypt - decrypt using a public key algorithm
=head1 SYNOPSIS
#include <openssl/evp.h>
int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_decrypt_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
unsigned char *out, size_t *outlen,
const unsigned char *in, size_t inlen);
@@ -16,30 +18,38 @@ EVP_PKEY_decrypt_init, EVP_PKEY_decrypt - decrypt using a public key algorithm
=head1 DESCRIPTION
The EVP_PKEY_decrypt_init() function initializes a public key algorithm
-context using key B<pkey> for a decryption operation.
+context using key I<pkey> for a decryption operation.
+
+The EVP_PKEY_decrypt_init_ex() function initializes a public key algorithm
+context using key I<pkey> for a decryption operation and sets the
+algorithm specific I<params>.
The EVP_PKEY_decrypt() function performs a public key decryption operation
-using B<ctx>. The data to be decrypted is specified using the B<in> and
-B<inlen> parameters. If B<out> is B<NULL> then the maximum size of the output
-buffer is written to the B<outlen> parameter. If B<out> is not B<NULL> then
-before the call the B<outlen> parameter should contain the length of the
-B<out> buffer, if the call is successful the decrypted data is written to
-B<out> and the amount of data written to B<outlen>.
+using I<ctx>. The data to be decrypted is specified using the I<in> and
+I<inlen> parameters. If I<out> is NULL then the minimum required size of
+the output buffer is written to the I<*outlen> parameter.
+
+If I<out> is not NULL then before the call the I<*outlen> parameter must
+contain the length of the I<out> buffer. If the call is successful the
+decrypted data is written to I<out> and the amount of the decrypted data
+written to I<*outlen>, otherwise an error is returned.
=head1 NOTES
After the call to EVP_PKEY_decrypt_init() algorithm specific control
operations can be performed to set any appropriate parameters for the
-operation.
+operation. These operations can be included in the EVP_PKEY_decrypt_init_ex()
+call.
The function EVP_PKEY_decrypt() can be called more than once on the same
context if several operations are performed using the same parameters.
=head1 RETURN VALUES
-EVP_PKEY_decrypt_init() and EVP_PKEY_decrypt() return 1 for success and 0
-or a negative value for failure. In particular a return value of -2
-indicates the operation is not supported by the public key algorithm.
+EVP_PKEY_decrypt_init(), EVP_PKEY_decrypt_init_ex() and EVP_PKEY_decrypt()
+return 1 for success and 0 or a negative value for failure. In particular a
+return value of -2 indicates the operation is not supported by the public key
+algorithm.
=head1 EXAMPLES
@@ -63,7 +73,7 @@ Decrypt data using OAEP (for RSA keys):
/* Error occurred */
if (EVP_PKEY_decrypt_init(ctx) <= 0)
/* Error */
- if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_OAEP_PADDING) <= 0)
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0)
/* Error */
/* Determine buffer length */
@@ -95,9 +105,9 @@ These functions were added in OpenSSL 1.0.0.
=head1 COPYRIGHT
-Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_derive.pod b/doc/man3/EVP_PKEY_derive.pod
index 76b3c3986b1c..d61bb5512f62 100644
--- a/doc/man3/EVP_PKEY_derive.pod
+++ b/doc/man3/EVP_PKEY_derive.pod
@@ -2,45 +2,61 @@
=head1 NAME
-EVP_PKEY_derive_init, EVP_PKEY_derive_set_peer, EVP_PKEY_derive - derive public key algorithm shared secret
+EVP_PKEY_derive_init, EVP_PKEY_derive_init_ex,
+EVP_PKEY_derive_set_peer_ex, EVP_PKEY_derive_set_peer, EVP_PKEY_derive
+- derive public key algorithm shared secret
=head1 SYNOPSIS
#include <openssl/evp.h>
int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
+ int EVP_PKEY_derive_set_peer_ex(EVP_PKEY_CTX *ctx, EVP_PKEY *peer,
+ int validate_peer);
int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer);
int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
=head1 DESCRIPTION
-The EVP_PKEY_derive_init() function initializes a public key algorithm
-context using key B<pkey> for shared secret derivation.
+EVP_PKEY_derive_init() initializes a public key algorithm context I<ctx> for
+shared secret derivation using the algorithm given when the context was created
+using L<EVP_PKEY_CTX_new(3)> or variants thereof. The algorithm is used to
+fetch a B<EVP_KEYEXCH> method implicitly, see L<provider(7)/Implicit fetch> for
+more information about implicit fetches.
-The EVP_PKEY_derive_set_peer() function sets the peer key: this will normally
-be a public key.
+EVP_PKEY_derive_init_ex() is the same as EVP_PKEY_derive_init() but additionally
+sets the passed parameters I<params> on the context before returning.
-The EVP_PKEY_derive() derives a shared secret using B<ctx>.
-If B<key> is B<NULL> then the maximum size of the output buffer is written to
-the B<keylen> parameter. If B<key> is not B<NULL> then before the call the
-B<keylen> parameter should contain the length of the B<key> buffer, if the call
-is successful the shared secret is written to B<key> and the amount of data
-written to B<keylen>.
+EVP_PKEY_derive_set_peer_ex() sets the peer key: this will normally
+be a public key. The I<validate_peer> will validate the public key if this value
+is non zero.
+
+EVP_PKEY_derive_set_peer() is similiar to EVP_PKEY_derive_set_peer_ex() with
+I<validate_peer> set to 1.
+
+EVP_PKEY_derive() derives a shared secret using I<ctx>.
+If I<key> is NULL then the maximum size of the output buffer is written to the
+I<keylen> parameter. If I<key> is not NULL then before the call the I<keylen>
+parameter should contain the length of the I<key> buffer, if the call is
+successful the shared secret is written to I<key> and the amount of data
+written to I<keylen>.
=head1 NOTES
-After the call to EVP_PKEY_derive_init() algorithm specific control
-operations can be performed to set any appropriate parameters for the
-operation.
+After the call to EVP_PKEY_derive_init(), algorithm
+specific control operations can be performed to set any appropriate parameters
+for the operation.
The function EVP_PKEY_derive() can be called more than once on the same
context if several operations are performed using the same parameters.
=head1 RETURN VALUES
-EVP_PKEY_derive_init() and EVP_PKEY_derive() return 1 for success and 0
-or a negative value for failure. In particular a return value of -2
-indicates the operation is not supported by the public key algorithm.
+EVP_PKEY_derive_init() and EVP_PKEY_derive() return 1
+for success and 0 or a negative value for failure.
+In particular a return value of -2 indicates the operation is not supported by
+the public key algorithm.
=head1 EXAMPLES
@@ -86,16 +102,21 @@ L<EVP_PKEY_decrypt(3)>,
L<EVP_PKEY_sign(3)>,
L<EVP_PKEY_verify(3)>,
L<EVP_PKEY_verify_recover(3)>,
+L<EVP_KEYEXCH_fetch(3)>
=head1 HISTORY
-These functions were added in OpenSSL 1.0.0.
+The EVP_PKEY_derive_init(), EVP_PKEY_derive_set_peer() and EVP_PKEY_derive()
+functions were originally added in OpenSSL 1.0.0.
+
+The EVP_PKEY_derive_init_ex() and EVP_PKEY_derive_set_peer_ex() functions were
+added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_digestsign_supports_digest.pod b/doc/man3/EVP_PKEY_digestsign_supports_digest.pod
new file mode 100644
index 000000000000..c043ce4e9590
--- /dev/null
+++ b/doc/man3/EVP_PKEY_digestsign_supports_digest.pod
@@ -0,0 +1,44 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_digestsign_supports_digest - indicate support for signature digest
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+ int EVP_PKEY_digestsign_supports_digest(EVP_PKEY *pkey, OSSL_LIB_CTX *libctx,
+ const char *name, const char *propq);
+
+=head1 DESCRIPTION
+
+The EVP_PKEY_digestsign_supports_digest() function queries whether the message
+digest I<name> is supported for public key signature operations associated with
+key I<pkey>. The query is done within an optional library context I<libctx> and
+with an optional property query I<propq>.
+
+=head1 RETURN VALUES
+
+The EVP_PKEY_digestsign_supports_digest() function returns 1 if the message
+digest algorithm identified by I<name> can be used for public key signature
+operations associated with key I<pkey> and 0 if it cannot be used. It returns
+a negative value for failure.
+
+=head1 SEE ALSO
+
+L<EVP_DigestSignInit_ex(3)>,
+
+=head1 HISTORY
+
+The EVP_PKEY_digestsign_supports_digest() function was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_PKEY_encapsulate.pod b/doc/man3/EVP_PKEY_encapsulate.pod
new file mode 100644
index 000000000000..9baf88d07bef
--- /dev/null
+++ b/doc/man3/EVP_PKEY_encapsulate.pod
@@ -0,0 +1,102 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_encapsulate_init, EVP_PKEY_encapsulate
+- Key encapsulation using a public key algorithm
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
+ int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx,
+ unsigned char *out, size_t *outlen,
+ unsigned char *genkey, size_t *genkeylen);
+
+=head1 DESCRIPTION
+
+The EVP_PKEY_encapsulate_init() function initializes a public key algorithm
+context I<ctx> for an encapsulation operation and then sets the I<params>
+on the context in the same way as calling L<EVP_PKEY_CTX_set_params(3)>.
+
+The EVP_PKEY_encapsulate() function performs a public key encapsulation
+operation using I<ctx> with the name I<name>.
+If I<out> is B<NULL> then the maximum size of the output buffer is written to the
+I<*outlen> parameter and the maximum size of the generated key buffer is written
+to I<*genkeylen>. If I<out> is not B<NULL> and the call is successful then the
+internally generated key is written to I<genkey> and its size is written to
+I<*genkeylen>. The encapsulated version of the generated key is written to
+I<out> and its size is written to I<*outlen>.
+
+=head1 NOTES
+
+After the call to EVP_PKEY_encapsulate_init() algorithm specific parameters
+for the operation may be set or modified using L<EVP_PKEY_CTX_set_params(3)>.
+
+=head1 RETURN VALUES
+
+EVP_PKEY_encapsulate_init() and EVP_PKEY_encapsulate() return 1 for
+success and 0 or a negative value for failure. In particular a return value of -2
+indicates the operation is not supported by the public key algorithm.
+
+=head1 EXAMPLES
+
+Encapsulate an RSASVE key (for RSA keys).
+
+ #include <openssl/evp.h>
+
+ /*
+ * NB: assumes rsa_pub_key is an public key of another party.
+ */
+
+ EVP_PKEY_CTX *ctx = NULL;
+ size_t secretlen = 0, outlen = 0;
+ unsigned char *out = NULL, *secret = NULL;
+
+ ctx = EVP_PKEY_CTX_new_from_pkey(libctx, rsa_pub_key, NULL);
+ if (ctx = NULL)
+ /* Error */
+ if (EVP_PKEY_encapsulate_init(ctx, NULL) <= 0)
+ /* Error */
+
+ /* Set the mode - only 'RSASVE' is currently supported */
+ if (EVP_PKEY_CTX_set_kem_op(ctx, "RSASVE") <= 0)
+ /* Error */
+ /* Determine buffer length */
+ if (EVP_PKEY_encapsulate(ctx, NULL, &outlen, NULL, &secretlen) <= 0)
+ /* Error */
+
+ out = OPENSSL_malloc(outlen);
+ secret = OPENSSL_malloc(secretlen);
+ if (out == NULL || secret == NULL)
+ /* malloc failure */
+
+ /*
+ * The generated 'secret' can be used as key material.
+ * The encapsulated 'out' can be sent to another party who can
+ * decapsulate it using their private key to retrieve the 'secret'.
+ */
+ if (EVP_PKEY_encapsulate(ctx, out, &outlen, secret, &secretlen) <= 0)
+ /* Error */
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_new(3)>,
+L<EVP_PKEY_decapsulate(3)>,
+L<EVP_KEM-RSA(7)>,
+
+=head1 HISTORY
+
+These functions were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_PKEY_encrypt.pod b/doc/man3/EVP_PKEY_encrypt.pod
index 2a3bf2a09741..53b2e0edd2e8 100644
--- a/doc/man3/EVP_PKEY_encrypt.pod
+++ b/doc/man3/EVP_PKEY_encrypt.pod
@@ -2,6 +2,7 @@
=head1 NAME
+EVP_PKEY_encrypt_init_ex,
EVP_PKEY_encrypt_init, EVP_PKEY_encrypt - encrypt using a public key algorithm
=head1 SYNOPSIS
@@ -9,6 +10,7 @@ EVP_PKEY_encrypt_init, EVP_PKEY_encrypt - encrypt using a public key algorithm
#include <openssl/evp.h>
int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_encrypt_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
unsigned char *out, size_t *outlen,
const unsigned char *in, size_t inlen);
@@ -18,6 +20,10 @@ EVP_PKEY_encrypt_init, EVP_PKEY_encrypt - encrypt using a public key algorithm
The EVP_PKEY_encrypt_init() function initializes a public key algorithm
context using key B<pkey> for an encryption operation.
+The EVP_PKEY_encrypt_init_ex() function initializes a public key algorithm
+context using key B<pkey> for an encryption operation and sets the
+algorithm specific B<params>.
+
The EVP_PKEY_encrypt() function performs a public key encryption operation
using B<ctx>. The data to be encrypted is specified using the B<in> and
B<inlen> parameters. If B<out> is B<NULL> then the maximum size of the output
@@ -30,16 +36,18 @@ B<out> and the amount of data written to B<outlen>.
After the call to EVP_PKEY_encrypt_init() algorithm specific control
operations can be performed to set any appropriate parameters for the
-operation.
+operation. These operations can be included in the EVP_PKEY_encrypt_init_ex()
+call.
The function EVP_PKEY_encrypt() can be called more than once on the same
context if several operations are performed using the same parameters.
=head1 RETURN VALUES
-EVP_PKEY_encrypt_init() and EVP_PKEY_encrypt() return 1 for success and 0
-or a negative value for failure. In particular a return value of -2
-indicates the operation is not supported by the public key algorithm.
+EVP_PKEY_encrypt_init(), EVP_PKEY_encrypt_init_ex() and EVP_PKEY_encrypt()
+return 1 for success and 0 or a negative value for failure. In particular a
+return value of -2 indicates the operation is not supported by the public key
+algorithm.
=head1 EXAMPLES
@@ -66,7 +74,7 @@ set 'eng = NULL;' to start with the default OpenSSL RSA implementation:
/* Error occurred */
if (EVP_PKEY_encrypt_init(ctx) <= 0)
/* Error */
- if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_OAEP_PADDING) <= 0)
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0)
/* Error */
/* Determine buffer length */
@@ -100,9 +108,9 @@ These functions were added in OpenSSL 1.0.0.
=head1 COPYRIGHT
-Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_fromdata.pod b/doc/man3/EVP_PKEY_fromdata.pod
new file mode 100644
index 000000000000..3e9e06d1a202
--- /dev/null
+++ b/doc/man3/EVP_PKEY_fromdata.pod
@@ -0,0 +1,280 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_fromdata_init, EVP_PKEY_fromdata, EVP_PKEY_fromdata_settable
+- functions to create keys and key parameters from user data
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_PKEY_fromdata_init(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, int selection,
+ OSSL_PARAM params[]);
+ const OSSL_PARAM *EVP_PKEY_fromdata_settable(EVP_PKEY_CTX *ctx, int selection);
+
+=head1 DESCRIPTION
+
+The functions described here are used to create new keys from user
+provided key data, such as I<n>, I<e> and I<d> for a minimal RSA
+keypair.
+
+These functions use an B<EVP_PKEY_CTX> context, which should primarily
+be created with L<EVP_PKEY_CTX_new_from_name(3)> or
+L<EVP_PKEY_CTX_new_id(3)>.
+
+The exact key data that the user can pass depends on the key type.
+These are passed as an L<OSSL_PARAM(3)> array.
+
+EVP_PKEY_fromdata_init() initializes a public key algorithm context
+for creating a key or key parameters from user data.
+
+EVP_PKEY_fromdata() creates the structure to store a key or key parameters,
+given data from I<params>, I<selection> and a context that's been initialized
+with EVP_PKEY_fromdata_init(). The result is written to I<*ppkey>.
+I<selection> is described in L</Selections>.
+The parameters that can be used for various types of key are as described by the
+diverse "Common parameters" sections of the
+L<B<EVP_PKEY-RSA>(7)|EVP_PKEY-RSA(7)/Common RSA parameters>,
+L<B<EVP_PKEY-DSA>(7)|EVP_PKEY-DSA(7)/Common DSA & DH parameters>,
+L<B<EVP_PKEY-DH>(7)|EVP_PKEY-DH(7)/Common DH parameters>,
+L<B<EVP_PKEY-EC>(7)|EVP_PKEY-EC(7)/Common EC parameters>,
+L<B<EVP_PKEY-ED448>(7)|EVP_PKEY-ED448(7)/Common X25519, X448, ED25519 and ED448 parameters>,
+L<B<EVP_PKEY-X25519>(7)|EVP_PKEY-X25519(7)/Common X25519, X448, ED25519 and ED448 parameters>,
+L<B<EVP_PKEY-X448>(7)|EVP_PKEY-X448(7)/Common X25519, X448, ED25519 and ED448 parameters>,
+and L<B<EVP_PKEY-ED25519>(7)|EVP_PKEY-ED25519(7)/Common X25519, X448, ED25519 and ED448 parameters> pages.
+
+=for comment the awful list of links above is made this way so we get nice
+rendering as a man-page while still getting proper links in HTML
+
+EVP_PKEY_fromdata_settable() gets a constant L<OSSL_PARAM(3)> array that describes
+the settable parameters that can be used with EVP_PKEY_fromdata().
+I<selection> is described in L</Selections>.
+
+Parameters in the I<params> array that are not among the settable parameters
+for the given I<selection> are ignored.
+
+=head2 Selections
+
+The following constants can be used for I<selection>:
+
+=over 4
+
+=item B<EVP_PKEY_KEY_PARAMETERS>
+
+Only key parameters will be selected.
+
+=item B<EVP_PKEY_PUBLIC_KEY>
+
+Only public key components will be selected. This includes optional key
+parameters.
+
+=item B<EVP_PKEY_KEYPAIR>
+
+Any keypair components will be selected. This includes the private key,
+public key and key parameters.
+
+=back
+
+=head1 NOTES
+
+These functions only work with key management methods coming from a provider.
+This is the mirror function to L<EVP_PKEY_todata(3)>.
+
+=for comment We may choose to make this available for legacy methods too...
+
+=head1 RETURN VALUES
+
+EVP_PKEY_fromdata_init() and EVP_PKEY_fromdata() return 1 for success and 0 or
+a negative value for failure. In particular a return value of -2 indicates the
+operation is not supported by the public key algorithm.
+
+=head1 EXAMPLES
+
+These examples are very terse for the sake of staying on topic, which
+is the EVP_PKEY_fromdata() set of functions. In real applications,
+BIGNUMs would be handled and converted to byte arrays with
+BN_bn2nativepad(), but that's off topic here.
+
+=begin comment
+
+TODO Write a set of cookbook documents and link to them.
+
+=end comment
+
+=head2 Creating an RSA keypair using raw key data
+
+ #include <openssl/evp.h>
+
+ /*
+ * These are extremely small to make this example simple. A real
+ * and secure application will not use such small numbers. A real
+ * and secure application is expected to use BIGNUMs, and to build
+ * this array dynamically.
+ */
+ unsigned long rsa_n = 0xbc747fc5;
+ unsigned long rsa_e = 0x10001;
+ unsigned long rsa_d = 0x7b133399;
+ OSSL_PARAM params[] = {
+ OSSL_PARAM_ulong("n", &rsa_n),
+ OSSL_PARAM_ulong("e", &rsa_e),
+ OSSL_PARAM_ulong("d", &rsa_d),
+ OSSL_PARAM_END
+ };
+
+ int main()
+ {
+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
+ EVP_PKEY *pkey = NULL;
+
+ if (ctx == NULL
+ || EVP_PKEY_fromdata_init(ctx) <= 0
+ || EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0)
+ exit(1);
+
+ /* Do what you want with |pkey| */
+ }
+
+=head2 Creating an ECC keypair using raw key data
+
+ #include <openssl/evp.h>
+ #include <openssl/param_build.h>
+ #include <openssl/ec.h>
+
+ /*
+ * Fixed data to represent the private and public key.
+ */
+ const unsigned char priv_data[] = {
+ 0xb9, 0x2f, 0x3c, 0xe6, 0x2f, 0xfb, 0x45, 0x68,
+ 0x39, 0x96, 0xf0, 0x2a, 0xaf, 0x6c, 0xda, 0xf2,
+ 0x89, 0x8a, 0x27, 0xbf, 0x39, 0x9b, 0x7e, 0x54,
+ 0x21, 0xc2, 0xa1, 0xe5, 0x36, 0x12, 0x48, 0x5d
+ };
+ /* UNCOMPRESSED FORMAT */
+ const unsigned char pub_data[] = {
+ POINT_CONVERSION_UNCOMPRESSED,
+ 0xcf, 0x20, 0xfb, 0x9a, 0x1d, 0x11, 0x6c, 0x5e,
+ 0x9f, 0xec, 0x38, 0x87, 0x6c, 0x1d, 0x2f, 0x58,
+ 0x47, 0xab, 0xa3, 0x9b, 0x79, 0x23, 0xe6, 0xeb,
+ 0x94, 0x6f, 0x97, 0xdb, 0xa3, 0x7d, 0xbd, 0xe5,
+ 0x26, 0xca, 0x07, 0x17, 0x8d, 0x26, 0x75, 0xff,
+ 0xcb, 0x8e, 0xb6, 0x84, 0xd0, 0x24, 0x02, 0x25,
+ 0x8f, 0xb9, 0x33, 0x6e, 0xcf, 0x12, 0x16, 0x2f,
+ 0x5c, 0xcd, 0x86, 0x71, 0xa8, 0xbf, 0x1a, 0x47
+ };
+
+ int main()
+ {
+ EVP_PKEY_CTX *ctx;
+ EVP_PKEY *pkey = NULL;
+ BIGNUM *priv;
+ OSSL_PARAM_BLD *param_bld;
+ OSSL_PARAM *params = NULL;
+ int exitcode = 0;
+
+ priv = BN_bin2bn(priv_data, sizeof(priv_data), NULL);
+
+ param_bld = OSSL_PARAM_BLD_new();
+ if (priv != NULL && param_bld != NULL
+ && OSSL_PARAM_BLD_push_utf8_string(param_bld, "group",
+ "prime256v1", 0)
+ && OSSL_PARAM_BLD_push_BN(param_bld, "priv", priv)
+ && OSSL_PARAM_BLD_push_octet_string(param_bld, "pub",
+ pub_data, sizeof(pub_data)))
+ params = OSSL_PARAM_BLD_to_param(param_bld);
+
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
+ if (ctx == NULL
+ || params == NULL
+ || EVP_PKEY_fromdata_init(ctx) <= 0
+ || EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) {
+ exitcode = 1;
+ } else {
+ /* Do what you want with |pkey| */
+ }
+
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(ctx);
+ OSSL_PARAM_free(params);
+ OSSL_PARAM_BLD_free(param_bld);
+ BN_free(priv);
+
+ exit(exitcode);
+ }
+
+=head2 Finding out params for an unknown key type
+
+ #include <openssl/evp.h>
+ #include <openssl/core.h>
+
+ /* Program expects a key type as first argument */
+ int main(int argc, char *argv[])
+ {
+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, argv[1], NULL);
+ const OSSL_PARAM *settable_params = NULL;
+
+ if (ctx == NULL)
+ exit(1);
+ settable_params = EVP_PKEY_fromdata_settable(ctx, EVP_PKEY_KEYPAIR);
+ if (settable_params == NULL)
+ exit(1);
+
+ for (; settable_params->key != NULL; settable_params++) {
+ const char *datatype = NULL;
+
+ switch (settable_params->data_type) {
+ case OSSL_PARAM_INTEGER:
+ datatype = "integer";
+ break;
+ case OSSL_PARAM_UNSIGNED_INTEGER:
+ datatype = "unsigned integer";
+ break;
+ case OSSL_PARAM_UTF8_STRING:
+ datatype = "printable string (utf-8 encoding expected)";
+ break;
+ case OSSL_PARAM_UTF8_PTR:
+ datatype = "printable string pointer (utf-8 encoding expected)";
+ break;
+ case OSSL_PARAM_OCTET_STRING:
+ datatype = "octet string";
+ break;
+ case OSSL_PARAM_OCTET_PTR:
+ datatype = "octet string pointer";
+ break;
+ }
+ printf("%s : %s ", settable_params->key, datatype);
+ if (settable_params->data_size == 0)
+ printf("(unlimited size)\n");
+ else
+ printf("(maximum size %zu)\n", settable_params->data_size);
+ }
+ }
+
+The descriptor L<OSSL_PARAM(3)> returned by
+EVP_PKEY_fromdata_settable() may also be used programmatically, for
+example with L<OSSL_PARAM_allocate_from_text(3)>.
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_new(3)>, L<provider(7)>, L<EVP_PKEY_gettable_params(3)>,
+L<OSSL_PARAM(3)>, L<EVP_PKEY_todata(3)>,
+L<EVP_PKEY-RSA(7)>, L<EVP_PKEY-DSA(7)>, L<EVP_PKEY-DH(7)>, L<EVP_PKEY-EC(7)>,
+L<EVP_PKEY-ED448(7)>, L<EVP_PKEY-X25519(7)>, L<EVP_PKEY-X448(7)>,
+L<EVP_PKEY-ED25519(7)>
+
+=head1 HISTORY
+
+These functions were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
+
diff --git a/doc/man3/EVP_PKEY_get_default_digest_nid.pod b/doc/man3/EVP_PKEY_get_default_digest_nid.pod
index ed52e9696c9f..ddabac8ff8e4 100644
--- a/doc/man3/EVP_PKEY_get_default_digest_nid.pod
+++ b/doc/man3/EVP_PKEY_get_default_digest_nid.pod
@@ -2,36 +2,52 @@
=head1 NAME
-EVP_PKEY_get_default_digest_nid - get default signature digest
+EVP_PKEY_get_default_digest_nid, EVP_PKEY_get_default_digest_name
+- get default signature digest
=head1 SYNOPSIS
#include <openssl/evp.h>
+
+ int EVP_PKEY_get_default_digest_name(EVP_PKEY *pkey,
+ char *mdname, size_t mdname_sz);
int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid);
=head1 DESCRIPTION
-The EVP_PKEY_get_default_digest_nid() function sets B<pnid> to the default
-message digest NID for the public key signature operations associated with key
-B<pkey>. Note that some signature algorithms (i.e. Ed25519 and Ed448) do not use
-a digest during signing. In this case B<pnid> will be set to NID_undef.
+EVP_PKEY_get_default_digest_name() fills in the default message digest
+name for the public key signature operations associated with key
+I<pkey> into I<mdname>, up to at most I<mdname_sz> bytes including the
+ending NUL byte. The name could be C<"UNDEF">, signifying that no digest
+should be used.
+
+EVP_PKEY_get_default_digest_nid() sets I<pnid> to the default message
+digest NID for the public key signature operations associated with key
+I<pkey>. Note that some signature algorithms (i.e. Ed25519 and Ed448)
+do not use a digest during signing. In this case I<pnid> will be set
+to NID_undef. This function is only reliable for legacy keys, which
+are keys with a B<EVP_PKEY_ASN1_METHOD>; these keys have typically
+been loaded from engines, or created with L<EVP_PKEY_assign_RSA(3)> or
+similar.
=head1 NOTES
-For all current standard OpenSSL public key algorithms SHA1 is returned.
+For all current standard OpenSSL public key algorithms SHA256 is returned.
=head1 RETURN VALUES
-The EVP_PKEY_get_default_digest_nid() function returns 1 if the message digest
-is advisory (that is other digests can be used) and 2 if it is mandatory (other
-digests can not be used). It returns 0 or a negative value for failure. In
-particular a return value of -2 indicates the operation is not supported by the
-public key algorithm.
+EVP_PKEY_get_default_digest_name() and EVP_PKEY_get_default_digest_nid()
+both return 1 if the message digest is advisory (that is other digests
+can be used) and 2 if it is mandatory (other digests can not be used).
+They return 0 or a negative value for failure. In particular a return
+value of -2 indicates the operation is not supported by the public key
+algorithm.
=head1 SEE ALSO
L<EVP_PKEY_CTX_new(3)>,
L<EVP_PKEY_sign(3)>,
+L<EVP_PKEY_digestsign_supports_digest(3)>,
L<EVP_PKEY_verify(3)>,
L<EVP_PKEY_verify_recover(3)>,
@@ -41,9 +57,9 @@ This function was added in OpenSSL 1.0.0.
=head1 COPYRIGHT
-Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_get_field_type.pod b/doc/man3/EVP_PKEY_get_field_type.pod
new file mode 100644
index 000000000000..e32fa7290c16
--- /dev/null
+++ b/doc/man3/EVP_PKEY_get_field_type.pod
@@ -0,0 +1,55 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_get_field_type, EVP_PKEY_get_ec_point_conv_form - get field type
+or point conversion form of a key
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_PKEY_get_field_type(const EVP_PKEY *pkey);
+ int EVP_PKEY_get_ec_point_conv_form(const EVP_PKEY *pkey);
+
+=head1 DESCRIPTION
+
+EVP_PKEY_get_field_type() returns the field type NID of the I<pkey>, if
+I<pkey>'s key type supports it. The types currently supported
+by the built-in OpenSSL providers are either B<NID_X9_62_prime_field>
+for prime curves or B<NID_X9_62_characteristic_two_field> for binary curves;
+these values are defined in the F<< <openssl/obj_mac.h> >> header file.
+
+EVP_PKEY_get_ec_point_conv_form() returns the point conversion format
+of the I<pkey>, if I<pkey>'s key type supports it.
+
+=head1 NOTES
+
+Among the standard OpenSSL key types, this is only supported for EC and
+SM2 keys. Other providers may support this for additional key types.
+
+=head1 RETURN VALUES
+
+EVP_PKEY_get_field_type() returns the field type NID or 0 on error.
+
+EVP_PKEY_get_ec_point_conv_form() returns the point conversion format number
+(see L<EC_GROUP_copy(3)>) or 0 on error.
+
+=head1 SEE ALSO
+
+L<EC_GROUP_copy(3)>
+
+=head1 HISTORY
+
+These functions were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_PKEY_get_group_name.pod b/doc/man3/EVP_PKEY_get_group_name.pod
new file mode 100644
index 000000000000..5844bf1abce4
--- /dev/null
+++ b/doc/man3/EVP_PKEY_get_group_name.pod
@@ -0,0 +1,46 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_get_group_name - get group name of a key
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_PKEY_get_group_name(EVP_PKEY *pkey, char *gname, size_t gname_sz,
+ size_t *gname_len);
+
+=head1 DESCRIPTION
+
+EVP_PKEY_get_group_name() fills in the group name of the I<pkey> into
+I<gname>, up to at most I<gname_sz> bytes including the ending NUL byte
+and assigns I<*gname_len> the actual length of the name not including
+the NUL byte, if I<pkey>'s key type supports it.
+I<gname> as well as I<gname_len> may individually be NULL, and won't be
+filled in or assigned in that case.
+
+=head1 NOTES
+
+Among the standard OpenSSL key types, this is only supported for DH, EC and
+SM2 keys. Other providers may support this for additional key types.
+
+=head1 RETURN VALUES
+
+EVP_PKEY_get_group_name() returns 1 if the group name could be filled in,
+otherwise 0.
+
+=head1 HISTORY
+
+This function was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_PKEY_get_size.pod b/doc/man3/EVP_PKEY_get_size.pod
new file mode 100644
index 000000000000..37bb9bb4c45b
--- /dev/null
+++ b/doc/man3/EVP_PKEY_get_size.pod
@@ -0,0 +1,91 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_get_size, EVP_PKEY_get_bits, EVP_PKEY_get_security_bits,
+EVP_PKEY_bits, EVP_PKEY_security_bits, EVP_PKEY_size
+- EVP_PKEY information functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_PKEY_get_size(const EVP_PKEY *pkey);
+ int EVP_PKEY_get_bits(const EVP_PKEY *pkey);
+ int EVP_PKEY_get_security_bits(const EVP_PKEY *pkey);
+
+ #define EVP_PKEY_bits EVP_PKEY_get_bits
+ #define EVP_PKEY_security_bits EVP_PKEY_get_security_bits
+ #define EVP_PKEY_size EVP_PKEY_get_size
+
+=head1 DESCRIPTION
+
+EVP_PKEY_get_size() returns the maximum suitable size for the output
+buffers for almost all operations that can be done with I<pkey>.
+The primary documented use is with L<EVP_SignFinal(3)> and
+L<EVP_SealInit(3)>, but it isn't limited there. The returned size is
+also large enough for the output buffer of L<EVP_PKEY_sign(3)>,
+L<EVP_PKEY_encrypt(3)>, L<EVP_PKEY_decrypt(3)>, L<EVP_PKEY_derive(3)>.
+
+It must be stressed that, unless the documentation for the operation
+that's being performed says otherwise, the size returned by
+EVP_PKEY_get_size() is only preliminary and not exact, so the final
+contents of the target buffer may be smaller. It is therefore crucial
+to take note of the size given back by the function that performs the
+operation, such as L<EVP_PKEY_sign(3)> (the I<siglen> argument will
+receive that length), to avoid bugs.
+
+EVP_PKEY_get_bits() returns the cryptographic length of the cryptosystem
+to which the key in I<pkey> belongs, in bits. Note that the definition
+of cryptographic length is specific to the key cryptosystem.
+
+EVP_PKEY_get_security_bits() returns the number of security bits of the given
+I<pkey>, bits of security is defined in NIST SP800-57.
+
+=head1 RETURN VALUES
+
+EVP_PKEY_get_size(), EVP_PKEY_get_bits() and EVP_PKEY_get_security_bits()
+return a positive number, or 0 if this size isn't available.
+
+=head1 NOTES
+
+Most functions that have an output buffer and are mentioned with
+EVP_PKEY_get_size() have a functionality where you can pass NULL for the
+buffer and still pass a pointer to an integer and get the exact size
+that this function call delivers in the context that it's called in.
+This allows those functions to be called twice, once to find out the
+exact buffer size, then allocate the buffer in between, and call that
+function again actually output the data. For those functions, it
+isn't strictly necessary to call EVP_PKEY_get_size() to find out the
+buffer size, but may be useful in cases where it's desirable to know
+the upper limit in advance.
+
+It should also be especially noted that EVP_PKEY_get_size() shouldn't be
+used to get the output size for EVP_DigestSignFinal(), according to
+L<EVP_DigestSignFinal(3)/NOTES>.
+
+=head1 SEE ALSO
+
+L<EVP_SignFinal(3)>,
+L<EVP_SealInit(3)>,
+L<EVP_PKEY_sign(3)>,
+L<EVP_PKEY_encrypt(3)>,
+L<EVP_PKEY_decrypt(3)>,
+L<EVP_PKEY_derive(3)>
+
+=head1 HISTORY
+
+The EVP_PKEY_bits(), EVP_PKEY_security_bits(), and EVP_PKEY_size() functions
+were renamed to include C<get> in their names in OpenSSL 3.0, respectively.
+The old names are kept as non-deprecated alias macros.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_PKEY_gettable_params.pod b/doc/man3/EVP_PKEY_gettable_params.pod
new file mode 100644
index 000000000000..b51e4c4de185
--- /dev/null
+++ b/doc/man3/EVP_PKEY_gettable_params.pod
@@ -0,0 +1,136 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_gettable_params, EVP_PKEY_get_params,
+EVP_PKEY_get_int_param, EVP_PKEY_get_size_t_param,
+EVP_PKEY_get_bn_param, EVP_PKEY_get_utf8_string_param,
+EVP_PKEY_get_octet_string_param
+- retrieve key parameters from a key
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ const OSSL_PARAM *EVP_PKEY_gettable_params(EVP_PKEY *pkey);
+ int EVP_PKEY_get_params(const EVP_PKEY *pkey, OSSL_PARAM params[]);
+ int EVP_PKEY_get_int_param(const EVP_PKEY *pkey, const char *key_name,
+ int *out);
+ int EVP_PKEY_get_size_t_param(const EVP_PKEY *pkey, const char *key_name,
+ size_t *out);
+ int EVP_PKEY_get_bn_param(const EVP_PKEY *pkey, const char *key_name,
+ BIGNUM **bn);
+ int EVP_PKEY_get_utf8_string_param(const EVP_PKEY *pkey, const char *key_name,
+ char *str, size_t max_buf_sz,
+ size_t *out_len);
+ int EVP_PKEY_get_octet_string_param(const EVP_PKEY *pkey, const char *key_name,
+ unsigned char *buf, size_t max_buf_sz,
+ size_t *out_len);
+
+=head1 DESCRIPTION
+
+See L<OSSL_PARAM(3)> for information about parameters.
+
+EVP_PKEY_get_params() retrieves parameters from the key I<pkey>, according to
+the contents of I<params>.
+
+EVP_PKEY_gettable_params() returns a constant list of I<params> indicating
+the names and types of key parameters that can be retrieved.
+
+An L<OSSL_PARAM(3)> of type B<OSSL_PARAM_INTEGER> or
+B<OSSL_PARAM_UNSIGNED_INTEGER> is of arbitrary length. Such a parameter can be
+obtained using any of the functions EVP_PKEY_get_int_param(),
+EVP_PKEY_get_size_t_param() or EVP_PKEY_get_bn_param(). Attempting to
+obtain an integer value that does not fit into a native C B<int> type will cause
+EVP_PKEY_get_int_param() to fail. Similarly attempting to obtain an integer
+value that is negative or does not fit into a native C B<size_t> type using
+EVP_PKEY_get_size_t_param() will also fail.
+
+EVP_PKEY_get_int_param() retrieves a key I<pkey> integer value I<*out>
+associated with a name of I<key_name> if it fits into C<int> type. For
+parameters that do not fit into C<int> use EVP_PKEY_get_bn_param().
+
+EVP_PKEY_get_size_t_param() retrieves a key I<pkey> size_t value I<*out>
+associated with a name of I<key_name> if it fits into C<size_t> type. For
+parameters that do not fit into C<size_t> use EVP_PKEY_get_bn_param().
+
+EVP_PKEY_get_bn_param() retrieves a key I<pkey> BIGNUM value I<**bn>
+associated with a name of I<key_name>. If I<*bn> is NULL then the BIGNUM
+is allocated by the method.
+
+EVP_PKEY_get_utf8_string_param() get a key I<pkey> UTF8 string value into a
+buffer I<str> of maximum size I<max_buf_sz> associated with a name of
+I<key_name>. The maximum size must be large enough to accomodate the string
+value including a terminating NUL byte, or this function will fail.
+If I<out_len> is not NULL, I<*out_len> is set to the length of the string
+not including the terminating NUL byte. The required buffer size not including
+the terminating NUL byte can be obtained from I<*out_len> by calling the
+function with I<str> set to NULL.
+
+EVP_PKEY_get_octet_string_param() get a key I<pkey>'s octet string value into a
+buffer I<buf> of maximum size I<max_buf_sz> associated with a name of I<key_name>.
+If I<out_len> is not NULL, I<*out_len> is set to the length of the contents.
+The required buffer size can be obtained from I<*out_len> by calling the
+function with I<buf> set to NULL.
+
+=head1 NOTES
+
+These functions only work for B<EVP_PKEY>s that contain a provider side key.
+
+=head1 RETURN VALUES
+
+EVP_PKEY_gettable_params() returns NULL on error or if it is not supported.
+
+All other methods return 1 if a value associated with the key's I<key_name> was
+successfully returned, or 0 if there was an error.
+An error may be returned by methods EVP_PKEY_get_utf8_string_param() and
+EVP_PKEY_get_octet_string_param() if I<max_buf_sz> is not big enough to hold the
+value. If I<out_len> is not NULL, I<*out_len> will be assigned the required
+buffer size to hold the value.
+
+=head1 EXAMPLES
+
+ #include <openssl/evp.h>
+
+ char curve_name[64];
+ unsigned char pub[256];
+ BIGNUM *bn_priv = NULL;
+
+ /*
+ * NB: assumes 'key' is set up before the next step. In this example the key
+ * is an EC key.
+ */
+
+ if (!EVP_PKEY_get_utf8_string_param(key, OSSL_PKEY_PARAM_GROUP_NAME,
+ curve_name, sizeof(curve_name), &len)) {
+ /* Error */
+ }
+ if (!EVP_PKEY_get_octet_string_param(key, OSSL_PKEY_PARAM_PUB_KEY,
+ pub, sizeof(pub), &len)) {
+ /* Error */
+ }
+ if (!EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_PRIV_KEY, &bn_priv)) {
+ /* Error */
+ }
+
+ BN_clear_free(bn_priv);
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_new(3)>, L<provider-keymgmt(7)>, L<OSSL_PARAM(3)>
+
+=head1 HISTORY
+
+These functions were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
+
diff --git a/doc/man3/EVP_PKEY_is_a.pod b/doc/man3/EVP_PKEY_is_a.pod
new file mode 100644
index 000000000000..8bada052fa6e
--- /dev/null
+++ b/doc/man3/EVP_PKEY_is_a.pod
@@ -0,0 +1,113 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_is_a, EVP_PKEY_can_sign, EVP_PKEY_type_names_do_all,
+EVP_PKEY_get0_type_name, EVP_PKEY_get0_description, EVP_PKEY_get0_provider
+- key type and capabilities functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_PKEY_is_a(const EVP_PKEY *pkey, const char *name);
+ int EVP_PKEY_can_sign(const EVP_PKEY *pkey);
+ int EVP_PKEY_type_names_do_all(const EVP_PKEY *pkey,
+ void (*fn)(const char *name, void *data),
+ void *data);
+ const char *EVP_PKEY_get0_type_name(const EVP_PKEY *key);
+ const char *EVP_PKEY_get0_description(const EVP_PKEY *key);
+ const OSSL_PROVIDER *EVP_PKEY_get0_provider(const EVP_PKEY *key);
+
+=head1 DESCRIPTION
+
+EVP_PKEY_is_a() checks if the key type of I<pkey> is I<name>.
+
+EVP_PKEY_can_sign() checks if the functionality for the key type of
+I<pkey> supports signing. No other check is done, such as whether
+I<pkey> contains a private key.
+
+EVP_PKEY_type_names_do_all() traverses all names for I<pkey>'s key type, and
+calls I<fn> with each name and I<data>. For example, an RSA B<EVP_PKEY> may
+be named both C<RSA> and C<rsaEncryption>.
+The order of the names depends on the provider implementation that holds
+the key.
+
+EVP_PKEY_get0_type_name() returns the first key type name that is found
+for the given I<pkey>. Note that the I<pkey> may have multiple synonyms
+associated with it. In this case it depends on the provider implementation
+that holds the key which one will be returned.
+Ownership of the returned string is retained by the I<pkey> object and should
+not be freed by the caller.
+
+EVP_PKEY_get0_description() returns a description of the type of B<EVP_PKEY>,
+meant for display and human consumption. The description is at the
+discretion of the key type implementation.
+
+EVP_PKEY_get0_provider() returns the provider of the B<EVP_PKEY>'s
+L<EVP_KEYMGMT(3)>.
+
+=head1 RETURN VALUES
+
+EVP_PKEY_is_a() returns 1 if I<pkey> has the key type I<name>,
+otherwise 0.
+
+EVP_PKEY_can_sign() returns 1 if the I<pkey> key type functionality
+supports signing, otherwise 0.
+
+EVP_PKEY_get0_type_name() returns the name that is found or NULL on error.
+
+EVP_PKEY_get0_description() returns the description if found or NULL if not.
+
+EVP_PKEY_get0_provider() returns the provider if found or NULL if not.
+
+EVP_PKEY_type_names_do_all() returns 1 if the callback was called for all
+names. A return value of 0 means that the callback was not called for any
+names.
+
+=head1 EXAMPLES
+
+=head2 EVP_PKEY_is_a()
+
+The loaded providers and what key types they support will ultimately
+determine what I<name> is possible to use with EVP_PKEY_is_a(). We do know
+that the default provider supports RSA, DH, DSA and EC keys, so we can use
+this as an crude example:
+
+ #include <openssl/evp.h>
+
+ ...
+ /* |pkey| is an EVP_PKEY* */
+ if (EVP_PKEY_is_a(pkey, "RSA")) {
+ BIGNUM *modulus = NULL;
+ if (EVP_PKEY_get_bn_param(pkey, "n", &modulus))
+ /* do whatever with the modulus */
+ BN_free(modulus);
+ }
+
+=head2 EVP_PKEY_can_sign()
+
+ #include <openssl/evp.h>
+
+ ...
+ /* |pkey| is an EVP_PKEY* */
+ if (!EVP_PKEY_can_sign(pkey)) {
+ fprintf(stderr, "Not a signing key!");
+ exit(1);
+ }
+ /* Sign something... */
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_PKEY_keygen.pod b/doc/man3/EVP_PKEY_keygen.pod
index 82df15363035..433123618606 100644
--- a/doc/man3/EVP_PKEY_keygen.pod
+++ b/doc/man3/EVP_PKEY_keygen.pod
@@ -2,22 +2,27 @@
=head1 NAME
-EVP_PKEY_keygen_init, EVP_PKEY_keygen, EVP_PKEY_paramgen_init,
-EVP_PKEY_paramgen, EVP_PKEY_CTX_set_cb, EVP_PKEY_CTX_get_cb,
+EVP_PKEY_Q_keygen,
+EVP_PKEY_keygen_init, EVP_PKEY_paramgen_init, EVP_PKEY_generate,
+EVP_PKEY_CTX_set_cb, EVP_PKEY_CTX_get_cb,
EVP_PKEY_CTX_get_keygen_info, EVP_PKEY_CTX_set_app_data,
EVP_PKEY_CTX_get_app_data,
-EVP_PKEY_gen_cb, EVP_PKEY_check, EVP_PKEY_public_check,
-EVP_PKEY_param_check
+EVP_PKEY_gen_cb,
+EVP_PKEY_paramgen, EVP_PKEY_keygen
- key and parameter generation and check functions
=head1 SYNOPSIS
#include <openssl/evp.h>
+ EVP_PKEY *EVP_PKEY_Q_keygen(OSSL_LIB_CTX *libctx, const char *propq,
+ const char *type, ...);
+
int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx);
- int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_generate(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
+ int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx);
@@ -29,30 +34,53 @@ EVP_PKEY_param_check
void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data);
void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx);
- int EVP_PKEY_check(EVP_PKEY_CTX *ctx);
- int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx);
- int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx);
-
=head1 DESCRIPTION
-The EVP_PKEY_keygen_init() function initializes a public key algorithm
-context using key B<pkey> for a key generation operation.
+Generating keys is sometimes straight forward, just generate the key's
+numbers and be done with it. However, there are certain key types that need
+key parameters, often called domain parameters but not necessarily limited
+to that, that also need to be generated. In addition to this, the caller
+may want to set user provided generation parameters that further affect key
+parameter or key generation, such as the desired key size.
+
+To flexibly allow all that's just been described, key parameter and key
+generation is divided into an initialization of a key algorithm context,
+functions to set user provided parameters, and finally the key parameter or
+key generation function itself.
+
+The key algorithm context must be created using L<EVP_PKEY_CTX_new(3)> or
+variants thereof, see that manual for details.
-The EVP_PKEY_keygen() function performs a key generation operation, the
-generated key is written to B<ppkey>.
+EVP_PKEY_keygen_init() initializes a public key algorithm context I<ctx>
+for a key generation operation.
-The functions EVP_PKEY_paramgen_init() and EVP_PKEY_paramgen() are similar
-except parameters are generated.
+EVP_PKEY_paramgen_init() is similar to EVP_PKEY_keygen_init() except key
+parameters are generated.
+
+After initialization, generation parameters may be provided with
+L<EVP_PKEY_CTX_ctrl(3)> or L<EVP_PKEY_CTX_set_params(3)>, or any other
+function described in those manuals.
+
+EVP_PKEY_generate() performs the generation operation, the resulting key
+parameters or key are written to I<*ppkey>. If I<*ppkey> is NULL when this
+function is called, it will be allocated, and should be freed by the caller
+when no longer useful, using L<EVP_PKEY_free(3)>.
+
+EVP_PKEY_paramgen() and EVP_PKEY_keygen() do exactly the same thing as
+EVP_PKEY_generate(), after checking that the corresponding EVP_PKEY_paramgen_init()
+or EVP_PKEY_keygen_init() was used to initialize I<ctx>.
+These are older functions that are kept for backward compatibility.
+It is safe to use EVP_PKEY_generate() instead.
The function EVP_PKEY_set_cb() sets the key or parameter generation callback
-to B<cb>. The function EVP_PKEY_CTX_get_cb() returns the key or parameter
+to I<cb>. The function EVP_PKEY_CTX_get_cb() returns the key or parameter
generation callback.
The function EVP_PKEY_CTX_get_keygen_info() returns parameters associated
-with the generation operation. If B<idx> is -1 the total number of
+with the generation operation. If I<idx> is -1 the total number of
parameters available is returned. Any non negative value returns the value of
that parameter. EVP_PKEY_CTX_gen_keygen_info() with a nonnegative value for
-B<idx> should only be called within the generation callback.
+I<idx> should only be called within the generation callback.
If the callback returns 0 then the key generation operation is aborted and an
error occurs. This might occur during a time consuming operation where
@@ -63,17 +91,26 @@ and retrieve an opaque pointer. This can be used to set some application
defined value which can be retrieved in the callback: for example a handle
which is used to update a "progress dialog".
-EVP_PKEY_check() validates the key-pair given by B<ctx>. This function first tries
-to use customized key check method in B<EVP_PKEY_METHOD> if it's present; otherwise
-it calls a default one defined in B<EVP_PKEY_ASN1_METHOD>.
+EVP_PKEY_Q_keygen() abstracts from the explicit use of B<EVP_PKEY_CTX> while
+providing a 'quick' but limited way of generating a new asymmetric key pair.
+It provides shorthands for simple and common cases of key generation.
+As usual, the library context I<libctx> and property query I<propq>
+can be given for fetching algorithms from providers.
+If I<type> is C<RSA>,
+a B<size_t> parameter must be given to specify the size of the RSA key.
+If I<type> is C<EC>,
+a string parameter must be given to specify the name of the EC curve.
+If I<type> is C<X25519>, C<X448>, C<ED25519>, C<ED448>, or C<SM2>
+no further parameter is needed.
-EVP_PKEY_public_check() validates the public component of the key-pair given by B<ctx>.
-This function first tries to use customized key check method in B<EVP_PKEY_METHOD>
-if it's present; otherwise it calls a default one defined in B<EVP_PKEY_ASN1_METHOD>.
+=head1 RETURN VALUES
-EVP_PKEY_param_check() validates the algorithm parameters of the key-pair given by B<ctx>.
-This function first tries to use customized key check method in B<EVP_PKEY_METHOD>
-if it's present; otherwise it calls a default one defined in B<EVP_PKEY_ASN1_METHOD>.
+EVP_PKEY_keygen_init(), EVP_PKEY_paramgen_init(), EVP_PKEY_keygen() and
+EVP_PKEY_paramgen() return 1 for success and 0 or a negative value for failure.
+In particular a return value of -2 indicates the operation is not supported by
+the public key algorithm.
+
+EVP_PKEY_Q_keygen() returns an B<EVP_PKEY>, or NULL on failure.
=head1 NOTES
@@ -99,17 +136,6 @@ public key components and parameters (if any). An OpenSSL private key is
equivalent to what some libraries call a "key pair". A private key can be used
in functions which require the use of a public key or parameters.
-=head1 RETURN VALUES
-
-EVP_PKEY_keygen_init(), EVP_PKEY_paramgen_init(), EVP_PKEY_keygen() and
-EVP_PKEY_paramgen() return 1 for success and 0 or a negative value for failure.
-In particular a return value of -2 indicates the operation is not supported by
-the public key algorithm.
-
-EVP_PKEY_check(), EVP_PKEY_public_check() and EVP_PKEY_param_check() return 1
-for success or others for failure. They return -2 if the operation is not supported
-for the specific algorithm.
-
=head1 EXAMPLES
Generate a 2048 bit RSA key:
@@ -179,6 +205,7 @@ Example of generation callback for OpenSSL public key implementations:
=head1 SEE ALSO
+L<EVP_RSA_gen(3)>, L<EVP_EC_gen(3)>,
L<EVP_PKEY_CTX_new(3)>,
L<EVP_PKEY_encrypt(3)>,
L<EVP_PKEY_decrypt(3)>,
@@ -189,16 +216,19 @@ L<EVP_PKEY_derive(3)>
=head1 HISTORY
-These functions were added in OpenSSL 1.0.0.
+EVP_PKEY_keygen_init(), int EVP_PKEY_paramgen_init(), EVP_PKEY_keygen(),
+EVP_PKEY_paramgen(), EVP_PKEY_gen_cb(), EVP_PKEY_CTX_set_cb(),
+EVP_PKEY_CTX_get_cb(), EVP_PKEY_CTX_get_keygen_info(),
+EVP_PKEY_CTX_set_app_data() and EVP_PKEY_CTX_get_app_data() were added in
+OpenSSL 1.0.0.
-EVP_PKEY_check(), EVP_PKEY_public_check() and EVP_PKEY_param_check() were added
-in OpenSSL 1.1.1.
+EVP_PKEY_Q_keygen() and EVP_PKEY_generate() were added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_meth_get_count.pod b/doc/man3/EVP_PKEY_meth_get_count.pod
index 4d2eab50fe0a..2e2a3fc13e31 100644
--- a/doc/man3/EVP_PKEY_meth_get_count.pod
+++ b/doc/man3/EVP_PKEY_meth_get_count.pod
@@ -8,6 +8,10 @@ EVP_PKEY_meth_get_count, EVP_PKEY_meth_get0, EVP_PKEY_meth_get0_info - enumerate
#include <openssl/evp.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
size_t EVP_PKEY_meth_get_count(void);
const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx);
void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags,
@@ -15,6 +19,9 @@ EVP_PKEY_meth_get_count, EVP_PKEY_meth_get0, EVP_PKEY_meth_get0_info - enumerate
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use the OSSL_PROVIDER APIs.
+
EVP_PKEY_meth_count() returns a count of the number of public key methods
available: it includes standard methods and any methods added by the
application.
@@ -38,11 +45,15 @@ EVP_PKEY_meth_get0_info() does not return a value.
L<EVP_PKEY_new(3)>
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2002-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_meth_new.pod b/doc/man3/EVP_PKEY_meth_new.pod
index 106873d9acc1..db0b09f855fc 100644
--- a/doc/man3/EVP_PKEY_meth_new.pod
+++ b/doc/man3/EVP_PKEY_meth_new.pod
@@ -29,6 +29,10 @@ EVP_PKEY_meth_remove
#include <openssl/evp.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
typedef struct evp_pkey_method_st EVP_PKEY_METHOD;
EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags);
@@ -42,7 +46,7 @@ EVP_PKEY_meth_remove
int (*init) (EVP_PKEY_CTX *ctx));
void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth,
int (*copy) (EVP_PKEY_CTX *dst,
- EVP_PKEY_CTX *src));
+ const EVP_PKEY_CTX *src));
void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth,
void (*cleanup) (EVP_PKEY_CTX *ctx));
void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth,
@@ -216,13 +220,13 @@ EVP_PKEY_meth_remove
int (**pctrl_str) (EVP_PKEY_CTX *ctx,
const char *type,
const char *value));
- void EVP_PKEY_meth_get_digestsign(EVP_PKEY_METHOD *pmeth,
+ void EVP_PKEY_meth_get_digestsign(const EVP_PKEY_METHOD *pmeth,
int (**digestsign) (EVP_MD_CTX *ctx,
unsigned char *sig,
size_t *siglen,
const unsigned char *tbs,
size_t tbslen));
- void EVP_PKEY_meth_get_digestverify(EVP_PKEY_METHOD *pmeth,
+ void EVP_PKEY_meth_get_digestverify(const EVP_PKEY_METHOD *pmeth,
int (**digestverify) (EVP_MD_CTX *ctx,
const unsigned char *sig,
size_t siglen,
@@ -234,12 +238,15 @@ EVP_PKEY_meth_remove
int (**pcheck) (EVP_PKEY *pkey));
void EVP_PKEY_meth_get_param_check(const EVP_PKEY_METHOD *pmeth,
int (**pcheck) (EVP_PKEY *pkey));
- void EVP_PKEY_meth_get_digest_custom(EVP_PKEY_METHOD *pmeth,
+ void EVP_PKEY_meth_get_digest_custom(const EVP_PKEY_METHOD *pmeth,
int (**pdigest_custom) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx));
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use the OSSL_PROVIDER APIs.
+
B<EVP_PKEY_METHOD> is a structure which holds a set of methods for a
specific public key cryptographic algorithm. Those methods are usually
used to perform different jobs, such as generating a key, signing or
@@ -259,7 +266,7 @@ The methods are the underlying implementations of a particular public key
algorithm present by the B<EVP_PKEY_CTX> object.
int (*init) (EVP_PKEY_CTX *ctx);
- int (*copy) (EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src);
+ int (*copy) (EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src);
void (*cleanup) (EVP_PKEY_CTX *ctx);
The init() method is called to initialize algorithm-specific data when a new
@@ -440,11 +447,18 @@ All EVP_PKEY_meth_set and EVP_PKEY_meth_get functions have no return
values. For the 'get' functions, function pointers are returned by
arguments.
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
+The signature of the I<copy> functional argument of EVP_PKEY_meth_set_copy()
+has changed in OpenSSL 3.0 so its I<src> parameter is now constified.
+
=head1 COPYRIGHT
-Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_new.pod b/doc/man3/EVP_PKEY_new.pod
index faf5a117e5ae..0ea7062f0182 100644
--- a/doc/man3/EVP_PKEY_new.pod
+++ b/doc/man3/EVP_PKEY_new.pod
@@ -2,10 +2,14 @@
=head1 NAME
+EVP_PKEY,
EVP_PKEY_new,
EVP_PKEY_up_ref,
+EVP_PKEY_dup,
EVP_PKEY_free,
+EVP_PKEY_new_raw_private_key_ex,
EVP_PKEY_new_raw_private_key,
+EVP_PKEY_new_raw_public_key_ex,
EVP_PKEY_new_raw_public_key,
EVP_PKEY_new_CMAC_key,
EVP_PKEY_new_mac_key,
@@ -17,16 +21,27 @@ EVP_PKEY_get_raw_public_key
#include <openssl/evp.h>
+ typedef evp_pkey_st EVP_PKEY;
+
EVP_PKEY *EVP_PKEY_new(void);
int EVP_PKEY_up_ref(EVP_PKEY *key);
+ EVP_PKEY *EVP_PKEY_dup(EVP_PKEY *key);
void EVP_PKEY_free(EVP_PKEY *key);
+ EVP_PKEY *EVP_PKEY_new_raw_private_key_ex(OSSL_LIB_CTX *libctx,
+ const char *keytype,
+ const char *propq,
+ const unsigned char *key,
+ size_t keylen);
EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
const unsigned char *key, size_t keylen);
+ EVP_PKEY *EVP_PKEY_new_raw_public_key_ex(OSSL_LIB_CTX *libctx,
+ const char *keytype,
+ const char *propq,
+ const unsigned char *key,
+ size_t keylen);
EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
const unsigned char *key, size_t keylen);
- EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
- size_t len, const EVP_CIPHER *cipher);
EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e, const unsigned char *key,
int keylen);
@@ -35,63 +50,116 @@ EVP_PKEY_get_raw_public_key
int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub,
size_t *len);
+The following function has been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
+ size_t len, const EVP_CIPHER *cipher);
+
=head1 DESCRIPTION
+B<EVP_PKEY> is a generic structure to hold diverse types of asymmetric keys
+(also known as "key pairs"), and can be used for diverse operations, like
+signing, verifying signatures, key derivation, etc. The asymmetric keys
+themselves are often refered to as the "internal key", and are handled by
+backends, such as providers (through L<EVP_KEYMGMT(3)>) or B<ENGINE>s.
+
+Conceptually, an B<EVP_PKEY> internal key may hold a private key, a public
+key, or both (a keypair), and along with those, key parameters if the key type
+requires them. The presence of these components determine what operations can
+be made; for example, signing normally requires the presence of a private key,
+and verifying normally requires the presence of a public key.
+
+=for comment ED signature require both the private and public key...
+
+B<EVP_PKEY> has also been used for MAC algorithm that were conceived as
+producing signatures, although not being public key algorithms; "POLY1305",
+"SIPHASH", "HMAC", "CMAC". This usage is considered legacy and is discouraged
+in favor of the L<EVP_MAC(3)> API.
+
The EVP_PKEY_new() function allocates an empty B<EVP_PKEY> structure which is
used by OpenSSL to store public and private keys. The reference count is set to
B<1>.
-EVP_PKEY_up_ref() increments the reference count of B<key>.
-
-EVP_PKEY_free() decrements the reference count of B<key> and, if the reference
-count is zero, frees it up. If B<key> is NULL, nothing is done.
-
-EVP_PKEY_new_raw_private_key() allocates a new B<EVP_PKEY>. If B<e> is non-NULL
-then the new B<EVP_PKEY> structure is associated with the engine B<e>. The
-B<type> argument indicates what kind of key this is. The value should be a NID
-for a public key algorithm that supports raw private keys, i.e. one of
-B<EVP_PKEY_HMAC>, B<EVP_PKEY_POLY1305>, B<EVP_PKEY_SIPHASH>, B<EVP_PKEY_X25519>,
-B<EVP_PKEY_ED25519>, B<EVP_PKEY_X448> or B<EVP_PKEY_ED448>. B<key> points to the
-raw private key data for this B<EVP_PKEY> which should be of length B<keylen>.
-The length should be appropriate for the type of the key. The public key data
-will be automatically derived from the given private key data (if appropriate
-for the algorithm type).
+EVP_PKEY_up_ref() increments the reference count of I<key>.
+
+EVP_PKEY_dup() duplicates the I<key>. The I<key> must not be ENGINE based or
+a raw key, otherwise the duplication will fail.
+
+EVP_PKEY_free() decrements the reference count of I<key> and, if the reference
+count is zero, frees it up. If I<key> is NULL, nothing is done.
+
+EVP_PKEY_new_raw_private_key_ex() allocates a new B<EVP_PKEY>. Unless an
+engine should be used for the key type, a provider for the key is found using
+the library context I<libctx> and the property query string I<propq>. The
+I<keytype> argument indicates what kind of key this is. The value should be a
+string for a public key algorithm that supports raw private keys, i.e one of
+"X25519", "ED25519", "X448" or "ED448". I<key> points to the raw private key
+data for this B<EVP_PKEY> which should be of length I<keylen>. The length
+should be appropriate for the type of the key. The public key data will be
+automatically derived from the given private key data (if appropriate for the
+algorithm type).
+
+EVP_PKEY_new_raw_private_key() does the same as
+EVP_PKEY_new_raw_private_key_ex() except that the default library context and
+default property query are used instead. If I<e> is non-NULL then the new
+B<EVP_PKEY> structure is associated with the engine I<e>. The I<type> argument
+indicates what kind of key this is. The value should be a NID for a public key
+algorithm that supports raw private keys, i.e. one of B<EVP_PKEY_X25519>,
+B<EVP_PKEY_ED25519>, B<EVP_PKEY_X448> or B<EVP_PKEY_ED448>.
+
+EVP_PKEY_new_raw_private_key_ex() and EVP_PKEY_new_raw_private_key() may also
+be used with most MACs implemented as public key algorithms, so key types such
+as "HMAC", "POLY1305", "SIPHASH", or their NID form B<EVP_PKEY_POLY1305>,
+B<EVP_PKEY_SIPHASH>, B<EVP_PKEY_HMAC> are also accepted. This usage is,
+as mentioned above, discouraged in favor of the L<EVP_MAC(3)> API.
+
+EVP_PKEY_new_raw_public_key_ex() works in the same way as
+EVP_PKEY_new_raw_private_key_ex() except that I<key> points to the raw
+public key data. The B<EVP_PKEY> structure will be initialised without any
+private key information. Algorithm types that support raw public keys are
+"X25519", "ED25519", "X448" or "ED448".
EVP_PKEY_new_raw_public_key() works in the same way as
-EVP_PKEY_new_raw_private_key() except that B<key> points to the raw public key
+EVP_PKEY_new_raw_private_key() except that I<key> points to the raw public key
data. The B<EVP_PKEY> structure will be initialised without any private key
information. Algorithm types that support raw public keys are
B<EVP_PKEY_X25519>, B<EVP_PKEY_ED25519>, B<EVP_PKEY_X448> or B<EVP_PKEY_ED448>.
-EVP_PKEY_new_CMAC_key() works in the same way as EVP_PKEY_new_raw_private_key()
-except it is only for the B<EVP_PKEY_CMAC> algorithm type. In addition to the
-raw private key data, it also takes a cipher algorithm to be used during
-creation of a CMAC in the B<cipher> argument. The cipher should be a standard
-encryption only cipher. For example AEAD and XTS ciphers should not be used.
-
EVP_PKEY_new_mac_key() works in the same way as EVP_PKEY_new_raw_private_key().
New applications should use EVP_PKEY_new_raw_private_key() instead.
-EVP_PKEY_get_raw_private_key() fills the buffer provided by B<priv> with raw
-private key data. The size of the B<priv> buffer should be in B<*len> on entry
-to the function, and on exit B<*len> is updated with the number of bytes
-actually written. If the buffer B<priv> is NULL then B<*len> is populated with
+EVP_PKEY_get_raw_private_key() fills the buffer provided by I<priv> with raw
+private key data. The size of the I<priv> buffer should be in I<*len> on entry
+to the function, and on exit I<*len> is updated with the number of bytes
+actually written. If the buffer I<priv> is NULL then I<*len> is populated with
the number of bytes required to hold the key. The calling application is
responsible for ensuring that the buffer is large enough to receive the private
key data. This function only works for algorithms that support raw private keys.
Currently this is: B<EVP_PKEY_HMAC>, B<EVP_PKEY_POLY1305>, B<EVP_PKEY_SIPHASH>,
B<EVP_PKEY_X25519>, B<EVP_PKEY_ED25519>, B<EVP_PKEY_X448> or B<EVP_PKEY_ED448>.
-EVP_PKEY_get_raw_public_key() fills the buffer provided by B<pub> with raw
-public key data. The size of the B<pub> buffer should be in B<*len> on entry
-to the function, and on exit B<*len> is updated with the number of bytes
-actually written. If the buffer B<pub> is NULL then B<*len> is populated with
+EVP_PKEY_get_raw_public_key() fills the buffer provided by I<pub> with raw
+public key data. The size of the I<pub> buffer should be in I<*len> on entry
+to the function, and on exit I<*len> is updated with the number of bytes
+actually written. If the buffer I<pub> is NULL then I<*len> is populated with
the number of bytes required to hold the key. The calling application is
responsible for ensuring that the buffer is large enough to receive the public
key data. This function only works for algorithms that support raw public keys.
Currently this is: B<EVP_PKEY_X25519>, B<EVP_PKEY_ED25519>, B<EVP_PKEY_X448> or
B<EVP_PKEY_ED448>.
+EVP_PKEY_new_CMAC_key() works in the same way as EVP_PKEY_new_raw_private_key()
+except it is only for the B<EVP_PKEY_CMAC> algorithm type. In addition to the
+raw private key data, it also takes a cipher algorithm to be used during
+creation of a CMAC in the B<cipher> argument. The cipher should be a standard
+encryption-only cipher. For example AEAD and XTS ciphers should not be used.
+
+Applications should use the L<EVP_MAC(3)> API instead
+and set the B<OSSL_MAC_PARAM_CIPHER> parameter on the B<EVP_MAC_CTX> object
+with the name of the cipher being used.
+
=head1 NOTES
The B<EVP_PKEY> structure is used by various OpenSSL functions which require a
@@ -99,22 +167,24 @@ general private key without reference to any particular algorithm.
The structure returned by EVP_PKEY_new() is empty. To add a private or public
key to this empty structure use the appropriate functions described in
-L<EVP_PKEY_set1_RSA(3)>, L<EVP_PKEY_set1_DSA>, L<EVP_PKEY_set1_DH> or
-L<EVP_PKEY_set1_EC_KEY>.
+L<EVP_PKEY_set1_RSA(3)>, L<EVP_PKEY_set1_DSA(3)>, L<EVP_PKEY_set1_DH(3)> or
+L<EVP_PKEY_set1_EC_KEY(3)>.
=head1 RETURN VALUES
EVP_PKEY_new(), EVP_PKEY_new_raw_private_key(), EVP_PKEY_new_raw_public_key(),
EVP_PKEY_new_CMAC_key() and EVP_PKEY_new_mac_key() return either the newly
-allocated B<EVP_PKEY> structure or B<NULL> if an error occurred.
+allocated B<EVP_PKEY> structure or NULL if an error occurred.
+
+EVP_PKEY_dup() returns the key duplicate or NULL if an error occurred.
EVP_PKEY_up_ref(), EVP_PKEY_get_raw_private_key() and
EVP_PKEY_get_raw_public_key() return 1 for success and 0 for failure.
=head1 SEE ALSO
-L<EVP_PKEY_set1_RSA(3)>, L<EVP_PKEY_set1_DSA>, L<EVP_PKEY_set1_DH> or
-L<EVP_PKEY_set1_EC_KEY>
+L<EVP_PKEY_set1_RSA(3)>, L<EVP_PKEY_set1_DSA(3)>, L<EVP_PKEY_set1_DH(3)> or
+L<EVP_PKEY_set1_EC_KEY(3)>
=head1 HISTORY
@@ -128,11 +198,21 @@ EVP_PKEY_new_raw_private_key(), EVP_PKEY_new_raw_public_key(),
EVP_PKEY_new_CMAC_key(), EVP_PKEY_new_raw_private_key() and
EVP_PKEY_get_raw_public_key() functions were added in OpenSSL 1.1.1.
+The EVP_PKEY_dup(), EVP_PKEY_new_raw_private_key_ex(), and
+EVP_PKEY_new_raw_public_key_ex()
+functions were added in OpenSSL 3.0.
+
+The EVP_PKEY_new_CMAC_key() was deprecated in OpenSSL 3.0.
+
+The documentation of B<EVP_PKEY> was amended in OpenSSL 3.0 to allow there to
+be the private part of the keypair without the public part, where this was
+previously implied to be disallowed.
+
=head1 COPYRIGHT
-Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_print_private.pod b/doc/man3/EVP_PKEY_print_private.pod
index e0750c7eedbb..3ea1873d8359 100644
--- a/doc/man3/EVP_PKEY_print_private.pod
+++ b/doc/man3/EVP_PKEY_print_private.pod
@@ -2,7 +2,9 @@
=head1 NAME
-EVP_PKEY_print_public, EVP_PKEY_print_private, EVP_PKEY_print_params - public key algorithm printing routines
+EVP_PKEY_print_public, EVP_PKEY_print_private, EVP_PKEY_print_params,
+EVP_PKEY_print_public_fp, EVP_PKEY_print_private_fp,
+EVP_PKEY_print_params_fp - public key algorithm printing routines
=head1 SYNOPSIS
@@ -10,25 +12,35 @@ EVP_PKEY_print_public, EVP_PKEY_print_private, EVP_PKEY_print_params - public ke
int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx);
+ int EVP_PKEY_print_public_fp(FILE *fp, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx);
int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx);
+ int EVP_PKEY_print_private_fp(FILE *fp, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx);
int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx);
+ int EVP_PKEY_print_params_fp(FILE *fp, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx);
=head1 DESCRIPTION
The functions EVP_PKEY_print_public(), EVP_PKEY_print_private() and
EVP_PKEY_print_params() print out the public, private or parameter components
-of key B<pkey> respectively. The key is sent to BIO B<out> in human readable
-form. The parameter B<indent> indicated how far the printout should be indented.
+of key I<pkey> respectively. The key is sent to B<BIO> I<out> in human readable
+form. The parameter I<indent> indicates how far the printout should be indented.
-The B<pctx> parameter allows the print output to be finely tuned by using
-ASN1 printing options. If B<pctx> is set to NULL then default values will
+The I<pctx> parameter allows the print output to be finely tuned by using
+ASN1 printing options. If I<pctx> is set to NULL then default values will
be used.
+The functions EVP_PKEY_print_public_fp(), EVP_PKEY_print_private_fp() and
+EVP_PKEY_print_params_fp() do the same as the B<BIO> based functions
+but use B<FILE> I<fp> instead.
+
=head1 NOTES
-Currently no public key algorithms include any options in the B<pctx> parameter.
+Currently no public key algorithms include any options in the I<pctx> parameter.
If the key does not include all the components indicated by the function then
only those contained in the key will be printed. For example passing a public
@@ -47,13 +59,17 @@ L<EVP_PKEY_keygen(3)>
=head1 HISTORY
-These functions were added in OpenSSL 1.0.0.
+The functions EVP_PKEY_print_public(), EVP_PKEY_print_private(),
+and EVP_PKEY_print_params() were added in OpenSSL 1.0.0.
+
+The functions EVP_PKEY_print_public_fp(), EVP_PKEY_print_private_fp(),
+and EVP_PKEY_print_params_fp() were added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2006-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_set1_RSA.pod b/doc/man3/EVP_PKEY_set1_RSA.pod
index d571e58d95ba..c0366d34fcee 100644
--- a/doc/man3/EVP_PKEY_set1_RSA.pod
+++ b/doc/man3/EVP_PKEY_set1_RSA.pod
@@ -8,13 +8,26 @@ EVP_PKEY_get0_RSA, EVP_PKEY_get0_DSA, EVP_PKEY_get0_DH, EVP_PKEY_get0_EC_KEY,
EVP_PKEY_assign_RSA, EVP_PKEY_assign_DSA, EVP_PKEY_assign_DH,
EVP_PKEY_assign_EC_KEY, EVP_PKEY_assign_POLY1305, EVP_PKEY_assign_SIPHASH,
EVP_PKEY_get0_hmac, EVP_PKEY_get0_poly1305, EVP_PKEY_get0_siphash,
-EVP_PKEY_type, EVP_PKEY_id, EVP_PKEY_base_id, EVP_PKEY_set_alias_type,
-EVP_PKEY_set1_engine, EVP_PKEY_get0_engine - EVP_PKEY assignment functions
+EVP_PKEY_get0, EVP_PKEY_type, EVP_PKEY_get_id, EVP_PKEY_get_base_id,
+EVP_PKEY_set1_engine, EVP_PKEY_get0_engine,
+EVP_PKEY_id, EVP_PKEY_base_id -
+EVP_PKEY assignment functions
=head1 SYNOPSIS
#include <openssl/evp.h>
+ int EVP_PKEY_get_id(const EVP_PKEY *pkey);
+ int EVP_PKEY_get_base_id(const EVP_PKEY *pkey);
+ int EVP_PKEY_type(int type);
+
+ #define EVP_PKEY_id EVP_PKEY_get_id
+ #define EVP_PKEY_base_id EVP_PKEY_get_base_id
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key);
int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key);
int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key);
@@ -28,10 +41,11 @@ EVP_PKEY_set1_engine, EVP_PKEY_get0_engine - EVP_PKEY assignment functions
const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len);
const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len);
const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len);
- RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey);
- DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey);
- DH *EVP_PKEY_get0_DH(EVP_PKEY *pkey);
- EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey);
+ const RSA *EVP_PKEY_get0_RSA(const EVP_PKEY *pkey);
+ const DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey);
+ const DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey);
+ const EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey);
+ void *EVP_PKEY_get0(const EVP_PKEY *pkey);
int EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key);
int EVP_PKEY_assign_DSA(EVP_PKEY *pkey, DSA *key);
@@ -40,76 +54,126 @@ EVP_PKEY_set1_engine, EVP_PKEY_get0_engine - EVP_PKEY assignment functions
int EVP_PKEY_assign_POLY1305(EVP_PKEY *pkey, ASN1_OCTET_STRING *key);
int EVP_PKEY_assign_SIPHASH(EVP_PKEY *pkey, ASN1_OCTET_STRING *key);
- int EVP_PKEY_id(const EVP_PKEY *pkey);
- int EVP_PKEY_base_id(const EVP_PKEY *pkey);
- int EVP_PKEY_type(int type);
- int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type);
-
ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey);
int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *engine);
=head1 DESCRIPTION
-EVP_PKEY_set1_RSA(), EVP_PKEY_set1_DSA(), EVP_PKEY_set1_DH() and
-EVP_PKEY_set1_EC_KEY() set the key referenced by B<pkey> to B<key>.
+EVP_PKEY_get_base_id() returns the type of I<pkey>. For example
+an RSA key will return B<EVP_PKEY_RSA>.
-EVP_PKEY_get1_RSA(), EVP_PKEY_get1_DSA(), EVP_PKEY_get1_DH() and
-EVP_PKEY_get1_EC_KEY() return the referenced key in B<pkey> or
-B<NULL> if the key is not of the correct type.
+EVP_PKEY_get_id() returns the actual OID associated with I<pkey>.
+Historically keys using the same algorithm could use different OIDs.
+For example an RSA key could use the OIDs corresponding to
+the NIDs B<NID_rsaEncryption> (equivalent to B<EVP_PKEY_RSA>) or
+B<NID_rsa> (equivalent to B<EVP_PKEY_RSA2>). The use of
+alternative non-standard OIDs is now rare so B<EVP_PKEY_RSA2> et al are not
+often seen in practice.
-EVP_PKEY_get0_hmac(), EVP_PKEY_get0_poly1305(), EVP_PKEY_get0_siphash(),
-EVP_PKEY_get0_RSA(), EVP_PKEY_get0_DSA(), EVP_PKEY_get0_DH()
-and EVP_PKEY_get0_EC_KEY() also return the referenced key in B<pkey> or B<NULL>
-if the key is not of the correct type but the reference count of the
-returned key is B<not> incremented and so must not be freed up after use.
+EVP_PKEY_type() returns the underlying type of the NID I<type>. For example
+EVP_PKEY_type(EVP_PKEY_RSA2) will return B<EVP_PKEY_RSA>.
+
+EVP_PKEY_set1_RSA(), EVP_PKEY_set1_DSA(), EVP_PKEY_set1_DH() and
+EVP_PKEY_set1_EC_KEY() set the key referenced by I<pkey> to I<key>. These
+functions are deprecated. Applications should instead use
+L<EVP_PKEY_fromdata(3)>.
EVP_PKEY_assign_RSA(), EVP_PKEY_assign_DSA(), EVP_PKEY_assign_DH(),
EVP_PKEY_assign_EC_KEY(), EVP_PKEY_assign_POLY1305() and
-EVP_PKEY_assign_SIPHASH() also set the referenced key to B<key>
-however these use the supplied B<key> internally and so B<key>
-will be freed when the parent B<pkey> is freed.
+EVP_PKEY_assign_SIPHASH() set the referenced key to I<key> however these use
+the supplied I<key> internally and so I<key> will be freed when the parent
+I<pkey> is freed. These macros are deprecated. Applications should instead read
+an EVP_PKEY directly using the OSSL_DECODER APIs (see
+L<OSSL_DECODER_CTX_new_for_pkey(3)>), or construct an EVP_PKEY from data using
+L<EVP_PKEY_fromdata(3)>.
-EVP_PKEY_base_id() returns the type of B<pkey>. For example
-an RSA key will return B<EVP_PKEY_RSA>.
+EVP_PKEY_get1_RSA(), EVP_PKEY_get1_DSA(), EVP_PKEY_get1_DH() and
+EVP_PKEY_get1_EC_KEY() return the referenced key in I<pkey> or NULL if the
+key is not of the correct type. The returned key must be freed after use.
+These functions are deprecated. Applications should instead use the EVP_PKEY
+directly where possible. If access to the low level key parameters is required
+then applications should use L<EVP_PKEY_get_params(3)> and other similar
+functions. To write an EVP_PKEY out use the OSSL_ENCODER APIs (see
+L<OSSL_ENCODER_CTX_new_for_pkey(3)>).
-EVP_PKEY_id() returns the actual OID associated with B<pkey>. Historically keys
-using the same algorithm could use different OIDs. For example an RSA key could
-use the OIDs corresponding to the NIDs B<NID_rsaEncryption> (equivalent to
-B<EVP_PKEY_RSA>) or B<NID_rsa> (equivalent to B<EVP_PKEY_RSA2>). The use of
-alternative non-standard OIDs is now rare so B<EVP_PKEY_RSA2> et al are not
-often seen in practice.
+EVP_PKEY_get0_hmac(), EVP_PKEY_get0_poly1305(), EVP_PKEY_get0_siphash(),
+EVP_PKEY_get0_RSA(), EVP_PKEY_get0_DSA(), EVP_PKEY_get0_DH() and
+EVP_PKEY_get0_EC_KEY() return the referenced key in I<pkey> or NULL if the
+key is not of the correct type. The reference count of the returned key is
+B<not> incremented and so the key must not be freed after use. These functions
+are deprecated. Applications should instead use the EVP_PKEY directly where
+possible. If access to the low level key parameters is required then
+applications should use L<EVP_PKEY_get_params(3)> and other similar functions.
+To write an EVP_PKEY out use the OSSL_ENCODER APIs (see
+L<OSSL_ENCODER_CTX_new_for_pkey(3)>). EVP_PKEY_get0() returns a pointer to the
+legacy key or NULL if the key is not legacy.
+
+Note that if an EVP_PKEY was not constructed using one of the deprecated
+functions such as EVP_PKEY_set1_RSA(), EVP_PKEY_set1_DSA(), EVP_PKEY_set1_DH()
+or EVP_PKEY_set1_EC_KEY(), or via the similarly named B<EVP_PKEY_assign> macros
+described above then the internal key will be managed by a provider (see
+L<provider(7)>). In that case the key returned by EVP_PKEY_get1_RSA(),
+EVP_PKEY_get1_DSA(), EVP_PKEY_get1_DH(), EVP_PKEY_get1_EC_KEY(),
+EVP_PKEY_get0_hmac(), EVP_PKEY_get0_poly1305(), EVP_PKEY_get0_siphash(),
+EVP_PKEY_get0_RSA(), EVP_PKEY_get0_DSA(), EVP_PKEY_get0_DH() or
+EVP_PKEY_get0_EC_KEY() will be a cached copy of the provider's key. Subsequent
+updates to the provider's key will not be reflected back in the cached copy, and
+updates made by an application to the returned key will not be reflected back in
+the provider's key. Subsequent calls to EVP_PKEY_get1_RSA(),
+EVP_PKEY_get1_DSA(), EVP_PKEY_get1_DH() and EVP_PKEY_get1_EC_KEY() will always
+return the cached copy returned by the first call.
+
+EVP_PKEY_get0_engine() returns a reference to the ENGINE handling I<pkey>. This
+function is deprecated. Applications should use providers instead of engines
+(see L<provider(7)> for details).
+
+EVP_PKEY_set1_engine() sets the ENGINE handling I<pkey> to I<engine>. It
+must be called after the key algorithm and components are set up.
+If I<engine> does not include an B<EVP_PKEY_METHOD> for I<pkey> an
+error occurs. This function is deprecated. Applications should use providers
+instead of engines (see L<provider(7)> for details).
-EVP_PKEY_type() returns the underlying type of the NID B<type>. For example
-EVP_PKEY_type(EVP_PKEY_RSA2) will return B<EVP_PKEY_RSA>.
+=head1 WARNINGS
-EVP_PKEY_get0_engine() returns a reference to the ENGINE handling B<pkey>.
+The following functions are only reliable with B<EVP_PKEY>s that have
+been assigned an internal key with EVP_PKEY_assign_*():
-EVP_PKEY_set1_engine() sets the ENGINE handling B<pkey> to B<engine>. It
-must be called after the key algorithm and components are set up.
-If B<engine> does not include an B<EVP_PKEY_METHOD> for B<pkey> an
-error occurs.
+EVP_PKEY_get_id(), EVP_PKEY_get_base_id(), EVP_PKEY_type()
+
+For EVP_PKEY key type checking purposes, L<EVP_PKEY_is_a(3)> is more generic.
-EVP_PKEY_set_alias_type() allows modifying a EVP_PKEY to use a
-different set of algorithms than the default. This is currently used
-to support SM2 keys, which use an identical encoding to ECDSA.
+The keys returned from the functions EVP_PKEY_get0_RSA(), EVP_PKEY_get0_DSA(),
+EVP_PKEY_get0_DH() and EVP_PKEY_get0_EC_KEY() were changed to have a "const"
+return type in OpenSSL 3.0. As described above the keys returned may be cached
+copies of the key held in a provider. Due to this, and unlike in earlier
+versions of OpenSSL, they should be considered read-only copies of the key.
+Updates to these keys will not be reflected back in the provider side key. The
+EVP_PKEY_get1_RSA(), EVP_PKEY_get1_DSA(), EVP_PKEY_get1_DH() and
+EVP_PKEY_get1_EC_KEY() functions were not changed to have a "const" return type
+in order that applications can "free" the return value. However applications
+should still consider them as read-only copies.
=head1 NOTES
In accordance with the OpenSSL naming convention the key obtained
-from or assigned to the B<pkey> using the B<1> functions must be
-freed as well as B<pkey>.
+from or assigned to the I<pkey> using the B<1> functions must be
+freed as well as I<pkey>.
EVP_PKEY_assign_RSA(), EVP_PKEY_assign_DSA(), EVP_PKEY_assign_DH(),
EVP_PKEY_assign_EC_KEY(), EVP_PKEY_assign_POLY1305()
and EVP_PKEY_assign_SIPHASH() are implemented as macros.
+EVP_PKEY_assign_EC_KEY() looks at the curve name id to determine if
+the passed B<EC_KEY> is an L<SM2(7)> key, and will set the B<EVP_PKEY>
+type to B<EVP_PKEY_SM2> in that case, instead of B<EVP_PKEY_EC>.
+
Most applications wishing to know a key type will simply call
-EVP_PKEY_base_id() and will not care about the actual type:
+EVP_PKEY_get_base_id() and will not care about the actual type:
which will be identical in almost all cases.
Previous versions of this document suggested using EVP_PKEY_type(pkey->type)
to determine the type of a key. Since B<EVP_PKEY> is now opaque this
-is no longer possible: the equivalent is EVP_PKEY_base_id(pkey).
+is no longer possible: the equivalent is EVP_PKEY_get_base_id(pkey).
EVP_PKEY_set1_engine() is typically used by an ENGINE returning an HSM
key as part of its routine to load a private key.
@@ -120,36 +184,47 @@ EVP_PKEY_set1_RSA(), EVP_PKEY_set1_DSA(), EVP_PKEY_set1_DH() and
EVP_PKEY_set1_EC_KEY() return 1 for success or 0 for failure.
EVP_PKEY_get1_RSA(), EVP_PKEY_get1_DSA(), EVP_PKEY_get1_DH() and
-EVP_PKEY_get1_EC_KEY() return the referenced key or B<NULL> if
+EVP_PKEY_get1_EC_KEY() return the referenced key or NULL if
an error occurred.
EVP_PKEY_assign_RSA(), EVP_PKEY_assign_DSA(), EVP_PKEY_assign_DH(),
EVP_PKEY_assign_EC_KEY(), EVP_PKEY_assign_POLY1305()
and EVP_PKEY_assign_SIPHASH() return 1 for success and 0 for failure.
-EVP_PKEY_base_id(), EVP_PKEY_id() and EVP_PKEY_type() return a key
+EVP_PKEY_get_base_id(), EVP_PKEY_get_id() and EVP_PKEY_type() return a key
type or B<NID_undef> (equivalently B<EVP_PKEY_NONE>) on error.
EVP_PKEY_set1_engine() returns 1 for success and 0 for failure.
-EVP_PKEY_set_alias_type() returns 1 for success and 0 for error.
+=head1 SEE ALSO
-=head1 EXAMPLES
+L<EVP_PKEY_new(3)>, L<SM2(7)>
-After loading an ECC key, it is possible to convert it to using SM2
-algorithms with EVP_PKEY_set_alias_type:
+=head1 HISTORY
- EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2);
+The EVP_PKEY_id() and EVP_PKEY_base_id() functions were renamed to
+include C<get> in their names in OpenSSL 3.0, respectively. The old names
+are kept as non-deprecated alias macros.
-=head1 SEE ALSO
+EVP_PKEY_set1_RSA, EVP_PKEY_set1_DSA, EVP_PKEY_set1_DH, EVP_PKEY_set1_EC_KEY,
+EVP_PKEY_get1_RSA, EVP_PKEY_get1_DSA, EVP_PKEY_get1_DH, EVP_PKEY_get1_EC_KEY,
+EVP_PKEY_get0_RSA, EVP_PKEY_get0_DSA, EVP_PKEY_get0_DH, EVP_PKEY_get0_EC_KEY,
+EVP_PKEY_assign_RSA, EVP_PKEY_assign_DSA, EVP_PKEY_assign_DH,
+EVP_PKEY_assign_EC_KEY, EVP_PKEY_assign_POLY1305, EVP_PKEY_assign_SIPHASH,
+EVP_PKEY_get0_hmac, EVP_PKEY_get0_poly1305, EVP_PKEY_get0_siphash,
+EVP_PKEY_set1_engine and EVP_PKEY_get0_engine were deprecated in OpenSSL 3.0.
+
+The return value from EVP_PKEY_get0_RSA, EVP_PKEY_get0_DSA, EVP_PKEY_get0_DH,
+EVP_PKEY_get0_EC_KEY were made const in OpenSSL 3.0.
-L<EVP_PKEY_new(3)>
+The function EVP_PKEY_set_alias_type() was previously documented on this page.
+It was removed in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_set1_encoded_public_key.pod b/doc/man3/EVP_PKEY_set1_encoded_public_key.pod
new file mode 100644
index 000000000000..cf27919a2c3f
--- /dev/null
+++ b/doc/man3/EVP_PKEY_set1_encoded_public_key.pod
@@ -0,0 +1,142 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_set1_encoded_public_key, EVP_PKEY_get1_encoded_public_key,
+EVP_PKEY_set1_tls_encodedpoint, EVP_PKEY_get1_tls_encodedpoint
+- functions to set and get public key data within an EVP_PKEY
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_PKEY_set1_encoded_public_key(EVP_PKEY *pkey,
+ const unsigned char *pub, size_t publen);
+
+ size_t EVP_PKEY_get1_encoded_public_key(EVP_PKEY *pkey, unsigned char **ppub);
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey,
+ const unsigned char *pt, size_t ptlen);
+
+ size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *pkey, unsigned char **ppt);
+
+=head1 DESCRIPTION
+
+EVP_PKEY_set1_encoded_public_key() can be used to set the public key value
+within an existing EVP_PKEY object. For the built-in OpenSSL algorithms this
+currently only works for those that support key exchange. Parameters are not
+set as part of this operation, so typically an application will create an
+EVP_PKEY first, set the parameters on it, and then call this function.
+For example setting the parameters might be done using
+L<EVP_PKEY_copy_parameters(3)>.
+
+The format for the encoded public key will depend on the algorithm in use. For
+DH it should be encoded as a positive integer in big-endian form. For EC is
+should be a point conforming to Sec. 2.3.4 of the SECG SEC 1 ("Elliptic
+Curve Cryptography") standard. For X25519 and X448 it should be encoded in a
+format as defined by RFC7748.
+
+The key to be updated is supplied in B<pkey>. The buffer containing the encoded
+key is pointed to be B<pub>. The length of the buffer is supplied in B<publen>.
+
+EVP_PKEY_get1_encoded_public_key() does the equivalent operation except that
+the encoded public key is returned to the application. The key containing the
+public key data is supplied in B<pkey>. A buffer containing the encoded key will
+be allocated and stored in B<*ppub>. The length of the encoded public key is
+returned by the function. The application is responsible for freeing the
+allocated buffer.
+
+The macro EVP_PKEY_set1_tls_encodedpoint() is deprecated and simply calls
+EVP_PKEY_set1_encoded_public_key() with all the same arguments. New applications
+should use EVP_PKEY_set1_encoded_public_key() instead.
+
+The macro EVP_PKEY_get1_tls_encodedpoint() is deprecated and simply calls
+EVP_PKEY_get1_encoded_public_key() with all the same arguments. New applications
+should use EVP_PKEY_get1_encoded_public_key() instead.
+
+
+=head1 RETURN VALUES
+
+EVP_PKEY_set1_encoded_public_key() returns 1 for success and 0 or a negative
+value for failure.
+
+EVP_PKEY_get1_encoded_public_key() returns the length of the encoded key or 0 for failure.
+
+=head1 EXAMPLES
+
+See L<EVP_PKEY_derive_init(3)> and L<EVP_PKEY_derive(3)> for information about
+performing a key exchange operation.
+
+=head2 Set up a peer's EVP_PKEY ready for a key exchange operation
+
+ #include <openssl/evp.h>
+
+ int exchange(EVP_PKEY *ourkey, unsigned char *peer_pub, size_t peer_pub_len)
+ {
+ EVP_PKEY *peerkey = EVP_PKEY_new();
+
+ if (peerkey == NULL || EVP_PKEY_copy_parameters(peerkey, ourkey) <= 0)
+ return 0;
+
+ if (EVP_PKEY_set1_encoded_public_key(peerkey, peer_pub,
+ peer_pub_len) <= 0)
+ return 0;
+
+ /* Do the key exchange here */
+
+ EVP_PKEY_free(peerkey);
+
+ return 1;
+ }
+
+=head2 Get an encoded public key to send to a peer
+
+ #include <openssl/evp.h>
+
+ int get_encoded_pub_key(EVP_PKEY *ourkey)
+ {
+ unsigned char *pubkey;
+ size_t pubkey_len;
+
+ pubkey_len = EVP_PKEY_get1_encoded_public_key(ourkey, &pubkey);
+ if (pubkey_len == 0)
+ return 0;
+
+ /*
+ * Send the encoded public key stored in the buffer at "pubkey" and of
+ * length pubkey_len, to the peer.
+ */
+
+ OPENSSL_free(pubkey);
+ return 1;
+ }
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_new(3)>, L<EVP_PKEY_copy_parameters(3)>,
+L<EVP_PKEY_derive_init(3)>, L<EVP_PKEY_derive(3)>,
+L<EVP_PKEY-DH(7)>, L<EVP_PKEY-EC(7)>, L<EVP_PKEY-X25519(7)>, L<EVP_PKEY-X448(7)>
+
+=head1 HISTORY
+
+EVP_PKEY_set1_encoded_public_key() and EVP_PKEY_get1_encoded_public_key() were
+added in OpenSSL 3.0.
+
+EVP_PKEY_set1_tls_encodedpoint() and EVP_PKEY_get1_tls_encodedpoint() were
+deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
+
diff --git a/doc/man3/EVP_PKEY_set_type.pod b/doc/man3/EVP_PKEY_set_type.pod
new file mode 100644
index 000000000000..5a326df0121b
--- /dev/null
+++ b/doc/man3/EVP_PKEY_set_type.pod
@@ -0,0 +1,68 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_set_type, EVP_PKEY_set_type_str, EVP_PKEY_set_type_by_keymgmt
+- functions to change the EVP_PKEY type
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_PKEY_set_type(EVP_PKEY *pkey, int type);
+ int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len);
+ int EVP_PKEY_set_type_by_keymgmt(EVP_PKEY *pkey, EVP_KEYMGMT *keymgmt);
+
+=head1 DESCRIPTION
+
+All the functions described here behave the same in so far that they
+clear all the previous key data and methods from I<pkey>, and reset it
+to be of the type of key given by the different arguments. If
+I<pkey> is NULL, these functions will still return the same return
+values as if it wasn't.
+
+EVP_PKEY_set_type() initialises I<pkey> to contain an internal legacy
+key. When doing this, it finds a L<EVP_PKEY_ASN1_METHOD(3)>
+corresponding to I<type>, and associates I<pkey> with the findings.
+It is an error if no L<EVP_PKEY_ASN1_METHOD(3)> could be found for
+I<type>.
+
+EVP_PKEY_set_type_str() initialises I<pkey> to contain an internal legacy
+key. When doing this, it finds a L<EVP_PKEY_ASN1_METHOD(3)>
+corresponding to I<str> that has then length I<len>, and associates
+I<pkey> with the findings.
+It is an error if no L<EVP_PKEY_ASN1_METHOD(3)> could be found for
+I<type>.
+
+For both EVP_PKEY_set_type() and EVP_PKEY_set_type_str(), I<pkey> gets
+a numeric type, which can be retrieved with L<EVP_PKEY_get_id(3)>. This
+numeric type is taken from the L<EVP_PKEY_ASN1_METHOD(3)> that was
+found, and is equal to or closely related to I<type> in the case of
+EVP_PKEY_set_type(), or related to I<str> in the case of
+EVP_PKEY_set_type_str().
+
+EVP_PKEY_set_type_by_keymgmt() initialises I<pkey> to contain an
+internal provider side key. When doing this, it associates I<pkey>
+with I<keymgmt>. For keys initialised like this, the numeric type
+retrieved with L<EVP_PKEY_get_id(3)> will always be B<EVP_PKEY_NONE>.
+
+=head1 RETURN VALUES
+
+All functions described here return 1 if successful, or 0 on error.
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_assign(3)>, L<EVP_PKEY_get_id(3)>, L<EVP_PKEY_get0_RSA(3)>,
+L<EVP_PKEY_copy_parameters(3)>, L<EVP_PKEY_ASN1_METHOD(3)>,
+L<EVP_KEYMGMT(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_PKEY_settable_params.pod b/doc/man3/EVP_PKEY_settable_params.pod
new file mode 100644
index 000000000000..6760818cda79
--- /dev/null
+++ b/doc/man3/EVP_PKEY_settable_params.pod
@@ -0,0 +1,83 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_settable_params, EVP_PKEY_set_params,
+EVP_PKEY_set_int_param, EVP_PKEY_set_size_t_param, EVP_PKEY_set_bn_param,
+EVP_PKEY_set_utf8_string_param, EVP_PKEY_set_octet_string_param
+- set key parameters into a key
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ const OSSL_PARAM *EVP_PKEY_settable_params(const EVP_PKEY *pkey);
+ int EVP_PKEY_set_params(EVP_PKEY *pkey, OSSL_PARAM params[]);
+ int EVP_PKEY_set_int_param(EVP_PKEY *pkey, const char *key_name, int in);
+ int EVP_PKEY_set_size_t_param(EVP_PKEY *pkey, const char *key_name, size_t in);
+ int EVP_PKEY_set_bn_param(EVP_PKEY *pkey, const char *key_name,
+ const BIGNUM *bn);
+ int EVP_PKEY_set_utf8_string_param(EVP_PKEY *pkey, const char *key_name,
+ const char *str);
+ int EVP_PKEY_set_octet_string_param(EVP_PKEY *pkey, const char *key_name,
+ const unsigned char *buf, size_t bsize);
+
+=head1 DESCRIPTION
+
+These functions can be used to set additional parameters into an existing
+B<EVP_PKEY>.
+
+EVP_PKEY_set_params() sets one or more I<params> into a I<pkey>.
+See L<OSSL_PARAM(3)> for information about parameters.
+
+EVP_PKEY_settable_params() returns a constant list of I<params> indicating
+the names and types of key parameters that can be set.
+See L<OSSL_PARAM(3)> for information about parameters.
+
+EVP_PKEY_set_int_param() sets an integer value I<in> into a key I<pkey> for the
+associated field I<key_name>.
+
+EVP_PKEY_set_size_t_param() sets an size_t value I<in> into a key I<pkey> for
+the associated field I<key_name>.
+
+EVP_PKEY_set_bn_param() sets the BIGNUM value I<bn> into a key I<pkey> for the
+associated field I<key_name>.
+
+EVP_PKEY_set_utf8_string_param() sets the UTF8 string I<str> into a key I<pkey>
+for the associated field I<key_name>.
+
+EVP_PKEY_set_octet_string_param() sets the octet string value I<buf> with a
+size I<bsize> into a key I<pkey> for the associated field I<key_name>.
+
+=head1 NOTES
+
+These functions only work for B<EVP_PKEY>s that contain a provider side key.
+
+=head1 RETURN VALUES
+
+EVP_PKEY_settable_params() returns NULL on error or if it is not supported,
+
+All other methods return 1 if a value was successfully set, or 0 if
+there was an error.
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_gettable_params(3)>,
+L<EVP_PKEY_CTX_new(3)>, L<provider-keymgmt(7)>, L<OSSL_PARAM(3)>,
+
+
+=head1 HISTORY
+
+These functions were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
+
diff --git a/doc/man3/EVP_PKEY_sign.pod b/doc/man3/EVP_PKEY_sign.pod
index 175aeed584d9..6752432bd58e 100644
--- a/doc/man3/EVP_PKEY_sign.pod
+++ b/doc/man3/EVP_PKEY_sign.pod
@@ -2,29 +2,37 @@
=head1 NAME
-EVP_PKEY_sign_init, EVP_PKEY_sign - sign using a public key algorithm
+EVP_PKEY_sign_init, EVP_PKEY_sign_init_ex, EVP_PKEY_sign
+- sign using a public key algorithm
=head1 SYNOPSIS
#include <openssl/evp.h>
int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_sign_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen);
=head1 DESCRIPTION
-The EVP_PKEY_sign_init() function initializes a public key algorithm
-context using key B<pkey> for a signing operation.
+EVP_PKEY_sign_init() initializes a public key algorithm context I<ctx> for
+signing using the algorithm given when the context was created
+using L<EVP_PKEY_CTX_new(3)> or variants thereof. The algorithm is used to
+fetch a B<EVP_SIGNATURE> method implicitly, see L<provider(7)/Implicit fetch>
+for more information about implicit fetches.
+
+EVP_PKEY_sign_init_ex() is the same as EVP_PKEY_sign_init() but additionally
+sets the passed parameters I<params> on the context before returning.
The EVP_PKEY_sign() function performs a public key signing operation
-using B<ctx>. The data to be signed is specified using the B<tbs> and
-B<tbslen> parameters. If B<sig> is B<NULL> then the maximum size of the output
-buffer is written to the B<siglen> parameter. If B<sig> is not B<NULL> then
-before the call the B<siglen> parameter should contain the length of the
-B<sig> buffer, if the call is successful the signature is written to
-B<sig> and the amount of data written to B<siglen>.
+using I<ctx>. The data to be signed is specified using the I<tbs> and
+I<tbslen> parameters. If I<sig> is NULL then the maximum size of the output
+buffer is written to the I<siglen> parameter. If I<sig> is not NULL then
+before the call the I<siglen> parameter should contain the length of the
+I<sig> buffer, if the call is successful the signature is written to
+I<sig> and the amount of data written to I<siglen>.
=head1 NOTES
@@ -101,13 +109,16 @@ L<EVP_PKEY_derive(3)>
=head1 HISTORY
-These functions were added in OpenSSL 1.0.0.
+The EVP_PKEY_sign_init() and EVP_PKEY_sign() functions were added in
+OpenSSL 1.0.0.
+
+The EVP_PKEY_sign_init_ex() function was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_size.pod b/doc/man3/EVP_PKEY_size.pod
deleted file mode 100644
index 786c5039142c..000000000000
--- a/doc/man3/EVP_PKEY_size.pod
+++ /dev/null
@@ -1,80 +0,0 @@
-=pod
-
-=head1 NAME
-
-EVP_PKEY_size, EVP_PKEY_bits, EVP_PKEY_security_bits
-- EVP_PKEY information functions
-
-=head1 SYNOPSIS
-
- #include <openssl/evp.h>
-
- int EVP_PKEY_size(const EVP_PKEY *pkey);
- int EVP_PKEY_bits(const EVP_PKEY *pkey);
- int EVP_PKEY_security_bits(const EVP_PKEY *pkey);
-
-=head1 DESCRIPTION
-
-EVP_PKEY_size() returns the maximum suitable size for the output
-buffers for almost all operations that can be done with I<pkey>.
-The primary documented use is with L<EVP_SignFinal(3)> and
-L<EVP_SealInit(3)>, but it isn't limited there. The returned size is
-also large enough for the output buffer of L<EVP_PKEY_sign(3)>,
-L<EVP_PKEY_encrypt(3)>, L<EVP_PKEY_decrypt(3)>, L<EVP_PKEY_derive(3)>.
-
-It must be stressed that, unless the documentation for the operation
-that's being performed says otherwise, the size returned by
-EVP_PKEY_size() is only preliminary and not exact, so the final
-contents of the target buffer may be smaller. It is therefore crucial
-to take note of the size given back by the function that performs the
-operation, such as L<EVP_PKEY_sign(3)> (the I<siglen> argument will
-receive that length), to avoid bugs.
-
-EVP_PKEY_bits() returns the cryptographic length of the cryptosystem
-to which the key in I<pkey> belongs, in bits. Note that the definition
-of cryptographic length is specific to the key cryptosystem.
-
-EVP_PKEY_security_bits() returns the number of security bits of the given
-I<pkey>, bits of security is defined in NIST SP800-57.
-
-=head1 RETURN VALUES
-
-EVP_PKEY_size(), EVP_PKEY_bits() and EVP_PKEY_security_bits() return a
-positive number, or 0 if this size isn't available.
-
-=head1 NOTES
-
-Most functions that have an output buffer and are mentioned with
-EVP_PKEY_size() have a functionality where you can pass NULL for the
-buffer and still pass a pointer to an integer and get the exact size
-that this function call delivers in the context that it's called in.
-This allows those functions to be called twice, once to find out the
-exact buffer size, then allocate the buffer in between, and call that
-function again actually output the data. For those functions, it
-isn't strictly necessary to call EVP_PKEY_size() to find out the
-buffer size, but may be useful in cases where it's desirable to know
-the upper limit in advance.
-
-It should also be especially noted that EVP_PKEY_size() shouldn't be
-used to get the output size for EVP_DigestSignFinal(), according to
-L<EVP_DigestSignFinal(3)/NOTES>.
-
-=head1 SEE ALSO
-
-L<EVP_SignFinal(3)>,
-L<EVP_SealInit(3)>,
-L<EVP_PKEY_sign(3)>,
-L<EVP_PKEY_encrypt(3)>,
-L<EVP_PKEY_decrypt(3)>,
-L<EVP_PKEY_derive(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the Apache License 2.0 (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man3/EVP_PKEY_todata.pod b/doc/man3/EVP_PKEY_todata.pod
new file mode 100644
index 000000000000..dedfb1b0cf8a
--- /dev/null
+++ b/doc/man3/EVP_PKEY_todata.pod
@@ -0,0 +1,64 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_todata, EVP_PKEY_export
+- functions to return keys as an array of key parameters
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_PKEY_todata(const EVP_PKEY *pkey, int selection, OSSL_PARAM **params);
+ int EVP_PKEY_export(const EVP_PKEY *pkey, int selection,
+ OSSL_CALLBACK *export_cb, void *export_cbarg);
+
+=head1 DESCRIPTION
+
+The functions described here are used to extract B<EVP_PKEY> key values as an
+array of L<OSSL_PARAM(3)>.
+
+EVP_PKEY_todata() extracts values from a key I<pkey> using the I<selection>.
+I<selection> is described in L<EVP_PKEY_fromdata(3)/Selections>.
+L<OSSL_PARAM_free(3)> should be used to free the returned parameters in
+I<*params>.
+
+EVP_PKEY_export() is similiar to EVP_PKEY_todata() but uses a callback
+I<export_cb> that gets passed the value of I<export_cbarg>.
+See L<openssl-core.h(7)> for more information about the callback. Note that the
+L<OSSL_PARAM(3)> array that is passed to the callback is not persistent after the
+callback returns. The user must preserve the items of interest, or use
+EVP_PKEY_todata() if persistence is required.
+
+=head1 NOTES
+
+These functions only work with key management methods coming from a provider.
+This is the mirror function to L<EVP_PKEY_fromdata(3)>.
+
+=head1 RETURN VALUES
+
+EVP_PKEY_todata() and EVP_PKEY_export() return 1 for success and 0 for failure.
+
+=head1 SEE ALSO
+
+L<OSSL_PARAM(3)>, L<openssl-core.h(7)>,
+L<EVP_PKEY_fromdata(3)>,
+L<EVP_PKEY-RSA(7)>, L<EVP_PKEY-DSA(7)>, L<EVP_PKEY-DH(7)>, L<EVP_PKEY-EC(7)>,
+L<EVP_PKEY-ED448(7)>, L<EVP_PKEY-X25519(7)>, L<EVP_PKEY-X448(7)>,
+L<EVP_PKEY-ED25519(7)>
+
+=head1 HISTORY
+
+These functions were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
+
diff --git a/doc/man3/EVP_PKEY_verify.pod b/doc/man3/EVP_PKEY_verify.pod
index 616fd5577fd2..77023cab8704 100644
--- a/doc/man3/EVP_PKEY_verify.pod
+++ b/doc/man3/EVP_PKEY_verify.pod
@@ -2,26 +2,34 @@
=head1 NAME
-EVP_PKEY_verify_init, EVP_PKEY_verify - signature verification using a public key algorithm
+EVP_PKEY_verify_init, EVP_PKEY_verify_init_ex, EVP_PKEY_verify
+- signature verification using a public key algorithm
=head1 SYNOPSIS
#include <openssl/evp.h>
int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_verify_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
const unsigned char *sig, size_t siglen,
const unsigned char *tbs, size_t tbslen);
=head1 DESCRIPTION
-The EVP_PKEY_verify_init() function initializes a public key algorithm
-context using key B<pkey> for a signature verification operation.
+EVP_PKEY_verify_init() initializes a public key algorithm context I<ctx> for
+signing using the algorithm given when the context was created
+using L<EVP_PKEY_CTX_new(3)> or variants thereof. The algorithm is used to
+fetch a B<EVP_SIGNATURE> method implicitly, see L<provider(7)/Implicit fetch>
+for more information about implicit fetches.
+
+EVP_PKEY_verify_init_ex() is the same as EVP_PKEY_verify_init() but additionally
+sets the passed parameters I<params> on the context before returning.
The EVP_PKEY_verify() function performs a public key verification operation
-using B<ctx>. The signature is specified using the B<sig> and
-B<siglen> parameters. The verified data (i.e. the data believed originally
-signed) is specified using the B<tbs> and B<tbslen> parameters.
+using I<ctx>. The signature is specified using the I<sig> and
+I<siglen> parameters. The verified data (i.e. the data believed originally
+signed) is specified using the I<tbs> and I<tbslen> parameters.
=head1 NOTES
@@ -89,13 +97,16 @@ L<EVP_PKEY_derive(3)>
=head1 HISTORY
-These functions were added in OpenSSL 1.0.0.
+The EVP_PKEY_verify_init() and EVP_PKEY_verify() functions were added in
+OpenSSL 1.0.0.
+
+The EVP_PKEY_verify_init_ex() function was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_PKEY_verify_recover.pod b/doc/man3/EVP_PKEY_verify_recover.pod
index a3a7818d7940..7f0a06c03960 100644
--- a/doc/man3/EVP_PKEY_verify_recover.pod
+++ b/doc/man3/EVP_PKEY_verify_recover.pod
@@ -2,29 +2,40 @@
=head1 NAME
-EVP_PKEY_verify_recover_init, EVP_PKEY_verify_recover - recover signature using a public key algorithm
+EVP_PKEY_verify_recover_init, EVP_PKEY_verify_recover_init_ex,
+EVP_PKEY_verify_recover
+- recover signature using a public key algorithm
=head1 SYNOPSIS
#include <openssl/evp.h>
int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_verify_recover_init_ex(EVP_PKEY_CTX *ctx,
+ const OSSL_PARAM params[]);
int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx,
unsigned char *rout, size_t *routlen,
const unsigned char *sig, size_t siglen);
=head1 DESCRIPTION
-The EVP_PKEY_verify_recover_init() function initializes a public key algorithm
-context using key B<pkey> for a verify recover operation.
+EVP_PKEY_verify_recover_init() initializes a public key algorithm context
+I<ctx> for signing using the algorithm given when the context was created
+using L<EVP_PKEY_CTX_new(3)> or variants thereof. The algorithm is used to
+fetch a B<EVP_SIGNATURE> method implicitly, see L<provider(7)/Implicit fetch>
+for more information about implicit fetches.
+
+EVP_PKEY_verify_recover_init_ex() is the same as
+EVP_PKEY_verify_recover_init() but additionally sets the passed parameters
+I<params> on the context before returning.
The EVP_PKEY_verify_recover() function recovers signed data
-using B<ctx>. The signature is specified using the B<sig> and
-B<siglen> parameters. If B<rout> is B<NULL> then the maximum size of the output
-buffer is written to the B<routlen> parameter. If B<rout> is not B<NULL> then
-before the call the B<routlen> parameter should contain the length of the
-B<rout> buffer, if the call is successful recovered data is written to
-B<rout> and the amount of data written to B<routlen>.
+using I<ctx>. The signature is specified using the I<sig> and
+I<siglen> parameters. If I<rout> is NULL then the maximum size of the output
+buffer is written to the I<routlen> parameter. If I<rout> is not NULL then
+before the call the I<routlen> parameter should contain the length of the
+I<rout> buffer, if the call is successful recovered data is written to
+I<rout> and the amount of data written to I<routlen>.
=head1 NOTES
@@ -100,13 +111,16 @@ L<EVP_PKEY_derive(3)>
=head1 HISTORY
-These functions were added in OpenSSL 1.0.0.
+The EVP_PKEY_verify_recover_init() and EVP_PKEY_verify_recover()
+functions were added in OpenSSL 1.0.0.
+
+The EVP_PKEY_verify_recover_init_ex() function was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2013-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_RAND.pod b/doc/man3/EVP_RAND.pod
new file mode 100644
index 000000000000..a4d72b70432f
--- /dev/null
+++ b/doc/man3/EVP_RAND.pod
@@ -0,0 +1,404 @@
+=pod
+
+=head1 NAME
+
+EVP_RAND, EVP_RAND_fetch, EVP_RAND_free, EVP_RAND_up_ref, EVP_RAND_CTX,
+EVP_RAND_CTX_new, EVP_RAND_CTX_free, EVP_RAND_instantiate,
+EVP_RAND_uninstantiate, EVP_RAND_generate, EVP_RAND_reseed, EVP_RAND_nonce,
+EVP_RAND_enable_locking, EVP_RAND_verify_zeroization, EVP_RAND_get_strength,
+EVP_RAND_get_state,
+EVP_RAND_get0_provider, EVP_RAND_CTX_get0_rand, EVP_RAND_is_a,
+EVP_RAND_get0_name, EVP_RAND_names_do_all,
+EVP_RAND_get0_description,
+EVP_RAND_CTX_get_params,
+EVP_RAND_CTX_set_params, EVP_RAND_do_all_provided, EVP_RAND_get_params,
+EVP_RAND_gettable_ctx_params, EVP_RAND_settable_ctx_params,
+EVP_RAND_CTX_gettable_params, EVP_RAND_CTX_settable_params,
+EVP_RAND_gettable_params, EVP_RAND_STATE_UNINITIALISED, EVP_RAND_STATE_READY,
+EVP_RAND_STATE_ERROR - EVP RAND routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ typedef struct evp_rand_st EVP_RAND;
+ typedef struct evp_rand_ctx_st EVP_RAND_CTX;
+
+ EVP_RAND *EVP_RAND_fetch(OSSL_LIB_CTX *libctx, const char *algorithm,
+ const char *properties);
+ int EVP_RAND_up_ref(EVP_RAND *rand);
+ void EVP_RAND_free(EVP_RAND *rand);
+ EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, EVP_RAND_CTX *parent);
+ void EVP_RAND_CTX_free(EVP_RAND_CTX *ctx);
+ EVP_RAND *EVP_RAND_CTX_get0_rand(EVP_RAND_CTX *ctx);
+ int EVP_RAND_get_params(EVP_RAND *rand, OSSL_PARAM params[]);
+ int EVP_RAND_CTX_get_params(EVP_RAND_CTX *ctx, OSSL_PARAM params[]);
+ int EVP_RAND_CTX_set_params(EVP_RAND_CTX *ctx, const OSSL_PARAM params[]);
+ const OSSL_PARAM *EVP_RAND_gettable_params(const EVP_RAND *rand);
+ const OSSL_PARAM *EVP_RAND_gettable_ctx_params(const EVP_RAND *rand);
+ const OSSL_PARAM *EVP_RAND_settable_ctx_params(const EVP_RAND *rand);
+ const OSSL_PARAM *EVP_RAND_CTX_gettable_params(EVP_RAND_CTX *ctx);
+ const OSSL_PARAM *EVP_RAND_CTX_settable_params(EVP_RAND_CTX *ctx);
+ const char *EVP_RAND_get0_name(const EVP_RAND *rand);
+ const char *EVP_RAND_get0_description(const EVP_RAND *rand);
+ int EVP_RAND_is_a(const EVP_RAND *rand, const char *name);
+ const OSSL_PROVIDER *EVP_RAND_get0_provider(const EVP_RAND *rand);
+ void EVP_RAND_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_RAND *rand, void *arg),
+ void *arg);
+ int EVP_RAND_names_do_all(const EVP_RAND *rand,
+ void (*fn)(const char *name, void *data),
+ void *data);
+
+ int EVP_RAND_instantiate(EVP_RAND_CTX *ctx, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *pstr, size_t pstr_len,
+ const OSSL_PARAM params[]);
+ int EVP_RAND_uninstantiate(EVP_RAND_CTX *ctx);
+ int EVP_RAND_generate(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen,
+ unsigned int strength, int prediction_resistance,
+ const unsigned char *addin, size_t addin_len);
+ int EVP_RAND_reseed(EVP_RAND_CTX *ctx, int prediction_resistance,
+ const unsigned char *ent, size_t ent_len,
+ const unsigned char *addin, size_t addin_len);
+ int EVP_RAND_nonce(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen);
+ int EVP_RAND_enable_locking(EVP_RAND_CTX *ctx);
+ int EVP_RAND_verify_zeroization(EVP_RAND_CTX *ctx);
+ unsigned int EVP_RAND_get_strength(EVP_RAND_CTX *ctx);
+ int EVP_RAND_get_state(EVP_RAND_CTX *ctx);
+
+ #define EVP_RAND_STATE_UNINITIALISED 0
+ #define EVP_RAND_STATE_READY 1
+ #define EVP_RAND_STATE_ERROR 2
+
+=head1 DESCRIPTION
+
+The EVP RAND routines are a high-level interface to random number generators
+both deterministic and not.
+If you just want to generate random bytes then you don't need to use
+these functions: just call RAND_bytes() or RAND_priv_bytes().
+If you want to do more, these calls should be used instead of the older
+RAND and RAND_DRBG functions.
+
+After creating a B<EVP_RAND_CTX> for the required algorithm using
+EVP_RAND_CTX_new(), inputs to the algorithm are supplied either by
+passing them as part of the EVP_RAND_instantiate() call or using calls to
+EVP_RAND_CTX_set_params() before calling EVP_RAND_instantiate(). Finally,
+call EVP_RAND_generate() to produce cryptographically secure random bytes.
+
+=head2 Types
+
+B<EVP_RAND> is a type that holds the implementation of a RAND.
+
+B<EVP_RAND_CTX> is a context type that holds the algorithm inputs.
+B<EVP_RAND_CTX> structures are reference counted.
+
+=head2 Algorithm implementation fetching
+
+EVP_RAND_fetch() fetches an implementation of a RAND I<algorithm>, given
+a library context I<libctx> and a set of I<properties>.
+See L<crypto(7)/ALGORITHM FETCHING> for further information.
+
+The returned value must eventually be freed with
+L<EVP_RAND_free(3)>.
+
+EVP_RAND_up_ref() increments the reference count of an already fetched
+RAND.
+
+EVP_RAND_free() frees a fetched algorithm.
+NULL is a valid parameter, for which this function is a no-op.
+
+=head2 Context manipulation functions
+
+EVP_RAND_CTX_new() creates a new context for the RAND implementation I<rand>.
+If not NULL, I<parent> specifies the seed source for this implementation.
+Not all random number generators need to have a seed source specified.
+If a parent is required, a NULL I<parent> will utilise the operating
+system entropy sources.
+It is recommended to minimise the number of random number generators that
+rely on the operating system for their randomness because this is often scarce.
+
+EVP_RAND_CTX_free() frees up the context I<ctx>. If I<ctx> is NULL, nothing
+is done.
+
+EVP_RAND_CTX_get0_rand() returns the B<EVP_RAND> associated with the context
+I<ctx>.
+
+=head2 Random Number Generator Functions
+
+EVP_RAND_instantiate() processes any parameters in I<params> and
+then instantiates the RAND I<ctx> with a minimum security strength
+of <strength> and personalisation string I<pstr> of length <pstr_len>.
+If I<prediction_resistance> is specified, fresh entropy from a live source
+will be sought. This call operates as per NIST SP 800-90A and SP 800-90C.
+
+EVP_RAND_uninstantiate() uninstantiates the RAND I<ctx> as per
+NIST SP 800-90A and SP 800-90C. Subsequent to this call, the RAND cannot
+be used to generate bytes. It can only be freed or instantiated again.
+
+EVP_RAND_generate() produces random bytes from the RAND I<ctx> with the
+additional input I<addin> of length I<addin_len>. The bytes
+produced will meet the security I<strength>.
+If I<prediction_resistance> is specified, fresh entropy from a live source
+will be sought. This call operates as per NIST SP 800-90A and SP 800-90C.
+
+EVP_RAND_reseed() reseeds the RAND with new entropy.
+Entropy I<ent> of length I<ent_len> bytes can be supplied as can additional
+input I<addin> of length I<addin_len> bytes. In the FIPS provider, both are
+treated as additional input as per NIST SP-800-90Ar1, Sections 9.1 and 9.2.
+Additional seed material is also drawn from the RAND's parent or the
+operating system. If I<prediction_resistance> is specified, fresh entropy
+from a live source will be sought. This call operates as per NIST SP 800-90A
+and SP 800-90C.
+
+EVP_RAND_nonce() creates a nonce in I<out> of maximum length I<outlen>
+bytes from the RAND I<ctx>. The function returns the length of the generated
+nonce. If I<out> is NULL, the length is still returned but no generation
+takes place. This allows a caller to dynamically allocate a buffer of the
+appropriate size.
+
+EVP_RAND_enable_locking() enables locking for the RAND I<ctx> and all of
+its parents. After this I<ctx> will operate in a thread safe manner, albeit
+more slowly. This function is not itself thread safe if called with the same
+I<ctx> from multiple threads. Typically locking should be enabled before a
+I<ctx> is shared across multiple threads.
+
+EVP_RAND_get_params() retrieves details about the implementation
+I<rand>.
+The set of parameters given with I<params> determine exactly what
+parameters should be retrieved.
+Note that a parameter that is unknown in the underlying context is
+simply ignored.
+
+EVP_RAND_CTX_get_params() retrieves chosen parameters, given the
+context I<ctx> and its underlying context.
+The set of parameters given with I<params> determine exactly what
+parameters should be retrieved.
+Note that a parameter that is unknown in the underlying context is
+simply ignored.
+
+EVP_RAND_CTX_set_params() passes chosen parameters to the underlying
+context, given a context I<ctx>.
+The set of parameters given with I<params> determine exactly what
+parameters are passed down.
+Note that a parameter that is unknown in the underlying context is
+simply ignored.
+Also, what happens when a needed parameter isn't passed down is
+defined by the implementation.
+
+EVP_RAND_gettable_params() returns an L<OSSL_PARAM(3)> array that describes
+the retrievable and settable parameters. EVP_RAND_gettable_params() returns
+parameters that can be used with EVP_RAND_get_params().
+
+EVP_RAND_gettable_ctx_params() and EVP_RAND_CTX_gettable_params() return
+constant L<OSSL_PARAM(3)> arrays that describe the retrievable parameters that
+can be used with EVP_RAND_CTX_get_params(). EVP_RAND_gettable_ctx_params()
+returns the parameters that can be retrieved from the algorithm, whereas
+EVP_RAND_CTX_gettable_params() returns the parameters that can be retrieved
+in the context's current state.
+
+EVP_RAND_settable_ctx_params() and EVP_RAND_CTX_settable_params() return
+constant L<OSSL_PARAM(3)> arrays that describe the settable parameters that
+can be used with EVP_RAND_CTX_set_params(). EVP_RAND_settable_ctx_params()
+returns the parameters that can be retrieved from the algorithm, whereas
+EVP_RAND_CTX_settable_params() returns the parameters that can be retrieved
+in the context's current state.
+
+=head2 Information functions
+
+EVP_RAND_get_strength() returns the security strength of the RAND I<ctx>.
+
+EVP_RAND_get_state() returns the current state of the RAND I<ctx>.
+States defined by the OpenSSL RNGs are:
+
+=over 4
+
+=item *
+
+EVP_RAND_STATE_UNINITIALISED: this RNG is currently uninitialised.
+The instantiate call will change this to the ready state.
+
+=item *
+
+EVP_RAND_STATE_READY: this RNG is currently ready to generate output.
+
+=item *
+
+EVP_RAND_STATE_ERROR: this RNG is in an error state.
+
+=back
+
+EVP_RAND_is_a() returns 1 if I<rand> is an implementation of an
+algorithm that's identifiable with I<name>, otherwise 0.
+
+EVP_RAND_get0_provider() returns the provider that holds the implementation
+of the given I<rand>.
+
+EVP_RAND_do_all_provided() traverses all RAND implemented by all activated
+providers in the given library context I<libctx>, and for each of the
+implementations, calls the given function I<fn> with the implementation method
+and the given I<arg> as argument.
+
+EVP_RAND_get0_name() returns the canonical name of I<rand>.
+
+EVP_RAND_names_do_all() traverses all names for I<rand>, and calls
+I<fn> with each name and I<data>.
+
+EVP_RAND_get0_description() returns a description of the rand, meant for
+display and human consumption. The description is at the discretion of
+the rand implementation.
+
+EVP_RAND_verify_zeroization() confirms if the internal DRBG state is
+currently zeroed. This is used by the FIPS provider to support the mandatory
+self tests.
+
+=head1 PARAMETERS
+
+The standard parameter names are:
+
+=over 4
+
+=item "state" (B<OSSL_RAND_PARAM_STATE>) <integer>
+
+Returns the state of the random number generator.
+
+=item "strength" (B<OSSL_RAND_PARAM_STRENGTH>) <unsigned integer>
+
+Returns the bit strength of the random number generator.
+
+=back
+
+For rands that are also deterministic random bit generators (DRBGs), these
+additional parameters are recognised. Not all
+parameters are relevant to, or are understood by all DRBG rands:
+
+=over 4
+
+=item "reseed_requests" (B<OSSL_DRBG_PARAM_RESEED_REQUESTS>) <unsigned integer>
+
+Reads or set the number of generate requests before reseeding the
+associated RAND ctx.
+
+=item "reseed_time_interval" (B<OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL>) <integer>
+
+Reads or set the number of elapsed seconds before reseeding the
+associated RAND ctx.
+
+=item "max_request" (B<OSSL_DRBG_PARAM_RESEED_REQUESTS>) <unsigned integer>
+
+Specifies the maximum number of bytes that can be generated in a single
+call to OSSL_FUNC_rand_generate.
+
+=item "min_entropylen" (B<OSSL_DRBG_PARAM_MIN_ENTROPYLEN>) <unsigned integer>
+
+=item "max_entropylen" (B<OSSL_DRBG_PARAM_MAX_ENTROPYLEN>) <unsigned integer>
+
+Specify the minimum and maximum number of bytes of random material that
+can be used to seed the DRBG.
+
+=item "min_noncelen" (B<OSSL_DRBG_PARAM_MIN_NONCELEN>) <unsigned integer>
+
+=item "max_noncelen" (B<OSSL_DRBG_PARAM_MAX_NONCELEN>) <unsigned integer>
+
+Specify the minimum and maximum number of bytes of nonce that can be used to
+seed the DRBG.
+
+=item "max_perslen" (B<OSSL_DRBG_PARAM_MAX_PERSLEN>) <unsigned integer>
+
+=item "max_adinlen" (B<OSSL_DRBG_PARAM_MAX_ADINLEN>) <unsigned integer>
+
+Specify the minimum and maximum number of bytes of personalisation string
+that can be used with the DRBG.
+
+=item "reseed_counter" (B<OSSL_DRBG_PARAM_RESEED_COUNTER>) <unsigned integer>
+
+Specifies the number of times the DRBG has been seeded or reseeded.
+
+=item "properties" (B<OSSL_RAND_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "mac" (B<OSSL_RAND_PARAM_MAC>) <UTF8 string>
+
+=item "digest" (B<OSSL_RAND_PARAM_DIGEST>) <UTF8 string>
+
+=item "cipher" (B<OSSL_RAND_PARAM_CIPHER>) <UTF8 string>
+
+For RAND implementations that use an underlying computation MAC, digest or
+cipher, these parameters set what the algorithm should be.
+
+The value is always the name of the intended algorithm,
+or the properties in the case of B<OSSL_RAND_PARAM_PROPERTIES>.
+
+=back
+
+=head1 NOTES
+
+An B<EVP_RAND_CTX> needs to have locking enabled if it acts as the parent of
+more than one child and the children can be accessed concurrently. This must
+be done by explicitly calling EVP_RAND_enable_locking().
+
+The RAND life-cycle is described in L<life_cycle-rand(7)>. In the future,
+the transitions described there will be enforced. When this is done, it will
+not be considered a breaking change to the API.
+
+=head1 RETURN VALUES
+
+EVP_RAND_fetch() returns a pointer to a newly fetched B<EVP_RAND>, or
+NULL if allocation failed.
+
+EVP_RAND_get0_provider() returns a pointer to the provider for the RAND, or
+NULL on error.
+
+EVP_RAND_CTX_get0_rand() returns a pointer to the B<EVP_RAND> associated
+with the context.
+
+EVP_RAND_get0_name() returns the name of the random number generation
+algorithm.
+
+EVP_RAND_up_ref() returns 1 on success, 0 on error.
+
+EVP_RAND_names_do_all() returns 1 if the callback was called for all names. A
+return value of 0 means that the callback was not called for any names.
+
+EVP_RAND_CTX_new() returns either the newly allocated
+B<EVP_RAND_CTX> structure or NULL if an error occurred.
+
+EVP_RAND_CTX_free() does not return a value.
+
+EVP_RAND_nonce() returns the length of the nonce.
+
+EVP_RAND_get_strength() returns the strength of the random number generator
+in bits.
+
+EVP_RAND_gettable_params(), EVP_RAND_gettable_ctx_params() and
+EVP_RAND_settable_ctx_params() return an array of OSSL_PARAMs.
+
+EVP_RAND_verify_zeroization() returns 1 if the internal DRBG state is
+currently zeroed, and 0 if not.
+
+The remaining functions return 1 for success and 0 or a negative value for
+failure.
+
+=head1 SEE ALSO
+
+L<RAND_bytes(3)>,
+L<EVP_RAND-CTR-DRBG(7)>,
+L<EVP_RAND-HASH-DRBG(7)>,
+L<EVP_RAND-HMAC-DRBG(7)>,
+L<EVP_RAND-TEST-RAND(7)>,
+L<provider-rand(7)>,
+L<life_cycle-rand(7)>
+
+=head1 HISTORY
+
+This functionality was added to OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_SIGNATURE.pod b/doc/man3/EVP_SIGNATURE.pod
new file mode 100644
index 000000000000..600522085398
--- /dev/null
+++ b/doc/man3/EVP_SIGNATURE.pod
@@ -0,0 +1,116 @@
+=pod
+
+=head1 NAME
+
+EVP_SIGNATURE,
+EVP_SIGNATURE_fetch, EVP_SIGNATURE_free, EVP_SIGNATURE_up_ref,
+EVP_SIGNATURE_is_a, EVP_SIGNATURE_get0_provider,
+EVP_SIGNATURE_do_all_provided, EVP_SIGNATURE_names_do_all,
+EVP_SIGNATURE_get0_name, EVP_SIGNATURE_get0_description,
+EVP_SIGNATURE_gettable_ctx_params, EVP_SIGNATURE_settable_ctx_params
+- Functions to manage EVP_SIGNATURE algorithm objects
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ typedef struct evp_signature_st EVP_SIGNATURE;
+
+ EVP_SIGNATURE *EVP_SIGNATURE_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties);
+ void EVP_SIGNATURE_free(EVP_SIGNATURE *signature);
+ int EVP_SIGNATURE_up_ref(EVP_SIGNATURE *signature);
+ const char *EVP_SIGNATURE_get0_name(const EVP_SIGNATURE *signature);
+ int EVP_SIGNATURE_is_a(const EVP_SIGNATURE *signature, const char *name);
+ OSSL_PROVIDER *EVP_SIGNATURE_get0_provider(const EVP_SIGNATURE *signature);
+ void EVP_SIGNATURE_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_SIGNATURE *signature,
+ void *arg),
+ void *arg);
+ int EVP_SIGNATURE_names_do_all(const EVP_SIGNATURE *signature,
+ void (*fn)(const char *name, void *data),
+ void *data);
+ const char *EVP_SIGNATURE_get0_name(const EVP_SIGNATURE *signature);
+ const char *EVP_SIGNATURE_get0_description(const EVP_SIGNATURE *signature);
+ const OSSL_PARAM *EVP_SIGNATURE_gettable_ctx_params(const EVP_SIGNATURE *sig);
+ const OSSL_PARAM *EVP_SIGNATURE_settable_ctx_params(const EVP_SIGNATURE *sig);
+
+=head1 DESCRIPTION
+
+EVP_SIGNATURE_fetch() fetches the implementation for the given
+B<algorithm> from any provider offering it, within the criteria given
+by the B<properties>.
+The algorithm will be one offering functions for performing signature related
+tasks such as signing and verifying.
+See L<crypto(7)/ALGORITHM FETCHING> for further information.
+
+The returned value must eventually be freed with EVP_SIGNATURE_free().
+
+EVP_SIGNATURE_free() decrements the reference count for the B<EVP_SIGNATURE>
+structure. Typically this structure will have been obtained from an earlier call
+to EVP_SIGNATURE_fetch(). If the reference count drops to 0 then the
+structure is freed.
+
+EVP_SIGNATURE_up_ref() increments the reference count for an B<EVP_SIGNATURE>
+structure.
+
+EVP_SIGNATURE_is_a() returns 1 if I<signature> is an implementation of an
+algorithm that's identifiable with I<name>, otherwise 0.
+
+EVP_SIGNATURE_get0_provider() returns the provider that I<signature> was
+fetched from.
+
+EVP_SIGNATURE_do_all_provided() traverses all SIGNATURE implemented by all
+activated roviders in the given library context I<libctx>, and for each of the
+implementations, calls the given function I<fn> with the implementation method
+and the given I<arg> as argument.
+
+EVP_SIGNATURE_get0_name() returns the algorithm name from the provided
+implementation for the given I<signature>. Note that the I<signature> may have
+multiple synonyms associated with it. In this case the first name from the
+algorithm definition is returned. Ownership of the returned string is retained
+by the I<signature> object and should not be freed by the caller.
+
+EVP_SIGNATURE_names_do_all() traverses all names for I<signature>, and calls
+I<fn> with each name and I<data>.
+
+EVP_SIGNATURE_get0_description() returns a description of the I<signature>,
+meant for display and human consumption. The description is at the
+discretion of the I<signature> implementation.
+
+EVP_SIGNATURE_gettable_ctx_params() and EVP_SIGNATURE_settable_ctx_params()
+return a constant L<OSSL_PARAM(3)> array that describes the names and types of key
+parameters that can be retrieved or set by a signature algorithm using
+L<EVP_PKEY_CTX_get_params(3)> and L<EVP_PKEY_CTX_set_params(3)>.
+
+=head1 RETURN VALUES
+
+EVP_SIGNATURE_fetch() returns a pointer to an B<EVP_SIGNATURE> for success
+or B<NULL> for failure.
+
+EVP_SIGNATURE_up_ref() returns 1 for success or 0 otherwise.
+
+EVP_SIGNATURE_names_do_all() returns 1 if the callback was called for all names.
+A return value of 0 means that the callback was not called for any names.
+
+EVP_SIGNATURE_gettable_ctx_params() and EVP_SIGNATURE_settable_ctx_params()
+return a constant L<OSSL_PARAM(3)> array or NULL on error.
+
+=head1 SEE ALSO
+
+L<crypto(7)/ALGORITHM FETCHING>, L<OSSL_PROVIDER(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_SealInit.pod b/doc/man3/EVP_SealInit.pod
index 4bee44922d53..721811ee7170 100644
--- a/doc/man3/EVP_SealInit.pod
+++ b/doc/man3/EVP_SealInit.pod
@@ -29,13 +29,13 @@ using one or more public keys, this allows the same encrypted data to be
decrypted using any of the corresponding private keys. B<ek> is an array of
buffers where the public key encrypted secret key will be written, each buffer
must contain enough room for the corresponding encrypted key: that is
-B<ek[i]> must have room for B<EVP_PKEY_size(pubk[i])> bytes. The actual
+B<ek[i]> must have room for B<EVP_PKEY_get_size(pubk[i])> bytes. The actual
size of each encrypted secret key is written to the array B<ekl>. B<pubk> is
an array of B<npubk> public keys.
The B<iv> parameter is a buffer where the generated IV is written to. It must
contain enough room for the corresponding cipher's IV, as determined by (for
-example) EVP_CIPHER_iv_length(type).
+example) EVP_CIPHER_get_iv_length(type).
If the cipher does not require an IV then the B<iv> parameter is ignored
and can be B<NULL>.
@@ -82,9 +82,9 @@ L<RAND(7)>
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_SignInit.pod b/doc/man3/EVP_SignInit.pod
index 299c5cf312ee..11832ff76180 100644
--- a/doc/man3/EVP_SignInit.pod
+++ b/doc/man3/EVP_SignInit.pod
@@ -2,7 +2,8 @@
=head1 NAME
-EVP_SignInit, EVP_SignInit_ex, EVP_SignUpdate, EVP_SignFinal
+EVP_SignInit, EVP_SignInit_ex, EVP_SignUpdate,
+EVP_SignFinal_ex, EVP_SignFinal
- EVP signing functions
=head1 SYNOPSIS
@@ -11,7 +12,10 @@ EVP_SignInit, EVP_SignInit_ex, EVP_SignUpdate, EVP_SignFinal
int EVP_SignInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
int EVP_SignUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt);
- int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sig, unsigned int *s, EVP_PKEY *pkey);
+ int EVP_SignFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s,
+ EVP_PKEY *pkey, OSSL_LIB_CTX *libctx, const char *propq);
+ int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sig, unsigned int *s,
+ EVP_PKEY *pkey);
void EVP_SignInit(EVP_MD_CTX *ctx, const EVP_MD *type);
@@ -28,20 +32,25 @@ EVP_SignUpdate() hashes I<cnt> bytes of data at I<d> into the
signature context I<ctx>. This function can be called several times on the
same I<ctx> to include additional data.
-EVP_SignFinal() signs the data in I<ctx> using the private key I<pkey> and
-places the signature in I<sig>. I<sig> must be at least C<EVP_PKEY_size(pkey)>
-bytes in size. I<s> is an OUT parameter, and not used as an IN parameter.
+EVP_SignFinal_ex() signs the data in I<ctx> using the private key
+I<pkey> and places the signature in I<sig>. The library context I<libctx> and
+property query I<propq> are used when creating a context to use with the key
+I<pkey>. I<sig> must be at least C<EVP_PKEY_get_size(pkey)> bytes in size.
+I<s> is an OUT parameter, and not used as an IN parameter.
The number of bytes of data written (i.e. the length of the signature)
-will be written to the integer at I<s>, at most C<EVP_PKEY_size(pkey)> bytes
-will be written.
+will be written to the integer at I<s>, at most C<EVP_PKEY_get_size(pkey)>
+bytes will be written.
+
+EVP_SignFinal() is similar to EVP_SignFinal_ex() but uses default
+values of NULL for the library context I<libctx> and the property query I<propq>.
EVP_SignInit() initializes a signing context I<ctx> to use the default
implementation of digest I<type>.
=head1 RETURN VALUES
-EVP_SignInit_ex(), EVP_SignUpdate() and EVP_SignFinal() return 1
-for success and 0 for failure.
+EVP_SignInit_ex(), EVP_SignUpdate(), EVP_SignFinal_ex() and
+EVP_SignFinal() return 1 for success and 0 for failure.
The error codes can be obtained by L<ERR_get_error(3)>.
@@ -51,10 +60,9 @@ The B<EVP> interface to digital signatures should almost always be used in
preference to the low-level interfaces. This is because the code then becomes
transparent to the algorithm used and much more flexible.
-When signing with DSA private keys the random number generator must be seeded.
-If the automatic seeding or reseeding of the OpenSSL CSPRNG fails due to
-external circumstances (see L<RAND(7)>), the operation will fail.
-This requirement does not hold for RSA signatures.
+When signing with some private key types the random number generator must
+be seeded. If the automatic seeding or reseeding of the OpenSSL CSPRNG fails
+due to external circumstances (see L<RAND(7)>), the operation will fail.
The call to EVP_SignFinal() internally finalizes a copy of the digest context.
This means that calls to EVP_SignUpdate() and EVP_SignFinal() can be called
@@ -76,22 +84,27 @@ data have been passed through EVP_SignUpdate().
It is not possible to change the signing parameters using these function.
-The previous two bugs are fixed in the newer EVP_SignDigest*() function.
+The previous two bugs are fixed in the newer EVP_DigestSign*() functions.
=head1 SEE ALSO
-L<EVP_PKEY_size(3)>, L<EVP_PKEY_bits(3)>, L<EVP_PKEY_security_bits(3)>,
+L<EVP_PKEY_get_size(3)>, L<EVP_PKEY_get_bits(3)>,
+L<EVP_PKEY_get_security_bits(3)>,
L<EVP_VerifyInit(3)>,
L<EVP_DigestInit(3)>,
L<evp(7)>, L<HMAC(3)>, L<MD2(3)>,
L<MD5(3)>, L<MDC2(3)>, L<RIPEMD160(3)>,
-L<SHA1(3)>, L<dgst(1)>
+L<SHA1(3)>, L<openssl-dgst(1)>
+
+=head1 HISTORY
+
+The function EVP_SignFinal_ex() was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_VerifyInit.pod b/doc/man3/EVP_VerifyInit.pod
index 3c6b2daeca78..a6d5772c3b83 100644
--- a/doc/man3/EVP_VerifyInit.pod
+++ b/doc/man3/EVP_VerifyInit.pod
@@ -3,7 +3,7 @@
=head1 NAME
EVP_VerifyInit_ex,
-EVP_VerifyInit, EVP_VerifyUpdate, EVP_VerifyFinal
+EVP_VerifyInit, EVP_VerifyUpdate, EVP_VerifyFinal_ex, EVP_VerifyFinal
- EVP signature verification functions
=head1 SYNOPSIS
@@ -12,6 +12,9 @@ EVP_VerifyInit, EVP_VerifyUpdate, EVP_VerifyFinal
int EVP_VerifyInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
int EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt);
+ int EVP_VerifyFinal_ex(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
+ unsigned int siglen, EVP_PKEY *pkey,
+ OSSL_LIB_CTX *libctx, const char *propq);
int EVP_VerifyFinal(EVP_MD_CTX *ctx, unsigned char *sigbuf, unsigned int siglen,
EVP_PKEY *pkey);
@@ -22,27 +25,32 @@ EVP_VerifyInit, EVP_VerifyUpdate, EVP_VerifyFinal
The EVP signature verification routines are a high-level interface to digital
signatures.
-EVP_VerifyInit_ex() sets up verification context B<ctx> to use digest
-B<type> from ENGINE B<impl>. B<ctx> must be created by calling
+EVP_VerifyInit_ex() sets up verification context I<ctx> to use digest
+I<type> from ENGINE I<impl>. I<ctx> must be created by calling
EVP_MD_CTX_new() before calling this function.
-EVP_VerifyUpdate() hashes B<cnt> bytes of data at B<d> into the
-verification context B<ctx>. This function can be called several times on the
-same B<ctx> to include additional data.
+EVP_VerifyUpdate() hashes I<cnt> bytes of data at I<d> into the
+verification context I<ctx>. This function can be called several times on the
+same I<ctx> to include additional data.
-EVP_VerifyFinal() verifies the data in B<ctx> using the public key B<pkey>
-and against the B<siglen> bytes at B<sigbuf>.
+EVP_VerifyFinal_ex() verifies the data in I<ctx> using the public key
+I<pkey> and I<siglen> bytes in I<sigbuf>.
+The library context I<libctx> and property query I<propq> are used when creating
+a context to use with the key I<pkey>.
-EVP_VerifyInit() initializes verification context B<ctx> to use the default
-implementation of digest B<type>.
+EVP_VerifyFinal() is similar to EVP_VerifyFinal_ex() but uses default
+values of NULL for the library context I<libctx> and the property query I<propq>.
+
+EVP_VerifyInit() initializes verification context I<ctx> to use the default
+implementation of digest I<type>.
=head1 RETURN VALUES
EVP_VerifyInit_ex() and EVP_VerifyUpdate() return 1 for success and 0 for
failure.
-EVP_VerifyFinal() returns 1 for a correct signature, 0 for failure and -1 if some
-other error occurred.
+EVP_VerifyFinal_ex() and EVP_VerifyFinal() return 1 for a correct
+signature, 0 for failure and a negative value if some other error occurred.
The error codes can be obtained by L<ERR_get_error(3)>.
@@ -81,13 +89,17 @@ L<EVP_SignInit(3)>,
L<EVP_DigestInit(3)>,
L<evp(7)>, L<HMAC(3)>, L<MD2(3)>,
L<MD5(3)>, L<MDC2(3)>, L<RIPEMD160(3)>,
-L<SHA1(3)>, L<dgst(1)>
+L<SHA1(3)>, L<openssl-dgst(1)>
+
+=head1 HISTORY
+
+The function EVP_VerifyFinal_ex() was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_aes.pod b/doc/man3/EVP_aes.pod
deleted file mode 100644
index 6377fc9a21b0..000000000000
--- a/doc/man3/EVP_aes.pod
+++ /dev/null
@@ -1,194 +0,0 @@
-=pod
-
-=head1 NAME
-
-EVP_aes_128_cbc,
-EVP_aes_192_cbc,
-EVP_aes_256_cbc,
-EVP_aes_128_cfb,
-EVP_aes_192_cfb,
-EVP_aes_256_cfb,
-EVP_aes_128_cfb1,
-EVP_aes_192_cfb1,
-EVP_aes_256_cfb1,
-EVP_aes_128_cfb8,
-EVP_aes_192_cfb8,
-EVP_aes_256_cfb8,
-EVP_aes_128_cfb128,
-EVP_aes_192_cfb128,
-EVP_aes_256_cfb128,
-EVP_aes_128_ctr,
-EVP_aes_192_ctr,
-EVP_aes_256_ctr,
-EVP_aes_128_ecb,
-EVP_aes_192_ecb,
-EVP_aes_256_ecb,
-EVP_aes_128_ofb,
-EVP_aes_192_ofb,
-EVP_aes_256_ofb,
-EVP_aes_128_cbc_hmac_sha1,
-EVP_aes_256_cbc_hmac_sha1,
-EVP_aes_128_cbc_hmac_sha256,
-EVP_aes_256_cbc_hmac_sha256,
-EVP_aes_128_ccm,
-EVP_aes_192_ccm,
-EVP_aes_256_ccm,
-EVP_aes_128_gcm,
-EVP_aes_192_gcm,
-EVP_aes_256_gcm,
-EVP_aes_128_ocb,
-EVP_aes_192_ocb,
-EVP_aes_256_ocb,
-EVP_aes_128_wrap,
-EVP_aes_192_wrap,
-EVP_aes_256_wrap,
-EVP_aes_128_wrap_pad,
-EVP_aes_192_wrap_pad,
-EVP_aes_256_wrap_pad,
-EVP_aes_128_xts,
-EVP_aes_256_xts
-- EVP AES cipher
-
-=head1 SYNOPSIS
-
-=for comment generic
-
- #include <openssl/evp.h>
-
- const EVP_CIPHER *EVP_ciphername(void)
-
-I<EVP_ciphername> is used a placeholder for any of the described cipher
-functions, such as I<EVP_aes_128_cbc>.
-
-=head1 DESCRIPTION
-
-The AES encryption algorithm for EVP.
-
-=over 4
-
-=item EVP_aes_128_cbc(),
-EVP_aes_192_cbc(),
-EVP_aes_256_cbc(),
-EVP_aes_128_cfb(),
-EVP_aes_192_cfb(),
-EVP_aes_256_cfb(),
-EVP_aes_128_cfb1(),
-EVP_aes_192_cfb1(),
-EVP_aes_256_cfb1(),
-EVP_aes_128_cfb8(),
-EVP_aes_192_cfb8(),
-EVP_aes_256_cfb8(),
-EVP_aes_128_cfb128(),
-EVP_aes_192_cfb128(),
-EVP_aes_256_cfb128(),
-EVP_aes_128_ctr(),
-EVP_aes_192_ctr(),
-EVP_aes_256_ctr(),
-EVP_aes_128_ecb(),
-EVP_aes_192_ecb(),
-EVP_aes_256_ecb(),
-EVP_aes_128_ofb(),
-EVP_aes_192_ofb(),
-EVP_aes_256_ofb()
-
-AES for 128, 192 and 256 bit keys in the following modes: CBC, CFB with 128-bit
-shift, CFB with 1-bit shift, CFB with 8-bit shift, CTR, ECB, and OFB.
-
-=item EVP_aes_128_cbc_hmac_sha1(),
-EVP_aes_256_cbc_hmac_sha1()
-
-Authenticated encryption with AES in CBC mode using SHA-1 as HMAC, with keys of
-128 and 256 bits length respectively. The authentication tag is 160 bits long.
-
-WARNING: this is not intended for usage outside of TLS and requires calling of
-some undocumented ctrl functions. These ciphers do not conform to the EVP AEAD
-interface.
-
-=item EVP_aes_128_cbc_hmac_sha256(),
-EVP_aes_256_cbc_hmac_sha256()
-
-Authenticated encryption with AES in CBC mode using SHA256 (SHA-2, 256-bits) as
-HMAC, with keys of 128 and 256 bits length respectively. The authentication tag
-is 256 bits long.
-
-WARNING: this is not intended for usage outside of TLS and requires calling of
-some undocumented ctrl functions. These ciphers do not conform to the EVP AEAD
-interface.
-
-=item EVP_aes_128_ccm(),
-EVP_aes_192_ccm(),
-EVP_aes_256_ccm(),
-EVP_aes_128_gcm(),
-EVP_aes_192_gcm(),
-EVP_aes_256_gcm(),
-EVP_aes_128_ocb(),
-EVP_aes_192_ocb(),
-EVP_aes_256_ocb()
-
-AES for 128, 192 and 256 bit keys in CBC-MAC Mode (CCM), Galois Counter Mode
-(GCM) and OCB Mode respectively. These ciphers require additional control
-operations to function correctly, see the L<EVP_EncryptInit(3)/AEAD Interface>
-section for details.
-
-=item EVP_aes_128_wrap(),
-EVP_aes_192_wrap(),
-EVP_aes_256_wrap(),
-EVP_aes_128_wrap_pad(),
-EVP_aes_128_wrap(),
-EVP_aes_192_wrap(),
-EVP_aes_256_wrap(),
-EVP_aes_192_wrap_pad(),
-EVP_aes_128_wrap(),
-EVP_aes_192_wrap(),
-EVP_aes_256_wrap(),
-EVP_aes_256_wrap_pad()
-
-AES key wrap with 128, 192 and 256 bit keys, as according to RFC 3394 section
-2.2.1 ("wrap") and RFC 5649 section 4.1 ("wrap with padding") respectively.
-
-=item EVP_aes_128_xts(),
-EVP_aes_256_xts()
-
-AES XTS mode (XTS-AES) is standardized in IEEE Std. 1619-2007 and described in NIST
-SP 800-38E. The XTS (XEX-based tweaked-codebook mode with ciphertext stealing)
-mode was designed by Prof. Phillip Rogaway of University of California, Davis,
-intended for encrypting data on a storage device.
-
-XTS-AES provides confidentiality but not authentication of data. It also
-requires a key of double-length for protection of a certain key size.
-In particular, XTS-AES-128 (B<EVP_aes_128_xts>) takes input of a 256-bit key to
-achieve AES 128-bit security, and XTS-AES-256 (B<EVP_aes_256_xts>) takes input
-of a 512-bit key to achieve AES 256-bit security.
-
-The XTS implementation in OpenSSL does not support streaming. That is there must
-only be one L<EVP_EncryptUpdate(3)> call per L<EVP_EncryptInit_ex(3)> call (and
-similarly with the "Decrypt" functions).
-
-The I<iv> parameter to L<EVP_EncryptInit_ex(3)> or L<EVP_DecryptInit_ex(3)> is
-the XTS "tweak" value.
-
-=back
-
-=head1 RETURN VALUES
-
-These functions return an B<EVP_CIPHER> structure that contains the
-implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
-details of the B<EVP_CIPHER> structure.
-
-=head1 SEE ALSO
-
-L<evp(7)>,
-L<EVP_EncryptInit(3)>,
-L<EVP_CIPHER_meth_new(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
-
diff --git a/doc/man3/EVP_aes_128_gcm.pod b/doc/man3/EVP_aes_128_gcm.pod
new file mode 100644
index 000000000000..0575901503b2
--- /dev/null
+++ b/doc/man3/EVP_aes_128_gcm.pod
@@ -0,0 +1,194 @@
+=pod
+
+=head1 NAME
+
+EVP_aes_128_cbc,
+EVP_aes_192_cbc,
+EVP_aes_256_cbc,
+EVP_aes_128_cfb,
+EVP_aes_192_cfb,
+EVP_aes_256_cfb,
+EVP_aes_128_cfb1,
+EVP_aes_192_cfb1,
+EVP_aes_256_cfb1,
+EVP_aes_128_cfb8,
+EVP_aes_192_cfb8,
+EVP_aes_256_cfb8,
+EVP_aes_128_cfb128,
+EVP_aes_192_cfb128,
+EVP_aes_256_cfb128,
+EVP_aes_128_ctr,
+EVP_aes_192_ctr,
+EVP_aes_256_ctr,
+EVP_aes_128_ecb,
+EVP_aes_192_ecb,
+EVP_aes_256_ecb,
+EVP_aes_128_ofb,
+EVP_aes_192_ofb,
+EVP_aes_256_ofb,
+EVP_aes_128_cbc_hmac_sha1,
+EVP_aes_256_cbc_hmac_sha1,
+EVP_aes_128_cbc_hmac_sha256,
+EVP_aes_256_cbc_hmac_sha256,
+EVP_aes_128_ccm,
+EVP_aes_192_ccm,
+EVP_aes_256_ccm,
+EVP_aes_128_gcm,
+EVP_aes_192_gcm,
+EVP_aes_256_gcm,
+EVP_aes_128_ocb,
+EVP_aes_192_ocb,
+EVP_aes_256_ocb,
+EVP_aes_128_wrap,
+EVP_aes_192_wrap,
+EVP_aes_256_wrap,
+EVP_aes_128_wrap_pad,
+EVP_aes_192_wrap_pad,
+EVP_aes_256_wrap_pad,
+EVP_aes_128_xts,
+EVP_aes_256_xts
+- EVP AES cipher
+
+=head1 SYNOPSIS
+
+=for openssl generic
+
+ #include <openssl/evp.h>
+
+ const EVP_CIPHER *EVP_ciphername(void)
+
+I<EVP_ciphername> is used a placeholder for any of the described cipher
+functions, such as I<EVP_aes_128_cbc>.
+
+=head1 DESCRIPTION
+
+The AES encryption algorithm for EVP.
+
+=over 4
+
+=item EVP_aes_128_cbc(),
+EVP_aes_192_cbc(),
+EVP_aes_256_cbc(),
+EVP_aes_128_cfb(),
+EVP_aes_192_cfb(),
+EVP_aes_256_cfb(),
+EVP_aes_128_cfb1(),
+EVP_aes_192_cfb1(),
+EVP_aes_256_cfb1(),
+EVP_aes_128_cfb8(),
+EVP_aes_192_cfb8(),
+EVP_aes_256_cfb8(),
+EVP_aes_128_cfb128(),
+EVP_aes_192_cfb128(),
+EVP_aes_256_cfb128(),
+EVP_aes_128_ctr(),
+EVP_aes_192_ctr(),
+EVP_aes_256_ctr(),
+EVP_aes_128_ecb(),
+EVP_aes_192_ecb(),
+EVP_aes_256_ecb(),
+EVP_aes_128_ofb(),
+EVP_aes_192_ofb(),
+EVP_aes_256_ofb()
+
+AES for 128, 192 and 256 bit keys in the following modes: CBC, CFB with 128-bit
+shift, CFB with 1-bit shift, CFB with 8-bit shift, CTR, ECB, and OFB.
+
+=item EVP_aes_128_cbc_hmac_sha1(),
+EVP_aes_256_cbc_hmac_sha1()
+
+Authenticated encryption with AES in CBC mode using SHA-1 as HMAC, with keys of
+128 and 256 bits length respectively. The authentication tag is 160 bits long.
+
+WARNING: this is not intended for usage outside of TLS and requires calling of
+some undocumented ctrl functions. These ciphers do not conform to the EVP AEAD
+interface.
+
+=item EVP_aes_128_cbc_hmac_sha256(),
+EVP_aes_256_cbc_hmac_sha256()
+
+Authenticated encryption with AES in CBC mode using SHA256 (SHA-2, 256-bits) as
+HMAC, with keys of 128 and 256 bits length respectively. The authentication tag
+is 256 bits long.
+
+WARNING: this is not intended for usage outside of TLS and requires calling of
+some undocumented ctrl functions. These ciphers do not conform to the EVP AEAD
+interface.
+
+=item EVP_aes_128_ccm(),
+EVP_aes_192_ccm(),
+EVP_aes_256_ccm(),
+EVP_aes_128_gcm(),
+EVP_aes_192_gcm(),
+EVP_aes_256_gcm(),
+EVP_aes_128_ocb(),
+EVP_aes_192_ocb(),
+EVP_aes_256_ocb()
+
+AES for 128, 192 and 256 bit keys in CBC-MAC Mode (CCM), Galois Counter Mode
+(GCM) and OCB Mode respectively. These ciphers require additional control
+operations to function correctly, see the L<EVP_EncryptInit(3)/AEAD Interface>
+section for details.
+
+=item EVP_aes_128_wrap(),
+EVP_aes_192_wrap(),
+EVP_aes_256_wrap(),
+EVP_aes_128_wrap_pad(),
+EVP_aes_128_wrap(),
+EVP_aes_192_wrap(),
+EVP_aes_256_wrap(),
+EVP_aes_192_wrap_pad(),
+EVP_aes_128_wrap(),
+EVP_aes_192_wrap(),
+EVP_aes_256_wrap(),
+EVP_aes_256_wrap_pad()
+
+AES key wrap with 128, 192 and 256 bit keys, as according to RFC 3394 section
+2.2.1 ("wrap") and RFC 5649 section 4.1 ("wrap with padding") respectively.
+
+=item EVP_aes_128_xts(),
+EVP_aes_256_xts()
+
+AES XTS mode (XTS-AES) is standardized in IEEE Std. 1619-2007 and described in NIST
+SP 800-38E. The XTS (XEX-based tweaked-codebook mode with ciphertext stealing)
+mode was designed by Prof. Phillip Rogaway of University of California, Davis,
+intended for encrypting data on a storage device.
+
+XTS-AES provides confidentiality but not authentication of data. It also
+requires a key of double-length for protection of a certain key size.
+In particular, XTS-AES-128 (B<EVP_aes_128_xts>) takes input of a 256-bit key to
+achieve AES 128-bit security, and XTS-AES-256 (B<EVP_aes_256_xts>) takes input
+of a 512-bit key to achieve AES 256-bit security.
+
+The XTS implementation in OpenSSL does not support streaming. That is there must
+only be one L<EVP_EncryptUpdate(3)> call per L<EVP_EncryptInit_ex(3)> call (and
+similarly with the "Decrypt" functions).
+
+The I<iv> parameter to L<EVP_EncryptInit_ex(3)> or L<EVP_DecryptInit_ex(3)> is
+the XTS "tweak" value.
+
+=back
+
+=head1 RETURN VALUES
+
+These functions return an B<EVP_CIPHER> structure that contains the
+implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
+details of the B<EVP_CIPHER> structure.
+
+=head1 SEE ALSO
+
+L<evp(7)>,
+L<EVP_EncryptInit(3)>,
+L<EVP_CIPHER_meth_new(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
+
diff --git a/doc/man3/EVP_aria.pod b/doc/man3/EVP_aria.pod
deleted file mode 100644
index c30ff9929cae..000000000000
--- a/doc/man3/EVP_aria.pod
+++ /dev/null
@@ -1,117 +0,0 @@
-=pod
-
-=head1 NAME
-
-EVP_aria_128_cbc,
-EVP_aria_192_cbc,
-EVP_aria_256_cbc,
-EVP_aria_128_cfb,
-EVP_aria_192_cfb,
-EVP_aria_256_cfb,
-EVP_aria_128_cfb1,
-EVP_aria_192_cfb1,
-EVP_aria_256_cfb1,
-EVP_aria_128_cfb8,
-EVP_aria_192_cfb8,
-EVP_aria_256_cfb8,
-EVP_aria_128_cfb128,
-EVP_aria_192_cfb128,
-EVP_aria_256_cfb128,
-EVP_aria_128_ctr,
-EVP_aria_192_ctr,
-EVP_aria_256_ctr,
-EVP_aria_128_ecb,
-EVP_aria_192_ecb,
-EVP_aria_256_ecb,
-EVP_aria_128_ofb,
-EVP_aria_192_ofb,
-EVP_aria_256_ofb,
-EVP_aria_128_ccm,
-EVP_aria_192_ccm,
-EVP_aria_256_ccm,
-EVP_aria_128_gcm,
-EVP_aria_192_gcm,
-EVP_aria_256_gcm,
-- EVP ARIA cipher
-
-=head1 SYNOPSIS
-
-=for comment generic
-
- #include <openssl/evp.h>
-
- const EVP_CIPHER *EVP_ciphername(void)
-
-I<EVP_ciphername> is used a placeholder for any of the described cipher
-functions, such as I<EVP_aria_128_cbc>.
-
-=head1 DESCRIPTION
-
-The ARIA encryption algorithm for EVP.
-
-=over 4
-
-=item EVP_aria_128_cbc(),
-EVP_aria_192_cbc(),
-EVP_aria_256_cbc(),
-EVP_aria_128_cfb(),
-EVP_aria_192_cfb(),
-EVP_aria_256_cfb(),
-EVP_aria_128_cfb1(),
-EVP_aria_192_cfb1(),
-EVP_aria_256_cfb1(),
-EVP_aria_128_cfb8(),
-EVP_aria_192_cfb8(),
-EVP_aria_256_cfb8(),
-EVP_aria_128_cfb128(),
-EVP_aria_192_cfb128(),
-EVP_aria_256_cfb128(),
-EVP_aria_128_ctr(),
-EVP_aria_192_ctr(),
-EVP_aria_256_ctr(),
-EVP_aria_128_ecb(),
-EVP_aria_192_ecb(),
-EVP_aria_256_ecb(),
-EVP_aria_128_ofb(),
-EVP_aria_192_ofb(),
-EVP_aria_256_ofb()
-
-ARIA for 128, 192 and 256 bit keys in the following modes: CBC, CFB with
-128-bit shift, CFB with 1-bit shift, CFB with 8-bit shift, CTR, ECB and OFB.
-
-=item EVP_aria_128_ccm(),
-EVP_aria_192_ccm(),
-EVP_aria_256_ccm(),
-EVP_aria_128_gcm(),
-EVP_aria_192_gcm(),
-EVP_aria_256_gcm(),
-
-ARIA for 128, 192 and 256 bit keys in CBC-MAC Mode (CCM) and Galois Counter
-Mode (GCM). These ciphers require additional control operations to function
-correctly, see the L<EVP_EncryptInit(3)/AEAD Interface> section for details.
-
-=back
-
-=head1 RETURN VALUES
-
-These functions return an B<EVP_CIPHER> structure that contains the
-implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
-details of the B<EVP_CIPHER> structure.
-
-=head1 SEE ALSO
-
-L<evp(7)>,
-L<EVP_EncryptInit(3)>,
-L<EVP_CIPHER_meth_new(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
-
diff --git a/doc/man3/EVP_aria_128_gcm.pod b/doc/man3/EVP_aria_128_gcm.pod
new file mode 100644
index 000000000000..6471acb24954
--- /dev/null
+++ b/doc/man3/EVP_aria_128_gcm.pod
@@ -0,0 +1,117 @@
+=pod
+
+=head1 NAME
+
+EVP_aria_128_cbc,
+EVP_aria_192_cbc,
+EVP_aria_256_cbc,
+EVP_aria_128_cfb,
+EVP_aria_192_cfb,
+EVP_aria_256_cfb,
+EVP_aria_128_cfb1,
+EVP_aria_192_cfb1,
+EVP_aria_256_cfb1,
+EVP_aria_128_cfb8,
+EVP_aria_192_cfb8,
+EVP_aria_256_cfb8,
+EVP_aria_128_cfb128,
+EVP_aria_192_cfb128,
+EVP_aria_256_cfb128,
+EVP_aria_128_ctr,
+EVP_aria_192_ctr,
+EVP_aria_256_ctr,
+EVP_aria_128_ecb,
+EVP_aria_192_ecb,
+EVP_aria_256_ecb,
+EVP_aria_128_ofb,
+EVP_aria_192_ofb,
+EVP_aria_256_ofb,
+EVP_aria_128_ccm,
+EVP_aria_192_ccm,
+EVP_aria_256_ccm,
+EVP_aria_128_gcm,
+EVP_aria_192_gcm,
+EVP_aria_256_gcm,
+- EVP ARIA cipher
+
+=head1 SYNOPSIS
+
+=for openssl generic
+
+ #include <openssl/evp.h>
+
+ const EVP_CIPHER *EVP_ciphername(void)
+
+I<EVP_ciphername> is used a placeholder for any of the described cipher
+functions, such as I<EVP_aria_128_cbc>.
+
+=head1 DESCRIPTION
+
+The ARIA encryption algorithm for EVP.
+
+=over 4
+
+=item EVP_aria_128_cbc(),
+EVP_aria_192_cbc(),
+EVP_aria_256_cbc(),
+EVP_aria_128_cfb(),
+EVP_aria_192_cfb(),
+EVP_aria_256_cfb(),
+EVP_aria_128_cfb1(),
+EVP_aria_192_cfb1(),
+EVP_aria_256_cfb1(),
+EVP_aria_128_cfb8(),
+EVP_aria_192_cfb8(),
+EVP_aria_256_cfb8(),
+EVP_aria_128_cfb128(),
+EVP_aria_192_cfb128(),
+EVP_aria_256_cfb128(),
+EVP_aria_128_ctr(),
+EVP_aria_192_ctr(),
+EVP_aria_256_ctr(),
+EVP_aria_128_ecb(),
+EVP_aria_192_ecb(),
+EVP_aria_256_ecb(),
+EVP_aria_128_ofb(),
+EVP_aria_192_ofb(),
+EVP_aria_256_ofb()
+
+ARIA for 128, 192 and 256 bit keys in the following modes: CBC, CFB with
+128-bit shift, CFB with 1-bit shift, CFB with 8-bit shift, CTR, ECB and OFB.
+
+=item EVP_aria_128_ccm(),
+EVP_aria_192_ccm(),
+EVP_aria_256_ccm(),
+EVP_aria_128_gcm(),
+EVP_aria_192_gcm(),
+EVP_aria_256_gcm(),
+
+ARIA for 128, 192 and 256 bit keys in CBC-MAC Mode (CCM) and Galois Counter
+Mode (GCM). These ciphers require additional control operations to function
+correctly, see the L<EVP_EncryptInit(3)/AEAD Interface> section for details.
+
+=back
+
+=head1 RETURN VALUES
+
+These functions return an B<EVP_CIPHER> structure that contains the
+implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
+details of the B<EVP_CIPHER> structure.
+
+=head1 SEE ALSO
+
+L<evp(7)>,
+L<EVP_EncryptInit(3)>,
+L<EVP_CIPHER_meth_new(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
+
diff --git a/doc/man3/EVP_bf_cbc.pod b/doc/man3/EVP_bf_cbc.pod
index 505d41b4943f..03385620873e 100644
--- a/doc/man3/EVP_bf_cbc.pod
+++ b/doc/man3/EVP_bf_cbc.pod
@@ -13,11 +13,11 @@ EVP_bf_ofb
#include <openssl/evp.h>
- const EVP_CIPHER *EVP_bf_cbc(void)
- const EVP_CIPHER *EVP_bf_cfb(void)
- const EVP_CIPHER *EVP_bf_cfb64(void)
- const EVP_CIPHER *EVP_bf_ecb(void)
- const EVP_CIPHER *EVP_bf_ofb(void)
+ const EVP_CIPHER *EVP_bf_cbc(void);
+ const EVP_CIPHER *EVP_bf_cfb(void);
+ const EVP_CIPHER *EVP_bf_cfb64(void);
+ const EVP_CIPHER *EVP_bf_ecb(void);
+ const EVP_CIPHER *EVP_bf_ofb(void);
=head1 DESCRIPTION
@@ -51,12 +51,11 @@ L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
-
diff --git a/doc/man3/EVP_blake2b512.pod b/doc/man3/EVP_blake2b512.pod
index 9b56f3e58164..649a29c98717 100644
--- a/doc/man3/EVP_blake2b512.pod
+++ b/doc/man3/EVP_blake2b512.pod
@@ -34,7 +34,7 @@ The BLAKE2b algorithm that produces a 512-bit output from a given input.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
-implementation of the symmetric cipher. See L<EVP_MD_meth_new(3)> for
+implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
@@ -54,9 +54,9 @@ L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_camellia.pod b/doc/man3/EVP_camellia.pod
deleted file mode 100644
index 6ad59f84b110..000000000000
--- a/doc/man3/EVP_camellia.pod
+++ /dev/null
@@ -1,100 +0,0 @@
-=pod
-
-=head1 NAME
-
-EVP_camellia_128_cbc,
-EVP_camellia_192_cbc,
-EVP_camellia_256_cbc,
-EVP_camellia_128_cfb,
-EVP_camellia_192_cfb,
-EVP_camellia_256_cfb,
-EVP_camellia_128_cfb1,
-EVP_camellia_192_cfb1,
-EVP_camellia_256_cfb1,
-EVP_camellia_128_cfb8,
-EVP_camellia_192_cfb8,
-EVP_camellia_256_cfb8,
-EVP_camellia_128_cfb128,
-EVP_camellia_192_cfb128,
-EVP_camellia_256_cfb128,
-EVP_camellia_128_ctr,
-EVP_camellia_192_ctr,
-EVP_camellia_256_ctr,
-EVP_camellia_128_ecb,
-EVP_camellia_192_ecb,
-EVP_camellia_256_ecb,
-EVP_camellia_128_ofb,
-EVP_camellia_192_ofb,
-EVP_camellia_256_ofb
-- EVP Camellia cipher
-
-=head1 SYNOPSIS
-
-=for comment generic
-
- #include <openssl/evp.h>
-
- const EVP_CIPHER *EVP_ciphername(void)
-
-I<EVP_ciphername> is used a placeholder for any of the described cipher
-functions, such as I<EVP_camellia_128_cbc>.
-
-=head1 DESCRIPTION
-
-The Camellia encryption algorithm for EVP.
-
-=over 4
-
-=item EVP_camellia_128_cbc(),
-EVP_camellia_192_cbc(),
-EVP_camellia_256_cbc(),
-EVP_camellia_128_cfb(),
-EVP_camellia_192_cfb(),
-EVP_camellia_256_cfb(),
-EVP_camellia_128_cfb1(),
-EVP_camellia_192_cfb1(),
-EVP_camellia_256_cfb1(),
-EVP_camellia_128_cfb8(),
-EVP_camellia_192_cfb8(),
-EVP_camellia_256_cfb8(),
-EVP_camellia_128_cfb128(),
-EVP_camellia_192_cfb128(),
-EVP_camellia_256_cfb128(),
-EVP_camellia_128_ctr(),
-EVP_camellia_192_ctr(),
-EVP_camellia_256_ctr(),
-EVP_camellia_128_ecb(),
-EVP_camellia_192_ecb(),
-EVP_camellia_256_ecb(),
-EVP_camellia_128_ofb(),
-EVP_camellia_192_ofb(),
-EVP_camellia_256_ofb()
-
-Camellia for 128, 192 and 256 bit keys in the following modes: CBC, CFB with
-128-bit shift, CFB with 1-bit shift, CFB with 8-bit shift, CTR, ECB and OFB.
-
-=back
-
-=head1 RETURN VALUES
-
-These functions return an B<EVP_CIPHER> structure that contains the
-implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
-details of the B<EVP_CIPHER> structure.
-
-=head1 SEE ALSO
-
-L<evp(7)>,
-L<EVP_EncryptInit(3)>,
-L<EVP_CIPHER_meth_new(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
-
diff --git a/doc/man3/EVP_camellia_128_ecb.pod b/doc/man3/EVP_camellia_128_ecb.pod
new file mode 100644
index 000000000000..4a57f79512c4
--- /dev/null
+++ b/doc/man3/EVP_camellia_128_ecb.pod
@@ -0,0 +1,100 @@
+=pod
+
+=head1 NAME
+
+EVP_camellia_128_cbc,
+EVP_camellia_192_cbc,
+EVP_camellia_256_cbc,
+EVP_camellia_128_cfb,
+EVP_camellia_192_cfb,
+EVP_camellia_256_cfb,
+EVP_camellia_128_cfb1,
+EVP_camellia_192_cfb1,
+EVP_camellia_256_cfb1,
+EVP_camellia_128_cfb8,
+EVP_camellia_192_cfb8,
+EVP_camellia_256_cfb8,
+EVP_camellia_128_cfb128,
+EVP_camellia_192_cfb128,
+EVP_camellia_256_cfb128,
+EVP_camellia_128_ctr,
+EVP_camellia_192_ctr,
+EVP_camellia_256_ctr,
+EVP_camellia_128_ecb,
+EVP_camellia_192_ecb,
+EVP_camellia_256_ecb,
+EVP_camellia_128_ofb,
+EVP_camellia_192_ofb,
+EVP_camellia_256_ofb
+- EVP Camellia cipher
+
+=head1 SYNOPSIS
+
+=for openssl generic
+
+ #include <openssl/evp.h>
+
+ const EVP_CIPHER *EVP_ciphername(void)
+
+I<EVP_ciphername> is used a placeholder for any of the described cipher
+functions, such as I<EVP_camellia_128_cbc>.
+
+=head1 DESCRIPTION
+
+The Camellia encryption algorithm for EVP.
+
+=over 4
+
+=item EVP_camellia_128_cbc(),
+EVP_camellia_192_cbc(),
+EVP_camellia_256_cbc(),
+EVP_camellia_128_cfb(),
+EVP_camellia_192_cfb(),
+EVP_camellia_256_cfb(),
+EVP_camellia_128_cfb1(),
+EVP_camellia_192_cfb1(),
+EVP_camellia_256_cfb1(),
+EVP_camellia_128_cfb8(),
+EVP_camellia_192_cfb8(),
+EVP_camellia_256_cfb8(),
+EVP_camellia_128_cfb128(),
+EVP_camellia_192_cfb128(),
+EVP_camellia_256_cfb128(),
+EVP_camellia_128_ctr(),
+EVP_camellia_192_ctr(),
+EVP_camellia_256_ctr(),
+EVP_camellia_128_ecb(),
+EVP_camellia_192_ecb(),
+EVP_camellia_256_ecb(),
+EVP_camellia_128_ofb(),
+EVP_camellia_192_ofb(),
+EVP_camellia_256_ofb()
+
+Camellia for 128, 192 and 256 bit keys in the following modes: CBC, CFB with
+128-bit shift, CFB with 1-bit shift, CFB with 8-bit shift, CTR, ECB and OFB.
+
+=back
+
+=head1 RETURN VALUES
+
+These functions return an B<EVP_CIPHER> structure that contains the
+implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
+details of the B<EVP_CIPHER> structure.
+
+=head1 SEE ALSO
+
+L<evp(7)>,
+L<EVP_EncryptInit(3)>,
+L<EVP_CIPHER_meth_new(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
+
diff --git a/doc/man3/EVP_cast5_cbc.pod b/doc/man3/EVP_cast5_cbc.pod
index 0be07279259f..e823a197f959 100644
--- a/doc/man3/EVP_cast5_cbc.pod
+++ b/doc/man3/EVP_cast5_cbc.pod
@@ -13,11 +13,11 @@ EVP_cast5_ofb
#include <openssl/evp.h>
- const EVP_CIPHER *EVP_cast5_cbc(void)
- const EVP_CIPHER *EVP_cast5_cfb(void)
- const EVP_CIPHER *EVP_cast5_cfb64(void)
- const EVP_CIPHER *EVP_cast5_ecb(void)
- const EVP_CIPHER *EVP_cast5_ofb(void)
+ const EVP_CIPHER *EVP_cast5_cbc(void);
+ const EVP_CIPHER *EVP_cast5_cfb(void);
+ const EVP_CIPHER *EVP_cast5_cfb64(void);
+ const EVP_CIPHER *EVP_cast5_ecb(void);
+ const EVP_CIPHER *EVP_cast5_ofb(void);
=head1 DESCRIPTION
@@ -51,12 +51,11 @@ L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
-
diff --git a/doc/man3/EVP_chacha20.pod b/doc/man3/EVP_chacha20.pod
index a21b64859568..060b1bfc254f 100644
--- a/doc/man3/EVP_chacha20.pod
+++ b/doc/man3/EVP_chacha20.pod
@@ -10,8 +10,8 @@ EVP_chacha20_poly1305
#include <openssl/evp.h>
- const EVP_CIPHER *EVP_chacha20(void)
- const EVP_CIPHER *EVP_chacha20_poly1305(void)
+ const EVP_CIPHER *EVP_chacha20(void);
+ const EVP_CIPHER *EVP_chacha20_poly1305(void);
=head1 DESCRIPTION
@@ -54,9 +54,9 @@ L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_des.pod b/doc/man3/EVP_des.pod
deleted file mode 100644
index a05149ff8586..000000000000
--- a/doc/man3/EVP_des.pod
+++ /dev/null
@@ -1,106 +0,0 @@
-=pod
-
-=head1 NAME
-
-EVP_des_cbc,
-EVP_des_cfb,
-EVP_des_cfb1,
-EVP_des_cfb8,
-EVP_des_cfb64,
-EVP_des_ecb,
-EVP_des_ofb,
-EVP_des_ede,
-EVP_des_ede_cbc,
-EVP_des_ede_cfb,
-EVP_des_ede_cfb64,
-EVP_des_ede_ecb,
-EVP_des_ede_ofb,
-EVP_des_ede3,
-EVP_des_ede3_cbc,
-EVP_des_ede3_cfb,
-EVP_des_ede3_cfb1,
-EVP_des_ede3_cfb8,
-EVP_des_ede3_cfb64,
-EVP_des_ede3_ecb,
-EVP_des_ede3_ofb,
-EVP_des_ede3_wrap
-- EVP DES cipher
-
-=head1 SYNOPSIS
-
-=for comment generic
-
- #include <openssl/evp.h>
-
- const EVP_CIPHER *EVP_ciphername(void)
-
-I<EVP_ciphername> is used a placeholder for any of the described cipher
-functions, such as I<EVP_des_cbc>.
-
-=head1 DESCRIPTION
-
-The DES encryption algorithm for EVP.
-
-=over 4
-
-=item EVP_des_cbc(),
-EVP_des_ecb(),
-EVP_des_cfb(),
-EVP_des_cfb1(),
-EVP_des_cfb8(),
-EVP_des_cfb64(),
-EVP_des_ofb()
-
-DES in CBC, ECB, CFB with 64-bit shift, CFB with 1-bit shift, CFB with 8-bit
-shift and OFB modes.
-
-=item EVP_des_ede(),
-EVP_des_ede_cbc(),
-EVP_des_ede_cfb(),
-EVP_des_ede_cfb64(),
-EVP_des_ede_ecb(),
-EVP_des_ede_ofb()
-
-Two key triple DES in ECB, CBC, CFB with 64-bit shift and OFB modes.
-
-=item EVP_des_ede3(),
-EVP_des_ede3_cbc(),
-EVP_des_ede3_cfb(),
-EVP_des_ede3_cfb1(),
-EVP_des_ede3_cfb8(),
-EVP_des_ede3_cfb64(),
-EVP_des_ede3_ecb(),
-EVP_des_ede3_ofb()
-
-Three-key triple DES in ECB, CBC, CFB with 64-bit shift, CFB with 1-bit shift,
-CFB with 8-bit shift and OFB modes.
-
-=item EVP_des_ede3_wrap()
-
-Triple-DES key wrap according to RFC 3217 Section 3.
-
-=back
-
-=head1 RETURN VALUES
-
-These functions return an B<EVP_CIPHER> structure that contains the
-implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
-details of the B<EVP_CIPHER> structure.
-
-=head1 SEE ALSO
-
-L<evp(7)>,
-L<EVP_EncryptInit(3)>,
-L<EVP_CIPHER_meth_new(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
-
diff --git a/doc/man3/EVP_des_cbc.pod b/doc/man3/EVP_des_cbc.pod
new file mode 100644
index 000000000000..fe9d5e6a0e07
--- /dev/null
+++ b/doc/man3/EVP_des_cbc.pod
@@ -0,0 +1,110 @@
+=pod
+
+=head1 NAME
+
+EVP_des_cbc,
+EVP_des_cfb,
+EVP_des_cfb1,
+EVP_des_cfb8,
+EVP_des_cfb64,
+EVP_des_ecb,
+EVP_des_ofb,
+EVP_des_ede,
+EVP_des_ede_cbc,
+EVP_des_ede_cfb,
+EVP_des_ede_cfb64,
+EVP_des_ede_ecb,
+EVP_des_ede_ofb,
+EVP_des_ede3,
+EVP_des_ede3_cbc,
+EVP_des_ede3_cfb,
+EVP_des_ede3_cfb1,
+EVP_des_ede3_cfb8,
+EVP_des_ede3_cfb64,
+EVP_des_ede3_ecb,
+EVP_des_ede3_ofb,
+EVP_des_ede3_wrap
+- EVP DES cipher
+
+=head1 SYNOPSIS
+
+=for openssl generic
+
+ #include <openssl/evp.h>
+
+ const EVP_CIPHER *EVP_ciphername(void)
+
+I<EVP_ciphername> is used a placeholder for any of the described cipher
+functions, such as I<EVP_des_cbc>.
+
+=head1 DESCRIPTION
+
+The DES encryption algorithm for EVP.
+
+=over 4
+
+=item EVP_des_cbc(),
+EVP_des_ecb(),
+EVP_des_cfb(),
+EVP_des_cfb1(),
+EVP_des_cfb8(),
+EVP_des_cfb64(),
+EVP_des_ofb()
+
+DES in CBC, ECB, CFB with 64-bit shift, CFB with 1-bit shift, CFB with 8-bit
+shift and OFB modes.
+
+None of these algorithms are provided by the OpenSSL default provider.
+To use them it is necessary to load either the OpenSSL legacy provider or another
+implementation.
+
+=item EVP_des_ede(),
+EVP_des_ede_cbc(),
+EVP_des_ede_cfb(),
+EVP_des_ede_cfb64(),
+EVP_des_ede_ecb(),
+EVP_des_ede_ofb()
+
+Two key triple DES in ECB, CBC, CFB with 64-bit shift and OFB modes.
+
+=item EVP_des_ede3(),
+EVP_des_ede3_cbc(),
+EVP_des_ede3_cfb(),
+EVP_des_ede3_cfb1(),
+EVP_des_ede3_cfb8(),
+EVP_des_ede3_cfb64(),
+EVP_des_ede3_ecb(),
+EVP_des_ede3_ofb()
+
+Three-key triple DES in ECB, CBC, CFB with 64-bit shift, CFB with 1-bit shift,
+CFB with 8-bit shift and OFB modes.
+
+=item EVP_des_ede3_wrap()
+
+Triple-DES key wrap according to RFC 3217 Section 3.
+
+=back
+
+=head1 RETURN VALUES
+
+These functions return an B<EVP_CIPHER> structure that contains the
+implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
+details of the B<EVP_CIPHER> structure.
+
+=head1 SEE ALSO
+
+L<evp(7)>,
+L<EVP_EncryptInit(3)>,
+L<EVP_CIPHER_meth_new(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
+
diff --git a/doc/man3/EVP_desx_cbc.pod b/doc/man3/EVP_desx_cbc.pod
index 321378e15a39..01987bf28cfb 100644
--- a/doc/man3/EVP_desx_cbc.pod
+++ b/doc/man3/EVP_desx_cbc.pod
@@ -9,7 +9,7 @@ EVP_desx_cbc
#include <openssl/evp.h>
- const EVP_CIPHER *EVP_desx_cbc(void)
+ const EVP_CIPHER *EVP_desx_cbc(void);
=head1 DESCRIPTION
@@ -23,6 +23,10 @@ All modes below use a key length of 128 bits and acts on blocks of 128-bits.
The DES-X algorithm in CBC mode.
+This algorithm is not provided by the OpenSSL default provider.
+To use it is necessary to load either the OpenSSL legacy provider or another
+implementation.
+
=back
=head1 RETURN VALUES
@@ -39,9 +43,9 @@ L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_idea_cbc.pod b/doc/man3/EVP_idea_cbc.pod
index 14dcc903b525..2fa5a2925f0f 100644
--- a/doc/man3/EVP_idea_cbc.pod
+++ b/doc/man3/EVP_idea_cbc.pod
@@ -13,11 +13,11 @@ EVP_idea_ofb
#include <openssl/evp.h>
- const EVP_CIPHER *EVP_idea_cbc(void)
- const EVP_CIPHER *EVP_idea_cfb(void)
- const EVP_CIPHER *EVP_idea_cfb64(void)
- const EVP_CIPHER *EVP_idea_ecb(void)
- const EVP_CIPHER *EVP_idea_ofb(void)
+ const EVP_CIPHER *EVP_idea_cbc(void);
+ const EVP_CIPHER *EVP_idea_cfb(void);
+ const EVP_CIPHER *EVP_idea_cfb64(void);
+ const EVP_CIPHER *EVP_idea_ecb(void);
+ const EVP_CIPHER *EVP_idea_ofb(void);
=head1 DESCRIPTION
@@ -49,12 +49,11 @@ L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
-
diff --git a/doc/man3/EVP_md2.pod b/doc/man3/EVP_md2.pod
index c66fb6f88392..420bb1545316 100644
--- a/doc/man3/EVP_md2.pod
+++ b/doc/man3/EVP_md2.pod
@@ -14,7 +14,7 @@ EVP_md2
=head1 DESCRIPTION
MD2 is a cryptographic hash function standardized in RFC 1319 and designed by
-Ronald Rivest.
+Ronald Rivest. This implementation is only available with the legacy provider.
=over 4
@@ -28,7 +28,7 @@ The MD2 algorithm which produces a 128-bit output from a given input.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
-implementation of the symmetric cipher. See L<EVP_MD_meth_new(3)> for
+implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
@@ -38,13 +38,14 @@ IETF RFC 1319.
=head1 SEE ALSO
L<evp(7)>,
+L<provider(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_md4.pod b/doc/man3/EVP_md4.pod
index 778ed0281eb1..a3d3beaaf83d 100644
--- a/doc/man3/EVP_md4.pod
+++ b/doc/man3/EVP_md4.pod
@@ -14,7 +14,8 @@ EVP_md4
=head1 DESCRIPTION
MD4 is a cryptographic hash function standardized in RFC 1320 and designed by
-Ronald Rivest, first published in 1990.
+Ronald Rivest, first published in 1990. This implementation is only available
+with the legacy provider.
=over 4
@@ -28,7 +29,7 @@ The MD4 algorithm which produces a 128-bit output from a given input.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
-implementation of the symmetric cipher. See L<EVP_MD_meth_new(3)> for
+implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
@@ -38,13 +39,14 @@ IETF RFC 1320.
=head1 SEE ALSO
L<evp(7)>,
+L<provider(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_md5.pod b/doc/man3/EVP_md5.pod
index ed0f99c99d37..9d729601a066 100644
--- a/doc/man3/EVP_md5.pod
+++ b/doc/man3/EVP_md5.pod
@@ -40,7 +40,7 @@ WARNING: this algorithm is not intended for non-SSL usage.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
-implementation of the symmetric cipher. See L<EVP_MD_meth_new(3)> for
+implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
@@ -54,9 +54,9 @@ L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_mdc2.pod b/doc/man3/EVP_mdc2.pod
index 13ff9cfb4962..7ebed04c700d 100644
--- a/doc/man3/EVP_mdc2.pod
+++ b/doc/man3/EVP_mdc2.pod
@@ -14,7 +14,8 @@ EVP_mdc2
=head1 DESCRIPTION
MDC-2 (Modification Detection Code 2 or Meyer-Schilling) is a cryptographic
-hash function based on a block cipher.
+hash function based on a block cipher. This implementation is only available
+with the legacy provider.
=over 4
@@ -28,7 +29,7 @@ The MDC-2DES algorithm of using MDC-2 with the DES block cipher. It produces a
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
-implementation of the symmetric cipher. See L<EVP_MD_meth_new(3)> for
+implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
@@ -38,13 +39,14 @@ ISO/IEC 10118-2:2000 Hash-Function 2, with DES as the underlying block cipher.
=head1 SEE ALSO
L<evp(7)>,
+L<provider(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_rc2_cbc.pod b/doc/man3/EVP_rc2_cbc.pod
index 79769b82635a..e6111ff3afc5 100644
--- a/doc/man3/EVP_rc2_cbc.pod
+++ b/doc/man3/EVP_rc2_cbc.pod
@@ -15,13 +15,13 @@ EVP_rc2_64_cbc
#include <openssl/evp.h>
- const EVP_CIPHER *EVP_rc2_cbc(void)
- const EVP_CIPHER *EVP_rc2_cfb(void)
- const EVP_CIPHER *EVP_rc2_cfb64(void)
- const EVP_CIPHER *EVP_rc2_ecb(void)
- const EVP_CIPHER *EVP_rc2_ofb(void)
- const EVP_CIPHER *EVP_rc2_40_cbc(void)
- const EVP_CIPHER *EVP_rc2_64_cbc(void)
+ const EVP_CIPHER *EVP_rc2_cbc(void);
+ const EVP_CIPHER *EVP_rc2_cfb(void);
+ const EVP_CIPHER *EVP_rc2_cfb64(void);
+ const EVP_CIPHER *EVP_rc2_ecb(void);
+ const EVP_CIPHER *EVP_rc2_ofb(void);
+ const EVP_CIPHER *EVP_rc2_40_cbc(void);
+ const EVP_CIPHER *EVP_rc2_64_cbc(void);
=head1 DESCRIPTION
@@ -65,9 +65,9 @@ L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_rc4.pod b/doc/man3/EVP_rc4.pod
index 7d642efdd950..9deaab97f82c 100644
--- a/doc/man3/EVP_rc4.pod
+++ b/doc/man3/EVP_rc4.pod
@@ -11,9 +11,9 @@ EVP_rc4_hmac_md5
#include <openssl/evp.h>
- const EVP_CIPHER *EVP_rc4(void)
- const EVP_CIPHER *EVP_rc4_40(void)
- const EVP_CIPHER *EVP_rc4_hmac_md5(void)
+ const EVP_CIPHER *EVP_rc4(void);
+ const EVP_CIPHER *EVP_rc4_40(void);
+ const EVP_CIPHER *EVP_rc4_hmac_md5(void);
=head1 DESCRIPTION
@@ -57,12 +57,11 @@ L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
-
diff --git a/doc/man3/EVP_rc5_32_12_16_cbc.pod b/doc/man3/EVP_rc5_32_12_16_cbc.pod
index 9eb8bd9dc3f9..8ac23b4a9ed1 100644
--- a/doc/man3/EVP_rc5_32_12_16_cbc.pod
+++ b/doc/man3/EVP_rc5_32_12_16_cbc.pod
@@ -13,11 +13,11 @@ EVP_rc5_32_12_16_ofb
#include <openssl/evp.h>
- const EVP_CIPHER *EVP_rc5_32_12_16_cbc(void)
- const EVP_CIPHER *EVP_rc5_32_12_16_cfb(void)
- const EVP_CIPHER *EVP_rc5_32_12_16_cfb64(void)
- const EVP_CIPHER *EVP_rc5_32_12_16_ecb(void)
- const EVP_CIPHER *EVP_rc5_32_12_16_ofb(void)
+ const EVP_CIPHER *EVP_rc5_32_12_16_cbc(void);
+ const EVP_CIPHER *EVP_rc5_32_12_16_cfb(void);
+ const EVP_CIPHER *EVP_rc5_32_12_16_cfb64(void);
+ const EVP_CIPHER *EVP_rc5_32_12_16_ecb(void);
+ const EVP_CIPHER *EVP_rc5_32_12_16_ofb(void);
=head1 DESCRIPTION
@@ -71,12 +71,11 @@ L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
-
diff --git a/doc/man3/EVP_ripemd160.pod b/doc/man3/EVP_ripemd160.pod
index bbb2dd959697..e559b0344942 100644
--- a/doc/man3/EVP_ripemd160.pod
+++ b/doc/man3/EVP_ripemd160.pod
@@ -15,6 +15,7 @@ EVP_ripemd160
RIPEMD-160 is a cryptographic hash function first published in 1996 belonging
to the RIPEMD family (RACE Integrity Primitives Evaluation Message Digest).
+This implementation is only available with the legacy provider.
=over 4
@@ -27,7 +28,7 @@ The RIPEMD-160 algorithm which produces a 160-bit output from a given input.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
-implementation of the symmetric cipher. See L<EVP_MD_meth_new(3)> for
+implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
@@ -37,13 +38,14 @@ ISO/IEC 10118-3:2016 Dedicated Hash-Function 1 (RIPEMD-160).
=head1 SEE ALSO
L<evp(7)>,
+L<provider(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_seed_cbc.pod b/doc/man3/EVP_seed_cbc.pod
index 0d2329510d5e..eef7dd540db2 100644
--- a/doc/man3/EVP_seed_cbc.pod
+++ b/doc/man3/EVP_seed_cbc.pod
@@ -13,11 +13,11 @@ EVP_seed_ofb
#include <openssl/evp.h>
- const EVP_CIPHER *EVP_seed_cbc(void)
- const EVP_CIPHER *EVP_seed_cfb(void)
- const EVP_CIPHER *EVP_seed_cfb128(void)
- const EVP_CIPHER *EVP_seed_ecb(void)
- const EVP_CIPHER *EVP_seed_ofb(void)
+ const EVP_CIPHER *EVP_seed_cbc(void);
+ const EVP_CIPHER *EVP_seed_cfb(void);
+ const EVP_CIPHER *EVP_seed_cfb128(void);
+ const EVP_CIPHER *EVP_seed_ecb(void);
+ const EVP_CIPHER *EVP_seed_ofb(void);
=head1 DESCRIPTION
@@ -51,12 +51,11 @@ L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
-
diff --git a/doc/man3/EVP_set_default_properties.pod b/doc/man3/EVP_set_default_properties.pod
new file mode 100644
index 000000000000..2d862772c251
--- /dev/null
+++ b/doc/man3/EVP_set_default_properties.pod
@@ -0,0 +1,71 @@
+=pod
+
+=head1 NAME
+
+EVP_set_default_properties, EVP_default_properties_enable_fips,
+EVP_default_properties_is_fips_enabled
+- Set default properties for future algorithm fetches
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_set_default_properties(OSSL_LIB_CTX *libctx, const char *propq);
+ int EVP_default_properties_enable_fips(OSSL_LIB_CTX *libctx, int enable);
+ int EVP_default_properties_is_fips_enabled(OSSL_LIB_CTX *libctx);
+
+=head1 DESCRIPTION
+
+EVP_set_default_properties() sets the default properties for all
+future EVP algorithm fetches, implicit as well as explicit. See
+L<crypto(7)/ALGORITHM FETCHING> for information about implicit and explicit
+fetching.
+
+EVP_set_default_properties stores the properties given with the string
+I<propq> among the EVP data that's been stored in the library context
+given with I<libctx> (NULL signifies the default library context).
+
+Any previous default property for the specified library context will
+be dropped.
+
+EVP_default_properties_enable_fips() sets the 'fips=yes' to be a default property
+if I<enable> is non zero, otherwise it clears 'fips' from the default property
+query for the given I<libctx>. It merges the fips default property query with any
+existing query strings that have been set via EVP_set_default_properties().
+
+EVP_default_properties_is_fips_enabled() indicates if 'fips=yes' is a default
+property for the given I<libctx>.
+
+=head1 NOTES
+
+EVP_set_default_properties() and EVP_default_properties_enable_fips() are not
+thread safe. They are intended to be called only during the initialisation
+phase of a I<libctx>.
+
+=head1 RETURN VALUES
+
+EVP_set_default_properties() and EVP_default_properties_enable_fips() return 1
+on success, or 0 on failure. An error is placed on the error stack if a
+failure occurs.
+
+EVP_default_properties_is_fips_enabled() returns 1 if the 'fips=yes' default
+property is set for the given I<libctx>, otherwise it returns 0.
+
+=head1 SEE ALSO
+
+L<EVP_MD_fetch(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_sha1.pod b/doc/man3/EVP_sha1.pod
index 93ba64410237..f3e9e8d4fa19 100644
--- a/doc/man3/EVP_sha1.pod
+++ b/doc/man3/EVP_sha1.pod
@@ -29,7 +29,7 @@ The SHA-1 algorithm which produces a 160-bit output from a given input.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
-implementation of the symmetric cipher. See L<EVP_MD_meth_new(3)> for
+implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
@@ -43,9 +43,9 @@ L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_sha224.pod b/doc/man3/EVP_sha224.pod
index 2de20bb1520f..97881b54635c 100644
--- a/doc/man3/EVP_sha224.pod
+++ b/doc/man3/EVP_sha224.pod
@@ -49,7 +49,7 @@ their outputs are of the same size.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
-implementation of the symmetric cipher. See L<EVP_MD_meth_new(3)> for
+implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
@@ -63,9 +63,9 @@ L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_sha3_224.pod b/doc/man3/EVP_sha3_224.pod
index c7bccc9f1f2d..4c349f55d32f 100644
--- a/doc/man3/EVP_sha3_224.pod
+++ b/doc/man3/EVP_sha3_224.pod
@@ -54,7 +54,7 @@ B<EVP_shake256> provides that of 256 bits.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
-implementation of the symmetric cipher. See L<EVP_MD_meth_new(3)> for
+implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
@@ -68,9 +68,9 @@ L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_sm3.pod b/doc/man3/EVP_sm3.pod
index 50ec429c7756..96997b1128ae 100644
--- a/doc/man3/EVP_sm3.pod
+++ b/doc/man3/EVP_sm3.pod
@@ -28,7 +28,7 @@ The SM3 hash function.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
-implementation of the symmetric cipher. See L<EVP_MD_meth_new(3)> for
+implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
@@ -42,10 +42,10 @@ L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
Copyright 2017 Ribose Inc. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_sm4_cbc.pod b/doc/man3/EVP_sm4_cbc.pod
index ecd51f09d41f..51df4435bc08 100644
--- a/doc/man3/EVP_sm4_cbc.pod
+++ b/doc/man3/EVP_sm4_cbc.pod
@@ -58,7 +58,7 @@ L<EVP_CIPHER_meth_new(3)>
Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
Copyright 2017 Ribose Inc. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/EVP_whirlpool.pod b/doc/man3/EVP_whirlpool.pod
index bf60b126b67a..3aaf1d50add4 100644
--- a/doc/man3/EVP_whirlpool.pod
+++ b/doc/man3/EVP_whirlpool.pod
@@ -14,7 +14,8 @@ EVP_whirlpool
=head1 DESCRIPTION
WHIRLPOOL is a cryptographic hash function standardized in ISO/IEC 10118-3:2004
-designed by Vincent Rijmen and Paulo S. L. M. Barreto.
+designed by Vincent Rijmen and Paulo S. L. M. Barreto. This implementation is
+only available with the legacy provider.
=over 4
@@ -29,7 +30,7 @@ input.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
-implementation of the symmetric cipher. See L<EVP_MD_meth_new(3)> for
+implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
@@ -39,13 +40,14 @@ ISO/IEC 10118-3:2004.
=head1 SEE ALSO
L<evp(7)>,
+L<provider(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/HMAC.pod b/doc/man3/HMAC.pod
index 27022686f7aa..87a567242f60 100644
--- a/doc/man3/HMAC.pod
+++ b/doc/man3/HMAC.pod
@@ -20,10 +20,14 @@ HMAC_size
#include <openssl/hmac.h>
- unsigned char *HMAC(const EVP_MD *evp_md, const void *key,
- int key_len, const unsigned char *d, size_t n,
+ unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
+ const unsigned char *data, size_t data_len,
unsigned char *md, unsigned int *md_len);
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
HMAC_CTX *HMAC_CTX_new(void);
int HMAC_CTX_reset(HMAC_CTX *ctx);
@@ -40,12 +44,12 @@ HMAC_size
size_t HMAC_size(const HMAC_CTX *e);
-Deprecated:
+The following function has been deprecated since OpenSSL 1.1.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
- #if OPENSSL_API_COMPAT < 0x10100000L
int HMAC_Init(HMAC_CTX *ctx, const void *key, int key_len,
const EVP_MD *md);
- #endif
=head1 DESCRIPTION
@@ -53,23 +57,31 @@ HMAC is a MAC (message authentication code), i.e. a keyed hash
function used for message authentication, which is based on a hash
function.
-HMAC() computes the message authentication code of the B<n> bytes at
-B<d> using the hash function B<evp_md> and the key B<key> which is
-B<key_len> bytes long.
+HMAC() computes the message authentication code of the I<data_len> bytes at
+I<data> using the hash function I<evp_md> and the key I<key> which is
+I<key_len> bytes long. The I<key> may also be NULL with I<key_len> being 0.
-It places the result in B<md> (which must have space for the output of
+It places the result in I<md> (which must have space for the output of
the hash function, which is no more than B<EVP_MAX_MD_SIZE> bytes).
-If B<md> is NULL, the digest is placed in a static array. The size of
-the output is placed in B<md_len>, unless it is B<NULL>. Note: passing a NULL
-value for B<md> to use the static array is not thread safe.
+If I<md> is NULL, the digest is placed in a static array. The size of
+the output is placed in I<md_len>, unless it is NULL. Note: passing a NULL
+value for I<md> to use the static array is not thread safe.
-B<evp_md> is a message digest such as EVP_sha1(), EVP_ripemd160() etc. HMAC does
-not support variable output length digests such as EVP_shake128() and
+I<evp_md> is a message digest such as EVP_sha1(), EVP_ripemd160() etc.
+HMAC does not support variable output length digests such as EVP_shake128() and
EVP_shake256().
+HMAC() uses the default B<OSSL_LIB_CTX>.
+Use L<EVP_Q_mac(3)> instead if a library context is required.
+
+All of the functions described below are deprecated.
+Applications should instead use L<EVP_MAC_CTX_new(3)>, L<EVP_MAC_CTX_free(3)>,
+L<EVP_MAC_init(3)>, L<EVP_MAC_update(3)> and L<EVP_MAC_final(3)>
+or the 'quick' single-shot MAC function L<EVP_Q_mac(3)>.
+
HMAC_CTX_new() creates a new HMAC_CTX in heap memory.
-HMAC_CTX_reset() zeros an existing B<HMAC_CTX> and associated
+HMAC_CTX_reset() clears an existing B<HMAC_CTX> and associated
resources, making it suitable for new computations as if it was newly
created with HMAC_CTX_new().
@@ -81,27 +93,27 @@ The following functions may be used if the message is not completely
stored in memory:
HMAC_Init_ex() initializes or reuses a B<HMAC_CTX> structure to use the hash
-function B<evp_md> and key B<key>. If both are NULL, or if B<key> is NULL
-and B<evp_md> is the same as the previous call, then the
+function I<evp_md> and key I<key>. If both are NULL, or if I<key> is NULL
+and I<evp_md> is the same as the previous call, then the
existing key is
-reused. B<ctx> must have been created with HMAC_CTX_new() before the first use
+reused. I<ctx> must have been created with HMAC_CTX_new() before the first use
of an B<HMAC_CTX> in this function.
-If HMAC_Init_ex() is called with B<key> NULL and B<evp_md> is not the
-same as the previous digest used by B<ctx> then an error is returned
+If HMAC_Init_ex() is called with I<key> NULL and I<evp_md> is not the
+same as the previous digest used by I<ctx> then an error is returned
because reuse of an existing key with a different digest is not supported.
HMAC_Init() initializes a B<HMAC_CTX> structure to use the hash
-function B<evp_md> and the key B<key> which is B<key_len> bytes
+function I<evp_md> and the key I<key> which is I<key_len> bytes
long.
HMAC_Update() can be called repeatedly with chunks of the message to
-be authenticated (B<len> bytes at B<data>).
+be authenticated (I<len> bytes at I<data>).
-HMAC_Final() places the message authentication code in B<md>, which
+HMAC_Final() places the message authentication code in I<md>, which
must have space for the hash function output.
-HMAC_CTX_copy() copies all of the internal state from B<sctx> into B<dctx>.
+HMAC_CTX_copy() copies all of the internal state from I<sctx> into I<dctx>.
HMAC_CTX_set_flags() applies the specified flags to the internal EVP_MD_CTXs.
These flags have the same meaning as for L<EVP_MD_CTX_set_flags(3)>.
@@ -117,7 +129,7 @@ HMAC() returns a pointer to the message authentication code or NULL if
an error occurred.
HMAC_CTX_new() returns a pointer to a new B<HMAC_CTX> on success or
-B<NULL> if an error occurred.
+NULL if an error occurred.
HMAC_CTX_reset(), HMAC_Init_ex(), HMAC_Update(), HMAC_Final() and
HMAC_CTX_copy() return 1 for success or 0 if an error occurred.
@@ -134,10 +146,12 @@ RFC 2104
=head1 SEE ALSO
-L<SHA1(3)>, L<evp(7)>
+L<SHA1(3)>, EVP_Q_mac(3), L<evp(7)>
=head1 HISTORY
+All functions except for HMAC() were deprecated in OpenSSL 3.0.
+
HMAC_CTX_init() was replaced with HMAC_CTX_reset() in OpenSSL 1.1.0.
HMAC_CTX_cleanup() existed in OpenSSL before version 1.1.0.
@@ -149,9 +163,9 @@ OpenSSL before version 1.0.0.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/MD5.pod b/doc/man3/MD5.pod
index 83547f2ce50c..2e01fe8193dd 100644
--- a/doc/man3/MD5.pod
+++ b/doc/man3/MD5.pod
@@ -9,6 +9,10 @@ MD4_Final, MD5_Init, MD5_Update, MD5_Final - MD2, MD4, and MD5 hash functions
#include <openssl/md2.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
unsigned char *MD2(const unsigned char *d, unsigned long n, unsigned char *md);
int MD2_Init(MD2_CTX *c);
@@ -18,6 +22,10 @@ MD4_Final, MD5_Init, MD5_Update, MD5_Final - MD2, MD4, and MD5 hash functions
#include <openssl/md4.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
unsigned char *MD4(const unsigned char *d, unsigned long n, unsigned char *md);
int MD4_Init(MD4_CTX *c);
@@ -27,6 +35,10 @@ MD4_Final, MD5_Init, MD5_Update, MD5_Final - MD2, MD4, and MD5 hash functions
#include <openssl/md5.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
unsigned char *MD5(const unsigned char *d, unsigned long n, unsigned char *md);
int MD5_Init(MD5_CTX *c);
@@ -35,6 +47,10 @@ MD4_Final, MD5_Init, MD5_Update, MD5_Final - MD2, MD4, and MD5 hash functions
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_DigestInit_ex(3)>, L<EVP_DigestUpdate(3)>
+and L<EVP_DigestFinal_ex(3)>.
+
MD2, MD4, and MD5 are cryptographic hash functions with a 128 bit output.
MD2(), MD4(), and MD5() compute the MD2, MD4, and MD5 message digest
@@ -64,8 +80,8 @@ etc. instead of calling the hash functions directly.
=head1 NOTE
MD2, MD4, and MD5 are recommended only for compatibility with existing
-applications. In new applications, SHA-1 or RIPEMD-160 should be
-preferred.
+applications. In new applications, hashes from the SHA-2 or SHA-3 family
+should be preferred.
=head1 RETURN VALUES
@@ -81,13 +97,17 @@ RFC 1319, RFC 1320, RFC 1321
=head1 SEE ALSO
-L<EVP_DigestInit(3)>
+L<EVP_DigestInit(3)>, L<EVP_MD-SHA2(7)>, L<EVP_MD-SHA3(7)>
+
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/MDC2_Init.pod b/doc/man3/MDC2_Init.pod
index b384b8c8aea7..f29c9b78dc25 100644
--- a/doc/man3/MDC2_Init.pod
+++ b/doc/man3/MDC2_Init.pod
@@ -8,6 +8,10 @@ MDC2, MDC2_Init, MDC2_Update, MDC2_Final - MDC2 hash function
#include <openssl/mdc2.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
unsigned char *MDC2(const unsigned char *d, unsigned long n,
unsigned char *md);
@@ -18,6 +22,10 @@ MDC2, MDC2_Init, MDC2_Update, MDC2_Final - MDC2 hash function
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_DigestInit_ex(3)>, L<EVP_DigestUpdate(3)>
+and L<EVP_DigestFinal_ex(3)>.
+
MDC2 is a method to construct hash functions with 128 bit output from
block ciphers. These functions are an implementation of MDC2 with
DES.
@@ -56,11 +64,15 @@ ISO/IEC 10118-2:2000 Hash-Function 2, with DES as the underlying block cipher.
L<EVP_DigestInit(3)>
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/NCONF_new_ex.pod b/doc/man3/NCONF_new_ex.pod
new file mode 100644
index 000000000000..6861fb198c10
--- /dev/null
+++ b/doc/man3/NCONF_new_ex.pod
@@ -0,0 +1,84 @@
+=pod
+
+=head1 NAME
+
+NCONF_new_ex, NCONF_new, NCONF_free, NCONF_default, NCONF_load,
+NCONF_get0_libctx, NCONF_get_section, NCONF_get_section_names
+- functionality to Load and parse configuration files manually
+
+=head1 SYNOPSIS
+
+ #include <openssl/conf.h>
+
+ typedef struct {
+ char *section;
+ char *name;
+ char *value;
+ } CONF_VALUE;
+
+ CONF *NCONF_new_ex(OSSL_LIB_CTX *libctx, CONF_METHOD *meth);
+ CONF *NCONF_new(CONF_METHOD *meth);
+ void NCONF_free(CONF *conf);
+ CONF_METHOD *NCONF_default(void);
+ int NCONF_load(CONF *conf, const char *file, long *eline);
+ OSSL_LIB_CTX *NCONF_get0_libctx(const CONF *conf);
+
+ STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf, const char *name);
+ STACK_OF(OPENSSL_CSTRING) *NCONF_get_section_names(const CONF *conf);
+
+=head1 DESCRIPTION
+
+NCONF_new_ex() creates a new CONF object in heap memory and assigns to
+it a context I<libctx> that can be used during loading. If the method table
+I<meth> is set to NULL then the default value of NCONF_default() is used.
+
+NCONF_new() is similar to NCONF_new_ex() but sets the I<libctx> to NULL.
+
+NCONF_free() frees the data associated with I<conf> and then frees the I<conf>
+object.
+
+NCONF_load() parses the file named I<filename> and adds the values found to
+I<conf>. If an error occurs I<file> and I<eline> list the file and line that
+the load failed on if they are not NULL.
+
+NCONF_default() gets the default method table for processing a configuration file.
+
+NCONF_get0_libctx() gets the library context associated with the I<conf>
+parameter.
+
+NCONF_get_section_names() gets the names of the sections associated with
+the I<conf> as B<STACK_OF(OPENSSL_CSTRING)> strings. The individual strings
+are associated with the I<conf> and will be invalid after I<conf> is
+freed. The returned stack must be freed with sk_OPENSSL_CSTRING_free().
+
+NCONF_get_section() gets the config values associated with the I<conf> from
+the config section I<name> as B<STACK_OF(CONF_VALUE)> structures. The returned
+stack is associated with the I<conf> and will be invalid after I<conf>
+is freed. It must not be freed by the caller.
+
+=head1 RETURN VALUES
+
+NCONF_load() returns 1 on success or 0 on error.
+
+NCONF_new_ex() and NCONF_new() return a newly created I<CONF> object
+or NULL if an error occurs.
+
+=head1 SEE ALSO
+
+L<CONF_modules_load_file(3)>,
+
+=head1 HISTORY
+
+NCONF_new_ex(), NCONF_get0_libctx(), and NCONF_get_section_names() were added
+in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OBJ_nid2obj.pod b/doc/man3/OBJ_nid2obj.pod
index b37d992307c2..94eb6cc5899f 100644
--- a/doc/man3/OBJ_nid2obj.pod
+++ b/doc/man3/OBJ_nid2obj.pod
@@ -5,7 +5,7 @@
i2t_ASN1_OBJECT,
OBJ_length, OBJ_get0_data, OBJ_nid2obj, OBJ_nid2ln,
OBJ_nid2sn, OBJ_obj2nid, OBJ_txt2nid, OBJ_ln2nid, OBJ_sn2nid, OBJ_cmp,
-OBJ_dup, OBJ_txt2obj, OBJ_obj2txt, OBJ_create, OBJ_cleanup
+OBJ_dup, OBJ_txt2obj, OBJ_obj2txt, OBJ_create, OBJ_cleanup, OBJ_add_sigid
- ASN1 object utility functions
=head1 SYNOPSIS
@@ -35,18 +35,20 @@ OBJ_dup, OBJ_txt2obj, OBJ_obj2txt, OBJ_create, OBJ_cleanup
size_t OBJ_length(const ASN1_OBJECT *obj);
const unsigned char *OBJ_get0_data(const ASN1_OBJECT *obj);
-Deprecated:
+ int OBJ_add_sigid(int signid, int dig_id, int pkey_id);
- #if OPENSSL_API_COMPAT < 0x10100000L
- void OBJ_cleanup(void)
- #endif
+The following function has been deprecated since OpenSSL 1.1.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ void OBJ_cleanup(void);
=head1 DESCRIPTION
The ASN1 object utility functions process ASN1_OBJECT structures which are
a representation of the ASN1 OBJECT IDENTIFIER (OID) type.
For convenience, OIDs are usually represented in source code as numeric
-identifiers, or I<NID>s. OpenSSL has an internal table of OIDs that
+identifiers, or B<NID>s. OpenSSL has an internal table of OIDs that
are generated when the library is built, and their corresponding NIDs
are available as defined constants. For the functions below, application
code should treat all returned values -- OIDs, NIDs, or names -- as
@@ -57,7 +59,7 @@ an ASN1_OBJECT structure, its long name and its short name respectively,
or B<NULL> if an error occurred.
OBJ_obj2nid(), OBJ_ln2nid(), OBJ_sn2nid() return the corresponding NID
-for the object I<o>, the long name <ln> or the short name <sn> respectively
+for the object I<o>, the long name I<ln> or the short name I<sn> respectively
or NID_undef if an error occurred.
OBJ_txt2nid() returns NID corresponding to text string I<s>. I<s> can be
@@ -94,6 +96,14 @@ OBJ_length() returns the size of the content octets of I<obj>.
OBJ_get0_data() returns a pointer to the content octets of I<obj>.
The returned pointer is an internal pointer which B<must not> be freed.
+OBJ_add_sigid() creates a new composite "Signature Algorithm" that associates a
+given NID with two other NIDs - one representing the underlying signature
+algorithm and the other representing a digest algorithm to be used in
+conjunction with it. I<signid> represents the NID for the composite "Signature
+Algorithm", I<dig_id> is the NID for the digest algorithm and I<pkey_id> is the
+NID for the underlying signature algorithm. As there are signature algorithms
+that do not require a digest, NID_undef is a valid I<dig_id>.
+
OBJ_cleanup() releases any resources allocated by creating new objects.
=head1 NOTES
@@ -170,6 +180,12 @@ Create a new object directly:
obj = OBJ_txt2obj("1.2.3.4", 1);
+=head1 BUGS
+
+Neither OBJ_create() nor OBJ_add_sigid() do any locking and are thus not
+thread safe. Moreover, none of the other functions should be called while
+concurrent calls to these two functions are possible.
+
=head1 SEE ALSO
L<ERR_get_error(3)>
@@ -181,9 +197,9 @@ and should not be used.
=head1 COPYRIGHT
-Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OCSP_REQUEST_new.pod b/doc/man3/OCSP_REQUEST_new.pod
index 283c226bc408..e34e591fe01b 100644
--- a/doc/man3/OCSP_REQUEST_new.pod
+++ b/doc/man3/OCSP_REQUEST_new.pod
@@ -62,7 +62,7 @@ OCSP_request_sign() and OCSP_request_add1_cert() return 1 for success and 0
for failure.
OCSP_request_onereq_count() returns the total number of B<OCSP_ONEREQ>
-structures in B<req>.
+structures in B<req> and -1 on error.
OCSP_request_onereq_get0() returns a pointer to an B<OCSP_ONEREQ> structure
or B<NULL> if the index value is out or range.
@@ -108,9 +108,9 @@ L<OCSP_sendreq_new(3)>
=head1 COPYRIGHT
-Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OCSP_cert_to_id.pod b/doc/man3/OCSP_cert_to_id.pod
index 49393f7329a0..298527f6bb25 100644
--- a/doc/man3/OCSP_cert_to_id.pod
+++ b/doc/man3/OCSP_cert_to_id.pod
@@ -79,9 +79,9 @@ L<OCSP_sendreq_new(3)>
=head1 COPYRIGHT
-Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OCSP_request_add1_nonce.pod b/doc/man3/OCSP_request_add1_nonce.pod
index 777d876d04af..ae25c45c0720 100644
--- a/doc/man3/OCSP_request_add1_nonce.pod
+++ b/doc/man3/OCSP_request_add1_nonce.pod
@@ -76,7 +76,7 @@ L<OCSP_sendreq_new(3)>
Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OCSP_resp_find_status.pod b/doc/man3/OCSP_resp_find_status.pod
index 72dcc426c649..f4afddcdefe9 100644
--- a/doc/man3/OCSP_resp_find_status.pod
+++ b/doc/man3/OCSP_resp_find_status.pod
@@ -2,17 +2,13 @@
=head1 NAME
-OCSP_resp_get0_certs,
-OCSP_resp_get0_signer,
-OCSP_resp_get0_id,
-OCSP_resp_get1_id,
-OCSP_resp_get0_produced_at,
-OCSP_resp_get0_signature,
-OCSP_resp_get0_tbs_sigalg,
-OCSP_resp_get0_respdata,
-OCSP_resp_find_status, OCSP_resp_count, OCSP_resp_get0, OCSP_resp_find,
-OCSP_single_get0_status, OCSP_check_validity,
-OCSP_basic_verify
+OCSP_resp_find_status, OCSP_resp_count,
+OCSP_resp_get0, OCSP_resp_find, OCSP_single_get0_status,
+OCSP_resp_get0_produced_at, OCSP_resp_get0_signature,
+OCSP_resp_get0_tbs_sigalg, OCSP_resp_get0_respdata,
+OCSP_resp_get0_certs, OCSP_resp_get0_signer,
+OCSP_resp_get0_id, OCSP_resp_get1_id,
+OCSP_check_validity, OCSP_basic_verify
- OCSP response utility functions
=head1 SYNOPSIS
@@ -60,12 +56,12 @@ OCSP_basic_verify
=head1 DESCRIPTION
-OCSP_resp_find_status() searches B<bs> for an OCSP response for B<id>. If it is
-successful the fields of the response are returned in B<*status>, B<*reason>,
-B<*revtime>, B<*thisupd> and B<*nextupd>. The B<*status> value will be one of
+OCSP_resp_find_status() searches I<bs> for an OCSP response for I<id>. If it is
+successful the fields of the response are returned in I<*status>, I<*reason>,
+I<*revtime>, I<*thisupd> and I<*nextupd>. The I<*status> value will be one of
B<V_OCSP_CERTSTATUS_GOOD>, B<V_OCSP_CERTSTATUS_REVOKED> or
-B<V_OCSP_CERTSTATUS_UNKNOWN>. The B<*reason> and B<*revtime> fields are only
-set if the status is B<V_OCSP_CERTSTATUS_REVOKED>. If set the B<*reason> field
+B<V_OCSP_CERTSTATUS_UNKNOWN>. The I<*reason> and I<*revtime> fields are only
+set if the status is B<V_OCSP_CERTSTATUS_REVOKED>. If set the I<*reason> field
will be set to the revocation reason which will be one of
B<OCSP_REVOKED_STATUS_NOSTATUS>, B<OCSP_REVOKED_STATUS_UNSPECIFIED>,
B<OCSP_REVOKED_STATUS_KEYCOMPROMISE>, B<OCSP_REVOKED_STATUS_CACOMPROMISE>,
@@ -73,91 +69,115 @@ B<OCSP_REVOKED_STATUS_AFFILIATIONCHANGED>, B<OCSP_REVOKED_STATUS_SUPERSEDED>,
B<OCSP_REVOKED_STATUS_CESSATIONOFOPERATION>,
B<OCSP_REVOKED_STATUS_CERTIFICATEHOLD> or B<OCSP_REVOKED_STATUS_REMOVEFROMCRL>.
-OCSP_resp_count() returns the number of B<OCSP_SINGLERESP> structures in B<bs>.
+OCSP_resp_count() returns the number of B<OCSP_SINGLERESP> structures in I<bs>.
-OCSP_resp_get0() returns the B<OCSP_SINGLERESP> structure in B<bs>
-corresponding to index B<idx>. Where B<idx> runs from 0 to
-OCSP_resp_count(bs) - 1.
+OCSP_resp_get0() returns the B<OCSP_SINGLERESP> structure in I<bs> corresponding
+to index I<idx>, where I<idx> runs from 0 to OCSP_resp_count(bs) - 1.
-OCSP_resp_find() searches B<bs> for B<id> and returns the index of the first
-matching entry after B<last> or starting from the beginning if B<last> is -1.
+OCSP_resp_find() searches I<bs> for I<id> and returns the index of the first
+matching entry after I<last> or starting from the beginning if I<last> is -1.
-OCSP_single_get0_status() extracts the fields of B<single> in B<*reason>,
-B<*revtime>, B<*thisupd> and B<*nextupd>.
+OCSP_single_get0_status() extracts the fields of I<single> in I<*reason>,
+I<*revtime>, I<*thisupd> and I<*nextupd>.
OCSP_resp_get0_produced_at() extracts the B<producedAt> field from the
-single response B<bs>.
+single response I<bs>.
-OCSP_resp_get0_signature() returns the signature from B<bs>.
+OCSP_resp_get0_signature() returns the signature from I<bs>.
-OCSP_resp_get0_tbs_sigalg() returns the B<signatureAlgorithm> from B<bs>.
+OCSP_resp_get0_tbs_sigalg() returns the B<signatureAlgorithm> from I<bs>.
-OCSP_resp_get0_respdata() returns the B<tbsResponseData> from B<bs>.
+OCSP_resp_get0_respdata() returns the B<tbsResponseData> from I<bs>.
-OCSP_resp_get0_certs() returns any certificates included in B<bs>.
+OCSP_resp_get0_certs() returns any certificates included in I<bs>.
OCSP_resp_get0_signer() attempts to retrieve the certificate that directly
-signed B<bs>. The OCSP protocol does not require that this certificate
+signed I<bs>. The OCSP protocol does not require that this certificate
is included in the B<certs> field of the response, so additional certificates
-can be supplied in B<extra_certs> if the certificates that may have
+can be supplied via the I<extra_certs> if the certificates that may have
signed the response are known via some out-of-band mechanism.
-OCSP_resp_get0_id() gets the responder id of B<bs>. If the responder ID is
-a name then <*pname> is set to the name and B<*pid> is set to NULL. If the
-responder ID is by key ID then B<*pid> is set to the key ID and B<*pname>
-is set to NULL. OCSP_resp_get1_id() leaves ownership of B<*pid> and B<*pname>
-with the caller, who is responsible for freeing them. Both functions return 1
-in case of success and 0 in case of failure. If OCSP_resp_get1_id() returns 0,
-no freeing of the results is necessary.
-
-OCSP_check_validity() checks the validity of B<thisupd> and B<nextupd> values
-which will be typically obtained from OCSP_resp_find_status() or
-OCSP_single_get0_status(). If B<sec> is nonzero it indicates how many seconds
-leeway should be allowed in the check. If B<maxsec> is positive it indicates
-the maximum age of B<thisupd> in seconds.
-
-OCSP_basic_verify() checks that the basic response message B<bs> is correctly
-signed and that the signer certificate can be validated. It takes B<st> as
-the trusted store and B<certs> as a set of untrusted intermediate certificates.
+OCSP_resp_get0_id() gets the responder id of I<bs>. If the responder ID is
+a name then <*pname> is set to the name and I<*pid> is set to NULL. If the
+responder ID is by key ID then I<*pid> is set to the key ID and I<*pname>
+is set to NULL.
+
+OCSP_resp_get1_id() is the same as OCSP_resp_get0_id()
+but leaves ownership of I<*pid> and I<*pname> with the caller,
+who is responsible for freeing them unless the function returns 0.
+
+OCSP_check_validity() checks the validity of its I<thisupd> and I<nextupd>
+arguments, which will be typically obtained from OCSP_resp_find_status() or
+OCSP_single_get0_status(). If I<sec> is nonzero it indicates how many seconds
+leeway should be allowed in the check. If I<maxsec> is positive it indicates
+the maximum age of I<thisupd> in seconds.
+
+OCSP_basic_verify() checks that the basic response message I<bs> is correctly
+signed and that the signer certificate can be validated. It takes I<st> as
+the trusted store and I<certs> as a set of untrusted intermediate certificates.
The function first tries to find the signer certificate of the response
-in <certs>. It also searches the certificates the responder may have included
-in B<bs> unless the B<flags> contain B<OCSP_NOINTERN>.
+in I<certs>. It then searches the certificates the responder may have included
+in I<bs> unless I<flags> contains B<OCSP_NOINTERN>.
It fails if the signer certificate cannot be found.
-Next, the function checks the signature of B<bs> and fails on error
-unless the B<flags> contain B<OCSP_NOSIGS>. Then the function already returns
-success if the B<flags> contain B<OCSP_NOVERIFY> or if the signer certificate
-was found in B<certs> and the B<flags> contain B<OCSP_TRUSTOTHER>.
+Next, unless I<flags> contains B<OCSP_NOSIGS>, the function checks
+the signature of I<bs> and fails on error. Then the function already returns
+success if I<flags> contains B<OCSP_NOVERIFY> or if the signer certificate
+was found in I<certs> and I<flags> contains B<OCSP_TRUSTOTHER>.
Otherwise the function continues by validating the signer certificate.
-To this end, all certificates in B<cert> and in B<bs> are considered as
-untrusted certificates for the construction of the validation path for the
-signer certificate unless the B<OCSP_NOCHAIN> flag is set. After successful path
+If I<flags> contains B<OCSP_PARTIAL_CHAIN> it takes intermediate CA
+certificates in I<st> as trust anchors.
+For more details, see the description of B<X509_V_FLAG_PARTIAL_CHAIN>
+in L<X509_VERIFY_PARAM_set_flags(3)/VERIFICATION FLAGS>.
+If I<flags> contains B<OCSP_NOCHAIN> it ignores all certificates in I<certs>
+and in I<bs>, else it takes them as untrusted intermediate CA certificates
+and uses them for constructing the validation path for the signer certificate.
+Certicate revocation status checks using CRLs is disabled during path validation
+if the signer certificate contains the B<id-pkix-ocsp-no-check> extension.
+After successful path
validation the function returns success if the B<OCSP_NOCHECKS> flag is set.
Otherwise it verifies that the signer certificate meets the OCSP issuer
criteria including potential delegation. If this does not succeed and the
-B<flags> do not contain B<OCSP_NOEXPLICIT> the function checks for explicit
+B<OCSP_NOEXPLICIT> flag is not set the function checks for explicit
trust for OCSP signing in the root CA certificate.
=head1 RETURN VALUES
-OCSP_resp_find_status() returns 1 if B<id> is found in B<bs> and 0 otherwise.
+OCSP_resp_find_status() returns 1 if I<id> is found in I<bs> and 0 otherwise.
-OCSP_resp_count() returns the total number of B<OCSP_SINGLERESP> fields in
-B<bs>.
+OCSP_resp_count() returns the total number of B<OCSP_SINGLERESP> fields in I<bs>
+or -1 on error.
OCSP_resp_get0() returns a pointer to an B<OCSP_SINGLERESP> structure or
-B<NULL> if B<idx> is out of range.
+NULL on error, such as I<idx> being out of range.
-OCSP_resp_find() returns the index of B<id> in B<bs> (which may be 0) or -1 if
-B<id> was not found.
+OCSP_resp_find() returns the index of I<id> in I<bs> (which may be 0)
+or -1 on error, such as when I<id> was not found.
-OCSP_single_get0_status() returns the status of B<single> or -1 if an error
+OCSP_single_get0_status() returns the status of I<single> or -1 if an error
occurred.
+OCSP_resp_get0_produced_at() returns the B<producedAt> field from I<bs>.
+
+OCSP_resp_get0_signature() returns the signature from I<bs>.
+
+OCSP_resp_get0_tbs_sigalg() returns the B<signatureAlgorithm> field from I<bs>.
+
+OCSP_resp_get0_respdata() returns the B<tbsResponseData> field from I<bs>.
+
+OCSP_resp_get0_certs() returns any certificates included in I<bs>.
+
OCSP_resp_get0_signer() returns 1 if the signing certificate was located,
-or 0 on error.
+or 0 if not found or on error.
+
+OCSP_resp_get0_id() and OCSP_resp_get1_id() return 1 on success, 0 on failure.
+
+OCSP_check_validity() returns 1 if I<thisupd> and I<nextupd> are valid time
+values and the current time + I<sec> is not before I<thisupd> and,
+if I<maxsec> >= 0, the current time - I<maxsec> is not past I<nextupd>.
+Otherwise it returns 0 to indicate an error.
-OCSP_basic_verify() returns 1 on success, 0 on error, or -1 on fatal error such
-as malloc failure.
+OCSP_basic_verify() returns 1 on success, 0 on verification not successful,
+or -1 on a fatal error such as malloc failure.
=head1 NOTES
@@ -167,15 +187,15 @@ can then take appropriate action based on the status of the certificate.
An OCSP response for a certificate contains B<thisUpdate> and B<nextUpdate>
fields. Normally the current time should be between these two values. To
-account for clock skew the B<maxsec> field can be set to nonzero in
+account for clock skew the I<maxsec> field can be set to nonzero in
OCSP_check_validity(). Some responders do not set the B<nextUpdate> field, this
would otherwise mean an ancient response would be considered valid: the
-B<maxsec> parameter to OCSP_check_validity() can be used to limit the permitted
+I<maxsec> parameter to OCSP_check_validity() can be used to limit the permitted
age of responses.
-The values written to B<*revtime>, B<*thisupd> and B<*nextupd> by
+The values written to I<*revtime>, I<*thisupd> and I<*nextupd> by
OCSP_resp_find_status() and OCSP_single_get0_status() are internal pointers
-which B<MUST NOT> be freed up by the calling application. Any or all of these
+which MUST NOT be freed up by the calling application. Any or all of these
parameters can be set to NULL if their value is not required.
=head1 SEE ALSO
@@ -185,13 +205,14 @@ L<OCSP_cert_to_id(3)>,
L<OCSP_request_add1_nonce(3)>,
L<OCSP_REQUEST_new(3)>,
L<OCSP_response_status(3)>,
-L<OCSP_sendreq_new(3)>
+L<OCSP_sendreq_new(3)>,
+L<X509_VERIFY_PARAM_set_flags(3)>
=head1 COPYRIGHT
-Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OCSP_response_status.pod b/doc/man3/OCSP_response_status.pod
index e7e22e4cb549..7ff74923a53f 100644
--- a/doc/man3/OCSP_response_status.pod
+++ b/doc/man3/OCSP_response_status.pod
@@ -4,8 +4,9 @@
OCSP_response_status, OCSP_response_get1_basic, OCSP_response_create,
OCSP_RESPONSE_free, OCSP_RESPID_set_by_name,
-OCSP_RESPID_set_by_key, OCSP_RESPID_match,
-OCSP_basic_sign, OCSP_basic_sign_ctx - OCSP response functions
+OCSP_RESPID_set_by_key_ex, OCSP_RESPID_set_by_key, OCSP_RESPID_match_ex,
+OCSP_RESPID_match, OCSP_basic_sign, OCSP_basic_sign_ctx
+- OCSP response functions
=head1 SYNOPSIS
@@ -17,7 +18,11 @@ OCSP_basic_sign, OCSP_basic_sign_ctx - OCSP response functions
void OCSP_RESPONSE_free(OCSP_RESPONSE *resp);
int OCSP_RESPID_set_by_name(OCSP_RESPID *respid, X509 *cert);
+ int OCSP_RESPID_set_by_key_ex(OCSP_RESPID *respid, X509 *cert,
+ OSSL_LIB_CTX *libctx, const char *propq);
int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert);
+ int OCSP_RESPID_match_ex(OCSP_RESPID *respid, X509 *cert, OSSL_LIB_CTX *libctx,
+ const char *propq);
int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert);
int OCSP_basic_sign(OCSP_BASICRESP *brsp, X509 *signer, EVP_PKEY *key,
@@ -28,49 +33,60 @@ OCSP_basic_sign, OCSP_basic_sign_ctx - OCSP response functions
=head1 DESCRIPTION
-OCSP_response_status() returns the OCSP response status of B<resp>. It returns
-one of the values: B<OCSP_RESPONSE_STATUS_SUCCESSFUL>,
-B<OCSP_RESPONSE_STATUS_MALFORMEDREQUEST>,
-B<OCSP_RESPONSE_STATUS_INTERNALERROR>, B<OCSP_RESPONSE_STATUS_TRYLATER>
-B<OCSP_RESPONSE_STATUS_SIGREQUIRED>, or B<OCSP_RESPONSE_STATUS_UNAUTHORIZED>.
+OCSP_response_status() returns the OCSP response status of I<resp>. It returns
+one of the values: I<OCSP_RESPONSE_STATUS_SUCCESSFUL>,
+I<OCSP_RESPONSE_STATUS_MALFORMEDREQUEST>,
+I<OCSP_RESPONSE_STATUS_INTERNALERROR>, I<OCSP_RESPONSE_STATUS_TRYLATER>
+I<OCSP_RESPONSE_STATUS_SIGREQUIRED>, or I<OCSP_RESPONSE_STATUS_UNAUTHORIZED>.
-OCSP_response_get1_basic() decodes and returns the B<OCSP_BASICRESP> structure
-contained in B<resp>.
+OCSP_response_get1_basic() decodes and returns the I<OCSP_BASICRESP> structure
+contained in I<resp>.
-OCSP_response_create() creates and returns an B<OCSP_RESPONSE> structure for
-B<status> and optionally including basic response B<bs>.
+OCSP_response_create() creates and returns an I<OCSP_RESPONSE> structure for
+I<status> and optionally including basic response I<bs>.
-OCSP_RESPONSE_free() frees up OCSP response B<resp>.
+OCSP_RESPONSE_free() frees up OCSP response I<resp>.
OCSP_RESPID_set_by_name() sets the name of the OCSP_RESPID to be the same as the
-subject name in the supplied X509 certificate B<cert> for the OCSP responder.
+subject name in the supplied X509 certificate I<cert> for the OCSP responder.
-OCSP_RESPID_set_by_key() sets the key of the OCSP_RESPID to be the same as the
-key in the supplied X509 certificate B<cert> for the OCSP responder. The key is
-stored as a SHA1 hash.
+OCSP_RESPID_set_by_key_ex() sets the key of the OCSP_RESPID to be the same as the
+key in the supplied X509 certificate I<cert> for the OCSP responder. The key is
+stored as a SHA1 hash. To calculate the hash the SHA1 algorithm is fetched using
+the library ctx I<libctx> and the property query string I<propq> (see
+L<crypto(7)/ALGORITHM FETCHING> for further information).
+
+OCSP_RESPID_set_by_key() does the same as OCSP_RESPID_set_by_key_ex() except
+that the default library context is used with an empty property query string.
Note that an OCSP_RESPID can only have one of the name, or the key set. Calling
OCSP_RESPID_set_by_name() or OCSP_RESPID_set_by_key() will clear any existing
setting.
-OCSP_RESPID_match() tests whether the OCSP_RESPID given in B<respid> matches
-with the X509 certificate B<cert>.
+OCSP_RESPID_match_ex() tests whether the OCSP_RESPID given in I<respid> matches
+with the X509 certificate I<cert> based on the SHA1 hash. To calculate the hash
+the SHA1 algorithm is fetched using the library ctx I<libctx> and the property
+query string I<propq> (see L<crypto(7)/ALGORITHM FETCHING> for further
+information).
+
+OCSP_RESPID_match() does the same as OCSP_RESPID_match_ex() except that the
+default library context is used with an empty property query string.
-OCSP_basic_sign() signs OCSP response B<brsp> using certificate B<signer>, private key
-B<key>, digest B<dgst> and additional certificates B<certs>. If the B<flags> option
-B<OCSP_NOCERTS> is set then no certificates will be included in the response. If the
-B<flags> option B<OCSP_RESPID_KEY> is set then the responder is identified by key ID
-rather than by name. OCSP_basic_sign_ctx() also signs OCSP response B<brsp> but
-uses the parameters contained in digest context B<ctx>.
+OCSP_basic_sign() signs OCSP response I<brsp> using certificate I<signer>, private key
+I<key>, digest I<dgst> and additional certificates I<certs>. If the I<flags> option
+I<OCSP_NOCERTS> is set then no certificates will be included in the response. If the
+I<flags> option I<OCSP_RESPID_KEY> is set then the responder is identified by key ID
+rather than by name. OCSP_basic_sign_ctx() also signs OCSP response I<brsp> but
+uses the parameters contained in digest context I<ctx>.
=head1 RETURN VALUES
OCSP_RESPONSE_status() returns a status value.
-OCSP_response_get1_basic() returns an B<OCSP_BASICRESP> structure pointer or
-B<NULL> if an error occurred.
+OCSP_response_get1_basic() returns an I<OCSP_BASICRESP> structure pointer or
+I<NULL> if an error occurred.
-OCSP_response_create() returns an B<OCSP_RESPONSE> structure pointer or B<NULL>
+OCSP_response_create() returns an I<OCSP_RESPONSE> structure pointer or I<NULL>
if an error occurred.
OCSP_RESPONSE_free() does not return a value.
@@ -85,7 +101,7 @@ or 0 otherwise.
=head1 NOTES
OCSP_response_get1_basic() is only called if the status of a response is
-B<OCSP_RESPONSE_STATUS_SUCCESSFUL>.
+I<OCSP_RESPONSE_STATUS_SUCCESSFUL>.
=head1 SEE ALSO
@@ -107,9 +123,9 @@ The OCSP_basic_sign_ctx() function was added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OCSP_sendreq_new.pod b/doc/man3/OCSP_sendreq_new.pod
index 65bdde88a2e1..6e4c8110f1f0 100644
--- a/doc/man3/OCSP_sendreq_new.pod
+++ b/doc/man3/OCSP_sendreq_new.pod
@@ -2,136 +2,122 @@
=head1 NAME
+OCSP_REQ_CTX,
OCSP_sendreq_new,
OCSP_sendreq_nbio,
+OCSP_sendreq_bio,
+OCSP_REQ_CTX_i2d,
+OCSP_REQ_CTX_add1_header,
OCSP_REQ_CTX_free,
OCSP_set_max_response_length,
-OCSP_REQ_CTX_add1_header,
-OCSP_REQ_CTX_set1_req,
-OCSP_sendreq_bio,
-OCSP_REQ_CTX_i2d
+OCSP_REQ_CTX_set1_req
- OCSP responder query functions
=head1 SYNOPSIS
#include <openssl/ocsp.h>
- OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req,
- int maxline);
-
- int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx);
-
- void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx);
+ OSSL_HTTP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path,
+ const OCSP_REQUEST *req, int buf_size);
+ OCSP_RESPONSE *OCSP_sendreq_bio(BIO *io, const char *path, OCSP_REQUEST *req);
- void OCSP_set_max_response_length(OCSP_REQ_CTX *rctx, unsigned long len);
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
- int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx,
+ typedef OSSL_HTTP_REQ_CTX OCSP_REQ_CTX;
+ int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OSSL_HTTP_REQ_CTX *rctx);
+ int OCSP_REQ_CTX_i2d(OCSP_REQ_CT *rctx, const ASN1_ITEM *it, ASN1_VALUE *req);
+ int OCSP_REQ_CTX_add1_header(OCSP_REQ_CT *rctx,
const char *name, const char *value);
-
- int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req);
-
- OCSP_RESPONSE *OCSP_sendreq_bio(BIO *io, const char *path, OCSP_REQUEST *req);
-
- int OCSP_REQ_CTX_i2d(OCSP_REQ_CTX *rctx, const char *content_type,
- const ASN1_ITEM *it, ASN1_VALUE *req);
+ void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx);
+ void OCSP_set_max_response_length(OCSP_REQ_CT *rctx, unsigned long len);
+ int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, const OCSP_REQUEST *req);
=head1 DESCRIPTION
-The function OCSP_sendreq_new() returns an B<OCSP_CTX> structure using the
-responder B<io>, the URL path B<path>, the OCSP request B<req> and with a
-response header maximum line length of B<maxline>. If B<maxline> is zero a
-default value of 4k is used. The OCSP request B<req> may be set to B<NULL>
-and provided later if required.
-
-OCSP_sendreq_nbio() performs nonblocking I/O on the OCSP request context
-B<rctx>. When the operation is complete it returns the response in B<*presp>.
-
-OCSP_REQ_CTX_free() frees up the OCSP context B<rctx>.
+These functions perform an OCSP POST request / response transfer over HTTP,
+using the HTTP request functions described in L<OSSL_HTTP_REQ_CTX(3)>.
+
+The function OCSP_sendreq_new() builds a complete B<OSSL_HTTP_REQ_CTX> structure
+with the B<BIO> I<io> to be used for requests and reponse, the URL path I<path>,
+optionally the OCSP request I<req>, and a response header maximum line length
+of I<buf_size>. If I<buf_size> is zero a default value of 4KiB is used.
+The I<req> may be set to NULL and provided later using OCSP_REQ_CTX_set1_req()
+or L<OSSL_HTTP_REQ_CTX_set1_req(3)>.
+The I<io> and I<path> arguments to OCSP_sendreq_new() correspond to the
+components of the URL.
+For example if the responder URL is C<http://example.com/ocspreq> the BIO
+I<io> should haven been connected to host C<example.com> on port 80 and I<path>
+should be set to C</ocspreq>.
+
+OCSP_sendreq_nbio() attempts to send the request prepared in I<rctx>
+and to gather the response via HTTP, using the BIO I<io> and I<path>
+that were given when calling OCSP_sendreq_new().
+If the operation gets completed it assigns the response,
+a pointer to a B<OCSP_RESPONSE> structure, in I<*presp>.
+The function may need to be called again if its result is -1, which indicates
+L<BIO_should_retry(3)>. In such a case it is advisable to sleep a little in
+between, using L<BIO_wait(3)> on the read BIO to prevent a busy loop.
+
+OCSP_sendreq_bio() combines OCSP_sendreq_new() with as many calls of
+OCSP_sendreq_nbio() as needed and then OCSP_REQ_CTX_free(), with a
+response header maximum line length 4k. It waits indefinitely on a response.
+It does not support setting a timeout or adding headers and is retained
+for compatibility; use L<OSSL_HTTP_transfer(3)> instead.
+
+OCSP_REQ_CTX_i2d(rctx, it, req) is equivalent to the following:
+
+ OSSL_HTTP_REQ_CTX_set1_req(rctx, "application/ocsp-request", it, req)
-OCSP_set_max_response_length() sets the maximum response length for B<rctx>
-to B<len>. If the response exceeds this length an error occurs. If not
-set a default value of 100k is used.
-
-OCSP_REQ_CTX_add1_header() adds header B<name> with value B<value> to the
-context B<rctx>. It can be called more than once to add multiple headers.
-It B<MUST> be called before any calls to OCSP_sendreq_nbio(). The B<req>
-parameter in the initial to OCSP_sendreq_new() call MUST be set to B<NULL> if
-additional headers are set.
-
-OCSP_REQ_CTX_set1_req() sets the OCSP request in B<rctx> to B<req>. This
-function should be called after any calls to OCSP_REQ_CTX_add1_header().
OCSP_REQ_CTX_set1_req(rctx, req) is equivalent to the following:
- OCSP_REQ_CTX_i2d(rctx, "application/ocsp-request",
- ASN1_ITEM_rptr(OCSP_REQUEST), (ASN1_VALUE *)req)
+ OSSL_HTTP_REQ_CTX_set1_req(rctx, "application/ocsp-request",
+ ASN1_ITEM_rptr(OCSP_REQUEST),
+ (const ASN1_VALUE *)req)
-OCSP_REQ_CTX_i2d() sets the request context B<rctx> to have the request
-B<req>, which has the ASN.1 type B<it>.
-The B<content_type>, if not NULL, will be included in the HTTP request.
-The function should be called after all other headers have already been added.
-
-OCSP_sendreq_bio() performs an OCSP request using the responder B<io>, the URL
-path B<path>, and the OCSP request B<req> with a response header maximum line
-length 4k. It waits indefinitely on a response.
+The deprecated type and the remaining deprecated functions
+have been superseded by the following equivalents:
+B<OCSP_REQ_CTX> by L<OSSL_HTTP_REQ_CTX(3)>,
+OCSP_REQ_CTX_add1_header() by L<OSSL_HTTP_REQ_CTX_add1_header(3)>,
+OCSP_REQ_CTX_free() by L<OSSL_HTTP_REQ_CTX_free(3)>, and
+OCSP_set_max_response_length() by
+L<OSSL_HTTP_REQ_CTX_set_max_response_length(3)>.
=head1 RETURN VALUES
-OCSP_sendreq_new() returns a valid B<OCSP_REQ_CTX> structure or B<NULL> if
-an error occurred.
-
-OCSP_sendreq_nbio() returns B<1> if the operation was completed successfully,
-B<-1> if the operation should be retried and B<0> if an error occurred.
+OCSP_sendreq_new() returns a valid B<OSSL_HTTP_REQ_CTX> structure or NULL
+if an error occurred.
-OCSP_REQ_CTX_add1_header(), OCSP_REQ_CTX_set1_req(), and OCSP_REQ_CTX_i2d()
-return B<1> for success and B<0> for failure.
+OCSP_sendreq_nbio() returns 1 for success, 0 on error, -1 if retry is needed.
OCSP_sendreq_bio() returns the B<OCSP_RESPONSE> structure sent by the
-responder or B<NULL> if an error occurred.
-
-OCSP_REQ_CTX_free() and OCSP_set_max_response_length() do not return values.
-
-=head1 NOTES
-
-These functions only perform a minimal HTTP query to a responder. If an
-application wishes to support more advanced features it should use an
-alternative more complete HTTP library.
-
-Currently only HTTP POST queries to responders are supported.
-
-The arguments to OCSP_sendreq_new() correspond to the components of the URL.
-For example if the responder URL is B<http://ocsp.com/ocspreq> the BIO
-B<io> should be connected to host B<ocsp.com> on port 80 and B<path>
-should be set to B<"/ocspreq">
-
-The headers added with OCSP_REQ_CTX_add1_header() are of the form
-"B<name>: B<value>" or just "B<name>" if B<value> is B<NULL>. So to add
-a Host header for B<ocsp.com> you would call:
-
- OCSP_REQ_CTX_add1_header(ctx, "Host", "ocsp.com");
-
-If OCSP_sendreq_nbio() indicates an operation should be retried the
-corresponding BIO can be examined to determine which operation (read or
-write) should be retried and appropriate action taken (for example a select()
-call on the underlying socket).
-
-OCSP_sendreq_bio() does not support retries and so cannot handle nonblocking
-I/O efficiently. It is retained for compatibility and its use in new
-applications is not recommended.
+responder or NULL if an error occurred.
=head1 SEE ALSO
-L<crypto(7)>,
+L<OSSL_HTTP_REQ_CTX(3)>, L<OSSL_HTTP_transfer(3)>,
L<OCSP_cert_to_id(3)>,
L<OCSP_request_add1_nonce(3)>,
L<OCSP_REQUEST_new(3)>,
L<OCSP_resp_find_status(3)>,
L<OCSP_response_status(3)>
+=head1 HISTORY
+
+B<OCSP_REQ_CTX>,
+OCSP_REQ_CTX_i2d(),
+OCSP_REQ_CTX_add1_header(),
+OCSP_REQ_CTX_free(),
+OCSP_set_max_response_length(),
+and OCSP_REQ_CTX_set1_req()
+were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OPENSSL_Applink.pod b/doc/man3/OPENSSL_Applink.pod
index 85930786c5f7..9991ea381b6f 100644
--- a/doc/man3/OPENSSL_Applink.pod
+++ b/doc/man3/OPENSSL_Applink.pod
@@ -27,7 +27,7 @@ Not available.
Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OPENSSL_FILE.pod b/doc/man3/OPENSSL_FILE.pod
new file mode 100644
index 000000000000..7d9dc2b3b86a
--- /dev/null
+++ b/doc/man3/OPENSSL_FILE.pod
@@ -0,0 +1,56 @@
+=pod
+
+=head1 NAME
+
+OPENSSL_FILE, OPENSSL_LINE, OPENSSL_FUNC,
+OPENSSL_MSTR, OPENSSL_MSTR_HELPER
+- generic C programming utility macros
+
+=head1 SYNOPSIS
+
+ #include <openssl/macros.h>
+
+ #define OPENSSL_FILE /* typically: __FILE__ */
+ #define OPENSSL_LINE /* typically: __LINE__ */
+ #define OPENSSL_FUNC /* typically: __func__ */
+
+ #define OPENSSL_MSTR_HELPER(x) #x
+ #define OPENSSL_MSTR(x) OPENSSL_MSTR_HELPER(x)
+
+=head1 DESCRIPTION
+
+The macros B<OPENSSL_FILE> and B<OPENSSL_LINE>
+typically yield the current filename and line number during C compilation.
+When B<OPENSSL_NO_FILENAMES> is defined they yield B<""> and B<0>, respectively.
+
+The macro B<OPENSSL_FUNC> attempts to yield the name of the C function
+currently being compiled, as far as language and compiler versions allow.
+Otherwise, it yields "(unknown function)".
+
+The macro B<OPENSSL_MSTR> yields the expansion of the macro given as argument,
+which is useful for concatenation with string constants.
+The macro B<OPENSSL_MSTR_HELPER> is an auxiliary macro for this purpose.
+
+=head1 RETURN VALUES
+
+see above
+
+=head1 SEE ALSO
+
+L<crypto(7)>
+
+=head1 HISTORY
+
+B<OPENSSL_FUNC>, B<OPENSSL_MSTR>, and B<OPENSSL_MSTR_HELPER>
+were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OPENSSL_LH_COMPFUNC.pod b/doc/man3/OPENSSL_LH_COMPFUNC.pod
index 29702aa0b586..d3bb272c4a94 100644
--- a/doc/man3/OPENSSL_LH_COMPFUNC.pod
+++ b/doc/man3/OPENSSL_LH_COMPFUNC.pod
@@ -6,20 +6,25 @@ LHASH, DECLARE_LHASH_OF,
OPENSSL_LH_COMPFUNC, OPENSSL_LH_HASHFUNC, OPENSSL_LH_DOALL_FUNC,
LHASH_DOALL_ARG_FN_TYPE,
IMPLEMENT_LHASH_HASH_FN, IMPLEMENT_LHASH_COMP_FN,
-lh_TYPE_new, lh_TYPE_free,
+lh_TYPE_new, lh_TYPE_free, lh_TYPE_flush,
lh_TYPE_insert, lh_TYPE_delete, lh_TYPE_retrieve,
-lh_TYPE_doall, lh_TYPE_doall_arg, lh_TYPE_error - dynamic hash table
+lh_TYPE_doall, lh_TYPE_doall_arg, lh_TYPE_error,
+OPENSSL_LH_new, OPENSSL_LH_free, OPENSSL_LH_flush,
+OPENSSL_LH_insert, OPENSSL_LH_delete, OPENSSL_LH_retrieve,
+OPENSSL_LH_doall, OPENSSL_LH_doall_arg, OPENSSL_LH_error
+- dynamic hash table
=head1 SYNOPSIS
-=for comment generic
+=for openssl generic
#include <openssl/lhash.h>
DECLARE_LHASH_OF(TYPE);
- LHASH *lh_TYPE_new(OPENSSL_LH_HASHFUNC hash, OPENSSL_LH_COMPFUNC compare);
+ LHASH_OF(TYPE) *lh_TYPE_new(OPENSSL_LH_HASHFUNC hash, OPENSSL_LH_COMPFUNC compare);
void lh_TYPE_free(LHASH_OF(TYPE) *table);
+ void lh_TYPE_flush(LHASH_OF(TYPE) *table);
TYPE *lh_TYPE_insert(LHASH_OF(TYPE) *table, TYPE *data);
TYPE *lh_TYPE_delete(LHASH_OF(TYPE) *table, TYPE *data);
@@ -36,29 +41,42 @@ lh_TYPE_doall, lh_TYPE_doall_arg, lh_TYPE_error - dynamic hash table
typedef void (*OPENSSL_LH_DOALL_FUNC)(const void *);
typedef void (*LHASH_DOALL_ARG_FN_TYPE)(const void *, const void *);
+ OPENSSL_LHASH *OPENSSL_LH_new(OPENSSL_LH_HASHFUNC h, OPENSSL_LH_COMPFUNC c);
+ void OPENSSL_LH_free(OPENSSL_LHASH *lh);
+ void OPENSSL_LH_flush(OPENSSL_LHASH *lh);
+
+ void *OPENSSL_LH_insert(OPENSSL_LHASH *lh, void *data);
+ void *OPENSSL_LH_delete(OPENSSL_LHASH *lh, const void *data);
+ void *OPENSSL_LH_retrieve(OPENSSL_LHASH *lh, const void *data);
+
+ void OPENSSL_LH_doall(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNC func);
+ void OPENSSL_LH_doall_arg(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNCARG func, void *arg);
+
+ int OPENSSL_LH_error(OPENSSL_LHASH *lh);
+
=head1 DESCRIPTION
This library implements type-checked dynamic hash tables. The hash
table entries can be arbitrary structures. Usually they consist of key
-and value fields. In the description here, I<TYPE> is used a placeholder
+and value fields. In the description here, B<I<TYPE>> is used a placeholder
for any of the OpenSSL datatypes, such as I<SSL_SESSION>.
-lh_TYPE_new() creates a new B<LHASH_OF(TYPE)> structure to store
+B<lh_I<TYPE>_new>() creates a new B<LHASH_OF>(B<I<TYPE>>) structure to store
arbitrary data entries, and specifies the 'hash' and 'compare'
-callbacks to be used in organising the table's entries. The B<hash>
+callbacks to be used in organising the table's entries. The I<hash>
callback takes a pointer to a table entry as its argument and returns
an unsigned long hash value for its key field. The hash value is
normally truncated to a power of 2, so make sure that your hash
-function returns well mixed low order bits. The B<compare> callback
+function returns well mixed low order bits. The I<compare> callback
takes two arguments (pointers to two hash table entries), and returns
0 if their keys are equal, nonzero otherwise.
If your hash table
-will contain items of some particular type and the B<hash> and
-B<compare> callbacks hash/compare these types, then the
+will contain items of some particular type and the I<hash> and
+I<compare> callbacks hash/compare these types, then the
B<IMPLEMENT_LHASH_HASH_FN> and B<IMPLEMENT_LHASH_COMP_FN> macros can be
used to create callback wrappers of the prototypes required by
-lh_TYPE_new() as shown in this example:
+B<lh_I<TYPE>_new>() as shown in this example:
/*
* Implement the hash and compare functions; "stuff" can be any word.
@@ -84,30 +102,35 @@ can be used in a common header file to declare the function wrappers:
DECLARE_LHASH_HASH_FN(stuff, TYPE)
DECLARE_LHASH_COMP_FN(stuff, TYPE)
-Then a hash table of TYPE objects can be created using this:
+Then a hash table of B<I<TYPE>> objects can be created using this:
LHASH_OF(TYPE) *htable;
- htable = lh_TYPE_new(LHASH_HASH_FN(stuff), LHASH_COMP_FN(stuff));
+ htable = B<lh_I<TYPE>_new>(LHASH_HASH_FN(stuff), LHASH_COMP_FN(stuff));
-lh_TYPE_free() frees the B<LHASH_OF(TYPE)> structure
-B<table>. Allocated hash table entries will not be freed; consider
-using lh_TYPE_doall() to deallocate any remaining entries in the
+B<lh_I<TYPE>_free>() frees the B<LHASH_OF>(B<I<TYPE>>) structure
+I<table>. Allocated hash table entries will not be freed; consider
+using B<lh_I<TYPE>_doall>() to deallocate any remaining entries in the
hash table (see below).
-lh_TYPE_insert() inserts the structure pointed to by B<data> into
-B<table>. If there already is an entry with the same key, the old
-value is replaced. Note that lh_TYPE_insert() stores pointers, the
+B<lh_I<TYPE>_flush>() empties the B<LHASH_OF>(B<I<TYPE>>) structure I<table>. New
+entries can be added to the flushed table. Allocated hash table entries
+will not be freed; consider using B<lh_I<TYPE>_doall>() to deallocate any
+remaining entries in the hash table (see below).
+
+B<lh_I<TYPE>_insert>() inserts the structure pointed to by I<data> into
+I<table>. If there already is an entry with the same key, the old
+value is replaced. Note that B<lh_I<TYPE>_insert>() stores pointers, the
data are not copied.
-lh_TYPE_delete() deletes an entry from B<table>.
+B<lh_I<TYPE>_delete>() deletes an entry from I<table>.
-lh_TYPE_retrieve() looks up an entry in B<table>. Normally, B<data>
+B<lh_I<TYPE>_retrieve>() looks up an entry in I<table>. Normally, I<data>
is a structure with the key field(s) set; the function will return a
pointer to a fully populated structure.
-lh_TYPE_doall() will, for every entry in the hash table, call
-B<func> with the data item as its parameter.
+B<lh_I<TYPE>_doall>() will, for every entry in the hash table, call
+I<func> with the data item as its parameter.
For example:
/* Cleans up resources belonging to 'a' (this is implemented elsewhere) */
@@ -131,9 +154,9 @@ you start (which will stop the hash table ever decreasing in size).
The best solution is probably to avoid deleting items from the hash
table inside a "doall" callback!
-lh_TYPE_doall_arg() is the same as lh_TYPE_doall() except that
-B<func> will be called with B<arg> as the second argument and B<func>
-should be of type B<LHASH_DOALL_ARG_FN_TYPE> (a callback prototype
+B<lh_I<TYPE>_doall_arg>() is the same as B<lh_I<TYPE>_doall>() except that
+I<func> will be called with I<arg> as the second argument and I<func>
+should be of type B<LHASH_DOALL_ARG_FN>(B<I<TYPE>>) (a callback prototype
that is passed both the table entry and an extra argument). As with
lh_doall(), you can instead choose to declare your callback with a
prototype matching the types you are dealing with and use the
@@ -153,36 +176,53 @@ that is provided by the caller):
logging_bio);
-lh_TYPE_error() can be used to determine if an error occurred in the last
+B<lh_I<TYPE>_error>() can be used to determine if an error occurred in the last
operation.
+OPENSSL_LH_new() is the same as the B<lh_I<TYPE>_new>() except that it is not
+type specific. So instead of returning an B<LHASH_OF(I<TYPE>)> value it returns
+a B<void *>. In the same way the functions OPENSSL_LH_free(),
+OPENSSL_LH_flush(), OPENSSL_LH_insert(), OPENSSL_LH_delete(),
+OPENSSL_LH_retrieve(), OPENSSL_LH_doall(), OPENSSL_LH_doall_arg(), and
+OPENSSL_LH_error() are equivalent to the similarly named B<lh_I<TYPE>> functions
+except that they return or use a B<void *> where the equivalent B<lh_I<TYPE>>
+function returns or uses a B<I<TYPE> *> or B<LHASH_OF(I<TYPE>) *>. B<lh_I<TYPE>>
+functions are implemented as type checked wrappers around the B<OPENSSL_LH>
+functions. Most applications should not call the B<OPENSSL_LH> functions
+directly.
+
=head1 RETURN VALUES
-lh_TYPE_new() returns B<NULL> on error, otherwise a pointer to the new
-B<LHASH> structure.
+B<lh_I<TYPE>_new>() and OPENSSL_LH_new() return NULL on error, otherwise a
+pointer to the new B<LHASH> structure.
-When a hash table entry is replaced, lh_TYPE_insert() returns the value
-being replaced. B<NULL> is returned on normal operation and on error.
+When a hash table entry is replaced, B<lh_I<TYPE>_insert>() or
+OPENSSL_LH_insert() return the value being replaced. NULL is returned on normal
+operation and on error.
-lh_TYPE_delete() returns the entry being deleted. B<NULL> is returned if
-there is no such value in the hash table.
+B<lh_I<TYPE>_delete>() and OPENSSL_LH_delete() return the entry being deleted.
+NULL is returned if there is no such value in the hash table.
-lh_TYPE_retrieve() returns the hash table entry if it has been found,
-B<NULL> otherwise.
+B<lh_I<TYPE>_retrieve>() and OPENSSL_LH_retrieve() return the hash table entry
+if it has been found, NULL otherwise.
-lh_TYPE_error() returns 1 if an error occurred in the last operation, 0
-otherwise. It's meaningful only after non-retrieve operations.
+B<lh_I<TYPE>_error>() and OPENSSL_LH_error() return 1 if an error occurred in
+the last operation, 0 otherwise. It's meaningful only after non-retrieve
+operations.
-lh_TYPE_free(), lh_TYPE_doall() and lh_TYPE_doall_arg() return no values.
+B<lh_I<TYPE>_free>(), OPENSSL_LH_free(), B<lh_I<TYPE>_flush>(),
+OPENSSL_LH_flush(), B<lh_I<TYPE>_doall>() OPENSSL_LH_doall(),
+B<lh_I<TYPE>_doall_arg>() and OPENSSL_LH_doall_arg() return no values.
=head1 NOTE
The LHASH code is not thread safe. All updating operations, as well as
-lh_TYPE_error call must be performed under a write lock. All retrieve
-operations should be performed under a read lock, I<unless> accurate
-usage statistics are desired. In which case, a write lock should be used
-for retrieve operations as well. For output of the usage statistics,
-using the functions from L<OPENSSL_LH_stats(3)>, a read lock suffices.
+B<lh_I<TYPE>_error>() or OPENSSL_LH_error() calls must be performed under
+a write lock. All retrieve operations should be performed under a read lock,
+I<unless> accurate usage statistics are desired. In which case, a write lock
+should be used for retrieve operations as well. For output of the usage
+statistics, using the functions from L<OPENSSL_LH_stats(3)>, a read lock
+suffices.
The LHASH code regards table entries as constant data. As such, it
internally represents lh_insert()'d items with a "const void *"
@@ -216,7 +256,8 @@ without any "const" qualifiers.
=head1 BUGS
-lh_TYPE_insert() returns B<NULL> both for success and error.
+B<lh_I<TYPE>_insert>() and OPENSSL_LH_insert() return NULL both for success
+and error.
=head1 SEE ALSO
@@ -231,7 +272,7 @@ type checking.
Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OPENSSL_LH_stats.pod b/doc/man3/OPENSSL_LH_stats.pod
index 231485ad363f..b86de52cb58b 100644
--- a/doc/man3/OPENSSL_LH_stats.pod
+++ b/doc/man3/OPENSSL_LH_stats.pod
@@ -23,9 +23,10 @@ OPENSSL_LH_node_stats_bio, OPENSSL_LH_node_usage_stats_bio - LHASH statistics
The B<LHASH> structure records statistics about most aspects of
accessing the hash table.
-OPENSSL_LH_stats() prints out statistics on the size of the hash table, how
-many entries are in it, and the number and result of calls to the
-routines in this library.
+OPENSSL_LH_stats() prints out statistics on the size of the hash table and how
+many entries are in it. For historical reasons, this function also outputs a
+number of additional statistics, but the tracking of these statistics is no
+longer supported and these statistics are always reported as zero.
OPENSSL_LH_node_stats() prints the number of entries for each 'bucket' in the
hash table.
@@ -58,9 +59,9 @@ L<bio(7)>, L<OPENSSL_LH_COMPFUNC(3)>
=head1 COPYRIGHT
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OPENSSL_VERSION_NUMBER.pod b/doc/man3/OPENSSL_VERSION_NUMBER.pod
deleted file mode 100644
index 55a55c706a51..000000000000
--- a/doc/man3/OPENSSL_VERSION_NUMBER.pod
+++ /dev/null
@@ -1,113 +0,0 @@
-=pod
-
-=head1 NAME
-
-OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT, OpenSSL_version,
-OpenSSL_version_num - get OpenSSL version number
-
-=head1 SYNOPSIS
-
- #include <openssl/opensslv.h>
- #define OPENSSL_VERSION_NUMBER 0xnnnnnnnnnL
- #define OPENSSL_VERSION_TEXT "OpenSSL x.y.z xx XXX xxxx"
-
- #include <openssl/crypto.h>
-
- unsigned long OpenSSL_version_num();
- const char *OpenSSL_version(int t);
-
-=head1 DESCRIPTION
-
-OPENSSL_VERSION_NUMBER is a numeric release version identifier:
-
- MNNFFPPS: major minor fix patch status
-
-The status nibble has one of the values 0 for development, 1 to e for betas
-1 to 14, and f for release.
-
-for example
-
- 0x000906000 == 0.9.6 dev
- 0x000906023 == 0.9.6b beta 3
- 0x00090605f == 0.9.6e release
-
-Versions prior to 0.9.3 have identifiers E<lt> 0x0930.
-Versions between 0.9.3 and 0.9.5 had a version identifier with this
-interpretation:
-
- MMNNFFRBB major minor fix final beta/patch
-
-for example
-
- 0x000904100 == 0.9.4 release
- 0x000905000 == 0.9.5 dev
-
-Version 0.9.5a had an interim interpretation that is like the current one,
-except the patch level got the highest bit set, to keep continuity. The
-number was therefore 0x0090581f.
-
-OPENSSL_VERSION_TEXT is the text variant of the version number and the
-release date. For example,
-"OpenSSL 1.0.1a 15 Oct 2015".
-
-OpenSSL_version_num() returns the version number.
-
-OpenSSL_version() returns different strings depending on B<t>:
-
-=over 4
-
-=item OPENSSL_VERSION
-
-The text variant of the version number and the release date. For example,
-"OpenSSL 1.0.1a 15 Oct 2015".
-
-=item OPENSSL_CFLAGS
-
-The compiler flags set for the compilation process in the form
-"compiler: ..." if available or "compiler: information not available"
-otherwise.
-
-=item OPENSSL_BUILT_ON
-
-The date of the build process in the form "built on: ..." if available
-or "built on: date not available" otherwise.
-
-=item OPENSSL_PLATFORM
-
-The "Configure" target of the library build in the form "platform: ..."
-if available or "platform: information not available" otherwise.
-
-=item OPENSSL_DIR
-
-The "OPENSSLDIR" setting of the library build in the form "OPENSSLDIR: "...""
-if available or "OPENSSLDIR: N/A" otherwise.
-
-=item OPENSSL_ENGINES_DIR
-
-The "ENGINESDIR" setting of the library build in the form "ENGINESDIR: "...""
-if available or "ENGINESDIR: N/A" otherwise.
-
-=back
-
-For an unknown B<t>, the text "not available" is returned.
-
-=head1 RETURN VALUES
-
-OpenSSL_version_num() returns the version number.
-
-OpenSSL_version() returns requested version strings.
-
-=head1 SEE ALSO
-
-L<crypto(7)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man3/OPENSSL_config.pod b/doc/man3/OPENSSL_config.pod
index 528eef0cf927..3fe6dd0e496b 100644
--- a/doc/man3/OPENSSL_config.pod
+++ b/doc/man3/OPENSSL_config.pod
@@ -8,10 +8,12 @@ OPENSSL_config, OPENSSL_no_config - simple OpenSSL configuration functions
#include <openssl/conf.h>
- #if OPENSSL_API_COMPAT < 0x10100000L
+The following functions have been deprecated since OpenSSL 1.1.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
void OPENSSL_config(const char *appname);
void OPENSSL_no_config(void);
- #endif
=head1 DESCRIPTION
@@ -75,9 +77,9 @@ deprecated in OpenSSL 1.1.0 by OPENSSL_init_crypto().
=head1 COPYRIGHT
-Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OPENSSL_fork_prepare.pod b/doc/man3/OPENSSL_fork_prepare.pod
index a47a07a390d8..6f8277c110da 100644
--- a/doc/man3/OPENSSL_fork_prepare.pod
+++ b/doc/man3/OPENSSL_fork_prepare.pod
@@ -11,12 +11,19 @@ OPENSSL_fork_child
#include <openssl/crypto.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
void OPENSSL_fork_prepare(void);
void OPENSSL_fork_parent(void);
void OPENSSL_fork_child(void);
=head1 DESCRIPTION
+These methods are currently unused, and as such, no replacement methods are
+required or planned.
+
OpenSSL has state that should be reset when a process forks. For example,
the entropy pool used to generate random numbers (and therefore encryption
keys) should not be shared across multiple programs.
@@ -53,9 +60,9 @@ These functions were added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OPENSSL_gmtime.pod b/doc/man3/OPENSSL_gmtime.pod
new file mode 100644
index 000000000000..b86557f3ca9e
--- /dev/null
+++ b/doc/man3/OPENSSL_gmtime.pod
@@ -0,0 +1,62 @@
+=pod
+
+=head1 NAME
+
+OPENSSL_gmtime,
+OPENSSL_gmtime_adj,
+OPENSSL_gmtime_diff - platform-agnostic OpenSSL time routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/crypto.h>
+
+ struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result);
+ int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec);
+ int OPENSSL_gmtime_diff(int *pday, int *psec,
+ const struct tm *from, const struct tm *to);
+
+=head1 DESCRIPTION
+
+OPENSSL_gmtime() returns the UTC time specified by I<timer> into the provided
+I<result> argument.
+
+OPENSSL_gmtime_adj() adds the offsets in I<offset_day> and I<offset_sec> to I<tm>.
+
+OPENSSL_gmtime_diff() calculates the difference between I<from> and I<to>.
+
+=head1 NOTES
+
+It is an error to call OPENSSL_gmtime() with I<result> equal to NULL. The
+contents of the time_t given by I<timer> are stored into the I<result>. Calling
+with I<timer> equal to NULL means use the current time.
+
+OPENSSL_gmtime_adj() converts I<tm> into a days and seconds value, adds the
+offsets, then converts back into a I<struct tm> specified by I<tm>. Leap seconds
+are not considered.
+
+OPENSSL_gmtime_diff() calculates the difference between the two I<struct tm>
+structures I<from> and I<to>. The difference in days is placed into I<*pday>,
+the remaining seconds are placed to I<*psec>. The value in I<*psec> will be less
+than the number of seconds per day (3600). Leap seconds are not considered.
+
+=head1 RETURN VALUES
+
+OPENSSL_gmtime() returns NULL on error, or I<result> on success.
+
+OPENSSL_gmtime_adj() and OPENSSL_gmtime_diff() return 0 on error, and 1 on success.
+
+=head1 HISTORY
+
+OPENSSL_gmtime(), OPENSSL_gmtime_adj() and OPENSSL_gmtime_diff() have been
+in OpenSSL since 1.0.0.
+
+=head1 COPYRIGHT
+
+Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OPENSSL_hexchar2int.pod b/doc/man3/OPENSSL_hexchar2int.pod
new file mode 100644
index 000000000000..9ca57063f879
--- /dev/null
+++ b/doc/man3/OPENSSL_hexchar2int.pod
@@ -0,0 +1,81 @@
+=pod
+
+=head1 NAME
+
+OPENSSL_hexchar2int,
+OPENSSL_hexstr2buf_ex, OPENSSL_hexstr2buf,
+OPENSSL_buf2hexstr_ex, OPENSSL_buf2hexstr
+- Hex encoding and decoding functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/crypto.h>
+
+ int OPENSSL_hexchar2int(unsigned char c);
+ int OPENSSL_hexstr2buf_ex(unsigned char *buf, size_t buf_n, long *buflen,
+ const char *str, const char sep);
+ unsigned char *OPENSSL_hexstr2buf(const char *str, long *len);
+ int OPENSSL_buf2hexstr_ex(char *str, size_t str_n, size_t *strlength,
+ const unsigned char *buf, long buflen,
+ const char sep);
+ char *OPENSSL_buf2hexstr(const unsigned char *buf, long buflen);
+
+=head1 DESCRIPTION
+
+OPENSSL_hexchar2int() converts a hexadecimal character to its numeric
+equivalent.
+
+OPENSSL_hexstr2buf_ex() decodes the hex string B<str> and places the
+resulting string of bytes in the given I<buf>.
+The character I<sep> is the separator between the bytes, setting this to '\0'
+means that there is no separator.
+I<buf_n> gives the size of the buffer.
+If I<buflen> is not NULL, it is filled in with the result length.
+To find out how large the result will be, call this function with NULL
+for I<buf>.
+Colons between two-character hex "bytes" are accepted and ignored.
+An odd number of hex digits is an error.
+
+OPENSSL_hexstr2buf() does the same thing as OPENSSL_hexstr2buf_ex(),
+but allocates the space for the result, and returns the result. It uses a
+default separator of ':'.
+The memory is allocated by calling OPENSSL_malloc() and should be
+released by calling OPENSSL_free().
+
+OPENSSL_buf2hexstr_ex() encodes the contents of the given I<buf> with
+length I<buflen> and places the resulting hexadecimal character string
+in the given I<str>.
+The character I<sep> is the separator between the bytes, setting this to '\0'
+means that there is no separator.
+I<str_n> gives the size of the of the string buffer.
+If I<strlength> is not NULL, it is filled in with the result length.
+To find out how large the result will be, call this function with NULL
+for I<str>.
+
+OPENSSL_buf2hexstr() does the same thing as OPENSSL_buf2hexstr_ex(),
+but allocates the space for the result, and returns the result. It uses a
+default separator of ':'.
+The memory is allocated by calling OPENSSL_malloc() and should be
+released by calling OPENSSL_free().
+
+=head1 RETURN VALUES
+
+OPENSSL_hexchar2int returns the value of a decoded hex character,
+or -1 on error.
+
+OPENSSL_buf2hexstr() and OPENSSL_hexstr2buf()
+return a pointer to allocated memory, or NULL on error.
+
+OPENSSL_buf2hexstr_ex() and OPENSSL_hexstr2buf_ex() return 1 on
+success, or 0 on error.
+
+=head1 COPYRIGHT
+
+Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OPENSSL_ia32cap.pod b/doc/man3/OPENSSL_ia32cap.pod
index 73c96d70e698..c6c1c0185ad8 100644
--- a/doc/man3/OPENSSL_ia32cap.pod
+++ b/doc/man3/OPENSSL_ia32cap.pod
@@ -69,10 +69,10 @@ executed on SSE2 capable CPU, but under control of OS that does not
enable XMM registers. Historically address of the capability vector copy
was exposed to application through OPENSSL_ia32cap_loc(), but not
anymore. Now the only way to affect the capability detection is to set
-OPENSSL_ia32cap environment variable prior target application start. To
-give a specific example, on Intel P4 processor 'env
-OPENSSL_ia32cap=0x16980010 apps/openssl', or better yet 'env
-OPENSSL_ia32cap=~0x1000000 apps/openssl' would achieve the desired
+B<OPENSSL_ia32cap> environment variable prior target application start. To
+give a specific example, on Intel P4 processor
+C<env OPENSSL_ia32cap=0x16980010 apps/openssl>, or better yet
+C<env OPENSSL_ia32cap=~0x1000000 apps/openssl> would achieve the desired
effect. Alternatively you can reconfigure the toolkit with no-sse2
option and recompile.
@@ -97,6 +97,8 @@ and RORX;
=item bit #64+16 denoting availability of AVX512F extension;
+=item bit #64+17 denoting availability of AVX512DQ extension;
+
=item bit #64+18 denoting availability of RDSEED instruction;
=item bit #64+19 denoting availability of ADCX and ADOX instructions;
@@ -116,50 +118,20 @@ aka AVX512IFMA extension;
=back
-To control this extended capability word use ':' as delimiter when
-setting up OPENSSL_ia32cap environment variable. For example assigning
-':~0x20' would disable AVX2 code paths, and ':0' - all post-AVX
+To control this extended capability word use C<:> as delimiter when
+setting up B<OPENSSL_ia32cap> environment variable. For example assigning
+C<:~0x20> would disable AVX2 code paths, and C<:0> - all post-AVX
extensions.
-It should be noted that whether or not some of the most "fancy"
-extension code paths are actually assembled depends on current assembler
-version. Base minimum of AES-NI/PCLMULQDQ, SSSE3 and SHA extension code
-paths are always assembled. Apart from that, minimum assembler version
-requirements are summarized in below table:
-
- Extension | GNU as | nasm | llvm
- ------------+--------+--------+--------
- AVX | 2.19 | 2.09 | 3.0
- AVX2 | 2.22 | 2.10 | 3.1
- ADCX/ADOX | 2.23 | 2.10 | 3.3
- AVX512 | 2.25 | 2.11.8 | see NOTES
- AVX512IFMA | 2.26 | 2.11.8 | see NOTES
- VAES | 2.30 | 2.13.3 |
-
-=head1 NOTES
-
-Even though AVX512 support was implemented in llvm 3.6, compilation of
-assembly modules apparently requires explicit -march flag. But then
-compiler generates processor-specific code, which in turn contradicts
-the mere idea of run-time switch execution facilitated by the variable
-in question. Till the limitation is lifted, it's possible to work around
-the problem by making build procedure use following script:
-
- #!/bin/sh
- exec clang -no-integrated-as "$@"
-
-instead of real clang. In which case it doesn't matter which clang
-version is used, as it is GNU assembler version that will be checked.
-
=head1 RETURN VALUES
Not available.
=head1 COPYRIGHT
-Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OPENSSL_init_crypto.pod b/doc/man3/OPENSSL_init_crypto.pod
index d01dba3d29dd..c3e72d274423 100644
--- a/doc/man3/OPENSSL_init_crypto.pod
+++ b/doc/man3/OPENSSL_init_crypto.pod
@@ -5,7 +5,7 @@
OPENSSL_INIT_new, OPENSSL_INIT_set_config_filename,
OPENSSL_INIT_set_config_appname, OPENSSL_INIT_set_config_file_flags,
OPENSSL_INIT_free, OPENSSL_init_crypto, OPENSSL_cleanup, OPENSSL_atexit,
-OPENSSL_thread_stop - OpenSSL initialisation
+OPENSSL_thread_stop_ex, OPENSSL_thread_stop - OpenSSL initialisation
and deinitialisation functions
=head1 SYNOPSIS
@@ -15,6 +15,7 @@ and deinitialisation functions
void OPENSSL_cleanup(void);
int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
int OPENSSL_atexit(void (*handler)(void));
+ void OPENSSL_thread_stop_ex(OSSL_LIB_CTX *ctx);
void OPENSSL_thread_stop(void);
OPENSSL_INIT_SETTINGS *OPENSSL_INIT_new(void);
@@ -100,10 +101,12 @@ B<OPENSSL_INIT_ADD_ALL_DIGESTS> will be ignored.
=item OPENSSL_INIT_LOAD_CONFIG
With this option an OpenSSL configuration file will be automatically loaded and
-used by calling OPENSSL_config(). This is not a default option for libcrypto.
-As of OpenSSL 1.1.1 this is a default option for libssl (see
-L<OPENSSL_init_ssl(3)> for further details about libssl initialisation). See the
-description of OPENSSL_INIT_new(), below.
+used by calling OPENSSL_config(). This is a default option.
+Note that in OpenSSL 1.1.1 this was the default for libssl but not for
+libcrypto (see L<OPENSSL_init_ssl(3)> for further details about libssl
+initialisation).
+In OpenSSL 1.1.0 this was a nondefault option for both libssl and libcrypto.
+See the description of OPENSSL_INIT_new(), below.
=item OPENSSL_INIT_NO_LOAD_CONFIG
@@ -119,43 +122,51 @@ sub-library (see L<ASYNC_start_job(3)>). This is a default option.
=item OPENSSL_INIT_ENGINE_RDRAND
With this option the library will automatically load and initialise the
-RDRAND engine (if available). This not a default option.
+RDRAND engine (if available). This not a default option and is deprecated
+in OpenSSL 3.0.
=item OPENSSL_INIT_ENGINE_DYNAMIC
With this option the library will automatically load and initialise the
-dynamic engine. This not a default option.
+dynamic engine. This not a default option and is deprecated
+in OpenSSL 3.0.
=item OPENSSL_INIT_ENGINE_OPENSSL
With this option the library will automatically load and initialise the
-openssl engine. This not a default option.
+openssl engine. This not a default option and is deprecated
+in OpenSSL 3.0.
=item OPENSSL_INIT_ENGINE_CRYPTODEV
With this option the library will automatically load and initialise the
-cryptodev engine (if available). This not a default option.
+cryptodev engine (if available). This not a default option and is deprecated
+in OpenSSL 3.0.
=item OPENSSL_INIT_ENGINE_CAPI
With this option the library will automatically load and initialise the
-CAPI engine (if available). This not a default option.
+CAPI engine (if available). This not a default option and is deprecated
+in OpenSSL 3.0.
=item OPENSSL_INIT_ENGINE_PADLOCK
With this option the library will automatically load and initialise the
-padlock engine (if available). This not a default option.
+padlock engine (if available). This not a default option and is deprecated
+in OpenSSL 3.0.
=item OPENSSL_INIT_ENGINE_AFALG
With this option the library will automatically load and initialise the
-AFALG engine. This not a default option.
+AFALG engine. This not a default option and is deprecated
+in OpenSSL 3.0.
=item OPENSSL_INIT_ENGINE_ALL_BUILTIN
With this option the library will automatically load and initialise all the
built in engines listed above with the exception of the openssl and afalg
-engines. This not a default option.
+engines. This not a default option and is deprecated
+in OpenSSL 3.0.
=item OPENSSL_INIT_ATFORK
@@ -194,7 +205,7 @@ Attempts to call OPENSSL_init_crypto() will fail and an ERR_R_INIT_FAIL error
will be added to the error stack. Note that because initialisation has failed
OpenSSL error strings will not be available, only an error code. This code can
be put through the openssl errstr command line application to produce a human
-readable error (see L<errstr(1)>).
+readable error (see L<openssl-errstr(1)>).
The OPENSSL_atexit() function enables the registration of a
function to be called during OPENSSL_cleanup(). Stop handlers are
@@ -202,11 +213,25 @@ called after deinitialisation of resources local to a thread, but before other
process wide resources are freed. In the event that multiple stop handlers are
registered, no guarantees are made about the order of execution.
-The OPENSSL_thread_stop() function deallocates resources associated
-with the current thread. Typically this function will be called automatically by
-the library when the thread exits. This should only be called directly if
-resources should be freed at an earlier time, or under the circumstances
-described in the NOTES section below.
+The OPENSSL_thread_stop_ex() function deallocates resources associated
+with the current thread for the given OSSL_LIB_CTX B<ctx>. The B<ctx> parameter
+can be NULL in which case the default OSSL_LIB_CTX is used.
+
+Typically, this function will be called automatically by the library when
+the thread exits as long as the OSSL_LIB_CTX has not been freed before the thread
+exits. If OSSL_LIB_CTX_free() is called OPENSSL_thread_stop_ex will be called
+automatically for the current thread (but not any other threads that may have
+used this OSSL_LIB_CTX).
+
+OPENSSL_thread_stop_ex should be called on all threads that will exit after the
+OSSL_LIB_CTX is freed.
+Typically this is not necessary for the default OSSL_LIB_CTX (because all
+resources are cleaned up on library exit) except if thread local resources
+should be freed before library exit, or under the circumstances described in
+the NOTES section below.
+
+OPENSSL_thread_stop() is the same as OPENSSL_thread_stop_ex() except that the
+default OSSL_LIB_CTX is always used.
The B<OPENSSL_INIT_LOAD_CONFIG> flag will load a configuration file, as with
L<CONF_modules_load_file(3)> with NULL filename and application name and the
@@ -214,7 +239,7 @@ B<CONF_MFLAGS_IGNORE_MISSING_FILE>, B<CONF_MFLAGS_IGNORE_RETURN_CODES> and
B<CONF_MFLAGS_DEFAULT_SECTION> flags.
The filename, application name, and flags can be customized by providing a
non-null B<OPENSSL_INIT_SETTINGS> object.
-The object can be allocated via B<OPENSSL_init_new()>.
+The object can be allocated via B<OPENSSL_INIT_new()>.
The B<OPENSSL_INIT_set_config_filename()> function can be used to specify a
nondefault filename, which is copied and need not refer to persistent storage.
Similarly, OPENSSL_INIT_set_config_appname() can be used to specify a
@@ -266,7 +291,7 @@ and OPENSSL_INIT_free() functions were added in OpenSSL 1.1.0.
Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OPENSSL_init_ssl.pod b/doc/man3/OPENSSL_init_ssl.pod
index cf4f08911409..ca060bffc83b 100644
--- a/doc/man3/OPENSSL_init_ssl.pod
+++ b/doc/man3/OPENSSL_init_ssl.pod
@@ -76,7 +76,7 @@ The OPENSSL_init_ssl() function was added in OpenSSL 1.1.0.
Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OPENSSL_instrument_bus.pod b/doc/man3/OPENSSL_instrument_bus.pod
index 744153ece6d5..1af07b29c7ed 100644
--- a/doc/man3/OPENSSL_instrument_bus.pod
+++ b/doc/man3/OPENSSL_instrument_bus.pod
@@ -7,8 +7,8 @@ OPENSSL_instrument_bus, OPENSSL_instrument_bus2 - instrument references to memor
=head1 SYNOPSIS
#ifdef OPENSSL_CPUID_OBJ
- size_t OPENSSL_instrument_bus(int *vector, size_t num);
- size_t OPENSSL_instrument_bus2(int *vector, size_t num, size_t max);
+ size_t OPENSSL_instrument_bus(unsigned int *vector, size_t num);
+ size_t OPENSSL_instrument_bus2(unsigned int *vector, size_t num, size_t max);
#endif
=head1 DESCRIPTION
@@ -43,9 +43,9 @@ Otherwise number of recorded values is returned.
=head1 COPYRIGHT
-Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OPENSSL_load_builtin_modules.pod b/doc/man3/OPENSSL_load_builtin_modules.pod
index bf0dc413bfe3..126ef8331a2d 100644
--- a/doc/man3/OPENSSL_load_builtin_modules.pod
+++ b/doc/man3/OPENSSL_load_builtin_modules.pod
@@ -44,11 +44,15 @@ None of the functions return a value.
L<config(5)>, L<OPENSSL_config(3)>
+=head1 HISTORY
+
+ENGINE_add_conf_module() was deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OPENSSL_malloc.pod b/doc/man3/OPENSSL_malloc.pod
index 9834a8f13147..76751012bde5 100644
--- a/doc/man3/OPENSSL_malloc.pod
+++ b/doc/man3/OPENSSL_malloc.pod
@@ -8,11 +8,11 @@ OPENSSL_clear_realloc, OPENSSL_clear_free, OPENSSL_cleanse,
CRYPTO_malloc, CRYPTO_zalloc, CRYPTO_realloc, CRYPTO_free,
OPENSSL_strdup, OPENSSL_strndup,
OPENSSL_memdup, OPENSSL_strlcpy, OPENSSL_strlcat,
-OPENSSL_hexstr2buf, OPENSSL_buf2hexstr, OPENSSL_hexchar2int,
CRYPTO_strdup, CRYPTO_strndup,
OPENSSL_mem_debug_push, OPENSSL_mem_debug_pop,
CRYPTO_mem_debug_push, CRYPTO_mem_debug_pop,
CRYPTO_clear_realloc, CRYPTO_clear_free,
+CRYPTO_malloc_fn, CRYPTO_realloc_fn, CRYPTO_free_fn,
CRYPTO_get_mem_functions, CRYPTO_set_mem_functions,
CRYPTO_get_alloc_counts,
CRYPTO_set_mem_debug, CRYPTO_mem_ctrl,
@@ -25,64 +25,63 @@ OPENSSL_MALLOC_FD
#include <openssl/crypto.h>
- int OPENSSL_malloc_init(void)
+ int OPENSSL_malloc_init(void);
- void *OPENSSL_malloc(size_t num)
- void *OPENSSL_zalloc(size_t num)
- void *OPENSSL_realloc(void *addr, size_t num)
- void OPENSSL_free(void *addr)
- char *OPENSSL_strdup(const char *str)
- char *OPENSSL_strndup(const char *str, size_t s)
+ void *OPENSSL_malloc(size_t num);
+ void *OPENSSL_zalloc(size_t num);
+ void *OPENSSL_realloc(void *addr, size_t num);
+ void OPENSSL_free(void *addr);
+ char *OPENSSL_strdup(const char *str);
+ char *OPENSSL_strndup(const char *str, size_t s);
size_t OPENSSL_strlcat(char *dst, const char *src, size_t size);
size_t OPENSSL_strlcpy(char *dst, const char *src, size_t size);
- void *OPENSSL_memdup(void *data, size_t s)
- void *OPENSSL_clear_realloc(void *p, size_t old_len, size_t num)
- void OPENSSL_clear_free(void *str, size_t num)
+ void *OPENSSL_memdup(void *data, size_t s);
+ void *OPENSSL_clear_realloc(void *p, size_t old_len, size_t num);
+ void OPENSSL_clear_free(void *str, size_t num);
void OPENSSL_cleanse(void *ptr, size_t len);
- unsigned char *OPENSSL_hexstr2buf(const char *str, long *len);
- char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len);
- int OPENSSL_hexchar2int(unsigned char c);
-
- void *CRYPTO_malloc(size_t num, const char *file, int line)
- void *CRYPTO_zalloc(size_t num, const char *file, int line)
- void *CRYPTO_realloc(void *p, size_t num, const char *file, int line)
- void CRYPTO_free(void *str, const char *, int)
- char *CRYPTO_strdup(const char *p, const char *file, int line)
- char *CRYPTO_strndup(const char *p, size_t num, const char *file, int line)
+ void *CRYPTO_malloc(size_t num, const char *file, int line);
+ void *CRYPTO_zalloc(size_t num, const char *file, int line);
+ void *CRYPTO_realloc(void *p, size_t num, const char *file, int line);
+ void CRYPTO_free(void *str, const char *, int);
+ char *CRYPTO_strdup(const char *p, const char *file, int line);
+ char *CRYPTO_strndup(const char *p, size_t num, const char *file, int line);
void *CRYPTO_clear_realloc(void *p, size_t old_len, size_t num,
- const char *file, int line)
- void CRYPTO_clear_free(void *str, size_t num, const char *, int)
-
- void CRYPTO_get_mem_functions(
- void *(**m)(size_t, const char *, int),
- void *(**r)(void *, size_t, const char *, int),
- void (**f)(void *, const char *, int))
- int CRYPTO_set_mem_functions(
- void *(*m)(size_t, const char *, int),
- void *(*r)(void *, size_t, const char *, int),
- void (*f)(void *, const char *, int))
-
- void CRYPTO_get_alloc_counts(int *m, int *r, int *f)
-
- int CRYPTO_set_mem_debug(int onoff)
+ const char *file, int line);
+ void CRYPTO_clear_free(void *str, size_t num, const char *, int);
+
+ typedef void *(*CRYPTO_malloc_fn)(size_t num, const char *file, int line);
+ typedef void *(*CRYPTO_realloc_fn)(void *addr, size_t num, const char *file,
+ int line);
+ typedef void (*CRYPTO_free_fn)(void *addr, const char *file, int line);
+ void CRYPTO_get_mem_functions(CRYPTO_malloc_fn *malloc_fn,
+ CRYPTO_realloc_fn *realloc_fn,
+ CRYPTO_free_fn *free_fn);
+ int CRYPTO_set_mem_functions(CRYPTO_malloc_fn malloc_fn,
+ CRYPTO_realloc_fn realloc_fn,
+ CRYPTO_free_fn free_fn);
+
+ void CRYPTO_get_alloc_counts(int *mcount, int *rcount, int *fcount);
env OPENSSL_MALLOC_FAILURES=... <application>
env OPENSSL_MALLOC_FD=... <application>
- int CRYPTO_mem_ctrl(int mode);
-
- int OPENSSL_mem_debug_push(const char *info)
- int OPENSSL_mem_debug_pop(void);
-
- int CRYPTO_mem_debug_push(const char *info, const char *file, int line);
- int CRYPTO_mem_debug_pop(void);
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
int CRYPTO_mem_leaks(BIO *b);
int CRYPTO_mem_leaks_fp(FILE *fp);
int CRYPTO_mem_leaks_cb(int (*cb)(const char *str, size_t len, void *u),
void *u);
+ int CRYPTO_set_mem_debug(int onoff);
+ int CRYPTO_mem_ctrl(int mode);
+ int OPENSSL_mem_debug_push(const char *info);
+ int OPENSSL_mem_debug_pop(void);
+ int CRYPTO_mem_debug_push(const char *info, const char *file, int line);
+ int CRYPTO_mem_debug_pop(void);
+
=head1 DESCRIPTION
OpenSSL memory allocation is handled by the B<OPENSSL_xxx> API. These are
@@ -118,61 +117,17 @@ OPENSSL_strlcpy(),
OPENSSL_strlcat() and OPENSSL_strnlen() are equivalents of the common C
library functions and are provided for portability.
-OPENSSL_hexstr2buf() parses B<str> as a hex string and returns a
-pointer to the parsed value. The memory is allocated by calling
-OPENSSL_malloc() and should be released by calling OPENSSL_free().
-If B<len> is not NULL, it is filled in with the output length.
-Colons between two-character hex "bytes" are ignored.
-An odd number of hex digits is an error.
-
-OPENSSL_buf2hexstr() takes the specified buffer and length, and returns
-a hex string for value, or NULL on error.
-B<Buffer> cannot be NULL; if B<len> is 0 an empty string is returned.
-
-OPENSSL_hexchar2int() converts a character to the hexadecimal equivalent,
-or returns -1 on error.
-
If no allocations have been done, it is possible to "swap out" the default
-implementations for OPENSSL_malloc(), OPENSSL_realloc and OPENSSL_free()
-and replace them with alternate versions (hooks).
+implementations for OPENSSL_malloc(), OPENSSL_realloc() and OPENSSL_free()
+and replace them with alternate versions.
CRYPTO_get_mem_functions() function fills in the given arguments with the
function pointers for the current implementations.
With CRYPTO_set_mem_functions(), you can specify a different set of functions.
-If any of B<m>, B<r>, or B<f> are NULL, then the function is not changed.
-
-The default implementation can include some debugging capability (if enabled
-at build-time).
-This adds some overhead by keeping a list of all memory allocations, and
-removes items from the list when they are free'd.
-This is most useful for identifying memory leaks.
-CRYPTO_set_mem_debug() turns this tracking on and off. In order to have
-any effect, is must be called before any of the allocation functions
-(e.g., CRYPTO_malloc()) are called, and is therefore normally one of the
-first lines of main() in an application.
-CRYPTO_mem_ctrl() provides fine-grained control of memory leak tracking.
-To enable tracking call CRYPTO_mem_ctrl() with a B<mode> argument of
-the B<CRYPTO_MEM_CHECK_ON>.
-To disable tracking call CRYPTO_mem_ctrl() with a B<mode> argument of
-the B<CRYPTO_MEM_CHECK_OFF>.
-
-While checking memory, it can be useful to store additional context
-about what is being done.
-For example, identifying the field names when parsing a complicated
-data structure.
-OPENSSL_mem_debug_push() (which calls CRYPTO_mem_debug_push())
-attaches an identifying string to the allocation stack.
-This must be a global or other static string; it is not copied.
-OPENSSL_mem_debug_pop() removes identifying state from the stack.
-
-At the end of the program, calling CRYPTO_mem_leaks() or
-CRYPTO_mem_leaks_fp() will report all "leaked" memory, writing it
-to the specified BIO B<b> or FILE B<fp>. These functions return 1 if
-there are no leaks, 0 if there are leaks and -1 if an error occurred.
-
-CRYPTO_mem_leaks_cb() does the same as CRYPTO_mem_leaks(), but instead
-of writing to a given BIO, the callback function is called for each
-output string with the string, length, and userdata B<u> as the callback
-parameters.
+If any of B<malloc_fn>, B<realloc_fn>, or B<free_fn> are NULL, then
+the function is not changed.
+While it's permitted to swap out only a few and not all the functions
+with CRYPTO_set_mem_functions(), it's recommended to swap them all out
+at once.
If the library is built with the C<crypto-mdebug> option, then one
function, CRYPTO_get_alloc_counts(), and two additional environment
@@ -194,12 +149,12 @@ other allocations (until the program exits or crashes) have a 25% chance of
failing.
If the variable B<OPENSSL_MALLOC_FD> is parsed as a positive integer, then
-it is taken as an open file descriptor, and a record of all allocations is
-written to that descriptor. If an allocation will fail, and the platform
-supports it, then a backtrace will be written to the descriptor. This can
-be useful because a malloc may fail but not be checked, and problems will
-only occur later. The following example in classic shell syntax shows how
-to use this (will not work on all platforms):
+it is taken as an open file descriptor. This is used in conjunction with
+B<OPENSSL_MALLOC_FAILURES> described above. For every allocation it will log
+details about how many allocations there have been so far, what percentage
+chance there is for this allocation failing, and whether it has actually failed.
+The following example in classic shell syntax shows how to use this (will not
+work on all platforms):
OPENSSL_MALLOC_FAILURES='200;@10'
export OPENSSL_MALLOC_FAILURES
@@ -207,47 +162,45 @@ to use this (will not work on all platforms):
export OPENSSL_MALLOC_FD
...app invocation... 3>/tmp/log$$
-
=head1 RETURN VALUES
OPENSSL_malloc_init(), OPENSSL_free(), OPENSSL_clear_free()
CRYPTO_free(), CRYPTO_clear_free() and CRYPTO_get_mem_functions()
return no value.
-CRYPTO_mem_leaks(), CRYPTO_mem_leaks_fp() and CRYPTO_mem_leaks_cb() return 1 if
-there are no leaks, 0 if there are leaks and -1 if an error occurred.
-
OPENSSL_malloc(), OPENSSL_zalloc(), OPENSSL_realloc(),
OPENSSL_clear_realloc(),
CRYPTO_malloc(), CRYPTO_zalloc(), CRYPTO_realloc(),
CRYPTO_clear_realloc(),
-OPENSSL_buf2hexstr(), OPENSSL_hexstr2buf(),
OPENSSL_strdup(), and OPENSSL_strndup()
return a pointer to allocated memory or NULL on error.
-CRYPTO_set_mem_functions() and CRYPTO_set_mem_debug()
-return 1 on success or 0 on failure (almost
+CRYPTO_set_mem_functions() returns 1 on success or 0 on failure (almost
always because allocations have already happened).
-CRYPTO_mem_ctrl() returns -1 if an error occurred, otherwise the
-previous value of the mode.
+CRYPTO_mem_leaks(), CRYPTO_mem_leaks_fp(), CRYPTO_mem_leaks_cb(),
+CRYPTO_set_mem_debug(), and CRYPTO_mem_ctrl() are deprecated and are no-ops that
+always return -1.
+OPENSSL_mem_debug_push(), OPENSSL_mem_debug_pop(),
+CRYPTO_mem_debug_push(), and CRYPTO_mem_debug_pop()
+are deprecated and are no-ops that always return 0.
-OPENSSL_mem_debug_push() and OPENSSL_mem_debug_pop()
-return 1 on success or 0 on failure.
+=head1 HISTORY
-=head1 NOTES
+OPENSSL_mem_debug_push(), OPENSSL_mem_debug_pop(),
+CRYPTO_mem_debug_push(), CRYPTO_mem_debug_pop(),
+CRYPTO_mem_leaks(), CRYPTO_mem_leaks_fp(),
+CRYPTO_mem_leaks_cb(), CRYPTO_set_mem_debug(), CRYPTO_mem_ctrl()
+were deprecated in OpenSSL 3.0.
+The memory-leak checking has been deprecated in OpenSSL 3.0 in favor of
+clang's memory and leak sanitizer.
-While it's permitted to swap out only a few and not all the functions
-with CRYPTO_set_mem_functions(), it's recommended to swap them all out
-at once. I<This applies specially if OpenSSL was built with the
-configuration option> C<crypto-mdebug> I<enabled. In case, swapping out
-only, say, the malloc() implementation is outright dangerous.>
=head1 COPYRIGHT
-Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OPENSSL_s390xcap.pod b/doc/man3/OPENSSL_s390xcap.pod
new file mode 100644
index 000000000000..f40524115324
--- /dev/null
+++ b/doc/man3/OPENSSL_s390xcap.pod
@@ -0,0 +1,199 @@
+=pod
+
+=head1 NAME
+
+OPENSSL_s390xcap - the IBM z processor capabilities vector
+
+=head1 SYNOPSIS
+
+ env OPENSSL_s390xcap=... <application>
+
+=head1 DESCRIPTION
+
+libcrypto supports z/Architecture instruction set extensions. These
+extensions are denoted by individual bits in the capabilities vector.
+When libcrypto is initialized, the bits returned by the STFLE instruction
+and by the QUERY functions are stored in the vector.
+
+To change the set of instructions available to an application, you can
+set the B<OPENSSL_s390xcap> environment variable before you start the
+application. After initialization, the capability vector is ANDed bitwise
+with a mask which is derived from the environment variable.
+
+The environment variable is a semicolon-separated list of tokens which is
+processed from left to right (whitespace is ignored):
+
+ OPENSSL_s390xcap="<tok1>;<tok2>;..."
+
+There are three types of tokens:
+
+=over 4
+
+=item <string>
+
+The name of a processor generation. A bit in the environment variable's
+mask is set to one if and only if the specified processor generation
+implements the corresponding instruction set extension. Possible values
+are B<z900>, B<z990>, B<z9>, B<z10>, B<z196>, B<zEC12>, B<z13>, B<z14>
+and B<z15>.
+
+=item <string>:<mask>:<mask>
+
+The name of an instruction followed by two 64-bit masks. The part of the
+environment variable's mask corresponding to the specified instruction is
+set to the specified 128-bit mask. Possible values are B<kimd>, B<klmd>,
+B<km>, B<kmc>, B<kmac>, B<kmctr>, B<kmo>, B<kmf>, B<prno>, B<kma>, B<pcc>
+and B<kdsa>.
+
+=item stfle:<mask>:<mask>:<mask>
+
+Store-facility-list-extended (stfle) followed by three 64-bit masks. The
+part of the environment variable's mask corresponding to the stfle
+instruction is set to the specified 192-bit mask.
+
+=back
+
+The 64-bit masks are specified in hexadecimal notation. The 0x prefix is
+optional. Prefix a mask with a tilde, C<~>, to denote a bitwise NOT operation.
+
+The following is a list of significant bits for each instruction. Colon
+rows separate the individual 64-bit masks. The bit numbers in the first
+column are consistent with [1], that is, 0 denotes the leftmost bit and
+the numbering is continuous across 64-bit mask boundaries.
+
+ Bit Mask Facility/Function
+
+ stfle:
+ # 17 1<<46 message-security assist
+ # 25 1<<38 store-clock-fast facility
+ :
+ # 76 1<<51 message-security assist extension 3
+ # 77 1<<50 message-security assist extension 4
+ :
+ #129 1<<62 vector facility
+ #134 1<<57 vector packed decimal facility
+ #135 1<<56 vector enhancements facility 1
+ #146 1<<45 message-security assist extension 8
+ #155 1<<36 message-security assist extension 9
+
+ kimd :
+ # 1 1<<62 KIMD-SHA-1
+ # 2 1<<61 KIMD-SHA-256
+ # 3 1<<60 KIMD-SHA-512
+ # 32 1<<31 KIMD-SHA3-224
+ # 33 1<<30 KIMD-SHA3-256
+ # 34 1<<29 KIMD-SHA3-384
+ # 35 1<<28 KIMD-SHA3-512
+ # 36 1<<27 KIMD-SHAKE-128
+ # 37 1<<26 KIMD-SHAKE-256
+ :
+ # 65 1<<62 KIMD-GHASH
+
+ klmd :
+ # 32 1<<31 KLMD-SHA3-224
+ # 33 1<<30 KLMD-SHA3-256
+ # 34 1<<29 KLMD-SHA3-384
+ # 35 1<<28 KLMD-SHA3-512
+ # 36 1<<27 KLMD-SHAKE-128
+ # 37 1<<26 KLMD-SHAKE-256
+ :
+
+ km :
+ # 18 1<<45 KM-AES-128
+ # 19 1<<44 KM-AES-192
+ # 20 1<<43 KM-AES-256
+ # 50 1<<13 KM-XTS-AES-128
+ # 52 1<<11 KM-XTS-AES-256
+ :
+
+ kmc :
+ # 18 1<<45 KMC-AES-128
+ # 19 1<<44 KMC-AES-192
+ # 20 1<<43 KMC-AES-256
+ :
+
+ kmac :
+ # 18 1<<45 KMAC-AES-128
+ # 19 1<<44 KMAC-AES-192
+ # 20 1<<43 KMAC-AES-256
+ :
+
+ kmctr:
+ :
+
+ kmo :
+ # 18 1<<45 KMO-AES-128
+ # 19 1<<44 KMO-AES-192
+ # 20 1<<43 KMO-AES-256
+ :
+
+ kmf :
+ # 18 1<<45 KMF-AES-128
+ # 19 1<<44 KMF-AES-192
+ # 20 1<<43 KMF-AES-256
+ :
+
+ prno :
+ :
+
+ kma :
+ # 18 1<<45 KMA-GCM-AES-128
+ # 19 1<<44 KMA-GCM-AES-192
+ # 20 1<<43 KMA-GCM-AES-256
+ :
+
+ pcc :
+ :
+ # 64 1<<63 PCC-Scalar-Multiply-P256
+ # 65 1<<62 PCC-Scalar-Multiply-P384
+ # 66 1<<61 PCC-Scalar-Multiply-P521
+ # 72 1<<55 PCC-Scalar-Multiply-Ed25519
+ # 73 1<<54 PCC-Scalar-Multiply-Ed448
+ # 80 1<<47 PCC-Scalar-Multiply-X25519
+ # 81 1<<46 PCC-Scalar-Multiply-X448
+
+ kdsa :
+ # 1 1<<62 KDSA-ECDSA-Verify-P256
+ # 2 1<<61 KDSA-ECDSA-Verify-P384
+ # 3 1<<60 KDSA-ECDSA-Verify-P521
+ # 9 1<<54 KDSA-ECDSA-Sign-P256
+ # 10 1<<53 KDSA-ECDSA-Sign-P384
+ # 11 1<<52 KDSA-ECDSA-Sign-P521
+ # 32 1<<31 KDSA-EdDSA-Verify-Ed25519
+ # 36 1<<27 KDSA-EdDSA-Verify-Ed448
+ # 40 1<<23 KDSA-EdDSA-Sign-Ed25519
+ # 44 1<<19 KDSA-EdDSA-Sign-Ed448
+ :
+
+=head1 RETURN VALUES
+
+Not available.
+
+=head1 EXAMPLES
+
+Disables all instruction set extensions which the z196 processor does not implement:
+
+ OPENSSL_s390xcap="z196"
+
+Disables the vector facility:
+
+ OPENSSL_s390xcap="stfle:~0:~0:~0x4000000000000000"
+
+Disables the KM-XTS-AES and the KIMD-SHAKE function codes:
+
+ OPENSSL_s390xcap="km:~0x2800:~0;kimd:~0xc000000:~0"
+
+=head1 SEE ALSO
+
+[1] z/Architecture Principles of Operation, SA22-7832-12
+
+=head1 COPYRIGHT
+
+Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OPENSSL_secure_malloc.pod b/doc/man3/OPENSSL_secure_malloc.pod
index 86c2522afe49..c5d4bb2dbbb8 100644
--- a/doc/man3/OPENSSL_secure_malloc.pod
+++ b/doc/man3/OPENSSL_secure_malloc.pod
@@ -14,7 +14,7 @@ CRYPTO_secure_used - secure heap storage
#include <openssl/crypto.h>
- int CRYPTO_secure_malloc_init(size_t size, int minsize);
+ int CRYPTO_secure_malloc_init(size_t size, size_t minsize);
int CRYPTO_secure_malloc_initialized();
@@ -53,8 +53,10 @@ put all intermediate values and computations there.
CRYPTO_secure_malloc_init() creates the secure heap, with the specified
C<size> in bytes. The C<minsize> parameter is the minimum size to
-allocate from the heap. Both C<size> and C<minsize> must be a power
-of two.
+allocate from the heap or zero to use a reasonable default value.
+Both C<size> and, if specified, C<minsize> must be a power of two and
+C<minsize> should generally be small, for example 16 or 32.
+C<minsize> must be less than a quarter of C<size> in any case.
CRYPTO_secure_malloc_initialized() indicates whether or not the secure
heap as been initialized and is available.
@@ -126,11 +128,14 @@ L<BN_new(3)>
The OPENSSL_secure_clear_free() function was added in OpenSSL 1.1.0g.
+The second argument to CRYPTO_secure_malloc_init() was changed from an B<int> to
+a B<size_t> in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OPENSSL_strcasecmp.pod b/doc/man3/OPENSSL_strcasecmp.pod
new file mode 100644
index 000000000000..1bb8b18c5013
--- /dev/null
+++ b/doc/man3/OPENSSL_strcasecmp.pod
@@ -0,0 +1,47 @@
+=pod
+
+=head1 NAME
+
+OPENSSL_strcasecmp, OPENSSL_strncasecmp - compare two strings ignoring case
+
+=head1 SYNOPSIS
+
+ #include <openssl/crypto.h>
+
+ int OPENSSL_strcasecmp(const char *s1, const char *s2);
+ int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n);
+
+=head1 DESCRIPTION
+
+The OPENSSL_strcasecmp function performs a byte-by-byte comparison of the strings
+B<s1> and B<s2>, ignoring the case of the characters.
+
+The OPENSSL_strncasecmp function is similar, except that it compares no more than
+B<n> bytes of B<s1> and B<s2>.
+
+In POSIX-compatible system and on Windows these functions use "C" locale for
+case insensitive. Otherwise the comparison is done in current locale.
+
+=head1 RETURN VALUES
+
+Both functions return an integer less than, equal to, or greater than zero if
+s1 is found, respectively, to be less than, to match, or be greater than s2.
+
+=head1 NOTES
+
+OpenSSL extensively uses case insensitive comparison of ASCII strings. Though
+OpenSSL itself is locale-agnostic, the applications using OpenSSL libraries may
+unpredictably suffer when they use localization (e.g. Turkish locale is
+well-known with a specific I/i cases). These functions use C locale for string
+comparison.
+
+=head1 COPYRIGHT
+
+Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_ALGORITHM.pod b/doc/man3/OSSL_ALGORITHM.pod
new file mode 100644
index 000000000000..cc9271b9a412
--- /dev/null
+++ b/doc/man3/OSSL_ALGORITHM.pod
@@ -0,0 +1,151 @@
+=pod
+
+=head1 NAME
+
+OSSL_ALGORITHM - OpenSSL Core type to define a fetchable algorithm
+
+=head1 SYNOPSIS
+
+ #include <openssl/core.h>
+
+ typedef struct ossl_algorithm_st OSSL_ALGORITHM;
+ struct ossl_algorithm_st {
+ const char *algorithm_names; /* key */
+ const char *property_definition; /* key */
+ const OSSL_DISPATCH *implementation;
+ const char *algorithm_description;
+ };
+
+=head1 DESCRIPTION
+
+The B<OSSL_ALGORITHM> type is a I<public structure> that describes an
+algorithm that a L<provider(7)> provides. Arrays of this type are returned
+by providers on demand from the OpenSSL libraries to describe what
+algorithms the providers provide implementations of, and with what
+properties.
+
+Arrays of this type must be terminated with a tuple where I<algorithm_names>
+is NULL.
+
+This type of array is typically returned by the provider's operation querying
+function, further described in L<provider-base(7)/Provider Functions>.
+
+=head2 B<OSSL_ALGORITHM> fields
+
+=over 4
+
+=item I<algorithm_names>
+
+This string is a colon separated set of names / identities, and is used by
+the appropriate fetching functionality (such as L<EVP_CIPHER_fetch(3)>,
+L<EVP_MD_fetch(3)>, etc) to find the desired algorithm.
+
+Multiple names / identities allow a specific algorithm implementation to be
+fetched multiple ways. For example, the RSA algorithm has the following
+known identities:
+
+=over 4
+
+=item *
+
+C<RSA>
+
+=item *
+
+C<rsaEncryption>
+
+This is the name of the algorithm's OBJECT IDENTIFIER (OID), as given by the
+L<PKCS#1 RFC's ASN.1 module|https://www.rfc-editor.org/rfc/rfc8017#appendix-C>
+
+=item *
+
+C<1.2.840.113549.1.1.1>
+
+This is the OID itself for C<rsaEncryption>, in canonical decimal text form.
+
+=back
+
+The resulting I<algorithm_names> string would look like this:
+
+ "RSA:rsaEncryption:1.2.840.113549.1.1.1"
+
+The OpenSSL libraries use the first of the algorithm names as the main
+or canonical name, on a per algorithm implementation basis.
+
+See the notes L</On the subject of algorithm names> below for a more in
+depth discussion on I<algorithm_names> and how that may interact with
+applications and libraries, including OpenSSL's.
+
+=item I<property_definition>
+
+This string defines a set of properties associated with a particular
+algorithm implementation, and is used by the appropriate fetching
+functionality (such as L<EVP_CIPHER_fetch(3)>, L<EVP_MD_fetch(3)>, etc) for
+a finer grained lookup of an algorithm implementation, which is useful in
+case multiple implementations of the same algorithm are available.
+
+See L<property(7)> for a further description of the contents of this
+string.
+
+=item I<implementation>
+
+Pointer to an L<OSSL_DISPATCH(3)> array, containing pointers to the
+functions of a particular algorithm implementation.
+
+=item I<algorithm_description>
+
+A string with a short human-readable description of the algorithm.
+
+=back
+
+=head1 NOTES
+
+=head2 On the subject of algorithm names
+
+Providers may find the need to register ASN.1 OIDs for algorithms using
+L<OBJ_create(3)> (via the B<core_obj_create> upcall described in
+L<provider-base(7)>, because some application or library -- possibly still
+the OpenSSL libraries, even -- use NIDs to look up algorithms.
+
+In that scenario, you must make sure that the corresponding B<OSSL_ALGORITHM>'s
+I<algorithm_names> includes both the short and the long name.
+
+Most of the time, registering ASN.1 OIDs like this shouldn't be necessary,
+and applications and libraries are encouraged to use L<OBJ_obj2txt(3)> to
+get a text representation of the OID, which may be a long or short name for
+OIDs that are registered, or the OID itself in canonical decimal text form
+if not (or if L<OBJ_obj2txt(3)> is called with I<no_name> = 1).
+
+It's recommended to make sure that the corresponding B<OSSL_ALGORITHM>'s
+I<algorithm_names> include known names as well as the OID itself in
+canonical decimal text form. That should cover all scenarios.
+
+=begin comment RETURN VALUES doesn't make sense for a manual that only
+describes a type, but document checkers still want that section, and
+to have more than just the section title.
+
+=head1 RETURN VALUES
+
+txt
+
+=end comment
+
+=head1 SEE ALSO
+
+L<crypto(7)>, L<provider-base(7)>, L<openssl-core.h(7)>,
+L<openssl-core_dispatch.h(7)>, L<OSSL_DISPATCH(3)>
+
+=head1 HISTORY
+
+B<OSSL_ALGORITHM> was added in OpenSSL 3.0
+
+=head1 COPYRIGHT
+
+Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CALLBACK.pod b/doc/man3/OSSL_CALLBACK.pod
new file mode 100644
index 000000000000..5fa8a8f08916
--- /dev/null
+++ b/doc/man3/OSSL_CALLBACK.pod
@@ -0,0 +1,77 @@
+=pod
+
+=head1 NAME
+
+OSSL_CALLBACK, OSSL_PASSPHRASE_CALLBACK - OpenSSL Core type to define callbacks
+
+=head1 SYNOPSIS
+
+ #include <openssl/core.h>
+ typedef int (OSSL_CALLBACK)(const OSSL_PARAM params[], void *arg);
+ typedef int (OSSL_PASSPHRASE_CALLBACK)(char *pass, size_t pass_size,
+ size_t *pass_len,
+ const OSSL_PARAM params[],
+ void *arg);
+
+=head1 DESCRIPTION
+
+For certain events or activities, provider functionality may need help from
+the application or the calling OpenSSL libraries themselves. For example,
+user input or direct (possibly optional) user output could be implemented
+this way.
+
+Callback functions themselves are always provided by or through the calling
+OpenSSL libraries, along with a generic pointer to data I<arg>. As far as
+the function receiving the pointer to the function pointer and I<arg> is
+concerned, the data that I<arg> points at is opaque, and the pointer should
+simply be passed back to the callback function when it's called.
+
+=over 4
+
+=item B<OSSL_CALLBACK>
+
+This is a generic callback function. When calling this callback function,
+the caller is expected to build an L<OSSL_PARAM(3)> array of data it wants or
+is expected to pass back, and pass that as I<params>, as well as the opaque
+data pointer it received, as I<arg>.
+
+=item B<OSSL_PASSPHRASE_CALLBACK>
+
+This is a specialised callback function, used specifically to prompt the
+user for a passphrase. When calling this callback function, a buffer to
+store the pass phrase needs to be given with I<pass>, and its size with
+I<pass_size>. The length of the prompted pass phrase will be given back in
+I<*pass_len>.
+
+Additional parameters can be passed with the L<OSSL_PARAM(3)> array I<params>,
+
+=back
+
+=begin comment RETURN VALUES doesn't make sense for a manual that only
+describes a type, but document checkers still want that section, and
+to have more than just the section title.
+
+=head1 RETURN VALUES
+
+txt
+
+=end comment
+
+=head1 SEE ALSO
+
+L<openssl-core.h(7)>
+
+=head1 HISTORY
+
+The types described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CMP_CTX_new.pod b/doc/man3/OSSL_CMP_CTX_new.pod
new file mode 100644
index 000000000000..3c4e2d3f7d06
--- /dev/null
+++ b/doc/man3/OSSL_CMP_CTX_new.pod
@@ -0,0 +1,802 @@
+=pod
+
+=head1 NAME
+
+OSSL_CMP_CTX_new,
+OSSL_CMP_CTX_free,
+OSSL_CMP_CTX_reinit,
+OSSL_CMP_CTX_set_option,
+OSSL_CMP_CTX_get_option,
+OSSL_CMP_CTX_set_log_cb,
+OSSL_CMP_CTX_set_log_verbosity,
+OSSL_CMP_CTX_print_errors,
+OSSL_CMP_CTX_set1_serverPath,
+OSSL_CMP_CTX_set1_server,
+OSSL_CMP_CTX_set_serverPort,
+OSSL_CMP_CTX_set1_proxy,
+OSSL_CMP_CTX_set1_no_proxy,
+OSSL_CMP_CTX_set_http_cb,
+OSSL_CMP_CTX_set_http_cb_arg,
+OSSL_CMP_CTX_get_http_cb_arg,
+OSSL_CMP_transfer_cb_t,
+OSSL_CMP_CTX_set_transfer_cb,
+OSSL_CMP_CTX_set_transfer_cb_arg,
+OSSL_CMP_CTX_get_transfer_cb_arg,
+OSSL_CMP_CTX_set1_srvCert,
+OSSL_CMP_CTX_set1_expected_sender,
+OSSL_CMP_CTX_set0_trustedStore,
+OSSL_CMP_CTX_get0_trustedStore,
+OSSL_CMP_CTX_set1_untrusted,
+OSSL_CMP_CTX_get0_untrusted,
+OSSL_CMP_CTX_set1_cert,
+OSSL_CMP_CTX_build_cert_chain,
+OSSL_CMP_CTX_set1_pkey,
+OSSL_CMP_CTX_set1_referenceValue,
+OSSL_CMP_CTX_set1_secretValue,
+OSSL_CMP_CTX_set1_recipient,
+OSSL_CMP_CTX_push0_geninfo_ITAV,
+OSSL_CMP_CTX_reset_geninfo_ITAVs,
+OSSL_CMP_CTX_set1_extraCertsOut,
+OSSL_CMP_CTX_set0_newPkey,
+OSSL_CMP_CTX_get0_newPkey,
+OSSL_CMP_CTX_set1_issuer,
+OSSL_CMP_CTX_set1_subjectName,
+OSSL_CMP_CTX_push1_subjectAltName,
+OSSL_CMP_CTX_set0_reqExtensions,
+OSSL_CMP_CTX_reqExtensions_have_SAN,
+OSSL_CMP_CTX_push0_policy,
+OSSL_CMP_CTX_set1_oldCert,
+OSSL_CMP_CTX_set1_p10CSR,
+OSSL_CMP_CTX_push0_genm_ITAV,
+OSSL_CMP_certConf_cb_t,
+OSSL_CMP_certConf_cb,
+OSSL_CMP_CTX_set_certConf_cb,
+OSSL_CMP_CTX_set_certConf_cb_arg,
+OSSL_CMP_CTX_get_certConf_cb_arg,
+OSSL_CMP_CTX_get_status,
+OSSL_CMP_CTX_get0_statusString,
+OSSL_CMP_CTX_get_failInfoCode,
+OSSL_CMP_CTX_get0_newCert,
+OSSL_CMP_CTX_get1_newChain,
+OSSL_CMP_CTX_get1_caPubs,
+OSSL_CMP_CTX_get1_extraCertsIn,
+OSSL_CMP_CTX_set1_transactionID,
+OSSL_CMP_CTX_set1_senderNonce
+- functions for managing the CMP client context data structure
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+
+ OSSL_CMP_CTX *OSSL_CMP_CTX_new(OSSL_LIB_CTX *libctx, const char *propq);
+ void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx);
+ int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx);
+ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val);
+ int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt);
+
+ /* logging and error reporting: */
+ int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_log_cb_t cb);
+ #define OSSL_CMP_CTX_set_log_verbosity(ctx, level)
+ void OSSL_CMP_CTX_print_errors(const OSSL_CMP_CTX *ctx);
+
+ /* message transfer: */
+ int OSSL_CMP_CTX_set1_serverPath(OSSL_CMP_CTX *ctx, const char *path);
+ int OSSL_CMP_CTX_set1_server(OSSL_CMP_CTX *ctx, const char *address);
+ int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port);
+ int OSSL_CMP_CTX_set1_proxy(OSSL_CMP_CTX *ctx, const char *name);
+ int OSSL_CMP_CTX_set1_no_proxy(OSSL_CMP_CTX *ctx, const char *names);
+ int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, HTTP_bio_cb_t cb);
+ int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
+ void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx);
+ typedef OSSL_CMP_MSG *(*OSSL_CMP_transfer_cb_t)(OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *req);
+ int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx,
+ OSSL_CMP_transfer_cb_t cb);
+ int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
+ void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx);
+
+ /* server authentication: */
+ int OSSL_CMP_CTX_set1_srvCert(OSSL_CMP_CTX *ctx, X509 *cert);
+ int OSSL_CMP_CTX_set1_expected_sender(OSSL_CMP_CTX *ctx,
+ const X509_NAME *name);
+ int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store);
+ X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx);
+ int OSSL_CMP_CTX_set1_untrusted(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs);
+ STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted(const OSSL_CMP_CTX *ctx);
+
+ /* client authentication: */
+ int OSSL_CMP_CTX_set1_cert(OSSL_CMP_CTX *ctx, X509 *cert);
+ int OSSL_CMP_CTX_build_cert_chain(OSSL_CMP_CTX *ctx, X509_STORE *own_trusted,
+ STACK_OF(X509) *candidates);
+ int OSSL_CMP_CTX_set1_pkey(OSSL_CMP_CTX *ctx, EVP_PKEY *pkey);
+ int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx,
+ const unsigned char *ref, int len);
+ int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx, const unsigned char *sec,
+ const int len);
+
+ /* CMP message header and extra certificates: */
+ int OSSL_CMP_CTX_set1_recipient(OSSL_CMP_CTX *ctx, const X509_NAME *name);
+ int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav);
+ int OSSL_CMP_CTX_reset_geninfo_ITAVs(OSSL_CMP_CTX *ctx);
+ int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx,
+ STACK_OF(X509) *extraCertsOut);
+
+ /* certificate template: */
+ int OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_CTX *ctx, int priv, EVP_PKEY *pkey);
+ EVP_PKEY *OSSL_CMP_CTX_get0_newPkey(const OSSL_CMP_CTX *ctx, int priv);
+ int OSSL_CMP_CTX_set1_issuer(OSSL_CMP_CTX *ctx, const X509_NAME *name);
+ int OSSL_CMP_CTX_set1_subjectName(OSSL_CMP_CTX *ctx, const X509_NAME *name);
+ int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx,
+ const GENERAL_NAME *name);
+ int OSSL_CMP_CTX_set0_reqExtensions(OSSL_CMP_CTX *ctx, X509_EXTENSIONS *exts);
+ int OSSL_CMP_CTX_reqExtensions_have_SAN(OSSL_CMP_CTX *ctx);
+ int OSSL_CMP_CTX_push0_policy(OSSL_CMP_CTX *ctx, POLICYINFO *pinfo);
+ int OSSL_CMP_CTX_set1_oldCert(OSSL_CMP_CTX *ctx, X509 *cert);
+ int OSSL_CMP_CTX_set1_p10CSR(OSSL_CMP_CTX *ctx, const X509_REQ *csr);
+
+ /* misc body contents: */
+ int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav);
+
+ /* certificate confirmation: */
+ typedef int (*OSSL_CMP_certConf_cb_t)(OSSL_CMP_CTX *ctx, X509 *cert,
+ int fail_info, const char **txt);
+ int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
+ const char **text);
+ int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_certConf_cb_t cb);
+ int OSSL_CMP_CTX_set_certConf_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
+ void *OSSL_CMP_CTX_get_certConf_cb_arg(const OSSL_CMP_CTX *ctx);
+
+ /* result fetching: */
+ int OSSL_CMP_CTX_get_status(const OSSL_CMP_CTX *ctx);
+ OSSL_CMP_PKIFREETEXT *OSSL_CMP_CTX_get0_statusString(const OSSL_CMP_CTX *ctx);
+ int OSSL_CMP_CTX_get_failInfoCode(const OSSL_CMP_CTX *ctx);
+
+ X509 *OSSL_CMP_CTX_get0_newCert(const OSSL_CMP_CTX *ctx);
+ STACK_OF(X509) *OSSL_CMP_CTX_get1_newChain(const OSSL_CMP_CTX *ctx);
+ STACK_OF(X509) *OSSL_CMP_CTX_get1_caPubs(const OSSL_CMP_CTX *ctx);
+ STACK_OF(X509) *OSSL_CMP_CTX_get1_extraCertsIn(const OSSL_CMP_CTX *ctx);
+
+ /* for testing and debugging purposes: */
+ int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx,
+ const ASN1_OCTET_STRING *id);
+ int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx,
+ const ASN1_OCTET_STRING *nonce);
+
+=head1 DESCRIPTION
+
+This is the context API for using CMP (Certificate Management Protocol) with
+OpenSSL.
+
+OSSL_CMP_CTX_new() allocates an B<OSSL_CMP_CTX> structure associated with
+the library context I<libctx> and property query string I<propq>,
+both of which may be NULL to select the defaults.
+It initializes the remaining fields to their default values - for instance,
+the logging verbosity is set to OSSL_CMP_LOG_INFO,
+the message timeout is set to 120 seconds,
+and the proof-of-possession method is set to OSSL_CRMF_POPO_SIGNATURE.
+
+OSSL_CMP_CTX_free() deallocates an OSSL_CMP_CTX structure.
+
+OSSL_CMP_CTX_reinit() prepares the given I<ctx> for a further transaction by
+clearing the internal CMP transaction (aka session) status, PKIStatusInfo,
+and any previous results (newCert, newChain, caPubs, and extraCertsIn)
+from the last executed transaction.
+It also clears any ITAVs that were added by OSSL_CMP_CTX_push0_genm_ITAV().
+All other field values (i.e., CMP options) are retained for potential re-use.
+
+OSSL_CMP_CTX_set_option() sets the given value for the given option
+(e.g., OSSL_CMP_OPT_IMPLICIT_CONFIRM) in the given OSSL_CMP_CTX structure.
+
+The following options can be set:
+
+=over 4
+
+=item B<OSSL_CMP_OPT_LOG_VERBOSITY>
+
+ The level of severity needed for actually outputting log messages
+ due to errors, warnings, general info, debugging, etc.
+ Default is OSSL_CMP_LOG_INFO. See also L<OSSL_CMP_log_open(3)>.
+
+=item B<OSSL_CMP_OPT_KEEP_ALIVE>
+
+ If the given value is 0 then HTTP connections are not kept open
+ after receiving a response, which is the default behavior for HTTP 1.0.
+ If the value is 1 or 2 then persistent connections are requested.
+ If the value is 2 then persistent connections are required,
+ i.e., in case the server does not grant them an error occurs.
+ The default value is 1: prefer to keep the connection open.
+
+=item B<OSSL_CMP_OPT_MSG_TIMEOUT>
+
+ Number of seconds a CMP request-response message round trip
+ is allowed to take before a timeout error is returned.
+ A value <= 0 means no limitation (waiting indefinitely).
+ Default is to use the B<OSSL_CMP_OPT_TOTAL_TIMEOUT> setting.
+
+=item B<OSSL_CMP_OPT_TOTAL_TIMEOUT>
+
+ Maximum total number of seconds a transaction may take,
+ including polling etc.
+ A value <= 0 means no limitation (waiting indefinitely).
+ Default is 0.
+
+=item B<OSSL_CMP_OPT_VALIDITY_DAYS>
+
+ Number of days new certificates are asked to be valid for.
+
+=item B<OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT>
+
+ Do not take default Subject Alternative Names
+ from the reference certificate.
+
+=item B<OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL>
+
+ Demand that the given Subject Alternative Names are flagged as critical.
+
+=item B<OSSL_CMP_OPT_POLICIES_CRITICAL>
+
+ Demand that the given policies are flagged as critical.
+
+=item B<OSSL_CMP_OPT_POPO_METHOD>
+
+ Select the proof of possession method to use. Possible values are:
+
+ OSSL_CRMF_POPO_NONE - ProofOfPossession field omitted
+ OSSL_CRMF_POPO_RAVERIFIED - assert that the RA has already
+ verified the PoPo
+ OSSL_CRMF_POPO_SIGNATURE - sign a value with private key,
+ which is the default.
+ OSSL_CRMF_POPO_KEYENC - decrypt the encrypted certificate
+ ("indirect method")
+
+ Note that a signature-based POPO can only be produced if a private key
+ is provided as the newPkey or client's pkey component of the CMP context.
+
+=item B<OSSL_CMP_OPT_DIGEST_ALGNID>
+
+ The NID of the digest algorithm to be used in RFC 4210's MSG_SIG_ALG
+ for signature-based message protection and Proof-of-Possession (POPO).
+ Default is SHA256.
+
+=item B<OSSL_CMP_OPT_OWF_ALGNID>
+ The NID of the digest algorithm to be used as one-way function (OWF)
+ in RFC 4210's MSG_MAC_ALG for PBM-based message protection.
+ Default is SHA256.
+
+=item B<OSSL_CMP_OPT_MAC_ALGNID>
+ The NID of the MAC algorithm to be used in RFC 4210's MSG_MAC_ALG
+ for PBM-based message protection.
+ Default is HMAC-SHA1 as per RFC 4210.
+
+=item B<OSSL_CMP_OPT_REVOCATION_REASON>
+
+ The reason code to be included in a Revocation Request (RR);
+ values: 0..10 (RFC 5210, 5.3.1) or -1 for none, which is the default.
+
+=item B<OSSL_CMP_OPT_IMPLICIT_CONFIRM>
+
+ Request server to enable implicit confirm mode, where the client
+ does not need to send confirmation upon receiving the
+ certificate. If the server does not enable implicit confirmation
+ in the return message, then confirmation is sent anyway.
+
+=item B<OSSL_CMP_OPT_DISABLE_CONFIRM>
+
+ Do not confirm enrolled certificates, to cope with broken servers
+ not supporting implicit confirmation correctly.
+B<WARNING:> This setting leads to unspecified behavior and it is meant
+exclusively to allow interoperability with server implementations violating
+RFC 4210.
+
+=item B<OSSL_CMP_OPT_UNPROTECTED_SEND>
+
+ Send messages without CMP-level protection.
+
+=item B<OSSL_CMP_OPT_UNPROTECTED_ERRORS>
+
+ Accept unprotected error responses which are either explicitly
+ unprotected or where protection verification failed. Applies to regular
+ error messages as well as certificate responses (IP/CP/KUP) and
+ revocation responses (RP) with rejection.
+B<WARNING:> This setting leads to unspecified behavior and it is meant
+exclusively to allow interoperability with server implementations violating
+RFC 4210.
+
+=item B<OSSL_CMP_OPT_IGNORE_KEYUSAGE>
+
+ Ignore key usage restrictions in the signer's certificate when
+ validating signature-based protection in received CMP messages.
+ Else, 'digitalSignature' must be allowed by CMP signer certificates.
+
+=item B<OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR>
+
+ Allow retrieving a trust anchor from extraCerts and using that
+ to validate the certificate chain of an IP message.
+
+=back
+
+OSSL_CMP_CTX_get_option() reads the current value of the given option
+(e.g., OSSL_CMP_OPT_IMPLICIT_CONFIRM) from the given OSSL_CMP_CTX structure.
+
+OSSL_CMP_CTX_set_log_cb() sets in I<ctx> the callback function I<cb>
+for handling error queue entries and logging messages.
+When I<cb> is NULL errors are printed to STDERR (if available, else ignored)
+any log messages are ignored.
+Alternatively, L<OSSL_CMP_log_open(3)> may be used to direct logging to STDOUT.
+
+OSSL_CMP_CTX_set_log_verbosity() is a macro setting the
+OSSL_CMP_OPT_LOG_VERBOSITY context option to the given level.
+
+OSSL_CMP_CTX_print_errors() outputs any entries in the OpenSSL error queue. It
+is similar to L<ERR_print_errors_cb(3)> but uses the CMP log callback function
+if set in the I<ctx> for uniformity with CMP logging if given. Otherwise it uses
+L<ERR_print_errors(3)> to print to STDERR (unless OPENSSL_NO_STDIO is defined).
+
+OSSL_CMP_CTX_set1_serverPath() sets the HTTP path of the CMP server on the host,
+also known as "CMP alias".
+The default is C</>.
+
+OSSL_CMP_CTX_set1_server() sets the given server I<address>
+(which may be a hostname or IP address or NULL) in the given I<ctx>.
+
+OSSL_CMP_CTX_set_serverPort() sets the port of the CMP server to connect to.
+If not used or the I<port> argument is 0
+the default port applies, which is 80 for HTTP and 443 for HTTPS.
+
+OSSL_CMP_CTX_set1_proxy() sets the HTTP proxy to be used for connecting to
+the given CMP server unless overruled by any "no_proxy" settings (see below).
+If TLS is not used this defaults to the value of
+the environment variable C<http_proxy> if set, else C<HTTP_PROXY>.
+Otherwise defaults to the value of C<https_proxy> if set, else C<HTTPS_PROXY>.
+An empty proxy string specifies not to use a proxy.
+Else the format is C<[http[s]://]address[:port][/path]>,
+where any path given is ignored.
+The default port number is 80, or 443 in case C<https:> is given.
+
+OSSL_CMP_CTX_set1_no_proxy() sets the list of server hostnames not to use
+an HTTP proxy for. The names may be separated by commas and/or whitespace.
+Defaults to the environment variable C<no_proxy> if set, else C<NO_PROXY>.
+
+OSSL_CMP_CTX_set_http_cb() sets the optional BIO connect/disconnect callback
+function, which has the prototype
+
+ typedef BIO *(*HTTP_bio_cb_t) (BIO *bio, void *ctx, int connect, int detail);
+
+The callback may modify the I<bio> provided by L<OSSL_CMP_MSG_http_perform(3)>,
+whereby it may make use of a custom defined argument I<ctx>
+stored in the OSSL_CMP_CTX by means of OSSL_CMP_CTX_set_http_cb_arg().
+During connection establishment, just after calling BIO_do_connect_retry(),
+the function is invoked with the I<connect> argument being 1 and the I<detail>
+argument being 1 if HTTPS is requested, i.e., SSL/TLS should be enabled. On
+disconnect I<connect> is 0 and I<detail> is 1 in case no error occurred, else 0.
+For instance, on connect the function may prepend a TLS BIO to implement HTTPS;
+after disconnect it may do some diagnostic output and/or specific cleanup.
+The function should return NULL to indicate failure.
+After disconnect the modified BIO will be deallocated using BIO_free_all().
+
+OSSL_CMP_CTX_set_http_cb_arg() sets an argument, respectively a pointer to
+a structure containing arguments,
+optionally to be used by the http connect/disconnect callback function.
+I<arg> is not consumed, and it must therefore explicitly be freed when not
+needed any more. I<arg> may be NULL to clear the entry.
+
+OSSL_CMP_CTX_get_http_cb_arg() gets the argument, respectively the pointer to a
+structure containing arguments, previously set by
+OSSL_CMP_CTX_set_http_cb_arg() or NULL if unset.
+
+OSSL_CMP_CTX_set_transfer_cb() sets the message transfer callback function,
+which has the type
+
+ typedef OSSL_CMP_MSG *(*OSSL_CMP_transfer_cb_t) (OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *req);
+
+Returns 1 on success, 0 on error.
+
+Default is NULL, which implies the use of L<OSSL_CMP_MSG_http_perform(3)>.
+The callback should send the CMP request message it obtains via the I<req>
+parameter and on success return the response, else it must return NULL.
+The transfer callback may make use of a custom defined argument stored in
+the ctx by means of OSSL_CMP_CTX_set_transfer_cb_arg(), which may be retrieved
+again through OSSL_CMP_CTX_get_transfer_cb_arg().
+
+OSSL_CMP_CTX_set_transfer_cb_arg() sets an argument, respectively a pointer to a
+structure containing arguments, optionally to be used by the transfer callback.
+I<arg> is not consumed, and it must therefore explicitly be freed when not
+needed any more. I<arg> may be NULL to clear the entry.
+
+OSSL_CMP_CTX_get_transfer_cb_arg() gets the argument, respectively the pointer
+to a structure containing arguments, previously set by
+OSSL_CMP_CTX_set_transfer_cb_arg() or NULL if unset.
+
+OSSL_CMP_CTX_set1_srvCert() sets the expected server cert in I<ctx> and trusts
+it directly (even if it is expired) when verifying signed response messages.
+May be used alternatively to OSSL_CMP_CTX_set0_trustedStore()
+to pin the accepted server.
+Any previously set value is freed.
+The I<cert> argument may be NULL to clear the entry.
+If set, the subject of the certificate is also used
+as default value for the recipient of CMP requests
+and as default value for the expected sender of CMP responses.
+
+OSSL_CMP_CTX_set1_expected_sender() sets the Distinguished Name (DN)
+expected in the sender field of CMP response messages.
+Defaults to the subject of the pinned server certificate, if any.
+This can be used to make sure that only a particular entity is accepted as
+CMP message signer, and attackers are not able to use arbitrary certificates
+of a trusted PKI hierarchy to fraudulently pose as CMP server.
+Note that this gives slightly more freedom than OSSL_CMP_CTX_set1_srvCert(),
+which pins the server to the holder of a particular certificate, while the
+expected sender name will continue to match after updates of the server cert.
+
+OSSL_CMP_CTX_set0_trustedStore() sets the certificate store of type X509_STORE
+containing trusted (root) CA certificates.
+The store may also hold CRLs and
+a certificate verification callback function used for CMP server authentication.
+Any store entry already set before is freed.
+When given a NULL parameter the entry is cleared.
+
+OSSL_CMP_CTX_get0_trustedStore() returns a pointer to the currently set
+certificate store containing trusted cert etc., or an empty store if unset.
+
+OSSL_CMP_CTX_set1_untrusted() sets up a list of non-trusted certificates
+of intermediate CAs that may be useful for path construction for the CMP client
+certificate, for the TLS client certificate (if any), when verifying
+the CMP server certificate, and when verifying newly enrolled certificates.
+The reference counts of those certificates handled successfully are increased.
+
+OSSL_CMP_CTX_get0_untrusted(OSSL_CMP_CTX *ctx) returns a pointer to the
+list of untrusted certs, which may be empty if unset.
+
+OSSL_CMP_CTX_set1_cert() sets the certificate related to the client's private key
+used for CMP message protection.
+Therefore the public key of this I<cert> must correspond to
+the private key set before or thereafter via OSSL_CMP_CTX_set1_pkey().
+When using signature-based protection of CMP request messages
+this CMP signer certificate will be included first in the extraCerts field.
+It serves as fallback reference certificate, see OSSL_CMP_CTX_set1_oldCert().
+The subject of this I<cert> will be used as the sender field of outgoing
+messages, while the subject of any cert set via OSSL_CMP_CTX_set1_oldCert()
+and any value set via OSSL_CMP_CTX_set1_subjectName() are used as fallback.
+
+The I<cert> argument may be NULL to clear the entry.
+
+OSSL_CMP_CTX_build_cert_chain() builds a certificate chain for the CMP signer
+certificate previously set in the I<ctx>. It adds the optional I<candidates>,
+a list of intermediate CA certs that may already constitute the targeted chain,
+to the untrusted certs that may already exist in the I<ctx>.
+Then the function uses this augumented set of certs for chain construction.
+If I<own_trusted> is NULL it builds the chain as far down as possible and
+ignores any verification errors. Else the CMP signer certificate must be
+verifiable where the chain reaches a trust anchor contained in I<own_trusted>.
+On success the function stores the resulting chain in I<ctx>
+for inclusion in the extraCerts field of signature-protected messages.
+Calling this function is optional; by default a chain construction
+is performed on demand that is equivalent to calling this function
+with the I<candidates> and I<own_trusted> arguments being NULL.
+
+OSSL_CMP_CTX_set1_pkey() sets the client's private key corresponding to the
+CMP signer certificate set via OSSL_CMP_CTX_set1_cert().
+This key is used create signature-based protection (protectionAlg = MSG_SIG_ALG)
+of outgoing messages
+unless a PBM secret has been set via OSSL_CMP_CTX_set1_secretValue().
+The I<pkey> argument may be NULL to clear the entry.
+
+OSSL_CMP_CTX_set1_secretValue() sets the byte string I<sec> with length I<len>
+as PBM secret in the given I<ctx> or clears it if the I<sec> argument is NULL.
+If present, this secret is used to create PBM-based protection of outgoing
+messages and to verify any PBM-based protection of incoming messages
+(protectionAlg = MSG_MAC_ALG). PBM stands for Password-Based MAC.
+PBM-based protection takes precedence over signature-based protection.
+
+OSSL_CMP_CTX_set1_referenceValue() sets the given referenceValue I<ref> with
+length I<len> in the given I<ctx> or clears it if the I<ref> argument is NULL.
+According to RFC 4210 section 5.1.1, if no value for the sender field in
+CMP message headers can be determined (i.e., no CMP signer certificate
+and no subject DN is set via OSSL_CMP_CTX_set1_subjectName()
+then the sender field will contain the NULL-DN
+and the senderKID field of the CMP message header must be set.
+When signature-based protection is used the senderKID will be set to
+the subjectKeyIdentifier of the CMP signer certificate as far as present.
+If not present or when PBM-based protection is used
+the I<ref> value is taken as the fallback value for the senderKID.
+
+OSSL_CMP_CTX_set1_recipient() sets the recipient name that will be used in the
+PKIHeader of CMP request messages, i.e. the X509 name of the (CA) server.
+
+The recipient field in the header of a CMP message is mandatory.
+If not given explicitly the recipient is determined in the following order:
+the subject of the CMP server certificate set using OSSL_CMP_CTX_set1_srvCert(),
+the value set using OSSL_CMP_CTX_set1_issuer(),
+the issuer of the certificate set using OSSL_CMP_CTX_set1_oldCert(),
+the issuer of the CMP signer certificate,
+as far as any of those is present, else the NULL-DN as last resort.
+
+OSSL_CMP_CTX_push0_geninfo_ITAV() adds I<itav> to the stack in the I<ctx> to be
+added to the GeneralInfo field of the CMP PKIMessage header of a request
+message sent with this context.
+
+OSSL_CMP_CTX_reset_geninfo_ITAVs()
+clears any ITAVs that were added by OSSL_CMP_CTX_push0_geninfo_ITAV().
+
+OSSL_CMP_CTX_set1_extraCertsOut() sets the stack of extraCerts that will be
+sent to remote.
+
+OSSL_CMP_CTX_set0_newPkey() can be used to explicitly set the given EVP_PKEY
+structure as the private or public key to be certified in the CMP context.
+The I<priv> parameter must be 0 if and only if the given key is a public key.
+
+OSSL_CMP_CTX_get0_newPkey() gives the key to use for certificate enrollment
+dependent on fields of the CMP context structure:
+the newPkey (which may be a private or public key) if present,
+else the public key in the p10CSR if present, else the client's private key.
+If the I<priv> parameter is not 0 and the selected key does not have a
+private component then NULL is returned.
+
+OSSL_CMP_CTX_set1_issuer() sets the name of the intended issuer that
+will be set in the CertTemplate, i.e., the X509 name of the CA server.
+
+OSSL_CMP_CTX_set1_subjectName() sets the subject DN that will be used in
+the CertTemplate structure when requesting a new cert. For Key Update Requests
+(KUR), it defaults to the subject DN of the reference certificate,
+see OSSL_CMP_CTX_set1_oldCert(). This default is used for Initialization
+Requests (IR) and Certification Requests (CR) only if no SANs are set.
+The I<subjectName> is also used as fallback for the sender field
+of outgoing CMP messages if no reference certificate is available.
+
+OSSL_CMP_CTX_push1_subjectAltName() adds the given X509 name to the list of
+alternate names on the certificate template request. This cannot be used if
+any Subject Alternative Name extension is set via
+OSSL_CMP_CTX_set0_reqExtensions().
+By default, unless B<OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT> has been set,
+the Subject Alternative Names are copied from the reference certificate,
+see OSSL_CMP_CTX_set1_oldCert().
+If set and the subject DN is not set with OSSL_CMP_CTX_set1_subjectName() then
+the certificate template of an IR and CR will not be filled with the default
+subject DN from the reference certificate.
+If a subject DN is desired it needs to be set explicitly with
+OSSL_CMP_CTX_set1_subjectName().
+
+OSSL_CMP_CTX_set0_reqExtensions() sets the X.509v3 extensions to be used in
+IR/CR/KUR.
+
+OSSL_CMP_CTX_reqExtensions_have_SAN() returns 1 if the context contains
+a Subject Alternative Name extension, else 0 or -1 on error.
+
+OSSL_CMP_CTX_push0_policy() adds the certificate policy info object
+to the X509_EXTENSIONS of the requested certificate template.
+
+OSSL_CMP_CTX_set1_oldCert() sets the old certificate to be updated in
+Key Update Requests (KUR) or to be revoked in Revocation Requests (RR).
+It must be given for RR, else it defaults to the CMP signer certificate.
+The I<reference certificate> determined in this way, if any, is also used for
+deriving default subject DN, public key, Subject Alternative Names, and the
+default issuer entry in the requested certificate template of IR/CR/KUR.
+The subject of the reference certificate is used as the sender field value
+in CMP message headers.
+Its issuer is used as default recipient in CMP message headers.
+
+OSSL_CMP_CTX_set1_p10CSR() sets the PKCS#10 CSR to use in P10CR messages.
+If such a CSR is provided, its subject, public key, and extension fields are
+also used as fallback values for the certificate template of IR/CR/KUR messages.
+
+OSSL_CMP_CTX_push0_genm_ITAV() adds I<itav> to the stack in the I<ctx> which
+will be the body of a General Message sent with this context.
+
+OSSL_CMP_certConf_cb() is the default certificate confirmation callback function.
+If the callback argument is not NULL it must point to a trust store.
+In this case the function checks that the newly enrolled certificate can be
+verified using this trust store and untrusted certificates from the I<ctx>,
+which have been augmented by the list of extraCerts received.
+If the callback argument is NULL the function tries building an approximate
+chain as far as possible using the same untrusted certificates from the I<ctx>,
+and if this fails it takes the received extraCerts as fallback.
+The resulting cert chain can be retrieved using OSSL_CMP_CTX_get1_newChain().
+
+OSSL_CMP_CTX_set_certConf_cb() sets the callback used for evaluating the newly
+enrolled certificate before the library sends, depending on its result,
+a positive or negative certConf message to the server. The callback has type
+
+ typedef int (*OSSL_CMP_certConf_cb_t) (OSSL_CMP_CTX *ctx, X509 *cert,
+ int fail_info, const char **txt);
+
+and should inspect the certificate it obtains via the I<cert> parameter and may
+overrule the pre-decision given in the I<fail_info> and I<*txt> parameters.
+If it accepts the certificate it must return 0, indicating success. Else it must
+return a bit field reflecting PKIFailureInfo with at least one failure bit and
+may set the I<*txt> output parameter to point to a string constant with more
+detail. The transfer callback may make use of a custom defined argument stored
+in the I<ctx> by means of OSSL_CMP_CTX_set_certConf_cb_arg(), which may be
+retrieved again through OSSL_CMP_CTX_get_certConf_cb_arg().
+Typically, the callback will check at least that the certificate can be verified
+using a set of trusted certificates.
+It also could compare the subject DN and other fields of the newly
+enrolled certificate with the certificate template of the request.
+
+OSSL_CMP_CTX_set_certConf_cb_arg() sets an argument, respectively a pointer to a
+structure containing arguments, optionally to be used by the certConf callback.
+I<arg> is not consumed, and it must therefore explicitly be freed when not
+needed any more. I<arg> may be NULL to clear the entry.
+
+OSSL_CMP_CTX_get_certConf_cb_arg() gets the argument, respectively the pointer
+to a structure containing arguments, previously set by
+OSSL_CMP_CTX_set_certConf_cb_arg(), or NULL if unset.
+
+OSSL_CMP_CTX_get_status() returns for client contexts the PKIstatus from
+the last received CertRepMessage or Revocation Response or error message:
+=item B<OSSL_CMP_PKISTATUS_accepted> on sucessful receipt of a GENP message:
+
+=over 4
+
+=item B<OSSL_CMP_PKISTATUS_request>
+
+if an IR/CR/KUR/RR/GENM request message could not be produced,
+
+=item B<OSSL_CMP_PKISTATUS_trans>
+
+on a transmission error or transaction error for this type of request, and
+
+=item B<OSSL_CMP_PKISTATUS_unspecified>
+
+if no such request was attempted or OSSL_CMP_CTX_reinit() has been called.
+
+=back
+
+For server contexts it returns
+B<OSSL_CMP_PKISTATUS_trans> if a transaction is open,
+otherwise B<OSSL_CMP_PKISTATUS_unspecified>.
+
+OSSL_CMP_CTX_get0_statusString() returns the statusString from the last received
+CertRepMessage or Revocation Response or error message, or NULL if unset.
+
+OSSL_CMP_CTX_get_failInfoCode() returns the error code from the failInfo field
+of the last received CertRepMessage or Revocation Response or error message,
+or -1 if no such response was received or OSSL_CMP_CTX_reinit() has been called.
+This is a bit field and the flags for it are specified in the header file
+F<< <openssl/cmp.h> >>.
+The flags start with OSSL_CMP_CTX_FAILINFO, for example:
+OSSL_CMP_CTX_FAILINFO_badAlg. Returns -1 if the failInfoCode field is unset.
+
+OSSL_CMP_CTX_get0_newCert() returns the pointer to the newly obtained
+certificate in case it is available, else NULL.
+
+OSSL_CMP_CTX_get1_newChain() returns a pointer to a duplicate of the stack of
+X.509 certificates computed by OSSL_CMP_certConf_cb() (if this function has
+been called) on the last received certificate response message IP/CP/KUP.
+
+OSSL_CMP_CTX_get1_caPubs() returns a pointer to a duplicate of the list of
+X.509 certificates in the caPubs field of the last received certificate
+response message (of type IP, CP, or KUP),
+or an empty stack if no caPubs have been received in the current transaction.
+
+OSSL_CMP_CTX_get1_extraCertsIn() returns a pointer to a duplicate of the list
+of X.509 certificates contained in the extraCerts field of the last received
+response message (except for pollRep and PKIConf), or
+an empty stack if no extraCerts have been received in the current transaction.
+
+OSSL_CMP_CTX_set1_transactionID() sets the given transaction ID in the given
+OSSL_CMP_CTX structure.
+
+OSSL_CMP_CTX_set1_senderNonce() stores the last sent sender I<nonce> in
+the I<ctx>. This will be used to validate the recipNonce in incoming messages.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+OSSL_CMP_CTX_free() and OSSL_CMP_CTX_print_errors() do not return anything.
+
+OSSL_CMP_CTX_new(),
+OSSL_CMP_CTX_get_http_cb_arg(),
+OSSL_CMP_CTX_get_transfer_cb_arg(),
+OSSL_CMP_CTX_get0_trustedStore(),
+OSSL_CMP_CTX_get0_untrusted(),
+OSSL_CMP_CTX_get0_newPkey(),
+OSSL_CMP_CTX_get_certConf_cb_arg(),
+OSSL_CMP_CTX_get0_statusString(),
+OSSL_CMP_CTX_get0_newCert(),
+OSSL_CMP_CTX_get0_newChain(),
+OSSL_CMP_CTX_get1_caPubs(), and
+OSSL_CMP_CTX_get1_extraCertsIn()
+return the intended pointer value as described above or NULL on error.
+
+OSSL_CMP_CTX_get_option(),
+OSSL_CMP_CTX_reqExtensions_have_SAN(),
+OSSL_CMP_CTX_get_status(), and
+OSSL_CMP_CTX_get_failInfoCode()
+return the intended value as described above or -1 on error.
+
+OSSL_CMP_certConf_cb() returns I<fail_info> if it is not equal to 0,
+else 0 on successful validation,
+or else a bit field with the B<OSSL_CMP_PKIFAILUREINFO_incorrectData> bit set.
+
+All other functions, including OSSL_CMP_CTX_reinit()
+and OSSL_CMP_CTX_reset_geninfo_ITAVs(),
+return 1 on success, 0 on error.
+
+=head1 EXAMPLES
+
+The following code omits error handling.
+
+Set up a CMP client context for sending requests and verifying responses:
+
+ cmp_ctx = OSSL_CMP_CTX_new();
+ OSSL_CMP_CTX_set1_server(cmp_ctx, name_or_address);
+ OSSL_CMP_CTX_set1_serverPort(cmp_ctx, port_string);
+ OSSL_CMP_CTX_set1_serverPath(cmp_ctx, path_or_alias);
+ OSSL_CMP_CTX_set0_trustedStore(cmp_ctx, ts);
+
+Set up client credentials for password-based protection (PBM):
+
+ OSSL_CMP_CTX_set1_referenceValue(cmp_ctx, ref, ref_len);
+ OSSL_CMP_CTX_set1_secretValue(cmp_ctx, sec, sec_len);
+
+Set up the details for certificate requests:
+
+ OSSL_CMP_CTX_set1_subjectName(cmp_ctx, name);
+ OSSL_CMP_CTX_set0_newPkey(cmp_ctx, 1, initialKey);
+
+Perform an Initialization Request transaction:
+
+ initialCert = OSSL_CMP_exec_IR_ses(cmp_ctx);
+
+Reset the transaction state of the CMP context and the credentials:
+
+ OSSL_CMP_CTX_reinit(cmp_ctx);
+ OSSL_CMP_CTX_set1_referenceValue(cmp_ctx, NULL, 0);
+ OSSL_CMP_CTX_set1_secretValue(cmp_ctx, NULL, 0);
+
+Perform a Certification Request transaction, making use of the new credentials:
+
+ OSSL_CMP_CTX_set1_cert(cmp_ctx, initialCert);
+ OSSL_CMP_CTX_set1_pkey(cmp_ctx, initialKey);
+ OSSL_CMP_CTX_set0_newPkey(cmp_ctx, 1, curentKey);
+ currentCert = OSSL_CMP_exec_CR_ses(cmp_ctx);
+
+Perform a Key Update Request, signed using the cert (and key) to be updated:
+
+ OSSL_CMP_CTX_reinit(cmp_ctx);
+ OSSL_CMP_CTX_set1_cert(cmp_ctx, currentCert);
+ OSSL_CMP_CTX_set1_pkey(cmp_ctx, currentKey);
+ OSSL_CMP_CTX_set0_newPkey(cmp_ctx, 1, updatedKey);
+ currentCert = OSSL_CMP_exec_KUR_ses(cmp_ctx);
+ currentKey = updatedKey;
+
+Perform a General Message transaction including, as an example,
+the id-it-signKeyPairTypes OID and prints info on the General Response contents:
+
+ OSSL_CMP_CTX_reinit(cmp_ctx);
+
+ ASN1_OBJECT *type = OBJ_txt2obj("1.3.6.1.5.5.7.4.2", 1);
+ OSSL_CMP_ITAV *itav = OSSL_CMP_ITAV_create(type, NULL);
+ OSSL_CMP_CTX_push0_genm_ITAV(cmp_ctx, itav);
+
+ STACK_OF(OSSL_CMP_ITAV) *itavs;
+ itavs = OSSL_CMP_exec_GENM_ses(cmp_ctx);
+ print_itavs(itavs);
+ sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free);
+
+=head1 SEE ALSO
+
+L<OSSL_CMP_exec_IR_ses(3)>, L<OSSL_CMP_exec_CR_ses(3)>,
+L<OSSL_CMP_exec_KUR_ses(3)>, L<OSSL_CMP_exec_GENM_ses(3)>,
+L<OSSL_CMP_exec_certreq(3)>, L<OSSL_CMP_MSG_http_perform(3)>,
+L<ERR_print_errors_cb(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+OSSL_CMP_CTX_reset_geninfo_ITAVs() was added in OpenSSL 3.0.8.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CMP_HDR_get0_transactionID.pod b/doc/man3/OSSL_CMP_HDR_get0_transactionID.pod
new file mode 100644
index 000000000000..36bdf1917f39
--- /dev/null
+++ b/doc/man3/OSSL_CMP_HDR_get0_transactionID.pod
@@ -0,0 +1,47 @@
+=pod
+
+=head1 NAME
+
+OSSL_CMP_HDR_get0_transactionID,
+OSSL_CMP_HDR_get0_recipNonce
+- functions manipulating CMP message headers
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+
+ ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_transactionID(const
+ OSSL_CMP_PKIHEADER *hdr);
+ ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const
+ OSSL_CMP_PKIHEADER *hdr);
+
+=head1 DESCRIPTION
+
+OSSL_CMP_HDR_get0_transactionID returns the transaction ID of the given
+PKIHeader.
+
+OSSL_CMP_HDR_get0_recipNonce returns the recipient nonce of the given PKIHeader.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210.
+
+=head1 RETURN VALUES
+
+The functions return the intended pointer value as described above
+or NULL if the respective entry does not exist and on error.
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CMP_ITAV_set0.pod b/doc/man3/OSSL_CMP_ITAV_set0.pod
new file mode 100644
index 000000000000..593af73fcdd5
--- /dev/null
+++ b/doc/man3/OSSL_CMP_ITAV_set0.pod
@@ -0,0 +1,111 @@
+=pod
+
+=head1 NAME
+
+OSSL_CMP_ITAV_create,
+OSSL_CMP_ITAV_set0,
+OSSL_CMP_ITAV_get0_type,
+OSSL_CMP_ITAV_get0_value,
+OSSL_CMP_ITAV_push0_stack_item
+- OSSL_CMP_ITAV utility functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+ OSSL_CMP_ITAV *OSSL_CMP_ITAV_create(ASN1_OBJECT *type, ASN1_TYPE *value);
+ void OSSL_CMP_ITAV_set0(OSSL_CMP_ITAV *itav, ASN1_OBJECT *type,
+ ASN1_TYPE *value);
+ ASN1_OBJECT *OSSL_CMP_ITAV_get0_type(const OSSL_CMP_ITAV *itav);
+ ASN1_TYPE *OSSL_CMP_ITAV_get0_value(const OSSL_CMP_ITAV *itav);
+
+ int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p,
+ OSSL_CMP_ITAV *itav);
+
+=head1 DESCRIPTION
+
+Certificate Management Protocol (CMP, RFC 4210) extension to OpenSSL
+
+ITAV is short for InfoTypeAndValue. This type is defined in RFC 4210
+section 5.3.19 and Appendix F. It is used at various places in CMP messages,
+e.g., in the generalInfo PKIHeader field, to hold a key-value pair.
+
+OSSL_CMP_ITAV_create() creates a new B<OSSL_CMP_ITAV> structure and fills it in.
+It combines OSSL_CMP_ITAV_new() and OSSL_CMP_ITAV_set0().
+
+OSSL_CMP_ITAV_set0() sets the I<itav> with an infoType of I<type> and an
+infoValue of I<value>. This function uses the pointers I<type> and I<value>
+internally, so they must B<not> be freed up after the call.
+
+OSSL_CMP_ITAV_get0_type() returns a direct pointer to the infoType in the
+I<itav>.
+
+OSSL_CMP_ITAV_get0_value() returns a direct pointer to the infoValue in
+the I<itav> as generic B<ASN1_TYPE> pointer.
+
+OSSL_CMP_ITAV_push0_stack_item() pushes I<itav> to the stack pointed to
+by I<*itav_sk_p>. It creates a new stack if I<*itav_sk_p> points to NULL.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+OSSL_CMP_ITAV_create() returns a pointer to the ITAV structure on success,
+or NULL on error.
+
+OSSL_CMP_ITAV_set0() does not return a value.
+
+OSSL_CMP_ITAV_get0_type() and OSSL_CMP_ITAV_get0_value()
+return the respective pointer or NULL if their input is NULL.
+
+OSSL_CMP_ITAV_push0_stack_item() returns 1 on success, 0 on error.
+
+=head1 EXAMPLES
+
+The following code creates and sets a structure representing a generic
+InfoTypeAndValue sequence, using an OID created from text as type, and an
+integer as value. Afterwards, it is pushed to the B<OSSL_CMP_CTX> to be later
+included in the requests' PKIHeader's genInfo field.
+
+ ASN1_OBJECT *type = OBJ_txt2obj("1.2.3.4.5", 1);
+ if (type == NULL) ...
+
+ ASN1_INTEGER *asn1int = ASN1_INTEGER_new();
+ if (asn1int == NULL || !ASN1_INTEGER_set(asn1int, 12345)) ...
+
+ ASN1_TYPE *val = ASN1_TYPE_new();
+ if (val == NULL) ...
+ ASN1_TYPE_set(val, V_ASN1_INTEGER, asn1int);
+
+ OSSL_CMP_ITAV *itav = OSSL_CMP_ITAV_create(type, val);
+ if (itav == NULL) ...
+
+ OSSL_CMP_CTX *ctx = OSSL_CMP_CTX_new();
+ if (ctx == NULL || !OSSL_CMP_CTX_geninfo_push0_ITAV(ctx, itav)) {
+ OSSL_CMP_ITAV_free(itav); /* also frees type and val */
+ goto err;
+ }
+
+ ...
+
+ OSSL_CMP_CTX_free(ctx); /* also frees itav */
+
+=head1 SEE ALSO
+
+L<OSSL_CMP_CTX_new(3)>, L<OSSL_CMP_CTX_free(3)>, L<ASN1_TYPE_set(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CMP_MSG_get0_header.pod b/doc/man3/OSSL_CMP_MSG_get0_header.pod
new file mode 100644
index 000000000000..c3297a3577ac
--- /dev/null
+++ b/doc/man3/OSSL_CMP_MSG_get0_header.pod
@@ -0,0 +1,147 @@
+=pod
+
+=head1 NAME
+
+OSSL_CMP_MSG_get0_header,
+OSSL_CMP_MSG_get_bodytype,
+OSSL_CMP_MSG_update_transactionID,
+OSSL_CMP_CTX_setup_CRM,
+OSSL_CMP_MSG_read,
+OSSL_CMP_MSG_write,
+d2i_OSSL_CMP_MSG_bio,
+i2d_OSSL_CMP_MSG_bio
+- function(s) manipulating CMP messages
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+
+ OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg);
+ int OSSL_CMP_MSG_get_bodytype(const OSSL_CMP_MSG *msg);
+ int OSSL_CMP_MSG_update_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
+ OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid);
+ OSSL_CMP_MSG *OSSL_CMP_MSG_read(const char *file, OSSL_LIB_CTX *libctx, const char *propq);
+ int OSSL_CMP_MSG_write(const char *file, const OSSL_CMP_MSG *msg);
+ OSSL_CMP_MSG *d2i_OSSL_CMP_MSG_bio(BIO *bio, OSSL_CMP_MSG **msg);
+ int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg);
+
+=head1 DESCRIPTION
+
+OSSL_CMP_MSG_get0_header() returns the header of the given CMP message.
+
+OSSL_CMP_MSG_get_bodytype() returns the body type of the given CMP message.
+
+OSSL_CMP_MSG_update_transactionID() updates the transactionID field
+in the header of the given message according to the CMP_CTX.
+This requires re-protecting the message (if it was protected).
+
+OSSL_CMP_CTX_setup_CRM() creates a CRMF certificate request message
+from various information provided in the CMP context argument I<ctx>
+for inclusion in a CMP request message based on details contained in I<ctx>.
+The I<rid> argument defines the request identifier to use, which typically is 0.
+
+The subject DN included in the certificate template is
+the first available value of these:
+
+=over 4
+
+=item any subject name in I<ctx> set via L<OSSL_CMP_CTX_set1_subjectName(3)> -
+if it is the NULL-DN (i.e., any empty sequence of RDNs), no subject is included,
+
+=item the subject field of any PKCS#10 CSR set in I<ctx>
+via L<OSSL_CMP_CTX_set1_p10CSR(3)>,
+
+=item the subject field of any reference certificate given in I<ctx>
+(see L<OSSL_CMP_CTX_set1_oldCert(3)>), but only if I<for_KUR> is nonzero
+or the I<ctx> does not include a Subject Alternative Name.
+
+=back
+
+The public key included is the first available value of these:
+
+=over 4
+
+=item the public key derived from any key set via L<OSSL_CMP_CTX_set0_newPkey(3)>,
+
+=item the public key of any PKCS#10 CSR given in I<ctx>,
+
+=item the public key of any reference certificate given in I<ctx>,
+
+=item the public key derived from any client's private key
+set via L<OSSL_CMP_CTX_set1_pkey(3)>.
+
+=back
+
+The set of X.509 extensions to include is computed as follows.
+If a PKCS#10 CSR is present in I<ctx>, default extensions are taken from there,
+otherwise the empty set is taken as the initial value.
+If there is a reference certificate in I<ctx> and contains Subject Alternative
+Names (SANs) and B<OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT> is not set,
+these override any SANs from the PKCS#10 CSR.
+The extensions are further augmented or overridden by any extensions with the
+same OIDs included in the I<ctx> via L<OSSL_CMP_CTX_set0_reqExtensions(3)>.
+The SANs are further overridden by any SANs included in I<ctx> via
+L<OSSL_CMP_CTX_push1_subjectAltName(3)>.
+Finally, policies are overridden by any policies included in I<ctx> via
+L<OSSL_CMP_CTX_push0_policy(3)>.
+
+OSSL_CMP_CTX_setup_CRM() also sets the sets the regToken control B<oldCertID>
+for KUR messages using the issuer name and serial number of the reference
+certificate, if present.
+
+OSSL_CMP_MSG_read() loads a DER-encoded OSSL_CMP_MSG from I<file>.
+
+OSSL_CMP_MSG_write() stores the given OSSL_CMP_MSG to I<file> in DER encoding.
+
+d2i_OSSL_CMP_MSG_bio() parses an ASN.1-encoded OSSL_CMP_MSG from the BIO I<bio>.
+It assigns a pointer to the new structure to I<*msg> if I<msg> is not NULL.
+
+i2d_OSSL_CMP_MSG_bio() writes the OSSL_CMP_MSG I<msg> in ASN.1 encoding
+to BIO I<bio>.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210.
+
+=head1 RETURN VALUES
+
+OSSL_CMP_MSG_get0_header() returns the intended pointer value as described above
+or NULL if the respective entry does not exist and on error.
+
+OSSL_CMP_MSG_get_bodytype() returns the body type or -1 on error.
+
+OSSL_CMP_CTX_setup_CRM() returns a pointer to a B<OSSL_CRMF_MSG> on success,
+NULL on error.
+
+d2i_OSSL_CMP_MSG_bio() returns the parsed message or NULL on error.
+
+OSSL_CMP_MSG_read() and d2i_OSSL_CMP_MSG_bio()
+return the parsed CMP message or NULL on error.
+
+OSSL_CMP_MSG_write() returns the number of bytes successfully encoded or a
+negative value if an error occurs.
+
+i2d_OSSL_CMP_MSG_bio() and OSSL_CMP_MSG_update_transactionID() return 1 on
+success, 0 on error.
+
+=head1 SEE ALSO
+
+L<OSSL_CMP_CTX_set1_subjectName(3)>, L<OSSL_CMP_CTX_set1_p10CSR(3)>,
+L<OSSL_CMP_CTX_set1_oldCert(3)>, L<OSSL_CMP_CTX_set0_newPkey(3)>,
+L<OSSL_CMP_CTX_set1_pkey(3)>, L<OSSL_CMP_CTX_set0_reqExtensions(3)>,
+L<OSSL_CMP_CTX_push1_subjectAltName(3)>, L<OSSL_CMP_CTX_push0_policy(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CMP_MSG_http_perform.pod b/doc/man3/OSSL_CMP_MSG_http_perform.pod
new file mode 100644
index 000000000000..d675da91143d
--- /dev/null
+++ b/doc/man3/OSSL_CMP_MSG_http_perform.pod
@@ -0,0 +1,60 @@
+=pod
+
+=head1 NAME
+
+OSSL_CMP_MSG_http_perform
+- client-side HTTP(S) transfer of a CMP request-response pair
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+
+ OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *req);
+
+=head1 DESCRIPTION
+
+OSSL_CMP_MSG_http_perform() sends the given PKIMessage I<req>
+to the CMP server specified in I<ctx> via L<OSSL_CMP_CTX_set1_server(3)>
+and optionally L<OSSL_CMP_CTX_set_serverPort(3)>, using
+any "CMP alias" optionally specified via L<OSSL_CMP_CTX_set1_serverPath(3)>.
+The default port is 80 for HTTP and 443 for HTTPS; the default path is "/".
+On success the function returns the server's response PKIMessage.
+
+The function makes use of any HTTP callback function
+set via L<OSSL_CMP_CTX_set_http_cb(3)>.
+It respects any timeout value set via L<OSSL_CMP_CTX_set_option(3)>
+with an B<OSSL_CMP_OPT_MSG_TIMEOUT> argument.
+It also respects any HTTP(S) proxy options set via L<OSSL_CMP_CTX_set1_proxy(3)>
+and L<OSSL_CMP_CTX_set1_no_proxy(3)> and the respective environment variables.
+Proxying plain HTTP is supported directly,
+while using a proxy for HTTPS connections requires a suitable callback function
+such as L<OSSL_HTTP_proxy_connect(3)>.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210.
+HTTP transfer for CMP is defined in RFC 6712.
+
+=head1 RETURN VALUES
+
+OSSL_CMP_MSG_http_perform() returns a CMP message on success, else NULL.
+
+=head1 SEE ALSO
+
+L<OSSL_CMP_CTX_new(3)>, L<OSSL_HTTP_proxy_connect(3)>.
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CMP_SRV_CTX_new.pod b/doc/man3/OSSL_CMP_SRV_CTX_new.pod
new file mode 100644
index 000000000000..d7f1a2e4dba7
--- /dev/null
+++ b/doc/man3/OSSL_CMP_SRV_CTX_new.pod
@@ -0,0 +1,168 @@
+=pod
+
+=head1 NAME
+
+OSSL_CMP_SRV_process_request,
+OSSL_CMP_CTX_server_perform,
+OSSL_CMP_SRV_CTX_new,
+OSSL_CMP_SRV_CTX_free,
+OSSL_CMP_SRV_cert_request_cb_t,
+OSSL_CMP_SRV_rr_cb_t,
+OSSL_CMP_SRV_certConf_cb_t,
+OSSL_CMP_SRV_genm_cb_t,
+OSSL_CMP_SRV_error_cb_t,
+OSSL_CMP_SRV_pollReq_cb_t,
+OSSL_CMP_SRV_CTX_init,
+OSSL_CMP_SRV_CTX_get0_cmp_ctx,
+OSSL_CMP_SRV_CTX_get0_custom_ctx,
+OSSL_CMP_SRV_CTX_set_send_unprotected_errors,
+OSSL_CMP_SRV_CTX_set_accept_unprotected,
+OSSL_CMP_SRV_CTX_set_accept_raverified,
+OSSL_CMP_SRV_CTX_set_grant_implicit_confirm
+- generic functions to set up and control a CMP server
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+
+ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req);
+ OSSL_CMP_MSG *OSSL_CMP_CTX_server_perform(OSSL_CMP_CTX *client_ctx,
+ const OSSL_CMP_MSG *req);
+ OSSL_CMP_SRV_CTX *OSSL_CMP_SRV_CTX_new(OSSL_LIB_CTX *libctx, const char *propq);
+ void OSSL_CMP_SRV_CTX_free(OSSL_CMP_SRV_CTX *srv_ctx);
+
+ typedef OSSL_CMP_PKISI *(*OSSL_CMP_SRV_cert_request_cb_t)(
+ OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req,
+ int certReqId,
+ const OSSL_CRMF_MSG *crm,
+ const X509_REQ *p10cr,
+ X509 **certOut,
+ STACK_OF(X509) **chainOut,
+ STACK_OF(X509) **caPubs);
+ typedef OSSL_CMP_PKISI *(*OSSL_CMP_SRV_rr_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req,
+ const X509_NAME *issuer,
+ const ASN1_INTEGER *serial);
+ typedef int (*OSSL_CMP_SRV_genm_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req,
+ STACK_OF(OSSL_CMP_ITAV) *in,
+ STACK_OF(OSSL_CMP_ITAV) **out);
+ typedef void (*OSSL_CMP_SRV_error_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req,
+ const OSSL_CMP_PKISI *statusInfo,
+ const ASN1_INTEGER *errorCode,
+ const OSSL_CMP_PKIFREETEXT *errorDetails);
+ typedef int (*OSSL_CMP_SRV_certConf_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req,
+ int certReqId,
+ const ASN1_OCTET_STRING *certHash,
+ const OSSL_CMP_PKISI *si);
+ typedef int (*OSSL_CMP_SRV_pollReq_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req,
+ int certReqId,
+ OSSL_CMP_MSG **certReq,
+ int64_t *check_after);
+ int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx,
+ OSSL_CMP_SRV_cert_request_cb_t process_cert_request,
+ OSSL_CMP_SRV_rr_cb_t process_rr,
+ OSSL_CMP_SRV_genm_cb_t process_genm,
+ OSSL_CMP_SRV_error_cb_t process_error,
+ OSSL_CMP_SRV_certConf_cb_t process_certConf,
+ OSSL_CMP_SRV_pollReq_cb_t process_pollReq);
+
+ OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx);
+ void *OSSL_CMP_SRV_CTX_get0_custom_ctx(const OSSL_CMP_SRV_CTX *srv_ctx);
+
+ int OSSL_CMP_SRV_CTX_set_send_unprotected_errors(OSSL_CMP_SRV_CTX *srv_ctx,
+ int val);
+ int OSSL_CMP_SRV_CTX_set_accept_unprotected(OSSL_CMP_SRV_CTX *srv_ctx, int val);
+ int OSSL_CMP_SRV_CTX_set_accept_raverified(OSSL_CMP_SRV_CTX *srv_ctx, int val);
+ int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx,
+ int val);
+
+=head1 DESCRIPTION
+
+OSSL_CMP_SRV_process_request() implements the generic aspects of a CMP server.
+Its arguments are the B<OSSL_CMP_SRV_CTX> I<srv_ctx> and the CMP request message
+I<req>. It does the typical generic checks on I<req>, calls
+the respective callback function (if present) for more specific processing,
+and then assembles a result message, which may be a CMP error message.
+If after return of the function the expression
+I<OSSL_CMP_CTX_get_status(OSSL_CMP_SRV_CTX_get0_cmp_ctx(srv_ctx))> yields -1
+then the function has closed the current transaction,
+which may be due to normal successful end of the transaction or due to an error.
+
+OSSL_CMP_CTX_server_perform() is an interface to
+OSSL_CMP_SRV_process_request() that can be used by a CMP client
+in the same way as L<OSSL_CMP_MSG_http_perform(3)>.
+The B<OSSL_CMP_SRV_CTX> must be set as I<transfer_cb_arg> of I<client_ctx>.
+
+OSSL_CMP_SRV_CTX_new() creates and initializes an B<OSSL_CMP_SRV_CTX> structure
+associated with the library context I<libctx> and property query string
+I<propq>, both of which may be NULL to select the defaults.
+
+OSSL_CMP_SRV_CTX_free() deletes the given I<srv_ctx>.
+
+OSSL_CMP_SRV_CTX_init() sets in the given I<srv_ctx> a custom server context
+pointer as well as callback functions performing the specific processing of CMP
+certificate requests, revocation requests, certificate confirmation requests,
+general messages, error messages, and poll requests.
+All arguments except I<srv_ctx> may be NULL.
+If a callback for some message type is not given this means that the respective
+type of CMP message is not supported by the server.
+
+OSSL_CMP_SRV_CTX_get0_cmp_ctx() returns the B<OSSL_CMP_CTX> from the I<srv_ctx>.
+
+OSSL_CMP_SRV_CTX_get0_custom_ctx() returns the custom server context from
+I<srv_ctx> that has been set using OSSL_CMP_SRV_CTX_init().
+
+OSSL_CMP_SRV_CTX_set_send_unprotected_errors() enables sending error messages
+and other forms of negative responses unprotected.
+
+OSSL_CMP_SRV_CTX_set_accept_unprotected() enables acceptance of requests
+without protection of with invalid protection.
+
+OSSL_CMP_SRV_CTX_set_accept_raverified() enables acceptance of ir/cr/kur
+messages with POPO 'RAVerified'.
+
+OSSL_CMP_SRV_CTX_set_grant_implicit_confirm() enables granting implicit
+confirmation of newly enrolled certificates if requested.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+So far the CMP server implementation is limited to one request per CMP message
+(and consequently to at most one response component per CMP message).
+
+=head1 RETURN VALUES
+
+OSSL_CMP_SRV_CTX_new() returns a B<OSSL_CMP_SRV_CTX> structure on success,
+NULL on error.
+
+OSSL_CMP_SRV_CTX_free() does not return a value.
+
+OSSL_CMP_SRV_CTX_get0_cmp_ctx() returns a B<OSSL_CMP_CTX> structure on success,
+NULL on error.
+
+OSSL_CMP_SRV_CTX_get0_custom_ctx() returns the custom server context
+that has been set using OSSL_CMP_SRV_CTX_init().
+
+All other functions return 1 on success, 0 on error.
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CMP_STATUSINFO_new.pod b/doc/man3/OSSL_CMP_STATUSINFO_new.pod
new file mode 100644
index 000000000000..9c5ce577c734
--- /dev/null
+++ b/doc/man3/OSSL_CMP_STATUSINFO_new.pod
@@ -0,0 +1,66 @@
+=pod
+
+=head1 NAME
+
+OSSL_CMP_STATUSINFO_new,
+OSSL_CMP_snprint_PKIStatusInfo,
+OSSL_CMP_CTX_snprint_PKIStatus
+- function(s) for managing the CMP PKIStatus
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+
+ OSSL_CMP_PKISI *OSSL_CMP_STATUSINFO_new(int status, int fail_info,
+ const char *text);
+ char *OSSL_CMP_snprint_PKIStatusInfo(const OSSL_CMP_PKISI *statusInfo,
+ char *buf, size_t bufsize);
+ char *OSSL_CMP_CTX_snprint_PKIStatus(const OSSL_CMP_CTX *ctx, char *buf,
+ size_t bufsize);
+
+=head1 DESCRIPTION
+
+This is the PKIStatus API for using CMP (Certificate Management Protocol) with
+OpenSSL.
+
+OSSL_CMP_STATUSINFO_new() creates a new PKIStatusInfo structure
+and fills in the given values.
+It sets the status field to I<status>,
+copies I<text> (unless it is NULL) to statusString,
+and interprets I<fail_info> as bit pattern for the failInfo field.
+
+OSSL_CMP_snprint_PKIStatusInfo() places a human-readable string
+representing the given statusInfo
+in the given buffer, with the given maximal length.
+
+OSSL_CMP_CTX_snprint_PKIStatus() places a human-readable string
+representing the PKIStatusInfo components of the CMP context I<ctx>
+in the given buffer, with the given maximal length.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+OSSL_CMP_STATUSINFO_new()
+returns a pointer to the structure on success, or NULL on error.
+
+OSSL_CMP_snprint_PKIStatusInfo() and
+OSSL_CMP_CTX_snprint_PKIStatus()
+return a copy of the buffer pointer containing the string or NULL on error.
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CMP_exec_certreq.pod b/doc/man3/OSSL_CMP_exec_certreq.pod
new file mode 100644
index 000000000000..b0d81c7c41a9
--- /dev/null
+++ b/doc/man3/OSSL_CMP_exec_certreq.pod
@@ -0,0 +1,173 @@
+=pod
+
+=head1 NAME
+
+OSSL_CMP_exec_certreq,
+OSSL_CMP_exec_IR_ses,
+OSSL_CMP_exec_CR_ses,
+OSSL_CMP_exec_P10CR_ses,
+OSSL_CMP_exec_KUR_ses,
+OSSL_CMP_IR,
+OSSL_CMP_CR,
+OSSL_CMP_P10CR,
+OSSL_CMP_KUR,
+OSSL_CMP_try_certreq,
+OSSL_CMP_exec_RR_ses,
+OSSL_CMP_exec_GENM_ses
+- functions implementing CMP client transactions
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+
+ X509 *OSSL_CMP_exec_certreq(OSSL_CMP_CTX *ctx, int req_type,
+ const OSSL_CRMF_MSG *crm);
+ X509 *OSSL_CMP_exec_IR_ses(OSSL_CMP_CTX *ctx);
+ X509 *OSSL_CMP_exec_CR_ses(OSSL_CMP_CTX *ctx);
+ X509 *OSSL_CMP_exec_P10CR_ses(OSSL_CMP_CTX *ctx);
+ X509 *OSSL_CMP_exec_KUR_ses(OSSL_CMP_CTX *ctx);
+ #define OSSL_CMP_IR
+ #define OSSL_CMP_CR
+ #define OSSL_CMP_P10CR
+ #define OSSL_CMP_KUR
+ int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type,
+ const OSSL_CRMF_MSG *crm, int *checkAfter);
+ int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx);
+ STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx);
+
+=head1 DESCRIPTION
+
+This is the OpenSSL API for doing CMP (Certificate Management Protocol)
+client-server transactions, i.e., sequences of CMP requests and responses.
+
+All functions take a populated OSSL_CMP_CTX structure as their first argument.
+Usually the server name, port, and path ("CMP alias") need to be set, as well as
+credentials the client can use for authenticating itself to the client.
+In order to authenticate the server the client typically needs a trust store.
+The functions return their respective main results directly, while there are
+also accessor functions for retrieving various results and status information
+from the I<ctx>. See L<OSSL_CMP_CTX_new(3)> etc. for details.
+
+The default conveying protocol is HTTP.
+Timeout values may be given per request-response pair and per transaction.
+See L<OSSL_CMP_MSG_http_perform(3)> for details.
+
+OSSL_CMP_exec_IR_ses() requests an initial certificate from the given PKI.
+
+OSSL_CMP_exec_CR_ses() requests an additional certificate.
+
+OSSL_CMP_exec_P10CR_ses() conveys a legacy PKCS#10 CSR requesting a certificate.
+
+OSSL_CMP_exec_KUR_ses() obtains an updated certificate.
+
+These four types of certificate enrollment are implemented as macros
+calling OSSL_CMP_exec_certreq().
+
+OSSL_CMP_exec_certreq() performs a certificate request of the type specified
+by the I<req_type> parameter, which may be IR, CR, P10CR, or KUR.
+For IR, CR, and KUR, the certificate template to be used in the request
+may be supplied via the I<crm> parameter pointing to a CRMF structure.
+Typically I<crm> is NULL, then the template ingredients are taken from I<ctx>
+and need to be filled in using L<OSSL_CMP_CTX_set1_subjectName(3)>,
+L<OSSL_CMP_CTX_set0_newPkey(3)>, L<OSSL_CMP_CTX_set1_oldCert(3)>, etc.
+For P10CR, L<OSSL_CMP_CTX_set1_p10CSR(3)> needs to be used instead.
+The enrollment session may be blocked by sleeping until the addressed
+CA (or an intermedate PKI component) can fully process and answer the request.
+
+OSSL_CMP_try_certreq() is an alternative to the above functions that is
+more flexible regarding what to do after receiving a checkAfter value.
+When called for the first time (with no certificate request in progress for
+the given I<ctx>) it starts a new transaction by sending a certificate request
+constructed as stated above using the I<req_type> and optional I<crm> parameter.
+Otherwise (when according to I<ctx> a 'waiting' status has been received before)
+it continues polling for the pending request
+unless the I<req_type> argument is < 0, which aborts the request.
+If the requested certificate is available the function returns 1 and the
+caller can use L<OSSL_CMP_CTX_get0_newCert(3)> to retrieve the new certificate.
+If no error occurred but no certificate is available yet then
+OSSL_CMP_try_certreq() remembers in the CMP context that it should be retried
+and returns -1 after assigning the received checkAfter value
+via the output pointer argument (unless it is NULL).
+The checkAfter value indicates the number of seconds the caller should let pass
+before trying again. The caller is free to sleep for the given number of seconds
+or for some other time and/or to do anything else before retrying by calling
+OSSL_CMP_try_certreq() again with the same parameter values as before.
+OSSL_CMP_try_certreq() then polls
+to see whether meanwhile the requested certificate is available.
+If the caller decides to abort the pending certificate request and provides
+a negative value as the I<req_type> argument then OSSL_CMP_try_certreq()
+aborts the CMP transaction by sending an error message to the server.
+
+OSSL_CMP_exec_RR_ses() requests the revocation of the certificate
+specified in the I<ctx> using L<OSSL_CMP_CTX_set1_oldCert(3)>.
+RFC 4210 is vague in which PKIStatus should be returned by the server.
+We take "accepted" and "grantedWithMods" as clear success and handle
+"revocationWarning" and "revocationNotification" just as warnings because CAs
+typically return them as an indication that the certificate was already revoked.
+"rejection" is a clear error. The values "waiting" and "keyUpdateWarning"
+make no sense for revocation and thus are treated as an error as well.
+
+OSSL_CMP_exec_GENM_ses() sends a general message containing the sequence of
+infoType and infoValue pairs (InfoTypeAndValue; short: B<ITAV>)
+optionally provided in the I<ctx> using L<OSSL_CMP_CTX_push0_genm_ITAV(3)>.
+On success it records in I<ctx> the status B<OSSL_CMP_PKISTATUS_accepted>
+and returns the list of B<ITAV>s received in the GENP message.
+This can be used, for instance, to poll for CRLs or CA Key Updates.
+See RFC 4210 section 5.3.19 and appendix E.5 for details.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+So far the CMP client implementation is limited to one request per CMP message
+(and consequently to at most one response component per CMP message).
+
+=head1 RETURN VALUES
+
+OSSL_CMP_exec_certreq(), OSSL_CMP_exec_IR_ses(), OSSL_CMP_exec_CR_ses(),
+OSSL_CMP_exec_P10CR_ses(), and OSSL_CMP_exec_KUR_ses() return a
+pointer to the newly obtained X509 certificate on success, NULL on error.
+This pointer will be freed implicitly by OSSL_CMP_CTX_free() or
+CSSL_CMP_CTX_reinit().
+
+OSSL_CMP_try_certreq() returns 1 if the requested certificate is available
+via L<OSSL_CMP_CTX_get0_newCert(3)>
+or on successfully aborting a pending certificate request, 0 on error, and -1
+in case a 'waiting' status has been received and checkAfter value is available.
+In the latter case L<OSSL_CMP_CTX_get0_newCert(3)> yields NULL
+and the output parameter I<checkAfter> has been used to
+assign the received value unless I<checkAfter> is NULL.
+
+OSSL_CMP_exec_RR_ses() returns 1 on success, 0 on error.
+
+OSSL_CMP_exec_GENM_ses() returns NULL on error,
+otherwise a pointer to the sequence of B<ITAV> received, which may be empty.
+This pointer must be freed by the caller.
+
+=head1 EXAMPLES
+
+See OSSL_CMP_CTX for examples on how to prepare the context for these
+functions.
+
+=head1 SEE ALSO
+
+L<OSSL_CMP_CTX_new(3)>, L<OSSL_CMP_CTX_free(3)>,
+L<OSSL_CMP_CTX_set1_subjectName(3)>, L<OSSL_CMP_CTX_set0_newPkey(3)>,
+L<OSSL_CMP_CTX_set1_p10CSR(3)>, L<OSSL_CMP_CTX_set1_oldCert(3)>,
+L<OSSL_CMP_CTX_get0_newCert(3)>, L<OSSL_CMP_CTX_push0_genm_ITAV(3)>,
+L<OSSL_CMP_MSG_http_perform(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CMP_log_open.pod b/doc/man3/OSSL_CMP_log_open.pod
new file mode 100644
index 000000000000..9a55370e3c0c
--- /dev/null
+++ b/doc/man3/OSSL_CMP_log_open.pod
@@ -0,0 +1,124 @@
+=pod
+
+=head1 NAME
+
+OSSL_CMP_log_open,
+OSSL_CMP_log_close,
+OSSL_CMP_severity,
+OSSL_CMP_LOG_EMERG,
+OSSL_CMP_LOG_ALERT,
+OSSL_CMP_LOG_CRIT,
+OSSL_CMP_LOG_ERR,
+OSSL_CMP_LOG_WARNING,
+OSSL_CMP_LOG_NOTICE,
+OSSL_CMP_LOG_INFO,
+OSSL_CMP_LOG_DEBUG,
+OSSL_CMP_LOG_TRACE,
+
+OSSL_CMP_log_cb_t,
+OSSL_CMP_print_to_bio,
+OSSL_CMP_print_errors_cb
+- functions for logging and error reporting
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp_util.h>
+
+ int OSSL_CMP_log_open(void);
+ void OSSL_CMP_log_close(void);
+
+ /* severity level declarations resemble those from syslog.h */
+ typedef int OSSL_CMP_severity;
+ #define OSSL_CMP_LOG_EMERG 0
+ #define OSSL_CMP_LOG_ALERT 1
+ #define OSSL_CMP_LOG_CRIT 2
+ #define OSSL_CMP_LOG_ERR 3
+ #define OSSL_CMP_LOG_WARNING 4
+ #define OSSL_CMP_LOG_NOTICE 5
+ #define OSSL_CMP_LOG_INFO 6
+ #define OSSL_CMP_LOG_DEBUG 7
+ #define OSSL_CMP_LOG_TRACE 8
+
+ typedef int (*OSSL_CMP_log_cb_t)(const char *component,
+ const char *file, int line,
+ OSSL_CMP_severity level, const char *msg);
+ int OSSL_CMP_print_to_bio(BIO *bio, const char *component, const char *file,
+ int line, OSSL_CMP_severity level, const char *msg);
+ void OSSL_CMP_print_errors_cb(OSSL_CMP_log_cb_t log_fn);
+
+=head1 DESCRIPTION
+
+The logging and error reporting facility described here contains
+convenience functions for CMP-specific logging,
+including a string prefix mirroring the severity levels of syslog.h,
+and enhancements of the error queue mechanism needed for large diagnostic
+messages produced by the CMP library in case of certificate validation failures.
+
+When an interesting activity is performed or an error occurs, some detail
+should be provided for user information, debugging, and auditing purposes.
+A CMP application can obtain this information by providing a callback function
+with the following type:
+
+ typedef int (*OSSL_CMP_log_cb_t)(const char *component,
+ const char *file, int line,
+ OSSL_CMP_severity level, const char *msg);
+
+The parameters may provide
+some component info (which may be a module name and/or function name) or NULL,
+a file pathname or NULL,
+a line number or 0 indicating the source code location,
+a severity level, and
+a message string describing the nature of the event, terminated by '\n'.
+
+Even when an activity is successful some warnings may be useful and some degree
+of auditing may be required. Therefore, the logging facility supports a severity
+level and the callback function has a I<level> parameter indicating such a
+level, such that error, warning, info, debug, etc. can be treated differently.
+The callback is activated only when the severity level is sufficient according
+to the current level of verbosity, which by default is B<OSSL_CMP_LOG_INFO>.
+
+The callback function may itself do non-trivial tasks like writing to
+a log file or remote stream, which in turn may fail.
+Therefore, the function should return 1 on success and 0 on failure.
+
+OSSL_CMP_log_open() initializes the CMP-specific logging facility to output
+everything to STDOUT. It fails if the integrated tracing is disabled or STDIO
+is not available. It may be called during application startup.
+Alternatively, L<OSSL_CMP_CTX_set_log_cb(3)> can be used for more flexibility.
+As long as neither if the two is used any logging output is ignored.
+
+OSSL_CMP_log_close() may be called when all activities are finished to flush
+any pending CMP-specific log output and deallocate related resources.
+It may be called multiple times. It does get called at OpenSSL stutdown.
+
+OSSL_CMP_print_to_bio() prints the given component info, filename, line number,
+severity level, and log message or error queue message to the given I<bio>.
+I<component> usually is a function or module name.
+If it is NULL, empty, or "(unknown function)" then "CMP" is used as fallback.
+
+OSSL_CMP_print_errors_cb() outputs any entries in the OpenSSL error queue.
+It is similar to L<ERR_print_errors_cb(3)> but uses the CMP log callback
+function I<log_fn> for uniformity with CMP logging if not NULL. Otherwise it
+prints to STDERR using L<OSSL_CMP_print_to_bio(3)> (unless B<OPENSSL_NO_STDIO>
+is defined).
+
+=head1 RETURN VALUES
+
+OSSL_CMP_log_close() and OSSL_CMP_print_errors_cb() do not return anything.
+
+All other functions return 1 on success, 0 on error.
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CMP_validate_msg.pod b/doc/man3/OSSL_CMP_validate_msg.pod
new file mode 100644
index 000000000000..44c901210feb
--- /dev/null
+++ b/doc/man3/OSSL_CMP_validate_msg.pod
@@ -0,0 +1,84 @@
+=pod
+
+=head1 NAME
+
+OSSL_CMP_validate_msg,
+OSSL_CMP_validate_cert_path
+- functions for verifying CMP message protection
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
+ int OSSL_CMP_validate_cert_path(const OSSL_CMP_CTX *ctx,
+ X509_STORE *trusted_store, X509 *cert);
+
+=head1 DESCRIPTION
+
+This is the API for validating the protection of CMP messages,
+which includes validating CMP message sender certificates and their paths
+while optionally checking the revocation status of the certificates(s).
+
+OSSL_CMP_validate_msg() validates the protection of the given I<msg>,
+which must be signature-based or using password-based MAC (PBM).
+In the former case a suitable trust anchor must be given in the CMP context
+I<ctx>, and in the latter case the matching secret must have been set there
+using L<OSSL_CMP_CTX_set1_secretValue(3)>.
+
+In case of signature algorithm, the certificate to use for the signature check
+is preferably the one provided by a call to L<OSSL_CMP_CTX_set1_srvCert(3)>.
+If no such sender cert has been pinned then candidate sender certificates are
+taken from the list of certificates received in the I<msg> extraCerts, then any
+certificates provided before via L<OSSL_CMP_CTX_set1_untrusted(3)>, and
+then all trusted certificates provided via L<OSSL_CMP_CTX_set0_trustedStore(3)>,
+where a candidate is acceptable only if has not expired, its subject DN matches
+the I<msg> sender DN (as far as present), and its subject key identifier
+is present and matches the senderKID (as far as the latter present).
+Each acceptable cert is tried in the given order to see if the message
+signature check succeeds and the cert and its path can be verified
+using any trust store set via L<OSSL_CMP_CTX_set0_trustedStore(3)>.
+
+If the option OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR was set by calling
+L<OSSL_CMP_CTX_set_option(3)>, for an Initialization Response (IP) message
+any self-issued certificate from the I<msg> extraCerts field may also be used
+as trust anchor for the path verification of an acceptable cert if it can be
+used also to validate the issued certificate returned in the IP message. This is
+according to TS 33.310 [Network Domain Security (NDS); Authentication Framework
+(AF)] document specified by the The 3rd Generation Partnership Project (3GPP).
+
+Any cert that has been found as described above is cached and tried first when
+validating the signatures of subsequent messages in the same transaction.
+
+OSSL_CMP_validate_cert_path() attempts to validate the given certificate and its
+path using the given store of trusted certs (possibly including CRLs and a cert
+verification callback) and non-trusted intermediate certs from the I<ctx>.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+OSSL_CMP_validate_msg() and OSSL_CMP_validate_cert_path()
+return 1 on success, 0 on error or validation failed.
+
+=head1 SEE ALSO
+
+L<OSSL_CMP_CTX_new(3)>, L<OSSL_CMP_exec_certreq(3)>,
+L<OSSL_CMP_CTX_set1_secretValue(3)>, L<OSSL_CMP_CTX_set1_srvCert(3)>,
+L<OSSL_CMP_CTX_set1_untrusted(3)>, L<OSSL_CMP_CTX_set0_trustedStore(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CORE_MAKE_FUNC.pod b/doc/man3/OSSL_CORE_MAKE_FUNC.pod
new file mode 100644
index 000000000000..a7a902a336c0
--- /dev/null
+++ b/doc/man3/OSSL_CORE_MAKE_FUNC.pod
@@ -0,0 +1,43 @@
+=pod
+
+=head1 NAME
+
+OSSL_CORE_MAKE_FUNC,
+SSL_OP_BIT,
+EXT_UTF8STRING
+- OpenSSL reserved symbols
+
+=head1 SYNOPSIS
+
+ #include <openssl/core_dispatch.h>
+
+ #define OSSL_CORE_MAKE_FUNC(type,name,args)
+ #define SSL_OP_BIT(n)
+ #define EXT_UTF8STRING(nid)
+
+=head1 DESCRIPTION
+
+There are certain macros that may appear in OpenSSL header files that are
+reserved for internal use. They should not be used by applications or assumed
+to exist.
+
+All the macros listed in the synopsis above are reserved.
+
+=head1 RETURN VALUES
+
+Not applicable.
+
+=head1 HISTORY
+
+The macros described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod b/doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod
new file mode 100644
index 000000000000..51296599e5c7
--- /dev/null
+++ b/doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod
@@ -0,0 +1,98 @@
+=pod
+
+=head1 NAME
+
+OSSL_CRMF_MSG_get0_tmpl,
+OSSL_CRMF_CERTTEMPLATE_get0_serialNumber,
+OSSL_CRMF_CERTTEMPLATE_get0_subject,
+OSSL_CRMF_CERTTEMPLATE_get0_issuer,
+OSSL_CRMF_CERTTEMPLATE_get0_extensions,
+OSSL_CRMF_CERTID_get0_serialNumber,
+OSSL_CRMF_CERTID_get0_issuer,
+OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert,
+OSSL_CRMF_MSG_get_certReqId
+- functions reading from CRMF CertReqMsg structures
+
+=head1 SYNOPSIS
+
+ #include <openssl/crmf.h>
+
+ OSSL_CRMF_CERTTEMPLATE *OSSL_CRMF_MSG_get0_tmpl(const OSSL_CRMF_MSG *crm);
+ const ASN1_INTEGER
+ *OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(const OSSL_CRMF_CERTTEMPLATE *tmpl);
+ const X509_NAME
+ *OSSL_CRMF_CERTTEMPLATE_get0_subject(const OSSL_CRMF_CERTTEMPLATE *tmpl);
+ const X509_NAME
+ *OSSL_CRMF_CERTTEMPLATE_get0_issuer(const OSSL_CRMF_CERTTEMPLATE *tmpl);
+ X509_EXTENSIONS
+ *OSSL_CRMF_CERTTEMPLATE_get0_extensions(const OSSL_CRMF_CERTTEMPLATE *tmpl);
+
+ const ASN1_INTEGER
+ *OSSL_CRMF_CERTID_get0_serialNumber(const OSSL_CRMF_CERTID *cid);
+ const X509_NAME *OSSL_CRMF_CERTID_get0_issuer(const OSSL_CRMF_CERTID *cid);
+
+ X509
+ *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(const OSSL_CRMF_ENCRYPTEDVALUE *ecert,
+ OSSL_LIB_CTX *libctx, const char *propq,
+ EVP_PKEY *pkey);
+
+ int OSSL_CRMF_MSG_get_certReqId(const OSSL_CRMF_MSG *crm);
+
+
+=head1 DESCRIPTION
+
+OSSL_CRMF_MSG_get0_tmpl() retrieves the certificate template of I<crm>.
+
+OSSL_CRMF_CERTTEMPLATE_get0_serialNumber() retrieves the serialNumber of the
+given certificate template I<tmpl>.
+
+OSSL_CRMF_CERTTEMPLATE_get0_subject() retrieves the subject name of the
+given certificate template I<tmpl>.
+
+OSSL_CRMF_CERTTEMPLATE_get0_issuer() retrieves the issuer name of the
+given certificate template I<tmpl>.
+
+OSSL_CRMF_CERTTEMPLATE_get0_extensions() retrieves the X.509 extensions
+of the given certificate template I<tmpl>, or NULL if not present.
+
+OSSL_CRMF_CERTID_get0_serialNumber retrieves the serialNumber
+of the given CertId I<cid>.
+
+OSSL_CRMF_CERTID_get0_issuer retrieves the issuer name
+of the given CertId I<cid>, which must be of ASN.1 type GEN_DIRNAME.
+
+OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert() decrypts the certificate in the given
+encryptedValue I<ecert>, using the private key I<pkey>, library context
+I<libctx> and property query string I<propq> (see L<OSSL_LIB_CTX(3)>).
+This is needed for the indirect POPO method as in RFC 4210 section 5.2.8.2.
+The function returns the decrypted certificate as a copy, leaving its ownership
+with the caller, who is responsible for freeing it.
+
+OSSL_CRMF_MSG_get_certReqId() retrieves the certReqId of I<crm>.
+
+
+=head1 RETURN VALUES
+
+OSSL_CRMF_MSG_get_certReqId() returns the certificate request ID as a
+nonnegative integer or -1 on error.
+
+All other functions return a pointer with the intended result or NULL on error.
+
+=head1 SEE ALSO
+
+RFC 4211
+
+=head1 HISTORY
+
+The OpenSSL CRMF support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CRMF_MSG_set0_validity.pod b/doc/man3/OSSL_CRMF_MSG_set0_validity.pod
new file mode 100644
index 000000000000..a87b7d530715
--- /dev/null
+++ b/doc/man3/OSSL_CRMF_MSG_set0_validity.pod
@@ -0,0 +1,120 @@
+=pod
+
+=head1 NAME
+
+OSSL_CRMF_MSG_set0_validity,
+OSSL_CRMF_MSG_set_certReqId,
+OSSL_CRMF_CERTTEMPLATE_fill,
+OSSL_CRMF_MSG_set0_extensions,
+OSSL_CRMF_MSG_push0_extension,
+OSSL_CRMF_MSG_create_popo,
+OSSL_CRMF_MSGS_verify_popo
+- functions populating and verifying CRMF CertReqMsg structures
+
+=head1 SYNOPSIS
+
+ #include <openssl/crmf.h>
+
+ int OSSL_CRMF_MSG_set0_validity(OSSL_CRMF_MSG *crm,
+ ASN1_TIME *notBefore, ASN1_TIME *notAfter);
+
+ int OSSL_CRMF_MSG_set_certReqId(OSSL_CRMF_MSG *crm, int rid);
+
+ int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl,
+ EVP_PKEY *pubkey,
+ const X509_NAME *subject,
+ const X509_NAME *issuer,
+ const ASN1_INTEGER *serial);
+
+ int OSSL_CRMF_MSG_set0_extensions(OSSL_CRMF_MSG *crm, X509_EXTENSIONS *exts);
+
+ int OSSL_CRMF_MSG_push0_extension(OSSL_CRMF_MSG *crm, X509_EXTENSION *ext);
+
+ int OSSL_CRMF_MSG_create_popo(int meth, OSSL_CRMF_MSG *crm,
+ EVP_PKEY *pkey, const EVP_MD *digest,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+ int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs,
+ int rid, int acceptRAVerified,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+=head1 DESCRIPTION
+
+OSSL_CRMF_MSG_set0_validity() sets the I<notBefore> and I<notAfter> fields
+as validity constraints in the certTemplate of I<crm>.
+Any of the I<notBefore> and I<notAfter> parameters may be NULL,
+which means no constraint for the respective field.
+On success ownership of I<notBefore> and I<notAfter> is transferred to I<crm>.
+
+OSSL_CRMF_MSG_set_certReqId() sets I<rid> as the certReqId of I<crm>.
+
+OSSL_CRMF_CERTTEMPLATE_fill() sets those fields of the certTemplate I<tmpl>
+for which non-NULL values are provided: I<pubkey>, I<subject>, I<issuer>,
+and/or I<serial>.
+X.509 extensions may be set using OSSL_CRMF_MSG_set0_extensions().
+On success the reference counter of the I<pubkey> (if given) is incremented,
+while the I<subject>, I<issuer>, and I<serial> structures (if given) are copied.
+
+OSSL_CRMF_MSG_set0_extensions() sets I<exts> as the extensions in the
+certTemplate of I<crm>. Frees any pre-existing ones and consumes I<exts>.
+
+OSSL_CRMF_MSG_push0_extension() pushes the X509 extension I<ext> to the
+extensions in the certTemplate of I<crm>. Consumes I<ext>.
+
+OSSL_CRMF_MSG_create_popo() creates and sets the Proof-of-Possession (POPO)
+according to the method I<meth> in I<crm>.
+The library context I<libctx> and property query string I<propq>,
+may be NULL to select the defaults.
+In case the method is OSSL_CRMF_POPO_SIGNATURE the POPO is calculated
+using the private key I<pkey> and the digest method I<digest>,
+where the I<digest> argument is ignored if I<pkey> is of a type (such as
+Ed25519 and Ed448) that is implicitly associated with a digest alorithm.
+
+I<meth> can be one of the following:
+
+=over 8
+
+=item * OSSL_CRMF_POPO_NONE - RFC 4211, section 4, POP field omitted.
+CA/RA uses out-of-band method to verify POP. Note that servers may fail in this
+case, resulting for instance in HTTP error code 500 (Internal error).
+
+=item * OSSL_CRMF_POPO_RAVERIFIED - RFC 4211, section 4, explicit indication
+that the RA has already verified the POP.
+
+=item * OSSL_CRMF_POPO_SIGNATURE - RFC 4211, section 4.1, only case 3 supported
+so far.
+
+=item * OSSL_CRMF_POPO_KEYENC - RFC 4211, section 4.2, only indirect method
+(subsequentMessage/enccert) supported,
+challenge-response exchange (challengeResp) not yet supported.
+
+=item * OSSL_CRMF_POPO_KEYAGREE - RFC 4211, section 4.3, not yet supported.
+
+=back
+
+OSSL_CRMF_MSGS_verify_popo verifies the Proof-of-Possession of the request with
+the given I<rid> in the list of I<reqs>. Optionally accepts RAVerified. It can
+make use of the library context I<libctx> and property query string I<propq>.
+
+=head1 RETURN VALUES
+
+All functions return 1 on success, 0 on error.
+
+=head1 SEE ALSO
+
+RFC 4211
+
+=head1 HISTORY
+
+The OpenSSL CRMF support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod b/doc/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod
new file mode 100644
index 000000000000..2a0fa04e473e
--- /dev/null
+++ b/doc/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod
@@ -0,0 +1,131 @@
+=pod
+
+=head1 NAME
+
+OSSL_CRMF_MSG_get0_regCtrl_regToken,
+OSSL_CRMF_MSG_set1_regCtrl_regToken,
+OSSL_CRMF_MSG_get0_regCtrl_authenticator,
+OSSL_CRMF_MSG_set1_regCtrl_authenticator,
+OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo,
+OSSL_CRMF_MSG_set0_SinglePubInfo,
+OSSL_CRMF_MSG_set_PKIPublicationInfo_action,
+OSSL_CRMF_MSG_get0_regCtrl_pkiPublicationInfo,
+OSSL_CRMF_MSG_set1_regCtrl_pkiPublicationInfo,
+OSSL_CRMF_MSG_get0_regCtrl_protocolEncrKey,
+OSSL_CRMF_MSG_set1_regCtrl_protocolEncrKey,
+OSSL_CRMF_MSG_get0_regCtrl_oldCertID,
+OSSL_CRMF_MSG_set1_regCtrl_oldCertID,
+OSSL_CRMF_CERTID_gen
+- functions getting or setting CRMF Registration Controls
+
+=head1 SYNOPSIS
+
+ #include <openssl/crmf.h>
+
+ ASN1_UTF8STRING
+ *OSSL_CRMF_MSG_get0_regCtrl_regToken(const OSSL_CRMF_MSG *msg);
+ int OSSL_CRMF_MSG_set1_regCtrl_regToken(OSSL_CRMF_MSG *msg,
+ const ASN1_UTF8STRING *tok);
+ ASN1_UTF8STRING
+ *OSSL_CRMF_MSG_get0_regCtrl_authenticator(const OSSL_CRMF_MSG *msg);
+ int OSSL_CRMF_MSG_set1_regCtrl_authenticator(OSSL_CRMF_MSG *msg,
+ const ASN1_UTF8STRING *auth);
+ int OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo(
+ OSSL_CRMF_PKIPUBLICATIONINFO *pi,
+ OSSL_CRMF_SINGLEPUBINFO *spi);
+ int OSSL_CRMF_MSG_set0_SinglePubInfo(OSSL_CRMF_SINGLEPUBINFO *spi,
+ int method, GENERAL_NAME *nm);
+ int OSSL_CRMF_MSG_set_PKIPublicationInfo_action(
+ OSSL_CRMF_PKIPUBLICATIONINFO *pi, int action);
+ OSSL_CRMF_PKIPUBLICATIONINFO
+ *OSSL_CRMF_MSG_get0_regCtrl_pkiPublicationInfo(const OSSL_CRMF_MSG *msg);
+ int OSSL_CRMF_MSG_set1_regCtrl_pkiPublicationInfo(OSSL_CRMF_MSG *msg,
+ const OSSL_CRMF_PKIPUBLICATIONINFO *pi);
+ X509_PUBKEY
+ *OSSL_CRMF_MSG_get0_regCtrl_protocolEncrKey(const OSSL_CRMF_MSG *msg);
+ int OSSL_CRMF_MSG_set1_regCtrl_protocolEncrKey(OSSL_CRMF_MSG *msg,
+ const X509_PUBKEY *pubkey);
+ OSSL_CRMF_CERTID
+ *OSSL_CRMF_MSG_get0_regCtrl_oldCertID(const OSSL_CRMF_MSG *msg);
+ int OSSL_CRMF_MSG_set1_regCtrl_oldCertID(OSSL_CRMF_MSG *msg,
+ const OSSL_CRMF_CERTID *cid);
+ OSSL_CRMF_CERTID *OSSL_CRMF_CERTID_gen(const X509_NAME *issuer,
+ const ASN1_INTEGER *serial);
+
+=head1 DESCRIPTION
+
+Each of the OSSL_CRMF_MSG_get0_regCtrl_X() functions
+returns the respective control X in the given I<msg>, if present.
+
+OSSL_CRMF_MSG_set1_regCtrl_regToken() sets the regToken control in the given
+I<msg> copying the given I<tok> as value. See RFC 4211, section 6.1.
+
+OSSL_CRMF_MSG_set1_regCtrl_authenticator() sets the authenticator control in
+the given I<msg> copying the given I<auth> as value. See RFC 4211, section 6.2.
+
+OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo() pushes the given I<spi>
+to I<si>. Consumes the I<spi> pointer.
+
+OSSL_CRMF_MSG_set0_SinglePubInfo() sets in the given SinglePubInfo I<spi>
+the I<method> and publication location, in the form of a GeneralName, I<nm>.
+The publication location is optional, and therefore I<nm> may be NULL.
+The function consumes the I<nm> pointer if present.
+Available methods are:
+ # define OSSL_CRMF_PUB_METHOD_DONTCARE 0
+ # define OSSL_CRMF_PUB_METHOD_X500 1
+ # define OSSL_CRMF_PUB_METHOD_WEB 2
+ # define OSSL_CRMF_PUB_METHOD_LDAP 3
+
+OSSL_CRMF_MSG_set_PKIPublicationInfo_action() sets the action in the given I<pi>
+using the given I<action> as value. See RFC 4211, section 6.3.
+Available actions are:
+ # define OSSL_CRMF_PUB_ACTION_DONTPUBLISH 0
+ # define OSSL_CRMF_PUB_ACTION_PLEASEPUBLISH 1
+
+OSSL_CRMF_MSG_set1_regCtrl_pkiPublicationInfo() sets the pkiPublicationInfo
+control in the given I<msg> copying the given I<tok> as value. See RFC 4211,
+section 6.3.
+
+OSSL_CRMF_MSG_set1_regCtrl_protocolEncrKey() sets the protocolEncrKey control in
+the given I<msg> copying the given I<pubkey> as value. See RFC 4211 section 6.6.
+
+OSSL_CRMF_MSG_set1_regCtrl_oldCertID() sets the B<oldCertID> regToken control in
+the given I<msg> copying the given I<cid> as value. See RFC 4211, section 6.5.
+
+OSSL_CRMF_CERTID_gen produces an OSSL_CRMF_CERTID_gen structure copying the
+given I<issuer> name and I<serial> number.
+
+=head1 RETURN VALUES
+
+All OSSL_CRMF_MSG_get0_*() functions
+return the respective pointer value or NULL if not present and on error.
+
+All OSSL_CRMF_MSG_set1_*() functions return 1 on success, 0 on error.
+
+OSSL_CRMF_CERTID_gen() returns a pointer to the resulting structure
+or NULL on error.
+
+=head1 NOTES
+
+A function OSSL_CRMF_MSG_set1_regCtrl_pkiArchiveOptions() for setting an
+Archive Options Control is not yet implemented due to missing features to
+create the needed OSSL_CRMF_PKIARCHIVEOPTINS content.
+
+=head1 SEE ALSO
+
+RFC 4211
+
+=head1 HISTORY
+
+The OpenSSL CRMF support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod b/doc/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod
new file mode 100644
index 000000000000..00541c32b4a5
--- /dev/null
+++ b/doc/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod
@@ -0,0 +1,68 @@
+=pod
+
+=head1 NAME
+
+OSSL_CRMF_MSG_get0_regInfo_utf8Pairs,
+OSSL_CRMF_MSG_set1_regInfo_utf8Pairs,
+OSSL_CRMF_MSG_get0_regInfo_certReq,
+OSSL_CRMF_MSG_set1_regInfo_certReq
+- functions getting or setting CRMF Registration Info
+
+=head1 SYNOPSIS
+
+ #include <openssl/crmf.h>
+
+ ASN1_UTF8STRING
+ *OSSL_CRMF_MSG_get0_regInfo_utf8Pairs(const OSSL_CRMF_MSG *msg);
+ int OSSL_CRMF_MSG_set1_regInfo_utf8Pairs(OSSL_CRMF_MSG *msg,
+ const ASN1_UTF8STRING *utf8pairs);
+ OSSL_CRMF_CERTREQUEST
+ *OSSL_CRMF_MSG_get0_regInfo_certReq(const OSSL_CRMF_MSG *msg);
+ int OSSL_CRMF_MSG_set1_regInfo_certReq(OSSL_CRMF_MSG *msg,
+ const OSSL_CRMF_CERTREQUEST *cr);
+
+=head1 DESCRIPTION
+
+OSSL_CRMF_MSG_get0_regInfo_utf8Pairs() returns the first utf8Pairs regInfo
+in the given I<msg>, if present.
+
+OSSL_CRMF_MSG_set1_regInfo_utf8Pairs() adds a copy of the given I<utf8pairs>
+value as utf8Pairs regInfo to the given I<msg>. See RFC 4211 section 7.1.
+
+OSSL_CRMF_MSG_get0_regInfo_certReq() returns the first certReq regInfo
+in the given I<msg>, if present.
+
+OSSL_CRMF_MSG_set1_regInfo_certReq() adds a copy of the given I<cr> value
+as certReq regInfo to the given I<msg>. See RFC 4211 section 7.2.
+
+=head1 RETURN VALUES
+
+All get0_*() functions return the respective pointer value, NULL if not present.
+
+All set1_*() functions return 1 on success, 0 on error.
+
+=head1 NOTES
+
+Calling the set1_*() functions multiple times
+adds multiple instances of the respective
+control to the regInfo structure of the given I<msg>. While RFC 4211 expects
+multiple utf8Pairs in one regInfo structure, it does not allow multiple certReq.
+
+=head1 SEE ALSO
+
+RFC 4211
+
+=head1 HISTORY
+
+The OpenSSL CRMF support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_CRMF_pbmp_new.pod b/doc/man3/OSSL_CRMF_pbmp_new.pod
new file mode 100644
index 000000000000..ff8b3c327cd2
--- /dev/null
+++ b/doc/man3/OSSL_CRMF_pbmp_new.pod
@@ -0,0 +1,92 @@
+=pod
+
+=head1 NAME
+
+OSSL_CRMF_pbm_new,
+OSSL_CRMF_pbmp_new
+- functions for producing Password-Based MAC (PBM)
+
+=head1 SYNOPSIS
+
+ #include <openssl/crmf.h>
+
+ int OSSL_CRMF_pbm_new(OSSL_LIB_CTX *libctx, const char *propq,
+ const OSSL_CRMF_PBMPARAMETER *pbmp,
+ const unsigned char *msg, size_t msglen,
+ const unsigned char *sec, size_t seclen,
+ unsigned char **mac, size_t *maclen);
+
+ OSSL_CRMF_PBMPARAMETER *OSSL_CRMF_pbmp_new(OSSL_LIB_CTX *libctx, size_t saltlen,
+ int owfnid, size_t itercnt,
+ int macnid);
+
+=head1 DESCRIPTION
+
+OSSL_CRMF_pbm_new() generates a PBM (Password-Based MAC) based on given PBM
+parameters I<pbmp>, message I<msg>, and secret I<sec>, along with the respective
+lengths I<msglen> and I<seclen>.
+The optional library context I<libctx> and I<propq> parameters may be used
+to influence the selection of the MAC algorithm referenced in the I<pbmp>;
+see L<crypto(7)/ALGORITHM FETCHING> for further information.
+On success writes the address of the newly
+allocated MAC via the I<mac> reference parameter and writes the length via the
+I<maclen> reference parameter unless it its NULL.
+
+OSSL_CRMF_pbmp_new() initializes and returns a new B<PBMParameter> structure
+with a new random salt of given length I<saltlen>,
+OWF (one-way function) NID I<owfnid>, OWF iteration count I<itercnt>,
+and MAC NID I<macnid>.
+The library context I<libctx> parameter may be used to select the provider
+for the random number generation (DRBG) and may be NULL for the default.
+
+=head1 NOTES
+
+The algorithms for the OWF (one-way function) and for the MAC (message
+authentication code) may be any with a NID defined in F<< <openssl/objects.h> >>.
+As specified by RFC 4210, these should include NID_hmac_sha1.
+
+RFC 4210 recommends that the salt SHOULD be at least 8 bytes (64 bits) long,
+where 16 bytes is common.
+
+The iteration count must be at least 100, as stipulated by RFC 4211, and is
+limited to at most 100000 to avoid DoS through manipulated or otherwise
+malformed input.
+
+=head1 RETURN VALUES
+
+OSSL_CRMF_pbm_new() returns 1 on success, 0 on error.
+
+OSSL_CRMF_pbmp_new() returns a new and initialized OSSL_CRMF_PBMPARAMETER
+structure, or NULL on error.
+
+=head1 EXAMPLES
+
+ OSSL_CRMF_PBMPARAMETER *pbm = NULL;
+ unsigned char *msg = "Hello";
+ unsigned char *sec = "SeCrEt";
+ unsigned char *mac = NULL;
+ size_t maclen;
+
+ if ((pbm = OSSL_CRMF_pbmp_new(16, NID_sha256, 500, NID_hmac_sha1) == NULL))
+ goto err;
+ if (!OSSL_CRMF_pbm_new(pbm, msg, 5, sec, 6, &mac, &maclen))
+ goto err;
+
+=head1 SEE ALSO
+
+RFC 4211 section 4.4
+
+=head1 HISTORY
+
+The OpenSSL CRMF support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_DECODER.pod b/doc/man3/OSSL_DECODER.pod
new file mode 100644
index 000000000000..334f955e16f9
--- /dev/null
+++ b/doc/man3/OSSL_DECODER.pod
@@ -0,0 +1,190 @@
+=pod
+
+=head1 NAME
+
+OSSL_DECODER,
+OSSL_DECODER_fetch,
+OSSL_DECODER_up_ref,
+OSSL_DECODER_free,
+OSSL_DECODER_get0_provider,
+OSSL_DECODER_get0_properties,
+OSSL_DECODER_is_a,
+OSSL_DECODER_get0_name,
+OSSL_DECODER_get0_description,
+OSSL_DECODER_do_all_provided,
+OSSL_DECODER_names_do_all,
+OSSL_DECODER_gettable_params,
+OSSL_DECODER_get_params
+- Decoder method routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/decoder.h>
+
+ typedef struct ossl_decoder_st OSSL_DECODER;
+
+ OSSL_DECODER *OSSL_DECODER_fetch(OSSL_LIB_CTX *ctx, const char *name,
+ const char *properties);
+ int OSSL_DECODER_up_ref(OSSL_DECODER *decoder);
+ void OSSL_DECODER_free(OSSL_DECODER *decoder);
+ const OSSL_PROVIDER *OSSL_DECODER_get0_provider(const OSSL_DECODER *decoder);
+ const char *OSSL_DECODER_get0_properties(const OSSL_DECODER *decoder);
+ int OSSL_DECODER_is_a(const OSSL_DECODER *decoder, const char *name);
+ const char *OSSL_DECODER_get0_name(const OSSL_DECODER *decoder);
+ const char *OSSL_DECODER_get0_description(const OSSL_DECODER *decoder);
+ void OSSL_DECODER_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(OSSL_DECODER *decoder, void *arg),
+ void *arg);
+ int OSSL_DECODER_names_do_all(const OSSL_DECODER *decoder,
+ void (*fn)(const char *name, void *data),
+ void *data);
+ const OSSL_PARAM *OSSL_DECODER_gettable_params(OSSL_DECODER *decoder);
+ int OSSL_DECODER_get_params(OSSL_DECODER_CTX *ctx, const OSSL_PARAM params[]);
+
+=head1 DESCRIPTION
+
+B<OSSL_DECODER> is a method for decoders, which know how to
+decode encoded data into an object of some type that the rest
+of OpenSSL knows how to handle.
+
+OSSL_DECODER_fetch() looks for an algorithm within the provider that
+has been loaded into the B<OSSL_LIB_CTX> given by I<ctx>, having the
+name given by I<name> and the properties given by I<properties>.
+The I<name> determines what type of object the fetched decoder
+method is expected to be able to decode, and the properties are
+used to determine the expected output type.
+For known properties and the values they may have, please have a look
+in L<provider-encoder(7)/Names and properties>.
+
+OSSL_DECODER_up_ref() increments the reference count for the given
+I<decoder>.
+
+OSSL_DECODER_free() decrements the reference count for the given
+I<decoder>, and when the count reaches zero, frees it.
+
+OSSL_DECODER_get0_provider() returns the provider of the given
+I<decoder>.
+
+OSSL_DECODER_get0_properties() returns the property definition associated
+with the given I<decoder>.
+
+OSSL_DECODER_is_a() checks if I<decoder> is an implementation
+of an algorithm that's identifiable with I<name>.
+
+OSSL_DECODER_get0_name() returns the name used to fetch the given I<decoder>.
+
+OSSL_DECODER_get0_description() returns a description of the I<decoder>, meant
+for display and human consumption. The description is at the discretion
+of the I<decoder> implementation.
+
+OSSL_DECODER_names_do_all() traverses all names for the given
+I<decoder>, and calls I<fn> with each name and I<data> as arguments.
+
+OSSL_DECODER_do_all_provided() traverses all decoder
+implementations by all activated providers in the library context
+I<libctx>, and for each of the implementations, calls I<fn> with the
+implementation method and I<arg> as arguments.
+
+OSSL_DECODER_gettable_params() returns an L<OSSL_PARAM(3)>
+array of parameter descriptors.
+
+OSSL_DECODER_get_params() attempts to get parameters specified
+with an L<OSSL_PARAM(3)> array I<params>. Parameters that the
+implementation doesn't recognise should be ignored.
+
+=head1 RETURN VALUES
+
+OSSL_DECODER_fetch() returns a pointer to an OSSL_DECODER object,
+or NULL on error.
+
+OSSL_DECODER_up_ref() returns 1 on success, or 0 on error.
+
+OSSL_DECODER_free() doesn't return any value.
+
+OSSL_DECODER_get0_provider() returns a pointer to a provider object, or
+NULL on error.
+
+OSSL_DECODER_get0_properties() returns a pointer to a property
+definition string, or NULL on error.
+
+OSSL_DECODER_is_a() returns 1 if I<decoder> was identifiable,
+otherwise 0.
+
+OSSL_DECODER_get0_name() returns the algorithm name from the provided
+implementation for the given I<decoder>. Note that the I<decoder> may have
+multiple synonyms associated with it. In this case the first name from the
+algorithm definition is returned. Ownership of the returned string is retained
+by the I<decoder> object and should not be freed by the caller.
+
+OSSL_DECODER_get0_description() returns a pointer to a decription, or NULL if
+there isn't one.
+
+OSSL_DECODER_names_do_all() returns 1 if the callback was called for all
+names. A return value of 0 means that the callback was not called for any names.
+
+=head1 NOTES
+
+OSSL_DECODER_fetch() may be called implicitly by other fetching
+functions, using the same library context and properties.
+Any other API that uses keys will typically do this.
+
+=head1 EXAMPLES
+
+To list all decoders in a provider to a bio_out:
+
+ static void collect_decoders(OSSL_DECODER *decoder, void *stack)
+ {
+ STACK_OF(OSSL_DECODER) *decoder_stack = stack;
+
+ sk_OSSL_DECODER_push(decoder_stack, decoder);
+ OSSL_DECODER_up_ref(decoder);
+ }
+
+ void print_name(const char *name, void *vdata)
+ {
+ BIO *bio = vdata;
+
+ BIO_printf(bio, "%s ", name);
+ }
+
+
+ STACK_OF(OSSL_DECODER) *decoders;
+ int i;
+
+ decoders = sk_OSSL_DECODER_new_null();
+
+ BIO_printf(bio_out, "DECODERs provided by %s:\n", provider);
+ OSSL_DECODER_do_all_provided(NULL, collect_decoders,
+ decoders);
+
+ for (i = 0; i < sk_OSSL_DECODER_num(decoders); i++) {
+ OSSL_DECODER *decoder = sk_OSSL_DECODER_value(decoders, i);
+
+ if (strcmp(OSSL_PROVIDER_get0_name(OSSL_DECODER_get0_provider(decoder)),
+ provider) != 0)
+ continue;
+
+ if (OSSL_DECODER_names_do_all(decoder, print_name, bio_out))
+ BIO_printf(bio_out, "\n");
+ }
+ sk_OSSL_DECODER_pop_free(decoders, OSSL_DECODER_free);
+
+=head1 SEE ALSO
+
+L<provider(7)>, L<OSSL_DECODER_CTX(3)>, L<OSSL_DECODER_from_bio(3)>,
+L<OSSL_DECODER_CTX_new_for_pkey(3)>, L<OSSL_LIB_CTX(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_DECODER_CTX.pod b/doc/man3/OSSL_DECODER_CTX.pod
new file mode 100644
index 000000000000..3ffd794cf0fb
--- /dev/null
+++ b/doc/man3/OSSL_DECODER_CTX.pod
@@ -0,0 +1,259 @@
+=pod
+
+=head1 NAME
+
+OSSL_DECODER_CTX,
+OSSL_DECODER_CTX_new,
+OSSL_DECODER_settable_ctx_params,
+OSSL_DECODER_CTX_set_params,
+OSSL_DECODER_CTX_free,
+OSSL_DECODER_CTX_set_selection,
+OSSL_DECODER_CTX_set_input_type,
+OSSL_DECODER_CTX_set_input_structure,
+OSSL_DECODER_CTX_add_decoder,
+OSSL_DECODER_CTX_add_extra,
+OSSL_DECODER_CTX_get_num_decoders,
+OSSL_DECODER_INSTANCE,
+OSSL_DECODER_CONSTRUCT,
+OSSL_DECODER_CLEANUP,
+OSSL_DECODER_CTX_set_construct,
+OSSL_DECODER_CTX_set_construct_data,
+OSSL_DECODER_CTX_set_cleanup,
+OSSL_DECODER_CTX_get_construct,
+OSSL_DECODER_CTX_get_construct_data,
+OSSL_DECODER_CTX_get_cleanup,
+OSSL_DECODER_export,
+OSSL_DECODER_INSTANCE_get_decoder,
+OSSL_DECODER_INSTANCE_get_decoder_ctx,
+OSSL_DECODER_INSTANCE_get_input_type,
+OSSL_DECODER_INSTANCE_get_input_structure
+- Decoder context routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/decoder.h>
+
+ typedef struct ossl_decoder_ctx_st OSSL_DECODER_CTX;
+
+ OSSL_DECODER_CTX *OSSL_DECODER_CTX_new(void);
+ const OSSL_PARAM *OSSL_DECODER_settable_ctx_params(OSSL_DECODER *decoder);
+ int OSSL_DECODER_CTX_set_params(OSSL_DECODER_CTX *ctx,
+ const OSSL_PARAM params[]);
+ void OSSL_DECODER_CTX_free(OSSL_DECODER_CTX *ctx);
+
+ int OSSL_DECODER_CTX_set_selection(OSSL_DECODER_CTX *ctx, int selection);
+ int OSSL_DECODER_CTX_set_input_type(OSSL_DECODER_CTX *ctx,
+ const char *input_type);
+ int OSSL_DECODER_CTX_set_input_structure(OSSL_DECODER_CTX *ctx,
+ const char *input_structure);
+ int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder);
+ int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx,
+ OSSL_LIB_CTX *libctx,
+ const char *propq);
+ int OSSL_DECODER_CTX_get_num_decoders(OSSL_DECODER_CTX *ctx);
+
+ typedef struct ossl_decoder_instance_st OSSL_DECODER_INSTANCE;
+ OSSL_DECODER *
+ OSSL_DECODER_INSTANCE_get_decoder(OSSL_DECODER_INSTANCE *decoder_inst);
+ void *
+ OSSL_DECODER_INSTANCE_get_decoder_ctx(OSSL_DECODER_INSTANCE *decoder_inst);
+ const char *
+ OSSL_DECODER_INSTANCE_get_input_type(OSSL_DECODER_INSTANCE *decoder_inst);
+ OSSL_DECODER_INSTANCE_get_input_structure(OSSL_DECODER_INSTANCE *decoder_inst,
+ int *was_set);
+
+ typedef int OSSL_DECODER_CONSTRUCT(OSSL_DECODER_INSTANCE *decoder_inst,
+ const OSSL_PARAM *object,
+ void *construct_data);
+ typedef void OSSL_DECODER_CLEANUP(void *construct_data);
+
+ int OSSL_DECODER_CTX_set_construct(OSSL_DECODER_CTX *ctx,
+ OSSL_DECODER_CONSTRUCT *construct);
+ int OSSL_DECODER_CTX_set_construct_data(OSSL_DECODER_CTX *ctx,
+ void *construct_data);
+ int OSSL_DECODER_CTX_set_cleanup(OSSL_DECODER_CTX *ctx,
+ OSSL_DECODER_CLEANUP *cleanup);
+ OSSL_DECODER_CONSTRUCT *OSSL_DECODER_CTX_get_construct(OSSL_DECODER_CTX *ctx);
+ void *OSSL_DECODER_CTX_get_construct_data(OSSL_DECODER_CTX *ctx);
+ OSSL_DECODER_CLEANUP *OSSL_DECODER_CTX_get_cleanup(OSSL_DECODER_CTX *ctx);
+
+ int OSSL_DECODER_export(OSSL_DECODER_INSTANCE *decoder_inst,
+ void *reference, size_t reference_sz,
+ OSSL_CALLBACK *export_cb, void *export_cbarg);
+
+=head1 DESCRIPTION
+
+The B<OSSL_DECODER_CTX> holds data about multiple decoders, as needed to
+figure out what the input data is and to attempt to unpack it into one of
+several possible related results. This also includes chaining decoders, so
+the output from one can become the input for another. This allows having
+generic format decoders such as PEM to DER, as well as more specialized
+decoders like DER to RSA.
+
+The chains may be limited by specifying an input type, which is considered a
+starting point. This is both considered by OSSL_DECODER_CTX_add_extra(),
+which will stop adding one more decoder implementations when it has already
+added those that take the specified input type, and functions like
+L<OSSL_DECODER_from_bio(3)>, which will only start the decoding process with
+the decoder implementations that take that input type. For example, if the
+input type is set to C<DER>, a PEM to DER decoder will be ignored.
+
+The input type can also be NULL, which means that the caller doesn't know
+what type of input they have. In this case, OSSL_DECODER_from_bio() will
+simply try with one decoder implementation after the other, and thereby
+discover what kind of input the caller gave it.
+
+For every decoding done, even an intermediary one, a constructor provided by
+the caller is called to attempt to construct an appropriate type / structure
+that the caller knows how to handle from the current decoding result.
+The constructor is set with OSSL_DECODER_CTX_set_construct().
+
+B<OSSL_DECODER_INSTANCE> is an opaque structure that contains data about the
+decoder that was just used, and that may be useful for the constructor.
+There are some functions to extract data from this type, described further
+down.
+
+=head2 Functions
+
+OSSL_DECODER_CTX_new() creates a new empty B<OSSL_DECODER_CTX>.
+
+OSSL_DECODER_settable_ctx_params() returns an L<OSSL_PARAM(3)> array of
+parameter descriptors.
+
+OSSL_DECODER_CTX_set_params() attempts to set parameters specified with an
+L<OSSL_PARAM(3)> array I<params>. These parameters are passed to all
+decoders that have been added to the I<ctx> so far. Parameters that an
+implementation doesn't recognise should be ignored by it.
+
+OSSL_DECODER_CTX_free() frees the given context I<ctx>.
+
+OSSL_DECODER_CTX_add_decoder() populates the B<OSSL_DECODER_CTX> I<ctx> with
+a decoder, to be used to attempt to decode some encoded input.
+
+OSSL_DECODER_CTX_add_extra() finds decoders that generate input for already
+added decoders, and adds them as well. This is used to build decoder
+chains.
+
+OSSL_DECODER_CTX_set_input_type() sets the starting input type. This limits
+the decoder chains to be considered, as explained in the general description
+above.
+
+OSSL_DECODER_CTX_set_input_structure() sets the name of the structure that
+the input is expected to have. This may be used to determines what decoder
+implementations may be used. NULL is a valid input structure, when it's not
+relevant, or when the decoder implementations are expected to figure it out.
+
+OSSL_DECODER_CTX_get_num_decoders() gets the number of decoders currently
+added to the context I<ctx>.
+
+OSSL_DECODER_CTX_set_construct() sets the constructor I<construct>.
+
+OSSL_DECODER_CTX_set_construct_data() sets the constructor data that is
+passed to the constructor every time it's called.
+
+OSSL_DECODER_CTX_set_cleanup() sets the constructor data I<cleanup>
+function. This is called by L<OSSL_DECODER_CTX_free(3)>.
+
+OSSL_DECODER_CTX_get_construct(), OSSL_DECODER_CTX_get_construct_data() and
+OSSL_DECODER_CTX_get_cleanup() return the values that have been set by
+OSSL_DECODER_CTX_set_construct(), OSSL_DECODER_CTX_set_construct_data() and
+OSSL_DECODER_CTX_set_cleanup() respectively.
+
+OSSL_DECODER_export() is a fallback function for constructors that cannot
+use the data they get directly for diverse reasons. It takes the same
+decode instance I<decoder_inst> that the constructor got and an object
+I<reference>, unpacks the object which it refers to, and exports it by
+creating an L<OSSL_PARAM(3)> array that it then passes to I<export_cb>,
+along with I<export_arg>.
+
+=head2 Constructor
+
+A B<OSSL_DECODER_CONSTRUCT> gets the following arguments:
+
+=over 4
+
+=item I<decoder_inst>
+
+The B<OSSL_DECODER_INSTANCE> for the decoder from which the constructor gets
+its data.
+
+=item I<object>
+
+A provider-native object abstraction produced by the decoder. Further
+information on the provider-native object abstraction can be found in
+L<provider-object(7)>.
+
+=item I<construct_data>
+
+The pointer that was set with OSSL_DECODE_CTX_set_construct_data().
+
+=back
+
+The constructor is expected to return 1 when the data it receives can be
+constructed, otherwise 0.
+
+These utility functions may be used by a constructor:
+
+OSSL_DECODER_INSTANCE_get_decoder() can be used to get the decoder
+implementation from a decoder instance I<decoder_inst>.
+
+OSSL_DECODER_INSTANCE_get_decoder_ctx() can be used to get the decoder
+implementation's provider context from a decoder instance I<decoder_inst>.
+
+OSSL_DECODER_INSTANCE_get_input_type() can be used to get the decoder
+implementation's input type from a decoder instance I<decoder_inst>.
+
+OSSL_DECODER_INSTANCE_get_input_structure() can be used to get the input
+structure for the decoder implementation from a decoder instance
+I<decoder_inst>.
+This may be NULL.
+
+=head1 RETURN VALUES
+
+OSSL_DECODER_CTX_new() returns a pointer to a B<OSSL_DECODER_CTX>, or NULL
+if the context structure couldn't be allocated.
+
+OSSL_DECODER_settable_ctx_params() returns an L<OSSL_PARAM(3)> array, or
+NULL if none is available.
+
+OSSL_DECODER_CTX_set_params() returns 1 if all recognised parameters were
+valid, or 0 if one of them was invalid or caused some other failure in the
+implementation.
+
+OSSL_DECODER_CTX_add_decoder(), OSSL_DECODER_CTX_add_extra(),
+OSSL_DECODER_CTX_set_construct(), OSSL_DECODER_CTX_set_construct_data() and
+OSSL_DECODER_CTX_set_cleanup() return 1 on success, or 0 on failure.
+
+OSSL_DECODER_CTX_get_construct(), OSSL_DECODER_CTX_get_construct_data() and
+OSSL_DECODER_CTX_get_cleanup() return the current pointers to the
+constructor, the constructor data and the cleanup functions, respectively.
+
+OSSL_DECODER_CTX_num_decoders() returns the current number of decoders. It
+returns 0 if I<ctx> is NULL.
+
+OSSL_DECODER_export() returns 1 on success, or 0 on failure.
+
+OSSL_DECODER_INSTANCE_decoder() returns an B<OSSL_DECODER> pointer on
+success, or NULL on failure.
+
+OSSL_DECODER_INSTANCE_decoder_ctx() returns a provider context pointer on
+success, or NULL on failure.
+
+=head1 SEE ALSO
+
+L<provider(7)>, L<OSSL_DECODER(3)>, L<OSSL_DECODER_from_bio(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_DECODER_CTX_new_for_pkey.pod b/doc/man3/OSSL_DECODER_CTX_new_for_pkey.pod
new file mode 100644
index 000000000000..213791404c77
--- /dev/null
+++ b/doc/man3/OSSL_DECODER_CTX_new_for_pkey.pod
@@ -0,0 +1,145 @@
+=pod
+
+=head1 NAME
+
+OSSL_DECODER_CTX_new_for_pkey,
+OSSL_DECODER_CTX_set_passphrase,
+OSSL_DECODER_CTX_set_pem_password_cb,
+OSSL_DECODER_CTX_set_passphrase_ui,
+OSSL_DECODER_CTX_set_passphrase_cb
+- Decoder routines to decode EVP_PKEYs
+
+=head1 SYNOPSIS
+
+ #include <openssl/decoder.h>
+
+ OSSL_DECODER_CTX *
+ OSSL_DECODER_CTX_new_for_pkey(EVP_PKEY **pkey,
+ const char *input_type,
+ const char *input_struct,
+ const char *keytype, int selection,
+ OSSL_LIB_CTX *libctx, const char *propquery);
+
+ int OSSL_DECODER_CTX_set_passphrase(OSSL_DECODER_CTX *ctx,
+ const unsigned char *kstr,
+ size_t klen);
+ int OSSL_DECODER_CTX_set_pem_password_cb(OSSL_DECODER_CTX *ctx,
+ pem_password_cb *cb,
+ void *cbarg);
+ int OSSL_DECODER_CTX_set_passphrase_ui(OSSL_DECODER_CTX *ctx,
+ const UI_METHOD *ui_method,
+ void *ui_data);
+ int OSSL_DECODER_CTX_set_passphrase_cb(OSSL_DECODER_CTX *ctx,
+ OSSL_PASSPHRASE_CALLBACK *cb,
+ void *cbarg);
+
+=head1 DESCRIPTION
+
+OSSL_DECODER_CTX_new_for_pkey() is a utility function that creates a
+B<OSSL_DECODER_CTX>, finds all applicable decoder implementations and sets
+them up, so all the caller has to do next is call functions like
+L<OSSL_DECODER_from_bio(3)>. The caller may use the optional I<input_type>,
+I<input_struct>, I<keytype> and I<selection> to specify what the input is
+expected to contain. The I<pkey> must reference an B<EVP_PKEY *> variable
+that will be set to the newly created B<EVP_PKEY> on succesfull decoding.
+The referenced variable must be initialized to NULL before calling the
+function.
+
+Internally OSSL_DECODER_CTX_new_for_pkey() searches for all available
+L<EVP_KEYMGMT(3)> implementations, and then builds a list of all potential
+decoder implementations that may be able to process the encoded input into
+data suitable for B<EVP_PKEY>s. All these implementations are implicitly
+fetched using I<libctx> and I<propquery>.
+
+The search of decoder implementations can be limited with I<input_type> and
+I<input_struct> which specifies a starting input type and input structure.
+NULL is valid for both of them and signifies that the decoder implementations
+will find out the input type on their own.
+They are set with L<OSSL_DECODER_CTX_set_input_type(3)> and
+L<OSSL_DECODER_CTX_set_input_structure(3)>.
+See L</Input Types> and L</Input Structures> below for further information.
+
+The search of decoder implementations can also be limited with I<keytype>
+and I<selection>, which specifies the expected resulting keytype and contents.
+NULL and zero are valid and signify that the decoder implementations will
+find out the keytype and key contents on their own from the input they get.
+
+If no suitable decoder implementation is found,
+OSSL_DECODER_CTX_new_for_pkey() still creates a B<OSSL_DECODER_CTX>, but
+with no associated decoder (L<OSSL_DECODER_CTX_get_num_decoders(3)> returns
+zero). This helps the caller to distinguish between an error when creating
+the B<OSSL_ENCODER_CTX> and missing encoder implementation, and allows it to
+act accordingly.
+
+OSSL_DECODER_CTX_set_passphrase() gives the implementation a pass phrase to
+use when decrypting the encoded private key. Alternatively, a pass phrase
+callback may be specified with the following functions.
+
+OSSL_DECODER_CTX_set_pem_password_cb(), OSSL_DECODER_CTX_set_passphrase_ui()
+and OSSL_DECODER_CTX_set_passphrase_cb() set up a callback method that the
+implementation can use to prompt for a pass phrase, giving the caller the
+choice of preferred pass phrase callback form. These are called indirectly,
+through an internal L<OSSL_PASSPHRASE_CALLBACK(3)> function.
+
+The internal L<OSSL_PASSPHRASE_CALLBACK(3)> function caches the pass phrase, to
+be re-used in all decodings that are performed in the same decoding run (for
+example, within one L<OSSL_DECODER_from_bio(3)> call).
+
+=head2 Input Types
+
+Available input types depend on the implementations that available providers
+offer, and provider documentation should have the details.
+
+Among the known input types that OpenSSL decoder implementations offer
+for B<EVP_PKEY>s are C<DER>, C<PEM>, C<MSBLOB> and C<PVK>.
+See L<openssl-glossary(7)> for further information on what these input
+types mean.
+
+=head2 Input Structures
+
+Available input structures depend on the implementations that available
+providers offer, and provider documentation should have the details.
+
+Among the known input structures that OpenSSL decoder implementations
+offer for B<EVP_PKEY>s are C<pkcs8> and C<SubjectPublicKeyInfo>.
+
+OpenSSL decoder implementations also support the input structure
+C<type-specific>. This is the structure used for keys encoded
+according to key type specific specifications. For example, RSA keys
+encoded according to PKCS#1.
+
+=head2 Selections
+
+I<selection> can be any one of the values described in
+L<EVP_PKEY_fromdata(3)/Selections>.
+Additionally I<selection> can also be set to B<0> to indicate that the code will
+auto detect the selection.
+
+=head1 RETURN VALUES
+
+OSSL_DECODER_CTX_new_for_pkey() returns a pointer to a
+B<OSSL_DECODER_CTX>, or NULL if it couldn't be created.
+
+OSSL_DECODER_CTX_set_passphrase(), OSSL_DECODER_CTX_set_pem_password_cb(),
+OSSL_DECODER_CTX_set_passphrase_ui() and
+OSSL_DECODER_CTX_set_passphrase_cb() all return 1 on success, or 0 on
+failure.
+
+=head1 SEE ALSO
+
+L<provider(7)>, L<OSSL_DECODER(3)>, L<OSSL_DECODER_CTX(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_DECODER_from_bio.pod b/doc/man3/OSSL_DECODER_from_bio.pod
new file mode 100644
index 000000000000..5118dee9ac8b
--- /dev/null
+++ b/doc/man3/OSSL_DECODER_from_bio.pod
@@ -0,0 +1,120 @@
+=pod
+
+=head1 NAME
+
+OSSL_DECODER_from_data,
+OSSL_DECODER_from_bio,
+OSSL_DECODER_from_fp
+- Routines to perform a decoding
+
+=head1 SYNOPSIS
+
+ #include <openssl/decoder.h>
+
+ int OSSL_DECODER_from_bio(OSSL_DECODER_CTX *ctx, BIO *in);
+ int OSSL_DECODER_from_fp(OSSL_DECODER_CTX *ctx, FILE *fp);
+ int OSSL_DECODER_from_data(OSSL_DECODER_CTX *ctx, const unsigned char **pdata,
+ size_t *pdata_len);
+
+Feature availability macros:
+
+=over 4
+
+=item OSSL_DECODER_from_fp() is only available when B<OPENSSL_NO_STDIO>
+is undefined.
+
+=back
+
+=head1 DESCRIPTION
+
+OSSL_DECODER_from_data() runs the decoding process for the context I<ctx>,
+with input coming from I<*pdata>, I<*pdata_len> bytes long. Both I<*pdata>
+and I<*pdata_len> must be non-NULL. When OSSL_DECODER_from_data() returns,
+I<*pdata> is updated to point at the location after what has been decoded,
+and I<*pdata_len> to have the number of remaining bytes.
+
+OSSL_DECODER_from_bio() runs the decoding process for the context I<ctx>,
+with the input coming from the B<BIO> I<in>. Should it make a difference,
+it's recommended to have the BIO set in binary mode rather than text mode.
+
+OSSL_DECODER_from_fp() does the same thing as OSSL_DECODER_from_bio(),
+except that the input is coming from the B<FILE> I<fp>.
+
+=head1 RETURN VALUES
+
+OSSL_DECODER_from_bio() and OSSL_DECODER_from_fp() return 1 on success, or 0
+on failure.
+
+=head1 EXAMPLES
+
+To decode an RSA key encoded with PEM from a bio:
+
+ OSSL_DECODER_CTX *dctx;
+ EVP_PKEY *pkey = NULL;
+ const char *format = "PEM"; /* NULL for any format */
+ const char *structure = NULL; /* any structure */
+ const char *keytype = "RSA"; /* NULL for any key */
+ const unsigned char *pass = "my password";
+
+ dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, format, structure,
+ keytype,
+ OSSL_KEYMGMT_SELECT_KEYPAIR,
+ NULL, NULL);
+ if (dctx == NULL) {
+ /* error: no suitable potential decoders found */
+ }
+ if (pass != NULL)
+ OSSL_DECODER_CTX_set_passphrase(dctx, pass, strlen(pass));
+ if (OSSL_DECODER_from_bio(dctx, bio)) {
+ /* pkey is created with the decoded data from the bio */
+ } else {
+ /* decoding failure */
+ }
+ OSSL_DECODER_CTX_free(dctx);
+
+To decode an EC key encoded with DER from a buffer:
+
+ OSSL_DECODER_CTX *dctx;
+ EVP_PKEY *pkey = NULL;
+ const char *format = "DER"; /* NULL for any format */
+ const char *structure = NULL; /* any structure */
+ const char *keytype = "EC"; /* NULL for any key */
+ const unsigned char *pass = NULL
+ const unsigned char *data = buffer;
+ size_t datalen = sizeof(buffer);
+
+ dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, format, structure,
+ keytype,
+ OSSL_KEYMGMT_SELECT_KEYPAIR
+ | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ NULL, NULL);
+ if (dctx == NULL) {
+ /* error: no suitable potential decoders found */
+ }
+ if (pass != NULL)
+ OSSL_DECODER_CTX_set_passphrase(dctx, pass, strlen(pass));
+ if (OSSL_DECODER_from_data(dctx, &data, &datalen)) {
+ /* pkey is created with the decoded data from the buffer */
+ } else {
+ /* decoding failure */
+ }
+ OSSL_DECODER_CTX_free(dctx);
+
+=head1 SEE ALSO
+
+L<provider(7)>, L<OSSL_DECODER_CTX(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_DISPATCH.pod b/doc/man3/OSSL_DISPATCH.pod
new file mode 100644
index 000000000000..1aca4019dcbc
--- /dev/null
+++ b/doc/man3/OSSL_DISPATCH.pod
@@ -0,0 +1,81 @@
+=pod
+
+=head1 NAME
+
+OSSL_DISPATCH - OpenSSL Core type to define a dispatchable function table
+
+=head1 SYNOPSIS
+
+ #include <openssl/core.h>
+
+ typedef struct ossl_dispatch_st OSSL_DISPATCH;
+ struct ossl_dispatch_st {
+ int function_id;
+ void (*function)(void);
+ };
+
+=head1 DESCRIPTION
+
+This type is a tuple of function identity and function pointer.
+Arrays of this type are passed between the OpenSSL libraries and the
+providers to describe what functionality one side provides to the other.
+
+Arrays of this type must be terminated with a tuple having function identity
+zero and function pointer NULL.
+
+=head2 B<OSSL_DISPATCH> fields
+
+=over 4
+
+=item I<function_id>
+
+OpenSSL defined function identity of the implemented function.
+
+=item I<function>
+
+Pointer to the implemented function itself. Despite the generic definition
+of this field, the implemented function it points to must have a function
+signature that corresponds to the I<function_id>
+
+=back
+
+Available function identities and corresponding function signatures are
+defined in L<openssl-core_dispatch.h(7)>.
+Furthermore, the chosen function identities and associated function
+signature must be chosen specifically for the operation that it's intended
+for, as determined by the intended L<OSSL_ALGORITHM(3)> array.
+
+Any function identity not recognised by the recipient of this type
+will be ignored.
+This ensures that providers built with one OpenSSL version in mind
+will work together with any other OpenSSL version that supports this
+mechanism.
+
+=begin comment RETURN VALUES doesn't make sense for a manual that only
+describes a type, but document checkers still want that section, and
+to have more than just the section title.
+
+=head1 RETURN VALUES
+
+txt
+
+=end comment
+
+=head1 SEE ALSO
+
+L<crypto(7)>, L<openssl-core_dispatch.h(7)>, L<OSSL_ALGORITHM(3)>
+
+=head1 HISTORY
+
+B<OSSL_DISPATCH> was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_ENCODER.pod b/doc/man3/OSSL_ENCODER.pod
new file mode 100644
index 000000000000..cfabba2e1d02
--- /dev/null
+++ b/doc/man3/OSSL_ENCODER.pod
@@ -0,0 +1,144 @@
+=pod
+
+=head1 NAME
+
+OSSL_ENCODER,
+OSSL_ENCODER_fetch,
+OSSL_ENCODER_up_ref,
+OSSL_ENCODER_free,
+OSSL_ENCODER_get0_provider,
+OSSL_ENCODER_get0_properties,
+OSSL_ENCODER_is_a,
+OSSL_ENCODER_get0_name,
+OSSL_ENCODER_get0_description,
+OSSL_ENCODER_do_all_provided,
+OSSL_ENCODER_names_do_all,
+OSSL_ENCODER_gettable_params,
+OSSL_ENCODER_get_params
+- Encoder method routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/encoder.h>
+
+ typedef struct ossl_encoder_st OSSL_ENCODER;
+
+ OSSL_ENCODER *OSSL_ENCODER_fetch(OSSL_LIB_CTX *ctx, const char *name,
+ const char *properties);
+ int OSSL_ENCODER_up_ref(OSSL_ENCODER *encoder);
+ void OSSL_ENCODER_free(OSSL_ENCODER *encoder);
+ const OSSL_PROVIDER *OSSL_ENCODER_get0_provider(const OSSL_ENCODER *encoder);
+ const char *OSSL_ENCODER_get0_properties(const OSSL_ENCODER *encoder);
+ int OSSL_ENCODER_is_a(const OSSL_ENCODER *encoder, const char *name);
+ const char *OSSL_ENCODER_get0_name(const OSSL_ENCODER *encoder);
+ const char *OSSL_ENCODER_get0_description(const OSSL_ENCODER *encoder);
+ void OSSL_ENCODER_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(OSSL_ENCODER *encoder, void *arg),
+ void *arg);
+ int OSSL_ENCODER_names_do_all(const OSSL_ENCODER *encoder,
+ void (*fn)(const char *name, void *data),
+ void *data);
+ const OSSL_PARAM *OSSL_ENCODER_gettable_params(OSSL_ENCODER *encoder);
+ int OSSL_ENCODER_get_params(OSSL_ENCODER_CTX *ctx, const OSSL_PARAM params[]);
+
+=head1 DESCRIPTION
+
+B<OSSL_ENCODER> is a method for encoders, which know how to
+encode an object of some kind to a encoded form, such as PEM,
+DER, or even human readable text.
+
+OSSL_ENCODER_fetch() looks for an algorithm within the provider that
+has been loaded into the B<OSSL_LIB_CTX> given by I<ctx>, having the
+name given by I<name> and the properties given by I<properties>.
+The I<name> determines what type of object the fetched encoder
+method is expected to be able to encode, and the properties are
+used to determine the expected output type.
+For known properties and the values they may have, please have a look
+in L<provider-encoder(7)/Names and properties>.
+
+OSSL_ENCODER_up_ref() increments the reference count for the given
+I<encoder>.
+
+OSSL_ENCODER_free() decrements the reference count for the given
+I<encoder>, and when the count reaches zero, frees it.
+
+OSSL_ENCODER_get0_provider() returns the provider of the given
+I<encoder>.
+
+OSSL_ENCODER_get0_properties() returns the property definition associated
+with the given I<encoder>.
+
+OSSL_ENCODER_is_a() checks if I<encoder> is an implementation of an
+algorithm that's identifiable with I<name>.
+
+OSSL_ENCODER_get0_name() returns the name used to fetch the given I<encoder>.
+
+OSSL_ENCODER_get0_description() returns a description of the I<loader>, meant
+for display and human consumption. The description is at the discretion of the
+I<loader> implementation.
+
+OSSL_ENCODER_names_do_all() traverses all names for the given
+I<encoder>, and calls I<fn> with each name and I<data> as arguments.
+
+OSSL_ENCODER_do_all_provided() traverses all encoder
+implementations by all activated providers in the library context
+I<libctx>, and for each of the implementations, calls I<fn> with the
+implementation method and I<arg> as arguments.
+
+OSSL_ENCODER_gettable_params() returns an L<OSSL_PARAM(3)>
+array of parameter descriptors.
+
+OSSL_ENCODER_get_params() attempts to get parameters specified
+with an L<OSSL_PARAM(3)> array I<params>. Parameters that the
+implementation doesn't recognise should be ignored.
+
+=head1 RETURN VALUES
+
+OSSL_ENCODER_fetch() returns a pointer to the key management
+implementation represented by an OSSL_ENCODER object, or NULL on
+error.
+
+OSSL_ENCODER_up_ref() returns 1 on success, or 0 on error.
+
+OSSL_ENCODER_free() doesn't return any value.
+
+OSSL_ENCODER_get0_provider() returns a pointer to a provider object, or
+NULL on error.
+
+OSSL_ENCODER_get0_properties() returns a pointer to a property
+definition string, or NULL on error.
+
+OSSL_ENCODER_is_a() returns 1 of I<encoder> was identifiable,
+otherwise 0.
+
+OSSL_ENCODER_get0_name() returns the algorithm name from the provided
+implementation for the given I<encoder>. Note that the I<encoder> may have
+multiple synonyms associated with it. In this case the first name from the
+algorithm definition is returned. Ownership of the returned string is retained
+by the I<encoder> object and should not be freed by the caller.
+
+OSSL_ENCODER_get0_description() returns a pointer to a decription, or NULL if
+there isn't one.
+
+OSSL_ENCODER_names_do_all() returns 1 if the callback was called for all
+names. A return value of 0 means that the callback was not called for any names.
+
+=head1 SEE ALSO
+
+L<provider(7)>, L<OSSL_ENCODER_CTX(3)>, L<OSSL_ENCODER_to_bio(3)>,
+L<OSSL_ENCODER_CTX_new_for_pkey(3)>, L<OSSL_LIB_CTX(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_ENCODER_CTX.pod b/doc/man3/OSSL_ENCODER_CTX.pod
new file mode 100644
index 000000000000..2d7a6a298f85
--- /dev/null
+++ b/doc/man3/OSSL_ENCODER_CTX.pod
@@ -0,0 +1,221 @@
+=pod
+
+=head1 NAME
+
+OSSL_ENCODER_CTX,
+OSSL_ENCODER_CTX_new,
+OSSL_ENCODER_settable_ctx_params,
+OSSL_ENCODER_CTX_set_params,
+OSSL_ENCODER_CTX_free,
+OSSL_ENCODER_CTX_set_selection,
+OSSL_ENCODER_CTX_set_output_type,
+OSSL_ENCODER_CTX_set_output_structure,
+OSSL_ENCODER_CTX_add_encoder,
+OSSL_ENCODER_CTX_add_extra,
+OSSL_ENCODER_CTX_get_num_encoders,
+OSSL_ENCODER_INSTANCE,
+OSSL_ENCODER_INSTANCE_get_encoder,
+OSSL_ENCODER_INSTANCE_get_encoder_ctx,
+OSSL_ENCODER_INSTANCE_get_output_type,
+OSSL_ENCODER_INSTANCE_get_output_structure,
+OSSL_ENCODER_CONSTRUCT,
+OSSL_ENCODER_CLEANUP,
+OSSL_ENCODER_CTX_set_construct,
+OSSL_ENCODER_CTX_set_construct_data,
+OSSL_ENCODER_CTX_set_cleanup
+- Encoder context routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/encoder.h>
+
+ typedef struct ossl_encoder_ctx_st OSSL_ENCODER_CTX;
+
+ OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new();
+ const OSSL_PARAM *OSSL_ENCODER_settable_ctx_params(OSSL_ENCODER *encoder);
+ int OSSL_ENCODER_CTX_set_params(OSSL_ENCODER_CTX *ctx,
+ const OSSL_PARAM params[]);
+ void OSSL_ENCODER_CTX_free(OSSL_ENCODER_CTX *ctx);
+
+ int OSSL_ENCODER_CTX_set_selection(OSSL_ENCODER_CTX *ctx, int selection);
+ int OSSL_ENCODER_CTX_set_output_type(OSSL_ENCODER_CTX *ctx,
+ const char *output_type);
+ int OSSL_ENCODER_CTX_set_output_structure(OSSL_ENCODER_CTX *ctx,
+ const char *output_structure);
+
+ int OSSL_ENCODER_CTX_add_encoder(OSSL_ENCODER_CTX *ctx, OSSL_ENCODER *encoder);
+ int OSSL_ENCODER_CTX_add_extra(OSSL_ENCODER_CTX *ctx,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ int OSSL_ENCODER_CTX_get_num_encoders(OSSL_ENCODER_CTX *ctx);
+
+ typedef struct ossl_encoder_instance_st OSSL_ENCODER_INSTANCE;
+ OSSL_ENCODER *
+ OSSL_ENCODER_INSTANCE_get_encoder(OSSL_ENCODER_INSTANCE *encoder_inst);
+ void *
+ OSSL_ENCODER_INSTANCE_get_encoder_ctx(OSSL_ENCODER_INSTANCE *encoder_inst);
+ const char *
+ OSSL_ENCODER_INSTANCE_get_output_type(OSSL_ENCODER_INSTANCE *encoder_inst);
+ const char *
+ OSSL_ENCODER_INSTANCE_get_output_structure(OSSL_ENCODER_INSTANCE *encoder_inst);
+
+ typedef const void *OSSL_ENCODER_CONSTRUCT(OSSL_ENCODER_INSTANCE *encoder_inst,
+ void *construct_data);
+ typedef void OSSL_ENCODER_CLEANUP(void *construct_data);
+
+ int OSSL_ENCODER_CTX_set_construct(OSSL_ENCODER_CTX *ctx,
+ OSSL_ENCODER_CONSTRUCT *construct);
+ int OSSL_ENCODER_CTX_set_construct_data(OSSL_ENCODER_CTX *ctx,
+ void *construct_data);
+ int OSSL_ENCODER_CTX_set_cleanup(OSSL_ENCODER_CTX *ctx,
+ OSSL_ENCODER_CLEANUP *cleanup);
+
+=head1 DESCRIPTION
+
+Encoding an input object to the desired encoding may be done with a chain of
+encoder implementations, which means that the output from one encoder may be
+the input for the next in the chain. The B<OSSL_ENCODER_CTX> holds all the
+data about these encoders. This allows having generic format encoders such
+as DER to PEM, as well as more specialized encoders like RSA to DER.
+
+The final output type must be given, and a chain of encoders must end with
+an implementation that produces that output type.
+
+At the beginning of the encoding process, a contructor provided by the
+caller is called to ensure that there is an appropriate provider-side object
+to start with.
+The constructor is set with OSSL_ENCODER_CTX_set_construct().
+
+B<OSSL_ENCODER_INSTANCE> is an opaque structure that contains data about the
+encoder that is going to be used, and that may be useful for the
+constructor. There are some functions to extract data from this type,
+described in L</Constructor> below.
+
+=head2 Functions
+
+OSSL_ENCODER_CTX_new() creates a B<OSSL_ENCODER_CTX>.
+
+OSSL_ENCODER_settable_ctx_params() returns an L<OSSL_PARAM(3)>
+array of parameter descriptors.
+
+OSSL_ENCODER_CTX_set_params() attempts to set parameters specified
+with an L<OSSL_PARAM(3)> array I<params>. Parameters that the
+implementation doesn't recognise should be ignored.
+
+OSSL_ENCODER_CTX_free() frees the given context I<ctx>.
+
+OSSL_ENCODER_CTX_add_encoder() populates the B<OSSL_ENCODER_CTX>
+I<ctx> with a encoder, to be used to encode an input object.
+
+OSSL_ENCODER_CTX_add_extra() finds encoders that further encodes output
+from already added encoders, and adds them as well. This is used to build
+encoder chains.
+
+OSSL_ENCODER_CTX_set_output_type() sets the ending output type. This must
+be specified, and determines if a complete encoder chain is available.
+
+OSSL_ENCODER_CTX_set_output_structure() sets the desired output structure.
+This may be used to determines what encoder implementations may be used.
+Depending on the type of object being encoded, the output structure may
+not be relevant.
+
+OSSL_ENCODER_CTX_get_num_encoders() gets the number of encoders currently
+added to the context I<ctx>.
+
+OSSL_ENCODER_CTX_set_construct() sets the constructor I<construct>.
+
+OSSL_ENCODER_CTX_set_construct_data() sets the constructor data that is
+passed to the constructor every time it's called.
+
+OSSL_ENCODER_CTX_set_cleanup() sets the constructor data I<cleanup>
+function. This is called by L<OSSL_ENCODER_CTX_free(3)>.
+
+=head2 Constructor
+
+A B<OSSL_ENCODER_CONSTRUCT> gets the following arguments:
+
+=over 4
+
+=item I<encoder_inst>
+
+The B<OSSL_ENCODER_INSTANCE> for the encoder from which the constructor gets
+its data.
+
+=item I<construct_data>
+
+The pointer that was set with OSSL_ENCODE_CTX_set_construct_data().
+
+=back
+
+The constructor is expected to return a valid (non-NULL) pointer to a
+provider-native object that can be used as first input of an encoding chain,
+or NULL to indicate that an error has occured.
+
+These utility functions may be used by a constructor:
+
+OSSL_ENCODER_INSTANCE_get_encoder() can be used to get the encoder
+implementation of the encoder instance I<encoder_inst>.
+
+OSSL_ENCODER_INSTANCE_get_encoder_ctx() can be used to get the encoder
+implementation's provider context of the encoder instance I<encoder_inst>.
+
+OSSL_ENCODER_INSTANCE_get_output_type() can be used to get the output type
+for the encoder implementation of the encoder instance I<encoder_inst>.
+This will never be NULL.
+
+OSSL_ENCODER_INSTANCE_get_output_structure() can be used to get the output
+structure for the encoder implementation of the encoder instance
+I<encoder_inst>.
+This may be NULL.
+
+=head1 RETURN VALUES
+
+OSSL_ENCODER_CTX_new() returns a pointer to a B<OSSL_ENCODER_CTX>, or NULL
+if the context structure couldn't be allocated.
+
+OSSL_ENCODER_settable_ctx_params() returns an L<OSSL_PARAM(3)> array, or
+NULL if none is available.
+
+OSSL_ENCODER_CTX_set_params() returns 1 if all recognised parameters were
+valid, or 0 if one of them was invalid or caused some other failure in the
+implementation.
+
+OSSL_ENCODER_CTX_add_encoder(), OSSL_ENCODER_CTX_add_extra(),
+OSSL_ENCODER_CTX_set_construct(), OSSL_ENCODER_CTX_set_construct_data() and
+OSSL_ENCODER_CTX_set_cleanup() return 1 on success, or 0 on failure.
+
+OSSL_ENCODER_CTX_get_num_encoders() returns the current number of encoders.
+It returns 0 if I<ctx> is NULL.
+
+OSSL_ENCODER_INSTANCE_get_encoder() returns an B<OSSL_ENCODER> pointer on
+success, or NULL on failure.
+
+OSSL_ENCODER_INSTANCE_get_encoder_ctx() returns a provider context pointer on
+success, or NULL on failure.
+
+OSSL_ENCODER_INSTANCE_get_output_type() returns a string with the name of the
+input type, if relevant. NULL is a valid returned value.
+
+OSSL_ENCODER_INSTANCE_get_output_type() returns a string with the name of the
+output type.
+
+OSSL_ENCODER_INSTANCE_get_output_structure() returns a string with the name
+of the output structure.
+
+=head1 SEE ALSO
+
+L<provider(7)>, L<OSSL_ENCODER(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_ENCODER_CTX_new_for_pkey.pod b/doc/man3/OSSL_ENCODER_CTX_new_for_pkey.pod
new file mode 100644
index 000000000000..8ba3bdd46718
--- /dev/null
+++ b/doc/man3/OSSL_ENCODER_CTX_new_for_pkey.pod
@@ -0,0 +1,146 @@
+=pod
+
+=head1 NAME
+
+OSSL_ENCODER_CTX_new_for_pkey,
+OSSL_ENCODER_CTX_set_cipher,
+OSSL_ENCODER_CTX_set_passphrase,
+OSSL_ENCODER_CTX_set_pem_password_cb,
+OSSL_ENCODER_CTX_set_passphrase_cb,
+OSSL_ENCODER_CTX_set_passphrase_ui
+- Encoder routines to encode EVP_PKEYs
+
+=head1 SYNOPSIS
+
+ #include <openssl/encoder.h>
+
+ OSSL_ENCODER_CTX *
+ OSSL_ENCODER_CTX_new_for_pkey(const EVP_PKEY *pkey, int selection,
+ const char *output_type,
+ const char *output_structure,
+ const char *propquery);
+
+ int OSSL_ENCODER_CTX_set_cipher(OSSL_ENCODER_CTX *ctx,
+ const char *cipher_name,
+ const char *propquery);
+ int OSSL_ENCODER_CTX_set_passphrase(OSSL_ENCODER_CTX *ctx,
+ const unsigned char *kstr,
+ size_t klen);
+ int OSSL_ENCODER_CTX_set_pem_password_cb(OSSL_ENCODER_CTX *ctx,
+ pem_password_cb *cb, void *cbarg);
+ int OSSL_ENCODER_CTX_set_passphrase_ui(OSSL_ENCODER_CTX *ctx,
+ const UI_METHOD *ui_method,
+ void *ui_data);
+ int OSSL_ENCODER_CTX_set_passphrase_cb(OSSL_ENCODER_CTX *ctx,
+ OSSL_PASSPHRASE_CALLBACK *cb,
+ void *cbarg);
+
+=head1 DESCRIPTION
+
+OSSL_ENCODER_CTX_new_for_pkey() is a utility function that creates a
+B<OSSL_ENCODER_CTX>, finds all applicable encoder implementations and sets
+them up, so almost all the caller has to do next is call functions like
+L<OSSL_ENCODER_to_bio(3)>. I<output_type> determines the final output
+encoding, and I<selection> can be used to select what parts of the I<pkey>
+should be included in the output. I<output_type> is further discussed in
+L</Output types> below, and I<selection> is further described in
+L</Selections>.
+
+Internally, OSSL_ENCODER_CTX_new_for_pkey() uses the names from the
+L<EVP_KEYMGMT(3)> implementation associated with I<pkey> to build a list of
+applicable encoder implementations that are used to process the I<pkey> into
+the encoding named by I<output_type>, with the outermost structure named by
+I<output_structure> if that's relevant. All these implementations are
+implicitly fetched, with I<propquery> for finer selection.
+
+If no suitable encoder implementation is found,
+OSSL_ENCODER_CTX_new_for_pkey() still creates a B<OSSL_ENCODER_CTX>, but
+with no associated encoder (L<OSSL_ENCODER_CTX_get_num_encoders(3)> returns
+zero). This helps the caller to distinguish between an error when creating
+the B<OSSL_ENCODER_CTX> and missing encoder implementation, and allows it to
+act accordingly.
+
+OSSL_ENCODER_CTX_set_cipher() tells the implementation what cipher
+should be used to encrypt encoded keys. The cipher is given by
+name I<cipher_name>. The interpretation of that I<cipher_name> is
+implementation dependent. The implementation may implement the cipher
+directly itself or by other implementations, or it may choose to fetch
+it. If the implementation supports fetching the cipher, then it may
+use I<propquery> as properties to be queried for when fetching.
+I<cipher_name> may also be NULL, which will result in unencrypted
+encoding.
+
+OSSL_ENCODER_CTX_set_passphrase() gives the implementation a
+pass phrase to use when encrypting the encoded private key.
+Alternatively, a pass phrase callback may be specified with the
+following functions.
+
+OSSL_ENCODER_CTX_set_pem_password_cb(), OSSL_ENCODER_CTX_set_passphrase_ui()
+and OSSL_ENCODER_CTX_set_passphrase_cb() sets up a callback method that the
+implementation can use to prompt for a pass phrase, giving the caller the
+choice of preferred pass phrase callback form. These are called indirectly,
+through an internal L<OSSL_PASSPHRASE_CALLBACK(3)> function.
+
+=head2 Output types
+
+The possible B<EVP_PKEY> output types depends on the available
+implementations.
+
+OpenSSL has built in implementations for the following output types:
+
+=over 4
+
+=item C<TEXT>
+
+The output is a human readable description of the key.
+L<EVP_PKEY_print_private(3)>, L<EVP_PKEY_print_public(3)> and
+L<EVP_PKEY_print_params(3)> use this for their output.
+
+=item C<DER>
+
+The output is the DER encoding of the I<selection> of the I<pkey>.
+
+=item C<PEM>
+
+The output is the I<selection> of the I<pkey> in PEM format.
+
+=back
+
+=head2 Selections
+
+I<selection> can be any one of the values described in
+L<EVP_PKEY_fromdata(3)/Selections>.
+
+These are only 'hints' since the encoder implementations are free to
+determine what makes sense to include in the output, and this may depend on
+the desired output. For example, an EC key in a PKCS#8 structure doesn't
+usually include the public key.
+
+=head1 RETURN VALUES
+
+OSSL_ENCODER_CTX_new_for_pkey() returns a pointer to an B<OSSL_ENCODER_CTX>,
+or NULL if it couldn't be created.
+
+OSSL_ENCODER_CTX_set_cipher(), OSSL_ENCODER_CTX_set_passphrase(),
+OSSL_ENCODER_CTX_set_pem_password_cb(), OSSL_ENCODER_CTX_set_passphrase_ui()
+and OSSL_ENCODER_CTX_set_passphrase_cb() all return 1 on success, or 0 on
+failure.
+
+=head1 SEE ALSO
+
+L<provider(7)>, L<OSSL_ENCODER(3)>, L<OSSL_ENCODER_CTX(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_ENCODER_to_bio.pod b/doc/man3/OSSL_ENCODER_to_bio.pod
new file mode 100644
index 000000000000..237e29b0b38b
--- /dev/null
+++ b/doc/man3/OSSL_ENCODER_to_bio.pod
@@ -0,0 +1,133 @@
+=pod
+
+=head1 NAME
+
+OSSL_ENCODER_to_data,
+OSSL_ENCODER_to_bio,
+OSSL_ENCODER_to_fp
+- Routines to perform an encoding
+
+=head1 SYNOPSIS
+
+ #include <openssl/encoder.h>
+
+ int OSSL_ENCODER_to_data(OSSL_ENCODER_CTX *ctx, unsigned char **pdata,
+ size_t *pdata_len);
+ int OSSL_ENCODER_to_bio(OSSL_ENCODER_CTX *ctx, BIO *out);
+ int OSSL_ENCODER_to_fp(OSSL_ENCODER_CTX *ctx, FILE *fp);
+
+Feature availability macros:
+
+=over 4
+
+=item OSSL_ENCODER_to_fp() is only available when B<OPENSSL_NO_STDIO>
+is undefined.
+
+=back
+
+=head1 DESCRIPTION
+
+OSSL_ENCODER_to_data() runs the encoding process for the context I<ctx>,
+with the output going to the I<*pdata> and I<*pdata_len>.
+If I<*pdata> is NULL when OSSL_ENCODER_to_data() is called, a buffer will be
+allocated using L<OPENSSL_zalloc(3)>, and I<*pdata> will be set to point at
+the start of that buffer, and I<*pdata_len> will be assigned its length when
+OSSL_ENCODER_to_data() returns.
+If I<*pdata> is non-NULL when OSSL_ENCODER_to_data() is called, I<*pdata_len>
+is assumed to have its size. In this case, I<*pdata> will be set to point
+after the encoded bytes, and I<*pdata_len> will be assigned the number of
+remaining bytes.
+
+OSSL_ENCODER_to_bio() runs the encoding process for the context I<ctx>, with
+the output going to the B<BIO> I<out>.
+
+OSSL_ENCODER_to_fp() does the same thing as OSSL_ENCODER_to_bio(), except
+that the output is going to the B<FILE> I<fp>.
+
+=for comment Know your encoder!
+
+For OSSL_ENCODER_to_bio() and OSSL_ENCODER_to_fp(), the application is
+required to set up the B<BIO> or B<FILE> properly, for example to have
+it in text or binary mode as is appropriate for the encoder output type.
+
+=head1 RETURN VALUES
+
+OSSL_ENCODER_to_bio(), OSSL_ENCODER_to_fp() and OSSL_ENCODER_to_data()
+return 1 on success, or 0 on failure.
+
+=head1 EXAMPLES
+
+To encode a pkey as PKCS#8 with PEM format into a bio:
+
+ OSSL_ENCODER_CTX *ectx;
+ const char *format = "PEM";
+ const char *structure = "PrivateKeyInfo"; /* PKCS#8 structure */
+ const unsigned char *pass = "my password";
+
+ ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey,
+ OSSL_KEYMGMT_SELECT_KEYPAIR
+ | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ format, structure,
+ NULL);
+ if (ectx == NULL) {
+ /* error: no suitable potential encoders found */
+ }
+ if (pass != NULL)
+ OSSL_ENCODER_CTX_set_passphrase(ectx, pass, strlen(pass));
+ if (OSSL_ENCODER_to_bio(ectx, bio)) {
+ /* pkey was successfully encoded into the bio */
+ } else {
+ /* encoding failure */
+ }
+ OSSL_ENCODER_CTX_free(ectx);
+
+To encode a pkey as PKCS#8 with DER format encrypted with
+AES-256-CBC into a buffer:
+
+ OSSL_ENCODER_CTX *ectx;
+ const char *format = "DER";
+ const char *structure = "PrivateKeyInfo"; /* PKCS#8 structure */
+ const unsigned char *pass = "my password";
+ unsigned char *data = NULL;
+ size_t datalen;
+
+ ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey,
+ OSSL_KEYMGMT_SELECT_KEYPAIR
+ | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ format, structure,
+ NULL);
+ if (ectx == NULL) {
+ /* error: no suitable potential encoders found */
+ }
+ if (pass != NULL) {
+ OSSL_ENCODER_CTX_set_passphrase(ectx, pass, strlen(pass));
+ OSSL_ENCODER_CTX_set_cipher(ctx, "AES-256-CBC", NULL);
+ }
+ if (OSSL_ENCODER_to_data(ectx, &data, &datalen)) {
+ /*
+ * pkey was successfully encoded into a newly allocated
+ * data buffer
+ */
+ } else {
+ /* encoding failure */
+ }
+ OSSL_ENCODER_CTX_free(ectx);
+
+=head1 SEE ALSO
+
+L<provider(7)>, L<OSSL_ENCODER_CTX(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_ESS_check_signing_certs.pod b/doc/man3/OSSL_ESS_check_signing_certs.pod
new file mode 100644
index 000000000000..bff26193d758
--- /dev/null
+++ b/doc/man3/OSSL_ESS_check_signing_certs.pod
@@ -0,0 +1,88 @@
+=pod
+
+=head1 NAME
+
+OSSL_ESS_signing_cert_new_init,
+OSSL_ESS_signing_cert_v2_new_init,
+OSSL_ESS_check_signing_certs
+- Enhanced Security Services (ESS) functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/ess.h>
+
+ ESS_SIGNING_CERT *OSSL_ESS_signing_cert_new_init(const X509 *signcert,
+ const STACK_OF(X509) *certs,
+ int set_issuer_serial);
+ ESS_SIGNING_CERT_V2 *OSSL_ESS_signing_cert_v2_new_init(const EVP_MD *hash_alg,
+ const X509 *signcert,
+ const
+ STACK_OF(X509) *certs,
+ int set_issuer_serial);
+ int OSSL_ESS_check_signing_certs(const ESS_SIGNING_CERT *ss,
+ const ESS_SIGNING_CERT_V2 *ssv2,
+ const STACK_OF(X509) *chain,
+ int require_signing_cert);
+
+=head1 DESCRIPTION
+
+OSSL_ESS_signing_cert_new_init() generates a new B<ESS_SIGNING_CERT> structure
+referencing the given I<signcert> and any given further I<certs>
+using their SHA-1 fingerprints.
+If I<set_issuer_serial> is nonzero then also the issuer and serial number
+of I<signcert> are included in the B<ESS_CERT_ID> as the B<issuerSerial> field.
+For all members of I<certs> the B<issuerSerial> field is always included.
+
+OSSL_ESS_signing_cert_v2_new_init() is the same as
+OSSL_ESS_signing_cert_new_init() except that it uses the given I<hash_alg> and
+generates a B<ESS_SIGNING_CERT_V2> structure with B<ESS_CERT_ID_V2> elements.
+
+OSSL_ESS_check_signing_certs() checks if the validation chain I<chain> contains
+the certificates required by the identifiers given in I<ss> and/or I<ssv2>.
+If I<require_signing_cert> is nonzero, I<ss> or I<ssv2> must not be NULL.
+If both I<ss> and I<ssv2> are not NULL, they are evaluated independently.
+The list of certificate identifiers in I<ss> is of type B<ESS_CERT_ID>,
+while the list contained in I<ssv2> is of type B<ESS_CERT_ID_V2>.
+As far as these lists are present, they must be nonempty.
+The certificate identified by their first entry must be the first element of
+I<chain>, i.e. the signer certificate.
+Any further certficates referenced in the list must also be found in I<chain>.
+The matching is done using the given certificate hash algorithm and value.
+In addition to the checks required by RFCs 2624 and 5035,
+if the B<issuerSerial> field is included in an B<ESSCertID> or B<ESSCertIDv2>
+it must match the certificate issuer and serial number attributes.
+
+=head1 NOTES
+
+ESS has been defined in RFC 2634, which has been updated in RFC 5035
+(ESS version 2) to support hash algorithms other than SHA-1.
+This is used for TSP (RFC 3161) and CAdES-BES (informational RFC 5126).
+
+=head1 RETURN VALUES
+
+OSSL_ESS_signing_cert_new_init() and OSSL_ESS_signing_cert_v2_new_init()
+return a pointer to the new structure or NULL on malloc failure.
+
+OSSL_ESS_check_signing_certs() returns 1 on success,
+0 if a required certificate cannot be found, -1 on other error.
+
+=head1 SEE ALSO
+
+L<TS_VERIFY_CTX_set_certs(3)>,
+L<CMS_verify(3)>
+
+=head1 HISTORY
+
+OSSL_ESS_signing_cert_new_init(), OSSL_ESS_signing_cert_v2_new_init(), and
+OSSL_ESS_check_signing_certs() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_HTTP_REQ_CTX.pod b/doc/man3/OSSL_HTTP_REQ_CTX.pod
new file mode 100644
index 000000000000..fbe1a152b80c
--- /dev/null
+++ b/doc/man3/OSSL_HTTP_REQ_CTX.pod
@@ -0,0 +1,266 @@
+=pod
+
+=head1 NAME
+
+OSSL_HTTP_REQ_CTX,
+OSSL_HTTP_REQ_CTX_new,
+OSSL_HTTP_REQ_CTX_free,
+OSSL_HTTP_REQ_CTX_set_request_line,
+OSSL_HTTP_REQ_CTX_add1_header,
+OSSL_HTTP_REQ_CTX_set_expected,
+OSSL_HTTP_REQ_CTX_set1_req,
+OSSL_HTTP_REQ_CTX_nbio,
+OSSL_HTTP_REQ_CTX_nbio_d2i,
+OSSL_HTTP_REQ_CTX_exchange,
+OSSL_HTTP_REQ_CTX_get0_mem_bio,
+OSSL_HTTP_REQ_CTX_get_resp_len,
+OSSL_HTTP_REQ_CTX_set_max_response_length,
+OSSL_HTTP_is_alive
+- HTTP client low-level functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/http.h>
+
+ typedef struct ossl_http_req_ctx_st OSSL_HTTP_REQ_CTX;
+
+ OSSL_HTTP_REQ_CTX *OSSL_HTTP_REQ_CTX_new(BIO *wbio, BIO *rbio, int buf_size);
+ void OSSL_HTTP_REQ_CTX_free(OSSL_HTTP_REQ_CTX *rctx);
+
+ int OSSL_HTTP_REQ_CTX_set_request_line(OSSL_HTTP_REQ_CTX *rctx, int method_POST,
+ const char *server, const char *port,
+ const char *path);
+ int OSSL_HTTP_REQ_CTX_add1_header(OSSL_HTTP_REQ_CTX *rctx,
+ const char *name, const char *value);
+
+ int OSSL_HTTP_REQ_CTX_set_expected(OSSL_HTTP_REQ_CTX *rctx,
+ const char *content_type, int asn1,
+ int timeout, int keep_alive);
+ int OSSL_HTTP_REQ_CTX_set1_req(OSSL_HTTP_REQ_CTX *rctx, const char *content_type,
+ const ASN1_ITEM *it, const ASN1_VALUE *req);
+ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx);
+ int OSSL_HTTP_REQ_CTX_nbio_d2i(OSSL_HTTP_REQ_CTX *rctx,
+ ASN1_VALUE **pval, const ASN1_ITEM *it);
+ BIO *OSSL_HTTP_REQ_CTX_exchange(OSSL_HTTP_REQ_CTX *rctx);
+
+ BIO *OSSL_HTTP_REQ_CTX_get0_mem_bio(const OSSL_HTTP_REQ_CTX *rctx);
+ size_t OSSL_HTTP_REQ_CTX_get_resp_len(const OSSL_HTTP_REQ_CTX *rctx);
+ void OSSL_HTTP_REQ_CTX_set_max_response_length(OSSL_HTTP_REQ_CTX *rctx,
+ unsigned long len);
+
+ int OSSL_HTTP_is_alive(const OSSL_HTTP_REQ_CTX *rctx);
+
+=head1 DESCRIPTION
+
+B<OSSL_HTTP_REQ_CTX> is a context structure for an HTTP request and response,
+used to collect all the necessary data to perform that request.
+
+This file documents low-level HTTP functions rarely used directly. High-level
+HTTP client functions like L<OSSL_HTTP_get(3)> and L<OSSL_HTTP_transfer(3)>
+should be preferred.
+
+OSSL_HTTP_REQ_CTX_new() allocates a new HTTP request context structure,
+which gets populated with the B<BIO> to write/send the request to (I<wbio>),
+the B<BIO> to read/receive the response from (I<rbio>, which may be equal to
+I<wbio>), and the maximum expected response header line length I<buf_size>.
+A value <= 0 indicates that
+the B<OSSL_HTTP_DEFAULT_MAX_LINE_LEN> of 4KiB should be used.
+I<buf_size> is also used as the number of content bytes that are read at a time.
+The allocated context structure includes an internal memory B<BIO>,
+which collects the HTTP request header lines.
+
+OSSL_HTTP_REQ_CTX_free() frees up the HTTP request context I<rctx>.
+The I<rbio> is not free'd, I<wbio> will be free'd if I<free_wbio> is set.
+
+OSSL_HTTP_REQ_CTX_set_request_line() adds the HTTP request line to the context.
+The HTTP method is determined by I<method_POST>,
+which should be 1 to indicate C<POST> or 0 to indicate C<GET>.
+I<server> and I<port> may be set to indicate a proxy server and port
+that the request should go through, otherwise they should be left NULL.
+I<path> is the HTTP request path; if left NULL, C</> is used.
+
+OSSL_HTTP_REQ_CTX_add1_header() adds header I<name> with value I<value> to the
+context I<rctx>. It can be called more than once to add multiple header lines.
+For example, to add a C<Host> header for C<example.com> you would call:
+
+ OSSL_HTTP_REQ_CTX_add1_header(ctx, "Host", "example.com");
+
+OSSL_HTTP_REQ_CTX_set_expected() optionally sets in I<rctx> some expectations
+of the HTTP client on the response.
+Due to the structure of an HTTP request, if the I<keep_alive> argument is
+nonzero the function must be used before calling OSSL_HTTP_REQ_CTX_set1_req().
+If the I<content_type> parameter
+is not NULL then the client will check that the given content type string
+is included in the HTTP header of the response and return an error if not.
+If the I<asn1> parameter is nonzero a structure in ASN.1 encoding will be
+expected as the response content and input streaming is disabled. This means
+that an ASN.1 sequence header is required, its length field is checked, and
+OSSL_HTTP_REQ_CTX_get0_mem_bio() should be used to get the buffered response.
+Otherwise (by default) any input format is allowed without length checks.
+In this case the BIO given as I<rbio> argument to OSSL_HTTP_REQ_CTX_new() should
+be used directly to read the response contents, which may support streaming.
+If the I<timeout> parameter is > 0 this indicates the maximum number of seconds
+the subsequent HTTP transfer (sending the request and receiving a response)
+is allowed to take.
+I<timeout> == 0 enables waiting indefinitely, i.e., no timeout can occur.
+This is the default.
+I<timeout> < 0 takes over any value set via the I<overall_timeout> argument of
+L<OSSL_HTTP_open(3)> with the default being 0, which means no timeout.
+If the I<keep_alive> parameter is 0, which is the default, the connection is not
+kept open after receiving a response. This is the default behavior for HTTP 1.0.
+If the value is 1 or 2 then a persistent connection is requested.
+If the value is 2 then a persistent connection is required,
+i.e., an error occurs in case the server does not grant it.
+
+OSSL_HTTP_REQ_CTX_set1_req() finalizes the HTTP request context.
+It is needed if the I<method_POST> parameter in the
+OSSL_HTTP_REQ_CTX_set_request_line() call was 1
+and an ASN.1-encoded request should be sent.
+It must also be used when requesting "keep-alive",
+even if a GET request is going to be sent, in which case I<req> must be NULL.
+Unless I<req> is NULL, the function adds the DER encoding of I<req> using
+the ASN.1 template I<it> to do the encoding (which does not support streaming).
+The HTTP header C<Content-Length> is filled out with the length of the request.
+I<content_type> must be NULL if I<req> is NULL.
+If I<content_type> isn't NULL,
+the HTTP header C<Content-Type> is also added with the given string value.
+The header lines are added to the internal memory B<BIO> for the request header.
+
+OSSL_HTTP_REQ_CTX_nbio() attempts to send the request prepared in I<rctx>
+and to gather the response via HTTP, using the I<wbio> and I<rbio>
+that were given when calling OSSL_HTTP_REQ_CTX_new().
+The function may need to be called again if its result is -1, which indicates
+L<BIO_should_retry(3)>. In such a case it is advisable to sleep a little in
+between, using L<BIO_wait(3)> on the read BIO to prevent a busy loop.
+
+OSSL_HTTP_REQ_CTX_nbio_d2i() is like OSSL_HTTP_REQ_CTX_nbio() but on successs
+in addition parses the response, which must be a DER-encoded ASN.1 structure,
+using the ASN.1 template I<it> and places the result in I<*pval>.
+
+OSSL_HTTP_REQ_CTX_exchange() calls OSSL_HTTP_REQ_CTX_nbio() as often as needed
+in order to exchange a request and response or until a timeout is reached.
+On success it returns a pointer to the BIO that can be used to read the result.
+If an ASN.1-encoded response was expected, this is the BIO
+returned by OSSL_HTTP_REQ_CTX_get0_mem_bio() when called after the exchange.
+This memory BIO does not support streaming.
+Otherwise the returned BIO is the I<rbio> given to OSSL_HTTP_REQ_CTX_new(),
+which may support streaming.
+When this BIO is returned, it has been read past the end of the response header,
+such that the actual response body can be read from it.
+The returned BIO pointer MUST NOT be freed by the caller.
+
+OSSL_HTTP_REQ_CTX_get0_mem_bio() returns the internal memory B<BIO>.
+Before the HTTP request is sent, this could be used to adapt its header lines.
+I<Use with caution!>
+After receiving a response via HTTP, the BIO represents the current state of
+reading the response header. If the response was expected to be ASN.1 encoded,
+its contents can be read via this BIO, which does not support streaming.
+The returned BIO pointer must not be freed by the caller.
+
+OSSL_HTTP_REQ_CTX_get_resp_len() returns the size of the response contents
+in I<rctx> if provided by the server as <Content-Length> header field, else 0.
+
+OSSL_HTTP_REQ_CTX_set_max_response_length() sets the maximum allowed
+response content length for I<rctx> to I<len>. If not set or I<len> is 0
+then the B<OSSL_HTTP_DEFAULT_MAX_RESP_LEN> is used, which currently is 100 KiB.
+If the C<Content-Length> header is present and exceeds this value or
+the content is an ASN.1 encoded structure with a length exceeding this value
+or both length indications are present but disagree then an error occurs.
+
+OSSL_HTTP_is_alive() can be used to query if the HTTP connection
+given by I<rctx> is still alive, i.e., has not been closed.
+It returns 0 if I<rctx> is NULL.
+
+If the client application requested or required a persistent connection
+and this was granted by the server, it can keep I<rctx> as long as it wants
+to send further requests and OSSL_HTTP_is_alive() returns nonzero,
+else it should call I<OSSL_HTTP_REQ_CTX_free(rctx)> or L<OSSL_HTTP_close(3)>.
+In case the client application keeps I<rctx> but the connection then dies
+for any reason at the server side, it will notice this obtaining an
+I/O error when trying to send the next request via I<rctx>.
+
+=head1 WARNINGS
+
+The server's response may be unexpected if the hostname that was used to
+create the I<wbio>, any C<Host> header, and the host specified in the
+request URL do not match.
+
+Many of these functions must be called in a certain order.
+
+First, the HTTP request context must be allocated:
+OSSL_HTTP_REQ_CTX_new().
+
+Then, the HTTP request must be prepared with request data:
+
+=over 4
+
+=item 1.
+
+Calling OSSL_HTTP_REQ_CTX_set_request_line().
+
+=item 2.
+
+Adding extra header lines with OSSL_HTTP_REQ_CTX_add1_header().
+This is optional and may be done multiple times with different names.
+
+=item 3.
+
+Finalize the request using OSSL_HTTP_REQ_CTX_set1_req().
+This may be omitted if the GET method is used and "keep-alive" is not requested.
+
+=back
+
+When the request context is fully prepared, the HTTP exchange may be performed
+with OSSL_HTTP_REQ_CTX_nbio() or OSSL_HTTP_REQ_CTX_exchange().
+
+=head1 RETURN VALUES
+
+OSSL_HTTP_REQ_CTX_new() returns a pointer to a B<OSSL_HTTP_REQ_CTX>, or NULL
+on error.
+
+OSSL_HTTP_REQ_CTX_free() and OSSL_HTTP_REQ_CTX_set_max_response_length()
+do not return values.
+
+OSSL_HTTP_REQ_CTX_set_request_line(), OSSL_HTTP_REQ_CTX_add1_header(),
+OSSL_HTTP_REQ_CTX_set1_req(), and OSSL_HTTP_REQ_CTX_set_expected()
+return 1 for success and 0 for failure.
+
+OSSL_HTTP_REQ_CTX_nbio() and OSSL_HTTP_REQ_CTX_nbio_d2i()
+return 1 for success, 0 on error or redirection, -1 if retry is needed.
+
+OSSL_HTTP_REQ_CTX_exchange() and OSSL_HTTP_REQ_CTX_get0_mem_bio()
+return a pointer to a B<BIO> on success as described above or NULL on failure.
+The returned BIO must not be freed by the caller.
+
+OSSL_HTTP_REQ_CTX_get_resp_len() returns the size of the response contents
+or 0 if not available or an error occurred.
+
+OSSL_HTTP_is_alive() returns 1 if its argument is non-NULL
+and the client requested a persistent connection
+and the server did not disagree on keeping the connection open, else 0.
+
+=head1 SEE ALSO
+
+L<BIO_should_retry(3)>,
+L<BIO_wait(3)>,
+L<ASN1_item_d2i_bio(3)>,
+L<ASN1_item_i2d_mem_bio(3)>,
+L<OSSL_HTTP_open(3)>,
+L<OSSL_HTTP_get(3)>,
+L<OSSL_HTTP_transfer(3)>,
+L<OSSL_HTTP_close(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_HTTP_parse_url.pod b/doc/man3/OSSL_HTTP_parse_url.pod
new file mode 100644
index 000000000000..945e981a73fa
--- /dev/null
+++ b/doc/man3/OSSL_HTTP_parse_url.pod
@@ -0,0 +1,107 @@
+=pod
+
+=head1 NAME
+
+OSSL_HTTP_adapt_proxy,
+OSSL_parse_url,
+OSSL_HTTP_parse_url,
+OCSP_parse_url
+- http utility functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/http.h>
+
+ const char *OSSL_HTTP_adapt_proxy(const char *proxy, const char *no_proxy,
+ const char *server, int use_ssl);
+
+ int OSSL_parse_url(const char *url, char **pscheme, char **puser, char **phost,
+ char **pport, int *pport_num,
+ char **ppath, char **pquery, char **pfrag);
+ int OSSL_HTTP_parse_url(const char *url,
+ int *pssl, char **puser, char **phost,
+ char **pport, int *pport_num,
+ char **ppath, char **pquery, char **pfrag);
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath,
+ int *pssl);
+
+=head1 DESCRIPTION
+
+OSSL_HTTP_adapt_proxy() takes an optional proxy hostname I<proxy>
+and returns it transformed according to the optional I<no_proxy> parameter,
+I<server>, I<use_ssl>, and the applicable environment variable, as follows.
+If I<proxy> is NULL, take any default value from the C<http_proxy>
+environment variable, or from C<https_proxy> if I<use_ssl> is nonzero.
+If this still does not yield a proxy hostname,
+take any further default value from the C<HTTP_PROXY>
+environment variable, or from C<HTTPS_PROXY> if I<use_ssl> is nonzero.
+If I<no_proxy> is NULL, take any default exclusion value from the C<no_proxy>
+environment variable, or else from C<NO_PROXY>.
+Return the determined proxy hostname unless the exclusion contains I<server>.
+Otherwise return NULL.
+
+OSSL_parse_url() parses its input string I<url> as a URL of the form
+C<[scheme://][userinfo@]host[:port][/path][?query][#fragment]> and splits it up
+into scheme, userinfo, host, port, path, query, and fragment components.
+The host (or server) component may be a DNS name or an IP address
+where IPv6 addresses should be enclosed in square brackets C<[> and C<]>.
+The port component is optional and defaults to C<0>.
+If given, it must be in decimal form. If the I<pport_num> argument is not NULL
+the integer value of the port number is assigned to I<*pport_num> on success.
+The path component is also optional and defaults to C</>.
+Each non-NULL result pointer argument I<pscheme>, I<puser>, I<phost>, I<pport>,
+I<ppath>, I<pquery>, and I<pfrag>, is assigned the respective url component.
+On success, they are guaranteed to contain non-NULL string pointers, else NULL.
+It is the reponsibility of the caller to free them using L<OPENSSL_free(3)>.
+If I<pquery> is NULL, any given query component is handled as part of the path.
+A string returned via I<*ppath> is guaranteed to begin with a C</> character.
+For absent scheme, userinfo, port, query, and fragment components
+an empty string is provided.
+
+OSSL_HTTP_parse_url() is a special form of OSSL_parse_url()
+where the scheme, if given, must be C<http> or C<https>.
+If I<pssl> is not NULL, I<*pssl> is assigned 1 in case parsing was successful
+and the scheme is C<https>, else 0.
+The port component is optional and defaults to C<443> if the scheme is C<https>,
+else C<80>.
+Note that relative paths must be given with a leading C</>,
+otherwise the first path element is interpreted as the hostname.
+
+Calling the deprecated function OCSP_parse_url(url, host, port, path, ssl)
+is equivalent to
+OSSL_HTTP_parse_url(url, ssl, NULL, host, port, NULL, path, NULL, NULL).
+
+=head1 RETURN VALUES
+
+OSSL_HTTP_adapt_proxy() returns NULL if no proxy is to be used,
+otherwise a constant proxy hostname string,
+which is either the proxy name handed in or an environment variable value.
+
+OSSL_parse_url(), OSSL_HTTP_parse_url(), and OCSP_parse_url()
+return 1 on success, 0 on error.
+
+=head1 SEE ALSO
+
+L<OSSL_HTTP_transfer(3)>
+
+=head1 HISTORY
+
+OSSL_HTTP_adapt_proxy(),
+OSSL_parse_url() and OSSL_HTTP_parse_url() were added in OpenSSL 3.0.
+OCSP_parse_url() was deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_HTTP_transfer.pod b/doc/man3/OSSL_HTTP_transfer.pod
new file mode 100644
index 000000000000..3337f6d4a35e
--- /dev/null
+++ b/doc/man3/OSSL_HTTP_transfer.pod
@@ -0,0 +1,284 @@
+=pod
+
+=head1 NAME
+
+OSSL_HTTP_open,
+OSSL_HTTP_bio_cb_t,
+OSSL_HTTP_proxy_connect,
+OSSL_HTTP_set1_request,
+OSSL_HTTP_exchange,
+OSSL_HTTP_get,
+OSSL_HTTP_transfer,
+OSSL_HTTP_close
+- HTTP client high-level functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/http.h>
+
+ typedef BIO *(*OSSL_HTTP_bio_cb_t)(BIO *bio, void *arg,
+ int connect, int detail);
+ OSSL_HTTP_REQ_CTX *OSSL_HTTP_open(const char *server, const char *port,
+ const char *proxy, const char *no_proxy,
+ int use_ssl, BIO *bio, BIO *rbio,
+ OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
+ int buf_size, int overall_timeout);
+ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port,
+ const char *proxyuser, const char *proxypass,
+ int timeout, BIO *bio_err, const char *prog);
+ int OSSL_HTTP_set1_request(OSSL_HTTP_REQ_CTX *rctx, const char *path,
+ const STACK_OF(CONF_VALUE) *headers,
+ const char *content_type, BIO *req,
+ const char *expected_content_type, int expect_asn1,
+ size_t max_resp_len, int timeout, int keep_alive);
+ BIO *OSSL_HTTP_exchange(OSSL_HTTP_REQ_CTX *rctx, char **redirection_url);
+ BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy,
+ BIO *bio, BIO *rbio,
+ OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
+ int buf_size, const STACK_OF(CONF_VALUE) *headers,
+ const char *expected_content_type, int expect_asn1,
+ size_t max_resp_len, int timeout);
+ BIO *OSSL_HTTP_transfer(OSSL_HTTP_REQ_CTX **prctx,
+ const char *server, const char *port,
+ const char *path, int use_ssl,
+ const char *proxy, const char *no_proxy,
+ BIO *bio, BIO *rbio,
+ OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
+ int buf_size, const STACK_OF(CONF_VALUE) *headers,
+ const char *content_type, BIO *req,
+ const char *expected_content_type, int expect_asn1,
+ size_t max_resp_len, int timeout, int keep_alive);
+ int OSSL_HTTP_close(OSSL_HTTP_REQ_CTX *rctx, int ok);
+
+=head1 DESCRIPTION
+
+OSSL_HTTP_open() initiates an HTTP session using the I<bio> argument if not
+NULL, else by connecting to a given I<server> optionally via a I<proxy>.
+
+Typically the OpenSSL build supports sockets and the I<bio> parameter is NULL.
+In this case I<rbio> must be NULL as well and the I<server> must be non-NULL.
+The function creates a network BIO internally using L<BIO_new_connect(3)>
+for connecting to the given server and the optionally given I<port>,
+defaulting to 80 for HTTP or 443 for HTTPS.
+Then this internal BIO is used for setting up a connection
+and for exchanging one or more request and response.
+If I<bio> is given and I<rbio> is NULL then this I<bio> is used instead.
+If both I<bio> and I<rbio> are given (which may be memory BIOs for instance)
+then no explicit connection is set up, but
+I<bio> is used for writing requests and I<rbio> for reading responses.
+As soon as the client has flushed I<bio> the server must be ready to provide
+a response or indicate a waiting condition via I<rbio>.
+
+If I<bio> is given, it is an error to provide I<proxy> or I<no_proxy> arguments,
+while I<server> and I<port> arguments may be given to support diagnostic output.
+If I<bio> is NULL the optional I<proxy> parameter can be used to set an
+HTTP(S) proxy to use (unless overridden by "no_proxy" settings).
+If TLS is not used this defaults to the environment variable C<http_proxy>
+if set, else C<HTTP_PROXY>.
+If I<use_ssl> != 0 it defaults to C<https_proxy> if set, else C<HTTPS_PROXY>.
+An empty proxy string C<""> forbids using a proxy.
+Else the format is
+C<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]>,
+where any userinfo, path, query, and fragment given is ignored.
+The default proxy port number is 80, or 443 in case "https:" is given.
+The HTTP client functions connect via the given proxy unless the I<server>
+is found in the optional list I<no_proxy> of proxy hostnames (if not NULL;
+default is the environment variable C<no_proxy> if set, else C<NO_PROXY>).
+Proxying plain HTTP is supported directly,
+while using a proxy for HTTPS connections requires a suitable callback function
+such as OSSL_HTTP_proxy_connect(), described below.
+
+If I<use_ssl> is nonzero a TLS connection is requested
+and the I<bio_update_fn> parameter must be provided.
+
+The parameter I<bio_update_fn>, which is optional if I<use_ssl> is 0,
+may be used to modify the connection BIO used by the HTTP client,
+but cannot be used when both I<bio> and I<rbio> are given.
+I<bio_update_fn> is a BIO connect/disconnect callback function with prototype
+
+ BIO *(*OSSL_HTTP_bio_cb_t)(BIO *bio, void *arg, int connect, int detail)
+
+The callback function may modify the BIO provided in the I<bio> argument,
+whereby it may make use of a custom defined argument I<arg>,
+which may for instance point to an B<SSL_CTX> structure.
+During connection establishment, just after calling BIO_do_connect_retry(), the
+callback function is invoked with the I<connect> argument being 1 and
+I<detail> being 1 if I<use_ssl> is nonzero (i.e., HTTPS is requested), else 0.
+On disconnect I<connect> is 0 and I<detail> is 1 if no error occurred, else 0.
+For instance, on connect the callback may push an SSL BIO to implement HTTPS;
+after disconnect it may do some diagnostic output and pop and free the SSL BIO.
+
+The callback function must return either the potentially modified BIO I<bio>.
+or NULL to indicate failure, in which case it should not modify the BIO.
+
+Here is a simple example that supports TLS connections (but not via a proxy):
+
+ BIO *http_tls_cb(BIO *bio, void *arg, int connect, int detail)
+ {
+ if (connect && detail) { /* connecting with TLS */
+ SSL_CTX *ctx = (SSL_CTX *)arg;
+ BIO *sbio = BIO_new_ssl(ctx, 1);
+
+ bio = sbio != NULL ? BIO_push(sbio, bio) : NULL;
+ } else if (!connect) { /* disconnecting */
+ BIO *hbio;
+
+ if (!detail) { /* an error has occurred */
+ /* optionally add diagnostics here */
+ }
+ BIO_ssl_shutdown(bio);
+ hbio = BIO_pop(bio);
+ BIO_free(bio); /* SSL BIO */
+ bio = hbio;
+ }
+ return bio;
+ }
+
+After disconnect the modified BIO will be deallocated using BIO_free_all().
+
+The I<buf_size> parameter specifies the response header maximum line length.
+A value <= 0 means that the B<OSSL_HTTP_DEFAULT_MAX_LINE_LEN> (4KiB) is used.
+I<buf_size> is also used as the number of content bytes that are read at a time.
+
+If the I<overall_timeout> parameter is > 0 this indicates the maximum number of
+seconds the overall HTTP transfer (i.e., connection setup if needed,
+sending requests, and receiving responses) is allowed to take until completion.
+A value <= 0 enables waiting indefinitely, i.e., no timeout.
+
+OSSL_HTTP_proxy_connect() may be used by an above BIO connect callback function
+to set up an SSL/TLS connection via an HTTPS proxy.
+It promotes the given BIO I<bio> representing a connection
+pre-established with a TLS proxy using the HTTP CONNECT method,
+optionally using proxy client credentials I<proxyuser> and I<proxypass>,
+to connect with TLS protection ultimately to I<server> and I<port>.
+If the I<port> argument is NULL or the empty string it defaults to "443".
+If the I<timeout> parameter is > 0 this indicates the maximum number of
+seconds the connection setup is allowed to take.
+A value <= 0 enables waiting indefinitely, i.e., no timeout.
+Since this function is typically called by applications such as
+L<openssl-s_client(1)> it uses the I<bio_err> and I<prog> parameters (unless
+NULL) to print additional diagnostic information in a user-oriented way.
+
+OSSL_HTTP_set1_request() sets up in I<rctx> the request header and content data
+and expectations on the response using the following parameters.
+If <rctx> indicates using a proxy for HTTP (but not HTTPS), the server hostname
+(and optionally port) needs to be placed in the header and thus must be present.
+If I<path> is NULL it defaults to "/".
+If I<req> is NULL the HTTP GET method will be used to send the request
+else HTTP POST with the contents of I<req> and optional I<content_type>, where
+the length of the data in I<req> does not need to be determined in advance: the
+BIO will be read on-the-fly while sending the request, which supports streaming.
+The optional list I<headers> may contain additional custom HTTP header lines.
+If the parameter I<expected_content_type>
+is not NULL then the client will check that the given content type string
+is included in the HTTP header of the response and return an error if not.
+If the I<expect_asn1> parameter is nonzero,
+a structure in ASN.1 encoding will be expected as response content.
+The I<max_resp_len> parameter specifies the maximum allowed
+response content length, where the value 0 indicates no limit.
+If the I<timeout> parameter is > 0 this indicates the maximum number of seconds
+the subsequent HTTP transfer (sending the request and receiving a response)
+is allowed to take.
+A value of 0 enables waiting indefinitely, i.e., no timeout.
+A value < 0 indicates that the I<overall_timeout> parameter value given
+when opening the HTTP transfer will be used instead.
+If I<keep_alive> is 0 the connection is not kept open
+after receiving a response, which is the default behavior for HTTP 1.0.
+If the value is 1 or 2 then a persistent connection is requested.
+If the value is 2 then a persistent connection is required,
+i.e., an error occurs in case the server does not grant it.
+
+OSSL_HTTP_exchange() exchanges any form of HTTP request and response
+as specified by I<rctx>, which must include both connection and request data,
+typically set up using OSSL_HTTP_open() and OSSL_HTTP_set1_request().
+It implements the core of the functions described below.
+If the HTTP method is GET and I<redirection_url>
+is not NULL the latter pointer is used to provide any new location that
+the server may return with HTTP code 301 (MOVED_PERMANENTLY) or 302 (FOUND).
+In this case the function returns NULL and the caller is
+responsible for deallocating the URL with L<OPENSSL_free(3)>.
+If the response header contains one or more "Content-Length" header lines and/or
+an ASN.1-encoded response is expected, which should include a total length,
+the length indications received are checked for consistency
+and for not exceeding any given maximum response length.
+If an ASN.1-encoded response is expected, the function returns on success
+the contents buffered in a memory BIO, which does not support streaming.
+Otherwise it returns directly the read BIO that holds the response contents,
+which allows a response of indefinite length and may support streaming.
+The caller is responsible for freeing the BIO pointer obtained.
+
+OSSL_HTTP_get() uses HTTP GET to obtain data from I<bio> if non-NULL,
+else from the server contained in the I<url>, and returns it as a BIO.
+It supports redirection via HTTP status code 301 or 302. It is meant for
+transfers with a single round trip, so does not support persistent connections.
+If I<bio> is non-NULL, any host and port components in the I<url> are not used
+for connecting but the hostname is used, as usual, for the C<Host> header.
+Any userinfo and fragment components in the I<url> are ignored.
+Any query component is handled as part of the path component.
+If the scheme component of the I<url> is C<https> a TLS connection is requested
+and the I<bio_update_fn>, as described for OSSL_HTTP_open(), must be provided.
+Also the remaining parameters are interpreted as described for OSSL_HTTP_open()
+and OSSL_HTTP_set1_request(), respectively.
+The caller is responsible for freeing the BIO pointer obtained.
+
+OSSL_HTTP_transfer() exchanges an HTTP request and response
+over a connection managed via I<prctx> without supporting redirection.
+It combines OSSL_HTTP_open(), OSSL_HTTP_set1_request(), OSSL_HTTP_exchange(),
+and OSSL_HTTP_close().
+If I<prctx> is not NULL it reuses any open connection represented by a non-NULL
+I<*prctx>. It keeps the connection open if a persistent connection is requested
+or required and this was granted by the server, else it closes the connection
+and assigns NULL to I<*prctx>.
+The remaining parameters are interpreted as described for OSSL_HTTP_open()
+and OSSL_HTTP_set1_request(), respectively.
+The caller is responsible for freeing the BIO pointer obtained.
+
+OSSL_HTTP_close() closes the connection and releases I<rctx>.
+The I<ok> parameter is passed to any BIO update function
+given during setup as described above for OSSL_HTTP_open().
+It must be 1 if no error occurred during the HTTP transfer and 0 otherwise.
+
+=head1 NOTES
+
+The names of the environment variables used by this implementation:
+C<http_proxy>, C<HTTP_PROXY>, C<https_proxy>, C<HTTPS_PROXY>, C<no_proxy>, and
+C<NO_PROXY>, have been chosen for maximal compatibility with
+other HTTP client implementations such as wget, curl, and git.
+
+=head1 RETURN VALUES
+
+OSSL_HTTP_open() returns on success a B<OSSL_HTTP_REQ_CTX>, else NULL.
+
+OSSL_HTTP_proxy_connect() and OSSL_HTTP_set1_request()
+return 1 on success, 0 on error.
+
+On success, OSSL_HTTP_exchange(), OSSL_HTTP_get(), and OSSL_HTTP_transfer()
+return a memory BIO that buffers all the data received if an ASN.1-encoded
+response is expected, otherwise a BIO that may support streaming.
+The BIO must be freed by the caller.
+On failure, they return NULL.
+Failure conditions include connection/transfer timeout, parse errors, etc.
+The caller is responsible for freeing the BIO pointer obtained.
+
+OSSL_HTTP_close() returns 0 if anything went wrong while disconnecting, else 1.
+
+=head1 SEE ALSO
+
+L<OSSL_HTTP_parse_url(3)>, L<BIO_new_connect(3)>,
+L<ASN1_item_i2d_mem_bio(3)>, L<ASN1_item_d2i_bio(3)>,
+L<OSSL_HTTP_is_alive(3)>
+
+=head1 HISTORY
+
+All the functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_ITEM.pod b/doc/man3/OSSL_ITEM.pod
new file mode 100644
index 000000000000..70d4bf361b75
--- /dev/null
+++ b/doc/man3/OSSL_ITEM.pod
@@ -0,0 +1,56 @@
+=pod
+
+=head1 NAME
+
+OSSL_ITEM - OpenSSL Core type for generic itemized data
+
+=head1 SYNOPSIS
+
+ #include <openssl/core.h>
+
+ typedef struct ossl_item_st OSSL_ITEM;
+ struct ossl_item_st {
+ unsigned int id;
+ void *ptr;
+ };
+
+=head1 DESCRIPTION
+
+This type is a tuple of integer and pointer.
+It's a generic type used as a generic descriptor, its exact meaning
+being defined by how it's used.
+Arrays of this type are passed between the OpenSSL libraries and the
+providers, and must be terminated with a tuple where the integer is
+zero and the pointer NULL.
+
+This is currently mainly used for the return value of the provider's error
+reason strings array, see L<provider-base(7)/Provider Functions>.
+
+=begin comment RETURN VALUES doesn't make sense for a manual that only
+describes a type, but document checkers still want that section, and
+to have more than just the section title.
+
+=head1 RETURN VALUES
+
+txt
+
+=end comment
+
+=head1 SEE ALSO
+
+L<crypto(7)>, L<provider-base(7)>, L<openssl-core.h(7)>
+
+=head1 HISTORY
+
+B<OSSL_ITEM> was added in OpenSSL 3.0
+
+=head1 COPYRIGHT
+
+Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_LIB_CTX.pod b/doc/man3/OSSL_LIB_CTX.pod
new file mode 100644
index 000000000000..45fdd8f39a6a
--- /dev/null
+++ b/doc/man3/OSSL_LIB_CTX.pod
@@ -0,0 +1,136 @@
+=pod
+
+=head1 NAME
+
+OSSL_LIB_CTX, OSSL_LIB_CTX_new, OSSL_LIB_CTX_new_from_dispatch,
+OSSL_LIB_CTX_new_child, OSSL_LIB_CTX_free, OSSL_LIB_CTX_load_config,
+OSSL_LIB_CTX_get0_global_default, OSSL_LIB_CTX_set0_default
+- OpenSSL library context
+
+=head1 SYNOPSIS
+
+ #include <openssl/crypto.h>
+
+ typedef struct ossl_lib_ctx_st OSSL_LIB_CTX;
+
+ OSSL_LIB_CTX *OSSL_LIB_CTX_new(void);
+ OSSL_LIB_CTX *OSSL_LIB_CTX_new_from_dispatch(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in);
+ OSSL_LIB_CTX *OSSL_LIB_CTX_new_child(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in);
+ int OSSL_LIB_CTX_load_config(OSSL_LIB_CTX *ctx, const char *config_file);
+ void OSSL_LIB_CTX_free(OSSL_LIB_CTX *ctx);
+ OSSL_LIB_CTX *OSSL_LIB_CTX_get0_global_default(void);
+ OSSL_LIB_CTX *OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX *ctx);
+
+=head1 DESCRIPTION
+
+B<OSSL_LIB_CTX> is an internal OpenSSL library context type.
+Applications may allocate their own, but may also use NULL to use
+a default context with functions that take an B<OSSL_LIB_CTX>
+argument.
+
+When a non default library context is in use care should be taken with
+multi-threaded applications to properly clean up thread local resources before
+the OSSL_LIB_CTX is freed.
+See L<OPENSSL_thread_stop_ex(3)> for more information.
+
+OSSL_LIB_CTX_new() creates a new OpenSSL library context.
+
+OSSL_LIB_CTX_new_from_dispatch() creates a new OpenSSL library context
+initialised to use callbacks from the OSSL_DISPATCH structure. This is primarily
+useful for provider authors. The I<handle> and dispatch structure arguments
+passed should be the same ones as passed to a provider's
+OSSL_provider_init function. Some OpenSSL functions, such as
+L<BIO_new_from_core_bio(3)>, require the library context to be created in this
+way in order to work.
+
+OSSL_LIB_CTX_new_child() is only useful to provider authors and does the same
+thing as OSSL_LIB_CTX_new_from_dispatch() except that it additionally links the
+new library context to the application library context. The new library context
+is a full library context in its own right, but will have all the same providers
+available to it that are available in the application library context (without
+having to reload them). If the application loads or unloads providers from the
+application library context then this will be automatically mirrored in the
+child library context.
+
+In addition providers that are not loaded in the parent library context can be
+explicitly loaded into the child library context independently from the parent
+library context. Providers loaded independently in this way will not be mirrored
+in the parent library context and will not be affected if the parent library
+context subsequently loads the same provider.
+
+A provider may call the function L<OSSL_PROVIDER_load(3)> with the child library
+context as required. If the provider already exists due to it being mirrored
+from the parent library context then it will remain available and its reference
+count will be increased. If L<OSSL_PROVIDER_load(3)> is called in this way then
+L<OSSL_PROVIDER_unload(3)> should be subsequently called to decrement the
+reference count. L<OSSL_PROVIDER_unload(3)> must not be called for a provider in
+the child library context that did not have an earlier L<OSSL_PROVIDER_load(3)>
+call for that provider in that child library context.
+
+In addition to providers, a child library context will also mirror the default
+properties (set via L<EVP_set_default_properties(3)>) from the parent library
+context. If L<EVP_set_default_properties(3)> is called directly on a child
+library context then the new properties will override anything from the parent
+library context and mirroring of the properties will stop.
+
+When OSSL_LIB_CTX_new_child() is called from within the scope of a provider's
+B<OSSL_provider_init> function the currently initialising provider is not yet
+available in the application's library context and therefore will similarly not
+yet be available in the newly constructed child library context. As soon as the
+B<OSSL_provider_init> function returns then the new provider is available in the
+application's library context and will be similarly mirrored in the child
+library context.
+
+OSSL_LIB_CTX_load_config() loads a configuration file using the given I<ctx>.
+This can be used to associate a library context with providers that are loaded
+from a configuration.
+
+OSSL_LIB_CTX_free() frees the given I<ctx>, unless it happens to be the
+default OpenSSL library context.
+
+OSSL_LIB_CTX_get0_global_default() returns a concrete (non NULL) reference to
+the global default library context.
+
+OSSL_LIB_CTX_set0_default() sets the default OpenSSL library context to be
+I<ctx> in the current thread. The previous default library context is
+returned. Care should be taken by the caller to restore the previous
+default library context with a subsequent call of this function. If I<ctx> is
+NULL then no change is made to the default library context, but a pointer to
+the current library context is still returned. On a successful call of this
+function the returned value will always be a concrete (non NULL) library
+context.
+
+Care should be taken when changing the default library context and starting
+async jobs (see L<ASYNC_start_job(3)>), as the default library context when
+the job is started will be used throughout the lifetime of an async job, no
+matter how the calling thread makes further default library context changes
+in the mean time. This means that the calling thread must not free the
+library context that was the default at the start of the async job before
+that job has finished.
+
+=head1 RETURN VALUES
+
+OSSL_LIB_CTX_new(), OSSL_LIB_CTX_get0_global_default() and
+OSSL_LIB_CTX_set0_default() return a library context pointer on success, or NULL
+on error.
+
+OSSL_LIB_CTX_free() doesn't return any value.
+
+OSSL_LIB_CTX_load_config() returns 1 on success, 0 on error.
+
+=head1 HISTORY
+
+All of the functions described on this page were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_PARAM.pod b/doc/man3/OSSL_PARAM.pod
new file mode 100644
index 000000000000..0aad61924f79
--- /dev/null
+++ b/doc/man3/OSSL_PARAM.pod
@@ -0,0 +1,366 @@
+=pod
+
+=head1 NAME
+
+OSSL_PARAM - a structure to pass or request object parameters
+
+=head1 SYNOPSIS
+
+ #include <openssl/core.h>
+
+ typedef struct ossl_param_st OSSL_PARAM;
+ struct ossl_param_st {
+ const char *key; /* the name of the parameter */
+ unsigned char data_type; /* declare what kind of content is in data */
+ void *data; /* value being passed in or out */
+ size_t data_size; /* data size */
+ size_t return_size; /* returned size */
+ };
+
+=head1 DESCRIPTION
+
+B<OSSL_PARAM> is a type that allows passing arbitrary data for some
+object between two parties that have no or very little shared
+knowledge about their respective internal structures for that object.
+
+A typical usage example could be an application that wants to set some
+parameters for an object, or wants to find out some parameters of an
+object.
+
+Arrays of this type can be used for the following purposes:
+
+=over 4
+
+=item * Setting parameters for some object
+
+The caller sets up the B<OSSL_PARAM> array and calls some function
+(the I<setter>) that has intimate knowledge about the object that can
+take the data from the B<OSSL_PARAM> array and assign them in a
+suitable form for the internal structure of the object.
+
+=item * Request parameters of some object
+
+The caller (the I<requestor>) sets up the B<OSSL_PARAM> array and
+calls some function (the I<responder>) that has intimate knowledge
+about the object, which can take the internal data of the object and
+copy (possibly convert) that to the memory prepared by the
+I<requestor> and pointed at with the B<OSSL_PARAM> I<data>.
+
+=item * Request parameter descriptors
+
+The caller gets an array of constant B<OSSL_PARAM>, which describe
+available parameters and some of their properties; name, data type and
+expected data size.
+For a detailed description of each field for this use, see the field
+descriptions below.
+
+The caller may then use the information from this descriptor array to
+build up its own B<OSSL_PARAM> array to pass down to a I<setter> or
+I<responder>.
+
+=back
+
+Normally, the order of the an B<OSSL_PARAM> array is not relevant.
+However, if the I<responder> can handle multiple elements with the
+same key, those elements must be handled in the order they are in.
+
+An B<OSSL_PARAM> array must have a terminating element, where I<key>
+is NULL. The usual full terminating template is:
+
+ { NULL, 0, NULL, 0, 0 }
+
+This can also be specified using L<OSSL_PARAM_END(3)>.
+
+=head2 Functional support
+
+Libcrypto offers a limited set of helper functions to handle
+B<OSSL_PARAM> items and arrays, please see L<OSSL_PARAM_get_int(3)>.
+Developers are free to extend or replace those as they see fit.
+
+=head2 B<OSSL_PARAM> fields
+
+=over 4
+
+=item I<key>
+
+The identity of the parameter in the form of a string.
+
+In an B<OSSL_PARAM> array, an item with this field set to NULL is
+considered a terminating item.
+
+=item I<data_type>
+
+The I<data_type> is a value that describes the type and organization of
+the data.
+See L</Supported types> below for a description of the types.
+
+=item I<data>
+
+=item I<data_size>
+
+I<data> is a pointer to the memory where the parameter data is (when
+setting parameters) or shall (when requesting parameters) be stored,
+and I<data_size> is its size in bytes.
+The organization of the data depends on the parameter type and flag.
+
+The I<data_size> needs special attention with the parameter type
+B<OSSL_PARAM_UTF8_STRING> in relation to C strings. When setting
+parameters, the size should be set to the length of the string, not
+counting the terminating NUL byte. When requesting parameters, the
+size should be set to the size of the buffer to be populated, which
+should accomodate enough space for a terminating NUL byte.
+
+When I<requesting parameters>, it's acceptable for I<data> to be NULL.
+This can be used by the I<requestor> to figure out dynamically exactly
+how much buffer space is needed to store the parameter data.
+In this case, I<data_size> is ignored.
+
+When the B<OSSL_PARAM> is used as a parameter descriptor, I<data>
+should be ignored.
+If I<data_size> is zero, it means that an arbitrary data size is
+accepted, otherwise it specifies the maximum size allowed.
+
+=item I<return_size>
+
+When an array of B<OSSL_PARAM> is used to request data, the
+I<responder> must set this field to indicate size of the parameter
+data, including padding as the case may be.
+In case the I<data_size> is an unsuitable size for the data, the
+I<responder> must still set this field to indicate the minimum data
+size required.
+(further notes on this in L</NOTES> below).
+
+When the B<OSSL_PARAM> is used as a parameter descriptor,
+I<return_size> should be ignored.
+
+=back
+
+B<NOTE:>
+
+The key names and associated types are defined by the entity that
+offers these parameters, i.e. names for parameters provided by the
+OpenSSL libraries are defined by the libraries, and names for
+parameters provided by providers are defined by those providers,
+except for the pointer form of strings (see data type descriptions
+below).
+Entities that want to set or request parameters need to know what
+those keys are and of what type, any functionality between those two
+entities should remain oblivious and just pass the B<OSSL_PARAM> array
+along.
+
+=head2 Supported types
+
+The I<data_type> field can be one of the following types:
+
+=over 4
+
+=item B<OSSL_PARAM_INTEGER>
+
+=item B<OSSL_PARAM_UNSIGNED_INTEGER>
+
+The parameter data is an integer (signed or unsigned) of arbitrary
+length, organized in native form, i.e. most significant byte first on
+Big-Endian systems, and least significant byte first on Little-Endian
+systems.
+
+=item B<OSSL_PARAM_REAL>
+
+The parameter data is a floating point value in native form.
+
+=item B<OSSL_PARAM_UTF8_STRING>
+
+The parameter data is a printable string.
+
+=item B<OSSL_PARAM_OCTET_STRING>
+
+The parameter data is an arbitrary string of bytes.
+
+=item B<OSSL_PARAM_UTF8_PTR>
+
+The parameter data is a pointer to a printable string.
+
+The difference between this and B<OSSL_PARAM_UTF8_STRING> is that I<data>
+doesn't point directly at the data, but to a pointer that points to the data.
+
+If there is any uncertainty about which to use, B<OSSL_PARAM_UTF8_STRING> is
+almost certainly the correct choice.
+
+This is used to indicate that constant data is or will be passed,
+and there is therefore no need to copy the data that is passed, just
+the pointer to it.
+
+I<data_size> must be set to the size of the data, not the size of the
+pointer to the data.
+If this is used in a parameter request,
+I<data_size> is not relevant. However, the I<responder> will set
+I<return_size> to the size of the data.
+
+Note that the use of this type is B<fragile> and can only be safely
+used for data that remains constant and in a constant location for a
+long enough duration (such as the life-time of the entity that
+offers these parameters).
+
+=item B<OSSL_PARAM_OCTET_PTR>
+
+The parameter data is a pointer to an arbitrary string of bytes.
+
+The difference between this and B<OSSL_PARAM_OCTET_STRING> is that
+I<data> doesn't point directly at the data, but to a pointer that
+points to the data.
+
+If there is any uncertainty about which to use, B<OSSL_PARAM_OCTET_STRING> is
+almost certainly the correct choice.
+
+This is used to indicate that constant data is or will be passed, and
+there is therefore no need to copy the data that is passed, just the
+pointer to it.
+
+I<data_size> must be set to the size of the data, not the size of the
+pointer to the data.
+If this is used in a parameter request,
+I<data_size> is not relevant. However, the I<responder> will set
+I<return_size> to the size of the data.
+
+Note that the use of this type is B<fragile> and can only be safely
+used for data that remains constant and in a constant location for a
+long enough duration (such as the life-time of the entity that
+offers these parameters).
+
+=back
+
+=head1 NOTES
+
+Both when setting and requesting parameters, the functions that are
+called will have to decide what is and what is not an error.
+The recommended behaviour is:
+
+=over 4
+
+=item *
+
+Keys that a I<setter> or I<responder> doesn't recognise should simply
+be ignored.
+That in itself isn't an error.
+
+=item *
+
+If the keys that a called I<setter> recognises form a consistent
+enough set of data, that call should succeed.
+
+=item *
+
+Apart from the I<return_size>, a I<responder> must never change the fields
+of an B<OSSL_PARAM>.
+To return a value, it should change the contents of the memory that
+I<data> points at.
+
+=item *
+
+If the data type for a key that it's associated with is incorrect,
+the called function may return an error.
+
+The called function may also try to convert the data to a suitable
+form (for example, it's plausible to pass a large number as an octet
+string, so even though a given key is defined as an
+B<OSSL_PARAM_UNSIGNED_INTEGER>, is plausible to pass the value as an
+B<OSSL_PARAM_OCTET_STRING>), but this is in no way mandatory.
+
+=item *
+
+If a I<responder> finds that some data sizes are too small for the
+requested data, it must set I<return_size> for each such
+B<OSSL_PARAM> item to the minimum required size, and eventually return
+an error.
+
+=item *
+
+For the integer type parameters (B<OSSL_PARAM_UNSIGNED_INTEGER> and
+B<OSSL_PARAM_INTEGER>), a I<responder> may choose to return an error
+if the I<data_size> isn't a suitable size (even if I<data_size> is
+bigger than needed). If the I<responder> finds the size suitable, it
+must fill all I<data_size> bytes and ensure correct padding for the
+native endianness, and set I<return_size> to the same value as
+I<data_size>.
+
+=back
+
+=begin comment RETURN VALUES doesn't make sense for a manual that only
+describes a type, but document checkers still want that section, and
+to have more than just the section title.
+
+=head1 RETURN VALUES
+
+txt
+
+=end comment
+
+=head1 EXAMPLES
+
+A couple of examples to just show how B<OSSL_PARAM> arrays could be
+set up.
+
+=head3 Example 1
+
+This example is for setting parameters on some object:
+
+ #include <openssl/core.h>
+
+ const char *foo = "some string";
+ size_t foo_l = strlen(foo);
+ const char bar[] = "some other string";
+ OSSL_PARAM set[] = {
+ { "foo", OSSL_PARAM_UTF8_PTR, &foo, foo_l, 0 },
+ { "bar", OSSL_PARAM_UTF8_STRING, (void *)&bar, sizeof(bar) - 1, 0 },
+ { NULL, 0, NULL, 0, 0 }
+ };
+
+=head3 Example 2
+
+This example is for requesting parameters on some object:
+
+ const char *foo = NULL;
+ size_t foo_l;
+ char bar[1024];
+ size_t bar_l;
+ OSSL_PARAM request[] = {
+ { "foo", OSSL_PARAM_UTF8_PTR, &foo, 0 /*irrelevant*/, 0 },
+ { "bar", OSSL_PARAM_UTF8_STRING, &bar, sizeof(bar), 0 },
+ { NULL, 0, NULL, 0, 0 }
+ };
+
+A I<responder> that receives this array (as I<params> in this example)
+could fill in the parameters like this:
+
+ /* OSSL_PARAM *params */
+
+ int i;
+
+ for (i = 0; params[i].key != NULL; i++) {
+ if (strcmp(params[i].key, "foo") == 0) {
+ *(char **)params[i].data = "foo value";
+ params[i].return_size = 9; /* length of "foo value" string */
+ } else if (strcmp(params[i].key, "bar") == 0) {
+ memcpy(params[i].data, "bar value", 10);
+ params[i].return_size = 9; /* length of "bar value" string */
+ }
+ /* Ignore stuff we don't know */
+ }
+
+=head1 SEE ALSO
+
+L<openssl-core.h(7)>, L<OSSL_PARAM_get_int(3)>, L<OSSL_PARAM_dup(3)>
+
+=head1 HISTORY
+
+B<OSSL_PARAM> was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_PARAM_BLD.pod b/doc/man3/OSSL_PARAM_BLD.pod
new file mode 100644
index 000000000000..455761c20d32
--- /dev/null
+++ b/doc/man3/OSSL_PARAM_BLD.pod
@@ -0,0 +1,203 @@
+=pod
+
+=head1 NAME
+
+OSSL_PARAM_BLD, OSSL_PARAM_BLD_new, OSSL_PARAM_BLD_to_param,
+OSSL_PARAM_BLD_free, OSSL_PARAM_BLD_push_int,
+OSSL_PARAM_BLD_push_uint, OSSL_PARAM_BLD_push_long,
+OSSL_PARAM_BLD_push_ulong, OSSL_PARAM_BLD_push_int32,
+OSSL_PARAM_BLD_push_uint32, OSSL_PARAM_BLD_push_int64,
+OSSL_PARAM_BLD_push_uint64, OSSL_PARAM_BLD_push_size_t,
+OSSL_PARAM_BLD_push_time_t, OSSL_PARAM_BLD_push_double,
+OSSL_PARAM_BLD_push_BN, OSSL_PARAM_BLD_push_BN_pad,
+OSSL_PARAM_BLD_push_utf8_string, OSSL_PARAM_BLD_push_utf8_ptr,
+OSSL_PARAM_BLD_push_octet_string, OSSL_PARAM_BLD_push_octet_ptr
+- functions to assist in the creation of OSSL_PARAM arrays
+
+=head1 SYNOPSIS
+
+=for openssl generic
+
+ #include <openssl/param_build.h>
+
+ typedef struct OSSL_PARAM_BLD;
+
+ OSSL_PARAM_BLD *OSSL_PARAM_BLD_new(void);
+ OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld);
+ void OSSL_PARAM_BLD_free(OSSL_PARAM_BLD *bld);
+
+ int OSSL_PARAM_BLD_push_TYPE(OSSL_PARAM_BLD *bld, const char *key, TYPE val);
+
+ int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD *bld, const char *key,
+ const BIGNUM *bn);
+ int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
+ const BIGNUM *bn, size_t sz);
+
+ int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key,
+ const char *buf, size_t bsize);
+ int OSSL_PARAM_BLD_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key,
+ char *buf, size_t bsize);
+ int OSSL_PARAM_BLD_push_octet_string(OSSL_PARAM_BLD *bld, const char *key,
+ const void *buf, size_t bsize);
+ int OSSL_PARAM_BLD_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key,
+ void *buf, size_t bsize);
+
+
+=head1 DESCRIPTION
+
+A collection of utility functions that simplify the creation of OSSL_PARAM
+arrays. The B<I<TYPE>> names are as per L<OSSL_PARAM_int(3)>.
+
+OSSL_PARAM_BLD_new() allocates and initialises a new OSSL_PARAM_BLD structure
+so that values can be added.
+Any existing values are cleared.
+
+OSSL_PARAM_BLD_free() deallocates the memory allocates by OSSL_PARAM_BLD_new().
+
+OSSL_PARAM_BLD_to_param() converts a built up OSSL_PARAM_BLD structure
+I<bld> into an allocated OSSL_PARAM array.
+The OSSL_PARAM array and all associated storage must be freed by calling
+OSSL_PARAM_free() with the functions return value.
+OSSL_PARAM_BLD_free() can safely be called any time after this function is.
+
+=begin comment
+
+POD is pretty good at recognising function names and making them appropriately
+bold... however, when part of the function name is variable, we have to help
+the processor along
+
+=end comment
+
+B<OSSL_PARAM_BLD_push_I<TYPE>>() are a series of functions which will create
+OSSL_PARAM objects of the specified size and correct type for the I<val>
+argument.
+I<val> is stored by value and an expression or auto variable can be used.
+
+OSSL_PARAM_BLD_push_BN() is a function that will create an OSSL_PARAM object
+that holds the specified BIGNUM I<bn>.
+If I<bn> is marked as being securely allocated, its OSSL_PARAM representation
+will also be securely allocated.
+The I<bn> argument is stored by reference and the underlying BIGNUM object
+must exist until after OSSL_PARAM_BLD_to_param() has been called.
+
+OSSL_PARAM_BLD_push_BN_pad() is a function that will create an OSSL_PARAM object
+that holds the specified BIGNUM I<bn>.
+The object will be padded to occupy exactly I<sz> bytes, if insufficient space
+is specified an error results.
+If I<bn> is marked as being securely allocated, its OSSL_PARAM representation
+will also be securely allocated.
+The I<bn> argument is stored by reference and the underlying BIGNUM object
+must exist until after OSSL_PARAM_BLD_to_param() has been called.
+
+OSSL_PARAM_BLD_push_utf8_string() is a function that will create an OSSL_PARAM
+object that references the UTF8 string specified by I<buf>.
+The length of the string I<bsize> should not include the terminating NUL byte.
+If it is zero then it will be calculated.
+The string that I<buf> points to is stored by reference and must remain in
+scope until after OSSL_PARAM_BLD_to_param() has been called.
+
+OSSL_PARAM_BLD_push_octet_string() is a function that will create an OSSL_PARAM
+object that references the octet string specified by I<buf> and <bsize>.
+The memory that I<buf> points to is stored by reference and must remain in
+scope until after OSSL_PARAM_BLD_to_param() has been called.
+
+OSSL_PARAM_BLD_push_utf8_ptr() is a function that will create an OSSL_PARAM
+object that references the UTF8 string specified by I<buf>.
+The length of the string I<bsize> should not include the terminating NUL byte.
+If it is zero then it will be calculated.
+The string I<buf> points to is stored by reference and must remain in
+scope until the OSSL_PARAM array is freed.
+
+OSSL_PARAM_BLD_push_octet_ptr() is a function that will create an OSSL_PARAM
+object that references the octet string specified by I<buf>.
+The memory I<buf> points to is stored by reference and must remain in
+scope until the OSSL_PARAM array is freed.
+
+=head1 RETURN VALUES
+
+OSSL_PARAM_BLD_new() returns the allocated OSSL_PARAM_BLD structure, or NULL
+on error.
+
+OSSL_PARAM_BLD_to_param() returns the allocated OSSL_PARAM array, or NULL
+on error.
+
+All of the OSSL_PARAM_BLD_push_TYPE functions return 1 on success and 0
+on error.
+
+=head1 NOTES
+
+OSSL_PARAM_BLD_push_BN() and OSSL_PARAM_BLD_push_BN_pad() currently only
+support nonnegative B<BIGNUM>s. They return an error on negative B<BIGNUM>s.
+
+=head1 EXAMPLES
+
+Both examples creating an OSSL_PARAM array that contains an RSA key.
+For both, the predefined key variables are:
+
+ BIGNUM *n; /* modulus */
+ unsigned int e; /* public exponent */
+ BIGNUM *d; /* private exponent */
+ BIGNUM *p, *q; /* first two prime factors */
+ BIGNUM *dmp1, *dmq1; /* first two CRT exponents */
+ BIGNUM *iqmp; /* first CRT coefficient */
+
+=head2 Example 1
+
+This example shows how to create an OSSL_PARAM array that contains an RSA
+private key.
+
+ OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
+ OSSL_PARAM *params = NULL;
+
+ if (bld == NULL
+ || !OSSL_PARAM_BLD_push_BN(bld, "n", n)
+ || !OSSL_PARAM_BLD_push_uint(bld, "e", e)
+ || !OSSL_PARAM_BLD_push_BN(bld, "d", d)
+ || !OSSL_PARAM_BLD_push_BN(bld, "rsa-factor1", p)
+ || !OSSL_PARAM_BLD_push_BN(bld, "rsa-factor2", q)
+ || !OSSL_PARAM_BLD_push_BN(bld, "rsa-exponent1", dmp1)
+ || !OSSL_PARAM_BLD_push_BN(bld, "rsa-exponent2", dmq1)
+ || !OSSL_PARAM_BLD_push_BN(bld, "rsa-coefficient1", iqmp)
+ || (params = OSSL_PARAM_BLD_to_param(bld)) == NULL)
+ goto err;
+ OSSL_PARAM_BLD_free(bld);
+ /* Use params */
+ ...
+ OSSL_PARAM_free(params);
+
+=head2 Example 2
+
+This example shows how to create an OSSL_PARAM array that contains an RSA
+public key.
+
+ OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
+ OSSL_PARAM *params = NULL;
+
+ if (nld == NULL
+ || !OSSL_PARAM_BLD_push_BN(bld, "n", n)
+ || !OSSL_PARAM_BLD_push_uint(bld, "e", e)
+ || (params = OSSL_PARAM_BLD_to_param(bld)) == NULL)
+ goto err;
+ OSSL_PARAM_BLD_free(bld);
+ /* Use params */
+ ...
+ OSSL_PARAM_free(params);
+
+=head1 SEE ALSO
+
+L<OSSL_PARAM_int(3)>, L<OSSL_PARAM(3)>, L<OSSL_PARAM_free(3)>
+
+=head1 HISTORY
+
+The functions described here were all added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_PARAM_allocate_from_text.pod b/doc/man3/OSSL_PARAM_allocate_from_text.pod
new file mode 100644
index 000000000000..e6dc2549fdb1
--- /dev/null
+++ b/doc/man3/OSSL_PARAM_allocate_from_text.pod
@@ -0,0 +1,207 @@
+=pod
+
+=head1 NAME
+
+OSSL_PARAM_allocate_from_text
+- OSSL_PARAM construction utilities
+
+=head1 SYNOPSIS
+
+ #include <openssl/params.h>
+
+ int OSSL_PARAM_allocate_from_text(OSSL_PARAM *to,
+ const OSSL_PARAM *paramdefs,
+ const char *key, const char *value,
+ size_t value_n,
+ int *found);
+
+=head1 DESCRIPTION
+
+With OpenSSL before version 3.0, parameters were passed down to or
+retrieved from algorithm implementations via control functions.
+Some of these control functions existed in variants that took string
+parameters, for example L<EVP_PKEY_CTX_ctrl_str(3)>.
+
+OpenSSL 3.0 introduces a new mechanism to do the same thing with an
+array of parameters that contain name, value, value type and value
+size (see L<OSSL_PARAM(3)> for more information).
+
+OSSL_PARAM_allocate_from_text() uses I<key> to look up an item in
+I<paramdefs>. If an item was found, it converts I<value> to something
+suitable for that item's I<data_type>, and stores the result in
+I<< to->data >> as well as its size in I<< to->data_size >>.
+I<< to->key >> and I<< to->data_type >> are assigned the corresponding
+values from the item that was found, and I<< to->return_size >> is set
+to zero.
+
+I<< to->data >> is always allocated using L<OPENSSL_zalloc(3)> and
+needs to be freed by the caller when it's not useful any more, using
+L<OPENSSL_free(3)>.
+
+If I<found> is not NULL, I<*found> is set to 1 if I<key> could be
+located in I<paramdefs>, and to 0 otherwise.
+
+=head2 The use of I<key> and I<value> in detail
+
+OSSL_PARAM_allocate_from_text() takes note if I<key> starts with
+"hex", and will only use the rest of I<key> to look up an item in
+I<paramdefs> in that case. As an example, if I<key> is "hexid", "id"
+will be looked up in I<paramdefs>.
+
+When an item in I<paramdefs> has been found, I<value> is converted
+depending on that item's I<data_type>, as follows:
+
+=over 4
+
+=item B<OSSL_PARAM_INTEGER> and B<OSSL_PARAM_UNSIGNED_INTEGER>
+
+If I<key> didn't start with "hex", I<value> is assumed to contain
+I<value_n> decimal characters, which are decoded, and the resulting
+bytes become the number stored in the I<< to->data >> storage.
+
+If I<value> starts with "0x", it is assumed to contain I<value_n>
+hexadecimal characters.
+
+If I<key> started with "hex", I<value> is assumed to contain
+I<value_n> hexadecimal characters without the "0x" prefix.
+
+If I<value> contains characters that couldn't be decoded as
+hexadecimal or decimal characters, OSSL_PARAM_allocate_from_text()
+considers that an error.
+
+=item B<OSSL_PARAM_UTF8_STRING>
+
+If I<key> started with "hex", OSSL_PARAM_allocate_from_text()
+considers that an error.
+
+Otherwise, I<value> is considered a C string and is copied to the
+I<< to->data >> storage.
+On systems where the native character encoding is EBCDIC, the bytes in
+I<< to->data >> are converted to ASCII.
+
+=item B<OSSL_PARAM_OCTET_STRING>
+
+If I<key> started with "hex", I<value> is assumed to contain
+I<value_n> hexadecimal characters, which are decoded, and the
+resulting bytes are stored in the I<< to->data >> storage.
+If I<value> contains characters that couldn't be decoded as
+hexadecimal or decimal characters, OSSL_PARAM_allocate_from_text()
+considers that an error.
+
+If I<key> didn't start with "hex", I<value_n> bytes from I<value> are
+copied to the I<< to->data >> storage.
+
+=back
+
+=head1 RETURN VALUES
+
+OSSL_PARAM_allocate_from_text() returns 1 if I<key> was found in
+I<paramdefs> and there was no other failure, otherwise 0.
+
+=head1 NOTES
+
+The parameter descriptor array comes from functions dedicated to
+return them.
+The following L<OSSL_PARAM(3)> attributes are used:
+
+=over 4
+
+=item I<key>
+
+=item I<data_type>
+
+=item I<data_size>
+
+=back
+
+All other attributes are ignored.
+
+The I<data_size> attribute can be zero, meaning that the parameter it
+describes expects arbitrary length data.
+
+=head1 EXAMPLES
+
+Code that looked like this:
+
+ int mac_ctrl_string(EVP_PKEY_CTX *ctx, const char *value)
+ {
+ int rv;
+ char *stmp, *vtmp = NULL;
+
+ stmp = OPENSSL_strdup(value);
+ if (stmp == NULL)
+ return -1;
+ vtmp = strchr(stmp, ':');
+ if (vtmp != NULL)
+ *vtmp++ = '\0';
+ rv = EVP_MAC_ctrl_str(ctx, stmp, vtmp);
+ OPENSSL_free(stmp);
+ return rv;
+ }
+
+ ...
+
+
+ for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) {
+ char *macopt = sk_OPENSSL_STRING_value(macopts, i);
+
+ if (pkey_ctrl_string(mac_ctx, macopt) <= 0) {
+ BIO_printf(bio_err,
+ "MAC parameter error \"%s\"\n", macopt);
+ ERR_print_errors(bio_err);
+ goto mac_end;
+ }
+ }
+
+Can be written like this instead:
+
+ OSSL_PARAM *params =
+ OPENSSL_zalloc(sizeof(*params)
+ * (sk_OPENSSL_STRING_num(opts) + 1));
+ const OSSL_PARAM *paramdefs = EVP_MAC_settable_ctx_params(mac);
+ size_t params_n;
+ char *opt = "<unknown>";
+
+ for (params_n = 0; params_n < (size_t)sk_OPENSSL_STRING_num(opts);
+ params_n++) {
+ char *stmp, *vtmp = NULL;
+
+ opt = sk_OPENSSL_STRING_value(opts, (int)params_n);
+ if ((stmp = OPENSSL_strdup(opt)) == NULL
+ || (vtmp = strchr(stmp, ':')) == NULL)
+ goto err;
+
+ *vtmp++ = '\0';
+ if (!OSSL_PARAM_allocate_from_text(&params[params_n],
+ paramdefs, stmp,
+ vtmp, strlen(vtmp), NULL))
+ goto err;
+ }
+ params[params_n] = OSSL_PARAM_construct_end();
+ if (!EVP_MAC_CTX_set_params(ctx, params))
+ goto err;
+ while (params_n-- > 0)
+ OPENSSL_free(params[params_n].data);
+ OPENSSL_free(params);
+ /* ... */
+ return;
+
+ err:
+ BIO_printf(bio_err, "MAC parameter error '%s'\n", opt);
+ ERR_print_errors(bio_err);
+
+
+=head1 SEE ALSO
+
+L<OSSL_PARAM(3)>, L<OSSL_PARAM_int(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_PARAM_dup.pod b/doc/man3/OSSL_PARAM_dup.pod
new file mode 100644
index 000000000000..4ae33faf1e4e
--- /dev/null
+++ b/doc/man3/OSSL_PARAM_dup.pod
@@ -0,0 +1,59 @@
+=pod
+
+=head1 NAME
+
+OSSL_PARAM_dup, OSSL_PARAM_merge, OSSL_PARAM_free
+- OSSL_PARAM array copy functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/params.h>
+
+ OSSL_PARAM *OSSL_PARAM_dup(const OSSL_PARAM *params);
+ OSSL_PARAM *OSSL_PARAM_merge(const OSSL_PARAM *params, const OSSL_PARAM *params1);
+ void OSSL_PARAM_free(OSSL_PARAM *params);
+
+=head1 DESCRIPTION
+
+Algorithm parameters can be exported/imported from/to providers using arrays of
+L<OSSL_PARAM(3)>. The following utility functions allow the parameters to be
+duplicated and merged with other L<OSSL_PARAM(3)> to assist in this process.
+
+OSSL_PARAM_dup() duplicates the parameter array I<params>. This function does a
+deep copy of the data.
+
+OSSL_PARAM_merge() merges the parameter arrays I<params> and I<params1> into a
+new parameter array. If I<params> and I<params1> contain values with the same
+'key' then the value from I<params1> will replace the I<param> value. This
+function does a shallow copy of the parameters. Either I<params> or I<params1>
+may be NULL. The behaviour of the merge is unpredictable if I<params> and
+I<params1> contain the same key, and there are multiple entries within either
+array that have the same key.
+
+OSSL_PARAM_free() frees the parameter array I<params> that was created using
+OSSL_PARAM_dup(), OSSL_PARAM_merge() or OSSL_PARAM_BLD_to_param().
+
+=head1 RETURN VALUES
+
+The functions OSSL_PARAM_dup() and OSSL_PARAM_merge() return a newly allocated
+L<OSSL_PARAM(3)> array, or NULL if there was an error. If both parameters are NULL
+ then NULL is returned.
+
+=head1 SEE ALSO
+
+L<OSSL_PARAM(3)>, L<OSSL_PARAM_BLD(3)>
+
+=head1 HISTORY
+
+The functions were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_PARAM_int.pod b/doc/man3/OSSL_PARAM_int.pod
new file mode 100644
index 000000000000..8864404a7a15
--- /dev/null
+++ b/doc/man3/OSSL_PARAM_int.pod
@@ -0,0 +1,413 @@
+=pod
+
+=head1 NAME
+
+OSSL_PARAM_double, OSSL_PARAM_int, OSSL_PARAM_int32, OSSL_PARAM_int64,
+OSSL_PARAM_long, OSSL_PARAM_size_t, OSSL_PARAM_time_t, OSSL_PARAM_uint,
+OSSL_PARAM_uint32, OSSL_PARAM_uint64, OSSL_PARAM_ulong, OSSL_PARAM_BN,
+OSSL_PARAM_utf8_string, OSSL_PARAM_octet_string, OSSL_PARAM_utf8_ptr,
+OSSL_PARAM_octet_ptr,
+OSSL_PARAM_END, OSSL_PARAM_DEFN,
+OSSL_PARAM_construct_double, OSSL_PARAM_construct_int,
+OSSL_PARAM_construct_int32, OSSL_PARAM_construct_int64,
+OSSL_PARAM_construct_long, OSSL_PARAM_construct_size_t,
+OSSL_PARAM_construct_time_t, OSSL_PARAM_construct_uint,
+OSSL_PARAM_construct_uint32, OSSL_PARAM_construct_uint64,
+OSSL_PARAM_construct_ulong, OSSL_PARAM_construct_BN,
+OSSL_PARAM_construct_utf8_string, OSSL_PARAM_construct_utf8_ptr,
+OSSL_PARAM_construct_octet_string, OSSL_PARAM_construct_octet_ptr,
+OSSL_PARAM_construct_end,
+OSSL_PARAM_locate, OSSL_PARAM_locate_const,
+OSSL_PARAM_get_double, OSSL_PARAM_get_int, OSSL_PARAM_get_int32,
+OSSL_PARAM_get_int64, OSSL_PARAM_get_long, OSSL_PARAM_get_size_t,
+OSSL_PARAM_get_time_t, OSSL_PARAM_get_uint, OSSL_PARAM_get_uint32,
+OSSL_PARAM_get_uint64, OSSL_PARAM_get_ulong, OSSL_PARAM_get_BN,
+OSSL_PARAM_get_utf8_string, OSSL_PARAM_get_octet_string,
+OSSL_PARAM_get_utf8_ptr, OSSL_PARAM_get_octet_ptr,
+OSSL_PARAM_get_utf8_string_ptr, OSSL_PARAM_get_octet_string_ptr,
+OSSL_PARAM_set_double, OSSL_PARAM_set_int, OSSL_PARAM_set_int32,
+OSSL_PARAM_set_int64, OSSL_PARAM_set_long, OSSL_PARAM_set_size_t,
+OSSL_PARAM_set_time_t, OSSL_PARAM_set_uint, OSSL_PARAM_set_uint32,
+OSSL_PARAM_set_uint64, OSSL_PARAM_set_ulong, OSSL_PARAM_set_BN,
+OSSL_PARAM_set_utf8_string, OSSL_PARAM_set_octet_string,
+OSSL_PARAM_set_utf8_ptr, OSSL_PARAM_set_octet_ptr,
+OSSL_PARAM_UNMODIFIED, OSSL_PARAM_modified, OSSL_PARAM_set_all_unmodified
+- OSSL_PARAM helpers
+
+=head1 SYNOPSIS
+
+=for openssl generic
+
+ #include <openssl/params.h>
+
+ /*
+ * TYPE in function names is one of:
+ * double, int, int32, int64, long, size_t, time_t, uint, uint32, uint64, ulong
+ * Corresponding TYPE in function arguments is one of:
+ * double, int, int32_t, int64_t, long, size_t, time_t, unsigned int, uint32_t,
+ * uint64_t, unsigned long
+ */
+
+ #define OSSL_PARAM_TYPE(key, address)
+ #define OSSL_PARAM_BN(key, address, size)
+ #define OSSL_PARAM_utf8_string(key, address, size)
+ #define OSSL_PARAM_octet_string(key, address, size)
+ #define OSSL_PARAM_utf8_ptr(key, address, size)
+ #define OSSL_PARAM_octet_ptr(key, address, size)
+ #define OSSL_PARAM_END
+
+ #define OSSL_PARAM_UNMODIFIED
+
+ #define OSSL_PARAM_DEFN(key, type, addr, sz) \
+ { (key), (type), (addr), (sz), OSSL_PARAM_UNMODIFIED }
+
+ OSSL_PARAM OSSL_PARAM_construct_TYPE(const char *key, TYPE *buf);
+ OSSL_PARAM OSSL_PARAM_construct_BN(const char *key, unsigned char *buf,
+ size_t bsize);
+ OSSL_PARAM OSSL_PARAM_construct_utf8_string(const char *key, char *buf,
+ size_t bsize);
+ OSSL_PARAM OSSL_PARAM_construct_octet_string(const char *key, void *buf,
+ size_t bsize);
+ OSSL_PARAM OSSL_PARAM_construct_utf8_ptr(const char *key, char **buf,
+ size_t bsize);
+ OSSL_PARAM OSSL_PARAM_construct_octet_ptr(const char *key, void **buf,
+ size_t bsize);
+ OSSL_PARAM OSSL_PARAM_construct_end(void);
+
+ OSSL_PARAM *OSSL_PARAM_locate(OSSL_PARAM *array, const char *key);
+ const OSSL_PARAM *OSSL_PARAM_locate_const(const OSSL_PARAM *array,
+ const char *key);
+
+ int OSSL_PARAM_get_TYPE(const OSSL_PARAM *p, TYPE *val);
+ int OSSL_PARAM_set_TYPE(OSSL_PARAM *p, TYPE val);
+
+ int OSSL_PARAM_get_BN(const OSSL_PARAM *p, BIGNUM **val);
+ int OSSL_PARAM_set_BN(OSSL_PARAM *p, const BIGNUM *val);
+
+ int OSSL_PARAM_get_utf8_string(const OSSL_PARAM *p, char **val,
+ size_t max_len);
+ int OSSL_PARAM_set_utf8_string(OSSL_PARAM *p, const char *val);
+
+ int OSSL_PARAM_get_octet_string(const OSSL_PARAM *p, void **val,
+ size_t max_len, size_t *used_len);
+ int OSSL_PARAM_set_octet_string(OSSL_PARAM *p, const void *val, size_t len);
+
+ int OSSL_PARAM_get_utf8_ptr(const OSSL_PARAM *p, const char **val);
+ int OSSL_PARAM_set_utf8_ptr(OSSL_PARAM *p, const char *val);
+
+ int OSSL_PARAM_get_octet_ptr(const OSSL_PARAM *p, const void **val,
+ size_t *used_len);
+ int OSSL_PARAM_set_octet_ptr(OSSL_PARAM *p, const void *val,
+ size_t used_len);
+
+ int OSSL_PARAM_get_utf8_string_ptr(const OSSL_PARAM *p, const char **val);
+ int OSSL_PARAM_get_octet_string_ptr(const OSSL_PARAM *p, const void **val,
+ size_t *used_len);
+
+ int OSSL_PARAM_modified(const OSSL_PARAM *param);
+ void OSSL_PARAM_set_all_unmodified(OSSL_PARAM *params);
+
+=head1 DESCRIPTION
+
+A collection of utility functions that simplify and add type safety to the
+L<OSSL_PARAM(3)> arrays. The following B<I<TYPE>> names are supported:
+
+=over 1
+
+=item *
+
+double
+
+=item *
+
+int
+
+=item *
+
+int32 (int32_t)
+
+=item *
+
+int64 (int64_t)
+
+=item *
+
+long int (long)
+
+=item *
+
+time_t
+
+=item *
+
+size_t
+
+=item *
+
+uint32 (uint32_t)
+
+=item *
+
+uint64 (uint64_t)
+
+=item *
+
+unsigned int (uint)
+
+=item *
+
+unsigned long int (ulong)
+
+=back
+
+OSSL_PARAM_TYPE() are a series of macros designed to assist initialising an
+array of L<OSSL_PARAM(3)> structures.
+Each of these macros defines a parameter of the specified B<I<TYPE>> with the
+provided I<key> and parameter variable I<address>.
+
+OSSL_PARAM_utf8_string(), OSSL_PARAM_octet_string(), OSSL_PARAM_utf8_ptr(),
+OSSL_PARAM_octet_ptr(), OSSL_PARAM_BN() are macros that provide support
+for defining UTF8 strings, OCTET strings and big numbers.
+A parameter with name I<key> is defined.
+The storage for this parameter is at I<address> and is of I<size> bytes.
+
+OSSL_PARAM_END provides an end of parameter list marker.
+This should terminate all L<OSSL_PARAM(3)> arrays.
+
+The OSSL_PARAM_DEFN() macro provides the ability to construct a single
+L<OSSL_PARAM(3)> (typically used in the construction of B<OSSL_PARAM> arrays). The
+I<key>, I<type>, I<addr> and I<sz> arguments correspond to the I<key>,
+I<data_type>, I<data> and I<data_size> fields of the L<OSSL_PARAM(3)> structure as
+described on the L<OSSL_PARAM(3)> page.
+
+OSSL_PARAM_construct_TYPE() are a series of functions that create L<OSSL_PARAM(3)>
+records dynamically.
+A parameter with name I<key> is created.
+The parameter will use storage pointed to by I<buf> and return size of I<ret>.
+
+OSSL_PARAM_construct_BN() is a function that constructs a large integer
+L<OSSL_PARAM(3)> structure.
+A parameter with name I<key>, storage I<buf>, size I<bsize> and return
+size I<rsize> is created.
+
+OSSL_PARAM_construct_utf8_string() is a function that constructs a UTF8
+string L<OSSL_PARAM(3)> structure.
+A parameter with name I<key>, storage I<buf> and size I<bsize> is created.
+If I<bsize> is zero, the string length is determined using strlen(3).
+Generally pass zero for I<bsize> instead of calling strlen(3) yourself.
+
+OSSL_PARAM_construct_octet_string() is a function that constructs an OCTET
+string L<OSSL_PARAM(3)> structure.
+A parameter with name I<key>, storage I<buf> and size I<bsize> is created.
+
+OSSL_PARAM_construct_utf8_ptr() is a function that constructs a UTF8 string
+pointer L<OSSL_PARAM(3)> structure.
+A parameter with name I<key>, storage pointer I<*buf> and size I<bsize>
+is created.
+
+OSSL_PARAM_construct_octet_ptr() is a function that constructs an OCTET string
+pointer L<OSSL_PARAM(3)> structure.
+A parameter with name I<key>, storage pointer I<*buf> and size I<bsize>
+is created.
+
+OSSL_PARAM_construct_end() is a function that constructs the terminating
+L<OSSL_PARAM(3)> structure.
+
+OSSL_PARAM_locate() is a function that searches an I<array> of parameters for
+the one matching the I<key> name.
+
+OSSL_PARAM_locate_const() behaves exactly like OSSL_PARAM_locate() except for
+the presence of I<const> for the I<array> argument and its return value.
+
+OSSL_PARAM_get_TYPE() retrieves a value of type B<I<TYPE>> from the parameter
+I<p>.
+The value is copied to the address I<val>.
+Type coercion takes place as discussed in the NOTES section.
+
+OSSL_PARAM_set_TYPE() stores a value I<val> of type B<I<TYPE>> into the
+parameter I<p>.
+If the parameter's I<data> field is NULL, then only its I<return_size> field
+will be assigned the size the parameter's I<data> buffer should have.
+Type coercion takes place as discussed in the NOTES section.
+
+OSSL_PARAM_get_BN() retrieves a BIGNUM from the parameter pointed to by I<p>.
+The BIGNUM referenced by I<val> is updated and is allocated if I<*val> is
+NULL.
+
+OSSL_PARAM_set_BN() stores the BIGNUM I<val> into the parameter I<p>.
+If the parameter's I<data> field is NULL, then only its I<return_size> field
+will be assigned the size the parameter's I<data> buffer should have.
+
+OSSL_PARAM_get_utf8_string() retrieves a UTF8 string from the parameter
+pointed to by I<p>.
+The string is stored into I<*val> with a size limit of I<max_len>,
+which must be large enough to accomodate a terminating NUL byte,
+otherwise this function will fail.
+If I<*val> is NULL, memory is allocated for the string (including the
+terminating NUL byte) and I<max_len> is ignored.
+If memory is allocated by this function, it must be freed by the caller.
+
+OSSL_PARAM_set_utf8_string() sets a UTF8 string from the parameter pointed to
+by I<p> to the value referenced by I<val>.
+If the parameter's I<data> field isn't NULL, its I<data_size> must indicate
+that the buffer is large enough to accomodate the string that I<val> points at,
+not including the terminating NUL byte, or this function will fail.
+A terminating NUL byte is added only if the parameter's I<data_size> indicates
+the buffer is longer than the string length, otherwise the string will not be
+NUL terminated.
+If the parameter's I<data> field is NULL, then only its I<return_size> field
+will be assigned the minimum size the parameter's I<data> buffer should have
+to accomodate the string, not including a terminating NUL byte.
+
+OSSL_PARAM_get_octet_string() retrieves an OCTET string from the parameter
+pointed to by I<p>.
+The OCTETs are either stored into I<*val> with a length limit of I<max_len> or,
+in the case when I<*val> is NULL, memory is allocated and
+I<max_len> is ignored. I<*used_len> is populated with the number of OCTETs
+stored. If I<val> is NULL then the OCTETS are not stored, but I<*used_len> is
+still populated.
+If memory is allocated by this function, it must be freed by the caller.
+
+OSSL_PARAM_set_octet_string() sets an OCTET string from the parameter
+pointed to by I<p> to the value referenced by I<val>.
+If the parameter's I<data> field is NULL, then only its I<return_size> field
+will be assigned the size the parameter's I<data> buffer should have.
+
+OSSL_PARAM_get_utf8_ptr() retrieves the UTF8 string pointer from the parameter
+referenced by I<p> and stores it in I<*val>.
+
+OSSL_PARAM_set_utf8_ptr() sets the UTF8 string pointer in the parameter
+referenced by I<p> to the values I<val>.
+
+OSSL_PARAM_get_octet_ptr() retrieves the OCTET string pointer from the parameter
+referenced by I<p> and stores it in I<*val>.
+The length of the OCTET string is stored in I<*used_len>.
+
+OSSL_PARAM_set_octet_ptr() sets the OCTET string pointer in the parameter
+referenced by I<p> to the values I<val>.
+The length of the OCTET string is provided by I<used_len>.
+
+OSSL_PARAM_get_utf8_string_ptr() retrieves the pointer to a UTF8 string from
+the parameter pointed to by I<p>, and stores that pointer in I<*val>.
+This is different from OSSL_PARAM_get_utf8_string(), which copies the
+string.
+
+OSSL_PARAM_get_octet_string_ptr() retrieves the pointer to a octet string
+from the parameter pointed to by I<p>, and stores that pointer in I<*val>,
+along with the string's length in I<*used_len>.
+This is different from OSSL_PARAM_get_octet_string(), which copies the
+string.
+
+The OSSL_PARAM_UNMODIFIED macro is used to detect if a parameter was set. On
+creation, via either the macros or construct calls, the I<return_size> field
+is set to this. If the parameter is set using the calls defined herein, the
+I<return_size> field is changed.
+
+OSSL_PARAM_modified() queries if the parameter I<param> has been set or not
+using the calls defined herein.
+
+OSSL_PARAM_set_all_unmodified() resets the unused indicator for all parameters
+in the array I<params>.
+
+=head1 RETURN VALUES
+
+OSSL_PARAM_construct_TYPE(), OSSL_PARAM_construct_BN(),
+OSSL_PARAM_construct_utf8_string(), OSSL_PARAM_construct_octet_string(),
+OSSL_PARAM_construct_utf8_ptr() and OSSL_PARAM_construct_octet_ptr()
+return a populated L<OSSL_PARAM(3)> structure.
+
+OSSL_PARAM_locate() and OSSL_PARAM_locate_const() return a pointer to
+the matching L<OSSL_PARAM(3)> object. They return NULL on error or when
+no object matching I<key> exists in the I<array>.
+
+OSSL_PARAM_modified() returns 1 if the parameter was set and 0 otherwise.
+
+All other functions return 1 on success and 0 on failure.
+
+=head1 NOTES
+
+Native types will be converted as required only if the value is exactly
+representable by the target type or parameter.
+Apart from that, the functions must be used appropriately for the
+expected type of the parameter.
+
+OSSL_PARAM_get_BN() and OSSL_PARAM_set_BN() currently only support
+nonnegative B<BIGNUM>s, and by consequence, only
+B<OSSL_PARAM_UNSIGNED_INTEGER>. OSSL_PARAM_construct_BN() currently
+constructs an L<OSSL_PARAM(3)> structure with the data type
+B<OSSL_PARAM_UNSIGNED_INTEGER>.
+
+For OSSL_PARAM_construct_utf8_ptr() and OSSL_PARAM_consstruct_octet_ptr(),
+I<bsize> is not relevant if the purpose is to send the L<OSSL_PARAM(3)> array
+to a I<responder>, i.e. to get parameter data back.
+In that case, I<bsize> can safely be given zero.
+See L<OSSL_PARAM(3)/DESCRIPTION> for further information on the
+possible purposes.
+
+=head1 EXAMPLES
+
+Reusing the examples from L<OSSL_PARAM(3)> to just show how
+L<OSSL_PARAM(3)> arrays can be handled using the macros and functions
+defined herein.
+
+=head2 Example 1
+
+This example is for setting parameters on some object:
+
+ #include <openssl/core.h>
+
+ const char *foo = "some string";
+ size_t foo_l = strlen(foo);
+ const char bar[] = "some other string";
+ const OSSL_PARAM set[] = {
+ OSSL_PARAM_utf8_ptr("foo", &foo, foo_l),
+ OSSL_PARAM_utf8_string("bar", bar, sizeof(bar) - 1),
+ OSSL_PARAM_END
+ };
+
+=head2 Example 2
+
+This example is for requesting parameters on some object, and also
+demonstrates that the requestor isn't obligated to request all
+available parameters:
+
+ const char *foo = NULL;
+ char bar[1024];
+ OSSL_PARAM request[] = {
+ OSSL_PARAM_utf8_ptr("foo", &foo, 0),
+ OSSL_PARAM_utf8_string("bar", bar, sizeof(bar)),
+ OSSL_PARAM_END
+ };
+
+A I<responder> that receives this array (as C<params> in this example)
+could fill in the parameters like this:
+
+ /* OSSL_PARAM *params */
+
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, "foo")) != NULL)
+ OSSL_PARAM_set_utf8_ptr(p, "foo value");
+ if ((p = OSSL_PARAM_locate(params, "bar")) != NULL)
+ OSSL_PARAM_set_utf8_string(p, "bar value");
+ if ((p = OSSL_PARAM_locate(params, "cookie")) != NULL)
+ OSSL_PARAM_set_utf8_ptr(p, "cookie value");
+
+=head1 SEE ALSO
+
+L<openssl-core.h(7)>, L<OSSL_PARAM(3)>
+
+=head1 HISTORY
+
+These APIs were introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_PROVIDER.pod b/doc/man3/OSSL_PROVIDER.pod
new file mode 100644
index 000000000000..9710469e07f2
--- /dev/null
+++ b/doc/man3/OSSL_PROVIDER.pod
@@ -0,0 +1,223 @@
+=pod
+
+=head1 NAME
+
+OSSL_PROVIDER_set_default_search_path,
+OSSL_PROVIDER, OSSL_PROVIDER_load, OSSL_PROVIDER_try_load, OSSL_PROVIDER_unload,
+OSSL_PROVIDER_available, OSSL_PROVIDER_do_all,
+OSSL_PROVIDER_gettable_params, OSSL_PROVIDER_get_params,
+OSSL_PROVIDER_query_operation, OSSL_PROVIDER_unquery_operation,
+OSSL_PROVIDER_get0_provider_ctx, OSSL_PROVIDER_get0_dispatch,
+OSSL_PROVIDER_add_builtin, OSSL_PROVIDER_get0_name, OSSL_PROVIDER_get_capabilities,
+OSSL_PROVIDER_self_test
+- provider routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/provider.h>
+
+ typedef struct ossl_provider_st OSSL_PROVIDER;
+
+ int OSSL_PROVIDER_set_default_search_path(OSSL_LIB_CTX *libctx,
+ const char *path);
+
+ OSSL_PROVIDER *OSSL_PROVIDER_load(OSSL_LIB_CTX *libctx, const char *name);
+ OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *libctx, const char *name,
+ int retain_fallbacks);
+ int OSSL_PROVIDER_unload(OSSL_PROVIDER *prov);
+ int OSSL_PROVIDER_available(OSSL_LIB_CTX *libctx, const char *name);
+ int OSSL_PROVIDER_do_all(OSSL_LIB_CTX *ctx,
+ int (*cb)(OSSL_PROVIDER *provider, void *cbdata),
+ void *cbdata);
+
+ const OSSL_PARAM *OSSL_PROVIDER_gettable_params(OSSL_PROVIDER *prov);
+ int OSSL_PROVIDER_get_params(OSSL_PROVIDER *prov, OSSL_PARAM params[]);
+
+ const OSSL_ALGORITHM *OSSL_PROVIDER_query_operation(const OSSL_PROVIDER *prov,
+ int operation_id,
+ int *no_cache);
+ void OSSL_PROVIDER_unquery_operation(const OSSL_PROVIDER *prov,
+ int operation_id,
+ const OSSL_ALGORITHM *algs);
+ void *OSSL_PROVIDER_get0_provider_ctx(const OSSL_PROVIDER *prov);
+ const OSSL_DISPATCH *OSSL_PROVIDER_get0_dispatch(const OSSL_PROVIDER *prov);
+
+ int OSSL_PROVIDER_add_builtin(OSSL_LIB_CTX *libctx, const char *name,
+ ossl_provider_init_fn *init_fn);
+
+ const char *OSSL_PROVIDER_get0_name(const OSSL_PROVIDER *prov);
+
+ int OSSL_PROVIDER_get_capabilities(const OSSL_PROVIDER *prov,
+ const char *capability,
+ OSSL_CALLBACK *cb,
+ void *arg);
+ int OSSL_PROVIDER_self_test(const OSSL_PROVIDER *prov);
+
+=head1 DESCRIPTION
+
+B<OSSL_PROVIDER> is a type that holds internal information about
+implementation providers (see L<provider(7)> for information on what a
+provider is).
+A provider can be built in to the application or the OpenSSL
+libraries, or can be a loadable module.
+The functions described here handle both forms.
+
+Some of these functions operate within a library context, please see
+L<OSSL_LIB_CTX(3)> for further details.
+
+=head2 Functions
+
+OSSL_PROVIDER_set_default_search_path() specifies the default search I<path>
+that is to be used for looking for providers in the specified I<libctx>.
+If left unspecified, an environment variable and a fall back default value will
+be used instead.
+
+OSSL_PROVIDER_add_builtin() is used to add a built in provider to
+B<OSSL_PROVIDER> store in the given library context, by associating a
+provider name with a provider initialization function.
+This name can then be used with OSSL_PROVIDER_load().
+
+OSSL_PROVIDER_load() loads and initializes a provider.
+This may simply initialize a provider that was previously added with
+OSSL_PROVIDER_add_builtin() and run its given initialization function,
+or load a provider module with the given name and run its provider
+entry point, C<OSSL_provider_init>. The I<name> can be a path
+to a provider module, in that case the provider name as returned
+by OSSL_PROVIDER_get0_name() will be the path. Interpretation
+of relative paths is platform dependent and they are relative
+to the configured "MODULESDIR" directory or the path set in
+the environment variable OPENSSL_MODULES if set.
+
+OSSL_PROVIDER_try_load() functions like OSSL_PROVIDER_load(), except that
+it does not disable the fallback providers if the provider cannot be
+loaded and initialized or if I<retain_fallbacks> is zero.
+If the provider loads successfully and I<retain_fallbacks> is nonzero, the
+fallback providers are disabled.
+
+OSSL_PROVIDER_unload() unloads the given provider.
+For a provider added with OSSL_PROVIDER_add_builtin(), this simply
+runs its teardown function.
+
+OSSL_PROVIDER_available() checks if a named provider is available
+for use.
+
+OSSL_PROVIDER_do_all() iterates over all loaded providers, calling
+I<cb> for each one, with the current provider in I<provider> and the
+I<cbdata> that comes from the caller. If no other provider has been loaded
+before calling this function, the default provider is still available as
+fallback.
+See L<OSSL_PROVIDER-default(7)> for more information on this fallback
+behaviour.
+
+OSSL_PROVIDER_gettable_params() is used to get a provider parameter
+descriptor set as a constant L<OSSL_PARAM(3)> array.
+
+OSSL_PROVIDER_get_params() is used to get provider parameter values.
+The caller must prepare the L<OSSL_PARAM(3)> array before calling this
+function, and the variables acting as buffers for this parameter array
+should be filled with data when it returns successfully.
+
+OSSL_PROVIDER_self_test() is used to run a provider's self tests on demand.
+If the self tests fail then the provider will fail to provide any further
+services and algorithms. L<OSSL_SELF_TEST_set_callback(3)> may be called
+beforehand in order to display diagnostics for the running self tests.
+
+OSSL_PROVIDER_query_operation() calls the provider's I<query_operation>
+function (see L<provider(7)>), if the provider has one. It returns an
+array of I<OSSL_ALGORITHM> for the given I<operation_id> terminated by an all
+NULL OSSL_ALGORITHM entry. This is considered a low-level function that most
+applications should not need to call.
+
+OSSL_PROVIDER_unquery_operation() calls the provider's I<unquery_operation>
+function (see L<provider(7)>), if the provider has one. This is considered a
+low-level function that most applications should not need to call.
+
+OSSL_PROVIDER_get0_provider_ctx() returns the provider context for the given
+provider. The provider context is an opaque handle set by the provider itself
+and is passed back to the provider by libcrypto in various function calls.
+
+OSSL_PROVIDER_get0_dispatch() returns the provider's dispatch table as it was
+returned in the I<out> parameter from the provider's init function. See
+L<provider-base(7)>.
+
+If it is permissible to cache references to this array then I<*no_store> is set
+to 0 or 1 otherwise. If the array is not cacheable then it is assumed to
+have a short lifetime.
+
+OSSL_PROVIDER_get0_name() returns the name of the given provider.
+
+OSSL_PROVIDER_get_capabilities() provides information about the capabilities
+supported by the provider specified in I<prov> with the capability name
+I<capability>. For each capability of that name supported by the provider it
+will call the callback I<cb> and supply a set of L<OSSL_PARAM(3)>s describing the
+capability. It will also pass back the argument I<arg>. For more details about
+capabilities and what they can be used for please see
+L<provider-base(7)/CAPABILTIIES>.
+
+=head1 RETURN VALUES
+
+OSSL_PROVIDER_set_default_search_path(), OSSL_PROVIDER_add(),
+OSSL_PROVIDER_unload(), OSSL_PROVIDER_get_params() and
+OSSL_PROVIDER_get_capabilities() return 1 on success, or 0 on error.
+
+OSSL_PROVIDER_load() and OSSL_PROVIDER_try_load() return a pointer to a
+provider object on success, or NULL on error.
+
+OSSL_PROVIDER_do_all() returns 1 if the callback I<cb> returns 1 for every
+provider it is called with, or 0 if any provider callback invocation returns 0;
+callback processing stops at the first callback invocation on a provider
+that returns 0.
+
+OSSL_PROVIDER_available() returns 1 if the named provider is available,
+otherwise 0.
+
+OSSL_PROVIDER_gettable_params() returns a pointer to an array
+of constant L<OSSL_PARAM(3)>, or NULL if none is provided.
+
+OSSL_PROVIDER_get_params() and returns 1 on success, or 0 on error.
+
+OSSL_PROVIDER_query_operation() returns an array of OSSL_ALGORITHM or NULL on
+error.
+
+OSSL_PROVIDER_self_test() returns 1 if the self tests pass, or 0 on error.
+
+=head1 EXAMPLES
+
+This demonstrates how to load the provider module "foo" and ask for
+its build information.
+
+ #include <openssl/params.h>
+ #include <openssl/provider.h>
+ #include <openssl/err.h>
+
+ OSSL_PROVIDER *prov = NULL;
+ const char *build = NULL;
+ OSSL_PARAM request[] = {
+ { "buildinfo", OSSL_PARAM_UTF8_PTR, &build, 0, 0 },
+ { NULL, 0, NULL, 0, 0 }
+ };
+
+ if ((prov = OSSL_PROVIDER_load(NULL, "foo")) != NULL
+ && OSSL_PROVIDER_get_params(prov, request))
+ printf("Provider 'foo' buildinfo: %s\n", build);
+ else
+ ERR_print_errors_fp(stderr);
+
+=head1 SEE ALSO
+
+L<openssl-core.h(7)>, L<OSSL_LIB_CTX(3)>, L<provider(7)>
+
+=head1 HISTORY
+
+The type and functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_SELF_TEST_new.pod b/doc/man3/OSSL_SELF_TEST_new.pod
new file mode 100644
index 000000000000..5fe838351908
--- /dev/null
+++ b/doc/man3/OSSL_SELF_TEST_new.pod
@@ -0,0 +1,175 @@
+=pod
+
+=head1 NAME
+
+OSSL_SELF_TEST_new,
+OSSL_SELF_TEST_free,
+OSSL_SELF_TEST_onbegin,
+OSSL_SELF_TEST_oncorrupt_byte,
+OSSL_SELF_TEST_onend - functionality to trigger a callback during a self test
+
+=head1 SYNOPSIS
+
+ #include <openssl/self_test.h>
+
+ OSSL_SELF_TEST *OSSL_SELF_TEST_new(OSSL_CALLBACK *cb, void *cbarg);
+ void OSSL_SELF_TEST_free(OSSL_SELF_TEST *st);
+
+ void OSSL_SELF_TEST_onbegin(OSSL_SELF_TEST *st, const char *type,
+ const char *desc);
+ int OSSL_SELF_TEST_oncorrupt_byte(OSSL_SELF_TEST *st, unsigned char *bytes);
+ void OSSL_SELF_TEST_onend(OSSL_SELF_TEST *st, int ret);
+
+=head1 DESCRIPTION
+
+These methods are intended for use by provider implementors, to display
+diagnostic information during self testing.
+
+OSSL_SELF_TEST_new() allocates an opaque B<OSSL_SELF_TEST> object that has a
+callback and callback argument associated with it.
+
+The callback I<cb> may be triggered multiple times by a self test to indicate
+different phases.
+
+OSSL_SELF_TEST_free() frees the space allocated by OSSL_SELF_TEST_new().
+
+OSSL_SELF_TEST_onbegin() may be inserted at the start of a block of self test
+code. It can be used for diagnostic purposes.
+If this method is called the callback I<cb> will receive the following
+L<OSSL_PARAM(3)> object.
+
+=over 4
+
+=item "st-phase" (B<OSSL_PROV_PARAM_SELF_TEST_PHASE>) <UTF8 string>
+
+The value is the string "Start"
+
+=back
+
+OSSL_SELF_TEST_oncorrupt_byte() may be inserted just after the known answer is
+calculated, but before the self test compares the result. The first byte in the
+passed in array of I<bytes> will be corrupted if the callback returns 0,
+otherwise it leaves the array unaltered. It can be used for failure testing.
+The I<type> and I<desc> can be used to identify an individual self test to
+target for failure testing.
+If this method is called the callback I<cb> will receive the following
+L<OSSL_PARAM(3)> object.
+
+=over 4
+
+=item "st-phase" (B<OSSL_PROV_PARAM_SELF_TEST_PHASE>) <UTF8 string>
+
+The value is the string "Corrupt"
+
+=back
+
+OSSL_SELF_TEST_onend() may be inserted at the end of a block of self test code
+just before cleanup to indicate if the test passed or failed. It can be used for
+diagnostic purposes.
+If this method is called the callback I<cb> will receive the following
+L<OSSL_PARAM(3)> object.
+
+=over 4
+
+=item "st-phase" (B<OSSL_PROV_PARAM_SELF_TEST_PHASE>) <UTF8 string>
+
+The value of the string is "Pass" if I<ret> is non zero, otherwise it has the
+value "Fail".
+
+=back
+
+After the callback I<cb> has been called the values that were set by
+OSSL_SELF_TEST_onbegin() for I<type> and I<desc> are set to the value "None".
+
+If OSSL_SELF_TEST_onbegin(), OSSL_SELF_TEST_oncorrupt_byte() or
+OSSL_SELF_TEST_onend() is called the following additional L<OSSL_PARAM(3)> are
+passed to the callback.
+
+=over 4
+
+=item "st-type" (B<OSSL_PROV_PARAM_SELF_TEST_TYPE>) <UTF8 string>
+
+The value is setup by the I<type> passed to OSSL_SELF_TEST_onbegin().
+This allows the callback to identify the type of test being run.
+
+=item "st-desc" (B<OSSL_PROV_PARAM_SELF_TEST_DESC>) <UTF8 string>
+
+The value is setup by the I<type> passed to OSSL_SELF_TEST_onbegin().
+This allows the callback to identify the sub category of the test being run.
+
+=back
+
+=head1 RETURN VALUES
+
+OSSL_SELF_TEST_new() returns the allocated B<OSSL_SELF_TEST> object, or NULL if
+it fails.
+
+OSSL_SELF_TEST_oncorrupt_byte() returns 1 if corruption occurs, otherwise it
+returns 0.
+
+=head1 EXAMPLES
+
+A single self test could be set up in the following way:
+
+ OSSL_SELF_TEST *st = NULL;
+ OSSL_CALLBACK *cb;
+ void *cbarg;
+ int ok = 0;
+ unsigned char out[EVP_MAX_MD_SIZE];
+ unsigned int out_len = 0;
+ EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+ EVP_MD *md = EVP_MD_fetch(libctx, t->algorithm, NULL);
+
+ /*
+ * Retrieve the callback - will be NULL if not set by the application via
+ * OSSL_SELF_TEST_set_callback().
+ */
+ OSSL_SELF_TEST_get_callback(libctx, &cb, &cbarg);
+
+ st = OSSL_SELF_TEST_new(cb, cb_arg);
+
+ /* Trigger the optional callback */
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_DIGEST,
+ OSSL_SELF_TEST_DESC_MD_SHA2);
+
+ if (!EVP_DigestInit_ex(ctx, md, NULL)
+ || !EVP_DigestUpdate(ctx, pt, pt_len)
+ || !EVP_DigestFinal(ctx, out, &out_len))
+ goto err;
+
+ /* Optional corruption - If the application callback returns 0 */
+ OSSL_SELF_TEST_oncorrupt_byte(st, out);
+
+ if (out_len != t->expected_len
+ || memcmp(out, t->expected, out_len) != 0)
+ goto err;
+ ok = 1;
+ err:
+ OSSL_SELF_TEST_onend(st, ok);
+ EVP_MD_free(md);
+ EVP_MD_CTX_free(ctx);
+
+Multiple self test's can be set up in a similar way by repeating the pattern of
+OSSL_SELF_TEST_onbegin(), OSSL_SELF_TEST_oncorrupt_byte(), OSSL_SELF_TEST_onend()
+for each test.
+
+=head1 SEE ALSO
+
+L<OSSL_SELF_TEST_set_callback(3)>,
+L<openssl-core.h(7)>,
+L<OSSL_PROVIDER-FIPS(7)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_SELF_TEST_set_callback.pod b/doc/man3/OSSL_SELF_TEST_set_callback.pod
new file mode 100644
index 000000000000..9866de018494
--- /dev/null
+++ b/doc/man3/OSSL_SELF_TEST_set_callback.pod
@@ -0,0 +1,52 @@
+=pod
+
+=head1 NAME
+
+OSSL_SELF_TEST_set_callback,
+OSSL_SELF_TEST_get_callback - specify a callback for processing self tests
+
+=head1 SYNOPSIS
+
+ #include <openssl/self_test.h>
+
+ void OSSL_SELF_TEST_set_callback(OSSL_LIB_CTX *ctx, OSSL_CALLBACK *cb, void *cbarg);
+ void OSSL_SELF_TEST_get_callback(OSSL_LIB_CTX *ctx, OSSL_CALLBACK **cb, void **cbarg);
+
+=head1 DESCRIPTION
+
+Set or gets the optional application callback (and the callback argument) that
+is called during self testing.
+The application callback L<OSSL_CALLBACK(3)> is associated with a B<OSSL_LIB_CTX>.
+The application callback function receives information about a running self test,
+and may return a result to the calling self test.
+See L<openssl-core.h(7)> for further information on the callback.
+
+=head1 RETURN VALUES
+
+OSSL_SELF_TEST_get_callback() returns the callback and callback argument that
+has been set via OSSL_SELF_TEST_set_callback() for the given library context
+I<ctx>.
+These returned parameters will be NULL if OSSL_SELF_TEST_set_callback() has
+not been called.
+
+=head1 SEE ALSO
+
+L<openssl-core.h(7)>,
+L<OSSL_PROVIDER-FIPS(7)>
+L<OSSL_SELF_TEST_new(3)>
+L<OSSL_LIB_CTX(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_STORE_INFO.pod b/doc/man3/OSSL_STORE_INFO.pod
index 4c68986c56b2..39bb93fbf5f2 100644
--- a/doc/man3/OSSL_STORE_INFO.pod
+++ b/doc/man3/OSSL_STORE_INFO.pod
@@ -3,15 +3,18 @@
=head1 NAME
OSSL_STORE_INFO, OSSL_STORE_INFO_get_type, OSSL_STORE_INFO_get0_NAME,
-OSSL_STORE_INFO_get0_NAME_description, OSSL_STORE_INFO_get0_PARAMS,
+OSSL_STORE_INFO_get0_NAME_description,
+OSSL_STORE_INFO_get0_PARAMS, OSSL_STORE_INFO_get0_PUBKEY,
OSSL_STORE_INFO_get0_PKEY, OSSL_STORE_INFO_get0_CERT, OSSL_STORE_INFO_get0_CRL,
OSSL_STORE_INFO_get1_NAME, OSSL_STORE_INFO_get1_NAME_description,
-OSSL_STORE_INFO_get1_PARAMS, OSSL_STORE_INFO_get1_PKEY,
-OSSL_STORE_INFO_get1_CERT,
-OSSL_STORE_INFO_get1_CRL, OSSL_STORE_INFO_type_string, OSSL_STORE_INFO_free,
+OSSL_STORE_INFO_get1_PARAMS, OSSL_STORE_INFO_get1_PUBKEY,
+OSSL_STORE_INFO_get1_PKEY, OSSL_STORE_INFO_get1_CERT, OSSL_STORE_INFO_get1_CRL,
+OSSL_STORE_INFO_type_string, OSSL_STORE_INFO_free,
OSSL_STORE_INFO_new_NAME, OSSL_STORE_INFO_set0_NAME_description,
-OSSL_STORE_INFO_new_PARAMS, OSSL_STORE_INFO_new_PKEY, OSSL_STORE_INFO_new_CERT,
-OSSL_STORE_INFO_new_CRL - Functions to manipulate OSSL_STORE_INFO objects
+OSSL_STORE_INFO_new_PARAMS, OSSL_STORE_INFO_new_PUBKEY,
+OSSL_STORE_INFO_new_PKEY, OSSL_STORE_INFO_new_CERT, OSSL_STORE_INFO_new_CRL,
+OSSL_STORE_INFO_new, OSSL_STORE_INFO_get0_data
+- Functions to manipulate OSSL_STORE_INFO objects
=head1 SYNOPSIS
@@ -27,6 +30,8 @@ OSSL_STORE_INFO_new_CRL - Functions to manipulate OSSL_STORE_INFO objects
char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *store_info);
EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *store_info);
EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *store_info);
+ EVP_PKEY *OSSL_STORE_INFO_get0_PUBKEY(const OSSL_STORE_INFO *info);
+ EVP_PKEY *OSSL_STORE_INFO_get1_PUBKEY(const OSSL_STORE_INFO *info);
EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *store_info);
EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *store_info);
X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *store_info);
@@ -41,10 +46,14 @@ OSSL_STORE_INFO_new_CRL - Functions to manipulate OSSL_STORE_INFO objects
OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name);
int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc);
OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(DSA *dsa_params);
+ OSSL_STORE_INFO *OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY *pubkey);
OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey);
OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509);
OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl);
+ OSSL_STORE_INFO *OSSL_STORE_INFO_new(int type, void *data);
+ void *OSSL_STORE_INFO_get0_data(int type, const OSSL_STORE_INFO *info);
+
=head1 DESCRIPTION
These functions are primarily useful for applications to retrieve
@@ -54,52 +63,70 @@ loaders to create B<OSSL_STORE_INFO> holders.
=head2 Types
B<OSSL_STORE_INFO> is an opaque type that's just an intermediary holder for
-the objects that have been retrieved by OSSL_STORE_load() and similar
-functions.
+the objects that have been retrieved by OSSL_STORE_load() and similar functions.
Supported OpenSSL type object can be extracted using one of
-STORE_INFO_get0_TYPE().
+STORE_INFO_get0_<TYPE>() where <TYPE> can be NAME, PARAMS, PKEY, CERT, or CRL.
The life time of this extracted object is as long as the life time of
the B<OSSL_STORE_INFO> it was extracted from, so care should be taken not
to free the latter too early.
-As an alternative, STORE_INFO_get1_TYPE() extracts a duplicate (or the
+As an alternative, STORE_INFO_get1_<TYPE>() extracts a duplicate (or the
same object with its reference count increased), which can be used
after the containing B<OSSL_STORE_INFO> has been freed.
-The object returned by STORE_INFO_get1_TYPE() must be freed separately
+The object returned by STORE_INFO_get1_<TYPE>() must be freed separately
by the caller.
-See L</SUPPORTED OBJECTS> for more information on the types that are
-supported.
+See L</SUPPORTED OBJECTS> for more information on the types that are supported.
=head2 Functions
OSSL_STORE_INFO_get_type() takes a B<OSSL_STORE_INFO> and returns the STORE
type number for the object inside.
+
STORE_INFO_get_type_string() takes a STORE type number and returns a
short string describing it.
OSSL_STORE_INFO_get0_NAME(), OSSL_STORE_INFO_get0_NAME_description(),
-OSSL_STORE_INFO_get0_PARAMS(), OSSL_STORE_INFO_get0_PKEY(),
-OSSL_STORE_INFO_get0_CERT() and OSSL_STORE_INFO_get0_CRL() all take a
-B<OSSL_STORE_INFO> and return the held object of the appropriate OpenSSL
-type provided that's what's held.
+OSSL_STORE_INFO_get0_PARAMS(), OSSL_STORE_INFO_get0_PUBKEY(),
+OSSL_STORE_INFO_get0_PKEY(), OSSL_STORE_INFO_get0_CERT(),
+OSSL_STORE_INFO_get0_CRL()
+all take a B<OSSL_STORE_INFO> and return the object it holds if the
+B<OSSL_STORE_INFO> type (as returned by OSSL_STORE_INFO_get_type())
+matches the function, otherwise NULL.
OSSL_STORE_INFO_get1_NAME(), OSSL_STORE_INFO_get1_NAME_description(),
-OSSL_STORE_INFO_get1_PARAMS(), OSSL_STORE_INFO_get1_PKEY(),
-OSSL_STORE_INFO_get1_CERT() and OSSL_STORE_INFO_get1_CRL() all take a
-B<OSSL_STORE_INFO> and return a duplicate of the held object of the
-appropriate OpenSSL type provided that's what's held.
+OSSL_STORE_INFO_get1_PARAMS(), OSSL_STORE_INFO_get1_PUBKEY(),
+OSSL_STORE_INFO_get1_PKEY(), OSSL_STORE_INFO_get1_CERT() and
+OSSL_STORE_INFO_get1_CRL()
+all take a B<OSSL_STORE_INFO> and return a duplicate the object it
+holds if the B<OSSL_STORE_INFO> type (as returned by
+OSSL_STORE_INFO_get_type()) matches the function, otherwise NULL.
OSSL_STORE_INFO_free() frees a B<OSSL_STORE_INFO> and its contained type.
OSSL_STORE_INFO_new_NAME() , OSSL_STORE_INFO_new_PARAMS(),
-OSSL_STORE_INFO_new_PKEY(), OSSL_STORE_INFO_new_CERT() and
-OSSL_STORE_INFO_new_CRL() create a B<OSSL_STORE_INFO>
-object to hold the given input object.
-Additionally, for B<OSSL_STORE_INFO_NAME>` objects,
+, OSSL_STORE_INFO_new_PUBKEY(), OSSL_STORE_INFO_new_PKEY(),
+OSSL_STORE_INFO_new_CERT() and OSSL_STORE_INFO_new_CRL()
+create a B<OSSL_STORE_INFO> object to hold the given input object.
+On success the input object is consumed.
+
+Additionally, for B<OSSL_STORE_INFO_NAME> objects,
OSSL_STORE_INFO_set0_NAME_description() can be used to add an extra
description.
This description is meant to be human readable and should be used for
information printout.
+OSSL_STORE_INFO_new() creates a B<OSSL_STORE_INFO> with an arbitrary I<type>
+number and I<data> structure. It's the responsibility of the caller to
+define type numbers other than the ones defined by F<< <openssl/store.h> >>,
+and to handle freeing the associated data structure on their own.
+I<Using type numbers that are defined by F<< <openssl/store.h> >> may cause
+undefined behaviours, including crashes>.
+
+OSSL_STORE_INFO_get0_data() returns the data pointer that was passed to
+OSSL_STORE_INFO_new() if I<type> matches the type number in I<info>.
+
+OSSL_STORE_INFO_new() and OSSL_STORE_INFO_get0_data() may be useful for
+applications that define their own STORE data, but must be used with care.
+
=head1 SUPPORTED OBJECTS
Currently supported object types are:
@@ -139,7 +166,11 @@ Key parameters.
=item OSSL_STORE_INFO_PKEY
-A private/public key of some sort.
+A keypair or just a private key (possibly with key parameters).
+
+=item OSSL_STORE_INFO_PUBKEY
+
+A public key (possibly with key parameters).
=item OSSL_STORE_INFO_CERT
@@ -162,18 +193,18 @@ OSSL_STORE_INFO_get0_PARAMS(), OSSL_STORE_INFO_get0_PKEY(),
OSSL_STORE_INFO_get0_CERT() and OSSL_STORE_INFO_get0_CRL() all return
a pointer to the OpenSSL object on success, NULL otherwise.
-OSSL_STORE_INFO_get0_NAME(), OSSL_STORE_INFO_get0_NAME_description(),
-OSSL_STORE_INFO_get0_PARAMS(), OSSL_STORE_INFO_get0_PKEY(),
-OSSL_STORE_INFO_get0_CERT() and OSSL_STORE_INFO_get0_CRL() all return
+OSSL_STORE_INFO_get1_NAME(), OSSL_STORE_INFO_get1_NAME_description(),
+OSSL_STORE_INFO_get1_PARAMS(), OSSL_STORE_INFO_get1_PKEY(),
+OSSL_STORE_INFO_get1_CERT() and OSSL_STORE_INFO_get1_CRL() all return
a pointer to a duplicate of the OpenSSL object on success, NULL otherwise.
-OSSL_STORE_INFO_type_string() returns a string on success, or B<NULL> on
+OSSL_STORE_INFO_type_string() returns a string on success, or NULL on
failure.
OSSL_STORE_INFO_new_NAME(), OSSL_STORE_INFO_new_PARAMS(),
OSSL_STORE_INFO_new_PKEY(), OSSL_STORE_INFO_new_CERT() and
OSSL_STORE_INFO_new_CRL() return a B<OSSL_STORE_INFO>
-pointer on success, or B<NULL> on failure.
+pointer on success, or NULL on failure.
OSSL_STORE_INFO_set0_NAME_description() returns 1 on success, or 0 on
failure.
@@ -184,19 +215,15 @@ L<ossl_store(7)>, L<OSSL_STORE_open(3)>, L<OSSL_STORE_register_loader(3)>
=head1 HISTORY
-OSSL_STORE_INFO(), OSSL_STORE_INFO_get_type(), OSSL_STORE_INFO_get0_NAME(),
-OSSL_STORE_INFO_get0_PARAMS(), OSSL_STORE_INFO_get0_PKEY(),
-OSSL_STORE_INFO_get0_CERT(), OSSL_STORE_INFO_get0_CRL(),
-OSSL_STORE_INFO_type_string(), OSSL_STORE_INFO_free(), OSSL_STORE_INFO_new_NAME(),
-OSSL_STORE_INFO_new_PARAMS(), OSSL_STORE_INFO_new_PKEY(),
-OSSL_STORE_INFO_new_CERT() and OSSL_STORE_INFO_new_CRL()
-were added in OpenSSL 1.1.1.
+The OSSL_STORE API was added in OpenSSL 1.1.1.
+
+The OSSL_STORE_INFO_PUBKEY object type was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OSSL_STORE_LOADER.pod b/doc/man3/OSSL_STORE_LOADER.pod
index b0c15b01c334..b1d838604bad 100644
--- a/doc/man3/OSSL_STORE_LOADER.pod
+++ b/doc/man3/OSSL_STORE_LOADER.pod
@@ -2,14 +2,26 @@
=head1 NAME
-OSSL_STORE_LOADER, OSSL_STORE_LOADER_CTX, OSSL_STORE_LOADER_new,
+OSSL_STORE_LOADER,
+OSSL_STORE_LOADER_fetch,
+OSSL_STORE_LOADER_up_ref,
+OSSL_STORE_LOADER_free,
+OSSL_STORE_LOADER_get0_provider,
+OSSL_STORE_LOADER_get0_properties,
+OSSL_STORE_LOADER_is_a,
+OSSL_STORE_LOADER_get0_description,
+OSSL_STORE_LOADER_do_all_provided,
+OSSL_STORE_LOADER_names_do_all,
+OSSL_STORE_LOADER_CTX, OSSL_STORE_LOADER_new,
OSSL_STORE_LOADER_get0_engine, OSSL_STORE_LOADER_get0_scheme,
-OSSL_STORE_LOADER_set_open, OSSL_STORE_LOADER_set_ctrl,
+OSSL_STORE_LOADER_set_open, OSSL_STORE_LOADER_set_open_ex,
+OSSL_STORE_LOADER_set_attach, OSSL_STORE_LOADER_set_ctrl,
OSSL_STORE_LOADER_set_expect, OSSL_STORE_LOADER_set_find,
OSSL_STORE_LOADER_set_load, OSSL_STORE_LOADER_set_eof,
OSSL_STORE_LOADER_set_error, OSSL_STORE_LOADER_set_close,
-OSSL_STORE_LOADER_free, OSSL_STORE_register_loader,
-OSSL_STORE_unregister_loader, OSSL_STORE_open_fn, OSSL_STORE_ctrl_fn,
+OSSL_STORE_register_loader, OSSL_STORE_unregister_loader,
+OSSL_STORE_open_fn, OSSL_STORE_open_ex_fn,
+OSSL_STORE_attach_fn, OSSL_STORE_ctrl_fn,
OSSL_STORE_expect_fn, OSSL_STORE_find_fn,
OSSL_STORE_load_fn, OSSL_STORE_eof_fn, OSSL_STORE_error_fn,
OSSL_STORE_close_fn - Types and functions to manipulate, register and
@@ -21,6 +33,29 @@ unregister STORE loaders for different URI schemes
typedef struct ossl_store_loader_st OSSL_STORE_LOADER;
+ OSSL_STORE_LOADER *OSSL_STORE_LOADER_fetch(OSSL_LIB_CTX *libctx,
+ const char *scheme,
+ const char *properties);
+ int OSSL_STORE_LOADER_up_ref(OSSL_STORE_LOADER *loader);
+ void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader);
+ const OSSL_PROVIDER *OSSL_STORE_LOADER_get0_provider(const OSSL_STORE_LOADER *
+ loader);
+ const char *OSSL_STORE_LOADER_get0_properties(const OSSL_STORE_LOADER *loader);
+ const char *OSSL_STORE_LOADER_get0_description(const OSSL_STORE_LOADER *loader);
+ int OSSL_STORE_LOADER_is_a(const OSSL_STORE_LOADER *loader,
+ const char *scheme);
+ void OSSL_STORE_LOADER_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*user_fn)(OSSL_STORE_LOADER *loader,
+ void *arg),
+ void *user_arg);
+ int OSSL_STORE_LOADER_names_do_all(const OSSL_STORE_LOADER *loader,
+ void (*fn)(const char *name, void *data),
+ void *data);
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
OSSL_STORE_LOADER *OSSL_STORE_LOADER_new(ENGINE *e, const char *scheme);
const ENGINE *OSSL_STORE_LOADER_get0_engine(const OSSL_STORE_LOADER
*store_loader);
@@ -30,11 +65,21 @@ unregister STORE loaders for different URI schemes
/* struct ossl_store_loader_ctx_st is defined differently by each loader */
typedef struct ossl_store_loader_ctx_st OSSL_STORE_LOADER_CTX;
- typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_open_fn)(const char *uri,
- const UI_METHOD *ui_method,
- void *ui_data);
+ typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_open_fn)(
+ const char *uri, const UI_METHOD *ui_method, void *ui_data);
int OSSL_STORE_LOADER_set_open(OSSL_STORE_LOADER *store_loader,
OSSL_STORE_open_fn store_open_function);
+ typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_open_ex_fn)(
+ const char *uri, const UI_METHOD *ui_method, void *ui_data);
+ int OSSL_STORE_LOADER_set_open_ex
+ (OSSL_STORE_LOADER *store_loader,
+ OSSL_STORE_open_ex_fn store_open_ex_function);
+ typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_attach_fn)
+ (const OSSL_STORE_LOADER *loader, BIO *bio,
+ OSSL_LIB_CTX *libctx, const char *propq,
+ const UI_METHOD *ui_method, void *ui_data);
+ int OSSL_STORE_LOADER_set_attach(OSSL_STORE_LOADER *loader,
+ OSSL_STORE_attach_fn attach_function);
typedef int (*OSSL_STORE_ctrl_fn)(OSSL_STORE_LOADER_CTX *ctx, int cmd,
va_list args);
int OSSL_STORE_LOADER_set_ctrl(OSSL_STORE_LOADER *store_loader,
@@ -67,48 +112,91 @@ unregister STORE loaders for different URI schemes
=head1 DESCRIPTION
-These functions help applications and engines to create loaders for
-schemes they support.
+B<OSSL_STORE_LOADER> is a method for OSSL_STORE loaders, which implement
+OSSL_STORE_open(), OSSL_STORE_open_ex(), OSSL_STORE_load(),
+OSSL_STORE_eof(), OSSL_STORE_error() and OSSL_STORE_close() for specific
+storage schemes.
+
+OSSL_STORE_LOADER_fetch() looks for an implementation for a storage
+I<scheme> within the providers that has been loaded into the B<OSSL_LIB_CTX>
+given by I<libctx>, and with the properties given by I<properties>.
+
+OSSL_STORE_LOADER_up_ref() increments the reference count for the given
+I<loader>.
+
+OSSL_STORE_LOADER_free() decrements the reference count for the given
+I<loader>, and when the count reaches zero, frees it.
+
+OSSL_STORE_LOADER_get0_provider() returns the provider of the given
+I<loader>.
+
+OSSL_STORE_LOADER_get0_properties() returns the property definition associated
+with the given I<loader>.
-=head2 Types
+OSSL_STORE_LOADER_is_a() checks if I<loader> is an implementation
+of an algorithm that's identifiable with I<scheme>.
-B<OSSL_STORE_LOADER> is the type to hold a loader.
-It contains a scheme and the functions needed to implement
-OSSL_STORE_open(), OSSL_STORE_load(), OSSL_STORE_eof(), OSSL_STORE_error() and
-OSSL_STORE_close() for this scheme.
+OSSL_STORE_LOADER_get0_description() returns a description of the I<loader>, meant
+for display and human consumption. The description is at the discretion of the
+I<loader> implementation.
+
+OSSL_STORE_LOADER_do_all_provided() traverses all store implementations
+by all activated providers in the library context I<libctx>, and for each
+of the implementations, calls I<user_fn> with the implementation method and
+I<user_arg> as arguments.
+
+OSSL_STORE_LOADER_names_do_all() traverses all names for the given
+I<loader>, and calls I<fn> with each name and I<data>.
+
+=head2 Legacy Types and Functions (deprecated)
+
+These functions help applications and engines to create loaders for
+schemes they support. These are all deprecated and discouraged in favour of
+provider implementations, see L<provider-storemgmt(7)>.
B<OSSL_STORE_LOADER_CTX> is a type template, to be defined by each loader
-using B<struct ossl_store_loader_ctx_st { ... }>.
+using C<struct ossl_store_loader_ctx_st { ... }>.
-B<OSSL_STORE_open_fn>, B<OSSL_STORE_ctrl_fn>, B<OSSL_STORE_expect_fn>,
-B<OSSL_STORE_find_fn>, B<OSSL_STORE_load_fn>, B<OSSL_STORE_eof_fn>,
-and B<OSSL_STORE_close_fn>
+B<OSSL_STORE_open_fn>, B<OSSL_STORE_open_ex_fn>,
+B<OSSL_STORE_ctrl_fn>, B<OSSL_STORE_expect_fn>, B<OSSL_STORE_find_fn>,
+B<OSSL_STORE_load_fn>, B<OSSL_STORE_eof_fn>, and B<OSSL_STORE_close_fn>
are the function pointer types used within a STORE loader.
The functions pointed at define the functionality of the given loader.
=over 4
-=item B<OSSL_STORE_open_fn>
+=item B<OSSL_STORE_open_fn> and B<OSSL_STORE_open_ex_fn>
-This function takes a URI and is expected to interpret it in the best
-manner possible according to the scheme the loader implements, it also
-takes a B<UI_METHOD> and associated data, to be used any time
-something needs to be prompted for.
+B<OSSL_STORE_open_ex_fn> takes a URI and is expected to
+interpret it in the best manner possible according to the scheme the
+loader implements. It also takes a B<UI_METHOD> and associated data,
+to be used any time something needs to be prompted for, as well as a
+library context I<libctx> with an associated property query I<propq>,
+to be used when fetching necessary algorithms to perform the loads.
Furthermore, this function is expected to initialize what needs to be
-initialized, to create a private data store (B<OSSL_STORE_LOADER_CTX>, see
-above), and to return it.
+initialized, to create a private data store (B<OSSL_STORE_LOADER_CTX>,
+see above), and to return it.
If something goes wrong, this function is expected to return NULL.
+B<OSSL_STORE_open_fn> does the same thing as
+B<OSSL_STORE_open_ex_fn> but uses NULL for the library
+context I<libctx> and property query I<propq>.
+
+=item B<OSSL_STORE_attach_fn>
+
+This function takes a B<BIO>, otherwise works like
+B<OSSL_STORE_open_ex_fn>.
+
=item B<OSSL_STORE_ctrl_fn>
This function takes a B<OSSL_STORE_LOADER_CTX> pointer, a command number
-B<cmd> and a B<va_list> B<args> and is used to manipulate loader
+I<cmd> and a B<va_list> I<args> and is used to manipulate loader
specific parameters.
=begin comment
Globally known command numbers are documented in L<OSSL_STORE_ctrl(3)>,
-along with what B<args> are expected with each of them.
+along with what I<args> are expected with each of them.
=end comment
@@ -121,9 +209,9 @@ This function is expected to return 1 on success, 0 on error.
=item B<OSSL_STORE_expect_fn>
This function takes a B<OSSL_STORE_LOADER_CTX> pointer and a B<OSSL_STORE_INFO>
-identity B<expected>, and is used to tell the loader what object type is
+identity I<expected>, and is used to tell the loader what object type is
expected.
-B<expected> may be zero to signify that no specific object type is expected.
+I<expected> may be zero to signify that no specific object type is expected.
This function is expected to return 1 on success, 0 on error.
@@ -133,10 +221,10 @@ This function takes a B<OSSL_STORE_LOADER_CTX> pointer and a
B<OSSL_STORE_SEARCH> search criterion, and is used to tell the loader what
to search for.
-When called with the loader context being B<NULL>, this function is expected
+When called with the loader context being NULL, this function is expected
to return 1 if the loader supports the criterion, otherwise 0.
-When called with the loader context being something other than B<NULL>, this
+When called with the loader context being something other than NULL, this
function is expected to return 1 on success, 0 on error.
=item B<OSSL_STORE_load_fn>
@@ -175,88 +263,126 @@ It returns 1 on success and 0 on error.
=back
-=head2 Functions
-
OSSL_STORE_LOADER_new() creates a new B<OSSL_STORE_LOADER>.
-It takes an B<ENGINE> B<e> and a string B<scheme>.
-B<scheme> must I<always> be set.
-Both B<e> and B<scheme> are used as is and must therefore be alive as
+It takes an B<ENGINE> I<e> and a string I<scheme>.
+I<scheme> must I<always> be set.
+Both I<e> and I<scheme> are used as is and must therefore be alive as
long as the created loader is.
-OSSL_STORE_LOADER_get0_engine() returns the engine of the B<store_loader>.
-OSSL_STORE_LOADER_get0_scheme() returns the scheme of the B<store_loader>.
+OSSL_STORE_LOADER_get0_engine() returns the engine of the I<store_loader>.
+OSSL_STORE_LOADER_get0_scheme() returns the scheme of the I<store_loader>.
OSSL_STORE_LOADER_set_open() sets the opener function for the
-B<store_loader>.
+I<store_loader>.
+
+OSSL_STORE_LOADER_set_open_ex() sets the opener with library context
+function for the I<store_loader>.
+
+OSSL_STORE_LOADER_set_attach() sets the attacher function for the
+I<store_loader>.
OSSL_STORE_LOADER_set_ctrl() sets the control function for the
-B<store_loader>.
+I<store_loader>.
OSSL_STORE_LOADER_set_expect() sets the expect function for the
-B<store_loader>.
+I<store_loader>.
OSSL_STORE_LOADER_set_load() sets the loader function for the
-B<store_loader>.
+I<store_loader>.
OSSL_STORE_LOADER_set_eof() sets the end of file checker function for the
-B<store_loader>.
+I<store_loader>.
OSSL_STORE_LOADER_set_close() sets the closing function for the
-B<store_loader>.
+I<store_loader>.
-OSSL_STORE_LOADER_free() frees the given B<store_loader>.
+OSSL_STORE_LOADER_free() frees the given I<store_loader>.
-OSSL_STORE_register_loader() register the given B<store_loader> and thereby
-makes it available for use with OSSL_STORE_open(), OSSL_STORE_load(),
-OSSL_STORE_eof() and OSSL_STORE_close().
+OSSL_STORE_register_loader() register the given I<store_loader> and
+thereby makes it available for use with OSSL_STORE_open(),
+OSSL_STORE_open_ex(), OSSL_STORE_load(), OSSL_STORE_eof()
+and OSSL_STORE_close().
OSSL_STORE_unregister_loader() unregister the store loader for the given
-B<scheme>.
+I<scheme>.
-=head1 NOTES
+=head1 RETURN VALUES
-The B<file:> scheme has built in support.
+OSSL_STORE_LOADER_fetch() returns a pointer to an OSSL_STORE_LOADER object,
+or NULL on error.
-=head1 RETURN VALUES
+OSSL_STORE_LOADER_up_ref() returns 1 on success, or 0 on error.
+
+OSSL_STORE_LOADER_names_do_all() returns 1 if the callback was called for all
+names. A return value of 0 means that the callback was not called for any names.
-The functions with the types B<OSSL_STORE_open_fn>, B<OSSL_STORE_ctrl_fn>,
-B<OSSL_STORE_expect_fn>,
-B<OSSL_STORE_load_fn>, B<OSSL_STORE_eof_fn> and B<OSSL_STORE_close_fn> have the
-same return values as OSSL_STORE_open(), OSSL_STORE_ctrl(), OSSL_STORE_expect(),
+OSSL_STORE_LOADER_free() doesn't return any value.
+
+OSSL_STORE_LOADER_get0_provider() returns a pointer to a provider object, or
+NULL on error.
+
+OSSL_STORE_LOADER_get0_properties() returns a pointer to a property
+definition string, or NULL on error.
+
+OSSL_STORE_LOADER_is_a() returns 1 if I<loader> was identifiable,
+otherwise 0.
+
+OSSL_STORE_LOADER_get0_description() returns a pointer to a decription, or NULL if
+there isn't one.
+
+The functions with the types B<OSSL_STORE_open_fn>,
+B<OSSL_STORE_open_ex_fn>, B<OSSL_STORE_ctrl_fn>,
+B<OSSL_STORE_expect_fn>, B<OSSL_STORE_load_fn>, B<OSSL_STORE_eof_fn>
+and B<OSSL_STORE_close_fn> have the same return values as OSSL_STORE_open(),
+OSSL_STORE_open_ex(), OSSL_STORE_ctrl(), OSSL_STORE_expect(),
OSSL_STORE_load(), OSSL_STORE_eof() and OSSL_STORE_close(), respectively.
OSSL_STORE_LOADER_new() returns a pointer to a B<OSSL_STORE_LOADER> on success,
-or B<NULL> on failure.
+or NULL on failure.
-OSSL_STORE_LOADER_set_open(), OSSL_STORE_LOADER_set_ctrl(),
-OSSL_STORE_LOADER_set_load(), OSSL_STORE_LOADER_set_eof() and
-OSSL_STORE_LOADER_set_close() return 1 on success, or 0 on failure.
+OSSL_STORE_LOADER_set_open(), OSSL_STORE_LOADER_set_open_ex(),
+OSSL_STORE_LOADER_set_ctrl(), OSSL_STORE_LOADER_set_load(),
+OSSL_STORE_LOADER_set_eof() and OSSL_STORE_LOADER_set_close() return 1
+on success, or 0 on failure.
OSSL_STORE_register_loader() returns 1 on success, or 0 on failure.
OSSL_STORE_unregister_loader() returns the unregistered loader on success,
-or B<NULL> on failure.
+or NULL on failure.
=head1 SEE ALSO
-L<ossl_store(7)>, L<OSSL_STORE_open(3)>
+L<ossl_store(7)>, L<OSSL_STORE_open(3)>, L<OSSL_LIB_CTX(3)>,
+L<provider-storemgmt(7)>
=head1 HISTORY
-OSSL_STORE_LOADER(), OSSL_STORE_LOADER_CTX(), OSSL_STORE_LOADER_new(),
-OSSL_STORE_LOADER_set0_scheme(), OSSL_STORE_LOADER_set_open(),
-OSSL_STORE_LOADER_set_ctrl(), OSSL_STORE_LOADER_set_load(),
-OSSL_STORE_LOADER_set_eof(), OSSL_STORE_LOADER_set_close(),
-OSSL_STORE_LOADER_free(), OSSL_STORE_register_loader(),
+OSSL_STORE_LOADER_fetch(), OSSL_STORE_LOADER_up_ref(),
+OSSL_STORE_LOADER_free(), OSSL_STORE_LOADER_get0_provider(),
+OSSL_STORE_LOADER_get0_properties(), OSSL_STORE_LOADER_is_a(),
+OSSL_STORE_LOADER_do_all_provided() and
+OSSL_STORE_LOADER_names_do_all() were added in OpenSSL 3.0.
+
+OSSL_STORE_open_ex_fn() was added in OpenSSL 3.0.
+
+B<OSSL_STORE_LOADER>, B<OSSL_STORE_LOADER_CTX>, OSSL_STORE_LOADER_new(),
+OSSL_STORE_LOADER_set0_scheme(), OSSL_STORE_LOADER_get0_scheme(),
+OSSL_STORE_LOADER_get0_engine(), OSSL_STORE_LOADER_set_expect(),
+OSSL_STORE_LOADER_set_find(), OSSL_STORE_LOADER_set_attach(),
+OSSL_STORE_LOADER_set_open_ex(), OSSL_STORE_LOADER_set_open(),
+OSSL_STORE_LOADER_set_ctrl(),
+OSSL_STORE_LOADER_set_load(), OSSL_STORE_LOADER_set_eof(),
+OSSL_STORE_LOADER_set_close(), OSSL_STORE_LOADER_free(),
+OSSL_STORE_register_loader(), OSSL_STORE_LOADER_set_error(),
OSSL_STORE_unregister_loader(), OSSL_STORE_open_fn(), OSSL_STORE_ctrl_fn(),
OSSL_STORE_load_fn(), OSSL_STORE_eof_fn() and OSSL_STORE_close_fn()
-were added in OpenSSL 1.1.1.
+were added in OpenSSL 1.1.1, and became deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OSSL_STORE_SEARCH.pod b/doc/man3/OSSL_STORE_SEARCH.pod
index 0c2dd2bc24c5..79186b08997e 100644
--- a/doc/man3/OSSL_STORE_SEARCH.pod
+++ b/doc/man3/OSSL_STORE_SEARCH.pod
@@ -139,27 +139,27 @@ OSSL_STORE_SEARCH_by_name(),
OSSL_STORE_SEARCH_by_issuer_serial(),
OSSL_STORE_SEARCH_by_key_fingerprint(),
and OSSL_STORE_SEARCH_by_alias()
-return a B<OSSL_STORE_SEARCH> pointer on success, or B<NULL> on failure.
+return a B<OSSL_STORE_SEARCH> pointer on success, or NULL on failure.
OSSL_STORE_SEARCH_get_type() returns the criterion type of the given
B<OSSL_STORE_SEARCH>.
There is no error value.
OSSL_STORE_SEARCH_get0_name() returns a B<X509_NAME> pointer on success,
-or B<NULL> when the given B<OSSL_STORE_SEARCH> was of a different type.
+or NULL when the given B<OSSL_STORE_SEARCH> was of a different type.
OSSL_STORE_SEARCH_get0_serial() returns a B<ASN1_INTEGER> pointer on success,
-or B<NULL> when the given B<OSSL_STORE_SEARCH> was of a different type.
+or NULL when the given B<OSSL_STORE_SEARCH> was of a different type.
OSSL_STORE_SEARCH_get0_bytes() returns a B<const unsigned char> pointer and
-sets B<*length> to the strings length on success, or B<NULL> when the given
+sets I<*length> to the strings length on success, or NULL when the given
B<OSSL_STORE_SEARCH> was of a different type.
OSSL_STORE_SEARCH_get0_string() returns a B<const char> pointer on success,
-or B<NULL> when the given B<OSSL_STORE_SEARCH> was of a different type.
+or NULL when the given B<OSSL_STORE_SEARCH> was of a different type.
OSSL_STORE_SEARCH_get0_digest() returns a B<const EVP_MD> pointer.
-B<NULL> is a valid value and means that the store loader default will
+NULL is a valid value and means that the store loader default will
be used when applicable.
=head1 SEE ALSO
@@ -183,9 +183,9 @@ were added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OSSL_STORE_attach.pod b/doc/man3/OSSL_STORE_attach.pod
new file mode 100644
index 000000000000..f272961bac34
--- /dev/null
+++ b/doc/man3/OSSL_STORE_attach.pod
@@ -0,0 +1,47 @@
+=pod
+
+=head1 NAME
+
+OSSL_STORE_attach - Functions to read objects from a BIO
+
+=head1 SYNOPSIS
+
+ #include <openssl/store.h>
+
+ OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bio, const char *scheme,
+ OSSL_LIB_CTX *libctx, const char *propq,
+ const UI_METHOD *ui_method, void *ui_data,
+ const OSSL_PARAM params[],
+ OSSL_STORE_post_process_info_fn post_process,
+ void *post_process_data);
+
+=head1 DESCRIPTION
+
+OSSL_STORE_attach() works like L<OSSL_STORE_open(3)>, except it takes a B<BIO>
+I<bio> instead of a I<uri>, along with a I<scheme> to determine what loader
+should be used to process the data. The reference count of the B<BIO> object
+is increased by 1 if the call is successful.
+
+=head1 RETURN VALUES
+
+OSSL_STORE_attach() returns a pointer to a B<OSSL_STORE_CTX> on success, or
+NULL on failure.
+
+=head1 SEE ALSO
+
+L<ossl_store(7)>, L<OSSL_STORE_open(3)>
+
+=head1 HISTORY
+
+OSSL_STORE_attach() was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_STORE_expect.pod b/doc/man3/OSSL_STORE_expect.pod
index ff3fb2a69d31..a60661f096ba 100644
--- a/doc/man3/OSSL_STORE_expect.pod
+++ b/doc/man3/OSSL_STORE_expect.pod
@@ -21,18 +21,20 @@ OSSL_STORE_find
OSSL_STORE_expect() helps applications filter what OSSL_STORE_load() returns
by specifying a B<OSSL_STORE_INFO> type.
-For example, if C<file:/foo/bar/store.pem> contains several different objects
-and only the certificates are interesting, the application can simply say
+By default, no expectations on the types of objects to be loaded are made.
+I<expected_type> may be 0 to indicate explicitly that no expectation is made,
+or it may be any of the known object types (see
+L<OSSL_STORE_INFO(3)/SUPPORTED OBJECTS>) except for B<OSSL_STORE_INFO_NAME>.
+For example, if C<file:/foo/bar/store.pem> contains several objects of different
+type and only certificates are interesting, the application can simply say
that it expects the type B<OSSL_STORE_INFO_CERT>.
-All known object types (see L<OSSL_STORE_INFO(3)/SUPPORTED OBJECTS>)
-except for B<OSSL_STORE_INFO_NAME> are supported.
OSSL_STORE_find() helps applications specify a criterion for a more fine
grained search of objects.
OSSL_STORE_supports_search() checks if the loader of the given OSSL_STORE
context supports the given search type.
-See L<OSSL_STORE_SEARCH/SUPPORTED CRITERION TYPES> for information on the
+See L<OSSL_STORE_SEARCH(3)/SUPPORTED CRITERION TYPES> for information on the
supported search criterion types.
OSSL_STORE_expect() and OSSL_STORE_find I<must> be called before the first
@@ -69,9 +71,9 @@ were added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OSSL_STORE_open.pod b/doc/man3/OSSL_STORE_open.pod
index 71fdd6932f82..fe51912e84c0 100644
--- a/doc/man3/OSSL_STORE_open.pod
+++ b/doc/man3/OSSL_STORE_open.pod
@@ -2,9 +2,11 @@
=head1 NAME
-OSSL_STORE_CTX, OSSL_STORE_post_process_info_fn, OSSL_STORE_open,
-OSSL_STORE_ctrl, OSSL_STORE_load, OSSL_STORE_eof, OSSL_STORE_error,
-OSSL_STORE_close - Types and functions to read objects from a URI
+OSSL_STORE_CTX, OSSL_STORE_post_process_info_fn,
+OSSL_STORE_open, OSSL_STORE_open_ex,
+OSSL_STORE_ctrl, OSSL_STORE_load, OSSL_STORE_eof,
+OSSL_STORE_error, OSSL_STORE_close
+- Types and functions to read objects from a URI
=head1 SYNOPSIS
@@ -19,18 +21,29 @@ OSSL_STORE_close - Types and functions to read objects from a URI
void *ui_data,
OSSL_STORE_post_process_info_fn post_process,
void *post_process_data);
- int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ... /* args */);
+ OSSL_STORE_CTX *
+ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq,
+ const UI_METHOD *ui_method, void *ui_data,
+ const OSSL_PARAM params[],
+ OSSL_STORE_post_process_info_fn post_process,
+ void *post_process_data);
+
OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx);
int OSSL_STORE_eof(OSSL_STORE_CTX *ctx);
int OSSL_STORE_error(OSSL_STORE_CTX *ctx);
int OSSL_STORE_close(OSSL_STORE_CTX *ctx);
+The following function has been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ... /* args */);
+
=head1 DESCRIPTION
These functions help the application to fetch supported objects (see
L<OSSL_STORE_INFO(3)/SUPPORTED OBJECTS> for information on which those are)
-from a given URI (see L</SUPPORTED SCHEMES> for more information on
-the supported URI schemes).
+from a given URI.
The general method to do so is to "open" the URI using OSSL_STORE_open(),
read each available and supported object using OSSL_STORE_load() as long as
OSSL_STORE_eof() hasn't been reached, and finish it off with OSSL_STORE_close().
@@ -41,19 +54,23 @@ described in L<OSSL_STORE_INFO(3)>.
=head2 Types
B<OSSL_STORE_CTX> is a context variable that holds all the internal
-information for OSSL_STORE_open(), OSSL_STORE_load(), OSSL_STORE_eof() and
-OSSL_STORE_close() to work together.
+information for OSSL_STORE_open(), OSSL_STORE_open_ex(),
+OSSL_STORE_load(), OSSL_STORE_eof() and OSSL_STORE_close() to work
+together.
=head2 Functions
-OSSL_STORE_open() takes a uri or path I<uri>, password UI method
+OSSL_STORE_open_ex() takes a uri or path I<uri>, password UI method
I<ui_method> with associated data I<ui_data>, and post processing
callback I<post_process> with associated data I<post_process_data>,
-opens a channel to the data located at that URI and returns a
+a library context I<libctx> with an associated property query I<propq>,
+and opens a channel to the data located at the URI and returns a
B<OSSL_STORE_CTX> with all necessary internal information.
The given I<ui_method> and I<ui_data> will be reused by all
functions that use B<OSSL_STORE_CTX> when interaction is needed,
for instance to provide a password.
+The auxiliary L<OSSL_PARAM(3)> parameters in I<params> can be set to further
+modify the store operation.
The given I<post_process> and I<post_process_data> will be reused by
OSSL_STORE_load() to manipulate or drop the value to be returned.
The I<post_process> function drops values by returning NULL, which
@@ -61,6 +78,9 @@ will cause OSSL_STORE_load() to start its process over with loading
the next object, until I<post_process> returns something other than
NULL, or the end of data is reached as indicated by OSSL_STORE_eof().
+OSSL_STORE_open() is similar to OSSL_STORE_open_ex() but uses NULL for
+the I<params>, the library context I<libctx> and property query I<propq>.
+
OSSL_STORE_ctrl() takes a B<OSSL_STORE_CTX>, and command number I<cmd> and
more arguments not specified here.
The available loader specific command numbers and arguments they each
@@ -75,14 +95,14 @@ There are also global controls available:
Controls if the loader should attempt to use secure memory for any
allocated B<OSSL_STORE_INFO> and its contents.
-This control expects one argument, a pointer to an B<int> that is expected to
+This control expects one argument, a pointer to an I<int> that is expected to
have the value 1 (yes) or 0 (no).
Any other value is an error.
=back
-OSSL_STORE_load() takes a B<OSSL_STORE_CTX>, tries to load the next available
-object and return it wrapped with B<OSSL_STORE_INFO>.
+OSSL_STORE_load() takes a B<OSSL_STORE_CTX> and tries to load the next
+available object and return it wrapped with B<OSSL_STORE_INFO>.
OSSL_STORE_eof() takes a B<OSSL_STORE_CTX> and checks if we've reached the end
of data.
@@ -97,12 +117,6 @@ by OSSL_STORE_open() and frees all other information that was stored in the
B<OSSL_STORE_CTX>, as well as the B<OSSL_STORE_CTX> itself.
If I<ctx> is NULL it does nothing.
-=head1 SUPPORTED SCHEMES
-
-The basic supported scheme is B<file:>.
-Any other scheme can be added dynamically, using
-OSSL_STORE_register_loader().
-
=head1 NOTES
A string without a scheme prefix (that is, a non-URI string) is
@@ -127,13 +141,13 @@ See L<passphrase-encoding(7)> for further information.
OSSL_STORE_open() returns a pointer to a B<OSSL_STORE_CTX> on success, or
NULL on failure.
-OSSL_STORE_load() returns a pointer to a B<OSSL_STORE_INFO> on success, or
-NULL on error or when end of data is reached.
+OSSL_STORE_load() returns a pointer to a B<OSSL_STORE_INFO> on success, or NULL
+on error or when end of data is reached.
Use OSSL_STORE_error() and OSSL_STORE_eof() to determine the meaning of a
returned NULL.
-OSSL_STORE_eof() returns 1 if the end of data has been reached, otherwise
-0.
+OSSL_STORE_eof() returns 1 if the end of data has been reached
+or an error occurred, 0 otherwise.
OSSL_STORE_error() returns 1 if an error occurred in an OSSL_STORE_load() call,
otherwise 0.
@@ -147,18 +161,24 @@ L<passphrase-encoding(7)>
=head1 HISTORY
-OSSL_STORE_CTX(), OSSL_STORE_post_process_info_fn(), OSSL_STORE_open(),
+OSSL_STORE_open_ex() was added in OpenSSL 3.0.
+
+B<OSSL_STORE_CTX>, OSSL_STORE_post_process_info_fn(), OSSL_STORE_open(),
OSSL_STORE_ctrl(), OSSL_STORE_load(), OSSL_STORE_eof() and OSSL_STORE_close()
were added in OpenSSL 1.1.1.
Handling of NULL I<ctx> argument for OSSL_STORE_close()
was introduced in OpenSSL 1.1.1h.
+OSSL_STORE_open_ex() was added in OpenSSL 3.0.
+
+OSSL_STORE_ctrl() and OSSL_STORE_vctrl() were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OSSL_trace_enabled.pod b/doc/man3/OSSL_trace_enabled.pod
new file mode 100644
index 000000000000..f9c9dffd8c6a
--- /dev/null
+++ b/doc/man3/OSSL_trace_enabled.pod
@@ -0,0 +1,292 @@
+=pod
+
+=head1 NAME
+
+OSSL_trace_enabled, OSSL_trace_begin, OSSL_trace_end,
+OSSL_TRACE_BEGIN, OSSL_TRACE_END, OSSL_TRACE_CANCEL,
+OSSL_TRACE, OSSL_TRACE1, OSSL_TRACE2, OSSL_TRACE3, OSSL_TRACE4,
+OSSL_TRACE5, OSSL_TRACE6, OSSL_TRACE7, OSSL_TRACE8, OSSL_TRACE9,
+OSSL_TRACEV,
+OSSL_TRACE_ENABLED
+- OpenSSL Tracing API
+
+=head1 SYNOPSIS
+
+=for openssl generic
+
+ #include <openssl/trace.h>
+
+ int OSSL_trace_enabled(int category);
+
+ BIO *OSSL_trace_begin(int category);
+ void OSSL_trace_end(int category, BIO *channel);
+
+ /* trace group macros */
+ OSSL_TRACE_BEGIN(category) {
+ ...
+ if (some_error) {
+ /* Leave trace group prematurely in case of an error */
+ OSSL_TRACE_CANCEL(category);
+ goto err;
+ }
+ ...
+ } OSSL_TRACE_END(category);
+
+ /* one-shot trace macros */
+ OSSL_TRACE1(category, format, arg1)
+ OSSL_TRACE2(category, format, arg1, arg2)
+ ...
+ OSSL_TRACE9(category, format, arg1, ..., arg9)
+
+ /* check whether a trace category is enabled */
+ if (OSSL_TRACE_ENABLED(category)) {
+ ...
+ }
+
+=head1 DESCRIPTION
+
+The functions described here are mainly interesting for those who provide
+OpenSSL functionality, either in OpenSSL itself or in engine modules
+or similar.
+
+If tracing is enabled (see L</NOTES> below), these functions are used to
+generate free text tracing output.
+
+The tracing output is divided into types which are enabled
+individually by the application.
+The tracing types are described in detail in
+L<OSSL_trace_set_callback(3)/Trace types>.
+The fallback type B<OSSL_TRACE_CATEGORY_ALL> should I<not> be used
+with the functions described here.
+
+Tracing for a specific category is enabled if a so called
+I<trace channel> is attached to it. A trace channel is simply a
+BIO object to which the application can write its trace output.
+
+The application has two different ways of registering a trace channel,
+either by directly providing a BIO object using OSSL_trace_set_channel(),
+or by providing a callback routine using OSSL_trace_set_callback().
+The latter is wrapped internally by a dedicated BIO object, so for the
+tracing code both channel types are effectively indistinguishable.
+We call them a I<simple trace channel> and a I<callback trace channel>,
+respectively.
+
+To produce trace output, it is necessary to obtain a pointer to the
+trace channel (i.e., the BIO object) using OSSL_trace_begin(), write
+to it using arbitrary BIO output routines, and finally releases the
+channel using OSSL_trace_end(). The OSSL_trace_begin()/OSSL_trace_end()
+calls surrounding the trace output create a group, which acts as a
+critical section (guarded by a mutex) to ensure that the trace output
+of different threads does not get mixed up.
+
+The tracing code normally does not call OSSL_trace_{begin,end}() directly,
+but rather uses a set of convenience macros, see the L</Macros> section below.
+
+
+=head2 Functions
+
+OSSL_trace_enabled() can be used to check if tracing for the given
+I<category> is enabled.
+
+OSSL_trace_begin() is used to starts a tracing section, and get the
+channel for the given I<category> in form of a BIO.
+This BIO can only be used for output.
+
+OSSL_trace_end() is used to end a tracing section.
+
+Using OSSL_trace_begin() and OSSL_trace_end() to wrap tracing sections
+is I<mandatory>.
+The result of trying to produce tracing output outside of such
+sections is undefined.
+
+=head2 Macros
+
+There are a number of convenience macros defined, to make tracing
+easy and consistent.
+
+OSSL_TRACE_BEGIN() and OSSL_TRACE_END() reserve the B<BIO> C<trc_out> and are
+used as follows to wrap a trace section:
+
+ OSSL_TRACE_BEGIN(TLS) {
+
+ BIO_fprintf(trc_out, ... );
+
+ } OSSL_TRACE_END(TLS);
+
+This will normally expand to:
+
+ do {
+ BIO *trc_out = OSSL_trace_begin(OSSL_TRACE_CATEGORY_TLS);
+ if (trc_out != NULL) {
+ ...
+ BIO_fprintf(trc_out, ...);
+ }
+ OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out);
+ } while (0);
+
+OSSL_TRACE_CANCEL() must be used before returning from or jumping out of a
+trace section:
+
+ OSSL_TRACE_BEGIN(TLS) {
+
+ if (some_error) {
+ OSSL_TRACE_CANCEL(TLS);
+ goto err;
+ }
+ BIO_fprintf(trc_out, ... );
+
+ } OSSL_TRACE_END(TLS);
+
+This will normally expand to:
+
+ do {
+ BIO *trc_out = OSSL_trace_begin(OSSL_TRACE_CATEGORY_TLS);
+ if (trc_out != NULL) {
+ if (some_error) {
+ OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out);
+ goto err;
+ }
+ BIO_fprintf(trc_out, ... );
+ }
+ OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out);
+ } while (0);
+
+
+OSSL_TRACE() and OSSL_TRACE1(), OSSL_TRACE2(), ... OSSL_TRACE9() are
+so-called one-shot macros:
+
+The macro call C<OSSL_TRACE(category, text)>, produces literal text trace output.
+
+The macro call C<OSSL_TRACEn(category, format, arg1, ..., argn)> produces
+printf-style trace output with n format field arguments (n=1,...,9).
+It expands to:
+
+ OSSL_TRACE_BEGIN(category) {
+ BIO_printf(trc_out, format, arg1, ..., argN)
+ } OSSL_TRACE_END(category)
+
+Internally, all one-shot macros are implemented using a generic OSSL_TRACEV()
+macro, since C90 does not support variadic macros. This helper macro has a rather
+weird synopsis and should not be used directly.
+
+The OSSL_TRACE_ENABLED() macro can be used to conditionally execute some code
+only if a specific trace category is enabled.
+In some situations this is simpler than entering a trace section using
+OSSL_TRACE_BEGIN() and OSSL_TRACE_END().
+For example, the code
+
+ if (OSSL_TRACE_ENABLED(TLS)) {
+ ...
+ }
+
+expands to
+
+ if (OSSL_trace_enabled(OSSL_TRACE_CATEGORY_TLS) {
+ ...
+ }
+
+=head1 NOTES
+
+If producing the trace output requires carrying out auxiliary calculations,
+this auxiliary code should be placed inside a conditional block which is
+executed only if the trace category is enabled.
+
+The most natural way to do this is to place the code inside the trace section
+itself because it already introduces such a conditional block.
+
+ OSSL_TRACE_BEGIN(TLS) {
+ int var = do_some_auxiliary_calculation();
+
+ BIO_printf(trc_out, "var = %d\n", var);
+
+ } OSSL_TRACE_END(TLS);
+
+In some cases it is more advantageous to use a simple conditional group instead
+of a trace section. This is the case if calculations and tracing happen in
+different locations of the code, or if the calculations are so time consuming
+that placing them inside a (critical) trace section would create too much
+contention.
+
+ if (OSSL_TRACE_ENABLED(TLS)) {
+ int var = do_some_auxiliary_calculation();
+
+ OSSL_TRACE1("var = %d\n", var);
+ }
+
+Note however that premature optimization of tracing code is in general futile
+and it's better to keep the tracing code as simple as possible.
+Because most often the limiting factor for the application's speed is the time
+it takes to print the trace output, not to calculate it.
+
+=head2 Configure Tracing
+
+By default, the OpenSSL library is built with tracing disabled. To
+use the tracing functionality documented here, it is therefore
+necessary to configure and build OpenSSL with the 'enable-trace' option.
+
+When the library is built with tracing disabled:
+
+=over 4
+
+=item *
+
+The macro B<OPENSSL_NO_TRACE> is defined in F<< <openssl/opensslconf.h> >>.
+
+=item *
+
+all functions are still present, but OSSL_trace_enabled() will always
+report the categories as disabled, and all other functions will do
+nothing.
+
+=item *
+
+the convenience macros are defined to produce dead code.
+For example, take this example from L</Macros> section above:
+
+ OSSL_TRACE_BEGIN(TLS) {
+
+ if (condition) {
+ OSSL_TRACE_CANCEL(TLS);
+ goto err;
+ }
+ BIO_fprintf(trc_out, ... );
+
+ } OSSL_TRACE_END(TLS);
+
+When the tracing API isn't operational, that will expand to:
+
+ do {
+ BIO *trc_out = NULL;
+ if (0) {
+ if (condition) {
+ ((void)0);
+ goto err;
+ }
+ BIO_fprintf(trc_out, ... );
+ }
+ } while (0);
+
+=back
+
+=head1 RETURN VALUES
+
+OSSL_trace_enabled() returns 1 if tracing for the given I<type> is
+operational and enabled, otherwise 0.
+
+OSSL_trace_begin() returns a B<BIO> pointer if the given I<type> is enabled,
+otherwise NULL.
+
+=head1 HISTORY
+
+The OpenSSL Tracing API was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_trace_get_category_num.pod b/doc/man3/OSSL_trace_get_category_num.pod
new file mode 100644
index 000000000000..5ab05a3a5cdf
--- /dev/null
+++ b/doc/man3/OSSL_trace_get_category_num.pod
@@ -0,0 +1,44 @@
+=pod
+
+=head1 NAME
+
+OSSL_trace_get_category_num, OSSL_trace_get_category_name
+- OpenSSL tracing information functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/trace.h>
+
+ int OSSL_trace_get_category_num(const char *name);
+ const char *OSSL_trace_get_category_name(int num);
+
+=head1 DESCRIPTION
+
+OSSL_trace_get_category_num() gives the category number corresponding
+to the given C<name>.
+
+OSSL_trace_get_category_name() gives the category name corresponding
+to the given C<num>.
+
+=head1 RETURN VALUES
+
+OSSL_trace_get_category_num() returns the category number if the given
+C<name> is a recognised category name, otherwise -1.
+
+OSSL_trace_get_category_name() returns the category name if the given
+C<num> is a recognised category number, otherwise NULL.
+
+=head1 HISTORY
+
+The OpenSSL Tracing API was added ino OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_trace_set_channel.pod b/doc/man3/OSSL_trace_set_channel.pod
new file mode 100644
index 000000000000..3b9c64e5412f
--- /dev/null
+++ b/doc/man3/OSSL_trace_set_channel.pod
@@ -0,0 +1,332 @@
+=pod
+
+=for openssl foreign manual atexit(3)
+
+=head1 NAME
+
+OSSL_trace_set_channel, OSSL_trace_set_prefix, OSSL_trace_set_suffix,
+OSSL_trace_set_callback, OSSL_trace_cb - Enabling trace output
+
+=head1 SYNOPSIS
+
+ #include <openssl/trace.h>
+
+ typedef size_t (*OSSL_trace_cb)(const char *buf, size_t cnt,
+ int category, int cmd, void *data);
+
+ void OSSL_trace_set_channel(int category, BIO *bio);
+ void OSSL_trace_set_prefix(int category, const char *prefix);
+ void OSSL_trace_set_suffix(int category, const char *suffix);
+ void OSSL_trace_set_callback(int category, OSSL_trace_cb cb, void *data);
+
+=head1 DESCRIPTION
+
+If available (see L</NOTES> below), the application can request
+internal trace output.
+This output comes in form of free text for humans to read.
+
+The trace output is divided into categories which can be
+enabled individually.
+Every category can be enabled individually by attaching a so called
+I<trace channel> to it, which in the simplest case is just a BIO object
+to which the application can write the tracing output for this category.
+Alternatively, the application can provide a tracer callback in order to
+get more finegrained trace information. This callback will be wrapped
+internally by a dedicated BIO object.
+
+For the tracing code, both trace channel types are indistinguishable.
+These are called a I<simple trace channel> and a I<callback trace channel>,
+respectively.
+
+=head2 Functions
+
+OSSL_trace_set_channel() is used to enable the given trace C<category>
+by attaching the B<BIO> I<bio> object as (simple) trace channel.
+On success the ownership of the BIO is transferred to the channel,
+so the caller must not free it directly.
+
+OSSL_trace_set_prefix() and OSSL_trace_set_suffix() can be used to add
+an extra line for each channel, to be output before and after group of
+tracing output.
+What constitues an output group is decided by the code that produces
+the output.
+The lines given here are considered immutable; for more dynamic
+tracing prefixes, consider setting a callback with
+OSSL_trace_set_callback() instead.
+
+OSSL_trace_set_callback() is used to enable the given trace
+I<category> by giving it the tracer callback I<cb> with the associated
+data I<data>, which will simply be passed through to I<cb> whenever
+it's called. The callback function is internally wrapped by a
+dedicated BIO object, the so called I<callback trace channel>.
+This should be used when it's desirable to do form the trace output to
+something suitable for application needs where a prefix and suffix
+line aren't enough.
+
+OSSL_trace_set_channel() and OSSL_trace_set_callback() are mutually
+exclusive, calling one of them will clear whatever was set by the
+previous call.
+
+Calling OSSL_trace_set_channel() with NULL for I<channel> or
+OSSL_trace_set_callback() with NULL for I<cb> disables tracing for
+the given I<category>.
+
+=head2 Trace callback
+
+The tracer callback must return a B<size_t>, which must be zero on
+error and otherwise return the number of bytes that were output.
+It receives a text buffer I<buf> with I<cnt> bytes of text, as well as
+the I<category>, a control number I<cmd>, and the I<data> that was
+passed to OSSL_trace_set_callback().
+
+The possible control numbers are:
+
+=over 4
+
+=item B<OSSL_TRACE_CTRL_BEGIN>
+
+The callback is called from OSSL_trace_begin(), which gives the
+callback the possibility to output a dynamic starting line, or set a
+prefix that should be output at the beginning of each line, or
+something other.
+
+=item B<OSSL_TRACE_CTRL_WRITE>
+
+This callback is called whenever data is written to the BIO by some
+regular BIO output routine.
+An arbitrary number of B<OSSL_TRACE_CTRL_WRITE> callbacks can occur
+inside a group marked by a pair of B<OSSL_TRACE_CTRL_BEGIN> and
+B<OSSL_TRACE_CTRL_END> calls, but never outside such a group.
+
+=item B<OSSL_TRACE_CTRL_END>
+
+The callback is called from OSSL_trace_end(), which gives the callback
+the possibility to output a dynamic ending line, or reset the line
+prefix that was set with B<OSSL_TRACE_CTRL_BEGIN>, or something other.
+
+=back
+
+=head2 Trace categories
+
+The trace categories are simple numbers available through macros.
+
+=over 4
+
+=item B<OSSL_TRACE_CATEGORY_TRACE>
+
+Traces the OpenSSL trace API itself.
+
+More precisely, this will generate trace output any time a new
+trace hook is set.
+
+=item B<OSSL_TRACE_CATEGORY_INIT>
+
+Traces OpenSSL library initialization and cleanup.
+
+This needs special care, as OpenSSL will do automatic cleanup after
+exit from C<main()>, and any tracing output done during this cleanup
+will be lost if the tracing channel or callback were cleaned away
+prematurely.
+A suggestion is to make such cleanup part of a function that's
+registered very early with L<atexit(3)>.
+
+=item B<OSSL_TRACE_CATEGORY_TLS>
+
+Traces the TLS/SSL protocol.
+
+=item B<OSSL_TRACE_CATEGORY_TLS_CIPHER>
+
+Traces the ciphers used by the TLS/SSL protocol.
+
+=item B<OSSL_TRACE_CATEGORY_CONF>
+
+Traces details about the provider and engine configuration.
+
+=item B<OSSL_TRACE_CATEGORY_ENGINE_TABLE>
+
+Traces the ENGINE algorithm table selection.
+
+More precisely, functions like ENGINE_get_pkey_asn1_meth_engine(),
+ENGINE_get_pkey_meth_engine(), ENGINE_get_cipher_engine(),
+ENGINE_get_digest_engine(), will generate trace summaries of the
+handling of internal tables.
+
+=item B<OSSL_TRACE_CATEGORY_ENGINE_REF_COUNT>
+
+Traces the ENGINE reference counting.
+
+More precisely, both reference counts in the ENGINE structure will be
+monitored with a line of trace output generated for each change.
+
+=item B<OSSL_TRACE_CATEGORY_PKCS5V2>
+
+Traces PKCS#5 v2 key generation.
+
+=item B<OSSL_TRACE_CATEGORY_PKCS12_KEYGEN>
+
+Traces PKCS#12 key generation.
+
+=item B<OSSL_TRACE_CATEGORY_PKCS12_DECRYPT>
+
+Traces PKCS#12 decryption.
+
+=item B<OSSL_TRACE_CATEGORY_X509V3_POLICY>
+
+Traces X509v3 policy processing.
+
+More precisely, this generates the complete policy tree at various
+point during evaluation.
+
+=item B<OSSL_TRACE_CATEGORY_BN_CTX>
+
+Traces BIGNUM context operations.
+
+=item B<OSSL_TRACE_CATEGORY_CMP>
+
+Traces CMP client and server activity.
+
+=item B<OSSL_TRACE_CATEGORY_STORE>
+
+Traces STORE operations.
+
+=item B<OSSL_TRACE_CATEGORY_DECODER>
+
+Traces decoder operations.
+
+=item B<OSSL_TRACE_CATEGORY_ENCODER>
+
+Traces encoder operations.
+
+=item B<OSSL_TRACE_CATEGORY_REF_COUNT>
+
+Traces decrementing certain ASN.1 structure references.
+
+=back
+
+There is also B<OSSL_TRACE_CATEGORY_ALL>, which works as a fallback
+and can be used to get I<all> trace output.
+
+Note, however, that in this case all trace output will effectively be
+associated with the 'ALL' category, which is undesirable if the
+application intends to include the category name in the trace output.
+In this case it is better to register separate channels for each
+trace category instead.
+
+=head1 RETURN VALUES
+
+OSSL_trace_set_channel(), OSSL_trace_set_prefix(),
+OSSL_trace_set_suffix(), and OSSL_trace_set_callback() return 1 on
+success, or 0 on failure.
+
+=head1 EXAMPLES
+
+In all examples below, the trace producing code is assumed to be
+the following:
+
+ int foo = 42;
+ const char bar[] = { 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15 };
+
+ OSSL_TRACE_BEGIN(TLS) {
+ BIO_puts(trc_out, "foo: ");
+ BIO_printf(trc_out, "%d\n", foo);
+ BIO_dump(trc_out, bar, sizeof(bar));
+ } OSSL_TRACE_END(TLS);
+
+=head2 Simple example
+
+An example with just a channel and constant prefix / suffix.
+
+ int main(int argc, char *argv[])
+ {
+ BIO *err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT);
+ OSSL_trace_set_channel(OSSL_TRACE_CATEGORY_SSL, err);
+ OSSL_trace_set_prefix(OSSL_TRACE_CATEGORY_SSL, "BEGIN TRACE[TLS]");
+ OSSL_trace_set_suffix(OSSL_TRACE_CATEGORY_SSL, "END TRACE[TLS]");
+
+ /* ... work ... */
+ }
+
+When the trace producing code above is performed, this will be output
+on standard error:
+
+ BEGIN TRACE[TLS]
+ foo: 42
+ 0000 - 00 01 02 03 04 05 06 07-08 09 0a 0b 0c 0d 0e 0f ................
+ END TRACE[TLS]
+
+=head2 Advanced example
+
+This example uses the callback, and depends on pthreads functionality.
+
+ static size_t cb(const char *buf, size_t cnt,
+ int category, int cmd, void *vdata)
+ {
+ BIO *bio = vdata;
+ const char *label = NULL;
+
+ switch (cmd) {
+ case OSSL_TRACE_CTRL_BEGIN:
+ label = "BEGIN";
+ break;
+ case OSSL_TRACE_CTRL_END:
+ label = "END";
+ break;
+ }
+
+ if (label != NULL) {
+ union {
+ pthread_t tid;
+ unsigned long ltid;
+ } tid;
+
+ tid.tid = pthread_self();
+ BIO_printf(bio, "%s TRACE[%s]:%lx\n",
+ label, OSSL_trace_get_category_name(category), tid.ltid);
+ }
+ return (size_t)BIO_puts(bio, buf);
+ }
+
+ int main(int argc, char *argv[])
+ {
+ BIO *err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT);
+ OSSL_trace_set_callback(OSSL_TRACE_CATEGORY_SSL, cb, err);
+
+ /* ... work ... */
+ }
+
+The output is almost the same as for the simple example above.
+
+ BEGIN TRACE[TLS]:7f9eb0193b80
+ foo: 42
+ 0000 - 00 01 02 03 04 05 06 07-08 09 0a 0b 0c 0d 0e 0f ................
+ END TRACE[TLS]:7f9eb0193b80
+
+=head1 NOTES
+
+=head2 Configure Tracing
+
+By default, the OpenSSL library is built with tracing disabled. To
+use the tracing functionality documented here, it is therefore
+necessary to configure and build OpenSSL with the 'enable-trace' option.
+
+When the library is built with tracing disabled, the macro
+B<OPENSSL_NO_TRACE> is defined in F<< <openssl/opensslconf.h> >> and all
+functions described here are inoperational, i.e. will do nothing.
+
+=head1 HISTORY
+
+OSSL_trace_set_channel(), OSSL_trace_set_prefix(),
+OSSL_trace_set_suffix(), and OSSL_trace_set_callback() were all added
+in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OpenSSL_add_all_algorithms.pod b/doc/man3/OpenSSL_add_all_algorithms.pod
index 0c086d1291d3..07403a32d534 100644
--- a/doc/man3/OpenSSL_add_all_algorithms.pod
+++ b/doc/man3/OpenSSL_add_all_algorithms.pod
@@ -9,15 +9,15 @@ add algorithms to internal table
#include <openssl/evp.h>
-Deprecated:
+The following functions have been deprecated since OpenSSL 1.1.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
- # if OPENSSL_API_COMPAT < 0x10100000L
void OpenSSL_add_all_algorithms(void);
void OpenSSL_add_all_ciphers(void);
void OpenSSL_add_all_digests(void);
- void EVP_cleanup(void)
-# endif
+ void EVP_cleanup(void);
=head1 DESCRIPTION
@@ -53,9 +53,9 @@ not be used.
=head1 COPYRIGHT
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/OpenSSL_version.pod b/doc/man3/OpenSSL_version.pod
new file mode 100644
index 000000000000..e1cf16e2a109
--- /dev/null
+++ b/doc/man3/OpenSSL_version.pod
@@ -0,0 +1,250 @@
+=pod
+
+=head1 NAME
+
+OPENSSL_VERSION_MAJOR, OPENSSL_VERSION_MINOR, OPENSSL_VERSION_PATCH,
+OPENSSL_VERSION_PRE_RELEASE, OPENSSL_VERSION_BUILD_METADATA,
+OPENSSL_VERSION_TEXT, OPENSSL_VERSION_PREREQ, OPENSSL_version_major,
+OPENSSL_version_minor, OPENSSL_version_patch, OPENSSL_version_pre_release,
+OPENSSL_version_build_metadata, OpenSSL_version, OPENSSL_VERSION_NUMBER,
+OpenSSL_version_num, OPENSSL_info
+- get OpenSSL version number and other information
+
+=head1 SYNOPSIS
+
+ #include <openssl/opensslv.h>
+
+ #define OPENSSL_VERSION_MAJOR x
+ #define OPENSSL_VERSION_MINOR y
+ #define OPENSSL_VERSION_PATCH z
+
+ /* The definitions here are typical release values */
+ #define OPENSSL_VERSION_PRE_RELEASE ""
+ #define OPENSSL_VERSION_BUILD_METADATA ""
+
+ #define OPENSSL_VERSION_TEXT "OpenSSL x.y.z xx XXX xxxx"
+
+ #define OPENSSL_VERSION_PREREQ(maj,min)
+
+ #include <openssl/crypto.h>
+
+ unsigned int OPENSSL_version_major(void);
+ unsigned int OPENSSL_version_minor(void);
+ unsigned int OPENSSL_version_patch(void);
+ const char *OPENSSL_version_pre_release(void);
+ const char *OPENSSL_version_build_metadata(void);
+
+ const char *OpenSSL_version(int t);
+
+ const char *OPENSSL_info(int t);
+
+ /* from openssl/opensslv.h */
+ #define OPENSSL_VERSION_NUMBER 0xnnnnnnnnL
+
+ /* from openssl/crypto.h */
+ unsigned long OpenSSL_version_num();
+
+=head1 DESCRIPTION
+
+=head2 Macros
+
+The three macros B<OPENSSL_VERSION_MAJOR>, B<OPENSSL_VERSION_MINOR> and
+B<OPENSSL_VERSION_PATCH> represent the three parts of a version
+identifier, B<I<MAJOR>.I<MINOR>.I<PATCH>>.
+
+The macro B<OPENSSL_VERSION_PRE_RELEASE> is an added bit of text that
+indicates that this is a pre-release version, such as C<"-dev"> for an
+ongoing development snapshot or C<"-alpha3"> for an alpha release.
+The value must be a string.
+
+The macro B<OPENSSL_VERSION_BUILD_METADATA> is extra information, reserved
+for other parties, such as C<"+fips">, or C<"+vendor.1">).
+The OpenSSL project will not touch this macro (will leave it an empty string).
+The value must be a string.
+
+B<OPENSSL_VERSION_STR> is a convenience macro to get the short version
+identifier string, C<"I<MAJOR>.I<MINOR>.I<PATCH>">.
+
+B<OPENSSL_FULL_VERSION_STR> is a convenience macro to get the longer
+version identifier string, which combines B<OPENSSL_VERSION_STR>,
+B<OPENSSL_VERSION_PRE_RELEASE> and B<OPENSSL_VERSION_BUILD_METADATA>.
+
+B<OPENSSL_VERSION_TEXT> is a convenience macro to get a full descriptive
+version text, which includes B<OPENSSL_FULL_VERSION_STR> and the release
+date.
+
+B<OPENSSL_VERSION_PREREQ> is a useful macro for checking whether the OpenSSL
+version for the headers in use is at least at the given pre-requisite major
+(B<maj>) and minor (B<min>) number or not. It will evaluate to true if the
+header version number (B<OPENSSL_VERSION_MAJOR>.B<OPENSSL_VERSION_MINOR>) is
+greater than or equal to B<maj>.B<min>.
+
+B<OPENSSL_VERSION_NUMBER> is a combination of the major, minor and
+patch version into a single integer 0xMNN00PP0L, where:
+
+=over 4
+
+=item M
+
+is the number from B<OPENSSL_VERSION_MAJOR>, in hexadecimal notation
+
+=item NN
+
+is the number from B<OPENSSL_VERSION_MINOR>, in hexadecimal notation
+
+=item PP
+
+is the number from B<OPENSSL_VERSION_PATCH>, in hexadecimal notation
+
+=back
+
+=head2 Functions
+
+OPENSSL_version_major(), OPENSSL_version_minor(), OPENSSL_version_patch(),
+OPENSSL_version_pre_release(), and OPENSSL_version_build_metadata() return
+the values of the macros above for the build of the library, respectively.
+
+OpenSSL_version() returns different strings depending on I<t>:
+
+=over 4
+
+=item OPENSSL_VERSION
+
+The value of B<OPENSSL_VERSION_TEXT>
+
+=item OPENSSL_VERSION_STRING
+
+The value of B<OPENSSL_VERSION_STR>
+
+=item OPENSSL_FULL_VERSION_STRING
+
+The value of B<OPENSSL_FULL_VERSION_STR>
+
+=item OPENSSL_CFLAGS
+
+The compiler flags set for the compilation process in the form
+C<compiler: ...> if available, or C<compiler: information not available>
+otherwise.
+
+=item OPENSSL_BUILT_ON
+
+The date of the build process in the form C<built on: ...> if available
+or C<built on: date not available> otherwise.
+The date would not be available in a reproducible build, for example.
+
+=item OPENSSL_PLATFORM
+
+The "Configure" target of the library build in the form C<platform: ...>
+if available, or C<platform: information not available> otherwise.
+
+=item OPENSSL_DIR
+
+The B<OPENSSLDIR> setting of the library build in the form C<OPENSSLDIR: "...">
+if available, or C<OPENSSLDIR: N/A> otherwise.
+
+=item OPENSSL_ENGINES_DIR
+
+The B<ENGINESDIR> setting of the library build in the form C<ENGINESDIR: "...">
+if available, or C<ENGINESDIR: N/A> otherwise. This option is deprecated in
+OpenSSL 3.0.
+
+=item OPENSSL_MODULES_DIR
+
+The B<MODULESDIR> setting of the library build in the form C<MODULESDIR: "...">
+if available, or C<MODULESDIR: N/A> otherwise.
+
+=item OPENSSL_CPU_INFO
+
+The current OpenSSL cpu settings.
+This is the current setting of the cpu capability flags. It is usually
+automatically configured but may be set via an environment variable.
+The value has the same syntax as the environment variable.
+For x86 the string looks like C<CPUINFO: OPENSSL_ia32cap=0x123:0x456>
+or C<CPUINFO: N/A> if not available.
+
+=back
+
+For an unknown I<t>, the text C<not available> is returned.
+
+OPENSSL_info() also returns different strings depending on I<t>:
+
+=over 4
+
+=item OPENSSL_INFO_CONFIG_DIR
+
+The configured C<OPENSSLDIR>, which is the default location for
+OpenSSL configuration files.
+
+=item OPENSSL_INFO_ENGINES_DIR
+
+The configured C<ENGINESDIR>, which is the default location for
+OpenSSL engines.
+
+=item OPENSSL_INFO_MODULES_DIR
+
+The configured C<MODULESDIR>, which is the default location for
+dynamically loadable OpenSSL modules other than engines.
+
+=item OPENSSL_INFO_DSO_EXTENSION
+
+The configured dynamically loadable module extension.
+
+=item OPENSSL_INFO_DIR_FILENAME_SEPARATOR
+
+The separator between a directory specification and a filename.
+Note that on some operating systems, this is not the same as the
+separator between directory elements.
+
+=item OPENSSL_INFO_LIST_SEPARATOR
+
+The OpenSSL list separator.
+This is typically used in strings that are lists of items, such as the
+value of the environment variable C<$PATH> on Unix (where the
+separator is C<:>) or C<%PATH%> on Windows (where the separator is
+C<;>).
+
+=item OPENSSL_INFO_CPU_SETTINGS
+
+The current OpenSSL cpu settings.
+This is the current setting of the cpu capability flags. It is usually
+automatically configured but may be set via an environment variable.
+The value has the same syntax as the environment variable.
+For x86 the string looks like C<OPENSSL_ia32cap=0x123:0x456>.
+
+=back
+
+For an unknown I<t>, NULL is returned.
+
+OpenSSL_version_num() returns the value of B<OPENSSL_VERSION_NUMBER>.
+
+=head1 RETURN VALUES
+
+OPENSSL_version_major(), OPENSSL_version_minor() and OPENSSL_version_patch()
+return the version number parts as integers.
+
+OPENSSL_version_pre_release() and OPENSSL_version_build_metadata() return
+the values of B<OPENSSL_VERSION_PRE_RELEASE> and
+B<OPENSSL_VERSION_BUILD_METADATA> respectively as constant strings.
+For any of them that is undefined, the empty string is returned.
+
+OpenSSL_version() returns constant strings.
+
+=head1 SEE ALSO
+
+L<crypto(7)>
+
+=head1 HISTORY
+
+The macros and functions described here were added in OpenSSL 3.0,
+except for OPENSSL_VERSION_NUMBER and OpenSSL_version_num().
+
+=head1 COPYRIGHT
+
+Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PEM_X509_INFO_read_bio_ex.pod b/doc/man3/PEM_X509_INFO_read_bio_ex.pod
new file mode 100644
index 000000000000..251775a3ade7
--- /dev/null
+++ b/doc/man3/PEM_X509_INFO_read_bio_ex.pod
@@ -0,0 +1,83 @@
+=pod
+
+=head1 NAME
+
+PEM_X509_INFO_read_ex, PEM_X509_INFO_read, PEM_X509_INFO_read_bio_ex, PEM_X509_INFO_read_bio
+- read PEM-encoded data structures into one or more B<X509_INFO> objects
+
+=head1 SYNOPSIS
+
+ #include <openssl/pem.h>
+
+ STACK_OF(X509_INFO) *PEM_X509_INFO_read_ex(FILE *fp, STACK_OF(X509_INFO) *sk,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx,
+ const char *propq);
+ STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
+ pem_password_cb *cb, void *u);
+ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bio,
+ STACK_OF(X509_INFO) *sk,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx,
+ const char *propq);
+ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
+ pem_password_cb *cb, void *u);
+
+=head1 DESCRIPTION
+
+PEM_X509_INFO_read_ex() loads the B<X509_INFO> objects from a file I<fp>.
+
+PEM_X509_INFO_read() is similar to PEM_X509_INFO_read_ex()
+but uses the default (NULL) library context I<libctx>
+and empty property query I<propq>.
+
+PEM_X509_INFO_read_bio_ex() loads the B<X509_INFO> objects using a bio I<bp>.
+
+PEM_X509_INFO_read_bio() is similar to PEM_X509_INFO_read_bio_ex()
+but uses the default (NULL) library context I<libctx>
+and empty property query I<propq>.
+
+Each of the loaded B<X509_INFO> objects can contain a CRL, a certificate,
+and/or a private key.
+The elements are read sequentially, and as far as they are of different type than
+the elements read before, they are combined into the same B<X509_INFO> object.
+The idea behind this is that if, for instance, a certificate is followed by
+a private key, the private key is supposed to correspond to the certificate.
+
+If the input stack I<sk> is NULL a new stack is allocated,
+else the given stack is extended.
+
+The optional I<cb> and I<u> parameters can be used for providing a pass phrase
+needed for decrypting encrypted PEM structures (normally only private keys).
+See L<PEM_read_bio_PrivateKey(3)> and L<passphrase-encoding(7)> for details.
+
+The library context I<libctx> and property query I<propq> are used for fetching
+algorithms from providers.
+
+=head1 RETURN VALUES
+
+PEM_X509_INFO_read_ex(), PEM_X509_INFO_read(),
+PEM_X509_INFO_read_bio_ex() and PEM_X509_INFO_read_bio() return
+a stack of B<X509_INFO> objects or NULL on failure.
+
+=head1 SEE ALSO
+
+L<PEM_read_bio_ex(3)>,
+L<PEM_read_bio_PrivateKey(3)>,
+L<passphrase-encoding(7)>
+
+=head1 HISTORY
+
+The functions PEM_X509_INFO_read_ex() and
+PEM_X509_INFO_read_bio_ex() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PEM_bytes_read_bio.pod b/doc/man3/PEM_bytes_read_bio.pod
index eb2fb2059ee7..c2cdf6cd10fe 100644
--- a/doc/man3/PEM_bytes_read_bio.pod
+++ b/doc/man3/PEM_bytes_read_bio.pod
@@ -78,7 +78,7 @@ PEM_bytes_read_bio_secmem() was introduced in OpenSSL 1.1.1
Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/PEM_read.pod b/doc/man3/PEM_read.pod
index 3c777b5470aa..c76039f711c2 100644
--- a/doc/man3/PEM_read.pod
+++ b/doc/man3/PEM_read.pod
@@ -11,9 +11,9 @@ PEM_read, PEM_read_bio, PEM_do_header, PEM_get_EVP_CIPHER_INFO
#include <openssl/pem.h>
int PEM_write(FILE *fp, const char *name, const char *header,
- const unsigned char *data, long len)
+ const unsigned char *data, long len);
int PEM_write_bio(BIO *bp, const char *name, const char *header,
- const unsigned char *data, long len)
+ const unsigned char *data, long len);
int PEM_read(FILE *fp, char **name, char **header,
unsigned char **data, long *len);
@@ -122,9 +122,9 @@ L<passphrase-encoding(7)>
=head1 COPYRIGHT
-Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 1998-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/PEM_read_CMS.pod b/doc/man3/PEM_read_CMS.pod
index e5f0803d7f0e..2b96db9c31a3 100644
--- a/doc/man3/PEM_read_CMS.pod
+++ b/doc/man3/PEM_read_CMS.pod
@@ -35,12 +35,16 @@ PEM_write_bio_PKCS8_PRIV_KEY_INFO,
PEM_read_SSL_SESSION,
PEM_read_bio_SSL_SESSION,
PEM_write_SSL_SESSION,
-PEM_write_bio_SSL_SESSION
+PEM_write_bio_SSL_SESSION,
+PEM_read_X509_PUBKEY,
+PEM_read_bio_X509_PUBKEY,
+PEM_write_X509_PUBKEY,
+PEM_write_bio_X509_PUBKEY
- PEM object encoding routines
=head1 SYNOPSIS
-=for comment generic
+=for openssl generic
#include <openssl/pem.h>
@@ -51,10 +55,41 @@ PEM_write_bio_SSL_SESSION
int PEM_write_TYPE(FILE *fp, const TYPE *a);
int PEM_write_bio_TYPE(BIO *bp, const TYPE *a);
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ #include <openssl/pem.h>
+
+ int PEM_write_DHxparams(FILE *out, const DH *dh);
+ int PEM_write_bio_DHxparams(BIO *out, const DH *dh);
+ EC_GROUP *PEM_read_ECPKParameters(FILE *fp, EC_GROUP **x, pem_password_cb *cb, void *u);
+ EC_GROUP *PEM_read_bio_ECPKParameters(BIO *bp, EC_GROUP **x, pem_password_cb *cb, void *u);
+ int PEM_write_ECPKParameters(FILE *out, const EC_GROUP *x);
+ int PEM_write_bio_ECPKParameters(BIO *out, const EC_GROUP *x),
+
+ EC_KEY *PEM_read_EC_PUBKEY(FILE *fp, EC_KEY **x, pem_password_cb *cb, void *u);
+ EC_KEY *PEM_read_bio_EC_PUBKEY(BIO *bp, EC_KEY **x, pem_password_cb *cb, void *u);
+ int PEM_write_EC_PUBKEY(FILE *out, const EC_KEY *x);
+ int PEM_write_bio_EC_PUBKEY(BIO *out, const EC_KEY *x);
+
+ EC_KEY *PEM_read_ECPrivateKey(FILE *out, EC_KEY **x, pem_password_cb *cb, void *u);
+ EC_KEY *PEM_read_bio_ECPrivateKey(BIO *out, EC_KEY **x, pem_password_cb *cb, void *u);
+ int PEM_write_ECPrivateKey(FILE *out, const EC_KEY *x, const EVP_CIPHER *enc,
+ const unsigned char *kstr, int klen,
+ pem_password_cb *cb, void *u);
+ int PEM_write_bio_ECPrivateKey(BIO *out, const EC_KEY *x, const EVP_CIPHER *enc,
+ const unsigned char *kstr, int klen,
+ pem_password_cb *cb, void *u);
+
=head1 DESCRIPTION
-In the description below, I<TYPE> is used
-as a placeholder for any of the OpenSSL datatypes, such as I<X509>.
+All of the functions described on this page are deprecated.
+Applications should use OSSL_ENCODER_to_bio() and OSSL_DECODER_from_bio()
+instead.
+
+In the description below, B<I<TYPE>> is used
+as a placeholder for any of the OpenSSL datatypes, such as B<X509>.
The macro B<DECLARE_PEM_rw> expands to the set of declarations shown in
the next four lines of the synopsis.
@@ -63,15 +98,17 @@ the PEM encoding. For more information on the templates, see
L<ASN1_ITEM(3)>. For more information on the lower-level routines used
by the functions here, see L<PEM_read(3)>.
-PEM_read_TYPE() reads a PEM-encoded object of I<TYPE> from the file B<fp>
-and returns it. The B<cb> and B<u> parameters are as described in
+B<PEM_read_I<TYPE>>() reads a PEM-encoded object of B<I<TYPE>> from the file
+I<fp> and returns it. The I<cb> and I<u> parameters are as described in
L<pem_password_cb(3)>.
-PEM_read_bio_TYPE() is similar to PEM_read_TYPE() but reads from the BIO B<bp>.
+B<PEM_read_bio_I<TYPE>>() is similar to B<PEM_read_I<TYPE>>() but reads from
+the BIO I<bp>.
-PEM_write_TYPE() writes the PEM encoding of the object B<a> to the file B<fp>.
+B<PEM_write_I<TYPE>>() writes the PEM encoding of the object I<a> to the file
+I<fp>.
-PEM_write_bio_TYPE() similarly writes to the BIO B<bp>.
+B<PEM_write_bio_I<TYPE>>() similarly writes to the BIO I<bp>.
=head1 NOTES
@@ -81,22 +118,34 @@ It will simply be treated as a byte sequence.
=head1 RETURN VALUES
-PEM_read_TYPE() and PEM_read_bio_TYPE() return a pointer to an allocated
-object, which should be released by calling TYPE_free(), or NULL on error.
+B<PEM_read_I<TYPE>>() and B<PEM_read_bio_I<TYPE>>() return a pointer to an
+allocated object, which should be released by calling B<I<TYPE>_free>(), or
+NULL on error.
-PEM_write_TYPE() and PEM_write_bio_TYPE() return the number of bytes written
-or zero on error.
+B<PEM_write_I<TYPE>>() and B<PEM_write_bio_I<TYPE>>() return the number of bytes
+written or zero on error.
=head1 SEE ALSO
L<PEM_read(3)>,
L<passphrase-encoding(7)>
+=head1 HISTORY
+
+The functions PEM_write_DHxparams(), PEM_write_bio_DHxparams(),
+PEM_read_ECPKParameters(), PEM_read_bio_ECPKParameters(),
+PEM_write_ECPKParameters(), PEM_write_bio_ECPKParameters(),
+PEM_read_EC_PUBKEY(), PEM_read_bio_EC_PUBKEY(),
+PEM_write_EC_PUBKEY(), PEM_write_bio_EC_PUBKEY(),
+PEM_read_ECPrivateKey(), PEM_read_bio_ECPrivateKey(),
+PEM_write_ECPrivateKey() and PEM_write_bio_ECPrivateKey()
+were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/PEM_read_bio_PrivateKey.pod b/doc/man3/PEM_read_bio_PrivateKey.pod
index 233df7fca217..ac93920addec 100644
--- a/doc/man3/PEM_read_bio_PrivateKey.pod
+++ b/doc/man3/PEM_read_bio_PrivateKey.pod
@@ -3,11 +3,17 @@
=head1 NAME
pem_password_cb,
-PEM_read_bio_PrivateKey, PEM_read_PrivateKey, PEM_write_bio_PrivateKey,
-PEM_write_bio_PrivateKey_traditional, PEM_write_PrivateKey,
+PEM_read_bio_PrivateKey_ex, PEM_read_bio_PrivateKey,
+PEM_read_PrivateKey_ex, PEM_read_PrivateKey,
+PEM_write_bio_PrivateKey_ex, PEM_write_bio_PrivateKey,
+PEM_write_bio_PrivateKey_traditional,
+PEM_write_PrivateKey_ex, PEM_write_PrivateKey,
PEM_write_bio_PKCS8PrivateKey, PEM_write_PKCS8PrivateKey,
PEM_write_bio_PKCS8PrivateKey_nid, PEM_write_PKCS8PrivateKey_nid,
-PEM_read_bio_PUBKEY, PEM_read_PUBKEY, PEM_write_bio_PUBKEY, PEM_write_PUBKEY,
+PEM_read_bio_PUBKEY_ex, PEM_read_bio_PUBKEY,
+PEM_read_PUBKEY_ex, PEM_read_PUBKEY,
+PEM_write_bio_PUBKEY_ex, PEM_write_bio_PUBKEY,
+PEM_write_PUBKEY_ex, PEM_write_PUBKEY,
PEM_read_bio_RSAPrivateKey, PEM_read_RSAPrivateKey,
PEM_write_bio_RSAPrivateKey, PEM_write_RSAPrivateKey,
PEM_read_bio_RSAPublicKey, PEM_read_RSAPublicKey, PEM_write_bio_RSAPublicKey,
@@ -15,8 +21,8 @@ PEM_write_RSAPublicKey, PEM_read_bio_RSA_PUBKEY, PEM_read_RSA_PUBKEY,
PEM_write_bio_RSA_PUBKEY, PEM_write_RSA_PUBKEY, PEM_read_bio_DSAPrivateKey,
PEM_read_DSAPrivateKey, PEM_write_bio_DSAPrivateKey, PEM_write_DSAPrivateKey,
PEM_read_bio_DSA_PUBKEY, PEM_read_DSA_PUBKEY, PEM_write_bio_DSA_PUBKEY,
-PEM_write_DSA_PUBKEY, PEM_read_bio_Parameters, PEM_write_bio_Parameters,
-PEM_read_bio_DSAparams, PEM_read_DSAparams,
+PEM_write_DSA_PUBKEY, PEM_read_bio_Parameters_ex, PEM_read_bio_Parameters,
+PEM_write_bio_Parameters, PEM_read_bio_DSAparams, PEM_read_DSAparams,
PEM_write_bio_DSAparams, PEM_write_DSAparams, PEM_read_bio_DHparams,
PEM_read_DHparams, PEM_write_bio_DHparams, PEM_write_DHparams,
PEM_read_bio_X509, PEM_read_X509, PEM_write_bio_X509, PEM_write_X509,
@@ -33,41 +39,105 @@ PEM_write_bio_PKCS7, PEM_write_PKCS7 - PEM routines
typedef int pem_password_cb(char *buf, int size, int rwflag, void *u);
+ EVP_PKEY *PEM_read_bio_PrivateKey_ex(BIO *bp, EVP_PKEY **x,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x,
pem_password_cb *cb, void *u);
+ EVP_PKEY *PEM_read_PrivateKey_ex(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
+ void *u, OSSL_LIB_CTX *libctx,
+ const char *propq);
EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x,
pem_password_cb *cb, void *u);
- int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
+ int PEM_write_bio_PrivateKey_ex(BIO *bp, const EVP_PKEY *x,
+ const EVP_CIPHER *enc,
+ unsigned char *kstr, int klen,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ int PEM_write_bio_PrivateKey(BIO *bp, const EVP_PKEY *x, const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_bio_PrivateKey_traditional(BIO *bp, EVP_PKEY *x,
const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
+ int PEM_write_PrivateKey_ex(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
+ unsigned char *kstr, int klen,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
-
int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
char *kstr, int klen,
pem_password_cb *cb, void *u);
- int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid,
+ int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, const EVP_PKEY *x, int nid,
char *kstr, int klen,
pem_password_cb *cb, void *u);
- int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid,
+ int PEM_write_PKCS8PrivateKey_nid(FILE *fp, const EVP_PKEY *x, int nid,
char *kstr, int klen,
pem_password_cb *cb, void *u);
+ EVP_PKEY *PEM_read_bio_PUBKEY_ex(BIO *bp, EVP_PKEY **x,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
EVP_PKEY *PEM_read_bio_PUBKEY(BIO *bp, EVP_PKEY **x,
pem_password_cb *cb, void *u);
+ EVP_PKEY *PEM_read_PUBKEY_ex(FILE *fp, EVP_PKEY **x,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
EVP_PKEY *PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x,
pem_password_cb *cb, void *u);
+ int PEM_write_bio_PUBKEY_ex(BIO *bp, EVP_PKEY *x,
+ OSSL_LIB_CTX *libctx, const char *propq);
int PEM_write_bio_PUBKEY(BIO *bp, EVP_PKEY *x);
+ int PEM_write_PUBKEY_ex(FILE *fp, EVP_PKEY *x,
+ OSSL_LIB_CTX *libctx, const char *propq);
int PEM_write_PUBKEY(FILE *fp, EVP_PKEY *x);
+ EVP_PKEY *PEM_read_bio_Parameters_ex(BIO *bp, EVP_PKEY **x,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x);
+ int PEM_write_bio_Parameters(BIO *bp, const EVP_PKEY *x);
+
+ X509 *PEM_read_bio_X509(BIO *bp, X509 **x, pem_password_cb *cb, void *u);
+ X509 *PEM_read_X509(FILE *fp, X509 **x, pem_password_cb *cb, void *u);
+ int PEM_write_bio_X509(BIO *bp, X509 *x);
+ int PEM_write_X509(FILE *fp, X509 *x);
+
+ X509 *PEM_read_bio_X509_AUX(BIO *bp, X509 **x, pem_password_cb *cb, void *u);
+ X509 *PEM_read_X509_AUX(FILE *fp, X509 **x, pem_password_cb *cb, void *u);
+ int PEM_write_bio_X509_AUX(BIO *bp, X509 *x);
+ int PEM_write_X509_AUX(FILE *fp, X509 *x);
+
+ X509_REQ *PEM_read_bio_X509_REQ(BIO *bp, X509_REQ **x,
+ pem_password_cb *cb, void *u);
+ X509_REQ *PEM_read_X509_REQ(FILE *fp, X509_REQ **x,
+ pem_password_cb *cb, void *u);
+ int PEM_write_bio_X509_REQ(BIO *bp, X509_REQ *x);
+ int PEM_write_X509_REQ(FILE *fp, X509_REQ *x);
+ int PEM_write_bio_X509_REQ_NEW(BIO *bp, X509_REQ *x);
+ int PEM_write_X509_REQ_NEW(FILE *fp, X509_REQ *x);
+
+ X509_CRL *PEM_read_bio_X509_CRL(BIO *bp, X509_CRL **x,
+ pem_password_cb *cb, void *u);
+ X509_CRL *PEM_read_X509_CRL(FILE *fp, X509_CRL **x,
+ pem_password_cb *cb, void *u);
+ int PEM_write_bio_X509_CRL(BIO *bp, X509_CRL *x);
+ int PEM_write_X509_CRL(FILE *fp, X509_CRL *x);
+
+ PKCS7 *PEM_read_bio_PKCS7(BIO *bp, PKCS7 **x, pem_password_cb *cb, void *u);
+ PKCS7 *PEM_read_PKCS7(FILE *fp, PKCS7 **x, pem_password_cb *cb, void *u);
+ int PEM_write_bio_PKCS7(BIO *bp, PKCS7 *x);
+ int PEM_write_PKCS7(FILE *fp, PKCS7 *x);
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
RSA *PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **x,
pem_password_cb *cb, void *u);
RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **x,
@@ -110,10 +180,6 @@ PEM_write_bio_PKCS7, PEM_write_PKCS7 - PEM routines
pem_password_cb *cb, void *u);
int PEM_write_bio_DSA_PUBKEY(BIO *bp, DSA *x);
int PEM_write_DSA_PUBKEY(FILE *fp, DSA *x);
-
- EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x);
- int PEM_write_bio_Parameters(BIO *bp, const EVP_PKEY *x);
-
DSA *PEM_read_bio_DSAparams(BIO *bp, DSA **x, pem_password_cb *cb, void *u);
DSA *PEM_read_DSAparams(FILE *fp, DSA **x, pem_password_cb *cb, void *u);
int PEM_write_bio_DSAparams(BIO *bp, DSA *x);
@@ -124,39 +190,12 @@ PEM_write_bio_PKCS7, PEM_write_PKCS7 - PEM routines
int PEM_write_bio_DHparams(BIO *bp, DH *x);
int PEM_write_DHparams(FILE *fp, DH *x);
- X509 *PEM_read_bio_X509(BIO *bp, X509 **x, pem_password_cb *cb, void *u);
- X509 *PEM_read_X509(FILE *fp, X509 **x, pem_password_cb *cb, void *u);
- int PEM_write_bio_X509(BIO *bp, X509 *x);
- int PEM_write_X509(FILE *fp, X509 *x);
-
- X509 *PEM_read_bio_X509_AUX(BIO *bp, X509 **x, pem_password_cb *cb, void *u);
- X509 *PEM_read_X509_AUX(FILE *fp, X509 **x, pem_password_cb *cb, void *u);
- int PEM_write_bio_X509_AUX(BIO *bp, X509 *x);
- int PEM_write_X509_AUX(FILE *fp, X509 *x);
-
- X509_REQ *PEM_read_bio_X509_REQ(BIO *bp, X509_REQ **x,
- pem_password_cb *cb, void *u);
- X509_REQ *PEM_read_X509_REQ(FILE *fp, X509_REQ **x,
- pem_password_cb *cb, void *u);
- int PEM_write_bio_X509_REQ(BIO *bp, X509_REQ *x);
- int PEM_write_X509_REQ(FILE *fp, X509_REQ *x);
- int PEM_write_bio_X509_REQ_NEW(BIO *bp, X509_REQ *x);
- int PEM_write_X509_REQ_NEW(FILE *fp, X509_REQ *x);
-
- X509_CRL *PEM_read_bio_X509_CRL(BIO *bp, X509_CRL **x,
- pem_password_cb *cb, void *u);
- X509_CRL *PEM_read_X509_CRL(FILE *fp, X509_CRL **x,
- pem_password_cb *cb, void *u);
- int PEM_write_bio_X509_CRL(BIO *bp, X509_CRL *x);
- int PEM_write_X509_CRL(FILE *fp, X509_CRL *x);
-
- PKCS7 *PEM_read_bio_PKCS7(BIO *bp, PKCS7 **x, pem_password_cb *cb, void *u);
- PKCS7 *PEM_read_PKCS7(FILE *fp, PKCS7 **x, pem_password_cb *cb, void *u);
- int PEM_write_bio_PKCS7(BIO *bp, PKCS7 *x);
- int PEM_write_PKCS7(FILE *fp, PKCS7 *x);
-
=head1 DESCRIPTION
+All of the functions described on this page that have a I<TYPE> of B<DH>, B<DSA>
+and B<RSA> are deprecated. Applications should use L<OSSL_ENCODER_to_bio(3)> and
+L<OSSL_DECODER_from_bio(3)> instead.
+
The PEM functions read or write structures in PEM format. In
this sense PEM format is simply base64 encoded data surrounded
by header lines.
@@ -165,13 +204,23 @@ For more details about the meaning of arguments see the
B<PEM FUNCTION ARGUMENTS> section.
Each operation has four functions associated with it. For
-brevity the term "B<TYPE> functions" will be used below to collectively
-refer to the PEM_read_bio_TYPE(), PEM_read_TYPE(),
-PEM_write_bio_TYPE(), and PEM_write_TYPE() functions.
-
-The B<PrivateKey> functions read or write a private key in PEM format using an
-EVP_PKEY structure. The write routines use PKCS#8 private key format and are
-equivalent to PEM_write_bio_PKCS8PrivateKey().The read functions transparently
+brevity the term "B<I<TYPE>> functions" will be used below to collectively
+refer to the B<PEM_read_bio_I<TYPE>>(), B<PEM_read_I<TYPE>>(),
+B<PEM_write_bio_I<TYPE>>(), and B<PEM_write_I<TYPE>>() functions.
+
+Some operations have additional variants that take a library context I<libctx>
+and a property query string I<propq>. The B<X509>, B<X509_REQ> and B<X509_CRL>
+objects may have an associated library context or property query string but
+there are no variants of these functions that take a library context or property
+query string parameter. In this case it is possible to set the appropriate
+library context or property query string by creating an empty B<X509>,
+B<X509_REQ> or B<X509_CRL> object using L<X509_new_ex(3)>, L<X509_REQ_new_ex(3)>
+or L<X509_CRL_new_ex(3)> respectively. Then pass the empty object as a parameter
+to the relevant PEM function. See the L</EXAMPLES> section below.
+
+The B<PrivateKey> functions read or write a private key in PEM format using
+an EVP_PKEY structure. The write routines use PKCS#8 private key format and are
+equivalent to PEM_write_bio_PKCS8PrivateKey(). The read functions transparently
handle traditional and PKCS#8 format encrypted and unencrypted keys.
PEM_write_bio_PrivateKey_traditional() writes out a private key in the
@@ -180,16 +229,16 @@ be used for compatibility with legacy programs.
PEM_write_bio_PKCS8PrivateKey() and PEM_write_PKCS8PrivateKey() write a private
key in an EVP_PKEY structure in PKCS#8 EncryptedPrivateKeyInfo format using
-PKCS#5 v2.0 password based encryption algorithms. The B<cipher> argument
+PKCS#5 v2.0 password based encryption algorithms. The I<cipher> argument
specifies the encryption algorithm to use: unlike some other PEM routines the
encryption is applied at the PKCS#8 level and not in the PEM headers. If
-B<cipher> is NULL then no encryption is used and a PKCS#8 PrivateKeyInfo
+I<cipher> is NULL then no encryption is used and a PKCS#8 PrivateKeyInfo
structure is used instead.
PEM_write_bio_PKCS8PrivateKey_nid() and PEM_write_PKCS8PrivateKey_nid()
also write out a private key as a PKCS#8 EncryptedPrivateKeyInfo however
it uses PKCS#5 v1.5 or PKCS#12 encryption algorithms instead. The algorithm
-to use is specified in the B<nid> parameter and should be the NID of the
+to use is specified in the I<nid> parameter and should be the NID of the
corresponding OBJECT IDENTIFIER (see NOTES section).
The B<PUBKEY> functions process a public key using an EVP_PKEY
@@ -258,36 +307,36 @@ structure.
The PEM functions have many common arguments.
-The B<bp> BIO parameter (if present) specifies the BIO to read from
+The I<bp> BIO parameter (if present) specifies the BIO to read from
or write to.
-The B<fp> FILE parameter (if present) specifies the FILE pointer to
+The I<fp> FILE parameter (if present) specifies the FILE pointer to
read from or write to.
-The PEM read functions all take an argument B<TYPE **x> and return
-a B<TYPE *> pointer. Where B<TYPE> is whatever structure the function
-uses. If B<x> is NULL then the parameter is ignored. If B<x> is not
-NULL but B<*x> is NULL then the structure returned will be written
-to B<*x>. If neither B<x> nor B<*x> is NULL then an attempt is made
-to reuse the structure at B<*x> (but see BUGS and EXAMPLES sections).
-Irrespective of the value of B<x> a pointer to the structure is always
+The PEM read functions all take an argument I<B<TYPE> **x> and return
+a I<B<TYPE> *> pointer. Where I<B<TYPE>> is whatever structure the function
+uses. If I<x> is NULL then the parameter is ignored. If I<x> is not
+NULL but I<*x> is NULL then the structure returned will be written
+to I<*x>. If neither I<x> nor I<*x> is NULL then an attempt is made
+to reuse the structure at I<*x> (but see BUGS and EXAMPLES sections).
+Irrespective of the value of I<x> a pointer to the structure is always
returned (or NULL if an error occurred).
-The PEM functions which write private keys take an B<enc> parameter
+The PEM functions which write private keys take an I<enc> parameter
which specifies the encryption algorithm to use, encryption is done
at the PEM level. If this parameter is set to NULL then the private
key is written in unencrypted form.
-The B<cb> argument is the callback to use when querying for the pass
+The I<cb> argument is the callback to use when querying for the pass
phrase used for encrypted PEM structures (normally only private keys).
-For the PEM write routines if the B<kstr> parameter is not NULL then
-B<klen> bytes at B<kstr> are used as the passphrase and B<cb> is
+For the PEM write routines if the I<kstr> parameter is not NULL then
+I<klen> bytes at I<kstr> are used as the passphrase and I<cb> is
ignored.
-If the B<cb> parameters is set to NULL and the B<u> parameter is not
-NULL then the B<u> parameter is interpreted as a null terminated string
-to use as the passphrase. If both B<cb> and B<u> are NULL then the
+If the I<cb> parameters is set to NULL and the I<u> parameter is not
+NULL then the I<u> parameter is interpreted as a NUL terminated string
+to use as the passphrase. If both I<cb> and I<u> are NULL then the
default callback routine is used which will typically prompt for the
passphrase on the current terminal with echoing turned off.
@@ -297,19 +346,30 @@ routine has the following form:
int cb(char *buf, int size, int rwflag, void *u);
-B<buf> is the buffer to write the passphrase to. B<size> is the maximum
-length of the passphrase (i.e. the size of buf). B<rwflag> is a flag
+I<buf> is the buffer to write the passphrase to. I<size> is the maximum
+length of the passphrase (i.e. the size of buf). I<rwflag> is a flag
which is set to 0 when reading and 1 when writing. A typical routine
will ask the user to verify the passphrase (for example by prompting
-for it twice) if B<rwflag> is 1. The B<u> parameter has the same
-value as the B<u> parameter passed to the PEM routine. It allows
+for it twice) if I<rwflag> is 1. The I<u> parameter has the same
+value as the I<u> parameter passed to the PEM routine. It allows
arbitrary data to be passed to the callback by the application
(for example a window handle in a GUI application). The callback
-B<must> return the number of characters in the passphrase or -1 if
-an error occurred.
+I<must> return the number of characters in the passphrase or -1 if
+an error occurred. The passphrase can be arbitrary data; in the case where it
+is a string, it is not NUL terminated. See the L</EXAMPLES> section below.
+
+Some implementations may need to use cryptographic algorithms during their
+operation. If this is the case and I<libctx> and I<propq> parameters have been
+passed then any algorithm fetches will use that library context and property
+query string. Otherwise the default library context and property query string
+will be used.
=head1 NOTES
+The PEM reading functions will skip any extraneous content or PEM data of
+a different type than they expect. This allows for example having a certificate
+(or multiple certificates) and a key in the PEM format in a single file.
+
The old B<PrivateKey> write routines are retained for compatibility.
New applications should write private keys using the
PEM_write_bio_PKCS8PrivateKey() or PEM_write_PKCS8PrivateKey() routines
@@ -327,7 +387,7 @@ this:
PEM_read_bio_X509(bp, &x, 0, NULL);
-this is a bug because an attempt will be made to reuse the data at B<x>
+this is a bug because an attempt will be made to reuse the data at I<x>
which is an uninitialised pointer.
These functions make no assumption regarding the pass phrase received from the
@@ -355,15 +415,15 @@ cipher encoded as a set of hexadecimal digits. After those two lines is
the base64-encoded encrypted data.
The encryption key is derived using EVP_BytesToKey(). The cipher's
-initialization vector is passed to EVP_BytesToKey() as the B<salt>
+initialization vector is passed to EVP_BytesToKey() as the I<salt>
parameter. Internally, B<PKCS5_SALT_LEN> bytes of the salt are used
(regardless of the size of the initialization vector). The user's
-password is passed to EVP_BytesToKey() using the B<data> and B<datal>
+password is passed to EVP_BytesToKey() using the I<data> and I<datal>
parameters. Finally, the library uses an iteration count of 1 for
EVP_BytesToKey().
-The B<key> derived by EVP_BytesToKey() along with the original initialization
-vector is then used to decrypt the encrypted data. The B<iv> produced by
+The I<key> derived by EVP_BytesToKey() along with the original initialization
+vector is then used to decrypt the encrypted data. The I<iv> produced by
EVP_BytesToKey() is not utilized or needed, and NULL should be passed to
the function.
@@ -372,8 +432,8 @@ The pseudo code to derive the key would look similar to:
EVP_CIPHER* cipher = EVP_des_ede3_cbc();
EVP_MD* md = EVP_md5();
- unsigned int nkey = EVP_CIPHER_key_length(cipher);
- unsigned int niv = EVP_CIPHER_iv_length(cipher);
+ unsigned int nkey = EVP_CIPHER_get_key_length(cipher);
+ unsigned int niv = EVP_CIPHER_get_iv_length(cipher);
unsigned char key[nkey];
unsigned char iv[niv];
@@ -391,12 +451,13 @@ an existing structure. Therefore, the following:
PEM_read_bio_X509(bp, &x, 0, NULL);
-where B<x> already contains a valid certificate, may not work, whereas:
+where I<x> already contains a valid certificate, may not work, whereas:
X509_free(x);
x = PEM_read_bio_X509(bp, NULL, 0, NULL);
-is guaranteed to work.
+is guaranteed to work. It is always acceptable for I<x> to contain a newly
+allocated, empty B<X509> object (for example allocated via L<X509_new_ex(3)>).
=head1 RETURN VALUES
@@ -410,6 +471,16 @@ The write routines return 1 for success or 0 for failure.
Although the PEM routines take several arguments in almost all applications
most of them are set to 0 or NULL.
+To read a certificate with a library context in PEM format from a BIO:
+
+ X509 *x = X509_new_ex(libctx, NULL);
+
+ if (x == NULL)
+ /* Error */
+
+ if (PEM_read_bio_X509(bp, &x, 0, NULL) == NULL)
+ /* Error */
+
Read a certificate in PEM format from a BIO:
X509 *x;
@@ -481,11 +552,31 @@ The old Netscape certificate sequences were no longer documented
in OpenSSL 1.1.0; applications should use the PKCS7 standard instead
as they will be formally deprecated in a future releases.
+PEM_read_bio_PrivateKey_ex(), PEM_read_PrivateKey_ex(),
+PEM_read_bio_PUBKEY_ex(), PEM_read_PUBKEY_ex() and
+PEM_read_bio_Parameters_ex() were introduced in OpenSSL 3.0.
+
+The functions PEM_read_bio_RSAPrivateKey(), PEM_read_RSAPrivateKey(),
+PEM_write_bio_RSAPrivateKey(), PEM_write_RSAPrivateKey(),
+PEM_read_bio_RSAPublicKey(), PEM_read_RSAPublicKey(),
+PEM_write_bio_RSAPublicKey(), PEM_write_RSAPublicKey(),
+PEM_read_bio_RSA_PUBKEY(), PEM_read_RSA_PUBKEY(),
+PEM_write_bio_RSA_PUBKEY(), PEM_write_RSA_PUBKEY(),
+PEM_read_bio_DSAPrivateKey(), PEM_read_DSAPrivateKey(),
+PEM_write_bio_DSAPrivateKey(), PEM_write_DSAPrivateKey(),
+PEM_read_bio_DSA_PUBKEY(), PEM_read_DSA_PUBKEY(),
+PEM_write_bio_DSA_PUBKEY(), PEM_write_DSA_PUBKEY();
+PEM_read_bio_DSAparams(), PEM_read_DSAparams(),
+PEM_write_bio_DSAparams(), PEM_write_DSAparams(),
+PEM_read_bio_DHparams(), PEM_read_DHparams(),
+PEM_write_bio_DHparams() and PEM_write_DHparams() were deprecated in 3.0.
+
+
=head1 COPYRIGHT
-Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/PEM_read_bio_ex.pod b/doc/man3/PEM_read_bio_ex.pod
index 9748e74e0f77..83d16af10a7d 100644
--- a/doc/man3/PEM_read_bio_ex.pod
+++ b/doc/man3/PEM_read_bio_ex.pod
@@ -62,7 +62,7 @@ The PEM_read_bio_ex() function was added in OpenSSL 1.1.1.
Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/PEM_write_bio_CMS_stream.pod b/doc/man3/PEM_write_bio_CMS_stream.pod
index bc3ee167e0c4..f555b259d4d6 100644
--- a/doc/man3/PEM_write_bio_CMS_stream.pod
+++ b/doc/man3/PEM_write_bio_CMS_stream.pod
@@ -42,7 +42,7 @@ The PEM_write_bio_CMS_stream() function was added in OpenSSL 1.0.0.
Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/PEM_write_bio_PKCS7_stream.pod b/doc/man3/PEM_write_bio_PKCS7_stream.pod
index 32b7ef2ef754..badc53979408 100644
--- a/doc/man3/PEM_write_bio_PKCS7_stream.pod
+++ b/doc/man3/PEM_write_bio_PKCS7_stream.pod
@@ -41,7 +41,7 @@ The PEM_write_bio_PKCS7_stream() function was added in OpenSSL 1.0.0.
Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/PKCS12_PBE_keyivgen.pod b/doc/man3/PKCS12_PBE_keyivgen.pod
new file mode 100644
index 000000000000..2cbaa8ed812e
--- /dev/null
+++ b/doc/man3/PKCS12_PBE_keyivgen.pod
@@ -0,0 +1,108 @@
+=pod
+
+=head1 NAME
+
+PKCS12_PBE_keyivgen, PKCS12_PBE_keyivgen_ex,
+PKCS12_pbe_crypt, PKCS12_pbe_crypt_ex - PKCS#12 Password based encryption
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md_type, int en_de);
+ int PKCS12_PBE_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md_type, int en_de,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor,
+ const char *pass, int passlen,
+ const unsigned char *in, int inlen,
+ unsigned char **data, int *datalen,
+ int en_de);
+ unsigned char *PKCS12_pbe_crypt_ex(const X509_ALGOR *algor,
+ const char *pass, int passlen,
+ const unsigned char *in, int inlen,
+ unsigned char **data, int *datalen,
+ int en_de, OSSL_LIB_CTX *libctx,
+ const char *propq);
+
+=head1 DESCRIPTION
+
+PKCS12_PBE_keyivgen() and PKCS12_PBE_keyivgen_ex() take a password I<pass> of
+length I<passlen>, parameters I<param> and a message digest function I<md_type>
+and perform a key derivation according to PKCS#12. The resulting key is
+then used to initialise the cipher context I<ctx> with a cipher I<cipher> for
+encryption (I<en_de>=1) or decryption (I<en_de>=0).
+
+PKCS12_PBE_keyivgen_ex() also allows the application to specify a library context
+I<libctx> and property query I<propq> to select appropriate algorithm
+implementations.
+
+PKCS12_pbe_crypt() and PKCS12_pbe_crypt_ex() will encrypt or decrypt a buffer
+based on the algorithm in I<algor> and password I<pass> of length I<passlen>.
+The input is from I<in> of length I<inlen> and output is into a malloc'd buffer
+returned in I<*data> of length I<datalen>. The operation is determined by I<en_de>,
+encryption (I<en_de>=1) or decryption (I<en_de>=0).
+
+PKCS12_pbe_crypt_ex() allows the application to specify a library context
+I<libctx> and property query I<propq> to select appropriate algorithm
+implementations.
+
+I<pass> is the password used in the derivation of length I<passlen>. I<pass>
+is an optional parameter and can be NULL. If I<passlen> is -1, then the
+function will calculate the length of I<pass> using strlen().
+
+I<salt> is the salt used in the derivation of length I<saltlen>. If the
+I<salt> is NULL, then I<saltlen> must be 0. The function will not
+attempt to calculate the length of the I<salt> because it is not assumed to
+be NULL terminated.
+
+I<iter> is the iteration count and its value should be greater than or
+equal to 1. RFC 2898 suggests an iteration count of at least 1000. Any
+I<iter> less than 1 is treated as a single iteration.
+
+I<digest> is the message digest function used in the derivation.
+
+Functions ending in _ex() take optional parameters I<libctx> and I<propq> which
+are used to select appropriate algorithm implementations.
+
+=head1 NOTES
+
+The functions are typically used in PKCS#12 to encrypt objects.
+
+These functions make no assumption regarding the given password.
+It will simply be treated as a byte sequence.
+
+=head1 RETURN VALUES
+
+PKCS12_PBE_keyivgen(), PKCS12_PBE_keyivgen_ex() return 1 on success or 0 on error.
+
+PKCS12_pbe_crypt() and PKCS12_pbe_crypt_ex() return a buffer containing the
+output or NULL if an error occurred.
+
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
+=head1 SEE ALSO
+
+L<EVP_PBE_CipherInit_ex(3)>,
+L<PKCS8_encrypt_ex(3)>,
+L<passphrase-encoding(7)>
+
+=head1 HISTORY
+
+PKCS12_PBE_keyivgen_ex() and PKCS12_pbe_crypt_ex() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_SAFEBAG_create_cert.pod b/doc/man3/PKCS12_SAFEBAG_create_cert.pod
new file mode 100644
index 000000000000..ef161f01badc
--- /dev/null
+++ b/doc/man3/PKCS12_SAFEBAG_create_cert.pod
@@ -0,0 +1,100 @@
+=pod
+
+=head1 NAME
+
+PKCS12_SAFEBAG_create_cert, PKCS12_SAFEBAG_create_crl,
+PKCS12_SAFEBAG_create_secret, PKCS12_SAFEBAG_create0_p8inf,
+PKCS12_SAFEBAG_create0_pkcs8, PKCS12_SAFEBAG_create_pkcs8_encrypt,
+PKCS12_SAFEBAG_create_pkcs8_encrypt_ex - Create PKCS#12 safeBag objects
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_cert(X509 *x509);
+ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_crl(X509_CRL *crl);
+ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_secret(int type, int vtype,
+ const unsigned char* value,
+ int len);
+ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_p8inf(PKCS8_PRIV_KEY_INFO *p8);
+ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_pkcs8(X509_SIG *p8);
+ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt(int pbe_nid,
+ const char *pass,
+ int passlen,
+ unsigned char *salt,
+ int saltlen, int iter,
+ PKCS8_PRIV_KEY_INFO *p8inf);
+ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(int pbe_nid,
+ const char *pass,
+ int passlen,
+ unsigned char *salt,
+ int saltlen, int iter,
+ PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *ctx,
+ const char *propq);
+
+=head1 DESCRIPTION
+
+PKCS12_SAFEBAG_create_cert() creates a new B<PKCS12_SAFEBAG> of type B<NID_certBag>
+containing the supplied certificate.
+
+PKCS12_SAFEBAG_create_crl() creates a new B<PKCS12_SAFEBAG> of type B<NID_crlBag>
+containing the supplied crl.
+
+PKCS12_SAFEBAG_create_secret() creates a new B<PKCS12_SAFEBAG> of type
+corresponding to a PKCS#12 B<secretBag>. The B<secretBag> contents are tagged as
+I<type> with an ASN1 value of type I<vtype> constructed using the bytes in
+I<value> of length I<len>.
+
+PKCS12_SAFEBAG_create0_p8inf() creates a new B<PKCS12_SAFEBAG> of type B<NID_keyBag>
+containing the supplied PKCS8 structure.
+
+PKCS12_SAFEBAG_create0_pkcs8() creates a new B<PKCS12_SAFEBAG> of type
+B<NID_pkcs8ShroudedKeyBag> containing the supplied PKCS8 structure.
+
+PKCS12_SAFEBAG_create_pkcs8_encrypt() creates a new B<PKCS12_SAFEBAG> of type
+B<NID_pkcs8ShroudedKeyBag> by encrypting the supplied PKCS8 I<p8inf>.
+If I<pbe_nid> is 0, a default encryption algorithm is used. I<pass> is the
+passphrase and I<iter> is the iteration count. If I<iter> is zero then a default
+value of 2048 is used. If I<salt> is NULL then a salt is generated randomly.
+
+PKCS12_SAFEBAG_create_pkcs8_encrypt_ex() is identical to PKCS12_SAFEBAG_create_pkcs8_encrypt()
+but allows for a library context I<ctx> and property query I<propq> to be used to select
+algorithm implementations.
+
+=head1 NOTES
+
+PKCS12_SAFEBAG_create_pkcs8_encrypt() makes assumptions regarding the encoding of the given pass
+phrase.
+See L<passphrase-encoding(7)> for more information.
+
+PKCS12_SAFEBAG_create_secret() was added in OpenSSL 3.0.
+
+=head1 RETURN VALUES
+
+All of these functions return a valid B<PKCS12_SAFEBAG> structure or NULL if an error occurred.
+
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
+=head1 SEE ALSO
+
+L<PKCS12_create(3)>,
+L<PKCS12_add_safe(3)>,
+L<PKCS12_add_safes(3)>
+
+=head1 HISTORY
+
+PKCS12_SAFEBAG_create_pkcs8_encrypt_ex() was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_SAFEBAG_get0_attrs.pod b/doc/man3/PKCS12_SAFEBAG_get0_attrs.pod
new file mode 100644
index 000000000000..7073c0d5cec0
--- /dev/null
+++ b/doc/man3/PKCS12_SAFEBAG_get0_attrs.pod
@@ -0,0 +1,50 @@
+=pod
+
+=head1 NAME
+
+PKCS12_SAFEBAG_get0_attrs, PKCS12_get_attr_gen
+- Retrieve attributes from a PKCS#12 safeBag
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ const STACK_OF(X509_ATTRIBUTE) *PKCS12_SAFEBAG_get0_attrs(const PKCS12_SAFEBAG *bag);
+
+ ASN1_TYPE *PKCS12_get_attr_gen(const STACK_OF(X509_ATTRIBUTE) *attrs,
+ int attr_nid);
+
+=head1 DESCRIPTION
+
+PKCS12_SAFEBAG_get0_attrs() retrieves the stack of B<X509_ATTRIBUTE>s from a
+PKCS#12 safeBag. I<bag> is the B<PKCS12_SAFEBAG> to retrieve the attributes from.
+
+PKCS12_get_attr_gen() retrieves an attribute by NID from a stack of
+B<X509_ATTRIBUTE>s. I<attr_nid> is the NID of the attribute to retrieve.
+
+=head1 RETURN VALUES
+
+PKCS12_SAFEBAG_get0_attrs() returns the stack of B<X509_ATTRIBUTE>s from a
+PKCS#12 safeBag, which could be empty.
+
+PKCS12_get_attr_gen() returns an B<ASN1_TYPE> object containing the attribute,
+or NULL if the attribute was either not present or an error occurred.
+
+PKCS12_get_attr_gen() does not allocate a new attribute. The returned attribute
+is still owned by the B<PKCS12_SAFEBAG> in which it resides.
+
+=head1 SEE ALSO
+
+L<PKCS12_get_friendlyname(3)>,
+L<PKCS12_add_friendlyname_asc(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_SAFEBAG_get1_cert.pod b/doc/man3/PKCS12_SAFEBAG_get1_cert.pod
new file mode 100644
index 000000000000..ecd212c775ec
--- /dev/null
+++ b/doc/man3/PKCS12_SAFEBAG_get1_cert.pod
@@ -0,0 +1,74 @@
+=pod
+
+=head1 NAME
+
+PKCS12_SAFEBAG_get0_attr, PKCS12_SAFEBAG_get0_type,
+PKCS12_SAFEBAG_get_nid, PKCS12_SAFEBAG_get_bag_nid,
+PKCS12_SAFEBAG_get0_bag_obj, PKCS12_SAFEBAG_get0_bag_type,
+PKCS12_SAFEBAG_get1_cert, PKCS12_SAFEBAG_get1_crl,
+PKCS12_SAFEBAG_get0_safes, PKCS12_SAFEBAG_get0_p8inf,
+PKCS12_SAFEBAG_get0_pkcs8 - Get objects from a PKCS#12 safeBag
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ const ASN1_TYPE *PKCS12_SAFEBAG_get0_attr(const PKCS12_SAFEBAG *bag,
+ int attr_nid);
+ const ASN1_OBJECT *PKCS12_SAFEBAG_get0_type(const PKCS12_SAFEBAG *bag);
+ int PKCS12_SAFEBAG_get_nid(const PKCS12_SAFEBAG *bag);
+ int PKCS12_SAFEBAG_get_bag_nid(const PKCS12_SAFEBAG *bag);
+ const ASN1_TYPE *PKCS12_SAFEBAG_get0_bag_obj(const PKCS12_SAFEBAG *bag);
+ const ASN1_OBJECT *PKCS12_SAFEBAG_get0_bag_type(const PKCS12_SAFEBAG *bag);
+ X509 *PKCS12_SAFEBAG_get1_cert(const PKCS12_SAFEBAG *bag);
+ X509_CRL *PKCS12_SAFEBAG_get1_crl(const PKCS12_SAFEBAG *bag);
+ const STACK_OF(PKCS12_SAFEBAG) *PKCS12_SAFEBAG_get0_safes(const PKCS12_SAFEBAG *bag);
+ const PKCS8_PRIV_KEY_INFO *PKCS12_SAFEBAG_get0_p8inf(const PKCS12_SAFEBAG *bag);
+ const X509_SIG *PKCS12_SAFEBAG_get0_pkcs8(const PKCS12_SAFEBAG *bag);
+
+=head1 DESCRIPTION
+
+PKCS12_SAFEBAG_get0_attr() gets the attribute value corresponding to the B<attr_nid>.
+
+PKCS12_SAFEBAG_get0_type() gets the B<safeBag> type as an OID, whereas
+PKCS12_SAFEBAG_get_nid() gets the B<safeBag> type as an NID, which could be
+B<NID_certBag>, B<NID_crlBag>, B<NID_keyBag>, B<NID_secretBag>, B<NID_safeContentsBag>
+or B<NID_pkcs8ShroudedKeyBag>.
+
+PKCS12_SAFEBAG_get_bag_nid() gets the type of the object contained within the
+B<PKCS12_SAFEBAG>. This corresponds to the bag type for most bags, but can be
+arbitrary for B<secretBag>s. PKCS12_SAFEBAG_get0_bag_type() gets this type as an OID.
+
+PKCS12_SAFEBAG_get0_bag_obj() retrieves the object contained within the safeBag.
+
+PKCS12_SAFEBAG_get1_cert() and PKCS12_SAFEBAG_get1_crl() return new B<X509> or
+B<X509_CRL> objects from the item in the safeBag.
+
+PKCS12_SAFEBAG_get0_p8inf() and PKCS12_SAFEBAG_get0_pkcs8() return the PKCS8 object
+from a PKCS8shroudedKeyBag or a keyBag.
+
+PKCS12_SAFEBAG_get0_safes() retrieves the set of B<safeBags> contained within a
+safeContentsBag.
+
+=head1 RETURN VALUES
+
+PKCS12_SAFEBAG_get_nid() and PKCS12_SAFEBAG_get_bag_nid() return the NID of the safeBag
+or bag object, or -1 if there is no corresponding NID.
+Other functions return a valid object of the specified type or NULL if an error occurred.
+
+=head1 SEE ALSO
+
+L<PKCS12_create(3)>,
+L<PKCS12_add_safe(3)>,
+L<PKCS12_add_safes(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_add1_attr_by_NID.pod b/doc/man3/PKCS12_add1_attr_by_NID.pod
new file mode 100644
index 000000000000..4871da35d7ee
--- /dev/null
+++ b/doc/man3/PKCS12_add1_attr_by_NID.pod
@@ -0,0 +1,52 @@
+=pod
+
+=head1 NAME
+
+PKCS12_add1_attr_by_NID, PKCS12_add1_attr_by_txt - Add an attribute to a PKCS#12
+safeBag structure
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ int PKCS12_add1_attr_by_NID(PKCS12_SAFEBAG *bag, int nid, int type,
+ const unsigned char *bytes, int len);
+ int PKCS12_add1_attr_by_txt(PKCS12_SAFEBAG *bag, const char *attrname, int type,
+ const unsigned char *bytes, int len);
+
+=head1 DESCRIPTION
+
+These functions add a PKCS#12 Attribute to the Attribute Set of the B<bag>.
+
+PKCS12_add1_attr_by_NID() adds an attribute of type B<nid> with a value of ASN1
+type B<type> constructed using B<len> bytes from B<bytes>.
+
+PKCS12_add1_attr_by_txt() adds an attribute of type B<attrname> with a value of
+ASN1 type B<type> constructed using B<len> bytes from B<bytes>.
+
+=head1 NOTES
+
+These functions do not check whether an existing attribute of the same type is
+present. There can be multiple attributes with the same type assigned to a
+safeBag.
+
+Both functions were added in OpenSSL 3.0.
+
+=head1 RETURN VALUES
+
+A return value of 1 indicates success, 0 indicates failure.
+
+=head1 SEE ALSO
+
+L<PKCS12_create(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_add_CSPName_asc.pod b/doc/man3/PKCS12_add_CSPName_asc.pod
new file mode 100644
index 000000000000..87d9e7130241
--- /dev/null
+++ b/doc/man3/PKCS12_add_CSPName_asc.pod
@@ -0,0 +1,36 @@
+=pod
+
+=head1 NAME
+
+PKCS12_add_CSPName_asc - Add a Microsoft CSP Name attribute to a PKCS#12 safeBag
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ int PKCS12_add_CSPName_asc(PKCS12_SAFEBAG *bag, const char *name, int namelen);
+
+=head1 DESCRIPTION
+
+PKCS12_add_CSPName_asc() adds an ASCII string representation of the Microsoft CSP Name attribute to a PKCS#12 safeBag.
+
+I<bag> is the B<PKCS12_SAFEBAG> to add the attribute to.
+
+=head1 RETURN VALUES
+
+Returns 1 for success or 0 for failure.
+
+=head1 SEE ALSO
+
+L<PKCS12_add_friendlyname_asc(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_add_cert.pod b/doc/man3/PKCS12_add_cert.pod
new file mode 100644
index 000000000000..ae3b21a13c6c
--- /dev/null
+++ b/doc/man3/PKCS12_add_cert.pod
@@ -0,0 +1,81 @@
+=pod
+
+=head1 NAME
+
+PKCS12_add_cert, PKCS12_add_key, PKCS12_add_key_ex,
+PKCS12_add_secret - Add an object to a set of PKCS#12 safeBags
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert);
+ PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
+ EVP_PKEY *key, int key_usage, int iter,
+ int key_nid, const char *pass);
+ PKCS12_SAFEBAG *PKCS12_add_key_ex(STACK_OF(PKCS12_SAFEBAG) **pbags,
+ EVP_PKEY *key, int key_usage, int iter,
+ int key_nid, const char *pass,
+ OSSL_LIB_CTX *ctx, const char *propq);
+
+ PKCS12_SAFEBAG *PKCS12_add_secret(STACK_OF(PKCS12_SAFEBAG) **pbags,
+ int nid_type, const unsigned char *value, int len);
+
+=head1 DESCRIPTION
+
+These functions create a new B<PKCS12_SAFEBAG> and add it to the set of safeBags
+in I<pbags>.
+
+PKCS12_add_cert() creates a PKCS#12 certBag containing the supplied
+certificate and adds this to the set of PKCS#12 safeBags.
+
+PKCS12_add_key() creates a PKCS#12 keyBag (unencrypted) or a pkcs8shroudedKeyBag
+(encrypted) containing the supplied B<EVP_PKEY> and adds this to the set of PKCS#12
+safeBags. If I<key_nid> is not -1 then the key is encrypted with the supplied
+algorithm, using I<pass> as the passphrase and I<iter> as the iteration count. If
+I<iter> is zero then a default value for iteration count of 2048 is used.
+
+PKCS12_add_key_ex() is identical to PKCS12_add_key() but allows for a library
+context I<ctx> and property query I<propq> to be used to select algorithm
+implementations.
+
+PKCS12_add_secret() creates a PKCS#12 secretBag with an OID corresponding to
+the supplied I<nid_type> containing the supplied value as an ASN1 octet string.
+This is then added to the set of PKCS#12 safeBags.
+
+=head1 NOTES
+
+If a certificate contains an I<alias> or a I<keyid> then this will be
+used for the corresponding B<friendlyName> or B<localKeyID> in the
+PKCS12 structure.
+
+PKCS12_add_key() makes assumptions regarding the encoding of the given pass
+phrase.
+See L<passphrase-encoding(7)> for more information.
+
+=head1 RETURN VALUES
+
+A valid B<PKCS12_SAFEBAG> structure or NULL if an error occurred.
+
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
+=head1 SEE ALSO
+
+L<PKCS12_create(3)>
+
+=head1 HISTORY
+
+PKCS12_add_secret() and PKCS12_add_key_ex() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_add_friendlyname_asc.pod b/doc/man3/PKCS12_add_friendlyname_asc.pod
new file mode 100644
index 000000000000..3920b5daa015
--- /dev/null
+++ b/doc/man3/PKCS12_add_friendlyname_asc.pod
@@ -0,0 +1,52 @@
+=pod
+
+=head1 NAME
+
+PKCS12_add_friendlyname_asc, PKCS12_add_friendlyname_utf8,
+PKCS12_add_friendlyname_uni - Functions to add the friendlyname attribute to a
+PKCS#12 safeBag
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ int PKCS12_add_friendlyname_asc(PKCS12_SAFEBAG *bag, const char *name,
+ int namelen);
+
+ int PKCS12_add_friendlyname_utf8(PKCS12_SAFEBAG *bag, const char *name,
+ int namelen);
+
+ int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag,
+ const unsigned char *name, int namelen);
+
+=head1 DESCRIPTION
+
+PKCS12_add_friendlyname_asc() adds an ASCII string representation of the PKCS#9
+friendlyName attribute to a PKCS#12 safeBag.
+
+PKCS12_add_friendlyname_utf8() adds a UTF-8 string representation of the PKCS#9
+friendlyName attribute to a PKCS#12 safeBag.
+
+PKCS12_add_friendlyname_uni() adds a Unicode string representation of the PKCS#9
+friendlyName attribute to a PKCS#12 safeBag.
+
+I<bag> is the B<PKCS12_SAFEBAG> to add the attribute to.
+
+=head1 RETURN VALUES
+
+Returns 1 for success or 0 for failure.
+
+=head1 SEE ALSO
+
+L<PKCS12_get_friendlyname(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_add_localkeyid.pod b/doc/man3/PKCS12_add_localkeyid.pod
new file mode 100644
index 000000000000..6d9ff9883ef7
--- /dev/null
+++ b/doc/man3/PKCS12_add_localkeyid.pod
@@ -0,0 +1,38 @@
+=pod
+
+=head1 NAME
+
+PKCS12_add_localkeyid - Add the localKeyId attribute to a PKCS#12 safeBag
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, const char *name,
+ int namelen);
+
+=head1 DESCRIPTION
+
+PKCS12_add_localkeyid() adds an octet string representation of the PKCS#9
+localKeyId attribute to a PKCS#12 safeBag.
+
+I<bag> is the B<PKCS12_SAFEBAG> to add the attribute to.
+
+=head1 RETURN VALUES
+
+Returns 1 for success or 0 for failure.
+
+=head1 SEE ALSO
+
+L<PKCS12_add_friendlyname_asc(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_add_safe.pod b/doc/man3/PKCS12_add_safe.pod
new file mode 100644
index 000000000000..881ab1d75cd7
--- /dev/null
+++ b/doc/man3/PKCS12_add_safe.pod
@@ -0,0 +1,87 @@
+=pod
+
+=head1 NAME
+
+PKCS12_add_safe, PKCS12_add_safe_ex,
+PKCS12_add_safes, PKCS12_add_safes_ex - Create and add objects to a PKCS#12 structure
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
+ int safe_nid, int iter, const char *pass);
+ int PKCS12_add_safe_ex(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
+ int safe_nid, int iter, const char *pass,
+ OSSL_LIB_CTX *ctx, const char *propq);
+
+ PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int p7_nid);
+ PKCS12 *PKCS12_add_safes_ex(STACK_OF(PKCS7) *safes, int p7_nid,
+ OSSL_LIB_CTX *ctx, const char *propq);
+
+=head1 DESCRIPTION
+
+PKCS12_add_safe() creates a new PKCS7 contentInfo containing the supplied
+B<PKCS12_SAFEBAG>s and adds this to a set of PKCS7 contentInfos. Its type
+depends on the value of B<safe_nid>:
+
+=over 4
+
+=item * If I<safe_nid> is -1, a plain PKCS7 I<data> contentInfo is created.
+
+=item * If I<safe_nid> is a valid PBE algorithm NID, a PKCS7 B<encryptedData>
+contentInfo is created. The algorithm uses I<pass> as the passphrase and I<iter>
+as the iteration count. If I<iter> is zero then a default value for iteration
+count of 2048 is used.
+
+=item * If I<safe_nid> is 0, a PKCS7 B<encryptedData> contentInfo is created using
+a default encryption algorithm, currently B<NID_pbe_WithSHA1And3_Key_TripleDES_CBC>.
+
+=back
+
+PKCS12_add_safe_ex() is identical to PKCS12_add_safe() but allows for a library
+context I<ctx> and property query I<propq> to be used to select algorithm
+implementations.
+
+PKCS12_add_safes() creates a B<PKCS12> structure containing the supplied set of
+PKCS7 contentInfos. The I<safes> are enclosed first within a PKCS7 contentInfo
+of type I<p7_nid>. Currently the only supported type is B<NID_pkcs7_data>.
+
+PKCS12_add_safes_ex() is identical to PKCS12_add_safes() but allows for a
+library context I<ctx> and property query I<propq> to be used to select
+algorithm implementations.
+
+=head1 NOTES
+
+PKCS12_add_safe() makes assumptions regarding the encoding of the given pass
+phrase.
+See L<passphrase-encoding(7)> for more information.
+
+=head1 RETURN VALUES
+
+PKCS12_add_safe() returns a value of 1 indicating success or 0 for failure.
+
+PKCS12_add_safes() returns a valid B<PKCS12> structure or NULL if an error occurred.
+
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
+=head1 SEE ALSO
+
+L<PKCS12_create(3)>
+
+=head1 HISTORY
+
+PKCS12_add_safe_ex() and PKCS12_add_safes_ex() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_create.pod b/doc/man3/PKCS12_create.pod
index 1587ea53e37d..dc0f06d9d323 100644
--- a/doc/man3/PKCS12_create.pod
+++ b/doc/man3/PKCS12_create.pod
@@ -2,7 +2,7 @@
=head1 NAME
-PKCS12_create - create a PKCS#12 structure
+PKCS12_create, PKCS12_create_ex - create a PKCS#12 structure
=head1 SYNOPSIS
@@ -11,36 +11,44 @@ PKCS12_create - create a PKCS#12 structure
PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey,
X509 *cert, STACK_OF(X509) *ca,
int nid_key, int nid_cert, int iter, int mac_iter, int keytype);
+ PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey,
+ X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
+ int iter, int mac_iter, int keytype,
+ OSSL_LIB_CTX *ctx, const char *propq);
=head1 DESCRIPTION
PKCS12_create() creates a PKCS#12 structure.
-B<pass> is the passphrase to use. B<name> is the B<friendlyName> to use for
-the supplied certificate and key. B<pkey> is the private key to include in
-the structure and B<cert> its corresponding certificates. B<ca>, if not B<NULL>
+I<pass> is the passphrase to use. I<name> is the B<friendlyName> to use for
+the supplied certificate and key. I<pkey> is the private key to include in
+the structure and I<cert> its corresponding certificates. I<ca>, if not B<NULL>
is an optional set of certificates to also include in the structure.
-B<nid_key> and B<nid_cert> are the encryption algorithms that should be used
+I<nid_key> and I<nid_cert> are the encryption algorithms that should be used
for the key and certificate respectively. The modes
-GCM, CCM, XTS, and OCB are unsupported. B<iter> is the encryption algorithm
-iteration count to use and B<mac_iter> is the MAC iteration count to use.
-B<keytype> is the type of key.
+GCM, CCM, XTS, and OCB are unsupported. I<iter> is the encryption algorithm
+iteration count to use and I<mac_iter> is the MAC iteration count to use.
+I<keytype> is the type of key.
+
+PKCS12_create_ex() is identical to PKCS12_create() but allows for a library context
+I<ctx> and property query I<propq> to be used to select algorithm implementations.
=head1 NOTES
-The parameters B<nid_key>, B<nid_cert>, B<iter>, B<mac_iter> and B<keytype>
+The parameters I<nid_key>, I<nid_cert>, I<iter>, I<mac_iter> and I<keytype>
can all be set to zero and sensible defaults will be used.
-These defaults are: 40 bit RC2 encryption for certificates, triple DES
-encryption for private keys, a key iteration count of PKCS12_DEFAULT_ITER
-(currently 2048) and a MAC iteration count of 1.
+These defaults are: AES password based encryption (PBES2 with PBKDF2 and
+AES-256-CBC) for private keys and certificates, the PBKDF2 and MAC key
+derivation iteration count of B<PKCS12_DEFAULT_ITER> (currently 2048), and
+MAC algorithm HMAC with SHA2-256.
The default MAC iteration count is 1 in order to retain compatibility with
old software which did not interpret MAC iteration counts. If such compatibility
-is not required then B<mac_iter> should be set to PKCS12_DEFAULT_ITER.
+is not required then I<mac_iter> should be set to PKCS12_DEFAULT_ITER.
-B<keytype> adds a flag to the store private key. This is a non standard extension
+I<keytype> adds a flag to the store private key. This is a non standard extension
that is only currently interpreted by MSIE. If set to zero the flag is omitted,
if set to B<KEY_SIG> the key can be used for signing only, if set to B<KEY_EX>
it can be used for signing and encryption. This option was useful for old
@@ -48,18 +56,18 @@ export grade software which could use signing only keys of arbitrary size but
had restrictions on the permissible sizes of keys which could be used for
encryption.
-If a certificate contains an B<alias> or B<keyid> then this will be
+If a certificate contains an I<alias> or I<keyid> then this will be
used for the corresponding B<friendlyName> or B<localKeyID> in the
PKCS12 structure.
-Either B<pkey>, B<cert> or both can be B<NULL> to indicate that no key or
+Either I<pkey>, I<cert> or both can be B<NULL> to indicate that no key or
certificate is required. In previous versions both had to be present or
a fatal error is returned.
-B<nid_key> or B<nid_cert> can be set to -1 indicating that no encryption
+I<nid_key> or I<nid_cert> can be set to -1 indicating that no encryption
should be used.
-B<mac_iter> can be set to -1 and the MAC will then be omitted entirely.
+I<mac_iter> can be set to -1 and the MAC will then be omitted entirely.
PKCS12_create() makes assumptions regarding the encoding of the given pass
phrase.
@@ -69,16 +77,28 @@ See L<passphrase-encoding(7)> for more information.
PKCS12_create() returns a valid B<PKCS12> structure or NULL if an error occurred.
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
=head1 SEE ALSO
L<d2i_PKCS12(3)>,
L<passphrase-encoding(7)>
+=head1 HISTORY
+
+PKCS12_create_ex() was added in OpenSSL 3.0.
+
+The defaults for encryption algorithms, MAC algorithm, and the MAC key
+derivation iteration count were changed in OpenSSL 3.0 to more modern
+standards.
+
=head1 COPYRIGHT
-Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/PKCS12_decrypt_skey.pod b/doc/man3/PKCS12_decrypt_skey.pod
new file mode 100644
index 000000000000..7a41b2b06c2f
--- /dev/null
+++ b/doc/man3/PKCS12_decrypt_skey.pod
@@ -0,0 +1,55 @@
+=pod
+
+=head1 NAME
+
+PKCS12_decrypt_skey, PKCS12_decrypt_skey_ex - PKCS12 shrouded keyBag
+decrypt functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(const PKCS12_SAFEBAG *bag,
+ const char *pass, int passlen);
+ PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey_ex(const PKCS12_SAFEBAG *bag,
+ const char *pass, int passlen,
+ OSSL_LIB_CTX *ctx,
+ const char *propq);
+
+=head1 DESCRIPTION
+
+PKCS12_decrypt_skey() Decrypt the PKCS#8 shrouded keybag contained within I<bag>
+using the supplied password I<pass> of length I<passlen>.
+
+PKCS12_decrypt_skey_ex() is similar to the above but allows for a library contex
+I<ctx> and property query I<propq> to be used to select algorithm implementations.
+
+=head1 RETURN VALUES
+
+Both functions will return the decrypted key or NULL if an error occurred.
+
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
+=head1 SEE ALSO
+
+L<PKCS8_decrypt_ex(3)>,
+L<PKCS8_encrypt_ex(3)>,
+L<PKCS12_add_key_ex(3)>,
+L<PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(3)>
+
+=head1 HISTORY
+
+PKCS12_decrypt_skey_ex() was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_gen_mac.pod b/doc/man3/PKCS12_gen_mac.pod
new file mode 100644
index 000000000000..53b55e870303
--- /dev/null
+++ b/doc/man3/PKCS12_gen_mac.pod
@@ -0,0 +1,72 @@
+=pod
+
+=head1 NAME
+
+PKCS12_gen_mac, PKCS12_setup_mac, PKCS12_set_mac,
+PKCS12_verify_mac - Functions to create and manipulate a PKCS#12 structure
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
+ unsigned char *mac, unsigned int *maclen);
+ int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen);
+ int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
+ unsigned char *salt, int saltlen, int iter,
+ const EVP_MD *md_type);
+ int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt,
+ int saltlen, const EVP_MD *md_type);
+
+=head1 DESCRIPTION
+
+PKCS12_gen_mac() generates an HMAC over the entire PKCS#12 object using the
+supplied password along with a set of already configured paramters.
+
+PKCS12_verify_mac() verifies the PKCS#12 object's HMAC using the supplied
+password.
+
+PKCS12_setup_mac() sets the MAC part of the PKCS#12 structure with the supplied
+parameters.
+
+PKCS12_set_mac() sets the MAC and MAC parameters into the PKCS#12 object.
+
+I<pass> is the passphrase to use in the HMAC. I<salt> is the salt value to use,
+I<iter> is the iteration count and I<md_type> is the message digest
+function to use.
+
+=head1 NOTES
+
+If I<salt> is NULL then a suitable salt will be generated and used.
+
+If I<iter> is 1 then an iteration count will be omitted from the PKCS#12
+structure.
+
+PKCS12_gen_mac(), PKCS12_verify_mac() and PKCS12_set_mac() make assumptions
+regarding the encoding of the given passphrase. See L<passphrase-encoding(7)>
+for more information.
+
+=head1 RETURN VALUES
+
+All functions return 1 on success and 0 if an error occurred.
+
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
+=head1 SEE ALSO
+
+L<d2i_PKCS12(3)>,
+L<PKCS12_create(3)>,
+L<passphrase-encoding(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_get_friendlyname.pod b/doc/man3/PKCS12_get_friendlyname.pod
new file mode 100644
index 000000000000..e96f7a255a7a
--- /dev/null
+++ b/doc/man3/PKCS12_get_friendlyname.pod
@@ -0,0 +1,39 @@
+=pod
+
+=head1 NAME
+
+PKCS12_get_friendlyname - Retrieve the friendlyname attribute from a PKCS#12 safeBag
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag);
+
+=head1 DESCRIPTION
+
+PKCS12_get_friendlyname() retrieves a UTF-8 string representation of the PKCS#9
+friendlyName attribute for a PKCS#12 safeBag item.
+
+I<bag> is the B<PKCS12_SAFEBAG> to retrieve the attribute from.
+
+=head1 RETURN VALUES
+
+A UTF-8 string, or NULL if the attribute was either not present or an error occurred.
+
+The returned string is allocated by OpenSSL and should be freed by the user.
+
+=head1 SEE ALSO
+
+L<PKCS12_add_friendlyname_asc(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_init.pod b/doc/man3/PKCS12_init.pod
new file mode 100644
index 000000000000..b0d3aa5fa9b8
--- /dev/null
+++ b/doc/man3/PKCS12_init.pod
@@ -0,0 +1,48 @@
+=pod
+
+=head1 NAME
+
+PKCS12_init, PKCS12_init_ex - Create a new empty PKCS#12 structure
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ PKCS12 *PKCS12_init(int mode);
+ PKCS12 *PKCS12_init_ex(int mode, OSSL_LIB_CTX *ctx, const char *propq);
+
+=head1 DESCRIPTION
+
+PKCS12_init() creates an empty PKCS#12 structure. Any PKCS#7 authSafes added
+to this structure are enclosed first within a single PKCS#7 contentInfo
+of type I<mode>. Currently the only supported type is B<NID_pkcs7_data>.
+
+PKCS12_init_ex() creates an empty PKCS#12 structure and assigns the supplied
+I<ctx> and I<propq> to be used to select algorithm implementations for
+operations performed on the B<PKCS12> object.
+
+=head1 RETURN VALUES
+
+PKCS12_init() and PKCS12_init_ex() return a valid B<PKCS12> structure or NULL
+if an error occurred.
+
+=head1 SEE ALSO
+
+L<d2i_PKCS12(3)>,
+L<PKCS12_create(3)>,
+L<passphrase-encoding(7)>
+
+=head1 HISTORY
+
+PKCS12_init_ex() was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_item_decrypt_d2i.pod b/doc/man3/PKCS12_item_decrypt_d2i.pod
new file mode 100644
index 000000000000..5bf498e8a894
--- /dev/null
+++ b/doc/man3/PKCS12_item_decrypt_d2i.pod
@@ -0,0 +1,73 @@
+=pod
+
+=head1 NAME
+
+PKCS12_item_decrypt_d2i, PKCS12_item_decrypt_d2i_ex,
+PKCS12_item_i2d_encrypt, PKCS12_item_i2d_encrypt_ex - PKCS12 item
+encrypt/decrypt functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ void *PKCS12_item_decrypt_d2i(const X509_ALGOR *algor, const ASN1_ITEM *it,
+ const char *pass, int passlen,
+ const ASN1_OCTET_STRING *oct, int zbuf);
+ void *PKCS12_item_decrypt_d2i_ex(const X509_ALGOR *algor, const ASN1_ITEM *it,
+ const char *pass, int passlen,
+ const ASN1_OCTET_STRING *oct, int zbuf,
+ OSSL_LIB_CTX *libctx,
+ const char *propq);
+ ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor,
+ const ASN1_ITEM *it,
+ const char *pass, int passlen,
+ void *obj, int zbuf);
+ ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt_ex(X509_ALGOR *algor,
+ const ASN1_ITEM *it,
+ const char *pass, int passlen,
+ void *obj, int zbuf,
+ OSSL_LIB_CTX *ctx,
+ const char *propq);
+
+=head1 DESCRIPTION
+
+PKCS12_item_decrypt_d2i() and PKCS12_item_decrypt_d2i_ex() decrypt an octet
+string containing an ASN.1 encoded object using the algorithm I<algor> and
+password I<pass> of length I<passlen>. If I<zbuf> is nonzero then the output
+buffer will zeroed after the decrypt.
+
+PKCS12_item_i2d_encrypt() and PKCS12_item_i2d_encrypt_ex() encrypt an ASN.1
+object I<it> using the algorithm I<algor> and password I<pass> of length
+I<passlen>, returning an encoded object in I<obj>. If I<zbuf> is nonzero then
+the buffer containing the input encoding will be zeroed after the encrypt.
+
+Functions ending in _ex() allow for a library context I<ctx> and property query
+I<propq> to be used to select algorithm implementations.
+
+=head1 RETURN VALUES
+
+PKCS12_item_decrypt_d2i() and PKCS12_item_decrypt_d2i_ex() return the decrypted
+object or NULL if an error occurred.
+
+PKCS12_item_i2d_encrypt() and PKCS12_item_i2d_encrypt_ex() return the encrypted
+data as an ASN.1 Octet String or NULL if an error occurred.
+
+=head1 SEE ALSO
+
+L<PKCS12_pbe_crypt_ex(3)>,
+L<PKCS8_encrypt_ex(3)>
+
+=head1 HISTORY
+
+PKCS12_item_decrypt_d2i_ex() and PKCS12_item_i2d_encrypt_ex() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_key_gen_utf8_ex.pod b/doc/man3/PKCS12_key_gen_utf8_ex.pod
new file mode 100644
index 000000000000..d66f8c700091
--- /dev/null
+++ b/doc/man3/PKCS12_key_gen_utf8_ex.pod
@@ -0,0 +1,138 @@
+=pod
+
+=head1 NAME
+
+PKCS12_key_gen_asc, PKCS12_key_gen_asc_ex,
+PKCS12_key_gen_uni, PKCS12_key_gen_uni_ex,
+PKCS12_key_gen_utf8, PKCS12_key_gen_utf8_ex - PKCS#12 Password based key derivation
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type);
+ int PKCS12_key_gen_asc_ex(const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type,
+ OSSL_LIB_CTX *ctx, const char *propq);
+ int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type);
+ int PKCS12_key_gen_uni_ex(unsigned char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type,
+ OSSL_LIB_CTX *ctx, const char *propq);
+ int PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type);
+ int PKCS12_key_gen_utf8_ex(const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type,
+ OSSL_LIB_CTX *ctx, const char *propq);
+
+=head1 DESCRIPTION
+
+These methods perform a key derivation according to PKCS#12 (RFC7292)
+with an input password I<pass> of length I<passlen>, a salt I<salt> of length
+I<saltlen>, an iteration count I<iter> and a digest algorithm I<md_type>.
+The ID byte I<id> determines how the resulting key is intended to be used:
+
+=over 4
+
+=item *
+
+If ID=1, then the pseudorandom bits being produced are to be used
+as key material for performing encryption or decryption.
+
+=item *
+
+If ID=2, then the pseudorandom bits being produced are to be used
+as an IV (Initial Value) for encryption or decryption.
+
+=item *
+
+If ID=3, then the pseudorandom bits being produced are to be used
+as an integrity key for MACing.
+
+=back
+
+The intended format of the supplied password is determined by the method chosen:
+
+=over 4
+
+=item *
+
+PKCS12_key_gen_asc() and PKCS12_key_gen_asc_ex() expect an ASCII-formatted password.
+
+=item *
+
+PKCS12_key_gen_uni() and PKCS12_key_gen_uni_ex() expect a Unicode-formatted password.
+
+=item *
+
+PKCS12_key_gen_utf8() and PKCS12_key_gen_utf8_ex() expect a UTF-8 encoded password.
+
+=back
+
+I<pass> is the password used in the derivation of length I<passlen>. I<pass>
+is an optional parameter and can be NULL. If I<passlen> is -1, then the
+function will calculate the length of I<pass> using strlen().
+
+I<salt> is the salt used in the derivation of length I<saltlen>. If the
+I<salt> is NULL, then I<saltlen> must be 0. The function will not
+attempt to calculate the length of the I<salt> because it is not assumed to
+be NULL terminated.
+
+I<iter> is the iteration count and its value should be greater than or
+equal to 1. RFC 2898 suggests an iteration count of at least 1000. Any
+I<iter> less than 1 is treated as a single iteration.
+
+I<digest> is the message digest function used in the derivation.
+
+The derived key will be written to I<out>. The size of the I<out> buffer
+is specified via I<n>.
+
+Functions ending in _ex() allow for a library context I<ctx> and property query
+I<propq> to be used to select algorithm implementations.
+
+=head1 NOTES
+
+A typical application of this function is to derive keying material for an
+encryption algorithm from a password in the I<pass>, a salt in I<salt>,
+and an iteration count.
+
+Increasing the I<iter> parameter slows down the algorithm which makes it
+harder for an attacker to perform a brute force attack using a large number
+of candidate passwords.
+
+=head1 RETURN VALUES
+
+Returns 1 on success or 0 on error.
+
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
+=head1 SEE ALSO
+
+L<PKCS12_create_ex(3)>,
+L<PKCS12_pbe_crypt_ex(3)>,
+L<passphrase-encoding(7)>
+
+=head1 HISTORY
+
+PKCS12_key_gen_asc_ex(), PKCS12_key_gen_uni_ex() and PKCS12_key_gen_utf8_ex()
+were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_newpass.pod b/doc/man3/PKCS12_newpass.pod
index 5fc041bfbdce..52d349e76c84 100644
--- a/doc/man3/PKCS12_newpass.pod
+++ b/doc/man3/PKCS12_newpass.pod
@@ -17,8 +17,6 @@ PKCS12_newpass() changes the password of a PKCS12 structure.
B<p12> is a pointer to a PKCS12 structure. B<oldpass> is the existing password
and B<newpass> is the new password.
-=head1 NOTES
-
Each of B<oldpass> and B<newpass> is independently interpreted as a string in
the UTF-8 encoding. If it is not valid UTF-8, it is assumed to be ISO8859-1
instead.
@@ -29,6 +27,15 @@ use. This may include passwords from local text files, or input from
the terminal or command line. Refer to the documentation of
L<UI_OpenSSL(3)>, for example.
+If the PKCS#12 structure does not have a password, then you must use the empty
+string "" for B<oldpass>. Using NULL for B<oldpass> will result in a
+PKCS12_newpass() failure.
+
+If the wrong password is used for B<oldpass> then the function will fail,
+with a MAC verification error. In rare cases the PKCS12 structure does not
+contain a MAC: in this case it will usually fail with a decryption padding
+error.
+
=head1 RETURN VALUES
PKCS12_newpass() returns 1 on success or 0 on failure. Applications can
@@ -83,17 +90,6 @@ the result to a new file.
}
-=head1 NOTES
-
-If the PKCS#12 structure does not have a password, then you must use the empty
-string "" for B<oldpass>. Using NULL for B<oldpass> will result in a
-PKCS12_newpass() failure.
-
-If the wrong password is used for B<oldpass> then the function will fail,
-with a MAC verification error. In rare cases the PKCS12 structure does not
-contain a MAC: in this case it will usually fail with a decryption padding
-error.
-
=head1 BUGS
The password format is a NULL terminated ASCII string which is converted to
@@ -107,9 +103,9 @@ L<passphrase-encoding(7)>
=head1 COPYRIGHT
-Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/PKCS12_pack_p7encdata.pod b/doc/man3/PKCS12_pack_p7encdata.pod
new file mode 100644
index 000000000000..36a1d5d12d90
--- /dev/null
+++ b/doc/man3/PKCS12_pack_p7encdata.pod
@@ -0,0 +1,59 @@
+=pod
+
+=head1 NAME
+
+PKCS12_pack_p7encdata, PKCS12_pack_p7encdata_ex - Pack a set of PKCS#12 safeBags
+into a PKCS#7 encrypted data object
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen,
+ unsigned char *salt, int saltlen, int iter,
+ STACK_OF(PKCS12_SAFEBAG) *bags);
+ PKCS7 *PKCS12_pack_p7encdata_ex(int pbe_nid, const char *pass, int passlen,
+ unsigned char *salt, int saltlen, int iter,
+ STACK_OF(PKCS12_SAFEBAG) *bags,
+ OSSL_LIB_CTX *ctx, const char *propq);
+
+=head1 DESCRIPTION
+
+PKCS12_pack_p7encdata() generates a PKCS#7 ContentInfo object of encrypted-data
+type from the set of safeBags I<bags>. The algorithm ID in I<pbe_nid> can be
+a PKCS#12 or PKCS#5 password based encryption algorithm, or a cipher algorithm.
+If a cipher algorithm is passed, the PKCS#5 PBES2 algorithm will be used with
+this cipher as a parameter.
+The password I<pass> of length I<passlen>, salt I<salt> of length I<saltlen>
+and iteration count I<iter> are inputs into the encryption operation.
+
+PKCS12_pack_p7encdata_ex() operates similar to the above but allows for a
+library context I<ctx> and property query I<propq> to be used to select the
+algorithm implementation.
+
+=head1 RETURN VALUES
+
+A B<PKCS7> object if successful, or NULL if an error occurred.
+
+=head1 CONFORMING TO
+
+IETF RFC 2315 (L<https://tools.ietf.org/html/rfc2315>)
+
+=head1 SEE ALSO
+
+L<PKCS12_pbe_crypt_ex(3)>
+
+=head1 HISTORY
+
+PKCS12_pack_p7encdata_ex() was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS12_parse.pod b/doc/man3/PKCS12_parse.pod
index 208644c019bf..f16600147b3f 100644
--- a/doc/man3/PKCS12_parse.pod
+++ b/doc/man3/PKCS12_parse.pod
@@ -21,10 +21,14 @@ certificate to B<*cert> and any additional certificates to B<*ca>.
=head1 NOTES
-The parameters B<pkey> and B<cert> cannot be B<NULL>. B<ca> can be <NULL> in
-which case additional certificates will be discarded. B<*ca> can also be a
-valid STACK in which case additional certificates are appended to B<*ca>. If
-B<*ca> is B<NULL> a new STACK will be allocated.
+Each of the parameters B<pkey>, B<cert>, and B<ca> can be NULL in which case
+the private key, the corresponding certificate, or the additional certificates,
+respectively, will be discarded.
+If any of B<pkey> and B<cert> is non-NULL the variable it points to is
+initialized.
+If B<ca> is non-NULL and B<*ca> is NULL a new STACK will be allocated.
+If B<ca> is non-NULL and B<*ca> is a valid STACK
+then additional certificates are appended in the given order to B<*ca>.
The B<friendlyName> and B<localKeyID> attributes (if present) on each
certificate will be stored in the B<alias> and B<keyid> attributes of the
@@ -63,9 +67,9 @@ L<passphrase-encoding(7)>
=head1 COPYRIGHT
-Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/PKCS5_PBE_keyivgen.pod b/doc/man3/PKCS5_PBE_keyivgen.pod
new file mode 100644
index 000000000000..72de3153b97d
--- /dev/null
+++ b/doc/man3/PKCS5_PBE_keyivgen.pod
@@ -0,0 +1,177 @@
+=pod
+
+=head1 NAME
+
+PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex, PKCS5_pbe2_set, PKCS5_pbe2_set_iv,
+PKCS5_pbe2_set_iv_ex, PKCS5_pbe_set, PKCS5_pbe_set_ex, PKCS5_pbe2_set_scrypt,
+PKCS5_pbe_set0_algor, PKCS5_pbe_set0_algor_ex,
+PKCS5_v2_PBE_keyivgen, PKCS5_v2_PBE_keyivgen_ex,
+PKCS5_v2_scrypt_keyivgen, PKCS5_v2_scrypt_keyivgen_ex,
+PKCS5_pbkdf2_set, PKCS5_pbkdf2_set_ex, EVP_PBE_scrypt, EVP_PBE_scrypt_ex
+- PKCS#5 Password based encryption routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md, int en_de);
+ int PKCS5_PBE_keyivgen_ex(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md, int en_de, OSSL_LIB_CTX *libctx,
+ const char *propq);
+ int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md, int en_de);
+ int PKCS5_v2_PBE_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md, int en_de,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ int EVP_PBE_scrypt(const char *pass, size_t passlen,
+ const unsigned char *salt, size_t saltlen,
+ uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
+ unsigned char *key, size_t keylen);
+ int EVP_PBE_scrypt_ex(const char *pass, size_t passlen,
+ const unsigned char *salt, size_t saltlen,
+ uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
+ unsigned char *key, size_t keylen,
+ OSSL_LIB_CTX *ctx, const char *propq);
+ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
+ int passlen, ASN1_TYPE *param,
+ const EVP_CIPHER *c, const EVP_MD *md, int en_de);
+ int PKCS5_v2_scrypt_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass,
+ int passlen, ASN1_TYPE *param,
+ const EVP_CIPHER *c, const EVP_MD *md, int en_de,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+ #include <openssl/x509.h>
+
+ int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
+ const unsigned char *salt, int saltlen);
+ int PKCS5_pbe_set0_algor_ex(X509_ALGOR *algor, int alg, int iter,
+ const unsigned char *salt, int saltlen,
+ OSSL_LIB_CTX *libctx);
+
+ X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
+ const unsigned char *salt, int saltlen);
+ X509_ALGOR *PKCS5_pbe_set_ex(int alg, int iter,
+ const unsigned char *salt, int saltlen,
+ OSSL_LIB_CTX *libctx);
+
+ X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
+ unsigned char *salt, int saltlen);
+ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
+ unsigned char *salt, int saltlen,
+ unsigned char *aiv, int prf_nid);
+ X509_ALGOR *PKCS5_pbe2_set_iv_ex(const EVP_CIPHER *cipher, int iter,
+ unsigned char *salt, int saltlen,
+ unsigned char *aiv, int prf_nid,
+ OSSL_LIB_CTX *libctx);
+ X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
+ const unsigned char *salt, int saltlen,
+ unsigned char *aiv, uint64_t N, uint64_t r,
+ uint64_t p);
+
+ X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
+ int prf_nid, int keylen);
+ X509_ALGOR *PKCS5_pbkdf2_set_ex(int iter, unsigned char *salt, int saltlen,
+ int prf_nid, int keylen,
+ OSSL_LIB_CTX *libctx);
+
+=head1 DESCRIPTION
+
+=head2 Key Derivation
+
+PKCS5_PBE_keyivgen() and PKCS5_PBE_keyivgen_ex() take a password I<pass> of
+length I<passlen>, parameters I<param> and a message digest function I<md_type>
+and performs a key derivation according to PKCS#5 PBES1. The resulting key is
+then used to initialise the cipher context I<ctx> with a cipher I<cipher> for
+encryption (I<en_de>=1) or decryption (I<en_de>=0).
+
+I<pass> is an optional parameter and can be NULL. If I<passlen> is -1, then the
+function will calculate the length of I<pass> using strlen().
+
+PKCS5_v2_PBE_keyivgen() and PKCS5_v2_PBE_keyivgen_ex() are similar to the above
+but instead use PKCS#5 PBES2 as the encryption algorithm using the supplied
+parameters.
+
+PKCS5_v2_scrypt_keyivgen() and PKCS5_v2_scrypt_keyivgen_ex() use SCRYPT as the
+key derivation part of the encryption algorithm.
+
+I<salt> is the salt used in the derivation of length I<saltlen>. If the
+I<salt> is NULL, then I<saltlen> must be 0. The function will not
+attempt to calculate the length of the I<salt> because it is not assumed to
+be NULL terminated.
+
+I<iter> is the iteration count and its value should be greater than or
+equal to 1. RFC 2898 suggests an iteration count of at least 1000. Any
+I<iter> less than 1 is treated as a single iteration.
+
+I<digest> is the message digest function used in the derivation.
+
+Functions ending in _ex() take optional parameters I<libctx> and I<propq> which
+are used to select appropriate algorithm implementations.
+
+=head2 Algorithm Identifier Creation
+
+PKCS5_pbe_set(), PKCS5_pbe_set_ex(), PKCS5_pbe2_set(), PKCS5_pbe2_set_iv(),
+PKCS5_pbe2_set_iv_ex() and PKCS5_pbe2_set_scrypt() generate an B<X509_ALGOR>
+object which represents an AlgorithmIdentifier containing the algorithm OID and
+associated parameters for the PBE algorithm.
+
+PKCS5_pbkdf2_set() and PKCS5_pbkdf2_set_ex() generate an B<X509_ALGOR>
+object which represents an AlgorithmIdentifier containing the algorithm OID and
+associated parameters for the PBKDF2 algorithm.
+
+PKCS5_pbe_set0_algor() and PKCS5_pbe_set0_algor_ex() set the PBE algorithm OID and
+parameters into the supplied B<X509_ALGOR>.
+
+=head1 NOTES
+
+The *_keyivgen() functions are typically used in PKCS#12 to encrypt objects.
+
+These functions make no assumption regarding the given password.
+It will simply be treated as a byte sequence.
+
+=head1 RETURN VALUES
+
+PKCS5_PBE_keyivgen(), PKCS5_v2_PBE_keyivgen(),
+PKCS5_v2_PBE_keyivgen_ex(), PKCS5_v2_scrypt_keyivgen(),
+PKCS5_v2_scrypt_keyivgen_ex(), PKCS5_pbe_set0_algor() and
+PKCS5_pbe_set0_algor_ex() return 1 for success and 0 if an error occurs.
+
+PKCS5_pbe_set(), PKCS5_pbe_set_ex(), PKCS5_pbe2_set(), PKCS5_pbe2_set_iv(),
+PKCS5_pbe2_set_iv_ex(), PKCS5_pbe2_set_scrypt(),
+PKCS5_pbkdf2_set() and PKCS5_pbkdf2_set_ex() return an B<X509_ALGOR> object or
+NULL if an error occurs.
+
+=head1 CONFORMING TO
+
+IETF RFC 8018 (L<https://tools.ietf.org/html/rfc8018>)
+
+=head1 SEE ALSO
+
+L<EVP_PBE_CipherInit_ex(3)>,
+L<PKCS12_pbe_crypt_ex(3)>,
+L<passphrase-encoding(7)>
+
+=head1 HISTORY
+
+PKCS5_v2_PBE_keyivgen_ex(), EVP_PBE_scrypt_ex(), PKCS5_v2_scrypt_keyivgen_ex(),
+PKCS5_pbe_set0_algor_ex(), PKCS5_pbe_set_ex(), PKCS5_pbe2_set_iv_ex() and
+PKCS5_pbkdf2_set_ex() were added in OpenSSL 3.0.
+
+From OpenSSL 3.0 the PBKDF1 algorithm used in PKCS5_PBE_keyivgen() and
+PKCS5_PBE_keyivgen_ex() has been moved to the legacy provider as an EVP_KDF.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS5_PBKDF2_HMAC.pod b/doc/man3/PKCS5_PBKDF2_HMAC.pod
index 455bf4b4649e..0984e993daef 100644
--- a/doc/man3/PKCS5_PBKDF2_HMAC.pod
+++ b/doc/man3/PKCS5_PBKDF2_HMAC.pod
@@ -35,9 +35,8 @@ B<iter> is the iteration count and its value should be greater than or
equal to 1. RFC 2898 suggests an iteration count of at least 1000. Any
B<iter> less than 1 is treated as a single iteration.
-B<digest> is the message digest function used in the derivation. Values include
-any of the EVP_* message digests. PKCS5_PBKDF2_HMAC_SHA1() calls
-PKCS5_PBKDF2_HMAC() with EVP_sha1().
+B<digest> is the message digest function used in the derivation.
+PKCS5_PBKDF2_HMAC_SHA1() calls PKCS5_PBKDF2_HMAC() with EVP_sha1().
The derived key will be written to B<out>. The size of the B<out> buffer
is specified via B<keylen>.
@@ -67,9 +66,9 @@ L<passphrase-encoding(7)>
=head1 COPYRIGHT
-Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/PKCS7_decrypt.pod b/doc/man3/PKCS7_decrypt.pod
index 4ed8aa77fa4e..aea15937ab86 100644
--- a/doc/man3/PKCS7_decrypt.pod
+++ b/doc/man3/PKCS7_decrypt.pod
@@ -49,7 +49,7 @@ L<ERR_get_error(3)>, L<PKCS7_encrypt(3)>
Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/PKCS7_encrypt.pod b/doc/man3/PKCS7_encrypt.pod
index 9895a1f73b60..79c769a77696 100644
--- a/doc/man3/PKCS7_encrypt.pod
+++ b/doc/man3/PKCS7_encrypt.pod
@@ -2,22 +2,26 @@
=head1 NAME
-PKCS7_encrypt - create a PKCS#7 envelopedData structure
+PKCS7_encrypt_ex, PKCS7_encrypt
+- create a PKCS#7 envelopedData structure
=head1 SYNOPSIS
#include <openssl/pkcs7.h>
+ PKCS7 *PKCS7_encrypt_ex(STACK_OF(X509) *certs, BIO *in,
+ const EVP_CIPHER *cipher, int flags,
+ OSSL_LIB_CTX *libctx, const char *propq);
PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
int flags);
=head1 DESCRIPTION
-PKCS7_encrypt() creates and returns a PKCS#7 envelopedData structure. B<certs>
-is a list of recipient certificates. B<in> is the content to be encrypted.
-B<cipher> is the symmetric cipher to use. B<flags> is an optional set of flags.
-
-=head1 NOTES
+PKCS7_encrypt_ex() creates and returns a PKCS#7 envelopedData structure.
+I<certs> is a list of recipient certificates. I<in> is the content to be
+encrypted. I<cipher> is the symmetric cipher to use. I<flags> is an optional set
+of flags. The library context I<libctx> and the property query I<propq> are used
+when retrieving algorithms from providers.
Only RSA keys are supported in PKCS#7 and envelopedData so the recipient
certificates supplied to this function must all contain RSA public keys, though
@@ -52,8 +56,6 @@ B<PKCS7_TEXT> is ignored.
If the B<PKCS7_STREAM> flag is set a partial B<PKCS7> structure is output
suitable for streaming I/O: no data is read from the BIO B<in>.
-=head1 NOTES
-
If the flag B<PKCS7_STREAM> is set the returned B<PKCS7> structure is B<not>
complete and outputting its contents via a function that does not
properly finalize the B<PKCS7> structure will give unpredictable
@@ -64,10 +66,13 @@ PEM_write_bio_PKCS7_stream() finalize the structure. Alternatively finalization
can be performed by obtaining the streaming ASN1 B<BIO> directly using
BIO_new_PKCS7().
+PKCS7_encrypt() is similar to PKCS7_encrypt_ex() but uses default
+values of NULL for the library context I<libctx> and the property query I<propq>.
+
=head1 RETURN VALUES
-PKCS7_encrypt() returns either a PKCS7 structure or NULL if an error occurred.
-The error can be obtained from ERR_get_error(3).
+PKCS7_encrypt_ex() and PKCS7_encrypt() return either a PKCS7 structure
+or NULL if an error occurred. The error can be obtained from ERR_get_error(3).
=head1 SEE ALSO
@@ -75,13 +80,15 @@ L<ERR_get_error(3)>, L<PKCS7_decrypt(3)>
=head1 HISTORY
+The function PKCS7_encrypt_ex() was added in OpenSSL 3.0.
+
The B<PKCS7_STREAM> flag was added in OpenSSL 1.0.0.
=head1 COPYRIGHT
-Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/PKCS7_get_octet_string.pod b/doc/man3/PKCS7_get_octet_string.pod
new file mode 100644
index 000000000000..7e7c3e0f1fbb
--- /dev/null
+++ b/doc/man3/PKCS7_get_octet_string.pod
@@ -0,0 +1,40 @@
+=pod
+
+=head1 NAME
+
+PKCS7_get_octet_string - return octet string from a PKCS#7 envelopedData structure
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs7.h>
+
+ ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7);
+
+=head1 DESCRIPTION
+
+PKCS7_get_octet_string() returns a pointer to an ASN1 octet string from a
+PKCS#7 envelopedData structure or B<NULL> if the structure cannot be parsed.
+
+=head1 NOTES
+
+As the B<0> implies, PKCS7_get_octet_string() returns internal pointers which
+should not be freed by the caller.
+
+=head1 RETURN VALUES
+
+PKCS7_get_octet_string() returns an ASN1_OCTET_STRING pointer.
+
+=head1 SEE ALSO
+
+L<PKCS7_type_is_data(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS7_sign.pod b/doc/man3/PKCS7_sign.pod
index 11b626191038..c0a07090759b 100644
--- a/doc/man3/PKCS7_sign.pod
+++ b/doc/man3/PKCS7_sign.pod
@@ -2,27 +2,34 @@
=head1 NAME
-PKCS7_sign - create a PKCS#7 signedData structure
+PKCS7_sign_ex, PKCS7_sign
+- create a PKCS#7 signedData structure
=head1 SYNOPSIS
#include <openssl/pkcs7.h>
+ PKCS7 *PKCS7_sign_ex(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+ BIO *data, int flags, OSSL_LIB_CTX *libctx,
+ const char *propq);
PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
BIO *data, int flags);
=head1 DESCRIPTION
-PKCS7_sign() creates and returns a PKCS#7 signedData structure.
+PKCS7_sign_ex() creates and returns a PKCS#7 signedData structure.
I<signcert> is the certificate to sign with, I<pkey> is the corresponding
private key. I<certs> is an optional set of extra certificates to include
in the PKCS#7 structure (for example any intermediate CAs in the chain).
+The library context I<libctx> and property query I<propq> are used when
+retrieving algorithms from providers.
The data to be signed is read from BIO I<data>.
I<flags> is an optional set of flags.
Any of the following flags (ored together) can be passed in the I<flags>
+parameter.
Many S/MIME clients expect the signed content to include valid MIME headers. If
the B<PKCS7_TEXT> flag is set MIME headers for type C<text/plain> are prepended
@@ -63,8 +70,6 @@ way data can be signed in a single pass.
If the B<PKCS7_PARTIAL> flag is set a partial B<PKCS7> structure is output to
which additional signers and capabilities can be added before finalization.
-=head1 NOTES
-
If the flag B<PKCS7_STREAM> is set the returned B<PKCS7> structure is B<not>
complete and outputting its contents via a function that does not properly
finalize the B<PKCS7> structure will give unpredictable results.
@@ -89,14 +94,18 @@ PKCS#7 structure is output.
In versions of OpenSSL before 1.0.0 the I<signcert> and I<pkey> parameters must
not be NULL.
+PKCS7_sign() is like PKCS7_sign_ex() except that it uses default values of
+NULL for the library context I<libctx> and the property query I<propq>.
+This is retained for API backward compatibiliy.
+
=head1 BUGS
Some advanced attributes such as counter signatures are not supported.
=head1 RETURN VALUES
-PKCS7_sign() returns either a valid PKCS7 structure or NULL if an error
-occurred. The error can be obtained from ERR_get_error(3).
+PKCS7_sign_ex() and PKCS7_sign() return either a valid PKCS7 structure
+or NULL if an error occurred. The error can be obtained from ERR_get_error(3).
=head1 SEE ALSO
@@ -104,6 +113,8 @@ L<ERR_get_error(3)>, L<PKCS7_verify(3)>
=head1 HISTORY
+The function PKCS7_sign_ex() was added in OpenSSL 3.0.
+
The B<PKCS7_PARTIAL> flag, and the ability for I<certs>, I<signcert>,
and I<pkey> parameters to be NULL were added in OpenSSL 1.0.0.
@@ -113,7 +124,7 @@ The B<PKCS7_STREAM> flag was added in OpenSSL 1.0.0.
Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/PKCS7_sign_add_signer.pod b/doc/man3/PKCS7_sign_add_signer.pod
index 0bbd6d8dca7c..d1271fe7f424 100644
--- a/doc/man3/PKCS7_sign_add_signer.pod
+++ b/doc/man3/PKCS7_sign_add_signer.pod
@@ -102,7 +102,7 @@ The PPKCS7_sign_add_signer() function was added in OpenSSL 1.0.0.
Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/PKCS7_type_is_other.pod b/doc/man3/PKCS7_type_is_other.pod
new file mode 100644
index 000000000000..9ce8d5a11e1d
--- /dev/null
+++ b/doc/man3/PKCS7_type_is_other.pod
@@ -0,0 +1,42 @@
+=pod
+
+=head1 NAME
+
+PKCS7_type_is_other - determine content type of PKCS#7 envelopedData structure
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs7.h>
+
+ int PKCS7_type_is_other(PKCS7 *p7);
+
+=head1 DESCRIPTION
+
+PKCS7_type_is_other() returns the whether the content type of a PKCS#7 envelopedData
+structure is one of the following content types:
+
+NID_pkcs7_data
+NID_pkcs7_signed
+NID_pkcs7_enveloped
+NID_pkcs7_signedAndEnveloped
+NID_pkcs7_digest
+NID_pkcs7_encrypted
+
+=head1 RETURN VALUES
+
+PKCS7_type_is_other() returns either 0 if the content type is matched or 1 otherwise.
+
+=head1 SEE ALSO
+
+L<PKCS7_type_is_data(3)>, L<PKCS7_get_octet_string(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS7_verify.pod b/doc/man3/PKCS7_verify.pod
index 4418e5489c9f..2f5f75aa2897 100644
--- a/doc/man3/PKCS7_verify.pod
+++ b/doc/man3/PKCS7_verify.pod
@@ -97,7 +97,7 @@ of the certificates supplied in I<certs> then the verify will fail because the
signer cannot be found.
Care should be taken when modifying the default verify behaviour, for example
-setting B<PKCS7_NOVERIFY|PKCS7_NOSIGS> will totally disable all verification
+setting C<PKCS7_NOVERIFY|PKCS7_NOSIGS> will totally disable all verification
and any signed message will be considered valid. This combination is however
useful if one merely wishes to write the content to I<out> and its validity
is not considered important.
@@ -133,7 +133,7 @@ L<ERR_get_error(3)>, L<PKCS7_sign(3)>
Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/PKCS8_encrypt.pod b/doc/man3/PKCS8_encrypt.pod
new file mode 100644
index 000000000000..8a42b83310c1
--- /dev/null
+++ b/doc/man3/PKCS8_encrypt.pod
@@ -0,0 +1,78 @@
+=pod
+
+=head1 NAME
+
+PKCS8_decrypt, PKCS8_decrypt_ex, PKCS8_encrypt, PKCS8_encrypt_ex,
+PKCS8_set0_pbe, PKCS8_set0_pbe_ex - PKCS8 encrypt/decrypt functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509.h>
+
+ PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(const X509_SIG *p8, const char *pass,
+ int passlen);
+ PKCS8_PRIV_KEY_INFO *PKCS8_decrypt_ex(const X509_SIG *p8, const char *pass,
+ int passlen, OSSL_LIB_CTX *ctx,
+ const char *propq);
+ X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
+ const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8);
+ X509_SIG *PKCS8_encrypt_ex(int pbe_nid, const EVP_CIPHER *cipher,
+ const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8,
+ OSSL_LIB_CTX *ctx, const char *propq);
+ X509_SIG *PKCS8_set0_pbe(const char *pass, int passlen,
+ PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe);
+ X509_SIG *PKCS8_set0_pbe_ex(const char *pass, int passlen,
+ PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe,
+ OSSL_LIB_CTX *ctx);
+
+=head1 DESCRIPTION
+
+PKCS8_encrypt() and PKCS8_encrypt_ex() perform encryption of an object I<p8> using
+the password I<pass> of length I<passlen>, salt I<salt> of length I<saltlen>
+and iteration count I<iter>.
+The resulting B<X509_SIG> contains the encoded algorithm parameters and encrypted
+key.
+
+PKCS8_decrypt() and PKCS8_decrypt_ex() perform decryption of an B<X509_SIG> in
+I<p8> using the password I<pass> of length I<passlen> along with algorithm
+parameters obtained from the I<p8>.
+
+PKCS8_set0_pbe() and PKCS8_set0_pbe_ex() perform encryption of the I<p8inf>
+using the password I<pass> of length I<passlen> and parameters I<pbe>.
+
+Functions ending in _ex() allow for a library context I<ctx> and property query
+I<propq> to be used to select algorithm implementations.
+
+=head1 RETURN VALUES
+
+PKCS8_encrypt(), PKCS8_encrypt_ex(), PKCS8_set0_pbe() and PKCS8_set0_pbe_ex()
+return an encrypted key in a B<X509_SIG> structure or NULL if an error occurs.
+
+PKCS8_decrypt() and PKCS8_decrypt_ex() return a B<PKCS8_PRIV_KEY_INFO> or NULL
+if an error occurs.
+
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
+=head1 SEE ALSO
+
+L<crypto(7)>
+
+=head1 HISTORY
+
+PKCS8_decrypt_ex(), PKCS8_encrypt_ex() and PKCS8_set0_pbe_ex() were added in
+OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PKCS8_pkey_add1_attr.pod b/doc/man3/PKCS8_pkey_add1_attr.pod
new file mode 100644
index 000000000000..340b56aafe24
--- /dev/null
+++ b/doc/man3/PKCS8_pkey_add1_attr.pod
@@ -0,0 +1,54 @@
+=pod
+
+=head1 NAME
+
+PKCS8_pkey_get0_attrs, PKCS8_pkey_add1_attr, PKCS8_pkey_add1_attr_by_NID, PKCS8_pkey_add1_attr_by_OBJ - PKCS8 attribute functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509.h>
+
+ const STACK_OF(X509_ATTRIBUTE) *
+ PKCS8_pkey_get0_attrs(const PKCS8_PRIV_KEY_INFO *p8);
+ int PKCS8_pkey_add1_attr(PKCS8_PRIV_KEY_INFO *p8, X509_ATTRIBUTE *attr);
+ int PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type,
+ const unsigned char *bytes, int len);
+ int PKCS8_pkey_add1_attr_by_OBJ(PKCS8_PRIV_KEY_INFO *p8, const ASN1_OBJECT *obj,
+ int type, const unsigned char *bytes, int len);
+
+=head1 DESCRIPTION
+
+PKCS8_pkey_get0_attrs() returns a const STACK of X509_ATTRIBUTE present in
+the passed const PKCS8_PRIV_KEY_INFO structure B<p8>.
+
+PKCS8_pkey_add1_attr() adds a constructed X509_ATTRIBUTE B<attr> to the
+existing PKCS8_PRIV_KEY_INFO structure B<p8>.
+
+PKCS8_pkey_add1_attr_by_NID() and PKCS8_pkey_add1_attr_by_OBJ() construct a new
+X509_ATTRIBUTE from the passed arguments and add it to the existing
+PKCS8_PRIV_KEY_INFO structure B<p8>.
+
+=head1 RETURN VALUES
+
+PKCS8_pkey_add1_attr(), PKCS8_pkey_add1_attr_by_NID(), and
+PKCS8_pkey_add1_attr_by_OBJ() return 1 for success and 0 for failure.
+
+=head1 NOTES
+
+STACK of X509_ATTRIBUTE is present in many X509-related structures and some of
+them have the corresponding set of similar functions.
+
+=head1 SEE ALSO
+
+L<crypto(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/RAND_DRBG_generate.pod b/doc/man3/RAND_DRBG_generate.pod
deleted file mode 100644
index bee2d6c176ef..000000000000
--- a/doc/man3/RAND_DRBG_generate.pod
+++ /dev/null
@@ -1,88 +0,0 @@
-=pod
-
-=head1 NAME
-
-RAND_DRBG_generate,
-RAND_DRBG_bytes
-- generate random bytes using the given drbg instance
-
-=head1 SYNOPSIS
-
- #include <openssl/rand_drbg.h>
-
- int RAND_DRBG_generate(RAND_DRBG *drbg,
- unsigned char *out, size_t outlen,
- int prediction_resistance,
- const unsigned char *adin, size_t adinlen);
-
- int RAND_DRBG_bytes(RAND_DRBG *drbg,
- unsigned char *out, size_t outlen);
-
-
-=head1 DESCRIPTION
-
-RAND_DRBG_generate() generates B<outlen> random bytes using the given
-DRBG instance B<drbg> and stores them in the buffer at B<out>.
-
-Before generating the output, the DRBG instance checks whether the maximum
-number of generate requests (I<reseed interval>) or the maximum timespan
-(I<reseed time interval>) since its last seeding have been reached.
-If this is the case, the DRBG reseeds automatically.
-Additionally, an immediate reseeding can be requested by setting the
-B<prediction_resistance> flag to 1. See NOTES section for more details.
-
-The caller can optionally provide additional data to be used for reseeding
-by passing a pointer B<adin> to a buffer of length B<adinlen>.
-This additional data is mixed into the internal state of the random
-generator but does not contribute to the entropy count.
-The additional data can be omitted by setting B<adin> to NULL and
-B<adinlen> to 0;
-
-RAND_DRBG_bytes() generates B<outlen> random bytes using the given
-DRBG instance B<drbg> and stores them in the buffer at B<out>.
-This function is a wrapper around the RAND_DRBG_generate() call,
-which collects some additional data from low entropy sources
-(e.g., a high resolution timer) and calls
-RAND_DRBG_generate(drbg, out, outlen, 0, adin, adinlen).
-
-
-=head1 RETURN VALUES
-
-RAND_DRBG_generate() and RAND_DRBG_bytes() return 1 on success,
-and 0 on failure.
-
-=head1 NOTES
-
-The I<reseed interval> and I<reseed time interval> of the B<drbg> are set to
-reasonable default values, which in general do not have to be adjusted.
-If necessary, they can be changed using L<RAND_DRBG_set_reseed_interval(3)>
-and L<RAND_DRBG_set_reseed_time_interval(3)>, respectively.
-
-A request for prediction resistance can only be satisfied by pulling fresh
-entropy from one of the approved entropy sources listed in section 5.5.2 of
-[NIST SP 800-90C].
-Since the default DRBG implementation does not have access to such an approved
-entropy source, a request for prediction resistance will always fail.
-In other words, prediction resistance is currently not supported yet by the DRBG.
-
-=head1 SEE ALSO
-
-L<RAND_bytes(3)>,
-L<RAND_DRBG_set_reseed_interval(3)>,
-L<RAND_DRBG_set_reseed_time_interval(3)>,
-L<RAND_DRBG(7)>
-
-=head1 HISTORY
-
-The RAND_DRBG functions were added in OpenSSL 1.1.1.
-
-=head1 COPYRIGHT
-
-Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man3/RAND_DRBG_get0_master.pod b/doc/man3/RAND_DRBG_get0_master.pod
deleted file mode 100644
index 55d1eab7c21f..000000000000
--- a/doc/man3/RAND_DRBG_get0_master.pod
+++ /dev/null
@@ -1,79 +0,0 @@
-=pod
-
-=head1 NAME
-
-RAND_DRBG_get0_master,
-RAND_DRBG_get0_public,
-RAND_DRBG_get0_private
-- get access to the global RAND_DRBG instances
-
-=head1 SYNOPSIS
-
- #include <openssl/rand_drbg.h>
-
- RAND_DRBG *RAND_DRBG_get0_master(void);
- RAND_DRBG *RAND_DRBG_get0_public(void);
- RAND_DRBG *RAND_DRBG_get0_private(void);
-
-
-=head1 DESCRIPTION
-
-The default RAND API implementation (RAND_OpenSSL()) utilizes three
-shared DRBG instances which are accessed via the RAND API:
-
-The <public> and <private> DRBG are thread-local instances, which are used
-by RAND_bytes() and RAND_priv_bytes(), respectively.
-The <master> DRBG is a global instance, which is not intended to be used
-directly, but is used internally to reseed the other two instances.
-
-These functions here provide access to the shared DRBG instances.
-
-=head1 RETURN VALUES
-
-RAND_DRBG_get0_master() returns a pointer to the <master> DRBG instance.
-
-RAND_DRBG_get0_public() returns a pointer to the <public> DRBG instance.
-
-RAND_DRBG_get0_private() returns a pointer to the <private> DRBG instance.
-
-
-=head1 NOTES
-
-It is not thread-safe to access the <master> DRBG instance.
-The <public> and <private> DRBG instance can be accessed safely, because
-they are thread-local. Note however, that changes to these two instances
-apply only to the current thread.
-
-For that reason it is recommended not to change the settings of these
-three instances directly.
-Instead, an application should change the default settings for new DRBG instances
-at initialization time, before creating additional threads.
-
-During initialization, it is possible to change the reseed interval
-and reseed time interval.
-It is also possible to exchange the reseeding callbacks entirely.
-
-=head1 SEE ALSO
-
-L<RAND_DRBG_set_callbacks(3)>,
-L<RAND_DRBG_set_reseed_defaults(3)>,
-L<RAND_DRBG_set_reseed_interval(3)>,
-L<RAND_DRBG_set_reseed_time_interval(3)>,
-L<RAND_DRBG_set_callbacks(3)>,
-L<RAND_DRBG_generate(3)>,
-L<RAND_DRBG(7)>
-
-=head1 HISTORY
-
-The RAND_DRBG functions were added in OpenSSL 1.1.1.
-
-=head1 COPYRIGHT
-
-Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man3/RAND_DRBG_new.pod b/doc/man3/RAND_DRBG_new.pod
deleted file mode 100644
index ca52e2f3ddfc..000000000000
--- a/doc/man3/RAND_DRBG_new.pod
+++ /dev/null
@@ -1,127 +0,0 @@
-=pod
-
-=head1 NAME
-
-RAND_DRBG_new,
-RAND_DRBG_secure_new,
-RAND_DRBG_set,
-RAND_DRBG_set_defaults,
-RAND_DRBG_instantiate,
-RAND_DRBG_uninstantiate,
-RAND_DRBG_free
-- initialize and cleanup a RAND_DRBG instance
-
-=head1 SYNOPSIS
-
- #include <openssl/rand_drbg.h>
-
-
- RAND_DRBG *RAND_DRBG_new(int type,
- unsigned int flags,
- RAND_DRBG *parent);
-
- RAND_DRBG *RAND_DRBG_secure_new(int type,
- unsigned int flags,
- RAND_DRBG *parent);
-
- int RAND_DRBG_set(RAND_DRBG *drbg,
- int type, unsigned int flags);
-
- int RAND_DRBG_set_defaults(int type, unsigned int flags);
-
- int RAND_DRBG_instantiate(RAND_DRBG *drbg,
- const unsigned char *pers, size_t perslen);
-
- int RAND_DRBG_uninstantiate(RAND_DRBG *drbg);
-
- void RAND_DRBG_free(RAND_DRBG *drbg);
-
-
-=head1 DESCRIPTION
-
-RAND_DRBG_new() and RAND_DRBG_secure_new()
-create a new DRBG instance of the given B<type>, allocated from the heap resp.
-the secure heap
-(using OPENSSL_zalloc() resp. OPENSSL_secure_zalloc()).
-
-RAND_DRBG_set() initializes the B<drbg> with the given B<type> and B<flags>.
-
-RAND_DRBG_set_defaults() sets the default B<type> and B<flags> for new DRBG
-instances.
-
-Currently, all DRBG types are based on AES-CTR, so B<type> can be one of the
-following values: NID_aes_128_ctr, NID_aes_192_ctr, NID_aes_256_ctr.
-Before the DRBG can be used to generate random bits, it is necessary to set
-its type and to instantiate it.
-
-The optional B<flags> argument specifies a set of bit flags which can be
-joined using the | operator. Currently, the only flag is
-RAND_DRBG_FLAG_CTR_NO_DF, which disables the use of the derivation function
-ctr_df. For an explanation, see [NIST SP 800-90A Rev. 1].
-
-If a B<parent> instance is specified then this will be used instead of
-the default entropy source for reseeding the B<drbg>. It is said that the
-B<drbg> is I<chained> to its B<parent>.
-For more information, see the NOTES section.
-
-
-RAND_DRBG_instantiate()
-seeds the B<drbg> instance using random input from trusted entropy sources.
-Optionally, a personalization string B<pers> of length B<perslen> can be
-specified.
-To omit the personalization string, set B<pers>=NULL and B<perslen>=0;
-
-RAND_DRBG_uninstantiate()
-clears the internal state of the B<drbg> and puts it back in the
-uninstantiated state.
-
-=head1 RETURN VALUES
-
-
-RAND_DRBG_new() and RAND_DRBG_secure_new() return a pointer to a DRBG
-instance allocated on the heap, resp. secure heap.
-
-RAND_DRBG_set(),
-RAND_DRBG_instantiate(), and
-RAND_DRBG_uninstantiate()
-return 1 on success, and 0 on failure.
-
-RAND_DRBG_free() does not return a value.
-
-=head1 NOTES
-
-The DRBG design supports I<chaining>, which means that a DRBG instance can
-use another B<parent> DRBG instance instead of the default entropy source
-to obtain fresh random input for reseeding, provided that B<parent> DRBG
-instance was properly instantiated, either from a trusted entropy source,
-or from yet another parent DRBG instance.
-For a detailed description of the reseeding process, see L<RAND_DRBG(7)>.
-
-The default DRBG type and flags are applied only during creation of a DRBG
-instance.
-To ensure that they are applied to the global and thread-local DRBG instances
-(<master>, resp. <public> and <private>), it is necessary to call
-RAND_DRBG_set_defaults() before creating any thread and before calling any
-cryptographic routines that obtain random data directly or indirectly.
-
-=head1 SEE ALSO
-
-L<OPENSSL_zalloc(3)>,
-L<OPENSSL_secure_zalloc(3)>,
-L<RAND_DRBG_generate(3)>,
-L<RAND_DRBG(7)>
-
-=head1 HISTORY
-
-The RAND_DRBG functions were added in OpenSSL 1.1.1.
-
-=head1 COPYRIGHT
-
-Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man3/RAND_DRBG_reseed.pod b/doc/man3/RAND_DRBG_reseed.pod
deleted file mode 100644
index 3610c1301e09..000000000000
--- a/doc/man3/RAND_DRBG_reseed.pod
+++ /dev/null
@@ -1,116 +0,0 @@
-=pod
-
-=head1 NAME
-
-RAND_DRBG_reseed,
-RAND_DRBG_set_reseed_interval,
-RAND_DRBG_set_reseed_time_interval,
-RAND_DRBG_set_reseed_defaults
-- reseed a RAND_DRBG instance
-
-=head1 SYNOPSIS
-
- #include <openssl/rand_drbg.h>
-
- int RAND_DRBG_reseed(RAND_DRBG *drbg,
- const unsigned char *adin, size_t adinlen,
- int prediction_resistance);
-
- int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg,
- unsigned int interval);
-
- int RAND_DRBG_set_reseed_time_interval(RAND_DRBG *drbg,
- time_t interval);
-
- int RAND_DRBG_set_reseed_defaults(
- unsigned int master_reseed_interval,
- unsigned int slave_reseed_interval,
- time_t master_reseed_time_interval,
- time_t slave_reseed_time_interval
- );
-
-
-=head1 DESCRIPTION
-
-RAND_DRBG_reseed()
-reseeds the given B<drbg>, obtaining entropy input from its entropy source
-and mixing in the specified additional data provided in the buffer B<adin>
-of length B<adinlen>.
-The additional data can be omitted by setting B<adin> to NULL and B<adinlen>
-to 0.
-An immediate reseeding from a live entropy source can be requested by setting
-the B<prediction_resistance> flag to 1.
-This feature is not implemented yet, so reseeding with prediction resistance
-requested will always fail.
-
-RAND_DRBG_set_reseed_interval()
-sets the reseed interval of the B<drbg>, which is the maximum allowed number
-of generate requests between consecutive reseedings.
-If B<interval> > 0, then the B<drbg> will reseed automatically whenever the
-number of generate requests since its last seeding exceeds the given reseed
-interval.
-If B<interval> == 0, then this feature is disabled.
-
-
-RAND_DRBG_set_reseed_time_interval()
-sets the reseed time interval of the B<drbg>, which is the maximum allowed
-number of seconds between consecutive reseedings.
-If B<interval> > 0, then the B<drbg> will reseed automatically whenever the
-elapsed time since its last reseeding exceeds the given reseed time interval.
-If B<interval> == 0, then this feature is disabled.
-
-RAND_DRBG_set_reseed_defaults() sets the default values for the reseed interval
-(B<master_reseed_interval> and B<slave_reseed_interval>)
-and the reseed time interval
-(B<master_reseed_time_interval> and B<slave_reseed_tme_interval>)
-of DRBG instances.
-The default values are set independently for master DRBG instances (which don't
-have a parent) and slave DRBG instances (which are chained to a parent DRBG).
-
-=head1 RETURN VALUES
-
-RAND_DRBG_reseed(),
-RAND_DRBG_set_reseed_interval(), and
-RAND_DRBG_set_reseed_time_interval(),
-return 1 on success, 0 on failure.
-
-
-=head1 NOTES
-
-The default OpenSSL random generator is already set up for automatic reseeding,
-so in general it is not necessary to reseed it explicitly, or to modify
-its reseeding thresholds.
-
-Normally, the entropy input for seeding a DRBG is either obtained from a
-trusted os entropy source or from a parent DRBG instance, which was seeded
-(directly or indirectly) from a trusted os entropy source.
-In exceptional cases it is possible to replace the reseeding mechanism entirely
-by providing application defined callbacks using RAND_DRBG_set_callbacks().
-
-The reseeding default values are applied only during creation of a DRBG instance.
-To ensure that they are applied to the global and thread-local DRBG instances
-(<master>, resp. <public> and <private>), it is necessary to call
-RAND_DRBG_set_reseed_defaults() before creating any thread and before calling any
- cryptographic routines that obtain random data directly or indirectly.
-
-=head1 SEE ALSO
-
-L<RAND_DRBG_generate(3)>,
-L<RAND_DRBG_bytes(3)>,
-L<RAND_DRBG_set_callbacks(3)>.
-L<RAND_DRBG(7)>
-
-=head1 HISTORY
-
-The RAND_DRBG functions were added in OpenSSL 1.1.1.
-
-=head1 COPYRIGHT
-
-Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man3/RAND_DRBG_set_callbacks.pod b/doc/man3/RAND_DRBG_set_callbacks.pod
deleted file mode 100644
index 4d04645694ce..000000000000
--- a/doc/man3/RAND_DRBG_set_callbacks.pod
+++ /dev/null
@@ -1,146 +0,0 @@
-=pod
-
-=head1 NAME
-
-RAND_DRBG_set_callbacks,
-RAND_DRBG_get_entropy_fn,
-RAND_DRBG_cleanup_entropy_fn,
-RAND_DRBG_get_nonce_fn,
-RAND_DRBG_cleanup_nonce_fn
-- set callbacks for reseeding
-
-=head1 SYNOPSIS
-
- #include <openssl/rand_drbg.h>
-
-
- int RAND_DRBG_set_callbacks(RAND_DRBG *drbg,
- RAND_DRBG_get_entropy_fn get_entropy,
- RAND_DRBG_cleanup_entropy_fn cleanup_entropy,
- RAND_DRBG_get_nonce_fn get_nonce,
- RAND_DRBG_cleanup_nonce_fn cleanup_nonce);
-
-
-=head2 Callback Functions
-
- typedef size_t (*RAND_DRBG_get_entropy_fn)(
- RAND_DRBG *drbg,
- unsigned char **pout,
- int entropy,
- size_t min_len, size_t max_len,
- int prediction_resistance);
-
- typedef void (*RAND_DRBG_cleanup_entropy_fn)(
- RAND_DRBG *drbg,
- unsigned char *out, size_t outlen);
-
- typedef size_t (*RAND_DRBG_get_nonce_fn)(
- RAND_DRBG *drbg,
- unsigned char **pout,
- int entropy,
- size_t min_len, size_t max_len);
-
- typedef void (*RAND_DRBG_cleanup_nonce_fn)(
- RAND_DRBG *drbg,
- unsigned char *out, size_t outlen);
-
-
-
-=head1 DESCRIPTION
-
-RAND_DRBG_set_callbacks() sets the callbacks for obtaining fresh entropy and
-the nonce when reseeding the given B<drbg>.
-The callback functions are implemented and provided by the caller.
-Their parameter lists need to match the function prototypes above.
-
-Setting the callbacks is allowed only if the DRBG has not been initialized yet.
-Otherwise, the operation will fail.
-To change the settings for one of the three shared DRBGs it is necessary to call
-RAND_DRBG_uninstantiate() first.
-
-The B<get_entropy>() callback is called by the B<drbg> when it requests fresh
-random input.
-It is expected that the callback allocates and fills a random buffer of size
-B<min_len> <= size <= B<max_len> (in bytes) which contains at least B<entropy>
-bits of randomness.
-The B<prediction_resistance> flag indicates whether the reseeding was
-triggered by a prediction resistance request.
-
-The buffer's address is to be returned in *B<pout> and the number of collected
-randomness bytes as return value.
-
-If the callback fails to acquire at least B<entropy> bits of randomness,
-it must indicate an error by returning a buffer length of 0.
-
-If B<prediction_resistance> was requested and the random source of the DRBG
-does not satisfy the conditions requested by [NIST SP 800-90C], then
-it must also indicate an error by returning a buffer length of 0.
-See NOTES section for more details.
-
-The B<cleanup_entropy>() callback is called from the B<drbg> to clear and
-free the buffer allocated previously by get_entropy().
-The values B<out> and B<outlen> are the random buffer's address and length,
-as returned by the get_entropy() callback.
-
-The B<get_nonce>() and B<cleanup_nonce>() callbacks are used to obtain a nonce
-and free it again. A nonce is only required for instantiation (not for reseeding)
-and only in the case where the DRBG uses a derivation function.
-The callbacks are analogous to get_entropy() and cleanup_entropy(),
-except for the missing prediction_resistance flag.
-
-If the derivation function is disabled, then no nonce is used for instantiation,
-and the B<get_nonce>() and B<cleanup_nonce>() callbacks can be omitted by
-setting them to NULL.
-
-
-=head1 RETURN VALUES
-
-RAND_DRBG_set_callbacks() return 1 on success, and 0 on failure
-
-=head1 NOTES
-
-It is important that B<cleanup_entropy>() and B<cleanup_nonce>() clear the buffer
-contents safely before freeing it, in order not to leave sensitive information
-about the DRBG's state in memory.
-
-A request for prediction resistance can only be satisfied by pulling fresh
-entropy from one of the approved entropy sources listed in section 5.5.2 of
-[NIST SP 800-90C].
-Since the default implementation of the get_entropy callback does not have access
-to such an approved entropy source, a request for prediction resistance will
-always fail.
-In other words, prediction resistance is currently not supported yet by the DRBG.
-
-The derivation function is disabled during initialization by calling the
-RAND_DRBG_set() function with the RAND_DRBG_FLAG_CTR_NO_DF flag.
-For more information on the derivation function and when it can be omitted,
-see [NIST SP 800-90A Rev. 1]. Roughly speaking it can be omitted if the random
-source has "full entropy", i.e., contains 8 bits of entropy per byte.
-
-Even if a nonce is required, the B<get_nonce>() and B<cleanup_nonce>()
-callbacks can be omitted by setting them to NULL.
-In this case the DRBG will automatically request an extra amount of entropy
-(using the B<get_entropy>() and B<cleanup_entropy>() callbacks) which it will
-utilize for the nonce, following the recommendations of [NIST SP 800-90A Rev. 1],
-section 8.6.7.
-
-=head1 SEE ALSO
-
-L<RAND_DRBG_new(3)>,
-L<RAND_DRBG_reseed(3)>,
-L<RAND_DRBG(7)>
-
-=head1 HISTORY
-
-The RAND_DRBG functions were added in OpenSSL 1.1.1.
-
-=head1 COPYRIGHT
-
-Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man3/RAND_DRBG_set_ex_data.pod b/doc/man3/RAND_DRBG_set_ex_data.pod
deleted file mode 100644
index 22b7332571dd..000000000000
--- a/doc/man3/RAND_DRBG_set_ex_data.pod
+++ /dev/null
@@ -1,68 +0,0 @@
-=pod
-
-=head1 NAME
-
-RAND_DRBG_set_ex_data,
-RAND_DRBG_get_ex_data,
-RAND_DRBG_get_ex_new_index
-- store and retrieve extra data from the DRBG instance
-
-=head1 SYNOPSIS
-
- #include <openssl/rand_drbg.h>
-
- int RAND_DRBG_set_ex_data(RAND_DRBG *drbg, int idx, void *data);
-
- void *RAND_DRBG_get_ex_data(const RAND_DRBG *drbg, int idx);
-
- int RAND_DRBG_get_ex_new_index(long argl, void *argp,
- CRYPTO_EX_new *new_func,
- CRYPTO_EX_dup *dup_func,
- CRYPTO_EX_free *free_func);
-
-
-
-=head1 DESCRIPTION
-
-RAND_DRBG_set_ex_data() enables an application to store arbitrary application
-specific data B<data> in a RAND_DRBG instance B<drbg>. The index B<idx> should
-be a value previously returned from a call to RAND_DRBG_get_ex_new_index().
-
-RAND_DRBG_get_ex_data() retrieves application specific data previously stored
-in an RAND_DRBG instance B<drbg>. The B<idx> value should be the same as that
-used when originally storing the data.
-
-For more detailed information see L<CRYPTO_get_ex_data(3)> and
-L<CRYPTO_set_ex_data(3)> which implement these functions and
-L<CRYPTO_get_ex_new_index(3)> for generating a unique index.
-
-=head1 RETURN VALUES
-
-RAND_DRBG_set_ex_data() returns 1 for success or 0 for failure.
-
-RAND_DRBG_get_ex_data() returns the previously stored value or NULL on
-failure. NULL may also be a valid value.
-
-
-=head1 NOTES
-
-RAND_DRBG_get_ex_new_index(...) is implemented as a macro and equivalent to
-CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DRBG,...).
-
-=head1 SEE ALSO
-
-L<CRYPTO_get_ex_data(3)>,
-L<CRYPTO_set_ex_data(3)>,
-L<CRYPTO_get_ex_new_index(3)>,
-L<RAND_DRBG(7)>
-
-=head1 COPYRIGHT
-
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man3/RAND_add.pod b/doc/man3/RAND_add.pod
index e4454d44124e..10a68114330a 100644
--- a/doc/man3/RAND_add.pod
+++ b/doc/man3/RAND_add.pod
@@ -18,12 +18,12 @@ RAND_keep_random_devices_open
void RAND_keep_random_devices_open(int keep);
-Deprecated:
+The following functions have been deprecated since OpenSSL 1.1.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
- #if OPENSSL_API_COMPAT < 0x10100000L
int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam);
void RAND_screen(void);
- #endif
=head1 DESCRIPTION
@@ -55,6 +55,11 @@ The content of B<buf> cannot be recovered from subsequent random generator outpu
Applications that intend to save and restore random state in an external file
should consider using L<RAND_load_file(3)> instead.
+NOTE: In FIPS mode, random data provided by the application is not considered to
+be a trusted entropy source. It is mixed into the internal state of the RNG as
+additional data only and this does not count as a full reseed.
+For more details, see L<EVP_RAND(7)>.
+
RAND_seed() is equivalent to RAND_add() with B<randomness> set to B<num>.
RAND_keep_random_devices_open() is used to control file descriptor
@@ -64,7 +69,8 @@ chroot(2) jail without the associated device nodes being available. When
the B<keep> argument is zero, this call disables the retention of file
descriptors. Conversely, a nonzero argument enables the retention of
file descriptors. This function is usually called during initialization
-and it takes effect immediately.
+and it takes effect immediately. This capability only applies to the default
+provider.
RAND_event() and RAND_screen() are equivalent to RAND_poll() and exist
for compatibility reasons only. See HISTORY section below.
@@ -86,6 +92,7 @@ L<RAND_bytes(3)>,
L<RAND_egd(3)>,
L<RAND_load_file(3)>,
L<RAND(7)>
+L<EVP_RAND(7)>
=head1 HISTORY
@@ -94,9 +101,9 @@ not be used.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RAND_bytes.pod b/doc/man3/RAND_bytes.pod
index c44c2f967607..ee7ed4af860c 100644
--- a/doc/man3/RAND_bytes.pod
+++ b/doc/man3/RAND_bytes.pod
@@ -2,7 +2,8 @@
=head1 NAME
-RAND_bytes, RAND_priv_bytes, RAND_pseudo_bytes - generate random data
+RAND_bytes, RAND_priv_bytes, RAND_bytes_ex, RAND_priv_bytes_ex,
+RAND_pseudo_bytes - generate random data
=head1 SYNOPSIS
@@ -11,11 +12,16 @@ RAND_bytes, RAND_priv_bytes, RAND_pseudo_bytes - generate random data
int RAND_bytes(unsigned char *buf, int num);
int RAND_priv_bytes(unsigned char *buf, int num);
-Deprecated:
+ int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num,
+ unsigned int strength);
+ int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num,
+ unsigned int strength);
+
+The following function has been deprecated since OpenSSL 1.1.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
- #if OPENSSL_API_COMPAT < 0x10100000L
int RAND_pseudo_bytes(unsigned char *buf, int num);
- #endif
=head1 DESCRIPTION
@@ -27,7 +33,18 @@ be used for generating values that should remain private. If using the
default RAND_METHOD, this function uses a separate "private" PRNG
instance so that a compromise of the "public" PRNG instance will not
affect the secrecy of these private values, as described in L<RAND(7)>
-and L<RAND_DRBG(7)>.
+and L<EVP_RAND(7)>.
+
+RAND_bytes_ex() and RAND_priv_bytes_ex() are the same as RAND_bytes() and
+RAND_priv_bytes() except that they both take additional I<strength> and
+I<ctx> parameters. The bytes genreated will have a security strength of at
+least I<strength> bits.
+The DRBG used for the operation is the public or private DRBG associated with
+the specified I<ctx>. The parameter can be NULL, in which case
+the default library context is used (see L<OSSL_LIB_CTX(3)>.
+If the default RAND_METHOD has been changed then for compatibility reasons the
+RAND_METHOD will be used in preference and the DRBG of the library context
+ignored.
=head1 NOTES
@@ -62,7 +79,7 @@ L<RAND_bytes(3)>,
L<RAND_priv_bytes(3)>,
L<ERR_get_error(3)>,
L<RAND(7)>,
-L<RAND_DRBG(7)>
+L<EVP_RAND(7)>
=head1 HISTORY
@@ -76,13 +93,17 @@ RAND_pseudo_bytes() was deprecated in OpenSSL 1.1.0; use RAND_bytes() instead.
The RAND_priv_bytes() function was added in OpenSSL 1.1.1.
+=item *
+
+The RAND_bytes_ex() and RAND_priv_bytes_ex() functions were added in OpenSSL 3.0
+
=back
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RAND_cleanup.pod b/doc/man3/RAND_cleanup.pod
index e5187532222d..ce61a9f2b12e 100644
--- a/doc/man3/RAND_cleanup.pod
+++ b/doc/man3/RAND_cleanup.pod
@@ -8,9 +8,11 @@ RAND_cleanup - erase the PRNG state
#include <openssl/rand.h>
- #if OPENSSL_API_COMPAT < 0x10100000L
- void RAND_cleanup(void)
- #endif
+The following function has been deprecated since OpenSSL 1.1.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ void RAND_cleanup(void);
=head1 DESCRIPTION
@@ -34,9 +36,9 @@ See L<OPENSSL_init_crypto(3)>
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RAND_egd.pod b/doc/man3/RAND_egd.pod
index 2b975ebd6ac5..3e57e8430dce 100644
--- a/doc/man3/RAND_egd.pod
+++ b/doc/man3/RAND_egd.pod
@@ -53,7 +53,7 @@ L<RAND(7)>
Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RAND_get0_primary.pod b/doc/man3/RAND_get0_primary.pod
new file mode 100644
index 000000000000..408d02077f29
--- /dev/null
+++ b/doc/man3/RAND_get0_primary.pod
@@ -0,0 +1,82 @@
+=pod
+
+=head1 NAME
+
+RAND_get0_primary,
+RAND_get0_public,
+RAND_get0_private
+- get access to the global EVP_RAND_CTX instances
+
+=head1 SYNOPSIS
+
+ #include <openssl/rand.h>
+
+ EVP_RAND_CTX *RAND_get0_primary(OSSL_LIB_CTX *ctx);
+ EVP_RAND_CTX *RAND_get0_public(OSSL_LIB_CTX *ctx);
+ EVP_RAND_CTX *RAND_get0_private(OSSL_LIB_CTX *ctx);
+
+=head1 DESCRIPTION
+
+The default RAND API implementation (RAND_OpenSSL()) utilizes three
+shared DRBG instances which are accessed via the RAND API:
+
+The I<public> and I<private> DRBG are thread-local instances, which are used
+by RAND_bytes() and RAND_priv_bytes(), respectively.
+The I<primary> DRBG is a global instance, which is not intended to be used
+directly, but is used internally to reseed the other two instances.
+
+These functions here provide access to the shared DRBG instances.
+
+=head1 RETURN VALUES
+
+RAND_get0_primary() returns a pointer to the I<primary> DRBG instance
+for the given OSSL_LIB_CTX B<ctx>.
+
+RAND_get0_public() returns a pointer to the I<public> DRBG instance
+for the given OSSL_LIB_CTX B<ctx>.
+
+RAND_get0_private() returns a pointer to the I<private> DRBG instance
+for the given OSSL_LIB_CTX B<ctx>.
+
+In all the above cases the B<ctx> parameter can
+be NULL in which case the default OSSL_LIB_CTX is used.
+
+=head1 NOTES
+
+It is not thread-safe to access the I<primary> DRBG instance.
+The I<public> and I<private> DRBG instance can be accessed safely, because
+they are thread-local. Note however, that changes to these two instances
+apply only to the current thread.
+
+For that reason it is recommended not to change the settings of these
+three instances directly.
+Instead, an application should change the default settings for new DRBG instances
+at initialization time, before creating additional threads.
+
+During initialization, it is possible to change the reseed interval
+and reseed time interval.
+It is also possible to exchange the reseeding callbacks entirely.
+
+To set the type of DRBG that will be instantiated, use the
+L<RAND_set_DRBG_type(3)> call before accessing the random number generation
+infrastructure.
+
+=head1 SEE ALSO
+
+L<EVP_RAND(3)>,
+L<RAND_set_DRBG_type(3)>
+
+=head1 HISTORY
+
+These functions were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/RAND_load_file.pod b/doc/man3/RAND_load_file.pod
index 6ddd2c89b0d6..baca54cb3c89 100644
--- a/doc/man3/RAND_load_file.pod
+++ b/doc/man3/RAND_load_file.pod
@@ -79,7 +79,7 @@ L<RAND(7)>
Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RAND_set_DRBG_type.pod b/doc/man3/RAND_set_DRBG_type.pod
new file mode 100644
index 000000000000..f78c15ff45f3
--- /dev/null
+++ b/doc/man3/RAND_set_DRBG_type.pod
@@ -0,0 +1,64 @@
+=pod
+
+=head1 NAME
+
+RAND_set_DRBG_type,
+RAND_set_seed_source_type
+- specify the global random number generator types
+
+=head1 SYNOPSIS
+
+ #include <openssl/rand.h>
+
+ int RAND_set_DRBG_type(OSSL_LIB_CTX *ctx, const char *drbg, const char *propq,
+ const char *cipher, const char *digest);
+ int RAND_set_seed_source_type(OSSL_LIB_CTX *ctx, const char *seed,
+ const char *propq);
+
+=head1 DESCRIPTION
+
+RAND_set_DRBG_type() specifies the random bit generator that will be
+used within the library context I<ctx>. A generator of name I<drbg>
+with properties I<propq> will be fetched. It will be instantiated with
+either I<cipher> or I<digest> as its underlying cryptographic algorithm.
+This specifies the type that will be used for the primary, public and
+private random instances.
+
+RAND_set_seed_source_type() specifies the seed source that will be used
+within the library context I<ctx>. The seed source of name I<seed>
+with properties I<propq> will be fetched and used to seed the primary
+random big generator.
+
+=head1 RETURN VALUES
+
+These function return 1 on success and 0 on failure.
+
+=head1 NOTES
+
+These functions must be called before the random bit generators are first
+created in the library context. They will return an error if the call
+is made too late.
+
+The default DRBG is "CTR-DRBG" using the "AES-256-CTR" cipher.
+
+The default seed source is "SEED-SRC".
+
+=head1 SEE ALSO
+
+L<EVP_RAND(3)>,
+L<RAND_get0_primary(3)>
+
+=head1 HISTORY
+
+These functions were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/RAND_set_rand_method.pod b/doc/man3/RAND_set_rand_method.pod
index 1e9360d220dc..0cd5ac41cee4 100644
--- a/doc/man3/RAND_set_rand_method.pod
+++ b/doc/man3/RAND_set_rand_method.pod
@@ -8,6 +8,10 @@ RAND_set_rand_method, RAND_get_rand_method, RAND_OpenSSL - select RAND method
#include <openssl/rand.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
RAND_METHOD *RAND_OpenSSL(void);
int RAND_set_rand_method(const RAND_METHOD *meth);
@@ -16,6 +20,10 @@ RAND_set_rand_method, RAND_get_rand_method, RAND_OpenSSL - select RAND method
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use L<RAND_set_DRBG_type(3)>,
+L<EVP_RAND(3)> and L<EVP_RAND(7)>.
+
A B<RAND_METHOD> specifies the functions that OpenSSL uses for random number
generation.
@@ -23,7 +31,8 @@ RAND_OpenSSL() returns the default B<RAND_METHOD> implementation by OpenSSL.
This implementation ensures that the PRNG state is unique for each thread.
If an B<ENGINE> is loaded that provides the RAND API, however, it will
-be used instead of the method returned by RAND_OpenSSL().
+be used instead of the method returned by RAND_OpenSSL(). This is deprecated
+in OpenSSL 3.0.
RAND_set_rand_method() makes B<meth> the method for PRNG use. If an
ENGINE was providing the method, it will be released first.
@@ -54,15 +63,22 @@ methods.
=head1 SEE ALSO
+L<EVP_RAND(3)>,
+L<RAND_set_DRBG_type(3)>,
L<RAND_bytes(3)>,
L<ENGINE_by_id(3)>,
+L<EVP_RAND(7)>,
L<RAND(7)>
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RC4_set_key.pod b/doc/man3/RC4_set_key.pod
index fe5d2d14857c..296f88eb6f20 100644
--- a/doc/man3/RC4_set_key.pod
+++ b/doc/man3/RC4_set_key.pod
@@ -8,6 +8,10 @@ RC4_set_key, RC4 - RC4 encryption
#include <openssl/rc4.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data);
void RC4(RC4_KEY *key, unsigned long len, const unsigned char *indata,
@@ -15,6 +19,10 @@ RC4_set_key, RC4 - RC4 encryption
=head1 DESCRIPTION
+All of the functions described on this page are deprecated. Applications should
+instead use L<EVP_EncryptInit_ex(3)>, L<EVP_EncryptUpdate(3)> and
+L<EVP_EncryptFinal_ex(3)> or the equivalently named decrypt functions.
+
This library implements the Alleged RC4 cipher, which is described for
example in I<Applied Cryptography>. It is believed to be compatible
with RC4[TM], a proprietary cipher of RSA Security Inc.
@@ -54,11 +62,15 @@ multiple encryptions using the same key stream.
L<EVP_EncryptInit(3)>
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RIPEMD160_Init.pod b/doc/man3/RIPEMD160_Init.pod
index d3cdf930d88e..48937a647f5a 100644
--- a/doc/man3/RIPEMD160_Init.pod
+++ b/doc/man3/RIPEMD160_Init.pod
@@ -9,6 +9,10 @@ RIPEMD-160 hash function
#include <openssl/ripemd.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
unsigned char *RIPEMD160(const unsigned char *d, unsigned long n,
unsigned char *md);
@@ -18,6 +22,10 @@ RIPEMD-160 hash function
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_DigestInit_ex(3)>, L<EVP_DigestUpdate(3)>
+and L<EVP_DigestFinal_ex(3)>.
+
RIPEMD-160 is a cryptographic hash function with a
160 bit output.
@@ -59,11 +67,15 @@ ISO/IEC 10118-3:2016 Dedicated Hash-Function 1 (RIPEMD-160).
L<EVP_DigestInit(3)>
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RSA_blinding_on.pod b/doc/man3/RSA_blinding_on.pod
index 85f4453b5cc8..c2d290b0dfdf 100644
--- a/doc/man3/RSA_blinding_on.pod
+++ b/doc/man3/RSA_blinding_on.pod
@@ -8,12 +8,18 @@ RSA_blinding_on, RSA_blinding_off - protect the RSA operation from timing attack
#include <openssl/rsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int RSA_blinding_on(RSA *rsa, BN_CTX *ctx);
void RSA_blinding_off(RSA *rsa);
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+
RSA is vulnerable to timing attacks. In a setup where attackers can
measure the time of RSA decryption or signature operations, blinding
must be used to protect the RSA operation from that attack.
@@ -31,11 +37,15 @@ RSA_blinding_on() returns 1 on success, and 0 if an error occurred.
RSA_blinding_off() returns no value.
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RSA_check_key.pod b/doc/man3/RSA_check_key.pod
index 8080b1a417dd..d9c0097772c4 100644
--- a/doc/man3/RSA_check_key.pod
+++ b/doc/man3/RSA_check_key.pod
@@ -8,12 +8,20 @@ RSA_check_key_ex, RSA_check_key - validate private RSA keys
#include <openssl/rsa.h>
- int RSA_check_key_ex(RSA *rsa, BN_GENCB *cb);
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
- int RSA_check_key(RSA *rsa);
+ int RSA_check_key_ex(const RSA *rsa, BN_GENCB *cb);
+
+ int RSA_check_key(const RSA *rsa);
=head1 DESCRIPTION
+Both of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_public_check(3)>,
+L<EVP_PKEY_private_check(3)> and L<EVP_PKEY_pairwise_check(3)>.
+
RSA_check_key_ex() function validates RSA keys.
It checks that B<p> and B<q> are
in fact prime, and that B<n = p*q>.
@@ -70,13 +78,15 @@ L<ERR_get_error(3)>
=head1 HISTORY
+All of these functions were deprecated in OpenSSL 3.0.
+
RSA_check_key_ex() appeared after OpenSSL 1.0.2.
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RSA_generate_key.pod b/doc/man3/RSA_generate_key.pod
index 491ba41e502d..d00045e8a3cb 100644
--- a/doc/man3/RSA_generate_key.pod
+++ b/doc/man3/RSA_generate_key.pod
@@ -2,6 +2,7 @@
=head1 NAME
+EVP_RSA_gen,
RSA_generate_key_ex, RSA_generate_key,
RSA_generate_multi_prime_key - generate RSA key pair
@@ -9,43 +10,53 @@ RSA_generate_multi_prime_key - generate RSA key pair
#include <openssl/rsa.h>
+ EVP_PKEY *EVP_RSA_gen(unsigned int bits);
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes, BIGNUM *e, BN_GENCB *cb);
-Deprecated:
+The following function has been deprecated since OpenSSL 0.9.8, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
- #if OPENSSL_API_COMPAT < 0x00908000L
RSA *RSA_generate_key(int bits, unsigned long e,
void (*callback)(int, int, void *), void *cb_arg);
- #endif
=head1 DESCRIPTION
+EVP_RSA_gen() generates a new RSA key pair with modulus size I<bits>.
+
+All of the functions described below are deprecated.
+Applications should instead use EVP_RSA_gen(), L<EVP_PKEY_Q_keygen(3)>, or
+L<EVP_PKEY_keygen_init(3)> and L<EVP_PKEY_keygen(3)>.
+
RSA_generate_key_ex() generates a 2-prime RSA key pair and stores it in the
-B<RSA> structure provided in B<rsa>. The pseudo-random number generator must
-be seeded prior to calling RSA_generate_key_ex().
+B<RSA> structure provided in I<rsa>.
RSA_generate_multi_prime_key() generates a multi-prime RSA key pair and stores
-it in the B<RSA> structure provided in B<rsa>. The number of primes is given by
-the B<primes> parameter. The random number generator must be seeded when
-calling RSA_generate_multi_prime_key().
+it in the B<RSA> structure provided in I<rsa>. The number of primes is given by
+the I<primes> parameter.
If the automatic seeding or reseeding of the OpenSSL CSPRNG fails due to
external circumstances (see L<RAND(7)>), the operation will fail.
-The modulus size will be of length B<bits>, the number of primes to form the
-modulus will be B<primes>, and the public exponent will be B<e>. Key sizes
-with B<num> E<lt> 1024 should be considered insecure. The exponent is an odd
+The modulus size will be of length I<bits>, the number of primes to form the
+modulus will be I<primes>, and the public exponent will be I<e>. Key sizes
+with I<num> E<lt> 1024 should be considered insecure. The exponent is an odd
number, typically 3, 17 or 65537.
In order to maintain adequate security level, the maximum number of permitted
-B<primes> depends on modulus bit length:
+I<primes> depends on modulus bit length:
<1024 | >=1024 | >=4096 | >=8192
------+--------+--------+-------
2 | 3 | 4 | 5
A callback function may be used to provide feedback about the
-progress of the key generation. If B<cb> is not B<NULL>, it
+progress of the key generation. If I<cb> is not NULL, it
will be called as follows using the BN_GENCB_call() function
described on the L<BN_generate_prime(3)> page.
@@ -63,46 +74,50 @@ described in L<BN_generate_prime(3)>.
=item *
When the n-th randomly generated prime is rejected as not
-suitable for the key, B<BN_GENCB_call(cb, 2, n)> is called.
+suitable for the key, I<BN_GENCB_call(cb, 2, n)> is called.
=item *
-When a random p has been found with p-1 relatively prime to B<e>,
-it is called as B<BN_GENCB_call(cb, 3, 0)>.
+When a random p has been found with p-1 relatively prime to I<e>,
+it is called as I<BN_GENCB_call(cb, 3, 0)>.
=back
The process is then repeated for prime q and other primes (if any)
-with B<BN_GENCB_call(cb, 3, i)> where B<i> indicates the i-th prime.
+with I<BN_GENCB_call(cb, 3, i)> where I<i> indicates the i-th prime.
=head1 RETURN VALUES
+EVP_RSA_gen() returns an I<EVP_PKEY> or NULL on failure.
+
RSA_generate_multi_prime_key() returns 1 on success or 0 on error.
RSA_generate_key_ex() returns 1 on success or 0 on error.
The error codes can be obtained by L<ERR_get_error(3)>.
RSA_generate_key() returns a pointer to the RSA structure or
-B<NULL> if the key generation fails.
+NULL if the key generation fails.
=head1 BUGS
-B<BN_GENCB_call(cb, 2, x)> is used with two different meanings.
+I<BN_GENCB_call(cb, 2, x)> is used with two different meanings.
=head1 SEE ALSO
-L<ERR_get_error(3)>, L<RAND_bytes(3)>, L<BN_generate_prime(3)>,
-L<RAND(7)>
+L<EVP_PKEY_Q_keygen(3)>
+L<BN_generate_prime(3)>, L<ERR_get_error(3)>,
+L<RAND_bytes(3)>, L<RAND(7)>
=head1 HISTORY
-RSA_generate_key() was deprecated in OpenSSL 0.9.8; use
-RSA_generate_key_ex() instead.
+EVP_RSA_gen() was added in OpenSSL 3.0.
+All other functions described here were deprecated in OpenSSL 3.0.
+For replacement see L<EVP_PKEY-RSA(7)>.
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RSA_get0_key.pod b/doc/man3/RSA_get0_key.pod
index adcd57c49071..0a0f79125a32 100644
--- a/doc/man3/RSA_get0_key.pod
+++ b/doc/man3/RSA_get0_key.pod
@@ -16,6 +16,10 @@ RSA_set0_multi_prime_params, RSA_get_version
#include <openssl/rsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);
@@ -48,6 +52,10 @@ RSA_set0_multi_prime_params, RSA_get_version
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_get_bn_param(3)> for any methods that
+return a B<BIGNUM>. Refer to L<EVP_PKEY-DH(7)> for more infomation.
+
An RSA object contains the components for the public and private key,
B<n>, B<e>, B<d>, B<p>, B<q>, B<dmp1>, B<dmq1> and B<iqmp>. B<n> is
the modulus common to both public and private key, B<e> is the public
@@ -139,6 +147,9 @@ RSA_get0_n(), RSA_get0_e(), RSA_get0_d(), RSA_get0_p(), RSA_get0_q(),
RSA_get0_dmp1(), RSA_get0_dmq1(), and RSA_get0_iqmp()
return the respective value.
+RSA_get0_pss_params() returns a B<RSA_PSS_PARAMS> pointer, or NULL if
+there is none.
+
RSA_get0_multi_prime_factors() and RSA_get0_multi_prime_crt_params() return
1 on success or 0 on failure.
@@ -169,11 +180,13 @@ and RSA_get_version() functions were added in OpenSSL 1.1.1.
Other functions described here were added in OpenSSL 1.1.0.
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RSA_meth_new.pod b/doc/man3/RSA_meth_new.pod
index f21095156c0f..29ea4161b0b5 100644
--- a/doc/man3/RSA_meth_new.pod
+++ b/doc/man3/RSA_meth_new.pod
@@ -20,6 +20,10 @@ RSA_meth_get_multi_prime_keygen, RSA_meth_set_multi_prime_keygen
#include <openssl/rsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
RSA_METHOD *RSA_meth_new(const char *name, int flags);
void RSA_meth_free(RSA_METHOD *meth);
@@ -123,10 +127,12 @@ RSA_meth_get_multi_prime_keygen, RSA_meth_set_multi_prime_keygen
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use the OSSL_PROVIDER APIs.
+
The B<RSA_METHOD> type is a structure used for the provision of custom
RSA implementations. It provides a set of functions used by OpenSSL
-for the implementation of the various RSA capabilities. See the L<rsa>
-page for more information.
+for the implementation of the various RSA capabilities.
RSA_meth_new() creates a new B<RSA_METHOD> structure. It should be
given a unique B<name> and a set of B<flags>. The B<name> should be a
@@ -245,6 +251,8 @@ L<RSA_generate_multi_prime_key(3)>
=head1 HISTORY
+All of these functions were deprecated in OpenSSL 3.0.
+
RSA_meth_get_multi_prime_keygen() and RSA_meth_set_multi_prime_keygen() were
added in OpenSSL 1.1.1.
@@ -252,9 +260,9 @@ Other functions described here were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RSA_new.pod b/doc/man3/RSA_new.pod
index d57fe826d1f6..7373c2042d9c 100644
--- a/doc/man3/RSA_new.pod
+++ b/doc/man3/RSA_new.pod
@@ -8,6 +8,10 @@ RSA_new, RSA_free - allocate and free RSA objects
#include <openssl/rsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
RSA *RSA_new(void);
void RSA_free(RSA *rsa);
@@ -35,11 +39,16 @@ L<ERR_get_error(3)>,
L<RSA_generate_key(3)>,
L<RSA_new_method(3)>
+=head1 HISTORY
+
+All functions described here were deprecated in OpenSSL 3.0.
+For replacement see EVP_PKEY-RSA(7).
+
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RSA_padding_add_PKCS1_type_1.pod b/doc/man3/RSA_padding_add_PKCS1_type_1.pod
index d0d42ce26595..9f7025c49755 100644
--- a/doc/man3/RSA_padding_add_PKCS1_type_1.pod
+++ b/doc/man3/RSA_padding_add_PKCS1_type_1.pod
@@ -6,7 +6,6 @@ RSA_padding_add_PKCS1_type_1, RSA_padding_check_PKCS1_type_1,
RSA_padding_add_PKCS1_type_2, RSA_padding_check_PKCS1_type_2,
RSA_padding_add_PKCS1_OAEP, RSA_padding_check_PKCS1_OAEP,
RSA_padding_add_PKCS1_OAEP_mgf1, RSA_padding_check_PKCS1_OAEP_mgf1,
-RSA_padding_add_SSLv23, RSA_padding_check_SSLv23,
RSA_padding_add_none, RSA_padding_check_none - asymmetric encryption
padding
@@ -14,6 +13,10 @@ padding
#include <openssl/rsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen,
const unsigned char *f, int fl);
@@ -44,12 +47,6 @@ padding
const unsigned char *p, int pl,
const EVP_MD *md, const EVP_MD *mgf1md);
- int RSA_padding_add_SSLv23(unsigned char *to, int tlen,
- const unsigned char *f, int fl);
-
- int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
- const unsigned char *f, int fl, int rsa_len);
-
int RSA_padding_add_none(unsigned char *to, int tlen,
const unsigned char *f, int fl);
@@ -58,6 +55,9 @@ padding
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use the EVP PKEY APIs.
+
The RSA_padding_xxx_xxx() functions are called from the RSA encrypt,
decrypt, sign and verify functions. Normally they should not be called
from application programs.
@@ -88,10 +88,6 @@ PKCS #1 v2.0 EME-PKCS1-v1_5 (PKCS #1 v1.5 block type 2)
PKCS #1 v2.0 EME-OAEP
-=item SSLv23
-
-PKCS #1 EME-PKCS1-v1_5 with SSL-specific modification
-
=item none
simply copy the data
@@ -148,11 +144,15 @@ L<RSA_private_decrypt(3)>,
L<RSA_sign(3)>, L<RSA_verify(3)>,
L<RAND(7)>
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RSA_print.pod b/doc/man3/RSA_print.pod
index 1367478f93c7..27495b2241af 100644
--- a/doc/man3/RSA_print.pod
+++ b/doc/man3/RSA_print.pod
@@ -10,23 +10,39 @@ DHparams_print, DHparams_print_fp - print cryptographic parameters
#include <openssl/rsa.h>
- int RSA_print(BIO *bp, RSA *x, int offset);
- int RSA_print_fp(FILE *fp, RSA *x, int offset);
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ int RSA_print(BIO *bp, const RSA *x, int offset);
+ int RSA_print_fp(FILE *fp, const RSA *x, int offset);
#include <openssl/dsa.h>
- int DSAparams_print(BIO *bp, DSA *x);
- int DSAparams_print_fp(FILE *fp, DSA *x);
- int DSA_print(BIO *bp, DSA *x, int offset);
- int DSA_print_fp(FILE *fp, DSA *x, int offset);
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ int DSAparams_print(BIO *bp, const DSA *x);
+ int DSAparams_print_fp(FILE *fp, const DSA *x);
+ int DSA_print(BIO *bp, const DSA *x, int offset);
+ int DSA_print_fp(FILE *fp, const DSA *x, int offset);
#include <openssl/dh.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int DHparams_print(BIO *bp, DH *x);
- int DHparams_print_fp(FILE *fp, DH *x);
+ int DHparams_print_fp(FILE *fp, const DH *x);
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_print_params(3)> and
+L<EVP_PKEY_print_private(3)>.
+
A human-readable hexadecimal output of the components of the RSA
key, DSA parameters or key or DH parameters is printed to B<bp> or B<fp>.
@@ -34,17 +50,26 @@ The output lines are indented by B<offset> spaces.
=head1 RETURN VALUES
-These functions return 1 on success, 0 on error.
+DSAparams_print(), DSAparams_print_fp(), DSA_print(), and DSA_print_fp()
+return 1 for success and 0 or a negative value for failure.
+
+DHparams_print() and DHparams_print_fp() return 1 on success, 0 on error.
=head1 SEE ALSO
-L<BN_bn2bin(3)>
+ L<EVP_PKEY_print_params(3)>,
+ L<EVP_PKEY_print_private(3)>,
+ L<BN_bn2bin(3)>
+
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RSA_private_encrypt.pod b/doc/man3/RSA_private_encrypt.pod
index 6629fff3c95b..a9bd23c1345c 100644
--- a/doc/man3/RSA_private_encrypt.pod
+++ b/doc/man3/RSA_private_encrypt.pod
@@ -8,6 +8,10 @@ RSA_private_encrypt, RSA_public_decrypt - low-level signature operations
#include <openssl/rsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int RSA_private_encrypt(int flen, unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
@@ -16,6 +20,11 @@ RSA_private_encrypt, RSA_public_decrypt - low-level signature operations
=head1 DESCRIPTION
+Both of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_sign_init_ex(3)>,
+L<EVP_PKEY_sign(3)>, L<EVP_PKEY_verify_recover_init(3)>, and
+L<EVP_PKEY_verify_recover(3)>.
+
These functions handle RSA signatures at a low-level.
RSA_private_encrypt() signs the B<flen> bytes at B<from> (usually a
@@ -60,13 +69,18 @@ obtained by L<ERR_get_error(3)>.
=head1 SEE ALSO
L<ERR_get_error(3)>,
-L<RSA_sign(3)>, L<RSA_verify(3)>
+L<RSA_sign(3)>, L<RSA_verify(3)>,
+L<EVP_PKEY_sign(3)>, L<EVP_PKEY_verify_recover(3)>
+
+=head1 HISTORY
+
+Both of these functions were deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RSA_public_encrypt.pod b/doc/man3/RSA_public_encrypt.pod
index 384c4823cb63..1d38073aeada 100644
--- a/doc/man3/RSA_public_encrypt.pod
+++ b/doc/man3/RSA_public_encrypt.pod
@@ -8,6 +8,10 @@ RSA_public_encrypt, RSA_private_decrypt - RSA public key cryptography
#include <openssl/rsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int RSA_public_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
@@ -16,6 +20,11 @@ RSA_public_encrypt, RSA_private_decrypt - RSA public key cryptography
=head1 DESCRIPTION
+Both of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_encrypt_init_ex(3)>,
+L<EVP_PKEY_encrypt(3)>, L<EVP_PKEY_decrypt_init_ex(3)> and
+L<EVP_PKEY_decrypt(3)>.
+
RSA_public_encrypt() encrypts the B<flen> bytes at B<from> (usually a
session key) using the public key B<rsa> and stores the ciphertext in
B<to>. B<to> must point to RSA_size(B<rsa>) bytes of memory.
@@ -35,11 +44,6 @@ new applications. SEE WARNING BELOW.
EME-OAEP as defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty
encoding parameter. This mode is recommended for all new applications.
-=item RSA_SSLV23_PADDING
-
-PKCS #1 v1.5 padding with an SSL-specific modification that denotes
-that the server is SSL3 capable.
-
=item RSA_NO_PADDING
Raw RSA encryption. This mode should I<only> be used to implement
@@ -97,11 +101,15 @@ SSL, PKCS #1 v2.0
L<ERR_get_error(3)>, L<RAND_bytes(3)>,
L<RSA_size(3)>
+=head1 HISTORY
+
+Both of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RSA_set_method.pod b/doc/man3/RSA_set_method.pod
index 449b841ed2ad..6e45d6b60b9d 100644
--- a/doc/man3/RSA_set_method.pod
+++ b/doc/man3/RSA_set_method.pod
@@ -10,15 +10,19 @@ RSA_new_method - select RSA method
#include <openssl/rsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
void RSA_set_default_method(const RSA_METHOD *meth);
- RSA_METHOD *RSA_get_default_method(void);
+ const RSA_METHOD *RSA_get_default_method(void);
int RSA_set_method(RSA *rsa, const RSA_METHOD *meth);
- RSA_METHOD *RSA_get_method(const RSA *rsa);
+ const RSA_METHOD *RSA_get_method(const RSA *rsa);
- RSA_METHOD *RSA_PKCS1_OpenSSL(void);
+ const RSA_METHOD *RSA_PKCS1_OpenSSL(void);
int RSA_flags(const RSA *rsa);
@@ -26,6 +30,9 @@ RSA_new_method - select RSA method
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use the OSSL_PROVIDER APIs.
+
An B<RSA_METHOD> specifies the functions that OpenSSL uses for RSA
operations. By modifying the method, alternative implementations such as
hardware accelerators may be used. IMPORTANT: See the NOTES section for
@@ -129,7 +136,7 @@ the default method is used.
const unsigned char *m, unsigned int m_length,
const unsigned char *sigbuf, unsigned int siglen,
const RSA *rsa);
- /* keygen. If NULL builtin RSA key generation will be used */
+ /* keygen. If NULL built-in RSA key generation will be used */
int (*rsa_keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
} RSA_METHOD;
@@ -171,14 +178,16 @@ L<RSA_new(3)>
=head1 HISTORY
+All of these functions were deprecated in OpenSSL 3.0.
+
The RSA_null_method(), which was a partial attempt to avoid patent issues,
was replaced to always return NULL in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RSA_sign.pod b/doc/man3/RSA_sign.pod
index 310abd4901fb..e883caf7682f 100644
--- a/doc/man3/RSA_sign.pod
+++ b/doc/man3/RSA_sign.pod
@@ -8,6 +8,10 @@ RSA_sign, RSA_verify - RSA signatures
#include <openssl/rsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int RSA_sign(int type, const unsigned char *m, unsigned int m_len,
unsigned char *sigret, unsigned int *siglen, RSA *rsa);
@@ -16,6 +20,10 @@ RSA_sign, RSA_verify - RSA signatures
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_sign_init(3)>, L<EVP_PKEY_sign(3)>,
+L<EVP_PKEY_verify_init(3)> and L<EVP_PKEY_verify(3)>.
+
RSA_sign() signs the message digest B<m> of size B<m_len> using the
private key B<rsa> using RSASSA-PKCS1-v1_5 as specified in RFC 3447. It
stores the signature in B<sigret> and the signature size in B<siglen>.
@@ -38,8 +46,8 @@ B<rsa> is the signer's public key.
=head1 RETURN VALUES
-RSA_sign() returns 1 on success.
-RSA_verify() returns 1 on successful verification.
+RSA_sign() returns 1 on success and 0 for failure.
+RSA_verify() returns 1 on successful verification and 0 for failure.
The error codes can be obtained by L<ERR_get_error(3)>.
@@ -53,11 +61,15 @@ L<ERR_get_error(3)>,
L<RSA_private_encrypt(3)>,
L<RSA_public_decrypt(3)>
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RSA_sign_ASN1_OCTET_STRING.pod b/doc/man3/RSA_sign_ASN1_OCTET_STRING.pod
index 6e8a53b53e59..6548bdb78a06 100644
--- a/doc/man3/RSA_sign_ASN1_OCTET_STRING.pod
+++ b/doc/man3/RSA_sign_ASN1_OCTET_STRING.pod
@@ -8,6 +8,10 @@ RSA_sign_ASN1_OCTET_STRING, RSA_verify_ASN1_OCTET_STRING - RSA signatures
#include <openssl/rsa.h>
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int RSA_sign_ASN1_OCTET_STRING(int dummy, unsigned char *m,
unsigned int m_len, unsigned char *sigret,
unsigned int *siglen, RSA *rsa);
@@ -18,6 +22,9 @@ RSA_sign_ASN1_OCTET_STRING, RSA_verify_ASN1_OCTET_STRING - RSA signatures
=head1 DESCRIPTION
+All of the functions described on this page are deprecated.
+Applications should instead use EVP PKEY APIs.
+
RSA_sign_ASN1_OCTET_STRING() signs the octet string B<m> of size
B<m_len> using the private key B<rsa> represented in DER using PKCS #1
padding. It stores the signature in B<sigret> and the signature size
@@ -55,11 +62,15 @@ L<RAND_bytes(3)>, L<RSA_sign(3)>,
L<RSA_verify(3)>,
L<RAND(7)>
+=head1 HISTORY
+
+All of these functions were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/RSA_size.pod b/doc/man3/RSA_size.pod
index 99498650866f..18e968c966b2 100644
--- a/doc/man3/RSA_size.pod
+++ b/doc/man3/RSA_size.pod
@@ -8,30 +8,38 @@ RSA_size, RSA_bits, RSA_security_bits - get RSA modulus size or security bits
#include <openssl/rsa.h>
- int RSA_size(const RSA *rsa);
-
int RSA_bits(const RSA *rsa);
- int RSA_security_bits(const RSA *rsa)
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
-=head1 DESCRIPTION
+ int RSA_size(const RSA *rsa);
-RSA_size() returns the RSA modulus size in bytes. It can be used to
-determine how much memory must be allocated for an RSA encrypted
-value.
+ int RSA_security_bits(const RSA *rsa);
+
+=head1 DESCRIPTION
RSA_bits() returns the number of significant bits.
B<rsa> and B<rsa-E<gt>n> must not be B<NULL>.
+The remaining functions described on this page are deprecated.
+Applications should instead use L<EVP_PKEY_get_size(3)>, L<EVP_PKEY_get_bits(3)>
+and L<EVP_PKEY_get_security_bits(3)>.
+
+RSA_size() returns the RSA modulus size in bytes. It can be used to
+determine how much memory must be allocated for an RSA encrypted
+value.
+
RSA_security_bits() returns the number of security bits of the given B<rsa>
key. See L<BN_security_bits(3)>.
=head1 RETURN VALUES
-RSA_size() returns the size of modulus in bytes.
+RSA_bits() returns the number of bits in the key.
-DSA_bits() returns the number of bits in the key.
+RSA_size() returns the size of modulus in bytes.
RSA_security_bits() returns the number of security bits.
@@ -41,13 +49,15 @@ L<BN_num_bits(3)>
=head1 HISTORY
+The RSA_size() and RSA_security_bits() functions were deprecated in OpenSSL 3.0.
+
The RSA_bits() function was added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SCT_new.pod b/doc/man3/SCT_new.pod
index 8da7f6adf21c..235762721992 100644
--- a/doc/man3/SCT_new.pod
+++ b/doc/man3/SCT_new.pod
@@ -108,7 +108,8 @@ See RFC 6962, Section 3.2 for the definition of LogID.
=item *
-SCT_set_timestamp() to set the time the SCT was issued (epoch time in milliseconds).
+SCT_set_timestamp() to set the time the SCT was issued (time in milliseconds
+since the Unix Epoch).
=item *
@@ -149,7 +150,7 @@ B<CT_LOG_ENTRY_TYPE_PRECERT> for a pre-certificate.
=item *
-The time that the SCT was issued (epoch time in milliseconds).
+The time that the SCT was issued (time in milliseconds since the Unix Epoch).
=item *
@@ -211,7 +212,7 @@ These functions were added in OpenSSL 1.1.0.
Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SCT_print.pod b/doc/man3/SCT_print.pod
index 2b9913d4b628..fbcbce2760c3 100644
--- a/doc/man3/SCT_print.pod
+++ b/doc/man3/SCT_print.pod
@@ -16,7 +16,7 @@ Prints Signed Certificate Timestamps in a human-readable way
=head1 DESCRIPTION
-SCT_print() prints a single Signed Certificate Timestamp (SCT) to a L<bio> in
+SCT_print() prints a single Signed Certificate Timestamp (SCT) to a B<BIO> in
a human-readable format. SCT_LIST_print() prints an entire list of SCTs in a
similar way. A separator can be specified to delimit each SCT in the output.
@@ -31,7 +31,7 @@ beforehand in order to set the validation status of an SCT first.
=head1 RETURN VALUES
-SCT_validation_status_string() returns a null-terminated string representing
+SCT_validation_status_string() returns a NUL-terminated string representing
the validation status of an B<SCT> object.
=head1 SEE ALSO
@@ -47,9 +47,9 @@ These functions were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SCT_validate.pod b/doc/man3/SCT_validate.pod
index fa7e2a8ba2cc..20fdfb44b5c4 100644
--- a/doc/man3/SCT_validate.pod
+++ b/doc/man3/SCT_validate.pod
@@ -96,7 +96,7 @@ These functions were added in OpenSSL 1.1.0.
Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SHA256_Init.pod b/doc/man3/SHA256_Init.pod
index f50839db6385..3d647c381b4e 100644
--- a/doc/man3/SHA256_Init.pod
+++ b/doc/man3/SHA256_Init.pod
@@ -11,41 +11,46 @@ SHA512_Final - Secure Hash Algorithm
#include <openssl/sha.h>
+ unsigned char *SHA1(const unsigned char *data, size_t count, unsigned char *md_buf);
+ unsigned char *SHA224(const unsigned char *data, size_t count, unsigned char *md_buf);
+ unsigned char *SHA256(const unsigned char *data, size_t count, unsigned char *md_buf);
+ unsigned char *SHA384(const unsigned char *data, size_t count, unsigned char *md_buf);
+ unsigned char *SHA512(const unsigned char *data, size_t count, unsigned char *md_buf);
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
int SHA1_Init(SHA_CTX *c);
int SHA1_Update(SHA_CTX *c, const void *data, size_t len);
int SHA1_Final(unsigned char *md, SHA_CTX *c);
- unsigned char *SHA1(const unsigned char *d, size_t n,
- unsigned char *md);
int SHA224_Init(SHA256_CTX *c);
int SHA224_Update(SHA256_CTX *c, const void *data, size_t len);
int SHA224_Final(unsigned char *md, SHA256_CTX *c);
- unsigned char *SHA224(const unsigned char *d, size_t n,
- unsigned char *md);
int SHA256_Init(SHA256_CTX *c);
int SHA256_Update(SHA256_CTX *c, const void *data, size_t len);
int SHA256_Final(unsigned char *md, SHA256_CTX *c);
- unsigned char *SHA256(const unsigned char *d, size_t n,
- unsigned char *md);
int SHA384_Init(SHA512_CTX *c);
int SHA384_Update(SHA512_CTX *c, const void *data, size_t len);
int SHA384_Final(unsigned char *md, SHA512_CTX *c);
- unsigned char *SHA384(const unsigned char *d, size_t n,
- unsigned char *md);
int SHA512_Init(SHA512_CTX *c);
int SHA512_Update(SHA512_CTX *c, const void *data, size_t len);
int SHA512_Final(unsigned char *md, SHA512_CTX *c);
- unsigned char *SHA512(const unsigned char *d, size_t n,
- unsigned char *md);
=head1 DESCRIPTION
-Applications should use the higher level functions
-L<EVP_DigestInit(3)> etc. instead of calling the hash
-functions directly.
+All of the functions described on this page
+except for SHA1(), SHA224(), SHA256(), SHA384() and SHA512() are deprecated.
+Applications should instead use L<EVP_DigestInit_ex(3)>, L<EVP_DigestUpdate(3)>
+and L<EVP_DigestFinal_ex(3)>, or the quick one-shot function L<EVP_Q_digest(3)>.
+SHA1(), SHA224(), SHA256(), SHA384(), and SHA256()
+can continue to be used. They can also be replaced by, e.g.,
+
+ (EVP_Q_digest(d, n, md, NULL, NULL, "SHA256", NULL) ? md : NULL)
SHA-1 (Secure Hash Algorithm) is a cryptographic hash function with a
160 bit output.
@@ -91,13 +96,18 @@ ANSI X9.30
=head1 SEE ALSO
+L<EVP_Q_digest(3)>,
L<EVP_DigestInit(3)>
+=head1 HISTORY
+
+All of these functions except SHA*() were deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SMIME_read_ASN1.pod b/doc/man3/SMIME_read_ASN1.pod
new file mode 100644
index 000000000000..a90d9a400420
--- /dev/null
+++ b/doc/man3/SMIME_read_ASN1.pod
@@ -0,0 +1,86 @@
+=pod
+
+=head1 NAME
+
+SMIME_read_ASN1_ex, SMIME_read_ASN1
+- parse S/MIME message
+
+=head1 SYNOPSIS
+
+ #include <openssl/asn1.h>
+
+ ASN1_VALUE *SMIME_read_ASN1_ex(BIO *in, int flags, BIO **bcont,
+ const ASN1_ITEM *it, ASN1_VALUE **x,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ ASN1_VALUE *SMIME_read_ASN1(BIO *in, BIO **bcont, const ASN1_ITEM *it);
+
+=head1 DESCRIPTION
+
+SMIME_read_ASN1_ex() parses a message in S/MIME format.
+
+I<in> is a BIO to read the message from.
+If the I<flags> argument contains B<CMS_BINARY> then the input is assumed to be
+in binary format and is not translated to canonical form.
+If in addition B<SMIME_ASCIICRLF> is set then the binary input is assumed
+to be followed by B<CR> and B<LF> characters, else only by an B<LF> character.
+I<x> can be used to optionally supply
+a previously created I<it> ASN1_VALUE object (such as CMS_ContentInfo or PKCS7),
+it can be set to NULL. Valid values that can be used by ASN.1 structure I<it>
+are ASN1_ITEM_rptr(PKCS7) or ASN1_ITEM_rptr(CMS_ContentInfo). Any algorithm
+fetches that occur during the operation will use the B<OSSL_LIB_CTX> supplied in
+the I<libctx> parameter, and use the property query string I<propq> See
+L<crypto(7)/ALGORITHM FETCHING> for further details about algorithm fetching.
+
+If cleartext signing is used then the content is saved in a memory bio which is
+written to I<*bcont>, otherwise I<*bcont> is set to NULL.
+
+The parsed ASN1_VALUE structure is returned or NULL if an error occurred.
+
+SMIME_read_ASN1() is similar to SMIME_read_ASN1_ex() but sets the value of I<x>
+to NULL and the value of I<flags> to 0.
+
+=head1 NOTES
+
+The higher level functions L<SMIME_read_CMS_ex(3)> and
+L<SMIME_read_PKCS7_ex(3)> should be used instead of SMIME_read_ASN1_ex().
+
+To support future functionality if I<bcont> is not NULL I<*bcont> should be
+initialized to NULL.
+
+=head1 BUGS
+
+The MIME parser used by SMIME_read_ASN1_ex() is somewhat primitive. While it will
+handle most S/MIME messages more complex compound formats may not work.
+
+The use of a memory BIO to hold the signed content limits the size of message
+which can be processed due to memory restraints: a streaming single pass option
+should be available.
+
+=head1 RETURN VALUES
+
+SMIME_read_ASN1_ex() and SMIME_read_ASN1() return a valid B<ASN1_VALUE>
+structure or B<NULL> if an error occurred. The error can be obtained from
+ERR_get_error(3).
+
+=head1 SEE ALSO
+
+L<ERR_get_error(3)>,
+L<SMIME_read_CMS_ex(3)>,
+L<SMIME_read_PKCS7_ex(3)>,
+L<SMIME_write_ASN1(3)>,
+L<SMIME_write_ASN1_ex(3)>
+
+=head1 HISTORY
+
+The function SMIME_read_ASN1_ex() was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/SMIME_read_CMS.pod b/doc/man3/SMIME_read_CMS.pod
index 800e4aa25f3c..733d26078a74 100644
--- a/doc/man3/SMIME_read_CMS.pod
+++ b/doc/man3/SMIME_read_CMS.pod
@@ -2,12 +2,14 @@
=head1 NAME
-SMIME_read_CMS - parse S/MIME message
+SMIME_read_CMS_ex, SMIME_read_CMS - parse S/MIME message
=head1 SYNOPSIS
#include <openssl/cms.h>
+ CMS_ContentInfo *SMIME_read_CMS_ex(BIO *bio, int flags, BIO **bcont,
+ CMS_ContentInfo **cms);
CMS_ContentInfo *SMIME_read_CMS(BIO *in, BIO **bcont);
=head1 DESCRIPTION
@@ -22,6 +24,15 @@ written to B<*bcont>, otherwise B<*bcont> is set to NULL.
The parsed CMS_ContentInfo structure is returned or NULL if an
error occurred.
+SMIME_read_CMS_ex() is similar to SMIME_read_CMS() but optionally a previously
+created I<cms> CMS_ContentInfo object can be supplied as well as some I<flags>.
+To create a I<cms> object use L<CMS_ContentInfo_new_ex(3)>.
+If the I<flags> argument contains B<CMS_BINARY> then the input is assumed to be
+in binary format and is not translated to canonical form.
+If in addition B<SMIME_ASCIICRLF> is set then the binary input is assumed
+to be followed by B<CR> and B<LF> characters, else only by an B<LF> character.
+If I<flags> is 0 and I<cms> is NULL then it is identical to SMIME_read_CMS().
+
=head1 NOTES
If B<*bcont> is not NULL then the message is clear text signed. B<*bcont> can
@@ -53,21 +64,27 @@ should be available.
=head1 RETURN VALUES
-SMIME_read_CMS() returns a valid B<CMS_ContentInfo> structure or B<NULL>
-if an error occurred. The error can be obtained from ERR_get_error(3).
+SMIME_read_CMS_ex() and SMIME_read_CMS() return a valid B<CMS_ContentInfo>
+structure or B<NULL> if an error occurred. The error can be obtained from
+ERR_get_error(3).
=head1 SEE ALSO
-L<ERR_get_error(3)>, L<CMS_type(3)>,
-L<SMIME_read_CMS(3)>, L<CMS_sign(3)>,
-L<CMS_verify(3)>, L<CMS_encrypt(3)>,
+L<ERR_get_error(3)>,
+L<CMS_sign(3)>,
+L<CMS_verify(3)>,
+L<CMS_encrypt(3)>,
L<CMS_decrypt(3)>
+=head1 HISTORY
+
+The function SMIME_read_CMS_ex() was added in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SMIME_read_PKCS7.pod b/doc/man3/SMIME_read_PKCS7.pod
index c11090891ad3..c2d422c512cd 100644
--- a/doc/man3/SMIME_read_PKCS7.pod
+++ b/doc/man3/SMIME_read_PKCS7.pod
@@ -2,12 +2,13 @@
=head1 NAME
-SMIME_read_PKCS7 - parse S/MIME message
+SMIME_read_PKCS7_ex, SMIME_read_PKCS7 - parse S/MIME message
=head1 SYNOPSIS
#include <openssl/pkcs7.h>
+ PKCS7 *SMIME_read_PKCS7_ex(BIO *bio, BIO **bcont, PKCS7 **p7);
PKCS7 *SMIME_read_PKCS7(BIO *in, BIO **bcont);
=head1 DESCRIPTION
@@ -23,6 +24,11 @@ B<*bcont> is set to B<NULL>.
The parsed PKCS#7 structure is returned or B<NULL> if an
error occurred.
+SMIME_read_PKCS7_ex() is similar to SMIME_read_PKCS7() but can optionally supply
+a previously created I<p7> PKCS#7 object. If I<p7> is NULL then it is identical
+to SMIME_read_PKCS7().
+To create a I<p7> object use L<PKCS7_new_ex(3)>.
+
=head1 NOTES
If B<*bcont> is not B<NULL> then the message is clear text
@@ -56,8 +62,8 @@ streaming single pass option should be available.
=head1 RETURN VALUES
-SMIME_read_PKCS7() returns a valid B<PKCS7> structure or B<NULL>
-if an error occurred. The error can be obtained from ERR_get_error(3).
+SMIME_read_PKCS7_ex() and SMIME_read_PKCS7() return a valid B<PKCS7> structure
+or B<NULL> if an error occurred. The error can be obtained from ERR_get_error(3).
=head1 SEE ALSO
@@ -66,11 +72,15 @@ L<SMIME_read_PKCS7(3)>, L<PKCS7_sign(3)>,
L<PKCS7_verify(3)>, L<PKCS7_encrypt(3)>
L<PKCS7_decrypt(3)>
+=head1 HISTORY
+
+The function SMIME_read_PKCS7_ex() was added in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SMIME_write_ASN1.pod b/doc/man3/SMIME_write_ASN1.pod
new file mode 100644
index 000000000000..4217d24225b5
--- /dev/null
+++ b/doc/man3/SMIME_write_ASN1.pod
@@ -0,0 +1,82 @@
+=pod
+
+=head1 NAME
+
+SMIME_write_ASN1_ex, SMIME_write_ASN1
+- convert structure to S/MIME format
+
+=head1 SYNOPSIS
+
+ #include <openssl/asn1.h>
+
+ int SMIME_write_ASN1_ex(BIO *out, ASN1_VALUE *val, BIO *data, int flags,
+ int ctype_nid, int econt_nid,
+ STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+ int SMIME_write_ASN1(BIO *out,
+ ASN1_VALUE *val, BIO *data, int flags, int ctype_nid, int econt_nid,
+ STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it);
+
+=head1 DESCRIPTION
+
+SMIME_write_ASN1_ex() adds the appropriate MIME headers to an object
+structure to produce an S/MIME message.
+
+I<out> is the BIO to write the data to. I<value> is the appropriate ASN1_VALUE
+structure (either CMS_ContentInfo or PKCS7). If streaming is enabled then the
+content must be supplied via I<data>.
+I<flags> is an optional set of flags. I<ctype_nid> is the NID of the content
+type, I<econt_nid> is the NID of the embedded content type and I<mdalgs> is a
+list of signed data digestAlgorithms. Valid values that can be used by the
+ASN.1 structure I<it> are ASN1_ITEM_rptr(PKCS7) or ASN1_ITEM_rptr(CMS_ContentInfo).
+The library context I<libctx> and the property query I<propq> are used when
+retrieving algorithms from providers.
+
+=head1 NOTES
+
+The higher level functions L<SMIME_write_CMS(3)> and
+L<SMIME_write_PKCS7(3)> should be used instead of SMIME_write_ASN1().
+
+The following flags can be passed in the B<flags> parameter.
+
+If B<CMS_DETACHED> is set then cleartext signing will be used, this option only
+makes sense for SignedData where B<CMS_DETACHED> is also set when the sign()
+method is called.
+
+If the B<CMS_TEXT> flag is set MIME headers for type B<text/plain> are added to
+the content, this only makes sense if B<CMS_DETACHED> is also set.
+
+If the B<CMS_STREAM> flag is set streaming is performed. This flag should only
+be set if B<CMS_STREAM> was also set in the previous call to a CMS_ContentInfo
+or PKCS7 creation function.
+
+If cleartext signing is being used and B<CMS_STREAM> not set then the data must
+be read twice: once to compute the signature in sign method and once to output
+the S/MIME message.
+
+If streaming is performed the content is output in BER format using indefinite
+length constructed encoding except in the case of signed data with detached
+content where the content is absent and DER format is used.
+
+=head1 RETURN VALUES
+
+SMIME_write_ASN1_ex() and SMIME_write_ASN1() return 1 for success or
+0 for failure.
+
+=head1 SEE ALSO
+
+L<ERR_get_error(3)>,
+L<SMIME_write_CMS(3)>,
+L<SMIME_write_PKCS7(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/SMIME_write_CMS.pod b/doc/man3/SMIME_write_CMS.pod
index d58baeb746db..ea471f450702 100644
--- a/doc/man3/SMIME_write_CMS.pod
+++ b/doc/man3/SMIME_write_CMS.pod
@@ -61,7 +61,7 @@ L<CMS_decrypt(3)>
Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SMIME_write_PKCS7.pod b/doc/man3/SMIME_write_PKCS7.pod
index b57312386e2e..66b12a221fce 100644
--- a/doc/man3/SMIME_write_PKCS7.pod
+++ b/doc/man3/SMIME_write_PKCS7.pod
@@ -62,7 +62,7 @@ L<PKCS7_decrypt(3)>
Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SRP_Calc_B.pod b/doc/man3/SRP_Calc_B.pod
new file mode 100644
index 000000000000..ec6221aa7cc9
--- /dev/null
+++ b/doc/man3/SRP_Calc_B.pod
@@ -0,0 +1,100 @@
+=pod
+
+=head1 NAME
+
+SRP_Calc_server_key,
+SRP_Calc_A,
+SRP_Calc_B_ex,
+SRP_Calc_B,
+SRP_Calc_u_ex,
+SRP_Calc_u,
+SRP_Calc_x_ex,
+SRP_Calc_x,
+SRP_Calc_client_key_ex,
+SRP_Calc_client_key
+- SRP authentication primitives
+
+=head1 SYNOPSIS
+
+ #include <openssl/srp.h>
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ /* server side .... */
+ BIGNUM *SRP_Calc_server_key(const BIGNUM *A, const BIGNUM *v, const BIGNUM *u,
+ const BIGNUM *b, const BIGNUM *N);
+ BIGNUM *SRP_Calc_B_ex(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g,
+ const BIGNUM *v, OSSL_LIB_CTX *libctx, const char *propq);
+ BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g,
+ const BIGNUM *v);
+
+ BIGNUM *SRP_Calc_u_ex(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ BIGNUM *SRP_Calc_u(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N);
+
+ /* client side .... */
+ BIGNUM *SRP_Calc_client_key_ex(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g,
+ const BIGNUM *x, const BIGNUM *a, const BIGNUM *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g,
+ const BIGNUM *x, const BIGNUM *a, const BIGNUM *u);
+ BIGNUM *SRP_Calc_x_ex(const BIGNUM *s, const char *user, const char *pass,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass);
+ BIGNUM *SRP_Calc_A(const BIGNUM *a, const BIGNUM *N, const BIGNUM *g);
+
+=head1 DESCRIPTION
+
+All of the functions described on this page are deprecated. There are no
+available replacement functions at this time.
+
+The SRP functions described on this page are used to calculate various
+parameters and keys used by SRP as defined in RFC2945. The server key and I<B>
+and I<u> parameters are used on the server side and are calculated via
+SRP_Calc_server_key(), SRP_Calc_B_ex(), SRP_Calc_B(), SRP_Calc_u_ex() and
+SRP_Calc_u(). The client key and B<x> and B<A> parameters are used on the
+client side and are calculated via the functions SRP_Calc_client_key_ex(),
+SRP_Calc_client_key(), SRP_Calc_x_ex(), SRP_Calc_x() and SRP_Calc_A(). See
+RFC2945 for a detailed description of their usage and the meaning of the various
+BIGNUM parameters to these functions.
+
+Most of these functions come in two forms. Those that take a I<libctx> and
+I<propq> parameter, and those that don't. Any cryptogrpahic functions that
+are fetched and used during the calculation use the provided I<libctx> and
+I<propq>. See L<crypto(7)/ALGORITHM FETCHING> for more details. The variants
+that do not take a I<libctx> and I<propq> parameter use the default library
+context and property query string. The SRP_Calc_server_key() and SRP_Calc_A()
+functions do not have a form that takes I<libctx> or I<propq> parameters because
+they do not need to fetch any cryptographic algorithms.
+
+=head1 RETURN VALUES
+
+All these functions return the calculated key or parameter, or NULL on error.
+
+=head1 SEE ALSO
+
+L<openssl-srp(1)>,
+L<SRP_VBASE_new(3)>,
+L<SRP_user_pwd_new(3)>
+
+=head1 HISTORY
+
+SRP_Calc_B_ex, SRP_Calc_u_ex, SRP_Calc_client_key_ex and SRP_Calc_x_ex were
+introduced in OpenSSL 3.0.
+
+All of the other functions were added in OpenSSL 1.0.1.
+
+All of these functions were deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/SRP_VBASE_new.pod b/doc/man3/SRP_VBASE_new.pod
new file mode 100644
index 000000000000..a4838fb6c617
--- /dev/null
+++ b/doc/man3/SRP_VBASE_new.pod
@@ -0,0 +1,108 @@
+=pod
+
+=head1 NAME
+
+SRP_VBASE_new,
+SRP_VBASE_free,
+SRP_VBASE_init,
+SRP_VBASE_add0_user,
+SRP_VBASE_get1_by_user,
+SRP_VBASE_get_by_user
+- Functions to create and manage a stack of SRP user verifier information
+
+=head1 SYNOPSIS
+
+ #include <openssl/srp.h>
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ SRP_VBASE *SRP_VBASE_new(char *seed_key);
+ void SRP_VBASE_free(SRP_VBASE *vb);
+
+ int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file);
+
+ int SRP_VBASE_add0_user(SRP_VBASE *vb, SRP_user_pwd *user_pwd);
+ SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username);
+ SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username);
+
+=head1 DESCRIPTION
+
+All of the functions described on this page are deprecated. There are no
+available replacement functions at this time.
+
+The SRP_VBASE_new() function allocates a structure to store server side SRP
+verifier information.
+If B<seed_key> is not NULL a copy is stored and used to generate dummy parameters
+for users that are not found by SRP_VBASE_get1_by_user(). This allows the server
+to hide the fact that it doesn't have a verifier for a particular username,
+as described in section 2.5.1.3 'Unknown SRP' of RFC 5054.
+The seed string should contain random NUL terminated binary data (therefore
+the random data should not contain NUL bytes!).
+
+The SRP_VBASE_free() function frees up the B<vb> structure.
+If B<vb> is NULL, nothing is done.
+
+The SRP_VBASE_init() function parses the information in a verifier file and
+populates the B<vb> structure.
+The verifier file is a text file containing multiple entries, whose format is:
+flag base64(verifier) base64(salt) username gNid userinfo(optional)
+where the flag can be 'V' (valid) or 'R' (revoked).
+Note that the base64 encoding used here is non-standard so it is recommended
+to use L<openssl-srp(1)> to generate this file.
+
+The SRP_VBASE_add0_user() function adds the B<user_pwd> verifier information
+to the B<vb> structure. See L<SRP_user_pwd_new(3)> to create and populate this
+record.
+The library takes ownership of B<user_pwd>, it should not be freed by the caller.
+
+The SRP_VBASE_get1_by_user() function returns the password info for the user
+whose username matches B<username>. It replaces the deprecated
+SRP_VBASE_get_by_user().
+If no matching user is found but a seed_key and default gN parameters have been
+set, dummy authentication information is generated from the seed_key, allowing
+the server to hide the fact that it doesn't have a verifier for a particular
+username. When using SRP as a TLS authentication mechanism, this will cause
+the handshake to proceed normally but the first client will be rejected with
+a "bad_record_mac" alert, as if the password was incorrect.
+If no matching user is found and the seed_key is not set, NULL is returned.
+Ownership of the returned pointer is released to the caller, it must be freed
+with SRP_user_pwd_free().
+
+=head1 RETURN VALUES
+
+SRP_VBASE_init() returns B<SRP_NO_ERROR> (0) on success and a positive value
+on failure.
+The error codes are B<SRP_ERR_OPEN_FILE> if the file could not be opened,
+B<SRP_ERR_VBASE_INCOMPLETE_FILE> if the file could not be parsed,
+B<SRP_ERR_MEMORY> on memory allocation failure and B<SRP_ERR_VBASE_BN_LIB>
+for invalid decoded parameter values.
+
+SRP_VBASE_add0_user() returns 1 on success and 0 on failure.
+
+=head1 SEE ALSO
+
+L<openssl-srp(1)>,
+L<SRP_create_verifier(3)>,
+L<SRP_user_pwd_new(3)>,
+L<SSL_CTX_set_srp_password(3)>
+
+=head1 HISTORY
+
+The SRP_VBASE_add0_user() function was added in OpenSSL 3.0.
+
+All other functions were added in OpenSSL 1.0.1.
+
+All of these functions were deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/SRP_create_verifier.pod b/doc/man3/SRP_create_verifier.pod
new file mode 100644
index 000000000000..a4de39a573ba
--- /dev/null
+++ b/doc/man3/SRP_create_verifier.pod
@@ -0,0 +1,139 @@
+=pod
+
+=head1 NAME
+
+SRP_create_verifier_ex,
+SRP_create_verifier,
+SRP_create_verifier_BN_ex,
+SRP_create_verifier_BN,
+SRP_check_known_gN_param,
+SRP_get_default_gN
+- SRP authentication primitives
+
+=head1 SYNOPSIS
+
+ #include <openssl/srp.h>
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ int SRP_create_verifier_BN_ex(const char *user, const char *pass, BIGNUM **salt,
+ BIGNUM **verifier, const BIGNUM *N,
+ const BIGNUM *g, OSSL_LIB_CTX *libctx,
+ const char *propq);
+ char *SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt,
+ BIGNUM **verifier, const BIGNUM *N, const BIGNUM *g);
+ char *SRP_create_verifier_ex(const char *user, const char *pass, char **salt,
+ char **verifier, const char *N, const char *g,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ char *SRP_create_verifier(const char *user, const char *pass, char **salt,
+ char **verifier, const char *N, const char *g);
+
+ char *SRP_check_known_gN_param(const BIGNUM *g, const BIGNUM *N);
+ SRP_gN *SRP_get_default_gN(const char *id);
+
+=head1 DESCRIPTION
+
+All of the functions described on this page are deprecated. There are no
+available replacement functions at this time.
+
+The SRP_create_verifier_BN_ex() function creates an SRP password verifier from
+the supplied parameters as defined in section 2.4 of RFC 5054 using the library
+context I<libctx> and property query string I<propq>. Any cryptographic
+algorithms that need to be fetched will use the I<libctx> and I<propq>. See
+L<crypto(7)/ALGORITHM FETCHING>.
+
+SRP_create_verifier_BN() is the same as SRP_create_verifier_BN_ex() except the
+default library context and property query string is used.
+
+On successful exit I<*verifier> will point to a newly allocated BIGNUM containing
+the verifier and (if a salt was not provided) I<*salt> will be populated with a
+newly allocated BIGNUM containing a random salt. If I<*salt> is not NULL then
+the provided salt is used instead.
+The caller is responsible for freeing the allocated I<*salt> and I<*verifier>
+BIGNUMS (use L<BN_free(3)>).
+
+The SRP_create_verifier() function is similar to SRP_create_verifier_BN() but
+all numeric parameters are in a non-standard base64 encoding originally designed
+for compatibility with libsrp. This is mainly present for historical compatibility
+and its use is discouraged.
+It is possible to pass NULL as I<N> and an SRP group id as I<g> instead to
+load the appropriate gN values (see SRP_get_default_gN()).
+If both I<N> and I<g> are NULL the 8192-bit SRP group parameters are used.
+The caller is responsible for freeing the allocated I<*salt> and I<*verifier>
+(use L<OPENSSL_free(3)>).
+
+The SRP_check_known_gN_param() function checks that I<g> and I<N> are valid
+SRP group parameters from RFC 5054 appendix A.
+
+The SRP_get_default_gN() function returns the gN parameters for the RFC 5054 I<id>
+SRP group size.
+The known ids are "1024", "1536", "2048", "3072", "4096", "6144" and "8192".
+
+=head1 RETURN VALUES
+
+SRP_create_verifier_BN_ex() and SRP_create_verifier_BN() return 1 on success and
+0 on failure.
+
+SRP_create_verifier_ex() and SRP_create_verifier() return NULL on failure and a
+non-NULL value on success:
+"*" if I<N> is not NULL, the selected group id otherwise. This value should
+not be freed.
+
+SRP_check_known_gN_param() returns the text representation of the group id
+(i.e. the prime bit size) or NULL if the arguments are not valid SRP group parameters.
+This value should not be freed.
+
+SRP_get_default_gN() returns NULL if I<id> is not a valid group size,
+or the 8192-bit group parameters if I<id> is NULL.
+
+=head1 EXAMPLES
+
+Generate and store a 8192 bit password verifier (error handling
+omitted for clarity):
+
+ #include <openssl/bn.h>
+ #include <openssl/srp.h>
+
+ const char *username = "username";
+ const char *password = "password";
+
+ SRP_VBASE *srpData = SRP_VBASE_new(NULL);
+
+ SRP_gN *gN = SRP_get_default_gN("8192");
+
+ BIGNUM *salt = NULL, *verifier = NULL;
+ SRP_create_verifier_BN_ex(username, password, &salt, &verifier, gN->N, gN->g,
+ NULL, NULL);
+
+ SRP_user_pwd *pwd = SRP_user_pwd_new();
+ SRP_user_pwd_set1_ids(pwd, username, NULL);
+ SRP_user_pwd_set0_sv(pwd, salt, verifier);
+ SRP_user_pwd_set_gN(pwd, gN->g, gN->N);
+
+ SRP_VBASE_add0_user(srpData, pwd);
+
+=head1 SEE ALSO
+
+L<openssl-srp(1)>,
+L<SRP_VBASE_new(3)>,
+L<SRP_user_pwd_new(3)>
+
+=head1 HISTORY
+
+SRP_create_verifier_BN_ex() and SRP_create_verifier_ex() were introduced in
+OpenSSL 3.0. All other functions were added in OpenSSL 1.0.1.
+
+All of these functions were deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/SRP_user_pwd_new.pod b/doc/man3/SRP_user_pwd_new.pod
new file mode 100644
index 000000000000..405ece0d7ab9
--- /dev/null
+++ b/doc/man3/SRP_user_pwd_new.pod
@@ -0,0 +1,77 @@
+=pod
+
+=head1 NAME
+
+SRP_user_pwd_new,
+SRP_user_pwd_free,
+SRP_user_pwd_set1_ids,
+SRP_user_pwd_set_gN,
+SRP_user_pwd_set0_sv
+- Functions to create a record of SRP user verifier information
+
+=head1 SYNOPSIS
+
+ #include <openssl/srp.h>
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ SRP_user_pwd *SRP_user_pwd_new(void);
+ void SRP_user_pwd_free(SRP_user_pwd *user_pwd);
+
+ int SRP_user_pwd_set1_ids(SRP_user_pwd *user_pwd, const char *id, const char *info);
+ void SRP_user_pwd_set_gN(SRP_user_pwd *user_pwd, const BIGNUM *g, const BIGNUM *N);
+ int SRP_user_pwd_set0_sv(SRP_user_pwd *user_pwd, BIGNUM *s, BIGNUM *v);
+
+=head1 DESCRIPTION
+
+All of the functions described on this page are deprecated. There are no
+available replacement functions at this time.
+
+The SRP_user_pwd_new() function allocates a structure to store a user verifier
+record.
+
+The SRP_user_pwd_free() function frees up the B<user_pwd> structure.
+If B<user_pwd> is NULL, nothing is done.
+
+The SRP_user_pwd_set1_ids() function sets the username to B<id> and the optional
+user info to B<info> for B<user_pwd>.
+The library allocates new copies of B<id> and B<info>, the caller still
+owns the original memory.
+
+The SRP_user_pwd_set0_sv() function sets the user salt to B<s> and the verifier
+to B<v> for B<user_pwd>.
+The library takes ownership of the values, they should not be freed by the caller.
+
+The SRP_user_pwd_set_gN() function sets the SRP group parameters for B<user_pwd>.
+The memory is not freed by SRP_user_pwd_free(), the caller must make sure it is
+freed once it is no longer used.
+
+=head1 RETURN VALUES
+
+SRP_user_pwd_set1_ids() returns 1 on success and 0 on failure or if B<id> was NULL.
+
+SRP_user_pwd_set0_sv() returns 1 if both B<s> and B<v> are not NULL, 0 otherwise.
+
+=head1 SEE ALSO
+
+L<openssl-srp(1)>,
+L<SRP_create_verifier(3)>,
+L<SRP_VBASE_new(3)>,
+L<SSL_CTX_set_srp_password(3)>
+
+=head1 HISTORY
+
+These functions were made public in OpenSSL 3.0 and are deprecated.
+
+=head1 COPYRIGHT
+
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/SSL_CIPHER_get_name.pod b/doc/man3/SSL_CIPHER_get_name.pod
index 26edae3d80be..e22a85a06370 100644
--- a/doc/man3/SSL_CIPHER_get_name.pod
+++ b/doc/man3/SSL_CIPHER_get_name.pod
@@ -27,7 +27,7 @@ SSL_CIPHER_get_protocol_id
const char *SSL_CIPHER_standard_name(const SSL_CIPHER *cipher);
const char *OPENSSL_cipher_name(const char *stdname);
int SSL_CIPHER_get_bits(const SSL_CIPHER *cipher, int *alg_bits);
- char *SSL_CIPHER_get_version(const SSL_CIPHER *cipher);
+ const char *SSL_CIPHER_get_version(const SSL_CIPHER *cipher);
char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int size);
int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *c);
int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *c);
@@ -157,7 +157,7 @@ Some examples for the output of SSL_CIPHER_description():
SSL_CIPHER_get_name(), SSL_CIPHER_standard_name(), OPENSSL_cipher_name(),
SSL_CIPHER_get_version() and SSL_CIPHER_description() return the corresponding
-value in a null-terminated string for a specific cipher or "(NONE)"
+value in a NUL-terminated string for a specific cipher or "(NONE)"
if the cipher is not found.
SSL_CIPHER_get_bits() returns a positive integer representing the number of
@@ -183,7 +183,7 @@ protocol-specific ID.
=head1 SEE ALSO
L<ssl(7)>, L<SSL_get_current_cipher(3)>,
-L<SSL_get_ciphers(3)>, L<ciphers(1)>
+L<SSL_get_ciphers(3)>, L<openssl-ciphers(1)>
=head1 HISTORY
@@ -203,9 +203,9 @@ The OPENSSL_cipher_name() function was added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_COMP_add_compression_method.pod b/doc/man3/SSL_COMP_add_compression_method.pod
index 76c036e5ce44..924553805eea 100644
--- a/doc/man3/SSL_COMP_add_compression_method.pod
+++ b/doc/man3/SSL_COMP_add_compression_method.pod
@@ -15,11 +15,11 @@ SSL_COMP_get0_name, SSL_COMP_get_id, SSL_COMP_free_compression_methods
const char *SSL_COMP_get0_name(const SSL_COMP *comp);
int SSL_COMP_get_id(const SSL_COMP *comp);
-Deprecated:
+The following function has been deprecated since OpenSSL 1.1.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
- #if OPENSSL_API_COMPAT < 0x10100000L
- void SSL_COMP_free_compression_methods(void)
- #endif
+ void SSL_COMP_free_compression_methods(void);
=head1 DESCRIPTION
@@ -96,9 +96,9 @@ The SSL_COMP_get0_name() and SSL_comp_get_id() functions were added in OpenSSL 1
=head1 COPYRIGHT
-Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CONF_CTX_new.pod b/doc/man3/SSL_CONF_CTX_new.pod
index df5492f79ba8..be5766189f46 100644
--- a/doc/man3/SSL_CONF_CTX_new.pod
+++ b/doc/man3/SSL_CONF_CTX_new.pod
@@ -28,6 +28,7 @@ SSL_CONF_CTX_free() does not return a value.
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_CONF_CTX_set_flags(3)>,
L<SSL_CONF_CTX_set_ssl_ctx(3)>,
L<SSL_CONF_CTX_set1_prefix(3)>,
@@ -42,7 +43,7 @@ These functions were added in OpenSSL 1.0.2.
Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CONF_CTX_set1_prefix.pod b/doc/man3/SSL_CONF_CTX_set1_prefix.pod
index b2eff5bf519f..a5d5454ef093 100644
--- a/doc/man3/SSL_CONF_CTX_set1_prefix.pod
+++ b/doc/man3/SSL_CONF_CTX_set1_prefix.pod
@@ -36,6 +36,7 @@ SSL_CONF_CTX_set1_prefix() returns 1 for success and 0 for failure.
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_CONF_CTX_new(3)>,
L<SSL_CONF_CTX_set_flags(3)>,
L<SSL_CONF_CTX_set_ssl_ctx(3)>,
@@ -50,7 +51,7 @@ These functions were added in OpenSSL 1.0.2.
Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CONF_CTX_set_flags.pod b/doc/man3/SSL_CONF_CTX_set_flags.pod
index d6f6ff589758..78c3ce7585dc 100644
--- a/doc/man3/SSL_CONF_CTX_set_flags.pod
+++ b/doc/man3/SSL_CONF_CTX_set_flags.pod
@@ -62,6 +62,7 @@ value after setting or clearing flags.
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_CONF_CTX_new(3)>,
L<SSL_CONF_CTX_set_ssl_ctx(3)>,
L<SSL_CONF_CTX_set1_prefix(3)>,
@@ -76,7 +77,7 @@ These functions were added in OpenSSL 1.0.2.
Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CONF_CTX_set_ssl_ctx.pod b/doc/man3/SSL_CONF_CTX_set_ssl_ctx.pod
index 3b001d1686f4..06cc1e4ec539 100644
--- a/doc/man3/SSL_CONF_CTX_set_ssl_ctx.pod
+++ b/doc/man3/SSL_CONF_CTX_set_ssl_ctx.pod
@@ -34,6 +34,7 @@ SSL_CONF_CTX_set_ssl_ctx() and SSL_CTX_set_ssl() do not return a value.
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_CONF_CTX_new(3)>,
L<SSL_CONF_CTX_set_flags(3)>,
L<SSL_CONF_CTX_set1_prefix(3)>,
@@ -48,7 +49,7 @@ These functions were added in OpenSSL 1.0.2.
Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CONF_cmd.pod b/doc/man3/SSL_CONF_cmd.pod
index 7f0e08868725..ae6ca432829e 100644
--- a/doc/man3/SSL_CONF_cmd.pod
+++ b/doc/man3/SSL_CONF_cmd.pod
@@ -9,142 +9,179 @@ SSL_CONF_cmd - send configuration command
#include <openssl/ssl.h>
- int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value);
- int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd);
+ int SSL_CONF_cmd(SSL_CONF_CTX *ctx, const char *option, const char *value);
+ int SSL_CONF_cmd_value_type(SSL_CONF_CTX *ctx, const char *option);
=head1 DESCRIPTION
-The function SSL_CONF_cmd() performs configuration operation B<cmd> with
+The function SSL_CONF_cmd() performs configuration operation B<option> with
optional parameter B<value> on B<ctx>. Its purpose is to simplify application
configuration of B<SSL_CTX> or B<SSL> structures by providing a common
framework for command line options or configuration files.
-SSL_CONF_cmd_value_type() returns the type of value that B<cmd> refers to.
+SSL_CONF_cmd_value_type() returns the type of value that B<option> refers to.
=head1 SUPPORTED COMMAND LINE COMMANDS
-Currently supported B<cmd> names for command lines (i.e. when the
-flag B<SSL_CONF_CMDLINE> is set) are listed below. Note: all B<cmd> names
-are case sensitive. Unless otherwise stated commands can be used by
+Currently supported B<option> names for command lines (i.e. when the
+flag B<SSL_CONF_FLAG_CMDLINE> is set) are listed below. Note: all B<option>
+names are case sensitive. Unless otherwise stated commands can be used by
both clients and servers and the B<value> parameter is not used. The default
prefix for command line commands is B<-> and that is reflected below.
=over 4
-=item B<-sigalgs>
+=item B<-bugs>
-This sets the supported signature algorithms for TLSv1.2 and TLSv1.3.
-For clients this
-value is used directly for the supported signature algorithms extension. For
-servers it is used to determine which signature algorithms to support.
+Various bug workarounds are set, same as setting B<SSL_OP_ALL>.
-The B<value> argument should be a colon separated list of signature algorithms
-in order of decreasing preference of the form B<algorithm+hash> or
-B<signature_scheme>. B<algorithm>
-is one of B<RSA>, B<DSA> or B<ECDSA> and B<hash> is a supported algorithm
-OID short name such as B<SHA1>, B<SHA224>, B<SHA256>, B<SHA384> of B<SHA512>.
-Note: algorithm and hash names are case sensitive.
-B<signature_scheme> is one of the signature schemes defined in TLSv1.3,
-specified using the IETF name, e.g., B<ecdsa_secp256r1_sha256>, B<ed25519>,
-or B<rsa_pss_pss_sha256>.
+=item B<-no_comp>
-If this option is not set then all signature algorithms supported by the
-OpenSSL library are permissible.
+Disables support for SSL/TLS compression, same as setting
+B<SSL_OP_NO_COMPRESSION>.
+As of OpenSSL 1.1.0, compression is off by default.
-Note: algorithms which specify a PKCS#1 v1.5 signature scheme (either by
-using B<RSA> as the B<algorithm> or by using one of the B<rsa_pkcs1_*>
-identifiers) are ignored in TLSv1.3 and will not be negotiated.
+=item B<-comp>
-=item B<-client_sigalgs>
+Enables support for SSL/TLS compression, same as clearing
+B<SSL_OP_NO_COMPRESSION>.
+This command was introduced in OpenSSL 1.1.0.
+As of OpenSSL 1.1.0, compression is off by default.
-This sets the supported signature algorithms associated with client
-authentication for TLSv1.2 and TLSv1.3.
-For servers the value is used in the
-B<signature_algorithms> field of a B<CertificateRequest> message.
-For clients it is
-used to determine which signature algorithm to use with the client certificate.
-If a server does not request a certificate this option has no effect.
+=item B<-no_ticket>
-The syntax of B<value> is identical to B<-sigalgs>. If not set then
-the value set for B<-sigalgs> will be used instead.
+Disables support for session tickets, same as setting B<SSL_OP_NO_TICKET>.
-=item B<-groups>
+=item B<-serverpref>
-This sets the supported groups. For clients, the groups are
-sent using the supported groups extension. For servers, it is used
-to determine which group to use. This setting affects groups used for
-signatures (in TLSv1.2 and earlier) and key exchange. The first group listed
-will also be used for the B<key_share> sent by a client in a TLSv1.3
-B<ClientHello>.
+Use server and not client preference order when determining which cipher suite,
+signature algorithm or elliptic curve to use for an incoming connection.
+Equivalent to B<SSL_OP_CIPHER_SERVER_PREFERENCE>. Only used by servers.
-The B<value> argument is a colon separated list of groups. The group can be
-either the B<NIST> name (e.g. B<P-256>), some other commonly used name where
-applicable (e.g. B<X25519>) or an OpenSSL OID name (e.g. B<prime256v1>). Group
-names are case sensitive. The list should be in order of preference with the
-most preferred group first.
+=item B<-client_renegotiation>
-=item B<-curves>
+Allows servers to accept client-initiated renegotiation. Equivalent to
+setting B<SSL_OP_ALLOW_CLIENT_RENEGOTIATION>.
+Only used by servers.
-This is a synonym for the "-groups" command.
+=item B<-legacy_renegotiation>
-=item B<-named_curve>
+Permits the use of unsafe legacy renegotiation. Equivalent to setting
+B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION>.
-This sets the temporary curve used for ephemeral ECDH modes. Only used by
-servers
+=item B<-no_renegotiation>
-The B<value> argument is a curve name or the special value B<auto> which
-picks an appropriate curve based on client and server preferences. The curve
-can be either the B<NIST> name (e.g. B<P-256>) or an OpenSSL OID name
-(e.g. B<prime256v1>). Curve names are case sensitive.
+Disables all attempts at renegotiation in TLSv1.2 and earlier, same as setting
+B<SSL_OP_NO_RENEGOTIATION>.
-=item B<-cipher>
+=item B<-no_resumption_on_reneg>
-Sets the TLSv1.2 and below ciphersuite list to B<value>. This list will be
-combined with any configured TLSv1.3 ciphersuites. Note: syntax checking
-of B<value> is currently not performed unless a B<SSL> or B<SSL_CTX> structure is
-associated with B<cctx>.
+Sets B<SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION>. Only used by servers.
-=item B<-ciphersuites>
+=item B<-legacy_server_connect>, B<-no_legacy_server_connect>
-Sets the available ciphersuites for TLSv1.3 to value. This is a simple colon
-(":") separated list of TLSv1.3 ciphersuite names in order of preference. This
-list will be combined any configured TLSv1.2 and below ciphersuites.
-See L<ciphers(1)> for more information.
+Permits or prohibits the use of unsafe legacy renegotiation for OpenSSL
+clients only. Equivalent to setting or clearing B<SSL_OP_LEGACY_SERVER_CONNECT>.
+=item B<-prioritize_chacha>
-=item B<-cert>
+Prioritize ChaCha ciphers when the client has a ChaCha20 cipher at the top of
+its preference list. This usually indicates a client without AES hardware
+acceleration (e.g. mobile) is in use. Equivalent to B<SSL_OP_PRIORITIZE_CHACHA>.
+Only used by servers. Requires B<-serverpref>.
-Attempts to use the file B<value> as the certificate for the appropriate
-context. It currently uses SSL_CTX_use_certificate_chain_file() if an B<SSL_CTX>
-structure is set or SSL_use_certificate_file() with filetype PEM if an B<SSL>
-structure is set. This option is only supported if certificate operations
-are permitted.
+=item B<-allow_no_dhe_kex>
-=item B<-key>
+In TLSv1.3 allow a non-(ec)dhe based key exchange mode on resumption. This means
+that there will be no forward secrecy for the resumed session.
-Attempts to use the file B<value> as the private key for the appropriate
-context. This option is only supported if certificate operations
-are permitted. Note: if no B<-key> option is set then a private key is
-not loaded unless the flag B<SSL_CONF_FLAG_REQUIRE_PRIVATE> is set.
+=item B<-strict>
-=item B<-dhparam>
+Enables strict mode protocol handling. Equivalent to setting
+B<SSL_CERT_FLAG_TLS_STRICT>.
-Attempts to use the file B<value> as the set of temporary DH parameters for
-the appropriate context. This option is only supported if certificate
-operations are permitted.
+=item B<-sigalgs> I<algs>
-=item B<-record_padding>
+This sets the supported signature algorithms for TLSv1.2 and TLSv1.3.
+For clients this value is used directly for the supported signature
+algorithms extension. For servers it is used to determine which signature
+algorithms to support.
+
+The B<algs> argument should be a colon separated list of signature
+algorithms in order of decreasing preference of the form B<algorithm+hash>
+or B<signature_scheme>. B<algorithm> is one of B<RSA>, B<DSA> or B<ECDSA> and
+B<hash> is a supported algorithm OID short name such as B<SHA1>, B<SHA224>,
+B<SHA256>, B<SHA384> of B<SHA512>. Note: algorithm and hash names are case
+sensitive. B<signature_scheme> is one of the signature schemes defined in
+TLSv1.3, specified using the IETF name, e.g., B<ecdsa_secp256r1_sha256>,
+B<ed25519>, or B<rsa_pss_pss_sha256>.
-Attempts to pad TLSv1.3 records so that they are a multiple of B<value> in
-length on send. A B<value> of 0 or 1 turns off padding. Otherwise, the
-B<value> must be >1 or <=16384.
+If this option is not set then all signature algorithms supported by the
+OpenSSL library are permissible.
-=item B<-no_renegotiation>
+Note: algorithms which specify a PKCS#1 v1.5 signature scheme (either by
+using B<RSA> as the B<algorithm> or by using one of the B<rsa_pkcs1_*>
+identifiers) are ignored in TLSv1.3 and will not be negotiated.
-Disables all attempts at renegotiation in TLSv1.2 and earlier, same as setting
-B<SSL_OP_NO_RENEGOTIATION>.
+=item B<-client_sigalgs> I<algs>
+
+This sets the supported signature algorithms associated with client
+authentication for TLSv1.2 and TLSv1.3. For servers the B<algs> is used
+in the B<signature_algorithms> field of a B<CertificateRequest> message.
+For clients it is used to determine which signature algorithm to use with
+the client certificate. If a server does not request a certificate this
+option has no effect.
+
+The syntax of B<algs> is identical to B<-sigalgs>. If not set, then the
+value set for B<-sigalgs> will be used instead.
+
+=item B<-groups> I<groups>
+
+This sets the supported groups. For clients, the groups are sent using
+the supported groups extension. For servers, it is used to determine which
+group to use. This setting affects groups used for signatures (in TLSv1.2
+and earlier) and key exchange. The first group listed will also be used
+for the B<key_share> sent by a client in a TLSv1.3 B<ClientHello>.
+
+The B<groups> argument is a colon separated list of groups. The group can
+be either the B<NIST> name (e.g. B<P-256>), some other commonly used name
+where applicable (e.g. B<X25519>, B<ffdhe2048>) or an OpenSSL OID name
+(e.g. B<prime256v1>). Group names are case sensitive. The list should be
+in order of preference with the most preferred group first.
+
+Currently supported groups for B<TLSv1.3> are B<P-256>, B<P-384>, B<P-521>,
+B<X25519>, B<X448>, B<ffdhe2048>, B<ffdhe3072>, B<ffdhe4096>, B<ffdhe6144>,
+B<ffdhe8192>.
+
+=item B<-curves> I<groups>
+
+This is a synonym for the B<-groups> command.
+
+=item B<-named_curve> I<curve>
+
+This sets the temporary curve used for ephemeral ECDH modes. Only used
+by servers.
+
+The B<groups> argument is a curve name or the special value B<auto> which
+picks an appropriate curve based on client and server preferences. The
+curve can be either the B<NIST> name (e.g. B<P-256>) or an OpenSSL OID name
+(e.g. B<prime256v1>). Curve names are case sensitive.
+
+=item B<-cipher> I<ciphers>
+
+Sets the TLSv1.2 and below ciphersuite list to B<ciphers>. This list will be
+combined with any configured TLSv1.3 ciphersuites. Note: syntax checking
+of B<ciphers> is currently not performed unless a B<SSL> or B<SSL_CTX>
+structure is associated with B<ctx>.
+
+=item B<-ciphersuites> I<1.3ciphers>
-=item B<-min_protocol>, B<-max_protocol>
+Sets the available ciphersuites for TLSv1.3 to value. This is a
+colon-separated list of TLSv1.3 ciphersuite names in order of preference. This
+list will be combined any configured TLSv1.2 and below ciphersuites.
+See L<openssl-ciphers(1)> for more information.
+
+=item B<-min_protocol> I<minprot>, B<-max_protocol> I<maxprot>
Sets the minimum and maximum supported protocol.
Currently supported protocol values are B<SSLv3>, B<TLSv1>, B<TLSv1.1>,
@@ -158,72 +195,57 @@ for DTLS.
To restrict the supported protocol versions use these commands rather than the
deprecated alternative commands below.
-=item B<-no_ssl3>, B<-no_tls1>, B<-no_tls1_1>, B<-no_tls1_2>, B<-no_tls1_3>
+=item B<-record_padding> I<padding>
-Disables protocol support for SSLv3, TLSv1.0, TLSv1.1, TLSv1.2 or TLSv1.3 by
-setting the corresponding options B<SSL_OP_NO_SSLv3>, B<SSL_OP_NO_TLSv1>,
-B<SSL_OP_NO_TLSv1_1>, B<SSL_OP_NO_TLSv1_2> and B<SSL_OP_NO_TLSv1_3>
-respectively. These options are deprecated, instead use B<-min_protocol> and
-B<-max_protocol>.
+Attempts to pad TLSv1.3 records so that they are a multiple of B<padding>
+in length on send. A B<padding> of 0 or 1 turns off padding. Otherwise,
+the B<padding> must be >1 or <=16384.
-=item B<-bugs>
+=item B<-debug_broken_protocol>
-Various bug workarounds are set, same as setting B<SSL_OP_ALL>.
+Ignored.
-=item B<-comp>
-
-Enables support for SSL/TLS compression, same as clearing
-B<SSL_OP_NO_COMPRESSION>.
-This command was introduced in OpenSSL 1.1.0.
-As of OpenSSL 1.1.0, compression is off by default.
+=item B<-no_middlebox>
-=item B<-no_comp>
+Turn off "middlebox compatibility", as described below.
-Disables support for SSL/TLS compression, same as setting
-B<SSL_OP_NO_COMPRESSION>.
-As of OpenSSL 1.1.0, compression is off by default.
-
-=item B<-no_ticket>
-
-Disables support for session tickets, same as setting B<SSL_OP_NO_TICKET>.
-
-=item B<-serverpref>
-
-Use server and not client preference order when determining which cipher suite,
-signature algorithm or elliptic curve to use for an incoming connection.
-Equivalent to B<SSL_OP_CIPHER_SERVER_PREFERENCE>. Only used by servers.
-
-=item B<-prioritize_chacha>
+=back
-Prioritize ChaCha ciphers when the client has a ChaCha20 cipher at the top of
-its preference list. This usually indicates a client without AES hardware
-acceleration (e.g. mobile) is in use. Equivalent to B<SSL_OP_PRIORITIZE_CHACHA>.
-Only used by servers. Requires B<-serverpref>.
+=head2 Additional Options
-=item B<-no_resumption_on_reneg>
+The following options are accepted by SSL_CONF_cmd(), but are not
+processed by the OpenSSL commands.
-set SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION flag. Only used by servers.
+=over 4
-=item B<-legacyrenegotiation>
+=item B<-cert> I<file>
-permits the use of unsafe legacy renegotiation. Equivalent to setting
-B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION>.
+Attempts to use B<file> as the certificate for the appropriate context. It
+currently uses SSL_CTX_use_certificate_chain_file() if an B<SSL_CTX>
+structure is set or SSL_use_certificate_file() with filetype PEM if an
+B<SSL> structure is set. This option is only supported if certificate
+operations are permitted.
-=item B<-legacy_server_connect>, B<-no_legacy_server_connect>
+=item B<-key> I<file>
-permits or prohibits the use of unsafe legacy renegotiation for OpenSSL
-clients only. Equivalent to setting or clearing B<SSL_OP_LEGACY_SERVER_CONNECT>.
-Set by default.
+Attempts to use B<file> as the private key for the appropriate context. This
+option is only supported if certificate operations are permitted. Note:
+if no B<-key> option is set then a private key is not loaded unless the
+flag B<SSL_CONF_FLAG_REQUIRE_PRIVATE> is set.
-=item B<-allow_no_dhe_kex>
+=item B<-dhparam> I<file>
-In TLSv1.3 allow a non-(ec)dhe based key exchange mode on resumption. This means
-that there will be no forward secrecy for the resumed session.
+Attempts to use B<file> as the set of temporary DH parameters for
+the appropriate context. This option is only supported if certificate
+operations are permitted.
-=item B<-strict>
+=item B<-no_ssl3>, B<-no_tls1>, B<-no_tls1_1>, B<-no_tls1_2>, B<-no_tls1_3>
-enables strict mode protocol handling. Equivalent to setting
-B<SSL_CERT_FLAG_TLS_STRICT>.
+Disables protocol support for SSLv3, TLSv1.0, TLSv1.1, TLSv1.2 or TLSv1.3 by
+setting the corresponding options B<SSL_OP_NO_SSLv3>, B<SSL_OP_NO_TLSv1>,
+B<SSL_OP_NO_TLSv1_1>, B<SSL_OP_NO_TLSv1_2> and B<SSL_OP_NO_TLSv1_3>
+respectively. These options are deprecated, use B<-min_protocol> and
+B<-max_protocol> instead.
=item B<-anti_replay>, B<-no_anti_replay>
@@ -241,13 +263,13 @@ required. Switching off anti-replay is equivalent to B<SSL_OP_NO_ANTI_REPLAY>.
=head1 SUPPORTED CONFIGURATION FILE COMMANDS
-Currently supported B<cmd> names for configuration files (i.e. when the
+Currently supported B<option> names for configuration files (i.e., when the
flag B<SSL_CONF_FLAG_FILE> is set) are listed below. All configuration file
-B<cmd> names are case insensitive so B<signaturealgorithms> is recognised
+B<option> names are case insensitive so B<signaturealgorithms> is recognised
as well as B<SignatureAlgorithms>. Unless otherwise stated the B<value> names
are also case insensitive.
-Note: the command prefix (if set) alters the recognised B<cmd> values.
+Note: the command prefix (if set) alters the recognised B<option> values.
=over 4
@@ -256,14 +278,14 @@ Note: the command prefix (if set) alters the recognised B<cmd> values.
Sets the ciphersuite list for TLSv1.2 and below to B<value>. This list will be
combined with any configured TLSv1.3 ciphersuites. Note: syntax
checking of B<value> is currently not performed unless an B<SSL> or B<SSL_CTX>
-structure is associated with B<cctx>.
+structure is associated with B<ctx>.
=item B<Ciphersuites>
-Sets the available ciphersuites for TLSv1.3 to B<value>. This is a simple colon
-(":") separated list of TLSv1.3 ciphersuite names in order of preference. This
+Sets the available ciphersuites for TLSv1.3 to B<value>. This is a
+colon-separated list of TLSv1.3 ciphersuite names in order of preference. This
list will be combined any configured TLSv1.2 and below ciphersuites.
-See L<ciphers(1)> for more information.
+See L<openssl-ciphers(1)> for more information.
=item B<Certificate>
@@ -359,9 +381,13 @@ B<ClientHello>.
The B<value> argument is a colon separated list of groups. The group can be
either the B<NIST> name (e.g. B<P-256>), some other commonly used name where
-applicable (e.g. B<X25519>) or an OpenSSL OID name (e.g. B<prime256v1>). Group
-names are case sensitive. The list should be in order of preference with the
-most preferred group first.
+applicable (e.g. B<X25519>, B<ffdhe2048>) or an OpenSSL OID name
+(e.g. B<prime256v1>). Group names are case sensitive. The list should be in
+order of preference with the most preferred group first.
+
+Currently supported groups for B<TLSv1.3> are B<P-256>, B<P-384>, B<P-521>,
+B<X25519>, B<X448>, B<ffdhe2048>, B<ffdhe3072>, B<ffdhe4096>, B<ffdhe6144>,
+B<ffdhe8192>.
=item B<Curves>
@@ -470,7 +496,6 @@ Equivalent to B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION>.
B<UnsafeLegacyServerConnect>: permits the use of unsafe legacy renegotiation
for OpenSSL clients only. Equivalent to B<SSL_OP_LEGACY_SERVER_CONNECT>.
-Set by default.
B<EncryptThenMac>: use encrypt-then-mac extension, enabled by
default. Inverse of B<SSL_OP_NO_ENCRYPT_THEN_MAC>: that is,
@@ -495,6 +520,18 @@ specification. Some applications may be able to mitigate the replay risks in
other ways and in such cases the built-in OpenSSL functionality is not required.
Disabling anti-replay is equivalent to setting B<SSL_OP_NO_ANTI_REPLAY>.
+B<ExtendedMasterSecret>: use extended master secret extension, enabled by
+default. Inverse of B<SSL_OP_NO_EXTENDED_MASTER_SECRET>: that is,
+B<-ExtendedMasterSecret> is the same as setting B<SSL_OP_NO_EXTENDED_MASTER_SECRET>.
+
+B<CANames>: use CA names extension, enabled by
+default. Inverse of B<SSL_OP_DISABLE_TLSEXT_CA_NAMES>: that is,
+B<-CANames> is the same as setting B<SSL_OP_DISABLE_TLSEXT_CA_NAMES>.
+
+B<KTLS>: Enables kernel TLS if support has been compiled in, and it is supported
+by the negotiated ciphersuites and extensions. Equivalent to
+B<SSL_OP_ENABLE_KTLS>.
+
=item B<VerifyMode>
The B<value> argument is a comma separated list of flags to set.
@@ -539,7 +576,7 @@ types:
=item B<SSL_CONF_TYPE_UNKNOWN>
-The B<cmd> string is unrecognised, this return value can be use to flag
+The B<option> string is unrecognised, this return value can be use to flag
syntax errors.
=item B<SSL_CONF_TYPE_STRING>
@@ -579,7 +616,7 @@ SSLv3 is B<always> disabled and attempt to override this by the user are
ignored.
By checking the return code of SSL_CONF_cmd() it is possible to query if a
-given B<cmd> is recognised, this is useful if SSL_CONF_cmd() values are
+given B<option> is recognised, this is useful if SSL_CONF_cmd() values are
mixed with additional application specific operations.
For example an application might call SSL_CONF_cmd() and if it returns
@@ -589,12 +626,12 @@ commands.
Applications can also use SSL_CONF_cmd() to process command lines though the
utility function SSL_CONF_cmd_argv() is normally used instead. One way
to do this is to set the prefix to an appropriate value using
-SSL_CONF_CTX_set1_prefix(), pass the current argument to B<cmd> and the
+SSL_CONF_CTX_set1_prefix(), pass the current argument to B<option> and the
following argument to B<value> (which may be NULL).
In this case if the return value is positive then it is used to skip that
number of arguments as they have been processed by SSL_CONF_cmd(). If -2 is
-returned then B<cmd> is not recognised and application specific arguments
+returned then B<option> is not recognised and application specific arguments
can be checked instead. If -3 is returned a required argument is missing
and an error is indicated. If 0 is returned some other error occurred and
this can be reported back to the user.
@@ -607,17 +644,17 @@ pathname to an absolute pathname.
=head1 RETURN VALUES
-SSL_CONF_cmd() returns 1 if the value of B<cmd> is recognised and B<value> is
-B<NOT> used and 2 if both B<cmd> and B<value> are used. In other words it
+SSL_CONF_cmd() returns 1 if the value of B<option> is recognised and B<value> is
+B<NOT> used and 2 if both B<option> and B<value> are used. In other words it
returns the number of arguments processed. This is useful when processing
command lines.
-A return value of -2 means B<cmd> is not recognised.
+A return value of -2 means B<option> is not recognised.
-A return value of -3 means B<cmd> is recognised and the command requires a
+A return value of -3 means B<option> is recognised and the command requires a
value but B<value> is NULL.
-A return code of 0 indicates that both B<cmd> and B<value> are valid but an
+A return code of 0 indicates that both B<option> and B<value> are valid but an
error occurred attempting to perform the operation: for example due to an
error in the syntax of B<value> in this case the error queue may provide
additional information.
@@ -670,6 +707,7 @@ Set supported curves to P-256, P-384:
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_CONF_CTX_new(3)>,
L<SSL_CONF_CTX_set_flags(3)>,
L<SSL_CONF_CTX_set1_prefix(3)>,
@@ -692,11 +730,14 @@ B<MinProtocol> and B<MaxProtocol> where added in OpenSSL 1.1.0.
B<AllowNoDHEKEX> and B<PrioritizeChaCha> were added in OpenSSL 1.1.1.
+The B<UnsafeLegacyServerConnect> option is no longer set by default from
+OpenSSL 3.0.
+
=head1 COPYRIGHT
Copyright 2012-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CONF_cmd_argv.pod b/doc/man3/SSL_CONF_cmd_argv.pod
index 130814803d86..7e694e1aab32 100644
--- a/doc/man3/SSL_CONF_cmd_argv.pod
+++ b/doc/man3/SSL_CONF_cmd_argv.pod
@@ -29,6 +29,7 @@ to an error: for example a syntax error in the argument.
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_CONF_CTX_new(3)>,
L<SSL_CONF_CTX_set_flags(3)>,
L<SSL_CONF_CTX_set1_prefix(3)>,
@@ -43,7 +44,7 @@ These functions were added in OpenSSL 1.0.2.
Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_add1_chain_cert.pod b/doc/man3/SSL_CTX_add1_chain_cert.pod
index 8fe8a7d5e18e..10afc71dc9b6 100644
--- a/doc/man3/SSL_CTX_add1_chain_cert.pod
+++ b/doc/man3/SSL_CTX_add1_chain_cert.pod
@@ -52,8 +52,9 @@ SSL_CTX_clear_chain_certs() clears any existing chain associated with the
current certificate of B<ctx>. (This is implemented by calling
SSL_CTX_set0_chain() with B<sk> set to B<NULL>).
-SSL_CTX_build_cert_chain() builds the certificate chain for B<ctx> normally
-this uses the chain store or the verify store if the chain store is not set.
+SSL_CTX_build_cert_chain() builds the certificate chain for B<ctx>.
+Normally this uses the chain store
+or the verify store if the chain store is not set.
If the function is successful the built chain will replace any existing chain.
The B<flags> parameter can be set to B<SSL_BUILD_CHAIN_FLAG_UNTRUSTED> to use
existing chain certificates as untrusted CAs, B<SSL_BUILD_CHAIN_FLAG_NO_ROOT>
@@ -63,6 +64,8 @@ sanity checking and rearranging them if necessary), the flag
B<SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR> ignores any errors during verification:
if flag B<SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR> is also set verification errors
are cleared from the error queue.
+Details of the chain building process are described in
+L<openssl-verification-options(1)/Certification Path Building>.
Each of these functions operates on the I<current> end entity
(i.e. server or client) certificate. This is the last certificate loaded or
@@ -140,6 +143,7 @@ All other functions return 1 for success and 0 for failure.
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_CTX_add_extra_chain_cert(3)>
=head1 HISTORY
@@ -148,9 +152,9 @@ These functions were added in OpenSSL 1.0.2.
=head1 COPYRIGHT
-Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_add_extra_chain_cert.pod b/doc/man3/SSL_CTX_add_extra_chain_cert.pod
index 05d17f8b0f67..b1554446ee0f 100644
--- a/doc/man3/SSL_CTX_add_extra_chain_cert.pod
+++ b/doc/man3/SSL_CTX_add_extra_chain_cert.pod
@@ -2,14 +2,19 @@
=head1 NAME
-SSL_CTX_add_extra_chain_cert, SSL_CTX_clear_extra_chain_certs - add or clear
-extra chain certificates
+SSL_CTX_add_extra_chain_cert,
+SSL_CTX_get_extra_chain_certs,
+SSL_CTX_get_extra_chain_certs_only,
+SSL_CTX_clear_extra_chain_certs
+- add, get or clear extra chain certificates
=head1 SYNOPSIS
#include <openssl/ssl.h>
long SSL_CTX_add_extra_chain_cert(SSL_CTX *ctx, X509 *x509);
+ long SSL_CTX_get_extra_chain_certs(SSL_CTX *ctx, STACK_OF(X509) **sk);
+ long SSL_CTX_get_extra_chain_certs_only(SSL_CTX *ctx, STACK_OF(X509) **sk);
long SSL_CTX_clear_extra_chain_certs(SSL_CTX *ctx);
=head1 DESCRIPTION
@@ -18,6 +23,15 @@ SSL_CTX_add_extra_chain_cert() adds the certificate B<x509> to the extra chain
certificates associated with B<ctx>. Several certificates can be added one
after another.
+SSL_CTX_get_extra_chain_certs() retrieves the extra chain certificates
+associated with B<ctx>, or the chain associated with the current certificate
+of B<ctx> if the extra chain is empty.
+The returned stack should not be freed by the caller.
+
+SSL_CTX_get_extra_chain_certs_only() retrieves the extra chain certificates
+associated with B<ctx>.
+The returned stack should not be freed by the caller.
+
SSL_CTX_clear_extra_chain_certs() clears all extra chain certificates
associated with B<ctx>.
@@ -70,9 +84,9 @@ L<SSL_build_cert_chain(3)>
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_add_session.pod b/doc/man3/SSL_CTX_add_session.pod
index d8b115bb0c7f..9943fcf1ca6a 100644
--- a/doc/man3/SSL_CTX_add_session.pod
+++ b/doc/man3/SSL_CTX_add_session.pod
@@ -69,7 +69,7 @@ L<SSL_SESSION_free(3)>
Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_config.pod b/doc/man3/SSL_CTX_config.pod
index 76c4d3238c34..8ddb4a9739aa 100644
--- a/doc/man3/SSL_CTX_config.pod
+++ b/doc/man3/SSL_CTX_config.pod
@@ -16,8 +16,6 @@ SSL_CTX_config, SSL_config - configure SSL_CTX or SSL structure
The functions SSL_CTX_config() and SSL_config() configure an B<SSL_CTX> or
B<SSL> structure using the configuration B<name>.
-=head1 NOTES
-
By calling SSL_CTX_config() or SSL_config() an application can perform many
complex tasks based on the contents of the configuration file: greatly
simplifying application configuration code. A degree of future proofing
@@ -71,6 +69,7 @@ the need for any additional application code.
=head1 SEE ALSO
+L<ssl(7)>,
L<config(5)>,
L<SSL_CONF_cmd(3)>,
L<CONF_modules_load_file(3)>
@@ -81,9 +80,9 @@ The SSL_CTX_config() and SSL_config() functions were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_ctrl.pod b/doc/man3/SSL_CTX_ctrl.pod
index 55fb015e6b82..199a9e029d54 100644
--- a/doc/man3/SSL_CTX_ctrl.pod
+++ b/doc/man3/SSL_CTX_ctrl.pod
@@ -35,7 +35,7 @@ L<ssl(7)>
Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_dane_enable.pod b/doc/man3/SSL_CTX_dane_enable.pod
index 6f9514ae77da..5a3977b70a4f 100644
--- a/doc/man3/SSL_CTX_dane_enable.pod
+++ b/doc/man3/SSL_CTX_dane_enable.pod
@@ -18,10 +18,10 @@ TLS client
uint8_t mtype, uint8_t ord);
int SSL_dane_enable(SSL *s, const char *basedomain);
int SSL_dane_tlsa_add(SSL *s, uint8_t usage, uint8_t selector,
- uint8_t mtype, unsigned const char *data, size_t dlen);
+ uint8_t mtype, const unsigned char *data, size_t dlen);
int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki);
int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector,
- uint8_t *mtype, unsigned const char **data,
+ uint8_t *mtype, const unsigned char **data,
size_t *dlen);
unsigned long SSL_CTX_dane_set_flags(SSL_CTX *ctx, unsigned long flags);
unsigned long SSL_CTX_dane_clear_flags(SSL_CTX *ctx, unsigned long flags);
@@ -136,7 +136,7 @@ SSL_CTX_dane_set_flags() and SSL_dane_set_flags() can be used to enable
optional DANE verification features.
SSL_CTX_dane_clear_flags() and SSL_dane_clear_flags() can be used to disable
the same features.
-The B<flags> argument is a bit mask of the features to enable or disable.
+The B<flags> argument is a bit-mask of the features to enable or disable.
The B<flags> set for an B<SSL_CTX> context are copied to each B<SSL> handle
associated with that context at the time the handle is created.
Subsequent changes in the context's B<flags> have no effect on the B<flags> set
@@ -348,6 +348,7 @@ L<SSL_set_verify(3)> with B<mode> equal to B<SSL_VERIFY_NONE>.
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_new(3)>,
L<SSL_add1_host(3)>,
L<SSL_set_hostflags(3)>,
@@ -372,9 +373,9 @@ These functions were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_flush_sessions.pod b/doc/man3/SSL_CTX_flush_sessions.pod
index c2f010646476..2ab7c883828c 100644
--- a/doc/man3/SSL_CTX_flush_sessions.pod
+++ b/doc/man3/SSL_CTX_flush_sessions.pod
@@ -49,7 +49,7 @@ L<SSL_CTX_sess_set_get_cb(3)>
Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_free.pod b/doc/man3/SSL_CTX_free.pod
index 6b7bf1a81736..b7c270ccded9 100644
--- a/doc/man3/SSL_CTX_free.pod
+++ b/doc/man3/SSL_CTX_free.pod
@@ -43,7 +43,7 @@ L<SSL_CTX_sess_set_get_cb(3)>
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_get0_param.pod b/doc/man3/SSL_CTX_get0_param.pod
index 55cddfded620..d066e747c028 100644
--- a/doc/man3/SSL_CTX_get0_param.pod
+++ b/doc/man3/SSL_CTX_get0_param.pod
@@ -2,17 +2,24 @@
=head1 NAME
-SSL_CTX_get0_param, SSL_get0_param, SSL_CTX_set1_param, SSL_set1_param -
+SSL_CTX_get0_param, SSL_get0_param, SSL_CTX_set1_param, SSL_set1_param,
+SSL_CTX_set_purpose, SSL_CTX_set_trust, SSL_set_purpose, SSL_set_trust -
get and set verification parameters
=head1 SYNOPSIS
#include <openssl/ssl.h>
- X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx)
- X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl)
- int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm)
- int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm)
+ X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx);
+ X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl);
+ int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm);
+ int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm);
+
+ int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose);
+ int SSL_set_purpose(SSL *ssl, int purpose);
+
+ int SSL_CTX_set_trust(SSL_CTX *ctx, int trust);
+ int SSL_set_trust(SSL *ssl, int trust);
=head1 DESCRIPTION
@@ -23,6 +30,14 @@ pointer must not be freed by the calling application.
SSL_CTX_set1_param() and SSL_set1_param() set the verification parameters
to B<vpm> for B<ctx> or B<ssl>.
+The functions SSL_CTX_set_purpose() and SSL_set_purpose() are shorthands which
+set the purpose parameter on the verification parameters object. These functions
+are equivalent to calling X509_VERIFY_PARAM_set_purpose() directly.
+
+The functions SSL_CTX_set_trust() and SSL_set_trust() are similarly shorthands
+which set the trust parameter on the verification parameters object. These
+functions are equivalent to calling X509_VERIFY_PARAM_set_trust() directly.
+
=head1 NOTES
Typically parameters are retrieved from an B<SSL_CTX> or B<SSL> structure
@@ -34,8 +49,9 @@ them to suit its needs: for example to add a hostname check.
SSL_CTX_get0_param() and SSL_get0_param() return a pointer to an
B<X509_VERIFY_PARAM> structure.
-SSL_CTX_set1_param() and SSL_set1_param() return 1 for success and 0
-for failure.
+SSL_CTX_set1_param(), SSL_set1_param(), SSL_CTX_set_purpose(),
+SSL_set_purpose(), SSL_CTX_set_trust() and SSL_set_trust() return 1 for success
+and 0 for failure.
=head1 EXAMPLES
@@ -46,6 +62,7 @@ Check hostname matches "www.foo.com" in peer certificate:
=head1 SEE ALSO
+L<ssl(7)>,
L<X509_VERIFY_PARAM_set_flags(3)>
=head1 HISTORY
@@ -54,9 +71,9 @@ These functions were added in OpenSSL 1.0.2.
=head1 COPYRIGHT
-Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_get_verify_mode.pod b/doc/man3/SSL_CTX_get_verify_mode.pod
index 5f6da9d405bc..a9b307328f49 100644
--- a/doc/man3/SSL_CTX_get_verify_mode.pod
+++ b/doc/man3/SSL_CTX_get_verify_mode.pod
@@ -51,7 +51,7 @@ L<ssl(7)>, L<SSL_CTX_set_verify(3)>
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_has_client_custom_ext.pod b/doc/man3/SSL_CTX_has_client_custom_ext.pod
index b220c5e79b7f..74bca1a0d890 100644
--- a/doc/man3/SSL_CTX_has_client_custom_ext.pod
+++ b/doc/man3/SSL_CTX_has_client_custom_ext.pod
@@ -29,7 +29,7 @@ L<SSL_CTX_add_client_custom_ext(3)>
Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_load_verify_locations.pod b/doc/man3/SSL_CTX_load_verify_locations.pod
index b16271bfaa19..b0dc8babd2d1 100644
--- a/doc/man3/SSL_CTX_load_verify_locations.pod
+++ b/doc/man3/SSL_CTX_load_verify_locations.pod
@@ -2,36 +2,51 @@
=head1 NAME
-SSL_CTX_load_verify_locations, SSL_CTX_set_default_verify_paths,
-SSL_CTX_set_default_verify_dir, SSL_CTX_set_default_verify_file - set
-default locations for trusted CA certificates
+SSL_CTX_load_verify_dir, SSL_CTX_load_verify_file,
+SSL_CTX_load_verify_store, SSL_CTX_set_default_verify_paths,
+SSL_CTX_set_default_verify_dir, SSL_CTX_set_default_verify_file,
+SSL_CTX_set_default_verify_store, SSL_CTX_load_verify_locations
+- set default locations for trusted CA certificates
=head1 SYNOPSIS
#include <openssl/ssl.h>
- int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
- const char *CApath);
+ int SSL_CTX_load_verify_dir(SSL_CTX *ctx, const char *CApath);
+ int SSL_CTX_load_verify_file(SSL_CTX *ctx, const char *CAfile);
+ int SSL_CTX_load_verify_store(SSL_CTX *ctx, const char *CAstore);
int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx);
-
int SSL_CTX_set_default_verify_file(SSL_CTX *ctx);
+ int SSL_CTX_set_default_verify_store(SSL_CTX *ctx);
+
+ int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
+ const char *CApath);
=head1 DESCRIPTION
-SSL_CTX_load_verify_locations() specifies the locations for B<ctx>, at
-which CA certificates for verification purposes are located. The certificates
-available via B<CAfile> and B<CApath> are trusted.
+SSL_CTX_load_verify_locations(), SSL_CTX_load_verify_dir(),
+SSL_CTX_load_verify_file(), SSL_CTX_load_verify_store() specifies the
+locations for B<ctx>, at which CA certificates for verification purposes
+are located. The certificates available via B<CAfile>, B<CApath> and
+B<CAstore> are trusted.
+
+Details of the certificate verification and chain checking process are
+described in L<openssl-verification-options(1)/Certification Path Validation>.
SSL_CTX_set_default_verify_paths() specifies that the default locations from
-which CA certificates are loaded should be used. There is one default directory
-and one default file. The default CA certificates directory is called "certs" in
-the default OpenSSL directory. Alternatively the SSL_CERT_DIR environment
-variable can be defined to override this location. The default CA certificates
-file is called "cert.pem" in the default OpenSSL directory. Alternatively the
-SSL_CERT_FILE environment variable can be defined to override this location.
+which CA certificates are loaded should be used. There is one default directory,
+one default file and one default store.
+The default CA certificates directory is called F<certs> in the default OpenSSL
+directory, and this is also the default store.
+Alternatively the B<SSL_CERT_DIR> environment variable can be defined to
+override this location.
+The default CA certificates file is called F<cert.pem> in the default
+OpenSSL directory.
+Alternatively the B<SSL_CERT_FILE> environment variable can be defined to
+override this location.
SSL_CTX_set_default_verify_dir() is similar to
SSL_CTX_set_default_verify_paths() except that just the default directory is
@@ -41,6 +56,10 @@ SSL_CTX_set_default_verify_file() is similar to
SSL_CTX_set_default_verify_paths() except that just the default file is
used.
+SSL_CTX_set_default_verify_store() is similar to
+SSL_CTX_set_default_verify_paths() except that just the default store is
+used.
+
=head1 NOTES
If B<CAfile> is not NULL, it points to a file of CA certificates in PEM
@@ -69,14 +88,15 @@ The certificates in B<CApath> are only looked up when required, e.g. when
building the certificate chain or when actually performing the verification
of a peer certificate.
-When looking up CA certificates, the OpenSSL library will first search the
-certificates in B<CAfile>, then those in B<CApath>. Certificate matching
-is done based on the subject name, the key identifier (if present), and the
-serial number as taken from the certificate to be verified. If these data
-do not match, the next certificate will be tried. If a first certificate
-matching the parameters is found, the verification process will be performed;
-no other certificates for the same parameters will be searched in case of
-failure.
+When looking up CA certificates for chain building, the OpenSSL library
+will search for suitable certificates first in B<CAfile>, then in B<CApath>.
+Details of the chain building process are described in
+L<openssl-verification-options(1)/Certification Path Building>.
+
+If B<CAstore> is not NULL, it's a URI for to a store, which may
+represent a single container or a whole catalogue of containers.
+Apart from the B<CAstore> not necessarily being a local file or
+directory, it's generally treated the same way as a B<CApath>.
In server mode, when requesting a client certificate, the server must send
the list of CAs of which it will accept client certificates. This list
@@ -151,9 +171,9 @@ L<SSL_CTX_set_client_CA_list(3)>
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_new.pod b/doc/man3/SSL_CTX_new.pod
index a6c036c365ea..61de1a655164 100644
--- a/doc/man3/SSL_CTX_new.pod
+++ b/doc/man3/SSL_CTX_new.pod
@@ -3,13 +3,14 @@
=head1 NAME
TLSv1_2_method, TLSv1_2_server_method, TLSv1_2_client_method,
-SSL_CTX_new, SSL_CTX_up_ref, SSLv3_method, SSLv3_server_method,
-SSLv3_client_method, TLSv1_method, TLSv1_server_method, TLSv1_client_method,
-TLSv1_1_method, TLSv1_1_server_method, TLSv1_1_client_method, TLS_method,
-TLS_server_method, TLS_client_method, SSLv23_method, SSLv23_server_method,
-SSLv23_client_method, DTLS_method, DTLS_server_method, DTLS_client_method,
-DTLSv1_method, DTLSv1_server_method, DTLSv1_client_method,
-DTLSv1_2_method, DTLSv1_2_server_method, DTLSv1_2_client_method
+SSL_CTX_new, SSL_CTX_new_ex, SSL_CTX_up_ref, SSLv3_method,
+SSLv3_server_method, SSLv3_client_method, TLSv1_method, TLSv1_server_method,
+TLSv1_client_method, TLSv1_1_method, TLSv1_1_server_method,
+TLSv1_1_client_method, TLS_method, TLS_server_method, TLS_client_method,
+SSLv23_method, SSLv23_server_method, SSLv23_client_method, DTLS_method,
+DTLS_server_method, DTLS_client_method, DTLSv1_method, DTLSv1_server_method,
+DTLSv1_client_method, DTLSv1_2_method, DTLSv1_2_server_method,
+DTLSv1_2_client_method
- create a new SSL_CTX object as framework for TLS/SSL or DTLS enabled
functions
@@ -17,6 +18,8 @@ functions
#include <openssl/ssl.h>
+ SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
+ const SSL_METHOD *method);
SSL_CTX *SSL_CTX_new(const SSL_METHOD *method);
int SSL_CTX_up_ref(SSL_CTX *ctx);
@@ -70,20 +73,48 @@ functions
=head1 DESCRIPTION
-SSL_CTX_new() creates a new B<SSL_CTX> object as framework to
-establish TLS/SSL or DTLS enabled connections. An B<SSL_CTX> object is
-reference counted. Creating an B<SSL_CTX> object for the first time increments
-the reference count. Freeing it (using SSL_CTX_free) decrements it. When the
-reference count drops to zero, any memory or resources allocated to the
-B<SSL_CTX> object are freed. SSL_CTX_up_ref() increments the reference count for
-an existing B<SSL_CTX> structure.
+SSL_CTX_new_ex() creates a new B<SSL_CTX> object, which holds various
+configuration and data relevant to SSL/TLS or DTLS session establishment.
+These are later inherited by the B<SSL> object representing an active session.
+The I<method> parameter specifies whether the context will be used for the
+client or server side or both - for details see the L</NOTES> below.
+The library context I<libctx> (see L<OSSL_LIB_CTX(3)>) is used to provide the
+cryptographic algorithms needed for the session. Any cryptographic algorithms
+that are used by any B<SSL> objects created from this B<SSL_CTX> will be fetched
+from the I<libctx> using the property query string I<propq> (see
+L<crypto(7)/ALGORITHM FETCHING>. Either or both the I<libctx> or I<propq>
+parameters may be NULL.
+
+SSL_CTX_new() does the same as SSL_CTX_new_ex() except that the default
+library context is used and no property query string is specified.
+
+An B<SSL_CTX> object is reference counted. Creating an B<SSL_CTX> object for the
+first time increments the reference count. Freeing the B<SSL_CTX> (using
+SSL_CTX_free) decrements it. When the reference count drops to zero, any memory
+or resources allocated to the B<SSL_CTX> object are freed. SSL_CTX_up_ref()
+increments the reference count for an existing B<SSL_CTX> structure.
+
+An B<SSL_CTX> object should not be changed after it is used to create any B<SSL>
+objects or from multiple threads concurrently, since the implementation does not
+provide serialization of access for these cases.
=head1 NOTES
-The SSL_CTX object uses B<method> as connection method.
-The methods exist in a generic type (for client and server use), a server only
-type, and a client only type.
-B<method> can be of the following types:
+On session estabilishment, by default, no peer credentials verification is done.
+This must be explicitly requested, typically using L<SSL_CTX_set_verify(3)>.
+For verifying peer certificates many options can be set using various functions
+such as L<SSL_CTX_load_verify_locations(3)> and L<SSL_CTX_set1_param(3)>.
+The L<X509_VERIFY_PARAM_set_purpose(3)> function can be used, also in conjunction
+with L<SSL_CTX_get0_param(3)>, to set the intended purpose of the session.
+The default is B<X509_PURPOSE_SSL_SERVER> on the client side
+and B<X509_PURPOSE_SSL_CLIENT> on the server side.
+
+The SSL_CTX object uses I<method> as the connection method.
+Three method variants are available: a generic method (for either client or
+server use), a server-only method, and a client-only method.
+
+The I<method> parameter of SSL_CTX_new_ex() and SSL_CTX_new()
+can be one of the following:
=over 4
@@ -197,7 +228,9 @@ SSL_CTX_up_ref() returns 1 for success and 0 for failure.
=head1 SEE ALSO
-L<SSL_CTX_set_options(3)>, L<SSL_CTX_free(3)>, L<SSL_accept(3)>,
+L<SSL_CTX_set_options(3)>, L<SSL_CTX_free(3)>,
+SSL_CTX_set_verify(3), L<SSL_CTX_set1_param(3)>, L<SSL_CTX_get0_param(3)>,
+L<SSL_connect(3)>, L<SSL_accept(3)>,
L<SSL_CTX_set_min_proto_version(3)>, L<ssl(7)>, L<SSL_set_connect_state(3)>
=head1 HISTORY
@@ -212,11 +245,13 @@ and TLS_client_method() functions were added in OpenSSL 1.1.0.
All version-specific methods were deprecated in OpenSSL 1.1.0.
+SSL_CTX_new_ex() was added in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_sess_number.pod b/doc/man3/SSL_CTX_sess_number.pod
index a96c8dd791ca..5b217b881e58 100644
--- a/doc/man3/SSL_CTX_sess_number.pod
+++ b/doc/man3/SSL_CTX_sess_number.pod
@@ -77,7 +77,7 @@ L<SSL_CTX_sess_set_cache_size(3)>
Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_sess_set_cache_size.pod b/doc/man3/SSL_CTX_sess_set_cache_size.pod
index 6a1c140ef16b..fe37a96d8456 100644
--- a/doc/man3/SSL_CTX_sess_set_cache_size.pod
+++ b/doc/man3/SSL_CTX_sess_set_cache_size.pod
@@ -54,7 +54,7 @@ L<SSL_CTX_flush_sessions(3)>
Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_sess_set_get_cb.pod b/doc/man3/SSL_CTX_sess_set_get_cb.pod
index d30f84d78a28..7fd5e0d1f2d7 100644
--- a/doc/man3/SSL_CTX_sess_set_get_cb.pod
+++ b/doc/man3/SSL_CTX_sess_set_get_cb.pod
@@ -115,7 +115,7 @@ L<SSL_CTX_free(3)>
Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_sessions.pod b/doc/man3/SSL_CTX_sessions.pod
index 41c0777cafc5..d0bc7104a308 100644
--- a/doc/man3/SSL_CTX_sessions.pod
+++ b/doc/man3/SSL_CTX_sessions.pod
@@ -8,7 +8,7 @@ SSL_CTX_sessions - access internal session cache
#include <openssl/ssl.h>
- struct lhash_st *SSL_CTX_sessions(SSL_CTX *ctx);
+ LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx);
=head1 DESCRIPTION
@@ -37,9 +37,9 @@ L<SSL_CTX_set_session_cache_mode(3)>
=head1 COPYRIGHT
-Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set0_CA_list.pod b/doc/man3/SSL_CTX_set0_CA_list.pod
index b483f83b7182..64e8117f9236 100644
--- a/doc/man3/SSL_CTX_set0_CA_list.pod
+++ b/doc/man3/SSL_CTX_set0_CA_list.pod
@@ -178,9 +178,9 @@ L<SSL_CTX_load_verify_locations(3)>
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set1_curves.pod b/doc/man3/SSL_CTX_set1_curves.pod
index 6c3d4fc9e912..cbd8f713468b 100644
--- a/doc/man3/SSL_CTX_set1_curves.pod
+++ b/doc/man3/SSL_CTX_set1_curves.pod
@@ -4,8 +4,8 @@
SSL_CTX_set1_groups, SSL_CTX_set1_groups_list, SSL_set1_groups,
SSL_set1_groups_list, SSL_get1_groups, SSL_get_shared_group,
-SSL_CTX_set1_curves, SSL_CTX_set1_curves_list, SSL_set1_curves,
-SSL_set1_curves_list, SSL_get1_curves, SSL_get_shared_curve
+SSL_get_negotiated_group, SSL_CTX_set1_curves, SSL_CTX_set1_curves_list,
+SSL_set1_curves, SSL_set1_curves_list, SSL_get1_curves, SSL_get_shared_curve
- EC supported curve functions
=head1 SYNOPSIS
@@ -20,6 +20,7 @@ SSL_set1_curves_list, SSL_get1_curves, SSL_get_shared_curve
int SSL_get1_groups(SSL *ssl, int *groups);
int SSL_get_shared_group(SSL *s, int n);
+ int SSL_get_negotiated_group(SSL *s);
int SSL_CTX_set1_curves(SSL_CTX *ctx, int *clist, int clistlen);
int SSL_CTX_set1_curves_list(SSL_CTX *ctx, char *list);
@@ -33,17 +34,27 @@ SSL_set1_curves_list, SSL_get1_curves, SSL_get_shared_curve
=head1 DESCRIPTION
For all of the functions below that set the supported groups there must be at
-least one group in the list.
+least one group in the list. A number of these functions identify groups via a
+unique integer NID value. However, support for some groups may be added by
+external providers. In this case there will be no NID assigned for the group.
+When setting such groups applications should use the "list" form of these
+functions (i.e. SSL_CTX_set1_groups_list() and SSL_set1_groups_list).
SSL_CTX_set1_groups() sets the supported groups for B<ctx> to B<glistlen>
groups in the array B<glist>. The array consist of all NIDs of groups in
preference order. For a TLS client the groups are used directly in the
supported groups extension. For a TLS server the groups are used to
-determine the set of shared groups.
+determine the set of shared groups. Currently supported groups for
+B<TLSv1.3> are B<NID_X9_62_prime256v1>, B<NID_secp384r1>, B<NID_secp521r1>,
+B<NID_X25519>, B<NID_X448>, B<NID_ffdhe2048>, B<NID_ffdhe3072>,
+B<NID_ffdhe4096>, B<NID_ffdhe6144> and B<NID_ffdhe8192>.
SSL_CTX_set1_groups_list() sets the supported groups for B<ctx> to
string B<list>. The string is a colon separated list of group NIDs or
-names, for example "P-521:P-384:P-256".
+names, for example "P-521:P-384:P-256:X25519:ffdhe2048". Currently supported
+groups for B<TLSv1.3> are B<P-256>, B<P-384>, B<P-521>, B<X25519>, B<X448>,
+B<ffdhe2048>, B<ffdhe3072>, B<ffdhe4096>, B<ffdhe6144>, B<ffdhe8192>. Support
+for other groups may be added by external providers.
SSL_set1_groups() and SSL_set1_groups_list() are similar except they set
supported groups for the SSL structure B<ssl>.
@@ -54,14 +65,27 @@ supported groups. The B<groups> parameter can be B<NULL> to simply
return the number of groups for memory allocation purposes. The
B<groups> array is in the form of a set of group NIDs in preference
order. It can return zero if the client did not send a supported groups
-extension.
+extension. If a supported group NID is unknown then the value is set to the
+bitwise OR of TLSEXT_nid_unknown (0x1000000) and the id of the group.
-SSL_get_shared_group() returns shared group B<n> for a server-side
-SSL B<ssl>. If B<n> is -1 then the total number of shared groups is
+SSL_get_shared_group() returns the NID of the shared group B<n> for a
+server-side SSL B<ssl>. If B<n> is -1 then the total number of shared groups is
returned, which may be zero. Other than for diagnostic purposes,
most applications will only be interested in the first shared group
so B<n> is normally set to zero. If the value B<n> is out of range,
-NID_undef is returned.
+NID_undef is returned. If the NID for the shared group is unknown then the value
+is set to the bitwise OR of TLSEXT_nid_unknown (0x1000000) and the id of the
+group.
+
+SSL_get_negotiated_group() returns the NID of the negotiated group used for
+the handshake key exchange process. For TLSv1.3 connections this typically
+reflects the state of the current connection, though in the case of PSK-only
+resumption, the returned value will be from a previous connection. For earlier
+TLS versions, when a session has been resumed, it always reflects the group
+used for key exchange during the initial handshake (otherwise it is from the
+current, non-resumption, connection). This can be called by either client or
+server. If the NID for the shared group is unknown then the value is set to the
+bitwise OR of TLSEXT_nid_unknown (0x1000000) and the id of the group.
All these functions are implemented as macros.
@@ -91,20 +115,25 @@ is -1.
When called on a client B<ssl>, SSL_get_shared_group() has no meaning and
returns -1.
+SSL_get_negotiated_group() returns the NID of the negotiated group used for
+key exchange, or NID_undef if there was no negotiated group.
+
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_CTX_add_extra_chain_cert(3)>
=head1 HISTORY
The curve functions were added in OpenSSL 1.0.2. The equivalent group
-functions were added in OpenSSL 1.1.1.
+functions were added in OpenSSL 1.1.1. The SSL_get_negotiated_group() function
+was added in OpenSSL 3.0.0.
=head1 COPYRIGHT
-Copyright 2013-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set1_sigalgs.pod b/doc/man3/SSL_CTX_set1_sigalgs.pod
index 1c462a95b6ae..eb3100634626 100644
--- a/doc/man3/SSL_CTX_set1_sigalgs.pod
+++ b/doc/man3/SSL_CTX_set1_sigalgs.pod
@@ -108,9 +108,9 @@ L<SSL_CONF_CTX_new(3)>
=head1 COPYRIGHT
-Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set1_verify_cert_store.pod b/doc/man3/SSL_CTX_set1_verify_cert_store.pod
index a7f2a53a80af..19ea92a905f2 100644
--- a/doc/man3/SSL_CTX_set1_verify_cert_store.pod
+++ b/doc/man3/SSL_CTX_set1_verify_cert_store.pod
@@ -63,6 +63,9 @@ the server's certificate chain and a SSL/TLS server will use it to verify
any client certificate chain.
The chain store is used to build the certificate chain.
+Details of the chain building and checking process are described in
+L<openssl-verification-options(1)/Certification Path Building> and
+L<openssl-verification-options(1)/Certification Path Validation>.
If the mode B<SSL_MODE_NO_AUTO_CHAIN> is set or a certificate chain is
configured already (for example using the functions such as
@@ -83,6 +86,7 @@ All these functions return 1 for success and 0 for failure.
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_CTX_add_extra_chain_cert(3)>
L<SSL_CTX_set0_chain(3)>
L<SSL_CTX_set1_chain(3)>
@@ -103,7 +107,7 @@ These functions were added in OpenSSL 1.0.2.
Copyright 2013-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_alpn_select_cb.pod b/doc/man3/SSL_CTX_set_alpn_select_cb.pod
index e90caecda425..102e6578512c 100644
--- a/doc/man3/SSL_CTX_set_alpn_select_cb.pod
+++ b/doc/man3/SSL_CTX_set_alpn_select_cb.pod
@@ -43,7 +43,7 @@ SSL_select_next_proto, SSL_get0_alpn_selected, SSL_get0_next_proto_negotiated
const unsigned char *server,
unsigned int server_len,
const unsigned char *client,
- unsigned int client_len)
+ unsigned int client_len);
void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
unsigned *len);
@@ -189,7 +189,7 @@ L<SSL_CTX_set_tlsext_servername_arg(3)>
Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_cert_cb.pod b/doc/man3/SSL_CTX_set_cert_cb.pod
index da084cb1f45c..c3966782c0dc 100644
--- a/doc/man3/SSL_CTX_set_cert_cb.pod
+++ b/doc/man3/SSL_CTX_set_cert_cb.pod
@@ -12,26 +12,24 @@ SSL_CTX_set_cert_cb, SSL_set_cert_cb - handle certificate callback function
void *arg);
void SSL_set_cert_cb(SSL *s, int (*cert_cb)(SSL *ssl, void *arg), void *arg);
- int (*cert_cb)(SSL *ssl, void *arg);
-
=head1 DESCRIPTION
-SSL_CTX_set_cert_cb() and SSL_set_cert_cb() sets the cert_cb() callback,
-B<arg> value is pointer which is passed to the application callback.
+SSL_CTX_set_cert_cb() and SSL_set_cert_cb() sets the I<cert_cb> callback,
+I<arg> value is pointer which is passed to the application callback.
-When cert_cb() is NULL, no callback function is used.
+When I<cert_cb> is NULL, no callback function is used.
-cert_cb() is the application defined callback. It is called before a
+I<cert_cb> is the application defined callback. It is called before a
certificate will be used by a client or server. The callback can then inspect
-the passed B<ssl> structure and set or clear any appropriate certificates. If
+the passed I<ssl> structure and set or clear any appropriate certificates. If
the callback is successful it B<MUST> return 1 even if no certificates have
been set. A zero is returned on error which will abort the handshake with a
fatal internal error alert. A negative return value will suspend the handshake
and the handshake function will return immediately.
L<SSL_get_error(3)> will return SSL_ERROR_WANT_X509_LOOKUP to
indicate, that the handshake was suspended. The next call to the handshake
-function will again lead to the call of cert_cb(). It is the job of the
-cert_cb() to store information about the state of the last call,
+function will again lead to the call of I<cert_cb>. It is the job of the
+I<cert_cb> to store information about the state of the last call,
if required to continue.
=head1 NOTES
@@ -72,9 +70,9 @@ L<SSL_clear(3)>, L<SSL_free(3)>
=head1 COPYRIGHT
-Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_cert_store.pod b/doc/man3/SSL_CTX_set_cert_store.pod
index f1a54a6950a6..f1fef9e649cd 100644
--- a/doc/man3/SSL_CTX_set_cert_store.pod
+++ b/doc/man3/SSL_CTX_set_cert_store.pod
@@ -81,7 +81,7 @@ L<SSL_CTX_set_verify(3)>
Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_cert_verify_callback.pod b/doc/man3/SSL_CTX_set_cert_verify_callback.pod
index 0c3378db660e..be59a548cbd9 100644
--- a/doc/man3/SSL_CTX_set_cert_verify_callback.pod
+++ b/doc/man3/SSL_CTX_set_cert_verify_callback.pod
@@ -20,24 +20,48 @@ the time when L<SSL_new(3)> is called.
=head1 NOTES
-Whenever a certificate is verified during a SSL/TLS handshake, a verification
-function is called. If the application does not explicitly specify a
-verification callback function, the built-in verification function is used.
+When a peer certificate has been received during a SSL/TLS handshake,
+a verification function is called regardless of the verification mode.
+If the application does not explicitly specify a verification callback function,
+the built-in verification function is used.
If a verification callback I<callback> is specified via
SSL_CTX_set_cert_verify_callback(), the supplied callback function is called
-instead. By setting I<callback> to NULL, the default behaviour is restored.
-
-When the verification must be performed, I<callback> will be called with
-the arguments callback(X509_STORE_CTX *x509_store_ctx, void *arg). The
-argument I<arg> is specified by the application when setting I<callback>.
-
-I<callback> should return 1 to indicate verification success and 0 to
-indicate verification failure. If SSL_VERIFY_PEER is set and I<callback>
-returns 0, the handshake will fail. As the verification procedure may
-allow the connection to continue in the case of failure (by always
-returning 1) the verification result must be set in any case using the
-B<error> member of I<x509_store_ctx> so that the calling application
-will be informed about the detailed result of the verification procedure!
+instead with the arguments callback(X509_STORE_CTX *x509_store_ctx, void *arg).
+The argument I<arg> is specified by the application when setting I<callback>.
+By setting I<callback> to NULL, the default behaviour is restored.
+
+I<callback> should return 1 to indicate verification success
+and 0 to indicate verification failure.
+In server mode, a return value of 0 leads to handshake failure.
+In client mode, the behaviour is as follows.
+All values, including 0, are ignored
+if the verification mode is B<SSL_VERIFY_NONE>.
+Otherwise, when the return value is less than or equal to 0, the handshake will
+fail.
+
+In client mode I<callback> may also call the L<SSL_set_retry_verify(3)>
+function on the B<SSL> object set in the I<x509_store_ctx> ex data (see
+L<SSL_get_ex_data_X509_STORE_CTX_idx(3)>) and return 1. This would be
+typically done in case the certificate verification was not yet able
+to succeed. This makes the handshake suspend and return control to the
+calling application with B<SSL_ERROR_WANT_RETRY_VERIFY>. The app can for
+instance fetch further certificates or cert status information needed for
+the verification. Calling L<SSL_connect(3)> again resumes the connection
+attempt by retrying the server certificate verification step.
+This process may even be repeated if need be.
+
+In any case a viable verification result value must be reflected
+in the B<error> member of I<x509_store_ctx>,
+which can be done using L<X509_STORE_CTX_set_error(3)>.
+This is particularly important in case
+the I<callback> allows the connection to continue (by returning 1).
+Note that the verification status in the store context is a possibly durable
+indication of the chain's validity!
+This gets recorded in the SSL session (and thus also in session tickets)
+and the validity of the originally presented chain is then visible
+on resumption, even though no chain is presented int that case.
+Moreover, the calling application will be informed about the detailed result of
+the verification procedure and may elect to base further decisions on it.
Within I<x509_store_ctx>, I<callback> has access to the I<verify_callback>
function set using L<SSL_CTX_set_verify(3)>.
@@ -65,14 +89,16 @@ SSL_CTX_set_cert_verify_callback() does not provide diagnostic information.
=head1 SEE ALSO
L<ssl(7)>, L<SSL_CTX_set_verify(3)>,
+L<X509_STORE_CTX_set_error(3)>,
L<SSL_get_verify_result(3)>,
+L<SSL_set_retry_verify(3)>,
L<SSL_CTX_load_verify_locations(3)>
=head1 COPYRIGHT
-Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_cipher_list.pod b/doc/man3/SSL_CTX_set_cipher_list.pod
index 66ade102830b..71f399400c2a 100644
--- a/doc/man3/SSL_CTX_set_cipher_list.pod
+++ b/doc/man3/SSL_CTX_set_cipher_list.pod
@@ -5,7 +5,9 @@
SSL_CTX_set_cipher_list,
SSL_set_cipher_list,
SSL_CTX_set_ciphersuites,
-SSL_set_ciphersuites
+SSL_set_ciphersuites,
+OSSL_default_cipher_list,
+OSSL_default_ciphersuites
- choose list of available SSL_CIPHERs
=head1 SYNOPSIS
@@ -18,11 +20,14 @@ SSL_set_ciphersuites
int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str);
int SSL_set_ciphersuites(SSL *s, const char *str);
+ const char *OSSL_default_cipher_list(void);
+ const char *OSSL_default_ciphersuites(void);
+
=head1 DESCRIPTION
SSL_CTX_set_cipher_list() sets the list of available ciphers (TLSv1.2 and below)
for B<ctx> using the control string B<str>. The format of the string is described
-in L<ciphers(1)>. The list of ciphers is inherited by all
+in L<openssl-ciphers(1)>. The list of ciphers is inherited by all
B<ssl> objects created from B<ctx>. This function does not impact TLSv1.3
ciphersuites. Use SSL_CTX_set_ciphersuites() to configure those.
@@ -54,13 +59,17 @@ An empty list is permissible. The default value for the this setting is:
SSL_set_ciphersuites() is the same as SSL_CTX_set_ciphersuites() except it
configures the ciphersuites for B<ssl>.
+OSSL_default_cipher_list() returns the default cipher string for TLSv1.2
+(and earlier) ciphers. OSSL_default_ciphersuites() returns the default
+cipher string for TLSv1.3 ciphersuites.
+
=head1 NOTES
-The control string B<str> for SSL_CTX_set_cipher_list() and
-SSL_set_cipher_list() should be universally usable and not depend
-on details of the library configuration (ciphers compiled in). Thus no
-syntax checking takes place. Items that are not recognized, because the
-corresponding ciphers are not compiled in or because they are mistyped,
+The control string B<str> for SSL_CTX_set_cipher_list(), SSL_set_cipher_list(),
+SSL_CTX_set_ciphersuites() and SSL_set_ciphersuites() should be universally
+usable and not depend on details of the library configuration (ciphers compiled
+in). Thus no syntax checking takes place. Items that are not recognized, because
+the corresponding ciphers are not compiled in or because they are mistyped,
are simply ignored. Failure is only flagged if no ciphers could be collected
at all.
@@ -71,7 +80,7 @@ additional restrictions apply. All ciphers have additional requirements.
ADH ciphers don't need a certificate, but DH-parameters must have been set.
All other ciphers need a corresponding certificate and key.
-A RSA cipher can only be chosen, when a RSA certificate is available.
+An RSA cipher can only be chosen, when an RSA certificate is available.
RSA ciphers using DHE need a certificate and key and additional DH-parameters
(see L<SSL_CTX_set_tmp_dh_callback(3)>).
@@ -85,6 +94,10 @@ of 512 bits and the server is not configured to use temporary RSA
keys), the "no shared cipher" (SSL_R_NO_SHARED_CIPHER) error is generated
and the handshake will fail.
+OSSL_default_cipher_list() and OSSL_default_ciphersuites() replace
+SSL_DEFAULT_CIPHER_LIST and TLS_DEFAULT_CIPHERSUITES, respectively. The
+cipher list defines are deprecated as of 3.0.
+
=head1 RETURN VALUES
SSL_CTX_set_cipher_list() and SSL_set_cipher_list() return 1 if any cipher
@@ -98,13 +111,17 @@ ciphersuite list was configured, and 0 otherwise.
L<ssl(7)>, L<SSL_get_ciphers(3)>,
L<SSL_CTX_use_certificate(3)>,
L<SSL_CTX_set_tmp_dh_callback(3)>,
-L<ciphers(1)>
+L<openssl-ciphers(1)>
+
+=head1 HISTORY
+
+OSSL_default_cipher_list() and OSSL_default_ciphersites() are new in 3.0.
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_client_cert_cb.pod b/doc/man3/SSL_CTX_set_client_cert_cb.pod
index 0dd147f951b2..f1341cb40e0b 100644
--- a/doc/man3/SSL_CTX_set_client_cert_cb.pod
+++ b/doc/man3/SSL_CTX_set_client_cert_cb.pod
@@ -13,29 +13,28 @@ SSL_CTX_set_client_cert_cb, SSL_CTX_get_client_cert_cb - handle client certifica
EVP_PKEY **pkey));
int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **x509,
EVP_PKEY **pkey);
- int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
=head1 DESCRIPTION
-SSL_CTX_set_client_cert_cb() sets the client_cert_cb() callback, that is
+SSL_CTX_set_client_cert_cb() sets the I<client_cert_cb> callback, that is
called when a client certificate is requested by a server and no certificate
was yet set for the SSL object.
-When client_cert_cb() is NULL, no callback function is used.
+When I<client_cert_cb> is NULL, no callback function is used.
SSL_CTX_get_client_cert_cb() returns a pointer to the currently set callback
function.
-client_cert_cb() is the application defined callback. If it wants to
+I<client_cert_cb> is the application defined callback. If it wants to
set a certificate, a certificate/private key combination must be set
-using the B<x509> and B<pkey> arguments and "1" must be returned. The
-certificate will be installed into B<ssl>, see the NOTES and BUGS sections.
+using the I<x509> and I<pkey> arguments and "1" must be returned. The
+certificate will be installed into I<ssl>, see the NOTES and BUGS sections.
If no certificate should be set, "0" has to be returned and no certificate
will be sent. A negative return value will suspend the handshake and the
handshake function will return immediately. L<SSL_get_error(3)>
will return SSL_ERROR_WANT_X509_LOOKUP to indicate, that the handshake was
suspended. The next call to the handshake function will again lead to the call
-of client_cert_cb(). It is the job of the client_cert_cb() to store information
+of I<client_cert_cb>. It is the job of the I<client_cert_cb> to store information
about the state of the last call, if required to continue.
=head1 NOTES
@@ -65,12 +64,12 @@ a certificate.
=head1 RETURN VALUES
-SSL_CTX_get_client_cert_cb() returns function pointer of client_cert_cb() or
+SSL_CTX_get_client_cert_cb() returns function pointer of I<client_cert_cb> or
NULL if the callback is not set.
=head1 BUGS
-The client_cert_cb() cannot return a complete certificate chain, it can
+The I<client_cert_cb> cannot return a complete certificate chain, it can
only return one client certificate. If the chain only has a length of 2,
the root CA certificate may be omitted according to the TLS standard and
thus a standard conforming answer can be sent to the server. For a
@@ -101,9 +100,9 @@ L<SSL_clear(3)>, L<SSL_free(3)>
=head1 COPYRIGHT
-Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_client_hello_cb.pod b/doc/man3/SSL_CTX_set_client_hello_cb.pod
index 2ec298960a03..d592102028ce 100644
--- a/doc/man3/SSL_CTX_set_client_hello_cb.pod
+++ b/doc/man3/SSL_CTX_set_client_hello_cb.pod
@@ -18,7 +18,7 @@ SSL_CTX_set_client_hello_cb, SSL_client_hello_cb_fn, SSL_client_hello_isv2, SSL_
const unsigned char **out);
int SSL_client_hello_get1_extensions_present(SSL *s, int **out,
size_t *outlen);
- int SSL_client_hello_get0_ext(SSL *s, int type, const unsigned char **out,
+ int SSL_client_hello_get0_ext(SSL *s, unsigned int type, const unsigned char **out,
size_t *outlen);
=head1 DESCRIPTION
@@ -26,7 +26,7 @@ SSL_CTX_set_client_hello_cb, SSL_client_hello_cb_fn, SSL_client_hello_isv2, SSL_
SSL_CTX_set_client_hello_cb() sets the callback function, which is automatically
called during the early stages of ClientHello processing on the server.
The argument supplied when setting the callback is passed back to the
-callback at runtime. A callback that returns failure (0) will cause the
+callback at run time. A callback that returns failure (0) will cause the
connection to terminate, and callbacks returning failure should indicate
what alert value is to be sent in the B<al> parameter. A callback may
also return a negative value to suspend the handshake, and the handshake
@@ -110,7 +110,7 @@ SSL_client_hello_get1_extensions_present() returns 1 on success and 0 on failure
=head1 SEE ALSO
L<ssl(7)>, L<SSL_CTX_set_tlsext_servername_callback(3)>,
-L<SSL_bytes_to_cipher_list>
+L<SSL_bytes_to_cipher_list(3)>
=head1 HISTORY
@@ -122,9 +122,9 @@ were added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_ct_validation_callback.pod b/doc/man3/SSL_CTX_set_ct_validation_callback.pod
index a0a8028f1fb5..962f5ebd7989 100644
--- a/doc/man3/SSL_CTX_set_ct_validation_callback.pod
+++ b/doc/man3/SSL_CTX_set_ct_validation_callback.pod
@@ -69,7 +69,7 @@ sufficient to allow the connection to continue.
The TLS handshake is aborted if the verification mode is not B<SSL_VERIFY_NONE>
and the callback returns a non-positive result.
-An arbitrary callback context argument, B<arg>, can be passed in when setting
+An arbitrary callback data argument, B<arg>, can be passed in when setting
the callback.
This will be passed to the callback whenever it is invoked.
Ownership of this context remains with the caller.
@@ -135,9 +135,9 @@ L<SSL_SESSION_get_time(3)>
=head1 COPYRIGHT
-Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_ctlog_list_file.pod b/doc/man3/SSL_CTX_set_ctlog_list_file.pod
index 5fb0feb45183..31f82dc51ce0 100644
--- a/doc/man3/SSL_CTX_set_ctlog_list_file.pod
+++ b/doc/man3/SSL_CTX_set_ctlog_list_file.pod
@@ -24,7 +24,7 @@ See L<CTLOG_STORE_new(3)> for the file format.
=head1 NOTES
These functions will not clear the existing CT log list - it will be appended
-to. To replace the existing list, use L<SSL_CTX_set0_ctlog_store> first.
+to. To replace the existing list, use L<SSL_CTX_set0_ctlog_store(3)> first.
If an error occurs whilst parsing a particular log entry in the file, that log
entry will be skipped.
@@ -43,9 +43,9 @@ L<CTLOG_STORE_new(3)>
=head1 COPYRIGHT
-Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_default_passwd_cb.pod b/doc/man3/SSL_CTX_set_default_passwd_cb.pod
index 991ce7a5a922..bc19890c6d6a 100644
--- a/doc/man3/SSL_CTX_set_default_passwd_cb.pod
+++ b/doc/man3/SSL_CTX_set_default_passwd_cb.pod
@@ -105,7 +105,7 @@ added in OpenSSL 1.1.0.
Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_ex_data.pod b/doc/man3/SSL_CTX_set_ex_data.pod
deleted file mode 100644
index fd0364b4877f..000000000000
--- a/doc/man3/SSL_CTX_set_ex_data.pod
+++ /dev/null
@@ -1,52 +0,0 @@
-=pod
-
-=head1 NAME
-
-SSL_CTX_get_ex_data, SSL_CTX_set_ex_data,
-SSL_get_ex_data, SSL_set_ex_data
-- Store and retrieve extra data from the SSL_CTX, SSL or SSL_SESSION
-
-=head1 SYNOPSIS
-
- #include <openssl/ssl.h>
-
- void *SSL_CTX_get_ex_data(const SSL_CTX *s, int idx);
-
- int SSL_CTX_set_ex_data(SSL_CTX *s, int idx, void *arg);
-
- void *SSL_get_ex_data(const SSL *s, int idx);
-
- int SSL_set_ex_data(SSL *s, int idx, void *arg);
-
-=head1 DESCRIPTION
-
-SSL*_set_ex_data() functions can be used to store arbitrary user data into the
-B<SSL_CTX>, or B<SSL> object. The user must supply a unique index
-which they can subsequently use to retrieve the data using SSL*_get_ex_data().
-
-For more detailed information see L<CRYPTO_get_ex_data(3)> and
-L<CRYPTO_set_ex_data(3)> which implement these functions and
-L<CRYPTO_get_ex_new_index(3)> for generating a unique index.
-
-=head1 RETURN VALUES
-
-The SSL*_set_ex_data() functions return 1 if the item is successfully stored
-and 0 if it is not.
-The SSL*_get_ex_data() functions return the ex_data pointer if successful,
-otherwise NULL.
-
-=head1 SEE ALSO
-
-L<CRYPTO_get_ex_data(3)>, L<CRYPTO_set_ex_data(3)>,
-L<CRYPTO_get_ex_new_index(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man3/SSL_CTX_set_generate_session_id.pod b/doc/man3/SSL_CTX_set_generate_session_id.pod
index 2ad3bf0fbf9d..14fb12cfd0f3 100644
--- a/doc/man3/SSL_CTX_set_generate_session_id.pod
+++ b/doc/man3/SSL_CTX_set_generate_session_id.pod
@@ -85,10 +85,10 @@ reason and return 1 on success.
=head1 RETURN VALUES
SSL_CTX_set_generate_session_id() and SSL_set_generate_session_id()
-always return 1.
+return 1 on success and 0 for failure.
SSL_has_matching_session_id() returns 1 if another session with the
-same id is already in the cache.
+same id is already in the cache, or 0 otherwise.
=head1 EXAMPLES
@@ -130,7 +130,7 @@ L<ssl(7)>, L<SSL_get_version(3)>
Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_info_callback.pod b/doc/man3/SSL_CTX_set_info_callback.pod
index cc032f870934..9cee64207384 100644
--- a/doc/man3/SSL_CTX_set_info_callback.pod
+++ b/doc/man3/SSL_CTX_set_info_callback.pod
@@ -50,7 +50,7 @@ the callback function was called. If B<ret> is 0, an error condition occurred.
If an alert is handled, SSL_CB_ALERT is set and B<ret> specifies the alert
information.
-B<where> is a bit mask made up of the following bits:
+B<where> is a bit-mask made up of the following bits:
=over 4
@@ -158,7 +158,7 @@ L<SSL_alert_type_string(3)>
Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_keylog_callback.pod b/doc/man3/SSL_CTX_set_keylog_callback.pod
index 9e0127f91a9a..27dfb3419e3a 100644
--- a/doc/man3/SSL_CTX_set_keylog_callback.pod
+++ b/doc/man3/SSL_CTX_set_keylog_callback.pod
@@ -29,7 +29,7 @@ The key logging callback is called with two items: the B<ssl> object associated
with the connection, and B<line>, a string containing the key material in the
format used by NSS for its B<SSLKEYLOGFILE> debugging output. To recreate that
file, the key logging callback should log B<line>, followed by a newline.
-B<line> will always be a NULL-terminated string.
+B<line> will always be a NUL-terminated string.
=head1 RETURN VALUES
@@ -42,9 +42,9 @@ L<ssl(7)>
=head1 COPYRIGHT
-Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_max_cert_list.pod b/doc/man3/SSL_CTX_set_max_cert_list.pod
index 3996c97682bc..ea18ccb3ff0e 100644
--- a/doc/man3/SSL_CTX_set_max_cert_list.pod
+++ b/doc/man3/SSL_CTX_set_max_cert_list.pod
@@ -74,7 +74,7 @@ L<SSL_CTX_set_verify(3)>
Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_min_proto_version.pod b/doc/man3/SSL_CTX_set_min_proto_version.pod
index 7dfbfecf079d..2adf9acce00a 100644
--- a/doc/man3/SSL_CTX_set_min_proto_version.pod
+++ b/doc/man3/SSL_CTX_set_min_proto_version.pod
@@ -54,6 +54,7 @@ All these functions are implemented using macros.
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_CTX_set_options(3)>, L<SSL_CONF_cmd(3)>
=head1 HISTORY
@@ -65,7 +66,7 @@ were added in OpenSSL 1.1.1.
Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_mode.pod b/doc/man3/SSL_CTX_set_mode.pod
index 85e3353e0e2c..4b0c4dcd17d5 100644
--- a/doc/man3/SSL_CTX_set_mode.pod
+++ b/doc/man3/SSL_CTX_set_mode.pod
@@ -18,13 +18,13 @@ SSL_CTX_set_mode, SSL_CTX_clear_mode, SSL_set_mode, SSL_clear_mode, SSL_CTX_get_
=head1 DESCRIPTION
-SSL_CTX_set_mode() adds the mode set via bit mask in B<mode> to B<ctx>.
+SSL_CTX_set_mode() adds the mode set via bit-mask in B<mode> to B<ctx>.
Options already set before are not cleared.
-SSL_CTX_clear_mode() removes the mode set via bit mask in B<mode> from B<ctx>.
+SSL_CTX_clear_mode() removes the mode set via bit-mask in B<mode> from B<ctx>.
-SSL_set_mode() adds the mode set via bit mask in B<mode> to B<ssl>.
+SSL_set_mode() adds the mode set via bit-mask in B<mode> to B<ssl>.
Options already set before are not cleared.
-SSL_clear_mode() removes the mode set via bit mask in B<mode> from B<ssl>.
+SSL_clear_mode() removes the mode set via bit-mask in B<mode> from B<ssl>.
SSL_CTX_get_mode() returns the mode set for B<ctx>.
@@ -121,10 +121,10 @@ default since 1.1.1.
=head1 RETURN VALUES
-SSL_CTX_set_mode() and SSL_set_mode() return the new mode bit mask
+SSL_CTX_set_mode() and SSL_set_mode() return the new mode bit-mask
after adding B<mode>.
-SSL_CTX_get_mode() and SSL_get_mode() return the current bit mask.
+SSL_CTX_get_mode() and SSL_get_mode() return the current bit-mask.
=head1 SEE ALSO
@@ -137,9 +137,9 @@ SSL_MODE_ASYNC was added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_msg_callback.pod b/doc/man3/SSL_CTX_set_msg_callback.pod
index 8cf77cc553a1..9f7a17433d29 100644
--- a/doc/man3/SSL_CTX_set_msg_callback.pod
+++ b/doc/man3/SSL_CTX_set_msg_callback.pod
@@ -134,7 +134,7 @@ The pseudo content type B<SSL3_RT_INNER_CONTENT_TYPE> was added in OpenSSL 1.1.1
Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_num_tickets.pod b/doc/man3/SSL_CTX_set_num_tickets.pod
index bc031008f2f4..0c7331bc6da9 100644
--- a/doc/man3/SSL_CTX_set_num_tickets.pod
+++ b/doc/man3/SSL_CTX_set_num_tickets.pod
@@ -5,7 +5,8 @@
SSL_set_num_tickets,
SSL_get_num_tickets,
SSL_CTX_set_num_tickets,
-SSL_CTX_get_num_tickets
+SSL_CTX_get_num_tickets,
+SSL_new_session_ticket
- control the number of TLSv1.3 session tickets that are issued
=head1 SYNOPSIS
@@ -13,9 +14,10 @@ SSL_CTX_get_num_tickets
#include <openssl/ssl.h>
int SSL_set_num_tickets(SSL *s, size_t num_tickets);
- size_t SSL_get_num_tickets(SSL *s);
+ size_t SSL_get_num_tickets(const SSL *s);
int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets);
- size_t SSL_CTX_get_num_tickets(SSL_CTX *ctx);
+ size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx);
+ int SSL_new_session_ticket(SSL *s);
=head1 DESCRIPTION
@@ -40,27 +42,53 @@ handshake then SSL_set_num_tickets() can be called again prior to calling
SSL_verify_client_post_handshake() to update the number of tickets that will be
sent.
+To issue tickets after other events (such as application-layer changes),
+SSL_new_session_ticket() is used by a server application to request that a new
+ticket be sent when it is safe to do so. New tickets are only allowed to be
+sent in this manner after the initial handshake has completed, and only for
+TLS 1.3 connections. By default, the ticket generation and transmission are
+delayed until the server is starting a new write operation, so that it is
+bundled with other application data being written and properly aligned to a
+record boundary. If the connection was at a record boundary when
+SSL_new_session_ticket() was called, the ticket can be sent immediately
+(without waiting for the next application write) by calling
+SSL_do_handshake(). SSL_new_session_ticket() can be called more than once to
+request additional tickets be sent; all such requests are queued and written
+together when it is safe to do so and triggered by SSL_write() or
+SSL_do_handshake(). Note that a successful return from
+SSL_new_session_ticket() indicates only that the request to send a ticket was
+processed, not that the ticket itself was sent. To be notified when the
+ticket itself is sent, a new-session callback can be registered with
+L<SSL_CTX_sess_set_new_cb(3)> that will be invoked as the ticket or tickets
+are generated.
+
SSL_CTX_get_num_tickets() and SSL_get_num_tickets() return the number of
tickets set by a previous call to SSL_CTX_set_num_tickets() or
SSL_set_num_tickets(), or 2 if no such call has been made.
=head1 RETURN VALUES
-SSL_CTX_set_num_tickets() and SSL_set_num_tickets() return 1 on success or 0 on
-failure.
+SSL_CTX_set_num_tickets(), SSL_set_num_tickets(), and
+SSL_new_session_ticket() return 1 on success or 0 on failure.
SSL_CTX_get_num_tickets() and SSL_get_num_tickets() return the number of tickets
that have been previously set.
+=head1 SEE ALSO
+
+L<ssl(7)>
+
=head1 HISTORY
-These functions were added in OpenSSL 1.1.1.
+SSL_new_session_ticket() was added in OpenSSL 3.0.0.
+SSL_set_num_tickets(), SSL_get_num_tickets(), SSL_CTX_set_num_tickets(), and
+SSL_CTX_get_num_tickets() were added in OpenSSL 1.1.1.
=head1 COPYRIGHT
Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_options.pod b/doc/man3/SSL_CTX_set_options.pod
index 969e0366c45a..08522522cd0b 100644
--- a/doc/man3/SSL_CTX_set_options.pod
+++ b/doc/man3/SSL_CTX_set_options.pod
@@ -10,29 +10,29 @@ SSL_get_secure_renegotiation_support - manipulate SSL options
#include <openssl/ssl.h>
- long SSL_CTX_set_options(SSL_CTX *ctx, long options);
- long SSL_set_options(SSL *ssl, long options);
+ uint64_t SSL_CTX_set_options(SSL_CTX *ctx, uint64_t options);
+ uint64_t SSL_set_options(SSL *ssl, uint64_t options);
- long SSL_CTX_clear_options(SSL_CTX *ctx, long options);
- long SSL_clear_options(SSL *ssl, long options);
+ uint64_t SSL_CTX_clear_options(SSL_CTX *ctx, uint64_t options);
+ uint64_t SSL_clear_options(SSL *ssl, uint64_t options);
- long SSL_CTX_get_options(SSL_CTX *ctx);
- long SSL_get_options(SSL *ssl);
+ uint64_t SSL_CTX_get_options(const SSL_CTX *ctx);
+ uint64_t SSL_get_options(const SSL *ssl);
long SSL_get_secure_renegotiation_support(SSL *ssl);
=head1 DESCRIPTION
-SSL_CTX_set_options() adds the options set via bit mask in B<options> to B<ctx>.
+SSL_CTX_set_options() adds the options set via bit-mask in B<options> to B<ctx>.
Options already set before are not cleared!
-SSL_set_options() adds the options set via bit mask in B<options> to B<ssl>.
+SSL_set_options() adds the options set via bit-mask in B<options> to B<ssl>.
Options already set before are not cleared!
-SSL_CTX_clear_options() clears the options set via bit mask in B<options>
+SSL_CTX_clear_options() clears the options set via bit-mask in B<options>
to B<ctx>.
-SSL_clear_options() clears the options set via bit mask in B<options> to B<ssl>.
+SSL_clear_options() clears the options set via bit-mask in B<options> to B<ssl>.
SSL_CTX_get_options() returns the options set for B<ctx>.
@@ -45,7 +45,7 @@ Note, this is implemented via a macro.
=head1 NOTES
The behaviour of the SSL library can be changed by setting several options.
-The options are coded as bit masks and can be combined by a bitwise B<or>
+The options are coded as bit-masks and can be combined by a bitwise B<or>
operation (|).
SSL_CTX_set_options() and SSL_set_options() affect the (external)
@@ -62,10 +62,11 @@ The following B<bug workaround> options are available:
=over 4
-=item SSL_OP_SAFARI_ECDHE_ECDSA_BUG
+=item SSL_OP_CRYPTOPRO_TLSEXT_BUG
-Don't prefer ECDHE-ECDSA ciphers when the client appears to be Safari on OS X.
-OS X 10.8..10.8.3 has broken support for ECDHE-ECDSA ciphers.
+Add server-hello extension from the early version of cryptopro draft
+when GOST ciphersuite is negotiated. Required for interoperability with CryptoPro
+CSP 3.x.
=item SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
@@ -74,6 +75,11 @@ vulnerability affecting CBC ciphers, which cannot be handled by some
broken SSL implementations. This option has no effect for connections
using other ciphers.
+=item SSL_OP_SAFARI_ECDHE_ECDSA_BUG
+
+Don't prefer ECDHE-ECDSA ciphers when the client appears to be Safari on OS X.
+OS X 10.8..10.8.3 has broken support for ECDHE-ECDSA ciphers.
+
=item SSL_OP_TLSEXT_PADDING
Adds a padding extension to ensure the ClientHello size is never between
@@ -82,8 +88,7 @@ implementations.
=item SSL_OP_ALL
-All of the above bug workarounds plus B<SSL_OP_LEGACY_SERVER_CONNECT> as
-mentioned below.
+All of the above bug workarounds.
=back
@@ -95,17 +100,20 @@ The following B<modifying> options are available:
=over 4
-=item SSL_OP_TLS_ROLLBACK_BUG
+=item SSL_OP_ALLOW_CLIENT_RENEGOTIATION
-Disable version rollback attack detection.
+Client-initiated renegotiation is disabled by default. Use
+this option to enable it.
-During the client key exchange, the client must send the same information
-about acceptable SSL/TLS protocol levels as during the first hello. Some
-clients violate this rule by adapting to the server's answer. (Example:
-the client sends a SSLv2 hello and accepts up to SSLv3.1=TLSv1, the server
-only understands up to SSLv3. In this case the client must still use the
-same SSLv3.1=TLSv1 announcement. Some clients step down to SSLv3 with respect
-to the server's answer and violate the version rollback protection.)
+=item SSL_OP_ALLOW_NO_DHE_KEX
+
+In TLSv1.3 allow a non-(ec)dhe based key exchange mode on resumption. This means
+that there will be no forward secrecy for the resumed session.
+
+=item SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
+
+Allow legacy insecure renegotiation between OpenSSL and unpatched clients or
+servers. See the B<SECURE RENEGOTIATION> section for more details.
=item SSL_OP_CIPHER_SERVER_PREFERENCE
@@ -114,34 +122,143 @@ preferences. When not set, the SSL server will always follow the clients
preferences. When set, the SSL/TLS server will choose following its
own preferences.
-=item SSL_OP_NO_SSLv3, SSL_OP_NO_TLSv1, SSL_OP_NO_TLSv1_1,
-SSL_OP_NO_TLSv1_2, SSL_OP_NO_TLSv1_3, SSL_OP_NO_DTLSv1, SSL_OP_NO_DTLSv1_2
+=item SSL_OP_CISCO_ANYCONNECT
-These options turn off the SSLv3, TLSv1, TLSv1.1, TLSv1.2 or TLSv1.3 protocol
-versions with TLS or the DTLSv1, DTLSv1.2 versions with DTLS,
-respectively.
-As of OpenSSL 1.1.0, these options are deprecated, use
-L<SSL_CTX_set_min_proto_version(3)> and
-L<SSL_CTX_set_max_proto_version(3)> instead.
+Use Cisco's version identifier of DTLS_BAD_VER when establishing a DTLSv1
+connection. Only available when using the deprecated DTLSv1_client_method() API.
-=item SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
+=item SSL_OP_CLEANSE_PLAINTEXT
-When performing renegotiation as a server, always start a new session
-(i.e., session resumption requests are only accepted in the initial
-handshake). This option is not needed for clients.
+By default TLS connections keep a copy of received plaintext
+application data in a static buffer until it is overwritten by the
+next portion of data. When enabling SSL_OP_CLEANSE_PLAINTEXT
+deciphered application data is cleansed by calling OPENSSL_cleanse(3)
+after passing data to the application. Data is also cleansed when
+releasing the connection (e.g. L<SSL_free(3)>).
+
+Since OpenSSL only cleanses internal buffers, the application is still
+responsible for cleansing all other buffers. Most notably, this
+applies to buffers passed to functions like L<SSL_read(3)>,
+L<SSL_peek(3)> but also like L<SSL_write(3)>.
+
+=item SSL_OP_COOKIE_EXCHANGE
+
+Turn on Cookie Exchange as described in RFC4347 Section 4.2.1. Only affects
+DTLS connections.
+
+=item SSL_OP_DISABLE_TLSEXT_CA_NAMES
+
+Disable TLS Extension CA Names. You may want to disable it for security reasons
+or for compatibility with some Windows TLS implementations crashing when this
+extension is larger than 1024 bytes.
+
+=item SSL_OP_ENABLE_KTLS
+
+Enable the use of kernel TLS. In order to benefit from kernel TLS OpenSSL must
+have been compiled with support for it, and it must be supported by the
+negotiated ciphersuites and extensions. The specific ciphersuites and extensions
+that are supported may vary by platform and kernel version.
+
+The kernel TLS data-path implements the record layer, and the encryption
+algorithm. The kernel will utilize the best hardware
+available for encryption. Using the kernel data-path should reduce the memory
+footprint of OpenSSL because no buffering is required. Also, the throughput
+should improve because data copy is avoided when user data is encrypted into
+kernel memory instead of the usual encrypt then copy to kernel.
+
+Kernel TLS might not support all the features of OpenSSL. For instance,
+renegotiation, and setting the maximum fragment size is not possible as of
+Linux 4.20.
+
+Note that with kernel TLS enabled some cryptographic operations are performed
+by the kernel directly and not via any available OpenSSL Providers. This might
+be undesirable if, for example, the application requires all cryptographic
+operations to be performed by the FIPS provider.
+
+=item SSL_OP_ENABLE_MIDDLEBOX_COMPAT
+
+If set then dummy Change Cipher Spec (CCS) messages are sent in TLSv1.3. This
+has the effect of making TLSv1.3 look more like TLSv1.2 so that middleboxes that
+do not understand TLSv1.3 will not drop the connection. Regardless of whether
+this option is set or not CCS messages received from the peer will always be
+ignored in TLSv1.3. This option is set by default. To switch it off use
+SSL_clear_options(). A future version of OpenSSL may not set this by default.
+
+=item SSL_OP_IGNORE_UNEXPECTED_EOF
+
+Some TLS implementations do not send the mandatory close_notify alert on
+shutdown. If the application tries to wait for the close_notify alert but the
+peer closes the connection without sending it, an error is generated. When this
+option is enabled the peer does not need to send the close_notify alert and a
+closed connection will be treated as if the close_notify alert was received.
+
+You should only enable this option if the protocol running over TLS
+can detect a truncation attack itself, and that the application is checking for
+that truncation attack.
+
+For more information on shutting down a connection, see L<SSL_shutdown(3)>.
+
+=item SSL_OP_LEGACY_SERVER_CONNECT
+
+Allow legacy insecure renegotiation between OpenSSL and unpatched servers
+B<only>. See the B<SECURE RENEGOTIATION> section for more details.
+
+=item SSL_OP_NO_ANTI_REPLAY
+
+By default, when a server is configured for early data (i.e., max_early_data > 0),
+OpenSSL will switch on replay protection. See L<SSL_read_early_data(3)> for a
+description of the replay protection feature. Anti-replay measures are required
+to comply with the TLSv1.3 specification. Some applications may be able to
+mitigate the replay risks in other ways and in such cases the built in OpenSSL
+functionality is not required. Those applications can turn this feature off by
+setting this option. This is a server-side opton only. It is ignored by
+clients.
=item SSL_OP_NO_COMPRESSION
-Do not use compression even if it is supported.
+Do not use compression even if it is supported. This option is set by default.
+To switch it off use SSL_clear_options().
+
+=item SSL_OP_NO_ENCRYPT_THEN_MAC
+
+Normally clients and servers will transparently attempt to negotiate the
+RFC7366 Encrypt-then-MAC option on TLS and DTLS connection.
+
+If this option is set, Encrypt-then-MAC is disabled. Clients will not
+propose, and servers will not accept the extension.
+
+=item SSL_OP_NO_EXTENDED_MASTER_SECRET
+
+Normally clients and servers will transparently attempt to negotiate the
+RFC7627 Extended Master Secret option on TLS and DTLS connection.
+
+If this option is set, Extended Master Secret is disabled. Clients will
+not propose, and servers will not accept the extension.
=item SSL_OP_NO_QUERY_MTU
Do not query the MTU. Only affects DTLS connections.
-=item SSL_OP_COOKIE_EXCHANGE
+=item SSL_OP_NO_RENEGOTIATION
-Turn on Cookie Exchange as described in RFC4347 Section 4.2.1. Only affects
-DTLS connections.
+Disable all renegotiation in TLSv1.2 and earlier. Do not send HelloRequest
+messages, and ignore renegotiation requests via ClientHello.
+
+=item SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
+
+When performing renegotiation as a server, always start a new session
+(i.e., session resumption requests are only accepted in the initial
+handshake). This option is not needed for clients.
+
+=item SSL_OP_NO_SSLv3, SSL_OP_NO_TLSv1, SSL_OP_NO_TLSv1_1,
+SSL_OP_NO_TLSv1_2, SSL_OP_NO_TLSv1_3, SSL_OP_NO_DTLSv1, SSL_OP_NO_DTLSv1_2
+
+These options turn off the SSLv3, TLSv1, TLSv1.1, TLSv1.2 or TLSv1.3 protocol
+versions with TLS or the DTLSv1, DTLSv1.2 versions with DTLS,
+respectively.
+As of OpenSSL 1.1.0, these options are deprecated, use
+L<SSL_CTX_set_min_proto_version(3)> and
+L<SSL_CTX_set_max_proto_version(3)> instead.
=item SSL_OP_NO_TICKET
@@ -179,35 +296,6 @@ In TLSv1.3 it is possible to suppress all tickets (stateful and stateless) from
being sent by calling L<SSL_CTX_set_num_tickets(3)> or
L<SSL_set_num_tickets(3)>.
-=item SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
-
-Allow legacy insecure renegotiation between OpenSSL and unpatched clients or
-servers. See the B<SECURE RENEGOTIATION> section for more details.
-
-=item SSL_OP_LEGACY_SERVER_CONNECT
-
-Allow legacy insecure renegotiation between OpenSSL and unpatched servers
-B<only>: this option is currently set by default. See the
-B<SECURE RENEGOTIATION> section for more details.
-
-=item SSL_OP_NO_ENCRYPT_THEN_MAC
-
-Normally clients and servers will transparently attempt to negotiate the
-RFC7366 Encrypt-then-MAC option on TLS and DTLS connection.
-
-If this option is set, Encrypt-then-MAC is disabled. Clients will not
-propose, and servers will not accept the extension.
-
-=item SSL_OP_NO_RENEGOTIATION
-
-Disable all renegotiation in TLSv1.2 and earlier. Do not send HelloRequest
-messages, and ignore renegotiation requests via ClientHello.
-
-=item SSL_OP_ALLOW_NO_DHE_KEX
-
-In TLSv1.3 allow a non-(ec)dhe based key exchange mode on resumption. This means
-that there will be no forward secrecy for the resumed session.
-
=item SSL_OP_PRIORITIZE_CHACHA
When SSL_OP_CIPHER_SERVER_PREFERENCE is set, temporarily reprioritize
@@ -217,25 +305,17 @@ those clients (e.g. mobile) use ChaCha20-Poly1305 if that cipher is anywhere
in the server cipher list; but still allows other clients to use AES and other
ciphers. Requires B<SSL_OP_CIPHER_SERVER_PREFERENCE>.
-=item SSL_OP_ENABLE_MIDDLEBOX_COMPAT
-
-If set then dummy Change Cipher Spec (CCS) messages are sent in TLSv1.3. This
-has the effect of making TLSv1.3 look more like TLSv1.2 so that middleboxes that
-do not understand TLSv1.3 will not drop the connection. Regardless of whether
-this option is set or not CCS messages received from the peer will always be
-ignored in TLSv1.3. This option is set by default. To switch it off use
-SSL_clear_options(). A future version of OpenSSL may not set this by default.
+=item SSL_OP_TLS_ROLLBACK_BUG
-=item SSL_OP_NO_ANTI_REPLAY
+Disable version rollback attack detection.
-By default, when a server is configured for early data (i.e., max_early_data > 0),
-OpenSSL will switch on replay protection. See L<SSL_read_early_data(3)> for a
-description of the replay protection feature. Anti-replay measures are required
-to comply with the TLSv1.3 specification. Some applications may be able to
-mitigate the replay risks in other ways and in such cases the built in OpenSSL
-functionality is not required. Those applications can turn this feature off by
-setting this option. This is a server-side opton only. It is ignored by
-clients.
+During the client key exchange, the client must send the same information
+about acceptable SSL/TLS protocol levels as during the first hello. Some
+clients violate this rule by adapting to the server's answer. (Example:
+the client sends a SSLv2 hello and accepts up to SSLv3.1=TLSv1, the server
+only understands up to SSLv3. In this case the client must still use the
+same SSLv3.1=TLSv1 announcement. Some clients step down to SSLv3 with respect
+to the server's answer and violate the version rollback protection.)
=back
@@ -305,7 +385,7 @@ unaware of the unpatched nature of the client.
If the option B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION> is set then
renegotiation B<always> succeeds.
-=head2 Patched OpenSSL client and unpatched server.
+=head2 Patched OpenSSL client and unpatched server
If the option B<SSL_OP_LEGACY_SERVER_CONNECT> or
B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION> is set then initial connections
@@ -313,15 +393,10 @@ and renegotiation between patched OpenSSL clients and unpatched servers
succeeds. If neither option is set then initial connections to unpatched
servers will fail.
-The option B<SSL_OP_LEGACY_SERVER_CONNECT> is currently set by default even
-though it has security implications: otherwise it would be impossible to
-connect to unpatched servers (i.e. all of them initially) and this is clearly
-not acceptable. Renegotiation is permitted because this does not add any
-additional security issues: during an attack clients do not see any
-renegotiations anyway.
-
-As more servers become patched the option B<SSL_OP_LEGACY_SERVER_CONNECT> will
-B<not> be set by default in a future version of OpenSSL.
+Setting the option B<SSL_OP_LEGACY_SERVER_CONNECT> has security implications;
+clients that are willing to connect to servers that do not implement
+RFC 5746 secure renegotiation are subject to attacks such as
+CVE-2009-3555.
OpenSSL client applications wishing to ensure they can connect to unpatched
servers should always B<set> B<SSL_OP_LEGACY_SERVER_CONNECT>
@@ -340,23 +415,23 @@ and renegotiation between OpenSSL and unpatched clients or servers.
=head1 RETURN VALUES
-SSL_CTX_set_options() and SSL_set_options() return the new options bit mask
+SSL_CTX_set_options() and SSL_set_options() return the new options bit-mask
after adding B<options>.
-SSL_CTX_clear_options() and SSL_clear_options() return the new options bit mask
+SSL_CTX_clear_options() and SSL_clear_options() return the new options bit-mask
after clearing B<options>.
-SSL_CTX_get_options() and SSL_get_options() return the current bit mask.
+SSL_CTX_get_options() and SSL_get_options() return the current bit-mask.
SSL_get_secure_renegotiation_support() returns 1 is the peer supports
secure renegotiation and 0 if it does not.
=head1 SEE ALSO
-L<ssl(7)>, L<SSL_new(3)>, L<SSL_clear(3)>,
+L<ssl(7)>, L<SSL_new(3)>, L<SSL_clear(3)>, L<SSL_shutdown(3)>
L<SSL_CTX_set_tmp_dh_callback(3)>,
L<SSL_CTX_set_min_proto_version(3)>,
-L<dhparam(1)>
+L<openssl-dhparam(1)>
=head1 HISTORY
@@ -366,11 +441,20 @@ OpenSSL 0.9.8m.
The B<SSL_OP_PRIORITIZE_CHACHA> and B<SSL_OP_NO_RENEGOTIATION> options
were added in OpenSSL 1.1.1.
+The B<SSL_OP_NO_EXTENDED_MASTER_SECRET> and B<SSL_OP_IGNORE_UNEXPECTED_EOF>
+options were added in OpenSSL 3.0.
+
+The B<SSL_OP_> constants and the corresponding parameter and return values
+of the affected functions were changed to C<uint64_t> type in OpenSSL 3.0.
+For that reason it is no longer possible use the B<SSL_OP_> macro values
+in preprocessor C<#if> conditions. However it is still possible to test
+whether these macros are defined or not.
+
=head1 COPYRIGHT
-Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_psk_client_callback.pod b/doc/man3/SSL_CTX_set_psk_client_callback.pod
index 0273ccb97a83..7ccea7273f83 100644
--- a/doc/man3/SSL_CTX_set_psk_client_callback.pod
+++ b/doc/man3/SSL_CTX_set_psk_client_callback.pod
@@ -107,11 +107,11 @@ the pre-shared key to use during the connection setup phase.
The callback is set using functions SSL_CTX_set_psk_client_callback()
or SSL_set_psk_client_callback(). The callback function is given the
-connection in parameter B<ssl>, a B<NULL>-terminated PSK identity hint
+connection in parameter B<ssl>, a B<NUL>-terminated PSK identity hint
sent by the server in parameter B<hint>, a buffer B<identity> of
-length B<max_identity_len> bytes where the resulting
-B<NUL>-terminated identity is to be stored, and a buffer B<psk> of
-length B<max_psk_len> bytes where the resulting pre-shared key is to
+length B<max_identity_len> bytes (including the B<NUL>-terminator) where the
+resulting B<NUL>-terminated identity is to be stored, and a buffer B<psk>
+of length B<max_psk_len> bytes where the resulting pre-shared key is to
be stored.
The callback for use in TLSv1.2 will also work in TLSv1.3 although it is
@@ -158,6 +158,7 @@ failure. In the event of failure the connection setup fails.
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_CTX_set_psk_find_session_callback(3)>,
L<SSL_set_psk_find_session_callback(3)>
@@ -168,9 +169,9 @@ were added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_quiet_shutdown.pod b/doc/man3/SSL_CTX_set_quiet_shutdown.pod
index 8ed9315df5c4..a99c4c6b9c81 100644
--- a/doc/man3/SSL_CTX_set_quiet_shutdown.pod
+++ b/doc/man3/SSL_CTX_set_quiet_shutdown.pod
@@ -64,7 +64,7 @@ L<SSL_clear(3)>, L<SSL_free(3)>
Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_read_ahead.pod b/doc/man3/SSL_CTX_set_read_ahead.pod
index 6d1e8bd5e8e9..c2fc6fd7dc8e 100644
--- a/doc/man3/SSL_CTX_set_read_ahead.pod
+++ b/doc/man3/SSL_CTX_set_read_ahead.pod
@@ -66,7 +66,7 @@ L<ssl(7)>, L<SSL_pending(3)>
Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_record_padding_callback.pod b/doc/man3/SSL_CTX_set_record_padding_callback.pod
index 13e56f0c57f6..7bf43c3f0d15 100644
--- a/doc/man3/SSL_CTX_set_record_padding_callback.pod
+++ b/doc/man3/SSL_CTX_set_record_padding_callback.pod
@@ -16,7 +16,7 @@ SSL_set_block_padding - install callback to specify TLS 1.3 record padding
#include <openssl/ssl.h>
void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx, size_t (*cb)(SSL *s, int type, size_t len, void *arg));
- void SSL_set_record_padding_callback(SSL *ssl, size_t (*cb)(SSL *s, int type, size_t len, void *arg));
+ int SSL_set_record_padding_callback(SSL *ssl, size_t (*cb)(SSL *s, int type, size_t len, void *arg));
void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg);
void *SSL_CTX_get_record_padding_callback_arg(const SSL_CTX *ctx);
@@ -32,6 +32,8 @@ SSL_set_block_padding - install callback to specify TLS 1.3 record padding
SSL_CTX_set_record_padding_callback() or SSL_set_record_padding_callback()
can be used to assign a callback function I<cb> to specify the padding
for TLS 1.3 records. The value set in B<ctx> is copied to a new SSL by SSL_new().
+Kernel TLS is not possible if the record padding callback is set, and the callback
+function cannot be set if Kernel TLS is already configured for the current SSL object.
SSL_CTX_set_record_padding_callback_arg() and SSL_set_record_padding_callback_arg()
assign a value B<arg> that is passed to the callback when it is invoked. The value
@@ -64,6 +66,9 @@ indicates no padding will be added. A return value that causes the record to
exceed the maximum record size (SSL3_RT_MAX_PLAIN_LENGTH) will pad out to the
maximum record size.
+The SSL_CTX_get_record_padding_callback_arg() function returns 1 on success or 0 if
+the callback function is not set because Kernel TLS is configured for the SSL object.
+
=head1 NOTES
The default behavior is to add no padding to the record.
@@ -84,11 +89,14 @@ L<ssl(7)>, L<SSL_new(3)>
The record padding API was added for TLS 1.3 support in OpenSSL 1.1.1.
+The return type of SSL_CTX_set_record_padding_callback() function was
+changed to int in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_security_level.pod b/doc/man3/SSL_CTX_set_security_level.pod
index f85959e7c045..a4595490013b 100644
--- a/doc/man3/SSL_CTX_set_security_level.pod
+++ b/doc/man3/SSL_CTX_set_security_level.pod
@@ -77,7 +77,9 @@ parameters offering below 80 bits of security are excluded. As a result RSA,
DSA and DH keys shorter than 1024 bits and ECC keys shorter than 160 bits
are prohibited. All export cipher suites are prohibited since they all offer
less than 80 bits of security. SSL version 2 is prohibited. Any cipher suite
-using MD5 for the MAC is also prohibited.
+using MD5 for the MAC is also prohibited. Note that signatures using SHA1
+and MD5 are also forbidden at this level as they have less than 80 security
+bits.
=item B<Level 2>
@@ -147,10 +149,11 @@ key size or the DH parameter size will abort the handshake with a fatal
alert.
Attempts to set certificates or parameters with insufficient security are
-also blocked. For example trying to set a certificate using a 512 bit RSA
-key using SSL_CTX_use_certificate() at level 1. Applications which do not
-check the return values for errors will misbehave: for example it might
-appear that a certificate is not set at all because it had been rejected.
+also blocked. For example trying to set a certificate using a 512 bit RSA key
+or a certificate with a signature with SHA1 digest at level 1 using
+SSL_CTX_use_certificate(). Applications which do not check the return values
+for errors will misbehave: for example it might appear that a certificate is
+not set at all because it had been rejected.
=head1 RETURN VALUES
@@ -168,15 +171,19 @@ to the security callback or NULL if the callback is not set.
SSL_CTX_get0_security_ex_data() and SSL_get0_security_ex_data() return the extra
data pointer or NULL if the ex data is not set.
+=head1 SEE ALSO
+
+L<ssl(7)>
+
=head1 HISTORY
These functions were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_session_cache_mode.pod b/doc/man3/SSL_CTX_set_session_cache_mode.pod
index 38603f250dab..25b588f58091 100644
--- a/doc/man3/SSL_CTX_set_session_cache_mode.pod
+++ b/doc/man3/SSL_CTX_set_session_cache_mode.pod
@@ -105,6 +105,11 @@ prevents these additions to the internal cache as well.
Enable both SSL_SESS_CACHE_NO_INTERNAL_LOOKUP and
SSL_SESS_CACHE_NO_INTERNAL_STORE at the same time.
+=item SSL_SESS_CACHE_UPDATE_TIME
+
+Updates the timestamp of the session when it is used, increasing the lifespan
+of the session. The session timeout applies to last use, rather then creation
+time.
=back
@@ -131,9 +136,9 @@ L<SSL_CTX_flush_sessions(3)>
=head1 COPYRIGHT
-Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_session_id_context.pod b/doc/man3/SSL_CTX_set_session_id_context.pod
index ccd37ba681d3..c9572bd0d83f 100644
--- a/doc/man3/SSL_CTX_set_session_id_context.pod
+++ b/doc/man3/SSL_CTX_set_session_id_context.pod
@@ -84,7 +84,7 @@ L<ssl(7)>
Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_session_ticket_cb.pod b/doc/man3/SSL_CTX_set_session_ticket_cb.pod
index aa520f4a6261..6bb12cddc3fd 100644
--- a/doc/man3/SSL_CTX_set_session_ticket_cb.pod
+++ b/doc/man3/SSL_CTX_set_session_ticket_cb.pod
@@ -43,7 +43,7 @@ decryption has been attempted and any session ticket application data is
available. If ticket decryption was successful then the B<ss> argument contains
the session data. The B<keyname> and B<keyname_len> arguments identify the key
used to decrypt the session ticket. The B<status> argument is the result of the
-ticket decryption. See the L<NOTES> section below for further details. The value
+ticket decryption. See the L</NOTES> section below for further details. The value
of B<arg> is the same as that given to SSL_CTX_set_session_ticket_cb(). The
B<dec_cb> callback is defined as type B<SSL_CTX_decrypt_session_ticket_fn>.
@@ -168,7 +168,7 @@ failure.
The B<gen_cb> callback must return 1 to continue the connection. A return of 0
will terminate the connection with an INTERNAL_ERROR alert.
-The B<dec_cb> callback must return a value as described in L<NOTES> above.
+The B<dec_cb> callback must return a value as described in L</NOTES> above.
=head1 SEE ALSO
@@ -184,7 +184,7 @@ and SSL_SESSION_get_ticket_appdata() functions were added in OpenSSL 1.1.1.
Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_split_send_fragment.pod b/doc/man3/SSL_CTX_set_split_send_fragment.pod
index d8fd3f5390c8..5097404398b2 100644
--- a/doc/man3/SSL_CTX_set_split_send_fragment.pod
+++ b/doc/man3/SSL_CTX_set_split_send_fragment.pod
@@ -28,7 +28,7 @@ SSL_SESSION_get_max_fragment_length - Control fragment size settings and pipelin
int SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode);
int SSL_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode);
- uint8_t SSL_SESSION_get_max_fragment_length(SSL_SESSION *session);
+ uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *session);
=head1 DESCRIPTION
@@ -164,6 +164,7 @@ all these functions are implemented using macros.
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_CTX_set_read_ahead(3)>, L<SSL_pending(3)>
=head1 HISTORY
@@ -178,9 +179,9 @@ and SSL_SESSION_get_max_fragment_length() functions were added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_srp_password.pod b/doc/man3/SSL_CTX_set_srp_password.pod
new file mode 100644
index 000000000000..7e7e98c8dcd9
--- /dev/null
+++ b/doc/man3/SSL_CTX_set_srp_password.pod
@@ -0,0 +1,224 @@
+=pod
+
+=head1 NAME
+
+SSL_CTX_set_srp_username,
+SSL_CTX_set_srp_password,
+SSL_CTX_set_srp_strength,
+SSL_CTX_set_srp_cb_arg,
+SSL_CTX_set_srp_username_callback,
+SSL_CTX_set_srp_client_pwd_callback,
+SSL_CTX_set_srp_verify_param_callback,
+SSL_set_srp_server_param,
+SSL_set_srp_server_param_pw,
+SSL_get_srp_g,
+SSL_get_srp_N,
+SSL_get_srp_username,
+SSL_get_srp_userinfo
+- SRP control operations
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name);
+ int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password);
+ int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength);
+ int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg);
+ int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx,
+ int (*cb) (SSL *s, int *ad, void *arg));
+ int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx,
+ char *(*cb) (SSL *s, void *arg));
+ int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx,
+ int (*cb) (SSL *s, void *arg));
+
+ int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
+ BIGNUM *sa, BIGNUM *v, char *info);
+ int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass,
+ const char *grp);
+
+ BIGNUM *SSL_get_srp_g(SSL *s);
+ BIGNUM *SSL_get_srp_N(SSL *s);
+
+ char *SSL_get_srp_username(SSL *s);
+ char *SSL_get_srp_userinfo(SSL *s);
+
+=head1 DESCRIPTION
+
+All of the functions described on this page are deprecated. There are no
+available replacement functions at this time.
+
+These functions provide access to SRP (Secure Remote Password) parameters,
+an alternate authentication mechanism for TLS. SRP allows the use of usernames
+and passwords over unencrypted channels without revealing the password to an
+eavesdropper. SRP also supplies a shared secret at the end of the authentication
+sequence that can be used to generate encryption keys.
+
+The SRP protocol, version 3 is specified in RFC 2945. SRP version 6 is described
+in RFC 5054 with applications to TLS authentication.
+
+The SSL_CTX_set_srp_username() function sets the SRP username for B<ctx>. This
+should be called on the client prior to creating a connection to the server.
+The length of B<name> must be shorter or equal to 255 characters.
+
+The SSL_CTX_set_srp_password() function sets the SRP password for B<ctx>. This
+may be called on the client prior to creating a connection to the server.
+This overrides the effect of SSL_CTX_set_srp_client_pwd_callback().
+
+The SSL_CTX_set_srp_strength() function sets the SRP strength for B<ctx>. This
+is the minimal length of the SRP prime in bits. If not specified 1024 is used.
+If not satisfied by the server key exchange the connection will be rejected.
+
+The SSL_CTX_set_srp_cb_arg() function sets an extra parameter that will
+be passed to all following callbacks as B<arg>.
+
+The SSL_CTX_set_srp_username_callback() function sets the server side callback
+that is invoked when an SRP username is found in a ClientHello.
+The callback parameters are the SSL connection B<s>, a writable error flag B<ad>
+and the extra argument B<arg> set by SSL_CTX_set_srp_cb_arg().
+This callback should setup the server for the key exchange by calling
+SSL_set_srp_server_param() with the appropriate parameters for the received
+username. The username can be obtained by calling SSL_get_srp_username().
+See L<SRP_VBASE_init(3)> to parse the verifier file created by L<openssl-srp(1)> or
+L<SRP_create_verifier(3)> to generate it.
+The callback should return B<SSL_ERROR_NONE> to proceed with the server key exchange,
+B<SSL3_AL_FATAL> for a fatal error or any value < 0 for a retryable error.
+In the event of a B<SSL3_AL_FATAL> the alert flag given by B<*al> will be sent
+back. By default this will be B<SSL_AD_UNKNOWN_PSK_IDENTITY>.
+
+The SSL_CTX_set_srp_client_pwd_callback() function sets the client password
+callback on the client.
+The callback parameters are the SSL connection B<s> and the extra argument B<arg>
+set by SSL_CTX_set_srp_cb_arg().
+The callback will be called as part of the generation of the client secrets.
+It should return the client password in text form or NULL to abort the connection.
+The resulting memory will be freed by the library as part of the callback resolution.
+This overrides the effect of SSL_CTX_set_srp_password().
+
+The SSL_CTX_set_srp_verify_param_callback() sets the SRP gN parameter verification
+callback on the client. This allows the client to perform custom verification when
+receiving the server SRP proposed parameters.
+The callback parameters are the SSL connection B<s> and the extra argument B<arg>
+set by SSL_CTX_set_srp_cb_arg().
+The callback should return a positive value to accept the server parameters.
+Returning 0 or a negative value will abort the connection. The server parameters
+can be obtained by calling SSL_get_srp_N() and SSL_get_srp_g().
+Sanity checks are already performed by the library after the handshake
+(B % N non zero, check against the strength parameter) and are not necessary.
+If no callback is set the g and N parameters will be checked against
+known RFC 5054 values.
+
+The SSL_set_srp_server_param() function sets all SRP parameters for
+the connection B<s>. B<N> and B<g> are the SRP group parameters, B<sa> is the
+user salt, B<v> the password verifier and B<info> is the optional user info.
+
+The SSL_set_srp_server_param_pw() function sets all SRP parameters for the
+connection B<s> by generating a random salt and a password verifier.
+B<user> is the username, B<pass> the password and B<grp> the SRP group parameters
+identifier for L<SRP_get_default_gN(3)>.
+
+The SSL_get_srp_g() function returns the SRP group generator for B<s>, or from
+the underlying SSL_CTX if it is NULL.
+
+The SSL_get_srp_N() function returns the SRP prime for B<s>, or from
+the underlying SSL_CTX if it is NULL.
+
+The SSL_get_srp_username() function returns the SRP username for B<s>, or from
+the underlying SSL_CTX if it is NULL.
+
+The SSL_get_srp_userinfo() function returns the SRP user info for B<s>, or from
+the underlying SSL_CTX if it is NULL.
+
+=head1 RETURN VALUES
+
+All SSL_CTX_set_* functions return 1 on success and 0 on failure.
+
+SSL_set_srp_server_param() returns 1 on success and -1 on failure.
+
+The SSL_get_SRP_* functions return a pointer to the requested data, the memory
+is owned by the library and should not be freed by the caller.
+
+=head1 EXAMPLES
+
+Setup SRP parameters on the client:
+
+ #include <openssl/ssl.h>
+
+ const char *username = "username";
+ const char *password = "password";
+
+ SSL_CTX *ctx = SSL_CTX_new(TLS_client_method());
+ if (!ctx)
+ /* Error */
+ if (!SSL_CTX_set_srp_username(ctx, username))
+ /* Error */
+ if (!SSL_CTX_set_srp_password(ctx, password))
+ /* Error */
+
+Setup SRP server with verifier file:
+
+ #include <openssl/srp.h>
+ #include <openssl/ssl.h>
+
+ const char *srpvfile = "password.srpv";
+
+ int srpServerCallback(SSL *s, int *ad, void *arg)
+ {
+ SRP_VBASE *srpData = (SRP_VBASE*) arg;
+ char *username = SSL_get_srp_username(s);
+
+ SRP_user_pwd *user_pwd = SRP_VBASE_get1_by_user(srpData, username);
+ if (!user_pwd)
+ /* Error */
+ return SSL3_AL_FATAL;
+
+ if (SSL_set_srp_server_param(s, user_pwd->N, user_pwd->g,
+ user_pwd->s, user_pwd->v, user_pwd->info) < 0)
+ /* Error */
+
+ SRP_user_pwd_free(user_pwd);
+ return SSL_ERROR_NONE;
+ }
+
+ SSL_CTX *ctx = SSL_CTX_new(TLS_server_method());
+ if (!ctx)
+ /* Error */
+
+ /*
+ * seedKey should contain a NUL terminated sequence
+ * of random non NUL bytes
+ */
+ const char *seedKey;
+
+ SRP_VBASE *srpData = SRP_VBASE_new(seedKey);
+ if (SRP_VBASE_init(srpData, (char*) srpvfile) != SRP_NO_ERROR)
+ /* Error */
+
+ SSL_CTX_set_srp_cb_arg(ctx, srpData);
+ SSL_CTX_set_srp_username_callback(ctx, srpServerCallback);
+
+=head1 SEE ALSO
+
+L<ssl(7)>,
+L<openssl-srp(1)>,
+L<SRP_VBASE_new(3)>,
+L<SRP_create_verifier(3)>
+
+=head1 HISTORY
+
+These functions were added in OpenSSL 1.0.1 and deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/SSL_CTX_set_ssl_version.pod b/doc/man3/SSL_CTX_set_ssl_version.pod
index 6c132756f2ca..10aa63f729c8 100644
--- a/doc/man3/SSL_CTX_set_ssl_version.pod
+++ b/doc/man3/SSL_CTX_set_ssl_version.pod
@@ -2,7 +2,7 @@
=head1 NAME
-SSL_CTX_set_ssl_version, SSL_set_ssl_method, SSL_get_ssl_method
+SSL_CTX_set_ssl_version, SSL_CTX_get_ssl_method, SSL_set_ssl_method, SSL_get_ssl_method
- choose a new TLS/SSL method
=head1 SYNOPSIS
@@ -10,20 +10,27 @@ SSL_CTX_set_ssl_version, SSL_set_ssl_method, SSL_get_ssl_method
#include <openssl/ssl.h>
int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *method);
+ const SSL_METHOD *SSL_CTX_get_ssl_method(const SSL_CTX *ctx);
+
int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method);
const SSL_METHOD *SSL_get_ssl_method(const SSL *ssl);
=head1 DESCRIPTION
SSL_CTX_set_ssl_version() sets a new default TLS/SSL B<method> for SSL objects
-newly created from this B<ctx>. SSL objects already created with
-L<SSL_new(3)> are not affected, except when
-L<SSL_clear(3)> is being called.
+newly created from this B<ctx>. Most of the configuration attached to the
+SSL_CTX object is retained, with the exception of the configured TLS ciphers,
+which are reset to the default values. SSL objects already created from this
+SSL_CTX with L<SSL_new(3)> are not affected, except when L<SSL_clear(3)> is
+being called, as described below.
+
+SSL_CTX_get_ssl_method() returns the SSL_METHOD which was used to construct the
+SSL_CTX.
SSL_set_ssl_method() sets a new TLS/SSL B<method> for a particular B<ssl>
object. It may be reset, when SSL_clear() is called.
-SSL_get_ssl_method() returns a function pointer to the TLS/SSL method
+SSL_get_ssl_method() returns a pointer to the TLS/SSL method
set in B<ssl>.
=head1 NOTES
@@ -35,6 +42,11 @@ When L<SSL_clear(3)> is called and no session is connected to
an SSL object, the method of the SSL object is reset to the method currently
set in the corresponding SSL_CTX object.
+SSL_CTX_set_version() has unusual semantics and no clear use case;
+it would usually be preferable to create a new SSL_CTX object than to
+try to reuse an existing one in this fashion. Its usage is considered
+deprecated.
+
=head1 RETURN VALUES
The following return values can occur for SSL_CTX_set_ssl_version()
@@ -52,17 +64,24 @@ The operation succeeded.
=back
+SSL_CTX_get_ssl_method() and SSL_get_ssl_method() always return non-NULL
+pointers.
+
=head1 SEE ALSO
L<SSL_CTX_new(3)>, L<SSL_new(3)>,
L<SSL_clear(3)>, L<ssl(7)>,
L<SSL_set_connect_state(3)>
+=head1 HISTORY
+
+SSL_CTX_set_ssl_version() was deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_stateless_cookie_generate_cb.pod b/doc/man3/SSL_CTX_set_stateless_cookie_generate_cb.pod
index aa167f6332ed..b42577f7cf2e 100644
--- a/doc/man3/SSL_CTX_set_stateless_cookie_generate_cb.pod
+++ b/doc/man3/SSL_CTX_set_stateless_cookie_generate_cb.pod
@@ -75,6 +75,7 @@ Neither function returns a value.
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_stateless(3)>,
L<DTLSv1_listen(3)>
@@ -87,7 +88,7 @@ SSL_CTX_set_stateless_cookie_verify_cb() were added in OpenSSL 1.1.1.
Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_timeout.pod b/doc/man3/SSL_CTX_set_timeout.pod
index e76353cfd4b9..9aca5374be01 100644
--- a/doc/man3/SSL_CTX_set_timeout.pod
+++ b/doc/man3/SSL_CTX_set_timeout.pod
@@ -70,7 +70,7 @@ L<SSL_get_default_timeout(3)>
Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_tlsext_servername_callback.pod b/doc/man3/SSL_CTX_set_tlsext_servername_callback.pod
index 0c21cfdb6bc7..a0a4bd636785 100644
--- a/doc/man3/SSL_CTX_set_tlsext_servername_callback.pod
+++ b/doc/man3/SSL_CTX_set_tlsext_servername_callback.pod
@@ -171,7 +171,7 @@ NULL.
Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_tlsext_status_cb.pod b/doc/man3/SSL_CTX_set_tlsext_status_cb.pod
index cb40a9dbcbcb..c63b3be6cfa8 100644
--- a/doc/man3/SSL_CTX_set_tlsext_status_cb.pod
+++ b/doc/man3/SSL_CTX_set_tlsext_status_cb.pod
@@ -106,6 +106,10 @@ SSL_get_tlsext_status_type() returns B<TLSEXT_STATUSTYPE_ocsp> on the client
side if SSL_set_tlsext_status_type() was previously called, or on the server
side if the client requested OCSP stapling. Otherwise -1 is returned.
+=head1 SEE ALSO
+
+L<ssl(7)>
+
=head1 HISTORY
The SSL_get_tlsext_status_type(), SSL_CTX_get_tlsext_status_type()
@@ -115,7 +119,7 @@ and SSL_CTX_set_tlsext_status_type() functions were added in OpenSSL 1.1.0.
Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod b/doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod
index 15642f48f1e5..5d178bb8e4de 100644
--- a/doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod
+++ b/doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod
@@ -2,20 +2,31 @@
=head1 NAME
-SSL_CTX_set_tlsext_ticket_key_cb - set a callback for session ticket processing
+SSL_CTX_set_tlsext_ticket_key_evp_cb,
+SSL_CTX_set_tlsext_ticket_key_cb
+- set a callback for session ticket processing
=head1 SYNOPSIS
#include <openssl/tls1.h>
- long SSL_CTX_set_tlsext_ticket_key_cb(SSL_CTX sslctx,
+ int SSL_CTX_set_tlsext_ticket_key_evp_cb(SSL_CTX sslctx,
+ int (*cb)(SSL *s, unsigned char key_name[16],
+ unsigned char iv[EVP_MAX_IV_LENGTH],
+ EVP_CIPHER_CTX *ctx, EVP_MAC_CTX *hctx, int enc));
+
+The following function has been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ int SSL_CTX_set_tlsext_ticket_key_cb(SSL_CTX sslctx,
int (*cb)(SSL *s, unsigned char key_name[16],
unsigned char iv[EVP_MAX_IV_LENGTH],
EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc));
=head1 DESCRIPTION
-SSL_CTX_set_tlsext_ticket_key_cb() sets a callback function I<cb> for handling
+SSL_CTX_set_tlsext_ticket_key_evp_cb() sets a callback function I<cb> for handling
session tickets for the ssl context I<sslctx>. Session tickets, defined in
RFC5077 provide an enhanced session resumption capability where the server
implementation is not required to maintain per session state. It only applies
@@ -38,7 +49,8 @@ ticket information or it starts a full TLS handshake to create a new session
ticket.
Before the callback function is started I<ctx> and I<hctx> have been
-initialised with L<EVP_CIPHER_CTX_reset(3)> and L<HMAC_CTX_reset(3)> respectively.
+initialised with L<EVP_CIPHER_CTX_reset(3)> and L<EVP_MAC_CTX_new(3)>
+respectively.
For new sessions tickets, when the client doesn't present a session ticket, or
an attempted retrieval of the ticket failed, or a renew option was indicated,
@@ -49,12 +61,13 @@ I<iv>, and set the cipher context I<ctx> and the hash context I<hctx>.
The I<name> is 16 characters long and is used as a key identifier.
The I<iv> length is the length of the IV of the corresponding cipher. The
-maximum IV length is B<EVP_MAX_IV_LENGTH> bytes defined in B<evp.h>.
+maximum IV length is B<EVP_MAX_IV_LENGTH> bytes defined in F<< <openssl/evp.h> >>.
The initialization vector I<iv> should be a random value. The cipher context
I<ctx> should use the initialisation vector I<iv>. The cipher context can be
-set using L<EVP_EncryptInit_ex(3)>. The hmac context can be set using
-L<HMAC_Init_ex(3)>.
+set using L<EVP_EncryptInit_ex(3)>. The hmac context and digest can be set using
+L<EVP_MAC_CTX_set_params(3)> with the B<OSSL_MAC_PARAM_KEY> and
+B<OSSL_MAC_PARAM_DIGEST> parameters respectively.
When the client presents a session ticket, the callback function with be called
with I<enc> set to 0 indicating that the I<cb> function should retrieve a set
@@ -62,8 +75,9 @@ of parameters. In this case I<name> and I<iv> have already been parsed out of
the session ticket. The OpenSSL library expects that the I<name> will be used
to retrieve a cryptographic parameters and that the cryptographic context
I<ctx> will be set with the retrieved parameters and the initialization vector
-I<iv>. using a function like L<EVP_DecryptInit_ex(3)>. The I<hctx> needs to be
-set using L<HMAC_Init_ex(3)>.
+I<iv>. using a function like L<EVP_DecryptInit_ex(3)>. The key material and
+digest for I<hctx> need to be set using L<EVP_MAC_CTX_set_params(3)> with the
+B<OSSL_MAC_PARAM_KEY> and B<OSSL_MAC_PARAM_DIGEST> parameters respectively.
If the I<name> is still valid but a renewal of the ticket is required the
callback function should return 2. The library will call the callback again
@@ -102,6 +116,14 @@ This indicates an error.
=back
+The SSL_CTX_set_tlsext_ticket_key_cb() function is identical to
+SSL_CTX_set_tlsext_ticket_key_evp_cb() except that it takes a deprecated
+HMAC_CTX pointer instead of an EVP_MAC_CTX one.
+Before this callback function is started I<hctx> will have been
+initialised with L<EVP_MAC_CTX_new(3)> and the digest set with
+L<EVP_MAC_CTX_set_params(3)>.
+The I<hctx> key material can be set using L<HMAC_Init_ex(3)>.
+
=head1 NOTES
Session resumption shortcuts the TLS so that the client certificate
@@ -129,13 +151,14 @@ Returns 1 to indicate the callback function was set and 0 otherwise.
Reference Implementation:
- SSL_CTX_set_tlsext_ticket_key_cb(SSL, ssl_tlsext_ticket_key_cb);
+ SSL_CTX_set_tlsext_ticket_key_evp_cb(SSL, ssl_tlsext_ticket_key_cb);
...
static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16],
unsigned char *iv, EVP_CIPHER_CTX *ctx,
- HMAC_CTX *hctx, int enc)
+ EVP_MAC_CTX *hctx, int enc)
{
+ OSSL_PARAM params[3];
your_type_t *key; /* something that you need to implement */
if (enc) { /* create new session */
@@ -156,8 +179,17 @@ Reference Implementation:
}
memcpy(key_name, key->name, 16);
- EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key->aes_key, iv);
- HMAC_Init_ex(&hctx, key->hmac_key, 32, EVP_sha256(), NULL);
+ if (EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key->aes_key,
+ iv) == 0)
+ return -1; /* error in cipher initialisation */
+
+ params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ key->hmac_key, 32);
+ params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
+ "sha256", 0);
+ params[2] = OSSL_PARAM_construct_end();
+ if (EVP_MAC_CTX_set_params(hctx, params) == 0)
+ return -1; /* error in mac initialisation */
return 1;
@@ -168,8 +200,17 @@ Reference Implementation:
if (key == NULL || key->expire < t)
return 0;
- HMAC_Init_ex(&hctx, key->hmac_key, 32, EVP_sha256(), NULL);
- EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key->aes_key, iv);
+ params[0] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ key->hmac_key, 32);
+ params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
+ "sha256", 0);
+ params[2] = OSSL_PARAM_construct_end();
+ if (EVP_MAC_CTX_set_params(hctx, params) == 0)
+ return -1; /* error in mac initialisation */
+
+ if (EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key->aes_key,
+ iv) == 0)
+ return -1; /* error in cipher initialisation */
if (key->expire < t - RENEW_TIME) { /* RENEW_TIME: implement */
/*
@@ -191,11 +232,18 @@ L<SSL_CTX_sess_number(3)>,
L<SSL_CTX_sess_set_get_cb(3)>,
L<SSL_CTX_set_session_id_context(3)>,
+=head1 HISTORY
+
+The SSL_CTX_set_tlsext_ticket_key_cb() function was deprecated in OpenSSL 3.0.
+
+The SSL_CTX_set_tlsext_ticket_key_evp_cb() function was introduced in
+OpenSSL 3.0.
+
=head1 COPYRIGHT
Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_tlsext_use_srtp.pod b/doc/man3/SSL_CTX_set_tlsext_use_srtp.pod
index e501934a7579..e91f32b7f8ec 100644
--- a/doc/man3/SSL_CTX_set_tlsext_use_srtp.pod
+++ b/doc/man3/SSL_CTX_set_tlsext_use_srtp.pod
@@ -97,13 +97,14 @@ object if one has been negotiated or NULL otherwise.
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_export_keying_material(3)>
=head1 COPYRIGHT
Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_tmp_dh_callback.pod b/doc/man3/SSL_CTX_set_tmp_dh_callback.pod
index fba649f8f572..4daf78b8d334 100644
--- a/doc/man3/SSL_CTX_set_tmp_dh_callback.pod
+++ b/doc/man3/SSL_CTX_set_tmp_dh_callback.pod
@@ -2,12 +2,24 @@
=head1 NAME
-SSL_CTX_set_tmp_dh_callback, SSL_CTX_set_tmp_dh, SSL_set_tmp_dh_callback, SSL_set_tmp_dh - handle DH keys for ephemeral key exchange
+SSL_CTX_set_dh_auto, SSL_set_dh_auto, SSL_CTX_set0_tmp_dh_pkey,
+SSL_set0_tmp_dh_pkey, SSL_CTX_set_tmp_dh_callback, SSL_CTX_set_tmp_dh,
+SSL_set_tmp_dh_callback, SSL_set_tmp_dh
+- handle DH keys for ephemeral key exchange
=head1 SYNOPSIS
#include <openssl/ssl.h>
+ long SSL_CTX_set_dh_auto(SSL_CTX *ctx, int onoff);
+ long SSL_set_dh_auto(SSL *s, int onoff);
+ int SSL_CTX_set0_tmp_dh_pkey(SSL_CTX *ctx, EVP_PKEY *dhpkey);
+ int SSL_set0_tmp_dh_pkey(SSL *s, EVP_PKEY *dhpkey);
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
DH *(*tmp_dh_callback)(SSL *ssl, int is_export,
int keylength));
@@ -16,37 +28,23 @@ SSL_CTX_set_tmp_dh_callback, SSL_CTX_set_tmp_dh, SSL_set_tmp_dh_callback, SSL_se
void SSL_set_tmp_dh_callback(SSL *ctx,
DH *(*tmp_dh_callback)(SSL *ssl, int is_export,
int keylength));
- long SSL_set_tmp_dh(SSL *ssl, DH *dh)
+ long SSL_set_tmp_dh(SSL *ssl, DH *dh);
=head1 DESCRIPTION
-SSL_CTX_set_tmp_dh_callback() sets the callback function for B<ctx> to be
-used when a DH parameters are required to B<tmp_dh_callback>.
-The callback is inherited by all B<ssl> objects created from B<ctx>.
-
-SSL_CTX_set_tmp_dh() sets DH parameters to be used to be B<dh>.
-The key is inherited by all B<ssl> objects created from B<ctx>.
-
-SSL_set_tmp_dh_callback() sets the callback only for B<ssl>.
+The functions described on this page are relevant for servers only.
-SSL_set_tmp_dh() sets the parameters only for B<ssl>.
+Some ciphersuites may use ephemeral Diffie-Hellman (DH) key exchange. In these
+cases, the session data is negotiated using the ephemeral/temporary DH key and
+the key supplied and certified by the certificate chain is only used for
+signing. Anonymous ciphers (without a permanent server key) also use ephemeral
+DH keys.
-These functions apply to SSL/TLS servers only.
-
-=head1 NOTES
-
-When using a cipher with RSA authentication, an ephemeral DH key exchange
-can take place. Ciphers with DSA keys always use ephemeral DH keys as well.
-In these cases, the session data are negotiated using the
-ephemeral/temporary DH key and the key supplied and certified
-by the certificate chain is only used for signing.
-Anonymous ciphers (without a permanent server key) also use ephemeral DH keys.
-
-Using ephemeral DH key exchange yields forward secrecy, as the connection
-can only be decrypted, when the DH key is known. By generating a temporary
+Using ephemeral DH key exchange yields forward secrecy as the connection
+can only be decrypted when the DH key is known. By generating a temporary
DH key inside the server application that is lost when the application
is left, it becomes impossible for an attacker to decrypt past sessions,
-even if he gets hold of the normal (certified) key, as this key was
+even if they get hold of the normal (certified) key, as this key was
only used for signing.
In order to perform a DH key exchange the server must use a DH group
@@ -54,80 +52,69 @@ In order to perform a DH key exchange the server must use a DH group
a new DH key during the negotiation.
As generating DH parameters is extremely time consuming, an application
-should not generate the parameters on the fly but supply the parameters.
-DH parameters can be reused, as the actual key is newly generated during
-the negotiation. The risk in reusing DH parameters is that an attacker
-may specialize on a very often used DH group. Applications should therefore
-generate their own DH parameters during the installation process using the
-openssl L<dhparam(1)> application. This application
-guarantees that "strong" primes are used.
-
-Files dh2048.pem, and dh4096.pem in the 'apps' directory of the current
-version of the OpenSSL distribution contain the 'SKIP' DH parameters,
-which use safe primes and were generated verifiably pseudo-randomly.
-These files can be converted into C code using the B<-C> option of the
-L<dhparam(1)> application. Generation of custom DH
-parameters during installation should still be preferred to stop an
-attacker from specializing on a commonly used group. File dh1024.pem
-contains old parameters that must not be used by applications.
-
-An application may either directly specify the DH parameters or
-can supply the DH parameters via a callback function.
-
-Previous versions of the callback used B<is_export> and B<keylength>
-parameters to control parameter generation for export and non-export
-cipher suites. Modern servers that do not support export cipher suites
-are advised to either use SSL_CTX_set_tmp_dh() or alternatively, use
-the callback but ignore B<keylength> and B<is_export> and simply
-supply at least 2048-bit parameters in the callback.
+should not generate the parameters on the fly. DH parameters can be reused, as
+the actual key is newly generated during the negotiation.
+
+Typically applications should use well know DH parameters that have built-in
+support in OpenSSL. The macros SSL_CTX_set_dh_auto() and SSL_set_dh_auto()
+configure OpenSSL to use the default built-in DH parameters for the B<SSL_CTX>
+and B<SSL> objects respectively. Passing a value of 1 in the I<onoff> parameter
+switches the feature on, and passing a value of 0 switches it off. The default
+setting is off.
+
+If "auto" DH parameters are switched on then the parameters will be selected to
+be consistent with the size of the key associated with the server's certificate.
+If there is no certificate (e.g. for PSK ciphersuites), then it it will be
+consistent with the size of the negotiated symmetric cipher key.
+
+Applications may supply their own DH parameters instead of using the built-in
+values. This approach is discouraged and applications should in preference use
+the built-in parameter support described above. Applications wishing to supply
+their own DH parameters should call SSL_CTX_set0_tmp_dh_pkey() or
+SSL_set0_tmp_dh_pkey() to supply the parameters for the B<SSL_CTX> or B<SSL>
+respectively. The parameters should be supplied in the I<dhpkey> argument as
+an B<EVP_PKEY> containg DH parameters. Ownership of the I<dhpkey> value is
+passed to the B<SSL_CTX> or B<SSL> object as a result of this call, and so the
+caller should not free it if the function call is succesful.
+
+The deprecated macros SSL_CTX_set_tmp_dh() and SSL_set_tmp_dh() do the same
+thing as SSL_CTX_set0_tmp_dh_pkey() and SSL_set0_tmp_dh_pkey() except that the
+DH parameters are supplied in a B<DH> object instead in the I<dh> argument, and
+ownership of the B<DH> object is retained by the application. Applications
+should use "auto" parameters instead, or call SSL_CTX_set0_tmp_dh_pkey() or
+SSL_set0_tmp_dh_pkey() as appropriate.
+
+An application may instead specify the DH parameters via a callback function
+using the functions SSL_CTX_set_tmp_dh_callback() or SSL_set_tmp_dh_callback()
+to set the callback for the B<SSL_CTX> or B<SSL> object respectively. These
+functions are deprecated. Applications should instead use "auto" parameters, or
+specify the parameters via SSL_CTX_set0_tmp_dh_pkey() or SSL_set0_tmp_dh_pkey()
+as appropriate.
+
+The callback will be invoked during a connection when DH parameters are
+required. The B<SSL> object for the current connection is supplied as an
+argument. Previous versions of OpenSSL used the B<is_export> and B<keylength>
+arguments to control parameter generation for export and non-export
+cipher suites. Modern OpenSSL does not support export ciphersuites and so these
+arguments are unused and can be ignored by the callback. The callback should
+return the parameters to be used in a DH object. Ownership of the DH object is
+retained by the application and should later be freed.
=head1 RETURN VALUES
-SSL_CTX_set_tmp_dh_callback() and SSL_set_tmp_dh_callback() do not return
-diagnostic output.
-
-SSL_CTX_set_tmp_dh() and SSL_set_tmp_dh() do return 1 on success and 0
-on failure. Check the error queue to find out the reason of failure.
-
-=head1 EXAMPLES
-
-Setup DH parameters with a key length of 2048 bits. (Error handling
-partly left out.)
-
-Command-line parameter generation:
-
- $ openssl dhparam -out dh_param_2048.pem 2048
-
-Code for setting up parameters during server initialization:
-
- SSL_CTX ctx = SSL_CTX_new();
-
- DH *dh_2048 = NULL;
- FILE *paramfile = fopen("dh_param_2048.pem", "r");
-
- if (paramfile) {
- dh_2048 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
- fclose(paramfile);
- } else {
- /* Error. */
- }
- if (dh_2048 == NULL)
- /* Error. */
- if (SSL_CTX_set_tmp_dh(ctx, dh_2048) != 1)
- /* Error. */
- ...
+All of these functions/macros return 1 for success or 0 on error.
=head1 SEE ALSO
L<ssl(7)>, L<SSL_CTX_set_cipher_list(3)>,
L<SSL_CTX_set_options(3)>,
-L<ciphers(1)>, L<dhparam(1)>
+L<openssl-ciphers(1)>, L<openssl-dhparam(1)>
=head1 COPYRIGHT
-Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_set_tmp_ecdh.pod b/doc/man3/SSL_CTX_set_tmp_ecdh.pod
new file mode 100644
index 000000000000..8e75ec708f63
--- /dev/null
+++ b/doc/man3/SSL_CTX_set_tmp_ecdh.pod
@@ -0,0 +1,50 @@
+=pod
+
+=head1 NAME
+
+SSL_CTX_set_tmp_ecdh, SSL_set_tmp_ecdh, SSL_CTX_set_ecdh_auto, SSL_set_ecdh_auto
+- handle ECDH keys for ephemeral key exchange
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ long SSL_CTX_set_tmp_ecdh(SSL_CTX *ctx, const EC_KEY *ecdh);
+ long SSL_set_tmp_ecdh(SSL *ssl, const EC_KEY *ecdh);
+
+ long SSL_CTX_set_ecdh_auto(SSL_CTX *ctx, int state);
+ long SSL_set_ecdh_auto(SSL *ssl, int state);
+
+=head1 DESCRIPTION
+
+SSL_CTX_set_tmp_ecdh() sets ECDH parameters to be used to be B<ecdh>.
+The key is inherited by all B<ssl> objects created from B<ctx>.
+This macro is deprecated in favor of L<SSL_CTX_set1_groups(3)>.
+
+SSL_set_tmp_ecdh() sets the parameters only for B<ssl>.
+This macro is deprecated in favor of L<SSL_set1_groups(3)>.
+
+SSL_CTX_set_ecdh_auto() and SSL_set_ecdh_auto() are deprecated and
+have no effect.
+
+=head1 RETURN VALUES
+
+SSL_CTX_set_tmp_ecdh() and SSL_set_tmp_ecdh() return 1 on success and 0
+on failure.
+
+=head1 SEE ALSO
+
+L<ssl(7)>, L<SSL_CTX_set1_curves(3)>, L<SSL_CTX_set_cipher_list(3)>,
+L<SSL_CTX_set_options(3)>, L<SSL_CTX_set_tmp_dh_callback(3)>,
+L<openssl-ciphers(1)>, L<openssl-ecparam(1)>
+
+=head1 COPYRIGHT
+
+Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/SSL_CTX_set_verify.pod b/doc/man3/SSL_CTX_set_verify.pod
index 1e759c3de0df..9d4abac30eba 100644
--- a/doc/man3/SSL_CTX_set_verify.pod
+++ b/doc/man3/SSL_CTX_set_verify.pod
@@ -9,7 +9,7 @@ SSL_verify_cb,
SSL_verify_client_post_handshake,
SSL_set_post_handshake_auth,
SSL_CTX_set_post_handshake_auth
-- set peer certificate verification parameters
+- set various SSL/TLS parameters for peer certificate verification
=head1 SYNOPSIS
@@ -44,6 +44,21 @@ L<SSL_new(3)>. Within the callback function,
B<SSL_get_ex_data_X509_STORE_CTX_idx> can be called to get the data index
of the current SSL object that is doing the verification.
+In client mode B<verify_callback> may also call the L<SSL_set_retry_verify(3)>
+function on the B<SSL> object set in the I<x509_store_ctx> ex data (see
+L<SSL_get_ex_data_X509_STORE_CTX_idx(3)>) and return 1.
+This would be typically done in case the certificate verification was not yet
+able to succeed.
+This makes the handshake suspend and return control to the calling application
+with B<SSL_ERROR_WANT_RETRY_VERIFY>.
+The application can for instance fetch further certificates or cert status
+information needed for the verification.
+Calling L<SSL_connect(3)> again resumes the connection attempt by retrying the
+server certificate verification step.
+This process may even be repeated if need be.
+Note that the handshake may still be aborted if a subsequent invocation of the
+callback (e.g., at a lower depth, or for a separate error condition) returns 0.
+
SSL_CTX_set_verify_depth() sets the maximum B<depth> for the certificate chain
verification that shall be allowed for B<ctx>.
@@ -348,9 +363,9 @@ and SSL_set_post_handshake_auth() functions were added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_use_certificate.pod b/doc/man3/SSL_CTX_use_certificate.pod
index b065d8f9e5cb..ca1827dada8a 100644
--- a/doc/man3/SSL_CTX_use_certificate.pod
+++ b/doc/man3/SSL_CTX_use_certificate.pod
@@ -20,27 +20,27 @@ SSL_CTX_use_cert_and_key, SSL_use_cert_and_key
#include <openssl/ssl.h>
int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
- int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, unsigned char *d);
+ int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d);
int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type);
int SSL_use_certificate(SSL *ssl, X509 *x);
- int SSL_use_certificate_ASN1(SSL *ssl, unsigned char *d, int len);
+ int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
int SSL_use_certificate_file(SSL *ssl, const char *file, int type);
int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file);
int SSL_use_certificate_chain_file(SSL *ssl, const char *file);
int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
- int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx, unsigned char *d,
+ int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx, const unsigned char *d,
long len);
int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);
int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
- int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, unsigned char *d, long len);
+ int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len);
int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type);
int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
- int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, unsigned char *d, long len);
+ int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, const unsigned char *d, long len);
int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type);
int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
- int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len);
+ int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d, long len);
int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
int SSL_CTX_check_private_key(const SSL_CTX *ctx);
@@ -92,10 +92,10 @@ SSL_CTX_use_PrivateKey() adds B<pkey> as private key to B<ctx>.
SSL_CTX_use_RSAPrivateKey() adds the private key B<rsa> of type RSA
to B<ctx>. SSL_use_PrivateKey() adds B<pkey> as private key to B<ssl>;
SSL_use_RSAPrivateKey() adds B<rsa> as private key of type RSA to B<ssl>.
-If a certificate has already been set and the private does not belong
-to the certificate an error is returned. To change a certificate, private
-key pair the new certificate needs to be set with SSL_use_certificate()
-or SSL_CTX_use_certificate() before setting the private key with
+If a certificate has already been set and the private key does not belong
+to the certificate an error is returned. To change a [certificate/private-key]
+pair, the new certificate needs to be set first with SSL_use_certificate() or
+SSL_CTX_use_certificate() before setting the private key with
SSL_CTX_use_PrivateKey() or SSL_use_PrivateKey().
SSL_CTX_use_cert_and_key() and SSL_use_cert_and_key() assign the X.509
@@ -130,7 +130,7 @@ RSA key found to B<ssl>.
SSL_CTX_check_private_key() checks the consistency of a private key with
the corresponding certificate loaded into B<ctx>. If more than one
key/certificate pair (RSA/DSA) is installed, the last item installed will
-be checked. If e.g. the last item was a RSA certificate or key, the RSA
+be checked. If e.g. the last item was an RSA certificate or key, the RSA
key/certificate pair will be checked. SSL_check_private_key() performs
the same check for B<ssl>. If no key/certificate was explicitly added for
this B<ssl>, the last item added into B<ctx> will be checked.
@@ -149,7 +149,8 @@ Files of type SSL_FILETYPE_PEM can contain more than one item.
SSL_CTX_use_certificate_chain_file() adds the first certificate found
in the file to the certificate store. The other certificates are added
-to the store of chain certificates using L<SSL_CTX_add1_chain_cert(3)>. Note: versions of OpenSSL before 1.0.2 only had a single
+to the store of chain certificates using L<SSL_CTX_add1_chain_cert(3)>.
+Note: versions of OpenSSL before 1.0.2 only had a single
certificate chain store for all certificate types, OpenSSL 1.0.2 and later
have a separate chain store for each type. SSL_CTX_use_certificate_chain_file()
should be used instead of the SSL_CTX_use_certificate_file() function in order
@@ -194,9 +195,9 @@ L<SSL_CTX_add_extra_chain_cert(3)>
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_use_psk_identity_hint.pod b/doc/man3/SSL_CTX_use_psk_identity_hint.pod
index b39fc09169ac..e3802b74f0e7 100644
--- a/doc/man3/SSL_CTX_use_psk_identity_hint.pod
+++ b/doc/man3/SSL_CTX_use_psk_identity_hint.pod
@@ -87,8 +87,6 @@ will default to SHA-256 for any returned PSK. TLSv1.3 early data exchanges are
possible in PSK connections only with the B<SSL_psk_find_session_cb_func>
callback, and are not possible with the B<SSL_psk_server_cb_func> callback.
-=head1 NOTES
-
A connection established via a TLSv1.3 PSK will appear as if session resumption
has occurred so that L<SSL_session_reused(3)> will return true.
@@ -137,6 +135,7 @@ TLS 1.3 and TLS 1.2."
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_CTX_set_psk_use_session_callback(3)>,
L<SSL_set_psk_use_session_callback(3)>
@@ -149,7 +148,7 @@ were added in OpenSSL 1.1.1.
Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_CTX_use_serverinfo.pod b/doc/man3/SSL_CTX_use_serverinfo.pod
index d35a196ffea3..ebdb5c6f7ca1 100644
--- a/doc/man3/SSL_CTX_use_serverinfo.pod
+++ b/doc/man3/SSL_CTX_use_serverinfo.pod
@@ -59,7 +59,7 @@ SSL_SERVERINFOV2 data or "BEGIN SERVERINFO FOR " for SSL_SERVERINFOV1 data.
If more than one certificate (RSA/DSA) is installed using
SSL_CTX_use_certificate(), the serverinfo extension will be loaded into the
-last certificate installed. If e.g. the last item was a RSA certificate, the
+last certificate installed. If e.g. the last item was an RSA certificate, the
loaded serverinfo extension data will be loaded for that certificate. To
use the serverinfo extension for multiple certificates,
SSL_CTX_use_serverinfo() needs to be called multiple times, once B<after>
@@ -71,11 +71,15 @@ On success, the functions return 1.
On failure, the functions return 0. Check out the error stack to find out
the reason.
+=head1 SEE ALSO
+
+L<ssl(7)>
+
=head1 COPYRIGHT
Copyright 2013-2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_SESSION_free.pod b/doc/man3/SSL_SESSION_free.pod
index 9a3bf3ec988e..74c6ec2a29cb 100644
--- a/doc/man3/SSL_SESSION_free.pod
+++ b/doc/man3/SSL_SESSION_free.pod
@@ -12,7 +12,7 @@ SSL_SESSION_free - create, free and manage SSL_SESSION structures
#include <openssl/ssl.h>
SSL_SESSION *SSL_SESSION_new(void);
- SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *src);
+ SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src);
int SSL_SESSION_up_ref(SSL_SESSION *ses);
void SSL_SESSION_free(SSL_SESSION *session);
@@ -79,7 +79,7 @@ The SSL_SESSION_dup() function was added in OpenSSL 1.1.1.
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_SESSION_get0_cipher.pod b/doc/man3/SSL_SESSION_get0_cipher.pod
index 5ef754c4a841..3883a6fa05d5 100644
--- a/doc/man3/SSL_SESSION_get0_cipher.pod
+++ b/doc/man3/SSL_SESSION_get0_cipher.pod
@@ -50,7 +50,7 @@ The SSL_SESSION_set_cipher() function was added in OpenSSL 1.1.1.
Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_SESSION_get0_hostname.pod b/doc/man3/SSL_SESSION_get0_hostname.pod
index 6e39cbc656dd..f560e7751d84 100644
--- a/doc/man3/SSL_SESSION_get0_hostname.pod
+++ b/doc/man3/SSL_SESSION_get0_hostname.pod
@@ -69,7 +69,7 @@ SSL_SESSION_set1_alpn_selected() functions were added in OpenSSL 1.1.1.
Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_SESSION_get0_id_context.pod b/doc/man3/SSL_SESSION_get0_id_context.pod
index 99b21bd126e9..c210eb0cf7d8 100644
--- a/doc/man3/SSL_SESSION_get0_id_context.pod
+++ b/doc/man3/SSL_SESSION_get0_id_context.pod
@@ -11,7 +11,7 @@ SSL_SESSION_set1_id_context
#include <openssl/ssl.h>
const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *s,
- unsigned int *len)
+ unsigned int *len);
int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx,
unsigned int sid_ctx_len);
@@ -46,9 +46,9 @@ The SSL_SESSION_get0_id_context() function was added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_SESSION_get0_peer.pod b/doc/man3/SSL_SESSION_get0_peer.pod
index f6f2a1cd25b7..3771041b538c 100644
--- a/doc/man3/SSL_SESSION_get0_peer.pod
+++ b/doc/man3/SSL_SESSION_get0_peer.pod
@@ -30,7 +30,7 @@ L<ssl(7)>
Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_SESSION_get_compress_id.pod b/doc/man3/SSL_SESSION_get_compress_id.pod
index 0bdccb4b7695..a0686efb972c 100644
--- a/doc/man3/SSL_SESSION_get_compress_id.pod
+++ b/doc/man3/SSL_SESSION_get_compress_id.pod
@@ -31,7 +31,7 @@ L<ssl(7)>
Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_SESSION_get_ex_data.pod b/doc/man3/SSL_SESSION_get_ex_data.pod
deleted file mode 100644
index f44c4e8e1fb5..000000000000
--- a/doc/man3/SSL_SESSION_get_ex_data.pod
+++ /dev/null
@@ -1,47 +0,0 @@
-=pod
-
-=head1 NAME
-
-SSL_SESSION_set_ex_data,
-SSL_SESSION_get_ex_data
-- get and set application specific data on a session
-
-=head1 SYNOPSIS
-
- #include <openssl/ssl.h>
-
- int SSL_SESSION_set_ex_data(SSL_SESSION *ss, int idx, void *data);
- void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx);
-
-=head1 DESCRIPTION
-
-SSL_SESSION_set_ex_data() enables an application to store arbitrary application
-specific data B<data> in an SSL_SESSION structure B<ss>. The index B<idx> should
-be a value previously returned from a call to L<CRYPTO_get_ex_new_index(3)>.
-
-SSL_SESSION_get_ex_data() retrieves application specific data previously stored
-in an SSL_SESSION structure B<s>. The B<idx> value should be the same as that
-used when originally storing the data.
-
-=head1 RETURN VALUES
-
-SSL_SESSION_set_ex_data() returns 1 for success or 0 for failure.
-
-SSL_SESSION_get_ex_data() returns the previously stored value or NULL on
-failure. NULL may also be a valid value.
-
-=head1 SEE ALSO
-
-L<ssl(7)>,
-L<CRYPTO_get_ex_new_index(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man3/SSL_SESSION_get_protocol_version.pod b/doc/man3/SSL_SESSION_get_protocol_version.pod
index 961ed3e923c7..b8b9b5aa10f1 100644
--- a/doc/man3/SSL_SESSION_get_protocol_version.pod
+++ b/doc/man3/SSL_SESSION_get_protocol_version.pod
@@ -48,7 +48,7 @@ The SSL_SESSION_set_protocol_version() function was added in OpenSSL 1.1.1.
Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_SESSION_get_time.pod b/doc/man3/SSL_SESSION_get_time.pod
index e98d128b02bc..00b693bae6f8 100644
--- a/doc/man3/SSL_SESSION_get_time.pod
+++ b/doc/man3/SSL_SESSION_get_time.pod
@@ -68,7 +68,7 @@ L<SSL_get_default_timeout(3)>
Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_SESSION_has_ticket.pod b/doc/man3/SSL_SESSION_has_ticket.pod
index 6fb41b75cb60..b4849d3a6bf7 100644
--- a/doc/man3/SSL_SESSION_has_ticket.pod
+++ b/doc/man3/SSL_SESSION_has_ticket.pod
@@ -51,7 +51,7 @@ and SSL_SESSION_get0_ticket() functions were added in OpenSSL 1.1.0.
Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_SESSION_is_resumable.pod b/doc/man3/SSL_SESSION_is_resumable.pod
index 8e47eee09ac7..6df7ed75b745 100644
--- a/doc/man3/SSL_SESSION_is_resumable.pod
+++ b/doc/man3/SSL_SESSION_is_resumable.pod
@@ -36,7 +36,7 @@ The SSL_SESSION_is_resumable() function was added in OpenSSL 1.1.1.
Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_SESSION_print.pod b/doc/man3/SSL_SESSION_print.pod
index 957411a771a7..7af730447a19 100644
--- a/doc/man3/SSL_SESSION_print.pod
+++ b/doc/man3/SSL_SESSION_print.pod
@@ -39,7 +39,7 @@ L<ssl(7)>
Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_SESSION_set1_id.pod b/doc/man3/SSL_SESSION_set1_id.pod
index deafdf1ea579..f4cdcde50900 100644
--- a/doc/man3/SSL_SESSION_set1_id.pod
+++ b/doc/man3/SSL_SESSION_set1_id.pod
@@ -11,7 +11,7 @@ SSL_SESSION_set1_id
#include <openssl/ssl.h>
const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s,
- unsigned int *len)
+ unsigned int *len);
int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid,
unsigned int sid_len);
@@ -40,9 +40,9 @@ The SSL_SESSION_set1_id() function was added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_accept.pod b/doc/man3/SSL_accept.pod
index 81c9dbea5748..8577cc8e0e0b 100644
--- a/doc/man3/SSL_accept.pod
+++ b/doc/man3/SSL_accept.pod
@@ -74,7 +74,7 @@ L<SSL_CTX_new(3)>
Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_alert_type_string.pod b/doc/man3/SSL_alert_type_string.pod
index b88465b1bfb5..120527479eee 100644
--- a/doc/man3/SSL_alert_type_string.pod
+++ b/doc/man3/SSL_alert_type_string.pod
@@ -234,7 +234,7 @@ L<ssl(7)>, L<SSL_CTX_set_info_callback(3)>
Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_alloc_buffers.pod b/doc/man3/SSL_alloc_buffers.pod
index ac3bd814c67c..678640a56933 100644
--- a/doc/man3/SSL_alloc_buffers.pod
+++ b/doc/man3/SSL_alloc_buffers.pod
@@ -51,15 +51,16 @@ SSL_alloc_buffers().
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_free(3)>, L<SSL_clear(3)>,
L<SSL_new(3)>, L<SSL_CTX_set_mode(3)>,
-L<CRYPTO_set_mem_functions>
+L<CRYPTO_set_mem_functions(3)>
=head1 COPYRIGHT
Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_check_chain.pod b/doc/man3/SSL_check_chain.pod
index 4de36cc78784..d00badbd753f 100644
--- a/doc/man3/SSL_check_chain.pod
+++ b/doc/man3/SSL_check_chain.pod
@@ -86,7 +86,7 @@ L<ssl(7)>
Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_clear.pod b/doc/man3/SSL_clear.pod
index 385e4f6e28d9..f5fc6e68ed2b 100644
--- a/doc/man3/SSL_clear.pod
+++ b/doc/man3/SSL_clear.pod
@@ -76,7 +76,7 @@ L<SSL_CTX_set_client_cert_cb(3)>
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_connect.pod b/doc/man3/SSL_connect.pod
index 0e6b6253586c..4e9bd9ca079b 100644
--- a/doc/man3/SSL_connect.pod
+++ b/doc/man3/SSL_connect.pod
@@ -89,7 +89,7 @@ L<SSL_CTX_new(3)>
Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_do_handshake.pod b/doc/man3/SSL_do_handshake.pod
index fa133d76a8ed..819576b09ffd 100644
--- a/doc/man3/SSL_do_handshake.pod
+++ b/doc/man3/SSL_do_handshake.pod
@@ -73,7 +73,7 @@ L<SSL_set_connect_state(3)>
Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_export_keying_material.pod b/doc/man3/SSL_export_keying_material.pod
index c6b9229cbf16..c7c5320295e6 100644
--- a/doc/man3/SSL_export_keying_material.pod
+++ b/doc/man3/SSL_export_keying_material.pod
@@ -71,6 +71,10 @@ SSL_export_keying_material() returns 0 or -1 on failure or 1 on success.
SSL_export_keying_material_early() returns 0 on failure or 1 on success.
+=head1 SEE ALSO
+
+L<ssl(7)>
+
=head1 HISTORY
The SSL_export_keying_material_early() function was added in OpenSSL 1.1.1.
@@ -79,7 +83,7 @@ The SSL_export_keying_material_early() function was added in OpenSSL 1.1.1.
Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_extension_supported.pod b/doc/man3/SSL_extension_supported.pod
index df23ac6551ba..fa7a1f692db7 100644
--- a/doc/man3/SSL_extension_supported.pod
+++ b/doc/man3/SSL_extension_supported.pod
@@ -3,6 +3,9 @@
=head1 NAME
SSL_extension_supported,
+SSL_custom_ext_add_cb_ex,
+SSL_custom_ext_free_cb_ex,
+SSL_custom_ext_parse_cb_ex,
SSL_CTX_add_custom_ext,
SSL_CTX_add_client_custom_ext, SSL_CTX_add_server_custom_ext,
custom_ext_add_cb, custom_ext_free_cb, custom_ext_parse_cb
@@ -12,24 +15,24 @@ custom_ext_add_cb, custom_ext_free_cb, custom_ext_parse_cb
#include <openssl/ssl.h>
- typedef int (*SSL_custom_ext_add_cb_ex) (SSL *s, unsigned int ext_type,
- unsigned int context,
- const unsigned char **out,
- size_t *outlen, X509 *x,
- size_t chainidx, int *al,
- void *add_arg);
-
- typedef void (*SSL_custom_ext_free_cb_ex) (SSL *s, unsigned int ext_type,
- unsigned int context,
- const unsigned char *out,
- void *add_arg);
-
- typedef int (*SSL_custom_ext_parse_cb_ex) (SSL *s, unsigned int ext_type,
- unsigned int context,
- const unsigned char *in,
- size_t inlen, X509 *x,
- size_t chainidx, int *al,
- void *parse_arg);
+ typedef int (*SSL_custom_ext_add_cb_ex)(SSL *s, unsigned int ext_type,
+ unsigned int context,
+ const unsigned char **out,
+ size_t *outlen, X509 *x,
+ size_t chainidx, int *al,
+ void *add_arg);
+
+ typedef void (*SSL_custom_ext_free_cb_ex)(SSL *s, unsigned int ext_type,
+ unsigned int context,
+ const unsigned char *out,
+ void *add_arg);
+
+ typedef int (*SSL_custom_ext_parse_cb_ex)(SSL *s, unsigned int ext_type,
+ unsigned int context,
+ const unsigned char *in,
+ size_t inlen, X509 *x,
+ size_t chainidx, int *al,
+ void *parse_arg);
int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
unsigned int context,
@@ -275,15 +278,19 @@ failure).
SSL_extension_supported() returns 1 if the extension B<ext_type> is handled
internally by OpenSSL and 0 otherwise.
+=head1 SEE ALSO
+
+L<ssl(7)>
+
=head1 HISTORY
The SSL_CTX_add_custom_ext() function was added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_free.pod b/doc/man3/SSL_free.pod
index 205ea7a88d2c..d262f55d151e 100644
--- a/doc/man3/SSL_free.pod
+++ b/doc/man3/SSL_free.pod
@@ -46,7 +46,7 @@ L<ssl(7)>
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get0_peer_scts.pod b/doc/man3/SSL_get0_peer_scts.pod
index 59120a36d932..d77b6268a572 100644
--- a/doc/man3/SSL_get0_peer_scts.pod
+++ b/doc/man3/SSL_get0_peer_scts.pod
@@ -37,7 +37,7 @@ L<SSL_CTX_set_ct_validation_callback(3)>
Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_SSL_CTX.pod b/doc/man3/SSL_get_SSL_CTX.pod
index efcd1456b40f..02443c104e86 100644
--- a/doc/man3/SSL_get_SSL_CTX.pod
+++ b/doc/man3/SSL_get_SSL_CTX.pod
@@ -27,7 +27,7 @@ L<ssl(7)>, L<SSL_new(3)>
Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_all_async_fds.pod b/doc/man3/SSL_get_all_async_fds.pod
index 6fa6ed4a62ef..82749249ea68 100644
--- a/doc/man3/SSL_get_all_async_fds.pod
+++ b/doc/man3/SSL_get_all_async_fds.pod
@@ -9,7 +9,7 @@ SSL_get_changed_async_fds
=head1 SYNOPSIS
-=for comment multiple includes
+=for openssl multiple includes
#include <openssl/async.h>
#include <openssl/ssl.h>
@@ -22,32 +22,32 @@ SSL_get_changed_async_fds
=head1 DESCRIPTION
SSL_waiting_for_async() determines whether an SSL connection is currently
-waiting for asynchronous operations to complete (see the SSL_MODE_ASYNC mode in
-L<SSL_CTX_set_mode(3)>).
+waiting for asynchronous operations to complete (see the B<SSL_MODE_ASYNC> mode
+in L<SSL_CTX_set_mode(3)>).
SSL_get_all_async_fds() returns a list of file descriptor which can be used in a
call to select() or poll() to determine whether the current asynchronous
operation has completed or not. A completed operation will result in data
appearing as "read ready" on the file descriptor (no actual data should be read
-from the file descriptor). This function should only be called if the SSL object
-is currently waiting for asynchronous work to complete (i.e.
-SSL_ERROR_WANT_ASYNC has been received - see L<SSL_get_error(3)>). Typically the
-list will only contain one file descriptor. However, if multiple asynchronous
+from the file descriptor). This function should only be called if the B<SSL>
+object is currently waiting for asynchronous work to complete (i.e.
+B<SSL_ERROR_WANT_ASYNC> has been received - see L<SSL_get_error(3)>). Typically
+the list will only contain one file descriptor. However, if multiple asynchronous
capable engines are in use then more than one is possible. The number of file
-descriptors returned is stored in B<*numfds> and the file descriptors themselves
-are in B<*fds>. The B<fds> parameter may be NULL in which case no file
-descriptors are returned but B<*numfds> is still populated. It is the callers
-responsibility to ensure sufficient memory is allocated at B<*fds> so typically
-this function is called twice (once with a NULL B<fds> parameter and once
+descriptors returned is stored in I<*numfds> and the file descriptors themselves
+are in I<*fds>. The I<fds> parameter may be NULL in which case no file
+descriptors are returned but I<*numfds> is still populated. It is the callers
+responsibility to ensure sufficient memory is allocated at I<*fds> so typically
+this function is called twice (once with a NULL I<fds> parameter and once
without).
SSL_get_changed_async_fds() returns a list of the asynchronous file descriptors
that have been added and a list that have been deleted since the last
-SSL_ERROR_WANT_ASYNC was received (or since the SSL object was created if no
-SSL_ERROR_WANT_ASYNC has been received). Similar to SSL_get_all_async_fds() it
-is the callers responsibility to ensure that B<*addfd> and B<*delfd> have
+B<SSL_ERROR_WANT_ASYNC> was received (or since the B<SSL> object was created if
+no B<SSL_ERROR_WANT_ASYNC> has been received). Similar to SSL_get_all_async_fds()
+it is the callers responsibility to ensure that I<*addfd> and I<*delfd> have
sufficient memory allocated, although they may be NULL. The number of added fds
-and the number of deleted fds are stored in B<*numaddfds> and B<*numdelfds>
+and the number of deleted fds are stored in I<*numaddfds> and I<*numdelfds>
respectively.
=head1 RETURN VALUES
@@ -60,15 +60,16 @@ SSL_get_all_async_fds() and SSL_get_changed_async_fds() return 1 on success or
=head1 NOTES
-On Windows platforms the openssl/async.h header is dependent on some
-of the types customarily made available by including windows.h. The
+On Windows platforms the F<< <openssl/async.h> >> header is dependent on some
+of the types customarily made available by including F<< <windows.h> >>. The
application developer is likely to require control over when the latter
is included, commonly as one of the first included headers. Therefore,
it is defined as an application developer's responsibility to include
-windows.h prior to async.h.
+F<< <windows.h> >> prior to F<< <openssl/async.h> >>.
=head1 SEE ALSO
+L<ssl(7)>,
L<SSL_get_error(3)>, L<SSL_CTX_set_mode(3)>
=head1 HISTORY
@@ -78,9 +79,9 @@ and SSL_get_changed_async_fds() functions were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_certificate.pod b/doc/man3/SSL_get_certificate.pod
new file mode 100644
index 000000000000..a57917c81339
--- /dev/null
+++ b/doc/man3/SSL_get_certificate.pod
@@ -0,0 +1,73 @@
+=pod
+
+=head1 NAME
+
+SSL_get_certificate, SSL_get_privatekey - retrieve TLS/SSL certificate and
+private key
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ X509 *SSL_get_certificate(const SSL *s);
+ EVP_PKEY *SSL_get_privatekey(const SSL *s);
+
+=head1 DESCRIPTION
+
+SSL_get_certificate() returns a pointer to an B<X509> object representing a
+certificate used as the local peer's identity.
+
+Multiple certificates can be configured; for example, a server might have both
+RSA and ECDSA certificates. The certificate which is returned by
+SSL_get_certificate() is determined as follows:
+
+=over 4
+
+=item
+
+If it is called before certificate selection has occurred, it returns the most
+recently added certificate, or NULL if no certificate has been added.
+
+=item
+
+After certificate selection has occurred, it returns the certificate which was
+selected during the handshake, or NULL if no certificate was selected (for
+example, on a client where no client certificate is in use).
+
+=back
+
+Certificate selection occurs during the handshake; therefore, the value returned
+by SSL_get_certificate() during any callback made during the handshake process
+will depend on whether that callback is made before or after certificate
+selection occurs.
+
+A specific use for SSL_get_certificate() is inside a callback set via a call to
+L<SSL_CTX_set_tlsext_status_cb(3)>. This callback occurs after certificate
+selection, where it can be used to examine a server's chosen certificate, for
+example for the purpose of identifying a certificate's OCSP responder URL so
+that an OCSP response can be obtained.
+
+SSL_get_privatekey() returns a pointer to the B<EVP_PKEY> object corresponding
+to the certificate returned by SSL_get_certificate(), if any.
+
+=head1 RETURN VALUES
+
+These functions return pointers to their respective objects, or NULL if no such
+object is available. Returned objects are owned by the SSL object and should not
+be freed by users of these functions.
+
+=head1 SEE ALSO
+
+L<ssl(7)>, L<SSL_CTX_set_tlsext_status_cb(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
+
diff --git a/doc/man3/SSL_get_ciphers.pod b/doc/man3/SSL_get_ciphers.pod
index 6c0891e48404..add0fc4cd045 100644
--- a/doc/man3/SSL_get_ciphers.pod
+++ b/doc/man3/SSL_get_ciphers.pod
@@ -109,7 +109,7 @@ L<SSL_CIPHER_get_name(3)>
Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_client_random.pod b/doc/man3/SSL_get_client_random.pod
index 1e4c66672ddd..6e92a518248a 100644
--- a/doc/man3/SSL_get_client_random.pod
+++ b/doc/man3/SSL_get_client_random.pod
@@ -96,7 +96,7 @@ L<SSL_CTX_set_psk_use_session_callback(3)>
Copyright 2015-2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_current_cipher.pod b/doc/man3/SSL_get_current_cipher.pod
index 4ed555aa4972..b41d9daf2f1c 100644
--- a/doc/man3/SSL_get_current_cipher.pod
+++ b/doc/man3/SSL_get_current_cipher.pod
@@ -63,7 +63,7 @@ L<ssl(7)>, L<SSL_CIPHER_get_name(3)>
Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_default_timeout.pod b/doc/man3/SSL_get_default_timeout.pod
index 4bbaba0123ac..fbe44c9d180e 100644
--- a/doc/man3/SSL_get_default_timeout.pod
+++ b/doc/man3/SSL_get_default_timeout.pod
@@ -42,7 +42,7 @@ L<SSL_get_default_timeout(3)>
Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_error.pod b/doc/man3/SSL_get_error.pod
index e6a1e8b63def..a90b22d98474 100644
--- a/doc/man3/SSL_get_error.pod
+++ b/doc/man3/SSL_get_error.pod
@@ -25,6 +25,15 @@ other OpenSSL function calls should appear in between. The current
thread's error queue must be empty before the TLS/SSL I/O operation is
attempted, or SSL_get_error() will not work reliably.
+=head1 NOTES
+
+Some TLS implementations do not send a close_notify alert on shutdown.
+
+On an unexpected EOF, versions before OpenSSL 3.0 returned
+B<SSL_ERROR_SYSCALL>, nothing was added to the error stack, and errno was 0.
+Since OpenSSL 3.0 the returned error is B<SSL_ERROR_SSL> with a meaningful
+error on the error stack.
+
=head1 RETURN VALUES
The following return values can currently occur:
@@ -44,6 +53,9 @@ No more data can be read.
Note that B<SSL_ERROR_ZERO_RETURN> does not necessarily
indicate that the underlying transport has been closed.
+This error can also appear when the option B<SSL_OP_IGNORE_UNEXPECTED_EOF>
+is set. See L<SSL_CTX_set_options(3)> for more details.
+
=item SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE
The operation did not complete and can be retried later.
@@ -73,7 +85,9 @@ protocol level.
It is safe to call SSL_read() or SSL_read_ex() when more data is available
even when the call that set this error was an SSL_write() or SSL_write_ex().
However, if the call was an SSL_write() or SSL_write_ex(), it should be called
-again to continue sending the application data.
+again to continue sending the application data. If you get B<SSL_ERROR_WANT_WRITE>
+from SSL_write() or SSL_write_ex() then you should not do any other operation
+that could trigger B<IO> other than to repeat the previous SSL_write() call.
For socket B<BIO>s (e.g. when SSL_set_fd() was used), select() or
poll() on the underlying socket can be used to find out when the
@@ -155,18 +169,6 @@ connection and SSL_shutdown() must not be called.
=back
-=head1 BUGS
-
-The B<SSL_ERROR_SYSCALL> with B<errno> value of 0 indicates unexpected EOF from
-the peer. This will be properly reported as B<SSL_ERROR_SSL> with reason
-code B<SSL_R_UNEXPECTED_EOF_WHILE_READING> in the OpenSSL 3.0 release because
-it is truly a TLS protocol error to terminate the connection without
-a SSL_shutdown().
-
-The issue is kept unfixed in OpenSSL 1.1.1 releases because many applications
-which choose to ignore this protocol error depend on the existing way of
-reporting the error.
-
=head1 SEE ALSO
L<ssl(7)>
@@ -178,9 +180,9 @@ The SSL_ERROR_WANT_CLIENT_HELLO_CB error code was added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_extms_support.pod b/doc/man3/SSL_get_extms_support.pod
index 9719c0a3aedc..60ea8e16d851 100644
--- a/doc/man3/SSL_get_extms_support.pod
+++ b/doc/man3/SSL_get_extms_support.pod
@@ -32,7 +32,7 @@ L<ssl(7)>
Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_fd.pod b/doc/man3/SSL_get_fd.pod
index ca260180fa14..18d54a6706b4 100644
--- a/doc/man3/SSL_get_fd.pod
+++ b/doc/man3/SSL_get_fd.pod
@@ -45,7 +45,7 @@ L<SSL_set_fd(3)>, L<ssl(7)> , L<bio(7)>
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_peer_cert_chain.pod b/doc/man3/SSL_get_peer_cert_chain.pod
index 1ead4f987c4c..f36329dca9f2 100644
--- a/doc/man3/SSL_get_peer_cert_chain.pod
+++ b/doc/man3/SSL_get_peer_cert_chain.pod
@@ -69,7 +69,7 @@ L<X509_chain_up_ref(3)>
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_peer_certificate.pod b/doc/man3/SSL_get_peer_certificate.pod
index fd2ce087665d..b695edc689fa 100644
--- a/doc/man3/SSL_get_peer_certificate.pod
+++ b/doc/man3/SSL_get_peer_certificate.pod
@@ -2,17 +2,21 @@
=head1 NAME
-SSL_get_peer_certificate - get the X509 certificate of the peer
+SSL_get_peer_certificate,
+SSL_get0_peer_certificate,
+SSL_get1_peer_certificate - get the X509 certificate of the peer
=head1 SYNOPSIS
#include <openssl/ssl.h>
X509 *SSL_get_peer_certificate(const SSL *ssl);
+ X509 *SSL_get0_peer_certificate(const SSL *ssl);
+ X509 *SSL_get1_peer_certificate(const SSL *ssl);
=head1 DESCRIPTION
-SSL_get_peer_certificate() returns a pointer to the X509 certificate the
+These functions return a pointer to the X509 certificate the
peer presented. If the peer did not present a certificate, NULL is returned.
=head1 NOTES
@@ -27,9 +31,15 @@ That a certificate is returned does not indicate information about the
verification state, use L<SSL_get_verify_result(3)>
to check the verification state.
-The reference count of the X509 object is incremented by one, so that it
-will not be destroyed when the session containing the peer certificate is
-freed. The X509 object must be explicitly freed using X509_free().
+The reference count of the X509 object returned by SSL_get1_peer_certificate()
+is incremented by one, so that it will not be destroyed when the session
+containing the peer certificate is freed. The X509 object must be explicitly
+freed using X509_free().
+
+The reference count of the X509 object returned by SSL_get0_peer_certificate()
+is not incremented, and must not be freed.
+
+SSL_get_peer_certificate() is an alias of SSL_get1_peer_certificate().
=head1 RETURN VALUES
@@ -52,11 +62,16 @@ The return value points to the certificate presented by the peer.
L<ssl(7)>, L<SSL_get_verify_result(3)>,
L<SSL_CTX_set_verify(3)>
+=head1 HISTORY
+
+SSL_get0_peer_certificate() and SSL_get1_peer_certificate() were added in 3.0.0.
+SSL_get_peer_certificate() was deprecated in 3.0.0.
+
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_peer_signature_nid.pod b/doc/man3/SSL_get_peer_signature_nid.pod
index dbca8cffb920..7776f3e25738 100644
--- a/doc/man3/SSL_get_peer_signature_nid.pod
+++ b/doc/man3/SSL_get_peer_signature_nid.pod
@@ -45,7 +45,7 @@ L<ssl(7)>, L<SSL_get_peer_certificate(3)>,
Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_peer_tmp_key.pod b/doc/man3/SSL_get_peer_tmp_key.pod
index a722a813bff8..fdbc05de5498 100644
--- a/doc/man3/SSL_get_peer_tmp_key.pod
+++ b/doc/man3/SSL_get_peer_tmp_key.pod
@@ -45,7 +45,7 @@ L<ssl(7)>, L<EVP_PKEY_free(3)>
Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_psk_identity.pod b/doc/man3/SSL_get_psk_identity.pod
index 2930a3b6dfaf..c7d6cca29162 100644
--- a/doc/man3/SSL_get_psk_identity.pod
+++ b/doc/man3/SSL_get_psk_identity.pod
@@ -29,11 +29,15 @@ no PSK identity hint was used during the connection setup.
Note that the return value is valid only during the lifetime of the
SSL object B<ssl>.
+=head1 SEE ALSO
+
+L<ssl(7)>
+
=head1 COPYRIGHT
Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_rbio.pod b/doc/man3/SSL_get_rbio.pod
index f6ae3e945951..9ea03a4c77cc 100644
--- a/doc/man3/SSL_get_rbio.pod
+++ b/doc/man3/SSL_get_rbio.pod
@@ -41,7 +41,7 @@ L<SSL_set_bio(3)>, L<ssl(7)> , L<bio(7)>
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_session.pod b/doc/man3/SSL_get_session.pod
index b7472bd6082a..8d5d1f6b4792 100644
--- a/doc/man3/SSL_get_session.pod
+++ b/doc/man3/SSL_get_session.pod
@@ -105,7 +105,7 @@ L<SSL_SESSION_free(3)>
Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_shared_sigalgs.pod b/doc/man3/SSL_get_shared_sigalgs.pod
index 668a2a58ecfb..c18114cdf472 100644
--- a/doc/man3/SSL_get_shared_sigalgs.pod
+++ b/doc/man3/SSL_get_shared_sigalgs.pod
@@ -80,7 +80,7 @@ L<ssl(7)>
Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_verify_result.pod b/doc/man3/SSL_get_verify_result.pod
index 5b9fc93d03d4..ac37408748b2 100644
--- a/doc/man3/SSL_get_verify_result.pod
+++ b/doc/man3/SSL_get_verify_result.pod
@@ -44,7 +44,7 @@ The verification succeeded or no peer certificate was presented.
=item Any other value
-Documented in L<verify(1)>.
+Documented in L<openssl-verify(1)>.
=back
@@ -52,13 +52,13 @@ Documented in L<verify(1)>.
L<ssl(7)>, L<SSL_set_verify_result(3)>,
L<SSL_get_peer_certificate(3)>,
-L<verify(1)>
+L<openssl-verify(1)>
=head1 COPYRIGHT
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_get_version.pod b/doc/man3/SSL_get_version.pod
index 5507ff3f3de9..d12927745a50 100644
--- a/doc/man3/SSL_get_version.pod
+++ b/doc/man3/SSL_get_version.pod
@@ -103,7 +103,7 @@ The SSL_is_dtls() function was added in OpenSSL 1.1.0.
Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_group_to_name.pod b/doc/man3/SSL_group_to_name.pod
new file mode 100644
index 000000000000..4551a1264c29
--- /dev/null
+++ b/doc/man3/SSL_group_to_name.pod
@@ -0,0 +1,43 @@
+=pod
+
+=head1 NAME
+
+SSL_group_to_name - get name of group
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ const char *SSL_group_to_name(const SSL *ssl, int id);
+
+=head1 DESCRIPTION
+
+SSL_group_to_name() is used to retrieve the TLS group name
+associated with a given TLS group ID, as registered via built-in
+or external providers and as returned by a call to SSL_get1_groups()
+or SSL_get_shared_group().
+
+=head1 RETURN VALUES
+
+If non-NULL, SSL_group_to_name() returns the TLS group name
+corresponding to the given I<id> as a NUL-terminated string.
+If SSL_group_to_name() returns NULL, an error occurred; possibly no
+corresponding tlsname was registered during provider initialisation.
+
+Note that the return value is valid only during the lifetime of the
+SSL object I<ssl>.
+
+=head1 SEE ALSO
+
+L<ssl(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/SSL_in_init.pod b/doc/man3/SSL_in_init.pod
index 0760f7ec4059..315d870284d8 100644
--- a/doc/man3/SSL_in_init.pod
+++ b/doc/man3/SSL_in_init.pod
@@ -102,7 +102,7 @@ L<SSL_read_early_data(3)>
Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_key_update.pod b/doc/man3/SSL_key_update.pod
index 068ace597836..6d5b42e0b166 100644
--- a/doc/man3/SSL_key_update.pod
+++ b/doc/man3/SSL_key_update.pod
@@ -32,10 +32,11 @@ peer to additionally update its sending keys. It is an error if B<updatetype> is
set to B<SSL_KEY_UPDATE_NONE>.
SSL_key_update() must only be called after the initial handshake has been
-completed and TLSv1.3 has been negotiated. The key update will not take place
-until the next time an IO operation such as SSL_read_ex() or SSL_write_ex()
-takes place on the connection. Alternatively SSL_do_handshake() can be called to
-force the update to take place immediately.
+completed and TLSv1.3 has been negotiated, at the same time, the application
+needs to ensure that the writing of data has been completed. The key update
+will not take place until the next time an IO operation such as SSL_read_ex()
+or SSL_write_ex() takes place on the connection. Alternatively SSL_do_handshake()
+can be called to force the update to take place immediately.
SSL_get_key_update_type() can be used to determine whether a key update
operation has been scheduled but not yet performed. The type of the pending key
@@ -100,9 +101,9 @@ OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_library_init.pod b/doc/man3/SSL_library_init.pod
index e486fae89d19..1b56c3b8aa29 100644
--- a/doc/man3/SSL_library_init.pod
+++ b/doc/man3/SSL_library_init.pod
@@ -47,9 +47,9 @@ deprecated in OpenSSL 1.1.0 by OPENSSL_init_ssl().
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_load_client_CA_file.pod b/doc/man3/SSL_load_client_CA_file.pod
index f354ef4177dc..988c7e893407 100644
--- a/doc/man3/SSL_load_client_CA_file.pod
+++ b/doc/man3/SSL_load_client_CA_file.pod
@@ -2,26 +2,36 @@
=head1 NAME
-SSL_load_client_CA_file,
+SSL_load_client_CA_file_ex, SSL_load_client_CA_file,
SSL_add_file_cert_subjects_to_stack,
-SSL_add_dir_cert_subjects_to_stack
+SSL_add_dir_cert_subjects_to_stack,
+SSL_add_store_cert_subjects_to_stack
- load certificate names
=head1 SYNOPSIS
#include <openssl/ssl.h>
+ STACK_OF(X509_NAME) *SSL_load_client_CA_file_ex(const char *file,
+ OSSL_LIB_CTX *libctx,
+ const char *propq);
STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
- const char *file)
+ const char *file);
int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
- const char *dir)
+ const char *dir);
+ int SSL_add_store_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
+ const char *store);
=head1 DESCRIPTION
-SSL_load_client_CA_file() reads certificates from I<file> and returns
-a STACK_OF(X509_NAME) with the subject names found.
+SSL_load_client_CA_file_ex() reads certificates from I<file> and returns
+a STACK_OF(X509_NAME) with the subject names found. The library context I<libctx>
+and property query I<propq> are used when fetching algorithms from providers.
+
+SSL_load_client_CA_file() is similar to SSL_load_client_CA_file_ex()
+but uses NULL for the library context I<libctx> and property query I<propq>.
SSL_add_file_cert_subjects_to_stack() reads certificates from I<file>,
and adds their subject name to the already existing I<stack>.
@@ -30,6 +40,10 @@ SSL_add_dir_cert_subjects_to_stack() reads certificates from every
file in the directory I<dir>, and adds their subject name to the
already existing I<stack>.
+SSL_add_store_cert_subjects_to_stack() loads certificates from the
+I<store> URI, and adds their subject name to the already existing
+I<stack>.
+
=head1 NOTES
SSL_load_client_CA_file() reads a file of PEM formatted certificates and
@@ -72,13 +86,19 @@ Load names of CAs from file and use it as a client CA list:
=head1 SEE ALSO
L<ssl(7)>,
+L<ossl_store(7)>,
L<SSL_CTX_set_client_CA_list(3)>
+=head1 HISTORY
+
+SSL_load_client_CA_file_ex() and SSL_add_store_cert_subjects_to_stack()
+were added in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_new.pod b/doc/man3/SSL_new.pod
index b8680526b8db..59d275523f98 100644
--- a/doc/man3/SSL_new.pod
+++ b/doc/man3/SSL_new.pod
@@ -61,7 +61,7 @@ L<SSL_set_tmp_dh_callback(3)>, or L<SSL_set_dh_auto(3)>
L<SSL_set_min_proto_version(3)> or L<SSL_set_max_proto_version(3)> (Note: Only
from OpenSSL 1.1.1h and above)
-=item any Verify mode, callback or depth set via L<SSL_set_verify(3)> or
+=item any verify mode, callback or depth set via L<SSL_set_verify(3)> or
L<SSL_set_verify_depth(3)> or any configured X509 verification parameters
=item any msg callback or info callback set via L<SSL_set_msg_callback(3)> or
@@ -124,9 +124,9 @@ L<ssl(7)>
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_pending.pod b/doc/man3/SSL_pending.pod
index eb42b554895e..c7cb6fce15cf 100644
--- a/doc/man3/SSL_pending.pod
+++ b/doc/man3/SSL_pending.pod
@@ -61,7 +61,7 @@ The SSL_has_pending() function was added in OpenSSL 1.1.0.
Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_read.pod b/doc/man3/SSL_read.pod
index 29ccd9947c32..0bfc2a413540 100644
--- a/doc/man3/SSL_read.pod
+++ b/doc/man3/SSL_read.pod
@@ -144,7 +144,7 @@ The SSL_read_ex() and SSL_peek_ex() functions were added in OpenSSL 1.1.1.
Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_read_early_data.pod b/doc/man3/SSL_read_early_data.pod
index 178bad731f1f..13c3bcf6a65d 100644
--- a/doc/man3/SSL_read_early_data.pod
+++ b/doc/man3/SSL_read_early_data.pod
@@ -66,7 +66,7 @@ the authentication stage of the handshake.
Early data has weaker security properties than other data sent over an SSL/TLS
connection. In particular the data does not have forward secrecy. There are also
-additional considerations around replay attacks (see L<REPLAY PROTECTION>
+additional considerations around replay attacks (see L</REPLAY PROTECTION>
below). For these reasons extreme care should be exercised when using early
data. For specific details, consult the TLS 1.3 specification.
@@ -367,7 +367,7 @@ All of the functions described above were added in OpenSSL 1.1.1.
Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_rstate_string.pod b/doc/man3/SSL_rstate_string.pod
index 7b3f52579ec3..2c0cf560e4de 100644
--- a/doc/man3/SSL_rstate_string.pod
+++ b/doc/man3/SSL_rstate_string.pod
@@ -60,7 +60,7 @@ L<ssl(7)>
Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_session_reused.pod b/doc/man3/SSL_session_reused.pod
index 82c59435901a..7b68e8a8cf69 100644
--- a/doc/man3/SSL_session_reused.pod
+++ b/doc/man3/SSL_session_reused.pod
@@ -44,9 +44,9 @@ L<SSL_CTX_set_session_cache_mode(3)>
=head1 COPYRIGHT
-Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_set1_host.pod b/doc/man3/SSL_set1_host.pod
index 5754d480c84a..c91a075a6a60 100644
--- a/doc/man3/SSL_set1_host.pod
+++ b/doc/man3/SSL_set1_host.pod
@@ -19,8 +19,8 @@ SSL server verification parameters
These functions configure server hostname checks in the SSL client.
SSL_set1_host() sets the expected DNS hostname to B<name> clearing
-any previously specified hostname or names. If B<name> is NULL,
-or the empty string the list of hostnames is cleared, and name
+any previously specified hostname. If B<name> is NULL
+or the empty string, the list of hostnames is cleared and name
checks are not performed on the peer certificate. When a nonempty
B<name> is specified, certificate verification automatically checks
the peer hostname via L<X509_check_host(3)> with B<flags> as specified
@@ -98,6 +98,7 @@ the lifetime of the SSL connection.
=head1 SEE ALSO
+L<ssl(7)>,
L<X509_check_host(3)>,
L<SSL_get_verify_result(3)>.
L<SSL_dane_enable(3)>.
@@ -110,7 +111,7 @@ These functions were added in OpenSSL 1.1.0.
Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_set_async_callback.pod b/doc/man3/SSL_set_async_callback.pod
new file mode 100644
index 000000000000..e0a665dc451b
--- /dev/null
+++ b/doc/man3/SSL_set_async_callback.pod
@@ -0,0 +1,131 @@
+=pod
+
+=head1 NAME
+
+SSL_CTX_set_async_callback,
+SSL_CTX_set_async_callback_arg,
+SSL_set_async_callback,
+SSL_set_async_callback_arg,
+SSL_get_async_status,
+SSL_async_callback_fn
+- manage asynchronous operations
+
+=head1 SYNOPSIS
+
+=for openssl multiple includes
+
+ #include <openssl/ssl.h>
+
+ typedef int (*SSL_async_callback_fn)(SSL *s, void *arg);
+ int SSL_CTX_set_async_callback(SSL_CTX *ctx, SSL_async_callback_fn callback);
+ int SSL_CTX_set_async_callback_arg(SSL_CTX *ctx, void *arg);
+ int SSL_set_async_callback(SSL *s, SSL_async_callback_fn callback);
+ int SSL_set_async_callback_arg(SSL *s, void *arg);
+ int SSL_get_async_status(SSL *s, int *status);
+
+=head1 DESCRIPTION
+
+SSL_CTX_set_async_callback() sets an asynchronous callback function. All B<SSL>
+objects generated based on this B<SSL_CTX> will get this callback. If an engine
+supports the callback mechanism, it will be automatically called if
+B<SSL_MODE_ASYNC> has been set and an asynchronous capable engine completes a
+cryptography operation to notify the application to resume the paused work flow.
+
+SSL_CTX_set_async_callback_arg() sets the callback argument.
+
+SSL_set_async_callback() allows an application to set a callback in an
+asynchronous B<SSL> object, so that when an engine completes a cryptography
+operation, the callback will be called to notify the application to resume the
+paused work flow.
+
+SSL_set_async_callback_arg() sets an argument for the B<SSL> object when the
+above callback is called.
+
+SSL_get_async_status() returns the engine status. This function facilitates the
+communication from the engine to the application. During an SSL session,
+cryptographic operations are dispatched to an engine. The engine status is very
+useful for an application to know if the operation has been successfully
+dispatched. If the engine does not support this additional callback method,
+B<ASYNC_STATUS_UNSUPPORTED> will be returned. See ASYNC_WAIT_CTX_set_status()
+for a description of all of the status values.
+
+An example of the above functions would be the following:
+
+=over 4
+
+=item 1.
+
+Application sets the async callback and callback data on an SSL connection
+by calling SSL_set_async_callback().
+
+=item 2.
+
+Application sets B<SSL_MODE_ASYNC> and makes an asynchronous SSL call
+
+=item 3.
+
+OpenSSL submits the asynchronous request to the engine. If a retry occurs at
+this point then the status within the B<ASYNC_WAIT_CTX> would be set and the
+async callback function would be called (goto Step 7).
+
+=item 4.
+
+The OpenSSL engine pauses the current job and returns, so that the
+application can continue processing other connections.
+
+=item 5.
+
+At a future point in time (probably via a polling mechanism or via an
+interrupt) the engine will become aware that the asynchronous request has
+finished processing.
+
+=item 6.
+
+The engine will call the application's callback passing the callback data as
+a parameter.
+
+=item 7.
+
+The callback function should then run. Note: it is a requirement that the
+callback function is small and nonblocking as it will be run in the context of
+a polling mechanism or an interrupt.
+
+=item 8.
+
+It is the application's responsibility via the callback function to schedule
+recalling the OpenSSL asynchronous function and to continue processing.
+
+=item 9.
+
+The callback function has the option to check the status returned via
+SSL_get_async_status() to determine whether a retry happened instead of the
+request being submitted, allowing different processing if required.
+
+=back
+
+=head1 RETURN VALUES
+
+SSL_CTX_set_async_callback(), SSL_set_async_callback(),
+SSL_CTX_set_async_callback_arg(), SSL_CTX_set_async_callback_arg() and
+SSL_get_async_status() return 1 on success or 0 on error.
+
+=head1 SEE ALSO
+
+L<ssl(7)>
+
+=head1 HISTORY
+
+SSL_CTX_set_async_callback(), SSL_CTX_set_async_callback_arg(),
+SSL_set_async_callback(), SSL_set_async_callback_arg() and
+SSL_get_async_status() were first added to OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/SSL_set_bio.pod b/doc/man3/SSL_set_bio.pod
index b824b5ae20ac..c666dc466ecd 100644
--- a/doc/man3/SSL_set_bio.pod
+++ b/doc/man3/SSL_set_bio.pod
@@ -78,10 +78,8 @@ and no references are consumed for the B<wbio>.
If the B<rbio> and B<wbio> parameters are different and the B<wbio>
is the same as the
previously set value and the old B<rbio> and B<wbio> values were different
-to each
-other then one reference is consumed for the B<rbio> and one reference
-is consumed
-for the B<wbio>.
+to each other, then one reference is consumed for the B<rbio> and one
+reference is consumed for the B<wbio>.
=back
@@ -104,9 +102,9 @@ SSL_set0_rbio() and SSL_set0_wbio() were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_set_connect_state.pod b/doc/man3/SSL_set_connect_state.pod
index 37bfa8fb54aa..559d23a759db 100644
--- a/doc/man3/SSL_set_connect_state.pod
+++ b/doc/man3/SSL_set_connect_state.pod
@@ -69,7 +69,7 @@ L<SSL_CTX_set_ssl_version(3)>
Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_set_fd.pod b/doc/man3/SSL_set_fd.pod
index 3195a4ece937..691b068d73fc 100644
--- a/doc/man3/SSL_set_fd.pod
+++ b/doc/man3/SSL_set_fd.pod
@@ -66,7 +66,7 @@ L<SSL_shutdown(3)>, L<ssl(7)> , L<bio(7)>
Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_set_retry_verify.pod b/doc/man3/SSL_set_retry_verify.pod
new file mode 100644
index 000000000000..4eb7f449ed59
--- /dev/null
+++ b/doc/man3/SSL_set_retry_verify.pod
@@ -0,0 +1,70 @@
+=pod
+
+=head1 NAME
+
+SSL_set_retry_verify - indicate that certificate verification should be retried
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ int SSL_set_retry_verify(SSL *ssl);
+
+=head1 DESCRIPTION
+
+SSL_set_retry_verify() should be called from the certificate verification
+callback on a client when the application wants to indicate that the handshake
+should be suspended and the control should be returned to the application.
+L<SSL_want_retry_verify(3)> will return 1 as a consequence until the handshake
+is resumed again by the application, retrying the verification step.
+
+Please refer to L<SSL_CTX_set_cert_verify_callback(3)> for further details.
+
+=head1 NOTES
+
+The effect of calling SSL_set_retry_verify() outside of the certificate
+verification callback on the client side is undefined.
+
+=head1 RETURN VALUES
+
+SSL_set_retry verify() returns 1 on success, 0 otherwise.
+
+=head1 EXAMPLES
+
+The following code snippet shows how to obtain the B<SSL> object associated
+with the B<X509_STORE_CTX> to call the SSL_set_retry_verify() function:
+
+ int idx = SSL_get_ex_data_X509_STORE_CTX_idx();
+ SSL *ssl;
+
+ /* this should not happen but check anyway */
+ if (idx < 0
+ || (ssl = X509_STORE_CTX_get_ex_data(ctx, idx)) == NULL)
+ return 0;
+
+ if (/* we need to retry verification callback */)
+ return SSL_set_retry_verify(ssl);
+
+ /* do normal processing of the verification callback */
+
+=head1 SEE ALSO
+
+L<ssl(7)>, L<SSL_connect(3)>, L<SSL_CTX_set_cert_verify_callback(3)>,
+L<SSL_want_retry_verify(3)>
+
+=head1 HISTORY
+
+SSL_set_retry_verify() was added in OpenSSL 3.0.2 to replace backwards
+incompatible handling of a negative return value from the verification
+callback.
+
+=head1 COPYRIGHT
+
+Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/SSL_set_session.pod b/doc/man3/SSL_set_session.pod
index 613035559c17..5e86ce5f87b7 100644
--- a/doc/man3/SSL_set_session.pod
+++ b/doc/man3/SSL_set_session.pod
@@ -21,7 +21,8 @@ with the L<SSL_session_reused(3)> call.
If there is already a session set inside B<ssl> (because it was set with
SSL_set_session() before or because the same B<ssl> was already used for
-a connection), SSL_SESSION_free() will be called for that session. If that old
+a connection), SSL_SESSION_free() will be called for that session.
+This is also the case when B<session> is a NULL pointer. If that old
session is still B<open>, it is considered bad and will be removed from the
session cache (if used). A session is considered open, if L<SSL_shutdown(3)> was
not called for the connection (or at least L<SSL_set_shutdown(3)> was used to
@@ -60,9 +61,9 @@ L<SSL_CTX_set_session_cache_mode(3)>
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_set_shutdown.pod b/doc/man3/SSL_set_shutdown.pod
index 1d08f6c2cf0f..54d541e4e4fe 100644
--- a/doc/man3/SSL_set_shutdown.pod
+++ b/doc/man3/SSL_set_shutdown.pod
@@ -20,7 +20,7 @@ SSL_get_shutdown() returns the shutdown mode of B<ssl>.
=head1 NOTES
-The shutdown state of an ssl connection is a bit mask of:
+The shutdown state of an ssl connection is a bit-mask of:
=over 4
@@ -71,9 +71,9 @@ L<SSL_clear(3)>, L<SSL_free(3)>
=head1 COPYRIGHT
-Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_set_verify_result.pod b/doc/man3/SSL_set_verify_result.pod
index 0a667af7e752..e095653849e4 100644
--- a/doc/man3/SSL_set_verify_result.pod
+++ b/doc/man3/SSL_set_verify_result.pod
@@ -23,7 +23,7 @@ the verification result of the B<ssl> object. It does not become part of the
established session, so if the session is to be reused later, the original
value will reappear.
-The valid codes for B<verify_result> are documented in L<verify(1)>.
+The valid codes for B<verify_result> are documented in L<openssl-verify(1)>.
=head1 RETURN VALUES
@@ -33,13 +33,13 @@ SSL_set_verify_result() does not provide a return value.
L<ssl(7)>, L<SSL_get_verify_result(3)>,
L<SSL_get_peer_certificate(3)>,
-L<verify(1)>
+L<openssl-verify(1)>
=head1 COPYRIGHT
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_shutdown.pod b/doc/man3/SSL_shutdown.pod
index a77721c85269..6797006a283e 100644
--- a/doc/man3/SSL_shutdown.pod
+++ b/doc/man3/SSL_shutdown.pod
@@ -15,8 +15,6 @@ SSL_shutdown - shut down a TLS/SSL connection
SSL_shutdown() shuts down an active TLS/SSL connection. It sends the
close_notify shutdown alert to the peer.
-=head1 NOTES
-
SSL_shutdown() tries to send the close_notify shutdown alert to the peer.
Whether the operation succeeds or not, the SSL_SENT_SHUTDOWN flag is set and
a currently open session is considered closed and good and will be kept in the
@@ -52,6 +50,44 @@ SSL_shutdown() only closes the write direction.
It is not possible to call SSL_write() after calling SSL_shutdown().
The read direction is closed by the peer.
+The behaviour of SSL_shutdown() additionally depends on the underlying BIO.
+If the underlying BIO is B<blocking>, SSL_shutdown() will only return once the
+handshake step has been finished or an error occurred.
+
+If the underlying BIO is B<nonblocking>, SSL_shutdown() will also return
+when the underlying BIO could not satisfy the needs of SSL_shutdown()
+to continue the handshake. In this case a call to SSL_get_error() with the
+return value of SSL_shutdown() will yield B<SSL_ERROR_WANT_READ> or
+B<SSL_ERROR_WANT_WRITE>. The calling process then must repeat the call after
+taking appropriate action to satisfy the needs of SSL_shutdown().
+The action depends on the underlying BIO. When using a nonblocking socket,
+nothing is to be done, but select() can be used to check for the required
+condition. When using a buffering BIO, like a BIO pair, data must be written
+into or retrieved out of the BIO before being able to continue.
+
+After SSL_shutdown() returned 0, it is possible to call SSL_shutdown() again
+to wait for the peer's close_notify alert.
+SSL_shutdown() will return 1 in that case.
+However, it is recommended to wait for it using SSL_read() instead.
+
+SSL_shutdown() can be modified to only set the connection to "shutdown"
+state but not actually send the close_notify alert messages,
+see L<SSL_CTX_set_quiet_shutdown(3)>.
+When "quiet shutdown" is enabled, SSL_shutdown() will always succeed
+and return 1.
+Note that this is not standard compliant behaviour.
+It should only be done when the peer has a way to make sure all
+data has been received and doesn't wait for the close_notify alert
+message, otherwise an unexpected EOF will be reported.
+
+There are implementations that do not send the required close_notify alert.
+If there is a need to communicate with such an implementation, and it's clear
+that all data has been received, do not wait for the peer's close_notify alert.
+Waiting for the close_notify alert when the peer just closes the connection
+will result in an error being generated.
+The error can be ignored using the B<SSL_OP_IGNORE_UNEXPECTED_EOF>.
+For more information see L<SSL_CTX_set_options(3)>.
+
=head2 First to close the connection
When the application is the first party to send the close_notify
@@ -89,44 +125,6 @@ If successful, SSL_shutdown() will return 1.
Whether SSL_RECEIVED_SHUTDOWN is already set can be checked using the
SSL_get_shutdown() (see also L<SSL_set_shutdown(3)> call.
-=head1 NOTES
-
-The behaviour of SSL_shutdown() additionally depends on the underlying BIO.
-If the underlying BIO is B<blocking>, SSL_shutdown() will only return once the
-handshake step has been finished or an error occurred.
-
-If the underlying BIO is B<nonblocking>, SSL_shutdown() will also return
-when the underlying BIO could not satisfy the needs of SSL_shutdown()
-to continue the handshake. In this case a call to SSL_get_error() with the
-return value of SSL_shutdown() will yield B<SSL_ERROR_WANT_READ> or
-B<SSL_ERROR_WANT_WRITE>. The calling process then must repeat the call after
-taking appropriate action to satisfy the needs of SSL_shutdown().
-The action depends on the underlying BIO. When using a nonblocking socket,
-nothing is to be done, but select() can be used to check for the required
-condition. When using a buffering BIO, like a BIO pair, data must be written
-into or retrieved out of the BIO before being able to continue.
-
-After SSL_shutdown() returned 0, it is possible to call SSL_shutdown() again
-to wait for the peer's close_notify alert.
-SSL_shutdown() will return 1 in that case.
-However, it is recommended to wait for it using SSL_read() instead.
-
-SSL_shutdown() can be modified to only set the connection to "shutdown"
-state but not actually send the close_notify alert messages,
-see L<SSL_CTX_set_quiet_shutdown(3)>.
-When "quiet shutdown" is enabled, SSL_shutdown() will always succeed
-and return 1.
-Note that this is not standard compliant behaviour.
-It should only be done when the peer has a way to make sure all
-data has been received and doesn't wait for the close_notify alert
-message, otherwise an unexpected EOF will be reported.
-
-There are implementations that do not send the required close_notify alert.
-If there is a need to communicate with such an implementation, and it's clear
-that all data has been received, do not wait for the peer's close_notify alert.
-Waiting for the close_notify alert when the peer just closes the connection will
-result in an error being generated.
-
=head1 RETURN VALUES
The following return values can occur:
@@ -163,7 +161,7 @@ It can also occur when not all data was read using SSL_read().
L<SSL_get_error(3)>, L<SSL_connect(3)>,
L<SSL_accept(3)>, L<SSL_set_shutdown(3)>,
-L<SSL_CTX_set_quiet_shutdown(3)>,
+L<SSL_CTX_set_quiet_shutdown(3)>, L<SSL_CTX_set_options(3)>
L<SSL_clear(3)>, L<SSL_free(3)>,
L<ssl(7)>, L<bio(7)>
@@ -171,7 +169,7 @@ L<ssl(7)>, L<bio(7)>
Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_state_string.pod b/doc/man3/SSL_state_string.pod
index 54dfdd6c231f..e2bf66b95aa9 100644
--- a/doc/man3/SSL_state_string.pod
+++ b/doc/man3/SSL_state_string.pod
@@ -13,10 +13,10 @@ SSL_state_string, SSL_state_string_long - get textual description of state of an
=head1 DESCRIPTION
-SSL_state_string() returns a 6 letter string indicating the current state
-of the SSL object B<ssl>.
+SSL_state_string() returns an abbreviated string indicating the current state
+of the SSL object B<ssl>. The returned NUL-terminated string contains 6 or fewer characters.
-SSL_state_string_long() returns a string indicating the current state of
+SSL_state_string_long() returns a descriptive string indicating the current state of
the SSL object B<ssl>.
=head1 NOTES
@@ -44,9 +44,9 @@ L<ssl(7)>, L<SSL_CTX_set_info_callback(3)>
=head1 COPYRIGHT
-Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_want.pod b/doc/man3/SSL_want.pod
index 4827e7eeac7f..1d274fd342a2 100644
--- a/doc/man3/SSL_want.pod
+++ b/doc/man3/SSL_want.pod
@@ -2,9 +2,9 @@
=head1 NAME
-SSL_want, SSL_want_nothing, SSL_want_read, SSL_want_write, SSL_want_x509_lookup,
-SSL_want_async, SSL_want_async_job, SSL_want_client_hello_cb - obtain state
-information TLS/SSL I/O operation
+SSL_want, SSL_want_nothing, SSL_want_read, SSL_want_write,
+SSL_want_x509_lookup, SSL_want_retry_verify, SSL_want_async, SSL_want_async_job,
+SSL_want_client_hello_cb - obtain state information TLS/SSL I/O operation
=head1 SYNOPSIS
@@ -15,6 +15,7 @@ information TLS/SSL I/O operation
int SSL_want_read(const SSL *ssl);
int SSL_want_write(const SSL *ssl);
int SSL_want_x509_lookup(const SSL *ssl);
+ int SSL_want_retry_verify(const SSL *ssl);
int SSL_want_async(const SSL *ssl);
int SSL_want_async_job(const SSL *ssl);
int SSL_want_client_hello_cb(const SSL *ssl);
@@ -53,47 +54,50 @@ There is no data to be written or to be read.
There are data in the SSL buffer that must be written to the underlying
B<BIO> layer in order to complete the actual SSL_*() operation.
-A call to L<SSL_get_error(3)> should return
-SSL_ERROR_WANT_WRITE.
+A call to L<SSL_get_error(3)> should return B<SSL_ERROR_WANT_WRITE>.
=item SSL_READING
More data must be read from the underlying B<BIO> layer in order to
complete the actual SSL_*() operation.
-A call to L<SSL_get_error(3)> should return
-SSL_ERROR_WANT_READ.
+A call to L<SSL_get_error(3)> should return B<SSL_ERROR_WANT_READ>.
=item SSL_X509_LOOKUP
The operation did not complete because an application callback set by
SSL_CTX_set_client_cert_cb() has asked to be called again.
-A call to L<SSL_get_error(3)> should return
-SSL_ERROR_WANT_X509_LOOKUP.
+A call to L<SSL_get_error(3)> should return B<SSL_ERROR_WANT_X509_LOOKUP>.
+
+=item SSL_RETRY_VERIFY
+
+The operation did not complete because a certificate verification callback
+has asked to be called again via L<SSL_set_retry_verify(3)>.
+A call to L<SSL_get_error(3)> should return B<SSL_ERROR_WANT_RETRY_VERIFY>.
=item SSL_ASYNC_PAUSED
An asynchronous operation partially completed and was then paused. See
L<SSL_get_all_async_fds(3)>. A call to L<SSL_get_error(3)> should return
-SSL_ERROR_WANT_ASYNC.
+B<SSL_ERROR_WANT_ASYNC>.
=item SSL_ASYNC_NO_JOBS
The asynchronous job could not be started because there were no async jobs
available in the pool (see ASYNC_init_thread(3)). A call to L<SSL_get_error(3)>
-should return SSL_ERROR_WANT_ASYNC_JOB.
+should return B<SSL_ERROR_WANT_ASYNC_JOB>.
=item SSL_CLIENT_HELLO_CB
The operation did not complete because an application callback set by
SSL_CTX_set_client_hello_cb() has asked to be called again.
-A call to L<SSL_get_error(3)> should return
-SSL_ERROR_WANT_CLIENT_HELLO_CB.
+A call to L<SSL_get_error(3)> should return B<SSL_ERROR_WANT_CLIENT_HELLO_CB>.
=back
-SSL_want_nothing(), SSL_want_read(), SSL_want_write(), SSL_want_x509_lookup(),
-SSL_want_async(), SSL_want_async_job(), and SSL_want_client_hello_cb() return
-1, when the corresponding condition is true or 0 otherwise.
+SSL_want_nothing(), SSL_want_read(), SSL_want_write(),
+SSL_want_x509_lookup(), SSL_want_retry_verify(),
+SSL_want_async(), SSL_want_async_job(), and SSL_want_client_hello_cb()
+return 1 when the corresponding condition is true or 0 otherwise.
=head1 SEE ALSO
@@ -106,9 +110,9 @@ were added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/SSL_write.pod b/doc/man3/SSL_write.pod
index 5e3ce1e7e4dd..e03cce2ad62e 100644
--- a/doc/man3/SSL_write.pod
+++ b/doc/man3/SSL_write.pod
@@ -2,12 +2,13 @@
=head1 NAME
-SSL_write_ex, SSL_write - write bytes to a TLS/SSL connection
+SSL_write_ex, SSL_write, SSL_sendfile - write bytes to a TLS/SSL connection
=head1 SYNOPSIS
#include <openssl/ssl.h>
+ ossl_ssize_t SSL_sendfile(SSL *s, int fd, off_t offset, size_t size, int flags);
int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written);
int SSL_write(SSL *ssl, const void *buf, int num);
@@ -17,6 +18,14 @@ SSL_write_ex() and SSL_write() write B<num> bytes from the buffer B<buf> into
the specified B<ssl> connection. On success SSL_write_ex() will store the number
of bytes written in B<*written>.
+SSL_sendfile() writes B<size> bytes from offset B<offset> in the file
+descriptor B<fd> to the specified SSL connection B<s>. This function provides
+efficient zero-copy semantics. SSL_sendfile() is available only when
+Kernel TLS is enabled, which can be checked by calling BIO_get_ktls_send().
+It is provided here to allow users to maintain the same interface.
+The meaning of B<flags> is platform dependent.
+Currently, under Linux it is ignored.
+
=head1 NOTES
In the paragraphs below a "write function" is defined as one of either
@@ -104,23 +113,42 @@ You should instead call SSL_get_error() to find out if it's retryable.
=back
+For SSL_sendfile(), the following return values can occur:
+
+=over 4
+
+=item Z<>>= 0
+
+The write operation was successful, the return value is the number
+of bytes of the file written to the TLS/SSL connection. The return
+value can be less than B<size> for a partial write.
+
+=item E<lt> 0
+
+The write operation was not successful, because either the connection was
+closed, an error occurred or action must be taken by the calling process.
+Call SSL_get_error() with the return value to find out the reason.
+
+=back
+
=head1 SEE ALSO
L<SSL_get_error(3)>, L<SSL_read_ex(3)>, L<SSL_read(3)>
L<SSL_CTX_set_mode(3)>, L<SSL_CTX_new(3)>,
L<SSL_connect(3)>, L<SSL_accept(3)>
-L<SSL_set_connect_state(3)>,
+L<SSL_set_connect_state(3)>, L<BIO_ctrl(3)>,
L<ssl(7)>, L<bio(7)>
=head1 HISTORY
The SSL_write_ex() function was added in OpenSSL 1.1.1.
+The SSL_sendfile() function was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/TS_RESP_CTX_new.pod b/doc/man3/TS_RESP_CTX_new.pod
new file mode 100644
index 000000000000..725a1921d133
--- /dev/null
+++ b/doc/man3/TS_RESP_CTX_new.pod
@@ -0,0 +1,49 @@
+=pod
+
+=head1 NAME
+
+TS_RESP_CTX_new_ex, TS_RESP_CTX_new,
+TS_RESP_CTX_free - Timestamp response context object creation
+
+=head1 SYNOPSIS
+
+ #include <openssl/ts.h>
+
+ TS_RESP_CTX *TS_RESP_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq);
+ TS_RESP_CTX *TS_RESP_CTX_new(void);
+ void TS_RESP_CTX_free(TS_RESP_CTX *ctx);
+
+=head1 DESCRIPTION
+
+Creates a response context that can be used for generating responses.
+
+TS_RESP_CTX_new_ex() allocates and initializes a TS_RESP_CTX structure with a
+library context of I<libctx> and a property query of I<propq>.
+The library context and property query can be used to select which providers
+supply the fetched algorithms.
+
+TS_RESP_CTX_new() is similar to TS_RESP_CTX_new_ex() but sets the library context
+and property query to NULL. This results in the default (NULL) library context
+being used for any operations requiring algorithm fetches.
+
+TS_RESP_CTX_free() frees the B<TS_RESP_CTX> object I<ctx>.
+
+=head1 RETURN VALUES
+
+If the allocation fails, TS_RESP_CTX_new_ex() and TS_RESP_CTX_new() return NULL,
+otherwise it returns a pointer to the newly allocated structure.
+
+=head1 HISTORY
+
+The function TS_RESP_CTX_new_ex() was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/TS_VERIFY_CTX_set_certs.pod b/doc/man3/TS_VERIFY_CTX_set_certs.pod
new file mode 100644
index 000000000000..5a35302c4100
--- /dev/null
+++ b/doc/man3/TS_VERIFY_CTX_set_certs.pod
@@ -0,0 +1,61 @@
+=pod
+
+=head1 NAME
+
+TS_VERIFY_CTX_set_certs, TS_VERIFY_CTS_set_certs
+- set certificates for TS response verification
+
+=head1 SYNOPSIS
+
+ #include <openssl/ts.h>
+
+ STACK_OF(X509) *TS_VERIFY_CTX_set_certs(TS_VERIFY_CTX *ctx,
+ STACK_OF(X509) *certs);
+ STACK_OF(X509) *TS_VERIFY_CTS_set_certs(TS_VERIFY_CTX *ctx,
+ STACK_OF(X509) *certs);
+
+=head1 DESCRIPTION
+
+The Time-Stamp Protocol (TSP) is defined by RFC 3161. TSP is a protocol used to
+provide long term proof of the existence of a certain datum before a particular
+time. TSP defines a Time Stamping Authority (TSA) and an entity who shall make
+requests to the TSA. Usually the TSA is denoted as the server side and the
+requesting entity is denoted as the client.
+
+In TSP, when a server is sending a response to a client, the server normally
+needs to sign the response data - the TimeStampToken (TST) - with its private
+key. Then the client shall verify the received TST by the server's certificate
+chain.
+
+TS_VERIFY_CTX_set_certs() is used to set the server's certificate chain when
+verifying a TST. B<ctx> is the verification context created in advance and
+B<certs> is a stack of B<X509> certificates.
+
+TS_VERIFY_CTS_set_certs() is a misspelled version of TS_VERIFY_CTX_set_certs()
+which takes the same parameters and returns the same result.
+
+=head1 RETURN VALUES
+
+TS_VERIFY_CTX_set_certs() returns the stack of B<X509> certificates the user
+passes in via parameter B<certs>.
+
+=head1 SEE ALSO
+
+L<OSSL_ESS_check_signing_certs(3)>
+
+=head1 HISTORY
+
+The spelling of TS_VERIFY_CTX_set_certs() was corrected in OpenSSL 3.0.0.
+The misspelled version TS_VERIFY_CTS_set_certs() has been retained for
+compatibility reasons, but it is deprecated in OpenSSL 3.0.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/UI_STRING.pod b/doc/man3/UI_STRING.pod
index 96dcf4db0f26..12acf8d6840b 100644
--- a/doc/man3/UI_STRING.pod
+++ b/doc/man3/UI_STRING.pod
@@ -139,7 +139,7 @@ L<UI(3)>
Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/UI_UTIL_read_pw.pod b/doc/man3/UI_UTIL_read_pw.pod
index a6528a0300aa..9de8fe1ddc97 100644
--- a/doc/man3/UI_UTIL_read_pw.pod
+++ b/doc/man3/UI_UTIL_read_pw.pod
@@ -62,9 +62,9 @@ L<UI_get_default_method(3)>
=head1 COPYRIGHT
-Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/UI_create_method.pod b/doc/man3/UI_create_method.pod
index c9295ff52649..23af53eccd88 100644
--- a/doc/man3/UI_create_method.pod
+++ b/doc/man3/UI_create_method.pod
@@ -212,7 +212,7 @@ and UI_method_get_data_destructor() functions were added in OpenSSL 1.1.1.
Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/UI_new.pod b/doc/man3/UI_new.pod
index f40b65df40e9..eb80f453d5c6 100644
--- a/doc/man3/UI_new.pod
+++ b/doc/man3/UI_new.pod
@@ -44,7 +44,7 @@ UI_get_method, UI_set_method, UI_OpenSSL, UI_null - user interface
int UI_dup_error_string(UI *ui, const char *text);
char *UI_construct_prompt(UI *ui_method,
- const char *object_desc, const char *object_name);
+ const char *phrase_desc, const char *object_name);
void *UI_add_user_data(UI *ui, void *user_data);
int UI_dup_user_data(UI *ui, void *user_data);
@@ -132,7 +132,7 @@ the possible answers (given through the I<action_desc> argument).
UI_add_info_string() and UI_add_error_string() add strings that are shown at
the same time as the prompt for extra information or to show an error string.
-The difference between the two is only conceptual. With the builtin method,
+The difference between the two is only conceptual. With the built-in method,
there's no technical difference between them. Other methods may make a
difference between them, however.
@@ -149,16 +149,18 @@ as their UI_add counterparts, except that they make their own copies
of all strings.
UI_construct_prompt() is a helper function that can be used to create
-a prompt from two pieces of information: an description and a name.
+a prompt from two pieces of information: a phrase description I<phrase_desc>
+and an object name I<object_name>, where the latter may be NULL.
The default constructor (if there is none provided by the method used)
-creates a string "Enter I<description> for I<name>:". With the
-description "pass phrase" and the filename "foo.key", that becomes
+creates a string "Enter I<phrase_desc> for I<object_name>:"
+where the " for I<object_name>" part is left out if I<object_name> is NULL.
+With the description "pass phrase" and the filename "foo.key", that becomes
"Enter pass phrase for foo.key:". Other methods may create whatever
string and may include encodings that will be processed by the other
method functions.
UI_add_user_data() adds a user data pointer for the method to use at any
-time. The builtin UI method doesn't care about this info. Note that several
+time. The built-in UI method doesn't care about this info. Note that several
calls to this function doesn't add data, it replaces the previous blob
with the one given as argument.
@@ -205,7 +207,7 @@ are assumed to be encoded according to the current locale or (for
Windows) code page.
For applications having different demands, these strings need to be
converted appropriately by the caller.
-For Windows, if the OPENSSL_WIN32_UTF8 environment variable is set,
+For Windows, if the B<OPENSSL_WIN32_UTF8> environment variable is set,
the built-in method UI_OpenSSL() will produce UTF-8 encoded strings
instead.
@@ -245,7 +247,7 @@ The UI_dup_user_data() function was added in OpenSSL 1.1.1.
Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509V3_get_d2i.pod b/doc/man3/X509V3_get_d2i.pod
index 159948b17029..4a2e81b0dbdf 100644
--- a/doc/man3/X509V3_get_d2i.pod
+++ b/doc/man3/X509V3_get_d2i.pod
@@ -2,11 +2,12 @@
=head1 NAME
-X509_get0_extensions, X509_CRL_get0_extensions, X509_REVOKED_get0_extensions,
X509V3_get_d2i, X509V3_add1_i2d, X509V3_EXT_d2i, X509V3_EXT_i2d,
-X509_get_ext_d2i, X509_add1_ext_i2d, X509_CRL_get_ext_d2i,
-X509_CRL_add1_ext_i2d, X509_REVOKED_get_ext_d2i,
-X509_REVOKED_add1_ext_i2d - X509 extension decode and encode functions
+X509_get_ext_d2i, X509_add1_ext_i2d,
+X509_CRL_get_ext_d2i, X509_CRL_add1_ext_i2d,
+X509_REVOKED_get_ext_d2i, X509_REVOKED_add1_ext_i2d,
+X509_get0_extensions, X509_CRL_get0_extensions,
+X509_REVOKED_get0_extensions - X509 extension decode and encode functions
=head1 SYNOPSIS
@@ -18,7 +19,7 @@ X509_REVOKED_add1_ext_i2d - X509 extension decode and encode functions
int crit, unsigned long flags);
void *X509V3_EXT_d2i(X509_EXTENSION *ext);
- X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext);
+ X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc);
void *X509_get_ext_d2i(const X509 *x, int nid, int *crit, int *idx);
int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit,
@@ -38,75 +39,79 @@ X509_REVOKED_add1_ext_i2d - X509 extension decode and encode functions
=head1 DESCRIPTION
-X509V3_get_ext_d2i() looks for an extension with OID B<nid> in the extensions
-B<x> and, if found, decodes it. If B<idx> is B<NULL> then only one
-occurrence of an extension is permissible otherwise the first extension after
-index B<*idx> is returned and B<*idx> updated to the location of the extension.
-If B<crit> is not B<NULL> then B<*crit> is set to a status value: -2 if the
-extension occurs multiple times (this is only returned if B<idx> is B<NULL>),
+X509V3_get_d2i() looks for an extension with OID I<nid> in the extensions
+I<x> and, if found, decodes it. If I<idx> is NULL then only one
+occurrence of an extension is permissible, otherwise the first extension after
+index I<*idx> is returned and I<*idx> updated to the location of the extension.
+If I<crit> is not NULL then I<*crit> is set to a status value: -2 if the
+extension occurs multiple times (this is only returned if I<idx> is NULL),
-1 if the extension could not be found, 0 if the extension is found and is
not critical and 1 if critical. A pointer to an extension specific structure
-or B<NULL> is returned.
+or NULL is returned.
-X509V3_add1_i2d() adds extension B<value> to STACK B<*x> (allocating a new
-STACK if necessary) using OID B<nid> and criticality B<crit> according
-to B<flags>.
+X509V3_add1_i2d() adds extension I<value> to STACK I<*x> (allocating a new
+STACK if necessary) using OID I<nid> and criticality I<crit> according
+to I<flags>.
X509V3_EXT_d2i() attempts to decode the ASN.1 data contained in extension
-B<ext> and returns a pointer to an extension specific structure or B<NULL>
+I<ext> and returns a pointer to an extension specific structure or NULL
if the extension could not be decoded (invalid syntax or not supported).
-X509V3_EXT_i2d() encodes the extension specific structure B<ext>
-with OID B<ext_nid> and criticality B<crit>.
+X509V3_EXT_i2d() encodes the extension specific structure I<ext_struc>
+with OID I<ext_nid> and criticality I<crit>.
X509_get_ext_d2i() and X509_add1_ext_i2d() operate on the extensions of
-certificate B<x>, they are otherwise identical to X509V3_get_d2i() and
-X509V3_add_i2d().
+certificate I<x>. They are otherwise identical to X509V3_get_d2i() and
+X509V3_add1_i2d().
X509_CRL_get_ext_d2i() and X509_CRL_add1_ext_i2d() operate on the extensions
-of CRL B<crl>, they are otherwise identical to X509V3_get_d2i() and
-X509V3_add_i2d().
+of CRL I<crl>. They are otherwise identical to X509V3_get_d2i() and
+X509V3_add1_i2d().
X509_REVOKED_get_ext_d2i() and X509_REVOKED_add1_ext_i2d() operate on the
-extensions of B<X509_REVOKED> structure B<r> (i.e for CRL entry extensions),
-they are otherwise identical to X509V3_get_d2i() and X509V3_add_i2d().
+extensions of B<X509_REVOKED> structure I<r> (i.e for CRL entry extensions).
+They are otherwise identical to X509V3_get_d2i() and X509V3_add1_i2d().
X509_get0_extensions(), X509_CRL_get0_extensions() and
-X509_REVOKED_get0_extensions() return a stack of all the extensions
-of a certificate a CRL or a CRL entry respectively.
+X509_REVOKED_get0_extensions() return a STACK of all the extensions
+of a certificate, a CRL or a CRL entry respectively.
=head1 NOTES
In almost all cases an extension can occur at most once and multiple
-occurrences is an error. Therefore, the B<idx> parameter is usually B<NULL>.
+occurrences is an error. Therefore, the I<idx> parameter is usually NULL.
-The B<flags> parameter may be one of the following values.
+The I<flags> parameter may be one of the following values.
B<X509V3_ADD_DEFAULT> appends a new extension only if the extension does
-not already exist. An error is returned if the extension does already
-exist.
+not exist. An error is returned if the extension exists.
B<X509V3_ADD_APPEND> appends a new extension, ignoring whether the extension
-already exists.
+exists.
-B<X509V3_ADD_REPLACE> replaces an extension if it exists otherwise appends
-a new extension.
+B<X509V3_ADD_REPLACE> replaces an existing extension. If the extension does
+not exist, appends a new extension.
-B<X509V3_ADD_REPLACE_EXISTING> replaces an existing extension if it exists
-otherwise returns an error.
+B<X509V3_ADD_REPLACE_EXISTING> replaces an existing extension. If the
+extension does not exist, returns an error.
B<X509V3_ADD_KEEP_EXISTING> appends a new extension only if the extension does
-not already exist. An error B<is not> returned if the extension does already
-exist.
+not exist. An error is B<not> returned if the extension exists.
-B<X509V3_ADD_DELETE> extension B<nid> is deleted: no new extension is added.
+B<X509V3_ADD_DELETE> deletes and frees an existing extension. If the extension
+does not exist, returns an error. No new extension is added.
-If B<X509V3_ADD_SILENT> is ored with B<flags>: any error returned will not
-be added to the error queue.
+If B<X509V3_ADD_SILENT> is bitwise ORed with I<flags>: any error returned
+will not be added to the error queue.
-The function X509V3_get_d2i() will return B<NULL> if the extension is not
+The function X509V3_get_d2i() and its variants
+will return NULL if the extension is not
found, occurs multiple times or cannot be decoded. It is possible to
-determine the precise reason by checking the value of B<*crit>.
+determine the precise reason by checking the value of I<*crit>.
+
+The function X509V3_add1_i2d() and its variants allocate B<X509_EXTENSION>
+objects on STACK I<*x> depending on I<flags>. The B<X509_EXTENSION> objects
+must be explicitly freed using X509_EXTENSION_free().
=head1 SUPPORTED EXTENSIONS
@@ -195,17 +200,17 @@ The following extensions are used by certificate transparency, RFC6962
=head1 RETURN VALUES
-X509V3_EXT_d2i() and *X509V3_get_d2i() return a pointer to an extension
-specific structure of B<NULL> if an error occurs.
-
-X509V3_EXT_i2d() returns a pointer to an B<X509_EXTENSION> structure
-or B<NULL> if an error occurs.
+X509V3_get_d2i(), its variants, and X509V3_EXT_d2i() return
+a pointer to an extension specific structure or NULL if an error occurs.
-X509V3_add1_i2d() returns 1 if the operation is successful and 0 if it
-fails due to a non-fatal error (extension not found, already exists,
+X509V3_add1_i2d() and its variants return 1 if the operation is successful
+and 0 if it fails due to a non-fatal error (extension not found, already exists,
cannot be encoded) or -1 due to a fatal error such as a memory allocation
failure.
+X509V3_EXT_i2d() returns a pointer to an B<X509_EXTENSION> structure
+or NULL if an error occurs.
+
X509_get0_extensions(), X509_CRL_get0_extensions() and
X509_REVOKED_get0_extensions() return a stack of extensions. They return
NULL if no extensions are present.
@@ -231,9 +236,9 @@ L<X509_verify_cert(3)>
=head1 COPYRIGHT
-Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509V3_set_ctx.pod b/doc/man3/X509V3_set_ctx.pod
new file mode 100644
index 000000000000..8287802e41b2
--- /dev/null
+++ b/doc/man3/X509V3_set_ctx.pod
@@ -0,0 +1,67 @@
+=pod
+
+=head1 NAME
+
+X509V3_set_ctx,
+X509V3_set_issuer_pkey - X.509 v3 extension generation utilities
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509v3.h>
+
+ void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subject,
+ X509_REQ *req, X509_CRL *crl, int flags);
+ int X509V3_set_issuer_pkey(X509V3_CTX *ctx, EVP_PKEY *pkey);
+
+=head1 DESCRIPTION
+
+X509V3_set_ctx() fills in the basic fields of I<ctx> of type B<X509V3_CTX>,
+providing details potentially needed by functions producing X509 v3 extensions,
+e.g., to look up values for filling in authority key identifiers.
+Any of I<subject>, I<req>, or I<crl> may be provided, pointing to a certificate,
+certification request, or certificate revocation list, respectively.
+When constructing the subject key identifier of a certificate by computing a
+hash value of its public key, the public key is taken from I<subject> or I<req>.
+Similarly, when constructing subject alternative names from any email addresses
+contained in a subject DN, the subject DN is taken from I<subject> or I<req>.
+If I<subject> or I<crl> is provided, I<issuer> should point to its issuer,
+for instance to help generating an authority key identifier extension.
+Note that if I<subject> is provided, I<issuer> may be the same as I<subject>,
+which means that I<subject> is self-issued (or even self-signed).
+I<flags> may be 0
+or contain B<X509V3_CTX_TEST>, which means that just the syntax of
+extension definitions is to be checked without actually producing an extension,
+or B<X509V3_CTX_REPLACE>, which means that each X.509v3 extension added as
+defined in some configuration section shall replace any already existing
+extension with the same OID.
+
+X509V3_set_issuer_pkey() explicitly sets the issuer private key of
+the certificate that has been provided in I<ctx>.
+This should be done for self-issued certificates (which may be self-signed
+or not) to provide fallback data for the authority key identifier extension.
+
+=head1 RETURN VALUES
+
+X509V3_set_ctx() and X509V3_set_issuer_pkey()
+return 1 on success and 0 on error.
+
+=head1 SEE ALSO
+
+L<X509_add_ext(3)>
+
+=head1 HISTORY
+
+X509V3_set_issuer_pkey() was added in OpenSSL 3.0.
+
+CTX_TEST was deprecated in OpenSSL 3.0; use X509V3_CTX_TEST instead.
+
+=head1 COPYRIGHT
+
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/X509_ALGOR_dup.pod b/doc/man3/X509_ALGOR_dup.pod
index de2faf8547af..7696fc61cc8f 100644
--- a/doc/man3/X509_ALGOR_dup.pod
+++ b/doc/man3/X509_ALGOR_dup.pod
@@ -60,7 +60,7 @@ The X509_ALGOR_copy() was added in 1.1.1e.
Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_CRL_get0_by_serial.pod b/doc/man3/X509_CRL_get0_by_serial.pod
index a704228eb9ec..67e4f4c3f802 100644
--- a/doc/man3/X509_CRL_get0_by_serial.pod
+++ b/doc/man3/X509_CRL_get0_by_serial.pod
@@ -13,7 +13,7 @@ functions
#include <openssl/x509.h>
int X509_CRL_get0_by_serial(X509_CRL *crl,
- X509_REVOKED **ret, ASN1_INTEGER *serial);
+ X509_REVOKED **ret, const ASN1_INTEGER *serial);
int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x);
STACK_OF(X509_REVOKED) *X509_CRL_get_REVOKED(X509_CRL *crl);
@@ -30,42 +30,42 @@ functions
=head1 DESCRIPTION
-X509_CRL_get0_by_serial() attempts to find a revoked entry in B<crl> for
-serial number B<serial>. If it is successful it sets B<*ret> to the internal
-pointer of the matching entry, as a result B<*ret> must not be freed up
+X509_CRL_get0_by_serial() attempts to find a revoked entry in I<crl> for
+serial number I<serial>. If it is successful, it sets I<*ret> to the internal
+pointer of the matching entry. As a result, I<*ret> B<MUST NOT> be freed
after the call.
X509_CRL_get0_by_cert() is similar to X509_get0_by_serial() except it
-looks for a revoked entry using the serial number of certificate B<x>.
+looks for a revoked entry using the serial number of certificate I<x>.
-X509_CRL_get_REVOKED() returns an internal pointer to a stack of all
-revoked entries for B<crl>.
+X509_CRL_get_REVOKED() returns an internal pointer to a STACK of all
+revoked entries for I<crl>.
X509_REVOKED_get0_serialNumber() returns an internal pointer to the
-serial number of B<r>.
+serial number of I<r>.
X509_REVOKED_get0_revocationDate() returns an internal pointer to the
-revocation date of B<r>.
+revocation date of I<r>.
-X509_REVOKED_set_serialNumber() sets the serial number of B<r> to B<serial>.
-The supplied B<serial> pointer is not used internally so it should be
-freed up after use.
+X509_REVOKED_set_serialNumber() sets the serial number of I<r> to I<serial>.
+The supplied I<serial> pointer is not used internally so it should be
+freed after use.
-X509_REVOKED_set_revocationDate() sets the revocation date of B<r> to
-B<tm>. The supplied B<tm> pointer is not used internally so it should be
-freed up after use.
+X509_REVOKED_set_revocationDate() sets the revocation date of I<r> to
+I<tm>. The supplied I<tm> pointer is not used internally so it should be
+freed after use.
-X509_CRL_add0_revoked() appends revoked entry B<rev> to CRL B<crl>. The
-pointer B<rev> is used internally so it must not be freed up after the call:
+X509_CRL_add0_revoked() appends revoked entry I<rev> to CRL I<crl>. The
+pointer I<rev> is used internally so it B<MUST NOT> be freed after the call:
it is freed when the parent CRL is freed.
-X509_CRL_sort() sorts the revoked entries of B<crl> into ascending serial
+X509_CRL_sort() sorts the revoked entries of I<crl> into ascending serial
number order.
=head1 NOTES
Applications can determine the number of revoked entries returned by
-X509_CRL_get_revoked() using sk_X509_REVOKED_num() and examine each one
+X509_CRL_get_REVOKED() using sk_X509_REVOKED_num() and examine each one
in turn using sk_X509_REVOKED_value().
=head1 RETURN VALUES
@@ -74,15 +74,15 @@ X509_CRL_get0_by_serial() and X509_CRL_get0_by_cert() return 0 for failure,
1 on success except if the revoked entry has the reason C<removeFromCRL> (8),
in which case 2 is returned.
-X509_REVOKED_set_serialNumber(), X509_REVOKED_set_revocationDate(),
-X509_CRL_add0_revoked() and X509_CRL_sort() return 1 for success and 0 for
-failure.
+X509_CRL_get_REVOKED() returns a STACK of revoked entries.
-X509_REVOKED_get0_serialNumber() returns an B<ASN1_INTEGER> pointer.
+X509_REVOKED_get0_serialNumber() returns an B<ASN1_INTEGER> structure.
-X509_REVOKED_get0_revocationDate() returns an B<ASN1_TIME> value.
+X509_REVOKED_get0_revocationDate() returns an B<ASN1_TIME> structure.
-X509_CRL_get_REVOKED() returns a STACK of revoked entries.
+X509_REVOKED_set_serialNumber(), X509_REVOKED_set_revocationDate(),
+X509_CRL_add0_revoked() and X509_CRL_sort() return 1 for success and 0 for
+failure.
=head1 SEE ALSO
@@ -105,9 +105,9 @@ L<X509_verify_cert(3)>
=head1 COPYRIGHT
-Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_EXTENSION_set_object.pod b/doc/man3/X509_EXTENSION_set_object.pod
index f3f0de636ef7..ff5de78ad778 100644
--- a/doc/man3/X509_EXTENSION_set_object.pod
+++ b/doc/man3/X509_EXTENSION_set_object.pod
@@ -88,7 +88,7 @@ L<X509V3_get_d2i(3)>
Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_LOOKUP.pod b/doc/man3/X509_LOOKUP.pod
index 3e0bb6ab221c..4d2fe38f25ab 100644
--- a/doc/man3/X509_LOOKUP.pod
+++ b/doc/man3/X509_LOOKUP.pod
@@ -6,9 +6,13 @@ X509_LOOKUP, X509_LOOKUP_TYPE,
X509_LOOKUP_new, X509_LOOKUP_free, X509_LOOKUP_init,
X509_LOOKUP_shutdown,
X509_LOOKUP_set_method_data, X509_LOOKUP_get_method_data,
-X509_LOOKUP_ctrl,
-X509_LOOKUP_load_file, X509_LOOKUP_add_dir,
-X509_LOOKUP_get_store, X509_LOOKUP_by_subject,
+X509_LOOKUP_ctrl_ex, X509_LOOKUP_ctrl,
+X509_LOOKUP_load_file_ex, X509_LOOKUP_load_file,
+X509_LOOKUP_add_dir,
+X509_LOOKUP_add_store_ex, X509_LOOKUP_add_store,
+X509_LOOKUP_load_store_ex, X509_LOOKUP_load_store,
+X509_LOOKUP_get_store,
+X509_LOOKUP_by_subject_ex, X509_LOOKUP_by_subject,
X509_LOOKUP_by_issuer_serial, X509_LOOKUP_by_fingerprint,
X509_LOOKUP_by_alias
- OpenSSL certificate lookup mechanisms
@@ -29,18 +33,33 @@ X509_LOOKUP_by_alias
int X509_LOOKUP_set_method_data(X509_LOOKUP *ctx, void *data);
void *X509_LOOKUP_get_method_data(const X509_LOOKUP *ctx);
+ int X509_LOOKUP_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
+ char **ret, OSSL_LIB_CTX *libctx, const char *propq);
int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
long argl, char **ret);
+ int X509_LOOKUP_load_file_ex(X509_LOOKUP *ctx, char *name, long type,
+ OSSL_LIB_CTX *libctx, const char *propq);
int X509_LOOKUP_load_file(X509_LOOKUP *ctx, char *name, long type);
+ int X509_LOOKUP_load_file_ex(X509_LOOKUP *ctx, char *name, long type,
+ OSSL_LIB_CTX *libctx, const char *propq);
int X509_LOOKUP_add_dir(X509_LOOKUP *ctx, char *name, long type);
+ int X509_LOOKUP_add_store_ex(X509_LOOKUP *ctx, char *uri, OSSL_LIB_CTX *libctx,
+ const char *propq);
+ int X509_LOOKUP_add_store(X509_LOOKUP *ctx, char *uri);
+ int X509_LOOKUP_load_store_ex(X509_LOOKUP *ctx, char *uri, OSSL_LIB_CTX *libctx,
+ const char *propq);
+ int X509_LOOKUP_load_store(X509_LOOKUP *ctx, char *uri);
X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx);
+ int X509_LOOKUP_by_subject_ex(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+ const X509_NAME *name, X509_OBJECT *ret,
+ OSSL_LIB_CTX *libctx, const char *propq);
int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
- X509_NAME *name, X509_OBJECT *ret);
+ const X509_NAME *name, X509_OBJECT *ret);
int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
- X509_NAME *name, ASN1_INTEGER *serial,
- X509_OBJECT *ret);
+ const X509_NAME *name,
+ const ASN1_INTEGER *serial, X509_OBJECT *ret);
int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
const unsigned char *bytes, int len,
X509_OBJECT *ret);
@@ -57,7 +76,7 @@ to enable lookup in that store.
X509_LOOKUP_new() creates a new B<X509_LOOKUP> using the given lookup
I<method>.
It can also be created by calling L<X509_STORE_add_lookup(3)>, which
-will associate an B<X509_STORE> with the lookup mechanism.
+will associate a B<X509_STORE> with the lookup mechanism.
X509_LOOKUP_init() initializes the internal state and resources as
needed by the given B<X509_LOOKUP> to do its work.
@@ -67,28 +86,34 @@ the given B<X509_LOOKUP>.
X509_LOOKUP_free() destructs the given B<X509_LOOKUP>.
-X509_LOOKUP_set_method_data() associates a pointer to application data
-to the given B<X509_LOOKUP>.
+X509_LOOKUP_set_method_data() and X509_LOOKUP_get_method_data()
+associates and retrieves a pointer to application data to and from the
+given B<X509_LOOKUP>, respectively.
-X509_LOOKUP_get_method_data() retrieves a pointer to application data
-from the given B<X509_LOOKUP>.
-
-X509_LOOKUP_ctrl() is used to set or get additional data to or from an
-B<X509_LOOKUP> structure or its associated L<X509_LOOKUP_METHOD(3)>.
+X509_LOOKUP_ctrl_ex() is used to set or get additional data to or from
+a B<X509_LOOKUP> structure or its associated L<X509_LOOKUP_METHOD(3)>.
The arguments of the control command are passed via I<argc> and I<argl>,
-its return value via I<*ret>.
+its return value via I<*ret>. The library context I<libctx> and property
+query I<propq> are used when fetching algorithms from providers.
The meaning of the arguments depends on the I<cmd> number of the
control command. In general, this function is not called directly, but
wrapped by a macro call, see below.
The control I<cmd>s known to OpenSSL are discussed in more depth
in L</Control Commands>.
-X509_LOOKUP_load_file() passes a filename to be loaded immediately
-into the associated B<X509_STORE>.
+X509_LOOKUP_ctrl() is similar to X509_LOOKUP_ctrl_ex() but
+uses NULL for the library context I<libctx> and property query I<propq>.
+
+X509_LOOKUP_load_file_ex() passes a filename to be loaded immediately
+into the associated B<X509_STORE>. The library context I<libctx> and property
+query I<propq> are used when fetching algorithms from providers.
I<type> indicates what type of object is expected.
This can only be used with a lookup using the implementation
L<X509_LOOKUP_file(3)>.
+X509_LOOKUP_load_file() is similar to X509_LOOKUP_load_file_ex() but
+uses NULL for the library context I<libctx> and property query I<propq>.
+
X509_LOOKUP_add_dir() passes a directory specification from which
certificates and CRLs are loaded on demand into the associated
B<X509_STORE>.
@@ -96,60 +121,50 @@ I<type> indicates what type of object is expected.
This can only be used with a lookup using the implementation
L<X509_LOOKUP_hash_dir(3)>.
-X509_LOOKUP_load_file(), X509_LOOKUP_add_dir(),
-X509_LOOKUP_add_store(), and X509_LOOKUP_load_store() are implemented
-as macros that use X509_LOOKUP_ctrl().
-
-X509_LOOKUP_by_subject(), X509_LOOKUP_by_issuer_serial(),
-X509_LOOKUP_by_fingerprint(), and X509_LOOKUP_by_alias() look up
-certificates and CRLs in the L<X509_STORE(3)> associated with the
-B<X509_LOOKUP> using different criteria, where the looked up object is
-stored in I<ret>.
+X509_LOOKUP_add_store_ex() passes a URI for a directory-like structure
+from which containers with certificates and CRLs are loaded on demand
+into the associated B<X509_STORE>. The library context I<libctx> and property
+query I<propq> are used when fetching algorithms from providers.
+
+X509_LOOKUP_add_store() is similar to X509_LOOKUP_add_store_ex() but
+uses NULL for the library context I<libctx> and property query I<propq>.
+
+X509_LOOKUP_load_store_ex() passes a URI for a single container from
+which certificates and CRLs are immediately loaded into the associated
+B<X509_STORE>. The library context I<libctx> and property query I<propq> are used
+when fetching algorithms from providers.
+These functions can only be used with a lookup using the
+implementation L<X509_LOOKUP_store(3)>.
+
+X509_LOOKUP_load_store() is similar to X509_LOOKUP_load_store_ex() but
+uses NULL for the library context I<libctx> and property query I<propq>.
+
+X509_LOOKUP_load_file_ex(), X509_LOOKUP_load_file(),
+X509_LOOKUP_add_dir(),
+X509_LOOKUP_add_store_ex() X509_LOOKUP_add_store(),
+X509_LOOKUP_load_store_ex() and X509_LOOKUP_load_store() are
+implemented as macros that use X509_LOOKUP_ctrl().
+
+X509_LOOKUP_by_subject_ex(), X509_LOOKUP_by_subject(),
+X509_LOOKUP_by_issuer_serial(), X509_LOOKUP_by_fingerprint(), and
+X509_LOOKUP_by_alias() look up certificates and CRLs in the L<X509_STORE(3)>
+associated with the B<X509_LOOKUP> using different criteria, where the looked up
+object is stored in I<ret>.
Some of the underlying B<X509_LOOKUP_METHOD>s will also cache objects
matching the criteria in the associated B<X509_STORE>, which makes it
possible to handle cases where the criteria have more than one hit.
-=head2 File Types
-
-X509_LOOKUP_load_file() and X509_LOOKUP_add_dir() take a I<type>,
-which can be one of the following:
-
-=over 4
-
-=item B<X509_FILETYPE_PEM>
-
-The file or files that are loaded are expected to be in PEM format.
-
-=item B<X509_FILETYPE_ASN1>
-
-The file or files that are loaded are expected to be in raw DER format.
-
-=item B<X509_FILETYPE_DEFAULT>
-
-The default certificate file or directory is used. In this case,
-I<name> is ignored.
-
-=begin comment
-
-TODO
-Document X509_get_default_cert_file_env(3),
-X509_get_default_cert_file(3), X509_get_default_cert_dir_env(3) and
-X509_get_default_cert_dir(3) and link to them here.
-
-=end comment
-
-=back
-
=head2 Control Commands
-The B<X509_LOOKUP_METHOD>s built into OpenSSL recognise the following
+The B<X509_LOOKUP_METHOD>s built into OpenSSL recognize the following
X509_LOOKUP_ctrl() I<cmd>s:
=over 4
=item B<X509_L_FILE_LOAD>
-This is the command that X509_LOOKUP_load_file() uses.
+This is the command that X509_LOOKUP_load_file_ex() and
+X509_LOOKUP_load_file() use.
The filename is passed in I<argc>, and the type in I<argl>.
=item B<X509_L_ADD_DIR>
@@ -160,19 +175,21 @@ I<argl>.
=item B<X509_L_ADD_STORE>
-This is the command that X509_LOOKUP_add_store() uses.
+This is the command that X509_LOOKUP_add_store_ex() and
+X509_LOOKUP_add_store() use.
The URI is passed in I<argc>.
=item B<X509_L_LOAD_STORE>
-This is the command that X509_LOOKUP_load_store() uses.
+This is the command that X509_LOOKUP_load_store_ex() and
+X509_LOOKUP_load_store() use.
The URI is passed in I<argc>.
=back
=head1 RETURN VALUES
-X509_LOOKUP_new() returns an B<X509_LOOKUP> pointer when successful,
+X509_LOOKUP_new() returns a B<X509_LOOKUP> pointer when successful,
or NULL on error.
X509_LOOKUP_init() and X509_LOOKUP_shutdown() return 1 on success, or
@@ -185,13 +202,13 @@ Otherwise, it returns what the control function in the
B<X509_LOOKUP_METHOD> returns, which is usually 1 on success and 0 in
error.
-X509_LOOKUP_get_store() returns an B<X509_STORE> pointer if there is
+X509_LOOKUP_get_store() returns a B<X509_STORE> pointer if there is
one, otherwise NULL.
-X509_LOOKUP_by_subject(), X509_LOOKUP_by_issuer_serial(),
-X509_LOOKUP_by_fingerprint(), and X509_LOOKUP_by_alias() all return 0
-if there is no B<X509_LOOKUP_METHOD> or that method doesn't implement
-the corresponding function.
+X509_LOOKUP_by_subject_ex(), X509_LOOKUP_by_subject(),
+X509_LOOKUP_by_issuer_serial(), X509_LOOKUP_by_fingerprint(), and
+X509_LOOKUP_by_alias() all return 0 if there is no B<X509_LOOKUP_METHOD> or that
+method doesn't implement the corresponding function.
Otherwise, it returns what the corresponding function in the
B<X509_LOOKUP_METHOD> returns, which is usually 1 on success and 0 in
error.
@@ -200,9 +217,18 @@ error.
L<X509_LOOKUP_METHOD(3)>, L<X509_STORE(3)>
+=head1 HISTORY
+
+The functions X509_LOOKUP_by_subject_ex() and
+X509_LOOKUP_ctrl_ex() were added in OpenSSL 3.0.
+
+The macros X509_LOOKUP_load_file_ex(),
+X509_LOOKUP_load_store_ex() and 509_LOOKUP_add_store_ex() were
+added in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
diff --git a/doc/man3/X509_LOOKUP_hash_dir.pod b/doc/man3/X509_LOOKUP_hash_dir.pod
index 365d0dea1c76..22a599692549 100644
--- a/doc/man3/X509_LOOKUP_hash_dir.pod
+++ b/doc/man3/X509_LOOKUP_hash_dir.pod
@@ -2,11 +2,11 @@
=head1 NAME
-X509_LOOKUP_hash_dir, X509_LOOKUP_file,
-X509_load_cert_file,
+X509_LOOKUP_hash_dir, X509_LOOKUP_file, X509_LOOKUP_store,
+X509_load_cert_file_ex, X509_load_cert_file,
X509_load_crl_file,
-X509_load_cert_crl_file - Default OpenSSL certificate
-lookup methods
+X509_load_cert_crl_file_ex, X509_load_cert_crl_file
+- Default OpenSSL certificate lookup methods
=head1 SYNOPSIS
@@ -14,9 +14,14 @@ lookup methods
X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void);
X509_LOOKUP_METHOD *X509_LOOKUP_file(void);
+ X509_LOOKUP_METHOD *X509_LOOKUP_store(void);
+ int X509_load_cert_file_ex(X509_LOOKUP *ctx, const char *file, int type,
+ OSSL_LIB_CTX *libctx, const char *propq);
int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type);
int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type);
+ int X509_load_cert_crl_file_ex(X509_LOOKUP *ctx, const char *file, int type,
+ OSSL_LIB_CTX *libctx, const char *propq);
int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type);
=head1 DESCRIPTION
@@ -82,10 +87,10 @@ the directory.
The directory should contain one certificate or CRL per file in PEM format,
with a filename of the form I<hash>.I<N> for a certificate, or
I<hash>.B<r>I<N> for a CRL.
-The I<hash> is the value returned by the L<X509_NAME_hash(3)> function applied
-to the subject name for certificates or issuer name for CRLs.
-The hash can also be obtained via the B<-hash> option of the L<x509(1)> or
-L<crl(1)> commands.
+The I<hash> is the value returned by the L<X509_NAME_hash_ex(3)> function
+applied to the subject name for certificates or issuer name for CRLs.
+The hash can also be obtained via the B<-hash> option of the
+L<openssl-x509(1)> or L<openssl-crl(1)> commands.
The .I<N> or .B<r>I<N> suffix is a sequence number that starts at zero, and is
incremented consecutively for each certificate or CRL with the same I<hash>
@@ -108,13 +113,27 @@ Note that the hash algorithm used for subject name hashing changed in OpenSSL
1.0.0, and all certificate stores have to be rehashed when moving from OpenSSL
0.9.8 to 1.0.0.
-OpenSSL includes a L<rehash(1)> utility which creates symlinks with correct
-hashed names for all files with .pem suffix in a given directory.
+OpenSSL includes a L<openssl-rehash(1)> utility which creates symlinks with
+hashed names for all files with F<.pem> suffix in a given directory.
+
+=head2 OSSL_STORE Method
+
+B<X509_LOOKUP_store> is a method that allows access to any store of
+certificates and CRLs through any loader supported by
+L<ossl_store(7)>.
+It works with the help of URIs, which can be direct references to
+certificates or CRLs, but can also be references to catalogues of such
+objects (that behave like directories).
+
+This method overlaps the L</File Method> and L</Hashed Directory Method>
+because of the 'file:' scheme loader.
+It does no caching of its own, but can use a caching L<ossl_store(7)>
+loader, and therefore depends on the loader's capability.
=head1 RETURN VALUES
-X509_LOOKUP_hash_dir() and X509_LOOKUP_file() always return a valid
-B<X509_LOOKUP_METHOD> structure.
+X509_LOOKUP_hash_dir(), X509_LOOKUP_file() and X509_LOOKUP_store()
+always return a valid B<X509_LOOKUP_METHOD> structure.
X509_load_cert_file(), X509_load_crl_file() and X509_load_cert_crl_file() return
the number of loaded objects or 0 on error.
@@ -123,15 +142,21 @@ the number of loaded objects or 0 on error.
L<PEM_read_PrivateKey(3)>,
L<X509_STORE_load_locations(3)>,
-L<X509_store_add_lookup(3)>,
L<SSL_CTX_load_verify_locations(3)>,
L<X509_LOOKUP_meth_new(3)>,
+L<ossl_store(7)>
+
+=head1 HISTORY
+
+The functions X509_load_cert_file_ex(),
+X509_load_cert_crl_file_ex() and X509_LOOKUP_store() were added in
+OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_LOOKUP_meth_new.pod b/doc/man3/X509_LOOKUP_meth_new.pod
index ad581d4b421e..202174993563 100644
--- a/doc/man3/X509_LOOKUP_meth_new.pod
+++ b/doc/man3/X509_LOOKUP_meth_new.pod
@@ -57,7 +57,7 @@ X509_OBJECT_set1_X509, X509_OBJECT_set1_X509_CRL
typedef int (*X509_LOOKUP_get_by_subject_fn)(X509_LOOKUP *ctx,
X509_LOOKUP_TYPE type,
- X509_NAME *name,
+ const X509_NAME *name,
X509_OBJECT *ret);
int X509_LOOKUP_meth_set_get_by_subject(X509_LOOKUP_METHOD *method,
X509_LOOKUP_get_by_subject_fn fn);
@@ -66,8 +66,8 @@ X509_OBJECT_set1_X509, X509_OBJECT_set1_X509_CRL
typedef int (*X509_LOOKUP_get_by_issuer_serial_fn)(X509_LOOKUP *ctx,
X509_LOOKUP_TYPE type,
- X509_NAME *name,
- ASN1_INTEGER *serial,
+ const X509_NAME *name,
+ const ASN1_INTEGER *serial,
X509_OBJECT *ret);
int X509_LOOKUP_meth_set_get_by_issuer_serial(
X509_LOOKUP_METHOD *method, X509_LOOKUP_get_by_issuer_serial_fn fn);
@@ -188,7 +188,7 @@ The functions described here were added in OpenSSL 1.1.0i.
Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_NAME_ENTRY_get_object.pod b/doc/man3/X509_NAME_ENTRY_get_object.pod
index 74f1a96d07ef..7533a586b13d 100644
--- a/doc/man3/X509_NAME_ENTRY_get_object.pod
+++ b/doc/man3/X509_NAME_ENTRY_get_object.pod
@@ -88,7 +88,7 @@ L<OBJ_nid2obj(3)>
Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_NAME_add_entry_by_txt.pod b/doc/man3/X509_NAME_add_entry_by_txt.pod
index 0459cf4a4655..8b17a016de47 100644
--- a/doc/man3/X509_NAME_add_entry_by_txt.pod
+++ b/doc/man3/X509_NAME_add_entry_by_txt.pod
@@ -66,13 +66,13 @@ RelativeDistinguishedName (RDN).
B<loc> actually determines the index where the new entry is inserted:
if it is -1 it is appended.
-B<set> determines how the new type is added. If it is zero a
-new RDN is created.
+B<set> determines how the new type is added.
+If it is zero a new RDN is created.
-If B<set> is -1 or 1 it is added to the previous or next RDN
-structure respectively. This will then be a multivalued RDN:
-since multivalues RDNs are very seldom used B<set> is almost
-always set to zero.
+If B<set> is -1 or 1 it is added as a new set member
+to the previous or next RDN structure, respectively.
+This will then become part of a multi-valued RDN (containing a set of AVAs).
+Since multi-valued RDNs are very rarely used B<set> typically will be zero.
=head1 RETURN VALUES
@@ -81,7 +81,7 @@ X509_NAME_add_entry_by_NID() and X509_NAME_add_entry() return 1 for
success of 0 if an error occurred.
X509_NAME_delete_entry() returns either the deleted B<X509_NAME_ENTRY>
-structure of B<NULL> if an error occurred.
+structure or B<NULL> if an error occurred.
=head1 EXAMPLES
@@ -117,9 +117,9 @@ L<ERR_get_error(3)>, L<d2i_X509_NAME(3)>
=head1 COPYRIGHT
-Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_NAME_get0_der.pod b/doc/man3/X509_NAME_get0_der.pod
index f91fd4d97778..78ed9920a08b 100644
--- a/doc/man3/X509_NAME_get0_der.pod
+++ b/doc/man3/X509_NAME_get0_der.pod
@@ -8,8 +8,8 @@ X509_NAME_get0_der - get X509_NAME DER encoding
#include <openssl/x509.h>
- int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder,
- size_t *pderlen)
+ int X509_NAME_get0_der(const X509_NAME *nm, const unsigned char **pder,
+ size_t *pderlen);
=head1 DESCRIPTION
@@ -30,9 +30,9 @@ L<d2i_X509(3)>
=head1 COPYRIGHT
-Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_NAME_get_index_by_NID.pod b/doc/man3/X509_NAME_get_index_by_NID.pod
index 420ace134874..805c5fc519fa 100644
--- a/doc/man3/X509_NAME_get_index_by_NID.pod
+++ b/doc/man3/X509_NAME_get_index_by_NID.pod
@@ -10,14 +10,17 @@ X509_NAME lookup and enumeration functions
#include <openssl/x509.h>
- int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos);
- int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int lastpos);
+ int X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, int lastpos);
+ int X509_NAME_get_index_by_OBJ(const X509_NAME *name,
+ const ASN1_OBJECT *obj, int lastpos);
int X509_NAME_entry_count(const X509_NAME *name);
X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc);
- int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len);
- int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, char *buf, int len);
+ int X509_NAME_get_text_by_NID(const X509_NAME *name, int nid,
+ char *buf, int len);
+ int X509_NAME_get_text_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj,
+ char *buf, int len);
=head1 DESCRIPTION
@@ -62,8 +65,8 @@ X509_NAME_get_entry() on any matching indices and then the
various B<X509_NAME_ENTRY> utility functions on the result.
The list of all relevant B<NID_*> and B<OBJ_* codes> can be found in
-the source code header files E<lt>openssl/obj_mac.hE<gt> and/or
-E<lt>openssl/objects.hE<gt>.
+the source code header files F<< <openssl/obj_mac.h> >> and/or
+F<< <openssl/objects.h> >>.
Applications which could pass invalid NIDs to X509_NAME_get_index_by_NID()
should check for the return value of -2. Alternatively the NID validity
@@ -76,7 +79,8 @@ return the index of the next matching entry or -1 if not found.
X509_NAME_get_index_by_NID() can also return -2 if the supplied
NID is invalid.
-X509_NAME_entry_count() returns the total number of entries.
+X509_NAME_entry_count() returns the total number of entries, and 0
+for failure.
X509_NAME_get_entry() returns an B<X509_NAME> pointer to the
requested entry or B<NULL> if the index is invalid.
@@ -112,9 +116,9 @@ L<ERR_get_error(3)>, L<d2i_X509_NAME(3)>
=head1 COPYRIGHT
-Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_NAME_print_ex.pod b/doc/man3/X509_NAME_print_ex.pod
index 96be1ac8ff34..e43bb191f523 100644
--- a/doc/man3/X509_NAME_print_ex.pod
+++ b/doc/man3/X509_NAME_print_ex.pod
@@ -9,34 +9,37 @@ X509_NAME_oneline - X509_NAME printing routines
#include <openssl/x509.h>
- int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent, unsigned long flags);
- int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent, unsigned long flags);
+ int X509_NAME_print_ex(BIO *out, const X509_NAME *nm,
+ int indent, unsigned long flags);
+ int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm,
+ int indent, unsigned long flags);
char *X509_NAME_oneline(const X509_NAME *a, char *buf, int size);
int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase);
=head1 DESCRIPTION
-X509_NAME_print_ex() prints a human readable version of B<nm> to BIO B<out>. Each
-line (for multiline formats) is indented by B<indent> spaces. The output format
-can be extensively customised by use of the B<flags> parameter.
+X509_NAME_print_ex() prints a human readable version of I<nm> to BIO I<out>.
+Each line (for multiline formats) is indented by I<indent> spaces. The
+output format can be extensively customised by use of the I<flags> parameter.
-X509_NAME_print_ex_fp() is identical to X509_NAME_print_ex() except the output is
-written to FILE pointer B<fp>.
+X509_NAME_print_ex_fp() is identical to X509_NAME_print_ex()
+except the output is written to FILE pointer I<fp>.
-X509_NAME_oneline() prints an ASCII version of B<a> to B<buf>.
-If B<buf> is B<NULL> then a buffer is dynamically allocated and returned, and
-B<size> is ignored.
-Otherwise, at most B<size> bytes will be written, including the ending '\0',
-and B<buf> is returned.
+X509_NAME_oneline() prints an ASCII version of I<a> to I<buf>.
+This supports multi-valued RDNs and escapes B</> and B<+> characters in values.
+If I<buf> is B<NULL> then a buffer is dynamically allocated and returned, and
+I<size> is ignored.
+Otherwise, at most I<size> bytes will be written, including the ending '\0',
+and I<buf> is returned.
-X509_NAME_print() prints out B<name> to B<bp> indenting each line by B<obase>
+X509_NAME_print() prints out I<name> to I<bp> indenting each line by I<obase>
characters. Multiple lines are used if the output (including indent) exceeds
80 characters.
=head1 NOTES
The functions X509_NAME_oneline() and X509_NAME_print()
-produce a non standard output form, they don't handle multi character fields and
+produce a non standard output form, they don't handle multi-character fields and
have various quirks and inconsistencies.
Their use is strongly discouraged in new applications and they could
be deprecated in a future release.
@@ -52,15 +55,18 @@ The complete set of the flags supported by X509_NAME_print_ex() is listed below.
Several options can be ored together.
The options B<XN_FLAG_SEP_COMMA_PLUS>, B<XN_FLAG_SEP_CPLUS_SPC>,
-B<XN_FLAG_SEP_SPLUS_SPC> and B<XN_FLAG_SEP_MULTILINE> determine the field separators
-to use. Two distinct separators are used between distinct RelativeDistinguishedName
-components and separate values in the same RDN for a multi-valued RDN. Multi-valued
-RDNs are currently very rare so the second separator will hardly ever be used.
-
-B<XN_FLAG_SEP_COMMA_PLUS> uses comma and plus as separators. B<XN_FLAG_SEP_CPLUS_SPC>
-uses comma and plus with spaces: this is more readable that plain comma and plus.
-B<XN_FLAG_SEP_SPLUS_SPC> uses spaced semicolon and plus. B<XN_FLAG_SEP_MULTILINE> uses
-spaced newline and plus respectively.
+B<XN_FLAG_SEP_SPLUS_SPC> and B<XN_FLAG_SEP_MULTILINE>
+determine the field separators to use.
+Two distinct separators are used between distinct RelativeDistinguishedName
+components and separate values in the same RDN for a multi-valued RDN.
+Multi-valued RDNs are currently very rare
+so the second separator will hardly ever be used.
+
+B<XN_FLAG_SEP_COMMA_PLUS> uses comma and plus as separators.
+B<XN_FLAG_SEP_CPLUS_SPC> uses comma and plus with spaces:
+this is more readable that plain comma and plus.
+B<XN_FLAG_SEP_SPLUS_SPC> uses spaced semicolon and plus.
+B<XN_FLAG_SEP_MULTILINE> uses spaced newline and plus respectively.
If B<XN_FLAG_DN_REV> is set the whole DN is printed in reversed order.
@@ -84,18 +90,21 @@ control how each field value is displayed.
In addition a number options can be set for commonly used formats.
-B<XN_FLAG_RFC2253> sets options which produce an output compatible with RFC2253 it
-is equivalent to:
- B<ASN1_STRFLGS_RFC2253 | XN_FLAG_SEP_COMMA_PLUS | XN_FLAG_DN_REV | XN_FLAG_FN_SN | XN_FLAG_DUMP_UNKNOWN_FIELDS>
-
+B<XN_FLAG_RFC2253> sets options which produce an output compatible with RFC2253.
+It is equivalent to:
+ C<ASN1_STRFLGS_RFC2253 | XN_FLAG_SEP_COMMA_PLUS | XN_FLAG_DN_REV
+ | XN_FLAG_FN_SN | XN_FLAG_DUMP_UNKNOWN_FIELDS>
B<XN_FLAG_ONELINE> is a more readable one line format which is the same as:
- B<ASN1_STRFLGS_RFC2253 | ASN1_STRFLGS_ESC_QUOTE | XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_SPC_EQ | XN_FLAG_FN_SN>
+ C<ASN1_STRFLGS_RFC2253 | ASN1_STRFLGS_ESC_QUOTE | XN_FLAG_SEP_CPLUS_SPC
+ | XN_FLAG_SPC_EQ | XN_FLAG_FN_SN>
B<XN_FLAG_MULTILINE> is a multiline format which is the same as:
- B<ASN1_STRFLGS_ESC_CTRL | ASN1_STRFLGS_ESC_MSB | XN_FLAG_SEP_MULTILINE | XN_FLAG_SPC_EQ | XN_FLAG_FN_LN | XN_FLAG_FN_ALIGN>
+ C<ASN1_STRFLGS_ESC_CTRL | ASN1_STRFLGS_ESC_MSB | XN_FLAG_SEP_MULTILINE
+ | XN_FLAG_SPC_EQ | XN_FLAG_FN_LN | XN_FLAG_FN_ALIGN>
-B<XN_FLAG_COMPAT> uses a format identical to X509_NAME_print(): in fact it calls X509_NAME_print() internally.
+B<XN_FLAG_COMPAT> uses a format identical to X509_NAME_print():
+in fact it calls X509_NAME_print() internally.
=head1 RETURN VALUES
@@ -103,9 +112,9 @@ X509_NAME_oneline() returns a valid string on success or NULL on error.
X509_NAME_print() returns 1 on success or 0 on error.
-X509_NAME_print_ex() and X509_NAME_print_ex_fp() return 1 on success or 0 on error
-if the B<XN_FLAG_COMPAT> is set, which is the same as X509_NAME_print(). Otherwise,
-it returns -1 on error or other values on success.
+X509_NAME_print_ex() and X509_NAME_print_ex_fp() return 1 on success or 0 on
+error if the B<XN_FLAG_COMPAT> is set, which is the same as X509_NAME_print().
+Otherwise, it returns -1 on error or other values on success.
=head1 SEE ALSO
@@ -113,9 +122,9 @@ L<ASN1_STRING_print_ex(3)>
=head1 COPYRIGHT
-Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_PUBKEY_new.pod b/doc/man3/X509_PUBKEY_new.pod
index b13310513b17..3d22857b80b7 100644
--- a/doc/man3/X509_PUBKEY_new.pod
+++ b/doc/man3/X509_PUBKEY_new.pod
@@ -2,83 +2,107 @@
=head1 NAME
-X509_PUBKEY_new, X509_PUBKEY_free, X509_PUBKEY_set, X509_PUBKEY_get0,
-X509_PUBKEY_get, d2i_PUBKEY, i2d_PUBKEY, d2i_PUBKEY_bio, d2i_PUBKEY_fp,
-i2d_PUBKEY_fp, i2d_PUBKEY_bio, X509_PUBKEY_set0_param,
-X509_PUBKEY_get0_param - SubjectPublicKeyInfo public key functions
+X509_PUBKEY_new_ex, X509_PUBKEY_new, X509_PUBKEY_free, X509_PUBKEY_dup,
+X509_PUBKEY_set, X509_PUBKEY_get0, X509_PUBKEY_get,
+d2i_PUBKEY_ex, d2i_PUBKEY, i2d_PUBKEY, d2i_PUBKEY_bio, d2i_PUBKEY_fp,
+i2d_PUBKEY_fp, i2d_PUBKEY_bio, X509_PUBKEY_set0_param, X509_PUBKEY_get0_param,
+X509_PUBKEY_eq - SubjectPublicKeyInfo public key functions
=head1 SYNOPSIS
#include <openssl/x509.h>
+ X509_PUBKEY *X509_PUBKEY_new_ex(OSSL_LIB_CTX *libctx, const char *propq);
X509_PUBKEY *X509_PUBKEY_new(void);
void X509_PUBKEY_free(X509_PUBKEY *a);
+ X509_PUBKEY *X509_PUBKEY_dup(const X509_PUBKEY *a);
int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey);
- EVP_PKEY *X509_PUBKEY_get0(X509_PUBKEY *key);
- EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key);
+ EVP_PKEY *X509_PUBKEY_get0(const X509_PUBKEY *key);
+ EVP_PKEY *X509_PUBKEY_get(const X509_PUBKEY *key);
+ EVP_PKEY *d2i_PUBKEY_ex(EVP_PKEY **a, const unsigned char **pp, long length,
+ OSSL_LIB_CTX *libctx, const char *propq);
EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length);
- int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp);
+ int i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp);
EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a);
EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a);
- int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey);
- int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey);
+ int i2d_PUBKEY_fp(const FILE *fp, EVP_PKEY *pkey);
+ int i2d_PUBKEY_bio(BIO *bp, const EVP_PKEY *pkey);
int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj,
int ptype, void *pval,
unsigned char *penc, int penclen);
int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg,
const unsigned char **pk, int *ppklen,
- X509_ALGOR **pa, X509_PUBKEY *pub);
+ X509_ALGOR **pa, const X509_PUBKEY *pub);
+ int X509_PUBKEY_eq(X509_PUBKEY *a, X509_PUBKEY *b);
=head1 DESCRIPTION
The B<X509_PUBKEY> structure represents the ASN.1 B<SubjectPublicKeyInfo>
structure defined in RFC5280 and used in certificates and certificate requests.
-X509_PUBKEY_new() allocates and initializes an B<X509_PUBKEY> structure.
+X509_PUBKEY_new_ex() allocates and initializes an B<X509_PUBKEY> structure
+associated with the given B<OSSL_LIB_CTX> in the I<libctx> parameter. Any
+algorithm fetches associated with using the B<X509_PUBKEY> object will use
+the property query string I<propq>. See L<crypto(7)/ALGORITHM FETCHING> for
+further information about algorithm fetching.
-X509_PUBKEY_free() frees up B<X509_PUBKEY> structure B<a>. If B<a> is NULL
+X509_PUBKEY_new() is the same as X509_PUBKEY_new_ex() except that the default
+(NULL) B<OSSL_LIB_CTX> and a NULL property query string are used.
+
+X509_PUBKEY_dup() creates a duplicate copy of the B<X509_PUBKEY> object
+specified by I<a>.
+
+X509_PUBKEY_free() frees up B<X509_PUBKEY> structure I<a>. If I<a> is NULL
nothing is done.
-X509_PUBKEY_set() sets the public key in B<*x> to the public key contained
-in the B<EVP_PKEY> structure B<pkey>. If B<*x> is not NULL any existing
+X509_PUBKEY_set() sets the public key in I<*x> to the public key contained
+in the B<EVP_PKEY> structure I<pkey>. If I<*x> is not NULL any existing
public key structure will be freed.
-X509_PUBKEY_get0() returns the public key contained in B<key>. The returned
+X509_PUBKEY_get0() returns the public key contained in I<key>. The returned
value is an internal pointer which B<MUST NOT> be freed after use.
X509_PUBKEY_get() is similar to X509_PUBKEY_get0() except the reference
count on the returned key is incremented so it B<MUST> be freed using
EVP_PKEY_free() after use.
-d2i_PUBKEY() and i2d_PUBKEY() decode and encode an B<EVP_PKEY> structure
-using B<SubjectPublicKeyInfo> format. They otherwise follow the conventions of
-other ASN.1 functions such as d2i_X509().
+d2i_PUBKEY_ex() decodes an B<EVP_PKEY> structure using B<SubjectPublicKeyInfo>
+format. Some public key decoding implementations may use cryptographic
+algorithms. In this case the supplied library context I<libctx> and property
+query string I<propq> are used.
+d2i_PUBKEY() does the same as d2i_PUBKEY_ex() except that the default
+library context and property query string are used.
+
+i2d_PUBKEY() encodes an B<EVP_PKEY> structure using B<SubjectPublicKeyInfo>
+format.
d2i_PUBKEY_bio(), d2i_PUBKEY_fp(), i2d_PUBKEY_bio() and i2d_PUBKEY_fp() are
similar to d2i_PUBKEY() and i2d_PUBKEY() except they decode or encode using a
B<BIO> or B<FILE> pointer.
-X509_PUBKEY_set0_param() sets the public key parameters of B<pub>. The
-OID associated with the algorithm is set to B<aobj>. The type of the
-algorithm parameters is set to B<type> using the structure B<pval>.
-The encoding of the public key itself is set to the B<penclen>
-bytes contained in buffer B<penc>. On success ownership of all the supplied
-parameters is passed to B<pub> so they must not be freed after the
+X509_PUBKEY_set0_param() sets the public key parameters of I<pub>. The
+OID associated with the algorithm is set to I<aobj>. The type of the
+algorithm parameters is set to I<type> using the structure I<pval>.
+The encoding of the public key itself is set to the I<penclen>
+bytes contained in buffer I<penc>. On success ownership of all the supplied
+parameters is passed to I<pub> so they must not be freed after the
call.
-X509_PUBKEY_get0_param() retrieves the public key parameters from B<pub>,
-B<*ppkalg> is set to the associated OID and the encoding consists of
-B<*ppklen> bytes at B<*pk>, B<*pa> is set to the associated
+X509_PUBKEY_get0_param() retrieves the public key parameters from I<pub>,
+I<*ppkalg> is set to the associated OID and the encoding consists of
+I<*ppklen> bytes at I<*pk>, I<*pa> is set to the associated
AlgorithmIdentifier for the public key. If the value of any of these
-parameters is not required it can be set to B<NULL>. All of the
+parameters is not required it can be set to NULL. All of the
retrieved pointers are internal and must not be freed after the
call.
+X509_PUBKEY_eq() compares two B<X509_PUBKEY> values.
+
=head1 NOTES
The B<X509_PUBKEY> functions can be used to encode and decode public keys
@@ -89,30 +113,36 @@ directly: they will instead call wrapper functions such as X509_get0_pubkey().
=head1 RETURN VALUES
-If the allocation fails, X509_PUBKEY_new() returns B<NULL> and sets an error
-code that can be obtained by L<ERR_get_error(3)>.
-
-Otherwise it returns a pointer to the newly allocated structure.
+If the allocation fails, X509_PUBKEY_new() and X509_PUBKEY_dup() return
+NULL and set an error code that can be obtained by L<ERR_get_error(3)>.
+Otherwise they return a pointer to the newly allocated structure.
X509_PUBKEY_free() does not return a value.
X509_PUBKEY_get0() and X509_PUBKEY_get() return a pointer to an B<EVP_PKEY>
-structure or B<NULL> if an error occurs.
+structure or NULL if an error occurs.
X509_PUBKEY_set(), X509_PUBKEY_set0_param() and X509_PUBKEY_get0_param()
return 1 for success and 0 if an error occurred.
+X509_PUBKEY_eq() returns 1 for equal, 0 for different, and < 0 on error.
+
=head1 SEE ALSO
L<d2i_X509(3)>,
L<ERR_get_error(3)>,
L<X509_get_pubkey(3)>,
+=head1 HISTORY
+
+The X509_PUBKEY_new_ex() and X509_PUBKEY_eq() functions were added in OpenSSL
+3.0.
+
=head1 COPYRIGHT
-Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_SIG_get0.pod b/doc/man3/X509_SIG_get0.pod
index bbf37230fc70..44c6166ffee4 100644
--- a/doc/man3/X509_SIG_get0.pod
+++ b/doc/man3/X509_SIG_get0.pod
@@ -11,7 +11,7 @@ X509_SIG_get0, X509_SIG_getm - DigestInfo functions
void X509_SIG_get0(const X509_SIG *sig, const X509_ALGOR **palg,
const ASN1_OCTET_STRING **pdigest);
void X509_SIG_getm(X509_SIG *sig, X509_ALGOR **palg,
- ASN1_OCTET_STRING **pdigest,
+ ASN1_OCTET_STRING **pdigest);
=head1 DESCRIPTION
@@ -30,9 +30,9 @@ L<d2i_X509(3)>
=head1 COPYRIGHT
-Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_STORE_CTX_get_error.pod b/doc/man3/X509_STORE_CTX_get_error.pod
index 74a28c07aa53..d0036b38b6a6 100644
--- a/doc/man3/X509_STORE_CTX_get_error.pod
+++ b/doc/man3/X509_STORE_CTX_get_error.pod
@@ -13,43 +13,48 @@ information
#include <openssl/x509.h>
- int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx);
+ int X509_STORE_CTX_get_error(const X509_STORE_CTX *ctx);
void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s);
- int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx);
+ int X509_STORE_CTX_get_error_depth(const X509_STORE_CTX *ctx);
void X509_STORE_CTX_set_error_depth(X509_STORE_CTX *ctx, int depth);
- X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx);
+ X509 *X509_STORE_CTX_get_current_cert(const X509_STORE_CTX *ctx);
void X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x);
- X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx);
+ X509 *X509_STORE_CTX_get0_cert(const X509_STORE_CTX *ctx);
- STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx);
+ STACK_OF(X509) *X509_STORE_CTX_get1_chain(const X509_STORE_CTX *ctx);
const char *X509_verify_cert_error_string(long n);
=head1 DESCRIPTION
-These functions are typically called after X509_verify_cert() has indicated
+These functions are typically called after certificate or chain verification
+using L<X509_verify_cert(3)> or L<X509_STORE_CTX_verify(3)> has indicated
an error or in a verification callback to determine the nature of an error.
-X509_STORE_CTX_get_error() returns the error code of B<ctx>, see
-the B<ERROR CODES> section for a full description of all error codes.
+X509_STORE_CTX_get_error() returns the error code of I<ctx>.
+See the L</ERROR CODES> section for a full description of all error codes.
+It may return a code != X509_V_OK even if X509_verify_cert() did not indicate
+an error, likely because a verification callback function has waived the error.
-X509_STORE_CTX_set_error() sets the error code of B<ctx> to B<s>. For example
+X509_STORE_CTX_set_error() sets the error code of I<ctx> to I<s>. For example
it might be used in a verification callback to set an error based on additional
checks.
-X509_STORE_CTX_get_error_depth() returns the B<depth> of the error. This is a
+X509_STORE_CTX_get_error_depth() returns the I<depth> of the error. This is a
nonnegative integer representing where in the certificate chain the error
occurred. If it is zero it occurred in the end entity certificate, one if
it is the certificate which signed the end entity certificate and so on.
-X509_STORE_CTX_set_error_depth() sets the error B<depth>.
+X509_STORE_CTX_set_error_depth() sets the error I<depth>.
This can be used in combination with X509_STORE_CTX_set_error() to set the
depth at which an error condition was detected.
-X509_STORE_CTX_get_current_cert() returns the certificate in B<ctx> which
-caused the error or B<NULL> if no certificate is relevant.
+X509_STORE_CTX_get_current_cert() returns the current certificate in
+I<ctx>. If an error occurred, the current certificate will be the one
+that is most closely related to the error, or possibly NULL if no such
+certificate is relevant.
-X509_STORE_CTX_set_current_cert() sets the certificate B<x> in B<ctx> which
+X509_STORE_CTX_set_current_cert() sets the certificate I<x> in I<ctx> which
caused the error.
This value is not intended to remain valid for very long, and remains owned by
the caller.
@@ -62,18 +67,17 @@ Once such a I<saved> certificate is no longer needed it can be freed with
L<X509_free(3)>.
X509_STORE_CTX_get0_cert() retrieves an internal pointer to the
-certificate being verified by the B<ctx>.
+certificate being verified by the I<ctx>.
X509_STORE_CTX_get1_chain() returns a complete validate chain if a previous
-call to X509_verify_cert() is successful. If the call to X509_verify_cert()
-is B<not> successful the returned chain may be incomplete or invalid. The
-returned chain persists after the B<ctx> structure is freed, when it is
-no longer needed it should be free up using:
+verification is successful. Otherwise the returned chain may be incomplete or
+invalid. The returned chain persists after the I<ctx> structure is freed.
+When it is no longer needed it should be free up using:
sk_X509_pop_free(chain, X509_free);
X509_verify_cert_error_string() returns a human readable error string for
-verification error B<n>.
+verification error I<n>.
=head1 RETURN VALUES
@@ -82,10 +86,10 @@ X509_STORE_CTX_get_error() returns B<X509_V_OK> or an error code.
X509_STORE_CTX_get_error_depth() returns a nonnegative error depth.
X509_STORE_CTX_get_current_cert() returns the certificate which caused the
-error or B<NULL> if no certificate is relevant to the error.
+error or NULL if no certificate is relevant to the error.
X509_verify_cert_error_string() returns a human readable error string for
-verification error B<n>.
+verification error I<n>.
=head1 ERROR CODES
@@ -97,161 +101,179 @@ error codes are defined but currently never returned: these are described as
=item B<X509_V_OK: ok>
-the operation was successful.
+The operation was successful.
+
+=item B<X509_V_ERR_UNSPECIFIED: unspecified certificate verification error>
+
+Unspecified error; should not happen.
=item B<X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: unable to get issuer certificate>
-the issuer certificate of a locally looked up certificate could not be found.
+The issuer certificate of a locally looked up certificate could not be found.
This normally means the list of trusted certificates is not complete.
+To allow any certificate (not only a self-signed one) in the trust store
+to terminate the chain the B<X509_V_FLAG_PARTIAL_CHAIN> flag may be set.
=item B<X509_V_ERR_UNABLE_TO_GET_CRL: unable to get certificate CRL>
-the CRL of a certificate could not be found.
+The CRL of a certificate could not be found.
-=item B<X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: unable to decrypt certificate's signature>
+=item B<X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
+unable to decrypt certificate's signature>
-the certificate signature could not be decrypted. This means that the actual
+The certificate signature could not be decrypted. This means that the actual
signature value could not be determined rather than it not matching the
expected value, this is only meaningful for RSA keys.
-=item B<X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: unable to decrypt CRL's signature>
+=item B<X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
+unable to decrypt CRL's signature>
-the CRL signature could not be decrypted: this means that the actual signature
+The CRL signature could not be decrypted: this means that the actual signature
value could not be determined rather than it not matching the expected value.
Unused.
-=item B<X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: unable to decode issuer public key>
+=item B<X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
+unable to decode issuer public key>
-the public key in the certificate SubjectPublicKeyInfo could not be read.
+The public key in the certificate C<SubjectPublicKeyInfo> field could
+not be read.
=item B<X509_V_ERR_CERT_SIGNATURE_FAILURE: certificate signature failure>
-the signature of the certificate is invalid.
+The signature of the certificate is invalid.
=item B<X509_V_ERR_CRL_SIGNATURE_FAILURE: CRL signature failure>
-the signature of the certificate is invalid.
+The signature of the CRL is invalid.
=item B<X509_V_ERR_CERT_NOT_YET_VALID: certificate is not yet valid>
-the certificate is not yet valid: the notBefore date is after the current time.
+The certificate is not yet valid: the C<notBefore> date is after the
+current time.
=item B<X509_V_ERR_CERT_HAS_EXPIRED: certificate has expired>
-the certificate has expired: that is the notAfter date is before the current time.
+The certificate has expired: that is the C<notAfter> date is before the
+current time.
=item B<X509_V_ERR_CRL_NOT_YET_VALID: CRL is not yet valid>
-the CRL is not yet valid.
+The CRL is not yet valid.
=item B<X509_V_ERR_CRL_HAS_EXPIRED: CRL has expired>
-the CRL has expired.
+The CRL has expired.
-=item B<X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: format error in certificate's notBefore field>
+=item B<X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+format error in certificate's notBefore field>
-the certificate notBefore field contains an invalid time.
+The certificate C<notBefore> field contains an invalid time.
-=item B<X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: format error in certificate's notAfter field>
+=item B<X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+format error in certificate's notAfter field>
-the certificate notAfter field contains an invalid time.
+The certificate C<notAfter> field contains an invalid time.
-=item B<X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: format error in CRL's lastUpdate field>
+=item B<X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
+format error in CRL's lastUpdate field>
-the CRL lastUpdate field contains an invalid time.
+The CRL B<lastUpdate> field contains an invalid time.
-=item B<X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: format error in CRL's nextUpdate field>
+=item B<X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
+format error in CRL's nextUpdate field>
-the CRL nextUpdate field contains an invalid time.
+The CRL C<nextUpdate> field contains an invalid time.
=item B<X509_V_ERR_OUT_OF_MEM: out of memory>
-an error occurred trying to allocate memory. This should never happen.
+An error occurred trying to allocate memory.
-=item B<X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: self signed certificate>
+=item B<X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: self-signed certificate>
-the passed certificate is self signed and the same certificate cannot be found
+The passed certificate is self-signed and the same certificate cannot be found
in the list of trusted certificates.
-=item B<X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: self signed certificate in certificate chain>
+=item B<X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+self-signed certificate in certificate chain>
-the certificate chain could be built up using the untrusted certificates but
-the root could not be found locally.
+The certificate chain could be built up using the untrusted certificates
+but no suitable trust anchor (which typically is a self-signed root certificate)
+could be found in the trust store.
-=item B<X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: unable to get local issuer certificate>
+=item B<X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+unable to get local issuer certificate>
-the issuer certificate could not be found: this occurs if the issuer certificate
+The issuer certificate could not be found: this occurs if the issuer certificate
of an untrusted certificate cannot be found.
-=item B<X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: unable to verify the first certificate>
+=item B<X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
+unable to verify the first certificate>
-no signatures could be verified because the chain contains only one certificate
-and it is not self signed.
+No signatures could be verified because the chain contains only one certificate
+and it is not self-signed and the B<X509_V_FLAG_PARTIAL_CHAIN> flag is not set.
=item B<X509_V_ERR_CERT_CHAIN_TOO_LONG: certificate chain too long>
-the certificate chain length is greater than the supplied maximum depth. Unused.
+The certificate chain length is greater than the supplied maximum depth.
=item B<X509_V_ERR_CERT_REVOKED: certificate revoked>
-the certificate has been revoked.
+The certificate has been revoked.
=item B<X509_V_ERR_INVALID_CA: invalid CA certificate>
-a CA certificate is invalid. Either it is not a CA or its extensions are not
+A CA certificate is invalid. Either it is not a CA or its extensions are not
consistent with the supplied purpose.
=item B<X509_V_ERR_PATH_LENGTH_EXCEEDED: path length constraint exceeded>
-the basicConstraints path-length parameter has been exceeded.
+The basicConstraints path-length parameter has been exceeded.
-=item B<X509_V_ERR_INVALID_PURPOSE: unsupported certificate purpose>
+=item B<X509_V_ERR_INVALID_PURPOSE: unsuitable certificate purpose>
-the supplied certificate cannot be used for the specified purpose.
+The target certificate cannot be used for the specified purpose.
=item B<X509_V_ERR_CERT_UNTRUSTED: certificate not trusted>
-the root CA is not marked as trusted for the specified purpose.
+The root CA is not marked as trusted for the specified purpose.
=item B<X509_V_ERR_CERT_REJECTED: certificate rejected>
-the root CA is marked to reject the specified purpose.
+The root CA is marked to reject the specified purpose.
=item B<X509_V_ERR_SUBJECT_ISSUER_MISMATCH: subject issuer mismatch>
-the current candidate issuer certificate was rejected because its subject name
-did not match the issuer name of the current certificate. This is only set
-if issuer check debugging is enabled it is used for status notification and
-is B<not> in itself an error.
+The current candidate issuer certificate was rejected because its subject name
+did not match the issuer name of the current certificate.
-=item B<X509_V_ERR_AKID_SKID_MISMATCH: authority and subject key identifier mismatch>
+=item B<X509_V_ERR_AKID_SKID_MISMATCH:
+authority and subject key identifier mismatch>
-the current candidate issuer certificate was rejected because its subject key
+The current candidate issuer certificate was rejected because its subject key
identifier was present and did not match the authority key identifier current
-certificate. This is only set if issuer check debugging is enabled it is used
-for status notification and is B<not> in itself an error.
+certificate.
-=item B<X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: authority and issuer serial number mismatch>
+=item B<X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
+authority and issuer serial number mismatch>
-the current candidate issuer certificate was rejected because its issuer name
+The current candidate issuer certificate was rejected because its issuer name
and serial number was present and did not match the authority key identifier of
-the current certificate. This is only set if issuer check debugging is enabled
-it is used for status notification and is B<not> in itself an error.
+the current certificate.
-=item B<X509_V_ERR_KEYUSAGE_NO_CERTSIGN:key usage does not include certificate signing>
+=item B<X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
+key usage does not include certificate signing>
-the current candidate issuer certificate was rejected because its keyUsage
-extension does not permit certificate signing. This is only set if issuer check
-debugging is enabled it is used for status notification and is B<not> in itself
-an error.
+The current candidate issuer certificate was rejected because its C<keyUsage>
+extension does not permit certificate signing.
-=item B<X509_V_ERR_INVALID_EXTENSION: invalid or inconsistent certificate extension>
+=item B<X509_V_ERR_INVALID_EXTENSION:
+invalid or inconsistent certificate extension>
A certificate extension had an invalid value (for example an incorrect
encoding) or some value inconsistent with other extensions.
-
-=item B<X509_V_ERR_INVALID_POLICY_EXTENSION: invalid or inconsistent certificate policy extension>
+=item B<X509_V_ERR_INVALID_POLICY_EXTENSION:
+invalid or inconsistent certificate policy extension>
A certificate policies extension had an invalid value (for example an incorrect
encoding) or some value inconsistent with other extensions. This error only
@@ -262,7 +284,7 @@ occurs if policy processing is enabled.
The verification flags were set to require and explicit policy but none was
present.
-=item B<X509_V_ERR_DIFFERENT_CRL_SCOPE: Different CRL scope>
+=item B<X509_V_ERR_DIFFERENT_CRL_SCOPE: different CRL scope>
The only CRLs that could be found did not match the scope of the certificate.
@@ -278,17 +300,20 @@ A name constraint violation occurred in the permitted subtrees.
A name constraint violation occurred in the excluded subtrees.
-=item B<X509_V_ERR_SUBTREE_MINMAX: name constraints minimum and maximum not supported>
+=item B<X509_V_ERR_SUBTREE_MINMAX:
+name constraints minimum and maximum not supported>
A certificate name constraints extension included a minimum or maximum field:
this is not supported.
-=item B<X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: unsupported name constraint type>
+=item B<X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE:
+unsupported name constraint type>
An unsupported name constraint type was encountered. OpenSSL currently only
supports directory name, DNS name, email and URI types.
-=item B<X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: unsupported or invalid name constraint syntax>
+=item B<X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX:
+unsupported or invalid name constraint syntax>
The format of the name constraint is not recognised: for example an email
address format of a form not mentioned in RFC3280. This could be caused by
@@ -301,8 +326,122 @@ happen if extended CRL checking is enabled.
=item B<X509_V_ERR_APPLICATION_VERIFICATION: application verification failure>
-an application specific error. This will never be returned unless explicitly
-set by an application.
+An application specific error. This will never be returned unless explicitly
+set by an application callback.
+
+=item B<X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: unable to get CRL issuer certificate>
+
+Unable to get CRL issuer certificate.
+
+=item B<X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: unhandled critical extension>
+
+Unhandled critical extension.
+
+=item B<X509_V_ERR_KEYUSAGE_NO_CRL_SIGN: key usage does not include CRL signing>
+
+Key usage does not include CRL signing.
+
+=item B<X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION: unhandled critical CRL extension>
+
+Unhandled critical CRL extension.
+
+=item B<X509_V_ERR_INVALID_NON_CA: invalid non-CA certificate (has CA markings)>
+
+Invalid non-CA certificate has CA markings.
+
+=item B<X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED: proxy path length constraint exceeded>
+
+Proxy path length constraint exceeded.
+
+=item B<X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE: key usage does not include digital signature>
+
+Key usage does not include digital signature, and therefore cannot sign
+certificates.
+
+=item B<X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED: proxy certificates not allowed, please set the appropriate flag>
+
+Proxy certificates not allowed unless the B<X509_V_FLAG_ALLOW_PROXY_CERTS> flag
+is set.
+
+=item B<X509_V_ERR_UNNESTED_RESOURCE: RFC 3779 resource not subset of parent's resources>
+
+See RFC 3779 for details.
+
+=item B<X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: unsupported or invalid name syntax>
+
+Unsupported or invalid name syntax.
+
+=item B<X509_V_ERR_PATH_LOOP: path loop>
+
+Path loop.
+
+=item B<X509_V_ERR_HOSTNAME_MISMATCH: hostname mismatch>
+
+Hostname mismatch.
+
+=item B<X509_V_ERR_EMAIL_MISMATCH: email address mismatch>
+
+Email address mismatch.
+
+=item B<X509_V_ERR_IP_ADDRESS_MISMATCH: IP address mismatch>
+
+IP address mismatch.
+
+=item B<X509_V_ERR_DANE_NO_MATCH: no matching DANE TLSA records>
+
+DANE TLSA authentication is enabled, but no TLSA records matched the
+certificate chain.
+This error is only possible in L<openssl-s_client(1)>.
+
+=item B<X509_V_ERR_EE_KEY_TOO_SMALL: EE certificate key too weak>
+
+EE certificate key too weak.
+
+=item B<X509_V_ERR_CA_KEY_TOO_SMALL: CA certificate key too weak>
+
+CA certificate key too weak.
+
+=item B<X509_V_ERR_CA_MD_TOO_WEAK: CA signature digest algorithm too weak>
+
+CA signature digest algorithm too weak.
+
+=item B<X509_V_ERR_INVALID_CALL: invalid certificate verification context>
+
+Invalid certificate verification context.
+
+=item B<X509_V_ERR_STORE_LOOKUP: issuer certificate lookup error>
+
+Issuer certificate lookup error.
+
+=item B<X509_V_ERR_NO_VALID_SCTS: certificate transparency required, but no valid SCTs found>
+
+Certificate Transparency required, but no valid SCTs found.
+
+=item B<X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION: proxy subject name violation>
+
+Proxy subject name violation.
+
+=item B<X509_V_ERR_OCSP_VERIFY_NEEDED: OCSP verification needed>
+
+Returned by the verify callback to indicate an OCSP verification is needed.
+
+=item B<X509_V_ERR_OCSP_VERIFY_FAILED: OCSP verification failed>
+
+Returned by the verify callback to indicate OCSP verification failed.
+
+=item B<X509_V_ERR_OCSP_CERT_UNKNOWN: OCSP unknown cert>
+
+Returned by the verify callback to indicate that the certificate is not
+recognized by the OCSP responder.
+
+=item B<X509_V_ERR_NO_ISSUER_PUBLIC_KEY: issuer certificate doesn't have a public key>
+
+The issuer certificate does not have a public key.
+
+=item B<X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH: subject signature algorithm and issuer public key algorithm mismatch>
+
+The issuer's public key is not of the type required by the signature in
+the subject's certificate.
=back
@@ -312,7 +451,7 @@ The above functions should be used instead of directly referencing the fields
in the B<X509_VERIFY_CTX> structure.
In versions of OpenSSL before 1.0 the current certificate returned by
-X509_STORE_CTX_get_current_cert() was never B<NULL>. Applications should
+X509_STORE_CTX_get_current_cert() was never NULL. Applications should
check the return value before printing out any debugging information relating
to the current certificate.
@@ -320,17 +459,23 @@ If an unrecognised error code is passed to X509_verify_cert_error_string() the
numerical value of the unknown code is returned in a static buffer. This is not
thread safe but will never happen unless an invalid code is passed.
+=head1 BUGS
+
+Previous versions of this documentation swapped the meaning of the
+B<X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT> and
+B<X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY> error codes.
+
=head1 SEE ALSO
-L<X509_verify_cert(3)>,
+L<X509_verify_cert(3)>, L<X509_STORE_CTX_verify(3)>,
L<X509_up_ref(3)>,
L<X509_free(3)>.
=head1 COPYRIGHT
-Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2009-2023 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_STORE_CTX_new.pod b/doc/man3/X509_STORE_CTX_new.pod
index bf16c1eced29..2319012a98e1 100644
--- a/doc/man3/X509_STORE_CTX_new.pod
+++ b/doc/man3/X509_STORE_CTX_new.pod
@@ -2,13 +2,13 @@
=head1 NAME
-X509_STORE_CTX_new, X509_STORE_CTX_cleanup, X509_STORE_CTX_free,
-X509_STORE_CTX_init, X509_STORE_CTX_set0_trusted_stack, X509_STORE_CTX_set_cert,
-X509_STORE_CTX_set0_crls,
-X509_STORE_CTX_get0_chain, X509_STORE_CTX_set0_verified_chain,
+X509_STORE_CTX_new_ex, X509_STORE_CTX_new, X509_STORE_CTX_cleanup,
+X509_STORE_CTX_free, X509_STORE_CTX_init, X509_STORE_CTX_set0_trusted_stack,
+X509_STORE_CTX_set_cert, X509_STORE_CTX_set0_crls,
X509_STORE_CTX_get0_param, X509_STORE_CTX_set0_param,
X509_STORE_CTX_get0_untrusted, X509_STORE_CTX_set0_untrusted,
X509_STORE_CTX_get_num_untrusted,
+X509_STORE_CTX_get0_chain, X509_STORE_CTX_set0_verified_chain,
X509_STORE_CTX_set_default,
X509_STORE_CTX_set_verify,
X509_STORE_CTX_verify_fn,
@@ -21,29 +21,30 @@ X509_STORE_CTX_purpose_inherit
#include <openssl/x509_vfy.h>
+ X509_STORE_CTX *X509_STORE_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq);
X509_STORE_CTX *X509_STORE_CTX_new(void);
void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx);
void X509_STORE_CTX_free(X509_STORE_CTX *ctx);
- int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store,
- X509 *x509, STACK_OF(X509) *chain);
+ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *trust_store,
+ X509 *target, STACK_OF(X509) *untrusted);
void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
- void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x);
- STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx);
- void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *chain);
+ void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *target);
void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk);
- X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx);
+ X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(const X509_STORE_CTX *ctx);
void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param);
- int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name);
- STACK_OF(X509)* X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx);
+ STACK_OF(X509)* X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx);
void X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
- int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx);
+ int X509_STORE_CTX_get_num_untrusted(const X509_STORE_CTX *ctx);
+ STACK_OF(X509) *X509_STORE_CTX_get0_chain(const X509_STORE_CTX *ctx);
+ void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *chain);
+ int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name);
typedef int (*X509_STORE_CTX_verify_fn)(X509_STORE_CTX *);
void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx, X509_STORE_CTX_verify_fn verify);
@@ -55,66 +56,100 @@ X509_STORE_CTX_purpose_inherit
=head1 DESCRIPTION
These functions initialise an B<X509_STORE_CTX> structure for subsequent use
-by X509_verify_cert().
+by L<X509_verify_cert(3)> or L<X509_STORE_CTX_verify(3)>.
-X509_STORE_CTX_new() returns a newly initialised B<X509_STORE_CTX> structure.
+X509_STORE_CTX_new_ex() returns a newly initialised B<X509_STORE_CTX>
+structure associated with the specified library context I<libctx> and property
+query string I<propq>. Any cryptographic algorithms fetched while performing
+processing with the X509_STORE_CTX will use that library context and property
+query string.
+
+X509_STORE_CTX_new() is the same as X509_STORE_CTX_new_ex() except that
+the default library context and a NULL property query string are used.
X509_STORE_CTX_cleanup() internally cleans up an B<X509_STORE_CTX> structure.
-The context can then be reused with a new call to X509_STORE_CTX_init().
+It is used by X509_STORE_CTX_init() and X509_STORE_CTX_free().
-X509_STORE_CTX_free() completely frees up B<ctx>. After this call B<ctx>
+X509_STORE_CTX_free() completely frees up I<ctx>. After this call I<ctx>
is no longer valid.
-If B<ctx> is NULL nothing is done.
-
-X509_STORE_CTX_init() sets up B<ctx> for a subsequent verification operation.
-It must be called before each call to X509_verify_cert(), i.e. a B<ctx> is only
-good for one call to X509_verify_cert(); if you want to verify a second
-certificate with the same B<ctx> then you must call X509_STORE_CTX_cleanup()
-and then X509_STORE_CTX_init() again before the second call to
-X509_verify_cert(). The trusted certificate store is set to B<store>, the end
-entity certificate to be verified is set to B<x509> and a set of additional
-certificates (which will be untrusted but may be used to build the chain) in
-B<chain>. Any or all of the B<store>, B<x509> and B<chain> parameters can be
-B<NULL>.
+If I<ctx> is NULL nothing is done.
+
+It must be called before each call to L<X509_verify_cert(3)> or
+L<X509_STORE_CTX_verify(3)>, i.e., a context is only good for one verification.
+If you want to verify a further certificate or chain with the same I<ctx>
+then you must call X509_STORE_CTX_init() again.
+The trusted certificate store is set to I<trust_store> of type B<X509_STORE>.
+This may be NULL because there are no trusted certificates or because
+they are provided simply as a list using X509_STORE_CTX_set0_trusted_stack().
+The certificate to be verified is set to I<target>,
+and a list of additional certificates may be provided in I<untrusted>,
+which will be untrusted but may be used to build the chain.
+Each of the I<trust_store>, I<target> and I<untrusted> parameters can be NULL.
+Yet note that L<X509_verify_cert(3)> and L<X509_STORE_CTX_verify(3)>
+will need a verification target.
+This can also be set using X509_STORE_CTX_set_cert().
+For L<X509_STORE_CTX_verify(3)>, which takes by default the first element of the
+list of untrusted certificates as its verification target,
+this can be also set indirectly using X509_STORE_CTX_set0_untrusted().
X509_STORE_CTX_set0_trusted_stack() sets the set of trusted certificates of
-B<ctx> to B<sk>. This is an alternative way of specifying trusted certificates
-instead of using an B<X509_STORE>.
+I<ctx> to I<sk>. This is an alternative way of specifying trusted certificates
+instead of using an B<X509_STORE> where its complexity is not needed
+or to make sure that only the given set I<sk> of certificates are trusted.
-X509_STORE_CTX_set_cert() sets the certificate to be verified in B<ctx> to
-B<x>.
+X509_STORE_CTX_set_cert() sets the target certificate to be verified in I<ctx>
+to I<target>.
+
+X509_STORE_CTX_set0_verified_chain() sets the validated chain to I<chain>.
+Ownership of the chain is transferred to I<ctx>,
+and so it should not be free'd by the caller.
-X509_STORE_CTX_set0_verified_chain() sets the validated chain used
-by B<ctx> to be B<chain>.
-Ownership of the chain is transferred to B<ctx> and should not be
-free'd by the caller.
X509_STORE_CTX_get0_chain() returns the internal pointer used by the
-B<ctx> that contains the validated chain.
+I<ctx> that contains the constructed (output) chain.
X509_STORE_CTX_set0_crls() sets a set of CRLs to use to aid certificate
-verification to B<sk>. These CRLs will only be used if CRL verification is
+verification to I<sk>. These CRLs will only be used if CRL verification is
enabled in the associated B<X509_VERIFY_PARAM> structure. This might be
used where additional "useful" CRLs are supplied as part of a protocol,
for example in a PKCS#7 structure.
X509_STORE_CTX_get0_param() retrieves an internal pointer
-to the verification parameters associated with B<ctx>.
+to the verification parameters associated with I<ctx>.
+
+X509_STORE_CTX_set0_param() sets the internal verification parameter pointer
+to I<param>. After this call B<param> should not be used.
X509_STORE_CTX_get0_untrusted() retrieves an internal pointer to the
-stack of untrusted certificates associated with B<ctx>.
+stack of untrusted certificates associated with I<ctx>.
-X509_STORE_CTX_set0_untrusted() sets the internal point to the stack
-of untrusted certificates associated with B<ctx> to B<sk>.
+X509_STORE_CTX_set0_untrusted() sets the internal pointer to the stack
+of untrusted certificates associated with I<ctx> to I<sk>.
+X509_STORE_CTX_verify() will take the first element, if any,
+as its default target if the target certificate is not set explicitly.
-X509_STORE_CTX_set0_param() sets the internal verification parameter pointer
-to B<param>. After this call B<param> should not be used.
+X509_STORE_CTX_get_num_untrusted() returns the number of untrusted certificates
+that were used in building the chain.
+This is can be used after calling L<X509_verify_cert(3)> and similar functions.
+With L<X509_STORE_CTX_verify(3)>, this does not count the first chain element.
-X509_STORE_CTX_set_default() looks up and sets the default verification
-method to B<name>. This uses the function X509_VERIFY_PARAM_lookup() to
-find an appropriate set of parameters from B<name>.
+X509_STORE_CTX_get0_chain() returns the internal pointer used by the
+I<ctx> that contains the validated chain.
-X509_STORE_CTX_get_num_untrusted() returns the number of untrusted certificates
-that were used in building the chain following a call to X509_verify_cert().
+Details of the chain building and checking process are described in
+L<openssl-verification-options(1)/Certification Path Building> and
+L<openssl-verification-options(1)/Certification Path Validation>.
+
+X509_STORE_CTX_set0_verified_chain() sets the validated chain used
+by I<ctx> to be I<chain>.
+Ownership of the chain is transferred to I<ctx>,
+and so it should not be free'd by the caller.
+
+X509_STORE_CTX_set_default() looks up and sets the default verification
+method to I<name>. This uses the function X509_VERIFY_PARAM_lookup() to
+find an appropriate set of parameters from the purpose identifier I<name>.
+Currently defined purposes are C<sslclient>, C<sslserver>, C<nssslserver>,
+C<smimesign>, C<smimeencrypt>, C<crlsign>, C<ocsphelper>, C<timestampsign>,
+and C<any>.
X509_STORE_CTX_set_verify() provides the capability for overriding the default
verify function. This function is responsible for verifying chain signatures and
@@ -204,13 +239,13 @@ should be made or reference counts increased instead.
=head1 RETURN VALUES
-X509_STORE_CTX_new() returns a newly allocated context or B<NULL> if an
+X509_STORE_CTX_new() returns a newly allocated context or NULL if an
error occurred.
X509_STORE_CTX_init() returns 1 for success or 0 if an error occurred.
X509_STORE_CTX_get0_param() returns a pointer to an B<X509_VERIFY_PARAM>
-structure or B<NULL> if an error occurred.
+structure or NULL if an error occurred.
X509_STORE_CTX_cleanup(), X509_STORE_CTX_free(),
X509_STORE_CTX_set0_trusted_stack(),
@@ -225,19 +260,22 @@ used.
=head1 SEE ALSO
-L<X509_verify_cert(3)>
+L<X509_verify_cert(3)>, L<X509_STORE_CTX_verify(3)>,
L<X509_VERIFY_PARAM_set_flags(3)>
=head1 HISTORY
The X509_STORE_CTX_set0_crls() function was added in OpenSSL 1.0.0.
The X509_STORE_CTX_get_num_untrusted() function was added in OpenSSL 1.1.0.
+The X509_STORE_CTX_new_ex() function was added in OpenSSL 3.0.
+
+There is no need to call X509_STORE_CTX_cleanup() explicitly since OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2009-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_STORE_CTX_set_verify_cb.pod b/doc/man3/X509_STORE_CTX_set_verify_cb.pod
index 81fe0b25a9b2..fefe6a25a0fe 100644
--- a/doc/man3/X509_STORE_CTX_set_verify_cb.pod
+++ b/doc/man3/X509_STORE_CTX_set_verify_cb.pod
@@ -14,14 +14,16 @@ X509_STORE_CTX_get_check_issued,
X509_STORE_CTX_get_get_issuer,
X509_STORE_CTX_get_verify_cb,
X509_STORE_CTX_set_verify_cb,
-X509_STORE_CTX_verify_cb
-- get and set verification callback
+X509_STORE_CTX_verify_cb,
+X509_STORE_CTX_print_verify_cb
+- get and set X509_STORE_CTX components such as verification callback
=head1 SYNOPSIS
#include <openssl/x509_vfy.h>
typedef int (*X509_STORE_CTX_verify_cb)(int, X509_STORE_CTX *);
+ int X509_STORE_CTX_print_verify_cb(int ok, X509_STORE_CTX *ctx);
X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx);
@@ -45,7 +47,7 @@ X509_STORE_CTX_set_verify_cb() sets the verification callback of B<ctx> to
B<verify_cb> overwriting any existing callback.
The verification callback can be used to customise the operation of certificate
-verification, either by overriding error conditions or logging errors for
+verification, for instance by overriding error conditions or logging errors for
debugging purposes.
However, a verification callback is B<not> essential and the default operation
@@ -63,6 +65,12 @@ structure and receive additional information about the error, for example
by calling X509_STORE_CTX_get_current_cert(). Additional application data can
be passed to the callback via the B<ex_data> mechanism.
+X509_STORE_CTX_print_verify_cb() is a verification callback function that,
+when a certificate verification has failed, adds an entry to the error queue
+with code B<X509_R_CERTIFICATE_VERIFICATION_FAILED> and with diagnostic details,
+including the most relevant fields of the target certificate that failed to
+verify and, if appropriate, of the available untrusted and trusted certificates.
+
X509_STORE_CTX_get_verify_cb() returns the value of the current callback
for the specific B<ctx>.
@@ -200,11 +208,13 @@ X509_STORE_CTX_get_cert_crl(), X509_STORE_CTX_get_check_policy(),
X509_STORE_CTX_get_lookup_certs(), X509_STORE_CTX_get_lookup_crls()
and X509_STORE_CTX_get_cleanup() functions were added in OpenSSL 1.1.0.
+X509_STORE_CTX_print_verify_cb() was added in OpenSSL 3.0.
+
=head1 COPYRIGHT
Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_STORE_add_cert.pod b/doc/man3/X509_STORE_add_cert.pod
index d840bd6d69bf..dc76704207eb 100644
--- a/doc/man3/X509_STORE_add_cert.pod
+++ b/doc/man3/X509_STORE_add_cert.pod
@@ -6,8 +6,10 @@ X509_STORE,
X509_STORE_add_cert, X509_STORE_add_crl, X509_STORE_set_depth,
X509_STORE_set_flags, X509_STORE_set_purpose, X509_STORE_set_trust,
X509_STORE_add_lookup,
-X509_STORE_load_locations,
-X509_STORE_set_default_paths
+X509_STORE_load_file_ex, X509_STORE_load_file, X509_STORE_load_path,
+X509_STORE_load_store_ex, X509_STORE_load_store,
+X509_STORE_set_default_paths_ex, X509_STORE_set_default_paths,
+X509_STORE_load_locations_ex, X509_STORE_load_locations
- X509_STORE manipulation
=head1 SYNOPSIS
@@ -26,9 +28,21 @@ X509_STORE_set_default_paths
X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *store,
X509_LOOKUP_METHOD *meth);
+ int X509_STORE_set_default_paths_ex(X509_STORE *ctx, OSSL_LIB_CTX *libctx,
+ const char *propq);
+ int X509_STORE_set_default_paths(X509_STORE *ctx);
+ int X509_STORE_load_file_ex(X509_STORE *ctx, const char *file,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ int X509_STORE_load_file(X509_STORE *ctx, const char *file);
+ int X509_STORE_load_path(X509_STORE *ctx, const char *dir);
+ int X509_STORE_load_store_ex(X509_STORE *ctx, const char *uri,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ int X509_STORE_load_store(X509_STORE *ctx, const char *uri);
+ int X509_STORE_load_locations_ex(X509_STORE *ctx, const char *file,
+ const char *dir, OSSL_LIB_CTX *libctx,
+ const char *propq);
int X509_STORE_load_locations(X509_STORE *ctx,
const char *file, const char *dir);
- int X509_STORE_set_default_paths(X509_STORE *ctx);
=head1 DESCRIPTION
@@ -39,6 +53,10 @@ It admits multiple lookup mechanisms and efficient scaling performance
with large numbers of certificates, and a great deal of flexibility in
how validation and policy checks are performed.
+Details of the chain building and checking process are described in
+L<openssl-verification-options(1)/Certification Path Building> and
+L<openssl-verification-options(1)/Certification Path Validation>.
+
L<X509_STORE_new(3)> creates an empty B<X509_STORE> structure, which contains
no information about trusted certificates or where such certificates
are located on disk, and is generally not usable. Normally, trusted
@@ -77,23 +95,54 @@ L<X509_LOOKUP_METHOD(3)> I<meth> and adds it to the B<X509_STORE>
I<store>. This also associates the B<X509_STORE> with the lookup, so
B<X509_LOOKUP> functions can look up objects in that store.
-X509_STORE_load_locations() loads trusted certificate(s) into an
-B<X509_STORE> from a given file and/or directory path. It is permitted
-to specify just a file, just a directory, or both paths. The certificates
-in the directory must be in hashed form, as documented in
-L<X509_LOOKUP_hash_dir(3)>.
+X509_STORE_load_file_ex() loads trusted certificate(s) into an
+B<X509_STORE> from a given file. The library context I<libctx> and property
+query I<propq> are used when fetching algorithms from providers.
-X509_STORE_set_default_paths() is somewhat misnamed, in that it does not
-set what default paths should be used for loading certificates. Instead,
-it loads certificates into the B<X509_STORE> from the hardcoded default
+X509_STORE_load_file() is similar to X509_STORE_load_file_ex() but
+uses NULL for the library context I<libctx> and property query I<propq>.
+
+X509_STORE_load_path() loads trusted certificate(s) into an
+B<X509_STORE> from a given directory path.
+The certificates in the directory must be in hashed form, as
+documented in L<X509_LOOKUP_hash_dir(3)>.
+
+X509_STORE_load_store_ex() loads trusted certificate(s) into an
+B<X509_STORE> from a store at a given URI. The library context I<libctx> and
+property query I<propq> are used when fetching algorithms from providers.
+
+X509_STORE_load_store() is similar to X509_STORE_load_store_ex() but
+uses NULL for the library context I<libctx> and property query I<propq>.
+
+X509_STORE_load_locations_ex() combines
+X509_STORE_load_file_ex() and X509_STORE_load_path() for a given file
+and/or directory path.
+It is permitted to specify just a file, just a directory, or both
paths.
+X509_STORE_load_locations() is similar to X509_STORE_load_locations_ex()
+but uses NULL for the library context I<libctx> and property query I<propq>.
+
+X509_STORE_set_default_paths_ex() is somewhat misnamed, in that it does
+not set what default paths should be used for loading certificates. Instead,
+it loads certificates into the B<X509_STORE> from the hardcoded default
+paths. The library context I<libctx> and property query I<propq> are used when
+fetching algorithms from providers.
+
+X509_STORE_set_default_paths() is similar to
+X509_STORE_set_default_paths_ex() but uses NULL for the library
+context I<libctx> and property query I<propq>.
+
=head1 RETURN VALUES
X509_STORE_add_cert(), X509_STORE_add_crl(), X509_STORE_set_depth(),
-X509_STORE_set_flags(), X509_STORE_set_purpose(),
-X509_STORE_set_trust(), X509_STORE_load_locations(), and
-X509_STORE_set_default_paths() return 1 on success or 0 on failure.
+X509_STORE_set_flags(), X509_STORE_set_purpose(), X509_STORE_set_trust(),
+X509_STORE_load_file_ex(), X509_STORE_load_file(),
+X509_STORE_load_path(),
+X509_STORE_load_store_ex(), X509_STORE_load_store(),
+X509_STORE_load_locations_ex(), X509_STORE_load_locations(),
+X509_STORE_set_default_paths_ex() and X509_STORE_set_default_paths()
+return 1 on success or 0 on failure.
X509_STORE_add_lookup() returns the found or created
L<X509_LOOKUP(3)>, or NULL on error.
@@ -105,11 +154,17 @@ L<X509_VERIFY_PARAM_set_depth(3)>.
L<X509_STORE_new(3)>,
L<X509_STORE_get0_param(3)>
+=head1 HISTORY
+
+The functions X509_STORE_set_default_paths_ex(),
+X509_STORE_load_file_ex(), X509_STORE_load_store_ex() and
+X509_STORE_load_locations_ex() were added in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_STORE_get0_param.pod b/doc/man3/X509_STORE_get0_param.pod
index 0aed725ad6d2..d9413fd49e15 100644
--- a/doc/man3/X509_STORE_get0_param.pod
+++ b/doc/man3/X509_STORE_get0_param.pod
@@ -3,15 +3,17 @@
=head1 NAME
X509_STORE_get0_param, X509_STORE_set1_param,
-X509_STORE_get0_objects - X509_STORE setter and getter functions
+X509_STORE_get0_objects, X509_STORE_get1_all_certs
+- X509_STORE setter and getter functions
=head1 SYNOPSIS
#include <openssl/x509_vfy.h>
- X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx);
- int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm);
- STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *ctx);
+ X509_VERIFY_PARAM *X509_STORE_get0_param(const X509_STORE *ctx);
+ int X509_STORE_set1_param(X509_STORE *ctx, const X509_VERIFY_PARAM *pm);
+ STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(const X509_STORE *ctx);
+ STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *st);
=head1 DESCRIPTION
@@ -22,10 +24,12 @@ X509_STORE_get0_param() retrieves an internal pointer to the verification
parameters for B<ctx>. The returned pointer must not be freed by the
calling application
-X509_STORE_get0_objects() retrieve an internal pointer to the store's
+X509_STORE_get0_objects() retrieves an internal pointer to the store's
X509 object cache. The cache contains B<X509> and B<X509_CRL> objects. The
returned pointer must not be freed by the calling application.
+X509_STORE_get1_all_certs() returns a list of all certificates in the store.
+The caller is responsible for freeing the returned list.
=head1 RETURN VALUES
@@ -36,6 +40,9 @@ X509_STORE_set1_param() returns 1 for success and 0 for failure.
X509_STORE_get0_objects() returns a pointer to a stack of B<X509_OBJECT>.
+X509_STORE_get1_all_certs() returns a pointer to a stack of the retrieved
+certificates on success, else NULL.
+
=head1 SEE ALSO
L<X509_STORE_new(3)>
@@ -44,12 +51,13 @@ L<X509_STORE_new(3)>
B<X509_STORE_get0_param> and B<X509_STORE_get0_objects> were added in
OpenSSL 1.1.0.
+B<X509_STORE_get1_certs> was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_STORE_new.pod b/doc/man3/X509_STORE_new.pod
index a28c8a20a82e..31d466faa42a 100644
--- a/doc/man3/X509_STORE_new.pod
+++ b/doc/man3/X509_STORE_new.pod
@@ -2,8 +2,9 @@
=head1 NAME
-X509_STORE_new, X509_STORE_up_ref, X509_STORE_free, X509_STORE_lock,
-X509_STORE_unlock - X509_STORE allocation, freeing and locking functions
+X509_STORE_new, X509_STORE_up_ref, X509_STORE_free,
+X509_STORE_lock,X509_STORE_unlock
+- X509_STORE allocation, freeing and locking functions
=head1 SYNOPSIS
@@ -48,9 +49,9 @@ functions were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_STORE_set_verify_cb_func.pod b/doc/man3/X509_STORE_set_verify_cb_func.pod
index 6d7098250d18..b73341a0f70d 100644
--- a/doc/man3/X509_STORE_set_verify_cb_func.pod
+++ b/doc/man3/X509_STORE_set_verify_cb_func.pod
@@ -22,6 +22,7 @@ X509_STORE_get_check_revocation,
X509_STORE_set_check_revocation,
X509_STORE_get_check_issued,
X509_STORE_set_check_issued,
+X509_STORE_CTX_get1_issuer,
X509_STORE_get_get_issuer,
X509_STORE_set_get_issuer,
X509_STORE_CTX_get_verify,
@@ -51,57 +52,65 @@ X509_STORE_CTX_lookup_certs_fn, X509_STORE_CTX_lookup_crls_fn
X509_CRL *crl, X509 *x);
typedef int (*X509_STORE_CTX_check_policy_fn)(X509_STORE_CTX *ctx);
typedef STACK_OF(X509) *(*X509_STORE_CTX_lookup_certs_fn)(X509_STORE_CTX *ctx,
- X509_NAME *nm);
- typedef STACK_OF(X509_CRL) *(*X509_STORE_CTX_lookup_crls_fn)(X509_STORE_CTX *ctx,
- X509_NAME *nm);
+ const X509_NAME *nm);
+ typedef STACK_OF(X509_CRL) *(*X509_STORE_CTX_lookup_crls_fn)(const
+ X509_STORE_CTX *ctx,
+ const X509_NAME *nm);
typedef int (*X509_STORE_CTX_cleanup_fn)(X509_STORE_CTX *ctx);
void X509_STORE_set_verify_cb(X509_STORE *ctx,
X509_STORE_CTX_verify_cb verify_cb);
- X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(X509_STORE_CTX *ctx);
+ X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(const X509_STORE_CTX *ctx);
void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify);
- X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx);
+ X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(const X509_STORE_CTX *ctx);
+ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
+ X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(const X509_STORE_CTX *ctx);
void X509_STORE_set_get_issuer(X509_STORE *ctx,
X509_STORE_CTX_get_issuer_fn get_issuer);
- X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(X509_STORE_CTX *ctx);
void X509_STORE_set_check_issued(X509_STORE *ctx,
X509_STORE_CTX_check_issued_fn check_issued);
- X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(X509_STORE_CTX *ctx);
+ X509_STORE_CTX_check_issued_fn
+ X509_STORE_get_check_issued(const X509_STORE_CTX *ctx);
void X509_STORE_set_check_revocation(X509_STORE *ctx,
X509_STORE_CTX_check_revocation_fn check_revocation);
- X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(X509_STORE_CTX *ctx);
+ X509_STORE_CTX_check_revocation_fn
+ X509_STORE_get_check_revocation(const X509_STORE_CTX *ctx);
void X509_STORE_set_get_crl(X509_STORE *ctx,
X509_STORE_CTX_get_crl_fn get_crl);
- X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(X509_STORE_CTX *ctx);
+ X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(const X509_STORE_CTX *ctx);
void X509_STORE_set_check_crl(X509_STORE *ctx,
X509_STORE_CTX_check_crl_fn check_crl);
- X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(X509_STORE_CTX *ctx);
+ X509_STORE_CTX_check_crl_fn
+ X509_STORE_get_check_crl(const X509_STORE_CTX *ctx);
void X509_STORE_set_cert_crl(X509_STORE *ctx,
X509_STORE_CTX_cert_crl_fn cert_crl);
- X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(X509_STORE_CTX *ctx);
+ X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(const X509_STORE_CTX *ctx);
void X509_STORE_set_check_policy(X509_STORE *ctx,
X509_STORE_CTX_check_policy_fn check_policy);
- X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(X509_STORE_CTX *ctx);
+ X509_STORE_CTX_check_policy_fn
+ X509_STORE_get_check_policy(const X509_STORE_CTX *ctx);
void X509_STORE_set_lookup_certs(X509_STORE *ctx,
X509_STORE_CTX_lookup_certs_fn lookup_certs);
- X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(X509_STORE_CTX *ctx);
+ X509_STORE_CTX_lookup_certs_fn
+ X509_STORE_get_lookup_certs(const X509_STORE_CTX *ctx);
void X509_STORE_set_lookup_crls(X509_STORE *ctx,
X509_STORE_CTX_lookup_crls_fn lookup_crls);
- X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(X509_STORE_CTX *ctx);
+ X509_STORE_CTX_lookup_crls_fn
+ X509_STORE_get_lookup_crls(const X509_STORE_CTX *ctx);
void X509_STORE_set_cleanup(X509_STORE *ctx,
X509_STORE_CTX_cleanup_fn cleanup);
- X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(X509_STORE_CTX *ctx);
+ X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(const X509_STORE_CTX *ctx);
/* Aliases */
void X509_STORE_set_verify_cb_func(X509_STORE *st,
@@ -113,14 +122,14 @@ X509_STORE_CTX_lookup_certs_fn, X509_STORE_CTX_lookup_crls_fn
=head1 DESCRIPTION
-X509_STORE_set_verify_cb() sets the verification callback of B<ctx> to
-B<verify_cb> overwriting the previous callback.
+X509_STORE_set_verify_cb() sets the verification callback of I<ctx> to
+I<verify_cb> overwriting the previous callback.
The callback assigned with this function becomes a default for the one
that can be assigned directly to the corresponding B<X509_STORE_CTX>,
please see L<X509_STORE_CTX_set_verify_cb(3)> for further information.
X509_STORE_set_verify() sets the final chain verification function for
-B<ctx> to B<verify>.
+I<ctx> to I<verify>.
Its purpose is to go through the chain of certificates and check that
all signatures are valid and that the current time is within the
limits of each certificate's first and last validity time.
@@ -129,17 +138,24 @@ on success.
I<If no chain verification function is provided, the internal default
function will be used instead.>
-X509_STORE_set_get_issuer() sets the function to get the issuer
-certificate that verifies the given certificate B<x>.
-When found, the issuer certificate must be assigned to B<*issuer>.
-This function must return 0 on failure and 1 on success.
-I<If no function to get the issuer is provided, the internal default
-function will be used instead.>
+X509_STORE_CTX_get1_issuer() tries to find a certificate from the I<store>
+component of I<ctx> with a subject name matching the issuer name of I<x>.
+On success it assigns to I<*issuer> the first match that is currently valid,
+or at least the most recently expired match if there is no currently valid one.
+If the function returns 1 the caller is responsible for freeing I<*issuer>.
+
+X509_STORE_set_get_issuer() sets the function I<get_issuer>
+to get the "best" candidate issuer certificate of the given certificate I<x>.
+When such a certificate is found, I<get_issuer> must up-ref and assign it
+to I<*issuer> and then return 1.
+Otherwise I<get_issuer> must return 0 if not found and -1 (or 0) on failure.
+If X509_STORE_set_get_issuer() is not used or I<get_issuer> is NULL
+then X509_STORE_CTX_get1_issuer() is used as the default implementation.
X509_STORE_set_check_issued() sets the function to check that a given
-certificate B<x> is issued by the issuer certificate B<issuer>.
-This function must return 0 on failure (among others if B<x> hasn't
-been issued with B<issuer>) and 1 on success.
+certificate I<x> is issued by the issuer certificate I<issuer>.
+This function must return 0 on failure (among others if I<x> hasn't
+been issued with I<issuer>) and 1 on success.
I<If no function to get the issuer is provided, the internal default
function will be used instead.>
@@ -152,20 +168,20 @@ I<If no function to get the issuer is provided, the internal default
function will be used instead.>
X509_STORE_set_get_crl() sets the function to get the crl for a given
-certificate B<x>.
-When found, the crl must be assigned to B<*crl>.
+certificate I<x>.
+When found, the crl must be assigned to I<*crl>.
This function must return 0 on failure and 1 on success.
I<If no function to get the issuer is provided, the internal default
function will be used instead.>
X509_STORE_set_check_crl() sets the function to check the validity of
-the given B<crl>.
+the given I<crl>.
This function must return 0 on failure and 1 on success.
I<If no function to get the issuer is provided, the internal default
function will be used instead.>
X509_STORE_set_cert_crl() sets the function to check the revocation
-status of the given certificate B<x> against the given B<crl>.
+status of the given certificate I<x> against the given I<crl>.
This function must return 0 on failure and 1 on success.
I<If no function to get the issuer is provided, the internal default
function will be used instead.>
@@ -178,7 +194,7 @@ function will be used instead.>
X509_STORE_set_lookup_certs() and X509_STORE_set_lookup_crls() set the
functions to look up all the certs or all the CRLs that match the
-given name B<nm>.
+given name I<nm>.
These functions return NULL on failure and a pointer to a stack of
certificates (B<X509>) or to a stack of CRLs (B<X509_CRL>) on
success.
@@ -229,6 +245,9 @@ The X509_STORE_set_*() functions do not return a value.
The X509_STORE_get_*() functions return a pointer of the appropriate
function type.
+X509_STORE_CTX_get1_issuer() returns
+1 if a suitable certificate is found, 0 if not found, -1 on other error.
+
=head1 SEE ALSO
L<X509_STORE_CTX_set_verify_cb(3)>, L<X509_STORE_CTX_get0_chain(3)>,
@@ -256,9 +275,9 @@ were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2009-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_VERIFY_PARAM_set_flags.pod b/doc/man3/X509_VERIFY_PARAM_set_flags.pod
index f6f304bf7bd0..75a167702296 100644
--- a/doc/man3/X509_VERIFY_PARAM_set_flags.pod
+++ b/doc/man3/X509_VERIFY_PARAM_set_flags.pod
@@ -10,11 +10,13 @@ X509_VERIFY_PARAM_get_depth, X509_VERIFY_PARAM_set_auth_level,
X509_VERIFY_PARAM_get_auth_level, X509_VERIFY_PARAM_set_time,
X509_VERIFY_PARAM_get_time,
X509_VERIFY_PARAM_add0_policy, X509_VERIFY_PARAM_set1_policies,
+X509_VERIFY_PARAM_get0_host,
X509_VERIFY_PARAM_set1_host, X509_VERIFY_PARAM_add1_host,
X509_VERIFY_PARAM_set_hostflags,
X509_VERIFY_PARAM_get_hostflags,
X509_VERIFY_PARAM_get0_peername,
-X509_VERIFY_PARAM_set1_email, X509_VERIFY_PARAM_set1_ip,
+X509_VERIFY_PARAM_get0_email, X509_VERIFY_PARAM_set1_email,
+X509_VERIFY_PARAM_set1_ip, X509_VERIFY_PARAM_get1_ip_asc,
X509_VERIFY_PARAM_set1_ip_asc
- X509 verification parameters
@@ -26,7 +28,7 @@ X509_VERIFY_PARAM_set1_ip_asc
unsigned long flags);
int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
unsigned long flags);
- unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param);
+ unsigned long X509_VERIFY_PARAM_get_flags(const X509_VERIFY_PARAM *param);
int X509_VERIFY_PARAM_set_inh_flags(X509_VERIFY_PARAM *param,
uint32_t flags);
@@ -50,6 +52,7 @@ X509_VERIFY_PARAM_set1_ip_asc
int auth_level);
int X509_VERIFY_PARAM_get_auth_level(const X509_VERIFY_PARAM *param);
+ char *X509_VERIFY_PARAM_get0_host(X509_VERIFY_PARAM *param, int n);
int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
const char *name, size_t namelen);
int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
@@ -57,9 +60,11 @@ X509_VERIFY_PARAM_set1_ip_asc
void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
unsigned int flags);
unsigned int X509_VERIFY_PARAM_get_hostflags(const X509_VERIFY_PARAM *param);
- char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param);
+ char *X509_VERIFY_PARAM_get0_peername(const X509_VERIFY_PARAM *param);
+ char *X509_VERIFY_PARAM_get0_email(X509_VERIFY_PARAM *param);
int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
const char *email, size_t emaillen);
+ char *X509_VERIFY_PARAM_get1_ip_asc(X509_VERIFY_PARAM *param);
int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
const unsigned char *ip, size_t iplen);
int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc);
@@ -70,7 +75,7 @@ These functions manipulate the B<X509_VERIFY_PARAM> structure associated with
a certificate verification operation.
The X509_VERIFY_PARAM_set_flags() function sets the flags in B<param> by oring
-it with B<flags>. See the B<VERIFICATION FLAGS> section for a complete
+it with B<flags>. See L</VERIFICATION FLAGS> for a complete
description of values the B<flags> parameter can take.
X509_VERIFY_PARAM_get_flags() returns the flags in B<param>.
@@ -84,7 +89,8 @@ X509_VERIFY_PARAM_clear_flags() clears the flags B<flags> in B<param>.
X509_VERIFY_PARAM_set_purpose() sets the verification purpose in B<param>
to B<purpose>. This determines the acceptable purpose of the certificate
-chain, for example SSL client or SSL server.
+chain, for example B<X509_PURPOSE_SSL_CLIENT>.
+The purpose requirement is cleared if B<purpose> is 0.
X509_VERIFY_PARAM_set_trust() sets the trust setting in B<param> to
B<trust>.
@@ -107,8 +113,8 @@ A maximal depth chain contains 2 more certificates than the limit, since
neither the end-entity certificate nor the trust-anchor count against this
limit.
Thus a B<depth> limit of 0 only allows the end-entity certificate to be signed
-directly by the trust-anchor, while with a B<depth> limit of 1 there can be one
-intermediate CA certificate between the trust-anchor and the end-entity
+directly by the trust anchor, while with a B<depth> limit of 1 there can be one
+intermediate CA certificate between the trust anchor and the end-entity
certificate.
X509_VERIFY_PARAM_set_auth_level() sets the authentication security level to
@@ -128,8 +134,13 @@ Security level 1 requires at least 80-bit-equivalent security and is broadly
interoperable, though it will, for example, reject MD5 signatures or RSA keys
shorter than 1024 bits.
+X509_VERIFY_PARAM_get0_host() returns the B<n>th expected DNS hostname that has
+been set using X509_VERIFY_PARAM_set1_host() or X509_VERIFY_PARAM_add1_host().
+To obtain all names start with B<n> = 0 and increment B<n> as long as no NULL
+pointer is returned.
+
X509_VERIFY_PARAM_set1_host() sets the expected DNS hostname to
-B<name> clearing any previously specified hostname or names. If
+B<name> clearing any previously specified hostname. If
B<name> is NULL, or empty the list of hostnames is cleared, and
name checks are not performed on the peer certificate. If B<name>
is NUL-terminated, B<namelen> may be zero, otherwise B<namelen>
@@ -177,12 +188,17 @@ string is allocated by the library and is no longer valid once the
associated B<param> argument is freed. Applications must not free
the return value.
+X509_VERIFY_PARAM_get0_email() returns the expected RFC822 email address.
+
X509_VERIFY_PARAM_set1_email() sets the expected RFC822 email address to
B<email>. If B<email> is NUL-terminated, B<emaillen> may be zero, otherwise
B<emaillen> must be set to the length of B<email>. When an email address
is specified, certificate verification automatically invokes
L<X509_check_email(3)>.
+X509_VERIFY_PARAM_get1_ip_asc() returns the expected IP address as a string.
+The caller is responsible for freeing it.
+
X509_VERIFY_PARAM_set1_ip() sets the expected IP address to B<ip>.
The B<ip> argument is in binary format, in network byte-order and
B<iplen> must be set to 4 for IPv4 and 16 for IPv6. When an IP
@@ -205,6 +221,10 @@ X509_VERIFY_PARAM_set1_email(), X509_VERIFY_PARAM_set1_ip() and
X509_VERIFY_PARAM_set1_ip_asc() return 1 for success and 0 for
failure.
+X509_VERIFY_PARAM_get0_host(), X509_VERIFY_PARAM_get0_email(), and
+X509_VERIFY_PARAM_get1_ip_asc(), return the string pointers pecified above
+or NULL if the respective value has not been set or on error.
+
X509_VERIFY_PARAM_get_flags() returns the current verification flags.
X509_VERIFY_PARAM_get_hostflags() returns any current host flags.
@@ -230,8 +250,8 @@ certificate. An error occurs if a suitable CRL cannot be found.
B<X509_V_FLAG_CRL_CHECK_ALL> enables CRL checking for the entire certificate
chain.
-B<X509_V_FLAG_IGNORE_CRITICAL> disabled critical extension checking. By default
-any unhandled critical extensions in certificates or (if checked) CRLs results
+B<X509_V_FLAG_IGNORE_CRITICAL> disables critical extension checking. By default
+any unhandled critical extensions in certificates or (if checked) CRLs result
in a fatal error. If this flag is set unhandled critical extensions are
ignored. B<WARNING> setting this option for anything other than debugging
purposes can be a security risk. Finer control over which extensions are
@@ -267,24 +287,24 @@ determine certificate status. If not set deltas are ignored.
B<X509_V_FLAG_CHECK_SS_SIGNATURE> requests checking the signature of
the last certificate in a chain if the certificate is supposedly self-signed.
This is prohibited and will result in an error if it is a non-conforming CA
-certificate with key usage restrictions not including the keyCertSign bit.
+certificate with key usage restrictions not including the I<keyCertSign> bit.
By default this check is disabled because it doesn't
add any additional security but in some cases applications might want to
check the signature anyway. A side effect of not checking the self-signature
of such a certificate is that disabled or unsupported message digests used for
the signature are not treated as fatal errors.
-When B<X509_V_FLAG_TRUSTED_FIRST> is set, construction of the certificate chain
-in L<X509_verify_cert(3)> will search the trust store for issuer certificates
+When B<X509_V_FLAG_TRUSTED_FIRST> is set, which is always the case since
+OpenSSL 1.1.0, construction of the certificate chain
+in L<X509_verify_cert(3)> searches the trust store for issuer certificates
before searching the provided untrusted certificates.
Local issuer certificates are often more likely to satisfy local security
requirements and lead to a locally trusted root.
This is especially important when some certificates in the trust store have
-explicit trust settings (see "TRUST SETTINGS" in L<x509(1)>).
-As of OpenSSL 1.1.0 this option is on by default.
+explicit trust settings (see "TRUST SETTINGS" in L<openssl-x509(1)>).
-The B<X509_V_FLAG_NO_ALT_CHAINS> flag suppresses checking for alternative
-chains.
+The B<X509_V_FLAG_NO_ALT_CHAINS> flag could have been used before OpenSSL 1.1.0
+to suppress checking for alternative chains.
By default, unless B<X509_V_FLAG_TRUSTED_FIRST> is set, when building a
certificate chain, if the first certificate chain found is not trusted, then
OpenSSL will attempt to replace untrusted certificates supplied by the peer
@@ -293,15 +313,15 @@ found that is trusted.
As of OpenSSL 1.1.0, with B<X509_V_FLAG_TRUSTED_FIRST> always set, this option
has no effect.
-The B<X509_V_FLAG_PARTIAL_CHAIN> flag causes intermediate certificates in the
-trust store to be treated as trust-anchors, in the same way as the self-signed
+The B<X509_V_FLAG_PARTIAL_CHAIN> flag causes non-self-signed certificates in the
+trust store to be treated as trust anchors, in the same way as self-signed
root CA certificates.
-This makes it possible to trust certificates issued by an intermediate CA
-without having to trust its ancestor root CA.
-With OpenSSL 1.1.0 and later and <X509_V_FLAG_PARTIAL_CHAIN> set, chain
-construction stops as soon as the first certificate from the trust store is
-added to the chain, whether that certificate is a self-signed "root"
-certificate or a not self-signed intermediate certificate.
+This makes it possible to trust self-issued certificates as well as certificates
+issued by an intermediate CA without having to trust their ancestor root CA.
+With OpenSSL 1.1.0 and later and B<X509_V_FLAG_PARTIAL_CHAIN> set, chain
+construction stops as soon as the first certificate contained in the trust store
+is added to the chain, whether that certificate is a self-signed "root"
+certificate or a not self-signed "intermediate" or self-issued certificate.
Thus, when an intermediate certificate is found in the trust store, the
verified chain passed to callbacks may be shorter than it otherwise would
be without the B<X509_V_FLAG_PARTIAL_CHAIN> flag.
@@ -367,7 +387,7 @@ L<X509_verify_cert(3)>,
L<X509_check_host(3)>,
L<X509_check_email(3)>,
L<X509_check_ip(3)>,
-L<x509(1)>
+L<openssl-x509(1)>
=head1 HISTORY
@@ -377,11 +397,14 @@ and has no effect.
The X509_VERIFY_PARAM_get_hostflags() function was added in OpenSSL 1.1.0i.
+The X509_VERIFY_PARAM_get0_host(), X509_VERIFY_PARAM_get0_email(),
+and X509_VERIFY_PARAM_get1_ip_asc() functions were added in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2009-2023 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_add_cert.pod b/doc/man3/X509_add_cert.pod
new file mode 100644
index 000000000000..1512d81701b8
--- /dev/null
+++ b/doc/man3/X509_add_cert.pod
@@ -0,0 +1,76 @@
+=pod
+
+=head1 NAME
+
+X509_add_cert,
+X509_add_certs -
+X509 certificate list addition functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509.h>
+
+ int X509_add_cert(STACK_OF(X509) *sk, X509 *cert, int flags);
+ int X509_add_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs, int flags);
+
+=head1 DESCRIPTION
+
+X509_add_cert() adds a certificate I<cert> to the given list I<sk>.
+
+X509_add_certs() adds a list of certificate I<certs> to the given list I<sk>.
+The I<certs> argument may be NULL, which implies no effect.
+It does not modify the list I<certs> but
+in case the B<X509_ADD_FLAG_UP_REF> flag (described below) is set
+the reference counters of those of its members added to I<sk> are increased.
+
+Both these functions have a I<flags> parameter,
+which is used to control details of the operation.
+
+The value B<X509_ADD_FLAG_DEFAULT>, which equals 0, means no special semantics.
+
+If B<X509_ADD_FLAG_UP_REF> is set then
+the reference counts of those certificates added successfully are increased.
+
+If B<X509_ADD_FLAG_PREPEND> is set then the certifcates are prepended to I<sk>.
+By default they are appended to I<sk>.
+In both cases the original order of the added certificates is preserved.
+
+If B<X509_ADD_FLAG_NO_DUP> is set then certificates already contained in I<sk>,
+which is determined using L<X509_cmp(3)>, are ignored.
+
+If B<X509_ADD_FLAG_NO_SS> is set then certificates that are marked self-signed,
+which is determined using L<X509_self_signed(3)>, are ignored.
+
+=head1 RETURN VALUES
+
+Both functions return 1 for success and 0 for failure.
+
+=head1 NOTES
+
+If X509_add_certs() is used with the flags B<X509_ADD_FLAG_NO_DUP> or
+B<X509_ADD_FLAG_NO_SS> it is advisable to use also B<X509_ADD_FLAG_UP_REF>
+because otherwise likely not for all members of the I<certs> list
+the ownership is transferred to the list of certificates I<sk>.
+
+Care should also be taken in case the I<certs> argument equals I<sk>.
+
+=head1 SEE ALSO
+
+L<X509_cmp(3)>
+L<X509_self_signed(3)>
+
+=head1 HISTORY
+
+The functions X509_add_cert() and X509_add_certs()
+were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/X509_check_ca.pod b/doc/man3/X509_check_ca.pod
index b70ecb787a68..91eba44f4100 100644
--- a/doc/man3/X509_check_ca.pod
+++ b/doc/man3/X509_check_ca.pod
@@ -13,7 +13,8 @@ X509_check_ca - check if given certificate is CA certificate
=head1 DESCRIPTION
This function checks if given certificate is CA certificate (can be used
-to sign other certificates).
+to sign other certificates). The certificate must be a complete certificate
+otherwise an error is returned.
=head1 RETURN VALUES
@@ -24,6 +25,8 @@ B<keyUsage> extension with bit B<keyCertSign> set, but without
B<basicConstraints>, and 5 if it has outdated Netscape Certificate Type
extension telling that it is CA certificate.
+This function will also return 0 on error.
+
Actually, any nonzero value means that this certificate could have been
used to sign other certificates.
@@ -35,9 +38,9 @@ L<X509_check_purpose(3)>
=head1 COPYRIGHT
-Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_check_host.pod b/doc/man3/X509_check_host.pod
index b8bdd4c83156..0156194c9915 100644
--- a/doc/man3/X509_check_host.pod
+++ b/doc/man3/X509_check_host.pod
@@ -24,7 +24,7 @@ The validity of the certificate and its trust level has to be checked by
other means.
X509_check_host() checks if the certificate Subject Alternative
-Name (SAN) or Subject CommonName (CN) matches the specified hostname,
+Name (SAN) or Subject CommonName (CN) matches the specified hostname,
which must be encoded in the preferred name syntax described
in section 3.5 of RFC 1034. By default, wildcards are supported
and they match only in the left-most label; but they may match
@@ -48,9 +48,13 @@ is responsible for freeing the peername via OPENSSL_free() when it
is no longer needed.
X509_check_email() checks if the certificate matches the specified
-email B<address>. Only the mailbox syntax of RFC 822 is supported,
+email B<address>. The mailbox syntax of RFC 822 is supported,
comments are not allowed, and no attempt is made to normalize quoted
-characters. The B<addresslen> argument must be the number of
+characters. The mailbox syntax of RFC 6531 is supported for
+SmtpUTF8Mailbox address in subjectAltName according to RFC 8398,
+with similar limitations as for RFC 822 syntax, and no attempt
+is made to convert from A-label to U-label before comparison.
+The B<addresslen> argument must be the number of
characters in the address string or zero in which case the length
is calculated with strlen(B<address>).
@@ -58,7 +62,8 @@ X509_check_ip() checks if the certificate matches a specified IPv4 or
IPv6 address. The B<address> array is in binary format, in network
byte order. The length is either 4 (IPv4) or 16 (IPv6). Only
explicitly marked addresses in the certificates are considered; IP
-addresses stored in DNS names and Common Names are ignored.
+addresses stored in DNS names and Common Names are ignored. There are
+currently no B<flags> that would affect the behavior of this call.
X509_check_ip_asc() is similar, except that the NUL-terminated
string B<address> is first converted to the internal representation.
@@ -130,7 +135,7 @@ NULs.
=head1 NOTES
Applications are encouraged to use X509_VERIFY_PARAM_set1_host()
-rather than explicitly calling L<X509_check_host(3)>. Host name
+rather than explicitly calling L<X509_check_host(3)>. Hostname
checks may be out of scope with the DANE-EE(3) certificate usage,
and the internal checks will be suppressed as appropriate when
DANE support is enabled.
@@ -141,8 +146,7 @@ L<SSL_get_verify_result(3)>,
L<X509_VERIFY_PARAM_set1_host(3)>,
L<X509_VERIFY_PARAM_add1_host(3)>,
L<X509_VERIFY_PARAM_set1_email(3)>,
-L<X509_VERIFY_PARAM_set1_ip(3)>,
-L<X509_VERIFY_PARAM_set1_ipasc(3)>
+L<X509_VERIFY_PARAM_set1_ip(3)>
=head1 HISTORY
@@ -150,9 +154,9 @@ These functions were added in OpenSSL 1.0.2.
=head1 COPYRIGHT
-Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2012-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_check_issued.pod b/doc/man3/X509_check_issued.pod
index 55f75ac84bb4..b83bc1396bec 100644
--- a/doc/man3/X509_check_issued.pod
+++ b/doc/man3/X509_check_issued.pod
@@ -21,24 +21,24 @@ but also compares all sub-fields of the B<authorityKeyIdentifier> extension of
I<subject>, as far as present, with the respective B<subjectKeyIdentifier>,
serial number, and issuer fields of I<issuer>, as far as present. It also checks
if the B<keyUsage> field (if present) of I<issuer> allows certificate signing.
-It does not check the certificate signature.
+It does not actually check the certificate signature. An error is returned
+if the I<issuer> or the I<subject> are incomplete certificates.
=head1 RETURN VALUES
-Function return B<X509_V_OK> if certificate I<subject> is issued by
-I<issuer> or some B<X509_V_ERR*> constant to indicate an error.
+X509_check_issued() returns B<X509_V_OK> if all checks are successful
+or some B<X509_V_ERR*> constant to indicate an error.
=head1 SEE ALSO
-L<X509_verify_cert(3)>,
-L<X509_check_ca(3)>,
-L<verify(1)>
+L<X509_verify_cert(3)>, L<X509_verify(3)>, L<X509_check_ca(3)>,
+L<openssl-verify(1)>, L<X509_self_signed(3)>
=head1 COPYRIGHT
-Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_check_private_key.pod b/doc/man3/X509_check_private_key.pod
index 4735dfd5689c..9c83a8ad20fb 100644
--- a/doc/man3/X509_check_private_key.pod
+++ b/doc/man3/X509_check_private_key.pod
@@ -46,7 +46,7 @@ L<ERR_get_error(3)>
Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_check_purpose.pod b/doc/man3/X509_check_purpose.pod
index 6af9e79815e4..a3cfb78d6198 100644
--- a/doc/man3/X509_check_purpose.pod
+++ b/doc/man3/X509_check_purpose.pod
@@ -8,14 +8,15 @@ X509_check_purpose - Check the purpose of a certificate
#include <openssl/x509v3.h>
- int X509_check_purpose(X509 *x, int id, int ca)
+ int X509_check_purpose(X509 *x, int id, int ca);
=head1 DESCRIPTION
This function checks if certificate I<x> was created with the purpose
represented by I<id>. If I<ca> is nonzero, then certificate I<x> is
checked to determine if it's a possible CA with various levels of certainty
-possibly returned.
+possibly returned. The certificate I<x> must be a complete certificate
+otherwise the function returns an error.
Below are the potential ID's that can be checked:
@@ -29,6 +30,9 @@ Below are the potential ID's that can be checked:
# define X509_PURPOSE_OCSP_HELPER 8
# define X509_PURPOSE_TIMESTAMP_SIGN 9
+The checks performed take into account the X.509 extensions
+keyUsage, extendedKeyUsage, and basicConstraints.
+
=head1 RETURN VALUES
For non-CA checks
@@ -66,7 +70,7 @@ For CA checks the below integers could be returned with the following meanings:
=head1 COPYRIGHT
-Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not use this
file except in compliance with the License. You can obtain a copy in the file
LICENSE in the source distribution or at L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_cmp.pod b/doc/man3/X509_cmp.pod
index 3cb16b2a81f1..272a9d259e70 100644
--- a/doc/man3/X509_cmp.pod
+++ b/doc/man3/X509_cmp.pod
@@ -25,16 +25,20 @@ This set of functions are used to compare X509 objects, including X509
certificates, X509 CRL objects and various values in an X509 certificate.
The X509_cmp() function compares two B<X509> objects indicated by parameters
-B<a> and B<b>. The comparison is based on the B<memcmp> result of the hash
+I<a> and I<b>. The comparison is based on the B<memcmp> result of the hash
values of two B<X509> objects and the canonical (DER) encoding values.
The X509_NAME_cmp() function compares two B<X509_NAME> objects indicated by
-parameters B<a> and B<b>. The comparison is based on the B<memcmp> result of
-the canonical (DER) encoding values of the two objects. L<i2d_X509_NAME(3)>
-has a more detailed description of the DER encoding of the B<X509_NAME> structure.
+parameters I<a> and I<b>. The comparison is based on the B<memcmp> result of the
+canonical (DER) encoding values of the two objects using L<i2d_X509_NAME(3)>.
+This procedure adheres to the matching rules for Distinguished Names (DN)
+given in RFC 4517 section 4.2.15 and RFC 5280 section 7.1.
+In particular, the order of Relative Distinguished Names (RDNs) is relevant.
+On the other hand, if an RDN is multi-valued, i.e., it contains a set of
+AttributeValueAssertions (AVAs), its members are effectively not ordered.
The X509_issuer_and_serial_cmp() function compares the serial number and issuer
-values in the given B<X509> objects B<a> and B<b>.
+values in the given B<X509> objects I<a> and I<b>.
The X509_issuer_name_cmp(), X509_subject_name_cmp() and X509_CRL_cmp() functions
are effectively wrappers of the X509_NAME_cmp() function. These functions compare
@@ -47,12 +51,12 @@ of just the issuer name.
=head1 RETURN VALUES
-Like common memory comparison functions, the B<X509> comparison functions return
-an integer less than, equal to, or greater than zero if object B<a> is found to
-be less than, to match, or be greater than object B<b>, respectively.
+The B<X509> comparison functions return B<-1>, B<0>, or B<1> if object I<a> is
+found to be less than, to match, or be greater than object I<b>, respectively.
X509_NAME_cmp(), X509_issuer_and_serial_cmp(), X509_issuer_name_cmp(),
-X509_subject_name_cmp() and X509_CRL_cmp() may return B<-2> to indicate an error.
+X509_subject_name_cmp(), X509_CRL_cmp(), and X509_CRL_match()
+may return B<-2> to indicate an error.
=head1 NOTES
@@ -70,7 +74,7 @@ L<i2d_X509_NAME(3)>, L<i2d_X509(3)>
=head1 COPYRIGHT
-Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
diff --git a/doc/man3/X509_cmp_time.pod b/doc/man3/X509_cmp_time.pod
index b55ade455de0..36a5109eb144 100644
--- a/doc/man3/X509_cmp_time.pod
+++ b/doc/man3/X509_cmp_time.pod
@@ -2,39 +2,54 @@
=head1 NAME
-X509_cmp_time, X509_cmp_current_time, X509_time_adj, X509_time_adj_ex
+X509_cmp_time, X509_cmp_current_time, X509_cmp_timeframe,
+X509_time_adj, X509_time_adj_ex, X509_gmtime_adj
- X509 time functions
=head1 SYNOPSIS
int X509_cmp_time(const ASN1_TIME *asn1_time, time_t *in_tm);
int X509_cmp_current_time(const ASN1_TIME *asn1_time);
+ int X509_cmp_timeframe(const X509_VERIFY_PARAM *vpm,
+ const ASN1_TIME *start, const ASN1_TIME *end);
ASN1_TIME *X509_time_adj(ASN1_TIME *asn1_time, long offset_sec, time_t *in_tm);
ASN1_TIME *X509_time_adj_ex(ASN1_TIME *asn1_time, int offset_day, long
offset_sec, time_t *in_tm);
+ ASN1_TIME *X509_gmtime_adj(ASN1_TIME *asn1_time, long offset_sec);
=head1 DESCRIPTION
-X509_cmp_time() compares the ASN1_TIME in B<asn1_time> with the time
-in <cmp_time>. X509_cmp_current_time() compares the ASN1_TIME in
-B<asn1_time> with the current time, expressed as time_t. B<asn1_time>
-must satisfy the ASN1_TIME format mandated by RFC 5280, i.e., its
-format must be either YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ.
+X509_cmp_time() compares the ASN1_TIME in I<asn1_time> with the time
+in <in_tm>.
-X509_time_adj_ex() sets the ASN1_TIME structure B<asn1_time> to the time
-B<offset_day> and B<offset_sec> after B<in_tm>.
+X509_cmp_current_time() compares the ASN1_TIME in
+I<asn1_time> with the current time, expressed as time_t.
-X509_time_adj() sets the ASN1_TIME structure B<asn1_time> to the time
-B<offset_sec> after B<in_tm>. This method can only handle second
+X509_cmp_timeframe() compares the given time period with the reference time
+included in the verification parameters I<vpm> if they are not NULL and contain
+B<X509_V_FLAG_USE_CHECK_TIME>; else the current time is used as reference time.
+
+X509_time_adj_ex() sets the ASN1_TIME structure I<asn1_time> to the time
+I<offset_day> and I<offset_sec> after I<in_tm>.
+
+X509_time_adj() sets the ASN1_TIME structure I<asn1_time> to the time
+I<offset_sec> after I<in_tm>. This method can only handle second
offsets up to the capacity of long, so the newer X509_time_adj_ex()
API should be preferred.
-In both methods, if B<asn1_time> is NULL, a new ASN1_TIME structure
+In both methods, if I<asn1_time> is NULL, a new ASN1_TIME structure
is allocated and returned.
-In all methods, if B<in_tm> is NULL, the current time, expressed as
+In all methods, if I<in_tm> is NULL, the current time, expressed as
time_t, is used.
+I<asn1_time> must satisfy the ASN1_TIME format mandated by RFC 5280,
+i.e., its format must be either YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ.
+
+X509_gmtime_adj() sets the ASN1_TIME structure I<asn1_time> to the time
+I<offset_sec> after the current time. It is equivalent to calling
+X509_time_adj() with the last parameter as NULL.
+
=head1 BUGS
Unlike many standard comparison functions, X509_cmp_time() and
@@ -42,18 +57,30 @@ X509_cmp_current_time() return 0 on error.
=head1 RETURN VALUES
-X509_cmp_time() and X509_cmp_current_time() return -1 if B<asn1_time>
-is earlier than, or equal to, B<cmp_time> (resp. current time), and 1
+X509_cmp_time() and X509_cmp_current_time() return -1 if I<asn1_time>
+is earlier than, or equal to, I<in_tm> (resp. current time), and 1
otherwise. These methods return 0 on error.
-X509_time_adj() and X509_time_adj_ex() return a pointer to the updated
-ASN1_TIME structure, and NULL on error.
+X509_cmp_timeframe() returns 0 if I<vpm> is not NULL and the verification
+parameters do not contain B<X509_V_FLAG_USE_CHECK_TIME>
+but do contain B<X509_V_FLAG_NO_CHECK_TIME>. Otherwise it returns
+1 if the end time is not NULL and the reference time (which has determined as
+stated above) is past the end time, -1 if the start time is not NULL and the
+reference time is before, else 0 to indicate that the reference time is in range
+(implying that the end time is not before the start time if both are present).
+
+X509_time_adj(), X509_time_adj_ex() and X509_gmtime_adj() return a pointer to
+the updated ASN1_TIME structure, and NULL on error.
+
+=head1 HISTORY
+
+X509_cmp_timeframe() was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_digest.pod b/doc/man3/X509_digest.pod
index 9322c37dbb6a..f4921dbc187b 100644
--- a/doc/man3/X509_digest.pod
+++ b/doc/man3/X509_digest.pod
@@ -2,7 +2,9 @@
=head1 NAME
-X509_digest, X509_CRL_digest,
+X509_digest,
+X509_digest_sig,
+X509_CRL_digest,
X509_pubkey_digest,
X509_NAME_digest,
X509_REQ_digest,
@@ -15,6 +17,8 @@ PKCS7_ISSUER_AND_SERIAL_digest
int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
unsigned int *len);
+ ASN1_OCTET_STRING *X509_digest_sig(const X509 *cert,
+ EVP_MD **md_used, int *md_is_fallback);
int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, unsigned char *md,
unsigned int *len);
@@ -36,30 +40,50 @@ PKCS7_ISSUER_AND_SERIAL_digest
=head1 DESCRIPTION
+X509_digest_sig() calculates a digest of the given certificate I<cert>
+using the same hash algorithm as in its signature, if the digest
+is an integral part of the certificate signature algorithm identifier.
+Otherwise, a fallback hash algorithm is determined as follows:
+SHA512 if the signature alorithm is ED25519,
+SHAKE256 if it is ED448, otherwise SHA256.
+The output parmeters are assigned as follows.
+Unless I<md_used> is NULL, the hash algorithm used is provided
+in I<*md_used> and must be freed by the caller (if it is not NULL).
+Unless I<md_is_fallback> is NULL,
+the I<*md_is_fallback> is set to 1 if the hash algorithm used is a fallback,
+otherwise to 0.
+
X509_pubkey_digest() returns a digest of the DER representation of the public
-key in the specified X509 B<data> object.
+key in the specified X509 I<data> object.
+
All other functions described here return a digest of the DER representation
-of their entire B<data> objects.
+of their entire I<data> objects.
-The B<type> parameter specifies the digest to
-be used, such as EVP_sha1(). The B<md> is a pointer to the buffer where the
+The I<type> parameter specifies the digest to
+be used, such as EVP_sha1(). The I<md> is a pointer to the buffer where the
digest will be copied and is assumed to be large enough; the constant
-B<EVP_MAX_MD_SIZE> is suggested. The B<len> parameter, if not NULL, points
+B<EVP_MAX_MD_SIZE> is suggested. The I<len> parameter, if not NULL, points
to a place where the digest size will be stored.
=head1 RETURN VALUES
-All functions described here return 1 for success and 0 for failure.
+X509_digest_sig() returns an ASN1_OCTET_STRING pointer on success, else NULL.
+
+All other functions described here return 1 for success and 0 for failure.
=head1 SEE ALSO
L<EVP_sha1(3)>
+=head1 HISTORY
+
+The X509_digest_sig() function was added in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_dup.pod b/doc/man3/X509_dup.pod
index 4f982089aa02..9fc355c7ce34 100644
--- a/doc/man3/X509_dup.pod
+++ b/doc/man3/X509_dup.pod
@@ -29,6 +29,7 @@ CERTIFICATEPOLICIES_free,
CERTIFICATEPOLICIES_new,
CMS_ContentInfo_free,
CMS_ContentInfo_new,
+CMS_ContentInfo_new_ex,
CMS_ContentInfo_print_ctx,
CMS_ReceiptRequest_free,
CMS_ReceiptRequest_new,
@@ -52,12 +53,20 @@ EDIPARTYNAME_new,
ESS_CERT_ID_dup,
ESS_CERT_ID_free,
ESS_CERT_ID_new,
+ESS_CERT_ID_V2_dup,
+ESS_CERT_ID_V2_free,
+ESS_CERT_ID_V2_new,
ESS_ISSUER_SERIAL_dup,
ESS_ISSUER_SERIAL_free,
ESS_ISSUER_SERIAL_new,
ESS_SIGNING_CERT_dup,
ESS_SIGNING_CERT_free,
+ESS_SIGNING_CERT_it,
ESS_SIGNING_CERT_new,
+ESS_SIGNING_CERT_V2_dup,
+ESS_SIGNING_CERT_V2_free,
+ESS_SIGNING_CERT_V2_it,
+ESS_SIGNING_CERT_V2_new,
EXTENDED_KEY_USAGE_free,
EXTENDED_KEY_USAGE_new,
GENERAL_NAMES_free,
@@ -75,7 +84,11 @@ IPAddressOrRange_free,
IPAddressOrRange_new,
IPAddressRange_free,
IPAddressRange_new,
+ISSUER_SIGN_TOOL_free,
+ISSUER_SIGN_TOOL_it,
+ISSUER_SIGN_TOOL_new,
ISSUING_DIST_POINT_free,
+ISSUING_DIST_POINT_it,
ISSUING_DIST_POINT_new,
NAME_CONSTRAINTS_free,
NAME_CONSTRAINTS_new,
@@ -116,6 +129,45 @@ OCSP_SIGNATURE_free,
OCSP_SIGNATURE_new,
OCSP_SINGLERESP_free,
OCSP_SINGLERESP_new,
+OSSL_CMP_ITAV_dup,
+OSSL_CMP_ITAV_free,
+OSSL_CMP_MSG_dup,
+OSSL_CMP_MSG_it,
+OSSL_CMP_MSG_free,
+OSSL_CMP_PKIHEADER_free,
+OSSL_CMP_PKIHEADER_it,
+OSSL_CMP_PKIHEADER_new,
+OSSL_CMP_PKISI_dup,
+OSSL_CMP_PKISI_free,
+OSSL_CMP_PKISI_it,
+OSSL_CMP_PKISI_new,
+OSSL_CMP_PKISTATUS_it,
+OSSL_CRMF_CERTID_dup,
+OSSL_CRMF_CERTID_free,
+OSSL_CRMF_CERTID_it,
+OSSL_CRMF_CERTID_new,
+OSSL_CRMF_CERTTEMPLATE_free,
+OSSL_CRMF_CERTTEMPLATE_it,
+OSSL_CRMF_CERTTEMPLATE_new,
+OSSL_CRMF_ENCRYPTEDVALUE_free,
+OSSL_CRMF_ENCRYPTEDVALUE_it,
+OSSL_CRMF_ENCRYPTEDVALUE_new,
+OSSL_CRMF_MSGS_free,
+OSSL_CRMF_MSGS_it,
+OSSL_CRMF_MSGS_new,
+OSSL_CRMF_MSG_dup,
+OSSL_CRMF_MSG_free,
+OSSL_CRMF_MSG_it,
+OSSL_CRMF_MSG_new,
+OSSL_CRMF_PBMPARAMETER_free,
+OSSL_CRMF_PBMPARAMETER_it,
+OSSL_CRMF_PBMPARAMETER_new,
+OSSL_CRMF_PKIPUBLICATIONINFO_free,
+OSSL_CRMF_PKIPUBLICATIONINFO_it,
+OSSL_CRMF_PKIPUBLICATIONINFO_new,
+OSSL_CRMF_SINGLEPUBINFO_free,
+OSSL_CRMF_SINGLEPUBINFO_it,
+OSSL_CRMF_SINGLEPUBINFO_new,
OTHERNAME_free,
OTHERNAME_new,
PBE2PARAM_free,
@@ -152,6 +204,7 @@ PKCS7_SIGN_ENVELOPE_free,
PKCS7_SIGN_ENVELOPE_new,
PKCS7_dup,
PKCS7_free,
+PKCS7_new_ex,
PKCS7_new,
PKCS7_print_ctx,
PKCS8_PRIV_KEY_INFO_free,
@@ -166,10 +219,10 @@ POLICY_CONSTRAINTS_free,
POLICY_CONSTRAINTS_new,
POLICY_MAPPING_free,
POLICY_MAPPING_new,
-PROFESSION_INFO_free,
-PROFESSION_INFO_new,
PROFESSION_INFOS_free,
PROFESSION_INFOS_new,
+PROFESSION_INFO_free,
+PROFESSION_INFO_new,
PROXY_CERT_INFO_EXTENSION_free,
PROXY_CERT_INFO_EXTENSION_new,
PROXY_POLICY_free,
@@ -180,6 +233,7 @@ RSA_OAEP_PARAMS_free,
RSA_OAEP_PARAMS_new,
RSA_PSS_PARAMS_free,
RSA_PSS_PARAMS_new,
+RSA_PSS_PARAMS_dup,
SCRYPT_PARAMS_free,
SCRYPT_PARAMS_new,
SXNETID_free,
@@ -209,6 +263,7 @@ TS_TST_INFO_new,
USERNOTICE_free,
USERNOTICE_new,
X509_ALGOR_free,
+X509_ALGOR_it,
X509_ALGOR_new,
X509_ATTRIBUTE_dup,
X509_ATTRIBUTE_free,
@@ -221,6 +276,7 @@ X509_CRL_INFO_free,
X509_CRL_INFO_new,
X509_CRL_dup,
X509_CRL_free,
+X509_CRL_new_ex,
X509_CRL_new,
X509_EXTENSION_dup,
X509_EXTENSION_free,
@@ -236,6 +292,7 @@ X509_REQ_INFO_new,
X509_REQ_dup,
X509_REQ_free,
X509_REQ_new,
+X509_REQ_new_ex,
X509_REVOKED_dup,
X509_REVOKED_free,
X509_REVOKED_new,
@@ -248,7 +305,7 @@ X509_dup,
=head1 SYNOPSIS
-=for comment generic
+=for openssl generic
#include <openssl/asn1t.h>
@@ -259,14 +316,22 @@ X509_dup,
extern const ASN1_ITEM TYPE_it;
TYPE *TYPE_new(void);
- TYPE *TYPE_dup(TYPE *a);
+ TYPE *TYPE_dup(const TYPE *a);
void TYPE_free(TYPE *a);
int TYPE_print_ctx(BIO *out, TYPE *a, int indent, const ASN1_PCTX *pctx);
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ DSA *DSAparams_dup(const DSA *dsa);
+ RSA *RSAPrivateKey_dup(const RSA *rsa);
+ RSA *RSAPublicKey_dup(const RSA *rsa);
+
=head1 DESCRIPTION
-In the description below, I<TYPE> is used
-as a placeholder for any of the OpenSSL datatypes, such as I<X509>.
+In the description below, B<I<TYPE>> is used
+as a placeholder for any of the OpenSSL datatypes, such as B<X509>.
The OpenSSL ASN1 parsing library templates are like a data-driven bytecode
interpreter.
@@ -282,31 +347,45 @@ The macro IMPLEMENT_ASN1_FUNCTIONS() is used once in a source file
to generate the function bodies.
-TYPE_new() allocates an empty object of the indicated type.
-The object returned must be released by calling TYPE_free().
+B<I<TYPE>_new>() allocates an empty object of the indicated type.
+The object returned must be released by calling B<I<TYPE>_free>().
+
+B<I<TYPE>_new_ex>() is similiar to B<I<TYPE>_new>() but also passes the
+library context I<libctx> and the property query I<propq> to use when retrieving
+algorithms from providers. This created object can then be used when loading
+binary data using B<d2i_I<TYPE>>().
-TYPE_dup() copies an existing object.
+B<I<TYPE>_dup>() copies an existing object, leaving it untouched.
-TYPE_free() releases the object and all pointers and sub-objects
+B<I<TYPE>_free>() releases the object and all pointers and sub-objects
within it.
-TYPE_print_ctx() prints the object B<a> on the specified BIO B<out>.
-Each line will be prefixed with B<indent> spaces.
-The B<pctx> specifies the printing context and is for internal
+B<I<TYPE>_print_ctx>() prints the object I<a> on the specified BIO I<out>.
+Each line will be prefixed with I<indent> spaces.
+The I<pctx> specifies the printing context and is for internal
use; use NULL to get the default behavior. If a print function is
-user-defined, then pass in any B<pctx> down to any nested calls.
+user-defined, then pass in any I<pctx> down to any nested calls.
=head1 RETURN VALUES
-TYPE_new() and TYPE_dup() return a pointer to the object or NULL on failure.
+B<I<TYPE>_new>(), B<I<TYPE>_new_ex>() and B<I<TYPE>_dup>() return a pointer to
+the object or NULL on failure.
+
+B<I<TYPE>_print_ctx>() returns 1 on success or zero on failure.
+
+=head1 HISTORY
+
+The functions X509_REQ_new_ex(), X509_CRL_new_ex(), PKCS7_new_ex() and
+CMS_ContentInfo_new_ex() were added in OpenSSL 3.0.
-TYPE_print_ctx() returns 1 on success or zero on failure.
+The functions DSAparams_dup(), RSAPrivateKey_dup() and RSAPublicKey_dup() were
+deprecated in 3.0.
=head1 COPYRIGHT
-Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_get0_distinguishing_id.pod b/doc/man3/X509_get0_distinguishing_id.pod
new file mode 100644
index 000000000000..7db260cdce0b
--- /dev/null
+++ b/doc/man3/X509_get0_distinguishing_id.pod
@@ -0,0 +1,73 @@
+=pod
+
+=head1 NAME
+
+X509_get0_distinguishing_id, X509_set0_distinguishing_id,
+X509_REQ_get0_distinguishing_id, X509_REQ_set0_distinguishing_id
+- get or set the Distinguishing ID for certificate operations
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509.h>
+
+ ASN1_OCTET_STRING *X509_get0_distinguishing_id(X509 *x);
+ void X509_set0_distinguishing_id(X509 *x, ASN1_OCTET_STRING *distid);
+ ASN1_OCTET_STRING *X509_REQ_get0_distinguishing_id(X509_REQ *x);
+ void X509_REQ_set0_distinguishing_id(X509_REQ *x, ASN1_OCTET_STRING *distid);
+
+=head1 DESCRIPTION
+
+The Distinguishing ID is defined in FIPS 196 as follows:
+
+=over 4
+
+=item I<Distinguishing identifier>
+
+Information which unambiguously distinguishes
+an entity in the authentication process.
+
+=back
+
+The SM2 signature algorithm requires a Distinguishing ID value when generating
+and verifying a signature, but the Ddistinguishing ID may also find other uses.
+In the context of SM2, the Distinguishing ID is often referred to as the "SM2
+ID".
+
+For the purpose off verifying a certificate or a certification request, a
+Distinguishing ID may be attached to it, so functions like L<X509_verify(3)>
+or L<X509_REQ_verify(3)> have easy access to that identity for signature
+verification.
+
+X509_get0_distinguishing_id() gets the Distinguishing ID value of a certificate
+B<x> by returning an B<ASN1_OCTET_STRING> object which should not be freed by
+the caller.
+
+X509_set0_distinguishing_id() assigns B<distid> to the certificate B<x>.
+Calling this function transfers the memory management of the value to the X509
+object, and therefore the value that has been passed in should not be freed by
+the caller after this function has been called.
+
+X509_REQ_get0_distinguishing_id() and X509_REQ_set0_distinguishing_id()
+have the same functionality as X509_get0_distinguishing_id() and
+X509_set0_distinguishing_id() except that they deal with B<X509_REQ>
+objects instead of B<X509>.
+
+=head1 RETURN VALUES
+
+X509_set0_distinguishing_id() and X509_REQ_set0_distinguishing_id() do not
+return a value.
+
+=head1 SEE ALSO
+
+L<X509_verify(3)>, L<SM2(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/X509_get0_notBefore.pod b/doc/man3/X509_get0_notBefore.pod
index 0427d4122a66..1af2920a52bc 100644
--- a/doc/man3/X509_get0_notBefore.pod
+++ b/doc/man3/X509_get0_notBefore.pod
@@ -95,7 +95,7 @@ X509_get_notBefore() and X509_get_notAfter() were deprecated in OpenSSL
Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_get0_signature.pod b/doc/man3/X509_get0_signature.pod
index 99565e2a1d80..e37a04fe8b27 100644
--- a/doc/man3/X509_get0_signature.pod
+++ b/doc/man3/X509_get0_signature.pod
@@ -3,8 +3,8 @@
=head1 NAME
X509_get0_signature, X509_REQ_set0_signature, X509_REQ_set1_signature_algo,
-X509_get_signature_nid, X509_get0_tbs_sigalg, X509_REQ_get0_signature,
-X509_REQ_get_signature_nid, X509_CRL_get0_signature, X509_CRL_get_signature_nid,
+X509_get_signature_nid, X509_get0_tbs_sigalg, X509_REQ_get0_signature,
+X509_REQ_get_signature_nid, X509_CRL_get0_signature, X509_CRL_get_signature_nid,
X509_get_signature_info, X509_SIG_INFO_get, X509_SIG_INFO_set - signature information
=head1 SYNOPSIS
@@ -132,9 +132,9 @@ were added in OpenSSL 1.1.1e.
=head1 COPYRIGHT
-Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_get0_uids.pod b/doc/man3/X509_get0_uids.pod
index 4eab26e23f44..48ae5afc4243 100644
--- a/doc/man3/X509_get0_uids.pod
+++ b/doc/man3/X509_get0_uids.pod
@@ -49,7 +49,7 @@ L<X509_verify_cert(3)>
Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_get_extension_flags.pod b/doc/man3/X509_get_extension_flags.pod
index d958b22a489b..054eab5a26c8 100644
--- a/doc/man3/X509_get_extension_flags.pod
+++ b/doc/man3/X509_get_extension_flags.pod
@@ -86,7 +86,7 @@ ASN1 object itself.
=item B<EXFLAG_NO_FINGERPRINT>
-Failed to compute the internal SHA1 hash value of the certificate.
+Failed to compute the internal SHA1 hash value of the certificate or CRL.
This may be due to malloc failure or because no SHA1 implementation was found.
=item B<EXFLAG_INVALID_POLICY>
@@ -201,7 +201,7 @@ X509_get_proxy_pathlen() were added in OpenSSL 1.1.0.
Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_get_pubkey.pod b/doc/man3/X509_get_pubkey.pod
index 2b9a956c2d04..fea0064b9bb2 100644
--- a/doc/man3/X509_get_pubkey.pod
+++ b/doc/man3/X509_get_pubkey.pod
@@ -14,7 +14,7 @@ public key
EVP_PKEY *X509_get_pubkey(X509 *x);
EVP_PKEY *X509_get0_pubkey(const X509 *x);
int X509_set_pubkey(X509 *x, EVP_PKEY *pkey);
- X509_PUBKEY *X509_get_X509_PUBKEY(X509 *x);
+ X509_PUBKEY *X509_get_X509_PUBKEY(const X509 *x);
EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req);
EVP_PKEY *X509_REQ_get0_pubkey(X509_REQ *req);
@@ -77,9 +77,9 @@ L<X509_verify_cert(3)>
=head1 COPYRIGHT
-Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_get_serialNumber.pod b/doc/man3/X509_get_serialNumber.pod
index 684adb7578b9..5594c8a284b0 100644
--- a/doc/man3/X509_get_serialNumber.pod
+++ b/doc/man3/X509_get_serialNumber.pod
@@ -64,7 +64,7 @@ The X509_get0_serialNumber() function was added in OpenSSL 1.1.0.
Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_get_subject_name.pod b/doc/man3/X509_get_subject_name.pod
index 807f9d3d9b19..64659de6ab6a 100644
--- a/doc/man3/X509_get_subject_name.pod
+++ b/doc/man3/X509_get_subject_name.pod
@@ -2,39 +2,65 @@
=head1 NAME
-X509_get_subject_name, X509_set_subject_name, X509_get_issuer_name,
-X509_set_issuer_name, X509_REQ_get_subject_name, X509_REQ_set_subject_name,
-X509_CRL_get_issuer, X509_CRL_set_issuer_name - get and set issuer or
-subject names
+X509_NAME_hash_ex, X509_NAME_hash,
+X509_get_subject_name, X509_set_subject_name, X509_subject_name_hash,
+X509_get_issuer_name, X509_set_issuer_name, X509_issuer_name_hash,
+X509_REQ_get_subject_name, X509_REQ_set_subject_name,
+X509_CRL_get_issuer, X509_CRL_set_issuer_name -
+get X509_NAME hashes or get and set issuer or subject names
=head1 SYNOPSIS
#include <openssl/x509.h>
+ unsigned long X509_NAME_hash_ex(const X509_NAME *x, OSSL_LIB_CTX *libctx,
+ const char *propq, int *ok);
+
X509_NAME *X509_get_subject_name(const X509 *x);
- int X509_set_subject_name(X509 *x, X509_NAME *name);
+ int X509_set_subject_name(X509 *x, const X509_NAME *name);
+ unsigned long X509_subject_name_hash(X509 *x);
X509_NAME *X509_get_issuer_name(const X509 *x);
- int X509_set_issuer_name(X509 *x, X509_NAME *name);
+ int X509_set_issuer_name(X509 *x, const X509_NAME *name);
+ unsigned long X509_issuer_name_hash(X509 *x);
X509_NAME *X509_REQ_get_subject_name(const X509_REQ *req);
- int X509_REQ_set_subject_name(X509_REQ *req, X509_NAME *name);
+ int X509_REQ_set_subject_name(X509_REQ *req, const X509_NAME *name);
X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl);
- int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name);
+ int X509_CRL_set_issuer_name(X509_CRL *x, const X509_NAME *name);
+
+The following macro has been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ #define X509_NAME_hash(x) X509_NAME_hash_ex(x, NULL, NULL, NULL)
=head1 DESCRIPTION
-X509_get_subject_name() returns the subject name of certificate B<x>. The
+X509_NAME_hash_ex() returns a hash value of name I<x> or 0 on failure,
+using any given library context I<libctx> and property query I<propq>.
+The I<ok> result argument may be NULL
+or else is used to return 1 for success and 0 for failure.
+Failure may happen on malloc error or if no SHA1 implementation is available.
+
+X509_NAME_hash() returns a hash value of name I<x> or 0 on failure,
+using the default library context and default property query.
+
+X509_get_subject_name() returns the subject name of certificate I<x>. The
returned value is an internal pointer which B<MUST NOT> be freed.
-X509_set_subject_name() sets the issuer name of certificate B<x> to
-B<name>. The B<name> parameter is copied internally and should be freed
+X509_set_subject_name() sets the issuer name of certificate I<x> to
+I<name>. The I<name> parameter is copied internally and should be freed
up when it is no longer needed.
-X509_get_issuer_name() and X509_set_issuer_name() are identical to
-X509_get_subject_name() and X509_set_subject_name() except the get and
-set the issuer name of B<x>.
+X509_subject_name_hash() returns a hash value of the subject name of
+certificate I<x>.
+
+X509_get_issuer_name(), X509_set_issuer_name(), and X509_issuer_name_hash()
+are identical to
+X509_get_subject_name(), X509_set_subject_name(), and X509_subject_name_hash()
+except they relate to the issuer name of I<x>.
Similarly X509_REQ_get_subject_name(), X509_REQ_set_subject_name(),
X509_CRL_get_issuer() and X509_CRL_set_issuer_name() get or set the subject
@@ -45,9 +71,21 @@ or issuer names of certificate requests of CRLs respectively.
X509_get_subject_name(), X509_get_issuer_name(), X509_REQ_get_subject_name()
and X509_CRL_get_issuer() return an B<X509_NAME> pointer.
+X509_NAME_hash_ex(), X509_NAME_hash(),
+X509_subject_name_hash() and X509_issuer_name_hash()
+return the first four bytes of the SHA1 hash value,
+converted to B<unsigned long> in little endian order,
+or 0 on failure.
+
X509_set_subject_name(), X509_set_issuer_name(), X509_REQ_set_subject_name()
and X509_CRL_set_issuer_name() return 1 for success and 0 for failure.
+=head1 BUGS
+
+In case X509_NAME_hash(), X509_subject_name_hash(), or X509_issuer_name_hash()
+returns 0 it remains unclear if this is the real hash value or due to failure.
+Better use X509_NAME_hash_ex() instead.
+
=head1 SEE ALSO
L<d2i_X509(3)>,
@@ -74,11 +112,13 @@ earlier versions.
X509_CRL_get_issuer() is a function in OpenSSL 1.1.0. It was previously
added in OpenSSL 1.0.0 as a macro.
+X509_NAME_hash() was turned into a macro and deprecated in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_get_version.pod b/doc/man3/X509_get_version.pod
index c1826ea30d70..082859e4f413 100644
--- a/doc/man3/X509_get_version.pod
+++ b/doc/man3/X509_get_version.pod
@@ -22,16 +22,18 @@ certificate request or CRL version
=head1 DESCRIPTION
X509_get_version() returns the numerical value of the version field of
-certificate B<x>. Note: this is defined by standards (X.509 et al) to be one
-less than the certificate version. So a version 3 certificate will return 2 and
-a version 1 certificate will return 0.
+certificate B<x>. These correspond to the constants B<X509_VERSION_1>,
+B<X509_VERSION_2>, and B<X509_VERSION_3>. Note: the values of these constants
+are defined by standards (X.509 et al) to be one less than the certificate
+version. So B<X509_VERSION_3> has value 2 and B<X509_VERSION_1> has value 0.
X509_set_version() sets the numerical value of the version field of certificate
B<x> to B<version>.
Similarly X509_REQ_get_version(), X509_REQ_set_version(),
X509_CRL_get_version() and X509_CRL_set_version() get and set the version
-number of certificate requests and CRLs.
+number of certificate requests and CRLs. They use constants
+B<X509_REQ_VERSION_1>, B<X509_CRL_VERSION_1>, and B<X509_CRL_VERSION_2>.
=head1 NOTES
@@ -73,9 +75,9 @@ functions in OpenSSL 1.1.0, in previous versions they were macros.
=head1 COPYRIGHT
-Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_load_http.pod b/doc/man3/X509_load_http.pod
new file mode 100644
index 000000000000..a147c43caa3f
--- /dev/null
+++ b/doc/man3/X509_load_http.pod
@@ -0,0 +1,68 @@
+=pod
+
+=head1 NAME
+
+X509_load_http,
+X509_http_nbio,
+X509_CRL_load_http,
+X509_CRL_http_nbio
+- certificate and CRL loading functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509.h>
+
+ X509 *X509_load_http(const char *url, BIO *bio, BIO *rbio, int timeout);
+ X509_CRL *X509_CRL_load_http(const char *url, BIO *bio, BIO *rbio, int timeout);
+
+The following macros have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ #define X509_http_nbio(rctx, pcert)
+ #define X509_CRL_http_nbio(rctx, pcrl)
+
+=head1 DESCRIPTION
+
+X509_load_http() and X509_CRL_load_http() loads a certificate or a CRL,
+respectively, in ASN.1 format using HTTP from the given B<url>.
+
+If B<bio> is given and B<rbio> is NULL then this BIO is used instead of an
+internal one for connecting, writing the request, and reading the response.
+If both B<bio> and B<rbio> are given (which may be memory BIOs, for instance)
+then no explicit connection is attempted,
+B<bio> is used for writing the request, and B<rbio> for reading the response.
+
+If the B<timeout> parameter is > 0 this indicates the maximum number of seconds
+to wait until the transfer is complete.
+A value of 0 enables waiting indefinitely,
+while a value < 0 immediately leads to a timeout condition.
+
+X509_http_nbio() and X509_CRL_http_nbio() are macros for backward compatibility
+that have the same effect as the functions above but with infinite timeout
+and without the possibility to specify custom BIOs.
+
+=head1 RETURN VALUES
+
+On success the function yield the loaded value, else NULL.
+Error conditions include connection/transfer timeout, parse errors, etc.
+
+=head1 SEE ALSO
+
+L<OSSL_HTTP_get(3)>
+
+=head1 HISTORY
+
+X509_load_http() and X509_CRL_load_http() were added in OpenSSL 3.0.
+X509_http_nbio() and X509_CRL_http_nbio() were deprecated in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/X509_new.pod b/doc/man3/X509_new.pod
index 4f5349931ab8..ea2b3a2cc9b0 100644
--- a/doc/man3/X509_new.pod
+++ b/doc/man3/X509_new.pod
@@ -2,14 +2,16 @@
=head1 NAME
-X509_chain_up_ref,
-X509_new, X509_free, X509_up_ref - X509 certificate ASN1 allocation functions
+X509_new, X509_new_ex,
+X509_free, X509_up_ref,
+X509_chain_up_ref - X509 certificate ASN1 allocation functions
=head1 SYNOPSIS
#include <openssl/x509.h>
X509 *X509_new(void);
+ X509 *X509_new_ex(OSSL_LIB_CTX *libctx, const char *propq);
void X509_free(X509 *a);
int X509_up_ref(X509 *a);
STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *x);
@@ -19,8 +21,16 @@ X509_new, X509_free, X509_up_ref - X509 certificate ASN1 allocation functions
The X509 ASN1 allocation routines, allocate and free an
X509 structure, which represents an X509 certificate.
-X509_new() allocates and initializes a X509 structure with reference count
-B<1>.
+X509_new_ex() allocates and initializes a X509 structure with a
+library context of I<libctx>, property query of I<propq> and a reference
+count of B<1>. Many X509 functions such as X509_check_purpose(), and
+X509_verify() use this library context to select which providers supply the
+fetched algorithms (SHA1 is used internally). This created X509 object can then
+be used when loading binary data using d2i_X509().
+
+X509_new() is similar to X509_new_ex() but sets the library context
+and property query to NULL. This results in the default (NULL) library context
+being used for any X509 operations requiring algorithm fetches.
X509_free() decrements the reference count of B<X509> structure B<a> and
frees it up if the reference count is zero. If B<a> is NULL nothing is done.
@@ -28,7 +38,7 @@ frees it up if the reference count is zero. If B<a> is NULL nothing is done.
X509_up_ref() increments the reference count of B<a>.
X509_chain_up_ref() increases the reference count of all certificates in
-chain B<x> and returns a copy of the stack.
+chain B<x> and returns a copy of the stack, or an empty stack if B<a> is NULL.
=head1 NOTES
@@ -37,20 +47,19 @@ used by several different operations each of which will free it up after
use: this avoids the need to duplicate the entire certificate structure.
The function X509_chain_up_ref() doesn't just up the reference count of
-each certificate it also returns a copy of the stack, using sk_X509_dup(),
+each certificate. It also returns a copy of the stack, using sk_X509_dup(),
but it serves a similar purpose: the returned chain persists after the
original has been freed.
=head1 RETURN VALUES
-If the allocation fails, X509_new() returns B<NULL> and sets an error
+If the allocation fails, X509_new() returns NULL and sets an error
code that can be obtained by L<ERR_get_error(3)>.
Otherwise it returns a pointer to the newly allocated structure.
X509_up_ref() returns 1 for success and 0 for failure.
-X509_chain_up_ref() returns a copy of the stack or B<NULL> if an error
-occurred.
+X509_chain_up_ref() returns a copy of the stack or NULL if an error occurred.
=head1 SEE ALSO
@@ -71,11 +80,15 @@ L<X509_sign(3)>,
L<X509V3_get_d2i(3)>,
L<X509_verify_cert(3)>
+=head1 HISTORY
+
+The function X509_new_ex() was added in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_sign.pod b/doc/man3/X509_sign.pod
index 8794c57e8d57..df66e3e5b748 100644
--- a/doc/man3/X509_sign.pod
+++ b/doc/man3/X509_sign.pod
@@ -2,9 +2,10 @@
=head1 NAME
-X509_sign, X509_sign_ctx, X509_verify, X509_REQ_sign, X509_REQ_sign_ctx,
-X509_REQ_verify, X509_CRL_sign, X509_CRL_sign_ctx, X509_CRL_verify -
-sign or verify certificate, certificate request or CRL signature
+X509_sign, X509_sign_ctx,
+X509_REQ_sign, X509_REQ_sign_ctx,
+X509_CRL_sign, X509_CRL_sign_ctx -
+sign certificate, certificate request, or CRL signature
=head1 SYNOPSIS
@@ -12,29 +13,22 @@ sign or verify certificate, certificate request or CRL signature
int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx);
- int X509_verify(X509 *a, EVP_PKEY *r);
int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md);
int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx);
- int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r);
int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md);
int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx);
- int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r);
=head1 DESCRIPTION
-X509_sign() signs certificate B<x> using private key B<pkey> and message
-digest B<md> and sets the signature in B<x>. X509_sign_ctx() also signs
-certificate B<x> but uses the parameters contained in digest context B<ctx>.
+X509_sign() signs certificate I<x> using private key I<pkey> and message
+digest I<md> and sets the signature in I<x>. X509_sign_ctx() also signs
+certificate I<x> but uses the parameters contained in digest context I<ctx>.
-X509_verify() verifies the signature of certificate B<x> using public key
-B<pkey>. Only the signature is checked: no other checks (such as certificate
-chain validity) are performed.
-
-X509_REQ_sign(), X509_REQ_sign_ctx(), X509_REQ_verify(),
-X509_CRL_sign(), X509_CRL_sign_ctx() and X509_CRL_verify() sign and verify
-certificate requests and CRLs respectively.
+X509_REQ_sign(), X509_REQ_sign_ctx(),
+X509_CRL_sign(), and X509_CRL_sign_ctx()
+sign certificate requests and CRLs, respectively.
=head1 NOTES
@@ -51,33 +45,18 @@ signature and signing will always update the encoding.
=head1 RETURN VALUES
-X509_sign(), X509_sign_ctx(), X509_REQ_sign(), X509_REQ_sign_ctx(),
-X509_CRL_sign() and X509_CRL_sign_ctx() return the size of the signature
+All functions return the size of the signature
in bytes for success and zero for failure.
-X509_verify(), X509_REQ_verify() and X509_CRL_verify() return 1 if the
-signature is valid and 0 if the signature check fails. If the signature
-could not be checked at all because it was invalid or some other error
-occurred then -1 is returned.
-
=head1 SEE ALSO
-L<d2i_X509(3)>,
L<ERR_get_error(3)>,
-L<X509_CRL_get0_by_serial(3)>,
-L<X509_get0_signature(3)>,
-L<X509_get_ext_d2i(3)>,
-L<X509_get_extension_flags(3)>,
-L<X509_get_pubkey(3)>,
-L<X509_get_subject_name(3)>,
-L<X509_get_version(3)>,
L<X509_NAME_add_entry_by_txt(3)>,
-L<X509_NAME_ENTRY_get_object(3)>,
-L<X509_NAME_get_index_by_NID(3)>,
-L<X509_NAME_print_ex(3)>,
L<X509_new(3)>,
-L<X509V3_get_d2i(3)>,
-L<X509_verify_cert(3)>
+L<X509_verify_cert(3)>,
+L<X509_verify(3)>,
+L<X509_REQ_verify_ex(3)>, L<X509_REQ_verify(3)>,
+L<X509_CRL_verify(3)>
=head1 HISTORY
@@ -85,13 +64,13 @@ The X509_sign(), X509_REQ_sign() and X509_CRL_sign() functions are
available in all versions of OpenSSL.
The X509_sign_ctx(), X509_REQ_sign_ctx()
-and X509_CRL_sign_ctx() functions were added OpenSSL 1.0.1.
+and X509_CRL_sign_ctx() functions were added in OpenSSL 1.0.1.
=head1 COPYRIGHT
-Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509_verify.pod b/doc/man3/X509_verify.pod
new file mode 100644
index 000000000000..ad22721bd1ac
--- /dev/null
+++ b/doc/man3/X509_verify.pod
@@ -0,0 +1,83 @@
+=pod
+
+=head1 NAME
+
+X509_verify, X509_self_signed,
+X509_REQ_verify_ex, X509_REQ_verify,
+X509_CRL_verify -
+verify certificate, certificate request, or CRL signature
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509.h>
+
+ int X509_verify(X509 *x, EVP_PKEY *pkey);
+ int X509_self_signed(X509 *cert, int verify_signature);
+
+ int X509_REQ_verify_ex(X509_REQ *a, EVP_PKEY *pkey, OSSL_LIB_CTX *libctx,
+ const char *propq);
+ int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r);
+ int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r);
+
+=head1 DESCRIPTION
+
+X509_verify() verifies the signature of certificate I<x> using public key
+I<pkey>. Only the signature is checked: no other checks (such as certificate
+chain validity) are performed.
+
+X509_self_signed() checks whether certificate I<cert> is self-signed.
+For success the issuer and subject names must match, the components of the
+authority key identifier (if present) must match the subject key identifier etc.
+The signature itself is actually verified only if B<verify_signature> is 1, as
+for explicitly trusted certificates this verification is not worth the effort.
+
+X509_REQ_verify_ex(), X509_REQ_verify() and X509_CRL_verify()
+verify the signatures of certificate requests and CRLs, respectively.
+
+=head1 RETURN VALUES
+
+X509_verify(),
+X509_REQ_verify_ex(), X509_REQ_verify() and X509_CRL_verify()
+return 1 if the signature is valid and 0 if the signature check fails.
+If the signature could not be checked at all because it was ill-formed,
+the certificate or the request was not complete or some other error occurred
+then -1 is returned.
+
+X509_self_signed() returns the same values but also returns 1
+if all respective fields match and B<verify_signature> is 0.
+
+=head1 SEE ALSO
+
+L<d2i_X509(3)>,
+L<ERR_get_error(3)>,
+L<X509_CRL_get0_by_serial(3)>,
+L<X509_get0_signature(3)>,
+L<X509_get_ext_d2i(3)>,
+L<X509_get_extension_flags(3)>,
+L<X509_get_pubkey(3)>,
+L<X509_get_subject_name(3)>,
+L<X509_get_version(3)>,
+L<X509_NAME_ENTRY_get_object(3)>,
+L<X509_NAME_get_index_by_NID(3)>,
+L<X509_NAME_print_ex(3)>,
+L<X509V3_get_d2i(3)>,
+L<X509_verify_cert(3)>,
+L<OSSL_LIB_CTX(3)>
+
+=head1 HISTORY
+
+The X509_verify(), X509_REQ_verify(), and X509_CRL_verify()
+functions are available in all versions of OpenSSL.
+
+X509_REQ_verify_ex(), and X509_self_signed() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/X509_verify_cert.pod b/doc/man3/X509_verify_cert.pod
index 74acf8df71fe..d54acfdb0bd4 100644
--- a/doc/man3/X509_verify_cert.pod
+++ b/doc/man3/X509_verify_cert.pod
@@ -2,57 +2,96 @@
=head1 NAME
-X509_verify_cert - discover and verify X509 certificate chain
+X509_build_chain,
+X509_verify_cert,
+X509_STORE_CTX_verify - build and verify X509 certificate chain
=head1 SYNOPSIS
- #include <openssl/x509.h>
+ #include <openssl/x509_vfy.h>
+ STACK_OF(X509) *X509_build_chain(X509 *target, STACK_OF(X509) *certs,
+ X509_STORE *store, int with_self_signed,
+ OSSL_LIB_CTX *libctx, const char *propq);
int X509_verify_cert(X509_STORE_CTX *ctx);
+ int X509_STORE_CTX_verify(X509_STORE_CTX *ctx);
=head1 DESCRIPTION
-The X509_verify_cert() function attempts to discover and validate a
-certificate chain based on parameters in B<ctx>. A complete description of
-the process is contained in the L<verify(1)> manual page.
-
-=head1 RETURN VALUES
+X509_build_chain() builds a certificate chain starting from I<target>
+using the optional list of intermediate CA certificates I<certs>.
+If I<store> is NULL it builds the chain as far down as possible, ignoring errors.
+Else the chain must reach a trust anchor contained in I<store>.
+It internally uses a B<X509_STORE_CTX> structure associated with the library
+context I<libctx> and property query string I<propq>, both of which may be NULL.
+In case there is more than one possibility for the chain, only one is taken.
-If a complete chain can be built and validated this function returns 1,
-otherwise it return zero, in exceptional circumstances it can also
-return a negative code.
+On success it returns a pointer to a new stack of (up_ref'ed) certificates
+starting with I<target> and followed by all available intermediate certificates.
+A self-signed trust anchor is included only if I<target> is the trust anchor
+of I<with_self_signed> is 1.
+If a non-NULL stack is returned the caller is responsible for freeing it.
-If the function fails additional error information can be obtained by
-examining B<ctx> using, for example X509_STORE_CTX_get_error().
-
-=head1 NOTES
+The X509_verify_cert() function attempts to discover and validate a
+certificate chain based on parameters in I<ctx>.
+The verification context, of type B<X509_STORE_CTX>, can be constructed
+using L<X509_STORE_CTX_new(3)> and L<X509_STORE_CTX_init(3)>.
+It usually includes a target certificate to be verified,
+a set of certificates serving as trust anchors,
+a list of non-trusted certificates that may be helpful for chain construction,
+flags such as X509_V_FLAG_X509_STRICT, and various other optional components
+such as a callback function that allows customizing the verification outcome.
+A complete description of the certificate verification process is contained in
+the L<openssl-verification-options(1)> manual page.
Applications rarely call this function directly but it is used by
OpenSSL internally for certificate validation, in both the S/MIME and
SSL/TLS code.
A negative return value from X509_verify_cert() can occur if it is invoked
-incorrectly, such as with no certificate set in B<ctx>, or when it is called
-twice in succession without reinitialising B<ctx> for the second call.
-A negative return value can also happen due to internal resource problems or if
-a retry operation is requested during internal lookups (which never happens
-with standard lookup methods).
-Applications must check for <= 0 return value on error.
+incorrectly, such as with no certificate set in I<ctx>, or when it is called
+twice in succession without reinitialising I<ctx> for the second call.
+A negative return value can also happen due to internal resource problems
+or because an internal inconsistency has been detected.
+Applications must interpret any return value <= 0 as an error.
+
+The X509_STORE_CTX_verify() behaves like X509_verify_cert() except that its
+target certificate is the first element of the list of untrusted certificates
+in I<ctx> unless a target certificate is set explicitly.
-=head1 BUGS
+=head1 RETURN VALUES
+
+X509_build_chain() returns NULL on error, else a stack of certificates.
+
+Both X509_verify_cert() and X509_STORE_CTX_verify()
+return 1 if a complete chain can be built and validated,
+otherwise they return 0, and in exceptional circumstances (such as malloc
+failure and internal errors) they can also return a negative code.
-This function uses the header B<x509.h> as opposed to most chain verification
-functions which use B<x509_vfy.h>.
+If a complete chain can be built and validated both functions return 1.
+If the certificate must be rejected on the basis of the data available
+or any required certificate status data is not available they return 0.
+If no definite answer possible they usually return a negative code.
+
+On error or failure additional error information can be obtained by
+examining I<ctx> using, for example, L<X509_STORE_CTX_get_error(3)>. Even if
+verification indicated success, the stored error code may be different from
+X509_V_OK, likely because a verification callback function has waived the error.
=head1 SEE ALSO
+L<X509_STORE_CTX_new(3)>, L<X509_STORE_CTX_init(3)>,
L<X509_STORE_CTX_get_error(3)>
+=head1 HISTORY
+
+X509_build_chain() and X509_STORE_CTX_verify() were added in OpenSSL 3.0.
+
=head1 COPYRIGHT
-Copyright 2009-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2009-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/X509v3_get_ext_by_NID.pod b/doc/man3/X509v3_get_ext_by_NID.pod
index 67a7df58823d..4010a71c4371 100644
--- a/doc/man3/X509v3_get_ext_by_NID.pod
+++ b/doc/man3/X509v3_get_ext_by_NID.pod
@@ -41,7 +41,8 @@ X509_REVOKED_add_ext - extension stack utility functions
int X509_CRL_get_ext_count(const X509_CRL *x);
X509_EXTENSION *X509_CRL_get_ext(const X509_CRL *x, int loc);
int X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, int lastpos);
- int X509_CRL_get_ext_by_OBJ(const X509_CRL *x, const ASN1_OBJECT *obj, int lastpos);
+ int X509_CRL_get_ext_by_OBJ(const X509_CRL *x, const ASN1_OBJECT *obj,
+ int lastpos);
int X509_CRL_get_ext_by_critical(const X509_CRL *x, int crit, int lastpos);
X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc);
int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc);
@@ -57,72 +58,81 @@ X509_REVOKED_add_ext - extension stack utility functions
=head1 DESCRIPTION
-X509v3_get_ext_count() retrieves the number of extensions in B<x>.
+X509v3_get_ext_count() retrieves the number of extensions in I<x>.
-X509v3_get_ext() retrieves extension B<loc> from B<x>. The index B<loc>
-can take any value from B<0> to X509_get_ext_count(x) - 1. The returned
-extension is an internal pointer which B<must not> be freed up by the
+X509v3_get_ext() retrieves extension I<loc> from I<x>. The index I<loc>
+can take any value from 0 to X509_get_ext_count(I<x>) - 1. The returned
+extension is an internal pointer which B<MUST NOT> be freed by the
application.
X509v3_get_ext_by_NID() and X509v3_get_ext_by_OBJ() look for an extension
-with B<nid> or B<obj> from extension stack B<x>. The search starts from the
-extension after B<lastpos> or from the beginning if <lastpos> is B<-1>. If
-the extension is found its index is returned otherwise B<-1> is returned.
+with I<nid> or I<obj> from extension STACK I<x>. The search starts from the
+extension after I<lastpos> or from the beginning if I<lastpos> is -1. If
+the extension is found, its index is returned, otherwise -1 is returned.
X509v3_get_ext_by_critical() is similar to X509v3_get_ext_by_NID() except it
-looks for an extension of criticality B<crit>. A zero value for B<crit>
-looks for a non-critical extension a nonzero value looks for a critical
+looks for an extension of criticality I<crit>. A zero value for I<crit>
+looks for a non-critical extension. A nonzero value looks for a critical
extension.
-X509v3_delete_ext() deletes the extension with index B<loc> from B<x>. The
-deleted extension is returned and must be freed by the caller. If B<loc>
-is in invalid index value B<NULL> is returned.
+X509v3_delete_ext() deletes the extension with index I<loc> from I<x>.
+The deleted extension is returned and must be freed by the caller.
+If I<loc> is an invalid index value, NULL is returned.
-X509v3_add_ext() adds extension B<ex> to stack B<*x> at position B<loc>. If
-B<loc> is B<-1> the new extension is added to the end. If B<*x> is B<NULL>
-a new stack will be allocated. The passed extension B<ex> is duplicated
+X509v3_add_ext() adds extension I<ex> to STACK I<*x> at position I<loc>. If
+I<loc> is -1, the new extension is added to the end. If I<*x> is NULL,
+a new STACK will be allocated. The passed extension I<ex> is duplicated
internally so it must be freed after use.
X509_get_ext_count(), X509_get_ext(), X509_get_ext_by_NID(),
X509_get_ext_by_OBJ(), X509_get_ext_by_critical(), X509_delete_ext()
-and X509_add_ext() operate on the extensions of certificate B<x> they are
+and X509_add_ext() operate on the extensions of certificate I<x>. They are
otherwise identical to the X509v3 functions.
X509_CRL_get_ext_count(), X509_CRL_get_ext(), X509_CRL_get_ext_by_NID(),
X509_CRL_get_ext_by_OBJ(), X509_CRL_get_ext_by_critical(),
X509_CRL_delete_ext() and X509_CRL_add_ext() operate on the extensions of
-CRL B<x> they are otherwise identical to the X509v3 functions.
+CRL I<x>. They are otherwise identical to the X509v3 functions.
X509_REVOKED_get_ext_count(), X509_REVOKED_get_ext(),
X509_REVOKED_get_ext_by_NID(), X509_REVOKED_get_ext_by_OBJ(),
X509_REVOKED_get_ext_by_critical(), X509_REVOKED_delete_ext() and
-X509_REVOKED_add_ext() operate on the extensions of CRL entry B<x>
-they are otherwise identical to the X509v3 functions.
+X509_REVOKED_add_ext() operate on the extensions of CRL entry I<x>.
+They are otherwise identical to the X509v3 functions.
=head1 NOTES
-These functions are used to examine stacks of extensions directly. Many
-applications will want to parse or encode and add an extension: they should
-use the extension encode and decode functions instead such as
+These functions are used to examine stacks of extensions directly.
+Applications that want to parse or encode and add an extension should
+use the extension encode and decode functions instead, such as
X509_add1_ext_i2d() and X509_get_ext_d2i().
-Extension indices start from zero, so a zero index return value is B<not> an
-error. These search functions start from the extension B<after> the B<lastpos>
-parameter so it should initially be set to B<-1>, if it is set to zero the
-initial extension will not be checked.
+For X509v3_get_ext_by_NID(), X509v3_get_ext_by_OBJ(),
+X509v3_get_ext_by_critical() and its variants, a zero index return value
+is not an error since extension STACK I<x> indices start from zero.
+These search functions start from the extension B<after> the I<lastpos> parameter
+so it should initially be set to -1. If it is set to zero, the initial extension
+will not be checked.
+
+X509v3_delete_ext() and its variants are a bit counter-intuitive
+because these functions do not free the extension they delete.
+They return an B<X509_EXTENSION> object which must be explicitly freed
+using X509_EXTENSION_free().
=head1 RETURN VALUES
-X509v3_get_ext_count() returns the extension count.
+X509v3_get_ext_count() returns the extension count or 0 for failure.
X509v3_get_ext(), X509v3_delete_ext() and X509_delete_ext() return an
-B<X509_EXTENSION> pointer or B<NULL> if an error occurs.
+B<X509_EXTENSION> structure or NULL if an error occurs.
+
+X509v3_get_ext_by_OBJ() and X509v3_get_ext_by_critical() return
+the extension index or -1 if an error occurs.
-X509v3_get_ext_by_NID() X509v3_get_ext_by_OBJ() and
-X509v3_get_ext_by_critical() return the an extension index or B<-1> if an
+X509v3_get_ext_by_NID() returns the extension index or negative values if an
error occurs.
-X509v3_add_ext() returns a stack of extensions or B<NULL> on error.
+X509v3_add_ext() returns a STACK of extensions or NULL on error.
X509_add_ext() returns 1 on success and 0 on error.
@@ -132,9 +142,9 @@ L<X509V3_get_d2i(3)>
=head1 COPYRIGHT
-Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/b2i_PVK_bio_ex.pod b/doc/man3/b2i_PVK_bio_ex.pod
new file mode 100644
index 000000000000..bd670b26140f
--- /dev/null
+++ b/doc/man3/b2i_PVK_bio_ex.pod
@@ -0,0 +1,69 @@
+=pod
+
+=head1 NAME
+
+b2i_PVK_bio, b2i_PVK_bio_ex, i2b_PVK_bio, i2b_PVK_bio_ex - Decode and encode
+functions for reading and writing MSBLOB format private keys
+
+=head1 SYNOPSIS
+
+ #include <openssl/pem.h>
+
+ EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u);
+ EVP_PKEY *b2i_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ int i2b_PVK_bio(BIO *out, const EVP_PKEY *pk, int enclevel,
+ pem_password_cb *cb, void *u);
+ int i2b_PVK_bio_ex(BIO *out, const EVP_PKEY *pk, int enclevel,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+=head1 DESCRIPTION
+
+b2i_PVK_bio_ex() decodes a private key of MSBLOB format read from a B<BIO>. It
+attempts to automatically determine the key type. If the key is encrypted then
+I<cb> is called with the user data I<u> in order to obtain a password to decrypt
+the key. The supplied library context I<libctx> and property query
+string I<propq> are used in any decrypt operation.
+
+b2i_PVK_bio() does the same as b2i_PVK_bio_ex() except that the default
+library context and property query string are used.
+
+i2b_PVK_bio_ex() encodes I<pk> using MSBLOB format. If I<enclevel> is 1 then
+a password obtained via I<pem_password_cb> is used to encrypt the private key.
+If I<enclevel> is 0 then no encryption is applied. The user data in I<u> is
+passed to the password callback. The supplied library context I<libctx> and
+property query string I<propq> are used in any decrypt operation.
+
+i2b_PVK_bio() does the same as i2b_PVK_bio_ex() except that the default
+library context and property query string are used.
+
+=head1 RETURN VALUES
+
+The b2i_PVK_bio() and b2i_PVK_bio_ex() functions return a valid B<EVP_KEY>
+structure or B<NULL> if an error occurs. The error code can be obtained by calling
+L<ERR_get_error(3)>.
+
+i2b_PVK_bio() and i2b_PVK_bio_ex() return the number of bytes successfully
+encoded or a negative value if an error occurs. The error code can be obtained
+by calling L<ERR_get_error(3)>.
+
+=head1 SEE ALSO
+
+L<crypto(7)>,
+L<d2i_PKCS8PrivateKey_bio(3)>
+
+=head1 HISTORY
+
+b2i_PVK_bio_ex() and i2b_PVK_bio_ex() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/d2i_DHparams.pod b/doc/man3/d2i_DHparams.pod
deleted file mode 100644
index 5be0c2986e53..000000000000
--- a/doc/man3/d2i_DHparams.pod
+++ /dev/null
@@ -1,42 +0,0 @@
-=pod
-
-=head1 NAME
-
-d2i_DHparams, i2d_DHparams - PKCS#3 DH parameter functions
-
-=head1 SYNOPSIS
-
- #include <openssl/dh.h>
-
- DH *d2i_DHparams(DH **a, const unsigned char **pp, long length);
- int i2d_DHparams(DH *a, unsigned char **pp);
-
-=head1 DESCRIPTION
-
-These functions decode and encode PKCS#3 DH parameters using the
-DHparameter structure described in PKCS#3.
-
-Otherwise these behave in a similar way to d2i_X509() and i2d_X509()
-described in the L<d2i_X509(3)> manual page.
-
-=head1 RETURN VALUES
-
-d2i_DHparams() returns a valid B<DH> structure or NULL if an error occurred.
-
-i2d_DHparams() returns the length of encoded data on success or a value which
-is less than or equal to 0 on error.
-
-=head1 SEE ALSO
-
-L<d2i_X509(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man3/d2i_PKCS8PrivateKey_bio.pod b/doc/man3/d2i_PKCS8PrivateKey_bio.pod
index 43a218a26a11..5b5371b70f19 100644
--- a/doc/man3/d2i_PKCS8PrivateKey_bio.pod
+++ b/doc/man3/d2i_PKCS8PrivateKey_bio.pod
@@ -13,19 +13,19 @@ i2d_PKCS8PrivateKey_nid_bio, i2d_PKCS8PrivateKey_nid_fp - PKCS#8 format private
EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u);
EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u);
- int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
+ int i2d_PKCS8PrivateKey_bio(BIO *bp, const EVP_PKEY *x, const EVP_CIPHER *enc,
char *kstr, int klen,
pem_password_cb *cb, void *u);
- int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
+ int i2d_PKCS8PrivateKey_fp(FILE *fp, const EVP_PKEY *x, const EVP_CIPHER *enc,
char *kstr, int klen,
pem_password_cb *cb, void *u);
- int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid,
+ int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, const EVP_PKEY *x, int nid,
char *kstr, int klen,
pem_password_cb *cb, void *u);
- int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid,
+ int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, const EVP_PKEY *x, int nid,
char *kstr, int klen,
pem_password_cb *cb, void *u);
@@ -66,7 +66,7 @@ L<passphrase-encoding(7)>
Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/d2i_PrivateKey.pod b/doc/man3/d2i_PrivateKey.pod
index e7272595bc40..fe78d5bc6f13 100644
--- a/doc/man3/d2i_PrivateKey.pod
+++ b/doc/man3/d2i_PrivateKey.pod
@@ -2,43 +2,87 @@
=head1 NAME
-d2i_PrivateKey, d2i_PublicKey, d2i_AutoPrivateKey,
-i2d_PrivateKey, i2d_PublicKey,
-d2i_PrivateKey_bio, d2i_PrivateKey_fp
+d2i_PrivateKey_ex, d2i_PrivateKey, d2i_PublicKey, d2i_KeyParams,
+d2i_AutoPrivateKey_ex, d2i_AutoPrivateKey, i2d_PrivateKey, i2d_PublicKey,
+i2d_KeyParams, i2d_KeyParams_bio, d2i_PrivateKey_ex_bio, d2i_PrivateKey_bio,
+d2i_PrivateKey_ex_fp, d2i_PrivateKey_fp, d2i_KeyParams_bio, i2d_PrivateKey_bio,
+i2d_PrivateKey_fp
- decode and encode functions for reading and saving EVP_PKEY structures
=head1 SYNOPSIS
#include <openssl/evp.h>
+ EVP_PKEY *d2i_PrivateKey_ex(int type, EVP_PKEY **a, const unsigned char **pp,
+ long length, OSSL_LIB_CTX *libctx,
+ const char *propq);
EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
long length);
EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp,
long length);
+ EVP_PKEY *d2i_KeyParams(int type, EVP_PKEY **a, const unsigned char **pp,
+ long length);
+ EVP_PKEY *d2i_AutoPrivateKey_ex(EVP_PKEY **a, const unsigned char **pp,
+ long length, OSSL_LIB_CTX *libctx,
+ const char *propq);
EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
long length);
- int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp);
- int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp);
+ int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp);
+ int i2d_PublicKey(const EVP_PKEY *a, unsigned char **pp);
+ int i2d_KeyParams(const EVP_PKEY *a, unsigned char **pp);
+ int i2d_KeyParams_bio(BIO *bp, const EVP_PKEY *pkey);
+ EVP_PKEY *d2i_KeyParams_bio(int type, EVP_PKEY **a, BIO *in);
+
+
+ #include <openssl/x509.h>
+
+ EVP_PKEY *d2i_PrivateKey_ex_bio(BIO *bp, EVP_PKEY **a, OSSL_LIB_CTX *libctx,
+ const char *propq);
EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a);
- EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a)
+ EVP_PKEY *d2i_PrivateKey_ex_fp(FILE *fp, EVP_PKEY **a, OSSL_LIB_CTX *libctx,
+ const char *propq);
+ EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a);
+
+ int i2d_PrivateKey_bio(BIO *bp, const EVP_PKEY *pkey);
+ int i2d_PrivateKey_fp(FILE *fp, const EVP_PKEY *pkey);
=head1 DESCRIPTION
-d2i_PrivateKey() decodes a private key using algorithm B<type>. It attempts to
-use any key specific format or PKCS#8 unencrypted PrivateKeyInfo format. The
-B<type> parameter should be a public key algorithm constant such as
-B<EVP_PKEY_RSA>. An error occurs if the decoded key does not match B<type>.
+d2i_PrivateKey_ex() decodes a private key using algorithm I<type>. It attempts
+to use any key-specific format or PKCS#8 unencrypted PrivateKeyInfo format.
+The I<type> parameter should be a public key algorithm constant such as
+B<EVP_PKEY_RSA>. An error occurs if the decoded key does not match I<type>. Some
+private key decoding implementations may use cryptographic algorithms (for
+example to automatically derive the public key if it is not explicitly
+included in the encoding). In this case the supplied library context I<libctx>
+and property query string I<propq> are used.
+If successful and the I<a> parameter is not NULL the function assigns the
+returned B<EVP_PKEY> structure pointer to I<*a>, overwriting any previous value.
+
+d2i_PrivateKey() does the same as d2i_PrivateKey_ex() except that the default
+library context and property query string are used.
d2i_PublicKey() does the same for public keys.
+d2i_KeyParams() does the same for key parameters.
+
+The d2i_PrivateKey_ex_bio() and d2i_PrivateKey_bio() functions are similar to
+d2i_PrivateKey_ex() and d2i_PrivateKey() respectively except that they decode
+the data read from the given BIO. The d2i_PrivateKey_ex_fp() and
+d2i_PrivateKey_fp() functions are the same except that they read the data from
+the given FILE.
-d2i_AutoPrivateKey() is similar to d2i_PrivateKey() except it attempts to
-automatically detect the private key format.
+d2i_AutoPrivateKey_ex() and d2i_AutoPrivateKey() are similar to
+d2i_PrivateKey_ex() and d2i_PrivateKey() respectively except that they attempt
+to automatically detect the private key format.
-i2d_PrivateKey() encodes B<key>. It uses a key specific format or, if none is
+i2d_PrivateKey() encodes I<a>. It uses a key specific format or, if none is
defined for that key type, PKCS#8 unencrypted PrivateKeyInfo format.
i2d_PublicKey() does the same for public keys.
-
+i2d_KeyParams() does the same for key parameters.
These functions are similar to the d2i_X509() functions; see L<d2i_X509(3)>.
+i2d_PrivateKey_bio() and i2d_PrivateKey_fp() do the same thing except that they
+encode to a B<BIO> or B<FILE> respectively. Again, these work similarly to the
+functions described in L<d2i_X509(3)>.
=head1 NOTES
@@ -50,34 +94,40 @@ All these functions use DER format and unencrypted keys. Applications wishing
to encrypt or decrypt private keys should use other functions such as
d2i_PKCS8PrivateKey() instead.
-If the B<*a> is not NULL when calling d2i_PrivateKey() or d2i_AutoPrivateKey()
-(i.e. an existing structure is being reused) and the key format is PKCS#8
-then B<*a> will be freed and replaced on a successful call.
-
-To decode a key with type B<EVP_PKEY_EC>, d2i_PublicKey() requires B<*a> to be
+To decode a key with type B<EVP_PKEY_EC>, d2i_PublicKey() requires I<*a> to be
a non-NULL EVP_PKEY structure assigned an EC_KEY structure referencing the proper
EC_GROUP.
=head1 RETURN VALUES
-The d2i_PrivateKey(), d2i_AutoPrivateKey(), d2i_PrivateKey_bio(), d2i_PrivateKey_fp(),
-and d2i_PublicKey() functions return a valid B<EVP_KEY> structure or B<NULL> if an
-error occurs. The error code can be obtained by calling L<ERR_get_error(3)>.
+The d2i_PrivateKey_ex(), d2i_PrivateKey(), d2i_AutoPrivateKey_ex(),
+d2i_AutoPrivateKey(), d2i_PrivateKey_ex_bio(), d2i_PrivateKey_bio(),
+d2i_PrivateKey_ex_fp(), d2i_PrivateKey_fp(), d2i_PublicKey(), d2i_KeyParams()
+and d2i_KeyParams_bio() functions return a valid B<EVP_PKEY> structure or NULL if
+an error occurs. The error code can be obtained by calling L<ERR_get_error(3)>.
+
+i2d_PrivateKey(), i2d_PublicKey() and i2d_KeyParams() return the number of
+bytes successfully encoded or a negative value if an error occurs. The error
+code can be obtained by calling L<ERR_get_error(3)>.
-i2d_PrivateKey() and i2d_PublicKey() return the number of bytes successfully
-encoded or a negative value if an error occurs. The error code can be obtained
-by calling L<ERR_get_error(3)>.
+i2d_PrivateKey_bio(), i2d_PrivateKey_fp() and i2d_KeyParams_bio() return 1 if
+successfully encoded or zero if an error occurs.
=head1 SEE ALSO
L<crypto(7)>,
L<d2i_PKCS8PrivateKey_bio(3)>
+=head1 HISTORY
+
+d2i_PrivateKey_ex(), d2i_PrivateKey_ex_bio(), d2i_PrivateKey_ex_fp(), and
+d2i_AutoPrivateKey_ex() were added in OpenSSL 3.0.
+
=head1 COPYRIGHT
Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/d2i_RSAPrivateKey.pod b/doc/man3/d2i_RSAPrivateKey.pod
new file mode 100644
index 000000000000..b4f5b4660900
--- /dev/null
+++ b/doc/man3/d2i_RSAPrivateKey.pod
@@ -0,0 +1,319 @@
+=pod
+
+=begin comment
+
+Any deprecated keypair/params d2i or i2d functions are collected on this page.
+
+=end comment
+
+=head1 NAME
+
+d2i_DSAPrivateKey,
+d2i_DSAPrivateKey_bio,
+d2i_DSAPrivateKey_fp,
+d2i_DSAPublicKey,
+d2i_DSA_PUBKEY,
+d2i_DSA_PUBKEY_bio,
+d2i_DSA_PUBKEY_fp,
+d2i_DSAparams,
+d2i_RSAPrivateKey,
+d2i_RSAPrivateKey_bio,
+d2i_RSAPrivateKey_fp,
+d2i_RSAPublicKey,
+d2i_RSAPublicKey_bio,
+d2i_RSAPublicKey_fp,
+d2i_RSA_PUBKEY,
+d2i_RSA_PUBKEY_bio,
+d2i_RSA_PUBKEY_fp,
+d2i_DHparams,
+d2i_DHparams_bio,
+d2i_DHparams_fp,
+d2i_ECPKParameters,
+d2i_ECParameters,
+d2i_ECPrivateKey,
+d2i_ECPrivateKey_bio,
+d2i_ECPrivateKey_fp,
+d2i_EC_PUBKEY,
+d2i_EC_PUBKEY_bio,
+d2i_EC_PUBKEY_fp,
+i2d_RSAPrivateKey,
+i2d_RSAPrivateKey_bio,
+i2d_RSAPrivateKey_fp,
+i2d_RSAPublicKey,
+i2d_RSAPublicKey_bio,
+i2d_RSAPublicKey_fp,
+i2d_RSA_PUBKEY,
+i2d_RSA_PUBKEY_bio,
+i2d_RSA_PUBKEY_fp,
+i2d_DHparams,
+i2d_DHparams_bio,
+i2d_DHparams_fp,
+i2d_DSAPrivateKey,
+i2d_DSAPrivateKey_bio,
+i2d_DSAPrivateKey_fp,
+i2d_DSAPublicKey,
+i2d_DSA_PUBKEY,
+i2d_DSA_PUBKEY_bio,
+i2d_DSA_PUBKEY_fp,
+i2d_DSAparams,
+i2d_ECPKParameters,
+i2d_ECParameters,
+i2d_ECPrivateKey,
+i2d_ECPrivateKey_bio,
+i2d_ECPrivateKey_fp,
+i2d_EC_PUBKEY,
+i2d_EC_PUBKEY_bio,
+i2d_EC_PUBKEY_fp
+- DEPRECATED
+
+=head1 SYNOPSIS
+
+=for openssl generic
+
+The following functions have been deprecated since OpenSSL 3.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ TYPE *d2i_TYPEPrivateKey(TYPE **a, const unsigned char **ppin, long length);
+ TYPE *d2i_TYPEPrivateKey_bio(BIO *bp, TYPE **a);
+ TYPE *d2i_TYPEPrivateKey_fp(FILE *fp, TYPE **a);
+ TYPE *d2i_TYPEPublicKey(TYPE **a, const unsigned char **ppin, long length);
+ TYPE *d2i_TYPEPublicKey_bio(BIO *bp, TYPE **a);
+ TYPE *d2i_TYPEPublicKey_fp(FILE *fp, TYPE **a);
+ TYPE *d2i_TYPEparams(TYPE **a, const unsigned char **ppin, long length);
+ TYPE *d2i_TYPEparams_bio(BIO *bp, TYPE **a);
+ TYPE *d2i_TYPEparams_fp(FILE *fp, TYPE **a);
+ TYPE *d2i_TYPE_PUBKEY(TYPE **a, const unsigned char **ppin, long length);
+ TYPE *d2i_TYPE_PUBKEY_bio(BIO *bp, TYPE **a);
+ TYPE *d2i_TYPE_PUBKEY_fp(FILE *fp, TYPE **a);
+
+ int i2d_TYPEPrivateKey(const TYPE *a, unsigned char **ppout);
+ int i2d_TYPEPrivateKey(TYPE *a, unsigned char **ppout);
+ int i2d_TYPEPrivateKey_fp(FILE *fp, const TYPE *a);
+ int i2d_TYPEPrivateKey_fp(FILE *fp, TYPE *a);
+ int i2d_TYPEPrivateKey_bio(BIO *bp, const TYPE *a);
+ int i2d_TYPEPrivateKey_bio(BIO *bp, TYPE *a);
+ int i2d_TYPEPublicKey(const TYPE *a, unsigned char **ppout);
+ int i2d_TYPEPublicKey(TYPE *a, unsigned char **ppout);
+ int i2d_TYPEPublicKey_fp(FILE *fp, const TYPE *a);
+ int i2d_TYPEPublicKey_fp(FILE *fp, TYPE *a);
+ int i2d_TYPEPublicKey_bio(BIO *bp, const TYPE *a);
+ int i2d_TYPEPublicKey_bio(BIO *bp, TYPE *a);
+ int i2d_TYPEparams(const TYPE *a, unsigned char **ppout);
+ int i2d_TYPEparams(TYPE *a, unsigned char **ppout);
+ int i2d_TYPEparams_fp(FILE *fp, const TYPE *a);
+ int i2d_TYPEparams_fp(FILE *fp, TYPE *a);
+ int i2d_TYPEparams_bio(BIO *bp, const TYPE *a);
+ int i2d_TYPEparams_bio(BIO *bp, TYPE *a);
+ int i2d_TYPE_PUBKEY(const TYPE *a, unsigned char **ppout);
+ int i2d_TYPE_PUBKEY(TYPE *a, unsigned char **ppout);
+ int i2d_TYPE_PUBKEY_fp(FILE *fp, const TYPE *a);
+ int i2d_TYPE_PUBKEY_fp(FILE *fp, TYPE *a);
+ int i2d_TYPE_PUBKEY_bio(BIO *bp, const TYPE *a);
+ int i2d_TYPE_PUBKEY_bio(BIO *bp, TYPE *a);
+
+=head1 DESCRIPTION
+
+All functions described here are deprecated. Please use L<OSSL_DECODER(3)>
+instead of the B<d2i> functions and L<OSSL_ENCODER(3)> instead of the B<i2d>
+functions. See L</Migration> below.
+
+In the description here, B<I<TYPE>> is used a placeholder for any of the
+OpenSSL datatypes, such as B<RSA>.
+The function parameters I<ppin> and I<ppout> are generally either both named
+I<pp> in the headers, or I<in> and I<out>.
+
+All the functions here behave the way that's described in L<d2i_X509(3)>.
+
+Please note that not all functions in the synopsis are available for all key
+types. For example, there are no d2i_RSAparams() or i2d_RSAparams(),
+because the PKCS#1 B<RSA> structure doesn't include any key parameters.
+
+B<d2i_I<TYPE>PrivateKey>() and derivates thereof decode DER encoded
+B<I<TYPE>> private key data organized in a type specific structure.
+
+B<d2i_I<TYPE>PublicKey>() and derivates thereof decode DER encoded
+B<I<TYPE>> public key data organized in a type specific structure.
+
+B<d2i_I<TYPE>params>() and derivates thereof decode DER encoded B<I<TYPE>>
+key parameters organized in a type specific structure.
+
+B<d2i_I<TYPE>_PUBKEY>() and derivates thereof decode DER encoded B<I<TYPE>>
+public key data organized in a B<SubjectPublicKeyInfo> structure.
+
+B<i2d_I<TYPE>PrivateKey>() and derivates thereof encode the private key
+B<I<TYPE>> data into a type specific DER encoded structure.
+
+B<i2d_I<TYPE>PublicKey>() and derivates thereof encode the public key
+B<I<TYPE>> data into a type specific DER encoded structure.
+
+B<i2d_I<TYPE>params>() and derivates thereof encode the B<I<TYPE>> key
+parameters data into a type specific DER encoded structure.
+
+B<i2d_I<TYPE>_PUBKEY>() and derivates thereof encode the public key
+B<I<TYPE>> data into a DER encoded B<SubjectPublicKeyInfo> structure.
+
+For example, d2i_RSAPrivateKey() and d2i_RSAPublicKey() expects the
+structure defined by PKCS#1.
+Similarly, i2d_RSAPrivateKey() and i2d_RSAPublicKey() produce DER encoded
+string organized according to PKCS#1.
+
+=head2 Migration
+
+Migration from the diverse B<I<TYPE>>s requires using corresponding new
+OpenSSL types. For all B<I<TYPE>>s described here, the corresponding new
+type is B<EVP_PKEY>. The rest of this section assumes that this has been
+done, exactly how to do that is described elsewhere.
+
+There are two migration paths:
+
+=over 4
+
+=item *
+
+Replace
+b<d2i_I<TYPE>PrivateKey()> with L<d2i_PrivateKey(3)>,
+b<d2i_I<TYPE>PublicKey()> with L<d2i_PublicKey(3)>,
+b<d2i_I<TYPE>params()> with L<d2i_KeyParams(3)>,
+b<d2i_I<TYPE>_PUBKEY()> with L<d2i_PUBKEY(3)>,
+b<i2d_I<TYPE>PrivateKey()> with L<i2d_PrivateKey(3)>,
+b<i2d_I<TYPE>PublicKey()> with L<i2d_PublicKey(3)>,
+b<i2d_I<TYPE>params()> with L<i2d_KeyParams(3)>,
+b<i2d_I<TYPE>_PUBKEY()> with L<i2d_PUBKEY(3)>.
+A caveat is that L<i2d_PrivateKey(3)> may output a DER encoded PKCS#8
+outermost structure instead of the type specific structure, and that
+L<d2i_PrivateKey(3)> recognises and unpacks a PKCS#8 structures.
+
+=item *
+
+Use L<OSSL_DECODER(3)> and L<OSSL_ENCODER(3)>. How to migrate is described
+below. All those descriptions assume that the key to be encoded is in the
+variable I<pkey>.
+
+=back
+
+=head3 Migrating B<i2d> functions to B<OSSL_ENCODER>
+
+The exact L<OSSL_ENCODER(3)> output is driven by arguments rather than by
+function names. The sample code to get DER encoded output in a type
+specific structure is uniform, the only things that vary are the selection
+of what part of the B<EVP_PKEY> should be output, and the structure. The
+B<i2d> functions names can therefore be translated into two variables,
+I<selection> and I<structure> as follows:
+
+=over 4
+
+=item B<i2d_I<TYPE>PrivateKey>() translates into:
+
+ int selection = EVP_PKEY_PRIVATE_KEY;
+ const char *structure = "type-specific";
+
+=item B<i2d_I<TYPE>PublicKey>() translates into:
+
+ int selection = EVP_PKEY_PUBLIC_KEY;
+ const char *structure = "type-specific";
+
+=item B<i2d_I<TYPE>params>() translates into:
+
+ int selection = EVP_PKEY_PARAMETERS;
+ const char *structure = "type-specific";
+
+=item B<i2d_I<TYPE>_PUBKEY>() translates into:
+
+ int selection = EVP_PKEY_PUBLIC_KEY;
+ const char *structure = "SubjectPublicKeyInfo";
+
+=back
+
+The following sample code does the rest of the work:
+
+ unsigned char *p = buffer; /* |buffer| is supplied by the caller */
+ size_t len = buffer_size; /* assumed be the size of |buffer| */
+ OSSL_ENCODER_CTX *ctx =
+ OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, "DER", structure,
+ NULL, NULL);
+ if (ctx == NULL) {
+ /* fatal error handling */
+ }
+ if (OSSL_ENCODER_CTX_get_num_encoders(ctx) == 0) {
+ OSSL_ENCODER_CTX_free(ctx);
+ /* non-fatal error handling */
+ }
+ if (!OSSL_ENCODER_to_data(ctx, &p, &len)) {
+ OSSL_ENCODER_CTX_free(ctx);
+ /* error handling */
+ }
+ OSSL_ENCODER_CTX_free(ctx);
+
+=for comment TODO: a similar section on OSSL_DECODER is to be added
+
+=head1 NOTES
+
+The letters B<i> and B<d> in B<i2d_I<TYPE>>() stand for
+"internal" (that is, an internal C structure) and "DER" respectively.
+So B<i2d_I<TYPE>>() converts from internal to DER.
+
+The functions can also understand B<BER> forms.
+
+The actual TYPE structure passed to B<i2d_I<TYPE>>() must be a valid
+populated B<I<TYPE>> structure -- it B<cannot> simply be fed with an
+empty structure such as that returned by TYPE_new().
+
+The encoded data is in binary form and may contain embedded zeros.
+Therefore, any FILE pointers or BIOs should be opened in binary mode.
+Functions such as strlen() will B<not> return the correct length
+of the encoded structure.
+
+The ways that I<*ppin> and I<*ppout> are incremented after the operation
+can trap the unwary. See the B<WARNINGS> section in L<d2i_X509(3)> for some
+common errors.
+The reason for this-auto increment behaviour is to reflect a typical
+usage of ASN1 functions: after one structure is encoded or decoded
+another will be processed after it.
+
+The following points about the data types might be useful:
+
+=over 4
+
+=item B<DSA_PUBKEY>
+
+Represents a DSA public key using a B<SubjectPublicKeyInfo> structure.
+
+=item B<DSAPublicKey>, B<DSAPrivateKey>
+
+Use a non-standard OpenSSL format and should be avoided; use B<DSA_PUBKEY>,
+L<PEM_write_PrivateKey(3)>, or similar instead.
+
+=back
+
+=head1 RETURN VALUES
+
+B<d2i_I<TYPE>>(), B<d2i_I<TYPE>_bio>() and B<d2i_I<TYPE>_fp>() return a valid
+B<I<TYPE>> structure or NULL if an error occurs. If the "reuse" capability has
+been used with a valid structure being passed in via I<a>, then the object is
+freed in the event of error and I<*a> is set to NULL.
+
+B<i2d_I<TYPE>>() returns the number of bytes successfully encoded or a negative
+value if an error occurs.
+
+B<i2d_I<TYPE>_bio>() and B<i2d_I<TYPE>_fp>() return 1 for success and 0 if an
+error occurs.
+
+=head1 SEE ALSO
+
+L<OSSL_ENCODER(3)>, L<OSSL_DECODER(3)>,
+L<d2i_PrivateKey(3)>, L<d2i_PublicKey(3)>, L<d2i_KeyParams(3)>,
+L<d2i_PUBKEY(3)>,
+L<i2d_PrivateKey(3)>, L<i2d_PublicKey(3)>, L<i2d_KeyParams(3)>,
+L<i2d_PUBKEY(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/d2i_SSL_SESSION.pod b/doc/man3/d2i_SSL_SESSION.pod
index 68ed302d73a6..fe8308c2bf0b 100644
--- a/doc/man3/d2i_SSL_SESSION.pod
+++ b/doc/man3/d2i_SSL_SESSION.pod
@@ -42,7 +42,7 @@ L<d2i_X509(3)>
Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/d2i_X509.pod b/doc/man3/d2i_X509.pod
index 30b419c512d6..c79a964e6d7f 100644
--- a/doc/man3/d2i_X509.pod
+++ b/doc/man3/d2i_X509.pod
@@ -1,5 +1,12 @@
=pod
+=begin comment
+
+Any keypair function here that gets deprecated should be moved to
+d2i_RSAPrivateKey.pod.
+
+=end comment
+
=head1 NAME
d2i_ACCESS_DESCRIPTION,
@@ -44,28 +51,14 @@ d2i_DIRECTORYSTRING,
d2i_DISPLAYTEXT,
d2i_DIST_POINT,
d2i_DIST_POINT_NAME,
-d2i_DSAPrivateKey,
-d2i_DSAPrivateKey_bio,
-d2i_DSAPrivateKey_fp,
-d2i_DSAPublicKey,
-d2i_DSA_PUBKEY,
-d2i_DSA_PUBKEY_bio,
-d2i_DSA_PUBKEY_fp,
d2i_DSA_SIG,
-d2i_DSAparams,
d2i_ECDSA_SIG,
-d2i_ECPKParameters,
-d2i_ECParameters,
-d2i_ECPrivateKey,
-d2i_ECPrivateKey_bio,
-d2i_ECPrivateKey_fp,
-d2i_EC_PUBKEY,
-d2i_EC_PUBKEY_bio,
-d2i_EC_PUBKEY_fp,
d2i_EDIPARTYNAME,
d2i_ESS_CERT_ID,
+d2i_ESS_CERT_ID_V2,
d2i_ESS_ISSUER_SERIAL,
d2i_ESS_SIGNING_CERT,
+d2i_ESS_SIGNING_CERT_V2,
d2i_EXTENDED_KEY_USAGE,
d2i_GENERAL_NAME,
d2i_GENERAL_NAMES,
@@ -73,6 +66,7 @@ d2i_IPAddressChoice,
d2i_IPAddressFamily,
d2i_IPAddressOrRange,
d2i_IPAddressRange,
+d2i_ISSUER_SIGN_TOOL,
d2i_ISSUING_DIST_POINT,
d2i_NAMING_AUTHORITY,
d2i_NETSCAPE_CERT_SEQUENCE,
@@ -94,6 +88,17 @@ d2i_OCSP_REVOKEDINFO,
d2i_OCSP_SERVICELOC,
d2i_OCSP_SIGNATURE,
d2i_OCSP_SINGLERESP,
+d2i_OSSL_CMP_MSG,
+d2i_OSSL_CMP_PKIHEADER,
+d2i_OSSL_CMP_PKISI,
+d2i_OSSL_CRMF_CERTID,
+d2i_OSSL_CRMF_CERTTEMPLATE,
+d2i_OSSL_CRMF_ENCRYPTEDVALUE,
+d2i_OSSL_CRMF_MSG,
+d2i_OSSL_CRMF_MSGS,
+d2i_OSSL_CRMF_PBMPARAMETER,
+d2i_OSSL_CRMF_PKIPUBLICATIONINFO,
+d2i_OSSL_CRMF_SINGLEPUBINFO,
d2i_OTHERNAME,
d2i_PBE2PARAM,
d2i_PBEPARAM,
@@ -127,17 +132,8 @@ d2i_POLICYQUALINFO,
d2i_PROFESSION_INFO,
d2i_PROXY_CERT_INFO_EXTENSION,
d2i_PROXY_POLICY,
-d2i_RSAPrivateKey,
-d2i_RSAPrivateKey_bio,
-d2i_RSAPrivateKey_fp,
-d2i_RSAPublicKey,
-d2i_RSAPublicKey_bio,
-d2i_RSAPublicKey_fp,
d2i_RSA_OAEP_PARAMS,
d2i_RSA_PSS_PARAMS,
-d2i_RSA_PUBKEY,
-d2i_RSA_PUBKEY_bio,
-d2i_RSA_PUBKEY_fp,
d2i_SCRYPT_PARAMS,
d2i_SCT_LIST,
d2i_SXNET,
@@ -174,6 +170,8 @@ d2i_X509_EXTENSIONS,
d2i_X509_NAME,
d2i_X509_NAME_ENTRY,
d2i_X509_PUBKEY,
+d2i_X509_PUBKEY_bio,
+d2i_X509_PUBKEY_fp,
d2i_X509_REQ,
d2i_X509_REQ_INFO,
d2i_X509_REQ_bio,
@@ -223,28 +221,14 @@ i2d_DIRECTORYSTRING,
i2d_DISPLAYTEXT,
i2d_DIST_POINT,
i2d_DIST_POINT_NAME,
-i2d_DSAPrivateKey,
-i2d_DSAPrivateKey_bio,
-i2d_DSAPrivateKey_fp,
-i2d_DSAPublicKey,
-i2d_DSA_PUBKEY,
-i2d_DSA_PUBKEY_bio,
-i2d_DSA_PUBKEY_fp,
i2d_DSA_SIG,
-i2d_DSAparams,
i2d_ECDSA_SIG,
-i2d_ECPKParameters,
-i2d_ECParameters,
-i2d_ECPrivateKey,
-i2d_ECPrivateKey_bio,
-i2d_ECPrivateKey_fp,
-i2d_EC_PUBKEY,
-i2d_EC_PUBKEY_bio,
-i2d_EC_PUBKEY_fp,
i2d_EDIPARTYNAME,
i2d_ESS_CERT_ID,
+i2d_ESS_CERT_ID_V2,
i2d_ESS_ISSUER_SERIAL,
i2d_ESS_SIGNING_CERT,
+i2d_ESS_SIGNING_CERT_V2,
i2d_EXTENDED_KEY_USAGE,
i2d_GENERAL_NAME,
i2d_GENERAL_NAMES,
@@ -252,6 +236,7 @@ i2d_IPAddressChoice,
i2d_IPAddressFamily,
i2d_IPAddressOrRange,
i2d_IPAddressRange,
+i2d_ISSUER_SIGN_TOOL,
i2d_ISSUING_DIST_POINT,
i2d_NAMING_AUTHORITY,
i2d_NETSCAPE_CERT_SEQUENCE,
@@ -273,6 +258,17 @@ i2d_OCSP_REVOKEDINFO,
i2d_OCSP_SERVICELOC,
i2d_OCSP_SIGNATURE,
i2d_OCSP_SINGLERESP,
+i2d_OSSL_CMP_MSG,
+i2d_OSSL_CMP_PKIHEADER,
+i2d_OSSL_CMP_PKISI,
+i2d_OSSL_CRMF_CERTID,
+i2d_OSSL_CRMF_CERTTEMPLATE,
+i2d_OSSL_CRMF_ENCRYPTEDVALUE,
+i2d_OSSL_CRMF_MSG,
+i2d_OSSL_CRMF_MSGS,
+i2d_OSSL_CRMF_PBMPARAMETER,
+i2d_OSSL_CRMF_PKIPUBLICATIONINFO,
+i2d_OSSL_CRMF_SINGLEPUBINFO,
i2d_OTHERNAME,
i2d_PBE2PARAM,
i2d_PBEPARAM,
@@ -309,17 +305,8 @@ i2d_POLICYQUALINFO,
i2d_PROFESSION_INFO,
i2d_PROXY_CERT_INFO_EXTENSION,
i2d_PROXY_POLICY,
-i2d_RSAPrivateKey,
-i2d_RSAPrivateKey_bio,
-i2d_RSAPrivateKey_fp,
-i2d_RSAPublicKey,
-i2d_RSAPublicKey_bio,
-i2d_RSAPublicKey_fp,
i2d_RSA_OAEP_PARAMS,
i2d_RSA_PSS_PARAMS,
-i2d_RSA_PUBKEY,
-i2d_RSA_PUBKEY_bio,
-i2d_RSA_PUBKEY_fp,
i2d_SCRYPT_PARAMS,
i2d_SCT_LIST,
i2d_SXNET,
@@ -356,6 +343,8 @@ i2d_X509_EXTENSIONS,
i2d_X509_NAME,
i2d_X509_NAME_ENTRY,
i2d_X509_PUBKEY,
+i2d_X509_PUBKEY_bio,
+i2d_X509_PUBKEY_fp,
i2d_X509_REQ,
i2d_X509_REQ_INFO,
i2d_X509_REQ_bio,
@@ -367,20 +356,23 @@ i2d_X509_VAL,
=head1 SYNOPSIS
-=for comment generic
+=for openssl generic
TYPE *d2i_TYPE(TYPE **a, const unsigned char **ppin, long length);
TYPE *d2i_TYPE_bio(BIO *bp, TYPE **a);
TYPE *d2i_TYPE_fp(FILE *fp, TYPE **a);
+ int i2d_TYPE(const TYPE *a, unsigned char **ppout);
int i2d_TYPE(TYPE *a, unsigned char **ppout);
+ int i2d_TYPE_fp(FILE *fp, const TYPE *a);
int i2d_TYPE_fp(FILE *fp, TYPE *a);
+ int i2d_TYPE_bio(BIO *bp, const TYPE *a);
int i2d_TYPE_bio(BIO *bp, TYPE *a);
=head1 DESCRIPTION
-In the description here, I<TYPE> is used a placeholder
-for any of the OpenSSL datatypes, such as I<X509_CRL>.
+In the description here, B<I<TYPE>> is used a placeholder
+for any of the OpenSSL datatypes, such as B<X509_CRL>.
The function parameters I<ppin> and I<ppout> are generally
either both named I<pp> in the headers, or I<in> and I<out>.
@@ -389,40 +381,40 @@ encoding. Unlike the C structures which can have pointers to sub-objects
within, the DER is a serialized encoding, suitable for sending over the
network, writing to a file, and so on.
-d2i_TYPE() attempts to decode B<len> bytes at B<*ppin>. If successful a
-pointer to the B<TYPE> structure is returned and B<*ppin> is incremented to
-the byte following the parsed data. If B<a> is not B<NULL> then a pointer
-to the returned structure is also written to B<*a>. If an error occurred
-then B<NULL> is returned.
+B<d2i_I<TYPE>>() attempts to decode I<len> bytes at I<*ppin>. If successful a
+pointer to the B<I<TYPE>> structure is returned and I<*ppin> is incremented to
+the byte following the parsed data. If I<a> is not NULL then a pointer
+to the returned structure is also written to I<*a>. If an error occurred
+then NULL is returned.
-On a successful return, if B<*a> is not B<NULL> then it is assumed that B<*a>
-contains a valid B<TYPE> structure and an attempt is made to reuse it. This
+On a successful return, if I<*a> is not NULL then it is assumed that I<*a>
+contains a valid B<I<TYPE>> structure and an attempt is made to reuse it. This
"reuse" capability is present for historical compatibility but its use is
B<strongly discouraged> (see BUGS below, and the discussion in the RETURN
VALUES section).
-d2i_TYPE_bio() is similar to d2i_TYPE() except it attempts
-to parse data from BIO B<bp>.
+B<d2i_I<TYPE>_bio>() is similar to B<d2i_I<TYPE>>() except it attempts
+to parse data from BIO I<bp>.
-d2i_TYPE_fp() is similar to d2i_TYPE() except it attempts
-to parse data from FILE pointer B<fp>.
+B<d2i_I<TYPE>_fp>() is similar to B<d2i_I<TYPE>>() except it attempts
+to parse data from FILE pointer I<fp>.
-i2d_TYPE() encodes the structure pointed to by B<a> into DER format.
-If B<ppout> is not B<NULL>, it writes the DER encoded data to the buffer
-at B<*ppout>, and increments it to point after the data just written.
+B<i2d_I<TYPE>>() encodes the structure pointed to by I<a> into DER format.
+If I<ppout> is not NULL, it writes the DER encoded data to the buffer
+at I<*ppout>, and increments it to point after the data just written.
If the return value is negative an error occurred, otherwise it
returns the length of the encoded data.
-If B<*ppout> is B<NULL> memory will be allocated for a buffer and the encoded
-data written to it. In this case B<*ppout> is not incremented and it points
+If I<*ppout> is NULL memory will be allocated for a buffer and the encoded
+data written to it. In this case I<*ppout> is not incremented and it points
to the start of the data just written.
-i2d_TYPE_bio() is similar to i2d_TYPE() except it writes
-the encoding of the structure B<a> to BIO B<bp> and it
+B<i2d_I<TYPE>_bio>() is similar to B<i2d_I<TYPE>>() except it writes
+the encoding of the structure I<a> to BIO I<bp> and it
returns 1 for success and 0 for failure.
-i2d_TYPE_fp() is similar to i2d_TYPE() except it writes
-the encoding of the structure B<a> to BIO B<bp> and it
+B<i2d_I<TYPE>_fp>() is similar to B<i2d_I<TYPE>>() except it writes
+the encoding of the structure I<a> to FILE pointer I<fp> and it
returns 1 for success and 0 for failure.
These routines do not encrypt private keys and therefore offer no
@@ -430,14 +422,14 @@ security; use L<PEM_write_PrivateKey(3)> or similar for writing to files.
=head1 NOTES
-The letters B<i> and B<d> in B<i2d_TYPE> stand for
+The letters B<i> and B<d> in B<i2d_I<TYPE>>() stand for
"internal" (that is, an internal C structure) and "DER" respectively.
-So B<i2d_TYPE> converts from internal to DER.
+So B<i2d_I<TYPE>>() converts from internal to DER.
The functions can also understand B<BER> forms.
-The actual TYPE structure passed to i2d_TYPE() must be a valid
-populated B<TYPE> structure -- it B<cannot> simply be fed with an
+The actual TYPE structure passed to B<i2d_I<TYPE>>() must be a valid
+populated B<I<TYPE>> structure -- it B<cannot> simply be fed with an
empty structure such as that returned by TYPE_new().
The encoded data is in binary form and may contain embedded zeros.
@@ -445,7 +437,7 @@ Therefore, any FILE pointers or BIOs should be opened in binary mode.
Functions such as strlen() will B<not> return the correct length
of the encoded structure.
-The ways that B<*ppin> and B<*ppout> are incremented after the operation
+The ways that I<*ppin> and I<*ppout> are incremented after the operation
can trap the unwary. See the B<WARNINGS> section for some common
errors.
The reason for this-auto increment behaviour is to reflect a typical
@@ -468,29 +460,16 @@ Represents a PKCS#3 DH parameters structure.
Represents an ANSI X9.42 DH parameters structure.
-=item B<DSA_PUBKEY>
-
-Represents a DSA public key using a B<SubjectPublicKeyInfo> structure.
-
-=item B<DSAPublicKey, DSAPrivateKey>
-
-Use a non-standard OpenSSL format and should be avoided; use B<DSA_PUBKEY>,
-B<PEM_write_PrivateKey(3)>, or similar instead.
-
=item B<ECDSA_SIG>
Represents an ECDSA signature.
-=item B<RSAPublicKey>
-
-Represents a PKCS#1 RSA public key structure.
-
=item B<X509_ALGOR>
Represents an B<AlgorithmIdentifier> structure as used in IETF RFC 6960 and
elsewhere.
-=item B<X509_Name>
+=item B<X509_NAME>
Represents a B<Name> type as used for subject and issuer names in
IETF RFC 6960 and elsewhere.
@@ -507,16 +486,16 @@ Represents the B<DigestInfo> structure defined in PKCS#1 and PKCS#7.
=head1 RETURN VALUES
-d2i_TYPE(), d2i_TYPE_bio() and d2i_TYPE_fp() return a valid B<TYPE> structure
-or B<NULL> if an error occurs. If the "reuse" capability has been used with
-a valid structure being passed in via B<a>, then the object is freed in
-the event of error and B<*a> is set to NULL.
+B<d2i_I<TYPE>>(), B<d2i_I<TYPE>_bio>() and B<d2i_I<TYPE>_fp>() return a valid
+B<I<TYPE>> structure or NULL if an error occurs. If the "reuse" capability has
+been used with a valid structure being passed in via I<a>, then the object is
+freed in the event of error and I<*a> is set to NULL.
-i2d_TYPE() returns the number of bytes successfully encoded or a negative
+B<i2d_I<TYPE>>() returns the number of bytes successfully encoded or a negative
value if an error occurs.
-i2d_TYPE_bio() and i2d_TYPE_fp() return 1 for success and 0 if an error
-occurs.
+B<i2d_I<TYPE>_bio>() and B<i2d_I<TYPE>_fp>() return 1 for success and 0 if an
+error occurs.
=head1 EXAMPLES
@@ -572,12 +551,12 @@ mistake is to attempt to use a buffer directly as follows:
...
OPENSSL_free(buf);
-This code will result in B<buf> apparently containing garbage because
+This code will result in I<buf> apparently containing garbage because
it was incremented after the call to point after the data just written.
-Also B<buf> will no longer contain the pointer allocated by OPENSSL_malloc()
+Also I<buf> will no longer contain the pointer allocated by OPENSSL_malloc()
and the subsequent call to OPENSSL_free() is likely to crash.
-Another trap to avoid is misuse of the B<a> argument to d2i_TYPE():
+Another trap to avoid is misuse of the I<a> argument to B<d2i_I<TYPE>>():
X509 *x;
@@ -585,40 +564,40 @@ Another trap to avoid is misuse of the B<a> argument to d2i_TYPE():
/* error */
This will probably crash somewhere in d2i_X509(). The reason for this
-is that the variable B<x> is uninitialized and an attempt will be made to
+is that the variable I<x> is uninitialized and an attempt will be made to
interpret its (invalid) value as an B<X509> structure, typically causing
-a segmentation violation. If B<x> is set to NULL first then this will not
+a segmentation violation. If I<x> is set to NULL first then this will not
happen.
=head1 BUGS
-In some versions of OpenSSL the "reuse" behaviour of d2i_TYPE() when
-B<*a> is valid is broken and some parts of the reused structure may
+In some versions of OpenSSL the "reuse" behaviour of B<d2i_I<TYPE>>() when
+I<*a> is valid is broken and some parts of the reused structure may
persist if they are not present in the new one. Additionally, in versions of
OpenSSL prior to 1.1.0, when the "reuse" behaviour is used and an error occurs
the behaviour is inconsistent. Some functions behaved as described here, while
-some did not free B<*a> on error and did not set B<*a> to NULL.
+some did not free I<*a> on error and did not set I<*a> to NULL.
As a result of the above issues the "reuse" behaviour is strongly discouraged.
-i2d_TYPE() will not return an error in many versions of OpenSSL,
+B<i2d_I<TYPE>>() will not return an error in many versions of OpenSSL,
if mandatory fields are not initialized due to a programming error
then the encoded structure may contain invalid data or omit the
-fields entirely and will not be parsed by d2i_TYPE(). This may be
-fixed in future so code should not assume that i2d_TYPE() will
+fields entirely and will not be parsed by B<d2i_I<TYPE>>(). This may be
+fixed in future so code should not assume that B<i2d_I<TYPE>>() will
always succeed.
-Any function which encodes a structure (i2d_TYPE(),
-i2d_TYPE() or i2d_TYPE()) may return a stale encoding if the
+Any function which encodes a structure (B<i2d_I<TYPE>>(),
+B<i2d_I<TYPE>_bio>() or B<i2d_I<TYPE>_fp>()) may return a stale encoding if the
structure has been modified after deserialization or previous
serialization. This is because some objects cache the encoding for
efficiency reasons.
=head1 COPYRIGHT
-Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 1998-2023 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/i2d_CMS_bio_stream.pod b/doc/man3/i2d_CMS_bio_stream.pod
index dd2bd213f1e1..88289b115fc4 100644
--- a/doc/man3/i2d_CMS_bio_stream.pod
+++ b/doc/man3/i2d_CMS_bio_stream.pod
@@ -45,7 +45,7 @@ The i2d_CMS_bio_stream() function was added in OpenSSL 1.0.0.
Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/i2d_PKCS7_bio_stream.pod b/doc/man3/i2d_PKCS7_bio_stream.pod
index a33aa08f2d32..ced178bd5580 100644
--- a/doc/man3/i2d_PKCS7_bio_stream.pod
+++ b/doc/man3/i2d_PKCS7_bio_stream.pod
@@ -45,7 +45,7 @@ The i2d_PKCS7_bio_stream() function was added in OpenSSL 1.0.0.
Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/i2d_re_X509_tbs.pod b/doc/man3/i2d_re_X509_tbs.pod
index 98ac4f41aee4..d9247794fc59 100644
--- a/doc/man3/i2d_re_X509_tbs.pod
+++ b/doc/man3/i2d_re_X509_tbs.pod
@@ -11,7 +11,7 @@ i2d_re_X509_tbs, i2d_re_X509_CRL_tbs, i2d_re_X509_REQ_tbs
#include <openssl/x509.h>
X509 *d2i_X509_AUX(X509 **px, const unsigned char **in, long len);
- int i2d_X509_AUX(X509 *x, unsigned char **out);
+ int i2d_X509_AUX(const X509 *x, unsigned char **out);
int i2d_re_X509_tbs(X509 *x, unsigned char **out);
int i2d_re_X509_CRL_tbs(X509_CRL *crl, unsigned char **pp);
int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp);
@@ -55,7 +55,7 @@ d2i_X509_AUX() returns a valid B<X509> structure or NULL if an error occurred.
i2d_X509_AUX() returns the length of encoded data or -1 on error.
i2d_re_X509_tbs(), i2d_re_X509_CRL_tbs() and i2d_re_X509_REQ_tbs() return the
-length of encoded data or 0 on error.
+length of encoded data or <=0 on error.
=head1 SEE ALSO
@@ -78,9 +78,9 @@ L<X509_verify_cert(3)>
=head1 COPYRIGHT
-Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/o2i_SCT_LIST.pod b/doc/man3/o2i_SCT_LIST.pod
index 28989387edba..1c3468a13239 100644
--- a/doc/man3/o2i_SCT_LIST.pod
+++ b/doc/man3/o2i_SCT_LIST.pod
@@ -19,13 +19,13 @@ decode and encode Signed Certificate Timestamp lists in TLS wire format
The SCT_LIST and SCT functions are very similar to the i2d and d2i family of
functions, except that they convert to and from TLS wire format, as described in
-RFC 6962. See L<d2i_SCT_LIST> for more information about how the parameters are
+RFC 6962. See L<d2i_SCT_LIST(3)> for more information about how the parameters are
treated and the return values.
=head1 RETURN VALUES
All of the functions have return values consistent with those stated for
-L<d2i_SCT_LIST> and L<i2d_SCT_LIST>.
+L<d2i_SCT_LIST(3)> and L<i2d_SCT_LIST(3)>.
=head1 SEE ALSO
@@ -41,7 +41,7 @@ These functions were added in OpenSSL 1.1.0.
Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man3/s2i_ASN1_IA5STRING.pod b/doc/man3/s2i_ASN1_IA5STRING.pod
new file mode 100644
index 000000000000..5c37144c2038
--- /dev/null
+++ b/doc/man3/s2i_ASN1_IA5STRING.pod
@@ -0,0 +1,99 @@
+=pod
+
+=head1 NAME
+
+i2s_ASN1_IA5STRING,
+s2i_ASN1_IA5STRING,
+i2s_ASN1_INTEGER,
+s2i_ASN1_INTEGER,
+i2s_ASN1_OCTET_STRING,
+s2i_ASN1_OCTET_STRING,
+i2s_ASN1_ENUMERATED,
+i2s_ASN1_ENUMERATED_TABLE,
+i2s_ASN1_UTF8STRING,
+s2i_ASN1_UTF8STRING
+- convert objects from/to ASN.1/string representation
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509v3.h>
+
+ char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5);
+ ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, const char *str);
+ char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, const ASN1_INTEGER *a);
+ ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value);
+ char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
+ const ASN1_OCTET_STRING *oct);
+ ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, const char *str);
+ char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *a);
+ char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method,
+ const ASN1_ENUMERATED *e);
+
+ char *i2s_ASN1_UTF8STRING(X509V3_EXT_METHOD *method,
+ ASN1_UTF8STRING *utf8);
+ ASN1_UTF8STRING *s2i_ASN1_UTF8STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, const char *str);
+
+=head1 DESCRIPTION
+
+These functions convert OpenSSL objects to and from their ASN.1/string
+representation. This function is used for B<X509v3> extensions.
+
+=head1 NOTES
+
+The letters B<i> and B<s> in B<i2s> and B<s2i> stand for
+"internal" (that is, an internal C structure) and string respectively.
+So B<i2s_ASN1_IA5STRING>() converts from internal to string.
+
+It is the caller's responsibility to free the returned string.
+In the B<i2s_ASN1_IA5STRING>() function the string is copied and
+the ownership of the original string remains with the caller.
+
+=head1 RETURN VALUES
+
+B<i2s_ASN1_IA5STRING>() returns the pointer to a IA5 string
+or NULL if an error occurs.
+
+B<s2i_ASN1_IA5STRING>() return a valid
+B<ASN1_IA5STRING> structure or NULL if an error occurs.
+
+B<i2s_ASN1_INTEGER>() return a valid
+string or NULL if an error occurs.
+
+B<s2i_ASN1_INTEGER>() returns the pointer to a B<ASN1_INTEGER>
+structure or NULL if an error occurs.
+
+B<i2s_ASN1_OCTET_STRING>() returns the pointer to a OCTET_STRING string
+or NULL if an error occurs.
+
+B<s2i_ASN1_OCTET_STRING>() return a valid
+B<ASN1_OCTET_STRING> structure or NULL if an error occurs.
+
+B<i2s_ASN1_ENUMERATED>() return a valid
+string or NULL if an error occurs.
+
+B<s2i_ASN1_ENUMERATED>() returns the pointer to a B<ASN1_ENUMERATED>
+structure or NULL if an error occurs.
+
+B<s2i_ASN1_UTF8STRING>() return a valid
+B<ASN1_UTF8STRING> structure or NULL if an error occurs.
+
+B<i2s_ASN1_UTF8STRING>() returns the pointer to a UTF-8 string
+or NULL if an error occurs.
+
+=head1 HISTORY
+
+i2s_ASN1_UTF8STRING() and s2i_ASN1_UTF8STRING() were made public in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man5/config.pod b/doc/man5/config.pod
index 3cc2d73a526d..77a8055e81fa 100644
--- a/doc/man5/config.pod
+++ b/doc/man5/config.pod
@@ -6,409 +6,514 @@ config - OpenSSL CONF library configuration files
=head1 DESCRIPTION
-The OpenSSL CONF library can be used to read configuration files.
-It is used for the OpenSSL master configuration file B<openssl.cnf>
-and in a few other places like B<SPKAC> files and certificate extension
-files for the B<x509> utility. OpenSSL applications can also use the
-CONF library for their own purposes.
-
-A configuration file is divided into a number of sections. Each section
-starts with a line B<[ section_name ]> and ends when a new section is
-started or end of file is reached. A section name can consist of
-alphanumeric characters and underscores.
-
-The first section of a configuration file is special and is referred
-to as the B<default> section. This section is usually unnamed and spans from the
-start of file until the first named section. When a name is being looked up
-it is first looked up in a named section (if any) and then the
-default section.
+This page documents the syntax of OpenSSL configuration files,
+as parsed by L<NCONF_load(3)> and related functions.
+This format is used by many of the OpenSSL commands, and to
+initialize the libraries when used by any application.
+
+The first part describes the general syntax of the configuration
+files, and subsequent sections describe the semantics of individual
+modules. Other modules are described in L<fips_config(5)> and
+L<x509v3_config(5)>.
+The syntax for defining ASN.1 values is described in
+L<ASN1_generate_nconf(3)>.
+
+=head1 SYNTAX
+
+A configuration file is a series of lines. Blank lines, and whitespace
+between the elements of a line, have no significance. A comment starts
+with a B<#> character; the rest of the line is ignored. If the B<#>
+is the first non-space character in a line, the entire line is ignored.
+
+=head2 Directives
+
+Two directives can be used to control the parsing of configuration files:
+B<.include> and B<.pragma>.
+
+For compatibility with older versions of OpenSSL, an equal sign after the
+directive will be ignored. Older versions will treat it as an assignment,
+so care should be taken if the difference in semantics is important.
+
+A file can include other files using the include syntax:
+
+ .include [=] pathname
+
+If B<pathname> is a simple filename, that file is included directly at
+that point. Included files can have B<.include> statements that specify
+other files. If B<pathname> is a directory, all files within that directory
+that have a C<.cnf> or C<.conf> extension will be included. (This is only
+available on systems with POSIX IO support.) Any sub-directories found
+inside the B<pathname> are B<ignored>. Similarly, if a file is opened
+while scanning a directory, and that file has an B<.include> directive
+that specifies a directory, that is also ignored.
+
+As a general rule, the B<pathname> should be an absolute path; this can
+be enforced with the B<abspath> and B<includedir> pragmas, described below.
+The environment variable B<OPENSSL_CONF_INCLUDE>, if it exists,
+is prepended to all relative pathnames.
+If the pathname is still relative, it is interpreted based on the
+current working directory.
+
+To require all file inclusions to name absolute paths, use the following
+directive:
+
+ .pragma [=] abspath:value
+
+The default behavior, where the B<value> is B<false> or B<off>, is to allow
+relative paths. To require all B<.include> pathnames to be absolute paths,
+use a B<value> of B<true> or B<on>.
+
+In these files, the dollar sign, B<$>, is used to reference a variable, as
+described below. On some platforms, however, it is common to treat B<$>
+as a regular character in symbol names. Supporting this behavior can be
+done with the following directive:
+
+ .pragma [=] dollarid:value
+
+The default behavior, where the B<value> is B<false> or B<off>, is to treat
+the dollarsign as indicating a variable name; C<foo$bar> is interpreted as
+C<foo> followed by the expansion of the variable C<bar>. If B<value> is
+B<true> or B<on>, then C<foo$bar> is a single seven-character name nad
+variable expansions must be specified using braces or parentheses.
+
+ .pragma [=] includedir:value
+
+If a relative pathname is specified in the B<.include> directive, and
+the B<OPENSSL_CONF_INCLUDE> environment variable doesn't exist, then
+the value of the B<includedir> pragma, if it exists, is prepended to the
+pathname.
+
+=head2 Settings
+
+A configuration file is divided into a number of I<sections>. A section
+begins with the section name in square brackets, and ends when a new
+section starts, or at the end of the file. The section name can consist
+of alphanumeric characters and underscores.
+Whitespace between the name and the brackets is removed.
+
+The first section of a configuration file is special and is referred to
+as the B<default> section. This section is usually unnamed and spans from
+the start of file until the first named section. When a name is being
+looked up, it is first looked up in the current or named section,
+and then the default section if necessary.
The environment is mapped onto a section called B<ENV>.
-Comments can be included by preceding them with the B<#> character
-
-Other files can be included using the B<.include> directive followed
-by a path. If the path points to a directory all files with
-names ending with B<.cnf> or B<.conf> are included from the directory.
-Recursive inclusion of directories from files in such directory is not
-supported. That means the files in the included directory can also contain
-B<.include> directives but only inclusion of regular files is supported
-there. The inclusion of directories is not supported on systems without
-POSIX IO support.
-
-It is strongly recommended to use absolute paths with the B<.include>
-directive. Relative paths are evaluated based on the application current
-working directory so unless the configuration file containing the
-B<.include> directive is application specific the inclusion will not
-work as expected.
-
-There can be optional B<=> character and whitespace characters between
-B<.include> directive and the path which can be useful in cases the
-configuration file needs to be loaded by old OpenSSL versions which do
-not support the B<.include> syntax. They would bail out with error
-if the B<=> character is not present but with it they just ignore
-the include.
-
-Each section in a configuration file consists of a number of name and
-value pairs of the form B<name=value>
-
-The B<name> string can contain any alphanumeric characters as well as
-a few punctuation symbols such as B<.> B<,> B<;> and B<_>.
-
-The B<value> string consists of the string following the B<=> character
-until end of line with any leading and trailing white space removed.
-
-The value string undergoes variable expansion. This can be done by
-including the form B<$var> or B<${var}>: this will substitute the value
-of the named variable in the current section. It is also possible to
-substitute a value from another section using the syntax B<$section::name>
-or B<${section::name}>. By using the form B<$ENV::name> environment
-variables can be substituted. It is also possible to assign values to
-environment variables by using the name B<ENV::name>, this will work
-if the program looks up environment variables using the B<CONF> library
-instead of calling getenv() directly. The value string must not exceed 64k in
-length after variable expansion. Otherwise an error will occur.
-
-It is possible to escape certain characters by using any kind of quote
-or the B<\> character. By making the last character of a line a B<\>
+Within a section are a series of name/value assignments, described in more
+detail below. As a reminder, the square brackets shown in this example
+are required, not optional:
+
+ [ section ]
+ name1 = This is value1
+ name2 = Another value
+ ...
+ [ newsection ]
+ name1 = New value1
+ name3 = Value 3
+
+The B<name> can contain any alphanumeric characters as well as a few
+punctuation symbols such as B<.> B<,> B<;> and B<_>.
+Whitespace after the name and before the equal sign is ignored.
+
+If a name is repeated in the same section, then all but the last
+value are ignored. In certain circumstances, such as with
+Certificate DNs, the same field may occur multiple times.
+In order to support this, commands like L<openssl-req(1)> ignore any
+leading text that is preceded with a period. For example:
+
+ 1.OU = First OU
+ 2.OU = Second OU
+
+The B<value> consists of the string following the B<=> character until end
+of line with any leading and trailing whitespace removed.
+
+The value string undergoes variable expansion. The text C<$var> or C<${var}>
+inserts the value of the named variable from the current section.
+To use a value from another section use C<$section::name>
+or C<${section::name}>.
+By using C<$ENV::name>, the value of the specified environment
+variable will be substituted.
+
+Variables must be defined before their value is referenced, otherwise
+an error is flagged and the file will not load.
+This can be worked around by specifying a default value in the B<default>
+section before the variable is used.
+
+Any name/value settings in an B<ENV> section are available
+to the configuration file, but are not propagated to the environment.
+
+It is an error if the value ends up longer than 64k.
+
+It is possible to escape certain characters by using a single B<'> or
+double B<"> quote around the value, or using a backslash B<\> before the
+character,
+By making the last character of a line a B<\>
a B<value> string can be spread across multiple lines. In addition
the sequences B<\n>, B<\r>, B<\b> and B<\t> are recognized.
-All expansion and escape rules as described above that apply to B<value>
-also apply to the path of the B<.include> directive.
+The expansion and escape rules as described above that apply to B<value>
+also apply to the pathname of the B<.include> directive.
=head1 OPENSSL LIBRARY CONFIGURATION
-Applications can automatically configure certain
-aspects of OpenSSL using the master OpenSSL configuration file, or optionally
-an alternative configuration file. The B<openssl> utility includes this
-functionality: any sub command uses the master OpenSSL configuration file
-unless an option is used in the sub command to use an alternative configuration
-file.
-
-To enable library configuration the default section needs to contain an
-appropriate line which points to the main configuration section. The default
-name is B<openssl_conf> which is used by the B<openssl> utility. Other
-applications may use an alternative name such as B<myapplication_conf>.
-All library configuration lines appear in the default section at the start
-of the configuration file.
-
-The configuration section should consist of a set of name value pairs which
-contain specific module configuration information. The B<name> represents
-the name of the I<configuration module>. The meaning of the B<value> is
-module specific: it may, for example, represent a further configuration
-section containing configuration module specific information. E.g.:
-
- # This must be in the default section
+The sections below use the informal term I<module> to refer to a part
+of the OpenSSL functionality. This is not the same as the formal term
+I<FIPS module>, for example.
+
+The OpenSSL configuration looks up the value of B<openssl_conf>
+in the default section and takes that as the name of a section that specifies
+how to configure any modules in the library. It is not an error to leave
+any module in its default configuration. An application can specify a
+different name by calling CONF_modules_load_file(), for example, directly.
+
+OpenSSL also looks up the value of B<config_diagnostics>.
+If this exists and has a nonzero numeric value, any error suppressing flags
+passed to CONF_modules_load() will be ignored.
+This is useful for diagnosing misconfigurations but its use in
+production requires additional consideration. With this option enabled,
+a configuration error will completely prevent access to a service.
+Without this option and in the presence of a configuration error, access
+will be allowed but the desired configuration will B<not> be used.
+
+ # These must be in the default section
+ config_diagnostics = 1
openssl_conf = openssl_init
[openssl_init]
+ oid_section = oids
+ providers = providers
+ alg_section = evp_properties
+ ssl_conf = ssl_configuration
+ engines = engines
+ random = random
+
+ [oids]
+ ... new oids here ...
- oid_section = new_oids
- engines = engine_section
-
- [new_oids]
+ [providers]
+ ... provider stuff here ...
- ... new oids here ...
+ [evp_properties]
+ ... EVP properties here ...
- [engine_section]
+ [ssl_configuration]
+ ... SSL/TLS configuration properties here ...
- ... engine stuff here ...
+ [engines]
+ ... engine properties here ...
-The features of each configuration module are described below.
+ [random]
+ ... random properties here ...
-=head2 ASN1 Object Configuration Module
+The semantics of each module are described below. The phrase "in the
+initialization section" refers to the section identified by the
+B<openssl_conf> or other name (given as B<openssl_init> in the
+example above). The examples below assume the configuration above
+is used to specify the individual sections.
-This module has the name B<oid_section>. The value of this variable points
-to a section containing name value pairs of OIDs: the name is the OID short
-and long name, the value is the numerical form of the OID. Although some of
-the B<openssl> utility sub commands already have their own ASN1 OBJECT section
-functionality not all do. By using the ASN1 OBJECT configuration module
-B<all> the B<openssl> utility sub commands can see the new objects as well
-as any compliant applications. For example:
+=head2 ASN.1 Object Identifier Configuration
- [new_oids]
+The name B<oid_section> in the initialization section names the section
+containing name/value pairs of OID's.
+The name is the short name; the value is an optional long name followed
+by a comma, and the numeric value.
+While some OpenSSL commands have their own section for specifying OID's,
+this section makes them available to all commands and applications.
- some_new_oid = 1.2.3.4
+ [oids]
+ shortName = a very long OID name, 1.2.3.4
+ newoid1 = 1.2.3.4.1
some_other_oid = 1.2.3.5
-It is also possible to set the value to the long name followed
-by a comma and the numerical OID form. For example:
+If a full configuration with the above fragment is in the file
+F<example.cnf>, then the following command line:
- shortName = some object long name, 1.2.3.4
+ OPENSSL_CONF=example.cnf openssl asn1parse -genstr OID:1.2.3.4.1
-=head2 Engine Configuration Module
+will output:
-This ENGINE configuration module has the name B<engines>. The value of this
-variable points to a section containing further ENGINE configuration
-information.
+ 0:d=0 hl=2 l= 4 prim: OBJECT :newoid1
-The section pointed to by B<engines> is a table of engine names (though see
-B<engine_id> below) and further sections containing configuration information
-specific to each ENGINE.
+showing that the OID "newoid1" has been added as "1.2.3.4.1".
-Each ENGINE specific section is used to set default algorithms, load
-dynamic, perform initialization and send ctrls. The actual operation performed
-depends on the I<command> name which is the name of the name value pair. The
-currently supported commands are listed below.
+=head2 Provider Configuration
-For example:
+The name B<providers> in the initialization section names the section
+containing cryptographic provider configuration. The name/value assignments
+in this section each name a provider, and point to the configuration section
+for that provider. The provider-specific section is used to specify how
+to load the module, activate it, and set other parameters.
- [engine_section]
+Within a provider section, the following names have meaning:
- # Configure ENGINE named "foo"
- foo = foo_section
- # Configure ENGINE named "bar"
- bar = bar_section
+=over 4
- [foo_section]
- ... foo ENGINE specific commands ...
+=item B<identity>
- [bar_section]
- ... "bar" ENGINE specific commands ...
+This is used to specify an alternate name, overriding the default name
+specified in the list of providers. For example:
-The command B<engine_id> is used to give the ENGINE name. If used this
-command must be first. For example:
+ [providers]
+ foo = foo_provider
- [engine_section]
- # This would normally handle an ENGINE named "foo"
- foo = foo_section
+ [foo_provider]
+ identity = my_fips_module
- [foo_section]
- # Override default name and use "myfoo" instead.
- engine_id = myfoo
+=item B<module>
-The command B<dynamic_path> loads and adds an ENGINE from the given path. It
-is equivalent to sending the ctrls B<SO_PATH> with the path argument followed
-by B<LIST_ADD> with value 2 and B<LOAD> to the dynamic ENGINE. If this is
-not the required behaviour then alternative ctrls can be sent directly
-to the dynamic ENGINE using ctrl commands.
+Specifies the pathname of the module (typically a shared library) to load.
-The command B<init> determines whether to initialize the ENGINE. If the value
-is B<0> the ENGINE will not be initialized, if B<1> and attempt it made to
-initialized the ENGINE immediately. If the B<init> command is not present
-then an attempt will be made to initialize the ENGINE after all commands in
-its section have been processed.
+=item B<activate>
-The command B<default_algorithms> sets the default algorithms an ENGINE will
-supply using the functions ENGINE_set_default_string().
+If present, the module is activated. The value assigned to this name is not
+significant.
-If the name matches none of the above command names it is assumed to be a
-ctrl command which is sent to the ENGINE. The value of the command is the
-argument to the ctrl command. If the value is the string B<EMPTY> then no
-value is sent to the command.
+=back
-For example:
+All parameters in the section as well as sub-sections are made
+available to the provider.
+=head3 Default provider and its activation
- [engine_section]
+If no providers are activated explicitly, the default one is activated implicitly.
+See L<OSSL_PROVIDER-default(7)> for more details.
- # Configure ENGINE named "foo"
- foo = foo_section
+If you add a section explicitly activating any other provider(s),
+you most probably need to explicitly activate the default provider,
+otherwise it becomes unavailable in openssl. It may make the system remotely unavailable.
- [foo_section]
- # Load engine from DSO
- dynamic_path = /some/path/fooengine.so
- # A foo specific ctrl.
- some_ctrl = some_value
- # Another ctrl that doesn't take a value.
- other_ctrl = EMPTY
- # Supply all default algorithms
- default_algorithms = ALL
+=head2 EVP Configuration
+
+The name B<alg_section> in the initialization section names the section
+containing algorithmic properties when using the B<EVP> API.
-=head2 EVP Configuration Module
+Within the algorithm properties section, the following names have meaning:
-This modules has the name B<alg_section> which points to a section containing
-algorithm commands.
+=over 4
-Currently the only algorithm command supported is B<fips_mode> whose
-value can only be the boolean string B<off>. If B<fips_mode> is set to B<on>,
-an error occurs as this library version is not FIPS capable.
+=item B<default_properties>
-=head2 SSL Configuration Module
+The value may be anything that is acceptable as a property query
+string for EVP_set_default_properties().
-This module has the name B<ssl_conf> which points to a section containing
-SSL configurations.
+=item B<fips_mode> (deprecated)
-Each line in the SSL configuration section contains the name of the
-configuration and the section containing it.
+The value is a boolean that can be B<yes> or B<no>. If the value is
+B<yes>, this is exactly equivalent to:
-Each configuration section consists of command value pairs for B<SSL_CONF>.
-Each pair will be passed to a B<SSL_CTX> or B<SSL> structure if it calls
-SSL_CTX_config() or SSL_config() with the appropriate configuration name.
+ default_properties = fips=yes
-Note: any characters before an initial dot in the configuration section are
-ignored so the same command can be used multiple times.
+If the value is B<no>, nothing happens. Using this name is deprecated, and
+if used, it must be the only name in the section.
-For example:
+=back
+
+=head2 SSL Configuration
+
+The name B<ssl_conf> in the initialization section names the section
+containing the list of SSL/TLS configurations.
+As with the providers, each name in this section identifies a
+section with the configuration for that name. For example:
- ssl_conf = ssl_sect
+ [ssl_configuration]
+ server = server_tls_config
+ client = client_tls_config
+ system_default = tls_system_default
- [ssl_sect]
+ [server_tls_config]
+ ... configuration for SSL/TLS servers ...
- server = server_section
+ [client_tls_config]
+ ... configuration for SSL/TLS clients ...
- [server_section]
+The configuration name B<system_default> has a special meaning. If it
+exists, it is applied whenever an B<SSL_CTX> object is created. For example,
+to impose system-wide minimum TLS and DTLS protocol versions:
+ [tls_system_default]
+ MinProtocol = TLSv1.2
+ MinProtocol = DTLSv1.2
+
+The minimum TLS protocol is applied to B<SSL_CTX> objects that are TLS-based,
+and the minimum DTLS protocol to those are DTLS-based.
+The same applies also to maximum versions set with B<MaxProtocol>.
+
+Each configuration section consists of name/value pairs that are parsed
+by B<SSL_CONF_cmd(3)>, which will be called by SSL_CTX_config() or
+SSL_config(), appropriately. Note that any characters before an initial
+dot in the configuration section are ignored, so that the same command can
+be used multiple times. This probably is most useful for loading different
+key types, as shown here:
+
+ [server_tls_config]
RSA.Certificate = server-rsa.pem
ECDSA.Certificate = server-ecdsa.pem
- Ciphers = ALL:!RC4
-The system default configuration with name B<system_default> if present will
-be applied during any creation of the B<SSL_CTX> structure.
+=head2 Engine Configuration
-Example of a configuration with the system default:
+The name B<engines> in the initialization section names the section
+containing the list of ENGINE configurations.
+As with the providers, each name in this section identifies an engine
+with the configuration for that engine.
+The engine-specific section is used to specify how to load the engine,
+activate it, and set other parameters.
- ssl_conf = ssl_sect
+Within an engine section, the following names have meaning:
- [ssl_sect]
- system_default = system_default_sect
+=over 4
- [system_default_sect]
- MinProtocol = TLSv1.2
- MinProtocol = DTLSv1.2
+=item B<engine_id>
-=head1 NOTES
+This is used to specify an alternate name, overriding the default name
+specified in the list of engines. If present, it must be first.
+For example:
-If a configuration file attempts to expand a variable that doesn't exist
-then an error is flagged and the file will not load. This can happen
-if an attempt is made to expand an environment variable that doesn't
-exist. For example in a previous version of OpenSSL the default OpenSSL
-master configuration file used the value of B<HOME> which may not be
-defined on non Unix systems and would cause an error.
+ [engines]
+ foo = foo_engine
-This can be worked around by including a B<default> section to provide
-a default value: then if the environment lookup fails the default value
-will be used instead. For this to work properly the default value must
-be defined earlier in the configuration file than the expansion. See
-the B<EXAMPLES> section for an example of how to do this.
+ [foo_engine]
+ engine_id = myfoo
-If the same variable exists in the same section then all but the last
-value will be silently ignored. In certain circumstances such as with
-DNs the same field may occur multiple times. This is usually worked
-around by ignoring any characters before an initial B<.> e.g.
+=item B<dynamic_path>
- 1.OU="My first OU"
- 2.OU="My Second OU"
+This loads and adds an ENGINE from the given path. It is equivalent to
+sending the ctrls B<SO_PATH> with the path argument followed by B<LIST_ADD>
+with value B<2> and B<LOAD> to the dynamic ENGINE. If this is not the
+required behaviour then alternative ctrls can be sent directly to the
+dynamic ENGINE using ctrl commands.
-=head1 EXAMPLES
+=item B<init>
-Here is a sample configuration file using some of the features
-mentioned above.
+This specifies whether to initialize the ENGINE. If the value is B<0> the
+ENGINE will not be initialized, if the value is B<1> an attempt is made
+to initialize
+the ENGINE immediately. If the B<init> command is not present then an
+attempt will be made to initialize the ENGINE after all commands in its
+section have been processed.
- # This is the default section.
+=item B<default_algorithms>
- HOME=/temp
- RANDFILE= ${ENV::HOME}/.rnd
- configdir=$ENV::HOME/config
+This sets the default algorithms an ENGINE will supply using the function
+ENGINE_set_default_string().
- [ section_one ]
+=back
- # We are now in section one.
+All other names are taken to be the name of a ctrl command that is
+sent to the ENGINE, and the value is the argument passed with the command.
+The special value B<EMPTY> means no value is sent with the command.
+For example:
- # Quotes permit leading and trailing whitespace
- any = " any variable name "
+ [engines]
+ foo = foo_engine
- other = A string that can \
- cover several lines \
- by including \\ characters
+ [foo_engine]
+ dynamic_path = /some/path/fooengine.so
+ some_ctrl = some_value
+ default_algorithms = ALL
+ other_ctrl = EMPTY
- message = Hello World\n
+=head2 Random Configuration
- [ section_two ]
+The name B<random> in the initialization section names the section
+containing the random number generater settings.
- greeting = $section_one::message
+Within the random section, the following names have meaning:
-This next example shows how to expand environment variables safely.
+=over 4
-Suppose you want a variable called B<tmpfile> to refer to a
-temporary filename. The directory it is placed in can determined by
-the B<TEMP> or B<TMP> environment variables but they may not be
-set to any value at all. If you just include the environment variable
-names and the variable doesn't exist then this will cause an error when
-an attempt is made to load the configuration file. By making use of the
-default section both values can be looked up with B<TEMP> taking
-priority and B</tmp> used if neither is defined:
+=item B<random>
- TMP=/tmp
- # The above value is used if TMP isn't in the environment
- TEMP=$ENV::TMP
- # The above value is used if TEMP isn't in the environment
- tmpfile=${ENV::TEMP}/tmp.filename
+This is used to specify the random bit generator.
+For example:
-Simple OpenSSL library configuration example to enter FIPS mode:
+ [random]
+ random = CTR-DRBG
- # Default appname: should match "appname" parameter (if any)
- # supplied to CONF_modules_load_file et al.
- openssl_conf = openssl_conf_section
+The available random bit generators are:
- [openssl_conf_section]
- # Configuration module list
- alg_section = evp_sect
+=over 4
- [evp_sect]
- # Set to "yes" to enter FIPS mode if supported
- fips_mode = yes
+=item B<CTR-DRBG>
-Note: in the above example you will get an error in non FIPS capable versions
-of OpenSSL.
+=item B<HASH-DRBG>
-Simple OpenSSL library configuration to make TLS 1.2 and DTLS 1.2 the
-system-default minimum TLS and DTLS versions, respectively:
+=item B<HMAC-DRBG>
- # Toplevel section for openssl (including libssl)
- openssl_conf = default_conf_section
+=back
- [default_conf_section]
- # We only specify configuration for the "ssl module"
- ssl_conf = ssl_section
+=item B<cipher>
- [ssl_section]
- system_default = system_default_section
+This specifies what cipher a B<CTR-DRBG> random bit generator will use.
+Other random bit generators ignore this name.
+The default value is B<AES-256-CTR>.
- [system_default_section]
- MinProtocol = TLSv1.2
- MinProtocol = DTLSv1.2
+=item B<digest>
-The minimum TLS protocol is applied to B<SSL_CTX> objects that are TLS-based,
-and the minimum DTLS protocol to those are DTLS-based.
-The same applies also to maximum versions set with B<MaxProtocol>.
+This specifies what digest the B<HASH-DRBG> or B<HMAC-DRBG> random bit
+generators will use. Other random bit generators ignore this name.
-More complex OpenSSL library configuration. Add OID and don't enter FIPS mode:
+=item B<properties>
- # Default appname: should match "appname" parameter (if any)
- # supplied to CONF_modules_load_file et al.
- openssl_conf = openssl_conf_section
+This sets the property query used when fetching the random bit generator and
+any underlying algorithms.
- [openssl_conf_section]
- # Configuration module list
- alg_section = evp_sect
- oid_section = new_oids
+=item B<seed>
- [evp_sect]
- # This will have no effect as FIPS mode is off by default.
- # Set to "yes" to enter FIPS mode, if supported
- fips_mode = no
+This sets the randomness source that should be used. By default B<SEED-SRC>
+will be used outside of the FIPS provider. The FIPS provider uses call backs
+to access the same randomness sources from outside the validated boundary.
- [new_oids]
- # New OID, just short name
- newoid1 = 1.2.3.4.1
- # New OID shortname and long name
- newoid2 = New OID 2 long name, 1.2.3.4.2
+=item B<seed_properties>
-The above examples can be used with any application supporting library
-configuration if "openssl_conf" is modified to match the appropriate "appname".
+This sets the property query used when fetching the randomness source.
-For example if the second sample file above is saved to "example.cnf" then
-the command line:
+=back
- OPENSSL_CONF=example.cnf openssl asn1parse -genstr OID:1.2.3.4.1
+=head1 EXAMPLES
-will output:
+This example shows how to use quoting and escaping.
- 0:d=0 hl=2 l= 4 prim: OBJECT :newoid1
+ # This is the default section.
+ HOME = /temp
+ configdir = $ENV::HOME/config
-showing that the OID "newoid1" has been added as "1.2.3.4.1".
+ [ section_one ]
+ # Quotes permit leading and trailing whitespace
+ any = " any variable name "
+ other = A string that can \
+ cover several lines \
+ by including \\ characters
+ message = Hello World\n
+
+ [ section_two ]
+ greeting = $section_one::message
+
+This example shows how to expand environment variables safely.
+In this example, the variable B<tempfile> is intended to refer
+to a temporary file, and the environment variable B<TEMP> or
+B<TMP>, if present, specify the directory where the file
+should be put.
+Since the default section is checked if a variable does not
+exist, it is possible to set B<TMP> to default to F</tmp>, and
+B<TEMP> to default to B<TMP>.
+
+ # These two lines must be in the default section.
+ TMP = /tmp
+ TEMP = $ENV::TMP
+
+ # This can be used anywhere
+ tmpfile = ${ENV::TEMP}/tmp.filename
+
+This example shows how to enforce FIPS mode for the application
+F<sample>.
+
+ sample = fips_config
+
+ [fips_config]
+ alg_section = evp_properties
+
+ [evp_properties]
+ default_properties = "fips=yes"
=head1 ENVIRONMENT
@@ -416,7 +521,7 @@ showing that the OID "newoid1" has been added as "1.2.3.4.1".
=item B<OPENSSL_CONF>
-The path to the config file.
+The path to the config file, or the empty string for none.
Ignored in set-user-ID and set-group-ID programs.
=item B<OPENSSL_ENGINES>
@@ -424,30 +529,55 @@ Ignored in set-user-ID and set-group-ID programs.
The path to the engines directory.
Ignored in set-user-ID and set-group-ID programs.
+=item B<OPENSSL_MODULES>
+
+The path to the directory with OpenSSL modules, such as providers.
+Ignored in set-user-ID and set-group-ID programs.
+
+=item B<OPENSSL_CONF_INCLUDE>
+
+The optional path to prepend to all B<.include> paths.
+
=back
=head1 BUGS
-Currently there is no way to include characters using the octal B<\nnn>
-form. Strings are all null terminated so nulls cannot form part of
-the value.
+There is no way to include characters using the octal B<\nnn> form. Strings
+are all null terminated so nulls cannot form part of the value.
The escaping isn't quite right: if you want to use sequences like B<\n>
you can't use any quote escaping on the same line.
-Files are loaded in a single pass. This means that a variable expansion
-will only work if the variables referenced are defined earlier in the
-file.
+The limit that only one directory can be opened and read at a time
+can be considered a bug and should be fixed.
+
+=head1 HISTORY
+
+An undocumented API, NCONF_WIN32(), used a slightly different set
+of parsing rules there were intended to be tailored to
+the Microsoft Windows platform.
+Specifically, the backslash character was not an escape character and
+could be used in pathnames, only the double-quote character was recognized,
+and comments began with a semi-colon.
+This function was deprecated in OpenSSL 3.0; applications with
+configuration files using that syntax will have to be modified.
=head1 SEE ALSO
-L<x509(1)>, L<req(1)>, L<ca(1)>
+L<openssl-x509(1)>, L<openssl-req(1)>, L<openssl-ca(1)>,
+L<openssl-fipsinstall(1)>,
+L<ASN1_generate_nconf(3)>,
+L<EVP_set_default_properties(3)>,
+L<CONF_modules_load(3)>,
+L<CONF_modules_load_file(3)>,
+L<fips_config(5)>, and
+L<x509v3_config(5)>.
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man5/fips_config.pod b/doc/man5/fips_config.pod
new file mode 100644
index 000000000000..cd0012a73a10
--- /dev/null
+++ b/doc/man5/fips_config.pod
@@ -0,0 +1,123 @@
+=pod
+
+=head1 NAME
+
+fips_config - OpenSSL FIPS configuration
+
+=head1 DESCRIPTION
+
+A separate configuration file, using the OpenSSL L<config(5)> syntax,
+is used to hold information about the FIPS module. This includes a digest
+of the shared library file, and status about the self-testing.
+This data is used automatically by the module itself for two
+purposes:
+
+=over 4
+
+=item - Run the startup FIPS self-test known answer tests (KATS).
+
+This is normally done once, at installation time, but may also be set up to
+run each time the module is used.
+
+=item - Verify the module's checksum.
+
+This is done each time the module is used.
+
+=back
+
+This file is generated by the L<openssl-fipsinstall(1)> program, and
+used internally by the FIPS module during its initialization.
+
+The following options are supported. They should all appear in a section
+whose name is identified by the B<fips> option in the B<providers>
+section, as described in L<config(5)/Provider Configuration Module>.
+
+=over 4
+
+=item B<activate>
+
+If present, the module is activated. The value assigned to this name is not
+significant.
+
+=item B<install-version>
+
+A version number for the fips install process. Should be 1.
+
+=item B<conditional-errors>
+
+The FIPS module normally enters an internal error mode if any self test fails.
+Once this error mode is active, no services or cryptographic algorithms are
+accessible from this point on.
+Continuous tests are a subset of the self tests (e.g., a key pair test during key
+generation, or the CRNG output test).
+Setting this value to C<0> allows the error mode to not be triggered if any
+continuous test fails. The default value of C<1> will trigger the error mode.
+Regardless of the value, the operation (e.g., key generation) that called the
+continuous test will return an error code if its continuous test fails. The
+operation may then be retried if the error mode has not been triggered.
+
+=item B<security-checks>
+
+This indicates if run-time checks related to enforcement of security parameters
+such as minimum security strength of keys and approved curve names are used.
+A value of '1' will perform the checks, otherwise if the value is '0' the checks
+are not performed and FIPS compliance must be done by procedures documented in
+the relevant Security Policy.
+
+=item B<module-mac>
+
+The calculated MAC of the FIPS provider file.
+
+=item B<install-status>
+
+An indicator that the self-tests were successfully run.
+This should only be written after the module has
+successfully passed its self tests during installation.
+If this field is not present, then the self tests will run when the module
+loads.
+
+=item B<install-mac>
+
+A MAC of the value of the B<install-status> option, to prevent accidental
+changes to that value.
+It is written-to at the same time as B<install-status> is updated.
+
+=back
+
+For example:
+
+ [fips_sect]
+ activate = 1
+ install-version = 1
+ conditional-errors = 1
+ security-checks = 1
+ module-mac = 41:D0:FA:C2:5D:41:75:CD:7D:C3:90:55:6F:A4:DC
+ install-mac = FE:10:13:5A:D3:B4:C7:82:1B:1E:17:4C:AC:84:0C
+ install-status = INSTALL_SELF_TEST_KATS_RUN
+
+=head1 NOTES
+
+When using the FIPS provider, it is recommended that the
+B<config_diagnostics> option is enabled to prevent accidental use of
+non-FIPS validated algorithms via broken or mistaken configuration.
+See L<config(5)>.
+
+=head1 SEE ALSO
+
+L<config(5)>
+L<openssl-fipsinstall(1)>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man5/x509v3_config.pod b/doc/man5/x509v3_config.pod
index 5c0caa5b2bf6..1830092394bc 100644
--- a/doc/man5/x509v3_config.pod
+++ b/doc/man5/x509v3_config.pod
@@ -6,112 +6,152 @@ x509v3_config - X509 V3 certificate extension configuration format
=head1 DESCRIPTION
-Several of the OpenSSL utilities can add extensions to a certificate or
-certificate request based on the contents of a configuration file.
+Several OpenSSL commands can add extensions to a certificate or
+certificate request based on the contents of a configuration file
+and CLI options such as B<-addext>.
+The syntax of configuration files is described in L<config(5)>.
+The commands typically have an option to specify the name of the configuration
+file, and a section within that file; see the documentation of the
+individual command for details.
-Typically the application will contain an option to point to an extension
-section. Each line of the extension section takes the form:
+This page uses B<extensions> as the name of the section, when needed
+in examples.
- extension_name=[critical,] extension_options
+Each entry in the extension section takes the form:
-If B<critical> is present then the extension will be critical.
+ name = [critical, ]value(s)
-The format of B<extension_options> depends on the value of B<extension_name>.
+If B<critical> is present then the extension will be marked as critical.
-There are four main types of extension: I<string> extensions, I<multi-valued>
-extensions, I<raw> and I<arbitrary> extensions.
+If multiple entries are processed for the same extension name,
+later entries override earlier ones with the same name.
-String extensions simply have a string which contains either the value itself
-or how it is obtained.
+The format of B<values> depends on the value of B<name>, many have a
+type-value pairing where the type and value are separated by a colon.
+There are four main types of extension:
-For example:
+ string
+ multi-valued
+ raw
+ arbitrary
- nsComment="This is a Comment"
+Each is described in the following paragraphs.
+
+String extensions simply have a string which contains either the value itself
+or how it is obtained.
Multi-valued extensions have a short form and a long form. The short form
-is a list of names and values:
+is a comma-separated list of names and values:
- basicConstraints=critical,CA:true,pathlen:1
+ basicConstraints = critical, CA:true, pathlen:1
The long form allows the values to be placed in a separate section:
- basicConstraints=critical,@bs_section
-
- [bs_section]
+ [extensions]
+ basicConstraints = critical, @basic_constraints
- CA=true
- pathlen=1
+ [basic_constraints]
+ CA = true
+ pathlen = 1
Both forms are equivalent.
-The syntax of raw extensions is governed by the extension code: it can
-for example contain data in multiple sections. The correct syntax to
-use is defined by the extension code itself: check out the certificate
-policies extension for an example.
+If an extension is multi-value and a field value must contain a comma the long
+form must be used otherwise the comma would be misinterpreted as a field
+separator. For example:
-If an extension type is unsupported then the I<arbitrary> extension syntax
-must be used, see the L<ARBITRARY EXTENSIONS|/"ARBITRARY EXTENSIONS"> section for more details.
+ subjectAltName = URI:ldap://somehost.com/CN=foo,OU=bar
-=head1 STANDARD EXTENSIONS
+will produce an error but the equivalent form:
-The following sections describe each supported extension in detail.
+ [extensions]
+ subjectAltName = @subject_alt_section
-=head2 Basic Constraints.
+ [subject_alt_section]
+ subjectAltName = URI:ldap://somehost.com/CN=foo,OU=bar
-This is a multi valued extension which indicates whether a certificate is
-a CA certificate. The first (mandatory) name is B<CA> followed by B<TRUE> or
-B<FALSE>. If B<CA> is B<TRUE> then an optional B<pathlen> name followed by a
-nonnegative value can be included.
+is valid.
-For example:
+OpenSSL does not support multiple occurrences of the same field within a
+section. In this example:
+
+ [extensions]
+ subjectAltName = @alt_section
+
+ [alt_section]
+ email = steve@example.com
+ email = steve@example.org
- basicConstraints=CA:TRUE
+will only recognize the last value. To specify multiple values append a
+numeric identifier, as shown here:
- basicConstraints=CA:FALSE
+ [extensions]
+ subjectAltName = @alt_section
- basicConstraints=critical,CA:TRUE, pathlen:0
+ [alt_section]
+ email.1 = steve@example.com
+ email.2 = steve@example.org
-A CA certificate B<must> include the basicConstraints value with the CA field
-set to TRUE. An end user certificate must either set CA to FALSE or exclude the
-extension entirely. Some software may require the inclusion of basicConstraints
-with CA set to FALSE for end entity certificates.
+The syntax of raw extensions is defined by the source code that parses
+the extension but should be documened.
+See L</Certificate Policies> for an example of a raw extension.
-The pathlen parameter indicates the maximum number of CAs that can appear
-below this one in a chain. So if you have a CA with a pathlen of zero it can
-only be used to sign end user certificates and not further CAs.
+If an extension type is unsupported, then the I<arbitrary> extension syntax
+must be used, see the L</ARBITRARY EXTENSIONS> section for more details.
+=head1 STANDARD EXTENSIONS
-=head2 Key Usage.
+The following sections describe the syntax of each supported extension.
+They do not define the semantics of the extension.
-Key usage is a multi valued extension consisting of a list of names of the
-permitted key usages.
+=head2 Basic Constraints
-The supported names are: digitalSignature, nonRepudiation, keyEncipherment,
-dataEncipherment, keyAgreement, keyCertSign, cRLSign, encipherOnly
-and decipherOnly.
+This is a multi-valued extension which indicates whether a certificate is
+a CA certificate. The first value is B<CA> followed by B<TRUE> or
+B<FALSE>. If B<CA> is B<TRUE> then an optional B<pathlen> name followed by a
+nonnegative value can be included.
-Examples:
+For example:
+
+ basicConstraints = CA:TRUE
+
+ basicConstraints = CA:FALSE
+
+ basicConstraints = critical, CA:TRUE, pathlen:1
- keyUsage=digitalSignature, nonRepudiation
+A CA certificate I<must> include the B<basicConstraints> name with the B<CA>
+parameter set to B<TRUE>. An end-user certificate must either have B<CA:FALSE>
+or omit the extension entirely.
+The B<pathlen> parameter specifies the maximum number of CAs that can appear
+below this one in a chain. A B<pathlen> of zero means the CA cannot sign
+any sub-CA's, and can only sign end-entity certificates.
- keyUsage=critical, keyCertSign
+=head2 Key Usage
+
+Key usage is a multi-valued extension consisting of a list of names of
+the permitted key usages. The defined values are: C<digitalSignature>,
+C<nonRepudiation>, C<keyEncipherment>, C<dataEncipherment>, C<keyAgreement>,
+C<keyCertSign>, C<cRLSign>, C<encipherOnly>, and C<decipherOnly>.
+
+Examples:
+ keyUsage = digitalSignature, nonRepudiation
-=head2 Extended Key Usage.
+ keyUsage = critical, keyCertSign
-This extensions consists of a list of usages indicating purposes for which
-the certificate public key can be used for,
+=head2 Extended Key Usage
-These can either be object short names or the dotted numerical form of OIDs.
-While any OID can be used only certain values make sense. In particular the
-following PKIX, NS and MS values are meaningful:
+This extension consists of a list of values indicating purposes for which
+the certificate public key can be used.
+Each value can be either a short text name or an OID.
+The following text names, and their intended meaning, are known:
- Value Meaning
- ----- -------
- serverAuth SSL/TLS Web Server Authentication.
- clientAuth SSL/TLS Web Client Authentication.
- codeSigning Code signing.
- emailProtection E-mail Protection (S/MIME).
+ Value Meaning according to RFC 5280 etc.
+ ----- ----------------------------------
+ serverAuth SSL/TLS WWW Server Authentication
+ clientAuth SSL/TLS WWW Client Authentication
+ codeSigning Code Signing
+ emailProtection E-mail Protection (S/MIME)
timeStamping Trusted Timestamping
OCSPSigning OCSP Signing
ipsecIKE ipsec Internet Key Exchange
@@ -120,244 +160,306 @@ following PKIX, NS and MS values are meaningful:
msCTLSign Microsoft Trust List Signing
msEFS Microsoft Encrypted File System
+While IETF RFC 5280 says that B<id-kp-serverAuth> and B<id-kp-clientAuth>
+are only for WWW use, in practice they are used for all kinds of TLS clients
+and servers, and this is what OpenSSL assumes as well.
+
Examples:
- extendedKeyUsage=critical,codeSigning,1.2.3.4
- extendedKeyUsage=serverAuth,clientAuth
+ extendedKeyUsage = critical, codeSigning, 1.2.3.4
+ extendedKeyUsage = serverAuth, clientAuth
-=head2 Subject Key Identifier.
+=head2 Subject Key Identifier
-This is really a string extension and can take two possible values. Either
-the word B<hash> which will automatically follow the guidelines in RFC3280
-or a hex string giving the extension value to include. The use of the hex
-string is strongly discouraged.
+The SKID extension specification has a value with three choices.
+If the value is the word B<none> then no SKID extension will be included.
+If the value is the word B<hash>, or by default for the B<x509>, B<req>, and
+B<ca> apps, the process specified in RFC 5280 section 4.2.1.2. (1) is followed:
+The keyIdentifier is composed of the 160-bit SHA-1 hash of the value of the BIT
+STRING subjectPublicKey (excluding the tag, length, and number of unused bits).
-Example:
+Otherwise, the value must be a hex string (possibly with C<:> separating bytes)
+to output directly, however, this is strongly discouraged.
- subjectKeyIdentifier=hash
+Example:
+ subjectKeyIdentifier = hash
-=head2 Authority Key Identifier.
+=head2 Authority Key Identifier
-The authority key identifier extension permits two options. keyid and issuer:
-both can take the optional value "always".
+The AKID extension specification may have the value B<none>
+indicating that no AKID shall be included.
+Otherwise it may have the value B<keyid> or B<issuer>
+or both of them, separated by C<,>.
+Either or both can have the option B<always>,
+indicated by putting a colon C<:> between the value and this option.
+For self-signed certificates the AKID is suppressed unless B<always> is present.
+By default the B<x509>, B<req>, and B<ca> apps behave as if
+"none" was given for self-signed certificates and "keyid, issuer" otherwise.
-If the keyid option is present an attempt is made to copy the subject key
-identifier from the parent certificate. If the value "always" is present
-then an error is returned if the option fails.
+If B<keyid> is present, an attempt is made to
+copy the subject key identifier (SKID) from the issuer certificate except if
+the issuer certificate is the same as the current one and it is not self-signed.
+The hash of the public key related to the signing key is taken as fallback
+if the issuer certificate is the same as the current certificate.
+If B<always> is present but no value can be obtained, an error is returned.
-The issuer option copies the issuer and serial number from the issuer
-certificate. This will only be done if the keyid option fails or
-is not included unless the "always" flag will always include the value.
+If B<issuer> is present, and in addition it has the option B<always> specified
+or B<keyid> is not present,
+then the issuer DN and serial number are copied from the issuer certificate.
-Example:
+Examples:
- authorityKeyIdentifier=keyid,issuer
+ authorityKeyIdentifier = keyid, issuer
+ authorityKeyIdentifier = keyid, issuer:always
-=head2 Subject Alternative Name.
+=head2 Subject Alternative Name
-The subject alternative name extension allows various literal values to be
-included in the configuration file. These include B<email> (an email address)
-B<URI> a uniform resource indicator, B<DNS> (a DNS domain name), B<RID> (a
-registered ID: OBJECT IDENTIFIER), B<IP> (an IP address), B<dirName>
-(a distinguished name) and otherName.
+This is a multi-valued extension that supports several types of name
+identifier, including
+B<email> (an email address),
+B<URI> (a uniform resource indicator),
+B<DNS> (a DNS domain name),
+B<RID> (a registered ID: OBJECT IDENTIFIER),
+B<IP> (an IP address),
+B<dirName> (a distinguished name),
+and B<otherName>.
+The syntax of each is described in the following paragraphs.
-The email option include a special 'copy' value. This will automatically
-include any email addresses contained in the certificate subject name in
-the extension.
+The B<email> option has two special values.
+C<copy> will automatically include any email addresses
+contained in the certificate subject name in the extension.
+C<move> will automatically move any email addresses
+from the certificate subject name to the extension.
-The IP address used in the B<IP> options can be in either IPv4 or IPv6 format.
+The IP address used in the B<IP> option can be in either IPv4 or IPv6 format.
-The value of B<dirName> should point to a section containing the distinguished
-name to use as a set of name value pairs. Multi values AVAs can be formed by
-prefacing the name with a B<+> character.
+The value of B<dirName> is specifies the configuration section containing
+the distinguished name to use, as a set of name-value pairs.
+Multi-valued AVAs can be formed by prefacing the name with a B<+> character.
-otherName can include arbitrary data associated with an OID: the value
-should be the OID followed by a semicolon and the content in standard
-L<ASN1_generate_nconf(3)> format.
+The value of B<otherName> can include arbitrary data associated with an OID;
+the value should be the OID followed by a semicolon and the content in specified
+using the syntax in L<ASN1_generate_nconf(3)>.
Examples:
- subjectAltName=email:copy,email:my@other.address,URI:http://my.url.here/
- subjectAltName=IP:192.168.7.1
- subjectAltName=IP:13::17
- subjectAltName=email:my@other.address,RID:1.2.3.4
- subjectAltName=otherName:1.2.3.4;UTF8:some other identifier
+ subjectAltName = email:copy, email:my@example.com, URI:http://my.example.com/
+
+ subjectAltName = IP:192.168.7.1
- subjectAltName=dirName:dir_sect
+ subjectAltName = IP:13::17
+
+ subjectAltName = email:my@example.com, RID:1.2.3.4
+
+ subjectAltName = otherName:1.2.3.4;UTF8:some other identifier
+
+ [extensions]
+ subjectAltName = dirName:dir_sect
[dir_sect]
- C=UK
- O=My Organization
- OU=My Unit
- CN=My Name
+ C = UK
+ O = My Organization
+ OU = My Unit
+ CN = My Name
+Non-ASCII Email Address conforming the syntax defined in Section 3.3 of RFC 6531
+are provided as otherName.SmtpUTF8Mailbox. According to RFC 8398, the email
+address should be provided as UTF8String. To enforce the valid representation in
+the certificate, the SmtpUTF8Mailbox should be provided as follows
-=head2 Issuer Alternative Name.
+ subjectAltName=@alts
+ [alts]
+ otherName = 1.3.6.1.5.5.7.8.9;FORMAT:UTF8,UTF8String:nonasciiname.example.com
-The issuer alternative name option supports all the literal options of
-subject alternative name. It does B<not> support the email:copy option because
-that would not make sense. It does support an additional issuer:copy option
-that will copy all the subject alternative name values from the issuer
-certificate (if possible).
+=head2 Issuer Alternative Name
+
+This extension supports most of the options of subject alternative name;
+it does not support B<email:copy>.
+It also adds B<issuer:copy> as an allowed value, which copies any subject
+alternative names from the issuer certificate, if possible.
Example:
issuerAltName = issuer:copy
+=head2 Authority Info Access
-=head2 Authority Info Access.
+This extension gives details about how to retrieve information that
+related to the certificate that the CA makes available. The syntax is
+B<access_id;location>, where B<access_id> is an object identifier
+(although only a few values are well-known) and B<location> has the same
+syntax as subject alternative name (except that B<email:copy> is not supported).
-The authority information access extension gives details about how to access
-certain information relating to the CA. Its syntax is accessOID;location
-where I<location> has the same syntax as subject alternative name (except
-that email:copy is not supported). accessOID can be any valid OID but only
-certain values are meaningful, for example OCSP and caIssuers.
+Possible values for access_id include B<OCSP> (OCSP responder),
+B<caIssuers> (CA Issuers),
+B<ad_timestamping> (AD Time Stamping),
+B<AD_DVCS> (ad dvcs),
+B<caRepository> (CA Repository).
-Example:
+Examples:
- authorityInfoAccess = OCSP;URI:http://ocsp.my.host/
- authorityInfoAccess = caIssuers;URI:http://my.ca/ca.html
+ authorityInfoAccess = OCSP;URI:http://ocsp.example.com/,caIssuers;URI:http://myca.example.com/ca.cer
+ authorityInfoAccess = OCSP;URI:http://ocsp.example.com/
=head2 CRL distribution points
-This is a multi-valued extension whose options can be either in name:value pair
-using the same form as subject alternative name or a single value representing
-a section name containing all the distribution point fields.
+This is a multi-valued extension whose values can be either a name-value
+pair using the same form as subject alternative name or a single value
+specifying the section name containing all the distribution point values.
+
+When a name-value pair is used, a DistributionPoint extension will
+be set with the given value as the fullName field as the distributionPoint
+value, and the reasons and cRLIssuer fields will be omitted.
+
+When a single option is used, the value specifies the section, and that
+section can have the following items:
+
+=over 4
+
+=item fullname
+
+The full name of the distribution point, in the same format as the subject
+alternative name.
+
+=item relativename
-For a name:value pair a new DistributionPoint with the fullName field set to
-the given value both the cRLissuer and reasons fields are omitted in this case.
+The value is taken as a distinguished name fragment that is set as the
+value of the nameRelativeToCRLIssuer field.
-In the single option case the section indicated contains values for each
-field. In this section:
+=item CRLIssuer
-If the name is "fullname" the value field should contain the full name
-of the distribution point in the same format as subject alternative name.
+The value must in the same format as the subject alternative name.
-If the name is "relativename" then the value field should contain a section
-name whose contents represent a DN fragment to be placed in this field.
+=item reasons
-The name "CRLIssuer" if present should contain a value for this field in
-subject alternative name format.
+A multi-value field that contains the reasons for revocation. The recognized
+values are: C<keyCompromise>, C<CACompromise>, C<affiliationChanged>,
+C<superseded>, C<cessationOfOperation>, C<certificateHold>,
+C<privilegeWithdrawn>, and C<AACompromise>.
-If the name is "reasons" the value field should consist of a comma
-separated field containing the reasons. Valid reasons are: "keyCompromise",
-"CACompromise", "affiliationChanged", "superseded", "cessationOfOperation",
-"certificateHold", "privilegeWithdrawn" and "AACompromise".
+=back
+Only one of B<fullname> or B<relativename> should be specified.
Simple examples:
- crlDistributionPoints=URI:http://myhost.com/myca.crl
- crlDistributionPoints=URI:http://my.com/my.crl,URI:http://oth.com/my.crl
+ crlDistributionPoints = URI:http://example.com/myca.crl
+
+ crlDistributionPoints = URI:http://example.com/myca.crl, URI:http://example.org/my.crl
Full distribution point example:
- crlDistributionPoints=crldp1_section
+ [extensions]
+ crlDistributionPoints = crldp1_section
[crldp1_section]
-
- fullname=URI:http://myhost.com/myca.crl
- CRLissuer=dirName:issuer_sect
- reasons=keyCompromise, CACompromise
+ fullname = URI:http://example.com/myca.crl
+ CRLissuer = dirName:issuer_sect
+ reasons = keyCompromise, CACompromise
[issuer_sect]
- C=UK
- O=Organisation
- CN=Some Name
+ C = UK
+ O = Organisation
+ CN = Some Name
=head2 Issuing Distribution Point
-This extension should only appear in CRLs. It is a multi valued extension
+This extension should only appear in CRLs. It is a multi-valued extension
whose syntax is similar to the "section" pointed to by the CRL distribution
-points extension with a few differences.
+points extension. The following names have meaning:
-The names "reasons" and "CRLissuer" are not recognized.
+=over 4
-The name "onlysomereasons" is accepted which sets this field. The value is
-in the same format as the CRL distribution point "reasons" field.
+=item fullname
-The names "onlyuser", "onlyCA", "onlyAA" and "indirectCRL" are also accepted
-the values should be a boolean value (TRUE or FALSE) to indicate the value of
-the corresponding field.
+The full name of the distribution point, in the same format as the subject
+alternative name.
-Example:
+=item relativename
- issuingDistributionPoint=critical, @idp_section
+The value is taken as a distinguished name fragment that is set as the
+value of the nameRelativeToCRLIssuer field.
- [idp_section]
+=item onlysomereasons
- fullname=URI:http://myhost.com/myca.crl
- indirectCRL=TRUE
- onlysomereasons=keyCompromise, CACompromise
+A multi-value field that contains the reasons for revocation. The recognized
+values are: C<keyCompromise>, C<CACompromise>, C<affiliationChanged>,
+C<superseded>, C<cessationOfOperation>, C<certificateHold>,
+C<privilegeWithdrawn>, and C<AACompromise>.
- [issuer_sect]
- C=UK
- O=Organisation
- CN=Some Name
+=item onlyuser, onlyCA, onlyAA, indirectCRL
+The value for each of these names is a boolean.
-=head2 Certificate Policies.
+=back
-This is a I<raw> extension. All the fields of this extension can be set by
-using the appropriate syntax.
+Example:
-If you follow the PKIX recommendations and just using one OID then you just
-include the value of that OID. Multiple OIDs can be set separated by commas,
-for example:
+ [extensions]
+ issuingDistributionPoint = critical, @idp_section
- certificatePolicies= 1.2.4.5, 1.1.3.4
+ [idp_section]
+ fullname = URI:http://example.com/myca.crl
+ indirectCRL = TRUE
+ onlysomereasons = keyCompromise, CACompromise
-If you wish to include qualifiers then the policy OID and qualifiers need to
-be specified in a separate section: this is done by using the @section syntax
-instead of a literal OID value.
+=head2 Certificate Policies
+
+This is a I<raw> extension that supports all of the defined fields of the
+certificate extension.
+
+Policies without qualifiers are specified by giving the OID.
+Multiple policies are comma-separated. For example:
+
+ certificatePolicies = 1.2.4.5, 1.1.3.4
+
+To include policy qualifiers, use the "@section" syntax to point to a
+section that specifies all the information.
The section referred to must include the policy OID using the name
-policyIdentifier, cPSuri qualifiers can be included using the syntax:
+B<policyIdentifier>. cPSuri qualifiers can be included using the syntax:
+
+ CPS.nnn = value
- CPS.nnn=value
+where C<nnn> is a number.
userNotice qualifiers can be set using the syntax:
- userNotice.nnn=@notice
+ userNotice.nnn = @notice
The value of the userNotice qualifier is specified in the relevant section.
-This section can include explicitText, organization and noticeNumbers
+This section can include B<explicitText>, B<organization>, and B<noticeNumbers>
options. explicitText and organization are text strings, noticeNumbers is a
comma separated list of numbers. The organization and noticeNumbers options
-(if included) must BOTH be present. If you use the userNotice option with IE5
-then you need the 'ia5org' option at the top level to modify the encoding:
-otherwise it will not be interpreted properly.
+(if included) must BOTH be present. Some software might require
+the B<ia5org> option at the top level; this changes the encoding from
+Displaytext to IA5String.
Example:
- certificatePolicies=ia5org,1.2.3.4,1.5.6.7.8,@polsect
+ [extensions]
+ certificatePolicies = ia5org, 1.2.3.4, 1.5.6.7.8, @polsect
[polsect]
-
policyIdentifier = 1.3.5.8
- CPS.1="http://my.host.name/"
- CPS.2="http://my.your.name/"
- userNotice.1=@notice
+ CPS.1 = "http://my.host.example.com/"
+ CPS.2 = "http://my.your.example.com/"
+ userNotice.1 = @notice
[notice]
+ explicitText = "Explicit Text Here"
+ organization = "Organisation Name"
+ noticeNumbers = 1, 2, 3, 4
- explicitText="Explicit Text Here"
- organization="Organisation Name"
- noticeNumbers=1,2,3,4
-
-The B<ia5org> option changes the type of the I<organization> field. In RFC2459
-it can only be of type DisplayText. In RFC3280 IA5String is also permissible.
-Some software (for example some versions of MSIE) may require ia5org.
-
-ASN1 type of explicitText can be specified by prepending B<UTF8>,
-B<BMP> or B<VISIBLE> prefix followed by colon. For example:
+The character encoding of explicitText can be specified by prefixing the
+value with B<UTF8>, B<BMP>, or B<VISIBLE> followed by colon. For example:
[notice]
- explicitText="UTF8:Explicit Text Here"
+ explicitText = "UTF8:Explicit Text Here"
=head2 Policy Constraints
@@ -369,7 +471,6 @@ Example:
policyConstraints = requireExplicitPolicy:3
-
=head2 Inhibit Any Policy
This is a string extension whose value must be a non negative integer.
@@ -378,33 +479,31 @@ Example:
inhibitAnyPolicy = 2
-
=head2 Name Constraints
-The name constraints extension is a multi-valued extension. The name should
+This is a multi-valued extension. The name should
begin with the word B<permitted> or B<excluded> followed by a B<;>. The rest of
-the name and the value follows the syntax of subjectAltName except email:copy
+the name and the value follows the syntax of subjectAltName except
+B<email:copy>
is not supported and the B<IP> form should consist of an IP addresses and
subnet mask separated by a B</>.
Examples:
- nameConstraints=permitted;IP:192.168.0.0/255.255.0.0
-
- nameConstraints=permitted;email:.somedomain.com
+ nameConstraints = permitted;IP:192.168.0.0/255.255.0.0
- nameConstraints=excluded;email:.com
+ nameConstraints = permitted;email:.example.com
+ nameConstraints = excluded;email:.com
=head2 OCSP No Check
-The OCSP No Check extension is a string extension but its value is ignored.
+This is a string extension. It is parsed, but ignored.
Example:
noCheck = ignored
-
=head2 TLS Feature (aka Must Staple)
This is a multi-valued extension consisting of a list of TLS extension
@@ -418,26 +517,19 @@ Example:
tlsfeature = status_request
-
=head1 DEPRECATED EXTENSIONS
The following extensions are non standard, Netscape specific and largely
obsolete. Their use in new applications is discouraged.
-=head2 Netscape String extensions.
+=head2 Netscape String extensions
Netscape Comment (B<nsComment>) is a string extension containing a comment
which will be displayed when the certificate is viewed in some browsers.
-
-Example:
-
- nsComment = "Some Random Comment"
-
-Other supported extensions in this category are: B<nsBaseUrl>,
+Other extensions of this type are: B<nsBaseUrl>,
B<nsRevocationUrl>, B<nsCaRevocationUrl>, B<nsRenewalUrl>, B<nsCaPolicyUrl>
and B<nsSslServerName>.
-
=head2 Netscape Certificate Type
This is a multi-valued extensions which consists of a list of flags to be
@@ -448,7 +540,6 @@ now used instead.
Acceptable values for nsCertType are: B<client>, B<server>, B<email>,
B<objsign>, B<reserved>, B<sslCA>, B<emailCA>, B<objCA>.
-
=head1 ARBITRARY EXTENSIONS
If an extension is not supported by the OpenSSL code then it must be encoded
@@ -462,26 +553,25 @@ The first way is to use the word ASN1 followed by the extension content
using the same syntax as L<ASN1_generate_nconf(3)>.
For example:
- 1.2.3.4=critical,ASN1:UTF8String:Some random data
-
- 1.2.3.4=ASN1:SEQUENCE:seq_sect
+ [extensions]
+ 1.2.3.4 = critical, ASN1:UTF8String:Some random data
+ 1.2.3.4.1 = ASN1:SEQUENCE:seq_sect
[seq_sect]
-
field1 = UTF8:field1
field2 = UTF8:field2
It is also possible to use the word DER to include the raw encoded data in any
extension.
- 1.2.3.4=critical,DER:01:02:03:04
- 1.2.3.4=DER:01020304
+ 1.2.3.4 = critical, DER:01:02:03:04
+ 1.2.3.4.1 = DER:01020304
The value following DER is a hex dump of the DER encoding of the extension
Any extension can be placed in this form to override the default behaviour.
For example:
- basicConstraints=critical,DER:00:01:02:03
+ basicConstraints = critical, DER:00:01:02:03
=head1 WARNINGS
@@ -491,52 +581,18 @@ purposes prohibited by their extensions because a specific application does
not recognize or honour the values of the relevant extensions.
The DER and ASN1 options should be used with caution. It is possible to create
-totally invalid extensions if they are not used carefully.
-
-=head1 NOTES
-
-If an extension is multi-value and a field value must contain a comma the long
-form must be used otherwise the comma would be misinterpreted as a field
-separator. For example:
-
- subjectAltName=URI:ldap://somehost.com/CN=foo,OU=bar
-
-will produce an error but the equivalent form:
-
- subjectAltName=@subject_alt_section
-
- [subject_alt_section]
- subjectAltName=URI:ldap://somehost.com/CN=foo,OU=bar
-
-is valid.
-
-Due to the behaviour of the OpenSSL B<conf> library the same field name
-can only occur once in a section. This means that:
-
- subjectAltName=@alt_section
-
- [alt_section]
-
- email=steve@here
- email=steve@there
-
-will only recognize the last value. This can be worked around by using the form:
-
- [alt_section]
-
- email.1=steve@here
- email.2=steve@there
+invalid extensions if they are not used carefully.
=head1 SEE ALSO
-L<req(1)>, L<ca(1)>, L<x509(1)>,
+L<openssl-req(1)>, L<openssl-ca(1)>, L<openssl-x509(1)>,
L<ASN1_generate_nconf(3)>
=head1 COPYRIGHT
-Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man7/EVP_ASYM_CIPHER-RSA.pod b/doc/man7/EVP_ASYM_CIPHER-RSA.pod
new file mode 100644
index 000000000000..c68cad6c42f9
--- /dev/null
+++ b/doc/man7/EVP_ASYM_CIPHER-RSA.pod
@@ -0,0 +1,90 @@
+=pod
+
+=head1 NAME
+
+EVP_ASYM_CIPHER-RSA
+- RSA Asymmetric Cipher algorithm support
+
+=head1 DESCRIPTION
+
+Asymmetric Cipher support for the B<RSA> key type.
+
+=head2 RSA Asymmetric Cipher parameters
+
+=over 4
+
+=item "pad-mode" (B<OSSL_ASYM_CIPHER_PARAM_PAD_MODE>) <UTF8 string>
+
+The default provider understands these RSA padding modes in string form:
+
+=over 4
+
+=item "none" (B<OSSL_PKEY_RSA_PAD_MODE_NONE>)
+
+=item "oaep" (B<OSSL_PKEY_RSA_PAD_MODE_OAEP>)
+
+=item "pkcs1" (B<OSSL_PKEY_RSA_PAD_MODE_PKCSV15>)
+
+=item "x931" (B<OSSL_PKEY_RSA_PAD_MODE_X931>)
+
+=back
+
+=item "pad-mode" (B<OSSL_ASYM_CIPHER_PARAM_PAD_MODE>) <integer>
+
+The default provider understands these RSA padding modes in integer form:
+
+=over 4
+
+=item 1 (B<RSA_PKCS1_PADDING>)
+
+=item 3 (B<RSA_NO_PADDING>)
+
+=item 4 (B<RSA_PKCS1_OAEP_PADDING>)
+
+=item 5 (B<RSA_X931_PADDING>)
+
+=back
+
+See L<EVP_PKEY_CTX_set_rsa_padding(3)> for further details.
+
+=item "digest" (B<OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST>) <UTF8 string>
+
+=item "digest-props" (B<OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS>) <UTF8 string>
+
+=item "mgf1-digest" (B<OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST>) <UTF8 string>
+
+=item "mgf1-digest-props" (B<OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS>) <UTF8 string>
+
+=item "oaep-label" (B<OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL>) <octet string>
+
+=item "tls-client-version" (B<OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION>) <unsigned integer>
+
+See B<RSA_PKCS1_WITH_TLS_PADDING> on the page L<EVP_PKEY_CTX_set_rsa_padding(3)>.
+
+=item "tls-negotiated-version" (B<OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION>) <unsigned integer>
+
+See B<RSA_PKCS1_WITH_TLS_PADDING> on the page L<EVP_PKEY_CTX_set_rsa_padding(3)>.
+
+See L<provider-asym_cipher(7)/Asymmetric Cipher Parameters> for more information.
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_PKEY-RSA(7)>,
+L<EVP_PKEY(3)>,
+L<provider-asym_cipher(7)>,
+L<provider-keymgmt(7)>,
+L<OSSL_PROVIDER-default(7)>
+L<OSSL_PROVIDER-FIPS(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_ASYM_CIPHER-SM2.pod b/doc/man7/EVP_ASYM_CIPHER-SM2.pod
new file mode 100644
index 000000000000..27f0032b78d1
--- /dev/null
+++ b/doc/man7/EVP_ASYM_CIPHER-SM2.pod
@@ -0,0 +1,41 @@
+=pod
+
+=head1 NAME
+
+EVP_ASYM_CIPHER-SM2
+- SM2 Asymmetric Cipher algorithm support
+
+=head1 DESCRIPTION
+
+Asymmetric Cipher support for the B<SM2> key type.
+
+=head2 SM2 Asymmetric Cipher parameters
+
+=over 4
+
+=item "digest" (B<OSSL_ASYM_CIPHER_PARAM_DIGEST>) <UTF8 string>
+
+=item "digest-props" (B<OSSL_ASYM_CIPHER_PARAM_DIGEST_PROPS>) <UTF8 string>
+
+See L<provider-asym_cipher(7)/Asymmetric Cipher Parameters>.
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_PKEY-SM2(7)>,
+L<EVP_PKEY(3)>,
+L<provider-asym_cipher(7)>,
+L<provider-keymgmt(7)>,
+L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_CIPHER-AES.pod b/doc/man7/EVP_CIPHER-AES.pod
new file mode 100644
index 000000000000..2c790d9cbd9e
--- /dev/null
+++ b/doc/man7/EVP_CIPHER-AES.pod
@@ -0,0 +1,77 @@
+=pod
+
+=head1 NAME
+
+EVP_CIPHER-AES - The AES EVP_CIPHER implementations
+
+=head1 DESCRIPTION
+
+Support for AES symmetric encryption using the B<EVP_CIPHER> API.
+
+=head2 Algorithm Names
+
+The following algorithms are available in the FIPS provider as well as the
+default provider:
+
+=over 4
+
+=item "AES-128-CBC", "AES-192-CBC" and "AES-256-CBC"
+
+=item "AES-128-CBC-CTS", "AES-192-CBC-CTS" and "AES-256-CBC-CTS"
+
+=item "AES-128-CFB", "AES-192-CFB", "AES-256-CFB",
+"AES-128-CFB1", "AES-192-CFB1", "AES-256-CFB1",
+"AES-128-CFB8", "AES-192-CFB8" and "AES-256-CFB8"
+
+=item "AES-128-CTR", "AES-192-CTR" and "AES-256-CTR"
+
+=item "AES-128-ECB", "AES-192-ECB" and "AES-256-ECB"
+
+=item "AES-192-OFB", "AES-128-OFB" and "AES-256-OFB"
+
+=item "AES-128-XTS" and "AES-256-XTS"
+
+=item "AES-128-CCM", "AES-192-CCM" and "AES-256-CCM"
+
+=item "AES-128-GCM", "AES-192-GCM" and "AES-256-GCM"
+
+=item "AES-128-WRAP", "AES-192-WRAP", "AES-256-WRAP",
+"AES-128-WRAP-PAD", "AES-192-WRAP-PAD", "AES-256-WRAP-PAD",
+"AES-128-WRAP-INV", "AES-192-WRAP-INV", "AES-256-WRAP-INV",
+"AES-128-WRAP-PAD-INV", "AES-192-WRAP-PAD-INV" and "AES-256-WRAP-PAD-INV"
+
+=item "AES-128-CBC-HMAC-SHA1", "AES-256-CBC-HMAC-SHA1",
+"AES-128-CBC-HMAC-SHA256" and "AES-256-CBC-HMAC-SHA256"
+
+=back
+
+The following algorithms are available in the default provider, but not the
+FIPS provider:
+
+=over 4
+
+=item "AES-128-OCB", "AES-192-OCB" and "AES-256-OCB"
+
+=item "AES-128-SIV", "AES-192-SIV" and "AES-256-SIV"
+
+=back
+
+=head2 Parameters
+
+This implementation supports the parameters described in
+L<EVP_EncryptInit(3)/PARAMETERS>.
+
+=head1 SEE ALSO
+
+L<provider-cipher(7)>, L<OSSL_PROVIDER-FIPS(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_CIPHER-ARIA.pod b/doc/man7/EVP_CIPHER-ARIA.pod
new file mode 100644
index 000000000000..0528741665e8
--- /dev/null
+++ b/doc/man7/EVP_CIPHER-ARIA.pod
@@ -0,0 +1,55 @@
+=pod
+
+=head1 NAME
+
+EVP_CIPHER-ARIA - The ARIA EVP_CIPHER implementations
+
+=head1 DESCRIPTION
+
+Support for ARIA symmetric encryption using the B<EVP_CIPHER> API.
+
+=head2 Algorithm Names
+
+The following algorithms are available in the default provider:
+
+=over 4
+
+=item "ARIA-128-CBC", "ARIA-192-CBC" and "ARIA-256-CBC"
+
+=item "ARIA-128-CFB", "ARIA-192-CFB", "ARIA-256-CFB",
+"ARIA-128-CFB1", "ARIA-192-CFB1", "ARIA-256-CFB1",
+"ARIA-128-CFB8", "ARIA-192-CFB8" and "ARIA-256-CFB8"
+
+=item "ARIA-128-CTR", "ARIA-192-CTR" and "ARIA-256-CTR"
+
+=item "ARIA-128-ECB", "ARIA-192-ECB" and "ARIA-256-ECB"
+
+=item "AES-192-OCB", "AES-128-OCB" and "AES-256-OCB"
+
+=item "ARIA-128-OFB", "ARIA-192-OFB" and "ARIA-256-OFB"
+
+=item "ARIA-128-CCM", "ARIA-192-CCM" and "ARIA-256-CCM"
+
+=item "ARIA-128-GCM", "ARIA-192-GCM" and "ARIA-256-GCM"
+
+=back
+
+=head2 Parameters
+
+This implementation supports the parameters described in
+L<EVP_EncryptInit(3)/PARAMETERS>.
+
+=head1 SEE ALSO
+
+L<provider-cipher(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_CIPHER-BLOWFISH.pod b/doc/man7/EVP_CIPHER-BLOWFISH.pod
new file mode 100644
index 000000000000..d79fc75539d0
--- /dev/null
+++ b/doc/man7/EVP_CIPHER-BLOWFISH.pod
@@ -0,0 +1,46 @@
+=pod
+
+=head1 NAME
+
+EVP_CIPHER-BLOWFISH - The BLOBFISH EVP_CIPHER implementations
+
+=head1 DESCRIPTION
+
+Support for BLOWFISH symmetric encryption using the B<EVP_CIPHER> API.
+
+=head2 Algorithm Names
+
+The following algorithms are available in the legacy provider:
+
+=over 4
+
+=item "BF-ECB"
+
+=item "BF-CBC"
+
+=item "BF-OFB"
+
+=item "BF-CFB"
+
+=back
+
+
+=head2 Parameters
+
+This implementation supports the parameters described in
+L<EVP_EncryptInit(3)/PARAMETERS>.
+
+=head1 SEE ALSO
+
+L<provider-cipher(7)>, L<OSSL_PROVIDER-legacy(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_CIPHER-CAMELLIA.pod b/doc/man7/EVP_CIPHER-CAMELLIA.pod
new file mode 100644
index 000000000000..bba8001d00cc
--- /dev/null
+++ b/doc/man7/EVP_CIPHER-CAMELLIA.pod
@@ -0,0 +1,51 @@
+=pod
+
+=head1 NAME
+
+EVP_CIPHER-CAMELLIA - The CAMELLIA EVP_CIPHER implementations
+
+=head1 DESCRIPTION
+
+Support for CAMELLIA symmetric encryption using the B<EVP_CIPHER> API.
+
+=head2 Algorithm Names
+
+The following algorithms are available in the default provider:
+
+=over 4
+
+=item "CAMELLIA-128-CBC", "CAMELLIA-192-CBC" and "CAMELLIA-256-CBC"
+
+=item "CAMELLIA-128-CBC-CTS", "CAMELLIA-192-CBC-CTS" and "CAMELLIA-256-CBC-CTS"
+
+=item "CAMELLIA-128-CFB", "CAMELLIA-192-CFB", "CAMELLIA-256-CFB",
+"CAMELLIA-128-CFB1", "CAMELLIA-192-CFB1", "CAMELLIA-256-CFB1",
+"CAMELLIA-128-CFB8", "CAMELLIA-192-CFB8" and "CAMELLIA-256-CFB8"
+
+=item "CAMELLIA-128-CTR", "CAMELLIA-192-CTR" and "CAMELLIA-256-CTR"
+
+=item "CAMELLIA-128-ECB", "CAMELLIA-192-ECB" and "CAMELLIA-256-ECB"
+
+=item "CAMELLIA-192-OFB", "CAMELLIA-128-OFB" and "CAMELLIA-256-OFB"
+
+=back
+
+=head2 Parameters
+
+This implementation supports the parameters described in
+L<EVP_EncryptInit(3)/PARAMETERS>.
+
+=head1 SEE ALSO
+
+L<provider-cipher(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_CIPHER-CAST.pod b/doc/man7/EVP_CIPHER-CAST.pod
new file mode 100644
index 000000000000..e68751d64331
--- /dev/null
+++ b/doc/man7/EVP_CIPHER-CAST.pod
@@ -0,0 +1,45 @@
+=pod
+
+=head1 NAME
+
+EVP_CIPHER-CAST - The CAST EVP_CIPHER implementations
+
+=head1 DESCRIPTION
+
+Support for CAST symmetric encryption using the B<EVP_CIPHER> API.
+
+=head2 Algorithm Names
+
+The following algorithms are available in the legacy provider:
+
+=over 4
+
+=item "CAST-128-CBC", "CAST-192-CBC" and "CAST-256-CBC"
+
+=item "CAST-128-CFB", "CAST-192-CFB", "CAST-256-CFB"
+
+=item "CAST-128-ECB", "CAST-192-ECB" and "CAST-256-ECB"
+
+=item "CAST-192-OFB", "CAST-128-OFB" and "CAST-256-OFB"
+
+=back
+
+=head2 Parameters
+
+This implementation supports the parameters described in
+L<EVP_EncryptInit(3)/PARAMETERS>.
+
+=head1 SEE ALSO
+
+L<provider-cipher(7)>, L<OSSL_PROVIDER-legacy(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_CIPHER-CHACHA.pod b/doc/man7/EVP_CIPHER-CHACHA.pod
new file mode 100644
index 000000000000..b7d57481ac73
--- /dev/null
+++ b/doc/man7/EVP_CIPHER-CHACHA.pod
@@ -0,0 +1,41 @@
+=pod
+
+=head1 NAME
+
+EVP_CIPHER-CHACHA - The CHACHA EVP_CIPHER implementations
+
+=head1 DESCRIPTION
+
+Support for CHACHA symmetric encryption using the B<EVP_CIPHER> API.
+
+=head2 Algorithm Names
+
+The following algorithms are available in the default provider:
+
+=over 4
+
+=item "ChaCha20"
+
+=item "ChaCha20-Poly1305"
+
+=back
+
+=head2 Parameters
+
+This implementation supports the parameters described in
+L<EVP_EncryptInit(3)/PARAMETERS>.
+
+=head1 SEE ALSO
+
+L<provider-cipher(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_CIPHER-DES.pod b/doc/man7/EVP_CIPHER-DES.pod
new file mode 100644
index 000000000000..25603f6fc676
--- /dev/null
+++ b/doc/man7/EVP_CIPHER-DES.pod
@@ -0,0 +1,78 @@
+=pod
+
+=head1 NAME
+
+EVP_CIPHER-DES - The DES EVP_CIPHER implementations
+
+=head1 DESCRIPTION
+
+Support for DES symmetric encryption using the B<EVP_CIPHER> API.
+
+=head2 Algorithm Names
+
+The following algorithms are available in the FIPS provider as well as the
+default provider:
+
+=over 4
+
+=item "DES-EDE3-ECB" or "DES-EDE3"
+
+=item "DES-EDE3-CBC" or "DES3"
+
+=back
+
+The following algorithms are available in the default provider, but not the
+FIPS provider:
+
+=over 4
+
+=item "DES-EDE3-CFB8" and "DES-EDE3-CFB1"
+
+=item "DES-EDE-ECB" or "DES-EDE"
+
+=item "DES-EDE-CBC"
+
+=item "DES-EDE-OFB"
+
+=item "DES-EDE-CFB"
+
+=item "DES3-WRAP"
+
+=back
+
+The following algorithms are available in the legacy provider:
+
+=over 4
+
+=item "DES-ECB"
+
+=item "DES-CBC"
+
+=item "DES-OFB"
+
+=item "DES-CFB", "DES-CFB1" and "DES-CFB8"
+
+=item "DESX-CBC"
+
+=back
+
+=head2 Parameters
+
+This implementation supports the parameters described in
+L<EVP_EncryptInit(3)/PARAMETERS>.
+
+=head1 SEE ALSO
+
+L<provider-cipher(7)>, L<OSSL_PROVIDER-FIPS(7)>, L<OSSL_PROVIDER-default(7)>,
+L<OSSL_PROVIDER-legacy(7)>,
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_CIPHER-IDEA.pod b/doc/man7/EVP_CIPHER-IDEA.pod
new file mode 100644
index 000000000000..29041592c77f
--- /dev/null
+++ b/doc/man7/EVP_CIPHER-IDEA.pod
@@ -0,0 +1,45 @@
+=pod
+
+=head1 NAME
+
+EVP_CIPHER-IDEA - The IDEA EVP_CIPHER implementations
+
+=head1 DESCRIPTION
+
+Support for IDEA symmetric encryption using the B<EVP_CIPHER> API.
+
+=head2 Algorithm Names
+
+The following algorithms are available in the legacy provider:
+
+=over 4
+
+=item "IDEA-ECB"
+
+=item "IDEA-CBC"
+
+=item "IDEA-OFB" or "IDEA-OFB64"
+
+=item "IDEA-CFB" or "IDEA-CFB64"
+
+=back
+
+=head2 Parameters
+
+This implementation supports the parameters described in
+L<EVP_EncryptInit(3)/PARAMETERS>.
+
+=head1 SEE ALSO
+
+L<provider-cipher(7)>, L<OSSL_PROVIDER-legacy(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_CIPHER-RC2.pod b/doc/man7/EVP_CIPHER-RC2.pod
new file mode 100644
index 000000000000..8a69a74622b8
--- /dev/null
+++ b/doc/man7/EVP_CIPHER-RC2.pod
@@ -0,0 +1,49 @@
+=pod
+
+=head1 NAME
+
+EVP_CIPHER-RC2 - The RC2 EVP_CIPHER implementations
+
+=head1 DESCRIPTION
+
+Support for RC2 symmetric encryption using the B<EVP_CIPHER> API.
+
+=head2 Algorithm Names
+
+The following algorithms are available in the legacy provider:
+
+=over 4
+
+=item "RC2-CBC", "RC2" or "RC2-128"
+
+=item "RC2-40-CBC" or "RC2-40"
+
+=item "RC2-64-CBC" or "RC2-64"
+
+=item "RC2-ECB"
+
+=item "RC2-CFB"
+
+=item "RC2-OFB"
+
+=back
+
+=head2 Parameters
+
+This implementation supports the parameters described in
+L<EVP_EncryptInit(3)/PARAMETERS>.
+
+=head1 SEE ALSO
+
+L<provider-cipher(7)>, L<OSSL_PROVIDER-legacy(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_CIPHER-RC4.pod b/doc/man7/EVP_CIPHER-RC4.pod
new file mode 100644
index 000000000000..309b7e24a078
--- /dev/null
+++ b/doc/man7/EVP_CIPHER-RC4.pod
@@ -0,0 +1,43 @@
+=pod
+
+=head1 NAME
+
+EVP_CIPHER-RC4 - The RC4 EVP_CIPHER implementations
+
+=head1 DESCRIPTION
+
+Support for RC4 symmetric encryption using the B<EVP_CIPHER> API.
+
+=head2 Algorithm Names
+
+The following algorithms are available in the legacy provider:
+
+=over 4
+
+=item "RC4"
+
+=item "RC4-40"
+
+=item "RC4-HMAC-MD5"
+
+=back
+
+=head2 Parameters
+
+This implementation supports the parameters described in
+L<EVP_EncryptInit(3)/PARAMETERS>.
+
+=head1 SEE ALSO
+
+L<provider-cipher(7)>, L<OSSL_PROVIDER-legacy(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_CIPHER-RC5.pod b/doc/man7/EVP_CIPHER-RC5.pod
new file mode 100644
index 000000000000..84204834b1d1
--- /dev/null
+++ b/doc/man7/EVP_CIPHER-RC5.pod
@@ -0,0 +1,47 @@
+=pod
+
+=head1 NAME
+
+EVP_CIPHER-RC5 - The RC5 EVP_CIPHER implementations
+
+=head1 DESCRIPTION
+
+Support for RC5 symmetric encryption using the B<EVP_CIPHER> API.
+
+Disabled by default. Use the I<enable-rc5> configuration option to enable.
+
+=head2 Algorithm Names
+
+The following algorithms are available in the legacy provider:
+
+=over 4
+
+=item "RC5-CBC" or "RC5"
+
+=item "RC5-ECB"
+
+=item "RC5-OFB"
+
+=item "RC5-CFB"
+
+=back
+
+=head2 Parameters
+
+This implementation supports the parameters described in
+L<EVP_EncryptInit(3)/PARAMETERS>.
+
+=head1 SEE ALSO
+
+L<provider-cipher(7)>, L<OSSL_PROVIDER-legacy(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_CIPHER-SEED.pod b/doc/man7/EVP_CIPHER-SEED.pod
new file mode 100644
index 000000000000..07b28917f836
--- /dev/null
+++ b/doc/man7/EVP_CIPHER-SEED.pod
@@ -0,0 +1,45 @@
+=pod
+
+=head1 NAME
+
+EVP_CIPHER-SEED - The SEED EVP_CIPHER implementations
+
+=head1 DESCRIPTION
+
+Support for SEED symmetric encryption using the B<EVP_CIPHER> API.
+
+=head2 Algorithm Names
+
+The following algorithms are available in the legacy provider:
+
+=over 4
+
+=item "SEED-CBC" or "SEED"
+
+=item "SEED-ECB"
+
+=item "SEED-OFB" or "SEED-OFB128"
+
+=item "SEED-CFB" or "SEED-CFB128"
+
+=back
+
+=head2 Parameters
+
+This implementation supports the parameters described in
+L<EVP_EncryptInit(3)/PARAMETERS>.
+
+=head1 SEE ALSO
+
+L<provider-cipher(7)>, L<OSSL_PROVIDER-legacy(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_CIPHER-SM4.pod b/doc/man7/EVP_CIPHER-SM4.pod
new file mode 100644
index 000000000000..36a51d18a423
--- /dev/null
+++ b/doc/man7/EVP_CIPHER-SM4.pod
@@ -0,0 +1,47 @@
+=pod
+
+=head1 NAME
+
+EVP_CIPHER-SM4 - The SM4 EVP_CIPHER implementations
+
+=head1 DESCRIPTION
+
+Support for SM4 symmetric encryption using the B<EVP_CIPHER> API.
+
+=head2 Algorithm Names
+
+The following algorithms are available in the default provider:
+
+=over 4
+
+=item "SM4-CBC:SM4"
+
+=item "SM4-ECB"
+
+=item "SM4-CTR"
+
+=item "SM4-OFB" or "SM4-OFB128"
+
+=item "SM4-CFB" or "SM4-CFB128"
+
+=back
+
+=head2 Parameters
+
+This implementation supports the parameters described in
+L<EVP_EncryptInit(3)/PARAMETERS>.
+
+=head1 SEE ALSO
+
+L<provider-cipher(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KDF-HKDF.pod b/doc/man7/EVP_KDF-HKDF.pod
new file mode 100644
index 000000000000..5fc0a73241cc
--- /dev/null
+++ b/doc/man7/EVP_KDF-HKDF.pod
@@ -0,0 +1,156 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF-HKDF - The HKDF EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+Support for computing the B<HKDF> KDF through the B<EVP_KDF> API.
+
+The EVP_KDF-HKDF algorithm implements the HKDF key derivation function.
+HKDF follows the "extract-then-expand" paradigm, where the KDF logically
+consists of two modules. The first stage takes the input keying material
+and "extracts" from it a fixed-length pseudorandom key K. The second stage
+"expands" the key K into several additional pseudorandom keys (the output
+of the KDF).
+
+=head2 Identity
+
+"HKDF" is the name for this implementation; it
+can be used with the EVP_KDF_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
+
+=item "key" (B<OSSL_KDF_PARAM_KEY>) <octet string>
+
+=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string>
+
+These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
+
+=item "info" (B<OSSL_KDF_PARAM_INFO>) <octet string>
+
+This parameter sets the info value.
+The length of the context info buffer cannot exceed 1024 bytes;
+this should be more than enough for any normal use of HKDF.
+
+=item "mode" (B<OSSL_KDF_PARAM_MODE>) <UTF8 string> or <integer>
+
+This parameter sets the mode for the HKDF operation.
+There are three modes that are currently defined:
+
+=over 4
+
+=item "EXTRACT_AND_EXPAND" or B<EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND>
+
+This is the default mode. Calling L<EVP_KDF_derive(3)> on an EVP_KDF_CTX set
+up for HKDF will perform an extract followed by an expand operation in one go.
+The derived key returned will be the result after the expand operation. The
+intermediate fixed-length pseudorandom key K is not returned.
+
+In this mode the digest, key, salt and info values must be set before a key is
+derived otherwise an error will occur.
+
+=item "EXTRACT_ONLY" or B<EVP_KDF_HKDF_MODE_EXTRACT_ONLY>
+
+In this mode calling L<EVP_KDF_derive(3)> will just perform the extract
+operation. The value returned will be the intermediate fixed-length pseudorandom
+key K. The I<keylen> parameter must match the size of K, which can be looked
+up by calling EVP_KDF_CTX_get_kdf_size() after setting the mode and digest.
+
+The digest, key and salt values must be set before a key is derived otherwise
+an error will occur.
+
+=item "EXPAND_ONLY" or B<EVP_KDF_HKDF_MODE_EXPAND_ONLY>
+
+In this mode calling L<EVP_KDF_derive(3)> will just perform the expand
+operation. The input key should be set to the intermediate fixed-length
+pseudorandom key K returned from a previous extract operation.
+
+The digest, key and info values must be set before a key is derived otherwise
+an error will occur.
+
+=back
+
+=back
+
+=head1 NOTES
+
+A context for HKDF can be obtained by calling:
+
+ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "HKDF", NULL);
+ EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
+
+The output length of an HKDF expand operation is specified via the I<keylen>
+parameter to the L<EVP_KDF_derive(3)> function. When using
+EVP_KDF_HKDF_MODE_EXTRACT_ONLY the I<keylen> parameter must equal the size of
+the intermediate fixed-length pseudorandom key otherwise an error will occur.
+For that mode, the fixed output size can be looked up by calling EVP_KDF_CTX_get_kdf_size()
+after setting the mode and digest on the B<EVP_KDF_CTX>.
+
+=head1 EXAMPLES
+
+This example derives 10 bytes using SHA-256 with the secret key "secret",
+salt value "salt" and info value "label":
+
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx;
+ unsigned char out[10];
+ OSSL_PARAM params[5], *p = params;
+
+ kdf = EVP_KDF_fetch(NULL, "HKDF", NULL);
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ SN_sha256, strlen(SN_sha256));
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ "secret", (size_t)6);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
+ "label", (size_t)5);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ "salt", (size_t)4);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
+ error("EVP_KDF_derive");
+ }
+
+ EVP_KDF_CTX_free(kctx);
+
+=head1 CONFORMING TO
+
+RFC 5869
+
+=head1 SEE ALSO
+
+L<EVP_KDF(3)>,
+L<EVP_KDF_CTX_new(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_CTX_get_kdf_size(3)>,
+L<EVP_KDF_CTX_set_params(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF(3)/PARAMETERS>,
+L<EVP_KDF-TLS13_KDF(7)>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KDF-KB.pod b/doc/man7/EVP_KDF-KB.pod
new file mode 100644
index 000000000000..6e25882d674c
--- /dev/null
+++ b/doc/man7/EVP_KDF-KB.pod
@@ -0,0 +1,172 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF-KB - The Key-Based EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+The EVP_KDF-KB algorithm implements the Key-Based key derivation function
+(KBKDF). KBKDF derives a key from repeated application of a keyed MAC to an
+input secret (and other optional values).
+
+=head2 Identity
+
+"KBKDF" is the name for this implementation; it can be used with the
+EVP_KDF_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "mode" (B<OSSL_KDF_PARAM_MODE>) <UTF8 string>
+
+The mode parameter determines which flavor of KBKDF to use - currently the
+choices are "counter" and "feedback". "counter" is the default, and will be
+used if unspecified.
+
+=item "mac" (B<OSSL_KDF_PARAM_MAC>) <UTF8 string>
+
+The value is either CMAC or HMAC.
+
+=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
+
+=item "cipher" (B<OSSL_KDF_PARAM_CIPHER>) <UTF8 string>
+
+=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "key" (B<OSSL_KDF_PARAM_KEY>) <octet string>
+
+=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string>
+
+=item "info (B<OSSL_KDF_PARAM_INFO>) <octet string>
+
+=item "seed" (B<OSSL_KDF_PARAM_SEED>) <octet string>
+
+The seed parameter is unused in counter mode.
+
+=item "use-l" (B<OSSL_KDF_PARAM_KBKDF_USE_L>) <integer>
+
+Set to B<0> to disable use of the optional Fixed Input data 'L' (see SP800-108).
+The default value of B<1> will be used if unspecified.
+
+=item "use-separator" (B<OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR>) <integer>
+
+Set to B<0> to disable use of the optional Fixed Input data 'zero separator'
+(see SP800-108) that is placed between the Label and Context.
+The default value of B<1> will be used if unspecified.
+
+=back
+
+Depending on whether mac is CMAC or HMAC, either digest or cipher is required
+(respectively) and the other is unused.
+
+The parameters key, salt, info, and seed correspond to KI, Label, Context, and
+IV (respectively) in SP800-108. As in that document, salt, info, and seed are
+optional and may be omitted.
+
+"mac", "digest", cipher" and "properties" are described in
+L<EVP_KDF(3)/PARAMETERS>.
+
+=head1 NOTES
+
+A context for KBKDF can be obtained by calling:
+
+ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL);
+ EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
+
+The output length of an KBKDF is specified via the C<keylen>
+parameter to the L<EVP_KDF_derive(3)> function.
+
+Note that currently OpenSSL only implements counter and feedback modes. Other
+variants may be supported in the future.
+
+=head1 EXAMPLES
+
+This example derives 10 bytes using COUNTER-HMAC-SHA256, with KI "secret",
+Label "label", and Context "context".
+
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx;
+ unsigned char out[10];
+ OSSL_PARAM params[6], *p = params;
+
+ kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL);
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ "SHA2-256", 0);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
+ "HMAC", 0);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ "secret", strlen("secret"));
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ "label", strlen("label"));
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
+ "context", strlen("context"));
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0)
+ error("EVP_KDF_derive");
+
+ EVP_KDF_CTX_free(kctx);
+
+This example derives 10 bytes using FEEDBACK-CMAC-AES256, with KI "secret",
+Label "label", and IV "sixteen bytes iv".
+
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx;
+ unsigned char out[10];
+ OSSL_PARAM params[8], *p = params;
+ unsigned char *iv = "sixteen bytes iv";
+
+ kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL);
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER, "AES256", 0);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC, "CMAC", 0);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MODE, "FEEDBACK", 0);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ "secret", strlen("secret"));
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ "label", strlen("label"));
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
+ "context", strlen("context"));
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED,
+ iv, strlen(iv));
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0)
+ error("EVP_KDF_derive");
+
+ EVP_KDF_CTX_free(kctx);
+
+=head1 CONFORMING TO
+
+NIST SP800-108, IETF RFC 6803, IETF RFC 8009.
+
+=head1 SEE ALSO
+
+L<EVP_KDF(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_CTX_get_kdf_size(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF(3)/PARAMETERS>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2019 Red Hat, Inc.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KDF-KRB5KDF.pod b/doc/man7/EVP_KDF-KRB5KDF.pod
new file mode 100644
index 000000000000..014f55e79827
--- /dev/null
+++ b/doc/man7/EVP_KDF-KRB5KDF.pod
@@ -0,0 +1,115 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF-KRB5KDF - The RFC3961 Krb5 KDF EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+Support for computing the B<KRB5KDF> KDF through the B<EVP_KDF> API.
+
+The EVP_KDF-KRB5KDF algorithm implements the key derivation function defined
+in RFC 3961, section 5.1 and is used by Krb5 to derive session keys.
+Three inputs are required to perform key derivation: a cipher, (for example
+AES-128-CBC), the initial key, and a constant.
+
+=head2 Identity
+
+"KRB5KDF" is the name for this implementation;
+it can be used with the EVP_KDF_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "cipher" (B<OSSL_KDF_PARAM_CIPHER>) <UTF8 string>
+
+=item "key" (B<OSSL_KDF_PARAM_KEY>) <octet string>
+
+These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
+
+=item "constant" (B<OSSL_KDF_PARAM_CONSTANT>) <octet string>
+
+This parameter sets the constant value for the KDF.
+If a value is already set, the contents are replaced.
+
+=back
+
+=head1 NOTES
+
+A context for KRB5KDF can be obtained by calling:
+
+ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "KRB5KDF", NULL);
+ EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
+
+The output length of the KRB5KDF derivation is specified via the I<keylen>
+parameter to the L<EVP_KDF_derive(3)> function, and MUST match the key
+length for the chosen cipher or an error is returned. Moreover, the
+constant's length must not exceed the block size of the cipher.
+Since the KRB5KDF output length depends on the chosen cipher, calling
+L<EVP_KDF_CTX_get_kdf_size(3)> to obtain the requisite length returns the correct length
+only after the cipher is set. Prior to that B<EVP_MAX_KEY_LENGTH> is returned.
+The caller must allocate a buffer of the correct length for the chosen
+cipher, and pass that buffer to the L<EVP_KDF_derive(3)> function along
+with that length.
+
+=head1 EXAMPLES
+
+This example derives a key using the AES-128-CBC cipher:
+
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx;
+ unsigned char key[16] = "01234...";
+ unsigned char constant[] = "I'm a constant";
+ unsigned char out[16];
+ size_t outlen = sizeof(out);
+ OSSL_PARAM params[4], *p = params;
+
+ kdf = EVP_KDF_fetch(NULL, "KRB5KDF", NULL);
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER,
+ SN_aes_128_cbc,
+ strlen(SN_aes_128_cbc));
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ key, (size_t)16);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_CONSTANT,
+ constant, strlen(constant));
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, out, outlen, params) <= 0)
+ /* Error */
+
+ EVP_KDF_CTX_free(kctx);
+
+=head1 CONFORMING TO
+
+RFC 3961
+
+=head1 SEE ALSO
+
+L<EVP_KDF(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_CTX_get_kdf_size(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF(3)/PARAMETERS>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
+
diff --git a/doc/man7/EVP_KDF-PBKDF1.pod b/doc/man7/EVP_KDF-PBKDF1.pod
new file mode 100644
index 000000000000..c73ad6a9ec38
--- /dev/null
+++ b/doc/man7/EVP_KDF-PBKDF1.pod
@@ -0,0 +1,82 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF-PBKDF1 - The PBKDF1 EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+Support for computing the B<PBKDF1> password-based KDF through the B<EVP_KDF>
+API.
+
+The EVP_KDF-PBKDF1 algorithm implements the PBKDF1 password-based key
+derivation function, as described in RFC 8018; it derives a key from a password
+using a salt and iteration count.
+
+=head2 Identity
+
+"PBKDF1" is the name for this implementation; it
+can be used with the EVP_KDF_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "pass" (B<OSSL_KDF_PARAM_PASSWORD>) <octet string>
+
+=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string>
+
+=item "iter" (B<OSSL_KDF_PARAM_ITER>) <unsigned integer>
+
+This parameter has a default value of 0 and should be set.
+
+=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
+
+These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
+
+=back
+
+=head1 NOTES
+
+A typical application of this algorithm is to derive keying material for an
+encryption algorithm from a password in the "pass", a salt in "salt",
+and an iteration count.
+
+Increasing the "iter" parameter slows down the algorithm which makes it
+harder for an attacker to perform a brute force attack using a large number
+of candidate passwords.
+
+No assumption is made regarding the given password; it is simply treated as a
+byte sequence.
+
+=head1 CONFORMING TO
+
+RFC 8018
+
+=head1 SEE ALSO
+
+L<EVP_KDF(3)>,
+L<EVP_KDF_CTX_new(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_CTX_set_params(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF(3)/PARAMETERS>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KDF-PBKDF2.pod b/doc/man7/EVP_KDF-PBKDF2.pod
new file mode 100644
index 000000000000..e6cadc8b826d
--- /dev/null
+++ b/doc/man7/EVP_KDF-PBKDF2.pod
@@ -0,0 +1,104 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF-PBKDF2 - The PBKDF2 EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+Support for computing the B<PBKDF2> password-based KDF through the B<EVP_KDF>
+API.
+
+The EVP_KDF-PBKDF2 algorithm implements the PBKDF2 password-based key
+derivation function, as described in SP800-132; it derives a key from a password
+using a salt and iteration count.
+
+=head2 Identity
+
+"PBKDF2" is the name for this implementation; it
+can be used with the EVP_KDF_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "pass" (B<OSSL_KDF_PARAM_PASSWORD>) <octet string>
+
+=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string>
+
+=item "iter" (B<OSSL_KDF_PARAM_ITER>) <unsigned integer>
+
+This parameter has a default value of 2048.
+
+=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
+
+These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
+
+=item "pkcs5" (B<OSSL_KDF_PARAM_PKCS5>) <integer>
+
+This parameter can be used to enable or disable SP800-132 compliance checks.
+Setting the mode to 0 enables the compliance checks.
+
+The checks performed are:
+
+=over 4
+
+=item - the iteration count is at least 1000.
+
+=item - the salt length is at least 128 bits.
+
+=item - the derived key length is at least 112 bits.
+
+=back
+
+The default provider uses a default mode of 1 for backwards compatibility,
+and the FIPS provider uses a default mode of 0.
+
+The value string is expected to be a decimal number 0 or 1.
+
+=back
+
+=head1 NOTES
+
+A typical application of this algorithm is to derive keying material for an
+encryption algorithm from a password in the "pass", a salt in "salt",
+and an iteration count.
+
+Increasing the "iter" parameter slows down the algorithm which makes it
+harder for an attacker to perform a brute force attack using a large number
+of candidate passwords.
+
+No assumption is made regarding the given password; it is simply treated as a
+byte sequence.
+
+=head1 CONFORMING TO
+
+SP800-132
+
+=head1 SEE ALSO
+
+L<EVP_KDF(3)>,
+L<EVP_KDF_CTX_new(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_CTX_set_params(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF(3)/PARAMETERS>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KDF-PKCS12KDF.pod b/doc/man7/EVP_KDF-PKCS12KDF.pod
new file mode 100644
index 000000000000..7edde1dc9bf7
--- /dev/null
+++ b/doc/man7/EVP_KDF-PKCS12KDF.pod
@@ -0,0 +1,86 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF-PKCS12KDF - The PKCS#12 EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+Support for computing the B<PKCS#12> password-based KDF through the B<EVP_KDF>
+API.
+
+The EVP_KDF-PKCS12KDF algorithm implements the PKCS#12 password-based key
+derivation function, as described in appendix B of RFC 7292 (PKCS #12:
+Personal Information Exchange Syntax); it derives a key from a password
+using a salt, iteration count and the intended usage.
+
+=head2 Identity
+
+"PKCS12KDF" is the name for this implementation; it
+can be used with the EVP_KDF_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "pass" (B<OSSL_KDF_PARAM_PASSWORD>) <octet string>
+
+=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string>
+
+=item "iter" (B<OSSL_KDF_PARAM_ITER>) <unsigned integer>
+
+=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
+
+These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
+
+=item "id" (B<OSSL_KDF_PARAM_PKCS12_ID>) <integer>
+
+This parameter is used to specify the intended usage of the output bits, as per
+RFC 7292 section B.3.
+
+=back
+
+=head1 NOTES
+
+A typical application of this algorithm is to derive keying material for an
+encryption algorithm from a password in the "pass", a salt in "salt",
+and an iteration count.
+
+Increasing the "iter" parameter slows down the algorithm which makes it
+harder for an attacker to perform a brute force attack using a large number
+of candidate passwords.
+
+No assumption is made regarding the given password; it is simply treated as a
+byte sequence.
+
+=head1 CONFORMING TO
+
+RFC7292
+
+=head1 SEE ALSO
+
+L<EVP_KDF(3)>,
+L<EVP_KDF_CTX_new(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_CTX_set_params(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF(3)/PARAMETERS>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KDF-SCRYPT.pod b/doc/man7/EVP_KDF-SCRYPT.pod
new file mode 100644
index 000000000000..2bda54c52077
--- /dev/null
+++ b/doc/man7/EVP_KDF-SCRYPT.pod
@@ -0,0 +1,150 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF-SCRYPT - The scrypt EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+Support for computing the B<scrypt> password-based KDF through the B<EVP_KDF>
+API.
+
+The EVP_KDF-SCRYPT algorithm implements the scrypt password-based key
+derivation function, as described in RFC 7914. It is memory-hard in the sense
+that it deliberately requires a significant amount of RAM for efficient
+computation. The intention of this is to render brute forcing of passwords on
+systems that lack large amounts of main memory (such as GPUs or ASICs)
+computationally infeasible.
+
+scrypt provides three work factors that can be customized: N, r and p. N, which
+has to be a positive power of two, is the general work factor and scales CPU
+time in an approximately linear fashion. r is the block size of the internally
+used hash function and p is the parallelization factor. Both r and p need to be
+greater than zero. The amount of RAM that scrypt requires for its computation
+is roughly (128 * N * r * p) bytes.
+
+In the original paper of Colin Percival ("Stronger Key Derivation via
+Sequential Memory-Hard Functions", 2009), the suggested values that give a
+computation time of less than 5 seconds on a 2.5 GHz Intel Core 2 Duo are N =
+2^20 = 1048576, r = 8, p = 1. Consequently, the required amount of memory for
+this computation is roughly 1 GiB. On a more recent CPU (Intel i7-5930K at 3.5
+GHz), this computation takes about 3 seconds. When N, r or p are not specified,
+they default to 1048576, 8, and 1, respectively. The maximum amount of RAM that
+may be used by scrypt defaults to 1025 MiB.
+
+=head2 Identity
+
+"SCRYPT" is the name for this implementation; it
+can be used with the EVP_KDF_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "pass" (B<OSSL_KDF_PARAM_PASSWORD>) <octet string>
+
+=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string>
+
+These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
+
+=item "n" (B<OSSL_KDF_PARAM_SCRYPT_N>) <unsigned integer>
+
+=item "r" (B<OSSL_KDF_PARAM_SCRYPT_R>) <unsigned integer>
+
+=item "p" (B<OSSL_KDF_PARAM_SCRYPT_P>) <unsigned integer>
+
+=item "maxmem_bytes" (B<OSSL_KDF_PARAM_SCRYPT_MAXMEM>) <unsigned integer>
+
+These parameters configure the scrypt work factors N, r, maxmem and p.
+Both N and maxmem_bytes are parameters of type B<uint64_t>.
+Both r and p are parameters of type B<uint32_t>.
+
+=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
+
+This can be used to set the property query string when fetching the
+fixed digest internally. NULL is used if this value is not set.
+
+=back
+
+=head1 NOTES
+
+A context for scrypt can be obtained by calling:
+
+ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "SCRYPT", NULL);
+ EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
+
+The output length of an scrypt key derivation is specified via the
+"keylen" parameter to the L<EVP_KDF_derive(3)> function.
+
+=head1 EXAMPLES
+
+This example derives a 64-byte long test vector using scrypt with the password
+"password", salt "NaCl" and N = 1024, r = 8, p = 16.
+
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx;
+ unsigned char out[64];
+ OSSL_PARAM params[6], *p = params;
+
+ kdf = EVP_KDF_fetch(NULL, "SCRYPT", NULL);
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
+ "password", (size_t)8);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ "NaCl", (size_t)4);
+ *p++ = OSSL_PARAM_construct_uint64(OSSL_KDF_PARAM_SCRYPT_N, (uint64_t)1024);
+ *p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_SCRYPT_R, (uint32_t)8);
+ *p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_SCRYPT_P, (uint32_t)16);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
+ error("EVP_KDF_derive");
+ }
+
+ {
+ const unsigned char expected[sizeof(out)] = {
+ 0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00,
+ 0x78, 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe,
+ 0x7c, 0x6a, 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30,
+ 0xe7, 0x73, 0x76, 0x63, 0x4b, 0x37, 0x31, 0x62,
+ 0x2e, 0xaf, 0x30, 0xd9, 0x2e, 0x22, 0xa3, 0x88,
+ 0x6f, 0xf1, 0x09, 0x27, 0x9d, 0x98, 0x30, 0xda,
+ 0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, 0xee, 0x6d,
+ 0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, 0x40
+ };
+
+ assert(!memcmp(out, expected, sizeof(out)));
+ }
+
+ EVP_KDF_CTX_free(kctx);
+
+=head1 CONFORMING TO
+
+RFC 7914
+
+=head1 SEE ALSO
+
+L<EVP_KDF(3)>,
+L<EVP_KDF_CTX_new(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_CTX_set_params(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF(3)/PARAMETERS>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KDF-SS.pod b/doc/man7/EVP_KDF-SS.pod
new file mode 100644
index 000000000000..7f158e421698
--- /dev/null
+++ b/doc/man7/EVP_KDF-SS.pod
@@ -0,0 +1,188 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF-SS - The Single Step / One Step EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+The EVP_KDF-SS algorithm implements the Single Step key derivation function (SSKDF).
+SSKDF derives a key using input such as a shared secret key (that was generated
+during the execution of a key establishment scheme) and fixedinfo.
+SSKDF is also informally referred to as 'Concat KDF'.
+
+=head2 Auxiliary function
+
+The implementation uses a selectable auxiliary function H, which can be one of:
+
+=over 4
+
+=item B<H(x) = hash(x, digest=md)>
+
+=item B<H(x) = HMAC_hash(x, key=salt, digest=md)>
+
+=item B<H(x) = KMACxxx(x, key=salt, custom="KDF", outlen=mac_size)>
+
+=back
+
+Both the HMAC and KMAC implementations set the key using the 'salt' value.
+The hash and HMAC also require the digest to be set.
+
+=head2 Identity
+
+"SSKDF" is the name for this implementation; it
+can be used with the EVP_KDF_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
+
+This parameter is ignored for KMAC.
+
+=item "mac" (B<OSSL_KDF_PARAM_MAC>) <UTF8 string>
+
+=item "maclen" (B<OSSL_KDF_PARAM_MAC_SIZE>) <unsigned integer>
+
+=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string>
+
+These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
+
+=item "key" (B<EVP_KDF_CTRL_SET_KEY>) <octet string>
+
+This parameter set the shared secret that is used for key derivation.
+
+=item "info" (B<OSSL_KDF_PARAM_INFO>) <octet string>
+
+This parameter sets an optional value for fixedinfo, also known as otherinfo.
+
+=back
+
+=head1 NOTES
+
+A context for SSKDF can be obtained by calling:
+
+ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL);
+ EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
+
+The output length of an SSKDF is specified via the I<keylen>
+parameter to the L<EVP_KDF_derive(3)> function.
+
+=head1 EXAMPLES
+
+This example derives 10 bytes using H(x) = SHA-256, with the secret key "secret"
+and fixedinfo value "label":
+
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx;
+ unsigned char out[10];
+ OSSL_PARAM params[4], *p = params;
+
+ kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL);
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ SN_sha256, strlen(SN_sha256));
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ "secret", (size_t)6);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
+ "label", (size_t)5);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
+ error("EVP_KDF_derive");
+ }
+
+ EVP_KDF_CTX_free(kctx);
+
+This example derives 10 bytes using H(x) = HMAC(SHA-256), with the secret key "secret",
+fixedinfo value "label" and salt "salt":
+
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx;
+ unsigned char out[10];
+ OSSL_PARAM params[6], *p = params;
+
+ kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL);
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
+ SN_hmac, strlen(SN_hmac));
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ SN_sha256, strlen(SN_sha256));
+ *p++ = OSSL_PARAM_construct_octet_string(EVP_KDF_CTRL_SET_KEY,
+ "secret", (size_t)6);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
+ "label", (size_t)5);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ "salt", (size_t)4);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
+ error("EVP_KDF_derive");
+ }
+
+ EVP_KDF_CTX_free(kctx);
+
+This example derives 10 bytes using H(x) = KMAC128(x,salt,outlen), with the secret key "secret"
+fixedinfo value "label", salt of "salt" and KMAC outlen of 20:
+
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx;
+ unsigned char out[10];
+ OSSL_PARAM params[6], *p = params;
+
+ kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL);
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
+ SN_kmac128, strlen(SN_kmac128));
+ *p++ = OSSL_PARAM_construct_octet_string(EVP_KDF_CTRL_SET_KEY,
+ "secret", (size_t)6);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
+ "label", (size_t)5);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ "salt", (size_t)4);
+ *p++ = OSSL_PARAM_construct_size_t(OSSL_KDF_PARAM_MAC_SIZE, (size_t)20);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
+ error("EVP_KDF_derive");
+ }
+
+ EVP_KDF_CTX_free(kctx);
+
+=head1 CONFORMING TO
+
+NIST SP800-56Cr1.
+
+=head1 SEE ALSO
+
+L<EVP_KDF(3)>,
+L<EVP_KDF_CTX_new(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_CTX_set_params(3)>,
+L<EVP_KDF_CTX_get_kdf_size(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF(3)/PARAMETERS>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. Copyright
+(c) 2019, Oracle and/or its affiliates. All rights reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KDF-SSHKDF.pod b/doc/man7/EVP_KDF-SSHKDF.pod
new file mode 100644
index 000000000000..c7a3263f455a
--- /dev/null
+++ b/doc/man7/EVP_KDF-SSHKDF.pod
@@ -0,0 +1,161 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF-SSHKDF - The SSHKDF EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+Support for computing the B<SSHKDF> KDF through the B<EVP_KDF> API.
+
+The EVP_KDF-SSHKDF algorithm implements the SSHKDF key derivation function.
+It is defined in RFC 4253, section 7.2 and is used by SSH to derive IVs,
+encryption keys and integrity keys.
+Five inputs are required to perform key derivation: The hashing function
+(for example SHA256), the Initial Key, the Exchange Hash, the Session ID,
+and the derivation key type.
+
+=head2 Identity
+
+"SSHKDF" is the name for this implementation; it
+can be used with the EVP_KDF_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
+
+=item "key" (B<OSSL_KDF_PARAM_KEY>) <octet string>
+
+These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
+
+=item "xcghash" (B<OSSL_KDF_PARAM_SSHKDF_XCGHASH>) <octet string>
+
+=item "session_id" (B<OSSL_KDF_PARAM_SSHKDF_SESSION_ID>) <octet string>
+
+These parameters set the respective values for the KDF.
+If a value is already set, the contents are replaced.
+
+=item "type" (B<OSSL_KDF_PARAM_SSHKDF_TYPE>) <UTF8 string>
+
+This parameter sets the type for the SSHKDF operation.
+There are six supported types:
+
+=over 4
+
+=item EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV
+
+The Initial IV from client to server.
+A single char of value 65 (ASCII char 'A').
+
+=item EVP_KDF_SSHKDF_TYPE_INITIAL_IV_SRV_TO_CLI
+
+The Initial IV from server to client
+A single char of value 66 (ASCII char 'B').
+
+=item EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_CLI_TO_SRV
+
+The Encryption Key from client to server
+A single char of value 67 (ASCII char 'C').
+
+=item EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_SRV_TO_CLI
+
+The Encryption Key from server to client
+A single char of value 68 (ASCII char 'D').
+
+=item EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_CLI_TO_SRV
+
+The Integrity Key from client to server
+A single char of value 69 (ASCII char 'E').
+
+=item EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_SRV_TO_CLI
+
+The Integrity Key from client to server
+A single char of value 70 (ASCII char 'F').
+
+=back
+
+=back
+
+=head1 NOTES
+
+A context for SSHKDF can be obtained by calling:
+
+ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "SSHKDF", NULL);
+ EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
+
+The output length of the SSHKDF derivation is specified via the I<keylen>
+parameter to the L<EVP_KDF_derive(3)> function.
+Since the SSHKDF output length is variable, calling L<EVP_KDF_CTX_get_kdf_size(3)>
+to obtain the requisite length is not meaningful. The caller must
+allocate a buffer of the desired length, and pass that buffer to the
+L<EVP_KDF_derive(3)> function along with the desired length.
+
+=head1 EXAMPLES
+
+This example derives an 8 byte IV using SHA-256 with a 1K "key" and appropriate
+"xcghash" and "session_id" values:
+
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx;
+ char type = EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV;
+ unsigned char key[1024] = "01234...";
+ unsigned char xcghash[32] = "012345...";
+ unsigned char session_id[32] = "012345...";
+ unsigned char out[8];
+ size_t outlen = sizeof(out);
+ OSSL_PARAM params[6], *p = params;
+
+ kdf = EVP_KDF_fetch(NULL, "SSHKDF", NULL);
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ SN_sha256, strlen(SN_sha256));
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ key, (size_t)1024);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SSHKDF_XCGHASH,
+ xcghash, (size_t)32);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SSHKDF_SESSION_ID,
+ session_id, (size_t)32);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_SSHKDF_TYPE,
+ &type, sizeof(type));
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, out, outlen, params) <= 0)
+ /* Error */
+
+
+=head1 CONFORMING TO
+
+RFC 4253
+
+=head1 SEE ALSO
+
+L<EVP_KDF(3)>,
+L<EVP_KDF_CTX_new(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_CTX_set_params(3)>,
+L<EVP_KDF_CTX_get_kdf_size(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF(3)/PARAMETERS>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
+
diff --git a/doc/man7/EVP_KDF-TLS13_KDF.pod b/doc/man7/EVP_KDF-TLS13_KDF.pod
new file mode 100644
index 000000000000..d588b121faf5
--- /dev/null
+++ b/doc/man7/EVP_KDF-TLS13_KDF.pod
@@ -0,0 +1,132 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF-TLS13_KDF - The TLS 1.3 EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+Support for computing the TLS 1.3 version of the B<HKDF> KDF through
+the B<EVP_KDF> API.
+
+The EVP_KDF-TLS13_KDF algorithm implements the HKDF key derivation function
+as used by TLS 1.3.
+
+=head2 Identity
+
+"TLS13-KDF" is the name for this implementation; it
+can be used with the EVP_KDF_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
+
+=item "key" (B<OSSL_KDF_PARAM_KEY>) <octet string>
+
+=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string>
+
+These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
+
+=item "prefix" (B<OSSL_KDF_PARAM_PREFIX>) <octet string>
+
+This parameter sets the label prefix on the specified TLS 1.3 KDF context.
+For TLS 1.3 this should be set to the ASCII string "tls13 " without a
+trailing zero byte. Refer to RFC 8446 section 7.1 "Key Schedule" for details.
+
+=item "label" (B<OSSL_KDF_PARAM_LABEL>) <octet string>
+
+This parameter sets the label on the specified TLS 1.3 KDF context.
+Refer to RFC 8446 section 7.1 "Key Schedule" for details.
+
+=item "data" (B<OSSL_KDF_PARAM_DATA>) <octet string>
+
+This parameter sets the context data on the specified TLS 1.3 KDF context.
+Refer to RFC 8446 section 7.1 "Key Schedule" for details.
+
+=item "mode" (B<OSSL_KDF_PARAM_MODE>) <UTF8 string> or <integer>
+
+This parameter sets the mode for the TLS 1.3 KDF operation.
+There are two modes that are currently defined:
+
+=over 4
+
+=item "EXTRACT_ONLY" or B<EVP_KDF_HKDF_MODE_EXTRACT_ONLY>
+
+In this mode calling L<EVP_KDF_derive(3)> will just perform the extract
+operation. The value returned will be the intermediate fixed-length pseudorandom
+key K. The I<keylen> parameter must match the size of K, which can be looked
+up by calling EVP_KDF_CTX_get_kdf_size() after setting the mode and digest.
+
+The digest, key and salt values must be set before a key is derived otherwise
+an error will occur.
+
+=item "EXPAND_ONLY" or B<EVP_KDF_HKDF_MODE_EXPAND_ONLY>
+
+In this mode calling L<EVP_KDF_derive(3)> will just perform the expand
+operation. The input key should be set to the intermediate fixed-length
+pseudorandom key K returned from a previous extract operation.
+
+The digest, key and info values must be set before a key is derived otherwise
+an error will occur.
+
+=back
+
+=back
+
+=head1 NOTES
+
+This KDF is intended for use by the TLS 1.3 implementation in libssl.
+It does not support all the options and capabilities that HKDF does.
+
+The I<OSSL_PARAM> array passed to L<EVP_KDF_derive(3)> or
+L<EVP_KDF_CTX_set_params(3)> must specify all of the parameters required.
+This KDF does not support a piecemeal approach to providing these.
+
+A context for a TLS 1.3 KDF can be obtained by calling:
+
+ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "TLS13-KDF", NULL);
+ EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
+
+The output length of a TLS 1.3 KDF expand operation is specified via the
+I<keylen> parameter to the L<EVP_KDF_derive(3)> function. When using
+EVP_KDF_HKDF_MODE_EXTRACT_ONLY the I<keylen> parameter must equal the size of
+the intermediate fixed-length pseudorandom key otherwise an error will occur.
+For that mode, the fixed output size can be looked up by calling
+EVP_KDF_CTX_get_kdf_size() after setting the mode and digest on the
+B<EVP_KDF_CTX>.
+
+=head1 CONFORMING TO
+
+RFC 8446
+
+=head1 SEE ALSO
+
+L<EVP_KDF(3)>,
+L<EVP_KDF_CTX_new(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_CTX_get_kdf_size(3)>,
+L<EVP_KDF_CTX_set_params(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF(3)/PARAMETERS>,
+L<EVP_KDF-HKDF(7)>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KDF-TLS1_PRF.pod b/doc/man7/EVP_KDF-TLS1_PRF.pod
new file mode 100644
index 000000000000..8a60e9731554
--- /dev/null
+++ b/doc/man7/EVP_KDF-TLS1_PRF.pod
@@ -0,0 +1,114 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF-TLS1_PRF - The TLS1 PRF EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+Support for computing the B<TLS1> PRF through the B<EVP_KDF> API.
+
+The EVP_KDF-TLS1_PRF algorithm implements the PRF used by TLS versions up to
+and including TLS 1.2.
+
+=head2 Identity
+
+"TLS1-PRF" is the name for this implementation; it
+can be used with the EVP_KDF_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
+
+These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
+
+The B<OSSL_KDF_PARAM_DIGEST> parameter is used to set the message digest
+associated with the TLS PRF.
+EVP_md5_sha1() is treated as a special case which uses the
+PRF algorithm using both B<MD5> and B<SHA1> as used in TLS 1.0 and 1.1.
+
+=item "secret" (B<OSSL_KDF_PARAM_SECRET>) <octet string>
+
+This parameter sets the secret value of the TLS PRF.
+Any existing secret value is replaced.
+
+=item "seed" (B<OSSL_KDF_PARAM_SEED>) <octet string>
+
+This parameter sets the context seed.
+The length of the context seed cannot exceed 1024 bytes;
+this should be more than enough for any normal use of the TLS PRF.
+
+=back
+
+=head1 NOTES
+
+A context for the TLS PRF can be obtained by calling:
+
+ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "TLS1-PRF", NULL);
+ EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
+
+The digest, secret value and seed must be set before a key is derived otherwise
+an error will occur.
+
+The output length of the PRF is specified by the I<keylen> parameter to the
+EVP_KDF_derive() function.
+
+=head1 EXAMPLES
+
+This example derives 10 bytes using SHA-256 with the secret key "secret"
+and seed value "seed":
+
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx;
+ unsigned char out[10];
+ OSSL_PARAM params[4], *p = params;
+
+ kdf = EVP_KDF_fetch(NULL, "TLS1-PRF", NULL);
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ SN_sha256, strlen(SN_sha256));
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SECRET,
+ "secret", (size_t)6);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED,
+ "seed", (size_t)4);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
+ error("EVP_KDF_derive");
+ }
+ EVP_KDF_CTX_free(kctx);
+
+=head1 CONFORMING TO
+
+RFC 2246, RFC 5246 and NIST SP 800-135 r1
+
+=head1 SEE ALSO
+
+L<EVP_KDF(3)>,
+L<EVP_KDF_CTX_new(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_CTX_set_params(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF(3)/PARAMETERS>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KDF-X942-ASN1.pod b/doc/man7/EVP_KDF-X942-ASN1.pod
new file mode 100644
index 000000000000..a5786ab83faa
--- /dev/null
+++ b/doc/man7/EVP_KDF-X942-ASN1.pod
@@ -0,0 +1,151 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF-X942-ASN1 - The X9.42-2003 asn1 EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+The EVP_KDF-X942-ASN1 algorithm implements the key derivation function
+X942KDF-ASN1. It is used by DH KeyAgreement, to derive a key using input such as
+a shared secret key and other info. The other info is DER encoded data that
+contains a 32 bit counter as well as optional fields for "partyu-info",
+"partyv-info", "supp-pubinfo" and "supp-privinfo".
+This kdf is used by Cryptographic Message Syntax (CMS).
+
+=head2 Identity
+
+"X942KDF-ASN1" or "X942KDF" is the name for this implementation; it
+can be used with the EVP_KDF_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
+
+These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
+
+=item "secret" (B<OSSL_KDF_PARAM_SECRET>) <octet string>
+
+The shared secret used for key derivation. This parameter sets the secret.
+
+=item "acvp-info" (B<OSSL_KDF_PARAM_X942_ACVPINFO>) <octet string>
+
+This value should not be used in production and should only be used for ACVP
+testing. It is an optional octet string containing a combined DER encoded blob
+of any of the optional fields related to "partyu-info", "partyv-info",
+"supp-pubinfo" and "supp-privinfo". If it is specified then none of these other
+fields should be used.
+
+=item "partyu-info" (B<OSSL_KDF_PARAM_X942_PARTYUINFO>) <octet string>
+
+An optional octet string containing public info contributed by the initiator.
+
+=item "ukm" (B<OSSL_KDF_PARAM_UKM>) <octet string>
+
+An alias for "partyu-info".
+In CMS this is the user keying material.
+
+=item "partyv-info" (B<OSSL_KDF_PARAM_X942_PARTYVINFO>) <octet string>
+
+An optional octet string containing public info contributed by the responder.
+
+=item "supp-pubinfo" (B<OSSL_KDF_PARAM_X942_SUPP_PUBINFO>) <octet string>
+
+An optional octet string containing some additional, mutually-known public
+information. Setting this value also sets "use-keybits" to 0.
+
+=item "use-keybits" (B<OSSL_KDF_PARAM_X942_USE_KEYBITS>) <integer>
+
+The default value of 1 will use the KEK key length (in bits) as the
+"supp-pubinfo". A value of 0 disables setting the "supp-pubinfo".
+
+=item "supp-privinfo" (B<OSSL_KDF_PARAM_X942_SUPP_PRIVINFO>) <octet string>
+
+An optional octet string containing some additional, mutually-known private
+information.
+
+=item "cekalg" (B<OSSL_KDF_PARAM_CEK_ALG>) <UTF8 string>
+
+This parameter sets the CEK wrapping algorithm name.
+Valid values are "AES-128-WRAP", "AES-192-WRAP", "AES-256-WRAP" and "DES3-WRAP".
+
+=back
+
+=head1 NOTES
+
+A context for X942KDF can be obtained by calling:
+
+ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "X942KDF", NULL);
+ EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
+
+The output length of an X942KDF is specified via the I<keylen>
+parameter to the L<EVP_KDF_derive(3)> function.
+
+=head1 EXAMPLES
+
+This example derives 24 bytes, with the secret key "secret" and random user
+keying material:
+
+ EVP_KDF_CTX *kctx;
+ EVP_KDF_CTX *kctx;
+ unsigned char out[192/8];
+ unsignred char ukm[64];
+ OSSL_PARAM params[5], *p = params;
+
+ if (RAND_bytes(ukm, sizeof(ukm)) <= 0)
+ error("RAND_bytes");
+
+ kdf = EVP_KDF_fetch(NULL, "X942KDF", NULL);
+ if (kctx == NULL)
+ error("EVP_KDF_fetch");
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+ if (kctx == NULL)
+ error("EVP_KDF_CTX_new");
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, "SHA256", 0);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SECRET,
+ "secret", (size_t)6);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_UKM, ukm, sizeof(ukm));
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CEK_ALG, "AES-256-WRAP, 0);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0)
+ error("EVP_KDF_derive");
+
+ EVP_KDF_CTX_free(kctx);
+
+=head1 CONFORMING TO
+
+ANS1 X9.42-2003
+RFC 2631
+
+=head1 SEE ALSO
+
+L<EVP_KDF(3)>,
+L<EVP_KDF_CTX_new(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_CTX_set_params(3)>,
+L<EVP_KDF_CTX_get_kdf_size(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF(3)/PARAMETERS>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KDF-X942-CONCAT.pod b/doc/man7/EVP_KDF-X942-CONCAT.pod
new file mode 100644
index 000000000000..6b8ebff37747
--- /dev/null
+++ b/doc/man7/EVP_KDF-X942-CONCAT.pod
@@ -0,0 +1,35 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF-X942-CONCAT - The X942 Concat EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+The EVP_KDF-X942-CONCAT algorithm is identical to EVP_KDF-X963. It is
+used for key agreement to derive a key using input such as a shared secret key
+and shared info.
+
+=head2 Identity
+
+"X942KDF_CONCAT" is the name for this implementation; it
+can be used with the EVP_KDF_fetch() function.
+
+This is an alias for "X963KDF".
+
+See L<EVP_KDF-X963(7)> for a list of supported parameters and examples.
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KDF-X963.pod b/doc/man7/EVP_KDF-X963.pod
new file mode 100644
index 000000000000..3d6f4372cf31
--- /dev/null
+++ b/doc/man7/EVP_KDF-X963.pod
@@ -0,0 +1,108 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF-X963 - The X9.63-2001 EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+The EVP_KDF-X963 algorithm implements the key derivation function (X963KDF).
+X963KDF is used by Cryptographic Message Syntax (CMS) for EC KeyAgreement, to
+derive a key using input such as a shared secret key and shared info.
+
+=head2 Identity
+
+"X963KDF" is the name for this implementation; it
+can be used with the EVP_KDF_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
+
+These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
+
+=item "key" (B<OSSL_KDF_PARAM_KEY>) <octet string>
+
+The shared secret used for key derivation.
+This parameter sets the secret.
+
+=item "info" (B<OSSL_KDF_PARAM_INFO>) <octet string>
+
+This parameter specifies an optional value for shared info.
+
+=back
+
+=head1 NOTES
+
+X963KDF is very similar to the SSKDF that uses a digest as the auxiliary function,
+X963KDF appends the counter to the secret, whereas SSKDF prepends the counter.
+
+A context for X963KDF can be obtained by calling:
+
+ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "X963KDF", NULL);
+ EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
+
+The output length of an X963KDF is specified via the I<keylen>
+parameter to the L<EVP_KDF_derive(3)> function.
+
+=head1 EXAMPLES
+
+This example derives 10 bytes, with the secret key "secret" and sharedinfo
+value "label":
+
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx;
+ unsigned char out[10];
+ OSSL_PARAM params[4], *p = params;
+
+ kdf = EVP_KDF_fetch(NULL, "X963KDF", NULL);
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ SN_sha256, strlen(SN_sha256));
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SECRET,
+ "secret", (size_t)6);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
+ "label", (size_t)5);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
+ error("EVP_KDF_derive");
+ }
+
+ EVP_KDF_CTX_free(kctx);
+
+=head1 CONFORMING TO
+
+"SEC 1: Elliptic Curve Cryptography"
+
+=head1 SEE ALSO
+
+L<EVP_KDF(3)>,
+L<EVP_KDF_CTX_new(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_CTX_set_params(3)>,
+L<EVP_KDF_CTX_get_kdf_size(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF(3)/PARAMETERS>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KEM-RSA.pod b/doc/man7/EVP_KEM-RSA.pod
new file mode 100644
index 000000000000..3a89f5db39a3
--- /dev/null
+++ b/doc/man7/EVP_KEM-RSA.pod
@@ -0,0 +1,70 @@
+=pod
+
+=head1 NAME
+
+EVP_KEM-RSA
+- EVP_KEM RSA keytype and algorithm support
+
+=head1 DESCRIPTION
+
+The B<RSA> keytype and its parameters are described in L<EVP_PKEY-RSA(7)>.
+See L<EVP_PKEY_encapsulate(3)> and L<EVP_PKEY_decapsulate(3)> for more info.
+
+=head2 RSA KEM parameters
+
+=over 4
+
+=item "operation" (B<OSSL_KEM_PARAM_OPERATION>) <UTF8 string>
+
+The OpenSSL RSA Key Encapsulation Mechanism only currently supports the
+following operation
+
+=over 4
+
+=item "RSASVE"
+
+The encapsulate function simply generates a secret using random bytes and then
+encrypts the secret using the RSA public key (with no padding).
+The decapsulate function recovers the secret using the RSA private key.
+
+=back
+
+This can be set using EVP_PKEY_CTX_set_kem_op().
+
+=back
+
+
+=head1 CONFORMING TO
+
+=over 4
+
+=item SP800-56Br2
+
+Section 7.2.1.2 RSASVE Generate Operation (RSASVE.GENERATE).
+Section 7.2.1.3 RSASVE Recovery Operation (RSASVE.RECOVER).
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_set_kem_op(3)>,
+L<EVP_PKEY_encapsulate(3)>,
+L<EVP_PKEY_decapsulate(3)>
+L<EVP_KEYMGMT(3)>,
+L<EVP_PKEY(3)>,
+L<provider-keymgmt(7)>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KEYEXCH-DH.pod b/doc/man7/EVP_KEYEXCH-DH.pod
new file mode 100644
index 000000000000..a6927afefb24
--- /dev/null
+++ b/doc/man7/EVP_KEYEXCH-DH.pod
@@ -0,0 +1,132 @@
+=pod
+
+=head1 NAME
+
+EVP_KEYEXCH-DH
+- DH Key Exchange algorithm support
+
+=head1 DESCRIPTION
+
+Key exchange support for the B<DH> key type.
+
+=head2 DH key exchange parameters
+
+=over 4
+
+=item "pad" (B<OSSL_EXCHANGE_PARAM_PAD>) <unsigned integer>
+
+Sets the padding mode for the associated key exchange ctx.
+Setting a value of 1 will turn padding on.
+Setting a value of 0 will turn padding off.
+If padding is off then the derived shared secret may be smaller than the
+largest possible secret size.
+If padding is on then the derived shared secret will have its first bytes
+filled with zeros where necessary to make the shared secret the same size as
+the largest possible secret size.
+The padding mode parameter is ignored (and padding implicitly enabled) when
+the KDF type is set to "X942KDF-ASN1" (B<OSSL_KDF_NAME_X942KDF_ASN1>).
+
+=item "kdf-type" (B<OSSL_EXCHANGE_PARAM_KDF_TYPE>) <UTF8 string>
+
+See L<provider-keyexch(7)/Common Key Exchange parameters>.
+
+=item "kdf-digest" (B<OSSL_EXCHANGE_PARAM_KDF_DIGEST>) <UTF8 string>
+
+See L<provider-keyexch(7)/Common Key Exchange parameters>.
+
+=item "kdf-digest-props" (B<OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS>) <UTF8 string>
+
+See L<provider-keyexch(7)/Common Key Exchange parameters>.
+
+=item "kdf-outlen" (B<OSSL_EXCHANGE_PARAM_KDF_OUTLEN>) <unsigned integer>
+
+See L<provider-keyexch(7)/Common Key Exchange parameters>.
+
+=item "kdf-ukm" (B<OSSL_EXCHANGE_PARAM_KDF_UKM>) <octet string>
+
+See L<provider-keyexch(7)/Common Key Exchange parameters>.
+
+=item "cekalg" (B<OSSL_KDF_PARAM_CEK_ALG>) <octet string ptr>
+
+See L<provider-kdf(7)/KDF Parameters>.
+
+=back
+
+=head1 EXAMPLES
+
+The examples assume a host and peer both generate keys using the same
+named group (or domain parameters). See L<EVP_PKEY-DH(7)/Examples>.
+Both the host and peer transfer their public key to each other.
+
+To convert the peer's generated key pair to a public key in DER format in order
+to transfer to the host:
+
+ EVP_PKEY *peer_key; /* It is assumed this contains the peers generated key */
+ unsigned char *peer_pub_der = NULL;
+ int peer_pub_der_len;
+
+ peer_pub_der_len = i2d_PUBKEY(peer_key, &peer_pub_der);
+ ...
+ OPENSSL_free(peer_pub_der);
+
+To convert the received peer's public key from DER format on the host:
+
+ const unsigned char *pd = peer_pub_der;
+ EVP_PKEY *peer_pub_key = d2i_PUBKEY(NULL, &pd, peer_pub_der_len);
+ ...
+ EVP_PKEY_free(peer_pub_key);
+
+To derive a shared secret on the host using the host's key and the peer's public
+key:
+
+ /* It is assumed that the host_key and peer_pub_key are set up */
+ void derive_secret(EVP_KEY *host_key, EVP_PKEY *peer_pub_key)
+ {
+ unsigned int pad = 1;
+ OSSL_PARAM params[2];
+ unsigned char *secret = NULL;
+ size_t secret_len = 0;
+ EVP_PKEY_CTX *dctx = EVP_PKEY_CTX_new_from_pkey(NULL, host_key, NULL);
+
+ EVP_PKEY_derive_init(dctx);
+
+ /* Optionally set the padding */
+ params[0] = OSSL_PARAM_construct_uint(OSSL_EXCHANGE_PARAM_PAD, &pad);
+ params[1] = OSSL_PARAM_construct_end();
+ EVP_PKEY_CTX_set_params(dctx, params);
+
+ EVP_PKEY_derive_set_peer(dctx, peer_pub_key);
+
+ /* Get the size by passing NULL as the buffer */
+ EVP_PKEY_derive(dctx, NULL, &secret_len);
+ secret = OPENSSL_zalloc(secret_len);
+
+ EVP_PKEY_derive(dctx, secret, &secret_len);
+ ...
+ OPENSSL_clear_free(secret, secret_len);
+ EVP_PKEY_CTX_free(dctx);
+ }
+
+Very similar code can be used by the peer to derive the same shared secret
+using the host's public key and the peer's generated key pair.
+
+=head1 SEE ALSO
+
+L<EVP_PKEY-DH(7)>,
+L<EVP_PKEY-FFC(7)>,
+L<EVP_PKEY(3)>,
+L<provider-keyexch(7)>,
+L<provider-keymgmt(7)>,
+L<OSSL_PROVIDER-default(7)>,
+L<OSSL_PROVIDER-FIPS(7)>,
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KEYEXCH-ECDH.pod b/doc/man7/EVP_KEYEXCH-ECDH.pod
new file mode 100644
index 000000000000..3d630d91bf65
--- /dev/null
+++ b/doc/man7/EVP_KEYEXCH-ECDH.pod
@@ -0,0 +1,117 @@
+=pod
+
+=head1 NAME
+
+EVP_KEYEXCH-ECDH - ECDH Key Exchange algorithm support
+
+=head1 DESCRIPTION
+
+Key exchange support for the B<ECDH> key type.
+
+=head2 ECDH Key Exchange parameters
+
+=over 4
+
+=item "ecdh-cofactor-mode" (B<OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE>) <integer>
+
+Sets or gets the ECDH mode of operation for the associated key exchange ctx.
+
+In the context of an Elliptic Curve Diffie-Hellman key exchange, this parameter
+can be used to select between the plain Diffie-Hellman (DH) or Cofactor
+Diffie-Hellman (CDH) variants of the key exchange algorithm.
+
+When setting, the value should be 1, 0 or -1, respectively forcing cofactor mode
+on, off, or resetting it to the default for the private key associated with the
+given key exchange ctx.
+
+When getting, the value should be either 1 or 0, respectively signaling if the
+cofactor mode is on or off.
+
+See also L<provider-keymgmt(7)> for the related
+B<OSSL_PKEY_PARAM_USE_COFACTOR_ECDH> parameter that can be set on a
+per-key basis.
+
+=item "kdf-type" (B<OSSL_EXCHANGE_PARAM_KDF_TYPE>) <UTF8 string>
+
+See L<provider-keyexch(7)/Common Key Exchange parameters>.
+
+=item "kdf-digest" (B<OSSL_EXCHANGE_PARAM_KDF_DIGEST>) <UTF8 string>
+
+See L<provider-keyexch(7)/Common Key Exchange parameters>.
+
+=item "kdf-digest-props" (B<OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS>) <UTF8 string>
+
+See L<provider-keyexch(7)/Common Key Exchange parameters>.
+
+=item "kdf-outlen" (B<OSSL_EXCHANGE_PARAM_KDF_OUTLEN>) <unsigned integer>
+
+See L<provider-keyexch(7)/Common Key Exchange parameters>.
+
+=item "kdf-ukm" (B<OSSL_EXCHANGE_PARAM_KDF_UKM>) <octet string>
+
+See L<provider-keyexch(7)/Common Key Exchange parameters>.
+
+=back
+
+=head1 EXAMPLES
+
+Keys for the host and peer must be generated as shown in
+L<EVP_PKEY-EC(7)/Examples> using the same curve name.
+
+The code to generate a shared secret for the normal case is identical to
+L<EVP_KEYEXCH-DH(7)/Examples>.
+
+To derive a shared secret on the host using the host's key and the peer's public
+key but also using X963KDF with a user key material:
+
+ /* It is assumed that the host_key, peer_pub_key and ukm are set up */
+ void derive_secret(EVP_PKEY *host_key, EVP_PKEY *peer_key,
+ unsigned char *ukm, size_t ukm_len)
+ {
+ unsigned char secret[64];
+ size_t out_len = sizeof(secret);
+ size_t secret_len = out_len;
+ unsigned int pad = 1;
+ OSSL_PARAM params[6];
+ EVP_PKEY_CTX *dctx = EVP_PKEY_CTX_new_from_pkey(NULL, host_key, NULL);
+
+ EVP_PKEY_derive_init(dctx);
+
+ params[0] = OSSL_PARAM_construct_uint(OSSL_EXCHANGE_PARAM_PAD, &pad);
+ params[1] = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE,
+ "X963KDF", 0);
+ params[2] = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST,
+ "SHA1", 0);
+ params[3] = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
+ &out_len);
+ params[4] = OSSL_PARAM_construct_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM,
+ ukm, ukm_len);
+ params[5] = OSSL_PARAM_construct_end();
+ EVP_PKEY_CTX_set_params(dctx, params);
+
+ EVP_PKEY_derive_set_peer(dctx, peer_pub_key);
+ EVP_PKEY_derive(dctx, secret, &secret_len);
+ ...
+ OPENSSL_clear_free(secret, secret_len);
+ EVP_PKEY_CTX_free(dctx);
+ }
+
+=head1 SEE ALSO
+
+L<EVP_PKEY-EC(7)>
+L<EVP_PKEY(3)>,
+L<provider-keyexch(7)>,
+L<provider-keymgmt(7)>,
+L<OSSL_PROVIDER-default(7)>,
+L<OSSL_PROVIDER-FIPS(7)>,
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KEYEXCH-X25519.pod b/doc/man7/EVP_KEYEXCH-X25519.pod
new file mode 100644
index 000000000000..6140c56196e4
--- /dev/null
+++ b/doc/man7/EVP_KEYEXCH-X25519.pod
@@ -0,0 +1,50 @@
+=pod
+
+=head1 NAME
+
+EVP_KEYEXCH-X25519,
+EVP_KEYEXCH-X448
+- X25519 and X448 Key Exchange algorithm support
+
+=head1 DESCRIPTION
+
+Key exchange support for the B<X25519> and B<X448> key types.
+
+=head2 Key exchange parameters
+
+=over 4
+
+=item "pad" (B<OSSL_EXCHANGE_PARAM_PAD>) <unsigned integer>
+
+See L<provider-keyexch(7)/Common Key Exchange parameters>.
+
+=back
+
+=head1 EXAMPLES
+
+Keys for the host and peer can be generated as shown in
+L<EVP_PKEY-X25519(7)/Examples>.
+
+The code to generate a shared secret is identical to
+L<EVP_KEYEXCH-DH(7)/Examples>.
+
+=head1 SEE ALSO
+
+L<EVP_PKEY-FFC(7)>,
+L<EVP_PKEY-DH(7)>
+L<EVP_PKEY(3)>,
+L<provider-keyexch(7)>,
+L<provider-keymgmt(7)>,
+L<OSSL_PROVIDER-default(7)>,
+L<OSSL_PROVIDER-FIPS(7)>,
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MAC-BLAKE2.pod b/doc/man7/EVP_MAC-BLAKE2.pod
new file mode 100644
index 000000000000..5557e153536a
--- /dev/null
+++ b/doc/man7/EVP_MAC-BLAKE2.pod
@@ -0,0 +1,90 @@
+=pod
+
+=head1 NAME
+
+EVP_MAC-BLAKE2, EVP_MAC-BLAKE2BMAC, EVP_MAC-BLAKE2SMAC
+- The BLAKE2 EVP_MAC implementations
+
+=head1 DESCRIPTION
+
+Support for computing BLAKE2 MACs through the B<EVP_MAC> API.
+
+=head2 Identity
+
+These implementations are identified with one of these names and
+properties, to be used with EVP_MAC_fetch():
+
+=over 4
+
+=item "BLAKE2BMAC", "provider=default"
+
+=item "BLAKE2SMAC", "provider=default"
+
+=back
+
+=head2 Supported parameters
+
+The general description of these parameters can be found in
+L<EVP_MAC(3)/PARAMETERS>.
+
+All these parameters can be set with EVP_MAC_CTX_set_params().
+Furthermore, the "size" parameter can be retrieved with
+EVP_MAC_CTX_get_params(), or with EVP_MAC_CTX_get_mac_size().
+The length of the "size" parameter should not exceed that of a B<size_t>.
+Likewise, the "block-size" parameter can be retrieved with
+EVP_MAC_CTX_get_params(), or with EVP_MAC_CTX_get_block_size().
+
+=over 4
+
+=item "key" (B<OSSL_MAC_PARAM_KEY>) <octet string>
+
+Sets the MAC key.
+It may be at most 64 bytes for BLAKE2BMAC or 32 for BLAKE2SMAC and at
+least 1 byte in both cases.
+Setting this parameter is identical to passing a I<key> to L<EVP_MAC_init(3)>.
+
+=item "custom" (B<OSSL_MAC_PARAM_CUSTOM>) <octet string>
+
+Sets the custom value.
+It is an optional value of at most 16 bytes for BLAKE2BMAC or 8 for
+BLAKE2SMAC, and is empty by default.
+
+=item "salt" (B<OSSL_MAC_PARAM_SALT>) <octet string>
+
+Sets the salt.
+It is an optional value of at most 16 bytes for BLAKE2BMAC or 8 for
+BLAKE2SMAC, and is empty by default.
+
+=item "size" (B<OSSL_MAC_PARAM_SIZE>) <unsigned integer>
+
+Sets the MAC size.
+It can be any number between 1 and 32 for EVP_MAC_BLAKE2S or between 1
+and 64 for EVP_MAC_BLAKE2B.
+It is 32 and 64 respectively by default.
+
+=item "block-size" (B<OSSL_MAC_PARAM_SIZE>) <unsigned integer>
+
+Gets the MAC block size.
+By default, it is 64 for EVP_MAC_BLAKE2S and 128 for EVP_MAC_BLAKE2B.
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_MAC_CTX_get_params(3)>, L<EVP_MAC_CTX_set_params(3)>,
+L<EVP_MAC(3)/PARAMETERS>, L<OSSL_PARAM(3)>
+
+=head1 HISTORY
+
+The macros and functions described here were added to OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MAC-CMAC.pod b/doc/man7/EVP_MAC-CMAC.pod
new file mode 100644
index 000000000000..cf80586f0244
--- /dev/null
+++ b/doc/man7/EVP_MAC-CMAC.pod
@@ -0,0 +1,86 @@
+=pod
+
+=head1 NAME
+
+EVP_MAC-CMAC - The CMAC EVP_MAC implementation
+
+=head1 DESCRIPTION
+
+Support for computing CMAC MACs through the B<EVP_MAC> API.
+
+This implementation uses EVP_CIPHER functions to get access to the underlying
+cipher.
+
+=head2 Identity
+
+This implementation is identified with this name and properties, to be
+used with EVP_MAC_fetch():
+
+=over 4
+
+=item "CMAC", "provider=default" or "provider=fips"
+
+=back
+
+=head2 Supported parameters
+
+The general description of these parameters can be found in
+L<EVP_MAC(3)/PARAMETERS>.
+
+The following parameter can be set with EVP_MAC_CTX_set_params():
+
+=over 4
+
+=item "key" (B<OSSL_MAC_PARAM_KEY>) <octet string>
+
+Sets the MAC key.
+Setting this parameter is identical to passing a I<key> to L<EVP_MAC_init(3)>.
+
+=item "cipher" (B<OSSL_MAC_PARAM_CIPHER>) <UTF8 string>
+
+Sets the name of the underlying cipher to be used.
+
+=item "properties" (B<OSSL_MAC_PARAM_PROPERTIES>) <UTF8 string>
+
+Sets the properties to be queried when trying to fetch the underlying cipher.
+This must be given together with the cipher naming parameter to be considered
+valid.
+
+=back
+
+The following parameters can be retrieved with
+EVP_MAC_CTX_get_params():
+
+=over 4
+
+=item "size" (B<OSSL_MAC_PARAM_SIZE>) <unsigned integer>
+
+The "size" parameter can also be retrieved with with EVP_MAC_CTX_get_mac_size().
+The length of the "size" parameter is equal to that of an B<unsigned int>.
+
+=back
+
+=over 4
+
+=item "block-size" (B<OSSL_MAC_PARAM_SIZE>) <unsigned integer>
+
+Gets the MAC block size. The "block-size" parameter can also be retrieved with
+EVP_MAC_CTX_get_block_size().
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_MAC_CTX_get_params(3)>, L<EVP_MAC_CTX_set_params(3)>,
+L<EVP_MAC(3)/PARAMETERS>, L<OSSL_PARAM(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MAC-GMAC.pod b/doc/man7/EVP_MAC-GMAC.pod
new file mode 100644
index 000000000000..7de83fe7b58e
--- /dev/null
+++ b/doc/man7/EVP_MAC-GMAC.pod
@@ -0,0 +1,83 @@
+=pod
+
+=head1 NAME
+
+EVP_MAC-GMAC - The GMAC EVP_MAC implementation
+
+=head1 DESCRIPTION
+
+Support for computing GMAC MACs through the B<EVP_MAC> API.
+
+This implementation uses EVP_CIPHER functions to get access to the underlying
+cipher.
+
+=head2 Identity
+
+This implementation is identified with this name and properties, to be
+used with EVP_MAC_fetch():
+
+=over 4
+
+=item "GMAC", "provider=default" or "provider=fips"
+
+=back
+
+=head2 Supported parameters
+
+The general description of these parameters can be found in
+L<EVP_MAC(3)/PARAMETERS>.
+
+The following parameter can be set with EVP_MAC_CTX_set_params():
+
+=over 4
+
+=item "key" (B<OSSL_MAC_PARAM_KEY>) <octet string>
+
+Sets the MAC key.
+Setting this parameter is identical to passing a I<key> to L<EVP_MAC_init(3)>.
+
+=item "iv" (B<OSSL_MAC_PARAM_IV>) <octet string>
+
+Sets the IV of the underlying cipher, when applicable.
+
+=item "cipher" (B<OSSL_MAC_PARAM_CIPHER>) <UTF8 string>
+
+Sets the name of the underlying cipher to be used.
+
+=item "properties" (B<OSSL_MAC_PARAM_PROPERTIES>) <UTF8 string>
+
+Sets the properties to be queried when trying to fetch the underlying cipher.
+This must be given together with the cipher naming parameter to be considered
+valid.
+
+=back
+
+The following parameters can be retrieved with
+EVP_MAC_CTX_get_params():
+
+=over 4
+
+=item "size" (B<OSSL_MAC_PARAM_SIZE>) <unsigned integer>
+
+Gets the MAC size.
+
+=back
+
+The "size" parameter can also be retrieved with EVP_MAC_CTX_get_mac_size().
+The length of the "size" parameter is equal to that of an B<unsigned int>.
+
+=head1 SEE ALSO
+
+L<EVP_MAC_CTX_get_params(3)>, L<EVP_MAC_CTX_set_params(3)>,
+L<EVP_MAC(3)/PARAMETERS>, L<OSSL_PARAM(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MAC-HMAC.pod b/doc/man7/EVP_MAC-HMAC.pod
new file mode 100644
index 000000000000..ea2eda9ec819
--- /dev/null
+++ b/doc/man7/EVP_MAC-HMAC.pod
@@ -0,0 +1,100 @@
+=pod
+
+=head1 NAME
+
+EVP_MAC-HMAC - The HMAC EVP_MAC implementation
+
+=head1 DESCRIPTION
+
+Support for computing HMAC MACs through the B<EVP_MAC> API.
+
+This implementation uses EVP_MD functions to get access to the underlying
+digest.
+
+=head2 Identity
+
+This implementation is identified with this name and properties, to be
+used with EVP_MAC_fetch():
+
+=over 4
+
+=item "HMAC", "provider=default" or "provider=fips"
+
+=back
+
+=head2 Supported parameters
+
+The general description of these parameters can be found in
+L<EVP_MAC(3)/PARAMETERS>.
+
+The following parameter can be set with EVP_MAC_CTX_set_params():
+
+=over 4
+
+=item "key" (B<OSSL_MAC_PARAM_KEY>) <octet string>
+
+Sets the MAC key.
+Setting this parameter is identical to passing a I<key> to L<EVP_MAC_init(3)>.
+
+=item "digest" (B<OSSL_MAC_PARAM_DIGEST>) <UTF8 string>
+
+Sets the name of the underlying digest to be used.
+
+=item "properties" (B<OSSL_MAC_PARAM_PROPERTIES>) <UTF8 string>
+
+Sets the properties to be queried when trying to fetch the underlying digest.
+This must be given together with the digest naming parameter ("digest", or
+B<OSSL_MAC_PARAM_DIGEST>) to be considered valid.
+
+=item "digest-noinit" (B<OSSL_MAC_PARAM_DIGEST_NOINIT>) <integer>
+
+A flag to set the MAC digest to not initialise the implementation
+specific data.
+The value 0 or 1 is expected.
+
+=item "digest-oneshot" (B<OSSL_MAC_PARAM_DIGEST_ONESHOT>) <integer>
+
+A flag to set the MAC digest to be a one-shot operation.
+The value 0 or 1 is expected.
+
+=item "tls-data-size" (B<OSSL_MAC_PARAM_TLS_DATA_SIZE>) <unsigned integer>
+
+=back
+
+=for comment The "flags" parameter is passed directly to HMAC_CTX_set_flags().
+
+The following parameter can be retrieved with EVP_MAC_CTX_get_params():
+
+=over 4
+
+=item "size" (B<OSSL_MAC_PARAM_SIZE>) <unsigned integer>
+
+The "size" parameter can also be retrieved with EVP_MAC_CTX_get_mac_size().
+The length of the "size" parameter is equal to that of an B<unsigned int>.
+
+=back
+
+=over 4
+
+=item "block-size" (B<OSSL_MAC_PARAM_SIZE>) <unsigned integer>
+
+Gets the MAC block size. The "block-size" parameter can also be retrieved with
+EVP_MAC_CTX_get_block_size().
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_MAC_CTX_get_params(3)>, L<EVP_MAC_CTX_set_params(3)>,
+L<EVP_MAC(3)/PARAMETERS>, L<OSSL_PARAM(3)>, L<HMAC(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MAC-KMAC.pod b/doc/man7/EVP_MAC-KMAC.pod
new file mode 100644
index 000000000000..1065c166db2c
--- /dev/null
+++ b/doc/man7/EVP_MAC-KMAC.pod
@@ -0,0 +1,152 @@
+=pod
+
+=head1 NAME
+
+EVP_MAC-KMAC, EVP_MAC-KMAC128, EVP_MAC-KMAC256
+- The KMAC EVP_MAC implementations
+
+=head1 DESCRIPTION
+
+Support for computing KMAC MACs through the B<EVP_MAC> API.
+
+=head2 Identity
+
+These implementations are identified with one of these names and
+properties, to be used with EVP_MAC_fetch():
+
+=over 4
+
+=item "KMAC-128", "provider=default" or "provider=fips"
+
+=item "KMAC-256", "provider=default" or "provider=fips"
+
+=back
+
+=head2 Supported parameters
+
+The general description of these parameters can be found in
+L<EVP_MAC(3)/PARAMETERS>.
+
+All these parameters can be set with EVP_MAC_CTX_set_params().
+Furthermore, the "size" parameter can be retrieved with
+EVP_MAC_CTX_get_params(), or with EVP_MAC_CTX_get_mac_size().
+The length of the "size" parameter should not exceed that of a B<size_t>.
+Likewise, the "block-size" parameter can be retrieved with
+EVP_MAC_CTX_get_params(), or with EVP_MAC_CTX_get_block_size().
+
+
+=over 4
+
+=item "key" (B<OSSL_MAC_PARAM_KEY>) <octet string>
+
+Sets the MAC key.
+Setting this parameter is identical to passing a I<key> to L<EVP_MAC_init(3)>.
+The length of the key (in bytes) must be in the range 4...512.
+
+=item "custom" (B<OSSL_MAC_PARAM_CUSTOM>) <octet string>
+
+Sets the custom value.
+It is an optional value with a length of at most 512 bytes, and is empty by default.
+
+=item "size" (B<OSSL_MAC_PARAM_SIZE>) <unsigned integer>
+
+Sets the MAC size.
+By default, it is 16 for C<KMAC-128> and 32 for C<KMAC-256>.
+
+=item "block-size" (B<OSSL_MAC_PARAM_SIZE>) <unsigned integer>
+
+Gets the MAC block size.
+By default, it is 168 for C<KMAC-128> and 136 for C<KMAC-256>.
+
+=item "xof" (B<OSSL_MAC_PARAM_XOF>) <integer>
+
+The "xof" parameter value is expected to be 1 or 0. Use 1 to enable XOF mode.
+The default value is 0.
+
+=back
+
+The "custom" parameter must be set as part of or before the EVP_MAC_init() call.
+The "xof" and "size" parameters can be set at any time before EVP_MAC_final().
+The "key" parameter is set as part of the EVP_MAC_init() call, but can be
+set before it instead.
+
+=head1 EXAMPLES
+
+ #include <openssl/evp.h>
+ #include <openssl/params.h>
+
+ static int do_kmac(const unsigned char *in, size_t in_len,
+ const unsigned char *key, size_t key_len,
+ const unsigned char *custom, size_t custom_len,
+ int xof_enabled, unsigned char *out, int out_len)
+ {
+ EVP_MAC_CTX *ctx = NULL;
+ EVP_MAC *mac = NULL;
+ OSSL_PARAM params[4], *p;
+ int ret = 0;
+ size_t l = 0;
+
+ mac = EVP_MAC_fetch(NULL, "KMAC-128", NULL);
+ if (mac == NULL)
+ goto err;
+ ctx = EVP_MAC_CTX_new(mac);
+ /* The mac can be freed after it is used by EVP_MAC_CTX_new */
+ EVP_MAC_free(mac);
+ if (ctx == NULL)
+ goto err;
+
+ /*
+ * Setup parameters required before calling EVP_MAC_init()
+ * The parameters OSSL_MAC_PARAM_XOF and OSSL_MAC_PARAM_SIZE may also be
+ * used at this point.
+ */
+ p = params;
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ (void *)key, key_len);
+ if (custom != NULL && custom_len != 0)
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_CUSTOM,
+ (void *)custom, custom_len);
+ *p = OSSL_PARAM_construct_end();
+ if (!EVP_MAC_CTX_set_params(ctx, params))
+ goto err;
+
+ if (!EVP_MAC_init(ctx))
+ goto err;
+
+ /*
+ * Note: the following optional parameters can be set any time
+ * before EVP_MAC_final().
+ */
+ p = params;
+ *p++ = OSSL_PARAM_construct_int(OSSL_MAC_PARAM_XOF, &xof_enabled);
+ *p++ = OSSL_PARAM_construct_int(OSSL_MAC_PARAM_SIZE, &out_len);
+ *p = OSSL_PARAM_construct_end();
+ if (!EVP_MAC_CTX_set_params(ctx, params))
+ goto err;
+
+ /* The update may be called multiple times here for streamed input */
+ if (!EVP_MAC_update(ctx, in, in_len))
+ goto err;
+ if (!EVP_MAC_final(ctx, out, &l, out_len))
+ goto err;
+ ret = 1;
+ err:
+ EVP_MAC_CTX_free(ctx);
+ return ret;
+ }
+
+=head1 SEE ALSO
+
+L<EVP_MAC_CTX_get_params(3)>, L<EVP_MAC_CTX_set_params(3)>,
+L<EVP_MAC(3)/PARAMETERS>, L<OSSL_PARAM(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MAC-Poly1305.pod b/doc/man7/EVP_MAC-Poly1305.pod
new file mode 100644
index 000000000000..a942226cd8aa
--- /dev/null
+++ b/doc/man7/EVP_MAC-Poly1305.pod
@@ -0,0 +1,73 @@
+=pod
+
+=head1 NAME
+
+EVP_MAC-Poly1305 - The Poly1305 EVP_MAC implementation
+
+=head1 DESCRIPTION
+
+Support for computing Poly1305 MACs through the B<EVP_MAC> API.
+
+=head2 Identity
+
+This implementation is identified with this name and properties, to be
+used with EVP_MAC_fetch():
+
+=over 4
+
+=item "POLY1305", "provider=default"
+
+=back
+
+=head2 Supported parameters
+
+The general description of these parameters can be found in
+L<EVP_MAC(3)/PARAMETERS>.
+
+The following parameter can be set with EVP_MAC_CTX_set_params():
+
+=over 4
+
+=item "key" (B<OSSL_MAC_PARAM_KEY>) <octet string>
+
+Sets the MAC key.
+Setting this parameter is identical to passing a I<key> to L<EVP_MAC_init(3)>.
+
+=back
+
+The following parameters can be retrieved with
+EVP_MAC_CTX_get_params():
+
+=over 4
+
+=item "size" (B<OSSL_MAC_PARAM_SIZE>) <unsigned integer>
+
+Gets the MAC size.
+
+=back
+
+The "size" parameter can also be retrieved with with EVP_MAC_CTX_get_mac_size().
+The length of the "size" parameter should not exceed that of an B<unsigned int>.
+
+=head1 NOTES
+
+The OpenSSL implementation of the Poly 1305 MAC corresponds to RFC 7539.
+
+It is critical to never reuse the key. The security implication noted in
+RFC 8439 applies equally to the OpenSSL implementation.
+
+=head1 SEE ALSO
+
+L<EVP_MAC_CTX_get_params(3)>, L<EVP_MAC_CTX_set_params(3)>,
+L<EVP_MAC(3)/PARAMETERS>, L<OSSL_PARAM(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MAC-Siphash.pod b/doc/man7/EVP_MAC-Siphash.pod
new file mode 100644
index 000000000000..7f5792bf3164
--- /dev/null
+++ b/doc/man7/EVP_MAC-Siphash.pod
@@ -0,0 +1,68 @@
+=pod
+
+=head1 NAME
+
+EVP_MAC-Siphash - The Siphash EVP_MAC implementation
+
+=head1 DESCRIPTION
+
+Support for computing Siphash MACs through the B<EVP_MAC> API.
+
+=head2 Identity
+
+This implementation is identified with this name and properties, to be
+used with EVP_MAC_fetch():
+
+=over 4
+
+=item "SIPHASH", "provider=default"
+
+=back
+
+
+=head2 Supported parameters
+
+The general description of these parameters can be found in
+L<EVP_MAC(3)/PARAMETERS>.
+
+All these parameters can be set with EVP_MAC_CTX_set_params().
+Furthermore, the "size" parameter can be retrieved with
+EVP_MAC_CTX_get_params(), or with EVP_MAC_CTX_get_mac_size().
+The length of the "size" parameter should not exceed that of a B<size_t>.
+
+=over 4
+
+=item "key" (B<OSSL_MAC_PARAM_KEY>) <octet string>
+
+Sets the MAC key.
+Setting this parameter is identical to passing a I<key> to L<EVP_MAC_init(3)>.
+
+=item "size" (B<OSSL_MAC_PARAM_SIZE>) <unsigned integer>
+
+Sets the MAC size.
+
+=item "c-rounds" (B<OSSL_MAC_PARAM_C_ROUNDS>) <unsigned integer>
+
+Specifies the number of rounds per message block. By default this is I<2>.
+
+=item "d-rounds" (B<OSSL_MAC_PARAM_D_ROUNDS>) <unsigned integer>
+
+Specifies the number of finalisation rounds. By default this is I<4>.
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_MAC_CTX_get_params(3)>, L<EVP_MAC_CTX_set_params(3)>,
+L<EVP_MAC(3)/PARAMETERS>, L<OSSL_PARAM(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MD-BLAKE2.pod b/doc/man7/EVP_MD-BLAKE2.pod
new file mode 100644
index 000000000000..f72d3da1ce8e
--- /dev/null
+++ b/doc/man7/EVP_MD-BLAKE2.pod
@@ -0,0 +1,46 @@
+=pod
+
+=head1 NAME
+
+EVP_MD-BLAKE2 - The BLAKE2 EVP_MD implementation
+
+=head1 DESCRIPTION
+
+Support for computing BLAKE2 digests through the B<EVP_MD> API.
+
+=head2 Identities
+
+This implementation is only available with the default provider, and
+includes the following varieties:
+
+=over 4
+
+=item BLAKE2S-256
+
+Known names are "BLAKE2S-256" and "BLAKE2s256".
+
+=item BLAKE2B-512
+
+Known names are "BLAKE2B-512" and "BLAKE2b512".
+
+=back
+
+=head2 Gettable Parameters
+
+This implementation supports the common gettable parameters described
+in L<EVP_MD-common(7)>.
+
+=head1 SEE ALSO
+
+L<provider-digest(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MD-MD2.pod b/doc/man7/EVP_MD-MD2.pod
new file mode 100644
index 000000000000..61fc42fc4d3e
--- /dev/null
+++ b/doc/man7/EVP_MD-MD2.pod
@@ -0,0 +1,34 @@
+=pod
+
+=head1 NAME
+
+EVP_MD-MD2 - The MD2 EVP_MD implementation
+
+=head1 DESCRIPTION
+
+Support for computing MD2 digests through the B<EVP_MD> API.
+
+=head2 Identity
+
+This implementation is only available with the legacy provider, and is
+identified with the name "MD2".
+
+=head2 Gettable Parameters
+
+This implementation supports the common gettable parameters described
+in L<EVP_MD-common(7)>.
+
+=head1 SEE ALSO
+
+L<provider-digest(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MD-MD4.pod b/doc/man7/EVP_MD-MD4.pod
new file mode 100644
index 000000000000..0a3f97c47b06
--- /dev/null
+++ b/doc/man7/EVP_MD-MD4.pod
@@ -0,0 +1,34 @@
+=pod
+
+=head1 NAME
+
+EVP_MD-MD4 - The MD4 EVP_MD implementation
+
+=head1 DESCRIPTION
+
+Support for computing MD4 digests through the B<EVP_MD> API.
+
+=head2 Identity
+
+This implementation is only available with the legacy provider, and is
+identified with the name "MD4".
+
+=head2 Gettable Parameters
+
+This implementation supports the common gettable parameters described
+in L<EVP_MD-common(7)>.
+
+=head1 SEE ALSO
+
+L<provider-digest(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MD-MD5-SHA1.pod b/doc/man7/EVP_MD-MD5-SHA1.pod
new file mode 100644
index 000000000000..61652ad5c69b
--- /dev/null
+++ b/doc/man7/EVP_MD-MD5-SHA1.pod
@@ -0,0 +1,56 @@
+=pod
+
+=head1 NAME
+
+EVP_MD-MD5-SHA1 - The MD5-SHA1 EVP_MD implementation
+
+=head1 DESCRIPTION
+
+Support for computing MD5-SHA1 digests through the B<EVP_MD> API.
+
+MD5-SHA1 is a rather special digest that's used with SSLv3.
+
+=head2 Identity
+
+This implementation is only available with the default provider, and is
+identified with the name "MD5-SHA1".
+
+=head2 Gettable Parameters
+
+This implementation supports the common gettable parameters described
+in L<EVP_MD-common(7)>.
+
+=head2 Settable Context Parameters
+
+This implementation supports the following L<OSSL_PARAM(3)> entries,
+settable for an B<EVP_MD_CTX> with L<EVP_MD_CTX_set_params(3)>:
+
+=over 4
+
+=item "ssl3-ms" (B<OSSL_DIGEST_PARAM_SSL3_MS>) <octet string>
+
+This parameter is set by libssl in order to calculate a signature hash for an
+SSLv3 CertificateVerify message as per RFC6101.
+It is only set after all handshake messages have already been digested via
+OP_digest_update() calls.
+The parameter provides the master secret value to be added to the digest.
+The digest implementation should calculate the complete digest as per RFC6101
+section 5.6.8.
+The next call after setting this parameter should be OP_digest_final().
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_MD_CTX_set_params(3)>, L<provider-digest(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MD-MD5.pod b/doc/man7/EVP_MD-MD5.pod
new file mode 100644
index 000000000000..98ae2c5be506
--- /dev/null
+++ b/doc/man7/EVP_MD-MD5.pod
@@ -0,0 +1,34 @@
+=pod
+
+=head1 NAME
+
+EVP_MD-MD5 - The MD5 EVP_MD implementation
+
+=head1 DESCRIPTION
+
+Support for computing MD5 digests through the B<EVP_MD> API.
+
+=head2 Identity
+
+This implementation is only available with the default provider, and is
+identified with the name "MD5".
+
+=head2 Gettable Parameters
+
+This implementation supports the common gettable parameters described
+in L<EVP_MD-common(7)>.
+
+=head1 SEE ALSO
+
+L<provider-digest(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MD-MDC2.pod b/doc/man7/EVP_MD-MDC2.pod
new file mode 100644
index 000000000000..c8f5cb5ec2ee
--- /dev/null
+++ b/doc/man7/EVP_MD-MDC2.pod
@@ -0,0 +1,50 @@
+=pod
+
+=head1 NAME
+
+EVP_MD-MDC2 - The MDC2 EVP_MD implementation
+
+=head1 DESCRIPTION
+
+Support for computing MDC2 digests through the B<EVP_MD> API.
+
+=head2 Identity
+
+This implementation is only available with the legacy provider, and is
+identified with the name "MDC2".
+
+=head2 Gettable Parameters
+
+This implementation supports the common gettable parameters described
+in L<EVP_MD-common(7)>.
+
+=head2 Settable Context Parameters
+
+This implementation supports the following L<OSSL_PARAM(3)> entries,
+settable for an B<EVP_MD_CTX> with L<EVP_MD_CTX_set_params(3)>:
+
+=over 4
+
+=item "pad-type" (B<OSSL_DIGEST_PARAM_PAD_TYPE>) <unsigned integer>
+
+Sets the padding type to be used.
+Normally the final MDC2 block is padded with zeros.
+If the pad type is set to 2 then the final block is padded with 0x80 followed by
+zeros.
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_MD_CTX_set_params(3)>, L<provider-digest(7)>, L<OSSL_PROVIDER-legacy(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MD-RIPEMD160.pod b/doc/man7/EVP_MD-RIPEMD160.pod
new file mode 100644
index 000000000000..0bf680d2d52c
--- /dev/null
+++ b/doc/man7/EVP_MD-RIPEMD160.pod
@@ -0,0 +1,39 @@
+=pod
+
+=head1 NAME
+
+EVP_MD-RIPEMD160 - The RIPEMD160 EVP_MD implementation
+
+=head1 DESCRIPTION
+
+Support for computing RIPEMD160 digests through the B<EVP_MD> API.
+
+=head2 Identities
+
+This implementation is available in both the default and legacy providers, and is
+identified with any of the names "RIPEMD-160", "RIPEMD160", "RIPEMD" and
+"RMD160".
+
+=head2 Gettable Parameters
+
+This implementation supports the common gettable parameters described
+in L<EVP_MD-common(7)>.
+
+=head1 SEE ALSO
+
+L<provider-digest(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 HISTORY
+
+This digest was added to the default provider in OpenSSL 3.0.7.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MD-SHA1.pod b/doc/man7/EVP_MD-SHA1.pod
new file mode 100644
index 000000000000..5fd94df4ce56
--- /dev/null
+++ b/doc/man7/EVP_MD-SHA1.pod
@@ -0,0 +1,55 @@
+=pod
+
+=head1 NAME
+
+EVP_MD-SHA1 - The SHA1 EVP_MD implementation
+
+=head1 DESCRIPTION
+
+Support for computing SHA1 digests through the B<EVP_MD> API.
+
+=head2 Identities
+
+This implementation is available with the FIPS provider as well as the
+default provider, and is identified with the names "SHA1" and "SHA-1".
+
+=head2 Gettable Parameters
+
+This implementation supports the common gettable parameters described
+in L<EVP_MD-common(7)>.
+
+=head2 Settable Context Parameters
+
+This implementation supports the following L<OSSL_PARAM(3)> entries,
+settable for an B<EVP_MD_CTX> with L<EVP_MD_CTX_set_params(3)>:
+
+=over 4
+
+=item "ssl3-ms" (B<OSSL_DIGEST_PARAM_SSL3_MS>) <octet string>
+
+This parameter is set by libssl in order to calculate a signature hash for an
+SSLv3 CertificateVerify message as per RFC6101.
+It is only set after all handshake messages have already been digested via
+OP_digest_update() calls.
+The parameter provides the master secret value to be added to the digest.
+The digest implementation should calculate the complete digest as per RFC6101
+section 5.6.8.
+The next call after setting this parameter should be OP_digest_final().
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_MD_CTX_set_params(3)>, L<provider-digest(7)>,
+L<OSSL_PROVIDER-FIPS(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MD-SHA2.pod b/doc/man7/EVP_MD-SHA2.pod
new file mode 100644
index 000000000000..2a2e799d8954
--- /dev/null
+++ b/doc/man7/EVP_MD-SHA2.pod
@@ -0,0 +1,77 @@
+=pod
+
+=head1 NAME
+
+EVP_MD-SHA2 - The SHA2 EVP_MD implementation
+
+=head1 DESCRIPTION
+
+Support for computing SHA2 digests through the B<EVP_MD> API.
+
+=head2 Identities
+
+This implementation includes the following varieties:
+
+=over 4
+
+=item *
+
+Available with the FIPS provider as well as the default provider:
+
+=over 4
+
+=item SHA2-224
+
+Known names are "SHA2-224", "SHA-224" and "SHA224".
+
+=item SHA2-256
+
+Known names are "SHA2-256", "SHA-256" and "SHA256".
+
+=item SHA2-384
+
+Known names are "SHA2-384", "SHA-384" and "SHA384".
+
+=item SHA2-512
+
+Known names are "SHA2-512", "SHA-512" and "SHA512".
+
+=back
+
+=item *
+
+Available with the default provider:
+
+=over 4
+
+=item SHA2-512/224
+
+Known names are "SHA2-512/224", "SHA-512/224" and "SHA512-224".
+
+=item SHA2-512/256
+
+Known names are "SHA2-512/256", "SHA-512/256" and "SHA512-256".
+
+=back
+
+=back
+
+=head2 Gettable Parameters
+
+This implementation supports the common gettable parameters described
+in L<EVP_MD-common(7)>.
+
+=head1 SEE ALSO
+
+L<provider-digest(7)>, L<OSSL_PROVIDER-FIPS(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MD-SHA3.pod b/doc/man7/EVP_MD-SHA3.pod
new file mode 100644
index 000000000000..bc5c3508be78
--- /dev/null
+++ b/doc/man7/EVP_MD-SHA3.pod
@@ -0,0 +1,46 @@
+=pod
+
+=head1 NAME
+
+EVP_MD-SHA3 - The SHA3 EVP_MD implementations
+
+=head1 DESCRIPTION
+
+Support for computing SHA3 digests through the B<EVP_MD> API.
+
+=head2 Identities
+
+This implementation is available with the FIPS provider as well as the
+default provider, and includes the following varieties:
+
+=over 4
+
+=item "SHA3-224"
+
+=item "SHA3-256"
+
+=item "SHA3-384"
+
+=item "SHA3-512"
+
+=back
+
+=head2 Gettable Parameters
+
+This implementation supports the common gettable parameters described
+in L<EVP_MD-common(7)>.
+
+=head1 SEE ALSO
+
+L<provider-digest(7)>, L<OSSL_PROVIDER-FIPS(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MD-SHAKE.pod b/doc/man7/EVP_MD-SHAKE.pod
new file mode 100644
index 000000000000..8a31cd53a8ba
--- /dev/null
+++ b/doc/man7/EVP_MD-SHAKE.pod
@@ -0,0 +1,83 @@
+=pod
+
+=head1 NAME
+
+EVP_MD-SHAKE, EVP_MD-KECCAK-KMAC
+- The SHAKE / KECCAK family EVP_MD implementations
+
+=head1 DESCRIPTION
+
+Support for computing SHAKE or KECCAK-KMAC digests through the
+B<EVP_MD> API.
+
+KECCAK-KMAC is a special digest that's used by the KMAC EVP_MAC
+implementation (see L<EVP_MAC-KMAC(7)>).
+
+=head2 Identities
+
+This implementation is available in the FIPS provider as well as the default
+provider, and includes the following varieties:
+
+=over 4
+
+=item KECCAK-KMAC-128
+
+Known names are "KECCAK-KMAC-128" and "KECCAK-KMAC128"
+This is used by L<EVP_MAC-KMAC128(7)>
+
+=item KECCAK-KMAC-256
+
+Known names are "KECCAK-KMAC-256" and "KECCAK-KMAC256"
+This is used by L<EVP_MAC-KMAC256(7)>
+
+=item SHAKE-128
+
+Known names are "SHAKE-128" and "SHAKE128"
+
+=item SHAKE-256
+
+Known names are "SHAKE-256" and "SHAKE256"
+
+=back
+
+=head2 Gettable Parameters
+
+This implementation supports the common gettable parameters described
+in L<EVP_MD-common(7)>.
+
+=head2 Settable Context Parameters
+
+These implementations support the following L<OSSL_PARAM(3)> entries,
+settable for an B<EVP_MD_CTX> with L<EVP_MD_CTX_set_params(3)>:
+
+=over 4
+
+=item "xoflen" (B<OSSL_DIGEST_PARAM_XOFLEN>) <unsigned integer>
+
+Sets the digest length for extendable output functions.
+The length of the "xoflen" parameter should not exceed that of a B<size_t>.
+
+For backwards compatibility reasons the default xoflen length for SHAKE-128 is
+16 (bytes) which results in a security strength of only 64 bits. To ensure the
+maximum security strength of 128 bits, the xoflen should be set to at least 32.
+
+For backwards compatibility reasons the default xoflen length for SHAKE-256 is
+32 (bytes) which results in a security strength of only 128 bits. To ensure the
+maximum security strength of 256 bits, the xoflen should be set to at least 64.
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_MD_CTX_set_params(3)>, L<provider-digest(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MD-SM3.pod b/doc/man7/EVP_MD-SM3.pod
new file mode 100644
index 000000000000..355c52ec847b
--- /dev/null
+++ b/doc/man7/EVP_MD-SM3.pod
@@ -0,0 +1,34 @@
+=pod
+
+=head1 NAME
+
+EVP_MD-SM3 - The SM3 EVP_MD implementations
+
+=head1 DESCRIPTION
+
+Support for computing SM3 digests through the B<EVP_MD> API.
+
+=head2 Identity
+
+This implementation is only available with the default provider, and is
+identified with the name "SM3".
+
+=head2 Gettable Parameters
+
+This implementation supports the common gettable parameters described
+in L<EVP_MD-common(7)>.
+
+=head1 SEE ALSO
+
+L<provider-digest(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MD-WHIRLPOOL.pod b/doc/man7/EVP_MD-WHIRLPOOL.pod
new file mode 100644
index 000000000000..2252ab2dba78
--- /dev/null
+++ b/doc/man7/EVP_MD-WHIRLPOOL.pod
@@ -0,0 +1,34 @@
+=pod
+
+=head1 NAME
+
+EVP_MD-WHIRLPOOL - The WHIRLPOOL EVP_MD implementation
+
+=head1 DESCRIPTION
+
+Support for computing WHIRLPOOL digests through the B<EVP_MD> API.
+
+=head2 Identity
+
+This implementation is only available with the legacy provider, and is
+identified with the name "WHIRLPOOL".
+
+=head2 Gettable Parameters
+
+This implementation supports the common gettable parameters described
+in L<EVP_MD-common(7)>.
+
+=head1 SEE ALSO
+
+L<provider-digest(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_MD-common.pod b/doc/man7/EVP_MD-common.pod
new file mode 100644
index 000000000000..afbb91ec07b2
--- /dev/null
+++ b/doc/man7/EVP_MD-common.pod
@@ -0,0 +1,62 @@
+=pod
+
+=head1 NAME
+
+EVP_MD-common - The OpenSSL EVP_MD implementations, common things
+
+=head1 DESCRIPTION
+
+All the OpenSSL EVP_MD implementations understand the following
+L<OSSL_PARAM(3)> entries that are
+gettable with L<EVP_MD_get_params(3)>, as well as these:
+
+=over 4
+
+=item "blocksize" (B<OSSL_DIGEST_PARAM_BLOCK_SIZE>) <unsigned integer>
+
+The digest block size.
+The length of the "blocksize" parameter should not exceed that of a
+B<size_t>.
+
+This value can also be retrieved with L<EVP_MD_get_block_size(3)>.
+
+=item "size" (B<OSSL_DIGEST_PARAM_SIZE>) <unsigned integer>
+
+The digest output size.
+The length of the "size" parameter should not exceed that of a B<size_t>.
+
+This value can also be retrieved with L<EVP_MD_get_size(3)>.
+
+=item "flags" (B<OSSL_DIGEST_PARAM_FLAGS>) <unsigned integer>
+
+Diverse flags that describe exceptional behaviour for the digest.
+These flags are described in L<EVP_MD_meth_set_flags(3)/DESCRIPTION>.
+
+The length of the "flags" parameter should equal that of an
+B<unsigned long int>.
+
+=begin comment
+
+The description of these flags should probably be moved. Also,
+EVP_MD_FLAG_FIPS isn't relevant any more.
+
+=end comment
+
+This value can also be retrieved with L<EVP_MD_get_flags(3)>.
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_MD_get_params(3)>, L<provider-digest(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_PKEY-DH.pod b/doc/man7/EVP_PKEY-DH.pod
new file mode 100644
index 000000000000..1dfc9c734544
--- /dev/null
+++ b/doc/man7/EVP_PKEY-DH.pod
@@ -0,0 +1,337 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY-DH, EVP_PKEY-DHX, EVP_KEYMGMT-DH, EVP_KEYMGMT-DHX
+- EVP_PKEY DH and DHX keytype and algorithm support
+
+=head1 DESCRIPTION
+
+For B<DH> FFC key agreement, two classes of domain parameters can be used:
+"safe" domain parameters that are associated with approved named safe-prime
+groups, and a class of "FIPS186-type" domain parameters. FIPS186-type domain
+parameters should only be used for backward compatibility with existing
+applications that cannot be upgraded to use the approved safe-prime groups.
+
+See L<EVP_PKEY-FFC(7)> for more information about FFC keys.
+
+The B<DH> key type uses PKCS#3 format which saves I<p> and I<g>, but not the
+I<q> value.
+The B<DHX> key type uses X9.42 format which saves the value of I<q> and this
+must be used for FIPS186-4. If key validation is required, users should be aware
+of the nuances associated with FIPS186-4 style parameters as discussed in
+L</DH key validation>.
+
+=head2 DH and DHX domain parameters
+
+In addition to the common FCC parameters that all FFC keytypes should support
+(see L<EVP_PKEY-FFC(7)/FFC parameters>) the B<DHX> and B<DH> keytype
+implementations support the following:
+
+=over 4
+
+=item "group" (B<OSSL_PKEY_PARAM_GROUP_NAME>) <UTF8 string>
+
+Sets or gets a string that associates a B<DH> or B<DHX> named safe prime group
+with known values for I<p>, I<q> and I<g>.
+
+The following values can be used by the OpenSSL's default and FIPS providers:
+"ffdhe2048", "ffdhe3072", "ffdhe4096", "ffdhe6144", "ffdhe8192",
+"modp_2048", "modp_3072", "modp_4096", "modp_6144", "modp_8192".
+
+The following additional values can also be used by OpenSSL's default provider:
+"modp_1536", "dh_1024_160", "dh_2048_224", "dh_2048_256".
+
+DH/DHX named groups can be easily validated since the parameters are well known.
+For protocols that only transfer I<p> and I<g> the value of I<q> can also be
+retrieved.
+
+=back
+
+=head2 DH and DHX additional parameters
+
+=over 4
+
+=item "encoded-pub-key" (B<OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY>) <octet string>
+
+Used for getting and setting the encoding of the DH public key used in a key
+exchange message for the TLS protocol.
+See EVP_PKEY_set1_encoded_public_key() and EVP_PKEY_get1_encoded_public_key().
+
+=back
+
+=head2 DH additional domain parameters
+
+=over 4
+
+=item "safeprime-generator" (B<OSSL_PKEY_PARAM_DH_GENERATOR>) <integer>
+
+Used for DH generation of safe primes using the old safe prime generator code.
+The default value is 2.
+It is recommended to use a named safe prime group instead, if domain parameter
+validation is required.
+
+Randomly generated safe primes are not allowed by FIPS, so setting this value
+for the OpenSSL FIPS provider will instead choose a named safe prime group
+based on the size of I<p>.
+
+=back
+
+=head2 DH and DHX domain parameter / key generation parameters
+
+In addition to the common FFC key generation parameters that all FFC key types
+should support (see L<EVP_PKEY-FFC(7)/FFC key generation parameters>) the
+B<DH> and B<DHX> keytype implementation supports the following:
+
+=over 4
+
+=item "type" (B<OSSL_PKEY_PARAM_FFC_TYPE>) <UTF8 string>
+
+Sets the type of parameter generation. For B<DH> valid values are:
+
+=over 4
+
+=item "fips186_4"
+
+=item "default"
+
+=item "fips186_2"
+
+These are described in L<EVP_PKEY-FFC(7)/FFC key generation parameters>
+
+=item "group"
+
+This specifies that a named safe prime name will be chosen using the "pbits"
+type.
+
+=item "generator"
+
+A safe prime generator. See the "safeprime-generator" type above.
+This is only valid for B<DH> keys.
+
+=back
+
+=item "pbits" (B<OSSL_PKEY_PARAM_FFC_PBITS>) <unsigned integer>
+
+Sets the size (in bits) of the prime 'p'.
+
+For "fips186_4" this must be 2048.
+For "fips186_2" this must be 1024.
+For "group" this can be any one of 2048, 3072, 4096, 6144 or 8192.
+
+=item "priv_len" (B<OSSL_PKEY_PARAM_DH_PRIV_LEN>) <integer>
+
+An optional value to set the maximum length of the generated private key.
+The default value used if this is not set is the maximum value of
+BN_num_bits(I<q>)). The minimum value that this can be set to is 2 * s.
+Where s is the security strength of the key which has values of
+112, 128, 152, 176 and 200 for key sizes of 2048, 3072, 4096, 6144 and 8192.
+
+=back
+
+=head2 DH key validation
+
+For B<DHX> that is not a named group the FIPS186-4 standard specifies that the
+values used for FFC parameter generation are also required for parameter
+validation. This means that optional FFC domain parameter values for
+I<seed>, I<pcounter> and I<gindex> or I<hindex> may need to be stored for
+validation purposes.
+For B<DHX> the I<seed> and I<pcounter> can be stored in ASN1 data
+(but the I<gindex> or I<hindex> cannot be stored). It is recommended to use a
+named safe prime group instead.
+
+For DH keys, L<EVP_PKEY_param_check(3)> behaves in the following way:
+The OpenSSL FIPS provider tests if the parameters are either an approved safe
+prime group OR that the FFC parameters conform to FIPS186-4 as defined in
+SP800-56Ar3 I<Assurances of Domain-Parameter Validity>.
+The OpenSSL default provider uses simpler checks that allows there to be no I<q>
+value for backwards compatibility.
+
+For DH keys, L<EVP_PKEY_param_check_quick(3)> is equivalent to
+L<EVP_PKEY_param_check(3)>.
+
+For DH keys, L<EVP_PKEY_public_check(3)> conforms to
+SP800-56Ar3 I<FFC Full Public-Key Validation>.
+
+For DH keys, L<EVP_PKEY_public_check_quick(3)> conforms to
+SP800-56Ar3 I<FFC Partial Public-Key Validation> when the
+DH key is an approved named safe prime group, otherwise it is the same as
+L<EVP_PKEY_public_check(3)>.
+
+For DH Keys, L<EVP_PKEY_private_check(3)> tests that the private key is in the
+correct range according to SP800-56Ar3. The OpenSSL FIPS provider requires the
+value of I<q> to be set (note that this is set for named safe prime groups).
+For backwards compatibility the OpenSSL default provider only requires I<p> to
+be set.
+
+For DH keys, L<EVP_PKEY_pairwise_check(3)> conforms to
+SP800-56Ar3 I<Owner Assurance of Pair-wise Consistency>.
+
+=head1 EXAMPLES
+
+An B<EVP_PKEY> context can be obtained by calling:
+
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);
+
+A B<DH> key can be generated with a named safe prime group by calling:
+
+ int priv_len = 2 * 112;
+ OSSL_PARAM params[3];
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);
+
+ params[0] = OSSL_PARAM_construct_utf8_string("group", "ffdhe2048", 0);
+ /* "priv_len" is optional */
+ params[1] = OSSL_PARAM_construct_int("priv_len", &priv_len);
+ params[2] = OSSL_PARAM_construct_end();
+
+ EVP_PKEY_keygen_init(pctx);
+ EVP_PKEY_CTX_set_params(pctx, params);
+ EVP_PKEY_generate(pctx, &pkey);
+ ...
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(pctx);
+
+B<DHX> domain parameters can be generated according to B<FIPS186-4> by calling:
+
+ int gindex = 2;
+ unsigned int pbits = 2048;
+ unsigned int qbits = 256;
+ OSSL_PARAM params[6];
+ EVP_PKEY *param_key = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+
+ pctx = EVP_PKEY_CTX_new_from_name(NULL, "DHX", NULL);
+ EVP_PKEY_paramgen_init(pctx);
+
+ params[0] = OSSL_PARAM_construct_uint("pbits", &pbits);
+ params[1] = OSSL_PARAM_construct_uint("qbits", &qbits);
+ params[2] = OSSL_PARAM_construct_int("gindex", &gindex);
+ params[3] = OSSL_PARAM_construct_utf8_string("type", "fips186_4", 0);
+ params[4] = OSSL_PARAM_construct_utf8_string("digest", "SHA256", 0);
+ params[5] = OSSL_PARAM_construct_end();
+ EVP_PKEY_CTX_set_params(pctx, params);
+
+ EVP_PKEY_generate(pctx, &param_key);
+
+ EVP_PKEY_print_params(bio_out, param_key, 0, NULL);
+ ...
+ EVP_PKEY_free(param_key);
+ EVP_PKEY_CTX_free(pctx);
+
+A B<DH> key can be generated using domain parameters by calling:
+
+ EVP_PKEY *key = NULL;
+ EVP_PKEY_CTX *gctx = EVP_PKEY_CTX_new_from_pkey(NULL, param_key, NULL);
+
+ EVP_PKEY_keygen_init(gctx);
+ EVP_PKEY_generate(gctx, &key);
+ EVP_PKEY_print_private(bio_out, key, 0, NULL);
+ ...
+ EVP_PKEY_free(key);
+ EVP_PKEY_CTX_free(gctx);
+
+To validate B<FIPS186-4> B<DHX> domain parameters decoded from B<PEM> or
+B<DER> data, additional values used during generation may be required to
+be set into the key.
+
+EVP_PKEY_todata(), OSSL_PARAM_merge(), and EVP_PKEY_fromdata() are useful
+to add these parameters to the original key or domain parameters before
+the actual validation. In production code the return values should be checked.
+
+ EVP_PKEY *received_domp = ...; /* parameters received and decoded */
+ unsigned char *seed = ...; /* and additional parameters received */
+ size_t seedlen = ...; /* by other means, required */
+ int gindex = ...; /* for the validation */
+ int pcounter = ...;
+ int hindex = ...;
+ OSSL_PARAM extra_params[4];
+ OSSL_PARAM *domain_params = NULL;
+ OSSL_PARAM *merged_params = NULL;
+ EVP_PKEY_CTX *ctx = NULL, *validate_ctx = NULL;
+ EVP_PKEY *complete_domp = NULL;
+
+ EVP_PKEY_todata(received_domp, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ &domain_params);
+ extra_params[0] = OSSL_PARAM_construct_octet_string("seed", seed, seedlen);
+ /*
+ * NOTE: For unverifiable g use "hindex" instead of "gindex"
+ * extra_params[1] = OSSL_PARAM_construct_int("hindex", &hindex);
+ */
+ extra_params[1] = OSSL_PARAM_construct_int("gindex", &gindex);
+ extra_params[2] = OSSL_PARAM_construct_int("pcounter", &pcounter);
+ extra_params[3] = OSSL_PARAM_construct_end();
+ merged_params = OSSL_PARAM_merge(domain_params, extra_params);
+
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, "DHX", NULL);
+ EVP_PKEY_fromdata_init(ctx);
+ EVP_PKEY_fromdata(ctx, &complete_domp, OSSL_KEYMGMT_SELECT_ALL,
+ merged_params);
+
+ validate_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, complete_domp, NULL);
+ if (EVP_PKEY_param_check(validate_ctx) > 0)
+ /* validation_passed(); */
+ else
+ /* validation_failed(); */
+
+ OSSL_PARAM_free(domain_params);
+ OSSL_PARAM_free(merged_params);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_CTX_free(validate_ctx);
+ EVP_PKEY_free(complete_domp);
+
+=head1 CONFORMING TO
+
+=over 4
+
+=item RFC 7919 (TLS ffdhe named safe prime groups)
+
+=item RFC 3526 (IKE modp named safe prime groups)
+
+=item RFC 5114 (Additional DH named groups for dh_1024_160", "dh_2048_224"
+ and "dh_2048_256").
+
+=back
+
+The following sections of SP800-56Ar3:
+
+=over 4
+
+=item 5.5.1.1 FFC Domain Parameter Selection/Generation
+
+=item Appendix D: FFC Safe-prime Groups
+
+=back
+
+The following sections of FIPS186-4:
+
+=over 4
+
+=item A.1.1.2 Generation of Probable Primes p and q Using an Approved Hash Function.
+
+=item A.2.3 Generation of canonical generator g.
+
+=item A.2.1 Unverifiable Generation of the Generator g.
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_PKEY-FFC(7)>,
+L<EVP_KEYEXCH-DH(7)>
+L<EVP_PKEY(3)>,
+L<provider-keymgmt(7)>,
+L<EVP_KEYMGMT(3)>,
+L<OSSL_PROVIDER-default(7)>,
+L<OSSL_PROVIDER-FIPS(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_PKEY-DSA.pod b/doc/man7/EVP_PKEY-DSA.pod
new file mode 100644
index 000000000000..cdafc0edad5c
--- /dev/null
+++ b/doc/man7/EVP_PKEY-DSA.pod
@@ -0,0 +1,123 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY-DSA, EVP_KEYMGMT-DSA - EVP_PKEY DSA keytype and algorithm support
+
+=head1 DESCRIPTION
+
+For B<DSA> the FIPS186-4 standard specifies that the values used for FFC
+parameter generation are also required for parameter validation.
+This means that optional FFC domain parameter values for I<seed>, I<pcounter>
+and I<gindex> may need to be stored for validation purposes. For B<DSA> these
+fields are not stored in the ASN1 data so they need to be stored externally if
+validation is required.
+
+=head2 DSA parameters
+
+The B<DSA> key type supports the FFC parameters (see
+L<EVP_PKEY-FFC(7)/FFC parameters>).
+
+=head2 DSA key generation parameters
+
+The B<DSA> key type supports the FFC key generation parameters (see
+L<EVP_PKEY-FFC(7)/FFC key generation parameters>
+
+The following restrictions apply to the "pbits" field:
+
+For "fips186_4" this must be either 2048 or 3072.
+For "fips186_2" this must be 1024.
+For "group" this can be any one of 2048, 3072, 4096, 6144 or 8192.
+
+=head2 DSA key validation
+
+For DSA keys, L<EVP_PKEY_param_check(3)> behaves in the following way:
+The OpenSSL FIPS provider conforms to the rules within the FIPS186-4
+standard for FFC parameter validation. For backwards compatibility the OpenSSL
+default provider uses a much simpler check (see below) for parameter validation,
+unless the seed parameter is set.
+
+For DSA keys, L<EVP_PKEY_param_check_quick(3)> behaves in the following way:
+A simple check of L and N and partial g is performed. The default provider
+also supports validation of legacy "fips186_2" keys.
+
+For DSA keys, L<EVP_PKEY_public_check(3)>, L<EVP_PKEY_private_check(3)> and
+L<EVP_PKEY_pairwise_check(3)> the OpenSSL default and FIPS providers conform to
+the rules within SP800-56Ar3 for public, private and pairwise tests respectively.
+
+=head1 EXAMPLES
+
+An B<EVP_PKEY> context can be obtained by calling:
+
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL);
+
+The B<DSA> domain parameters can be generated by calling:
+
+ unsigned int pbits = 2048;
+ unsigned int qbits = 256;
+ int gindex = 1;
+ OSSL_PARAM params[5];
+ EVP_PKEY *param_key = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+
+ pctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL);
+ EVP_PKEY_paramgen_init(pctx);
+
+ params[0] = OSSL_PARAM_construct_uint("pbits", &pbits);
+ params[1] = OSSL_PARAM_construct_uint("qbits", &qbits);
+ params[2] = OSSL_PARAM_construct_int("gindex", &gindex);
+ params[3] = OSSL_PARAM_construct_utf8_string("digest", "SHA384", 0);
+ params[4] = OSSL_PARAM_construct_end();
+ EVP_PKEY_CTX_set_params(pctx, params);
+
+ EVP_PKEY_generate(pctx, &param_key);
+ EVP_PKEY_CTX_free(pctx);
+
+ EVP_PKEY_print_params(bio_out, param_key, 0, NULL);
+
+A B<DSA> key can be generated using domain parameters by calling:
+
+ EVP_PKEY *key = NULL;
+ EVP_PKEY_CTX *gctx = NULL;
+
+ gctx = EVP_PKEY_CTX_new_from_pkey(NULL, param_key, NULL);
+ EVP_PKEY_keygen_init(gctx);
+ EVP_PKEY_generate(gctx, &key);
+ EVP_PKEY_CTX_free(gctx);
+ EVP_PKEY_print_private(bio_out, key, 0, NULL);
+
+
+=head1 CONFORMING TO
+
+The following sections of FIPS186-4:
+
+=over 4
+
+=item A.1.1.2 Generation of Probable Primes p and q Using an Approved Hash Function.
+
+=item A.2.3 Generation of canonical generator g.
+
+=item A.2.1 Unverifiable Generation of the Generator g.
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_PKEY-FFC(7)>,
+L<EVP_SIGNATURE-DSA(7)>
+L<EVP_PKEY(3)>,
+L<provider-keymgmt(7)>,
+L<EVP_KEYMGMT(3)>,
+L<OSSL_PROVIDER-default(7)>,
+L<OSSL_PROVIDER-FIPS(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_PKEY-EC.pod b/doc/man7/EVP_PKEY-EC.pod
new file mode 100644
index 000000000000..668a024014b4
--- /dev/null
+++ b/doc/man7/EVP_PKEY-EC.pod
@@ -0,0 +1,282 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY-EC,
+EVP_KEYMGMT-EC
+- EVP_PKEY EC keytype and algorithm support
+
+=head1 DESCRIPTION
+
+The B<EC> keytype is implemented in OpenSSL's default provider.
+
+=head2 Common EC parameters
+
+The normal way of specifying domain parameters for an EC curve is via the
+curve name "group". For curves with no curve name, explicit parameters can be
+used that specify "field-type", "p", "a", "b", "generator" and "order".
+Explicit parameters are supported for backwards compability reasons, but they
+are not compliant with multiple standards (including RFC5915) which only allow
+named curves.
+
+The following KeyGen/Gettable/Import/Export types are available for the
+built-in EC algorithm:
+
+=over 4
+
+=item "group" (B<OSSL_PKEY_PARAM_GROUP_NAME>) <UTF8 string>
+
+The curve name.
+
+=item "field-type" (B<OSSL_PKEY_PARAM_EC_FIELD_TYPE>) <UTF8 string>
+
+The value should be either "prime-field" or "characteristic-two-field",
+which correspond to prime field Fp and binary field F2^m.
+
+=item "p" (B<OSSL_PKEY_PARAM_EC_P>) <unsigned integer>
+
+For a curve over Fp I<p> is the prime for the field. For a curve over F2^m I<p>
+represents the irreducible polynomial - each bit represents a term in the
+polynomial. Therefore, there will either be three or five bits set dependent on
+whether the polynomial is a trinomial or a pentanomial.
+
+=item "a" (B<OSSL_PKEY_PARAM_EC_A>) <unsigned integer>
+
+=item "b" (B<OSSL_PKEY_PARAM_EC_B>) <unsigned integer>
+
+=item "seed" (B<OSSL_PKEY_PARAM_EC_SEED>) <octet string>
+
+I<a> and I<b> represents the coefficients of the curve
+For Fp: y^2 mod p = x^3 +ax + b mod p OR
+For F2^m: y^2 + xy = x^3 + ax^2 + b
+
+I<seed> is an optional value that is for information purposes only.
+It represents the random number seed used to generate the coefficient I<b> from a
+random number.
+
+=item "generator" (B<OSSL_PKEY_PARAM_EC_GENERATOR>) <octet string>
+
+=item "order" (B<OSSL_PKEY_PARAM_EC_ORDER>) <unsigned integer>
+
+=item "cofactor" (B<OSSL_PKEY_PARAM_EC_COFACTOR>) <unsigned integer>
+
+The I<generator> is a well defined point on the curve chosen for cryptographic
+operations. The encoding conforms with Sec. 2.3.3 of the SECG SEC 1 ("Elliptic Curve
+Cryptography") standard. See EC_POINT_oct2point().
+Integers used for point multiplications will be between 0 and
+I<order> - 1.
+I<cofactor> is an optional value.
+I<order> multiplied by the I<cofactor> gives the number of points on the curve.
+
+=item "decoded-from-explicit" (B<OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS>) <integer>
+
+Gets a flag indicating wether the key or parameters were decoded from explicit
+curve parameters. Set to 1 if so or 0 if a named curve was used.
+
+=item "use-cofactor-flag" (B<OSSL_PKEY_PARAM_USE_COFACTOR_ECDH>) <integer>
+
+Enable Cofactor DH (ECC CDH) if this value is 1, otherwise it uses normal EC DH
+if the value is zero. The cofactor variant multiplies the shared secret by the
+EC curve's cofactor (note for some curves the cofactor is 1).
+
+See also L<EVP_KEYEXCH-ECDH(7)> for the related
+B<OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE> parameter that can be set on a
+per-operation basis.
+
+=item "encoding" (B<OSSL_PKEY_PARAM_EC_ENCODING>) <UTF8 string>
+
+Set the format used for serializing the EC group parameters.
+Valid values are "explicit" or "named_curve". The default value is "named_curve".
+
+=item "point-format" (B<OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT>) <UTF8 string>
+
+Sets or gets the point_conversion_form for the I<key>. For a description of
+point_conversion_forms please see L<EC_POINT_new(3)>. Valid values are
+"uncompressed" or "compressed". The default value is "uncompressed".
+
+=item "group-check" (B<OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE>) <UTF8 string>
+
+Sets or Gets the type of group check done when EVP_PKEY_param_check() is called.
+Valid values are "default", "named" and "named-nist".
+The "named" type checks that the domain parameters match the inbuilt curve parameters,
+"named-nist" is similiar but also checks that the named curve is a nist curve.
+The "default" type does domain parameter validation for the OpenSSL default provider,
+but is equivalent to "named-nist" for the OpenSSL FIPS provider.
+
+=item "include-public" (B<OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC>) <integer>
+
+Setting this value to 0 indicates that the public key should not be included when
+encoding the private key. The default value of 1 will include the public key.
+
+=item "pub" (B<OSSL_PKEY_PARAM_PUB_KEY>) <octet string>
+
+The public key value in encoded EC point format conforming to Sec. 2.3.3 and
+2.3.4 of the SECG SEC 1 ("Elliptic Curve Cryptography") standard.
+This parameter is used when importing or exporting the public key value with the
+EVP_PKEY_fromdata() and EVP_PKEY_todata() functions.
+
+Note, in particular, that the choice of point compression format used for
+encoding the exported value via EVP_PKEY_todata() depends on the underlying
+provider implementation.
+Before OpenSSL 3.0.8, the implementation of providers included with OpenSSL always
+opted for an encoding in compressed format, unconditionally.
+Since OpenSSL 3.0.8, the implementation has been changed to honor the
+B<OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT> parameter, if set, or to default
+to uncompressed format.
+
+=item "priv" (B<OSSL_PKEY_PARAM_PRIV_KEY>) <unsigned integer>
+
+The private key value.
+
+=item "encoded-pub-key" (B<OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY>) <octet string>
+
+Used for getting and setting the encoding of an EC public key. The public key
+is expected to be a point conforming to Sec. 2.3.4 of the SECG SEC 1 ("Elliptic
+Curve Cryptography") standard.
+
+=item "qx" (B<OSSL_PKEY_PARAM_EC_PUB_X>) <unsigned integer>
+
+Used for getting the EC public key X component.
+
+=item "qy" (B<OSSL_PKEY_PARAM_EC_PUB_Y>) <unsigned integer>
+
+Used for getting the EC public key Y component.
+
+=item (B<OSSL_PKEY_PARAM_DEFAULT_DIGEST>) <UTF8 string>
+
+Getter that returns the default digest name.
+(Currently returns "SHA256" as of OpenSSL 3.0).
+
+=back
+
+The following Gettable types are also available for the built-in EC algorithm:
+
+=over 4
+
+=item "basis-type" (B<OSSL_PKEY_PARAM_EC_CHAR2_TYPE>) <UTF8 string>
+
+Supports the values "tpBasis" for a trinomial or "ppBasis" for a pentanomial.
+This field is only used for a binary field F2^m.
+
+=item "m" (B<OSSL_PKEY_PARAM_EC_CHAR2_M>) <integer>
+
+=item "tp" (B<OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS>) <integer>
+
+=item "k1" (B<OSSL_PKEY_PARAM_EC_CHAR2_PP_K1>) <integer>
+
+=item "k2" (B<OSSL_PKEY_PARAM_EC_CHAR2_PP_K2>) <integer>
+
+=item "k3" (B<OSSL_PKEY_PARAM_EC_CHAR2_PP_K3>) <integer>
+
+These fields are only used for a binary field F2^m.
+I<m> is the degree of the binary field.
+
+I<tp> is the middle bit of a trinomial so its value must be in the
+range m > tp > 0.
+
+I<k1>, I<k2> and I<k3> are used to get the middle bits of a pentanomial such
+that m > k3 > k2 > k1 > 0
+
+=back
+
+=head2 EC key validation
+
+For EC keys, L<EVP_PKEY_param_check(3)> behaves in the following way:
+For the OpenSSL default provider it uses either
+L<EC_GROUP_check(3)> or L<EC_GROUP_check_named_curve(3)> depending on the flag
+EC_FLAG_CHECK_NAMED_GROUP.
+The OpenSSL FIPS provider uses L<EC_GROUP_check_named_curve(3)> in order to
+conform to SP800-56Ar3 I<Assurances of Domain-Parameter Validity>.
+
+For EC keys, L<EVP_PKEY_param_check_quick(3)> is equivalent to
+L<EVP_PKEY_param_check(3)>.
+
+For EC keys, L<EVP_PKEY_public_check(3)> and L<EVP_PKEY_public_check_quick(3)>
+conform to SP800-56Ar3 I<ECC Full Public-Key Validation> and
+I<ECC Partial Public-Key Validation> respectively.
+
+For EC Keys, L<EVP_PKEY_private_check(3)> and L<EVP_PKEY_pairwise_check(3)>
+conform to SP800-56Ar3 I<Private key validity> and
+I<Owner Assurance of Pair-wise Consistency> respectively.
+
+=head1 EXAMPLES
+
+An B<EVP_PKEY> context can be obtained by calling:
+
+ EVP_PKEY_CTX *pctx =
+ EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
+
+An B<EVP_PKEY> ECDSA or ECDH key can be generated with a "P-256" named group by
+calling:
+
+ pkey = EVP_EC_gen("P-256");
+
+or like this:
+
+ EVP_PKEY *key = NULL;
+ OSSL_PARAM params[2];
+ EVP_PKEY_CTX *gctx =
+ EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
+
+ EVP_PKEY_keygen_init(gctx);
+
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
+ "P-256", 0);
+ params[1] = OSSL_PARAM_construct_end();
+ EVP_PKEY_CTX_set_params(gctx, params);
+
+ EVP_PKEY_generate(gctx, &key);
+
+ EVP_PKEY_print_private(bio_out, key, 0, NULL);
+ ...
+ EVP_PKEY_free(key);
+ EVP_PKEY_CTX_free(gctx);
+
+An B<EVP_PKEY> EC CDH (Cofactor Diffie-Hellman) key can be generated with a
+"K-571" named group by calling:
+
+ int use_cdh = 1;
+ EVP_PKEY *key = NULL;
+ OSSL_PARAM params[3];
+ EVP_PKEY_CTX *gctx =
+ EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
+
+ EVP_PKEY_keygen_init(gctx);
+
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
+ "K-571", 0);
+ /*
+ * This curve has a cofactor that is not 1 - so setting CDH mode changes
+ * the behaviour. For many curves the cofactor is 1 - so setting this has
+ * no effect.
+ */
+ params[1] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
+ &use_cdh);
+ params[2] = OSSL_PARAM_construct_end();
+ EVP_PKEY_CTX_set_params(gctx, params);
+
+ EVP_PKEY_generate(gctx, &key);
+ EVP_PKEY_print_private(bio_out, key, 0, NULL);
+ ...
+ EVP_PKEY_free(key);
+ EVP_PKEY_CTX_free(gctx);
+
+=head1 SEE ALSO
+
+L<EVP_EC_gen(3)>,
+L<EVP_KEYMGMT(3)>,
+L<EVP_PKEY(3)>,
+L<provider-keymgmt(7)>,
+L<EVP_SIGNATURE-ECDSA(7)>,
+L<EVP_KEYEXCH-ECDH(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_PKEY-FFC.pod b/doc/man7/EVP_PKEY-FFC.pod
new file mode 100644
index 000000000000..0b96bc24a614
--- /dev/null
+++ b/doc/man7/EVP_PKEY-FFC.pod
@@ -0,0 +1,232 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY-FFC - EVP_PKEY DSA and DH/DHX shared FFC parameters.
+
+=head1 DESCRIPTION
+
+Finite field cryptography (FFC) is a method of implementing discrete logarithm
+cryptography using finite field mathematics. DSA is an example of FFC and
+Diffie-Hellman key establishment algorithms specified in SP800-56A can also be
+implemented as FFC.
+
+The B<DSA>, B<DH> and B<DHX> keytypes are implemented in OpenSSL's default and
+FIPS providers.
+The implementations support the basic DSA, DH and DHX keys, containing the public
+and private keys I<pub> and I<priv> as well as the three main domain parameters
+I<p>, I<q> and I<g>.
+
+For B<DSA> (and B<DH> that is not a named group) the FIPS186-4 standard
+specifies that the values used for FFC parameter generation are also required
+for parameter validation.
+This means that optional FFC domain parameter values for I<seed>, I<pcounter>
+and I<gindex> may need to be stored for validation purposes.
+For B<DH> the I<seed> and I<pcounter> can be stored in ASN1 data
+(but the I<gindex> is not). For B<DSA> however, these fields are not stored in
+the ASN1 data so they need to be stored externally if validation is required.
+
+The B<DH> key type uses PKCS#3 format which saves p and g, but not the 'q' value.
+The B<DHX> key type uses X9.42 format which saves the value of 'q' and this
+must be used for FIPS186-4.
+
+=head2 FFC parameters
+
+In addition to the common parameters that all keytypes should support (see
+L<provider-keymgmt(7)/Common parameters>), the B<DSA>, B<DH> and B<DHX> keytype
+implementations support the following.
+
+=over 4
+
+=item "pub" (B<OSSL_PKEY_PARAM_PUB_KEY>) <unsigned integer>
+
+The public key value.
+
+=item "priv" (B<OSSL_PKEY_PARAM_PRIV_KEY>) <unsigned integer>
+
+The private key value.
+
+=back
+
+=head2 FFC DSA, DH and DHX domain parameters
+
+=over 4
+
+=item "p" (B<OSSL_PKEY_PARAM_FFC_P>) <unsigned integer>
+
+A DSA or Diffie-Hellman prime "p" value.
+
+=item "g" (B<OSSL_PKEY_PARAM_FFC_G>) <unsigned integer>
+
+A DSA or Diffie-Hellman generator "g" value.
+
+=back
+
+=head2 FFC DSA and DHX domain parameters
+
+=over 4
+
+=item "q" (B<OSSL_PKEY_PARAM_FFC_Q>) <unsigned integer>
+
+A DSA or Diffie-Hellman prime "q" value.
+
+=item "seed" (B<OSSL_PKEY_PARAM_FFC_SEED>) <octet string>
+
+An optional domain parameter I<seed> value used during generation and validation
+of I<p>, I<q> and canonical I<g>.
+For validation this needs to set the I<seed> that was produced during generation.
+
+=item "gindex" (B<OSSL_PKEY_PARAM_FFC_GINDEX>) <integer>
+
+Sets the index to use for canonical generation and verification of the generator
+I<g>.
+Set this to a positive value from 0..FF to use this mode. This I<gindex> can
+then be reused during key validation to verify the value of I<g>. If this value
+is not set or is -1 then unverifiable generation of the generator I<g> will be
+used.
+
+=item "pcounter" (B<OSSL_PKEY_PARAM_FFC_PCOUNTER>) <integer>
+
+An optional domain parameter I<counter> value that is output during generation
+of I<p>. This value must be saved if domain parameter validation is required.
+
+=item "hindex" (B<OSSL_PKEY_PARAM_FFC_H>) <integer>
+
+For unverifiable generation of the generator I<g> this value is output during
+generation of I<g>. Its value is the first integer larger than one that
+satisfies g = h^j mod p (where g != 1 and "j" is the cofactor).
+
+=item "j" (B<OSSL_PKEY_PARAM_FFC_COFACTOR>) <unsigned integer>
+
+An optional informational cofactor parameter that should equal to (p - 1) / q.
+
+=item "validate-pq" (B<OSSL_PKEY_PARAM_FFC_VALIDATE_PQ>) <unsigned integer>
+
+=item "validate-g" (B<OSSL_PKEY_PARAM_FFC_VALIDATE_G>) <unsigned integer>
+
+These boolean values are used during FIPS186-4 or FIPS186-2 key validation checks
+(See L<EVP_PKEY_param_check(3)>) to select validation options. By default
+I<validate-pq> and I<validate-g> are both set to 1 to check that p,q and g are
+valid. Either of these may be set to 0 to skip a test, which is mainly useful
+for testing purposes.
+
+=item "validate-legacy" (B<OSSL_PKEY_PARAM_FFC_VALIDATE_LEGACY>) <unsigned integer>
+
+This boolean value is used during key validation checks
+(See L<EVP_PKEY_param_check(3)>) to select the validation type. The default
+value of 0 selects FIPS186-4 validation. Setting this value to 1 selects
+FIPS186-2 validation.
+
+=back
+
+=head2 FFC key generation parameters
+
+The following key generation types are available for DSA and DHX algorithms:
+
+=over 4
+
+=item "type" (B<OSSL_PKEY_PARAM_FFC_TYPE>) <UTF8 string>
+
+Sets the type of parameter generation. The shared valid values are:
+
+=over 4
+
+=item "fips186_4"
+
+The current standard.
+
+=item "fips186_2"
+
+The old standard that should only be used for legacy purposes.
+
+=item "default"
+
+This can choose one of "fips186_4" or "fips186_2" depending on other
+parameters set for parameter generation.
+
+=back
+
+=item "pbits" (B<OSSL_PKEY_PARAM_FFC_PBITS>) <unsigned integer>
+
+Sets the size (in bits) of the prime 'p'.
+
+=item "qbits" (B<OSSL_PKEY_PARAM_FFC_QBITS>) <unsigned integer>
+
+Sets the size (in bits) of the prime 'q'.
+
+For "fips186_4" this can be either 224 or 256.
+For "fips186_2" this has a size of 160.
+
+=item "digest" (B<OSSL_PKEY_PARAM_FFC_DIGEST>) <UTF8 string>
+
+Sets the Digest algorithm to be used as part of the Key Generation Function
+associated with the given Key Generation I<ctx>.
+This must also be set for key validation.
+
+=item "properties" (B<OSSL_PKEY_PARAM_FFC_DIGEST_PROPS>) <UTF8 string>
+
+Sets properties to be used upon look up of the implementation for the selected
+Digest algorithm for the Key Generation Function associated with the given key
+generation I<ctx>. This may also be set for key validation.
+
+=item "seed" (B<OSSL_PKEY_PARAM_FFC_SEED>) <octet string>
+
+For "fips186_4" or "fips186_2" generation this sets the I<seed> data to use
+instead of generating a random seed internally. This should be used for
+testing purposes only. This will either produce fixed values for the generated
+parameters OR it will fail if the seed did not generate valid primes.
+
+=item "gindex" (B<OSSL_PKEY_PARAM_FFC_GINDEX>) <integer>
+
+=item "pcounter" (B<OSSL_PKEY_PARAM_FFC_PCOUNTER>) <integer>
+
+=item "hindex" (B<OSSL_PKEY_PARAM_FFC_H>) <integer>
+
+These types are described above.
+
+=back
+
+=head1 CONFORMING TO
+
+The following sections of SP800-56Ar3:
+
+=over 4
+
+=item 5.5.1.1 FFC Domain Parameter Selection/Generation
+
+=back
+
+The following sections of FIPS186-4:
+
+=over 4
+
+=item A.1.1.2 Generation of Probable Primes p and q Using an Approved Hash Function.
+
+=item A.2.3 Generation of canonical generator g.
+
+=item A.2.1 Unverifiable Generation of the Generator g.
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_PKEY-DSA(7)>,
+L<EVP_PKEY-DH(7)>,
+L<EVP_SIGNATURE-DSA(7)>,
+L<EVP_KEYEXCH-DH(7)>
+L<EVP_KEYMGMT(3)>,
+L<EVP_PKEY(3)>,
+L<provider-keymgmt(7)>,
+L<OSSL_PROVIDER-default(7)>,
+L<OSSL_PROVIDER-FIPS(7)>,
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_PKEY-HMAC.pod b/doc/man7/EVP_PKEY-HMAC.pod
new file mode 100644
index 000000000000..84b647e53055
--- /dev/null
+++ b/doc/man7/EVP_PKEY-HMAC.pod
@@ -0,0 +1,95 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY-HMAC, EVP_KEYMGMT-HMAC, EVP_PKEY-Siphash, EVP_KEYMGMT-Siphash,
+EVP_PKEY-Poly1305, EVP_KEYMGMT-Poly1305, EVP_PKEY-CMAC, EVP_KEYMGMT-CMAC
+- EVP_PKEY legacy MAC keytypes and algorithm support
+
+=head1 DESCRIPTION
+
+The B<HMAC> and B<CMAC> key types are implemented in OpenSSL's default and FIPS
+providers. Additionally the B<Siphash> and B<Poly1305> key types are implemented
+in the default provider. Performing MAC operations via an EVP_PKEY
+is considered legacy and are only available for backwards compatibility purposes
+and for a restricted set of algorithms. The preferred way of performing MAC
+operations is via the EVP_MAC APIs. See L<EVP_MAC_init(3)>.
+
+For further details on using EVP_PKEY based MAC keys see
+L<EVP_SIGNATURE-HMAC(7)>, L<EVP_SIGNATURE-Siphash(7)>,
+L<EVP_SIGNATURE-Poly1305(7)> or L<EVP_SIGNATURE-CMAC(7)>.
+
+=head2 Common MAC parameters
+
+All the B<MAC> keytypes support the following parameters.
+
+=over 4
+
+=item "priv" (B<OSSL_PKEY_PARAM_PRIV_KEY>) <octet string>
+
+The MAC key value.
+
+=item "properties" (B<OSSL_PKEY_PARAM_PROPERTIES>) <UTF8 string>
+
+A property query string to be used when any algorithms are fetched.
+
+=back
+
+=head2 CMAC parameters
+
+As well as the parameters described above, the B<CMAC> keytype additionally
+supports the following parameters.
+
+=over 4
+
+=item "cipher" (B<OSSL_PKEY_PARAM_CIPHER>) <UTF8 string>
+
+The name of a cipher to be used when generating the MAC.
+
+=item "engine" (B<OSSL_PKEY_PARAM_ENGINE>) <UTF8 string>
+
+The name of an engine to be used for the specified cipher (if any).
+
+=back
+
+=head2 Common MAC key generation parameters
+
+MAC key generation is unusual in that no new key is actually generated. Instead
+a new provider side key object is created with the supplied raw key value. This
+is done for backwards compatibility with previous versions of OpenSSL.
+
+=over 4
+
+=item "priv" (B<OSSL_PKEY_PARAM_PRIV_KEY>) <octet string>
+
+The MAC key value.
+
+=back
+
+=head2 CMAC key generation parameters
+
+In addition to the common MAC key generation parameters, the CMAC key generation
+additionally recognises the following.
+
+=over 4
+
+=item "cipher" (B<OSSL_PKEY_PARAM_CIPHER>) <UTF8 string>
+
+The name of a cipher to be used when generating the MAC.
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_KEYMGMT(3)>, L<EVP_PKEY(3)>, L<provider-keymgmt(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_PKEY-RSA.pod b/doc/man7/EVP_PKEY-RSA.pod
new file mode 100644
index 000000000000..f1141a364b86
--- /dev/null
+++ b/doc/man7/EVP_PKEY-RSA.pod
@@ -0,0 +1,274 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY-RSA, EVP_KEYMGMT-RSA, RSA
+- EVP_PKEY RSA keytype and algorithm support
+
+=head1 DESCRIPTION
+
+The B<RSA> keytype is implemented in OpenSSL's default and FIPS providers.
+That implementation supports the basic RSA keys, containing the modulus I<n>,
+the public exponent I<e>, the private exponent I<d>, and a collection of prime
+factors, exponents and coefficient for CRT calculations, of which the first
+few are known as I<p> and I<q>, I<dP> and I<dQ>, and I<qInv>.
+
+=head2 Common RSA parameters
+
+In addition to the common parameters that all keytypes should support (see
+L<provider-keymgmt(7)/Common parameters>), the B<RSA> keytype implementation
+supports the following.
+
+=over 4
+
+=item "n" (B<OSSL_PKEY_PARAM_RSA_N>) <unsigned integer>
+
+The RSA modulus "n" value.
+
+=item "e" (B<OSSL_PKEY_PARAM_RSA_E>) <unsigned integer>
+
+The RSA public exponent "e" value.
+This value must always be set when creating a raw key using L<EVP_PKEY_fromdata(3)>.
+Note that when a decryption operation is performed, that this value is used for
+blinding purposes to prevent timing attacks.
+
+=item "d" (B<OSSL_PKEY_PARAM_RSA_D>) <unsigned integer>
+
+The RSA private exponent "d" value.
+
+=item "rsa-factor1" (B<OSSL_PKEY_PARAM_RSA_FACTOR1>) <unsigned integer>
+
+=item "rsa-factor2" (B<OSSL_PKEY_PARAM_RSA_FACTOR2>) <unsigned integer>
+
+=item "rsa-factor3" (B<OSSL_PKEY_PARAM_RSA_FACTOR3>) <unsigned integer>
+
+=item "rsa-factor4" (B<OSSL_PKEY_PARAM_RSA_FACTOR4>) <unsigned integer>
+
+=item "rsa-factor5" (B<OSSL_PKEY_PARAM_RSA_FACTOR5>) <unsigned integer>
+
+=item "rsa-factor6" (B<OSSL_PKEY_PARAM_RSA_FACTOR6>) <unsigned integer>
+
+=item "rsa-factor7" (B<OSSL_PKEY_PARAM_RSA_FACTOR7>) <unsigned integer>
+
+=item "rsa-factor8" (B<OSSL_PKEY_PARAM_RSA_FACTOR8>) <unsigned integer>
+
+=item "rsa-factor9" (B<OSSL_PKEY_PARAM_RSA_FACTOR9>) <unsigned integer>
+
+=item "rsa-factor10" (B<OSSL_PKEY_PARAM_RSA_FACTOR10>) <unsigned integer>
+
+RSA prime factors. The factors are known as "p", "q" and "r_i" in RFC8017.
+Up to eight additional "r_i" prime factors are supported.
+
+=item "rsa-exponent1" (B<OSSL_PKEY_PARAM_RSA_EXPONENT1>) <unsigned integer>
+
+=item "rsa-exponent2" (B<OSSL_PKEY_PARAM_RSA_EXPONENT2>) <unsigned integer>
+
+=item "rsa-exponent3" (B<OSSL_PKEY_PARAM_RSA_EXPONENT3>) <unsigned integer>
+
+=item "rsa-exponent4" (B<OSSL_PKEY_PARAM_RSA_EXPONENT4>) <unsigned integer>
+
+=item "rsa-exponent5" (B<OSSL_PKEY_PARAM_RSA_EXPONENT5>) <unsigned integer>
+
+=item "rsa-exponent6" (B<OSSL_PKEY_PARAM_RSA_EXPONENT6>) <unsigned integer>
+
+=item "rsa-exponent7" (B<OSSL_PKEY_PARAM_RSA_EXPONENT7>) <unsigned integer>
+
+=item "rsa-exponent8" (B<OSSL_PKEY_PARAM_RSA_EXPONENT8>) <unsigned integer>
+
+=item "rsa-exponent9" (B<OSSL_PKEY_PARAM_RSA_EXPONENT9>) <unsigned integer>
+
+=item "rsa-exponent10" (B<OSSL_PKEY_PARAM_RSA_EXPONENT10>) <unsigned integer>
+
+RSA CRT (Chinese Remainder Theorem) exponents. The exponents are known
+as "dP", "dQ" and "d_i in RFC8017".
+Up to eight additional "d_i" exponents are supported.
+
+=item "rsa-coefficient1" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT1>) <unsigned integer>
+
+=item "rsa-coefficient2" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT2>) <unsigned integer>
+
+=item "rsa-coefficient3" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT3>) <unsigned integer>
+
+=item "rsa-coefficient4" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT4>) <unsigned integer>
+
+=item "rsa-coefficient5" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT5>) <unsigned integer>
+
+=item "rsa-coefficient6" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT6>) <unsigned integer>
+
+=item "rsa-coefficient7" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT7>) <unsigned integer>
+
+=item "rsa-coefficient8" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT8>) <unsigned integer>
+
+=item "rsa-coefficient9" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT9>) <unsigned integer>
+
+RSA CRT (Chinese Remainder Theorem) coefficients. The coefficients are known as
+"qInv" and "t_i".
+Up to eight additional "t_i" exponents are supported.
+
+=back
+
+=head2 RSA key generation parameters
+
+When generating RSA keys, the following key generation parameters may be used.
+
+=over 4
+
+=item "bits" (B<OSSL_PKEY_PARAM_RSA_BITS>) <unsigned integer>
+
+The value should be the cryptographic length for the B<RSA> cryptosystem, in
+bits.
+
+=item "primes" (B<OSSL_PKEY_PARAM_RSA_PRIMES>) <unsigned integer>
+
+The value should be the number of primes for the generated B<RSA> key. The
+default is 2. It isn't permitted to specify a larger number of primes than
+10. Additionally, the number of primes is limited by the length of the key
+being generated so the maximum number could be less.
+Some providers may only support a value of 2.
+
+=item "e" (B<OSSL_PKEY_PARAM_RSA_E>) <unsigned integer>
+
+The RSA "e" value. The value may be any odd number greater than or equal to
+65537. The default value is 65537.
+For legacy reasons a value of 3 is currently accepted but is deprecated.
+
+=back
+
+=head2 RSA key generation parameters for FIPS module testing
+
+When generating RSA keys, the following additional key generation parameters may
+be used for algorithm testing purposes only. Do not use these to generate
+RSA keys for a production environment.
+
+=over 4
+
+=item "xp" (B<OSSL_PKEY_PARAM_RSA_TEST_XP>) <unsigned integer>
+
+=item "xq" (B<OSSL_PKEY_PARAM_RSA_TEST_XQ>) <unsigned integer>
+
+These 2 fields are normally randomly generated and are used to generate "p" and
+"q".
+
+=item "xp1" (B<OSSL_PKEY_PARAM_RSA_TEST_XP1>) <unsigned integer>
+
+=item "xp2" (B<OSSL_PKEY_PARAM_RSA_TEST_XP2>) <unsigned integer>
+
+=item "xq1" (B<OSSL_PKEY_PARAM_RSA_TEST_XQ1>) <unsigned integer>
+
+=item "xq2" (B<OSSL_PKEY_PARAM_RSA_TEST_XQ2>) <unsigned integer>
+
+These 4 fields are normally randomly generated. The prime factors "p1", "p2",
+"q1" and "q2" are determined from these values.
+
+=back
+
+=head2 RSA key parameters for FIPS module testing
+
+The following intermediate values can be retrieved only if the values
+specified in L</"RSA key generation parameters for FIPS module testing"> are set.
+These should not be accessed in a production environment.
+
+=over 4
+
+=item "p1" (B<OSSL_PKEY_PARAM_RSA_TEST_P1>) <unsigned integer>
+
+=item "p2" (B<OSSL_PKEY_PARAM_RSA_TEST_P2>) <unsigned integer>
+
+=item "q1" (B<OSSL_PKEY_PARAM_RSA_TEST_Q1>) <unsigned integer>
+
+=item "q2" (B<OSSL_PKEY_PARAM_RSA_TEST_Q2>) <unsigned integer>
+
+The auxiliary probable primes.
+
+=back
+
+=head2 RSA key validation
+
+For RSA keys, L<EVP_PKEY_param_check(3)> and L<EVP_PKEY_param_check_quick(3)>
+both return 1 unconditionally.
+
+For RSA keys, L<EVP_PKEY_public_check(3)> conforms to the SP800-56Br1 I<public key
+check> when the OpenSSL FIPS provider is used. The OpenSSL default provider
+performs similiar tests but relaxes the keysize restrictions for backwards
+compatibility.
+
+For RSA keys, L<EVP_PKEY_public_check_quick(3)> is the same as
+L<EVP_PKEY_public_check(3)>.
+
+For RSA keys, L<EVP_PKEY_private_check(3)> conforms to the SP800-56Br1
+I<private key test>.
+
+For RSA keys, L<EVP_PKEY_pairwise_check(3)> conforms to the
+SP800-56Br1 I<KeyPair Validation check> for the OpenSSL FIPS provider. The
+OpenSSL default provider allows testing of the validity of multi-primes.
+
+=head1 CONFORMING TO
+
+=over 4
+
+=item FIPS186-4
+
+Section B.3.6 Generation of Probable Primes with Conditions Based on
+Auxiliary Probable Primes
+
+=item RFC 8017, excluding RSA-PSS and RSA-OAEP
+
+=for comment RSA-PSS, and probably also RSA-OAEP, need separate keytypes,
+and will be described in separate pages for those RSA keytypes.
+
+=back
+
+=head1 EXAMPLES
+
+An B<EVP_PKEY> context can be obtained by calling:
+
+ EVP_PKEY_CTX *pctx =
+ EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
+
+An B<RSA> key can be generated simply like this:
+
+ pkey = EVP_RSA_gen(4096);
+
+or like this:
+
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *pctx =
+ EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
+
+ EVP_PKEY_keygen_init(pctx);
+ EVP_PKEY_generate(pctx, &pkey);
+ EVP_PKEY_CTX_free(pctx);
+
+An B<RSA> key can be generated with key generation parameters:
+
+ unsigned int primes = 3;
+ unsigned int bits = 4096;
+ OSSL_PARAM params[3];
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
+
+ EVP_PKEY_keygen_init(pctx);
+
+ params[0] = OSSL_PARAM_construct_uint("bits", &bits);
+ params[1] = OSSL_PARAM_construct_uint("primes", &primes);
+ params[2] = OSSL_PARAM_construct_end();
+ EVP_PKEY_CTX_set_params(pctx, params);
+
+ EVP_PKEY_generate(pctx, &pkey);
+ EVP_PKEY_print_private(bio_out, pkey, 0, NULL);
+ EVP_PKEY_CTX_free(pctx);
+
+=head1 SEE ALSO
+
+L<EVP_RSA_gen(3)>, L<EVP_KEYMGMT(3)>, L<EVP_PKEY(3)>, L<provider-keymgmt(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_PKEY-SM2.pod b/doc/man7/EVP_PKEY-SM2.pod
new file mode 100644
index 000000000000..8bdc506cec21
--- /dev/null
+++ b/doc/man7/EVP_PKEY-SM2.pod
@@ -0,0 +1,94 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY-SM2, EVP_KEYMGMT-SM2, SM2
+- EVP_PKEY keytype support for the Chinese SM2 signature and encryption algorithms
+
+=head1 DESCRIPTION
+
+The B<SM2> algorithm was first defined by the Chinese national standard GM/T
+0003-2012 and was later standardized by ISO as ISO/IEC 14888. B<SM2> is actually
+an elliptic curve based algorithm. The current implementation in OpenSSL supports
+both signature and encryption schemes via the EVP interface.
+
+When doing the B<SM2> signature algorithm, it requires a distinguishing identifier
+to form the message prefix which is hashed before the real message is hashed.
+
+=head2 Common SM2 parameters
+
+SM2 uses the parameters defined in L<EVP_PKEY-EC(7)/Common EC parameters>.
+The following parameters are different:
+
+=over 4
+
+=item "cofactor" (B<OSSL_PKEY_PARAM_EC_COFACTOR>) <unsigned integer>
+
+This parameter is ignored for B<SM2>.
+
+=item (B<OSSL_PKEY_PARAM_DEFAULT_DIGEST>) <UTF8 string>
+
+Getter that returns the default digest name.
+(Currently returns "SM3" as of OpenSSL 3.0).
+
+=back
+
+=head1 NOTES
+
+B<SM2> signatures can be generated by using the 'DigestSign' series of APIs, for
+instance, EVP_DigestSignInit(), EVP_DigestSignUpdate() and EVP_DigestSignFinal().
+Ditto for the verification process by calling the 'DigestVerify' series of APIs.
+
+Before computing an B<SM2> signature, an B<EVP_PKEY_CTX> needs to be created,
+and an B<SM2> ID must be set for it, like this:
+
+ EVP_PKEY_CTX_set1_id(pctx, id, id_len);
+
+Before calling the EVP_DigestSignInit() or EVP_DigestVerifyInit() functions,
+that B<EVP_PKEY_CTX> should be assigned to the B<EVP_MD_CTX>, like this:
+
+ EVP_MD_CTX_set_pkey_ctx(mctx, pctx);
+
+There is normally no need to pass a B<pctx> parameter to EVP_DigestSignInit()
+or EVP_DigestVerifyInit() in such a scenario.
+
+SM2 can be tested with the L<openssl-speed(1)> application since version 3.0.
+Currently, the only valid algorithm name is B<sm2>.
+
+Since version 3.0, SM2 keys can be generated and loaded only when the domain
+parameters specify the SM2 elliptic curve.
+
+=head1 EXAMPLES
+
+This example demonstrates the calling sequence for using an B<EVP_PKEY> to verify
+a message with the SM2 signature algorithm and the SM3 hash algorithm:
+
+ #include <openssl/evp.h>
+
+ /* obtain an EVP_PKEY using whatever methods... */
+ mctx = EVP_MD_CTX_new();
+ pctx = EVP_PKEY_CTX_new(pkey, NULL);
+ EVP_PKEY_CTX_set1_id(pctx, id, id_len);
+ EVP_MD_CTX_set_pkey_ctx(mctx, pctx);
+ EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, pkey);
+ EVP_DigestVerifyUpdate(mctx, msg, msg_len);
+ EVP_DigestVerifyFinal(mctx, sig, sig_len)
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_new(3)>,
+L<EVP_DigestSignInit(3)>,
+L<EVP_DigestVerifyInit(3)>,
+L<EVP_PKEY_CTX_set1_id(3)>,
+L<EVP_MD_CTX_set_pkey_ctx(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_PKEY-X25519.pod b/doc/man7/EVP_PKEY-X25519.pod
new file mode 100644
index 000000000000..9e13e15f7f4f
--- /dev/null
+++ b/doc/man7/EVP_PKEY-X25519.pod
@@ -0,0 +1,106 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY-X25519, EVP_PKEY-X448, EVP_PKEY-ED25519, EVP_PKEY-ED448,
+EVP_KEYMGMT-X25519, EVP_KEYMGMT-X448, EVP_KEYMGMT-ED25519, EVP_KEYMGMT-ED448
+- EVP_PKEY X25519, X448, ED25519 and ED448 keytype and algorithm support
+
+=head1 DESCRIPTION
+
+The B<X25519>, B<X448>, B<ED25519> and B<ED448> keytypes are
+implemented in OpenSSL's default and FIPS providers. These implementations
+support the associated key, containing the public key I<pub> and the
+private key I<priv>.
+
+No additional parameters can be set during key generation.
+
+
+=head2 Common X25519, X448, ED25519 and ED448 parameters
+
+In addition to the common parameters that all keytypes should support (see
+L<provider-keymgmt(7)/Common parameters>), the implementation of these keytypes
+support the following.
+
+=over 4
+
+=item "group" (B<OSSL_PKEY_PARAM_GROUP_NAME>) <UTF8 string>
+
+This is only supported by X25519 and X448. The group name must be "x25519" or
+"x448" respectively for those algorithms. This is only present for consistency
+with other key exchange algorithms and is typically not needed.
+
+=item "pub" (B<OSSL_PKEY_PARAM_PUB_KEY>) <octet string>
+
+The public key value.
+
+=item "priv" (B<OSSL_PKEY_PARAM_PRIV_KEY>) <octet string>
+
+The private key value.
+
+=item "encoded-pub-key" (B<OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY>) <octet string>
+
+Used for getting and setting the encoding of a public key for the B<X25519> and
+B<X448> key types. Public keys are expected be encoded in a format as defined by
+RFC7748.
+
+=back
+
+=head2 ED25519 and ED448 parameters
+
+=over 4
+
+=item "mandatory-digest" (B<OSSL_PKEY_PARAM_MANDATORY_DIGEST>) <UTF8 string>
+
+The empty string, signifying that no digest may be specified.
+
+=back
+
+=head1 CONFORMING TO
+
+=over 4
+
+=item RFC 8032
+
+=item RFC 8410
+
+=back
+
+=head1 EXAMPLES
+
+An B<EVP_PKEY> context can be obtained by calling:
+
+ EVP_PKEY_CTX *pctx =
+ EVP_PKEY_CTX_new_from_name(NULL, "X25519", NULL);
+
+ EVP_PKEY_CTX *pctx =
+ EVP_PKEY_CTX_new_from_name(NULL, "X448", NULL);
+
+ EVP_PKEY_CTX *pctx =
+ EVP_PKEY_CTX_new_from_name(NULL, "ED25519", NULL);
+
+ EVP_PKEY_CTX *pctx =
+ EVP_PKEY_CTX_new_from_name(NULL, "ED448", NULL);
+
+An B<X25519> key can be generated like this:
+
+ pkey = EVP_PKEY_Q_keygen(NULL, NULL, "X25519");
+
+An B<X448>, B<ED25519>, or B<ED448> key can be generated likewise.
+
+=head1 SEE ALSO
+
+L<EVP_KEYMGMT(3)>, L<EVP_PKEY(3)>, L<provider-keymgmt(7)>,
+L<EVP_KEYEXCH-X25519(7)>, L<EVP_KEYEXCH-X448(7)>,
+L<EVP_SIGNATURE-ED25519(7)>, L<EVP_SIGNATURE-ED448(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_RAND-CTR-DRBG.pod b/doc/man7/EVP_RAND-CTR-DRBG.pod
new file mode 100644
index 000000000000..1012494250fb
--- /dev/null
+++ b/doc/man7/EVP_RAND-CTR-DRBG.pod
@@ -0,0 +1,107 @@
+=pod
+
+=head1 NAME
+
+EVP_RAND-CTR-DRBG - The CTR DRBG EVP_RAND implementation
+
+=head1 DESCRIPTION
+
+Support for the counter deterministic random bit generator through the
+B<EVP_RAND> API.
+
+=head2 Identity
+
+"CTR-DRBG" is the name for this implementation; it can be used with the
+EVP_RAND_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "state" (B<OSSL_RAND_PARAM_STATE>) <integer>
+
+=item "strength" (B<OSSL_RAND_PARAM_STRENGTH>) <unsigned integer>
+
+=item "max_request" (B<OSSL_RAND_PARAM_MAX_REQUEST>) <unsigned integer>
+
+=item "reseed_requests" (B<OSSL_DRBG_PARAM_RESEED_REQUESTS>) <unsigned integer>
+
+=item "reseed_time_interval" (B<OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL>) <integer>
+
+=item "min_entropylen" (B<OSSL_DRBG_PARAM_MIN_ENTROPYLEN>) <unsigned integer>
+
+=item "max_entropylen" (B<OSSL_DRBG_PARAM_MAX_ENTROPYLEN>) <unsigned integer>
+
+=item "min_noncelen" (B<OSSL_DRBG_PARAM_MIN_NONCELEN>) <unsigned integer>
+
+=item "max_noncelen" (B<OSSL_DRBG_PARAM_MAX_NONCELEN>) <unsigned integer>
+
+=item "max_perslen" (B<OSSL_DRBG_PARAM_MAX_PERSLEN>) <unsigned integer>
+
+=item "max_adinlen" (B<OSSL_DRBG_PARAM_MAX_ADINLEN>) <unsigned integer>
+
+=item "reseed_counter" (B<OSSL_DRBG_PARAM_RESEED_COUNTER>) <unsigned integer>
+
+=item "properties" (B<OSSL_DRBG_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "cipher" (B<OSSL_DRBG_PARAM_CIPHER>) <UTF8 string>
+
+These parameters work as described in L<EVP_RAND(3)/PARAMETERS>.
+
+=item "use_derivation_function" (B<OSSL_DRBG_PARAM_USE_DF>) <integer>
+
+This Boolean indicates if a derivation function should be used or not.
+A nonzero value (the default) uses the derivation function. A zero value
+does not.
+
+=back
+
+=head1 NOTES
+
+A context for CTR DRBG can be obtained by calling:
+
+ EVP_RAND *rand = EVP_RAND_fetch(NULL, "CTR-DRBG", NULL);
+ EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand);
+
+=head1 EXAMPLES
+
+ EVP_RAND *rand;
+ EVP_RAND_CTX *rctx;
+ unsigned char bytes[100];
+ OSSL_PARAM params[2], *p = params;
+ unsigned int strength = 128;
+
+ rand = EVP_RAND_fetch(NULL, "CTR-DRBG", NULL);
+ rctx = EVP_RAND_CTX_new(rand, NULL);
+ EVP_RAND_free(rand);
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER,
+ SN_aes_256_ctr, 0);
+ *p = OSSL_PARAM_construct_end();
+ EVP_RAND_instantiate(rctx, strength, 0, NULL, 0, params);
+
+ EVP_RAND_generate(rctx, bytes, sizeof(bytes), strength, 0, NULL, 0);
+
+ EVP_RAND_CTX_free(rctx);
+
+=head1 CONFORMING TO
+
+NIST SP 800-90A and SP 800-90B
+
+=head1 SEE ALSO
+
+L<EVP_RAND(3)>,
+L<EVP_RAND(3)/PARAMETERS>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_RAND-HASH-DRBG.pod b/doc/man7/EVP_RAND-HASH-DRBG.pod
new file mode 100644
index 000000000000..62ded203ad09
--- /dev/null
+++ b/doc/man7/EVP_RAND-HASH-DRBG.pod
@@ -0,0 +1,100 @@
+=pod
+
+=head1 NAME
+
+EVP_RAND-HASH-DRBG - The HASH DRBG EVP_RAND implementation
+
+=head1 DESCRIPTION
+
+Support for the hash deterministic random bit generator through the
+B<EVP_RAND> API.
+
+=head2 Identity
+
+"HASH-DRBG" is the name for this implementation; it can be used with the
+EVP_RAND_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "state" (B<OSSL_RAND_PARAM_STATE>) <integer>
+
+=item "strength" (B<OSSL_RAND_PARAM_STRENGTH>) <unsigned integer>
+
+=item "max_request" (B<OSSL_RAND_PARAM_MAX_REQUEST>) <unsigned integer>
+
+=item "reseed_requests" (B<OSSL_DRBG_PARAM_RESEED_REQUESTS>) <unsigned integer>
+
+=item "reseed_time_interval" (B<OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL>) <integer>
+
+=item "min_entropylen" (B<OSSL_DRBG_PARAM_MIN_ENTROPYLEN>) <unsigned integer>
+
+=item "max_entropylen" (B<OSSL_DRBG_PARAM_MAX_ENTROPYLEN>) <unsigned integer>
+
+=item "min_noncelen" (B<OSSL_DRBG_PARAM_MIN_NONCELEN>) <unsigned integer>
+
+=item "max_noncelen" (B<OSSL_DRBG_PARAM_MAX_NONCELEN>) <unsigned integer>
+
+=item "max_perslen" (B<OSSL_DRBG_PARAM_MAX_PERSLEN>) <unsigned integer>
+
+=item "max_adinlen" (B<OSSL_DRBG_PARAM_MAX_ADINLEN>) <unsigned integer>
+
+=item "reseed_counter" (B<OSSL_DRBG_PARAM_RESEED_COUNTER>) <unsigned integer>
+
+=item "properties" (B<OSSL_DRBG_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "digest" (B<OSSL_DRBG_PARAM_DIGEST>) <UTF8 string>
+
+These parameters work as described in L<EVP_RAND(3)/PARAMETERS>.
+
+=back
+
+=head1 NOTES
+
+A context for HASH DRBG can be obtained by calling:
+
+ EVP_RAND *rand = EVP_RAND_fetch(NULL, "HASH-DRBG", NULL);
+ EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand);
+
+=head1 EXAMPLES
+
+ EVP_RAND *rand;
+ EVP_RAND_CTX *rctx;
+ unsigned char bytes[100];
+ OSSL_PARAM params[2], *p = params;
+ unsigned int strength = 128;
+
+ rand = EVP_RAND_fetch(NULL, "HASH-DRBG", NULL);
+ rctx = EVP_RAND_CTX_new(rand, NULL);
+ EVP_RAND_free(rand);
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_DIGEST, SN_sha512, 0);
+ *p = OSSL_PARAM_construct_end();
+ EVP_RAND_instantiate(rctx, strength, 0, NULL, 0, params);
+
+ EVP_RAND_generate(rctx, bytes, sizeof(bytes), strength, 0, NULL, 0);
+
+ EVP_RAND_CTX_free(rctx);
+
+=head1 CONFORMING TO
+
+NIST SP 800-90A and SP 800-90B
+
+=head1 SEE ALSO
+
+L<EVP_RAND(3)>,
+L<EVP_RAND(3)/PARAMETERS>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_RAND-HMAC-DRBG.pod b/doc/man7/EVP_RAND-HMAC-DRBG.pod
new file mode 100644
index 000000000000..54ae61478d79
--- /dev/null
+++ b/doc/man7/EVP_RAND-HMAC-DRBG.pod
@@ -0,0 +1,103 @@
+=pod
+
+=head1 NAME
+
+EVP_RAND-HMAC-DRBG - The HMAC DRBG EVP_RAND implementation
+
+=head1 DESCRIPTION
+
+Support for the HMAC deterministic random bit generator through the
+B<EVP_RAND> API.
+
+=head2 Identity
+
+"HMAC-DRBG" is the name for this implementation; it can be used with the
+EVP_RAND_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "state" (B<OSSL_RAND_PARAM_STATE>) <integer>
+
+=item "strength" (B<OSSL_RAND_PARAM_STRENGTH>) <unsigned integer>
+
+=item "max_request" (B<OSSL_RAND_PARAM_MAX_REQUEST>) <unsigned integer>
+
+=item "reseed_requests" (B<OSSL_DRBG_PARAM_RESEED_REQUESTS>) <unsigned integer>
+
+=item "reseed_time_interval" (B<OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL>) <integer>
+
+=item "min_entropylen" (B<OSSL_DRBG_PARAM_MIN_ENTROPYLEN>) <unsigned integer>
+
+=item "max_entropylen" (B<OSSL_DRBG_PARAM_MAX_ENTROPYLEN>) <unsigned integer>
+
+=item "min_noncelen" (B<OSSL_DRBG_PARAM_MIN_NONCELEN>) <unsigned integer>
+
+=item "max_noncelen" (B<OSSL_DRBG_PARAM_MAX_NONCELEN>) <unsigned integer>
+
+=item "max_perslen" (B<OSSL_DRBG_PARAM_MAX_PERSLEN>) <unsigned integer>
+
+=item "max_adinlen" (B<OSSL_DRBG_PARAM_MAX_ADINLEN>) <unsigned integer>
+
+=item "reseed_counter" (B<OSSL_DRBG_PARAM_RESEED_COUNTER>) <unsigned integer>
+
+=item "properties" (B<OSSL_DRBG_PARAM_PROPERTIES>) <UTF8 string>
+
+=item "mac" (B<OSSL_DRBG_PARAM_MAC>) <UTF8 string>
+
+=item "digest" (B<OSSL_DRBG_PARAM_DIGEST>) <UTF8 string>
+
+These parameters work as described in L<EVP_RAND(3)/PARAMETERS>.
+
+=back
+
+=head1 NOTES
+
+A context for HMAC DRBG can be obtained by calling:
+
+ EVP_RAND *rand = EVP_RAND_fetch(NULL, "HMAC-DRBG", NULL);
+ EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand);
+
+=head1 EXAMPLES
+
+ EVP_RAND *rand;
+ EVP_RAND_CTX *rctx;
+ unsigned char bytes[100];
+ OSSL_PARAM params[3], *p = params;
+ unsigned int strength = 128;
+
+ rand = EVP_RAND_fetch(NULL, "HMAC-DRBG", NULL);
+ rctx = EVP_RAND_CTX_new(rand, NULL);
+ EVP_RAND_free(rand);
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_MAC, SN_hmac, 0);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_DIGEST, SN_sha256, 0);
+ *p = OSSL_PARAM_construct_end();
+ EVP_RAND_instantiate(rctx, strength, 0, NULL, 0, params);
+
+ EVP_RAND_generate(rctx, bytes, sizeof(bytes), strength, 0, NULL, 0);
+
+ EVP_RAND_CTX_free(rctx);
+
+=head1 CONFORMING TO
+
+NIST SP 800-90A and SP 800-90B
+
+=head1 SEE ALSO
+
+L<EVP_RAND(3)>,
+L<EVP_RAND(3)/PARAMETERS>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_RAND-SEED-SRC.pod b/doc/man7/EVP_RAND-SEED-SRC.pod
new file mode 100644
index 000000000000..516fa64f577e
--- /dev/null
+++ b/doc/man7/EVP_RAND-SEED-SRC.pod
@@ -0,0 +1,87 @@
+=pod
+
+=head1 NAME
+
+EVP_RAND-SEED-SRC - The randomness seed source EVP_RAND implementation
+
+=head1 DESCRIPTION
+
+Support for deterministic random number generator seeding through the
+B<EVP_RAND> API.
+
+The seed sources used are specified at the time OpenSSL is configured for
+building using the B<--with-rand-seed=> option. By default, operating system
+randomness sources are used.
+
+=head2 Identity
+
+"SEED-SRC" is the name for this implementation; it can be used with the
+EVP_RAND_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "state" (B<OSSL_RAND_PARAM_STATE>) <integer>
+
+=item "strength" (B<OSSL_RAND_PARAM_STRENGTH>) <unsigned integer>
+
+=item "max_request" (B<OSSL_RAND_PARAM_MAX_REQUEST>) <unsigned integer>
+
+These parameters work as described in L<EVP_RAND(3)/PARAMETERS>.
+
+=back
+
+=head1 NOTES
+
+A context for the seed source can be obtained by calling:
+
+ EVP_RAND *rand = EVP_RAND_fetch(NULL, "SEED-SRC", NULL);
+ EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand);
+
+=head1 EXAMPLES
+
+ EVP_RAND *rand;
+ EVP_RAND_CTX *seed, *rctx;
+ unsigned char bytes[100];
+ OSSL_PARAM params[2], *p = params;
+ unsigned int strength = 128;
+
+ /* Create a seed source */
+ rand = EVP_RAND_fetch(NULL, "SEED-SRC", NULL);
+ seed = EVP_RAND_CTX_new(rand, NULL);
+ EVP_RAND_free(rand);
+
+ /* Feed this into a DRBG */
+ rand = EVP_RAND_fetch(NULL, "CTR-DRBG", NULL);
+ rctx = EVP_RAND_CTX_new(rand, seed);
+ EVP_RAND_free(rand);
+
+ /* Configure the DRBG */
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER,
+ SN_aes_256_ctr, 0);
+ *p = OSSL_PARAM_construct_end();
+ EVP_RAND_instantiate(rctx, strength, 0, NULL, 0, params);
+
+ EVP_RAND_generate(rctx, bytes, sizeof(bytes), strength, 0, NULL, 0);
+
+ EVP_RAND_CTX_free(rctx);
+ EVP_RAND_CTX_free(seed);
+
+=head1 SEE ALSO
+
+L<EVP_RAND(3)>,
+L<EVP_RAND(3)/PARAMETERS>
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_RAND-TEST-RAND.pod b/doc/man7/EVP_RAND-TEST-RAND.pod
new file mode 100644
index 000000000000..a5527cee3f87
--- /dev/null
+++ b/doc/man7/EVP_RAND-TEST-RAND.pod
@@ -0,0 +1,116 @@
+=pod
+
+=head1 NAME
+
+EVP_RAND-TEST-RAND - The test EVP_RAND implementation
+
+=head1 DESCRIPTION
+
+Support for a test generator through the B<EVP_RAND> API. This generator is
+for test purposes only, it does not generate random numbers.
+
+=head2 Identity
+
+"TEST-RAND" is the name for this implementation; it can be used with the
+EVP_RAND_fetch() function.
+
+=head2 Supported parameters
+
+The supported parameters are:
+
+=over 4
+
+=item "state" (B<OSSL_RAND_PARAM_STATE>) <integer>
+
+These parameter works as described in L<EVP_RAND(3)/PARAMETERS>.
+
+=item "strength" (B<OSSL_RAND_PARAM_STRENGTH>) <unsigned integer>
+
+=item "reseed_requests" (B<OSSL_DRBG_PARAM_RESEED_REQUESTS>) <unsigned integer>
+
+=item "reseed_time_interval" (B<OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL>) <integer>
+
+=item "max_request" (B<OSSL_DRBG_PARAM_RESEED_REQUESTS>) <unsigned integer>
+
+=item "min_entropylen" (B<OSSL_DRBG_PARAM_MIN_ENTROPYLEN>) <unsigned integer>
+
+=item "max_entropylen" (B<OSSL_DRBG_PARAM_MAX_ENTROPYLEN>) <unsigned integer>
+
+=item "min_noncelen" (B<OSSL_DRBG_PARAM_MIN_NONCELEN>) <unsigned integer>
+
+=item "max_noncelen" (B<OSSL_DRBG_PARAM_MAX_NONCELEN>) <unsigned integer>
+
+=item "max_perslen" (B<OSSL_DRBG_PARAM_MAX_PERSLEN>) <unsigned integer>
+
+=item "max_adinlen" (B<OSSL_DRBG_PARAM_MAX_ADINLEN>) <unsigned integer>
+
+=item "reseed_counter" (B<OSSL_DRBG_PARAM_RESEED_COUNTER>) <unsigned integer>
+
+These parameters work as described in L<EVP_RAND(3)/PARAMETERS>, except that
+they can all be set as well as read.
+
+=item "test_entropy" (B<OSSL_RAND_PARAM_TEST_ENTROPY>) <octet string>
+
+Sets the bytes returned when the test generator is sent an entropy request.
+The current position is remembered across generate calls.
+If there are insufficient data present to satisfy a call, an error is returned.
+
+=item "test_nonce" (B<OSSL_RAND_PARAM_TEST_NONCE>) <octet string>
+
+Sets the bytes returned when the test generator is sent a nonce request.
+Each nonce request will return all of the bytes.
+
+=back
+
+=head1 NOTES
+
+A context for a test generator can be obtained by calling:
+
+ EVP_RAND *rand = EVP_RAND_fetch(NULL, "TEST-RAND", NULL);
+ EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand);
+
+=head1 EXAMPLES
+
+ EVP_RAND *rand;
+ EVP_RAND_CTX *rctx;
+ unsigned char bytes[100];
+ OSSL_PARAM params[4], *p = params;
+ unsigned char entropy[1000] = { ... };
+ unsigned char nonce[20] = { ... };
+ unsigned int strength = 48;
+
+ rand = EVP_RAND_fetch(NULL, "TEST-RAND", NULL);
+ rctx = EVP_RAND_CTX_new(rand, NULL);
+ EVP_RAND_free(rand);
+
+ *p++ = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, &strength);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY,
+ entropy, sizeof(entropy));
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_NONCE,
+ nonce, sizeof(nonce));
+ *p = OSSL_PARAM_construct_end();
+ EVP_RAND_instantiate(rctx, strength, 0, NULL, 0, params);
+
+ EVP_RAND_generate(rctx, bytes, sizeof(bytes), strength, 0, NULL, 0);
+
+ EVP_RAND_CTX_free(rctx);
+
+=head1 SEE ALSO
+
+L<EVP_RAND(3)>,
+L<EVP_RAND(3)/PARAMETERS>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_RAND.pod b/doc/man7/EVP_RAND.pod
new file mode 100644
index 000000000000..08f48fdc451a
--- /dev/null
+++ b/doc/man7/EVP_RAND.pod
@@ -0,0 +1,306 @@
+=pod
+
+=head1 NAME
+
+EVP_RAND - the random bit generator
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+ #include <rand.h>
+
+=head1 DESCRIPTION
+
+The default OpenSSL RAND method is based on the EVP_RAND classes to provide
+non-deterministic inputs to other cryptographic algorithms.
+
+While the RAND API is the 'frontend' which is intended to be used by
+application developers for obtaining random bytes, the EVP_RAND API
+serves as the 'backend', connecting the former with the operating
+systems's entropy sources and providing access to deterministic random
+bit generators (DRBG) and their configuration parameters.
+A DRBG is a certain type of cryptographically-secure pseudo-random
+number generator (CSPRNG), which is described in
+[NIST SP 800-90A Rev. 1].
+
+=head2 Disclaimer
+
+Unless you have very specific requirements for your random generator,
+it is in general not necessary to utilize the EVP_RAND API directly.
+The usual way to obtain random bytes is to use L<RAND_bytes(3)> or
+L<RAND_priv_bytes(3)>, see also L<RAND(7)>.
+
+=head2 Typical Use Cases
+
+Typical examples for such special use cases are the following:
+
+=over 2
+
+=item *
+
+You want to use your own private DRBG instances.
+Multiple DRBG instances which are accessed only by a single thread provide
+additional security (because their internal states are independent) and
+better scalability in multithreaded applications (because they don't need
+to be locked).
+
+=item *
+
+You need to integrate a previously unsupported entropy source.
+Refer to L<provider-rand(7)> for the implementation details to support adding
+randomness sources to EVP_RAND.
+
+=item *
+
+You need to change the default settings of the standard OpenSSL RAND
+implementation to meet specific requirements.
+
+=back
+
+
+=head1 EVP_RAND CHAINING
+
+An EVP_RAND instance can be used as the entropy source of another
+EVP_RAND instance, provided it has itself access to a valid entropy source.
+The EVP_RAND instance which acts as entropy source is called the I<parent>,
+the other instance the I<child>. Typically, the child will be a DRBG because
+it does not make sense for the child to be an entropy source.
+
+This is called chaining. A chained EVP_RAND instance is created by passing
+a pointer to the parent EVP_RAND_CTX as argument to the EVP_RAND_CTX_new() call.
+It is possible to create chains of more than two DRBG in a row.
+It is also possible to use any EVP_RAND_CTX class as the parent, however, only
+a live entropy source may ignore and not use its parent.
+
+=head1 THE THREE SHARED DRBG INSTANCES
+
+Currently, there are three shared DRBG instances,
+the <primary>, <public>, and <private> DRBG.
+While the <primary> DRBG is a single global instance, the <public> and <private>
+DRBG are created per thread and accessed through thread-local storage.
+
+By default, the functions L<RAND_bytes(3)> and L<RAND_priv_bytes(3)> use
+the thread-local <public> and <private> DRBG instance, respectively.
+
+=head2 The <primary> DRBG instance
+
+The <primary> DRBG is not used directly by the application, only for reseeding
+the two other two DRBG instances. It reseeds itself by obtaining randomness
+either from os entropy sources or by consuming randomness which was added
+previously by L<RAND_add(3)>.
+
+=head2 The <public> DRBG instance
+
+This instance is used per default by L<RAND_bytes(3)>.
+
+=head2 The <private> DRBG instance
+
+This instance is used per default by L<RAND_priv_bytes(3)>
+
+
+=head1 LOCKING
+
+The <primary> DRBG is intended to be accessed concurrently for reseeding
+by its child DRBG instances. The necessary locking is done internally.
+It is I<not> thread-safe to access the <primary> DRBG directly via the
+EVP_RAND interface.
+The <public> and <private> DRBG are thread-local, i.e. there is an
+instance of each per thread. So they can safely be accessed without
+locking via the EVP_RAND interface.
+
+Pointers to these DRBG instances can be obtained using
+RAND_get0_primary(), RAND_get0_public() and RAND_get0_private(), respectively.
+Note that it is not allowed to store a pointer to one of the thread-local
+DRBG instances in a variable or other memory location where it will be
+accessed and used by multiple threads.
+
+All other DRBG instances created by an application don't support locking,
+because they are intended to be used by a single thread.
+Instead of accessing a single DRBG instance concurrently from different
+threads, it is recommended to instantiate a separate DRBG instance per
+thread. Using the <primary> DRBG as entropy source for multiple DRBG
+instances on different threads is thread-safe, because the DRBG instance
+will lock the <primary> DRBG automatically for obtaining random input.
+
+=head1 THE OVERALL PICTURE
+
+The following picture gives an overview over how the DRBG instances work
+together and are being used.
+
+ +--------------------+
+ | os entropy sources |
+ +--------------------+
+ |
+ v +-----------------------------+
+ RAND_add() ==> <primary> <-| shared DRBG (with locking) |
+ / \ +-----------------------------+
+ / \ +---------------------------+
+ <public> <private> <- | per-thread DRBG instances |
+ | | +---------------------------+
+ v v
+ RAND_bytes() RAND_priv_bytes()
+ | ^
+ | |
+ +------------------+ +------------------------------------+
+ | general purpose | | used for secrets like session keys |
+ | random generator | | and private keys for certificates |
+ +------------------+ +------------------------------------+
+
+
+The usual way to obtain random bytes is to call RAND_bytes(...) or
+RAND_priv_bytes(...). These calls are roughly equivalent to calling
+EVP_RAND_generate(<public>, ...) and
+EVP_RAND_generate(<private>, ...),
+respectively.
+
+=head1 RESEEDING
+
+A DRBG instance seeds itself automatically, pulling random input from
+its entropy source. The entropy source can be either a trusted operating
+system entropy source, or another DRBG with access to such a source.
+
+Automatic reseeding occurs after a predefined number of generate requests.
+The selection of the trusted entropy sources is configured at build
+time using the --with-rand-seed option. The following sections explain
+the reseeding process in more detail.
+
+=head2 Automatic Reseeding
+
+Before satisfying a generate request (L<EVP_RAND_generate(3)>), the DRBG
+reseeds itself automatically, if one of the following conditions holds:
+
+- the DRBG was not instantiated (=seeded) yet or has been uninstantiated.
+
+- the number of generate requests since the last reseeding exceeds a
+certain threshold, the so called I<reseed_interval>.
+This behaviour can be disabled by setting the I<reseed_interval> to 0.
+
+- the time elapsed since the last reseeding exceeds a certain time
+interval, the so called I<reseed_time_interval>.
+This can be disabled by setting the I<reseed_time_interval> to 0.
+
+- the DRBG is in an error state.
+
+B<Note>: An error state is entered if the entropy source fails while
+the DRBG is seeding or reseeding.
+The last case ensures that the DRBG automatically recovers
+from the error as soon as the entropy source is available again.
+
+=head2 Manual Reseeding
+
+In addition to automatic reseeding, the caller can request an immediate
+reseeding of the DRBG with fresh entropy by setting the
+I<prediction resistance> parameter to 1 when calling
+L<EVP_RAND_generate(3)>.
+
+The document [NIST SP 800-90C] describes prediction resistance requests
+in detail and imposes strict conditions on the entropy sources that are
+approved for providing prediction resistance.
+A request for prediction resistance can only be satisfied by pulling fresh
+entropy from a live entropy source (section 5.5.2 of [NIST SP 800-90C]).
+It is up to the user to ensure that a live entropy source is configured
+and is being used.
+
+For the three shared DRBGs (and only for these) there is another way to
+reseed them manually:
+If L<RAND_add(3)> is called with a positive I<randomness> argument
+(or L<RAND_seed(3)>), then this will immediately reseed the <primary> DRBG.
+The <public> and <private> DRBG will detect this on their next generate
+call and reseed, pulling randomness from <primary>.
+
+The last feature has been added to support the common practice used with
+previous OpenSSL versions to call RAND_add() before calling RAND_bytes().
+
+
+=head2 Entropy Input and Additional Data
+
+The DRBG distinguishes two different types of random input: I<entropy>,
+which comes from a trusted source, and I<additional input>',
+which can optionally be added by the user and is considered untrusted.
+It is possible to add I<additional input> not only during reseeding,
+but also for every generate request.
+
+
+=head2 Configuring the Random Seed Source
+
+In most cases OpenSSL will automatically choose a suitable seed source
+for automatically seeding and reseeding its <primary> DRBG. In some cases
+however, it will be necessary to explicitly specify a seed source during
+configuration, using the --with-rand-seed option. For more information,
+see the INSTALL instructions. There are also operating systems where no
+seed source is available and automatic reseeding is disabled by default.
+
+The following two sections describe the reseeding process of the primary
+DRBG, depending on whether automatic reseeding is available or not.
+
+
+=head2 Reseeding the primary DRBG with automatic seeding enabled
+
+Calling RAND_poll() or RAND_add() is not necessary, because the DRBG
+pulls the necessary entropy from its source automatically.
+However, both calls are permitted, and do reseed the RNG.
+
+RAND_add() can be used to add both kinds of random input, depending on the
+value of the I<randomness> argument:
+
+=over 4
+
+=item randomness == 0:
+
+The random bytes are mixed as additional input into the current state of
+the DRBG.
+Mixing in additional input is not considered a full reseeding, hence the
+reseed counter is not reset.
+
+
+=item randomness > 0:
+
+The random bytes are used as entropy input for a full reseeding
+(resp. reinstantiation) if the DRBG is instantiated
+(resp. uninstantiated or in an error state).
+The number of random bits required for reseeding is determined by the
+security strength of the DRBG. Currently it defaults to 256 bits (32 bytes).
+It is possible to provide less randomness than required.
+In this case the missing randomness will be obtained by pulling random input
+from the trusted entropy sources.
+
+=back
+
+NOTE: Manual reseeding is *not allowed* in FIPS mode, because
+[NIST SP-800-90Ar1] mandates that entropy *shall not* be provided by
+the consuming application for instantiation (Section 9.1) or
+reseeding (Section 9.2). For that reason, the I<randomness>
+argument is ignored and the random bytes provided by the L<RAND_add(3)> and
+L<RAND_seed(3)> calls are treated as additional data.
+
+=head2 Reseeding the primary DRBG with automatic seeding disabled
+
+Calling RAND_poll() will always fail.
+
+RAND_add() needs to be called for initial seeding and periodic reseeding.
+At least 48 bytes (384 bits) of randomness have to be provided, otherwise
+the (re-)seeding of the DRBG will fail. This corresponds to one and a half
+times the security strength of the DRBG. The extra half is used for the
+nonce during instantiation.
+
+More precisely, the number of bytes needed for seeding depend on the
+I<security strength> of the DRBG, which is set to 256 by default.
+
+=head1 SEE ALSO
+
+L<RAND(7)>, L<EVP_RAND(3)>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_SIGNATURE-DSA.pod b/doc/man7/EVP_SIGNATURE-DSA.pod
new file mode 100644
index 000000000000..5a42d6b1cd22
--- /dev/null
+++ b/doc/man7/EVP_SIGNATURE-DSA.pod
@@ -0,0 +1,58 @@
+=pod
+
+=head1 NAME
+
+EVP_SIGNATURE-DSA
+- The B<EVP_PKEY> DSA signature implementation
+
+=head1 DESCRIPTION
+
+Support for computing DSA signatures.
+See L<EVP_PKEY-DSA(7)> for information related to DSA keys.
+
+=head2 Signature Parameters
+
+The following signature parameters can be set using EVP_PKEY_CTX_set_params().
+This may be called after EVP_PKEY_sign_init() or EVP_PKEY_verify_init(),
+and before calling EVP_PKEY_sign() or EVP_PKEY_verify().
+
+=over 4
+
+=item "digest" (B<OSSL_SIGNATURE_PARAM_DIGEST>) <UTF8 string>
+
+=item "properties" (B<OSSL_SIGNATURE_PARAM_PROPERTIES>) <UTF8 string>
+
+The settable parameters are described in L<provider-signature(7)>.
+
+=back
+
+The following signature parameters can be retrieved using
+EVP_PKEY_CTX_get_params().
+
+=over 4
+
+=item "algorithm-id" (B<OSSL_SIGNATURE_PARAM_ALGORITHM_ID>) <octet string>
+
+=item "digest" (B<OSSL_SIGNATURE_PARAM_DIGEST>) <UTF8 string>
+
+The gettable parameters are described in L<provider-signature(7)>.
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_set_params(3)>,
+L<EVP_PKEY_sign(3)>,
+L<EVP_PKEY_verify(3)>,
+L<provider-signature(7)>,
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_SIGNATURE-ECDSA.pod b/doc/man7/EVP_SIGNATURE-ECDSA.pod
new file mode 100644
index 000000000000..0f6aa13c4a2f
--- /dev/null
+++ b/doc/man7/EVP_SIGNATURE-ECDSA.pod
@@ -0,0 +1,57 @@
+=pod
+
+=head1 NAME
+
+EVP_SIGNATURE-ECDSA - The EVP_PKEY ECDSA signature implementation.
+
+=head1 DESCRIPTION
+
+Support for computing ECDSA signatures.
+See L<EVP_PKEY-EC(7)> for information related to EC keys.
+
+=head2 ECDSA Signature Parameters
+
+The following signature parameters can be set using EVP_PKEY_CTX_set_params().
+This may be called after EVP_PKEY_sign_init() or EVP_PKEY_verify_init(),
+and before calling EVP_PKEY_sign() or EVP_PKEY_verify().
+
+=over 4
+
+=item "digest" (B<OSSL_SIGNATURE_PARAM_DIGEST>) <UTF8 string>
+
+=item "properties" (B<OSSL_SIGNATURE_PARAM_PROPERTIES>) <UTF8 string>
+
+These parameters are described in L<provider-signature(7)>.
+
+=back
+
+The following signature parameters can be retrieved using
+EVP_PKEY_CTX_get_params().
+
+=over 4
+
+=item "algorithm-id" (B<OSSL_SIGNATURE_PARAM_ALGORITHM_ID>) <octet string>
+
+=item "digest" (B<OSSL_SIGNATURE_PARAM_DIGEST>) <UTF8 string>
+
+The parameters are described in L<provider-signature(7)>.
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_set_params(3)>,
+L<EVP_PKEY_sign(3)>,
+L<EVP_PKEY_verify(3)>,
+L<provider-signature(7)>,
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_SIGNATURE-ED25519.pod b/doc/man7/EVP_SIGNATURE-ED25519.pod
new file mode 100644
index 000000000000..2183d83c2eae
--- /dev/null
+++ b/doc/man7/EVP_SIGNATURE-ED25519.pod
@@ -0,0 +1,102 @@
+=pod
+
+=head1 NAME
+
+EVP_SIGNATURE-ED25519,
+EVP_SIGNATURE-ED448,
+Ed25519,
+Ed448
+- EVP_PKEY Ed25519 and Ed448 support
+
+=head1 DESCRIPTION
+
+The B<Ed25519> and B<Ed448> EVP_PKEY implementation supports key generation,
+one-shot digest sign and digest verify using PureEdDSA and B<Ed25519> or B<Ed448>
+(see RFC8032). It has associated private and public key formats compatible with
+RFC 8410.
+
+=head2 ED25519 and ED448 Signature Parameters
+
+No additional parameters can be set during one-shot signing or verification.
+In particular, because PureEdDSA is used, a digest must B<NOT> be specified when
+signing or verifying.
+See L<EVP_PKEY-X25519(7)> for information related to B<X25519> and B<X448> keys.
+
+The following signature parameters can be retrieved using
+EVP_PKEY_CTX_get_params().
+
+=over 4
+
+=item "algorithm-id" (B<OSSL_SIGNATURE_PARAM_ALGORITHM_ID>) <octet string>
+
+The parameters are described in L<provider-signature(7)>.
+
+=back
+
+=head1 NOTES
+
+The PureEdDSA algorithm does not support the streaming mechanism
+of other signature algorithms using, for example, EVP_DigestUpdate().
+The message to sign or verify must be passed using the one-shot
+EVP_DigestSign() and EVP_DigestVerify() functions.
+
+When calling EVP_DigestSignInit() or EVP_DigestVerifyInit(), the
+digest I<type> parameter B<MUST> be set to NULL.
+
+Applications wishing to sign certificates (or other structures such as
+CRLs or certificate requests) using Ed25519 or Ed448 can either use X509_sign()
+or X509_sign_ctx() in the usual way.
+
+Ed25519 or Ed448 private keys can be set directly using
+L<EVP_PKEY_new_raw_private_key(3)> or loaded from a PKCS#8 private key file
+using L<PEM_read_bio_PrivateKey(3)> (or similar function). Completely new keys
+can also be generated (see the example below). Setting a private key also sets
+the associated public key.
+
+Ed25519 or Ed448 public keys can be set directly using
+L<EVP_PKEY_new_raw_public_key(3)> or loaded from a SubjectPublicKeyInfo
+structure in a PEM file using L<PEM_read_bio_PUBKEY(3)> (or similar function).
+
+Ed25519 and Ed448 can be tested with the L<openssl-speed(1)> application
+since version 1.1.1.
+Valid algorithm names are B<ed25519>, B<ed448> and B<eddsa>. If B<eddsa> is
+specified, then both Ed25519 and Ed448 are benchmarked.
+
+=head1 EXAMPLES
+
+To sign a message using a ED25519 or ED448 key:
+
+ void do_sign(EVP_PKEY *ed_key, unsigned char *msg, size_t msg_len)
+ {
+ size_t sig_len;
+ unsigned char *sig = NULL;
+ EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
+
+ EVP_DigestSignInit(md_ctx, NULL, NULL, NULL, ed_key);
+ /* Calculate the requires size for the signature by passing a NULL buffer */
+ EVP_DigestSign(md_ctx, NULL, &sig_len, msg, msg_len);
+ sig = OPENSSL_zalloc(sig_len);
+
+ EVP_DigestSign(md_ctx, sig, &sig_len, msg, msg_len);
+ ...
+ OPENSSL_free(sig);
+ EVP_MD_CTX_free(md_ctx);
+ }
+
+=head1 SEE ALSO
+
+L<EVP_PKEY-X25519(7)>
+L<provider-signature(7)>,
+L<EVP_DigestSignInit(3)>,
+L<EVP_DigestVerifyInit(3)>,
+
+=head1 COPYRIGHT
+
+Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_SIGNATURE-HMAC.pod b/doc/man7/EVP_SIGNATURE-HMAC.pod
new file mode 100644
index 000000000000..6628d9ebc2bc
--- /dev/null
+++ b/doc/man7/EVP_SIGNATURE-HMAC.pod
@@ -0,0 +1,49 @@
+=pod
+
+=head1 NAME
+
+EVP_SIGNATURE-HMAC, EVP_SIGNATURE-Siphash, EVP_SIGNATURE-Poly1305,
+EVP_SIGNATURE-CMAC
+- The legacy B<EVP_PKEY> MAC signature implementations
+
+=head1 DESCRIPTION
+
+The algorithms described here have legacy support for creating MACs using
+L<EVP_DigestSignInit(3)> and related functions. This is not the preferred way of
+creating MACs. Instead you should use the newer L<EVP_MAC_init(3)> functions.
+This mechanism is provided for backwards compatibility with older versions of
+OpenSSL.
+
+The same signature parameters can be set using EVP_PKEY_CTX_set_params() as can
+be set via EVP_MAC_CTX_set_params() for the underlying EVP_MAC. See
+L<EVP_MAC-HMAC(7)>, L<EVP_MAC-Siphash(7)>, L<EVP_MAC-Poly1305(7)> and
+L<EVP_MAC-CMAC(7)> for details.
+
+ See L<EVP_PKEY-HMAC(7)>, L<EVP_PKEY-Siphash(7)>, L<EVP_PKEY-Poly1305(7)> or
+ L<EVP_PKEY-CMAC(7)> for details about parameters that are supported during the
+ creation of an EVP_PKEY.
+
+=head1 SEE ALSO
+
+L<EVP_MAC_init(3)>,
+L<EVP_DigestSignInit(3)>,
+L<EVP_PKEY-HMAC(7)>,
+L<EVP_PKEY-Siphash(7)>,
+L<EVP_PKEY-Poly1305(7)>,
+L<EVP_PKEY-CMAC(7)>,
+L<EVP_MAC-HMAC(7)>,
+L<EVP_MAC-Siphash(7)>,
+L<EVP_MAC-Poly1305(7)>,
+L<EVP_MAC-CMAC(7)>,
+L<provider-signature(7)>,
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_SIGNATURE-RSA.pod b/doc/man7/EVP_SIGNATURE-RSA.pod
new file mode 100644
index 000000000000..1ce32cc44368
--- /dev/null
+++ b/doc/man7/EVP_SIGNATURE-RSA.pod
@@ -0,0 +1,112 @@
+=pod
+
+=head1 NAME
+
+EVP_SIGNATURE-RSA
+- The EVP_PKEY RSA signature implementation
+
+=head1 DESCRIPTION
+
+Support for computing RSA signatures.
+See L<EVP_PKEY-RSA(7)> for information related to RSA keys.
+
+=head2 Signature Parameters
+
+The following signature parameters can be set using EVP_PKEY_CTX_set_params().
+This may be called after EVP_PKEY_sign_init() or EVP_PKEY_verify_init(),
+and before calling EVP_PKEY_sign() or EVP_PKEY_verify().
+
+=over 4
+
+=item "digest" (B<OSSL_SIGNATURE_PARAM_DIGEST>) <UTF8 string>
+
+=item "properties" (B<OSSL_SIGNATURE_PARAM_PROPERTIES>) <UTF8 string>
+
+These common parameters are described in L<provider-signature(7)>.
+
+=item "pad-mode" (B<OSSL_SIGNATURE_PARAM_PAD_MODE>) <UTF8 string>
+
+The type of padding to be used. Its value can be one of the following:
+
+=over 4
+
+=item "none" (B<OSSL_PKEY_RSA_PAD_MODE_NONE>)
+
+=item "pkcs1" (B<OSSL_PKEY_RSA_PAD_MODE_PKCSV15>)
+
+=item "x931" (B<OSSL_PKEY_RSA_PAD_MODE_X931>)
+
+=item "pss" (B<OSSL_PKEY_RSA_PAD_MODE_PSS>)
+
+=back
+
+=item "mgf1-digest" (B<OSSL_SIGNATURE_PARAM_MGF1_DIGEST>) <UTF8 string>
+
+The digest algorithm name to use for the maskGenAlgorithm used by "pss" mode.
+
+=item "mgf1-properties" (B<OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES>) <UTF8 string>
+
+Sets the name of the property query associated with the "mgf1-digest" algorithm.
+NULL is used if this optional value is not set.
+
+=item "saltlen" (B<OSSL_SIGNATURE_PARAM_PSS_SALTLEN>) <integer> or <UTF8 string>
+
+The "pss" mode minimum salt length. The value can either be an integer,
+a string value representing a number or one of the following string values:
+
+=over 4
+
+=item "digest" (B<OSSL_PKEY_RSA_PSS_SALT_LEN_DIGEST>)
+
+Use the same length as the digest size.
+
+=item "max" (B<OSSL_PKEY_RSA_PSS_SALT_LEN_MAX>)
+
+Use the maximum salt length.
+
+=item "auto" (B<OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO>)
+
+Auto detect the salt length.
+
+=back
+
+=back
+
+The following signature parameters can be retrieved using
+EVP_PKEY_CTX_get_params().
+
+=over 4
+
+=item "algorithm-id" (B<OSSL_SIGNATURE_PARAM_ALGORITHM_ID>) <octet string>
+
+This common parameter is described in L<provider-signature(7)>.
+
+=item "digest" (B<OSSL_SIGNATURE_PARAM_DIGEST>) <UTF8 string>
+
+=item "pad-mode" (B<OSSL_SIGNATURE_PARAM_PAD_MODE>) <UTF8 string>
+
+=item "mgf1-digest" (B<OSSL_SIGNATURE_PARAM_MGF1_DIGEST>) <UTF8 string>
+
+=item "saltlen" (B<OSSL_SIGNATURE_PARAM_PSS_SALTLEN>) <integer> or <UTF8 string>
+
+These parameters are as described above.
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_set_params(3)>,
+L<EVP_PKEY_sign(3)>,
+L<EVP_PKEY_verify(3)>,
+L<provider-signature(7)>,
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/Ed25519.pod b/doc/man7/Ed25519.pod
deleted file mode 100644
index 8ab4fff76493..000000000000
--- a/doc/man7/Ed25519.pod
+++ /dev/null
@@ -1,87 +0,0 @@
-=pod
-
-=head1 NAME
-
-Ed25519,
-Ed448
-- EVP_PKEY Ed25519 and Ed448 support
-
-=head1 DESCRIPTION
-
-The B<Ed25519> and B<Ed448> EVP_PKEY implementation supports key generation,
-one-shot digest sign and digest verify using PureEdDSA and B<Ed25519> or B<Ed448>
-(see RFC8032). It has associated private and public key formats compatible with
-RFC 8410.
-
-No additional parameters can be set during key generation, one-shot signing or
-verification. In particular, because PureEdDSA is used, a digest must B<NOT> be
-specified when signing or verifying.
-
-=head1 NOTES
-
-The PureEdDSA algorithm does not support the streaming mechanism
-of other signature algorithms using, for example, EVP_DigestUpdate().
-The message to sign or verify must be passed using the one-shot
-EVP_DigestSign() and EVP_DigestVerify() functions.
-
-When calling EVP_DigestSignInit() or EVP_DigestVerifyInit(), the
-digest B<type> parameter B<MUST> be set to B<NULL>.
-
-Applications wishing to sign certificates (or other structures such as
-CRLs or certificate requests) using Ed25519 or Ed448 can either use X509_sign()
-or X509_sign_ctx() in the usual way.
-
-A context for the B<Ed25519> algorithm can be obtained by calling:
-
- EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL);
-
-For the B<Ed448> algorithm a context can be obtained by calling:
-
- EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED448, NULL);
-
-Ed25519 or Ed448 private keys can be set directly using
-L<EVP_PKEY_new_raw_private_key(3)> or loaded from a PKCS#8 private key file
-using L<PEM_read_bio_PrivateKey(3)> (or similar function). Completely new keys
-can also be generated (see the example below). Setting a private key also sets
-the associated public key.
-
-Ed25519 or Ed448 public keys can be set directly using
-L<EVP_PKEY_new_raw_public_key(3)> or loaded from a SubjectPublicKeyInfo
-structure in a PEM file using L<PEM_read_bio_PUBKEY(3)> (or similar function).
-
-Ed25519 and Ed448 can be tested within L<speed(1)> application since version 1.1.1.
-Valid algorithm names are B<ed25519>, B<ed448> and B<eddsa>. If B<eddsa> is
-specified, then both Ed25519 and Ed448 are benchmarked.
-
-=head1 EXAMPLES
-
-This example generates an B<ED25519> private key and writes it to standard
-output in PEM format:
-
- #include <openssl/evp.h>
- #include <openssl/pem.h>
- ...
- EVP_PKEY *pkey = NULL;
- EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL);
- EVP_PKEY_keygen_init(pctx);
- EVP_PKEY_keygen(pctx, &pkey);
- EVP_PKEY_CTX_free(pctx);
- PEM_write_PrivateKey(stdout, pkey, NULL, NULL, 0, NULL, NULL);
-
-=head1 SEE ALSO
-
-L<EVP_PKEY_CTX_new(3)>,
-L<EVP_PKEY_keygen(3)>,
-L<EVP_DigestSignInit(3)>,
-L<EVP_DigestVerifyInit(3)>,
-
-=head1 COPYRIGHT
-
-Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man7/OSSL_PROVIDER-FIPS.pod b/doc/man7/OSSL_PROVIDER-FIPS.pod
new file mode 100644
index 000000000000..58008ae59f19
--- /dev/null
+++ b/doc/man7/OSSL_PROVIDER-FIPS.pod
@@ -0,0 +1,419 @@
+=pod
+
+=head1 NAME
+
+OSSL_PROVIDER-FIPS - OpenSSL FIPS provider
+
+=head1 DESCRIPTION
+
+The OpenSSL FIPS provider is a special provider that conforms to the Federal
+Information Processing Standards (FIPS) specified in FIPS 140-2. This 'module'
+contains an approved set of cryptographic algorithms that is validated by an
+accredited testing laboratory.
+
+=head2 Properties
+
+The implementations in this provider specifically have these properties
+defined:
+
+=over 4
+
+=item "provider=fips"
+
+=item "fips=yes"
+
+=back
+
+It may be used in a property query string with fetching functions such as
+L<EVP_MD_fetch(3)> or L<EVP_CIPHER_fetch(3)>, as well as with other
+functions that take a property query string, such as
+L<EVP_PKEY_CTX_new_from_name(3)>.
+
+It isn't mandatory to query for any of these properties, except to
+make sure to get implementations of this provider and none other.
+
+The "fips=yes" property can be use to make sure only FIPS approved
+implementations are used for crypto operations. This may also include
+other non-crypto support operations that are not in the FIPS provider,
+such as asymmetric key encoders,
+see L<OSSL_PROVIDER-default(7)/Asymmetric Key Management>.
+
+=head1 OPERATIONS AND ALGORITHMS
+
+The OpenSSL FIPS provider supports these operations and algorithms:
+
+=head2 Hashing Algorithms / Message Digests
+
+=over 4
+
+=item SHA1, see L<EVP_MD-SHA1(7)>
+
+=item SHA2, see L<EVP_MD-SHA2(7)>
+
+=item SHA3, see L<EVP_MD-SHA3(7)>
+
+=item KECCAK-KMAC, see L<EVP_MD-KECCAK-KMAC(7)>
+
+=back
+
+=head2 Symmetric Ciphers
+
+=over 4
+
+=item AES, see L<EVP_CIPHER-AES(7)>
+
+=item DES-EDE3 (TripleDES), see L<EVP_CIPHER-DES(7)>
+
+=back
+
+=head2 Message Authentication Code (MAC)
+
+=over 4
+
+=item CMAC, see L<EVP_MAC-CMAC(7)>
+
+=item GMAC, see L<EVP_MAC-GMAC(7)>
+
+=item HMAC, see L<EVP_MAC-HMAC(7)>
+
+=item KMAC, see L<EVP_MAC-KMAC(7)>
+
+=back
+
+=head2 Key Derivation Function (KDF)
+
+=over 4
+
+=item HKDF, see L<EVP_KDF-HKDF(7)>
+
+=item TLS13-KDF, see L<EVP_KDF-TLS13_KDF(7)>
+
+=item SSKDF, see L<EVP_KDF-SS(7)>
+
+=item PBKDF2, see L<EVP_KDF-PBKDF2(7)>
+
+=item SSHKDF, see L<EVP_KDF-SSHKDF(7)>
+
+=item TLS1-PRF, see L<EVP_KDF-TLS1_PRF(7)>
+
+=item KBKDF, see L<EVP_KDF-KB(7)>
+
+=item X942KDF-ASN1, see L<EVP_KDF-X942-ASN1(7)>
+
+=item X942KDF-CONCAT, see L<EVP_KDF-X942-CONCAT(7)>
+
+=item X963KDF, see L<EVP_KDF-X963(7)>
+
+=back
+
+=head2 Key Exchange
+
+=over 4
+
+=item DH, see L<EVP_KEYEXCH-DH(7)>
+
+=item ECDH, see L<EVP_KEYEXCH-ECDH(7)>
+
+=item X25519, see L<EVP_KEYEXCH-X25519(7)>
+
+=item X448, see L<EVP_KEYEXCH-X448(7)>
+
+=back
+
+=head2 Asymmetric Signature
+
+=over 4
+
+=item RSA, see L<EVP_SIGNATURE-RSA(7)>
+
+=item X25519, see L<EVP_SIGNATURE-ED25519(7)>
+
+=item X448, see L<EVP_SIGNATURE-ED448(7)>
+
+=item HMAC, see L<EVP_SIGNATURE-HMAC(7)>
+
+=item CMAC, see L<EVP_SIGNATURE-CMAC(7)>
+
+=back
+
+=head2 Asymmetric Cipher
+
+=over 4
+
+=item RSA, see L<EVP_ASYM_CIPHER-RSA(7)>
+
+=back
+
+=head2 Asymmetric Key Encapsulation
+
+=over 4
+
+=item RSA, see L<EVP_KEM-RSA(7)>
+
+=back
+
+=head2 Asymmetric Key Management
+
+=over 4
+
+=item DH, see L<EVP_KEYMGMT-DH(7)>
+
+=item DHX, see L<EVP_KEYMGMT-DHX(7)>
+
+=item DSA, see L<EVP_KEYMGMT-DSA(7)>
+
+=item RSA, see L<EVP_KEYMGMT-RSA(7)>
+
+=item EC, see L<EVP_KEYMGMT-EC(7)>
+
+=item X25519, see L<EVP_KEYMGMT-X25519(7)>
+
+=item X448, see L<EVP_KEYMGMT-X448(7)>
+
+=back
+
+=head1 SELF TESTING
+
+One of the requirements for the FIPS module is self testing. An optional callback
+mechanism is available to return information to the user using
+L<OSSL_SELF_TEST_set_callback(3)>.
+
+The parameters passed to the callback are described in L<OSSL_SELF_TEST_new(3)>
+
+The OpenSSL FIPS module uses the following mechanism to provide information
+about the self tests as they run.
+This is useful for debugging if a self test is failing.
+The callback also allows forcing any self test to fail, in order to check that
+it operates correctly on failure.
+Note that all self tests run even if a self test failure occurs.
+
+The FIPS module passes the following type(s) to OSSL_SELF_TEST_onbegin().
+
+=over 4
+
+=item "Module_Integrity" (B<OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY>)
+
+Uses HMAC SHA256 on the module file to validate that the module has not been
+modified. The integrity value is compared to a value written to a configuration
+file during installation.
+
+=item "Install_Integrity" (B<OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY>)
+
+Uses HMAC SHA256 on a fixed string to validate that the installation process
+has already been performed and the self test KATS have already been tested,
+The integrity value is compared to a value written to a configuration
+file after successfully running the self tests during installation.
+
+=item "KAT_Cipher" (B<OSSL_SELF_TEST_TYPE_KAT_CIPHER>)
+
+Known answer test for a symmetric cipher.
+
+=item "KAT_AsymmetricCipher" (B<OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER>)
+
+Known answer test for a asymmetric cipher.
+
+=item "KAT_Digest" (B<OSSL_SELF_TEST_TYPE_KAT_DIGEST>)
+
+Known answer test for a digest.
+
+=item "KAT_Signature" (B<OSSL_SELF_TEST_TYPE_KAT_SIGNATURE>)
+
+Known answer test for a signature.
+
+=item "PCT_Signature" (B<OSSL_SELF_TEST_TYPE_PCT_SIGNATURE>)
+
+Pairwise Consistency check for a signature.
+
+=item "KAT_KDF" (B<OSSL_SELF_TEST_TYPE_KAT_KDF>)
+
+Known answer test for a key derivation function.
+
+=item "KAT_KA" (B<OSSL_SELF_TEST_TYPE_KAT_KA>)
+
+Known answer test for key agreement.
+
+=item "DRBG" (B<OSSL_SELF_TEST_TYPE_DRBG>)
+
+Known answer test for a Deterministic Random Bit Generator.
+
+=item "Conditional_PCT" (B<OSSL_SELF_TEST_TYPE_PCT>)
+
+Conditional test that is run during the generation of key pairs.
+
+=item "Continuous_RNG_Test" (B<OSSL_SELF_TEST_TYPE_CRNG>)
+
+Continuous random number generator test.
+
+=back
+
+The "Module_Integrity" self test is always run at startup.
+The "Install_Integrity" self test is used to check if the self tests have
+already been run at installation time. If they have already run then the
+self tests are not run on subsequent startups.
+All other self test categories are run once at installation time, except for the
+"Pairwise_Consistency_Test".
+
+There is only one instance of the "Module_Integrity" and "Install_Integrity"
+self tests. All other self tests may have multiple instances.
+
+
+The FIPS module passes the following descriptions(s) to OSSL_SELF_TEST_onbegin().
+
+=over 4
+
+=item "HMAC" (B<OSSL_SELF_TEST_DESC_INTEGRITY_HMAC>)
+
+"Module_Integrity" and "Install_Integrity" use this.
+
+=item "RSA" (B<OSSL_SELF_TEST_DESC_PCT_RSA_PKCS1>)
+
+=item "ECDSA" (B<OSSL_SELF_TEST_DESC_PCT_ECDSA>)
+
+=item "DSA" (B<OSSL_SELF_TEST_DESC_PCT_DSA>)
+
+Key generation tests used with the "Pairwise_Consistency_Test" type.
+
+=item "RSA_Encrypt" (B<OSSL_SELF_TEST_DESC_ASYM_RSA_ENC>)
+
+=item "RSA_Decrypt" (B<OSSL_SELF_TEST_DESC_ASYM_RSA_DEC>)
+
+"KAT_AsymmetricCipher" uses this to indicate an encrypt or decrypt KAT.
+
+=item "AES_GCM" (B<OSSL_SELF_TEST_DESC_CIPHER_AES_GCM>)
+
+=item "AES_ECB_Decrypt" (B<OSSL_SELF_TEST_DESC_CIPHER_AES_ECB>)
+
+=item "TDES" (B<OSSL_SELF_TEST_DESC_CIPHER_TDES>)
+
+Symmetric cipher tests used with the "KAT_Cipher" type.
+
+=item "SHA1" (B<OSSL_SELF_TEST_DESC_MD_SHA1>)
+
+=item "SHA2" (B<OSSL_SELF_TEST_DESC_MD_SHA2>)
+
+=item "SHA3" (B<OSSL_SELF_TEST_DESC_MD_SHA3>)
+
+Digest tests used with the "KAT_Digest" type.
+
+=item "DSA" (B<OSSL_SELF_TEST_DESC_SIGN_DSA>)
+
+=item "RSA" (B<OSSL_SELF_TEST_DESC_SIGN_RSA>)
+
+=item "ECDSA" (B<OSSL_SELF_TEST_DESC_SIGN_ECDSA>)
+
+Signature tests used with the "KAT_Signature" type.
+
+=item "ECDH" (B<OSSL_SELF_TEST_DESC_KA_ECDH>)
+
+=item "DH" (B<OSSL_SELF_TEST_DESC_KA_DH>)
+
+Key agreement tests used with the "KAT_KA" type.
+
+=item "HKDF" (B<OSSL_SELF_TEST_DESC_KDF_HKDF>)
+
+=item "TLS13_KDF_EXTRACT" (B<OSSL_SELF_TEST_DESC_KDF_TLS13_EXTRACT>)
+
+=item "TLS13_KDF_EXPAND" (B<OSSL_SELF_TEST_DESC_KDF_TLS13_EXPAND>)
+
+=item "SSKDF" (B<OSSL_SELF_TEST_DESC_KDF_SSKDF>)
+
+=item "X963KDF" (B<OSSL_SELF_TEST_DESC_KDF_X963KDF>)
+
+=item "X942KDF" (B<OSSL_SELF_TEST_DESC_KDF_X942KDF>)
+
+=item "PBKDF2" (B<OSSL_SELF_TEST_DESC_KDF_PBKDF2>)
+
+=item "SSHKDF" (B<OSSL_SELF_TEST_DESC_KDF_SSHKDF>)
+
+=item "TLS12_PRF" (B<OSSL_SELF_TEST_DESC_KDF_TLS12_PRF>)
+
+=item "KBKDF" (B<OSSL_SELF_TEST_DESC_KDF_KBKDF>)
+
+Key Derivation Function tests used with the "KAT_KDF" type.
+
+=item "CTR" (B<OSSL_SELF_TEST_DESC_DRBG_CTR>)
+
+=item "HASH" (B<OSSL_SELF_TEST_DESC_DRBG_HASH>)
+
+=item "HMAC" (B<OSSL_SELF_TEST_DESC_DRBG_HMAC>)
+
+DRBG tests used with the "DRBG" type.
+
+= item "RNG" (B<OSSL_SELF_TEST_DESC_RNG>)
+
+"Continuous_RNG_Test" uses this.
+
+=back
+
+=head1 EXAMPLES
+
+A simple self test callback is shown below for illustrative purposes.
+
+ #include <openssl/self_test.h>
+
+ static OSSL_CALLBACK self_test_cb;
+
+ static int self_test_cb(const OSSL_PARAM params[], void *arg)
+ {
+ int ret = 0;
+ const OSSL_PARAM *p = NULL;
+ const char *phase = NULL, *type = NULL, *desc = NULL;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_PHASE);
+ if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
+ goto err;
+ phase = (const char *)p->data;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_DESC);
+ if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
+ goto err;
+ desc = (const char *)p->data;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_TYPE);
+ if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
+ goto err;
+ type = (const char *)p->data;
+
+ /* Do some logging */
+ if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0)
+ BIO_printf(bio_out, "%s : (%s) : ", desc, type);
+ if (strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0
+ || strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0)
+ BIO_printf(bio_out, "%s\n", phase);
+
+ /* Corrupt the SHA1 self test during the 'corrupt' phase by returning 0 */
+ if (strcmp(phase, OSSL_SELF_TEST_PHASE_CORRUPT) == 0
+ && strcmp(desc, OSSL_SELF_TEST_DESC_MD_SHA1) == 0) {
+ BIO_printf(bio_out, "%s %s", phase, desc);
+ return 0;
+ }
+ ret = 1;
+ err:
+ return ret;
+ }
+
+=head1 SEE ALSO
+
+L<openssl-fipsinstall(1)>,
+L<fips_config(5)>,
+L<OSSL_SELF_TEST_set_callback(3)>,
+L<OSSL_SELF_TEST_new(3)>,
+L<OSSL_PARAM(3)>,
+L<openssl-core.h(7)>,
+L<openssl-core_dispatch.h(7)>,
+L<provider(7)>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/OSSL_PROVIDER-base.pod b/doc/man7/OSSL_PROVIDER-base.pod
new file mode 100644
index 000000000000..c51adbde1e97
--- /dev/null
+++ b/doc/man7/OSSL_PROVIDER-base.pod
@@ -0,0 +1,100 @@
+=pod
+
+=head1 NAME
+
+OSSL_PROVIDER-base - OpenSSL base provider
+
+=head1 DESCRIPTION
+
+The OpenSSL base provider supplies the encoding for OpenSSL's
+asymmetric cryptography.
+
+=head2 Properties
+
+The implementations in this provider specifically have this property
+defined:
+
+=over 4
+
+=item "provider=base"
+
+=back
+
+It may be used in a property query string with fetching functions.
+
+It isn't mandatory to query for this property, except to make sure to get
+implementations of this provider and none other.
+
+=over 4
+
+=item "type=parameters"
+
+=item "type=private"
+
+=item "type=public"
+
+=back
+
+These may be used in a property query string with fetching functions to select
+which data are to be encoded. Either the private key material, the public
+key material or the domain parameters can be selected.
+
+=over 4
+
+=item "format=der"
+
+=item "format=pem"
+
+=item "format=text"
+
+=back
+
+These may be used in a property query string with fetching functions to select
+the encoding output format. Either the DER, PEM and plaintext are
+currently permitted.
+
+=head1 OPERATIONS AND ALGORITHMS
+
+The OpenSSL base provider supports these operations and algorithms:
+
+=head2 Asymmetric Key Encoder
+
+In addition to "provider=base", some of these encoders define the
+property "fips=yes", to allow them to be used together with the FIPS
+provider.
+
+=over 4
+
+=item RSA, see L<OSSL_ENCODER-RSA(7)>
+
+=item DH, see L<OSSL_ENCODER-DH(7)>
+
+=item DSA, see L<OSSL_ENCODER-DSA(7)>
+
+=item EC, see L<OSSL_ENCODER-EC(7)>
+
+=item X25519, see L<OSSL_ENCODER-X25519(7)>
+
+=item X448, see L<OSSL_ENCODER-X448(7)>
+
+=back
+
+=head1 SEE ALSO
+
+L<OSSL_PROVIDER-default(7)>, L<openssl-core.h(7)>,
+L<openssl-core_dispatch.h(7)>, L<provider(7)>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/OSSL_PROVIDER-default.pod b/doc/man7/OSSL_PROVIDER-default.pod
new file mode 100644
index 000000000000..43ba0ef02d52
--- /dev/null
+++ b/doc/man7/OSSL_PROVIDER-default.pod
@@ -0,0 +1,261 @@
+=pod
+
+=head1 NAME
+
+OSSL_PROVIDER-default - OpenSSL default provider
+
+=head1 DESCRIPTION
+
+The OpenSSL default provider supplies the majority of OpenSSL's diverse
+algorithm implementations. If an application doesn't specify anything else
+explicitly (e.g. in the application or via config), then this is the
+provider that will be used as fallback: It is loaded automatically the
+first time that an algorithm is fetched from a provider or a function
+acting on providers is called and no other provider has been loaded yet.
+
+If an attempt to load a provider has already been made (whether successful
+or not) then the default provider won't be loaded automatically. Therefore
+if the default provider is to be used in conjunction with other providers
+then it must be loaded explicitly. Automatic loading of the default
+provider only occurs a maximum of once; if the default provider is
+explicitly unloaded then the default provider will not be automatically
+loaded again.
+
+=head2 Properties
+
+The implementations in this provider specifically have this property
+defined:
+
+=over 4
+
+=item "provider=default"
+
+=back
+
+It may be used in a property query string with fetching functions such as
+L<EVP_MD_fetch(3)> or L<EVP_CIPHER_fetch(3)>, as well as with other
+functions that take a property query string, such as
+L<EVP_PKEY_CTX_new_from_name(3)>.
+
+It isn't mandatory to query for this property, except to make sure to get
+implementations of this provider and none other.
+
+Some implementations may define additional properties. Exact information is
+listed below
+
+=head1 OPERATIONS AND ALGORITHMS
+
+The OpenSSL default provider supports these operations and algorithms:
+
+=head2 Hashing Algorithms / Message Digests
+
+=over 4
+
+=item SHA1, see L<EVP_MD-SHA1(7)>
+
+=item SHA2, see L<EVP_MD-SHA2(7)>
+
+=item SHA3, see L<EVP_MD-SHA3(7)>
+
+=item KECCAK-KMAC, see L<EVP_MD-KECCAK-KMAC(7)>
+
+=item SHAKE, see L<EVP_MD-SHAKE(7)>
+
+=item BLAKE2, see L<EVP_MD-BLAKE2(7)>
+
+=item SM3, see L<EVP_MD-SM3(7)>
+
+=item MD5, see L<EVP_MD-MD5(7)>
+
+=item MD5-SHA1, see L<EVP_MD-MD5-SHA1(7)>
+
+=item RIPEMD160, see L<EVP_MD-RIPEMD160(7)>
+
+=back
+
+=head2 Symmetric Ciphers
+
+=over 4
+
+=item AES, see L<EVP_CIPHER-AES(7)>
+
+=item ARIA, see L<EVP_CIPHER-ARIA(7)>
+
+=item CAMELLIA, see L<EVP_CIPHER-CAMELLIA(7)>
+
+=item 3DES, see L<EVP_CIPHER-DES(7)>
+
+=item SEED, see L<EVP_CIPHER-SEED(7)>
+
+=item SM4, see L<EVP_CIPHER-SM4(7)>
+
+=item ChaCha20, see L<EVP_CIPHER-CHACHA(7)>
+
+=item ChaCha20-Poly1305, see L<EVP_CIPHER-CHACHA(7)>
+
+=back
+
+=head2 Message Authentication Code (MAC)
+
+=over 4
+
+=item BLAKE2, see L<EVP_MAC-BLAKE2(7)>
+
+=item CMAC, see L<EVP_MAC-CMAC(7)>
+
+=item GMAC, see L<EVP_MAC-GMAC(7)>
+
+=item HMAC, see L<EVP_MAC-HMAC(7)>
+
+=item KMAC, see L<EVP_MAC-KMAC(7)>
+
+=item SIPHASH, see L<EVP_MAC-Siphash(7)>
+
+=item POLY1305, see L<EVP_MAC-Poly1305(7)>
+
+=back
+
+=head2 Key Derivation Function (KDF)
+
+=over 4
+
+=item HKDF, see L<EVP_KDF-HKDF(7)>
+
+=item SSKDF, see L<EVP_KDF-SS(7)>
+
+=item PBKDF2, see L<EVP_KDF-PBKDF2(7)>
+
+=item PKCS12KDF, see L<EVP_KDF-PKCS12KDF(7)>
+
+=item SSHKDF, see L<EVP_KDF-SSHKDF(7)>
+
+=item TLS1-PRF, see L<EVP_KDF-TLS1_PRF(7)>
+
+=item KBKDF, see L<EVP_KDF-KB(7)>
+
+=item X942KDF-ASN1, see L<EVP_KDF-X942-ASN1(7)>
+
+=item X942KDF-CONCAT, see L<EVP_KDF-X942-CONCAT(7)>
+
+=item X963KDF, see L<EVP_KDF-X963(7)>
+
+=item SCRYPT, see L<EVP_KDF-SCRYPT(7)>
+
+=item KRB5KDF, see L<EVP_KDF-KRB5KDF(7)>
+
+
+=back
+
+=head2 Key Exchange
+
+=over 4
+
+=item DH, see L<EVP_KEYEXCH-DH(7)>
+
+=item ECDH, see L<EVP_KEYEXCH-ECDH(7)>
+
+=item X25519, see L<EVP_KEYEXCH-X25519(7)>
+
+=item X448, see L<EVP_KEYEXCH-X448(7)>
+
+=back
+
+=head2 Asymmetric Signature
+
+=over 4
+
+=item DSA, see L<EVP_SIGNATURE-DSA(7)>
+
+=item RSA, see L<EVP_SIGNATURE-RSA(7)>
+
+=item HMAC, see L<EVP_SIGNATURE-HMAC(7)>
+
+=item SIPHASH, see L<EVP_SIGNATURE-Siphash(7)>
+
+=item POLY1305, see L<EVP_SIGNATURE-Poly1305(7)>
+
+=item CMAC, see L<EVP_SIGNATURE-CMAC(7)>
+
+=back
+
+=head2 Asymmetric Cipher
+
+=over 4
+
+=item RSA, see L<EVP_ASYM_CIPHER-RSA(7)>
+
+=item SM2, see L<EVP_ASYM_CIPHER-SM2(7)>
+
+=back
+
+=head2 Asymmetric Key Encapsulation
+
+=over 4
+
+=item RSA, see L<EVP_KEM-RSA(7)>
+
+=back
+
+=head2 Asymmetric Key Management
+
+=over 4
+
+=item DH, see L<EVP_KEYMGMT-DH(7)>
+
+=item DHX, see L<EVP_KEYMGMT-DHX(7)>
+
+=item DSA, see L<EVP_KEYMGMT-DSA(7)>
+
+=item RSA, see L<EVP_KEYMGMT-RSA(7)>
+
+=item EC, see L<EVP_KEYMGMT-EC(7)>
+
+=item X25519, see L<EVP_KEYMGMT-X25519(7)>
+
+=item X448, see L<EVP_KEYMGMT-X448(7)>
+
+=back
+
+=head2 Asymmetric Key Encoder
+
+The default provider also includes all of the encoding algorithms
+present in the base provider. Some of these have the property "fips=yes",
+to allow them to be used together with the FIPS provider.
+
+=over 4
+
+=item RSA, see L<OSSL_ENCODER-RSA(7)>
+
+=item DH, see L<OSSL_ENCODER-DH(7)>
+
+=item DSA, see L<OSSL_ENCODER-DSA(7)>
+
+=item EC, see L<OSSL_ENCODER-EC(7)>
+
+=item X25519, see L<OSSL_ENCODER-X25519(7)>
+
+=item X448, see L<OSSL_ENCODER-X448(7)>
+
+=back
+
+=head1 SEE ALSO
+
+L<openssl-core.h(7)>, L<openssl-core_dispatch.h(7)>, L<provider(7)>,
+L<OSSL_PROVIDER-base(7)>
+
+=head1 HISTORY
+
+The RIPEMD160 digest was added to the default provider in OpenSSL 3.0.7.
+
+All other functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/OSSL_PROVIDER-legacy.pod b/doc/man7/OSSL_PROVIDER-legacy.pod
new file mode 100644
index 000000000000..f10827de7baa
--- /dev/null
+++ b/doc/man7/OSSL_PROVIDER-legacy.pod
@@ -0,0 +1,131 @@
+=pod
+
+=head1 NAME
+
+OSSL_PROVIDER-legacy - OpenSSL legacy provider
+
+=head1 DESCRIPTION
+
+The OpenSSL legacy provider supplies OpenSSL implementations of algorithms
+that have been deemed legacy. Such algorithms have commonly fallen out of
+use, have been deemed insecure by the cryptography community, or something
+similar.
+
+We can consider this the retirement home of cryptographic algorithms.
+
+=head2 Properties
+
+The implementations in this provider specifically has this property
+defined:
+
+=over 4
+
+=item "provider=legacy"
+
+=back
+
+It may be used in a property query string with fetching functions such as
+L<EVP_MD_fetch(3)> or L<EVP_CIPHER_fetch(3)>, as well as with other
+functions that take a property query string, such as
+L<EVP_PKEY_CTX_new_from_name(3)>.
+
+It isn't mandatory to query for any of these properties, except to
+make sure to get implementations of this provider and none other.
+
+=head1 OPERATIONS AND ALGORITHMS
+
+The OpenSSL legacy provider supports these operations and algorithms:
+
+=head2 Hashing Algorithms / Message Digests
+
+=over 4
+
+=item MD2, see L<EVP_MD-MD2(7)>
+
+=item MD4, see L<EVP_MD-MD4(7)>
+
+=item MDC2, see L<EVP_MD-MDC2(7)>
+
+=item WHIRLPOOL, see L<EVP_MD-WHIRLPOOL(7)>
+
+=item RIPEMD160, see L<EVP_MD-RIPEMD160(7)>
+
+=back
+
+=head2 Symmetric Ciphers
+
+Not all of these symmetric cipher algorithms are enabled by default.
+
+=over 4
+
+=item Blowfish, see L<EVP_CIPHER-BLOWFISH(7)>
+
+=item CAST, see L<EVP_CIPHER-CAST(7)>
+
+=item DES, see L<EVP_CIPHER-DES(7)>
+
+The algorithm names are: DES_ECB, DES_CBC, DES_OFB, DES_CFB, DES_CFB1, DES_CFB8
+and DESX_CBC.
+
+=item IDEA, see L<EVP_CIPHER-IDEA(7)>
+
+=item RC2, see L<EVP_CIPHER-RC2(7)>
+
+=item RC4, see L<EVP_CIPHER-RC4(7)>
+
+=item RC5, see L<EVP_CIPHER-RC5(7)>
+
+Disabled by default. Use I<enable-rc5> config option to enable.
+
+=item SEED, see L<EVP_CIPHER-SEED(7)>
+
+=back
+
+=head2 Key Derivation Function (KDF)
+
+=over 4
+
+=item PBKDF1
+
+=back
+
+=begin comment
+
+When algorithms for other operations start appearing, the
+following =head2 titles are appropriate to use:
+
+- Message Authentication Code (MAC)
+
+- Key Derivation Function (KDF)
+
+- Key Exchange
+
+- Signature
+
+- Asymmetric Cipher
+
+- Asymmetric Key Management
+
+=end comment
+
+=head1 SEE ALSO
+
+L<OSSL_PARAM(3)>,
+L<openssl-core.h(7)>,
+L<openssl-core_dispatch.h(7)>,
+L<provider(7)>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/OSSL_PROVIDER-null.pod b/doc/man7/OSSL_PROVIDER-null.pod
new file mode 100644
index 000000000000..618ca1df1892
--- /dev/null
+++ b/doc/man7/OSSL_PROVIDER-null.pod
@@ -0,0 +1,39 @@
+=pod
+
+=head1 NAME
+
+OSSL_PROVIDER-null - OpenSSL null provider
+
+=head1 DESCRIPTION
+
+The OpenSSL null provider supplies no algorithms.
+
+It can used to guarantee that the default library context and a fallback
+provider will not be accidentally accessed.
+
+=head2 Properties
+
+The null provider defines no properties.
+
+=head1 OPERATIONS AND ALGORITHMS
+
+The OpenSSL null provider supports no operations and algorithms.
+
+=head1 SEE ALSO
+
+L<provider(7)>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/RAND.pod b/doc/man7/RAND.pod
index 7ce44ad9b6bd..c4a630856c58 100644
--- a/doc/man7/RAND.pod
+++ b/doc/man7/RAND.pod
@@ -33,11 +33,12 @@ is available or the trusted source(s) temporarily fail to provide sufficient
random seed material.
In this case the CSPRNG enters an error state and ceases to provide output,
until it is able to recover from the error by reseeding itself.
-For more details on reseeding and error recovery, see L<RAND_DRBG(7)>.
+For more details on reseeding and error recovery, see L<EVP_RAND(7)>.
For values that should remain secret, you can use L<RAND_priv_bytes(3)>
instead.
-This method does not provide 'better' randomness, it uses the same type of CSPRNG.
+This method does not provide 'better' randomness, it uses the same type of
+CSPRNG.
The intention behind using a dedicated CSPRNG exclusively for private
values is that none of its output should be visible to an attacker (e.g.,
used as salt value), in order to reveal as little information as
@@ -45,41 +46,35 @@ possible about its internal state, and that a compromise of the "public"
CSPRNG instance will not affect the secrecy of these private values.
In the rare case where the default implementation does not satisfy your special
-requirements, there are two options:
+requirements, the default RAND internals can be replaced by your own
+L<EVP_RAND(3)> objects.
-=over 2
+Changing the default random generator should be necessary
+only in exceptional cases and is not recommended, unless you have a profound
+knowledge of cryptographic principles and understand the implications of your
+changes.
-=item *
+=head1 DEFAULT SETUP
-Replace the default RAND method by your own RAND method using
-L<RAND_set_rand_method(3)>.
+The default OpenSSL RAND method is based on the EVP_RAND deterministic random
+bit generator (DRBG) classes.
+A DRBG is a certain type of cryptographically-secure pseudo-random
+number generator (CSPRNG), which is described in [NIST SP 800-90A Rev. 1].
-=item *
-
-Modify the default settings of the OpenSSL RAND method by modifying the security
-parameters of the underlying DRBG, which is described in detail in L<RAND_DRBG(7)>.
-
-=back
-
-Changing the default random generator or its default parameters should be necessary
-only in exceptional cases and is not recommended, unless you have a profound knowledge
-of cryptographic principles and understand the implications of your changes.
=head1 SEE ALSO
-L<RAND_add(3)>,
L<RAND_bytes(3)>,
L<RAND_priv_bytes(3)>,
-L<RAND_get_rand_method(3)>,
-L<RAND_set_rand_method(3)>,
-L<RAND_OpenSSL(3)>,
-L<RAND_DRBG(7)>
+L<EVP_RAND(3)>,
+L<RAND_get0_primary(3)>,
+L<EVP_RAND(7)>
=head1 COPYRIGHT
-Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man7/RAND_DRBG.pod b/doc/man7/RAND_DRBG.pod
deleted file mode 100644
index ba457f050483..000000000000
--- a/doc/man7/RAND_DRBG.pod
+++ /dev/null
@@ -1,301 +0,0 @@
-=pod
-
-=head1 NAME
-
-RAND_DRBG - the deterministic random bit generator
-
-=head1 SYNOPSIS
-
- #include <openssl/rand_drbg.h>
-
-=head1 DESCRIPTION
-
-The default OpenSSL RAND method is based on the RAND_DRBG class,
-which implements a deterministic random bit generator (DRBG).
-A DRBG is a certain type of cryptographically-secure pseudo-random
-number generator (CSPRNG), which is described in
-[NIST SP 800-90A Rev. 1].
-
-While the RAND API is the 'frontend' which is intended to be used by
-application developers for obtaining random bytes, the RAND_DRBG API
-serves as the 'backend', connecting the former with the operating
-systems's entropy sources and providing access to the DRBG's
-configuration parameters.
-
-=head2 Disclaimer
-
-Unless you have very specific requirements for your random generator,
-it is in general not necessary to utilize the RAND_DRBG API directly.
-The usual way to obtain random bytes is to use L<RAND_bytes(3)> or
-L<RAND_priv_bytes(3)>, see also L<RAND(7)>.
-
-=head2 Typical Use Cases
-
-Typical examples for such special use cases are the following:
-
-=over 2
-
-=item *
-
-You want to use your own private DRBG instances.
-Multiple DRBG instances which are accessed only by a single thread provide
-additional security (because their internal states are independent) and
-better scalability in multithreaded applications (because they don't need
-to be locked).
-
-=item *
-
-You need to integrate a previously unsupported entropy source.
-
-=item *
-
-You need to change the default settings of the standard OpenSSL RAND
-implementation to meet specific requirements.
-
-=back
-
-
-=head1 CHAINING
-
-A DRBG instance can be used as the entropy source of another DRBG instance,
-provided it has itself access to a valid entropy source.
-The DRBG instance which acts as entropy source is called the I<parent> DRBG,
-the other instance the I<child> DRBG.
-
-This is called chaining. A chained DRBG instance is created by passing
-a pointer to the parent DRBG as argument to the RAND_DRBG_new() call.
-It is possible to create chains of more than two DRBG in a row.
-
-=head1 THE THREE SHARED DRBG INSTANCES
-
-Currently, there are three shared DRBG instances,
-the <master>, <public>, and <private> DRBG.
-While the <master> DRBG is a single global instance, the <public> and <private>
-DRBG are created per thread and accessed through thread-local storage.
-
-By default, the functions L<RAND_bytes(3)> and L<RAND_priv_bytes(3)> use
-the thread-local <public> and <private> DRBG instance, respectively.
-
-=head2 The <master> DRBG instance
-
-The <master> DRBG is not used directly by the application, only for reseeding
-the two other two DRBG instances. It reseeds itself by obtaining randomness
-either from os entropy sources or by consuming randomness which was added
-previously by L<RAND_add(3)>.
-
-=head2 The <public> DRBG instance
-
-This instance is used per default by L<RAND_bytes(3)>.
-
-=head2 The <private> DRBG instance
-
-This instance is used per default by L<RAND_priv_bytes(3)>
-
-
-=head1 LOCKING
-
-The <master> DRBG is intended to be accessed concurrently for reseeding
-by its child DRBG instances. The necessary locking is done internally.
-It is I<not> thread-safe to access the <master> DRBG directly via the
-RAND_DRBG interface.
-The <public> and <private> DRBG are thread-local, i.e. there is an
-instance of each per thread. So they can safely be accessed without
-locking via the RAND_DRBG interface.
-
-Pointers to these DRBG instances can be obtained using
-RAND_DRBG_get0_master(),
-RAND_DRBG_get0_public(), and
-RAND_DRBG_get0_private(), respectively.
-Note that it is not allowed to store a pointer to one of the thread-local
-DRBG instances in a variable or other memory location where it will be
-accessed and used by multiple threads.
-
-All other DRBG instances created by an application don't support locking,
-because they are intended to be used by a single thread.
-Instead of accessing a single DRBG instance concurrently from different
-threads, it is recommended to instantiate a separate DRBG instance per
-thread. Using the <master> DRBG as entropy source for multiple DRBG
-instances on different threads is thread-safe, because the DRBG instance
-will lock the <master> DRBG automatically for obtaining random input.
-
-=head1 THE OVERALL PICTURE
-
-The following picture gives an overview over how the DRBG instances work
-together and are being used.
-
- +--------------------+
- | os entropy sources |
- +--------------------+
- |
- v +-----------------------------+
- RAND_add() ==> <master> <-| shared DRBG (with locking) |
- / \ +-----------------------------+
- / \ +---------------------------+
- <public> <private> <- | per-thread DRBG instances |
- | | +---------------------------+
- v v
- RAND_bytes() RAND_priv_bytes()
- | ^
- | |
- +------------------+ +------------------------------------+
- | general purpose | | used for secrets like session keys |
- | random generator | | and private keys for certificates |
- +------------------+ +------------------------------------+
-
-
-The usual way to obtain random bytes is to call RAND_bytes(...) or
-RAND_priv_bytes(...). These calls are roughly equivalent to calling
-RAND_DRBG_bytes(<public>, ...) and RAND_DRBG_bytes(<private>, ...),
-respectively. The method L<RAND_DRBG_bytes(3)> is a convenience method
-wrapping the L<RAND_DRBG_generate(3)> function, which serves the actual
-request for random data.
-
-=head1 RESEEDING
-
-A DRBG instance seeds itself automatically, pulling random input from
-its entropy source. The entropy source can be either a trusted operating
-system entropy source, or another DRBG with access to such a source.
-
-Automatic reseeding occurs after a predefined number of generate requests.
-The selection of the trusted entropy sources is configured at build
-time using the --with-rand-seed option. The following sections explain
-the reseeding process in more detail.
-
-=head2 Automatic Reseeding
-
-Before satisfying a generate request (L<RAND_DRBG_generate(3)>), the DRBG
-reseeds itself automatically, if one of the following conditions holds:
-
-- the DRBG was not instantiated (=seeded) yet or has been uninstantiated.
-
-- the number of generate requests since the last reseeding exceeds a
-certain threshold, the so called I<reseed_interval>.
-This behaviour can be disabled by setting the I<reseed_interval> to 0.
-
-- the time elapsed since the last reseeding exceeds a certain time
-interval, the so called I<reseed_time_interval>.
-This can be disabled by setting the I<reseed_time_interval> to 0.
-
-- the DRBG is in an error state.
-
-B<Note>: An error state is entered if the entropy source fails while
-the DRBG is seeding or reseeding.
-The last case ensures that the DRBG automatically recovers
-from the error as soon as the entropy source is available again.
-
-=head2 Manual Reseeding
-
-In addition to automatic reseeding, the caller can request an immediate
-reseeding of the DRBG with fresh entropy by setting the
-I<prediction resistance> parameter to 1 when calling L<RAND_DRBG_generate(3)>.
-
-The document [NIST SP 800-90C] describes prediction resistance requests
-in detail and imposes strict conditions on the entropy sources that are
-approved for providing prediction resistance.
-Since the default DRBG implementation does not have access to such an approved
-entropy source, a request for prediction resistance will currently always fail.
-In other words, prediction resistance is currently not supported yet by the DRBG.
-
-
-For the three shared DRBGs (and only for these) there is another way to
-reseed them manually:
-If L<RAND_add(3)> is called with a positive I<randomness> argument
-(or L<RAND_seed(3)>), then this will immediately reseed the <master> DRBG.
-The <public> and <private> DRBG will detect this on their next generate
-call and reseed, pulling randomness from <master>.
-
-The last feature has been added to support the common practice used with
-previous OpenSSL versions to call RAND_add() before calling RAND_bytes().
-
-
-=head2 Entropy Input vs. Additional Data
-
-The DRBG distinguishes two different types of random input: I<entropy>,
-which comes from a trusted source, and I<additional input>',
-which can optionally be added by the user and is considered untrusted.
-It is possible to add I<additional input> not only during reseeding,
-but also for every generate request.
-This is in fact done automatically by L<RAND_DRBG_bytes(3)>.
-
-
-=head2 Configuring the Random Seed Source
-
-In most cases OpenSSL will automatically choose a suitable seed source
-for automatically seeding and reseeding its <master> DRBG. In some cases
-however, it will be necessary to explicitly specify a seed source during
-configuration, using the --with-rand-seed option. For more information,
-see the INSTALL instructions. There are also operating systems where no
-seed source is available and automatic reseeding is disabled by default.
-
-The following two sections describe the reseeding process of the master
-DRBG, depending on whether automatic reseeding is available or not.
-
-
-=head2 Reseeding the master DRBG with automatic seeding enabled
-
-Calling RAND_poll() or RAND_add() is not necessary, because the DRBG
-pulls the necessary entropy from its source automatically.
-However, both calls are permitted, and do reseed the RNG.
-
-RAND_add() can be used to add both kinds of random input, depending on the
-value of the B<randomness> argument:
-
-=over 4
-
-=item randomness == 0:
-
-The random bytes are mixed as additional input into the current state of
-the DRBG.
-Mixing in additional input is not considered a full reseeding, hence the
-reseed counter is not reset.
-
-
-=item randomness > 0:
-
-The random bytes are used as entropy input for a full reseeding
-(resp. reinstantiation) if the DRBG is instantiated
-(resp. uninstantiated or in an error state).
-The number of random bits required for reseeding is determined by the
-security strength of the DRBG. Currently it defaults to 256 bits (32 bytes).
-It is possible to provide less randomness than required.
-In this case the missing randomness will be obtained by pulling random input
-from the trusted entropy sources.
-
-=back
-
-=head2 Reseeding the master DRBG with automatic seeding disabled
-
-Calling RAND_poll() will always fail.
-
-RAND_add() needs to be called for initial seeding and periodic reseeding.
-At least 48 bytes (384 bits) of randomness have to be provided, otherwise
-the (re-)seeding of the DRBG will fail. This corresponds to one and a half
-times the security strength of the DRBG. The extra half is used for the
-nonce during instantiation.
-
-More precisely, the number of bytes needed for seeding depend on the
-I<security strength> of the DRBG, which is set to 256 by default.
-
-=head1 SEE ALSO
-
-L<RAND_DRBG_bytes(3)>,
-L<RAND_DRBG_generate(3)>,
-L<RAND_DRBG_reseed(3)>,
-L<RAND_DRBG_get0_master(3)>,
-L<RAND_DRBG_get0_public(3)>,
-L<RAND_DRBG_get0_private(3)>,
-L<RAND_DRBG_set_reseed_interval(3)>,
-L<RAND_DRBG_set_reseed_time_interval(3)>,
-L<RAND_DRBG_set_reseed_defaults(3)>,
-L<RAND(7)>,
-
-=head1 COPYRIGHT
-
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man7/RSA-PSS.pod b/doc/man7/RSA-PSS.pod
index 29775d862103..a378121ac163 100644
--- a/doc/man7/RSA-PSS.pod
+++ b/doc/man7/RSA-PSS.pod
@@ -53,7 +53,7 @@ L<EVP_PKEY_derive(3)>
Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man7/SM2.pod b/doc/man7/SM2.pod
deleted file mode 100644
index 43786749b1eb..000000000000
--- a/doc/man7/SM2.pod
+++ /dev/null
@@ -1,79 +0,0 @@
-=pod
-
-=head1 NAME
-
-SM2 - Chinese SM2 signature and encryption algorithm support
-
-=head1 DESCRIPTION
-
-The B<SM2> algorithm was first defined by the Chinese national standard GM/T
-0003-2012 and was later standardized by ISO as ISO/IEC 14888. B<SM2> is actually
-an elliptic curve based algorithm. The current implementation in OpenSSL supports
-both signature and encryption schemes via the EVP interface.
-
-When doing the B<SM2> signature algorithm, it requires a distinguishing identifier
-to form the message prefix which is hashed before the real message is hashed.
-
-=head1 NOTES
-
-B<SM2> signatures can be generated by using the 'DigestSign' series of APIs, for
-instance, EVP_DigestSignInit(), EVP_DigestSignUpdate() and EVP_DigestSignFinal().
-Ditto for the verification process by calling the 'DigestVerify' series of APIs.
-
-There are several special steps that need to be done before computing an B<SM2>
-signature.
-
-The B<EVP_PKEY> structure will default to using ECDSA for signatures when it is
-created. It should be set to B<EVP_PKEY_SM2> by calling:
-
- EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2);
-
-Then an ID should be set by calling:
-
- EVP_PKEY_CTX_set1_id(pctx, id, id_len);
-
-When calling the EVP_DigestSignInit() or EVP_DigestVerifyInit() functions, a
-preallocated B<EVP_PKEY_CTX> should be assigned to the B<EVP_MD_CTX>. This is
-done by calling:
-
- EVP_MD_CTX_set_pkey_ctx(mctx, pctx);
-
-And normally there is no need to pass a B<pctx> parameter to EVP_DigestSignInit()
-or EVP_DigestVerifyInit() in such a scenario.
-
-=head1 EXAMPLES
-
-This example demonstrates the calling sequence for using an B<EVP_PKEY> to verify
-a message with the SM2 signature algorithm and the SM3 hash algorithm:
-
- #include <openssl/evp.h>
-
- /* obtain an EVP_PKEY using whatever methods... */
- EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2);
- mctx = EVP_MD_CTX_new();
- pctx = EVP_PKEY_CTX_new(pkey, NULL);
- EVP_PKEY_CTX_set1_id(pctx, id, id_len);
- EVP_MD_CTX_set_pkey_ctx(mctx, pctx);;
- EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, pkey);
- EVP_DigestVerifyUpdate(mctx, msg, msg_len);
- EVP_DigestVerifyFinal(mctx, sig, sig_len)
-
-=head1 SEE ALSO
-
-L<EVP_PKEY_CTX_new(3)>,
-L<EVP_PKEY_set_alias_type(3)>,
-L<EVP_DigestSignInit(3)>,
-L<EVP_DigestVerifyInit(3)>,
-L<EVP_PKEY_CTX_set1_id(3)>,
-L<EVP_MD_CTX_set_pkey_ctx(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man7/X25519.pod b/doc/man7/X25519.pod
index 6f153cb4b983..b599d2219b61 100644
--- a/doc/man7/X25519.pod
+++ b/doc/man7/X25519.pod
@@ -66,7 +66,7 @@ L<EVP_PKEY_derive_set_peer(3)>
Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man7/bio.pod b/doc/man7/bio.pod
index 23b231b44e35..9b86e9493d1c 100644
--- a/doc/man7/bio.pod
+++ b/doc/man7/bio.pod
@@ -6,7 +6,7 @@ bio - Basic I/O abstraction
=head1 SYNOPSIS
-=for comment generic
+=for openssl generic
#include <openssl/bio.h>
@@ -17,7 +17,7 @@ details from an application. If an application uses a BIO for its
I/O it can transparently handle SSL connections, unencrypted network
connections and file I/O.
-There are two type of BIO, a source/sink BIO and a filter BIO.
+There are two types of BIO, a source/sink BIO and a filter BIO.
As its name implies a source/sink BIO is a source and/or sink of data,
examples include a socket BIO and a file BIO.
@@ -31,7 +31,7 @@ BIO will encrypt data if it is being written to and decrypt data
if it is being read from.
BIOs can be joined together to form a chain (a single BIO is a chain
-with one component). A chain normally consist of one source/sink
+with one component). A chain normally consists of one source/sink
BIO and one or more filter BIOs. Data read from or written to the
first BIO then traverses the chain to the end (normally a source/sink
BIO).
@@ -47,10 +47,10 @@ in a memory leak.
Calling BIO_free_all() on a single BIO has the same effect as calling
BIO_free() on it other than the discarded return value.
-Normally the B<type> argument is supplied by a function which returns a
+Normally the I<type> argument is supplied by a function which returns a
pointer to a BIO_METHOD. There is a naming convention for such functions:
-a source/sink BIO is normally called BIO_s_*() and a filter BIO
-BIO_f_*();
+a source/sink BIO typically starts with I<BIO_s_> and
+a filter BIO with I<BIO_f_>.
=head1 EXAMPLES
@@ -64,6 +64,7 @@ L<BIO_ctrl(3)>,
L<BIO_f_base64(3)>, L<BIO_f_buffer(3)>,
L<BIO_f_cipher(3)>, L<BIO_f_md(3)>,
L<BIO_f_null(3)>, L<BIO_f_ssl(3)>,
+L<BIO_f_readbuffer(3)>,
L<BIO_find_type(3)>, L<BIO_new(3)>,
L<BIO_new_bio_pair(3)>,
L<BIO_push(3)>, L<BIO_read_ex(3)>,
@@ -76,9 +77,9 @@ L<BIO_should_retry(3)>
=head1 COPYRIGHT
-Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man7/crypto.pod b/doc/man7/crypto.pod
index e08c5c8aec13..59c60e4b5f92 100644
--- a/doc/man7/crypto.pod
+++ b/doc/man7/crypto.pod
@@ -10,49 +10,503 @@ See the individual manual pages for details.
=head1 DESCRIPTION
-The OpenSSL B<crypto> library implements a wide range of cryptographic
-algorithms used in various Internet standards. The services provided
-by this library are used by the OpenSSL implementations of SSL, TLS
-and S/MIME, and they have also been used to implement SSH, OpenPGP, and
-other cryptographic standards.
+The OpenSSL crypto library (C<libcrypto>) implements a wide range of
+cryptographic algorithms used in various Internet standards. The services
+provided by this library are used by the OpenSSL implementations of TLS and
+CMS, and they have also been used to implement many other third party products
+and protocols.
-B<libcrypto> consists of a number of sub-libraries that implement the
-individual algorithms.
+The functionality includes symmetric encryption, public key cryptography, key
+agreement, certificate handling, cryptographic hash functions, cryptographic
+pseudo-random number generators, message authentication codes (MACs), key
+derivation functions (KDFs), and various utilities.
-The functionality includes symmetric encryption, public key
-cryptography and key agreement, certificate handling, cryptographic
-hash functions, cryptographic pseudo-random number generator, and
-various utilities.
+=head2 Algorithms
-=head1 NOTES
+Cryptographic primitives such as the SHA256 digest, or AES encryption are
+referred to in OpenSSL as "algorithms". Each algorithm may have multiple
+implementations available for use. For example the RSA algorithm is available as
+a "default" implementation suitable for general use, and a "fips" implementation
+which has been validated to FIPS standards for situations where that is
+important. It is also possible that a third party could add additional
+implementations such as in a hardware security module (HSM).
-Some of the newer functions follow a naming convention using the numbers
-B<0> and B<1>. For example the functions:
+=head2 Operations
- int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
- int X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj);
+Different algorithms can be grouped together by their purpose. For example there
+are algorithms for encryption, and different algorithms for digesting data.
+These different groups are known as "operations" in OpenSSL. Each operation
+has a different set of functions associated with it. For example to perform an
+encryption operation using AES (or any other encryption algorithm) you would use
+the encryption functions detailed on the L<EVP_EncryptInit(3)> page. Or to
+perform a digest operation using SHA256 then you would use the digesting
+functions on the L<EVP_DigestInit(3)> page.
-The B<0> version uses the supplied structure pointer directly
-in the parent and it will be freed up when the parent is freed.
-In the above example B<crl> would be freed but B<rev> would not.
+=head2 Providers
-The B<1> function uses a copy of the supplied structure pointer
-(or in some cases increases its link count) in the parent and
-so both (B<x> and B<obj> above) should be freed up.
+A provider in OpenSSL is a component that collects together algorithm
+implementations. In order to use an algorithm you must have at least one
+provider loaded that contains an implementation of it. OpenSSL comes with a
+number of providers and they may also be obtained from third parties. If you
+don't load a provider explicitly (either in program code or via config) then the
+OpenSSL built-in "default" provider will be automatically loaded.
-=head1 RETURN VALUES
+=head2 Library contexts
-See the individual manual pages for details.
+A library context can be thought of as a "scope" within which configuration
+options take effect. When a provider is loaded, it is only loaded within the
+scope of a given library context. In this way it is possible for different
+components of a complex application to each use a different library context and
+have different providers loaded with different configuration settings.
+
+If an application does not explicitly create a library context then the
+"default" library context will be used.
+
+Library contexts are represented by the B<OSSL_LIB_CTX> type. Many OpenSSL API
+functions take a library context as a parameter. Applications can always pass
+B<NULL> for this parameter to just use the default library context.
+
+The default library context is automatically created the first time it is
+needed. This will automatically load any available configuration file and will
+initialise OpenSSL for use. Unlike in earlier versions of OpenSSL (prior to
+1.1.0) no explicit initialisation steps need to be taken.
+
+Similarly when the application exits the default library context is
+automatically destroyed. No explicit de-initialisation steps need to be taken.
+
+See L<OSSL_LIB_CTX(3)> for more information about library contexts.
+See also L</ALGORITHM FETCHING>.
+
+=head2 Multi-threaded applications
+
+As long as OpenSSL has been built with support for threads (the default case
+on most platforms) then most OpenSSL I<functions> are thread-safe in the sense
+that it is safe to call the same function from multiple threads at the same
+time. However most OpenSSL I<data structures> are not thread-safe. For example
+the L<BIO_write(3)> and L<BIO_read(3)> functions are thread safe. However it
+would not be thread safe to call BIO_write() from one thread while calling
+BIO_read() in another where both functions are passed the same B<BIO> object
+since both of them may attempt to make changes to the same B<BIO> object.
+
+There are exceptions to these rules. A small number of functions are not thread
+safe at all. Where this is the case this restriction should be noted in the
+documentation for the function. Similarly some data structures may be partially
+or fully thread safe. For example it is safe to use an B<OSSL_LIB_CTX> in
+multiple threads.
+
+See L<openssl-threads(7)> for a more detailed discussion on OpenSSL threading
+support.
+
+=head1 ALGORITHM FETCHING
+
+In order to use an algorithm an implementation for it must first be "fetched".
+Fetching is the process of looking through the available implementations,
+applying selection criteria (via a property query string), and finally choosing
+the implementation that will be used.
+
+Two types of fetching are supported by OpenSSL - explicit fetching and implicit
+fetching.
+
+=head2 Property query strings
+
+When fetching an algorithm it is possible to specify a property query string to
+guide the selection process. For example a property query string of
+"provider=default" could be used to force the selection to only consider
+algorithm implementations in the default provider.
+
+Property query strings can be specified explicitly as an argument to a function.
+It is also possible to specify a default property query string for the whole
+library context using the L<EVP_set_default_properties(3)> function. Where both
+default properties and function specific properties are specified then they are
+combined. Function specific properties will override default properties where
+there is a conflict.
+
+See L<property(7)> for more information about properties.
+
+=head2 Explicit fetching
+
+Users of the OpenSSL libraries never query a provider directly for an algorithm
+implementation. Instead, the diverse OpenSSL APIs often have explicit fetching
+functions that do the work, and they return an appropriate algorithm object back
+to the user. These functions usually have the name C<APINAME_fetch>, where
+C<APINAME> is the name of the operation. For example L<EVP_MD_fetch(3)> can
+be used to explicitly fetch a digest algorithm implementation. The user is
+responsible for freeing the object returned from the C<APINAME_fetch> function
+using C<APINAME_free> when it is no longer needed.
+
+These fetching functions follow a fairly common pattern, where three
+arguments are passed:
+
+=over 4
+
+=item The library context
+
+See L<OSSL_LIB_CTX(3)> for a more detailed description.
+This may be NULL to signify the default (global) library context, or a
+context created by the user. Only providers loaded in this library context (see
+L<OSSL_PROVIDER_load(3)>) will be considered by the fetching function. In case
+no provider has been loaded in this library context then the default provider
+will be loaded as a fallback (see L<OSSL_PROVIDER-default(7)>).
+
+=item An identifier
+
+For all currently implemented fetching functions this is the algorithm name.
+
+=item A property query string
+
+The property query string used to guide selection of the algorithm
+implementation.
+
+=back
+
+The algorithm implementation that is fetched can then be used with other diverse
+functions that use them. For example the L<EVP_DigestInit_ex(3)> function takes
+as a parameter an B<EVP_MD> object which may have been returned from an earlier
+call to L<EVP_MD_fetch(3)>.
+
+=head2 Implicit fetch
+
+OpenSSL has a number of functions that return an algorithm object with no
+associated implementation, such as L<EVP_sha256(3)>, L<EVP_aes_128_cbc(3)>,
+L<EVP_get_cipherbyname(3)> or L<EVP_get_digestbyname(3)>. These are present for
+compatibility with OpenSSL before version 3.0 where explicit fetching was not
+available.
+
+When they are used with functions like L<EVP_DigestInit_ex(3)> or
+L<EVP_CipherInit_ex(3)>, the actual implementation to be used is
+fetched implicitly using default search criteria.
+
+In some cases implicit fetching can also occur when a NULL algorithm parameter
+is supplied. In this case an algorithm implementation is implicitly fetched
+using default search criteria and an algorithm name that is consistent with
+the context in which it is being used.
+
+Functions that revolve around B<EVP_PKEY_CTX> and L<EVP_PKEY(3)>, such as
+L<EVP_DigestSignInit(3)> and friends, all fetch the implementations
+implicitly. Because these functions involve both an operation type (such as
+L<EVP_SIGNATURE(3)>) and an L<EVP_KEYMGMT(3)> for the L<EVP_PKEY(3)>, they try
+the following:
+
+=over 4
+
+=item 1.
+
+Fetch the operation type implementation from any provider given a library
+context and property string stored in the B<EVP_PKEY_CTX>.
+
+If the provider of the operation type implementation is different from the
+provider of the L<EVP_PKEY(3)>'s L<EVP_KEYMGMT(3)> implementation, try to
+fetch a L<EVP_KEYMGMT(3)> implementation in the same provider as the operation
+type implementation and export the L<EVP_PKEY(3)> to it (effectively making a
+temporary copy of the original key).
+
+If anything in this step fails, the next step is used as a fallback.
+
+=item 2.
+
+As a fallback, try to fetch the operation type implementation from the same
+provider as the original L<EVP_PKEY(3)>'s L<EVP_KEYMGMT(3)>, still using the
+propery string from the B<EVP_PKEY_CTX>.
+
+=back
+
+=head1 FETCHING EXAMPLES
+
+The following section provides a series of examples of fetching algorithm
+implementations.
+
+Fetch any available implementation of SHA2-256 in the default context. Note
+that some algorithms have aliases. So "SHA256" and "SHA2-256" are synonymous:
+
+ EVP_MD *md = EVP_MD_fetch(NULL, "SHA2-256", NULL);
+ ...
+ EVP_MD_free(md);
+
+Fetch any available implementation of AES-128-CBC in the default context:
+
+ EVP_CIPHER *cipher = EVP_CIPHER_fetch(NULL, "AES-128-CBC", NULL);
+ ...
+ EVP_CIPHER_free(cipher);
+
+Fetch an implementation of SHA2-256 from the default provider in the default
+context:
+
+ EVP_MD *md = EVP_MD_fetch(NULL, "SHA2-256", "provider=default");
+ ...
+ EVP_MD_free(md);
+
+Fetch an implementation of SHA2-256 that is not from the default provider in the
+default context:
+
+ EVP_MD *md = EVP_MD_fetch(NULL, "SHA2-256", "provider!=default");
+ ...
+ EVP_MD_free(md);
+
+Fetch an implementation of SHA2-256 from the default provider in the specified
+context:
+
+ EVP_MD *md = EVP_MD_fetch(ctx, "SHA2-256", "provider=default");
+ ...
+ EVP_MD_free(md);
+
+Load the legacy provider into the default context and then fetch an
+implementation of WHIRLPOOL from it:
+
+ /* This only needs to be done once - usually at application start up */
+ OSSL_PROVIDER *legacy = OSSL_PROVIDER_load(NULL, "legacy");
+
+ EVP_MD *md = EVP_MD_fetch(NULL, "WHIRLPOOL", "provider=legacy");
+ ...
+ EVP_MD_free(md);
+
+Note that in the above example the property string "provider=legacy" is optional
+since, assuming no other providers have been loaded, the only implementation of
+the "whirlpool" algorithm is in the "legacy" provider. Also note that the
+default provider should be explicitly loaded if it is required in addition to
+other providers:
+
+ /* This only needs to be done once - usually at application start up */
+ OSSL_PROVIDER *legacy = OSSL_PROVIDER_load(NULL, "legacy");
+ OSSL_PROVIDER *default = OSSL_PROVIDER_load(NULL, "default");
+
+ EVP_MD *md_whirlpool = EVP_MD_fetch(NULL, "whirlpool", NULL);
+ EVP_MD *md_sha256 = EVP_MD_fetch(NULL, "SHA2-256", NULL);
+ ...
+ EVP_MD_free(md_whirlpool);
+ EVP_MD_free(md_sha256);
+
+=head1 OPENSSL PROVIDERS
+
+OpenSSL comes with a set of providers.
+
+The algorithms available in each of these providers may vary due to build time
+configuration options. The L<openssl-list(1)> command can be used to list the
+currently available algorithms.
+
+The names of the algorithms shown from L<openssl-list(1)> can be used as an
+algorithm identifier to the appropriate fetching function. Also see the provider
+specific manual pages linked below for further details about using the
+algorithms available in each of the providers.
+
+As well as the OpenSSL providers third parties can also implement providers.
+For information on writing a provider see L<provider(7)>.
+
+=head2 Default provider
+
+The default provider is built in as part of the F<libcrypto> library and
+contains all of the most commonly used algorithm implementations. Should it be
+needed (if other providers are loaded and offer implementations of the same
+algorithms), the property query string "provider=default" can be used as a
+search criterion for these implementations. The default provider includes all
+of the functionality in the base provider below.
+
+If you don't load any providers at all then the "default" provider will be
+automatically loaded. If you explicitly load any provider then the "default"
+provider would also need to be explicitly loaded if it is required.
+
+See L<OSSL_PROVIDER-default(7)>.
+
+=head2 Base provider
+
+The base provider is built in as part of the F<libcrypto> library and contains
+algorithm implementations for encoding and decoding for OpenSSL keys.
+Should it be needed (if other providers are loaded and offer
+implementations of the same algorithms), the property query string
+"provider=base" can be used as a search criterion for these implementations.
+Some encoding and decoding algorithm implementations are not FIPS algorithm
+implementations in themselves but support algorithms from the FIPS provider and
+are allowed for use in "FIPS mode". The property query string "fips=yes" can be
+used to select such algorithms.
+
+See L<OSSL_PROVIDER-base(7)>.
+
+=head2 FIPS provider
+
+The FIPS provider is a dynamically loadable module, and must therefore
+be loaded explicitly, either in code or through OpenSSL configuration
+(see L<config(5)>). It contains algorithm implementations that have been
+validated according to the FIPS 140-2 standard. Should it be needed (if other
+providers are loaded and offer implementations of the same algorithms), the
+property query string "provider=fips" can be used as a search criterion for
+these implementations. All approved algorithm implementations in the FIPS
+provider can also be selected with the property "fips=yes". The FIPS provider
+may also contain non-approved algorithm implementations and these can be
+selected with the property "fips=no".
+
+See L<OSSL_PROVIDER-FIPS(7)> and L<fips_module(7)>.
+
+=head2 Legacy provider
+
+The legacy provider is a dynamically loadable module, and must therefore
+be loaded explicitly, either in code or through OpenSSL configuration
+(see L<config(5)>). It contains algorithm implementations that are considered
+insecure, or are no longer in common use such as MD2 or RC4. Should it be needed
+(if other providers are loaded and offer implementations of the same algorithms),
+the property "provider=legacy" can be used as a search criterion for these
+implementations.
+
+See L<OSSL_PROVIDER-legacy(7)>.
+
+=head2 Null provider
+
+The null provider is built in as part of the F<libcrypto> library. It contains
+no algorithms in it at all. When fetching algorithms the default provider will
+be automatically loaded if no other provider has been explicitly loaded. To
+prevent that from happening you can explicitly load the null provider.
+
+See L<OSSL_PROVIDER-null(7)>.
+
+=head1 USING ALGORITHMS IN APPLICATIONS
+
+Cryptographic algorithms are made available to applications through use of the
+"EVP" APIs. Each of the various operations such as encryption, digesting,
+message authentication codes, etc., have a set of EVP function calls that can
+be invoked to use them. See the L<evp(7)> page for further details.
+
+Most of these follow a common pattern. A "context" object is first created. For
+example for a digest operation you would use an B<EVP_MD_CTX>, and for an
+encryption/decryption operation you would use an B<EVP_CIPHER_CTX>. The
+operation is then initialised ready for use via an "init" function - optionally
+passing in a set of parameters (using the L<OSSL_PARAM(3)> type) to configure how
+the operation should behave. Next data is fed into the operation in a series of
+"update" calls. The operation is finalised using a "final" call which will
+typically provide some kind of output. Finally the context is cleaned up and
+freed.
+
+The following shows a complete example for doing this process for digesting
+data using SHA256. The process is similar for other operations such as
+encryption/decryption, signatures, message authentication codes, etc.
+
+ #include <stdio.h>
+ #include <openssl/evp.h>
+ #include <openssl/bio.h>
+ #include <openssl/err.h>
+
+ int main(void)
+ {
+ EVP_MD_CTX *ctx = NULL;
+ EVP_MD *sha256 = NULL;
+ const unsigned char msg[] = {
+ 0x00, 0x01, 0x02, 0x03
+ };
+ unsigned int len = 0;
+ unsigned char *outdigest = NULL;
+ int ret = 1;
+
+ /* Create a context for the digest operation */
+ ctx = EVP_MD_CTX_new();
+ if (ctx == NULL)
+ goto err;
+
+ /*
+ * Fetch the SHA256 algorithm implementation for doing the digest. We're
+ * using the "default" library context here (first NULL parameter), and
+ * we're not supplying any particular search criteria for our SHA256
+ * implementation (second NULL parameter). Any SHA256 implementation will
+ * do.
+ */
+ sha256 = EVP_MD_fetch(NULL, "SHA256", NULL);
+ if (sha256 == NULL)
+ goto err;
+
+ /* Initialise the digest operation */
+ if (!EVP_DigestInit_ex(ctx, sha256, NULL))
+ goto err;
+
+ /*
+ * Pass the message to be digested. This can be passed in over multiple
+ * EVP_DigestUpdate calls if necessary
+ */
+ if (!EVP_DigestUpdate(ctx, msg, sizeof(msg)))
+ goto err;
+
+ /* Allocate the output buffer */
+ outdigest = OPENSSL_malloc(EVP_MD_get_size(sha256));
+ if (outdigest == NULL)
+ goto err;
+
+ /* Now calculate the digest itself */
+ if (!EVP_DigestFinal_ex(ctx, outdigest, &len))
+ goto err;
+
+ /* Print out the digest result */
+ BIO_dump_fp(stdout, outdigest, len);
+
+ ret = 0;
+
+ err:
+ /* Clean up all the resources we allocated */
+ OPENSSL_free(outdigest);
+ EVP_MD_free(sha256);
+ EVP_MD_CTX_free(ctx);
+ if (ret != 0)
+ ERR_print_errors_fp(stderr);
+ return ret;
+ }
+
+=head1 CONFIGURATION
+
+By default OpenSSL will load a configuration file when it is first used. This
+will set up various configuration settings within the default library context.
+Applications that create their own library contexts may optionally configure
+them with a config file using the L<OSSL_LIB_CTX_load_config(3)> function.
+
+The configuration file can be used to automatically load providers and set up
+default property query strings.
+
+For information on the OpenSSL configuration file format see L<config(5)>.
+
+=head1 ENCODING AND DECODING KEYS
+
+Many algorithms require the use of a key. Keys can be generated dynamically
+using the EVP APIs (for example see L<EVP_PKEY_Q_keygen(3)>). However it is often
+necessary to save or load keys (or their associated parameters) to or from some
+external format such as PEM or DER (see L<openssl-glossary(7)>). OpenSSL uses
+encoders and decoders to perform this task.
+
+Encoders and decoders are just algorithm implementations in the same way as
+any other algorithm implementation in OpenSSL. They are implemented by
+providers. The OpenSSL encoders and decoders are available in the default
+provider. They are also duplicated in the base provider.
+
+For information about encoders see L<OSSL_ENCODER_CTX_new_for_pkey(3)>. For
+information about decoders see L<OSSL_DECODER_CTX_new_for_pkey(3)>.
+
+=head1 LIBRARY CONVENTIONS
+
+Many OpenSSL functions that "get" or "set" a value follow a naming convention
+using the numbers B<0> and B<1>, i.e. "get0", "get1", "set0" and "set1". This
+can also apply to some functions that "add" a value to an existing set, i.e.
+"add0" and "add1".
+
+For example the functions:
+
+ int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
+ int X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj);
+
+In the B<0> version the ownership of the object is passed to (for an add or set)
+or retained by (for a get) the parent object. For example after calling the
+X509_CRL_add0_revoked() function above, ownership of the I<rev> object is passed
+to the I<crl> object. Therefore, after calling this function I<rev> should not
+be freed directly. It will be freed implicitly when I<crl> is freed.
+
+In the B<1> version the ownership of the object is not passed to or retained by
+the parent object. Instead a copy or "up ref" of the object is performed. So
+after calling the X509_add1_trust_object() function above the application will
+still be responsible for freeing the I<obj> value where appropriate.
=head1 SEE ALSO
-L<openssl(1)>, L<ssl(7)>
+L<openssl(1)>, L<ssl(7)>, L<evp(7)>, L<OSSL_LIB_CTX(3)>, L<openssl-threads(7)>,
+L<property(7)>, L<OSSL_PROVIDER-default(7)>, L<OSSL_PROVIDER-base(7)>,
+L<OSSL_PROVIDER-FIPS(7)>, L<OSSL_PROVIDER-legacy(7)>, L<OSSL_PROVIDER-null(7)>,
+L<openssl-glossary(7)>, L<provider(7)>
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man7/ct.pod b/doc/man7/ct.pod
index 9f82c0ba44be..ca2a43e429d2 100644
--- a/doc/man7/ct.pod
+++ b/doc/man7/ct.pod
@@ -45,7 +45,7 @@ The ct library was added in OpenSSL 1.1.0.
Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man7/des_modes.pod b/doc/man7/des_modes.pod
index f7415d77f485..34f05b3d5d70 100644
--- a/doc/man7/des_modes.pod
+++ b/doc/man7/des_modes.pod
@@ -250,7 +250,7 @@ L<BF_encrypt(3)>, L<DES_crypt(3)>
Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man7/evp.pod b/doc/man7/evp.pod
index fd8d6c7fe38d..44d385655e5f 100644
--- a/doc/man7/evp.pod
+++ b/doc/man7/evp.pod
@@ -29,10 +29,11 @@ The B<EVP_PKEY>I<XXX> functions provide a high-level interface to
asymmetric algorithms. To create a new EVP_PKEY see
L<EVP_PKEY_new(3)>. EVP_PKEYs can be associated
with a private key of a particular algorithm by using the functions
-described on the L<EVP_PKEY_set1_RSA(3)> page, or
+described on the L<EVP_PKEY_fromdata(3)> page, or
new keys can be generated using L<EVP_PKEY_keygen(3)>.
-EVP_PKEYs can be compared using L<EVP_PKEY_cmp(3)>, or printed using
-L<EVP_PKEY_print_private(3)>.
+EVP_PKEYs can be compared using L<EVP_PKEY_eq(3)>, or printed using
+L<EVP_PKEY_print_private(3)>. L<EVP_PKEY_todata(3)> can be used to convert a
+key back into an L<OSSL_PARAM(3)> array.
The EVP_PKEY functions support the full range of asymmetric algorithm operations:
@@ -90,7 +91,8 @@ L<EVP_SignInit(3)>,
L<EVP_VerifyInit(3)>,
L<EVP_EncodeInit(3)>,
L<EVP_PKEY_new(3)>,
-L<EVP_PKEY_set1_RSA(3)>,
+L<EVP_PKEY_fromdata(3)>,
+L<EVP_PKEY_todata(3)>,
L<EVP_PKEY_keygen(3)>,
L<EVP_PKEY_print_private(3)>,
L<EVP_PKEY_decrypt(3)>,
@@ -104,9 +106,9 @@ L<ENGINE_by_id(3)>
=head1 COPYRIGHT
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man7/fips_module.pod b/doc/man7/fips_module.pod
new file mode 100644
index 000000000000..b1d67ca61b43
--- /dev/null
+++ b/doc/man7/fips_module.pod
@@ -0,0 +1,477 @@
+=pod
+
+=head1 NAME
+
+fips_module - OpenSSL fips module guide
+
+=head1 SYNOPSIS
+
+See the individual manual pages for details.
+
+=head1 DESCRIPTION
+
+This guide details different ways that OpenSSL can be used in conjunction
+with the FIPS module. Which is the correct approach to use will depend on your
+own specific circumstances and what you are attempting to achieve.
+
+Note that the old functions FIPS_mode() and FIPS_mode_set() are no longer
+present so you must remove them from your application if you use them.
+
+Applications written to use the OpenSSL 3.0 FIPS module should not use any
+legacy APIs or features that avoid the FIPS module. Specifically this includes:
+
+=over 4
+
+=item *
+
+Low level cryptographic APIs (use the high level APIs, such as EVP, instead)
+
+=item *
+
+Engines
+
+=item *
+
+Any functions that create or modify custom "METHODS" (for example
+EVP_MD_meth_new(), EVP_CIPHER_meth_new(), EVP_PKEY_meth_new(), RSA_meth_new(),
+EC_KEY_METHOD_new(), etc.)
+
+=back
+
+All of the above APIs are deprecated in OpenSSL 3.0 - so a simple rule is to
+avoid using all deprecated functions. See L<migration_guide(7)> for a list of
+deprecated functions.
+
+=head2 Making all applications use the FIPS module by default
+
+One simple approach is to cause all applications that are using OpenSSL to only
+use the FIPS module for cryptographic algorithms by default.
+
+This approach can be done purely via configuration. As long as applications are
+built and linked against OpenSSL 3.0 and do not override the loading of the
+default config file or its settings then they can automatically start using the
+FIPS module without the need for any further code changes.
+
+To do this the default OpenSSL config file will have to be modified. The
+location of this config file will depend on the platform, and any options that
+were given during the build process. You can check the location of the config
+file by running this command:
+
+ $ openssl version -d
+ OPENSSLDIR: "/usr/local/ssl"
+
+Caution: Many Operating Systems install OpenSSL by default. It is a common error
+to not have the correct version of OpenSSL in your $PATH. Check that you are
+running an OpenSSL 3.0 version like this:
+
+ $ openssl version -v
+ OpenSSL 3.0.0-dev xx XXX xxxx (Library: OpenSSL 3.0.0-dev xx XXX xxxx)
+
+The B<OPENSSLDIR> value above gives the directory name for where the default
+config file is stored. So in this case the default config file will be called
+F</usr/local/ssl/openssl.cnf>.
+
+Edit the config file to add the following lines near the beginning:
+
+ config_diagnostics = 1
+ openssl_conf = openssl_init
+
+ .include /usr/local/ssl/fipsmodule.cnf
+
+ [openssl_init]
+ providers = provider_sect
+
+ [provider_sect]
+ fips = fips_sect
+ base = base_sect
+
+ [base_sect]
+ activate = 1
+
+Obviously the include file location above should match the path and name of the
+FIPS module config file that you installed earlier.
+See L<https://github.com/openssl/openssl/blob/master/README-FIPS.md>.
+
+For FIPS usage, it is recommened that the B<config_diagnostics> option is
+enabled to prevent accidental use of non-FIPS validated algorithms via broken
+or mistaken configuration. See L<config(5)>.
+
+Any applications that use OpenSSL 3.0 and are started after these changes are
+made will start using only the FIPS module unless those applications take
+explicit steps to avoid this default behaviour. Note that this configuration
+also activates the "base" provider. The base provider does not include any
+cryptographic algorithms (and therefore does not impact the validation status of
+any cryptographic operations), but does include other supporting algorithms that
+may be required. It is designed to be used in conjunction with the FIPS module.
+
+This approach has the primary advantage that it is simple, and no code changes
+are required in applications in order to benefit from the FIPS module. There are
+some disadvantages to this approach:
+
+=over 4
+
+=item *
+
+You may not want all applications to use the FIPS module.
+
+It may be the case that some applications should and some should not use the
+FIPS module.
+
+=item *
+
+If applications take explicit steps to not load the default config file or
+set different settings.
+
+This method will not work for these cases.
+
+=item *
+
+The algorithms available in the FIPS module are a subset of the algorithms
+that are available in the default OpenSSL Provider.
+
+If any applications attempt to use any algorithms that are not present,
+then they will fail.
+
+=item *
+
+Usage of certain deprecated APIs avoids the use of the FIPS module.
+
+If any applications use those APIs then the FIPS module will not be used.
+
+=back
+
+=head2 Selectively making applications use the FIPS module by default
+
+A variation on the above approach is to do the same thing on an individual
+application basis. The default OpenSSL config file depends on the compiled in
+value for B<OPENSSLDIR> as described in the section above. However it is also
+possible to override the config file to be used via the B<OPENSSL_CONF>
+environment variable. For example the following, on Unix, will cause the
+application to be executed with a non-standard config file location:
+
+ $ OPENSSL_CONF=/my/nondefault/openssl.cnf myapplication
+
+Using this mechanism you can control which config file is loaded (and hence
+whether the FIPS module is loaded) on an application by application basis.
+
+This removes the disadvantage listed above that you may not want all
+applications to use the FIPS module. All the other advantages and disadvantages
+still apply.
+
+=head2 Programmatically loading the FIPS module (default library context)
+
+Applications may choose to load the FIPS provider explicitly rather than relying
+on config to do this. The config file is still necessary in order to hold the
+FIPS module config data (such as its self test status and integrity data). But
+in this case we do not automatically activate the FIPS provider via that config
+file.
+
+To do things this way configure as per
+L</Making all applications use the FIPS module by default> above, but edit the
+F<fipsmodule.cnf> file to remove or comment out the line which says
+C<activate = 1> (note that setting this value to 0 is I<not> sufficient).
+This means all the required config information will be available to load the
+FIPS module, but it is not automatically loaded when the application starts. The
+FIPS provider can then be loaded programmatically like this:
+
+ #include <openssl/provider.h>
+
+ int main(void)
+ {
+ OSSL_PROVIDER *fips;
+ OSSL_PROVIDER *base;
+
+ fips = OSSL_PROVIDER_load(NULL, "fips");
+ if (fips == NULL) {
+ printf("Failed to load FIPS provider\n");
+ exit(EXIT_FAILURE);
+ }
+ base = OSSL_PROVIDER_load(NULL, "base");
+ if (base == NULL) {
+ OSSL_PROVIDER_unload(fips);
+ printf("Failed to load base provider\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Rest of application */
+
+ OSSL_PROVIDER_unload(base);
+ OSSL_PROVIDER_unload(fips);
+ exit(EXIT_SUCCESS);
+ }
+
+Note that this should be one of the first things that you do in your
+application. If any OpenSSL functions get called that require the use of
+cryptographic functions before this occurs then, if no provider has yet been
+loaded, then the default provider will be automatically loaded. If you then
+later explicitly load the FIPS provider then you will have both the FIPS and the
+default provider loaded at the same time. It is undefined which implementation
+of an algorithm will be used if multiple implementations are available and you
+have not explicitly specified via a property query (see below) which one should
+be used.
+
+Also note that in this example we have additionally loaded the "base" provider.
+This loads a sub-set of algorithms that are also available in the default
+provider - specifically non cryptographic ones which may be used in conjunction
+with the FIPS provider. For example this contains algorithms for encoding and
+decoding keys. If you decide not to load the default provider then you
+will usually want to load the base provider instead.
+
+In this example we are using the "default" library context. OpenSSL functions
+operate within the scope of a library context. If no library context is
+explicitly specified then the default library context is used. For further
+details about library contexts see the L<OSSL_LIB_CTX(3)> man page.
+
+=head2 Loading the FIPS module at the same time as other providers
+
+It is possible to have the FIPS provider and other providers (such as the
+default provider) all loaded at the same time into the same library context. You
+can use a property query string during algorithm fetches to specify which
+implementation you would like to use.
+
+For example to fetch an implementation of SHA256 which conforms to FIPS
+standards you can specify the property query C<fips=yes> like this:
+
+ EVP_MD *sha256;
+
+ sha256 = EVP_MD_fetch(NULL, "SHA2-256", "fips=yes");
+
+If no property query is specified, or more than one implementation matches the
+property query then it is undefined which implementation of a particular
+algorithm will be returned.
+
+This example shows an explicit request for an implementation of SHA256 from the
+default provider:
+
+ EVP_MD *sha256;
+
+ sha256 = EVP_MD_fetch(NULL, "SHA2-256", "provider=default");
+
+It is also possible to set a default property query string. The following
+example sets the default property query of C<fips=yes> for all fetches within
+the default library context:
+
+ EVP_set_default_properties(NULL, "fips=yes");
+
+If a fetch function has both an explicit property query specified, and a
+default property query is defined then the two queries are merged together and
+both apply. The local property query overrides the default properties if the
+same property name is specified in both.
+
+There are two important built-in properties that you should be aware of:
+
+The "provider" property enables you to specify which provider you want an
+implementation to be fetched from, e.g. C<provider=default> or C<provider=fips>.
+All algorithms implemented in a provider have this property set on them.
+
+There is also the C<fips> property. All FIPS algorithms match against the
+property query C<fips=yes>. There are also some non-cryptographic algorithms
+available in the default and base providers that also have the C<fips=yes>
+property defined for them. These are the encoder and decoder algorithms that
+can (for example) be used to write out a key generated in the FIPS provider to a
+file. The encoder and decoder algorithms are not in the FIPS module itself but
+are allowed to be used in conjunction with the FIPS algorithms.
+
+It is possible to specify default properties within a config file. For example
+the following config file automatically loads the default and FIPS providers and
+sets the default property value to be C<fips=yes>. Note that this config file
+does not load the "base" provider. All supporting algorithms that are in "base"
+are also in "default", so it is unnecessary in this case:
+
+ config_diagnostics = 1
+ openssl_conf = openssl_init
+
+ .include /usr/local/ssl/fipsmodule.cnf
+
+ [openssl_init]
+ providers = provider_sect
+ alg_section = algorithm_sect
+
+ [provider_sect]
+ fips = fips_sect
+ default = default_sect
+
+ [default_sect]
+ activate = 1
+
+ [algorithm_sect]
+ default_properties = fips=yes
+
+=head2 Programmatically loading the FIPS module (nondefault library context)
+
+In addition to using properties to separate usage of the FIPS module from other
+usages this can also be achieved using library contexts. In this example we
+create two library contexts. In one we assume the existence of a config file
+called F<openssl-fips.cnf> that automatically loads and configures the FIPS and
+base providers. The other library context will just use the default provider.
+
+ OSSL_LIB_CTX *fips_libctx, *nonfips_libctx;
+ OSSL_PROVIDER *defctxnull = NULL;
+ EVP_MD *fipssha256 = NULL, *nonfipssha256 = NULL;
+ int ret = 1;
+
+ /*
+ * Create two nondefault library contexts. One for fips usage and
+ * one for non-fips usage
+ */
+ fips_libctx = OSSL_LIB_CTX_new();
+ nonfips_libctx = OSSL_LIB_CTX_new();
+ if (fips_libctx == NULL || nonfips_libctx == NULL)
+ goto err;
+
+ /* Prevent anything from using the default library context */
+ defctxnull = OSSL_PROVIDER_load(NULL, "null");
+
+ /*
+ * Load config file for the FIPS library context. We assume that
+ * this config file will automatically activate the FIPS and base
+ * providers so we don't need to explicitly load them here.
+ */
+ if (!OSSL_LIB_CTX_load_config(fips_libctx, "openssl-fips.cnf"))
+ goto err;
+
+ /*
+ * We don't need to do anything special to load the default
+ * provider into nonfips_libctx. This happens automatically if no
+ * other providers are loaded.
+ * Because we don't call OSSL_LIB_CTX_load_config() explicitly for
+ * nonfips_libctx it will just use the default config file.
+ */
+
+ /* As an example get some digests */
+
+ /* Get a FIPS validated digest */
+ fipssha256 = EVP_MD_fetch(fips_libctx, "SHA2-256", NULL);
+ if (fipssha256 == NULL)
+ goto err;
+
+ /* Get a non-FIPS validated digest */
+ nonfipssha256 = EVP_MD_fetch(nonfips_libctx, "SHA2-256", NULL);
+ if (nonfipssha256 == NULL)
+ goto err;
+
+ /* Use the digests */
+
+ printf("Success\n");
+ ret = 0;
+
+ err:
+ EVP_MD_free(fipssha256);
+ EVP_MD_free(nonfipssha256);
+ OSSL_LIB_CTX_free(fips_libctx);
+ OSSL_LIB_CTX_free(nonfips_libctx);
+ OSSL_PROVIDER_unload(defctxnull);
+
+ return ret;
+
+Note that we have made use of the special "null" provider here which we load
+into the default library context. We could have chosen to use the default
+library context for FIPS usage, and just create one additional library context
+for other usages - or vice versa. However if code has not been converted to use
+library contexts then the default library context will be automatically used.
+This could be the case for your own existing applications as well as certain
+parts of OpenSSL itself. Not all parts of OpenSSL are library context aware. If
+this happens then you could "accidentally" use the wrong library context for a
+particular operation. To be sure this doesn't happen you can load the "null"
+provider into the default library context. Because a provider has been
+explicitly loaded, the default provider will not automatically load. This means
+code using the default context by accident will fail because no algorithms will
+be available.
+
+See L<migration_guide(7)/Library Context> for additional information about the
+Library Context.
+
+=head2 Using Encoders and Decoders with the FIPS module
+
+Encoders and decoders are used to read and write keys or parameters from or to
+some external format (for example a PEM file). If your application generates
+keys or parameters that then need to be written into PEM or DER format
+then it is likely that you will need to use an encoder to do this. Similarly
+you need a decoder to read previously saved keys and parameters. In most cases
+this will be invisible to you if you are using APIs that existed in
+OpenSSL 1.1.1 or earlier such as L<i2d_PrivateKey(3)>. However the appropriate
+encoder/decoder will need to be available in the library context associated with
+the key or parameter object. The built-in OpenSSL encoders and decoders are
+implemented in both the default and base providers and are not in the FIPS
+module boundary. However since they are not cryptographic algorithms themselves
+it is still possible to use them in conjunction with the FIPS module, and
+therefore these encoders/decoders have the C<fips=yes> property against them.
+You should ensure that either the default or base provider is loaded into the
+library context in this case.
+
+=head2 Using the FIPS module in SSL/TLS
+
+Writing an application that uses libssl in conjunction with the FIPS module is
+much the same as writing a normal libssl application. If you are using global
+properties and the default library context to specify usage of FIPS validated
+algorithms then this will happen automatically for all cryptographic algorithms
+in libssl. If you are using a nondefault library context to load the FIPS
+provider then you can supply this to libssl using the function
+L<SSL_CTX_new_ex(3)>. This works as a drop in replacement for the function
+L<SSL_CTX_new(3)> except it provides you with the capability to specify the
+library context to be used. You can also use the same function to specify
+libssl specific properties to use.
+
+In this first example we create two SSL_CTX objects using two different library
+contexts.
+
+ /*
+ * We assume that a nondefault library context with the FIPS
+ * provider loaded has been created called fips_libctx.
+ */
+ SSL_CTX *fips_ssl_ctx = SSL_CTX_new_ex(fips_libctx, NULL, TLS_method());
+ /*
+ * We assume that a nondefault library context with the default
+ * provider loaded has been created called non_fips_libctx.
+ */
+ SSL_CTX *non_fips_ssl_ctx = SSL_CTX_new_ex(non_fips_libctx, NULL,
+ TLS_method());
+
+In this second example we create two SSL_CTX objects using different properties
+to specify FIPS usage:
+
+ /*
+ * The "fips=yes" property includes all FIPS approved algorithms
+ * as well as encoders from the default provider that are allowed
+ * to be used. The NULL below indicates that we are using the
+ * default library context.
+ */
+ SSL_CTX *fips_ssl_ctx = SSL_CTX_new_ex(NULL, "fips=yes", TLS_method());
+ /*
+ * The "provider!=fips" property allows algorithms from any
+ * provider except the FIPS provider
+ */
+ SSL_CTX *non_fips_ssl_ctx = SSL_CTX_new_ex(NULL, "provider!=fips",
+ TLS_method());
+
+=head2 Confirming that an algorithm is being provided by the FIPS module
+
+A chain of links needs to be followed to go from an algorithm instance to the
+provider that implements it. The process is similar for all algorithms. Here the
+example of a digest is used.
+
+To go from an B<EVP_MD_CTX> to an B<EVP_MD>, use L<EVP_MD_CTX_md(3)> .
+To go from the B<EVP_MD> to its B<OSSL_PROVIDER>,
+use L<EVP_MD_get0_provider(3)>.
+To extract the name from the B<OSSL_PROVIDER>, use
+L<OSSL_PROVIDER_get0_name(3)>.
+
+=head1 SEE ALSO
+
+L<migration_guide(7)>, L<crypto(7)>, L<fips_config(5)>
+
+=head1 HISTORY
+
+The FIPS module guide was created for use with the new FIPS provider
+in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/img/cipher.png b/doc/man7/img/cipher.png
new file mode 100644
index 000000000000..79b8b621e6aa
--- /dev/null
+++ b/doc/man7/img/cipher.png
Binary files differ
diff --git a/doc/man7/img/digest.png b/doc/man7/img/digest.png
new file mode 100644
index 000000000000..9f35deb5dcc8
--- /dev/null
+++ b/doc/man7/img/digest.png
Binary files differ
diff --git a/doc/man7/img/kdf.png b/doc/man7/img/kdf.png
new file mode 100644
index 000000000000..144e398a218c
--- /dev/null
+++ b/doc/man7/img/kdf.png
Binary files differ
diff --git a/doc/man7/img/mac.png b/doc/man7/img/mac.png
new file mode 100644
index 000000000000..d3978767c9f2
--- /dev/null
+++ b/doc/man7/img/mac.png
Binary files differ
diff --git a/doc/man7/img/pkey.png b/doc/man7/img/pkey.png
new file mode 100644
index 000000000000..d31b5d3841a7
--- /dev/null
+++ b/doc/man7/img/pkey.png
Binary files differ
diff --git a/doc/man7/img/rand.png b/doc/man7/img/rand.png
new file mode 100644
index 000000000000..7572ca6fd8f1
--- /dev/null
+++ b/doc/man7/img/rand.png
Binary files differ
diff --git a/doc/man7/life_cycle-cipher.pod b/doc/man7/life_cycle-cipher.pod
new file mode 100644
index 000000000000..1fe05688ed3e
--- /dev/null
+++ b/doc/man7/life_cycle-cipher.pod
@@ -0,0 +1,370 @@
+=pod
+
+=head1 NAME
+
+life_cycle-cipher - The cipher algorithm life-cycle
+
+=head1 DESCRIPTION
+
+All symmetric ciphers (CIPHERs) go through a number of stages in their
+life-cycle:
+
+=over 4
+
+=item start
+
+This state represents the CIPHER before it has been allocated. It is the
+starting state for any life-cycle transitions.
+
+=item newed
+
+This state represents the CIPHER after it has been allocated.
+
+=item initialised
+
+These states represent the CIPHER when it is set up and capable of processing
+input. There are three possible initialised states:
+
+=over 4
+
+=item initialised using EVP_CipherInit
+
+=item initialised for decryption using EVP_DecryptInit
+
+=item initialised for encryption using EVP_EncryptInit
+
+=back
+
+=item updated
+
+These states represent the CIPHER when it is set up and capable of processing
+additional input or generating output. The three possible states directly
+correspond to those for initialised above. The three different streams should
+not be mixed.
+
+=item finaled
+
+This state represents the CIPHER when it has generated output.
+
+=item freed
+
+This state is entered when the CIPHER is freed. It is the terminal state
+for all life-cycle transitions.
+
+=back
+
+=head2 State Transition Diagram
+
+The usual life-cycle of a CIPHER is illustrated:
+
+=begin man
+
+ +---------------------------+
+ | |
+ | start |
+ | |
+ +---------------------------+ + - - - - - - - - - - - - - +
+ | ' any of the initialised '
+ | EVP_CIPHER_CTX_new ' updated or finaled states '
+ v ' '
+ +---------------------------+ + - - - - - - - - - - - - - +
+ | | |
+ | newed | | EVP_CIPHER_CTX_reset
+ | | <----+
+ +---------------------------+
+ | | |
+ +---------+ | +---------+
+ EVP_DecryptInit | | EVP_CipherInit | EVP_EncryptInit
+ v v v
+ +---------------------------+ +---------------------------+ +---------------------------+
+ | | | | | |
+ | initialised | | initialised | | initialised |
+ | for decryption | | | | for encryption |
+ +---------------------------+ +---------------------------+ +---------------------------+
+ | | |
+ | EVP_DecryptUpdate | EVP_CipherUpdate EVP_EncryptUpdate |
+ | v |
+ | +---------------------------+ |
+ | | |--------------------+ |
+ | | updated | EVP_CipherUpdate | |
+ | | | <------------------+ |
+ v +---------------------------+ v
+ +---------------------------+ | +---------------------------+
+ | |---------------------+ | | |
+ | updated | EVP_DecryptUpdate | | | updated |------+
+ | for decryption | <-------------------+ | | for encryption | |
+ +---------------------------+ | +---------------------------+ |
+ | EVP_CipherFinal | | ^ |
+ +-------+ | +--------+ | |
+ EVP_DecryptFinal | | | EVP_EncryptFinal +-------------------+
+ v v v EVP_EncryptUpdate
+ +---------------------------+
+ | |-----------------------------+
+ | finaled | |
+ | | <---------------------------+
+ +---------------------------+ EVP_CIPHER_CTX_get_params
+ | (AEAD encryption)
+ | EVP_CIPHER_CTX_free
+ v
+ +---------------------------+
+ | |
+ | freed |
+ | |
+ +---------------------------+
+
+=end man
+
+=for html <img src="img/cipher.png">
+
+=head2 Formal State Transitions
+
+This section defines all of the legal state transitions.
+This is the canonical list.
+
+=begin man
+
+ Function Call ---------------------------------------------- Current State -----------------------------------------------
+ start newed initialised updated finaled initialised updated initialised updated freed
+ decryption decryption encryption encryption
+ EVP_CIPHER_CTX_new newed
+ EVP_CipherInit initialised initialised initialised initialised initialised initialised initialised initialised
+ EVP_DecryptInit initialised initialised initialised initialised initialised initialised initialised initialised
+ decryption decryption decryption decryption decryption decryption decryption decryption
+ EVP_EncryptInit initialised initialised initialised initialised initialised initialised initialised initialised
+ encryption encryption encryption encryption encryption encryption encryption encryption
+ EVP_CipherUpdate updated updated
+ EVP_DecryptUpdate updated updated
+ decryption decryption
+ EVP_EncryptUpdate updated updated
+ encryption encryption
+ EVP_CipherFinal finaled
+ EVP_DecryptFinal finaled
+ EVP_EncryptFinal finaled
+ EVP_CIPHER_CTX_free freed freed freed freed freed freed freed freed freed
+ EVP_CIPHER_CTX_reset newed newed newed newed newed newed newed newed
+ EVP_CIPHER_CTX_get_params newed initialised updated initialised updated initialised updated
+ decryption decryption encryption encryption
+ EVP_CIPHER_CTX_set_params newed initialised updated initialised updated initialised updated
+ decryption decryption encryption encryption
+ EVP_CIPHER_CTX_gettable_params newed initialised updated initialised updated initialised updated
+ decryption decryption encryption encryption
+ EVP_CIPHER_CTX_settable_params newed initialised updated initialised updated initialised updated
+ decryption decryption encryption encryption
+
+=end man
+
+=begin html
+
+<table style="border:1px solid; border-collapse:collapse">
+<tr><th style="border:1px solid" align="left">Function Call</th>
+ <th style="border:1px solid" colspan="10">Current State</th></tr>
+<tr><th style="border:1px solid"></th>
+ <th style="border:1px solid" align="center">start</th>
+ <th style="border:1px solid" align="center">newed</th>
+ <th style="border:1px solid" align="center">initialised</th>
+ <th style="border:1px solid" align="center">updated</th>
+ <th style="border:1px solid" align="center">finaled</th>
+ <th style="border:1px solid" align="center">initialised<br>decryption</th>
+ <th style="border:1px solid" align="center">updated<br>decryption</th>
+ <th style="border:1px solid" align="center">initialised<br>encryption</th>
+ <th style="border:1px solid" align="center">updated<br>encryption</th>
+ <th style="border:1px solid" align="center">freed</th></tr>
+<tr><th style="border:1px solid" align="left">EVP_CIPHER_CTX_new</th>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_CipherInit</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_DecryptInit</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">initialised<br>decryption</td>
+ <td style="border:1px solid" align="center">initialised<br>decryption</td>
+ <td style="border:1px solid" align="center">initialised<br>decryption</td>
+ <td style="border:1px solid" align="center">initialised<br>decryption</td>
+ <td style="border:1px solid" align="center">initialised<br>decryption</td>
+ <td style="border:1px solid" align="center">initialised<br>decryption</td>
+ <td style="border:1px solid" align="center">initialised<br>decryption</td>
+ <td style="border:1px solid" align="center">initialised<br>decryption</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_EncryptInit</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">initialised<br>encryption</td>
+ <td style="border:1px solid" align="center">initialised<br>encryption</td>
+ <td style="border:1px solid" align="center">initialised<br>encryption</td>
+ <td style="border:1px solid" align="center">initialised<br>encryption</td>
+ <td style="border:1px solid" align="center">initialised<br>encryption</td>
+ <td style="border:1px solid" align="center">initialised<br>encryption</td>
+ <td style="border:1px solid" align="center">initialised<br>encryption</td>
+ <td style="border:1px solid" align="center">initialised<br>encryption</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_CipherUpdate</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_DecryptUpdate</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">updated<br>decryption</td>
+ <td style="border:1px solid" align="center">updated<br>decryption</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_EncryptUpdate</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">updated<br>encryption</td>
+ <td style="border:1px solid" align="center">updated<br>encryption</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_CipherFinal</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">finaled</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_DecryptFinal</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">finaled<br>decryption</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_EncryptFinal</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">finaled<br>decryption</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_CIPHER_CTX_free</th>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_CIPHER_CTX_reset</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_CIPHER_CTX_get_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">initialised<br>decryption</td>
+ <td style="border:1px solid" align="center">updated<br>decryption</td>
+ <td style="border:1px solid" align="center">initialised<br>encryption</td>
+ <td style="border:1px solid" align="center">updated<br>encryption</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_CIPHER_CTX_set_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">initialised<br>decryption</td>
+ <td style="border:1px solid" align="center">updated<br>decryption</td>
+ <td style="border:1px solid" align="center">initialised<br>encryption</td>
+ <td style="border:1px solid" align="center">updated<br>encryption</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_CIPHER_CTX_gettable_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">initialised<br>decryption</td>
+ <td style="border:1px solid" align="center">updated<br>decryption</td>
+ <td style="border:1px solid" align="center">initialised<br>encryption</td>
+ <td style="border:1px solid" align="center">updated<br>encryption</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_CIPHER_CTX_settable_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">initialised<br>decryption</td>
+ <td style="border:1px solid" align="center">updated<br>decryption</td>
+ <td style="border:1px solid" align="center">initialised<br>encryption</td>
+ <td style="border:1px solid" align="center">updated<br>encryption</td>
+ <td style="border:1px solid" align="center"></td></tr>
+</table>
+
+=end html
+
+=head1 NOTES
+
+At some point the EVP layer will begin enforcing the transitions described
+herein.
+
+=head1 SEE ALSO
+
+L<provider-cipher(7)>, L<EVP_EncryptInit(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/life_cycle-digest.pod b/doc/man7/life_cycle-digest.pod
new file mode 100644
index 000000000000..709fd0d04ce7
--- /dev/null
+++ b/doc/man7/life_cycle-digest.pod
@@ -0,0 +1,221 @@
+=pod
+
+=head1 NAME
+
+life_cycle-digest - The digest algorithm life-cycle
+
+=head1 DESCRIPTION
+
+All message digests (MDs) go through a number of stages in their life-cycle:
+
+=over 4
+
+=item start
+
+This state represents the MD before it has been allocated. It is the
+starting state for any life-cycle transitions.
+
+=item newed
+
+This state represents the MD after it has been allocated.
+
+=item initialised
+
+This state represents the MD when it is set up and capable of processing
+input.
+
+=item updated
+
+This state represents the MD when it is set up and capable of processing
+additional input or generating output.
+
+=item finaled
+
+This state represents the MD when it has generated output.
+
+=item freed
+
+This state is entered when the MD is freed. It is the terminal state
+for all life-cycle transitions.
+
+=back
+
+=head2 State Transition Diagram
+
+The usual life-cycle of a MD is illustrated:
+
+=begin man
+
+ +-------------------+
+ | start |
+ +-------------------+
+ |
+ | EVP_MD_CTX_new
+ v
+ +-------------------+ EVP_MD_CTX_reset
+ | newed | <------------------------------+
+ +-------------------+ |
+ | |
+ | EVP_DigestInit |
+ v |
+ +-------------------+ |
+ +--> | initialised | <+ EVP_DigestInit |
+ | +-------------------+ | |
+ | | | EVP_DigestUpdate |
+ | | EVP_DigestUpdate | +------------------+ |
+ | v | v | |
+ | +------------------------------------------------+ |
+ EVP_DigestInit | | updated | --+
+ | +------------------------------------------------+ |
+ | | | |
+ | | EVP_DigestFinal | EVP_DigestFinalXOF |
+ | v v |
+ | +------------------------------------------------+ |
+ +--- | finaled | --+
+ +------------------------------------------------+
+ |
+ | EVP_MD_CTX_free
+ v
+ +-------------------+
+ | freed |
+ +-------------------+
+
+=end man
+
+=for html <img src="img/digest.png">
+
+=head2 Formal State Transitions
+
+This section defines all of the legal state transitions.
+This is the canonical list.
+
+=begin man
+
+ Function Call --------------------- Current State ----------------------
+ start newed initialised updated finaled freed
+ EVP_MD_CTX_new newed
+ EVP_DigestInit initialised initialised initialised initialised
+ EVP_DigestUpdate updated updated
+ EVP_DigestFinal finaled
+ EVP_DigestFinalXOF finaled
+ EVP_MD_CTX_free freed freed freed freed freed
+ EVP_MD_CTX_reset newed newed newed newed
+ EVP_MD_CTX_get_params newed initialised updated
+ EVP_MD_CTX_set_params newed initialised updated
+ EVP_MD_CTX_gettable_params newed initialised updated
+ EVP_MD_CTX_settable_params newed initialised updated
+
+=end man
+
+=begin html
+
+<table style="border:1px solid; border-collapse:collapse">
+<tr><th style="border:1px solid" align="left">Function Call</th>
+ <th style="border:1px solid" colspan="6">Current State</th></tr>
+<tr><th style="border:1px solid"></th>
+ <th style="border:1px solid" align="center">start</th>
+ <th style="border:1px solid" align="center">newed</th>
+ <th style="border:1px solid" align="center">initialised</th>
+ <th style="border:1px solid" align="center">updated</th>
+ <th style="border:1px solid" align="center">finaled</th>
+ <th style="border:1px solid" align="center">freed</th></tr>
+<tr><th style="border:1px solid" align="left">EVP_MD_CTX_new</th>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_DigestInit</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_DigestUpdate</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_DigestFinal</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">finaled</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_DigestFinalXOF</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">finaled</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_MD_CTX_free</th>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_MD_CTX_reset</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_MD_CTX_get_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_MD_CTX_set_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_MD_CTX_gettable_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_MD_CTX_settable_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+</table>
+
+=end html
+
+=head1 NOTES
+
+At some point the EVP layer will begin enforcing the transitions described
+herein.
+
+=head1 SEE ALSO
+
+L<provider-digest(7)>, L<EVP_DigestInit(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/life_cycle-kdf.pod b/doc/man7/life_cycle-kdf.pod
new file mode 100644
index 000000000000..9fe042a2c24d
--- /dev/null
+++ b/doc/man7/life_cycle-kdf.pod
@@ -0,0 +1,165 @@
+=pod
+
+=head1 NAME
+
+life_cycle-kdf - The KDF algorithm life-cycle
+
+=head1 DESCRIPTION
+
+All key derivation functions (KDFs) and pseudo random functions (PRFs)
+go through a number of stages in their life-cycle:
+
+=over 4
+
+=item start
+
+This state represents the KDF/PRF before it has been allocated. It is the
+starting state for any life-cycle transitions.
+
+=item newed
+
+This state represents the KDF/PRF after it has been allocated.
+
+=item deriving
+
+This state represents the KDF/PRF when it is set up and capable of generating
+output.
+
+=item freed
+
+This state is entered when the KDF/PRF is freed. It is the terminal state
+for all life-cycle transitions.
+
+=back
+
+=head2 State Transition Diagram
+
+The usual life-cycle of a KDF/PRF is illustrated:
+
+=begin man
+
+ +-------------------+
+ | start |
+ +-------------------+
+ |
+ | EVP_KDF_CTX_new
+ v
+ +-------------------+
+ | newed | <+
+ +-------------------+ |
+ | |
+ | EVP_KDF_derive |
+ v | EVP_KDF_CTX_reset
+ EVP_KDF_derive +-------------------+ |
+ + - - - - - - - - | | |
+ ' | deriving | |
+ + - - - - - - - -> | | -+
+ +-------------------+
+ |
+ | EVP_KDF_CTX_free
+ v
+ +-------------------+
+ | freed |
+ +-------------------+
+
+=end man
+
+=for html <img src="img/kdf.png">
+
+=head2 Formal State Transitions
+
+This section defines all of the legal state transitions.
+This is the canonical list.
+
+=begin man
+
+ Function Call ------------- Current State -------------
+ start newed deriving freed
+ EVP_KDF_CTX_new newed
+ EVP_KDF_derive deriving deriving
+ EVP_KDF_CTX_free freed freed freed
+ EVP_KDF_CTX_reset newed newed
+ EVP_KDF_CTX_get_params newed deriving
+ EVP_KDF_CTX_set_params newed deriving
+ EVP_KDF_CTX_gettable_params newed deriving
+ EVP_KDF_CTX_settable_params newed deriving
+
+=end man
+
+=begin html
+
+<table style="border:1px solid; border-collapse:collapse">
+<tr><th style="border:1px solid" align="left">Function Call</th>
+ <th style="border:1px solid" colspan="4">Current State</th></tr>
+<tr><th style="border:1px solid"></th>
+ <th style="border:1px solid" align="center">start</th>
+ <th style="border:1px solid" align="center">newed</th>
+ <th style="border:1px solid" align="center">deriving</th>
+ <th style="border:1px solid" align="center">freed</th></tr>
+<tr><th style="border:1px solid" align="left">EVP_KDF_CTX_new</th>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid"></td>
+ <td style="border:1px solid"></td>
+ <td style="border:1px solid"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_KDF_derive</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">deriving</td>
+ <td style="border:1px solid" align="center">deriving</td>
+ <td style="border:1px solid"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_KDF_CTX_free</th>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_KDF_CTX_reset</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_KDF_CTX_get_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">deriving</td>
+ <td style="border:1px solid"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_KDF_CTX_set_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">deriving</td>
+ <td style="border:1px solid"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_KDF_CTX_gettable_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">deriving</td>
+ <td style="border:1px solid"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_KDF_CTX_settable_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">deriving</td>
+ <td style="border:1px solid"></td></tr>
+</table>
+
+=end html
+
+=head1 NOTES
+
+At some point the EVP layer will begin enforcing the transitions described
+herein.
+
+=head1 SEE ALSO
+
+L<provider-kdf(7)>, L<EVP_KDF(3)>.
+
+=head1 HISTORY
+
+The provider KDF interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/life_cycle-mac.pod b/doc/man7/life_cycle-mac.pod
new file mode 100644
index 000000000000..60b8b55d4bf0
--- /dev/null
+++ b/doc/man7/life_cycle-mac.pod
@@ -0,0 +1,218 @@
+=pod
+
+=head1 NAME
+
+life_cycle-mac - The MAC algorithm life-cycle
+
+=head1 DESCRIPTION
+
+All message authentication codes (MACs)
+go through a number of stages in their life-cycle:
+
+=over 4
+
+=item start
+
+This state represents the MAC before it has been allocated. It is the
+starting state for any life-cycle transitions.
+
+=item newed
+
+This state represents the MAC after it has been allocated.
+
+=item initialised
+
+This state represents the MAC when it is set up and capable of processing
+input.
+
+=item updated
+
+This state represents the MAC when it is set up and capable of processing
+additional input or generating output.
+
+=item finaled
+
+This state represents the MAC when it has generated output.
+
+=item freed
+
+This state is entered when the MAC is freed. It is the terminal state
+for all life-cycle transitions.
+
+=back
+
+=head2 State Transition Diagram
+
+The usual life-cycle of a MAC is illustrated:
+
+=begin man
+
+ +-------------------+
+ | start |
+ +-------------------+
+ |
+ | EVP_MAC_CTX_new
+ v
+ +-------------------+
+ | newed |
+ +-------------------+
+ |
+ | EVP_MAC_init
+ v
+ +-------------------+
+ +> | initialised | <+
+ | +-------------------+ |
+ | | |
+ | | EVP_MAC_update | EVP_MAC_init
+ | v |
+ EVP_MAC_init | +-------------------+ |
+ | | updated | -+
+ | +-------------------+
+ | | |
+ | | EVP_MAC_final | EVP_MAC_finalXOF
+ | v v
+ | +-------------------+
+ +- | finaled |
+ +-------------------+
+ |
+ | EVP_MAC_CTX_free
+ v
+ +-------------------+
+ | freed |
+ +-------------------+
+
+=end man
+
+=for html <img src="img/mac.png">
+
+=head2 Formal State Transitions
+
+This section defines all of the legal state transitions.
+This is the canonical list.
+
+=begin man
+
+ Function Call --------------------- Current State ----------------------
+ start newed initialised updated finaled freed
+ EVP_MAC_CTX_new newed
+ EVP_MAC_init initialised initialised initialised initialised
+ EVP_MAC_update updated updated
+ EVP_MAC_final finaled
+ EVP_MAC_finalXOF finaled
+ EVP_MAC_CTX_free freed freed freed freed freed
+ EVP_MAC_CTX_get_params newed initialised updated
+ EVP_MAC_CTX_set_params newed initialised updated
+ EVP_MAC_CTX_gettable_params newed initialised updated
+ EVP_MAC_CTX_settable_params newed initialised updated
+
+=end man
+
+=begin html
+
+<table style="border:1px solid; border-collapse:collapse">
+<tr><th style="border:1px solid" align="left">Function Call</th>
+ <th style="border:1px solid" colspan="6">Current State</th></tr>
+<tr><th style="border:1px solid"></th>
+ <th style="border:1px solid" align="center">start</th>
+ <th style="border:1px solid" align="center">newed</th>
+ <th style="border:1px solid" align="center">initialised</th>
+ <th style="border:1px solid" align="center">updated</th>
+ <th style="border:1px solid" align="center">finaled</th>
+ <th style="border:1px solid" align="center">freed</th></tr>
+<tr><th style="border:1px solid" align="left">EVP_MAC_CTX_new</th>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_MAC_init</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_MAC_update</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_MAC_final</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">finaled</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_MAC_finalXOF</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">finaled</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_MAC_CTX_free</th>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_MAC_CTX_get_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_MAC_CTX_set_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_MAC_CTX_gettable_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_MAC_CTX_settable_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">initialised</td>
+ <td style="border:1px solid" align="center">updated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+</table>
+
+=end html
+
+=head1 NOTES
+
+At some point the EVP layer will begin enforcing the transitions described
+herein.
+
+=head1 SEE ALSO
+
+L<provider-mac(7)>, L<EVP_MAC(3)>.
+
+=head1 HISTORY
+
+The provider MAC interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/life_cycle-pkey.pod b/doc/man7/life_cycle-pkey.pod
new file mode 100644
index 000000000000..6768750f4819
--- /dev/null
+++ b/doc/man7/life_cycle-pkey.pod
@@ -0,0 +1,713 @@
+=pod
+
+=head1 NAME
+
+life_cycle-pkey - The PKEY algorithm life-cycle
+
+=head1 DESCRIPTION
+
+All public keys (PKEYs) go through a number of stages in their life-cycle:
+
+=over 4
+
+=item start
+
+This state represents the PKEY before it has been allocated. It is the
+starting state for any life-cycle transitions.
+
+=item newed
+
+This state represents the PKEY after it has been allocated.
+
+=item decapsulate
+
+This state represents the PKEY when it is ready to perform a private key decapsulation
+opeartion.
+
+=item decrypt
+
+This state represents the PKEY when it is ready to decrypt some ciphertext.
+
+=item derive
+
+This state represents the PKEY when it is ready to derive a shared secret.
+
+=item digest sign
+
+This state represents the PKEY when it is ready to perform a private key signature
+operation.
+
+=item encapsulate
+
+This state represents the PKEY when it is ready to perform a public key encapsulation
+opeartion.
+
+=item encrypt
+
+This state represents the PKEY when it is ready to encrypt some plaintext.
+
+=item key generation
+
+This state represents the PKEY when it is ready to generate a new public/private key.
+
+=item parameter generation
+
+This state represents the PKEY when it is ready to generate key parameters.
+
+=item verify
+
+This state represents the PKEY when it is ready to verify a public key signature.
+
+=item verify recover
+
+This state represents the PKEY when it is ready to recover a public key signature data.
+
+=item freed
+
+This state is entered when the PKEY is freed. It is the terminal state
+for all life-cycle transitions.
+
+=back
+
+=head2 State Transition Diagram
+
+The usual life-cycle of a PKEY object is illustrated:
+
+=begin man
+
+ +-------------+
+ | |
+ | start |
+ | |
+ EVP_PKEY_derive +-------------+
+ +-------------+ EVP_PKEY_derive_set_peer | +-------------+
+ | |----------------------------+ | +----------------------------| |
+ | derive | | | | EVP_PKEY_verify | verify |
+ | |<---------------------------+ | +--------------------------->| |
+ +-------------+ | +-------------+
+ ^ | ^
+ | EVP_PKEY_derive_init | EVP_PKEY_verify_init |
+ +---------------------------------------+ | +---------------------------------------+
+ | | |
+ +-------------+ | | | +-------------+
+ | |----------------------------+ | | | +----------------------------| |
+ | digest sign | EVP_PKEY_sign | | | | | EVP_PKEY_verify_recover | verify |
+ | |<---------------------------+ | | | +--------------------------->| recover |
+ +-------------+ | | | +-------------+
+ ^ | | | ^
+ | EVP_PKEY_sign_init | | | EVP_PKEY_verify_recover_init |
+ +---------------------------------+ | | | +---------------------------------+
+ | | | | |
+ +-------------+ | | | | | +-------------+
+ | |----------------------------+ | | | | | +----------------------------| |
+ | decapsulate | EVP_PKEY_decapsulate | | | | | | | EVP_PKEY_decrypt | decrypt |
+ | |<---------------------------+ | | v | | +--------------------------->| |
+ +-------------+ | +-------------+ | +-------------+
+ ^ +---| |---+ ^
+ | EVP_PKEY_decapsulate_init | | EVP_PKEY_decrypt_init |
+ +-------------------------------------| newed |-------------------------------------+
+ | |
+ +---| |---+
+ +-------------+ | +-------------+ | +-------------+
+ | |----------------------------+ | | | | +----------------------------| |
+ | encapsulate | EVP_PKEY_encapsulate | | | | | | EVP_PKEY_encrypt | encrypt |
+ | |<---------------------------+ | | | | +--------------------------->| |
+ +-------------+ | | | | +-------------+
+ ^ | | | | ^
+ | EVP_PKEY_encapsulate_init | | | | EVP_PKEY_encrypt_init |
+ +---------------------------------+ | | +---------------------------------+
+ | |
+ +---------------------------------------+ +---------------------------------------+
+ | EVP_PKEY_paramgen_init EVP_PKEY_keygen_init |
+ v v
+ +-------------+ +-------------+
+ | |----------------------------+ +----------------------------| |
+ | parameter | | | | key |
+ | generation |<---------------------------+ +--------------------------->| generation |
+ +-------------+ EVP_PKEY_paramgen EVP_PKEY_keygen +-------------+
+ EVP_PKEY_gen EVP_PKEY_gen
+
+
+ + - - - - - + +-----------+
+ ' ' EVP_PKEY_CTX_free | |
+ ' any state '------------------->| freed |
+ ' ' | |
+ + - - - - - + +-----------+
+
+=end man
+
+=for html <img src="img/pkey.png">
+
+=head2 Formal State Transitions
+
+This section defines all of the legal state transitions.
+This is the canonical list.
+
+=begin man
+
+ Function Call ---------------------------------------------------------------------- Current State ----------------------------------------------------------------------
+ start newed digest verify verify encrypt decrypt derive encapsulate decapsulate parameter key freed
+ sign recover generation generation
+ EVP_PKEY_CTX_new newed
+ EVP_PKEY_CTX_new_id newed
+ EVP_PKEY_CTX_new_from_name newed
+ EVP_PKEY_CTX_new_from_pkey newed
+ EVP_PKEY_sign_init digest digest digest digest digest digest digest digest digest digest digest
+ sign sign sign sign sign sign sign sign sign sign sign
+ EVP_PKEY_sign digest
+ sign
+ EVP_PKEY_verify_init verify verify verify verify verify verify verify verify verify verify verify
+ EVP_PKEY_verify verify
+ EVP_PKEY_verify_recover_init verify verify verify verify verify verify verify verify verify verify verify
+ recover recover recover recover recover recover recover recover recover recover recover
+ EVP_PKEY_verify_recover verify
+ recover
+ EVP_PKEY_encrypt_init encrypt encrypt encrypt encrypt encrypt encrypt encrypt encrypt encrypt encrypt encrypt
+ EVP_PKEY_encrypt encrypt
+ EVP_PKEY_decrypt_init decrypt decrypt decrypt decrypt decrypt decrypt decrypt decrypt decrypt decrypt decrypt
+ EVP_PKEY_decrypt decrypt
+ EVP_PKEY_derive_init derive derive derive derive derive derive derive derive derive derive derive
+ EVP_PKEY_derive_set_peer derive
+ EVP_PKEY_derive derive
+ EVP_PKEY_encapsulate_init encapsulate encapsulate encapsulate encapsulate encapsulate encapsulate encapsulate encapsulate encapsulate encapsulate encapsulate
+ EVP_PKEY_encapsulate encapsulate
+ EVP_PKEY_decapsulate_init decapsulate decapsulate decapsulate decapsulate decapsulate decapsulate decapsulate decapsulate decapsulate decapsulate decapsulate
+ EVP_PKEY_decapsulate decapsulate
+ EVP_PKEY_paramgen_init parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter
+ generation generation generation generation generation generation generation generation generation generation generation
+ EVP_PKEY_paramgen parameter
+ generation
+ EVP_PKEY_keygen_init key key key key key key key key key key key
+ generation generation generation generation generation generation generation generation generation generation generation
+ EVP_PKEY_keygen key
+ generation
+ EVP_PKEY_gen parameter key
+ generation generation
+ EVP_PKEY_CTX_get_params newed digest verify verify encrypt decrypt derive encapsulate decapsulate parameter key
+ sign recover generation generation
+ EVP_PKEY_CTX_set_params newed digest verify verify encrypt decrypt derive encapsulate decapsulate parameter key
+ sign recover generation generation
+ EVP_PKEY_CTX_gettable_params newed digest verify verify encrypt decrypt derive encapsulate decapsulate parameter key
+ sign recover generation generation
+ EVP_PKEY_CTX_settable_params newed digest verify verify encrypt decrypt derive encapsulate decapsulate parameter key
+ sign recover generation generation
+ EVP_PKEY_CTX_free freed freed freed freed freed freed freed freed freed freed freed freed
+
+=end man
+
+=begin html
+
+<table style="border:1px solid; border-collapse:collapse">
+<tr><th style="border:1px solid" align="left">Function Call</th>
+ <th style="border:1px solid" colspan="13">Current State</th></tr>
+<tr><th style="border:1px solid"></th>
+ <th style="border:1px solid" align="center">start</th>
+ <th style="border:1px solid" align="center">newed</th>
+ <th style="border:1px solid" align="center">digest<br>sign</th>
+ <th style="border:1px solid" align="center">verify</th>
+ <th style="border:1px solid" align="center">verify<br>recover</th>
+ <th style="border:1px solid" align="center">encrypt</th>
+ <th style="border:1px solid" align="center">decrypt</th>
+ <th style="border:1px solid" align="center">derive</th>
+ <th style="border:1px solid" align="center">encapsulate</th>
+ <th style="border:1px solid" align="center">decapsulate</th>
+ <th style="border:1px solid" align="center">parameter<br>generation</th>
+ <th style="border:1px solid" align="center">key<br>generation</th>
+ <th style="border:1px solid" align="center">freed</th>
+</tr>
+
+<tr><th style="border:1px solid" align="left">EVP_PKEY_CTX_new</th>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_CTX_new_id</th>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_CTX_new_from_name</th>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_CTX_new_from_pkey</th>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_sign_init</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">digest<br>sign</td>
+ <td style="border:1px solid" align="center">digest<br>sign</td>
+ <td style="border:1px solid" align="center">digest<br>sign</td>
+ <td style="border:1px solid" align="center">digest<br>sign</td>
+ <td style="border:1px solid" align="center">digest<br>sign</td>
+ <td style="border:1px solid" align="center">digest<br>sign</td>
+ <td style="border:1px solid" align="center">digest<br>sign</td>
+ <td style="border:1px solid" align="center">digest<br>sign</td>
+ <td style="border:1px solid" align="center">digest<br>sign</td>
+ <td style="border:1px solid" align="center">digest<br>sign</td>
+ <td style="border:1px solid" align="center">digest<br>sign</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_sign</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">digest<br>sign</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_verify_init</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">verify</td>
+ <td style="border:1px solid" align="center">verify</td>
+ <td style="border:1px solid" align="center">verify</td>
+ <td style="border:1px solid" align="center">verify</td>
+ <td style="border:1px solid" align="center">verify</td>
+ <td style="border:1px solid" align="center">verify</td>
+ <td style="border:1px solid" align="center">verify</td>
+ <td style="border:1px solid" align="center">verify</td>
+ <td style="border:1px solid" align="center">verify</td>
+ <td style="border:1px solid" align="center">verify</td>
+ <td style="border:1px solid" align="center">verify</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_verify</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">verify</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_verify_recover_init</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">verify<br>recover</td>
+ <td style="border:1px solid" align="center">verify<br>recover</td>
+ <td style="border:1px solid" align="center">verify<br>recover</td>
+ <td style="border:1px solid" align="center">verify<br>recover</td>
+ <td style="border:1px solid" align="center">verify<br>recover</td>
+ <td style="border:1px solid" align="center">verify<br>recover</td>
+ <td style="border:1px solid" align="center">verify<br>recover</td>
+ <td style="border:1px solid" align="center">verify<br>recover</td>
+ <td style="border:1px solid" align="center">verify<br>recover</td>
+ <td style="border:1px solid" align="center">verify<br>recover</td>
+ <td style="border:1px solid" align="center">verify<br>recover</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_verify_recover</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">verify<br>recover</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_encrypt_init</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">encrypt</td>
+ <td style="border:1px solid" align="center">encrypt</td>
+ <td style="border:1px solid" align="center">encrypt</td>
+ <td style="border:1px solid" align="center">encrypt</td>
+ <td style="border:1px solid" align="center">encrypt</td>
+ <td style="border:1px solid" align="center">encrypt</td>
+ <td style="border:1px solid" align="center">encrypt</td>
+ <td style="border:1px solid" align="center">encrypt</td>
+ <td style="border:1px solid" align="center">encrypt</td>
+ <td style="border:1px solid" align="center">encrypt</td>
+ <td style="border:1px solid" align="center">encrypt</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_encrypt</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">encrypt</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_decrypt_init</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">decrypt</td>
+ <td style="border:1px solid" align="center">decrypt</td>
+ <td style="border:1px solid" align="center">decrypt</td>
+ <td style="border:1px solid" align="center">decrypt</td>
+ <td style="border:1px solid" align="center">decrypt</td>
+ <td style="border:1px solid" align="center">decrypt</td>
+ <td style="border:1px solid" align="center">decrypt</td>
+ <td style="border:1px solid" align="center">decrypt</td>
+ <td style="border:1px solid" align="center">decrypt</td>
+ <td style="border:1px solid" align="center">decrypt</td>
+ <td style="border:1px solid" align="center">decrypt</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_decrypt</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">decrypt</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_derive_init</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_derive_set_peer</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_derive</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_encapsulate_init</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">encapsulate</td>
+ <td style="border:1px solid" align="center">encapsulate</td>
+ <td style="border:1px solid" align="center">encapsulate</td>
+ <td style="border:1px solid" align="center">encapsulate</td>
+ <td style="border:1px solid" align="center">encapsulate</td>
+ <td style="border:1px solid" align="center">encapsulate</td>
+ <td style="border:1px solid" align="center">encapsulate</td>
+ <td style="border:1px solid" align="center">encapsulate</td>
+ <td style="border:1px solid" align="center">encapsulate</td>
+ <td style="border:1px solid" align="center">encapsulate</td>
+ <td style="border:1px solid" align="center">encapsulate</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_encapsulate</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">encapsulate</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_decapsulate_init</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">decapsulate</td>
+ <td style="border:1px solid" align="center">decapsulate</td>
+ <td style="border:1px solid" align="center">decapsulate</td>
+ <td style="border:1px solid" align="center">decapsulate</td>
+ <td style="border:1px solid" align="center">decapsulate</td>
+ <td style="border:1px solid" align="center">decapsulate</td>
+ <td style="border:1px solid" align="center">decapsulate</td>
+ <td style="border:1px solid" align="center">decapsulate</td>
+ <td style="border:1px solid" align="center">decapsulate</td>
+ <td style="border:1px solid" align="center">decapsulate</td>
+ <td style="border:1px solid" align="center">decapsulate</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_decapsulate</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">decapsulate</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_paramgen_init</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_paramgen</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_keygen_init</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_keygen</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_gen</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_CTX_get_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">digest<br>sign</td>
+ <td style="border:1px solid" align="center">verify</td>
+ <td style="border:1px solid" align="center">verify<br>recover</td>
+ <td style="border:1px solid" align="center">encrypt</td>
+ <td style="border:1px solid" align="center">decrypt</td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center">encapsulate</td>
+ <td style="border:1px solid" align="center">decapsulate</td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_CTX_set_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">digest<br>sign</td>
+ <td style="border:1px solid" align="center">verify</td>
+ <td style="border:1px solid" align="center">verify<br>recover</td>
+ <td style="border:1px solid" align="center">encrypt</td>
+ <td style="border:1px solid" align="center">decrypt</td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center">encapsulate</td>
+ <td style="border:1px solid" align="center">decapsulate</td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_CTX_gettable_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">digest<br>sign</td>
+ <td style="border:1px solid" align="center">verify</td>
+ <td style="border:1px solid" align="center">verify<br>recover</td>
+ <td style="border:1px solid" align="center">encrypt</td>
+ <td style="border:1px solid" align="center">decrypt</td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center">encapsulate</td>
+ <td style="border:1px solid" align="center">decapsulate</td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_CTX_settable_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">digest<br>sign</td>
+ <td style="border:1px solid" align="center">verify</td>
+ <td style="border:1px solid" align="center">verify<br>recover</td>
+ <td style="border:1px solid" align="center">encrypt</td>
+ <td style="border:1px solid" align="center">decrypt</td>
+ <td style="border:1px solid" align="center">derive</td>
+ <td style="border:1px solid" align="center">encapsulate</td>
+ <td style="border:1px solid" align="center">decapsulate</td>
+ <td style="border:1px solid" align="center">parameter<br>generation</td>
+ <td style="border:1px solid" align="center">key<br>generation</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+<tr><th style="border:1px solid" align="left">EVP_PKEY_CTX_free</th>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center"></td>
+</tr>
+</table>
+
+=end html
+
+=head1 NOTES
+
+At some point the EVP layer will begin enforcing the transitions described
+herein.
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_new(3)>,
+L<EVP_PKEY_decapsulate(3)>, L<EVP_PKEY_decrypt(3)>, L<EVP_PKEY_encapsulate(3)>,
+L<EVP_PKEY_encrypt(3)>, L<EVP_PKEY_derive(3)>, L<EVP_PKEY_keygen(3)>,
+L<EVP_PKEY_sign(3)>, L<EVP_PKEY_verify(3)>, L<EVP_PKEY_verify_recover(3)>
+
+=head1 HISTORY
+
+The provider PKEY interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/life_cycle-rand.pod b/doc/man7/life_cycle-rand.pod
new file mode 100644
index 000000000000..8afb229b58ba
--- /dev/null
+++ b/doc/man7/life_cycle-rand.pod
@@ -0,0 +1,193 @@
+=pod
+
+=head1 NAME
+
+life_cycle-rand - The RAND algorithm life-cycle
+
+=head1 DESCRIPTION
+
+All random number generator (RANDs)
+go through a number of stages in their life-cycle:
+
+=over 4
+
+=item start
+
+This state represents the RAND before it has been allocated. It is the
+starting state for any life-cycle transitions.
+
+=item newed
+
+This state represents the RAND after it has been allocated but unable to
+generate any output.
+
+=item instantiated
+
+This state represents the RAND when it is set up and capable of generating
+output.
+
+=item uninstantiated
+
+This state represents the RAND when it has been shutdown and it is no longer
+capable of generating output.
+
+=item freed
+
+This state is entered when the RAND is freed. It is the terminal state
+for all life-cycle transitions.
+
+=back
+
+=head2 State Transition Diagram
+
+The usual life-cycle of a RAND is illustrated:
+
+=begin man
+
+ +-------------------------+
+ | start |
+ +-------------------------+
+ |
+ | EVP_RAND_CTX_new
+ v
+ +-------------------------+
+ | newed |
+ +-------------------------+
+ |
+ | EVP_RAND_instantiate
+ v
+ EVP_RAND_generate +-------------------------+
+ +-------------------- | |
+ | | instantiated |
+ +-------------------> | | <+
+ +-------------------------+ '
+ | '
+ | EVP_RAND_uninstantiate ' EVP_RAND_instantiate
+ v '
+ +-------------------------+ '
+ | uninstantiated | -+
+ +-------------------------+
+ |
+ | EVP_RAND_CTX_free
+ v
+ +-------------------------+
+ | freed |
+ +-------------------------+
+
+=end man
+
+=for html <img src="img/rand.png">
+
+=head2 Formal State Transitions
+
+This section defines all of the legal state transitions.
+This is the canonical list.
+
+=begin man
+
+ Function Call ------------------ Current State ------------------
+ start newed instantiated uninstantiated freed
+ EVP_RAND_CTX_new newed
+ EVP_RAND_instantiate instantiated
+ EVP_RAND_generate instantiated
+ EVP_RAND_uninstantiate uninstantiated
+ EVP_RAND_CTX_free freed freed freed freed
+ EVP_RAND_CTX_get_params newed instantiated uninstantiated freed
+ EVP_RAND_CTX_set_params newed instantiated uninstantiated freed
+ EVP_RAND_CTX_gettable_params newed instantiated uninstantiated freed
+ EVP_RAND_CTX_settable_params newed instantiated uninstantiated freed
+
+=end man
+
+=begin html
+
+<table style="border:1px solid; border-collapse:collapse">
+<tr><th style="border:1px solid" align="left">Function Call</th>
+ <th style="border:1px solid" colspan="5">Current State</th></tr>
+<tr><th style="border:1px solid"></th>
+ <th style="border:1px solid" align="center">start</th>
+ <th style="border:1px solid" align="center">newed</th>
+ <th style="border:1px solid" align="center">instantiated</th>
+ <th style="border:1px solid" align="center">uninstantiated</th>
+ <th style="border:1px solid" align="center">freed</th></tr>
+<tr><th style="border:1px solid" align="left">EVP_RAND_CTX_new</th>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_RAND_instantiate</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">instantiated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_RAND_generate</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">instantiated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_RAND_uninstantiate</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">uninstantiated</td>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_RAND_CTX_free</th>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center">freed</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_RAND_CTX_get_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">instantiated</td>
+ <td style="border:1px solid" align="center">uninstantiated</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_RAND_CTX_set_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">instantiated</td>
+ <td style="border:1px solid" align="center">uninstantiated</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_RAND_CTX_gettable_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">instantiated</td>
+ <td style="border:1px solid" align="center">uninstantiated</td>
+ <td style="border:1px solid" align="center"></td></tr>
+<tr><th style="border:1px solid" align="left">EVP_RAND_CTX_settable_params</th>
+ <td style="border:1px solid" align="center"></td>
+ <td style="border:1px solid" align="center">newed</td>
+ <td style="border:1px solid" align="center">instantiated</td>
+ <td style="border:1px solid" align="center">uninstantiated</td>
+ <td style="border:1px solid" align="center"></td></tr>
+</table>
+
+=end html
+
+=head1 NOTES
+
+At some point the EVP layer will begin enforcing the transitions described
+herein.
+
+=head1 SEE ALSO
+
+L<provider-rand(7)>, L<EVP_RAND(3)>.
+
+=head1 HISTORY
+
+The provider RAND interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/migration_guide.pod b/doc/man7/migration_guide.pod
new file mode 100644
index 000000000000..a234147f46a0
--- /dev/null
+++ b/doc/man7/migration_guide.pod
@@ -0,0 +1,2432 @@
+=pod
+
+=head1 NAME
+
+migration_guide - OpenSSL migration guide
+
+=head1 SYNOPSIS
+
+See the individual manual pages for details.
+
+=head1 DESCRIPTION
+
+This guide details the changes required to migrate to new versions of OpenSSL.
+Currently this covers OpenSSL 3.0. For earlier versions refer to
+L<https://github.com/openssl/openssl/blob/master/CHANGES.md>.
+For an overview of some of the key concepts introduced in OpenSSL 3.0 see
+L<crypto(7)>.
+
+=head1 OPENSSL 3.0
+
+=head2 Main Changes from OpenSSL 1.1.1
+
+=head3 Major Release
+
+OpenSSL 3.0 is a major release and consequently any application that currently
+uses an older version of OpenSSL will at the very least need to be recompiled in
+order to work with the new version. It is the intention that the large majority
+of applications will work unchanged with OpenSSL 3.0 if those applications
+previously worked with OpenSSL 1.1.1. However this is not guaranteed and some
+changes may be required in some cases. Changes may also be required if
+applications need to take advantage of some of the new features available in
+OpenSSL 3.0 such as the availability of the FIPS module.
+
+=head3 License Change
+
+In previous versions, OpenSSL was licensed under the L<dual OpenSSL and SSLeay
+licenses|https://www.openssl.org/source/license-openssl-ssleay.txt>
+(both licenses apply). From OpenSSL 3.0 this is replaced by the
+L<Apache License v2|https://www.openssl.org/source/apache-license-2.0.txt>.
+
+=head3 Providers and FIPS support
+
+One of the key changes from OpenSSL 1.1.1 is the introduction of the Provider
+concept. Providers collect together and make available algorithm implementations.
+With OpenSSL 3.0 it is possible to specify, either programmatically or via a
+config file, which providers you want to use for any given application.
+OpenSSL 3.0 comes with 5 different providers as standard. Over time third
+parties may distribute additional providers that can be plugged into OpenSSL.
+All algorithm implementations available via providers are accessed through the
+"high level" APIs (for example those functions prefixed with C<EVP>). They cannot
+be accessed using the L</Low Level APIs>.
+
+One of the standard providers available is the FIPS provider. This makes
+available FIPS validated cryptographic algorithms.
+The FIPS provider is disabled by default and needs to be enabled explicitly
+at configuration time using the C<enable-fips> option. If it is enabled,
+the FIPS provider gets built and installed in addition to the other standard
+providers. No separate installation procedure is necessary.
+There is however a dedicated C<install_fips> make target, which serves the
+special purpose of installing only the FIPS provider into an existing
+OpenSSL installation.
+
+Not all algorithms may be available for the application at a particular moment.
+If the application code uses any digest or cipher algorithm via the EVP interface,
+the application should verify the result of the L<EVP_EncryptInit(3)>,
+L<EVP_EncryptInit_ex(3)>, and L<EVP_DigestInit(3)> functions. In case when
+the requested algorithm is not available, these functions will fail.
+
+See also L</Legacy Algorithms> for information on the legacy provider.
+
+See also L</Completing the installation of the FIPS Module> and
+L</Using the FIPS Module in applications>.
+
+=head3 Low Level APIs
+
+OpenSSL has historically provided two sets of APIs for invoking cryptographic
+algorithms: the "high level" APIs (such as the C<EVP> APIs) and the "low level"
+APIs. The high level APIs are typically designed to work across all algorithm
+types. The "low level" APIs are targeted at a specific algorithm implementation.
+For example, the EVP APIs provide the functions L<EVP_EncryptInit_ex(3)>,
+L<EVP_EncryptUpdate(3)> and L<EVP_EncryptFinal(3)> to perform symmetric
+encryption. Those functions can be used with the algorithms AES, CHACHA, 3DES etc.
+On the other hand, to do AES encryption using the low level APIs you would have
+to call AES specific functions such as L<AES_set_encrypt_key(3)>,
+L<AES_encrypt(3)>, and so on. The functions for 3DES are different.
+Use of the low level APIs has been informally discouraged by the OpenSSL
+development team for a long time. However in OpenSSL 3.0 this is made more
+formal. All such low level APIs have been deprecated. You may still use them in
+your applications, but you may start to see deprecation warnings during
+compilation (dependent on compiler support for this). Deprecated APIs may be
+removed from future versions of OpenSSL so you are strongly encouraged to update
+your code to use the high level APIs instead.
+
+This is described in more detail in L</Deprecation of Low Level Functions>
+
+=head3 Legacy Algorithms
+
+Some cryptographic algorithms such as B<MD2> and B<DES> that were available via
+the EVP APIs are now considered legacy and their use is strongly discouraged.
+These legacy EVP algorithms are still available in OpenSSL 3.0 but not by
+default. If you want to use them then you must load the legacy provider.
+This can be as simple as a config file change, or can be done programmatically.
+See L<OSSL_PROVIDER-legacy(7)> for a complete list of algorithms.
+Applications using the EVP APIs to access these algorithms should instead use
+more modern algorithms. If that is not possible then these applications
+should ensure that the legacy provider has been loaded. This can be achieved
+either programmatically or via configuration. See L<crypto(7)> man page for
+more information about providers.
+
+=head3 Engines and "METHOD" APIs
+
+The refactoring to support Providers conflicts internally with the APIs used to
+support engines, including the ENGINE API and any function that creates or
+modifies custom "METHODS" (for example L<EVP_MD_meth_new(3)>,
+L<EVP_CIPHER_meth_new(3)>, L<EVP_PKEY_meth_new(3)>, L<RSA_meth_new(3)>,
+L<EC_KEY_METHOD_new(3)>, etc.). These functions are being deprecated in
+OpenSSL 3.0, and users of these APIs should know that their use can likely
+bypass provider selection and configuration, with unintended consequences.
+This is particularly relevant for applications written to use the OpenSSL 3.0
+FIPS module, as detailed below. Authors and maintainers of external engines are
+strongly encouraged to refactor their code transforming engines into providers
+using the new Provider API and avoiding deprecated methods.
+
+=head3 Support of legacy engines
+
+If openssl is not built without engine support or deprecated API support, engines
+will still work. However, their applicability will be limited.
+
+New algorithms provided via engines will still work.
+
+Engine-backed keys can be loaded via custom B<OSSL_STORE> implementation.
+In this case the B<EVP_PKEY> objects created via L<ENGINE_load_private_key(3)>
+will be concidered legacy and will continue to work.
+
+To ensure the future compatibility, the engines should be turned to providers.
+To prefer the provider-based hardware offload, you can specify the default
+properties to prefer your provider.
+
+=head3 Versioning Scheme
+
+The OpenSSL versioning scheme has changed with the OpenSSL 3.0 release. The new
+versioning scheme has this format:
+
+MAJOR.MINOR.PATCH
+
+For OpenSSL 1.1.1 and below, different patch levels were indicated by a letter
+at the end of the release version number. This will no longer be used and
+instead the patch level is indicated by the final number in the version. A
+change in the second (MINOR) number indicates that new features may have been
+added. OpenSSL versions with the same major number are API and ABI compatible.
+If the major number changes then API and ABI compatibility is not guaranteed.
+
+For more information, see L<OpenSSL_version(3)>.
+
+=head3 Other major new features
+
+=head4 Certificate Management Protocol (CMP, RFC 4210)
+
+This also covers CRMF (RFC 4211) and HTTP transfer (RFC 6712)
+See L<openssl-cmp(1)> and L<OSSL_CMP_exec_certreq(3)> as starting points.
+
+=head4 HTTP(S) client
+
+A proper HTTP(S) client that supports GET and POST, redirection, plain and
+ASN.1-encoded contents, proxies, and timeouts.
+
+=head4 Key Derivation Function API (EVP_KDF)
+
+This simplifies the process of adding new KDF and PRF implementations.
+
+Previously KDF algorithms had been shoe-horned into using the EVP_PKEY object
+which was not a logical mapping.
+Existing applications that use KDF algorithms using EVP_PKEY
+(scrypt, TLS1 PRF and HKDF) may be slower as they use an EVP_KDF bridge
+internally.
+All new applications should use the new L<EVP_KDF(3)> interface.
+See also L<OSSL_PROVIDER-default(7)/Key Derivation Function (KDF)> and
+L<OSSL_PROVIDER-FIPS(7)/Key Derivation Function (KDF)>.
+
+=head4 Message Authentication Code API (EVP_MAC)
+
+This simplifies the process of adding MAC implementations.
+
+This includes a generic EVP_PKEY to EVP_MAC bridge, to facilitate the continued
+use of MACs through raw private keys in functionality such as
+L<EVP_DigestSign(3)> and L<EVP_DigestVerify(3)>.
+
+All new applications should use the new L<EVP_MAC(3)> interface.
+See also L<OSSL_PROVIDER-default(7)/Message Authentication Code (MAC)>
+and L<OSSL_PROVIDER-FIPS(7)/Message Authentication Code (MAC)>.
+
+=head4 Support for Linux Kernel TLS
+
+In order to use KTLS, support for it must be compiled in using the
+C<enable-ktls> configuration option. It must also be enabled at run time using
+the B<SSL_OP_ENABLE_KTLS> option.
+
+=head4 New Algorithms
+
+=over 4
+
+=item *
+
+KDF algorithms "SINGLE STEP" and "SSH"
+
+See L<EVP_KDF-SS(7)> and L<EVP_KDF-SSHKDF(7)>
+
+=item *
+
+MAC Algorithms "GMAC" and "KMAC"
+
+See L<EVP_MAC-GMAC(7)> and L<EVP_MAC-KMAC(7)>.
+
+=item *
+
+KEM Algorithm "RSASVE"
+
+See L<EVP_KEM-RSA(7)>.
+
+=item *
+
+Cipher Algorithm "AES-SIV"
+
+See L<EVP_EncryptInit(3)/SIV Mode>.
+
+=item *
+
+AES Key Wrap inverse ciphers supported by EVP layer.
+
+The inverse ciphers use AES decryption for wrapping, and AES encryption for
+unwrapping. The algorithms are: "AES-128-WRAP-INV", "AES-192-WRAP-INV",
+"AES-256-WRAP-INV", "AES-128-WRAP-PAD-INV", "AES-192-WRAP-PAD-INV" and
+"AES-256-WRAP-PAD-INV".
+
+=item *
+
+CTS ciphers added to EVP layer.
+
+The algorithms are "AES-128-CBC-CTS", "AES-192-CBC-CTS", "AES-256-CBC-CTS",
+"CAMELLIA-128-CBC-CTS", "CAMELLIA-192-CBC-CTS" and "CAMELLIA-256-CBC-CTS".
+CS1, CS2 and CS3 variants are supported.
+
+=back
+
+=head4 CMS and PKCS#7 updates
+
+=over 4
+
+=item *
+
+Added CAdES-BES signature verification support.
+
+=item *
+
+Added CAdES-BES signature scheme and attributes support (RFC 5126) to CMS API.
+
+=item *
+
+Added AuthEnvelopedData content type structure (RFC 5083) using AES_GCM
+
+This uses the AES-GCM parameter (RFC 5084) for the Cryptographic Message Syntax.
+Its purpose is to support encryption and decryption of a digital envelope that
+is both authenticated and encrypted using AES GCM mode.
+
+=item *
+
+L<PKCS7_get_octet_string(3)> and L<PKCS7_type_is_other(3)> were made public.
+
+=back
+
+=head4 PKCS#12 API updates
+
+The default algorithms for pkcs12 creation with the PKCS12_create() function
+were changed to more modern PBKDF2 and AES based algorithms. The default
+MAC iteration count was changed to PKCS12_DEFAULT_ITER to make it equal
+with the password-based encryption iteration count. The default digest
+algorithm for the MAC computation was changed to SHA-256. The pkcs12
+application now supports -legacy option that restores the previous
+default algorithms to support interoperability with legacy systems.
+
+Added enhanced PKCS#12 APIs which accept a library context B<OSSL_LIB_CTX>
+and (where relevant) a property query. Other APIs which handle PKCS#7 and
+PKCS#8 objects have also been enhanced where required. This includes:
+
+L<PKCS12_add_key_ex(3)>, L<PKCS12_add_safe_ex(3)>, L<PKCS12_add_safes_ex(3)>,
+L<PKCS12_create_ex(3)>, L<PKCS12_decrypt_skey_ex(3)>, L<PKCS12_init_ex(3)>,
+L<PKCS12_item_decrypt_d2i_ex(3)>, L<PKCS12_item_i2d_encrypt_ex(3)>,
+L<PKCS12_key_gen_asc_ex(3)>, L<PKCS12_key_gen_uni_ex(3)>, L<PKCS12_key_gen_utf8_ex(3)>,
+L<PKCS12_pack_p7encdata_ex(3)>, L<PKCS12_pbe_crypt_ex(3)>, L<PKCS12_PBE_keyivgen_ex(3)>,
+L<PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(3)>, L<PKCS5_pbe2_set_iv_ex(3)>,
+L<PKCS5_pbe_set0_algor_ex(3)>, L<PKCS5_pbe_set_ex(3)>, L<PKCS5_pbkdf2_set_ex(3)>,
+L<PKCS5_v2_PBE_keyivgen_ex(3)>, L<PKCS5_v2_scrypt_keyivgen_ex(3)>,
+L<PKCS8_decrypt_ex(3)>, L<PKCS8_encrypt_ex(3)>, L<PKCS8_set0_pbe_ex(3)>.
+
+As part of this change the EVP_PBE_xxx APIs can also accept a library
+context and property query and will call an extended version of the key/IV
+derivation function which supports these parameters. This includes
+L<EVP_PBE_CipherInit_ex(3)>, L<EVP_PBE_find_ex(3)> and L<EVP_PBE_scrypt_ex(3)>.
+
+=head4 Windows thread synchronization changes
+
+Windows thread synchronization uses read/write primitives (SRWLock) when
+supported by the OS, otherwise CriticalSection continues to be used.
+
+=head4 Trace API
+
+A new generic trace API has been added which provides support for enabling
+instrumentation through trace output. This feature is mainly intended as an aid
+for developers and is disabled by default. To utilize it, OpenSSL needs to be
+configured with the C<enable-trace> option.
+
+If the tracing API is enabled, the application can activate trace output by
+registering BIOs as trace channels for a number of tracing and debugging
+categories. See L<OSSL_trace_enabled(3)>.
+
+=head4 Key validation updates
+
+L<EVP_PKEY_public_check(3)> and L<EVP_PKEY_param_check(3)> now work for
+more key types. This includes RSA, DSA, ED25519, X25519, ED448 and X448.
+Previously (in 1.1.1) they would return -2. For key types that do not have
+parameters then L<EVP_PKEY_param_check(3)> will always return 1.
+
+=head3 Other notable deprecations and changes
+
+=head4 The function code part of an OpenSSL error code is no longer relevant
+
+This code is now always set to zero. Related functions are deprecated.
+
+=head4 STACK and HASH macros have been cleaned up
+
+The type-safe wrappers are declared everywhere and implemented once.
+See L<DEFINE_STACK_OF(3)> and L<DECLARE_LHASH_OF(3)>.
+
+=head4 The RAND_DRBG subsystem has been removed
+
+The new L<EVP_RAND(3)> is a partial replacement: the DRBG callback framework is
+absent. The RAND_DRBG API did not fit well into the new provider concept as
+implemented by EVP_RAND and EVP_RAND_CTX.
+
+=head4 Removed FIPS_mode() and FIPS_mode_set()
+
+These functions are legacy APIs that are not applicable to the new provider
+model. Applications should instead use
+L<EVP_default_properties_is_fips_enabled(3)> and
+L<EVP_default_properties_enable_fips(3)>.
+
+=head4 Key generation is slower
+
+The Miller-Rabin test now uses 64 rounds, which is used for all prime generation,
+including RSA key generation. This affects the time for larger keys sizes.
+
+The default key generation method for the regular 2-prime RSA keys was changed
+to the FIPS186-4 B.3.6 method (Generation of Probable Primes with Conditions
+Based on Auxiliary Probable Primes). This method is slower than the original
+method.
+
+=head4 Change PBKDF2 to conform to SP800-132 instead of the older PKCS5 RFC2898
+
+This checks that the salt length is at least 128 bits, the derived key length is
+at least 112 bits, and that the iteration count is at least 1000.
+For backwards compatibility these checks are disabled by default in the
+default provider, but are enabled by default in the FIPS provider.
+
+To enable or disable the checks see B<OSSL_KDF_PARAM_PKCS5> in
+L<EVP_KDF-PBKDF2(7)>. The parameter can be set using L<EVP_KDF_derive(3)>.
+
+=head4 Enforce a minimum DH modulus size of 512 bits
+
+Smaller sizes now result in an error.
+
+=head4 SM2 key changes
+
+EC EVP_PKEYs with the SM2 curve have been reworked to automatically become
+EVP_PKEY_SM2 rather than EVP_PKEY_EC.
+
+Unlike in previous OpenSSL versions, this means that applications cannot
+call C<EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)> to get SM2 computations.
+
+Parameter and key generation is also reworked to make it possible
+to generate EVP_PKEY_SM2 parameters and keys. Applications must now generate
+SM2 keys directly and must not create an EVP_PKEY_EC key first. It is no longer
+possible to import an SM2 key with domain parameters other than the SM2 elliptic
+curve ones.
+
+Validation of SM2 keys has been separated from the validation of regular EC
+keys, allowing to improve the SM2 validation process to reject loaded private
+keys that are not conforming to the SM2 ISO standard.
+In particular, a private scalar I<k> outside the range I<< 1 <= k < n-1 >> is
+now correctly rejected.
+
+=head4 EVP_PKEY_set_alias_type() method has been removed
+
+This function made a B<EVP_PKEY> object mutable after it had been set up. In
+OpenSSL 3.0 it was decided that a provided key should not be able to change its
+type, so this function has been removed.
+
+=head4 Functions that return an internal key should be treated as read only
+
+Functions such as L<EVP_PKEY_get0_RSA(3)> behave slightly differently in
+OpenSSL 3.0. Previously they returned a pointer to the low-level key used
+internally by libcrypto. From OpenSSL 3.0 this key may now be held in a
+provider. Calling these functions will only return a handle on the internal key
+where the EVP_PKEY was constructed using this key in the first place, for
+example using a function or macro such as L<EVP_PKEY_assign_RSA(3)>,
+L<EVP_PKEY_set1_RSA(3)>, etc.
+Where the EVP_PKEY holds a provider managed key, then these functions now return
+a cached copy of the key. Changes to the internal provider key that take place
+after the first time the cached key is accessed will not be reflected back in
+the cached copy. Similarly any changes made to the cached copy by application
+code will not be reflected back in the internal provider key.
+
+For the above reasons the keys returned from these functions should typically be
+treated as read-only. To emphasise this the value returned from
+L<EVP_PKEY_get0_RSA(3)>, L<EVP_PKEY_get0_DSA(3)>, L<EVP_PKEY_get0_EC_KEY(3)> and
+L<EVP_PKEY_get0_DH(3)> have been made const. This may break some existing code.
+Applications broken by this change should be modified. The preferred solution is
+to refactor the code to avoid the use of these deprecated functions. Failing
+this the code should be modified to use a const pointer instead.
+The L<EVP_PKEY_get1_RSA(3)>, L<EVP_PKEY_get1_DSA(3)>, L<EVP_PKEY_get1_EC_KEY(3)>
+and L<EVP_PKEY_get1_DH(3)> functions continue to return a non-const pointer to
+enable them to be "freed". However they should also be treated as read-only.
+
+=head4 The public key check has moved from EVP_PKEY_derive() to EVP_PKEY_derive_set_peer()
+
+This may mean result in an error in L<EVP_PKEY_derive_set_peer(3)> rather than
+during L<EVP_PKEY_derive(3)>.
+To disable this check use EVP_PKEY_derive_set_peer_ex(dh, peer, 0).
+
+=head4 The print format has cosmetic changes for some functions
+
+The output from numerous "printing" functions such as L<X509_signature_print(3)>,
+L<X509_print_ex(3)>, L<X509_CRL_print_ex(3)>, and other similar functions has been
+amended such that there may be cosmetic differences between the output
+observed in 1.1.1 and 3.0. This also applies to the B<-text> output from the
+B<openssl x509> and B<openssl crl> applications.
+
+=head4 Interactive mode from the B<openssl> program has been removed
+
+From now on, running it without arguments is equivalent to B<openssl help>.
+
+=head4 The error return values from some control calls (ctrl) have changed
+
+One significant change is that controls which used to return -2 for
+invalid inputs, now return -1 indicating a generic error condition instead.
+
+=head4 DH and DHX key types have different settable parameters
+
+Previously (in 1.1.1) these conflicting parameters were allowed, but will now
+result in errors. See L<EVP_PKEY-DH(7)> for further details. This affects the
+behaviour of L<openssl-genpkey(1)> for DH parameter generation.
+
+=head4 EVP_CIPHER_CTX_set_flags() ordering change
+
+If using a cipher from a provider the B<EVP_CIPH_FLAG_LENGTH_BITS> flag can only
+be set B<after> the cipher has been assigned to the cipher context.
+See L<EVP_EncryptInit(3)/FLAGS> for more information.
+
+=head4 Validation of operation context parameters
+
+Due to move of the implementation of cryptographic operations to the
+providers, validation of various operation parameters can be postponed until
+the actual operation is executed where previously it happened immediately
+when an operation parameter was set.
+
+For example when setting an unsupported curve with
+EVP_PKEY_CTX_set_ec_paramgen_curve_nid() this function call will not fail
+but later keygen operations with the EVP_PKEY_CTX will fail.
+
+=head4 Removal of function code from the error codes
+
+The function code part of the error code is now always set to 0. For that
+reason the ERR_GET_FUNC() macro was removed. Applications must resolve
+the error codes only using the library number and the reason code.
+
+=head4 ChaCha20-Poly1305 cipher does not allow a truncated IV length to be used
+
+In OpenSSL 3.0 setting the IV length to any value other than 12 will result in an
+error.
+Prior to OpenSSL 3.0 the ivlen could be smaller that the required 12 byte length,
+using EVP_CIPHER_CTX_ctrl(ctx, EVP_CRTL_AEAD_SET_IVLEN, ivlen, NULL). This resulted
+in an IV that had leading zero padding.
+
+=head2 Installation and Compilation
+
+Please refer to the INSTALL.md file in the top of the distribution for
+instructions on how to build and install OpenSSL 3.0. Please also refer to the
+various platform specific NOTES files for your specific platform.
+
+=head2 Upgrading from OpenSSL 1.1.1
+
+Upgrading to OpenSSL 3.0 from OpenSSL 1.1.1 should be relatively straight
+forward in most cases. The most likely area where you will encounter problems
+is if you have used low level APIs in your code (as discussed above). In that
+case you are likely to start seeing deprecation warnings when compiling your
+application. If this happens you have 3 options:
+
+=over 4
+
+=item 1.
+
+Ignore the warnings. They are just warnings. The deprecated functions are still present and you may still use them. However be aware that they may be removed from a future version of OpenSSL.
+
+=item 2.
+
+Suppress the warnings. Refer to your compiler documentation on how to do this.
+
+=item 3.
+
+Remove your usage of the low level APIs. In this case you will need to rewrite your code to use the high level APIs instead
+
+=back
+
+=head3 Error code changes
+
+As OpenSSL 3.0 provides a brand new Encoder/Decoder mechanism for working with
+widely used file formats, application code that checks for particular error
+reason codes on key loading failures might need an update.
+
+Password-protected keys may deserve special attention. If only some errors
+are treated as an indicator that the user should be asked about the password again,
+it's worth testing these scenarios and processing the newly relevant codes.
+
+There may be more cases to treat specially, depending on the calling application code.
+
+=head2 Upgrading from OpenSSL 1.0.2
+
+Upgrading to OpenSSL 3.0 from OpenSSL 1.0.2 is likely to be significantly more
+difficult. In addition to the issues discussed above in the section about
+L</Upgrading from OpenSSL 1.1.1>, the main things to be aware of are:
+
+=over 4
+
+=item 1.
+
+The build and installation procedure has changed significantly.
+
+Check the file INSTALL.md in the top of the installation for instructions on how
+to build and install OpenSSL for your platform. Also read the various NOTES
+files in the same directory, as applicable for your platform.
+
+=item 2.
+
+Many structures have been made opaque in OpenSSL 3.0.
+
+The structure definitions have been removed from the public header files and
+moved to internal header files. In practice this means that you can no longer
+stack allocate some structures. Instead they must be heap allocated through some
+function call (typically those function names have a C<_new> suffix to them).
+Additionally you must use "setter" or "getter" functions to access the fields
+within those structures.
+
+For example code that previously looked like this:
+
+ EVP_MD_CTX md_ctx;
+
+ /* This line will now generate compiler errors */
+ EVP_MD_CTX_init(&md_ctx);
+
+The code needs to be amended to look like this:
+
+ EVP_MD_CTX *md_ctx;
+
+ md_ctx = EVP_MD_CTX_new();
+ ...
+ ...
+ EVP_MD_CTX_free(md_ctx);
+
+=item 3.
+
+Support for TLSv1.3 has been added.
+
+This has a number of implications for SSL/TLS applications. See the
+L<TLS1.3 page|https://wiki.openssl.org/index.php/TLS1.3> for further details.
+
+=back
+
+More details about the breaking changes between OpenSSL versions 1.0.2 and 1.1.0
+can be found on the
+L<OpenSSL 1.1.0 Changes page|https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes>.
+
+=head3 Upgrading from the OpenSSL 2.0 FIPS Object Module
+
+The OpenSSL 2.0 FIPS Object Module was a separate download that had to be built
+separately and then integrated into your main OpenSSL 1.0.2 build.
+In OpenSSL 3.0 the FIPS support is fully integrated into the mainline version of
+OpenSSL and is no longer a separate download. For further information see
+L</Completing the installation of the FIPS Module>.
+
+The function calls FIPS_mode() and FIPS_mode_set() have been removed
+from OpenSSL 3.0. You should rewrite your application to not use them.
+See L<fips_module(7)> and L<OSSL_PROVIDER-FIPS(7)> for details.
+
+=head2 Completing the installation of the FIPS Module
+
+The FIPS Module will be built and installed automatically if FIPS support has
+been configured. The current documentation can be found in the
+L<README-FIPS|https://github.com/openssl/openssl/blob/master/README-FIPS.md> file.
+
+=head2 Programming
+
+Applications written to work with OpenSSL 1.1.1 will mostly just work with
+OpenSSL 3.0. However changes will be required if you want to take advantage of
+some of the new features that OpenSSL 3.0 makes available. In order to do that
+you need to understand some new concepts introduced in OpenSSL 3.0.
+Read L<crypto(7)/Library contexts> for further information.
+
+=head3 Library Context
+
+A library context allows different components of a complex application to each
+use a different library context and have different providers loaded with
+different configuration settings.
+See L<crypto(7)/Library contexts> for further info.
+
+If the user creates an B<OSSL_LIB_CTX> via L<OSSL_LIB_CTX_new(3)> then many
+functions may need to be changed to pass additional parameters to handle the
+library context.
+
+=head4 Using a Library Context - Old functions that should be changed
+
+If a library context is needed then all EVP_* digest functions that return a
+B<const EVP_MD *> such as EVP_sha256() should be replaced with a call to
+L<EVP_MD_fetch(3)>. See L<crypto(7)/ALGORITHM FETCHING>.
+
+If a library context is needed then all EVP_* cipher functions that return a
+B<const EVP_CIPHER *> such as EVP_aes_128_cbc() should be replaced vith a call to
+L<EVP_CIPHER_fetch(3)>. See L<crypto(7)/ALGORITHM FETCHING>.
+
+Some functions can be passed an object that has already been set up with a library
+context such as L<d2i_X509(3)>, L<d2i_X509_CRL(3)>, L<d2i_X509_REQ(3)> and
+L<d2i_X509_PUBKEY(3)>. If NULL is passed instead then the created object will be
+set up with the default library context. Use L<X509_new_ex(3)>,
+L<X509_CRL_new_ex(3)>, L<X509_REQ_new_ex(3)> and L<X509_PUBKEY_new_ex(3)> if a
+library context is required.
+
+All functions listed below with a I<NAME> have a replacment function I<NAME_ex>
+that takes B<OSSL_LIB_CTX> as an additional argument. Functions that have other
+mappings are listed along with the respective name.
+
+=over 4
+
+=item *
+
+L<ASN1_item_new(3)>, L<ASN1_item_d2i(3)>, L<ASN1_item_d2i_fp(3)>,
+L<ASN1_item_d2i_bio(3)>, L<ASN1_item_sign(3)> and L<ASN1_item_verify(3)>
+
+=item *
+
+L<BIO_new(3)>
+
+=item *
+
+b2i_RSA_PVK_bio() and i2b_PVK_bio()
+
+=item *
+
+L<BN_CTX_new(3)> and L<BN_CTX_secure_new(3)>
+
+=item *
+
+L<CMS_AuthEnvelopedData_create(3)>, L<CMS_ContentInfo_new(3)>, L<CMS_data_create(3)>,
+L<CMS_digest_create(3)>, L<CMS_EncryptedData_encrypt(3)>, L<CMS_encrypt(3)>,
+L<CMS_EnvelopedData_create(3)>, L<CMS_ReceiptRequest_create0(3)> and L<CMS_sign(3)>
+
+=item *
+
+L<CONF_modules_load_file(3)>
+
+=item *
+
+L<CTLOG_new(3)>, L<CTLOG_new_from_base64(3)> and L<CTLOG_STORE_new(3)>
+
+=item *
+
+L<CT_POLICY_EVAL_CTX_new(3)>
+
+=item *
+
+L<d2i_AutoPrivateKey(3)>, L<d2i_PrivateKey(3)> and L<d2i_PUBKEY(3)>
+
+=item *
+
+L<d2i_PrivateKey_bio(3)> and L<d2i_PrivateKey_fp(3)>
+
+Use L<d2i_PrivateKey_ex_bio(3)> and L<d2i_PrivateKey_ex_fp(3)>
+
+=item *
+
+L<EC_GROUP_new(3)>
+
+Use L<EC_GROUP_new_by_curve_name_ex(3)> or L<EC_GROUP_new_from_params(3)>.
+
+=item *
+
+L<EVP_DigestSignInit(3)> and L<EVP_DigestVerifyInit(3)>
+
+=item *
+
+L<EVP_PBE_CipherInit(3)>, L<EVP_PBE_find(3)> and L<EVP_PBE_scrypt(3)>
+
+=item *
+
+L<PKCS5_PBE_keyivgen(3)>
+
+=item *
+
+L<EVP_PKCS82PKEY(3)>
+
+=item *
+
+L<EVP_PKEY_CTX_new_id(3)>
+
+Use L<EVP_PKEY_CTX_new_from_name(3)>
+
+=item *
+
+L<EVP_PKEY_derive_set_peer(3)>, L<EVP_PKEY_new_raw_private_key(3)>
+and L<EVP_PKEY_new_raw_public_key(3)>
+
+=item *
+
+L<EVP_SignFinal(3)> and L<EVP_VerifyFinal(3)>
+
+=item *
+
+L<NCONF_new(3)>
+
+=item *
+
+L<OCSP_RESPID_match(3)> and L<OCSP_RESPID_set_by_key(3)>
+
+=item *
+
+L<OPENSSL_thread_stop(3)>
+
+=item *
+
+L<OSSL_STORE_open(3)>
+
+=item *
+
+L<PEM_read_bio_Parameters(3)>, L<PEM_read_bio_PrivateKey(3)>, L<PEM_read_bio_PUBKEY(3)>,
+L<PEM_read_PrivateKey(3)> and L<PEM_read_PUBKEY(3)>
+
+=item *
+
+L<PEM_write_bio_PrivateKey(3)>, L<PEM_write_bio_PUBKEY(3)>, L<PEM_write_PrivateKey(3)>
+and L<PEM_write_PUBKEY(3)>
+
+=item *
+
+L<PEM_X509_INFO_read_bio(3)> and L<PEM_X509_INFO_read(3)>
+
+=item *
+
+L<PKCS12_add_key(3)>, L<PKCS12_add_safe(3)>, L<PKCS12_add_safes(3)>,
+L<PKCS12_create(3)>, L<PKCS12_decrypt_skey(3)>, L<PKCS12_init(3)>, L<PKCS12_item_decrypt_d2i(3)>,
+L<PKCS12_item_i2d_encrypt(3)>, L<PKCS12_key_gen_asc(3)>, L<PKCS12_key_gen_uni(3)>,
+L<PKCS12_key_gen_utf8(3)>, L<PKCS12_pack_p7encdata(3)>, L<PKCS12_pbe_crypt(3)>,
+L<PKCS12_PBE_keyivgen(3)>, L<PKCS12_SAFEBAG_create_pkcs8_encrypt(3)>
+
+=item *
+
+L<PKCS5_pbe_set0_algor(3)>, L<PKCS5_pbe_set(3)>, L<PKCS5_pbe2_set_iv(3)>,
+L<PKCS5_pbkdf2_set(3)> and L<PKCS5_v2_scrypt_keyivgen(3)>
+
+=item *
+
+L<PKCS7_encrypt(3)>, L<PKCS7_new(3)> and L<PKCS7_sign(3)>
+
+=item *
+
+L<PKCS8_decrypt(3)>, L<PKCS8_encrypt(3)> and L<PKCS8_set0_pbe(3)>
+
+=item *
+
+L<RAND_bytes(3)> and L<RAND_priv_bytes(3)>
+
+=item *
+
+L<SMIME_write_ASN1(3)>
+
+=item *
+
+L<SSL_load_client_CA_file(3)>
+
+=item *
+
+L<SSL_CTX_new(3)>
+
+=item *
+
+L<TS_RESP_CTX_new(3)>
+
+=item *
+
+L<X509_CRL_new(3)>
+
+=item *
+
+L<X509_load_cert_crl_file(3)> and L<X509_load_cert_file(3)>
+
+=item *
+
+L<X509_LOOKUP_by_subject(3)> and L<X509_LOOKUP_ctrl(3)>
+
+=item *
+
+L<X509_NAME_hash(3)>
+
+=item *
+
+L<X509_new(3)>
+
+=item *
+
+L<X509_REQ_new(3)> and L<X509_REQ_verify(3)>
+
+=item *
+
+L<X509_STORE_CTX_new(3)>, L<X509_STORE_set_default_paths(3)>, L<X509_STORE_load_file(3)>,
+L<X509_STORE_load_locations(3)> and L<X509_STORE_load_store(3)>
+
+=back
+
+=head4 New functions that use a Library context
+
+The following functions can be passed a library context if required.
+Passing NULL will use the default library context.
+
+=over 4
+
+=item *
+
+L<BIO_new_from_core_bio(3)>
+
+=item *
+
+L<EVP_ASYM_CIPHER_fetch(3)> and L<EVP_ASYM_CIPHER_do_all_provided(3)>
+
+=item *
+
+L<EVP_CIPHER_fetch(3)> and L<EVP_CIPHER_do_all_provided(3)>
+
+=item *
+
+L<EVP_default_properties_enable_fips(3)> and
+L<EVP_default_properties_is_fips_enabled(3)>
+
+=item *
+
+L<EVP_KDF_fetch(3)> and L<EVP_KDF_do_all_provided(3)>
+
+=item *
+
+L<EVP_KEM_fetch(3)> and L<EVP_KEM_do_all_provided(3)>
+
+=item *
+
+L<EVP_KEYEXCH_fetch(3)> and L<EVP_KEYEXCH_do_all_provided(3)>
+
+=item *
+
+L<EVP_KEYMGMT_fetch(3)> and L<EVP_KEYMGMT_do_all_provided(3)>
+
+=item *
+
+L<EVP_MAC_fetch(3)> and L<EVP_MAC_do_all_provided(3)>
+
+=item *
+
+L<EVP_MD_fetch(3)> and L<EVP_MD_do_all_provided(3)>
+
+=item *
+
+L<EVP_PKEY_CTX_new_from_pkey(3)>
+
+=item *
+
+L<EVP_PKEY_Q_keygen(3)>
+
+=item *
+
+L<EVP_Q_mac(3)> and L<EVP_Q_digest(3)>
+
+=item *
+
+L<EVP_RAND(3)> and L<EVP_RAND_do_all_provided(3)>
+
+=item *
+
+L<EVP_set_default_properties(3)>
+
+=item *
+
+L<EVP_SIGNATURE_fetch(3)> and L<EVP_SIGNATURE_do_all_provided(3)>
+
+=item *
+
+L<OSSL_CMP_CTX_new(3)> and L<OSSL_CMP_SRV_CTX_new(3)>
+
+=item *
+
+L<OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(3)>
+
+=item *
+
+L<OSSL_CRMF_MSG_create_popo(3)> and L<OSSL_CRMF_MSGS_verify_popo(3)>
+
+=item *
+
+L<OSSL_CRMF_pbm_new(3)> and L<OSSL_CRMF_pbmp_new(3)>
+
+=item *
+
+L<OSSL_DECODER_CTX_add_extra(3)> and L<OSSL_DECODER_CTX_new_for_pkey(3)>
+
+=item *
+
+L<OSSL_DECODER_fetch(3)> and L<OSSL_DECODER_do_all_provided(3)>
+
+=item *
+
+L<OSSL_ENCODER_CTX_add_extra(3)>
+
+=item *
+
+L<OSSL_ENCODER_fetch(3)> and L<OSSL_ENCODER_do_all_provided(3)>
+
+=item *
+
+L<OSSL_LIB_CTX_free(3)>, L<OSSL_LIB_CTX_load_config(3)> and L<OSSL_LIB_CTX_set0_default(3)>
+
+=item *
+
+L<OSSL_PROVIDER_add_builtin(3)>, L<OSSL_PROVIDER_available(3)>,
+L<OSSL_PROVIDER_do_all(3)>, L<OSSL_PROVIDER_load(3)>,
+L<OSSL_PROVIDER_set_default_search_path(3)> and L<OSSL_PROVIDER_try_load(3)>
+
+=item *
+
+L<OSSL_SELF_TEST_get_callback(3)> and L<OSSL_SELF_TEST_set_callback(3)>
+
+=item *
+
+L<OSSL_STORE_attach(3)>
+
+=item *
+
+L<OSSL_STORE_LOADER_fetch(3)> and L<OSSL_STORE_LOADER_do_all_provided(3)>
+
+=item *
+
+L<RAND_get0_primary(3)>, L<RAND_get0_private(3)>, L<RAND_get0_public(3)>,
+L<RAND_set_DRBG_type(3)> and L<RAND_set_seed_source_type(3)>
+
+=back
+
+=head3 Providers
+
+Providers are described in detail here L<crypto(7)/Providers>.
+See also L<crypto(7)/OPENSSL PROVIDERS>.
+
+=head3 Fetching algorithms and property queries
+
+Implicit and Explicit Fetching is described in detail here
+L<crypto(7)/ALGORITHM FETCHING>.
+
+=head3 Mapping EVP controls and flags to provider L<OSSL_PARAM(3)> parameters
+
+The existing functions for controls (such as L<EVP_CIPHER_CTX_ctrl(3)>) and
+manipulating flags (such as L<EVP_MD_CTX_set_flags(3)>)internally use
+B<OSSL_PARAMS> to pass information to/from provider objects.
+See L<OSSL_PARAM(3)> for additional information related to parameters.
+
+For ciphers see L<EVP_EncryptInit(3)/CONTROLS>, L<EVP_EncryptInit(3)/FLAGS> and
+L<EVP_EncryptInit(3)/PARAMETERS>.
+
+For digests see L<EVP_DigestInit(3)/CONTROLS>, L<EVP_DigestInit(3)/FLAGS> and
+L<EVP_DigestInit(3)/PARAMETERS>.
+
+=head3 Deprecation of Low Level Functions
+
+A significant number of APIs have been deprecated in OpenSSL 3.0.
+This section describes some common categories of deprecations.
+See L</Deprecated function mappings> for the list of deprecated functions
+that refer to these categories.
+
+=head4 Providers are a replacement for engines and low-level method overrides
+
+Any accessor that uses an ENGINE is deprecated (such as EVP_PKEY_set1_engine()).
+Applications using engines should instead use providers.
+
+Before providers were added algorithms were overriden by changing the methods
+used by algorithms. All these methods such as RSA_new_method() and RSA_meth_new()
+are now deprecated and can be replaced by using providers instead.
+
+=head4 Deprecated i2d and d2i functions for low-level key types
+
+Any i2d and d2i functions such as d2i_DHparams() that take a low-level key type
+have been deprecated. Applications should instead use the L<OSSL_DECODER(3)> and
+L<OSSL_ENCODER(3)> APIs to read and write files.
+See L<d2i_RSAPrivateKey(3)/Migration> for further details.
+
+=head4 Deprecated low-level key object getters and setters
+
+Applications that set or get low-level key objects (such as EVP_PKEY_set1_DH()
+or EVP_PKEY_get0()) should instead use the OSSL_ENCODER
+(See L<OSSL_ENCODER_to_bio(3)>) or OSSL_DECODER (See L<OSSL_DECODER_from_bio(3)>)
+APIs, or alternatively use L<EVP_PKEY_fromdata(3)> or L<EVP_PKEY_todata(3)>.
+
+=head4 Deprecated low-level key parameter getters
+
+Functions that access low-level objects directly such as L<RSA_get0_n(3)> are now
+deprecated. Applications should use one of L<EVP_PKEY_get_bn_param(3)>,
+L<EVP_PKEY_get_int_param(3)>, l<EVP_PKEY_get_size_t_param(3)>,
+L<EVP_PKEY_get_utf8_string_param(3)>, L<EVP_PKEY_get_octet_string_param(3)> or
+L<EVP_PKEY_get_params(3)> to access fields from an EVP_PKEY.
+Gettable parameters are listed in L<EVP_PKEY-RSA(7)/Common RSA parameters>,
+L<EVP_PKEY-DH(7)/DH parameters>, L<EVP_PKEY-DSA(7)/DSA parameters>,
+L<EVP_PKEY-FFC(7)/FFC parameters>, L<EVP_PKEY-EC(7)/Common EC parameters> and
+L<EVP_PKEY-X25519(7)/Common X25519, X448, ED25519 and ED448 parameters>.
+Applications may also use L<EVP_PKEY_todata(3)> to return all fields.
+
+=head4 Deprecated low-level key parameter setters
+
+Functions that access low-level objects directly such as L<RSA_set0_crt_params(3)>
+are now deprecated. Applications should use L<EVP_PKEY_fromdata(3)> to create
+new keys from user provided key data. Keys should be immutable once they are
+created, so if required the user may use L<EVP_PKEY_todata(3)>, L<OSSL_PARAM_merge(3)>,
+and L<EVP_PKEY_fromdata(3)> to create a modified key.
+See L<EVP_PKEY-DH(7)/Examples> for more information.
+See L</Deprecated low-level key generation functions> for information on
+generating a key using parameters.
+
+=head4 Deprecated low-level object creation
+
+Low-level objects were created using methods such as L<RSA_new(3)>,
+L<RSA_up_ref(3)> and L<RSA_free(3)>. Applications should instead use the
+high-level EVP_PKEY APIs, e.g. L<EVP_PKEY_new(3)>, L<EVP_PKEY_up_ref(3)> and
+L<EVP_PKEY_free(3)>.
+See also L<EVP_PKEY_CTX_new_from_name(3)> and L<EVP_PKEY_CTX_new_from_pkey(3)>.
+
+EVP_PKEYs may be created in a variety of ways:
+See also L</Deprecated low-level key generation functions>,
+L</Deprecated low-level key reading and writing functions> and
+L</Deprecated low-level key parameter setters>.
+
+=head4 Deprecated low-level encryption functions
+
+Low-level encryption functions such as L<AES_encrypt(3)> and L<AES_decrypt(3)>
+have been informally discouraged from use for a long time. Applications should
+instead use the high level EVP APIs L<EVP_EncryptInit_ex(3)>,
+L<EVP_EncryptUpdate(3)>, and L<EVP_EncryptFinal_ex(3)> or
+L<EVP_DecryptInit_ex(3)>, L<EVP_DecryptUpdate(3)> and L<EVP_DecryptFinal_ex(3)>.
+
+=head4 Deprecated low-level digest functions
+
+Use of low-level digest functions such as L<SHA1_Init(3)> have been
+informally discouraged from use for a long time. Applications should instead
+use the the high level EVP APIs L<EVP_DigestInit_ex(3)>, L<EVP_DigestUpdate(3)>
+and L<EVP_DigestFinal_ex(3)>, or the quick one-shot L<EVP_Q_digest(3)>.
+
+Note that the functions L<SHA1(3)>, L<SHA224(3)>, L<SHA256(3)>, L<SHA384(3)>
+and L<SHA512(3)> have changed to macros that use L<EVP_Q_digest(3)>.
+
+=head4 Deprecated low-level signing functions
+
+Use of low-level signing functions such as L<DSA_sign(3)> have been
+informally discouraged for a long time. Instead applications should use
+L<EVP_DigestSign(3)> and L<EVP_DigestVerify(3)>.
+See also L<EVP_SIGNATURE-RSA(7)>, L<EVP_SIGNATURE-DSA(7)>,
+L<EVP_SIGNATURE-ECDSA(7)> and L<EVP_SIGNATURE-ED25519(7)>.
+
+=head4 Deprecated low-level MAC functions
+
+Low-level mac functions such as L<CMAC_Init(3)> are deprecated.
+Applications should instead use the new L<EVP_MAC(3)> interface, using
+L<EVP_MAC_CTX_new(3)>, L<EVP_MAC_CTX_free(3)>, L<EVP_MAC_init(3)>,
+L<EVP_MAC_update(3)> and L<EVP_MAC_final(3)> or the single-shot MAC function
+L<EVP_Q_mac(3)>.
+See L<EVP_MAC(3)>, L<EVP_MAC-HMAC(7)>, L<EVP_MAC-CMAC(7)>, L<EVP_MAC-GMAC(7)>,
+L<EVP_MAC-KMAC(7)>, L<EVP_MAC-BLAKE2(7)>, L<EVP_MAC-Poly1305(7)> and
+L<EVP_MAC-Siphash(7)> for additional information.
+
+Note that the one-shot method HMAC() is still available for compatibility purposes,
+but this can also be replaced by using EVP_Q_MAC if a library context is required.
+
+=head4 Deprecated low-level validation functions
+
+Low-level validation functions such as L<DH_check(3)> have been informally
+discouraged from use for a long time. Applications should instead use the high-level
+EVP_PKEY APIs such as L<EVP_PKEY_check(3)>, L<EVP_PKEY_param_check(3)>,
+L<EVP_PKEY_param_check_quick(3)>, L<EVP_PKEY_public_check(3)>,
+L<EVP_PKEY_public_check_quick(3)>, L<EVP_PKEY_private_check(3)>,
+and L<EVP_PKEY_pairwise_check(3)>.
+
+=head4 Deprecated low-level key exchange functions
+
+Many low-level functions have been informally discouraged from use for a long
+time. Applications should instead use L<EVP_PKEY_derive(3)>.
+See L<EVP_KEYEXCH-DH(7)>, L<EVP_KEYEXCH-ECDH(7)> and L<EVP_KEYEXCH-X25519(7)>.
+
+=head4 Deprecated low-level key generation functions
+
+Many low-level functions have been informally discouraged from use for a long
+time. Applications should instead use L<EVP_PKEY_keygen_init(3)> and
+L<EVP_PKEY_generate(3)> as described in L<EVP_PKEY-DSA(7)>, L<EVP_PKEY-DH(7)>,
+L<EVP_PKEY-RSA(7)>, L<EVP_PKEY-EC(7)> and L<EVP_PKEY-X25519(7)>.
+The 'quick' one-shot function L<EVP_PKEY_Q_keygen(3)> and macros for the most
+common cases: <EVP_RSA_gen(3)> and L<EVP_EC_gen(3)> may also be used.
+
+=head4 Deprecated low-level key reading and writing functions
+
+Use of low-level objects (such as DSA) has been informally discouraged from use
+for a long time. Functions to read and write these low-level objects (such as
+PEM_read_DSA_PUBKEY()) should be replaced. Applications should instead use
+L<OSSL_ENCODER_to_bio(3)> and L<OSSL_DECODER_from_bio(3)>.
+
+=head4 Deprecated low-level key printing functions
+
+Use of low-level objects (such as DSA) has been informally discouraged from use
+for a long time. Functions to print these low-level objects such as
+DSA_print() should be replaced with the equivalent EVP_PKEY functions.
+Application should use one of L<EVP_PKEY_print_public(3)>,
+L<EVP_PKEY_print_private(3)>, L<EVP_PKEY_print_params(3)>,
+L<EVP_PKEY_print_public_fp(3)>, L<EVP_PKEY_print_private_fp(3)> or
+L<EVP_PKEY_print_params_fp(3)>. Note that internally these use
+L<OSSL_ENCODER_to_bio(3)> and L<OSSL_DECODER_from_bio(3)>.
+
+=head3 Deprecated function mappings
+
+The following functions have been deprecated in 3.0.
+
+=over 4
+
+=item *
+
+AES_bi_ige_encrypt() and AES_ige_encrypt()
+
+There is no replacement for the IGE functions. New code should not use these modes.
+These undocumented functions were never integrated into the EVP layer.
+They implemented the AES Infinite Garble Extension (IGE) mode and AES
+Bi-directional IGE mode. These modes were never formally standardised and
+usage of these functions is believed to be very small. In particular
+AES_bi_ige_encrypt() has a known bug. It accepts 2 AES keys, but only one
+is ever used. The security implications are believed to be minimal, but
+this issue was never fixed for backwards compatibility reasons.
+
+=item *
+
+AES_encrypt(), AES_decrypt(), AES_set_encrypt_key(), AES_set_decrypt_key(),
+AES_cbc_encrypt(), AES_cfb128_encrypt(), AES_cfb1_encrypt(), AES_cfb8_encrypt(),
+AES_ecb_encrypt(), AES_ofb128_encrypt()
+
+=item *
+
+AES_unwrap_key(), AES_wrap_key()
+
+See L</Deprecated low-level encryption functions>
+
+=item *
+
+AES_options()
+
+There is no replacement. It returned a string indicating if the AES code was unrolled.
+
+=item *
+
+ASN1_digest(), ASN1_sign(), ASN1_verify()
+
+There are no replacements. These old functions are not used, and could be
+disabled with the macro NO_ASN1_OLD since OpenSSL 0.9.7.
+
+=item *
+
+ASN1_STRING_length_set()
+
+Use L<ASN1_STRING_set(3)> or L<ASN1_STRING_set0(3)> instead.
+This was a potentially unsafe function that could change the bounds of a
+previously passed in pointer.
+
+=item *
+
+BF_encrypt(), BF_decrypt(), BF_set_key(), BF_cbc_encrypt(), BF_cfb64_encrypt(),
+BF_ecb_encrypt(), BF_ofb64_encrypt()
+
+See L</Deprecated low-level encryption functions>.
+The Blowfish algorithm has been moved to the L<Legacy Provider|/Legacy Algorithms>.
+
+=item *
+
+BF_options()
+
+There is no replacement. This option returned a constant string.
+
+=item *
+
+BIO_get_callback(), BIO_set_callback(), BIO_debug_callback()
+
+Use the respective non-deprecated _ex() functions.
+
+=item *
+
+BN_is_prime_ex(), BN_is_prime_fasttest_ex()
+
+Use L<BN_check_prime(3)> which avoids possible misuse and always uses at least
+64 rounds of the Miller-Rabin primality test.
+
+=item *
+
+BN_pseudo_rand(), BN_pseudo_rand_range()
+
+Use L<BN_rand(3)> and L<BN_rand_range(3)>.
+
+=item *
+
+BN_X931_derive_prime_ex(), BN_X931_generate_prime_ex(), BN_X931_generate_Xpq()
+
+There are no replacements for these low-level functions. They were used internally
+by RSA_X931_derive_ex() and RSA_X931_generate_key_ex() which are also deprecated.
+Use L<EVP_PKEY_keygen(3)> instead.
+
+=item *
+
+Camellia_encrypt(), Camellia_decrypt(), Camellia_set_key(),
+Camellia_cbc_encrypt(), Camellia_cfb128_encrypt(), Camellia_cfb1_encrypt(),
+Camellia_cfb8_encrypt(), Camellia_ctr128_encrypt(), Camellia_ecb_encrypt(),
+Camellia_ofb128_encrypt()
+
+See L</Deprecated low-level encryption functions>.
+
+=item *
+
+CAST_encrypt(), CAST_decrypt(), CAST_set_key(), CAST_cbc_encrypt(),
+CAST_cfb64_encrypt(), CAST_ecb_encrypt(), CAST_ofb64_encrypt()
+
+See L</Deprecated low-level encryption functions>.
+The CAST algorithm has been moved to the L<Legacy Provider|/Legacy Algorithms>.
+
+=item *
+
+CMAC_CTX_new(), CMAC_CTX_cleanup(), CMAC_CTX_copy(), CMAC_CTX_free(),
+CMAC_CTX_get0_cipher_ctx()
+
+See L</Deprecated low-level MAC functions>.
+
+=item *
+
+CMAC_Init(), CMAC_Update(), CMAC_Final(), CMAC_resume()
+
+See L</Deprecated low-level MAC functions>.
+
+=item *
+
+CRYPTO_mem_ctrl(), CRYPTO_mem_debug_free(), CRYPTO_mem_debug_malloc(),
+CRYPTO_mem_debug_pop(), CRYPTO_mem_debug_push(), CRYPTO_mem_debug_realloc(),
+CRYPTO_mem_leaks(), CRYPTO_mem_leaks_cb(), CRYPTO_mem_leaks_fp(),
+CRYPTO_set_mem_debug()
+
+Memory-leak checking has been deprecated in favor of more modern development
+tools, such as compiler memory and leak sanitizers or Valgrind.
+
+=item *
+
+CRYPTO_cts128_encrypt_block(), CRYPTO_cts128_encrypt(),
+CRYPTO_cts128_decrypt_block(), CRYPTO_cts128_decrypt(),
+CRYPTO_nistcts128_encrypt_block(), CRYPTO_nistcts128_encrypt(),
+CRYPTO_nistcts128_decrypt_block(), CRYPTO_nistcts128_decrypt()
+
+Use the higher level functions EVP_CipherInit_ex2(), EVP_CipherUpdate() and
+EVP_CipherFinal_ex() instead.
+See the "cts_mode" parameter in
+L<EVP_EncryptInit(3)/Gettable and Settable EVP_CIPHER_CTX parameters>.
+See L<EVP_EncryptInit(3)/EXAMPLES> for a AES-256-CBC-CTS example.
+
+=item *
+
+d2i_DHparams(), d2i_DHxparams(), d2i_DSAparams(), d2i_DSAPrivateKey(),
+d2i_DSAPrivateKey_bio(), d2i_DSAPrivateKey_fp(), d2i_DSA_PUBKEY(),
+d2i_DSA_PUBKEY_bio(), d2i_DSA_PUBKEY_fp(), d2i_DSAPublicKey(),
+d2i_ECParameters(), d2i_ECPrivateKey(), d2i_ECPrivateKey_bio(),
+d2i_ECPrivateKey_fp(), d2i_EC_PUBKEY(), d2i_EC_PUBKEY_bio(),
+d2i_EC_PUBKEY_fp(), o2i_ECPublicKey(), d2i_RSAPrivateKey(),
+d2i_RSAPrivateKey_bio(), d2i_RSAPrivateKey_fp(), d2i_RSA_PUBKEY(),
+d2i_RSA_PUBKEY_bio(), d2i_RSA_PUBKEY_fp(), d2i_RSAPublicKey(),
+d2i_RSAPublicKey_bio(), d2i_RSAPublicKey_fp()
+
+See L</Deprecated i2d and d2i functions for low-level key types>
+
+=item *
+
+DES_crypt(), DES_fcrypt(), DES_encrypt1(), DES_encrypt2(), DES_encrypt3(),
+DES_decrypt3(), DES_ede3_cbc_encrypt(), DES_ede3_cfb64_encrypt(),
+DES_ede3_cfb_encrypt(),DES_ede3_ofb64_encrypt(),
+DES_ecb_encrypt(), DES_ecb3_encrypt(), DES_ofb64_encrypt(), DES_ofb_encrypt(),
+DES_cfb64_encrypt DES_cfb_encrypt(), DES_cbc_encrypt(), DES_ncbc_encrypt(),
+DES_pcbc_encrypt(), DES_xcbc_encrypt(), DES_cbc_cksum(), DES_quad_cksum(),
+DES_check_key_parity(), DES_is_weak_key(), DES_key_sched(), DES_options(),
+DES_random_key(), DES_set_key(), DES_set_key_checked(), DES_set_key_unchecked(),
+DES_set_odd_parity(), DES_string_to_2keys(), DES_string_to_key()
+
+See L</Deprecated low-level encryption functions>.
+Algorithms for "DESX-CBC", "DES-ECB", "DES-CBC", "DES-OFB", "DES-CFB",
+"DES-CFB1" and "DES-CFB8" have been moved to the L<Legacy Provider|/Legacy Algorithms>.
+
+=item *
+
+DH_bits(), DH_security_bits(), DH_size()
+
+Use L<EVP_PKEY_get_bits(3)>, L<EVP_PKEY_get_security_bits(3)> and
+L<EVP_PKEY_get_size(3)>.
+
+=item *
+
+DH_check(), DH_check_ex(), DH_check_params(), DH_check_params_ex(),
+DH_check_pub_key(), DH_check_pub_key_ex()
+
+See L</Deprecated low-level validation functions>
+
+=item *
+
+DH_clear_flags(), DH_test_flags(), DH_set_flags()
+
+The B<DH_FLAG_CACHE_MONT_P> flag has been deprecated without replacement.
+The B<DH_FLAG_TYPE_DH> and B<DH_FLAG_TYPE_DHX> have been deprecated.
+Use EVP_PKEY_is_a() to determine the type of a key.
+There is no replacement for setting these flags.
+
+=item *
+
+DH_compute_key() DH_compute_key_padded()
+
+See L</Deprecated low-level key exchange functions>.
+
+=item *
+
+DH_new(), DH_new_by_nid(), DH_free(), DH_up_ref()
+
+See L</Deprecated low-level object creation>
+
+=item *
+
+DH_generate_key(), DH_generate_parameters_ex()
+
+See L</Deprecated low-level key generation functions>.
+
+=item *
+
+DH_get0_pqg(), DH_get0_p(), DH_get0_q(), DH_get0_g(), DH_get0_key(),
+DH_get0_priv_key(), DH_get0_pub_key(), DH_get_length(), DH_get_nid()
+
+See L</Deprecated low-level key parameter getters>
+
+=item *
+
+DH_get_1024_160(), DH_get_2048_224(), DH_get_2048_256()
+
+Applications should instead set the B<OSSL_PKEY_PARAM_GROUP_NAME> as specified in
+L<EVP_PKEY-DH(7)/DH parameters>) to one of "dh_1024_160", "dh_2048_224" or
+"dh_2048_256" when generating a DH key.
+
+=item *
+
+DH_KDF_X9_42()
+
+Applications should use L<EVP_PKEY_CTX_set_dh_kdf_type(3)> instead.
+
+=item *
+
+DH_get_default_method(), DH_get0_engine(), DH_meth_*(), DH_new_method(),
+DH_OpenSSL(), DH_get_ex_data(), DH_set_default_method(), DH_set_method(),
+DH_set_ex_data()
+
+See L</Providers are a replacement for engines and low-level method overrides>
+
+=item *
+
+DHparams_print(), DHparams_print_fp()
+
+See L</Deprecated low-level key printing functions>
+
+=item *
+
+DH_set0_key(), DH_set0_pqg(), DH_set_length()
+
+See L</Deprecated low-level key parameter setters>
+
+=item *
+
+DSA_bits(), DSA_security_bits(), DSA_size()
+
+Use L<EVP_PKEY_get_bits(3)>, L<EVP_PKEY_get_security_bits(3)> and
+L<EVP_PKEY_get_size(3)>.
+
+=item *
+
+DHparams_dup(), DSA_dup_DH()
+
+There is no direct replacement. Applications may use L<EVP_PKEY_copy_parameters(3)>
+and L<EVP_PKEY_dup(3)> instead.
+
+=item *
+
+DSA_generate_key(), DSA_generate_parameters_ex()
+
+See L</Deprecated low-level key generation functions>.
+
+=item *
+
+DSA_get0_engine(), DSA_get_default_method(), DSA_get_ex_data(),
+DSA_get_method(), DSA_meth_*(), DSA_new_method(), DSA_OpenSSL(),
+DSA_set_default_method(), DSA_set_ex_data(), DSA_set_method()
+
+See L</Providers are a replacement for engines and low-level method overrides>.
+
+=item *
+
+DSA_get0_p(), DSA_get0_q(), DSA_get0_g(), DSA_get0_pqg(), DSA_get0_key(),
+DSA_get0_priv_key(), DSA_get0_pub_key()
+
+See L</Deprecated low-level key parameter getters>.
+
+=item *
+
+DSA_new(), DSA_free(), DSA_up_ref()
+
+See L</Deprecated low-level object creation>
+
+=item *
+
+DSAparams_dup()
+
+There is no direct replacement. Applications may use L<EVP_PKEY_copy_parameters(3)>
+and L<EVP_PKEY_dup(3)> instead.
+
+=item *
+
+DSAparams_print(), DSAparams_print_fp(), DSA_print(), DSA_print_fp()
+
+See L</Deprecated low-level key printing functions>
+
+=item *
+
+DSA_set0_key(), DSA_set0_pqg()
+
+See L</Deprecated low-level key parameter setters>
+
+=item *
+
+DSA_set_flags(), DSA_clear_flags(), DSA_test_flags()
+
+The B<DSA_FLAG_CACHE_MONT_P> flag has been deprecated without replacement.
+
+=item *
+
+DSA_sign(), DSA_do_sign(), DSA_sign_setup(), DSA_verify(), DSA_do_verify()
+
+See L</Deprecated low-level signing functions>.
+
+=item *
+
+ECDH_compute_key()
+
+See L</Deprecated low-level key exchange functions>.
+
+=item *
+
+ECDH_KDF_X9_62()
+
+Applications may either set this using the helper function
+L<EVP_PKEY_CTX_set_ecdh_kdf_type(3)> or by setting an L<OSSL_PARAM(3)> using the
+"kdf-type" as shown in L<EVP_KEYEXCH-ECDH(7)/EXAMPLES>
+
+=item *
+
+ECDSA_sign(), ECDSA_sign_ex(), ECDSA_sign_setup(), ECDSA_do_sign(),
+ECDSA_do_sign_ex(), ECDSA_verify(), ECDSA_do_verify()
+
+See L</Deprecated low-level signing functions>.
+
+=item *
+
+ECDSA_size()
+
+Applications should use L<EVP_PKEY_get_size(3)>.
+
+=item *
+
+EC_GF2m_simple_method(), EC_GFp_mont_method(), EC_GFp_nist_method(),
+EC_GFp_nistp224_method(), EC_GFp_nistp256_method(), EC_GFp_nistp521_method(),
+EC_GFp_simple_method()
+
+There are no replacements for these functions. Applications should rely on the
+library automatically assigning a suitable method internally when an EC_GROUP
+is constructed.
+
+=item *
+
+EC_GROUP_clear_free()
+
+Use L<EC_GROUP_free(3)> instead.
+
+=item *
+
+EC_GROUP_get_curve_GF2m(), EC_GROUP_get_curve_GFp(), EC_GROUP_set_curve_GF2m(),
+EC_GROUP_set_curve_GFp()
+
+Applications should use L<EC_GROUP_get_curve(3)> and L<EC_GROUP_set_curve(3)>.
+
+=item *
+
+EC_GROUP_have_precompute_mult(), EC_GROUP_precompute_mult(),
+EC_KEY_precompute_mult()
+
+These functions are not widely used. Applications should instead switch to
+named curves which OpenSSL has hardcoded lookup tables for.
+
+=item *
+
+EC_GROUP_new(), EC_GROUP_method_of(), EC_POINT_method_of()
+
+EC_METHOD is now an internal-only concept and a suitable EC_METHOD is assigned
+internally without application intervention.
+Users of EC_GROUP_new() should switch to a different suitable constructor.
+
+=item *
+
+EC_KEY_can_sign()
+
+Applications should use L<EVP_PKEY_can_sign(3)> instead.
+
+=item *
+
+EC_KEY_check_key()
+
+See L</Deprecated low-level validation functions>
+
+=item *
+
+EC_KEY_set_flags(), EC_KEY_get_flags(), EC_KEY_clear_flags()
+
+See L<EVP_PKEY-EC(7)/Common EC parameters> which handles flags as seperate
+parameters for B<OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT>,
+B<OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE>, B<OSSL_PKEY_PARAM_EC_ENCODING>,
+B<OSSL_PKEY_PARAM_USE_COFACTOR_ECDH> and
+B<OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC>.
+See also L<EVP_PKEY-EC(7)/EXAMPLES>
+
+=item *
+
+EC_KEY_dup(), EC_KEY_copy()
+
+There is no direct replacement. Applications may use L<EVP_PKEY_copy_parameters(3)>
+and L<EVP_PKEY_dup(3)> instead.
+
+=item *
+
+EC_KEY_decoded_from_explicit_params()
+
+There is no replacement.
+
+=item *
+
+EC_KEY_generate_key()
+
+See L</Deprecated low-level key generation functions>.
+
+=item *
+
+EC_KEY_get0_group(), EC_KEY_get0_private_key(), EC_KEY_get0_public_key(),
+EC_KEY_get_conv_form(), EC_KEY_get_enc_flags()
+
+See L</Deprecated low-level key parameter getters>.
+
+=item *
+
+EC_KEY_get0_engine(), EC_KEY_get_default_method(), EC_KEY_get_method(),
+EC_KEY_new_method(), EC_KEY_get_ex_data(), EC_KEY_OpenSSL(),
+EC_KEY_set_ex_data(), EC_KEY_set_default_method(), EC_KEY_METHOD_*(),
+EC_KEY_set_method()
+
+See L</Providers are a replacement for engines and low-level method overrides>
+
+=item *
+
+EC_METHOD_get_field_type()
+
+Use L<EC_GROUP_get_field_type(3)> instead.
+See L</Providers are a replacement for engines and low-level method overrides>
+
+=item *
+
+EC_KEY_key2buf(), EC_KEY_oct2key(), EC_KEY_oct2priv(), EC_KEY_priv2buf(),
+EC_KEY_priv2oct()
+
+There are no replacements for these.
+
+=item *
+
+EC_KEY_new(), EC_KEY_new_by_curve_name(), EC_KEY_free(), EC_KEY_up_ref()
+
+See L</Deprecated low-level object creation>
+
+=item *
+
+EC_KEY_print(), EC_KEY_print_fp()
+
+See L</Deprecated low-level key printing functions>
+
+=item *
+
+EC_KEY_set_asn1_flag(), EC_KEY_set_conv_form(), EC_KEY_set_enc_flags()
+
+See L</Deprecated low-level key parameter setters>.
+
+=item *
+
+EC_KEY_set_group(), EC_KEY_set_private_key(), EC_KEY_set_public_key(),
+EC_KEY_set_public_key_affine_coordinates()
+
+See L</Deprecated low-level key parameter setters>.
+
+=item *
+
+ECParameters_print(), ECParameters_print_fp(), ECPKParameters_print(),
+ECPKParameters_print_fp()
+
+See L</Deprecated low-level key printing functions>
+
+=item *
+
+EC_POINT_bn2point(), EC_POINT_point2bn()
+
+These functions were not particularly useful, since EC point serialization
+formats are not individual big-endian integers.
+
+=item *
+
+EC_POINT_get_affine_coordinates_GF2m(), EC_POINT_get_affine_coordinates_GFp(),
+EC_POINT_set_affine_coordinates_GF2m(), EC_POINT_set_affine_coordinates_GFp()
+
+Applications should use L<EC_POINT_get_affine_coordinates(3)> and
+L<EC_POINT_set_affine_coordinates(3)> instead.
+
+=item *
+
+EC_POINT_get_Jprojective_coordinates_GFp(), EC_POINT_set_Jprojective_coordinates_GFp()
+
+These functions are not widely used. Applications should instead use the
+L<EC_POINT_set_affine_coordinates(3)> and L<EC_POINT_get_affine_coordinates(3)>
+functions.
+
+=item *
+
+EC_POINT_make_affine(), EC_POINTs_make_affine()
+
+There is no replacement. These functions were not widely used, and OpenSSL
+automatically performs this conversion when needed.
+
+=item *
+
+EC_POINT_set_compressed_coordinates_GF2m(), EC_POINT_set_compressed_coordinates_GFp()
+
+Applications should use L<EC_POINT_set_compressed_coordinates(3)> instead.
+
+=item *
+
+EC_POINTs_mul()
+
+This function is not widely used. Applications should instead use the
+L<EC_POINT_mul(3)> function.
+
+=item *
+
+B<ENGINE_*()>
+
+All engine functions are deprecated. An engine should be rewritten as a provider.
+See L</Providers are a replacement for engines and low-level method overrides>.
+
+=item *
+
+B<ERR_load_*()>, ERR_func_error_string(), ERR_get_error_line(),
+ERR_get_error_line_data(), ERR_get_state()
+
+OpenSSL now loads error strings automatically so these functions are not needed.
+
+=item *
+
+ERR_peek_error_line_data(), ERR_peek_last_error_line_data()
+
+The new functions are L<ERR_peek_error_func(3)>, L<ERR_peek_last_error_func(3)>,
+L<ERR_peek_error_data(3)>, L<ERR_peek_last_error_data(3)>, L<ERR_get_error_all(3)>,
+L<ERR_peek_error_all(3)> and L<ERR_peek_last_error_all(3)>.
+Applications should use L<ERR_get_error_all(3)>, or pick information
+with ERR_peek functions and finish off with getting the error code by using
+L<ERR_get_error(3)>.
+
+=item *
+
+EVP_CIPHER_CTX_iv(), EVP_CIPHER_CTX_iv_noconst(), EVP_CIPHER_CTX_original_iv()
+
+Applications should instead use L<EVP_CIPHER_CTX_get_updated_iv(3)>,
+L<EVP_CIPHER_CTX_get_updated_iv(3)> and L<EVP_CIPHER_CTX_get_original_iv(3)>
+respectively.
+See L<EVP_CIPHER_CTX_get_original_iv(3)> for further information.
+
+=item *
+
+B<EVP_CIPHER_meth_*()>, EVP_MD_CTX_set_update_fn(), EVP_MD_CTX_update_fn(),
+B<EVP_MD_meth_*()>
+
+See L</Providers are a replacement for engines and low-level method overrides>.
+
+=item *
+
+EVP_PKEY_CTRL_PKCS7_ENCRYPT(), EVP_PKEY_CTRL_PKCS7_DECRYPT(),
+EVP_PKEY_CTRL_PKCS7_SIGN(), EVP_PKEY_CTRL_CMS_ENCRYPT(),
+EVP_PKEY_CTRL_CMS_DECRYPT(), and EVP_PKEY_CTRL_CMS_SIGN()
+
+These control operations are not invoked by the OpenSSL library anymore and
+are replaced by direct checks of the key operation against the key type
+when the operation is initialized.
+
+=item *
+
+EVP_PKEY_CTX_get0_dh_kdf_ukm(), EVP_PKEY_CTX_get0_ecdh_kdf_ukm()
+
+See the "kdf-ukm" item in L<EVP_KEYEXCH-DH(7)/DH key exchange parameters> and
+L<EVP_KEYEXCH-ECDH(7)/ECDH Key Exchange parameters>.
+These functions are obsolete and should not be required.
+
+=item *
+
+EVP_PKEY_CTX_set_rsa_keygen_pubexp()
+
+Applications should use L<EVP_PKEY_CTX_set1_rsa_keygen_pubexp(3)> instead.
+
+=item *
+
+EVP_PKEY_cmp(), EVP_PKEY_cmp_parameters()
+
+Applications should use L<EVP_PKEY_eq(3)> and L<EVP_PKEY_parameters_eq(3)> instead.
+See L<EVP_PKEY_copy_parameters(3)> for further details.
+
+=item *
+
+EVP_PKEY_encrypt_old(), EVP_PKEY_decrypt_old(),
+
+Applications should use L<EVP_PKEY_encrypt_init(3)> and L<EVP_PKEY_encrypt(3)> or
+L<EVP_PKEY_decrypt_init(3)> and L<EVP_PKEY_decrypt(3)> instead.
+
+=item *
+
+EVP_PKEY_get0()
+
+This function returns NULL if the key comes from a provider.
+
+=item *
+
+EVP_PKEY_get0_DH(), EVP_PKEY_get0_DSA(), EVP_PKEY_get0_EC_KEY(), EVP_PKEY_get0_RSA(),
+EVP_PKEY_get1_DH(), EVP_PKEY_get1_DSA(), EVP_PKEY_get1_EC_KEY and EVP_PKEY_get1_RSA(),
+EVP_PKEY_get0_hmac(), EVP_PKEY_get0_poly1305(), EVP_PKEY_get0_siphash()
+
+See L</Functions that return an internal key should be treated as read only>.
+
+=item *
+
+B<EVP_PKEY_meth_*()>
+
+See L</Providers are a replacement for engines and low-level method overrides>.
+
+=item *
+
+EVP_PKEY_new_CMAC_key()
+
+See L</Deprecated low-level MAC functions>.
+
+=item *
+
+EVP_PKEY_assign(), EVP_PKEY_set1_DH(), EVP_PKEY_set1_DSA(),
+EVP_PKEY_set1_EC_KEY(), EVP_PKEY_set1_RSA()
+
+See L</Deprecated low-level key object getters and setters>
+
+=item *
+
+EVP_PKEY_set1_tls_encodedpoint() EVP_PKEY_get1_tls_encodedpoint()
+
+These functions were previously used by libssl to set or get an encoded public
+key into/from an EVP_PKEY object. With OpenSSL 3.0 these are replaced by the more
+generic functions L<EVP_PKEY_set1_encoded_public_key(3)> and
+L<EVP_PKEY_get1_encoded_public_key(3)>.
+The old versions have been converted to deprecated macros that just call the
+new functions.
+
+=item *
+
+EVP_PKEY_set1_engine(), EVP_PKEY_get0_engine()
+
+See L</Providers are a replacement for engines and low-level method overrides>.
+
+=item *
+
+EVP_PKEY_set_alias_type()
+
+This function has been removed. There is no replacement.
+See L</EVP_PKEY_set_alias_type() method has been removed>
+
+=item *
+
+HMAC_Init_ex(), HMAC_Update(), HMAC_Final(), HMAC_size()
+
+See L</Deprecated low-level MAC functions>.
+
+=item *
+
+HMAC_CTX_new(), HMAC_CTX_free(), HMAC_CTX_copy(), HMAC_CTX_reset(),
+HMAC_CTX_set_flags(), HMAC_CTX_get_md()
+
+See L</Deprecated low-level MAC functions>.
+
+=item *
+
+i2d_DHparams(), i2d_DHxparams()
+
+See L</Deprecated low-level key reading and writing functions>
+and L<d2i_RSAPrivateKey(3)/Migration>
+
+=item *
+
+i2d_DSAparams(), i2d_DSAPrivateKey(), i2d_DSAPrivateKey_bio(),
+i2d_DSAPrivateKey_fp(), i2d_DSA_PUBKEY(), i2d_DSA_PUBKEY_bio(),
+i2d_DSA_PUBKEY_fp(), i2d_DSAPublicKey()
+
+See L</Deprecated low-level key reading and writing functions>
+and L<d2i_RSAPrivateKey(3)/Migration>
+
+=item *
+
+i2d_ECParameters(), i2d_ECPrivateKey(), i2d_ECPrivateKey_bio(),
+i2d_ECPrivateKey_fp(), i2d_EC_PUBKEY(), i2d_EC_PUBKEY_bio(),
+i2d_EC_PUBKEY_fp(), i2o_ECPublicKey()
+
+See L</Deprecated low-level key reading and writing functions>
+and L<d2i_RSAPrivateKey(3)/Migration>
+
+=item *
+
+i2d_RSAPrivateKey(), i2d_RSAPrivateKey_bio(), i2d_RSAPrivateKey_fp(),
+i2d_RSA_PUBKEY(), i2d_RSA_PUBKEY_bio(), i2d_RSA_PUBKEY_fp(),
+i2d_RSAPublicKey(), i2d_RSAPublicKey_bio(), i2d_RSAPublicKey_fp()
+
+See L</Deprecated low-level key reading and writing functions>
+and L<d2i_RSAPrivateKey(3)/Migration>
+
+=item *
+
+IDEA_encrypt(), IDEA_set_decrypt_key(), IDEA_set_encrypt_key(),
+IDEA_cbc_encrypt(), IDEA_cfb64_encrypt(), IDEA_ecb_encrypt(),
+IDEA_ofb64_encrypt()
+
+See L</Deprecated low-level encryption functions>.
+IDEA has been moved to the L<Legacy Provider|/Legacy Algorithms>.
+
+=item *
+
+IDEA_options()
+
+There is no replacement. This function returned a constant string.
+
+=item *
+
+MD2(), MD2_Init(), MD2_Update(), MD2_Final()
+
+See L</Deprecated low-level encryption functions>.
+MD2 has been moved to the L<Legacy Provider|/Legacy Algorithms>.
+
+=item *
+
+MD2_options()
+
+There is no replacement. This function returned a constant string.
+
+=item *
+
+MD4(), MD4_Init(), MD4_Update(), MD4_Final(), MD4_Transform()
+
+See L</Deprecated low-level encryption functions>.
+MD4 has been moved to the L<Legacy Provider|/Legacy Algorithms>.
+
+=item *
+
+MDC2(), MDC2_Init(), MDC2_Update(), MDC2_Final()
+
+See L</Deprecated low-level encryption functions>.
+MDC2 has been moved to the L<Legacy Provider|/Legacy Algorithms>.
+
+=item *
+
+MD5(), MD5_Init(), MD5_Update(), MD5_Final(), MD5_Transform()
+
+See L</Deprecated low-level encryption functions>.
+
+=item *
+
+NCONF_WIN32()
+
+This undocumented function has no replacement.
+See L<config(5)/HISTORY> for more details.
+
+=item *
+
+OCSP_parse_url()
+
+Use L<OSSL_HTTP_parse_url(3)> instead.
+
+=item *
+
+B<OCSP_REQ_CTX> type and B<OCSP_REQ_CTX_*()> functions
+
+These methods were used to collect all necessary data to form a HTTP request,
+and to perform the HTTP transfer with that request. With OpenSSL 3.0, the
+type is B<OSSL_HTTP_REQ_CTX>, and the deprecated functions are replaced
+with B<OSSL_HTTP_REQ_CTX_*()>. See L<OSSL_HTTP_REQ_CTX(3)> for additional
+details.
+
+=item *
+
+OPENSSL_fork_child(), OPENSSL_fork_parent(), OPENSSL_fork_prepare()
+
+There is no replacement for these functions. These pthread fork support methods
+were unused by OpenSSL.
+
+=item *
+
+OSSL_STORE_ctrl(), OSSL_STORE_do_all_loaders(), OSSL_STORE_LOADER_get0_engine(),
+OSSL_STORE_LOADER_get0_scheme(), OSSL_STORE_LOADER_new(),
+OSSL_STORE_LOADER_set_attach(), OSSL_STORE_LOADER_set_close(),
+OSSL_STORE_LOADER_set_ctrl(), OSSL_STORE_LOADER_set_eof(),
+OSSL_STORE_LOADER_set_error(), OSSL_STORE_LOADER_set_expect(),
+OSSL_STORE_LOADER_set_find(), OSSL_STORE_LOADER_set_load(),
+OSSL_STORE_LOADER_set_open(), OSSL_STORE_LOADER_set_open_ex(),
+OSSL_STORE_register_loader(), OSSL_STORE_unregister_loader(),
+OSSL_STORE_vctrl()
+
+These functions helped applications and engines create loaders for
+schemes they supported. These are all deprecated and discouraged in favour of
+provider implementations, see L<provider-storemgmt(7)>.
+
+=item *
+
+PEM_read_DHparams(), PEM_read_bio_DHparams(),
+PEM_read_DSAparams(), PEM_read_bio_DSAparams(),
+PEM_read_DSAPrivateKey(), PEM_read_DSA_PUBKEY(),
+PEM_read_bio_DSAPrivateKey and PEM_read_bio_DSA_PUBKEY(),
+PEM_read_ECPKParameters(), PEM_read_ECPrivateKey(), PEM_read_EC_PUBKEY(),
+PEM_read_bio_ECPKParameters(), PEM_read_bio_ECPrivateKey(), PEM_read_bio_EC_PUBKEY(),
+PEM_read_RSAPrivateKey(), PEM_read_RSA_PUBKEY(), PEM_read_RSAPublicKey(),
+PEM_read_bio_RSAPrivateKey(), PEM_read_bio_RSA_PUBKEY(), PEM_read_bio_RSAPublicKey(),
+PEM_write_bio_DHparams(), PEM_write_bio_DHxparams(), PEM_write_DHparams(), PEM_write_DHxparams(),
+PEM_write_DSAparams(), PEM_write_DSAPrivateKey(), PEM_write_DSA_PUBKEY(),
+PEM_write_bio_DSAparams(), PEM_write_bio_DSAPrivateKey(), PEM_write_bio_DSA_PUBKEY(),
+PEM_write_ECPKParameters(), PEM_write_ECPrivateKey(), PEM_write_EC_PUBKEY(),
+PEM_write_bio_ECPKParameters(), PEM_write_bio_ECPrivateKey(), PEM_write_bio_EC_PUBKEY(),
+PEM_write_RSAPrivateKey(), PEM_write_RSA_PUBKEY(), PEM_write_RSAPublicKey(),
+PEM_write_bio_RSAPrivateKey(), PEM_write_bio_RSA_PUBKEY(),
+PEM_write_bio_RSAPublicKey(),
+
+See L</Deprecated low-level key reading and writing functions>
+
+=item *
+
+PKCS1_MGF1()
+
+See L</Deprecated low-level encryption functions>.
+
+=item *
+
+RAND_get_rand_method(), RAND_set_rand_method(), RAND_OpenSSL(),
+RAND_set_rand_engine()
+
+Applications should instead use L<RAND_set_DRBG_type(3)>,
+L<EVP_RAND(3)> and L<EVP_RAND(7)>.
+See L<RAND_set_rand_method(3)> for more details.
+
+=item *
+
+RC2_encrypt(), RC2_decrypt(), RC2_set_key(), RC2_cbc_encrypt(), RC2_cfb64_encrypt(),
+RC2_ecb_encrypt(), RC2_ofb64_encrypt(),
+RC4(), RC4_set_key(), RC4_options(),
+RC5_32_encrypt(), RC5_32_set_key(), RC5_32_decrypt(), RC5_32_cbc_encrypt(),
+RC5_32_cfb64_encrypt(), RC5_32_ecb_encrypt(), RC5_32_ofb64_encrypt()
+
+See L</Deprecated low-level encryption functions>.
+The Algorithms "RC2", "RC4" and "RC5" have been moved to the L<Legacy Provider|/Legacy Algorithms>.
+
+=item *
+
+RIPEMD160(), RIPEMD160_Init(), RIPEMD160_Update(), RIPEMD160_Final(),
+RIPEMD160_Transform()
+
+See L</Deprecated low-level digest functions>.
+The RIPE algorithm has been moved to the L<Legacy Provider|/Legacy Algorithms>.
+
+=item *
+
+RSA_bits(), RSA_security_bits(), RSA_size()
+
+Use L<EVP_PKEY_get_bits(3)>, L<EVP_PKEY_get_security_bits(3)> and
+L<EVP_PKEY_get_size(3)>.
+
+=item *
+
+RSA_check_key(), RSA_check_key_ex()
+
+See L</Deprecated low-level validation functions>
+
+=item *
+
+RSA_clear_flags(), RSA_flags(), RSA_set_flags(), RSA_test_flags(),
+RSA_setup_blinding(), RSA_blinding_off(), RSA_blinding_on()
+
+All of these RSA flags have been deprecated without replacement:
+
+B<RSA_FLAG_BLINDING>, B<RSA_FLAG_CACHE_PRIVATE>, B<RSA_FLAG_CACHE_PUBLIC>,
+B<RSA_FLAG_EXT_PKEY>, B<RSA_FLAG_NO_BLINDING>, B<RSA_FLAG_THREAD_SAFE>
+B<RSA_METHOD_FLAG_NO_CHECK>
+
+=item *
+
+RSA_generate_key_ex(), RSA_generate_multi_prime_key()
+
+See L</Deprecated low-level key generation functions>.
+
+=item *
+
+RSA_get0_engine()
+
+See L</Providers are a replacement for engines and low-level method overrides>
+
+=item *
+
+RSA_get0_crt_params(), RSA_get0_d(), RSA_get0_dmp1(), RSA_get0_dmq1(),
+RSA_get0_e(), RSA_get0_factors(), RSA_get0_iqmp(), RSA_get0_key(),
+RSA_get0_multi_prime_crt_params(), RSA_get0_multi_prime_factors(), RSA_get0_n(),
+RSA_get0_p(), RSA_get0_pss_params(), RSA_get0_q(),
+RSA_get_multi_prime_extra_count()
+
+See L</Deprecated low-level key parameter getters>
+
+=item *
+
+RSA_new(), RSA_free(), RSA_up_ref()
+
+See L</Deprecated low-level object creation>.
+
+=item *
+
+RSA_get_default_method(), RSA_get_ex_data and RSA_get_method()
+
+See L</Providers are a replacement for engines and low-level method overrides>.
+
+=item *
+
+RSA_get_version()
+
+There is no replacement.
+
+=item *
+
+B<RSA_meth_*()>, RSA_new_method(), RSA_null_method and RSA_PKCS1_OpenSSL()
+
+See L</Providers are a replacement for engines and low-level method overrides>.
+
+=item *
+
+B<RSA_padding_add_*()>, B<RSA_padding_check_*()>
+
+See L</Deprecated low-level signing functions> and
+L</Deprecated low-level encryption functions>.
+
+=item *
+
+RSA_print(), RSA_print_fp()
+
+See L</Deprecated low-level key printing functions>
+
+=item *
+
+RSA_public_encrypt(), RSA_private_decrypt()
+
+See L</Deprecated low-level encryption functions>
+
+=item *
+
+RSA_private_encrypt(), RSA_public_decrypt()
+
+This is equivalent to doing sign and verify recover operations (with a padding
+mode of none). See L</Deprecated low-level signing functions>.
+
+=item *
+
+RSAPrivateKey_dup(), RSAPublicKey_dup()
+
+There is no direct replacement. Applications may use L<EVP_PKEY_dup(3)>.
+
+=item *
+
+RSAPublicKey_it(), RSAPrivateKey_it()
+
+See L</Deprecated low-level key reading and writing functions>
+
+=item *
+
+RSA_set0_crt_params(), RSA_set0_factors(), RSA_set0_key(),
+RSA_set0_multi_prime_params()
+
+See L</Deprecated low-level key parameter setters>.
+
+=item *
+
+RSA_set_default_method(), RSA_set_method(), RSA_set_ex_data()
+
+See L</Providers are a replacement for engines and low-level method overrides>
+
+=item *
+
+RSA_sign(), RSA_sign_ASN1_OCTET_STRING(), RSA_verify(),
+RSA_verify_ASN1_OCTET_STRING(), RSA_verify_PKCS1_PSS(),
+RSA_verify_PKCS1_PSS_mgf1()
+
+See L</Deprecated low-level signing functions>.
+
+=item *
+
+RSA_X931_derive_ex(), RSA_X931_generate_key_ex(), RSA_X931_hash_id()
+
+There are no replacements for these functions.
+X931 padding can be set using L<EVP_SIGNATURE-RSA(7)/Signature Parameters>.
+See B<OSSL_SIGNATURE_PARAM_PAD_MODE>.
+
+=item *
+
+SEED_encrypt(), SEED_decrypt(), SEED_set_key(), SEED_cbc_encrypt(),
+SEED_cfb128_encrypt(), SEED_ecb_encrypt(), SEED_ofb128_encrypt()
+
+See L</Deprecated low-level encryption functions>.
+The SEED algorithm has been moved to the L<Legacy Provider|/Legacy Algorithms>.
+
+=item *
+
+SHA1_Init(), SHA1_Update(), SHA1_Final(), SHA1_Transform(),
+SHA224_Init(), SHA224_Update(), SHA224_Final(),
+SHA256_Init(), SHA256_Update(), SHA256_Final(), SHA256_Transform(),
+SHA384_Init(), SHA384_Update(), SHA384_Final(),
+SHA512_Init(), SHA512_Update(), SHA512_Final(), SHA512_Transform()
+
+See L</Deprecated low-level digest functions>.
+
+=item *
+
+SRP_Calc_A(), SRP_Calc_B(), SRP_Calc_client_key(), SRP_Calc_server_key(),
+SRP_Calc_u(), SRP_Calc_x(), SRP_check_known_gN_param(), SRP_create_verifier(),
+SRP_create_verifier_BN(), SRP_get_default_gN(), SRP_user_pwd_free(), SRP_user_pwd_new(),
+SRP_user_pwd_set0_sv(), SRP_user_pwd_set1_ids(), SRP_user_pwd_set_gN(),
+SRP_VBASE_add0_user(), SRP_VBASE_free(), SRP_VBASE_get1_by_user(), SRP_VBASE_init(),
+SRP_VBASE_new(), SRP_Verify_A_mod_N(), SRP_Verify_B_mod_N()
+
+There are no replacements for the SRP functions.
+
+=item *
+
+SSL_CTX_set_tmp_dh_callback(), SSL_set_tmp_dh_callback(),
+SSL_CTX_set_tmp_dh(), SSL_set_tmp_dh()
+
+These are used to set the Diffie-Hellman (DH) parameters that are to be used by
+servers requiring ephemeral DH keys. Instead applications should consider using
+the built-in DH parameters that are available by calling L<SSL_CTX_set_dh_auto(3)>
+or L<SSL_set_dh_auto(3)>. If custom parameters are necessary then applications can
+use the alternative functions L<SSL_CTX_set0_tmp_dh_pkey(3)> and
+L<SSL_set0_tmp_dh_pkey(3)>. There is no direct replacement for the "callback"
+functions. The callback was originally useful in order to have different
+parameters for export and non-export ciphersuites. Export ciphersuites are no
+longer supported by OpenSSL. Use of the callback functions should be replaced
+by one of the other methods described above.
+
+=item *
+
+SSL_CTX_set_tlsext_ticket_key_cb()
+
+Use the new L<SSL_CTX_set_tlsext_ticket_key_evp_cb(3)> function instead.
+
+=item *
+
+WHIRLPOOL(), WHIRLPOOL_Init(), WHIRLPOOL_Update(), WHIRLPOOL_Final(),
+WHIRLPOOL_BitUpdate()
+
+See L</Deprecated low-level digest functions>.
+The Whirlpool algorithm has been moved to the L<Legacy Provider|/Legacy Algorithms>.
+
+=item *
+
+X509_certificate_type()
+
+This was an undocumented function. Applications can use L<X509_get0_pubkey(3)>
+and L<X509_get0_signature(3)> instead.
+
+=item *
+
+X509_http_nbio(), X509_CRL_http_nbio()
+
+Use L<X509_load_http(3)> and L<X509_CRL_load_http(3)> instead.
+
+=back
+
+=head2 Using the FIPS Module in applications
+
+See L<fips_module(7)> and L<OSSL_PROVIDER-FIPS(7)> for details.
+
+=head2 OpenSSL command line application changes
+
+=head3 New applications
+
+L<B<openssl kdf>|openssl-kdf(1)> uses the new L<EVP_KDF(3)> API.
+L<B<openssl kdf>|openssl-mac(1)> uses the new L<EVP_MAC(3)> API.
+
+=head3 Added options
+
+B<-provider_path> and B<-provider> are available to all apps and can be used
+multiple times to load any providers, such as the 'legacy' provider or third
+party providers. If used then the 'default' provider would also need to be
+specified if required. The B<-provider_path> must be specified before the
+B<-provider> option.
+
+The B<list> app has many new options. See L<openssl-list(1)> for more
+information.
+
+B<-crl_lastupdate> and B<-crl_nextupdate> used by B<openssl ca> allows
+explicit setting of fields in the generated CRL.
+
+=head3 Removed options
+
+Interactive mode is not longer available.
+
+The B<-crypt> option used by B<openssl passwd>.
+The B<-c> option used by B<openssl x509>, B<openssl dhparam>,
+B<openssl dsaparam>, and B<openssl ecparam>.
+
+=head3 Other Changes
+
+The output of Command line applications may have minor changes.
+These are primarily changes in capitalisation and white space. However, in some
+cases, there are additional differences.
+For example, the DH parameters output from B<openssl dhparam> now lists 'P',
+'Q', 'G' and 'pcounter' instead of 'prime', 'generator', 'subgroup order' and
+'counter' respectively.
+
+The B<openssl> commands that read keys, certificates, and CRLs now
+automatically detect the PEM or DER format of the input files so it is not
+necessary to explicitly specify the input format anymore. However if the
+input format option is used the specified format will be required.
+
+B<openssl speed> no longer uses low-level API calls.
+This implies some of the performance numbers might not be comparable with the
+previous releases due to higher overhead. This applies particularly to
+measuring performance on smaller data chunks.
+
+b<openssl dhparam>, B<openssl dsa>, B<openssl gendsa>, B<openssl dsaparam>,
+B<openssl genrsa> and B<openssl rsa> have been modified to use PKEY APIs.
+B<openssl genrsa> and B<openssl rsa> now write PKCS #8 keys by default.
+
+=head3 Default settings
+
+"SHA256" is now the default digest for TS query used by B<openssl ts>.
+
+=head3 Deprecated apps
+
+B<openssl rsautl> is deprecated, use B<openssl pkeyutl> instead.
+B<openssl dhparam>, B<openssl dsa>, B<openssl gendsa>, B<openssl dsaparam>,
+B<openssl genrsa>, B<openssl rsa>, B<openssl genrsa> and B<openssl rsa> are
+now in maintenance mode and no new features will be added to them.
+
+=head2 TLS Changes
+
+=over 4
+
+=item *
+
+TLS 1.3 FFDHE key exchange support added
+
+This uses DH safe prime named groups.
+
+=item *
+
+Support for fully "pluggable" TLSv1.3 groups.
+
+This means that providers may supply their own group implementations (using
+either the "key exchange" or the "key encapsulation" methods) which will
+automatically be detected and used by libssl.
+
+=item *
+
+SSL and SSL_CTX options are now 64 bit instead of 32 bit.
+
+The signatures of the functions to get and set options on SSL and
+SSL_CTX objects changed from "unsigned long" to "uint64_t" type.
+
+This may require source code changes. For example it is no longer possible
+to use the B<SSL_OP_> macro values in preprocessor C<#if> conditions.
+However it is still possible to test whether these macros are defined or not.
+
+See L<SSL_CTX_get_options(3)>, L<SSL_CTX_set_options(3)>,
+L<SSL_get_options(3)> and L<SSL_set_options(3)>.
+
+=item *
+
+SSL_set1_host() and SSL_add1_host() Changes
+
+These functions now take IP literal addresses as well as actual hostnames.
+
+=item *
+
+Added SSL option SSL_OP_CLEANSE_PLAINTEXT
+
+If the option is set, openssl cleanses (zeroizes) plaintext bytes from
+internal buffers after delivering them to the application. Note,
+the application is still responsible for cleansing other copies
+(e.g.: data received by L<SSL_read(3)>).
+
+=item *
+
+Client-initiated renegotiation is disabled by default.
+
+To allow it, use the B<-client_renegotiation> option,
+the B<SSL_OP_ALLOW_CLIENT_RENEGOTIATION> flag, or the C<ClientRenegotiation>
+config parameter as appropriate.
+
+=item *
+
+Secure renegotiation is now required by default for TLS connections
+
+Support for RFC 5746 secure renegotiation is now required by default for
+SSL or TLS connections to succeed. Applications that require the ability
+to connect to legacy peers will need to explicitly set
+SSL_OP_LEGACY_SERVER_CONNECT. Accordingly, SSL_OP_LEGACY_SERVER_CONNECT
+is no longer set as part of SSL_OP_ALL.
+
+=item *
+
+Combining the Configure options no-ec and no-dh no longer disables TLSv1.3
+
+Typically if OpenSSL has no EC or DH algorithms then it cannot support
+connections with TLSv1.3. However OpenSSL now supports "pluggable" groups
+through providers. Therefore third party providers may supply group
+implementations even where there are no built-in ones. Attempting to create
+TLS connections in such a build without also disabling TLSv1.3 at run time or
+using third party provider groups may result in handshake failures. TLSv1.3
+can be disabled at compile time using the "no-tls1_3" Configure option.
+
+=item *
+
+SSL_CTX_set_ciphersuites() and SSL_set_ciphersuites() changes.
+
+The methods now ignore unknown ciphers.
+
+=item *
+
+Security callback change.
+
+The security callback, which can be customised by application code, supports
+the security operation SSL_SECOP_TMP_DH. This is defined to take an EVP_PKEY
+in the "other" parameter. In most places this is what is passed. All these
+places occur server side. However there was one client side call of this
+security operation and it passed a DH object instead. This is incorrect
+according to the definition of SSL_SECOP_TMP_DH, and is inconsistent with all
+of the other locations. Therefore this client side call has been changed to
+pass an EVP_PKEY instead.
+
+=item *
+
+New SSL option SSL_OP_IGNORE_UNEXPECTED_EOF
+
+The SSL option SSL_OP_IGNORE_UNEXPECTED_EOF is introduced. If that option
+is set, an unexpected EOF is ignored, it pretends a close notify was received
+instead and so the returned error becomes SSL_ERROR_ZERO_RETURN.
+
+=item *
+
+The security strength of SHA1 and MD5 based signatures in TLS has been reduced.
+
+This results in SSL 3, TLS 1.0, TLS 1.1 and DTLS 1.0 no longer
+working at the default security level of 1 and instead requires security
+level 0. The security level can be changed either using the cipher string
+with C<@SECLEVEL>, or calling L<SSL_CTX_set_security_level(3)>. This also means
+that where the signature algorithms extension is missing from a ClientHello
+then the handshake will fail in TLS 1.2 at security level 1. This is because,
+although this extension is optional, failing to provide one means that
+OpenSSL will fallback to a default set of signature algorithms. This default
+set requires the availability of SHA1.
+
+=item *
+
+X509 certificates signed using SHA1 are no longer allowed at security level 1 and above.
+
+In TLS/SSL the default security level is 1. It can be set either using the cipher
+string with C<@SECLEVEL>, or calling L<SSL_CTX_set_security_level(3)>. If the
+leaf certificate is signed with SHA-1, a call to L<SSL_CTX_use_certificate(3)>
+will fail if the security level is not lowered first.
+Outside TLS/SSL, the default security level is -1 (effectively 0). It can
+be set using L<X509_VERIFY_PARAM_set_auth_level(3)> or using the B<-auth_level>
+options of the commands.
+
+=back
+
+=head1 SEE ALSO
+
+L<fips_module(7)>
+
+=head1 HISTORY
+
+The migration guide was created for OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/openssl-core.h.pod b/doc/man7/openssl-core.h.pod
new file mode 100644
index 000000000000..568bf397b4a7
--- /dev/null
+++ b/doc/man7/openssl-core.h.pod
@@ -0,0 +1,54 @@
+=pod
+
+=head1 NAME
+
+openssl/core.h - OpenSSL Core types
+
+=head1 SYNOPSIS
+
+ #include <openssl/core.h>
+
+=head1 DESCRIPTION
+
+The F<< <openssl/core.h> >> header defines a number of public types that
+are used to communicate between the OpenSSL libraries and
+implementation providers.
+These types are designed to minimise the need for intimate knowledge
+of internal structures between the OpenSSL libraries and the providers.
+
+The types are:
+
+=over 4
+
+=item L<OSSL_DISPATCH(3)>
+
+=item L<OSSL_ITEM(3)>
+
+=item L<OSSL_ALGORITHM(3)>
+
+=item L<OSSL_PARAM(3)>
+
+=item L<OSSL_CALLBACK(3)>
+
+=item L<OSSL_PASSPHRASE_CALLBACK(3)>
+
+=back
+
+=head1 SEE ALSO
+
+L<openssl-core_dispatch.h(7)>
+
+=head1 HISTORY
+
+The types described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/openssl-core_dispatch.h.pod b/doc/man7/openssl-core_dispatch.h.pod
new file mode 100644
index 000000000000..a19e1331fa68
--- /dev/null
+++ b/doc/man7/openssl-core_dispatch.h.pod
@@ -0,0 +1,56 @@
+=pod
+
+=head1 NAME
+
+openssl/core_dispatch.h
+- OpenSSL provider dispatch numbers and function types
+
+=head1 SYNOPSIS
+
+ #include <openssl/core_dispatch.h>
+
+=head1 DESCRIPTION
+
+The F<< <openssl/core_dispatch.h> >> header defines all the operation
+numbers, dispatch numbers and provider interface function types
+currently available.
+
+The operation and dispatch numbers are represented with macros, which
+are named as follows:
+
+=over 4
+
+=item operation numbers
+
+These macros have the form C<OSSL_OP_I<opname>>.
+
+=item dipatch numbers
+
+These macros have the form C<OSSL_FUNC_I<opname>_I<funcname>>, where
+C<I<opname>> is the same as in the macro for the operation this
+function belongs to.
+
+=back
+
+With every dispatch number, there is an associated function type.
+
+For further information, please see the L<provider(7)>
+
+=head1 SEE ALSO
+
+L<provider(7)>
+
+=head1 HISTORY
+
+The types and macros described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/openssl-core_names.h.pod b/doc/man7/openssl-core_names.h.pod
new file mode 100644
index 000000000000..a11bf3feee79
--- /dev/null
+++ b/doc/man7/openssl-core_names.h.pod
@@ -0,0 +1,49 @@
+=pod
+
+=head1 NAME
+
+openssl/core_names.h - OpenSSL provider parameter names
+
+=head1 SYNOPSIS
+
+ #include <openssl/core_names.h>
+
+=head1 DESCRIPTION
+
+The F<< <openssl/core_names.h> >> header defines a multitude of macros
+for L<OSSL_PARAM(3)> names, algorithm names and other known names used
+with OpenSSL's providers, made available for practical purposes only.
+
+Existing names are further described in the manuals for OpenSSL's
+providers (see L</SEE ALSO>) and the manuals for each algorithm they
+provide (listed in those provider manuals).
+
+=head1 SEE ALSO
+
+L<OSSL_PROVIDER-default(7)>, L<OSSL_PROVIDER-FIPS(7)>,
+L<OSSL_PROVIDER-legacy(7)>
+
+=head1 HISTORY
+
+The macros described here were added in OpenSSL 3.0.
+
+=head1 CAVEATS
+
+I<This header file does not constitute a general registry of names>.
+Providers that implement new algorithms are to be responsible for
+their own parameter names.
+
+However, authors of provider that implement their own variants of
+algorithms that OpenSSL providers support will want to pay attention
+to the names provided in this header to work in a compatible manner.
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/openssl-env.pod b/doc/man7/openssl-env.pod
new file mode 100644
index 000000000000..a2443d54d822
--- /dev/null
+++ b/doc/man7/openssl-env.pod
@@ -0,0 +1,101 @@
+=pod
+
+=head1 NAME
+
+openssl-env - OpenSSL environment variables
+
+=head1 DESCRIPTION
+
+The OpenSSL libraries use environment variables to override the
+compiled-in default paths for various data.
+To avoid security risks, the environment is usually not consulted when
+the executable is set-user-ID or set-group-ID.
+
+=over 4
+
+=item B<CTLOG_FILE>
+
+Specifies the path to a certificate transparency log list.
+See L<CTLOG_STORE_new(3)>.
+
+=item B<OPENSSL>
+
+Specifies the path to the B<openssl> executable. Used by
+the B<rehash> script (see L<openssl-rehash(1)/Script Configuration>)
+and by the B<CA.pl> script (see L<CA.pl(1)/NOTES>
+
+=item B<OPENSSL_CONF>, B<OPENSSL_CONF_INCLUDE>
+
+Specifies the path to a configuration file and the directory for
+included files.
+See L<config(5)>.
+
+=item B<OPENSSL_CONFIG>
+
+Specifies a configuration option and filename for the B<req> and B<ca>
+commands invoked by the B<CA.pl> script.
+See L<CA.pl(1)>.
+
+=item B<OPENSSL_ENGINES>
+
+Specifies the directory from which dynamic engines are loaded.
+See L<openssl-engine(1)>.
+
+=item B<OPENSSL_MALLOC_FD>, B<OPENSSL_MALLOC_FAILURES>
+
+If built with debugging, this allows memory allocation to fail.
+See L<OPENSSL_malloc(3)>.
+
+=item B<OPENSSL_MODULES>
+
+Specifies the directory from which cryptographic providers are loaded.
+Equivalently, the generic B<-provider-path> command-line option may be used.
+
+=item B<OPENSSL_WIN32_UTF8>
+
+If set, then L<UI_OpenSSL(3)> returns UTF-8 encoded strings, rather than
+ones encoded in the current code page, and
+the L<openssl(1)> program also transcodes the command-line parameters
+from the current code page to UTF-8.
+This environment variable is only checked on Microsoft Windows platforms.
+
+=item B<RANDFILE>
+
+The state file for the random number generator.
+This should not be needed in normal use.
+See L<RAND_load_file(3)>.
+
+=item B<SSL_CERT_DIR>, B<SSL_CERT_FILE>
+
+Specify the default directory or file containing CA certificates.
+See L<SSL_CTX_load_verify_locations(3)>.
+
+=item B<TSGET>
+
+Additional arguments for the L<tsget(1)> command.
+
+=item B<OPENSSL_ia32cap>, B<OPENSSL_sparcv9cap>, B<OPENSSL_ppccap>, B<OPENSSL_armcap>, B<OPENSSL_s390xcap>
+
+OpenSSL supports a number of different algorithm implementations for
+various machines and, by default, it determines which to use based on the
+processor capabilities and run time feature enquiry. These environment
+variables can be used to exert more control over this selection process.
+See L<OPENSSL_ia32cap(3)>, L<OPENSSL_s390xcap(3)>.
+
+=item B<NO_PROXY>, B<HTTPS_PROXY>, B<HTTP_PROXY>
+
+Specify a proxy hostname.
+See L<OSSL_HTTP_parse_url(3)>.
+
+=back
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/openssl-glossary.pod b/doc/man7/openssl-glossary.pod
new file mode 100644
index 000000000000..b112b375ac20
--- /dev/null
+++ b/doc/man7/openssl-glossary.pod
@@ -0,0 +1,231 @@
+=pod
+
+=head1 NAME
+
+openssl-glossary - An OpenSSL Glossary
+
+=head1 DESCRIPTION
+
+=for comment Please keep the items in case-insensitive alphabetical order
+
+=over 4
+
+=item Algorithm
+
+Cryptograpic primitives such as the SHA256 digest, or AES encryption are
+referred to in OpenSSL as "algorithms". There can be more than one
+implementation for any given algorithm available for use.
+
+L<crypto(7)>
+
+=item ASN.1, ASN1
+
+ASN.1 ("Abstract Syntax Notation One") is a notation for describing abstract
+types and values. It is defined in the ITU-T documents X.680 to X.683:
+
+L<https://www.itu.int/rec/T-REC-X.680>,
+L<https://www.itu.int/rec/T-REC-X.681>,
+L<https://www.itu.int/rec/T-REC-X.682>,
+L<https://www.itu.int/rec/T-REC-X.683>
+
+=item Base Provider
+
+An OpenSSL Provider that contains encoders and decoders for OpenSSL keys. All
+the algorithm implementations in the Base Provider are also available in the
+Default Provider.
+
+L<OSSL_PROVIDER-base(7)>
+
+=item Decoder
+
+A decoder is a type of algorithm used for decoding keys and parameters from some
+external format such as PEM or DER.
+
+L<OSSL_DECODER_CTX_new_for_pkey(3)>
+
+=item Default Provider
+
+An OpenSSL Provider that contains the most commmon OpenSSL algorithm
+implementations. It is loaded by default if no other provider is available. All
+the algorithm implementations in the Base Provider are also available in the
+Default Provider.
+
+L<OSSL_PROVIDER-default(7)>
+
+=item DER ("Distinguished Encoding Rules")
+
+DER is a binary encoding of data, structured according to an ASN.1
+specification. This is a common encoding used for cryptographic objects
+such as private and public keys, certificates, CRLs, ...
+
+It is defined in ITU-T document X.690:
+
+L<https://www.itu.int/rec/T-REC-X.690>
+
+=item Encoder
+
+An encoder is a type of algorithm used for encoding keys and parameters to some
+external format such as PEM or DER.
+
+L<OSSL_ENCODER_CTX_new_for_pkey(3)>
+
+=item Explicit Fetching
+
+Explicit Fetching is a type of Fetching (see Fetching). Explicit Fetching is
+where a function call is made to obtain an algorithm object representing an
+implementation such as L<EVP_MD_fetch(3)> or L<EVP_CIPHER_fetch(3)>
+
+=item Fetching
+
+Fetching is the process of looking through the available algorithm
+implementations, applying selection criteria (via a property query string), and
+finally choosing the implementation that will be used.
+
+Also see Explicit Fetching and Implict Fetching.
+
+L<crypto(7)>
+
+=item FIPS Provider
+
+An OpenSSL Provider that contains OpenSSL algorithm implementations that have
+been validated according to the FIPS 140-2 standard.
+
+L<OSSL_PROVIDER-FIPS(7)>
+
+=item Implicit Fetching
+
+Implicit Fetching is a type of Fetching (see Fetching). Implicit Fetching is
+where an algorithm object with no associated implementation is used such as the
+return value from L<EVP_sha256(3)> or L<EVP_aes_128_cbc(3)>. With implicit
+fetching an implementation is fetched automatically using default selection
+criteria the first time the algorithm is used.
+
+=item Legacy Provider
+
+An OpenSSL Provider that contains algorithm implementations that are considered
+insecure or are no longer in common use.
+
+L<OSSL_PROVIDER-legacy(7)>
+
+=item Library Context
+
+A Library Context in OpenSSL is represented by the type B<OSSL_LIB_CTX>. It can
+be thought of as a scope within which configuration options apply. If an
+application does not explicitly create a library context then the "default"
+one is used. Many OpenSSL functions can take a library context as an argument.
+A NULL value can always be passed to indicate the default library context.
+
+L<OSSL_LIB_CTX(3)>
+
+=item MSBLOB
+
+MSBLOB is a Microsoft specific binary format for RSA and DSA keys, both
+private and public. This form is never passphrase protected.
+
+=item Null Provider
+
+An OpenSSL Provider that contains no algorithm implementations. This can be
+useful to prevent the default provider from being automatically loaded in a
+library context.
+
+L<OSSL_PROVIDER-null(7)>
+
+=item Operation
+
+An operation is a group of OpenSSL functions with a common purpose such as
+encryption, or digesting.
+
+L<crypto(7)>
+
+=item PEM ("Privacy Enhanced Message")
+
+PEM is a format used for encoding of binary content into a mail and ASCII
+friendly form. The content is a series of base64-encoded lines, surrounded
+by begin/end markers each on their own line. For example:
+
+ -----BEGIN PRIVATE KEY-----
+ MIICdg....
+ ... bhTQ==
+ -----END PRIVATE KEY-----
+
+Optional header line(s) may appear after the begin line, and their existence
+depends on the type of object being written or read.
+
+For all OpenSSL uses, the binary content is expected to be a DER encoded
+structure.
+
+This is defined in IETF RFC 1421:
+
+L<https://tools.ietf.org/html/rfc1421>
+
+=item PKCS#8
+
+PKCS#8 is a specification of ASN.1 structures that OpenSSL uses for storing
+or transmitting any private key in a key type agnostic manner.
+There are two structures worth noting for OpenSSL use, one that contains the
+key data in unencrypted form (known as "PrivateKeyInfo") and an encrypted
+wrapper structure (known as "EncryptedPrivateKeyInfo").
+
+This is specified in RFC 5208:
+
+L<https://tools.ietf.org/html/rfc5208>
+
+=item Property
+
+A property is a way of classifying and selecting algorithm implementations.
+A property is a key/value pair expressed as a string. For example all algorithm
+implementations in the default provider have the property "provider=default".
+An algorithm implementation can have multiple properties defined against it.
+
+Also see Property Query String.
+
+L<property(7)>
+
+=item Property Query String
+
+A property query string is a string containing a sequence of properties that
+can be used to select an algorithm implementation. For example the query string
+"provider=example,foo=bar" will select algorithms from the "example" provider
+that have a "foo" property defined for them with a value of "bar".
+
+Property Query Strings are used during fetching. See Fetching.
+
+L<property(7)>
+
+=item Provider
+
+A provider in OpenSSL is a component that groups together algorithm
+implementations. Providers can come from OpenSSL itself or from third parties.
+
+L<provider(7)>
+
+=item PVK
+
+PVK is a Microsoft specific binary format for RSA and DSA private keys.
+This form may be passphrase protected.
+
+=item SubjectPublicKeyInfo
+
+SubjectPublicKeyInfo is an ASN.1 structure that OpenSSL uses for storing and
+transmitting any public key in a key type agnostic manner.
+
+This is specified as part of the specification for certificates, RFC 5280:
+
+L<https://tools.ietf.org/html/rfc5280>
+
+=back
+
+=head1 HISTORY
+
+This glossary was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/openssl-threads.pod b/doc/man7/openssl-threads.pod
new file mode 100644
index 000000000000..56cc638e1b86
--- /dev/null
+++ b/doc/man7/openssl-threads.pod
@@ -0,0 +1,105 @@
+=pod
+
+=head1 NAME
+
+openssl-threads - Overview of thread safety in OpenSSL
+
+=head1 DESCRIPTION
+
+In this man page, we use the term B<thread-safe> to indicate that an
+object or function can be used by multiple threads at the same time.
+
+OpenSSL can be built with or without threads support. The most important
+use of this support is so that OpenSSL itself can use a single consistent
+API, as shown in L<CRYPTO_THREAD_run_once(3)/EXAMPLES>.
+Multi-platform applications can also use this API.
+
+In particular, being configured for threads support does not imply that
+all OpenSSL objects are thread-safe.
+To emphasize: I<most objects are not safe for simultaneous use>.
+Exceptions to this should be documented on the specific manual pages, and
+some general high-level guidance is given here.
+
+One major use of the OpenSSL thread API is to implement reference counting.
+Many objects within OpenSSL are reference-counted, so resources are not
+released, until the last reference is removed.
+References are often increased automatically (such as when an B<X509>
+certificate object is added into an B<X509_STORE> trust store).
+There is often an B<I<object>_up_ref>() function that can be used to increase
+the reference count.
+Failure to match B<I<object>_up_ref>() calls with the right number of
+B<I<object>_free>() calls is a common source of memory leaks when a program
+exits.
+
+Many objects have set and get API's to set attributes in the object.
+A C<set0> passes ownership from the caller to the object and a
+C<get0> returns a pointer but the attribute ownership
+remains with the object and a reference to it is returned.
+A C<set1> or C<get1> function does not change the ownership, but instead
+updates the attribute's reference count so that the object is shared
+between the caller and the object; the caller must free the returned
+attribute when finished.
+Functions that involve attributes that have reference counts themselves,
+but are named with just C<set> or C<get> are historical; and the documentation
+must state how the references are handled.
+Get methods are often thread-safe as long as the ownership requirements are
+met and shared objects are not modified.
+Set methods, or modifying shared objects, are generally not thread-safe
+as discussed below.
+
+Objects are thread-safe
+as long as the API's being invoked don't modify the object; in this
+case the parameter is usually marked in the API as C<const>.
+Not all parameters are marked this way.
+Note that a C<const> declaration does not mean immutable; for example
+L<X509_cmp(3)> takes pointers to C<const> objects, but the implementation
+uses a C cast to remove that so it can lock objects, generate and cache
+a DER encoding, and so on.
+
+Another instance of thread-safety is when updates to an object's
+internal state, such as cached values, are done with locks.
+One example of this is the reference counting API's described above.
+
+In all cases, however, it is generally not safe for one thread to
+mutate an object, such as setting elements of a private or public key,
+while another thread is using that object, such as verifying a signature.
+
+The same API's can usually be used simultaneously on different objects
+without interference.
+For example, two threads can calculate a signature using two different
+B<EVP_PKEY_CTX> objects.
+
+For implicit global state or singletons, thread-safety depends on the facility.
+The L<CRYPTO_secure_malloc(3)> and related API's have their own lock,
+while L<CRYPTO_malloc(3)> assumes the underlying platform allocation
+will do any necessary locking.
+Some API's, such as L<NCONF_load(3)> and related, or L<OBJ_create(3)>
+do no locking at all; this can be considered a bug.
+
+A separate, although related, issue is modifying "factory" objects
+when other objects have been created from that.
+For example, an B<SSL_CTX> object created by L<SSL_CTX_new(3)> is used
+to create per-connection B<SSL> objects by calling L<SSL_new(3)>.
+In this specific case, and probably for factory methods in general, it is
+not safe to modify the factory object after it has been used to create
+other objects.
+
+=head1 SEE ALSO
+
+CRYPTO_THREAD_run_once(3),
+local system threads documentation.
+
+=head1 BUGS
+
+This page is admittedly very incomplete.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/openssl_user_macros.pod.in b/doc/man7/openssl_user_macros.pod.in
new file mode 100644
index 000000000000..829fe69aeb40
--- /dev/null
+++ b/doc/man7/openssl_user_macros.pod.in
@@ -0,0 +1,102 @@
+=pod
+
+=head1 NAME
+
+openssl_user_macros, OPENSSL_API_COMPAT, OPENSSL_NO_DEPRECATED
+- User defined macros
+
+=head1 DESCRIPTION
+
+User defined macros allow the programmer to control certain aspects of
+what is exposed by the OpenSSL headers.
+
+B<NOTE:> to be effective, a user defined macro I<must be defined
+before including any header file that depends on it>, either in the
+compilation command (C<cc -DMACRO=value>) or by defining the macro in
+source before including any headers.
+
+Other manual pages may refer to this page when declarations depend on
+user defined macros.
+
+=head2 The macros
+
+=over 4
+
+=item B<OPENSSL_API_COMPAT>
+
+The value is a version number, given in one of the following two forms:
+
+=over 4
+
+=item C<0xMNNFF000L>
+
+This is the form supported for all versions up to 1.1.x, where C<M>
+represents the major number, C<NN> represents the minor number, and
+C<FF> represents the fix number, as a hexadecimal number. For version
+1.1.0, that's C<0x10100000L>.
+
+Any version number may be given, but these numbers are
+the current known major deprecation points, making them the most
+meaningful:
+
+=over 4
+
+=item C<0x00908000L> (version 0.9.8)
+
+=item C<0x10000000L> (version 1.0.0)
+
+=item C<0x10100000L> (version 1.1.0)
+
+=back
+
+For convenience, higher numbers are accepted as well, as long as
+feasible. For example, C<0x60000000L> will work as expected.
+However, it is recommended to start using the second form instead:
+
+=item C<mmnnpp>
+
+This form is a simple decimal number calculated with this formula:
+
+I<major> * 10000 + I<minor> * 100 + I<patch>
+
+where I<major>, I<minor> and I<patch> are the desired major,
+minor and patch components of the version number. For example:
+
+=over 4
+
+=item 30000 corresponds to version 3.0.0
+
+=item 10002 corresponds to version 1.0.2
+
+=item 420101 corresponds to version 42.1.1
+
+=back
+
+=back
+
+If B<OPENSSL_API_COMPAT> is undefined, this default value is used in its
+place:
+C<{- join('', map { my @x = split /=/,$_; $x[1] }
+ grep /^OPENSSL_CONFIGURED_API=/, @{$config{openssl_api_defines} // []})
+ || '0x00000000L'
+ -}>
+
+=item B<OPENSSL_NO_DEPRECATED>
+
+If this macro is defined, all deprecated public symbols in all OpenSSL
+versions up to and including the version given by B<OPENSSL_API_COMPAT>
+(or the default value given above, when B<OPENSSL_API_COMPAT> isn't defined)
+will be hidden.
+
+=back
+
+=head1 COPYRIGHT
+
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/ossl_store-file.pod b/doc/man7/ossl_store-file.pod
index 996043b0fb85..d4d163eabbe9 100644
--- a/doc/man7/ossl_store-file.pod
+++ b/doc/man7/ossl_store-file.pod
@@ -14,7 +14,7 @@ ossl_store-file - The store 'file' scheme loader
=head1 SYNOPSIS
-=for comment generic
+=for openssl generic
#include <openssl/store.h>
@@ -46,7 +46,7 @@ only).
=head1 NOTES
When needed, the 'file' scheme loader will require a pass phrase by
-using the C<UI_METHOD> that was passed via OSSL_STORE_open().
+using the B<UI_METHOD> that was passed via OSSL_STORE_open().
This pass phrase is expected to be UTF-8 encoded, anything else will
give an undefined result.
The files made accessible through this loader are expected to be
@@ -63,7 +63,7 @@ L<ossl_store(7)>, L<passphrase-encoding(7)>
Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man7/ossl_store.pod b/doc/man7/ossl_store.pod
index 19e15a65f82b..3152cff10424 100644
--- a/doc/man7/ossl_store.pod
+++ b/doc/man7/ossl_store.pod
@@ -6,7 +6,7 @@ ossl_store - Store retrieval functions
=head1 SYNOPSIS
-=for comment generic
+=for openssl generic
#include <openssl/store.h>
@@ -79,7 +79,7 @@ L<OSSL_STORE_SEARCH(3)>
Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man7/passphrase-encoding.pod b/doc/man7/passphrase-encoding.pod
index 19dcef9acc36..35a2545dda9e 100644
--- a/doc/man7/passphrase-encoding.pod
+++ b/doc/man7/passphrase-encoding.pod
@@ -105,7 +105,7 @@ Also note that the sub-sections below discuss human readable pass phrases.
This is particularly relevant for PKCS#12 objects, where human readable pass
phrases are assumed.
For other objects, it's as legitimate to use any byte sequence (such as a
-sequence of bytes from `/dev/urandom` that's been saved away), which makes any
+sequence of bytes from F</dev/urandom> that's been saved away), which makes any
character encoding discussion irrelevant; in such cases, simply use the same
byte sequence as it is.
@@ -116,7 +116,7 @@ encoded using UTF-8.
This is default on most modern Unixes, but may involve an effort on other
platforms.
Specifically for Windows, setting the environment variable
-C<OPENSSL_WIN32_UTF8> will have anything entered on [Windows] console prompt
+B<OPENSSL_WIN32_UTF8> will have anything entered on [Windows] console prompt
converted to UTF-8 (command line and separately prompted pass phrases alike).
=head2 Opening existing objects
@@ -170,9 +170,9 @@ L<d2i_PKCS8PrivateKey_bio(3)>
=head1 COPYRIGHT
-Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man7/property.pod b/doc/man7/property.pod
new file mode 100644
index 000000000000..eb0f6b176ccb
--- /dev/null
+++ b/doc/man7/property.pod
@@ -0,0 +1,177 @@
+=pod
+
+=head1 NAME
+
+property - Properties, a selection mechanism for algorithm implementations
+
+=head1 DESCRIPTION
+
+As of OpenSSL 3.0, a new method has been introduced to decide which of
+multiple implementations of an algorithm will be used.
+The method is centered around the concept of properties.
+Each implementation defines a number of properties and when an algorithm
+is being selected, filters based on these properties can be used to
+choose the most appropriate implementation of the algorithm.
+
+Properties are like variables, they are referenced by name and have a value
+assigned.
+
+=head2 Property Names
+
+Property names fall into two categories: those reserved by the OpenSSL
+project and user defined names.
+A I<reserved> property name consists of a single C-style identifier
+(except for leading underscores not being permitted), which begins
+with a letter and can be followed by any number of letters, numbers
+and underscores.
+Property names are case-insensitive, but OpenSSL will only use lowercase
+letters.
+
+A I<user defined> property name is similar, but it B<must> consist of
+two or more C-style identifiers, separated by periods.
+The last identifier in the name can be considered the 'true' property
+name, which is prefixed by some sort of 'namespace'.
+Providers for example could include their name in the prefix and use
+property names like
+
+ <provider_name>.<property_name>
+ <provider_name>.<algorithm_name>.<property_name>
+
+=head2 Properties
+
+A I<property> is a I<name=value> pair.
+A I<property definition> is a sequence of comma separated properties.
+There can be any number of properties in a definition, however each name must
+be unique.
+For example: "" defines an empty property definition (i.e., no restriction);
+"my.foo=bar" defines a property named I<my.foo> which has a string value I<bar>
+and "iteration.count=3" defines a property named I<iteration.count> which
+has a numeric value of I<3>.
+The full syntax for property definitions appears below.
+
+=head2 Implementations
+
+Each implementation of an algorithm can define any number of
+properties.
+For example, the default provider defines the property I<provider=default>
+for all of its algorithms.
+Likewise, OpenSSL's FIPS provider defines I<provider=fips> and the legacy
+provider defines I<provider=legacy> for all of their algorithms.
+
+=head2 Queries
+
+A I<property query clause> is a single conditional test.
+For example, "fips=yes", "provider!=default" or "?iteration.count=3".
+The first two represent mandatory clauses, such clauses B<must> match
+for any algorithm to even be under consideration.
+The third clause represents an optional clause.
+Matching such clauses is not a requirement, but any additional optional
+match counts in favor of the algorithm.
+More details about that in the B<Lookups> section.
+A I<property query> is a sequence of comma separated property query clauses.
+It is an error if a property name appears in more than one query clause.
+The full syntax for property queries appears below, but the available syntactic
+features are:
+
+=over 4
+
+=item *
+
+B<=> is an infix operator providing an equality test.
+
+=item *
+
+B<!=> is an infix operator providing an inequality test.
+
+=item *
+
+B<?> is a prefix operator that means that the following clause is optional
+but preferred.
+
+=item *
+
+B<-> is a prefix operator that means any global query clause involving the
+following property name should be ignored.
+
+=item *
+
+B<"..."> is a quoted string.
+The quotes are not included in the body of the string.
+
+=item *
+
+B<'...'> is a quoted string.
+The quotes are not included in the body of the string.
+
+=back
+
+=head2 Lookups
+
+When an algorithm is looked up, a property query is used to determine
+the best matching algorithm.
+All mandatory query clauses B<must> be present and the implementation
+that additionally has the largest number of matching optional query
+clauses will be used.
+If there is more than one such optimal candidate, the result will be
+chosen from amongst those in an indeterminate way.
+Ordering of optional clauses is not significant.
+
+=head2 Shortcut
+
+In order to permit a more concise expression of boolean properties, there
+is one short cut: a property name alone (e.g. "my.property") is
+exactly equivalent to "my.property=yes" in both definitions and queries.
+
+=head2 Global and Local
+
+Two levels of property query are supported.
+A context based property query that applies to all fetch operations and a local
+property query.
+Where both the context and local queries include a clause with the same name,
+the local clause overrides the context clause.
+
+It is possible for a local property query to remove a clause in the context
+property query by preceding the property name with a '-'.
+For example, a context property query that contains "fips=yes" would normally
+result in implementations that have "fips=yes".
+
+However, if the setting of the "fips" property is irrelevant to the
+operations being performed, the local property query can include the
+clause "-fips".
+Note that the local property query could not use "fips=no" because that would
+disallow any implementations with "fips=yes" rather than not caring about the
+setting.
+
+=head1 SYNTAX
+
+The lexical syntax in EBNF is given by:
+
+ Definition ::= PropertyName ( '=' Value )?
+ ( ',' PropertyName ( '=' Value )? )*
+ Query ::= PropertyQuery ( ',' PropertyQuery )*
+ PropertyQuery ::= '-' PropertyName
+ | '?'? ( PropertyName (( '=' | '!=' ) Value)?)
+ Value ::= NumberLiteral | StringLiteral
+ StringLiteral ::= QuotedString | UnquotedString
+ QuotedString ::= '"' [^"]* '"' | "'" [^']* "'"
+ UnquotedString ::= [A-Za-z] [^{space},]+
+ NumberLiteral ::= '0' ( [0-7]* | 'x' [0-9A-Fa-f]+ ) | '-'? [1-9] [0-9]+
+ PropertyName ::= [A-Za-z] [A-Za-z0-9_]* ( '.' [A-Za-z] [A-Za-z0-9_]* )*
+
+The flavour of EBNF being used is defined by:
+L<https://www.w3.org/TR/2010/REC-xquery-20101214/#EBNFNotation>.
+
+=head1 HISTORY
+
+Properties were added in OpenSSL 3.0
+
+=head1 COPYRIGHT
+
+Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider-asym_cipher.pod b/doc/man7/provider-asym_cipher.pod
new file mode 100644
index 000000000000..ac3f6271969d
--- /dev/null
+++ b/doc/man7/provider-asym_cipher.pod
@@ -0,0 +1,269 @@
+=pod
+
+=head1 NAME
+
+provider-asym_cipher - The asym_cipher library E<lt>-E<gt> provider functions
+
+=head1 SYNOPSIS
+
+=for openssl multiple includes
+
+ #include <openssl/core_dispatch.h>
+ #include <openssl/core_names.h>
+
+ /*
+ * None of these are actual functions, but are displayed like this for
+ * the function signatures for functions that are offered as function
+ * pointers in OSSL_DISPATCH arrays.
+ */
+
+ /* Context management */
+ void *OSSL_FUNC_asym_cipher_newctx(void *provctx);
+ void OSSL_FUNC_asym_cipher_freectx(void *ctx);
+ void *OSSL_FUNC_asym_cipher_dupctx(void *ctx);
+
+ /* Encryption */
+ int OSSL_FUNC_asym_cipher_encrypt_init(void *ctx, void *provkey,
+ const OSSL_PARAM params[]);
+ int OSSL_FUNC_asym_cipher_encrypt(void *ctx, unsigned char *out, size_t *outlen,
+ size_t outsize, const unsigned char *in,
+ size_t inlen);
+
+ /* Decryption */
+ int OSSL_FUNC_asym_cipher_decrypt_init(void *ctx, void *provkey,
+ const OSSL_PARAM params[]);
+ int OSSL_FUNC_asym_cipher_decrypt(void *ctx, unsigned char *out, size_t *outlen,
+ size_t outsize, const unsigned char *in,
+ size_t inlen);
+
+ /* Asymmetric Cipher parameters */
+ int OSSL_FUNC_asym_cipher_get_ctx_params(void *ctx, OSSL_PARAM params[]);
+ const OSSL_PARAM *OSSL_FUNC_asym_cipher_gettable_ctx_params(void *provctx);
+ int OSSL_FUNC_asym_cipher_set_ctx_params(void *ctx, const OSSL_PARAM params[]);
+ const OSSL_PARAM *OSSL_FUNC_asym_cipher_settable_ctx_params(void *provctx);
+
+=head1 DESCRIPTION
+
+This documentation is primarily aimed at provider authors. See L<provider(7)>
+for further information.
+
+The asymmetric cipher (OSSL_OP_ASYM_CIPHER) operation enables providers to
+implement asymmetric cipher algorithms and make them available to applications
+via the API functions L<EVP_PKEY_encrypt(3)>,
+L<EVP_PKEY_decrypt(3)> and
+other related functions).
+
+All "functions" mentioned here are passed as function pointers between
+F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
+L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
+provider_query_operation() function
+(see L<provider-base(7)/Provider Functions>).
+
+All these "functions" have a corresponding function type definition
+named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
+function pointer from an L<OSSL_DISPATCH(3)> element named
+B<OSSL_FUNC_{name}>.
+For example, the "function" OSSL_FUNC_asym_cipher_newctx() has these:
+
+ typedef void *(OSSL_FUNC_asym_cipher_newctx_fn)(void *provctx);
+ static ossl_inline OSSL_FUNC_asym_cipher_newctx_fn
+ OSSL_FUNC_asym_cipher_newctx(const OSSL_DISPATCH *opf);
+
+L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
+macros in L<openssl-core_dispatch.h(7)>, as follows:
+
+ OSSL_FUNC_asym_cipher_newctx OSSL_FUNC_ASYM_CIPHER_NEWCTX
+ OSSL_FUNC_asym_cipher_freectx OSSL_FUNC_ASYM_CIPHER_FREECTX
+ OSSL_FUNC_asym_cipher_dupctx OSSL_FUNC_ASYM_CIPHER_DUPCTX
+
+ OSSL_FUNC_asym_cipher_encrypt_init OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT
+ OSSL_FUNC_asym_cipher_encrypt OSSL_FUNC_ASYM_CIPHER_ENCRYPT
+
+ OSSL_FUNC_asym_cipher_decrypt_init OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT
+ OSSL_FUNC_asym_cipher_decrypt OSSL_FUNC_ASYM_CIPHER_DECRYPT
+
+ OSSL_FUNC_asym_cipher_get_ctx_params OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS
+ OSSL_FUNC_asym_cipher_gettable_ctx_params OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS
+ OSSL_FUNC_asym_cipher_set_ctx_params OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS
+ OSSL_FUNC_asym_cipher_settable_ctx_params OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS
+
+An asymmetric cipher algorithm implementation may not implement all of these
+functions.
+In order to be a consistent set of functions a provider must implement
+OSSL_FUNC_asym_cipher_newctx and OSSL_FUNC_asym_cipher_freectx.
+It must also implement both of OSSL_FUNC_asym_cipher_encrypt_init and
+OSSL_FUNC_asym_cipher_encrypt, or both of OSSL_FUNC_asym_cipher_decrypt_init and
+OSSL_FUNC_asym_cipher_decrypt.
+OSSL_FUNC_asym_cipher_get_ctx_params is optional but if it is present then so must
+OSSL_FUNC_asym_cipher_gettable_ctx_params.
+Similarly, OSSL_FUNC_asym_cipher_set_ctx_params is optional but if it is present then
+so must OSSL_FUNC_asym_cipher_settable_ctx_params.
+
+An asymmetric cipher algorithm must also implement some mechanism for generating,
+loading or importing keys via the key management (OSSL_OP_KEYMGMT) operation.
+See L<provider-keymgmt(7)> for further details.
+
+=head2 Context Management Functions
+
+OSSL_FUNC_asym_cipher_newctx() should create and return a pointer to a provider side
+structure for holding context information during an asymmetric cipher operation.
+A pointer to this context will be passed back in a number of the other
+asymmetric cipher operation function calls.
+The parameter I<provctx> is the provider context generated during provider
+initialisation (see L<provider(7)>).
+
+OSSL_FUNC_asym_cipher_freectx() is passed a pointer to the provider side asymmetric
+cipher context in the I<ctx> parameter.
+This function should free any resources associated with that context.
+
+OSSL_FUNC_asym_cipher_dupctx() should duplicate the provider side asymmetric cipher
+context in the I<ctx> parameter and return the duplicate copy.
+
+=head2 Encryption Functions
+
+OSSL_FUNC_asym_cipher_encrypt_init() initialises a context for an asymmetric encryption
+given a provider side asymmetric cipher context in the I<ctx> parameter, and a
+pointer to a provider key object in the I<provkey> parameter.
+The I<params>, if not NULL, should be set on the context in a manner similar to
+using OSSL_FUNC_asym_cipher_set_ctx_params().
+The key object should have been previously generated, loaded or imported into
+the provider using the key management (OSSL_OP_KEYMGMT) operation (see
+provider-keymgmt(7)>.
+OSSL_FUNC_asym_cipher_encrypt() performs the actual encryption itself.
+A previously initialised asymmetric cipher context is passed in the I<ctx>
+parameter.
+The data to be encrypted is pointed to by the I<in> parameter which is I<inlen>
+bytes long.
+Unless I<out> is NULL, the encrypted data should be written to the location
+pointed to by the I<out> parameter and it should not exceed I<outsize> bytes in
+length.
+The length of the encrypted data should be written to I<*outlen>.
+If I<out> is NULL then the maximum length of the encrypted data should be
+written to I<*outlen>.
+
+=head2 Decryption Functions
+
+OSSL_FUNC_asym_cipher_decrypt_init() initialises a context for an asymmetric decryption
+given a provider side asymmetric cipher context in the I<ctx> parameter, and a
+pointer to a provider key object in the I<provkey> parameter.
+The I<params>, if not NULL, should be set on the context in a manner similar to
+using OSSL_FUNC_asym_cipher_set_ctx_params().
+The key object should have been previously generated, loaded or imported into
+the provider using the key management (OSSL_OP_KEYMGMT) operation (see
+provider-keymgmt(7)>.
+
+OSSL_FUNC_asym_cipher_decrypt() performs the actual decryption itself.
+A previously initialised asymmetric cipher context is passed in the I<ctx>
+parameter.
+The data to be decrypted is pointed to by the I<in> parameter which is I<inlen>
+bytes long.
+Unless I<out> is NULL, the decrypted data should be written to the location
+pointed to by the I<out> parameter and it should not exceed I<outsize> bytes in
+length.
+The length of the decrypted data should be written to I<*outlen>.
+If I<out> is NULL then the maximum length of the decrypted data should be
+written to I<*outlen>.
+
+=head2 Asymmetric Cipher Parameters
+
+See L<OSSL_PARAM(3)> for further details on the parameters structure used by
+the OSSL_FUNC_asym_cipher_get_ctx_params() and OSSL_FUNC_asym_cipher_set_ctx_params()
+functions.
+
+OSSL_FUNC_asym_cipher_get_ctx_params() gets asymmetric cipher parameters associated
+with the given provider side asymmetric cipher context I<ctx> and stores them in
+I<params>.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_asym_cipher_set_ctx_params() sets the asymmetric cipher parameters associated
+with the given provider side asymmetric cipher context I<ctx> to I<params>.
+Any parameter settings are additional to any that were previously set.
+Passing NULL for I<params> should return true.
+
+Parameters currently recognised by built-in asymmetric cipher algorithms are as
+follows.
+Not all parameters are relevant to, or are understood by all asymmetric cipher
+algorithms:
+
+=over 4
+
+=item "pad-mode" (B<OSSL_ASYM_CIPHER_PARAM_PAD_MODE>) <UTF8 string> OR <integer>
+
+The type of padding to be used. The interpretation of this value will depend
+on the algorithm in use.
+
+=item "digest" (B<OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST>) <UTF8 string>
+
+Gets or sets the name of the OAEP digest algorithm used when OAEP padding is in
+use.
+
+=item "digest" (B<OSSL_ASYM_CIPHER_PARAM_DIGEST>) <UTF8 string>
+
+Gets or sets the name of the digest algorithm used by the algorithm (where
+applicable).
+
+=item "digest-props" (B<OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS>) <UTF8 string>
+
+Gets or sets the properties to use when fetching the OAEP digest algorithm.
+
+=item "digest-props" (B<OSSL_ASYM_CIPHER_PARAM_DIGEST_PROPS>) <UTF8 string>
+
+Gets or sets the properties to use when fetching the cipher digest algorithm.
+
+=item "mgf1-digest" (B<OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST>) <UTF8 string>
+
+Gets or sets the name of the MGF1 digest algorithm used when OAEP or PSS padding
+is in use.
+
+=item "mgf1-digest-props" (B<OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS>) <UTF8 string>
+
+Gets or sets the properties to use when fetching the MGF1 digest algorithm.
+
+=item "oaep-label" (B<OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL>) <octet string ptr>
+
+Gets the OAEP label used when OAEP padding is in use.
+
+=item "oaep-label" (B<OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL>) <octet string>
+
+Sets the OAEP label used when OAEP padding is in use.
+
+=item "tls-client-version" (B<OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION>) <unsigned integer>
+
+The TLS protocol version first requested by the client.
+
+=item "tls-negotiated-version" (B<OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION>) <unsigned integer>
+
+The negotiated TLS protocol version.
+
+=back
+
+OSSL_FUNC_asym_cipher_gettable_ctx_params() and OSSL_FUNC_asym_cipher_settable_ctx_params()
+get a constant L<OSSL_PARAM(3)> array that describes the gettable and settable
+parameters, i.e. parameters that can be used with OSSL_FUNC_asym_cipherget_ctx_params()
+and OSSL_FUNC_asym_cipher_set_ctx_params() respectively.
+
+=head1 RETURN VALUES
+
+OSSL_FUNC_asym_cipher_newctx() and OSSL_FUNC_asym_cipher_dupctx() should return the newly
+created provider side asymmetric cipher context, or NULL on failure.
+
+All other functions should return 1 for success or 0 on error.
+
+=head1 SEE ALSO
+
+L<provider(7)>
+
+=head1 HISTORY
+
+The provider ASYM_CIPHER interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider-base.pod b/doc/man7/provider-base.pod
new file mode 100644
index 000000000000..c587e0e529b6
--- /dev/null
+++ b/doc/man7/provider-base.pod
@@ -0,0 +1,819 @@
+=pod
+
+=head1 NAME
+
+provider-base
+- The basic OpenSSL library E<lt>-E<gt> provider functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/core_dispatch.h>
+
+ /*
+ * None of these are actual functions, but are displayed like this for
+ * the function signatures for functions that are offered as function
+ * pointers in OSSL_DISPATCH arrays.
+ */
+
+ /* Functions offered by libcrypto to the providers */
+ const OSSL_ITEM *core_gettable_params(const OSSL_CORE_HANDLE *handle);
+ int core_get_params(const OSSL_CORE_HANDLE *handle, OSSL_PARAM params[]);
+
+ typedef void (*OSSL_thread_stop_handler_fn)(void *arg);
+ int core_thread_start(const OSSL_CORE_HANDLE *handle,
+ OSSL_thread_stop_handler_fn handfn,
+ void *arg);
+
+ OPENSSL_CORE_CTX *core_get_libctx(const OSSL_CORE_HANDLE *handle);
+ void core_new_error(const OSSL_CORE_HANDLE *handle);
+ void core_set_error_debug(const OSSL_CORE_HANDLE *handle,
+ const char *file, int line, const char *func);
+ void core_vset_error(const OSSL_CORE_HANDLE *handle,
+ uint32_t reason, const char *fmt, va_list args);
+
+ int core_obj_add_sigid(const OSSL_CORE_HANDLE *prov, const char *sign_name,
+ const char *digest_name, const char *pkey_name);
+ int core_obj_create(const OSSL_CORE_HANDLE *handle, const char *oid,
+ const char *sn, const char *ln);
+
+ /*
+ * Some OpenSSL functionality is directly offered to providers via
+ * dispatch
+ */
+ void *CRYPTO_malloc(size_t num, const char *file, int line);
+ void *CRYPTO_zalloc(size_t num, const char *file, int line);
+ void CRYPTO_free(void *ptr, const char *file, int line);
+ void CRYPTO_clear_free(void *ptr, size_t num,
+ const char *file, int line);
+ void *CRYPTO_realloc(void *addr, size_t num,
+ const char *file, int line);
+ void *CRYPTO_clear_realloc(void *addr, size_t old_num, size_t num,
+ const char *file, int line);
+ void *CRYPTO_secure_malloc(size_t num, const char *file, int line);
+ void *CRYPTO_secure_zalloc(size_t num, const char *file, int line);
+ void CRYPTO_secure_free(void *ptr, const char *file, int line);
+ void CRYPTO_secure_clear_free(void *ptr, size_t num,
+ const char *file, int line);
+ int CRYPTO_secure_allocated(const void *ptr);
+ void OPENSSL_cleanse(void *ptr, size_t len);
+
+ unsigned char *OPENSSL_hexstr2buf(const char *str, long *buflen);
+
+ OSSL_CORE_BIO *BIO_new_file(const char *filename, const char *mode);
+ OSSL_CORE_BIO *BIO_new_membuf(const void *buf, int len);
+ int BIO_read_ex(OSSL_CORE_BIO *bio, void *data, size_t data_len,
+ size_t *bytes_read);
+ int BIO_write_ex(OSSL_CORE_BIO *bio, const void *data, size_t data_len,
+ size_t *written);
+ int BIO_up_ref(OSSL_CORE_BIO *bio);
+ int BIO_free(OSSL_CORE_BIO *bio);
+ int BIO_vprintf(OSSL_CORE_BIO *bio, const char *format, va_list args);
+ int BIO_vsnprintf(char *buf, size_t n, const char *fmt, va_list args);
+
+ void OSSL_SELF_TEST_set_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK *cb,
+ void *cbarg);
+
+ size_t get_entropy(const OSSL_CORE_HANDLE *handle,
+ unsigned char **pout, int entropy,
+ size_t min_len, size_t max_len);
+ void cleanup_entropy(const OSSL_CORE_HANDLE *handle,
+ unsigned char *buf, size_t len);
+ size_t get_nonce(const OSSL_CORE_HANDLE *handle,
+ unsigned char **pout, size_t min_len, size_t max_len,
+ const void *salt, size_t salt_len);
+ void cleanup_nonce(const OSSL_CORE_HANDLE *handle,
+ unsigned char *buf, size_t len);
+
+ /* Functions for querying the providers in the application library context */
+ int provider_register_child_cb(const OSSL_CORE_HANDLE *handle,
+ int (*create_cb)(const OSSL_CORE_HANDLE *provider,
+ void *cbdata),
+ int (*remove_cb)(const OSSL_CORE_HANDLE *provider,
+ void *cbdata),
+ int (*global_props_cb)(const char *props, void *cbdata),
+ void *cbdata);
+ void provider_deregister_child_cb(const OSSL_CORE_HANDLE *handle);
+ const char *provider_name(const OSSL_CORE_HANDLE *prov);
+ void *provider_get0_provider_ctx(const OSSL_CORE_HANDLE *prov);
+ const OSSL_DISPATCH *provider_get0_dispatch(const OSSL_CORE_HANDLE *prov);
+ int provider_up_ref(const OSSL_CORE_HANDLE *prov, int activate);
+ int provider_free(const OSSL_CORE_HANDLE *prov, int deactivate);
+
+ /* Functions offered by the provider to libcrypto */
+ void provider_teardown(void *provctx);
+ const OSSL_ITEM *provider_gettable_params(void *provctx);
+ int provider_get_params(void *provctx, OSSL_PARAM params[]);
+ const OSSL_ALGORITHM *provider_query_operation(void *provctx,
+ int operation_id,
+ const int *no_store);
+ void provider_unquery_operation(void *provctx, int operation_id,
+ const OSSL_ALGORITHM *algs);
+ const OSSL_ITEM *provider_get_reason_strings(void *provctx);
+ int provider_get_capabilities(void *provctx, const char *capability,
+ OSSL_CALLBACK *cb, void *arg);
+ int provider_self_test(void *provctx);
+
+=head1 DESCRIPTION
+
+All "functions" mentioned here are passed as function pointers between
+F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays, in the call
+of the provider initialization function. See L<provider(7)/Provider>
+for a description of the initialization function. They are known as "upcalls".
+
+All these "functions" have a corresponding function type definition
+named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
+function pointer from a L<OSSL_DISPATCH(3)> element named
+B<OSSL_FUNC_{name}>.
+For example, the "function" core_gettable_params() has these:
+
+ typedef OSSL_PARAM *
+ (OSSL_FUNC_core_gettable_params_fn)(const OSSL_CORE_HANDLE *handle);
+ static ossl_inline OSSL_NAME_core_gettable_params_fn
+ OSSL_FUNC_core_gettable_params(const OSSL_DISPATCH *opf);
+
+L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
+macros in L<openssl-core_dispatch.h(7)>, as follows:
+
+For I<in> (the L<OSSL_DISPATCH(3)> array passed from F<libcrypto> to the
+provider):
+
+ core_gettable_params OSSL_FUNC_CORE_GETTABLE_PARAMS
+ core_get_params OSSL_FUNC_CORE_GET_PARAMS
+ core_thread_start OSSL_FUNC_CORE_THREAD_START
+ core_get_libctx OSSL_FUNC_CORE_GET_LIBCTX
+ core_new_error OSSL_FUNC_CORE_NEW_ERROR
+ core_set_error_debug OSSL_FUNC_CORE_SET_ERROR_DEBUG
+ core_vset_error OSSL_FUNC_CORE_VSET_ERROR
+ core_obj_add_sigid OSSL_FUNC_CORE_OBJ_ADD_SIGID
+ core_obj_create OSSL_FUNC_CORE_OBJ_CREATE
+ CRYPTO_malloc OSSL_FUNC_CRYPTO_MALLOC
+ CRYPTO_zalloc OSSL_FUNC_CRYPTO_ZALLOC
+ CRYPTO_free OSSL_FUNC_CRYPTO_FREE
+ CRYPTO_clear_free OSSL_FUNC_CRYPTO_CLEAR_FREE
+ CRYPTO_realloc OSSL_FUNC_CRYPTO_REALLOC
+ CRYPTO_clear_realloc OSSL_FUNC_CRYPTO_CLEAR_REALLOC
+ CRYPTO_secure_malloc OSSL_FUNC_CRYPTO_SECURE_MALLOC
+ CRYPTO_secure_zalloc OSSL_FUNC_CRYPTO_SECURE_ZALLOC
+ CRYPTO_secure_free OSSL_FUNC_CRYPTO_SECURE_FREE
+ CRYPTO_secure_clear_free OSSL_FUNC_CRYPTO_SECURE_CLEAR_FREE
+ CRYPTO_secure_allocated OSSL_FUNC_CRYPTO_SECURE_ALLOCATED
+ BIO_new_file OSSL_FUNC_BIO_NEW_FILE
+ BIO_new_mem_buf OSSL_FUNC_BIO_NEW_MEMBUF
+ BIO_read_ex OSSL_FUNC_BIO_READ_EX
+ BIO_write_ex OSSL_FUNC_BIO_WRITE_EX
+ BIO_up_ref OSSL_FUNC_BIO_UP_REF
+ BIO_free OSSL_FUNC_BIO_FREE
+ BIO_vprintf OSSL_FUNC_BIO_VPRINTF
+ BIO_vsnprintf OSSL_FUNC_BIO_VSNPRINTF
+ BIO_puts OSSL_FUNC_BIO_PUTS
+ BIO_gets OSSL_FUNC_BIO_GETS
+ BIO_ctrl OSSL_FUNC_BIO_CTRL
+ OPENSSL_cleanse OSSL_FUNC_OPENSSL_CLEANSE
+ OSSL_SELF_TEST_set_callback OSSL_FUNC_SELF_TEST_CB
+ ossl_rand_get_entropy OSSL_FUNC_GET_ENTROPY
+ ossl_rand_cleanup_entropy OSSL_FUNC_CLEANUP_ENTROPY
+ ossl_rand_get_nonce OSSL_FUNC_GET_NONCE
+ ossl_rand_cleanup_nonce OSSL_FUNC_CLEANUP_NONCE
+ provider_register_child_cb OSSL_FUNC_PROVIDER_REGISTER_CHILD_CB
+ provider_deregister_child_cb OSSL_FUNC_PROVIDER_DEREGISTER_CHILD_CB
+ provider_name OSSL_FUNC_PROVIDER_NAME
+ provider_get0_provider_ctx OSSL_FUNC_PROVIDER_GET0_PROVIDER_CTX
+ provider_get0_dispatch OSSL_FUNC_PROVIDER_GET0_DISPATCH
+ provider_up_ref OSSL_FUNC_PROVIDER_UP_REF
+ provider_free OSSL_FUNC_PROVIDER_FREE
+
+For I<*out> (the L<OSSL_DISPATCH(3)> array passed from the provider to
+F<libcrypto>):
+
+ provider_teardown OSSL_FUNC_PROVIDER_TEARDOWN
+ provider_gettable_params OSSL_FUNC_PROVIDER_GETTABLE_PARAMS
+ provider_get_params OSSL_FUNC_PROVIDER_GET_PARAMS
+ provider_query_operation OSSL_FUNC_PROVIDER_QUERY_OPERATION
+ provider_unquery_operation OSSL_FUNC_PROVIDER_UNQUERY_OPERATION
+ provider_get_reason_strings OSSL_FUNC_PROVIDER_GET_REASON_STRINGS
+ provider_get_capabilities OSSL_FUNC_PROVIDER_GET_CAPABILITIES
+ provider_self_test OSSL_FUNC_PROVIDER_SELF_TEST
+
+=head2 Core functions
+
+core_gettable_params() returns a constant array of descriptor
+L<OSSL_PARAM(3)>, for parameters that core_get_params() can handle.
+
+core_get_params() retrieves parameters from the core for the given I<handle>.
+See L</Core parameters> below for a description of currently known
+parameters.
+
+The core_thread_start() function informs the core that the provider has stated
+an interest in the current thread. The core will inform the provider when the
+thread eventually stops. It must be passed the I<handle> for this provider, as
+well as a callback I<handfn> which will be called when the thread stops. The
+callback will subsequently be called, with the supplied argument I<arg>, from
+the thread that is stopping and gets passed the provider context as an
+argument. This may be useful to perform thread specific clean up such as
+freeing thread local variables.
+
+core_get_libctx() retrieves the core context in which the library
+object for the current provider is stored, accessible through the I<handle>.
+This function is useful only for built-in providers such as the default
+provider. Never cast this to OSSL_LIB_CTX in a provider that is not
+built-in as the OSSL_LIB_CTX of the library loading the provider might be
+a completely different structure than the OSSL_LIB_CTX of the library the
+provider is linked to. Use L<OSSL_LIB_CTX_new_child(3)> instead to obtain
+a proper library context that is linked to the application library context.
+
+core_new_error(), core_set_error_debug() and core_vset_error() are
+building blocks for reporting an error back to the core, with
+reference to the I<handle>.
+
+=over 4
+
+=item core_new_error()
+
+allocates a new thread specific error record.
+
+This corresponds to the OpenSSL function L<ERR_new(3)>.
+
+=item core_set_error_debug()
+
+sets debugging information in the current thread specific error
+record.
+The debugging information includes the name of the file I<file>, the
+line I<line> and the function name I<func> where the error occurred.
+
+This corresponds to the OpenSSL function L<ERR_set_debug(3)>.
+
+=item core_vset_error()
+
+sets the I<reason> for the error, along with any addition data.
+The I<reason> is a number defined by the provider and used to index
+the reason strings table that's returned by
+provider_get_reason_strings().
+The additional data is given as a format string I<fmt> and a set of
+arguments I<args>, which are treated in the same manner as with
+BIO_vsnprintf().
+I<file> and I<line> may also be passed to indicate exactly where the
+error occurred or was reported.
+
+This corresponds to the OpenSSL function L<ERR_vset_error(3)>.
+
+=back
+
+The core_obj_create() function registers a new OID and associated short name
+I<sn> and long name I<ln> for the given I<handle>. It is similar to the OpenSSL
+function L<OBJ_create(3)> except that it returns 1 on success or 0 on failure.
+It will treat as success the case where the OID already exists (even if the
+short name I<sn> or long name I<ln> provided as arguments differ from those
+associated with the existing OID, in which case the new names are not
+associated).
+This function is not thread safe.
+
+The core_obj_add_sigid() function registers a new composite signature algorithm
+(I<sign_name>) consisting of an underlying signature algorithm (I<pkey_name>)
+and digest algorithm (I<digest_name>) for the given I<handle>. It assumes that
+the OIDs for the composite signature algorithm as well as for the underlying
+signature and digest algorithms are either already known to OpenSSL or have been
+registered via a call to core_obj_create(). It corresponds to the OpenSSL
+function L<OBJ_add_sigid(3)>, except that the objects are identified by name
+rather than a numeric NID. Any name (OID, short name or long name) can be used
+to identify the object. It will treat as success the case where the composite
+signature algorithm already exists (even if registered against a different
+underlying signature or digest algorithm). For I<digest_name>, NULL or an
+empty string is permissible for signature algorithms that do not need a digest
+to operate correctly. The function returns 1 on success or 0 on failure.
+This function is not thread safe.
+
+CRYPTO_malloc(), CRYPTO_zalloc(), CRYPTO_free(), CRYPTO_clear_free(),
+CRYPTO_realloc(), CRYPTO_clear_realloc(), CRYPTO_secure_malloc(),
+CRYPTO_secure_zalloc(), CRYPTO_secure_free(),
+CRYPTO_secure_clear_free(), CRYPTO_secure_allocated(),
+BIO_new_file(), BIO_new_mem_buf(), BIO_read_ex(), BIO_write_ex(), BIO_up_ref(),
+BIO_free(), BIO_vprintf(), BIO_vsnprintf(), BIO_gets(), BIO_puts(),
+BIO_ctrl(), OPENSSL_cleanse() and
+OPENSSL_hexstr2buf() correspond exactly to the public functions with
+the same name. As a matter of fact, the pointers in the L<OSSL_DISPATCH(3)>
+array are typically direct pointers to those public functions. Note that the BIO
+functions take an B<OSSL_CORE_BIO> type rather than the standard B<BIO>
+type. This is to ensure that a provider does not mix BIOs from the core
+with BIOs used on the provider side (the two are not compatible).
+OSSL_SELF_TEST_set_callback() is used to set an optional callback that can be
+passed into a provider. This may be ignored by a provider.
+
+get_entropy() retrieves seeding material from the operating system.
+The seeding material will have at least I<entropy> bytes of randomness and the
+output will have at least I<min_len> and at most I<max_len> bytes.
+The buffer address is stored in I<*pout> and the buffer length is
+returned to the caller. On error, zero is returned.
+
+cleanup_entropy() is used to clean up and free the buffer returned by
+get_entropy(). The entropy pointer returned by get_entropy() is passed in
+B<buf> and its length in B<len>.
+
+get_nonce() retrieves a nonce using the passed I<salt> parameter
+of length I<salt_len> and operating system specific information.
+The I<salt> should contain uniquely identifying information and this is
+included, in an unspecified manner, as part of the output.
+The output is stored in a buffer which contrains at least I<min_len> and at
+most I<max_len> bytes. The buffer address is stored in I<*pout> and the
+buffer length returned to the caller. On error, zero is returned.
+
+cleanup_nonce() is used to clean up and free the buffer returned by
+get_nonce(). The nonce pointer returned by get_nonce() is passed in
+B<buf> and its length in B<len>.
+
+provider_register_child_cb() registers callbacks for being informed about the
+loading and unloading of providers in the application's library context.
+I<handle> is this provider's handle and I<cbdata> is this provider's data
+that will be passed back to the callbacks. It returns 1 on success or 0
+otherwise. These callbacks may be called while holding locks in libcrypto. In
+order to avoid deadlocks the callback implementation must not be long running
+and must not call other OpenSSL API functions or upcalls.
+
+I<create_cb> is a callback that will be called when a new provider is loaded
+into the application's library context. It is also called for any providers that
+are already loaded at the point that this callback is registered. The callback
+is passed the handle being used for the new provider being loadded and this
+provider's data in I<cbdata>. It should return 1 on success or 0 on failure.
+
+I<remove_cb> is a callback that will be called when a new provider is unloaded
+from the application's library context. It is passed the handle being used for
+the provider being unloaded and this provider's data in I<cbdata>. It should
+return 1 on success or 0 on failure.
+
+I<global_props_cb> is a callback that will be called when the global properties
+from the parent library context are changed. It should return 1 on success
+or 0 on failure.
+
+provider_deregister_child_cb() unregisters callbacks previously registered via
+provider_register_child_cb(). If provider_register_child_cb() has been called
+then provider_deregister_child_cb() should be called at or before the point that
+this provider's teardown function is called.
+
+provider_name() returns a string giving the name of the provider identified by
+I<handle>.
+
+provider_get0_provider_ctx() returns the provider context that is associated
+with the provider identified by I<prov>.
+
+provider_get0_dispatch() gets the dispatch table registered by the provider
+identified by I<prov> when it initialised.
+
+provider_up_ref() increments the reference count on the provider I<prov>. If
+I<activate> is nonzero then the provider is also loaded if it is not already
+loaded. It returns 1 on success or 0 on failure.
+
+provider_free() decrements the reference count on the provider I<prov>. If
+I<deactivate> is nonzero then the provider is also unloaded if it is not
+already loaded. It returns 1 on success or 0 on failure.
+
+=head2 Provider functions
+
+provider_teardown() is called when a provider is shut down and removed
+from the core's provider store.
+It must free the passed I<provctx>.
+
+provider_gettable_params() should return a constant array of
+descriptor L<OSSL_PARAM(3)>, for parameters that provider_get_params()
+can handle.
+
+provider_get_params() should process the L<OSSL_PARAM(3)> array
+I<params>, setting the values of the parameters it understands.
+
+provider_query_operation() should return a constant L<OSSL_ALGORITHM(3)>
+that corresponds to the given I<operation_id>.
+It should indicate if the core may store a reference to this array by
+setting I<*no_store> to 0 (core may store a reference) or 1 (core may
+not store a reference).
+
+provider_unquery_operation() informs the provider that the result of a
+provider_query_operation() is no longer directly required and that the function
+pointers have been copied. The I<operation_id> should match that passed to
+provider_query_operation() and I<algs> should be its return value.
+
+provider_get_reason_strings() should return a constant L<OSSL_ITEM(3)>
+array that provides reason strings for reason codes the provider may
+use when reporting errors using core_put_error().
+
+The provider_get_capabilities() function should call the callback I<cb> passing
+it a set of L<OSSL_PARAM(3)>s and the caller supplied argument I<arg>. The
+L<OSSL_PARAM(3)>s should provide details about the capability with the name given
+in the I<capability> argument relevant for the provider context I<provctx>. If a
+provider supports multiple capabilities with the given name then it may call the
+callback multiple times (one for each capability). Capabilities can be useful for
+describing the services that a provider can offer. For further details see the
+L</CAPABILITIES> section below. It should return 1 on success or 0 on error.
+
+The provider_self_test() function should perform known answer tests on a subset
+of the algorithms that it uses, and may also verify the integrity of the
+provider module. It should return 1 on success or 0 on error. It will return 1
+if this function is not used.
+
+None of these functions are mandatory, but a provider is fairly
+useless without at least provider_query_operation(), and
+provider_gettable_params() is fairly useless if not accompanied by
+provider_get_params().
+
+=head2 Provider parameters
+
+provider_get_params() can return the following provider parameters to the core:
+
+=over 4
+
+=item "name" (B<OSSL_PROV_PARAM_NAME>) <UTF8 ptr>
+
+This points to a string that should give a unique name for the provider.
+
+=item "version" (B<OSSL_PROV_PARAM_VERSION>) <UTF8 ptr>
+
+This points to a string that is a version number associated with this provider.
+OpenSSL in-built providers use OPENSSL_VERSION_STR, but this may be different
+for any third party provider. This string is for informational purposes only.
+
+=item "buildinfo" (B<OSSL_PROV_PARAM_BUILDINFO>) <UTF8 ptr>
+
+This points to a string that is a build information associated with this provider.
+OpenSSL in-built providers use OPENSSL_FULL_VERSION_STR, but this may be
+different for any third party provider.
+
+=item "status" (B<OSSL_PROV_PARAM_STATUS>) <unsigned integer>
+
+This returns 0 if the provider has entered an error state, otherwise it returns
+1.
+
+=back
+
+provider_gettable_params() should return the above parameters.
+
+
+=head2 Core parameters
+
+core_get_params() can retrieve the following core parameters for each provider:
+
+=over 4
+
+=item "openssl-version" (B<OSSL_PROV_PARAM_CORE_VERSION>) <UTF8 string ptr>
+
+This points to the OpenSSL libraries' full version string, i.e. the string
+expanded from the macro B<OPENSSL_VERSION_STR>.
+
+=item "provider-name" (B<OSSL_PROV_PARAM_CORE_PROV_NAME>) <UTF8 string ptr>
+
+This points to the OpenSSL libraries' idea of what the calling provider is named.
+
+=item "module-filename" (B<OSSL_PROV_PARAM_CORE_MODULE_FILENAME>) <UTF8 string ptr>
+
+This points to a string containing the full filename of the providers
+module file.
+
+=back
+
+Additionally, provider specific configuration parameters from the
+config file are available, in dotted name form.
+The dotted name form is a concatenation of section names and final
+config command name separated by periods.
+
+For example, let's say we have the following config example:
+
+ config_diagnostics = 1
+ openssl_conf = openssl_init
+
+ [openssl_init]
+ providers = providers_sect
+
+ [providers_sect]
+ foo = foo_sect
+
+ [foo_sect]
+ activate = 1
+ data1 = 2
+ data2 = str
+ more = foo_more
+
+ [foo_more]
+ data3 = foo,bar
+
+The provider will have these additional parameters available:
+
+=over 4
+
+=item "activate"
+
+pointing at the string "1"
+
+=item "data1"
+
+pointing at the string "2"
+
+=item "data2"
+
+pointing at the string "str"
+
+=item "more.data3"
+
+pointing at the string "foo,bar"
+
+=back
+
+For more information on handling parameters, see L<OSSL_PARAM(3)> as
+L<OSSL_PARAM_int(3)>.
+
+=head1 CAPABILITIES
+
+Capabilities describe some of the services that a provider can offer.
+Applications can query the capabilities to discover those services.
+
+=head3 "TLS-GROUP" Capability
+
+The "TLS-GROUP" capability can be queried by libssl to discover the list of
+TLS groups that a provider can support. Each group supported can be used for
+I<key exchange> (KEX) or I<key encapsulation method> (KEM) during a TLS
+handshake.
+TLS clients can advertise the list of TLS groups they support in the
+supported_groups extension, and TLS servers can select a group from the offered
+list that they also support. In this way a provider can add to the list of
+groups that libssl already supports with additional ones.
+
+Each TLS group that a provider supports should be described via the callback
+passed in through the provider_get_capabilities function. Each group should have
+the following details supplied (all are mandatory, except
+B<OSSL_CAPABILITY_TLS_GROUP_IS_KEM>):
+
+=over 4
+
+=item "tls-group-name" (B<OSSL_CAPABILITY_TLS_GROUP_NAME>) <UTF8 string>
+
+The name of the group as given in the IANA TLS Supported Groups registry
+L<https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8>.
+
+=item "tls-group-name-internal" (B<OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL>) <UTF8 string>
+
+The name of the group as known by the provider. This could be the same as the
+"tls-group-name", but does not have to be.
+
+=item "tls-group-id" (B<OSSL_CAPABILITY_TLS_GROUP_ID>) <unsigned integer>
+
+The TLS group id value as given in the IANA TLS Supported Groups registry.
+
+=item "tls-group-alg" (B<OSSL_CAPABILITY_TLS_GROUP_ALG>) <UTF8 string>
+
+The name of a Key Management algorithm that the provider offers and that should
+be used with this group. Keys created should be able to support I<key exchange>
+or I<key encapsulation method> (KEM), as implied by the optional
+B<OSSL_CAPABILITY_TLS_GROUP_IS_KEM> flag.
+The algorithm must support key and parameter generation as well as the
+key/parameter generation parameter, B<OSSL_PKEY_PARAM_GROUP_NAME>. The group
+name given via "tls-group-name-internal" above will be passed via
+B<OSSL_PKEY_PARAM_GROUP_NAME> when libssl wishes to generate keys/parameters.
+
+=item "tls-group-sec-bits" (B<OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS>) <unsigned integer>
+
+The number of bits of security offered by keys in this group. The number of bits
+should be comparable with the ones given in table 2 and 3 of the NIST SP800-57
+document.
+
+=item "tls-group-is-kem" (B<OSSL_CAPABILITY_TLS_GROUP_IS_KEM>) <unsigned integer>
+
+Boolean flag to describe if the group should be used in I<key exchange> (KEX)
+mode (0, default) or in I<key encapsulation method> (KEM) mode (1).
+
+This parameter is optional: if not specified, KEX mode is assumed as the default
+mode for the group.
+
+In KEX mode, in a typical Diffie-Hellman fashion, both sides execute I<keygen>
+then I<derive> against the peer public key. To operate in KEX mode, the group
+implementation must support the provider functions as described in
+L<provider-keyexch(7)>.
+
+In KEM mode, the client executes I<keygen> and sends its public key, the server
+executes I<encapsulate> using the client's public key and sends back the
+resulting I<ciphertext>, finally the client executes I<decapsulate> to retrieve
+the same I<shared secret> generated by the server's I<encapsulate>. To operate
+in KEM mode, the group implementation must support the provider functions as
+described in L<provider-kem(7)>.
+
+Both in KEX and KEM mode, the resulting I<shared secret> is then used according
+to the protocol specification.
+
+=item "tls-min-tls" (B<OSSL_CAPABILITY_TLS_GROUP_MIN_TLS>) <integer>
+
+=item "tls-max-tls" (B<OSSL_CAPABILITY_TLS_GROUP_MAX_TLS>) <integer>
+
+=item "tls-min-dtls" (B<OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS>) <integer>
+
+=item "tls-max-dtls" (B<OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS>) <integer>
+
+These parameters can be used to describe the minimum and maximum TLS and DTLS
+versions supported by the group. The values equate to the on-the-wire encoding
+of the various TLS versions. For example TLSv1.3 is 0x0304 (772 decimal), and
+TLSv1.2 is 0x0303 (771 decimal). A 0 indicates that there is no defined minimum
+or maximum. A -1 indicates that the group should not be used in that protocol.
+
+=back
+
+=head1 EXAMPLES
+
+This is an example of a simple provider made available as a
+dynamically loadable module.
+It implements the fictitious algorithm C<FOO> for the fictitious
+operation C<BAR>.
+
+ #include <malloc.h>
+ #include <openssl/core.h>
+ #include <openssl/core_dispatch.h>
+
+ /* Errors used in this provider */
+ #define E_MALLOC 1
+
+ static const OSSL_ITEM reasons[] = {
+ { E_MALLOC, "memory allocation failure" }.
+ { 0, NULL } /* Termination */
+ };
+
+ /*
+ * To ensure we get the function signature right, forward declare
+ * them using function types provided by openssl/core_dispatch.h
+ */
+ OSSL_FUNC_bar_newctx_fn foo_newctx;
+ OSSL_FUNC_bar_freectx_fn foo_freectx;
+ OSSL_FUNC_bar_init_fn foo_init;
+ OSSL_FUNC_bar_update_fn foo_update;
+ OSSL_FUNC_bar_final_fn foo_final;
+
+ OSSL_FUNC_provider_query_operation_fn p_query;
+ OSSL_FUNC_provider_get_reason_strings_fn p_reasons;
+ OSSL_FUNC_provider_teardown_fn p_teardown;
+
+ OSSL_provider_init_fn OSSL_provider_init;
+
+ OSSL_FUNC_core_put_error *c_put_error = NULL;
+
+ /* Provider context */
+ struct prov_ctx_st {
+ OSSL_CORE_HANDLE *handle;
+ }
+
+ /* operation context for the algorithm FOO */
+ struct foo_ctx_st {
+ struct prov_ctx_st *provctx;
+ int b;
+ };
+
+ static void *foo_newctx(void *provctx)
+ {
+ struct foo_ctx_st *fooctx = malloc(sizeof(*fooctx));
+
+ if (fooctx != NULL)
+ fooctx->provctx = provctx;
+ else
+ c_put_error(provctx->handle, E_MALLOC, __FILE__, __LINE__);
+ return fooctx;
+ }
+
+ static void foo_freectx(void *fooctx)
+ {
+ free(fooctx);
+ }
+
+ static int foo_init(void *vfooctx)
+ {
+ struct foo_ctx_st *fooctx = vfooctx;
+
+ fooctx->b = 0x33;
+ }
+
+ static int foo_update(void *vfooctx, unsigned char *in, size_t inl)
+ {
+ struct foo_ctx_st *fooctx = vfooctx;
+
+ /* did you expect something serious? */
+ if (inl == 0)
+ return 1;
+ for (; inl-- > 0; in++)
+ *in ^= fooctx->b;
+ return 1;
+ }
+
+ static int foo_final(void *vfooctx)
+ {
+ struct foo_ctx_st *fooctx = vfooctx;
+
+ fooctx->b = 0x66;
+ }
+
+ static const OSSL_DISPATCH foo_fns[] = {
+ { OSSL_FUNC_BAR_NEWCTX, (void (*)(void))foo_newctx },
+ { OSSL_FUNC_BAR_FREECTX, (void (*)(void))foo_freectx },
+ { OSSL_FUNC_BAR_INIT, (void (*)(void))foo_init },
+ { OSSL_FUNC_BAR_UPDATE, (void (*)(void))foo_update },
+ { OSSL_FUNC_BAR_FINAL, (void (*)(void))foo_final },
+ { 0, NULL }
+ };
+
+ static const OSSL_ALGORITHM bars[] = {
+ { "FOO", "provider=chumbawamba", foo_fns },
+ { NULL, NULL, NULL }
+ };
+
+ static const OSSL_ALGORITHM *p_query(void *provctx, int operation_id,
+ int *no_store)
+ {
+ switch (operation_id) {
+ case OSSL_OP_BAR:
+ return bars;
+ }
+ return NULL;
+ }
+
+ static const OSSL_ITEM *p_reasons(void *provctx)
+ {
+ return reasons;
+ }
+
+ static void p_teardown(void *provctx)
+ {
+ free(provctx);
+ }
+
+ static const OSSL_DISPATCH prov_fns[] = {
+ { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))p_teardown },
+ { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))p_query },
+ { OSSL_FUNC_PROVIDER_GET_REASON_STRINGS, (void (*)(void))p_reasons },
+ { 0, NULL }
+ };
+
+ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in,
+ const OSSL_DISPATCH **out,
+ void **provctx)
+ {
+ struct prov_ctx_st *pctx = NULL;
+
+ for (; in->function_id != 0; in++)
+ switch (in->function_id) {
+ case OSSL_FUNC_CORE_PUT_ERROR:
+ c_put_error = OSSL_FUNC_core_put_error(in);
+ break;
+ }
+
+ *out = prov_fns;
+
+ if ((pctx = malloc(sizeof(*pctx))) == NULL) {
+ /*
+ * ALEA IACTA EST, if the core retrieves the reason table
+ * regardless, that string will be displayed, otherwise not.
+ */
+ c_put_error(handle, E_MALLOC, __FILE__, __LINE__);
+ return 0;
+ }
+ pctx->handle = handle;
+ return 1;
+ }
+
+This relies on a few things existing in F<openssl/core_dispatch.h>:
+
+ #define OSSL_OP_BAR 4711
+
+ #define OSSL_FUNC_BAR_NEWCTX 1
+ typedef void *(OSSL_FUNC_bar_newctx_fn)(void *provctx);
+ static ossl_inline OSSL_FUNC_bar_newctx(const OSSL_DISPATCH *opf)
+ { return (OSSL_FUNC_bar_newctx_fn *)opf->function; }
+
+ #define OSSL_FUNC_BAR_FREECTX 2
+ typedef void (OSSL_FUNC_bar_freectx_fn)(void *ctx);
+ static ossl_inline OSSL_FUNC_bar_newctx(const OSSL_DISPATCH *opf)
+ { return (OSSL_FUNC_bar_freectx_fn *)opf->function; }
+
+ #define OSSL_FUNC_BAR_INIT 3
+ typedef void *(OSSL_FUNC_bar_init_fn)(void *ctx);
+ static ossl_inline OSSL_FUNC_bar_init(const OSSL_DISPATCH *opf)
+ { return (OSSL_FUNC_bar_init_fn *)opf->function; }
+
+ #define OSSL_FUNC_BAR_UPDATE 4
+ typedef void *(OSSL_FUNC_bar_update_fn)(void *ctx,
+ unsigned char *in, size_t inl);
+ static ossl_inline OSSL_FUNC_bar_update(const OSSL_DISPATCH *opf)
+ { return (OSSL_FUNC_bar_update_fn *)opf->function; }
+
+ #define OSSL_FUNC_BAR_FINAL 5
+ typedef void *(OSSL_FUNC_bar_final_fn)(void *ctx);
+ static ossl_inline OSSL_FUNC_bar_final(const OSSL_DISPATCH *opf)
+ { return (OSSL_FUNC_bar_final_fn *)opf->function; }
+
+=head1 SEE ALSO
+
+L<provider(7)>
+
+=head1 HISTORY
+
+The concept of providers and everything surrounding them was
+introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider-cipher.pod b/doc/man7/provider-cipher.pod
new file mode 100644
index 000000000000..1faf698107be
--- /dev/null
+++ b/doc/man7/provider-cipher.pod
@@ -0,0 +1,247 @@
+=pod
+
+=head1 NAME
+
+provider-cipher - The cipher library E<lt>-E<gt> provider functions
+
+=head1 SYNOPSIS
+
+=for openssl multiple includes
+
+ #include <openssl/core_dispatch.h>
+ #include <openssl/core_names.h>
+
+ /*
+ * None of these are actual functions, but are displayed like this for
+ * the function signatures for functions that are offered as function
+ * pointers in OSSL_DISPATCH arrays.
+ */
+
+ /* Context management */
+ void *OSSL_FUNC_cipher_newctx(void *provctx);
+ void OSSL_FUNC_cipher_freectx(void *cctx);
+ void *OSSL_FUNC_cipher_dupctx(void *cctx);
+
+ /* Encryption/decryption */
+ int OSSL_FUNC_cipher_encrypt_init(void *cctx, const unsigned char *key,
+ size_t keylen, const unsigned char *iv,
+ size_t ivlen, const OSSL_PARAM params[]);
+ int OSSL_FUNC_cipher_decrypt_init(void *cctx, const unsigned char *key,
+ size_t keylen, const unsigned char *iv,
+ size_t ivlen, const OSSL_PARAM params[]);
+ int OSSL_FUNC_cipher_update(void *cctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in, size_t inl);
+ int OSSL_FUNC_cipher_final(void *cctx, unsigned char *out, size_t *outl,
+ size_t outsize);
+ int OSSL_FUNC_cipher_cipher(void *cctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in, size_t inl);
+
+ /* Cipher parameter descriptors */
+ const OSSL_PARAM *OSSL_FUNC_cipher_gettable_params(void *provctx);
+
+ /* Cipher operation parameter descriptors */
+ const OSSL_PARAM *OSSL_FUNC_cipher_gettable_ctx_params(void *cctx,
+ void *provctx);
+ const OSSL_PARAM *OSSL_FUNC_cipher_settable_ctx_params(void *cctx,
+ void *provctx);
+
+ /* Cipher parameters */
+ int OSSL_FUNC_cipher_get_params(OSSL_PARAM params[]);
+
+ /* Cipher operation parameters */
+ int OSSL_FUNC_cipher_get_ctx_params(void *cctx, OSSL_PARAM params[]);
+ int OSSL_FUNC_cipher_set_ctx_params(void *cctx, const OSSL_PARAM params[]);
+
+=head1 DESCRIPTION
+
+This documentation is primarily aimed at provider authors. See L<provider(7)>
+for further information.
+
+The CIPHER operation enables providers to implement cipher algorithms and make
+them available to applications via the API functions L<EVP_EncryptInit_ex(3)>,
+L<EVP_EncryptUpdate(3)> and L<EVP_EncryptFinal(3)> (as well as the decrypt
+equivalents and other related functions).
+
+All "functions" mentioned here are passed as function pointers between
+F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
+L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
+provider_query_operation() function
+(see L<provider-base(7)/Provider Functions>).
+
+All these "functions" have a corresponding function type definition
+named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
+function pointer from an L<OSSL_DISPATCH(3)> element named
+B<OSSL_FUNC_{name}>.
+For example, the "function" OSSL_FUNC_cipher_newctx() has these:
+
+ typedef void *(OSSL_FUNC_cipher_newctx_fn)(void *provctx);
+ static ossl_inline OSSL_FUNC_cipher_newctx_fn
+ OSSL_FUNC_cipher_newctx(const OSSL_DISPATCH *opf);
+
+L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
+macros in L<openssl-core_dispatch.h(7)>, as follows:
+
+ OSSL_FUNC_cipher_newctx OSSL_FUNC_CIPHER_NEWCTX
+ OSSL_FUNC_cipher_freectx OSSL_FUNC_CIPHER_FREECTX
+ OSSL_FUNC_cipher_dupctx OSSL_FUNC_CIPHER_DUPCTX
+
+ OSSL_FUNC_cipher_encrypt_init OSSL_FUNC_CIPHER_ENCRYPT_INIT
+ OSSL_FUNC_cipher_decrypt_init OSSL_FUNC_CIPHER_DECRYPT_INIT
+ OSSL_FUNC_cipher_update OSSL_FUNC_CIPHER_UPDATE
+ OSSL_FUNC_cipher_final OSSL_FUNC_CIPHER_FINAL
+ OSSL_FUNC_cipher_cipher OSSL_FUNC_CIPHER_CIPHER
+
+ OSSL_FUNC_cipher_get_params OSSL_FUNC_CIPHER_GET_PARAMS
+ OSSL_FUNC_cipher_get_ctx_params OSSL_FUNC_CIPHER_GET_CTX_PARAMS
+ OSSL_FUNC_cipher_set_ctx_params OSSL_FUNC_CIPHER_SET_CTX_PARAMS
+
+ OSSL_FUNC_cipher_gettable_params OSSL_FUNC_CIPHER_GETTABLE_PARAMS
+ OSSL_FUNC_cipher_gettable_ctx_params OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS
+ OSSL_FUNC_cipher_settable_ctx_params OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS
+
+A cipher algorithm implementation may not implement all of these functions.
+In order to be a consistent set of functions there must at least be a complete
+set of "encrypt" functions, or a complete set of "decrypt" functions, or a
+single "cipher" function.
+In all cases both the OSSL_FUNC_cipher_newctx and OSSL_FUNC_cipher_freectx functions must be
+present.
+All other functions are optional.
+
+=head2 Context Management Functions
+
+OSSL_FUNC_cipher_newctx() should create and return a pointer to a provider side
+structure for holding context information during a cipher operation.
+A pointer to this context will be passed back in a number of the other cipher
+operation function calls.
+The parameter I<provctx> is the provider context generated during provider
+initialisation (see L<provider(7)>).
+
+OSSL_FUNC_cipher_freectx() is passed a pointer to the provider side cipher context in
+the I<cctx> parameter.
+This function should free any resources associated with that context.
+
+OSSL_FUNC_cipher_dupctx() should duplicate the provider side cipher context in the
+I<cctx> parameter and return the duplicate copy.
+
+=head2 Encryption/Decryption Functions
+
+OSSL_FUNC_cipher_encrypt_init() initialises a cipher operation for encryption given a
+newly created provider side cipher context in the I<cctx> parameter.
+The key to be used is given in I<key> which is I<keylen> bytes long.
+The IV to be used is given in I<iv> which is I<ivlen> bytes long.
+The I<params>, if not NULL, should be set on the context in a manner similar to
+using OSSL_FUNC_cipher_set_ctx_params().
+
+OSSL_FUNC_cipher_decrypt_init() is the same as OSSL_FUNC_cipher_encrypt_init() except that it
+initialises the context for a decryption operation.
+
+OSSL_FUNC_cipher_update() is called to supply data to be encrypted/decrypted as part of
+a previously initialised cipher operation.
+The I<cctx> parameter contains a pointer to a previously initialised provider
+side context.
+OSSL_FUNC_cipher_update() should encrypt/decrypt I<inl> bytes of data at the location
+pointed to by I<in>.
+The encrypted data should be stored in I<out> and the amount of data written to
+I<*outl> which should not exceed I<outsize> bytes.
+OSSL_FUNC_cipher_update() may be called multiple times for a single cipher operation.
+It is the responsibility of the cipher implementation to handle input lengths
+that are not multiples of the block length.
+In such cases a cipher implementation will typically cache partial blocks of
+input data until a complete block is obtained.
+I<out> may be the same location as I<in> but it should not partially overlap.
+The same expectations apply to I<outsize> as documented for
+L<EVP_EncryptUpdate(3)> and L<EVP_DecryptUpdate(3)>.
+
+OSSL_FUNC_cipher_final() completes an encryption or decryption started through previous
+OSSL_FUNC_cipher_encrypt_init() or OSSL_FUNC_cipher_decrypt_init(), and OSSL_FUNC_cipher_update()
+calls.
+The I<cctx> parameter contains a pointer to the provider side context.
+Any final encryption/decryption output should be written to I<out> and the
+amount of data written to I<*outl> which should not exceed I<outsize> bytes.
+The same expectations apply to I<outsize> as documented for
+L<EVP_EncryptFinal(3)> and L<EVP_DecryptFinal(3)>.
+
+OSSL_FUNC_cipher_cipher() performs encryption/decryption using the provider side cipher
+context in the I<cctx> parameter that should have been previously initialised via
+a call to OSSL_FUNC_cipher_encrypt_init() or OSSL_FUNC_cipher_decrypt_init().
+This should call the raw underlying cipher function without any padding.
+This will be invoked in the provider as a result of the application calling
+L<EVP_Cipher(3)>.
+The application is responsible for ensuring that the input is a multiple of the
+block length.
+The data to be encrypted/decrypted will be in I<in>, and it will be I<inl> bytes
+in length.
+The output from the encryption/decryption should be stored in I<out> and the
+amount of data stored should be put in I<*outl> which should be no more than
+I<outsize> bytes.
+
+=head2 Cipher Parameters
+
+See L<OSSL_PARAM(3)> for further details on the parameters structure used by
+these functions.
+
+OSSL_FUNC_cipher_get_params() gets details of the algorithm implementation
+and stores them in I<params>.
+
+OSSL_FUNC_cipher_set_ctx_params() sets cipher operation parameters for the
+provider side cipher context I<cctx> to I<params>.
+Any parameter settings are additional to any that were previously set.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_cipher_get_ctx_params() gets cipher operation details details from
+the given provider side cipher context I<cctx> and stores them in I<params>.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_cipher_gettable_params(), OSSL_FUNC_cipher_gettable_ctx_params(),
+and OSSL_FUNC_cipher_settable_ctx_params() all return constant L<OSSL_PARAM(3)>
+arrays as descriptors of the parameters that OSSL_FUNC_cipher_get_params(),
+OSSL_FUNC_cipher_get_ctx_params(), and OSSL_FUNC_cipher_set_ctx_params()
+can handle, respectively. OSSL_FUNC_cipher_gettable_ctx_params() and
+OSSL_FUNC_cipher_settable_ctx_params() will return the parameters associated
+with the provider side context I<cctx> in its current state if it is
+not NULL. Otherwise, they return the parameters associated with the
+provider side algorithm I<provctx>.
+
+Parameters currently recognised by built-in ciphers are listed in
+L<EVP_EncryptInit(3)/PARAMETERS>.
+Not all parameters are relevant to, or are understood by all ciphers.
+
+=head1 RETURN VALUES
+
+OSSL_FUNC_cipher_newctx() and OSSL_FUNC_cipher_dupctx() should return the newly created
+provider side cipher context, or NULL on failure.
+
+OSSL_FUNC_cipher_encrypt_init(), OSSL_FUNC_cipher_decrypt_init(), OSSL_FUNC_cipher_update(),
+OSSL_FUNC_cipher_final(), OSSL_FUNC_cipher_cipher(), OSSL_FUNC_cipher_get_params(),
+OSSL_FUNC_cipher_get_ctx_params() and OSSL_FUNC_cipher_set_ctx_params() should return 1 for
+success or 0 on error.
+
+OSSL_FUNC_cipher_gettable_params(), OSSL_FUNC_cipher_gettable_ctx_params() and
+OSSL_FUNC_cipher_settable_ctx_params() should return a constant L<OSSL_PARAM(3)>
+array, or NULL if none is offered.
+
+=head1 SEE ALSO
+
+L<provider(7)>, L<OSSL_PROVIDER-FIPS(7)>, L<OSSL_PROVIDER-default(7)>,
+L<OSSL_PROVIDER-legacy(7)>,
+L<EVP_CIPHER-AES(7)>, L<EVP_CIPHER-ARIA(7)>, L<EVP_CIPHER-BLOWFISH(7)>,
+L<EVP_CIPHER-CAMELLIA(7)>, L<EVP_CIPHER-CAST(7)>, L<EVP_CIPHER-CHACHA(7)>,
+L<EVP_CIPHER-DES(7)>, L<EVP_CIPHER-IDEA(7)>, L<EVP_CIPHER-RC2(7)>,
+L<EVP_CIPHER-RC4(7)>, L<EVP_CIPHER-RC5(7)>, L<EVP_CIPHER-SEED(7)>,
+L<EVP_CIPHER-SM4(7)>,
+L<life_cycle-cipher(7)>, L<EVP_EncryptInit(3)>
+
+=head1 HISTORY
+
+The provider CIPHER interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider-decoder.pod b/doc/man7/provider-decoder.pod
new file mode 100644
index 000000000000..f279955a6088
--- /dev/null
+++ b/doc/man7/provider-decoder.pod
@@ -0,0 +1,312 @@
+=pod
+
+=head1 NAME
+
+provider-decoder - The OSSL_DECODER library E<lt>-E<gt> provider functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/core_dispatch.h>
+
+ /*
+ * None of these are actual functions, but are displayed like this for
+ * the function signatures for functions that are offered as function
+ * pointers in OSSL_DISPATCH arrays.
+ */
+
+ /* Decoder parameter accessor and descriptor */
+ const OSSL_PARAM *OSSL_FUNC_decoder_gettable_params(void *provctx);
+ int OSSL_FUNC_decoder_get_params(OSSL_PARAM params[]);
+
+ /* Functions to construct / destruct / manipulate the decoder context */
+ void *OSSL_FUNC_decoder_newctx(void *provctx);
+ void OSSL_FUNC_decoder_freectx(void *ctx);
+ const OSSL_PARAM *OSSL_FUNC_decoder_settable_ctx_params(void *provctx);
+ int OSSL_FUNC_decoder_set_ctx_params(void *ctx, const OSSL_PARAM params[]);
+
+ /* Functions to check selection support */
+ int OSSL_FUNC_decoder_does_selection(void *provctx, int selection);
+
+ /* Functions to decode object data */
+ int OSSL_FUNC_decoder_decode(void *ctx, OSSL_CORE_BIO *in,
+ int selection,
+ OSSL_CALLBACK *data_cb, void *data_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg);
+
+ /* Functions to export a decoded object */
+ void *OSSL_FUNC_decoder_export_object(void *ctx,
+ const void *objref, size_t objref_sz,
+ OSSL_CALLBACK *export_cb,
+ void *export_cbarg);
+
+=head1 DESCRIPTION
+
+I<The term "decode" is used throughout this manual. This includes but is
+not limited to deserialization as individual decoders can also do
+decoding into intermediate data formats.>
+
+The DECODER operation is a generic method to create a provider-native
+object reference or intermediate decoded data from an encoded form
+read from the given B<OSSL_CORE_BIO>. If the caller wants to decode
+data from memory, it should provide a L<BIO_s_mem(3)> B<BIO>. The decoded
+data or object reference is passed along with eventual metadata
+to the I<metadata_cb> as L<OSSL_PARAM(3)> parameters.
+
+The decoder doesn't need to know more about the B<OSSL_CORE_BIO>
+pointer than being able to pass it to the appropriate BIO upcalls (see
+L<provider-base(7)/Core functions>).
+
+The DECODER implementation may be part of a chain, where data is
+passed from one to the next. For example, there may be an
+implementation to decode an object from PEM to DER, and another one
+that decodes DER to a provider-native object.
+
+The last decoding step in the decoding chain is usually supposed to create
+a provider-native object referenced by an object reference. To import
+that object into a different provider the OSSL_FUNC_decoder_export_object()
+can be called as the final step of the decoding process.
+
+All "functions" mentioned here are passed as function pointers between
+F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
+L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
+provider_query_operation() function
+(see L<provider-base(7)/Provider Functions>).
+
+All these "functions" have a corresponding function type definition
+named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
+function pointer from an L<OSSL_DISPATCH(3)> element named
+B<OSSL_FUNC_{name}>.
+For example, the "function" OSSL_FUNC_decoder_decode() has these:
+
+ typedef int
+ (OSSL_FUNC_decoder_decode_fn)(void *ctx, OSSL_CORE_BIO *in,
+ int selection,
+ OSSL_CALLBACK *data_cb, void *data_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg);
+ static ossl_inline OSSL_FUNC_decoder_decode_fn
+ OSSL_FUNC_decoder_decode(const OSSL_DISPATCH *opf);
+
+L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
+macros in L<openssl-core_dispatch.h(7)>, as follows:
+
+ OSSL_FUNC_decoder_get_params OSSL_FUNC_DECODER_GET_PARAMS
+ OSSL_FUNC_decoder_gettable_params OSSL_FUNC_DECODER_GETTABLE_PARAMS
+
+ OSSL_FUNC_decoder_newctx OSSL_FUNC_DECODER_NEWCTX
+ OSSL_FUNC_decoder_freectx OSSL_FUNC_DECODER_FREECTX
+ OSSL_FUNC_decoder_set_ctx_params OSSL_FUNC_DECODER_SET_CTX_PARAMS
+ OSSL_FUNC_decoder_settable_ctx_params OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS
+
+ OSSL_FUNC_decoder_does_selection OSSL_FUNC_DECODER_DOES_SELECTION
+
+ OSSL_FUNC_decoder_decode OSSL_FUNC_DECODER_DECODE
+
+ OSSL_FUNC_decoder_export_object OSSL_FUNC_DECODER_EXPORT_OBJECT
+
+=head2 Names and properties
+
+The name of an implementation should match the target type of object
+it decodes. For example, an implementation that decodes an RSA key
+should be named "RSA". Likewise, an implementation that decodes DER data
+from PEM input should be named "DER".
+
+Properties can be used to further specify details about an implementation:
+
+=over 4
+
+=item input
+
+This property is used to specify what format of input the implementation
+can decode.
+
+This property is I<mandatory>.
+
+OpenSSL providers recognize the following input types:
+
+=over 4
+
+=item pem
+
+An implementation with that input type decodes PEM formatted data.
+
+=item der
+
+An implementation with that input type decodes DER formatted data.
+
+=item msblob
+
+An implementation with that input type decodes MSBLOB formatted data.
+
+=item pvk
+
+An implementation with that input type decodes PVK formatted data.
+
+=back
+
+=item structure
+
+This property is used to specify the structure that the decoded data is
+expected to have.
+
+This property is I<optional>.
+
+Structures currently recognised by built-in decoders:
+
+=over 4
+
+=item "type-specific"
+
+Type specific structure.
+
+=item "pkcs8"
+
+Structure according to the PKCS#8 specification.
+
+=item "SubjectPublicKeyInfo"
+
+Encoding of public keys according to the Subject Public Key Info of RFC 5280.
+
+=back
+
+=back
+
+The possible values of both these properties is open ended. A provider may
+very well specify input types and structures that libcrypto doesn't know
+anything about.
+
+=head2 Subset selections
+
+Sometimes, an object has more than one subset of data that is interesting to
+treat separately or together. It's possible to specify what subsets are to
+be decoded, with a set of bits I<selection> that are passed in an B<int>.
+
+This set of bits depend entirely on what kind of provider-side object is
+to be decoded. For example, those bits are assumed to be the same as those
+used with L<provider-keymgmt(7)> (see L<provider-keymgmt(7)/Key Objects>) when
+the object is an asymmetric keypair - e.g., B<OSSL_KEYMGMT_SELECT_PRIVATE_KEY>
+if the object to be decoded is supposed to contain private key components.
+
+OSSL_FUNC_decoder_does_selection() should tell if a particular implementation
+supports any of the combinations given by I<selection>.
+
+=head2 Context functions
+
+OSSL_FUNC_decoder_newctx() returns a context to be used with the rest of
+the functions.
+
+OSSL_FUNC_decoder_freectx() frees the given I<ctx> as created by
+OSSL_FUNC_decoder_newctx().
+
+OSSL_FUNC_decoder_set_ctx_params() sets context data according to parameters
+from I<params> that it recognises. Unrecognised parameters should be
+ignored.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_decoder_settable_ctx_params() returns a constant L<OSSL_PARAM(3)>
+array describing the parameters that OSSL_FUNC_decoder_set_ctx_params()
+can handle.
+
+See L<OSSL_PARAM(3)> for further details on the parameters structure used by
+OSSL_FUNC_decoder_set_ctx_params() and OSSL_FUNC_decoder_settable_ctx_params().
+
+=head2 Export function
+
+When a provider-native object is created by a decoder it would be unsuitable
+for direct use with a foreign provider. The export function allows for
+exporting the object into that foreign provider if the foreign provider
+supports the type of the object and provides an import function.
+
+OSSL_FUNC_decoder_export_object() should export the object of size I<objref_sz>
+referenced by I<objref> as an L<OSSL_PARAM(3)> array and pass that into the
+I<export_cb> as well as the given I<export_cbarg>.
+
+=head2 Decoding functions
+
+OSSL_FUNC_decoder_decode() should decode the data as read from
+the B<OSSL_CORE_BIO> I<in> to produce decoded data or an object to be
+passed as reference in an L<OSSL_PARAM(3)> array along with possible other
+metadata that was decoded from the input. This L<OSSL_PARAM(3)> array is
+then passed to the I<data_cb> callback. The I<selection> bits,
+if relevant, should determine what the input data should contain.
+The decoding functions also take an L<OSSL_PASSPHRASE_CALLBACK(3)> function
+pointer along with a pointer to application data I<cbarg>, which should be
+used when a pass phrase prompt is needed.
+
+It's important to understand that the return value from this function is
+interpreted as follows:
+
+=over 4
+
+=item True (1)
+
+This means "carry on the decoding process", and is meaningful even though
+this function couldn't decode the input into anything, because there may be
+another decoder implementation that can decode it into something.
+
+The I<data_cb> callback should never be called when this function can't
+decode the input into anything.
+
+=item False (0)
+
+This means "stop the decoding process", and is meaningful when the input
+could be decoded into some sort of object that this function understands,
+but further treatment of that object results into errors that won't be
+possible for some other decoder implementation to get a different result.
+
+=back
+
+The conditions to stop the decoding process are at the discretion of the
+implementation.
+
+=head2 Decoder operation parameters
+
+There are currently no operation parameters currently recognised by the
+built-in decoders.
+
+Parameters currently recognised by the built-in pass phrase callback:
+
+=over 4
+
+=item "info" (B<OSSL_PASSPHRASE_PARAM_INFO>) <UTF8 string>
+
+A string of information that will become part of the pass phrase
+prompt. This could be used to give the user information on what kind
+of object it's being prompted for.
+
+=back
+
+=head1 RETURN VALUES
+
+OSSL_FUNC_decoder_newctx() returns a pointer to a context, or NULL on
+failure.
+
+OSSL_FUNC_decoder_set_ctx_params() returns 1, unless a recognised
+parameter was invalid or caused an error, for which 0 is returned.
+
+OSSL_FUNC_decoder_settable_ctx_params() returns a pointer to an array of
+constant L<OSSL_PARAM(3)> elements.
+
+OSSL_FUNC_decoder_does_selection() returns 1 if the decoder implementation
+supports any of the I<selection> bits, otherwise 0.
+
+OSSL_FUNC_decoder_decode() returns 1 to signal that the decoding process
+should continue, or 0 to signal that it should stop.
+
+=head1 SEE ALSO
+
+L<provider(7)>
+
+=head1 HISTORY
+
+The DECODER interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider-digest.pod b/doc/man7/provider-digest.pod
new file mode 100644
index 000000000000..c96dfe396676
--- /dev/null
+++ b/doc/man7/provider-digest.pod
@@ -0,0 +1,286 @@
+=pod
+
+=head1 NAME
+
+provider-digest - The digest library E<lt>-E<gt> provider functions
+
+=head1 SYNOPSIS
+
+=for openssl multiple includes
+
+ #include <openssl/core_dispatch.h>
+ #include <openssl/core_names.h>
+
+ /*
+ * Digests support the following function signatures in OSSL_DISPATCH arrays.
+ * (The function signatures are not actual functions).
+ */
+
+ /* Context management */
+ void *OSSL_FUNC_digest_newctx(void *provctx);
+ void OSSL_FUNC_digest_freectx(void *dctx);
+ void *OSSL_FUNC_digest_dupctx(void *dctx);
+
+ /* Digest generation */
+ int OSSL_FUNC_digest_init(void *dctx, const OSSL_PARAM params[]);
+ int OSSL_FUNC_digest_update(void *dctx, const unsigned char *in, size_t inl);
+ int OSSL_FUNC_digest_final(void *dctx, unsigned char *out, size_t *outl,
+ size_t outsz);
+ int OSSL_FUNC_digest_digest(void *provctx, const unsigned char *in, size_t inl,
+ unsigned char *out, size_t *outl, size_t outsz);
+
+ /* Digest parameter descriptors */
+ const OSSL_PARAM *OSSL_FUNC_digest_gettable_params(void *provctx);
+
+ /* Digest operation parameter descriptors */
+ const OSSL_PARAM *OSSL_FUNC_digest_gettable_ctx_params(void *dctx,
+ void *provctx);
+ const OSSL_PARAM *OSSL_FUNC_digest_settable_ctx_params(void *dctx,
+ void *provctx);
+
+ /* Digest parameters */
+ int OSSL_FUNC_digest_get_params(OSSL_PARAM params[]);
+
+ /* Digest operation parameters */
+ int OSSL_FUNC_digest_set_ctx_params(void *dctx, const OSSL_PARAM params[]);
+ int OSSL_FUNC_digest_get_ctx_params(void *dctx, OSSL_PARAM params[]);
+
+=head1 DESCRIPTION
+
+This documentation is primarily aimed at provider authors. See L<provider(7)>
+for further information.
+
+The DIGEST operation enables providers to implement digest algorithms and make
+them available to applications via the API functions L<EVP_DigestInit_ex(3)>,
+L<EVP_DigestUpdate(3)> and L<EVP_DigestFinal(3)> (and other related functions).
+
+All "functions" mentioned here are passed as function pointers between
+F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
+L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
+provider_query_operation() function
+(see L<provider-base(7)/Provider Functions>).
+
+All these "functions" have a corresponding function type definition
+named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
+function pointer from an L<OSSL_DISPATCH(3)> element named
+B<OSSL_FUNC_{name}>.
+For example, the "function" OSSL_FUNC_digest_newctx() has these:
+
+ typedef void *(OSSL_FUNC_digest_newctx_fn)(void *provctx);
+ static ossl_inline OSSL_FUNC_digest_newctx_fn
+ OSSL_FUNC_digest_newctx(const OSSL_DISPATCH *opf);
+
+L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
+macros in L<openssl-core_dispatch.h(7)>, as follows:
+
+ OSSL_FUNC_digest_newctx OSSL_FUNC_DIGEST_NEWCTX
+ OSSL_FUNC_digest_freectx OSSL_FUNC_DIGEST_FREECTX
+ OSSL_FUNC_digest_dupctx OSSL_FUNC_DIGEST_DUPCTX
+
+ OSSL_FUNC_digest_init OSSL_FUNC_DIGEST_INIT
+ OSSL_FUNC_digest_update OSSL_FUNC_DIGEST_UPDATE
+ OSSL_FUNC_digest_final OSSL_FUNC_DIGEST_FINAL
+ OSSL_FUNC_digest_digest OSSL_FUNC_DIGEST_DIGEST
+
+ OSSL_FUNC_digest_get_params OSSL_FUNC_DIGEST_GET_PARAMS
+ OSSL_FUNC_digest_get_ctx_params OSSL_FUNC_DIGEST_GET_CTX_PARAMS
+ OSSL_FUNC_digest_set_ctx_params OSSL_FUNC_DIGEST_SET_CTX_PARAMS
+
+ OSSL_FUNC_digest_gettable_params OSSL_FUNC_DIGEST_GETTABLE_PARAMS
+ OSSL_FUNC_digest_gettable_ctx_params OSSL_FUNC_DIGEST_GETTABLE_CTX_PARAMS
+ OSSL_FUNC_digest_settable_ctx_params OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS
+
+A digest algorithm implementation may not implement all of these functions.
+In order to be usable all or none of OSSL_FUNC_digest_newctx, OSSL_FUNC_digest_freectx,
+OSSL_FUNC_digest_init, OSSL_FUNC_digest_update and OSSL_FUNC_digest_final should be implemented.
+All other functions are optional.
+
+=head2 Context Management Functions
+
+OSSL_FUNC_digest_newctx() should create and return a pointer to a provider side
+structure for holding context information during a digest operation.
+A pointer to this context will be passed back in a number of the other digest
+operation function calls.
+The parameter I<provctx> is the provider context generated during provider
+initialisation (see L<provider(7)>).
+
+OSSL_FUNC_digest_freectx() is passed a pointer to the provider side digest context in
+the I<dctx> parameter.
+This function should free any resources associated with that context.
+
+OSSL_FUNC_digest_dupctx() should duplicate the provider side digest context in the
+I<dctx> parameter and return the duplicate copy.
+
+=head2 Digest Generation Functions
+
+OSSL_FUNC_digest_init() initialises a digest operation given a newly created
+provider side digest context in the I<dctx> parameter.
+The I<params>, if not NULL, should be set on the context in a manner similar to
+using OSSL_FUNC_digest_set_ctx_params().
+
+OSSL_FUNC_digest_update() is called to supply data to be digested as part of a
+previously initialised digest operation.
+The I<dctx> parameter contains a pointer to a previously initialised provider
+side context.
+OSSL_FUNC_digest_update() should digest I<inl> bytes of data at the location pointed to
+by I<in>.
+OSSL_FUNC_digest_update() may be called multiple times for a single digest operation.
+
+OSSL_FUNC_digest_final() generates a digest started through previous OSSL_FUNC_digest_init()
+and OSSL_FUNC_digest_update() calls.
+The I<dctx> parameter contains a pointer to the provider side context.
+The digest should be written to I<*out> and the length of the digest to
+I<*outl>.
+The digest should not exceed I<outsz> bytes.
+
+OSSL_FUNC_digest_digest() is a "oneshot" digest function.
+No provider side digest context is used.
+Instead the provider context that was created during provider initialisation is
+passed in the I<provctx> parameter (see L<provider(7)>).
+I<inl> bytes at I<in> should be digested and the result should be stored at
+I<out>. The length of the digest should be stored in I<*outl> which should not
+exceed I<outsz> bytes.
+
+=head2 Digest Parameters
+
+See L<OSSL_PARAM(3)> for further details on the parameters structure used by
+these functions.
+
+OSSL_FUNC_digest_get_params() gets details of the algorithm implementation
+and stores them in I<params>.
+
+OSSL_FUNC_digest_set_ctx_params() sets digest operation parameters for the
+provider side digest context I<dctx> to I<params>.
+Any parameter settings are additional to any that were previously set.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_digest_get_ctx_params() gets digest operation details details from
+the given provider side digest context I<dctx> and stores them in I<params>.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_digest_gettable_params() returns a constant L<OSSL_PARAM(3)> array
+containing descriptors of the parameters that OSSL_FUNC_digest_get_params()
+can handle.
+
+OSSL_FUNC_digest_gettable_ctx_params() and
+OSSL_FUNC_digest_settable_ctx_params() both return constant
+L<OSSL_PARAM(3)> arrays as descriptors of the parameters that
+OSSL_FUNC_digest_get_ctx_params() and OSSL_FUNC_digest_set_ctx_params()
+can handle, respectively. The array is based on the current state of
+the provider side context if I<dctx> is not NULL and on the provider
+side algorithm I<provctx> otherwise.
+
+Parameters currently recognised by built-in digests with this function
+are as follows. Not all parameters are relevant to, or are understood
+by all digests:
+
+=over 4
+
+=item "blocksize" (B<OSSL_DIGEST_PARAM_BLOCK_SIZE>) <unsigned integer>
+
+The digest block size.
+The length of the "blocksize" parameter should not exceed that of a B<size_t>.
+
+=item "size" (B<OSSL_DIGEST_PARAM_SIZE>) <unsigned integer>
+
+The digest output size.
+The length of the "size" parameter should not exceed that of a B<size_t>.
+
+=item "flags" (B<OSSL_DIGEST_PARAM_FLAGS>) <unsigned integer>
+
+Diverse flags that describe exceptional behaviour for the digest:
+
+=over 4
+
+=item B<EVP_MD_FLAG_ONESHOT>
+
+This digest method can only handle one block of input.
+
+=item B<EVP_MD_FLAG_XOF>
+
+This digest method is an extensible-output function (XOF) and supports
+setting the B<OSSL_DIGEST_PARAM_XOFLEN> parameter.
+
+=item B<EVP_MD_FLAG_DIGALGID_NULL>
+
+When setting up a DigestAlgorithmIdentifier, this flag will have the
+parameter set to NULL by default. Use this for PKCS#1. I<Note: if
+combined with EVP_MD_FLAG_DIGALGID_ABSENT, the latter will override.>
+
+=item B<EVP_MD_FLAG_DIGALGID_ABSENT>
+
+When setting up a DigestAlgorithmIdentifier, this flag will have the
+parameter be left absent by default. I<Note: if combined with
+EVP_MD_FLAG_DIGALGID_NULL, the latter will be overridden.>
+
+=item B<EVP_MD_FLAG_DIGALGID_CUSTOM>
+
+Custom DigestAlgorithmIdentifier handling via ctrl, with
+B<EVP_MD_FLAG_DIGALGID_ABSENT> as default. I<Note: if combined with
+EVP_MD_FLAG_DIGALGID_NULL, the latter will be overridden.>
+Currently unused.
+
+=back
+
+The length of the "flags" parameter should equal that of an
+B<unsigned long int>.
+
+=back
+
+=head2 Digest Context Parameters
+
+OSSL_FUNC_digest_set_ctx_params() sets digest parameters associated with the
+given provider side digest context I<dctx> to I<params>.
+Any parameter settings are additional to any that were previously set.
+See L<OSSL_PARAM(3)> for further details on the parameters structure.
+
+OSSL_FUNC_digest_get_ctx_params() gets details of currently set parameters
+values associated with the give provider side digest context I<dctx>
+and stores them in I<params>.
+See L<OSSL_PARAM(3)> for further details on the parameters structure.
+
+=head1 RETURN VALUES
+
+OSSL_FUNC_digest_newctx() and OSSL_FUNC_digest_dupctx() should return the newly created
+provider side digest context, or NULL on failure.
+
+OSSL_FUNC_digest_init(), OSSL_FUNC_digest_update(), OSSL_FUNC_digest_final(), OSSL_FUNC_digest_digest(),
+OSSL_FUNC_digest_set_params() and OSSL_FUNC_digest_get_params() should return 1 for success or
+0 on error.
+
+OSSL_FUNC_digest_size() should return the digest size.
+
+OSSL_FUNC_digest_block_size() should return the block size of the underlying digest
+algorithm.
+
+=head1 BUGS
+
+The EVP_Q_digest(), EVP_Digest() and EVP_DigestFinal_ex() API calls do not
+expect the digest size to be larger than EVP_MAX_MD_SIZE. Any algorithm which
+produces larger digests is unusable with those API calls.
+
+=head1 SEE ALSO
+
+L<provider(7)>, L<OSSL_PROVIDER-FIPS(7)>, L<OSSL_PROVIDER-default(7)>,
+L<OSSL_PROVIDER-legacy(7)>,
+L<EVP_MD-common(7)>, L<EVP_MD-BLAKE2(7)>, L<EVP_MD-MD2(7)>,
+L<EVP_MD-MD4(7)>, L<EVP_MD-MD5(7)>, L<EVP_MD-MD5-SHA1(7)>,
+L<EVP_MD-MDC2(7)>, L<EVP_MD-RIPEMD160(7)>, L<EVP_MD-SHA1(7)>,
+L<EVP_MD-SHA2(7)>, L<EVP_MD-SHA3(7)>, L<EVP_MD-SHAKE(7)>,
+L<EVP_MD-SM3(7)>, L<EVP_MD-WHIRLPOOL(7)>,
+L<life_cycle-digest(7)>, L<EVP_DigestInit(3)>
+
+=head1 HISTORY
+
+The provider DIGEST interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider-encoder.pod b/doc/man7/provider-encoder.pod
new file mode 100644
index 000000000000..f3e9ce5b1632
--- /dev/null
+++ b/doc/man7/provider-encoder.pod
@@ -0,0 +1,331 @@
+=pod
+
+=head1 NAME
+
+provider-encoder - The OSSL_ENCODER library E<lt>-E<gt> provider functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/core_dispatch.h>
+
+ /*
+ * None of these are actual functions, but are displayed like this for
+ * the function signatures for functions that are offered as function
+ * pointers in OSSL_DISPATCH arrays.
+ */
+
+ /* Encoder parameter accessor and descriptor */
+ const OSSL_PARAM *OSSL_FUNC_encoder_gettable_params(void *provctx);
+ int OSSL_FUNC_encoder_get_params(OSSL_PARAM params[]);
+
+ /* Functions to construct / destruct / manipulate the encoder context */
+ void *OSSL_FUNC_encoder_newctx(void *provctx);
+ void OSSL_FUNC_encoder_freectx(void *ctx);
+ int OSSL_FUNC_encoder_set_ctx_params(void *ctx, const OSSL_PARAM params[]);
+ const OSSL_PARAM *OSSL_FUNC_encoder_settable_ctx_params(void *provctx);
+
+ /* Functions to check selection support */
+ int OSSL_FUNC_encoder_does_selection(void *provctx, int selection);
+
+ /* Functions to encode object data */
+ int OSSL_FUNC_encoder_encode(void *ctx, OSSL_CORE_BIO *out,
+ const void *obj_raw,
+ const OSSL_PARAM obj_abstract[],
+ int selection,
+ OSSL_PASSPHRASE_CALLBACK *cb,
+ void *cbarg);
+
+ /* Functions to import and free a temporary object to be encoded */
+ void *OSSL_FUNC_encoder_import_object(void *ctx, int selection,
+ const OSSL_PARAM params[]);
+ void OSSL_FUNC_encoder_free_object(void *obj);
+
+
+=head1 DESCRIPTION
+
+I<We use the wide term "encode" in this manual. This includes but is
+not limited to serialization.>
+
+The ENCODER operation is a generic method to encode a provider-native
+object (I<obj_raw>) or an object abstraction (I<object_abstract>, see
+L<provider-object(7)>) into an encoded form, and write the result to
+the given OSSL_CORE_BIO. If the caller wants to get the encoded
+stream to memory, it should provide a L<BIO_s_mem(3)> B<BIO>.
+
+The encoder doesn't need to know more about the B<OSSL_CORE_BIO>
+pointer than being able to pass it to the appropriate BIO upcalls (see
+L<provider-base(7)/Core functions>).
+
+The ENCODER implementation may be part of a chain, where data is
+passed from one to the next. For example, there may be an
+implementation to encode an object to DER (that object is assumed to
+be provider-native and thereby passed via I<obj_raw>), and another one
+that encodes DER to PEM (that one would receive the DER encoding via
+I<obj_abstract>).
+
+=begin comment
+
+Having the DER encoding passed via I<obj_abstract> may seem
+complicated. However, there may be associated meta-data, such as the
+original data type, that need to be passed alongside it, and since
+L<provider-object(7)> already defines a way to pass such data,
+inventing another way to do it makes things even more complicated.
+
+=end comment
+
+The encoding using the L<OSSL_PARAM(3)> array form allows a
+encoder to be used for data that's been exported from another
+provider, and thereby allow them to exist independently of each
+other.
+
+The encoding using a provider side object can only be safely used
+with provider data coming from the same provider, for example keys
+with the L<KEYMGMT|provider-keymgmt(7)> provider.
+
+All "functions" mentioned here are passed as function pointers between
+F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
+L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
+provider_query_operation() function
+(see L<provider-base(7)/Provider Functions>).
+
+All these "functions" have a corresponding function type definition
+named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
+function pointer from an L<OSSL_DISPATCH(3)> element named
+B<OSSL_FUNC_{name}>.
+For example, the "function" OSSL_FUNC_encoder_encode() has these:
+
+ typedef int
+ (OSSL_FUNC_encoder_encode_fn)(void *ctx, OSSL_CORE_BIO *out,
+ const void *obj_raw,
+ const OSSL_PARAM obj_abstract[],
+ int selection,
+ OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg);
+ static ossl_inline OSSL_FUNC_encoder_encode_fn
+ OSSL_FUNC_encoder_encode(const OSSL_DISPATCH *opf);
+
+L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
+macros in L<openssl-core_dispatch.h(7)>, as follows:
+
+ OSSL_FUNC_encoder_get_params OSSL_FUNC_ENCODER_GET_PARAMS
+ OSSL_FUNC_encoder_gettable_params OSSL_FUNC_ENCODER_GETTABLE_PARAMS
+
+ OSSL_FUNC_encoder_newctx OSSL_FUNC_ENCODER_NEWCTX
+ OSSL_FUNC_encoder_freectx OSSL_FUNC_ENCODER_FREECTX
+ OSSL_FUNC_encoder_set_ctx_params OSSL_FUNC_ENCODER_SET_CTX_PARAMS
+ OSSL_FUNC_encoder_settable_ctx_params OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS
+
+ OSSL_FUNC_encoder_does_selection OSSL_FUNC_ENCODER_DOES_SELECTION
+
+ OSSL_FUNC_encoder_encode OSSL_FUNC_ENCODER_ENCODE
+
+ OSSL_FUNC_encoder_import_object OSSL_FUNC_ENCODER_IMPORT_OBJECT
+ OSSL_FUNC_encoder_free_object OSSL_FUNC_ENCODER_FREE_OBJECT
+
+=head2 Names and properties
+
+The name of an implementation should match the type of object it handles.
+For example, an implementation that encodes an RSA key should be named "RSA".
+Likewise, an implementation that further encodes DER should be named "DER".
+
+Properties can be used to further specify details about an implementation:
+
+=over 4
+
+=item output
+
+This property is used to specify what type of output the implementation
+produces.
+
+This property is I<mandatory>.
+
+OpenSSL providers recognize the following output types:
+
+=over 4
+
+=item text
+
+An implementation with that output type outputs human readable text, making
+that implementation suitable for C<-text> output in diverse L<openssl(1)>
+commands.
+
+=item pem
+
+An implementation with that output type outputs PEM formatted data.
+
+=item der
+
+An implementation with that output type outputs DER formatted data.
+
+=item msblob
+
+An implementation with that output type outputs MSBLOB formatted data.
+
+=item pvk
+
+An implementation with that output type outputs PVK formatted data.
+
+=back
+
+=item structure
+
+This property is used to specify the structure that is used for the encoded
+object. An example could be C<pkcs8>, to specify explicitly that an object
+(presumably an asymmetric key pair, in this case) will be wrapped in a
+PKCS#8 structure as part of the encoding.
+
+This property is I<optional>.
+
+=back
+
+The possible values of both these properties is open ended. A provider may
+very well specify output types and structures that libcrypto doesn't know
+anything about.
+
+=head2 Subset selections
+
+Sometimes, an object has more than one subset of data that is interesting to
+treat separately or together. It's possible to specify what subsets are to
+be encoded, with a set of bits I<selection> that are passed in an B<int>.
+
+This set of bits depend entirely on what kind of provider-side object is
+passed. For example, those bits are assumed to be the same as those used
+with L<provider-keymgmt(7)> (see L<provider-keymgmt(7)/Key Objects>) when
+the object is an asymmetric keypair.
+
+ENCODER implementations are free to regard the I<selection> as a set of
+hints, but must do so with care. In the end, the output must make sense,
+and if there's a corresponding decoder, the resulting decoded object must
+match the original object that was encoded.
+
+OSSL_FUNC_encoder_does_selection() should tell if a particular implementation
+supports any of the combinations given by I<selection>.
+
+=head2 Context functions
+
+OSSL_FUNC_encoder_newctx() returns a context to be used with the rest of
+the functions.
+
+OSSL_FUNC_encoder_freectx() frees the given I<ctx>, if it was created by
+OSSL_FUNC_encoder_newctx().
+
+OSSL_FUNC_encoder_set_ctx_params() sets context data according to parameters
+from I<params> that it recognises. Unrecognised parameters should be
+ignored.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_encoder_settable_ctx_params() returns a constant L<OSSL_PARAM(3)>
+array describing the parameters that OSSL_FUNC_encoder_set_ctx_params()
+can handle.
+
+See L<OSSL_PARAM(3)> for further details on the parameters structure used by
+OSSL_FUNC_encoder_set_ctx_params() and OSSL_FUNC_encoder_settable_ctx_params().
+
+=head2 Import functions
+
+A provider-native object may be associated with a foreign provider, and may
+therefore be unsuitable for direct use with a given ENCODER implementation.
+Provided that the foreign provider's implementation to handle the object has
+a function to export that object in L<OSSL_PARAM(3)> array form, the ENCODER
+implementation should be able to import that array and create a suitable
+object to be passed to OSSL_FUNC_encoder_encode()'s I<obj_raw>.
+
+OSSL_FUNC_encoder_import_object() should import the subset of I<params>
+given with I<selection> to create a provider-native object that can be
+passed as I<obj_raw> to OSSL_FUNC_encoder_encode().
+
+OSSL_FUNC_encoder_free_object() should free the object that was created with
+OSSL_FUNC_encoder_import_object().
+
+=head2 Encoding functions
+
+OSSL_FUNC_encoder_encode() should take a provider-native object (in
+I<obj_raw>) or an object abstraction (in I<obj_abstract>), and should output
+the object in encoded form to the B<OSSL_CORE_BIO>. The I<selection> bits,
+if relevant, should determine in greater detail what will be output.
+The encoding functions also take an L<OSSL_PASSPHRASE_CALLBACK(3)> function
+pointer along with a pointer to application data I<cbarg>, which should be
+used when a pass phrase prompt is needed.
+
+=head2 Encoder operation parameters
+
+Operation parameters currently recognised by built-in encoders are as
+follows:
+
+=over 4
+
+=item "cipher" (B<OSSL_ENCODER_PARAM_CIPHER>) <UTF8 string>
+
+The name of the encryption cipher to be used when generating encrypted
+encoding. This is used when encoding private keys, as well as
+other objects that need protection.
+
+If this name is invalid for the encoding implementation, the
+implementation should refuse to perform the encoding, i.e.
+OSSL_FUNC_encoder_encode_data() and OSSL_FUNC_encoder_encode_object()
+should return an error.
+
+=item "properties" (B<OSSL_ENCODER_PARAM_PROPERTIES>) <UTF8 string>
+
+The properties to be queried when trying to fetch the algorithm given
+with the "cipher" parameter.
+This must be given together with the "cipher" parameter to be
+considered valid.
+
+The encoding implementation isn't obligated to use this value.
+However, it is recommended that implementations that do not handle
+property strings return an error on receiving this parameter unless
+its value NULL or the empty string.
+
+=item "save-parameters" (B<OSSL_ENCODER_PARAM_SAVE_PARAMETERS>) <integer>
+
+If set to 0 disables saving of key domain parameters. Default is 1.
+It currently has an effect only on DSA keys.
+
+=back
+
+Parameters currently recognised by the built-in pass phrase callback:
+
+=over 4
+
+=item "info" (B<OSSL_PASSPHRASE_PARAM_INFO>) <UTF8 string>
+
+A string of information that will become part of the pass phrase
+prompt. This could be used to give the user information on what kind
+of object it's being prompted for.
+
+=back
+
+=head1 RETURN VALUES
+
+OSSL_FUNC_encoder_newctx() returns a pointer to a context, or NULL on
+failure.
+
+OSSL_FUNC_encoder_set_ctx_params() returns 1, unless a recognised
+parameter was invalid or caused an error, for which 0 is returned.
+
+OSSL_FUNC_encoder_settable_ctx_params() returns a pointer to an array of
+constant L<OSSL_PARAM(3)> elements.
+
+OSSL_FUNC_encoder_does_selection() returns 1 if the encoder implementation
+supports any of the I<selection> bits, otherwise 0.
+
+OSSL_FUNC_encoder_encode() returns 1 on success, or 0 on failure.
+
+=head1 SEE ALSO
+
+L<provider(7)>
+
+=head1 HISTORY
+
+The ENCODER interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider-kdf.pod b/doc/man7/provider-kdf.pod
new file mode 100644
index 000000000000..ad80869ebea7
--- /dev/null
+++ b/doc/man7/provider-kdf.pod
@@ -0,0 +1,359 @@
+=pod
+
+=head1 NAME
+
+provider-kdf - The KDF library E<lt>-E<gt> provider functions
+
+=head1 SYNOPSIS
+
+=for openssl multiple includes
+
+ #include <openssl/core_dispatch.h>
+ #include <openssl/core_names.h>
+
+ /*
+ * None of these are actual functions, but are displayed like this for
+ * the function signatures for functions that are offered as function
+ * pointers in OSSL_DISPATCH arrays.
+ */
+
+ /* Context management */
+ void *OSSL_FUNC_kdf_newctx(void *provctx);
+ void OSSL_FUNC_kdf_freectx(void *kctx);
+ void *OSSL_FUNC_kdf_dupctx(void *src);
+
+ /* Encryption/decryption */
+ int OSSL_FUNC_kdf_reset(void *kctx);
+ int OSSL_FUNC_kdf_derive(void *kctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[]);
+
+ /* KDF parameter descriptors */
+ const OSSL_PARAM *OSSL_FUNC_kdf_gettable_params(void *provctx);
+ const OSSL_PARAM *OSSL_FUNC_kdf_gettable_ctx_params(void *kcxt, void *provctx);
+ const OSSL_PARAM *OSSL_FUNC_kdf_settable_ctx_params(void *kcxt, void *provctx);
+
+ /* KDF parameters */
+ int OSSL_FUNC_kdf_get_params(OSSL_PARAM params[]);
+ int OSSL_FUNC_kdf_get_ctx_params(void *kctx, OSSL_PARAM params[]);
+ int OSSL_FUNC_kdf_set_ctx_params(void *kctx, const OSSL_PARAM params[]);
+
+=head1 DESCRIPTION
+
+This documentation is primarily aimed at provider authors. See L<provider(7)>
+for further information.
+
+The KDF operation enables providers to implement KDF algorithms and make
+them available to applications via the API functions L<EVP_KDF_CTX_reset(3)>,
+and L<EVP_KDF_derive(3)>.
+
+All "functions" mentioned here are passed as function pointers between
+F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
+L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
+provider_query_operation() function
+(see L<provider-base(7)/Provider Functions>).
+
+All these "functions" have a corresponding function type definition
+named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
+function pointer from an L<OSSL_DISPATCH(3)> element named
+B<OSSL_FUNC_{name}>.
+For example, the "function" OSSL_FUNC_kdf_newctx() has these:
+
+ typedef void *(OSSL_FUNC_kdf_newctx_fn)(void *provctx);
+ static ossl_inline OSSL_FUNC_kdf_newctx_fn
+ OSSL_FUNC_kdf_newctx(const OSSL_DISPATCH *opf);
+
+L<OSSL_DISPATCH(3)> array entries are identified by numbers that are provided as
+macros in L<openssl-core_dispatch.h(7)>, as follows:
+
+ OSSL_FUNC_kdf_newctx OSSL_FUNC_KDF_NEWCTX
+ OSSL_FUNC_kdf_freectx OSSL_FUNC_KDF_FREECTX
+ OSSL_FUNC_kdf_dupctx OSSL_FUNC_KDF_DUPCTX
+
+ OSSL_FUNC_kdf_reset OSSL_FUNC_KDF_RESET
+ OSSL_FUNC_kdf_derive OSSL_FUNC_KDF_DERIVE
+
+ OSSL_FUNC_kdf_get_params OSSL_FUNC_KDF_GET_PARAMS
+ OSSL_FUNC_kdf_get_ctx_params OSSL_FUNC_KDF_GET_CTX_PARAMS
+ OSSL_FUNC_kdf_set_ctx_params OSSL_FUNC_KDF_SET_CTX_PARAMS
+
+ OSSL_FUNC_kdf_gettable_params OSSL_FUNC_KDF_GETTABLE_PARAMS
+ OSSL_FUNC_kdf_gettable_ctx_params OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS
+ OSSL_FUNC_kdf_settable_ctx_params OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS
+
+A KDF algorithm implementation may not implement all of these functions.
+In order to be a consistent set of functions, at least the following functions
+must be implemented: OSSL_FUNC_kdf_newctx(), OSSL_FUNC_kdf_freectx(),
+OSSL_FUNC_kdf_set_ctx_params(), OSSL_FUNC_kdf_derive().
+All other functions are optional.
+
+=head2 Context Management Functions
+
+OSSL_FUNC_kdf_newctx() should create and return a pointer to a provider side
+structure for holding context information during a KDF operation.
+A pointer to this context will be passed back in a number of the other KDF
+operation function calls.
+The parameter I<provctx> is the provider context generated during provider
+initialisation (see L<provider(7)>).
+
+OSSL_FUNC_kdf_freectx() is passed a pointer to the provider side KDF context in
+the I<kctx> parameter.
+If it receives NULL as I<kctx> value, it should not do anything other than
+return.
+This function should free any resources associated with that context.
+
+OSSL_FUNC_kdf_dupctx() should duplicate the provider side KDF context in the
+I<kctx> parameter and return the duplicate copy.
+
+=head2 Encryption/Decryption Functions
+
+OSSL_FUNC_kdf_reset() initialises a KDF operation given a provider
+side KDF context in the I<kctx> parameter.
+
+OSSL_FUNC_kdf_derive() performs the KDF operation after processing the
+I<params> as per OSSL_FUNC_kdf_set_ctx_params().
+The I<kctx> parameter contains a pointer to the provider side context.
+The resulting key of the desired I<keylen> should be written to I<key>.
+If the algorithm does not support the requested I<keylen> the function must
+return error.
+
+=head2 KDF Parameters
+
+See L<OSSL_PARAM(3)> for further details on the parameters structure used by
+these functions.
+
+OSSL_FUNC_kdf_get_params() gets details of parameter values associated with the
+provider algorithm and stores them in I<params>.
+
+OSSL_FUNC_kdf_set_ctx_params() sets KDF parameters associated with the given
+provider side KDF context I<kctx> to I<params>.
+Any parameter settings are additional to any that were previously set.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_kdf_get_ctx_params() retrieves gettable parameter values associated
+with the given provider side KDF context I<kctx> and stores them in I<params>.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_kdf_gettable_params(), OSSL_FUNC_kdf_gettable_ctx_params(),
+and OSSL_FUNC_kdf_settable_ctx_params() all return constant L<OSSL_PARAM(3)>
+arrays as descriptors of the parameters that OSSL_FUNC_kdf_get_params(),
+OSSL_FUNC_kdf_get_ctx_params(), and OSSL_FUNC_kdf_set_ctx_params()
+can handle, respectively. OSSL_FUNC_kdf_gettable_ctx_params() and
+OSSL_FUNC_kdf_settable_ctx_params() will return the parameters associated
+with the provider side context I<kctx> in its current state if it is
+not NULL. Otherwise, they return the parameters associated with the
+provider side algorithm I<provctx>.
+
+
+Parameters currently recognised by built-in KDFs are as follows. Not all
+parameters are relevant to, or are understood by all KDFs:
+
+=over 4
+
+=item "size" (B<OSSL_KDF_PARAM_SIZE>) <unsigned integer>
+
+Gets the output size from the associated KDF ctx.
+If the algorithm produces a variable amount of output, SIZE_MAX should be
+returned.
+If the input parameters required to calculate the fixed output size have not yet
+been supplied, 0 should be returned indicating an error.
+
+=item "key" (B<OSSL_KDF_PARAM_KEY>) <octet string>
+
+Sets the key in the associated KDF ctx.
+
+=item "secret" (B<OSSL_KDF_PARAM_SECRET>) <octet string>
+
+Sets the secret in the associated KDF ctx.
+
+=item "pass" (B<OSSL_KDF_PARAM_PASSWORD>) <octet string>
+
+Sets the password in the associated KDF ctx.
+
+=item "cipher" (B<OSSL_KDF_PARAM_CIPHER>) <UTF8 string>
+
+=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
+
+=item "mac" (B<OSSL_KDF_PARAM_MAC>) <UTF8 string>
+
+Sets the name of the underlying cipher, digest or MAC to be used.
+It must name a suitable algorithm for the KDF that's being used.
+
+=item "maclen" (B<OSSL_KDF_PARAM_MAC_SIZE>) <octet string>
+
+Sets the length of the MAC in the associated KDF ctx.
+
+=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
+
+Sets the properties to be queried when trying to fetch the underlying algorithm.
+This must be given together with the algorithm naming parameter to be
+considered valid.
+
+=item "iter" (B<OSSL_KDF_PARAM_ITER>) <unsigned integer>
+
+Sets the number of iterations in the associated KDF ctx.
+
+=item "mode" (B<OSSL_KDF_PARAM_MODE>) <UTF8 string>
+
+Sets the mode in the associated KDF ctx.
+
+=item "pkcs5" (B<OSSL_KDF_PARAM_PKCS5>) <integer>
+
+Enables or diables the SP800-132 compliance checks.
+A mode of 0 enables the compliance checks.
+
+The checks performed are:
+
+=over 4
+
+=item - the iteration count is at least 1000.
+
+=item - the salt length is at least 128 bits.
+
+=item - the derived key length is at least 112 bits.
+
+=back
+
+=item "ukm" (B<OSSL_KDF_PARAM_UKM>) <octet string>
+
+Sets an optional random string that is provided by the sender called
+"partyAInfo". In CMS this is the user keying material.
+
+
+=item "cekalg" (B<OSSL_KDF_PARAM_CEK_ALG>) <UTF8 string>
+
+Sets the CEK wrapping algorithm name in the associated KDF ctx.
+
+=item "n" (B<OSSL_KDF_PARAM_SCRYPT_N>) <unsigned integer>
+
+Sets the scrypt work factor parameter N in the associated KDF ctx.
+
+=item "r" (B<OSSL_KDF_PARAM_SCRYPT_R>) <unsigned integer>
+
+Sets the scrypt work factor parameter r in the associated KDF ctx.
+
+=item "p" (B<OSSL_KDF_PARAM_SCRYPT_P>) <unsigned integer>
+
+Sets the scrypt work factor parameter p in the associated KDF ctx.
+
+=item "maxmem_bytes" (B<OSSL_KDF_PARAM_SCRYPT_MAXMEM>) <unsigned integer>
+
+Sets the scrypt work factor parameter maxmem in the associated KDF ctx.
+
+=item "prefix" (B<OSSL_KDF_PARAM_PREFIX>) <octet string>
+
+Sets the prefix string using by the TLS 1.3 version of HKDF in the
+associated KDF ctx.
+
+=item "label" (B<OSSL_KDF_PARAM_LABEL>) <octet string>
+
+Sets the label string using by the TLS 1.3 version of HKDF in the
+associated KDF ctx.
+
+=item "data" (B<OSSL_KDF_PARAM_DATA>) <octet string>
+
+Sets the context string using by the TLS 1.3 version of HKDF in the
+associated KDF ctx.
+
+=item "info" (B<OSSL_KDF_PARAM_INFO>) <octet string>
+
+Sets the optional shared info in the associated KDF ctx.
+
+=item "seed" (B<OSSL_KDF_PARAM_SEED>) <octet string>
+
+Sets the IV in the associated KDF ctx.
+
+=item "xcghash" (B<OSSL_KDF_PARAM_SSHKDF_XCGHASH>) <octet string>
+
+Sets the xcghash in the associated KDF ctx.
+
+=item "session_id" (B<OSSL_KDF_PARAM_SSHKDF_SESSION_ID>) <octet string>
+
+Sets the session ID in the associated KDF ctx.
+
+=item "type" (B<OSSL_KDF_PARAM_SSHKDF_TYPE>) <UTF8 string>
+
+Sets the SSH KDF type parameter in the associated KDF ctx.
+There are six supported types:
+
+=over 4
+
+=item EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV
+
+The Initial IV from client to server.
+A single char of value 65 (ASCII char 'A').
+
+=item EVP_KDF_SSHKDF_TYPE_INITIAL_IV_SRV_TO_CLI
+
+The Initial IV from server to client
+A single char of value 66 (ASCII char 'B').
+
+=item EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_CLI_TO_SRV
+
+The Encryption Key from client to server
+A single char of value 67 (ASCII char 'C').
+
+=item EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_SRV_TO_CLI
+
+The Encryption Key from server to client
+A single char of value 68 (ASCII char 'D').
+
+=item EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_CLI_TO_SRV
+
+The Integrity Key from client to server
+A single char of value 69 (ASCII char 'E').
+
+=item EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_SRV_TO_CLI
+
+The Integrity Key from client to server
+A single char of value 70 (ASCII char 'F').
+
+=back
+
+=item "constant" (B<OSSL_KDF_PARAM_CONSTANT>) <octet string>
+
+Sets the constant value in the associated KDF ctx.
+
+=item "id" (B<OSSL_KDF_PARAM_PKCS12_ID>) <integer>
+
+Sets the intended usage of the output bits in the associated KDF ctx.
+It is defined as per RFC 7292 section B.3.
+
+=back
+
+=head1 RETURN VALUES
+
+OSSL_FUNC_kdf_newctx() and OSSL_FUNC_kdf_dupctx() should return the newly created
+provider side KDF context, or NULL on failure.
+
+OSSL_FUNC_kdf_derive(), OSSL_FUNC_kdf_get_params(),
+OSSL_FUNC_kdf_get_ctx_params() and OSSL_FUNC_kdf_set_ctx_params() should return 1 for
+success or 0 on error.
+
+OSSL_FUNC_kdf_gettable_params(), OSSL_FUNC_kdf_gettable_ctx_params() and
+OSSL_FUNC_kdf_settable_ctx_params() should return a constant L<OSSL_PARAM(3)>
+array, or NULL if none is offered.
+
+=head1 NOTES
+
+The KDF life-cycle is described in L<life_cycle-kdf(7)>. Providers should
+ensure that the various transitions listed there are supported. At some point
+the EVP layer will begin enforcing the listed transitions.
+
+=head1 SEE ALSO
+
+L<provider(7)>, L<life_cycle-kdf(7)>, L<EVP_KDF(3)>.
+
+=head1 HISTORY
+
+The provider KDF interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider-kem.pod b/doc/man7/provider-kem.pod
new file mode 100644
index 000000000000..8436a7f25e3f
--- /dev/null
+++ b/doc/man7/provider-kem.pod
@@ -0,0 +1,212 @@
+=pod
+
+=head1 NAME
+
+provider-kem - The kem library E<lt>-E<gt> provider functions
+
+=head1 SYNOPSIS
+
+=for openssl multiple includes
+
+ #include <openssl/core_dispatch.h>
+ #include <openssl/core_names.h>
+
+ /*
+ * None of these are actual functions, but are displayed like this for
+ * the function signatures for functions that are offered as function
+ * pointers in OSSL_DISPATCH arrays.
+ */
+
+ /* Context management */
+ void *OSSL_FUNC_kem_newctx(void *provctx);
+ void OSSL_FUNC_kem_freectx(void *ctx);
+ void *OSSL_FUNC_kem_dupctx(void *ctx);
+
+ /* Encapsulation */
+ int OSSL_FUNC_kem_encapsulate_init(void *ctx, void *provkey, const char *name,
+ const OSSL_PARAM params[]);
+ int OSSL_FUNC_kem_encapsulate(void *ctx, unsigned char *out, size_t *outlen,
+ unsigned char *secret, size_t *secretlen);
+
+ /* Decapsulation */
+ int OSSL_FUNC_kem_decapsulate_init(void *ctx, void *provkey, const char *name);
+ int OSSL_FUNC_kem_decapsulate(void *ctx, unsigned char *out, size_t *outlen,
+ const unsigned char *in, size_t inlen);
+
+ /* KEM parameters */
+ int OSSL_FUNC_kem_get_ctx_params(void *ctx, OSSL_PARAM params[]);
+ const OSSL_PARAM *OSSL_FUNC_kem_gettable_ctx_params(void *ctx, void *provctx);
+ int OSSL_FUNC_kem_set_ctx_params(void *ctx, const OSSL_PARAM params[]);
+ const OSSL_PARAM *OSSL_FUNC_kem_settable_ctx_params(void *ctx, void *provctx);
+
+=head1 DESCRIPTION
+
+This documentation is primarily aimed at provider authors. See L<provider(7)>
+for further information.
+
+The asymmetric kem (OSSL_OP_KEM) operation enables providers to
+implement asymmetric kem algorithms and make them available to applications
+via the API functions L<EVP_PKEY_encapsulate(3)>,
+L<EVP_PKEY_decapsulate(3)> and other related functions.
+
+All "functions" mentioned here are passed as function pointers between
+F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
+L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
+provider_query_operation() function
+(see L<provider-base(7)/Provider Functions>).
+
+All these "functions" have a corresponding function type definition
+named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
+function pointer from an L<OSSL_DISPATCH(3)> element named
+B<OSSL_FUNC_{name}>.
+For example, the "function" OSSL_FUNC_kem_newctx() has these:
+
+ typedef void *(OSSL_FUNC_kem_newctx_fn)(void *provctx);
+ static ossl_inline OSSL_FUNC_kem_newctx_fn
+ OSSL_FUNC_kem_newctx(const OSSL_DISPATCH *opf);
+
+L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
+macros in L<openssl-core_dispatch.h(7)>, as follows:
+
+ OSSL_FUNC_kem_newctx OSSL_FUNC_KEM_NEWCTX
+ OSSL_FUNC_kem_freectx OSSL_FUNC_KEM_FREECTX
+ OSSL_FUNC_kem_dupctx OSSL_FUNC_KEM_DUPCTX
+
+ OSSL_FUNC_kem_encapsulate_init OSSL_FUNC_KEM_ENCAPSULATE_INIT
+ OSSL_FUNC_kem_encapsulate OSSL_FUNC_KEM_ENCAPSULATE
+
+ OSSL_FUNC_kem_decapsulate_init OSSL_FUNC_KEM_DECAPSULATE_INIT
+ OSSL_FUNC_kem_decapsulate OSSL_FUNC_KEM_DECAPSULATE
+
+ OSSL_FUNC_kem_get_ctx_params OSSL_FUNC_KEM_GET_CTX_PARAMS
+ OSSL_FUNC_kem_gettable_ctx_params OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS
+ OSSL_FUNC_kem_set_ctx_params OSSL_FUNC_KEM_SET_CTX_PARAMS
+ OSSL_FUNC_kem_settable_ctx_params OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS
+
+An asymmetric kem algorithm implementation may not implement all of these
+functions.
+In order to be a consistent set of functions a provider must implement
+OSSL_FUNC_kem_newctx and OSSL_FUNC_kem_freectx.
+It must also implement both of OSSL_FUNC_kem_encapsulate_init and
+OSSL_FUNC_kem_encapsulate, or both of OSSL_FUNC_kem_decapsulate_init and
+OSSL_FUNC_kem_decapsulate.
+OSSL_FUNC_kem_get_ctx_params is optional but if it is present then so must
+OSSL_FUNC_kem_gettable_ctx_params.
+Similarly, OSSL_FUNC_kem_set_ctx_params is optional but if it is present then
+so must OSSL_FUNC_kem_settable_ctx_params.
+
+An asymmetric kem algorithm must also implement some mechanism for generating,
+loading or importing keys via the key management (OSSL_OP_KEYMGMT) operation.
+See L<provider-keymgmt(7)> for further details.
+
+=head2 Context Management Functions
+
+OSSL_FUNC_kem_newctx() should create and return a pointer to a provider side
+structure for holding context information during an asymmetric kem operation.
+A pointer to this context will be passed back in a number of the other
+asymmetric kem operation function calls.
+The parameter I<provctx> is the provider context generated during provider
+initialisation (see L<provider(7)>).
+
+OSSL_FUNC_kem_freectx() is passed a pointer to the provider side asymmetric
+kem context in the I<ctx> parameter.
+This function should free any resources associated with that context.
+
+OSSL_FUNC_kem_dupctx() should duplicate the provider side asymmetric kem
+context in the I<ctx> parameter and return the duplicate copy.
+
+=head2 Asymmetric Key Encapsulation Functions
+
+OSSL_FUNC_kem_encapsulate_init() initialises a context for an asymmetric
+encapsulation given a provider side asymmetric kem context in the I<ctx>
+parameter, a pointer to a provider key object in the I<provkey> parameter and
+the I<name> of the algorithm.
+The I<params>, if not NULL, should be set on the context in a manner similar to
+using OSSL_FUNC_kem_set_ctx_params().
+The key object should have been previously generated, loaded or imported into
+the provider using the key management (OSSL_OP_KEYMGMT) operation (see
+provider-keymgmt(7)>.
+
+OSSL_FUNC_kem_encapsulate() performs the actual encapsulation itself.
+A previously initialised asymmetric kem context is passed in the I<ctx>
+parameter.
+Unless I<out> is NULL, the data to be encapsulated is internally generated,
+and returned into the buffer pointed to by the I<secret> parameter and the
+encapsulated data should also be written to the location pointed to by the
+I<out> parameter. The length of the encapsulated data should be written to
+I<*outlen> and the length of the generated secret should be written to
+I<*secretlen>.
+
+If I<out> is NULL then the maximum length of the encapsulated data should be
+written to I<*outlen>, and the maximum length of the generated secret should be
+written to I<*secretlen>.
+
+=head2 Decapsulation Functions
+
+OSSL_FUNC_kem_decapsulate_init() initialises a context for an asymmetric
+decapsulation given a provider side asymmetric kem context in the I<ctx>
+parameter, a pointer to a provider key object in the I<provkey> parameter, and
+a I<name> of the algorithm.
+The key object should have been previously generated, loaded or imported into
+the provider using the key management (OSSL_OP_KEYMGMT) operation (see
+provider-keymgmt(7)>.
+
+OSSL_FUNC_kem_decapsulate() performs the actual decapsulation itself.
+A previously initialised asymmetric kem context is passed in the I<ctx>
+parameter.
+The data to be decapsulated is pointed to by the I<in> parameter which is I<inlen>
+bytes long.
+Unless I<out> is NULL, the decapsulated data should be written to the location
+pointed to by the I<out> parameter.
+The length of the decapsulated data should be written to I<*outlen>.
+If I<out> is NULL then the maximum length of the decapsulated data should be
+written to I<*outlen>.
+
+=head2 Asymmetric Key Encapsulation Parameters
+
+See L<OSSL_PARAM(3)> for further details on the parameters structure used by
+the OSSL_FUNC_kem_get_ctx_params() and OSSL_FUNC_kem_set_ctx_params()
+functions.
+
+OSSL_FUNC_kem_get_ctx_params() gets asymmetric kem parameters associated
+with the given provider side asymmetric kem context I<ctx> and stores them in
+I<params>.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_kem_set_ctx_params() sets the asymmetric kem parameters associated
+with the given provider side asymmetric kem context I<ctx> to I<params>.
+Any parameter settings are additional to any that were previously set.
+Passing NULL for I<params> should return true.
+
+No parameters are currently recognised by built-in asymmetric kem algorithms.
+
+OSSL_FUNC_kem_gettable_ctx_params() and OSSL_FUNC_kem_settable_ctx_params()
+get a constant L<OSSL_PARAM(3)> array that describes the gettable and settable
+parameters, i.e. parameters that can be used with OSSL_FUNC_kem_get_ctx_params()
+and OSSL_FUNC_kem_set_ctx_params() respectively.
+
+=head1 RETURN VALUES
+
+OSSL_FUNC_kem_newctx() and OSSL_FUNC_kem_dupctx() should return the newly
+created provider side asymmetric kem context, or NULL on failure.
+
+All other functions should return 1 for success or 0 on error.
+
+=head1 SEE ALSO
+
+L<provider(7)>
+
+=head1 HISTORY
+
+The provider KEM interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider-keyexch.pod b/doc/man7/provider-keyexch.pod
new file mode 100644
index 000000000000..9e146d31c719
--- /dev/null
+++ b/doc/man7/provider-keyexch.pod
@@ -0,0 +1,238 @@
+=pod
+
+=head1 NAME
+
+provider-keyexch - The keyexch library E<lt>-E<gt> provider functions
+
+=head1 SYNOPSIS
+
+=for openssl multiple includes
+
+ #include <openssl/core_dispatch.h>
+ #include <openssl/core_names.h>
+
+ /*
+ * None of these are actual functions, but are displayed like this for
+ * the function signatures for functions that are offered as function
+ * pointers in OSSL_DISPATCH arrays.
+ */
+
+ /* Context management */
+ void *OSSL_FUNC_keyexch_newctx(void *provctx);
+ void OSSL_FUNC_keyexch_freectx(void *ctx);
+ void *OSSL_FUNC_keyexch_dupctx(void *ctx);
+
+ /* Shared secret derivation */
+ int OSSL_FUNC_keyexch_init(void *ctx, void *provkey,
+ const OSSL_PARAM params[]);
+ int OSSL_FUNC_keyexch_set_peer(void *ctx, void *provkey);
+ int OSSL_FUNC_keyexch_derive(void *ctx, unsigned char *secret, size_t *secretlen,
+ size_t outlen);
+
+ /* Key Exchange parameters */
+ int OSSL_FUNC_keyexch_set_ctx_params(void *ctx, const OSSL_PARAM params[]);
+ const OSSL_PARAM *OSSL_FUNC_keyexch_settable_ctx_params(void *ctx,
+ void *provctx);
+ int OSSL_FUNC_keyexch_get_ctx_params(void *ctx, OSSL_PARAM params[]);
+ const OSSL_PARAM *OSSL_FUNC_keyexch_gettable_ctx_params(void *ctx,
+ void *provctx);
+
+=head1 DESCRIPTION
+
+This documentation is primarily aimed at provider authors. See L<provider(7)>
+for further information.
+
+The key exchange (OSSL_OP_KEYEXCH) operation enables providers to implement key
+exchange algorithms and make them available to applications via
+L<EVP_PKEY_derive(3)> and
+other related functions).
+
+All "functions" mentioned here are passed as function pointers between
+F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
+L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
+provider_query_operation() function
+(see L<provider-base(7)/Provider Functions>).
+
+All these "functions" have a corresponding function type definition
+named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
+function pointer from an L<OSSL_DISPATCH(3)> element named
+B<OSSL_FUNC_{name}>.
+For example, the "function" OSSL_FUNC_keyexch_newctx() has these:
+
+ typedef void *(OSSL_FUNC_keyexch_newctx_fn)(void *provctx);
+ static ossl_inline OSSL_FUNC_keyexch_newctx_fn
+ OSSL_FUNC_keyexch_newctx(const OSSL_DISPATCH *opf);
+
+L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
+macros in L<openssl-core_dispatch.h(7)>, as follows:
+
+ OSSL_FUNC_keyexch_newctx OSSL_FUNC_KEYEXCH_NEWCTX
+ OSSL_FUNC_keyexch_freectx OSSL_FUNC_KEYEXCH_FREECTX
+ OSSL_FUNC_keyexch_dupctx OSSL_FUNC_KEYEXCH_DUPCTX
+
+ OSSL_FUNC_keyexch_init OSSL_FUNC_KEYEXCH_INIT
+ OSSL_FUNC_keyexch_set_peer OSSL_FUNC_KEYEXCH_SET_PEER
+ OSSL_FUNC_keyexch_derive OSSL_FUNC_KEYEXCH_DERIVE
+
+ OSSL_FUNC_keyexch_set_ctx_params OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS
+ OSSL_FUNC_keyexch_settable_ctx_params OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS
+ OSSL_FUNC_keyexch_get_ctx_params OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS
+ OSSL_FUNC_keyexch_gettable_ctx_params OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS
+
+A key exchange algorithm implementation may not implement all of these functions.
+In order to be a consistent set of functions a provider must implement
+OSSL_FUNC_keyexch_newctx, OSSL_FUNC_keyexch_freectx, OSSL_FUNC_keyexch_init and OSSL_FUNC_keyexch_derive.
+All other functions are optional.
+
+A key exchange algorithm must also implement some mechanism for generating,
+loading or importing keys via the key management (OSSL_OP_KEYMGMT) operation.
+See L<provider-keymgmt(7)> for further details.
+
+=head2 Context Management Functions
+
+OSSL_FUNC_keyexch_newctx() should create and return a pointer to a provider side
+structure for holding context information during a key exchange operation.
+A pointer to this context will be passed back in a number of the other key
+exchange operation function calls.
+The parameter I<provctx> is the provider context generated during provider
+initialisation (see L<provider(7)>).
+
+OSSL_FUNC_keyexch_freectx() is passed a pointer to the provider side key exchange
+context in the I<ctx> parameter.
+This function should free any resources associated with that context.
+
+OSSL_FUNC_keyexch_dupctx() should duplicate the provider side key exchange context in
+the I<ctx> parameter and return the duplicate copy.
+
+=head2 Shared Secret Derivation Functions
+
+OSSL_FUNC_keyexch_init() initialises a key exchange operation given a provider side key
+exchange context in the I<ctx> parameter, and a pointer to a provider key object
+in the I<provkey> parameter.
+The I<params>, if not NULL, should be set on the context in a manner similar to
+using OSSL_FUNC_keyexch_set_params().
+The key object should have been previously
+generated, loaded or imported into the provider using the key management
+(OSSL_OP_KEYMGMT) operation (see provider-keymgmt(7)>.
+
+OSSL_FUNC_keyexch_set_peer() is called to supply the peer's public key (in the
+I<provkey> parameter) to be used when deriving the shared secret.
+It is also passed a previously initialised key exchange context in the I<ctx>
+parameter.
+The key object should have been previously generated, loaded or imported into
+the provider using the key management (OSSL_OP_KEYMGMT) operation (see
+provider-keymgmt(7)>.
+
+OSSL_FUNC_keyexch_derive() performs the actual key exchange itself by deriving a shared
+secret.
+A previously initialised key exchange context is passed in the I<ctx>
+parameter.
+The derived secret should be written to the location I<secret> which should not
+exceed I<outlen> bytes.
+The length of the shared secret should be written to I<*secretlen>.
+If I<secret> is NULL then the maximum length of the shared secret should be
+written to I<*secretlen>.
+
+=head2 Key Exchange Parameters Functions
+
+OSSL_FUNC_keyexch_set_ctx_params() sets key exchange parameters associated with the
+given provider side key exchange context I<ctx> to I<params>,
+see L</Common Key Exchange parameters>.
+Any parameter settings are additional to any that were previously set.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_keyexch_get_ctx_params() gets key exchange parameters associated with the
+given provider side key exchange context I<ctx> into I<params>,
+see L</Common Key Exchange parameters>.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_keyexch_settable_ctx_params() yields a constant L<OSSL_PARAM(3)> array that
+describes the settable parameters, i.e. parameters that can be used with
+OP_signature_set_ctx_params().
+If OSSL_FUNC_keyexch_settable_ctx_params() is present, OSSL_FUNC_keyexch_set_ctx_params() must
+also be present, and vice versa.
+Similarly, OSSL_FUNC_keyexch_gettable_ctx_params() yields a constant L<OSSL_PARAM(3)>
+array that describes the gettable parameters, i.e. parameters that can be
+handled by OP_signature_get_ctx_params().
+If OSSL_FUNC_keyexch_gettable_ctx_params() is present, OSSL_FUNC_keyexch_get_ctx_params() must
+also be present, and vice versa.
+
+Notice that not all settable parameters are also gettable, and vice versa.
+
+=head2 Common Key Exchange parameters
+
+See L<OSSL_PARAM(3)> for further details on the parameters structure used by
+the OSSL_FUNC_keyexch_set_ctx_params() and OSSL_FUNC_keyexch_get_ctx_params() functions.
+
+Common parameters currently recognised by built-in key exchange algorithms are
+as follows.
+
+=over 4
+
+=item "kdf-type" (B<OSSL_EXCHANGE_PARAM_KDF_TYPE>) <UTF8 string>
+
+Sets or gets the Key Derivation Function type to apply within the associated key
+exchange ctx.
+
+=item "kdf-digest" (B<OSSL_EXCHANGE_PARAM_KDF_DIGEST>) <UTF8 string>
+
+Sets or gets the Digest algorithm to be used as part of the Key Derivation Function
+associated with the given key exchange ctx.
+
+=item "kdf-digest-props" (B<OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS>) <UTF8 string>
+
+Sets properties to be used upon look up of the implementation for the selected
+Digest algorithm for the Key Derivation Function associated with the given key
+exchange ctx.
+
+=item "kdf-outlen" (B<OSSL_EXCHANGE_PARAM_KDF_OUTLEN>) <unsigned integer>
+
+Sets or gets the desired size for the output of the chosen Key Derivation Function
+associated with the given key exchange ctx.
+The length of the "kdf-outlen" parameter should not exceed that of a B<size_t>.
+
+=item "kdf-ukm" (B<OSSL_EXCHANGE_PARAM_KDF_UKM>) <octet string>
+
+Sets the User Key Material to be used as part of the selected Key Derivation
+Function associated with the given key exchange ctx.
+
+=item "kdf-ukm" (B<OSSL_EXCHANGE_PARAM_KDF_UKM>) <octet string ptr>
+
+Gets a pointer to the User Key Material to be used as part of the selected
+Key Derivation Function associated with the given key exchange ctx. Providers
+usually do not need to support this gettable parameter as its sole purpose
+is to support functionality of the deprecated EVP_PKEY_CTX_get0_ecdh_kdf_ukm()
+and EVP_PKEY_CTX_get0_dh_kdf_ukm() functions.
+
+=back
+
+=head1 RETURN VALUES
+
+OSSL_FUNC_keyexch_newctx() and OSSL_FUNC_keyexch_dupctx() should return the newly created
+provider side key exchange context, or NULL on failure.
+
+OSSL_FUNC_keyexch_init(), OSSL_FUNC_keyexch_set_peer(), OSSL_FUNC_keyexch_derive(),
+OSSL_FUNC_keyexch_set_params(), and OSSL_FUNC_keyexch_get_params() should return 1 for success
+or 0 on error.
+
+OSSL_FUNC_keyexch_settable_ctx_params() and OSSL_FUNC_keyexch_gettable_ctx_params() should
+always return a constant L<OSSL_PARAM(3)> array.
+
+=head1 SEE ALSO
+
+L<provider(7)>
+
+=head1 HISTORY
+
+The provider KEYEXCH interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider-keymgmt.pod b/doc/man7/provider-keymgmt.pod
new file mode 100644
index 000000000000..be3a65e31978
--- /dev/null
+++ b/doc/man7/provider-keymgmt.pod
@@ -0,0 +1,422 @@
+=pod
+
+=head1 NAME
+
+provider-keymgmt - The KEYMGMT library E<lt>-E<gt> provider functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/core_dispatch.h>
+
+ /*
+ * None of these are actual functions, but are displayed like this for
+ * the function signatures for functions that are offered as function
+ * pointers in OSSL_DISPATCH arrays.
+ */
+
+ /* Key object (keydata) creation and destruction */
+ void *OSSL_FUNC_keymgmt_new(void *provctx);
+ void OSSL_FUNC_keymgmt_free(void *keydata);
+
+ /* Generation, a more complex constructor */
+ void *OSSL_FUNC_keymgmt_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[]);
+ int OSSL_FUNC_keymgmt_gen_set_template(void *genctx, void *template);
+ int OSSL_FUNC_keymgmt_gen_set_params(void *genctx, const OSSL_PARAM params[]);
+ const OSSL_PARAM *OSSL_FUNC_keymgmt_gen_settable_params(void *genctx,
+ void *provctx);
+ void *OSSL_FUNC_keymgmt_gen(void *genctx, OSSL_CALLBACK *cb, void *cbarg);
+ void OSSL_FUNC_keymgmt_gen_cleanup(void *genctx);
+
+ /* Key loading by object reference, also a constructor */
+ void *OSSL_FUNC_keymgmt_load(const void *reference, size_t *reference_sz);
+
+ /* Key object information */
+ int OSSL_FUNC_keymgmt_get_params(void *keydata, OSSL_PARAM params[]);
+ const OSSL_PARAM *OSSL_FUNC_keymgmt_gettable_params(void *provctx);
+ int OSSL_FUNC_keymgmt_set_params(void *keydata, const OSSL_PARAM params[]);
+ const OSSL_PARAM *OSSL_FUNC_keymgmt_settable_params(void *provctx);
+
+ /* Key object content checks */
+ int OSSL_FUNC_keymgmt_has(const void *keydata, int selection);
+ int OSSL_FUNC_keymgmt_match(const void *keydata1, const void *keydata2,
+ int selection);
+
+ /* Discovery of supported operations */
+ const char *OSSL_FUNC_keymgmt_query_operation_name(int operation_id);
+
+ /* Key object import and export functions */
+ int OSSL_FUNC_keymgmt_import(void *keydata, int selection, const OSSL_PARAM params[]);
+ const OSSL_PARAM *OSSL_FUNC_keymgmt_import_types(int selection);
+ int OSSL_FUNC_keymgmt_export(void *keydata, int selection,
+ OSSL_CALLBACK *param_cb, void *cbarg);
+ const OSSL_PARAM *OSSL_FUNC_keymgmt_export_types(int selection);
+
+ /* Key object duplication, a constructor */
+ void *OSSL_FUNC_keymgmt_dup(const void *keydata_from, int selection);
+
+ /* Key object validation */
+ int OSSL_FUNC_keymgmt_validate(const void *keydata, int selection, int checktype);
+
+=head1 DESCRIPTION
+
+The KEYMGMT operation doesn't have much public visibility in OpenSSL
+libraries, it's rather an internal operation that's designed to work
+in tandem with operations that use private/public key pairs.
+
+Because the KEYMGMT operation shares knowledge with the operations it
+works with in tandem, they must belong to the same provider.
+The OpenSSL libraries will ensure that they do.
+
+The primary responsibility of the KEYMGMT operation is to hold the
+provider side key data for the OpenSSL library EVP_PKEY structure.
+
+All "functions" mentioned here are passed as function pointers between
+F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
+L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
+provider_query_operation() function
+(see L<provider-base(7)/Provider Functions>).
+
+All these "functions" have a corresponding function type definition
+named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
+function pointer from a L<OSSL_DISPATCH(3)> element named
+B<OSSL_FUNC_{name}>.
+For example, the "function" OSSL_FUNC_keymgmt_new() has these:
+
+ typedef void *(OSSL_FUNC_keymgmt_new_fn)(void *provctx);
+ static ossl_inline OSSL_FUNC_keymgmt_new_fn
+ OSSL_FUNC_keymgmt_new(const OSSL_DISPATCH *opf);
+
+L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
+macros in L<openssl-core_dispatch.h(7)>, as follows:
+
+ OSSL_FUNC_keymgmt_new OSSL_FUNC_KEYMGMT_NEW
+ OSSL_FUNC_keymgmt_free OSSL_FUNC_KEYMGMT_FREE
+
+ OSSL_FUNC_keymgmt_gen_init OSSL_FUNC_KEYMGMT_GEN_INIT
+ OSSL_FUNC_keymgmt_gen_set_template OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE
+ OSSL_FUNC_keymgmt_gen_set_params OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS
+ OSSL_FUNC_keymgmt_gen_settable_params OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS
+ OSSL_FUNC_keymgmt_gen OSSL_FUNC_KEYMGMT_GEN
+ OSSL_FUNC_keymgmt_gen_cleanup OSSL_FUNC_KEYMGMT_GEN_CLEANUP
+
+ OSSL_FUNC_keymgmt_load OSSL_FUNC_KEYMGMT_LOAD
+
+ OSSL_FUNC_keymgmt_get_params OSSL_FUNC_KEYMGMT_GET_PARAMS
+ OSSL_FUNC_keymgmt_gettable_params OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS
+ OSSL_FUNC_keymgmt_set_params OSSL_FUNC_KEYMGMT_SET_PARAMS
+ OSSL_FUNC_keymgmt_settable_params OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS
+
+ OSSL_FUNC_keymgmt_query_operation_name OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME
+
+ OSSL_FUNC_keymgmt_has OSSL_FUNC_KEYMGMT_HAS
+ OSSL_FUNC_keymgmt_validate OSSL_FUNC_KEYMGMT_VALIDATE
+ OSSL_FUNC_keymgmt_match OSSL_FUNC_KEYMGMT_MATCH
+
+ OSSL_FUNC_keymgmt_import OSSL_FUNC_KEYMGMT_IMPORT
+ OSSL_FUNC_keymgmt_import_types OSSL_FUNC_KEYMGMT_IMPORT_TYPES
+ OSSL_FUNC_keymgmt_export OSSL_FUNC_KEYMGMT_EXPORT
+ OSSL_FUNC_keymgmt_export_types OSSL_FUNC_KEYMGMT_EXPORT_TYPES
+
+ OSSL_FUNC_keymgmt_dup OSSL_FUNC_KEYMGMT_DUP
+
+=head2 Key Objects
+
+A key object is a collection of data for an asymmetric key, and is
+represented as I<keydata> in this manual.
+
+The exact contents of a key object are defined by the provider, and it
+is assumed that different operations in one and the same provider use
+the exact same structure to represent this collection of data, so that
+for example, a key object that has been created using the KEYMGMT
+interface that we document here can be passed as is to other provider
+operations, such as OP_signature_sign_init() (see
+L<provider-signature(7)>).
+
+With some of the KEYMGMT functions, it's possible to select a specific
+subset of data to handle, governed by the bits in a I<selection>
+indicator. The bits are:
+
+=over 4
+
+=item B<OSSL_KEYMGMT_SELECT_PRIVATE_KEY>
+
+Indicating that the private key data in a key object should be
+considered.
+
+=item B<OSSL_KEYMGMT_SELECT_PUBLIC_KEY>
+
+Indicating that the public key data in a key object should be
+considered.
+
+=item B<OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS>
+
+Indicating that the domain parameters in a key object should be
+considered.
+
+=item B<OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS>
+
+Indicating that other parameters in a key object should be
+considered.
+
+Other parameters are key parameters that don't fit any other
+classification. In other words, this particular selector bit works as
+a last resort bit bucket selector.
+
+=back
+
+Some selector bits have also been combined for easier use:
+
+=over 4
+
+=item B<OSSL_KEYMGMT_SELECT_ALL_PARAMETERS>
+
+Indicating that all key object parameters should be considered,
+regardless of their more granular classification.
+
+=for comment This should used by EVP functions such as
+EVP_PKEY_copy_parameters() and EVP_PKEY_parameters_eq()
+
+This is a combination of B<OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS> and
+B<OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS>.
+
+=for comment If more parameter categories are added, they should be
+mentioned here too.
+
+=item B<OSSL_KEYMGMT_SELECT_KEYPAIR>
+
+Indicating that both the whole key pair in a key object should be
+considered, i.e. the combination of public and private key.
+
+This is a combination of B<OSSL_KEYMGMT_SELECT_PRIVATE_KEY> and
+B<OSSL_KEYMGMT_SELECT_PUBLIC_KEY>.
+
+=item B<OSSL_KEYMGMT_SELECT_ALL>
+
+Indicating that everything in a key object should be considered.
+
+=back
+
+The exact interpretation of those bits or how they combine is left to
+each function where you can specify a selector.
+
+It's left to the provider implementation to decide what is reasonable
+to do with regards to received selector bits and how to do it.
+Among others, an implementation of OSSL_FUNC_keymgmt_match() might opt
+to not compare the private half if it has compared the public half,
+since a match of one half implies a match of the other half.
+
+=head2 Constructing and Destructing Functions
+
+OSSL_FUNC_keymgmt_new() should create a provider side key object. The
+provider context I<provctx> is passed and may be incorporated in the
+key object, but that is not mandatory.
+
+OSSL_FUNC_keymgmt_free() should free the passed I<keydata>.
+
+OSSL_FUNC_keymgmt_gen_init(), OSSL_FUNC_keymgmt_gen_set_template(),
+OSSL_FUNC_keymgmt_gen_set_params(), OSSL_FUNC_keymgmt_gen_settable_params(),
+OSSL_FUNC_keymgmt_gen() and OSSL_FUNC_keymgmt_gen_cleanup() work together as a
+more elaborate context based key object constructor.
+
+OSSL_FUNC_keymgmt_gen_init() should create the key object generation context
+and initialize it with I<selections>, which will determine what kind
+of contents the key object to be generated should get.
+The I<params>, if not NULL, should be set on the context in a manner similar to
+using OSSL_FUNC_keymgmt_set_params().
+
+OSSL_FUNC_keymgmt_gen_set_template() should add I<template> to the context
+I<genctx>. The I<template> is assumed to be a key object constructed
+with the same KEYMGMT, and from which content that the implementation
+chooses can be used as a template for the key object to be generated.
+Typically, the generation of a DSA or DH key would get the domain
+parameters from this I<template>.
+
+OSSL_FUNC_keymgmt_gen_set_params() should set additional parameters from
+I<params> in the key object generation context I<genctx>.
+
+OSSL_FUNC_keymgmt_gen_settable_params() should return a constant array of
+descriptor L<OSSL_PARAM(3)>, for parameters that OSSL_FUNC_keymgmt_gen_set_params()
+can handle.
+
+OSSL_FUNC_keymgmt_gen() should perform the key object generation itself, and
+return the result. The callback I<cb> should be called at regular
+intervals with indications on how the key object generation
+progresses.
+
+OSSL_FUNC_keymgmt_gen_cleanup() should clean up and free the key object
+generation context I<genctx>
+
+OSSL_FUNC_keymgmt_load() creates a provider side key object based on a
+I<reference> object with a size of I<reference_sz> bytes, that only the
+provider knows how to interpret, but that may come from other operations.
+Outside the provider, this reference is simply an array of bytes.
+
+At least one of OSSL_FUNC_keymgmt_new(), OSSL_FUNC_keymgmt_gen() and
+OSSL_FUNC_keymgmt_load() are mandatory, as well as OSSL_FUNC_keymgmt_free() and
+OSSL_FUNC_keymgmt_has(). Additionally, if OSSL_FUNC_keymgmt_gen() is present,
+OSSL_FUNC_keymgmt_gen_init() and OSSL_FUNC_keymgmt_gen_cleanup() must be
+present as well.
+
+=head2 Key Object Information Functions
+
+OSSL_FUNC_keymgmt_get_params() should extract information data associated
+with the given I<keydata>, see L</Common Information Parameters>.
+
+OSSL_FUNC_keymgmt_gettable_params() should return a constant array of
+descriptor L<OSSL_PARAM(3)>, for parameters that OSSL_FUNC_keymgmt_get_params()
+can handle.
+
+If OSSL_FUNC_keymgmt_gettable_params() is present, OSSL_FUNC_keymgmt_get_params()
+must also be present, and vice versa.
+
+OSSL_FUNC_keymgmt_set_params() should update information data associated
+with the given I<keydata>, see L</Common Information Parameters>.
+
+OSSL_FUNC_keymgmt_settable_params() should return a constant array of
+descriptor L<OSSL_PARAM(3)>, for parameters that OSSL_FUNC_keymgmt_set_params()
+can handle.
+
+If OSSL_FUNC_keymgmt_settable_params() is present, OSSL_FUNC_keymgmt_set_params()
+must also be present, and vice versa.
+
+=head2 Key Object Checking Functions
+
+OSSL_FUNC_keymgmt_query_operation_name() should return the name of the
+supported algorithm for the operation I<operation_id>. This is
+similar to provider_query_operation() (see L<provider-base(7)>),
+but only works as an advisory. If this function is not present, or
+returns NULL, the caller is free to assume that there's an algorithm
+from the same provider, of the same name as the one used to fetch the
+keymgmt and try to use that.
+
+OSSL_FUNC_keymgmt_has() should check whether the given I<keydata> contains the subsets
+of data indicated by the I<selector>. A combination of several
+selector bits must consider all those subsets, not just one. An
+implementation is, however, free to consider an empty subset of data
+to still be a valid subset. For algorithms where some selection is
+not meaningful such as B<OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS> for
+RSA keys the function should just return 1 as the selected subset
+is not really missing in the key.
+
+OSSL_FUNC_keymgmt_validate() should check if the I<keydata> contains valid
+data subsets indicated by I<selection>. Some combined selections of
+data subsets may cause validation of the combined data.
+For example, the combination of B<OSSL_KEYMGMT_SELECT_PRIVATE_KEY> and
+B<OSSL_KEYMGMT_SELECT_PUBLIC_KEY> (or B<OSSL_KEYMGMT_SELECT_KEYPAIR>
+for short) is expected to check that the pairwise consistency of
+I<keydata> is valid. The I<checktype> parameter controls what type of check is
+performed on the subset of data. Two types of check are defined:
+B<OSSL_KEYMGMT_VALIDATE_FULL_CHECK> and B<OSSL_KEYMGMT_VALIDATE_QUICK_CHECK>.
+The interpretation of how much checking is performed in a full check versus a
+quick check is key type specific. Some providers may have no distinction
+between a full check and a quick check. For algorithms where some selection is
+not meaningful such as B<OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS> for
+RSA keys the function should just return 1 as there is nothing to validate for
+that selection.
+
+OSSL_FUNC_keymgmt_match() should check if the data subset indicated by
+I<selection> in I<keydata1> and I<keydata2> match. It is assumed that
+the caller has ensured that I<keydata1> and I<keydata2> are both owned
+by the implementation of this function.
+
+=head2 Key Object Import, Export and Duplication Functions
+
+OSSL_FUNC_keymgmt_import() should import data indicated by I<selection> into
+I<keydata> with values taken from the L<OSSL_PARAM(3)> array I<params>.
+
+OSSL_FUNC_keymgmt_export() should extract values indicated by I<selection>
+from I<keydata>, create an L<OSSL_PARAM(3)> array with them and call
+I<param_cb> with that array as well as the given I<cbarg>.
+
+OSSL_FUNC_keymgmt_import_types() should return a constant array of descriptor
+L<OSSL_PARAM(3)> for data indicated by I<selection>, for parameters that
+OSSL_FUNC_keymgmt_import() can handle.
+
+OSSL_FUNC_keymgmt_export_types() should return a constant array of descriptor
+L<OSSL_PARAM(3)> for data indicated by I<selection>, that the
+OSSL_FUNC_keymgmt_export() callback can expect to receive.
+
+OSSL_FUNC_keymgmt_dup() should duplicate data subsets indicated by
+I<selection> or the whole key data I<keydata_from> and create a new
+provider side key object with the data.
+
+=head2 Common Information Parameters
+
+See L<OSSL_PARAM(3)> for further details on the parameters structure.
+
+Common information parameters currently recognised by all built-in
+keymgmt algorithms are as follows:
+
+=over 4
+
+=item "bits" (B<OSSL_PKEY_PARAM_BITS>) <integer>
+
+The value should be the cryptographic length of the cryptosystem to
+which the key belongs, in bits. The definition of cryptographic
+length is specific to the key cryptosystem.
+
+=item "max-size" (B<OSSL_PKEY_PARAM_MAX_SIZE>) <integer>
+
+The value should be the maximum size that a caller should allocate to
+safely store a signature (called I<sig> in L<provider-signature(7)>),
+the result of asymmmetric encryption / decryption (I<out> in
+L<provider-asym_cipher(7)>, a derived secret (I<secret> in
+L<provider-keyexch(7)>, and similar data).
+
+Because an EVP_KEYMGMT method is always tightly bound to another method
+(signature, asymmetric cipher, key exchange, ...) and must be of the
+same provider, this number only needs to be synchronised with the
+dimensions handled in the rest of the same provider.
+
+=item "security-bits" (B<OSSL_PKEY_PARAM_SECURITY_BITS>) <integer>
+
+The value should be the number of security bits of the given key.
+Bits of security is defined in SP800-57.
+
+=back
+
+=head1 RETURN VALUES
+
+OSSL_FUNC_keymgmt_new() and OSSL_FUNC_keymgmt_dup() should return a valid
+reference to the newly created provider side key object, or NULL on failure.
+
+OSSL_FUNC_keymgmt_import(), OSSL_FUNC_keymgmt_export(), OSSL_FUNC_keymgmt_get_params() and
+OSSL_FUNC_keymgmt_set_params() should return 1 for success or 0 on error.
+
+OSSL_FUNC_keymgmt_validate() should return 1 on successful validation, or 0 on
+failure.
+
+OSSL_FUNC_keymgmt_has() should return 1 if all the selected data subsets are contained
+in the given I<keydata> or 0 otherwise.
+
+OSSL_FUNC_keymgmt_query_operation_name() should return a pointer to a string matching
+the requested operation, or NULL if the same name used to fetch the keymgmt
+applies.
+
+OSSL_FUNC_keymgmt_gettable_params() and OSSL_FUNC_keymgmt_settable_params()
+OSSL_FUNC_keymgmt_import_types(), OSSL_FUNC_keymgmt_export_types()
+should
+always return a constant L<OSSL_PARAM(3)> array.
+
+=head1 SEE ALSO
+
+L<provider(7)>,
+L<EVP_PKEY-X25519(7)>, L<EVP_PKEY-X448(7)>, L<EVP_PKEY-ED25519(7)>,
+L<EVP_PKEY-ED448(7)>, L<EVP_PKEY-EC(7)>, L<EVP_PKEY-RSA(7)>,
+L<EVP_PKEY-DSA(7)>, L<EVP_PKEY-DH(7)>
+
+=head1 HISTORY
+
+The KEYMGMT interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider-mac.pod b/doc/man7/provider-mac.pod
new file mode 100644
index 000000000000..a90bf15948b4
--- /dev/null
+++ b/doc/man7/provider-mac.pod
@@ -0,0 +1,236 @@
+=pod
+
+=head1 NAME
+
+provider-mac - The mac library E<lt>-E<gt> provider functions
+
+=head1 SYNOPSIS
+
+=for openssl multiple includes
+
+ #include <openssl/core_dispatch.h>
+ #include <openssl/core_names.h>
+
+ /*
+ * None of these are actual functions, but are displayed like this for
+ * the function signatures for functions that are offered as function
+ * pointers in OSSL_DISPATCH arrays.
+ */
+
+ /* Context management */
+ void *OSSL_FUNC_mac_newctx(void *provctx);
+ void OSSL_FUNC_mac_freectx(void *mctx);
+ void *OSSL_FUNC_mac_dupctx(void *src);
+
+ /* Encryption/decryption */
+ int OSSL_FUNC_mac_init(void *mctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[]);
+ int OSSL_FUNC_mac_update(void *mctx, const unsigned char *in, size_t inl);
+ int OSSL_FUNC_mac_final(void *mctx, unsigned char *out, size_t *outl, size_t outsize);
+
+ /* MAC parameter descriptors */
+ const OSSL_PARAM *OSSL_FUNC_mac_gettable_params(void *provctx);
+ const OSSL_PARAM *OSSL_FUNC_mac_gettable_ctx_params(void *mctx, void *provctx);
+ const OSSL_PARAM *OSSL_FUNC_mac_settable_ctx_params(void *mctx, void *provctx);
+
+ /* MAC parameters */
+ int OSSL_FUNC_mac_get_params(OSSL_PARAM params[]);
+ int OSSL_FUNC_mac_get_ctx_params(void *mctx, OSSL_PARAM params[]);
+ int OSSL_FUNC_mac_set_ctx_params(void *mctx, const OSSL_PARAM params[]);
+
+=head1 DESCRIPTION
+
+This documentation is primarily aimed at provider authors. See L<provider(7)>
+for further information.
+
+The MAC operation enables providers to implement mac algorithms and make
+them available to applications via the API functions L<EVP_MAC_init(3)>,
+L<EVP_MAC_update(3)> and L<EVP_MAC_final(3)>.
+
+All "functions" mentioned here are passed as function pointers between
+F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
+L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
+provider_query_operation() function
+(see L<provider-base(7)/Provider Functions>).
+
+All these "functions" have a corresponding function type definition
+named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
+function pointer from an L<OSSL_DISPATCH(3)> element named
+B<OSSL_FUNC_{name}>.
+For example, the "function" OSSL_FUNC_mac_newctx() has these:
+
+ typedef void *(OSSL_FUNC_mac_newctx_fn)(void *provctx);
+ static ossl_inline OSSL_FUNC_mac_newctx_fn
+ OSSL_FUNC_mac_newctx(const OSSL_DISPATCH *opf);
+
+L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
+macros in L<openssl-core_dispatch.h(7)>, as follows:
+
+ OSSL_FUNC_mac_newctx OSSL_FUNC_MAC_NEWCTX
+ OSSL_FUNC_mac_freectx OSSL_FUNC_MAC_FREECTX
+ OSSL_FUNC_mac_dupctx OSSL_FUNC_MAC_DUPCTX
+
+ OSSL_FUNC_mac_init OSSL_FUNC_MAC_INIT
+ OSSL_FUNC_mac_update OSSL_FUNC_MAC_UPDATE
+ OSSL_FUNC_mac_final OSSL_FUNC_MAC_FINAL
+
+ OSSL_FUNC_mac_get_params OSSL_FUNC_MAC_GET_PARAMS
+ OSSL_FUNC_mac_get_ctx_params OSSL_FUNC_MAC_GET_CTX_PARAMS
+ OSSL_FUNC_mac_set_ctx_params OSSL_FUNC_MAC_SET_CTX_PARAMS
+
+ OSSL_FUNC_mac_gettable_params OSSL_FUNC_MAC_GETTABLE_PARAMS
+ OSSL_FUNC_mac_gettable_ctx_params OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS
+ OSSL_FUNC_mac_settable_ctx_params OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS
+
+A mac algorithm implementation may not implement all of these functions.
+In order to be a consistent set of functions, at least the following functions
+must be implemented: OSSL_FUNC_mac_newctx(), OSSL_FUNC_mac_freectx(), OSSL_FUNC_mac_init(),
+OSSL_FUNC_mac_update(), OSSL_FUNC_mac_final().
+All other functions are optional.
+
+=head2 Context Management Functions
+
+OSSL_FUNC_mac_newctx() should create and return a pointer to a provider side
+structure for holding context information during a mac operation.
+A pointer to this context will be passed back in a number of the other mac
+operation function calls.
+The parameter I<provctx> is the provider context generated during provider
+initialisation (see L<provider(7)>).
+
+OSSL_FUNC_mac_freectx() is passed a pointer to the provider side mac context in
+the I<mctx> parameter.
+If it receives NULL as I<mctx> value, it should not do anything other than
+return.
+This function should free any resources associated with that context.
+
+OSSL_FUNC_mac_dupctx() should duplicate the provider side mac context in the
+I<mctx> parameter and return the duplicate copy.
+
+=head2 Encryption/Decryption Functions
+
+OSSL_FUNC_mac_init() initialises a mac operation given a newly created provider
+side mac context in the I<mctx> parameter. The I<params> are set before setting
+the MAC I<key> of I<keylen> bytes.
+
+OSSL_FUNC_mac_update() is called to supply data for MAC computation of a previously
+initialised mac operation.
+The I<mctx> parameter contains a pointer to a previously initialised provider
+side context.
+OSSL_FUNC_mac_update() may be called multiple times for a single mac operation.
+
+OSSL_FUNC_mac_final() completes the MAC computation started through previous
+OSSL_FUNC_mac_init() and OSSL_FUNC_mac_update() calls.
+The I<mctx> parameter contains a pointer to the provider side context.
+The resulting MAC should be written to I<out> and the amount of data written
+to I<*outl>, which should not exceed I<outsize> bytes.
+The same expectations apply to I<outsize> as documented for
+L<EVP_MAC_final(3)>.
+
+=head2 Mac Parameters
+
+See L<OSSL_PARAM(3)> for further details on the parameters structure used by
+these functions.
+
+OSSL_FUNC_mac_get_params() gets details of parameter values associated with the
+provider algorithm and stores them in I<params>.
+
+OSSL_FUNC_mac_set_ctx_params() sets mac parameters associated with the given
+provider side mac context I<mctx> to I<params>.
+Any parameter settings are additional to any that were previously set.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_mac_get_ctx_params() gets details of currently set parameter values
+associated with the given provider side mac context I<mctx> and stores them
+in I<params>.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_mac_gettable_params(), OSSL_FUNC_mac_gettable_ctx_params(),
+and OSSL_FUNC_mac_settable_ctx_params() all return constant L<OSSL_PARAM(3)>
+arrays as descriptors of the parameters that OSSL_FUNC_mac_get_params(),
+OSSL_FUNC_mac_get_ctx_params(), and OSSL_FUNC_mac_set_ctx_params()
+can handle, respectively. OSSL_FUNC_mac_gettable_ctx_params() and
+OSSL_FUNC_mac_settable_ctx_params() will return the parameters associated
+with the provider side context I<mctx> in its current state if it is
+not NULL. Otherwise, they return the parameters associated with the
+provider side algorithm I<provctx>.
+
+All MAC implementations are expected to handle the following parameters:
+
+=over 4
+
+=item with OSSL_FUNC_set_ctx_params():
+
+=over 4
+
+=item "key" (B<OSSL_MAC_PARAM_KEY>) <octet string>
+
+Sets the key in the associated MAC ctx. This is identical to passing a I<key>
+argument to the OSSL_FUNC_mac_init() function.
+
+=back
+
+=item with OSSL_FUNC_get_params():
+
+=over 4
+
+=item "size" (B<OSSL_MAC_PARAM_SIZE>) <integer>
+
+Can be used to get the default MAC size (which might be the only allowable
+MAC size for the implementation).
+
+Note that some implementations allow setting the size that the resulting MAC
+should have as well, see the documentation of the implementation.
+
+=back
+
+=over 4
+
+=item "size" (B<OSSL_MAC_PARAM_BLOCK_SIZE>) <integer>
+
+Can be used to get the MAC block size (if supported by the algorithm).
+
+=back
+
+=back
+
+=head1 NOTES
+
+The MAC life-cycle is described in L<life_cycle-rand(7)>. Providers should
+ensure that the various transitions listed there are supported. At some point
+the EVP layer will begin enforcing the listed transitions.
+
+=head1 RETURN VALUES
+
+OSSL_FUNC_mac_newctx() and OSSL_FUNC_mac_dupctx() should return the newly created
+provider side mac context, or NULL on failure.
+
+OSSL_FUNC_mac_init(), OSSL_FUNC_mac_update(), OSSL_FUNC_mac_final(), OSSL_FUNC_mac_get_params(),
+OSSL_FUNC_mac_get_ctx_params() and OSSL_FUNC_mac_set_ctx_params() should return 1 for
+success or 0 on error.
+
+OSSL_FUNC_mac_gettable_params(), OSSL_FUNC_mac_gettable_ctx_params() and
+OSSL_FUNC_mac_settable_ctx_params() should return a constant L<OSSL_PARAM(3)>
+array, or NULL if none is offered.
+
+=head1 SEE ALSO
+
+L<provider(7)>,
+L<EVP_MAC-BLAKE2(7)>, L<EVP_MAC-CMAC(7)>, L<EVP_MAC-GMAC(7)>,
+L<EVP_MAC-HMAC(7)>, L<EVP_MAC-KMAC(7)>, L<EVP_MAC-Poly1305(7)>,
+L<EVP_MAC-Siphash(7)>,
+L<life_cycle-mac(7)>, L<EVP_MAC(3)>
+
+=head1 HISTORY
+
+The provider MAC interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider-object.pod b/doc/man7/provider-object.pod
new file mode 100644
index 000000000000..1088e035510f
--- /dev/null
+++ b/doc/man7/provider-object.pod
@@ -0,0 +1,194 @@
+=pod
+
+=head1 NAME
+
+provider-object - A specification for a provider-native object abstraction
+
+=head1 SYNOPSIS
+
+=for openssl multiple includes
+
+ #include <openssl/core_object.h>
+ #include <openssl/core_names.h>
+
+=head1 DESCRIPTION
+
+The provider-native object abstraction is a set of L<OSSL_PARAM(3)> keys and
+values that can be used to pass provider-native objects to OpenSSL library
+code or between different provider operation implementations with the help
+of OpenSSL library code.
+
+The intention is that certain provider-native operations can pass any sort
+of object that belong with other operations, or with OpenSSL library code.
+
+An object may be passed in the following manners:
+
+=over 4
+
+=item 1.
+
+I<By value>
+
+This means that the I<object data> is passed as an octet string or an UTF8
+string, which can be handled in diverse ways by other provided implementations.
+The encoding of the object depends on the context it's used in; for example,
+L<OSSL_DECODER(3)> allows multiple encodings, depending on existing decoders.
+If central OpenSSL library functionality is to handle the data directly, it
+B<must> be encoded in DER for all object types except for B<OSSL_OBJECT_NAME>
+(see L</Parameter reference> below), where it's assumed to a plain UTF8 string.
+
+=for comment A future extension might be to be able to specify encoding as a
+separate parameter.
+
+=item 2.
+
+I<By reference>
+
+This means that the I<object data> isn't passed directly, an I<object
+reference> is passed instead. It's an octet string that only the correct
+provider understands correctly.
+
+=back
+
+Objects I<by value> can be used by anything that handles DER encoded
+objects.
+
+Objects I<by reference> need a higher level of cooperation from the
+implementation where the object originated (let's call it X) and its target
+implementation (let's call it Y):
+
+=over 4
+
+=item 1.
+
+I<An object loading function in the target implementation>
+
+The target implementation (Y) may have a function that can take an I<object
+reference>. This can only be used if the target implementation is from the
+same provider as the one originating the object abstraction in question (X).
+
+The exact target implementation to use is determined from the I<object type>
+and possibly the I<object data type>.
+For example, when the OpenSSL library receives an object abstraction with the
+I<object type> B<OSSL_OBJECT_PKEY>, it will fetch a L<provider-keymgmt(7)>
+using the I<object data type> as its key type (the second argument in
+L<EVP_KEYMGMT_fetch(3)>).
+
+=item 2.
+
+I<An object exporter in the originating implementation>
+
+The originating implementation (X) may have an exporter function. This
+exporter function can be used to export the object in L<OSSL_PARAM(3)> form,
+that can then be imported by the target implementation's imported function.
+
+This can be used when it's not possible to fetch the target implementation
+(Y) from the same provider.
+
+=back
+
+=head2 Parameter reference
+
+A provider-native object abstraction is an L<OSSL_PARAM(3)> with a selection
+of the following parameters:
+
+=over 4
+
+=item "data" (B<OSSL_OBJECT_PARAM_DATA>) <octet string> or <UTF8 string>
+
+The object data I<passed by value>.
+
+=item "reference" (B<OSSL_OBJECT_PARAM_REFERENCE>) <octet string>
+
+The object data I<passed by reference>.
+
+=item "type" (B<OSSL_OBJECT_PARAM_TYPE>) <integer>
+
+The I<object type>, a number that may have any of the following values (all
+defined in F<< <openssl/core_object.h> >>):
+
+=over 4
+
+=item B<OSSL_OBJECT_NAME>
+
+The object data may only be I<passed by value>, and should be a UTF8
+string.
+
+This is useful for L<provider-storemgmt(7)> when a URI load results in new
+URIs.
+
+=item B<OSSL_OBJECT_PKEY>
+
+The object data is suitable as provider-native B<EVP_PKEY> key data. The
+object data may be I<passed by value> or I<passed by reference>.
+
+=item B<OSSL_OBJECT_CERT>
+
+The object data is suitable as B<X509> data. The object data for this
+object type can only be I<passed by value>, and should be an octet string.
+
+Since there's no provider-native X.509 object, OpenSSL libraries that
+receive this object abstraction are expected to convert the data to a
+B<X509> object with d2i_X509().
+
+=item B<OSSL_OBJECT_CRL>
+
+The object data is suitable as B<X509_CRL> data. The object data can
+only be I<passed by value>, and should be an octet string.
+
+Since there's no provider-native X.509 CRL object, OpenSSL libraries that
+receive this object abstraction are expected to convert the data to a
+B<X509_CRL> object with d2i_X509_CRL().
+
+=back
+
+=item "data-type" (B<OSSL_OBJECT_PARAM_DATA_TYPE>) <UTF8 string>
+
+The specific type of the object content. Legitimate values depend on the
+object type; if it is B<OSSL_OBJECT_PKEY>, the data type is expected to be a
+key type suitable for fetching a L<provider-keymgmt(7)> that can handle the
+data.
+
+=for comment For objects with an unknown object type (OSSL_OBJECT_PARAM_TYPE
+is either missing or has the value OSSL_OBJECT_UNKNOWN), libcrypto
+interprets the object data type as the input type for a decoder.
+
+=item "data-structure" (B<OSSL_OBJECT_PARAM_DATA_STRUCTURE>) <UTF8 string>
+
+The outermost structure of the object content. Legitimate values depend on
+the object type.
+
+=item "desc" (B<OSSL_OBJECT_PARAM_DESC>) <UTF8 string>
+
+A human readable text that describes extra details on the object.
+
+=back
+
+When a provider-native object abtraction is used, it I<must> contain object
+data in at least one form (object data I<passed by value>, i.e. the "data"
+item, or object data I<passed by reference>, i.e. the "reference" item).
+Both may be present at once, in which case the OpenSSL library code that
+receives this will use the most optimal variant.
+
+For objects with the object type B<OSSL_OBJECT_NAME>, that object type
+I<must> be given.
+
+=head1 SEE ALSO
+
+L<provider(7)>, L<OSSL_DECODER(3)>
+
+=head1 HISTORY
+
+The concept of providers and everything surrounding them was
+introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider-rand.pod b/doc/man7/provider-rand.pod
new file mode 100644
index 000000000000..e115d845dcd9
--- /dev/null
+++ b/doc/man7/provider-rand.pod
@@ -0,0 +1,302 @@
+=pod
+
+=head1 NAME
+
+provider-rand - The random number generation library E<lt>-E<gt> provider
+functions
+
+=head1 SYNOPSIS
+
+=for openssl multiple includes
+
+ #include <openssl/core_dispatch.h>
+ #include <openssl/core_names.h>
+
+ /*
+ * None of these are actual functions, but are displayed like this for
+ * the function signatures for functions that are offered as function
+ * pointers in OSSL_DISPATCH arrays.
+ */
+
+ /* Context management */
+ void *OSSL_FUNC_rand_newctx(void *provctx, void *parent,
+ const OSSL_DISPATCH *parent_calls);
+ void OSSL_FUNC_rand_freectx(void *ctx);
+
+ /* Random number generator functions: NIST */
+ int OSSL_FUNC_rand_instantiate(void *ctx, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *pstr, size_t pstr_len,
+ const OSSL_PARAM params[]);
+ int OSSL_FUNC_rand_uninstantiate(void *ctx);
+ int OSSL_FUNC_rand_generate(void *ctx, unsigned char *out, size_t outlen,
+ unsigned int strength, int prediction_resistance,
+ const unsigned char *addin, size_t addin_len);
+ int OSSL_FUNC_rand_reseed(void *ctx, int prediction_resistance,
+ const unsigned char *ent, size_t ent_len,
+ const unsigned char *addin, size_t addin_len);
+
+ /* Random number generator functions: additional */
+ size_t OSSL_FUNC_rand_nonce(void *ctx, unsigned char *out, size_t outlen,
+ int strength, size_t min_noncelen,
+ size_t max_noncelen);
+ size_t OSSL_FUNC_rand_get_seed(void *ctx, unsigned char **buffer,
+ int entropy, size_t min_len, size_t max_len,
+ int prediction_resistance,
+ const unsigned char *adin, size_t adin_len);
+ void OSSL_FUNC_rand_clear_seed(void *ctx, unsigned char *buffer, size_t b_len);
+ int OSSL_FUNC_rand_verify_zeroization(void *ctx);
+
+ /* Context Locking */
+ int OSSL_FUNC_rand_enable_locking(void *ctx);
+ int OSSL_FUNC_rand_lock(void *ctx);
+ void OSSL_FUNC_rand_unlock(void *ctx);
+
+ /* RAND parameter descriptors */
+ const OSSL_PARAM *OSSL_FUNC_rand_gettable_params(void *provctx);
+ const OSSL_PARAM *OSSL_FUNC_rand_gettable_ctx_params(void *ctx, void *provctx);
+ const OSSL_PARAM *OSSL_FUNC_rand_settable_ctx_params(void *ctx, void *provctx);
+
+ /* RAND parameters */
+ int OSSL_FUNC_rand_get_params(OSSL_PARAM params[]);
+ int OSSL_FUNC_rand_get_ctx_params(void *ctx, OSSL_PARAM params[]);
+ int OSSL_FUNC_rand_set_ctx_params(void *ctx, const OSSL_PARAM params[]);
+
+=head1 DESCRIPTION
+
+This documentation is primarily aimed at provider authors. See L<provider(7)>
+for further information.
+
+The RAND operation enables providers to implement random number generation
+algorithms and random number sources and make
+them available to applications via the API function L<EVP_RAND(3)>.
+
+=head2 Context Management Functions
+
+OSSL_FUNC_rand_newctx() should create and return a pointer to a provider side
+structure for holding context information during a rand operation.
+A pointer to this context will be passed back in a number of the other rand
+operation function calls.
+The parameter I<provctx> is the provider context generated during provider
+initialisation (see L<provider(7)>).
+The parameter I<parent> specifies another rand instance to be used for
+seeding purposes. If NULL and the specific instance supports it, the
+operating system will be used for seeding.
+The parameter I<parent_calls> points to the dispatch table for I<parent>.
+Thus, the parent need not be from the same provider as the new instance.
+
+OSSL_FUNC_rand_freectx() is passed a pointer to the provider side rand context in
+the I<mctx> parameter.
+If it receives NULL as I<ctx> value, it should not do anything other than
+return.
+This function should free any resources associated with that context.
+
+=head2 Random Number Generator Functions: NIST
+
+These functions correspond to those defined in NIST SP 800-90A and SP 800-90C.
+
+OSSL_FUNC_rand_instantiate() is used to instantiate the DRBG I<ctx> at a requested
+security I<strength>. In addition, I<prediction_resistance> can be requested.
+Additional input I<addin> of length I<addin_len> bytes can optionally
+be provided. The parameters specified in I<params> configure the DRBG and these
+should be processed before instantiation.
+
+OSSL_FUNC_rand_uninstantiate() is used to uninstantiate the DRBG I<ctx>. After being
+uninstantiated, a DRBG is unable to produce output until it is instantiated
+anew.
+
+OSSL_FUNC_rand_generate() is used to generate random bytes from the DRBG I<ctx>.
+It will generate I<outlen> bytes placing them into the buffer pointed to by
+I<out>. The generated bytes will meet the specified security I<strength> and,
+if I<prediction_resistance> is true, the bytes will be produced after reseeding
+from a live entropy source. Additional input I<addin> of length I<addin_len>
+bytes can optionally be provided.
+
+=head2 Random Number Generator Functions: Additional
+
+OSSL_FUNC_rand_nonce() is used to generate a nonce of the given I<strength> with a
+length from I<min_noncelen> to I<max_noncelen>. If the output buffer I<out> is
+NULL, the length of the nonce should be returned.
+
+OSSL_FUNC_rand_get_seed() is used by deterministic generators to obtain their
+seeding material from their parent. The seed bytes will meet the specified
+security level of I<entropy> bits and there will be between I<min_len>
+and I<max_len> inclusive bytes in total. If I<prediction_resistance> is
+true, the bytes will be produced from a live entropy source. Additional
+input I<addin> of length I<addin_len> bytes can optionally be provided.
+A pointer to the seed material is returned in I<*buffer> and this must be
+freed by a later call to OSSL_FUNC_rand_clear_seed().
+
+OSSL_FUNC_rand_clear_seed() frees a seed I<buffer> of length I<b_len> bytes
+which was previously allocated by OSSL_FUNC_rand_get_seed().
+
+OSSL_FUNC_rand_verify_zeroization() is used to determine if the internal state of the
+DRBG is zero. This capability is mandated by NIST as part of the self
+tests, it is unlikely to be useful in other circumstances.
+
+=head2 Context Locking
+
+When DRBGs are used by multiple threads, there must be locking employed to
+ensure their proper operation. Because locking introduces an overhead, it
+is disabled by default.
+
+OSSL_FUNC_rand_enable_locking() allows locking to be turned on for a DRBG and all of
+its parent DRBGs. From this call onwards, the DRBG can be used in a thread
+safe manner.
+
+OSSL_FUNC_rand_lock() is used to lock a DRBG. Once locked, exclusive access
+is guaranteed.
+
+OSSL_FUNC_rand_unlock() is used to unlock a DRBG.
+
+=head2 Rand Parameters
+
+See L<OSSL_PARAM(3)> for further details on the parameters structure used by
+these functions.
+
+OSSL_FUNC_rand_get_params() gets details of parameter values associated with the
+provider algorithm and stores them in I<params>.
+
+OSSL_FUNC_rand_set_ctx_params() sets rand parameters associated with the given
+provider side rand context I<ctx> to I<params>.
+Any parameter settings are additional to any that were previously set.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_rand_get_ctx_params() gets details of currently set parameter values
+associated with the given provider side rand context I<ctx> and stores them
+in I<params>.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_rand_gettable_params(), OSSL_FUNC_rand_gettable_ctx_params(),
+and OSSL_FUNC_rand_settable_ctx_params() all return constant L<OSSL_PARAM(3)>
+arrays as descriptors of the parameters that OSSL_FUNC_rand_get_params(),
+OSSL_FUNC_rand_get_ctx_params(), and OSSL_FUNC_rand_set_ctx_params()
+can handle, respectively. OSSL_FUNC_rand_gettable_ctx_params()
+and OSSL_FUNC_rand_settable_ctx_params() will return the parameters
+associated with the provider side context I<ctx> in its current state
+if it is not NULL. Otherwise, they return the parameters associated
+with the provider side algorithm I<provctx>.
+
+
+Parameters currently recognised by built-in rands are as follows. Not all
+parameters are relevant to, or are understood by all rands:
+
+=over 4
+
+=item "state" (B<OSSL_RAND_PARAM_STATE>) <integer>
+
+Returns the state of the random number generator.
+
+=item "strength" (B<OSSL_RAND_PARAM_STRENGTH>) <unsigned integer>
+
+Returns the bit strength of the random number generator.
+
+=back
+
+For rands that are also deterministic random bit generators (DRBGs), these
+additional parameters are recognised. Not all
+parameters are relevant to, or are understood by all DRBG rands:
+
+=over 4
+
+=item "reseed_requests" (B<OSSL_DRBG_PARAM_RESEED_REQUESTS>) <unsigned integer>
+
+Reads or set the number of generate requests before reseeding the
+associated RAND ctx.
+
+=item "reseed_time_interval" (B<OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL>) <integer>
+
+Reads or set the number of elapsed seconds before reseeding the
+associated RAND ctx.
+
+=item "max_request" (B<OSSL_DRBG_PARAM_RESEED_REQUESTS>) <unsigned integer>
+
+Specifies the maximum number of bytes that can be generated in a single
+call to OSSL_FUNC_rand_generate.
+
+=item "min_entropylen" (B<OSSL_DRBG_PARAM_MIN_ENTROPYLEN>) <unsigned integer>
+
+=item "max_entropylen" (B<OSSL_DRBG_PARAM_MAX_ENTROPYLEN>) <unsigned integer>
+
+Specify the minimum and maximum number of bytes of random material that
+can be used to seed the DRBG.
+
+=item "min_noncelen" (B<OSSL_DRBG_PARAM_MIN_NONCELEN>) <unsigned integer>
+
+=item "max_noncelen" (B<OSSL_DRBG_PARAM_MAX_NONCELEN>) <unsigned integer>
+
+Specify the minimum and maximum number of bytes of nonce that can be used to
+instantiate the DRBG.
+
+=item "max_perslen" (B<OSSL_DRBG_PARAM_MAX_PERSLEN>) <unsigned integer>
+
+=item "max_adinlen" (B<OSSL_DRBG_PARAM_MAX_ADINLEN>) <unsigned integer>
+
+Specify the minimum and maximum number of bytes of personalisation string
+that can be used with the DRBG.
+
+=item "reseed_counter" (B<OSSL_DRBG_PARAM_RESEED_COUNTER>) <unsigned integer>
+
+Specifies the number of times the DRBG has been seeded or reseeded.
+
+=item "digest" (B<OSSL_DRBG_PARAM_DIGEST>) <UTF8 string>
+
+=item "cipher" (B<OSSL_DRBG_PARAM_CIPHER>) <UTF8 string>
+
+=item "mac" (B<OSSL_DRBG_PARAM_MAC>) <UTF8 string>
+
+Sets the name of the underlying cipher, digest or MAC to be used.
+It must name a suitable algorithm for the DRBG that's being used.
+
+=item "properties" (B<OSSL_DRBG_PARAM_PROPERTIES>) <UTF8 string>
+
+Sets the properties to be queried when trying to fetch an underlying algorithm.
+This must be given together with the algorithm naming parameter to be
+considered valid.
+
+=back
+
+=head1 RETURN VALUES
+
+OSSL_FUNC_rand_newctx() should return the newly created
+provider side rand context, or NULL on failure.
+
+OSSL_FUNC_rand_gettable_params(), OSSL_FUNC_rand_gettable_ctx_params() and
+OSSL_FUNC_rand_settable_ctx_params() should return a constant L<OSSL_PARAM(3)>
+array, or NULL if none is offered.
+
+OSSL_FUNC_rand_nonce() returns the size of the generated nonce, or 0 on error.
+
+OSSL_FUNC_rand_get_seed() returns the size of the generated seed, or 0 on
+error.
+
+All of the remaining functions should return 1 for success or 0 on error.
+
+=head1 NOTES
+
+The RAND life-cycle is described in L<life_cycle-rand(7)>. Providers should
+ensure that the various transitions listed there are supported. At some point
+the EVP layer will begin enforcing the listed transitions.
+
+=head1 SEE ALSO
+
+L<provider(7)>,
+L<RAND(7)>,
+L<EVP_RAND(7)>,
+L<life_cycle-rand(7)>,
+L<EVP_RAND(3)>
+
+=head1 HISTORY
+
+The provider RAND interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider-signature.pod b/doc/man7/provider-signature.pod
new file mode 100644
index 000000000000..fa38be1b16da
--- /dev/null
+++ b/doc/man7/provider-signature.pod
@@ -0,0 +1,439 @@
+=pod
+
+=head1 NAME
+
+provider-signature - The signature library E<lt>-E<gt> provider functions
+
+=head1 SYNOPSIS
+
+=for openssl multiple includes
+
+ #include <openssl/core_dispatch.h>
+ #include <openssl/core_names.h>
+
+ /*
+ * None of these are actual functions, but are displayed like this for
+ * the function signatures for functions that are offered as function
+ * pointers in OSSL_DISPATCH arrays.
+ */
+
+ /* Context management */
+ void *OSSL_FUNC_signature_newctx(void *provctx, const char *propq);
+ void OSSL_FUNC_signature_freectx(void *ctx);
+ void *OSSL_FUNC_signature_dupctx(void *ctx);
+
+ /* Signing */
+ int OSSL_FUNC_signature_sign_init(void *ctx, void *provkey,
+ const OSSL_PARAM params[]);
+ int OSSL_FUNC_signature_sign(void *ctx, unsigned char *sig, size_t *siglen,
+ size_t sigsize, const unsigned char *tbs, size_t tbslen);
+
+ /* Verifying */
+ int OSSL_FUNC_signature_verify_init(void *ctx, void *provkey,
+ const OSSL_PARAM params[]);
+ int OSSL_FUNC_signature_verify(void *ctx, const unsigned char *sig, size_t siglen,
+ const unsigned char *tbs, size_t tbslen);
+
+ /* Verify Recover */
+ int OSSL_FUNC_signature_verify_recover_init(void *ctx, void *provkey,
+ const OSSL_PARAM params[]);
+ int OSSL_FUNC_signature_verify_recover(void *ctx, unsigned char *rout,
+ size_t *routlen, size_t routsize,
+ const unsigned char *sig, size_t siglen);
+
+ /* Digest Sign */
+ int OSSL_FUNC_signature_digest_sign_init(void *ctx, const char *mdname,
+ void *provkey,
+ const OSSL_PARAM params[]);
+ int OSSL_FUNC_signature_digest_sign_update(void *ctx, const unsigned char *data,
+ size_t datalen);
+ int OSSL_FUNC_signature_digest_sign_final(void *ctx, unsigned char *sig,
+ size_t *siglen, size_t sigsize);
+ int OSSL_FUNC_signature_digest_sign(void *ctx,
+ unsigned char *sigret, size_t *siglen,
+ size_t sigsize, const unsigned char *tbs,
+ size_t tbslen);
+
+ /* Digest Verify */
+ int OSSL_FUNC_signature_digest_verify_init(void *ctx, const char *mdname,
+ void *provkey,
+ const OSSL_PARAM params[]);
+ int OSSL_FUNC_signature_digest_verify_update(void *ctx,
+ const unsigned char *data,
+ size_t datalen);
+ int OSSL_FUNC_signature_digest_verify_final(void *ctx, const unsigned char *sig,
+ size_t siglen);
+ int OSSL_FUNC_signature_digest_verify(void *ctx, const unsigned char *sig,
+ size_t siglen, const unsigned char *tbs,
+ size_t tbslen);
+
+ /* Signature parameters */
+ int OSSL_FUNC_signature_get_ctx_params(void *ctx, OSSL_PARAM params[]);
+ const OSSL_PARAM *OSSL_FUNC_signature_gettable_ctx_params(void *ctx,
+ void *provctx);
+ int OSSL_FUNC_signature_set_ctx_params(void *ctx, const OSSL_PARAM params[]);
+ const OSSL_PARAM *OSSL_FUNC_signature_settable_ctx_params(void *ctx,
+ void *provctx);
+ /* MD parameters */
+ int OSSL_FUNC_signature_get_ctx_md_params(void *ctx, OSSL_PARAM params[]);
+ const OSSL_PARAM * OSSL_FUNC_signature_gettable_ctx_md_params(void *ctx);
+ int OSSL_FUNC_signature_set_ctx_md_params(void *ctx, const OSSL_PARAM params[]);
+ const OSSL_PARAM * OSSL_FUNC_signature_settable_ctx_md_params(void *ctx);
+
+=head1 DESCRIPTION
+
+This documentation is primarily aimed at provider authors. See L<provider(7)>
+for further information.
+
+The signature (OSSL_OP_SIGNATURE) operation enables providers to implement
+signature algorithms and make them available to applications via the API
+functions L<EVP_PKEY_sign(3)>,
+L<EVP_PKEY_verify(3)>,
+and L<EVP_PKEY_verify_recover(3)> (as well
+as other related functions).
+
+All "functions" mentioned here are passed as function pointers between
+F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
+L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
+provider_query_operation() function
+(see L<provider-base(7)/Provider Functions>).
+
+All these "functions" have a corresponding function type definition
+named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
+function pointer from an L<OSSL_DISPATCH(3)> element named
+B<OSSL_FUNC_{name}>.
+For example, the "function" OSSL_FUNC_signature_newctx() has these:
+
+ typedef void *(OSSL_FUNC_signature_newctx_fn)(void *provctx, const char *propq);
+ static ossl_inline OSSL_FUNC_signature_newctx_fn
+ OSSL_FUNC_signature_newctx(const OSSL_DISPATCH *opf);
+
+L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
+macros in L<openssl-core_dispatch.h(7)>, as follows:
+
+ OSSL_FUNC_signature_newctx OSSL_FUNC_SIGNATURE_NEWCTX
+ OSSL_FUNC_signature_freectx OSSL_FUNC_SIGNATURE_FREECTX
+ OSSL_FUNC_signature_dupctx OSSL_FUNC_SIGNATURE_DUPCTX
+
+ OSSL_FUNC_signature_sign_init OSSL_FUNC_SIGNATURE_SIGN_INIT
+ OSSL_FUNC_signature_sign OSSL_FUNC_SIGNATURE_SIGN
+
+ OSSL_FUNC_signature_verify_init OSSL_FUNC_SIGNATURE_VERIFY_INIT
+ OSSL_FUNC_signature_verify OSSL_FUNC_SIGNATURE_VERIFY
+
+ OSSL_FUNC_signature_verify_recover_init OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT
+ OSSL_FUNC_signature_verify_recover OSSL_FUNC_SIGNATURE_VERIFY_RECOVER
+
+ OSSL_FUNC_signature_digest_sign_init OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT
+ OSSL_FUNC_signature_digest_sign_update OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE
+ OSSL_FUNC_signature_digest_sign_final OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL
+ OSSL_FUNC_signature_digest_sign OSSL_FUNC_SIGNATURE_DIGEST_SIGN
+
+ OSSL_FUNC_signature_digest_verify_init OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT
+ OSSL_FUNC_signature_digest_verify_update OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE
+ OSSL_FUNC_signature_digest_verify_final OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL
+ OSSL_FUNC_signature_digest_verify OSSL_FUNC_SIGNATURE_DIGEST_VERIFY
+
+ OSSL_FUNC_signature_get_ctx_params OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS
+ OSSL_FUNC_signature_gettable_ctx_params OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS
+ OSSL_FUNC_signature_set_ctx_params OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS
+ OSSL_FUNC_signature_settable_ctx_params OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS
+
+ OSSL_FUNC_signature_get_ctx_md_params OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS
+ OSSL_FUNC_signature_gettable_ctx_md_params OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS
+ OSSL_FUNC_signature_set_ctx_md_params OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS
+ OSSL_FUNC_signature_settable_ctx_md_params OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS
+
+A signature algorithm implementation may not implement all of these functions.
+In order to be a consistent set of functions we must have at least a set of
+context functions (OSSL_FUNC_signature_newctx and OSSL_FUNC_signature_freectx) as well as a
+set of "signature" functions, i.e. at least one of:
+
+=over 4
+
+=item OSSL_FUNC_signature_sign_init and OSSL_FUNC_signature_sign
+
+=item OSSL_FUNC_signature_verify_init and OSSL_FUNC_signature_verify
+
+=item OSSL_FUNC_signature_verify_recover_init and OSSL_FUNC_signature_verify_init
+
+=item OSSL_FUNC_signature_digest_sign_init, OSSL_FUNC_signature_digest_sign_update and OSSL_FUNC_signature_digest_sign_final
+
+=item OSSL_FUNC_signature_digest_verify_init, OSSL_FUNC_signature_digest_verify_update and OSSL_FUNC_signature_digest_verify_final
+
+=item OSSL_FUNC_signature_digest_sign_init and OSSL_FUNC_signature_digest_sign
+
+=item OSSL_FUNC_signature_digest_verify_init and OSSL_FUNC_signature_digest_verify
+
+=back
+
+OSSL_FUNC_signature_set_ctx_params and OSSL_FUNC_signature_settable_ctx_params are optional,
+but if one of them is present then the other one must also be present. The same
+applies to OSSL_FUNC_signature_get_ctx_params and OSSL_FUNC_signature_gettable_ctx_params, as
+well as the "md_params" functions. The OSSL_FUNC_signature_dupctx function is optional.
+
+A signature algorithm must also implement some mechanism for generating,
+loading or importing keys via the key management (OSSL_OP_KEYMGMT) operation.
+See L<provider-keymgmt(7)> for further details.
+
+=head2 Context Management Functions
+
+OSSL_FUNC_signature_newctx() should create and return a pointer to a provider side
+structure for holding context information during a signature operation.
+A pointer to this context will be passed back in a number of the other signature
+operation function calls.
+The parameter I<provctx> is the provider context generated during provider
+initialisation (see L<provider(7)>). The I<propq> parameter is a property query
+string that may be (optionally) used by the provider during any "fetches" that
+it may perform (if it performs any).
+
+OSSL_FUNC_signature_freectx() is passed a pointer to the provider side signature
+context in the I<ctx> parameter.
+This function should free any resources associated with that context.
+
+OSSL_FUNC_signature_dupctx() should duplicate the provider side signature context in
+the I<ctx> parameter and return the duplicate copy.
+
+=head2 Signing Functions
+
+OSSL_FUNC_signature_sign_init() initialises a context for signing given a provider side
+signature context in the I<ctx> parameter, and a pointer to a provider key object
+in the I<provkey> parameter.
+The I<params>, if not NULL, should be set on the context in a manner similar to
+using OSSL_FUNC_signature_set_ctx_params().
+The key object should have been previously generated, loaded or imported into
+the provider using the key management (OSSL_OP_KEYMGMT) operation (see
+provider-keymgmt(7)>.
+
+OSSL_FUNC_signature_sign() performs the actual signing itself.
+A previously initialised signature context is passed in the I<ctx>
+parameter.
+The data to be signed is pointed to be the I<tbs> parameter which is I<tbslen>
+bytes long.
+Unless I<sig> is NULL, the signature should be written to the location pointed
+to by the I<sig> parameter and it should not exceed I<sigsize> bytes in length.
+The length of the signature should be written to I<*siglen>.
+If I<sig> is NULL then the maximum length of the signature should be written to
+I<*siglen>.
+
+=head2 Verify Functions
+
+OSSL_FUNC_signature_verify_init() initialises a context for verifying a signature given
+a provider side signature context in the I<ctx> parameter, and a pointer to a
+provider key object in the I<provkey> parameter.
+The I<params>, if not NULL, should be set on the context in a manner similar to
+using OSSL_FUNC_signature_set_ctx_params().
+The key object should have been previously generated, loaded or imported into
+the provider using the key management (OSSL_OP_KEYMGMT) operation (see
+provider-keymgmt(7)>.
+
+OSSL_FUNC_signature_verify() performs the actual verification itself.
+A previously initialised signature context is passed in the I<ctx> parameter.
+The data that the signature covers is pointed to be the I<tbs> parameter which
+is I<tbslen> bytes long.
+The signature is pointed to by the I<sig> parameter which is I<siglen> bytes
+long.
+
+=head2 Verify Recover Functions
+
+OSSL_FUNC_signature_verify_recover_init() initialises a context for recovering the
+signed data given a provider side signature context in the I<ctx> parameter, and
+a pointer to a provider key object in the I<provkey> parameter.
+The I<params>, if not NULL, should be set on the context in a manner similar to
+using OSSL_FUNC_signature_set_ctx_params().
+The key object should have been previously generated, loaded or imported into
+the provider using the key management (OSSL_OP_KEYMGMT) operation (see
+provider-keymgmt(7)>.
+
+OSSL_FUNC_signature_verify_recover() performs the actual verify recover itself.
+A previously initialised signature context is passed in the I<ctx> parameter.
+The signature is pointed to by the I<sig> parameter which is I<siglen> bytes
+long.
+Unless I<rout> is NULL, the recovered data should be written to the location
+pointed to by I<rout> which should not exceed I<routsize> bytes in length.
+The length of the recovered data should be written to I<*routlen>.
+If I<rout> is NULL then the maximum size of the output buffer is written to
+the I<routlen> parameter.
+
+=head2 Digest Sign Functions
+
+OSSL_FUNC_signature_digeset_sign_init() initialises a context for signing given a
+provider side signature context in the I<ctx> parameter, and a pointer to a
+provider key object in the I<provkey> parameter.
+The I<params>, if not NULL, should be set on the context in a manner similar to
+using OSSL_FUNC_signature_set_ctx_params() and
+OSSL_FUNC_signature_set_ctx_md_params().
+The key object should have been
+previously generated, loaded or imported into the provider using the
+key management (OSSL_OP_KEYMGMT) operation (see provider-keymgmt(7)>.
+The name of the digest to be used will be in the I<mdname> parameter.
+
+OSSL_FUNC_signature_digest_sign_update() provides data to be signed in the I<data>
+parameter which should be of length I<datalen>. A previously initialised
+signature context is passed in the I<ctx> parameter. This function may be called
+multiple times to cumulatively add data to be signed.
+
+OSSL_FUNC_signature_digest_sign_final() finalises a signature operation previously
+started through OSSL_FUNC_signature_digest_sign_init() and
+OSSL_FUNC_signature_digest_sign_update() calls. Once finalised no more data will be
+added through OSSL_FUNC_signature_digest_sign_update(). A previously initialised
+signature context is passed in the I<ctx> parameter. Unless I<sig> is NULL, the
+signature should be written to the location pointed to by the I<sig> parameter
+and it should not exceed I<sigsize> bytes in length. The length of the signature
+should be written to I<*siglen>. If I<sig> is NULL then the maximum length of
+the signature should be written to I<*siglen>.
+
+OSSL_FUNC_signature_digest_sign() implements a "one shot" digest sign operation
+previously started through OSSL_FUNC_signature_digeset_sign_init(). A previously
+initialised signature context is passed in the I<ctx> parameter. The data to be
+signed is in I<tbs> which should be I<tbslen> bytes long. Unless I<sig> is NULL,
+the signature should be written to the location pointed to by the I<sig>
+parameter and it should not exceed I<sigsize> bytes in length. The length of the
+signature should be written to I<*siglen>. If I<sig> is NULL then the maximum
+length of the signature should be written to I<*siglen>.
+
+=head2 Digest Verify Functions
+
+OSSL_FUNC_signature_digeset_verify_init() initialises a context for verifying given a
+provider side verification context in the I<ctx> parameter, and a pointer to a
+provider key object in the I<provkey> parameter.
+The I<params>, if not NULL, should be set on the context in a manner similar to
+OSSL_FUNC_signature_set_ctx_params() and
+OSSL_FUNC_signature_set_ctx_md_params().
+The key object should have been
+previously generated, loaded or imported into the provider using the
+key management (OSSL_OP_KEYMGMT) operation (see provider-keymgmt(7)>.
+The name of the digest to be used will be in the I<mdname> parameter.
+
+OSSL_FUNC_signature_digest_verify_update() provides data to be verified in the I<data>
+parameter which should be of length I<datalen>. A previously initialised
+verification context is passed in the I<ctx> parameter. This function may be
+called multiple times to cumulatively add data to be verified.
+
+OSSL_FUNC_signature_digest_verify_final() finalises a verification operation previously
+started through OSSL_FUNC_signature_digest_verify_init() and
+OSSL_FUNC_signature_digest_verify_update() calls. Once finalised no more data will be
+added through OSSL_FUNC_signature_digest_verify_update(). A previously initialised
+verification context is passed in the I<ctx> parameter. The signature to be
+verified is in I<sig> which is I<siglen> bytes long.
+
+OSSL_FUNC_signature_digest_verify() implements a "one shot" digest verify operation
+previously started through OSSL_FUNC_signature_digeset_verify_init(). A previously
+initialised verification context is passed in the I<ctx> parameter. The data to be
+verified is in I<tbs> which should be I<tbslen> bytes long. The signature to be
+verified is in I<sig> which is I<siglen> bytes long.
+
+=head2 Signature parameters
+
+See L<OSSL_PARAM(3)> for further details on the parameters structure used by
+the OSSL_FUNC_signature_get_ctx_params() and OSSL_FUNC_signature_set_ctx_params() functions.
+
+OSSL_FUNC_signature_get_ctx_params() gets signature parameters associated with the
+given provider side signature context I<ctx> and stored them in I<params>.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_signature_set_ctx_params() sets the signature parameters associated with the
+given provider side signature context I<ctx> to I<params>.
+Any parameter settings are additional to any that were previously set.
+Passing NULL for I<params> should return true.
+
+Common parameters currently recognised by built-in signature algorithms are as
+follows.
+
+=over 4
+
+=item "digest" (B<OSSL_SIGNATURE_PARAM_DIGEST>) <UTF8 string>
+
+Get or sets the name of the digest algorithm used for the input to the
+signature functions. It is required in order to calculate the "algorithm-id".
+
+=item "properties" (B<OSSL_SIGNATURE_PARAM_PROPERTIES>) <UTF8 string>
+
+Sets the name of the property query associated with the "digest" algorithm.
+NULL is used if this optional value is not set.
+
+=item "digest-size" (B<OSSL_SIGNATURE_PARAM_DIGEST_SIZE>) <unsigned integer>
+
+Gets or sets the output size of the digest algorithm used for the input to the
+signature functions.
+The length of the "digest-size" parameter should not exceed that of a B<size_t>.
+
+=item "algorithm-id" (B<OSSL_SIGNATURE_PARAM_ALGORITHM_ID>) <octet string>
+
+Gets the DER encoded AlgorithmIdentifier that corresponds to the combination of
+signature algorithm and digest algorithm for the signature operation.
+
+=item "kat" (B<OSSL_SIGNATURE_PARAM_KAT>) <unsigned integer>
+
+Sets a flag to modify the sign operation to return an error if the initial
+calculated signature is invalid.
+In the normal mode of operation - new random values are chosen until the
+signature operation succeeds.
+By default it retries until a signature is calculated.
+Setting the value to 0 causes the sign operation to retry,
+otherwise the sign operation is only tried once and returns whether or not it
+was successful.
+Known answer tests can be performed if the random generator is overridden to
+supply known values that either pass or fail.
+
+=back
+
+OSSL_FUNC_signature_gettable_ctx_params() and OSSL_FUNC_signature_settable_ctx_params() get a
+constant L<OSSL_PARAM(3)> array that describes the gettable and settable parameters,
+i.e. parameters that can be used with OSSL_FUNC_signature_get_ctx_params() and
+OSSL_FUNC_signature_set_ctx_params() respectively.
+
+=head2 MD parameters
+
+See L<OSSL_PARAM(3)> for further details on the parameters structure used by
+the OSSL_FUNC_signature_get_md_ctx_params() and OSSL_FUNC_signature_set_md_ctx_params()
+functions.
+
+OSSL_FUNC_signature_get_md_ctx_params() gets digest parameters associated with the
+given provider side digest signature context I<ctx> and stores them in I<params>.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_signature_set_ms_ctx_params() sets the digest parameters associated with the
+given provider side digest signature context I<ctx> to I<params>.
+Any parameter settings are additional to any that were previously set.
+Passing NULL for I<params> should return true.
+
+Parameters currently recognised by built-in signature algorithms are the same
+as those for built-in digest algorithms. See
+L<provider-digest(7)/Digest Parameters> for further information.
+
+OSSL_FUNC_signature_gettable_md_ctx_params() and OSSL_FUNC_signature_settable_md_ctx_params()
+get a constant L<OSSL_PARAM(3)> array that describes the gettable and settable
+digest parameters, i.e. parameters that can be used with
+OSSL_FUNC_signature_get_md_ctx_params() and OSSL_FUNC_signature_set_md_ctx_params()
+respectively.
+
+=head1 RETURN VALUES
+
+OSSL_FUNC_signature_newctx() and OSSL_FUNC_signature_dupctx() should return the newly created
+provider side signature, or NULL on failure.
+
+OSSL_FUNC_signature_gettable_ctx_params(), OSSL_FUNC_signature_settable_ctx_params(),
+OSSL_FUNC_signature_gettable_md_ctx_params() and OSSL_FUNC_signature_settable_md_ctx_params(),
+return the gettable or settable parameters in a constant L<OSSL_PARAM(3)> array.
+
+All other functions should return 1 for success or 0 on error.
+
+=head1 SEE ALSO
+
+L<provider(7)>
+
+=head1 HISTORY
+
+The provider SIGNATURE interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider-storemgmt.pod b/doc/man7/provider-storemgmt.pod
new file mode 100644
index 000000000000..cde95f66e1ee
--- /dev/null
+++ b/doc/man7/provider-storemgmt.pod
@@ -0,0 +1,198 @@
+=pod
+
+=head1 NAME
+
+provider-storemgmt - The OSSL_STORE library E<lt>-E<gt> provider functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/core_dispatch.h>
+
+ /*
+ * None of these are actual functions, but are displayed like this for
+ * the function signatures for functions that are offered as function
+ * pointers in OSSL_DISPATCH arrays.
+ */
+
+ void *OSSL_FUNC_store_open(void *provctx, const char *uri);
+ void *OSSL_FUNC_store_attach(void *provctx, OSSL_CORE_BIO *bio);
+ const OSSL_PARAM *store_settable_ctx_params(void *provctx);
+ int OSSL_FUNC_store_set_ctx_params(void *loaderctx, const OSSL_PARAM[]);
+ int OSSL_FUNC_store_load(void *loaderctx,
+ OSSL_CALLBACK *object_cb, void *object_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg);
+ int OSSL_FUNC_store_eof(void *loaderctx);
+ int OSSL_FUNC_store_close(void *loaderctx);
+
+ int OSSL_FUNC_store_export_object
+ (void *loaderctx, const void *objref, size_t objref_sz,
+ OSSL_CALLBACK *export_cb, void *export_cbarg);
+
+=head1 DESCRIPTION
+
+The STORE operation is the provider side of the L<ossl_store(7)> API.
+
+The primary responsibility of the STORE operation is to load all sorts
+of objects from a container indicated by URI. These objects are given
+to the OpenSSL library in provider-native object abstraction form (see
+L<provider-object(7)>). The OpenSSL library is then responsible for
+passing on that abstraction to suitable provided functions.
+
+Examples of functions that the OpenSSL library can pass the abstraction to
+include OSSL_FUNC_keymgmt_load() (L<provider-keymgmt(7)>),
+OSSL_FUNC_store_export_object() (which exports the object in parameterized
+form).
+
+All "functions" mentioned here are passed as function pointers between
+F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
+L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
+provider_query_operation() function
+(see L<provider-base(7)/Provider Functions>).
+
+All these "functions" have a corresponding function type definition named
+B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the function pointer
+from a L<OSSL_DISPATCH(3)> element named B<OSSL_get_{name}>.
+For example, the "function" OSSL_FUNC_store_attach() has these:
+
+ typedef void *(OSSL_FUNC_store_attach_fn)(void *provctx,
+ OSSL_CORE_BIO * bio);
+ static ossl_inline OSSL_FUNC_store_attach_fn
+ OSSL_FUNC_store_attach(const OSSL_DISPATCH *opf);
+
+L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as macros
+in L<openssl-core_dispatch.h(7)>, as follows:
+
+ OSSL_FUNC_store_open OSSL_FUNC_STORE_OPEN
+ OSSL_FUNC_store_attach OSSL_FUNC_STORE_ATTACH
+ OSSL_FUNC_store_settable_ctx_params OSSL_FUNC_STORE_SETTABLE_CTX_PARAMS
+ OSSL_FUNC_store_set_ctx_params OSSL_FUNC_STORE_SET_CTX_PARAMS
+ OSSL_FUNC_store_load OSSL_FUNC_STORE_LOAD
+ OSSL_FUNC_store_eof OSSL_FUNC_STORE_EOF
+ OSSL_FUNC_store_close OSSL_FUNC_STORE_CLOSE
+ OSSL_FUNC_store_export_object OSSL_FUNC_STORE_EXPORT_OBJECT
+
+=head2 Functions
+
+OSSL_FUNC_store_open() should create a provider side context with data based
+on the input I<uri>. The implementation is entirely responsible for the
+interpretation of the URI.
+
+OSSL_FUNC_store_attach() should create a provider side context with the core
+B<BIO> I<bio> attached. This is an alternative to using a URI to find storage,
+supporting L<OSSL_STORE_attach(3)>.
+
+OSSL_FUNC_store_settable_ctx_params() should return a constant array of
+descriptor L<OSSL_PARAM(3)>, for parameters that OSSL_FUNC_store_set_ctx_params()
+can handle.
+
+OSSL_FUNC_store_set_ctx_params() should set additional parameters, such as what
+kind of data to expect, search criteria, and so on. More on those below, in
+L</Load Parameters>. Whether unrecognised parameters are an error or simply
+ignored is at the implementation's discretion.
+Passing NULL for I<params> should return true.
+
+OSSL_FUNC_store_load() loads the next object from the URI opened by
+OSSL_FUNC_store_open(), creates an object abstraction for it (see
+L<provider-object(7)>), and calls I<object_cb> with it as well as
+I<object_cbarg>. I<object_cb> will then interpret the object abstraction
+and do what it can to wrap it or decode it into an OpenSSL structure. In
+case a passphrase needs to be prompted to unlock an object, I<pw_cb> should
+be called.
+
+OSSL_FUNC_store_eof() indicates if the end of the set of objects from the
+URI has been reached. When that happens, there's no point trying to do any
+further loading.
+
+OSSL_FUNC_store_close() frees the provider side context I<ctx>.
+
+When a provider-native object is created by a store manager it would be unsuitable
+for direct use with a foreign provider. The export function allows for
+exporting the object to that foreign provider if the foreign provider
+supports the type of the object and provides an import function.
+
+OSSL_FUNC_store_export_object() should export the object of size I<objref_sz>
+referenced by I<objref> as an L<OSSL_PARAM(3)> array and pass that to the
+I<export_cb> as well as the given I<export_cbarg>.
+
+=head2 Load Parameters
+
+=over 4
+
+=item "expect" (B<OSSL_STORE_PARAM_EXPECT>) <integer>
+
+Is a hint of what type of data the OpenSSL library expects to get.
+This is only useful for optimization, as the library will check that the
+object types match the expectation too.
+
+The number that can be given through this parameter is found in
+F<< <openssl/store.h> >>, with the macros having names starting with
+C<OSSL_STORE_INFO_>. These are further described in
+L<OSSL_STORE_INFO(3)/SUPPORTED OBJECTS>.
+
+=item "subject" (B<OSSL_STORE_PARAM_SUBJECT>) <octet string>
+
+Indicates that the caller wants to search for an object with the given
+subject associated. This can be used to select specific certificates
+by subject.
+
+The contents of the octet string is expected to be in DER form.
+
+=item "issuer" (B<OSSL_STORE_PARAM_ISSUER>) <octet string>
+
+Indicates that the caller wants to search for an object with the given
+issuer associated. This can be used to select specific certificates
+by issuer.
+
+The contents of the octet string is expected to be in DER form.
+
+=item "serial" (B<OSSL_STORE_PARAM_SERIAL>) <integer>
+
+Indicates that the caller wants to search for an object with the given
+serial number associated.
+
+=item "digest" (B<OSSL_STORE_PARAM_DIGEST>) <UTF8 string>
+
+=item "fingerprint" (B<OSSL_STORE_PARAM_FINGERPRINT>) <octet string>
+
+Indicates that the caller wants to search for an object with the given
+fingerprint, computed with the given digest.
+
+=item "alias" (B<OSSL_STORE_PARAM_ALIAS>) <UTF8 string>
+
+Indicates that the caller wants to search for an object with the given
+alias (some call it a "friendly name").
+
+=item "properties" (B<OSSL_STORE_PARAM_PROPERTIES) <utf8 string>
+
+Property string to use when querying for algorithms such as the B<OSSL_DECODER>
+decoder implementations.
+
+=item "input-type" (B<OSSL_STORE_PARAM_INPUT_TYPE) <utf8 string>
+
+Type of the input format as a hint to use when decoding the objects in the
+store.
+
+=back
+
+Several of these search criteria may be combined. For example, to
+search for a certificate by issuer+serial, both the "issuer" and the
+"serial" parameters will be given.
+
+=head1 SEE ALSO
+
+L<provider(7)>
+
+=head1 HISTORY
+
+The STORE interface was introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider.pod b/doc/man7/provider.pod
new file mode 100644
index 000000000000..a061fc4709d0
--- /dev/null
+++ b/doc/man7/provider.pod
@@ -0,0 +1,264 @@
+=pod
+
+=head1 NAME
+
+provider - OpenSSL operation implementation providers
+
+=head1 SYNOPSIS
+
+=for openssl generic
+
+#include <openssl/provider.h>
+
+=head1 DESCRIPTION
+
+=head2 General
+
+This page contains information useful to provider authors.
+
+A I<provider>, in OpenSSL terms, is a unit of code that provides one
+or more implementations for various operations for diverse algorithms
+that one might want to perform.
+
+An I<operation> is something one wants to do, such as encryption and
+decryption, key derivation, MAC calculation, signing and verification,
+etc.
+
+An I<algorithm> is a named method to perform an operation.
+Very often, the algorithms revolve around cryptographic operations,
+but may also revolve around other types of operation, such as managing
+certain types of objects.
+
+See L<crypto(7)> for further details.
+
+=head2 Provider
+
+A I<provider> offers an initialization function, as a set of base
+functions in the form of an L<OSSL_DISPATCH(3)> array, and by extension,
+a set of L<OSSL_ALGORITHM(3)>s (see L<openssl-core.h(7)>).
+It may be a dynamically loadable module, or may be built-in, in
+OpenSSL libraries or in the application.
+If it's a dynamically loadable module, the initialization function
+must be named C<OSSL_provider_init> and must be exported.
+If it's built-in, the initialization function may have any name.
+
+The initialization function must have the following signature:
+
+ int NAME(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in, const OSSL_DISPATCH **out,
+ void **provctx);
+
+I<handle> is the OpenSSL library object for the provider, and works
+as a handle for everything the OpenSSL libraries need to know about
+the provider.
+For the provider itself, it is passed to some of the functions given in the
+dispatch array I<in>.
+
+I<in> is a dispatch array of base functions offered by the OpenSSL
+libraries, and the available functions are further described in
+L<provider-base(7)>.
+
+I<*out> must be assigned a dispatch array of base functions that the
+provider offers to the OpenSSL libraries.
+The functions that may be offered are further described in
+L<provider-base(7)>, and they are the central means of communication
+between the OpenSSL libraries and the provider.
+
+I<*provctx> should be assigned a provider specific context to allow
+the provider multiple simultaneous uses.
+This pointer will be passed to various operation functions offered by
+the provider.
+
+Note that the provider will not be made available for applications to use until
+the initialization function has completed and returned successfully.
+
+One of the functions the provider offers to the OpenSSL libraries is
+the central mechanism for the OpenSSL libraries to get access to
+operation implementations for diverse algorithms.
+Its referred to with the number B<OSSL_FUNC_PROVIDER_QUERY_OPERATION>
+and has the following signature:
+
+ const OSSL_ALGORITHM *provider_query_operation(void *provctx,
+ int operation_id,
+ const int *no_store);
+
+I<provctx> is the provider specific context that was passed back by
+the initialization function.
+
+I<operation_id> is an operation identity (see L</Operations> below).
+
+I<no_store> is a flag back to the OpenSSL libraries which, when
+nonzero, signifies that the OpenSSL libraries will not store a
+reference to the returned data in their internal store of
+implementations.
+
+The returned L<OSSL_ALGORITHM(3)> is the foundation of any OpenSSL
+library API that uses providers for their implementation, most
+commonly in the I<fetching> type of functions
+(see L<crypto(7)/ALGORITHM FETCHING>).
+
+=head2 Operations
+
+Operations are referred to with numbers, via macros with names
+starting with C<OSSL_OP_>.
+
+With each operation comes a set of defined function types that a
+provider may or may not offer, depending on its needs.
+
+Currently available operations are:
+
+=over 4
+
+=item Digests
+
+In the OpenSSL libraries, the corresponding method object is
+B<EVP_MD>.
+The number for this operation is B<OSSL_OP_DIGEST>.
+The functions the provider can offer are described in
+L<provider-digest(7)>.
+
+=item Symmetric ciphers
+
+In the OpenSSL libraries, the corresponding method object is
+B<EVP_CIPHER>.
+The number for this operation is B<OSSL_OP_CIPHER>.
+The functions the provider can offer are described in
+L<provider-cipher(7)>.
+
+=item Message Authentication Code (MAC)
+
+In the OpenSSL libraries, the corresponding method object is
+B<EVP_MAC>.
+The number for this operation is B<OSSL_OP_MAC>.
+The functions the provider can offer are described in
+L<provider-mac(7)>.
+
+=item Key Derivation Function (KDF)
+
+In the OpenSSL libraries, the corresponding method object is
+B<EVP_KDF>.
+The number for this operation is B<OSSL_OP_KDF>.
+The functions the provider can offer are described in
+L<provider-kdf(7)>.
+
+=item Key Exchange
+
+In the OpenSSL libraries, the corresponding method object is
+B<EVP_KEYEXCH>.
+The number for this operation is B<OSSL_OP_KEYEXCH>.
+The functions the provider can offer are described in
+L<provider-keyexch(7)>.
+
+=item Asymmetric Ciphers
+
+In the OpenSSL libraries, the corresponding method object is
+B<EVP_ASYM_CIPHER>.
+The number for this operation is B<OSSL_OP_ASYM_CIPHER>.
+The functions the provider can offer are described in
+L<provider-asym_cipher(7)>.
+
+=item Asymmetric Key Encapsulation
+
+In the OpenSSL libraries, the corresponding method object is B<EVP_KEM>.
+The number for this operation is B<OSSL_OP_KEM>.
+The functions the provider can offer are described in L<provider-kem(7)>.
+
+=item Encoding
+
+In the OpenSSL libraries, the corresponding method object is
+B<OSSL_ENCODER>.
+The number for this operation is B<OSSL_OP_ENCODER>.
+The functions the provider can offer are described in
+L<provider-encoder(7)>.
+
+=item Decoding
+
+In the OpenSSL libraries, the corresponding method object is
+B<OSSL_DECODER>.
+The number for this operation is B<OSSL_OP_DECODER>.
+The functions the provider can offer are described in
+L<provider-decoder(7)>.
+
+=item Random Number Generation
+
+The number for this operation is B<OSSL_OP_RAND>.
+The functions the provider can offer for random number generation are described
+in L<provider-rand(7)>.
+
+=item Key Management
+
+The number for this operation is B<OSSL_OP_KEYMGMT>.
+The functions the provider can offer for key management are described in
+L<provider-keymgmt(7)>.
+
+=item Signing and Signature Verification
+
+The number for this operation is B<OSSL_OP_SIGNATURE>.
+The functions the provider can offer for digital signatures are described in
+L<provider-signature(7)>.
+
+=item Store Management
+
+The number for this operation is B<OSSL_OP_STORE>.
+The functions the provider can offer for store management are described in
+L<provider-storemgmt(7)>.
+
+=back
+
+=head3 Algorithm naming
+
+Algorithm names are case insensitive. Any particular algorithm can have multiple
+aliases associated with it. The canonical OpenSSL naming scheme follows this
+format:
+
+ALGNAME[VERSION?][-SUBNAME[VERSION?]?][-SIZE?][-MODE?]
+
+VERSION is only present if there are multiple versions of an algorithm (e.g.
+MD2, MD4, MD5). It may be omitted if there is only one version.
+
+SUBNAME may be present where multiple algorithms are combined together,
+e.g. MD5-SHA1.
+
+SIZE is only present if multiple versions of an algorithm exist with different
+sizes (e.g. AES-128-CBC, AES-256-CBC)
+
+MODE is only present where applicable.
+
+Other aliases may exist for example where standards bodies or common practice
+use alternative names or names that OpenSSL has used historically.
+
+=head1 OPENSSL PROVIDERS
+
+OpenSSL provides a number of its own providers. These are the default, base,
+fips, legacy and null providers. See L<crypto(7)> for an overview of these
+providers.
+
+=head1 SEE ALSO
+
+L<EVP_DigestInit_ex(3)>, L<EVP_EncryptInit_ex(3)>,
+L<OSSL_LIB_CTX(3)>,
+L<EVP_set_default_properties(3)>,
+L<EVP_MD_fetch(3)>,
+L<EVP_CIPHER_fetch(3)>,
+L<EVP_KEYMGMT_fetch(3)>,
+L<openssl-core.h(7)>,
+L<provider-base(7)>,
+L<provider-digest(7)>,
+L<provider-cipher(7)>,
+L<provider-keyexch(7)>
+
+=head1 HISTORY
+
+The concept of providers and everything surrounding them was
+introduced in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/proxy-certificates.pod b/doc/man7/proxy-certificates.pod
index df5ee1b4b518..0a637f25df16 100644
--- a/doc/man7/proxy-certificates.pod
+++ b/doc/man7/proxy-certificates.pod
@@ -57,24 +57,22 @@ See L</NOTES> for a discussion on this requirement.
Creating proxy certificates can be done using the L<openssl-x509(1)>
command, with some extra extensions:
- [ v3_proxy ]
+ [ proxy ]
# A proxy certificate MUST NEVER be a CA certificate.
- basicConstraints=CA:FALSE
-
+ basicConstraints = CA:FALSE
# Usual authority key ID
- authorityKeyIdentifier=keyid,issuer:always
-
+ authorityKeyIdentifier = keyid,issuer:always
# The extension which marks this certificate as a proxy
- proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:1,policy:text:AB
+ proxyCertInfo = critical,language:id-ppl-anyLanguage,pathlen:1,policy:text:AB
It's also possible to specify the proxy extension in a separate section:
- proxyCertInfo=critical,@proxy_ext
+ proxyCertInfo = critical,@proxy_ext
[ proxy_ext ]
- language=id-ppl-anyLanguage
- pathlen=0
- policy=text:BC
+ language = id-ppl-anyLanguage
+ pathlen = 0
+ policy = text:BC
The policy value has a specific syntax, I<syntag>:I<string>, where the
I<syntag> determines what will be done with the string. The following
@@ -99,12 +97,12 @@ colons between each byte (every second hex digit):
indicates that the text of the policy should be taken from a file.
The string is then a filename. This is useful for policies that are
-large (more than a few lines, e.g. XML documents).
+more than a few lines, such as XML or other markup.
=back
-I<NOTE: The proxy policy value is what determines the rights granted
-to the process during the proxy certificate. It's up to the
+Note that the proxy policy value is what determines the rights granted
+to the process during the proxy certificate, and it is up to the
application to interpret and combine these policies.>
With a proxy extension, creating a proxy certificate is a matter of
@@ -112,23 +110,23 @@ two commands:
openssl req -new -config proxy.cnf \
-out proxy.req -keyout proxy.key \
- -subj "/DC=org/DC=openssl/DC=users/CN=proxy 1"
+ -subj "/DC=org/DC=openssl/DC=users/CN=proxy"
openssl x509 -req -CAcreateserial -in proxy.req -out proxy.crt \
-CA user.crt -CAkey user.key -days 7 \
- -extfile proxy.cnf -extensions v3_proxy1
+ -extfile proxy.cnf -extensions proxy
You can also create a proxy certificate using another proxy
-certificate as issuer (note: using a different configuration
-section for the proxy extensions):
+certificate as issuer. Note that this example uses a different
+configuration section for the proxy extensions:
openssl req -new -config proxy.cnf \
-out proxy2.req -keyout proxy2.key \
- -subj "/DC=org/DC=openssl/DC=users/CN=proxy 1/CN=proxy 2"
+ -subj "/DC=org/DC=openssl/DC=users/CN=proxy/CN=proxy 2"
openssl x509 -req -CAcreateserial -in proxy2.req -out proxy2.crt \
-CA proxy.crt -CAkey proxy.key -days 7 \
- -extfile proxy.cnf -extensions v3_proxy2
+ -extfile proxy.cnf -extensions proxy_2
=head2 Using proxy certs in applications
@@ -217,7 +215,7 @@ The following skeleton code can be used as a starting point:
* bottom. You get the CA root first, followed by the
* possible chain of intermediate CAs, followed by the EE
* certificate, followed by the possible proxy
- * certificates.
+ * certificates.
*/
X509 *xs = X509_STORE_CTX_get_current_cert(ctx);
@@ -236,7 +234,7 @@ The following skeleton code can be used as a starting point:
* by pulling them from some database. If there
* are none to be found, clear all rights (making
* this and any subsequent proxy certificate void
- * of any rights).
+ * of any rights).
*/
memset(rights->rights, 0, sizeof(rights->rights));
break;
@@ -353,7 +351,7 @@ L<RFC 3820|https://tools.ietf.org/html/rfc3820>
=head1 COPYRIGHT
-Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
diff --git a/doc/man7/scrypt.pod b/doc/man7/scrypt.pod
deleted file mode 100644
index a005133747c6..000000000000
--- a/doc/man7/scrypt.pod
+++ /dev/null
@@ -1,115 +0,0 @@
-=pod
-
-=head1 NAME
-
-scrypt - EVP_PKEY scrypt KDF support
-
-=head1 DESCRIPTION
-
-The EVP_PKEY_SCRYPT algorithm implements the scrypt password based key
-derivation function, as described in RFC 7914. It is memory-hard in the sense
-that it deliberately requires a significant amount of RAM for efficient
-computation. The intention of this is to render brute forcing of passwords on
-systems that lack large amounts of main memory (such as GPUs or ASICs)
-computationally infeasible.
-
-scrypt provides three work factors that can be customized: N, r and p. N, which
-has to be a positive power of two, is the general work factor and scales CPU
-time in an approximately linear fashion. r is the block size of the internally
-used hash function and p is the parallelization factor. Both r and p need to be
-greater than zero. The amount of RAM that scrypt requires for its computation
-is roughly (128 * N * r * p) bytes.
-
-In the original paper of Colin Percival ("Stronger Key Derivation via
-Sequential Memory-Hard Functions", 2009), the suggested values that give a
-computation time of less than 5 seconds on a 2.5 GHz Intel Core 2 Duo are N =
-2^20 = 1048576, r = 8, p = 1. Consequently, the required amount of memory for
-this computation is roughly 1 GiB. On a more recent CPU (Intel i7-5930K at 3.5
-GHz), this computation takes about 3 seconds. When N, r or p are not specified,
-they default to 1048576, 8, and 1, respectively. The default amount of RAM that
-may be used by scrypt defaults to 1025 MiB.
-
-=head1 NOTES
-
-A context for scrypt can be obtained by calling:
-
- EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SCRYPT, NULL);
-
-The output length of an scrypt key derivation is specified via the
-length parameter to the L<EVP_PKEY_derive(3)> function.
-
-=head1 EXAMPLES
-
-This example derives a 64-byte long test vector using scrypt using the password
-"password", salt "NaCl" and N = 1024, r = 8, p = 16.
-
- EVP_PKEY_CTX *pctx;
- unsigned char out[64];
-
- size_t outlen = sizeof(out);
- pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SCRYPT, NULL);
-
- if (EVP_PKEY_derive_init(pctx) <= 0) {
- error("EVP_PKEY_derive_init");
- }
- if (EVP_PKEY_CTX_set1_pbe_pass(pctx, "password", 8) <= 0) {
- error("EVP_PKEY_CTX_set1_pbe_pass");
- }
- if (EVP_PKEY_CTX_set1_scrypt_salt(pctx, "NaCl", 4) <= 0) {
- error("EVP_PKEY_CTX_set1_scrypt_salt");
- }
- if (EVP_PKEY_CTX_set_scrypt_N(pctx, 1024) <= 0) {
- error("EVP_PKEY_CTX_set_scrypt_N");
- }
- if (EVP_PKEY_CTX_set_scrypt_r(pctx, 8) <= 0) {
- error("EVP_PKEY_CTX_set_scrypt_r");
- }
- if (EVP_PKEY_CTX_set_scrypt_p(pctx, 16) <= 0) {
- error("EVP_PKEY_CTX_set_scrypt_p");
- }
- if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) {
- error("EVP_PKEY_derive");
- }
-
- {
- const unsigned char expected[sizeof(out)] = {
- 0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00,
- 0x78, 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe,
- 0x7c, 0x6a, 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30,
- 0xe7, 0x73, 0x76, 0x63, 0x4b, 0x37, 0x31, 0x62,
- 0x2e, 0xaf, 0x30, 0xd9, 0x2e, 0x22, 0xa3, 0x88,
- 0x6f, 0xf1, 0x09, 0x27, 0x9d, 0x98, 0x30, 0xda,
- 0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, 0xee, 0x6d,
- 0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, 0x40
- };
-
- assert(!memcmp(out, expected, sizeof(out)));
- }
-
- EVP_PKEY_CTX_free(pctx);
-
-=head1 CONFORMING TO
-
-RFC 7914
-
-=head1 SEE ALSO
-
-L<EVP_PKEY_CTX_set1_scrypt_salt(3)>,
-L<EVP_PKEY_CTX_set_scrypt_N(3)>,
-L<EVP_PKEY_CTX_set_scrypt_r(3)>,
-L<EVP_PKEY_CTX_set_scrypt_p(3)>,
-L<EVP_PKEY_CTX_set_scrypt_maxmem_bytes(3)>,
-L<EVP_PKEY_CTX_new(3)>,
-L<EVP_PKEY_CTX_ctrl_str(3)>,
-L<EVP_PKEY_derive(3)>
-
-=head1 COPYRIGHT
-
-Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the OpenSSL license (the "License"). You may not use
-this file except in compliance with the License. You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man7/ssl.pod b/doc/man7/ssl.pod
index d439860b5b5b..7aff45c5ccd1 100644
--- a/doc/man7/ssl.pod
+++ b/doc/man7/ssl.pod
@@ -10,9 +10,11 @@ See the individual manual pages for details.
=head1 DESCRIPTION
-The OpenSSL B<ssl> library implements the Secure Sockets Layer (SSL v2/v3) and
-Transport Layer Security (TLS v1) protocols. It provides a rich API which is
-documented here.
+The OpenSSL B<ssl> library implements several versions of the
+Secure Sockets Layer, Transport Layer Security, and Datagram Transport Layer
+Security protocols.
+This page gives a brief overview of the extensive API and data types
+provided by the library.
An B<SSL_CTX> object is created as a framework to establish
TLS/SSL enabled connections (see L<SSL_CTX_new(3)>).
@@ -35,8 +37,7 @@ TLS/SSL connection.
=head1 DATA STRUCTURES
-Currently the OpenSSL B<ssl> library functions deals with the following data
-structures:
+Here are some of the main data structures in the library.
=over 4
@@ -73,7 +74,6 @@ links to mostly all other structures.
=back
-
=head1 HEADER FILES
Currently the OpenSSL B<ssl> library provides the following C header files
@@ -81,761 +81,34 @@ containing the prototypes for the data structures and functions:
=over 4
-=item B<ssl.h>
+=item F<< <openssl/ssl.h> >>
This is the common header file for the SSL/TLS API. Include it into your
program to make the API of the B<ssl> library available. It internally
includes both more private SSL headers and headers from the B<crypto> library.
Whenever you need hard-core details on the internals of the SSL API, look
inside this header file.
+This file also includes the others listed below.
-=item B<ssl2.h>
+=item F<< <openssl/ssl2.h> >>
Unused. Present for backwards compatibility only.
-=item B<ssl3.h>
+=item F<< <openssl/ssl3.h> >>
This is the sub header file dealing with the SSLv3 protocol only.
-I<Usually you don't have to include it explicitly because
-it's already included by ssl.h>.
-=item B<tls1.h>
+=item F<< <openssl/tls1.h> >>
This is the sub header file dealing with the TLSv1 protocol only.
-I<Usually you don't have to include it explicitly because
-it's already included by ssl.h>.
-
-=back
-
-=head1 API FUNCTIONS
-
-Currently the OpenSSL B<ssl> library exports 214 API functions.
-They are documented in the following:
-
-=head2 Dealing with Protocol Methods
-
-Here we document the various API functions which deal with the SSL/TLS
-protocol methods defined in B<SSL_METHOD> structures.
-
-=over 4
-
-=item const SSL_METHOD *B<TLS_method>(void);
-
-Constructor for the I<version-flexible> SSL_METHOD structure for clients,
-servers or both.
-See L<SSL_CTX_new(3)> for details.
-
-=item const SSL_METHOD *B<TLS_client_method>(void);
-
-Constructor for the I<version-flexible> SSL_METHOD structure for clients.
-Must be used to support the TLSv1.3 protocol.
-
-=item const SSL_METHOD *B<TLS_server_method>(void);
-
-Constructor for the I<version-flexible> SSL_METHOD structure for servers.
-Must be used to support the TLSv1.3 protocol.
-
-=item const SSL_METHOD *B<TLSv1_2_method>(void);
-
-Constructor for the TLSv1.2 SSL_METHOD structure for clients, servers or both.
-
-=item const SSL_METHOD *B<TLSv1_2_client_method>(void);
-
-Constructor for the TLSv1.2 SSL_METHOD structure for clients.
-
-=item const SSL_METHOD *B<TLSv1_2_server_method>(void);
-
-Constructor for the TLSv1.2 SSL_METHOD structure for servers.
-
-=item const SSL_METHOD *B<TLSv1_1_method>(void);
-
-Constructor for the TLSv1.1 SSL_METHOD structure for clients, servers or both.
-
-=item const SSL_METHOD *B<TLSv1_1_client_method>(void);
-
-Constructor for the TLSv1.1 SSL_METHOD structure for clients.
-
-=item const SSL_METHOD *B<TLSv1_1_server_method>(void);
-
-Constructor for the TLSv1.1 SSL_METHOD structure for servers.
-
-=item const SSL_METHOD *B<TLSv1_method>(void);
-
-Constructor for the TLSv1 SSL_METHOD structure for clients, servers or both.
-
-=item const SSL_METHOD *B<TLSv1_client_method>(void);
-
-Constructor for the TLSv1 SSL_METHOD structure for clients.
-
-=item const SSL_METHOD *B<TLSv1_server_method>(void);
-
-Constructor for the TLSv1 SSL_METHOD structure for servers.
-
-=item const SSL_METHOD *B<SSLv3_method>(void);
-
-Constructor for the SSLv3 SSL_METHOD structure for clients, servers or both.
-
-=item const SSL_METHOD *B<SSLv3_client_method>(void);
-
-Constructor for the SSLv3 SSL_METHOD structure for clients.
-
-=item const SSL_METHOD *B<SSLv3_server_method>(void);
-
-Constructor for the SSLv3 SSL_METHOD structure for servers.
-
-=back
-
-=head2 Dealing with Ciphers
-
-Here we document the various API functions which deal with the SSL/TLS
-ciphers defined in B<SSL_CIPHER> structures.
-
-=over 4
-
-=item char *B<SSL_CIPHER_description>(SSL_CIPHER *cipher, char *buf, int len);
-
-Write a string to I<buf> (with a maximum size of I<len>) containing a human
-readable description of I<cipher>. Returns I<buf>.
-
-=item int B<SSL_CIPHER_get_bits>(SSL_CIPHER *cipher, int *alg_bits);
-
-Determine the number of bits in I<cipher>. Because of export crippled ciphers
-there are two bits: The bits the algorithm supports in general (stored to
-I<alg_bits>) and the bits which are actually used (the return value).
-
-=item const char *B<SSL_CIPHER_get_name>(SSL_CIPHER *cipher);
-
-Return the internal name of I<cipher> as a string. These are the various
-strings defined by the I<SSL3_TXT_xxx> and I<TLS1_TXT_xxx>
-definitions in the header files.
-
-=item const char *B<SSL_CIPHER_get_version>(SSL_CIPHER *cipher);
-
-Returns a string like "C<SSLv3>" or "C<TLSv1.2>" which indicates the
-SSL/TLS protocol version to which I<cipher> belongs (i.e. where it was defined
-in the specification the first time).
-
-=back
-
-=head2 Dealing with Protocol Contexts
-
-Here we document the various API functions which deal with the SSL/TLS
-protocol context defined in the B<SSL_CTX> structure.
-
-=over 4
-
-=item int B<SSL_CTX_add_client_CA>(SSL_CTX *ctx, X509 *x);
-
-=item long B<SSL_CTX_add_extra_chain_cert>(SSL_CTX *ctx, X509 *x509);
-
-=item int B<SSL_CTX_add_session>(SSL_CTX *ctx, SSL_SESSION *c);
-
-=item int B<SSL_CTX_check_private_key>(const SSL_CTX *ctx);
-
-=item long B<SSL_CTX_ctrl>(SSL_CTX *ctx, int cmd, long larg, char *parg);
-
-=item void B<SSL_CTX_flush_sessions>(SSL_CTX *s, long t);
-
-=item void B<SSL_CTX_free>(SSL_CTX *a);
-
-=item char *B<SSL_CTX_get_app_data>(SSL_CTX *ctx);
-
-=item X509_STORE *B<SSL_CTX_get_cert_store>(SSL_CTX *ctx);
-
-=item STACK *B<SSL_CTX_get_ciphers>(const SSL_CTX *ctx);
-
-=item STACK *B<SSL_CTX_get_client_CA_list>(const SSL_CTX *ctx);
-
-=item int (*B<SSL_CTX_get_client_cert_cb>(SSL_CTX *ctx))(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
-
-=item void B<SSL_CTX_get_default_read_ahead>(SSL_CTX *ctx);
-
-=item char *B<SSL_CTX_get_ex_data>(const SSL_CTX *s, int idx);
-
-=item int B<SSL_CTX_get_ex_new_index>(long argl, char *argp, int (*new_func);(void), int (*dup_func)(void), void (*free_func)(void))
-
-=item void (*B<SSL_CTX_get_info_callback>(SSL_CTX *ctx))(SSL *ssl, int cb, int ret);
-
-=item int B<SSL_CTX_get_quiet_shutdown>(const SSL_CTX *ctx);
-
-=item void B<SSL_CTX_get_read_ahead>(SSL_CTX *ctx);
-
-=item int B<SSL_CTX_get_session_cache_mode>(SSL_CTX *ctx);
-
-=item long B<SSL_CTX_get_timeout>(const SSL_CTX *ctx);
-
-=item int (*B<SSL_CTX_get_verify_callback>(const SSL_CTX *ctx))(int ok, X509_STORE_CTX *ctx);
-
-=item int B<SSL_CTX_get_verify_mode>(SSL_CTX *ctx);
-
-=item int B<SSL_CTX_load_verify_locations>(SSL_CTX *ctx, const char *CAfile, const char *CApath);
-
-=item SSL_CTX *B<SSL_CTX_new>(const SSL_METHOD *meth);
-
-=item int SSL_CTX_up_ref(SSL_CTX *ctx);
-
-=item int B<SSL_CTX_remove_session>(SSL_CTX *ctx, SSL_SESSION *c);
-
-=item int B<SSL_CTX_sess_accept>(SSL_CTX *ctx);
-
-=item int B<SSL_CTX_sess_accept_good>(SSL_CTX *ctx);
-
-=item int B<SSL_CTX_sess_accept_renegotiate>(SSL_CTX *ctx);
-
-=item int B<SSL_CTX_sess_cache_full>(SSL_CTX *ctx);
-
-=item int B<SSL_CTX_sess_cb_hits>(SSL_CTX *ctx);
-
-=item int B<SSL_CTX_sess_connect>(SSL_CTX *ctx);
-
-=item int B<SSL_CTX_sess_connect_good>(SSL_CTX *ctx);
-
-=item int B<SSL_CTX_sess_connect_renegotiate>(SSL_CTX *ctx);
-
-=item int B<SSL_CTX_sess_get_cache_size>(SSL_CTX *ctx);
-
-=item SSL_SESSION *(*B<SSL_CTX_sess_get_get_cb>(SSL_CTX *ctx))(SSL *ssl, unsigned char *data, int len, int *copy);
-
-=item int (*B<SSL_CTX_sess_get_new_cb>(SSL_CTX *ctx)(SSL *ssl, SSL_SESSION *sess);
-
-=item void (*B<SSL_CTX_sess_get_remove_cb>(SSL_CTX *ctx)(SSL_CTX *ctx, SSL_SESSION *sess);
-
-=item int B<SSL_CTX_sess_hits>(SSL_CTX *ctx);
-
-=item int B<SSL_CTX_sess_misses>(SSL_CTX *ctx);
-
-=item int B<SSL_CTX_sess_number>(SSL_CTX *ctx);
-
-=item void B<SSL_CTX_sess_set_cache_size>(SSL_CTX *ctx, t);
-
-=item void B<SSL_CTX_sess_set_get_cb>(SSL_CTX *ctx, SSL_SESSION *(*cb)(SSL *ssl, unsigned char *data, int len, int *copy));
-
-=item void B<SSL_CTX_sess_set_new_cb>(SSL_CTX *ctx, int (*cb)(SSL *ssl, SSL_SESSION *sess));
-
-=item void B<SSL_CTX_sess_set_remove_cb>(SSL_CTX *ctx, void (*cb)(SSL_CTX *ctx, SSL_SESSION *sess));
-
-=item int B<SSL_CTX_sess_timeouts>(SSL_CTX *ctx);
-
-=item LHASH *B<SSL_CTX_sessions>(SSL_CTX *ctx);
-
-=item int B<SSL_CTX_set_app_data>(SSL_CTX *ctx, void *arg);
-
-=item void B<SSL_CTX_set_cert_store>(SSL_CTX *ctx, X509_STORE *cs);
-
-=item void B<SSL_CTX_set1_cert_store>(SSL_CTX *ctx, X509_STORE *cs);
-
-=item void B<SSL_CTX_set_cert_verify_cb>(SSL_CTX *ctx, int (*cb)(), char *arg)
-
-=item int B<SSL_CTX_set_cipher_list>(SSL_CTX *ctx, char *str);
-
-=item void B<SSL_CTX_set_client_CA_list>(SSL_CTX *ctx, STACK *list);
-
-=item void B<SSL_CTX_set_client_cert_cb>(SSL_CTX *ctx, int (*cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey));
-
-=item int B<SSL_CTX_set_ct_validation_callback>(SSL_CTX *ctx, ssl_ct_validation_cb callback, void *arg);
-
-=item void B<SSL_CTX_set_default_passwd_cb>(SSL_CTX *ctx, int (*cb);(void))
-
-=item void B<SSL_CTX_set_default_read_ahead>(SSL_CTX *ctx, int m);
-
-=item int B<SSL_CTX_set_default_verify_paths>(SSL_CTX *ctx);
-
-Use the default paths to locate trusted CA certificates. There is one default
-directory path and one default file path. Both are set via this call.
-
-=item int B<SSL_CTX_set_default_verify_dir>(SSL_CTX *ctx)
-
-Use the default directory path to locate trusted CA certificates.
-
-=item int B<SSL_CTX_set_default_verify_file>(SSL_CTX *ctx)
-
-Use the file path to locate trusted CA certificates.
-
-=item int B<SSL_CTX_set_ex_data>(SSL_CTX *s, int idx, char *arg);
-
-=item void B<SSL_CTX_set_info_callback>(SSL_CTX *ctx, void (*cb)(SSL *ssl, int cb, int ret));
-
-=item void B<SSL_CTX_set_msg_callback>(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
-
-=item void B<SSL_CTX_set_msg_callback_arg>(SSL_CTX *ctx, void *arg);
-
-=item unsigned long B<SSL_CTX_clear_options>(SSL_CTX *ctx, unsigned long op);
-
-=item unsigned long B<SSL_CTX_get_options>(SSL_CTX *ctx);
-
-=item unsigned long B<SSL_CTX_set_options>(SSL_CTX *ctx, unsigned long op);
-
-=item void B<SSL_CTX_set_quiet_shutdown>(SSL_CTX *ctx, int mode);
-
-=item void B<SSL_CTX_set_read_ahead>(SSL_CTX *ctx, int m);
-
-=item void B<SSL_CTX_set_session_cache_mode>(SSL_CTX *ctx, int mode);
-
-=item int B<SSL_CTX_set_ssl_version>(SSL_CTX *ctx, const SSL_METHOD *meth);
-
-=item void B<SSL_CTX_set_timeout>(SSL_CTX *ctx, long t);
-
-=item long B<SSL_CTX_set_tmp_dh>(SSL_CTX* ctx, DH *dh);
-
-=item long B<SSL_CTX_set_tmp_dh_callback>(SSL_CTX *ctx, DH *(*cb)(void));
-
-=item void B<SSL_CTX_set_verify>(SSL_CTX *ctx, int mode, int (*cb);(void))
-
-=item int B<SSL_CTX_use_PrivateKey>(SSL_CTX *ctx, EVP_PKEY *pkey);
-
-=item int B<SSL_CTX_use_PrivateKey_ASN1>(int type, SSL_CTX *ctx, unsigned char *d, long len);
-
-=item int B<SSL_CTX_use_PrivateKey_file>(SSL_CTX *ctx, const char *file, int type);
-
-=item int B<SSL_CTX_use_RSAPrivateKey>(SSL_CTX *ctx, RSA *rsa);
-
-=item int B<SSL_CTX_use_RSAPrivateKey_ASN1>(SSL_CTX *ctx, unsigned char *d, long len);
-
-=item int B<SSL_CTX_use_RSAPrivateKey_file>(SSL_CTX *ctx, const char *file, int type);
-
-=item int B<SSL_CTX_use_certificate>(SSL_CTX *ctx, X509 *x);
-
-=item int B<SSL_CTX_use_certificate_ASN1>(SSL_CTX *ctx, int len, unsigned char *d);
-
-=item int B<SSL_CTX_use_certificate_file>(SSL_CTX *ctx, const char *file, int type);
-
-=item int B<SSL_CTX_use_cert_and_key>(SSL_CTX *ctx, X509 *x, EVP_PKEY *pkey, STACK_OF(X509) *chain, int override);
-
-=item X509 *B<SSL_CTX_get0_certificate>(const SSL_CTX *ctx);
-
-=item EVP_PKEY *B<SSL_CTX_get0_privatekey>(const SSL_CTX *ctx);
-
-=item void B<SSL_CTX_set_psk_client_callback>(SSL_CTX *ctx, unsigned int (*callback)(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len));
-
-=item int B<SSL_CTX_use_psk_identity_hint>(SSL_CTX *ctx, const char *hint);
-
-=item void B<SSL_CTX_set_psk_server_callback>(SSL_CTX *ctx, unsigned int (*callback)(SSL *ssl, const char *identity, unsigned char *psk, int max_psk_len));
-
=back
-=head2 Dealing with Sessions
-
-Here we document the various API functions which deal with the SSL/TLS
-sessions defined in the B<SSL_SESSION> structures.
-
-=over 4
-
-=item int B<SSL_SESSION_cmp>(const SSL_SESSION *a, const SSL_SESSION *b);
-
-=item void B<SSL_SESSION_free>(SSL_SESSION *ss);
-
-=item char *B<SSL_SESSION_get_app_data>(SSL_SESSION *s);
-
-=item char *B<SSL_SESSION_get_ex_data>(const SSL_SESSION *s, int idx);
-
-=item int B<SSL_SESSION_get_ex_new_index>(long argl, char *argp, int (*new_func);(void), int (*dup_func)(void), void (*free_func)(void))
-
-=item long B<SSL_SESSION_get_time>(const SSL_SESSION *s);
-
-=item long B<SSL_SESSION_get_timeout>(const SSL_SESSION *s);
-
-=item unsigned long B<SSL_SESSION_hash>(const SSL_SESSION *a);
-
-=item SSL_SESSION *B<SSL_SESSION_new>(void);
-
-=item int B<SSL_SESSION_print>(BIO *bp, const SSL_SESSION *x);
-
-=item int B<SSL_SESSION_print_fp>(FILE *fp, const SSL_SESSION *x);
-
-=item int B<SSL_SESSION_set_app_data>(SSL_SESSION *s, char *a);
-
-=item int B<SSL_SESSION_set_ex_data>(SSL_SESSION *s, int idx, char *arg);
-
-=item long B<SSL_SESSION_set_time>(SSL_SESSION *s, long t);
-
-=item long B<SSL_SESSION_set_timeout>(SSL_SESSION *s, long t);
-
-=back
-
-=head2 Dealing with Connections
-
-Here we document the various API functions which deal with the SSL/TLS
-connection defined in the B<SSL> structure.
-
-=over 4
-
-=item int B<SSL_accept>(SSL *ssl);
-
-=item int B<SSL_add_dir_cert_subjects_to_stack>(STACK *stack, const char *dir);
-
-=item int B<SSL_add_file_cert_subjects_to_stack>(STACK *stack, const char *file);
-
-=item int B<SSL_add_client_CA>(SSL *ssl, X509 *x);
-
-=item char *B<SSL_alert_desc_string>(int value);
-
-=item char *B<SSL_alert_desc_string_long>(int value);
-
-=item char *B<SSL_alert_type_string>(int value);
-
-=item char *B<SSL_alert_type_string_long>(int value);
-
-=item int B<SSL_check_private_key>(const SSL *ssl);
-
-=item void B<SSL_clear>(SSL *ssl);
-
-=item long B<SSL_clear_num_renegotiations>(SSL *ssl);
-
-=item int B<SSL_connect>(SSL *ssl);
-
-=item int B<SSL_copy_session_id>(SSL *t, const SSL *f);
-
-Sets the session details for B<t> to be the same as in B<f>. Returns 1 on
-success or 0 on failure.
-
-=item long B<SSL_ctrl>(SSL *ssl, int cmd, long larg, char *parg);
-
-=item int B<SSL_do_handshake>(SSL *ssl);
-
-=item SSL *B<SSL_dup>(SSL *ssl);
-
-SSL_dup() allows applications to configure an SSL handle for use
-in multiple SSL connections, and then duplicate it prior to initiating
-each connection with the duplicated handle.
-Use of SSL_dup() avoids the need to repeat the configuration of the
-handles for each connection.
-
-For SSL_dup() to work, the connection MUST be in its initial state
-and MUST NOT have not yet have started the SSL handshake.
-For connections that are not in their initial state SSL_dup() just
-increments an internal reference count and returns the I<same>
-handle.
-It may be possible to use L<SSL_clear(3)> to recycle an SSL handle
-that is not in its initial state for re-use, but this is best
-avoided.
-Instead, save and restore the session, if desired, and construct a
-fresh handle for each connection.
-
-=item STACK *B<SSL_dup_CA_list>(STACK *sk);
-
-=item void B<SSL_free>(SSL *ssl);
-
-=item SSL_CTX *B<SSL_get_SSL_CTX>(const SSL *ssl);
-
-=item char *B<SSL_get_app_data>(SSL *ssl);
-
-=item X509 *B<SSL_get_certificate>(const SSL *ssl);
-
-=item const char *B<SSL_get_cipher>(const SSL *ssl);
-
-=item int B<SSL_is_dtls>(const SSL *ssl);
-
-=item int B<SSL_get_cipher_bits>(const SSL *ssl, int *alg_bits);
-
-=item char *B<SSL_get_cipher_list>(const SSL *ssl, int n);
-
-=item char *B<SSL_get_cipher_name>(const SSL *ssl);
-
-=item char *B<SSL_get_cipher_version>(const SSL *ssl);
-
-=item STACK *B<SSL_get_ciphers>(const SSL *ssl);
-
-=item STACK *B<SSL_get_client_CA_list>(const SSL *ssl);
-
-=item SSL_CIPHER *B<SSL_get_current_cipher>(SSL *ssl);
-
-=item long B<SSL_get_default_timeout>(const SSL *ssl);
-
-=item int B<SSL_get_error>(const SSL *ssl, int i);
-
-=item char *B<SSL_get_ex_data>(const SSL *ssl, int idx);
-
-=item int B<SSL_get_ex_data_X509_STORE_CTX_idx>(void);
-
-=item int B<SSL_get_ex_new_index>(long argl, char *argp, int (*new_func);(void), int (*dup_func)(void), void (*free_func)(void))
-
-=item int B<SSL_get_fd>(const SSL *ssl);
-
-=item void (*B<SSL_get_info_callback>(const SSL *ssl);)()
-
-=item int B<SSL_get_key_update_type>(SSL *s);
-
-=item STACK *B<SSL_get_peer_cert_chain>(const SSL *ssl);
-
-=item X509 *B<SSL_get_peer_certificate>(const SSL *ssl);
-
-=item const STACK_OF(SCT) *B<SSL_get0_peer_scts>(SSL *s);
-
-=item EVP_PKEY *B<SSL_get_privatekey>(const SSL *ssl);
-
-=item int B<SSL_get_quiet_shutdown>(const SSL *ssl);
-
-=item BIO *B<SSL_get_rbio>(const SSL *ssl);
-
-=item int B<SSL_get_read_ahead>(const SSL *ssl);
-
-=item SSL_SESSION *B<SSL_get_session>(const SSL *ssl);
-
-=item char *B<SSL_get_shared_ciphers>(const SSL *ssl, char *buf, int size);
-
-=item int B<SSL_get_shutdown>(const SSL *ssl);
-
-=item const SSL_METHOD *B<SSL_get_ssl_method>(SSL *ssl);
-
-=item int B<SSL_get_state>(const SSL *ssl);
-
-=item long B<SSL_get_time>(const SSL *ssl);
-
-=item long B<SSL_get_timeout>(const SSL *ssl);
-
-=item int (*B<SSL_get_verify_callback>(const SSL *ssl))(int, X509_STORE_CTX *)
-
-=item int B<SSL_get_verify_mode>(const SSL *ssl);
-
-=item long B<SSL_get_verify_result>(const SSL *ssl);
-
-=item char *B<SSL_get_version>(const SSL *ssl);
-
-=item BIO *B<SSL_get_wbio>(const SSL *ssl);
-
-=item int B<SSL_in_accept_init>(SSL *ssl);
-
-=item int B<SSL_in_before>(SSL *ssl);
-
-=item int B<SSL_in_connect_init>(SSL *ssl);
-
-=item int B<SSL_in_init>(SSL *ssl);
-
-=item int B<SSL_is_init_finished>(SSL *ssl);
-
-=item int B<SSL_key_update>(SSL *s, int updatetype);
-
-=item STACK *B<SSL_load_client_CA_file>(const char *file);
-
-=item SSL *B<SSL_new>(SSL_CTX *ctx);
-
-=item int SSL_up_ref(SSL *s);
-
-=item long B<SSL_num_renegotiations>(SSL *ssl);
-
-=item int B<SSL_peek>(SSL *ssl, void *buf, int num);
-
-=item int B<SSL_pending>(const SSL *ssl);
-
-=item int B<SSL_read>(SSL *ssl, void *buf, int num);
-
-=item int B<SSL_renegotiate>(SSL *ssl);
-
-=item char *B<SSL_rstate_string>(SSL *ssl);
-
-=item char *B<SSL_rstate_string_long>(SSL *ssl);
-
-=item long B<SSL_session_reused>(SSL *ssl);
-
-=item void B<SSL_set_accept_state>(SSL *ssl);
-
-=item void B<SSL_set_app_data>(SSL *ssl, char *arg);
-
-=item void B<SSL_set_bio>(SSL *ssl, BIO *rbio, BIO *wbio);
-
-=item int B<SSL_set_cipher_list>(SSL *ssl, char *str);
-
-=item void B<SSL_set_client_CA_list>(SSL *ssl, STACK *list);
-
-=item void B<SSL_set_connect_state>(SSL *ssl);
-
-=item int B<SSL_set_ct_validation_callback>(SSL *ssl, ssl_ct_validation_cb callback, void *arg);
-
-=item int B<SSL_set_ex_data>(SSL *ssl, int idx, char *arg);
-
-=item int B<SSL_set_fd>(SSL *ssl, int fd);
-
-=item void B<SSL_set_info_callback>(SSL *ssl, void (*cb);(void))
-
-=item void B<SSL_set_msg_callback>(SSL *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
-
-=item void B<SSL_set_msg_callback_arg>(SSL *ctx, void *arg);
-
-=item unsigned long B<SSL_clear_options>(SSL *ssl, unsigned long op);
-
-=item unsigned long B<SSL_get_options>(SSL *ssl);
-
-=item unsigned long B<SSL_set_options>(SSL *ssl, unsigned long op);
-
-=item void B<SSL_set_quiet_shutdown>(SSL *ssl, int mode);
-
-=item void B<SSL_set_read_ahead>(SSL *ssl, int yes);
-
-=item int B<SSL_set_rfd>(SSL *ssl, int fd);
-
-=item int B<SSL_set_session>(SSL *ssl, SSL_SESSION *session);
-
-=item void B<SSL_set_shutdown>(SSL *ssl, int mode);
-
-=item int B<SSL_set_ssl_method>(SSL *ssl, const SSL_METHOD *meth);
-
-=item void B<SSL_set_time>(SSL *ssl, long t);
-
-=item void B<SSL_set_timeout>(SSL *ssl, long t);
-
-=item void B<SSL_set_verify>(SSL *ssl, int mode, int (*callback);(void))
-
-=item void B<SSL_set_verify_result>(SSL *ssl, long arg);
-
-=item int B<SSL_set_wfd>(SSL *ssl, int fd);
-
-=item int B<SSL_shutdown>(SSL *ssl);
-
-=item OSSL_HANDSHAKE_STATE B<SSL_get_state>(const SSL *ssl);
-
-Returns the current handshake state.
-
-=item char *B<SSL_state_string>(const SSL *ssl);
-
-=item char *B<SSL_state_string_long>(const SSL *ssl);
-
-=item long B<SSL_total_renegotiations>(SSL *ssl);
-
-=item int B<SSL_use_PrivateKey>(SSL *ssl, EVP_PKEY *pkey);
-
-=item int B<SSL_use_PrivateKey_ASN1>(int type, SSL *ssl, unsigned char *d, long len);
-
-=item int B<SSL_use_PrivateKey_file>(SSL *ssl, const char *file, int type);
-
-=item int B<SSL_use_RSAPrivateKey>(SSL *ssl, RSA *rsa);
-
-=item int B<SSL_use_RSAPrivateKey_ASN1>(SSL *ssl, unsigned char *d, long len);
-
-=item int B<SSL_use_RSAPrivateKey_file>(SSL *ssl, const char *file, int type);
-
-=item int B<SSL_use_certificate>(SSL *ssl, X509 *x);
-
-=item int B<SSL_use_certificate_ASN1>(SSL *ssl, int len, unsigned char *d);
-
-=item int B<SSL_use_certificate_file>(SSL *ssl, const char *file, int type);
-
-=item int B<SSL_use_cert_and_key>(SSL *ssl, X509 *x, EVP_PKEY *pkey, STACK_OF(X509) *chain, int override);
-
-=item int B<SSL_version>(const SSL *ssl);
-
-=item int B<SSL_want>(const SSL *ssl);
-
-=item int B<SSL_want_nothing>(const SSL *ssl);
-
-=item int B<SSL_want_read>(const SSL *ssl);
-
-=item int B<SSL_want_write>(const SSL *ssl);
-
-=item int B<SSL_want_x509_lookup>(const SSL *ssl);
-
-=item int B<SSL_write>(SSL *ssl, const void *buf, int num);
-
-=item void B<SSL_set_psk_client_callback>(SSL *ssl, unsigned int (*callback)(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len));
-
-=item int B<SSL_use_psk_identity_hint>(SSL *ssl, const char *hint);
-
-=item void B<SSL_set_psk_server_callback>(SSL *ssl, unsigned int (*callback)(SSL *ssl, const char *identity, unsigned char *psk, int max_psk_len));
-
-=item const char *B<SSL_get_psk_identity_hint>(SSL *ssl);
-
-=item const char *B<SSL_get_psk_identity>(SSL *ssl);
-
-=back
-
-=head1 RETURN VALUES
-
-See the individual manual pages for details.
-
-=head1 SEE ALSO
-
-L<openssl(1)>, L<crypto(7)>,
-L<CRYPTO_get_ex_new_index(3)>,
-L<SSL_accept(3)>, L<SSL_clear(3)>,
-L<SSL_connect(3)>,
-L<SSL_CIPHER_get_name(3)>,
-L<SSL_COMP_add_compression_method(3)>,
-L<SSL_CTX_add_extra_chain_cert(3)>,
-L<SSL_CTX_add_session(3)>,
-L<SSL_CTX_ctrl(3)>,
-L<SSL_CTX_flush_sessions(3)>,
-L<SSL_CTX_get_verify_mode(3)>,
-L<SSL_CTX_load_verify_locations(3)>
-L<SSL_CTX_new(3)>,
-L<SSL_CTX_sess_number(3)>,
-L<SSL_CTX_sess_set_cache_size(3)>,
-L<SSL_CTX_sess_set_get_cb(3)>,
-L<SSL_CTX_sessions(3)>,
-L<SSL_CTX_set_cert_store(3)>,
-L<SSL_CTX_set_cert_verify_callback(3)>,
-L<SSL_CTX_set_cipher_list(3)>,
-L<SSL_CTX_set_client_CA_list(3)>,
-L<SSL_CTX_set_client_cert_cb(3)>,
-L<SSL_CTX_set_default_passwd_cb(3)>,
-L<SSL_CTX_set_generate_session_id(3)>,
-L<SSL_CTX_set_info_callback(3)>,
-L<SSL_CTX_set_max_cert_list(3)>,
-L<SSL_CTX_set_mode(3)>,
-L<SSL_CTX_set_msg_callback(3)>,
-L<SSL_CTX_set_options(3)>,
-L<SSL_CTX_set_quiet_shutdown(3)>,
-L<SSL_CTX_set_read_ahead(3)>,
-L<SSL_CTX_set_security_level(3)>,
-L<SSL_CTX_set_session_cache_mode(3)>,
-L<SSL_CTX_set_session_id_context(3)>,
-L<SSL_CTX_set_ssl_version(3)>,
-L<SSL_CTX_set_timeout(3)>,
-L<SSL_CTX_set_tmp_dh_callback(3)>,
-L<SSL_CTX_set_verify(3)>,
-L<SSL_CTX_use_certificate(3)>,
-L<SSL_alert_type_string(3)>,
-L<SSL_do_handshake(3)>,
-L<SSL_enable_ct(3)>,
-L<SSL_get_SSL_CTX(3)>,
-L<SSL_get_ciphers(3)>,
-L<SSL_get_client_CA_list(3)>,
-L<SSL_get_default_timeout(3)>,
-L<SSL_get_error(3)>,
-L<SSL_get_ex_data_X509_STORE_CTX_idx(3)>,
-L<SSL_get_fd(3)>,
-L<SSL_get_peer_cert_chain(3)>,
-L<SSL_get_rbio(3)>,
-L<SSL_get_session(3)>,
-L<SSL_get_verify_result(3)>,
-L<SSL_get_version(3)>,
-L<SSL_load_client_CA_file(3)>,
-L<SSL_new(3)>,
-L<SSL_pending(3)>,
-L<SSL_read_ex(3)>,
-L<SSL_read(3)>,
-L<SSL_rstate_string(3)>,
-L<SSL_session_reused(3)>,
-L<SSL_set_bio(3)>,
-L<SSL_set_connect_state(3)>,
-L<SSL_set_fd(3)>,
-L<SSL_set_session(3)>,
-L<SSL_set_shutdown(3)>,
-L<SSL_shutdown(3)>,
-L<SSL_state_string(3)>,
-L<SSL_want(3)>,
-L<SSL_write_ex(3)>,
-L<SSL_write(3)>,
-L<SSL_SESSION_free(3)>,
-L<SSL_SESSION_get_time(3)>,
-L<d2i_SSL_SESSION(3)>,
-L<SSL_CTX_set_psk_client_callback(3)>,
-L<SSL_CTX_use_psk_identity_hint(3)>,
-L<SSL_get_psk_identity(3)>,
-L<DTLSv1_listen(3)>
-
-=head1 HISTORY
-
-B<SSLv2_client_method>, B<SSLv2_server_method> and B<SSLv2_method> were removed
-in OpenSSL 1.1.0.
-
-The return type of B<SSL_copy_session_id> was changed from void to int in
-OpenSSL 1.1.0.
-
=head1 COPYRIGHT
Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/man7/x509.pod b/doc/man7/x509.pod
index 7274e5ce9552..7ce0d7fa4408 100644
--- a/doc/man7/x509.pod
+++ b/doc/man7/x509.pod
@@ -52,20 +52,20 @@ L<X509_NAME_add_entry_by_txt(3)>,
L<X509_NAME_add_entry_by_NID(3)>,
L<X509_NAME_print_ex(3)>,
L<X509_NAME_new(3)>,
+L<PEM_X509_INFO_read(3)>,
L<d2i_X509(3)>,
L<d2i_X509_ALGOR(3)>,
L<d2i_X509_CRL(3)>,
L<d2i_X509_NAME(3)>,
L<d2i_X509_REQ(3)>,
L<d2i_X509_SIG(3)>,
-L<X509v3(3)>,
L<crypto(7)>
=head1 COPYRIGHT
Copyright 2003-2021 The OpenSSL Project Authors. All Rights Reserved.
-Licensed under the OpenSSL license (the "License"). You may not use
+Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
diff --git a/doc/perlvars.pm b/doc/perlvars.pm
new file mode 100644
index 000000000000..f4c20aa3925a
--- /dev/null
+++ b/doc/perlvars.pm
@@ -0,0 +1,224 @@
+#! /usr/bin/env perl
+# Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+
+# Set some Perl variables for use by util/dofile.pl when processing
+# POD files (mainly man1).
+
+use configdata;
+
+# Verify options
+$OpenSSL::safe::opt_v_synopsis = ""
+. "[B<-allow_proxy_certs>]\n"
+. "[B<-attime> I<timestamp>]\n"
+. "[B<-no_check_time>]\n"
+. "[B<-check_ss_sig>]\n"
+. "[B<-crl_check>]\n"
+. "[B<-crl_check_all>]\n"
+. "[B<-explicit_policy>]\n"
+. "[B<-extended_crl>]\n"
+. "[B<-ignore_critical>]\n"
+. "[B<-inhibit_any>]\n"
+. "[B<-inhibit_map>]\n"
+. "[B<-partial_chain>]\n"
+. "[B<-policy> I<arg>]\n"
+. "[B<-policy_check>]\n"
+. "[B<-policy_print>]\n"
+. "[B<-purpose> I<purpose>]\n"
+. "[B<-suiteB_128>]\n"
+. "[B<-suiteB_128_only>]\n"
+. "[B<-suiteB_192>]\n"
+. "[B<-trusted_first>]\n"
+. "[B<-no_alt_chains>]\n"
+. "[B<-use_deltas>]\n"
+. "[B<-auth_level> I<num>]\n"
+. "[B<-verify_depth> I<num>]\n"
+. "[B<-verify_email> I<email>]\n"
+. "[B<-verify_hostname> I<hostname>]\n"
+. "[B<-verify_ip> I<ip>]\n"
+. "[B<-verify_name> I<name>]\n"
+. "[B<-x509_strict>]\n"
+. "[B<-issuer_checks>]";
+$OpenSSL::safe::opt_v_item = ""
+. "=item B<-allow_proxy_certs>, B<-attime>, B<-no_check_time>,\n"
+. "B<-check_ss_sig>, B<-crl_check>, B<-crl_check_all>,\n"
+. "B<-explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,\n"
+. "B<-inhibit_map>, B<-no_alt_chains>, B<-partial_chain>, B<-policy>,\n"
+. "B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,\n"
+. "B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,\n"
+. "B<-auth_level>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,\n"
+. "B<-verify_ip>, B<-verify_name>, B<-x509_strict> B<-issuer_checks>\n"
+. "\n"
+. "Set various options of certificate chain verification.\n"
+. "See L<openssl-verification-options(1)/Verification Options> for details.";
+
+
+# Extended validation options.
+$OpenSSL::safe::opt_x_synopsis = ""
+. "[B<-xkey> I<infile>]\n"
+. "[B<-xcert> I<file>]\n"
+. "[B<-xchain> I<file>]\n"
+. "[B<-xchain_build> I<file>]\n"
+. "[B<-xcertform> B<DER>|B<PEM>]>\n"
+. "[B<-xkeyform> B<DER>|B<PEM>]>";
+$OpenSSL::safe::opt_x_item = ""
+. "=item B<-xkey> I<infile>, B<-xcert> I<file>, B<-xchain> I<file>,\n"
+. "B<-xchain_build> I<file>, B<-xcertform> B<DER>|B<PEM>,\n"
+. "B<-xkeyform> B<DER>|B<PEM>\n"
+. "\n"
+. "Set extended certificate verification options.\n"
+. "See L<openssl-verification-options(1)/Extended Verification Options> for details.";
+
+# Name output options
+$OpenSSL::safe::opt_name_synopsis = ""
+. "[B<-nameopt> I<option>]";
+$OpenSSL::safe::opt_name_item = ""
+. "=item B<-nameopt> I<option>\n"
+. "\n"
+. "This specifies how the subject or issuer names are displayed.\n"
+. "See L<openssl-namedisplay-options(1)> for details.";
+
+# Random State Options
+$OpenSSL::safe::opt_r_synopsis = ""
+. "[B<-rand> I<files>]\n"
+. "[B<-writerand> I<file>]";
+$OpenSSL::safe::opt_r_item = ""
+. "=item B<-rand> I<files>, B<-writerand> I<file>\n"
+. "\n"
+. "See L<openssl(1)/Random State Options> for details.";
+
+# Provider options
+$OpenSSL::safe::opt_provider_synopsis = ""
+. "[B<-provider> I<name>]\n"
+. "[B<-provider-path> I<path>]\n"
+. "[B<-propquery> I<propq>]";
+$OpenSSL::safe::opt_provider_item = ""
+. "=item B<-provider> I<name>\n"
+. "\n"
+. "=item B<-provider-path> I<path>\n"
+. "\n"
+. "=item B<-propquery> I<propq>\n"
+. "\n"
+. "See L<openssl(1)/Provider Options>, L<provider(7)>, and L<property(7)>.";
+
+# Configuration option
+$OpenSSL::safe::opt_config_synopsis = ""
+. "[B<-config> I<configfile>]";
+$OpenSSL::safe::opt_config_item = ""
+. "=item B<-config> I<configfile>\n"
+. "\n"
+. "See L<openssl(1)/Configuration Option>.";
+
+# Engine option
+$OpenSSL::safe::opt_engine_synopsis = "";
+$OpenSSL::safe::opt_engine_item = "";
+if (!$disabled{"deprecated-3.0"}) {
+ $OpenSSL::safe::opt_engine_synopsis = ""
+ . "[B<-engine> I<id>]\n";
+ $OpenSSL::safe::opt_engine_item = ""
+ . "=item B<-engine> I<id>\n"
+ . "\n"
+ . "See L<openssl(1)/Engine Options>.\n"
+ . "This option is deprecated.";
+}
+
+# Trusted certs options
+$OpenSSL::safe::opt_trust_synopsis = ""
+. "[B<-CAfile> I<file>]\n"
+. "[B<-no-CAfile>]\n"
+. "[B<-CApath> I<dir>]\n"
+. "[B<-no-CApath>]\n"
+. "[B<-CAstore> I<uri>]\n"
+. "[B<-no-CAstore>]";
+$OpenSSL::safe::opt_trust_item = ""
+. "=item B<-CAfile> I<file>, B<-no-CAfile>, B<-CApath> I<dir>, B<-no-CApath>,\n"
+. "B<-CAstore> I<uri>, B<-no-CAstore>\n"
+. "\n"
+. "See L<openssl-verification-options(1)/Trusted Certificate Options> for details.";
+
+# TLS Version Options
+$OpenSSL::safe::opt_versiontls_synopsis = ""
+. "[B<-no_ssl3>]\n"
+. "[B<-no_tls1>]\n"
+. "[B<-no_tls1_1>]\n"
+. "[B<-no_tls1_2>]\n"
+. "[B<-no_tls1_3>]\n"
+. "[B<-ssl3>]\n"
+. "[B<-tls1>]\n"
+. "[B<-tls1_1>]\n"
+. "[B<-tls1_2>]\n"
+. "[B<-tls1_3>]";
+$OpenSSL::safe::opt_versiontls_item = ""
+. "=item B<-no_ssl3>, B<-no_tls1>, B<-no_tls1_1>, B<-no_tls1_2>, B<-no_tls1_3>,\n"
+. "B<-ssl3>, B<-tls1>, B<-tls1_1>, B<-tls1_2>, B<-tls1_3>\n"
+. "\n"
+. "See L<openssl(1)/TLS Version Options>.";
+
+# TLS/DTLS Version Options
+$OpenSSL::safe::opt_version_synopsis = ""
+. "$OpenSSL::safe::opt_versiontls_synopsis\n"
+. "[B<-dtls>]\n"
+. "[B<-dtls1>]\n"
+. "[B<-dtls1_2>]";
+$OpenSSL::safe::opt_version_item = "\n"
+. "$OpenSSL::safe::opt_versiontls_item\n"
+. "\n"
+. "=item B<-dtls>, B<-dtls1>, B<-dtls1_2>\n"
+. "\n"
+. "These specify the use of DTLS instead of TLS.\n"
+. "See L<openssl(1)/TLS Version Options>.";
+
+# SSL connection options.
+# TODO # options will probably be re-ordered.
+$OpenSSL::safe::opt_s_synopsis = ""
+. "[B<-bugs>]\n"
+. "[B<-no_comp>]\n"
+. "[B<-comp>]\n"
+. "[B<-no_ticket>]\n"
+. "[B<-serverpref>]\n"
+. "[B<-client_renegotiation>]\n"
+. "[B<-legacy_renegotiation>]\n"
+. "[B<-no_renegotiation>]\n"
+. "[B<-no_resumption_on_reneg>]\n"
+. "[B<-legacy_server_connect>]\n"
+. "[B<-no_legacy_server_connect>]\n"
+. "[B<-no_etm>]\n"
+. "[B<-allow_no_dhe_kex>]\n"
+. "[B<-prioritize_chacha>]\n"
+. "[B<-strict>]\n"
+. "[B<-sigalgs> I<algs>]\n"
+. "[B<-client_sigalgs> I<algs>]\n"
+. "[B<-groups> I<groups>]\n"
+. "[B<-curves> I<curves>]\n"
+. "[B<-named_curve> I<curve>]\n"
+. "[B<-cipher> I<ciphers>]\n"
+. "[B<-ciphersuites> I<1.3ciphers>]\n"
+. "[B<-min_protocol> I<minprot>]\n"
+. "[B<-max_protocol> I<maxprot>]\n"
+. "[B<-record_padding> I<padding>]\n"
+. "[B<-debug_broken_protocol>]\n"
+. "[B<-no_middlebox>]";
+$OpenSSL::safe::opt_s_item = ""
+. "=item B<-bugs>, B<-comp>, B<-no_comp>, B<-no_ticket>, B<-serverpref>,\n"
+. "B<-client_renegotiation>,\n"
+. "B<-legacy_renegotiation>, B<-no_renegotiation>,\n"
+. "B<-no_resumption_on_reneg>,\n"
+. "B<-legacy_server_connect>, B<-no_legacy_server_connect>, B<-no_etm>\n"
+. "B<-allow_no_dhe_kex>, B<-prioritize_chacha>, B<-strict>, B<-sigalgs>\n"
+. "I<algs>, B<-client_sigalgs> I<algs>, B<-groups> I<groups>, B<-curves>\n"
+. "I<curves>, B<-named_curve> I<curve>, B<-cipher> I<ciphers>, B<-ciphersuites>\n"
+. "I<1.3ciphers>, B<-min_protocol> I<minprot>, B<-max_protocol> I<maxprot>,\n"
+. "B<-record_padding> I<padding>, B<-debug_broken_protocol>, B<-no_middlebox>\n"
+. "\n"
+. "See L<SSL_CONF_cmd(3)/SUPPORTED COMMAND LINE COMMANDS> for details.";
+
+package OpenSSL::safe;
+sub output_do_not_edit_headers {
+ return "\n=begin comment\n\n"
+ . join("\n", @autowarntext)
+ . "\n\n=end comment";
+}
+1;
diff --git a/e_os.h b/e_os.h
index 9af7f3758d94..db05b7f8150f 100644
--- a/e_os.h
+++ b/e_os.h
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -22,51 +22,6 @@
* outside; this file e_os.h is not part of the exported interface.
*/
-# ifndef DEVRANDOM
-/*
- * set this to a comma-separated list of 'random' device files to try out. By
- * default, we will try to read at least one of these files
- */
-# define DEVRANDOM "/dev/urandom", "/dev/random", "/dev/hwrng", "/dev/srandom"
-# if defined(__linux) && !defined(__ANDROID__)
-# ifndef DEVRANDOM_WAIT
-# define DEVRANDOM_WAIT "/dev/random"
-# endif
-/*
- * Linux kernels 4.8 and later changes how their random device works and there
- * is no reliable way to tell that /dev/urandom has been seeded -- getentropy(2)
- * should be used instead.
- */
-# ifndef DEVRANDOM_SAFE_KERNEL
-# define DEVRANDOM_SAFE_KERNEL 4, 8
-# endif
-/*
- * Some operating systems do not permit select(2) on their random devices,
- * defining this to zero will force the use of read(2) to extract one byte
- * from /dev/random.
- */
-# ifndef DEVRANDM_WAIT_USE_SELECT
-# define DEVRANDM_WAIT_USE_SELECT 1
-# endif
-/*
- * Define the shared memory identifier used to indicate if the operating
- * system has properly seeded the DEVRANDOM source.
- */
-# ifndef OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID
-# define OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID 114
-# endif
-
-# endif
-# endif
-# if !defined(OPENSSL_NO_EGD) && !defined(DEVRANDOM_EGD)
-/*
- * set this to a comma-separated list of 'egd' sockets to try out. These
- * sockets will be tried in the order listed in case accessing the device
- * files listed in DEVRANDOM did not return enough randomness.
- */
-# define DEVRANDOM_EGD "/var/run/egd-pool", "/dev/egd-pool", "/etc/egd-pool", "/etc/entropy"
-# endif
-
# if defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)
# define NO_CHMOD
# define NO_SYSLOG
@@ -110,7 +65,6 @@
# define _setmode setmode
# define _O_TEXT O_TEXT
# define _O_BINARY O_BINARY
-# define HAS_LFN_SUPPORT(name) (pathconf((name), _PC_NAME_MAX) > 12)
# undef DEVRANDOM_EGD /* Neither MS-DOS nor FreeDOS provide 'egd' sockets. */
# undef DEVRANDOM
# define DEVRANDOM "/dev/urandom\x24"
@@ -154,6 +108,14 @@
*/
# include <winsock2.h>
# include <ws2tcpip.h>
+ /*
+ * Clang-based C++Builder 10.3.3 toolchains cannot find C inline
+ * definitions at link-time. This header defines WspiapiLoad() as an
+ * __inline function. https://quality.embarcadero.com/browse/RSP-33806
+ */
+# if !defined(__BORLANDC__) || !defined(__clang__)
+# include <wspiapi.h>
+# endif
/* yes, they have to be #included prior to <windows.h> */
# endif
# include <windows.h>
@@ -185,21 +147,6 @@ FILE *__iob_func();
# define stdin (&__iob_func()[0])
# define stdout (&__iob_func()[1])
# define stderr (&__iob_func()[2])
-# elif _MSC_VER<1300 && defined(I_CAN_LIVE_WITH_LNK4049)
-# undef stdin
-# undef stdout
-# undef stderr
- /*
- * pre-1300 has __p__iob(), but it's available only in msvcrt.lib,
- * or in other words with /MD. Declaring implicit import, i.e. with
- * _imp_ prefix, works correctly with all compiler options, but
- * without /MD results in LINK warning LNK4049: 'locally defined
- * symbol "__iob" imported'.
- */
-extern FILE *_imp___iob;
-# define stdin (&_imp___iob[0])
-# define stdout (&_imp___iob[1])
-# define stderr (&_imp___iob[2])
# endif
# endif
# endif
@@ -236,7 +183,7 @@ extern FILE *_imp___iob;
# else /* The non-microsoft world */
# if defined(OPENSSL_SYS_VXWORKS)
-# include <sys/times.h>
+# include <time.h>
# else
# include <sys/time.h>
# endif
@@ -286,11 +233,7 @@ extern FILE *_imp___iob;
# else
/* !defined VMS */
-# ifdef OPENSSL_UNISTD
-# include OPENSSL_UNISTD
-# else
-# include <unistd.h>
-# endif
+# include <unistd.h>
# include <sys/types.h>
# ifdef OPENSSL_SYS_WIN32_CYGWIN
# include <io.h>
@@ -306,8 +249,6 @@ extern FILE *_imp___iob;
/***********************************************/
# if defined(OPENSSL_SYS_WINDOWS)
-# define strcasecmp _stricmp
-# define strncasecmp _strnicmp
# if (_MSC_VER >= 1310) && !defined(_WIN32_WCE)
# define open _open
# define fdopen _fdopen
@@ -345,15 +286,147 @@ struct servent *getservbyname(const char *name, const char *proto);
# endif
/* end vxworks */
+/* system-specific variants defining ossl_sleep() */
+#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
+# include <unistd.h>
+static ossl_inline void ossl_sleep(unsigned long millis)
+{
+# ifdef OPENSSL_SYS_VXWORKS
+ struct timespec ts;
+ ts.tv_sec = (long int) (millis / 1000);
+ ts.tv_nsec = (long int) (millis % 1000) * 1000000ul;
+ nanosleep(&ts, NULL);
+# elif defined(__TANDEM)
+# if !defined(_REENTRANT)
+# include <cextdecs.h(PROCESS_DELAY_)>
+ /* HPNS does not support usleep for non threaded apps */
+ PROCESS_DELAY_(millis * 1000);
+# elif defined(_SPT_MODEL_)
+# include <spthread.h>
+# include <spt_extensions.h>
+ usleep(millis * 1000);
+# else
+ usleep(millis * 1000);
+# endif
+# else
+ usleep(millis * 1000);
+# endif
+}
+#elif defined(_WIN32)
+# include <windows.h>
+static ossl_inline void ossl_sleep(unsigned long millis)
+{
+ Sleep(millis);
+}
+#else
+/* Fallback to a busy wait */
+static ossl_inline void ossl_sleep(unsigned long millis)
+{
+ struct timeval start, now;
+ unsigned long elapsedms;
+
+ gettimeofday(&start, NULL);
+ do {
+ gettimeofday(&now, NULL);
+ elapsedms = (((now.tv_sec - start.tv_sec) * 1000000)
+ + now.tv_usec - start.tv_usec) / 1000;
+ } while (elapsedms < millis);
+}
+#endif /* defined OPENSSL_SYS_UNIX */
+
+/* ----------------------------- HP NonStop -------------------------------- */
+/* Required to support platform variant without getpid() and pid_t. */
+# if defined(__TANDEM) && defined(_GUARDIAN_TARGET)
+# include <strings.h>
+# include <netdb.h>
+# define getservbyname(name,proto) getservbyname((char*)name,proto)
+# define gethostbyname(name) gethostbyname((char*)name)
+# define ioctlsocket(a,b,c) ioctl(a,b,c)
+# ifdef NO_GETPID
+inline int nssgetpid();
+# ifndef NSSGETPID_MACRO
+# define NSSGETPID_MACRO
+# include <cextdecs.h(PROCESSHANDLE_GETMINE_)>
+# include <cextdecs.h(PROCESSHANDLE_DECOMPOSE_)>
+ inline int nssgetpid()
+ {
+ short phandle[10]={0};
+ union pseudo_pid {
+ struct {
+ short cpu;
+ short pin;
+ } cpu_pin ;
+ int ppid;
+ } ppid = { 0 };
+ PROCESSHANDLE_GETMINE_(phandle);
+ PROCESSHANDLE_DECOMPOSE_(phandle, &ppid.cpu_pin.cpu, &ppid.cpu_pin.pin);
+ return ppid.ppid;
+ }
+# define getpid(a) nssgetpid(a)
+# endif /* NSSGETPID_MACRO */
+# endif /* NO_GETPID */
+/*# define setsockopt(a,b,c,d,f) setsockopt(a,b,c,(char*)d,f)*/
+/*# define getsockopt(a,b,c,d,f) getsockopt(a,b,c,(char*)d,f)*/
+/*# define connect(a,b,c) connect(a,(struct sockaddr *)b,c)*/
+/*# define bind(a,b,c) bind(a,(struct sockaddr *)b,c)*/
+/*# define sendto(a,b,c,d,e,f) sendto(a,(char*)b,c,d,(struct sockaddr *)e,f)*/
+# if defined(OPENSSL_THREADS) && !defined(_PUT_MODEL_)
+ /*
+ * HPNS SPT threads
+ */
+# define SPT_THREAD_SIGNAL 1
+# define SPT_THREAD_AWARE 1
+# include <spthread.h>
+# undef close
+# define close spt_close
+/*
+# define get_last_socket_error() errno
+# define clear_socket_error() errno=0
+# define ioctlsocket(a,b,c) ioctl(a,b,c)
+# define closesocket(s) close(s)
+# define readsocket(s,b,n) read((s),(char*)(b),(n))
+# define writesocket(s,b,n) write((s),(char*)(b),(n)
+*/
+# define accept(a,b,c) accept(a,(struct sockaddr *)b,c)
+# define recvfrom(a,b,c,d,e,f) recvfrom(a,b,(socklen_t)c,d,e,f)
+# endif
+# endif
+
# ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
# define CRYPTO_memcmp memcmp
# endif
-/* unistd.h defines _POSIX_VERSION */
-# if !defined(OPENSSL_NO_SECURE_MEMORY) && defined(OPENSSL_SYS_UNIX) \
- && ( (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) \
- || defined(__sun) || defined(__hpux) || defined(__sgi) \
- || defined(__osf__) )
-# define OPENSSL_SECURE_MEMORY /* secure memory is implemented */
+# ifndef OPENSSL_NO_SECURE_MEMORY
+ /* unistd.h defines _POSIX_VERSION */
+# if (defined(OPENSSL_SYS_UNIX) \
+ && ( (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) \
+ || defined(__sun) || defined(__hpux) || defined(__sgi) \
+ || defined(__osf__) )) \
+ || defined(_WIN32)
+ /* secure memory is implemented */
+# else
+# define OPENSSL_NO_SECURE_MEMORY
+# endif
# endif
+
+/*
+ * str[n]casecmp_l is defined in POSIX 2008-01. Value is taken accordingly
+ * https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
+ * There are also equivalent functions on Windows.
+ * There is no locale_t on NONSTOP.
+ */
+# if defined(OPENSSL_SYS_WINDOWS)
+# define locale_t _locale_t
+# define freelocale _free_locale
+# define strcasecmp_l _stricmp_l
+# define strncasecmp_l _strnicmp_l
+# define strcasecmp _stricmp
+# define strncasecmp _strnicmp
+# elif !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200809L \
+ || defined(OPENSSL_SYS_TANDEM)
+# ifndef OPENSSL_NO_LOCALE
+# define OPENSSL_NO_LOCALE
+# endif
+# endif
+
#endif
diff --git a/engines/asm/e_padlock-x86.pl b/engines/asm/e_padlock-x86.pl
index 7d5c92d98ce3..3e9a22fca4bf 100644
--- a/engines/asm/e_padlock-x86.pl
+++ b/engines/asm/e_padlock-x86.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2011-2023 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -42,8 +42,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../crypto/perlasm");
require "x86asm.pl";
-$output=pop;
-open STDOUT,">$output";
+$output=pop and open STDOUT,">$output";
&asm_init($ARGV[0]);
diff --git a/engines/asm/e_padlock-x86_64.pl b/engines/asm/e_padlock-x86_64.pl
index f60bec1e7d5d..b147868851d5 100644
--- a/engines/asm/e_padlock-x86_64.pl
+++ b/engines/asm/e_padlock-x86_64.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright 2011-2023 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
@@ -19,9 +19,10 @@
# Assembler helpers for Padlock engine. See even e_padlock-x86.pl for
# details.
-$flavour = shift;
-$output = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -30,7 +31,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../crypto/perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+ or die "can't call $xlate: $!";
*STDOUT=*OUT;
$code=".text\n";
diff --git a/engines/build.info b/engines/build.info
index 1db771971cd5..19e3eab0c184 100644
--- a/engines/build.info
+++ b/engines/build.info
@@ -1,9 +1,22 @@
IF[{- !$disabled{"engine"} -}]
+ $PADLOCKASM=
+ IF[{- !$disabled{asm} -}]
+ $PADLOCKASM_x86=e_padlock-x86.S
+ $PADLOCKASM_x86_64=e_padlock-x86_64.s
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+ IF[$PADLOCKASM_{- $target{asm_arch} -}]
+ $PADLOCKASM=$PADLOCKASM_{- $target{asm_arch} -}
+ $PADLOCKDEF=PADLOCK_ASM
+ ENDIF
+ ENDIF
IF[{- $disabled{"dynamic-engine"} -}]
LIBS=../libcrypto
- IF[{- !$disabled{hw} && !$disabled{'hw-padlock'} -}]
- SOURCE[../libcrypto]= e_padlock.c {- $target{padlock_asm_src} -}
+ IF[{- !$disabled{padlockeng} -}]
+ SOURCE[../libcrypto]=e_padlock.c $PADLOCKASM
+ DEFINE[../libcrypto]=$PADLOCKDEF
ENDIF
IF[{- !$disabled{capieng} -}]
SOURCE[../libcrypto]=e_capi.c
@@ -11,36 +24,80 @@ IF[{- !$disabled{"engine"} -}]
IF[{- !$disabled{afalgeng} -}]
SOURCE[../libcrypto]=e_afalg.c
ENDIF
+ IF[{- !$disabled{"devcryptoeng"} -}]
+ SOURCE[../libcrypto]=e_devcrypto.c
+ ENDIF
ELSE
- IF[{- !$disabled{hw} && !$disabled{'hw-padlock'} -}]
- ENGINES=padlock
- SOURCE[padlock]=e_padlock.c {- $target{padlock_asm_src} -}
+ IF[{- !$disabled{padlockeng} -}]
+ MODULES{engine}=padlock
+ SOURCE[padlock]=e_padlock.c $PADLOCKASM
+ DEFINE[padlock]=$PADLOCKDEF
DEPEND[padlock]=../libcrypto
INCLUDE[padlock]=../include
+ IF[{- defined $target{shared_defflag} -}]
+ SOURCE[padlock]=padlock.ld
+ GENERATE[padlock.ld]=../util/engines.num
+ ENDIF
ENDIF
IF[{- !$disabled{capieng} -}]
- ENGINES=capi
+ MODULES{engine}=capi
SOURCE[capi]=e_capi.c
DEPEND[capi]=../libcrypto
INCLUDE[capi]=../include
+ IF[{- defined $target{shared_defflag} -}]
+ SOURCE[capi]=capi.ld
+ GENERATE[capi.ld]=../util/engines.num
+ ENDIF
ENDIF
IF[{- !$disabled{afalgeng} -}]
- ENGINES=afalg
+ MODULES{engine}=afalg
SOURCE[afalg]=e_afalg.c
DEPEND[afalg]=../libcrypto
INCLUDE[afalg]= ../include
+ IF[{- defined $target{shared_defflag} -}]
+ SOURCE[afalg]=afalg.ld
+ GENERATE[afalg.ld]=../util/engines.num
+ ENDIF
+ ENDIF
+ IF[{- !$disabled{"devcryptoeng"} -}]
+ MODULES{engine}=devcrypto
+ SOURCE[devcrypto]=e_devcrypto.c
+ DEPEND[devcrypto]=../libcrypto
+ INCLUDE[devcrypto]=../include
+ IF[{- defined $target{shared_defflag} -}]
+ SOURCE[devcrypto]=devcrypto.ld
+ GENERATE[devcrypto.ld]=../util/engines.num
+ ENDIF
+ ENDIF
+ IF[{- !$disabled{"loadereng"} -}]
+ MODULES{engine}=loader_attic
+ SOURCE[loader_attic]=e_loader_attic.c ../crypto/pem/pvkfmt.c
+ DEFINE[loader_attic]=OPENSSL_NO_PROVIDER_CODE
+ DEPEND[loader_attic]=../libcrypto
+ INCLUDE[loader_attic]=../include
+ IF[{- defined $target{shared_defflag} -}]
+ SOURCE[loader_attic]=loader_attic.ld
+ GENERATE[loader_attic.ld]=../util/engines.num
+ ENDIF
ENDIF
- ENGINES_NO_INST=ossltest dasync
+ MODULES{noinst,engine}=ossltest dasync
SOURCE[dasync]=e_dasync.c
DEPEND[dasync]=../libcrypto
INCLUDE[dasync]=../include
+ IF[{- defined $target{shared_defflag} -}]
+ SOURCE[dasync]=dasync.ld
+ GENERATE[dasync.ld]=../util/engines.num
+ ENDIF
+
SOURCE[ossltest]=e_ossltest.c
DEPEND[ossltest]=../libcrypto
INCLUDE[ossltest]=../include
+ IF[{- defined $target{shared_defflag} -}]
+ SOURCE[ossltest]=ossltest.ld
+ GENERATE[ossltest.ld]=../util/engines.num
+ ENDIF
ENDIF
-
- GENERATE[e_padlock-x86.s]=asm/e_padlock-x86.pl \
- $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
- GENERATE[e_padlock-x86_64.s]=asm/e_padlock-x86_64.pl $(PERLASM_SCHEME)
+ GENERATE[e_padlock-x86.S]=asm/e_padlock-x86.pl
+ GENERATE[e_padlock-x86_64.s]=asm/e_padlock-x86_64.pl
ENDIF
diff --git a/engines/e_afalg.c b/engines/e_afalg.c
index 2d16c1383442..2c08cbb28dde 100644
--- a/engines/e_afalg.c
+++ b/engines/e_afalg.c
@@ -1,12 +1,15 @@
/*
* Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
/* Required for vmsplice */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
@@ -121,11 +124,56 @@ static ossl_inline int io_read(aio_context_t ctx, long n, struct iocb **iocb)
return syscall(__NR_io_submit, ctx, n, iocb);
}
+/* A version of 'struct timespec' with 32-bit time_t and nanoseconds. */
+struct __timespec32
+{
+ __kernel_long_t tv_sec;
+ __kernel_long_t tv_nsec;
+};
+
static ossl_inline int io_getevents(aio_context_t ctx, long min, long max,
struct io_event *events,
struct timespec *timeout)
{
- return syscall(__NR_io_getevents, ctx, min, max, events, timeout);
+#if defined(__NR_io_pgetevents_time64)
+ /* Check if we are a 32-bit architecture with a 64-bit time_t */
+ if (sizeof(*timeout) != sizeof(struct __timespec32)) {
+ int ret = syscall(__NR_io_pgetevents_time64, ctx, min, max, events,
+ timeout, NULL);
+ if (ret == 0 || errno != ENOSYS)
+ return ret;
+ }
+#endif
+
+#if defined(__NR_io_getevents)
+ if (sizeof(*timeout) == sizeof(struct __timespec32))
+ /*
+ * time_t matches our architecture length, we can just use
+ * __NR_io_getevents
+ */
+ return syscall(__NR_io_getevents, ctx, min, max, events, timeout);
+ else {
+ /*
+ * We don't have __NR_io_pgetevents_time64, but we are using a
+ * 64-bit time_t on a 32-bit architecture. If we can fit the
+ * timeout value in a 32-bit time_t, then let's do that
+ * and then use the __NR_io_getevents syscall.
+ */
+ if (timeout && timeout->tv_sec == (long)timeout->tv_sec) {
+ struct __timespec32 ts32;
+
+ ts32.tv_sec = (__kernel_long_t) timeout->tv_sec;
+ ts32.tv_nsec = (__kernel_long_t) timeout->tv_nsec;
+
+ return syscall(__NR_io_getevents, ctx, min, max, events, ts32);
+ } else {
+ return syscall(__NR_io_getevents, ctx, min, max, events, NULL);
+ }
+ }
+#endif
+
+ errno = ENOSYS;
+ return -1;
}
static void afalg_waitfd_cleanup(ASYNC_WAIT_CTX *ctx, const void *key,
@@ -276,6 +324,15 @@ static int afalg_fin_cipher_aio(afalg_aio *aio, int sfd, unsigned char *buf,
}
if (eval > 0) {
+#ifdef OSSL_SANITIZE_MEMORY
+ /*
+ * In a memory sanitiser build, the changes to memory made by the
+ * system call aren't reliably detected. By initialising the
+ * memory here, the sanitiser is told that they are okay.
+ */
+ memset(events, 0, sizeof(events));
+#endif
+
/* Get results of AIO read */
r = io_getevents(aio->aio_ctx, 1, MAX_INFLIGHTS,
events, &timeout);
@@ -407,7 +464,7 @@ static int afalg_start_cipher_sk(afalg_ctx *actx, const unsigned char *in,
size_t inl, const unsigned char *iv,
unsigned int enc)
{
- struct msghdr msg = { 0 };
+ struct msghdr msg;
struct cmsghdr *cmsg;
struct iovec iov;
ssize_t sbytes;
@@ -416,6 +473,7 @@ static int afalg_start_cipher_sk(afalg_ctx *actx, const unsigned char *in,
# endif
char cbuf[CMSG_SPACE(ALG_IV_LEN(ALG_AES_IV_LEN)) + CMSG_SPACE(ALG_OP_LEN)];
+ memset(&msg, 0, sizeof(msg));
memset(cbuf, 0, sizeof(cbuf));
msg.msg_control = cbuf;
msg.msg_controllen = sizeof(cbuf);
@@ -495,7 +553,7 @@ static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
int ciphertype;
- int ret;
+ int ret, len;
afalg_ctx *actx;
const char *ciphername;
@@ -504,7 +562,7 @@ static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
return 0;
}
- if (EVP_CIPHER_CTX_cipher(ctx) == NULL) {
+ if (EVP_CIPHER_CTX_get0_cipher(ctx) == NULL) {
ALG_WARN("%s(%d): Cipher object NULL\n", __FILE__, __LINE__);
return 0;
}
@@ -515,7 +573,7 @@ static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
return 0;
}
- ciphertype = EVP_CIPHER_CTX_nid(ctx);
+ ciphertype = EVP_CIPHER_CTX_get_nid(ctx);
switch (ciphertype) {
case NID_aes_128_cbc:
case NID_aes_192_cbc:
@@ -528,9 +586,9 @@ static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
return 0;
}
- if (ALG_AES_IV_LEN != EVP_CIPHER_CTX_iv_length(ctx)) {
+ if (ALG_AES_IV_LEN != EVP_CIPHER_CTX_get_iv_length(ctx)) {
ALG_WARN("%s(%d): Unsupported IV length :%d\n", __FILE__, __LINE__,
- EVP_CIPHER_CTX_iv_length(ctx));
+ EVP_CIPHER_CTX_get_iv_length(ctx));
return 0;
}
@@ -539,8 +597,9 @@ static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
if (ret < 1)
return 0;
-
- ret = afalg_set_key(actx, key, EVP_CIPHER_CTX_key_length(ctx));
+ if ((len = EVP_CIPHER_CTX_get_key_length(ctx)) <= 0)
+ goto err;
+ ret = afalg_set_key(actx, key, len);
if (ret < 1)
goto err;
@@ -586,14 +645,14 @@ static int afalg_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
* set iv now for decrypt operation as the input buffer can be
* overwritten for inplace operation where in = out.
*/
- if (EVP_CIPHER_CTX_encrypting(ctx) == 0) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx) == 0) {
memcpy(nxtiv, in + (inl - ALG_AES_IV_LEN), ALG_AES_IV_LEN);
}
/* Send input data to kernel space */
ret = afalg_start_cipher_sk(actx, (unsigned char *)in, inl,
EVP_CIPHER_CTX_iv(ctx),
- EVP_CIPHER_CTX_encrypting(ctx));
+ EVP_CIPHER_CTX_is_encrypting(ctx));
if (ret < 1) {
return 0;
}
@@ -603,7 +662,7 @@ static int afalg_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (ret < 1)
return 0;
- if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), out + (inl - ALG_AES_IV_LEN),
ALG_AES_IV_LEN);
} else {
@@ -658,6 +717,9 @@ static cbc_handles *get_cipher_handle(int nid)
static const EVP_CIPHER *afalg_aes_cbc(int nid)
{
cbc_handles *cipher_handle = get_cipher_handle(nid);
+
+ if (cipher_handle == NULL)
+ return NULL;
if (cipher_handle->_hidden == NULL
&& ((cipher_handle->_hidden =
EVP_CIPHER_meth_new(nid,
@@ -825,9 +887,19 @@ void engine_load_afalg_int(void)
toadd = engine_afalg();
if (toadd == NULL)
return;
+ ERR_set_mark();
ENGINE_add(toadd);
+ /*
+ * If the "add" worked, it gets a structural reference. So either way, we
+ * release our just-created reference.
+ */
ENGINE_free(toadd);
- ERR_clear_error();
+ /*
+ * If the "add" didn't work, it was probably a conflict because it was
+ * already added (eg. someone calling ENGINE_load_blah then calling
+ * ENGINE_load_builtin_engines() perhaps).
+ */
+ ERR_pop_to_mark();
}
# endif
diff --git a/engines/e_afalg.h b/engines/e_afalg.h
index 3323c898c634..b8e4911d21ef 100644
--- a/engines/e_afalg.h
+++ b/engines/e_afalg.h
@@ -1,7 +1,7 @@
/*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/engines/e_afalg.txt b/engines/e_afalg.txt
index 3b79305acf9b..37f023b87ed1 100644
--- a/engines/e_afalg.txt
+++ b/engines/e_afalg.txt
@@ -1,19 +1,10 @@
-# Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
-# Function codes
-AFALG_F_AFALG_CHK_PLATFORM:100:afalg_chk_platform
-AFALG_F_AFALG_CREATE_SK:101:afalg_create_sk
-AFALG_F_AFALG_INIT_AIO:102:afalg_init_aio
-AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION:103:\
- afalg_setup_async_event_notification
-AFALG_F_AFALG_SET_KEY:104:afalg_set_key
-AFALG_F_BIND_AFALG:105:bind_afalg
-
#Reason codes
AFALG_R_EVENTFD_FAILED:108:eventfd failed
AFALG_R_FAILED_TO_GET_PLATFORM_INFO:111:failed to get platform info
diff --git a/engines/e_afalg_err.c b/engines/e_afalg_err.c
index 18fe9c34e0e2..47a3d034e50d 100644
--- a/engines/e_afalg_err.c
+++ b/engines/e_afalg_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,17 +13,6 @@
#ifndef OPENSSL_NO_ERR
-static ERR_STRING_DATA AFALG_str_functs[] = {
- {ERR_PACK(0, AFALG_F_AFALG_CHK_PLATFORM, 0), "afalg_chk_platform"},
- {ERR_PACK(0, AFALG_F_AFALG_CREATE_SK, 0), "afalg_create_sk"},
- {ERR_PACK(0, AFALG_F_AFALG_INIT_AIO, 0), "afalg_init_aio"},
- {ERR_PACK(0, AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION, 0),
- "afalg_setup_async_event_notification"},
- {ERR_PACK(0, AFALG_F_AFALG_SET_KEY, 0), "afalg_set_key"},
- {ERR_PACK(0, AFALG_F_BIND_AFALG, 0), "bind_afalg"},
- {0, NULL}
-};
-
static ERR_STRING_DATA AFALG_str_reasons[] = {
{ERR_PACK(0, 0, AFALG_R_EVENTFD_FAILED), "eventfd failed"},
{ERR_PACK(0, 0, AFALG_R_FAILED_TO_GET_PLATFORM_INFO),
@@ -56,7 +45,6 @@ static int ERR_load_AFALG_strings(void)
if (!error_loaded) {
#ifndef OPENSSL_NO_ERR
- ERR_load_strings(lib_code, AFALG_str_functs);
ERR_load_strings(lib_code, AFALG_str_reasons);
#endif
error_loaded = 1;
@@ -68,16 +56,16 @@ static void ERR_unload_AFALG_strings(void)
{
if (error_loaded) {
#ifndef OPENSSL_NO_ERR
- ERR_unload_strings(lib_code, AFALG_str_functs);
ERR_unload_strings(lib_code, AFALG_str_reasons);
#endif
error_loaded = 0;
}
}
-static void ERR_AFALG_error(int function, int reason, char *file, int line)
+static void ERR_AFALG_error(int function, int reason, const char *file, int line)
{
if (lib_code == 0)
lib_code = ERR_get_next_error_library();
- ERR_PUT_error(lib_code, function, reason, file, line);
+ ERR_raise(lib_code, reason);
+ ERR_set_debug(file, line, NULL);
}
diff --git a/engines/e_afalg_err.h b/engines/e_afalg_err.h
index 3036443f4470..2070c04a1c11 100644
--- a/engines/e_afalg_err.h
+++ b/engines/e_afalg_err.h
@@ -1,28 +1,23 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef OSSL_ENGINES_E_AFALG_ERR_H
-# define OSSL_ENGINES_E_AFALG_ERR_H
+#ifndef OSSL_E_AFALG_ERR_H
+# define OSSL_E_AFALG_ERR_H
+# pragma once
-# define AFALGerr(f, r) ERR_AFALG_error((f), (r), OPENSSL_FILE, OPENSSL_LINE)
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
-/*
- * AFALG function codes.
- */
-# define AFALG_F_AFALG_CHK_PLATFORM 100
-# define AFALG_F_AFALG_CREATE_SK 101
-# define AFALG_F_AFALG_INIT_AIO 102
-# define AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION 103
-# define AFALG_F_AFALG_SET_KEY 104
-# define AFALG_F_BIND_AFALG 105
+# define AFALGerr(f, r) ERR_AFALG_error(0, (r), OPENSSL_FILE, OPENSSL_LINE)
+
/*
* AFALG reason codes.
diff --git a/engines/e_capi.c b/engines/e_capi.c
index 37202b81f398..6f223a692273 100644
--- a/engines/e_capi.c
+++ b/engines/e_capi.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#ifdef _WIN32
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0400
@@ -597,9 +600,19 @@ void engine_load_capi_int(void)
ENGINE *toadd = engine_capi();
if (!toadd)
return;
+ ERR_set_mark();
ENGINE_add(toadd);
+ /*
+ * If the "add" worked, it gets a structural reference. So either way, we
+ * release our just-created reference.
+ */
ENGINE_free(toadd);
- ERR_clear_error();
+ /*
+ * If the "add" didn't work, it was probably a conflict because it was
+ * already added (eg. someone calling ENGINE_load_blah then calling
+ * ENGINE_load_builtin_engines() perhaps).
+ */
+ ERR_pop_to_mark();
}
# endif
@@ -1107,10 +1120,19 @@ static char *wide_to_asc(LPCWSTR wstr)
{
char *str;
int len_0, sz;
+ size_t len_1;
if (!wstr)
return NULL;
- len_0 = (int)wcslen(wstr) + 1; /* WideCharToMultiByte expects int */
+
+ len_1 = wcslen(wstr) + 1;
+
+ if (len_1 > INT_MAX) {
+ CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_FUNCTION_NOT_SUPPORTED);
+ return NULL;
+ }
+
+ len_0 = (int)len_1; /* WideCharToMultiByte expects int */
sz = WideCharToMultiByte(CP_ACP, 0, wstr, len_0, NULL, 0, NULL, NULL);
if (!sz) {
CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR);
@@ -1301,13 +1323,14 @@ static void capi_dump_prov_info(CAPI_CTX *ctx, BIO *out,
CRYPT_KEY_PROV_INFO *pinfo)
{
char *provname = NULL, *contname = NULL;
- if (!pinfo) {
+
+ if (pinfo == NULL) {
BIO_printf(out, " No Private Key\n");
return;
}
provname = wide_to_asc(pinfo->pwszProvName);
contname = wide_to_asc(pinfo->pwszContainerName);
- if (!provname || !contname)
+ if (provname == NULL || contname == NULL)
goto err;
BIO_printf(out, " Private Key Info:\n");
@@ -1777,7 +1800,7 @@ static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
sk_X509_free(certs);
- if (!*pcert)
+ if (*pcert == NULL)
return 0;
/* Setup key for selected certificate */
diff --git a/engines/e_capi.txt b/engines/e_capi.txt
index 3f34cdf6b7e9..dc557eef98ff 100644
--- a/engines/e_capi.txt
+++ b/engines/e_capi.txt
@@ -1,32 +1,10 @@
-# Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
-# Function codes
-CAPI_F_CAPI_CERT_GET_FNAME:99:capi_cert_get_fname
-CAPI_F_CAPI_CTRL:100:capi_ctrl
-CAPI_F_CAPI_CTX_NEW:101:capi_ctx_new
-CAPI_F_CAPI_CTX_SET_PROVNAME:102:capi_ctx_set_provname
-CAPI_F_CAPI_DSA_DO_SIGN:114:capi_dsa_do_sign
-CAPI_F_CAPI_GET_KEY:103:capi_get_key
-CAPI_F_CAPI_GET_PKEY:115:capi_get_pkey
-CAPI_F_CAPI_GET_PROVNAME:104:capi_get_provname
-CAPI_F_CAPI_GET_PROV_INFO:105:capi_get_prov_info
-CAPI_F_CAPI_INIT:106:capi_init
-CAPI_F_CAPI_LIST_CONTAINERS:107:capi_list_containers
-CAPI_F_CAPI_LOAD_PRIVKEY:108:capi_load_privkey
-CAPI_F_CAPI_OPEN_STORE:109:capi_open_store
-CAPI_F_CAPI_RSA_PRIV_DEC:110:capi_rsa_priv_dec
-CAPI_F_CAPI_RSA_PRIV_ENC:111:capi_rsa_priv_enc
-CAPI_F_CAPI_RSA_SIGN:112:capi_rsa_sign
-CAPI_F_CAPI_VTRACE:118:capi_vtrace
-CAPI_F_CERT_SELECT_DIALOG:117:cert_select_dialog
-CAPI_F_CLIENT_CERT_SELECT:116:*
-CAPI_F_WIDE_TO_ASC:113:wide_to_asc
-
#Reason codes
CAPI_R_CANT_CREATE_HASH_OBJECT:100:cant create hash object
CAPI_R_CANT_FIND_CAPI_CONTEXT:101:cant find capi context
diff --git a/engines/e_capi_err.c b/engines/e_capi_err.c
index b72bc51a874e..1d7636562e9b 100644
--- a/engines/e_capi_err.c
+++ b/engines/e_capi_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,30 +13,6 @@
#ifndef OPENSSL_NO_ERR
-static ERR_STRING_DATA CAPI_str_functs[] = {
- {ERR_PACK(0, CAPI_F_CAPI_CERT_GET_FNAME, 0), "capi_cert_get_fname"},
- {ERR_PACK(0, CAPI_F_CAPI_CTRL, 0), "capi_ctrl"},
- {ERR_PACK(0, CAPI_F_CAPI_CTX_NEW, 0), "capi_ctx_new"},
- {ERR_PACK(0, CAPI_F_CAPI_CTX_SET_PROVNAME, 0), "capi_ctx_set_provname"},
- {ERR_PACK(0, CAPI_F_CAPI_DSA_DO_SIGN, 0), "capi_dsa_do_sign"},
- {ERR_PACK(0, CAPI_F_CAPI_GET_KEY, 0), "capi_get_key"},
- {ERR_PACK(0, CAPI_F_CAPI_GET_PKEY, 0), "capi_get_pkey"},
- {ERR_PACK(0, CAPI_F_CAPI_GET_PROVNAME, 0), "capi_get_provname"},
- {ERR_PACK(0, CAPI_F_CAPI_GET_PROV_INFO, 0), "capi_get_prov_info"},
- {ERR_PACK(0, CAPI_F_CAPI_INIT, 0), "capi_init"},
- {ERR_PACK(0, CAPI_F_CAPI_LIST_CONTAINERS, 0), "capi_list_containers"},
- {ERR_PACK(0, CAPI_F_CAPI_LOAD_PRIVKEY, 0), "capi_load_privkey"},
- {ERR_PACK(0, CAPI_F_CAPI_OPEN_STORE, 0), "capi_open_store"},
- {ERR_PACK(0, CAPI_F_CAPI_RSA_PRIV_DEC, 0), "capi_rsa_priv_dec"},
- {ERR_PACK(0, CAPI_F_CAPI_RSA_PRIV_ENC, 0), "capi_rsa_priv_enc"},
- {ERR_PACK(0, CAPI_F_CAPI_RSA_SIGN, 0), "capi_rsa_sign"},
- {ERR_PACK(0, CAPI_F_CAPI_VTRACE, 0), "capi_vtrace"},
- {ERR_PACK(0, CAPI_F_CERT_SELECT_DIALOG, 0), "cert_select_dialog"},
- {ERR_PACK(0, CAPI_F_CLIENT_CERT_SELECT, 0), ""},
- {ERR_PACK(0, CAPI_F_WIDE_TO_ASC, 0), "wide_to_asc"},
- {0, NULL}
-};
-
static ERR_STRING_DATA CAPI_str_reasons[] = {
{ERR_PACK(0, 0, CAPI_R_CANT_CREATE_HASH_OBJECT), "cant create hash object"},
{ERR_PACK(0, 0, CAPI_R_CANT_FIND_CAPI_CONTEXT), "cant find capi context"},
@@ -92,7 +68,6 @@ static int ERR_load_CAPI_strings(void)
if (!error_loaded) {
#ifndef OPENSSL_NO_ERR
- ERR_load_strings(lib_code, CAPI_str_functs);
ERR_load_strings(lib_code, CAPI_str_reasons);
#endif
error_loaded = 1;
@@ -104,16 +79,16 @@ static void ERR_unload_CAPI_strings(void)
{
if (error_loaded) {
#ifndef OPENSSL_NO_ERR
- ERR_unload_strings(lib_code, CAPI_str_functs);
ERR_unload_strings(lib_code, CAPI_str_reasons);
#endif
error_loaded = 0;
}
}
-static void ERR_CAPI_error(int function, int reason, char *file, int line)
+static void ERR_CAPI_error(int function, int reason, const char *file, int line)
{
if (lib_code == 0)
lib_code = ERR_get_next_error_library();
- ERR_PUT_error(lib_code, function, reason, file, line);
+ ERR_raise(lib_code, reason);
+ ERR_set_debug(file, line, NULL);
}
diff --git a/engines/e_capi_err.h b/engines/e_capi_err.h
index e3a927aa7339..cd80c9be89f1 100644
--- a/engines/e_capi_err.h
+++ b/engines/e_capi_err.h
@@ -1,42 +1,23 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef OSSL_ENGINES_E_CAPI_ERR_H
-# define OSSL_ENGINES_E_CAPI_ERR_H
+#ifndef OSSL_E_CAPI_ERR_H
+# define OSSL_E_CAPI_ERR_H
+# pragma once
-# define CAPIerr(f, r) ERR_CAPI_error((f), (r), OPENSSL_FILE, OPENSSL_LINE)
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
-/*
- * CAPI function codes.
- */
-# define CAPI_F_CAPI_CERT_GET_FNAME 99
-# define CAPI_F_CAPI_CTRL 100
-# define CAPI_F_CAPI_CTX_NEW 101
-# define CAPI_F_CAPI_CTX_SET_PROVNAME 102
-# define CAPI_F_CAPI_DSA_DO_SIGN 114
-# define CAPI_F_CAPI_GET_KEY 103
-# define CAPI_F_CAPI_GET_PKEY 115
-# define CAPI_F_CAPI_GET_PROVNAME 104
-# define CAPI_F_CAPI_GET_PROV_INFO 105
-# define CAPI_F_CAPI_INIT 106
-# define CAPI_F_CAPI_LIST_CONTAINERS 107
-# define CAPI_F_CAPI_LOAD_PRIVKEY 108
-# define CAPI_F_CAPI_OPEN_STORE 109
-# define CAPI_F_CAPI_RSA_PRIV_DEC 110
-# define CAPI_F_CAPI_RSA_PRIV_ENC 111
-# define CAPI_F_CAPI_RSA_SIGN 112
-# define CAPI_F_CAPI_VTRACE 118
-# define CAPI_F_CERT_SELECT_DIALOG 117
-# define CAPI_F_CLIENT_CERT_SELECT 116
-# define CAPI_F_WIDE_TO_ASC 113
+# define CAPIerr(f, r) ERR_CAPI_error(0, (r), OPENSSL_FILE, OPENSSL_LINE)
+
/*
* CAPI reason codes.
diff --git a/engines/e_dasync.c b/engines/e_dasync.c
index 9ad043b1bd1a..7974106ae219 100644
--- a/engines/e_dasync.c
+++ b/engines/e_dasync.c
@@ -1,12 +1,24 @@
/*
* Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+/*
+ * SHA-1 low level APIs are deprecated for public use, but still ok for
+ * internal use. Note, that due to symbols not being exported, only the
+ * #defines and strucures can be accessed, in this case SHA_CBLOCK and
+ * sizeof(SHA_CTX).
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/opensslconf.h>
#if defined(_WIN32)
# include <windows.h>
#endif
@@ -84,7 +96,7 @@ static int dasync_digest_nids(const int **nids)
if (!init) {
const EVP_MD *md;
if ((md = dasync_sha1()) != NULL)
- digest_nids[pos++] = EVP_MD_type(md);
+ digest_nids[pos++] = EVP_MD_get_type(md);
digest_nids[pos] = 0;
init = 1;
}
@@ -93,22 +105,29 @@ static int dasync_digest_nids(const int **nids)
}
/* RSA */
-
-static int dasync_pub_enc(int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding);
-static int dasync_pub_dec(int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding);
-static int dasync_rsa_priv_enc(int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding);
-static int dasync_rsa_priv_dec(int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding);
-static int dasync_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
- BN_CTX *ctx);
-
-static int dasync_rsa_init(RSA *rsa);
-static int dasync_rsa_finish(RSA *rsa);
-
-static RSA_METHOD *dasync_rsa_method = NULL;
+static int dasync_pkey(ENGINE *e, EVP_PKEY_METHOD **pmeth,
+ const int **pnids, int nid);
+
+static int dasync_rsa_init(EVP_PKEY_CTX *ctx);
+static void dasync_rsa_cleanup(EVP_PKEY_CTX *ctx);
+static int dasync_rsa_paramgen_init(EVP_PKEY_CTX *ctx);
+static int dasync_rsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
+static int dasync_rsa_keygen_init(EVP_PKEY_CTX *ctx);
+static int dasync_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
+static int dasync_rsa_encrypt_init(EVP_PKEY_CTX *ctx);
+static int dasync_rsa_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out,
+ size_t *outlen, const unsigned char *in,
+ size_t inlen);
+static int dasync_rsa_decrypt_init(EVP_PKEY_CTX *ctx);
+static int dasync_rsa_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out,
+ size_t *outlen, const unsigned char *in,
+ size_t inlen);
+static int dasync_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2);
+static int dasync_rsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
+ const char *value);
+
+static EVP_PKEY_METHOD *dasync_rsa;
+static const EVP_PKEY_METHOD *dasync_rsa_orig;
/* AES */
@@ -120,6 +139,14 @@ static int dasync_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl);
static int dasync_aes128_cbc_cleanup(EVP_CIPHER_CTX *ctx);
+static int dasync_aes256_ctr_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
+ void *ptr);
+static int dasync_aes256_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc);
+static int dasync_aes256_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl);
+static int dasync_aes256_ctr_cleanup(EVP_CIPHER_CTX *ctx);
+
static int dasync_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type,
int arg, void *ptr);
static int dasync_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx,
@@ -152,6 +179,12 @@ static const EVP_CIPHER *dasync_aes_128_cbc(void)
return _hidden_aes_128_cbc;
}
+static EVP_CIPHER *_hidden_aes_256_ctr = NULL;
+static const EVP_CIPHER *dasync_aes_256_ctr(void)
+{
+ return _hidden_aes_256_ctr;
+}
+
/*
* Holds the EVP_CIPHER object for aes_128_cbc_hmac_sha1 in this engine. Set up
* once only during engine bind and can then be reused many times.
@@ -173,8 +206,10 @@ static const EVP_CIPHER *dasync_aes_128_cbc_hmac_sha1(void)
static void destroy_ciphers(void)
{
EVP_CIPHER_meth_free(_hidden_aes_128_cbc);
+ EVP_CIPHER_meth_free(_hidden_aes_256_ctr);
EVP_CIPHER_meth_free(_hidden_aes_128_cbc_hmac_sha1);
_hidden_aes_128_cbc = NULL;
+ _hidden_aes_256_ctr = NULL;
_hidden_aes_128_cbc_hmac_sha1 = NULL;
}
@@ -182,33 +217,39 @@ static int dasync_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
const int **nids, int nid);
static int dasync_cipher_nids[] = {
- NID_aes_128_cbc_hmac_sha1,
NID_aes_128_cbc,
+ NID_aes_256_ctr,
+ NID_aes_128_cbc_hmac_sha1,
0
};
static int bind_dasync(ENGINE *e)
{
- /* Setup RSA_METHOD */
- if ((dasync_rsa_method = RSA_meth_new("Dummy Async RSA method", 0)) == NULL
- || RSA_meth_set_pub_enc(dasync_rsa_method, dasync_pub_enc) == 0
- || RSA_meth_set_pub_dec(dasync_rsa_method, dasync_pub_dec) == 0
- || RSA_meth_set_priv_enc(dasync_rsa_method, dasync_rsa_priv_enc) == 0
- || RSA_meth_set_priv_dec(dasync_rsa_method, dasync_rsa_priv_dec) == 0
- || RSA_meth_set_mod_exp(dasync_rsa_method, dasync_rsa_mod_exp) == 0
- || RSA_meth_set_bn_mod_exp(dasync_rsa_method, BN_mod_exp_mont) == 0
- || RSA_meth_set_init(dasync_rsa_method, dasync_rsa_init) == 0
- || RSA_meth_set_finish(dasync_rsa_method, dasync_rsa_finish) == 0) {
- DASYNCerr(DASYNC_F_BIND_DASYNC, DASYNC_R_INIT_FAILED);
+ /* Setup RSA */
+ ;
+ if ((dasync_rsa_orig = EVP_PKEY_meth_find(EVP_PKEY_RSA)) == NULL
+ || (dasync_rsa = EVP_PKEY_meth_new(EVP_PKEY_RSA,
+ EVP_PKEY_FLAG_AUTOARGLEN)) == NULL)
return 0;
- }
+ EVP_PKEY_meth_set_init(dasync_rsa, dasync_rsa_init);
+ EVP_PKEY_meth_set_cleanup(dasync_rsa, dasync_rsa_cleanup);
+ EVP_PKEY_meth_set_paramgen(dasync_rsa, dasync_rsa_paramgen_init,
+ dasync_rsa_paramgen);
+ EVP_PKEY_meth_set_keygen(dasync_rsa, dasync_rsa_keygen_init,
+ dasync_rsa_keygen);
+ EVP_PKEY_meth_set_encrypt(dasync_rsa, dasync_rsa_encrypt_init,
+ dasync_rsa_encrypt);
+ EVP_PKEY_meth_set_decrypt(dasync_rsa, dasync_rsa_decrypt_init,
+ dasync_rsa_decrypt);
+ EVP_PKEY_meth_set_ctrl(dasync_rsa, dasync_rsa_ctrl,
+ dasync_rsa_ctrl_str);
/* Ensure the dasync error handling is set up */
ERR_load_DASYNC_strings();
if (!ENGINE_set_id(e, engine_dasync_id)
|| !ENGINE_set_name(e, engine_dasync_name)
- || !ENGINE_set_RSA(e, dasync_rsa_method)
+ || !ENGINE_set_pkey_meths(e, dasync_pkey)
|| !ENGINE_set_digests(e, dasync_digests)
|| !ENGINE_set_ciphers(e, dasync_ciphers)
|| !ENGINE_set_destroy_function(e, dasync_destroy)
@@ -260,12 +301,35 @@ static int bind_dasync(ENGINE *e)
_hidden_aes_128_cbc = NULL;
}
+ _hidden_aes_256_ctr = EVP_CIPHER_meth_new(NID_aes_256_ctr,
+ 1 /* block size */,
+ 32 /* key len */);
+ if (_hidden_aes_256_ctr == NULL
+ || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_256_ctr,16)
+ || !EVP_CIPHER_meth_set_flags(_hidden_aes_256_ctr,
+ EVP_CIPH_FLAG_DEFAULT_ASN1
+ | EVP_CIPH_CTR_MODE
+ | EVP_CIPH_FLAG_PIPELINE
+ | EVP_CIPH_CUSTOM_COPY)
+ || !EVP_CIPHER_meth_set_init(_hidden_aes_256_ctr,
+ dasync_aes256_init_key)
+ || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_256_ctr,
+ dasync_aes256_ctr_cipher)
+ || !EVP_CIPHER_meth_set_cleanup(_hidden_aes_256_ctr,
+ dasync_aes256_ctr_cleanup)
+ || !EVP_CIPHER_meth_set_ctrl(_hidden_aes_256_ctr,
+ dasync_aes256_ctr_ctrl)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_256_ctr,
+ sizeof(struct dasync_pipeline_ctx))) {
+ EVP_CIPHER_meth_free(_hidden_aes_256_ctr);
+ _hidden_aes_256_ctr = NULL;
+ }
+
_hidden_aes_128_cbc_hmac_sha1 = EVP_CIPHER_meth_new(
NID_aes_128_cbc_hmac_sha1,
16 /* block size */,
16 /* key len */);
if (_hidden_aes_128_cbc_hmac_sha1 == NULL
- || EVP_aes_128_cbc_hmac_sha1() == NULL
|| !EVP_CIPHER_meth_set_iv_length(_hidden_aes_128_cbc_hmac_sha1,16)
|| !EVP_CIPHER_meth_set_flags(_hidden_aes_128_cbc_hmac_sha1,
EVP_CIPH_CBC_MODE
@@ -290,6 +354,16 @@ static int bind_dasync(ENGINE *e)
return 1;
}
+static void destroy_pkey(void)
+{
+ /*
+ * We don't actually need to free the dasync_rsa method since this is
+ * automatically freed for us by libcrypto.
+ */
+ dasync_rsa_orig = NULL;
+ dasync_rsa = NULL;
+}
+
# ifndef OPENSSL_NO_DYNAMIC_ENGINE
static int bind_helper(ENGINE *e, const char *id)
{
@@ -321,9 +395,19 @@ void engine_load_dasync_int(void)
ENGINE *toadd = engine_dasync();
if (!toadd)
return;
+ ERR_set_mark();
ENGINE_add(toadd);
+ /*
+ * If the "add" worked, it gets a structural reference. So either way, we
+ * release our just-created reference.
+ */
ENGINE_free(toadd);
- ERR_clear_error();
+ /*
+ * If the "add" didn't work, it was probably a conflict because it was
+ * already added (eg. someone calling ENGINE_load_blah then calling
+ * ENGINE_load_builtin_engines() perhaps).
+ */
+ ERR_pop_to_mark();
}
static int dasync_init(ENGINE *e)
@@ -342,11 +426,30 @@ static int dasync_destroy(ENGINE *e)
{
destroy_digests();
destroy_ciphers();
- RSA_meth_free(dasync_rsa_method);
+ destroy_pkey();
ERR_unload_DASYNC_strings();
return 1;
}
+static int dasync_pkey(ENGINE *e, EVP_PKEY_METHOD **pmeth,
+ const int **pnids, int nid)
+{
+ static const int rnid = EVP_PKEY_RSA;
+
+ if (pmeth == NULL) {
+ *pnids = &rnid;
+ return 1;
+ }
+
+ if (nid == EVP_PKEY_RSA) {
+ *pmeth = dasync_rsa;
+ return 1;
+ }
+
+ *pmeth = NULL;
+ return 0;
+}
+
static int dasync_digests(ENGINE *e, const EVP_MD **digest,
const int **nids, int nid)
{
@@ -374,10 +477,6 @@ static int dasync_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
int ok = 1;
if (cipher == NULL) {
/* We are returning a list of supported nids */
- if (dasync_aes_128_cbc_hmac_sha1() == NULL) {
- *nids = dasync_cipher_nids + 1;
- return 1;
- }
*nids = dasync_cipher_nids;
return (sizeof(dasync_cipher_nids) -
1) / sizeof(dasync_cipher_nids[0]);
@@ -387,6 +486,9 @@ static int dasync_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
case NID_aes_128_cbc:
*cipher = dasync_aes_128_cbc();
break;
+ case NID_aes_256_ctr:
+ *cipher = dasync_aes_256_ctr();
+ break;
case NID_aes_128_cbc_hmac_sha1:
*cipher = dasync_aes_128_cbc_hmac_sha1();
break;
@@ -417,6 +519,8 @@ static void wait_cleanup(ASYNC_WAIT_CTX *ctx, const void *key,
static void dummy_pause_job(void) {
ASYNC_JOB *job;
ASYNC_WAIT_CTX *waitctx;
+ ASYNC_callback_fn callback;
+ void * callback_arg;
OSSL_ASYNC_FD pipefds[2] = {0, 0};
OSSL_ASYNC_FD *writefd;
#if defined(ASYNC_WIN)
@@ -431,6 +535,18 @@ static void dummy_pause_job(void) {
waitctx = ASYNC_get_wait_ctx(job);
+ if (ASYNC_WAIT_CTX_get_callback(waitctx, &callback, &callback_arg) && callback != NULL) {
+ /*
+ * In the Dummy async engine we are cheating. We call the callback that the job
+ * is complete before the call to ASYNC_pause_job(). A real
+ * async engine would only call the callback when the job was actually complete
+ */
+ (*callback)(callback_arg);
+ ASYNC_pause_job();
+ return;
+ }
+
+
if (ASYNC_WAIT_CTX_get_fd(waitctx, engine_dasync_id, &pipefds[0],
(void **)&writefd)) {
pipefds[1] = *writefd;
@@ -485,13 +601,11 @@ static void dummy_pause_job(void) {
* SHA1 implementation. At the moment we just defer to the standard
* implementation
*/
-#undef data
-#define data(ctx) ((SHA_CTX *)EVP_MD_CTX_md_data(ctx))
static int dasync_sha1_init(EVP_MD_CTX *ctx)
{
dummy_pause_job();
- return SHA1_Init(data(ctx));
+ return EVP_MD_meth_get_init(EVP_sha1())(ctx);
}
static int dasync_sha1_update(EVP_MD_CTX *ctx, const void *data,
@@ -499,74 +613,21 @@ static int dasync_sha1_update(EVP_MD_CTX *ctx, const void *data,
{
dummy_pause_job();
- return SHA1_Update(data(ctx), data, (size_t)count);
+ return EVP_MD_meth_get_update(EVP_sha1())(ctx, data, count);
}
static int dasync_sha1_final(EVP_MD_CTX *ctx, unsigned char *md)
{
dummy_pause_job();
- return SHA1_Final(md, data(ctx));
-}
-
-/*
- * RSA implementation
- */
-
-static int dasync_pub_enc(int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding) {
- /* Ignore errors - we carry on anyway */
- dummy_pause_job();
- return RSA_meth_get_pub_enc(RSA_PKCS1_OpenSSL())
- (flen, from, to, rsa, padding);
-}
-
-static int dasync_pub_dec(int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding) {
- /* Ignore errors - we carry on anyway */
- dummy_pause_job();
- return RSA_meth_get_pub_dec(RSA_PKCS1_OpenSSL())
- (flen, from, to, rsa, padding);
-}
-
-static int dasync_rsa_priv_enc(int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding)
-{
- /* Ignore errors - we carry on anyway */
- dummy_pause_job();
- return RSA_meth_get_priv_enc(RSA_PKCS1_OpenSSL())
- (flen, from, to, rsa, padding);
-}
-
-static int dasync_rsa_priv_dec(int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding)
-{
- /* Ignore errors - we carry on anyway */
- dummy_pause_job();
- return RSA_meth_get_priv_dec(RSA_PKCS1_OpenSSL())
- (flen, from, to, rsa, padding);
-}
-
-static int dasync_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
-{
- /* Ignore errors - we carry on anyway */
- dummy_pause_job();
- return RSA_meth_get_mod_exp(RSA_PKCS1_OpenSSL())(r0, I, rsa, ctx);
-}
-
-static int dasync_rsa_init(RSA *rsa)
-{
- return RSA_meth_get_init(RSA_PKCS1_OpenSSL())(rsa);
-}
-static int dasync_rsa_finish(RSA *rsa)
-{
- return RSA_meth_get_finish(RSA_PKCS1_OpenSSL())(rsa);
+ return EVP_MD_meth_get_final(EVP_sha1())(ctx, md);
}
/* Cipher helper functions */
static int dasync_cipher_ctrl_helper(EVP_CIPHER_CTX *ctx, int type, int arg,
- void *ptr, int aeadcapable)
+ void *ptr, int aeadcapable,
+ const EVP_CIPHER *ciph)
{
int ret;
struct dasync_pipeline_ctx *pipe_ctx =
@@ -576,6 +637,18 @@ static int dasync_cipher_ctrl_helper(EVP_CIPHER_CTX *ctx, int type, int arg,
return 0;
switch (type) {
+ case EVP_CTRL_COPY:
+ {
+ size_t sz = EVP_CIPHER_impl_ctx_size(ciph);
+ void *inner_cipher_data = OPENSSL_malloc(sz);
+
+ if (inner_cipher_data == NULL)
+ return -1;
+ memcpy(inner_cipher_data, pipe_ctx->inner_cipher_data, sz);
+ pipe_ctx->inner_cipher_data = inner_cipher_data;
+ }
+ break;
+
case EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS:
pipe_ctx->numpipes = arg;
pipe_ctx->outbufs = (unsigned char **)ptr;
@@ -617,7 +690,7 @@ static int dasync_cipher_ctrl_helper(EVP_CIPHER_CTX *ctx, int type, int arg,
len = p[arg - 2] << 8 | p[arg - 1];
- if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
if ((p[arg - 4] << 8 | p[arg - 3]) >= TLS1_1_VERSION) {
if (len < AES_BLOCK_SIZE)
return 0;
@@ -631,21 +704,6 @@ static int dasync_cipher_ctrl_helper(EVP_CIPHER_CTX *ctx, int type, int arg,
}
}
- case EVP_CTRL_COPY:
- {
- const EVP_CIPHER *cipher = aeadcapable
- ? EVP_aes_128_cbc_hmac_sha1()
- : EVP_aes_128_cbc();
- size_t data_size = EVP_CIPHER_impl_ctx_size(cipher);
- void *cipher_data = OPENSSL_malloc(data_size);
-
- if (cipher_data == NULL)
- return 0;
- memcpy(cipher_data, pipe_ctx->inner_cipher_data, data_size);
- pipe_ctx->inner_cipher_data = cipher_data;
- return 1;
- }
-
default:
return 0;
}
@@ -745,7 +803,7 @@ static int dasync_cipher_cleanup_helper(EVP_CIPHER_CTX *ctx,
static int dasync_aes128_cbc_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
void *ptr)
{
- return dasync_cipher_ctrl_helper(ctx, type, arg, ptr, 0);
+ return dasync_cipher_ctrl_helper(ctx, type, arg, ptr, 0, EVP_aes_128_cbc());
}
static int dasync_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
@@ -765,6 +823,29 @@ static int dasync_aes128_cbc_cleanup(EVP_CIPHER_CTX *ctx)
return dasync_cipher_cleanup_helper(ctx, EVP_aes_128_cbc());
}
+static int dasync_aes256_ctr_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
+ void *ptr)
+{
+ return dasync_cipher_ctrl_helper(ctx, type, arg, ptr, 0, EVP_aes_256_ctr());
+}
+
+static int dasync_aes256_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ return dasync_cipher_init_key_helper(ctx, key, iv, enc, EVP_aes_256_ctr());
+}
+
+static int dasync_aes256_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ return dasync_cipher_helper(ctx, out, in, inl, EVP_aes_256_ctr());
+}
+
+static int dasync_aes256_ctr_cleanup(EVP_CIPHER_CTX *ctx)
+{
+ return dasync_cipher_cleanup_helper(ctx, EVP_aes_256_ctr());
+}
+
/*
* AES128 CBC HMAC SHA1 Implementation
@@ -773,7 +854,7 @@ static int dasync_aes128_cbc_cleanup(EVP_CIPHER_CTX *ctx)
static int dasync_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type,
int arg, void *ptr)
{
- return dasync_cipher_ctrl_helper(ctx, type, arg, ptr, 1);
+ return dasync_cipher_ctrl_helper(ctx, type, arg, ptr, 1, EVP_aes_128_cbc_hmac_sha1());
}
static int dasync_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx,
@@ -805,3 +886,125 @@ static int dasync_aes128_cbc_hmac_sha1_cleanup(EVP_CIPHER_CTX *ctx)
*/
return dasync_cipher_cleanup_helper(ctx, EVP_aes_128_cbc_hmac_sha1());
}
+
+
+/*
+ * RSA implementation
+ */
+static int dasync_rsa_init(EVP_PKEY_CTX *ctx)
+{
+ static int (*pinit)(EVP_PKEY_CTX *ctx);
+
+ if (pinit == NULL)
+ EVP_PKEY_meth_get_init(dasync_rsa_orig, &pinit);
+ return pinit(ctx);
+}
+
+static void dasync_rsa_cleanup(EVP_PKEY_CTX *ctx)
+{
+ static void (*pcleanup)(EVP_PKEY_CTX *ctx);
+
+ if (pcleanup == NULL)
+ EVP_PKEY_meth_get_cleanup(dasync_rsa_orig, &pcleanup);
+ pcleanup(ctx);
+}
+
+static int dasync_rsa_paramgen_init(EVP_PKEY_CTX *ctx)
+{
+ static int (*pparamgen_init)(EVP_PKEY_CTX *ctx);
+
+ if (pparamgen_init == NULL)
+ EVP_PKEY_meth_get_paramgen(dasync_rsa_orig, &pparamgen_init, NULL);
+ return pparamgen_init != NULL ? pparamgen_init(ctx) : 1;
+}
+
+static int dasync_rsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+ static int (*pparamgen)(EVP_PKEY_CTX *c, EVP_PKEY *pkey);
+
+ if (pparamgen == NULL)
+ EVP_PKEY_meth_get_paramgen(dasync_rsa_orig, NULL, &pparamgen);
+ return pparamgen != NULL ? pparamgen(ctx, pkey) : 1;
+}
+
+static int dasync_rsa_keygen_init(EVP_PKEY_CTX *ctx)
+{
+ static int (*pkeygen_init)(EVP_PKEY_CTX *ctx);
+
+ if (pkeygen_init == NULL)
+ EVP_PKEY_meth_get_keygen(dasync_rsa_orig, &pkeygen_init, NULL);
+ return pkeygen_init != NULL ? pkeygen_init(ctx) : 1;
+}
+
+static int dasync_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+ static int (*pkeygen)(EVP_PKEY_CTX *c, EVP_PKEY *pkey);
+
+ if (pkeygen == NULL)
+ EVP_PKEY_meth_get_keygen(dasync_rsa_orig, NULL, &pkeygen);
+ return pkeygen(ctx, pkey);
+}
+
+static int dasync_rsa_encrypt_init(EVP_PKEY_CTX *ctx)
+{
+ static int (*pencrypt_init)(EVP_PKEY_CTX *ctx);
+
+ if (pencrypt_init == NULL)
+ EVP_PKEY_meth_get_encrypt(dasync_rsa_orig, &pencrypt_init, NULL);
+ return pencrypt_init != NULL ? pencrypt_init(ctx) : 1;
+}
+
+static int dasync_rsa_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out,
+ size_t *outlen, const unsigned char *in,
+ size_t inlen)
+{
+ static int (*pencryptfn)(EVP_PKEY_CTX *ctx, unsigned char *out,
+ size_t *outlen, const unsigned char *in,
+ size_t inlen);
+
+ if (pencryptfn == NULL)
+ EVP_PKEY_meth_get_encrypt(dasync_rsa_orig, NULL, &pencryptfn);
+ return pencryptfn(ctx, out, outlen, in, inlen);
+}
+
+static int dasync_rsa_decrypt_init(EVP_PKEY_CTX *ctx)
+{
+ static int (*pdecrypt_init)(EVP_PKEY_CTX *ctx);
+
+ if (pdecrypt_init == NULL)
+ EVP_PKEY_meth_get_decrypt(dasync_rsa_orig, &pdecrypt_init, NULL);
+ return pdecrypt_init != NULL ? pdecrypt_init(ctx) : 1;
+}
+
+static int dasync_rsa_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out,
+ size_t *outlen, const unsigned char *in,
+ size_t inlen)
+{
+ static int (*pdecrypt)(EVP_PKEY_CTX *ctx, unsigned char *out,
+ size_t *outlen, const unsigned char *in,
+ size_t inlen);
+
+ if (pdecrypt == NULL)
+ EVP_PKEY_meth_get_encrypt(dasync_rsa_orig, NULL, &pdecrypt);
+ return pdecrypt(ctx, out, outlen, in, inlen);
+}
+
+static int dasync_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+{
+ static int (*pctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2);
+
+ if (pctrl == NULL)
+ EVP_PKEY_meth_get_ctrl(dasync_rsa_orig, &pctrl, NULL);
+ return pctrl(ctx, type, p1, p2);
+}
+
+static int dasync_rsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
+ const char *value)
+{
+ static int (*pctrl_str)(EVP_PKEY_CTX *ctx, const char *type,
+ const char *value);
+
+ if (pctrl_str == NULL)
+ EVP_PKEY_meth_get_ctrl(dasync_rsa_orig, NULL, &pctrl_str);
+ return pctrl_str(ctx, type, value);
+}
diff --git a/engines/e_dasync.txt b/engines/e_dasync.txt
index bff64bcf2f54..d050a148c308 100644
--- a/engines/e_dasync.txt
+++ b/engines/e_dasync.txt
@@ -1,22 +1,9 @@
-# Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
-# Function codes
-DASYNC_F_BIND_DASYNC:107:bind_dasync
-DASYNC_F_CIPHER_AES_128_CBC_CODE:100:*
-DASYNC_F_DASYNC_AES128_CBC_HMAC_SHA1_INIT_KEY:109:*
-DASYNC_F_DASYNC_AES128_INIT_KEY:108:*
-DASYNC_F_DASYNC_BN_MOD_EXP:101:*
-DASYNC_F_DASYNC_CIPHER_INIT_KEY_HELPER:110:dasync_cipher_init_key_helper
-DASYNC_F_DASYNC_MOD_EXP:102:*
-DASYNC_F_DASYNC_PRIVATE_DECRYPT:103:*
-DASYNC_F_DASYNC_PRIVATE_ENCRYPT:104:*
-DASYNC_F_DASYNC_PUBLIC_DECRYPT:105:*
-DASYNC_F_DASYNC_PUBLIC_ENCRYPT:106:*
-
#Reason codes
DASYNC_R_INIT_FAILED:100:init failed
diff --git a/engines/e_dasync_err.c b/engines/e_dasync_err.c
index 794fb710cf6e..16021f3196dd 100644
--- a/engines/e_dasync_err.c
+++ b/engines/e_dasync_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,22 +13,6 @@
#ifndef OPENSSL_NO_ERR
-static ERR_STRING_DATA DASYNC_str_functs[] = {
- {ERR_PACK(0, DASYNC_F_BIND_DASYNC, 0), "bind_dasync"},
- {ERR_PACK(0, DASYNC_F_CIPHER_AES_128_CBC_CODE, 0), ""},
- {ERR_PACK(0, DASYNC_F_DASYNC_AES128_CBC_HMAC_SHA1_INIT_KEY, 0), ""},
- {ERR_PACK(0, DASYNC_F_DASYNC_AES128_INIT_KEY, 0), ""},
- {ERR_PACK(0, DASYNC_F_DASYNC_BN_MOD_EXP, 0), ""},
- {ERR_PACK(0, DASYNC_F_DASYNC_CIPHER_INIT_KEY_HELPER, 0),
- "dasync_cipher_init_key_helper"},
- {ERR_PACK(0, DASYNC_F_DASYNC_MOD_EXP, 0), ""},
- {ERR_PACK(0, DASYNC_F_DASYNC_PRIVATE_DECRYPT, 0), ""},
- {ERR_PACK(0, DASYNC_F_DASYNC_PRIVATE_ENCRYPT, 0), ""},
- {ERR_PACK(0, DASYNC_F_DASYNC_PUBLIC_DECRYPT, 0), ""},
- {ERR_PACK(0, DASYNC_F_DASYNC_PUBLIC_ENCRYPT, 0), ""},
- {0, NULL}
-};
-
static ERR_STRING_DATA DASYNC_str_reasons[] = {
{ERR_PACK(0, 0, DASYNC_R_INIT_FAILED), "init failed"},
{0, NULL}
@@ -46,7 +30,6 @@ static int ERR_load_DASYNC_strings(void)
if (!error_loaded) {
#ifndef OPENSSL_NO_ERR
- ERR_load_strings(lib_code, DASYNC_str_functs);
ERR_load_strings(lib_code, DASYNC_str_reasons);
#endif
error_loaded = 1;
@@ -58,16 +41,16 @@ static void ERR_unload_DASYNC_strings(void)
{
if (error_loaded) {
#ifndef OPENSSL_NO_ERR
- ERR_unload_strings(lib_code, DASYNC_str_functs);
ERR_unload_strings(lib_code, DASYNC_str_reasons);
#endif
error_loaded = 0;
}
}
-static void ERR_DASYNC_error(int function, int reason, char *file, int line)
+static void ERR_DASYNC_error(int function, int reason, const char *file, int line)
{
if (lib_code == 0)
lib_code = ERR_get_next_error_library();
- ERR_PUT_error(lib_code, function, reason, file, line);
+ ERR_raise(lib_code, reason);
+ ERR_set_debug(file, line, NULL);
}
diff --git a/engines/e_dasync_err.h b/engines/e_dasync_err.h
index 5b74d8be25f1..7a067c6037a6 100644
--- a/engines/e_dasync_err.h
+++ b/engines/e_dasync_err.h
@@ -1,33 +1,23 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef OSSL_ENGINES_E_DASYNC_ERR_H
-# define OSSL_ENGINES_E_DASYNC_ERR_H
+#ifndef OSSL_E_DASYNC_ERR_H
+# define OSSL_E_DASYNC_ERR_H
+# pragma once
-# define DASYNCerr(f, r) ERR_DASYNC_error((f), (r), OPENSSL_FILE, OPENSSL_LINE)
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
-/*
- * DASYNC function codes.
- */
-# define DASYNC_F_BIND_DASYNC 107
-# define DASYNC_F_CIPHER_AES_128_CBC_CODE 100
-# define DASYNC_F_DASYNC_AES128_CBC_HMAC_SHA1_INIT_KEY 109
-# define DASYNC_F_DASYNC_AES128_INIT_KEY 108
-# define DASYNC_F_DASYNC_BN_MOD_EXP 101
-# define DASYNC_F_DASYNC_CIPHER_INIT_KEY_HELPER 110
-# define DASYNC_F_DASYNC_MOD_EXP 102
-# define DASYNC_F_DASYNC_PRIVATE_DECRYPT 103
-# define DASYNC_F_DASYNC_PRIVATE_ENCRYPT 104
-# define DASYNC_F_DASYNC_PUBLIC_DECRYPT 105
-# define DASYNC_F_DASYNC_PUBLIC_ENCRYPT 106
+# define DASYNCerr(f, r) ERR_DASYNC_error(0, (r), OPENSSL_FILE, OPENSSL_LINE)
+
/*
* DASYNC reason codes.
diff --git a/engines/e_devcrypto.c b/engines/e_devcrypto.c
new file mode 100644
index 000000000000..b42317522730
--- /dev/null
+++ b/engines/e_devcrypto.c
@@ -0,0 +1,1382 @@
+/*
+ * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* We need to use some deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include "../e_os.h"
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include <openssl/conf.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/engine.h>
+#include <openssl/objects.h>
+#include "crypto/cryptodev.h"
+
+/* #define ENGINE_DEVCRYPTO_DEBUG */
+
+#if CRYPTO_ALGORITHM_MIN < CRYPTO_ALGORITHM_MAX
+# define CHECK_BSD_STYLE_MACROS
+#endif
+
+#define engine_devcrypto_id "devcrypto"
+
+/*
+ * Use session2_op on FreeBSD which permits requesting specific
+ * drivers or classes of drivers at session creation time.
+ */
+#ifdef CIOCGSESSION2
+typedef struct session2_op session_op_t;
+#else
+typedef struct session_op session_op_t;
+#endif
+
+/*
+ * ONE global file descriptor for all sessions. This allows operations
+ * such as digest session data copying (see digest_copy()), but is also
+ * saner... why re-open /dev/crypto for every session?
+ */
+static int cfd = -1;
+#define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */
+#define DEVCRYPTO_USE_SOFTWARE 1 /* allow software drivers */
+#define DEVCRYPTO_REJECT_SOFTWARE 2 /* only disallow confirmed software drivers */
+
+#define DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS DEVCRYPTO_REJECT_SOFTWARE
+static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS;
+
+/*
+ * cipher/digest status & acceleration definitions
+ * Make sure the defaults are set to 0
+ */
+struct driver_info_st {
+ enum devcrypto_status_t {
+ DEVCRYPTO_STATUS_FAILURE = -3, /* unusable for other reason */
+ DEVCRYPTO_STATUS_NO_CIOCCPHASH = -2, /* hash state copy not supported */
+ DEVCRYPTO_STATUS_NO_CIOCGSESSION = -1, /* session open failed */
+ DEVCRYPTO_STATUS_UNKNOWN = 0, /* not tested yet */
+ DEVCRYPTO_STATUS_USABLE = 1 /* algo can be used */
+ } status;
+
+ enum devcrypto_accelerated_t {
+ DEVCRYPTO_NOT_ACCELERATED = -1, /* software implemented */
+ DEVCRYPTO_ACCELERATION_UNKNOWN = 0, /* acceleration support unknown */
+ DEVCRYPTO_ACCELERATED = 1 /* hardware accelerated */
+ } accelerated;
+
+ char *driver_name;
+};
+
+#ifdef OPENSSL_NO_DYNAMIC_ENGINE
+void engine_load_devcrypto_int(void);
+#endif
+
+static int clean_devcrypto_session(session_op_t *sess) {
+ if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) {
+ ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
+ return 0;
+ }
+ memset(sess, 0, sizeof(*sess));
+ return 1;
+}
+
+/******************************************************************************
+ *
+ * Ciphers
+ *
+ * Because they all do the same basic operation, we have only one set of
+ * method functions for them all to share, and a mapping table between
+ * NIDs and cryptodev IDs, with all the necessary size data.
+ *
+ *****/
+
+struct cipher_ctx {
+ session_op_t sess;
+ int op; /* COP_ENCRYPT or COP_DECRYPT */
+ unsigned long mode; /* EVP_CIPH_*_MODE */
+
+ /* to handle ctr mode being a stream cipher */
+ unsigned char partial[EVP_MAX_BLOCK_LENGTH];
+ unsigned int blocksize, num;
+};
+
+static const struct cipher_data_st {
+ int nid;
+ int blocksize;
+ int keylen;
+ int ivlen;
+ int flags;
+ int devcryptoid;
+} cipher_data[] = {
+#ifndef OPENSSL_NO_DES
+ { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC },
+ { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC },
+#endif
+#ifndef OPENSSL_NO_BF
+ { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC },
+#endif
+#ifndef OPENSSL_NO_CAST
+ { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC },
+#endif
+ { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
+ { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
+ { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
+#ifndef OPENSSL_NO_RC4
+ { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 },
+#endif
+#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR)
+ { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
+ { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
+ { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
+#endif
+#if 0 /* Not yet supported */
+ { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
+ { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
+#endif
+#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB)
+ { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
+ { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
+ { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
+#endif
+#if 0 /* Not yet supported */
+ { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
+ { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
+ { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+ { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE,
+ CRYPTO_CAMELLIA_CBC },
+ { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE,
+ CRYPTO_CAMELLIA_CBC },
+ { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE,
+ CRYPTO_CAMELLIA_CBC },
+#endif
+};
+
+static size_t find_cipher_data_index(int nid)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(cipher_data); i++)
+ if (nid == cipher_data[i].nid)
+ return i;
+ return (size_t)-1;
+}
+
+static size_t get_cipher_data_index(int nid)
+{
+ size_t i = find_cipher_data_index(nid);
+
+ if (i != (size_t)-1)
+ return i;
+
+ /*
+ * Code further down must make sure that only NIDs in the table above
+ * are used. If any other NID reaches this function, there's a grave
+ * coding error further down.
+ */
+ assert("Code that never should be reached" == NULL);
+ return -1;
+}
+
+static const struct cipher_data_st *get_cipher_data(int nid)
+{
+ return &cipher_data[get_cipher_data_index(nid)];
+}
+
+/*
+ * Following are the three necessary functions to map OpenSSL functionality
+ * with cryptodev.
+ */
+
+static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ struct cipher_ctx *cipher_ctx =
+ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
+ const struct cipher_data_st *cipher_d =
+ get_cipher_data(EVP_CIPHER_CTX_get_nid(ctx));
+ int ret;
+
+ /* cleanup a previous session */
+ if (cipher_ctx->sess.ses != 0 &&
+ clean_devcrypto_session(&cipher_ctx->sess) == 0)
+ return 0;
+
+ cipher_ctx->sess.cipher = cipher_d->devcryptoid;
+ cipher_ctx->sess.keylen = cipher_d->keylen;
+ cipher_ctx->sess.key = (void *)key;
+ cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT;
+ cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE;
+ cipher_ctx->blocksize = cipher_d->blocksize;
+#ifdef CIOCGSESSION2
+ cipher_ctx->sess.crid = (use_softdrivers == DEVCRYPTO_USE_SOFTWARE) ?
+ CRYPTO_FLAG_SOFTWARE | CRYPTO_FLAG_HARDWARE :
+ CRYPTO_FLAG_HARDWARE;
+ ret = ioctl(cfd, CIOCGSESSION2, &cipher_ctx->sess);
+#else
+ ret = ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess);
+#endif
+ if (ret < 0) {
+ ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ struct cipher_ctx *cipher_ctx =
+ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
+ struct crypt_op cryp;
+ unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
+#if !defined(COP_FLAG_WRITE_IV)
+ unsigned char saved_iv[EVP_MAX_IV_LENGTH];
+ const unsigned char *ivptr;
+ size_t nblocks, ivlen;
+#endif
+
+ memset(&cryp, 0, sizeof(cryp));
+ cryp.ses = cipher_ctx->sess.ses;
+ cryp.len = inl;
+ cryp.src = (void *)in;
+ cryp.dst = (void *)out;
+ cryp.iv = (void *)iv;
+ cryp.op = cipher_ctx->op;
+#if !defined(COP_FLAG_WRITE_IV)
+ cryp.flags = 0;
+
+ ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
+ if (ivlen > 0)
+ switch (cipher_ctx->mode) {
+ case EVP_CIPH_CBC_MODE:
+ assert(inl >= ivlen);
+ if (!EVP_CIPHER_CTX_is_encrypting(ctx)) {
+ ivptr = in + inl - ivlen;
+ memcpy(saved_iv, ivptr, ivlen);
+ }
+ break;
+
+ case EVP_CIPH_CTR_MODE:
+ break;
+
+ default: /* should not happen */
+ return 0;
+ }
+#else
+ cryp.flags = COP_FLAG_WRITE_IV;
+#endif
+
+ if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) {
+ ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
+ return 0;
+ }
+
+#if !defined(COP_FLAG_WRITE_IV)
+ if (ivlen > 0)
+ switch (cipher_ctx->mode) {
+ case EVP_CIPH_CBC_MODE:
+ assert(inl >= ivlen);
+ if (EVP_CIPHER_CTX_is_encrypting(ctx))
+ ivptr = out + inl - ivlen;
+ else
+ ivptr = saved_iv;
+
+ memcpy(iv, ivptr, ivlen);
+ break;
+
+ case EVP_CIPH_CTR_MODE:
+ nblocks = (inl + cipher_ctx->blocksize - 1)
+ / cipher_ctx->blocksize;
+ do {
+ ivlen--;
+ nblocks += iv[ivlen];
+ iv[ivlen] = (uint8_t) nblocks;
+ nblocks >>= 8;
+ } while (ivlen);
+ break;
+
+ default: /* should not happen */
+ return 0;
+ }
+#endif
+
+ return 1;
+}
+
+static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ struct cipher_ctx *cipher_ctx =
+ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
+ size_t nblocks, len;
+
+ /* initial partial block */
+ while (cipher_ctx->num && inl) {
+ (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num];
+ --inl;
+ cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize;
+ }
+
+ /* full blocks */
+ if (inl > (unsigned int) cipher_ctx->blocksize) {
+ nblocks = inl/cipher_ctx->blocksize;
+ len = nblocks * cipher_ctx->blocksize;
+ if (cipher_do_cipher(ctx, out, in, len) < 1)
+ return 0;
+ inl -= len;
+ out += len;
+ in += len;
+ }
+
+ /* final partial block */
+ if (inl) {
+ memset(cipher_ctx->partial, 0, cipher_ctx->blocksize);
+ if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial,
+ cipher_ctx->blocksize) < 1)
+ return 0;
+ while (inl--) {
+ out[cipher_ctx->num] = in[cipher_ctx->num]
+ ^ cipher_ctx->partial[cipher_ctx->num];
+ cipher_ctx->num++;
+ }
+ }
+
+ return 1;
+}
+
+static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2)
+{
+ struct cipher_ctx *cipher_ctx =
+ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
+ EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2;
+ struct cipher_ctx *to_cipher_ctx;
+
+ switch (type) {
+
+ case EVP_CTRL_COPY:
+ if (cipher_ctx == NULL)
+ return 1;
+ /* when copying the context, a new session needs to be initialized */
+ to_cipher_ctx =
+ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx);
+ memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess));
+ return cipher_init(to_ctx, (void *)cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx),
+ (cipher_ctx->op == COP_ENCRYPT));
+
+ case EVP_CTRL_INIT:
+ memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess));
+ return 1;
+
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+static int cipher_cleanup(EVP_CIPHER_CTX *ctx)
+{
+ struct cipher_ctx *cipher_ctx =
+ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
+
+ return clean_devcrypto_session(&cipher_ctx->sess);
+}
+
+/*
+ * Keep tables of known nids, associated methods, selected ciphers, and driver
+ * info.
+ * Note that known_cipher_nids[] isn't necessarily indexed the same way as
+ * cipher_data[] above, which the other tables are.
+ */
+static int known_cipher_nids[OSSL_NELEM(cipher_data)];
+static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */
+static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, };
+static int selected_ciphers[OSSL_NELEM(cipher_data)];
+static struct driver_info_st cipher_driver_info[OSSL_NELEM(cipher_data)];
+
+
+static int devcrypto_test_cipher(size_t cipher_data_index)
+{
+ return (cipher_driver_info[cipher_data_index].status == DEVCRYPTO_STATUS_USABLE
+ && selected_ciphers[cipher_data_index] == 1
+ && (cipher_driver_info[cipher_data_index].accelerated
+ == DEVCRYPTO_ACCELERATED
+ || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
+ || (cipher_driver_info[cipher_data_index].accelerated
+ != DEVCRYPTO_NOT_ACCELERATED
+ && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
+}
+
+static void prepare_cipher_methods(void)
+{
+ size_t i;
+ session_op_t sess;
+ unsigned long cipher_mode;
+#ifdef CIOCGSESSION2
+ struct crypt_find_op fop;
+ enum devcrypto_accelerated_t accelerated;
+#elif defined(CIOCGSESSINFO)
+ struct session_info_op siop;
+#endif
+
+ memset(&cipher_driver_info, 0, sizeof(cipher_driver_info));
+
+ memset(&sess, 0, sizeof(sess));
+ sess.key = (void *)"01234567890123456789012345678901234567890123456789";
+
+ for (i = 0, known_cipher_nids_amount = 0;
+ i < OSSL_NELEM(cipher_data); i++) {
+
+ selected_ciphers[i] = 1;
+ /*
+ * Check that the cipher is usable
+ */
+ sess.cipher = cipher_data[i].devcryptoid;
+ sess.keylen = cipher_data[i].keylen;
+#ifdef CIOCGSESSION2
+ /*
+ * When using CIOCGSESSION2, first try to allocate a hardware
+ * ("accelerated") session. If that fails, fall back to
+ * allocating a software session.
+ */
+ sess.crid = CRYPTO_FLAG_HARDWARE;
+ if (ioctl(cfd, CIOCGSESSION2, &sess) == 0) {
+ accelerated = DEVCRYPTO_ACCELERATED;
+ } else {
+ sess.crid = CRYPTO_FLAG_SOFTWARE;
+ if (ioctl(cfd, CIOCGSESSION2, &sess) < 0) {
+ cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
+ continue;
+ }
+ accelerated = DEVCRYPTO_NOT_ACCELERATED;
+ }
+#else
+ if (ioctl(cfd, CIOCGSESSION, &sess) < 0) {
+ cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
+ continue;
+ }
+#endif
+
+ cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE;
+
+ if ((known_cipher_methods[i] =
+ EVP_CIPHER_meth_new(cipher_data[i].nid,
+ cipher_mode == EVP_CIPH_CTR_MODE ? 1 :
+ cipher_data[i].blocksize,
+ cipher_data[i].keylen)) == NULL
+ || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i],
+ cipher_data[i].ivlen)
+ || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i],
+ cipher_data[i].flags
+ | EVP_CIPH_CUSTOM_COPY
+ | EVP_CIPH_CTRL_INIT
+ | EVP_CIPH_FLAG_DEFAULT_ASN1)
+ || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init)
+ || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i],
+ cipher_mode == EVP_CIPH_CTR_MODE ?
+ ctr_do_cipher :
+ cipher_do_cipher)
+ || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl)
+ || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i],
+ cipher_cleanup)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
+ sizeof(struct cipher_ctx))) {
+ cipher_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
+ EVP_CIPHER_meth_free(known_cipher_methods[i]);
+ known_cipher_methods[i] = NULL;
+ } else {
+ cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
+#ifdef CIOCGSESSION2
+ cipher_driver_info[i].accelerated = accelerated;
+ fop.crid = sess.crid;
+ if (ioctl(cfd, CIOCFINDDEV, &fop) == 0) {
+ cipher_driver_info[i].driver_name =
+ OPENSSL_strndup(fop.name, sizeof(fop.name));
+ }
+#elif defined(CIOCGSESSINFO)
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
+ cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
+ } else {
+ cipher_driver_info[i].driver_name =
+ OPENSSL_strndup(siop.cipher_info.cra_driver_name,
+ CRYPTODEV_MAX_ALG_NAME);
+ if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
+ cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
+ else
+ cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
+ }
+#endif /* CIOCGSESSINFO */
+ }
+ ioctl(cfd, CIOCFSESSION, &sess.ses);
+ if (devcrypto_test_cipher(i)) {
+ known_cipher_nids[known_cipher_nids_amount++] =
+ cipher_data[i].nid;
+ }
+ }
+}
+
+static void rebuild_known_cipher_nids(ENGINE *e)
+{
+ size_t i;
+
+ for (i = 0, known_cipher_nids_amount = 0; i < OSSL_NELEM(cipher_data); i++) {
+ if (devcrypto_test_cipher(i))
+ known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid;
+ }
+ ENGINE_unregister_ciphers(e);
+ ENGINE_register_ciphers(e);
+}
+
+static const EVP_CIPHER *get_cipher_method(int nid)
+{
+ size_t i = get_cipher_data_index(nid);
+
+ if (i == (size_t)-1)
+ return NULL;
+ return known_cipher_methods[i];
+}
+
+static int get_cipher_nids(const int **nids)
+{
+ *nids = known_cipher_nids;
+ return known_cipher_nids_amount;
+}
+
+static void destroy_cipher_method(int nid)
+{
+ size_t i = get_cipher_data_index(nid);
+
+ EVP_CIPHER_meth_free(known_cipher_methods[i]);
+ known_cipher_methods[i] = NULL;
+}
+
+static void destroy_all_cipher_methods(void)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
+ destroy_cipher_method(cipher_data[i].nid);
+ OPENSSL_free(cipher_driver_info[i].driver_name);
+ cipher_driver_info[i].driver_name = NULL;
+ }
+}
+
+static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
+ const int **nids, int nid)
+{
+ if (cipher == NULL)
+ return get_cipher_nids(nids);
+
+ *cipher = get_cipher_method(nid);
+
+ return *cipher != NULL;
+}
+
+static void devcrypto_select_all_ciphers(int *cipher_list)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(cipher_data); i++)
+ cipher_list[i] = 1;
+}
+
+static int cryptodev_select_cipher_cb(const char *str, int len, void *usr)
+{
+ int *cipher_list = (int *)usr;
+ char *name;
+ const EVP_CIPHER *EVP;
+ size_t i;
+
+ if (len == 0)
+ return 1;
+ if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
+ return 0;
+ EVP = EVP_get_cipherbyname(name);
+ if (EVP == NULL)
+ fprintf(stderr, "devcrypto: unknown cipher %s\n", name);
+ else if ((i = find_cipher_data_index(EVP_CIPHER_get_nid(EVP))) != (size_t)-1)
+ cipher_list[i] = 1;
+ else
+ fprintf(stderr, "devcrypto: cipher %s not available\n", name);
+ OPENSSL_free(name);
+ return 1;
+}
+
+static void dump_cipher_info(void)
+{
+ size_t i;
+ const char *name;
+
+ fprintf (stderr, "Information about ciphers supported by the /dev/crypto"
+ " engine:\n");
+#ifndef CIOCGSESSINFO
+ fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
+#endif
+ for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
+ name = OBJ_nid2sn(cipher_data[i].nid);
+ fprintf (stderr, "Cipher %s, NID=%d, /dev/crypto info: id=%d, ",
+ name ? name : "unknown", cipher_data[i].nid,
+ cipher_data[i].devcryptoid);
+ if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION ) {
+ fprintf (stderr, "CIOCGSESSION (session open call) failed\n");
+ continue;
+ }
+ fprintf (stderr, "driver=%s ", cipher_driver_info[i].driver_name ?
+ cipher_driver_info[i].driver_name : "unknown");
+ if (cipher_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
+ fprintf(stderr, "(hw accelerated)");
+ else if (cipher_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
+ fprintf(stderr, "(software)");
+ else
+ fprintf(stderr, "(acceleration status unknown)");
+ if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
+ fprintf (stderr, ". Cipher setup failed");
+ fprintf(stderr, "\n");
+ }
+ fprintf(stderr, "\n");
+}
+
+/*
+ * We only support digests if the cryptodev implementation supports multiple
+ * data updates and session copying. Otherwise, we would be forced to maintain
+ * a cache, which is perilous if there's a lot of data coming in (if someone
+ * wants to checksum an OpenSSL tarball, for example).
+ */
+#if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
+#define IMPLEMENT_DIGEST
+
+/******************************************************************************
+ *
+ * Digests
+ *
+ * Because they all do the same basic operation, we have only one set of
+ * method functions for them all to share, and a mapping table between
+ * NIDs and cryptodev IDs, with all the necessary size data.
+ *
+ *****/
+
+struct digest_ctx {
+ session_op_t sess;
+ /* This signals that the init function was called, not that it succeeded. */
+ int init_called;
+ unsigned char digest_res[HASH_MAX_LEN];
+};
+
+static const struct digest_data_st {
+ int nid;
+ int blocksize;
+ int digestlen;
+ int devcryptoid;
+} digest_data[] = {
+#ifndef OPENSSL_NO_MD5
+ { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 },
+#endif
+ { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 },
+#ifndef OPENSSL_NO_RMD160
+# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160)
+ { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 },
+# endif
+#endif
+#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224)
+ { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 },
+#endif
+#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256)
+ { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 },
+#endif
+#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384)
+ { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 },
+#endif
+#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512)
+ { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 },
+#endif
+};
+
+static size_t find_digest_data_index(int nid)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(digest_data); i++)
+ if (nid == digest_data[i].nid)
+ return i;
+ return (size_t)-1;
+}
+
+static size_t get_digest_data_index(int nid)
+{
+ size_t i = find_digest_data_index(nid);
+
+ if (i != (size_t)-1)
+ return i;
+
+ /*
+ * Code further down must make sure that only NIDs in the table above
+ * are used. If any other NID reaches this function, there's a grave
+ * coding error further down.
+ */
+ assert("Code that never should be reached" == NULL);
+ return -1;
+}
+
+static const struct digest_data_st *get_digest_data(int nid)
+{
+ return &digest_data[get_digest_data_index(nid)];
+}
+
+/*
+ * Following are the five necessary functions to map OpenSSL functionality
+ * with cryptodev: init, update, final, cleanup, and copy.
+ */
+
+static int digest_init(EVP_MD_CTX *ctx)
+{
+ struct digest_ctx *digest_ctx =
+ (struct digest_ctx *)EVP_MD_CTX_get0_md_data(ctx);
+ const struct digest_data_st *digest_d =
+ get_digest_data(EVP_MD_CTX_get_type(ctx));
+
+ digest_ctx->init_called = 1;
+
+ memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess));
+ digest_ctx->sess.mac = digest_d->devcryptoid;
+ if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) {
+ ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
+ return 0;
+ }
+ return 1;
+}
+
+static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen,
+ void *res, unsigned int flags)
+{
+ struct crypt_op cryp;
+
+ memset(&cryp, 0, sizeof(cryp));
+ cryp.ses = ctx->sess.ses;
+ cryp.len = srclen;
+ cryp.src = (void *)src;
+ cryp.dst = NULL;
+ cryp.mac = res;
+ cryp.flags = flags;
+ return ioctl(cfd, CIOCCRYPT, &cryp);
+}
+
+static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+ struct digest_ctx *digest_ctx =
+ (struct digest_ctx *)EVP_MD_CTX_get0_md_data(ctx);
+
+ if (count == 0)
+ return 1;
+
+ if (digest_ctx == NULL)
+ return 0;
+
+ if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
+ if (digest_op(digest_ctx, data, count, digest_ctx->digest_res, 0) >= 0)
+ return 1;
+ } else if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) >= 0) {
+ return 1;
+ }
+
+ ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
+ return 0;
+}
+
+static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+ struct digest_ctx *digest_ctx =
+ (struct digest_ctx *)EVP_MD_CTX_get0_md_data(ctx);
+
+ if (md == NULL || digest_ctx == NULL)
+ return 0;
+
+ if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
+ memcpy(md, digest_ctx->digest_res, EVP_MD_CTX_get_size(ctx));
+ } else if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) {
+ ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
+{
+ struct digest_ctx *digest_from =
+ (struct digest_ctx *)EVP_MD_CTX_get0_md_data(from);
+ struct digest_ctx *digest_to =
+ (struct digest_ctx *)EVP_MD_CTX_get0_md_data(to);
+ struct cphash_op cphash;
+
+ if (digest_from == NULL || digest_from->init_called != 1)
+ return 1;
+
+ if (!digest_init(to)) {
+ ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
+ return 0;
+ }
+
+ cphash.src_ses = digest_from->sess.ses;
+ cphash.dst_ses = digest_to->sess.ses;
+ if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
+ ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
+ return 0;
+ }
+ return 1;
+}
+
+static int digest_cleanup(EVP_MD_CTX *ctx)
+{
+ struct digest_ctx *digest_ctx =
+ (struct digest_ctx *)EVP_MD_CTX_get0_md_data(ctx);
+
+ if (digest_ctx == NULL)
+ return 1;
+
+ return clean_devcrypto_session(&digest_ctx->sess);
+}
+
+/*
+ * Keep tables of known nids, associated methods, selected digests, and
+ * driver info.
+ * Note that known_digest_nids[] isn't necessarily indexed the same way as
+ * digest_data[] above, which the other tables are.
+ */
+static int known_digest_nids[OSSL_NELEM(digest_data)];
+static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */
+static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, };
+static int selected_digests[OSSL_NELEM(digest_data)];
+static struct driver_info_st digest_driver_info[OSSL_NELEM(digest_data)];
+
+static int devcrypto_test_digest(size_t digest_data_index)
+{
+ return (digest_driver_info[digest_data_index].status == DEVCRYPTO_STATUS_USABLE
+ && selected_digests[digest_data_index] == 1
+ && (digest_driver_info[digest_data_index].accelerated
+ == DEVCRYPTO_ACCELERATED
+ || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
+ || (digest_driver_info[digest_data_index].accelerated
+ != DEVCRYPTO_NOT_ACCELERATED
+ && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
+}
+
+static void rebuild_known_digest_nids(ENGINE *e)
+{
+ size_t i;
+
+ for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); i++) {
+ if (devcrypto_test_digest(i))
+ known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
+ }
+ ENGINE_unregister_digests(e);
+ ENGINE_register_digests(e);
+}
+
+static void prepare_digest_methods(void)
+{
+ size_t i;
+ session_op_t sess1, sess2;
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+ struct cphash_op cphash;
+
+ memset(&digest_driver_info, 0, sizeof(digest_driver_info));
+
+ memset(&sess1, 0, sizeof(sess1));
+ memset(&sess2, 0, sizeof(sess2));
+
+ for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data);
+ i++) {
+
+ selected_digests[i] = 1;
+
+ /*
+ * Check that the digest is usable
+ */
+ sess1.mac = digest_data[i].devcryptoid;
+ sess2.ses = 0;
+ if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) {
+ digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
+ goto finish;
+ }
+
+#ifdef CIOCGSESSINFO
+ /* gather hardware acceleration info from the driver */
+ siop.ses = sess1.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
+ digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
+ } else {
+ digest_driver_info[i].driver_name =
+ OPENSSL_strndup(siop.hash_info.cra_driver_name,
+ CRYPTODEV_MAX_ALG_NAME);
+ if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
+ digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
+ else
+ digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
+ }
+#endif
+
+ /* digest must be capable of hash state copy */
+ sess2.mac = sess1.mac;
+ if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) {
+ digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
+ goto finish;
+ }
+ cphash.src_ses = sess1.ses;
+ cphash.dst_ses = sess2.ses;
+ if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
+ digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCCPHASH;
+ goto finish;
+ }
+ if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid,
+ NID_undef)) == NULL
+ || !EVP_MD_meth_set_input_blocksize(known_digest_methods[i],
+ digest_data[i].blocksize)
+ || !EVP_MD_meth_set_result_size(known_digest_methods[i],
+ digest_data[i].digestlen)
+ || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init)
+ || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update)
+ || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final)
+ || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy)
+ || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
+ || !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
+ sizeof(struct digest_ctx))) {
+ digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
+ EVP_MD_meth_free(known_digest_methods[i]);
+ known_digest_methods[i] = NULL;
+ goto finish;
+ }
+ digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
+finish:
+ ioctl(cfd, CIOCFSESSION, &sess1.ses);
+ if (sess2.ses != 0)
+ ioctl(cfd, CIOCFSESSION, &sess2.ses);
+ if (devcrypto_test_digest(i))
+ known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
+ }
+}
+
+static const EVP_MD *get_digest_method(int nid)
+{
+ size_t i = get_digest_data_index(nid);
+
+ if (i == (size_t)-1)
+ return NULL;
+ return known_digest_methods[i];
+}
+
+static int get_digest_nids(const int **nids)
+{
+ *nids = known_digest_nids;
+ return known_digest_nids_amount;
+}
+
+static void destroy_digest_method(int nid)
+{
+ size_t i = get_digest_data_index(nid);
+
+ EVP_MD_meth_free(known_digest_methods[i]);
+ known_digest_methods[i] = NULL;
+}
+
+static void destroy_all_digest_methods(void)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(digest_data); i++) {
+ destroy_digest_method(digest_data[i].nid);
+ OPENSSL_free(digest_driver_info[i].driver_name);
+ digest_driver_info[i].driver_name = NULL;
+ }
+}
+
+static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
+ const int **nids, int nid)
+{
+ if (digest == NULL)
+ return get_digest_nids(nids);
+
+ *digest = get_digest_method(nid);
+
+ return *digest != NULL;
+}
+
+static void devcrypto_select_all_digests(int *digest_list)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(digest_data); i++)
+ digest_list[i] = 1;
+}
+
+static int cryptodev_select_digest_cb(const char *str, int len, void *usr)
+{
+ int *digest_list = (int *)usr;
+ char *name;
+ const EVP_MD *EVP;
+ size_t i;
+
+ if (len == 0)
+ return 1;
+ if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
+ return 0;
+ EVP = EVP_get_digestbyname(name);
+ if (EVP == NULL)
+ fprintf(stderr, "devcrypto: unknown digest %s\n", name);
+ else if ((i = find_digest_data_index(EVP_MD_get_type(EVP))) != (size_t)-1)
+ digest_list[i] = 1;
+ else
+ fprintf(stderr, "devcrypto: digest %s not available\n", name);
+ OPENSSL_free(name);
+ return 1;
+}
+
+static void dump_digest_info(void)
+{
+ size_t i;
+ const char *name;
+
+ fprintf (stderr, "Information about digests supported by the /dev/crypto"
+ " engine:\n");
+#ifndef CIOCGSESSINFO
+ fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
+#endif
+
+ for (i = 0; i < OSSL_NELEM(digest_data); i++) {
+ name = OBJ_nid2sn(digest_data[i].nid);
+ fprintf (stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s",
+ name ? name : "unknown", digest_data[i].nid,
+ digest_data[i].devcryptoid,
+ digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown");
+ if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) {
+ fprintf (stderr, ". CIOCGSESSION (session open) failed\n");
+ continue;
+ }
+ if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
+ fprintf(stderr, " (hw accelerated)");
+ else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
+ fprintf(stderr, " (software)");
+ else
+ fprintf(stderr, " (acceleration status unknown)");
+ if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
+ fprintf (stderr, ". Cipher setup failed\n");
+ else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH)
+ fprintf(stderr, ", CIOCCPHASH failed\n");
+ else
+ fprintf(stderr, ", CIOCCPHASH capable\n");
+ }
+ fprintf(stderr, "\n");
+}
+
+#endif
+
+/******************************************************************************
+ *
+ * CONTROL COMMANDS
+ *
+ *****/
+
+#define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE
+#define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1)
+#define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2)
+#define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3)
+
+static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
+#if defined(CIOCGSESSINFO) || defined(CIOCGSESSION2)
+ {DEVCRYPTO_CMD_USE_SOFTDRIVERS,
+ "USE_SOFTDRIVERS",
+ "specifies whether to use software (not accelerated) drivers ("
+ OPENSSL_MSTR(DEVCRYPTO_REQUIRE_ACCELERATED) "=use only accelerated drivers, "
+ OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, "
+ OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE)
+ "=use if acceleration can't be determined) [default="
+ OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS) "]",
+ ENGINE_CMD_FLAG_NUMERIC},
+#endif
+
+ {DEVCRYPTO_CMD_CIPHERS,
+ "CIPHERS",
+ "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]",
+ ENGINE_CMD_FLAG_STRING},
+
+#ifdef IMPLEMENT_DIGEST
+ {DEVCRYPTO_CMD_DIGESTS,
+ "DIGESTS",
+ "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]",
+ ENGINE_CMD_FLAG_STRING},
+#endif
+
+ {DEVCRYPTO_CMD_DUMP_INFO,
+ "DUMP_INFO",
+ "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'",
+ ENGINE_CMD_FLAG_NO_INPUT},
+
+ {0, NULL, NULL, 0}
+};
+
+static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
+{
+ int *new_list;
+ switch (cmd) {
+#if defined(CIOCGSESSINFO) || defined(CIOCGSESSION2)
+ case DEVCRYPTO_CMD_USE_SOFTDRIVERS:
+ switch (i) {
+ case DEVCRYPTO_REQUIRE_ACCELERATED:
+ case DEVCRYPTO_USE_SOFTWARE:
+ case DEVCRYPTO_REJECT_SOFTWARE:
+ break;
+ default:
+ fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i);
+ return 0;
+ }
+ if (use_softdrivers == i)
+ return 1;
+ use_softdrivers = i;
+#ifdef IMPLEMENT_DIGEST
+ rebuild_known_digest_nids(e);
+#endif
+ rebuild_known_cipher_nids(e);
+ return 1;
+#endif /* CIOCGSESSINFO || CIOCGSESSION2 */
+
+ case DEVCRYPTO_CMD_CIPHERS:
+ if (p == NULL)
+ return 1;
+ if (OPENSSL_strcasecmp((const char *)p, "ALL") == 0) {
+ devcrypto_select_all_ciphers(selected_ciphers);
+ } else if (OPENSSL_strcasecmp((const char*)p, "NONE") == 0) {
+ memset(selected_ciphers, 0, sizeof(selected_ciphers));
+ } else {
+ new_list=OPENSSL_zalloc(sizeof(selected_ciphers));
+ if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) {
+ OPENSSL_free(new_list);
+ return 0;
+ }
+ memcpy(selected_ciphers, new_list, sizeof(selected_ciphers));
+ OPENSSL_free(new_list);
+ }
+ rebuild_known_cipher_nids(e);
+ return 1;
+
+#ifdef IMPLEMENT_DIGEST
+ case DEVCRYPTO_CMD_DIGESTS:
+ if (p == NULL)
+ return 1;
+ if (OPENSSL_strcasecmp((const char *)p, "ALL") == 0) {
+ devcrypto_select_all_digests(selected_digests);
+ } else if (OPENSSL_strcasecmp((const char*)p, "NONE") == 0) {
+ memset(selected_digests, 0, sizeof(selected_digests));
+ } else {
+ new_list=OPENSSL_zalloc(sizeof(selected_digests));
+ if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) {
+ OPENSSL_free(new_list);
+ return 0;
+ }
+ memcpy(selected_digests, new_list, sizeof(selected_digests));
+ OPENSSL_free(new_list);
+ }
+ rebuild_known_digest_nids(e);
+ return 1;
+#endif /* IMPLEMENT_DIGEST */
+
+ case DEVCRYPTO_CMD_DUMP_INFO:
+ dump_cipher_info();
+#ifdef IMPLEMENT_DIGEST
+ dump_digest_info();
+#endif
+ return 1;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ *
+ * LOAD / UNLOAD
+ *
+ *****/
+
+/*
+ * Opens /dev/crypto
+ */
+static int open_devcrypto(void)
+{
+ int fd;
+
+ if (cfd >= 0)
+ return 1;
+
+ if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
+#ifndef ENGINE_DEVCRYPTO_DEBUG
+ if (errno != ENOENT)
+#endif
+ fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
+ return 0;
+ }
+
+#ifdef CRIOGET
+ if (ioctl(fd, CRIOGET, &cfd) < 0) {
+ fprintf(stderr, "Could not create crypto fd: %s\n", strerror(errno));
+ close(fd);
+ cfd = -1;
+ return 0;
+ }
+ close(fd);
+#else
+ cfd = fd;
+#endif
+
+ return 1;
+}
+
+static int close_devcrypto(void)
+{
+ int ret;
+
+ if (cfd < 0)
+ return 1;
+ ret = close(cfd);
+ cfd = -1;
+ if (ret != 0) {
+ fprintf(stderr, "Error closing /dev/crypto: %s\n", strerror(errno));
+ return 0;
+ }
+ return 1;
+}
+
+static int devcrypto_unload(ENGINE *e)
+{
+ destroy_all_cipher_methods();
+#ifdef IMPLEMENT_DIGEST
+ destroy_all_digest_methods();
+#endif
+
+ close_devcrypto();
+
+ return 1;
+}
+
+static int bind_devcrypto(ENGINE *e) {
+
+ if (!ENGINE_set_id(e, engine_devcrypto_id)
+ || !ENGINE_set_name(e, "/dev/crypto engine")
+ || !ENGINE_set_destroy_function(e, devcrypto_unload)
+ || !ENGINE_set_cmd_defns(e, devcrypto_cmds)
+ || !ENGINE_set_ctrl_function(e, devcrypto_ctrl))
+ return 0;
+
+ prepare_cipher_methods();
+#ifdef IMPLEMENT_DIGEST
+ prepare_digest_methods();
+#endif
+
+ return (ENGINE_set_ciphers(e, devcrypto_ciphers)
+#ifdef IMPLEMENT_DIGEST
+ && ENGINE_set_digests(e, devcrypto_digests)
+#endif
+/*
+ * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD
+ * implementations, it seems to only exist in FreeBSD, and regarding the
+ * parameters in its crypt_kop, the manual crypto(4) has this to say:
+ *
+ * The semantics of these arguments are currently undocumented.
+ *
+ * Reading through the FreeBSD source code doesn't give much more than
+ * their CRK_MOD_EXP implementation for ubsec.
+ *
+ * It doesn't look much better with cryptodev-linux. They have the crypt_kop
+ * structure as well as the command (CRK_*) in cryptodev.h, but no support
+ * seems to be implemented at all for the moment.
+ *
+ * At the time of writing, it seems impossible to write proper support for
+ * FreeBSD's asym features without some very deep knowledge and access to
+ * specific kernel modules.
+ *
+ * /Richard Levitte, 2017-05-11
+ */
+#if 0
+ && ENGINE_set_RSA(e, devcrypto_rsa)
+# ifndef OPENSSL_NO_DSA
+ && ENGINE_set_DSA(e, devcrypto_dsa)
+# endif
+# ifndef OPENSSL_NO_DH
+ && ENGINE_set_DH(e, devcrypto_dh)
+# endif
+# ifndef OPENSSL_NO_EC
+ && ENGINE_set_EC(e, devcrypto_ec)
+# endif
+#endif
+ );
+}
+
+#ifdef OPENSSL_NO_DYNAMIC_ENGINE
+/*
+ * In case this engine is built into libcrypto, then it doesn't offer any
+ * ability to be dynamically loadable.
+ */
+void engine_load_devcrypto_int(void)
+{
+ ENGINE *e = NULL;
+
+ if (!open_devcrypto())
+ return;
+
+ if ((e = ENGINE_new()) == NULL
+ || !bind_devcrypto(e)) {
+ close_devcrypto();
+ ENGINE_free(e);
+ return;
+ }
+
+ ERR_set_mark();
+ ENGINE_add(e);
+ /*
+ * If the "add" worked, it gets a structural reference. So either way, we
+ * release our just-created reference.
+ */
+ ENGINE_free(e); /* Loose our local reference */
+ /*
+ * If the "add" didn't work, it was probably a conflict because it was
+ * already added (eg. someone calling ENGINE_load_blah then calling
+ * ENGINE_load_builtin_engines() perhaps).
+ */
+ ERR_pop_to_mark();
+}
+
+#else
+
+static int bind_helper(ENGINE *e, const char *id)
+{
+ if ((id && (strcmp(id, engine_devcrypto_id) != 0))
+ || !open_devcrypto())
+ return 0;
+ if (!bind_devcrypto(e)) {
+ close_devcrypto();
+ return 0;
+ }
+ return 1;
+}
+
+IMPLEMENT_DYNAMIC_CHECK_FN()
+IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
+
+#endif
diff --git a/engines/e_loader_attic.c b/engines/e_loader_attic.c
new file mode 100644
index 000000000000..eba7ab14b8e3
--- /dev/null
+++ b/engines/e_loader_attic.c
@@ -0,0 +1,1773 @@
+/*
+ * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* THIS ENGINE IS FOR TESTING PURPOSES ONLY. */
+
+/* This file has quite some overlap with providers/implementations/storemgmt/file_store.c */
+
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include <string.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include <openssl/bio.h>
+#include <openssl/dsa.h> /* For d2i_DSAPrivateKey */
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/pkcs12.h> /* For the PKCS8 stuff o.O */
+#include <openssl/rsa.h> /* For d2i_RSAPrivateKey */
+#include <openssl/safestack.h>
+#include <openssl/store.h>
+#include <openssl/ui.h>
+#include <openssl/engine.h>
+#include <openssl/x509.h> /* For the PKCS8 stuff o.O */
+#include "internal/asn1.h" /* For asn1_d2i_read_bio */
+#include "internal/o_dir.h"
+#include "internal/cryptlib.h"
+#include "crypto/ctype.h" /* For ossl_isdigit */
+#include "crypto/pem.h" /* For PVK and "blob" PEM headers */
+
+#include "e_loader_attic_err.c"
+
+DEFINE_STACK_OF(OSSL_STORE_INFO)
+
+#ifdef _WIN32
+# define stat _stat
+#endif
+
+#ifndef S_ISDIR
+# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
+#endif
+
+/*-
+ * Password prompting
+ * ------------------
+ */
+
+static char *file_get_pass(const UI_METHOD *ui_method, char *pass,
+ size_t maxsize, const char *desc, const char *info,
+ void *data)
+{
+ UI *ui = UI_new();
+ char *prompt = NULL;
+
+ if (ui == NULL) {
+ ATTICerr(0, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (ui_method != NULL)
+ UI_set_method(ui, ui_method);
+ UI_add_user_data(ui, data);
+
+ if ((prompt = UI_construct_prompt(ui, desc, info)) == NULL) {
+ ATTICerr(0, ERR_R_MALLOC_FAILURE);
+ pass = NULL;
+ } else if (UI_add_input_string(ui, prompt, UI_INPUT_FLAG_DEFAULT_PWD,
+ pass, 0, maxsize - 1) <= 0) {
+ ATTICerr(0, ERR_R_UI_LIB);
+ pass = NULL;
+ } else {
+ switch (UI_process(ui)) {
+ case -2:
+ ATTICerr(0, ATTIC_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED);
+ pass = NULL;
+ break;
+ case -1:
+ ATTICerr(0, ERR_R_UI_LIB);
+ pass = NULL;
+ break;
+ default:
+ break;
+ }
+ }
+
+ OPENSSL_free(prompt);
+ UI_free(ui);
+ return pass;
+}
+
+struct pem_pass_data {
+ const UI_METHOD *ui_method;
+ void *data;
+ const char *prompt_desc;
+ const char *prompt_info;
+};
+
+static int file_fill_pem_pass_data(struct pem_pass_data *pass_data,
+ const char *desc, const char *info,
+ const UI_METHOD *ui_method, void *ui_data)
+{
+ if (pass_data == NULL)
+ return 0;
+ pass_data->ui_method = ui_method;
+ pass_data->data = ui_data;
+ pass_data->prompt_desc = desc;
+ pass_data->prompt_info = info;
+ return 1;
+}
+
+/* This is used anywhere a pem_password_cb is needed */
+static int file_get_pem_pass(char *buf, int num, int w, void *data)
+{
+ struct pem_pass_data *pass_data = data;
+ char *pass = file_get_pass(pass_data->ui_method, buf, num,
+ pass_data->prompt_desc, pass_data->prompt_info,
+ pass_data->data);
+
+ return pass == NULL ? 0 : strlen(pass);
+}
+
+/*
+ * Check if |str| ends with |suffix| preceded by a space, and if it does,
+ * return the index of that space. If there is no such suffix in |str|,
+ * return -1.
+ * For |str| == "FOO BAR" and |suffix| == "BAR", the returned value is 3.
+ */
+static int check_suffix(const char *str, const char *suffix)
+{
+ int str_len = strlen(str);
+ int suffix_len = strlen(suffix) + 1;
+ const char *p = NULL;
+
+ if (suffix_len >= str_len)
+ return -1;
+ p = str + str_len - suffix_len;
+ if (*p != ' '
+ || strcmp(p + 1, suffix) != 0)
+ return -1;
+ return p - str;
+}
+
+/*
+ * EMBEDDED is a special type of OSSL_STORE_INFO, specially for the file
+ * handlers, so we define it internally. This uses the possibility to
+ * create an OSSL_STORE_INFO with a generic data pointer and arbitrary
+ * type number.
+ *
+ * This is used by a FILE_HANDLER's try_decode function to signal that it
+ * has decoded the incoming blob into a new blob, and that the attempted
+ * decoding should be immediately restarted with the new blob, using the
+ * new PEM name.
+ */
+/* Negative numbers are never used for public OSSL_STORE_INFO types */
+#define STORE_INFO_EMBEDDED -1
+
+/* This is the embedded data */
+struct embedded_st {
+ BUF_MEM *blob;
+ char *pem_name;
+};
+
+/* Helper functions */
+static struct embedded_st *get0_EMBEDDED(OSSL_STORE_INFO *info)
+{
+ return OSSL_STORE_INFO_get0_data(STORE_INFO_EMBEDDED, info);
+}
+
+static void store_info_free(OSSL_STORE_INFO *info)
+{
+ struct embedded_st *data;
+
+ if (info != NULL && (data = get0_EMBEDDED(info)) != NULL) {
+ BUF_MEM_free(data->blob);
+ OPENSSL_free(data->pem_name);
+ OPENSSL_free(data);
+ }
+ OSSL_STORE_INFO_free(info);
+}
+
+static OSSL_STORE_INFO *new_EMBEDDED(const char *new_pem_name,
+ BUF_MEM *embedded)
+{
+ OSSL_STORE_INFO *info = NULL;
+ struct embedded_st *data = NULL;
+
+ if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL
+ || (info = OSSL_STORE_INFO_new(STORE_INFO_EMBEDDED, data)) == NULL) {
+ ATTICerr(0, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(data);
+ return NULL;
+ }
+
+ data->blob = embedded;
+ data->pem_name =
+ new_pem_name == NULL ? NULL : OPENSSL_strdup(new_pem_name);
+
+ if (new_pem_name != NULL && data->pem_name == NULL) {
+ ATTICerr(0, ERR_R_MALLOC_FAILURE);
+ store_info_free(info);
+ info = NULL;
+ }
+
+ return info;
+}
+
+/*-
+ * The file scheme decoders
+ * ------------------------
+ *
+ * Each possible data type has its own decoder, which either operates
+ * through a given PEM name, or attempts to decode to see if the blob
+ * it's given is decodable for its data type. The assumption is that
+ * only the correct data type will match the content.
+ */
+
+/*-
+ * The try_decode function is called to check if the blob of data can
+ * be used by this handler, and if it can, decodes it into a supported
+ * OpenSSL type and returns a OSSL_STORE_INFO with the decoded data.
+ * Input:
+ * pem_name: If this blob comes from a PEM file, this holds
+ * the PEM name. If it comes from another type of
+ * file, this is NULL.
+ * pem_header: If this blob comes from a PEM file, this holds
+ * the PEM headers. If it comes from another type of
+ * file, this is NULL.
+ * blob: The blob of data to match with what this handler
+ * can use.
+ * len: The length of the blob.
+ * handler_ctx: For a handler marked repeatable, this pointer can
+ * be used to create a context for the handler. IT IS
+ * THE HANDLER'S RESPONSIBILITY TO CREATE AND DESTROY
+ * THIS CONTEXT APPROPRIATELY, i.e. create on first call
+ * and destroy when about to return NULL.
+ * matchcount: A pointer to an int to count matches for this data.
+ * Usually becomes 0 (no match) or 1 (match!), but may
+ * be higher in the (unlikely) event that the data matches
+ * more than one possibility. The int will always be
+ * zero when the function is called.
+ * ui_method: Application UI method for getting a password, pin
+ * or any other interactive data.
+ * ui_data: Application data to be passed to ui_method when
+ * it's called.
+ * libctx: The library context to be used if applicable
+ * propq: The property query string for any algorithm fetches
+ * Output:
+ * a OSSL_STORE_INFO
+ */
+typedef OSSL_STORE_INFO *(*file_try_decode_fn)(const char *pem_name,
+ const char *pem_header,
+ const unsigned char *blob,
+ size_t len, void **handler_ctx,
+ int *matchcount,
+ const UI_METHOD *ui_method,
+ void *ui_data, const char *uri,
+ OSSL_LIB_CTX *libctx,
+ const char *propq);
+/*
+ * The eof function should return 1 if there's no more data to be found
+ * with the handler_ctx, otherwise 0. This is only used when the handler is
+ * marked repeatable.
+ */
+typedef int (*file_eof_fn)(void *handler_ctx);
+/*
+ * The destroy_ctx function is used to destroy the handler_ctx that was
+ * initiated by a repeatable try_decode function. This is only used when
+ * the handler is marked repeatable.
+ */
+typedef void (*file_destroy_ctx_fn)(void **handler_ctx);
+
+typedef struct file_handler_st {
+ const char *name;
+ file_try_decode_fn try_decode;
+ file_eof_fn eof;
+ file_destroy_ctx_fn destroy_ctx;
+
+ /* flags */
+ int repeatable;
+} FILE_HANDLER;
+
+/*
+ * PKCS#12 decoder. It operates by decoding all of the blob content,
+ * extracting all the interesting data from it and storing them internally,
+ * then serving them one piece at a time.
+ */
+static OSSL_STORE_INFO *try_decode_PKCS12(const char *pem_name,
+ const char *pem_header,
+ const unsigned char *blob,
+ size_t len, void **pctx,
+ int *matchcount,
+ const UI_METHOD *ui_method,
+ void *ui_data, const char *uri,
+ OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ OSSL_STORE_INFO *store_info = NULL;
+ STACK_OF(OSSL_STORE_INFO) *ctx = *pctx;
+
+ if (ctx == NULL) {
+ /* Initial parsing */
+ PKCS12 *p12;
+
+ if (pem_name != NULL)
+ /* No match, there is no PEM PKCS12 tag */
+ return NULL;
+
+ if ((p12 = d2i_PKCS12(NULL, &blob, len)) != NULL) {
+ char *pass = NULL;
+ char tpass[PEM_BUFSIZE];
+ EVP_PKEY *pkey = NULL;
+ X509 *cert = NULL;
+ STACK_OF(X509) *chain = NULL;
+
+ *matchcount = 1;
+
+ if (!PKCS12_mac_present(p12)
+ || PKCS12_verify_mac(p12, "", 0)
+ || PKCS12_verify_mac(p12, NULL, 0)) {
+ pass = "";
+ } else {
+ if ((pass = file_get_pass(ui_method, tpass, PEM_BUFSIZE,
+ "PKCS12 import", uri,
+ ui_data)) == NULL) {
+ ATTICerr(0, ATTIC_R_PASSPHRASE_CALLBACK_ERROR);
+ goto p12_end;
+ }
+ if (!PKCS12_verify_mac(p12, pass, strlen(pass))) {
+ ATTICerr(0, ATTIC_R_ERROR_VERIFYING_PKCS12_MAC);
+ goto p12_end;
+ }
+ }
+
+ if (PKCS12_parse(p12, pass, &pkey, &cert, &chain)) {
+ OSSL_STORE_INFO *osi_pkey = NULL;
+ OSSL_STORE_INFO *osi_cert = NULL;
+ OSSL_STORE_INFO *osi_ca = NULL;
+ int ok = 1;
+
+ if ((ctx = sk_OSSL_STORE_INFO_new_null()) != NULL) {
+ if (pkey != NULL) {
+ if ((osi_pkey = OSSL_STORE_INFO_new_PKEY(pkey)) != NULL
+ /* clearing pkey here avoids case distinctions */
+ && (pkey = NULL) == NULL
+ && sk_OSSL_STORE_INFO_push(ctx, osi_pkey) != 0)
+ osi_pkey = NULL;
+ else
+ ok = 0;
+ }
+ if (ok && cert != NULL) {
+ if ((osi_cert = OSSL_STORE_INFO_new_CERT(cert)) != NULL
+ /* clearing cert here avoids case distinctions */
+ && (cert = NULL) == NULL
+ && sk_OSSL_STORE_INFO_push(ctx, osi_cert) != 0)
+ osi_cert = NULL;
+ else
+ ok = 0;
+ }
+ while (ok && sk_X509_num(chain) > 0) {
+ X509 *ca = sk_X509_value(chain, 0);
+
+ if ((osi_ca = OSSL_STORE_INFO_new_CERT(ca)) != NULL
+ && sk_X509_shift(chain) != NULL
+ && sk_OSSL_STORE_INFO_push(ctx, osi_ca) != 0)
+ osi_ca = NULL;
+ else
+ ok = 0;
+ }
+ }
+ EVP_PKEY_free(pkey);
+ X509_free(cert);
+ sk_X509_pop_free(chain, X509_free);
+ store_info_free(osi_pkey);
+ store_info_free(osi_cert);
+ store_info_free(osi_ca);
+ if (!ok) {
+ sk_OSSL_STORE_INFO_pop_free(ctx, store_info_free);
+ ctx = NULL;
+ }
+ *pctx = ctx;
+ }
+ }
+ p12_end:
+ PKCS12_free(p12);
+ if (ctx == NULL)
+ return NULL;
+ }
+
+ *matchcount = 1;
+ store_info = sk_OSSL_STORE_INFO_shift(ctx);
+ return store_info;
+}
+
+static int eof_PKCS12(void *ctx_)
+{
+ STACK_OF(OSSL_STORE_INFO) *ctx = ctx_;
+
+ return ctx == NULL || sk_OSSL_STORE_INFO_num(ctx) == 0;
+}
+
+static void destroy_ctx_PKCS12(void **pctx)
+{
+ STACK_OF(OSSL_STORE_INFO) *ctx = *pctx;
+
+ sk_OSSL_STORE_INFO_pop_free(ctx, store_info_free);
+ *pctx = NULL;
+}
+
+static FILE_HANDLER PKCS12_handler = {
+ "PKCS12",
+ try_decode_PKCS12,
+ eof_PKCS12,
+ destroy_ctx_PKCS12,
+ 1 /* repeatable */
+};
+
+/*
+ * Encrypted PKCS#8 decoder. It operates by just decrypting the given blob
+ * into a new blob, which is returned as an EMBEDDED STORE_INFO. The whole
+ * decoding process will then start over with the new blob.
+ */
+static OSSL_STORE_INFO *try_decode_PKCS8Encrypted(const char *pem_name,
+ const char *pem_header,
+ const unsigned char *blob,
+ size_t len, void **pctx,
+ int *matchcount,
+ const UI_METHOD *ui_method,
+ void *ui_data,
+ const char *uri,
+ OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ X509_SIG *p8 = NULL;
+ char kbuf[PEM_BUFSIZE];
+ char *pass = NULL;
+ const X509_ALGOR *dalg = NULL;
+ const ASN1_OCTET_STRING *doct = NULL;
+ OSSL_STORE_INFO *store_info = NULL;
+ BUF_MEM *mem = NULL;
+ unsigned char *new_data = NULL;
+ int new_data_len;
+
+ if (pem_name != NULL) {
+ if (strcmp(pem_name, PEM_STRING_PKCS8) != 0)
+ return NULL;
+ *matchcount = 1;
+ }
+
+ if ((p8 = d2i_X509_SIG(NULL, &blob, len)) == NULL)
+ return NULL;
+
+ *matchcount = 1;
+
+ if ((mem = BUF_MEM_new()) == NULL) {
+ ATTICerr(0, ERR_R_MALLOC_FAILURE);
+ goto nop8;
+ }
+
+ if ((pass = file_get_pass(ui_method, kbuf, PEM_BUFSIZE,
+ "PKCS8 decrypt pass phrase", uri,
+ ui_data)) == NULL) {
+ ATTICerr(0, ATTIC_R_BAD_PASSWORD_READ);
+ goto nop8;
+ }
+
+ X509_SIG_get0(p8, &dalg, &doct);
+ if (!PKCS12_pbe_crypt(dalg, pass, strlen(pass), doct->data, doct->length,
+ &new_data, &new_data_len, 0))
+ goto nop8;
+
+ mem->data = (char *)new_data;
+ mem->max = mem->length = (size_t)new_data_len;
+ X509_SIG_free(p8);
+ p8 = NULL;
+
+ store_info = new_EMBEDDED(PEM_STRING_PKCS8INF, mem);
+ if (store_info == NULL) {
+ ATTICerr(0, ERR_R_MALLOC_FAILURE);
+ goto nop8;
+ }
+
+ return store_info;
+ nop8:
+ X509_SIG_free(p8);
+ BUF_MEM_free(mem);
+ return NULL;
+}
+
+static FILE_HANDLER PKCS8Encrypted_handler = {
+ "PKCS8Encrypted",
+ try_decode_PKCS8Encrypted
+};
+
+/*
+ * Private key decoder. Decodes all sorts of private keys, both PKCS#8
+ * encoded ones and old style PEM ones (with the key type is encoded into
+ * the PEM name).
+ */
+static OSSL_STORE_INFO *try_decode_PrivateKey(const char *pem_name,
+ const char *pem_header,
+ const unsigned char *blob,
+ size_t len, void **pctx,
+ int *matchcount,
+ const UI_METHOD *ui_method,
+ void *ui_data, const char *uri,
+ OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ OSSL_STORE_INFO *store_info = NULL;
+ EVP_PKEY *pkey = NULL;
+ const EVP_PKEY_ASN1_METHOD *ameth = NULL;
+
+ if (pem_name != NULL) {
+ if (strcmp(pem_name, PEM_STRING_PKCS8INF) == 0) {
+ PKCS8_PRIV_KEY_INFO *p8inf =
+ d2i_PKCS8_PRIV_KEY_INFO(NULL, &blob, len);
+
+ *matchcount = 1;
+ if (p8inf != NULL)
+ pkey = EVP_PKCS82PKEY_ex(p8inf, libctx, propq);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ } else {
+ int slen;
+ int pkey_id;
+
+ if ((slen = check_suffix(pem_name, "PRIVATE KEY")) > 0
+ && (ameth = EVP_PKEY_asn1_find_str(NULL, pem_name,
+ slen)) != NULL
+ && EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL,
+ ameth)) {
+ *matchcount = 1;
+ pkey = d2i_PrivateKey_ex(pkey_id, NULL, &blob, len,
+ libctx, propq);
+ }
+ }
+ } else {
+ int i;
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE *curengine = ENGINE_get_first();
+
+ while (curengine != NULL) {
+ ENGINE_PKEY_ASN1_METHS_PTR asn1meths =
+ ENGINE_get_pkey_asn1_meths(curengine);
+
+ if (asn1meths != NULL) {
+ const int *nids = NULL;
+ int nids_n = asn1meths(curengine, NULL, &nids, 0);
+
+ for (i = 0; i < nids_n; i++) {
+ EVP_PKEY_ASN1_METHOD *ameth2 = NULL;
+ EVP_PKEY *tmp_pkey = NULL;
+ const unsigned char *tmp_blob = blob;
+ int pkey_id, pkey_flags;
+
+ if (!asn1meths(curengine, &ameth2, NULL, nids[i])
+ || !EVP_PKEY_asn1_get0_info(&pkey_id, NULL,
+ &pkey_flags, NULL, NULL,
+ ameth2)
+ || (pkey_flags & ASN1_PKEY_ALIAS) != 0)
+ continue;
+
+ ERR_set_mark(); /* prevent flooding error queue */
+ tmp_pkey = d2i_PrivateKey_ex(pkey_id, NULL,
+ &tmp_blob, len,
+ libctx, propq);
+ if (tmp_pkey != NULL) {
+ if (pkey != NULL)
+ EVP_PKEY_free(tmp_pkey);
+ else
+ pkey = tmp_pkey;
+ (*matchcount)++;
+ }
+ ERR_pop_to_mark();
+ }
+ }
+ curengine = ENGINE_get_next(curengine);
+ }
+#endif
+
+ for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
+ EVP_PKEY *tmp_pkey = NULL;
+ const unsigned char *tmp_blob = blob;
+ int pkey_id, pkey_flags;
+
+ ameth = EVP_PKEY_asn1_get0(i);
+ if (!EVP_PKEY_asn1_get0_info(&pkey_id, NULL, &pkey_flags, NULL,
+ NULL, ameth)
+ || (pkey_flags & ASN1_PKEY_ALIAS) != 0)
+ continue;
+
+ ERR_set_mark(); /* prevent flooding error queue */
+ tmp_pkey = d2i_PrivateKey_ex(pkey_id, NULL, &tmp_blob, len,
+ libctx, propq);
+ if (tmp_pkey != NULL) {
+ if (pkey != NULL)
+ EVP_PKEY_free(tmp_pkey);
+ else
+ pkey = tmp_pkey;
+ (*matchcount)++;
+ }
+ ERR_pop_to_mark();
+ }
+
+ if (*matchcount > 1) {
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ }
+ }
+ if (pkey == NULL)
+ /* No match */
+ return NULL;
+
+ store_info = OSSL_STORE_INFO_new_PKEY(pkey);
+ if (store_info == NULL)
+ EVP_PKEY_free(pkey);
+
+ return store_info;
+}
+
+static FILE_HANDLER PrivateKey_handler = {
+ "PrivateKey",
+ try_decode_PrivateKey
+};
+
+/*
+ * Public key decoder. Only supports SubjectPublicKeyInfo formatted keys.
+ */
+static OSSL_STORE_INFO *try_decode_PUBKEY(const char *pem_name,
+ const char *pem_header,
+ const unsigned char *blob,
+ size_t len, void **pctx,
+ int *matchcount,
+ const UI_METHOD *ui_method,
+ void *ui_data, const char *uri,
+ OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ OSSL_STORE_INFO *store_info = NULL;
+ EVP_PKEY *pkey = NULL;
+
+ if (pem_name != NULL) {
+ if (strcmp(pem_name, PEM_STRING_PUBLIC) != 0)
+ /* No match */
+ return NULL;
+ *matchcount = 1;
+ }
+
+ if ((pkey = d2i_PUBKEY(NULL, &blob, len)) != NULL) {
+ *matchcount = 1;
+ store_info = OSSL_STORE_INFO_new_PUBKEY(pkey);
+ }
+
+ return store_info;
+}
+
+static FILE_HANDLER PUBKEY_handler = {
+ "PUBKEY",
+ try_decode_PUBKEY
+};
+
+/*
+ * Key parameter decoder.
+ */
+static OSSL_STORE_INFO *try_decode_params(const char *pem_name,
+ const char *pem_header,
+ const unsigned char *blob,
+ size_t len, void **pctx,
+ int *matchcount,
+ const UI_METHOD *ui_method,
+ void *ui_data, const char *uri,
+ OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ OSSL_STORE_INFO *store_info = NULL;
+ EVP_PKEY *pkey = NULL;
+ const EVP_PKEY_ASN1_METHOD *ameth = NULL;
+
+ if (pem_name != NULL) {
+ int slen;
+ int pkey_id;
+
+ if ((slen = check_suffix(pem_name, "PARAMETERS")) > 0
+ && (ameth = EVP_PKEY_asn1_find_str(NULL, pem_name, slen)) != NULL
+ && EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL,
+ ameth)) {
+ *matchcount = 1;
+ pkey = d2i_KeyParams(pkey_id, NULL, &blob, len);
+ }
+ } else {
+ int i;
+
+ for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
+ EVP_PKEY *tmp_pkey = NULL;
+ const unsigned char *tmp_blob = blob;
+ int pkey_id, pkey_flags;
+
+ ameth = EVP_PKEY_asn1_get0(i);
+ if (!EVP_PKEY_asn1_get0_info(&pkey_id, NULL, &pkey_flags, NULL,
+ NULL, ameth)
+ || (pkey_flags & ASN1_PKEY_ALIAS) != 0)
+ continue;
+
+ ERR_set_mark(); /* prevent flooding error queue */
+
+ tmp_pkey = d2i_KeyParams(pkey_id, NULL, &tmp_blob, len);
+
+ if (tmp_pkey != NULL) {
+ if (pkey != NULL)
+ EVP_PKEY_free(tmp_pkey);
+ else
+ pkey = tmp_pkey;
+ (*matchcount)++;
+ }
+ ERR_pop_to_mark();
+ }
+
+ if (*matchcount > 1) {
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ }
+ }
+ if (pkey == NULL)
+ /* No match */
+ return NULL;
+
+ store_info = OSSL_STORE_INFO_new_PARAMS(pkey);
+ if (store_info == NULL)
+ EVP_PKEY_free(pkey);
+
+ return store_info;
+}
+
+static FILE_HANDLER params_handler = {
+ "params",
+ try_decode_params
+};
+
+/*
+ * X.509 certificate decoder.
+ */
+static OSSL_STORE_INFO *try_decode_X509Certificate(const char *pem_name,
+ const char *pem_header,
+ const unsigned char *blob,
+ size_t len, void **pctx,
+ int *matchcount,
+ const UI_METHOD *ui_method,
+ void *ui_data,
+ const char *uri,
+ OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ OSSL_STORE_INFO *store_info = NULL;
+ X509 *cert = NULL;
+
+ /*
+ * In most cases, we can try to interpret the serialized data as a trusted
+ * cert (X509 + X509_AUX) and fall back to reading it as a normal cert
+ * (just X509), but if the PEM name specifically declares it as a trusted
+ * cert, then no fallback should be engaged. |ignore_trusted| tells if
+ * the fallback can be used (1) or not (0).
+ */
+ int ignore_trusted = 1;
+
+ if (pem_name != NULL) {
+ if (strcmp(pem_name, PEM_STRING_X509_TRUSTED) == 0)
+ ignore_trusted = 0;
+ else if (strcmp(pem_name, PEM_STRING_X509_OLD) != 0
+ && strcmp(pem_name, PEM_STRING_X509) != 0)
+ /* No match */
+ return NULL;
+ *matchcount = 1;
+ }
+
+ cert = X509_new_ex(libctx, propq);
+ if (cert == NULL)
+ return NULL;
+
+ if ((d2i_X509_AUX(&cert, &blob, len)) != NULL
+ || (ignore_trusted && (d2i_X509(&cert, &blob, len)) != NULL)) {
+ *matchcount = 1;
+ store_info = OSSL_STORE_INFO_new_CERT(cert);
+ }
+
+ if (store_info == NULL)
+ X509_free(cert);
+
+ return store_info;
+}
+
+static FILE_HANDLER X509Certificate_handler = {
+ "X509Certificate",
+ try_decode_X509Certificate
+};
+
+/*
+ * X.509 CRL decoder.
+ */
+static OSSL_STORE_INFO *try_decode_X509CRL(const char *pem_name,
+ const char *pem_header,
+ const unsigned char *blob,
+ size_t len, void **pctx,
+ int *matchcount,
+ const UI_METHOD *ui_method,
+ void *ui_data, const char *uri,
+ OSSL_LIB_CTX *libctx,
+ const char *propq)
+{
+ OSSL_STORE_INFO *store_info = NULL;
+ X509_CRL *crl = NULL;
+
+ if (pem_name != NULL) {
+ if (strcmp(pem_name, PEM_STRING_X509_CRL) != 0)
+ /* No match */
+ return NULL;
+ *matchcount = 1;
+ }
+
+ if ((crl = d2i_X509_CRL(NULL, &blob, len)) != NULL) {
+ *matchcount = 1;
+ store_info = OSSL_STORE_INFO_new_CRL(crl);
+ }
+
+ if (store_info == NULL)
+ X509_CRL_free(crl);
+
+ return store_info;
+}
+
+static FILE_HANDLER X509CRL_handler = {
+ "X509CRL",
+ try_decode_X509CRL
+};
+
+/*
+ * To finish it all off, we collect all the handlers.
+ */
+static const FILE_HANDLER *file_handlers[] = {
+ &PKCS12_handler,
+ &PKCS8Encrypted_handler,
+ &X509Certificate_handler,
+ &X509CRL_handler,
+ &params_handler,
+ &PUBKEY_handler,
+ &PrivateKey_handler,
+};
+
+
+/*-
+ * The loader itself
+ * -----------------
+ */
+
+struct ossl_store_loader_ctx_st {
+ char *uri; /* The URI we currently try to load */
+ enum {
+ is_raw = 0,
+ is_pem,
+ is_dir
+ } type;
+ int errcnt;
+#define FILE_FLAG_SECMEM (1<<0)
+#define FILE_FLAG_ATTACHED (1<<1)
+ unsigned int flags;
+ union {
+ struct { /* Used with is_raw and is_pem */
+ BIO *file;
+
+ /*
+ * The following are used when the handler is marked as
+ * repeatable
+ */
+ const FILE_HANDLER *last_handler;
+ void *last_handler_ctx;
+ } file;
+ struct { /* Used with is_dir */
+ OPENSSL_DIR_CTX *ctx;
+ int end_reached;
+
+ /*
+ * When a search expression is given, these are filled in.
+ * |search_name| contains the file basename to look for.
+ * The string is exactly 8 characters long.
+ */
+ char search_name[9];
+
+ /*
+ * The directory reading utility we have combines opening with
+ * reading the first name. To make sure we can detect the end
+ * at the right time, we read early and cache the name.
+ */
+ const char *last_entry;
+ int last_errno;
+ } dir;
+ } _;
+
+ /* Expected object type. May be unspecified */
+ int expected_type;
+
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+};
+
+static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ OPENSSL_free(ctx->propq);
+ OPENSSL_free(ctx->uri);
+ if (ctx->type != is_dir) {
+ if (ctx->_.file.last_handler != NULL) {
+ ctx->_.file.last_handler->destroy_ctx(&ctx->_.file.last_handler_ctx);
+ ctx->_.file.last_handler_ctx = NULL;
+ ctx->_.file.last_handler = NULL;
+ }
+ }
+ OPENSSL_free(ctx);
+}
+
+static int file_find_type(OSSL_STORE_LOADER_CTX *ctx)
+{
+ BIO *buff = NULL;
+ char peekbuf[4096] = { 0, };
+
+ if ((buff = BIO_new(BIO_f_buffer())) == NULL)
+ return 0;
+
+ ctx->_.file.file = BIO_push(buff, ctx->_.file.file);
+ if (BIO_buffer_peek(ctx->_.file.file, peekbuf, sizeof(peekbuf) - 1) > 0) {
+ peekbuf[sizeof(peekbuf) - 1] = '\0';
+ if (strstr(peekbuf, "-----BEGIN ") != NULL)
+ ctx->type = is_pem;
+ }
+ return 1;
+}
+
+static OSSL_STORE_LOADER_CTX *file_open_ex
+ (const OSSL_STORE_LOADER *loader, const char *uri,
+ OSSL_LIB_CTX *libctx, const char *propq,
+ const UI_METHOD *ui_method, void *ui_data)
+{
+ OSSL_STORE_LOADER_CTX *ctx = NULL;
+ struct stat st;
+ struct {
+ const char *path;
+ unsigned int check_absolute:1;
+ } path_data[2];
+ size_t path_data_n = 0, i;
+ const char *path;
+
+ /*
+ * First step, just take the URI as is.
+ */
+ path_data[path_data_n].check_absolute = 0;
+ path_data[path_data_n++].path = uri;
+
+ /*
+ * Second step, if the URI appears to start with the 'file' scheme,
+ * extract the path and make that the second path to check.
+ * There's a special case if the URI also contains an authority, then
+ * the full URI shouldn't be used as a path anywhere.
+ */
+ if (OPENSSL_strncasecmp(uri, "file:", 5) == 0) {
+ const char *p = &uri[5];
+
+ if (strncmp(&uri[5], "//", 2) == 0) {
+ path_data_n--; /* Invalidate using the full URI */
+ if (OPENSSL_strncasecmp(&uri[7], "localhost/", 10) == 0) {
+ p = &uri[16];
+ } else if (uri[7] == '/') {
+ p = &uri[7];
+ } else {
+ ATTICerr(0, ATTIC_R_URI_AUTHORITY_UNSUPPORTED);
+ return NULL;
+ }
+ }
+
+ path_data[path_data_n].check_absolute = 1;
+#ifdef _WIN32
+ /* Windows file: URIs with a drive letter start with a / */
+ if (p[0] == '/' && p[2] == ':' && p[3] == '/') {
+ char c = tolower(p[1]);
+
+ if (c >= 'a' && c <= 'z') {
+ p++;
+ /* We know it's absolute, so no need to check */
+ path_data[path_data_n].check_absolute = 0;
+ }
+ }
+#endif
+ path_data[path_data_n++].path = p;
+ }
+
+
+ for (i = 0, path = NULL; path == NULL && i < path_data_n; i++) {
+ /*
+ * If the scheme "file" was an explicit part of the URI, the path must
+ * be absolute. So says RFC 8089
+ */
+ if (path_data[i].check_absolute && path_data[i].path[0] != '/') {
+ ATTICerr(0, ATTIC_R_PATH_MUST_BE_ABSOLUTE);
+ ERR_add_error_data(1, path_data[i].path);
+ return NULL;
+ }
+
+ if (stat(path_data[i].path, &st) < 0) {
+ ERR_raise_data(ERR_LIB_SYS, errno,
+ "calling stat(%s)",
+ path_data[i].path);
+ } else {
+ path = path_data[i].path;
+ }
+ }
+ if (path == NULL) {
+ return NULL;
+ }
+
+ /* Successfully found a working path */
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx == NULL) {
+ ATTICerr(0, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ ctx->uri = OPENSSL_strdup(uri);
+ if (ctx->uri == NULL) {
+ ATTICerr(0, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (S_ISDIR(st.st_mode)) {
+ ctx->type = is_dir;
+ ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx, path);
+ ctx->_.dir.last_errno = errno;
+ if (ctx->_.dir.last_entry == NULL) {
+ if (ctx->_.dir.last_errno != 0) {
+ ERR_raise(ERR_LIB_SYS, ctx->_.dir.last_errno);
+ goto err;
+ }
+ ctx->_.dir.end_reached = 1;
+ }
+ } else if ((ctx->_.file.file = BIO_new_file(path, "rb")) == NULL
+ || !file_find_type(ctx)) {
+ BIO_free_all(ctx->_.file.file);
+ goto err;
+ }
+ if (propq != NULL) {
+ ctx->propq = OPENSSL_strdup(propq);
+ if (ctx->propq == NULL) {
+ ATTICerr(0, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ ctx->libctx = libctx;
+
+ return ctx;
+ err:
+ OSSL_STORE_LOADER_CTX_free(ctx);
+ return NULL;
+}
+
+static OSSL_STORE_LOADER_CTX *file_open
+ (const OSSL_STORE_LOADER *loader, const char *uri,
+ const UI_METHOD *ui_method, void *ui_data)
+{
+ return file_open_ex(loader, uri, NULL, NULL, ui_method, ui_data);
+}
+
+static OSSL_STORE_LOADER_CTX *file_attach
+ (const OSSL_STORE_LOADER *loader, BIO *bp,
+ OSSL_LIB_CTX *libctx, const char *propq,
+ const UI_METHOD *ui_method, void *ui_data)
+{
+ OSSL_STORE_LOADER_CTX *ctx = NULL;
+
+ if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL
+ || (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL)) {
+ ATTICerr(0, ERR_R_MALLOC_FAILURE);
+ OSSL_STORE_LOADER_CTX_free(ctx);
+ return NULL;
+ }
+ ctx->libctx = libctx;
+ ctx->flags |= FILE_FLAG_ATTACHED;
+ ctx->_.file.file = bp;
+ if (!file_find_type(ctx)) {
+ /* Safety measure */
+ ctx->_.file.file = NULL;
+ goto err;
+ }
+ return ctx;
+err:
+ OSSL_STORE_LOADER_CTX_free(ctx);
+ return NULL;
+}
+
+static int file_ctrl(OSSL_STORE_LOADER_CTX *ctx, int cmd, va_list args)
+{
+ int ret = 1;
+
+ switch (cmd) {
+ case OSSL_STORE_C_USE_SECMEM:
+ {
+ int on = *(va_arg(args, int *));
+
+ switch (on) {
+ case 0:
+ ctx->flags &= ~FILE_FLAG_SECMEM;
+ break;
+ case 1:
+ ctx->flags |= FILE_FLAG_SECMEM;
+ break;
+ default:
+ ATTICerr(0, ERR_R_PASSED_INVALID_ARGUMENT);
+ ret = 0;
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static int file_expect(OSSL_STORE_LOADER_CTX *ctx, int expected)
+{
+ ctx->expected_type = expected;
+ return 1;
+}
+
+static int file_find(OSSL_STORE_LOADER_CTX *ctx,
+ const OSSL_STORE_SEARCH *search)
+{
+ /*
+ * If ctx == NULL, the library is looking to know if this loader supports
+ * the given search type.
+ */
+
+ if (OSSL_STORE_SEARCH_get_type(search) == OSSL_STORE_SEARCH_BY_NAME) {
+ unsigned long hash = 0;
+
+ if (ctx == NULL)
+ return 1;
+
+ if (ctx->type != is_dir) {
+ ATTICerr(0, ATTIC_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES);
+ return 0;
+ }
+
+ hash = X509_NAME_hash_ex(OSSL_STORE_SEARCH_get0_name(search),
+ NULL, NULL, NULL);
+ BIO_snprintf(ctx->_.dir.search_name, sizeof(ctx->_.dir.search_name),
+ "%08lx", hash);
+ return 1;
+ }
+
+ if (ctx != NULL)
+ ATTICerr(0, ATTIC_R_UNSUPPORTED_SEARCH_TYPE);
+ return 0;
+}
+
+static OSSL_STORE_INFO *file_load_try_decode(OSSL_STORE_LOADER_CTX *ctx,
+ const char *pem_name,
+ const char *pem_header,
+ unsigned char *data, size_t len,
+ const UI_METHOD *ui_method,
+ void *ui_data, int *matchcount)
+{
+ OSSL_STORE_INFO *result = NULL;
+ BUF_MEM *new_mem = NULL;
+ char *new_pem_name = NULL;
+ int t = 0;
+
+ again:
+ {
+ size_t i = 0;
+ void *handler_ctx = NULL;
+ const FILE_HANDLER **matching_handlers =
+ OPENSSL_zalloc(sizeof(*matching_handlers)
+ * OSSL_NELEM(file_handlers));
+
+ if (matching_handlers == NULL) {
+ ATTICerr(0, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ *matchcount = 0;
+ for (i = 0; i < OSSL_NELEM(file_handlers); i++) {
+ const FILE_HANDLER *handler = file_handlers[i];
+ int try_matchcount = 0;
+ void *tmp_handler_ctx = NULL;
+ OSSL_STORE_INFO *tmp_result;
+ unsigned long err;
+
+ ERR_set_mark();
+ tmp_result =
+ handler->try_decode(pem_name, pem_header, data, len,
+ &tmp_handler_ctx, &try_matchcount,
+ ui_method, ui_data, ctx->uri,
+ ctx->libctx, ctx->propq);
+ /* avoid flooding error queue with low-level ASN.1 parse errors */
+ err = ERR_peek_last_error();
+ if (ERR_GET_LIB(err) == ERR_LIB_ASN1
+ && ERR_GET_REASON(err) == ERR_R_NESTED_ASN1_ERROR)
+ ERR_pop_to_mark();
+ else
+ ERR_clear_last_mark();
+
+ if (try_matchcount > 0) {
+
+ matching_handlers[*matchcount] = handler;
+
+ if (handler_ctx)
+ handler->destroy_ctx(&handler_ctx);
+ handler_ctx = tmp_handler_ctx;
+
+ if ((*matchcount += try_matchcount) > 1) {
+ /* more than one match => ambiguous, kill any result */
+ store_info_free(result);
+ store_info_free(tmp_result);
+ if (handler->destroy_ctx != NULL)
+ handler->destroy_ctx(&handler_ctx);
+ handler_ctx = NULL;
+ tmp_result = NULL;
+ result = NULL;
+ }
+ if (result == NULL)
+ result = tmp_result;
+ if (result == NULL) /* e.g., PKCS#12 file decryption error */
+ break;
+ }
+ }
+
+ if (result != NULL
+ && *matchcount == 1 && matching_handlers[0]->repeatable) {
+ ctx->_.file.last_handler = matching_handlers[0];
+ ctx->_.file.last_handler_ctx = handler_ctx;
+ }
+
+ OPENSSL_free(matching_handlers);
+ }
+
+ err:
+ OPENSSL_free(new_pem_name);
+ BUF_MEM_free(new_mem);
+
+ if (result != NULL
+ && (t = OSSL_STORE_INFO_get_type(result)) == STORE_INFO_EMBEDDED) {
+ struct embedded_st *embedded = get0_EMBEDDED(result);
+
+ /* "steal" the embedded data */
+ pem_name = new_pem_name = embedded->pem_name;
+ new_mem = embedded->blob;
+ data = (unsigned char *)new_mem->data;
+ len = new_mem->length;
+ embedded->pem_name = NULL;
+ embedded->blob = NULL;
+
+ store_info_free(result);
+ result = NULL;
+ goto again;
+ }
+
+ return result;
+}
+
+static OSSL_STORE_INFO *file_load_try_repeat(OSSL_STORE_LOADER_CTX *ctx,
+ const UI_METHOD *ui_method,
+ void *ui_data)
+{
+ OSSL_STORE_INFO *result = NULL;
+ int try_matchcount = 0;
+
+ if (ctx->_.file.last_handler != NULL) {
+ result =
+ ctx->_.file.last_handler->try_decode(NULL, NULL, NULL, 0,
+ &ctx->_.file.last_handler_ctx,
+ &try_matchcount,
+ ui_method, ui_data, ctx->uri,
+ ctx->libctx, ctx->propq);
+
+ if (result == NULL) {
+ ctx->_.file.last_handler->destroy_ctx(&ctx->_.file.last_handler_ctx);
+ ctx->_.file.last_handler_ctx = NULL;
+ ctx->_.file.last_handler = NULL;
+ }
+ }
+ return result;
+}
+
+static void pem_free_flag(void *pem_data, int secure, size_t num)
+{
+ if (secure)
+ OPENSSL_secure_clear_free(pem_data, num);
+ else
+ OPENSSL_free(pem_data);
+}
+static int file_read_pem(BIO *bp, char **pem_name, char **pem_header,
+ unsigned char **data, long *len,
+ const UI_METHOD *ui_method, void *ui_data,
+ const char *uri, int secure)
+{
+ int i = secure
+ ? PEM_read_bio_ex(bp, pem_name, pem_header, data, len,
+ PEM_FLAG_SECURE | PEM_FLAG_EAY_COMPATIBLE)
+ : PEM_read_bio(bp, pem_name, pem_header, data, len);
+
+ if (i <= 0)
+ return 0;
+
+ /*
+ * 10 is the number of characters in "Proc-Type:", which
+ * PEM_get_EVP_CIPHER_INFO() requires to be present.
+ * If the PEM header has less characters than that, it's
+ * not worth spending cycles on it.
+ */
+ if (strlen(*pem_header) > 10) {
+ EVP_CIPHER_INFO cipher;
+ struct pem_pass_data pass_data;
+
+ if (!PEM_get_EVP_CIPHER_INFO(*pem_header, &cipher)
+ || !file_fill_pem_pass_data(&pass_data, "PEM pass phrase", uri,
+ ui_method, ui_data)
+ || !PEM_do_header(&cipher, *data, len, file_get_pem_pass,
+ &pass_data)) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static OSSL_STORE_INFO *file_try_read_msblob(BIO *bp, int *matchcount)
+{
+ OSSL_STORE_INFO *result = NULL;
+ int ispub = -1;
+
+ {
+ unsigned int magic = 0, bitlen = 0;
+ int isdss = 0;
+ unsigned char peekbuf[16] = { 0, };
+ const unsigned char *p = peekbuf;
+
+ if (BIO_buffer_peek(bp, peekbuf, sizeof(peekbuf)) <= 0)
+ return 0;
+ if (ossl_do_blob_header(&p, sizeof(peekbuf), &magic, &bitlen,
+ &isdss, &ispub) <= 0)
+ return 0;
+ }
+
+ (*matchcount)++;
+
+ {
+ EVP_PKEY *tmp = ispub
+ ? b2i_PublicKey_bio(bp)
+ : b2i_PrivateKey_bio(bp);
+
+ if (tmp == NULL
+ || (result = OSSL_STORE_INFO_new_PKEY(tmp)) == NULL) {
+ EVP_PKEY_free(tmp);
+ return 0;
+ }
+ }
+
+ return result;
+}
+
+static OSSL_STORE_INFO *file_try_read_PVK(BIO *bp, const UI_METHOD *ui_method,
+ void *ui_data, const char *uri,
+ int *matchcount)
+{
+ OSSL_STORE_INFO *result = NULL;
+
+ {
+ unsigned int saltlen = 0, keylen = 0;
+ unsigned char peekbuf[24] = { 0, };
+ const unsigned char *p = peekbuf;
+
+ if (BIO_buffer_peek(bp, peekbuf, sizeof(peekbuf)) <= 0)
+ return 0;
+ if (!ossl_do_PVK_header(&p, sizeof(peekbuf), 0, &saltlen, &keylen))
+ return 0;
+ }
+
+ (*matchcount)++;
+
+ {
+ EVP_PKEY *tmp = NULL;
+ struct pem_pass_data pass_data;
+
+ if (!file_fill_pem_pass_data(&pass_data, "PVK pass phrase", uri,
+ ui_method, ui_data)
+ || (tmp = b2i_PVK_bio(bp, file_get_pem_pass, &pass_data)) == NULL
+ || (result = OSSL_STORE_INFO_new_PKEY(tmp)) == NULL) {
+ EVP_PKEY_free(tmp);
+ return 0;
+ }
+ }
+
+ return result;
+}
+
+static int file_read_asn1(BIO *bp, unsigned char **data, long *len)
+{
+ BUF_MEM *mem = NULL;
+
+ if (asn1_d2i_read_bio(bp, &mem) < 0)
+ return 0;
+
+ *data = (unsigned char *)mem->data;
+ *len = (long)mem->length;
+ OPENSSL_free(mem);
+
+ return 1;
+}
+
+static int file_name_to_uri(OSSL_STORE_LOADER_CTX *ctx, const char *name,
+ char **data)
+{
+ assert(name != NULL);
+ assert(data != NULL);
+ {
+ const char *pathsep = ossl_ends_with_dirsep(ctx->uri) ? "" : "/";
+ long calculated_length = strlen(ctx->uri) + strlen(pathsep)
+ + strlen(name) + 1 /* \0 */;
+
+ *data = OPENSSL_zalloc(calculated_length);
+ if (*data == NULL) {
+ ATTICerr(0, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ OPENSSL_strlcat(*data, ctx->uri, calculated_length);
+ OPENSSL_strlcat(*data, pathsep, calculated_length);
+ OPENSSL_strlcat(*data, name, calculated_length);
+ }
+ return 1;
+}
+
+static int file_name_check(OSSL_STORE_LOADER_CTX *ctx, const char *name)
+{
+ const char *p = NULL;
+ size_t len = strlen(ctx->_.dir.search_name);
+
+ /* If there are no search criteria, all names are accepted */
+ if (ctx->_.dir.search_name[0] == '\0')
+ return 1;
+
+ /* If the expected type isn't supported, no name is accepted */
+ if (ctx->expected_type != 0
+ && ctx->expected_type != OSSL_STORE_INFO_CERT
+ && ctx->expected_type != OSSL_STORE_INFO_CRL)
+ return 0;
+
+ /*
+ * First, check the basename
+ */
+ if (OPENSSL_strncasecmp(name, ctx->_.dir.search_name, len) != 0
+ || name[len] != '.')
+ return 0;
+ p = &name[len + 1];
+
+ /*
+ * Then, if the expected type is a CRL, check that the extension starts
+ * with 'r'
+ */
+ if (*p == 'r') {
+ p++;
+ if (ctx->expected_type != 0
+ && ctx->expected_type != OSSL_STORE_INFO_CRL)
+ return 0;
+ } else if (ctx->expected_type == OSSL_STORE_INFO_CRL) {
+ return 0;
+ }
+
+ /*
+ * Last, check that the rest of the extension is a decimal number, at
+ * least one digit long.
+ */
+ if (!isdigit(*p))
+ return 0;
+ while (isdigit(*p))
+ p++;
+
+#ifdef __VMS
+ /*
+ * One extra step here, check for a possible generation number.
+ */
+ if (*p == ';')
+ for (p++; *p != '\0'; p++)
+ if (!ossl_isdigit(*p))
+ break;
+#endif
+
+ /*
+ * If we've reached the end of the string at this point, we've successfully
+ * found a fitting file name.
+ */
+ return *p == '\0';
+}
+
+static int file_eof(OSSL_STORE_LOADER_CTX *ctx);
+static int file_error(OSSL_STORE_LOADER_CTX *ctx);
+static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
+ const UI_METHOD *ui_method,
+ void *ui_data)
+{
+ OSSL_STORE_INFO *result = NULL;
+
+ ctx->errcnt = 0;
+
+ if (ctx->type == is_dir) {
+ do {
+ char *newname = NULL;
+
+ if (ctx->_.dir.last_entry == NULL) {
+ if (!ctx->_.dir.end_reached) {
+ assert(ctx->_.dir.last_errno != 0);
+ ERR_raise(ERR_LIB_SYS, ctx->_.dir.last_errno);
+ ctx->errcnt++;
+ }
+ return NULL;
+ }
+
+ if (ctx->_.dir.last_entry[0] != '.'
+ && file_name_check(ctx, ctx->_.dir.last_entry)
+ && !file_name_to_uri(ctx, ctx->_.dir.last_entry, &newname))
+ return NULL;
+
+ /*
+ * On the first call (with a NULL context), OPENSSL_DIR_read()
+ * cares about the second argument. On the following calls, it
+ * only cares that it isn't NULL. Therefore, we can safely give
+ * it our URI here.
+ */
+ ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx, ctx->uri);
+ ctx->_.dir.last_errno = errno;
+ if (ctx->_.dir.last_entry == NULL && ctx->_.dir.last_errno == 0)
+ ctx->_.dir.end_reached = 1;
+
+ if (newname != NULL
+ && (result = OSSL_STORE_INFO_new_NAME(newname)) == NULL) {
+ OPENSSL_free(newname);
+ ATTICerr(0, ERR_R_OSSL_STORE_LIB);
+ return NULL;
+ }
+ } while (result == NULL && !file_eof(ctx));
+ } else {
+ int matchcount = -1;
+
+ again:
+ result = file_load_try_repeat(ctx, ui_method, ui_data);
+ if (result != NULL)
+ return result;
+
+ if (file_eof(ctx))
+ return NULL;
+
+ do {
+ char *pem_name = NULL; /* PEM record name */
+ char *pem_header = NULL; /* PEM record header */
+ unsigned char *data = NULL; /* DER encoded data */
+ long len = 0; /* DER encoded data length */
+
+ matchcount = -1;
+ if (ctx->type == is_pem) {
+ if (!file_read_pem(ctx->_.file.file, &pem_name, &pem_header,
+ &data, &len, ui_method, ui_data, ctx->uri,
+ (ctx->flags & FILE_FLAG_SECMEM) != 0)) {
+ ctx->errcnt++;
+ goto endloop;
+ }
+ } else {
+ if ((result = file_try_read_msblob(ctx->_.file.file,
+ &matchcount)) != NULL
+ || (result = file_try_read_PVK(ctx->_.file.file,
+ ui_method, ui_data, ctx->uri,
+ &matchcount)) != NULL)
+ goto endloop;
+
+ if (!file_read_asn1(ctx->_.file.file, &data, &len)) {
+ ctx->errcnt++;
+ goto endloop;
+ }
+ }
+
+ result = file_load_try_decode(ctx, pem_name, pem_header, data, len,
+ ui_method, ui_data, &matchcount);
+
+ if (result != NULL)
+ goto endloop;
+
+ /*
+ * If a PEM name matches more than one handler, the handlers are
+ * badly coded.
+ */
+ if (!ossl_assert(pem_name == NULL || matchcount <= 1)) {
+ ctx->errcnt++;
+ goto endloop;
+ }
+
+ if (matchcount > 1) {
+ ATTICerr(0, ATTIC_R_AMBIGUOUS_CONTENT_TYPE);
+ } else if (matchcount == 1) {
+ /*
+ * If there are other errors on the stack, they already show
+ * what the problem is.
+ */
+ if (ERR_peek_error() == 0) {
+ ATTICerr(0, ATTIC_R_UNSUPPORTED_CONTENT_TYPE);
+ if (pem_name != NULL)
+ ERR_add_error_data(3, "PEM type is '", pem_name, "'");
+ }
+ }
+ if (matchcount > 0)
+ ctx->errcnt++;
+
+ endloop:
+ pem_free_flag(pem_name, (ctx->flags & FILE_FLAG_SECMEM) != 0, 0);
+ pem_free_flag(pem_header, (ctx->flags & FILE_FLAG_SECMEM) != 0, 0);
+ pem_free_flag(data, (ctx->flags & FILE_FLAG_SECMEM) != 0, len);
+ } while (matchcount == 0 && !file_eof(ctx) && !file_error(ctx));
+
+ /* We bail out on ambiguity */
+ if (matchcount > 1) {
+ store_info_free(result);
+ return NULL;
+ }
+
+ if (result != NULL
+ && ctx->expected_type != 0
+ && ctx->expected_type != OSSL_STORE_INFO_get_type(result)) {
+ store_info_free(result);
+ goto again;
+ }
+ }
+
+ return result;
+}
+
+static int file_error(OSSL_STORE_LOADER_CTX *ctx)
+{
+ return ctx->errcnt > 0;
+}
+
+static int file_eof(OSSL_STORE_LOADER_CTX *ctx)
+{
+ if (ctx->type == is_dir)
+ return ctx->_.dir.end_reached;
+
+ if (ctx->_.file.last_handler != NULL
+ && !ctx->_.file.last_handler->eof(ctx->_.file.last_handler_ctx))
+ return 0;
+ return BIO_eof(ctx->_.file.file);
+}
+
+static int file_close(OSSL_STORE_LOADER_CTX *ctx)
+{
+ if ((ctx->flags & FILE_FLAG_ATTACHED) == 0) {
+ if (ctx->type == is_dir)
+ OPENSSL_DIR_end(&ctx->_.dir.ctx);
+ else
+ BIO_free_all(ctx->_.file.file);
+ } else {
+ /*
+ * Because file_attach() called file_find_type(), we know that a
+ * BIO_f_buffer() has been pushed on top of the regular BIO.
+ */
+ BIO *buff = ctx->_.file.file;
+
+ /* Detach buff */
+ (void)BIO_pop(ctx->_.file.file);
+ /* Safety measure */
+ ctx->_.file.file = NULL;
+
+ BIO_free(buff);
+ }
+ OSSL_STORE_LOADER_CTX_free(ctx);
+ return 1;
+}
+
+/*-
+ * ENGINE management
+ */
+
+static const char *loader_attic_id = "loader_attic";
+static const char *loader_attic_name = "'file:' loader";
+
+static OSSL_STORE_LOADER *loader_attic = NULL;
+
+static int loader_attic_init(ENGINE *e)
+{
+ return 1;
+}
+
+
+static int loader_attic_finish(ENGINE *e)
+{
+ return 1;
+}
+
+
+static int loader_attic_destroy(ENGINE *e)
+{
+ OSSL_STORE_LOADER *loader = OSSL_STORE_unregister_loader("file");
+
+ if (loader == NULL)
+ return 0;
+
+ ERR_unload_ATTIC_strings();
+ OSSL_STORE_LOADER_free(loader);
+ return 1;
+}
+
+static int bind_loader_attic(ENGINE *e)
+{
+
+ /* Ensure the ATTIC error handling is set up on best effort basis */
+ ERR_load_ATTIC_strings();
+
+ if (/* Create the OSSL_STORE_LOADER */
+ (loader_attic = OSSL_STORE_LOADER_new(e, "file")) == NULL
+ || !OSSL_STORE_LOADER_set_open_ex(loader_attic, file_open_ex)
+ || !OSSL_STORE_LOADER_set_open(loader_attic, file_open)
+ || !OSSL_STORE_LOADER_set_attach(loader_attic, file_attach)
+ || !OSSL_STORE_LOADER_set_ctrl(loader_attic, file_ctrl)
+ || !OSSL_STORE_LOADER_set_expect(loader_attic, file_expect)
+ || !OSSL_STORE_LOADER_set_find(loader_attic, file_find)
+ || !OSSL_STORE_LOADER_set_load(loader_attic, file_load)
+ || !OSSL_STORE_LOADER_set_eof(loader_attic, file_eof)
+ || !OSSL_STORE_LOADER_set_error(loader_attic, file_error)
+ || !OSSL_STORE_LOADER_set_close(loader_attic, file_close)
+ /* Init the engine itself */
+ || !ENGINE_set_id(e, loader_attic_id)
+ || !ENGINE_set_name(e, loader_attic_name)
+ || !ENGINE_set_destroy_function(e, loader_attic_destroy)
+ || !ENGINE_set_init_function(e, loader_attic_init)
+ || !ENGINE_set_finish_function(e, loader_attic_finish)
+ /* Finally, register the method with libcrypto */
+ || !OSSL_STORE_register_loader(loader_attic)) {
+ OSSL_STORE_LOADER_free(loader_attic);
+ loader_attic = NULL;
+ ATTICerr(0, ATTIC_R_INIT_FAILED);
+ return 0;
+ }
+
+ return 1;
+}
+
+#ifdef OPENSSL_NO_DYNAMIC_ENGINE
+# error "Only allowed as dynamically shared object"
+#endif
+
+static int bind_helper(ENGINE *e, const char *id)
+{
+ if (id && (strcmp(id, loader_attic_id) != 0))
+ return 0;
+ if (!bind_loader_attic(e))
+ return 0;
+ return 1;
+}
+
+IMPLEMENT_DYNAMIC_CHECK_FN()
+ IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
diff --git a/engines/e_loader_attic.txt b/engines/e_loader_attic.txt
new file mode 100644
index 000000000000..4fb8fdf5e8ac
--- /dev/null
+++ b/engines/e_loader_attic.txt
@@ -0,0 +1,21 @@
+# Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+#Reason codes
+ATTIC_R_AMBIGUOUS_CONTENT_TYPE:100:ambiguous content type
+ATTIC_R_BAD_PASSWORD_READ:101:bad password read
+ATTIC_R_ERROR_VERIFYING_PKCS12_MAC:102:error verifying pkcs12 mac
+ATTIC_R_INIT_FAILED:103:init failed
+ATTIC_R_PASSPHRASE_CALLBACK_ERROR:104:passphrase callback error
+ATTIC_R_PATH_MUST_BE_ABSOLUTE:105:path must be absolute
+ATTIC_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES:106:\
+ search only supported for directories
+ATTIC_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED:107:\
+ ui process interrupted or cancelled
+ATTIC_R_UNSUPPORTED_CONTENT_TYPE:108:unsupported content type
+ATTIC_R_UNSUPPORTED_SEARCH_TYPE:109:unsupported search type
+ATTIC_R_URI_AUTHORITY_UNSUPPORTED:110:uri authority unsupported
diff --git a/engines/e_loader_attic_err.c b/engines/e_loader_attic_err.c
new file mode 100644
index 000000000000..d7c71463d8cc
--- /dev/null
+++ b/engines/e_loader_attic_err.c
@@ -0,0 +1,73 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include "e_loader_attic_err.h"
+
+#ifndef OPENSSL_NO_ERR
+
+static ERR_STRING_DATA ATTIC_str_reasons[] = {
+ {ERR_PACK(0, 0, ATTIC_R_AMBIGUOUS_CONTENT_TYPE), "ambiguous content type"},
+ {ERR_PACK(0, 0, ATTIC_R_BAD_PASSWORD_READ), "bad password read"},
+ {ERR_PACK(0, 0, ATTIC_R_ERROR_VERIFYING_PKCS12_MAC),
+ "error verifying pkcs12 mac"},
+ {ERR_PACK(0, 0, ATTIC_R_INIT_FAILED), "init failed"},
+ {ERR_PACK(0, 0, ATTIC_R_PASSPHRASE_CALLBACK_ERROR),
+ "passphrase callback error"},
+ {ERR_PACK(0, 0, ATTIC_R_PATH_MUST_BE_ABSOLUTE), "path must be absolute"},
+ {ERR_PACK(0, 0, ATTIC_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES),
+ "search only supported for directories"},
+ {ERR_PACK(0, 0, ATTIC_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED),
+ "ui process interrupted or cancelled"},
+ {ERR_PACK(0, 0, ATTIC_R_UNSUPPORTED_CONTENT_TYPE),
+ "unsupported content type"},
+ {ERR_PACK(0, 0, ATTIC_R_UNSUPPORTED_SEARCH_TYPE),
+ "unsupported search type"},
+ {ERR_PACK(0, 0, ATTIC_R_URI_AUTHORITY_UNSUPPORTED),
+ "uri authority unsupported"},
+ {0, NULL}
+};
+
+#endif
+
+static int lib_code = 0;
+static int error_loaded = 0;
+
+static int ERR_load_ATTIC_strings(void)
+{
+ if (lib_code == 0)
+ lib_code = ERR_get_next_error_library();
+
+ if (!error_loaded) {
+#ifndef OPENSSL_NO_ERR
+ ERR_load_strings(lib_code, ATTIC_str_reasons);
+#endif
+ error_loaded = 1;
+ }
+ return 1;
+}
+
+static void ERR_unload_ATTIC_strings(void)
+{
+ if (error_loaded) {
+#ifndef OPENSSL_NO_ERR
+ ERR_unload_strings(lib_code, ATTIC_str_reasons);
+#endif
+ error_loaded = 0;
+ }
+}
+
+static void ERR_ATTIC_error(int function, int reason, const char *file, int line)
+{
+ if (lib_code == 0)
+ lib_code = ERR_get_next_error_library();
+ ERR_raise(lib_code, reason);
+ ERR_set_debug(file, line, NULL);
+}
diff --git a/engines/e_loader_attic_err.h b/engines/e_loader_attic_err.h
new file mode 100644
index 000000000000..b4a144f4cbca
--- /dev/null
+++ b/engines/e_loader_attic_err.h
@@ -0,0 +1,37 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_E_LOADER_ATTIC_ERR_H
+# define OSSL_E_LOADER_ATTIC_ERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+
+# define ATTICerr(f, r) ERR_ATTIC_error(0, (r), OPENSSL_FILE, OPENSSL_LINE)
+
+
+/*
+ * ATTIC reason codes.
+ */
+# define ATTIC_R_AMBIGUOUS_CONTENT_TYPE 100
+# define ATTIC_R_BAD_PASSWORD_READ 101
+# define ATTIC_R_ERROR_VERIFYING_PKCS12_MAC 102
+# define ATTIC_R_INIT_FAILED 103
+# define ATTIC_R_PASSPHRASE_CALLBACK_ERROR 104
+# define ATTIC_R_PATH_MUST_BE_ABSOLUTE 105
+# define ATTIC_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES 106
+# define ATTIC_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED 107
+# define ATTIC_R_UNSUPPORTED_CONTENT_TYPE 108
+# define ATTIC_R_UNSUPPORTED_SEARCH_TYPE 109
+# define ATTIC_R_URI_AUTHORITY_UNSUPPORTED 110
+
+#endif
diff --git a/engines/e_ossltest.c b/engines/e_ossltest.c
index 64376247c3f0..c925d2c5a6a7 100644
--- a/engines/e_ossltest.c
+++ b/engines/e_ossltest.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,6 +13,18 @@
* used for any purpose except testing
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+/*
+ * SHA low level APIs are deprecated for public use, but still ok for
+ * internal use. Note, that due to symbols not being exported, only the
+ * #defines and type definitions can be accessed, function calls are not
+ * available. The digest lengths, block sizes and sizeof(CTX) are used herein
+ * for several different digests.
+ */
+#include "internal/deprecated.h"
+
#include <stdio.h>
#include <string.h>
@@ -25,6 +37,8 @@
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/crypto.h>
+#include <openssl/pem.h>
+#include <crypto/evp.h>
#include "e_ossltest_err.c"
@@ -134,10 +148,13 @@ static const EVP_MD *digest_sha256(void)
/* SHA384/SHA512 */
static int digest_sha384_init(EVP_MD_CTX *ctx);
+static int digest_sha384_update(EVP_MD_CTX *ctx, const void *data,
+ size_t count);
+static int digest_sha384_final(EVP_MD_CTX *ctx, unsigned char *md);
+
static int digest_sha512_init(EVP_MD_CTX *ctx);
static int digest_sha512_update(EVP_MD_CTX *ctx, const void *data,
size_t count);
-static int digest_sha384_final(EVP_MD_CTX *ctx, unsigned char *md);
static int digest_sha512_final(EVP_MD_CTX *ctx, unsigned char *md);
static EVP_MD *_hidden_sha384_md = NULL;
@@ -153,7 +170,7 @@ static const EVP_MD *digest_sha384(void)
sizeof(EVP_MD *) + sizeof(SHA512_CTX))
|| !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_DIGALGID_ABSENT)
|| !EVP_MD_meth_set_init(md, digest_sha384_init)
- || !EVP_MD_meth_set_update(md, digest_sha512_update)
+ || !EVP_MD_meth_set_update(md, digest_sha384_update)
|| !EVP_MD_meth_set_final(md, digest_sha384_final)) {
EVP_MD_meth_free(md);
md = NULL;
@@ -206,15 +223,15 @@ static int ossltest_digest_nids(const int **nids)
if (!init) {
const EVP_MD *md;
if ((md = digest_md5()) != NULL)
- digest_nids[pos++] = EVP_MD_type(md);
+ digest_nids[pos++] = EVP_MD_get_type(md);
if ((md = digest_sha1()) != NULL)
- digest_nids[pos++] = EVP_MD_type(md);
+ digest_nids[pos++] = EVP_MD_get_type(md);
if ((md = digest_sha256()) != NULL)
- digest_nids[pos++] = EVP_MD_type(md);
+ digest_nids[pos++] = EVP_MD_get_type(md);
if ((md = digest_sha384()) != NULL)
- digest_nids[pos++] = EVP_MD_type(md);
+ digest_nids[pos++] = EVP_MD_get_type(md);
if ((md = digest_sha512()) != NULL)
- digest_nids[pos++] = EVP_MD_type(md);
+ digest_nids[pos++] = EVP_MD_get_type(md);
digest_nids[pos] = 0;
init = 1;
}
@@ -227,21 +244,39 @@ static int ossltest_ciphers(ENGINE *, const EVP_CIPHER **,
const int **, int);
static int ossltest_cipher_nids[] = {
- NID_aes_128_cbc, NID_aes_128_gcm, 0
+ NID_aes_128_cbc, NID_aes_128_gcm,
+ NID_aes_128_cbc_hmac_sha1, 0
};
/* AES128 */
-int ossltest_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
- const unsigned char *iv, int enc);
-int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl);
-int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
- const unsigned char *iv, int enc);
-int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl);
+static int ossltest_aes128_init_key(EVP_CIPHER_CTX *ctx,
+ const unsigned char *key,
+ const unsigned char *iv, int enc);
+static int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl);
+static int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx,
+ const unsigned char *key,
+ const unsigned char *iv, int enc);
+static int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl);
static int ossltest_aes128_gcm_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
void *ptr);
+static int ossltest_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx,
+ const unsigned char *key,
+ const unsigned char *iv,
+ int enc);
+static int ossltest_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx,
+ unsigned char *out,
+ const unsigned char *in,
+ size_t inl);
+static int ossltest_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type,
+ int arg, void *ptr);
+
+typedef struct {
+ size_t payload_length; /* AAD length in decrypt case */
+ unsigned int tls_ver;
+} EVP_AES_HMAC_SHA1;
static EVP_CIPHER *_hidden_aes_128_cbc = NULL;
static const EVP_CIPHER *ossltest_aes_128_cbc(void)
@@ -259,12 +294,13 @@ static const EVP_CIPHER *ossltest_aes_128_cbc(void)
|| !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_cbc,
ossltest_aes128_cbc_cipher)
|| !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_cbc,
- EVP_CIPHER_impl_ctx_size(EVP_aes_128_cbc())))) {
+ EVP_CIPHER_impl_ctx_size(EVP_aes_128_cbc())))) {
EVP_CIPHER_meth_free(_hidden_aes_128_cbc);
_hidden_aes_128_cbc = NULL;
}
return _hidden_aes_128_cbc;
}
+
static EVP_CIPHER *_hidden_aes_128_gcm = NULL;
#define AES_GCM_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \
@@ -288,20 +324,91 @@ static const EVP_CIPHER *ossltest_aes_128_gcm(void)
|| !EVP_CIPHER_meth_set_ctrl(_hidden_aes_128_gcm,
ossltest_aes128_gcm_ctrl)
|| !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_gcm,
- EVP_CIPHER_impl_ctx_size(EVP_aes_128_gcm())))) {
+ EVP_CIPHER_impl_ctx_size(EVP_aes_128_gcm())))) {
EVP_CIPHER_meth_free(_hidden_aes_128_gcm);
_hidden_aes_128_gcm = NULL;
}
return _hidden_aes_128_gcm;
}
+static EVP_CIPHER *_hidden_aes_128_cbc_hmac_sha1 = NULL;
+
+static const EVP_CIPHER *ossltest_aes_128_cbc_hmac_sha1(void)
+{
+ if (_hidden_aes_128_cbc_hmac_sha1 == NULL
+ && ((_hidden_aes_128_cbc_hmac_sha1
+ = EVP_CIPHER_meth_new(NID_aes_128_cbc_hmac_sha1,
+ 16 /* block size */,
+ 16 /* key len */)) == NULL
+ || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_128_cbc_hmac_sha1,16)
+ || !EVP_CIPHER_meth_set_flags(_hidden_aes_128_cbc_hmac_sha1,
+ EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 |
+ EVP_CIPH_FLAG_AEAD_CIPHER)
+ || !EVP_CIPHER_meth_set_init(_hidden_aes_128_cbc_hmac_sha1,
+ ossltest_aes128_cbc_hmac_sha1_init_key)
+ || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_cbc_hmac_sha1,
+ ossltest_aes128_cbc_hmac_sha1_cipher)
+ || !EVP_CIPHER_meth_set_ctrl(_hidden_aes_128_cbc_hmac_sha1,
+ ossltest_aes128_cbc_hmac_sha1_ctrl)
+ || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_aes_128_cbc_hmac_sha1,
+ EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv)
+ || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_aes_128_cbc_hmac_sha1,
+ EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_cbc_hmac_sha1,
+ sizeof(EVP_AES_HMAC_SHA1)))) {
+ EVP_CIPHER_meth_free(_hidden_aes_128_cbc_hmac_sha1);
+ _hidden_aes_128_cbc_hmac_sha1 = NULL;
+ }
+ return _hidden_aes_128_cbc_hmac_sha1;
+}
+
static void destroy_ciphers(void)
{
EVP_CIPHER_meth_free(_hidden_aes_128_cbc);
EVP_CIPHER_meth_free(_hidden_aes_128_gcm);
+ EVP_CIPHER_meth_free(_hidden_aes_128_cbc_hmac_sha1);
_hidden_aes_128_cbc = NULL;
+ _hidden_aes_128_gcm = NULL;
+ _hidden_aes_128_cbc_hmac_sha1 = NULL;
+}
+
+/* Key loading */
+static EVP_PKEY *load_key(ENGINE *eng, const char *key_id, int pub,
+ UI_METHOD *ui_method, void *ui_data)
+{
+ BIO *in;
+ EVP_PKEY *key;
+
+ if (OPENSSL_strncasecmp(key_id, "ot:", 3) != 0)
+ return NULL;
+ key_id += 3;
+
+ fprintf(stderr, "[ossltest]Loading %s key %s\n",
+ pub ? "Public" : "Private", key_id);
+ in = BIO_new_file(key_id, "r");
+ if (!in)
+ return NULL;
+ if (pub)
+ key = PEM_read_bio_PUBKEY(in, NULL, 0, NULL);
+ else
+ key = PEM_read_bio_PrivateKey(in, NULL, 0, NULL);
+ BIO_free(in);
+ return key;
+}
+
+static EVP_PKEY *ossltest_load_privkey(ENGINE *eng, const char *key_id,
+ UI_METHOD *ui_method, void *ui_data)
+{
+ return load_key(eng, key_id, 0, ui_method, ui_data);
+}
+
+static EVP_PKEY *ossltest_load_pubkey(ENGINE *eng, const char *key_id,
+ UI_METHOD *ui_method, void *ui_data)
+{
+ return load_key(eng, key_id, 1, ui_method, ui_data);
}
+
static int bind_ossltest(ENGINE *e)
{
/* Ensure the ossltest error handling is set up */
@@ -313,6 +420,8 @@ static int bind_ossltest(ENGINE *e)
|| !ENGINE_set_ciphers(e, ossltest_ciphers)
|| !ENGINE_set_RAND(e, ossltest_rand_method())
|| !ENGINE_set_destroy_function(e, ossltest_destroy)
+ || !ENGINE_set_load_privkey_function(e, ossltest_load_privkey)
+ || !ENGINE_set_load_pubkey_function(e, ossltest_load_pubkey)
|| !ENGINE_set_init_function(e, ossltest_init)
|| !ENGINE_set_finish_function(e, ossltest_finish)) {
OSSLTESTerr(OSSLTEST_F_BIND_OSSLTEST, OSSLTEST_R_INIT_FAILED);
@@ -431,6 +540,9 @@ static int ossltest_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
case NID_aes_128_gcm:
*cipher = ossltest_aes_128_gcm();
break;
+ case NID_aes_128_cbc_hmac_sha1:
+ *cipher = ossltest_aes_128_cbc_hmac_sha1();
+ break;
default:
ok = 0;
*cipher = NULL;
@@ -454,23 +566,20 @@ static void fill_known_data(unsigned char *md, unsigned int len)
* value, so that all "MD5" digests using the test engine always end up with
* the same value.
*/
-#undef data
-#define data(ctx) ((MD5_CTX *)EVP_MD_CTX_md_data(ctx))
static int digest_md5_init(EVP_MD_CTX *ctx)
{
- return MD5_Init(data(ctx));
+ return EVP_MD_meth_get_init(EVP_md5())(ctx);
}
static int digest_md5_update(EVP_MD_CTX *ctx, const void *data,
size_t count)
{
- return MD5_Update(data(ctx), data, (size_t)count);
+ return EVP_MD_meth_get_update(EVP_md5())(ctx, data, count);
}
static int digest_md5_final(EVP_MD_CTX *ctx, unsigned char *md)
{
- int ret;
- ret = MD5_Final(md, data(ctx));
+ int ret = EVP_MD_meth_get_final(EVP_md5())(ctx, md);
if (ret > 0) {
fill_known_data(md, MD5_DIGEST_LENGTH);
@@ -481,23 +590,20 @@ static int digest_md5_final(EVP_MD_CTX *ctx, unsigned char *md)
/*
* SHA1 implementation.
*/
-#undef data
-#define data(ctx) ((SHA_CTX *)EVP_MD_CTX_md_data(ctx))
static int digest_sha1_init(EVP_MD_CTX *ctx)
{
- return SHA1_Init(data(ctx));
+ return EVP_MD_meth_get_init(EVP_sha1())(ctx);
}
static int digest_sha1_update(EVP_MD_CTX *ctx, const void *data,
size_t count)
{
- return SHA1_Update(data(ctx), data, (size_t)count);
+ return EVP_MD_meth_get_update(EVP_sha1())(ctx, data, count);
}
static int digest_sha1_final(EVP_MD_CTX *ctx, unsigned char *md)
{
- int ret;
- ret = SHA1_Final(md, data(ctx));
+ int ret = EVP_MD_meth_get_final(EVP_sha1())(ctx, md);
if (ret > 0) {
fill_known_data(md, SHA_DIGEST_LENGTH);
@@ -508,23 +614,20 @@ static int digest_sha1_final(EVP_MD_CTX *ctx, unsigned char *md)
/*
* SHA256 implementation.
*/
-#undef data
-#define data(ctx) ((SHA256_CTX *)EVP_MD_CTX_md_data(ctx))
static int digest_sha256_init(EVP_MD_CTX *ctx)
{
- return SHA256_Init(data(ctx));
+ return EVP_MD_meth_get_init(EVP_sha256())(ctx);
}
static int digest_sha256_update(EVP_MD_CTX *ctx, const void *data,
size_t count)
{
- return SHA256_Update(data(ctx), data, (size_t)count);
+ return EVP_MD_meth_get_update(EVP_sha256())(ctx, data, count);
}
static int digest_sha256_final(EVP_MD_CTX *ctx, unsigned char *md)
{
- int ret;
- ret = SHA256_Final(md, data(ctx));
+ int ret = EVP_MD_meth_get_final(EVP_sha256())(ctx, md);
if (ret > 0) {
fill_known_data(md, SHA256_DIGEST_LENGTH);
@@ -533,31 +636,22 @@ static int digest_sha256_final(EVP_MD_CTX *ctx, unsigned char *md)
}
/*
- * SHA384/512 implementation.
+ * SHA384 implementation.
*/
-#undef data
-#define data(ctx) ((SHA512_CTX *)EVP_MD_CTX_md_data(ctx))
static int digest_sha384_init(EVP_MD_CTX *ctx)
{
- return SHA384_Init(data(ctx));
+ return EVP_MD_meth_get_init(EVP_sha384())(ctx);
}
-static int digest_sha512_init(EVP_MD_CTX *ctx)
-{
- return SHA512_Init(data(ctx));
-}
-
-static int digest_sha512_update(EVP_MD_CTX *ctx, const void *data,
+static int digest_sha384_update(EVP_MD_CTX *ctx, const void *data,
size_t count)
{
- return SHA512_Update(data(ctx), data, (size_t)count);
+ return EVP_MD_meth_get_update(EVP_sha384())(ctx, data, count);
}
static int digest_sha384_final(EVP_MD_CTX *ctx, unsigned char *md)
{
- int ret;
- /* Actually uses SHA512_Final! */
- ret = SHA512_Final(md, data(ctx));
+ int ret = EVP_MD_meth_get_final(EVP_sha384())(ctx, md);
if (ret > 0) {
fill_known_data(md, SHA384_DIGEST_LENGTH);
@@ -565,10 +659,23 @@ static int digest_sha384_final(EVP_MD_CTX *ctx, unsigned char *md)
return ret;
}
+/*
+ * SHA512 implementation.
+ */
+static int digest_sha512_init(EVP_MD_CTX *ctx)
+{
+ return EVP_MD_meth_get_init(EVP_sha512())(ctx);
+}
+
+static int digest_sha512_update(EVP_MD_CTX *ctx, const void *data,
+ size_t count)
+{
+ return EVP_MD_meth_get_update(EVP_sha512())(ctx, data, count);
+}
+
static int digest_sha512_final(EVP_MD_CTX *ctx, unsigned char *md)
{
- int ret;
- ret = SHA512_Final(md, data(ctx));
+ int ret = EVP_MD_meth_get_final(EVP_sha512())(ctx, md);
if (ret > 0) {
fill_known_data(md, SHA512_DIGEST_LENGTH);
@@ -580,14 +687,15 @@ static int digest_sha512_final(EVP_MD_CTX *ctx, unsigned char *md)
* AES128 Implementation
*/
-int ossltest_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
- const unsigned char *iv, int enc)
+static int ossltest_aes128_init_key(EVP_CIPHER_CTX *ctx,
+ const unsigned char *key,
+ const unsigned char *iv, int enc)
{
return EVP_CIPHER_meth_get_init(EVP_aes_128_cbc()) (ctx, key, iv, enc);
}
-int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
+static int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
{
unsigned char *tmpbuf;
int ret;
@@ -613,15 +721,15 @@ int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return ret;
}
-int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
- const unsigned char *iv, int enc)
+static int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx,
+ const unsigned char *key,
+ const unsigned char *iv, int enc)
{
return EVP_CIPHER_meth_get_init(EVP_aes_128_gcm()) (ctx, key, iv, enc);
}
-
-int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
+static int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
{
unsigned char *tmpbuf = OPENSSL_malloc(inl);
@@ -666,6 +774,128 @@ static int ossltest_aes128_gcm_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
return 1;
}
+#define NO_PAYLOAD_LENGTH ((size_t)-1)
+# define data(ctx) ((EVP_AES_HMAC_SHA1 *)EVP_CIPHER_CTX_get_cipher_data(ctx))
+
+static int ossltest_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx,
+ const unsigned char *inkey,
+ const unsigned char *iv,
+ int enc)
+{
+ EVP_AES_HMAC_SHA1 *key = data(ctx);
+ key->payload_length = NO_PAYLOAD_LENGTH;
+ return 1;
+}
+
+static int ossltest_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx,
+ unsigned char *out,
+ const unsigned char *in,
+ size_t len)
+{
+ EVP_AES_HMAC_SHA1 *key = data(ctx);
+ unsigned int l;
+ size_t plen = key->payload_length;
+
+ key->payload_length = NO_PAYLOAD_LENGTH;
+
+ if (len % AES_BLOCK_SIZE)
+ return 0;
+
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
+ if (plen == NO_PAYLOAD_LENGTH)
+ plen = len;
+ else if (len !=
+ ((plen + SHA_DIGEST_LENGTH +
+ AES_BLOCK_SIZE) & -AES_BLOCK_SIZE))
+ return 0;
+
+ memmove(out, in, plen);
+
+ if (plen != len) { /* "TLS" mode of operation */
+ /* calculate HMAC and append it to payload */
+ fill_known_data(out + plen, SHA_DIGEST_LENGTH);
+
+ /* pad the payload|hmac */
+ plen += SHA_DIGEST_LENGTH;
+ for (l = len - plen - 1; plen < len; plen++)
+ out[plen] = l;
+ }
+ } else {
+ /* decrypt HMAC|padding at once */
+ memmove(out, in, len);
+
+ if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */
+ unsigned int maxpad, pad;
+
+ if (key->tls_ver >= TLS1_1_VERSION) {
+ if (len < (AES_BLOCK_SIZE + SHA_DIGEST_LENGTH + 1))
+ return 0;
+
+ /* omit explicit iv */
+ in += AES_BLOCK_SIZE;
+ out += AES_BLOCK_SIZE;
+ len -= AES_BLOCK_SIZE;
+ } else if (len < (SHA_DIGEST_LENGTH + 1))
+ return 0;
+
+ /* figure out payload length */
+ pad = out[len - 1];
+ maxpad = len - (SHA_DIGEST_LENGTH + 1);
+ if (pad > maxpad)
+ return 0;
+ for (plen = len - pad - 1; plen < len; plen++)
+ if (out[plen] != pad)
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int ossltest_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type,
+ int arg, void *ptr)
+{
+ EVP_AES_HMAC_SHA1 *key = data(ctx);
+
+ switch (type) {
+ case EVP_CTRL_AEAD_SET_MAC_KEY:
+ return 1;
+
+ case EVP_CTRL_AEAD_TLS1_AAD:
+ {
+ unsigned char *p = ptr;
+ unsigned int len;
+
+ if (arg != EVP_AEAD_TLS1_AAD_LEN)
+ return -1;
+
+ len = p[arg - 2] << 8 | p[arg - 1];
+ key->tls_ver = p[arg - 4] << 8 | p[arg - 3];
+
+ if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
+ key->payload_length = len;
+ if (key->tls_ver >= TLS1_1_VERSION) {
+ if (len < AES_BLOCK_SIZE)
+ return 0;
+ len -= AES_BLOCK_SIZE;
+ p[arg - 2] = len >> 8;
+ p[arg - 1] = len;
+ }
+
+ return (int)(((len + SHA_DIGEST_LENGTH +
+ AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)
+ - len);
+ } else {
+ key->payload_length = arg;
+
+ return SHA_DIGEST_LENGTH;
+ }
+ }
+ default:
+ return -1;
+ }
+}
+
static int ossltest_rand_bytes(unsigned char *buf, int num)
{
unsigned char val = 1;
diff --git a/engines/e_ossltest.txt b/engines/e_ossltest.txt
index 2b2e31a0756b..645917fe3bb8 100644
--- a/engines/e_ossltest.txt
+++ b/engines/e_ossltest.txt
@@ -1,13 +1,9 @@
-# Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
-# Function codes
-OSSLTEST_F_BIND_OSSLTEST:100:bind_ossltest
-OSSLTEST_F_OSSLTEST_AES128_INIT_KEY:101:*
-
#Reason codes
OSSLTEST_R_INIT_FAILED:100:init failed
diff --git a/engines/e_ossltest_err.c b/engines/e_ossltest_err.c
index 920a13a6922a..f229aeb4384c 100644
--- a/engines/e_ossltest_err.c
+++ b/engines/e_ossltest_err.c
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,12 +13,6 @@
#ifndef OPENSSL_NO_ERR
-static ERR_STRING_DATA OSSLTEST_str_functs[] = {
- {ERR_PACK(0, OSSLTEST_F_BIND_OSSLTEST, 0), "bind_ossltest"},
- {ERR_PACK(0, OSSLTEST_F_OSSLTEST_AES128_INIT_KEY, 0), ""},
- {0, NULL}
-};
-
static ERR_STRING_DATA OSSLTEST_str_reasons[] = {
{ERR_PACK(0, 0, OSSLTEST_R_INIT_FAILED), "init failed"},
{0, NULL}
@@ -36,7 +30,6 @@ static int ERR_load_OSSLTEST_strings(void)
if (!error_loaded) {
#ifndef OPENSSL_NO_ERR
- ERR_load_strings(lib_code, OSSLTEST_str_functs);
ERR_load_strings(lib_code, OSSLTEST_str_reasons);
#endif
error_loaded = 1;
@@ -48,16 +41,16 @@ static void ERR_unload_OSSLTEST_strings(void)
{
if (error_loaded) {
#ifndef OPENSSL_NO_ERR
- ERR_unload_strings(lib_code, OSSLTEST_str_functs);
ERR_unload_strings(lib_code, OSSLTEST_str_reasons);
#endif
error_loaded = 0;
}
}
-static void ERR_OSSLTEST_error(int function, int reason, char *file, int line)
+static void ERR_OSSLTEST_error(int function, int reason, const char *file, int line)
{
if (lib_code == 0)
lib_code = ERR_get_next_error_library();
- ERR_PUT_error(lib_code, function, reason, file, line);
+ ERR_raise(lib_code, reason);
+ ERR_set_debug(file, line, NULL);
}
diff --git a/engines/e_ossltest_err.h b/engines/e_ossltest_err.h
index 8e6535b76c08..c89409079be7 100644
--- a/engines/e_ossltest_err.h
+++ b/engines/e_ossltest_err.h
@@ -1,24 +1,23 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef OSSL_ENGINES_E_OSSLTEST_ERR_H
-# define OSSL_ENGINES_E_OSSLTEST_ERR_H
+#ifndef OSSL_E_OSSLTEST_ERR_H
+# define OSSL_E_OSSLTEST_ERR_H
+# pragma once
-# define OSSLTESTerr(f, r) ERR_OSSLTEST_error((f), (r), OPENSSL_FILE, OPENSSL_LINE)
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
-/*
- * OSSLTEST function codes.
- */
-# define OSSLTEST_F_BIND_OSSLTEST 100
-# define OSSLTEST_F_OSSLTEST_AES128_INIT_KEY 101
+# define OSSLTESTerr(f, r) ERR_OSSLTEST_error(0, (r), OPENSSL_FILE, OPENSSL_LINE)
+
/*
* OSSLTEST reason codes.
diff --git a/engines/e_padlock.c b/engines/e_padlock.c
index a82c07e81373..9ad1c48c71a5 100644
--- a/engines/e_padlock.c
+++ b/engines/e_padlock.c
@@ -1,12 +1,18 @@
/*
- * Copyright 2004-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * This file uses the low level AES and engine functions (which are deprecated
+ * for non-internal use) in order to implement the padlock engine AES ciphers.
+ */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <stdio.h>
#include <string.h>
@@ -19,53 +25,49 @@
#include <openssl/err.h>
#include <openssl/modes.h>
-#ifndef OPENSSL_NO_HW
-# ifndef OPENSSL_NO_HW_PADLOCK
-
-/* Attempt to have a single source for both 0.9.7 and 0.9.8 :-) */
-# if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
-# ifndef OPENSSL_NO_DYNAMIC_ENGINE
-# define DYNAMIC_ENGINE
-# endif
-# elif (OPENSSL_VERSION_NUMBER >= 0x00907000L)
-# ifdef ENGINE_DYNAMIC_SUPPORT
-# define DYNAMIC_ENGINE
-# endif
-# else
-# error "Only OpenSSL >= 0.9.7 is supported"
-# endif
+#ifndef OPENSSL_NO_PADLOCKENG
/*
* VIA PadLock AES is available *ONLY* on some x86 CPUs. Not only that it
* doesn't exist elsewhere, but it even can't be compiled on other platforms!
*/
-# undef COMPILE_HW_PADLOCK
-# if defined(PADLOCK_ASM)
-# define COMPILE_HW_PADLOCK
-# ifdef OPENSSL_NO_DYNAMIC_ENGINE
+# undef COMPILE_PADLOCKENG
+# if defined(PADLOCK_ASM)
+# define COMPILE_PADLOCKENG
+# ifdef OPENSSL_NO_DYNAMIC_ENGINE
static ENGINE *ENGINE_padlock(void);
-# endif
# endif
+# endif
-# ifdef OPENSSL_NO_DYNAMIC_ENGINE
+# ifdef OPENSSL_NO_DYNAMIC_ENGINE
void engine_load_padlock_int(void);
void engine_load_padlock_int(void)
{
/* On non-x86 CPUs it just returns. */
-# ifdef COMPILE_HW_PADLOCK
+# ifdef COMPILE_PADLOCKENG
ENGINE *toadd = ENGINE_padlock();
if (!toadd)
return;
+ ERR_set_mark();
ENGINE_add(toadd);
+ /*
+ * If the "add" worked, it gets a structural reference. So either way, we
+ * release our just-created reference.
+ */
ENGINE_free(toadd);
- ERR_clear_error();
-# endif
+ /*
+ * If the "add" didn't work, it was probably a conflict because it was
+ * already added (eg. someone calling ENGINE_load_blah then calling
+ * ENGINE_load_builtin_engines() perhaps).
+ */
+ ERR_pop_to_mark();
+# endif
}
-# endif
+# endif
-# ifdef COMPILE_HW_PADLOCK
+# ifdef COMPILE_PADLOCKENG
/* Function for ENGINE detection and control */
static int padlock_available(void);
@@ -119,7 +121,7 @@ static int padlock_bind_helper(ENGINE *e)
return 1;
}
-# ifdef OPENSSL_NO_DYNAMIC_ENGINE
+# ifdef OPENSSL_NO_DYNAMIC_ENGINE
/* Constructor */
static ENGINE *ENGINE_padlock(void)
{
@@ -136,7 +138,7 @@ static ENGINE *ENGINE_padlock(void)
return eng;
}
-# endif
+# endif
/* Check availability of the engine */
static int padlock_init(ENGINE *e)
@@ -148,7 +150,7 @@ static int padlock_init(ENGINE *e)
* This stuff is needed if this ENGINE is being compiled into a
* self-contained shared-library.
*/
-# ifndef OPENSSL_NO_DYNAMIC_ENGINE
+# ifndef OPENSSL_NO_DYNAMIC_ENGINE
static int padlock_bind_fn(ENGINE *e, const char *id)
{
if (id && (strcmp(id, padlock_id) != 0)) {
@@ -164,14 +166,14 @@ static int padlock_bind_fn(ENGINE *e, const char *id)
IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(padlock_bind_fn)
-# endif /* !OPENSSL_NO_DYNAMIC_ENGINE */
+# endif /* !OPENSSL_NO_DYNAMIC_ENGINE */
/* ===== Here comes the "real" engine ===== */
/* Some AES-related constants */
-# define AES_BLOCK_SIZE 16
-# define AES_KEY_SIZE_128 16
-# define AES_KEY_SIZE_192 24
-# define AES_KEY_SIZE_256 32
+# define AES_BLOCK_SIZE 16
+# define AES_KEY_SIZE_128 16
+# define AES_KEY_SIZE_192 24
+# define AES_KEY_SIZE_256 32
/*
* Here we store the status information relevant to the current context.
*/
@@ -237,29 +239,29 @@ static int padlock_available(void)
/* ===== AES encryption/decryption ===== */
-# if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb)
-# define NID_aes_128_cfb NID_aes_128_cfb128
-# endif
+# if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb)
+# define NID_aes_128_cfb NID_aes_128_cfb128
+# endif
-# if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb)
-# define NID_aes_128_ofb NID_aes_128_ofb128
-# endif
+# if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb)
+# define NID_aes_128_ofb NID_aes_128_ofb128
+# endif
-# if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb)
-# define NID_aes_192_cfb NID_aes_192_cfb128
-# endif
+# if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb)
+# define NID_aes_192_cfb NID_aes_192_cfb128
+# endif
-# if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb)
-# define NID_aes_192_ofb NID_aes_192_ofb128
-# endif
+# if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb)
+# define NID_aes_192_ofb NID_aes_192_ofb128
+# endif
-# if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb)
-# define NID_aes_256_cfb NID_aes_256_cfb128
-# endif
+# if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb)
+# define NID_aes_256_cfb NID_aes_256_cfb128
+# endif
-# if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb)
-# define NID_aes_256_ofb NID_aes_256_ofb128
-# endif
+# if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb)
+# define NID_aes_256_ofb NID_aes_256_ofb128
+# endif
/* List of supported ciphers. */
static const int padlock_cipher_nids[] = {
@@ -289,9 +291,9 @@ static int padlock_cipher_nids_num = (sizeof(padlock_cipher_nids) /
static int padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
-# define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) + \
+# define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) + \
( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F ) )
-# define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\
+# define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\
NEAREST_ALIGNED(EVP_CIPHER_CTX_get_cipher_data(ctx)))
static int
@@ -322,13 +324,13 @@ padlock_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
size_t chunk;
- if ((chunk = EVP_CIPHER_CTX_num(ctx))) { /* borrow chunk variable */
+ if ((chunk = EVP_CIPHER_CTX_get_num(ctx))) { /* borrow chunk variable */
unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx);
if (chunk >= AES_BLOCK_SIZE)
return 0; /* bogus value */
- if (EVP_CIPHER_CTX_encrypting(ctx))
+ if (EVP_CIPHER_CTX_is_encrypting(ctx))
while (chunk < AES_BLOCK_SIZE && nbytes != 0) {
ivp[chunk] = *(out_arg++) = *(in_arg++) ^ ivp[chunk];
chunk++, nbytes--;
@@ -396,7 +398,7 @@ padlock_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
/*
* ctx->num is maintained in byte-oriented modes, such as CFB and OFB...
*/
- if ((chunk = EVP_CIPHER_CTX_num(ctx))) { /* borrow chunk variable */
+ if ((chunk = EVP_CIPHER_CTX_get_num(ctx))) { /* borrow chunk variable */
unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx);
if (chunk >= AES_BLOCK_SIZE)
@@ -455,7 +457,12 @@ padlock_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
const unsigned char *in_arg, size_t nbytes)
{
struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
- unsigned int num = EVP_CIPHER_CTX_num(ctx);
+ int n = EVP_CIPHER_CTX_get_num(ctx);
+ unsigned int num;
+
+ if (n < 0)
+ return 0;
+ num = (unsigned int)n;
CRYPTO_ctr128_encrypt_ctr32(in_arg, out_arg, nbytes,
cdata, EVP_CIPHER_CTX_iv_noconst(ctx),
@@ -466,17 +473,17 @@ padlock_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
return 1;
}
-# define EVP_CIPHER_block_size_ECB AES_BLOCK_SIZE
-# define EVP_CIPHER_block_size_CBC AES_BLOCK_SIZE
-# define EVP_CIPHER_block_size_OFB 1
-# define EVP_CIPHER_block_size_CFB 1
-# define EVP_CIPHER_block_size_CTR 1
+# define EVP_CIPHER_block_size_ECB AES_BLOCK_SIZE
+# define EVP_CIPHER_block_size_CBC AES_BLOCK_SIZE
+# define EVP_CIPHER_block_size_OFB 1
+# define EVP_CIPHER_block_size_CFB 1
+# define EVP_CIPHER_block_size_CTR 1
/*
* Declaring so many ciphers by hand would be a pain. Instead introduce a bit
* of preprocessor magic :-)
*/
-# define DECLARE_AES_EVP(ksize,lmode,umode) \
+# define DECLARE_AES_EVP(ksize,lmode,umode) \
static EVP_CIPHER *_hidden_aes_##ksize##_##lmode = NULL; \
static const EVP_CIPHER *padlock_aes_##ksize##_##lmode(void) \
{ \
@@ -598,8 +605,8 @@ padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
struct padlock_cipher_data *cdata;
- int key_len = EVP_CIPHER_CTX_key_length(ctx) * 8;
- unsigned long mode = EVP_CIPHER_CTX_mode(ctx);
+ int key_len = EVP_CIPHER_CTX_get_key_length(ctx) * 8;
+ unsigned long mode = EVP_CIPHER_CTX_get_mode(ctx);
if (key == NULL)
return 0; /* ERROR */
@@ -611,7 +618,7 @@ padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
if (mode == EVP_CIPH_OFB_MODE || mode == EVP_CIPH_CTR_MODE)
cdata->cword.b.encdec = 0;
else
- cdata->cword.b.encdec = (EVP_CIPHER_CTX_encrypting(ctx) == 0);
+ cdata->cword.b.encdec = (EVP_CIPHER_CTX_is_encrypting(ctx) == 0);
cdata->cword.b.rounds = 10 + (key_len - 128) / 32;
cdata->cword.b.ksize = (key_len - 128) / 64;
@@ -639,12 +646,12 @@ padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
AES_set_decrypt_key(key, key_len, &cdata->ks);
else
AES_set_encrypt_key(key, key_len, &cdata->ks);
-# ifndef AES_ASM
+# ifndef AES_ASM
/*
* OpenSSL C functions use byte-swapped extended key.
*/
padlock_key_bswap(&cdata->ks);
-# endif
+# endif
cdata->cword.b.keygen = 1;
break;
@@ -727,12 +734,10 @@ static RAND_METHOD padlock_rand = {
padlock_rand_status, /* rand status */
};
-# endif /* COMPILE_HW_PADLOCK */
-# endif /* !OPENSSL_NO_HW_PADLOCK */
-#endif /* !OPENSSL_NO_HW */
+# endif /* COMPILE_PADLOCKENG */
+#endif /* !OPENSSL_NO_PADLOCKENG */
-#if defined(OPENSSL_NO_HW) || defined(OPENSSL_NO_HW_PADLOCK) \
- || !defined(COMPILE_HW_PADLOCK)
+#if defined(OPENSSL_NO_PADLOCKENG) || !defined(COMPILE_PADLOCKENG)
# ifndef OPENSSL_NO_DYNAMIC_ENGINE
OPENSSL_EXPORT
int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns);
diff --git a/include/crypto/__DECC_INCLUDE_EPILOGUE.H b/include/crypto/__DECC_INCLUDE_EPILOGUE.H
index c350018ad190..e57c0eab3e3a 100644
--- a/include/crypto/__DECC_INCLUDE_EPILOGUE.H
+++ b/include/crypto/__DECC_INCLUDE_EPILOGUE.H
@@ -1,7 +1,7 @@
/*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/include/crypto/__DECC_INCLUDE_PROLOGUE.H b/include/crypto/__DECC_INCLUDE_PROLOGUE.H
index 9a9c777f93f8..a01395755713 100644
--- a/include/crypto/__DECC_INCLUDE_PROLOGUE.H
+++ b/include/crypto/__DECC_INCLUDE_PROLOGUE.H
@@ -1,7 +1,7 @@
/*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/include/crypto/aes_platform.h b/include/crypto/aes_platform.h
new file mode 100644
index 000000000000..e95ad5aa5de6
--- /dev/null
+++ b/include/crypto/aes_platform.h
@@ -0,0 +1,450 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_AES_PLATFORM_H
+# define OSSL_AES_PLATFORM_H
+# pragma once
+
+# include <openssl/aes.h>
+
+# ifdef VPAES_ASM
+int vpaes_set_encrypt_key(const unsigned char *userKey, int bits,
+ AES_KEY *key);
+int vpaes_set_decrypt_key(const unsigned char *userKey, int bits,
+ AES_KEY *key);
+void vpaes_encrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key);
+void vpaes_decrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key);
+void vpaes_cbc_encrypt(const unsigned char *in,
+ unsigned char *out,
+ size_t length,
+ const AES_KEY *key, unsigned char *ivec, int enc);
+# endif /* VPAES_ASM */
+
+# ifdef BSAES_ASM
+void ossl_bsaes_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ size_t length, const AES_KEY *key,
+ unsigned char ivec[16], int enc);
+void ossl_bsaes_ctr32_encrypt_blocks(const unsigned char *in,
+ unsigned char *out, size_t len,
+ const AES_KEY *key,
+ const unsigned char ivec[16]);
+void ossl_bsaes_xts_encrypt(const unsigned char *inp, unsigned char *out,
+ size_t len, const AES_KEY *key1,
+ const AES_KEY *key2, const unsigned char iv[16]);
+void ossl_bsaes_xts_decrypt(const unsigned char *inp, unsigned char *out,
+ size_t len, const AES_KEY *key1,
+ const AES_KEY *key2, const unsigned char iv[16]);
+# endif /* BSAES_ASM */
+
+# ifdef AES_CTR_ASM
+void AES_ctr32_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const AES_KEY *key,
+ const unsigned char ivec[AES_BLOCK_SIZE]);
+# endif /* AES_CTR_ASM */
+
+# ifdef AES_XTS_ASM
+void AES_xts_encrypt(const unsigned char *inp, unsigned char *out, size_t len,
+ const AES_KEY *key1, const AES_KEY *key2,
+ const unsigned char iv[16]);
+void AES_xts_decrypt(const unsigned char *inp, unsigned char *out, size_t len,
+ const AES_KEY *key1, const AES_KEY *key2,
+ const unsigned char iv[16]);
+# endif /* AES_XTS_ASM */
+
+# if defined(OPENSSL_CPUID_OBJ)
+# if (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC))
+# include "crypto/ppc_arch.h"
+# ifdef VPAES_ASM
+# define VPAES_CAPABLE (OPENSSL_ppccap_P & PPC_ALTIVEC)
+# endif
+# define HWAES_CAPABLE (OPENSSL_ppccap_P & PPC_CRYPTO207)
+# define HWAES_set_encrypt_key aes_p8_set_encrypt_key
+# define HWAES_set_decrypt_key aes_p8_set_decrypt_key
+# define HWAES_encrypt aes_p8_encrypt
+# define HWAES_decrypt aes_p8_decrypt
+# define HWAES_cbc_encrypt aes_p8_cbc_encrypt
+# define HWAES_ctr32_encrypt_blocks aes_p8_ctr32_encrypt_blocks
+# define HWAES_xts_encrypt aes_p8_xts_encrypt
+# define HWAES_xts_decrypt aes_p8_xts_decrypt
+# endif /* PPC */
+
+# if (defined(__arm__) || defined(__arm) || defined(__aarch64__))
+# include "arm_arch.h"
+# if __ARM_MAX_ARCH__>=7
+# if defined(BSAES_ASM)
+# define BSAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
+# endif
+# if defined(VPAES_ASM)
+# define VPAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
+# endif
+# define HWAES_CAPABLE (OPENSSL_armcap_P & ARMV8_AES)
+# define HWAES_set_encrypt_key aes_v8_set_encrypt_key
+# define HWAES_set_decrypt_key aes_v8_set_decrypt_key
+# define HWAES_encrypt aes_v8_encrypt
+# define HWAES_decrypt aes_v8_decrypt
+# define HWAES_cbc_encrypt aes_v8_cbc_encrypt
+# define HWAES_ecb_encrypt aes_v8_ecb_encrypt
+# if __ARM_MAX_ARCH__>=8 && defined(__aarch64__)
+# define HWAES_xts_encrypt aes_v8_xts_encrypt
+# define HWAES_xts_decrypt aes_v8_xts_decrypt
+# endif
+# define HWAES_ctr32_encrypt_blocks aes_v8_ctr32_encrypt_blocks
+# define AES_PMULL_CAPABLE ((OPENSSL_armcap_P & ARMV8_PMULL) && (OPENSSL_armcap_P & ARMV8_AES))
+# define AES_GCM_ENC_BYTES 512
+# define AES_GCM_DEC_BYTES 512
+# if __ARM_MAX_ARCH__>=8 && defined(__aarch64__)
+# define AES_gcm_encrypt armv8_aes_gcm_encrypt
+# define AES_gcm_decrypt armv8_aes_gcm_decrypt
+# define AES_GCM_ASM(gctx) ((gctx)->ctr==aes_v8_ctr32_encrypt_blocks && \
+ (gctx)->gcm.ghash==gcm_ghash_v8)
+size_t aes_gcm_enc_128_kernel(const uint8_t * plaintext, uint64_t plaintext_length, uint8_t * ciphertext,
+ uint64_t *Xi, unsigned char ivec[16], const void *key);
+size_t aes_gcm_enc_192_kernel(const uint8_t * plaintext, uint64_t plaintext_length, uint8_t * ciphertext,
+ uint64_t *Xi, unsigned char ivec[16], const void *key);
+size_t aes_gcm_enc_256_kernel(const uint8_t * plaintext, uint64_t plaintext_length, uint8_t * ciphertext,
+ uint64_t *Xi, unsigned char ivec[16], const void *key);
+size_t aes_gcm_dec_128_kernel(const uint8_t * ciphertext, uint64_t plaintext_length, uint8_t * plaintext,
+ uint64_t *Xi, unsigned char ivec[16], const void *key);
+size_t aes_gcm_dec_192_kernel(const uint8_t * ciphertext, uint64_t plaintext_length, uint8_t * plaintext,
+ uint64_t *Xi, unsigned char ivec[16], const void *key);
+size_t aes_gcm_dec_256_kernel(const uint8_t * ciphertext, uint64_t plaintext_length, uint8_t * plaintext,
+ uint64_t *Xi, unsigned char ivec[16], const void *key);
+size_t armv8_aes_gcm_encrypt(const unsigned char *in, unsigned char *out, size_t len, const void *key,
+ unsigned char ivec[16], u64 *Xi);
+size_t armv8_aes_gcm_decrypt(const unsigned char *in, unsigned char *out, size_t len, const void *key,
+ unsigned char ivec[16], u64 *Xi);
+void gcm_ghash_v8(u64 Xi[2],const u128 Htable[16],const u8 *inp, size_t len);
+# endif
+# endif
+# endif
+# endif /* OPENSSL_CPUID_OBJ */
+
+# if defined(AES_ASM) && ( \
+ defined(__x86_64) || defined(__x86_64__) || \
+ defined(_M_AMD64) || defined(_M_X64) )
+# define AES_CBC_HMAC_SHA_CAPABLE 1
+# define AESNI_CBC_HMAC_SHA_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32)))
+# endif
+
+# if defined(AES_ASM) && !defined(I386_ONLY) && ( \
+ ((defined(__i386) || defined(__i386__) || \
+ defined(_M_IX86)) && defined(OPENSSL_IA32_SSE2))|| \
+ defined(__x86_64) || defined(__x86_64__) || \
+ defined(_M_AMD64) || defined(_M_X64) )
+
+/* AES-NI section */
+
+# define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32)))
+# ifdef VPAES_ASM
+# define VPAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
+# endif
+# ifdef BSAES_ASM
+# define BSAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
+# endif
+
+# define AES_GCM_ENC_BYTES 32
+# define AES_GCM_DEC_BYTES 16
+
+int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
+ AES_KEY *key);
+int aesni_set_decrypt_key(const unsigned char *userKey, int bits,
+ AES_KEY *key);
+
+void aesni_encrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key);
+void aesni_decrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key);
+
+void aesni_ecb_encrypt(const unsigned char *in,
+ unsigned char *out,
+ size_t length, const AES_KEY *key, int enc);
+void aesni_cbc_encrypt(const unsigned char *in,
+ unsigned char *out,
+ size_t length,
+ const AES_KEY *key, unsigned char *ivec, int enc);
+# ifndef OPENSSL_NO_OCB
+void aesni_ocb_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const void *key,
+ size_t start_block_num,
+ unsigned char offset_i[16],
+ const unsigned char L_[][16],
+ unsigned char checksum[16]);
+void aesni_ocb_decrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const void *key,
+ size_t start_block_num,
+ unsigned char offset_i[16],
+ const unsigned char L_[][16],
+ unsigned char checksum[16]);
+# endif /* OPENSSL_NO_OCB */
+
+void aesni_ctr32_encrypt_blocks(const unsigned char *in,
+ unsigned char *out,
+ size_t blocks,
+ const void *key, const unsigned char *ivec);
+
+void aesni_xts_encrypt(const unsigned char *in,
+ unsigned char *out,
+ size_t length,
+ const AES_KEY *key1, const AES_KEY *key2,
+ const unsigned char iv[16]);
+
+void aesni_xts_decrypt(const unsigned char *in,
+ unsigned char *out,
+ size_t length,
+ const AES_KEY *key1, const AES_KEY *key2,
+ const unsigned char iv[16]);
+
+void aesni_ccm64_encrypt_blocks(const unsigned char *in,
+ unsigned char *out,
+ size_t blocks,
+ const void *key,
+ const unsigned char ivec[16],
+ unsigned char cmac[16]);
+
+void aesni_ccm64_decrypt_blocks(const unsigned char *in,
+ unsigned char *out,
+ size_t blocks,
+ const void *key,
+ const unsigned char ivec[16],
+ unsigned char cmac[16]);
+
+# if defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
+size_t aesni_gcm_encrypt(const unsigned char *in, unsigned char *out, size_t len,
+ const void *key, unsigned char ivec[16], u64 *Xi);
+size_t aesni_gcm_decrypt(const unsigned char *in, unsigned char *out, size_t len,
+ const void *key, unsigned char ivec[16], u64 *Xi);
+void gcm_ghash_avx(u64 Xi[2], const u128 Htable[16], const u8 *in, size_t len);
+
+# define AES_gcm_encrypt aesni_gcm_encrypt
+# define AES_gcm_decrypt aesni_gcm_decrypt
+# define AES_GCM_ASM(ctx) (ctx->ctr == aesni_ctr32_encrypt_blocks && \
+ ctx->gcm.ghash == gcm_ghash_avx)
+# endif
+
+
+# elif defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
+
+/* Fujitsu SPARC64 X support */
+# include "crypto/sparc_arch.h"
+
+# define SPARC_AES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_AES)
+# define HWAES_CAPABLE (OPENSSL_sparcv9cap_P[0] & SPARCV9_FJAESX)
+# define HWAES_set_encrypt_key aes_fx_set_encrypt_key
+# define HWAES_set_decrypt_key aes_fx_set_decrypt_key
+# define HWAES_encrypt aes_fx_encrypt
+# define HWAES_decrypt aes_fx_decrypt
+# define HWAES_cbc_encrypt aes_fx_cbc_encrypt
+# define HWAES_ctr32_encrypt_blocks aes_fx_ctr32_encrypt_blocks
+
+void aes_t4_set_encrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
+void aes_t4_set_decrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
+void aes_t4_encrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key);
+void aes_t4_decrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key);
+/*
+ * Key-length specific subroutines were chosen for following reason.
+ * Each SPARC T4 core can execute up to 8 threads which share core's
+ * resources. Loading as much key material to registers allows to
+ * minimize references to shared memory interface, as well as amount
+ * of instructions in inner loops [much needed on T4]. But then having
+ * non-key-length specific routines would require conditional branches
+ * either in inner loops or on subroutines' entries. Former is hardly
+ * acceptable, while latter means code size increase to size occupied
+ * by multiple key-length specific subroutines, so why fight?
+ */
+void aes128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const AES_KEY *key,
+ unsigned char *ivec, int /*unused*/);
+void aes128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const AES_KEY *key,
+ unsigned char *ivec, int /*unused*/);
+void aes192_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const AES_KEY *key,
+ unsigned char *ivec, int /*unused*/);
+void aes192_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const AES_KEY *key,
+ unsigned char *ivec, int /*unused*/);
+void aes256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const AES_KEY *key,
+ unsigned char *ivec, int /*unused*/);
+void aes256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const AES_KEY *key,
+ unsigned char *ivec, int /*unused*/);
+void aes128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const AES_KEY *key,
+ unsigned char *ivec);
+void aes192_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const AES_KEY *key,
+ unsigned char *ivec);
+void aes256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const AES_KEY *key,
+ unsigned char *ivec);
+void aes128_t4_xts_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const AES_KEY *key1,
+ const AES_KEY *key2, const unsigned char *ivec);
+void aes128_t4_xts_decrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const AES_KEY *key1,
+ const AES_KEY *key2, const unsigned char *ivec);
+void aes256_t4_xts_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const AES_KEY *key1,
+ const AES_KEY *key2, const unsigned char *ivec);
+void aes256_t4_xts_decrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const AES_KEY *key1,
+ const AES_KEY *key2, const unsigned char *ivec);
+
+# elif defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
+/* IBM S390X support */
+# include "s390x_arch.h"
+
+
+/* Convert key size to function code: [16,24,32] -> [18,19,20]. */
+# define S390X_AES_FC(keylen) (S390X_AES_128 + ((((keylen) << 3) - 128) >> 6))
+
+/* Most modes of operation need km for partial block processing. */
+# define S390X_aes_128_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
+ S390X_CAPBIT(S390X_AES_128))
+# define S390X_aes_192_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
+ S390X_CAPBIT(S390X_AES_192))
+# define S390X_aes_256_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
+ S390X_CAPBIT(S390X_AES_256))
+
+# define S390X_aes_128_cbc_CAPABLE 1 /* checked by callee */
+# define S390X_aes_192_cbc_CAPABLE 1
+# define S390X_aes_256_cbc_CAPABLE 1
+
+# define S390X_aes_128_ecb_CAPABLE S390X_aes_128_CAPABLE
+# define S390X_aes_192_ecb_CAPABLE S390X_aes_192_CAPABLE
+# define S390X_aes_256_ecb_CAPABLE S390X_aes_256_CAPABLE
+
+# define S390X_aes_128_ofb_CAPABLE (S390X_aes_128_CAPABLE && \
+ (OPENSSL_s390xcap_P.kmo[0] & \
+ S390X_CAPBIT(S390X_AES_128)))
+# define S390X_aes_192_ofb_CAPABLE (S390X_aes_192_CAPABLE && \
+ (OPENSSL_s390xcap_P.kmo[0] & \
+ S390X_CAPBIT(S390X_AES_192)))
+# define S390X_aes_256_ofb_CAPABLE (S390X_aes_256_CAPABLE && \
+ (OPENSSL_s390xcap_P.kmo[0] & \
+ S390X_CAPBIT(S390X_AES_256)))
+
+# define S390X_aes_128_cfb_CAPABLE (S390X_aes_128_CAPABLE && \
+ (OPENSSL_s390xcap_P.kmf[0] & \
+ S390X_CAPBIT(S390X_AES_128)))
+# define S390X_aes_192_cfb_CAPABLE (S390X_aes_192_CAPABLE && \
+ (OPENSSL_s390xcap_P.kmf[0] & \
+ S390X_CAPBIT(S390X_AES_192)))
+# define S390X_aes_256_cfb_CAPABLE (S390X_aes_256_CAPABLE && \
+ (OPENSSL_s390xcap_P.kmf[0] & \
+ S390X_CAPBIT(S390X_AES_256)))
+# define S390X_aes_128_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
+ S390X_CAPBIT(S390X_AES_128))
+# define S390X_aes_192_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
+ S390X_CAPBIT(S390X_AES_192))
+# define S390X_aes_256_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
+ S390X_CAPBIT(S390X_AES_256))
+# define S390X_aes_128_cfb1_CAPABLE 0
+# define S390X_aes_192_cfb1_CAPABLE 0
+# define S390X_aes_256_cfb1_CAPABLE 0
+
+# define S390X_aes_128_ctr_CAPABLE 1 /* checked by callee */
+# define S390X_aes_192_ctr_CAPABLE 1
+# define S390X_aes_256_ctr_CAPABLE 1
+
+# define S390X_aes_128_xts_CAPABLE 1 /* checked by callee */
+# define S390X_aes_256_xts_CAPABLE 1
+
+# define S390X_aes_128_gcm_CAPABLE (S390X_aes_128_CAPABLE && \
+ (OPENSSL_s390xcap_P.kma[0] & \
+ S390X_CAPBIT(S390X_AES_128)))
+# define S390X_aes_192_gcm_CAPABLE (S390X_aes_192_CAPABLE && \
+ (OPENSSL_s390xcap_P.kma[0] & \
+ S390X_CAPBIT(S390X_AES_192)))
+# define S390X_aes_256_gcm_CAPABLE (S390X_aes_256_CAPABLE && \
+ (OPENSSL_s390xcap_P.kma[0] & \
+ S390X_CAPBIT(S390X_AES_256)))
+
+# define S390X_aes_128_ccm_CAPABLE (S390X_aes_128_CAPABLE && \
+ (OPENSSL_s390xcap_P.kmac[0] & \
+ S390X_CAPBIT(S390X_AES_128)))
+# define S390X_aes_192_ccm_CAPABLE (S390X_aes_192_CAPABLE && \
+ (OPENSSL_s390xcap_P.kmac[0] & \
+ S390X_CAPBIT(S390X_AES_192)))
+# define S390X_aes_256_ccm_CAPABLE (S390X_aes_256_CAPABLE && \
+ (OPENSSL_s390xcap_P.kmac[0] & \
+ S390X_CAPBIT(S390X_AES_256)))
+# define S390X_CCM_AAD_FLAG 0x40
+
+# ifndef OPENSSL_NO_OCB
+# define S390X_aes_128_ocb_CAPABLE 0
+# define S390X_aes_192_ocb_CAPABLE 0
+# define S390X_aes_256_ocb_CAPABLE 0
+# endif /* OPENSSL_NO_OCB */
+
+# ifndef OPENSSL_NO_SIV
+# define S390X_aes_128_siv_CAPABLE 0
+# define S390X_aes_192_siv_CAPABLE 0
+# define S390X_aes_256_siv_CAPABLE 0
+# endif /* OPENSSL_NO_SIV */
+
+/* Convert key size to function code: [16,24,32] -> [18,19,20]. */
+# define S390X_AES_FC(keylen) (S390X_AES_128 + ((((keylen) << 3) - 128) >> 6))
+# endif
+
+# if defined(HWAES_CAPABLE)
+int HWAES_set_encrypt_key(const unsigned char *userKey, const int bits,
+ AES_KEY *key);
+int HWAES_set_decrypt_key(const unsigned char *userKey, const int bits,
+ AES_KEY *key);
+void HWAES_encrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key);
+void HWAES_decrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key);
+void HWAES_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ size_t length, const AES_KEY *key,
+ unsigned char *ivec, const int enc);
+void HWAES_ecb_encrypt(const unsigned char *in, unsigned char *out,
+ size_t length, const AES_KEY *key,
+ const int enc);
+void HWAES_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
+ size_t len, const void *key,
+ const unsigned char ivec[16]);
+void HWAES_xts_encrypt(const unsigned char *inp, unsigned char *out,
+ size_t len, const AES_KEY *key1,
+ const AES_KEY *key2, const unsigned char iv[16]);
+void HWAES_xts_decrypt(const unsigned char *inp, unsigned char *out,
+ size_t len, const AES_KEY *key1,
+ const AES_KEY *key2, const unsigned char iv[16]);
+# ifndef OPENSSL_NO_OCB
+# ifdef HWAES_ocb_encrypt
+void HWAES_ocb_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const void *key,
+ size_t start_block_num,
+ unsigned char offset_i[16],
+ const unsigned char L_[][16],
+ unsigned char checksum[16]);
+# else
+# define HWAES_ocb_encrypt ((ocb128_f)NULL)
+# endif
+# ifdef HWAES_ocb_decrypt
+void HWAES_ocb_decrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const void *key,
+ size_t start_block_num,
+ unsigned char offset_i[16],
+ const unsigned char L_[][16],
+ unsigned char checksum[16]);
+# else
+# define HWAES_ocb_decrypt ((ocb128_f)NULL)
+# endif
+# endif /* OPENSSL_NO_OCB */
+
+# endif /* HWAES_CAPABLE */
+
+#endif /* OSSL_AES_PLATFORM_H */
diff --git a/include/crypto/aria.h b/include/crypto/aria.h
index 03a62950ae41..21a9932e847c 100644
--- a/include/crypto/aria.h
+++ b/include/crypto/aria.h
@@ -1,8 +1,8 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,6 +12,7 @@
#ifndef OSSL_CRYPTO_ARIA_H
# define OSSL_CRYPTO_ARIA_H
+# pragma once
# include <openssl/opensslconf.h>
@@ -39,12 +40,12 @@ struct aria_key_st {
typedef struct aria_key_st ARIA_KEY;
-int aria_set_encrypt_key(const unsigned char *userKey, const int bits,
- ARIA_KEY *key);
-int aria_set_decrypt_key(const unsigned char *userKey, const int bits,
- ARIA_KEY *key);
+int ossl_aria_set_encrypt_key(const unsigned char *userKey, const int bits,
+ ARIA_KEY *key);
+int ossl_aria_set_decrypt_key(const unsigned char *userKey, const int bits,
+ ARIA_KEY *key);
-void aria_encrypt(const unsigned char *in, unsigned char *out,
- const ARIA_KEY *key);
+void ossl_aria_encrypt(const unsigned char *in, unsigned char *out,
+ const ARIA_KEY *key);
#endif
diff --git a/include/crypto/asn1.h b/include/crypto/asn1.h
index 9c9b4d897456..ec76ae6fc6d8 100644
--- a/include/crypto/asn1.h
+++ b/include/crypto/asn1.h
@@ -1,23 +1,32 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#ifndef OSSL_CRYPTO_ASN1_H
+# define OSSL_CRYPTO_ASN1_H
+# pragma once
+
+# include <openssl/asn1.h>
+# include <openssl/core_dispatch.h> /* OSSL_FUNC_keymgmt_import() */
+
/* Internal ASN1 structures and functions: not for application use */
/* ASN1 public key method structure */
+#include <openssl/core.h>
+
struct evp_pkey_asn1_method_st {
int pkey_id;
int pkey_base_id;
unsigned long pkey_flags;
char *pem_str;
char *info;
- int (*pub_decode) (EVP_PKEY *pk, X509_PUBKEY *pub);
+ int (*pub_decode) (EVP_PKEY *pk, const X509_PUBKEY *pub);
int (*pub_encode) (X509_PUBKEY *pub, const EVP_PKEY *pk);
int (*pub_cmp) (const EVP_PKEY *a, const EVP_PKEY *b);
int (*pub_print) (BIO *out, const EVP_PKEY *pkey, int indent,
@@ -47,9 +56,10 @@ struct evp_pkey_asn1_method_st {
const unsigned char **pder, int derlen);
int (*old_priv_encode) (const EVP_PKEY *pkey, unsigned char **pder);
/* Custom ASN1 signature verification */
- int (*item_verify) (EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
- X509_ALGOR *a, ASN1_BIT_STRING *sig, EVP_PKEY *pkey);
- int (*item_sign) (EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
+ int (*item_verify) (EVP_MD_CTX *ctx, const ASN1_ITEM *it, const void *data,
+ const X509_ALGOR *a, const ASN1_BIT_STRING *sig,
+ EVP_PKEY *pkey);
+ int (*item_sign) (EVP_MD_CTX *ctx, const ASN1_ITEM *it, const void *data,
X509_ALGOR *alg1, X509_ALGOR *alg2,
ASN1_BIT_STRING *sig);
int (*siginf_set) (X509_SIG_INFO *siginf, const X509_ALGOR *alg,
@@ -63,26 +73,35 @@ struct evp_pkey_asn1_method_st {
int (*set_pub_key) (EVP_PKEY *pk, const unsigned char *pub, size_t len);
int (*get_priv_key) (const EVP_PKEY *pk, unsigned char *priv, size_t *len);
int (*get_pub_key) (const EVP_PKEY *pk, unsigned char *pub, size_t *len);
+
+ /* Exports and imports to / from providers */
+ size_t (*dirty_cnt) (const EVP_PKEY *pk);
+ int (*export_to) (const EVP_PKEY *pk, void *to_keydata,
+ OSSL_FUNC_keymgmt_import_fn *importer,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ OSSL_CALLBACK *import_from;
+ int (*copy) (EVP_PKEY *to, EVP_PKEY *from);
+
+ int (*priv_decode_ex) (EVP_PKEY *pk,
+ const PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *libctx,
+ const char *propq);
} /* EVP_PKEY_ASN1_METHOD */ ;
DEFINE_STACK_OF_CONST(EVP_PKEY_ASN1_METHOD)
-extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth;
-extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth;
-extern const EVP_PKEY_ASN1_METHOD dhx_asn1_meth;
-extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[5];
-extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
-extern const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth;
-extern const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth;
-extern const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth;
-extern const EVP_PKEY_ASN1_METHOD ed448_asn1_meth;
-extern const EVP_PKEY_ASN1_METHOD sm2_asn1_meth;
-extern const EVP_PKEY_ASN1_METHOD poly1305_asn1_meth;
-
-extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
-extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2];
-extern const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth;
-extern const EVP_PKEY_ASN1_METHOD siphash_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_dh_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_dhx_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_dsa_asn1_meths[5];
+extern const EVP_PKEY_ASN1_METHOD ossl_eckey_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_ecx25519_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_ecx448_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_sm2_asn1_meth;
+
+extern const EVP_PKEY_ASN1_METHOD ossl_rsa_asn1_meths[2];
+extern const EVP_PKEY_ASN1_METHOD ossl_rsa_pss_asn1_meth;
/*
* These are used internally in the ASN1_OBJECT to keep track of whether the
@@ -110,4 +129,21 @@ struct asn1_pctx_st {
unsigned long str_flags;
} /* ASN1_PCTX */ ;
-int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
+/* ASN1 type functions */
+
+int ossl_asn1_type_set_octetstring_int(ASN1_TYPE *a, long num,
+ unsigned char *data, int len);
+int ossl_asn1_type_get_octetstring_int(const ASN1_TYPE *a, long *num,
+ unsigned char *data, int max_len);
+
+int ossl_x509_algor_new_from_md(X509_ALGOR **palg, const EVP_MD *md);
+const EVP_MD *ossl_x509_algor_get_md(X509_ALGOR *alg);
+X509_ALGOR *ossl_x509_algor_mgf1_decode(X509_ALGOR *alg);
+int ossl_x509_algor_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md);
+int ossl_asn1_time_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags);
+
+EVP_PKEY * ossl_d2i_PrivateKey_legacy(int keytype, EVP_PKEY **a,
+ const unsigned char **pp, long length,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+#endif /* ndef OSSL_CRYPTO_ASN1_H */
diff --git a/include/crypto/asn1_dsa.h b/include/crypto/asn1_dsa.h
new file mode 100644
index 000000000000..3eadb9ec3c54
--- /dev/null
+++ b/include/crypto/asn1_dsa.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_ASN1_DSA_H
+# define OSSL_CRYPTO_ASN1_DSA_H
+# pragma once
+
+#include "internal/packet.h"
+
+int ossl_encode_der_length(WPACKET *pkt, size_t cont_len);
+int ossl_encode_der_integer(WPACKET *pkt, const BIGNUM *n);
+int ossl_encode_der_dsa_sig(WPACKET *pkt, const BIGNUM *r, const BIGNUM *s);
+int ossl_decode_der_length(PACKET *pkt, PACKET *subpkt);
+int ossl_decode_der_integer(PACKET *pkt, BIGNUM *n);
+size_t ossl_decode_der_dsa_sig(BIGNUM *r, BIGNUM *s, const unsigned char **ppin,
+ size_t len);
+
+#endif
diff --git a/include/crypto/asn1err.h b/include/crypto/asn1err.h
new file mode 100644
index 000000000000..6441386bbc4a
--- /dev/null
+++ b/include/crypto/asn1err.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_ASN1ERR_H
+# define OSSL_CRYPTO_ASN1ERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_ASN1_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/async.h b/include/crypto/async.h
index dc8e937b0ced..7bc0dbb65b79 100644
--- a/include/crypto/async.h
+++ b/include/crypto/async.h
@@ -1,15 +1,19 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/async.h>
+#ifndef OSSL_CRYPTO_ASYNC_H
+# define OSSL_CRYPTO_ASYNC_H
+# pragma once
+
+# include <openssl/async.h>
int async_init(void);
void async_deinit(void);
-void async_delete_thread_state(void);
+#endif
diff --git a/include/crypto/asyncerr.h b/include/crypto/asyncerr.h
new file mode 100644
index 000000000000..574e0af733ba
--- /dev/null
+++ b/include/crypto/asyncerr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_ASYNCERR_H
+# define OSSL_CRYPTO_ASYNCERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_ASYNC_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/bioerr.h b/include/crypto/bioerr.h
new file mode 100644
index 000000000000..a0c06099f79b
--- /dev/null
+++ b/include/crypto/bioerr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_BIOERR_H
+# define OSSL_CRYPTO_BIOERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_BIO_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/bn.h b/include/crypto/bn.h
index 9f866ed71abf..390e5ac07c2b 100644
--- a/include/crypto/bn.h
+++ b/include/crypto/bn.h
@@ -1,7 +1,7 @@
/*
* Copyright 2014-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,6 +9,7 @@
#ifndef OSSL_CRYPTO_BN_H
# define OSSL_CRYPTO_BN_H
+# pragma once
# include <openssl/bn.h>
# include <limits.h>
@@ -86,6 +87,33 @@ int bn_lshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n);
int bn_rshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n);
int bn_div_fixed_top(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
const BIGNUM *d, BN_CTX *ctx);
+
+#define BN_PRIMETEST_COMPOSITE 0
+#define BN_PRIMETEST_COMPOSITE_WITH_FACTOR 1
+#define BN_PRIMETEST_COMPOSITE_NOT_POWER_OF_PRIME 2
+#define BN_PRIMETEST_PROBABLY_PRIME 3
+
+int ossl_bn_miller_rabin_is_prime(const BIGNUM *w, int iterations, BN_CTX *ctx,
+ BN_GENCB *cb, int enhanced, int *status);
+
+const BIGNUM *ossl_bn_get0_small_factors(void);
+
+int ossl_bn_rsa_fips186_4_gen_prob_primes(BIGNUM *p, BIGNUM *Xpout,
+ BIGNUM *p1, BIGNUM *p2,
+ const BIGNUM *Xp, const BIGNUM *Xp1,
+ const BIGNUM *Xp2, int nlen,
+ const BIGNUM *e, BN_CTX *ctx,
+ BN_GENCB *cb);
+
+int ossl_bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin,
+ const BIGNUM *r1, const BIGNUM *r2,
+ int nlen, const BIGNUM *e, BN_CTX *ctx,
+ BN_GENCB *cb);
+
+OSSL_LIB_CTX *ossl_bn_get_libctx(BN_CTX *ctx);
+
+extern const BIGNUM ossl_bn_inv_sqrt_2;
+
int ossl_bn_rsa_do_unblind(const BIGNUM *intermediate,
const BN_BLINDING *blinding,
const BIGNUM *possible_arg2,
diff --git a/include/crypto/bn_conf.h.in b/include/crypto/bn_conf.h.in
index b6b9eb743fd3..dbc901b145ea 100644
--- a/include/crypto/bn_conf.h.in
+++ b/include/crypto/bn_conf.h.in
@@ -1,8 +1,8 @@
{- join("\n",map { "/* $_ */" } @autowarntext) -}
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,6 +10,7 @@
#ifndef OSSL_CRYPTO_BN_CONF_H
# define OSSL_CRYPTO_BN_CONF_H
+# pragma once
/*
* The contents of this file are not used in the UEFI build, as
diff --git a/include/crypto/bn_dh.h b/include/crypto/bn_dh.h
index 70ebca28753c..6d12c20e0212 100644
--- a/include/crypto/bn_dh.h
+++ b/include/crypto/bn_dh.h
@@ -1,24 +1,43 @@
/*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#define declare_dh_bn(x) \
- extern const BIGNUM _bignum_dh##x##_p; \
- extern const BIGNUM _bignum_dh##x##_g; \
- extern const BIGNUM _bignum_dh##x##_q;
+ extern const BIGNUM ossl_bignum_dh##x##_p; \
+ extern const BIGNUM ossl_bignum_dh##x##_q; \
+ extern const BIGNUM ossl_bignum_dh##x##_g; \
declare_dh_bn(1024_160)
declare_dh_bn(2048_224)
declare_dh_bn(2048_256)
-extern const BIGNUM _bignum_ffdhe2048_p;
-extern const BIGNUM _bignum_ffdhe3072_p;
-extern const BIGNUM _bignum_ffdhe4096_p;
-extern const BIGNUM _bignum_ffdhe6144_p;
-extern const BIGNUM _bignum_ffdhe8192_p;
-extern const BIGNUM _bignum_const_2;
+extern const BIGNUM ossl_bignum_const_2;
+
+extern const BIGNUM ossl_bignum_ffdhe2048_p;
+extern const BIGNUM ossl_bignum_ffdhe3072_p;
+extern const BIGNUM ossl_bignum_ffdhe4096_p;
+extern const BIGNUM ossl_bignum_ffdhe6144_p;
+extern const BIGNUM ossl_bignum_ffdhe8192_p;
+extern const BIGNUM ossl_bignum_ffdhe2048_q;
+extern const BIGNUM ossl_bignum_ffdhe3072_q;
+extern const BIGNUM ossl_bignum_ffdhe4096_q;
+extern const BIGNUM ossl_bignum_ffdhe6144_q;
+extern const BIGNUM ossl_bignum_ffdhe8192_q;
+
+extern const BIGNUM ossl_bignum_modp_1536_p;
+extern const BIGNUM ossl_bignum_modp_2048_p;
+extern const BIGNUM ossl_bignum_modp_3072_p;
+extern const BIGNUM ossl_bignum_modp_4096_p;
+extern const BIGNUM ossl_bignum_modp_6144_p;
+extern const BIGNUM ossl_bignum_modp_8192_p;
+extern const BIGNUM ossl_bignum_modp_1536_q;
+extern const BIGNUM ossl_bignum_modp_2048_q;
+extern const BIGNUM ossl_bignum_modp_3072_q;
+extern const BIGNUM ossl_bignum_modp_4096_q;
+extern const BIGNUM ossl_bignum_modp_6144_q;
+extern const BIGNUM ossl_bignum_modp_8192_q;
diff --git a/include/crypto/bn_srp.h b/include/crypto/bn_srp.h
index d4b282a6bbbe..00b160aad120 100644
--- a/include/crypto/bn_srp.h
+++ b/include/crypto/bn_srp.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,24 +9,24 @@
#ifndef OPENSSL_NO_SRP
-extern const BIGNUM bn_group_1024;
+extern const BIGNUM ossl_bn_group_1024;
-extern const BIGNUM bn_group_1536;
+extern const BIGNUM ossl_bn_group_1536;
-extern const BIGNUM bn_group_2048;
+extern const BIGNUM ossl_bn_group_2048;
-extern const BIGNUM bn_group_3072;
+extern const BIGNUM ossl_bn_group_3072;
-extern const BIGNUM bn_group_4096;
+extern const BIGNUM ossl_bn_group_4096;
-extern const BIGNUM bn_group_6144;
+extern const BIGNUM ossl_bn_group_6144;
-extern const BIGNUM bn_group_8192;
+extern const BIGNUM ossl_bn_group_8192;
-extern const BIGNUM bn_generator_19;
+extern const BIGNUM ossl_bn_generator_19;
-extern const BIGNUM bn_generator_5;
+extern const BIGNUM ossl_bn_generator_5;
-extern const BIGNUM bn_generator_2;
+extern const BIGNUM ossl_bn_generator_2;
#endif
diff --git a/include/crypto/bnerr.h b/include/crypto/bnerr.h
new file mode 100644
index 000000000000..131e30fa71df
--- /dev/null
+++ b/include/crypto/bnerr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_BNERR_H
+# define OSSL_CRYPTO_BNERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_BN_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/buffererr.h b/include/crypto/buffererr.h
new file mode 100644
index 000000000000..54976d95b5a8
--- /dev/null
+++ b/include/crypto/buffererr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_BUFFERERR_H
+# define OSSL_CRYPTO_BUFFERERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_BUF_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/chacha.h b/include/crypto/chacha.h
index 4029400a670c..d29998ffe49a 100644
--- a/include/crypto/chacha.h
+++ b/include/crypto/chacha.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,6 +9,7 @@
#ifndef OSSL_CRYPTO_CHACHA_H
#define OSSL_CRYPTO_CHACHA_H
+# pragma once
#include <stddef.h>
@@ -35,8 +36,8 @@ void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp,
((unsigned int)(p)[0]) | ((unsigned int)(p)[1]<<8) | \
((unsigned int)(p)[2]<<16) | ((unsigned int)(p)[3]<<24) )
-#define CHACHA_KEY_SIZE 32
-#define CHACHA_CTR_SIZE 16
-#define CHACHA_BLK_SIZE 64
+#define CHACHA_KEY_SIZE 32
+#define CHACHA_CTR_SIZE 16
+#define CHACHA_BLK_SIZE 64
#endif
diff --git a/include/crypto/cmll_platform.h b/include/crypto/cmll_platform.h
new file mode 100644
index 000000000000..8cadadf68aa0
--- /dev/null
+++ b/include/crypto/cmll_platform.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CMLL_PLATFORM_H
+# define OSSL_CMLL_PLATFORM_H
+# pragma once
+
+# if defined(CMLL_ASM) && (defined(__sparc) || defined(__sparc__))
+
+/* Fujitsu SPARC64 X support */
+# include "crypto/sparc_arch.h"
+
+# ifndef OPENSSL_NO_CAMELLIA
+# define SPARC_CMLL_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_CAMELLIA)
+# include <openssl/camellia.h>
+
+void cmll_t4_set_key(const unsigned char *key, int bits, CAMELLIA_KEY *ks);
+void cmll_t4_encrypt(const unsigned char *in, unsigned char *out,
+ const CAMELLIA_KEY *key);
+void cmll_t4_decrypt(const unsigned char *in, unsigned char *out,
+ const CAMELLIA_KEY *key);
+
+void cmll128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const CAMELLIA_KEY *key,
+ unsigned char *ivec, int /*unused*/);
+void cmll128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const CAMELLIA_KEY *key,
+ unsigned char *ivec, int /*unused*/);
+void cmll256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const CAMELLIA_KEY *key,
+ unsigned char *ivec, int /*unused*/);
+void cmll256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const CAMELLIA_KEY *key,
+ unsigned char *ivec, int /*unused*/);
+void cmll128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const CAMELLIA_KEY *key,
+ unsigned char *ivec);
+void cmll256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const CAMELLIA_KEY *key,
+ unsigned char *ivec);
+# endif /* OPENSSL_NO_CAMELLIA */
+
+# endif /* CMLL_ASM && sparc */
+
+#endif /* OSSL_CRYPTO_CIPHERMODE_PLATFORM_H */
diff --git a/include/crypto/cmperr.h b/include/crypto/cmperr.h
new file mode 100644
index 000000000000..ac61dd4875c2
--- /dev/null
+++ b/include/crypto/cmperr.h
@@ -0,0 +1,30 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_CMPERR_H
+# define OSSL_CRYPTO_CMPERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# ifndef OPENSSL_NO_CMP
+
+int ossl_err_load_CMP_strings(void);
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/cmserr.h b/include/crypto/cmserr.h
new file mode 100644
index 000000000000..1de2f9c7d51d
--- /dev/null
+++ b/include/crypto/cmserr.h
@@ -0,0 +1,30 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_CMSERR_H
+# define OSSL_CRYPTO_CMSERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# ifndef OPENSSL_NO_CMS
+
+int ossl_err_load_CMS_strings(void);
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/comperr.h b/include/crypto/comperr.h
new file mode 100644
index 000000000000..0fd9c6de711a
--- /dev/null
+++ b/include/crypto/comperr.h
@@ -0,0 +1,30 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_COMPERR_H
+# define OSSL_CRYPTO_COMPERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# ifndef OPENSSL_NO_COMP
+
+int ossl_err_load_COMP_strings(void);
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/conferr.h b/include/crypto/conferr.h
new file mode 100644
index 000000000000..cb367e4f32a0
--- /dev/null
+++ b/include/crypto/conferr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_CONFERR_H
+# define OSSL_CRYPTO_CONFERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_CONF_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/crmferr.h b/include/crypto/crmferr.h
new file mode 100644
index 000000000000..f1a27e04993b
--- /dev/null
+++ b/include/crypto/crmferr.h
@@ -0,0 +1,30 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_CRMFERR_H
+# define OSSL_CRYPTO_CRMFERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# ifndef OPENSSL_NO_CRMF
+
+int ossl_err_load_CRMF_strings(void);
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/cryptlib.h b/include/crypto/cryptlib.h
index 38b5dac9a364..39a956bfd362 100644
--- a/include/crypto/cryptlib.h
+++ b/include/crypto/cryptlib.h
@@ -1,35 +1,39 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include "internal/cryptlib.h"
+#ifndef OSSL_CRYPTO_CRYPTLIB_H
+# define OSSL_CRYPTO_CRYPTLIB_H
+# pragma once
-/* This file is not scanned by mkdef.pl, whereas cryptlib.h is */
+# include <openssl/core.h>
+# include "internal/cryptlib.h"
-struct thread_local_inits_st {
- int async;
- int err_state;
- int rand;
-};
+/* This file is not scanned by mkdef.pl, whereas cryptlib.h is */
-int ossl_init_thread_start(uint64_t opts);
+int ossl_init_thread_start(const void *index, void *arg,
+ OSSL_thread_stop_handler_fn handfn);
+int ossl_init_thread_deregister(void *index);
+int ossl_init_thread(void);
+void ossl_cleanup_thread(void);
+void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx);
/*
* OPENSSL_INIT flags. The primary list of these is in crypto.h. Flags below
* are those omitted from crypto.h because they are "reserved for internal
* use".
*/
-# define OPENSSL_INIT_ZLIB 0x00010000L
# define OPENSSL_INIT_BASE_ONLY 0x00040000L
-/* OPENSSL_INIT_THREAD flags */
-# define OPENSSL_INIT_THREAD_ASYNC 0x01
-# define OPENSSL_INIT_THREAD_ERR_STATE 0x02
-# define OPENSSL_INIT_THREAD_RAND 0x04
-
+void ossl_trace_cleanup(void);
void ossl_malloc_setup_failures(void);
+
+int ossl_crypto_alloc_ex_data_intern(int class_index, void *obj,
+ CRYPTO_EX_DATA *ad, int idx);
+
+#endif /* OSSL_CRYPTO_CRYPTLIB_H */
diff --git a/include/crypto/cryptoerr.h b/include/crypto/cryptoerr.h
new file mode 100644
index 000000000000..288b87ac8638
--- /dev/null
+++ b/include/crypto/cryptoerr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_CRYPTOERR_H
+# define OSSL_CRYPTO_CRYPTOERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_CRYPTO_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/cterr.h b/include/crypto/cterr.h
new file mode 100644
index 000000000000..760bc796be4d
--- /dev/null
+++ b/include/crypto/cterr.h
@@ -0,0 +1,30 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_CTERR_H
+# define OSSL_CRYPTO_CTERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# ifndef OPENSSL_NO_CT
+
+int ossl_err_load_CT_strings(void);
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/ctype.h b/include/crypto/ctype.h
index 81ef8f5cf7e1..22f6922183b5 100644
--- a/include/crypto/ctype.h
+++ b/include/crypto/ctype.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -20,6 +20,9 @@
*/
#ifndef OSSL_CRYPTO_CTYPE_H
# define OSSL_CRYPTO_CTYPE_H
+# pragma once
+
+# include <openssl/e_os2.h>
# define CTYPE_MASK_lower 0x1
# define CTYPE_MASK_upper 0x2
@@ -54,10 +57,15 @@ int ossl_fromascii(int c);
# define ossl_fromascii(c) (c)
# endif
int ossl_ctype_check(int c, unsigned int mask);
+
int ossl_tolower(int c);
int ossl_toupper(int c);
-int ascii_isdigit(const char inchar);
+int ossl_isdigit(int c);
+int ossl_islower(int c);
+int ossl_isupper(int c);
+
+int ossl_ascii_isdigit(int c);
# define ossl_isalnum(c) (ossl_ctype_check((c), CTYPE_MASK_alnum))
# define ossl_isalpha(c) (ossl_ctype_check((c), CTYPE_MASK_alpha))
@@ -68,15 +76,11 @@ int ascii_isdigit(const char inchar);
# endif
# define ossl_isblank(c) (ossl_ctype_check((c), CTYPE_MASK_blank))
# define ossl_iscntrl(c) (ossl_ctype_check((c), CTYPE_MASK_cntrl))
-# define ossl_isdigit(c) (ossl_ctype_check((c), CTYPE_MASK_digit))
# define ossl_isgraph(c) (ossl_ctype_check((c), CTYPE_MASK_graph))
-# define ossl_islower(c) (ossl_ctype_check((c), CTYPE_MASK_lower))
# define ossl_isprint(c) (ossl_ctype_check((c), CTYPE_MASK_print))
# define ossl_ispunct(c) (ossl_ctype_check((c), CTYPE_MASK_punct))
# define ossl_isspace(c) (ossl_ctype_check((c), CTYPE_MASK_space))
-# define ossl_isupper(c) (ossl_ctype_check((c), CTYPE_MASK_upper))
# define ossl_isxdigit(c) (ossl_ctype_check((c), CTYPE_MASK_xdigit))
# define ossl_isbase64(c) (ossl_ctype_check((c), CTYPE_MASK_base64))
# define ossl_isasn1print(c) (ossl_ctype_check((c), CTYPE_MASK_asn1print))
-
#endif
diff --git a/include/crypto/decoder.h b/include/crypto/decoder.h
new file mode 100644
index 000000000000..107a7b502ad0
--- /dev/null
+++ b/include/crypto/decoder.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_DECODER_H
+# define OSSL_CRYPTO_DECODER_H
+# pragma once
+
+# include <openssl/decoder.h>
+
+OSSL_DECODER *ossl_decoder_fetch_by_number(OSSL_LIB_CTX *libctx,
+ int id,
+ const char *properties);
+
+/*
+ * These are specially made for the 'file:' provider-native loader, which
+ * uses this to install a DER to anything decoder, which doesn't do much
+ * except read a DER blob and pass it on as a provider object abstraction
+ * (provider-object(7)).
+ */
+void *ossl_decoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef,
+ OSSL_PROVIDER *prov);
+
+OSSL_DECODER_INSTANCE *
+ossl_decoder_instance_new(OSSL_DECODER *decoder, void *decoderctx);
+void ossl_decoder_instance_free(OSSL_DECODER_INSTANCE *decoder_inst);
+int ossl_decoder_ctx_add_decoder_inst(OSSL_DECODER_CTX *ctx,
+ OSSL_DECODER_INSTANCE *di);
+
+int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
+ EVP_PKEY **pkey, const char *keytype,
+ OSSL_LIB_CTX *libctx,
+ const char *propquery);
+
+int ossl_decoder_get_number(const OSSL_DECODER *encoder);
+int ossl_decoder_store_cache_flush(OSSL_LIB_CTX *libctx);
+int ossl_decoder_store_remove_all_provided(const OSSL_PROVIDER *prov);
+
+#endif
diff --git a/include/crypto/decodererr.h b/include/crypto/decodererr.h
new file mode 100644
index 000000000000..d7badc43793c
--- /dev/null
+++ b/include/crypto/decodererr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_DECODERERR_H
+# define OSSL_CRYPTO_DECODERERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_OSSL_DECODER_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/des_platform.h b/include/crypto/des_platform.h
new file mode 100644
index 000000000000..07ea1ddd0acc
--- /dev/null
+++ b/include/crypto/des_platform.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_DES_PLATFORM_H
+# define OSSL_DES_PLATFORM_H
+# pragma once
+
+# if defined(DES_ASM) && (defined(__sparc) || defined(__sparc__))
+
+/* Fujitsu SPARC64 X support */
+# include "crypto/sparc_arch.h"
+
+# ifndef OPENSSL_NO_DES
+# define SPARC_DES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_DES)
+# include <openssl/des.h>
+void des_t4_key_expand(const void *key, DES_key_schedule *ks);
+void des_t4_ede3_cbc_encrypt(const void *inp, void *out, size_t len,
+ const DES_key_schedule ks[3], unsigned char iv[8]);
+void des_t4_ede3_cbc_decrypt(const void *inp, void *out, size_t len,
+ const DES_key_schedule ks[3], unsigned char iv[8]);
+void des_t4_cbc_encrypt(const void *inp, void *out, size_t len,
+ const DES_key_schedule *ks, unsigned char iv[8]);
+void des_t4_cbc_decrypt(const void *inp, void *out, size_t len,
+ const DES_key_schedule *ks, unsigned char iv[8]);
+# endif /* OPENSSL_NO_DES */
+
+# endif /* DES_ASM && sparc */
+
+#endif /* OSSL_CRYPTO_CIPHERMODE_PLATFORM_H */
diff --git a/include/crypto/dh.h b/include/crypto/dh.h
new file mode 100644
index 000000000000..51232d18c244
--- /dev/null
+++ b/include/crypto/dh.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_DH_H
+# define OSSL_CRYPTO_DH_H
+# pragma once
+
+# include <openssl/core.h>
+# include <openssl/params.h>
+# include <openssl/dh.h>
+# include "internal/ffc.h"
+
+DH *ossl_dh_new_by_nid_ex(OSSL_LIB_CTX *libctx, int nid);
+DH *ossl_dh_new_ex(OSSL_LIB_CTX *libctx);
+void ossl_dh_set0_libctx(DH *d, OSSL_LIB_CTX *libctx);
+int ossl_dh_generate_ffc_parameters(DH *dh, int type, int pbits, int qbits,
+ BN_GENCB *cb);
+int ossl_dh_generate_public_key(BN_CTX *ctx, const DH *dh,
+ const BIGNUM *priv_key, BIGNUM *pub_key);
+int ossl_dh_get_named_group_uid_from_size(int pbits);
+const char *ossl_dh_gen_type_id2name(int id);
+int ossl_dh_gen_type_name2id(const char *name, int type);
+void ossl_dh_cache_named_group(DH *dh);
+int ossl_dh_is_named_safe_prime_group(const DH *dh);
+
+FFC_PARAMS *ossl_dh_get0_params(DH *dh);
+int ossl_dh_get0_nid(const DH *dh);
+int ossl_dh_params_fromdata(DH *dh, const OSSL_PARAM params[]);
+int ossl_dh_key_fromdata(DH *dh, const OSSL_PARAM params[], int include_private);
+int ossl_dh_params_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]);
+int ossl_dh_key_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[],
+ int include_private);
+DH *ossl_dh_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int ossl_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh);
+
+int ossl_dh_check_pub_key_partial(const DH *dh, const BIGNUM *pub_key, int *ret);
+int ossl_dh_check_priv_key(const DH *dh, const BIGNUM *priv_key, int *ret);
+int ossl_dh_check_pairwise(const DH *dh);
+
+const DH_METHOD *ossl_dh_get_method(const DH *dh);
+
+int ossl_dh_buf2key(DH *key, const unsigned char *buf, size_t len);
+size_t ossl_dh_key2buf(const DH *dh, unsigned char **pbuf, size_t size,
+ int alloc);
+
+int ossl_dh_kdf_X9_42_asn1(unsigned char *out, size_t outlen,
+ const unsigned char *Z, size_t Zlen,
+ const char *cek_alg,
+ const unsigned char *ukm, size_t ukmlen,
+ const EVP_MD *md,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int ossl_dh_is_foreign(const DH *dh);
+DH *ossl_dh_dup(const DH *dh, int selection);
+
+#endif /* OSSL_CRYPTO_DH_H */
diff --git a/include/crypto/dherr.h b/include/crypto/dherr.h
new file mode 100644
index 000000000000..bb24d131eb88
--- /dev/null
+++ b/include/crypto/dherr.h
@@ -0,0 +1,30 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_DHERR_H
+# define OSSL_CRYPTO_DHERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# ifndef OPENSSL_NO_DH
+
+int ossl_err_load_DH_strings(void);
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/dsa.h b/include/crypto/dsa.h
new file mode 100644
index 000000000000..260c30fa4b0f
--- /dev/null
+++ b/include/crypto/dsa.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_DSA_H
+# define OSSL_CRYPTO_DSA_H
+# pragma once
+
+# include <openssl/core.h>
+# include <openssl/dsa.h>
+# include "internal/ffc.h"
+
+#define DSA_PARAMGEN_TYPE_FIPS_186_4 0 /* Use FIPS186-4 standard */
+#define DSA_PARAMGEN_TYPE_FIPS_186_2 1 /* Use legacy FIPS186-2 standard */
+#define DSA_PARAMGEN_TYPE_FIPS_DEFAULT 2
+
+DSA *ossl_dsa_new(OSSL_LIB_CTX *libctx);
+void ossl_dsa_set0_libctx(DSA *d, OSSL_LIB_CTX *libctx);
+
+int ossl_dsa_generate_ffc_parameters(DSA *dsa, int type, int pbits, int qbits,
+ BN_GENCB *cb);
+
+int ossl_dsa_sign_int(int type, const unsigned char *dgst, int dlen,
+ unsigned char *sig, unsigned int *siglen, DSA *dsa);
+
+FFC_PARAMS *ossl_dsa_get0_params(DSA *dsa);
+int ossl_dsa_ffc_params_fromdata(DSA *dsa, const OSSL_PARAM params[]);
+int ossl_dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[],
+ int include_private);
+DSA *ossl_dsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+int ossl_dsa_generate_public_key(BN_CTX *ctx, const DSA *dsa,
+ const BIGNUM *priv_key, BIGNUM *pub_key);
+int ossl_dsa_check_params(const DSA *dsa, int checktype, int *ret);
+int ossl_dsa_check_pub_key(const DSA *dsa, const BIGNUM *pub_key, int *ret);
+int ossl_dsa_check_pub_key_partial(const DSA *dsa, const BIGNUM *pub_key,
+ int *ret);
+int ossl_dsa_check_priv_key(const DSA *dsa, const BIGNUM *priv_key, int *ret);
+int ossl_dsa_check_pairwise(const DSA *dsa);
+int ossl_dsa_is_foreign(const DSA *dsa);
+DSA *ossl_dsa_dup(const DSA *dsa, int selection);
+
+#endif
diff --git a/include/crypto/dsaerr.h b/include/crypto/dsaerr.h
new file mode 100644
index 000000000000..9898097d0dd1
--- /dev/null
+++ b/include/crypto/dsaerr.h
@@ -0,0 +1,30 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_DSAERR_H
+# define OSSL_CRYPTO_DSAERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# ifndef OPENSSL_NO_DSA
+
+int ossl_err_load_DSA_strings(void);
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/dso_conf.h.in b/include/crypto/dso_conf.h.in
index 57a09b10a259..12de11ade8da 100644
--- a/include/crypto/dso_conf.h.in
+++ b/include/crypto/dso_conf.h.in
@@ -1,8 +1,8 @@
{- join("\n",map { "/* $_ */" } @autowarntext) -}
/*
- * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,6 +10,8 @@
#ifndef OSSL_CRYPTO_DSO_CONF_H
# define OSSL_CRYPTO_DSO_CONF_H
+# pragma once
+
{- # The DSO code currently always implements all functions so that no
# applications will have to worry about that from a compilation point
# of view. However, the "method"s may return zero unless that platform
@@ -27,5 +29,5 @@
@macros = ( "DSO_DLFCN" );
}
join("\n", map { "# define $_" } @macros); -}
-# define DSO_EXTENSION "{- $target{dso_extension} -}"
+# define DSO_EXTENSION "{- platform->dsoext() -}"
#endif
diff --git a/include/crypto/ec.h b/include/crypto/ec.h
index fe52ae704bb9..62163b31ac13 100644
--- a/include/crypto/ec.h
+++ b/include/crypto/ec.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,11 +11,20 @@
#ifndef OSSL_CRYPTO_EC_H
# define OSSL_CRYPTO_EC_H
+# pragma once
+
# include <openssl/opensslconf.h>
+# include <openssl/evp.h>
-# ifndef OPENSSL_NO_EC
+int ossl_ec_curve_name2nid(const char *name);
+const char *ossl_ec_curve_nid2nist_int(int nid);
+int ossl_ec_curve_nist2nid_int(const char *name);
+int evp_pkey_ctx_set_ec_param_enc_prov(EVP_PKEY_CTX *ctx, int param_enc);
+# ifndef OPENSSL_NO_EC
+# include <openssl/core.h>
# include <openssl/ec.h>
+# include "crypto/types.h"
/*-
* Computes the multiplicative inverse of x in the range
@@ -38,16 +47,54 @@
* reduction round on the input can be omitted by the underlying
* implementations for better SCA properties on regular input values).
*/
-__owur int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
- const BIGNUM *x, BN_CTX *ctx);
+__owur int ossl_ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
+ const BIGNUM *x, BN_CTX *ctx);
/*-
* ECDH Key Derivation Function as defined in ANSI X9.63
*/
-int ecdh_KDF_X9_63(unsigned char *out, size_t outlen,
- const unsigned char *Z, size_t Zlen,
- const unsigned char *sinfo, size_t sinfolen,
- const EVP_MD *md);
+int ossl_ecdh_kdf_X9_63(unsigned char *out, size_t outlen,
+ const unsigned char *Z, size_t Zlen,
+ const unsigned char *sinfo, size_t sinfolen,
+ const EVP_MD *md, OSSL_LIB_CTX *libctx,
+ const char *propq);
+
+int ossl_ec_key_public_check(const EC_KEY *eckey, BN_CTX *ctx);
+int ossl_ec_key_public_check_quick(const EC_KEY *eckey, BN_CTX *ctx);
+int ossl_ec_key_private_check(const EC_KEY *eckey);
+int ossl_ec_key_pairwise_check(const EC_KEY *eckey, BN_CTX *ctx);
+OSSL_LIB_CTX *ossl_ec_key_get_libctx(const EC_KEY *eckey);
+const char *ossl_ec_key_get0_propq(const EC_KEY *eckey);
+void ossl_ec_key_set0_libctx(EC_KEY *key, OSSL_LIB_CTX *libctx);
+
+/* Backend support */
+int ossl_ec_group_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl,
+ OSSL_PARAM params[], OSSL_LIB_CTX *libctx,
+ const char *propq,
+ BN_CTX *bnctx, unsigned char **genbuf);
+int ossl_ec_group_fromdata(EC_KEY *ec, const OSSL_PARAM params[]);
+int ossl_ec_group_set_params(EC_GROUP *group, const OSSL_PARAM params[]);
+int ossl_ec_key_fromdata(EC_KEY *ecx, const OSSL_PARAM params[],
+ int include_private);
+int ossl_ec_key_otherparams_fromdata(EC_KEY *ec, const OSSL_PARAM params[]);
+int ossl_ec_key_is_foreign(const EC_KEY *ec);
+EC_KEY *ossl_ec_key_dup(const EC_KEY *key, int selection);
+int ossl_x509_algor_is_sm2(const X509_ALGOR *palg);
+EC_KEY *ossl_ec_key_param_from_x509_algor(const X509_ALGOR *palg,
+ OSSL_LIB_CTX *libctx,
+ const char *propq);
+EC_KEY *ossl_ec_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+int ossl_ec_set_ecdh_cofactor_mode(EC_KEY *ec, int mode);
+int ossl_ec_encoding_name2id(const char *name);
+int ossl_ec_encoding_param2id(const OSSL_PARAM *p, int *id);
+int ossl_ec_pt_format_name2id(const char *name);
+int ossl_ec_pt_format_param2id(const OSSL_PARAM *p, int *id);
+char *ossl_ec_pt_format_id2name(int id);
+
+char *ossl_ec_check_group_type_id2name(int flags);
+int ossl_ec_set_check_group_type_from_name(EC_KEY *ec, const char *name);
# endif /* OPENSSL_NO_EC */
#endif
diff --git a/include/crypto/ecerr.h b/include/crypto/ecerr.h
new file mode 100644
index 000000000000..4658ae8fb2cd
--- /dev/null
+++ b/include/crypto/ecerr.h
@@ -0,0 +1,30 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_ECERR_H
+# define OSSL_CRYPTO_ECERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# ifndef OPENSSL_NO_EC
+
+int ossl_err_load_EC_strings(void);
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/ecx.h b/include/crypto/ecx.h
new file mode 100644
index 000000000000..48b95fa5bac8
--- /dev/null
+++ b/include/crypto/ecx.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Internal EC functions for other submodules: not for application use */
+
+#ifndef OSSL_CRYPTO_ECX_H
+# define OSSL_CRYPTO_ECX_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+
+# ifndef OPENSSL_NO_EC
+
+# include <openssl/core.h>
+# include <openssl/e_os2.h>
+# include <openssl/crypto.h>
+# include "internal/refcount.h"
+# include "crypto/types.h"
+
+# define X25519_KEYLEN 32
+# define X448_KEYLEN 56
+# define ED25519_KEYLEN 32
+# define ED448_KEYLEN 57
+
+# define MAX_KEYLEN ED448_KEYLEN
+
+# define X25519_BITS 253
+# define X25519_SECURITY_BITS 128
+
+# define X448_BITS 448
+# define X448_SECURITY_BITS 224
+
+# define ED25519_BITS 256
+/* RFC8032 Section 8.5 */
+# define ED25519_SECURITY_BITS 128
+# define ED25519_SIGSIZE 64
+
+# define ED448_BITS 456
+/* RFC8032 Section 8.5 */
+# define ED448_SECURITY_BITS 224
+# define ED448_SIGSIZE 114
+
+
+typedef enum {
+ ECX_KEY_TYPE_X25519,
+ ECX_KEY_TYPE_X448,
+ ECX_KEY_TYPE_ED25519,
+ ECX_KEY_TYPE_ED448
+} ECX_KEY_TYPE;
+
+#define KEYTYPE2NID(type) \
+ ((type) == ECX_KEY_TYPE_X25519 \
+ ? EVP_PKEY_X25519 \
+ : ((type) == ECX_KEY_TYPE_X448 \
+ ? EVP_PKEY_X448 \
+ : ((type) == ECX_KEY_TYPE_ED25519 \
+ ? EVP_PKEY_ED25519 \
+ : EVP_PKEY_ED448)))
+
+struct ecx_key_st {
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+ unsigned int haspubkey:1;
+ unsigned char pubkey[MAX_KEYLEN];
+ unsigned char *privkey;
+ size_t keylen;
+ ECX_KEY_TYPE type;
+ CRYPTO_REF_COUNT references;
+ CRYPTO_RWLOCK *lock;
+};
+
+size_t ossl_ecx_key_length(ECX_KEY_TYPE type);
+ECX_KEY *ossl_ecx_key_new(OSSL_LIB_CTX *libctx, ECX_KEY_TYPE type,
+ int haspubkey, const char *propq);
+void ossl_ecx_key_set0_libctx(ECX_KEY *key, OSSL_LIB_CTX *libctx);
+unsigned char *ossl_ecx_key_allocate_privkey(ECX_KEY *key);
+void ossl_ecx_key_free(ECX_KEY *key);
+int ossl_ecx_key_up_ref(ECX_KEY *key);
+ECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key, int selection);
+
+int ossl_x25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
+ const uint8_t peer_public_value[32]);
+void ossl_x25519_public_from_private(uint8_t out_public_value[32],
+ const uint8_t private_key[32]);
+
+int
+ossl_ed25519_public_from_private(OSSL_LIB_CTX *ctx, uint8_t out_public_key[32],
+ const uint8_t private_key[32],
+ const char *propq);
+int
+ossl_ed25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
+ const uint8_t public_key[32], const uint8_t private_key[32],
+ OSSL_LIB_CTX *libctx, const char *propq);
+int
+ossl_ed25519_verify(const uint8_t *message, size_t message_len,
+ const uint8_t signature[64], const uint8_t public_key[32],
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+int
+ossl_ed448_public_from_private(OSSL_LIB_CTX *ctx, uint8_t out_public_key[57],
+ const uint8_t private_key[57], const char *propq);
+int
+ossl_ed448_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig, const uint8_t *message,
+ size_t message_len, const uint8_t public_key[57],
+ const uint8_t private_key[57], const uint8_t *context,
+ size_t context_len, const char *propq);
+
+int
+ossl_ed448_verify(OSSL_LIB_CTX *ctx, const uint8_t *message, size_t message_len,
+ const uint8_t signature[114], const uint8_t public_key[57],
+ const uint8_t *context, size_t context_len, const char *propq);
+
+int
+ossl_x448(uint8_t out_shared_key[56], const uint8_t private_key[56],
+ const uint8_t peer_public_value[56]);
+void
+ossl_x448_public_from_private(uint8_t out_public_value[56],
+ const uint8_t private_key[56]);
+
+
+/* Backend support */
+typedef enum {
+ KEY_OP_PUBLIC,
+ KEY_OP_PRIVATE,
+ KEY_OP_KEYGEN
+} ecx_key_op_t;
+
+ECX_KEY *ossl_ecx_key_op(const X509_ALGOR *palg,
+ const unsigned char *p, int plen,
+ int pkey_id, ecx_key_op_t op,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+int ossl_ecx_public_from_private(ECX_KEY *key);
+int ossl_ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
+ int include_private);
+ECX_KEY *ossl_ecx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+ECX_KEY *ossl_evp_pkey_get1_X25519(EVP_PKEY *pkey);
+ECX_KEY *ossl_evp_pkey_get1_X448(EVP_PKEY *pkey);
+ECX_KEY *ossl_evp_pkey_get1_ED25519(EVP_PKEY *pkey);
+ECX_KEY *ossl_evp_pkey_get1_ED448(EVP_PKEY *pkey);
+# endif /* OPENSSL_NO_EC */
+#endif
diff --git a/include/crypto/encoder.h b/include/crypto/encoder.h
new file mode 100644
index 000000000000..562081ad4134
--- /dev/null
+++ b/include/crypto/encoder.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_ENCODER_H
+# define OSSL_CRYPTO_ENCODER_H
+# pragma once
+
+# include <openssl/types.h>
+
+OSSL_ENCODER *ossl_encoder_fetch_by_number(OSSL_LIB_CTX *libctx, int id,
+ const char *properties);
+int ossl_encoder_get_number(const OSSL_ENCODER *encoder);
+int ossl_encoder_store_cache_flush(OSSL_LIB_CTX *libctx);
+int ossl_encoder_store_remove_all_provided(const OSSL_PROVIDER *prov);
+
+#endif
diff --git a/include/crypto/encodererr.h b/include/crypto/encodererr.h
new file mode 100644
index 000000000000..56c458234bdd
--- /dev/null
+++ b/include/crypto/encodererr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_ENCODERERR_H
+# define OSSL_CRYPTO_ENCODERERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_OSSL_ENCODER_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/engine.h b/include/crypto/engine.h
index f80ae3ec30c9..fac6ed0966ae 100644
--- a/include/crypto/engine.h
+++ b/include/crypto/engine.h
@@ -1,7 +1,7 @@
/*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/include/crypto/engineerr.h b/include/crypto/engineerr.h
new file mode 100644
index 000000000000..737c841d645a
--- /dev/null
+++ b/include/crypto/engineerr.h
@@ -0,0 +1,30 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_ENGINEERR_H
+# define OSSL_CRYPTO_ENGINEERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# ifndef OPENSSL_NO_ENGINE
+
+int ossl_err_load_ENGINE_strings(void);
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/err.h b/include/crypto/err.h
index 8ab0e5baaa2c..15ec6fd0390a 100644
--- a/include/crypto/err.h
+++ b/include/crypto/err.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,10 +9,11 @@
#ifndef OSSL_CRYPTO_ERR_H
# define OSSL_CRYPTO_ERR_H
+# pragma once
-int err_load_crypto_strings_int(void);
+int ossl_err_load_ERR_strings(void);
+int ossl_err_load_crypto_strings(void);
void err_cleanup(void);
-void err_delete_thread_state(void);
int err_shelve_state(void **);
void err_unshelve_state(void *);
diff --git a/include/crypto/ess.h b/include/crypto/ess.h
new file mode 100644
index 000000000000..7acde5f8a4f5
--- /dev/null
+++ b/include/crypto/ess.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_ESS_H
+# define OSSL_CRYPTO_ESS_H
+# pragma once
+
+/*-
+ * IssuerSerial ::= SEQUENCE {
+ * issuer GeneralNames,
+ * serialNumber CertificateSerialNumber
+ * }
+ */
+
+struct ESS_issuer_serial {
+ STACK_OF(GENERAL_NAME) *issuer;
+ ASN1_INTEGER *serial;
+};
+
+/*-
+ * ESSCertID ::= SEQUENCE {
+ * certHash Hash,
+ * issuerSerial IssuerSerial OPTIONAL
+ * }
+ */
+
+struct ESS_cert_id {
+ ASN1_OCTET_STRING *hash; /* Always SHA-1 digest. */
+ ESS_ISSUER_SERIAL *issuer_serial;
+};
+
+/*-
+ * SigningCertificate ::= SEQUENCE {
+ * certs SEQUENCE OF ESSCertID,
+ * policies SEQUENCE OF PolicyInformation OPTIONAL
+ * }
+ */
+
+struct ESS_signing_cert {
+ STACK_OF(ESS_CERT_ID) *cert_ids;
+ STACK_OF(POLICYINFO) *policy_info;
+};
+
+/*-
+ * ESSCertIDv2 ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier DEFAULT id-sha256,
+ * certHash Hash,
+ * issuerSerial IssuerSerial OPTIONAL
+ * }
+ */
+
+struct ESS_cert_id_v2_st {
+ X509_ALGOR *hash_alg; /* Default: SHA-256 */
+ ASN1_OCTET_STRING *hash;
+ ESS_ISSUER_SERIAL *issuer_serial;
+};
+
+/*-
+ * SigningCertificateV2 ::= SEQUENCE {
+ * certs SEQUENCE OF ESSCertIDv2,
+ * policies SEQUENCE OF PolicyInformation OPTIONAL
+ * }
+ */
+
+struct ESS_signing_cert_v2_st {
+ STACK_OF(ESS_CERT_ID_V2) *cert_ids;
+ STACK_OF(POLICYINFO) *policy_info;
+};
+
+#endif /* OSSL_CRYPTO_ESS_H */
diff --git a/include/crypto/esserr.h b/include/crypto/esserr.h
new file mode 100644
index 000000000000..8df2df11eded
--- /dev/null
+++ b/include/crypto/esserr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_ESSERR_H
+# define OSSL_CRYPTO_ESSERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_ESS_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/evp.h b/include/crypto/evp.h
index d86aed36f075..e70d8e9e8459 100644
--- a/include/crypto/evp.h
+++ b/include/crypto/evp.h
@@ -1,14 +1,20 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/evp.h>
-#include "internal/refcount.h"
+#ifndef OSSL_CRYPTO_EVP_H
+# define OSSL_CRYPTO_EVP_H
+# pragma once
+
+# include <openssl/evp.h>
+# include <openssl/core_dispatch.h>
+# include "internal/refcount.h"
+# include "crypto/ecx.h"
/*
* Don't free up md_ctx->pctx in EVP_MD_CTX_reset, use the reserved flag
@@ -16,7 +22,93 @@
*/
#define EVP_MD_CTX_FLAG_KEEP_PKEY_CTX 0x0400
+#define evp_pkey_ctx_is_legacy(ctx) \
+ ((ctx)->keymgmt == NULL)
+#define evp_pkey_ctx_is_provided(ctx) \
+ (!evp_pkey_ctx_is_legacy(ctx))
+
struct evp_pkey_ctx_st {
+ /* Actual operation */
+ int operation;
+
+ /*
+ * Library context, property query, keytype and keymgmt associated with
+ * this context
+ */
+ OSSL_LIB_CTX *libctx;
+ char *propquery;
+ const char *keytype;
+ /* If |pkey| below is set, this field is always a reference to its keymgmt */
+ EVP_KEYMGMT *keymgmt;
+
+ union {
+ struct {
+ void *genctx;
+ } keymgmt;
+
+ struct {
+ EVP_KEYEXCH *exchange;
+ /*
+ * Opaque ctx returned from a providers exchange algorithm
+ * implementation OSSL_FUNC_keyexch_newctx()
+ */
+ void *algctx;
+ } kex;
+
+ struct {
+ EVP_SIGNATURE *signature;
+ /*
+ * Opaque ctx returned from a providers signature algorithm
+ * implementation OSSL_FUNC_signature_newctx()
+ */
+ void *algctx;
+ } sig;
+
+ struct {
+ EVP_ASYM_CIPHER *cipher;
+ /*
+ * Opaque ctx returned from a providers asymmetric cipher algorithm
+ * implementation OSSL_FUNC_asym_cipher_newctx()
+ */
+ void *algctx;
+ } ciph;
+ struct {
+ EVP_KEM *kem;
+ /*
+ * Opaque ctx returned from a providers KEM algorithm
+ * implementation OSSL_FUNC_kem_newctx()
+ */
+ void *algctx;
+ } encap;
+ } op;
+
+ /*
+ * Cached parameters. Inits of operations that depend on these should
+ * call evp_pkey_ctx_use_delayed_data() when the operation has been set
+ * up properly.
+ */
+ struct {
+ /* Distinguishing Identifier, ISO/IEC 15946-3, FIPS 196 */
+ char *dist_id_name; /* The name used with EVP_PKEY_CTX_ctrl_str() */
+ void *dist_id; /* The distinguishing ID itself */
+ size_t dist_id_len; /* The length of the distinguishing ID */
+
+ /* Indicators of what has been set. Keep them together! */
+ unsigned int dist_id_set : 1;
+ } cached_parameters;
+
+ /* Application specific data, usually used by the callback */
+ void *app_data;
+ /* Keygen callback */
+ EVP_PKEY_gen_cb *pkey_gencb;
+ /* implementation specific keygen data */
+ int *keygen_info;
+ int keygen_info_count;
+
+ /* Legacy fields below */
+
+ /* EVP_PKEY identity */
+ int legacy_keytype;
/* Method associated with this operation */
const EVP_PKEY_METHOD *pmeth;
/* Engine that implements this method or NULL if builtin */
@@ -25,17 +117,17 @@ struct evp_pkey_ctx_st {
EVP_PKEY *pkey;
/* Peer key for key agreement, may be NULL */
EVP_PKEY *peerkey;
- /* Actual operation */
- int operation;
/* Algorithm specific data */
void *data;
- /* Application specific data */
- void *app_data;
- /* Keygen callback */
- EVP_PKEY_gen_cb *pkey_gencb;
- /* implementation specific keygen data */
- int *keygen_info;
- int keygen_info_count;
+ /* Indicator if digest_custom needs to be called */
+ unsigned int flag_call_digest_custom:1;
+ /*
+ * Used to support taking custody of memory in the case of a provider being
+ * used with the deprecated EVP_PKEY_CTX_set_rsa_keygen_pubexp() API. This
+ * member should NOT be used for any other purpose and should be removed
+ * when said deprecated API is excised completely.
+ */
+ BIGNUM *rsa_pubexp;
} /* EVP_PKEY_CTX */ ;
#define EVP_PKEY_FLAG_DYNAMIC 1
@@ -44,7 +136,7 @@ struct evp_pkey_method_st {
int pkey_id;
int flags;
int (*init) (EVP_PKEY_CTX *ctx);
- int (*copy) (EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src);
+ int (*copy) (EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src);
void (*cleanup) (EVP_PKEY_CTX *ctx);
int (*paramgen_init) (EVP_PKEY_CTX *ctx);
int (*paramgen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
@@ -93,30 +185,74 @@ DEFINE_STACK_OF_CONST(EVP_PKEY_METHOD)
void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx);
-extern const EVP_PKEY_METHOD cmac_pkey_meth;
-extern const EVP_PKEY_METHOD dh_pkey_meth;
-extern const EVP_PKEY_METHOD dhx_pkey_meth;
-extern const EVP_PKEY_METHOD dsa_pkey_meth;
-extern const EVP_PKEY_METHOD ec_pkey_meth;
-extern const EVP_PKEY_METHOD sm2_pkey_meth;
-extern const EVP_PKEY_METHOD ecx25519_pkey_meth;
-extern const EVP_PKEY_METHOD ecx448_pkey_meth;
-extern const EVP_PKEY_METHOD ed25519_pkey_meth;
-extern const EVP_PKEY_METHOD ed448_pkey_meth;
-extern const EVP_PKEY_METHOD hmac_pkey_meth;
-extern const EVP_PKEY_METHOD rsa_pkey_meth;
-extern const EVP_PKEY_METHOD rsa_pss_pkey_meth;
-extern const EVP_PKEY_METHOD scrypt_pkey_meth;
-extern const EVP_PKEY_METHOD tls1_prf_pkey_meth;
-extern const EVP_PKEY_METHOD hkdf_pkey_meth;
-extern const EVP_PKEY_METHOD poly1305_pkey_meth;
-extern const EVP_PKEY_METHOD siphash_pkey_meth;
+const EVP_PKEY_METHOD *ossl_dh_pkey_method(void);
+const EVP_PKEY_METHOD *ossl_dhx_pkey_method(void);
+const EVP_PKEY_METHOD *ossl_dsa_pkey_method(void);
+const EVP_PKEY_METHOD *ossl_ec_pkey_method(void);
+const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void);
+const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void);
+const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void);
+const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void);
+const EVP_PKEY_METHOD *ossl_rsa_pkey_method(void);
+const EVP_PKEY_METHOD *ossl_rsa_pss_pkey_method(void);
+
+struct evp_mac_st {
+ OSSL_PROVIDER *prov;
+ int name_id;
+ char *type_name;
+ const char *description;
+
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+
+ OSSL_FUNC_mac_newctx_fn *newctx;
+ OSSL_FUNC_mac_dupctx_fn *dupctx;
+ OSSL_FUNC_mac_freectx_fn *freectx;
+ OSSL_FUNC_mac_init_fn *init;
+ OSSL_FUNC_mac_update_fn *update;
+ OSSL_FUNC_mac_final_fn *final;
+ OSSL_FUNC_mac_gettable_params_fn *gettable_params;
+ OSSL_FUNC_mac_gettable_ctx_params_fn *gettable_ctx_params;
+ OSSL_FUNC_mac_settable_ctx_params_fn *settable_ctx_params;
+ OSSL_FUNC_mac_get_params_fn *get_params;
+ OSSL_FUNC_mac_get_ctx_params_fn *get_ctx_params;
+ OSSL_FUNC_mac_set_ctx_params_fn *set_ctx_params;
+};
+
+struct evp_kdf_st {
+ OSSL_PROVIDER *prov;
+ int name_id;
+ char *type_name;
+ const char *description;
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+
+ OSSL_FUNC_kdf_newctx_fn *newctx;
+ OSSL_FUNC_kdf_dupctx_fn *dupctx;
+ OSSL_FUNC_kdf_freectx_fn *freectx;
+ OSSL_FUNC_kdf_reset_fn *reset;
+ OSSL_FUNC_kdf_derive_fn *derive;
+ OSSL_FUNC_kdf_gettable_params_fn *gettable_params;
+ OSSL_FUNC_kdf_gettable_ctx_params_fn *gettable_ctx_params;
+ OSSL_FUNC_kdf_settable_ctx_params_fn *settable_ctx_params;
+ OSSL_FUNC_kdf_get_params_fn *get_params;
+ OSSL_FUNC_kdf_get_ctx_params_fn *get_ctx_params;
+ OSSL_FUNC_kdf_set_ctx_params_fn *set_ctx_params;
+};
+
+#define EVP_ORIG_DYNAMIC 0
+#define EVP_ORIG_GLOBAL 1
+#define EVP_ORIG_METH 2
struct evp_md_st {
+ /* nid */
int type;
+
+ /* Legacy structure members */
int pkey_type;
int md_size;
unsigned long flags;
+ int origin;
int (*init) (EVP_MD_CTX *ctx);
int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count);
int (*final) (EVP_MD_CTX *ctx, unsigned char *md);
@@ -126,16 +262,44 @@ struct evp_md_st {
int ctx_size; /* how big does the ctx->md_data need to be */
/* control function */
int (*md_ctrl) (EVP_MD_CTX *ctx, int cmd, int p1, void *p2);
+
+ /* New structure members */
+ /* Above comment to be removed when legacy has gone */
+ int name_id;
+ char *type_name;
+ const char *description;
+ OSSL_PROVIDER *prov;
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+ OSSL_FUNC_digest_newctx_fn *newctx;
+ OSSL_FUNC_digest_init_fn *dinit;
+ OSSL_FUNC_digest_update_fn *dupdate;
+ OSSL_FUNC_digest_final_fn *dfinal;
+ OSSL_FUNC_digest_digest_fn *digest;
+ OSSL_FUNC_digest_freectx_fn *freectx;
+ OSSL_FUNC_digest_dupctx_fn *dupctx;
+ OSSL_FUNC_digest_get_params_fn *get_params;
+ OSSL_FUNC_digest_set_ctx_params_fn *set_ctx_params;
+ OSSL_FUNC_digest_get_ctx_params_fn *get_ctx_params;
+ OSSL_FUNC_digest_gettable_params_fn *gettable_params;
+ OSSL_FUNC_digest_settable_ctx_params_fn *settable_ctx_params;
+ OSSL_FUNC_digest_gettable_ctx_params_fn *gettable_ctx_params;
+
} /* EVP_MD */ ;
struct evp_cipher_st {
int nid;
+
int block_size;
/* Default value for variable length ciphers */
int key_len;
int iv_len;
+
+ /* Legacy structure members */
/* Various flags */
unsigned long flags;
+ /* How the EVP_CIPHER was created. */
+ int origin;
/* init key */
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
@@ -154,6 +318,29 @@ struct evp_cipher_st {
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);
/* Application data */
void *app_data;
+
+ /* New structure members */
+ /* Above comment to be removed when legacy has gone */
+ int name_id;
+ char *type_name;
+ const char *description;
+ OSSL_PROVIDER *prov;
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+ OSSL_FUNC_cipher_newctx_fn *newctx;
+ OSSL_FUNC_cipher_encrypt_init_fn *einit;
+ OSSL_FUNC_cipher_decrypt_init_fn *dinit;
+ OSSL_FUNC_cipher_update_fn *cupdate;
+ OSSL_FUNC_cipher_final_fn *cfinal;
+ OSSL_FUNC_cipher_cipher_fn *ccipher;
+ OSSL_FUNC_cipher_freectx_fn *freectx;
+ OSSL_FUNC_cipher_dupctx_fn *dupctx;
+ OSSL_FUNC_cipher_get_params_fn *get_params;
+ OSSL_FUNC_cipher_get_ctx_params_fn *get_ctx_params;
+ OSSL_FUNC_cipher_set_ctx_params_fn *set_ctx_params;
+ OSSL_FUNC_cipher_gettable_params_fn *gettable_params;
+ OSSL_FUNC_cipher_gettable_ctx_params_fn *gettable_ctx_params;
+ OSSL_FUNC_cipher_settable_ctx_params_fn *settable_ctx_params;
} /* EVP_CIPHER */ ;
/* Macros to code block cipher wrappers */
@@ -165,7 +352,7 @@ struct evp_cipher_st {
#define BLOCK_CIPHER_ecb_loop() \
size_t i, bl; \
- bl = EVP_CIPHER_CTX_cipher(ctx)->block_size; \
+ bl = EVP_CIPHER_CTX_get0_cipher(ctx)->block_size; \
if (inl < bl) return 1;\
inl -= bl; \
for (i=0; i <= inl; i+=bl)
@@ -174,26 +361,26 @@ struct evp_cipher_st {
static int cname##_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) \
{\
BLOCK_CIPHER_ecb_loop() \
- cprefix##_ecb_encrypt(in + i, out + i, &EVP_C_DATA(kstruct,ctx)->ksched, EVP_CIPHER_CTX_encrypting(ctx)); \
+ cprefix##_ecb_encrypt(in + i, out + i, &EVP_C_DATA(kstruct,ctx)->ksched, EVP_CIPHER_CTX_is_encrypting(ctx)); \
return 1;\
}
-#define EVP_MAXCHUNK ((size_t)1<<(sizeof(long)*8-2))
+#define EVP_MAXCHUNK ((size_t)1 << 30)
#define BLOCK_CIPHER_func_ofb(cname, cprefix, cbits, kstruct, ksched) \
static int cname##_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) \
{\
while(inl>=EVP_MAXCHUNK) {\
- int num = EVP_CIPHER_CTX_num(ctx);\
- cprefix##_ofb##cbits##_encrypt(in, out, (long)EVP_MAXCHUNK, &EVP_C_DATA(kstruct,ctx)->ksched, EVP_CIPHER_CTX_iv_noconst(ctx), &num); \
+ int num = EVP_CIPHER_CTX_get_num(ctx);\
+ cprefix##_ofb##cbits##_encrypt(in, out, (long)EVP_MAXCHUNK, &EVP_C_DATA(kstruct,ctx)->ksched, ctx->iv, &num); \
EVP_CIPHER_CTX_set_num(ctx, num);\
inl-=EVP_MAXCHUNK;\
in +=EVP_MAXCHUNK;\
out+=EVP_MAXCHUNK;\
}\
if (inl) {\
- int num = EVP_CIPHER_CTX_num(ctx);\
- cprefix##_ofb##cbits##_encrypt(in, out, (long)inl, &EVP_C_DATA(kstruct,ctx)->ksched, EVP_CIPHER_CTX_iv_noconst(ctx), &num); \
+ int num = EVP_CIPHER_CTX_get_num(ctx);\
+ cprefix##_ofb##cbits##_encrypt(in, out, (long)inl, &EVP_C_DATA(kstruct,ctx)->ksched, ctx->iv, &num); \
EVP_CIPHER_CTX_set_num(ctx, num);\
}\
return 1;\
@@ -204,13 +391,13 @@ static int cname##_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const uns
{\
while(inl>=EVP_MAXCHUNK) \
{\
- cprefix##_cbc_encrypt(in, out, (long)EVP_MAXCHUNK, &EVP_C_DATA(kstruct,ctx)->ksched, EVP_CIPHER_CTX_iv_noconst(ctx), EVP_CIPHER_CTX_encrypting(ctx));\
+ cprefix##_cbc_encrypt(in, out, (long)EVP_MAXCHUNK, &EVP_C_DATA(kstruct,ctx)->ksched, ctx->iv, EVP_CIPHER_CTX_is_encrypting(ctx));\
inl-=EVP_MAXCHUNK;\
in +=EVP_MAXCHUNK;\
out+=EVP_MAXCHUNK;\
}\
if (inl)\
- cprefix##_cbc_encrypt(in, out, (long)inl, &EVP_C_DATA(kstruct,ctx)->ksched, EVP_CIPHER_CTX_iv_noconst(ctx), EVP_CIPHER_CTX_encrypting(ctx));\
+ cprefix##_cbc_encrypt(in, out, (long)inl, &EVP_C_DATA(kstruct,ctx)->ksched, ctx->iv, EVP_CIPHER_CTX_is_encrypting(ctx));\
return 1;\
}
@@ -222,13 +409,13 @@ static int cname##_cfb##cbits##_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (inl < chunk) chunk = inl;\
while (inl && inl >= chunk)\
{\
- int num = EVP_CIPHER_CTX_num(ctx);\
+ int num = EVP_CIPHER_CTX_get_num(ctx);\
cprefix##_cfb##cbits##_encrypt(in, out, (long) \
((cbits == 1) \
&& !EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS) \
? chunk*8 : chunk), \
- &EVP_C_DATA(kstruct, ctx)->ksched, EVP_CIPHER_CTX_iv_noconst(ctx),\
- &num, EVP_CIPHER_CTX_encrypting(ctx));\
+ &EVP_C_DATA(kstruct, ctx)->ksched, ctx->iv,\
+ &num, EVP_CIPHER_CTX_is_encrypting(ctx));\
EVP_CIPHER_CTX_set_num(ctx, num);\
inl -= chunk;\
in += chunk;\
@@ -250,6 +437,7 @@ static int cname##_cfb##cbits##_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static const EVP_CIPHER cname##_##mode = { \
nid##_##nmode, block_size, key_len, iv_len, \
flags | EVP_CIPH_##MODE##_MODE, \
+ EVP_ORIG_GLOBAL, \
init_key, \
cname##_##mode##_cipher, \
cleanup, \
@@ -305,6 +493,7 @@ BLOCK_CIPHER_def_ecb(cname, kstruct, nid, block_size, key_len, flags, \
static const EVP_CIPHER cname##_cbc = {\
nid##_cbc, block_size, key_len, iv_len, \
flags | EVP_CIPH_CBC_MODE,\
+ EVP_ORIG_GLOBAL,\
init_key,\
cname##_cbc_cipher,\
cleanup,\
@@ -318,6 +507,7 @@ const EVP_CIPHER *EVP_##cname##_cbc(void) { return &cname##_cbc; }\
static const EVP_CIPHER cname##_cfb = {\
nid##_cfb64, 1, key_len, iv_len, \
flags | EVP_CIPH_CFB_MODE,\
+ EVP_ORIG_GLOBAL,\
init_key,\
cname##_cfb_cipher,\
cleanup,\
@@ -331,6 +521,7 @@ const EVP_CIPHER *EVP_##cname##_cfb(void) { return &cname##_cfb; }\
static const EVP_CIPHER cname##_ofb = {\
nid##_ofb64, 1, key_len, iv_len, \
flags | EVP_CIPH_OFB_MODE,\
+ EVP_ORIG_GLOBAL,\
init_key,\
cname##_ofb_cipher,\
cleanup,\
@@ -344,6 +535,7 @@ const EVP_CIPHER *EVP_##cname##_ofb(void) { return &cname##_ofb; }\
static const EVP_CIPHER cname##_ecb = {\
nid##_ecb, block_size, key_len, iv_len, \
flags | EVP_CIPH_ECB_MODE,\
+ EVP_ORIG_GLOBAL,\
init_key,\
cname##_ecb_cipher,\
cleanup,\
@@ -372,66 +564,293 @@ const EVP_CIPHER *EVP_##cname##_ecb(void) { return &cname##_ecb; }
(fl)|EVP_CIPH_FLAG_DEFAULT_ASN1, \
cipher##_init_key, NULL, NULL, NULL, NULL)
+typedef struct {
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+ unsigned int iv_len;
+ unsigned int tag_len;
+} evp_cipher_aead_asn1_params;
-# ifndef OPENSSL_NO_EC
-
-#define X25519_KEYLEN 32
-#define X448_KEYLEN 56
-#define ED448_KEYLEN 57
+int evp_cipher_param_to_asn1_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
+ evp_cipher_aead_asn1_params *params);
-#define MAX_KEYLEN ED448_KEYLEN
+int evp_cipher_asn1_to_param_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
+ evp_cipher_aead_asn1_params *params);
+/*
+ * To support transparent execution of operation in backends other
+ * than the "origin" key, we support transparent export/import to
+ * those providers, and maintain a cache of the imported keydata,
+ * so we don't need to redo the export/import every time we perform
+ * the same operation in that same provider.
+ * This requires that the "origin" backend (whether it's a legacy or a
+ * provider "origin") implements exports, and that the target provider
+ * has an EVP_KEYMGMT that implements import.
+ */
typedef struct {
- unsigned char pubkey[MAX_KEYLEN];
- unsigned char *privkey;
-} ECX_KEY;
+ EVP_KEYMGMT *keymgmt;
+ void *keydata;
+ int selection;
+} OP_CACHE_ELEM;
-#endif
+DEFINE_STACK_OF(OP_CACHE_ELEM)
/*
- * Type needs to be a bit field Sub-type needs to be for variations on the
- * method, as in, can it do arbitrary encryption....
+ * An EVP_PKEY can have the following states:
+ *
+ * untyped & empty:
+ *
+ * type == EVP_PKEY_NONE && keymgmt == NULL
+ *
+ * typed & empty:
+ *
+ * (type != EVP_PKEY_NONE && pkey.ptr == NULL) ## legacy (libcrypto only)
+ * || (keymgmt != NULL && keydata == NULL) ## provider side
+ *
+ * fully assigned:
+ *
+ * (type != EVP_PKEY_NONE && pkey.ptr != NULL) ## legacy (libcrypto only)
+ * || (keymgmt != NULL && keydata != NULL) ## provider side
+ *
+ * The easiest way to detect a legacy key is:
+ *
+ * keymgmt == NULL && type != EVP_PKEY_NONE
+ *
+ * The easiest way to detect a provider side key is:
+ *
+ * keymgmt != NULL
*/
+#define evp_pkey_is_blank(pk) \
+ ((pk)->type == EVP_PKEY_NONE && (pk)->keymgmt == NULL)
+#define evp_pkey_is_typed(pk) \
+ ((pk)->type != EVP_PKEY_NONE || (pk)->keymgmt != NULL)
+#ifndef FIPS_MODULE
+# define evp_pkey_is_assigned(pk) \
+ ((pk)->pkey.ptr != NULL || (pk)->keydata != NULL)
+#else
+# define evp_pkey_is_assigned(pk) \
+ ((pk)->keydata != NULL)
+#endif
+#define evp_pkey_is_legacy(pk) \
+ ((pk)->type != EVP_PKEY_NONE && (pk)->keymgmt == NULL)
+#define evp_pkey_is_provided(pk) \
+ ((pk)->keymgmt != NULL)
+
+union legacy_pkey_st {
+ void *ptr;
+ struct rsa_st *rsa; /* RSA */
+# ifndef OPENSSL_NO_DSA
+ struct dsa_st *dsa; /* DSA */
+# endif
+# ifndef OPENSSL_NO_DH
+ struct dh_st *dh; /* DH */
+# endif
+# ifndef OPENSSL_NO_EC
+ struct ec_key_st *ec; /* ECC */
+ ECX_KEY *ecx; /* X25519, X448, Ed25519, Ed448 */
+# endif
+};
+
struct evp_pkey_st {
+ /* == Legacy attributes == */
int type;
int save_type;
- CRYPTO_REF_COUNT references;
+
+# ifndef FIPS_MODULE
+ /*
+ * Legacy key "origin" is composed of a pointer to an EVP_PKEY_ASN1_METHOD,
+ * a pointer to a low level key and possibly a pointer to an engine.
+ */
const EVP_PKEY_ASN1_METHOD *ameth;
ENGINE *engine;
ENGINE *pmeth_engine; /* If not NULL public key ENGINE to use */
- union {
- void *ptr;
-# ifndef OPENSSL_NO_RSA
- struct rsa_st *rsa; /* RSA */
-# endif
-# ifndef OPENSSL_NO_DSA
- struct dsa_st *dsa; /* DSA */
-# endif
-# ifndef OPENSSL_NO_DH
- struct dh_st *dh; /* DH */
-# endif
-# ifndef OPENSSL_NO_EC
- struct ec_key_st *ec; /* ECC */
- ECX_KEY *ecx; /* X25519, X448, Ed25519, Ed448 */
+
+ /* Union to store the reference to an origin legacy key */
+ union legacy_pkey_st pkey;
+
+ /* Union to store the reference to a non-origin legacy key */
+ union legacy_pkey_st legacy_cache_pkey;
# endif
- } pkey;
- int save_parameters;
- STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
+
+ /* == Common attributes == */
+ CRYPTO_REF_COUNT references;
CRYPTO_RWLOCK *lock;
+#ifndef FIPS_MODULE
+ STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
+ int save_parameters;
+ unsigned int foreign:1; /* the low-level key is using an engine or an app-method */
+ CRYPTO_EX_DATA ex_data;
+#endif
+
+ /* == Provider attributes == */
+
+ /*
+ * Provider keydata "origin" is composed of a pointer to an EVP_KEYMGMT
+ * and a pointer to the provider side key data. This is never used at
+ * the same time as the legacy key data above.
+ */
+ EVP_KEYMGMT *keymgmt;
+ void *keydata;
+ /*
+ * If any libcrypto code does anything that may modify the keydata
+ * contents, this dirty counter must be incremented.
+ */
+ size_t dirty_cnt;
+
+ /*
+ * To support transparent execution of operation in backends other
+ * than the "origin" key, we support transparent export/import to
+ * those providers, and maintain a cache of the imported keydata,
+ * so we don't need to redo the export/import every time we perform
+ * the same operation in that same provider.
+ */
+ STACK_OF(OP_CACHE_ELEM) *operation_cache;
+
+ /*
+ * We keep a copy of that "origin"'s dirty count, so we know if the
+ * operation cache needs flushing.
+ */
+ size_t dirty_cnt_copy;
+
+ /* Cache of key object information */
+ struct {
+ int bits;
+ int security_bits;
+ int size;
+ } cache;
} /* EVP_PKEY */ ;
+#define EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) \
+ ((ctx)->operation == EVP_PKEY_OP_SIGN \
+ || (ctx)->operation == EVP_PKEY_OP_SIGNCTX \
+ || (ctx)->operation == EVP_PKEY_OP_VERIFY \
+ || (ctx)->operation == EVP_PKEY_OP_VERIFYCTX \
+ || (ctx)->operation == EVP_PKEY_OP_VERIFYRECOVER)
+
+#define EVP_PKEY_CTX_IS_DERIVE_OP(ctx) \
+ ((ctx)->operation == EVP_PKEY_OP_DERIVE)
+
+#define EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) \
+ ((ctx)->operation == EVP_PKEY_OP_ENCRYPT \
+ || (ctx)->operation == EVP_PKEY_OP_DECRYPT)
+
+#define EVP_PKEY_CTX_IS_GEN_OP(ctx) \
+ ((ctx)->operation == EVP_PKEY_OP_PARAMGEN \
+ || (ctx)->operation == EVP_PKEY_OP_KEYGEN)
+
+#define EVP_PKEY_CTX_IS_FROMDATA_OP(ctx) \
+ ((ctx)->operation == EVP_PKEY_OP_FROMDATA)
+
+#define EVP_PKEY_CTX_IS_KEM_OP(ctx) \
+ ((ctx)->operation == EVP_PKEY_OP_ENCAPSULATE \
+ || (ctx)->operation == EVP_PKEY_OP_DECAPSULATE)
void openssl_add_all_ciphers_int(void);
void openssl_add_all_digests_int(void);
void evp_cleanup_int(void);
void evp_app_cleanup_int(void);
+void *evp_pkey_export_to_provider(EVP_PKEY *pk, OSSL_LIB_CTX *libctx,
+ EVP_KEYMGMT **keymgmt,
+ const char *propquery);
+#ifndef FIPS_MODULE
+int evp_pkey_copy_downgraded(EVP_PKEY **dest, const EVP_PKEY *src);
+void *evp_pkey_get_legacy(EVP_PKEY *pk);
+void evp_pkey_free_legacy(EVP_PKEY *x);
+EVP_PKEY *evp_pkcs82pkey_legacy(const PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *libctx, const char *propq);
+#endif
+
+/*
+ * KEYMGMT utility functions
+ */
+
+/*
+ * Key import structure and helper function, to be used as an export callback
+ */
+struct evp_keymgmt_util_try_import_data_st {
+ EVP_KEYMGMT *keymgmt;
+ void *keydata;
+
+ int selection;
+};
+int evp_keymgmt_util_try_import(const OSSL_PARAM params[], void *arg);
+int evp_keymgmt_util_assign_pkey(EVP_PKEY *pkey, EVP_KEYMGMT *keymgmt,
+ void *keydata);
+EVP_PKEY *evp_keymgmt_util_make_pkey(EVP_KEYMGMT *keymgmt, void *keydata);
+
+int evp_keymgmt_util_export(const EVP_PKEY *pk, int selection,
+ OSSL_CALLBACK *export_cb, void *export_cbarg);
+void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
+ int selection);
+OP_CACHE_ELEM *evp_keymgmt_util_find_operation_cache(EVP_PKEY *pk,
+ EVP_KEYMGMT *keymgmt,
+ int selection);
+int evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk, int locking);
+int evp_keymgmt_util_cache_keydata(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
+ void *keydata, int selection);
+void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk);
+void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
+ int selection, const OSSL_PARAM params[]);
+int evp_keymgmt_util_has(EVP_PKEY *pk, int selection);
+int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection);
+int evp_keymgmt_util_copy(EVP_PKEY *to, EVP_PKEY *from, int selection);
+void *evp_keymgmt_util_gen(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
+ void *genctx, OSSL_CALLBACK *cb, void *cbarg);
+int evp_keymgmt_util_get_deflt_digest_name(EVP_KEYMGMT *keymgmt,
+ void *keydata,
+ char *mdname, size_t mdname_sz);
+const char *evp_keymgmt_util_query_operation_name(EVP_KEYMGMT *keymgmt,
+ int op_id);
+
+/*
+ * KEYMGMT provider interface functions
+ */
+void *evp_keymgmt_newdata(const EVP_KEYMGMT *keymgmt);
+void evp_keymgmt_freedata(const EVP_KEYMGMT *keymgmt, void *keyddata);
+int evp_keymgmt_get_params(const EVP_KEYMGMT *keymgmt,
+ void *keydata, OSSL_PARAM params[]);
+int evp_keymgmt_set_params(const EVP_KEYMGMT *keymgmt,
+ void *keydata, const OSSL_PARAM params[]);
+void *evp_keymgmt_gen_init(const EVP_KEYMGMT *keymgmt, int selection,
+ const OSSL_PARAM params[]);
+int evp_keymgmt_gen_set_template(const EVP_KEYMGMT *keymgmt, void *genctx,
+ void *template);
+int evp_keymgmt_gen_set_params(const EVP_KEYMGMT *keymgmt, void *genctx,
+ const OSSL_PARAM params[]);
+void *evp_keymgmt_gen(const EVP_KEYMGMT *keymgmt, void *genctx,
+ OSSL_CALLBACK *cb, void *cbarg);
+void evp_keymgmt_gen_cleanup(const EVP_KEYMGMT *keymgmt, void *genctx);
+
+int evp_keymgmt_has_load(const EVP_KEYMGMT *keymgmt);
+void *evp_keymgmt_load(const EVP_KEYMGMT *keymgmt,
+ const void *objref, size_t objref_sz);
+
+int evp_keymgmt_has(const EVP_KEYMGMT *keymgmt, void *keyddata, int selection);
+int evp_keymgmt_validate(const EVP_KEYMGMT *keymgmt, void *keydata,
+ int selection, int checktype);
+int evp_keymgmt_match(const EVP_KEYMGMT *keymgmt,
+ const void *keydata1, const void *keydata2,
+ int selection);
+
+int evp_keymgmt_import(const EVP_KEYMGMT *keymgmt, void *keydata,
+ int selection, const OSSL_PARAM params[]);
+const OSSL_PARAM *evp_keymgmt_import_types(const EVP_KEYMGMT *keymgmt,
+ int selection);
+int evp_keymgmt_export(const EVP_KEYMGMT *keymgmt, void *keydata,
+ int selection, OSSL_CALLBACK *param_cb, void *cbarg);
+const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt,
+ int selection);
+void *evp_keymgmt_dup(const EVP_KEYMGMT *keymgmt,
+ const void *keydata_from, int selection);
+EVP_KEYMGMT *evp_keymgmt_fetch_from_prov(OSSL_PROVIDER *prov,
+ const char *name,
+ const char *properties);
/* Pulling defines out of C source files */
-#define EVP_RC4_KEY_SIZE 16
-#ifndef TLS1_1_VERSION
-# define TLS1_1_VERSION 0x0302
-#endif
+# define EVP_RC4_KEY_SIZE 16
+# ifndef TLS1_1_VERSION
+# define TLS1_1_VERSION 0x0302
+# endif
void evp_encode_ctx_set_flags(EVP_ENCODE_CTX *ctx, unsigned int flags);
@@ -440,3 +859,94 @@ void evp_encode_ctx_set_flags(EVP_ENCODE_CTX *ctx, unsigned int flags);
#define EVP_ENCODE_CTX_NO_NEWLINES 1
/* Use the SRP base64 alphabet instead of the standard one */
#define EVP_ENCODE_CTX_USE_SRP_ALPHABET 2
+
+const EVP_CIPHER *evp_get_cipherbyname_ex(OSSL_LIB_CTX *libctx,
+ const char *name);
+const EVP_MD *evp_get_digestbyname_ex(OSSL_LIB_CTX *libctx,
+ const char *name);
+
+int ossl_pkcs5_pbkdf2_hmac_ex(const char *pass, int passlen,
+ const unsigned char *salt, int saltlen, int iter,
+ const EVP_MD *digest, int keylen,
+ unsigned char *out,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+# ifndef FIPS_MODULE
+/*
+ * Internal helpers for stricter EVP_PKEY_CTX_{set,get}_params().
+ *
+ * Return 1 on success, 0 or negative for errors.
+ *
+ * In particular they return -2 if any of the params is not supported.
+ *
+ * They are not available in FIPS_MODULE as they depend on
+ * - EVP_PKEY_CTX_{get,set}_params()
+ * - EVP_PKEY_CTX_{gettable,settable}_params()
+ *
+ */
+int evp_pkey_ctx_set_params_strict(EVP_PKEY_CTX *ctx, OSSL_PARAM *params);
+int evp_pkey_ctx_get_params_strict(EVP_PKEY_CTX *ctx, OSSL_PARAM *params);
+
+EVP_MD_CTX *evp_md_ctx_new_ex(EVP_PKEY *pkey, const ASN1_OCTET_STRING *id,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int evp_pkey_name2type(const char *name);
+const char *evp_pkey_type2name(int type);
+
+int evp_pkey_ctx_set1_id_prov(EVP_PKEY_CTX *ctx, const void *id, int len);
+int evp_pkey_ctx_get1_id_prov(EVP_PKEY_CTX *ctx, void *id);
+int evp_pkey_ctx_get1_id_len_prov(EVP_PKEY_CTX *ctx, size_t *id_len);
+
+int evp_pkey_ctx_use_cached_data(EVP_PKEY_CTX *ctx);
+# endif /* !defined(FIPS_MODULE) */
+
+int evp_method_store_cache_flush(OSSL_LIB_CTX *libctx);
+int evp_method_store_remove_all_provided(const OSSL_PROVIDER *prov);
+
+int evp_default_properties_enable_fips_int(OSSL_LIB_CTX *libctx, int enable,
+ int loadconfig);
+int evp_set_default_properties_int(OSSL_LIB_CTX *libctx, const char *propq,
+ int loadconfig, int mirrored);
+char *evp_get_global_properties_str(OSSL_LIB_CTX *libctx, int loadconfig);
+
+void evp_md_ctx_clear_digest(EVP_MD_CTX *ctx, int force, int keep_digest);
+
+/* Three possible states: */
+# define EVP_PKEY_STATE_UNKNOWN 0
+# define EVP_PKEY_STATE_LEGACY 1
+# define EVP_PKEY_STATE_PROVIDER 2
+int evp_pkey_ctx_state(const EVP_PKEY_CTX *ctx);
+
+/* These two must ONLY be called for provider side operations */
+int evp_pkey_ctx_ctrl_to_param(EVP_PKEY_CTX *ctx,
+ int keytype, int optype,
+ int cmd, int p1, void *p2);
+int evp_pkey_ctx_ctrl_str_to_param(EVP_PKEY_CTX *ctx,
+ const char *name, const char *value);
+
+/* These two must ONLY be called for legacy operations */
+int evp_pkey_ctx_set_params_to_ctrl(EVP_PKEY_CTX *ctx, const OSSL_PARAM *params);
+int evp_pkey_ctx_get_params_to_ctrl(EVP_PKEY_CTX *ctx, OSSL_PARAM *params);
+
+/* This must ONLY be called for legacy EVP_PKEYs */
+int evp_pkey_get_params_to_ctrl(const EVP_PKEY *pkey, OSSL_PARAM *params);
+
+/* Same as the public get0 functions but are not const */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+DH *evp_pkey_get0_DH_int(const EVP_PKEY *pkey);
+EC_KEY *evp_pkey_get0_EC_KEY_int(const EVP_PKEY *pkey);
+RSA *evp_pkey_get0_RSA_int(const EVP_PKEY *pkey);
+# endif
+
+/* Get internal identification number routines */
+int evp_asym_cipher_get_number(const EVP_ASYM_CIPHER *cipher);
+int evp_cipher_get_number(const EVP_CIPHER *cipher);
+int evp_kdf_get_number(const EVP_KDF *kdf);
+int evp_kem_get_number(const EVP_KEM *wrap);
+int evp_keyexch_get_number(const EVP_KEYEXCH *keyexch);
+int evp_keymgmt_get_number(const EVP_KEYMGMT *keymgmt);
+int evp_mac_get_number(const EVP_MAC *mac);
+int evp_md_get_number(const EVP_MD *md);
+int evp_rand_get_number(const EVP_RAND *rand);
+int evp_signature_get_number(const EVP_SIGNATURE *signature);
+
+#endif /* OSSL_CRYPTO_EVP_H */
diff --git a/include/crypto/evperr.h b/include/crypto/evperr.h
new file mode 100644
index 000000000000..d90ba83f8b9f
--- /dev/null
+++ b/include/crypto/evperr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_EVPERR_H
+# define OSSL_CRYPTO_EVPERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_EVP_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/httperr.h b/include/crypto/httperr.h
new file mode 100644
index 000000000000..969df17b832b
--- /dev/null
+++ b/include/crypto/httperr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_HTTPERR_H
+# define OSSL_CRYPTO_HTTPERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_HTTP_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/lhash.h b/include/crypto/lhash.h
index ab060cce74b4..0f64869f54ba 100644
--- a/include/crypto/lhash.h
+++ b/include/crypto/lhash.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,7 +9,8 @@
#ifndef OSSL_CRYPTO_LHASH_H
# define OSSL_CRYPTO_LHASH_H
+# pragma once
-unsigned long openssl_lh_strcasehash(const char *);
+unsigned long ossl_lh_strcasehash(const char *);
-#endif
+#endif /* OSSL_CRYPTO_LHASH_H */
diff --git a/include/crypto/md32_common.h b/include/crypto/md32_common.h
index 1124e9c24b2a..3b16f1b7216c 100644
--- a/include/crypto/md32_common.h
+++ b/include/crypto/md32_common.h
@@ -1,7 +1,7 @@
/*
* Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/include/crypto/modes.h b/include/crypto/modes.h
new file mode 100644
index 000000000000..19f9d85959c5
--- /dev/null
+++ b/include/crypto/modes.h
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2010-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* This header can move into provider when legacy support is removed */
+#include <openssl/modes.h>
+
+#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
+typedef __int64 i64;
+typedef unsigned __int64 u64;
+# define U64(C) C##UI64
+#elif defined(__arch64__)
+typedef long i64;
+typedef unsigned long u64;
+# define U64(C) C##UL
+#else
+typedef long long i64;
+typedef unsigned long long u64;
+# define U64(C) C##ULL
+#endif
+
+typedef unsigned int u32;
+typedef unsigned char u8;
+
+#define STRICT_ALIGNMENT 1
+#ifndef PEDANTIC
+# if defined(__i386) || defined(__i386__) || \
+ defined(__x86_64) || defined(__x86_64__) || \
+ defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || \
+ defined(__aarch64__) || \
+ defined(__s390__) || defined(__s390x__)
+# undef STRICT_ALIGNMENT
+# endif
+#endif
+
+#if !defined(PEDANTIC) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
+# if defined(__GNUC__) && __GNUC__>=2
+# if defined(__x86_64) || defined(__x86_64__)
+# define BSWAP8(x) ({ u64 ret_=(x); \
+ asm ("bswapq %0" \
+ : "+r"(ret_)); ret_; })
+# define BSWAP4(x) ({ u32 ret_=(x); \
+ asm ("bswapl %0" \
+ : "+r"(ret_)); ret_; })
+# elif (defined(__i386) || defined(__i386__)) && !defined(I386_ONLY)
+# define BSWAP8(x) ({ u32 lo_=(u64)(x)>>32,hi_=(x); \
+ asm ("bswapl %0; bswapl %1" \
+ : "+r"(hi_),"+r"(lo_)); \
+ (u64)hi_<<32|lo_; })
+# define BSWAP4(x) ({ u32 ret_=(x); \
+ asm ("bswapl %0" \
+ : "+r"(ret_)); ret_; })
+# elif defined(__aarch64__)
+# if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
+ __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
+# define BSWAP8(x) ({ u64 ret_; \
+ asm ("rev %0,%1" \
+ : "=r"(ret_) : "r"(x)); ret_; })
+# define BSWAP4(x) ({ u32 ret_; \
+ asm ("rev %w0,%w1" \
+ : "=r"(ret_) : "r"(x)); ret_; })
+# endif
+# elif (defined(__arm__) || defined(__arm)) && !defined(STRICT_ALIGNMENT)
+# define BSWAP8(x) ({ u32 lo_=(u64)(x)>>32,hi_=(x); \
+ asm ("rev %0,%0; rev %1,%1" \
+ : "+r"(hi_),"+r"(lo_)); \
+ (u64)hi_<<32|lo_; })
+# define BSWAP4(x) ({ u32 ret_; \
+ asm ("rev %0,%1" \
+ : "=r"(ret_) : "r"((u32)(x))); \
+ ret_; })
+# endif
+# elif defined(_MSC_VER)
+# if _MSC_VER>=1300
+# include <stdlib.h>
+# pragma intrinsic(_byteswap_uint64,_byteswap_ulong)
+# define BSWAP8(x) _byteswap_uint64((u64)(x))
+# define BSWAP4(x) _byteswap_ulong((u32)(x))
+# elif defined(_M_IX86)
+__inline u32 _bswap4(u32 val)
+{
+_asm mov eax, val _asm bswap eax}
+# define BSWAP4(x) _bswap4(x)
+# endif
+# endif
+#endif
+#if defined(BSWAP4) && !defined(STRICT_ALIGNMENT)
+# define GETU32(p) BSWAP4(*(const u32 *)(p))
+# define PUTU32(p,v) *(u32 *)(p) = BSWAP4(v)
+#else
+# define GETU32(p) ((u32)(p)[0]<<24|(u32)(p)[1]<<16|(u32)(p)[2]<<8|(u32)(p)[3])
+# define PUTU32(p,v) ((p)[0]=(u8)((v)>>24),(p)[1]=(u8)((v)>>16),(p)[2]=(u8)((v)>>8),(p)[3]=(u8)(v))
+#endif
+/*- GCM definitions */ typedef struct {
+ u64 hi, lo;
+} u128;
+
+#ifdef TABLE_BITS
+# undef TABLE_BITS
+#endif
+/*
+ * Even though permitted values for TABLE_BITS are 8, 4 and 1, it should
+ * never be set to 8 [or 1]. For further information see gcm128.c.
+ */
+#define TABLE_BITS 4
+
+struct gcm128_context {
+ /* Following 6 names follow names in GCM specification */
+ union {
+ u64 u[2];
+ u32 d[4];
+ u8 c[16];
+ size_t t[16 / sizeof(size_t)];
+ } Yi, EKi, EK0, len, Xi, H;
+ /*
+ * Relative position of Xi, H and pre-computed Htable is used in some
+ * assembler modules, i.e. don't change the order!
+ */
+#if TABLE_BITS==8
+ u128 Htable[256];
+#else
+ u128 Htable[16];
+ void (*gmult) (u64 Xi[2], const u128 Htable[16]);
+ void (*ghash) (u64 Xi[2], const u128 Htable[16], const u8 *inp,
+ size_t len);
+#endif
+ unsigned int mres, ares;
+ block128_f block;
+ void *key;
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+ unsigned char Xn[48];
+#endif
+};
+
+/*
+ * The maximum permitted number of cipher blocks per data unit in XTS mode.
+ * Reference IEEE Std 1619-2018.
+ */
+#define XTS_MAX_BLOCKS_PER_DATA_UNIT (1<<20)
+
+struct xts128_context {
+ void *key1, *key2;
+ block128_f block1, block2;
+};
+
+struct ccm128_context {
+ union {
+ u64 u[2];
+ u8 c[16];
+ } nonce, cmac;
+ u64 blocks;
+ block128_f block;
+ void *key;
+};
+
+#ifndef OPENSSL_NO_OCB
+
+typedef union {
+ u64 a[2];
+ unsigned char c[16];
+} OCB_BLOCK;
+# define ocb_block16_xor(in1,in2,out) \
+ ( (out)->a[0]=(in1)->a[0]^(in2)->a[0], \
+ (out)->a[1]=(in1)->a[1]^(in2)->a[1] )
+# if STRICT_ALIGNMENT
+# define ocb_block16_xor_misaligned(in1,in2,out) \
+ ocb_block_xor((in1)->c,(in2)->c,16,(out)->c)
+# else
+# define ocb_block16_xor_misaligned ocb_block16_xor
+# endif
+
+struct ocb128_context {
+ /* Need both encrypt and decrypt key schedules for decryption */
+ block128_f encrypt;
+ block128_f decrypt;
+ void *keyenc;
+ void *keydec;
+ ocb128_f stream; /* direction dependent */
+ /* Key dependent variables. Can be reused if key remains the same */
+ size_t l_index;
+ size_t max_l_index;
+ OCB_BLOCK l_star;
+ OCB_BLOCK l_dollar;
+ OCB_BLOCK *l;
+ /* Must be reset for each session */
+ struct {
+ u64 blocks_hashed;
+ u64 blocks_processed;
+ OCB_BLOCK offset_aad;
+ OCB_BLOCK sum;
+ OCB_BLOCK offset;
+ OCB_BLOCK checksum;
+ } sess;
+};
+#endif /* OPENSSL_NO_OCB */
+
+#ifndef OPENSSL_NO_SIV
+
+#define SIV_LEN 16
+
+typedef union siv_block_u {
+ uint64_t word[SIV_LEN/sizeof(uint64_t)];
+ unsigned char byte[SIV_LEN];
+} SIV_BLOCK;
+
+struct siv128_context {
+ /* d stores intermediate results of S2V; it corresponds to D from the
+ pseudocode in section 2.4 of RFC 5297. */
+ SIV_BLOCK d;
+ SIV_BLOCK tag;
+ EVP_CIPHER_CTX *cipher_ctx;
+ EVP_MAC *mac;
+ EVP_MAC_CTX *mac_ctx_init;
+ int final_ret;
+ int crypto_ok;
+};
+
+#endif /* OPENSSL_NO_SIV */
diff --git a/include/crypto/objects.h b/include/crypto/objects.h
index 76e1b4d98838..f22e9287723a 100644
--- a/include/crypto/objects.h
+++ b/include/crypto/objects.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,4 +9,4 @@
#include <openssl/objects.h>
-void obj_cleanup_int(void);
+void ossl_obj_cleanup_int(void);
diff --git a/include/crypto/objectserr.h b/include/crypto/objectserr.h
new file mode 100644
index 000000000000..ec9948241c35
--- /dev/null
+++ b/include/crypto/objectserr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_OBJECTSERR_H
+# define OSSL_CRYPTO_OBJECTSERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_OBJ_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/ocsperr.h b/include/crypto/ocsperr.h
new file mode 100644
index 000000000000..f9529b2a2f72
--- /dev/null
+++ b/include/crypto/ocsperr.h
@@ -0,0 +1,30 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_OCSPERR_H
+# define OSSL_CRYPTO_OCSPERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# ifndef OPENSSL_NO_OCSP
+
+int ossl_err_load_OCSP_strings(void);
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/pem.h b/include/crypto/pem.h
new file mode 100644
index 000000000000..2cb4253d6a14
--- /dev/null
+++ b/include/crypto/pem.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_PEM_H
+# define OSSL_INTERNAL_PEM_H
+# pragma once
+
+# include <openssl/pem.h>
+# include "crypto/types.h"
+
+/* Found in crypto/pem/pvkfmt.c */
+
+/* Maximum length of a blob after header */
+# define BLOB_MAX_LENGTH 102400
+
+int ossl_do_blob_header(const unsigned char **in, unsigned int length,
+ unsigned int *pmagic, unsigned int *pbitlen,
+ int *pisdss, int *pispub);
+unsigned int ossl_blob_length(unsigned bitlen, int isdss, int ispub);
+int ossl_do_PVK_header(const unsigned char **in, unsigned int length,
+ int skip_magic,
+ unsigned int *psaltlen, unsigned int *pkeylen);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef OPENSSL_NO_DSA
+DSA *ossl_b2i_DSA_after_header(const unsigned char **in, unsigned int bitlen,
+ int ispub);
+# endif
+RSA *ossl_b2i_RSA_after_header(const unsigned char **in, unsigned int bitlen,
+ int ispub);
+# endif
+EVP_PKEY *ossl_b2i(const unsigned char **in, unsigned int length, int *ispub);
+EVP_PKEY *ossl_b2i_bio(BIO *in, int *ispub);
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef OPENSSL_NO_DSA
+DSA *b2i_DSA_PVK_bio(BIO *in, pem_password_cb *cb, void *u);
+DSA *b2i_DSA_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
+# endif
+RSA *b2i_RSA_PVK_bio(BIO *in, pem_password_cb *cb, void *u);
+RSA *b2i_RSA_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
+# endif
+
+#endif
diff --git a/include/crypto/pemerr.h b/include/crypto/pemerr.h
new file mode 100644
index 000000000000..b255ff5c6488
--- /dev/null
+++ b/include/crypto/pemerr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_PEMERR_H
+# define OSSL_CRYPTO_PEMERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_PEM_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/pkcs12err.h b/include/crypto/pkcs12err.h
new file mode 100644
index 000000000000..662f412e97c5
--- /dev/null
+++ b/include/crypto/pkcs12err.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_PKCS12ERR_H
+# define OSSL_CRYPTO_PKCS12ERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_PKCS12_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h
new file mode 100644
index 000000000000..9caa9af4a25f
--- /dev/null
+++ b/include/crypto/pkcs7.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_PKCS7_H
+# define OSSL_CRYPTO_PKCS7_H
+# pragma once
+
+void ossl_pkcs7_resolve_libctx(PKCS7 *p7);
+
+void ossl_pkcs7_set0_libctx(PKCS7 *p7, OSSL_LIB_CTX *ctx);
+int ossl_pkcs7_set1_propq(PKCS7 *p7, const char *propq);
+
+#endif
diff --git a/include/crypto/pkcs7err.h b/include/crypto/pkcs7err.h
new file mode 100644
index 000000000000..c195190bf8f6
--- /dev/null
+++ b/include/crypto/pkcs7err.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_PKCS7ERR_H
+# define OSSL_CRYPTO_PKCS7ERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_PKCS7_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/poly1305.h b/include/crypto/poly1305.h
index 5fef239d0f8f..ba54f3bdcbe1 100644
--- a/include/crypto/poly1305.h
+++ b/include/crypto/poly1305.h
@@ -1,12 +1,16 @@
/*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#ifndef OSSL_CRYPTO_POLY1305_H
+# define OSSL_CRYPTO_POLY1305_H
+# pragma once
+
#include <stddef.h>
#define POLY1305_BLOCK_SIZE 16
@@ -15,7 +19,28 @@
typedef struct poly1305_context POLY1305;
+typedef void (*poly1305_blocks_f) (void *ctx, const unsigned char *inp,
+ size_t len, unsigned int padbit);
+typedef void (*poly1305_emit_f) (void *ctx, unsigned char mac[16],
+ const unsigned int nonce[4]);
+
+struct poly1305_context {
+ double opaque[24]; /* large enough to hold internal state, declared
+ * 'double' to ensure at least 64-bit invariant
+ * alignment across all platforms and
+ * configurations */
+ unsigned int nonce[4];
+ unsigned char data[POLY1305_BLOCK_SIZE];
+ size_t num;
+ struct {
+ poly1305_blocks_f blocks;
+ poly1305_emit_f emit;
+ } func;
+};
+
size_t Poly1305_ctx_size(void);
void Poly1305_Init(POLY1305 *ctx, const unsigned char key[32]);
void Poly1305_Update(POLY1305 *ctx, const unsigned char *inp, size_t len);
void Poly1305_Final(POLY1305 *ctx, unsigned char mac[16]);
+
+#endif /* OSSL_CRYPTO_POLY1305_H */
diff --git a/include/crypto/ppc_arch.h b/include/crypto/ppc_arch.h
new file mode 100644
index 000000000000..3b3ce4bff50a
--- /dev/null
+++ b/include/crypto/ppc_arch.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_PPC_ARCH_H
+# define OSSL_CRYPTO_PPC_ARCH_H
+
+extern unsigned int OPENSSL_ppccap_P;
+
+/*
+ * Flags' usage can appear ambiguous, because they are set rather
+ * to reflect OpenSSL performance preferences than actual processor
+ * capabilities.
+ */
+# define PPC_FPU64 (1<<0)
+# define PPC_ALTIVEC (1<<1)
+# define PPC_CRYPTO207 (1<<2)
+# define PPC_FPU (1<<3)
+# define PPC_MADD300 (1<<4)
+# define PPC_MFTB (1<<5)
+# define PPC_MFSPR268 (1<<6)
+
+#endif
diff --git a/include/crypto/punycode.h b/include/crypto/punycode.h
new file mode 100644
index 000000000000..133826d87e1b
--- /dev/null
+++ b/include/crypto/punycode.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_PUNYCODE_H
+# define OSSL_CRYPTO_PUNYCODE_H
+# pragma once
+
+int ossl_punycode_decode (
+ const char *pEncoded,
+ const size_t enc_len,
+ unsigned int *pDecoded,
+ unsigned int *pout_length
+);
+
+int ossl_a2ulabel(const char *in, char *out, size_t *outlen);
+
+int ossl_a2ucompare(const char *a, const char *u);
+#endif
diff --git a/include/crypto/rand.h b/include/crypto/rand.h
index 9e02bb0e504b..165deaf95c5e 100644
--- a/include/crypto/rand.h
+++ b/include/crypto/rand.h
@@ -1,14 +1,14 @@
/*
- * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
- * Licensed under the OpenSSL licenses, (the "License");
+ * Licensed under the Apache License 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* https://www.openssl.org/source/license.html
@@ -17,8 +17,10 @@
#ifndef OSSL_CRYPTO_RAND_H
# define OSSL_CRYPTO_RAND_H
+# pragma once
# include <openssl/rand.h>
+# include "crypto/rand_pool.h"
# if defined(__APPLE__) && !defined(OPENSSL_NO_APPLE_CRYPTO_RANDOM)
# include <Availability.h>
@@ -30,115 +32,98 @@
# endif
# endif
-/* forward declaration */
-typedef struct rand_pool_st RAND_POOL;
-
-void rand_cleanup_int(void);
-void rand_drbg_cleanup_int(void);
-void drbg_delete_thread_state(void);
-
-/* Hardware-based seeding functions. */
-size_t rand_acquire_entropy_from_tsc(RAND_POOL *pool);
-size_t rand_acquire_entropy_from_cpu(RAND_POOL *pool);
-
-/* DRBG entropy callbacks. */
-size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
- unsigned char **pout,
- int entropy, size_t min_len, size_t max_len,
- int prediction_resistance);
-void rand_drbg_cleanup_entropy(RAND_DRBG *drbg,
- unsigned char *out, size_t outlen);
-size_t rand_drbg_get_nonce(RAND_DRBG *drbg,
- unsigned char **pout,
- int entropy, size_t min_len, size_t max_len);
-void rand_drbg_cleanup_nonce(RAND_DRBG *drbg,
- unsigned char *out, size_t outlen);
-
-size_t rand_drbg_get_additional_data(RAND_POOL *pool, unsigned char **pout);
-
-void rand_drbg_cleanup_additional_data(RAND_POOL *pool, unsigned char *out);
-
/*
- * RAND_POOL functions
+ * Defines related to seed sources
*/
-RAND_POOL *rand_pool_new(int entropy_requested, int secure,
- size_t min_len, size_t max_len);
-RAND_POOL *rand_pool_attach(const unsigned char *buffer, size_t len,
- size_t entropy);
-void rand_pool_free(RAND_POOL *pool);
-
-const unsigned char *rand_pool_buffer(RAND_POOL *pool);
-unsigned char *rand_pool_detach(RAND_POOL *pool);
-void rand_pool_reattach(RAND_POOL *pool, unsigned char *buffer);
-
-size_t rand_pool_entropy(RAND_POOL *pool);
-size_t rand_pool_length(RAND_POOL *pool);
-
-size_t rand_pool_entropy_available(RAND_POOL *pool);
-size_t rand_pool_entropy_needed(RAND_POOL *pool);
-/* |entropy_factor| expresses how many bits of data contain 1 bit of entropy */
-size_t rand_pool_bytes_needed(RAND_POOL *pool, unsigned int entropy_factor);
-size_t rand_pool_bytes_remaining(RAND_POOL *pool);
-
-int rand_pool_add(RAND_POOL *pool,
- const unsigned char *buffer, size_t len, size_t entropy);
-unsigned char *rand_pool_add_begin(RAND_POOL *pool, size_t len);
-int rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy);
-
-
+#ifndef DEVRANDOM
/*
- * Add random bytes to the pool to acquire requested amount of entropy
- *
- * This function is platform specific and tries to acquire the requested
- * amount of entropy by polling platform specific entropy sources.
- *
- * If the function succeeds in acquiring at least |entropy_requested| bits
- * of entropy, the total entropy count is returned. If it fails, it returns
- * an entropy count of 0.
+ * set this to a comma-separated list of 'random' device files to try out. By
+ * default, we will try to read at least one of these files
*/
-size_t rand_pool_acquire_entropy(RAND_POOL *pool);
-
+# define DEVRANDOM "/dev/urandom", "/dev/random", "/dev/hwrng", "/dev/srandom"
+# if defined(__linux) && !defined(__ANDROID__)
+# ifndef DEVRANDOM_WAIT
+# define DEVRANDOM_WAIT "/dev/random"
+# endif
/*
- * Add some application specific nonce data
- *
- * This function is platform specific and adds some application specific
- * data to the nonce used for instantiating the drbg.
- *
- * This data currently consists of the process and thread id, and a high
- * resolution timestamp. The data does not include an atomic counter,
- * because that is added by the calling function rand_drbg_get_nonce().
- *
- * Returns 1 on success and 0 on failure.
+ * Linux kernels 4.8 and later changes how their random device works and there
+ * is no reliable way to tell that /dev/urandom has been seeded -- getentropy(2)
+ * should be used instead.
*/
-int rand_pool_add_nonce_data(RAND_POOL *pool);
+# ifndef DEVRANDOM_SAFE_KERNEL
+# define DEVRANDOM_SAFE_KERNEL 4, 8
+# endif
+/*
+ * Some operating systems do not permit select(2) on their random devices,
+ * defining this to zero will force the use of read(2) to extract one byte
+ * from /dev/random.
+ */
+# ifndef DEVRANDM_WAIT_USE_SELECT
+# define DEVRANDM_WAIT_USE_SELECT 1
+# endif
+/*
+ * Define the shared memory identifier used to indicate if the operating
+ * system has properly seeded the DEVRANDOM source.
+ */
+# ifndef OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID
+# define OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID 114
+# endif
+# endif
+#endif
+#if !defined(OPENSSL_NO_EGD) && !defined(DEVRANDOM_EGD)
/*
- * Add some platform specific additional data
- *
- * This function is platform specific and adds some random noise to the
- * additional data used for generating random bytes and for reseeding
- * the drbg.
- *
- * Returns 1 on success and 0 on failure.
+ * set this to a comma-separated list of 'egd' sockets to try out. These
+ * sockets will be tried in the order listed in case accessing the device
+ * files listed in DEVRANDOM did not return enough randomness.
*/
-int rand_pool_add_additional_data(RAND_POOL *pool);
+# define DEVRANDOM_EGD "/var/run/egd-pool", "/dev/egd-pool", "/etc/egd-pool", "/etc/entropy"
+#endif
+
+void ossl_rand_cleanup_int(void);
/*
* Initialise the random pool reseeding sources.
*
* Returns 1 on success and 0 on failure.
*/
-int rand_pool_init(void);
+int ossl_rand_pool_init(void);
/*
* Finalise the random pool reseeding sources.
*/
-void rand_pool_cleanup(void);
+void ossl_rand_pool_cleanup(void);
/*
* Control the random pool use of open file descriptors.
*/
-void rand_pool_keep_random_devices_open(int keep);
+void ossl_rand_pool_keep_random_devices_open(int keep);
+
+/*
+ * Configuration
+ */
+void ossl_random_add_conf_module(void);
+
+/*
+ * Get and cleanup random seed material.
+ */
+size_t ossl_rand_get_entropy(ossl_unused const OSSL_CORE_HANDLE *handle,
+ unsigned char **pout, int entropy,
+ size_t min_len, size_t max_len);
+void ossl_rand_cleanup_entropy(ossl_unused const OSSL_CORE_HANDLE *handle,
+ unsigned char *buf, size_t len);
+size_t ossl_rand_get_nonce(ossl_unused const OSSL_CORE_HANDLE *handle,
+ unsigned char **pout, size_t min_len, size_t max_len,
+ const void *salt, size_t salt_len);
+void ossl_rand_cleanup_nonce(ossl_unused const OSSL_CORE_HANDLE *handle,
+ unsigned char *buf, size_t len);
+
+/*
+ * Get seeding material from the operating system sources.
+ */
+size_t ossl_pool_acquire_entropy(RAND_POOL *pool);
+int ossl_pool_add_nonce_data(RAND_POOL *pool);
+void ossl_rand_ctx_free(void *vdgbl);
#endif
diff --git a/include/crypto/rand_pool.h b/include/crypto/rand_pool.h
new file mode 100644
index 000000000000..f4d1d954bc80
--- /dev/null
+++ b/include/crypto/rand_pool.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_PROVIDER_RAND_POOL_H
+# define OSSL_PROVIDER_RAND_POOL_H
+# pragma once
+
+# include <stdio.h>
+# include <openssl/rand.h>
+
+/*
+ * Maximum allocation size for RANDOM_POOL buffers
+ *
+ * The max_len value for the buffer provided to the rand_drbg_get_entropy()
+ * callback is currently 2^31 bytes (2 gigabytes), if a derivation function
+ * is used. Since this is much too large to be allocated, the ossl_rand_pool_new()
+ * function chooses more modest values as default pool length, bounded
+ * by RAND_POOL_MIN_LENGTH and RAND_POOL_MAX_LENGTH
+ *
+ * The choice of the RAND_POOL_FACTOR is large enough such that the
+ * RAND_POOL can store a random input which has a lousy entropy rate of
+ * 8/256 (= 0.03125) bits per byte. This input will be sent through the
+ * derivation function which 'compresses' the low quality input into a
+ * high quality output.
+ *
+ * The factor 1.5 below is the pessimistic estimate for the extra amount
+ * of entropy required when no get_nonce() callback is defined.
+ */
+# define RAND_POOL_FACTOR 256
+# define RAND_POOL_MAX_LENGTH (RAND_POOL_FACTOR * \
+ 3 * (RAND_DRBG_STRENGTH / 16))
+/*
+ * = (RAND_POOL_FACTOR * \
+ * 1.5 * (RAND_DRBG_STRENGTH / 8))
+ */
+
+/*
+ * Initial allocation minimum.
+ *
+ * There is a distinction between the secure and normal allocation minimums.
+ * Ideally, the secure allocation size should be a power of two. The normal
+ * allocation size doesn't have any such restriction.
+ *
+ * The secure value is based on 128 bits of secure material, which is 16 bytes.
+ * Typically, the DRBGs will set a minimum larger than this so optimal
+ * allocation ought to take place (for full quality seed material).
+ *
+ * The normal value has been chosen by noticing that the rand_drbg_get_nonce
+ * function is usually the largest of the built in allocation (twenty four
+ * bytes and then appending another sixteen bytes). This means the buffer ends
+ * with 40 bytes. The value of forty eight is comfortably above this which
+ * allows some slack in the platform specific values used.
+ */
+# define RAND_POOL_MIN_ALLOCATION(secure) ((secure) ? 16 : 48)
+
+/*
+ * The 'random pool' acts as a dumb container for collecting random
+ * input from various entropy sources. It is the callers duty to 1) initialize
+ * the random pool, 2) pass it to the polling callbacks, 3) seed the RNG, and
+ * 4) cleanup the random pool again.
+ *
+ * The random pool contains no locking mechanism because its scope and
+ * lifetime is intended to be restricted to a single stack frame.
+ */
+typedef struct rand_pool_st {
+ unsigned char *buffer; /* points to the beginning of the random pool */
+ size_t len; /* current number of random bytes contained in the pool */
+
+ int attached; /* true pool was attached to existing buffer */
+ int secure; /* 1: allocated on the secure heap, 0: otherwise */
+
+ size_t min_len; /* minimum number of random bytes requested */
+ size_t max_len; /* maximum number of random bytes (allocated buffer size) */
+ size_t alloc_len; /* current number of bytes allocated */
+ size_t entropy; /* current entropy count in bits */
+ size_t entropy_requested; /* requested entropy count in bits */
+} RAND_POOL;
+
+RAND_POOL *ossl_rand_pool_new(int entropy_requested, int secure,
+ size_t min_len, size_t max_len);
+RAND_POOL *ossl_rand_pool_attach(const unsigned char *buffer, size_t len,
+ size_t entropy);
+void ossl_rand_pool_free(RAND_POOL *pool);
+
+const unsigned char *ossl_rand_pool_buffer(RAND_POOL *pool);
+unsigned char *ossl_rand_pool_detach(RAND_POOL *pool);
+void ossl_rand_pool_reattach(RAND_POOL *pool, unsigned char *buffer);
+
+size_t ossl_rand_pool_entropy(RAND_POOL *pool);
+size_t ossl_rand_pool_length(RAND_POOL *pool);
+
+size_t ossl_rand_pool_entropy_available(RAND_POOL *pool);
+size_t ossl_rand_pool_entropy_needed(RAND_POOL *pool);
+/* |entropy_factor| expresses how many bits of data contain 1 bit of entropy */
+size_t ossl_rand_pool_bytes_needed(RAND_POOL *pool, unsigned int entropy_factor);
+size_t ossl_rand_pool_bytes_remaining(RAND_POOL *pool);
+
+int ossl_rand_pool_add(RAND_POOL *pool,
+ const unsigned char *buffer, size_t len, size_t entropy);
+unsigned char *ossl_rand_pool_add_begin(RAND_POOL *pool, size_t len);
+int ossl_rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy);
+
+#endif /* OSSL_PROVIDER_RAND_POOL_H */
diff --git a/include/crypto/randerr.h b/include/crypto/randerr.h
new file mode 100644
index 000000000000..832a8b7d36f5
--- /dev/null
+++ b/include/crypto/randerr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_RANDERR_H
+# define OSSL_CRYPTO_RANDERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_RAND_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/rsa.h b/include/crypto/rsa.h
new file mode 100644
index 000000000000..949873d0ee38
--- /dev/null
+++ b/include/crypto/rsa.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_RSA_H
+# define OSSL_INTERNAL_RSA_H
+# pragma once
+
+# include <openssl/core.h>
+# include <openssl/rsa.h>
+# include "crypto/types.h"
+
+#define RSA_MIN_MODULUS_BITS 512
+
+typedef struct rsa_pss_params_30_st {
+ int hash_algorithm_nid;
+ struct {
+ int algorithm_nid; /* Currently always NID_mgf1 */
+ int hash_algorithm_nid;
+ } mask_gen;
+ int salt_len;
+ int trailer_field;
+} RSA_PSS_PARAMS_30;
+
+RSA_PSS_PARAMS_30 *ossl_rsa_get0_pss_params_30(RSA *r);
+int ossl_rsa_pss_params_30_set_defaults(RSA_PSS_PARAMS_30 *rsa_pss_params);
+int ossl_rsa_pss_params_30_copy(RSA_PSS_PARAMS_30 *to,
+ const RSA_PSS_PARAMS_30 *from);
+int ossl_rsa_pss_params_30_is_unrestricted(const RSA_PSS_PARAMS_30 *rsa_pss_params);
+int ossl_rsa_pss_params_30_set_hashalg(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int hashalg_nid);
+int ossl_rsa_pss_params_30_set_maskgenalg(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int maskgenalg_nid);
+int ossl_rsa_pss_params_30_set_maskgenhashalg(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int maskgenhashalg_nid);
+int ossl_rsa_pss_params_30_set_saltlen(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int saltlen);
+int ossl_rsa_pss_params_30_set_trailerfield(RSA_PSS_PARAMS_30 *rsa_pss_params,
+ int trailerfield);
+int ossl_rsa_pss_params_30_hashalg(const RSA_PSS_PARAMS_30 *rsa_pss_params);
+int ossl_rsa_pss_params_30_maskgenalg(const RSA_PSS_PARAMS_30 *rsa_pss_params);
+int ossl_rsa_pss_params_30_maskgenhashalg(const RSA_PSS_PARAMS_30 *rsa_pss_params);
+int ossl_rsa_pss_params_30_saltlen(const RSA_PSS_PARAMS_30 *rsa_pss_params);
+int ossl_rsa_pss_params_30_trailerfield(const RSA_PSS_PARAMS_30 *rsa_pss_params);
+
+const char *ossl_rsa_mgf_nid2name(int mgf);
+int ossl_rsa_oaeppss_md2nid(const EVP_MD *md);
+const char *ossl_rsa_oaeppss_nid2name(int md);
+
+RSA *ossl_rsa_new_with_ctx(OSSL_LIB_CTX *libctx);
+OSSL_LIB_CTX *ossl_rsa_get0_libctx(RSA *r);
+void ossl_rsa_set0_libctx(RSA *r, OSSL_LIB_CTX *libctx);
+
+int ossl_rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes,
+ const STACK_OF(BIGNUM) *exps,
+ const STACK_OF(BIGNUM) *coeffs);
+int ossl_rsa_get0_all_params(RSA *r, STACK_OF(BIGNUM_const) *primes,
+ STACK_OF(BIGNUM_const) *exps,
+ STACK_OF(BIGNUM_const) *coeffs);
+int ossl_rsa_is_foreign(const RSA *rsa);
+RSA *ossl_rsa_dup(const RSA *rsa, int selection);
+
+int ossl_rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[],
+ int include_private);
+int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[], int include_private);
+int ossl_rsa_pss_params_30_todata(const RSA_PSS_PARAMS_30 *pss,
+ OSSL_PARAM_BLD *bld, OSSL_PARAM params[]);
+int ossl_rsa_pss_params_30_fromdata(RSA_PSS_PARAMS_30 *pss_params,
+ int *defaults_set,
+ const OSSL_PARAM params[],
+ OSSL_LIB_CTX *libctx);
+int ossl_rsa_set0_pss_params(RSA *r, RSA_PSS_PARAMS *pss);
+int ossl_rsa_pss_get_param_unverified(const RSA_PSS_PARAMS *pss,
+ const EVP_MD **pmd, const EVP_MD **pmgf1md,
+ int *psaltlen, int *ptrailerField);
+RSA_PSS_PARAMS *ossl_rsa_pss_decode(const X509_ALGOR *alg);
+int ossl_rsa_param_decode(RSA *rsa, const X509_ALGOR *alg);
+RSA *ossl_rsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+int ossl_rsa_padding_check_PKCS1_type_2_TLS(OSSL_LIB_CTX *ctx, unsigned char *to,
+ size_t tlen,
+ const unsigned char *from,
+ size_t flen, int client_version,
+ int alt_version);
+int ossl_rsa_padding_add_PKCS1_OAEP_mgf1_ex(OSSL_LIB_CTX *libctx,
+ unsigned char *to, int tlen,
+ const unsigned char *from, int flen,
+ const unsigned char *param,
+ int plen, const EVP_MD *md,
+ const EVP_MD *mgf1md);
+
+int ossl_rsa_validate_public(const RSA *key);
+int ossl_rsa_validate_private(const RSA *key);
+int ossl_rsa_validate_pairwise(const RSA *key);
+
+int ossl_rsa_verify(int dtype, const unsigned char *m,
+ unsigned int m_len, unsigned char *rm,
+ size_t *prm_len, const unsigned char *sigbuf,
+ size_t siglen, RSA *rsa);
+
+const unsigned char *ossl_rsa_digestinfo_encoding(int md_nid, size_t *len);
+
+extern const char *ossl_rsa_mp_factor_names[];
+extern const char *ossl_rsa_mp_exp_names[];
+extern const char *ossl_rsa_mp_coeff_names[];
+
+ASN1_STRING *ossl_rsa_ctx_to_pss_string(EVP_PKEY_CTX *pkctx);
+int ossl_rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
+ const X509_ALGOR *sigalg, EVP_PKEY *pkey);
+
+# if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+int ossl_rsa_acvp_test_gen_params_new(OSSL_PARAM **dst, const OSSL_PARAM src[]);
+void ossl_rsa_acvp_test_gen_params_free(OSSL_PARAM *dst);
+
+int ossl_rsa_acvp_test_set_params(RSA *r, const OSSL_PARAM params[]);
+int ossl_rsa_acvp_test_get_params(RSA *r, OSSL_PARAM params[]);
+typedef struct rsa_acvp_test_st RSA_ACVP_TEST;
+void ossl_rsa_acvp_test_free(RSA_ACVP_TEST *t);
+# else
+# define RSA_ACVP_TEST void
+# endif
+
+RSA *evp_pkey_get1_RSA_PSS(EVP_PKEY *pkey);
+#endif
diff --git a/include/crypto/rsaerr.h b/include/crypto/rsaerr.h
new file mode 100644
index 000000000000..9b23500b3708
--- /dev/null
+++ b/include/crypto/rsaerr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_RSAERR_H
+# define OSSL_CRYPTO_RSAERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_RSA_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/security_bits.h b/include/crypto/security_bits.h
new file mode 100644
index 000000000000..58f49681dc63
--- /dev/null
+++ b/include/crypto/security_bits.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_SECURITY_BITS_H
+# define OSSL_SECURITY_BITS_H
+# pragma once
+
+uint16_t ossl_ifc_ffc_compute_security_bits(int n);
+
+#endif
diff --git a/include/crypto/sha.h b/include/crypto/sha.h
index 6d15edb9e57e..64305d1790b2 100644
--- a/include/crypto/sha.h
+++ b/include/crypto/sha.h
@@ -1,8 +1,8 @@
/*
- * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,10 +10,13 @@
#ifndef OSSL_CRYPTO_SHA_H
# define OSSL_CRYPTO_SHA_H
+# pragma once
-# include <openssl/opensslconf.h>
+# include <openssl/sha.h>
int sha512_224_init(SHA512_CTX *);
int sha512_256_init(SHA512_CTX *);
+int ossl_sha1_ctrl(SHA_CTX *ctx, int cmd, int mslen, void *ms);
+unsigned char *ossl_sha1(const unsigned char *d, size_t n, unsigned char *md);
#endif
diff --git a/include/crypto/siphash.h b/include/crypto/siphash.h
index 9573680f0f15..0d0767fcf481 100644
--- a/include/crypto/siphash.h
+++ b/include/crypto/siphash.h
@@ -1,18 +1,22 @@
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <stddef.h>
+#ifndef OSSL_CRYPTO_SIPHASH_H
+# define OSSL_CRYPTO_SIPHASH_H
+# pragma once
-#define SIPHASH_BLOCK_SIZE 8
-#define SIPHASH_KEY_SIZE 16
-#define SIPHASH_MIN_DIGEST_SIZE 8
-#define SIPHASH_MAX_DIGEST_SIZE 16
+# include <stddef.h>
+
+# define SIPHASH_BLOCK_SIZE 8
+# define SIPHASH_KEY_SIZE 16
+# define SIPHASH_MIN_DIGEST_SIZE 8
+# define SIPHASH_MAX_DIGEST_SIZE 16
typedef struct siphash_st SIPHASH;
@@ -23,3 +27,24 @@ int SipHash_Init(SIPHASH *ctx, const unsigned char *k,
int crounds, int drounds);
void SipHash_Update(SIPHASH *ctx, const unsigned char *in, size_t inlen);
int SipHash_Final(SIPHASH *ctx, unsigned char *out, size_t outlen);
+
+/* Based on https://131002.net/siphash C reference implementation */
+
+struct siphash_st {
+ uint64_t total_inlen;
+ uint64_t v0;
+ uint64_t v1;
+ uint64_t v2;
+ uint64_t v3;
+ unsigned int len;
+ unsigned int hash_size;
+ unsigned int crounds;
+ unsigned int drounds;
+ unsigned char leavings[SIPHASH_BLOCK_SIZE];
+};
+
+/* default: SipHash-2-4 */
+# define SIPHASH_C_ROUNDS 2
+# define SIPHASH_D_ROUNDS 4
+
+#endif
diff --git a/include/crypto/siv.h b/include/crypto/siv.h
new file mode 100644
index 000000000000..8dc58bd32106
--- /dev/null
+++ b/include/crypto/siv.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_NO_SIV
+
+typedef struct siv128_context SIV128_CONTEXT;
+
+SIV128_CONTEXT *ossl_siv128_new(const unsigned char *key, int klen,
+ EVP_CIPHER *cbc, EVP_CIPHER *ctr,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int ossl_siv128_init(SIV128_CONTEXT *ctx, const unsigned char *key, int klen,
+ const EVP_CIPHER *cbc, const EVP_CIPHER *ctr,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int ossl_siv128_copy_ctx(SIV128_CONTEXT *dest, SIV128_CONTEXT *src);
+int ossl_siv128_aad(SIV128_CONTEXT *ctx, const unsigned char *aad, size_t len);
+int ossl_siv128_encrypt(SIV128_CONTEXT *ctx,
+ const unsigned char *in, unsigned char *out, size_t len);
+int ossl_siv128_decrypt(SIV128_CONTEXT *ctx,
+ const unsigned char *in, unsigned char *out, size_t len);
+int ossl_siv128_finish(SIV128_CONTEXT *ctx);
+int ossl_siv128_set_tag(SIV128_CONTEXT *ctx, const unsigned char *tag,
+ size_t len);
+int ossl_siv128_get_tag(SIV128_CONTEXT *ctx, unsigned char *tag, size_t len);
+int ossl_siv128_cleanup(SIV128_CONTEXT *ctx);
+int ossl_siv128_speed(SIV128_CONTEXT *ctx, int arg);
+
+#endif /* OPENSSL_NO_SIV */
diff --git a/include/crypto/sm2.h b/include/crypto/sm2.h
index a7f5548c0843..9ab6c0b72236 100644
--- a/include/crypto/sm2.h
+++ b/include/crypto/sm2.h
@@ -3,7 +3,7 @@
* Copyright 2017 Ribose Inc. All Rights Reserved.
* Ported from Ribose contributions from Botan.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,67 +11,76 @@
#ifndef OSSL_CRYPTO_SM2_H
# define OSSL_CRYPTO_SM2_H
+# pragma once
+
# include <openssl/opensslconf.h>
-# ifndef OPENSSL_NO_SM2
+# if !defined(OPENSSL_NO_SM2) && !defined(FIPS_MODULE)
# include <openssl/ec.h>
+# include "crypto/types.h"
+
+int ossl_sm2_key_private_check(const EC_KEY *eckey);
/* The default user id as specified in GM/T 0009-2012 */
# define SM2_DEFAULT_USERID "1234567812345678"
-int sm2_compute_z_digest(uint8_t *out,
- const EVP_MD *digest,
- const uint8_t *id,
- const size_t id_len,
- const EC_KEY *key);
+int ossl_sm2_compute_z_digest(uint8_t *out,
+ const EVP_MD *digest,
+ const uint8_t *id,
+ const size_t id_len,
+ const EC_KEY *key);
/*
* SM2 signature operation. Computes Z and then signs H(Z || msg) using SM2
*/
-ECDSA_SIG *sm2_do_sign(const EC_KEY *key,
+ECDSA_SIG *ossl_sm2_do_sign(const EC_KEY *key,
+ const EVP_MD *digest,
+ const uint8_t *id,
+ const size_t id_len,
+ const uint8_t *msg, size_t msg_len);
+
+int ossl_sm2_do_verify(const EC_KEY *key,
const EVP_MD *digest,
+ const ECDSA_SIG *signature,
const uint8_t *id,
const size_t id_len,
const uint8_t *msg, size_t msg_len);
-int sm2_do_verify(const EC_KEY *key,
- const EVP_MD *digest,
- const ECDSA_SIG *signature,
- const uint8_t *id,
- const size_t id_len,
- const uint8_t *msg, size_t msg_len);
-
/*
* SM2 signature generation.
*/
-int sm2_sign(const unsigned char *dgst, int dgstlen,
- unsigned char *sig, unsigned int *siglen, EC_KEY *eckey);
+int ossl_sm2_internal_sign(const unsigned char *dgst, int dgstlen,
+ unsigned char *sig, unsigned int *siglen,
+ EC_KEY *eckey);
/*
* SM2 signature verification.
*/
-int sm2_verify(const unsigned char *dgst, int dgstlen,
- const unsigned char *sig, int siglen, EC_KEY *eckey);
+int ossl_sm2_internal_verify(const unsigned char *dgst, int dgstlen,
+ const unsigned char *sig, int siglen,
+ EC_KEY *eckey);
/*
* SM2 encryption
*/
-int sm2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len,
- size_t *ct_size);
+int ossl_sm2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest,
+ size_t msg_len, size_t *ct_size);
-int sm2_plaintext_size(const unsigned char *ct, size_t ct_size, size_t *pt_size);
+int ossl_sm2_plaintext_size(const unsigned char *ct, size_t ct_size,
+ size_t *pt_size);
-int sm2_encrypt(const EC_KEY *key,
- const EVP_MD *digest,
- const uint8_t *msg,
- size_t msg_len,
- uint8_t *ciphertext_buf, size_t *ciphertext_len);
+int ossl_sm2_encrypt(const EC_KEY *key,
+ const EVP_MD *digest,
+ const uint8_t *msg, size_t msg_len,
+ uint8_t *ciphertext_buf, size_t *ciphertext_len);
-int sm2_decrypt(const EC_KEY *key,
- const EVP_MD *digest,
- const uint8_t *ciphertext,
- size_t ciphertext_len, uint8_t *ptext_buf, size_t *ptext_len);
+int ossl_sm2_decrypt(const EC_KEY *key,
+ const EVP_MD *digest,
+ const uint8_t *ciphertext, size_t ciphertext_len,
+ uint8_t *ptext_buf, size_t *ptext_len);
+const unsigned char *ossl_sm2_algorithmidentifier_encoding(int md_nid,
+ size_t *len);
# endif /* OPENSSL_NO_SM2 */
#endif
diff --git a/include/crypto/sm2err.h b/include/crypto/sm2err.h
index d1c0ee25918c..706f4d69dec2 100644
--- a/include/crypto/sm2err.h
+++ b/include/crypto/sm2err.h
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,39 +10,18 @@
#ifndef OSSL_CRYPTO_SM2ERR_H
# define OSSL_CRYPTO_SM2ERR_H
-
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# pragma once
# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
# ifndef OPENSSL_NO_SM2
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_SM2_strings(void);
-
-/*
- * SM2 function codes.
- */
-# define SM2_F_PKEY_SM2_COPY 115
-# define SM2_F_PKEY_SM2_CTRL 109
-# define SM2_F_PKEY_SM2_CTRL_STR 110
-# define SM2_F_PKEY_SM2_DIGEST_CUSTOM 114
-# define SM2_F_PKEY_SM2_INIT 111
-# define SM2_F_PKEY_SM2_SIGN 112
-# define SM2_F_SM2_COMPUTE_MSG_HASH 100
-# define SM2_F_SM2_COMPUTE_USERID_DIGEST 101
-# define SM2_F_SM2_COMPUTE_Z_DIGEST 113
-# define SM2_F_SM2_DECRYPT 102
-# define SM2_F_SM2_ENCRYPT 103
-# define SM2_F_SM2_PLAINTEXT_SIZE 104
-# define SM2_F_SM2_SIGN 105
-# define SM2_F_SM2_SIG_GEN 106
-# define SM2_F_SM2_SIG_VERIFY 107
-# define SM2_F_SM2_VERIFY 108
+int ossl_err_load_SM2_strings(void);
/*
* SM2 reason codes.
@@ -58,8 +37,13 @@ int ERR_load_SM2_strings(void);
# define SM2_R_INVALID_DIGEST_TYPE 103
# define SM2_R_INVALID_ENCODING 104
# define SM2_R_INVALID_FIELD 105
+# define SM2_R_INVALID_PRIVATE_KEY 113
# define SM2_R_NO_PARAMETERS_SET 109
# define SM2_R_USER_ID_TOO_LARGE 106
# endif
+
+# ifdef __cplusplus
+}
+# endif
#endif
diff --git a/include/crypto/sm3.h b/include/crypto/sm3.h
deleted file mode 100644
index 97e746033331..000000000000
--- a/include/crypto/sm3.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright 2017 Ribose Inc. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef OSSL_CRYPTO_SM3_H
-# define OSSL_CRYPTO_SM3_H
-
-# include <openssl/opensslconf.h>
-
-# ifdef OPENSSL_NO_SM3
-# error SM3 is disabled.
-# endif
-
-# define SM3_DIGEST_LENGTH 32
-# define SM3_WORD unsigned int
-
-# define SM3_CBLOCK 64
-# define SM3_LBLOCK (SM3_CBLOCK/4)
-
-typedef struct SM3state_st {
- SM3_WORD A, B, C, D, E, F, G, H;
- SM3_WORD Nl, Nh;
- SM3_WORD data[SM3_LBLOCK];
- unsigned int num;
-} SM3_CTX;
-
-int sm3_init(SM3_CTX *c);
-int sm3_update(SM3_CTX *c, const void *data, size_t len);
-int sm3_final(unsigned char *md, SM3_CTX *c);
-
-void sm3_block_data_order(SM3_CTX *c, const void *p, size_t num);
-
-#endif
diff --git a/include/crypto/sm4.h b/include/crypto/sm4.h
index abe28f385e0a..e21ec81ca6a8 100644
--- a/include/crypto/sm4.h
+++ b/include/crypto/sm4.h
@@ -1,8 +1,8 @@
/*
- * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2017 Ribose Inc. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,6 +10,7 @@
#ifndef OSSL_CRYPTO_SM4_H
# define OSSL_CRYPTO_SM4_H
+# pragma once
# include <openssl/opensslconf.h>
# include <openssl/e_os2.h>
@@ -28,10 +29,10 @@ typedef struct SM4_KEY_st {
uint32_t rk[SM4_KEY_SCHEDULE];
} SM4_KEY;
-int SM4_set_key(const uint8_t *key, SM4_KEY *ks);
+int ossl_sm4_set_key(const uint8_t *key, SM4_KEY *ks);
-void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks);
+void ossl_sm4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks);
-void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks);
+void ossl_sm4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks);
#endif
diff --git a/include/crypto/sparc_arch.h b/include/crypto/sparc_arch.h
new file mode 100644
index 000000000000..447e715bf205
--- /dev/null
+++ b/include/crypto/sparc_arch.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_SPARC_ARCH_H
+# define OSSL_CRYPTO_SPARC_ARCH_H
+
+# define SPARCV9_TICK_PRIVILEGED (1<<0)
+# define SPARCV9_PREFER_FPU (1<<1)
+# define SPARCV9_VIS1 (1<<2)
+# define SPARCV9_VIS2 (1<<3)/* reserved */
+# define SPARCV9_FMADD (1<<4)
+# define SPARCV9_BLK (1<<5)/* VIS1 block copy */
+# define SPARCV9_VIS3 (1<<6)
+# define SPARCV9_RANDOM (1<<7)
+# define SPARCV9_64BIT_STACK (1<<8)
+# define SPARCV9_FJAESX (1<<9)/* Fujitsu SPARC64 X AES */
+# define SPARCV9_FJDESX (1<<10)/* Fujitsu SPARC64 X DES, reserved */
+# define SPARCV9_FJHPCACE (1<<11)/* Fujitsu HPC-ACE, reserved */
+# define SPARCV9_IMA (1<<13)/* reserved */
+# define SPARCV9_VIS4 (1<<14)/* reserved */
+
+/*
+ * OPENSSL_sparcv9cap_P[1] is copy of Compatibility Feature Register,
+ * %asr26, SPARC-T4 and later. There is no SPARCV9_CFR bit in
+ * OPENSSL_sparcv9cap_P[0], as %cfr copy is sufficient...
+ */
+# define CFR_AES 0x00000001/* Supports AES opcodes */
+# define CFR_DES 0x00000002/* Supports DES opcodes */
+# define CFR_KASUMI 0x00000004/* Supports KASUMI opcodes */
+# define CFR_CAMELLIA 0x00000008/* Supports CAMELLIA opcodes */
+# define CFR_MD5 0x00000010/* Supports MD5 opcodes */
+# define CFR_SHA1 0x00000020/* Supports SHA1 opcodes */
+# define CFR_SHA256 0x00000040/* Supports SHA256 opcodes */
+# define CFR_SHA512 0x00000080/* Supports SHA512 opcodes */
+# define CFR_MPMUL 0x00000100/* Supports MPMUL opcodes */
+# define CFR_MONTMUL 0x00000200/* Supports MONTMUL opcodes */
+# define CFR_MONTSQR 0x00000400/* Supports MONTSQR opcodes */
+# define CFR_CRC32C 0x00000800/* Supports CRC32C opcodes */
+# define CFR_XMPMUL 0x00001000/* Supports XMPMUL opcodes */
+# define CFR_XMONTMUL 0x00002000/* Supports XMONTMUL opcodes */
+# define CFR_XMONTSQR 0x00004000/* Supports XMONTSQR opcodes */
+
+# if defined(OPENSSL_PIC) && !defined(__PIC__)
+# define __PIC__
+# endif
+
+# if defined(__SUNPRO_C) && defined(__sparcv9) && !defined(__arch64__)
+# define __arch64__
+# endif
+
+# define SPARC_PIC_THUNK(reg) \
+ .align 32; \
+.Lpic_thunk: \
+ jmp %o7 + 8; \
+ add %o7, reg, reg;
+
+# define SPARC_PIC_THUNK_CALL(reg) \
+ sethi %hi(_GLOBAL_OFFSET_TABLE_-4), reg; \
+ call .Lpic_thunk; \
+ or reg, %lo(_GLOBAL_OFFSET_TABLE_+4), reg;
+
+# if 1
+# define SPARC_SETUP_GOT_REG(reg) SPARC_PIC_THUNK_CALL(reg)
+# else
+# define SPARC_SETUP_GOT_REG(reg) \
+ sethi %hi(_GLOBAL_OFFSET_TABLE_-4), reg; \
+ call .+8; \
+ or reg,%lo(_GLOBAL_OFFSET_TABLE_+4), reg; \
+ add %o7, reg, reg
+# endif
+
+# if defined(__arch64__)
+
+# define SPARC_LOAD_ADDRESS(SYM, reg) \
+ setx SYM, %o7, reg;
+# define LDPTR ldx
+# define SIZE_T_CC %xcc
+# define STACK_FRAME 192
+# define STACK_BIAS 2047
+# define STACK_7thARG (STACK_BIAS+176)
+
+# else
+
+# define SPARC_LOAD_ADDRESS(SYM, reg) \
+ set SYM, reg;
+# define LDPTR ld
+# define SIZE_T_CC %icc
+# define STACK_FRAME 112
+# define STACK_BIAS 0
+# define STACK_7thARG 92
+# define SPARC_LOAD_ADDRESS_LEAF(SYM,reg,tmp) SPARC_LOAD_ADDRESS(SYM,reg)
+
+# endif
+
+# ifdef __PIC__
+# undef SPARC_LOAD_ADDRESS
+# undef SPARC_LOAD_ADDRESS_LEAF
+# define SPARC_LOAD_ADDRESS(SYM, reg) \
+ SPARC_SETUP_GOT_REG(reg); \
+ sethi %hi(SYM), %o7; \
+ or %o7, %lo(SYM), %o7; \
+ LDPTR [reg + %o7], reg;
+# endif
+
+# ifndef SPARC_LOAD_ADDRESS_LEAF
+# define SPARC_LOAD_ADDRESS_LEAF(SYM, reg, tmp) \
+ mov %o7, tmp; \
+ SPARC_LOAD_ADDRESS(SYM, reg) \
+ mov tmp, %o7;
+# endif
+
+# ifndef __ASSEMBLER__
+extern unsigned int OPENSSL_sparcv9cap_P[2];
+# endif
+
+#endif /* OSSL_CRYPTO_SPARC_ARCH_H */
diff --git a/include/crypto/sparse_array.h b/include/crypto/sparse_array.h
new file mode 100644
index 000000000000..7ef742837989
--- /dev/null
+++ b/include/crypto/sparse_array.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_SPARSE_ARRAY_H
+# define OSSL_CRYPTO_SPARSE_ARRAY_H
+# pragma once
+
+# include <openssl/e_os2.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# define SPARSE_ARRAY_OF(type) struct sparse_array_st_ ## type
+
+# define DEFINE_SPARSE_ARRAY_OF_INTERNAL(type, ctype) \
+ SPARSE_ARRAY_OF(type); \
+ static ossl_unused ossl_inline SPARSE_ARRAY_OF(type) * \
+ ossl_sa_##type##_new(void) \
+ { \
+ return (SPARSE_ARRAY_OF(type) *)ossl_sa_new(); \
+ } \
+ static ossl_unused ossl_inline void \
+ ossl_sa_##type##_free(SPARSE_ARRAY_OF(type) *sa) \
+ { \
+ ossl_sa_free((OPENSSL_SA *)sa); \
+ } \
+ static ossl_unused ossl_inline void \
+ ossl_sa_##type##_free_leaves(SPARSE_ARRAY_OF(type) *sa) \
+ { \
+ ossl_sa_free_leaves((OPENSSL_SA *)sa); \
+ } \
+ static ossl_unused ossl_inline size_t \
+ ossl_sa_##type##_num(const SPARSE_ARRAY_OF(type) *sa) \
+ { \
+ return ossl_sa_num((OPENSSL_SA *)sa); \
+ } \
+ static ossl_unused ossl_inline void \
+ ossl_sa_##type##_doall(const SPARSE_ARRAY_OF(type) *sa, \
+ void (*leaf)(ossl_uintmax_t, type *)) \
+ { \
+ ossl_sa_doall((OPENSSL_SA *)sa, \
+ (void (*)(ossl_uintmax_t, void *))leaf); \
+ } \
+ static ossl_unused ossl_inline void \
+ ossl_sa_##type##_doall_arg(const SPARSE_ARRAY_OF(type) *sa, \
+ void (*leaf)(ossl_uintmax_t, type *, void *), \
+ void *arg) \
+ { \
+ ossl_sa_doall_arg((OPENSSL_SA *)sa, \
+ (void (*)(ossl_uintmax_t, void *, void *))leaf, arg); \
+ } \
+ static ossl_unused ossl_inline ctype \
+ *ossl_sa_##type##_get(const SPARSE_ARRAY_OF(type) *sa, ossl_uintmax_t n) \
+ { \
+ return (type *)ossl_sa_get((OPENSSL_SA *)sa, n); \
+ } \
+ static ossl_unused ossl_inline int \
+ ossl_sa_##type##_set(SPARSE_ARRAY_OF(type) *sa, \
+ ossl_uintmax_t n, ctype *val) \
+ { \
+ return ossl_sa_set((OPENSSL_SA *)sa, n, (void *)val); \
+ } \
+ SPARSE_ARRAY_OF(type)
+
+# define DEFINE_SPARSE_ARRAY_OF(type) \
+ DEFINE_SPARSE_ARRAY_OF_INTERNAL(type, type)
+# define DEFINE_SPARSE_ARRAY_OF_CONST(type) \
+ DEFINE_SPARSE_ARRAY_OF_INTERNAL(type, const type)
+
+typedef struct sparse_array_st OPENSSL_SA;
+OPENSSL_SA *ossl_sa_new(void);
+void ossl_sa_free(OPENSSL_SA *sa);
+void ossl_sa_free_leaves(OPENSSL_SA *sa);
+size_t ossl_sa_num(const OPENSSL_SA *sa);
+void ossl_sa_doall(const OPENSSL_SA *sa, void (*leaf)(ossl_uintmax_t, void *));
+void ossl_sa_doall_arg(const OPENSSL_SA *sa,
+ void (*leaf)(ossl_uintmax_t, void *, void *), void *);
+void *ossl_sa_get(const OPENSSL_SA *sa, ossl_uintmax_t n);
+int ossl_sa_set(OPENSSL_SA *sa, ossl_uintmax_t n, void *val);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/store.h b/include/crypto/store.h
index 428d3c60e13e..5645fc92355f 100644
--- a/include/crypto/store.h
+++ b/include/crypto/store.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,20 +9,15 @@
#ifndef OSSL_CRYPTO_STORE_H
# define OSSL_CRYPTO_STORE_H
+# pragma once
# include <openssl/bio.h>
# include <openssl/store.h>
# include <openssl/ui.h>
-/*
- * Two functions to read PEM data off an already opened BIO. To be used
- * instead of OSSLSTORE_open() and OSSLSTORE_close(). Everything is done
- * as usual with OSSLSTORE_load() and OSSLSTORE_eof().
- */
-OSSL_STORE_CTX *ossl_store_attach_pem_bio(BIO *bp, const UI_METHOD *ui_method,
- void *ui_data);
-int ossl_store_detach_pem_bio(OSSL_STORE_CTX *ctx);
-
void ossl_store_cleanup_int(void);
+int ossl_store_loader_get_number(const OSSL_STORE_LOADER *loader);
+int ossl_store_loader_store_cache_flush(OSSL_LIB_CTX *libctx);
+int ossl_store_loader_store_remove_all_provided(const OSSL_PROVIDER *prov);
#endif
diff --git a/include/crypto/storeerr.h b/include/crypto/storeerr.h
new file mode 100644
index 000000000000..c46d845f8e41
--- /dev/null
+++ b/include/crypto/storeerr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_STOREERR_H
+# define OSSL_CRYPTO_STOREERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_OSSL_STORE_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/tserr.h b/include/crypto/tserr.h
new file mode 100644
index 000000000000..2f34ba319de8
--- /dev/null
+++ b/include/crypto/tserr.h
@@ -0,0 +1,30 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_TSERR_H
+# define OSSL_CRYPTO_TSERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# ifndef OPENSSL_NO_TS
+
+int ossl_err_load_TS_strings(void);
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/types.h b/include/crypto/types.h
new file mode 100644
index 000000000000..ad17f052e45f
--- /dev/null
+++ b/include/crypto/types.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* When removal is simulated, we still need the type internally */
+
+#ifndef OSSL_CRYPTO_TYPES_H
+# define OSSL_CRYPTO_TYPES_H
+# pragma once
+
+# ifdef OPENSSL_NO_DEPRECATED_3_0
+typedef struct rsa_st RSA;
+typedef struct rsa_meth_st RSA_METHOD;
+# ifndef OPENSSL_NO_EC
+typedef struct ec_key_st EC_KEY;
+typedef struct ec_key_method_st EC_KEY_METHOD;
+# endif
+# ifndef OPENSSL_NO_DSA
+typedef struct dsa_st DSA;
+# endif
+# endif
+
+# ifndef OPENSSL_NO_EC
+typedef struct ecx_key_st ECX_KEY;
+# endif
+
+#endif
diff --git a/include/crypto/uierr.h b/include/crypto/uierr.h
new file mode 100644
index 000000000000..789077a89f3e
--- /dev/null
+++ b/include/crypto/uierr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_UIERR_H
+# define OSSL_CRYPTO_UIERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_UI_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/x509.h b/include/crypto/x509.h
index 243ea74f6f4e..631150b76969 100644
--- a/include/crypto/x509.h
+++ b/include/crypto/x509.h
@@ -1,15 +1,21 @@
/*
- * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include "internal/refcount.h"
-#include <openssl/x509.h>
-#include <openssl/conf.h>
+#ifndef OSSL_CRYPTO_X509_H
+# define OSSL_CRYPTO_X509_H
+# pragma once
+
+# include "internal/refcount.h"
+# include <openssl/asn1.h>
+# include <openssl/x509.h>
+# include <openssl/conf.h>
+# include "crypto/types.h"
/* Internal X509 structures and functions: not for application use */
@@ -73,6 +79,11 @@ struct X509_req_st {
ASN1_BIT_STRING *signature; /* signature */
CRYPTO_REF_COUNT references;
CRYPTO_RWLOCK *lock;
+
+ /* Set on live certificates for authentication purposes */
+ ASN1_OCTET_STRING *distinguishing_id;
+ OSSL_LIB_CTX *libctx;
+ char *propq;
};
struct X509_crl_info_st {
@@ -111,6 +122,9 @@ struct X509_crl_st {
const X509_CRL_METHOD *meth;
void *meth_data;
CRYPTO_RWLOCK *lock;
+
+ OSSL_LIB_CTX *libctx;
+ char *propq;
};
struct x509_revoked_st {
@@ -177,7 +191,7 @@ struct x509_st {
STACK_OF(DIST_POINT) *crldp;
STACK_OF(GENERAL_NAME) *altname;
NAME_CONSTRAINTS *nc;
-#ifndef OPENSSL_NO_RFC3779
+# ifndef OPENSSL_NO_RFC3779
STACK_OF(IPAddressFamily) *rfc3779_addr;
struct ASIdentifiers_st *rfc3779_asid;
# endif
@@ -185,6 +199,12 @@ struct x509_st {
X509_CERT_AUX *aux;
CRYPTO_RWLOCK *lock;
volatile int ex_cached;
+
+ /* Set on live certificates for authentication purposes */
+ ASN1_OCTET_STRING *distinguishing_id;
+
+ OSSL_LIB_CTX *libctx;
+ char *propq;
} /* X509 */ ;
/*
@@ -193,7 +213,7 @@ struct x509_st {
* kept and passed around.
*/
struct x509_store_ctx_st { /* X509_STORE_CTX */
- X509_STORE *ctx;
+ X509_STORE *store;
/* The following are set by the caller */
/* The cert to check */
X509 *cert;
@@ -223,8 +243,11 @@ struct x509_store_ctx_st { /* X509_STORE_CTX */
int (*cert_crl) (X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x);
/* Check policy status of the chain */
int (*check_policy) (X509_STORE_CTX *ctx);
- STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx, X509_NAME *nm);
- STACK_OF(X509_CRL) *(*lookup_crls) (X509_STORE_CTX *ctx, X509_NAME *nm);
+ STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx,
+ const X509_NAME *nm);
+ /* cannot constify 'ctx' param due to lookup_certs_sk() in x509_vfy.c */
+ STACK_OF(X509_CRL) *(*lookup_crls) (const X509_STORE_CTX *ctx,
+ const X509_NAME *nm);
int (*cleanup) (X509_STORE_CTX *ctx);
/* The following is built up */
/* if 0, rebuild chain */
@@ -255,6 +278,9 @@ struct x509_store_ctx_st { /* X509_STORE_CTX */
SSL_DANE *dane;
/* signed via bare TA public key, rather than CA certificate */
int bare_ta_signed;
+
+ OSSL_LIB_CTX *libctx;
+ char *propq;
};
/* PKCS#8 private key info structure */
@@ -282,10 +308,63 @@ struct x509_object_st {
} data;
};
-int a2i_ipadd(unsigned char *ipout, const char *ipasc);
-int x509_set1_time(ASN1_TIME **ptm, const ASN1_TIME *tm);
+int ossl_a2i_ipadd(unsigned char *ipout, const char *ipasc);
+int ossl_x509_set1_time(ASN1_TIME **ptm, const ASN1_TIME *tm);
+int ossl_x509_print_ex_brief(BIO *bio, X509 *cert, unsigned long neg_cflags);
+int ossl_x509v3_cache_extensions(X509 *x);
+int ossl_x509_init_sig_info(X509 *x);
+
+int ossl_x509_set0_libctx(X509 *x, OSSL_LIB_CTX *libctx, const char *propq);
+int ossl_x509_crl_set0_libctx(X509_CRL *x, OSSL_LIB_CTX *libctx,
+ const char *propq);
+int ossl_x509_req_set0_libctx(X509_REQ *x, OSSL_LIB_CTX *libctx,
+ const char *propq);
+int ossl_asn1_item_digest_ex(const ASN1_ITEM *it, const EVP_MD *type,
+ void *data, unsigned char *md, unsigned int *len,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int ossl_x509_add_cert_new(STACK_OF(X509) **sk, X509 *cert, int flags);
+int ossl_x509_add_certs_new(STACK_OF(X509) **p_sk, STACK_OF(X509) *certs,
+ int flags);
+
+STACK_OF(X509_ATTRIBUTE) *ossl_x509at_dup(const STACK_OF(X509_ATTRIBUTE) *x);
+
+int ossl_x509_PUBKEY_get0_libctx(OSSL_LIB_CTX **plibctx, const char **ppropq,
+ const X509_PUBKEY *key);
+/* Calculate default key identifier according to RFC 5280 section 4.2.1.2 (1) */
+ASN1_OCTET_STRING *ossl_x509_pubkey_hash(X509_PUBKEY *pubkey);
+
+X509_PUBKEY *ossl_d2i_X509_PUBKEY_INTERNAL(const unsigned char **pp,
+ long len, OSSL_LIB_CTX *libctx);
+void ossl_X509_PUBKEY_INTERNAL_free(X509_PUBKEY *xpub);
-void x509_init_sig_info(X509 *x);
+RSA *ossl_d2i_RSA_PSS_PUBKEY(RSA **a, const unsigned char **pp, long length);
+int ossl_i2d_RSA_PSS_PUBKEY(const RSA *a, unsigned char **pp);
+# ifndef OPENSSL_NO_DSA
+DSA *ossl_d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length);
+# endif /* OPENSSL_NO_DSA */
+# ifndef OPENSSL_NO_DH
+DH *ossl_d2i_DH_PUBKEY(DH **a, const unsigned char **pp, long length);
+int ossl_i2d_DH_PUBKEY(const DH *a, unsigned char **pp);
+DH *ossl_d2i_DHx_PUBKEY(DH **a, const unsigned char **pp, long length);
+int ossl_i2d_DHx_PUBKEY(const DH *a, unsigned char **pp);
+# endif /* OPENSSL_NO_DH */
+# ifndef OPENSSL_NO_EC
+ECX_KEY *ossl_d2i_ED25519_PUBKEY(ECX_KEY **a,
+ const unsigned char **pp, long length);
+int ossl_i2d_ED25519_PUBKEY(const ECX_KEY *a, unsigned char **pp);
+ECX_KEY *ossl_d2i_ED448_PUBKEY(ECX_KEY **a,
+ const unsigned char **pp, long length);
+int ossl_i2d_ED448_PUBKEY(const ECX_KEY *a, unsigned char **pp);
+ECX_KEY *ossl_d2i_X25519_PUBKEY(ECX_KEY **a,
+ const unsigned char **pp, long length);
+int ossl_i2d_X25519_PUBKEY(const ECX_KEY *a, unsigned char **pp);
+ECX_KEY *ossl_d2i_X448_PUBKEY(ECX_KEY **a,
+ const unsigned char **pp, long length);
+int ossl_i2d_X448_PUBKEY(const ECX_KEY *a, unsigned char **pp);
+# endif /* OPENSSL_NO_EC */
+EVP_PKEY *ossl_d2i_PUBKEY_legacy(EVP_PKEY **a, const unsigned char **pp,
+ long length);
int x509v3_add_len_value_uchar(const char *name, const unsigned char *value,
size_t vallen, STACK_OF(CONF_VALUE) **extlist);
+#endif /* OSSL_CRYPTO_X509_H */
diff --git a/include/crypto/x509err.h b/include/crypto/x509err.h
new file mode 100644
index 000000000000..53f567d92e24
--- /dev/null
+++ b/include/crypto/x509err.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_X509ERR_H
+# define OSSL_CRYPTO_X509ERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_X509_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/crypto/x509v3err.h b/include/crypto/x509v3err.h
new file mode 100644
index 000000000000..66d3ad92f865
--- /dev/null
+++ b/include/crypto/x509v3err.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_X509V3ERR_H
+# define OSSL_CRYPTO_X509V3ERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_X509V3_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/internal/__DECC_INCLUDE_EPILOGUE.H b/include/internal/__DECC_INCLUDE_EPILOGUE.H
index c350018ad190..e57c0eab3e3a 100644
--- a/include/internal/__DECC_INCLUDE_EPILOGUE.H
+++ b/include/internal/__DECC_INCLUDE_EPILOGUE.H
@@ -1,7 +1,7 @@
/*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/include/internal/__DECC_INCLUDE_PROLOGUE.H b/include/internal/__DECC_INCLUDE_PROLOGUE.H
index 9a9c777f93f8..a01395755713 100644
--- a/include/internal/__DECC_INCLUDE_PROLOGUE.H
+++ b/include/internal/__DECC_INCLUDE_PROLOGUE.H
@@ -1,7 +1,7 @@
/*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/include/internal/asn1.h b/include/internal/asn1.h
new file mode 100644
index 000000000000..3143e3405f1d
--- /dev/null
+++ b/include/internal/asn1.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_ASN1_H
+# define OSSL_INTERNAL_ASN1_H
+# pragma once
+
+int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
+
+#endif
diff --git a/include/internal/bio.h b/include/internal/bio.h
index c343b276295c..547a73d02d4e 100644
--- a/include/internal/bio.h
+++ b/include/internal/bio.h
@@ -1,13 +1,18 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/bio.h>
+#ifndef OSSL_INTERNAL_BIO_H
+# define OSSL_INTERNAL_BIO_H
+# pragma once
+
+# include <openssl/core.h>
+# include <openssl/bio.h>
struct bio_method_st {
int type;
@@ -31,3 +36,56 @@ void bio_cleanup(void);
/* Old style to new style BIO_METHOD conversion functions */
int bwrite_conv(BIO *bio, const char *data, size_t datal, size_t *written);
int bread_conv(BIO *bio, char *data, size_t datal, size_t *read);
+
+/* Changes to these internal BIOs must also update include/openssl/bio.h */
+# define BIO_CTRL_SET_KTLS 72
+# define BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG 74
+# define BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG 75
+
+/*
+ * This is used with socket BIOs:
+ * BIO_FLAGS_KTLS_TX means we are using ktls with this BIO for sending.
+ * BIO_FLAGS_KTLS_TX_CTRL_MSG means we are about to send a ctrl message next.
+ * BIO_FLAGS_KTLS_RX means we are using ktls with this BIO for receiving.
+ */
+# define BIO_FLAGS_KTLS_TX_CTRL_MSG 0x1000
+# define BIO_FLAGS_KTLS_RX 0x2000
+# define BIO_FLAGS_KTLS_TX 0x4000
+
+/* KTLS related controls and flags */
+# define BIO_set_ktls_flag(b, is_tx) \
+ BIO_set_flags(b, (is_tx) ? BIO_FLAGS_KTLS_TX : BIO_FLAGS_KTLS_RX)
+# define BIO_should_ktls_flag(b, is_tx) \
+ BIO_test_flags(b, (is_tx) ? BIO_FLAGS_KTLS_TX : BIO_FLAGS_KTLS_RX)
+# define BIO_set_ktls_ctrl_msg_flag(b) \
+ BIO_set_flags(b, BIO_FLAGS_KTLS_TX_CTRL_MSG)
+# define BIO_should_ktls_ctrl_msg_flag(b) \
+ BIO_test_flags(b, BIO_FLAGS_KTLS_TX_CTRL_MSG)
+# define BIO_clear_ktls_ctrl_msg_flag(b) \
+ BIO_clear_flags(b, BIO_FLAGS_KTLS_TX_CTRL_MSG)
+
+# define BIO_set_ktls(b, keyblob, is_tx) \
+ BIO_ctrl(b, BIO_CTRL_SET_KTLS, is_tx, keyblob)
+# define BIO_set_ktls_ctrl_msg(b, record_type) \
+ BIO_ctrl(b, BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG, record_type, NULL)
+# define BIO_clear_ktls_ctrl_msg(b) \
+ BIO_ctrl(b, BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG, 0, NULL)
+
+/* Functions to allow the core to offer the CORE_BIO type to providers */
+OSSL_CORE_BIO *ossl_core_bio_new_from_bio(BIO *bio);
+OSSL_CORE_BIO *ossl_core_bio_new_file(const char *filename, const char *mode);
+OSSL_CORE_BIO *ossl_core_bio_new_mem_buf(const void *buf, int len);
+int ossl_core_bio_read_ex(OSSL_CORE_BIO *cb, void *data, size_t dlen,
+ size_t *readbytes);
+int ossl_core_bio_write_ex(OSSL_CORE_BIO *cb, const void *data, size_t dlen,
+ size_t *written);
+int ossl_core_bio_gets(OSSL_CORE_BIO *cb, char *buf, int size);
+int ossl_core_bio_puts(OSSL_CORE_BIO *cb, const char *buf);
+long ossl_core_bio_ctrl(OSSL_CORE_BIO *cb, int cmd, long larg, void *parg);
+int ossl_core_bio_up_ref(OSSL_CORE_BIO *cb);
+int ossl_core_bio_free(OSSL_CORE_BIO *cb);
+int ossl_core_bio_vprintf(OSSL_CORE_BIO *cb, const char *format, va_list args);
+
+int ossl_bio_init_core(OSSL_LIB_CTX *libctx, const OSSL_DISPATCH *fns);
+
+#endif
diff --git a/include/internal/comp.h b/include/internal/comp.h
index ac6e38b47415..3ad86fc7b1f1 100644
--- a/include/internal/comp.h
+++ b/include/internal/comp.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,4 +9,4 @@
#include <openssl/comp.h>
-void comp_zlib_cleanup_int(void);
+void ossl_comp_zlib_cleanup(void);
diff --git a/include/internal/conf.h b/include/internal/conf.h
index 163fea8de418..8c6c29cd2c5f 100644
--- a/include/internal/conf.h
+++ b/include/internal/conf.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,10 +9,11 @@
#ifndef OSSL_INTERNAL_CONF_H
# define OSSL_INTERNAL_CONF_H
+# pragma once
-#include <openssl/conf.h>
+# include <openssl/conf.h>
-#define DEFAULT_CONF_MFLAGS \
+# define DEFAULT_CONF_MFLAGS \
(CONF_MFLAGS_DEFAULT_SECTION | \
CONF_MFLAGS_IGNORE_MISSING_FILE | \
CONF_MFLAGS_IGNORE_RETURN_CODES)
@@ -23,8 +24,8 @@ struct ossl_init_settings_st {
unsigned long flags;
};
-int openssl_config_int(const OPENSSL_INIT_SETTINGS *);
-void openssl_no_config_int(void);
-void conf_modules_free_int(void);
+int ossl_config_int(const OPENSSL_INIT_SETTINGS *);
+void ossl_no_config_int(void);
+void ossl_config_modules_free(void);
#endif
diff --git a/include/internal/constant_time.h b/include/internal/constant_time.h
index 6600a1d72aeb..0ed6f823c11e 100644
--- a/include/internal/constant_time.h
+++ b/include/internal/constant_time.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2014-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,6 +9,7 @@
#ifndef OSSL_INTERNAL_CONSTANT_TIME_H
# define OSSL_INTERNAL_CONSTANT_TIME_H
+# pragma once
# include <stdlib.h>
# include <string.h>
@@ -181,6 +182,11 @@ static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a)
return constant_time_msb_32(~a & (a - 1));
}
+static ossl_inline uint64_t constant_time_is_zero_64(uint64_t a)
+{
+ return constant_time_msb_64(~a & (a - 1));
+}
+
static ossl_inline unsigned int constant_time_eq(unsigned int a,
unsigned int b)
{
@@ -353,6 +359,34 @@ static ossl_inline void constant_time_cond_swap_64(uint64_t mask, uint64_t *a,
}
/*
+ * mask must be 0xFF or 0x00.
+ * "constant time" is per len.
+ *
+ * if (mask) {
+ * unsigned char tmp[len];
+ *
+ * memcpy(tmp, a, len);
+ * memcpy(a, b);
+ * memcpy(b, tmp);
+ * }
+ */
+static ossl_inline void constant_time_cond_swap_buff(unsigned char mask,
+ unsigned char *a,
+ unsigned char *b,
+ size_t len)
+{
+ size_t i;
+ unsigned char tmp;
+
+ for (i = 0; i < len; i++) {
+ tmp = a[i] ^ b[i];
+ tmp &= mask;
+ a[i] ^= tmp;
+ b[i] ^= tmp;
+ }
+}
+
+/*
* table is a two dimensional array of bytes. Each row has rowsize elements.
* Copies row number idx into out. rowsize and numrows are not considered
* private.
diff --git a/include/internal/core.h b/include/internal/core.h
new file mode 100644
index 000000000000..03adb66bd342
--- /dev/null
+++ b/include/internal/core.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_CORE_H
+# define OSSL_INTERNAL_CORE_H
+# pragma once
+
+/*
+ * namespaces:
+ *
+ * ossl_method_ Core Method API
+ */
+
+/*
+ * construct an arbitrary method from a dispatch table found by looking
+ * up a match for the < operation_id, name, property > combination.
+ * constructor and destructor are the constructor and destructor for that
+ * arbitrary object.
+ *
+ * These objects are normally cached, unless the provider says not to cache.
+ * However, force_cache can be used to force caching whatever the provider
+ * says (for example, because the application knows better).
+ */
+typedef struct ossl_method_construct_method_st {
+ /* Get a temporary store */
+ void *(*get_tmp_store)(void *data);
+ /* Reserve the appropriate method store */
+ int (*lock_store)(void *store, void *data);
+ /* Unreserve the appropriate method store */
+ int (*unlock_store)(void *store, void *data);
+ /* Get an already existing method from a store */
+ void *(*get)(void *store, const OSSL_PROVIDER **prov, void *data);
+ /* Store a method in a store */
+ int (*put)(void *store, void *method, const OSSL_PROVIDER *prov,
+ const char *name, const char *propdef, void *data);
+ /* Construct a new method */
+ void *(*construct)(const OSSL_ALGORITHM *algodef, OSSL_PROVIDER *prov,
+ void *data);
+ /* Destruct a method */
+ void (*destruct)(void *method, void *data);
+} OSSL_METHOD_CONSTRUCT_METHOD;
+
+void *ossl_method_construct(OSSL_LIB_CTX *ctx, int operation_id,
+ OSSL_PROVIDER **provider_rw, int force_cache,
+ OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data);
+
+void ossl_algorithm_do_all(OSSL_LIB_CTX *libctx, int operation_id,
+ OSSL_PROVIDER *provider,
+ int (*pre)(OSSL_PROVIDER *, int operation_id,
+ int no_store, void *data, int *result),
+ int (*reserve_store)(int no_store, void *data),
+ void (*fn)(OSSL_PROVIDER *provider,
+ const OSSL_ALGORITHM *algo,
+ int no_store, void *data),
+ int (*unreserve_store)(void *data),
+ int (*post)(OSSL_PROVIDER *, int operation_id,
+ int no_store, void *data, int *result),
+ void *data);
+char *ossl_algorithm_get1_first_name(const OSSL_ALGORITHM *algo);
+
+__owur int ossl_lib_ctx_write_lock(OSSL_LIB_CTX *ctx);
+__owur int ossl_lib_ctx_read_lock(OSSL_LIB_CTX *ctx);
+int ossl_lib_ctx_unlock(OSSL_LIB_CTX *ctx);
+int ossl_lib_ctx_is_child(OSSL_LIB_CTX *ctx);
+#endif
diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h
index 6e7291ae41bc..934d4b089c20 100644
--- a/include/internal/cryptlib.h
+++ b/include/internal/cryptlib.h
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,19 +9,22 @@
#ifndef OSSL_INTERNAL_CRYPTLIB_H
# define OSSL_INTERNAL_CRYPTLIB_H
+# pragma once
# include <stdlib.h>
# include <string.h>
# ifdef OPENSSL_USE_APPLINK
-# undef BIO_FLAGS_UPLINK
-# define BIO_FLAGS_UPLINK 0x8000
+# define BIO_FLAGS_UPLINK_INTERNAL 0x8000
# include "ms/uplink.h"
+# else
+# define BIO_FLAGS_UPLINK_INTERNAL 0
# endif
# include <openssl/crypto.h>
# include <openssl/buffer.h>
# include <openssl/bio.h>
+# include <openssl/asn1.h>
# include <openssl/err.h>
# include "internal/nelem.h"
@@ -42,12 +45,19 @@ __owur static ossl_inline int ossl_assert_int(int expr, const char *exprstr,
#endif
-typedef struct ex_callback_st EX_CALLBACK;
+/*
+ * Use this inside a union with the field that needs to be aligned to a
+ * reasonable boundary for the platform. The most pessimistic alignment
+ * of the listed types will be used by the compiler.
+ */
+# define OSSL_UNION_ALIGN \
+ double align; \
+ ossl_uintmax_t align_int; \
+ void *align_ptr
+typedef struct ex_callback_st EX_CALLBACK;
DEFINE_STACK_OF(EX_CALLBACK)
-typedef struct app_mem_info_st APP_INFO;
-
typedef struct mem_st MEM;
DEFINE_LHASH_OF(MEM);
@@ -76,9 +86,14 @@ DEFINE_LHASH_OF(MEM);
# define HEX_SIZE(type) (sizeof(type)*2)
void OPENSSL_cpuid_setup(void);
+#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
+ defined(__x86_64) || defined(__x86_64__) || \
+ defined(_M_AMD64) || defined(_M_X64)
extern unsigned int OPENSSL_ia32cap_P[];
+#endif
void OPENSSL_showfatal(const char *fmta, ...);
-void crypto_cleanup_all_ex_data_int(void);
+int ossl_do_ex_data_init(OSSL_LIB_CTX *ctx);
+void ossl_crypto_cleanup_all_ex_data_int(OSSL_LIB_CTX *ctx);
int openssl_init_fork_handlers(void);
int openssl_get_fork_id(void);
@@ -96,4 +111,153 @@ uint32_t OPENSSL_rdtsc(void);
size_t OPENSSL_instrument_bus(unsigned int *, size_t);
size_t OPENSSL_instrument_bus2(unsigned int *, size_t, size_t);
+/* ex_data structures */
+
+/*
+ * Each structure type (sometimes called a class), that supports
+ * exdata has a stack of callbacks for each instance.
+ */
+struct ex_callback_st {
+ long argl; /* Arbitrary long */
+ void *argp; /* Arbitrary void * */
+ int priority; /* Priority ordering for freeing */
+ CRYPTO_EX_new *new_func;
+ CRYPTO_EX_free *free_func;
+ CRYPTO_EX_dup *dup_func;
+};
+
+/*
+ * The state for each class. This could just be a typedef, but
+ * a structure allows future changes.
+ */
+typedef struct ex_callbacks_st {
+ STACK_OF(EX_CALLBACK) *meth;
+} EX_CALLBACKS;
+
+typedef struct ossl_ex_data_global_st {
+ CRYPTO_RWLOCK *ex_data_lock;
+ EX_CALLBACKS ex_data[CRYPTO_EX_INDEX__COUNT];
+} OSSL_EX_DATA_GLOBAL;
+
+
+/* OSSL_LIB_CTX */
+
+# define OSSL_LIB_CTX_PROVIDER_STORE_RUN_ONCE_INDEX 0
+# define OSSL_LIB_CTX_DEFAULT_METHOD_STORE_RUN_ONCE_INDEX 1
+# define OSSL_LIB_CTX_METHOD_STORE_RUN_ONCE_INDEX 2
+# define OSSL_LIB_CTX_MAX_RUN_ONCE 3
+
+# define OSSL_LIB_CTX_EVP_METHOD_STORE_INDEX 0
+# define OSSL_LIB_CTX_PROVIDER_STORE_INDEX 1
+# define OSSL_LIB_CTX_PROPERTY_DEFN_INDEX 2
+# define OSSL_LIB_CTX_PROPERTY_STRING_INDEX 3
+# define OSSL_LIB_CTX_NAMEMAP_INDEX 4
+# define OSSL_LIB_CTX_DRBG_INDEX 5
+# define OSSL_LIB_CTX_DRBG_NONCE_INDEX 6
+# define OSSL_LIB_CTX_RAND_CRNGT_INDEX 7
+# ifdef FIPS_MODULE
+# define OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX 8
+# endif
+# define OSSL_LIB_CTX_FIPS_PROV_INDEX 9
+# define OSSL_LIB_CTX_ENCODER_STORE_INDEX 10
+# define OSSL_LIB_CTX_DECODER_STORE_INDEX 11
+# define OSSL_LIB_CTX_SELF_TEST_CB_INDEX 12
+# define OSSL_LIB_CTX_BIO_PROV_INDEX 13
+# define OSSL_LIB_CTX_GLOBAL_PROPERTIES 14
+# define OSSL_LIB_CTX_STORE_LOADER_STORE_INDEX 15
+# define OSSL_LIB_CTX_PROVIDER_CONF_INDEX 16
+# define OSSL_LIB_CTX_BIO_CORE_INDEX 17
+# define OSSL_LIB_CTX_CHILD_PROVIDER_INDEX 18
+# define OSSL_LIB_CTX_MAX_INDEXES 19
+
+# define OSSL_LIB_CTX_METHOD_LOW_PRIORITY -1
+# define OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY 0
+# define OSSL_LIB_CTX_METHOD_PRIORITY_1 1
+# define OSSL_LIB_CTX_METHOD_PRIORITY_2 2
+
+typedef struct ossl_lib_ctx_method {
+ int priority;
+ void *(*new_func)(OSSL_LIB_CTX *ctx);
+ void (*free_func)(void *);
+} OSSL_LIB_CTX_METHOD;
+
+OSSL_LIB_CTX *ossl_lib_ctx_get_concrete(OSSL_LIB_CTX *ctx);
+int ossl_lib_ctx_is_default(OSSL_LIB_CTX *ctx);
+int ossl_lib_ctx_is_global_default(OSSL_LIB_CTX *ctx);
+
+/* Functions to retrieve pointers to data by index */
+void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *, int /* index */,
+ const OSSL_LIB_CTX_METHOD * ctx);
+
+void ossl_lib_ctx_default_deinit(void);
+OSSL_EX_DATA_GLOBAL *ossl_lib_ctx_get_ex_data_global(OSSL_LIB_CTX *ctx);
+typedef int (ossl_lib_ctx_run_once_fn)(OSSL_LIB_CTX *ctx);
+typedef void (ossl_lib_ctx_onfree_fn)(OSSL_LIB_CTX *ctx);
+
+int ossl_lib_ctx_run_once(OSSL_LIB_CTX *ctx, unsigned int idx,
+ ossl_lib_ctx_run_once_fn run_once_fn);
+int ossl_lib_ctx_onfree(OSSL_LIB_CTX *ctx, ossl_lib_ctx_onfree_fn onfreefn);
+const char *ossl_lib_ctx_get_descriptor(OSSL_LIB_CTX *libctx);
+
+void ossl_release_default_drbg_ctx(void);
+
+OSSL_LIB_CTX *ossl_crypto_ex_data_get_ossl_lib_ctx(const CRYPTO_EX_DATA *ad);
+int ossl_crypto_new_ex_data_ex(OSSL_LIB_CTX *ctx, int class_index, void *obj,
+ CRYPTO_EX_DATA *ad);
+int ossl_crypto_get_ex_new_index_ex(OSSL_LIB_CTX *ctx, int class_index,
+ long argl, void *argp,
+ CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func,
+ CRYPTO_EX_free *free_func,
+ int priority);
+int ossl_crypto_free_ex_index_ex(OSSL_LIB_CTX *ctx, int class_index, int idx);
+
+/* Function for simple binary search */
+
+/* Flags */
+# define OSSL_BSEARCH_VALUE_ON_NOMATCH 0x01
+# define OSSL_BSEARCH_FIRST_VALUE_ON_MATCH 0x02
+
+const void *ossl_bsearch(const void *key, const void *base, int num,
+ int size, int (*cmp) (const void *, const void *),
+ int flags);
+
+char *ossl_sk_ASN1_UTF8STRING2text(STACK_OF(ASN1_UTF8STRING) *text,
+ const char *sep, size_t max_len);
+char *ossl_ipaddr_to_asc(unsigned char *p, int len);
+
+char *ossl_buf2hexstr_sep(const unsigned char *buf, long buflen, char sep);
+unsigned char *ossl_hexstr2buf_sep(const char *str, long *buflen,
+ const char sep);
+
+static ossl_inline int ossl_ends_with_dirsep(const char *path)
+{
+ if (*path != '\0')
+ path += strlen(path) - 1;
+# if defined __VMS
+ if (*path == ']' || *path == '>' || *path == ':')
+ return 1;
+# elif defined _WIN32
+ if (*path == '\\')
+ return 1;
+# endif
+ return *path == '/';
+}
+
+static ossl_inline int ossl_is_absolute_path(const char *path)
+{
+# if defined __VMS
+ if (strchr(path, ':') != NULL
+ || ((path[0] == '[' || path[0] == '<')
+ && path[1] != '.' && path[1] != '-'
+ && path[1] != ']' && path[1] != '>'))
+ return 1;
+# elif defined _WIN32
+ if (path[0] == '\\'
+ || (path[0] != '\0' && path[1] == ':'))
+ return 1;
+# endif
+ return path[0] == '/';
+}
+
#endif
diff --git a/include/internal/dane.h b/include/internal/dane.h
index 7a39bd7d7d46..a3d78a7f8050 100644
--- a/include/internal/dane.h
+++ b/include/internal/dane.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,8 +9,9 @@
#ifndef OSSL_INTERNAL_DANE_H
#define OSSL_INTERNAL_DANE_H
+# pragma once
-#include <openssl/safestack.h>
+# include <openssl/safestack.h>
/*-
* Certificate usages:
diff --git a/include/internal/deprecated.h b/include/internal/deprecated.h
new file mode 100644
index 000000000000..a313a015459e
--- /dev/null
+++ b/include/internal/deprecated.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This header file should be included by internal code that needs to use APIs
+ * that have been deprecated for public use, but where those symbols will still
+ * be available internally. For example the EVP and provider code needs to use
+ * low level APIs that are otherwise deprecated.
+ *
+ * This header *must* be the first OpenSSL header included by a source file.
+ */
+
+#ifndef OSSL_INTERNAL_DEPRECATED_H
+# define OSSL_INTERNAL_DEPRECATED_H
+# pragma once
+
+# include <openssl/configuration.h>
+
+# undef OPENSSL_NO_DEPRECATED
+# define OPENSSL_SUPPRESS_DEPRECATED
+
+# include <openssl/macros.h>
+
+#endif
diff --git a/include/internal/der.h b/include/internal/der.h
new file mode 100644
index 000000000000..f23fabc29022
--- /dev/null
+++ b/include/internal/der.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/bn.h>
+#include "internal/packet.h"
+
+/*
+ * NOTE: X.690 numbers the identifier octet bits 1 to 8.
+ * We use the same numbering in comments here.
+ */
+
+/* Well known primitive tags */
+
+/*
+ * DER UNIVERSAL tags, occupying bits 1-5 in the DER identifier byte
+ * These are only valid for the UNIVERSAL class. With the other classes,
+ * these bits have a different meaning.
+ */
+#define DER_P_EOC 0 /* BER End Of Contents tag */
+#define DER_P_BOOLEAN 1
+#define DER_P_INTEGER 2
+#define DER_P_BIT_STRING 3
+#define DER_P_OCTET_STRING 4
+#define DER_P_NULL 5
+#define DER_P_OBJECT 6
+#define DER_P_OBJECT_DESCRIPTOR 7
+#define DER_P_EXTERNAL 8
+#define DER_P_REAL 9
+#define DER_P_ENUMERATED 10
+#define DER_P_UTF8STRING 12
+#define DER_P_SEQUENCE 16
+#define DER_P_SET 17
+#define DER_P_NUMERICSTRING 18
+#define DER_P_PRINTABLESTRING 19
+#define DER_P_T61STRING 20
+#define DER_P_VIDEOTEXSTRING 21
+#define DER_P_IA5STRING 22
+#define DER_P_UTCTIME 23
+#define DER_P_GENERALIZEDTIME 24
+#define DER_P_GRAPHICSTRING 25
+#define DER_P_ISO64STRING 26
+#define DER_P_GENERALSTRING 27
+#define DER_P_UNIVERSALSTRING 28
+#define DER_P_BMPSTRING 30
+
+/* DER Flags, occupying bit 6 in the DER identifier byte */
+#define DER_F_PRIMITIVE 0x00
+#define DER_F_CONSTRUCTED 0x20
+
+/* DER classes tags, occupying bits 7-8 in the DER identifier byte */
+#define DER_C_UNIVERSAL 0x00
+#define DER_C_APPLICATION 0x40
+#define DER_C_CONTEXT 0x80
+#define DER_C_PRIVATE 0xC0
+
+/*
+ * Run-time constructors.
+ *
+ * They all construct DER backwards, so care should be taken to use them
+ * that way.
+ */
+
+/* This can be used for all items that don't have a context */
+#define DER_NO_CONTEXT -1
+
+int ossl_DER_w_precompiled(WPACKET *pkt, int tag,
+ const unsigned char *precompiled,
+ size_t precompiled_n);
+
+int ossl_DER_w_boolean(WPACKET *pkt, int tag, int b);
+int ossl_DER_w_uint32(WPACKET *pkt, int tag, uint32_t v);
+int ossl_DER_w_bn(WPACKET *pkt, int tag, const BIGNUM *v);
+int ossl_DER_w_null(WPACKET *pkt, int tag);
+int ossl_DER_w_octet_string(WPACKET *pkt, int tag,
+ const unsigned char *data, size_t data_n);
+int ossl_DER_w_octet_string_uint32(WPACKET *pkt, int tag, uint32_t value);
+
+/*
+ * All constructors for constructed elements have a begin and a end function
+ */
+int ossl_DER_w_begin_sequence(WPACKET *pkt, int tag);
+int ossl_DER_w_end_sequence(WPACKET *pkt, int tag);
diff --git a/include/internal/dso.h b/include/internal/dso.h
index c57c0c407592..160ddb98db14 100644
--- a/include/internal/dso.h
+++ b/include/internal/dso.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,6 +9,7 @@
#ifndef OSSL_INTERNAL_DSO_H
# define OSSL_INTERNAL_DSO_H
+# pragma once
# include <openssl/crypto.h>
# include "internal/dsoerr.h"
@@ -160,6 +161,4 @@ DSO *DSO_dsobyaddr(void *addr, int flags);
*/
void *DSO_global_lookup(const char *name);
-int ERR_load_DSO_strings(void);
-
#endif
diff --git a/include/internal/dsoerr.h b/include/internal/dsoerr.h
index 94d642a22d8c..b1719e8377f4 100644
--- a/include/internal/dsoerr.h
+++ b/include/internal/dsoerr.h
@@ -1,8 +1,8 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,73 +10,39 @@
#ifndef OSSL_INTERNAL_DSOERR_H
# define OSSL_INTERNAL_DSOERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
# ifdef __cplusplus
-extern "C"
+extern "C" {
# endif
-int ERR_load_DSO_strings(void);
-/*
- * DSO function codes.
- */
-# define DSO_F_DLFCN_BIND_FUNC 100
-# define DSO_F_DLFCN_LOAD 102
-# define DSO_F_DLFCN_MERGER 130
-# define DSO_F_DLFCN_NAME_CONVERTER 123
-# define DSO_F_DLFCN_UNLOAD 103
-# define DSO_F_DL_BIND_FUNC 104
-# define DSO_F_DL_LOAD 106
-# define DSO_F_DL_MERGER 131
-# define DSO_F_DL_NAME_CONVERTER 124
-# define DSO_F_DL_UNLOAD 107
-# define DSO_F_DSO_BIND_FUNC 108
-# define DSO_F_DSO_CONVERT_FILENAME 126
-# define DSO_F_DSO_CTRL 110
-# define DSO_F_DSO_FREE 111
-# define DSO_F_DSO_GET_FILENAME 127
-# define DSO_F_DSO_GLOBAL_LOOKUP 139
-# define DSO_F_DSO_LOAD 112
-# define DSO_F_DSO_MERGE 132
-# define DSO_F_DSO_NEW_METHOD 113
-# define DSO_F_DSO_PATHBYADDR 105
-# define DSO_F_DSO_SET_FILENAME 129
-# define DSO_F_DSO_UP_REF 114
-# define DSO_F_VMS_BIND_SYM 115
-# define DSO_F_VMS_LOAD 116
-# define DSO_F_VMS_MERGER 133
-# define DSO_F_VMS_UNLOAD 117
-# define DSO_F_WIN32_BIND_FUNC 101
-# define DSO_F_WIN32_GLOBALLOOKUP 142
-# define DSO_F_WIN32_JOINER 135
-# define DSO_F_WIN32_LOAD 120
-# define DSO_F_WIN32_MERGER 134
-# define DSO_F_WIN32_NAME_CONVERTER 125
-# define DSO_F_WIN32_PATHBYADDR 109
-# define DSO_F_WIN32_SPLITTER 136
-# define DSO_F_WIN32_UNLOAD 121
+int ossl_err_load_DSO_strings(void);
/*
* DSO reason codes.
*/
-# define DSO_R_CTRL_FAILED 100
-# define DSO_R_DSO_ALREADY_LOADED 110
-# define DSO_R_EMPTY_FILE_STRUCTURE 113
-# define DSO_R_FAILURE 114
-# define DSO_R_FILENAME_TOO_BIG 101
-# define DSO_R_FINISH_FAILED 102
-# define DSO_R_INCORRECT_FILE_SYNTAX 115
-# define DSO_R_LOAD_FAILED 103
-# define DSO_R_NAME_TRANSLATION_FAILED 109
-# define DSO_R_NO_FILENAME 111
-# define DSO_R_NULL_HANDLE 104
-# define DSO_R_SET_FILENAME_FAILED 112
-# define DSO_R_STACK_ERROR 105
-# define DSO_R_SYM_FAILURE 106
-# define DSO_R_UNLOAD_FAILED 107
-# define DSO_R_UNSUPPORTED 108
+# define DSO_R_CTRL_FAILED 100
+# define DSO_R_DSO_ALREADY_LOADED 110
+# define DSO_R_EMPTY_FILE_STRUCTURE 113
+# define DSO_R_FAILURE 114
+# define DSO_R_FILENAME_TOO_BIG 101
+# define DSO_R_FINISH_FAILED 102
+# define DSO_R_INCORRECT_FILE_SYNTAX 115
+# define DSO_R_LOAD_FAILED 103
+# define DSO_R_NAME_TRANSLATION_FAILED 109
+# define DSO_R_NO_FILENAME 111
+# define DSO_R_NULL_HANDLE 104
+# define DSO_R_SET_FILENAME_FAILED 112
+# define DSO_R_STACK_ERROR 105
+# define DSO_R_SYM_FAILURE 106
+# define DSO_R_UNLOAD_FAILED 107
+# define DSO_R_UNSUPPORTED 108
+
+# ifdef __cplusplus
+}
+# endif
#endif
diff --git a/include/internal/endian.h b/include/internal/endian.h
new file mode 100644
index 000000000000..8b34e03e4404
--- /dev/null
+++ b/include/internal/endian.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_ENDIAN_H
+# define OSSL_INTERNAL_ENDIAN_H
+# pragma once
+
+/*
+ * IS_LITTLE_ENDIAN and IS_BIG_ENDIAN can be used to detect the endiannes
+ * at compile time. To use it, DECLARE_IS_ENDIAN must be used to declare
+ * a variable.
+ *
+ * L_ENDIAN and B_ENDIAN can be used at preprocessor time. They can be set
+ * in the configarion using the lib_cppflags variable. If neither is
+ * set, it will fall back to code works with either endianness.
+ */
+
+# if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__)
+# define DECLARE_IS_ENDIAN const int ossl_is_little_endian = __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define IS_LITTLE_ENDIAN (ossl_is_little_endian)
+# define IS_BIG_ENDIAN (!ossl_is_little_endian)
+# if defined(L_ENDIAN) && (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__)
+# error "L_ENDIAN defined on a big endian machine"
+# endif
+# if defined(B_ENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+# error "B_ENDIAN defined on a little endian machine"
+# endif
+# if !defined(L_ENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+# define L_ENDIAN
+# endif
+# if !defined(B_ENDIAN) && (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__)
+# define B_ENDIAN
+# endif
+# else
+# define DECLARE_IS_ENDIAN \
+ const union { \
+ long one; \
+ char little; \
+ } ossl_is_endian = { 1 }
+
+# define IS_LITTLE_ENDIAN (ossl_is_endian.little != 0)
+# define IS_BIG_ENDIAN (ossl_is_endian.little == 0)
+# endif
+
+#endif
diff --git a/include/internal/err.h b/include/internal/err.h
index 88dde7059157..d8a308f0b46f 100644
--- a/include/internal/err.h
+++ b/include/internal/err.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,6 +9,7 @@
#ifndef OSSL_INTERNAL_ERR_H
# define OSSL_INTERNAL_ERR_H
+# pragma once
void err_free_strings_int(void);
diff --git a/include/internal/ffc.h b/include/internal/ffc.h
new file mode 100644
index 000000000000..c4f090875f33
--- /dev/null
+++ b/include/internal/ffc.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_FFC_H
+# define OSSL_INTERNAL_FFC_H
+# pragma once
+
+# include <openssl/core.h>
+# include <openssl/bn.h>
+# include <openssl/evp.h>
+# include <openssl/dh.h> /* Uses Error codes from DH */
+# include <openssl/params.h>
+# include <openssl/param_build.h>
+# include "internal/sizes.h"
+
+/* Default value for gindex when canonical generation of g is not used */
+# define FFC_UNVERIFIABLE_GINDEX -1
+
+/* The different types of FFC keys */
+# define FFC_PARAM_TYPE_DSA 0
+# define FFC_PARAM_TYPE_DH 1
+
+/*
+ * The mode used by functions that share code for both generation and
+ * verification. See ossl_ffc_params_FIPS186_4_gen_verify().
+ */
+#define FFC_PARAM_MODE_VERIFY 0
+#define FFC_PARAM_MODE_GENERATE 1
+
+/* Return codes for generation and validation of FFC parameters */
+#define FFC_PARAM_RET_STATUS_FAILED 0
+#define FFC_PARAM_RET_STATUS_SUCCESS 1
+/* Returned if validating and g is only partially verifiable */
+#define FFC_PARAM_RET_STATUS_UNVERIFIABLE_G 2
+
+/* Validation flags */
+# define FFC_PARAM_FLAG_VALIDATE_PQ 0x01
+# define FFC_PARAM_FLAG_VALIDATE_G 0x02
+# define FFC_PARAM_FLAG_VALIDATE_PQG \
+ (FFC_PARAM_FLAG_VALIDATE_PQ | FFC_PARAM_FLAG_VALIDATE_G)
+#define FFC_PARAM_FLAG_VALIDATE_LEGACY 0x04
+
+/*
+ * NB: These values must align with the equivalently named macros in
+ * openssl/dh.h. We cannot use those macros here in case DH has been disabled.
+ */
+# define FFC_CHECK_P_NOT_PRIME 0x00001
+# define FFC_CHECK_P_NOT_SAFE_PRIME 0x00002
+# define FFC_CHECK_UNKNOWN_GENERATOR 0x00004
+# define FFC_CHECK_NOT_SUITABLE_GENERATOR 0x00008
+# define FFC_CHECK_Q_NOT_PRIME 0x00010
+# define FFC_CHECK_INVALID_Q_VALUE 0x00020
+# define FFC_CHECK_INVALID_J_VALUE 0x00040
+
+# define FFC_CHECK_BAD_LN_PAIR 0x00080
+# define FFC_CHECK_INVALID_SEED_SIZE 0x00100
+# define FFC_CHECK_MISSING_SEED_OR_COUNTER 0x00200
+# define FFC_CHECK_INVALID_G 0x00400
+# define FFC_CHECK_INVALID_PQ 0x00800
+# define FFC_CHECK_INVALID_COUNTER 0x01000
+# define FFC_CHECK_P_MISMATCH 0x02000
+# define FFC_CHECK_Q_MISMATCH 0x04000
+# define FFC_CHECK_G_MISMATCH 0x08000
+# define FFC_CHECK_COUNTER_MISMATCH 0x10000
+
+/* Validation Return codes */
+# define FFC_ERROR_PUBKEY_TOO_SMALL 0x01
+# define FFC_ERROR_PUBKEY_TOO_LARGE 0x02
+# define FFC_ERROR_PUBKEY_INVALID 0x04
+# define FFC_ERROR_NOT_SUITABLE_GENERATOR 0x08
+# define FFC_ERROR_PRIVKEY_TOO_SMALL 0x10
+# define FFC_ERROR_PRIVKEY_TOO_LARGE 0x20
+# define FFC_ERROR_PASSED_NULL_PARAM 0x40
+
+/*
+ * Finite field cryptography (FFC) domain parameters are used by DH and DSA.
+ * Refer to FIPS186_4 Appendix A & B.
+ */
+typedef struct ffc_params_st {
+ /* Primes */
+ BIGNUM *p;
+ BIGNUM *q;
+ /* Generator */
+ BIGNUM *g;
+ /* DH X9.42 Optional Subgroup factor j >= 2 where p = j * q + 1 */
+ BIGNUM *j;
+
+ /* Required for FIPS186_4 validation of p, q and optionally canonical g */
+ unsigned char *seed;
+ /* If this value is zero the hash size is used as the seed length */
+ size_t seedlen;
+ /* Required for FIPS186_4 validation of p and q */
+ int pcounter;
+ int nid; /* The identity of a named group */
+
+ /*
+ * Required for FIPS186_4 generation & validation of canonical g.
+ * It uses unverifiable g if this value is -1.
+ */
+ int gindex;
+ int h; /* loop counter for unverifiable g */
+
+ unsigned int flags;
+ /*
+ * The digest to use for generation or validation. If this value is NULL,
+ * then the digest is chosen using the value of N.
+ */
+ const char *mdname;
+ const char *mdprops;
+ /* Default key length for known named groups according to RFC7919 */
+ int keylength;
+} FFC_PARAMS;
+
+void ossl_ffc_params_init(FFC_PARAMS *params);
+void ossl_ffc_params_cleanup(FFC_PARAMS *params);
+void ossl_ffc_params_set0_pqg(FFC_PARAMS *params, BIGNUM *p, BIGNUM *q,
+ BIGNUM *g);
+void ossl_ffc_params_get0_pqg(const FFC_PARAMS *params, const BIGNUM **p,
+ const BIGNUM **q, const BIGNUM **g);
+void ossl_ffc_params_set0_j(FFC_PARAMS *d, BIGNUM *j);
+int ossl_ffc_params_set_seed(FFC_PARAMS *params,
+ const unsigned char *seed, size_t seedlen);
+void ossl_ffc_params_set_gindex(FFC_PARAMS *params, int index);
+void ossl_ffc_params_set_pcounter(FFC_PARAMS *params, int index);
+void ossl_ffc_params_set_h(FFC_PARAMS *params, int index);
+void ossl_ffc_params_set_flags(FFC_PARAMS *params, unsigned int flags);
+void ossl_ffc_params_enable_flags(FFC_PARAMS *params, unsigned int flags,
+ int enable);
+int ossl_ffc_set_digest(FFC_PARAMS *params, const char *alg, const char *props);
+
+int ossl_ffc_params_set_validate_params(FFC_PARAMS *params,
+ const unsigned char *seed,
+ size_t seedlen, int counter);
+void ossl_ffc_params_get_validate_params(const FFC_PARAMS *params,
+ unsigned char **seed, size_t *seedlen,
+ int *pcounter);
+
+int ossl_ffc_params_copy(FFC_PARAMS *dst, const FFC_PARAMS *src);
+int ossl_ffc_params_cmp(const FFC_PARAMS *a, const FFC_PARAMS *b, int ignore_q);
+
+#ifndef FIPS_MODULE
+int ossl_ffc_params_print(BIO *bp, const FFC_PARAMS *ffc, int indent);
+#endif /* FIPS_MODULE */
+
+
+int ossl_ffc_params_FIPS186_4_generate(OSSL_LIB_CTX *libctx, FFC_PARAMS *params,
+ int type, size_t L, size_t N,
+ int *res, BN_GENCB *cb);
+int ossl_ffc_params_FIPS186_2_generate(OSSL_LIB_CTX *libctx, FFC_PARAMS *params,
+ int type, size_t L, size_t N,
+ int *res, BN_GENCB *cb);
+
+int ossl_ffc_params_FIPS186_4_gen_verify(OSSL_LIB_CTX *libctx,
+ FFC_PARAMS *params, int mode, int type,
+ size_t L, size_t N, int *res,
+ BN_GENCB *cb);
+int ossl_ffc_params_FIPS186_2_gen_verify(OSSL_LIB_CTX *libctx,
+ FFC_PARAMS *params, int mode, int type,
+ size_t L, size_t N, int *res,
+ BN_GENCB *cb);
+
+int ossl_ffc_params_simple_validate(OSSL_LIB_CTX *libctx,
+ const FFC_PARAMS *params,
+ int paramstype, int *res);
+int ossl_ffc_params_full_validate(OSSL_LIB_CTX *libctx,
+ const FFC_PARAMS *params,
+ int paramstype, int *res);
+int ossl_ffc_params_FIPS186_4_validate(OSSL_LIB_CTX *libctx,
+ const FFC_PARAMS *params,
+ int type, int *res, BN_GENCB *cb);
+int ossl_ffc_params_FIPS186_2_validate(OSSL_LIB_CTX *libctx,
+ const FFC_PARAMS *params,
+ int type, int *res, BN_GENCB *cb);
+
+int ossl_ffc_generate_private_key(BN_CTX *ctx, const FFC_PARAMS *params,
+ int N, int s, BIGNUM *priv);
+
+int ossl_ffc_params_validate_unverifiable_g(BN_CTX *ctx, BN_MONT_CTX *mont,
+ const BIGNUM *p, const BIGNUM *q,
+ const BIGNUM *g, BIGNUM *tmp,
+ int *ret);
+
+int ossl_ffc_validate_public_key(const FFC_PARAMS *params,
+ const BIGNUM *pub_key, int *ret);
+int ossl_ffc_validate_public_key_partial(const FFC_PARAMS *params,
+ const BIGNUM *pub_key, int *ret);
+int ossl_ffc_validate_private_key(const BIGNUM *upper, const BIGNUM *priv_key,
+ int *ret);
+
+int ossl_ffc_params_todata(const FFC_PARAMS *ffc, OSSL_PARAM_BLD *tmpl,
+ OSSL_PARAM params[]);
+int ossl_ffc_params_fromdata(FFC_PARAMS *ffc, const OSSL_PARAM params[]);
+
+typedef struct dh_named_group_st DH_NAMED_GROUP;
+const DH_NAMED_GROUP *ossl_ffc_name_to_dh_named_group(const char *name);
+const DH_NAMED_GROUP *ossl_ffc_uid_to_dh_named_group(int uid);
+#ifndef OPENSSL_NO_DH
+const DH_NAMED_GROUP *ossl_ffc_numbers_to_dh_named_group(const BIGNUM *p,
+ const BIGNUM *q,
+ const BIGNUM *g);
+#endif
+int ossl_ffc_named_group_get_uid(const DH_NAMED_GROUP *group);
+const char *ossl_ffc_named_group_get_name(const DH_NAMED_GROUP *);
+#ifndef OPENSSL_NO_DH
+int ossl_ffc_named_group_get_keylength(const DH_NAMED_GROUP *group);
+const BIGNUM *ossl_ffc_named_group_get_q(const DH_NAMED_GROUP *group);
+int ossl_ffc_named_group_set(FFC_PARAMS *ffc, const DH_NAMED_GROUP *group);
+#endif
+
+#endif /* OSSL_INTERNAL_FFC_H */
diff --git a/include/internal/ktls.h b/include/internal/ktls.h
new file mode 100644
index 000000000000..95492fd0659f
--- /dev/null
+++ b/include/internal/ktls.h
@@ -0,0 +1,404 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#if defined(OPENSSL_SYS_LINUX)
+# ifndef OPENSSL_NO_KTLS
+# include <linux/version.h>
+# if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
+# define OPENSSL_NO_KTLS
+# ifndef PEDANTIC
+# warning "KTLS requires Kernel Headers >= 4.13.0"
+# warning "Skipping Compilation of KTLS"
+# endif
+# endif
+# endif
+#endif
+
+#ifndef HEADER_INTERNAL_KTLS
+# define HEADER_INTERNAL_KTLS
+# pragma once
+
+# ifndef OPENSSL_NO_KTLS
+
+# if defined(__FreeBSD__)
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <sys/ktls.h>
+# include <netinet/in.h>
+# include <netinet/tcp.h>
+# include <openssl/ssl3.h>
+
+# ifndef TCP_RXTLS_ENABLE
+# define OPENSSL_NO_KTLS_RX
+# endif
+# define OPENSSL_KTLS_AES_GCM_128
+# define OPENSSL_KTLS_AES_GCM_256
+# define OPENSSL_KTLS_TLS13
+
+typedef struct tls_enable ktls_crypto_info_t;
+
+/*
+ * FreeBSD does not require any additional steps to enable KTLS before
+ * setting keys.
+ */
+static ossl_inline int ktls_enable(int fd)
+{
+ return 1;
+}
+
+/*
+ * The TCP_TXTLS_ENABLE socket option marks the outgoing socket buffer
+ * as using TLS. If successful, then data sent using this socket will
+ * be encrypted and encapsulated in TLS records using the tls_en
+ * provided here.
+ *
+ * The TCP_RXTLS_ENABLE socket option marks the incoming socket buffer
+ * as using TLS. If successful, then data received for this socket will
+ * be authenticated and decrypted using the tls_en provided here.
+ */
+static ossl_inline int ktls_start(int fd, ktls_crypto_info_t *tls_en, int is_tx)
+{
+ if (is_tx)
+ return setsockopt(fd, IPPROTO_TCP, TCP_TXTLS_ENABLE,
+ tls_en, sizeof(*tls_en)) ? 0 : 1;
+# ifndef OPENSSL_NO_KTLS_RX
+ return setsockopt(fd, IPPROTO_TCP, TCP_RXTLS_ENABLE, tls_en,
+ sizeof(*tls_en)) ? 0 : 1;
+# else
+ return 0;
+# endif
+}
+
+/*
+ * Send a TLS record using the tls_en provided in ktls_start and use
+ * record_type instead of the default SSL3_RT_APPLICATION_DATA.
+ * When the socket is non-blocking, then this call either returns EAGAIN or
+ * the entire record is pushed to TCP. It is impossible to send a partial
+ * record using this control message.
+ */
+static ossl_inline int ktls_send_ctrl_message(int fd, unsigned char record_type,
+ const void *data, size_t length)
+{
+ struct msghdr msg = { 0 };
+ int cmsg_len = sizeof(record_type);
+ struct cmsghdr *cmsg;
+ char buf[CMSG_SPACE(cmsg_len)];
+ struct iovec msg_iov; /* Vector of data to send/receive into */
+
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof(buf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = IPPROTO_TCP;
+ cmsg->cmsg_type = TLS_SET_RECORD_TYPE;
+ cmsg->cmsg_len = CMSG_LEN(cmsg_len);
+ *((unsigned char *)CMSG_DATA(cmsg)) = record_type;
+ msg.msg_controllen = cmsg->cmsg_len;
+
+ msg_iov.iov_base = (void *)data;
+ msg_iov.iov_len = length;
+ msg.msg_iov = &msg_iov;
+ msg.msg_iovlen = 1;
+
+ return sendmsg(fd, &msg, 0);
+}
+
+# ifdef OPENSSL_NO_KTLS_RX
+
+static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
+{
+ return -1;
+}
+
+# else /* !defined(OPENSSL_NO_KTLS_RX) */
+
+/*
+ * Receive a TLS record using the tls_en provided in ktls_start. The
+ * kernel strips any explicit IV and authentication tag, but provides
+ * the TLS record header via a control message. If there is an error
+ * with the TLS record such as an invalid header, invalid padding, or
+ * authentication failure recvmsg() will fail with an error.
+ */
+static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
+{
+ struct msghdr msg = { 0 };
+ int cmsg_len = sizeof(struct tls_get_record);
+ struct tls_get_record *tgr;
+ struct cmsghdr *cmsg;
+ char buf[CMSG_SPACE(cmsg_len)];
+ struct iovec msg_iov; /* Vector of data to send/receive into */
+ int ret;
+ unsigned char *p = data;
+ const size_t prepend_length = SSL3_RT_HEADER_LENGTH;
+
+ if (length <= prepend_length) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof(buf);
+
+ msg_iov.iov_base = p + prepend_length;
+ msg_iov.iov_len = length - prepend_length;
+ msg.msg_iov = &msg_iov;
+ msg.msg_iovlen = 1;
+
+ ret = recvmsg(fd, &msg, 0);
+ if (ret <= 0)
+ return ret;
+
+ if ((msg.msg_flags & (MSG_EOR | MSG_CTRUNC)) != MSG_EOR) {
+ errno = EMSGSIZE;
+ return -1;
+ }
+
+ if (msg.msg_controllen == 0) {
+ errno = EBADMSG;
+ return -1;
+ }
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ if (cmsg->cmsg_level != IPPROTO_TCP || cmsg->cmsg_type != TLS_GET_RECORD
+ || cmsg->cmsg_len != CMSG_LEN(cmsg_len)) {
+ errno = EBADMSG;
+ return -1;
+ }
+
+ tgr = (struct tls_get_record *)CMSG_DATA(cmsg);
+ p[0] = tgr->tls_type;
+ p[1] = tgr->tls_vmajor;
+ p[2] = tgr->tls_vminor;
+ *(uint16_t *)(p + 3) = htons(ret);
+
+ return ret + prepend_length;
+}
+
+# endif /* OPENSSL_NO_KTLS_RX */
+
+/*
+ * KTLS enables the sendfile system call to send data from a file over
+ * TLS.
+ */
+static ossl_inline ossl_ssize_t ktls_sendfile(int s, int fd, off_t off,
+ size_t size, int flags)
+{
+ off_t sbytes = 0;
+ int ret;
+
+ ret = sendfile(fd, s, off, size, NULL, &sbytes, flags);
+ if (ret == -1 && sbytes == 0)
+ return -1;
+ return sbytes;
+}
+
+# endif /* __FreeBSD__ */
+
+# if defined(OPENSSL_SYS_LINUX)
+
+# include <linux/tls.h>
+# if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)
+# define OPENSSL_NO_KTLS_RX
+# ifndef PEDANTIC
+# warning "KTLS requires Kernel Headers >= 4.17.0 for receiving"
+# warning "Skipping Compilation of KTLS receive data path"
+# endif
+# endif
+# define OPENSSL_KTLS_AES_GCM_128
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)
+# define OPENSSL_KTLS_AES_GCM_256
+# define OPENSSL_KTLS_TLS13
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)
+# define OPENSSL_KTLS_AES_CCM_128
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
+# ifndef OPENSSL_NO_CHACHA
+# define OPENSSL_KTLS_CHACHA20_POLY1305
+# endif
+# endif
+# endif
+# endif
+
+# include <sys/sendfile.h>
+# include <netinet/tcp.h>
+# include <linux/socket.h>
+# include <openssl/ssl3.h>
+# include <openssl/tls1.h>
+# include <openssl/evp.h>
+
+# ifndef SOL_TLS
+# define SOL_TLS 282
+# endif
+
+# ifndef TCP_ULP
+# define TCP_ULP 31
+# endif
+
+# ifndef TLS_RX
+# define TLS_RX 2
+# endif
+
+struct tls_crypto_info_all {
+ union {
+# ifdef OPENSSL_KTLS_AES_GCM_128
+ struct tls12_crypto_info_aes_gcm_128 gcm128;
+# endif
+# ifdef OPENSSL_KTLS_AES_GCM_256
+ struct tls12_crypto_info_aes_gcm_256 gcm256;
+# endif
+# ifdef OPENSSL_KTLS_AES_CCM_128
+ struct tls12_crypto_info_aes_ccm_128 ccm128;
+# endif
+# ifdef OPENSSL_KTLS_CHACHA20_POLY1305
+ struct tls12_crypto_info_chacha20_poly1305 chacha20poly1305;
+# endif
+ };
+ size_t tls_crypto_info_len;
+};
+
+typedef struct tls_crypto_info_all ktls_crypto_info_t;
+
+/*
+ * When successful, this socket option doesn't change the behaviour of the
+ * TCP socket, except changing the TCP setsockopt handler to enable the
+ * processing of SOL_TLS socket options. All other functionality remains the
+ * same.
+ */
+static ossl_inline int ktls_enable(int fd)
+{
+ return setsockopt(fd, SOL_TCP, TCP_ULP, "tls", sizeof("tls")) ? 0 : 1;
+}
+
+/*
+ * The TLS_TX socket option changes the send/sendmsg handlers of the TCP socket.
+ * If successful, then data sent using this socket will be encrypted and
+ * encapsulated in TLS records using the crypto_info provided here.
+ * The TLS_RX socket option changes the recv/recvmsg handlers of the TCP socket.
+ * If successful, then data received using this socket will be decrypted,
+ * authenticated and decapsulated using the crypto_info provided here.
+ */
+static ossl_inline int ktls_start(int fd, ktls_crypto_info_t *crypto_info,
+ int is_tx)
+{
+ return setsockopt(fd, SOL_TLS, is_tx ? TLS_TX : TLS_RX,
+ crypto_info, crypto_info->tls_crypto_info_len) ? 0 : 1;
+}
+
+/*
+ * Send a TLS record using the crypto_info provided in ktls_start and use
+ * record_type instead of the default SSL3_RT_APPLICATION_DATA.
+ * When the socket is non-blocking, then this call either returns EAGAIN or
+ * the entire record is pushed to TCP. It is impossible to send a partial
+ * record using this control message.
+ */
+static ossl_inline int ktls_send_ctrl_message(int fd, unsigned char record_type,
+ const void *data, size_t length)
+{
+ struct msghdr msg;
+ int cmsg_len = sizeof(record_type);
+ struct cmsghdr *cmsg;
+ union {
+ struct cmsghdr hdr;
+ char buf[CMSG_SPACE(sizeof(unsigned char))];
+ } cmsgbuf;
+ struct iovec msg_iov; /* Vector of data to send/receive into */
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_control = cmsgbuf.buf;
+ msg.msg_controllen = sizeof(cmsgbuf.buf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_TLS;
+ cmsg->cmsg_type = TLS_SET_RECORD_TYPE;
+ cmsg->cmsg_len = CMSG_LEN(cmsg_len);
+ *((unsigned char *)CMSG_DATA(cmsg)) = record_type;
+ msg.msg_controllen = cmsg->cmsg_len;
+
+ msg_iov.iov_base = (void *)data;
+ msg_iov.iov_len = length;
+ msg.msg_iov = &msg_iov;
+ msg.msg_iovlen = 1;
+
+ return sendmsg(fd, &msg, 0);
+}
+
+/*
+ * KTLS enables the sendfile system call to send data from a file over TLS.
+ * @flags are ignored on Linux. (placeholder for FreeBSD sendfile)
+ * */
+static ossl_inline ossl_ssize_t ktls_sendfile(int s, int fd, off_t off, size_t size, int flags)
+{
+ return sendfile(s, fd, &off, size);
+}
+
+# ifdef OPENSSL_NO_KTLS_RX
+
+
+static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
+{
+ return -1;
+}
+
+# else /* !defined(OPENSSL_NO_KTLS_RX) */
+
+/*
+ * Receive a TLS record using the crypto_info provided in ktls_start.
+ * The kernel strips the TLS record header, IV and authentication tag,
+ * returning only the plaintext data or an error on failure.
+ * We add the TLS record header here to satisfy routines in rec_layer_s3.c
+ */
+static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
+{
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ union {
+ struct cmsghdr hdr;
+ char buf[CMSG_SPACE(sizeof(unsigned char))];
+ } cmsgbuf;
+ struct iovec msg_iov;
+ int ret;
+ unsigned char *p = data;
+ const size_t prepend_length = SSL3_RT_HEADER_LENGTH;
+
+ if (length < prepend_length + EVP_GCM_TLS_TAG_LEN) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_control = cmsgbuf.buf;
+ msg.msg_controllen = sizeof(cmsgbuf.buf);
+
+ msg_iov.iov_base = p + prepend_length;
+ msg_iov.iov_len = length - prepend_length - EVP_GCM_TLS_TAG_LEN;
+ msg.msg_iov = &msg_iov;
+ msg.msg_iovlen = 1;
+
+ ret = recvmsg(fd, &msg, 0);
+ if (ret < 0)
+ return ret;
+
+ if (msg.msg_controllen > 0) {
+ cmsg = CMSG_FIRSTHDR(&msg);
+ if (cmsg->cmsg_type == TLS_GET_RECORD_TYPE) {
+ p[0] = *((unsigned char *)CMSG_DATA(cmsg));
+ p[1] = TLS1_2_VERSION_MAJOR;
+ p[2] = TLS1_2_VERSION_MINOR;
+ /* returned length is limited to msg_iov.iov_len above */
+ p[3] = (ret >> 8) & 0xff;
+ p[4] = ret & 0xff;
+ ret += prepend_length;
+ }
+ }
+
+ return ret;
+}
+
+# endif /* OPENSSL_NO_KTLS_RX */
+
+# endif /* OPENSSL_SYS_LINUX */
+# endif /* OPENSSL_NO_KTLS */
+#endif /* HEADER_INTERNAL_KTLS */
diff --git a/include/internal/namemap.h b/include/internal/namemap.h
new file mode 100644
index 000000000000..a4c60ae695c9
--- /dev/null
+++ b/include/internal/namemap.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/cryptlib.h"
+
+typedef struct ossl_namemap_st OSSL_NAMEMAP;
+
+OSSL_NAMEMAP *ossl_namemap_stored(OSSL_LIB_CTX *libctx);
+
+OSSL_NAMEMAP *ossl_namemap_new(void);
+void ossl_namemap_free(OSSL_NAMEMAP *namemap);
+int ossl_namemap_empty(OSSL_NAMEMAP *namemap);
+
+int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number, const char *name);
+int ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number,
+ const char *name, size_t name_len);
+
+/*
+ * The number<->name relationship is 1<->many
+ * Therefore, the name->number mapping is a simple function, while the
+ * number->name mapping is an iterator.
+ */
+int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name);
+int ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap,
+ const char *name, size_t name_len);
+const char *ossl_namemap_num2name(const OSSL_NAMEMAP *namemap, int number,
+ size_t idx);
+int ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number,
+ void (*fn)(const char *name, void *data),
+ void *data);
+
+/*
+ * A utility that handles several names in a string, divided by a given
+ * separator.
+ */
+int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number,
+ const char *names, const char separator);
diff --git a/include/internal/nelem.h b/include/internal/nelem.h
index 699ef88ee523..b758513b4cae 100644
--- a/include/internal/nelem.h
+++ b/include/internal/nelem.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,6 +9,7 @@
#ifndef OSSL_INTERNAL_NELEM_H
# define OSSL_INTERNAL_NELEM_H
+# pragma once
# define OSSL_NELEM(x) (sizeof(x)/sizeof((x)[0]))
#endif
diff --git a/include/internal/numbers.h b/include/internal/numbers.h
index f5ade5226e5b..4f4d3306d5da 100644
--- a/include/internal/numbers.h
+++ b/include/internal/numbers.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,22 +9,23 @@
#ifndef OSSL_INTERNAL_NUMBERS_H
# define OSSL_INTERNAL_NUMBERS_H
+# pragma once
# include <limits.h>
-# if (-1 & 3) == 0x03 /* Two's complement */
+# if (-1 & 3) == 0x03 /* Two's complement */
# define __MAXUINT__(T) ((T) -1)
# define __MAXINT__(T) ((T) ((((T) 1) << ((sizeof(T) * CHAR_BIT) - 1)) ^ __MAXUINT__(T)))
# define __MININT__(T) (-__MAXINT__(T) - 1)
-# elif (-1 & 3) == 0x02 /* One's complement */
+# elif (-1 & 3) == 0x02 /* One's complement */
# define __MAXUINT__(T) (((T) -1) + 1)
# define __MAXINT__(T) ((T) ((((T) 1) << ((sizeof(T) * CHAR_BIT) - 1)) ^ __MAXUINT__(T)))
# define __MININT__(T) (-__MAXINT__(T))
-# elif (-1 & 3) == 0x01 /* Sign/magnitude */
+# elif (-1 & 3) == 0x01 /* Sign/magnitude */
# define __MAXINT__(T) ((T) (((((T) 1) << ((sizeof(T) * CHAR_BIT) - 2)) - 1) | (((T) 1) << ((sizeof(T) * CHAR_BIT) - 2))))
# define __MAXUINT__(T) ((T) (__MAXINT__(T) | (((T) 1) << ((sizeof(T) * CHAR_BIT) - 1))))
@@ -60,9 +61,25 @@
# define UINT64_MAX __MAXUINT__(uint64_t)
# endif
+# ifndef INT128_MAX
+# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16
+typedef __int128_t int128_t;
+typedef __uint128_t uint128_t;
+# define INT128_MIN __MININT__(int128_t)
+# define INT128_MAX __MAXINT__(int128_t)
+# define UINT128_MAX __MAXUINT__(uint128_t)
+# endif
+# endif
+
# ifndef SIZE_MAX
# define SIZE_MAX __MAXUINT__(size_t)
# endif
+# ifndef OSSL_INTMAX_MAX
+# define OSSL_INTMAX_MIN __MININT__(ossl_intmax_t)
+# define OSSL_INTMAX_MAX __MAXINT__(ossl_intmax_t)
+# define OSSL_UINTMAX_MAX __MAXUINT__(ossl_uintmax_t)
+# endif
+
#endif
diff --git a/include/internal/o_dir.h b/include/internal/o_dir.h
index dafc8dd2e74b..add34d14be11 100644
--- a/include/internal/o_dir.h
+++ b/include/internal/o_dir.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -38,6 +38,7 @@
#ifndef OSSL_INTERNAL_O_DIR_H
# define OSSL_INTERNAL_O_DIR_H
+# pragma once
typedef struct OPENSSL_dir_context_st OPENSSL_DIR_CTX;
diff --git a/include/internal/o_str.h b/include/internal/o_str.h
deleted file mode 100644
index 15c12e820d2b..000000000000
--- a/include/internal/o_str.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2003-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef OSSL_INTERNAL_O_STR_H
-# define OSSL_INTERNAL_O_STR_H
-
-# include <stddef.h> /* to get size_t */
-
-int OPENSSL_memcmp(const void *p1, const void *p2, size_t n);
-
-#endif
diff --git a/include/internal/packet.h b/include/internal/packet.h
new file mode 100644
index 000000000000..ed76172078a4
--- /dev/null
+++ b/include/internal/packet.h
@@ -0,0 +1,937 @@
+/*
+ * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_PACKET_H
+# define OSSL_INTERNAL_PACKET_H
+# pragma once
+
+# include <string.h>
+# include <openssl/bn.h>
+# include <openssl/buffer.h>
+# include <openssl/crypto.h>
+# include <openssl/e_os2.h>
+
+# include "internal/numbers.h"
+
+typedef struct {
+ /* Pointer to where we are currently reading from */
+ const unsigned char *curr;
+ /* Number of bytes remaining */
+ size_t remaining;
+} PACKET;
+
+/* Internal unchecked shorthand; don't use outside this file. */
+static ossl_inline void packet_forward(PACKET *pkt, size_t len)
+{
+ pkt->curr += len;
+ pkt->remaining -= len;
+}
+
+/*
+ * Returns the number of bytes remaining to be read in the PACKET
+ */
+static ossl_inline size_t PACKET_remaining(const PACKET *pkt)
+{
+ return pkt->remaining;
+}
+
+/*
+ * Returns a pointer to the first byte after the packet data.
+ * Useful for integrating with non-PACKET parsing code.
+ * Specifically, we use PACKET_end() to verify that a d2i_... call
+ * has consumed the entire packet contents.
+ */
+static ossl_inline const unsigned char *PACKET_end(const PACKET *pkt)
+{
+ return pkt->curr + pkt->remaining;
+}
+
+/*
+ * Returns a pointer to the PACKET's current position.
+ * For use in non-PACKETized APIs.
+ */
+static ossl_inline const unsigned char *PACKET_data(const PACKET *pkt)
+{
+ return pkt->curr;
+}
+
+/*
+ * Initialise a PACKET with |len| bytes held in |buf|. This does not make a
+ * copy of the data so |buf| must be present for the whole time that the PACKET
+ * is being used.
+ */
+__owur static ossl_inline int PACKET_buf_init(PACKET *pkt,
+ const unsigned char *buf,
+ size_t len)
+{
+ /* Sanity check for negative values. */
+ if (len > (size_t)(SIZE_MAX / 2))
+ return 0;
+
+ pkt->curr = buf;
+ pkt->remaining = len;
+ return 1;
+}
+
+/* Initialize a PACKET to hold zero bytes. */
+static ossl_inline void PACKET_null_init(PACKET *pkt)
+{
+ pkt->curr = NULL;
+ pkt->remaining = 0;
+}
+
+/*
+ * Returns 1 if the packet has length |num| and its contents equal the |num|
+ * bytes read from |ptr|. Returns 0 otherwise (lengths or contents not equal).
+ * If lengths are equal, performs the comparison in constant time.
+ */
+__owur static ossl_inline int PACKET_equal(const PACKET *pkt, const void *ptr,
+ size_t num)
+{
+ if (PACKET_remaining(pkt) != num)
+ return 0;
+ return CRYPTO_memcmp(pkt->curr, ptr, num) == 0;
+}
+
+/*
+ * Peek ahead and initialize |subpkt| with the next |len| bytes read from |pkt|.
+ * Data is not copied: the |subpkt| packet will share its underlying buffer with
+ * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
+ */
+__owur static ossl_inline int PACKET_peek_sub_packet(const PACKET *pkt,
+ PACKET *subpkt, size_t len)
+{
+ if (PACKET_remaining(pkt) < len)
+ return 0;
+
+ return PACKET_buf_init(subpkt, pkt->curr, len);
+}
+
+/*
+ * Initialize |subpkt| with the next |len| bytes read from |pkt|. Data is not
+ * copied: the |subpkt| packet will share its underlying buffer with the
+ * original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
+ */
+__owur static ossl_inline int PACKET_get_sub_packet(PACKET *pkt,
+ PACKET *subpkt, size_t len)
+{
+ if (!PACKET_peek_sub_packet(pkt, subpkt, len))
+ return 0;
+
+ packet_forward(pkt, len);
+
+ return 1;
+}
+
+/*
+ * Peek ahead at 2 bytes in network order from |pkt| and store the value in
+ * |*data|
+ */
+__owur static ossl_inline int PACKET_peek_net_2(const PACKET *pkt,
+ unsigned int *data)
+{
+ if (PACKET_remaining(pkt) < 2)
+ return 0;
+
+ *data = ((unsigned int)(*pkt->curr)) << 8;
+ *data |= *(pkt->curr + 1);
+
+ return 1;
+}
+
+/* Equivalent of n2s */
+/* Get 2 bytes in network order from |pkt| and store the value in |*data| */
+__owur static ossl_inline int PACKET_get_net_2(PACKET *pkt, unsigned int *data)
+{
+ if (!PACKET_peek_net_2(pkt, data))
+ return 0;
+
+ packet_forward(pkt, 2);
+
+ return 1;
+}
+
+/* Same as PACKET_get_net_2() but for a size_t */
+__owur static ossl_inline int PACKET_get_net_2_len(PACKET *pkt, size_t *data)
+{
+ unsigned int i;
+ int ret = PACKET_get_net_2(pkt, &i);
+
+ if (ret)
+ *data = (size_t)i;
+
+ return ret;
+}
+
+/*
+ * Peek ahead at 3 bytes in network order from |pkt| and store the value in
+ * |*data|
+ */
+__owur static ossl_inline int PACKET_peek_net_3(const PACKET *pkt,
+ unsigned long *data)
+{
+ if (PACKET_remaining(pkt) < 3)
+ return 0;
+
+ *data = ((unsigned long)(*pkt->curr)) << 16;
+ *data |= ((unsigned long)(*(pkt->curr + 1))) << 8;
+ *data |= *(pkt->curr + 2);
+
+ return 1;
+}
+
+/* Equivalent of n2l3 */
+/* Get 3 bytes in network order from |pkt| and store the value in |*data| */
+__owur static ossl_inline int PACKET_get_net_3(PACKET *pkt, unsigned long *data)
+{
+ if (!PACKET_peek_net_3(pkt, data))
+ return 0;
+
+ packet_forward(pkt, 3);
+
+ return 1;
+}
+
+/* Same as PACKET_get_net_3() but for a size_t */
+__owur static ossl_inline int PACKET_get_net_3_len(PACKET *pkt, size_t *data)
+{
+ unsigned long i;
+ int ret = PACKET_get_net_3(pkt, &i);
+
+ if (ret)
+ *data = (size_t)i;
+
+ return ret;
+}
+
+/*
+ * Peek ahead at 4 bytes in network order from |pkt| and store the value in
+ * |*data|
+ */
+__owur static ossl_inline int PACKET_peek_net_4(const PACKET *pkt,
+ unsigned long *data)
+{
+ if (PACKET_remaining(pkt) < 4)
+ return 0;
+
+ *data = ((unsigned long)(*pkt->curr)) << 24;
+ *data |= ((unsigned long)(*(pkt->curr + 1))) << 16;
+ *data |= ((unsigned long)(*(pkt->curr + 2))) << 8;
+ *data |= *(pkt->curr + 3);
+
+ return 1;
+}
+
+/*
+ * Peek ahead at 8 bytes in network order from |pkt| and store the value in
+ * |*data|
+ */
+__owur static ossl_inline int PACKET_peek_net_8(const PACKET *pkt,
+ uint64_t *data)
+{
+ if (PACKET_remaining(pkt) < 8)
+ return 0;
+
+ *data = ((uint64_t)(*pkt->curr)) << 56;
+ *data |= ((uint64_t)(*(pkt->curr + 1))) << 48;
+ *data |= ((uint64_t)(*(pkt->curr + 2))) << 40;
+ *data |= ((uint64_t)(*(pkt->curr + 3))) << 32;
+ *data |= ((uint64_t)(*(pkt->curr + 4))) << 24;
+ *data |= ((uint64_t)(*(pkt->curr + 5))) << 16;
+ *data |= ((uint64_t)(*(pkt->curr + 6))) << 8;
+ *data |= *(pkt->curr + 7);
+
+ return 1;
+}
+
+/* Equivalent of n2l */
+/* Get 4 bytes in network order from |pkt| and store the value in |*data| */
+__owur static ossl_inline int PACKET_get_net_4(PACKET *pkt, unsigned long *data)
+{
+ if (!PACKET_peek_net_4(pkt, data))
+ return 0;
+
+ packet_forward(pkt, 4);
+
+ return 1;
+}
+
+/* Same as PACKET_get_net_4() but for a size_t */
+__owur static ossl_inline int PACKET_get_net_4_len(PACKET *pkt, size_t *data)
+{
+ unsigned long i;
+ int ret = PACKET_get_net_4(pkt, &i);
+
+ if (ret)
+ *data = (size_t)i;
+
+ return ret;
+}
+
+/* Get 8 bytes in network order from |pkt| and store the value in |*data| */
+__owur static ossl_inline int PACKET_get_net_8(PACKET *pkt, uint64_t *data)
+{
+ if (!PACKET_peek_net_8(pkt, data))
+ return 0;
+
+ packet_forward(pkt, 8);
+
+ return 1;
+}
+
+/* Peek ahead at 1 byte from |pkt| and store the value in |*data| */
+__owur static ossl_inline int PACKET_peek_1(const PACKET *pkt,
+ unsigned int *data)
+{
+ if (!PACKET_remaining(pkt))
+ return 0;
+
+ *data = *pkt->curr;
+
+ return 1;
+}
+
+/* Get 1 byte from |pkt| and store the value in |*data| */
+__owur static ossl_inline int PACKET_get_1(PACKET *pkt, unsigned int *data)
+{
+ if (!PACKET_peek_1(pkt, data))
+ return 0;
+
+ packet_forward(pkt, 1);
+
+ return 1;
+}
+
+/* Same as PACKET_get_1() but for a size_t */
+__owur static ossl_inline int PACKET_get_1_len(PACKET *pkt, size_t *data)
+{
+ unsigned int i;
+ int ret = PACKET_get_1(pkt, &i);
+
+ if (ret)
+ *data = (size_t)i;
+
+ return ret;
+}
+
+/*
+ * Peek ahead at 4 bytes in reverse network order from |pkt| and store the value
+ * in |*data|
+ */
+__owur static ossl_inline int PACKET_peek_4(const PACKET *pkt,
+ unsigned long *data)
+{
+ if (PACKET_remaining(pkt) < 4)
+ return 0;
+
+ *data = *pkt->curr;
+ *data |= ((unsigned long)(*(pkt->curr + 1))) << 8;
+ *data |= ((unsigned long)(*(pkt->curr + 2))) << 16;
+ *data |= ((unsigned long)(*(pkt->curr + 3))) << 24;
+
+ return 1;
+}
+
+/* Equivalent of c2l */
+/*
+ * Get 4 bytes in reverse network order from |pkt| and store the value in
+ * |*data|
+ */
+__owur static ossl_inline int PACKET_get_4(PACKET *pkt, unsigned long *data)
+{
+ if (!PACKET_peek_4(pkt, data))
+ return 0;
+
+ packet_forward(pkt, 4);
+
+ return 1;
+}
+
+/*
+ * Peek ahead at |len| bytes from the |pkt| and store a pointer to them in
+ * |*data|. This just points at the underlying buffer that |pkt| is using. The
+ * caller should not free this data directly (it will be freed when the
+ * underlying buffer gets freed
+ */
+__owur static ossl_inline int PACKET_peek_bytes(const PACKET *pkt,
+ const unsigned char **data,
+ size_t len)
+{
+ if (PACKET_remaining(pkt) < len)
+ return 0;
+
+ *data = pkt->curr;
+
+ return 1;
+}
+
+/*
+ * Read |len| bytes from the |pkt| and store a pointer to them in |*data|. This
+ * just points at the underlying buffer that |pkt| is using. The caller should
+ * not free this data directly (it will be freed when the underlying buffer gets
+ * freed
+ */
+__owur static ossl_inline int PACKET_get_bytes(PACKET *pkt,
+ const unsigned char **data,
+ size_t len)
+{
+ if (!PACKET_peek_bytes(pkt, data, len))
+ return 0;
+
+ packet_forward(pkt, len);
+
+ return 1;
+}
+
+/* Peek ahead at |len| bytes from |pkt| and copy them to |data| */
+__owur static ossl_inline int PACKET_peek_copy_bytes(const PACKET *pkt,
+ unsigned char *data,
+ size_t len)
+{
+ if (PACKET_remaining(pkt) < len)
+ return 0;
+
+ memcpy(data, pkt->curr, len);
+
+ return 1;
+}
+
+/*
+ * Read |len| bytes from |pkt| and copy them to |data|.
+ * The caller is responsible for ensuring that |data| can hold |len| bytes.
+ */
+__owur static ossl_inline int PACKET_copy_bytes(PACKET *pkt,
+ unsigned char *data, size_t len)
+{
+ if (!PACKET_peek_copy_bytes(pkt, data, len))
+ return 0;
+
+ packet_forward(pkt, len);
+
+ return 1;
+}
+
+/*
+ * Copy packet data to |dest|, and set |len| to the number of copied bytes.
+ * If the packet has more than |dest_len| bytes, nothing is copied.
+ * Returns 1 if the packet data fits in |dest_len| bytes, 0 otherwise.
+ * Does not forward PACKET position (because it is typically the last thing
+ * done with a given PACKET).
+ */
+__owur static ossl_inline int PACKET_copy_all(const PACKET *pkt,
+ unsigned char *dest,
+ size_t dest_len, size_t *len)
+{
+ if (PACKET_remaining(pkt) > dest_len) {
+ *len = 0;
+ return 0;
+ }
+ *len = pkt->remaining;
+ memcpy(dest, pkt->curr, pkt->remaining);
+ return 1;
+}
+
+/*
+ * Copy |pkt| bytes to a newly allocated buffer and store a pointer to the
+ * result in |*data|, and the length in |len|.
+ * If |*data| is not NULL, the old data is OPENSSL_free'd.
+ * If the packet is empty, or malloc fails, |*data| will be set to NULL.
+ * Returns 1 if the malloc succeeds and 0 otherwise.
+ * Does not forward PACKET position (because it is typically the last thing
+ * done with a given PACKET).
+ */
+__owur static ossl_inline int PACKET_memdup(const PACKET *pkt,
+ unsigned char **data, size_t *len)
+{
+ size_t length;
+
+ OPENSSL_free(*data);
+ *data = NULL;
+ *len = 0;
+
+ length = PACKET_remaining(pkt);
+
+ if (length == 0)
+ return 1;
+
+ *data = OPENSSL_memdup(pkt->curr, length);
+ if (*data == NULL)
+ return 0;
+
+ *len = length;
+ return 1;
+}
+
+/*
+ * Read a C string from |pkt| and copy to a newly allocated, NUL-terminated
+ * buffer. Store a pointer to the result in |*data|.
+ * If |*data| is not NULL, the old data is OPENSSL_free'd.
+ * If the data in |pkt| does not contain a NUL-byte, the entire data is
+ * copied and NUL-terminated.
+ * Returns 1 if the malloc succeeds and 0 otherwise.
+ * Does not forward PACKET position (because it is typically the last thing done
+ * with a given PACKET).
+ */
+__owur static ossl_inline int PACKET_strndup(const PACKET *pkt, char **data)
+{
+ OPENSSL_free(*data);
+
+ /* This will succeed on an empty packet, unless pkt->curr == NULL. */
+ *data = OPENSSL_strndup((const char *)pkt->curr, PACKET_remaining(pkt));
+ return (*data != NULL);
+}
+
+/* Returns 1 if |pkt| contains at least one 0-byte, 0 otherwise. */
+static ossl_inline int PACKET_contains_zero_byte(const PACKET *pkt)
+{
+ return memchr(pkt->curr, 0, pkt->remaining) != NULL;
+}
+
+/* Move the current reading position forward |len| bytes */
+__owur static ossl_inline int PACKET_forward(PACKET *pkt, size_t len)
+{
+ if (PACKET_remaining(pkt) < len)
+ return 0;
+
+ packet_forward(pkt, len);
+
+ return 1;
+}
+
+/*
+ * Reads a variable-length vector prefixed with a one-byte length, and stores
+ * the contents in |subpkt|. |pkt| can equal |subpkt|.
+ * Data is not copied: the |subpkt| packet will share its underlying buffer with
+ * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
+ * Upon failure, the original |pkt| and |subpkt| are not modified.
+ */
+__owur static ossl_inline int PACKET_get_length_prefixed_1(PACKET *pkt,
+ PACKET *subpkt)
+{
+ unsigned int length;
+ const unsigned char *data;
+ PACKET tmp = *pkt;
+ if (!PACKET_get_1(&tmp, &length) ||
+ !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
+ return 0;
+ }
+
+ *pkt = tmp;
+ subpkt->curr = data;
+ subpkt->remaining = length;
+
+ return 1;
+}
+
+/*
+ * Like PACKET_get_length_prefixed_1, but additionally, fails when there are
+ * leftover bytes in |pkt|.
+ */
+__owur static ossl_inline int PACKET_as_length_prefixed_1(PACKET *pkt,
+ PACKET *subpkt)
+{
+ unsigned int length;
+ const unsigned char *data;
+ PACKET tmp = *pkt;
+ if (!PACKET_get_1(&tmp, &length) ||
+ !PACKET_get_bytes(&tmp, &data, (size_t)length) ||
+ PACKET_remaining(&tmp) != 0) {
+ return 0;
+ }
+
+ *pkt = tmp;
+ subpkt->curr = data;
+ subpkt->remaining = length;
+
+ return 1;
+}
+
+/*
+ * Reads a variable-length vector prefixed with a two-byte length, and stores
+ * the contents in |subpkt|. |pkt| can equal |subpkt|.
+ * Data is not copied: the |subpkt| packet will share its underlying buffer with
+ * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
+ * Upon failure, the original |pkt| and |subpkt| are not modified.
+ */
+__owur static ossl_inline int PACKET_get_length_prefixed_2(PACKET *pkt,
+ PACKET *subpkt)
+{
+ unsigned int length;
+ const unsigned char *data;
+ PACKET tmp = *pkt;
+
+ if (!PACKET_get_net_2(&tmp, &length) ||
+ !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
+ return 0;
+ }
+
+ *pkt = tmp;
+ subpkt->curr = data;
+ subpkt->remaining = length;
+
+ return 1;
+}
+
+/*
+ * Like PACKET_get_length_prefixed_2, but additionally, fails when there are
+ * leftover bytes in |pkt|.
+ */
+__owur static ossl_inline int PACKET_as_length_prefixed_2(PACKET *pkt,
+ PACKET *subpkt)
+{
+ unsigned int length;
+ const unsigned char *data;
+ PACKET tmp = *pkt;
+
+ if (!PACKET_get_net_2(&tmp, &length) ||
+ !PACKET_get_bytes(&tmp, &data, (size_t)length) ||
+ PACKET_remaining(&tmp) != 0) {
+ return 0;
+ }
+
+ *pkt = tmp;
+ subpkt->curr = data;
+ subpkt->remaining = length;
+
+ return 1;
+}
+
+/*
+ * Reads a variable-length vector prefixed with a three-byte length, and stores
+ * the contents in |subpkt|. |pkt| can equal |subpkt|.
+ * Data is not copied: the |subpkt| packet will share its underlying buffer with
+ * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
+ * Upon failure, the original |pkt| and |subpkt| are not modified.
+ */
+__owur static ossl_inline int PACKET_get_length_prefixed_3(PACKET *pkt,
+ PACKET *subpkt)
+{
+ unsigned long length;
+ const unsigned char *data;
+ PACKET tmp = *pkt;
+ if (!PACKET_get_net_3(&tmp, &length) ||
+ !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
+ return 0;
+ }
+
+ *pkt = tmp;
+ subpkt->curr = data;
+ subpkt->remaining = length;
+
+ return 1;
+}
+
+/* Writeable packets */
+
+typedef struct wpacket_sub WPACKET_SUB;
+struct wpacket_sub {
+ /* The parent WPACKET_SUB if we have one or NULL otherwise */
+ WPACKET_SUB *parent;
+
+ /*
+ * Offset into the buffer where the length of this WPACKET goes. We use an
+ * offset in case the buffer grows and gets reallocated.
+ */
+ size_t packet_len;
+
+ /* Number of bytes in the packet_len or 0 if we don't write the length */
+ size_t lenbytes;
+
+ /* Number of bytes written to the buf prior to this packet starting */
+ size_t pwritten;
+
+ /* Flags for this sub-packet */
+ unsigned int flags;
+};
+
+typedef struct wpacket_st WPACKET;
+struct wpacket_st {
+ /* The buffer where we store the output data */
+ BUF_MEM *buf;
+
+ /* Fixed sized buffer which can be used as an alternative to buf */
+ unsigned char *staticbuf;
+
+ /*
+ * Offset into the buffer where we are currently writing. We use an offset
+ * in case the buffer grows and gets reallocated.
+ */
+ size_t curr;
+
+ /* Number of bytes written so far */
+ size_t written;
+
+ /* Maximum number of bytes we will allow to be written to this WPACKET */
+ size_t maxsize;
+
+ /* Our sub-packets (always at least one if not finished) */
+ WPACKET_SUB *subs;
+
+ /* Writing from the end first? */
+ unsigned int endfirst : 1;
+};
+
+/* Flags */
+
+/* Default */
+#define WPACKET_FLAGS_NONE 0
+
+/* Error on WPACKET_close() if no data written to the WPACKET */
+#define WPACKET_FLAGS_NON_ZERO_LENGTH 1
+
+/*
+ * Abandon all changes on WPACKET_close() if no data written to the WPACKET,
+ * i.e. this does not write out a zero packet length
+ */
+#define WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH 2
+
+
+/*
+ * Initialise a WPACKET with the buffer in |buf|. The buffer must exist
+ * for the whole time that the WPACKET is being used. Additionally |lenbytes| of
+ * data is preallocated at the start of the buffer to store the length of the
+ * WPACKET once we know it.
+ */
+int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes);
+
+/*
+ * Same as WPACKET_init_len except there is no preallocation of the WPACKET
+ * length.
+ */
+int WPACKET_init(WPACKET *pkt, BUF_MEM *buf);
+
+/*
+ * Same as WPACKET_init_len except there is no underlying buffer. No data is
+ * ever actually written. We just keep track of how much data would have been
+ * written if a buffer was there.
+ */
+int WPACKET_init_null(WPACKET *pkt, size_t lenbytes);
+
+/*
+ * Same as WPACKET_init_null except we set the WPACKET to assume DER length
+ * encoding for sub-packets.
+ */
+int WPACKET_init_null_der(WPACKET *pkt);
+
+/*
+ * Same as WPACKET_init_len except we do not use a growable BUF_MEM structure.
+ * A fixed buffer of memory |buf| of size |len| is used instead. A failure will
+ * occur if you attempt to write beyond the end of the buffer
+ */
+int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len,
+ size_t lenbytes);
+
+/*
+ * Same as WPACKET_init_static_len except lenbytes is always 0, and we set the
+ * WPACKET to write to the end of the buffer moving towards the start and use
+ * DER length encoding for sub-packets.
+ */
+int WPACKET_init_der(WPACKET *pkt, unsigned char *buf, size_t len);
+
+/*
+ * Set the flags to be applied to the current sub-packet
+ */
+int WPACKET_set_flags(WPACKET *pkt, unsigned int flags);
+
+/*
+ * Closes the most recent sub-packet. It also writes out the length of the
+ * packet to the required location (normally the start of the WPACKET) if
+ * appropriate. The top level WPACKET should be closed using WPACKET_finish()
+ * instead of this function.
+ */
+int WPACKET_close(WPACKET *pkt);
+
+/*
+ * The same as WPACKET_close() but only for the top most WPACKET. Additionally
+ * frees memory resources for this WPACKET.
+ */
+int WPACKET_finish(WPACKET *pkt);
+
+/*
+ * Iterate through all the sub-packets and write out their lengths as if they
+ * were being closed. The lengths will be overwritten with the final lengths
+ * when the sub-packets are eventually closed (which may be different if more
+ * data is added to the WPACKET). This function fails if a sub-packet is of 0
+ * length and WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH is set.
+ */
+int WPACKET_fill_lengths(WPACKET *pkt);
+
+/*
+ * Initialise a new sub-packet. Additionally |lenbytes| of data is preallocated
+ * at the start of the sub-packet to store its length once we know it. Don't
+ * call this directly. Use the convenience macros below instead.
+ */
+int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes);
+
+/*
+ * Convenience macros for calling WPACKET_start_sub_packet_len with different
+ * lengths
+ */
+#define WPACKET_start_sub_packet_u8(pkt) \
+ WPACKET_start_sub_packet_len__((pkt), 1)
+#define WPACKET_start_sub_packet_u16(pkt) \
+ WPACKET_start_sub_packet_len__((pkt), 2)
+#define WPACKET_start_sub_packet_u24(pkt) \
+ WPACKET_start_sub_packet_len__((pkt), 3)
+#define WPACKET_start_sub_packet_u32(pkt) \
+ WPACKET_start_sub_packet_len__((pkt), 4)
+
+/*
+ * Same as WPACKET_start_sub_packet_len__() except no bytes are pre-allocated
+ * for the sub-packet length.
+ */
+int WPACKET_start_sub_packet(WPACKET *pkt);
+
+/*
+ * Allocate bytes in the WPACKET for the output. This reserves the bytes
+ * and counts them as "written", but doesn't actually do the writing. A pointer
+ * to the allocated bytes is stored in |*allocbytes|. |allocbytes| may be NULL.
+ * WARNING: the allocated bytes must be filled in immediately, without further
+ * WPACKET_* calls. If not then the underlying buffer may be realloc'd and
+ * change its location.
+ */
+int WPACKET_allocate_bytes(WPACKET *pkt, size_t len,
+ unsigned char **allocbytes);
+
+/*
+ * The same as WPACKET_allocate_bytes() except additionally a new sub-packet is
+ * started for the allocated bytes, and then closed immediately afterwards. The
+ * number of length bytes for the sub-packet is in |lenbytes|. Don't call this
+ * directly. Use the convenience macros below instead.
+ */
+int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len,
+ unsigned char **allocbytes, size_t lenbytes);
+
+/*
+ * Convenience macros for calling WPACKET_sub_allocate_bytes with different
+ * lengths
+ */
+#define WPACKET_sub_allocate_bytes_u8(pkt, len, bytes) \
+ WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 1)
+#define WPACKET_sub_allocate_bytes_u16(pkt, len, bytes) \
+ WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 2)
+#define WPACKET_sub_allocate_bytes_u24(pkt, len, bytes) \
+ WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 3)
+#define WPACKET_sub_allocate_bytes_u32(pkt, len, bytes) \
+ WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 4)
+
+/*
+ * The same as WPACKET_allocate_bytes() except the reserved bytes are not
+ * actually counted as written. Typically this will be for when we don't know
+ * how big arbitrary data is going to be up front, but we do know what the
+ * maximum size will be. If this function is used, then it should be immediately
+ * followed by a WPACKET_allocate_bytes() call before any other WPACKET
+ * functions are called (unless the write to the allocated bytes is abandoned).
+ *
+ * For example: If we are generating a signature, then the size of that
+ * signature may not be known in advance. We can use WPACKET_reserve_bytes() to
+ * handle this:
+ *
+ * if (!WPACKET_sub_reserve_bytes_u16(&pkt, EVP_PKEY_get_size(pkey), &sigbytes1)
+ * || EVP_SignFinal(md_ctx, sigbytes1, &siglen, pkey) <= 0
+ * || !WPACKET_sub_allocate_bytes_u16(&pkt, siglen, &sigbytes2)
+ * || sigbytes1 != sigbytes2)
+ * goto err;
+ */
+int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes);
+
+/*
+ * The "reserve_bytes" equivalent of WPACKET_sub_allocate_bytes__()
+ */
+int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len,
+ unsigned char **allocbytes, size_t lenbytes);
+
+/*
+ * Convenience macros for WPACKET_sub_reserve_bytes with different lengths
+ */
+#define WPACKET_sub_reserve_bytes_u8(pkt, len, bytes) \
+ WPACKET_reserve_bytes__((pkt), (len), (bytes), 1)
+#define WPACKET_sub_reserve_bytes_u16(pkt, len, bytes) \
+ WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 2)
+#define WPACKET_sub_reserve_bytes_u24(pkt, len, bytes) \
+ WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 3)
+#define WPACKET_sub_reserve_bytes_u32(pkt, len, bytes) \
+ WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 4)
+
+/*
+ * Write the value stored in |val| into the WPACKET. The value will consume
+ * |bytes| amount of storage. An error will occur if |val| cannot be
+ * accommodated in |bytes| storage, e.g. attempting to write the value 256 into
+ * 1 byte will fail. Don't call this directly. Use the convenience macros below
+ * instead.
+ */
+int WPACKET_put_bytes__(WPACKET *pkt, uint64_t val, size_t bytes);
+
+/*
+ * Convenience macros for calling WPACKET_put_bytes with different
+ * lengths
+ */
+#define WPACKET_put_bytes_u8(pkt, val) \
+ WPACKET_put_bytes__((pkt), (val), 1)
+#define WPACKET_put_bytes_u16(pkt, val) \
+ WPACKET_put_bytes__((pkt), (val), 2)
+#define WPACKET_put_bytes_u24(pkt, val) \
+ WPACKET_put_bytes__((pkt), (val), 3)
+#define WPACKET_put_bytes_u32(pkt, val) \
+ WPACKET_put_bytes__((pkt), (val), 4)
+#define WPACKET_put_bytes_u64(pkt, val) \
+ WPACKET_put_bytes__((pkt), (val), 8)
+
+/* Set a maximum size that we will not allow the WPACKET to grow beyond */
+int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize);
+
+/* Copy |len| bytes of data from |*src| into the WPACKET. */
+int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len);
+
+/* Set |len| bytes of data to |ch| into the WPACKET. */
+int WPACKET_memset(WPACKET *pkt, int ch, size_t len);
+
+/*
+ * Copy |len| bytes of data from |*src| into the WPACKET and prefix with its
+ * length (consuming |lenbytes| of data for the length). Don't call this
+ * directly. Use the convenience macros below instead.
+ */
+int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len,
+ size_t lenbytes);
+
+/* Convenience macros for calling WPACKET_sub_memcpy with different lengths */
+#define WPACKET_sub_memcpy_u8(pkt, src, len) \
+ WPACKET_sub_memcpy__((pkt), (src), (len), 1)
+#define WPACKET_sub_memcpy_u16(pkt, src, len) \
+ WPACKET_sub_memcpy__((pkt), (src), (len), 2)
+#define WPACKET_sub_memcpy_u24(pkt, src, len) \
+ WPACKET_sub_memcpy__((pkt), (src), (len), 3)
+#define WPACKET_sub_memcpy_u32(pkt, src, len) \
+ WPACKET_sub_memcpy__((pkt), (src), (len), 4)
+
+/*
+ * Return the total number of bytes written so far to the underlying buffer
+ * including any storage allocated for length bytes
+ */
+int WPACKET_get_total_written(WPACKET *pkt, size_t *written);
+
+/*
+ * Returns the length of the current sub-packet. This excludes any bytes
+ * allocated for the length itself.
+ */
+int WPACKET_get_length(WPACKET *pkt, size_t *len);
+
+/*
+ * Returns a pointer to the current write location, but does not allocate any
+ * bytes.
+ */
+unsigned char *WPACKET_get_curr(WPACKET *pkt);
+
+/* Returns true if the underlying buffer is actually NULL */
+int WPACKET_is_null_buf(WPACKET *pkt);
+
+/* Release resources in a WPACKET if a failure has occurred. */
+void WPACKET_cleanup(WPACKET *pkt);
+
+#endif /* OSSL_INTERNAL_PACKET_H */
diff --git a/include/internal/param_build_set.h b/include/internal/param_build_set.h
new file mode 100644
index 000000000000..126211b7f298
--- /dev/null
+++ b/include/internal/param_build_set.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_PARAM_BUILD_SET_H
+# define OSSL_INTERNAL_PARAM_BUILD_SET_H
+# pragma once
+
+# include <openssl/safestack.h>
+# include <openssl/param_build.h>
+# include "internal/cryptlib.h"
+
+typedef union {
+ OSSL_UNION_ALIGN;
+} OSSL_PARAM_ALIGNED_BLOCK;
+
+# define OSSL_PARAM_ALIGN_SIZE sizeof(OSSL_PARAM_ALIGNED_BLOCK)
+
+size_t ossl_param_bytes_to_blocks(size_t bytes);
+void ossl_param_set_secure_block(OSSL_PARAM *last, void *secure_buffer,
+ size_t secure_buffer_sz);
+
+int ossl_param_build_set_int(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+ const char *key, int num);
+int ossl_param_build_set_long(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+ const char *key, long num);
+int ossl_param_build_set_utf8_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+ const char *key, const char *buf);
+int ossl_param_build_set_octet_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+ const char *key,
+ const unsigned char *data,
+ size_t data_len);
+int ossl_param_build_set_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+ const char *key, const BIGNUM *bn);
+int ossl_param_build_set_bn_pad(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+ const char *key, const BIGNUM *bn, size_t sz);
+int ossl_param_build_set_multi_key_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+ const char *names[],
+ STACK_OF(BIGNUM_const) *stk);
+
+#endif /* OSSL_INTERNAL_PARAM_BUILD_SET_H */
diff --git a/include/internal/passphrase.h b/include/internal/passphrase.h
new file mode 100644
index 000000000000..54d997b0d90b
--- /dev/null
+++ b/include/internal/passphrase.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_PASSPHRASE_H
+# define OSSL_INTERNAL_PASSPHRASE_H
+# pragma once
+
+/*
+ * This is a passphrase reader bridge with bells and whistles.
+ *
+ * On one hand, an API may wish to offer all sorts of passphrase callback
+ * possibilities to users, or may have to do so for historical reasons.
+ * On the other hand, that same API may have demands from other interfaces,
+ * notably from the libcrypto <-> provider interface, which uses
+ * OSSL_PASSPHRASE_CALLBACK consistently.
+ *
+ * The structure and functions below are the fundaments for bridging one
+ * passphrase callback form to another.
+ *
+ * In addition, extra features are included (this may be a growing list):
+ *
+ * - password caching. This is to be used by APIs where it's likely
+ * that the same passphrase may be asked for more than once, but the
+ * user shouldn't get prompted more than once. For example, this is
+ * useful for OSSL_DECODER, which may have to use a passphrase while
+ * trying to find out what input it has.
+ */
+
+/*
+ * Structure to hold whatever the calling user may specify. This structure
+ * is intended to be integrated into API specific structures or to be used
+ * as a local on-stack variable type. Therefore, no functions to allocate
+ * or freed it on the heap is offered.
+ */
+struct ossl_passphrase_data_st {
+ enum {
+ is_expl_passphrase = 1, /* Explicit passphrase given by user */
+ is_pem_password, /* pem_password_cb given by user */
+ is_ossl_passphrase, /* OSSL_PASSPHRASE_CALLBACK given by user */
+ is_ui_method /* UI_METHOD given by user */
+ } type;
+ union {
+ struct {
+ char *passphrase_copy;
+ size_t passphrase_len;
+ } expl_passphrase;
+
+ struct {
+ pem_password_cb *password_cb;
+ void *password_cbarg;
+ } pem_password;
+
+ struct {
+ OSSL_PASSPHRASE_CALLBACK *passphrase_cb;
+ void *passphrase_cbarg;
+ } ossl_passphrase;
+
+ struct {
+ const UI_METHOD *ui_method;
+ void *ui_method_data;
+ } ui_method;
+ } _;
+
+ /*-
+ * Flags section
+ */
+
+ /* Set to indicate that caching should be done */
+ unsigned int flag_cache_passphrase:1;
+
+ /*-
+ * Misc section: caches and other
+ */
+
+ char *cached_passphrase;
+ size_t cached_passphrase_len;
+};
+
+/* Structure manipulation */
+
+void ossl_pw_clear_passphrase_data(struct ossl_passphrase_data_st *data);
+void ossl_pw_clear_passphrase_cache(struct ossl_passphrase_data_st *data);
+
+int ossl_pw_set_passphrase(struct ossl_passphrase_data_st *data,
+ const unsigned char *passphrase,
+ size_t passphrase_len);
+int ossl_pw_set_pem_password_cb(struct ossl_passphrase_data_st *data,
+ pem_password_cb *cb, void *cbarg);
+int ossl_pw_set_ossl_passphrase_cb(struct ossl_passphrase_data_st *data,
+ OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg);
+int ossl_pw_set_ui_method(struct ossl_passphrase_data_st *data,
+ const UI_METHOD *ui_method, void *ui_data);
+
+int ossl_pw_enable_passphrase_caching(struct ossl_passphrase_data_st *data);
+int ossl_pw_disable_passphrase_caching(struct ossl_passphrase_data_st *data);
+
+/* Central function for direct calls */
+
+int ossl_pw_get_passphrase(char *pass, size_t pass_size, size_t *pass_len,
+ const OSSL_PARAM params[], int verify,
+ struct ossl_passphrase_data_st *data);
+
+/* Callback functions */
+
+/*
+ * All of these callback expect that the callback argument is a
+ * struct ossl_passphrase_data_st
+ */
+
+pem_password_cb ossl_pw_pem_password;
+pem_password_cb ossl_pw_pvk_password;
+/* One callback for encoding (verification prompt) and one for decoding */
+OSSL_PASSPHRASE_CALLBACK ossl_pw_passphrase_callback_enc;
+OSSL_PASSPHRASE_CALLBACK ossl_pw_passphrase_callback_dec;
+
+#endif
diff --git a/include/internal/property.h b/include/internal/property.h
new file mode 100644
index 000000000000..d09274d0c92c
--- /dev/null
+++ b/include/internal/property.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_PROPERTY_H
+# define OSSL_INTERNAL_PROPERTY_H
+# pragma once
+
+# include "internal/cryptlib.h"
+
+typedef struct ossl_method_store_st OSSL_METHOD_STORE;
+typedef struct ossl_property_list_st OSSL_PROPERTY_LIST;
+
+typedef enum {
+ OSSL_PROPERTY_TYPE_STRING, OSSL_PROPERTY_TYPE_NUMBER,
+ OSSL_PROPERTY_TYPE_VALUE_UNDEFINED
+} OSSL_PROPERTY_TYPE;
+typedef struct ossl_property_definition_st OSSL_PROPERTY_DEFINITION;
+
+/* Initialisation */
+int ossl_property_parse_init(OSSL_LIB_CTX *ctx);
+
+/* Property definition parser */
+OSSL_PROPERTY_LIST *ossl_parse_property(OSSL_LIB_CTX *ctx, const char *defn);
+/* Property query parser */
+OSSL_PROPERTY_LIST *ossl_parse_query(OSSL_LIB_CTX *ctx, const char *s,
+ int create_values);
+/* Property checker of query vs definition */
+int ossl_property_match_count(const OSSL_PROPERTY_LIST *query,
+ const OSSL_PROPERTY_LIST *defn);
+int ossl_property_is_enabled(OSSL_LIB_CTX *ctx, const char *property_name,
+ const OSSL_PROPERTY_LIST *prop_list);
+/* Free a parsed property list */
+void ossl_property_free(OSSL_PROPERTY_LIST *p);
+
+/* Get a property from a property list */
+const OSSL_PROPERTY_DEFINITION *
+ossl_property_find_property(const OSSL_PROPERTY_LIST *list,
+ OSSL_LIB_CTX *libctx, const char *name);
+OSSL_PROPERTY_TYPE ossl_property_get_type(const OSSL_PROPERTY_DEFINITION *prop);
+const char *ossl_property_get_string_value(OSSL_LIB_CTX *libctx,
+ const OSSL_PROPERTY_DEFINITION *prop);
+int64_t ossl_property_get_number_value(const OSSL_PROPERTY_DEFINITION *prop);
+
+
+/* Implementation store functions */
+OSSL_METHOD_STORE *ossl_method_store_new(OSSL_LIB_CTX *ctx);
+void ossl_method_store_free(OSSL_METHOD_STORE *store);
+
+int ossl_method_lock_store(OSSL_METHOD_STORE *store);
+int ossl_method_unlock_store(OSSL_METHOD_STORE *store);
+
+int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov,
+ int nid, const char *properties, void *method,
+ int (*method_up_ref)(void *),
+ void (*method_destruct)(void *));
+int ossl_method_store_remove(OSSL_METHOD_STORE *store, int nid,
+ const void *method);
+void ossl_method_store_do_all(OSSL_METHOD_STORE *store,
+ void (*fn)(int id, void *method, void *fnarg),
+ void *fnarg);
+int ossl_method_store_fetch(OSSL_METHOD_STORE *store,
+ int nid, const char *prop_query,
+ const OSSL_PROVIDER **prov, void **method);
+int ossl_method_store_remove_all_provided(OSSL_METHOD_STORE *store,
+ const OSSL_PROVIDER *prov);
+
+/* Get the global properties associate with the specified library context */
+OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *ctx,
+ int loadconfig);
+
+/* property query cache functions */
+int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
+ int nid, const char *prop_query, void **result);
+int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
+ int nid, const char *prop_query, void *result,
+ int (*method_up_ref)(void *),
+ void (*method_destruct)(void *));
+
+__owur int ossl_method_store_cache_flush_all(OSSL_METHOD_STORE *store);
+
+/* Merge two property queries together */
+OSSL_PROPERTY_LIST *ossl_property_merge(const OSSL_PROPERTY_LIST *a,
+ const OSSL_PROPERTY_LIST *b);
+
+size_t ossl_property_list_to_string(OSSL_LIB_CTX *ctx,
+ const OSSL_PROPERTY_LIST *list, char *buf,
+ size_t bufsize);
+
+int ossl_global_properties_no_mirrored(OSSL_LIB_CTX *libctx);
+void ossl_global_properties_stop_mirroring(OSSL_LIB_CTX *libctx);
+
+#endif
diff --git a/include/internal/propertyerr.h b/include/internal/propertyerr.h
new file mode 100644
index 000000000000..fbee53f11e84
--- /dev/null
+++ b/include/internal/propertyerr.h
@@ -0,0 +1,43 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_PROPERTYERR_H
+# define OSSL_INTERNAL_PROPERTYERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_PROP_strings(void);
+
+/*
+ * PROP reason codes.
+ */
+# define PROP_R_NAME_TOO_LONG 100
+# define PROP_R_NOT_AN_ASCII_CHARACTER 101
+# define PROP_R_NOT_AN_HEXADECIMAL_DIGIT 102
+# define PROP_R_NOT_AN_IDENTIFIER 103
+# define PROP_R_NOT_AN_OCTAL_DIGIT 104
+# define PROP_R_NOT_A_DECIMAL_DIGIT 105
+# define PROP_R_NO_MATCHING_STRING_DELIMITER 106
+# define PROP_R_NO_VALUE 107
+# define PROP_R_PARSE_FAILED 108
+# define PROP_R_STRING_TOO_LONG 109
+# define PROP_R_TRAILING_CHARACTERS 110
+
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/internal/provider.h b/include/internal/provider.h
new file mode 100644
index 000000000000..a0d9b8f8682d
--- /dev/null
+++ b/include/internal/provider.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_PROVIDER_H
+# define OSSL_INTERNAL_PROVIDER_H
+# pragma once
+
+# include <openssl/core.h>
+# include <openssl/core_dispatch.h>
+# include "internal/dso.h"
+# include "internal/symhacks.h"
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/*
+ * namespaces:
+ *
+ * ossl_provider_ Provider Object internal API
+ * OSSL_PROVIDER Provider Object
+ */
+
+/* Provider Object finder, constructor and destructor */
+OSSL_PROVIDER *ossl_provider_find(OSSL_LIB_CTX *libctx, const char *name,
+ int noconfig);
+OSSL_PROVIDER *ossl_provider_new(OSSL_LIB_CTX *libctx, const char *name,
+ OSSL_provider_init_fn *init_function,
+ int noconfig);
+int ossl_provider_up_ref(OSSL_PROVIDER *prov);
+void ossl_provider_free(OSSL_PROVIDER *prov);
+
+/* Setters */
+int ossl_provider_set_fallback(OSSL_PROVIDER *prov);
+int ossl_provider_set_module_path(OSSL_PROVIDER *prov, const char *module_path);
+int ossl_provider_add_parameter(OSSL_PROVIDER *prov, const char *name,
+ const char *value);
+
+int ossl_provider_is_child(const OSSL_PROVIDER *prov);
+int ossl_provider_set_child(OSSL_PROVIDER *prov, const OSSL_CORE_HANDLE *handle);
+const OSSL_CORE_HANDLE *ossl_provider_get_parent(OSSL_PROVIDER *prov);
+int ossl_provider_up_ref_parent(OSSL_PROVIDER *prov, int activate);
+int ossl_provider_free_parent(OSSL_PROVIDER *prov, int deactivate);
+int ossl_provider_default_props_update(OSSL_LIB_CTX *libctx, const char *props);
+
+/* Disable fallback loading */
+int ossl_provider_disable_fallback_loading(OSSL_LIB_CTX *libctx);
+
+/*
+ * Activate the Provider
+ * If the Provider is a module, the module will be loaded
+ */
+int ossl_provider_activate(OSSL_PROVIDER *prov, int upcalls, int aschild);
+int ossl_provider_deactivate(OSSL_PROVIDER *prov, int removechildren);
+int ossl_provider_add_to_store(OSSL_PROVIDER *prov, OSSL_PROVIDER **actualprov,
+ int retain_fallbacks);
+
+/* Return pointer to the provider's context */
+void *ossl_provider_ctx(const OSSL_PROVIDER *prov);
+
+/* Iterate over all loaded providers */
+int ossl_provider_doall_activated(OSSL_LIB_CTX *,
+ int (*cb)(OSSL_PROVIDER *provider,
+ void *cbdata),
+ void *cbdata);
+
+/* Getters for other library functions */
+const char *ossl_provider_name(const OSSL_PROVIDER *prov);
+const DSO *ossl_provider_dso(const OSSL_PROVIDER *prov);
+const char *ossl_provider_module_name(const OSSL_PROVIDER *prov);
+const char *ossl_provider_module_path(const OSSL_PROVIDER *prov);
+void *ossl_provider_prov_ctx(const OSSL_PROVIDER *prov);
+const OSSL_DISPATCH *ossl_provider_get0_dispatch(const OSSL_PROVIDER *prov);
+OSSL_LIB_CTX *ossl_provider_libctx(const OSSL_PROVIDER *prov);
+
+/* Thin wrappers around calls to the provider */
+void ossl_provider_teardown(const OSSL_PROVIDER *prov);
+const OSSL_PARAM *ossl_provider_gettable_params(const OSSL_PROVIDER *prov);
+int ossl_provider_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[]);
+int ossl_provider_get_capabilities(const OSSL_PROVIDER *prov,
+ const char *capability,
+ OSSL_CALLBACK *cb,
+ void *arg);
+int ossl_provider_self_test(const OSSL_PROVIDER *prov);
+const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov,
+ int operation_id,
+ int *no_cache);
+void ossl_provider_unquery_operation(const OSSL_PROVIDER *prov,
+ int operation_id,
+ const OSSL_ALGORITHM *algs);
+
+/*
+ * Cache of bits to see if we already added methods for an operation in
+ * the "permanent" method store.
+ * They should never be called for temporary method stores!
+ */
+int ossl_provider_set_operation_bit(OSSL_PROVIDER *provider, size_t bitnum);
+int ossl_provider_test_operation_bit(OSSL_PROVIDER *provider, size_t bitnum,
+ int *result);
+
+/* Configuration */
+void ossl_provider_add_conf_module(void);
+
+/* Child providers */
+int ossl_provider_init_as_child(OSSL_LIB_CTX *ctx,
+ const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in);
+void ossl_provider_deinit_child(OSSL_LIB_CTX *ctx);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/include/internal/refcount.h b/include/internal/refcount.h
index 8fb536eadc07..7412d62f56fd 100644
--- a/include/internal/refcount.h
+++ b/include/internal/refcount.h
@@ -1,35 +1,34 @@
/*
- * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_REFCOUNT_H
# define OSSL_INTERNAL_REFCOUNT_H
+# pragma once
-/* Used to checking reference counts, most while doing perl5 stuff :-) */
-# if defined(OPENSSL_NO_STDIO)
-# if defined(REF_PRINT)
-# error "REF_PRINT requires stdio"
-# endif
-# endif
+# include <openssl/e_os2.h>
+# include <openssl/trace.h>
-# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
- && !defined(__STDC_NO_ATOMICS__)
-# include <stdatomic.h>
-# define HAVE_C11_ATOMICS
-# endif
+# ifndef OPENSSL_DEV_NO_ATOMICS
+# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
+ && !defined(__STDC_NO_ATOMICS__)
+# include <stdatomic.h>
+# define HAVE_C11_ATOMICS
+# endif
-# if defined(HAVE_C11_ATOMICS) && defined(ATOMIC_INT_LOCK_FREE) \
- && ATOMIC_INT_LOCK_FREE > 0
+# if defined(HAVE_C11_ATOMICS) && defined(ATOMIC_INT_LOCK_FREE) \
+ && ATOMIC_INT_LOCK_FREE > 0
-# define HAVE_ATOMICS 1
+# define HAVE_ATOMICS 1
typedef _Atomic int CRYPTO_REF_COUNT;
-static inline int CRYPTO_UP_REF(_Atomic int *val, int *ret, void *lock)
+static inline int CRYPTO_UP_REF(_Atomic int *val, int *ret,
+ ossl_unused void *lock)
{
*ret = atomic_fetch_add_explicit(val, 1, memory_order_relaxed) + 1;
return 1;
@@ -45,7 +44,8 @@ static inline int CRYPTO_UP_REF(_Atomic int *val, int *ret, void *lock)
* to mutable members doesn't have to be serialized anymore, which would
* otherwise imply an acquire fence. Hence conditional acquire fence...
*/
-static inline int CRYPTO_DOWN_REF(_Atomic int *val, int *ret, void *lock)
+static inline int CRYPTO_DOWN_REF(_Atomic int *val, int *ret,
+ ossl_unused void *lock)
{
*ret = atomic_fetch_sub_explicit(val, 1, memory_order_relaxed) - 1;
if (*ret == 0)
@@ -53,78 +53,108 @@ static inline int CRYPTO_DOWN_REF(_Atomic int *val, int *ret, void *lock)
return 1;
}
-# elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) && __GCC_ATOMIC_INT_LOCK_FREE > 0
+# elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) && __GCC_ATOMIC_INT_LOCK_FREE > 0
-# define HAVE_ATOMICS 1
+# define HAVE_ATOMICS 1
typedef int CRYPTO_REF_COUNT;
-static __inline__ int CRYPTO_UP_REF(int *val, int *ret, void *lock)
+static __inline__ int CRYPTO_UP_REF(int *val, int *ret, ossl_unused void *lock)
{
*ret = __atomic_fetch_add(val, 1, __ATOMIC_RELAXED) + 1;
return 1;
}
-static __inline__ int CRYPTO_DOWN_REF(int *val, int *ret, void *lock)
+static __inline__ int CRYPTO_DOWN_REF(int *val, int *ret,
+ ossl_unused void *lock)
{
*ret = __atomic_fetch_sub(val, 1, __ATOMIC_RELAXED) - 1;
if (*ret == 0)
__atomic_thread_fence(__ATOMIC_ACQUIRE);
return 1;
}
+# elif defined(__ICL) && defined(_WIN32)
+# define HAVE_ATOMICS 1
+typedef volatile int CRYPTO_REF_COUNT;
+
+static __inline int CRYPTO_UP_REF(volatile int *val, int *ret,
+ ossl_unused void *lock)
+{
+ *ret = _InterlockedExchangeAdd((void *)val, 1) + 1;
+ return 1;
+}
-# elif defined(_MSC_VER) && _MSC_VER>=1200
+static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret,
+ ossl_unused void *lock)
+{
+ *ret = _InterlockedExchangeAdd((void *)val, -1) - 1;
+ return 1;
+}
-# define HAVE_ATOMICS 1
+# elif defined(_MSC_VER) && _MSC_VER>=1200
+
+# define HAVE_ATOMICS 1
typedef volatile int CRYPTO_REF_COUNT;
-# if (defined(_M_ARM) && _M_ARM>=7 && !defined(_WIN32_WCE)) || defined(_M_ARM64)
-# include <intrin.h>
-# if defined(_M_ARM64) && !defined(_ARM_BARRIER_ISH)
-# define _ARM_BARRIER_ISH _ARM64_BARRIER_ISH
-# endif
+# if (defined(_M_ARM) && _M_ARM>=7 && !defined(_WIN32_WCE)) || defined(_M_ARM64)
+# include <intrin.h>
+# if defined(_M_ARM64) && !defined(_ARM_BARRIER_ISH)
+# define _ARM_BARRIER_ISH _ARM64_BARRIER_ISH
+# endif
-static __inline int CRYPTO_UP_REF(volatile int *val, int *ret, void *lock)
+static __inline int CRYPTO_UP_REF(volatile int *val, int *ret,
+ ossl_unused void *lock)
{
*ret = _InterlockedExchangeAdd_nf(val, 1) + 1;
return 1;
}
-static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret, void *lock)
+static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret,
+ ossl_unused void *lock)
{
*ret = _InterlockedExchangeAdd_nf(val, -1) - 1;
if (*ret == 0)
__dmb(_ARM_BARRIER_ISH);
return 1;
}
-# else
-# if !defined(_WIN32_WCE)
-# pragma intrinsic(_InterlockedExchangeAdd)
# else
-# if _WIN32_WCE >= 0x600
- extern long __cdecl _InterlockedExchangeAdd(long volatile*, long);
+# if !defined(_WIN32_WCE)
+# pragma intrinsic(_InterlockedExchangeAdd)
# else
- /* under Windows CE we still have old-style Interlocked* functions */
- extern long __cdecl InterlockedExchangeAdd(long volatile*, long);
-# define _InterlockedExchangeAdd InterlockedExchangeAdd
+# if _WIN32_WCE >= 0x600
+ extern long __cdecl _InterlockedExchangeAdd(long volatile*, long);
+# else
+ /* under Windows CE we still have old-style Interlocked* functions */
+ extern long __cdecl InterlockedExchangeAdd(long volatile*, long);
+# define _InterlockedExchangeAdd InterlockedExchangeAdd
+# endif
# endif
-# endif
-static __inline int CRYPTO_UP_REF(volatile int *val, int *ret, void *lock)
+static __inline int CRYPTO_UP_REF(volatile int *val, int *ret,
+ ossl_unused void *lock)
{
*ret = _InterlockedExchangeAdd(val, 1) + 1;
return 1;
}
-static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret, void *lock)
+static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret,
+ ossl_unused void *lock)
{
*ret = _InterlockedExchangeAdd(val, -1) - 1;
return 1;
}
+# endif
+
# endif
+# endif /* !OPENSSL_DEV_NO_ATOMICS */
-# else
+/*
+ * All the refcounting implementations above define HAVE_ATOMICS, so if it's
+ * still undefined here (such as when OPENSSL_DEV_NO_ATOMICS is defined), it
+ * means we need to implement a fallback. This fallback uses locks.
+ */
+# ifndef HAVE_ATOMICS
typedef int CRYPTO_REF_COUNT;
@@ -140,11 +170,9 @@ typedef int CRYPTO_REF_COUNT;
# define REF_ASSERT_ISNT(i)
# endif
-# ifdef REF_PRINT
-# define REF_PRINT_COUNT(a, b) \
- fprintf(stderr, "%p:%4d:%s\n", b, b->references, a)
-# else
-# define REF_PRINT_COUNT(a, b)
-# endif
+# define REF_PRINT_EX(text, count, object) \
+ OSSL_TRACE3(REF_COUNT, "%p:%4d:%s\n", (object), (count), (text));
+# define REF_PRINT_COUNT(text, object) \
+ REF_PRINT_EX(text, object->references, (void *)object)
#endif
diff --git a/include/internal/sha3.h b/include/internal/sha3.h
new file mode 100644
index 000000000000..80ad86e58e3e
--- /dev/null
+++ b/include/internal/sha3.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* This header can move into provider when legacy support is removed */
+#ifndef OSSL_INTERNAL_SHA3_H
+# define OSSL_INTERNAL_SHA3_H
+# pragma once
+
+# include <openssl/e_os2.h>
+# include <stddef.h>
+
+# define KECCAK1600_WIDTH 1600
+# define SHA3_MDSIZE(bitlen) (bitlen / 8)
+# define KMAC_MDSIZE(bitlen) 2 * (bitlen / 8)
+# define SHA3_BLOCKSIZE(bitlen) (KECCAK1600_WIDTH - bitlen * 2) / 8
+
+typedef struct keccak_st KECCAK1600_CTX;
+
+typedef size_t (sha3_absorb_fn)(void *vctx, const void *inp, size_t len);
+typedef int (sha3_final_fn)(unsigned char *md, void *vctx);
+
+typedef struct prov_sha3_meth_st
+{
+ sha3_absorb_fn *absorb;
+ sha3_final_fn *final;
+} PROV_SHA3_METHOD;
+
+struct keccak_st {
+ uint64_t A[5][5];
+ size_t block_size; /* cached ctx->digest->block_size */
+ size_t md_size; /* output length, variable in XOF */
+ size_t bufsz; /* used bytes in below buffer */
+ unsigned char buf[KECCAK1600_WIDTH / 8 - 32];
+ unsigned char pad;
+ PROV_SHA3_METHOD meth;
+};
+
+void ossl_sha3_reset(KECCAK1600_CTX *ctx);
+int ossl_sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen);
+int ossl_keccak_kmac_init(KECCAK1600_CTX *ctx, unsigned char pad,
+ size_t bitlen);
+int ossl_sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len);
+int ossl_sha3_final(unsigned char *md, KECCAK1600_CTX *ctx);
+
+size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len,
+ size_t r);
+
+#endif /* OSSL_INTERNAL_SHA3_H */
diff --git a/include/internal/sizes.h b/include/internal/sizes.h
new file mode 100644
index 000000000000..f6496c818265
--- /dev/null
+++ b/include/internal/sizes.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_SIZES_H
+# define OSSL_INTERNAL_SIZES_H
+# pragma once
+
+/*
+ * Max sizes used to allocate buffers with a fixed sizes, for example for
+ * stack allocations, structure fields, ...
+ */
+# define OSSL_MAX_NAME_SIZE 50 /* Algorithm name */
+# define OSSL_MAX_PROPQUERY_SIZE 256 /* Property query strings */
+# define OSSL_MAX_ALGORITHM_ID_SIZE 256 /* AlgorithmIdentifier DER */
+
+#endif
diff --git a/include/internal/sm3.h b/include/internal/sm3.h
new file mode 100644
index 000000000000..db1d61f0523c
--- /dev/null
+++ b/include/internal/sm3.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017 Ribose Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* This header can move into provider when legacy support is removed */
+#ifndef OSSL_INTERNAL_SM3_H
+# define OSSL_INTERNAL_SM3_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+
+# ifdef OPENSSL_NO_SM3
+# error SM3 is disabled.
+# endif
+
+# define SM3_DIGEST_LENGTH 32
+# define SM3_WORD unsigned int
+
+# define SM3_CBLOCK 64
+# define SM3_LBLOCK (SM3_CBLOCK/4)
+
+typedef struct SM3state_st {
+ SM3_WORD A, B, C, D, E, F, G, H;
+ SM3_WORD Nl, Nh;
+ SM3_WORD data[SM3_LBLOCK];
+ unsigned int num;
+} SM3_CTX;
+
+int ossl_sm3_init(SM3_CTX *c);
+int ossl_sm3_update(SM3_CTX *c, const void *data, size_t len);
+int ossl_sm3_final(unsigned char *md, SM3_CTX *c);
+
+#endif /* OSSL_INTERNAL_SM3_H */
diff --git a/include/internal/sockets.h b/include/internal/sockets.h
index 4fc1aecdbb20..1876af8fafec 100644
--- a/include/internal/sockets.h
+++ b/include/internal/sockets.h
@@ -1,15 +1,17 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-
#ifndef OSSL_INTERNAL_SOCKETS_H
# define OSSL_INTERNAL_SOCKETS_H
+# pragma once
+
+# include <openssl/opensslconf.h>
# if defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)
# define NO_SYS_PARAM_H
@@ -26,6 +28,8 @@
# elif defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
# if defined(__DJGPP__)
+# define WATT32
+# define WATT32_NO_OLDIES
# include <sys/socket.h>
# include <sys/un.h>
# include <tcp.h>
@@ -132,8 +136,6 @@ struct servent *PASCAL getservbyname(const char *, const char *);
# define readsocket(s,b,n) recv((s),(b),(n),0)
# define writesocket(s,b,n) send((s),(b),(n),0)
# elif defined(__DJGPP__)
-# define WATT32
-# define WATT32_NO_OLDIES
# define closesocket(s) close_s(s)
# define readsocket(s,b,n) read_s(s,b,n)
# define writesocket(s,b,n) send(s,b,n,0)
@@ -147,6 +149,17 @@ struct servent *PASCAL getservbyname(const char *, const char *);
# define closesocket(s) close(s)
# define readsocket(s,b,n) read((s),(b),(n))
# define writesocket(s,b,n) write((s),(char *)(b),(n))
+# elif defined(OPENSSL_SYS_TANDEM)
+# if defined(OPENSSL_TANDEM_FLOSS)
+# include <floss.h(floss_read, floss_write)>
+# define readsocket(s,b,n) floss_read((s),(b),(n))
+# define writesocket(s,b,n) floss_write((s),(b),(n))
+# else
+# define readsocket(s,b,n) read((s),(b),(n))
+# define writesocket(s,b,n) write((s),(b),(n))
+# endif
+# define ioctlsocket(a,b,c) ioctl(a,b,c)
+# define closesocket(s) close(s)
# else
# define ioctlsocket(a,b,c) ioctl(a,b,c)
# define closesocket(s) close(s)
@@ -154,4 +167,11 @@ struct servent *PASCAL getservbyname(const char *, const char *);
# define writesocket(s,b,n) write((s),(b),(n))
# endif
+/* also in apps/include/apps.h */
+# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WINCE)
+# define openssl_fdset(a, b) FD_SET((unsigned int)(a), b)
+# else
+# define openssl_fdset(a, b) FD_SET(a, b)
+# endif
+
#endif
diff --git a/include/internal/sslconf.h b/include/internal/sslconf.h
index 92c8941d0250..fd7f7e333183 100644
--- a/include/internal/sslconf.h
+++ b/include/internal/sslconf.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,6 +9,7 @@
#ifndef OSSL_INTERNAL_SSLCONF_H
# define OSSL_INTERNAL_SSLCONF_H
+# pragma once
typedef struct ssl_conf_cmd_st SSL_CONF_CMD;
diff --git a/include/internal/symhacks.h b/include/internal/symhacks.h
new file mode 100644
index 000000000000..33bae51e49cc
--- /dev/null
+++ b/include/internal/symhacks.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_SYMHACKS_H
+# define OSSL_INTERNAL_SYMHACKS_H
+# pragma once
+
+# include <openssl/e_os2.h>
+
+# if defined(OPENSSL_SYS_VMS)
+
+/* ossl_provider_gettable_params vs OSSL_PROVIDER_gettable_params */
+# undef ossl_provider_gettable_params
+# define ossl_provider_gettable_params ossl_int_prov_gettable_params
+/* ossl_provider_get_params vs OSSL_PROVIDER_get_params */
+# undef ossl_provider_get_params
+# define ossl_provider_get_params ossl_int_prov_get_params
+
+# endif
+
+#endif /* ! defined HEADER_VMS_IDHACKS_H */
diff --git a/include/internal/thread_once.h b/include/internal/thread_once.h
index 8f8aa6e1c4b1..d6cb2eeec3bc 100644
--- a/include/internal/thread_once.h
+++ b/include/internal/thread_once.h
@@ -1,17 +1,28 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#include <openssl/crypto.h>
+#ifndef OSSL_INTERNAL_THREAD_ONCE_H
+# define OSSL_INTERNAL_THREAD_ONCE_H
+# pragma once
+# include <openssl/crypto.h>
+
+/*
+ * Initialisation of global data should never happen via "RUN_ONCE" inside the
+ * FIPS module. Global data should instead always be associated with a specific
+ * OSSL_LIB_CTX object. In this way data will get cleaned up correctly when the
+ * module gets unloaded.
+ */
+# if !defined(FIPS_MODULE) || defined(ALLOW_RUN_ONCE_IN_FIPS)
/*
* DEFINE_RUN_ONCE: Define an initialiser function that should be run exactly
- * once. It takes no arguments and returns and int result (1 for success or
+ * once. It takes no arguments and returns an int result (1 for success or
* 0 for failure). Typical usage might be:
*
* DEFINE_RUN_ONCE(myinitfunc)
@@ -23,7 +34,7 @@
* return 0;
* }
*/
-#define DEFINE_RUN_ONCE(init) \
+# define DEFINE_RUN_ONCE(init) \
static int init(void); \
int init##_ossl_ret_ = 0; \
void init##_ossl_(void) \
@@ -36,14 +47,14 @@
* DECLARE_RUN_ONCE: Declare an initialiser function that should be run exactly
* once that has been defined in another file via DEFINE_RUN_ONCE().
*/
-#define DECLARE_RUN_ONCE(init) \
+# define DECLARE_RUN_ONCE(init) \
extern int init##_ossl_ret_; \
void init##_ossl_(void);
/*
* DEFINE_RUN_ONCE_STATIC: Define an initialiser function that should be run
* exactly once. This function will be declared as static within the file. It
- * takes no arguments and returns and int result (1 for success or 0 for
+ * takes no arguments and returns an int result (1 for success or 0 for
* failure). Typical usage might be:
*
* DEFINE_RUN_ONCE_STATIC(myinitfunc)
@@ -55,7 +66,7 @@
* return 0;
* }
*/
-#define DEFINE_RUN_ONCE_STATIC(init) \
+# define DEFINE_RUN_ONCE_STATIC(init) \
static int init(void); \
static int init##_ossl_ret_ = 0; \
static void init##_ossl_(void) \
@@ -96,7 +107,7 @@
* return 0;
* }
*/
-#define DEFINE_RUN_ONCE_STATIC_ALT(initalt, init) \
+# define DEFINE_RUN_ONCE_STATIC_ALT(initalt, init) \
static int initalt(void); \
static void initalt##_ossl_(void) \
{ \
@@ -115,7 +126,7 @@
*
* (*) by convention, since the init function must return 1 on success.
*/
-#define RUN_ONCE(once, init) \
+# define RUN_ONCE(once, init) \
(CRYPTO_THREAD_run_once(once, init##_ossl_) ? init##_ossl_ret_ : 0)
/*
@@ -133,5 +144,8 @@
*
* (*) by convention, since the init function must return 1 on success.
*/
-#define RUN_ONCE_ALT(once, initalt, init) \
+# define RUN_ONCE_ALT(once, initalt, init) \
(CRYPTO_THREAD_run_once(once, initalt##_ossl_) ? init##_ossl_ret_ : 0)
+
+# endif /* FIPS_MODULE */
+#endif /* OSSL_INTERNAL_THREAD_ONCE_H */
diff --git a/include/internal/tlsgroups.h b/include/internal/tlsgroups.h
new file mode 100644
index 000000000000..8a35ced12270
--- /dev/null
+++ b/include/internal/tlsgroups.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_TLSGROUPS_H
+# define OSSL_INTERNAL_TLSGROUPS_H
+# pragma once
+
+# define OSSL_TLS_GROUP_ID_sect163k1 0x0001
+# define OSSL_TLS_GROUP_ID_sect163r1 0x0002
+# define OSSL_TLS_GROUP_ID_sect163r2 0x0003
+# define OSSL_TLS_GROUP_ID_sect193r1 0x0004
+# define OSSL_TLS_GROUP_ID_sect193r2 0x0005
+# define OSSL_TLS_GROUP_ID_sect233k1 0x0006
+# define OSSL_TLS_GROUP_ID_sect233r1 0x0007
+# define OSSL_TLS_GROUP_ID_sect239k1 0x0008
+# define OSSL_TLS_GROUP_ID_sect283k1 0x0009
+# define OSSL_TLS_GROUP_ID_sect283r1 0x000A
+# define OSSL_TLS_GROUP_ID_sect409k1 0x000B
+# define OSSL_TLS_GROUP_ID_sect409r1 0x000C
+# define OSSL_TLS_GROUP_ID_sect571k1 0x000D
+# define OSSL_TLS_GROUP_ID_sect571r1 0x000E
+# define OSSL_TLS_GROUP_ID_secp160k1 0x000F
+# define OSSL_TLS_GROUP_ID_secp160r1 0x0010
+# define OSSL_TLS_GROUP_ID_secp160r2 0x0011
+# define OSSL_TLS_GROUP_ID_secp192k1 0x0012
+# define OSSL_TLS_GROUP_ID_secp192r1 0x0013
+# define OSSL_TLS_GROUP_ID_secp224k1 0x0014
+# define OSSL_TLS_GROUP_ID_secp224r1 0x0015
+# define OSSL_TLS_GROUP_ID_secp256k1 0x0016
+# define OSSL_TLS_GROUP_ID_secp256r1 0x0017
+# define OSSL_TLS_GROUP_ID_secp384r1 0x0018
+# define OSSL_TLS_GROUP_ID_secp521r1 0x0019
+# define OSSL_TLS_GROUP_ID_brainpoolP256r1 0x001A
+# define OSSL_TLS_GROUP_ID_brainpoolP384r1 0x001B
+# define OSSL_TLS_GROUP_ID_brainpoolP512r1 0x001C
+# define OSSL_TLS_GROUP_ID_x25519 0x001D
+# define OSSL_TLS_GROUP_ID_x448 0x001E
+# define OSSL_TLS_GROUP_ID_ffdhe2048 0x0100
+# define OSSL_TLS_GROUP_ID_ffdhe3072 0x0101
+# define OSSL_TLS_GROUP_ID_ffdhe4096 0x0102
+# define OSSL_TLS_GROUP_ID_ffdhe6144 0x0103
+# define OSSL_TLS_GROUP_ID_ffdhe8192 0x0104
+
+#endif
diff --git a/include/internal/tsan_assist.h b/include/internal/tsan_assist.h
index cc30162eb74e..60ecbd5f04f3 100644
--- a/include/internal/tsan_assist.h
+++ b/include/internal/tsan_assist.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -130,7 +130,13 @@
#ifndef TSAN_QUALIFIER
-# define TSAN_QUALIFIER volatile
+# ifdef OPENSSL_THREADS
+# define TSAN_QUALIFIER volatile
+# define TSAN_REQUIRES_LOCKING
+# else /* OPENSSL_THREADS */
+# define TSAN_QUALIFIER
+# endif /* OPENSSL_THREADS */
+
# define tsan_load(ptr) (*(ptr))
# define tsan_store(ptr, val) (*(ptr) = (val))
# define tsan_counter(ptr) ((*(ptr))++)
diff --git a/include/internal/unicode.h b/include/internal/unicode.h
new file mode 100644
index 000000000000..a6de8352d680
--- /dev/null
+++ b/include/internal/unicode.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_UNICODE_H
+# define OSSL_INTERNAL_UNICODE_H
+# pragma once
+
+typedef enum {
+ SURROGATE_MIN = 0xd800UL,
+ SURROGATE_MAX = 0xdfffUL,
+ UNICODE_MAX = 0x10ffffUL,
+ UNICODE_LIMIT
+} UNICODE_CONSTANTS;
+
+static ossl_unused ossl_inline int is_unicode_surrogate(unsigned long value)
+{
+ return value >= SURROGATE_MIN && value <= SURROGATE_MAX;
+}
+
+static ossl_unused ossl_inline int is_unicode_valid(unsigned long value)
+{
+ return value <= UNICODE_MAX && !is_unicode_surrogate(value);
+}
+
+#endif
diff --git a/include/openssl/__DECC_INCLUDE_EPILOGUE.H b/include/openssl/__DECC_INCLUDE_EPILOGUE.H
index ad0a5f56dc9d..d251d0a03cfd 100644
--- a/include/openssl/__DECC_INCLUDE_EPILOGUE.H
+++ b/include/openssl/__DECC_INCLUDE_EPILOGUE.H
@@ -1,7 +1,7 @@
/*
* Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/include/openssl/__DECC_INCLUDE_PROLOGUE.H b/include/openssl/__DECC_INCLUDE_PROLOGUE.H
index 5f5513e821ac..91ac6b33caf4 100644
--- a/include/openssl/__DECC_INCLUDE_PROLOGUE.H
+++ b/include/openssl/__DECC_INCLUDE_PROLOGUE.H
@@ -1,7 +1,7 @@
/*
* Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/include/openssl/aes.h b/include/openssl/aes.h
index 245c552abd05..d0f9dfc6f1cd 100644
--- a/include/openssl/aes.h
+++ b/include/openssl/aes.h
@@ -1,14 +1,20 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_AES_H
-# define HEADER_AES_H
+#ifndef OPENSSL_AES_H
+# define OPENSSL_AES_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_AES_H
+# endif
# include <openssl/opensslconf.h>
@@ -17,72 +23,85 @@
extern "C" {
# endif
-# define AES_ENCRYPT 1
-# define AES_DECRYPT 0
-
-/*
- * Because array size can't be a const in C, the following two are macros.
- * Both sizes are in bytes.
- */
-# define AES_MAXNR 14
# define AES_BLOCK_SIZE 16
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+
+# define AES_ENCRYPT 1
+# define AES_DECRYPT 0
+
+# define AES_MAXNR 14
+
+
/* This should be a hidden type, but EVP requires that the size be known */
struct aes_key_st {
-# ifdef AES_LONG
+# ifdef AES_LONG
unsigned long rd_key[4 * (AES_MAXNR + 1)];
-# else
+# else
unsigned int rd_key[4 * (AES_MAXNR + 1)];
-# endif
+# endif
int rounds;
};
typedef struct aes_key_st AES_KEY;
-const char *AES_options(void);
-
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 const char *AES_options(void);
+OSSL_DEPRECATEDIN_3_0
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
+OSSL_DEPRECATEDIN_3_0
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
-
+OSSL_DEPRECATEDIN_3_0
void AES_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
+OSSL_DEPRECATEDIN_3_0
void AES_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
-
+OSSL_DEPRECATEDIN_3_0
void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key, const int enc);
+OSSL_DEPRECATEDIN_3_0
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc);
+OSSL_DEPRECATEDIN_3_0
void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
+OSSL_DEPRECATEDIN_3_0
void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
+OSSL_DEPRECATEDIN_3_0
void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
+OSSL_DEPRECATEDIN_3_0
void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num);
+
/* NB: the IV is _two_ blocks long */
+OSSL_DEPRECATEDIN_3_0
void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc);
/* NB: the IV is _four_ blocks long */
+OSSL_DEPRECATEDIN_3_0
void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
- size_t length, const AES_KEY *key,
- const AES_KEY *key2, const unsigned char *ivec,
- const int enc);
-
+ size_t length, const AES_KEY *key, const AES_KEY *key2,
+ const unsigned char *ivec, const int enc);
+OSSL_DEPRECATEDIN_3_0
int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
- unsigned char *out,
- const unsigned char *in, unsigned int inlen);
+ unsigned char *out, const unsigned char *in,
+ unsigned int inlen);
+OSSL_DEPRECATEDIN_3_0
int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
- unsigned char *out,
- const unsigned char *in, unsigned int inlen);
+ unsigned char *out, const unsigned char *in,
+ unsigned int inlen);
+# endif
# ifdef __cplusplus
diff --git a/include/openssl/asn1.h b/include/openssl/asn1.h
deleted file mode 100644
index 9522eec18f7a..000000000000
--- a/include/openssl/asn1.h
+++ /dev/null
@@ -1,886 +0,0 @@
-/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_ASN1_H
-# define HEADER_ASN1_H
-
-# include <time.h>
-# include <openssl/e_os2.h>
-# include <openssl/opensslconf.h>
-# include <openssl/bio.h>
-# include <openssl/safestack.h>
-# include <openssl/asn1err.h>
-# include <openssl/symhacks.h>
-
-# include <openssl/ossl_typ.h>
-# if OPENSSL_API_COMPAT < 0x10100000L
-# include <openssl/bn.h>
-# endif
-
-# ifdef OPENSSL_BUILD_SHLIBCRYPTO
-# undef OPENSSL_EXTERN
-# define OPENSSL_EXTERN OPENSSL_EXPORT
-# endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-# define V_ASN1_UNIVERSAL 0x00
-# define V_ASN1_APPLICATION 0x40
-# define V_ASN1_CONTEXT_SPECIFIC 0x80
-# define V_ASN1_PRIVATE 0xc0
-
-# define V_ASN1_CONSTRUCTED 0x20
-# define V_ASN1_PRIMITIVE_TAG 0x1f
-# define V_ASN1_PRIMATIVE_TAG /*compat*/ V_ASN1_PRIMITIVE_TAG
-
-# define V_ASN1_APP_CHOOSE -2/* let the recipient choose */
-# define V_ASN1_OTHER -3/* used in ASN1_TYPE */
-# define V_ASN1_ANY -4/* used in ASN1 template code */
-
-# define V_ASN1_UNDEF -1
-/* ASN.1 tag values */
-# define V_ASN1_EOC 0
-# define V_ASN1_BOOLEAN 1 /**/
-# define V_ASN1_INTEGER 2
-# define V_ASN1_BIT_STRING 3
-# define V_ASN1_OCTET_STRING 4
-# define V_ASN1_NULL 5
-# define V_ASN1_OBJECT 6
-# define V_ASN1_OBJECT_DESCRIPTOR 7
-# define V_ASN1_EXTERNAL 8
-# define V_ASN1_REAL 9
-# define V_ASN1_ENUMERATED 10
-# define V_ASN1_UTF8STRING 12
-# define V_ASN1_SEQUENCE 16
-# define V_ASN1_SET 17
-# define V_ASN1_NUMERICSTRING 18 /**/
-# define V_ASN1_PRINTABLESTRING 19
-# define V_ASN1_T61STRING 20
-# define V_ASN1_TELETEXSTRING 20/* alias */
-# define V_ASN1_VIDEOTEXSTRING 21 /**/
-# define V_ASN1_IA5STRING 22
-# define V_ASN1_UTCTIME 23
-# define V_ASN1_GENERALIZEDTIME 24 /**/
-# define V_ASN1_GRAPHICSTRING 25 /**/
-# define V_ASN1_ISO64STRING 26 /**/
-# define V_ASN1_VISIBLESTRING 26/* alias */
-# define V_ASN1_GENERALSTRING 27 /**/
-# define V_ASN1_UNIVERSALSTRING 28 /**/
-# define V_ASN1_BMPSTRING 30
-
-/*
- * NB the constants below are used internally by ASN1_INTEGER
- * and ASN1_ENUMERATED to indicate the sign. They are *not* on
- * the wire tag values.
- */
-
-# define V_ASN1_NEG 0x100
-# define V_ASN1_NEG_INTEGER (2 | V_ASN1_NEG)
-# define V_ASN1_NEG_ENUMERATED (10 | V_ASN1_NEG)
-
-/* For use with d2i_ASN1_type_bytes() */
-# define B_ASN1_NUMERICSTRING 0x0001
-# define B_ASN1_PRINTABLESTRING 0x0002
-# define B_ASN1_T61STRING 0x0004
-# define B_ASN1_TELETEXSTRING 0x0004
-# define B_ASN1_VIDEOTEXSTRING 0x0008
-# define B_ASN1_IA5STRING 0x0010
-# define B_ASN1_GRAPHICSTRING 0x0020
-# define B_ASN1_ISO64STRING 0x0040
-# define B_ASN1_VISIBLESTRING 0x0040
-# define B_ASN1_GENERALSTRING 0x0080
-# define B_ASN1_UNIVERSALSTRING 0x0100
-# define B_ASN1_OCTET_STRING 0x0200
-# define B_ASN1_BIT_STRING 0x0400
-# define B_ASN1_BMPSTRING 0x0800
-# define B_ASN1_UNKNOWN 0x1000
-# define B_ASN1_UTF8STRING 0x2000
-# define B_ASN1_UTCTIME 0x4000
-# define B_ASN1_GENERALIZEDTIME 0x8000
-# define B_ASN1_SEQUENCE 0x10000
-/* For use with ASN1_mbstring_copy() */
-# define MBSTRING_FLAG 0x1000
-# define MBSTRING_UTF8 (MBSTRING_FLAG)
-# define MBSTRING_ASC (MBSTRING_FLAG|1)
-# define MBSTRING_BMP (MBSTRING_FLAG|2)
-# define MBSTRING_UNIV (MBSTRING_FLAG|4)
-# define SMIME_OLDMIME 0x400
-# define SMIME_CRLFEOL 0x800
-# define SMIME_STREAM 0x1000
- struct X509_algor_st;
-DEFINE_STACK_OF(X509_ALGOR)
-
-# define ASN1_STRING_FLAG_BITS_LEFT 0x08/* Set if 0x07 has bits left value */
-/*
- * This indicates that the ASN1_STRING is not a real value but just a place
- * holder for the location where indefinite length constructed data should be
- * inserted in the memory buffer
- */
-# define ASN1_STRING_FLAG_NDEF 0x010
-
-/*
- * This flag is used by the CMS code to indicate that a string is not
- * complete and is a place holder for content when it had all been accessed.
- * The flag will be reset when content has been written to it.
- */
-
-# define ASN1_STRING_FLAG_CONT 0x020
-/*
- * This flag is used by ASN1 code to indicate an ASN1_STRING is an MSTRING
- * type.
- */
-# define ASN1_STRING_FLAG_MSTRING 0x040
-/* String is embedded and only content should be freed */
-# define ASN1_STRING_FLAG_EMBED 0x080
-/* String should be parsed in RFC 5280's time format */
-# define ASN1_STRING_FLAG_X509_TIME 0x100
-/* This is the base type that holds just about everything :-) */
-struct asn1_string_st {
- int length;
- int type;
- unsigned char *data;
- /*
- * The value of the following field depends on the type being held. It
- * is mostly being used for BIT_STRING so if the input data has a
- * non-zero 'unused bits' value, it will be handled correctly
- */
- long flags;
-};
-
-/*
- * ASN1_ENCODING structure: this is used to save the received encoding of an
- * ASN1 type. This is useful to get round problems with invalid encodings
- * which can break signatures.
- */
-
-typedef struct ASN1_ENCODING_st {
- unsigned char *enc; /* DER encoding */
- long len; /* Length of encoding */
- int modified; /* set to 1 if 'enc' is invalid */
-} ASN1_ENCODING;
-
-/* Used with ASN1 LONG type: if a long is set to this it is omitted */
-# define ASN1_LONG_UNDEF 0x7fffffffL
-
-# define STABLE_FLAGS_MALLOC 0x01
-/*
- * A zero passed to ASN1_STRING_TABLE_new_add for the flags is interpreted
- * as "don't change" and STABLE_FLAGS_MALLOC is always set. By setting
- * STABLE_FLAGS_MALLOC only we can clear the existing value. Use the alias
- * STABLE_FLAGS_CLEAR to reflect this.
- */
-# define STABLE_FLAGS_CLEAR STABLE_FLAGS_MALLOC
-# define STABLE_NO_MASK 0x02
-# define DIRSTRING_TYPE \
- (B_ASN1_PRINTABLESTRING|B_ASN1_T61STRING|B_ASN1_BMPSTRING|B_ASN1_UTF8STRING)
-# define PKCS9STRING_TYPE (DIRSTRING_TYPE|B_ASN1_IA5STRING)
-
-typedef struct asn1_string_table_st {
- int nid;
- long minsize;
- long maxsize;
- unsigned long mask;
- unsigned long flags;
-} ASN1_STRING_TABLE;
-
-DEFINE_STACK_OF(ASN1_STRING_TABLE)
-
-/* size limits: this stuff is taken straight from RFC2459 */
-
-# define ub_name 32768
-# define ub_common_name 64
-# define ub_locality_name 128
-# define ub_state_name 128
-# define ub_organization_name 64
-# define ub_organization_unit_name 64
-# define ub_title 64
-# define ub_email_address 128
-
-/*
- * Declarations for template structures: for full definitions see asn1t.h
- */
-typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE;
-typedef struct ASN1_TLC_st ASN1_TLC;
-/* This is just an opaque pointer */
-typedef struct ASN1_VALUE_st ASN1_VALUE;
-
-/* Declare ASN1 functions: the implement macro in in asn1t.h */
-
-# define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type)
-
-# define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \
- DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, type)
-
-# define DECLARE_ASN1_FUNCTIONS_name(type, name) \
- DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
- DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name)
-
-# define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \
- DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
- DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name)
-
-# define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \
- type *d2i_##name(type **a, const unsigned char **in, long len); \
- int i2d_##name(type *a, unsigned char **out); \
- DECLARE_ASN1_ITEM(itname)
-
-# define DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \
- type *d2i_##name(type **a, const unsigned char **in, long len); \
- int i2d_##name(const type *a, unsigned char **out); \
- DECLARE_ASN1_ITEM(name)
-
-# define DECLARE_ASN1_NDEF_FUNCTION(name) \
- int i2d_##name##_NDEF(name *a, unsigned char **out);
-
-# define DECLARE_ASN1_FUNCTIONS_const(name) \
- DECLARE_ASN1_ALLOC_FUNCTIONS(name) \
- DECLARE_ASN1_ENCODE_FUNCTIONS_const(name, name)
-
-# define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
- type *name##_new(void); \
- void name##_free(type *a);
-
-# define DECLARE_ASN1_PRINT_FUNCTION(stname) \
- DECLARE_ASN1_PRINT_FUNCTION_fname(stname, stname)
-
-# define DECLARE_ASN1_PRINT_FUNCTION_fname(stname, fname) \
- int fname##_print_ctx(BIO *out, stname *x, int indent, \
- const ASN1_PCTX *pctx);
-
-# define D2I_OF(type) type *(*)(type **,const unsigned char **,long)
-# define I2D_OF(type) int (*)(type *,unsigned char **)
-# define I2D_OF_const(type) int (*)(const type *,unsigned char **)
-
-# define CHECKED_D2I_OF(type, d2i) \
- ((d2i_of_void*) (1 ? d2i : ((D2I_OF(type))0)))
-# define CHECKED_I2D_OF(type, i2d) \
- ((i2d_of_void*) (1 ? i2d : ((I2D_OF(type))0)))
-# define CHECKED_NEW_OF(type, xnew) \
- ((void *(*)(void)) (1 ? xnew : ((type *(*)(void))0)))
-# define CHECKED_PTR_OF(type, p) \
- ((void*) (1 ? p : (type*)0))
-# define CHECKED_PPTR_OF(type, p) \
- ((void**) (1 ? p : (type**)0))
-
-# define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **,const unsigned char **,long)
-# define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(type *,unsigned char **)
-# define TYPEDEF_D2I2D_OF(type) TYPEDEF_D2I_OF(type); TYPEDEF_I2D_OF(type)
-
-TYPEDEF_D2I2D_OF(void);
-
-/*-
- * The following macros and typedefs allow an ASN1_ITEM
- * to be embedded in a structure and referenced. Since
- * the ASN1_ITEM pointers need to be globally accessible
- * (possibly from shared libraries) they may exist in
- * different forms. On platforms that support it the
- * ASN1_ITEM structure itself will be globally exported.
- * Other platforms will export a function that returns
- * an ASN1_ITEM pointer.
- *
- * To handle both cases transparently the macros below
- * should be used instead of hard coding an ASN1_ITEM
- * pointer in a structure.
- *
- * The structure will look like this:
- *
- * typedef struct SOMETHING_st {
- * ...
- * ASN1_ITEM_EXP *iptr;
- * ...
- * } SOMETHING;
- *
- * It would be initialised as e.g.:
- *
- * SOMETHING somevar = {...,ASN1_ITEM_ref(X509),...};
- *
- * and the actual pointer extracted with:
- *
- * const ASN1_ITEM *it = ASN1_ITEM_ptr(somevar.iptr);
- *
- * Finally an ASN1_ITEM pointer can be extracted from an
- * appropriate reference with: ASN1_ITEM_rptr(X509). This
- * would be used when a function takes an ASN1_ITEM * argument.
- *
- */
-
-# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
-
-/* ASN1_ITEM pointer exported type */
-typedef const ASN1_ITEM ASN1_ITEM_EXP;
-
-/* Macro to obtain ASN1_ITEM pointer from exported type */
-# define ASN1_ITEM_ptr(iptr) (iptr)
-
-/* Macro to include ASN1_ITEM pointer from base type */
-# define ASN1_ITEM_ref(iptr) (&(iptr##_it))
-
-# define ASN1_ITEM_rptr(ref) (&(ref##_it))
-
-# define DECLARE_ASN1_ITEM(name) \
- OPENSSL_EXTERN const ASN1_ITEM name##_it;
-
-# else
-
-/*
- * Platforms that can't easily handle shared global variables are declared as
- * functions returning ASN1_ITEM pointers.
- */
-
-/* ASN1_ITEM pointer exported type */
-typedef const ASN1_ITEM *ASN1_ITEM_EXP (void);
-
-/* Macro to obtain ASN1_ITEM pointer from exported type */
-# define ASN1_ITEM_ptr(iptr) (iptr())
-
-/* Macro to include ASN1_ITEM pointer from base type */
-# define ASN1_ITEM_ref(iptr) (iptr##_it)
-
-# define ASN1_ITEM_rptr(ref) (ref##_it())
-
-# define DECLARE_ASN1_ITEM(name) \
- const ASN1_ITEM * name##_it(void);
-
-# endif
-
-/* Parameters used by ASN1_STRING_print_ex() */
-
-/*
- * These determine which characters to escape: RFC2253 special characters,
- * control characters and MSB set characters
- */
-
-# define ASN1_STRFLGS_ESC_2253 1
-# define ASN1_STRFLGS_ESC_CTRL 2
-# define ASN1_STRFLGS_ESC_MSB 4
-
-/*
- * This flag determines how we do escaping: normally RC2253 backslash only,
- * set this to use backslash and quote.
- */
-
-# define ASN1_STRFLGS_ESC_QUOTE 8
-
-/* These three flags are internal use only. */
-
-/* Character is a valid PrintableString character */
-# define CHARTYPE_PRINTABLESTRING 0x10
-/* Character needs escaping if it is the first character */
-# define CHARTYPE_FIRST_ESC_2253 0x20
-/* Character needs escaping if it is the last character */
-# define CHARTYPE_LAST_ESC_2253 0x40
-
-/*
- * NB the internal flags are safely reused below by flags handled at the top
- * level.
- */
-
-/*
- * If this is set we convert all character strings to UTF8 first
- */
-
-# define ASN1_STRFLGS_UTF8_CONVERT 0x10
-
-/*
- * If this is set we don't attempt to interpret content: just assume all
- * strings are 1 byte per character. This will produce some pretty odd
- * looking output!
- */
-
-# define ASN1_STRFLGS_IGNORE_TYPE 0x20
-
-/* If this is set we include the string type in the output */
-# define ASN1_STRFLGS_SHOW_TYPE 0x40
-
-/*
- * This determines which strings to display and which to 'dump' (hex dump of
- * content octets or DER encoding). We can only dump non character strings or
- * everything. If we don't dump 'unknown' they are interpreted as character
- * strings with 1 octet per character and are subject to the usual escaping
- * options.
- */
-
-# define ASN1_STRFLGS_DUMP_ALL 0x80
-# define ASN1_STRFLGS_DUMP_UNKNOWN 0x100
-
-/*
- * These determine what 'dumping' does, we can dump the content octets or the
- * DER encoding: both use the RFC2253 #XXXXX notation.
- */
-
-# define ASN1_STRFLGS_DUMP_DER 0x200
-
-/*
- * This flag specifies that RC2254 escaping shall be performed.
- */
-#define ASN1_STRFLGS_ESC_2254 0x400
-
-/*
- * All the string flags consistent with RFC2253, escaping control characters
- * isn't essential in RFC2253 but it is advisable anyway.
- */
-
-# define ASN1_STRFLGS_RFC2253 (ASN1_STRFLGS_ESC_2253 | \
- ASN1_STRFLGS_ESC_CTRL | \
- ASN1_STRFLGS_ESC_MSB | \
- ASN1_STRFLGS_UTF8_CONVERT | \
- ASN1_STRFLGS_DUMP_UNKNOWN | \
- ASN1_STRFLGS_DUMP_DER)
-
-DEFINE_STACK_OF(ASN1_INTEGER)
-
-DEFINE_STACK_OF(ASN1_GENERALSTRING)
-
-DEFINE_STACK_OF(ASN1_UTF8STRING)
-
-typedef struct asn1_type_st {
- int type;
- union {
- char *ptr;
- ASN1_BOOLEAN boolean;
- ASN1_STRING *asn1_string;
- ASN1_OBJECT *object;
- ASN1_INTEGER *integer;
- ASN1_ENUMERATED *enumerated;
- ASN1_BIT_STRING *bit_string;
- ASN1_OCTET_STRING *octet_string;
- ASN1_PRINTABLESTRING *printablestring;
- ASN1_T61STRING *t61string;
- ASN1_IA5STRING *ia5string;
- ASN1_GENERALSTRING *generalstring;
- ASN1_BMPSTRING *bmpstring;
- ASN1_UNIVERSALSTRING *universalstring;
- ASN1_UTCTIME *utctime;
- ASN1_GENERALIZEDTIME *generalizedtime;
- ASN1_VISIBLESTRING *visiblestring;
- ASN1_UTF8STRING *utf8string;
- /*
- * set and sequence are left complete and still contain the set or
- * sequence bytes
- */
- ASN1_STRING *set;
- ASN1_STRING *sequence;
- ASN1_VALUE *asn1_value;
- } value;
-} ASN1_TYPE;
-
-DEFINE_STACK_OF(ASN1_TYPE)
-
-typedef STACK_OF(ASN1_TYPE) ASN1_SEQUENCE_ANY;
-
-DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY)
-DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SET_ANY)
-
-/* This is used to contain a list of bit names */
-typedef struct BIT_STRING_BITNAME_st {
- int bitnum;
- const char *lname;
- const char *sname;
-} BIT_STRING_BITNAME;
-
-# define B_ASN1_TIME \
- B_ASN1_UTCTIME | \
- B_ASN1_GENERALIZEDTIME
-
-# define B_ASN1_PRINTABLE \
- B_ASN1_NUMERICSTRING| \
- B_ASN1_PRINTABLESTRING| \
- B_ASN1_T61STRING| \
- B_ASN1_IA5STRING| \
- B_ASN1_BIT_STRING| \
- B_ASN1_UNIVERSALSTRING|\
- B_ASN1_BMPSTRING|\
- B_ASN1_UTF8STRING|\
- B_ASN1_SEQUENCE|\
- B_ASN1_UNKNOWN
-
-# define B_ASN1_DIRECTORYSTRING \
- B_ASN1_PRINTABLESTRING| \
- B_ASN1_TELETEXSTRING|\
- B_ASN1_BMPSTRING|\
- B_ASN1_UNIVERSALSTRING|\
- B_ASN1_UTF8STRING
-
-# define B_ASN1_DISPLAYTEXT \
- B_ASN1_IA5STRING| \
- B_ASN1_VISIBLESTRING| \
- B_ASN1_BMPSTRING|\
- B_ASN1_UTF8STRING
-
-DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
-
-int ASN1_TYPE_get(const ASN1_TYPE *a);
-void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value);
-int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value);
-int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b);
-
-ASN1_TYPE *ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t);
-void *ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t);
-
-ASN1_OBJECT *ASN1_OBJECT_new(void);
-void ASN1_OBJECT_free(ASN1_OBJECT *a);
-int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp);
-ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
- long length);
-
-DECLARE_ASN1_ITEM(ASN1_OBJECT)
-
-DEFINE_STACK_OF(ASN1_OBJECT)
-
-ASN1_STRING *ASN1_STRING_new(void);
-void ASN1_STRING_free(ASN1_STRING *a);
-void ASN1_STRING_clear_free(ASN1_STRING *a);
-int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str);
-ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *a);
-ASN1_STRING *ASN1_STRING_type_new(int type);
-int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b);
- /*
- * Since this is used to store all sorts of things, via macros, for now,
- * make its data void *
- */
-int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len);
-void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len);
-int ASN1_STRING_length(const ASN1_STRING *x);
-void ASN1_STRING_length_set(ASN1_STRING *x, int n);
-int ASN1_STRING_type(const ASN1_STRING *x);
-DEPRECATEDIN_1_1_0(unsigned char *ASN1_STRING_data(ASN1_STRING *x))
-const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x);
-
-DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING)
-int ASN1_BIT_STRING_set(ASN1_BIT_STRING *a, unsigned char *d, int length);
-int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value);
-int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n);
-int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a,
- const unsigned char *flags, int flags_len);
-
-int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
- BIT_STRING_BITNAME *tbl, int indent);
-int ASN1_BIT_STRING_num_asc(const char *name, BIT_STRING_BITNAME *tbl);
-int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, const char *name, int value,
- BIT_STRING_BITNAME *tbl);
-
-DECLARE_ASN1_FUNCTIONS(ASN1_INTEGER)
-ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
- long length);
-ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x);
-int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y);
-
-DECLARE_ASN1_FUNCTIONS(ASN1_ENUMERATED)
-
-int ASN1_UTCTIME_check(const ASN1_UTCTIME *a);
-ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t);
-ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
- int offset_day, long offset_sec);
-int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str);
-int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t);
-
-int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *a);
-ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
- time_t t);
-ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
- time_t t, int offset_day,
- long offset_sec);
-int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str);
-
-int ASN1_TIME_diff(int *pday, int *psec,
- const ASN1_TIME *from, const ASN1_TIME *to);
-
-DECLARE_ASN1_FUNCTIONS(ASN1_OCTET_STRING)
-ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *a);
-int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a,
- const ASN1_OCTET_STRING *b);
-int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *str, const unsigned char *data,
- int len);
-
-DECLARE_ASN1_FUNCTIONS(ASN1_VISIBLESTRING)
-DECLARE_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING)
-DECLARE_ASN1_FUNCTIONS(ASN1_UTF8STRING)
-DECLARE_ASN1_FUNCTIONS(ASN1_NULL)
-DECLARE_ASN1_FUNCTIONS(ASN1_BMPSTRING)
-
-int UTF8_getc(const unsigned char *str, int len, unsigned long *val);
-int UTF8_putc(unsigned char *str, int len, unsigned long value);
-
-DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE)
-
-DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING)
-DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT)
-DECLARE_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING)
-DECLARE_ASN1_FUNCTIONS(ASN1_T61STRING)
-DECLARE_ASN1_FUNCTIONS(ASN1_IA5STRING)
-DECLARE_ASN1_FUNCTIONS(ASN1_GENERALSTRING)
-DECLARE_ASN1_FUNCTIONS(ASN1_UTCTIME)
-DECLARE_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME)
-DECLARE_ASN1_FUNCTIONS(ASN1_TIME)
-
-DECLARE_ASN1_ITEM(ASN1_OCTET_STRING_NDEF)
-
-ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t);
-ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
- int offset_day, long offset_sec);
-int ASN1_TIME_check(const ASN1_TIME *t);
-ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
- ASN1_GENERALIZEDTIME **out);
-int ASN1_TIME_set_string(ASN1_TIME *s, const char *str);
-int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str);
-int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm);
-int ASN1_TIME_normalize(ASN1_TIME *s);
-int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t);
-int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b);
-
-int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a);
-int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size);
-int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a);
-int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size);
-int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a);
-int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size);
-int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type);
-int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a);
-
-int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num);
-ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
- const char *sn, const char *ln);
-
-int ASN1_INTEGER_get_int64(int64_t *pr, const ASN1_INTEGER *a);
-int ASN1_INTEGER_set_int64(ASN1_INTEGER *a, int64_t r);
-int ASN1_INTEGER_get_uint64(uint64_t *pr, const ASN1_INTEGER *a);
-int ASN1_INTEGER_set_uint64(ASN1_INTEGER *a, uint64_t r);
-
-int ASN1_INTEGER_set(ASN1_INTEGER *a, long v);
-long ASN1_INTEGER_get(const ASN1_INTEGER *a);
-ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai);
-BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn);
-
-int ASN1_ENUMERATED_get_int64(int64_t *pr, const ASN1_ENUMERATED *a);
-int ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *a, int64_t r);
-
-
-int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v);
-long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a);
-ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai);
-BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn);
-
-/* General */
-/* given a string, return the correct type, max is the maximum length */
-int ASN1_PRINTABLE_type(const unsigned char *s, int max);
-
-unsigned long ASN1_tag2bit(int tag);
-
-/* SPECIALS */
-int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
- int *pclass, long omax);
-int ASN1_check_infinite_end(unsigned char **p, long len);
-int ASN1_const_check_infinite_end(const unsigned char **p, long len);
-void ASN1_put_object(unsigned char **pp, int constructed, int length,
- int tag, int xclass);
-int ASN1_put_eoc(unsigned char **pp);
-int ASN1_object_size(int constructed, int length, int tag);
-
-/* Used to implement other functions */
-void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x);
-
-# define ASN1_dup_of(type,i2d,d2i,x) \
- ((type*)ASN1_dup(CHECKED_I2D_OF(type, i2d), \
- CHECKED_D2I_OF(type, d2i), \
- CHECKED_PTR_OF(type, x)))
-
-# define ASN1_dup_of_const(type,i2d,d2i,x) \
- ((type*)ASN1_dup(CHECKED_I2D_OF(const type, i2d), \
- CHECKED_D2I_OF(type, d2i), \
- CHECKED_PTR_OF(const type, x)))
-
-void *ASN1_item_dup(const ASN1_ITEM *it, void *x);
-
-/* ASN1 alloc/free macros for when a type is only used internally */
-
-# define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type))
-# define M_ASN1_free_of(x, type) \
- ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type))
-
-# ifndef OPENSSL_NO_STDIO
-void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x);
-
-# define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \
- ((type*)ASN1_d2i_fp(CHECKED_NEW_OF(type, xnew), \
- CHECKED_D2I_OF(type, d2i), \
- in, \
- CHECKED_PPTR_OF(type, x)))
-
-void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);
-int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x);
-
-# define ASN1_i2d_fp_of(type,i2d,out,x) \
- (ASN1_i2d_fp(CHECKED_I2D_OF(type, i2d), \
- out, \
- CHECKED_PTR_OF(type, x)))
-
-# define ASN1_i2d_fp_of_const(type,i2d,out,x) \
- (ASN1_i2d_fp(CHECKED_I2D_OF(const type, i2d), \
- out, \
- CHECKED_PTR_OF(const type, x)))
-
-int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x);
-int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags);
-# endif
-
-int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in);
-
-void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x);
-
-# define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \
- ((type*)ASN1_d2i_bio( CHECKED_NEW_OF(type, xnew), \
- CHECKED_D2I_OF(type, d2i), \
- in, \
- CHECKED_PPTR_OF(type, x)))
-
-void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x);
-int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x);
-
-# define ASN1_i2d_bio_of(type,i2d,out,x) \
- (ASN1_i2d_bio(CHECKED_I2D_OF(type, i2d), \
- out, \
- CHECKED_PTR_OF(type, x)))
-
-# define ASN1_i2d_bio_of_const(type,i2d,out,x) \
- (ASN1_i2d_bio(CHECKED_I2D_OF(const type, i2d), \
- out, \
- CHECKED_PTR_OF(const type, x)))
-
-int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x);
-int ASN1_UTCTIME_print(BIO *fp, const ASN1_UTCTIME *a);
-int ASN1_GENERALIZEDTIME_print(BIO *fp, const ASN1_GENERALIZEDTIME *a);
-int ASN1_TIME_print(BIO *fp, const ASN1_TIME *a);
-int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v);
-int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags);
-int ASN1_buf_print(BIO *bp, const unsigned char *buf, size_t buflen, int off);
-int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num,
- unsigned char *buf, int off);
-int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent);
-int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent,
- int dump);
-const char *ASN1_tag2str(int tag);
-
-/* Used to load and write Netscape format cert */
-
-int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s);
-
-int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len);
-int ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len);
-int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num,
- unsigned char *data, int len);
-int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num,
- unsigned char *data, int max_len);
-
-void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it);
-
-ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it,
- ASN1_OCTET_STRING **oct);
-
-void ASN1_STRING_set_default_mask(unsigned long mask);
-int ASN1_STRING_set_default_mask_asc(const char *p);
-unsigned long ASN1_STRING_get_default_mask(void);
-int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
- int inform, unsigned long mask);
-int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
- int inform, unsigned long mask,
- long minsize, long maxsize);
-
-ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
- const unsigned char *in, int inlen,
- int inform, int nid);
-ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid);
-int ASN1_STRING_TABLE_add(int, long, long, unsigned long, unsigned long);
-void ASN1_STRING_TABLE_cleanup(void);
-
-/* ASN1 template functions */
-
-/* Old API compatible functions */
-ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it);
-void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it);
-ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in,
- long len, const ASN1_ITEM *it);
-int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
-int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
- const ASN1_ITEM *it);
-
-void ASN1_add_oid_module(void);
-void ASN1_add_stable_module(void);
-
-ASN1_TYPE *ASN1_generate_nconf(const char *str, CONF *nconf);
-ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf);
-int ASN1_str2mask(const char *str, unsigned long *pmask);
-
-/* ASN1 Print flags */
-
-/* Indicate missing OPTIONAL fields */
-# define ASN1_PCTX_FLAGS_SHOW_ABSENT 0x001
-/* Mark start and end of SEQUENCE */
-# define ASN1_PCTX_FLAGS_SHOW_SEQUENCE 0x002
-/* Mark start and end of SEQUENCE/SET OF */
-# define ASN1_PCTX_FLAGS_SHOW_SSOF 0x004
-/* Show the ASN1 type of primitives */
-# define ASN1_PCTX_FLAGS_SHOW_TYPE 0x008
-/* Don't show ASN1 type of ANY */
-# define ASN1_PCTX_FLAGS_NO_ANY_TYPE 0x010
-/* Don't show ASN1 type of MSTRINGs */
-# define ASN1_PCTX_FLAGS_NO_MSTRING_TYPE 0x020
-/* Don't show field names in SEQUENCE */
-# define ASN1_PCTX_FLAGS_NO_FIELD_NAME 0x040
-/* Show structure names of each SEQUENCE field */
-# define ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME 0x080
-/* Don't show structure name even at top level */
-# define ASN1_PCTX_FLAGS_NO_STRUCT_NAME 0x100
-
-int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent,
- const ASN1_ITEM *it, const ASN1_PCTX *pctx);
-ASN1_PCTX *ASN1_PCTX_new(void);
-void ASN1_PCTX_free(ASN1_PCTX *p);
-unsigned long ASN1_PCTX_get_flags(const ASN1_PCTX *p);
-void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags);
-unsigned long ASN1_PCTX_get_nm_flags(const ASN1_PCTX *p);
-void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags);
-unsigned long ASN1_PCTX_get_cert_flags(const ASN1_PCTX *p);
-void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags);
-unsigned long ASN1_PCTX_get_oid_flags(const ASN1_PCTX *p);
-void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags);
-unsigned long ASN1_PCTX_get_str_flags(const ASN1_PCTX *p);
-void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags);
-
-ASN1_SCTX *ASN1_SCTX_new(int (*scan_cb) (ASN1_SCTX *ctx));
-void ASN1_SCTX_free(ASN1_SCTX *p);
-const ASN1_ITEM *ASN1_SCTX_get_item(ASN1_SCTX *p);
-const ASN1_TEMPLATE *ASN1_SCTX_get_template(ASN1_SCTX *p);
-unsigned long ASN1_SCTX_get_flags(ASN1_SCTX *p);
-void ASN1_SCTX_set_app_data(ASN1_SCTX *p, void *data);
-void *ASN1_SCTX_get_app_data(ASN1_SCTX *p);
-
-const BIO_METHOD *BIO_f_asn1(void);
-
-BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it);
-
-int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
- const ASN1_ITEM *it);
-int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
- const char *hdr, const ASN1_ITEM *it);
-int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
- int ctype_nid, int econt_nid,
- STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it);
-ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
-int SMIME_crlf_copy(BIO *in, BIO *out, int flags);
-int SMIME_text(BIO *in, BIO *out);
-
-const ASN1_ITEM *ASN1_ITEM_lookup(const char *name);
-const ASN1_ITEM *ASN1_ITEM_get(size_t i);
-
-# ifdef __cplusplus
-}
-# endif
-#endif
diff --git a/include/openssl/asn1.h.in b/include/openssl/asn1.h.in
new file mode 100644
index 000000000000..6d5094a3ff7d
--- /dev/null
+++ b/include/openssl/asn1.h.in
@@ -0,0 +1,961 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_ASN1_H
+# define OPENSSL_ASN1_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_ASN1_H
+# endif
+
+# include <time.h>
+# include <openssl/e_os2.h>
+# include <openssl/opensslconf.h>
+# include <openssl/bio.h>
+# include <openssl/safestack.h>
+# include <openssl/asn1err.h>
+# include <openssl/symhacks.h>
+
+# include <openssl/types.h>
+# include <openssl/bn.h>
+
+# ifdef OPENSSL_BUILD_SHLIBCRYPTO
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+# endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+# define V_ASN1_UNIVERSAL 0x00
+# define V_ASN1_APPLICATION 0x40
+# define V_ASN1_CONTEXT_SPECIFIC 0x80
+# define V_ASN1_PRIVATE 0xc0
+
+# define V_ASN1_CONSTRUCTED 0x20
+# define V_ASN1_PRIMITIVE_TAG 0x1f
+# define V_ASN1_PRIMATIVE_TAG /*compat*/ V_ASN1_PRIMITIVE_TAG
+
+# define V_ASN1_APP_CHOOSE -2/* let the recipient choose */
+# define V_ASN1_OTHER -3/* used in ASN1_TYPE */
+# define V_ASN1_ANY -4/* used in ASN1 template code */
+
+# define V_ASN1_UNDEF -1
+/* ASN.1 tag values */
+# define V_ASN1_EOC 0
+# define V_ASN1_BOOLEAN 1 /**/
+# define V_ASN1_INTEGER 2
+# define V_ASN1_BIT_STRING 3
+# define V_ASN1_OCTET_STRING 4
+# define V_ASN1_NULL 5
+# define V_ASN1_OBJECT 6
+# define V_ASN1_OBJECT_DESCRIPTOR 7
+# define V_ASN1_EXTERNAL 8
+# define V_ASN1_REAL 9
+# define V_ASN1_ENUMERATED 10
+# define V_ASN1_UTF8STRING 12
+# define V_ASN1_SEQUENCE 16
+# define V_ASN1_SET 17
+# define V_ASN1_NUMERICSTRING 18 /**/
+# define V_ASN1_PRINTABLESTRING 19
+# define V_ASN1_T61STRING 20
+# define V_ASN1_TELETEXSTRING 20/* alias */
+# define V_ASN1_VIDEOTEXSTRING 21 /**/
+# define V_ASN1_IA5STRING 22
+# define V_ASN1_UTCTIME 23
+# define V_ASN1_GENERALIZEDTIME 24 /**/
+# define V_ASN1_GRAPHICSTRING 25 /**/
+# define V_ASN1_ISO64STRING 26 /**/
+# define V_ASN1_VISIBLESTRING 26/* alias */
+# define V_ASN1_GENERALSTRING 27 /**/
+# define V_ASN1_UNIVERSALSTRING 28 /**/
+# define V_ASN1_BMPSTRING 30
+
+/*
+ * NB the constants below are used internally by ASN1_INTEGER
+ * and ASN1_ENUMERATED to indicate the sign. They are *not* on
+ * the wire tag values.
+ */
+
+# define V_ASN1_NEG 0x100
+# define V_ASN1_NEG_INTEGER (2 | V_ASN1_NEG)
+# define V_ASN1_NEG_ENUMERATED (10 | V_ASN1_NEG)
+
+/* For use with d2i_ASN1_type_bytes() */
+# define B_ASN1_NUMERICSTRING 0x0001
+# define B_ASN1_PRINTABLESTRING 0x0002
+# define B_ASN1_T61STRING 0x0004
+# define B_ASN1_TELETEXSTRING 0x0004
+# define B_ASN1_VIDEOTEXSTRING 0x0008
+# define B_ASN1_IA5STRING 0x0010
+# define B_ASN1_GRAPHICSTRING 0x0020
+# define B_ASN1_ISO64STRING 0x0040
+# define B_ASN1_VISIBLESTRING 0x0040
+# define B_ASN1_GENERALSTRING 0x0080
+# define B_ASN1_UNIVERSALSTRING 0x0100
+# define B_ASN1_OCTET_STRING 0x0200
+# define B_ASN1_BIT_STRING 0x0400
+# define B_ASN1_BMPSTRING 0x0800
+# define B_ASN1_UNKNOWN 0x1000
+# define B_ASN1_UTF8STRING 0x2000
+# define B_ASN1_UTCTIME 0x4000
+# define B_ASN1_GENERALIZEDTIME 0x8000
+# define B_ASN1_SEQUENCE 0x10000
+/* For use with ASN1_mbstring_copy() */
+# define MBSTRING_FLAG 0x1000
+# define MBSTRING_UTF8 (MBSTRING_FLAG)
+# define MBSTRING_ASC (MBSTRING_FLAG|1)
+# define MBSTRING_BMP (MBSTRING_FLAG|2)
+# define MBSTRING_UNIV (MBSTRING_FLAG|4)
+# define SMIME_OLDMIME 0x400
+# define SMIME_CRLFEOL 0x800
+# define SMIME_STREAM 0x1000
+
+/* Stacks for types not otherwise defined in this header */
+{-
+ generate_stack_macros("X509_ALGOR");
+-}
+
+
+# define ASN1_STRING_FLAG_BITS_LEFT 0x08/* Set if 0x07 has bits left value */
+/*
+ * This indicates that the ASN1_STRING is not a real value but just a place
+ * holder for the location where indefinite length constructed data should be
+ * inserted in the memory buffer
+ */
+# define ASN1_STRING_FLAG_NDEF 0x010
+
+/*
+ * This flag is used by the CMS code to indicate that a string is not
+ * complete and is a place holder for content when it had all been accessed.
+ * The flag will be reset when content has been written to it.
+ */
+
+# define ASN1_STRING_FLAG_CONT 0x020
+/*
+ * This flag is used by ASN1 code to indicate an ASN1_STRING is an MSTRING
+ * type.
+ */
+# define ASN1_STRING_FLAG_MSTRING 0x040
+/* String is embedded and only content should be freed */
+# define ASN1_STRING_FLAG_EMBED 0x080
+/* String should be parsed in RFC 5280's time format */
+# define ASN1_STRING_FLAG_X509_TIME 0x100
+/* This is the base type that holds just about everything :-) */
+struct asn1_string_st {
+ int length;
+ int type;
+ unsigned char *data;
+ /*
+ * The value of the following field depends on the type being held. It
+ * is mostly being used for BIT_STRING so if the input data has a
+ * non-zero 'unused bits' value, it will be handled correctly
+ */
+ long flags;
+};
+
+/*
+ * ASN1_ENCODING structure: this is used to save the received encoding of an
+ * ASN1 type. This is useful to get round problems with invalid encodings
+ * which can break signatures.
+ */
+
+typedef struct ASN1_ENCODING_st {
+ unsigned char *enc; /* DER encoding */
+ long len; /* Length of encoding */
+ int modified; /* set to 1 if 'enc' is invalid */
+} ASN1_ENCODING;
+
+/* Used with ASN1 LONG type: if a long is set to this it is omitted */
+# define ASN1_LONG_UNDEF 0x7fffffffL
+
+# define STABLE_FLAGS_MALLOC 0x01
+/*
+ * A zero passed to ASN1_STRING_TABLE_new_add for the flags is interpreted
+ * as "don't change" and STABLE_FLAGS_MALLOC is always set. By setting
+ * STABLE_FLAGS_MALLOC only we can clear the existing value. Use the alias
+ * STABLE_FLAGS_CLEAR to reflect this.
+ */
+# define STABLE_FLAGS_CLEAR STABLE_FLAGS_MALLOC
+# define STABLE_NO_MASK 0x02
+# define DIRSTRING_TYPE \
+ (B_ASN1_PRINTABLESTRING|B_ASN1_T61STRING|B_ASN1_BMPSTRING|B_ASN1_UTF8STRING)
+# define PKCS9STRING_TYPE (DIRSTRING_TYPE|B_ASN1_IA5STRING)
+
+struct asn1_string_table_st {
+ int nid;
+ long minsize;
+ long maxsize;
+ unsigned long mask;
+ unsigned long flags;
+};
+
+{-
+ generate_stack_macros("ASN1_STRING_TABLE");
+-}
+
+/* size limits: this stuff is taken straight from RFC2459 */
+
+# define ub_name 32768
+# define ub_common_name 64
+# define ub_locality_name 128
+# define ub_state_name 128
+# define ub_organization_name 64
+# define ub_organization_unit_name 64
+# define ub_title 64
+# define ub_email_address 128
+
+/*
+ * Declarations for template structures: for full definitions see asn1t.h
+ */
+typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE;
+typedef struct ASN1_TLC_st ASN1_TLC;
+/* This is just an opaque pointer */
+typedef struct ASN1_VALUE_st ASN1_VALUE;
+
+/* Declare ASN1 functions: the implement macro in in asn1t.h */
+
+/*
+ * The mysterious 'extern' that's passed to some macros is innocuous,
+ * and is there to quiet pre-C99 compilers that may complain about empty
+ * arguments in macro calls.
+ */
+
+# define DECLARE_ASN1_FUNCTIONS_attr(attr, type) \
+ DECLARE_ASN1_FUNCTIONS_name_attr(attr, type, type)
+# define DECLARE_ASN1_FUNCTIONS(type) \
+ DECLARE_ASN1_FUNCTIONS_attr(extern, type)
+
+# define DECLARE_ASN1_ALLOC_FUNCTIONS_attr(attr, type) \
+ DECLARE_ASN1_ALLOC_FUNCTIONS_name_attr(attr, type, type)
+# define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \
+ DECLARE_ASN1_ALLOC_FUNCTIONS_attr(extern, type)
+
+# define DECLARE_ASN1_FUNCTIONS_name_attr(attr, type, name) \
+ DECLARE_ASN1_ALLOC_FUNCTIONS_name_attr(attr, type, name) \
+ DECLARE_ASN1_ENCODE_FUNCTIONS_name_attr(attr, type, name)
+# define DECLARE_ASN1_FUNCTIONS_name(type, name) \
+ DECLARE_ASN1_FUNCTIONS_name_attr(extern, type, name)
+
+# define DECLARE_ASN1_ENCODE_FUNCTIONS_attr(attr, type, itname, name) \
+ DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(attr, type, name) \
+ DECLARE_ASN1_ITEM_attr(attr, itname)
+# define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \
+ DECLARE_ASN1_ENCODE_FUNCTIONS_attr(extern, type, itname, name)
+
+# define DECLARE_ASN1_ENCODE_FUNCTIONS_name_attr(attr, type, name) \
+ DECLARE_ASN1_ENCODE_FUNCTIONS_attr(attr, type, name, name)
+# define DECLARE_ASN1_ENCODE_FUNCTIONS_name(type, name) \
+ DECLARE_ASN1_ENCODE_FUNCTIONS_name_attr(extern, type, name)
+
+# define DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(attr, type, name) \
+ attr type *d2i_##name(type **a, const unsigned char **in, long len); \
+ attr int i2d_##name(const type *a, unsigned char **out);
+# define DECLARE_ASN1_ENCODE_FUNCTIONS_only(type, name) \
+ DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(extern, type, name)
+
+# define DECLARE_ASN1_NDEF_FUNCTION_attr(attr, name) \
+ attr int i2d_##name##_NDEF(const name *a, unsigned char **out);
+# define DECLARE_ASN1_NDEF_FUNCTION(name) \
+ DECLARE_ASN1_NDEF_FUNCTION_attr(extern, name)
+
+# define DECLARE_ASN1_ALLOC_FUNCTIONS_name_attr(attr, type, name) \
+ attr type *name##_new(void); \
+ attr void name##_free(type *a);
+# define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
+ DECLARE_ASN1_ALLOC_FUNCTIONS_name_attr(extern, type, name)
+
+# define DECLARE_ASN1_DUP_FUNCTION_attr(attr, type) \
+ DECLARE_ASN1_DUP_FUNCTION_name_attr(attr, type, type)
+# define DECLARE_ASN1_DUP_FUNCTION(type) \
+ DECLARE_ASN1_DUP_FUNCTION_attr(extern, type)
+
+# define DECLARE_ASN1_DUP_FUNCTION_name_attr(attr, type, name) \
+ attr type *name##_dup(const type *a);
+# define DECLARE_ASN1_DUP_FUNCTION_name(type, name) \
+ DECLARE_ASN1_DUP_FUNCTION_name_attr(extern, type, name)
+
+# define DECLARE_ASN1_PRINT_FUNCTION_attr(attr, stname) \
+ DECLARE_ASN1_PRINT_FUNCTION_fname_attr(attr, stname, stname)
+# define DECLARE_ASN1_PRINT_FUNCTION(stname) \
+ DECLARE_ASN1_PRINT_FUNCTION_attr(extern, stname)
+
+# define DECLARE_ASN1_PRINT_FUNCTION_fname_attr(attr, stname, fname) \
+ attr int fname##_print_ctx(BIO *out, const stname *x, int indent, \
+ const ASN1_PCTX *pctx);
+# define DECLARE_ASN1_PRINT_FUNCTION_fname(stname, fname) \
+ DECLARE_ASN1_PRINT_FUNCTION_fname_attr(extern, stname, fname)
+
+# define D2I_OF(type) type *(*)(type **,const unsigned char **,long)
+# define I2D_OF(type) int (*)(const type *,unsigned char **)
+
+# define CHECKED_D2I_OF(type, d2i) \
+ ((d2i_of_void*) (1 ? d2i : ((D2I_OF(type))0)))
+# define CHECKED_I2D_OF(type, i2d) \
+ ((i2d_of_void*) (1 ? i2d : ((I2D_OF(type))0)))
+# define CHECKED_NEW_OF(type, xnew) \
+ ((void *(*)(void)) (1 ? xnew : ((type *(*)(void))0)))
+# define CHECKED_PTR_OF(type, p) \
+ ((void*) (1 ? p : (type*)0))
+# define CHECKED_PPTR_OF(type, p) \
+ ((void**) (1 ? p : (type**)0))
+
+# define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **,const unsigned char **,long)
+# define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(const type *,unsigned char **)
+# define TYPEDEF_D2I2D_OF(type) TYPEDEF_D2I_OF(type); TYPEDEF_I2D_OF(type)
+
+typedef void *d2i_of_void(void **, const unsigned char **, long);
+typedef int i2d_of_void(const void *, unsigned char **);
+
+/*-
+ * The following macros and typedefs allow an ASN1_ITEM
+ * to be embedded in a structure and referenced. Since
+ * the ASN1_ITEM pointers need to be globally accessible
+ * (possibly from shared libraries) they may exist in
+ * different forms. On platforms that support it the
+ * ASN1_ITEM structure itself will be globally exported.
+ * Other platforms will export a function that returns
+ * an ASN1_ITEM pointer.
+ *
+ * To handle both cases transparently the macros below
+ * should be used instead of hard coding an ASN1_ITEM
+ * pointer in a structure.
+ *
+ * The structure will look like this:
+ *
+ * typedef struct SOMETHING_st {
+ * ...
+ * ASN1_ITEM_EXP *iptr;
+ * ...
+ * } SOMETHING;
+ *
+ * It would be initialised as e.g.:
+ *
+ * SOMETHING somevar = {...,ASN1_ITEM_ref(X509),...};
+ *
+ * and the actual pointer extracted with:
+ *
+ * const ASN1_ITEM *it = ASN1_ITEM_ptr(somevar.iptr);
+ *
+ * Finally an ASN1_ITEM pointer can be extracted from an
+ * appropriate reference with: ASN1_ITEM_rptr(X509). This
+ * would be used when a function takes an ASN1_ITEM * argument.
+ *
+ */
+
+
+/*
+ * Platforms that can't easily handle shared global variables are declared as
+ * functions returning ASN1_ITEM pointers.
+ */
+
+/* ASN1_ITEM pointer exported type */
+typedef const ASN1_ITEM *ASN1_ITEM_EXP (void);
+
+/* Macro to obtain ASN1_ITEM pointer from exported type */
+# define ASN1_ITEM_ptr(iptr) (iptr())
+
+/* Macro to include ASN1_ITEM pointer from base type */
+# define ASN1_ITEM_ref(iptr) (iptr##_it)
+
+# define ASN1_ITEM_rptr(ref) (ref##_it())
+
+# define DECLARE_ASN1_ITEM_attr(attr, name) \
+ attr const ASN1_ITEM * name##_it(void);
+# define DECLARE_ASN1_ITEM(name) \
+ DECLARE_ASN1_ITEM_attr(extern, name)
+
+/* Parameters used by ASN1_STRING_print_ex() */
+
+/*
+ * These determine which characters to escape: RFC2253 special characters,
+ * control characters and MSB set characters
+ */
+
+# define ASN1_STRFLGS_ESC_2253 1
+# define ASN1_STRFLGS_ESC_CTRL 2
+# define ASN1_STRFLGS_ESC_MSB 4
+
+/* Lower 8 bits are reserved as an output type specifier */
+# define ASN1_DTFLGS_TYPE_MASK 0x0FUL
+# define ASN1_DTFLGS_RFC822 0x00UL
+# define ASN1_DTFLGS_ISO8601 0x01UL
+
+/*
+ * This flag determines how we do escaping: normally RC2253 backslash only,
+ * set this to use backslash and quote.
+ */
+
+# define ASN1_STRFLGS_ESC_QUOTE 8
+
+/* These three flags are internal use only. */
+
+/* Character is a valid PrintableString character */
+# define CHARTYPE_PRINTABLESTRING 0x10
+/* Character needs escaping if it is the first character */
+# define CHARTYPE_FIRST_ESC_2253 0x20
+/* Character needs escaping if it is the last character */
+# define CHARTYPE_LAST_ESC_2253 0x40
+
+/*
+ * NB the internal flags are safely reused below by flags handled at the top
+ * level.
+ */
+
+/*
+ * If this is set we convert all character strings to UTF8 first
+ */
+
+# define ASN1_STRFLGS_UTF8_CONVERT 0x10
+
+/*
+ * If this is set we don't attempt to interpret content: just assume all
+ * strings are 1 byte per character. This will produce some pretty odd
+ * looking output!
+ */
+
+# define ASN1_STRFLGS_IGNORE_TYPE 0x20
+
+/* If this is set we include the string type in the output */
+# define ASN1_STRFLGS_SHOW_TYPE 0x40
+
+/*
+ * This determines which strings to display and which to 'dump' (hex dump of
+ * content octets or DER encoding). We can only dump non character strings or
+ * everything. If we don't dump 'unknown' they are interpreted as character
+ * strings with 1 octet per character and are subject to the usual escaping
+ * options.
+ */
+
+# define ASN1_STRFLGS_DUMP_ALL 0x80
+# define ASN1_STRFLGS_DUMP_UNKNOWN 0x100
+
+/*
+ * These determine what 'dumping' does, we can dump the content octets or the
+ * DER encoding: both use the RFC2253 #XXXXX notation.
+ */
+
+# define ASN1_STRFLGS_DUMP_DER 0x200
+
+/*
+ * This flag specifies that RC2254 escaping shall be performed.
+ */
+#define ASN1_STRFLGS_ESC_2254 0x400
+
+/*
+ * All the string flags consistent with RFC2253, escaping control characters
+ * isn't essential in RFC2253 but it is advisable anyway.
+ */
+
+# define ASN1_STRFLGS_RFC2253 (ASN1_STRFLGS_ESC_2253 | \
+ ASN1_STRFLGS_ESC_CTRL | \
+ ASN1_STRFLGS_ESC_MSB | \
+ ASN1_STRFLGS_UTF8_CONVERT | \
+ ASN1_STRFLGS_DUMP_UNKNOWN | \
+ ASN1_STRFLGS_DUMP_DER)
+
+
+struct asn1_type_st {
+ int type;
+ union {
+ char *ptr;
+ ASN1_BOOLEAN boolean;
+ ASN1_STRING *asn1_string;
+ ASN1_OBJECT *object;
+ ASN1_INTEGER *integer;
+ ASN1_ENUMERATED *enumerated;
+ ASN1_BIT_STRING *bit_string;
+ ASN1_OCTET_STRING *octet_string;
+ ASN1_PRINTABLESTRING *printablestring;
+ ASN1_T61STRING *t61string;
+ ASN1_IA5STRING *ia5string;
+ ASN1_GENERALSTRING *generalstring;
+ ASN1_BMPSTRING *bmpstring;
+ ASN1_UNIVERSALSTRING *universalstring;
+ ASN1_UTCTIME *utctime;
+ ASN1_GENERALIZEDTIME *generalizedtime;
+ ASN1_VISIBLESTRING *visiblestring;
+ ASN1_UTF8STRING *utf8string;
+ /*
+ * set and sequence are left complete and still contain the set or
+ * sequence bytes
+ */
+ ASN1_STRING *set;
+ ASN1_STRING *sequence;
+ ASN1_VALUE *asn1_value;
+ } value;
+};
+
+{-
+ generate_stack_macros("ASN1_TYPE");
+-}
+
+typedef STACK_OF(ASN1_TYPE) ASN1_SEQUENCE_ANY;
+
+DECLARE_ASN1_ENCODE_FUNCTIONS_name(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY)
+DECLARE_ASN1_ENCODE_FUNCTIONS_name(ASN1_SEQUENCE_ANY, ASN1_SET_ANY)
+
+/* This is used to contain a list of bit names */
+typedef struct BIT_STRING_BITNAME_st {
+ int bitnum;
+ const char *lname;
+ const char *sname;
+} BIT_STRING_BITNAME;
+
+# define B_ASN1_TIME \
+ B_ASN1_UTCTIME | \
+ B_ASN1_GENERALIZEDTIME
+
+# define B_ASN1_PRINTABLE \
+ B_ASN1_NUMERICSTRING| \
+ B_ASN1_PRINTABLESTRING| \
+ B_ASN1_T61STRING| \
+ B_ASN1_IA5STRING| \
+ B_ASN1_BIT_STRING| \
+ B_ASN1_UNIVERSALSTRING|\
+ B_ASN1_BMPSTRING|\
+ B_ASN1_UTF8STRING|\
+ B_ASN1_SEQUENCE|\
+ B_ASN1_UNKNOWN
+
+# define B_ASN1_DIRECTORYSTRING \
+ B_ASN1_PRINTABLESTRING| \
+ B_ASN1_TELETEXSTRING|\
+ B_ASN1_BMPSTRING|\
+ B_ASN1_UNIVERSALSTRING|\
+ B_ASN1_UTF8STRING
+
+# define B_ASN1_DISPLAYTEXT \
+ B_ASN1_IA5STRING| \
+ B_ASN1_VISIBLESTRING| \
+ B_ASN1_BMPSTRING|\
+ B_ASN1_UTF8STRING
+
+DECLARE_ASN1_ALLOC_FUNCTIONS_name(ASN1_TYPE, ASN1_TYPE)
+DECLARE_ASN1_ENCODE_FUNCTIONS(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
+
+int ASN1_TYPE_get(const ASN1_TYPE *a);
+void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value);
+int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value);
+int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b);
+
+ASN1_TYPE *ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t);
+void *ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t);
+
+{-
+ generate_stack_macros("ASN1_OBJECT");
+-}
+
+DECLARE_ASN1_FUNCTIONS(ASN1_OBJECT)
+
+ASN1_STRING *ASN1_STRING_new(void);
+void ASN1_STRING_free(ASN1_STRING *a);
+void ASN1_STRING_clear_free(ASN1_STRING *a);
+int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str);
+DECLARE_ASN1_DUP_FUNCTION(ASN1_STRING)
+ASN1_STRING *ASN1_STRING_type_new(int type);
+int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b);
+ /*
+ * Since this is used to store all sorts of things, via macros, for now,
+ * make its data void *
+ */
+int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len);
+void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len);
+int ASN1_STRING_length(const ASN1_STRING *x);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 void ASN1_STRING_length_set(ASN1_STRING *x, int n);
+# endif
+int ASN1_STRING_type(const ASN1_STRING *x);
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 unsigned char *ASN1_STRING_data(ASN1_STRING *x);
+# endif
+const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING)
+int ASN1_BIT_STRING_set(ASN1_BIT_STRING *a, unsigned char *d, int length);
+int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value);
+int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n);
+int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a,
+ const unsigned char *flags, int flags_len);
+
+int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
+ BIT_STRING_BITNAME *tbl, int indent);
+int ASN1_BIT_STRING_num_asc(const char *name, BIT_STRING_BITNAME *tbl);
+int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, const char *name, int value,
+ BIT_STRING_BITNAME *tbl);
+
+{-
+ generate_stack_macros("ASN1_INTEGER");
+-}
+
+
+DECLARE_ASN1_FUNCTIONS(ASN1_INTEGER)
+ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
+ long length);
+DECLARE_ASN1_DUP_FUNCTION(ASN1_INTEGER)
+int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_ENUMERATED)
+
+int ASN1_UTCTIME_check(const ASN1_UTCTIME *a);
+ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t);
+ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
+ int offset_day, long offset_sec);
+int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str);
+int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t);
+
+int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *a);
+ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
+ time_t t);
+ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
+ time_t t, int offset_day,
+ long offset_sec);
+int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str);
+
+int ASN1_TIME_diff(int *pday, int *psec,
+ const ASN1_TIME *from, const ASN1_TIME *to);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_OCTET_STRING)
+DECLARE_ASN1_DUP_FUNCTION(ASN1_OCTET_STRING)
+int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a,
+ const ASN1_OCTET_STRING *b);
+int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *str, const unsigned char *data,
+ int len);
+
+{-
+ generate_stack_macros("ASN1_UTF8STRING");
+-}
+
+DECLARE_ASN1_FUNCTIONS(ASN1_VISIBLESTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UTF8STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_NULL)
+DECLARE_ASN1_FUNCTIONS(ASN1_BMPSTRING)
+
+int UTF8_getc(const unsigned char *str, int len, unsigned long *val);
+int UTF8_putc(unsigned char *str, int len, unsigned long value);
+
+{-
+ generate_stack_macros("ASN1_GENERALSTRING");
+-}
+
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE)
+
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING)
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT)
+DECLARE_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_T61STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_IA5STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_GENERALSTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UTCTIME)
+DECLARE_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME)
+DECLARE_ASN1_FUNCTIONS(ASN1_TIME)
+
+DECLARE_ASN1_DUP_FUNCTION(ASN1_TIME)
+DECLARE_ASN1_DUP_FUNCTION(ASN1_UTCTIME)
+DECLARE_ASN1_DUP_FUNCTION(ASN1_GENERALIZEDTIME)
+
+DECLARE_ASN1_ITEM(ASN1_OCTET_STRING_NDEF)
+
+ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t);
+ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
+ int offset_day, long offset_sec);
+int ASN1_TIME_check(const ASN1_TIME *t);
+ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
+ ASN1_GENERALIZEDTIME **out);
+int ASN1_TIME_set_string(ASN1_TIME *s, const char *str);
+int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str);
+int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm);
+int ASN1_TIME_normalize(ASN1_TIME *s);
+int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t);
+int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b);
+
+int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a);
+int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size);
+int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a);
+int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size);
+int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a);
+int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size);
+int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type);
+int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a);
+
+int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num);
+ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
+ const char *sn, const char *ln);
+
+int ASN1_INTEGER_get_int64(int64_t *pr, const ASN1_INTEGER *a);
+int ASN1_INTEGER_set_int64(ASN1_INTEGER *a, int64_t r);
+int ASN1_INTEGER_get_uint64(uint64_t *pr, const ASN1_INTEGER *a);
+int ASN1_INTEGER_set_uint64(ASN1_INTEGER *a, uint64_t r);
+
+int ASN1_INTEGER_set(ASN1_INTEGER *a, long v);
+long ASN1_INTEGER_get(const ASN1_INTEGER *a);
+ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai);
+BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn);
+
+int ASN1_ENUMERATED_get_int64(int64_t *pr, const ASN1_ENUMERATED *a);
+int ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *a, int64_t r);
+
+
+int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v);
+long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a);
+ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai);
+BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn);
+
+/* General */
+/* given a string, return the correct type, max is the maximum length */
+int ASN1_PRINTABLE_type(const unsigned char *s, int max);
+
+unsigned long ASN1_tag2bit(int tag);
+
+/* SPECIALS */
+int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
+ int *pclass, long omax);
+int ASN1_check_infinite_end(unsigned char **p, long len);
+int ASN1_const_check_infinite_end(const unsigned char **p, long len);
+void ASN1_put_object(unsigned char **pp, int constructed, int length,
+ int tag, int xclass);
+int ASN1_put_eoc(unsigned char **pp);
+int ASN1_object_size(int constructed, int length, int tag);
+
+/* Used to implement other functions */
+void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, const void *x);
+
+# define ASN1_dup_of(type,i2d,d2i,x) \
+ ((type*)ASN1_dup(CHECKED_I2D_OF(type, i2d), \
+ CHECKED_D2I_OF(type, d2i), \
+ CHECKED_PTR_OF(const type, x)))
+
+void *ASN1_item_dup(const ASN1_ITEM *it, const void *x);
+int ASN1_item_sign_ex(const ASN1_ITEM *it, X509_ALGOR *algor1,
+ X509_ALGOR *algor2, ASN1_BIT_STRING *signature,
+ const void *data, const ASN1_OCTET_STRING *id,
+ EVP_PKEY *pkey, const EVP_MD *md, OSSL_LIB_CTX *libctx,
+ const char *propq);
+int ASN1_item_verify_ex(const ASN1_ITEM *it, const X509_ALGOR *alg,
+ const ASN1_BIT_STRING *signature, const void *data,
+ const ASN1_OCTET_STRING *id, EVP_PKEY *pkey,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+/* ASN1 alloc/free macros for when a type is only used internally */
+
+# define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type))
+# define M_ASN1_free_of(x, type) \
+ ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type))
+
+# ifndef OPENSSL_NO_STDIO
+void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x);
+
+# define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \
+ ((type*)ASN1_d2i_fp(CHECKED_NEW_OF(type, xnew), \
+ CHECKED_D2I_OF(type, d2i), \
+ in, \
+ CHECKED_PPTR_OF(type, x)))
+
+void *ASN1_item_d2i_fp_ex(const ASN1_ITEM *it, FILE *in, void *x,
+ OSSL_LIB_CTX *libctx, const char *propq);
+void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);
+int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, const void *x);
+
+# define ASN1_i2d_fp_of(type,i2d,out,x) \
+ (ASN1_i2d_fp(CHECKED_I2D_OF(type, i2d), \
+ out, \
+ CHECKED_PTR_OF(const type, x)))
+
+int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, const void *x);
+int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags);
+# endif
+
+int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in);
+
+void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x);
+
+# define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \
+ ((type*)ASN1_d2i_bio( CHECKED_NEW_OF(type, xnew), \
+ CHECKED_D2I_OF(type, d2i), \
+ in, \
+ CHECKED_PPTR_OF(type, x)))
+
+void *ASN1_item_d2i_bio_ex(const ASN1_ITEM *it, BIO *in, void *pval,
+ OSSL_LIB_CTX *libctx, const char *propq);
+void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *pval);
+int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, const void *x);
+
+# define ASN1_i2d_bio_of(type,i2d,out,x) \
+ (ASN1_i2d_bio(CHECKED_I2D_OF(type, i2d), \
+ out, \
+ CHECKED_PTR_OF(const type, x)))
+
+int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, const void *x);
+BIO *ASN1_item_i2d_mem_bio(const ASN1_ITEM *it, const ASN1_VALUE *val);
+int ASN1_UTCTIME_print(BIO *fp, const ASN1_UTCTIME *a);
+int ASN1_GENERALIZEDTIME_print(BIO *fp, const ASN1_GENERALIZEDTIME *a);
+int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm);
+int ASN1_TIME_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags);
+int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v);
+int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags);
+int ASN1_buf_print(BIO *bp, const unsigned char *buf, size_t buflen, int off);
+int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num,
+ unsigned char *buf, int off);
+int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent);
+int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent,
+ int dump);
+const char *ASN1_tag2str(int tag);
+
+/* Used to load and write Netscape format cert */
+
+int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s);
+
+int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len);
+int ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len);
+int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num,
+ unsigned char *data, int len);
+int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num,
+ unsigned char *data, int max_len);
+
+void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it);
+
+ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it,
+ ASN1_OCTET_STRING **oct);
+
+void ASN1_STRING_set_default_mask(unsigned long mask);
+int ASN1_STRING_set_default_mask_asc(const char *p);
+unsigned long ASN1_STRING_get_default_mask(void);
+int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
+ int inform, unsigned long mask);
+int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
+ int inform, unsigned long mask,
+ long minsize, long maxsize);
+
+ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
+ const unsigned char *in, int inlen,
+ int inform, int nid);
+ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid);
+int ASN1_STRING_TABLE_add(int, long, long, unsigned long, unsigned long);
+void ASN1_STRING_TABLE_cleanup(void);
+
+/* ASN1 template functions */
+
+/* Old API compatible functions */
+ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it);
+ASN1_VALUE *ASN1_item_new_ex(const ASN1_ITEM *it, OSSL_LIB_CTX *libctx,
+ const char *propq);
+void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it);
+ASN1_VALUE *ASN1_item_d2i_ex(ASN1_VALUE **val, const unsigned char **in,
+ long len, const ASN1_ITEM *it,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in,
+ long len, const ASN1_ITEM *it);
+int ASN1_item_i2d(const ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
+int ASN1_item_ndef_i2d(const ASN1_VALUE *val, unsigned char **out,
+ const ASN1_ITEM *it);
+
+void ASN1_add_oid_module(void);
+void ASN1_add_stable_module(void);
+
+ASN1_TYPE *ASN1_generate_nconf(const char *str, CONF *nconf);
+ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf);
+int ASN1_str2mask(const char *str, unsigned long *pmask);
+
+/* ASN1 Print flags */
+
+/* Indicate missing OPTIONAL fields */
+# define ASN1_PCTX_FLAGS_SHOW_ABSENT 0x001
+/* Mark start and end of SEQUENCE */
+# define ASN1_PCTX_FLAGS_SHOW_SEQUENCE 0x002
+/* Mark start and end of SEQUENCE/SET OF */
+# define ASN1_PCTX_FLAGS_SHOW_SSOF 0x004
+/* Show the ASN1 type of primitives */
+# define ASN1_PCTX_FLAGS_SHOW_TYPE 0x008
+/* Don't show ASN1 type of ANY */
+# define ASN1_PCTX_FLAGS_NO_ANY_TYPE 0x010
+/* Don't show ASN1 type of MSTRINGs */
+# define ASN1_PCTX_FLAGS_NO_MSTRING_TYPE 0x020
+/* Don't show field names in SEQUENCE */
+# define ASN1_PCTX_FLAGS_NO_FIELD_NAME 0x040
+/* Show structure names of each SEQUENCE field */
+# define ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME 0x080
+/* Don't show structure name even at top level */
+# define ASN1_PCTX_FLAGS_NO_STRUCT_NAME 0x100
+
+int ASN1_item_print(BIO *out, const ASN1_VALUE *ifld, int indent,
+ const ASN1_ITEM *it, const ASN1_PCTX *pctx);
+ASN1_PCTX *ASN1_PCTX_new(void);
+void ASN1_PCTX_free(ASN1_PCTX *p);
+unsigned long ASN1_PCTX_get_flags(const ASN1_PCTX *p);
+void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags);
+unsigned long ASN1_PCTX_get_nm_flags(const ASN1_PCTX *p);
+void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags);
+unsigned long ASN1_PCTX_get_cert_flags(const ASN1_PCTX *p);
+void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags);
+unsigned long ASN1_PCTX_get_oid_flags(const ASN1_PCTX *p);
+void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags);
+unsigned long ASN1_PCTX_get_str_flags(const ASN1_PCTX *p);
+void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags);
+
+ASN1_SCTX *ASN1_SCTX_new(int (*scan_cb) (ASN1_SCTX *ctx));
+void ASN1_SCTX_free(ASN1_SCTX *p);
+const ASN1_ITEM *ASN1_SCTX_get_item(ASN1_SCTX *p);
+const ASN1_TEMPLATE *ASN1_SCTX_get_template(ASN1_SCTX *p);
+unsigned long ASN1_SCTX_get_flags(ASN1_SCTX *p);
+void ASN1_SCTX_set_app_data(ASN1_SCTX *p, void *data);
+void *ASN1_SCTX_get_app_data(ASN1_SCTX *p);
+
+const BIO_METHOD *BIO_f_asn1(void);
+
+/* cannot constify val because of CMS_stream() */
+BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it);
+
+int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
+ const ASN1_ITEM *it);
+int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
+ const char *hdr, const ASN1_ITEM *it);
+/* cannot constify val because of CMS_dataFinal() */
+int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+ int ctype_nid, int econt_nid,
+ STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it);
+int SMIME_write_ASN1_ex(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+ int ctype_nid, int econt_nid,
+ STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
+ASN1_VALUE *SMIME_read_ASN1_ex(BIO *bio, int flags, BIO **bcont,
+ const ASN1_ITEM *it, ASN1_VALUE **x,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int SMIME_crlf_copy(BIO *in, BIO *out, int flags);
+int SMIME_text(BIO *in, BIO *out);
+
+const ASN1_ITEM *ASN1_ITEM_lookup(const char *name);
+const ASN1_ITEM *ASN1_ITEM_get(size_t i);
+
+/* Legacy compatibility */
+# define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \
+ DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
+ DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name)
+# define DECLARE_ASN1_FUNCTIONS_const(type) DECLARE_ASN1_FUNCTIONS(type)
+# define DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \
+ DECLARE_ASN1_ENCODE_FUNCTIONS(type, name)
+# define I2D_OF_const(type) I2D_OF(type)
+# define ASN1_dup_of_const(type,i2d,d2i,x) ASN1_dup_of(type,i2d,d2i,x)
+# define ASN1_i2d_fp_of_const(type,i2d,out,x) ASN1_i2d_fp_of(type,i2d,out,x)
+# define ASN1_i2d_bio_of_const(type,i2d,out,x) ASN1_i2d_bio_of(type,i2d,out,x)
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/asn1_mac.h b/include/openssl/asn1_mac.h
index 7ac1782a3f20..fdcb983656ac 100644
--- a/include/openssl/asn1_mac.h
+++ b/include/openssl/asn1_mac.h
@@ -1,7 +1,7 @@
/*
* Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/include/openssl/asn1err.h b/include/openssl/asn1err.h
index e1ad1fefeca7..d4276220cbbe 100644
--- a/include/openssl/asn1err.h
+++ b/include/openssl/asn1err.h
@@ -1,140 +1,22 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_ASN1ERR_H
-# define HEADER_ASN1ERR_H
+#ifndef OPENSSL_ASN1ERR_H
+# define OPENSSL_ASN1ERR_H
+# pragma once
+# include <openssl/opensslconf.h>
# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_ASN1_strings(void);
-/*
- * ASN1 function codes.
- */
-# define ASN1_F_A2D_ASN1_OBJECT 100
-# define ASN1_F_A2I_ASN1_INTEGER 102
-# define ASN1_F_A2I_ASN1_STRING 103
-# define ASN1_F_APPEND_EXP 176
-# define ASN1_F_ASN1_BIO_INIT 113
-# define ASN1_F_ASN1_BIT_STRING_SET_BIT 183
-# define ASN1_F_ASN1_CB 177
-# define ASN1_F_ASN1_CHECK_TLEN 104
-# define ASN1_F_ASN1_COLLECT 106
-# define ASN1_F_ASN1_D2I_EX_PRIMITIVE 108
-# define ASN1_F_ASN1_D2I_FP 109
-# define ASN1_F_ASN1_D2I_READ_BIO 107
-# define ASN1_F_ASN1_DIGEST 184
-# define ASN1_F_ASN1_DO_ADB 110
-# define ASN1_F_ASN1_DO_LOCK 233
-# define ASN1_F_ASN1_DUP 111
-# define ASN1_F_ASN1_ENC_SAVE 115
-# define ASN1_F_ASN1_EX_C2I 204
-# define ASN1_F_ASN1_FIND_END 190
-# define ASN1_F_ASN1_GENERALIZEDTIME_ADJ 216
-# define ASN1_F_ASN1_GENERATE_V3 178
-# define ASN1_F_ASN1_GET_INT64 224
-# define ASN1_F_ASN1_GET_OBJECT 114
-# define ASN1_F_ASN1_GET_UINT64 225
-# define ASN1_F_ASN1_I2D_BIO 116
-# define ASN1_F_ASN1_I2D_FP 117
-# define ASN1_F_ASN1_ITEM_D2I_FP 206
-# define ASN1_F_ASN1_ITEM_DUP 191
-# define ASN1_F_ASN1_ITEM_EMBED_D2I 120
-# define ASN1_F_ASN1_ITEM_EMBED_NEW 121
-# define ASN1_F_ASN1_ITEM_EX_I2D 144
-# define ASN1_F_ASN1_ITEM_FLAGS_I2D 118
-# define ASN1_F_ASN1_ITEM_I2D_BIO 192
-# define ASN1_F_ASN1_ITEM_I2D_FP 193
-# define ASN1_F_ASN1_ITEM_PACK 198
-# define ASN1_F_ASN1_ITEM_SIGN 195
-# define ASN1_F_ASN1_ITEM_SIGN_CTX 220
-# define ASN1_F_ASN1_ITEM_UNPACK 199
-# define ASN1_F_ASN1_ITEM_VERIFY 197
-# define ASN1_F_ASN1_MBSTRING_NCOPY 122
-# define ASN1_F_ASN1_OBJECT_NEW 123
-# define ASN1_F_ASN1_OUTPUT_DATA 214
-# define ASN1_F_ASN1_PCTX_NEW 205
-# define ASN1_F_ASN1_PRIMITIVE_NEW 119
-# define ASN1_F_ASN1_SCTX_NEW 221
-# define ASN1_F_ASN1_SIGN 128
-# define ASN1_F_ASN1_STR2TYPE 179
-# define ASN1_F_ASN1_STRING_GET_INT64 227
-# define ASN1_F_ASN1_STRING_GET_UINT64 230
-# define ASN1_F_ASN1_STRING_SET 186
-# define ASN1_F_ASN1_STRING_TABLE_ADD 129
-# define ASN1_F_ASN1_STRING_TO_BN 228
-# define ASN1_F_ASN1_STRING_TYPE_NEW 130
-# define ASN1_F_ASN1_TEMPLATE_EX_D2I 132
-# define ASN1_F_ASN1_TEMPLATE_NEW 133
-# define ASN1_F_ASN1_TEMPLATE_NOEXP_D2I 131
-# define ASN1_F_ASN1_TIME_ADJ 217
-# define ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING 134
-# define ASN1_F_ASN1_TYPE_GET_OCTETSTRING 135
-# define ASN1_F_ASN1_UTCTIME_ADJ 218
-# define ASN1_F_ASN1_VERIFY 137
-# define ASN1_F_B64_READ_ASN1 209
-# define ASN1_F_B64_WRITE_ASN1 210
-# define ASN1_F_BIO_NEW_NDEF 208
-# define ASN1_F_BITSTR_CB 180
-# define ASN1_F_BN_TO_ASN1_STRING 229
-# define ASN1_F_C2I_ASN1_BIT_STRING 189
-# define ASN1_F_C2I_ASN1_INTEGER 194
-# define ASN1_F_C2I_ASN1_OBJECT 196
-# define ASN1_F_C2I_IBUF 226
-# define ASN1_F_C2I_UINT64_INT 101
-# define ASN1_F_COLLECT_DATA 140
-# define ASN1_F_D2I_ASN1_OBJECT 147
-# define ASN1_F_D2I_ASN1_UINTEGER 150
-# define ASN1_F_D2I_AUTOPRIVATEKEY 207
-# define ASN1_F_D2I_PRIVATEKEY 154
-# define ASN1_F_D2I_PUBLICKEY 155
-# define ASN1_F_DO_BUF 142
-# define ASN1_F_DO_CREATE 124
-# define ASN1_F_DO_DUMP 125
-# define ASN1_F_DO_TCREATE 222
-# define ASN1_F_I2A_ASN1_OBJECT 126
-# define ASN1_F_I2D_ASN1_BIO_STREAM 211
-# define ASN1_F_I2D_ASN1_OBJECT 143
-# define ASN1_F_I2D_DSA_PUBKEY 161
-# define ASN1_F_I2D_EC_PUBKEY 181
-# define ASN1_F_I2D_PRIVATEKEY 163
-# define ASN1_F_I2D_PUBLICKEY 164
-# define ASN1_F_I2D_RSA_PUBKEY 165
-# define ASN1_F_LONG_C2I 166
-# define ASN1_F_NDEF_PREFIX 127
-# define ASN1_F_NDEF_SUFFIX 136
-# define ASN1_F_OID_MODULE_INIT 174
-# define ASN1_F_PARSE_TAGGING 182
-# define ASN1_F_PKCS5_PBE2_SET_IV 167
-# define ASN1_F_PKCS5_PBE2_SET_SCRYPT 231
-# define ASN1_F_PKCS5_PBE_SET 202
-# define ASN1_F_PKCS5_PBE_SET0_ALGOR 215
-# define ASN1_F_PKCS5_PBKDF2_SET 219
-# define ASN1_F_PKCS5_SCRYPT_SET 232
-# define ASN1_F_SMIME_READ_ASN1 212
-# define ASN1_F_SMIME_TEXT 213
-# define ASN1_F_STABLE_GET 138
-# define ASN1_F_STBL_MODULE_INIT 223
-# define ASN1_F_UINT32_C2I 105
-# define ASN1_F_UINT32_NEW 139
-# define ASN1_F_UINT64_C2I 112
-# define ASN1_F_UINT64_NEW 141
-# define ASN1_F_X509_CRL_ADD0_REVOKED 169
-# define ASN1_F_X509_INFO_NEW 170
-# define ASN1_F_X509_NAME_ENCODE 203
-# define ASN1_F_X509_NAME_EX_D2I 158
-# define ASN1_F_X509_NAME_EX_NEW 171
-# define ASN1_F_X509_PKEY_NEW 173
/*
* ASN1 reason codes.
@@ -199,6 +81,7 @@ int ERR_load_ASN1_strings(void);
# define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 133
# define ASN1_R_INVALID_UTF8STRING 134
# define ASN1_R_INVALID_VALUE 219
+# define ASN1_R_LENGTH_TOO_LONG 231
# define ASN1_R_LIST_ERROR 188
# define ASN1_R_MIME_NO_CONTENT_TYPE 206
# define ASN1_R_MIME_PARSE_ERROR 207
@@ -239,6 +122,7 @@ int ERR_load_ASN1_strings(void);
# define ASN1_R_TYPE_NOT_PRIMITIVE 195
# define ASN1_R_UNEXPECTED_EOC 159
# define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 215
+# define ASN1_R_UNKNOWN_DIGEST 229
# define ASN1_R_UNKNOWN_FORMAT 160
# define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 161
# define ASN1_R_UNKNOWN_OBJECT_TYPE 162
diff --git a/include/openssl/asn1t.h b/include/openssl/asn1t.h
deleted file mode 100644
index a450ba0d9dea..000000000000
--- a/include/openssl/asn1t.h
+++ /dev/null
@@ -1,945 +0,0 @@
-/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_ASN1T_H
-# define HEADER_ASN1T_H
-
-# include <stddef.h>
-# include <openssl/e_os2.h>
-# include <openssl/asn1.h>
-
-# ifdef OPENSSL_BUILD_SHLIBCRYPTO
-# undef OPENSSL_EXTERN
-# define OPENSSL_EXTERN OPENSSL_EXPORT
-# endif
-
-/* ASN1 template defines, structures and functions */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
-
-/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */
-# define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr))
-
-/* Macros for start and end of ASN1_ITEM definition */
-
-# define ASN1_ITEM_start(itname) \
- const ASN1_ITEM itname##_it = {
-
-# define static_ASN1_ITEM_start(itname) \
- static const ASN1_ITEM itname##_it = {
-
-# define ASN1_ITEM_end(itname) \
- };
-
-# else
-
-/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */
-# define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)((iptr)()))
-
-/* Macros for start and end of ASN1_ITEM definition */
-
-# define ASN1_ITEM_start(itname) \
- const ASN1_ITEM * itname##_it(void) \
- { \
- static const ASN1_ITEM local_it = {
-
-# define static_ASN1_ITEM_start(itname) \
- static ASN1_ITEM_start(itname)
-
-# define ASN1_ITEM_end(itname) \
- }; \
- return &local_it; \
- }
-
-# endif
-
-/* Macros to aid ASN1 template writing */
-
-# define ASN1_ITEM_TEMPLATE(tname) \
- static const ASN1_TEMPLATE tname##_item_tt
-
-# define ASN1_ITEM_TEMPLATE_END(tname) \
- ;\
- ASN1_ITEM_start(tname) \
- ASN1_ITYPE_PRIMITIVE,\
- -1,\
- &tname##_item_tt,\
- 0,\
- NULL,\
- 0,\
- #tname \
- ASN1_ITEM_end(tname)
-# define static_ASN1_ITEM_TEMPLATE_END(tname) \
- ;\
- static_ASN1_ITEM_start(tname) \
- ASN1_ITYPE_PRIMITIVE,\
- -1,\
- &tname##_item_tt,\
- 0,\
- NULL,\
- 0,\
- #tname \
- ASN1_ITEM_end(tname)
-
-/* This is a ASN1 type which just embeds a template */
-
-/*-
- * This pair helps declare a SEQUENCE. We can do:
- *
- * ASN1_SEQUENCE(stname) = {
- * ... SEQUENCE components ...
- * } ASN1_SEQUENCE_END(stname)
- *
- * This will produce an ASN1_ITEM called stname_it
- * for a structure called stname.
- *
- * If you want the same structure but a different
- * name then use:
- *
- * ASN1_SEQUENCE(itname) = {
- * ... SEQUENCE components ...
- * } ASN1_SEQUENCE_END_name(stname, itname)
- *
- * This will create an item called itname_it using
- * a structure called stname.
- */
-
-# define ASN1_SEQUENCE(tname) \
- static const ASN1_TEMPLATE tname##_seq_tt[]
-
-# define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname)
-
-# define static_ASN1_SEQUENCE_END(stname) static_ASN1_SEQUENCE_END_name(stname, stname)
-
-# define ASN1_SEQUENCE_END_name(stname, tname) \
- ;\
- ASN1_ITEM_start(tname) \
- ASN1_ITYPE_SEQUENCE,\
- V_ASN1_SEQUENCE,\
- tname##_seq_tt,\
- sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
- NULL,\
- sizeof(stname),\
- #tname \
- ASN1_ITEM_end(tname)
-
-# define static_ASN1_SEQUENCE_END_name(stname, tname) \
- ;\
- static_ASN1_ITEM_start(tname) \
- ASN1_ITYPE_SEQUENCE,\
- V_ASN1_SEQUENCE,\
- tname##_seq_tt,\
- sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
- NULL,\
- sizeof(stname),\
- #stname \
- ASN1_ITEM_end(tname)
-
-# define ASN1_NDEF_SEQUENCE(tname) \
- ASN1_SEQUENCE(tname)
-
-# define ASN1_NDEF_SEQUENCE_cb(tname, cb) \
- ASN1_SEQUENCE_cb(tname, cb)
-
-# define ASN1_SEQUENCE_cb(tname, cb) \
- static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
- ASN1_SEQUENCE(tname)
-
-# define ASN1_BROKEN_SEQUENCE(tname) \
- static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \
- ASN1_SEQUENCE(tname)
-
-# define ASN1_SEQUENCE_ref(tname, cb) \
- static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), offsetof(tname, lock), cb, 0}; \
- ASN1_SEQUENCE(tname)
-
-# define ASN1_SEQUENCE_enc(tname, enc, cb) \
- static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_ENCODING, 0, 0, cb, offsetof(tname, enc)}; \
- ASN1_SEQUENCE(tname)
-
-# define ASN1_NDEF_SEQUENCE_END(tname) \
- ;\
- ASN1_ITEM_start(tname) \
- ASN1_ITYPE_NDEF_SEQUENCE,\
- V_ASN1_SEQUENCE,\
- tname##_seq_tt,\
- sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
- NULL,\
- sizeof(tname),\
- #tname \
- ASN1_ITEM_end(tname)
-# define static_ASN1_NDEF_SEQUENCE_END(tname) \
- ;\
- static_ASN1_ITEM_start(tname) \
- ASN1_ITYPE_NDEF_SEQUENCE,\
- V_ASN1_SEQUENCE,\
- tname##_seq_tt,\
- sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
- NULL,\
- sizeof(tname),\
- #tname \
- ASN1_ITEM_end(tname)
-
-# define ASN1_BROKEN_SEQUENCE_END(stname) ASN1_SEQUENCE_END_ref(stname, stname)
-# define static_ASN1_BROKEN_SEQUENCE_END(stname) \
- static_ASN1_SEQUENCE_END_ref(stname, stname)
-
-# define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
-
-# define ASN1_SEQUENCE_END_cb(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
-# define static_ASN1_SEQUENCE_END_cb(stname, tname) static_ASN1_SEQUENCE_END_ref(stname, tname)
-
-# define ASN1_SEQUENCE_END_ref(stname, tname) \
- ;\
- ASN1_ITEM_start(tname) \
- ASN1_ITYPE_SEQUENCE,\
- V_ASN1_SEQUENCE,\
- tname##_seq_tt,\
- sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
- &tname##_aux,\
- sizeof(stname),\
- #tname \
- ASN1_ITEM_end(tname)
-# define static_ASN1_SEQUENCE_END_ref(stname, tname) \
- ;\
- static_ASN1_ITEM_start(tname) \
- ASN1_ITYPE_SEQUENCE,\
- V_ASN1_SEQUENCE,\
- tname##_seq_tt,\
- sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
- &tname##_aux,\
- sizeof(stname),\
- #stname \
- ASN1_ITEM_end(tname)
-
-# define ASN1_NDEF_SEQUENCE_END_cb(stname, tname) \
- ;\
- ASN1_ITEM_start(tname) \
- ASN1_ITYPE_NDEF_SEQUENCE,\
- V_ASN1_SEQUENCE,\
- tname##_seq_tt,\
- sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
- &tname##_aux,\
- sizeof(stname),\
- #stname \
- ASN1_ITEM_end(tname)
-
-/*-
- * This pair helps declare a CHOICE type. We can do:
- *
- * ASN1_CHOICE(chname) = {
- * ... CHOICE options ...
- * ASN1_CHOICE_END(chname)
- *
- * This will produce an ASN1_ITEM called chname_it
- * for a structure called chname. The structure
- * definition must look like this:
- * typedef struct {
- * int type;
- * union {
- * ASN1_SOMETHING *opt1;
- * ASN1_SOMEOTHER *opt2;
- * } value;
- * } chname;
- *
- * the name of the selector must be 'type'.
- * to use an alternative selector name use the
- * ASN1_CHOICE_END_selector() version.
- */
-
-# define ASN1_CHOICE(tname) \
- static const ASN1_TEMPLATE tname##_ch_tt[]
-
-# define ASN1_CHOICE_cb(tname, cb) \
- static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
- ASN1_CHOICE(tname)
-
-# define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname)
-
-# define static_ASN1_CHOICE_END(stname) static_ASN1_CHOICE_END_name(stname, stname)
-
-# define ASN1_CHOICE_END_name(stname, tname) ASN1_CHOICE_END_selector(stname, tname, type)
-
-# define static_ASN1_CHOICE_END_name(stname, tname) static_ASN1_CHOICE_END_selector(stname, tname, type)
-
-# define ASN1_CHOICE_END_selector(stname, tname, selname) \
- ;\
- ASN1_ITEM_start(tname) \
- ASN1_ITYPE_CHOICE,\
- offsetof(stname,selname) ,\
- tname##_ch_tt,\
- sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\
- NULL,\
- sizeof(stname),\
- #stname \
- ASN1_ITEM_end(tname)
-
-# define static_ASN1_CHOICE_END_selector(stname, tname, selname) \
- ;\
- static_ASN1_ITEM_start(tname) \
- ASN1_ITYPE_CHOICE,\
- offsetof(stname,selname) ,\
- tname##_ch_tt,\
- sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\
- NULL,\
- sizeof(stname),\
- #stname \
- ASN1_ITEM_end(tname)
-
-# define ASN1_CHOICE_END_cb(stname, tname, selname) \
- ;\
- ASN1_ITEM_start(tname) \
- ASN1_ITYPE_CHOICE,\
- offsetof(stname,selname) ,\
- tname##_ch_tt,\
- sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\
- &tname##_aux,\
- sizeof(stname),\
- #stname \
- ASN1_ITEM_end(tname)
-
-/* This helps with the template wrapper form of ASN1_ITEM */
-
-# define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \
- (flags), (tag), 0,\
- #name, ASN1_ITEM_ref(type) }
-
-/* These help with SEQUENCE or CHOICE components */
-
-/* used to declare other types */
-
-# define ASN1_EX_TYPE(flags, tag, stname, field, type) { \
- (flags), (tag), offsetof(stname, field),\
- #field, ASN1_ITEM_ref(type) }
-
-/* implicit and explicit helper macros */
-
-# define ASN1_IMP_EX(stname, field, type, tag, ex) \
- ASN1_EX_TYPE(ASN1_TFLG_IMPLICIT | (ex), tag, stname, field, type)
-
-# define ASN1_EXP_EX(stname, field, type, tag, ex) \
- ASN1_EX_TYPE(ASN1_TFLG_EXPLICIT | (ex), tag, stname, field, type)
-
-/* Any defined by macros: the field used is in the table itself */
-
-# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
-# define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) }
-# define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) }
-# else
-# define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, tblname##_adb }
-# define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, tblname##_adb }
-# endif
-/* Plain simple type */
-# define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type)
-/* Embedded simple type */
-# define ASN1_EMBED(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_EMBED,0, stname, field, type)
-
-/* OPTIONAL simple type */
-# define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type)
-# define ASN1_OPT_EMBED(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL|ASN1_TFLG_EMBED, 0, stname, field, type)
-
-/* IMPLICIT tagged simple type */
-# define ASN1_IMP(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, 0)
-# define ASN1_IMP_EMBED(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_EMBED)
-
-/* IMPLICIT tagged OPTIONAL simple type */
-# define ASN1_IMP_OPT(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL)
-# define ASN1_IMP_OPT_EMBED(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_EMBED)
-
-/* Same as above but EXPLICIT */
-
-# define ASN1_EXP(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, 0)
-# define ASN1_EXP_EMBED(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_EMBED)
-# define ASN1_EXP_OPT(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL)
-# define ASN1_EXP_OPT_EMBED(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_EMBED)
-
-/* SEQUENCE OF type */
-# define ASN1_SEQUENCE_OF(stname, field, type) \
- ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, stname, field, type)
-
-/* OPTIONAL SEQUENCE OF */
-# define ASN1_SEQUENCE_OF_OPT(stname, field, type) \
- ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type)
-
-/* Same as above but for SET OF */
-
-# define ASN1_SET_OF(stname, field, type) \
- ASN1_EX_TYPE(ASN1_TFLG_SET_OF, 0, stname, field, type)
-
-# define ASN1_SET_OF_OPT(stname, field, type) \
- ASN1_EX_TYPE(ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type)
-
-/* Finally compound types of SEQUENCE, SET, IMPLICIT, EXPLICIT and OPTIONAL */
-
-# define ASN1_IMP_SET_OF(stname, field, type, tag) \
- ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF)
-
-# define ASN1_EXP_SET_OF(stname, field, type, tag) \
- ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF)
-
-# define ASN1_IMP_SET_OF_OPT(stname, field, type, tag) \
- ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL)
-
-# define ASN1_EXP_SET_OF_OPT(stname, field, type, tag) \
- ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL)
-
-# define ASN1_IMP_SEQUENCE_OF(stname, field, type, tag) \
- ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF)
-
-# define ASN1_IMP_SEQUENCE_OF_OPT(stname, field, type, tag) \
- ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL)
-
-# define ASN1_EXP_SEQUENCE_OF(stname, field, type, tag) \
- ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF)
-
-# define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \
- ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL)
-
-/* EXPLICIT using indefinite length constructed form */
-# define ASN1_NDEF_EXP(stname, field, type, tag) \
- ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_NDEF)
-
-/* EXPLICIT OPTIONAL using indefinite length constructed form */
-# define ASN1_NDEF_EXP_OPT(stname, field, type, tag) \
- ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_NDEF)
-
-/* Macros for the ASN1_ADB structure */
-
-# define ASN1_ADB(name) \
- static const ASN1_ADB_TABLE name##_adbtbl[]
-
-# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
-
-# define ASN1_ADB_END(name, flags, field, adb_cb, def, none) \
- ;\
- static const ASN1_ADB name##_adb = {\
- flags,\
- offsetof(name, field),\
- adb_cb,\
- name##_adbtbl,\
- sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\
- def,\
- none\
- }
-
-# else
-
-# define ASN1_ADB_END(name, flags, field, adb_cb, def, none) \
- ;\
- static const ASN1_ITEM *name##_adb(void) \
- { \
- static const ASN1_ADB internal_adb = \
- {\
- flags,\
- offsetof(name, field),\
- adb_cb,\
- name##_adbtbl,\
- sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\
- def,\
- none\
- }; \
- return (const ASN1_ITEM *) &internal_adb; \
- } \
- void dummy_function(void)
-
-# endif
-
-# define ADB_ENTRY(val, template) {val, template}
-
-# define ASN1_ADB_TEMPLATE(name) \
- static const ASN1_TEMPLATE name##_tt
-
-/*
- * This is the ASN1 template structure that defines a wrapper round the
- * actual type. It determines the actual position of the field in the value
- * structure, various flags such as OPTIONAL and the field name.
- */
-
-struct ASN1_TEMPLATE_st {
- unsigned long flags; /* Various flags */
- long tag; /* tag, not used if no tagging */
- unsigned long offset; /* Offset of this field in structure */
- const char *field_name; /* Field name */
- ASN1_ITEM_EXP *item; /* Relevant ASN1_ITEM or ASN1_ADB */
-};
-
-/* Macro to extract ASN1_ITEM and ASN1_ADB pointer from ASN1_TEMPLATE */
-
-# define ASN1_TEMPLATE_item(t) (t->item_ptr)
-# define ASN1_TEMPLATE_adb(t) (t->item_ptr)
-
-typedef struct ASN1_ADB_TABLE_st ASN1_ADB_TABLE;
-typedef struct ASN1_ADB_st ASN1_ADB;
-
-struct ASN1_ADB_st {
- unsigned long flags; /* Various flags */
- unsigned long offset; /* Offset of selector field */
- int (*adb_cb)(long *psel); /* Application callback */
- const ASN1_ADB_TABLE *tbl; /* Table of possible types */
- long tblcount; /* Number of entries in tbl */
- const ASN1_TEMPLATE *default_tt; /* Type to use if no match */
- const ASN1_TEMPLATE *null_tt; /* Type to use if selector is NULL */
-};
-
-struct ASN1_ADB_TABLE_st {
- long value; /* NID for an object or value for an int */
- const ASN1_TEMPLATE tt; /* item for this value */
-};
-
-/* template flags */
-
-/* Field is optional */
-# define ASN1_TFLG_OPTIONAL (0x1)
-
-/* Field is a SET OF */
-# define ASN1_TFLG_SET_OF (0x1 << 1)
-
-/* Field is a SEQUENCE OF */
-# define ASN1_TFLG_SEQUENCE_OF (0x2 << 1)
-
-/*
- * Special case: this refers to a SET OF that will be sorted into DER order
- * when encoded *and* the corresponding STACK will be modified to match the
- * new order.
- */
-# define ASN1_TFLG_SET_ORDER (0x3 << 1)
-
-/* Mask for SET OF or SEQUENCE OF */
-# define ASN1_TFLG_SK_MASK (0x3 << 1)
-
-/*
- * These flags mean the tag should be taken from the tag field. If EXPLICIT
- * then the underlying type is used for the inner tag.
- */
-
-/* IMPLICIT tagging */
-# define ASN1_TFLG_IMPTAG (0x1 << 3)
-
-/* EXPLICIT tagging, inner tag from underlying type */
-# define ASN1_TFLG_EXPTAG (0x2 << 3)
-
-# define ASN1_TFLG_TAG_MASK (0x3 << 3)
-
-/* context specific IMPLICIT */
-# define ASN1_TFLG_IMPLICIT (ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT)
-
-/* context specific EXPLICIT */
-# define ASN1_TFLG_EXPLICIT (ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT)
-
-/*
- * If tagging is in force these determine the type of tag to use. Otherwise
- * the tag is determined by the underlying type. These values reflect the
- * actual octet format.
- */
-
-/* Universal tag */
-# define ASN1_TFLG_UNIVERSAL (0x0<<6)
-/* Application tag */
-# define ASN1_TFLG_APPLICATION (0x1<<6)
-/* Context specific tag */
-# define ASN1_TFLG_CONTEXT (0x2<<6)
-/* Private tag */
-# define ASN1_TFLG_PRIVATE (0x3<<6)
-
-# define ASN1_TFLG_TAG_CLASS (0x3<<6)
-
-/*
- * These are for ANY DEFINED BY type. In this case the 'item' field points to
- * an ASN1_ADB structure which contains a table of values to decode the
- * relevant type
- */
-
-# define ASN1_TFLG_ADB_MASK (0x3<<8)
-
-# define ASN1_TFLG_ADB_OID (0x1<<8)
-
-# define ASN1_TFLG_ADB_INT (0x1<<9)
-
-/*
- * This flag when present in a SEQUENCE OF, SET OF or EXPLICIT causes
- * indefinite length constructed encoding to be used if required.
- */
-
-# define ASN1_TFLG_NDEF (0x1<<11)
-
-/* Field is embedded and not a pointer */
-# define ASN1_TFLG_EMBED (0x1 << 12)
-
-/* This is the actual ASN1 item itself */
-
-struct ASN1_ITEM_st {
- char itype; /* The item type, primitive, SEQUENCE, CHOICE
- * or extern */
- long utype; /* underlying type */
- const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains
- * the contents */
- long tcount; /* Number of templates if SEQUENCE or CHOICE */
- const void *funcs; /* functions that handle this type */
- long size; /* Structure size (usually) */
- const char *sname; /* Structure name */
-};
-
-/*-
- * These are values for the itype field and
- * determine how the type is interpreted.
- *
- * For PRIMITIVE types the underlying type
- * determines the behaviour if items is NULL.
- *
- * Otherwise templates must contain a single
- * template and the type is treated in the
- * same way as the type specified in the template.
- *
- * For SEQUENCE types the templates field points
- * to the members, the size field is the
- * structure size.
- *
- * For CHOICE types the templates field points
- * to each possible member (typically a union)
- * and the 'size' field is the offset of the
- * selector.
- *
- * The 'funcs' field is used for application
- * specific functions.
- *
- * The EXTERN type uses a new style d2i/i2d.
- * The new style should be used where possible
- * because it avoids things like the d2i IMPLICIT
- * hack.
- *
- * MSTRING is a multiple string type, it is used
- * for a CHOICE of character strings where the
- * actual strings all occupy an ASN1_STRING
- * structure. In this case the 'utype' field
- * has a special meaning, it is used as a mask
- * of acceptable types using the B_ASN1 constants.
- *
- * NDEF_SEQUENCE is the same as SEQUENCE except
- * that it will use indefinite length constructed
- * encoding if requested.
- *
- */
-
-# define ASN1_ITYPE_PRIMITIVE 0x0
-
-# define ASN1_ITYPE_SEQUENCE 0x1
-
-# define ASN1_ITYPE_CHOICE 0x2
-
-# define ASN1_ITYPE_EXTERN 0x4
-
-# define ASN1_ITYPE_MSTRING 0x5
-
-# define ASN1_ITYPE_NDEF_SEQUENCE 0x6
-
-/*
- * Cache for ASN1 tag and length, so we don't keep re-reading it for things
- * like CHOICE
- */
-
-struct ASN1_TLC_st {
- char valid; /* Values below are valid */
- int ret; /* return value */
- long plen; /* length */
- int ptag; /* class value */
- int pclass; /* class value */
- int hdrlen; /* header length */
-};
-
-/* Typedefs for ASN1 function pointers */
-typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
- const ASN1_ITEM *it, int tag, int aclass, char opt,
- ASN1_TLC *ctx);
-
-typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
- const ASN1_ITEM *it, int tag, int aclass);
-typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
-typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
-
-typedef int ASN1_ex_print_func(BIO *out, ASN1_VALUE **pval,
- int indent, const char *fname,
- const ASN1_PCTX *pctx);
-
-typedef int ASN1_primitive_i2c(ASN1_VALUE **pval, unsigned char *cont,
- int *putype, const ASN1_ITEM *it);
-typedef int ASN1_primitive_c2i(ASN1_VALUE **pval, const unsigned char *cont,
- int len, int utype, char *free_cont,
- const ASN1_ITEM *it);
-typedef int ASN1_primitive_print(BIO *out, ASN1_VALUE **pval,
- const ASN1_ITEM *it, int indent,
- const ASN1_PCTX *pctx);
-
-typedef struct ASN1_EXTERN_FUNCS_st {
- void *app_data;
- ASN1_ex_new_func *asn1_ex_new;
- ASN1_ex_free_func *asn1_ex_free;
- ASN1_ex_free_func *asn1_ex_clear;
- ASN1_ex_d2i *asn1_ex_d2i;
- ASN1_ex_i2d *asn1_ex_i2d;
- ASN1_ex_print_func *asn1_ex_print;
-} ASN1_EXTERN_FUNCS;
-
-typedef struct ASN1_PRIMITIVE_FUNCS_st {
- void *app_data;
- unsigned long flags;
- ASN1_ex_new_func *prim_new;
- ASN1_ex_free_func *prim_free;
- ASN1_ex_free_func *prim_clear;
- ASN1_primitive_c2i *prim_c2i;
- ASN1_primitive_i2c *prim_i2c;
- ASN1_primitive_print *prim_print;
-} ASN1_PRIMITIVE_FUNCS;
-
-/*
- * This is the ASN1_AUX structure: it handles various miscellaneous
- * requirements. For example the use of reference counts and an informational
- * callback. The "informational callback" is called at various points during
- * the ASN1 encoding and decoding. It can be used to provide minor
- * customisation of the structures used. This is most useful where the
- * supplied routines *almost* do the right thing but need some extra help at
- * a few points. If the callback returns zero then it is assumed a fatal
- * error has occurred and the main operation should be abandoned. If major
- * changes in the default behaviour are required then an external type is
- * more appropriate.
- */
-
-typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it,
- void *exarg);
-
-typedef struct ASN1_AUX_st {
- void *app_data;
- int flags;
- int ref_offset; /* Offset of reference value */
- int ref_lock; /* Lock type to use */
- ASN1_aux_cb *asn1_cb;
- int enc_offset; /* Offset of ASN1_ENCODING structure */
-} ASN1_AUX;
-
-/* For print related callbacks exarg points to this structure */
-typedef struct ASN1_PRINT_ARG_st {
- BIO *out;
- int indent;
- const ASN1_PCTX *pctx;
-} ASN1_PRINT_ARG;
-
-/* For streaming related callbacks exarg points to this structure */
-typedef struct ASN1_STREAM_ARG_st {
- /* BIO to stream through */
- BIO *out;
- /* BIO with filters appended */
- BIO *ndef_bio;
- /* Streaming I/O boundary */
- unsigned char **boundary;
-} ASN1_STREAM_ARG;
-
-/* Flags in ASN1_AUX */
-
-/* Use a reference count */
-# define ASN1_AFLG_REFCOUNT 1
-/* Save the encoding of structure (useful for signatures) */
-# define ASN1_AFLG_ENCODING 2
-/* The Sequence length is invalid */
-# define ASN1_AFLG_BROKEN 4
-
-/* operation values for asn1_cb */
-
-# define ASN1_OP_NEW_PRE 0
-# define ASN1_OP_NEW_POST 1
-# define ASN1_OP_FREE_PRE 2
-# define ASN1_OP_FREE_POST 3
-# define ASN1_OP_D2I_PRE 4
-# define ASN1_OP_D2I_POST 5
-# define ASN1_OP_I2D_PRE 6
-# define ASN1_OP_I2D_POST 7
-# define ASN1_OP_PRINT_PRE 8
-# define ASN1_OP_PRINT_POST 9
-# define ASN1_OP_STREAM_PRE 10
-# define ASN1_OP_STREAM_POST 11
-# define ASN1_OP_DETACHED_PRE 12
-# define ASN1_OP_DETACHED_POST 13
-
-/* Macro to implement a primitive type */
-# define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0)
-# define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \
- ASN1_ITEM_start(itname) \
- ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \
- ASN1_ITEM_end(itname)
-
-/* Macro to implement a multi string type */
-# define IMPLEMENT_ASN1_MSTRING(itname, mask) \
- ASN1_ITEM_start(itname) \
- ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \
- ASN1_ITEM_end(itname)
-
-# define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \
- ASN1_ITEM_start(sname) \
- ASN1_ITYPE_EXTERN, \
- tag, \
- NULL, \
- 0, \
- &fptrs, \
- 0, \
- #sname \
- ASN1_ITEM_end(sname)
-
-/* Macro to implement standard functions in terms of ASN1_ITEM structures */
-
-# define IMPLEMENT_ASN1_FUNCTIONS(stname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, stname, stname)
-
-# define IMPLEMENT_ASN1_FUNCTIONS_name(stname, itname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, itname)
-
-# define IMPLEMENT_ASN1_FUNCTIONS_ENCODE_name(stname, itname) \
- IMPLEMENT_ASN1_FUNCTIONS_ENCODE_fname(stname, itname, itname)
-
-# define IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(stname) \
- IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(static, stname, stname, stname)
-
-# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS(stname) \
- IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, stname, stname)
-
-# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(pre, stname, itname, fname) \
- pre stname *fname##_new(void) \
- { \
- return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \
- } \
- pre void fname##_free(stname *a) \
- { \
- ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \
- }
-
-# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \
- stname *fname##_new(void) \
- { \
- return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \
- } \
- void fname##_free(stname *a) \
- { \
- ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \
- }
-
-# define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \
- IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \
- IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname)
-
-# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \
- stname *d2i_##fname(stname **a, const unsigned char **in, long len) \
- { \
- return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\
- } \
- int i2d_##fname(stname *a, unsigned char **out) \
- { \
- return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
- }
-
-# define IMPLEMENT_ASN1_NDEF_FUNCTION(stname) \
- int i2d_##stname##_NDEF(stname *a, unsigned char **out) \
- { \
- return ASN1_item_ndef_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(stname));\
- }
-
-# define IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(stname) \
- static stname *d2i_##stname(stname **a, \
- const unsigned char **in, long len) \
- { \
- return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, \
- ASN1_ITEM_rptr(stname)); \
- } \
- static int i2d_##stname(stname *a, unsigned char **out) \
- { \
- return ASN1_item_i2d((ASN1_VALUE *)a, out, \
- ASN1_ITEM_rptr(stname)); \
- }
-
-/*
- * This includes evil casts to remove const: they will go away when full ASN1
- * constification is done.
- */
-# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \
- stname *d2i_##fname(stname **a, const unsigned char **in, long len) \
- { \
- return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\
- } \
- int i2d_##fname(const stname *a, unsigned char **out) \
- { \
- return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
- }
-
-# define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \
- stname * stname##_dup(stname *x) \
- { \
- return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \
- }
-
-# define IMPLEMENT_ASN1_PRINT_FUNCTION(stname) \
- IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, stname, stname)
-
-# define IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, itname, fname) \
- int fname##_print_ctx(BIO *out, stname *x, int indent, \
- const ASN1_PCTX *pctx) \
- { \
- return ASN1_item_print(out, (ASN1_VALUE *)x, indent, \
- ASN1_ITEM_rptr(itname), pctx); \
- }
-
-# define IMPLEMENT_ASN1_FUNCTIONS_const(name) \
- IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name)
-
-# define IMPLEMENT_ASN1_FUNCTIONS_const_fname(stname, itname, fname) \
- IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \
- IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname)
-
-/* external definitions for primitive types */
-
-DECLARE_ASN1_ITEM(ASN1_BOOLEAN)
-DECLARE_ASN1_ITEM(ASN1_TBOOLEAN)
-DECLARE_ASN1_ITEM(ASN1_FBOOLEAN)
-DECLARE_ASN1_ITEM(ASN1_SEQUENCE)
-DECLARE_ASN1_ITEM(CBIGNUM)
-DECLARE_ASN1_ITEM(BIGNUM)
-DECLARE_ASN1_ITEM(INT32)
-DECLARE_ASN1_ITEM(ZINT32)
-DECLARE_ASN1_ITEM(UINT32)
-DECLARE_ASN1_ITEM(ZUINT32)
-DECLARE_ASN1_ITEM(INT64)
-DECLARE_ASN1_ITEM(ZINT64)
-DECLARE_ASN1_ITEM(UINT64)
-DECLARE_ASN1_ITEM(ZUINT64)
-
-# if OPENSSL_API_COMPAT < 0x10200000L
-/*
- * LONG and ZLONG are strongly discouraged for use as stored data, as the
- * underlying C type (long) differs in size depending on the architecture.
- * They are designed with 32-bit longs in mind.
- */
-DECLARE_ASN1_ITEM(LONG)
-DECLARE_ASN1_ITEM(ZLONG)
-# endif
-
-DEFINE_STACK_OF(ASN1_VALUE)
-
-/* Functions used internally by the ASN1 code */
-
-int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
-void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
-
-int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
- const ASN1_ITEM *it, int tag, int aclass, char opt,
- ASN1_TLC *ctx);
-
-int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
- const ASN1_ITEM *it, int tag, int aclass);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/include/openssl/asn1t.h.in b/include/openssl/asn1t.h.in
new file mode 100644
index 000000000000..b536fe51a20a
--- /dev/null
+++ b/include/openssl/asn1t.h.in
@@ -0,0 +1,923 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_ASN1T_H
+# define OPENSSL_ASN1T_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_ASN1T_H
+# endif
+
+# include <stddef.h>
+# include <openssl/e_os2.h>
+# include <openssl/asn1.h>
+
+# ifdef OPENSSL_BUILD_SHLIBCRYPTO
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+# endif
+
+/* ASN1 template defines, structures and functions */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-
+ * These are the possible values for the itype field of the
+ * ASN1_ITEM structure and determine how it is interpreted.
+ *
+ * For PRIMITIVE types the underlying type
+ * determines the behaviour if items is NULL.
+ *
+ * Otherwise templates must contain a single
+ * template and the type is treated in the
+ * same way as the type specified in the template.
+ *
+ * For SEQUENCE types the templates field points
+ * to the members, the size field is the
+ * structure size.
+ *
+ * For CHOICE types the templates field points
+ * to each possible member (typically a union)
+ * and the 'size' field is the offset of the
+ * selector.
+ *
+ * The 'funcs' field is used for application-specific
+ * data and functions.
+ *
+ * The EXTERN type uses a new style d2i/i2d.
+ * The new style should be used where possible
+ * because it avoids things like the d2i IMPLICIT
+ * hack.
+ *
+ * MSTRING is a multiple string type, it is used
+ * for a CHOICE of character strings where the
+ * actual strings all occupy an ASN1_STRING
+ * structure. In this case the 'utype' field
+ * has a special meaning, it is used as a mask
+ * of acceptable types using the B_ASN1 constants.
+ *
+ * NDEF_SEQUENCE is the same as SEQUENCE except
+ * that it will use indefinite length constructed
+ * encoding if requested.
+ *
+ */
+
+# define ASN1_ITYPE_PRIMITIVE 0x0
+# define ASN1_ITYPE_SEQUENCE 0x1
+# define ASN1_ITYPE_CHOICE 0x2
+/* unused value 0x3 */
+# define ASN1_ITYPE_EXTERN 0x4
+# define ASN1_ITYPE_MSTRING 0x5
+# define ASN1_ITYPE_NDEF_SEQUENCE 0x6
+
+/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */
+# define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)((iptr)()))
+
+/* Macros for start and end of ASN1_ITEM definition */
+
+# define ASN1_ITEM_start(itname) \
+ const ASN1_ITEM * itname##_it(void) \
+ { \
+ static const ASN1_ITEM local_it = {
+
+# define static_ASN1_ITEM_start(itname) \
+ static ASN1_ITEM_start(itname)
+
+# define ASN1_ITEM_end(itname) \
+ }; \
+ return &local_it; \
+ }
+
+/* Macros to aid ASN1 template writing */
+
+# define ASN1_ITEM_TEMPLATE(tname) \
+ static const ASN1_TEMPLATE tname##_item_tt
+
+# define ASN1_ITEM_TEMPLATE_END(tname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_PRIMITIVE,\
+ -1,\
+ &tname##_item_tt,\
+ 0,\
+ NULL,\
+ 0,\
+ #tname \
+ ASN1_ITEM_end(tname)
+# define static_ASN1_ITEM_TEMPLATE_END(tname) \
+ ;\
+ static_ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_PRIMITIVE,\
+ -1,\
+ &tname##_item_tt,\
+ 0,\
+ NULL,\
+ 0,\
+ #tname \
+ ASN1_ITEM_end(tname)
+
+/* This is a ASN1 type which just embeds a template */
+
+/*-
+ * This pair helps declare a SEQUENCE. We can do:
+ *
+ * ASN1_SEQUENCE(stname) = {
+ * ... SEQUENCE components ...
+ * } ASN1_SEQUENCE_END(stname)
+ *
+ * This will produce an ASN1_ITEM called stname_it
+ * for a structure called stname.
+ *
+ * If you want the same structure but a different
+ * name then use:
+ *
+ * ASN1_SEQUENCE(itname) = {
+ * ... SEQUENCE components ...
+ * } ASN1_SEQUENCE_END_name(stname, itname)
+ *
+ * This will create an item called itname_it using
+ * a structure called stname.
+ */
+
+# define ASN1_SEQUENCE(tname) \
+ static const ASN1_TEMPLATE tname##_seq_tt[]
+
+# define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname)
+
+# define static_ASN1_SEQUENCE_END(stname) static_ASN1_SEQUENCE_END_name(stname, stname)
+
+# define ASN1_SEQUENCE_END_name(stname, tname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_SEQUENCE,\
+ V_ASN1_SEQUENCE,\
+ tname##_seq_tt,\
+ sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+ NULL,\
+ sizeof(stname),\
+ #tname \
+ ASN1_ITEM_end(tname)
+
+# define static_ASN1_SEQUENCE_END_name(stname, tname) \
+ ;\
+ static_ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_SEQUENCE,\
+ V_ASN1_SEQUENCE,\
+ tname##_seq_tt,\
+ sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+ NULL,\
+ sizeof(stname),\
+ #stname \
+ ASN1_ITEM_end(tname)
+
+# define ASN1_NDEF_SEQUENCE(tname) \
+ ASN1_SEQUENCE(tname)
+
+# define ASN1_NDEF_SEQUENCE_cb(tname, cb) \
+ ASN1_SEQUENCE_cb(tname, cb)
+
+# define ASN1_SEQUENCE_cb(tname, cb) \
+ static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0, NULL}; \
+ ASN1_SEQUENCE(tname)
+
+# define ASN1_SEQUENCE_const_cb(tname, const_cb) \
+ static const ASN1_AUX tname##_aux = \
+ {NULL, ASN1_AFLG_CONST_CB, 0, 0, NULL, 0, const_cb}; \
+ ASN1_SEQUENCE(tname)
+
+# define ASN1_SEQUENCE_cb_const_cb(tname, cb, const_cb) \
+ static const ASN1_AUX tname##_aux = \
+ {NULL, ASN1_AFLG_CONST_CB, 0, 0, cb, 0, const_cb}; \
+ ASN1_SEQUENCE(tname)
+
+# define ASN1_SEQUENCE_ref(tname, cb) \
+ static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), offsetof(tname, lock), cb, 0, NULL}; \
+ ASN1_SEQUENCE(tname)
+
+# define ASN1_SEQUENCE_enc(tname, enc, cb) \
+ static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_ENCODING, 0, 0, cb, offsetof(tname, enc), NULL}; \
+ ASN1_SEQUENCE(tname)
+
+# define ASN1_NDEF_SEQUENCE_END(tname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_NDEF_SEQUENCE,\
+ V_ASN1_SEQUENCE,\
+ tname##_seq_tt,\
+ sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+ NULL,\
+ sizeof(tname),\
+ #tname \
+ ASN1_ITEM_end(tname)
+# define static_ASN1_NDEF_SEQUENCE_END(tname) \
+ ;\
+ static_ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_NDEF_SEQUENCE,\
+ V_ASN1_SEQUENCE,\
+ tname##_seq_tt,\
+ sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+ NULL,\
+ sizeof(tname),\
+ #tname \
+ ASN1_ITEM_end(tname)
+
+
+# define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
+
+# define ASN1_SEQUENCE_END_cb(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
+# define static_ASN1_SEQUENCE_END_cb(stname, tname) static_ASN1_SEQUENCE_END_ref(stname, tname)
+
+# define ASN1_SEQUENCE_END_ref(stname, tname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_SEQUENCE,\
+ V_ASN1_SEQUENCE,\
+ tname##_seq_tt,\
+ sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+ &tname##_aux,\
+ sizeof(stname),\
+ #tname \
+ ASN1_ITEM_end(tname)
+# define static_ASN1_SEQUENCE_END_ref(stname, tname) \
+ ;\
+ static_ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_SEQUENCE,\
+ V_ASN1_SEQUENCE,\
+ tname##_seq_tt,\
+ sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+ &tname##_aux,\
+ sizeof(stname),\
+ #stname \
+ ASN1_ITEM_end(tname)
+
+# define ASN1_NDEF_SEQUENCE_END_cb(stname, tname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_NDEF_SEQUENCE,\
+ V_ASN1_SEQUENCE,\
+ tname##_seq_tt,\
+ sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+ &tname##_aux,\
+ sizeof(stname),\
+ #stname \
+ ASN1_ITEM_end(tname)
+
+/*-
+ * This pair helps declare a CHOICE type. We can do:
+ *
+ * ASN1_CHOICE(chname) = {
+ * ... CHOICE options ...
+ * ASN1_CHOICE_END(chname)
+ *
+ * This will produce an ASN1_ITEM called chname_it
+ * for a structure called chname. The structure
+ * definition must look like this:
+ * typedef struct {
+ * int type;
+ * union {
+ * ASN1_SOMETHING *opt1;
+ * ASN1_SOMEOTHER *opt2;
+ * } value;
+ * } chname;
+ *
+ * the name of the selector must be 'type'.
+ * to use an alternative selector name use the
+ * ASN1_CHOICE_END_selector() version.
+ */
+
+# define ASN1_CHOICE(tname) \
+ static const ASN1_TEMPLATE tname##_ch_tt[]
+
+# define ASN1_CHOICE_cb(tname, cb) \
+ static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0, NULL}; \
+ ASN1_CHOICE(tname)
+
+# define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname)
+
+# define static_ASN1_CHOICE_END(stname) static_ASN1_CHOICE_END_name(stname, stname)
+
+# define ASN1_CHOICE_END_name(stname, tname) ASN1_CHOICE_END_selector(stname, tname, type)
+
+# define static_ASN1_CHOICE_END_name(stname, tname) static_ASN1_CHOICE_END_selector(stname, tname, type)
+
+# define ASN1_CHOICE_END_selector(stname, tname, selname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_CHOICE,\
+ offsetof(stname,selname) ,\
+ tname##_ch_tt,\
+ sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\
+ NULL,\
+ sizeof(stname),\
+ #stname \
+ ASN1_ITEM_end(tname)
+
+# define static_ASN1_CHOICE_END_selector(stname, tname, selname) \
+ ;\
+ static_ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_CHOICE,\
+ offsetof(stname,selname) ,\
+ tname##_ch_tt,\
+ sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\
+ NULL,\
+ sizeof(stname),\
+ #stname \
+ ASN1_ITEM_end(tname)
+
+# define ASN1_CHOICE_END_cb(stname, tname, selname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_CHOICE,\
+ offsetof(stname,selname) ,\
+ tname##_ch_tt,\
+ sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\
+ &tname##_aux,\
+ sizeof(stname),\
+ #stname \
+ ASN1_ITEM_end(tname)
+
+/* This helps with the template wrapper form of ASN1_ITEM */
+
+# define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \
+ (flags), (tag), 0,\
+ #name, ASN1_ITEM_ref(type) }
+
+/* These help with SEQUENCE or CHOICE components */
+
+/* used to declare other types */
+
+# define ASN1_EX_TYPE(flags, tag, stname, field, type) { \
+ (flags), (tag), offsetof(stname, field),\
+ #field, ASN1_ITEM_ref(type) }
+
+/* implicit and explicit helper macros */
+
+# define ASN1_IMP_EX(stname, field, type, tag, ex) \
+ ASN1_EX_TYPE(ASN1_TFLG_IMPLICIT | (ex), tag, stname, field, type)
+
+# define ASN1_EXP_EX(stname, field, type, tag, ex) \
+ ASN1_EX_TYPE(ASN1_TFLG_EXPLICIT | (ex), tag, stname, field, type)
+
+/* Any defined by macros: the field used is in the table itself */
+
+# define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, tblname##_adb }
+# define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, tblname##_adb }
+
+/* Plain simple type */
+# define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type)
+/* Embedded simple type */
+# define ASN1_EMBED(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_EMBED,0, stname, field, type)
+
+/* OPTIONAL simple type */
+# define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type)
+# define ASN1_OPT_EMBED(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL|ASN1_TFLG_EMBED, 0, stname, field, type)
+
+/* IMPLICIT tagged simple type */
+# define ASN1_IMP(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, 0)
+# define ASN1_IMP_EMBED(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_EMBED)
+
+/* IMPLICIT tagged OPTIONAL simple type */
+# define ASN1_IMP_OPT(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL)
+# define ASN1_IMP_OPT_EMBED(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_EMBED)
+
+/* Same as above but EXPLICIT */
+
+# define ASN1_EXP(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, 0)
+# define ASN1_EXP_EMBED(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_EMBED)
+# define ASN1_EXP_OPT(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL)
+# define ASN1_EXP_OPT_EMBED(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_EMBED)
+
+/* SEQUENCE OF type */
+# define ASN1_SEQUENCE_OF(stname, field, type) \
+ ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, stname, field, type)
+
+/* OPTIONAL SEQUENCE OF */
+# define ASN1_SEQUENCE_OF_OPT(stname, field, type) \
+ ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type)
+
+/* Same as above but for SET OF */
+
+# define ASN1_SET_OF(stname, field, type) \
+ ASN1_EX_TYPE(ASN1_TFLG_SET_OF, 0, stname, field, type)
+
+# define ASN1_SET_OF_OPT(stname, field, type) \
+ ASN1_EX_TYPE(ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type)
+
+/* Finally compound types of SEQUENCE, SET, IMPLICIT, EXPLICIT and OPTIONAL */
+
+# define ASN1_IMP_SET_OF(stname, field, type, tag) \
+ ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF)
+
+# define ASN1_EXP_SET_OF(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF)
+
+# define ASN1_IMP_SET_OF_OPT(stname, field, type, tag) \
+ ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL)
+
+# define ASN1_EXP_SET_OF_OPT(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL)
+
+# define ASN1_IMP_SEQUENCE_OF(stname, field, type, tag) \
+ ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF)
+
+# define ASN1_IMP_SEQUENCE_OF_OPT(stname, field, type, tag) \
+ ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL)
+
+# define ASN1_EXP_SEQUENCE_OF(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF)
+
+# define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL)
+
+/* EXPLICIT using indefinite length constructed form */
+# define ASN1_NDEF_EXP(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_NDEF)
+
+/* EXPLICIT OPTIONAL using indefinite length constructed form */
+# define ASN1_NDEF_EXP_OPT(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_NDEF)
+
+/* Macros for the ASN1_ADB structure */
+
+# define ASN1_ADB(name) \
+ static const ASN1_ADB_TABLE name##_adbtbl[]
+
+# define ASN1_ADB_END(name, flags, field, adb_cb, def, none) \
+ ;\
+ static const ASN1_ITEM *name##_adb(void) \
+ { \
+ static const ASN1_ADB internal_adb = \
+ {\
+ flags,\
+ offsetof(name, field),\
+ adb_cb,\
+ name##_adbtbl,\
+ sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\
+ def,\
+ none\
+ }; \
+ return (const ASN1_ITEM *) &internal_adb; \
+ } \
+ void dummy_function(void)
+
+# define ADB_ENTRY(val, template) {val, template}
+
+# define ASN1_ADB_TEMPLATE(name) \
+ static const ASN1_TEMPLATE name##_tt
+
+/*
+ * This is the ASN1 template structure that defines a wrapper round the
+ * actual type. It determines the actual position of the field in the value
+ * structure, various flags such as OPTIONAL and the field name.
+ */
+
+struct ASN1_TEMPLATE_st {
+ unsigned long flags; /* Various flags */
+ long tag; /* tag, not used if no tagging */
+ unsigned long offset; /* Offset of this field in structure */
+ const char *field_name; /* Field name */
+ ASN1_ITEM_EXP *item; /* Relevant ASN1_ITEM or ASN1_ADB */
+};
+
+/* Macro to extract ASN1_ITEM and ASN1_ADB pointer from ASN1_TEMPLATE */
+
+# define ASN1_TEMPLATE_item(t) (t->item_ptr)
+# define ASN1_TEMPLATE_adb(t) (t->item_ptr)
+
+typedef struct ASN1_ADB_TABLE_st ASN1_ADB_TABLE;
+typedef struct ASN1_ADB_st ASN1_ADB;
+
+struct ASN1_ADB_st {
+ unsigned long flags; /* Various flags */
+ unsigned long offset; /* Offset of selector field */
+ int (*adb_cb)(long *psel); /* Application callback */
+ const ASN1_ADB_TABLE *tbl; /* Table of possible types */
+ long tblcount; /* Number of entries in tbl */
+ const ASN1_TEMPLATE *default_tt; /* Type to use if no match */
+ const ASN1_TEMPLATE *null_tt; /* Type to use if selector is NULL */
+};
+
+struct ASN1_ADB_TABLE_st {
+ long value; /* NID for an object or value for an int */
+ const ASN1_TEMPLATE tt; /* item for this value */
+};
+
+/* template flags */
+
+/* Field is optional */
+# define ASN1_TFLG_OPTIONAL (0x1)
+
+/* Field is a SET OF */
+# define ASN1_TFLG_SET_OF (0x1 << 1)
+
+/* Field is a SEQUENCE OF */
+# define ASN1_TFLG_SEQUENCE_OF (0x2 << 1)
+
+/*
+ * Special case: this refers to a SET OF that will be sorted into DER order
+ * when encoded *and* the corresponding STACK will be modified to match the
+ * new order.
+ */
+# define ASN1_TFLG_SET_ORDER (0x3 << 1)
+
+/* Mask for SET OF or SEQUENCE OF */
+# define ASN1_TFLG_SK_MASK (0x3 << 1)
+
+/*
+ * These flags mean the tag should be taken from the tag field. If EXPLICIT
+ * then the underlying type is used for the inner tag.
+ */
+
+/* IMPLICIT tagging */
+# define ASN1_TFLG_IMPTAG (0x1 << 3)
+
+/* EXPLICIT tagging, inner tag from underlying type */
+# define ASN1_TFLG_EXPTAG (0x2 << 3)
+
+# define ASN1_TFLG_TAG_MASK (0x3 << 3)
+
+/* context specific IMPLICIT */
+# define ASN1_TFLG_IMPLICIT (ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT)
+
+/* context specific EXPLICIT */
+# define ASN1_TFLG_EXPLICIT (ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT)
+
+/*
+ * If tagging is in force these determine the type of tag to use. Otherwise
+ * the tag is determined by the underlying type. These values reflect the
+ * actual octet format.
+ */
+
+/* Universal tag */
+# define ASN1_TFLG_UNIVERSAL (0x0<<6)
+/* Application tag */
+# define ASN1_TFLG_APPLICATION (0x1<<6)
+/* Context specific tag */
+# define ASN1_TFLG_CONTEXT (0x2<<6)
+/* Private tag */
+# define ASN1_TFLG_PRIVATE (0x3<<6)
+
+# define ASN1_TFLG_TAG_CLASS (0x3<<6)
+
+/*
+ * These are for ANY DEFINED BY type. In this case the 'item' field points to
+ * an ASN1_ADB structure which contains a table of values to decode the
+ * relevant type
+ */
+
+# define ASN1_TFLG_ADB_MASK (0x3<<8)
+
+# define ASN1_TFLG_ADB_OID (0x1<<8)
+
+# define ASN1_TFLG_ADB_INT (0x1<<9)
+
+/*
+ * This flag when present in a SEQUENCE OF, SET OF or EXPLICIT causes
+ * indefinite length constructed encoding to be used if required.
+ */
+
+# define ASN1_TFLG_NDEF (0x1<<11)
+
+/* Field is embedded and not a pointer */
+# define ASN1_TFLG_EMBED (0x1 << 12)
+
+/* This is the actual ASN1 item itself */
+
+struct ASN1_ITEM_st {
+ char itype; /* The item type, primitive, SEQUENCE, CHOICE
+ * or extern */
+ long utype; /* underlying type */
+ const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains
+ * the contents */
+ long tcount; /* Number of templates if SEQUENCE or CHOICE */
+ const void *funcs; /* further data and type-specific functions */
+ /* funcs can be ASN1_PRIMITIVE_FUNCS*, ASN1_EXTERN_FUNCS*, or ASN1_AUX* */
+ long size; /* Structure size (usually) */
+ const char *sname; /* Structure name */
+};
+
+/*
+ * Cache for ASN1 tag and length, so we don't keep re-reading it for things
+ * like CHOICE
+ */
+
+struct ASN1_TLC_st {
+ char valid; /* Values below are valid */
+ int ret; /* return value */
+ long plen; /* length */
+ int ptag; /* class value */
+ int pclass; /* class value */
+ int hdrlen; /* header length */
+};
+
+/* Typedefs for ASN1 function pointers */
+typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
+ const ASN1_ITEM *it, int tag, int aclass, char opt,
+ ASN1_TLC *ctx);
+
+typedef int ASN1_ex_d2i_ex(ASN1_VALUE **pval, const unsigned char **in, long len,
+ const ASN1_ITEM *it, int tag, int aclass, char opt,
+ ASN1_TLC *ctx, OSSL_LIB_CTX *libctx,
+ const char *propq);
+typedef int ASN1_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
+ const ASN1_ITEM *it, int tag, int aclass);
+typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
+typedef int ASN1_ex_new_ex_func(ASN1_VALUE **pval, const ASN1_ITEM *it,
+ OSSL_LIB_CTX *libctx, const char *propq);
+typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+typedef int ASN1_ex_print_func(BIO *out, const ASN1_VALUE **pval,
+ int indent, const char *fname,
+ const ASN1_PCTX *pctx);
+
+typedef int ASN1_primitive_i2c(const ASN1_VALUE **pval, unsigned char *cont,
+ int *putype, const ASN1_ITEM *it);
+typedef int ASN1_primitive_c2i(ASN1_VALUE **pval, const unsigned char *cont,
+ int len, int utype, char *free_cont,
+ const ASN1_ITEM *it);
+typedef int ASN1_primitive_print(BIO *out, const ASN1_VALUE **pval,
+ const ASN1_ITEM *it, int indent,
+ const ASN1_PCTX *pctx);
+
+typedef struct ASN1_EXTERN_FUNCS_st {
+ void *app_data;
+ ASN1_ex_new_func *asn1_ex_new;
+ ASN1_ex_free_func *asn1_ex_free;
+ ASN1_ex_free_func *asn1_ex_clear;
+ ASN1_ex_d2i *asn1_ex_d2i;
+ ASN1_ex_i2d *asn1_ex_i2d;
+ ASN1_ex_print_func *asn1_ex_print;
+ ASN1_ex_new_ex_func *asn1_ex_new_ex;
+ ASN1_ex_d2i_ex *asn1_ex_d2i_ex;
+} ASN1_EXTERN_FUNCS;
+
+typedef struct ASN1_PRIMITIVE_FUNCS_st {
+ void *app_data;
+ unsigned long flags;
+ ASN1_ex_new_func *prim_new;
+ ASN1_ex_free_func *prim_free;
+ ASN1_ex_free_func *prim_clear;
+ ASN1_primitive_c2i *prim_c2i;
+ ASN1_primitive_i2c *prim_i2c;
+ ASN1_primitive_print *prim_print;
+} ASN1_PRIMITIVE_FUNCS;
+
+/*
+ * This is the ASN1_AUX structure: it handles various miscellaneous
+ * requirements. For example the use of reference counts and an informational
+ * callback. The "informational callback" is called at various points during
+ * the ASN1 encoding and decoding. It can be used to provide minor
+ * customisation of the structures used. This is most useful where the
+ * supplied routines *almost* do the right thing but need some extra help at
+ * a few points. If the callback returns zero then it is assumed a fatal
+ * error has occurred and the main operation should be abandoned. If major
+ * changes in the default behaviour are required then an external type is
+ * more appropriate.
+ * For the operations ASN1_OP_I2D_PRE, ASN1_OP_I2D_POST, ASN1_OP_PRINT_PRE, and
+ * ASN1_OP_PRINT_POST, meanwhile a variant of the callback with const parameter
+ * 'in' is provided to make clear statically that its input is not modified. If
+ * and only if this variant is in use the flag ASN1_AFLG_CONST_CB must be set.
+ */
+
+typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it,
+ void *exarg);
+typedef int ASN1_aux_const_cb(int operation, const ASN1_VALUE **in,
+ const ASN1_ITEM *it, void *exarg);
+
+typedef struct ASN1_AUX_st {
+ void *app_data;
+ int flags;
+ int ref_offset; /* Offset of reference value */
+ int ref_lock; /* Offset of lock value */
+ ASN1_aux_cb *asn1_cb;
+ int enc_offset; /* Offset of ASN1_ENCODING structure */
+ ASN1_aux_const_cb *asn1_const_cb; /* for ASN1_OP_I2D_ and ASN1_OP_PRINT_ */
+} ASN1_AUX;
+
+/* For print related callbacks exarg points to this structure */
+typedef struct ASN1_PRINT_ARG_st {
+ BIO *out;
+ int indent;
+ const ASN1_PCTX *pctx;
+} ASN1_PRINT_ARG;
+
+/* For streaming related callbacks exarg points to this structure */
+typedef struct ASN1_STREAM_ARG_st {
+ /* BIO to stream through */
+ BIO *out;
+ /* BIO with filters appended */
+ BIO *ndef_bio;
+ /* Streaming I/O boundary */
+ unsigned char **boundary;
+} ASN1_STREAM_ARG;
+
+/* Flags in ASN1_AUX */
+
+/* Use a reference count */
+# define ASN1_AFLG_REFCOUNT 1
+/* Save the encoding of structure (useful for signatures) */
+# define ASN1_AFLG_ENCODING 2
+/* The Sequence length is invalid */
+# define ASN1_AFLG_BROKEN 4
+/* Use the new asn1_const_cb */
+# define ASN1_AFLG_CONST_CB 8
+
+/* operation values for asn1_cb */
+
+# define ASN1_OP_NEW_PRE 0
+# define ASN1_OP_NEW_POST 1
+# define ASN1_OP_FREE_PRE 2
+# define ASN1_OP_FREE_POST 3
+# define ASN1_OP_D2I_PRE 4
+# define ASN1_OP_D2I_POST 5
+# define ASN1_OP_I2D_PRE 6
+# define ASN1_OP_I2D_POST 7
+# define ASN1_OP_PRINT_PRE 8
+# define ASN1_OP_PRINT_POST 9
+# define ASN1_OP_STREAM_PRE 10
+# define ASN1_OP_STREAM_POST 11
+# define ASN1_OP_DETACHED_PRE 12
+# define ASN1_OP_DETACHED_POST 13
+# define ASN1_OP_DUP_PRE 14
+# define ASN1_OP_DUP_POST 15
+# define ASN1_OP_GET0_LIBCTX 16
+# define ASN1_OP_GET0_PROPQ 17
+
+/* Macro to implement a primitive type */
+# define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0)
+# define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \
+ ASN1_ITEM_start(itname) \
+ ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \
+ ASN1_ITEM_end(itname)
+
+/* Macro to implement a multi string type */
+# define IMPLEMENT_ASN1_MSTRING(itname, mask) \
+ ASN1_ITEM_start(itname) \
+ ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \
+ ASN1_ITEM_end(itname)
+
+# define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \
+ ASN1_ITEM_start(sname) \
+ ASN1_ITYPE_EXTERN, \
+ tag, \
+ NULL, \
+ 0, \
+ &fptrs, \
+ 0, \
+ #sname \
+ ASN1_ITEM_end(sname)
+
+/* Macro to implement standard functions in terms of ASN1_ITEM structures */
+
+# define IMPLEMENT_ASN1_FUNCTIONS(stname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, stname, stname)
+
+# define IMPLEMENT_ASN1_FUNCTIONS_name(stname, itname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, itname)
+
+# define IMPLEMENT_ASN1_FUNCTIONS_ENCODE_name(stname, itname) \
+ IMPLEMENT_ASN1_FUNCTIONS_ENCODE_fname(stname, itname, itname)
+
+# define IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(stname) \
+ IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(static, stname, stname, stname)
+
+# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS(stname) \
+ IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, stname, stname)
+
+# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(pre, stname, itname, fname) \
+ pre stname *fname##_new(void) \
+ { \
+ return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \
+ } \
+ pre void fname##_free(stname *a) \
+ { \
+ ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \
+ }
+
+# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \
+ stname *fname##_new(void) \
+ { \
+ return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \
+ } \
+ void fname##_free(stname *a) \
+ { \
+ ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \
+ }
+
+# define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \
+ IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \
+ IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname)
+
+# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \
+ stname *d2i_##fname(stname **a, const unsigned char **in, long len) \
+ { \
+ return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\
+ } \
+ int i2d_##fname(const stname *a, unsigned char **out) \
+ { \
+ return ASN1_item_i2d((const ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
+ }
+
+# define IMPLEMENT_ASN1_NDEF_FUNCTION(stname) \
+ int i2d_##stname##_NDEF(const stname *a, unsigned char **out) \
+ { \
+ return ASN1_item_ndef_i2d((const ASN1_VALUE *)a, out, ASN1_ITEM_rptr(stname));\
+ }
+
+# define IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(stname) \
+ static stname *d2i_##stname(stname **a, \
+ const unsigned char **in, long len) \
+ { \
+ return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, \
+ ASN1_ITEM_rptr(stname)); \
+ } \
+ static int i2d_##stname(const stname *a, unsigned char **out) \
+ { \
+ return ASN1_item_i2d((const ASN1_VALUE *)a, out, \
+ ASN1_ITEM_rptr(stname)); \
+ }
+
+# define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \
+ stname * stname##_dup(const stname *x) \
+ { \
+ return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \
+ }
+
+# define IMPLEMENT_ASN1_PRINT_FUNCTION(stname) \
+ IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, stname, stname)
+
+# define IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, itname, fname) \
+ int fname##_print_ctx(BIO *out, const stname *x, int indent, \
+ const ASN1_PCTX *pctx) \
+ { \
+ return ASN1_item_print(out, (const ASN1_VALUE *)x, indent, \
+ ASN1_ITEM_rptr(itname), pctx); \
+ }
+
+/* external definitions for primitive types */
+
+DECLARE_ASN1_ITEM(ASN1_BOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_TBOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_FBOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_SEQUENCE)
+DECLARE_ASN1_ITEM(CBIGNUM)
+DECLARE_ASN1_ITEM(BIGNUM)
+DECLARE_ASN1_ITEM(INT32)
+DECLARE_ASN1_ITEM(ZINT32)
+DECLARE_ASN1_ITEM(UINT32)
+DECLARE_ASN1_ITEM(ZUINT32)
+DECLARE_ASN1_ITEM(INT64)
+DECLARE_ASN1_ITEM(ZINT64)
+DECLARE_ASN1_ITEM(UINT64)
+DECLARE_ASN1_ITEM(ZUINT64)
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+/*
+ * LONG and ZLONG are strongly discouraged for use as stored data, as the
+ * underlying C type (long) differs in size depending on the architecture.
+ * They are designed with 32-bit longs in mind.
+ */
+DECLARE_ASN1_ITEM(LONG)
+DECLARE_ASN1_ITEM(ZLONG)
+# endif
+
+{-
+ generate_stack_macros("ASN1_VALUE");
+-}
+
+
+/* Functions used internally by the ASN1 code */
+
+int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
+void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
+ const ASN1_ITEM *it, int tag, int aclass, char opt,
+ ASN1_TLC *ctx);
+
+int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
+ const ASN1_ITEM *it, int tag, int aclass);
+
+/* Legacy compatibility */
+# define IMPLEMENT_ASN1_FUNCTIONS_const(name) IMPLEMENT_ASN1_FUNCTIONS(name)
+# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \
+ IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname)
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/openssl/async.h b/include/openssl/async.h
index 7052b89052af..bc27d5db06a7 100644
--- a/include/openssl/async.h
+++ b/include/openssl/async.h
@@ -1,7 +1,7 @@
/*
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,8 +9,14 @@
#include <stdlib.h>
-#ifndef HEADER_ASYNC_H
-# define HEADER_ASYNC_H
+#ifndef OPENSSL_ASYNC_H
+# define OPENSSL_ASYNC_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_ASYNC_H
+# endif
#if defined(_WIN32)
# if defined(BASETYPES) || defined(_WINDEF_H)
@@ -31,12 +37,18 @@ extern "C" {
typedef struct async_job_st ASYNC_JOB;
typedef struct async_wait_ctx_st ASYNC_WAIT_CTX;
+typedef int (*ASYNC_callback_fn)(void *arg);
#define ASYNC_ERR 0
#define ASYNC_NO_JOBS 1
#define ASYNC_PAUSE 2
#define ASYNC_FINISH 3
+#define ASYNC_STATUS_UNSUPPORTED 0
+#define ASYNC_STATUS_ERR 1
+#define ASYNC_STATUS_OK 2
+#define ASYNC_STATUS_EAGAIN 3
+
int ASYNC_init_thread(size_t max_size, size_t init_size);
void ASYNC_cleanup_thread(void);
@@ -52,6 +64,14 @@ int ASYNC_WAIT_CTX_get_fd(ASYNC_WAIT_CTX *ctx, const void *key,
OSSL_ASYNC_FD *fd, void **custom_data);
int ASYNC_WAIT_CTX_get_all_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *fd,
size_t *numfds);
+int ASYNC_WAIT_CTX_get_callback(ASYNC_WAIT_CTX *ctx,
+ ASYNC_callback_fn *callback,
+ void **callback_arg);
+int ASYNC_WAIT_CTX_set_callback(ASYNC_WAIT_CTX *ctx,
+ ASYNC_callback_fn callback,
+ void *callback_arg);
+int ASYNC_WAIT_CTX_set_status(ASYNC_WAIT_CTX *ctx, int status);
+int ASYNC_WAIT_CTX_get_status(ASYNC_WAIT_CTX *ctx);
int ASYNC_WAIT_CTX_get_changed_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *addfd,
size_t *numaddfds, OSSL_ASYNC_FD *delfd,
size_t *numdelfds);
diff --git a/include/openssl/asyncerr.h b/include/openssl/asyncerr.h
index 91afbbb2f5b8..c093f7be4547 100644
--- a/include/openssl/asyncerr.h
+++ b/include/openssl/asyncerr.h
@@ -1,35 +1,22 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_ASYNCERR_H
-# define HEADER_ASYNCERR_H
+#ifndef OPENSSL_ASYNCERR_H
+# define OPENSSL_ASYNCERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_ASYNC_strings(void);
-/*
- * ASYNC function codes.
- */
-# define ASYNC_F_ASYNC_CTX_NEW 100
-# define ASYNC_F_ASYNC_INIT_THREAD 101
-# define ASYNC_F_ASYNC_JOB_NEW 102
-# define ASYNC_F_ASYNC_PAUSE_JOB 103
-# define ASYNC_F_ASYNC_START_FUNC 104
-# define ASYNC_F_ASYNC_START_JOB 105
-# define ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD 106
/*
* ASYNC reason codes.
diff --git a/include/openssl/bio.h b/include/openssl/bio.h
deleted file mode 100644
index ae559a510507..000000000000
--- a/include/openssl/bio.h
+++ /dev/null
@@ -1,801 +0,0 @@
-/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_BIO_H
-# define HEADER_BIO_H
-
-# include <openssl/e_os2.h>
-
-# ifndef OPENSSL_NO_STDIO
-# include <stdio.h>
-# endif
-# include <stdarg.h>
-
-# include <openssl/crypto.h>
-# include <openssl/bioerr.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* There are the classes of BIOs */
-# define BIO_TYPE_DESCRIPTOR 0x0100 /* socket, fd, connect or accept */
-# define BIO_TYPE_FILTER 0x0200
-# define BIO_TYPE_SOURCE_SINK 0x0400
-
-/* These are the 'types' of BIOs */
-# define BIO_TYPE_NONE 0
-# define BIO_TYPE_MEM ( 1|BIO_TYPE_SOURCE_SINK)
-# define BIO_TYPE_FILE ( 2|BIO_TYPE_SOURCE_SINK)
-
-# define BIO_TYPE_FD ( 4|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR)
-# define BIO_TYPE_SOCKET ( 5|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR)
-# define BIO_TYPE_NULL ( 6|BIO_TYPE_SOURCE_SINK)
-# define BIO_TYPE_SSL ( 7|BIO_TYPE_FILTER)
-# define BIO_TYPE_MD ( 8|BIO_TYPE_FILTER)
-# define BIO_TYPE_BUFFER ( 9|BIO_TYPE_FILTER)
-# define BIO_TYPE_CIPHER (10|BIO_TYPE_FILTER)
-# define BIO_TYPE_BASE64 (11|BIO_TYPE_FILTER)
-# define BIO_TYPE_CONNECT (12|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR)
-# define BIO_TYPE_ACCEPT (13|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR)
-
-# define BIO_TYPE_NBIO_TEST (16|BIO_TYPE_FILTER)/* server proxy BIO */
-# define BIO_TYPE_NULL_FILTER (17|BIO_TYPE_FILTER)
-# define BIO_TYPE_BIO (19|BIO_TYPE_SOURCE_SINK)/* half a BIO pair */
-# define BIO_TYPE_LINEBUFFER (20|BIO_TYPE_FILTER)
-# define BIO_TYPE_DGRAM (21|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR)
-# define BIO_TYPE_ASN1 (22|BIO_TYPE_FILTER)
-# define BIO_TYPE_COMP (23|BIO_TYPE_FILTER)
-# ifndef OPENSSL_NO_SCTP
-# define BIO_TYPE_DGRAM_SCTP (24|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR)
-# endif
-
-#define BIO_TYPE_START 128
-
-/*
- * BIO_FILENAME_READ|BIO_CLOSE to open or close on free.
- * BIO_set_fp(in,stdin,BIO_NOCLOSE);
- */
-# define BIO_NOCLOSE 0x00
-# define BIO_CLOSE 0x01
-
-/*
- * These are used in the following macros and are passed to BIO_ctrl()
- */
-# define BIO_CTRL_RESET 1/* opt - rewind/zero etc */
-# define BIO_CTRL_EOF 2/* opt - are we at the eof */
-# define BIO_CTRL_INFO 3/* opt - extra tit-bits */
-# define BIO_CTRL_SET 4/* man - set the 'IO' type */
-# define BIO_CTRL_GET 5/* man - get the 'IO' type */
-# define BIO_CTRL_PUSH 6/* opt - internal, used to signify change */
-# define BIO_CTRL_POP 7/* opt - internal, used to signify change */
-# define BIO_CTRL_GET_CLOSE 8/* man - set the 'close' on free */
-# define BIO_CTRL_SET_CLOSE 9/* man - set the 'close' on free */
-# define BIO_CTRL_PENDING 10/* opt - is their more data buffered */
-# define BIO_CTRL_FLUSH 11/* opt - 'flush' buffered output */
-# define BIO_CTRL_DUP 12/* man - extra stuff for 'duped' BIO */
-# define BIO_CTRL_WPENDING 13/* opt - number of bytes still to write */
-# define BIO_CTRL_SET_CALLBACK 14/* opt - set callback function */
-# define BIO_CTRL_GET_CALLBACK 15/* opt - set callback function */
-
-# define BIO_CTRL_PEEK 29/* BIO_f_buffer special */
-# define BIO_CTRL_SET_FILENAME 30/* BIO_s_file special */
-
-/* dgram BIO stuff */
-# define BIO_CTRL_DGRAM_CONNECT 31/* BIO dgram special */
-# define BIO_CTRL_DGRAM_SET_CONNECTED 32/* allow for an externally connected
- * socket to be passed in */
-# define BIO_CTRL_DGRAM_SET_RECV_TIMEOUT 33/* setsockopt, essentially */
-# define BIO_CTRL_DGRAM_GET_RECV_TIMEOUT 34/* getsockopt, essentially */
-# define BIO_CTRL_DGRAM_SET_SEND_TIMEOUT 35/* setsockopt, essentially */
-# define BIO_CTRL_DGRAM_GET_SEND_TIMEOUT 36/* getsockopt, essentially */
-
-# define BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP 37/* flag whether the last */
-# define BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP 38/* I/O operation tiemd out */
-
-/* #ifdef IP_MTU_DISCOVER */
-# define BIO_CTRL_DGRAM_MTU_DISCOVER 39/* set DF bit on egress packets */
-/* #endif */
-
-# define BIO_CTRL_DGRAM_QUERY_MTU 40/* as kernel for current MTU */
-# define BIO_CTRL_DGRAM_GET_FALLBACK_MTU 47
-# define BIO_CTRL_DGRAM_GET_MTU 41/* get cached value for MTU */
-# define BIO_CTRL_DGRAM_SET_MTU 42/* set cached value for MTU.
- * want to use this if asking
- * the kernel fails */
-
-# define BIO_CTRL_DGRAM_MTU_EXCEEDED 43/* check whether the MTU was
- * exceed in the previous write
- * operation */
-
-# define BIO_CTRL_DGRAM_GET_PEER 46
-# define BIO_CTRL_DGRAM_SET_PEER 44/* Destination for the data */
-
-# define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45/* Next DTLS handshake timeout
- * to adjust socket timeouts */
-# define BIO_CTRL_DGRAM_SET_DONT_FRAG 48
-
-# define BIO_CTRL_DGRAM_GET_MTU_OVERHEAD 49
-
-/* Deliberately outside of OPENSSL_NO_SCTP - used in bss_dgram.c */
-# define BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE 50
-# ifndef OPENSSL_NO_SCTP
-/* SCTP stuff */
-# define BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY 51
-# define BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY 52
-# define BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD 53
-# define BIO_CTRL_DGRAM_SCTP_GET_SNDINFO 60
-# define BIO_CTRL_DGRAM_SCTP_SET_SNDINFO 61
-# define BIO_CTRL_DGRAM_SCTP_GET_RCVINFO 62
-# define BIO_CTRL_DGRAM_SCTP_SET_RCVINFO 63
-# define BIO_CTRL_DGRAM_SCTP_GET_PRINFO 64
-# define BIO_CTRL_DGRAM_SCTP_SET_PRINFO 65
-# define BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN 70
-# endif
-
-# define BIO_CTRL_DGRAM_SET_PEEK_MODE 71
-
-/* modifiers */
-# define BIO_FP_READ 0x02
-# define BIO_FP_WRITE 0x04
-# define BIO_FP_APPEND 0x08
-# define BIO_FP_TEXT 0x10
-
-# define BIO_FLAGS_READ 0x01
-# define BIO_FLAGS_WRITE 0x02
-# define BIO_FLAGS_IO_SPECIAL 0x04
-# define BIO_FLAGS_RWS (BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPECIAL)
-# define BIO_FLAGS_SHOULD_RETRY 0x08
-# ifndef BIO_FLAGS_UPLINK
-/*
- * "UPLINK" flag denotes file descriptors provided by application. It
- * defaults to 0, as most platforms don't require UPLINK interface.
- */
-# define BIO_FLAGS_UPLINK 0
-# endif
-
-# define BIO_FLAGS_BASE64_NO_NL 0x100
-
-/*
- * This is used with memory BIOs:
- * BIO_FLAGS_MEM_RDONLY means we shouldn't free up or change the data in any way;
- * BIO_FLAGS_NONCLEAR_RST means we shouldn't clear data on reset.
- */
-# define BIO_FLAGS_MEM_RDONLY 0x200
-# define BIO_FLAGS_NONCLEAR_RST 0x400
-# define BIO_FLAGS_IN_EOF 0x800
-
-typedef union bio_addr_st BIO_ADDR;
-typedef struct bio_addrinfo_st BIO_ADDRINFO;
-
-int BIO_get_new_index(void);
-void BIO_set_flags(BIO *b, int flags);
-int BIO_test_flags(const BIO *b, int flags);
-void BIO_clear_flags(BIO *b, int flags);
-
-# define BIO_get_flags(b) BIO_test_flags(b, ~(0x0))
-# define BIO_set_retry_special(b) \
- BIO_set_flags(b, (BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY))
-# define BIO_set_retry_read(b) \
- BIO_set_flags(b, (BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY))
-# define BIO_set_retry_write(b) \
- BIO_set_flags(b, (BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY))
-
-/* These are normally used internally in BIOs */
-# define BIO_clear_retry_flags(b) \
- BIO_clear_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
-# define BIO_get_retry_flags(b) \
- BIO_test_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
-
-/* These should be used by the application to tell why we should retry */
-# define BIO_should_read(a) BIO_test_flags(a, BIO_FLAGS_READ)
-# define BIO_should_write(a) BIO_test_flags(a, BIO_FLAGS_WRITE)
-# define BIO_should_io_special(a) BIO_test_flags(a, BIO_FLAGS_IO_SPECIAL)
-# define BIO_retry_type(a) BIO_test_flags(a, BIO_FLAGS_RWS)
-# define BIO_should_retry(a) BIO_test_flags(a, BIO_FLAGS_SHOULD_RETRY)
-
-/*
- * The next three are used in conjunction with the BIO_should_io_special()
- * condition. After this returns true, BIO *BIO_get_retry_BIO(BIO *bio, int
- * *reason); will walk the BIO stack and return the 'reason' for the special
- * and the offending BIO. Given a BIO, BIO_get_retry_reason(bio) will return
- * the code.
- */
-/*
- * Returned from the SSL bio when the certificate retrieval code had an error
- */
-# define BIO_RR_SSL_X509_LOOKUP 0x01
-/* Returned from the connect BIO when a connect would have blocked */
-# define BIO_RR_CONNECT 0x02
-/* Returned from the accept BIO when an accept would have blocked */
-# define BIO_RR_ACCEPT 0x03
-
-/* These are passed by the BIO callback */
-# define BIO_CB_FREE 0x01
-# define BIO_CB_READ 0x02
-# define BIO_CB_WRITE 0x03
-# define BIO_CB_PUTS 0x04
-# define BIO_CB_GETS 0x05
-# define BIO_CB_CTRL 0x06
-
-/*
- * The callback is called before and after the underling operation, The
- * BIO_CB_RETURN flag indicates if it is after the call
- */
-# define BIO_CB_RETURN 0x80
-# define BIO_CB_return(a) ((a)|BIO_CB_RETURN)
-# define BIO_cb_pre(a) (!((a)&BIO_CB_RETURN))
-# define BIO_cb_post(a) ((a)&BIO_CB_RETURN)
-
-typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi,
- long argl, long ret);
-typedef long (*BIO_callback_fn_ex)(BIO *b, int oper, const char *argp,
- size_t len, int argi,
- long argl, int ret, size_t *processed);
-BIO_callback_fn BIO_get_callback(const BIO *b);
-void BIO_set_callback(BIO *b, BIO_callback_fn callback);
-
-BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b);
-void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex callback);
-
-char *BIO_get_callback_arg(const BIO *b);
-void BIO_set_callback_arg(BIO *b, char *arg);
-
-typedef struct bio_method_st BIO_METHOD;
-
-const char *BIO_method_name(const BIO *b);
-int BIO_method_type(const BIO *b);
-
-typedef int BIO_info_cb(BIO *, int, int);
-typedef BIO_info_cb bio_info_cb; /* backward compatibility */
-
-DEFINE_STACK_OF(BIO)
-
-/* Prefix and suffix callback in ASN1 BIO */
-typedef int asn1_ps_func (BIO *b, unsigned char **pbuf, int *plen,
- void *parg);
-
-# ifndef OPENSSL_NO_SCTP
-/* SCTP parameter structs */
-struct bio_dgram_sctp_sndinfo {
- uint16_t snd_sid;
- uint16_t snd_flags;
- uint32_t snd_ppid;
- uint32_t snd_context;
-};
-
-struct bio_dgram_sctp_rcvinfo {
- uint16_t rcv_sid;
- uint16_t rcv_ssn;
- uint16_t rcv_flags;
- uint32_t rcv_ppid;
- uint32_t rcv_tsn;
- uint32_t rcv_cumtsn;
- uint32_t rcv_context;
-};
-
-struct bio_dgram_sctp_prinfo {
- uint16_t pr_policy;
- uint32_t pr_value;
-};
-# endif
-
-/*
- * #define BIO_CONN_get_param_hostname BIO_ctrl
- */
-
-# define BIO_C_SET_CONNECT 100
-# define BIO_C_DO_STATE_MACHINE 101
-# define BIO_C_SET_NBIO 102
-/* # define BIO_C_SET_PROXY_PARAM 103 */
-# define BIO_C_SET_FD 104
-# define BIO_C_GET_FD 105
-# define BIO_C_SET_FILE_PTR 106
-# define BIO_C_GET_FILE_PTR 107
-# define BIO_C_SET_FILENAME 108
-# define BIO_C_SET_SSL 109
-# define BIO_C_GET_SSL 110
-# define BIO_C_SET_MD 111
-# define BIO_C_GET_MD 112
-# define BIO_C_GET_CIPHER_STATUS 113
-# define BIO_C_SET_BUF_MEM 114
-# define BIO_C_GET_BUF_MEM_PTR 115
-# define BIO_C_GET_BUFF_NUM_LINES 116
-# define BIO_C_SET_BUFF_SIZE 117
-# define BIO_C_SET_ACCEPT 118
-# define BIO_C_SSL_MODE 119
-# define BIO_C_GET_MD_CTX 120
-/* # define BIO_C_GET_PROXY_PARAM 121 */
-# define BIO_C_SET_BUFF_READ_DATA 122/* data to read first */
-# define BIO_C_GET_CONNECT 123
-# define BIO_C_GET_ACCEPT 124
-# define BIO_C_SET_SSL_RENEGOTIATE_BYTES 125
-# define BIO_C_GET_SSL_NUM_RENEGOTIATES 126
-# define BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT 127
-# define BIO_C_FILE_SEEK 128
-# define BIO_C_GET_CIPHER_CTX 129
-# define BIO_C_SET_BUF_MEM_EOF_RETURN 130/* return end of input
- * value */
-# define BIO_C_SET_BIND_MODE 131
-# define BIO_C_GET_BIND_MODE 132
-# define BIO_C_FILE_TELL 133
-# define BIO_C_GET_SOCKS 134
-# define BIO_C_SET_SOCKS 135
-
-# define BIO_C_SET_WRITE_BUF_SIZE 136/* for BIO_s_bio */
-# define BIO_C_GET_WRITE_BUF_SIZE 137
-# define BIO_C_MAKE_BIO_PAIR 138
-# define BIO_C_DESTROY_BIO_PAIR 139
-# define BIO_C_GET_WRITE_GUARANTEE 140
-# define BIO_C_GET_READ_REQUEST 141
-# define BIO_C_SHUTDOWN_WR 142
-# define BIO_C_NREAD0 143
-# define BIO_C_NREAD 144
-# define BIO_C_NWRITE0 145
-# define BIO_C_NWRITE 146
-# define BIO_C_RESET_READ_REQUEST 147
-# define BIO_C_SET_MD_CTX 148
-
-# define BIO_C_SET_PREFIX 149
-# define BIO_C_GET_PREFIX 150
-# define BIO_C_SET_SUFFIX 151
-# define BIO_C_GET_SUFFIX 152
-
-# define BIO_C_SET_EX_ARG 153
-# define BIO_C_GET_EX_ARG 154
-
-# define BIO_C_SET_CONNECT_MODE 155
-
-# define BIO_set_app_data(s,arg) BIO_set_ex_data(s,0,arg)
-# define BIO_get_app_data(s) BIO_get_ex_data(s,0)
-
-# define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL)
-
-# ifndef OPENSSL_NO_SOCK
-/* IP families we support, for BIO_s_connect() and BIO_s_accept() */
-/* Note: the underlying operating system may not support some of them */
-# define BIO_FAMILY_IPV4 4
-# define BIO_FAMILY_IPV6 6
-# define BIO_FAMILY_IPANY 256
-
-/* BIO_s_connect() */
-# define BIO_set_conn_hostname(b,name) BIO_ctrl(b,BIO_C_SET_CONNECT,0, \
- (char *)(name))
-# define BIO_set_conn_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,1, \
- (char *)(port))
-# define BIO_set_conn_address(b,addr) BIO_ctrl(b,BIO_C_SET_CONNECT,2, \
- (char *)(addr))
-# define BIO_set_conn_ip_family(b,f) BIO_int_ctrl(b,BIO_C_SET_CONNECT,3,f)
-# define BIO_get_conn_hostname(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,0))
-# define BIO_get_conn_port(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1))
-# define BIO_get_conn_address(b) ((const BIO_ADDR *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2))
-# define BIO_get_conn_ip_family(b) BIO_ctrl(b,BIO_C_GET_CONNECT,3,NULL)
-# define BIO_set_conn_mode(b,n) BIO_ctrl(b,BIO_C_SET_CONNECT_MODE,(n),NULL)
-
-/* BIO_s_accept() */
-# define BIO_set_accept_name(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0, \
- (char *)(name))
-# define BIO_set_accept_port(b,port) BIO_ctrl(b,BIO_C_SET_ACCEPT,1, \
- (char *)(port))
-# define BIO_get_accept_name(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,0))
-# define BIO_get_accept_port(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,1))
-# define BIO_get_peer_name(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,2))
-# define BIO_get_peer_port(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,3))
-/* #define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) */
-# define BIO_set_nbio_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,2,(n)?(void *)"a":NULL)
-# define BIO_set_accept_bios(b,bio) BIO_ctrl(b,BIO_C_SET_ACCEPT,3, \
- (char *)(bio))
-# define BIO_set_accept_ip_family(b,f) BIO_int_ctrl(b,BIO_C_SET_ACCEPT,4,f)
-# define BIO_get_accept_ip_family(b) BIO_ctrl(b,BIO_C_GET_ACCEPT,4,NULL)
-
-/* Aliases kept for backward compatibility */
-# define BIO_BIND_NORMAL 0
-# define BIO_BIND_REUSEADDR BIO_SOCK_REUSEADDR
-# define BIO_BIND_REUSEADDR_IF_UNUSED BIO_SOCK_REUSEADDR
-# define BIO_set_bind_mode(b,mode) BIO_ctrl(b,BIO_C_SET_BIND_MODE,mode,NULL)
-# define BIO_get_bind_mode(b) BIO_ctrl(b,BIO_C_GET_BIND_MODE,0,NULL)
-
-/* BIO_s_accept() and BIO_s_connect() */
-# define BIO_do_connect(b) BIO_do_handshake(b)
-# define BIO_do_accept(b) BIO_do_handshake(b)
-# endif /* OPENSSL_NO_SOCK */
-
-# define BIO_do_handshake(b) BIO_ctrl(b,BIO_C_DO_STATE_MACHINE,0,NULL)
-
-/* BIO_s_datagram(), BIO_s_fd(), BIO_s_socket(), BIO_s_accept() and BIO_s_connect() */
-# define BIO_set_fd(b,fd,c) BIO_int_ctrl(b,BIO_C_SET_FD,c,fd)
-# define BIO_get_fd(b,c) BIO_ctrl(b,BIO_C_GET_FD,0,(char *)(c))
-
-/* BIO_s_file() */
-# define BIO_set_fp(b,fp,c) BIO_ctrl(b,BIO_C_SET_FILE_PTR,c,(char *)(fp))
-# define BIO_get_fp(b,fpp) BIO_ctrl(b,BIO_C_GET_FILE_PTR,0,(char *)(fpp))
-
-/* BIO_s_fd() and BIO_s_file() */
-# define BIO_seek(b,ofs) (int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL)
-# define BIO_tell(b) (int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL)
-
-/*
- * name is cast to lose const, but might be better to route through a
- * function so we can do it safely
- */
-# ifdef CONST_STRICT
-/*
- * If you are wondering why this isn't defined, its because CONST_STRICT is
- * purely a compile-time kludge to allow const to be checked.
- */
-int BIO_read_filename(BIO *b, const char *name);
-# else
-# define BIO_read_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \
- BIO_CLOSE|BIO_FP_READ,(char *)(name))
-# endif
-# define BIO_write_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \
- BIO_CLOSE|BIO_FP_WRITE,name)
-# define BIO_append_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \
- BIO_CLOSE|BIO_FP_APPEND,name)
-# define BIO_rw_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \
- BIO_CLOSE|BIO_FP_READ|BIO_FP_WRITE,name)
-
-/*
- * WARNING WARNING, this ups the reference count on the read bio of the SSL
- * structure. This is because the ssl read BIO is now pointed to by the
- * next_bio field in the bio. So when you free the BIO, make sure you are
- * doing a BIO_free_all() to catch the underlying BIO.
- */
-# define BIO_set_ssl(b,ssl,c) BIO_ctrl(b,BIO_C_SET_SSL,c,(char *)(ssl))
-# define BIO_get_ssl(b,sslp) BIO_ctrl(b,BIO_C_GET_SSL,0,(char *)(sslp))
-# define BIO_set_ssl_mode(b,client) BIO_ctrl(b,BIO_C_SSL_MODE,client,NULL)
-# define BIO_set_ssl_renegotiate_bytes(b,num) \
- BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_BYTES,num,NULL)
-# define BIO_get_num_renegotiates(b) \
- BIO_ctrl(b,BIO_C_GET_SSL_NUM_RENEGOTIATES,0,NULL)
-# define BIO_set_ssl_renegotiate_timeout(b,seconds) \
- BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT,seconds,NULL)
-
-/* defined in evp.h */
-/* #define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,1,(char *)(md)) */
-
-# define BIO_get_mem_data(b,pp) BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)(pp))
-# define BIO_set_mem_buf(b,bm,c) BIO_ctrl(b,BIO_C_SET_BUF_MEM,c,(char *)(bm))
-# define BIO_get_mem_ptr(b,pp) BIO_ctrl(b,BIO_C_GET_BUF_MEM_PTR,0, \
- (char *)(pp))
-# define BIO_set_mem_eof_return(b,v) \
- BIO_ctrl(b,BIO_C_SET_BUF_MEM_EOF_RETURN,v,NULL)
-
-/* For the BIO_f_buffer() type */
-# define BIO_get_buffer_num_lines(b) BIO_ctrl(b,BIO_C_GET_BUFF_NUM_LINES,0,NULL)
-# define BIO_set_buffer_size(b,size) BIO_ctrl(b,BIO_C_SET_BUFF_SIZE,size,NULL)
-# define BIO_set_read_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,0)
-# define BIO_set_write_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,1)
-# define BIO_set_buffer_read_data(b,buf,num) BIO_ctrl(b,BIO_C_SET_BUFF_READ_DATA,num,buf)
-
-/* Don't use the next one unless you know what you are doing :-) */
-# define BIO_dup_state(b,ret) BIO_ctrl(b,BIO_CTRL_DUP,0,(char *)(ret))
-
-# define BIO_reset(b) (int)BIO_ctrl(b,BIO_CTRL_RESET,0,NULL)
-# define BIO_eof(b) (int)BIO_ctrl(b,BIO_CTRL_EOF,0,NULL)
-# define BIO_set_close(b,c) (int)BIO_ctrl(b,BIO_CTRL_SET_CLOSE,(c),NULL)
-# define BIO_get_close(b) (int)BIO_ctrl(b,BIO_CTRL_GET_CLOSE,0,NULL)
-# define BIO_pending(b) (int)BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL)
-# define BIO_wpending(b) (int)BIO_ctrl(b,BIO_CTRL_WPENDING,0,NULL)
-/* ...pending macros have inappropriate return type */
-size_t BIO_ctrl_pending(BIO *b);
-size_t BIO_ctrl_wpending(BIO *b);
-# define BIO_flush(b) (int)BIO_ctrl(b,BIO_CTRL_FLUSH,0,NULL)
-# define BIO_get_info_callback(b,cbp) (int)BIO_ctrl(b,BIO_CTRL_GET_CALLBACK,0, \
- cbp)
-# define BIO_set_info_callback(b,cb) (int)BIO_callback_ctrl(b,BIO_CTRL_SET_CALLBACK,cb)
-
-/* For the BIO_f_buffer() type */
-# define BIO_buffer_get_num_lines(b) BIO_ctrl(b,BIO_CTRL_GET,0,NULL)
-# define BIO_buffer_peek(b,s,l) BIO_ctrl(b,BIO_CTRL_PEEK,(l),(s))
-
-/* For BIO_s_bio() */
-# define BIO_set_write_buf_size(b,size) (int)BIO_ctrl(b,BIO_C_SET_WRITE_BUF_SIZE,size,NULL)
-# define BIO_get_write_buf_size(b,size) (size_t)BIO_ctrl(b,BIO_C_GET_WRITE_BUF_SIZE,size,NULL)
-# define BIO_make_bio_pair(b1,b2) (int)BIO_ctrl(b1,BIO_C_MAKE_BIO_PAIR,0,b2)
-# define BIO_destroy_bio_pair(b) (int)BIO_ctrl(b,BIO_C_DESTROY_BIO_PAIR,0,NULL)
-# define BIO_shutdown_wr(b) (int)BIO_ctrl(b, BIO_C_SHUTDOWN_WR, 0, NULL)
-/* macros with inappropriate type -- but ...pending macros use int too: */
-# define BIO_get_write_guarantee(b) (int)BIO_ctrl(b,BIO_C_GET_WRITE_GUARANTEE,0,NULL)
-# define BIO_get_read_request(b) (int)BIO_ctrl(b,BIO_C_GET_READ_REQUEST,0,NULL)
-size_t BIO_ctrl_get_write_guarantee(BIO *b);
-size_t BIO_ctrl_get_read_request(BIO *b);
-int BIO_ctrl_reset_read_request(BIO *b);
-
-/* ctrl macros for dgram */
-# define BIO_ctrl_dgram_connect(b,peer) \
- (int)BIO_ctrl(b,BIO_CTRL_DGRAM_CONNECT,0, (char *)(peer))
-# define BIO_ctrl_set_connected(b,peer) \
- (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_CONNECTED, 0, (char *)(peer))
-# define BIO_dgram_recv_timedout(b) \
- (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP, 0, NULL)
-# define BIO_dgram_send_timedout(b) \
- (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP, 0, NULL)
-# define BIO_dgram_get_peer(b,peer) \
- (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, (char *)(peer))
-# define BIO_dgram_set_peer(b,peer) \
- (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)(peer))
-# define BIO_dgram_get_mtu_overhead(b) \
- (unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU_OVERHEAD, 0, NULL)
-
-#define BIO_get_ex_new_index(l, p, newf, dupf, freef) \
- CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, l, p, newf, dupf, freef)
-int BIO_set_ex_data(BIO *bio, int idx, void *data);
-void *BIO_get_ex_data(BIO *bio, int idx);
-uint64_t BIO_number_read(BIO *bio);
-uint64_t BIO_number_written(BIO *bio);
-
-/* For BIO_f_asn1() */
-int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix,
- asn1_ps_func *prefix_free);
-int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix,
- asn1_ps_func **pprefix_free);
-int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix,
- asn1_ps_func *suffix_free);
-int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix,
- asn1_ps_func **psuffix_free);
-
-const BIO_METHOD *BIO_s_file(void);
-BIO *BIO_new_file(const char *filename, const char *mode);
-# ifndef OPENSSL_NO_STDIO
-BIO *BIO_new_fp(FILE *stream, int close_flag);
-# endif
-BIO *BIO_new(const BIO_METHOD *type);
-int BIO_free(BIO *a);
-void BIO_set_data(BIO *a, void *ptr);
-void *BIO_get_data(BIO *a);
-void BIO_set_init(BIO *a, int init);
-int BIO_get_init(BIO *a);
-void BIO_set_shutdown(BIO *a, int shut);
-int BIO_get_shutdown(BIO *a);
-void BIO_vfree(BIO *a);
-int BIO_up_ref(BIO *a);
-int BIO_read(BIO *b, void *data, int dlen);
-int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes);
-int BIO_gets(BIO *bp, char *buf, int size);
-int BIO_write(BIO *b, const void *data, int dlen);
-int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written);
-int BIO_puts(BIO *bp, const char *buf);
-int BIO_indent(BIO *b, int indent, int max);
-long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg);
-long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp);
-void *BIO_ptr_ctrl(BIO *bp, int cmd, long larg);
-long BIO_int_ctrl(BIO *bp, int cmd, long larg, int iarg);
-BIO *BIO_push(BIO *b, BIO *append);
-BIO *BIO_pop(BIO *b);
-void BIO_free_all(BIO *a);
-BIO *BIO_find_type(BIO *b, int bio_type);
-BIO *BIO_next(BIO *b);
-void BIO_set_next(BIO *b, BIO *next);
-BIO *BIO_get_retry_BIO(BIO *bio, int *reason);
-int BIO_get_retry_reason(BIO *bio);
-void BIO_set_retry_reason(BIO *bio, int reason);
-BIO *BIO_dup_chain(BIO *in);
-
-int BIO_nread0(BIO *bio, char **buf);
-int BIO_nread(BIO *bio, char **buf, int num);
-int BIO_nwrite0(BIO *bio, char **buf);
-int BIO_nwrite(BIO *bio, char **buf, int num);
-
-long BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi,
- long argl, long ret);
-
-const BIO_METHOD *BIO_s_mem(void);
-const BIO_METHOD *BIO_s_secmem(void);
-BIO *BIO_new_mem_buf(const void *buf, int len);
-# ifndef OPENSSL_NO_SOCK
-const BIO_METHOD *BIO_s_socket(void);
-const BIO_METHOD *BIO_s_connect(void);
-const BIO_METHOD *BIO_s_accept(void);
-# endif
-const BIO_METHOD *BIO_s_fd(void);
-const BIO_METHOD *BIO_s_log(void);
-const BIO_METHOD *BIO_s_bio(void);
-const BIO_METHOD *BIO_s_null(void);
-const BIO_METHOD *BIO_f_null(void);
-const BIO_METHOD *BIO_f_buffer(void);
-const BIO_METHOD *BIO_f_linebuffer(void);
-const BIO_METHOD *BIO_f_nbio_test(void);
-# ifndef OPENSSL_NO_DGRAM
-const BIO_METHOD *BIO_s_datagram(void);
-int BIO_dgram_non_fatal_error(int error);
-BIO *BIO_new_dgram(int fd, int close_flag);
-# ifndef OPENSSL_NO_SCTP
-const BIO_METHOD *BIO_s_datagram_sctp(void);
-BIO *BIO_new_dgram_sctp(int fd, int close_flag);
-int BIO_dgram_is_sctp(BIO *bio);
-int BIO_dgram_sctp_notification_cb(BIO *b,
- void (*handle_notifications) (BIO *bio,
- void *context,
- void *buf),
- void *context);
-int BIO_dgram_sctp_wait_for_dry(BIO *b);
-int BIO_dgram_sctp_msg_waiting(BIO *b);
-# endif
-# endif
-
-# ifndef OPENSSL_NO_SOCK
-int BIO_sock_should_retry(int i);
-int BIO_sock_non_fatal_error(int error);
-# endif
-
-int BIO_fd_should_retry(int i);
-int BIO_fd_non_fatal_error(int error);
-int BIO_dump_cb(int (*cb) (const void *data, size_t len, void *u),
- void *u, const char *s, int len);
-int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u),
- void *u, const char *s, int len, int indent);
-int BIO_dump(BIO *b, const char *bytes, int len);
-int BIO_dump_indent(BIO *b, const char *bytes, int len, int indent);
-# ifndef OPENSSL_NO_STDIO
-int BIO_dump_fp(FILE *fp, const char *s, int len);
-int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent);
-# endif
-int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data,
- int datalen);
-
-# ifndef OPENSSL_NO_SOCK
-BIO_ADDR *BIO_ADDR_new(void);
-int BIO_ADDR_rawmake(BIO_ADDR *ap, int family,
- const void *where, size_t wherelen, unsigned short port);
-void BIO_ADDR_free(BIO_ADDR *);
-void BIO_ADDR_clear(BIO_ADDR *ap);
-int BIO_ADDR_family(const BIO_ADDR *ap);
-int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l);
-unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap);
-char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric);
-char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric);
-char *BIO_ADDR_path_string(const BIO_ADDR *ap);
-
-const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai);
-int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai);
-int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai);
-int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai);
-const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai);
-void BIO_ADDRINFO_free(BIO_ADDRINFO *bai);
-
-enum BIO_hostserv_priorities {
- BIO_PARSE_PRIO_HOST, BIO_PARSE_PRIO_SERV
-};
-int BIO_parse_hostserv(const char *hostserv, char **host, char **service,
- enum BIO_hostserv_priorities hostserv_prio);
-enum BIO_lookup_type {
- BIO_LOOKUP_CLIENT, BIO_LOOKUP_SERVER
-};
-int BIO_lookup(const char *host, const char *service,
- enum BIO_lookup_type lookup_type,
- int family, int socktype, BIO_ADDRINFO **res);
-int BIO_lookup_ex(const char *host, const char *service,
- int lookup_type, int family, int socktype, int protocol,
- BIO_ADDRINFO **res);
-int BIO_sock_error(int sock);
-int BIO_socket_ioctl(int fd, long type, void *arg);
-int BIO_socket_nbio(int fd, int mode);
-int BIO_sock_init(void);
-# if OPENSSL_API_COMPAT < 0x10100000L
-# define BIO_sock_cleanup() while(0) continue
-# endif
-int BIO_set_tcp_ndelay(int sock, int turn_on);
-
-DEPRECATEDIN_1_1_0(struct hostent *BIO_gethostbyname(const char *name))
-DEPRECATEDIN_1_1_0(int BIO_get_port(const char *str, unsigned short *port_ptr))
-DEPRECATEDIN_1_1_0(int BIO_get_host_ip(const char *str, unsigned char *ip))
-DEPRECATEDIN_1_1_0(int BIO_get_accept_socket(char *host_port, int mode))
-DEPRECATEDIN_1_1_0(int BIO_accept(int sock, char **ip_port))
-
-union BIO_sock_info_u {
- BIO_ADDR *addr;
-};
-enum BIO_sock_info_type {
- BIO_SOCK_INFO_ADDRESS
-};
-int BIO_sock_info(int sock,
- enum BIO_sock_info_type type, union BIO_sock_info_u *info);
-
-# define BIO_SOCK_REUSEADDR 0x01
-# define BIO_SOCK_V6_ONLY 0x02
-# define BIO_SOCK_KEEPALIVE 0x04
-# define BIO_SOCK_NONBLOCK 0x08
-# define BIO_SOCK_NODELAY 0x10
-
-int BIO_socket(int domain, int socktype, int protocol, int options);
-int BIO_connect(int sock, const BIO_ADDR *addr, int options);
-int BIO_bind(int sock, const BIO_ADDR *addr, int options);
-int BIO_listen(int sock, const BIO_ADDR *addr, int options);
-int BIO_accept_ex(int accept_sock, BIO_ADDR *addr, int options);
-int BIO_closesocket(int sock);
-
-BIO *BIO_new_socket(int sock, int close_flag);
-BIO *BIO_new_connect(const char *host_port);
-BIO *BIO_new_accept(const char *host_port);
-# endif /* OPENSSL_NO_SOCK*/
-
-BIO *BIO_new_fd(int fd, int close_flag);
-
-int BIO_new_bio_pair(BIO **bio1, size_t writebuf1,
- BIO **bio2, size_t writebuf2);
-/*
- * If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints.
- * Otherwise returns 0 and sets *bio1 and *bio2 to NULL. Size 0 uses default
- * value.
- */
-
-void BIO_copy_next_retry(BIO *b);
-
-/*
- * long BIO_ghbn_ctrl(int cmd,int iarg,char *parg);
- */
-
-# define ossl_bio__attr__(x)
-# if defined(__GNUC__) && defined(__STDC_VERSION__) \
- && !defined(__APPLE__)
- /*
- * Because we support the 'z' modifier, which made its appearance in C99,
- * we can't use __attribute__ with pre C99 dialects.
- */
-# if __STDC_VERSION__ >= 199901L
-# undef ossl_bio__attr__
-# define ossl_bio__attr__ __attribute__
-# if __GNUC__*10 + __GNUC_MINOR__ >= 44
-# define ossl_bio__printf__ __gnu_printf__
-# else
-# define ossl_bio__printf__ __printf__
-# endif
-# endif
-# endif
-int BIO_printf(BIO *bio, const char *format, ...)
-ossl_bio__attr__((__format__(ossl_bio__printf__, 2, 3)));
-int BIO_vprintf(BIO *bio, const char *format, va_list args)
-ossl_bio__attr__((__format__(ossl_bio__printf__, 2, 0)));
-int BIO_snprintf(char *buf, size_t n, const char *format, ...)
-ossl_bio__attr__((__format__(ossl_bio__printf__, 3, 4)));
-int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
-ossl_bio__attr__((__format__(ossl_bio__printf__, 3, 0)));
-# undef ossl_bio__attr__
-# undef ossl_bio__printf__
-
-
-BIO_METHOD *BIO_meth_new(int type, const char *name);
-void BIO_meth_free(BIO_METHOD *biom);
-int (*BIO_meth_get_write(const BIO_METHOD *biom)) (BIO *, const char *, int);
-int (*BIO_meth_get_write_ex(const BIO_METHOD *biom)) (BIO *, const char *, size_t,
- size_t *);
-int BIO_meth_set_write(BIO_METHOD *biom,
- int (*write) (BIO *, const char *, int));
-int BIO_meth_set_write_ex(BIO_METHOD *biom,
- int (*bwrite) (BIO *, const char *, size_t, size_t *));
-int (*BIO_meth_get_read(const BIO_METHOD *biom)) (BIO *, char *, int);
-int (*BIO_meth_get_read_ex(const BIO_METHOD *biom)) (BIO *, char *, size_t, size_t *);
-int BIO_meth_set_read(BIO_METHOD *biom,
- int (*read) (BIO *, char *, int));
-int BIO_meth_set_read_ex(BIO_METHOD *biom,
- int (*bread) (BIO *, char *, size_t, size_t *));
-int (*BIO_meth_get_puts(const BIO_METHOD *biom)) (BIO *, const char *);
-int BIO_meth_set_puts(BIO_METHOD *biom,
- int (*puts) (BIO *, const char *));
-int (*BIO_meth_get_gets(const BIO_METHOD *biom)) (BIO *, char *, int);
-int BIO_meth_set_gets(BIO_METHOD *biom,
- int (*gets) (BIO *, char *, int));
-long (*BIO_meth_get_ctrl(const BIO_METHOD *biom)) (BIO *, int, long, void *);
-int BIO_meth_set_ctrl(BIO_METHOD *biom,
- long (*ctrl) (BIO *, int, long, void *));
-int (*BIO_meth_get_create(const BIO_METHOD *bion)) (BIO *);
-int BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *));
-int (*BIO_meth_get_destroy(const BIO_METHOD *biom)) (BIO *);
-int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *));
-long (*BIO_meth_get_callback_ctrl(const BIO_METHOD *biom))
- (BIO *, int, BIO_info_cb *);
-int BIO_meth_set_callback_ctrl(BIO_METHOD *biom,
- long (*callback_ctrl) (BIO *, int,
- BIO_info_cb *));
-
-# ifdef __cplusplus
-}
-# endif
-#endif
diff --git a/include/openssl/bio.h.in b/include/openssl/bio.h.in
new file mode 100644
index 000000000000..c521e41e4a17
--- /dev/null
+++ b/include/openssl/bio.h.in
@@ -0,0 +1,864 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_BIO_H
+# define OPENSSL_BIO_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_BIO_H
+# endif
+
+# include <openssl/e_os2.h>
+
+# ifndef OPENSSL_NO_STDIO
+# include <stdio.h>
+# endif
+# include <stdarg.h>
+
+# include <openssl/crypto.h>
+# include <openssl/bioerr.h>
+# include <openssl/core.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* There are the classes of BIOs */
+# define BIO_TYPE_DESCRIPTOR 0x0100 /* socket, fd, connect or accept */
+# define BIO_TYPE_FILTER 0x0200
+# define BIO_TYPE_SOURCE_SINK 0x0400
+
+/* These are the 'types' of BIOs */
+# define BIO_TYPE_NONE 0
+# define BIO_TYPE_MEM ( 1|BIO_TYPE_SOURCE_SINK)
+# define BIO_TYPE_FILE ( 2|BIO_TYPE_SOURCE_SINK)
+
+# define BIO_TYPE_FD ( 4|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR)
+# define BIO_TYPE_SOCKET ( 5|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR)
+# define BIO_TYPE_NULL ( 6|BIO_TYPE_SOURCE_SINK)
+# define BIO_TYPE_SSL ( 7|BIO_TYPE_FILTER)
+# define BIO_TYPE_MD ( 8|BIO_TYPE_FILTER)
+# define BIO_TYPE_BUFFER ( 9|BIO_TYPE_FILTER)
+# define BIO_TYPE_CIPHER (10|BIO_TYPE_FILTER)
+# define BIO_TYPE_BASE64 (11|BIO_TYPE_FILTER)
+# define BIO_TYPE_CONNECT (12|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR)
+# define BIO_TYPE_ACCEPT (13|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR)
+
+# define BIO_TYPE_NBIO_TEST (16|BIO_TYPE_FILTER)/* server proxy BIO */
+# define BIO_TYPE_NULL_FILTER (17|BIO_TYPE_FILTER)
+# define BIO_TYPE_BIO (19|BIO_TYPE_SOURCE_SINK)/* half a BIO pair */
+# define BIO_TYPE_LINEBUFFER (20|BIO_TYPE_FILTER)
+# define BIO_TYPE_DGRAM (21|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR)
+# define BIO_TYPE_ASN1 (22|BIO_TYPE_FILTER)
+# define BIO_TYPE_COMP (23|BIO_TYPE_FILTER)
+# ifndef OPENSSL_NO_SCTP
+# define BIO_TYPE_DGRAM_SCTP (24|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR)
+# endif
+# define BIO_TYPE_CORE_TO_PROV (25|BIO_TYPE_SOURCE_SINK)
+
+#define BIO_TYPE_START 128
+
+/*
+ * BIO_FILENAME_READ|BIO_CLOSE to open or close on free.
+ * BIO_set_fp(in,stdin,BIO_NOCLOSE);
+ */
+# define BIO_NOCLOSE 0x00
+# define BIO_CLOSE 0x01
+
+/*
+ * These are used in the following macros and are passed to BIO_ctrl()
+ */
+# define BIO_CTRL_RESET 1/* opt - rewind/zero etc */
+# define BIO_CTRL_EOF 2/* opt - are we at the eof */
+# define BIO_CTRL_INFO 3/* opt - extra tit-bits */
+# define BIO_CTRL_SET 4/* man - set the 'IO' type */
+# define BIO_CTRL_GET 5/* man - get the 'IO' type */
+# define BIO_CTRL_PUSH 6/* opt - internal, used to signify change */
+# define BIO_CTRL_POP 7/* opt - internal, used to signify change */
+# define BIO_CTRL_GET_CLOSE 8/* man - set the 'close' on free */
+# define BIO_CTRL_SET_CLOSE 9/* man - set the 'close' on free */
+# define BIO_CTRL_PENDING 10/* opt - is their more data buffered */
+# define BIO_CTRL_FLUSH 11/* opt - 'flush' buffered output */
+# define BIO_CTRL_DUP 12/* man - extra stuff for 'duped' BIO */
+# define BIO_CTRL_WPENDING 13/* opt - number of bytes still to write */
+# define BIO_CTRL_SET_CALLBACK 14/* opt - set callback function */
+# define BIO_CTRL_GET_CALLBACK 15/* opt - set callback function */
+
+# define BIO_CTRL_PEEK 29/* BIO_f_buffer special */
+# define BIO_CTRL_SET_FILENAME 30/* BIO_s_file special */
+
+/* dgram BIO stuff */
+# define BIO_CTRL_DGRAM_CONNECT 31/* BIO dgram special */
+# define BIO_CTRL_DGRAM_SET_CONNECTED 32/* allow for an externally connected
+ * socket to be passed in */
+# define BIO_CTRL_DGRAM_SET_RECV_TIMEOUT 33/* setsockopt, essentially */
+# define BIO_CTRL_DGRAM_GET_RECV_TIMEOUT 34/* getsockopt, essentially */
+# define BIO_CTRL_DGRAM_SET_SEND_TIMEOUT 35/* setsockopt, essentially */
+# define BIO_CTRL_DGRAM_GET_SEND_TIMEOUT 36/* getsockopt, essentially */
+
+# define BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP 37/* flag whether the last */
+# define BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP 38/* I/O operation timed out */
+
+/* #ifdef IP_MTU_DISCOVER */
+# define BIO_CTRL_DGRAM_MTU_DISCOVER 39/* set DF bit on egress packets */
+/* #endif */
+
+# define BIO_CTRL_DGRAM_QUERY_MTU 40/* as kernel for current MTU */
+# define BIO_CTRL_DGRAM_GET_FALLBACK_MTU 47
+# define BIO_CTRL_DGRAM_GET_MTU 41/* get cached value for MTU */
+# define BIO_CTRL_DGRAM_SET_MTU 42/* set cached value for MTU.
+ * want to use this if asking
+ * the kernel fails */
+
+# define BIO_CTRL_DGRAM_MTU_EXCEEDED 43/* check whether the MTU was
+ * exceed in the previous write
+ * operation */
+
+# define BIO_CTRL_DGRAM_GET_PEER 46
+# define BIO_CTRL_DGRAM_SET_PEER 44/* Destination for the data */
+
+# define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45/* Next DTLS handshake timeout
+ * to adjust socket timeouts */
+# define BIO_CTRL_DGRAM_SET_DONT_FRAG 48
+
+# define BIO_CTRL_DGRAM_GET_MTU_OVERHEAD 49
+
+/* Deliberately outside of OPENSSL_NO_SCTP - used in bss_dgram.c */
+# define BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE 50
+# ifndef OPENSSL_NO_SCTP
+/* SCTP stuff */
+# define BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY 51
+# define BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY 52
+# define BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD 53
+# define BIO_CTRL_DGRAM_SCTP_GET_SNDINFO 60
+# define BIO_CTRL_DGRAM_SCTP_SET_SNDINFO 61
+# define BIO_CTRL_DGRAM_SCTP_GET_RCVINFO 62
+# define BIO_CTRL_DGRAM_SCTP_SET_RCVINFO 63
+# define BIO_CTRL_DGRAM_SCTP_GET_PRINFO 64
+# define BIO_CTRL_DGRAM_SCTP_SET_PRINFO 65
+# define BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN 70
+# endif
+
+# define BIO_CTRL_DGRAM_SET_PEEK_MODE 71
+
+/*
+ * internal BIO:
+ * # define BIO_CTRL_SET_KTLS_SEND 72
+ * # define BIO_CTRL_SET_KTLS_SEND_CTRL_MSG 74
+ * # define BIO_CTRL_CLEAR_KTLS_CTRL_MSG 75
+ */
+
+# define BIO_CTRL_GET_KTLS_SEND 73
+# define BIO_CTRL_GET_KTLS_RECV 76
+
+# define BIO_CTRL_DGRAM_SCTP_WAIT_FOR_DRY 77
+# define BIO_CTRL_DGRAM_SCTP_MSG_WAITING 78
+
+/* BIO_f_prefix controls */
+# define BIO_CTRL_SET_PREFIX 79
+# define BIO_CTRL_SET_INDENT 80
+# define BIO_CTRL_GET_INDENT 81
+
+# ifndef OPENSSL_NO_KTLS
+# define BIO_get_ktls_send(b) \
+ (BIO_ctrl(b, BIO_CTRL_GET_KTLS_SEND, 0, NULL) > 0)
+# define BIO_get_ktls_recv(b) \
+ (BIO_ctrl(b, BIO_CTRL_GET_KTLS_RECV, 0, NULL) > 0)
+# else
+# define BIO_get_ktls_send(b) (0)
+# define BIO_get_ktls_recv(b) (0)
+# endif
+
+/* modifiers */
+# define BIO_FP_READ 0x02
+# define BIO_FP_WRITE 0x04
+# define BIO_FP_APPEND 0x08
+# define BIO_FP_TEXT 0x10
+
+# define BIO_FLAGS_READ 0x01
+# define BIO_FLAGS_WRITE 0x02
+# define BIO_FLAGS_IO_SPECIAL 0x04
+# define BIO_FLAGS_RWS (BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPECIAL)
+# define BIO_FLAGS_SHOULD_RETRY 0x08
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+/* This #define was replaced by an internal constant and should not be used. */
+# define BIO_FLAGS_UPLINK 0
+# endif
+
+# define BIO_FLAGS_BASE64_NO_NL 0x100
+
+/*
+ * This is used with memory BIOs:
+ * BIO_FLAGS_MEM_RDONLY means we shouldn't free up or change the data in any way;
+ * BIO_FLAGS_NONCLEAR_RST means we shouldn't clear data on reset.
+ */
+# define BIO_FLAGS_MEM_RDONLY 0x200
+# define BIO_FLAGS_NONCLEAR_RST 0x400
+# define BIO_FLAGS_IN_EOF 0x800
+
+/* the BIO FLAGS values 0x1000 to 0x4000 are reserved for internal KTLS flags */
+
+typedef union bio_addr_st BIO_ADDR;
+typedef struct bio_addrinfo_st BIO_ADDRINFO;
+
+int BIO_get_new_index(void);
+void BIO_set_flags(BIO *b, int flags);
+int BIO_test_flags(const BIO *b, int flags);
+void BIO_clear_flags(BIO *b, int flags);
+
+# define BIO_get_flags(b) BIO_test_flags(b, ~(0x0))
+# define BIO_set_retry_special(b) \
+ BIO_set_flags(b, (BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY))
+# define BIO_set_retry_read(b) \
+ BIO_set_flags(b, (BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY))
+# define BIO_set_retry_write(b) \
+ BIO_set_flags(b, (BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY))
+
+/* These are normally used internally in BIOs */
+# define BIO_clear_retry_flags(b) \
+ BIO_clear_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
+# define BIO_get_retry_flags(b) \
+ BIO_test_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
+
+/* These should be used by the application to tell why we should retry */
+# define BIO_should_read(a) BIO_test_flags(a, BIO_FLAGS_READ)
+# define BIO_should_write(a) BIO_test_flags(a, BIO_FLAGS_WRITE)
+# define BIO_should_io_special(a) BIO_test_flags(a, BIO_FLAGS_IO_SPECIAL)
+# define BIO_retry_type(a) BIO_test_flags(a, BIO_FLAGS_RWS)
+# define BIO_should_retry(a) BIO_test_flags(a, BIO_FLAGS_SHOULD_RETRY)
+
+/*
+ * The next three are used in conjunction with the BIO_should_io_special()
+ * condition. After this returns true, BIO *BIO_get_retry_BIO(BIO *bio, int
+ * *reason); will walk the BIO stack and return the 'reason' for the special
+ * and the offending BIO. Given a BIO, BIO_get_retry_reason(bio) will return
+ * the code.
+ */
+/*
+ * Returned from the SSL bio when the certificate retrieval code had an error
+ */
+# define BIO_RR_SSL_X509_LOOKUP 0x01
+/* Returned from the connect BIO when a connect would have blocked */
+# define BIO_RR_CONNECT 0x02
+/* Returned from the accept BIO when an accept would have blocked */
+# define BIO_RR_ACCEPT 0x03
+
+/* These are passed by the BIO callback */
+# define BIO_CB_FREE 0x01
+# define BIO_CB_READ 0x02
+# define BIO_CB_WRITE 0x03
+# define BIO_CB_PUTS 0x04
+# define BIO_CB_GETS 0x05
+# define BIO_CB_CTRL 0x06
+
+/*
+ * The callback is called before and after the underling operation, The
+ * BIO_CB_RETURN flag indicates if it is after the call
+ */
+# define BIO_CB_RETURN 0x80
+# define BIO_CB_return(a) ((a)|BIO_CB_RETURN)
+# define BIO_cb_pre(a) (!((a)&BIO_CB_RETURN))
+# define BIO_cb_post(a) ((a)&BIO_CB_RETURN)
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi,
+ long argl, long ret);
+OSSL_DEPRECATEDIN_3_0 BIO_callback_fn BIO_get_callback(const BIO *b);
+OSSL_DEPRECATEDIN_3_0 void BIO_set_callback(BIO *b, BIO_callback_fn callback);
+OSSL_DEPRECATEDIN_3_0 long BIO_debug_callback(BIO *bio, int cmd,
+ const char *argp, int argi,
+ long argl, long ret);
+# endif
+
+typedef long (*BIO_callback_fn_ex)(BIO *b, int oper, const char *argp,
+ size_t len, int argi,
+ long argl, int ret, size_t *processed);
+BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b);
+void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex callback);
+long BIO_debug_callback_ex(BIO *bio, int oper, const char *argp, size_t len,
+ int argi, long argl, int ret, size_t *processed);
+
+char *BIO_get_callback_arg(const BIO *b);
+void BIO_set_callback_arg(BIO *b, char *arg);
+
+typedef struct bio_method_st BIO_METHOD;
+
+const char *BIO_method_name(const BIO *b);
+int BIO_method_type(const BIO *b);
+
+typedef int BIO_info_cb(BIO *, int, int);
+typedef BIO_info_cb bio_info_cb; /* backward compatibility */
+
+{-
+ generate_stack_macros("BIO");
+-}
+
+
+/* Prefix and suffix callback in ASN1 BIO */
+typedef int asn1_ps_func (BIO *b, unsigned char **pbuf, int *plen,
+ void *parg);
+
+typedef void (*BIO_dgram_sctp_notification_handler_fn) (BIO *b,
+ void *context,
+ void *buf);
+# ifndef OPENSSL_NO_SCTP
+/* SCTP parameter structs */
+struct bio_dgram_sctp_sndinfo {
+ uint16_t snd_sid;
+ uint16_t snd_flags;
+ uint32_t snd_ppid;
+ uint32_t snd_context;
+};
+
+struct bio_dgram_sctp_rcvinfo {
+ uint16_t rcv_sid;
+ uint16_t rcv_ssn;
+ uint16_t rcv_flags;
+ uint32_t rcv_ppid;
+ uint32_t rcv_tsn;
+ uint32_t rcv_cumtsn;
+ uint32_t rcv_context;
+};
+
+struct bio_dgram_sctp_prinfo {
+ uint16_t pr_policy;
+ uint32_t pr_value;
+};
+# endif
+
+/*
+ * #define BIO_CONN_get_param_hostname BIO_ctrl
+ */
+
+# define BIO_C_SET_CONNECT 100
+# define BIO_C_DO_STATE_MACHINE 101
+# define BIO_C_SET_NBIO 102
+/* # define BIO_C_SET_PROXY_PARAM 103 */
+# define BIO_C_SET_FD 104
+# define BIO_C_GET_FD 105
+# define BIO_C_SET_FILE_PTR 106
+# define BIO_C_GET_FILE_PTR 107
+# define BIO_C_SET_FILENAME 108
+# define BIO_C_SET_SSL 109
+# define BIO_C_GET_SSL 110
+# define BIO_C_SET_MD 111
+# define BIO_C_GET_MD 112
+# define BIO_C_GET_CIPHER_STATUS 113
+# define BIO_C_SET_BUF_MEM 114
+# define BIO_C_GET_BUF_MEM_PTR 115
+# define BIO_C_GET_BUFF_NUM_LINES 116
+# define BIO_C_SET_BUFF_SIZE 117
+# define BIO_C_SET_ACCEPT 118
+# define BIO_C_SSL_MODE 119
+# define BIO_C_GET_MD_CTX 120
+/* # define BIO_C_GET_PROXY_PARAM 121 */
+# define BIO_C_SET_BUFF_READ_DATA 122/* data to read first */
+# define BIO_C_GET_CONNECT 123
+# define BIO_C_GET_ACCEPT 124
+# define BIO_C_SET_SSL_RENEGOTIATE_BYTES 125
+# define BIO_C_GET_SSL_NUM_RENEGOTIATES 126
+# define BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT 127
+# define BIO_C_FILE_SEEK 128
+# define BIO_C_GET_CIPHER_CTX 129
+# define BIO_C_SET_BUF_MEM_EOF_RETURN 130/* return end of input
+ * value */
+# define BIO_C_SET_BIND_MODE 131
+# define BIO_C_GET_BIND_MODE 132
+# define BIO_C_FILE_TELL 133
+# define BIO_C_GET_SOCKS 134
+# define BIO_C_SET_SOCKS 135
+
+# define BIO_C_SET_WRITE_BUF_SIZE 136/* for BIO_s_bio */
+# define BIO_C_GET_WRITE_BUF_SIZE 137
+# define BIO_C_MAKE_BIO_PAIR 138
+# define BIO_C_DESTROY_BIO_PAIR 139
+# define BIO_C_GET_WRITE_GUARANTEE 140
+# define BIO_C_GET_READ_REQUEST 141
+# define BIO_C_SHUTDOWN_WR 142
+# define BIO_C_NREAD0 143
+# define BIO_C_NREAD 144
+# define BIO_C_NWRITE0 145
+# define BIO_C_NWRITE 146
+# define BIO_C_RESET_READ_REQUEST 147
+# define BIO_C_SET_MD_CTX 148
+
+# define BIO_C_SET_PREFIX 149
+# define BIO_C_GET_PREFIX 150
+# define BIO_C_SET_SUFFIX 151
+# define BIO_C_GET_SUFFIX 152
+
+# define BIO_C_SET_EX_ARG 153
+# define BIO_C_GET_EX_ARG 154
+
+# define BIO_C_SET_CONNECT_MODE 155
+
+# define BIO_set_app_data(s,arg) BIO_set_ex_data(s,0,arg)
+# define BIO_get_app_data(s) BIO_get_ex_data(s,0)
+
+# define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL)
+
+# ifndef OPENSSL_NO_SOCK
+/* IP families we support, for BIO_s_connect() and BIO_s_accept() */
+/* Note: the underlying operating system may not support some of them */
+# define BIO_FAMILY_IPV4 4
+# define BIO_FAMILY_IPV6 6
+# define BIO_FAMILY_IPANY 256
+
+/* BIO_s_connect() */
+# define BIO_set_conn_hostname(b,name) BIO_ctrl(b,BIO_C_SET_CONNECT,0, \
+ (char *)(name))
+# define BIO_set_conn_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,1, \
+ (char *)(port))
+# define BIO_set_conn_address(b,addr) BIO_ctrl(b,BIO_C_SET_CONNECT,2, \
+ (char *)(addr))
+# define BIO_set_conn_ip_family(b,f) BIO_int_ctrl(b,BIO_C_SET_CONNECT,3,f)
+# define BIO_get_conn_hostname(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,0))
+# define BIO_get_conn_port(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1))
+# define BIO_get_conn_address(b) ((const BIO_ADDR *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2))
+# define BIO_get_conn_ip_family(b) BIO_ctrl(b,BIO_C_GET_CONNECT,3,NULL)
+# define BIO_set_conn_mode(b,n) BIO_ctrl(b,BIO_C_SET_CONNECT_MODE,(n),NULL)
+
+/* BIO_s_accept() */
+# define BIO_set_accept_name(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0, \
+ (char *)(name))
+# define BIO_set_accept_port(b,port) BIO_ctrl(b,BIO_C_SET_ACCEPT,1, \
+ (char *)(port))
+# define BIO_get_accept_name(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,0))
+# define BIO_get_accept_port(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,1))
+# define BIO_get_peer_name(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,2))
+# define BIO_get_peer_port(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,3))
+/* #define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) */
+# define BIO_set_nbio_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,2,(n)?(void *)"a":NULL)
+# define BIO_set_accept_bios(b,bio) BIO_ctrl(b,BIO_C_SET_ACCEPT,3, \
+ (char *)(bio))
+# define BIO_set_accept_ip_family(b,f) BIO_int_ctrl(b,BIO_C_SET_ACCEPT,4,f)
+# define BIO_get_accept_ip_family(b) BIO_ctrl(b,BIO_C_GET_ACCEPT,4,NULL)
+
+/* Aliases kept for backward compatibility */
+# define BIO_BIND_NORMAL 0
+# define BIO_BIND_REUSEADDR BIO_SOCK_REUSEADDR
+# define BIO_BIND_REUSEADDR_IF_UNUSED BIO_SOCK_REUSEADDR
+# define BIO_set_bind_mode(b,mode) BIO_ctrl(b,BIO_C_SET_BIND_MODE,mode,NULL)
+# define BIO_get_bind_mode(b) BIO_ctrl(b,BIO_C_GET_BIND_MODE,0,NULL)
+# endif /* OPENSSL_NO_SOCK */
+
+# define BIO_do_connect(b) BIO_do_handshake(b)
+# define BIO_do_accept(b) BIO_do_handshake(b)
+
+# define BIO_do_handshake(b) BIO_ctrl(b,BIO_C_DO_STATE_MACHINE,0,NULL)
+
+/* BIO_s_datagram(), BIO_s_fd(), BIO_s_socket(), BIO_s_accept() and BIO_s_connect() */
+# define BIO_set_fd(b,fd,c) BIO_int_ctrl(b,BIO_C_SET_FD,c,fd)
+# define BIO_get_fd(b,c) BIO_ctrl(b,BIO_C_GET_FD,0,(char *)(c))
+
+/* BIO_s_file() */
+# define BIO_set_fp(b,fp,c) BIO_ctrl(b,BIO_C_SET_FILE_PTR,c,(char *)(fp))
+# define BIO_get_fp(b,fpp) BIO_ctrl(b,BIO_C_GET_FILE_PTR,0,(char *)(fpp))
+
+/* BIO_s_fd() and BIO_s_file() */
+# define BIO_seek(b,ofs) (int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL)
+# define BIO_tell(b) (int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL)
+
+/*
+ * name is cast to lose const, but might be better to route through a
+ * function so we can do it safely
+ */
+# ifdef CONST_STRICT
+/*
+ * If you are wondering why this isn't defined, its because CONST_STRICT is
+ * purely a compile-time kludge to allow const to be checked.
+ */
+int BIO_read_filename(BIO *b, const char *name);
+# else
+# define BIO_read_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \
+ BIO_CLOSE|BIO_FP_READ,(char *)(name))
+# endif
+# define BIO_write_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \
+ BIO_CLOSE|BIO_FP_WRITE,name)
+# define BIO_append_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \
+ BIO_CLOSE|BIO_FP_APPEND,name)
+# define BIO_rw_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \
+ BIO_CLOSE|BIO_FP_READ|BIO_FP_WRITE,name)
+
+/*
+ * WARNING WARNING, this ups the reference count on the read bio of the SSL
+ * structure. This is because the ssl read BIO is now pointed to by the
+ * next_bio field in the bio. So when you free the BIO, make sure you are
+ * doing a BIO_free_all() to catch the underlying BIO.
+ */
+# define BIO_set_ssl(b,ssl,c) BIO_ctrl(b,BIO_C_SET_SSL,c,(char *)(ssl))
+# define BIO_get_ssl(b,sslp) BIO_ctrl(b,BIO_C_GET_SSL,0,(char *)(sslp))
+# define BIO_set_ssl_mode(b,client) BIO_ctrl(b,BIO_C_SSL_MODE,client,NULL)
+# define BIO_set_ssl_renegotiate_bytes(b,num) \
+ BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_BYTES,num,NULL)
+# define BIO_get_num_renegotiates(b) \
+ BIO_ctrl(b,BIO_C_GET_SSL_NUM_RENEGOTIATES,0,NULL)
+# define BIO_set_ssl_renegotiate_timeout(b,seconds) \
+ BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT,seconds,NULL)
+
+/* defined in evp.h */
+/* #define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,1,(char *)(md)) */
+
+# define BIO_get_mem_data(b,pp) BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)(pp))
+# define BIO_set_mem_buf(b,bm,c) BIO_ctrl(b,BIO_C_SET_BUF_MEM,c,(char *)(bm))
+# define BIO_get_mem_ptr(b,pp) BIO_ctrl(b,BIO_C_GET_BUF_MEM_PTR,0, \
+ (char *)(pp))
+# define BIO_set_mem_eof_return(b,v) \
+ BIO_ctrl(b,BIO_C_SET_BUF_MEM_EOF_RETURN,v,NULL)
+
+/* For the BIO_f_buffer() type */
+# define BIO_get_buffer_num_lines(b) BIO_ctrl(b,BIO_C_GET_BUFF_NUM_LINES,0,NULL)
+# define BIO_set_buffer_size(b,size) BIO_ctrl(b,BIO_C_SET_BUFF_SIZE,size,NULL)
+# define BIO_set_read_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,0)
+# define BIO_set_write_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,1)
+# define BIO_set_buffer_read_data(b,buf,num) BIO_ctrl(b,BIO_C_SET_BUFF_READ_DATA,num,buf)
+
+/* Don't use the next one unless you know what you are doing :-) */
+# define BIO_dup_state(b,ret) BIO_ctrl(b,BIO_CTRL_DUP,0,(char *)(ret))
+
+# define BIO_reset(b) (int)BIO_ctrl(b,BIO_CTRL_RESET,0,NULL)
+# define BIO_eof(b) (int)BIO_ctrl(b,BIO_CTRL_EOF,0,NULL)
+# define BIO_set_close(b,c) (int)BIO_ctrl(b,BIO_CTRL_SET_CLOSE,(c),NULL)
+# define BIO_get_close(b) (int)BIO_ctrl(b,BIO_CTRL_GET_CLOSE,0,NULL)
+# define BIO_pending(b) (int)BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL)
+# define BIO_wpending(b) (int)BIO_ctrl(b,BIO_CTRL_WPENDING,0,NULL)
+/* ...pending macros have inappropriate return type */
+size_t BIO_ctrl_pending(BIO *b);
+size_t BIO_ctrl_wpending(BIO *b);
+# define BIO_flush(b) (int)BIO_ctrl(b,BIO_CTRL_FLUSH,0,NULL)
+# define BIO_get_info_callback(b,cbp) (int)BIO_ctrl(b,BIO_CTRL_GET_CALLBACK,0, \
+ cbp)
+# define BIO_set_info_callback(b,cb) (int)BIO_callback_ctrl(b,BIO_CTRL_SET_CALLBACK,cb)
+
+/* For the BIO_f_buffer() type */
+# define BIO_buffer_get_num_lines(b) BIO_ctrl(b,BIO_CTRL_GET,0,NULL)
+# define BIO_buffer_peek(b,s,l) BIO_ctrl(b,BIO_CTRL_PEEK,(l),(s))
+
+/* For BIO_s_bio() */
+# define BIO_set_write_buf_size(b,size) (int)BIO_ctrl(b,BIO_C_SET_WRITE_BUF_SIZE,size,NULL)
+# define BIO_get_write_buf_size(b,size) (size_t)BIO_ctrl(b,BIO_C_GET_WRITE_BUF_SIZE,size,NULL)
+# define BIO_make_bio_pair(b1,b2) (int)BIO_ctrl(b1,BIO_C_MAKE_BIO_PAIR,0,b2)
+# define BIO_destroy_bio_pair(b) (int)BIO_ctrl(b,BIO_C_DESTROY_BIO_PAIR,0,NULL)
+# define BIO_shutdown_wr(b) (int)BIO_ctrl(b, BIO_C_SHUTDOWN_WR, 0, NULL)
+/* macros with inappropriate type -- but ...pending macros use int too: */
+# define BIO_get_write_guarantee(b) (int)BIO_ctrl(b,BIO_C_GET_WRITE_GUARANTEE,0,NULL)
+# define BIO_get_read_request(b) (int)BIO_ctrl(b,BIO_C_GET_READ_REQUEST,0,NULL)
+size_t BIO_ctrl_get_write_guarantee(BIO *b);
+size_t BIO_ctrl_get_read_request(BIO *b);
+int BIO_ctrl_reset_read_request(BIO *b);
+
+/* ctrl macros for dgram */
+# define BIO_ctrl_dgram_connect(b,peer) \
+ (int)BIO_ctrl(b,BIO_CTRL_DGRAM_CONNECT,0, (char *)(peer))
+# define BIO_ctrl_set_connected(b,peer) \
+ (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_CONNECTED, 0, (char *)(peer))
+# define BIO_dgram_recv_timedout(b) \
+ (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP, 0, NULL)
+# define BIO_dgram_send_timedout(b) \
+ (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP, 0, NULL)
+# define BIO_dgram_get_peer(b,peer) \
+ (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, (char *)(peer))
+# define BIO_dgram_set_peer(b,peer) \
+ (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)(peer))
+# define BIO_dgram_get_mtu_overhead(b) \
+ (unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU_OVERHEAD, 0, NULL)
+
+/* ctrl macros for BIO_f_prefix */
+# define BIO_set_prefix(b,p) BIO_ctrl((b), BIO_CTRL_SET_PREFIX, 0, (void *)(p))
+# define BIO_set_indent(b,i) BIO_ctrl((b), BIO_CTRL_SET_INDENT, (i), NULL)
+# define BIO_get_indent(b) BIO_ctrl((b), BIO_CTRL_GET_INDENT, 0, NULL)
+
+#define BIO_get_ex_new_index(l, p, newf, dupf, freef) \
+ CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, l, p, newf, dupf, freef)
+int BIO_set_ex_data(BIO *bio, int idx, void *data);
+void *BIO_get_ex_data(const BIO *bio, int idx);
+uint64_t BIO_number_read(BIO *bio);
+uint64_t BIO_number_written(BIO *bio);
+
+/* For BIO_f_asn1() */
+int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix,
+ asn1_ps_func *prefix_free);
+int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix,
+ asn1_ps_func **pprefix_free);
+int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix,
+ asn1_ps_func *suffix_free);
+int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix,
+ asn1_ps_func **psuffix_free);
+
+const BIO_METHOD *BIO_s_file(void);
+BIO *BIO_new_file(const char *filename, const char *mode);
+BIO *BIO_new_from_core_bio(OSSL_LIB_CTX *libctx, OSSL_CORE_BIO *corebio);
+# ifndef OPENSSL_NO_STDIO
+BIO *BIO_new_fp(FILE *stream, int close_flag);
+# endif
+BIO *BIO_new_ex(OSSL_LIB_CTX *libctx, const BIO_METHOD *method);
+BIO *BIO_new(const BIO_METHOD *type);
+int BIO_free(BIO *a);
+void BIO_set_data(BIO *a, void *ptr);
+void *BIO_get_data(BIO *a);
+void BIO_set_init(BIO *a, int init);
+int BIO_get_init(BIO *a);
+void BIO_set_shutdown(BIO *a, int shut);
+int BIO_get_shutdown(BIO *a);
+void BIO_vfree(BIO *a);
+int BIO_up_ref(BIO *a);
+int BIO_read(BIO *b, void *data, int dlen);
+int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes);
+int BIO_gets(BIO *bp, char *buf, int size);
+int BIO_get_line(BIO *bio, char *buf, int size);
+int BIO_write(BIO *b, const void *data, int dlen);
+int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written);
+int BIO_puts(BIO *bp, const char *buf);
+int BIO_indent(BIO *b, int indent, int max);
+long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg);
+long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp);
+void *BIO_ptr_ctrl(BIO *bp, int cmd, long larg);
+long BIO_int_ctrl(BIO *bp, int cmd, long larg, int iarg);
+BIO *BIO_push(BIO *b, BIO *append);
+BIO *BIO_pop(BIO *b);
+void BIO_free_all(BIO *a);
+BIO *BIO_find_type(BIO *b, int bio_type);
+BIO *BIO_next(BIO *b);
+void BIO_set_next(BIO *b, BIO *next);
+BIO *BIO_get_retry_BIO(BIO *bio, int *reason);
+int BIO_get_retry_reason(BIO *bio);
+void BIO_set_retry_reason(BIO *bio, int reason);
+BIO *BIO_dup_chain(BIO *in);
+
+int BIO_nread0(BIO *bio, char **buf);
+int BIO_nread(BIO *bio, char **buf, int num);
+int BIO_nwrite0(BIO *bio, char **buf);
+int BIO_nwrite(BIO *bio, char **buf, int num);
+
+const BIO_METHOD *BIO_s_mem(void);
+const BIO_METHOD *BIO_s_secmem(void);
+BIO *BIO_new_mem_buf(const void *buf, int len);
+# ifndef OPENSSL_NO_SOCK
+const BIO_METHOD *BIO_s_socket(void);
+const BIO_METHOD *BIO_s_connect(void);
+const BIO_METHOD *BIO_s_accept(void);
+# endif
+const BIO_METHOD *BIO_s_fd(void);
+const BIO_METHOD *BIO_s_log(void);
+const BIO_METHOD *BIO_s_bio(void);
+const BIO_METHOD *BIO_s_null(void);
+const BIO_METHOD *BIO_f_null(void);
+const BIO_METHOD *BIO_f_buffer(void);
+const BIO_METHOD *BIO_f_readbuffer(void);
+const BIO_METHOD *BIO_f_linebuffer(void);
+const BIO_METHOD *BIO_f_nbio_test(void);
+const BIO_METHOD *BIO_f_prefix(void);
+const BIO_METHOD *BIO_s_core(void);
+# ifndef OPENSSL_NO_DGRAM
+const BIO_METHOD *BIO_s_datagram(void);
+int BIO_dgram_non_fatal_error(int error);
+BIO *BIO_new_dgram(int fd, int close_flag);
+# ifndef OPENSSL_NO_SCTP
+const BIO_METHOD *BIO_s_datagram_sctp(void);
+BIO *BIO_new_dgram_sctp(int fd, int close_flag);
+int BIO_dgram_is_sctp(BIO *bio);
+int BIO_dgram_sctp_notification_cb(BIO *b,
+ BIO_dgram_sctp_notification_handler_fn handle_notifications,
+ void *context);
+int BIO_dgram_sctp_wait_for_dry(BIO *b);
+int BIO_dgram_sctp_msg_waiting(BIO *b);
+# endif
+# endif
+
+# ifndef OPENSSL_NO_SOCK
+int BIO_sock_should_retry(int i);
+int BIO_sock_non_fatal_error(int error);
+int BIO_socket_wait(int fd, int for_read, time_t max_time);
+# endif
+int BIO_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds);
+int BIO_do_connect_retry(BIO *bio, int timeout, int nap_milliseconds);
+
+int BIO_fd_should_retry(int i);
+int BIO_fd_non_fatal_error(int error);
+int BIO_dump_cb(int (*cb) (const void *data, size_t len, void *u),
+ void *u, const void *s, int len);
+int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u),
+ void *u, const void *s, int len, int indent);
+int BIO_dump(BIO *b, const void *bytes, int len);
+int BIO_dump_indent(BIO *b, const void *bytes, int len, int indent);
+# ifndef OPENSSL_NO_STDIO
+int BIO_dump_fp(FILE *fp, const void *s, int len);
+int BIO_dump_indent_fp(FILE *fp, const void *s, int len, int indent);
+# endif
+int BIO_hex_string(BIO *out, int indent, int width, const void *data,
+ int datalen);
+
+# ifndef OPENSSL_NO_SOCK
+BIO_ADDR *BIO_ADDR_new(void);
+int BIO_ADDR_rawmake(BIO_ADDR *ap, int family,
+ const void *where, size_t wherelen, unsigned short port);
+void BIO_ADDR_free(BIO_ADDR *);
+void BIO_ADDR_clear(BIO_ADDR *ap);
+int BIO_ADDR_family(const BIO_ADDR *ap);
+int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l);
+unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap);
+char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric);
+char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric);
+char *BIO_ADDR_path_string(const BIO_ADDR *ap);
+
+const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai);
+int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai);
+int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai);
+int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai);
+const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai);
+void BIO_ADDRINFO_free(BIO_ADDRINFO *bai);
+
+enum BIO_hostserv_priorities {
+ BIO_PARSE_PRIO_HOST, BIO_PARSE_PRIO_SERV
+};
+int BIO_parse_hostserv(const char *hostserv, char **host, char **service,
+ enum BIO_hostserv_priorities hostserv_prio);
+enum BIO_lookup_type {
+ BIO_LOOKUP_CLIENT, BIO_LOOKUP_SERVER
+};
+int BIO_lookup(const char *host, const char *service,
+ enum BIO_lookup_type lookup_type,
+ int family, int socktype, BIO_ADDRINFO **res);
+int BIO_lookup_ex(const char *host, const char *service,
+ int lookup_type, int family, int socktype, int protocol,
+ BIO_ADDRINFO **res);
+int BIO_sock_error(int sock);
+int BIO_socket_ioctl(int fd, long type, void *arg);
+int BIO_socket_nbio(int fd, int mode);
+int BIO_sock_init(void);
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define BIO_sock_cleanup() while(0) continue
+# endif
+int BIO_set_tcp_ndelay(int sock, int turn_on);
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 struct hostent *BIO_gethostbyname(const char *name);
+OSSL_DEPRECATEDIN_1_1_0 int BIO_get_port(const char *str, unsigned short *port_ptr);
+OSSL_DEPRECATEDIN_1_1_0 int BIO_get_host_ip(const char *str, unsigned char *ip);
+OSSL_DEPRECATEDIN_1_1_0 int BIO_get_accept_socket(char *host_port, int mode);
+OSSL_DEPRECATEDIN_1_1_0 int BIO_accept(int sock, char **ip_port);
+# endif
+
+union BIO_sock_info_u {
+ BIO_ADDR *addr;
+};
+enum BIO_sock_info_type {
+ BIO_SOCK_INFO_ADDRESS
+};
+int BIO_sock_info(int sock,
+ enum BIO_sock_info_type type, union BIO_sock_info_u *info);
+
+# define BIO_SOCK_REUSEADDR 0x01
+# define BIO_SOCK_V6_ONLY 0x02
+# define BIO_SOCK_KEEPALIVE 0x04
+# define BIO_SOCK_NONBLOCK 0x08
+# define BIO_SOCK_NODELAY 0x10
+
+int BIO_socket(int domain, int socktype, int protocol, int options);
+int BIO_connect(int sock, const BIO_ADDR *addr, int options);
+int BIO_bind(int sock, const BIO_ADDR *addr, int options);
+int BIO_listen(int sock, const BIO_ADDR *addr, int options);
+int BIO_accept_ex(int accept_sock, BIO_ADDR *addr, int options);
+int BIO_closesocket(int sock);
+
+BIO *BIO_new_socket(int sock, int close_flag);
+BIO *BIO_new_connect(const char *host_port);
+BIO *BIO_new_accept(const char *host_port);
+# endif /* OPENSSL_NO_SOCK*/
+
+BIO *BIO_new_fd(int fd, int close_flag);
+
+int BIO_new_bio_pair(BIO **bio1, size_t writebuf1,
+ BIO **bio2, size_t writebuf2);
+/*
+ * If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints.
+ * Otherwise returns 0 and sets *bio1 and *bio2 to NULL. Size 0 uses default
+ * value.
+ */
+
+void BIO_copy_next_retry(BIO *b);
+
+/*
+ * long BIO_ghbn_ctrl(int cmd,int iarg,char *parg);
+ */
+
+# define ossl_bio__attr__(x)
+# if defined(__GNUC__) && defined(__STDC_VERSION__) \
+ && !defined(__MINGW32__) && !defined(__MINGW64__) \
+ && !defined(__APPLE__)
+ /*
+ * Because we support the 'z' modifier, which made its appearance in C99,
+ * we can't use __attribute__ with pre C99 dialects.
+ */
+# if __STDC_VERSION__ >= 199901L
+# undef ossl_bio__attr__
+# define ossl_bio__attr__ __attribute__
+# if __GNUC__*10 + __GNUC_MINOR__ >= 44
+# define ossl_bio__printf__ __gnu_printf__
+# else
+# define ossl_bio__printf__ __printf__
+# endif
+# endif
+# endif
+int BIO_printf(BIO *bio, const char *format, ...)
+ossl_bio__attr__((__format__(ossl_bio__printf__, 2, 3)));
+int BIO_vprintf(BIO *bio, const char *format, va_list args)
+ossl_bio__attr__((__format__(ossl_bio__printf__, 2, 0)));
+int BIO_snprintf(char *buf, size_t n, const char *format, ...)
+ossl_bio__attr__((__format__(ossl_bio__printf__, 3, 4)));
+int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
+ossl_bio__attr__((__format__(ossl_bio__printf__, 3, 0)));
+# undef ossl_bio__attr__
+# undef ossl_bio__printf__
+
+
+BIO_METHOD *BIO_meth_new(int type, const char *name);
+void BIO_meth_free(BIO_METHOD *biom);
+int (*BIO_meth_get_write(const BIO_METHOD *biom)) (BIO *, const char *, int);
+int (*BIO_meth_get_write_ex(const BIO_METHOD *biom)) (BIO *, const char *, size_t,
+ size_t *);
+int BIO_meth_set_write(BIO_METHOD *biom,
+ int (*write) (BIO *, const char *, int));
+int BIO_meth_set_write_ex(BIO_METHOD *biom,
+ int (*bwrite) (BIO *, const char *, size_t, size_t *));
+int (*BIO_meth_get_read(const BIO_METHOD *biom)) (BIO *, char *, int);
+int (*BIO_meth_get_read_ex(const BIO_METHOD *biom)) (BIO *, char *, size_t, size_t *);
+int BIO_meth_set_read(BIO_METHOD *biom,
+ int (*read) (BIO *, char *, int));
+int BIO_meth_set_read_ex(BIO_METHOD *biom,
+ int (*bread) (BIO *, char *, size_t, size_t *));
+int (*BIO_meth_get_puts(const BIO_METHOD *biom)) (BIO *, const char *);
+int BIO_meth_set_puts(BIO_METHOD *biom,
+ int (*puts) (BIO *, const char *));
+int (*BIO_meth_get_gets(const BIO_METHOD *biom)) (BIO *, char *, int);
+int BIO_meth_set_gets(BIO_METHOD *biom,
+ int (*gets) (BIO *, char *, int));
+long (*BIO_meth_get_ctrl(const BIO_METHOD *biom)) (BIO *, int, long, void *);
+int BIO_meth_set_ctrl(BIO_METHOD *biom,
+ long (*ctrl) (BIO *, int, long, void *));
+int (*BIO_meth_get_create(const BIO_METHOD *bion)) (BIO *);
+int BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *));
+int (*BIO_meth_get_destroy(const BIO_METHOD *biom)) (BIO *);
+int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *));
+long (*BIO_meth_get_callback_ctrl(const BIO_METHOD *biom))
+ (BIO *, int, BIO_info_cb *);
+int BIO_meth_set_callback_ctrl(BIO_METHOD *biom,
+ long (*callback_ctrl) (BIO *, int,
+ BIO_info_cb *));
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/bioerr.h b/include/openssl/bioerr.h
index 46e2c96ee354..787b30afceb3 100644
--- a/include/openssl/bioerr.h
+++ b/include/openssl/bioerr.h
@@ -1,84 +1,22 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_BIOERR_H
-# define HEADER_BIOERR_H
+#ifndef OPENSSL_BIOERR_H
+# define OPENSSL_BIOERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_BIO_strings(void);
-/*
- * BIO function codes.
- */
-# define BIO_F_ACPT_STATE 100
-# define BIO_F_ADDRINFO_WRAP 148
-# define BIO_F_ADDR_STRINGS 134
-# define BIO_F_BIO_ACCEPT 101
-# define BIO_F_BIO_ACCEPT_EX 137
-# define BIO_F_BIO_ACCEPT_NEW 152
-# define BIO_F_BIO_ADDR_NEW 144
-# define BIO_F_BIO_BIND 147
-# define BIO_F_BIO_CALLBACK_CTRL 131
-# define BIO_F_BIO_CONNECT 138
-# define BIO_F_BIO_CONNECT_NEW 153
-# define BIO_F_BIO_CTRL 103
-# define BIO_F_BIO_GETS 104
-# define BIO_F_BIO_GET_HOST_IP 106
-# define BIO_F_BIO_GET_NEW_INDEX 102
-# define BIO_F_BIO_GET_PORT 107
-# define BIO_F_BIO_LISTEN 139
-# define BIO_F_BIO_LOOKUP 135
-# define BIO_F_BIO_LOOKUP_EX 143
-# define BIO_F_BIO_MAKE_PAIR 121
-# define BIO_F_BIO_METH_NEW 146
-# define BIO_F_BIO_NEW 108
-# define BIO_F_BIO_NEW_DGRAM_SCTP 145
-# define BIO_F_BIO_NEW_FILE 109
-# define BIO_F_BIO_NEW_MEM_BUF 126
-# define BIO_F_BIO_NREAD 123
-# define BIO_F_BIO_NREAD0 124
-# define BIO_F_BIO_NWRITE 125
-# define BIO_F_BIO_NWRITE0 122
-# define BIO_F_BIO_PARSE_HOSTSERV 136
-# define BIO_F_BIO_PUTS 110
-# define BIO_F_BIO_READ 111
-# define BIO_F_BIO_READ_EX 105
-# define BIO_F_BIO_READ_INTERN 120
-# define BIO_F_BIO_SOCKET 140
-# define BIO_F_BIO_SOCKET_NBIO 142
-# define BIO_F_BIO_SOCK_INFO 141
-# define BIO_F_BIO_SOCK_INIT 112
-# define BIO_F_BIO_WRITE 113
-# define BIO_F_BIO_WRITE_EX 119
-# define BIO_F_BIO_WRITE_INTERN 128
-# define BIO_F_BUFFER_CTRL 114
-# define BIO_F_CONN_CTRL 127
-# define BIO_F_CONN_STATE 115
-# define BIO_F_DGRAM_SCTP_NEW 149
-# define BIO_F_DGRAM_SCTP_READ 132
-# define BIO_F_DGRAM_SCTP_WRITE 133
-# define BIO_F_DOAPR_OUTCH 150
-# define BIO_F_FILE_CTRL 116
-# define BIO_F_FILE_READ 130
-# define BIO_F_LINEBUFFER_CTRL 129
-# define BIO_F_LINEBUFFER_NEW 151
-# define BIO_F_MEM_WRITE 117
-# define BIO_F_NBIOF_NEW 154
-# define BIO_F_SLG_WRITE 155
-# define BIO_F_SSL_NEW 118
/*
* BIO reason codes.
@@ -89,6 +27,7 @@ int ERR_load_BIO_strings(void);
# define BIO_R_BAD_FOPEN_MODE 101
# define BIO_R_BROKEN_PIPE 124
# define BIO_R_CONNECT_ERROR 103
+# define BIO_R_CONNECT_TIMEOUT 147
# define BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET 107
# define BIO_R_GETSOCKNAME_ERROR 132
# define BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS 133
@@ -105,7 +44,9 @@ int ERR_load_BIO_strings(void);
# define BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED 144
# define BIO_R_NO_PORT_DEFINED 113
# define BIO_R_NO_SUCH_FILE 128
-# define BIO_R_NULL_PARAMETER 115
+# define BIO_R_NULL_PARAMETER 115 /* unused */
+# define BIO_R_TRANSFER_ERROR 104
+# define BIO_R_TRANSFER_TIMEOUT 105
# define BIO_R_UNABLE_TO_BIND_SOCKET 117
# define BIO_R_UNABLE_TO_CREATE_SOCKET 118
# define BIO_R_UNABLE_TO_KEEPALIVE 137
diff --git a/include/openssl/blowfish.h b/include/openssl/blowfish.h
index cd3e460e98f3..667d6423912b 100644
--- a/include/openssl/blowfish.h
+++ b/include/openssl/blowfish.h
@@ -1,14 +1,20 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_BLOWFISH_H
-# define HEADER_BLOWFISH_H
+#ifndef OPENSSL_BLOWFISH_H
+# define OPENSSL_BLOWFISH_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_BLOWFISH_H
+# endif
# include <openssl/opensslconf.h>
@@ -18,40 +24,51 @@
extern "C" {
# endif
-# define BF_ENCRYPT 1
-# define BF_DECRYPT 0
+# define BF_BLOCK 8
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+
+# define BF_ENCRYPT 1
+# define BF_DECRYPT 0
/*-
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* ! BF_LONG has to be at least 32 bits wide. !
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
-# define BF_LONG unsigned int
+# define BF_LONG unsigned int
-# define BF_ROUNDS 16
-# define BF_BLOCK 8
+# define BF_ROUNDS 16
typedef struct bf_key_st {
BF_LONG P[BF_ROUNDS + 2];
BF_LONG S[4 * 256];
} BF_KEY;
-void BF_set_key(BF_KEY *key, int len, const unsigned char *data);
-
-void BF_encrypt(BF_LONG *data, const BF_KEY *key);
-void BF_decrypt(BF_LONG *data, const BF_KEY *key);
-
-void BF_ecb_encrypt(const unsigned char *in, unsigned char *out,
- const BF_KEY *key, int enc);
-void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
- const BF_KEY *schedule, unsigned char *ivec, int enc);
-void BF_cfb64_encrypt(const unsigned char *in, unsigned char *out,
- long length, const BF_KEY *schedule,
- unsigned char *ivec, int *num, int enc);
-void BF_ofb64_encrypt(const unsigned char *in, unsigned char *out,
- long length, const BF_KEY *schedule,
- unsigned char *ivec, int *num);
-const char *BF_options(void);
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 void BF_set_key(BF_KEY *key, int len,
+ const unsigned char *data);
+OSSL_DEPRECATEDIN_3_0 void BF_encrypt(BF_LONG *data, const BF_KEY *key);
+OSSL_DEPRECATEDIN_3_0 void BF_decrypt(BF_LONG *data, const BF_KEY *key);
+OSSL_DEPRECATEDIN_3_0 void BF_ecb_encrypt(const unsigned char *in,
+ unsigned char *out, const BF_KEY *key,
+ int enc);
+OSSL_DEPRECATEDIN_3_0 void BF_cbc_encrypt(const unsigned char *in,
+ unsigned char *out, long length,
+ const BF_KEY *schedule,
+ unsigned char *ivec, int enc);
+OSSL_DEPRECATEDIN_3_0 void BF_cfb64_encrypt(const unsigned char *in,
+ unsigned char *out,
+ long length, const BF_KEY *schedule,
+ unsigned char *ivec, int *num,
+ int enc);
+OSSL_DEPRECATEDIN_3_0 void BF_ofb64_encrypt(const unsigned char *in,
+ unsigned char *out,
+ long length, const BF_KEY *schedule,
+ unsigned char *ivec, int *num);
+OSSL_DEPRECATEDIN_3_0 const char *BF_options(void);
+# endif
# ifdef __cplusplus
}
diff --git a/include/openssl/bn.h b/include/openssl/bn.h
index d87766049a42..ecd7f01b9bed 100644
--- a/include/openssl/bn.h
+++ b/include/openssl/bn.h
@@ -1,22 +1,28 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_BN_H
-# define HEADER_BN_H
+#ifndef OPENSSL_BN_H
+# define OPENSSL_BN_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_BN_H
+# endif
# include <openssl/e_os2.h>
# ifndef OPENSSL_NO_STDIO
# include <stdio.h>
# endif
# include <openssl/opensslconf.h>
-# include <openssl/ossl_typ.h>
+# include <openssl/types.h>
# include <openssl/crypto.h>
# include <openssl/bnerr.h>
@@ -61,7 +67,7 @@ extern "C" {
# define BN_FLG_CONSTTIME 0x04
# define BN_FLG_SECURE 0x08
-# if OPENSSL_API_COMPAT < 0x00908000L
+# ifndef OPENSSL_NO_DEPRECATED_0_9_8
/* deprecated name for the flag */
# define BN_FLG_EXP_CONSTTIME BN_FLG_CONSTTIME
# define BN_FLG_FREE 0x8000 /* used for debugging */
@@ -103,8 +109,9 @@ void BN_GENCB_set(BN_GENCB *gencb, int (*callback) (int, int, BN_GENCB *),
void *BN_GENCB_get_arg(BN_GENCB *cb);
-# define BN_prime_checks 0 /* default: select number of iterations based
- * on the size of the number */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define BN_prime_checks 0 /* default: select number of iterations based
+ * on the size of the number */
/*
* BN_prime_checks_for_size() returns the number of Miller-Rabin iterations
@@ -169,14 +176,15 @@ void *BN_GENCB_get_arg(BN_GENCB *cb);
* (b) >= 6 | >= 12 | 34 | 64 bit
*/
-# define BN_prime_checks_for_size(b) ((b) >= 3747 ? 3 : \
- (b) >= 1345 ? 4 : \
- (b) >= 476 ? 5 : \
- (b) >= 400 ? 6 : \
- (b) >= 347 ? 7 : \
- (b) >= 308 ? 8 : \
- (b) >= 55 ? 27 : \
- /* b >= 6 */ 34)
+# define BN_prime_checks_for_size(b) ((b) >= 3747 ? 3 : \
+ (b) >= 1345 ? 4 : \
+ (b) >= 476 ? 5 : \
+ (b) >= 400 ? 6 : \
+ (b) >= 347 ? 7 : \
+ (b) >= 308 ? 8 : \
+ (b) >= 55 ? 27 : \
+ /* b >= 6 */ 34)
+# endif
# define BN_num_bytes(a) ((BN_num_bits(a)+7)/8)
@@ -190,7 +198,7 @@ int BN_is_odd(const BIGNUM *a);
void BN_zero_ex(BIGNUM *a);
-# if OPENSSL_API_COMPAT >= 0x00908000L
+# if OPENSSL_API_LEVEL > 908
# define BN_zero(a) BN_zero_ex(a)
# else
# define BN_zero(a) (BN_set_word((a),0))
@@ -198,18 +206,32 @@ void BN_zero_ex(BIGNUM *a);
const BIGNUM *BN_value_one(void);
char *BN_options(void);
+BN_CTX *BN_CTX_new_ex(OSSL_LIB_CTX *ctx);
BN_CTX *BN_CTX_new(void);
+BN_CTX *BN_CTX_secure_new_ex(OSSL_LIB_CTX *ctx);
BN_CTX *BN_CTX_secure_new(void);
void BN_CTX_free(BN_CTX *c);
void BN_CTX_start(BN_CTX *ctx);
BIGNUM *BN_CTX_get(BN_CTX *ctx);
void BN_CTX_end(BN_CTX *ctx);
+int BN_rand_ex(BIGNUM *rnd, int bits, int top, int bottom,
+ unsigned int strength, BN_CTX *ctx);
int BN_rand(BIGNUM *rnd, int bits, int top, int bottom);
+int BN_priv_rand_ex(BIGNUM *rnd, int bits, int top, int bottom,
+ unsigned int strength, BN_CTX *ctx);
int BN_priv_rand(BIGNUM *rnd, int bits, int top, int bottom);
+int BN_rand_range_ex(BIGNUM *r, const BIGNUM *range, unsigned int strength,
+ BN_CTX *ctx);
int BN_rand_range(BIGNUM *rnd, const BIGNUM *range);
+int BN_priv_rand_range_ex(BIGNUM *r, const BIGNUM *range,
+ unsigned int strength, BN_CTX *ctx);
int BN_priv_rand_range(BIGNUM *rnd, const BIGNUM *range);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom);
+OSSL_DEPRECATEDIN_3_0
int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range);
+# endif
int BN_num_bits(const BIGNUM *a);
int BN_num_bits_word(BN_ULONG l);
int BN_security_bits(int L, int N);
@@ -223,6 +245,8 @@ int BN_bn2bin(const BIGNUM *a, unsigned char *to);
int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen);
BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret);
int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen);
+BIGNUM *BN_native2bn(const unsigned char *s, int len, BIGNUM *ret);
+int BN_bn2nativepad(const BIGNUM *a, unsigned char *to, int tolen);
BIGNUM *BN_mpi2bn(const unsigned char *s, int len, BIGNUM *ret);
int BN_bn2mpi(const BIGNUM *a, unsigned char *to);
int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
@@ -292,6 +316,11 @@ int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, const BIGNUM *p1,
BN_CTX *ctx, BN_MONT_CTX *m_ctx);
int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_exp_mont_consttime_x2(BIGNUM *rr1, const BIGNUM *a1, const BIGNUM *p1,
+ const BIGNUM *m1, BN_MONT_CTX *in_mont1,
+ BIGNUM *rr2, const BIGNUM *a2, const BIGNUM *p2,
+ const BIGNUM *m2, BN_MONT_CTX *in_mont2,
+ BN_CTX *ctx);
int BN_mask_bits(BIGNUM *a, int n);
# ifndef OPENSSL_NO_STDIO
@@ -323,38 +352,51 @@ BIGNUM *BN_mod_sqrt(BIGNUM *ret,
void BN_consttime_swap(BN_ULONG swap, BIGNUM *a, BIGNUM *b, int nwords);
/* Deprecated versions */
-DEPRECATEDIN_0_9_8(BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe,
- const BIGNUM *add,
- const BIGNUM *rem,
- void (*callback) (int, int,
- void *),
- void *cb_arg))
-DEPRECATEDIN_0_9_8(int
- BN_is_prime(const BIGNUM *p, int nchecks,
- void (*callback) (int, int, void *),
- BN_CTX *ctx, void *cb_arg))
-DEPRECATEDIN_0_9_8(int
- BN_is_prime_fasttest(const BIGNUM *p, int nchecks,
- void (*callback) (int, int, void *),
- BN_CTX *ctx, void *cb_arg,
- int do_trial_division))
-
-/* Newer versions */
-int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add,
- const BIGNUM *rem, BN_GENCB *cb);
+# ifndef OPENSSL_NO_DEPRECATED_0_9_8
+OSSL_DEPRECATEDIN_0_9_8
+BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe,
+ const BIGNUM *add, const BIGNUM *rem,
+ void (*callback) (int, int, void *),
+ void *cb_arg);
+OSSL_DEPRECATEDIN_0_9_8
+int BN_is_prime(const BIGNUM *p, int nchecks,
+ void (*callback) (int, int, void *),
+ BN_CTX *ctx, void *cb_arg);
+OSSL_DEPRECATEDIN_0_9_8
+int BN_is_prime_fasttest(const BIGNUM *p, int nchecks,
+ void (*callback) (int, int, void *),
+ BN_CTX *ctx, void *cb_arg,
+ int do_trial_division);
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
int BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, BN_GENCB *cb);
+OSSL_DEPRECATEDIN_3_0
int BN_is_prime_fasttest_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx,
int do_trial_division, BN_GENCB *cb);
+# endif
+/* Newer versions */
+int BN_generate_prime_ex2(BIGNUM *ret, int bits, int safe,
+ const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb,
+ BN_CTX *ctx);
+int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add,
+ const BIGNUM *rem, BN_GENCB *cb);
+int BN_check_prime(const BIGNUM *p, BN_CTX *ctx, BN_GENCB *cb);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0
int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
const BIGNUM *Xp, const BIGNUM *Xp1,
const BIGNUM *Xp2, const BIGNUM *e, BN_CTX *ctx,
BN_GENCB *cb);
+OSSL_DEPRECATEDIN_3_0
int BN_X931_generate_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, BIGNUM *Xp1,
BIGNUM *Xp2, const BIGNUM *Xp, const BIGNUM *e,
BN_CTX *ctx, BN_GENCB *cb);
+# endif
BN_MONT_CTX *BN_MONT_CTX_new(void);
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
@@ -398,10 +440,12 @@ BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
BN_CTX *ctx,
BN_MONT_CTX *m_ctx),
BN_MONT_CTX *m_ctx);
-
-DEPRECATEDIN_0_9_8(void BN_set_params(int mul, int high, int low, int mont))
-DEPRECATEDIN_0_9_8(int BN_get_params(int which)) /* 0, mul, 1 high, 2 low, 3
- * mont */
+# ifndef OPENSSL_NO_DEPRECATED_0_9_8
+OSSL_DEPRECATEDIN_0_9_8
+void BN_set_params(int mul, int high, int low, int mont);
+OSSL_DEPRECATEDIN_0_9_8
+int BN_get_params(int which); /* 0, mul, 1 high, 2 low, 3 mont */
+# endif
BN_RECP_CTX *BN_RECP_CTX_new(void);
void BN_RECP_CTX_free(BN_RECP_CTX *recp);
@@ -519,16 +563,16 @@ BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *bn);
BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *bn);
BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *bn);
-# if OPENSSL_API_COMPAT < 0x10100000L
-# define get_rfc2409_prime_768 BN_get_rfc2409_prime_768
-# define get_rfc2409_prime_1024 BN_get_rfc2409_prime_1024
-# define get_rfc3526_prime_1536 BN_get_rfc3526_prime_1536
-# define get_rfc3526_prime_2048 BN_get_rfc3526_prime_2048
-# define get_rfc3526_prime_3072 BN_get_rfc3526_prime_3072
-# define get_rfc3526_prime_4096 BN_get_rfc3526_prime_4096
-# define get_rfc3526_prime_6144 BN_get_rfc3526_prime_6144
-# define get_rfc3526_prime_8192 BN_get_rfc3526_prime_8192
-# endif
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define get_rfc2409_prime_768 BN_get_rfc2409_prime_768
+# define get_rfc2409_prime_1024 BN_get_rfc2409_prime_1024
+# define get_rfc3526_prime_1536 BN_get_rfc3526_prime_1536
+# define get_rfc3526_prime_2048 BN_get_rfc3526_prime_2048
+# define get_rfc3526_prime_3072 BN_get_rfc3526_prime_3072
+# define get_rfc3526_prime_4096 BN_get_rfc3526_prime_4096
+# define get_rfc3526_prime_6144 BN_get_rfc3526_prime_6144
+# define get_rfc3526_prime_8192 BN_get_rfc3526_prime_8192
+# endif
int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom);
diff --git a/include/openssl/bnerr.h b/include/openssl/bnerr.h
index 5c83777f9f06..7c3f6ef3d4ba 100644
--- a/include/openssl/bnerr.h
+++ b/include/openssl/bnerr.h
@@ -1,78 +1,22 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_BNERR_H
-# define HEADER_BNERR_H
+#ifndef OPENSSL_BNERR_H
+# define OPENSSL_BNERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_BN_strings(void);
-/*
- * BN function codes.
- */
-# define BN_F_BNRAND 127
-# define BN_F_BNRAND_RANGE 138
-# define BN_F_BN_BLINDING_CONVERT_EX 100
-# define BN_F_BN_BLINDING_CREATE_PARAM 128
-# define BN_F_BN_BLINDING_INVERT_EX 101
-# define BN_F_BN_BLINDING_NEW 102
-# define BN_F_BN_BLINDING_UPDATE 103
-# define BN_F_BN_BN2DEC 104
-# define BN_F_BN_BN2HEX 105
-# define BN_F_BN_COMPUTE_WNAF 142
-# define BN_F_BN_CTX_GET 116
-# define BN_F_BN_CTX_NEW 106
-# define BN_F_BN_CTX_START 129
-# define BN_F_BN_DIV 107
-# define BN_F_BN_DIV_RECP 130
-# define BN_F_BN_EXP 123
-# define BN_F_BN_EXPAND_INTERNAL 120
-# define BN_F_BN_GENCB_NEW 143
-# define BN_F_BN_GENERATE_DSA_NONCE 140
-# define BN_F_BN_GENERATE_PRIME_EX 141
-# define BN_F_BN_GF2M_MOD 131
-# define BN_F_BN_GF2M_MOD_EXP 132
-# define BN_F_BN_GF2M_MOD_MUL 133
-# define BN_F_BN_GF2M_MOD_SOLVE_QUAD 134
-# define BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR 135
-# define BN_F_BN_GF2M_MOD_SQR 136
-# define BN_F_BN_GF2M_MOD_SQRT 137
-# define BN_F_BN_LSHIFT 145
-# define BN_F_BN_MOD_EXP2_MONT 118
-# define BN_F_BN_MOD_EXP_MONT 109
-# define BN_F_BN_MOD_EXP_MONT_CONSTTIME 124
-# define BN_F_BN_MOD_EXP_MONT_WORD 117
-# define BN_F_BN_MOD_EXP_RECP 125
-# define BN_F_BN_MOD_EXP_SIMPLE 126
-# define BN_F_BN_MOD_INVERSE 110
-# define BN_F_BN_MOD_INVERSE_NO_BRANCH 139
-# define BN_F_BN_MOD_LSHIFT_QUICK 119
-# define BN_F_BN_MOD_SQRT 121
-# define BN_F_BN_MONT_CTX_NEW 149
-# define BN_F_BN_MPI2BN 112
-# define BN_F_BN_NEW 113
-# define BN_F_BN_POOL_GET 147
-# define BN_F_BN_RAND 114
-# define BN_F_BN_RAND_RANGE 122
-# define BN_F_BN_RECP_CTX_NEW 150
-# define BN_F_BN_RSHIFT 146
-# define BN_F_BN_SET_WORDS 144
-# define BN_F_BN_STACK_PUSH 148
-# define BN_F_BN_USUB 115
-# define BN_F_OSSL_BN_RSA_DO_UNBLIND 151
/*
* BN reason codes.
@@ -92,7 +36,9 @@ int ERR_load_BN_strings(void);
# define BN_R_NOT_A_SQUARE 111
# define BN_R_NOT_INITIALIZED 107
# define BN_R_NO_INVERSE 108
+# define BN_R_NO_PRIME_CANDIDATE 121
# define BN_R_NO_SOLUTION 116
+# define BN_R_NO_SUITABLE_DIGEST 120
# define BN_R_PRIVATE_KEY_TOO_LARGE 117
# define BN_R_P_IS_NOT_PRIME 112
# define BN_R_TOO_MANY_ITERATIONS 113
diff --git a/include/openssl/buffer.h b/include/openssl/buffer.h
index d2765766b7ce..5773b986bd21 100644
--- a/include/openssl/buffer.h
+++ b/include/openssl/buffer.h
@@ -1,17 +1,23 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_BUFFER_H
-# define HEADER_BUFFER_H
+#ifndef OPENSSL_BUFFER_H
+# define OPENSSL_BUFFER_H
+# pragma once
-# include <openssl/ossl_typ.h>
-# ifndef HEADER_CRYPTO_H
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_BUFFER_H
+# endif
+
+# include <openssl/types.h>
+# ifndef OPENSSL_CRYPTO_H
# include <openssl/crypto.h>
# endif
# include <openssl/buffererr.h>
@@ -24,16 +30,14 @@ extern "C" {
# include <stddef.h>
# include <sys/types.h>
-/*
- * These names are outdated as of OpenSSL 1.1; a future release
- * will move them to be deprecated.
- */
-# define BUF_strdup(s) OPENSSL_strdup(s)
-# define BUF_strndup(s, size) OPENSSL_strndup(s, size)
-# define BUF_memdup(data, size) OPENSSL_memdup(data, size)
-# define BUF_strlcpy(dst, src, size) OPENSSL_strlcpy(dst, src, size)
-# define BUF_strlcat(dst, src, size) OPENSSL_strlcat(dst, src, size)
-# define BUF_strnlen(str, maxlen) OPENSSL_strnlen(str, maxlen)
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define BUF_strdup(s) OPENSSL_strdup(s)
+# define BUF_strndup(s, size) OPENSSL_strndup(s, size)
+# define BUF_memdup(data, size) OPENSSL_memdup(data, size)
+# define BUF_strlcpy(dst, src, size) OPENSSL_strlcpy(dst, src, size)
+# define BUF_strlcat(dst, src, size) OPENSSL_strlcat(dst, src, size)
+# define BUF_strnlen(str, maxlen) OPENSSL_strnlen(str, maxlen)
+# endif
struct buf_mem_st {
size_t length; /* current number of bytes */
diff --git a/include/openssl/buffererr.h b/include/openssl/buffererr.h
index 04f6ff7a8393..d18b1f8f0735 100644
--- a/include/openssl/buffererr.h
+++ b/include/openssl/buffererr.h
@@ -1,31 +1,22 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_BUFERR_H
-# define HEADER_BUFERR_H
+#ifndef OPENSSL_BUFFERERR_H
+# define OPENSSL_BUFFERERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_BUF_strings(void);
-/*
- * BUF function codes.
- */
-# define BUF_F_BUF_MEM_GROW 100
-# define BUF_F_BUF_MEM_GROW_CLEAN 105
-# define BUF_F_BUF_MEM_NEW 101
/*
* BUF reason codes.
diff --git a/include/openssl/camellia.h b/include/openssl/camellia.h
index 151f3c134917..88c2279e90f1 100644
--- a/include/openssl/camellia.h
+++ b/include/openssl/camellia.h
@@ -1,14 +1,20 @@
/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_CAMELLIA_H
-# define HEADER_CAMELLIA_H
+#ifndef OPENSSL_CAMELLIA_H
+# define OPENSSL_CAMELLIA_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_CAMELLIA_H
+# endif
# include <openssl/opensslconf.h>
@@ -18,8 +24,12 @@
extern "C" {
#endif
-# define CAMELLIA_ENCRYPT 1
-# define CAMELLIA_DECRYPT 0
+# define CAMELLIA_BLOCK_SIZE 16
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+
+# define CAMELLIA_ENCRYPT 1
+# define CAMELLIA_DECRYPT 0
/*
* Because array size can't be a const in C, the following two are macros.
@@ -28,9 +38,8 @@ extern "C" {
/* This should be a hidden type, but EVP requires that the size be known */
-# define CAMELLIA_BLOCK_SIZE 16
-# define CAMELLIA_TABLE_BYTE_LEN 272
-# define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4)
+# define CAMELLIA_TABLE_BYTE_LEN 272
+# define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4)
typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN]; /* to match
* with WORD */
@@ -44,36 +53,61 @@ struct camellia_key_st {
};
typedef struct camellia_key_st CAMELLIA_KEY;
-int Camellia_set_key(const unsigned char *userKey, const int bits,
- CAMELLIA_KEY *key);
-
-void Camellia_encrypt(const unsigned char *in, unsigned char *out,
- const CAMELLIA_KEY *key);
-void Camellia_decrypt(const unsigned char *in, unsigned char *out,
- const CAMELLIA_KEY *key);
-
-void Camellia_ecb_encrypt(const unsigned char *in, unsigned char *out,
- const CAMELLIA_KEY *key, const int enc);
-void Camellia_cbc_encrypt(const unsigned char *in, unsigned char *out,
- size_t length, const CAMELLIA_KEY *key,
- unsigned char *ivec, const int enc);
-void Camellia_cfb128_encrypt(const unsigned char *in, unsigned char *out,
- size_t length, const CAMELLIA_KEY *key,
- unsigned char *ivec, int *num, const int enc);
-void Camellia_cfb1_encrypt(const unsigned char *in, unsigned char *out,
- size_t length, const CAMELLIA_KEY *key,
- unsigned char *ivec, int *num, const int enc);
-void Camellia_cfb8_encrypt(const unsigned char *in, unsigned char *out,
- size_t length, const CAMELLIA_KEY *key,
- unsigned char *ivec, int *num, const int enc);
-void Camellia_ofb128_encrypt(const unsigned char *in, unsigned char *out,
- size_t length, const CAMELLIA_KEY *key,
- unsigned char *ivec, int *num);
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int Camellia_set_key(const unsigned char *userKey,
+ const int bits,
+ CAMELLIA_KEY *key);
+OSSL_DEPRECATEDIN_3_0 void Camellia_encrypt(const unsigned char *in,
+ unsigned char *out,
+ const CAMELLIA_KEY *key);
+OSSL_DEPRECATEDIN_3_0 void Camellia_decrypt(const unsigned char *in,
+ unsigned char *out,
+ const CAMELLIA_KEY *key);
+OSSL_DEPRECATEDIN_3_0 void Camellia_ecb_encrypt(const unsigned char *in,
+ unsigned char *out,
+ const CAMELLIA_KEY *key,
+ const int enc);
+OSSL_DEPRECATEDIN_3_0 void Camellia_cbc_encrypt(const unsigned char *in,
+ unsigned char *out,
+ size_t length,
+ const CAMELLIA_KEY *key,
+ unsigned char *ivec,
+ const int enc);
+OSSL_DEPRECATEDIN_3_0 void Camellia_cfb128_encrypt(const unsigned char *in,
+ unsigned char *out,
+ size_t length,
+ const CAMELLIA_KEY *key,
+ unsigned char *ivec,
+ int *num,
+ const int enc);
+OSSL_DEPRECATEDIN_3_0 void Camellia_cfb1_encrypt(const unsigned char *in,
+ unsigned char *out,
+ size_t length,
+ const CAMELLIA_KEY *key,
+ unsigned char *ivec,
+ int *num,
+ const int enc);
+OSSL_DEPRECATEDIN_3_0 void Camellia_cfb8_encrypt(const unsigned char *in,
+ unsigned char *out,
+ size_t length,
+ const CAMELLIA_KEY *key,
+ unsigned char *ivec,
+ int *num,
+ const int enc);
+OSSL_DEPRECATEDIN_3_0 void Camellia_ofb128_encrypt(const unsigned char *in,
+ unsigned char *out,
+ size_t length,
+ const CAMELLIA_KEY *key,
+ unsigned char *ivec,
+ int *num);
+OSSL_DEPRECATEDIN_3_0
void Camellia_ctr128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const CAMELLIA_KEY *key,
unsigned char ivec[CAMELLIA_BLOCK_SIZE],
unsigned char ecount_buf[CAMELLIA_BLOCK_SIZE],
unsigned int *num);
+# endif
# ifdef __cplusplus
}
diff --git a/include/openssl/cast.h b/include/openssl/cast.h
index 2cc89ae0133c..0bf217beab23 100644
--- a/include/openssl/cast.h
+++ b/include/openssl/cast.h
@@ -1,14 +1,20 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_CAST_H
-# define HEADER_CAST_H
+#ifndef OPENSSL_CAST_H
+# define OPENSSL_CAST_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_CAST_H
+# endif
# include <openssl/opensslconf.h>
@@ -17,33 +23,45 @@
extern "C" {
# endif
-# define CAST_ENCRYPT 1
-# define CAST_DECRYPT 0
-
-# define CAST_LONG unsigned int
-
# define CAST_BLOCK 8
# define CAST_KEY_LENGTH 16
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+
+# define CAST_ENCRYPT 1
+# define CAST_DECRYPT 0
+
+# define CAST_LONG unsigned int
+
typedef struct cast_key_st {
CAST_LONG data[32];
int short_key; /* Use reduced rounds for short key */
} CAST_KEY;
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
void CAST_set_key(CAST_KEY *key, int len, const unsigned char *data);
+OSSL_DEPRECATEDIN_3_0
void CAST_ecb_encrypt(const unsigned char *in, unsigned char *out,
const CAST_KEY *key, int enc);
+OSSL_DEPRECATEDIN_3_0
void CAST_encrypt(CAST_LONG *data, const CAST_KEY *key);
+OSSL_DEPRECATEDIN_3_0
void CAST_decrypt(CAST_LONG *data, const CAST_KEY *key);
+OSSL_DEPRECATEDIN_3_0
void CAST_cbc_encrypt(const unsigned char *in, unsigned char *out,
long length, const CAST_KEY *ks, unsigned char *iv,
int enc);
+OSSL_DEPRECATEDIN_3_0
void CAST_cfb64_encrypt(const unsigned char *in, unsigned char *out,
long length, const CAST_KEY *schedule,
unsigned char *ivec, int *num, int enc);
+OSSL_DEPRECATEDIN_3_0
void CAST_ofb64_encrypt(const unsigned char *in, unsigned char *out,
long length, const CAST_KEY *schedule,
unsigned char *ivec, int *num);
+# endif
# ifdef __cplusplus
}
diff --git a/include/openssl/cmac.h b/include/openssl/cmac.h
index 3535a9abf751..f50861836f48 100644
--- a/include/openssl/cmac.h
+++ b/include/openssl/cmac.h
@@ -1,41 +1,52 @@
/*
- * Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_CMAC_H
-# define HEADER_CMAC_H
+#ifndef OPENSSL_CMAC_H
+# define OPENSSL_CMAC_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_CMAC_H
+# endif
# ifndef OPENSSL_NO_CMAC
-#ifdef __cplusplus
+# ifdef __cplusplus
extern "C" {
-#endif
+# endif
-# include <openssl/evp.h>
+# include <openssl/evp.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
/* Opaque */
typedef struct CMAC_CTX_st CMAC_CTX;
-
-CMAC_CTX *CMAC_CTX_new(void);
-void CMAC_CTX_cleanup(CMAC_CTX *ctx);
-void CMAC_CTX_free(CMAC_CTX *ctx);
-EVP_CIPHER_CTX *CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx);
-int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in);
-
-int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
- const EVP_CIPHER *cipher, ENGINE *impl);
-int CMAC_Update(CMAC_CTX *ctx, const void *data, size_t dlen);
-int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen);
-int CMAC_resume(CMAC_CTX *ctx);
-
-#ifdef __cplusplus
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 CMAC_CTX *CMAC_CTX_new(void);
+OSSL_DEPRECATEDIN_3_0 void CMAC_CTX_cleanup(CMAC_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 void CMAC_CTX_free(CMAC_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 EVP_CIPHER_CTX *CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in);
+OSSL_DEPRECATEDIN_3_0 int CMAC_Init(CMAC_CTX *ctx,
+ const void *key, size_t keylen,
+ const EVP_CIPHER *cipher, ENGINE *impl);
+OSSL_DEPRECATEDIN_3_0 int CMAC_Update(CMAC_CTX *ctx,
+ const void *data, size_t dlen);
+OSSL_DEPRECATEDIN_3_0 int CMAC_Final(CMAC_CTX *ctx,
+ unsigned char *out, size_t *poutlen);
+OSSL_DEPRECATEDIN_3_0 int CMAC_resume(CMAC_CTX *ctx);
+# endif
+
+# ifdef __cplusplus
}
-#endif
+# endif
# endif
#endif
diff --git a/include/openssl/cmp.h.in b/include/openssl/cmp.h.in
new file mode 100644
index 000000000000..f05cb3e54851
--- /dev/null
+++ b/include/openssl/cmp.h.in
@@ -0,0 +1,477 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_CMP_H
+# define OPENSSL_CMP_H
+
+# include <openssl/opensslconf.h>
+# ifndef OPENSSL_NO_CMP
+
+# include <openssl/crmf.h>
+# include <openssl/cmperr.h>
+# include <openssl/cmp_util.h>
+# include <openssl/http.h>
+
+/* explicit #includes not strictly needed since implied by the above: */
+# include <openssl/types.h>
+# include <openssl/safestack.h>
+# include <openssl/x509.h>
+# include <openssl/x509v3.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# define OSSL_CMP_PVNO 2
+
+/*-
+ * PKIFailureInfo ::= BIT STRING {
+ * -- since we can fail in more than one way!
+ * -- More codes may be added in the future if/when required.
+ * badAlg (0),
+ * -- unrecognized or unsupported Algorithm Identifier
+ * badMessageCheck (1),
+ * -- integrity check failed (e.g., signature did not verify)
+ * badRequest (2),
+ * -- transaction not permitted or supported
+ * badTime (3),
+ * -- messageTime was not sufficiently close to the system time,
+ * -- as defined by local policy
+ * badCertId (4),
+ * -- no certificate could be found matching the provided criteria
+ * badDataFormat (5),
+ * -- the data submitted has the wrong format
+ * wrongAuthority (6),
+ * -- the authority indicated in the request is different from the
+ * -- one creating the response token
+ * incorrectData (7),
+ * -- the requester's data is incorrect (for notary services)
+ * missingTimeStamp (8),
+ * -- when the timestamp is missing but should be there
+ * -- (by policy)
+ * badPOP (9),
+ * -- the proof-of-possession failed
+ * certRevoked (10),
+ * -- the certificate has already been revoked
+ * certConfirmed (11),
+ * -- the certificate has already been confirmed
+ * wrongIntegrity (12),
+ * -- invalid integrity, password based instead of signature or
+ * -- vice versa
+ * badRecipientNonce (13),
+ * -- invalid recipient nonce, either missing or wrong value
+ * timeNotAvailable (14),
+ * -- the TSA's time source is not available
+ * unacceptedPolicy (15),
+ * -- the requested TSA policy is not supported by the TSA.
+ * unacceptedExtension (16),
+ * -- the requested extension is not supported by the TSA.
+ * addInfoNotAvailable (17),
+ * -- the additional information requested could not be
+ * -- understood or is not available
+ * badSenderNonce (18),
+ * -- invalid sender nonce, either missing or wrong size
+ * badCertTemplate (19),
+ * -- invalid cert. template or missing mandatory information
+ * signerNotTrusted (20),
+ * -- signer of the message unknown or not trusted
+ * transactionIdInUse (21),
+ * -- the transaction identifier is already in use
+ * unsupportedVersion (22),
+ * -- the version of the message is not supported
+ * notAuthorized (23),
+ * -- the sender was not authorized to make the preceding
+ * -- request or perform the preceding action
+ * systemUnavail (24),
+ * -- the request cannot be handled due to system unavailability
+ * systemFailure (25),
+ * -- the request cannot be handled due to system failure
+ * duplicateCertReq (26)
+ * -- certificate cannot be issued because a duplicate
+ * -- certificate already exists
+ * }
+ */
+# define OSSL_CMP_PKIFAILUREINFO_badAlg 0
+# define OSSL_CMP_PKIFAILUREINFO_badMessageCheck 1
+# define OSSL_CMP_PKIFAILUREINFO_badRequest 2
+# define OSSL_CMP_PKIFAILUREINFO_badTime 3
+# define OSSL_CMP_PKIFAILUREINFO_badCertId 4
+# define OSSL_CMP_PKIFAILUREINFO_badDataFormat 5
+# define OSSL_CMP_PKIFAILUREINFO_wrongAuthority 6
+# define OSSL_CMP_PKIFAILUREINFO_incorrectData 7
+# define OSSL_CMP_PKIFAILUREINFO_missingTimeStamp 8
+# define OSSL_CMP_PKIFAILUREINFO_badPOP 9
+# define OSSL_CMP_PKIFAILUREINFO_certRevoked 10
+# define OSSL_CMP_PKIFAILUREINFO_certConfirmed 11
+# define OSSL_CMP_PKIFAILUREINFO_wrongIntegrity 12
+# define OSSL_CMP_PKIFAILUREINFO_badRecipientNonce 13
+# define OSSL_CMP_PKIFAILUREINFO_timeNotAvailable 14
+# define OSSL_CMP_PKIFAILUREINFO_unacceptedPolicy 15
+# define OSSL_CMP_PKIFAILUREINFO_unacceptedExtension 16
+# define OSSL_CMP_PKIFAILUREINFO_addInfoNotAvailable 17
+# define OSSL_CMP_PKIFAILUREINFO_badSenderNonce 18
+# define OSSL_CMP_PKIFAILUREINFO_badCertTemplate 19
+# define OSSL_CMP_PKIFAILUREINFO_signerNotTrusted 20
+# define OSSL_CMP_PKIFAILUREINFO_transactionIdInUse 21
+# define OSSL_CMP_PKIFAILUREINFO_unsupportedVersion 22
+# define OSSL_CMP_PKIFAILUREINFO_notAuthorized 23
+# define OSSL_CMP_PKIFAILUREINFO_systemUnavail 24
+# define OSSL_CMP_PKIFAILUREINFO_systemFailure 25
+# define OSSL_CMP_PKIFAILUREINFO_duplicateCertReq 26
+# define OSSL_CMP_PKIFAILUREINFO_MAX 26
+# define OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN \
+ ((1 << (OSSL_CMP_PKIFAILUREINFO_MAX + 1)) - 1)
+# if OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN > INT_MAX
+# error CMP_PKIFAILUREINFO_MAX bit pattern does not fit in type int
+# endif
+
+typedef ASN1_BIT_STRING OSSL_CMP_PKIFAILUREINFO;
+
+# define OSSL_CMP_CTX_FAILINFO_badAlg (1 << 0)
+# define OSSL_CMP_CTX_FAILINFO_badMessageCheck (1 << 1)
+# define OSSL_CMP_CTX_FAILINFO_badRequest (1 << 2)
+# define OSSL_CMP_CTX_FAILINFO_badTime (1 << 3)
+# define OSSL_CMP_CTX_FAILINFO_badCertId (1 << 4)
+# define OSSL_CMP_CTX_FAILINFO_badDataFormat (1 << 5)
+# define OSSL_CMP_CTX_FAILINFO_wrongAuthority (1 << 6)
+# define OSSL_CMP_CTX_FAILINFO_incorrectData (1 << 7)
+# define OSSL_CMP_CTX_FAILINFO_missingTimeStamp (1 << 8)
+# define OSSL_CMP_CTX_FAILINFO_badPOP (1 << 9)
+# define OSSL_CMP_CTX_FAILINFO_certRevoked (1 << 10)
+# define OSSL_CMP_CTX_FAILINFO_certConfirmed (1 << 11)
+# define OSSL_CMP_CTX_FAILINFO_wrongIntegrity (1 << 12)
+# define OSSL_CMP_CTX_FAILINFO_badRecipientNonce (1 << 13)
+# define OSSL_CMP_CTX_FAILINFO_timeNotAvailable (1 << 14)
+# define OSSL_CMP_CTX_FAILINFO_unacceptedPolicy (1 << 15)
+# define OSSL_CMP_CTX_FAILINFO_unacceptedExtension (1 << 16)
+# define OSSL_CMP_CTX_FAILINFO_addInfoNotAvailable (1 << 17)
+# define OSSL_CMP_CTX_FAILINFO_badSenderNonce (1 << 18)
+# define OSSL_CMP_CTX_FAILINFO_badCertTemplate (1 << 19)
+# define OSSL_CMP_CTX_FAILINFO_signerNotTrusted (1 << 20)
+# define OSSL_CMP_CTX_FAILINFO_transactionIdInUse (1 << 21)
+# define OSSL_CMP_CTX_FAILINFO_unsupportedVersion (1 << 22)
+# define OSSL_CMP_CTX_FAILINFO_notAuthorized (1 << 23)
+# define OSSL_CMP_CTX_FAILINFO_systemUnavail (1 << 24)
+# define OSSL_CMP_CTX_FAILINFO_systemFailure (1 << 25)
+# define OSSL_CMP_CTX_FAILINFO_duplicateCertReq (1 << 26)
+
+/*-
+ * PKIStatus ::= INTEGER {
+ * accepted (0),
+ * -- you got exactly what you asked for
+ * grantedWithMods (1),
+ * -- you got something like what you asked for; the
+ * -- requester is responsible for ascertaining the differences
+ * rejection (2),
+ * -- you don't get it, more information elsewhere in the message
+ * waiting (3),
+ * -- the request body part has not yet been processed; expect to
+ * -- hear more later (note: proper handling of this status
+ * -- response MAY use the polling req/rep PKIMessages specified
+ * -- in Section 5.3.22; alternatively, polling in the underlying
+ * -- transport layer MAY have some utility in this regard)
+ * revocationWarning (4),
+ * -- this message contains a warning that a revocation is
+ * -- imminent
+ * revocationNotification (5),
+ * -- notification that a revocation has occurred
+ * keyUpdateWarning (6)
+ * -- update already done for the oldCertId specified in
+ * -- CertReqMsg
+ * }
+ */
+# define OSSL_CMP_PKISTATUS_request -3
+# define OSSL_CMP_PKISTATUS_trans -2
+# define OSSL_CMP_PKISTATUS_unspecified -1
+# define OSSL_CMP_PKISTATUS_accepted 0
+# define OSSL_CMP_PKISTATUS_grantedWithMods 1
+# define OSSL_CMP_PKISTATUS_rejection 2
+# define OSSL_CMP_PKISTATUS_waiting 3
+# define OSSL_CMP_PKISTATUS_revocationWarning 4
+# define OSSL_CMP_PKISTATUS_revocationNotification 5
+# define OSSL_CMP_PKISTATUS_keyUpdateWarning 6
+
+typedef ASN1_INTEGER OSSL_CMP_PKISTATUS;
+DECLARE_ASN1_ITEM(OSSL_CMP_PKISTATUS)
+
+# define OSSL_CMP_CERTORENCCERT_CERTIFICATE 0
+# define OSSL_CMP_CERTORENCCERT_ENCRYPTEDCERT 1
+
+/* data type declarations */
+typedef struct ossl_cmp_ctx_st OSSL_CMP_CTX;
+typedef struct ossl_cmp_pkiheader_st OSSL_CMP_PKIHEADER;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PKIHEADER)
+typedef struct ossl_cmp_msg_st OSSL_CMP_MSG;
+DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_MSG)
+DECLARE_ASN1_ENCODE_FUNCTIONS(OSSL_CMP_MSG, OSSL_CMP_MSG, OSSL_CMP_MSG)
+typedef struct ossl_cmp_certstatus_st OSSL_CMP_CERTSTATUS;
+{-
+ generate_stack_macros("OSSL_CMP_CERTSTATUS");
+-}
+typedef struct ossl_cmp_itav_st OSSL_CMP_ITAV;
+DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_ITAV)
+{-
+ generate_stack_macros("OSSL_CMP_ITAV");
+-}
+typedef struct ossl_cmp_revrepcontent_st OSSL_CMP_REVREPCONTENT;
+typedef struct ossl_cmp_pkisi_st OSSL_CMP_PKISI;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PKISI)
+DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_PKISI)
+{-
+ generate_stack_macros("OSSL_CMP_PKISI");
+-}
+typedef struct ossl_cmp_certrepmessage_st OSSL_CMP_CERTREPMESSAGE;
+{-
+ generate_stack_macros("OSSL_CMP_CERTREPMESSAGE");
+-}
+typedef struct ossl_cmp_pollrep_st OSSL_CMP_POLLREP;
+typedef STACK_OF(OSSL_CMP_POLLREP) OSSL_CMP_POLLREPCONTENT;
+typedef struct ossl_cmp_certresponse_st OSSL_CMP_CERTRESPONSE;
+{-
+ generate_stack_macros("OSSL_CMP_CERTRESPONSE");
+-}
+typedef STACK_OF(ASN1_UTF8STRING) OSSL_CMP_PKIFREETEXT;
+
+/*
+ * function DECLARATIONS
+ */
+
+/* from cmp_asn.c */
+OSSL_CMP_ITAV *OSSL_CMP_ITAV_create(ASN1_OBJECT *type, ASN1_TYPE *value);
+void OSSL_CMP_ITAV_set0(OSSL_CMP_ITAV *itav, ASN1_OBJECT *type,
+ ASN1_TYPE *value);
+ASN1_OBJECT *OSSL_CMP_ITAV_get0_type(const OSSL_CMP_ITAV *itav);
+ASN1_TYPE *OSSL_CMP_ITAV_get0_value(const OSSL_CMP_ITAV *itav);
+int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p,
+ OSSL_CMP_ITAV *itav);
+void OSSL_CMP_ITAV_free(OSSL_CMP_ITAV *itav);
+void OSSL_CMP_MSG_free(OSSL_CMP_MSG *msg);
+
+/* from cmp_ctx.c */
+OSSL_CMP_CTX *OSSL_CMP_CTX_new(OSSL_LIB_CTX *libctx, const char *propq);
+void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx);
+int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx);
+/* CMP general options: */
+# define OSSL_CMP_OPT_LOG_VERBOSITY 0
+/* CMP transfer options: */
+# define OSSL_CMP_OPT_KEEP_ALIVE 10
+# define OSSL_CMP_OPT_MSG_TIMEOUT 11
+# define OSSL_CMP_OPT_TOTAL_TIMEOUT 12
+/* CMP request options: */
+# define OSSL_CMP_OPT_VALIDITY_DAYS 20
+# define OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT 21
+# define OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL 22
+# define OSSL_CMP_OPT_POLICIES_CRITICAL 23
+# define OSSL_CMP_OPT_POPO_METHOD 24
+# define OSSL_CMP_OPT_IMPLICIT_CONFIRM 25
+# define OSSL_CMP_OPT_DISABLE_CONFIRM 26
+# define OSSL_CMP_OPT_REVOCATION_REASON 27
+/* CMP protection options: */
+# define OSSL_CMP_OPT_UNPROTECTED_SEND 30
+# define OSSL_CMP_OPT_UNPROTECTED_ERRORS 31
+# define OSSL_CMP_OPT_OWF_ALGNID 32
+# define OSSL_CMP_OPT_MAC_ALGNID 33
+# define OSSL_CMP_OPT_DIGEST_ALGNID 34
+# define OSSL_CMP_OPT_IGNORE_KEYUSAGE 35
+# define OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR 36
+int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val);
+int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt);
+/* CMP-specific callback for logging and outputting the error queue: */
+int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_log_cb_t cb);
+# define OSSL_CMP_CTX_set_log_verbosity(ctx, level) \
+ OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_LOG_VERBOSITY, level)
+void OSSL_CMP_CTX_print_errors(const OSSL_CMP_CTX *ctx);
+/* message transfer: */
+int OSSL_CMP_CTX_set1_serverPath(OSSL_CMP_CTX *ctx, const char *path);
+int OSSL_CMP_CTX_set1_server(OSSL_CMP_CTX *ctx, const char *address);
+int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port);
+int OSSL_CMP_CTX_set1_proxy(OSSL_CMP_CTX *ctx, const char *name);
+int OSSL_CMP_CTX_set1_no_proxy(OSSL_CMP_CTX *ctx, const char *names);
+int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_HTTP_bio_cb_t cb);
+int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
+void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx);
+typedef OSSL_CMP_MSG *(*OSSL_CMP_transfer_cb_t) (OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *req);
+int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_transfer_cb_t cb);
+int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
+void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx);
+/* server authentication: */
+int OSSL_CMP_CTX_set1_srvCert(OSSL_CMP_CTX *ctx, X509 *cert);
+int OSSL_CMP_CTX_set1_expected_sender(OSSL_CMP_CTX *ctx, const X509_NAME *name);
+int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store);
+X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx);
+int OSSL_CMP_CTX_set1_untrusted(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs);
+STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted(const OSSL_CMP_CTX *ctx);
+/* client authentication: */
+int OSSL_CMP_CTX_set1_cert(OSSL_CMP_CTX *ctx, X509 *cert);
+int OSSL_CMP_CTX_build_cert_chain(OSSL_CMP_CTX *ctx, X509_STORE *own_trusted,
+ STACK_OF(X509) *candidates);
+int OSSL_CMP_CTX_set1_pkey(OSSL_CMP_CTX *ctx, EVP_PKEY *pkey);
+int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx,
+ const unsigned char *ref, int len);
+int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx, const unsigned char *sec,
+ const int len);
+/* CMP message header and extra certificates: */
+int OSSL_CMP_CTX_set1_recipient(OSSL_CMP_CTX *ctx, const X509_NAME *name);
+int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav);
+int OSSL_CMP_CTX_reset_geninfo_ITAVs(OSSL_CMP_CTX *ctx);
+int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx,
+ STACK_OF(X509) *extraCertsOut);
+/* certificate template: */
+int OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_CTX *ctx, int priv, EVP_PKEY *pkey);
+EVP_PKEY *OSSL_CMP_CTX_get0_newPkey(const OSSL_CMP_CTX *ctx, int priv);
+int OSSL_CMP_CTX_set1_issuer(OSSL_CMP_CTX *ctx, const X509_NAME *name);
+int OSSL_CMP_CTX_set1_subjectName(OSSL_CMP_CTX *ctx, const X509_NAME *name);
+int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx,
+ const GENERAL_NAME *name);
+int OSSL_CMP_CTX_set0_reqExtensions(OSSL_CMP_CTX *ctx, X509_EXTENSIONS *exts);
+int OSSL_CMP_CTX_reqExtensions_have_SAN(OSSL_CMP_CTX *ctx);
+int OSSL_CMP_CTX_push0_policy(OSSL_CMP_CTX *ctx, POLICYINFO *pinfo);
+int OSSL_CMP_CTX_set1_oldCert(OSSL_CMP_CTX *ctx, X509 *cert);
+int OSSL_CMP_CTX_set1_p10CSR(OSSL_CMP_CTX *ctx, const X509_REQ *csr);
+/* misc body contents: */
+int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav);
+/* certificate confirmation: */
+typedef int (*OSSL_CMP_certConf_cb_t) (OSSL_CMP_CTX *ctx, X509 *cert,
+ int fail_info, const char **txt);
+int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
+ const char **text);
+int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_certConf_cb_t cb);
+int OSSL_CMP_CTX_set_certConf_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
+void *OSSL_CMP_CTX_get_certConf_cb_arg(const OSSL_CMP_CTX *ctx);
+/* result fetching: */
+int OSSL_CMP_CTX_get_status(const OSSL_CMP_CTX *ctx);
+OSSL_CMP_PKIFREETEXT *OSSL_CMP_CTX_get0_statusString(const OSSL_CMP_CTX *ctx);
+int OSSL_CMP_CTX_get_failInfoCode(const OSSL_CMP_CTX *ctx);
+# define OSSL_CMP_PKISI_BUFLEN 1024
+X509 *OSSL_CMP_CTX_get0_newCert(const OSSL_CMP_CTX *ctx);
+STACK_OF(X509) *OSSL_CMP_CTX_get1_newChain(const OSSL_CMP_CTX *ctx);
+STACK_OF(X509) *OSSL_CMP_CTX_get1_caPubs(const OSSL_CMP_CTX *ctx);
+STACK_OF(X509) *OSSL_CMP_CTX_get1_extraCertsIn(const OSSL_CMP_CTX *ctx);
+int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx,
+ const ASN1_OCTET_STRING *id);
+int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx,
+ const ASN1_OCTET_STRING *nonce);
+
+/* from cmp_status.c */
+char *OSSL_CMP_CTX_snprint_PKIStatus(const OSSL_CMP_CTX *ctx, char *buf,
+ size_t bufsize);
+char *OSSL_CMP_snprint_PKIStatusInfo(const OSSL_CMP_PKISI *statusInfo,
+ char *buf, size_t bufsize);
+OSSL_CMP_PKISI *
+OSSL_CMP_STATUSINFO_new(int status, int fail_info, const char *text);
+
+/* from cmp_hdr.c */
+ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_transactionID(const
+ OSSL_CMP_PKIHEADER *hdr);
+ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr);
+
+/* from cmp_msg.c */
+OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg);
+int OSSL_CMP_MSG_get_bodytype(const OSSL_CMP_MSG *msg);
+int OSSL_CMP_MSG_update_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
+OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid);
+OSSL_CMP_MSG *OSSL_CMP_MSG_read(const char *file, OSSL_LIB_CTX *libctx,
+ const char *propq);
+int OSSL_CMP_MSG_write(const char *file, const OSSL_CMP_MSG *msg);
+OSSL_CMP_MSG *d2i_OSSL_CMP_MSG_bio(BIO *bio, OSSL_CMP_MSG **msg);
+int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg);
+
+/* from cmp_vfy.c */
+int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg);
+int OSSL_CMP_validate_cert_path(const OSSL_CMP_CTX *ctx,
+ X509_STORE *trusted_store, X509 *cert);
+
+/* from cmp_http.c */
+OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *req);
+
+/* from cmp_server.c */
+typedef struct ossl_cmp_srv_ctx_st OSSL_CMP_SRV_CTX;
+OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req);
+OSSL_CMP_MSG * OSSL_CMP_CTX_server_perform(OSSL_CMP_CTX *client_ctx,
+ const OSSL_CMP_MSG *req);
+OSSL_CMP_SRV_CTX *OSSL_CMP_SRV_CTX_new(OSSL_LIB_CTX *libctx, const char *propq);
+void OSSL_CMP_SRV_CTX_free(OSSL_CMP_SRV_CTX *srv_ctx);
+typedef OSSL_CMP_PKISI *(*OSSL_CMP_SRV_cert_request_cb_t)
+ (OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *req, int certReqId,
+ const OSSL_CRMF_MSG *crm, const X509_REQ *p10cr,
+ X509 **certOut, STACK_OF(X509) **chainOut, STACK_OF(X509) **caPubs);
+typedef OSSL_CMP_PKISI *(*OSSL_CMP_SRV_rr_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req,
+ const X509_NAME *issuer,
+ const ASN1_INTEGER *serial);
+typedef int (*OSSL_CMP_SRV_genm_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req,
+ const STACK_OF(OSSL_CMP_ITAV) *in,
+ STACK_OF(OSSL_CMP_ITAV) **out);
+typedef void (*OSSL_CMP_SRV_error_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req,
+ const OSSL_CMP_PKISI *statusInfo,
+ const ASN1_INTEGER *errorCode,
+ const OSSL_CMP_PKIFREETEXT *errDetails);
+typedef int (*OSSL_CMP_SRV_certConf_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req,
+ int certReqId,
+ const ASN1_OCTET_STRING *certHash,
+ const OSSL_CMP_PKISI *si);
+typedef int (*OSSL_CMP_SRV_pollReq_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req, int certReqId,
+ OSSL_CMP_MSG **certReq,
+ int64_t *check_after);
+int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx,
+ OSSL_CMP_SRV_cert_request_cb_t process_cert_request,
+ OSSL_CMP_SRV_rr_cb_t process_rr,
+ OSSL_CMP_SRV_genm_cb_t process_genm,
+ OSSL_CMP_SRV_error_cb_t process_error,
+ OSSL_CMP_SRV_certConf_cb_t process_certConf,
+ OSSL_CMP_SRV_pollReq_cb_t process_pollReq);
+OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx);
+void *OSSL_CMP_SRV_CTX_get0_custom_ctx(const OSSL_CMP_SRV_CTX *srv_ctx);
+int OSSL_CMP_SRV_CTX_set_send_unprotected_errors(OSSL_CMP_SRV_CTX *srv_ctx,
+ int val);
+int OSSL_CMP_SRV_CTX_set_accept_unprotected(OSSL_CMP_SRV_CTX *srv_ctx, int val);
+int OSSL_CMP_SRV_CTX_set_accept_raverified(OSSL_CMP_SRV_CTX *srv_ctx, int val);
+int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx,
+ int val);
+
+/* from cmp_client.c */
+X509 *OSSL_CMP_exec_certreq(OSSL_CMP_CTX *ctx, int req_type,
+ const OSSL_CRMF_MSG *crm);
+# define OSSL_CMP_IR 0
+# define OSSL_CMP_CR 2
+# define OSSL_CMP_P10CR 4
+# define OSSL_CMP_KUR 7
+# define OSSL_CMP_exec_IR_ses(ctx) \
+ OSSL_CMP_exec_certreq(ctx, OSSL_CMP_IR, NULL)
+# define OSSL_CMP_exec_CR_ses(ctx) \
+ OSSL_CMP_exec_certreq(ctx, OSSL_CMP_CR, NULL)
+# define OSSL_CMP_exec_P10CR_ses(ctx) \
+ OSSL_CMP_exec_certreq(ctx, OSSL_CMP_P10CR, NULL)
+# define OSSL_CMP_exec_KUR_ses(ctx) \
+ OSSL_CMP_exec_certreq(ctx, OSSL_CMP_KUR, NULL)
+int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type,
+ const OSSL_CRMF_MSG *crm, int *checkAfter);
+int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx);
+STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx);
+
+# ifdef __cplusplus
+}
+# endif
+# endif /* !defined(OPENSSL_NO_CMP) */
+#endif /* !defined(OPENSSL_CMP_H) */
diff --git a/include/openssl/cmp_util.h b/include/openssl/cmp_util.h
new file mode 100644
index 000000000000..9a168922bfce
--- /dev/null
+++ b/include/openssl/cmp_util.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_CMP_UTIL_H
+# define OPENSSL_CMP_UTIL_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# ifndef OPENSSL_NO_CMP
+
+# include <openssl/macros.h>
+# include <openssl/trace.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int OSSL_CMP_log_open(void);
+void OSSL_CMP_log_close(void);
+# define OSSL_CMP_LOG_PREFIX "CMP "
+
+/*
+ * generalized logging/error callback mirroring the severity levels of syslog.h
+ */
+typedef int OSSL_CMP_severity;
+# define OSSL_CMP_LOG_EMERG 0
+# define OSSL_CMP_LOG_ALERT 1
+# define OSSL_CMP_LOG_CRIT 2
+# define OSSL_CMP_LOG_ERR 3
+# define OSSL_CMP_LOG_WARNING 4
+# define OSSL_CMP_LOG_NOTICE 5
+# define OSSL_CMP_LOG_INFO 6
+# define OSSL_CMP_LOG_DEBUG 7
+# define OSSL_CMP_LOG_TRACE 8
+# define OSSL_CMP_LOG_MAX OSSL_CMP_LOG_TRACE
+typedef int (*OSSL_CMP_log_cb_t)(const char *func, const char *file, int line,
+ OSSL_CMP_severity level, const char *msg);
+
+int OSSL_CMP_print_to_bio(BIO *bio, const char *component, const char *file,
+ int line, OSSL_CMP_severity level, const char *msg);
+/* use of the logging callback for outputting error queue */
+void OSSL_CMP_print_errors_cb(OSSL_CMP_log_cb_t log_fn);
+
+# ifdef __cplusplus
+}
+# endif
+# endif /* !defined(OPENSSL_NO_CMP) */
+#endif /* !defined(OPENSSL_CMP_UTIL_H) */
diff --git a/include/openssl/cmperr.h b/include/openssl/cmperr.h
new file mode 100644
index 000000000000..06e9dbff363d
--- /dev/null
+++ b/include/openssl/cmperr.h
@@ -0,0 +1,114 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_CMPERR_H
+# define OPENSSL_CMPERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
+
+
+# ifndef OPENSSL_NO_CMP
+
+
+/*
+ * CMP reason codes.
+ */
+# define CMP_R_ALGORITHM_NOT_SUPPORTED 139
+# define CMP_R_BAD_CHECKAFTER_IN_POLLREP 167
+# define CMP_R_BAD_REQUEST_ID 108
+# define CMP_R_CERTHASH_UNMATCHED 156
+# define CMP_R_CERTID_NOT_FOUND 109
+# define CMP_R_CERTIFICATE_NOT_ACCEPTED 169
+# define CMP_R_CERTIFICATE_NOT_FOUND 112
+# define CMP_R_CERTREQMSG_NOT_FOUND 157
+# define CMP_R_CERTRESPONSE_NOT_FOUND 113
+# define CMP_R_CERT_AND_KEY_DO_NOT_MATCH 114
+# define CMP_R_CHECKAFTER_OUT_OF_RANGE 181
+# define CMP_R_ENCOUNTERED_KEYUPDATEWARNING 176
+# define CMP_R_ENCOUNTERED_WAITING 162
+# define CMP_R_ERROR_CALCULATING_PROTECTION 115
+# define CMP_R_ERROR_CREATING_CERTCONF 116
+# define CMP_R_ERROR_CREATING_CERTREP 117
+# define CMP_R_ERROR_CREATING_CERTREQ 163
+# define CMP_R_ERROR_CREATING_ERROR 118
+# define CMP_R_ERROR_CREATING_GENM 119
+# define CMP_R_ERROR_CREATING_GENP 120
+# define CMP_R_ERROR_CREATING_PKICONF 122
+# define CMP_R_ERROR_CREATING_POLLREP 123
+# define CMP_R_ERROR_CREATING_POLLREQ 124
+# define CMP_R_ERROR_CREATING_RP 125
+# define CMP_R_ERROR_CREATING_RR 126
+# define CMP_R_ERROR_PARSING_PKISTATUS 107
+# define CMP_R_ERROR_PROCESSING_MESSAGE 158
+# define CMP_R_ERROR_PROTECTING_MESSAGE 127
+# define CMP_R_ERROR_SETTING_CERTHASH 128
+# define CMP_R_ERROR_UNEXPECTED_CERTCONF 160
+# define CMP_R_ERROR_VALIDATING_PROTECTION 140
+# define CMP_R_ERROR_VALIDATING_SIGNATURE 171
+# define CMP_R_FAILED_BUILDING_OWN_CHAIN 164
+# define CMP_R_FAILED_EXTRACTING_PUBKEY 141
+# define CMP_R_FAILURE_OBTAINING_RANDOM 110
+# define CMP_R_FAIL_INFO_OUT_OF_RANGE 129
+# define CMP_R_INVALID_ARGS 100
+# define CMP_R_INVALID_OPTION 174
+# define CMP_R_MISSING_CERTID 165
+# define CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION 130
+# define CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE 142
+# define CMP_R_MISSING_P10CSR 121
+# define CMP_R_MISSING_PBM_SECRET 166
+# define CMP_R_MISSING_PRIVATE_KEY 131
+# define CMP_R_MISSING_PROTECTION 143
+# define CMP_R_MISSING_REFERENCE_CERT 168
+# define CMP_R_MISSING_SECRET 178
+# define CMP_R_MISSING_SENDER_IDENTIFICATION 111
+# define CMP_R_MISSING_TRUST_ANCHOR 179
+# define CMP_R_MISSING_TRUST_STORE 144
+# define CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED 161
+# define CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED 170
+# define CMP_R_MULTIPLE_SAN_SOURCES 102
+# define CMP_R_NO_STDIO 194
+# define CMP_R_NO_SUITABLE_SENDER_CERT 145
+# define CMP_R_NULL_ARGUMENT 103
+# define CMP_R_PKIBODY_ERROR 146
+# define CMP_R_PKISTATUSINFO_NOT_FOUND 132
+# define CMP_R_POLLING_FAILED 172
+# define CMP_R_POTENTIALLY_INVALID_CERTIFICATE 147
+# define CMP_R_RECEIVED_ERROR 180
+# define CMP_R_RECIPNONCE_UNMATCHED 148
+# define CMP_R_REQUEST_NOT_ACCEPTED 149
+# define CMP_R_REQUEST_REJECTED_BY_SERVER 182
+# define CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED 150
+# define CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG 151
+# define CMP_R_TOTAL_TIMEOUT 184
+# define CMP_R_TRANSACTIONID_UNMATCHED 152
+# define CMP_R_TRANSFER_ERROR 159
+# define CMP_R_UNEXPECTED_PKIBODY 133
+# define CMP_R_UNEXPECTED_PKISTATUS 185
+# define CMP_R_UNEXPECTED_PVNO 153
+# define CMP_R_UNKNOWN_ALGORITHM_ID 134
+# define CMP_R_UNKNOWN_CERT_TYPE 135
+# define CMP_R_UNKNOWN_PKISTATUS 186
+# define CMP_R_UNSUPPORTED_ALGORITHM 136
+# define CMP_R_UNSUPPORTED_KEY_TYPE 137
+# define CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC 154
+# define CMP_R_VALUE_TOO_LARGE 175
+# define CMP_R_VALUE_TOO_SMALL 177
+# define CMP_R_WRONG_ALGORITHM_OID 138
+# define CMP_R_WRONG_CERTID 189
+# define CMP_R_WRONG_CERTID_IN_RP 187
+# define CMP_R_WRONG_PBM_VALUE 155
+# define CMP_R_WRONG_RP_COMPONENT_COUNT 188
+# define CMP_R_WRONG_SERIAL_IN_RP 173
+
+# endif
+#endif
diff --git a/include/openssl/cms.h b/include/openssl/cms.h
deleted file mode 100644
index c7627968c7a0..000000000000
--- a/include/openssl/cms.h
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Copyright 2008-2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_CMS_H
-# define HEADER_CMS_H
-
-# include <openssl/opensslconf.h>
-
-# ifndef OPENSSL_NO_CMS
-# include <openssl/x509.h>
-# include <openssl/x509v3.h>
-# include <openssl/cmserr.h>
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-typedef struct CMS_ContentInfo_st CMS_ContentInfo;
-typedef struct CMS_SignerInfo_st CMS_SignerInfo;
-typedef struct CMS_CertificateChoices CMS_CertificateChoices;
-typedef struct CMS_RevocationInfoChoice_st CMS_RevocationInfoChoice;
-typedef struct CMS_RecipientInfo_st CMS_RecipientInfo;
-typedef struct CMS_ReceiptRequest_st CMS_ReceiptRequest;
-typedef struct CMS_Receipt_st CMS_Receipt;
-typedef struct CMS_RecipientEncryptedKey_st CMS_RecipientEncryptedKey;
-typedef struct CMS_OtherKeyAttribute_st CMS_OtherKeyAttribute;
-
-DEFINE_STACK_OF(CMS_SignerInfo)
-DEFINE_STACK_OF(CMS_RecipientEncryptedKey)
-DEFINE_STACK_OF(CMS_RecipientInfo)
-DEFINE_STACK_OF(CMS_RevocationInfoChoice)
-DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo)
-DECLARE_ASN1_FUNCTIONS(CMS_ReceiptRequest)
-DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
-
-# define CMS_SIGNERINFO_ISSUER_SERIAL 0
-# define CMS_SIGNERINFO_KEYIDENTIFIER 1
-
-# define CMS_RECIPINFO_NONE -1
-# define CMS_RECIPINFO_TRANS 0
-# define CMS_RECIPINFO_AGREE 1
-# define CMS_RECIPINFO_KEK 2
-# define CMS_RECIPINFO_PASS 3
-# define CMS_RECIPINFO_OTHER 4
-
-/* S/MIME related flags */
-
-# define CMS_TEXT 0x1
-# define CMS_NOCERTS 0x2
-# define CMS_NO_CONTENT_VERIFY 0x4
-# define CMS_NO_ATTR_VERIFY 0x8
-# define CMS_NOSIGS \
- (CMS_NO_CONTENT_VERIFY|CMS_NO_ATTR_VERIFY)
-# define CMS_NOINTERN 0x10
-# define CMS_NO_SIGNER_CERT_VERIFY 0x20
-# define CMS_NOVERIFY 0x20
-# define CMS_DETACHED 0x40
-# define CMS_BINARY 0x80
-# define CMS_NOATTR 0x100
-# define CMS_NOSMIMECAP 0x200
-# define CMS_NOOLDMIMETYPE 0x400
-# define CMS_CRLFEOL 0x800
-# define CMS_STREAM 0x1000
-# define CMS_NOCRL 0x2000
-# define CMS_PARTIAL 0x4000
-# define CMS_REUSE_DIGEST 0x8000
-# define CMS_USE_KEYID 0x10000
-# define CMS_DEBUG_DECRYPT 0x20000
-# define CMS_KEY_PARAM 0x40000
-# define CMS_ASCIICRLF 0x80000
-
-const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms);
-
-BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont);
-int CMS_dataFinal(CMS_ContentInfo *cms, BIO *bio);
-
-ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms);
-int CMS_is_detached(CMS_ContentInfo *cms);
-int CMS_set_detached(CMS_ContentInfo *cms, int detached);
-
-# ifdef HEADER_PEM_H
-DECLARE_PEM_rw_const(CMS, CMS_ContentInfo)
-# endif
-int CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms);
-CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms);
-int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms);
-
-BIO *BIO_new_CMS(BIO *out, CMS_ContentInfo *cms);
-int i2d_CMS_bio_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, int flags);
-int PEM_write_bio_CMS_stream(BIO *out, CMS_ContentInfo *cms, BIO *in,
- int flags);
-CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont);
-int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags);
-
-int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont,
- unsigned int flags);
-
-CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
- STACK_OF(X509) *certs, BIO *data,
- unsigned int flags);
-
-CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
- X509 *signcert, EVP_PKEY *pkey,
- STACK_OF(X509) *certs, unsigned int flags);
-
-int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags);
-CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags);
-
-int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
- unsigned int flags);
-CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
- unsigned int flags);
-
-int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
- const unsigned char *key, size_t keylen,
- BIO *dcont, BIO *out, unsigned int flags);
-
-CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
- const unsigned char *key,
- size_t keylen, unsigned int flags);
-
-int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
- const unsigned char *key, size_t keylen);
-
-int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
- X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags);
-
-int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
- STACK_OF(X509) *certs,
- X509_STORE *store, unsigned int flags);
-
-STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms);
-
-CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in,
- const EVP_CIPHER *cipher, unsigned int flags);
-
-int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert,
- BIO *dcont, BIO *out, unsigned int flags);
-
-int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert);
-int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
- unsigned char *key, size_t keylen,
- const unsigned char *id, size_t idlen);
-int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
- unsigned char *pass, ossl_ssize_t passlen);
-
-STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms);
-int CMS_RecipientInfo_type(CMS_RecipientInfo *ri);
-EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri);
-CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher);
-CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
- X509 *recip, unsigned int flags);
-int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey);
-int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert);
-int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
- EVP_PKEY **pk, X509 **recip,
- X509_ALGOR **palg);
-int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri,
- ASN1_OCTET_STRING **keyid,
- X509_NAME **issuer,
- ASN1_INTEGER **sno);
-
-CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
- unsigned char *key, size_t keylen,
- unsigned char *id, size_t idlen,
- ASN1_GENERALIZEDTIME *date,
- ASN1_OBJECT *otherTypeId,
- ASN1_TYPE *otherType);
-
-int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
- X509_ALGOR **palg,
- ASN1_OCTET_STRING **pid,
- ASN1_GENERALIZEDTIME **pdate,
- ASN1_OBJECT **potherid,
- ASN1_TYPE **pothertype);
-
-int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
- unsigned char *key, size_t keylen);
-
-int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri,
- const unsigned char *id, size_t idlen);
-
-int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri,
- unsigned char *pass,
- ossl_ssize_t passlen);
-
-CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
- int iter, int wrap_nid,
- int pbe_nid,
- unsigned char *pass,
- ossl_ssize_t passlen,
- const EVP_CIPHER *kekciph);
-
-int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri);
-int CMS_RecipientInfo_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri);
-
-int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
- unsigned int flags);
-CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags);
-
-int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid);
-const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms);
-
-CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms);
-int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert);
-int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert);
-STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms);
-
-CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms);
-int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl);
-int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl);
-STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms);
-
-int CMS_SignedData_init(CMS_ContentInfo *cms);
-CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
- X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
- unsigned int flags);
-EVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si);
-EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si);
-STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms);
-
-void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer);
-int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si,
- ASN1_OCTET_STRING **keyid,
- X509_NAME **issuer, ASN1_INTEGER **sno);
-int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert);
-int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
- unsigned int flags);
-void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk,
- X509 **signer, X509_ALGOR **pdig,
- X509_ALGOR **psig);
-ASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si);
-int CMS_SignerInfo_sign(CMS_SignerInfo *si);
-int CMS_SignerInfo_verify(CMS_SignerInfo *si);
-int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain);
-
-int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs);
-int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs,
- int algnid, int keysize);
-int CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap);
-
-int CMS_signed_get_attr_count(const CMS_SignerInfo *si);
-int CMS_signed_get_attr_by_NID(const CMS_SignerInfo *si, int nid,
- int lastpos);
-int CMS_signed_get_attr_by_OBJ(const CMS_SignerInfo *si, const ASN1_OBJECT *obj,
- int lastpos);
-X509_ATTRIBUTE *CMS_signed_get_attr(const CMS_SignerInfo *si, int loc);
-X509_ATTRIBUTE *CMS_signed_delete_attr(CMS_SignerInfo *si, int loc);
-int CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr);
-int CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si,
- const ASN1_OBJECT *obj, int type,
- const void *bytes, int len);
-int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si,
- int nid, int type,
- const void *bytes, int len);
-int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si,
- const char *attrname, int type,
- const void *bytes, int len);
-void *CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, const ASN1_OBJECT *oid,
- int lastpos, int type);
-
-int CMS_unsigned_get_attr_count(const CMS_SignerInfo *si);
-int CMS_unsigned_get_attr_by_NID(const CMS_SignerInfo *si, int nid,
- int lastpos);
-int CMS_unsigned_get_attr_by_OBJ(const CMS_SignerInfo *si,
- const ASN1_OBJECT *obj, int lastpos);
-X509_ATTRIBUTE *CMS_unsigned_get_attr(const CMS_SignerInfo *si, int loc);
-X509_ATTRIBUTE *CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc);
-int CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr);
-int CMS_unsigned_add1_attr_by_OBJ(CMS_SignerInfo *si,
- const ASN1_OBJECT *obj, int type,
- const void *bytes, int len);
-int CMS_unsigned_add1_attr_by_NID(CMS_SignerInfo *si,
- int nid, int type,
- const void *bytes, int len);
-int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si,
- const char *attrname, int type,
- const void *bytes, int len);
-void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid,
- int lastpos, int type);
-
-int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr);
-CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
- int allorfirst,
- STACK_OF(GENERAL_NAMES)
- *receiptList, STACK_OF(GENERAL_NAMES)
- *receiptsTo);
-int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr);
-void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
- ASN1_STRING **pcid,
- int *pallorfirst,
- STACK_OF(GENERAL_NAMES) **plist,
- STACK_OF(GENERAL_NAMES) **prto);
-int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri,
- X509_ALGOR **palg,
- ASN1_OCTET_STRING **pukm);
-STACK_OF(CMS_RecipientEncryptedKey)
-*CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri);
-
-int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri,
- X509_ALGOR **pubalg,
- ASN1_BIT_STRING **pubkey,
- ASN1_OCTET_STRING **keyid,
- X509_NAME **issuer,
- ASN1_INTEGER **sno);
-
-int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert);
-
-int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek,
- ASN1_OCTET_STRING **keyid,
- ASN1_GENERALIZEDTIME **tm,
- CMS_OtherKeyAttribute **other,
- X509_NAME **issuer, ASN1_INTEGER **sno);
-int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek,
- X509 *cert);
-int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk);
-EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri);
-int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms,
- CMS_RecipientInfo *ri,
- CMS_RecipientEncryptedKey *rek);
-
-int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg,
- ASN1_OCTET_STRING *ukm, int keylen);
-
-/* Backward compatibility for spelling errors. */
-# define CMS_R_UNKNOWN_DIGEST_ALGORITM CMS_R_UNKNOWN_DIGEST_ALGORITHM
-# define CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE \
- CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE
-
-# ifdef __cplusplus
-}
-# endif
-# endif
-#endif
diff --git a/include/openssl/cms.h.in b/include/openssl/cms.h.in
new file mode 100644
index 000000000000..da20ddf2f41d
--- /dev/null
+++ b/include/openssl/cms.h.in
@@ -0,0 +1,395 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_CMS_H
+# define OPENSSL_CMS_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_CMS_H
+# endif
+
+# include <openssl/opensslconf.h>
+
+# ifndef OPENSSL_NO_CMS
+# include <openssl/x509.h>
+# include <openssl/x509v3.h>
+# include <openssl/cmserr.h>
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+typedef struct CMS_ContentInfo_st CMS_ContentInfo;
+typedef struct CMS_SignerInfo_st CMS_SignerInfo;
+typedef struct CMS_CertificateChoices CMS_CertificateChoices;
+typedef struct CMS_RevocationInfoChoice_st CMS_RevocationInfoChoice;
+typedef struct CMS_RecipientInfo_st CMS_RecipientInfo;
+typedef struct CMS_ReceiptRequest_st CMS_ReceiptRequest;
+typedef struct CMS_Receipt_st CMS_Receipt;
+typedef struct CMS_RecipientEncryptedKey_st CMS_RecipientEncryptedKey;
+typedef struct CMS_OtherKeyAttribute_st CMS_OtherKeyAttribute;
+
+{-
+ generate_stack_macros("CMS_SignerInfo")
+ .generate_stack_macros("CMS_RecipientEncryptedKey")
+ .generate_stack_macros("CMS_RecipientInfo")
+ .generate_stack_macros("CMS_RevocationInfoChoice");
+-}
+
+DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo)
+DECLARE_ASN1_FUNCTIONS(CMS_ReceiptRequest)
+DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
+
+CMS_ContentInfo *CMS_ContentInfo_new_ex(OSSL_LIB_CTX *libctx, const char *propq);
+
+# define CMS_SIGNERINFO_ISSUER_SERIAL 0
+# define CMS_SIGNERINFO_KEYIDENTIFIER 1
+
+# define CMS_RECIPINFO_NONE -1
+# define CMS_RECIPINFO_TRANS 0
+# define CMS_RECIPINFO_AGREE 1
+# define CMS_RECIPINFO_KEK 2
+# define CMS_RECIPINFO_PASS 3
+# define CMS_RECIPINFO_OTHER 4
+
+/* S/MIME related flags */
+
+# define CMS_TEXT 0x1
+# define CMS_NOCERTS 0x2
+# define CMS_NO_CONTENT_VERIFY 0x4
+# define CMS_NO_ATTR_VERIFY 0x8
+# define CMS_NOSIGS \
+ (CMS_NO_CONTENT_VERIFY|CMS_NO_ATTR_VERIFY)
+# define CMS_NOINTERN 0x10
+# define CMS_NO_SIGNER_CERT_VERIFY 0x20
+# define CMS_NOVERIFY 0x20
+# define CMS_DETACHED 0x40
+# define CMS_BINARY 0x80
+# define CMS_NOATTR 0x100
+# define CMS_NOSMIMECAP 0x200
+# define CMS_NOOLDMIMETYPE 0x400
+# define CMS_CRLFEOL 0x800
+# define CMS_STREAM 0x1000
+# define CMS_NOCRL 0x2000
+# define CMS_PARTIAL 0x4000
+# define CMS_REUSE_DIGEST 0x8000
+# define CMS_USE_KEYID 0x10000
+# define CMS_DEBUG_DECRYPT 0x20000
+# define CMS_KEY_PARAM 0x40000
+# define CMS_ASCIICRLF 0x80000
+# define CMS_CADES 0x100000
+# define CMS_USE_ORIGINATOR_KEYID 0x200000
+
+const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms);
+
+BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont);
+int CMS_dataFinal(CMS_ContentInfo *cms, BIO *bio);
+
+ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms);
+int CMS_is_detached(CMS_ContentInfo *cms);
+int CMS_set_detached(CMS_ContentInfo *cms, int detached);
+
+# ifdef OPENSSL_PEM_H
+DECLARE_PEM_rw(CMS, CMS_ContentInfo)
+# endif
+int CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms);
+CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms);
+int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms);
+
+BIO *BIO_new_CMS(BIO *out, CMS_ContentInfo *cms);
+int i2d_CMS_bio_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, int flags);
+int PEM_write_bio_CMS_stream(BIO *out, CMS_ContentInfo *cms, BIO *in,
+ int flags);
+CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont);
+CMS_ContentInfo *SMIME_read_CMS_ex(BIO *bio, int flags, BIO **bcont, CMS_ContentInfo **ci);
+int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags);
+
+int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont,
+ unsigned int flags);
+
+CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
+ STACK_OF(X509) *certs, BIO *data,
+ unsigned int flags);
+CMS_ContentInfo *CMS_sign_ex(X509 *signcert, EVP_PKEY *pkey,
+ STACK_OF(X509) *certs, BIO *data,
+ unsigned int flags, OSSL_LIB_CTX *ctx,
+ const char *propq);
+
+CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
+ X509 *signcert, EVP_PKEY *pkey,
+ STACK_OF(X509) *certs, unsigned int flags);
+
+int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags);
+CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags);
+CMS_ContentInfo *CMS_data_create_ex(BIO *in, unsigned int flags,
+ OSSL_LIB_CTX *ctx, const char *propq);
+
+int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
+ unsigned int flags);
+CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
+ unsigned int flags);
+CMS_ContentInfo *CMS_digest_create_ex(BIO *in, const EVP_MD *md,
+ unsigned int flags, OSSL_LIB_CTX *ctx,
+ const char *propq);
+
+int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
+ const unsigned char *key, size_t keylen,
+ BIO *dcont, BIO *out, unsigned int flags);
+
+CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
+ const unsigned char *key,
+ size_t keylen, unsigned int flags);
+CMS_ContentInfo *CMS_EncryptedData_encrypt_ex(BIO *in, const EVP_CIPHER *cipher,
+ const unsigned char *key,
+ size_t keylen, unsigned int flags,
+ OSSL_LIB_CTX *ctx,
+ const char *propq);
+
+int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
+ const unsigned char *key, size_t keylen);
+
+int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
+ X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags);
+
+int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
+ STACK_OF(X509) *certs,
+ X509_STORE *store, unsigned int flags);
+
+STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms);
+
+CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in,
+ const EVP_CIPHER *cipher, unsigned int flags);
+CMS_ContentInfo *CMS_encrypt_ex(STACK_OF(X509) *certs, BIO *in,
+ const EVP_CIPHER *cipher, unsigned int flags,
+ OSSL_LIB_CTX *ctx, const char *propq);
+
+int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert,
+ BIO *dcont, BIO *out, unsigned int flags);
+
+int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert);
+int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk,
+ X509 *cert, X509 *peer);
+int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
+ unsigned char *key, size_t keylen,
+ const unsigned char *id, size_t idlen);
+int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
+ unsigned char *pass, ossl_ssize_t passlen);
+
+STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms);
+int CMS_RecipientInfo_type(CMS_RecipientInfo *ri);
+EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri);
+CMS_ContentInfo *CMS_AuthEnvelopedData_create(const EVP_CIPHER *cipher);
+CMS_ContentInfo *
+CMS_AuthEnvelopedData_create_ex(const EVP_CIPHER *cipher, OSSL_LIB_CTX *ctx,
+ const char *propq);
+CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher);
+CMS_ContentInfo *CMS_EnvelopedData_create_ex(const EVP_CIPHER *cipher,
+ OSSL_LIB_CTX *ctx,
+ const char *propq);
+
+CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
+ X509 *recip, unsigned int flags);
+CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip,
+ EVP_PKEY *originatorPrivKey, X509 * originator, unsigned int flags);
+int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey);
+int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert);
+int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
+ EVP_PKEY **pk, X509 **recip,
+ X509_ALGOR **palg);
+int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri,
+ ASN1_OCTET_STRING **keyid,
+ X509_NAME **issuer,
+ ASN1_INTEGER **sno);
+
+CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
+ unsigned char *key, size_t keylen,
+ unsigned char *id, size_t idlen,
+ ASN1_GENERALIZEDTIME *date,
+ ASN1_OBJECT *otherTypeId,
+ ASN1_TYPE *otherType);
+
+int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
+ X509_ALGOR **palg,
+ ASN1_OCTET_STRING **pid,
+ ASN1_GENERALIZEDTIME **pdate,
+ ASN1_OBJECT **potherid,
+ ASN1_TYPE **pothertype);
+
+int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
+ unsigned char *key, size_t keylen);
+
+int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri,
+ const unsigned char *id, size_t idlen);
+
+int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri,
+ unsigned char *pass,
+ ossl_ssize_t passlen);
+
+CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
+ int iter, int wrap_nid,
+ int pbe_nid,
+ unsigned char *pass,
+ ossl_ssize_t passlen,
+ const EVP_CIPHER *kekciph);
+
+int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri);
+int CMS_RecipientInfo_encrypt(const CMS_ContentInfo *cms, CMS_RecipientInfo *ri);
+
+int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
+ unsigned int flags);
+CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags);
+
+int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid);
+const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms);
+
+CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms);
+int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert);
+int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert);
+STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms);
+
+CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms);
+int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl);
+int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl);
+STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms);
+
+int CMS_SignedData_init(CMS_ContentInfo *cms);
+CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
+ X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
+ unsigned int flags);
+EVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si);
+EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si);
+STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms);
+
+void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer);
+int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si,
+ ASN1_OCTET_STRING **keyid,
+ X509_NAME **issuer, ASN1_INTEGER **sno);
+int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert);
+int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
+ unsigned int flags);
+void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk,
+ X509 **signer, X509_ALGOR **pdig,
+ X509_ALGOR **psig);
+ASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si);
+int CMS_SignerInfo_sign(CMS_SignerInfo *si);
+int CMS_SignerInfo_verify(CMS_SignerInfo *si);
+int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain);
+
+int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs);
+int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs,
+ int algnid, int keysize);
+int CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap);
+
+int CMS_signed_get_attr_count(const CMS_SignerInfo *si);
+int CMS_signed_get_attr_by_NID(const CMS_SignerInfo *si, int nid,
+ int lastpos);
+int CMS_signed_get_attr_by_OBJ(const CMS_SignerInfo *si, const ASN1_OBJECT *obj,
+ int lastpos);
+X509_ATTRIBUTE *CMS_signed_get_attr(const CMS_SignerInfo *si, int loc);
+X509_ATTRIBUTE *CMS_signed_delete_attr(CMS_SignerInfo *si, int loc);
+int CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr);
+int CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si,
+ const ASN1_OBJECT *obj, int type,
+ const void *bytes, int len);
+int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si,
+ int nid, int type,
+ const void *bytes, int len);
+int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si,
+ const char *attrname, int type,
+ const void *bytes, int len);
+void *CMS_signed_get0_data_by_OBJ(const CMS_SignerInfo *si,
+ const ASN1_OBJECT *oid,
+ int lastpos, int type);
+
+int CMS_unsigned_get_attr_count(const CMS_SignerInfo *si);
+int CMS_unsigned_get_attr_by_NID(const CMS_SignerInfo *si, int nid,
+ int lastpos);
+int CMS_unsigned_get_attr_by_OBJ(const CMS_SignerInfo *si,
+ const ASN1_OBJECT *obj, int lastpos);
+X509_ATTRIBUTE *CMS_unsigned_get_attr(const CMS_SignerInfo *si, int loc);
+X509_ATTRIBUTE *CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc);
+int CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr);
+int CMS_unsigned_add1_attr_by_OBJ(CMS_SignerInfo *si,
+ const ASN1_OBJECT *obj, int type,
+ const void *bytes, int len);
+int CMS_unsigned_add1_attr_by_NID(CMS_SignerInfo *si,
+ int nid, int type,
+ const void *bytes, int len);
+int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si,
+ const char *attrname, int type,
+ const void *bytes, int len);
+void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid,
+ int lastpos, int type);
+
+int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr);
+CMS_ReceiptRequest *CMS_ReceiptRequest_create0(
+ unsigned char *id, int idlen, int allorfirst,
+ STACK_OF(GENERAL_NAMES) *receiptList,
+ STACK_OF(GENERAL_NAMES) *receiptsTo);
+CMS_ReceiptRequest *CMS_ReceiptRequest_create0_ex(
+ unsigned char *id, int idlen, int allorfirst,
+ STACK_OF(GENERAL_NAMES) *receiptList,
+ STACK_OF(GENERAL_NAMES) *receiptsTo,
+ OSSL_LIB_CTX *ctx);
+
+int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr);
+void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
+ ASN1_STRING **pcid,
+ int *pallorfirst,
+ STACK_OF(GENERAL_NAMES) **plist,
+ STACK_OF(GENERAL_NAMES) **prto);
+int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri,
+ X509_ALGOR **palg,
+ ASN1_OCTET_STRING **pukm);
+STACK_OF(CMS_RecipientEncryptedKey)
+*CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri);
+
+int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri,
+ X509_ALGOR **pubalg,
+ ASN1_BIT_STRING **pubkey,
+ ASN1_OCTET_STRING **keyid,
+ X509_NAME **issuer,
+ ASN1_INTEGER **sno);
+
+int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert);
+
+int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek,
+ ASN1_OCTET_STRING **keyid,
+ ASN1_GENERALIZEDTIME **tm,
+ CMS_OtherKeyAttribute **other,
+ X509_NAME **issuer, ASN1_INTEGER **sno);
+int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek,
+ X509 *cert);
+int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk);
+int CMS_RecipientInfo_kari_set0_pkey_and_peer(CMS_RecipientInfo *ri, EVP_PKEY *pk, X509 *peer);
+EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri);
+int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms,
+ CMS_RecipientInfo *ri,
+ CMS_RecipientEncryptedKey *rek);
+
+int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg,
+ ASN1_OCTET_STRING *ukm, int keylen);
+
+/* Backward compatibility for spelling errors. */
+# define CMS_R_UNKNOWN_DIGEST_ALGORITM CMS_R_UNKNOWN_DIGEST_ALGORITHM
+# define CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE \
+ CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE
+
+# ifdef __cplusplus
+}
+# endif
+# endif
+#endif
diff --git a/include/openssl/cmserr.h b/include/openssl/cmserr.h
index d589f592c805..d48c2a4ab89f 100644
--- a/include/openssl/cmserr.h
+++ b/include/openssl/cmserr.h
@@ -1,115 +1,24 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_CMSERR_H
-# define HEADER_CMSERR_H
-
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+#ifndef OPENSSL_CMSERR_H
+# define OPENSSL_CMSERR_H
+# pragma once
# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifndef OPENSSL_NO_CMS
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_CMS_strings(void);
+# ifndef OPENSSL_NO_CMS
-/*
- * CMS function codes.
- */
-# define CMS_F_CHECK_CONTENT 99
-# define CMS_F_CMS_ADD0_CERT 164
-# define CMS_F_CMS_ADD0_RECIPIENT_KEY 100
-# define CMS_F_CMS_ADD0_RECIPIENT_PASSWORD 165
-# define CMS_F_CMS_ADD1_RECEIPTREQUEST 158
-# define CMS_F_CMS_ADD1_RECIPIENT_CERT 101
-# define CMS_F_CMS_ADD1_SIGNER 102
-# define CMS_F_CMS_ADD1_SIGNINGTIME 103
-# define CMS_F_CMS_COMPRESS 104
-# define CMS_F_CMS_COMPRESSEDDATA_CREATE 105
-# define CMS_F_CMS_COMPRESSEDDATA_INIT_BIO 106
-# define CMS_F_CMS_COPY_CONTENT 107
-# define CMS_F_CMS_COPY_MESSAGEDIGEST 108
-# define CMS_F_CMS_DATA 109
-# define CMS_F_CMS_DATAFINAL 110
-# define CMS_F_CMS_DATAINIT 111
-# define CMS_F_CMS_DECRYPT 112
-# define CMS_F_CMS_DECRYPT_SET1_KEY 113
-# define CMS_F_CMS_DECRYPT_SET1_PASSWORD 166
-# define CMS_F_CMS_DECRYPT_SET1_PKEY 114
-# define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX 115
-# define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO 116
-# define CMS_F_CMS_DIGESTEDDATA_DO_FINAL 117
-# define CMS_F_CMS_DIGEST_VERIFY 118
-# define CMS_F_CMS_ENCODE_RECEIPT 161
-# define CMS_F_CMS_ENCRYPT 119
-# define CMS_F_CMS_ENCRYPTEDCONTENT_INIT 179
-# define CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO 120
-# define CMS_F_CMS_ENCRYPTEDDATA_DECRYPT 121
-# define CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT 122
-# define CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY 123
-# define CMS_F_CMS_ENVELOPEDDATA_CREATE 124
-# define CMS_F_CMS_ENVELOPEDDATA_INIT_BIO 125
-# define CMS_F_CMS_ENVELOPED_DATA_INIT 126
-# define CMS_F_CMS_ENV_ASN1_CTRL 171
-# define CMS_F_CMS_FINAL 127
-# define CMS_F_CMS_GET0_CERTIFICATE_CHOICES 128
-# define CMS_F_CMS_GET0_CONTENT 129
-# define CMS_F_CMS_GET0_ECONTENT_TYPE 130
-# define CMS_F_CMS_GET0_ENVELOPED 131
-# define CMS_F_CMS_GET0_REVOCATION_CHOICES 132
-# define CMS_F_CMS_GET0_SIGNED 133
-# define CMS_F_CMS_MSGSIGDIGEST_ADD1 162
-# define CMS_F_CMS_RECEIPTREQUEST_CREATE0 159
-# define CMS_F_CMS_RECEIPT_VERIFY 160
-# define CMS_F_CMS_RECIPIENTINFO_DECRYPT 134
-# define CMS_F_CMS_RECIPIENTINFO_ENCRYPT 169
-# define CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT 178
-# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG 175
-# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID 173
-# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS 172
-# define CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP 174
-# define CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT 135
-# define CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT 136
-# define CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID 137
-# define CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP 138
-# define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP 139
-# define CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT 140
-# define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT 141
-# define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS 142
-# define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID 143
-# define CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT 167
-# define CMS_F_CMS_RECIPIENTINFO_SET0_KEY 144
-# define CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD 168
-# define CMS_F_CMS_RECIPIENTINFO_SET0_PKEY 145
-# define CMS_F_CMS_SD_ASN1_CTRL 170
-# define CMS_F_CMS_SET1_IAS 176
-# define CMS_F_CMS_SET1_KEYID 177
-# define CMS_F_CMS_SET1_SIGNERIDENTIFIER 146
-# define CMS_F_CMS_SET_DETACHED 147
-# define CMS_F_CMS_SIGN 148
-# define CMS_F_CMS_SIGNED_DATA_INIT 149
-# define CMS_F_CMS_SIGNERINFO_CONTENT_SIGN 150
-# define CMS_F_CMS_SIGNERINFO_SIGN 151
-# define CMS_F_CMS_SIGNERINFO_VERIFY 152
-# define CMS_F_CMS_SIGNERINFO_VERIFY_CERT 153
-# define CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT 154
-# define CMS_F_CMS_SIGN_RECEIPT 163
-# define CMS_F_CMS_SI_CHECK_ATTRIBUTES 183
-# define CMS_F_CMS_STREAM 155
-# define CMS_F_CMS_UNCOMPRESS 156
-# define CMS_F_CMS_VERIFY 157
-# define CMS_F_KEK_UNWRAP_KEY 180
/*
* CMS reason codes.
@@ -119,6 +28,8 @@ int ERR_load_CMS_strings(void);
# define CMS_R_CERTIFICATE_ALREADY_PRESENT 175
# define CMS_R_CERTIFICATE_HAS_NO_KEYID 160
# define CMS_R_CERTIFICATE_VERIFY_ERROR 100
+# define CMS_R_CIPHER_AEAD_SET_TAG_ERROR 184
+# define CMS_R_CIPHER_GET_TAG 185
# define CMS_R_CIPHER_INITIALISATION_ERROR 101
# define CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR 102
# define CMS_R_CMS_DATAFINAL_ERROR 103
@@ -132,14 +43,19 @@ int ERR_load_CMS_strings(void);
# define CMS_R_CONTENT_VERIFY_ERROR 109
# define CMS_R_CTRL_ERROR 110
# define CMS_R_CTRL_FAILURE 111
+# define CMS_R_DECODE_ERROR 187
# define CMS_R_DECRYPT_ERROR 112
# define CMS_R_ERROR_GETTING_PUBLIC_KEY 113
# define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE 114
# define CMS_R_ERROR_SETTING_KEY 115
# define CMS_R_ERROR_SETTING_RECIPIENTINFO 116
+# define CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR 183
# define CMS_R_INVALID_ENCRYPTED_KEY_LENGTH 117
# define CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER 176
# define CMS_R_INVALID_KEY_LENGTH 118
+# define CMS_R_INVALID_LABEL 190
+# define CMS_R_INVALID_OAEP_PARAMETERS 191
+# define CMS_R_KDF_PARAMETER_ERROR 186
# define CMS_R_MD_BIO_INIT_ERROR 119
# define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH 120
# define CMS_R_MESSAGEDIGEST_WRONG_LENGTH 121
@@ -170,9 +86,11 @@ int ERR_load_CMS_strings(void);
# define CMS_R_NO_PUBLIC_KEY 134
# define CMS_R_NO_RECEIPT_REQUEST 168
# define CMS_R_NO_SIGNERS 135
+# define CMS_R_PEER_KEY_ERROR 188
# define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 136
# define CMS_R_RECEIPT_DECODE_ERROR 169
# define CMS_R_RECIPIENT_ERROR 137
+# define CMS_R_SHARED_INFO_ERROR 189
# define CMS_R_SIGNER_CERTIFICATE_NOT_FOUND 138
# define CMS_R_SIGNFINAL_ERROR 139
# define CMS_R_SMIME_TEXT_ERROR 140
@@ -189,8 +107,10 @@ int ERR_load_CMS_strings(void);
# define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM 151
# define CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM 194
# define CMS_R_UNSUPPORTED_CONTENT_TYPE 152
+# define CMS_R_UNSUPPORTED_ENCRYPTION_TYPE 192
# define CMS_R_UNSUPPORTED_KEK_ALGORITHM 153
# define CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM 179
+# define CMS_R_UNSUPPORTED_LABEL_SOURCE 193
# define CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE 155
# define CMS_R_UNSUPPORTED_RECIPIENT_TYPE 154
# define CMS_R_UNSUPPORTED_TYPE 156
diff --git a/include/openssl/comp.h b/include/openssl/comp.h
index d814d3cf2518..06ff58100ff0 100644
--- a/include/openssl/comp.h
+++ b/include/openssl/comp.h
@@ -1,14 +1,20 @@
/*
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_COMP_H
-# define HEADER_COMP_H
+#ifndef OPENSSL_COMP_H
+# define OPENSSL_COMP_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_COMP_H
+# endif
# include <openssl/opensslconf.h>
@@ -35,11 +41,11 @@ int COMP_expand_block(COMP_CTX *ctx, unsigned char *out, int olen,
COMP_METHOD *COMP_zlib(void);
-#if OPENSSL_API_COMPAT < 0x10100000L
-#define COMP_zlib_cleanup() while(0) continue
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define COMP_zlib_cleanup() while(0) continue
#endif
-# ifdef HEADER_BIO_H
+# ifdef OPENSSL_BIO_H
# ifdef ZLIB
const BIO_METHOD *BIO_f_zlib(void);
# endif
diff --git a/include/openssl/comperr.h b/include/openssl/comperr.h
index 90231e9aa34f..01dd3e6bc642 100644
--- a/include/openssl/comperr.h
+++ b/include/openssl/comperr.h
@@ -1,37 +1,24 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_COMPERR_H
-# define HEADER_COMPERR_H
-
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+#ifndef OPENSSL_COMPERR_H
+# define OPENSSL_COMPERR_H
+# pragma once
# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifndef OPENSSL_NO_COMP
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_COMP_strings(void);
+# ifndef OPENSSL_NO_COMP
-/*
- * COMP function codes.
- */
-# define COMP_F_BIO_ZLIB_FLUSH 99
-# define COMP_F_BIO_ZLIB_NEW 100
-# define COMP_F_BIO_ZLIB_READ 101
-# define COMP_F_BIO_ZLIB_WRITE 102
-# define COMP_F_COMP_CTX_NEW 103
/*
* COMP reason codes.
diff --git a/include/openssl/conf.h b/include/openssl/conf.h
deleted file mode 100644
index 7336cd2f1d1a..000000000000
--- a/include/openssl/conf.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_CONF_H
-# define HEADER_CONF_H
-
-# include <openssl/bio.h>
-# include <openssl/lhash.h>
-# include <openssl/safestack.h>
-# include <openssl/e_os2.h>
-# include <openssl/ossl_typ.h>
-# include <openssl/conferr.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct {
- char *section;
- char *name;
- char *value;
-} CONF_VALUE;
-
-DEFINE_STACK_OF(CONF_VALUE)
-DEFINE_LHASH_OF(CONF_VALUE);
-
-struct conf_st;
-struct conf_method_st;
-typedef struct conf_method_st CONF_METHOD;
-
-struct conf_method_st {
- const char *name;
- CONF *(*create) (CONF_METHOD *meth);
- int (*init) (CONF *conf);
- int (*destroy) (CONF *conf);
- int (*destroy_data) (CONF *conf);
- int (*load_bio) (CONF *conf, BIO *bp, long *eline);
- int (*dump) (const CONF *conf, BIO *bp);
- int (*is_number) (const CONF *conf, char c);
- int (*to_int) (const CONF *conf, char c);
- int (*load) (CONF *conf, const char *name, long *eline);
-};
-
-/* Module definitions */
-
-typedef struct conf_imodule_st CONF_IMODULE;
-typedef struct conf_module_st CONF_MODULE;
-
-DEFINE_STACK_OF(CONF_MODULE)
-DEFINE_STACK_OF(CONF_IMODULE)
-
-/* DSO module function typedefs */
-typedef int conf_init_func (CONF_IMODULE *md, const CONF *cnf);
-typedef void conf_finish_func (CONF_IMODULE *md);
-
-# define CONF_MFLAGS_IGNORE_ERRORS 0x1
-# define CONF_MFLAGS_IGNORE_RETURN_CODES 0x2
-# define CONF_MFLAGS_SILENT 0x4
-# define CONF_MFLAGS_NO_DSO 0x8
-# define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10
-# define CONF_MFLAGS_DEFAULT_SECTION 0x20
-
-int CONF_set_default_method(CONF_METHOD *meth);
-void CONF_set_nconf(CONF *conf, LHASH_OF(CONF_VALUE) *hash);
-LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file,
- long *eline);
-# ifndef OPENSSL_NO_STDIO
-LHASH_OF(CONF_VALUE) *CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp,
- long *eline);
-# endif
-LHASH_OF(CONF_VALUE) *CONF_load_bio(LHASH_OF(CONF_VALUE) *conf, BIO *bp,
- long *eline);
-STACK_OF(CONF_VALUE) *CONF_get_section(LHASH_OF(CONF_VALUE) *conf,
- const char *section);
-char *CONF_get_string(LHASH_OF(CONF_VALUE) *conf, const char *group,
- const char *name);
-long CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group,
- const char *name);
-void CONF_free(LHASH_OF(CONF_VALUE) *conf);
-#ifndef OPENSSL_NO_STDIO
-int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out);
-#endif
-int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out);
-
-DEPRECATEDIN_1_1_0(void OPENSSL_config(const char *config_name))
-
-#if OPENSSL_API_COMPAT < 0x10100000L
-# define OPENSSL_no_config() \
- OPENSSL_init_crypto(OPENSSL_INIT_NO_LOAD_CONFIG, NULL)
-#endif
-
-/*
- * New conf code. The semantics are different from the functions above. If
- * that wasn't the case, the above functions would have been replaced
- */
-
-struct conf_st {
- CONF_METHOD *meth;
- void *meth_data;
- LHASH_OF(CONF_VALUE) *data;
-};
-
-CONF *NCONF_new(CONF_METHOD *meth);
-CONF_METHOD *NCONF_default(void);
-CONF_METHOD *NCONF_WIN32(void);
-void NCONF_free(CONF *conf);
-void NCONF_free_data(CONF *conf);
-
-int NCONF_load(CONF *conf, const char *file, long *eline);
-# ifndef OPENSSL_NO_STDIO
-int NCONF_load_fp(CONF *conf, FILE *fp, long *eline);
-# endif
-int NCONF_load_bio(CONF *conf, BIO *bp, long *eline);
-STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf,
- const char *section);
-char *NCONF_get_string(const CONF *conf, const char *group, const char *name);
-int NCONF_get_number_e(const CONF *conf, const char *group, const char *name,
- long *result);
-#ifndef OPENSSL_NO_STDIO
-int NCONF_dump_fp(const CONF *conf, FILE *out);
-#endif
-int NCONF_dump_bio(const CONF *conf, BIO *out);
-
-#define NCONF_get_number(c,g,n,r) NCONF_get_number_e(c,g,n,r)
-
-/* Module functions */
-
-int CONF_modules_load(const CONF *cnf, const char *appname,
- unsigned long flags);
-int CONF_modules_load_file(const char *filename, const char *appname,
- unsigned long flags);
-void CONF_modules_unload(int all);
-void CONF_modules_finish(void);
-#if OPENSSL_API_COMPAT < 0x10100000L
-# define CONF_modules_free() while(0) continue
-#endif
-int CONF_module_add(const char *name, conf_init_func *ifunc,
- conf_finish_func *ffunc);
-
-const char *CONF_imodule_get_name(const CONF_IMODULE *md);
-const char *CONF_imodule_get_value(const CONF_IMODULE *md);
-void *CONF_imodule_get_usr_data(const CONF_IMODULE *md);
-void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data);
-CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md);
-unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md);
-void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags);
-void *CONF_module_get_usr_data(CONF_MODULE *pmod);
-void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data);
-
-char *CONF_get1_default_config_file(void);
-
-int CONF_parse_list(const char *list, int sep, int nospc,
- int (*list_cb) (const char *elem, int len, void *usr),
- void *arg);
-
-void OPENSSL_load_builtin_modules(void);
-
-
-# ifdef __cplusplus
-}
-# endif
-#endif
diff --git a/include/openssl/conf.h.in b/include/openssl/conf.h.in
new file mode 100644
index 000000000000..b0bd579aa489
--- /dev/null
+++ b/include/openssl/conf.h.in
@@ -0,0 +1,174 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros generate_lhash_macros);
+-}
+
+#ifndef OPENSSL_CONF_H
+# define OPENSSL_CONF_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_CONF_H
+# endif
+
+# include <openssl/bio.h>
+# include <openssl/lhash.h>
+# include <openssl/safestack.h>
+# include <openssl/e_os2.h>
+# include <openssl/types.h>
+# include <openssl/conferr.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ char *section;
+ char *name;
+ char *value;
+} CONF_VALUE;
+
+{-
+ generate_stack_macros("CONF_VALUE")
+ .generate_lhash_macros("CONF_VALUE");
+-}
+
+struct conf_st;
+struct conf_method_st;
+typedef struct conf_method_st CONF_METHOD;
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# include <openssl/conftypes.h>
+# endif
+
+/* Module definitions */
+typedef struct conf_imodule_st CONF_IMODULE;
+typedef struct conf_module_st CONF_MODULE;
+
+STACK_OF(CONF_MODULE);
+STACK_OF(CONF_IMODULE);
+
+/* DSO module function typedefs */
+typedef int conf_init_func (CONF_IMODULE *md, const CONF *cnf);
+typedef void conf_finish_func (CONF_IMODULE *md);
+
+# define CONF_MFLAGS_IGNORE_ERRORS 0x1
+# define CONF_MFLAGS_IGNORE_RETURN_CODES 0x2
+# define CONF_MFLAGS_SILENT 0x4
+# define CONF_MFLAGS_NO_DSO 0x8
+# define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10
+# define CONF_MFLAGS_DEFAULT_SECTION 0x20
+
+int CONF_set_default_method(CONF_METHOD *meth);
+void CONF_set_nconf(CONF *conf, LHASH_OF(CONF_VALUE) *hash);
+LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file,
+ long *eline);
+# ifndef OPENSSL_NO_STDIO
+LHASH_OF(CONF_VALUE) *CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp,
+ long *eline);
+# endif
+LHASH_OF(CONF_VALUE) *CONF_load_bio(LHASH_OF(CONF_VALUE) *conf, BIO *bp,
+ long *eline);
+STACK_OF(CONF_VALUE) *CONF_get_section(LHASH_OF(CONF_VALUE) *conf,
+ const char *section);
+char *CONF_get_string(LHASH_OF(CONF_VALUE) *conf, const char *group,
+ const char *name);
+long CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group,
+ const char *name);
+void CONF_free(LHASH_OF(CONF_VALUE) *conf);
+#ifndef OPENSSL_NO_STDIO
+int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out);
+#endif
+int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out);
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 void OPENSSL_config(const char *config_name);
+#endif
+
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define OPENSSL_no_config() \
+ OPENSSL_init_crypto(OPENSSL_INIT_NO_LOAD_CONFIG, NULL)
+#endif
+
+/*
+ * New conf code. The semantics are different from the functions above. If
+ * that wasn't the case, the above functions would have been replaced
+ */
+
+CONF *NCONF_new_ex(OSSL_LIB_CTX *libctx, CONF_METHOD *meth);
+OSSL_LIB_CTX *NCONF_get0_libctx(const CONF *conf);
+CONF *NCONF_new(CONF_METHOD *meth);
+CONF_METHOD *NCONF_default(void);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 CONF_METHOD *NCONF_WIN32(void);
+#endif
+void NCONF_free(CONF *conf);
+void NCONF_free_data(CONF *conf);
+
+int NCONF_load(CONF *conf, const char *file, long *eline);
+# ifndef OPENSSL_NO_STDIO
+int NCONF_load_fp(CONF *conf, FILE *fp, long *eline);
+# endif
+int NCONF_load_bio(CONF *conf, BIO *bp, long *eline);
+STACK_OF(OPENSSL_CSTRING) *NCONF_get_section_names(const CONF *conf);
+STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf,
+ const char *section);
+char *NCONF_get_string(const CONF *conf, const char *group, const char *name);
+int NCONF_get_number_e(const CONF *conf, const char *group, const char *name,
+ long *result);
+#ifndef OPENSSL_NO_STDIO
+int NCONF_dump_fp(const CONF *conf, FILE *out);
+#endif
+int NCONF_dump_bio(const CONF *conf, BIO *out);
+
+#define NCONF_get_number(c,g,n,r) NCONF_get_number_e(c,g,n,r)
+
+/* Module functions */
+
+int CONF_modules_load(const CONF *cnf, const char *appname,
+ unsigned long flags);
+int CONF_modules_load_file_ex(OSSL_LIB_CTX *libctx, const char *filename,
+ const char *appname, unsigned long flags);
+int CONF_modules_load_file(const char *filename, const char *appname,
+ unsigned long flags);
+void CONF_modules_unload(int all);
+void CONF_modules_finish(void);
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define CONF_modules_free() while(0) continue
+#endif
+int CONF_module_add(const char *name, conf_init_func *ifunc,
+ conf_finish_func *ffunc);
+
+const char *CONF_imodule_get_name(const CONF_IMODULE *md);
+const char *CONF_imodule_get_value(const CONF_IMODULE *md);
+void *CONF_imodule_get_usr_data(const CONF_IMODULE *md);
+void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data);
+CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md);
+unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md);
+void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags);
+void *CONF_module_get_usr_data(CONF_MODULE *pmod);
+void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data);
+
+char *CONF_get1_default_config_file(void);
+
+int CONF_parse_list(const char *list, int sep, int nospc,
+ int (*list_cb) (const char *elem, int len, void *usr),
+ void *arg);
+
+void OPENSSL_load_builtin_modules(void);
+
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/conf_api.h b/include/openssl/conf_api.h
index a0275ad79bc4..ed67d5778f1d 100644
--- a/include/openssl/conf_api.h
+++ b/include/openssl/conf_api.h
@@ -1,14 +1,20 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_CONF_API_H
-# define HEADER_CONF_API_H
+#ifndef OPENSSL_CONF_API_H
+# define OPENSSL_CONF_API_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_CONF_API_H
+# endif
# include <openssl/lhash.h>
# include <openssl/conf.h>
diff --git a/include/openssl/conferr.h b/include/openssl/conferr.h
index 32b922918566..496e2e1efd66 100644
--- a/include/openssl/conferr.h
+++ b/include/openssl/conferr.h
@@ -1,57 +1,30 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_CONFERR_H
-# define HEADER_CONFERR_H
+#ifndef OPENSSL_CONFERR_H
+# define OPENSSL_CONFERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_CONF_strings(void);
-/*
- * CONF function codes.
- */
-# define CONF_F_CONF_DUMP_FP 104
-# define CONF_F_CONF_LOAD 100
-# define CONF_F_CONF_LOAD_FP 103
-# define CONF_F_CONF_PARSE_LIST 119
-# define CONF_F_DEF_LOAD 120
-# define CONF_F_DEF_LOAD_BIO 121
-# define CONF_F_GET_NEXT_FILE 107
-# define CONF_F_MODULE_ADD 122
-# define CONF_F_MODULE_INIT 115
-# define CONF_F_MODULE_LOAD_DSO 117
-# define CONF_F_MODULE_RUN 118
-# define CONF_F_NCONF_DUMP_BIO 105
-# define CONF_F_NCONF_DUMP_FP 106
-# define CONF_F_NCONF_GET_NUMBER_E 112
-# define CONF_F_NCONF_GET_SECTION 108
-# define CONF_F_NCONF_GET_STRING 109
-# define CONF_F_NCONF_LOAD 113
-# define CONF_F_NCONF_LOAD_BIO 110
-# define CONF_F_NCONF_LOAD_FP 114
-# define CONF_F_NCONF_NEW 111
-# define CONF_F_PROCESS_INCLUDE 116
-# define CONF_F_SSL_MODULE_INIT 123
-# define CONF_F_STR_COPY 101
/*
* CONF reason codes.
*/
# define CONF_R_ERROR_LOADING_DSO 110
+# define CONF_R_INVALID_PRAGMA 122
# define CONF_R_LIST_CANNOT_BE_NULL 115
+# define CONF_R_MANDATORY_BRACES_IN_VARIABLE_EXPANSION 123
# define CONF_R_MISSING_CLOSE_SQUARE_BRACKET 100
# define CONF_R_MISSING_EQUAL_SIGN 101
# define CONF_R_MISSING_INIT_FUNCTION 112
@@ -63,7 +36,9 @@ int ERR_load_CONF_strings(void);
# define CONF_R_NO_SUCH_FILE 114
# define CONF_R_NO_VALUE 108
# define CONF_R_NUMBER_TOO_LARGE 121
+# define CONF_R_OPENSSL_CONF_REFERENCES_MISSING_SECTION 124
# define CONF_R_RECURSIVE_DIRECTORY_INCLUDE 111
+# define CONF_R_RELATIVE_PATH 125
# define CONF_R_SSL_COMMAND_SECTION_EMPTY 117
# define CONF_R_SSL_COMMAND_SECTION_NOT_FOUND 118
# define CONF_R_SSL_SECTION_EMPTY 119
diff --git a/include/openssl/configuration.h.in b/include/openssl/configuration.h.in
new file mode 100644
index 000000000000..b84dc1dfe3c9
--- /dev/null
+++ b/include/openssl/configuration.h.in
@@ -0,0 +1,69 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_CONFIGURATION_H
+# define OPENSSL_CONFIGURATION_H
+# pragma once
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# ifdef OPENSSL_ALGORITHM_DEFINES
+# error OPENSSL_ALGORITHM_DEFINES no longer supported
+# endif
+
+/*
+ * OpenSSL was configured with the following options:
+ */
+
+{- if (@{$config{openssl_sys_defines}}) {
+ foreach (@{$config{openssl_sys_defines}}) {
+ $OUT .= "# ifndef $_\n";
+ $OUT .= "# define $_ 1\n";
+ $OUT .= "# endif\n";
+ }
+ }
+ foreach (@{$config{openssl_api_defines}}) {
+ (my $macro, my $value) = $_ =~ /^(.*?)=(.*?)$/;
+ $OUT .= "# define $macro $value\n";
+ }
+ if (@{$config{openssl_feature_defines}}) {
+ foreach (@{$config{openssl_feature_defines}}) {
+ $OUT .= "# ifndef $_\n";
+ $OUT .= "# define $_\n";
+ $OUT .= "# endif\n";
+ }
+ }
+ "";
+-}
+
+/* Generate 80386 code? */
+{- $config{processor} eq "386" ? "# define" : "# undef" -} I386_ONLY
+
+/*
+ * The following are cipher-specific, but are part of the public API.
+ */
+# if !defined(OPENSSL_SYS_UEFI)
+{- $config{bn_ll} ? "# define" : "# undef" -} BN_LLONG
+/* Only one for the following should be defined */
+{- $config{b64l} ? "# define" : "# undef" -} SIXTY_FOUR_BIT_LONG
+{- $config{b64} ? "# define" : "# undef" -} SIXTY_FOUR_BIT
+{- $config{b32} ? "# define" : "# undef" -} THIRTY_TWO_BIT
+# endif
+
+# define RC4_INT {- $config{rc4_int} -}
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif /* OPENSSL_CONFIGURATION_H */
diff --git a/include/openssl/conftypes.h b/include/openssl/conftypes.h
new file mode 100644
index 000000000000..17cefaa44335
--- /dev/null
+++ b/include/openssl/conftypes.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_CONFTYPES_H
+# define OPENSSL_CONFTYPES_H
+# pragma once
+
+#ifndef OPENSSL_CONF_H
+# include <openssl/conf.h>
+#endif
+
+/*
+ * The contents of this file are deprecated and will be made opaque
+ */
+struct conf_method_st {
+ const char *name;
+ CONF *(*create) (CONF_METHOD *meth);
+ int (*init) (CONF *conf);
+ int (*destroy) (CONF *conf);
+ int (*destroy_data) (CONF *conf);
+ int (*load_bio) (CONF *conf, BIO *bp, long *eline);
+ int (*dump) (const CONF *conf, BIO *bp);
+ int (*is_number) (const CONF *conf, char c);
+ int (*to_int) (const CONF *conf, char c);
+ int (*load) (CONF *conf, const char *name, long *eline);
+};
+
+struct conf_st {
+ CONF_METHOD *meth;
+ void *meth_data;
+ LHASH_OF(CONF_VALUE) *data;
+ int flag_dollarid;
+ int flag_abspath;
+ char *includedir;
+ OSSL_LIB_CTX *libctx;
+};
+
+#endif
diff --git a/include/openssl/core.h b/include/openssl/core.h
new file mode 100644
index 000000000000..9683ac70a55c
--- /dev/null
+++ b/include/openssl/core.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_CORE_H
+# define OPENSSL_CORE_H
+# pragma once
+
+# include <stddef.h>
+# include <openssl/types.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/*-
+ * Base types
+ * ----------
+ *
+ * These are the types that the OpenSSL core and providers have in common
+ * to communicate data between them.
+ */
+
+/* Opaque handles to be used with core upcall functions from providers */
+typedef struct ossl_core_handle_st OSSL_CORE_HANDLE;
+typedef struct openssl_core_ctx_st OPENSSL_CORE_CTX;
+typedef struct ossl_core_bio_st OSSL_CORE_BIO;
+
+/*
+ * Dispatch table element. function_id numbers and the functions are defined
+ * in core_dispatch.h, see macros with 'OSSL_CORE_MAKE_FUNC' in their names.
+ *
+ * An array of these is always terminated by function_id == 0
+ */
+struct ossl_dispatch_st {
+ int function_id;
+ void (*function)(void);
+};
+
+/*
+ * Other items, essentially an int<->pointer map element.
+ *
+ * We make this type distinct from OSSL_DISPATCH to ensure that dispatch
+ * tables remain tables with function pointers only.
+ *
+ * This is used whenever we need to pass things like a table of error reason
+ * codes <-> reason string maps, ...
+ *
+ * Usage determines which field works as key if any, rather than field order.
+ *
+ * An array of these is always terminated by id == 0 && ptr == NULL
+ */
+struct ossl_item_st {
+ unsigned int id;
+ void *ptr;
+};
+
+/*
+ * Type to tie together algorithm names, property definition string and
+ * the algorithm implementation in the form of a dispatch table.
+ *
+ * An array of these is always terminated by algorithm_names == NULL
+ */
+struct ossl_algorithm_st {
+ const char *algorithm_names; /* key */
+ const char *property_definition; /* key */
+ const OSSL_DISPATCH *implementation;
+ const char *algorithm_description;
+};
+
+/*
+ * Type to pass object data in a uniform way, without exposing the object
+ * structure.
+ *
+ * An array of these is always terminated by key == NULL
+ */
+struct ossl_param_st {
+ const char *key; /* the name of the parameter */
+ unsigned int data_type; /* declare what kind of content is in buffer */
+ void *data; /* value being passed in or out */
+ size_t data_size; /* data size */
+ size_t return_size; /* returned content size */
+};
+
+/* Currently supported OSSL_PARAM data types */
+/*
+ * OSSL_PARAM_INTEGER and OSSL_PARAM_UNSIGNED_INTEGER
+ * are arbitrary length and therefore require an arbitrarily sized buffer,
+ * since they may be used to pass numbers larger than what is natively
+ * available.
+ *
+ * The number must be buffered in native form, i.e. MSB first on B_ENDIAN
+ * systems and LSB first on L_ENDIAN systems. This means that arbitrary
+ * native integers can be stored in the buffer, just make sure that the
+ * buffer size is correct and the buffer itself is properly aligned (for
+ * example by having the buffer field point at a C integer).
+ */
+# define OSSL_PARAM_INTEGER 1
+# define OSSL_PARAM_UNSIGNED_INTEGER 2
+/*-
+ * OSSL_PARAM_REAL
+ * is a C binary floating point values in native form and alignment.
+ */
+# define OSSL_PARAM_REAL 3
+/*-
+ * OSSL_PARAM_UTF8_STRING
+ * is a printable string. It is expected to be printed as it is.
+ */
+# define OSSL_PARAM_UTF8_STRING 4
+/*-
+ * OSSL_PARAM_OCTET_STRING
+ * is a string of bytes with no further specification. It is expected to be
+ * printed as a hexdump.
+ */
+# define OSSL_PARAM_OCTET_STRING 5
+/*-
+ * OSSL_PARAM_UTF8_PTR
+ * is a pointer to a printable string. It is expected to be printed as it is.
+ *
+ * The difference between this and OSSL_PARAM_UTF8_STRING is that only pointers
+ * are manipulated for this type.
+ *
+ * This is more relevant for parameter requests, where the responding
+ * function doesn't need to copy the data to the provided buffer, but
+ * sets the provided buffer to point at the actual data instead.
+ *
+ * WARNING! Using these is FRAGILE, as it assumes that the actual
+ * data and its location are constant.
+ *
+ * EXTRA WARNING! If you are not completely sure you most likely want
+ * to use the OSSL_PARAM_UTF8_STRING type.
+ */
+# define OSSL_PARAM_UTF8_PTR 6
+/*-
+ * OSSL_PARAM_OCTET_PTR
+ * is a pointer to a string of bytes with no further specification. It is
+ * expected to be printed as a hexdump.
+ *
+ * The difference between this and OSSL_PARAM_OCTET_STRING is that only pointers
+ * are manipulated for this type.
+ *
+ * This is more relevant for parameter requests, where the responding
+ * function doesn't need to copy the data to the provided buffer, but
+ * sets the provided buffer to point at the actual data instead.
+ *
+ * WARNING! Using these is FRAGILE, as it assumes that the actual
+ * data and its location are constant.
+ *
+ * EXTRA WARNING! If you are not completely sure you most likely want
+ * to use the OSSL_PARAM_OCTET_STRING type.
+ */
+# define OSSL_PARAM_OCTET_PTR 7
+
+/*
+ * Typedef for the thread stop handling callback. Used both internally and by
+ * providers.
+ *
+ * Providers may register for notifications about threads stopping by
+ * registering a callback to hear about such events. Providers register the
+ * callback using the OSSL_FUNC_CORE_THREAD_START function in the |in| dispatch
+ * table passed to OSSL_provider_init(). The arg passed back to a provider will
+ * be the provider side context object.
+ */
+typedef void (*OSSL_thread_stop_handler_fn)(void *arg);
+
+
+/*-
+ * Provider entry point
+ * --------------------
+ *
+ * This function is expected to be present in any dynamically loadable
+ * provider module. By definition, if this function doesn't exist in a
+ * module, that module is not an OpenSSL provider module.
+ */
+/*-
+ * |handle| pointer to opaque type OSSL_CORE_HANDLE. This can be used
+ * together with some functions passed via |in| to query data.
+ * |in| is the array of functions that the Core passes to the provider.
+ * |out| will be the array of base functions that the provider passes
+ * back to the Core.
+ * |provctx| a provider side context object, optionally created if the
+ * provider needs it. This value is passed to other provider
+ * functions, notably other context constructors.
+ */
+typedef int (OSSL_provider_init_fn)(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in,
+ const OSSL_DISPATCH **out,
+ void **provctx);
+# ifdef __VMS
+# pragma names save
+# pragma names uppercase,truncated
+# endif
+OPENSSL_EXPORT OSSL_provider_init_fn OSSL_provider_init;
+# ifdef __VMS
+# pragma names restore
+# endif
+
+/*
+ * Generic callback function signature.
+ *
+ * The expectation is that any provider function that wants to offer
+ * a callback / hook can do so by taking an argument with this type,
+ * as well as a pointer to caller-specific data. When calling the
+ * callback, the provider function can populate an OSSL_PARAM array
+ * with data of its choice and pass that in the callback call, along
+ * with the caller data argument.
+ *
+ * libcrypto may use the OSSL_PARAM array to create arguments for an
+ * application callback it knows about.
+ */
+typedef int (OSSL_CALLBACK)(const OSSL_PARAM params[], void *arg);
+typedef int (OSSL_INOUT_CALLBACK)(const OSSL_PARAM in_params[],
+ OSSL_PARAM out_params[], void *arg);
+/*
+ * Passphrase callback function signature
+ *
+ * This is similar to the generic callback function above, but adds a
+ * result parameter.
+ */
+typedef int (OSSL_PASSPHRASE_CALLBACK)(char *pass, size_t pass_size,
+ size_t *pass_len,
+ const OSSL_PARAM params[], void *arg);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h
new file mode 100644
index 000000000000..99fcda00200a
--- /dev/null
+++ b/include/openssl/core_dispatch.h
@@ -0,0 +1,943 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_CORE_NUMBERS_H
+# define OPENSSL_CORE_NUMBERS_H
+# pragma once
+
+# include <stdarg.h>
+# include <openssl/core.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/*-
+ * Identities
+ * ----------
+ *
+ * All series start with 1, to allow 0 to be an array terminator.
+ * For any FUNC identity, we also provide a function signature typedef
+ * and a static inline function to extract a function pointer from a
+ * OSSL_DISPATCH element in a type safe manner.
+ *
+ * Names:
+ * for any function base name 'foo' (uppercase form 'FOO'), we will have
+ * the following:
+ * - a macro for the identity with the name OSSL_FUNC_'FOO' or derivatives
+ * thereof (to be specified further down)
+ * - a function signature typedef with the name OSSL_FUNC_'foo'_fn
+ * - a function pointer extractor function with the name OSSL_FUNC_'foo'
+ */
+
+/*
+ * Helper macro to create the function signature typedef and the extractor
+ * |type| is the return-type of the function, |name| is the name of the
+ * function to fetch, and |args| is a parenthesized list of parameters
+ * for the function (that is, it is |name|'s function signature).
+ * Note: This is considered a "reserved" internal macro. Applications should
+ * not use this or assume its existence.
+ */
+#define OSSL_CORE_MAKE_FUNC(type,name,args) \
+ typedef type (OSSL_FUNC_##name##_fn)args; \
+ static ossl_unused ossl_inline \
+ OSSL_FUNC_##name##_fn *OSSL_FUNC_##name(const OSSL_DISPATCH *opf) \
+ { \
+ return (OSSL_FUNC_##name##_fn *)opf->function; \
+ }
+
+/*
+ * Core function identities, for the two OSSL_DISPATCH tables being passed
+ * in the OSSL_provider_init call.
+ *
+ * 0 serves as a marker for the end of the OSSL_DISPATCH array, and must
+ * therefore NEVER be used as a function identity.
+ */
+/* Functions provided by the Core to the provider, reserved numbers 1-1023 */
+# define OSSL_FUNC_CORE_GETTABLE_PARAMS 1
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *,
+ core_gettable_params,(const OSSL_CORE_HANDLE *prov))
+# define OSSL_FUNC_CORE_GET_PARAMS 2
+OSSL_CORE_MAKE_FUNC(int,core_get_params,(const OSSL_CORE_HANDLE *prov,
+ OSSL_PARAM params[]))
+# define OSSL_FUNC_CORE_THREAD_START 3
+OSSL_CORE_MAKE_FUNC(int,core_thread_start,(const OSSL_CORE_HANDLE *prov,
+ OSSL_thread_stop_handler_fn handfn,
+ void *arg))
+# define OSSL_FUNC_CORE_GET_LIBCTX 4
+OSSL_CORE_MAKE_FUNC(OPENSSL_CORE_CTX *,core_get_libctx,
+ (const OSSL_CORE_HANDLE *prov))
+# define OSSL_FUNC_CORE_NEW_ERROR 5
+OSSL_CORE_MAKE_FUNC(void,core_new_error,(const OSSL_CORE_HANDLE *prov))
+# define OSSL_FUNC_CORE_SET_ERROR_DEBUG 6
+OSSL_CORE_MAKE_FUNC(void,core_set_error_debug,
+ (const OSSL_CORE_HANDLE *prov,
+ const char *file, int line, const char *func))
+# define OSSL_FUNC_CORE_VSET_ERROR 7
+OSSL_CORE_MAKE_FUNC(void,core_vset_error,
+ (const OSSL_CORE_HANDLE *prov,
+ uint32_t reason, const char *fmt, va_list args))
+# define OSSL_FUNC_CORE_SET_ERROR_MARK 8
+OSSL_CORE_MAKE_FUNC(int, core_set_error_mark, (const OSSL_CORE_HANDLE *prov))
+# define OSSL_FUNC_CORE_CLEAR_LAST_ERROR_MARK 9
+OSSL_CORE_MAKE_FUNC(int, core_clear_last_error_mark,
+ (const OSSL_CORE_HANDLE *prov))
+# define OSSL_FUNC_CORE_POP_ERROR_TO_MARK 10
+OSSL_CORE_MAKE_FUNC(int, core_pop_error_to_mark, (const OSSL_CORE_HANDLE *prov))
+
+
+/* Functions to access the OBJ database */
+
+#define OSSL_FUNC_CORE_OBJ_ADD_SIGID 11
+#define OSSL_FUNC_CORE_OBJ_CREATE 12
+
+OSSL_CORE_MAKE_FUNC(int, core_obj_add_sigid,
+ (const OSSL_CORE_HANDLE *prov, const char *sign_name,
+ const char *digest_name, const char *pkey_name))
+OSSL_CORE_MAKE_FUNC(int, core_obj_create,
+ (const OSSL_CORE_HANDLE *prov, const char *oid,
+ const char *sn, const char *ln))
+
+/* Memory allocation, freeing, clearing. */
+#define OSSL_FUNC_CRYPTO_MALLOC 20
+OSSL_CORE_MAKE_FUNC(void *,
+ CRYPTO_malloc, (size_t num, const char *file, int line))
+#define OSSL_FUNC_CRYPTO_ZALLOC 21
+OSSL_CORE_MAKE_FUNC(void *,
+ CRYPTO_zalloc, (size_t num, const char *file, int line))
+#define OSSL_FUNC_CRYPTO_FREE 22
+OSSL_CORE_MAKE_FUNC(void,
+ CRYPTO_free, (void *ptr, const char *file, int line))
+#define OSSL_FUNC_CRYPTO_CLEAR_FREE 23
+OSSL_CORE_MAKE_FUNC(void,
+ CRYPTO_clear_free, (void *ptr, size_t num, const char *file, int line))
+#define OSSL_FUNC_CRYPTO_REALLOC 24
+OSSL_CORE_MAKE_FUNC(void *,
+ CRYPTO_realloc, (void *addr, size_t num, const char *file, int line))
+#define OSSL_FUNC_CRYPTO_CLEAR_REALLOC 25
+OSSL_CORE_MAKE_FUNC(void *,
+ CRYPTO_clear_realloc, (void *addr, size_t old_num, size_t num,
+ const char *file, int line))
+#define OSSL_FUNC_CRYPTO_SECURE_MALLOC 26
+OSSL_CORE_MAKE_FUNC(void *,
+ CRYPTO_secure_malloc, (size_t num, const char *file, int line))
+#define OSSL_FUNC_CRYPTO_SECURE_ZALLOC 27
+OSSL_CORE_MAKE_FUNC(void *,
+ CRYPTO_secure_zalloc, (size_t num, const char *file, int line))
+#define OSSL_FUNC_CRYPTO_SECURE_FREE 28
+OSSL_CORE_MAKE_FUNC(void,
+ CRYPTO_secure_free, (void *ptr, const char *file, int line))
+#define OSSL_FUNC_CRYPTO_SECURE_CLEAR_FREE 29
+OSSL_CORE_MAKE_FUNC(void,
+ CRYPTO_secure_clear_free, (void *ptr, size_t num, const char *file,
+ int line))
+#define OSSL_FUNC_CRYPTO_SECURE_ALLOCATED 30
+OSSL_CORE_MAKE_FUNC(int,
+ CRYPTO_secure_allocated, (const void *ptr))
+#define OSSL_FUNC_OPENSSL_CLEANSE 31
+OSSL_CORE_MAKE_FUNC(void,
+ OPENSSL_cleanse, (void *ptr, size_t len))
+
+/* Bio functions provided by the core */
+#define OSSL_FUNC_BIO_NEW_FILE 40
+#define OSSL_FUNC_BIO_NEW_MEMBUF 41
+#define OSSL_FUNC_BIO_READ_EX 42
+#define OSSL_FUNC_BIO_WRITE_EX 43
+#define OSSL_FUNC_BIO_UP_REF 44
+#define OSSL_FUNC_BIO_FREE 45
+#define OSSL_FUNC_BIO_VPRINTF 46
+#define OSSL_FUNC_BIO_VSNPRINTF 47
+#define OSSL_FUNC_BIO_PUTS 48
+#define OSSL_FUNC_BIO_GETS 49
+#define OSSL_FUNC_BIO_CTRL 50
+
+
+OSSL_CORE_MAKE_FUNC(OSSL_CORE_BIO *, BIO_new_file, (const char *filename,
+ const char *mode))
+OSSL_CORE_MAKE_FUNC(OSSL_CORE_BIO *, BIO_new_membuf, (const void *buf, int len))
+OSSL_CORE_MAKE_FUNC(int, BIO_read_ex, (OSSL_CORE_BIO *bio, void *data,
+ size_t data_len, size_t *bytes_read))
+OSSL_CORE_MAKE_FUNC(int, BIO_write_ex, (OSSL_CORE_BIO *bio, const void *data,
+ size_t data_len, size_t *written))
+OSSL_CORE_MAKE_FUNC(int, BIO_gets, (OSSL_CORE_BIO *bio, char *buf, int size))
+OSSL_CORE_MAKE_FUNC(int, BIO_puts, (OSSL_CORE_BIO *bio, const char *str))
+OSSL_CORE_MAKE_FUNC(int, BIO_up_ref, (OSSL_CORE_BIO *bio))
+OSSL_CORE_MAKE_FUNC(int, BIO_free, (OSSL_CORE_BIO *bio))
+OSSL_CORE_MAKE_FUNC(int, BIO_vprintf, (OSSL_CORE_BIO *bio, const char *format,
+ va_list args))
+OSSL_CORE_MAKE_FUNC(int, BIO_vsnprintf,
+ (char *buf, size_t n, const char *fmt, va_list args))
+OSSL_CORE_MAKE_FUNC(int, BIO_ctrl, (OSSL_CORE_BIO *bio,
+ int cmd, long num, void *ptr))
+
+#define OSSL_FUNC_SELF_TEST_CB 100
+OSSL_CORE_MAKE_FUNC(void, self_test_cb, (OPENSSL_CORE_CTX *ctx, OSSL_CALLBACK **cb,
+ void **cbarg))
+
+/* Functions to get seed material from the operating system */
+#define OSSL_FUNC_GET_ENTROPY 101
+#define OSSL_FUNC_CLEANUP_ENTROPY 102
+#define OSSL_FUNC_GET_NONCE 103
+#define OSSL_FUNC_CLEANUP_NONCE 104
+OSSL_CORE_MAKE_FUNC(size_t, get_entropy, (const OSSL_CORE_HANDLE *handle,
+ unsigned char **pout, int entropy,
+ size_t min_len, size_t max_len))
+OSSL_CORE_MAKE_FUNC(void, cleanup_entropy, (const OSSL_CORE_HANDLE *handle,
+ unsigned char *buf, size_t len))
+OSSL_CORE_MAKE_FUNC(size_t, get_nonce, (const OSSL_CORE_HANDLE *handle,
+ unsigned char **pout, size_t min_len,
+ size_t max_len, const void *salt,
+ size_t salt_len))
+OSSL_CORE_MAKE_FUNC(void, cleanup_nonce, (const OSSL_CORE_HANDLE *handle,
+ unsigned char *buf, size_t len))
+
+/* Functions to access the core's providers */
+#define OSSL_FUNC_PROVIDER_REGISTER_CHILD_CB 105
+#define OSSL_FUNC_PROVIDER_DEREGISTER_CHILD_CB 106
+#define OSSL_FUNC_PROVIDER_NAME 107
+#define OSSL_FUNC_PROVIDER_GET0_PROVIDER_CTX 108
+#define OSSL_FUNC_PROVIDER_GET0_DISPATCH 109
+#define OSSL_FUNC_PROVIDER_UP_REF 110
+#define OSSL_FUNC_PROVIDER_FREE 111
+
+OSSL_CORE_MAKE_FUNC(int, provider_register_child_cb,
+ (const OSSL_CORE_HANDLE *handle,
+ int (*create_cb)(const OSSL_CORE_HANDLE *provider, void *cbdata),
+ int (*remove_cb)(const OSSL_CORE_HANDLE *provider, void *cbdata),
+ int (*global_props_cb)(const char *props, void *cbdata),
+ void *cbdata))
+OSSL_CORE_MAKE_FUNC(void, provider_deregister_child_cb,
+ (const OSSL_CORE_HANDLE *handle))
+OSSL_CORE_MAKE_FUNC(const char *, provider_name,
+ (const OSSL_CORE_HANDLE *prov))
+OSSL_CORE_MAKE_FUNC(void *, provider_get0_provider_ctx,
+ (const OSSL_CORE_HANDLE *prov))
+OSSL_CORE_MAKE_FUNC(const OSSL_DISPATCH *, provider_get0_dispatch,
+ (const OSSL_CORE_HANDLE *prov))
+OSSL_CORE_MAKE_FUNC(int, provider_up_ref,
+ (const OSSL_CORE_HANDLE *prov, int activate))
+OSSL_CORE_MAKE_FUNC(int, provider_free,
+ (const OSSL_CORE_HANDLE *prov, int deactivate))
+
+/* Functions provided by the provider to the Core, reserved numbers 1024-1535 */
+# define OSSL_FUNC_PROVIDER_TEARDOWN 1024
+OSSL_CORE_MAKE_FUNC(void,provider_teardown,(void *provctx))
+# define OSSL_FUNC_PROVIDER_GETTABLE_PARAMS 1025
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *,
+ provider_gettable_params,(void *provctx))
+# define OSSL_FUNC_PROVIDER_GET_PARAMS 1026
+OSSL_CORE_MAKE_FUNC(int,provider_get_params,(void *provctx,
+ OSSL_PARAM params[]))
+# define OSSL_FUNC_PROVIDER_QUERY_OPERATION 1027
+OSSL_CORE_MAKE_FUNC(const OSSL_ALGORITHM *,provider_query_operation,
+ (void *provctx, int operation_id, int *no_store))
+# define OSSL_FUNC_PROVIDER_UNQUERY_OPERATION 1028
+OSSL_CORE_MAKE_FUNC(void, provider_unquery_operation,
+ (void *provctx, int operation_id, const OSSL_ALGORITHM *))
+# define OSSL_FUNC_PROVIDER_GET_REASON_STRINGS 1029
+OSSL_CORE_MAKE_FUNC(const OSSL_ITEM *,provider_get_reason_strings,
+ (void *provctx))
+# define OSSL_FUNC_PROVIDER_GET_CAPABILITIES 1030
+OSSL_CORE_MAKE_FUNC(int, provider_get_capabilities, (void *provctx,
+ const char *capability, OSSL_CALLBACK *cb, void *arg))
+# define OSSL_FUNC_PROVIDER_SELF_TEST 1031
+OSSL_CORE_MAKE_FUNC(int, provider_self_test, (void *provctx))
+
+/* Operations */
+
+# define OSSL_OP_DIGEST 1
+# define OSSL_OP_CIPHER 2 /* Symmetric Ciphers */
+# define OSSL_OP_MAC 3
+# define OSSL_OP_KDF 4
+# define OSSL_OP_RAND 5
+# define OSSL_OP_KEYMGMT 10
+# define OSSL_OP_KEYEXCH 11
+# define OSSL_OP_SIGNATURE 12
+# define OSSL_OP_ASYM_CIPHER 13
+# define OSSL_OP_KEM 14
+/* New section for non-EVP operations */
+# define OSSL_OP_ENCODER 20
+# define OSSL_OP_DECODER 21
+# define OSSL_OP_STORE 22
+/* Highest known operation number */
+# define OSSL_OP__HIGHEST 22
+
+/* Digests */
+
+# define OSSL_FUNC_DIGEST_NEWCTX 1
+# define OSSL_FUNC_DIGEST_INIT 2
+# define OSSL_FUNC_DIGEST_UPDATE 3
+# define OSSL_FUNC_DIGEST_FINAL 4
+# define OSSL_FUNC_DIGEST_DIGEST 5
+# define OSSL_FUNC_DIGEST_FREECTX 6
+# define OSSL_FUNC_DIGEST_DUPCTX 7
+# define OSSL_FUNC_DIGEST_GET_PARAMS 8
+# define OSSL_FUNC_DIGEST_SET_CTX_PARAMS 9
+# define OSSL_FUNC_DIGEST_GET_CTX_PARAMS 10
+# define OSSL_FUNC_DIGEST_GETTABLE_PARAMS 11
+# define OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS 12
+# define OSSL_FUNC_DIGEST_GETTABLE_CTX_PARAMS 13
+
+OSSL_CORE_MAKE_FUNC(void *, digest_newctx, (void *provctx))
+OSSL_CORE_MAKE_FUNC(int, digest_init, (void *dctx, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, digest_update,
+ (void *dctx, const unsigned char *in, size_t inl))
+OSSL_CORE_MAKE_FUNC(int, digest_final,
+ (void *dctx,
+ unsigned char *out, size_t *outl, size_t outsz))
+OSSL_CORE_MAKE_FUNC(int, digest_digest,
+ (void *provctx, const unsigned char *in, size_t inl,
+ unsigned char *out, size_t *outl, size_t outsz))
+
+OSSL_CORE_MAKE_FUNC(void, digest_freectx, (void *dctx))
+OSSL_CORE_MAKE_FUNC(void *, digest_dupctx, (void *dctx))
+
+OSSL_CORE_MAKE_FUNC(int, digest_get_params, (OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, digest_set_ctx_params,
+ (void *vctx, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, digest_get_ctx_params,
+ (void *vctx, OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, digest_gettable_params,
+ (void *provctx))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, digest_settable_ctx_params,
+ (void *dctx, void *provctx))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, digest_gettable_ctx_params,
+ (void *dctx, void *provctx))
+
+/* Symmetric Ciphers */
+
+# define OSSL_FUNC_CIPHER_NEWCTX 1
+# define OSSL_FUNC_CIPHER_ENCRYPT_INIT 2
+# define OSSL_FUNC_CIPHER_DECRYPT_INIT 3
+# define OSSL_FUNC_CIPHER_UPDATE 4
+# define OSSL_FUNC_CIPHER_FINAL 5
+# define OSSL_FUNC_CIPHER_CIPHER 6
+# define OSSL_FUNC_CIPHER_FREECTX 7
+# define OSSL_FUNC_CIPHER_DUPCTX 8
+# define OSSL_FUNC_CIPHER_GET_PARAMS 9
+# define OSSL_FUNC_CIPHER_GET_CTX_PARAMS 10
+# define OSSL_FUNC_CIPHER_SET_CTX_PARAMS 11
+# define OSSL_FUNC_CIPHER_GETTABLE_PARAMS 12
+# define OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS 13
+# define OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS 14
+
+OSSL_CORE_MAKE_FUNC(void *, cipher_newctx, (void *provctx))
+OSSL_CORE_MAKE_FUNC(int, cipher_encrypt_init, (void *cctx,
+ const unsigned char *key,
+ size_t keylen,
+ const unsigned char *iv,
+ size_t ivlen,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, cipher_decrypt_init, (void *cctx,
+ const unsigned char *key,
+ size_t keylen,
+ const unsigned char *iv,
+ size_t ivlen,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, cipher_update,
+ (void *cctx,
+ unsigned char *out, size_t *outl, size_t outsize,
+ const unsigned char *in, size_t inl))
+OSSL_CORE_MAKE_FUNC(int, cipher_final,
+ (void *cctx,
+ unsigned char *out, size_t *outl, size_t outsize))
+OSSL_CORE_MAKE_FUNC(int, cipher_cipher,
+ (void *cctx,
+ unsigned char *out, size_t *outl, size_t outsize,
+ const unsigned char *in, size_t inl))
+OSSL_CORE_MAKE_FUNC(void, cipher_freectx, (void *cctx))
+OSSL_CORE_MAKE_FUNC(void *, cipher_dupctx, (void *cctx))
+OSSL_CORE_MAKE_FUNC(int, cipher_get_params, (OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, cipher_get_ctx_params, (void *cctx,
+ OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, cipher_set_ctx_params, (void *cctx,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, cipher_gettable_params,
+ (void *provctx))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, cipher_settable_ctx_params,
+ (void *cctx, void *provctx))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, cipher_gettable_ctx_params,
+ (void *cctx, void *provctx))
+
+/* MACs */
+
+# define OSSL_FUNC_MAC_NEWCTX 1
+# define OSSL_FUNC_MAC_DUPCTX 2
+# define OSSL_FUNC_MAC_FREECTX 3
+# define OSSL_FUNC_MAC_INIT 4
+# define OSSL_FUNC_MAC_UPDATE 5
+# define OSSL_FUNC_MAC_FINAL 6
+# define OSSL_FUNC_MAC_GET_PARAMS 7
+# define OSSL_FUNC_MAC_GET_CTX_PARAMS 8
+# define OSSL_FUNC_MAC_SET_CTX_PARAMS 9
+# define OSSL_FUNC_MAC_GETTABLE_PARAMS 10
+# define OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS 11
+# define OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS 12
+
+OSSL_CORE_MAKE_FUNC(void *, mac_newctx, (void *provctx))
+OSSL_CORE_MAKE_FUNC(void *, mac_dupctx, (void *src))
+OSSL_CORE_MAKE_FUNC(void, mac_freectx, (void *mctx))
+OSSL_CORE_MAKE_FUNC(int, mac_init, (void *mctx, const unsigned char *key,
+ size_t keylen, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, mac_update,
+ (void *mctx, const unsigned char *in, size_t inl))
+OSSL_CORE_MAKE_FUNC(int, mac_final,
+ (void *mctx,
+ unsigned char *out, size_t *outl, size_t outsize))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, mac_gettable_params, (void *provctx))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, mac_gettable_ctx_params,
+ (void *mctx, void *provctx))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, mac_settable_ctx_params,
+ (void *mctx, void *provctx))
+OSSL_CORE_MAKE_FUNC(int, mac_get_params, (OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, mac_get_ctx_params,
+ (void *mctx, OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, mac_set_ctx_params,
+ (void *mctx, const OSSL_PARAM params[]))
+
+/* KDFs and PRFs */
+
+# define OSSL_FUNC_KDF_NEWCTX 1
+# define OSSL_FUNC_KDF_DUPCTX 2
+# define OSSL_FUNC_KDF_FREECTX 3
+# define OSSL_FUNC_KDF_RESET 4
+# define OSSL_FUNC_KDF_DERIVE 5
+# define OSSL_FUNC_KDF_GETTABLE_PARAMS 6
+# define OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS 7
+# define OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS 8
+# define OSSL_FUNC_KDF_GET_PARAMS 9
+# define OSSL_FUNC_KDF_GET_CTX_PARAMS 10
+# define OSSL_FUNC_KDF_SET_CTX_PARAMS 11
+
+OSSL_CORE_MAKE_FUNC(void *, kdf_newctx, (void *provctx))
+OSSL_CORE_MAKE_FUNC(void *, kdf_dupctx, (void *src))
+OSSL_CORE_MAKE_FUNC(void, kdf_freectx, (void *kctx))
+OSSL_CORE_MAKE_FUNC(void, kdf_reset, (void *kctx))
+OSSL_CORE_MAKE_FUNC(int, kdf_derive, (void *kctx, unsigned char *key,
+ size_t keylen, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, kdf_gettable_params, (void *provctx))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, kdf_gettable_ctx_params,
+ (void *kctx, void *provctx))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, kdf_settable_ctx_params,
+ (void *kctx, void *provctx))
+OSSL_CORE_MAKE_FUNC(int, kdf_get_params, (OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, kdf_get_ctx_params,
+ (void *kctx, OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, kdf_set_ctx_params,
+ (void *kctx, const OSSL_PARAM params[]))
+
+/* RAND */
+
+# define OSSL_FUNC_RAND_NEWCTX 1
+# define OSSL_FUNC_RAND_FREECTX 2
+# define OSSL_FUNC_RAND_INSTANTIATE 3
+# define OSSL_FUNC_RAND_UNINSTANTIATE 4
+# define OSSL_FUNC_RAND_GENERATE 5
+# define OSSL_FUNC_RAND_RESEED 6
+# define OSSL_FUNC_RAND_NONCE 7
+# define OSSL_FUNC_RAND_ENABLE_LOCKING 8
+# define OSSL_FUNC_RAND_LOCK 9
+# define OSSL_FUNC_RAND_UNLOCK 10
+# define OSSL_FUNC_RAND_GETTABLE_PARAMS 11
+# define OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS 12
+# define OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS 13
+# define OSSL_FUNC_RAND_GET_PARAMS 14
+# define OSSL_FUNC_RAND_GET_CTX_PARAMS 15
+# define OSSL_FUNC_RAND_SET_CTX_PARAMS 16
+# define OSSL_FUNC_RAND_VERIFY_ZEROIZATION 17
+# define OSSL_FUNC_RAND_GET_SEED 18
+# define OSSL_FUNC_RAND_CLEAR_SEED 19
+
+OSSL_CORE_MAKE_FUNC(void *,rand_newctx,
+ (void *provctx, void *parent,
+ const OSSL_DISPATCH *parent_calls))
+OSSL_CORE_MAKE_FUNC(void,rand_freectx, (void *vctx))
+OSSL_CORE_MAKE_FUNC(int,rand_instantiate,
+ (void *vdrbg, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *pstr, size_t pstr_len,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int,rand_uninstantiate, (void *vdrbg))
+OSSL_CORE_MAKE_FUNC(int,rand_generate,
+ (void *vctx, unsigned char *out, size_t outlen,
+ unsigned int strength, int prediction_resistance,
+ const unsigned char *addin, size_t addin_len))
+OSSL_CORE_MAKE_FUNC(int,rand_reseed,
+ (void *vctx, int prediction_resistance,
+ const unsigned char *ent, size_t ent_len,
+ const unsigned char *addin, size_t addin_len))
+OSSL_CORE_MAKE_FUNC(size_t,rand_nonce,
+ (void *vctx, unsigned char *out, unsigned int strength,
+ size_t min_noncelen, size_t max_noncelen))
+OSSL_CORE_MAKE_FUNC(int,rand_enable_locking, (void *vctx))
+OSSL_CORE_MAKE_FUNC(int,rand_lock, (void *vctx))
+OSSL_CORE_MAKE_FUNC(void,rand_unlock, (void *vctx))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *,rand_gettable_params, (void *provctx))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *,rand_gettable_ctx_params,
+ (void *vctx, void *provctx))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *,rand_settable_ctx_params,
+ (void *vctx, void *provctx))
+OSSL_CORE_MAKE_FUNC(int,rand_get_params, (OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int,rand_get_ctx_params,
+ (void *vctx, OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int,rand_set_ctx_params,
+ (void *vctx, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(void,rand_set_callbacks,
+ (void *vctx, OSSL_INOUT_CALLBACK *get_entropy,
+ OSSL_CALLBACK *cleanup_entropy,
+ OSSL_INOUT_CALLBACK *get_nonce,
+ OSSL_CALLBACK *cleanup_nonce, void *arg))
+OSSL_CORE_MAKE_FUNC(int,rand_verify_zeroization,
+ (void *vctx))
+OSSL_CORE_MAKE_FUNC(size_t,rand_get_seed,
+ (void *vctx, unsigned char **buffer,
+ int entropy, size_t min_len, size_t max_len,
+ int prediction_resistance,
+ const unsigned char *adin, size_t adin_len))
+OSSL_CORE_MAKE_FUNC(void,rand_clear_seed,
+ (void *vctx, unsigned char *buffer, size_t b_len))
+
+/*-
+ * Key management
+ *
+ * The Key Management takes care of provider side key objects, and includes
+ * all current functionality to create them, destroy them, set parameters
+ * and key material, etc, essentially everything that manipulates the keys
+ * themselves and their parameters.
+ *
+ * The key objects are commonly refered to as |keydata|, and it MUST be able
+ * to contain parameters if the key has any, the public key and the private
+ * key. All parts are optional, but their presence determines what can be
+ * done with the key object in terms of encryption, signature, and so on.
+ * The assumption from libcrypto is that the key object contains any of the
+ * following data combinations:
+ *
+ * - parameters only
+ * - public key only
+ * - public key + private key
+ * - parameters + public key
+ * - parameters + public key + private key
+ *
+ * What "parameters", "public key" and "private key" means in detail is left
+ * to the implementation. In the case of DH and DSA, they would typically
+ * include domain parameters, while for certain variants of RSA, they would
+ * typically include PSS or OAEP parameters.
+ *
+ * Key objects are created with OSSL_FUNC_keymgmt_new() and destroyed with
+ * OSSL_FUNC_keymgmt_free(). Key objects can have data filled in with
+ * OSSL_FUNC_keymgmt_import().
+ *
+ * Three functions are made available to check what selection of data is
+ * present in a key object: OSSL_FUNC_keymgmt_has_parameters(),
+ * OSSL_FUNC_keymgmt_has_public_key(), and OSSL_FUNC_keymgmt_has_private_key(),
+ */
+
+/* Key data subset selection - individual bits */
+# define OSSL_KEYMGMT_SELECT_PRIVATE_KEY 0x01
+# define OSSL_KEYMGMT_SELECT_PUBLIC_KEY 0x02
+# define OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS 0x04
+# define OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS 0x80
+
+/* Key data subset selection - combinations */
+# define OSSL_KEYMGMT_SELECT_ALL_PARAMETERS \
+ ( OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS \
+ | OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS)
+# define OSSL_KEYMGMT_SELECT_KEYPAIR \
+ ( OSSL_KEYMGMT_SELECT_PRIVATE_KEY | OSSL_KEYMGMT_SELECT_PUBLIC_KEY )
+# define OSSL_KEYMGMT_SELECT_ALL \
+ ( OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS )
+
+# define OSSL_KEYMGMT_VALIDATE_FULL_CHECK 0
+# define OSSL_KEYMGMT_VALIDATE_QUICK_CHECK 1
+
+/* Basic key object creation */
+# define OSSL_FUNC_KEYMGMT_NEW 1
+OSSL_CORE_MAKE_FUNC(void *, keymgmt_new, (void *provctx))
+
+/* Generation, a more complex constructor */
+# define OSSL_FUNC_KEYMGMT_GEN_INIT 2
+# define OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE 3
+# define OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS 4
+# define OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS 5
+# define OSSL_FUNC_KEYMGMT_GEN 6
+# define OSSL_FUNC_KEYMGMT_GEN_CLEANUP 7
+OSSL_CORE_MAKE_FUNC(void *, keymgmt_gen_init,
+ (void *provctx, int selection, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, keymgmt_gen_set_template,
+ (void *genctx, void *templ))
+OSSL_CORE_MAKE_FUNC(int, keymgmt_gen_set_params,
+ (void *genctx, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *,
+ keymgmt_gen_settable_params,
+ (void *genctx, void *provctx))
+OSSL_CORE_MAKE_FUNC(void *, keymgmt_gen,
+ (void *genctx, OSSL_CALLBACK *cb, void *cbarg))
+OSSL_CORE_MAKE_FUNC(void, keymgmt_gen_cleanup, (void *genctx))
+
+/* Key loading by object reference */
+# define OSSL_FUNC_KEYMGMT_LOAD 8
+OSSL_CORE_MAKE_FUNC(void *, keymgmt_load,
+ (const void *reference, size_t reference_sz))
+
+/* Basic key object destruction */
+# define OSSL_FUNC_KEYMGMT_FREE 10
+OSSL_CORE_MAKE_FUNC(void, keymgmt_free, (void *keydata))
+
+/* Key object information, with discovery */
+#define OSSL_FUNC_KEYMGMT_GET_PARAMS 11
+#define OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS 12
+OSSL_CORE_MAKE_FUNC(int, keymgmt_get_params,
+ (void *keydata, OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, keymgmt_gettable_params,
+ (void *provctx))
+
+#define OSSL_FUNC_KEYMGMT_SET_PARAMS 13
+#define OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS 14
+OSSL_CORE_MAKE_FUNC(int, keymgmt_set_params,
+ (void *keydata, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, keymgmt_settable_params,
+ (void *provctx))
+
+/* Key checks - discovery of supported operations */
+# define OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME 20
+OSSL_CORE_MAKE_FUNC(const char *, keymgmt_query_operation_name,
+ (int operation_id))
+
+/* Key checks - key data content checks */
+# define OSSL_FUNC_KEYMGMT_HAS 21
+OSSL_CORE_MAKE_FUNC(int, keymgmt_has, (const void *keydata, int selection))
+
+/* Key checks - validation */
+# define OSSL_FUNC_KEYMGMT_VALIDATE 22
+OSSL_CORE_MAKE_FUNC(int, keymgmt_validate, (const void *keydata, int selection,
+ int checktype))
+
+/* Key checks - matching */
+# define OSSL_FUNC_KEYMGMT_MATCH 23
+OSSL_CORE_MAKE_FUNC(int, keymgmt_match,
+ (const void *keydata1, const void *keydata2,
+ int selection))
+
+/* Import and export functions, with discovery */
+# define OSSL_FUNC_KEYMGMT_IMPORT 40
+# define OSSL_FUNC_KEYMGMT_IMPORT_TYPES 41
+# define OSSL_FUNC_KEYMGMT_EXPORT 42
+# define OSSL_FUNC_KEYMGMT_EXPORT_TYPES 43
+OSSL_CORE_MAKE_FUNC(int, keymgmt_import,
+ (void *keydata, int selection, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, keymgmt_import_types,
+ (int selection))
+OSSL_CORE_MAKE_FUNC(int, keymgmt_export,
+ (void *keydata, int selection,
+ OSSL_CALLBACK *param_cb, void *cbarg))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, keymgmt_export_types,
+ (int selection))
+
+/* Dup function, constructor */
+# define OSSL_FUNC_KEYMGMT_DUP 44
+OSSL_CORE_MAKE_FUNC(void *, keymgmt_dup,
+ (const void *keydata_from, int selection))
+
+/* Key Exchange */
+
+# define OSSL_FUNC_KEYEXCH_NEWCTX 1
+# define OSSL_FUNC_KEYEXCH_INIT 2
+# define OSSL_FUNC_KEYEXCH_DERIVE 3
+# define OSSL_FUNC_KEYEXCH_SET_PEER 4
+# define OSSL_FUNC_KEYEXCH_FREECTX 5
+# define OSSL_FUNC_KEYEXCH_DUPCTX 6
+# define OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS 7
+# define OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS 8
+# define OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS 9
+# define OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS 10
+
+OSSL_CORE_MAKE_FUNC(void *, keyexch_newctx, (void *provctx))
+OSSL_CORE_MAKE_FUNC(int, keyexch_init, (void *ctx, void *provkey,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, keyexch_derive, (void *ctx, unsigned char *secret,
+ size_t *secretlen, size_t outlen))
+OSSL_CORE_MAKE_FUNC(int, keyexch_set_peer, (void *ctx, void *provkey))
+OSSL_CORE_MAKE_FUNC(void, keyexch_freectx, (void *ctx))
+OSSL_CORE_MAKE_FUNC(void *, keyexch_dupctx, (void *ctx))
+OSSL_CORE_MAKE_FUNC(int, keyexch_set_ctx_params, (void *ctx,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, keyexch_settable_ctx_params,
+ (void *ctx, void *provctx))
+OSSL_CORE_MAKE_FUNC(int, keyexch_get_ctx_params, (void *ctx,
+ OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, keyexch_gettable_ctx_params,
+ (void *ctx, void *provctx))
+
+/* Signature */
+
+# define OSSL_FUNC_SIGNATURE_NEWCTX 1
+# define OSSL_FUNC_SIGNATURE_SIGN_INIT 2
+# define OSSL_FUNC_SIGNATURE_SIGN 3
+# define OSSL_FUNC_SIGNATURE_VERIFY_INIT 4
+# define OSSL_FUNC_SIGNATURE_VERIFY 5
+# define OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT 6
+# define OSSL_FUNC_SIGNATURE_VERIFY_RECOVER 7
+# define OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT 8
+# define OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE 9
+# define OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL 10
+# define OSSL_FUNC_SIGNATURE_DIGEST_SIGN 11
+# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT 12
+# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE 13
+# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL 14
+# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY 15
+# define OSSL_FUNC_SIGNATURE_FREECTX 16
+# define OSSL_FUNC_SIGNATURE_DUPCTX 17
+# define OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS 18
+# define OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS 19
+# define OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS 20
+# define OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS 21
+# define OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS 22
+# define OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS 23
+# define OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS 24
+# define OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS 25
+
+OSSL_CORE_MAKE_FUNC(void *, signature_newctx, (void *provctx,
+ const char *propq))
+OSSL_CORE_MAKE_FUNC(int, signature_sign_init, (void *ctx, void *provkey,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, signature_sign, (void *ctx, unsigned char *sig,
+ size_t *siglen, size_t sigsize,
+ const unsigned char *tbs,
+ size_t tbslen))
+OSSL_CORE_MAKE_FUNC(int, signature_verify_init, (void *ctx, void *provkey,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, signature_verify, (void *ctx,
+ const unsigned char *sig,
+ size_t siglen,
+ const unsigned char *tbs,
+ size_t tbslen))
+OSSL_CORE_MAKE_FUNC(int, signature_verify_recover_init,
+ (void *ctx, void *provkey, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, signature_verify_recover,
+ (void *ctx, unsigned char *rout, size_t *routlen,
+ size_t routsize, const unsigned char *sig, size_t siglen))
+OSSL_CORE_MAKE_FUNC(int, signature_digest_sign_init,
+ (void *ctx, const char *mdname, void *provkey,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, signature_digest_sign_update,
+ (void *ctx, const unsigned char *data, size_t datalen))
+OSSL_CORE_MAKE_FUNC(int, signature_digest_sign_final,
+ (void *ctx, unsigned char *sig, size_t *siglen,
+ size_t sigsize))
+OSSL_CORE_MAKE_FUNC(int, signature_digest_sign,
+ (void *ctx, unsigned char *sigret, size_t *siglen,
+ size_t sigsize, const unsigned char *tbs, size_t tbslen))
+OSSL_CORE_MAKE_FUNC(int, signature_digest_verify_init,
+ (void *ctx, const char *mdname, void *provkey,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, signature_digest_verify_update,
+ (void *ctx, const unsigned char *data, size_t datalen))
+OSSL_CORE_MAKE_FUNC(int, signature_digest_verify_final,
+ (void *ctx, const unsigned char *sig, size_t siglen))
+OSSL_CORE_MAKE_FUNC(int, signature_digest_verify,
+ (void *ctx, const unsigned char *sig, size_t siglen,
+ const unsigned char *tbs, size_t tbslen))
+OSSL_CORE_MAKE_FUNC(void, signature_freectx, (void *ctx))
+OSSL_CORE_MAKE_FUNC(void *, signature_dupctx, (void *ctx))
+OSSL_CORE_MAKE_FUNC(int, signature_get_ctx_params,
+ (void *ctx, OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, signature_gettable_ctx_params,
+ (void *ctx, void *provctx))
+OSSL_CORE_MAKE_FUNC(int, signature_set_ctx_params,
+ (void *ctx, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, signature_settable_ctx_params,
+ (void *ctx, void *provctx))
+OSSL_CORE_MAKE_FUNC(int, signature_get_ctx_md_params,
+ (void *ctx, OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, signature_gettable_ctx_md_params,
+ (void *ctx))
+OSSL_CORE_MAKE_FUNC(int, signature_set_ctx_md_params,
+ (void *ctx, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, signature_settable_ctx_md_params,
+ (void *ctx))
+
+
+/* Asymmetric Ciphers */
+
+# define OSSL_FUNC_ASYM_CIPHER_NEWCTX 1
+# define OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT 2
+# define OSSL_FUNC_ASYM_CIPHER_ENCRYPT 3
+# define OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT 4
+# define OSSL_FUNC_ASYM_CIPHER_DECRYPT 5
+# define OSSL_FUNC_ASYM_CIPHER_FREECTX 6
+# define OSSL_FUNC_ASYM_CIPHER_DUPCTX 7
+# define OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS 8
+# define OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS 9
+# define OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS 10
+# define OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS 11
+
+OSSL_CORE_MAKE_FUNC(void *, asym_cipher_newctx, (void *provctx))
+OSSL_CORE_MAKE_FUNC(int, asym_cipher_encrypt_init, (void *ctx, void *provkey,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, asym_cipher_encrypt, (void *ctx, unsigned char *out,
+ size_t *outlen,
+ size_t outsize,
+ const unsigned char *in,
+ size_t inlen))
+OSSL_CORE_MAKE_FUNC(int, asym_cipher_decrypt_init, (void *ctx, void *provkey,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, asym_cipher_decrypt, (void *ctx, unsigned char *out,
+ size_t *outlen,
+ size_t outsize,
+ const unsigned char *in,
+ size_t inlen))
+OSSL_CORE_MAKE_FUNC(void, asym_cipher_freectx, (void *ctx))
+OSSL_CORE_MAKE_FUNC(void *, asym_cipher_dupctx, (void *ctx))
+OSSL_CORE_MAKE_FUNC(int, asym_cipher_get_ctx_params,
+ (void *ctx, OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, asym_cipher_gettable_ctx_params,
+ (void *ctx, void *provctx))
+OSSL_CORE_MAKE_FUNC(int, asym_cipher_set_ctx_params,
+ (void *ctx, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, asym_cipher_settable_ctx_params,
+ (void *ctx, void *provctx))
+
+/* Asymmetric Key encapsulation */
+# define OSSL_FUNC_KEM_NEWCTX 1
+# define OSSL_FUNC_KEM_ENCAPSULATE_INIT 2
+# define OSSL_FUNC_KEM_ENCAPSULATE 3
+# define OSSL_FUNC_KEM_DECAPSULATE_INIT 4
+# define OSSL_FUNC_KEM_DECAPSULATE 5
+# define OSSL_FUNC_KEM_FREECTX 6
+# define OSSL_FUNC_KEM_DUPCTX 7
+# define OSSL_FUNC_KEM_GET_CTX_PARAMS 8
+# define OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS 9
+# define OSSL_FUNC_KEM_SET_CTX_PARAMS 10
+# define OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS 11
+
+OSSL_CORE_MAKE_FUNC(void *, kem_newctx, (void *provctx))
+OSSL_CORE_MAKE_FUNC(int, kem_encapsulate_init, (void *ctx, void *provkey,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, kem_encapsulate, (void *ctx,
+ unsigned char *out, size_t *outlen,
+ unsigned char *secret,
+ size_t *secretlen))
+OSSL_CORE_MAKE_FUNC(int, kem_decapsulate_init, (void *ctx, void *provkey,
+ const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, kem_decapsulate, (void *ctx,
+ unsigned char *out, size_t *outlen,
+ const unsigned char *in, size_t inlen))
+OSSL_CORE_MAKE_FUNC(void, kem_freectx, (void *ctx))
+OSSL_CORE_MAKE_FUNC(void *, kem_dupctx, (void *ctx))
+OSSL_CORE_MAKE_FUNC(int, kem_get_ctx_params, (void *ctx, OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, kem_gettable_ctx_params,
+ (void *ctx, void *provctx))
+OSSL_CORE_MAKE_FUNC(int, kem_set_ctx_params,
+ (void *ctx, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, kem_settable_ctx_params,
+ (void *ctx, void *provctx))
+
+/* Encoders and decoders */
+# define OSSL_FUNC_ENCODER_NEWCTX 1
+# define OSSL_FUNC_ENCODER_FREECTX 2
+# define OSSL_FUNC_ENCODER_GET_PARAMS 3
+# define OSSL_FUNC_ENCODER_GETTABLE_PARAMS 4
+# define OSSL_FUNC_ENCODER_SET_CTX_PARAMS 5
+# define OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS 6
+# define OSSL_FUNC_ENCODER_DOES_SELECTION 10
+# define OSSL_FUNC_ENCODER_ENCODE 11
+# define OSSL_FUNC_ENCODER_IMPORT_OBJECT 20
+# define OSSL_FUNC_ENCODER_FREE_OBJECT 21
+OSSL_CORE_MAKE_FUNC(void *, encoder_newctx, (void *provctx))
+OSSL_CORE_MAKE_FUNC(void, encoder_freectx, (void *ctx))
+OSSL_CORE_MAKE_FUNC(int, encoder_get_params, (OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, encoder_gettable_params,
+ (void *provctx))
+OSSL_CORE_MAKE_FUNC(int, encoder_set_ctx_params,
+ (void *ctx, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, encoder_settable_ctx_params,
+ (void *provctx))
+
+OSSL_CORE_MAKE_FUNC(int, encoder_does_selection,
+ (void *provctx, int selection))
+OSSL_CORE_MAKE_FUNC(int, encoder_encode,
+ (void *ctx, OSSL_CORE_BIO *out,
+ const void *obj_raw, const OSSL_PARAM obj_abstract[],
+ int selection,
+ OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg))
+
+OSSL_CORE_MAKE_FUNC(void *, encoder_import_object,
+ (void *ctx, int selection, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(void, encoder_free_object, (void *obj))
+
+# define OSSL_FUNC_DECODER_NEWCTX 1
+# define OSSL_FUNC_DECODER_FREECTX 2
+# define OSSL_FUNC_DECODER_GET_PARAMS 3
+# define OSSL_FUNC_DECODER_GETTABLE_PARAMS 4
+# define OSSL_FUNC_DECODER_SET_CTX_PARAMS 5
+# define OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS 6
+# define OSSL_FUNC_DECODER_DOES_SELECTION 10
+# define OSSL_FUNC_DECODER_DECODE 11
+# define OSSL_FUNC_DECODER_EXPORT_OBJECT 20
+OSSL_CORE_MAKE_FUNC(void *, decoder_newctx, (void *provctx))
+OSSL_CORE_MAKE_FUNC(void, decoder_freectx, (void *ctx))
+OSSL_CORE_MAKE_FUNC(int, decoder_get_params, (OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, decoder_gettable_params,
+ (void *provctx))
+OSSL_CORE_MAKE_FUNC(int, decoder_set_ctx_params,
+ (void *ctx, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, decoder_settable_ctx_params,
+ (void *provctx))
+
+OSSL_CORE_MAKE_FUNC(int, decoder_does_selection,
+ (void *provctx, int selection))
+OSSL_CORE_MAKE_FUNC(int, decoder_decode,
+ (void *ctx, OSSL_CORE_BIO *in, int selection,
+ OSSL_CALLBACK *data_cb, void *data_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg))
+OSSL_CORE_MAKE_FUNC(int, decoder_export_object,
+ (void *ctx, const void *objref, size_t objref_sz,
+ OSSL_CALLBACK *export_cb, void *export_cbarg))
+
+/*-
+ * Store
+ *
+ * Objects are scanned by using the 'open', 'load', 'eof' and 'close'
+ * functions, which implement an OSSL_STORE loader.
+ *
+ * store_load() works in a way that's very similar to the decoders, in
+ * that they pass an abstract object through a callback, either as a DER
+ * octet string or as an object reference, which libcrypto will have to
+ * deal with.
+ */
+
+#define OSSL_FUNC_STORE_OPEN 1
+#define OSSL_FUNC_STORE_ATTACH 2
+#define OSSL_FUNC_STORE_SETTABLE_CTX_PARAMS 3
+#define OSSL_FUNC_STORE_SET_CTX_PARAMS 4
+#define OSSL_FUNC_STORE_LOAD 5
+#define OSSL_FUNC_STORE_EOF 6
+#define OSSL_FUNC_STORE_CLOSE 7
+#define OSSL_FUNC_STORE_EXPORT_OBJECT 8
+OSSL_CORE_MAKE_FUNC(void *, store_open, (void *provctx, const char *uri))
+OSSL_CORE_MAKE_FUNC(void *, store_attach, (void *provctx, OSSL_CORE_BIO *in))
+OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, store_settable_ctx_params,
+ (void *provctx))
+OSSL_CORE_MAKE_FUNC(int, store_set_ctx_params,
+ (void *loaderctx, const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, store_load,
+ (void *loaderctx,
+ OSSL_CALLBACK *object_cb, void *object_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg))
+OSSL_CORE_MAKE_FUNC(int, store_eof, (void *loaderctx))
+OSSL_CORE_MAKE_FUNC(int, store_close, (void *loaderctx))
+OSSL_CORE_MAKE_FUNC(int, store_export_object,
+ (void *loaderctx, const void *objref, size_t objref_sz,
+ OSSL_CALLBACK *export_cb, void *export_cbarg))
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
new file mode 100644
index 000000000000..6bed5a8a670f
--- /dev/null
+++ b/include/openssl/core_names.h
@@ -0,0 +1,556 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_CORE_NAMES_H
+# define OPENSSL_CORE_NAMES_H
+# pragma once
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/* Well known parameter names that core passes to providers */
+#define OSSL_PROV_PARAM_CORE_VERSION "openssl-version" /* utf8_ptr */
+#define OSSL_PROV_PARAM_CORE_PROV_NAME "provider-name" /* utf8_ptr */
+#define OSSL_PROV_PARAM_CORE_MODULE_FILENAME "module-filename" /* utf8_ptr */
+
+/* Well known parameter names that Providers can define */
+#define OSSL_PROV_PARAM_NAME "name" /* utf8_ptr */
+#define OSSL_PROV_PARAM_VERSION "version" /* utf8_ptr */
+#define OSSL_PROV_PARAM_BUILDINFO "buildinfo" /* utf8_ptr */
+#define OSSL_PROV_PARAM_STATUS "status" /* uint */
+#define OSSL_PROV_PARAM_SECURITY_CHECKS "security-checks" /* uint */
+
+/* Self test callback parameters */
+#define OSSL_PROV_PARAM_SELF_TEST_PHASE "st-phase" /* utf8_string */
+#define OSSL_PROV_PARAM_SELF_TEST_TYPE "st-type" /* utf8_string */
+#define OSSL_PROV_PARAM_SELF_TEST_DESC "st-desc" /* utf8_string */
+
+/*-
+ * Provider-native object abstractions
+ *
+ * These are used when a provider wants to pass object data or an object
+ * reference back to libcrypto. This is only useful for provider functions
+ * that take a callback to which an OSSL_PARAM array with these parameters
+ * can be passed.
+ *
+ * This set of parameter names is explained in detail in provider-object(7)
+ * (doc/man7/provider-object.pod)
+ */
+#define OSSL_OBJECT_PARAM_TYPE "type" /* INTEGER */
+#define OSSL_OBJECT_PARAM_DATA_TYPE "data-type" /* UTF8_STRING */
+#define OSSL_OBJECT_PARAM_DATA_STRUCTURE "data-structure" /* UTF8_STRING */
+#define OSSL_OBJECT_PARAM_REFERENCE "reference" /* OCTET_STRING */
+#define OSSL_OBJECT_PARAM_DATA "data" /* OCTET_STRING or UTF8_STRING */
+#define OSSL_OBJECT_PARAM_DESC "desc" /* UTF8_STRING */
+
+/*
+ * Algorithm parameters
+ * If "engine" or "properties" are specified, they should always be paired
+ * with the algorithm type.
+ * Note these are common names that are shared by many types (such as kdf, mac,
+ * and pkey) e.g: see OSSL_MAC_PARAM_DIGEST below.
+ */
+#define OSSL_ALG_PARAM_DIGEST "digest" /* utf8_string */
+#define OSSL_ALG_PARAM_CIPHER "cipher" /* utf8_string */
+#define OSSL_ALG_PARAM_ENGINE "engine" /* utf8_string */
+#define OSSL_ALG_PARAM_MAC "mac" /* utf8_string */
+#define OSSL_ALG_PARAM_PROPERTIES "properties"/* utf8_string */
+
+/* cipher parameters */
+#define OSSL_CIPHER_PARAM_PADDING "padding" /* uint */
+#define OSSL_CIPHER_PARAM_USE_BITS "use-bits" /* uint */
+#define OSSL_CIPHER_PARAM_TLS_VERSION "tls-version" /* uint */
+#define OSSL_CIPHER_PARAM_TLS_MAC "tls-mac" /* octet_ptr */
+#define OSSL_CIPHER_PARAM_TLS_MAC_SIZE "tls-mac-size" /* size_t */
+#define OSSL_CIPHER_PARAM_MODE "mode" /* uint */
+#define OSSL_CIPHER_PARAM_BLOCK_SIZE "blocksize" /* size_t */
+#define OSSL_CIPHER_PARAM_AEAD "aead" /* int, 0 or 1 */
+#define OSSL_CIPHER_PARAM_CUSTOM_IV "custom-iv" /* int, 0 or 1 */
+#define OSSL_CIPHER_PARAM_CTS "cts" /* int, 0 or 1 */
+#define OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK "tls-multi" /* int, 0 or 1 */
+#define OSSL_CIPHER_PARAM_HAS_RAND_KEY "has-randkey" /* int, 0 or 1 */
+#define OSSL_CIPHER_PARAM_KEYLEN "keylen" /* size_t */
+#define OSSL_CIPHER_PARAM_IVLEN "ivlen" /* size_t */
+#define OSSL_CIPHER_PARAM_IV "iv" /* octet_string OR octet_ptr */
+#define OSSL_CIPHER_PARAM_UPDATED_IV "updated-iv" /* octet_string OR octet_ptr */
+#define OSSL_CIPHER_PARAM_NUM "num" /* uint */
+#define OSSL_CIPHER_PARAM_ROUNDS "rounds" /* uint */
+#define OSSL_CIPHER_PARAM_AEAD_TAG "tag" /* octet_string */
+#define OSSL_CIPHER_PARAM_AEAD_TLS1_AAD "tlsaad" /* octet_string */
+#define OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD "tlsaadpad" /* size_t */
+#define OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED "tlsivfixed" /* octet_string */
+#define OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN "tlsivgen" /* octet_string */
+#define OSSL_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV "tlsivinv" /* octet_string */
+#define OSSL_CIPHER_PARAM_AEAD_IVLEN OSSL_CIPHER_PARAM_IVLEN
+#define OSSL_CIPHER_PARAM_AEAD_TAGLEN "taglen" /* size_t */
+#define OSSL_CIPHER_PARAM_AEAD_MAC_KEY "mackey" /* octet_string */
+#define OSSL_CIPHER_PARAM_RANDOM_KEY "randkey" /* octet_string */
+#define OSSL_CIPHER_PARAM_RC2_KEYBITS "keybits" /* size_t */
+#define OSSL_CIPHER_PARAM_SPEED "speed" /* uint */
+#define OSSL_CIPHER_PARAM_CTS_MODE "cts_mode" /* utf8_string */
+/* For passing the AlgorithmIdentifier parameter in DER form */
+#define OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS "alg_id_param" /* octet_string */
+
+#define OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT \
+ "tls1multi_maxsndfrag" /* uint */
+#define OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE \
+ "tls1multi_maxbufsz" /* size_t */
+#define OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE \
+ "tls1multi_interleave" /* uint */
+#define OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD \
+ "tls1multi_aad" /* octet_string */
+#define OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN \
+ "tls1multi_aadpacklen" /* uint */
+#define OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC \
+ "tls1multi_enc" /* octet_string */
+#define OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN \
+ "tls1multi_encin" /* octet_string */
+#define OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN \
+ "tls1multi_enclen" /* size_t */
+
+/* OSSL_CIPHER_PARAM_CTS_MODE Values */
+#define OSSL_CIPHER_CTS_MODE_CS1 "CS1"
+#define OSSL_CIPHER_CTS_MODE_CS2 "CS2"
+#define OSSL_CIPHER_CTS_MODE_CS3 "CS3"
+
+/* digest parameters */
+#define OSSL_DIGEST_PARAM_XOFLEN "xoflen" /* size_t */
+#define OSSL_DIGEST_PARAM_SSL3_MS "ssl3-ms" /* octet string */
+#define OSSL_DIGEST_PARAM_PAD_TYPE "pad-type" /* uint */
+#define OSSL_DIGEST_PARAM_MICALG "micalg" /* utf8 string */
+#define OSSL_DIGEST_PARAM_BLOCK_SIZE "blocksize" /* size_t */
+#define OSSL_DIGEST_PARAM_SIZE "size" /* size_t */
+#define OSSL_DIGEST_PARAM_XOF "xof" /* int, 0 or 1 */
+#define OSSL_DIGEST_PARAM_ALGID_ABSENT "algid-absent" /* int, 0 or 1 */
+
+/* Known DIGEST names (not a complete list) */
+#define OSSL_DIGEST_NAME_MD5 "MD5"
+#define OSSL_DIGEST_NAME_MD5_SHA1 "MD5-SHA1"
+#define OSSL_DIGEST_NAME_SHA1 "SHA1"
+#define OSSL_DIGEST_NAME_SHA2_224 "SHA2-224"
+#define OSSL_DIGEST_NAME_SHA2_256 "SHA2-256"
+#define OSSL_DIGEST_NAME_SHA2_384 "SHA2-384"
+#define OSSL_DIGEST_NAME_SHA2_512 "SHA2-512"
+#define OSSL_DIGEST_NAME_SHA2_512_224 "SHA2-512/224"
+#define OSSL_DIGEST_NAME_SHA2_512_256 "SHA2-512/256"
+#define OSSL_DIGEST_NAME_MD2 "MD2"
+#define OSSL_DIGEST_NAME_MD4 "MD4"
+#define OSSL_DIGEST_NAME_MDC2 "MDC2"
+#define OSSL_DIGEST_NAME_RIPEMD160 "RIPEMD160"
+#define OSSL_DIGEST_NAME_SHA3_224 "SHA3-224"
+#define OSSL_DIGEST_NAME_SHA3_256 "SHA3-256"
+#define OSSL_DIGEST_NAME_SHA3_384 "SHA3-384"
+#define OSSL_DIGEST_NAME_SHA3_512 "SHA3-512"
+#define OSSL_DIGEST_NAME_KECCAK_KMAC128 "KECCAK-KMAC-128"
+#define OSSL_DIGEST_NAME_KECCAK_KMAC256 "KECCAK-KMAC-256"
+#define OSSL_DIGEST_NAME_SM3 "SM3"
+
+/* MAC parameters */
+#define OSSL_MAC_PARAM_KEY "key" /* octet string */
+#define OSSL_MAC_PARAM_IV "iv" /* octet string */
+#define OSSL_MAC_PARAM_CUSTOM "custom" /* utf8 string */
+#define OSSL_MAC_PARAM_SALT "salt" /* octet string */
+#define OSSL_MAC_PARAM_XOF "xof" /* int, 0 or 1 */
+#define OSSL_MAC_PARAM_DIGEST_NOINIT "digest-noinit" /* int, 0 or 1 */
+#define OSSL_MAC_PARAM_DIGEST_ONESHOT "digest-oneshot" /* int, 0 or 1 */
+#define OSSL_MAC_PARAM_C_ROUNDS "c-rounds" /* unsigned int */
+#define OSSL_MAC_PARAM_D_ROUNDS "d-rounds" /* unsigned int */
+
+/*
+ * If "engine" or "properties" are specified, they should always be paired
+ * with "cipher" or "digest".
+ */
+#define OSSL_MAC_PARAM_CIPHER OSSL_ALG_PARAM_CIPHER /* utf8 string */
+#define OSSL_MAC_PARAM_DIGEST OSSL_ALG_PARAM_DIGEST /* utf8 string */
+#define OSSL_MAC_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES /* utf8 string */
+#define OSSL_MAC_PARAM_SIZE "size" /* size_t */
+#define OSSL_MAC_PARAM_BLOCK_SIZE "block-size" /* size_t */
+#define OSSL_MAC_PARAM_TLS_DATA_SIZE "tls-data-size" /* size_t */
+
+/* Known MAC names */
+#define OSSL_MAC_NAME_BLAKE2BMAC "BLAKE2BMAC"
+#define OSSL_MAC_NAME_BLAKE2SMAC "BLAKE2SMAC"
+#define OSSL_MAC_NAME_CMAC "CMAC"
+#define OSSL_MAC_NAME_GMAC "GMAC"
+#define OSSL_MAC_NAME_HMAC "HMAC"
+#define OSSL_MAC_NAME_KMAC128 "KMAC128"
+#define OSSL_MAC_NAME_KMAC256 "KMAC256"
+#define OSSL_MAC_NAME_POLY1305 "POLY1305"
+#define OSSL_MAC_NAME_SIPHASH "SIPHASH"
+
+/* KDF / PRF parameters */
+#define OSSL_KDF_PARAM_SECRET "secret" /* octet string */
+#define OSSL_KDF_PARAM_KEY "key" /* octet string */
+#define OSSL_KDF_PARAM_SALT "salt" /* octet string */
+#define OSSL_KDF_PARAM_PASSWORD "pass" /* octet string */
+#define OSSL_KDF_PARAM_PREFIX "prefix" /* octet string */
+#define OSSL_KDF_PARAM_LABEL "label" /* octet string */
+#define OSSL_KDF_PARAM_DATA "data" /* octet string */
+#define OSSL_KDF_PARAM_DIGEST OSSL_ALG_PARAM_DIGEST /* utf8 string */
+#define OSSL_KDF_PARAM_CIPHER OSSL_ALG_PARAM_CIPHER /* utf8 string */
+#define OSSL_KDF_PARAM_MAC OSSL_ALG_PARAM_MAC /* utf8 string */
+#define OSSL_KDF_PARAM_MAC_SIZE "maclen" /* size_t */
+#define OSSL_KDF_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES /* utf8 string */
+#define OSSL_KDF_PARAM_ITER "iter" /* unsigned int */
+#define OSSL_KDF_PARAM_MODE "mode" /* utf8 string or int */
+#define OSSL_KDF_PARAM_PKCS5 "pkcs5" /* int */
+#define OSSL_KDF_PARAM_UKM "ukm" /* octet string */
+#define OSSL_KDF_PARAM_CEK_ALG "cekalg" /* utf8 string */
+#define OSSL_KDF_PARAM_SCRYPT_N "n" /* uint64_t */
+#define OSSL_KDF_PARAM_SCRYPT_R "r" /* uint32_t */
+#define OSSL_KDF_PARAM_SCRYPT_P "p" /* uint32_t */
+#define OSSL_KDF_PARAM_SCRYPT_MAXMEM "maxmem_bytes" /* uint64_t */
+#define OSSL_KDF_PARAM_INFO "info" /* octet string */
+#define OSSL_KDF_PARAM_SEED "seed" /* octet string */
+#define OSSL_KDF_PARAM_SSHKDF_XCGHASH "xcghash" /* octet string */
+#define OSSL_KDF_PARAM_SSHKDF_SESSION_ID "session_id" /* octet string */
+#define OSSL_KDF_PARAM_SSHKDF_TYPE "type" /* int */
+#define OSSL_KDF_PARAM_SIZE "size" /* size_t */
+#define OSSL_KDF_PARAM_CONSTANT "constant" /* octet string */
+#define OSSL_KDF_PARAM_PKCS12_ID "id" /* int */
+#define OSSL_KDF_PARAM_KBKDF_USE_L "use-l" /* int */
+#define OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR "use-separator" /* int */
+#define OSSL_KDF_PARAM_X942_ACVPINFO "acvp-info"
+#define OSSL_KDF_PARAM_X942_PARTYUINFO "partyu-info"
+#define OSSL_KDF_PARAM_X942_PARTYVINFO "partyv-info"
+#define OSSL_KDF_PARAM_X942_SUPP_PUBINFO "supp-pubinfo"
+#define OSSL_KDF_PARAM_X942_SUPP_PRIVINFO "supp-privinfo"
+#define OSSL_KDF_PARAM_X942_USE_KEYBITS "use-keybits"
+
+/* Known KDF names */
+#define OSSL_KDF_NAME_HKDF "HKDF"
+#define OSSL_KDF_NAME_TLS1_3_KDF "TLS13-KDF"
+#define OSSL_KDF_NAME_PBKDF1 "PBKDF1"
+#define OSSL_KDF_NAME_PBKDF2 "PBKDF2"
+#define OSSL_KDF_NAME_SCRYPT "SCRYPT"
+#define OSSL_KDF_NAME_SSHKDF "SSHKDF"
+#define OSSL_KDF_NAME_SSKDF "SSKDF"
+#define OSSL_KDF_NAME_TLS1_PRF "TLS1-PRF"
+#define OSSL_KDF_NAME_X942KDF_ASN1 "X942KDF-ASN1"
+#define OSSL_KDF_NAME_X942KDF_CONCAT "X942KDF-CONCAT"
+#define OSSL_KDF_NAME_X963KDF "X963KDF"
+#define OSSL_KDF_NAME_KBKDF "KBKDF"
+#define OSSL_KDF_NAME_KRB5KDF "KRB5KDF"
+
+/* Known RAND names */
+#define OSSL_RAND_PARAM_STATE "state"
+#define OSSL_RAND_PARAM_STRENGTH "strength"
+#define OSSL_RAND_PARAM_MAX_REQUEST "max_request"
+#define OSSL_RAND_PARAM_TEST_ENTROPY "test_entropy"
+#define OSSL_RAND_PARAM_TEST_NONCE "test_nonce"
+
+/* RAND/DRBG names */
+#define OSSL_DRBG_PARAM_RESEED_REQUESTS "reseed_requests"
+#define OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL "reseed_time_interval"
+#define OSSL_DRBG_PARAM_MIN_ENTROPYLEN "min_entropylen"
+#define OSSL_DRBG_PARAM_MAX_ENTROPYLEN "max_entropylen"
+#define OSSL_DRBG_PARAM_MIN_NONCELEN "min_noncelen"
+#define OSSL_DRBG_PARAM_MAX_NONCELEN "max_noncelen"
+#define OSSL_DRBG_PARAM_MAX_PERSLEN "max_perslen"
+#define OSSL_DRBG_PARAM_MAX_ADINLEN "max_adinlen"
+#define OSSL_DRBG_PARAM_RESEED_COUNTER "reseed_counter"
+#define OSSL_DRBG_PARAM_RESEED_TIME "reseed_time"
+#define OSSL_DRBG_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES
+#define OSSL_DRBG_PARAM_DIGEST OSSL_ALG_PARAM_DIGEST
+#define OSSL_DRBG_PARAM_CIPHER OSSL_ALG_PARAM_CIPHER
+#define OSSL_DRBG_PARAM_MAC OSSL_ALG_PARAM_MAC
+#define OSSL_DRBG_PARAM_USE_DF "use_derivation_function"
+
+/* DRBG call back parameters */
+#define OSSL_DRBG_PARAM_ENTROPY_REQUIRED "entropy_required"
+#define OSSL_DRBG_PARAM_PREDICTION_RESISTANCE "prediction_resistance"
+#define OSSL_DRBG_PARAM_MIN_LENGTH "minium_length"
+#define OSSL_DRBG_PARAM_MAX_LENGTH "maxium_length"
+#define OSSL_DRBG_PARAM_RANDOM_DATA "random_data"
+#define OSSL_DRBG_PARAM_SIZE "size"
+
+/* PKEY parameters */
+/* Common PKEY parameters */
+#define OSSL_PKEY_PARAM_BITS "bits" /* integer */
+#define OSSL_PKEY_PARAM_MAX_SIZE "max-size" /* integer */
+#define OSSL_PKEY_PARAM_SECURITY_BITS "security-bits" /* integer */
+#define OSSL_PKEY_PARAM_DIGEST OSSL_ALG_PARAM_DIGEST
+#define OSSL_PKEY_PARAM_CIPHER OSSL_ALG_PARAM_CIPHER /* utf8 string */
+#define OSSL_PKEY_PARAM_ENGINE OSSL_ALG_PARAM_ENGINE /* utf8 string */
+#define OSSL_PKEY_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES
+#define OSSL_PKEY_PARAM_DEFAULT_DIGEST "default-digest" /* utf8 string */
+#define OSSL_PKEY_PARAM_MANDATORY_DIGEST "mandatory-digest" /* utf8 string */
+#define OSSL_PKEY_PARAM_PAD_MODE "pad-mode"
+#define OSSL_PKEY_PARAM_DIGEST_SIZE "digest-size"
+#define OSSL_PKEY_PARAM_MASKGENFUNC "mgf"
+#define OSSL_PKEY_PARAM_MGF1_DIGEST "mgf1-digest"
+#define OSSL_PKEY_PARAM_MGF1_PROPERTIES "mgf1-properties"
+#define OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY "encoded-pub-key"
+#define OSSL_PKEY_PARAM_GROUP_NAME "group"
+#define OSSL_PKEY_PARAM_DIST_ID "distid"
+#define OSSL_PKEY_PARAM_PUB_KEY "pub"
+#define OSSL_PKEY_PARAM_PRIV_KEY "priv"
+
+/* Diffie-Hellman/DSA Parameters */
+#define OSSL_PKEY_PARAM_FFC_P "p"
+#define OSSL_PKEY_PARAM_FFC_G "g"
+#define OSSL_PKEY_PARAM_FFC_Q "q"
+#define OSSL_PKEY_PARAM_FFC_GINDEX "gindex"
+#define OSSL_PKEY_PARAM_FFC_PCOUNTER "pcounter"
+#define OSSL_PKEY_PARAM_FFC_SEED "seed"
+#define OSSL_PKEY_PARAM_FFC_COFACTOR "j"
+#define OSSL_PKEY_PARAM_FFC_H "hindex"
+#define OSSL_PKEY_PARAM_FFC_VALIDATE_PQ "validate-pq"
+#define OSSL_PKEY_PARAM_FFC_VALIDATE_G "validate-g"
+#define OSSL_PKEY_PARAM_FFC_VALIDATE_LEGACY "validate-legacy"
+
+/* Diffie-Hellman params */
+#define OSSL_PKEY_PARAM_DH_GENERATOR "safeprime-generator"
+#define OSSL_PKEY_PARAM_DH_PRIV_LEN "priv_len"
+
+/* Elliptic Curve Domain Parameters */
+#define OSSL_PKEY_PARAM_EC_PUB_X "qx"
+#define OSSL_PKEY_PARAM_EC_PUB_Y "qy"
+
+/* Elliptic Curve Explicit Domain Parameters */
+#define OSSL_PKEY_PARAM_EC_FIELD_TYPE "field-type"
+#define OSSL_PKEY_PARAM_EC_P "p"
+#define OSSL_PKEY_PARAM_EC_A "a"
+#define OSSL_PKEY_PARAM_EC_B "b"
+#define OSSL_PKEY_PARAM_EC_GENERATOR "generator"
+#define OSSL_PKEY_PARAM_EC_ORDER "order"
+#define OSSL_PKEY_PARAM_EC_COFACTOR "cofactor"
+#define OSSL_PKEY_PARAM_EC_SEED "seed"
+#define OSSL_PKEY_PARAM_EC_CHAR2_M "m"
+#define OSSL_PKEY_PARAM_EC_CHAR2_TYPE "basis-type"
+#define OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS "tp"
+#define OSSL_PKEY_PARAM_EC_CHAR2_PP_K1 "k1"
+#define OSSL_PKEY_PARAM_EC_CHAR2_PP_K2 "k2"
+#define OSSL_PKEY_PARAM_EC_CHAR2_PP_K3 "k3"
+#define OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS "decoded-from-explicit"
+
+/* Elliptic Curve Key Parameters */
+#define OSSL_PKEY_PARAM_USE_COFACTOR_FLAG "use-cofactor-flag"
+#define OSSL_PKEY_PARAM_USE_COFACTOR_ECDH \
+ OSSL_PKEY_PARAM_USE_COFACTOR_FLAG
+
+/* RSA Keys */
+/*
+ * n, e, d are the usual public and private key components
+ *
+ * rsa-num is the number of factors, including p and q
+ * rsa-factor is used for each factor: p, q, r_i (i = 3, ...)
+ * rsa-exponent is used for each exponent: dP, dQ, d_i (i = 3, ...)
+ * rsa-coefficient is used for each coefficient: qInv, t_i (i = 3, ...)
+ *
+ * The number of rsa-factor items must be equal to the number of rsa-exponent
+ * items, and the number of rsa-coefficients must be one less.
+ * (the base i for the coefficients is 2, not 1, at least as implied by
+ * RFC 8017)
+ */
+#define OSSL_PKEY_PARAM_RSA_N "n"
+#define OSSL_PKEY_PARAM_RSA_E "e"
+#define OSSL_PKEY_PARAM_RSA_D "d"
+#define OSSL_PKEY_PARAM_RSA_FACTOR "rsa-factor"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT "rsa-exponent"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT "rsa-coefficient"
+#define OSSL_PKEY_PARAM_RSA_FACTOR1 OSSL_PKEY_PARAM_RSA_FACTOR"1"
+#define OSSL_PKEY_PARAM_RSA_FACTOR2 OSSL_PKEY_PARAM_RSA_FACTOR"2"
+#define OSSL_PKEY_PARAM_RSA_FACTOR3 OSSL_PKEY_PARAM_RSA_FACTOR"3"
+#define OSSL_PKEY_PARAM_RSA_FACTOR4 OSSL_PKEY_PARAM_RSA_FACTOR"4"
+#define OSSL_PKEY_PARAM_RSA_FACTOR5 OSSL_PKEY_PARAM_RSA_FACTOR"5"
+#define OSSL_PKEY_PARAM_RSA_FACTOR6 OSSL_PKEY_PARAM_RSA_FACTOR"6"
+#define OSSL_PKEY_PARAM_RSA_FACTOR7 OSSL_PKEY_PARAM_RSA_FACTOR"7"
+#define OSSL_PKEY_PARAM_RSA_FACTOR8 OSSL_PKEY_PARAM_RSA_FACTOR"8"
+#define OSSL_PKEY_PARAM_RSA_FACTOR9 OSSL_PKEY_PARAM_RSA_FACTOR"9"
+#define OSSL_PKEY_PARAM_RSA_FACTOR10 OSSL_PKEY_PARAM_RSA_FACTOR"10"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT1 OSSL_PKEY_PARAM_RSA_EXPONENT"1"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT2 OSSL_PKEY_PARAM_RSA_EXPONENT"2"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT3 OSSL_PKEY_PARAM_RSA_EXPONENT"3"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT4 OSSL_PKEY_PARAM_RSA_EXPONENT"4"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT5 OSSL_PKEY_PARAM_RSA_EXPONENT"5"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT6 OSSL_PKEY_PARAM_RSA_EXPONENT"6"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT7 OSSL_PKEY_PARAM_RSA_EXPONENT"7"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT8 OSSL_PKEY_PARAM_RSA_EXPONENT"8"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT9 OSSL_PKEY_PARAM_RSA_EXPONENT"9"
+#define OSSL_PKEY_PARAM_RSA_EXPONENT10 OSSL_PKEY_PARAM_RSA_EXPONENT"10"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT1 OSSL_PKEY_PARAM_RSA_COEFFICIENT"1"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT2 OSSL_PKEY_PARAM_RSA_COEFFICIENT"2"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT3 OSSL_PKEY_PARAM_RSA_COEFFICIENT"3"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT4 OSSL_PKEY_PARAM_RSA_COEFFICIENT"4"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT5 OSSL_PKEY_PARAM_RSA_COEFFICIENT"5"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT6 OSSL_PKEY_PARAM_RSA_COEFFICIENT"6"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT7 OSSL_PKEY_PARAM_RSA_COEFFICIENT"7"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT8 OSSL_PKEY_PARAM_RSA_COEFFICIENT"8"
+#define OSSL_PKEY_PARAM_RSA_COEFFICIENT9 OSSL_PKEY_PARAM_RSA_COEFFICIENT"9"
+
+/* RSA padding modes */
+#define OSSL_PKEY_RSA_PAD_MODE_NONE "none"
+#define OSSL_PKEY_RSA_PAD_MODE_PKCSV15 "pkcs1"
+#define OSSL_PKEY_RSA_PAD_MODE_OAEP "oaep"
+#define OSSL_PKEY_RSA_PAD_MODE_X931 "x931"
+#define OSSL_PKEY_RSA_PAD_MODE_PSS "pss"
+
+/* RSA pss padding salt length */
+#define OSSL_PKEY_RSA_PSS_SALT_LEN_DIGEST "digest"
+#define OSSL_PKEY_RSA_PSS_SALT_LEN_MAX "max"
+#define OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO "auto"
+
+/* Key generation parameters */
+#define OSSL_PKEY_PARAM_RSA_BITS OSSL_PKEY_PARAM_BITS
+#define OSSL_PKEY_PARAM_RSA_PRIMES "primes"
+#define OSSL_PKEY_PARAM_RSA_DIGEST OSSL_PKEY_PARAM_DIGEST
+#define OSSL_PKEY_PARAM_RSA_DIGEST_PROPS OSSL_PKEY_PARAM_PROPERTIES
+#define OSSL_PKEY_PARAM_RSA_MASKGENFUNC OSSL_PKEY_PARAM_MASKGENFUNC
+#define OSSL_PKEY_PARAM_RSA_MGF1_DIGEST OSSL_PKEY_PARAM_MGF1_DIGEST
+#define OSSL_PKEY_PARAM_RSA_PSS_SALTLEN "saltlen"
+
+/* Key generation parameters */
+#define OSSL_PKEY_PARAM_FFC_TYPE "type"
+#define OSSL_PKEY_PARAM_FFC_PBITS "pbits"
+#define OSSL_PKEY_PARAM_FFC_QBITS "qbits"
+#define OSSL_PKEY_PARAM_FFC_DIGEST OSSL_PKEY_PARAM_DIGEST
+#define OSSL_PKEY_PARAM_FFC_DIGEST_PROPS OSSL_PKEY_PARAM_PROPERTIES
+
+#define OSSL_PKEY_PARAM_EC_ENCODING "encoding" /* utf8_string */
+#define OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT "point-format"
+#define OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE "group-check"
+#define OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC "include-public"
+
+/* OSSL_PKEY_PARAM_EC_ENCODING values */
+#define OSSL_PKEY_EC_ENCODING_EXPLICIT "explicit"
+#define OSSL_PKEY_EC_ENCODING_GROUP "named_curve"
+
+#define OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_UNCOMPRESSED "uncompressed"
+#define OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED "compressed"
+#define OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_HYBRID "hybrid"
+
+#define OSSL_PKEY_EC_GROUP_CHECK_DEFAULT "default"
+#define OSSL_PKEY_EC_GROUP_CHECK_NAMED "named"
+#define OSSL_PKEY_EC_GROUP_CHECK_NAMED_NIST "named-nist"
+
+/* Key Exchange parameters */
+#define OSSL_EXCHANGE_PARAM_PAD "pad" /* uint */
+#define OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE "ecdh-cofactor-mode" /* int */
+#define OSSL_EXCHANGE_PARAM_KDF_TYPE "kdf-type" /* utf8_string */
+#define OSSL_EXCHANGE_PARAM_KDF_DIGEST "kdf-digest" /* utf8_string */
+#define OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS "kdf-digest-props" /* utf8_string */
+#define OSSL_EXCHANGE_PARAM_KDF_OUTLEN "kdf-outlen" /* size_t */
+/* The following parameter is an octet_string on set and an octet_ptr on get */
+#define OSSL_EXCHANGE_PARAM_KDF_UKM "kdf-ukm"
+
+/* Signature parameters */
+#define OSSL_SIGNATURE_PARAM_ALGORITHM_ID "algorithm-id"
+#define OSSL_SIGNATURE_PARAM_PAD_MODE OSSL_PKEY_PARAM_PAD_MODE
+#define OSSL_SIGNATURE_PARAM_DIGEST OSSL_PKEY_PARAM_DIGEST
+#define OSSL_SIGNATURE_PARAM_PROPERTIES OSSL_PKEY_PARAM_PROPERTIES
+#define OSSL_SIGNATURE_PARAM_PSS_SALTLEN "saltlen"
+#define OSSL_SIGNATURE_PARAM_MGF1_DIGEST OSSL_PKEY_PARAM_MGF1_DIGEST
+#define OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES \
+ OSSL_PKEY_PARAM_MGF1_PROPERTIES
+#define OSSL_SIGNATURE_PARAM_DIGEST_SIZE OSSL_PKEY_PARAM_DIGEST_SIZE
+
+/* Asym cipher parameters */
+#define OSSL_ASYM_CIPHER_PARAM_DIGEST OSSL_PKEY_PARAM_DIGEST
+#define OSSL_ASYM_CIPHER_PARAM_PROPERTIES OSSL_PKEY_PARAM_PROPERTIES
+#define OSSL_ASYM_CIPHER_PARAM_ENGINE OSSL_PKEY_PARAM_ENGINE
+#define OSSL_ASYM_CIPHER_PARAM_PAD_MODE OSSL_PKEY_PARAM_PAD_MODE
+#define OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST \
+ OSSL_PKEY_PARAM_MGF1_DIGEST
+#define OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS \
+ OSSL_PKEY_PARAM_MGF1_PROPERTIES
+#define OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST OSSL_ALG_PARAM_DIGEST
+#define OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS "digest-props"
+/* The following parameter is an octet_string on set and an octet_ptr on get */
+#define OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL "oaep-label"
+#define OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION "tls-client-version"
+#define OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION "tls-negotiated-version"
+
+/*
+ * Encoder / decoder parameters
+ */
+#define OSSL_ENCODER_PARAM_CIPHER OSSL_ALG_PARAM_CIPHER
+#define OSSL_ENCODER_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES
+/* Currently PVK only, but reusable for others as needed */
+#define OSSL_ENCODER_PARAM_ENCRYPT_LEVEL "encrypt-level"
+#define OSSL_ENCODER_PARAM_SAVE_PARAMETERS "save-parameters" /* integer */
+
+#define OSSL_DECODER_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES
+
+/* Passphrase callback parameters */
+#define OSSL_PASSPHRASE_PARAM_INFO "info"
+
+/* Keygen callback parameters, from provider to libcrypto */
+#define OSSL_GEN_PARAM_POTENTIAL "potential" /* integer */
+#define OSSL_GEN_PARAM_ITERATION "iteration" /* integer */
+
+/* ACVP Test parameters : These should not be used normally */
+#define OSSL_PKEY_PARAM_RSA_TEST_XP1 "xp1"
+#define OSSL_PKEY_PARAM_RSA_TEST_XP2 "xp2"
+#define OSSL_PKEY_PARAM_RSA_TEST_XP "xp"
+#define OSSL_PKEY_PARAM_RSA_TEST_XQ1 "xq1"
+#define OSSL_PKEY_PARAM_RSA_TEST_XQ2 "xq2"
+#define OSSL_PKEY_PARAM_RSA_TEST_XQ "xq"
+#define OSSL_PKEY_PARAM_RSA_TEST_P1 "p1"
+#define OSSL_PKEY_PARAM_RSA_TEST_P2 "p2"
+#define OSSL_PKEY_PARAM_RSA_TEST_Q1 "q1"
+#define OSSL_PKEY_PARAM_RSA_TEST_Q2 "q2"
+#define OSSL_SIGNATURE_PARAM_KAT "kat"
+
+/* KEM parameters */
+#define OSSL_KEM_PARAM_OPERATION "operation"
+
+/* OSSL_KEM_PARAM_OPERATION values */
+#define OSSL_KEM_PARAM_OPERATION_RSASVE "RSASVE"
+
+/* Capabilities */
+
+/* TLS-GROUP Capability */
+#define OSSL_CAPABILITY_TLS_GROUP_NAME "tls-group-name"
+#define OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL "tls-group-name-internal"
+#define OSSL_CAPABILITY_TLS_GROUP_ID "tls-group-id"
+#define OSSL_CAPABILITY_TLS_GROUP_ALG "tls-group-alg"
+#define OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS "tls-group-sec-bits"
+#define OSSL_CAPABILITY_TLS_GROUP_IS_KEM "tls-group-is-kem"
+#define OSSL_CAPABILITY_TLS_GROUP_MIN_TLS "tls-min-tls"
+#define OSSL_CAPABILITY_TLS_GROUP_MAX_TLS "tls-max-tls"
+#define OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS "tls-min-dtls"
+#define OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS "tls-max-dtls"
+
+/*-
+ * storemgmt parameters
+ */
+
+/*
+ * Used by storemgmt_ctx_set_params():
+ *
+ * - OSSL_STORE_PARAM_EXPECT is an INTEGER, and the value is any of the
+ * OSSL_STORE_INFO numbers. This is used to set the expected type of
+ * object loaded.
+ *
+ * - OSSL_STORE_PARAM_SUBJECT, OSSL_STORE_PARAM_ISSUER,
+ * OSSL_STORE_PARAM_SERIAL, OSSL_STORE_PARAM_FINGERPRINT,
+ * OSSL_STORE_PARAM_DIGEST, OSSL_STORE_PARAM_ALIAS
+ * are used as search criteria.
+ * (OSSL_STORE_PARAM_DIGEST is used with OSSL_STORE_PARAM_FINGERPRINT)
+ */
+#define OSSL_STORE_PARAM_EXPECT "expect" /* INTEGER */
+#define OSSL_STORE_PARAM_SUBJECT "subject" /* DER blob => OCTET_STRING */
+#define OSSL_STORE_PARAM_ISSUER "name" /* DER blob => OCTET_STRING */
+#define OSSL_STORE_PARAM_SERIAL "serial" /* INTEGER */
+#define OSSL_STORE_PARAM_DIGEST "digest" /* UTF8_STRING */
+#define OSSL_STORE_PARAM_FINGERPRINT "fingerprint" /* OCTET_STRING */
+#define OSSL_STORE_PARAM_ALIAS "alias" /* UTF8_STRING */
+
+/* You may want to pass properties for the provider implementation to use */
+#define OSSL_STORE_PARAM_PROPERTIES "properties" /* utf8_string */
+/* OSSL_DECODER input type if a decoder is used by the store */
+#define OSSL_STORE_PARAM_INPUT_TYPE "input-type" /* UTF8_STRING */
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/include/openssl/core_object.h b/include/openssl/core_object.h
new file mode 100644
index 000000000000..62ccf39d3259
--- /dev/null
+++ b/include/openssl/core_object.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_CORE_OBJECT_H
+# define OPENSSL_CORE_OBJECT_H
+# pragma once
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/*-
+ * Known object types
+ *
+ * These numbers are used as values for the OSSL_PARAM parameter
+ * OSSL_OBJECT_PARAM_TYPE.
+ *
+ * For most of these types, there's a corresponding libcrypto object type.
+ * The corresponding type is indicated with a comment after the number.
+ */
+# define OSSL_OBJECT_UNKNOWN 0
+# define OSSL_OBJECT_NAME 1 /* char * */
+# define OSSL_OBJECT_PKEY 2 /* EVP_PKEY * */
+# define OSSL_OBJECT_CERT 3 /* X509 * */
+# define OSSL_OBJECT_CRL 4 /* X509_CRL * */
+
+/*
+ * The rest of the associated OSSL_PARAM elements is described in core_names.h
+ */
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/include/openssl/crmf.h.in b/include/openssl/crmf.h.in
new file mode 100644
index 000000000000..4d37ea6d9437
--- /dev/null
+++ b/include/openssl/crmf.h.in
@@ -0,0 +1,180 @@
+/*-
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * CRMF (RFC 4211) implementation by M. Peylo, M. Viljanen, and D. von Oheimb.
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_CRMF_H
+# define OPENSSL_CRMF_H
+
+# include <openssl/opensslconf.h>
+
+# ifndef OPENSSL_NO_CRMF
+# include <openssl/opensslv.h>
+# include <openssl/safestack.h>
+# include <openssl/crmferr.h>
+# include <openssl/x509v3.h> /* for GENERAL_NAME etc. */
+
+/* explicit #includes not strictly needed since implied by the above: */
+# include <openssl/types.h>
+# include <openssl/x509.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# define OSSL_CRMF_POPOPRIVKEY_THISMESSAGE 0
+# define OSSL_CRMF_POPOPRIVKEY_SUBSEQUENTMESSAGE 1
+# define OSSL_CRMF_POPOPRIVKEY_DHMAC 2
+# define OSSL_CRMF_POPOPRIVKEY_AGREEMAC 3
+# define OSSL_CRMF_POPOPRIVKEY_ENCRYPTEDKEY 4
+
+# define OSSL_CRMF_SUBSEQUENTMESSAGE_ENCRCERT 0
+# define OSSL_CRMF_SUBSEQUENTMESSAGE_CHALLENGERESP 1
+
+typedef struct ossl_crmf_encryptedvalue_st OSSL_CRMF_ENCRYPTEDVALUE;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_ENCRYPTEDVALUE)
+typedef struct ossl_crmf_msg_st OSSL_CRMF_MSG;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_MSG)
+DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_MSG)
+{-
+ generate_stack_macros("OSSL_CRMF_MSG");
+-}
+typedef struct ossl_crmf_attributetypeandvalue_st OSSL_CRMF_ATTRIBUTETYPEANDVALUE;
+typedef struct ossl_crmf_pbmparameter_st OSSL_CRMF_PBMPARAMETER;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_PBMPARAMETER)
+typedef struct ossl_crmf_poposigningkey_st OSSL_CRMF_POPOSIGNINGKEY;
+typedef struct ossl_crmf_certrequest_st OSSL_CRMF_CERTREQUEST;
+typedef struct ossl_crmf_certid_st OSSL_CRMF_CERTID;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_CERTID)
+DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTID)
+{-
+ generate_stack_macros("OSSL_CRMF_CERTID");
+-}
+
+typedef struct ossl_crmf_pkipublicationinfo_st OSSL_CRMF_PKIPUBLICATIONINFO;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_PKIPUBLICATIONINFO)
+typedef struct ossl_crmf_singlepubinfo_st OSSL_CRMF_SINGLEPUBINFO;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_SINGLEPUBINFO)
+typedef struct ossl_crmf_certtemplate_st OSSL_CRMF_CERTTEMPLATE;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_CERTTEMPLATE)
+typedef STACK_OF(OSSL_CRMF_MSG) OSSL_CRMF_MSGS;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_MSGS)
+
+typedef struct ossl_crmf_optionalvalidity_st OSSL_CRMF_OPTIONALVALIDITY;
+
+/* crmf_pbm.c */
+OSSL_CRMF_PBMPARAMETER *OSSL_CRMF_pbmp_new(OSSL_LIB_CTX *libctx, size_t slen,
+ int owfnid, size_t itercnt,
+ int macnid);
+int OSSL_CRMF_pbm_new(OSSL_LIB_CTX *libctx, const char *propq,
+ const OSSL_CRMF_PBMPARAMETER *pbmp,
+ const unsigned char *msg, size_t msglen,
+ const unsigned char *sec, size_t seclen,
+ unsigned char **mac, size_t *maclen);
+
+/* crmf_lib.c */
+int OSSL_CRMF_MSG_set1_regCtrl_regToken(OSSL_CRMF_MSG *msg,
+ const ASN1_UTF8STRING *tok);
+ASN1_UTF8STRING
+*OSSL_CRMF_MSG_get0_regCtrl_regToken(const OSSL_CRMF_MSG *msg);
+int OSSL_CRMF_MSG_set1_regCtrl_authenticator(OSSL_CRMF_MSG *msg,
+ const ASN1_UTF8STRING *auth);
+ASN1_UTF8STRING
+*OSSL_CRMF_MSG_get0_regCtrl_authenticator(const OSSL_CRMF_MSG *msg);
+int
+OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo(OSSL_CRMF_PKIPUBLICATIONINFO *pi,
+ OSSL_CRMF_SINGLEPUBINFO *spi);
+# define OSSL_CRMF_PUB_METHOD_DONTCARE 0
+# define OSSL_CRMF_PUB_METHOD_X500 1
+# define OSSL_CRMF_PUB_METHOD_WEB 2
+# define OSSL_CRMF_PUB_METHOD_LDAP 3
+int OSSL_CRMF_MSG_set0_SinglePubInfo(OSSL_CRMF_SINGLEPUBINFO *spi,
+ int method, GENERAL_NAME *nm);
+# define OSSL_CRMF_PUB_ACTION_DONTPUBLISH 0
+# define OSSL_CRMF_PUB_ACTION_PLEASEPUBLISH 1
+int OSSL_CRMF_MSG_set_PKIPublicationInfo_action(OSSL_CRMF_PKIPUBLICATIONINFO *pi,
+ int action);
+int OSSL_CRMF_MSG_set1_regCtrl_pkiPublicationInfo(OSSL_CRMF_MSG *msg,
+ const OSSL_CRMF_PKIPUBLICATIONINFO *pi);
+OSSL_CRMF_PKIPUBLICATIONINFO
+*OSSL_CRMF_MSG_get0_regCtrl_pkiPublicationInfo(const OSSL_CRMF_MSG *msg);
+int OSSL_CRMF_MSG_set1_regCtrl_protocolEncrKey(OSSL_CRMF_MSG *msg,
+ const X509_PUBKEY *pubkey);
+X509_PUBKEY
+*OSSL_CRMF_MSG_get0_regCtrl_protocolEncrKey(const OSSL_CRMF_MSG *msg);
+int OSSL_CRMF_MSG_set1_regCtrl_oldCertID(OSSL_CRMF_MSG *msg,
+ const OSSL_CRMF_CERTID *cid);
+OSSL_CRMF_CERTID
+*OSSL_CRMF_MSG_get0_regCtrl_oldCertID(const OSSL_CRMF_MSG *msg);
+OSSL_CRMF_CERTID *OSSL_CRMF_CERTID_gen(const X509_NAME *issuer,
+ const ASN1_INTEGER *serial);
+
+int OSSL_CRMF_MSG_set1_regInfo_utf8Pairs(OSSL_CRMF_MSG *msg,
+ const ASN1_UTF8STRING *utf8pairs);
+ASN1_UTF8STRING
+*OSSL_CRMF_MSG_get0_regInfo_utf8Pairs(const OSSL_CRMF_MSG *msg);
+int OSSL_CRMF_MSG_set1_regInfo_certReq(OSSL_CRMF_MSG *msg,
+ const OSSL_CRMF_CERTREQUEST *cr);
+OSSL_CRMF_CERTREQUEST
+*OSSL_CRMF_MSG_get0_regInfo_certReq(const OSSL_CRMF_MSG *msg);
+
+int OSSL_CRMF_MSG_set0_validity(OSSL_CRMF_MSG *crm,
+ ASN1_TIME *notBefore, ASN1_TIME *notAfter);
+int OSSL_CRMF_MSG_set_certReqId(OSSL_CRMF_MSG *crm, int rid);
+int OSSL_CRMF_MSG_get_certReqId(const OSSL_CRMF_MSG *crm);
+int OSSL_CRMF_MSG_set0_extensions(OSSL_CRMF_MSG *crm, X509_EXTENSIONS *exts);
+
+int OSSL_CRMF_MSG_push0_extension(OSSL_CRMF_MSG *crm, X509_EXTENSION *ext);
+# define OSSL_CRMF_POPO_NONE -1
+# define OSSL_CRMF_POPO_RAVERIFIED 0
+# define OSSL_CRMF_POPO_SIGNATURE 1
+# define OSSL_CRMF_POPO_KEYENC 2
+# define OSSL_CRMF_POPO_KEYAGREE 3
+int OSSL_CRMF_MSG_create_popo(int meth, OSSL_CRMF_MSG *crm,
+ EVP_PKEY *pkey, const EVP_MD *digest,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs,
+ int rid, int acceptRAVerified,
+ OSSL_LIB_CTX *libctx, const char *propq);
+OSSL_CRMF_CERTTEMPLATE *OSSL_CRMF_MSG_get0_tmpl(const OSSL_CRMF_MSG *crm);
+const ASN1_INTEGER
+*OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(const OSSL_CRMF_CERTTEMPLATE *tmpl);
+const X509_NAME
+*OSSL_CRMF_CERTTEMPLATE_get0_subject(const OSSL_CRMF_CERTTEMPLATE *tmpl);
+const X509_NAME
+*OSSL_CRMF_CERTTEMPLATE_get0_issuer(const OSSL_CRMF_CERTTEMPLATE *tmpl);
+X509_EXTENSIONS
+*OSSL_CRMF_CERTTEMPLATE_get0_extensions(const OSSL_CRMF_CERTTEMPLATE *tmpl);
+const X509_NAME
+*OSSL_CRMF_CERTID_get0_issuer(const OSSL_CRMF_CERTID *cid);
+const ASN1_INTEGER
+*OSSL_CRMF_CERTID_get0_serialNumber(const OSSL_CRMF_CERTID *cid);
+int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl,
+ EVP_PKEY *pubkey,
+ const X509_NAME *subject,
+ const X509_NAME *issuer,
+ const ASN1_INTEGER *serial);
+X509
+*OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(const OSSL_CRMF_ENCRYPTEDVALUE *ecert,
+ OSSL_LIB_CTX *libctx, const char *propq,
+ EVP_PKEY *pkey);
+
+# ifdef __cplusplus
+}
+# endif
+# endif /* !defined(OPENSSL_NO_CRMF) */
+#endif /* !defined(OPENSSL_CRMF_H) */
diff --git a/include/openssl/crmferr.h b/include/openssl/crmferr.h
new file mode 100644
index 000000000000..b242b922ef1a
--- /dev/null
+++ b/include/openssl/crmferr.h
@@ -0,0 +1,50 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_CRMFERR_H
+# define OPENSSL_CRMFERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
+
+
+# ifndef OPENSSL_NO_CRMF
+
+
+/*
+ * CRMF reason codes.
+ */
+# define CRMF_R_BAD_PBM_ITERATIONCOUNT 100
+# define CRMF_R_CRMFERROR 102
+# define CRMF_R_ERROR 103
+# define CRMF_R_ERROR_DECODING_CERTIFICATE 104
+# define CRMF_R_ERROR_DECRYPTING_CERTIFICATE 105
+# define CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY 106
+# define CRMF_R_FAILURE_OBTAINING_RANDOM 107
+# define CRMF_R_ITERATIONCOUNT_BELOW_100 108
+# define CRMF_R_MALFORMED_IV 101
+# define CRMF_R_NULL_ARGUMENT 109
+# define CRMF_R_POPOSKINPUT_NOT_SUPPORTED 113
+# define CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY 117
+# define CRMF_R_POPO_MISSING 121
+# define CRMF_R_POPO_MISSING_PUBLIC_KEY 118
+# define CRMF_R_POPO_MISSING_SUBJECT 119
+# define CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED 120
+# define CRMF_R_SETTING_MAC_ALGOR_FAILURE 110
+# define CRMF_R_SETTING_OWF_ALGOR_FAILURE 111
+# define CRMF_R_UNSUPPORTED_ALGORITHM 112
+# define CRMF_R_UNSUPPORTED_CIPHER 114
+# define CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO 115
+# define CRMF_R_UNSUPPORTED_POPO_METHOD 116
+
+# endif
+#endif
diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h
deleted file mode 100644
index 7d0b526236f8..000000000000
--- a/include/openssl/crypto.h
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_CRYPTO_H
-# define HEADER_CRYPTO_H
-
-# include <stdlib.h>
-# include <time.h>
-
-# include <openssl/e_os2.h>
-
-# ifndef OPENSSL_NO_STDIO
-# include <stdio.h>
-# endif
-
-# include <openssl/safestack.h>
-# include <openssl/opensslv.h>
-# include <openssl/ossl_typ.h>
-# include <openssl/opensslconf.h>
-# include <openssl/cryptoerr.h>
-
-# ifdef CHARSET_EBCDIC
-# include <openssl/ebcdic.h>
-# endif
-
-/*
- * Resolve problems on some operating systems with symbol names that clash
- * one way or another
- */
-# include <openssl/symhacks.h>
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-# include <openssl/opensslv.h>
-# endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-# define SSLeay OpenSSL_version_num
-# define SSLeay_version OpenSSL_version
-# define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER
-# define SSLEAY_VERSION OPENSSL_VERSION
-# define SSLEAY_CFLAGS OPENSSL_CFLAGS
-# define SSLEAY_BUILT_ON OPENSSL_BUILT_ON
-# define SSLEAY_PLATFORM OPENSSL_PLATFORM
-# define SSLEAY_DIR OPENSSL_DIR
-
-/*
- * Old type for allocating dynamic locks. No longer used. Use the new thread
- * API instead.
- */
-typedef struct {
- int dummy;
-} CRYPTO_dynlock;
-
-# endif /* OPENSSL_API_COMPAT */
-
-typedef void CRYPTO_RWLOCK;
-
-CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void);
-int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock);
-int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock);
-int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock);
-void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock);
-
-int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock);
-
-/*
- * The following can be used to detect memory leaks in the library. If
- * used, it turns on malloc checking
- */
-# define CRYPTO_MEM_CHECK_OFF 0x0 /* Control only */
-# define CRYPTO_MEM_CHECK_ON 0x1 /* Control and mode bit */
-# define CRYPTO_MEM_CHECK_ENABLE 0x2 /* Control and mode bit */
-# define CRYPTO_MEM_CHECK_DISABLE 0x3 /* Control only */
-
-struct crypto_ex_data_st {
- STACK_OF(void) *sk;
-};
-DEFINE_STACK_OF(void)
-
-/*
- * Per class, we have a STACK of function pointers.
- */
-# define CRYPTO_EX_INDEX_SSL 0
-# define CRYPTO_EX_INDEX_SSL_CTX 1
-# define CRYPTO_EX_INDEX_SSL_SESSION 2
-# define CRYPTO_EX_INDEX_X509 3
-# define CRYPTO_EX_INDEX_X509_STORE 4
-# define CRYPTO_EX_INDEX_X509_STORE_CTX 5
-# define CRYPTO_EX_INDEX_DH 6
-# define CRYPTO_EX_INDEX_DSA 7
-# define CRYPTO_EX_INDEX_EC_KEY 8
-# define CRYPTO_EX_INDEX_RSA 9
-# define CRYPTO_EX_INDEX_ENGINE 10
-# define CRYPTO_EX_INDEX_UI 11
-# define CRYPTO_EX_INDEX_BIO 12
-# define CRYPTO_EX_INDEX_APP 13
-# define CRYPTO_EX_INDEX_UI_METHOD 14
-# define CRYPTO_EX_INDEX_DRBG 15
-# define CRYPTO_EX_INDEX__COUNT 16
-
-/* No longer needed, so this is a no-op */
-#define OPENSSL_malloc_init() while(0) continue
-
-int CRYPTO_mem_ctrl(int mode);
-
-# define OPENSSL_malloc(num) \
- CRYPTO_malloc(num, OPENSSL_FILE, OPENSSL_LINE)
-# define OPENSSL_zalloc(num) \
- CRYPTO_zalloc(num, OPENSSL_FILE, OPENSSL_LINE)
-# define OPENSSL_realloc(addr, num) \
- CRYPTO_realloc(addr, num, OPENSSL_FILE, OPENSSL_LINE)
-# define OPENSSL_clear_realloc(addr, old_num, num) \
- CRYPTO_clear_realloc(addr, old_num, num, OPENSSL_FILE, OPENSSL_LINE)
-# define OPENSSL_clear_free(addr, num) \
- CRYPTO_clear_free(addr, num, OPENSSL_FILE, OPENSSL_LINE)
-# define OPENSSL_free(addr) \
- CRYPTO_free(addr, OPENSSL_FILE, OPENSSL_LINE)
-# define OPENSSL_memdup(str, s) \
- CRYPTO_memdup((str), s, OPENSSL_FILE, OPENSSL_LINE)
-# define OPENSSL_strdup(str) \
- CRYPTO_strdup(str, OPENSSL_FILE, OPENSSL_LINE)
-# define OPENSSL_strndup(str, n) \
- CRYPTO_strndup(str, n, OPENSSL_FILE, OPENSSL_LINE)
-# define OPENSSL_secure_malloc(num) \
- CRYPTO_secure_malloc(num, OPENSSL_FILE, OPENSSL_LINE)
-# define OPENSSL_secure_zalloc(num) \
- CRYPTO_secure_zalloc(num, OPENSSL_FILE, OPENSSL_LINE)
-# define OPENSSL_secure_free(addr) \
- CRYPTO_secure_free(addr, OPENSSL_FILE, OPENSSL_LINE)
-# define OPENSSL_secure_clear_free(addr, num) \
- CRYPTO_secure_clear_free(addr, num, OPENSSL_FILE, OPENSSL_LINE)
-# define OPENSSL_secure_actual_size(ptr) \
- CRYPTO_secure_actual_size(ptr)
-
-size_t OPENSSL_strlcpy(char *dst, const char *src, size_t siz);
-size_t OPENSSL_strlcat(char *dst, const char *src, size_t siz);
-size_t OPENSSL_strnlen(const char *str, size_t maxlen);
-char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len);
-unsigned char *OPENSSL_hexstr2buf(const char *str, long *len);
-int OPENSSL_hexchar2int(unsigned char c);
-
-# define OPENSSL_MALLOC_MAX_NELEMS(type) (((1U<<(sizeof(int)*8-1))-1)/sizeof(type))
-
-unsigned long OpenSSL_version_num(void);
-const char *OpenSSL_version(int type);
-# define OPENSSL_VERSION 0
-# define OPENSSL_CFLAGS 1
-# define OPENSSL_BUILT_ON 2
-# define OPENSSL_PLATFORM 3
-# define OPENSSL_DIR 4
-# define OPENSSL_ENGINES_DIR 5
-
-int OPENSSL_issetugid(void);
-
-typedef void CRYPTO_EX_new (void *parent, void *ptr, CRYPTO_EX_DATA *ad,
- int idx, long argl, void *argp);
-typedef void CRYPTO_EX_free (void *parent, void *ptr, CRYPTO_EX_DATA *ad,
- int idx, long argl, void *argp);
-typedef int CRYPTO_EX_dup (CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from,
- void *from_d, int idx, long argl, void *argp);
-__owur int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
- CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
- CRYPTO_EX_free *free_func);
-/* No longer use an index. */
-int CRYPTO_free_ex_index(int class_index, int idx);
-
-/*
- * Initialise/duplicate/free CRYPTO_EX_DATA variables corresponding to a
- * given class (invokes whatever per-class callbacks are applicable)
- */
-int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad);
-int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
- const CRYPTO_EX_DATA *from);
-
-void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad);
-
-/*
- * Get/set data in a CRYPTO_EX_DATA variable corresponding to a particular
- * index (relative to the class type involved)
- */
-int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val);
-void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx);
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-/*
- * This function cleans up all "ex_data" state. It mustn't be called under
- * potential race-conditions.
- */
-# define CRYPTO_cleanup_all_ex_data() while(0) continue
-
-/*
- * The old locking functions have been removed completely without compatibility
- * macros. This is because the old functions either could not properly report
- * errors, or the returned error values were not clearly documented.
- * Replacing the locking functions with no-ops would cause race condition
- * issues in the affected applications. It is far better for them to fail at
- * compile time.
- * On the other hand, the locking callbacks are no longer used. Consequently,
- * the callback management functions can be safely replaced with no-op macros.
- */
-# define CRYPTO_num_locks() (1)
-# define CRYPTO_set_locking_callback(func)
-# define CRYPTO_get_locking_callback() (NULL)
-# define CRYPTO_set_add_lock_callback(func)
-# define CRYPTO_get_add_lock_callback() (NULL)
-
-/*
- * These defines where used in combination with the old locking callbacks,
- * they are not called anymore, but old code that's not called might still
- * use them.
- */
-# define CRYPTO_LOCK 1
-# define CRYPTO_UNLOCK 2
-# define CRYPTO_READ 4
-# define CRYPTO_WRITE 8
-
-/* This structure is no longer used */
-typedef struct crypto_threadid_st {
- int dummy;
-} CRYPTO_THREADID;
-/* Only use CRYPTO_THREADID_set_[numeric|pointer]() within callbacks */
-# define CRYPTO_THREADID_set_numeric(id, val)
-# define CRYPTO_THREADID_set_pointer(id, ptr)
-# define CRYPTO_THREADID_set_callback(threadid_func) (0)
-# define CRYPTO_THREADID_get_callback() (NULL)
-# define CRYPTO_THREADID_current(id)
-# define CRYPTO_THREADID_cmp(a, b) (-1)
-# define CRYPTO_THREADID_cpy(dest, src)
-# define CRYPTO_THREADID_hash(id) (0UL)
-
-# if OPENSSL_API_COMPAT < 0x10000000L
-# define CRYPTO_set_id_callback(func)
-# define CRYPTO_get_id_callback() (NULL)
-# define CRYPTO_thread_id() (0UL)
-# endif /* OPENSSL_API_COMPAT < 0x10000000L */
-
-# define CRYPTO_set_dynlock_create_callback(dyn_create_function)
-# define CRYPTO_set_dynlock_lock_callback(dyn_lock_function)
-# define CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function)
-# define CRYPTO_get_dynlock_create_callback() (NULL)
-# define CRYPTO_get_dynlock_lock_callback() (NULL)
-# define CRYPTO_get_dynlock_destroy_callback() (NULL)
-# endif /* OPENSSL_API_COMPAT < 0x10100000L */
-
-int CRYPTO_set_mem_functions(
- void *(*m) (size_t, const char *, int),
- void *(*r) (void *, size_t, const char *, int),
- void (*f) (void *, const char *, int));
-int CRYPTO_set_mem_debug(int flag);
-void CRYPTO_get_mem_functions(
- void *(**m) (size_t, const char *, int),
- void *(**r) (void *, size_t, const char *, int),
- void (**f) (void *, const char *, int));
-
-void *CRYPTO_malloc(size_t num, const char *file, int line);
-void *CRYPTO_zalloc(size_t num, const char *file, int line);
-void *CRYPTO_memdup(const void *str, size_t siz, const char *file, int line);
-char *CRYPTO_strdup(const char *str, const char *file, int line);
-char *CRYPTO_strndup(const char *str, size_t s, const char *file, int line);
-void CRYPTO_free(void *ptr, const char *file, int line);
-void CRYPTO_clear_free(void *ptr, size_t num, const char *file, int line);
-void *CRYPTO_realloc(void *addr, size_t num, const char *file, int line);
-void *CRYPTO_clear_realloc(void *addr, size_t old_num, size_t num,
- const char *file, int line);
-
-int CRYPTO_secure_malloc_init(size_t sz, int minsize);
-int CRYPTO_secure_malloc_done(void);
-void *CRYPTO_secure_malloc(size_t num, const char *file, int line);
-void *CRYPTO_secure_zalloc(size_t num, const char *file, int line);
-void CRYPTO_secure_free(void *ptr, const char *file, int line);
-void CRYPTO_secure_clear_free(void *ptr, size_t num,
- const char *file, int line);
-int CRYPTO_secure_allocated(const void *ptr);
-int CRYPTO_secure_malloc_initialized(void);
-size_t CRYPTO_secure_actual_size(void *ptr);
-size_t CRYPTO_secure_used(void);
-
-void OPENSSL_cleanse(void *ptr, size_t len);
-
-# ifndef OPENSSL_NO_CRYPTO_MDEBUG
-# define OPENSSL_mem_debug_push(info) \
- CRYPTO_mem_debug_push(info, OPENSSL_FILE, OPENSSL_LINE)
-# define OPENSSL_mem_debug_pop() \
- CRYPTO_mem_debug_pop()
-int CRYPTO_mem_debug_push(const char *info, const char *file, int line);
-int CRYPTO_mem_debug_pop(void);
-void CRYPTO_get_alloc_counts(int *mcount, int *rcount, int *fcount);
-
-/*-
- * Debugging functions (enabled by CRYPTO_set_mem_debug(1))
- * The flag argument has the following significance:
- * 0: called before the actual memory allocation has taken place
- * 1: called after the actual memory allocation has taken place
- */
-void CRYPTO_mem_debug_malloc(void *addr, size_t num, int flag,
- const char *file, int line);
-void CRYPTO_mem_debug_realloc(void *addr1, void *addr2, size_t num, int flag,
- const char *file, int line);
-void CRYPTO_mem_debug_free(void *addr, int flag,
- const char *file, int line);
-
-int CRYPTO_mem_leaks_cb(int (*cb) (const char *str, size_t len, void *u),
- void *u);
-# ifndef OPENSSL_NO_STDIO
-int CRYPTO_mem_leaks_fp(FILE *);
-# endif
-int CRYPTO_mem_leaks(BIO *bio);
-# endif
-
-/* die if we have to */
-ossl_noreturn void OPENSSL_die(const char *assertion, const char *file, int line);
-# if OPENSSL_API_COMPAT < 0x10100000L
-# define OpenSSLDie(f,l,a) OPENSSL_die((a),(f),(l))
-# endif
-# define OPENSSL_assert(e) \
- (void)((e) ? 0 : (OPENSSL_die("assertion failed: " #e, OPENSSL_FILE, OPENSSL_LINE), 1))
-
-int OPENSSL_isservice(void);
-
-int FIPS_mode(void);
-int FIPS_mode_set(int r);
-
-void OPENSSL_init(void);
-# ifdef OPENSSL_SYS_UNIX
-void OPENSSL_fork_prepare(void);
-void OPENSSL_fork_parent(void);
-void OPENSSL_fork_child(void);
-# endif
-
-struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result);
-int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec);
-int OPENSSL_gmtime_diff(int *pday, int *psec,
- const struct tm *from, const struct tm *to);
-
-/*
- * CRYPTO_memcmp returns zero iff the |len| bytes at |a| and |b| are equal.
- * It takes an amount of time dependent on |len|, but independent of the
- * contents of |a| and |b|. Unlike memcmp, it cannot be used to put elements
- * into a defined order as the return value when a != b is undefined, other
- * than to be non-zero.
- */
-int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len);
-
-/* Standard initialisation options */
-# define OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS 0x00000001L
-# define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L
-# define OPENSSL_INIT_ADD_ALL_CIPHERS 0x00000004L
-# define OPENSSL_INIT_ADD_ALL_DIGESTS 0x00000008L
-# define OPENSSL_INIT_NO_ADD_ALL_CIPHERS 0x00000010L
-# define OPENSSL_INIT_NO_ADD_ALL_DIGESTS 0x00000020L
-# define OPENSSL_INIT_LOAD_CONFIG 0x00000040L
-# define OPENSSL_INIT_NO_LOAD_CONFIG 0x00000080L
-# define OPENSSL_INIT_ASYNC 0x00000100L
-# define OPENSSL_INIT_ENGINE_RDRAND 0x00000200L
-# define OPENSSL_INIT_ENGINE_DYNAMIC 0x00000400L
-# define OPENSSL_INIT_ENGINE_OPENSSL 0x00000800L
-# define OPENSSL_INIT_ENGINE_CRYPTODEV 0x00001000L
-# define OPENSSL_INIT_ENGINE_CAPI 0x00002000L
-# define OPENSSL_INIT_ENGINE_PADLOCK 0x00004000L
-# define OPENSSL_INIT_ENGINE_AFALG 0x00008000L
-/* OPENSSL_INIT_ZLIB 0x00010000L */
-# define OPENSSL_INIT_ATFORK 0x00020000L
-/* OPENSSL_INIT_BASE_ONLY 0x00040000L */
-# define OPENSSL_INIT_NO_ATEXIT 0x00080000L
-/* OPENSSL_INIT flag range 0xfff00000 reserved for OPENSSL_init_ssl() */
-/* Max OPENSSL_INIT flag value is 0x80000000 */
-
-/* openssl and dasync not counted as builtin */
-# define OPENSSL_INIT_ENGINE_ALL_BUILTIN \
- (OPENSSL_INIT_ENGINE_RDRAND | OPENSSL_INIT_ENGINE_DYNAMIC \
- | OPENSSL_INIT_ENGINE_CRYPTODEV | OPENSSL_INIT_ENGINE_CAPI | \
- OPENSSL_INIT_ENGINE_PADLOCK)
-
-
-/* Library initialisation functions */
-void OPENSSL_cleanup(void);
-int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
-int OPENSSL_atexit(void (*handler)(void));
-void OPENSSL_thread_stop(void);
-
-/* Low-level control of initialization */
-OPENSSL_INIT_SETTINGS *OPENSSL_INIT_new(void);
-# ifndef OPENSSL_NO_STDIO
-int OPENSSL_INIT_set_config_filename(OPENSSL_INIT_SETTINGS *settings,
- const char *config_filename);
-void OPENSSL_INIT_set_config_file_flags(OPENSSL_INIT_SETTINGS *settings,
- unsigned long flags);
-int OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS *settings,
- const char *config_appname);
-# endif
-void OPENSSL_INIT_free(OPENSSL_INIT_SETTINGS *settings);
-
-# if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
-# if defined(_WIN32)
-# if defined(BASETYPES) || defined(_WINDEF_H)
-/* application has to include <windows.h> in order to use this */
-typedef DWORD CRYPTO_THREAD_LOCAL;
-typedef DWORD CRYPTO_THREAD_ID;
-
-typedef LONG CRYPTO_ONCE;
-# define CRYPTO_ONCE_STATIC_INIT 0
-# endif
-# else
-# include <pthread.h>
-typedef pthread_once_t CRYPTO_ONCE;
-typedef pthread_key_t CRYPTO_THREAD_LOCAL;
-typedef pthread_t CRYPTO_THREAD_ID;
-
-# define CRYPTO_ONCE_STATIC_INIT PTHREAD_ONCE_INIT
-# endif
-# endif
-
-# if !defined(CRYPTO_ONCE_STATIC_INIT)
-typedef unsigned int CRYPTO_ONCE;
-typedef unsigned int CRYPTO_THREAD_LOCAL;
-typedef unsigned int CRYPTO_THREAD_ID;
-# define CRYPTO_ONCE_STATIC_INIT 0
-# endif
-
-int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void));
-
-int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *));
-void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key);
-int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val);
-int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key);
-
-CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void);
-int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b);
-
-
-# ifdef __cplusplus
-}
-# endif
-#endif
diff --git a/include/openssl/crypto.h.in b/include/openssl/crypto.h.in
new file mode 100644
index 000000000000..7232f647e8a3
--- /dev/null
+++ b/include/openssl/crypto.h.in
@@ -0,0 +1,535 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_CRYPTO_H
+# define OPENSSL_CRYPTO_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_CRYPTO_H
+# endif
+
+# include <stdlib.h>
+# include <time.h>
+
+# include <openssl/e_os2.h>
+
+# ifndef OPENSSL_NO_STDIO
+# include <stdio.h>
+# endif
+
+# include <openssl/safestack.h>
+# include <openssl/opensslv.h>
+# include <openssl/types.h>
+# include <openssl/opensslconf.h>
+# include <openssl/cryptoerr.h>
+# include <openssl/core.h>
+
+# ifdef CHARSET_EBCDIC
+# include <openssl/ebcdic.h>
+# endif
+
+/*
+ * Resolve problems on some operating systems with symbol names that clash
+ * one way or another
+ */
+# include <openssl/symhacks.h>
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# include <openssl/opensslv.h>
+# endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define SSLeay OpenSSL_version_num
+# define SSLeay_version OpenSSL_version
+# define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER
+# define SSLEAY_VERSION OPENSSL_VERSION
+# define SSLEAY_CFLAGS OPENSSL_CFLAGS
+# define SSLEAY_BUILT_ON OPENSSL_BUILT_ON
+# define SSLEAY_PLATFORM OPENSSL_PLATFORM
+# define SSLEAY_DIR OPENSSL_DIR
+
+/*
+ * Old type for allocating dynamic locks. No longer used. Use the new thread
+ * API instead.
+ */
+typedef struct {
+ int dummy;
+} CRYPTO_dynlock;
+
+# endif /* OPENSSL_NO_DEPRECATED_1_1_0 */
+
+typedef void CRYPTO_RWLOCK;
+
+CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void);
+__owur int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock);
+__owur int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock);
+int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock);
+void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock);
+
+int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock);
+int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret,
+ CRYPTO_RWLOCK *lock);
+int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock);
+
+/* No longer needed, so this is a no-op */
+#define OPENSSL_malloc_init() while(0) continue
+
+# define OPENSSL_malloc(num) \
+ CRYPTO_malloc(num, OPENSSL_FILE, OPENSSL_LINE)
+# define OPENSSL_zalloc(num) \
+ CRYPTO_zalloc(num, OPENSSL_FILE, OPENSSL_LINE)
+# define OPENSSL_realloc(addr, num) \
+ CRYPTO_realloc(addr, num, OPENSSL_FILE, OPENSSL_LINE)
+# define OPENSSL_clear_realloc(addr, old_num, num) \
+ CRYPTO_clear_realloc(addr, old_num, num, OPENSSL_FILE, OPENSSL_LINE)
+# define OPENSSL_clear_free(addr, num) \
+ CRYPTO_clear_free(addr, num, OPENSSL_FILE, OPENSSL_LINE)
+# define OPENSSL_free(addr) \
+ CRYPTO_free(addr, OPENSSL_FILE, OPENSSL_LINE)
+# define OPENSSL_memdup(str, s) \
+ CRYPTO_memdup((str), s, OPENSSL_FILE, OPENSSL_LINE)
+# define OPENSSL_strdup(str) \
+ CRYPTO_strdup(str, OPENSSL_FILE, OPENSSL_LINE)
+# define OPENSSL_strndup(str, n) \
+ CRYPTO_strndup(str, n, OPENSSL_FILE, OPENSSL_LINE)
+# define OPENSSL_secure_malloc(num) \
+ CRYPTO_secure_malloc(num, OPENSSL_FILE, OPENSSL_LINE)
+# define OPENSSL_secure_zalloc(num) \
+ CRYPTO_secure_zalloc(num, OPENSSL_FILE, OPENSSL_LINE)
+# define OPENSSL_secure_free(addr) \
+ CRYPTO_secure_free(addr, OPENSSL_FILE, OPENSSL_LINE)
+# define OPENSSL_secure_clear_free(addr, num) \
+ CRYPTO_secure_clear_free(addr, num, OPENSSL_FILE, OPENSSL_LINE)
+# define OPENSSL_secure_actual_size(ptr) \
+ CRYPTO_secure_actual_size(ptr)
+
+size_t OPENSSL_strlcpy(char *dst, const char *src, size_t siz);
+size_t OPENSSL_strlcat(char *dst, const char *src, size_t siz);
+size_t OPENSSL_strnlen(const char *str, size_t maxlen);
+int OPENSSL_buf2hexstr_ex(char *str, size_t str_n, size_t *strlength,
+ const unsigned char *buf, size_t buflen,
+ const char sep);
+char *OPENSSL_buf2hexstr(const unsigned char *buf, long buflen);
+int OPENSSL_hexstr2buf_ex(unsigned char *buf, size_t buf_n, size_t *buflen,
+ const char *str, const char sep);
+unsigned char *OPENSSL_hexstr2buf(const char *str, long *buflen);
+int OPENSSL_hexchar2int(unsigned char c);
+int OPENSSL_strcasecmp(const char *s1, const char *s2);
+int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n);
+
+# define OPENSSL_MALLOC_MAX_NELEMS(type) (((1U<<(sizeof(int)*8-1))-1)/sizeof(type))
+
+/*
+ * These functions return the values of OPENSSL_VERSION_MAJOR,
+ * OPENSSL_VERSION_MINOR, OPENSSL_VERSION_PATCH, OPENSSL_VERSION_PRE_RELEASE
+ * and OPENSSL_VERSION_BUILD_METADATA, respectively.
+ */
+unsigned int OPENSSL_version_major(void);
+unsigned int OPENSSL_version_minor(void);
+unsigned int OPENSSL_version_patch(void);
+const char *OPENSSL_version_pre_release(void);
+const char *OPENSSL_version_build_metadata(void);
+
+unsigned long OpenSSL_version_num(void);
+const char *OpenSSL_version(int type);
+# define OPENSSL_VERSION 0
+# define OPENSSL_CFLAGS 1
+# define OPENSSL_BUILT_ON 2
+# define OPENSSL_PLATFORM 3
+# define OPENSSL_DIR 4
+# define OPENSSL_ENGINES_DIR 5
+# define OPENSSL_VERSION_STRING 6
+# define OPENSSL_FULL_VERSION_STRING 7
+# define OPENSSL_MODULES_DIR 8
+# define OPENSSL_CPU_INFO 9
+
+const char *OPENSSL_info(int type);
+/*
+ * The series starts at 1001 to avoid confusion with the OpenSSL_version
+ * types.
+ */
+# define OPENSSL_INFO_CONFIG_DIR 1001
+# define OPENSSL_INFO_ENGINES_DIR 1002
+# define OPENSSL_INFO_MODULES_DIR 1003
+# define OPENSSL_INFO_DSO_EXTENSION 1004
+# define OPENSSL_INFO_DIR_FILENAME_SEPARATOR 1005
+# define OPENSSL_INFO_LIST_SEPARATOR 1006
+# define OPENSSL_INFO_SEED_SOURCE 1007
+# define OPENSSL_INFO_CPU_SETTINGS 1008
+
+int OPENSSL_issetugid(void);
+
+struct crypto_ex_data_st {
+ OSSL_LIB_CTX *ctx;
+ STACK_OF(void) *sk;
+};
+
+{-
+ generate_stack_macros("void");
+-}
+
+
+/*
+ * Per class, we have a STACK of function pointers.
+ */
+# define CRYPTO_EX_INDEX_SSL 0
+# define CRYPTO_EX_INDEX_SSL_CTX 1
+# define CRYPTO_EX_INDEX_SSL_SESSION 2
+# define CRYPTO_EX_INDEX_X509 3
+# define CRYPTO_EX_INDEX_X509_STORE 4
+# define CRYPTO_EX_INDEX_X509_STORE_CTX 5
+# define CRYPTO_EX_INDEX_DH 6
+# define CRYPTO_EX_INDEX_DSA 7
+# define CRYPTO_EX_INDEX_EC_KEY 8
+# define CRYPTO_EX_INDEX_RSA 9
+# define CRYPTO_EX_INDEX_ENGINE 10
+# define CRYPTO_EX_INDEX_UI 11
+# define CRYPTO_EX_INDEX_BIO 12
+# define CRYPTO_EX_INDEX_APP 13
+# define CRYPTO_EX_INDEX_UI_METHOD 14
+# define CRYPTO_EX_INDEX_RAND_DRBG 15
+# define CRYPTO_EX_INDEX_DRBG CRYPTO_EX_INDEX_RAND_DRBG
+# define CRYPTO_EX_INDEX_OSSL_LIB_CTX 16
+# define CRYPTO_EX_INDEX_EVP_PKEY 17
+# define CRYPTO_EX_INDEX__COUNT 18
+
+typedef void CRYPTO_EX_new (void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+ int idx, long argl, void *argp);
+typedef void CRYPTO_EX_free (void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+ int idx, long argl, void *argp);
+typedef int CRYPTO_EX_dup (CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from,
+ void **from_d, int idx, long argl, void *argp);
+__owur int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
+ CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func,
+ CRYPTO_EX_free *free_func);
+/* No longer use an index. */
+int CRYPTO_free_ex_index(int class_index, int idx);
+
+/*
+ * Initialise/duplicate/free CRYPTO_EX_DATA variables corresponding to a
+ * given class (invokes whatever per-class callbacks are applicable)
+ */
+int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad);
+int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
+ const CRYPTO_EX_DATA *from);
+
+void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad);
+
+/* Allocate a single item in the CRYPTO_EX_DATA variable */
+int CRYPTO_alloc_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad,
+ int idx);
+
+/*
+ * Get/set data in a CRYPTO_EX_DATA variable corresponding to a particular
+ * index (relative to the class type involved)
+ */
+int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val);
+void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx);
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+/*
+ * This function cleans up all "ex_data" state. It mustn't be called under
+ * potential race-conditions.
+ */
+# define CRYPTO_cleanup_all_ex_data() while(0) continue
+
+/*
+ * The old locking functions have been removed completely without compatibility
+ * macros. This is because the old functions either could not properly report
+ * errors, or the returned error values were not clearly documented.
+ * Replacing the locking functions with no-ops would cause race condition
+ * issues in the affected applications. It is far better for them to fail at
+ * compile time.
+ * On the other hand, the locking callbacks are no longer used. Consequently,
+ * the callback management functions can be safely replaced with no-op macros.
+ */
+# define CRYPTO_num_locks() (1)
+# define CRYPTO_set_locking_callback(func)
+# define CRYPTO_get_locking_callback() (NULL)
+# define CRYPTO_set_add_lock_callback(func)
+# define CRYPTO_get_add_lock_callback() (NULL)
+
+/*
+ * These defines where used in combination with the old locking callbacks,
+ * they are not called anymore, but old code that's not called might still
+ * use them.
+ */
+# define CRYPTO_LOCK 1
+# define CRYPTO_UNLOCK 2
+# define CRYPTO_READ 4
+# define CRYPTO_WRITE 8
+
+/* This structure is no longer used */
+typedef struct crypto_threadid_st {
+ int dummy;
+} CRYPTO_THREADID;
+/* Only use CRYPTO_THREADID_set_[numeric|pointer]() within callbacks */
+# define CRYPTO_THREADID_set_numeric(id, val)
+# define CRYPTO_THREADID_set_pointer(id, ptr)
+# define CRYPTO_THREADID_set_callback(threadid_func) (0)
+# define CRYPTO_THREADID_get_callback() (NULL)
+# define CRYPTO_THREADID_current(id)
+# define CRYPTO_THREADID_cmp(a, b) (-1)
+# define CRYPTO_THREADID_cpy(dest, src)
+# define CRYPTO_THREADID_hash(id) (0UL)
+
+# ifndef OPENSSL_NO_DEPRECATED_1_0_0
+# define CRYPTO_set_id_callback(func)
+# define CRYPTO_get_id_callback() (NULL)
+# define CRYPTO_thread_id() (0UL)
+# endif /* OPENSSL_NO_DEPRECATED_1_0_0 */
+
+# define CRYPTO_set_dynlock_create_callback(dyn_create_function)
+# define CRYPTO_set_dynlock_lock_callback(dyn_lock_function)
+# define CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function)
+# define CRYPTO_get_dynlock_create_callback() (NULL)
+# define CRYPTO_get_dynlock_lock_callback() (NULL)
+# define CRYPTO_get_dynlock_destroy_callback() (NULL)
+# endif /* OPENSSL_NO_DEPRECATED_1_1_0 */
+
+typedef void *(*CRYPTO_malloc_fn)(size_t num, const char *file, int line);
+typedef void *(*CRYPTO_realloc_fn)(void *addr, size_t num, const char *file,
+ int line);
+typedef void (*CRYPTO_free_fn)(void *addr, const char *file, int line);
+int CRYPTO_set_mem_functions(CRYPTO_malloc_fn malloc_fn,
+ CRYPTO_realloc_fn realloc_fn,
+ CRYPTO_free_fn free_fn);
+void CRYPTO_get_mem_functions(CRYPTO_malloc_fn *malloc_fn,
+ CRYPTO_realloc_fn *realloc_fn,
+ CRYPTO_free_fn *free_fn);
+
+void *CRYPTO_malloc(size_t num, const char *file, int line);
+void *CRYPTO_zalloc(size_t num, const char *file, int line);
+void *CRYPTO_memdup(const void *str, size_t siz, const char *file, int line);
+char *CRYPTO_strdup(const char *str, const char *file, int line);
+char *CRYPTO_strndup(const char *str, size_t s, const char *file, int line);
+void CRYPTO_free(void *ptr, const char *file, int line);
+void CRYPTO_clear_free(void *ptr, size_t num, const char *file, int line);
+void *CRYPTO_realloc(void *addr, size_t num, const char *file, int line);
+void *CRYPTO_clear_realloc(void *addr, size_t old_num, size_t num,
+ const char *file, int line);
+
+int CRYPTO_secure_malloc_init(size_t sz, size_t minsize);
+int CRYPTO_secure_malloc_done(void);
+void *CRYPTO_secure_malloc(size_t num, const char *file, int line);
+void *CRYPTO_secure_zalloc(size_t num, const char *file, int line);
+void CRYPTO_secure_free(void *ptr, const char *file, int line);
+void CRYPTO_secure_clear_free(void *ptr, size_t num,
+ const char *file, int line);
+int CRYPTO_secure_allocated(const void *ptr);
+int CRYPTO_secure_malloc_initialized(void);
+size_t CRYPTO_secure_actual_size(void *ptr);
+size_t CRYPTO_secure_used(void);
+
+void OPENSSL_cleanse(void *ptr, size_t len);
+
+# ifndef OPENSSL_NO_CRYPTO_MDEBUG
+/*
+ * The following can be used to detect memory leaks in the library. If
+ * used, it turns on malloc checking
+ */
+# define CRYPTO_MEM_CHECK_OFF 0x0 /* Control only */
+# define CRYPTO_MEM_CHECK_ON 0x1 /* Control and mode bit */
+# define CRYPTO_MEM_CHECK_ENABLE 0x2 /* Control and mode bit */
+# define CRYPTO_MEM_CHECK_DISABLE 0x3 /* Control only */
+
+void CRYPTO_get_alloc_counts(int *mcount, int *rcount, int *fcount);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define OPENSSL_mem_debug_push(info) \
+ CRYPTO_mem_debug_push(info, OPENSSL_FILE, OPENSSL_LINE)
+# define OPENSSL_mem_debug_pop() \
+ CRYPTO_mem_debug_pop()
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int CRYPTO_set_mem_debug(int flag);
+OSSL_DEPRECATEDIN_3_0 int CRYPTO_mem_ctrl(int mode);
+OSSL_DEPRECATEDIN_3_0 int CRYPTO_mem_debug_push(const char *info,
+ const char *file, int line);
+OSSL_DEPRECATEDIN_3_0 int CRYPTO_mem_debug_pop(void);
+OSSL_DEPRECATEDIN_3_0 void CRYPTO_mem_debug_malloc(void *addr, size_t num,
+ int flag,
+ const char *file, int line);
+OSSL_DEPRECATEDIN_3_0 void CRYPTO_mem_debug_realloc(void *addr1, void *addr2,
+ size_t num, int flag,
+ const char *file, int line);
+OSSL_DEPRECATEDIN_3_0 void CRYPTO_mem_debug_free(void *addr, int flag,
+ const char *file, int line);
+OSSL_DEPRECATEDIN_3_0
+int CRYPTO_mem_leaks_cb(int (*cb)(const char *str, size_t len, void *u),
+ void *u);
+# endif
+# ifndef OPENSSL_NO_STDIO
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int CRYPTO_mem_leaks_fp(FILE *);
+# endif
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int CRYPTO_mem_leaks(BIO *bio);
+# endif
+# endif /* OPENSSL_NO_CRYPTO_MDEBUG */
+
+/* die if we have to */
+ossl_noreturn void OPENSSL_die(const char *assertion, const char *file, int line);
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define OpenSSLDie(f,l,a) OPENSSL_die((a),(f),(l))
+# endif
+# define OPENSSL_assert(e) \
+ (void)((e) ? 0 : (OPENSSL_die("assertion failed: " #e, OPENSSL_FILE, OPENSSL_LINE), 1))
+
+int OPENSSL_isservice(void);
+
+void OPENSSL_init(void);
+# ifdef OPENSSL_SYS_UNIX
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 void OPENSSL_fork_prepare(void);
+OSSL_DEPRECATEDIN_3_0 void OPENSSL_fork_parent(void);
+OSSL_DEPRECATEDIN_3_0 void OPENSSL_fork_child(void);
+# endif
+# endif
+
+struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result);
+int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec);
+int OPENSSL_gmtime_diff(int *pday, int *psec,
+ const struct tm *from, const struct tm *to);
+
+/*
+ * CRYPTO_memcmp returns zero iff the |len| bytes at |a| and |b| are equal.
+ * It takes an amount of time dependent on |len|, but independent of the
+ * contents of |a| and |b|. Unlike memcmp, it cannot be used to put elements
+ * into a defined order as the return value when a != b is undefined, other
+ * than to be non-zero.
+ */
+int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len);
+
+/* Standard initialisation options */
+# define OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS 0x00000001L
+# define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L
+# define OPENSSL_INIT_ADD_ALL_CIPHERS 0x00000004L
+# define OPENSSL_INIT_ADD_ALL_DIGESTS 0x00000008L
+# define OPENSSL_INIT_NO_ADD_ALL_CIPHERS 0x00000010L
+# define OPENSSL_INIT_NO_ADD_ALL_DIGESTS 0x00000020L
+# define OPENSSL_INIT_LOAD_CONFIG 0x00000040L
+# define OPENSSL_INIT_NO_LOAD_CONFIG 0x00000080L
+# define OPENSSL_INIT_ASYNC 0x00000100L
+# define OPENSSL_INIT_ENGINE_RDRAND 0x00000200L
+# define OPENSSL_INIT_ENGINE_DYNAMIC 0x00000400L
+# define OPENSSL_INIT_ENGINE_OPENSSL 0x00000800L
+# define OPENSSL_INIT_ENGINE_CRYPTODEV 0x00001000L
+# define OPENSSL_INIT_ENGINE_CAPI 0x00002000L
+# define OPENSSL_INIT_ENGINE_PADLOCK 0x00004000L
+# define OPENSSL_INIT_ENGINE_AFALG 0x00008000L
+/* FREE: 0x00010000L */
+# define OPENSSL_INIT_ATFORK 0x00020000L
+/* OPENSSL_INIT_BASE_ONLY 0x00040000L */
+# define OPENSSL_INIT_NO_ATEXIT 0x00080000L
+/* OPENSSL_INIT flag range 0x03f00000 reserved for OPENSSL_init_ssl() */
+/* FREE: 0x04000000L */
+/* FREE: 0x08000000L */
+/* FREE: 0x10000000L */
+/* FREE: 0x20000000L */
+/* FREE: 0x40000000L */
+/* FREE: 0x80000000L */
+/* Max OPENSSL_INIT flag value is 0x80000000 */
+
+/* openssl and dasync not counted as builtin */
+# define OPENSSL_INIT_ENGINE_ALL_BUILTIN \
+ (OPENSSL_INIT_ENGINE_RDRAND | OPENSSL_INIT_ENGINE_DYNAMIC \
+ | OPENSSL_INIT_ENGINE_CRYPTODEV | OPENSSL_INIT_ENGINE_CAPI | \
+ OPENSSL_INIT_ENGINE_PADLOCK)
+
+/* Library initialisation functions */
+void OPENSSL_cleanup(void);
+int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
+int OPENSSL_atexit(void (*handler)(void));
+void OPENSSL_thread_stop(void);
+void OPENSSL_thread_stop_ex(OSSL_LIB_CTX *ctx);
+
+/* Low-level control of initialization */
+OPENSSL_INIT_SETTINGS *OPENSSL_INIT_new(void);
+# ifndef OPENSSL_NO_STDIO
+int OPENSSL_INIT_set_config_filename(OPENSSL_INIT_SETTINGS *settings,
+ const char *config_filename);
+void OPENSSL_INIT_set_config_file_flags(OPENSSL_INIT_SETTINGS *settings,
+ unsigned long flags);
+int OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS *settings,
+ const char *config_appname);
+# endif
+void OPENSSL_INIT_free(OPENSSL_INIT_SETTINGS *settings);
+
+# if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
+# if defined(_WIN32)
+# if defined(BASETYPES) || defined(_WINDEF_H)
+/* application has to include <windows.h> in order to use this */
+typedef DWORD CRYPTO_THREAD_LOCAL;
+typedef DWORD CRYPTO_THREAD_ID;
+
+typedef LONG CRYPTO_ONCE;
+# define CRYPTO_ONCE_STATIC_INIT 0
+# endif
+# else
+# if defined(__TANDEM) && defined(_SPT_MODEL_)
+# define SPT_THREAD_SIGNAL 1
+# define SPT_THREAD_AWARE 1
+# include <spthread.h>
+# else
+# include <pthread.h>
+# endif
+typedef pthread_once_t CRYPTO_ONCE;
+typedef pthread_key_t CRYPTO_THREAD_LOCAL;
+typedef pthread_t CRYPTO_THREAD_ID;
+
+# define CRYPTO_ONCE_STATIC_INIT PTHREAD_ONCE_INIT
+# endif
+# endif
+
+# if !defined(CRYPTO_ONCE_STATIC_INIT)
+typedef unsigned int CRYPTO_ONCE;
+typedef unsigned int CRYPTO_THREAD_LOCAL;
+typedef unsigned int CRYPTO_THREAD_ID;
+# define CRYPTO_ONCE_STATIC_INIT 0
+# endif
+
+int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void));
+
+int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *));
+void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key);
+int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val);
+int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key);
+
+CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void);
+int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b);
+
+OSSL_LIB_CTX *OSSL_LIB_CTX_new(void);
+OSSL_LIB_CTX *OSSL_LIB_CTX_new_from_dispatch(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in);
+OSSL_LIB_CTX *OSSL_LIB_CTX_new_child(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in);
+int OSSL_LIB_CTX_load_config(OSSL_LIB_CTX *ctx, const char *config_file);
+void OSSL_LIB_CTX_free(OSSL_LIB_CTX *);
+OSSL_LIB_CTX *OSSL_LIB_CTX_get0_global_default(void);
+OSSL_LIB_CTX *OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX *libctx);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/cryptoerr.h b/include/openssl/cryptoerr.h
index 3db5a4ee9911..c6a04d9b973a 100644
--- a/include/openssl/cryptoerr.h
+++ b/include/openssl/cryptoerr.h
@@ -1,57 +1,46 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_CRYPTOERR_H
-# define HEADER_CRYPTOERR_H
+#ifndef OPENSSL_CRYPTOERR_H
+# define OPENSSL_CRYPTOERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_CRYPTO_strings(void);
-/*
- * CRYPTO function codes.
- */
-# define CRYPTO_F_CMAC_CTX_NEW 120
-# define CRYPTO_F_CRYPTO_DUP_EX_DATA 110
-# define CRYPTO_F_CRYPTO_FREE_EX_DATA 111
-# define CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX 100
-# define CRYPTO_F_CRYPTO_MEMDUP 115
-# define CRYPTO_F_CRYPTO_NEW_EX_DATA 112
-# define CRYPTO_F_CRYPTO_OCB128_COPY_CTX 121
-# define CRYPTO_F_CRYPTO_OCB128_INIT 122
-# define CRYPTO_F_CRYPTO_SET_EX_DATA 102
-# define CRYPTO_F_FIPS_MODE_SET 109
-# define CRYPTO_F_GET_AND_LOCK 113
-# define CRYPTO_F_OPENSSL_ATEXIT 114
-# define CRYPTO_F_OPENSSL_BUF2HEXSTR 117
-# define CRYPTO_F_OPENSSL_FOPEN 119
-# define CRYPTO_F_OPENSSL_HEXSTR2BUF 118
-# define CRYPTO_F_OPENSSL_INIT_CRYPTO 116
-# define CRYPTO_F_OPENSSL_LH_NEW 126
-# define CRYPTO_F_OPENSSL_SK_DEEP_COPY 127
-# define CRYPTO_F_OPENSSL_SK_DUP 128
-# define CRYPTO_F_PKEY_HMAC_INIT 123
-# define CRYPTO_F_PKEY_POLY1305_INIT 124
-# define CRYPTO_F_PKEY_SIPHASH_INIT 125
-# define CRYPTO_F_SK_RESERVE 129
/*
* CRYPTO reason codes.
*/
-# define CRYPTO_R_FIPS_MODE_NOT_SUPPORTED 101
+# define CRYPTO_R_BAD_ALGORITHM_NAME 117
+# define CRYPTO_R_CONFLICTING_NAMES 118
+# define CRYPTO_R_HEX_STRING_TOO_SHORT 121
# define CRYPTO_R_ILLEGAL_HEX_DIGIT 102
+# define CRYPTO_R_INSUFFICIENT_DATA_SPACE 106
+# define CRYPTO_R_INSUFFICIENT_PARAM_SIZE 107
+# define CRYPTO_R_INSUFFICIENT_SECURE_DATA_SPACE 108
+# define CRYPTO_R_INVALID_NEGATIVE_VALUE 122
+# define CRYPTO_R_INVALID_NULL_ARGUMENT 109
+# define CRYPTO_R_INVALID_OSSL_PARAM_TYPE 110
# define CRYPTO_R_ODD_NUMBER_OF_DIGITS 103
+# define CRYPTO_R_PROVIDER_ALREADY_EXISTS 104
+# define CRYPTO_R_PROVIDER_SECTION_ERROR 105
+# define CRYPTO_R_RANDOM_SECTION_ERROR 119
+# define CRYPTO_R_SECURE_MALLOC_FAILURE 111
+# define CRYPTO_R_STRING_TOO_LONG 112
+# define CRYPTO_R_TOO_MANY_BYTES 113
+# define CRYPTO_R_TOO_MANY_RECORDS 114
+# define CRYPTO_R_TOO_SMALL_BUFFER 116
+# define CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION 120
+# define CRYPTO_R_ZERO_LENGTH_NUMBER 115
#endif
diff --git a/include/openssl/cryptoerr_legacy.h b/include/openssl/cryptoerr_legacy.h
new file mode 100644
index 000000000000..ccab33a5d4f0
--- /dev/null
+++ b/include/openssl/cryptoerr_legacy.h
@@ -0,0 +1,1466 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This header file preserves symbols from pre-3.0 OpenSSL.
+ * It should never be included directly, as it's already included
+ * by the public {lib}err.h headers, and since it will go away some
+ * time in the future.
+ */
+
+#ifndef OPENSSL_CRYPTOERR_LEGACY_H
+# define OPENSSL_CRYPTOERR_LEGACY_H
+# pragma once
+
+# include <openssl/macros.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int ERR_load_ASN1_strings(void);
+OSSL_DEPRECATEDIN_3_0 int ERR_load_ASYNC_strings(void);
+OSSL_DEPRECATEDIN_3_0 int ERR_load_BIO_strings(void);
+OSSL_DEPRECATEDIN_3_0 int ERR_load_BN_strings(void);
+OSSL_DEPRECATEDIN_3_0 int ERR_load_BUF_strings(void);
+# ifndef OPENSSL_NO_CMS
+OSSL_DEPRECATEDIN_3_0 int ERR_load_CMS_strings(void);
+# endif
+# ifndef OPENSSL_NO_COMP
+OSSL_DEPRECATEDIN_3_0 int ERR_load_COMP_strings(void);
+# endif
+OSSL_DEPRECATEDIN_3_0 int ERR_load_CONF_strings(void);
+OSSL_DEPRECATEDIN_3_0 int ERR_load_CRYPTO_strings(void);
+# ifndef OPENSSL_NO_CT
+OSSL_DEPRECATEDIN_3_0 int ERR_load_CT_strings(void);
+# endif
+# ifndef OPENSSL_NO_DH
+OSSL_DEPRECATEDIN_3_0 int ERR_load_DH_strings(void);
+# endif
+# ifndef OPENSSL_NO_DSA
+OSSL_DEPRECATEDIN_3_0 int ERR_load_DSA_strings(void);
+# endif
+# ifndef OPENSSL_NO_EC
+OSSL_DEPRECATEDIN_3_0 int ERR_load_EC_strings(void);
+# endif
+# ifndef OPENSSL_NO_ENGINE
+OSSL_DEPRECATEDIN_3_0 int ERR_load_ENGINE_strings(void);
+# endif
+OSSL_DEPRECATEDIN_3_0 int ERR_load_ERR_strings(void);
+OSSL_DEPRECATEDIN_3_0 int ERR_load_EVP_strings(void);
+OSSL_DEPRECATEDIN_3_0 int ERR_load_KDF_strings(void);
+OSSL_DEPRECATEDIN_3_0 int ERR_load_OBJ_strings(void);
+# ifndef OPENSSL_NO_OCSP
+OSSL_DEPRECATEDIN_3_0 int ERR_load_OCSP_strings(void);
+# endif
+OSSL_DEPRECATEDIN_3_0 int ERR_load_PEM_strings(void);
+OSSL_DEPRECATEDIN_3_0 int ERR_load_PKCS12_strings(void);
+OSSL_DEPRECATEDIN_3_0 int ERR_load_PKCS7_strings(void);
+OSSL_DEPRECATEDIN_3_0 int ERR_load_RAND_strings(void);
+OSSL_DEPRECATEDIN_3_0 int ERR_load_RSA_strings(void);
+OSSL_DEPRECATEDIN_3_0 int ERR_load_OSSL_STORE_strings(void);
+# ifndef OPENSSL_NO_TS
+OSSL_DEPRECATEDIN_3_0 int ERR_load_TS_strings(void);
+# endif
+OSSL_DEPRECATEDIN_3_0 int ERR_load_UI_strings(void);
+OSSL_DEPRECATEDIN_3_0 int ERR_load_X509_strings(void);
+OSSL_DEPRECATEDIN_3_0 int ERR_load_X509V3_strings(void);
+
+/* Collected _F_ macros from OpenSSL 1.1.1 */
+
+/*
+ * ASN1 function codes.
+ */
+# define ASN1_F_A2D_ASN1_OBJECT 0
+# define ASN1_F_A2I_ASN1_INTEGER 0
+# define ASN1_F_A2I_ASN1_STRING 0
+# define ASN1_F_APPEND_EXP 0
+# define ASN1_F_ASN1_BIO_INIT 0
+# define ASN1_F_ASN1_BIT_STRING_SET_BIT 0
+# define ASN1_F_ASN1_CB 0
+# define ASN1_F_ASN1_CHECK_TLEN 0
+# define ASN1_F_ASN1_COLLECT 0
+# define ASN1_F_ASN1_D2I_EX_PRIMITIVE 0
+# define ASN1_F_ASN1_D2I_FP 0
+# define ASN1_F_ASN1_D2I_READ_BIO 0
+# define ASN1_F_ASN1_DIGEST 0
+# define ASN1_F_ASN1_DO_ADB 0
+# define ASN1_F_ASN1_DO_LOCK 0
+# define ASN1_F_ASN1_DUP 0
+# define ASN1_F_ASN1_ENC_SAVE 0
+# define ASN1_F_ASN1_EX_C2I 0
+# define ASN1_F_ASN1_FIND_END 0
+# define ASN1_F_ASN1_GENERALIZEDTIME_ADJ 0
+# define ASN1_F_ASN1_GENERATE_V3 0
+# define ASN1_F_ASN1_GET_INT64 0
+# define ASN1_F_ASN1_GET_OBJECT 0
+# define ASN1_F_ASN1_GET_UINT64 0
+# define ASN1_F_ASN1_I2D_BIO 0
+# define ASN1_F_ASN1_I2D_FP 0
+# define ASN1_F_ASN1_ITEM_D2I_FP 0
+# define ASN1_F_ASN1_ITEM_DUP 0
+# define ASN1_F_ASN1_ITEM_EMBED_D2I 0
+# define ASN1_F_ASN1_ITEM_EMBED_NEW 0
+# define ASN1_F_ASN1_ITEM_FLAGS_I2D 0
+# define ASN1_F_ASN1_ITEM_I2D_BIO 0
+# define ASN1_F_ASN1_ITEM_I2D_FP 0
+# define ASN1_F_ASN1_ITEM_PACK 0
+# define ASN1_F_ASN1_ITEM_SIGN 0
+# define ASN1_F_ASN1_ITEM_SIGN_CTX 0
+# define ASN1_F_ASN1_ITEM_UNPACK 0
+# define ASN1_F_ASN1_ITEM_VERIFY 0
+# define ASN1_F_ASN1_MBSTRING_NCOPY 0
+# define ASN1_F_ASN1_OBJECT_NEW 0
+# define ASN1_F_ASN1_OUTPUT_DATA 0
+# define ASN1_F_ASN1_PCTX_NEW 0
+# define ASN1_F_ASN1_PRIMITIVE_NEW 0
+# define ASN1_F_ASN1_SCTX_NEW 0
+# define ASN1_F_ASN1_SIGN 0
+# define ASN1_F_ASN1_STR2TYPE 0
+# define ASN1_F_ASN1_STRING_GET_INT64 0
+# define ASN1_F_ASN1_STRING_GET_UINT64 0
+# define ASN1_F_ASN1_STRING_SET 0
+# define ASN1_F_ASN1_STRING_TABLE_ADD 0
+# define ASN1_F_ASN1_STRING_TO_BN 0
+# define ASN1_F_ASN1_STRING_TYPE_NEW 0
+# define ASN1_F_ASN1_TEMPLATE_EX_D2I 0
+# define ASN1_F_ASN1_TEMPLATE_NEW 0
+# define ASN1_F_ASN1_TEMPLATE_NOEXP_D2I 0
+# define ASN1_F_ASN1_TIME_ADJ 0
+# define ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING 0
+# define ASN1_F_ASN1_TYPE_GET_OCTETSTRING 0
+# define ASN1_F_ASN1_UTCTIME_ADJ 0
+# define ASN1_F_ASN1_VERIFY 0
+# define ASN1_F_B64_READ_ASN1 0
+# define ASN1_F_B64_WRITE_ASN1 0
+# define ASN1_F_BIO_NEW_NDEF 0
+# define ASN1_F_BITSTR_CB 0
+# define ASN1_F_BN_TO_ASN1_STRING 0
+# define ASN1_F_C2I_ASN1_BIT_STRING 0
+# define ASN1_F_C2I_ASN1_INTEGER 0
+# define ASN1_F_C2I_ASN1_OBJECT 0
+# define ASN1_F_C2I_IBUF 0
+# define ASN1_F_C2I_UINT64_INT 0
+# define ASN1_F_COLLECT_DATA 0
+# define ASN1_F_D2I_ASN1_OBJECT 0
+# define ASN1_F_D2I_ASN1_UINTEGER 0
+# define ASN1_F_D2I_AUTOPRIVATEKEY 0
+# define ASN1_F_D2I_PRIVATEKEY 0
+# define ASN1_F_D2I_PUBLICKEY 0
+# define ASN1_F_DO_BUF 0
+# define ASN1_F_DO_CREATE 0
+# define ASN1_F_DO_DUMP 0
+# define ASN1_F_DO_TCREATE 0
+# define ASN1_F_I2A_ASN1_OBJECT 0
+# define ASN1_F_I2D_ASN1_BIO_STREAM 0
+# define ASN1_F_I2D_ASN1_OBJECT 0
+# define ASN1_F_I2D_DSA_PUBKEY 0
+# define ASN1_F_I2D_EC_PUBKEY 0
+# define ASN1_F_I2D_PRIVATEKEY 0
+# define ASN1_F_I2D_PUBLICKEY 0
+# define ASN1_F_I2D_RSA_PUBKEY 0
+# define ASN1_F_LONG_C2I 0
+# define ASN1_F_NDEF_PREFIX 0
+# define ASN1_F_NDEF_SUFFIX 0
+# define ASN1_F_OID_MODULE_INIT 0
+# define ASN1_F_PARSE_TAGGING 0
+# define ASN1_F_PKCS5_PBE2_SET_IV 0
+# define ASN1_F_PKCS5_PBE2_SET_SCRYPT 0
+# define ASN1_F_PKCS5_PBE_SET 0
+# define ASN1_F_PKCS5_PBE_SET0_ALGOR 0
+# define ASN1_F_PKCS5_PBKDF2_SET 0
+# define ASN1_F_PKCS5_SCRYPT_SET 0
+# define ASN1_F_SMIME_READ_ASN1 0
+# define ASN1_F_SMIME_TEXT 0
+# define ASN1_F_STABLE_GET 0
+# define ASN1_F_STBL_MODULE_INIT 0
+# define ASN1_F_UINT32_C2I 0
+# define ASN1_F_UINT32_NEW 0
+# define ASN1_F_UINT64_C2I 0
+# define ASN1_F_UINT64_NEW 0
+# define ASN1_F_X509_CRL_ADD0_REVOKED 0
+# define ASN1_F_X509_INFO_NEW 0
+# define ASN1_F_X509_NAME_ENCODE 0
+# define ASN1_F_X509_NAME_EX_D2I 0
+# define ASN1_F_X509_NAME_EX_NEW 0
+# define ASN1_F_X509_PKEY_NEW 0
+
+/*
+ * ASYNC function codes.
+ */
+# define ASYNC_F_ASYNC_CTX_NEW 0
+# define ASYNC_F_ASYNC_INIT_THREAD 0
+# define ASYNC_F_ASYNC_JOB_NEW 0
+# define ASYNC_F_ASYNC_PAUSE_JOB 0
+# define ASYNC_F_ASYNC_START_FUNC 0
+# define ASYNC_F_ASYNC_START_JOB 0
+# define ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD 0
+
+/*
+ * BIO function codes.
+ */
+# define BIO_F_ACPT_STATE 0
+# define BIO_F_ADDRINFO_WRAP 0
+# define BIO_F_ADDR_STRINGS 0
+# define BIO_F_BIO_ACCEPT 0
+# define BIO_F_BIO_ACCEPT_EX 0
+# define BIO_F_BIO_ACCEPT_NEW 0
+# define BIO_F_BIO_ADDR_NEW 0
+# define BIO_F_BIO_BIND 0
+# define BIO_F_BIO_CALLBACK_CTRL 0
+# define BIO_F_BIO_CONNECT 0
+# define BIO_F_BIO_CONNECT_NEW 0
+# define BIO_F_BIO_CTRL 0
+# define BIO_F_BIO_GETS 0
+# define BIO_F_BIO_GET_HOST_IP 0
+# define BIO_F_BIO_GET_NEW_INDEX 0
+# define BIO_F_BIO_GET_PORT 0
+# define BIO_F_BIO_LISTEN 0
+# define BIO_F_BIO_LOOKUP 0
+# define BIO_F_BIO_LOOKUP_EX 0
+# define BIO_F_BIO_MAKE_PAIR 0
+# define BIO_F_BIO_METH_NEW 0
+# define BIO_F_BIO_NEW 0
+# define BIO_F_BIO_NEW_DGRAM_SCTP 0
+# define BIO_F_BIO_NEW_FILE 0
+# define BIO_F_BIO_NEW_MEM_BUF 0
+# define BIO_F_BIO_NREAD 0
+# define BIO_F_BIO_NREAD0 0
+# define BIO_F_BIO_NWRITE 0
+# define BIO_F_BIO_NWRITE0 0
+# define BIO_F_BIO_PARSE_HOSTSERV 0
+# define BIO_F_BIO_PUTS 0
+# define BIO_F_BIO_READ 0
+# define BIO_F_BIO_READ_EX 0
+# define BIO_F_BIO_READ_INTERN 0
+# define BIO_F_BIO_SOCKET 0
+# define BIO_F_BIO_SOCKET_NBIO 0
+# define BIO_F_BIO_SOCK_INFO 0
+# define BIO_F_BIO_SOCK_INIT 0
+# define BIO_F_BIO_WRITE 0
+# define BIO_F_BIO_WRITE_EX 0
+# define BIO_F_BIO_WRITE_INTERN 0
+# define BIO_F_BUFFER_CTRL 0
+# define BIO_F_CONN_CTRL 0
+# define BIO_F_CONN_STATE 0
+# define BIO_F_DGRAM_SCTP_NEW 0
+# define BIO_F_DGRAM_SCTP_READ 0
+# define BIO_F_DGRAM_SCTP_WRITE 0
+# define BIO_F_DOAPR_OUTCH 0
+# define BIO_F_FILE_CTRL 0
+# define BIO_F_FILE_READ 0
+# define BIO_F_LINEBUFFER_CTRL 0
+# define BIO_F_LINEBUFFER_NEW 0
+# define BIO_F_MEM_WRITE 0
+# define BIO_F_NBIOF_NEW 0
+# define BIO_F_SLG_WRITE 0
+# define BIO_F_SSL_NEW 0
+
+/*
+ * BN function codes.
+ */
+# define BN_F_BNRAND 0
+# define BN_F_BNRAND_RANGE 0
+# define BN_F_BN_BLINDING_CONVERT_EX 0
+# define BN_F_BN_BLINDING_CREATE_PARAM 0
+# define BN_F_BN_BLINDING_INVERT_EX 0
+# define BN_F_BN_BLINDING_NEW 0
+# define BN_F_BN_BLINDING_UPDATE 0
+# define BN_F_BN_BN2DEC 0
+# define BN_F_BN_BN2HEX 0
+# define BN_F_BN_COMPUTE_WNAF 0
+# define BN_F_BN_CTX_GET 0
+# define BN_F_BN_CTX_NEW 0
+# define BN_F_BN_CTX_START 0
+# define BN_F_BN_DIV 0
+# define BN_F_BN_DIV_RECP 0
+# define BN_F_BN_EXP 0
+# define BN_F_BN_EXPAND_INTERNAL 0
+# define BN_F_BN_GENCB_NEW 0
+# define BN_F_BN_GENERATE_DSA_NONCE 0
+# define BN_F_BN_GENERATE_PRIME_EX 0
+# define BN_F_BN_GF2M_MOD 0
+# define BN_F_BN_GF2M_MOD_EXP 0
+# define BN_F_BN_GF2M_MOD_MUL 0
+# define BN_F_BN_GF2M_MOD_SOLVE_QUAD 0
+# define BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR 0
+# define BN_F_BN_GF2M_MOD_SQR 0
+# define BN_F_BN_GF2M_MOD_SQRT 0
+# define BN_F_BN_LSHIFT 0
+# define BN_F_BN_MOD_EXP2_MONT 0
+# define BN_F_BN_MOD_EXP_MONT 0
+# define BN_F_BN_MOD_EXP_MONT_CONSTTIME 0
+# define BN_F_BN_MOD_EXP_MONT_WORD 0
+# define BN_F_BN_MOD_EXP_RECP 0
+# define BN_F_BN_MOD_EXP_SIMPLE 0
+# define BN_F_BN_MOD_INVERSE 0
+# define BN_F_BN_MOD_INVERSE_NO_BRANCH 0
+# define BN_F_BN_MOD_LSHIFT_QUICK 0
+# define BN_F_BN_MOD_SQRT 0
+# define BN_F_BN_MONT_CTX_NEW 0
+# define BN_F_BN_MPI2BN 0
+# define BN_F_BN_NEW 0
+# define BN_F_BN_POOL_GET 0
+# define BN_F_BN_RAND 0
+# define BN_F_BN_RAND_RANGE 0
+# define BN_F_BN_RECP_CTX_NEW 0
+# define BN_F_BN_RSHIFT 0
+# define BN_F_BN_SET_WORDS 0
+# define BN_F_BN_STACK_PUSH 0
+# define BN_F_BN_USUB 0
+
+/*
+ * BUF function codes.
+ */
+# define BUF_F_BUF_MEM_GROW 0
+# define BUF_F_BUF_MEM_GROW_CLEAN 0
+# define BUF_F_BUF_MEM_NEW 0
+
+# ifndef OPENSSL_NO_CMS
+/*
+ * CMS function codes.
+ */
+# define CMS_F_CHECK_CONTENT 0
+# define CMS_F_CMS_ADD0_CERT 0
+# define CMS_F_CMS_ADD0_RECIPIENT_KEY 0
+# define CMS_F_CMS_ADD0_RECIPIENT_PASSWORD 0
+# define CMS_F_CMS_ADD1_RECEIPTREQUEST 0
+# define CMS_F_CMS_ADD1_RECIPIENT_CERT 0
+# define CMS_F_CMS_ADD1_SIGNER 0
+# define CMS_F_CMS_ADD1_SIGNINGTIME 0
+# define CMS_F_CMS_COMPRESS 0
+# define CMS_F_CMS_COMPRESSEDDATA_CREATE 0
+# define CMS_F_CMS_COMPRESSEDDATA_INIT_BIO 0
+# define CMS_F_CMS_COPY_CONTENT 0
+# define CMS_F_CMS_COPY_MESSAGEDIGEST 0
+# define CMS_F_CMS_DATA 0
+# define CMS_F_CMS_DATAFINAL 0
+# define CMS_F_CMS_DATAINIT 0
+# define CMS_F_CMS_DECRYPT 0
+# define CMS_F_CMS_DECRYPT_SET1_KEY 0
+# define CMS_F_CMS_DECRYPT_SET1_PASSWORD 0
+# define CMS_F_CMS_DECRYPT_SET1_PKEY 0
+# define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX 0
+# define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO 0
+# define CMS_F_CMS_DIGESTEDDATA_DO_FINAL 0
+# define CMS_F_CMS_DIGEST_VERIFY 0
+# define CMS_F_CMS_ENCODE_RECEIPT 0
+# define CMS_F_CMS_ENCRYPT 0
+# define CMS_F_CMS_ENCRYPTEDCONTENT_INIT 0
+# define CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO 0
+# define CMS_F_CMS_ENCRYPTEDDATA_DECRYPT 0
+# define CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT 0
+# define CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY 0
+# define CMS_F_CMS_ENVELOPEDDATA_CREATE 0
+# define CMS_F_CMS_ENVELOPEDDATA_INIT_BIO 0
+# define CMS_F_CMS_ENVELOPED_DATA_INIT 0
+# define CMS_F_CMS_ENV_ASN1_CTRL 0
+# define CMS_F_CMS_FINAL 0
+# define CMS_F_CMS_GET0_CERTIFICATE_CHOICES 0
+# define CMS_F_CMS_GET0_CONTENT 0
+# define CMS_F_CMS_GET0_ECONTENT_TYPE 0
+# define CMS_F_CMS_GET0_ENVELOPED 0
+# define CMS_F_CMS_GET0_REVOCATION_CHOICES 0
+# define CMS_F_CMS_GET0_SIGNED 0
+# define CMS_F_CMS_MSGSIGDIGEST_ADD1 0
+# define CMS_F_CMS_RECEIPTREQUEST_CREATE0 0
+# define CMS_F_CMS_RECEIPT_VERIFY 0
+# define CMS_F_CMS_RECIPIENTINFO_DECRYPT 0
+# define CMS_F_CMS_RECIPIENTINFO_ENCRYPT 0
+# define CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT 0
+# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG 0
+# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID 0
+# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS 0
+# define CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP 0
+# define CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT 0
+# define CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT 0
+# define CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID 0
+# define CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP 0
+# define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP 0
+# define CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT 0
+# define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT 0
+# define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS 0
+# define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID 0
+# define CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT 0
+# define CMS_F_CMS_RECIPIENTINFO_SET0_KEY 0
+# define CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD 0
+# define CMS_F_CMS_RECIPIENTINFO_SET0_PKEY 0
+# define CMS_F_CMS_SD_ASN1_CTRL 0
+# define CMS_F_CMS_SET1_IAS 0
+# define CMS_F_CMS_SET1_KEYID 0
+# define CMS_F_CMS_SET1_SIGNERIDENTIFIER 0
+# define CMS_F_CMS_SET_DETACHED 0
+# define CMS_F_CMS_SIGN 0
+# define CMS_F_CMS_SIGNED_DATA_INIT 0
+# define CMS_F_CMS_SIGNERINFO_CONTENT_SIGN 0
+# define CMS_F_CMS_SIGNERINFO_SIGN 0
+# define CMS_F_CMS_SIGNERINFO_VERIFY 0
+# define CMS_F_CMS_SIGNERINFO_VERIFY_CERT 0
+# define CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT 0
+# define CMS_F_CMS_SIGN_RECEIPT 0
+# define CMS_F_CMS_SI_CHECK_ATTRIBUTES 0
+# define CMS_F_CMS_STREAM 0
+# define CMS_F_CMS_UNCOMPRESS 0
+# define CMS_F_CMS_VERIFY 0
+# define CMS_F_KEK_UNWRAP_KEY 0
+# endif
+
+# ifndef OPENSSL_NO_COMP
+/*
+ * COMP function codes.
+ */
+# define COMP_F_BIO_ZLIB_FLUSH 0
+# define COMP_F_BIO_ZLIB_NEW 0
+# define COMP_F_BIO_ZLIB_READ 0
+# define COMP_F_BIO_ZLIB_WRITE 0
+# define COMP_F_COMP_CTX_NEW 0
+# endif
+
+/*
+ * CONF function codes.
+ */
+# define CONF_F_CONF_DUMP_FP 0
+# define CONF_F_CONF_LOAD 0
+# define CONF_F_CONF_LOAD_FP 0
+# define CONF_F_CONF_PARSE_LIST 0
+# define CONF_F_DEF_LOAD 0
+# define CONF_F_DEF_LOAD_BIO 0
+# define CONF_F_GET_NEXT_FILE 0
+# define CONF_F_MODULE_ADD 0
+# define CONF_F_MODULE_INIT 0
+# define CONF_F_MODULE_LOAD_DSO 0
+# define CONF_F_MODULE_RUN 0
+# define CONF_F_NCONF_DUMP_BIO 0
+# define CONF_F_NCONF_DUMP_FP 0
+# define CONF_F_NCONF_GET_NUMBER_E 0
+# define CONF_F_NCONF_GET_SECTION 0
+# define CONF_F_NCONF_GET_STRING 0
+# define CONF_F_NCONF_LOAD 0
+# define CONF_F_NCONF_LOAD_BIO 0
+# define CONF_F_NCONF_LOAD_FP 0
+# define CONF_F_NCONF_NEW 0
+# define CONF_F_PROCESS_INCLUDE 0
+# define CONF_F_SSL_MODULE_INIT 0
+# define CONF_F_STR_COPY 0
+
+/*
+ * CRYPTO function codes.
+ */
+# define CRYPTO_F_CMAC_CTX_NEW 0
+# define CRYPTO_F_CRYPTO_DUP_EX_DATA 0
+# define CRYPTO_F_CRYPTO_FREE_EX_DATA 0
+# define CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX 0
+# define CRYPTO_F_CRYPTO_MEMDUP 0
+# define CRYPTO_F_CRYPTO_NEW_EX_DATA 0
+# define CRYPTO_F_CRYPTO_OCB128_COPY_CTX 0
+# define CRYPTO_F_CRYPTO_OCB128_INIT 0
+# define CRYPTO_F_CRYPTO_SET_EX_DATA 0
+# define CRYPTO_F_GET_AND_LOCK 0
+# define CRYPTO_F_OPENSSL_ATEXIT 0
+# define CRYPTO_F_OPENSSL_BUF2HEXSTR 0
+# define CRYPTO_F_OPENSSL_FOPEN 0
+# define CRYPTO_F_OPENSSL_HEXSTR2BUF 0
+# define CRYPTO_F_OPENSSL_INIT_CRYPTO 0
+# define CRYPTO_F_OPENSSL_LH_NEW 0
+# define CRYPTO_F_OPENSSL_SK_DEEP_COPY 0
+# define CRYPTO_F_OPENSSL_SK_DUP 0
+# define CRYPTO_F_PKEY_HMAC_INIT 0
+# define CRYPTO_F_PKEY_POLY1305_INIT 0
+# define CRYPTO_F_PKEY_SIPHASH_INIT 0
+# define CRYPTO_F_SK_RESERVE 0
+
+# ifndef OPENSSL_NO_CT
+/*
+ * CT function codes.
+ */
+# define CT_F_CTLOG_NEW 0
+# define CT_F_CTLOG_NEW_FROM_BASE64 0
+# define CT_F_CTLOG_NEW_FROM_CONF 0
+# define CT_F_CTLOG_STORE_LOAD_CTX_NEW 0
+# define CT_F_CTLOG_STORE_LOAD_FILE 0
+# define CT_F_CTLOG_STORE_LOAD_LOG 0
+# define CT_F_CTLOG_STORE_NEW 0
+# define CT_F_CT_BASE64_DECODE 0
+# define CT_F_CT_POLICY_EVAL_CTX_NEW 0
+# define CT_F_CT_V1_LOG_ID_FROM_PKEY 0
+# define CT_F_I2O_SCT 0
+# define CT_F_I2O_SCT_LIST 0
+# define CT_F_I2O_SCT_SIGNATURE 0
+# define CT_F_O2I_SCT 0
+# define CT_F_O2I_SCT_LIST 0
+# define CT_F_O2I_SCT_SIGNATURE 0
+# define CT_F_SCT_CTX_NEW 0
+# define CT_F_SCT_CTX_VERIFY 0
+# define CT_F_SCT_NEW 0
+# define CT_F_SCT_NEW_FROM_BASE64 0
+# define CT_F_SCT_SET0_LOG_ID 0
+# define CT_F_SCT_SET1_EXTENSIONS 0
+# define CT_F_SCT_SET1_LOG_ID 0
+# define CT_F_SCT_SET1_SIGNATURE 0
+# define CT_F_SCT_SET_LOG_ENTRY_TYPE 0
+# define CT_F_SCT_SET_SIGNATURE_NID 0
+# define CT_F_SCT_SET_VERSION 0
+# endif
+
+# ifndef OPENSSL_NO_DH
+/*
+ * DH function codes.
+ */
+# define DH_F_COMPUTE_KEY 0
+# define DH_F_DHPARAMS_PRINT_FP 0
+# define DH_F_DH_BUILTIN_GENPARAMS 0
+# define DH_F_DH_CHECK_EX 0
+# define DH_F_DH_CHECK_PARAMS_EX 0
+# define DH_F_DH_CHECK_PUB_KEY_EX 0
+# define DH_F_DH_CMS_DECRYPT 0
+# define DH_F_DH_CMS_SET_PEERKEY 0
+# define DH_F_DH_CMS_SET_SHARED_INFO 0
+# define DH_F_DH_METH_DUP 0
+# define DH_F_DH_METH_NEW 0
+# define DH_F_DH_METH_SET1_NAME 0
+# define DH_F_DH_NEW_BY_NID 0
+# define DH_F_DH_NEW_METHOD 0
+# define DH_F_DH_PARAM_DECODE 0
+# define DH_F_DH_PKEY_PUBLIC_CHECK 0
+# define DH_F_DH_PRIV_DECODE 0
+# define DH_F_DH_PRIV_ENCODE 0
+# define DH_F_DH_PUB_DECODE 0
+# define DH_F_DH_PUB_ENCODE 0
+# define DH_F_DO_DH_PRINT 0
+# define DH_F_GENERATE_KEY 0
+# define DH_F_PKEY_DH_CTRL_STR 0
+# define DH_F_PKEY_DH_DERIVE 0
+# define DH_F_PKEY_DH_INIT 0
+# define DH_F_PKEY_DH_KEYGEN 0
+# endif
+
+# ifndef OPENSSL_NO_DSA
+/*
+ * DSA function codes.
+ */
+# define DSA_F_DSAPARAMS_PRINT 0
+# define DSA_F_DSAPARAMS_PRINT_FP 0
+# define DSA_F_DSA_BUILTIN_PARAMGEN 0
+# define DSA_F_DSA_BUILTIN_PARAMGEN2 0
+# define DSA_F_DSA_DO_SIGN 0
+# define DSA_F_DSA_DO_VERIFY 0
+# define DSA_F_DSA_METH_DUP 0
+# define DSA_F_DSA_METH_NEW 0
+# define DSA_F_DSA_METH_SET1_NAME 0
+# define DSA_F_DSA_NEW_METHOD 0
+# define DSA_F_DSA_PARAM_DECODE 0
+# define DSA_F_DSA_PRINT_FP 0
+# define DSA_F_DSA_PRIV_DECODE 0
+# define DSA_F_DSA_PRIV_ENCODE 0
+# define DSA_F_DSA_PUB_DECODE 0
+# define DSA_F_DSA_PUB_ENCODE 0
+# define DSA_F_DSA_SIGN 0
+# define DSA_F_DSA_SIGN_SETUP 0
+# define DSA_F_DSA_SIG_NEW 0
+# define DSA_F_OLD_DSA_PRIV_DECODE 0
+# define DSA_F_PKEY_DSA_CTRL 0
+# define DSA_F_PKEY_DSA_CTRL_STR 0
+# define DSA_F_PKEY_DSA_KEYGEN 0
+# endif
+
+# ifndef OPENSSL_NO_EC
+/*
+ * EC function codes.
+ */
+# define EC_F_BN_TO_FELEM 0
+# define EC_F_D2I_ECPARAMETERS 0
+# define EC_F_D2I_ECPKPARAMETERS 0
+# define EC_F_D2I_ECPRIVATEKEY 0
+# define EC_F_DO_EC_KEY_PRINT 0
+# define EC_F_ECDH_CMS_DECRYPT 0
+# define EC_F_ECDH_CMS_SET_SHARED_INFO 0
+# define EC_F_ECDH_COMPUTE_KEY 0
+# define EC_F_ECDH_SIMPLE_COMPUTE_KEY 0
+# define EC_F_ECDSA_DO_SIGN_EX 0
+# define EC_F_ECDSA_DO_VERIFY 0
+# define EC_F_ECDSA_SIGN_EX 0
+# define EC_F_ECDSA_SIGN_SETUP 0
+# define EC_F_ECDSA_SIG_NEW 0
+# define EC_F_ECDSA_VERIFY 0
+# define EC_F_ECD_ITEM_VERIFY 0
+# define EC_F_ECKEY_PARAM2TYPE 0
+# define EC_F_ECKEY_PARAM_DECODE 0
+# define EC_F_ECKEY_PRIV_DECODE 0
+# define EC_F_ECKEY_PRIV_ENCODE 0
+# define EC_F_ECKEY_PUB_DECODE 0
+# define EC_F_ECKEY_PUB_ENCODE 0
+# define EC_F_ECKEY_TYPE2PARAM 0
+# define EC_F_ECPARAMETERS_PRINT 0
+# define EC_F_ECPARAMETERS_PRINT_FP 0
+# define EC_F_ECPKPARAMETERS_PRINT 0
+# define EC_F_ECPKPARAMETERS_PRINT_FP 0
+# define EC_F_ECP_NISTZ256_GET_AFFINE 0
+# define EC_F_ECP_NISTZ256_INV_MOD_ORD 0
+# define EC_F_ECP_NISTZ256_MULT_PRECOMPUTE 0
+# define EC_F_ECP_NISTZ256_POINTS_MUL 0
+# define EC_F_ECP_NISTZ256_PRE_COMP_NEW 0
+# define EC_F_ECP_NISTZ256_WINDOWED_MUL 0
+# define EC_F_ECX_KEY_OP 0
+# define EC_F_ECX_PRIV_ENCODE 0
+# define EC_F_ECX_PUB_ENCODE 0
+# define EC_F_EC_ASN1_GROUP2CURVE 0
+# define EC_F_EC_ASN1_GROUP2FIELDID 0
+# define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY 0
+# define EC_F_EC_GF2M_SIMPLE_FIELD_INV 0
+# define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT 0
+# define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE 0
+# define EC_F_EC_GF2M_SIMPLE_LADDER_POST 0
+# define EC_F_EC_GF2M_SIMPLE_LADDER_PRE 0
+# define EC_F_EC_GF2M_SIMPLE_OCT2POINT 0
+# define EC_F_EC_GF2M_SIMPLE_POINT2OCT 0
+# define EC_F_EC_GF2M_SIMPLE_POINTS_MUL 0
+# define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 0
+# define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 0
+# define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES 0
+# define EC_F_EC_GFP_MONT_FIELD_DECODE 0
+# define EC_F_EC_GFP_MONT_FIELD_ENCODE 0
+# define EC_F_EC_GFP_MONT_FIELD_INV 0
+# define EC_F_EC_GFP_MONT_FIELD_MUL 0
+# define EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE 0
+# define EC_F_EC_GFP_MONT_FIELD_SQR 0
+# define EC_F_EC_GFP_MONT_GROUP_SET_CURVE 0
+# define EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE 0
+# define EC_F_EC_GFP_NISTP224_POINTS_MUL 0
+# define EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES 0
+# define EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE 0
+# define EC_F_EC_GFP_NISTP256_POINTS_MUL 0
+# define EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES 0
+# define EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE 0
+# define EC_F_EC_GFP_NISTP521_POINTS_MUL 0
+# define EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES 0
+# define EC_F_EC_GFP_NIST_FIELD_MUL 0
+# define EC_F_EC_GFP_NIST_FIELD_SQR 0
+# define EC_F_EC_GFP_NIST_GROUP_SET_CURVE 0
+# define EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES 0
+# define EC_F_EC_GFP_SIMPLE_FIELD_INV 0
+# define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT 0
+# define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE 0
+# define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE 0
+# define EC_F_EC_GFP_SIMPLE_OCT2POINT 0
+# define EC_F_EC_GFP_SIMPLE_POINT2OCT 0
+# define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE 0
+# define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES 0
+# define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES 0
+# define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES 0
+# define EC_F_EC_GROUP_CHECK 0
+# define EC_F_EC_GROUP_CHECK_DISCRIMINANT 0
+# define EC_F_EC_GROUP_COPY 0
+# define EC_F_EC_GROUP_GET_CURVE 0
+# define EC_F_EC_GROUP_GET_CURVE_GF2M 0
+# define EC_F_EC_GROUP_GET_CURVE_GFP 0
+# define EC_F_EC_GROUP_GET_DEGREE 0
+# define EC_F_EC_GROUP_GET_ECPARAMETERS 0
+# define EC_F_EC_GROUP_GET_ECPKPARAMETERS 0
+# define EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS 0
+# define EC_F_EC_GROUP_GET_TRINOMIAL_BASIS 0
+# define EC_F_EC_GROUP_NEW 0
+# define EC_F_EC_GROUP_NEW_BY_CURVE_NAME 0
+# define EC_F_EC_GROUP_NEW_FROM_DATA 0
+# define EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS 0
+# define EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS 0
+# define EC_F_EC_GROUP_SET_CURVE 0
+# define EC_F_EC_GROUP_SET_CURVE_GF2M 0
+# define EC_F_EC_GROUP_SET_CURVE_GFP 0
+# define EC_F_EC_GROUP_SET_GENERATOR 0
+# define EC_F_EC_GROUP_SET_SEED 0
+# define EC_F_EC_KEY_CHECK_KEY 0
+# define EC_F_EC_KEY_COPY 0
+# define EC_F_EC_KEY_GENERATE_KEY 0
+# define EC_F_EC_KEY_NEW 0
+# define EC_F_EC_KEY_NEW_METHOD 0
+# define EC_F_EC_KEY_OCT2PRIV 0
+# define EC_F_EC_KEY_PRINT 0
+# define EC_F_EC_KEY_PRINT_FP 0
+# define EC_F_EC_KEY_PRIV2BUF 0
+# define EC_F_EC_KEY_PRIV2OCT 0
+# define EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES 0
+# define EC_F_EC_KEY_SIMPLE_CHECK_KEY 0
+# define EC_F_EC_KEY_SIMPLE_OCT2PRIV 0
+# define EC_F_EC_KEY_SIMPLE_PRIV2OCT 0
+# define EC_F_EC_PKEY_CHECK 0
+# define EC_F_EC_PKEY_PARAM_CHECK 0
+# define EC_F_EC_POINTS_MAKE_AFFINE 0
+# define EC_F_EC_POINTS_MUL 0
+# define EC_F_EC_POINT_ADD 0
+# define EC_F_EC_POINT_BN2POINT 0
+# define EC_F_EC_POINT_CMP 0
+# define EC_F_EC_POINT_COPY 0
+# define EC_F_EC_POINT_DBL 0
+# define EC_F_EC_POINT_GET_AFFINE_COORDINATES 0
+# define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M 0
+# define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP 0
+# define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP 0
+# define EC_F_EC_POINT_INVERT 0
+# define EC_F_EC_POINT_IS_AT_INFINITY 0
+# define EC_F_EC_POINT_IS_ON_CURVE 0
+# define EC_F_EC_POINT_MAKE_AFFINE 0
+# define EC_F_EC_POINT_NEW 0
+# define EC_F_EC_POINT_OCT2POINT 0
+# define EC_F_EC_POINT_POINT2BUF 0
+# define EC_F_EC_POINT_POINT2OCT 0
+# define EC_F_EC_POINT_SET_AFFINE_COORDINATES 0
+# define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M 0
+# define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP 0
+# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES 0
+# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M 0
+# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP 0
+# define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP 0
+# define EC_F_EC_POINT_SET_TO_INFINITY 0
+# define EC_F_EC_PRE_COMP_NEW 0
+# define EC_F_EC_SCALAR_MUL_LADDER 0
+# define EC_F_EC_WNAF_MUL 0
+# define EC_F_EC_WNAF_PRECOMPUTE_MULT 0
+# define EC_F_I2D_ECPARAMETERS 0
+# define EC_F_I2D_ECPKPARAMETERS 0
+# define EC_F_I2D_ECPRIVATEKEY 0
+# define EC_F_I2O_ECPUBLICKEY 0
+# define EC_F_NISTP224_PRE_COMP_NEW 0
+# define EC_F_NISTP256_PRE_COMP_NEW 0
+# define EC_F_NISTP521_PRE_COMP_NEW 0
+# define EC_F_O2I_ECPUBLICKEY 0
+# define EC_F_OLD_EC_PRIV_DECODE 0
+# define EC_F_OSSL_ECDH_COMPUTE_KEY 0
+# define EC_F_OSSL_ECDSA_SIGN_SIG 0
+# define EC_F_OSSL_ECDSA_VERIFY_SIG 0
+# define EC_F_PKEY_ECD_CTRL 0
+# define EC_F_PKEY_ECD_DIGESTSIGN 0
+# define EC_F_PKEY_ECD_DIGESTSIGN25519 0
+# define EC_F_PKEY_ECD_DIGESTSIGN448 0
+# define EC_F_PKEY_ECX_DERIVE 0
+# define EC_F_PKEY_EC_CTRL 0
+# define EC_F_PKEY_EC_CTRL_STR 0
+# define EC_F_PKEY_EC_DERIVE 0
+# define EC_F_PKEY_EC_INIT 0
+# define EC_F_PKEY_EC_KDF_DERIVE 0
+# define EC_F_PKEY_EC_KEYGEN 0
+# define EC_F_PKEY_EC_PARAMGEN 0
+# define EC_F_PKEY_EC_SIGN 0
+# define EC_F_VALIDATE_ECX_DERIVE 0
+# endif
+
+# ifndef OPENSSL_NO_ENGINE
+/*
+ * ENGINE function codes.
+ */
+# define ENGINE_F_DIGEST_UPDATE 0
+# define ENGINE_F_DYNAMIC_CTRL 0
+# define ENGINE_F_DYNAMIC_GET_DATA_CTX 0
+# define ENGINE_F_DYNAMIC_LOAD 0
+# define ENGINE_F_DYNAMIC_SET_DATA_CTX 0
+# define ENGINE_F_ENGINE_ADD 0
+# define ENGINE_F_ENGINE_BY_ID 0
+# define ENGINE_F_ENGINE_CMD_IS_EXECUTABLE 0
+# define ENGINE_F_ENGINE_CTRL 0
+# define ENGINE_F_ENGINE_CTRL_CMD 0
+# define ENGINE_F_ENGINE_CTRL_CMD_STRING 0
+# define ENGINE_F_ENGINE_FINISH 0
+# define ENGINE_F_ENGINE_GET_CIPHER 0
+# define ENGINE_F_ENGINE_GET_DIGEST 0
+# define ENGINE_F_ENGINE_GET_FIRST 0
+# define ENGINE_F_ENGINE_GET_LAST 0
+# define ENGINE_F_ENGINE_GET_NEXT 0
+# define ENGINE_F_ENGINE_GET_PKEY_ASN1_METH 0
+# define ENGINE_F_ENGINE_GET_PKEY_METH 0
+# define ENGINE_F_ENGINE_GET_PREV 0
+# define ENGINE_F_ENGINE_INIT 0
+# define ENGINE_F_ENGINE_LIST_ADD 0
+# define ENGINE_F_ENGINE_LIST_REMOVE 0
+# define ENGINE_F_ENGINE_LOAD_PRIVATE_KEY 0
+# define ENGINE_F_ENGINE_LOAD_PUBLIC_KEY 0
+# define ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT 0
+# define ENGINE_F_ENGINE_NEW 0
+# define ENGINE_F_ENGINE_PKEY_ASN1_FIND_STR 0
+# define ENGINE_F_ENGINE_REMOVE 0
+# define ENGINE_F_ENGINE_SET_DEFAULT_STRING 0
+# define ENGINE_F_ENGINE_SET_ID 0
+# define ENGINE_F_ENGINE_SET_NAME 0
+# define ENGINE_F_ENGINE_TABLE_REGISTER 0
+# define ENGINE_F_ENGINE_UNLOCKED_FINISH 0
+# define ENGINE_F_ENGINE_UP_REF 0
+# define ENGINE_F_INT_CLEANUP_ITEM 0
+# define ENGINE_F_INT_CTRL_HELPER 0
+# define ENGINE_F_INT_ENGINE_CONFIGURE 0
+# define ENGINE_F_INT_ENGINE_MODULE_INIT 0
+# define ENGINE_F_OSSL_HMAC_INIT 0
+# endif
+
+/*
+ * EVP function codes.
+ */
+# define EVP_F_AESNI_INIT_KEY 0
+# define EVP_F_AESNI_XTS_INIT_KEY 0
+# define EVP_F_AES_GCM_CTRL 0
+# define EVP_F_AES_INIT_KEY 0
+# define EVP_F_AES_OCB_CIPHER 0
+# define EVP_F_AES_T4_INIT_KEY 0
+# define EVP_F_AES_T4_XTS_INIT_KEY 0
+# define EVP_F_AES_WRAP_CIPHER 0
+# define EVP_F_AES_XTS_INIT_KEY 0
+# define EVP_F_ALG_MODULE_INIT 0
+# define EVP_F_ARIA_CCM_INIT_KEY 0
+# define EVP_F_ARIA_GCM_CTRL 0
+# define EVP_F_ARIA_GCM_INIT_KEY 0
+# define EVP_F_ARIA_INIT_KEY 0
+# define EVP_F_B64_NEW 0
+# define EVP_F_CAMELLIA_INIT_KEY 0
+# define EVP_F_CHACHA20_POLY1305_CTRL 0
+# define EVP_F_CMLL_T4_INIT_KEY 0
+# define EVP_F_DES_EDE3_WRAP_CIPHER 0
+# define EVP_F_DO_SIGVER_INIT 0
+# define EVP_F_ENC_NEW 0
+# define EVP_F_EVP_CIPHERINIT_EX 0
+# define EVP_F_EVP_CIPHER_ASN1_TO_PARAM 0
+# define EVP_F_EVP_CIPHER_CTX_COPY 0
+# define EVP_F_EVP_CIPHER_CTX_CTRL 0
+# define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH 0
+# define EVP_F_EVP_CIPHER_PARAM_TO_ASN1 0
+# define EVP_F_EVP_DECRYPTFINAL_EX 0
+# define EVP_F_EVP_DECRYPTUPDATE 0
+# define EVP_F_EVP_DIGESTFINALXOF 0
+# define EVP_F_EVP_DIGESTINIT_EX 0
+# define EVP_F_EVP_ENCRYPTDECRYPTUPDATE 0
+# define EVP_F_EVP_ENCRYPTFINAL_EX 0
+# define EVP_F_EVP_ENCRYPTUPDATE 0
+# define EVP_F_EVP_MD_CTX_COPY_EX 0
+# define EVP_F_EVP_MD_SIZE 0
+# define EVP_F_EVP_OPENINIT 0
+# define EVP_F_EVP_PBE_ALG_ADD 0
+# define EVP_F_EVP_PBE_ALG_ADD_TYPE 0
+# define EVP_F_EVP_PBE_CIPHERINIT 0
+# define EVP_F_EVP_PBE_SCRYPT 0
+# define EVP_F_EVP_PKCS82PKEY 0
+# define EVP_F_EVP_PKEY2PKCS8 0
+# define EVP_F_EVP_PKEY_ASN1_ADD0 0
+# define EVP_F_EVP_PKEY_CHECK 0
+# define EVP_F_EVP_PKEY_COPY_PARAMETERS 0
+# define EVP_F_EVP_PKEY_CTX_CTRL 0
+# define EVP_F_EVP_PKEY_CTX_CTRL_STR 0
+# define EVP_F_EVP_PKEY_CTX_DUP 0
+# define EVP_F_EVP_PKEY_CTX_MD 0
+# define EVP_F_EVP_PKEY_DECRYPT 0
+# define EVP_F_EVP_PKEY_DECRYPT_INIT 0
+# define EVP_F_EVP_PKEY_DECRYPT_OLD 0
+# define EVP_F_EVP_PKEY_DERIVE 0
+# define EVP_F_EVP_PKEY_DERIVE_INIT 0
+# define EVP_F_EVP_PKEY_DERIVE_SET_PEER 0
+# define EVP_F_EVP_PKEY_ENCRYPT 0
+# define EVP_F_EVP_PKEY_ENCRYPT_INIT 0
+# define EVP_F_EVP_PKEY_ENCRYPT_OLD 0
+# define EVP_F_EVP_PKEY_GET0_DH 0
+# define EVP_F_EVP_PKEY_GET0_DSA 0
+# define EVP_F_EVP_PKEY_GET0_EC_KEY 0
+# define EVP_F_EVP_PKEY_GET0_HMAC 0
+# define EVP_F_EVP_PKEY_GET0_POLY1305 0
+# define EVP_F_EVP_PKEY_GET0_RSA 0
+# define EVP_F_EVP_PKEY_GET0_SIPHASH 0
+# define EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY 0
+# define EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY 0
+# define EVP_F_EVP_PKEY_KEYGEN 0
+# define EVP_F_EVP_PKEY_KEYGEN_INIT 0
+# define EVP_F_EVP_PKEY_METH_ADD0 0
+# define EVP_F_EVP_PKEY_METH_NEW 0
+# define EVP_F_EVP_PKEY_NEW 0
+# define EVP_F_EVP_PKEY_NEW_CMAC_KEY 0
+# define EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY 0
+# define EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY 0
+# define EVP_F_EVP_PKEY_PARAMGEN 0
+# define EVP_F_EVP_PKEY_PARAMGEN_INIT 0
+# define EVP_F_EVP_PKEY_PARAM_CHECK 0
+# define EVP_F_EVP_PKEY_PUBLIC_CHECK 0
+# define EVP_F_EVP_PKEY_SET1_ENGINE 0
+# define EVP_F_EVP_PKEY_SET_ALIAS_TYPE 0
+# define EVP_F_EVP_PKEY_SIGN 0
+# define EVP_F_EVP_PKEY_SIGN_INIT 0
+# define EVP_F_EVP_PKEY_VERIFY 0
+# define EVP_F_EVP_PKEY_VERIFY_INIT 0
+# define EVP_F_EVP_PKEY_VERIFY_RECOVER 0
+# define EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT 0
+# define EVP_F_EVP_SIGNFINAL 0
+# define EVP_F_EVP_VERIFYFINAL 0
+# define EVP_F_INT_CTX_NEW 0
+# define EVP_F_OK_NEW 0
+# define EVP_F_PKCS5_PBE_KEYIVGEN 0
+# define EVP_F_PKCS5_V2_PBE_KEYIVGEN 0
+# define EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN 0
+# define EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN 0
+# define EVP_F_PKEY_SET_TYPE 0
+# define EVP_F_RC2_MAGIC_TO_METH 0
+# define EVP_F_RC5_CTRL 0
+# define EVP_F_R_32_12_16_INIT_KEY 0
+# define EVP_F_S390X_AES_GCM_CTRL 0
+# define EVP_F_UPDATE 0
+
+/*
+ * KDF function codes.
+ */
+# define KDF_F_PKEY_HKDF_CTRL_STR 0
+# define KDF_F_PKEY_HKDF_DERIVE 0
+# define KDF_F_PKEY_HKDF_INIT 0
+# define KDF_F_PKEY_SCRYPT_CTRL_STR 0
+# define KDF_F_PKEY_SCRYPT_CTRL_UINT64 0
+# define KDF_F_PKEY_SCRYPT_DERIVE 0
+# define KDF_F_PKEY_SCRYPT_INIT 0
+# define KDF_F_PKEY_SCRYPT_SET_MEMBUF 0
+# define KDF_F_PKEY_TLS1_PRF_CTRL_STR 0
+# define KDF_F_PKEY_TLS1_PRF_DERIVE 0
+# define KDF_F_PKEY_TLS1_PRF_INIT 0
+# define KDF_F_TLS1_PRF_ALG 0
+
+/*
+ * KDF reason codes.
+ */
+# define KDF_R_INVALID_DIGEST 0
+# define KDF_R_MISSING_ITERATION_COUNT 0
+# define KDF_R_MISSING_KEY 0
+# define KDF_R_MISSING_MESSAGE_DIGEST 0
+# define KDF_R_MISSING_PARAMETER 0
+# define KDF_R_MISSING_PASS 0
+# define KDF_R_MISSING_SALT 0
+# define KDF_R_MISSING_SECRET 0
+# define KDF_R_MISSING_SEED 0
+# define KDF_R_UNKNOWN_PARAMETER_TYPE 0
+# define KDF_R_VALUE_ERROR 0
+# define KDF_R_VALUE_MISSING 0
+
+/*
+ * OBJ function codes.
+ */
+# define OBJ_F_OBJ_ADD_OBJECT 0
+# define OBJ_F_OBJ_ADD_SIGID 0
+# define OBJ_F_OBJ_CREATE 0
+# define OBJ_F_OBJ_DUP 0
+# define OBJ_F_OBJ_NAME_NEW_INDEX 0
+# define OBJ_F_OBJ_NID2LN 0
+# define OBJ_F_OBJ_NID2OBJ 0
+# define OBJ_F_OBJ_NID2SN 0
+# define OBJ_F_OBJ_TXT2OBJ 0
+
+# ifndef OPENSSL_NO_OCSP
+/*
+ * OCSP function codes.
+ */
+# define OCSP_F_D2I_OCSP_NONCE 0
+# define OCSP_F_OCSP_BASIC_ADD1_STATUS 0
+# define OCSP_F_OCSP_BASIC_SIGN 0
+# define OCSP_F_OCSP_BASIC_SIGN_CTX 0
+# define OCSP_F_OCSP_BASIC_VERIFY 0
+# define OCSP_F_OCSP_CERT_ID_NEW 0
+# define OCSP_F_OCSP_CHECK_DELEGATED 0
+# define OCSP_F_OCSP_CHECK_IDS 0
+# define OCSP_F_OCSP_CHECK_ISSUER 0
+# define OCSP_F_OCSP_CHECK_VALIDITY 0
+# define OCSP_F_OCSP_MATCH_ISSUERID 0
+# define OCSP_F_OCSP_PARSE_URL 0
+# define OCSP_F_OCSP_REQUEST_SIGN 0
+# define OCSP_F_OCSP_REQUEST_VERIFY 0
+# define OCSP_F_OCSP_RESPONSE_GET1_BASIC 0
+# define OCSP_F_PARSE_HTTP_LINE1 0
+# endif
+
+/*
+ * PEM function codes.
+ */
+# define PEM_F_B2I_DSS 0
+# define PEM_F_B2I_PVK_BIO 0
+# define PEM_F_B2I_RSA 0
+# define PEM_F_CHECK_BITLEN_DSA 0
+# define PEM_F_CHECK_BITLEN_RSA 0
+# define PEM_F_D2I_PKCS8PRIVATEKEY_BIO 0
+# define PEM_F_D2I_PKCS8PRIVATEKEY_FP 0
+# define PEM_F_DO_B2I 0
+# define PEM_F_DO_B2I_BIO 0
+# define PEM_F_DO_BLOB_HEADER 0
+# define PEM_F_DO_I2B 0
+# define PEM_F_DO_PK8PKEY 0
+# define PEM_F_DO_PK8PKEY_FP 0
+# define PEM_F_DO_PVK_BODY 0
+# define PEM_F_DO_PVK_HEADER 0
+# define PEM_F_GET_HEADER_AND_DATA 0
+# define PEM_F_GET_NAME 0
+# define PEM_F_I2B_PVK 0
+# define PEM_F_I2B_PVK_BIO 0
+# define PEM_F_LOAD_IV 0
+# define PEM_F_PEM_ASN1_READ 0
+# define PEM_F_PEM_ASN1_READ_BIO 0
+# define PEM_F_PEM_ASN1_WRITE 0
+# define PEM_F_PEM_ASN1_WRITE_BIO 0
+# define PEM_F_PEM_DEF_CALLBACK 0
+# define PEM_F_PEM_DO_HEADER 0
+# define PEM_F_PEM_GET_EVP_CIPHER_INFO 0
+# define PEM_F_PEM_READ 0
+# define PEM_F_PEM_READ_BIO 0
+# define PEM_F_PEM_READ_BIO_DHPARAMS 0
+# define PEM_F_PEM_READ_BIO_EX 0
+# define PEM_F_PEM_READ_BIO_PARAMETERS 0
+# define PEM_F_PEM_READ_BIO_PRIVATEKEY 0
+# define PEM_F_PEM_READ_DHPARAMS 0
+# define PEM_F_PEM_READ_PRIVATEKEY 0
+# define PEM_F_PEM_SIGNFINAL 0
+# define PEM_F_PEM_WRITE 0
+# define PEM_F_PEM_WRITE_BIO 0
+# define PEM_F_PEM_WRITE_BIO_PRIVATEKEY_TRADITIONAL 0
+# define PEM_F_PEM_WRITE_PRIVATEKEY 0
+# define PEM_F_PEM_X509_INFO_READ 0
+# define PEM_F_PEM_X509_INFO_READ_BIO 0
+# define PEM_F_PEM_X509_INFO_WRITE_BIO 0
+
+/*
+ * PKCS12 function codes.
+ */
+# define PKCS12_F_OPENSSL_ASC2UNI 0
+# define PKCS12_F_OPENSSL_UNI2ASC 0
+# define PKCS12_F_OPENSSL_UNI2UTF8 0
+# define PKCS12_F_OPENSSL_UTF82UNI 0
+# define PKCS12_F_PKCS12_CREATE 0
+# define PKCS12_F_PKCS12_GEN_MAC 0
+# define PKCS12_F_PKCS12_INIT 0
+# define PKCS12_F_PKCS12_ITEM_DECRYPT_D2I 0
+# define PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT 0
+# define PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG 0
+# define PKCS12_F_PKCS12_KEY_GEN_ASC 0
+# define PKCS12_F_PKCS12_KEY_GEN_UNI 0
+# define PKCS12_F_PKCS12_KEY_GEN_UTF8 0
+# define PKCS12_F_PKCS12_NEWPASS 0
+# define PKCS12_F_PKCS12_PACK_P7DATA 0
+# define PKCS12_F_PKCS12_PACK_P7ENCDATA 0
+# define PKCS12_F_PKCS12_PARSE 0
+# define PKCS12_F_PKCS12_PBE_CRYPT 0
+# define PKCS12_F_PKCS12_PBE_KEYIVGEN 0
+# define PKCS12_F_PKCS12_SAFEBAG_CREATE0_P8INF 0
+# define PKCS12_F_PKCS12_SAFEBAG_CREATE0_PKCS8 0
+# define PKCS12_F_PKCS12_SAFEBAG_CREATE_PKCS8_ENCRYPT 0
+# define PKCS12_F_PKCS12_SETUP_MAC 0
+# define PKCS12_F_PKCS12_SET_MAC 0
+# define PKCS12_F_PKCS12_UNPACK_AUTHSAFES 0
+# define PKCS12_F_PKCS12_UNPACK_P7DATA 0
+# define PKCS12_F_PKCS12_VERIFY_MAC 0
+# define PKCS12_F_PKCS8_ENCRYPT 0
+# define PKCS12_F_PKCS8_SET0_PBE 0
+
+/*
+ * PKCS7 function codes.
+ */
+# define PKCS7_F_DO_PKCS7_SIGNED_ATTRIB 0
+# define PKCS7_F_PKCS7_ADD0_ATTRIB_SIGNING_TIME 0
+# define PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP 0
+# define PKCS7_F_PKCS7_ADD_CERTIFICATE 0
+# define PKCS7_F_PKCS7_ADD_CRL 0
+# define PKCS7_F_PKCS7_ADD_RECIPIENT_INFO 0
+# define PKCS7_F_PKCS7_ADD_SIGNATURE 0
+# define PKCS7_F_PKCS7_ADD_SIGNER 0
+# define PKCS7_F_PKCS7_BIO_ADD_DIGEST 0
+# define PKCS7_F_PKCS7_COPY_EXISTING_DIGEST 0
+# define PKCS7_F_PKCS7_CTRL 0
+# define PKCS7_F_PKCS7_DATADECODE 0
+# define PKCS7_F_PKCS7_DATAFINAL 0
+# define PKCS7_F_PKCS7_DATAINIT 0
+# define PKCS7_F_PKCS7_DATAVERIFY 0
+# define PKCS7_F_PKCS7_DECRYPT 0
+# define PKCS7_F_PKCS7_DECRYPT_RINFO 0
+# define PKCS7_F_PKCS7_ENCODE_RINFO 0
+# define PKCS7_F_PKCS7_ENCRYPT 0
+# define PKCS7_F_PKCS7_FINAL 0
+# define PKCS7_F_PKCS7_FIND_DIGEST 0
+# define PKCS7_F_PKCS7_GET0_SIGNERS 0
+# define PKCS7_F_PKCS7_RECIP_INFO_SET 0
+# define PKCS7_F_PKCS7_SET_CIPHER 0
+# define PKCS7_F_PKCS7_SET_CONTENT 0
+# define PKCS7_F_PKCS7_SET_DIGEST 0
+# define PKCS7_F_PKCS7_SET_TYPE 0
+# define PKCS7_F_PKCS7_SIGN 0
+# define PKCS7_F_PKCS7_SIGNATUREVERIFY 0
+# define PKCS7_F_PKCS7_SIGNER_INFO_SET 0
+# define PKCS7_F_PKCS7_SIGNER_INFO_SIGN 0
+# define PKCS7_F_PKCS7_SIGN_ADD_SIGNER 0
+# define PKCS7_F_PKCS7_SIMPLE_SMIMECAP 0
+# define PKCS7_F_PKCS7_VERIFY 0
+
+/*
+ * RAND function codes.
+ */
+# define RAND_F_DATA_COLLECT_METHOD 0
+# define RAND_F_DRBG_BYTES 0
+# define RAND_F_DRBG_GET_ENTROPY 0
+# define RAND_F_DRBG_SETUP 0
+# define RAND_F_GET_ENTROPY 0
+# define RAND_F_RAND_BYTES 0
+# define RAND_F_RAND_DRBG_ENABLE_LOCKING 0
+# define RAND_F_RAND_DRBG_GENERATE 0
+# define RAND_F_RAND_DRBG_GET_ENTROPY 0
+# define RAND_F_RAND_DRBG_GET_NONCE 0
+# define RAND_F_RAND_DRBG_INSTANTIATE 0
+# define RAND_F_RAND_DRBG_NEW 0
+# define RAND_F_RAND_DRBG_RESEED 0
+# define RAND_F_RAND_DRBG_RESTART 0
+# define RAND_F_RAND_DRBG_SET 0
+# define RAND_F_RAND_DRBG_SET_DEFAULTS 0
+# define RAND_F_RAND_DRBG_UNINSTANTIATE 0
+# define RAND_F_RAND_LOAD_FILE 0
+# define RAND_F_RAND_POOL_ACQUIRE_ENTROPY 0
+# define RAND_F_RAND_POOL_ADD 0
+# define RAND_F_RAND_POOL_ADD_BEGIN 0
+# define RAND_F_RAND_POOL_ADD_END 0
+# define RAND_F_RAND_POOL_ATTACH 0
+# define RAND_F_RAND_POOL_BYTES_NEEDED 0
+# define RAND_F_RAND_POOL_GROW 0
+# define RAND_F_RAND_POOL_NEW 0
+# define RAND_F_RAND_PSEUDO_BYTES 0
+# define RAND_F_RAND_WRITE_FILE 0
+
+/*
+ * RSA function codes.
+ */
+# define RSA_F_CHECK_PADDING_MD 0
+# define RSA_F_ENCODE_PKCS1 0
+# define RSA_F_INT_RSA_VERIFY 0
+# define RSA_F_OLD_RSA_PRIV_DECODE 0
+# define RSA_F_PKEY_PSS_INIT 0
+# define RSA_F_PKEY_RSA_CTRL 0
+# define RSA_F_PKEY_RSA_CTRL_STR 0
+# define RSA_F_PKEY_RSA_SIGN 0
+# define RSA_F_PKEY_RSA_VERIFY 0
+# define RSA_F_PKEY_RSA_VERIFYRECOVER 0
+# define RSA_F_RSA_ALGOR_TO_MD 0
+# define RSA_F_RSA_BUILTIN_KEYGEN 0
+# define RSA_F_RSA_CHECK_KEY 0
+# define RSA_F_RSA_CHECK_KEY_EX 0
+# define RSA_F_RSA_CMS_DECRYPT 0
+# define RSA_F_RSA_CMS_VERIFY 0
+# define RSA_F_RSA_ITEM_VERIFY 0
+# define RSA_F_RSA_METH_DUP 0
+# define RSA_F_RSA_METH_NEW 0
+# define RSA_F_RSA_METH_SET1_NAME 0
+# define RSA_F_RSA_MGF1_TO_MD 0
+# define RSA_F_RSA_MULTIP_INFO_NEW 0
+# define RSA_F_RSA_NEW_METHOD 0
+# define RSA_F_RSA_NULL 0
+# define RSA_F_RSA_NULL_PRIVATE_DECRYPT 0
+# define RSA_F_RSA_NULL_PRIVATE_ENCRYPT 0
+# define RSA_F_RSA_NULL_PUBLIC_DECRYPT 0
+# define RSA_F_RSA_NULL_PUBLIC_ENCRYPT 0
+# define RSA_F_RSA_OSSL_PRIVATE_DECRYPT 0
+# define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT 0
+# define RSA_F_RSA_OSSL_PUBLIC_DECRYPT 0
+# define RSA_F_RSA_OSSL_PUBLIC_ENCRYPT 0
+# define RSA_F_RSA_PADDING_ADD_NONE 0
+# define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP 0
+# define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1 0
+# define RSA_F_RSA_PADDING_ADD_PKCS1_PSS 0
+# define RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1 0
+# define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1 0
+# define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2 0
+# define RSA_F_RSA_PADDING_ADD_SSLV23 0
+# define RSA_F_RSA_PADDING_ADD_X931 0
+# define RSA_F_RSA_PADDING_CHECK_NONE 0
+# define RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP 0
+# define RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1 0
+# define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1 0
+# define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2 0
+# define RSA_F_RSA_PADDING_CHECK_SSLV23 0
+# define RSA_F_RSA_PADDING_CHECK_X931 0
+# define RSA_F_RSA_PARAM_DECODE 0
+# define RSA_F_RSA_PRINT 0
+# define RSA_F_RSA_PRINT_FP 0
+# define RSA_F_RSA_PRIV_DECODE 0
+# define RSA_F_RSA_PRIV_ENCODE 0
+# define RSA_F_RSA_PSS_GET_PARAM 0
+# define RSA_F_RSA_PSS_TO_CTX 0
+# define RSA_F_RSA_PUB_DECODE 0
+# define RSA_F_RSA_SETUP_BLINDING 0
+# define RSA_F_RSA_SIGN 0
+# define RSA_F_RSA_SIGN_ASN1_OCTET_STRING 0
+# define RSA_F_RSA_VERIFY 0
+# define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING 0
+# define RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1 0
+# define RSA_F_SETUP_TBUF 0
+
+/*
+ * OSSL_STORE function codes.
+ */
+# define OSSL_STORE_F_FILE_CTRL 0
+# define OSSL_STORE_F_FILE_FIND 0
+# define OSSL_STORE_F_FILE_GET_PASS 0
+# define OSSL_STORE_F_FILE_LOAD 0
+# define OSSL_STORE_F_FILE_LOAD_TRY_DECODE 0
+# define OSSL_STORE_F_FILE_NAME_TO_URI 0
+# define OSSL_STORE_F_FILE_OPEN 0
+# define OSSL_STORE_F_OSSL_STORE_ATTACH_PEM_BIO 0
+# define OSSL_STORE_F_OSSL_STORE_EXPECT 0
+# define OSSL_STORE_F_OSSL_STORE_FILE_ATTACH_PEM_BIO_INT 0
+# define OSSL_STORE_F_OSSL_STORE_FIND 0
+# define OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT 0
+# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT 0
+# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL 0
+# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME 0
+# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION 0
+# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS 0
+# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY 0
+# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT 0
+# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL 0
+# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED 0
+# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME 0
+# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS 0
+# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY 0
+# define OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION 0
+# define OSSL_STORE_F_OSSL_STORE_INIT_ONCE 0
+# define OSSL_STORE_F_OSSL_STORE_LOADER_NEW 0
+# define OSSL_STORE_F_OSSL_STORE_OPEN 0
+# define OSSL_STORE_F_OSSL_STORE_OPEN_INT 0
+# define OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT 0
+# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ALIAS 0
+# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ISSUER_SERIAL 0
+# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT 0
+# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_NAME 0
+# define OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT 0
+# define OSSL_STORE_F_TRY_DECODE_PARAMS 0
+# define OSSL_STORE_F_TRY_DECODE_PKCS12 0
+# define OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED 0
+
+# ifndef OPENSSL_NO_TS
+/*
+ * TS function codes.
+ */
+# define TS_F_DEF_SERIAL_CB 0
+# define TS_F_DEF_TIME_CB 0
+# define TS_F_ESS_ADD_SIGNING_CERT 0
+# define TS_F_ESS_ADD_SIGNING_CERT_V2 0
+# define TS_F_ESS_CERT_ID_NEW_INIT 0
+# define TS_F_ESS_CERT_ID_V2_NEW_INIT 0
+# define TS_F_ESS_SIGNING_CERT_NEW_INIT 0
+# define TS_F_ESS_SIGNING_CERT_V2_NEW_INIT 0
+# define TS_F_INT_TS_RESP_VERIFY_TOKEN 0
+# define TS_F_PKCS7_TO_TS_TST_INFO 0
+# define TS_F_TS_ACCURACY_SET_MICROS 0
+# define TS_F_TS_ACCURACY_SET_MILLIS 0
+# define TS_F_TS_ACCURACY_SET_SECONDS 0
+# define TS_F_TS_CHECK_IMPRINTS 0
+# define TS_F_TS_CHECK_NONCES 0
+# define TS_F_TS_CHECK_POLICY 0
+# define TS_F_TS_CHECK_SIGNING_CERTS 0
+# define TS_F_TS_CHECK_STATUS_INFO 0
+# define TS_F_TS_COMPUTE_IMPRINT 0
+# define TS_F_TS_CONF_INVALID 0
+# define TS_F_TS_CONF_LOAD_CERT 0
+# define TS_F_TS_CONF_LOAD_CERTS 0
+# define TS_F_TS_CONF_LOAD_KEY 0
+# define TS_F_TS_CONF_LOOKUP_FAIL 0
+# define TS_F_TS_CONF_SET_DEFAULT_ENGINE 0
+# define TS_F_TS_GET_STATUS_TEXT 0
+# define TS_F_TS_MSG_IMPRINT_SET_ALGO 0
+# define TS_F_TS_REQ_SET_MSG_IMPRINT 0
+# define TS_F_TS_REQ_SET_NONCE 0
+# define TS_F_TS_REQ_SET_POLICY_ID 0
+# define TS_F_TS_RESP_CREATE_RESPONSE 0
+# define TS_F_TS_RESP_CREATE_TST_INFO 0
+# define TS_F_TS_RESP_CTX_ADD_FAILURE_INFO 0
+# define TS_F_TS_RESP_CTX_ADD_MD 0
+# define TS_F_TS_RESP_CTX_ADD_POLICY 0
+# define TS_F_TS_RESP_CTX_NEW 0
+# define TS_F_TS_RESP_CTX_SET_ACCURACY 0
+# define TS_F_TS_RESP_CTX_SET_CERTS 0
+# define TS_F_TS_RESP_CTX_SET_DEF_POLICY 0
+# define TS_F_TS_RESP_CTX_SET_SIGNER_CERT 0
+# define TS_F_TS_RESP_CTX_SET_STATUS_INFO 0
+# define TS_F_TS_RESP_GET_POLICY 0
+# define TS_F_TS_RESP_SET_GENTIME_WITH_PRECISION 0
+# define TS_F_TS_RESP_SET_STATUS_INFO 0
+# define TS_F_TS_RESP_SET_TST_INFO 0
+# define TS_F_TS_RESP_SIGN 0
+# define TS_F_TS_RESP_VERIFY_SIGNATURE 0
+# define TS_F_TS_TST_INFO_SET_ACCURACY 0
+# define TS_F_TS_TST_INFO_SET_MSG_IMPRINT 0
+# define TS_F_TS_TST_INFO_SET_NONCE 0
+# define TS_F_TS_TST_INFO_SET_POLICY_ID 0
+# define TS_F_TS_TST_INFO_SET_SERIAL 0
+# define TS_F_TS_TST_INFO_SET_TIME 0
+# define TS_F_TS_TST_INFO_SET_TSA 0
+# define TS_F_TS_VERIFY 0
+# define TS_F_TS_VERIFY_CERT 0
+# define TS_F_TS_VERIFY_CTX_NEW 0
+# endif
+
+/*
+ * UI function codes.
+ */
+# define UI_F_CLOSE_CONSOLE 0
+# define UI_F_ECHO_CONSOLE 0
+# define UI_F_GENERAL_ALLOCATE_BOOLEAN 0
+# define UI_F_GENERAL_ALLOCATE_PROMPT 0
+# define UI_F_NOECHO_CONSOLE 0
+# define UI_F_OPEN_CONSOLE 0
+# define UI_F_UI_CONSTRUCT_PROMPT 0
+# define UI_F_UI_CREATE_METHOD 0
+# define UI_F_UI_CTRL 0
+# define UI_F_UI_DUP_ERROR_STRING 0
+# define UI_F_UI_DUP_INFO_STRING 0
+# define UI_F_UI_DUP_INPUT_BOOLEAN 0
+# define UI_F_UI_DUP_INPUT_STRING 0
+# define UI_F_UI_DUP_USER_DATA 0
+# define UI_F_UI_DUP_VERIFY_STRING 0
+# define UI_F_UI_GET0_RESULT 0
+# define UI_F_UI_GET_RESULT_LENGTH 0
+# define UI_F_UI_NEW_METHOD 0
+# define UI_F_UI_PROCESS 0
+# define UI_F_UI_SET_RESULT 0
+# define UI_F_UI_SET_RESULT_EX 0
+
+/*
+ * X509 function codes.
+ */
+# define X509_F_ADD_CERT_DIR 0
+# define X509_F_BUILD_CHAIN 0
+# define X509_F_BY_FILE_CTRL 0
+# define X509_F_CHECK_NAME_CONSTRAINTS 0
+# define X509_F_CHECK_POLICY 0
+# define X509_F_DANE_I2D 0
+# define X509_F_DIR_CTRL 0
+# define X509_F_GET_CERT_BY_SUBJECT 0
+# define X509_F_I2D_X509_AUX 0
+# define X509_F_LOOKUP_CERTS_SK 0
+# define X509_F_NETSCAPE_SPKI_B64_DECODE 0
+# define X509_F_NETSCAPE_SPKI_B64_ENCODE 0
+# define X509_F_NEW_DIR 0
+# define X509_F_X509AT_ADD1_ATTR 0
+# define X509_F_X509V3_ADD_EXT 0
+# define X509_F_X509_ATTRIBUTE_CREATE_BY_NID 0
+# define X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ 0
+# define X509_F_X509_ATTRIBUTE_CREATE_BY_TXT 0
+# define X509_F_X509_ATTRIBUTE_GET0_DATA 0
+# define X509_F_X509_ATTRIBUTE_SET1_DATA 0
+# define X509_F_X509_CHECK_PRIVATE_KEY 0
+# define X509_F_X509_CRL_DIFF 0
+# define X509_F_X509_CRL_METHOD_NEW 0
+# define X509_F_X509_CRL_PRINT_FP 0
+# define X509_F_X509_EXTENSION_CREATE_BY_NID 0
+# define X509_F_X509_EXTENSION_CREATE_BY_OBJ 0
+# define X509_F_X509_GET_PUBKEY_PARAMETERS 0
+# define X509_F_X509_LOAD_CERT_CRL_FILE 0
+# define X509_F_X509_LOAD_CERT_FILE 0
+# define X509_F_X509_LOAD_CRL_FILE 0
+# define X509_F_X509_LOOKUP_METH_NEW 0
+# define X509_F_X509_LOOKUP_NEW 0
+# define X509_F_X509_NAME_ADD_ENTRY 0
+# define X509_F_X509_NAME_CANON 0
+# define X509_F_X509_NAME_ENTRY_CREATE_BY_NID 0
+# define X509_F_X509_NAME_ENTRY_CREATE_BY_TXT 0
+# define X509_F_X509_NAME_ENTRY_SET_OBJECT 0
+# define X509_F_X509_NAME_ONELINE 0
+# define X509_F_X509_NAME_PRINT 0
+# define X509_F_X509_OBJECT_NEW 0
+# define X509_F_X509_PRINT_EX_FP 0
+# define X509_F_X509_PUBKEY_DECODE 0
+# define X509_F_X509_PUBKEY_GET 0
+# define X509_F_X509_PUBKEY_GET0 0
+# define X509_F_X509_PUBKEY_SET 0
+# define X509_F_X509_REQ_CHECK_PRIVATE_KEY 0
+# define X509_F_X509_REQ_PRINT_EX 0
+# define X509_F_X509_REQ_PRINT_FP 0
+# define X509_F_X509_REQ_TO_X509 0
+# define X509_F_X509_STORE_ADD_CERT 0
+# define X509_F_X509_STORE_ADD_CRL 0
+# define X509_F_X509_STORE_ADD_LOOKUP 0
+# define X509_F_X509_STORE_CTX_GET1_ISSUER 0
+# define X509_F_X509_STORE_CTX_INIT 0
+# define X509_F_X509_STORE_CTX_NEW 0
+# define X509_F_X509_STORE_CTX_PURPOSE_INHERIT 0
+# define X509_F_X509_STORE_NEW 0
+# define X509_F_X509_TO_X509_REQ 0
+# define X509_F_X509_TRUST_ADD 0
+# define X509_F_X509_TRUST_SET 0
+# define X509_F_X509_VERIFY_CERT 0
+# define X509_F_X509_VERIFY_PARAM_NEW 0
+
+/*
+ * X509V3 function codes.
+ */
+# define X509V3_F_A2I_GENERAL_NAME 0
+# define X509V3_F_ADDR_VALIDATE_PATH_INTERNAL 0
+# define X509V3_F_ASIDENTIFIERCHOICE_CANONIZE 0
+# define X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL 0
+# define X509V3_F_BIGNUM_TO_STRING 0
+# define X509V3_F_COPY_EMAIL 0
+# define X509V3_F_COPY_ISSUER 0
+# define X509V3_F_DO_DIRNAME 0
+# define X509V3_F_DO_EXT_I2D 0
+# define X509V3_F_DO_EXT_NCONF 0
+# define X509V3_F_GNAMES_FROM_SECTNAME 0
+# define X509V3_F_I2S_ASN1_ENUMERATED 0
+# define X509V3_F_I2S_ASN1_IA5STRING 0
+# define X509V3_F_I2S_ASN1_INTEGER 0
+# define X509V3_F_I2V_AUTHORITY_INFO_ACCESS 0
+# define X509V3_F_LEVEL_ADD_NODE 0
+# define X509V3_F_NOTICE_SECTION 0
+# define X509V3_F_NREF_NOS 0
+# define X509V3_F_POLICY_CACHE_CREATE 0
+# define X509V3_F_POLICY_CACHE_NEW 0
+# define X509V3_F_POLICY_DATA_NEW 0
+# define X509V3_F_POLICY_SECTION 0
+# define X509V3_F_PROCESS_PCI_VALUE 0
+# define X509V3_F_R2I_CERTPOL 0
+# define X509V3_F_R2I_PCI 0
+# define X509V3_F_S2I_ASN1_IA5STRING 0
+# define X509V3_F_S2I_ASN1_INTEGER 0
+# define X509V3_F_S2I_ASN1_OCTET_STRING 0
+# define X509V3_F_S2I_SKEY_ID 0
+# define X509V3_F_SET_DIST_POINT_NAME 0
+# define X509V3_F_SXNET_ADD_ID_ASC 0
+# define X509V3_F_SXNET_ADD_ID_INTEGER 0
+# define X509V3_F_SXNET_ADD_ID_ULONG 0
+# define X509V3_F_SXNET_GET_ID_ASC 0
+# define X509V3_F_SXNET_GET_ID_ULONG 0
+# define X509V3_F_TREE_INIT 0
+# define X509V3_F_V2I_ASIDENTIFIERS 0
+# define X509V3_F_V2I_ASN1_BIT_STRING 0
+# define X509V3_F_V2I_AUTHORITY_INFO_ACCESS 0
+# define X509V3_F_V2I_AUTHORITY_KEYID 0
+# define X509V3_F_V2I_BASIC_CONSTRAINTS 0
+# define X509V3_F_V2I_CRLD 0
+# define X509V3_F_V2I_EXTENDED_KEY_USAGE 0
+# define X509V3_F_V2I_GENERAL_NAMES 0
+# define X509V3_F_V2I_GENERAL_NAME_EX 0
+# define X509V3_F_V2I_IDP 0
+# define X509V3_F_V2I_IPADDRBLOCKS 0
+# define X509V3_F_V2I_ISSUER_ALT 0
+# define X509V3_F_V2I_NAME_CONSTRAINTS 0
+# define X509V3_F_V2I_POLICY_CONSTRAINTS 0
+# define X509V3_F_V2I_POLICY_MAPPINGS 0
+# define X509V3_F_V2I_SUBJECT_ALT 0
+# define X509V3_F_V2I_TLS_FEATURE 0
+# define X509V3_F_V3_GENERIC_EXTENSION 0
+# define X509V3_F_X509V3_ADD1_I2D 0
+# define X509V3_F_X509V3_ADD_VALUE 0
+# define X509V3_F_X509V3_EXT_ADD 0
+# define X509V3_F_X509V3_EXT_ADD_ALIAS 0
+# define X509V3_F_X509V3_EXT_I2D 0
+# define X509V3_F_X509V3_EXT_NCONF 0
+# define X509V3_F_X509V3_GET_SECTION 0
+# define X509V3_F_X509V3_GET_STRING 0
+# define X509V3_F_X509V3_GET_VALUE_BOOL 0
+# define X509V3_F_X509V3_PARSE_LIST 0
+# define X509V3_F_X509_PURPOSE_ADD 0
+# define X509V3_F_X509_PURPOSE_SET 0
+
+/*
+ * Compatibility defines.
+ */
+# define EVP_R_OPERATON_NOT_INITIALIZED EVP_R_OPERATION_NOT_INITIALIZED
+
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/ct.h b/include/openssl/ct.h
deleted file mode 100644
index ebdba34d6777..000000000000
--- a/include/openssl/ct.h
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_CT_H
-# define HEADER_CT_H
-
-# include <openssl/opensslconf.h>
-
-# ifndef OPENSSL_NO_CT
-# include <openssl/ossl_typ.h>
-# include <openssl/safestack.h>
-# include <openssl/x509.h>
-# include <openssl/cterr.h>
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-
-/* Minimum RSA key size, from RFC6962 */
-# define SCT_MIN_RSA_BITS 2048
-
-/* All hashes are SHA256 in v1 of Certificate Transparency */
-# define CT_V1_HASHLEN SHA256_DIGEST_LENGTH
-
-typedef enum {
- CT_LOG_ENTRY_TYPE_NOT_SET = -1,
- CT_LOG_ENTRY_TYPE_X509 = 0,
- CT_LOG_ENTRY_TYPE_PRECERT = 1
-} ct_log_entry_type_t;
-
-typedef enum {
- SCT_VERSION_NOT_SET = -1,
- SCT_VERSION_V1 = 0
-} sct_version_t;
-
-typedef enum {
- SCT_SOURCE_UNKNOWN,
- SCT_SOURCE_TLS_EXTENSION,
- SCT_SOURCE_X509V3_EXTENSION,
- SCT_SOURCE_OCSP_STAPLED_RESPONSE
-} sct_source_t;
-
-typedef enum {
- SCT_VALIDATION_STATUS_NOT_SET,
- SCT_VALIDATION_STATUS_UNKNOWN_LOG,
- SCT_VALIDATION_STATUS_VALID,
- SCT_VALIDATION_STATUS_INVALID,
- SCT_VALIDATION_STATUS_UNVERIFIED,
- SCT_VALIDATION_STATUS_UNKNOWN_VERSION
-} sct_validation_status_t;
-
-DEFINE_STACK_OF(SCT)
-DEFINE_STACK_OF(CTLOG)
-
-/******************************************
- * CT policy evaluation context functions *
- ******************************************/
-
-/*
- * Creates a new, empty policy evaluation context.
- * The caller is responsible for calling CT_POLICY_EVAL_CTX_free when finished
- * with the CT_POLICY_EVAL_CTX.
- */
-CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void);
-
-/* Deletes a policy evaluation context and anything it owns. */
-void CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx);
-
-/* Gets the peer certificate that the SCTs are for */
-X509* CT_POLICY_EVAL_CTX_get0_cert(const CT_POLICY_EVAL_CTX *ctx);
-
-/*
- * Sets the certificate associated with the received SCTs.
- * Increments the reference count of cert.
- * Returns 1 on success, 0 otherwise.
- */
-int CT_POLICY_EVAL_CTX_set1_cert(CT_POLICY_EVAL_CTX *ctx, X509 *cert);
-
-/* Gets the issuer of the aforementioned certificate */
-X509* CT_POLICY_EVAL_CTX_get0_issuer(const CT_POLICY_EVAL_CTX *ctx);
-
-/*
- * Sets the issuer of the certificate associated with the received SCTs.
- * Increments the reference count of issuer.
- * Returns 1 on success, 0 otherwise.
- */
-int CT_POLICY_EVAL_CTX_set1_issuer(CT_POLICY_EVAL_CTX *ctx, X509 *issuer);
-
-/* Gets the CT logs that are trusted sources of SCTs */
-const CTLOG_STORE *CT_POLICY_EVAL_CTX_get0_log_store(const CT_POLICY_EVAL_CTX *ctx);
-
-/* Sets the log store that is in use. It must outlive the CT_POLICY_EVAL_CTX. */
-void CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(CT_POLICY_EVAL_CTX *ctx,
- CTLOG_STORE *log_store);
-
-/*
- * Gets the time, in milliseconds since the Unix epoch, that will be used as the
- * current time when checking whether an SCT was issued in the future.
- * Such SCTs will fail validation, as required by RFC6962.
- */
-uint64_t CT_POLICY_EVAL_CTX_get_time(const CT_POLICY_EVAL_CTX *ctx);
-
-/*
- * Sets the time to evaluate SCTs against, in milliseconds since the Unix epoch.
- * If an SCT's timestamp is after this time, it will be interpreted as having
- * been issued in the future. RFC6962 states that "TLS clients MUST reject SCTs
- * whose timestamp is in the future", so an SCT will not validate in this case.
- */
-void CT_POLICY_EVAL_CTX_set_time(CT_POLICY_EVAL_CTX *ctx, uint64_t time_in_ms);
-
-/*****************
- * SCT functions *
- *****************/
-
-/*
- * Creates a new, blank SCT.
- * The caller is responsible for calling SCT_free when finished with the SCT.
- */
-SCT *SCT_new(void);
-
-/*
- * Creates a new SCT from some base64-encoded strings.
- * The caller is responsible for calling SCT_free when finished with the SCT.
- */
-SCT *SCT_new_from_base64(unsigned char version,
- const char *logid_base64,
- ct_log_entry_type_t entry_type,
- uint64_t timestamp,
- const char *extensions_base64,
- const char *signature_base64);
-
-/*
- * Frees the SCT and the underlying data structures.
- */
-void SCT_free(SCT *sct);
-
-/*
- * Free a stack of SCTs, and the underlying SCTs themselves.
- * Intended to be compatible with X509V3_EXT_FREE.
- */
-void SCT_LIST_free(STACK_OF(SCT) *a);
-
-/*
- * Returns the version of the SCT.
- */
-sct_version_t SCT_get_version(const SCT *sct);
-
-/*
- * Set the version of an SCT.
- * Returns 1 on success, 0 if the version is unrecognized.
- */
-__owur int SCT_set_version(SCT *sct, sct_version_t version);
-
-/*
- * Returns the log entry type of the SCT.
- */
-ct_log_entry_type_t SCT_get_log_entry_type(const SCT *sct);
-
-/*
- * Set the log entry type of an SCT.
- * Returns 1 on success, 0 otherwise.
- */
-__owur int SCT_set_log_entry_type(SCT *sct, ct_log_entry_type_t entry_type);
-
-/*
- * Gets the ID of the log that an SCT came from.
- * Ownership of the log ID remains with the SCT.
- * Returns the length of the log ID.
- */
-size_t SCT_get0_log_id(const SCT *sct, unsigned char **log_id);
-
-/*
- * Set the log ID of an SCT to point directly to the *log_id specified.
- * The SCT takes ownership of the specified pointer.
- * Returns 1 on success, 0 otherwise.
- */
-__owur int SCT_set0_log_id(SCT *sct, unsigned char *log_id, size_t log_id_len);
-
-/*
- * Set the log ID of an SCT.
- * This makes a copy of the log_id.
- * Returns 1 on success, 0 otherwise.
- */
-__owur int SCT_set1_log_id(SCT *sct, const unsigned char *log_id,
- size_t log_id_len);
-
-/*
- * Returns the timestamp for the SCT (epoch time in milliseconds).
- */
-uint64_t SCT_get_timestamp(const SCT *sct);
-
-/*
- * Set the timestamp of an SCT (epoch time in milliseconds).
- */
-void SCT_set_timestamp(SCT *sct, uint64_t timestamp);
-
-/*
- * Return the NID for the signature used by the SCT.
- * For CT v1, this will be either NID_sha256WithRSAEncryption or
- * NID_ecdsa_with_SHA256 (or NID_undef if incorrect/unset).
- */
-int SCT_get_signature_nid(const SCT *sct);
-
-/*
- * Set the signature type of an SCT
- * For CT v1, this should be either NID_sha256WithRSAEncryption or
- * NID_ecdsa_with_SHA256.
- * Returns 1 on success, 0 otherwise.
- */
-__owur int SCT_set_signature_nid(SCT *sct, int nid);
-
-/*
- * Set *ext to point to the extension data for the SCT. ext must not be NULL.
- * The SCT retains ownership of this pointer.
- * Returns length of the data pointed to.
- */
-size_t SCT_get0_extensions(const SCT *sct, unsigned char **ext);
-
-/*
- * Set the extensions of an SCT to point directly to the *ext specified.
- * The SCT takes ownership of the specified pointer.
- */
-void SCT_set0_extensions(SCT *sct, unsigned char *ext, size_t ext_len);
-
-/*
- * Set the extensions of an SCT.
- * This takes a copy of the ext.
- * Returns 1 on success, 0 otherwise.
- */
-__owur int SCT_set1_extensions(SCT *sct, const unsigned char *ext,
- size_t ext_len);
-
-/*
- * Set *sig to point to the signature for the SCT. sig must not be NULL.
- * The SCT retains ownership of this pointer.
- * Returns length of the data pointed to.
- */
-size_t SCT_get0_signature(const SCT *sct, unsigned char **sig);
-
-/*
- * Set the signature of an SCT to point directly to the *sig specified.
- * The SCT takes ownership of the specified pointer.
- */
-void SCT_set0_signature(SCT *sct, unsigned char *sig, size_t sig_len);
-
-/*
- * Set the signature of an SCT to be a copy of the *sig specified.
- * Returns 1 on success, 0 otherwise.
- */
-__owur int SCT_set1_signature(SCT *sct, const unsigned char *sig,
- size_t sig_len);
-
-/*
- * The origin of this SCT, e.g. TLS extension, OCSP response, etc.
- */
-sct_source_t SCT_get_source(const SCT *sct);
-
-/*
- * Set the origin of this SCT, e.g. TLS extension, OCSP response, etc.
- * Returns 1 on success, 0 otherwise.
- */
-__owur int SCT_set_source(SCT *sct, sct_source_t source);
-
-/*
- * Returns a text string describing the validation status of |sct|.
- */
-const char *SCT_validation_status_string(const SCT *sct);
-
-/*
- * Pretty-prints an |sct| to |out|.
- * It will be indented by the number of spaces specified by |indent|.
- * If |logs| is not NULL, it will be used to lookup the CT log that the SCT came
- * from, so that the log name can be printed.
- */
-void SCT_print(const SCT *sct, BIO *out, int indent, const CTLOG_STORE *logs);
-
-/*
- * Pretty-prints an |sct_list| to |out|.
- * It will be indented by the number of spaces specified by |indent|.
- * SCTs will be delimited by |separator|.
- * If |logs| is not NULL, it will be used to lookup the CT log that each SCT
- * came from, so that the log names can be printed.
- */
-void SCT_LIST_print(const STACK_OF(SCT) *sct_list, BIO *out, int indent,
- const char *separator, const CTLOG_STORE *logs);
-
-/*
- * Gets the last result of validating this SCT.
- * If it has not been validated yet, returns SCT_VALIDATION_STATUS_NOT_SET.
- */
-sct_validation_status_t SCT_get_validation_status(const SCT *sct);
-
-/*
- * Validates the given SCT with the provided context.
- * Sets the "validation_status" field of the SCT.
- * Returns 1 if the SCT is valid and the signature verifies.
- * Returns 0 if the SCT is invalid or could not be verified.
- * Returns -1 if an error occurs.
- */
-__owur int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx);
-
-/*
- * Validates the given list of SCTs with the provided context.
- * Sets the "validation_status" field of each SCT.
- * Returns 1 if there are no invalid SCTs and all signatures verify.
- * Returns 0 if at least one SCT is invalid or could not be verified.
- * Returns a negative integer if an error occurs.
- */
-__owur int SCT_LIST_validate(const STACK_OF(SCT) *scts,
- CT_POLICY_EVAL_CTX *ctx);
-
-
-/*********************************
- * SCT parsing and serialisation *
- *********************************/
-
-/*
- * Serialize (to TLS format) a stack of SCTs and return the length.
- * "a" must not be NULL.
- * If "pp" is NULL, just return the length of what would have been serialized.
- * If "pp" is not NULL and "*pp" is null, function will allocate a new pointer
- * for data that caller is responsible for freeing (only if function returns
- * successfully).
- * If "pp" is NULL and "*pp" is not NULL, caller is responsible for ensuring
- * that "*pp" is large enough to accept all of the serialized data.
- * Returns < 0 on error, >= 0 indicating bytes written (or would have been)
- * on success.
- */
-__owur int i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp);
-
-/*
- * Convert TLS format SCT list to a stack of SCTs.
- * If "a" or "*a" is NULL, a new stack will be created that the caller is
- * responsible for freeing (by calling SCT_LIST_free).
- * "**pp" and "*pp" must not be NULL.
- * Upon success, "*pp" will point to after the last bytes read, and a stack
- * will be returned.
- * Upon failure, a NULL pointer will be returned, and the position of "*pp" is
- * not defined.
- */
-STACK_OF(SCT) *o2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp,
- size_t len);
-
-/*
- * Serialize (to DER format) a stack of SCTs and return the length.
- * "a" must not be NULL.
- * If "pp" is NULL, just returns the length of what would have been serialized.
- * If "pp" is not NULL and "*pp" is null, function will allocate a new pointer
- * for data that caller is responsible for freeing (only if function returns
- * successfully).
- * If "pp" is NULL and "*pp" is not NULL, caller is responsible for ensuring
- * that "*pp" is large enough to accept all of the serialized data.
- * Returns < 0 on error, >= 0 indicating bytes written (or would have been)
- * on success.
- */
-__owur int i2d_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp);
-
-/*
- * Parses an SCT list in DER format and returns it.
- * If "a" or "*a" is NULL, a new stack will be created that the caller is
- * responsible for freeing (by calling SCT_LIST_free).
- * "**pp" and "*pp" must not be NULL.
- * Upon success, "*pp" will point to after the last bytes read, and a stack
- * will be returned.
- * Upon failure, a NULL pointer will be returned, and the position of "*pp" is
- * not defined.
- */
-STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp,
- long len);
-
-/*
- * Serialize (to TLS format) an |sct| and write it to |out|.
- * If |out| is null, no SCT will be output but the length will still be returned.
- * If |out| points to a null pointer, a string will be allocated to hold the
- * TLS-format SCT. It is the responsibility of the caller to free it.
- * If |out| points to an allocated string, the TLS-format SCT will be written
- * to it.
- * The length of the SCT in TLS format will be returned.
- */
-__owur int i2o_SCT(const SCT *sct, unsigned char **out);
-
-/*
- * Parses an SCT in TLS format and returns it.
- * If |psct| is not null, it will end up pointing to the parsed SCT. If it
- * already points to a non-null pointer, the pointer will be free'd.
- * |in| should be a pointer to a string containing the TLS-format SCT.
- * |in| will be advanced to the end of the SCT if parsing succeeds.
- * |len| should be the length of the SCT in |in|.
- * Returns NULL if an error occurs.
- * If the SCT is an unsupported version, only the SCT's 'sct' and 'sct_len'
- * fields will be populated (with |in| and |len| respectively).
- */
-SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len);
-
-/********************
- * CT log functions *
- ********************/
-
-/*
- * Creates a new CT log instance with the given |public_key| and |name|.
- * Takes ownership of |public_key| but copies |name|.
- * Returns NULL if malloc fails or if |public_key| cannot be converted to DER.
- * Should be deleted by the caller using CTLOG_free when no longer needed.
- */
-CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name);
-
-/*
- * Creates a new CTLOG instance with the base64-encoded SubjectPublicKeyInfo DER
- * in |pkey_base64|. The |name| is a string to help users identify this log.
- * Returns 1 on success, 0 on failure.
- * Should be deleted by the caller using CTLOG_free when no longer needed.
- */
-int CTLOG_new_from_base64(CTLOG ** ct_log,
- const char *pkey_base64, const char *name);
-
-/*
- * Deletes a CT log instance and its fields.
- */
-void CTLOG_free(CTLOG *log);
-
-/* Gets the name of the CT log */
-const char *CTLOG_get0_name(const CTLOG *log);
-/* Gets the ID of the CT log */
-void CTLOG_get0_log_id(const CTLOG *log, const uint8_t **log_id,
- size_t *log_id_len);
-/* Gets the public key of the CT log */
-EVP_PKEY *CTLOG_get0_public_key(const CTLOG *log);
-
-/**************************
- * CT log store functions *
- **************************/
-
-/*
- * Creates a new CT log store.
- * Should be deleted by the caller using CTLOG_STORE_free when no longer needed.
- */
-CTLOG_STORE *CTLOG_STORE_new(void);
-
-/*
- * Deletes a CT log store and all of the CT log instances held within.
- */
-void CTLOG_STORE_free(CTLOG_STORE *store);
-
-/*
- * Finds a CT log in the store based on its log ID.
- * Returns the CT log, or NULL if no match is found.
- */
-const CTLOG *CTLOG_STORE_get0_log_by_id(const CTLOG_STORE *store,
- const uint8_t *log_id,
- size_t log_id_len);
-
-/*
- * Loads a CT log list into a |store| from a |file|.
- * Returns 1 if loading is successful, or 0 otherwise.
- */
-__owur int CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file);
-
-/*
- * Loads the default CT log list into a |store|.
- * Returns 1 if loading is successful, or 0 otherwise.
- */
-__owur int CTLOG_STORE_load_default_file(CTLOG_STORE *store);
-
-# ifdef __cplusplus
-}
-# endif
-# endif
-#endif
diff --git a/include/openssl/ct.h.in b/include/openssl/ct.h.in
new file mode 100644
index 000000000000..16086b33bd45
--- /dev/null
+++ b/include/openssl/ct.h.in
@@ -0,0 +1,525 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_CT_H
+# define OPENSSL_CT_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_CT_H
+# endif
+
+# include <openssl/opensslconf.h>
+
+# ifndef OPENSSL_NO_CT
+# include <openssl/types.h>
+# include <openssl/safestack.h>
+# include <openssl/x509.h>
+# include <openssl/cterr.h>
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+
+/* Minimum RSA key size, from RFC6962 */
+# define SCT_MIN_RSA_BITS 2048
+
+/* All hashes are SHA256 in v1 of Certificate Transparency */
+# define CT_V1_HASHLEN SHA256_DIGEST_LENGTH
+
+{-
+ generate_stack_macros("SCT")
+ .generate_stack_macros("CTLOG");
+-}
+
+
+typedef enum {
+ CT_LOG_ENTRY_TYPE_NOT_SET = -1,
+ CT_LOG_ENTRY_TYPE_X509 = 0,
+ CT_LOG_ENTRY_TYPE_PRECERT = 1
+} ct_log_entry_type_t;
+
+typedef enum {
+ SCT_VERSION_NOT_SET = -1,
+ SCT_VERSION_V1 = 0
+} sct_version_t;
+
+typedef enum {
+ SCT_SOURCE_UNKNOWN,
+ SCT_SOURCE_TLS_EXTENSION,
+ SCT_SOURCE_X509V3_EXTENSION,
+ SCT_SOURCE_OCSP_STAPLED_RESPONSE
+} sct_source_t;
+
+typedef enum {
+ SCT_VALIDATION_STATUS_NOT_SET,
+ SCT_VALIDATION_STATUS_UNKNOWN_LOG,
+ SCT_VALIDATION_STATUS_VALID,
+ SCT_VALIDATION_STATUS_INVALID,
+ SCT_VALIDATION_STATUS_UNVERIFIED,
+ SCT_VALIDATION_STATUS_UNKNOWN_VERSION
+} sct_validation_status_t;
+
+/******************************************
+ * CT policy evaluation context functions *
+ ******************************************/
+
+/*
+ * Creates a new, empty policy evaluation context associated with the given
+ * library context and property query string.
+ * The caller is responsible for calling CT_POLICY_EVAL_CTX_free when finished
+ * with the CT_POLICY_EVAL_CTX.
+ */
+CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new_ex(OSSL_LIB_CTX *libctx,
+ const char *propq);
+
+/*
+ * The same as CT_POLICY_EVAL_CTX_new_ex() but the default library
+ * context and property query string is used.
+ */
+CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void);
+
+/* Deletes a policy evaluation context and anything it owns. */
+void CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx);
+
+/* Gets the peer certificate that the SCTs are for */
+X509* CT_POLICY_EVAL_CTX_get0_cert(const CT_POLICY_EVAL_CTX *ctx);
+
+/*
+ * Sets the certificate associated with the received SCTs.
+ * Increments the reference count of cert.
+ * Returns 1 on success, 0 otherwise.
+ */
+int CT_POLICY_EVAL_CTX_set1_cert(CT_POLICY_EVAL_CTX *ctx, X509 *cert);
+
+/* Gets the issuer of the aforementioned certificate */
+X509* CT_POLICY_EVAL_CTX_get0_issuer(const CT_POLICY_EVAL_CTX *ctx);
+
+/*
+ * Sets the issuer of the certificate associated with the received SCTs.
+ * Increments the reference count of issuer.
+ * Returns 1 on success, 0 otherwise.
+ */
+int CT_POLICY_EVAL_CTX_set1_issuer(CT_POLICY_EVAL_CTX *ctx, X509 *issuer);
+
+/* Gets the CT logs that are trusted sources of SCTs */
+const CTLOG_STORE *CT_POLICY_EVAL_CTX_get0_log_store(const CT_POLICY_EVAL_CTX *ctx);
+
+/* Sets the log store that is in use. It must outlive the CT_POLICY_EVAL_CTX. */
+void CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(CT_POLICY_EVAL_CTX *ctx,
+ CTLOG_STORE *log_store);
+
+/*
+ * Gets the time, in milliseconds since the Unix epoch, that will be used as the
+ * current time when checking whether an SCT was issued in the future.
+ * Such SCTs will fail validation, as required by RFC6962.
+ */
+uint64_t CT_POLICY_EVAL_CTX_get_time(const CT_POLICY_EVAL_CTX *ctx);
+
+/*
+ * Sets the time to evaluate SCTs against, in milliseconds since the Unix epoch.
+ * If an SCT's timestamp is after this time, it will be interpreted as having
+ * been issued in the future. RFC6962 states that "TLS clients MUST reject SCTs
+ * whose timestamp is in the future", so an SCT will not validate in this case.
+ */
+void CT_POLICY_EVAL_CTX_set_time(CT_POLICY_EVAL_CTX *ctx, uint64_t time_in_ms);
+
+/*****************
+ * SCT functions *
+ *****************/
+
+/*
+ * Creates a new, blank SCT.
+ * The caller is responsible for calling SCT_free when finished with the SCT.
+ */
+SCT *SCT_new(void);
+
+/*
+ * Creates a new SCT from some base64-encoded strings.
+ * The caller is responsible for calling SCT_free when finished with the SCT.
+ */
+SCT *SCT_new_from_base64(unsigned char version,
+ const char *logid_base64,
+ ct_log_entry_type_t entry_type,
+ uint64_t timestamp,
+ const char *extensions_base64,
+ const char *signature_base64);
+
+/*
+ * Frees the SCT and the underlying data structures.
+ */
+void SCT_free(SCT *sct);
+
+/*
+ * Free a stack of SCTs, and the underlying SCTs themselves.
+ * Intended to be compatible with X509V3_EXT_FREE.
+ */
+void SCT_LIST_free(STACK_OF(SCT) *a);
+
+/*
+ * Returns the version of the SCT.
+ */
+sct_version_t SCT_get_version(const SCT *sct);
+
+/*
+ * Set the version of an SCT.
+ * Returns 1 on success, 0 if the version is unrecognized.
+ */
+__owur int SCT_set_version(SCT *sct, sct_version_t version);
+
+/*
+ * Returns the log entry type of the SCT.
+ */
+ct_log_entry_type_t SCT_get_log_entry_type(const SCT *sct);
+
+/*
+ * Set the log entry type of an SCT.
+ * Returns 1 on success, 0 otherwise.
+ */
+__owur int SCT_set_log_entry_type(SCT *sct, ct_log_entry_type_t entry_type);
+
+/*
+ * Gets the ID of the log that an SCT came from.
+ * Ownership of the log ID remains with the SCT.
+ * Returns the length of the log ID.
+ */
+size_t SCT_get0_log_id(const SCT *sct, unsigned char **log_id);
+
+/*
+ * Set the log ID of an SCT to point directly to the *log_id specified.
+ * The SCT takes ownership of the specified pointer.
+ * Returns 1 on success, 0 otherwise.
+ */
+__owur int SCT_set0_log_id(SCT *sct, unsigned char *log_id, size_t log_id_len);
+
+/*
+ * Set the log ID of an SCT.
+ * This makes a copy of the log_id.
+ * Returns 1 on success, 0 otherwise.
+ */
+__owur int SCT_set1_log_id(SCT *sct, const unsigned char *log_id,
+ size_t log_id_len);
+
+/*
+ * Returns the timestamp for the SCT (epoch time in milliseconds).
+ */
+uint64_t SCT_get_timestamp(const SCT *sct);
+
+/*
+ * Set the timestamp of an SCT (epoch time in milliseconds).
+ */
+void SCT_set_timestamp(SCT *sct, uint64_t timestamp);
+
+/*
+ * Return the NID for the signature used by the SCT.
+ * For CT v1, this will be either NID_sha256WithRSAEncryption or
+ * NID_ecdsa_with_SHA256 (or NID_undef if incorrect/unset).
+ */
+int SCT_get_signature_nid(const SCT *sct);
+
+/*
+ * Set the signature type of an SCT
+ * For CT v1, this should be either NID_sha256WithRSAEncryption or
+ * NID_ecdsa_with_SHA256.
+ * Returns 1 on success, 0 otherwise.
+ */
+__owur int SCT_set_signature_nid(SCT *sct, int nid);
+
+/*
+ * Set *ext to point to the extension data for the SCT. ext must not be NULL.
+ * The SCT retains ownership of this pointer.
+ * Returns length of the data pointed to.
+ */
+size_t SCT_get0_extensions(const SCT *sct, unsigned char **ext);
+
+/*
+ * Set the extensions of an SCT to point directly to the *ext specified.
+ * The SCT takes ownership of the specified pointer.
+ */
+void SCT_set0_extensions(SCT *sct, unsigned char *ext, size_t ext_len);
+
+/*
+ * Set the extensions of an SCT.
+ * This takes a copy of the ext.
+ * Returns 1 on success, 0 otherwise.
+ */
+__owur int SCT_set1_extensions(SCT *sct, const unsigned char *ext,
+ size_t ext_len);
+
+/*
+ * Set *sig to point to the signature for the SCT. sig must not be NULL.
+ * The SCT retains ownership of this pointer.
+ * Returns length of the data pointed to.
+ */
+size_t SCT_get0_signature(const SCT *sct, unsigned char **sig);
+
+/*
+ * Set the signature of an SCT to point directly to the *sig specified.
+ * The SCT takes ownership of the specified pointer.
+ */
+void SCT_set0_signature(SCT *sct, unsigned char *sig, size_t sig_len);
+
+/*
+ * Set the signature of an SCT to be a copy of the *sig specified.
+ * Returns 1 on success, 0 otherwise.
+ */
+__owur int SCT_set1_signature(SCT *sct, const unsigned char *sig,
+ size_t sig_len);
+
+/*
+ * The origin of this SCT, e.g. TLS extension, OCSP response, etc.
+ */
+sct_source_t SCT_get_source(const SCT *sct);
+
+/*
+ * Set the origin of this SCT, e.g. TLS extension, OCSP response, etc.
+ * Returns 1 on success, 0 otherwise.
+ */
+__owur int SCT_set_source(SCT *sct, sct_source_t source);
+
+/*
+ * Returns a text string describing the validation status of |sct|.
+ */
+const char *SCT_validation_status_string(const SCT *sct);
+
+/*
+ * Pretty-prints an |sct| to |out|.
+ * It will be indented by the number of spaces specified by |indent|.
+ * If |logs| is not NULL, it will be used to lookup the CT log that the SCT came
+ * from, so that the log name can be printed.
+ */
+void SCT_print(const SCT *sct, BIO *out, int indent, const CTLOG_STORE *logs);
+
+/*
+ * Pretty-prints an |sct_list| to |out|.
+ * It will be indented by the number of spaces specified by |indent|.
+ * SCTs will be delimited by |separator|.
+ * If |logs| is not NULL, it will be used to lookup the CT log that each SCT
+ * came from, so that the log names can be printed.
+ */
+void SCT_LIST_print(const STACK_OF(SCT) *sct_list, BIO *out, int indent,
+ const char *separator, const CTLOG_STORE *logs);
+
+/*
+ * Gets the last result of validating this SCT.
+ * If it has not been validated yet, returns SCT_VALIDATION_STATUS_NOT_SET.
+ */
+sct_validation_status_t SCT_get_validation_status(const SCT *sct);
+
+/*
+ * Validates the given SCT with the provided context.
+ * Sets the "validation_status" field of the SCT.
+ * Returns 1 if the SCT is valid and the signature verifies.
+ * Returns 0 if the SCT is invalid or could not be verified.
+ * Returns -1 if an error occurs.
+ */
+__owur int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx);
+
+/*
+ * Validates the given list of SCTs with the provided context.
+ * Sets the "validation_status" field of each SCT.
+ * Returns 1 if there are no invalid SCTs and all signatures verify.
+ * Returns 0 if at least one SCT is invalid or could not be verified.
+ * Returns a negative integer if an error occurs.
+ */
+__owur int SCT_LIST_validate(const STACK_OF(SCT) *scts,
+ CT_POLICY_EVAL_CTX *ctx);
+
+
+/*********************************
+ * SCT parsing and serialization *
+ *********************************/
+
+/*
+ * Serialize (to TLS format) a stack of SCTs and return the length.
+ * "a" must not be NULL.
+ * If "pp" is NULL, just return the length of what would have been serialized.
+ * If "pp" is not NULL and "*pp" is null, function will allocate a new pointer
+ * for data that caller is responsible for freeing (only if function returns
+ * successfully).
+ * If "pp" is NULL and "*pp" is not NULL, caller is responsible for ensuring
+ * that "*pp" is large enough to accept all of the serialized data.
+ * Returns < 0 on error, >= 0 indicating bytes written (or would have been)
+ * on success.
+ */
+__owur int i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp);
+
+/*
+ * Convert TLS format SCT list to a stack of SCTs.
+ * If "a" or "*a" is NULL, a new stack will be created that the caller is
+ * responsible for freeing (by calling SCT_LIST_free).
+ * "**pp" and "*pp" must not be NULL.
+ * Upon success, "*pp" will point to after the last bytes read, and a stack
+ * will be returned.
+ * Upon failure, a NULL pointer will be returned, and the position of "*pp" is
+ * not defined.
+ */
+STACK_OF(SCT) *o2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp,
+ size_t len);
+
+/*
+ * Serialize (to DER format) a stack of SCTs and return the length.
+ * "a" must not be NULL.
+ * If "pp" is NULL, just returns the length of what would have been serialized.
+ * If "pp" is not NULL and "*pp" is null, function will allocate a new pointer
+ * for data that caller is responsible for freeing (only if function returns
+ * successfully).
+ * If "pp" is NULL and "*pp" is not NULL, caller is responsible for ensuring
+ * that "*pp" is large enough to accept all of the serialized data.
+ * Returns < 0 on error, >= 0 indicating bytes written (or would have been)
+ * on success.
+ */
+__owur int i2d_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp);
+
+/*
+ * Parses an SCT list in DER format and returns it.
+ * If "a" or "*a" is NULL, a new stack will be created that the caller is
+ * responsible for freeing (by calling SCT_LIST_free).
+ * "**pp" and "*pp" must not be NULL.
+ * Upon success, "*pp" will point to after the last bytes read, and a stack
+ * will be returned.
+ * Upon failure, a NULL pointer will be returned, and the position of "*pp" is
+ * not defined.
+ */
+STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp,
+ long len);
+
+/*
+ * Serialize (to TLS format) an |sct| and write it to |out|.
+ * If |out| is null, no SCT will be output but the length will still be returned.
+ * If |out| points to a null pointer, a string will be allocated to hold the
+ * TLS-format SCT. It is the responsibility of the caller to free it.
+ * If |out| points to an allocated string, the TLS-format SCT will be written
+ * to it.
+ * The length of the SCT in TLS format will be returned.
+ */
+__owur int i2o_SCT(const SCT *sct, unsigned char **out);
+
+/*
+ * Parses an SCT in TLS format and returns it.
+ * If |psct| is not null, it will end up pointing to the parsed SCT. If it
+ * already points to a non-null pointer, the pointer will be free'd.
+ * |in| should be a pointer to a string containing the TLS-format SCT.
+ * |in| will be advanced to the end of the SCT if parsing succeeds.
+ * |len| should be the length of the SCT in |in|.
+ * Returns NULL if an error occurs.
+ * If the SCT is an unsupported version, only the SCT's 'sct' and 'sct_len'
+ * fields will be populated (with |in| and |len| respectively).
+ */
+SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len);
+
+/********************
+ * CT log functions *
+ ********************/
+
+/*
+ * Creates a new CT log instance with the given |public_key| and |name| and
+ * associates it with the give library context |libctx| and property query
+ * string |propq|.
+ * Takes ownership of |public_key| but copies |name|.
+ * Returns NULL if malloc fails or if |public_key| cannot be converted to DER.
+ * Should be deleted by the caller using CTLOG_free when no longer needed.
+ */
+CTLOG *CTLOG_new_ex(EVP_PKEY *public_key, const char *name, OSSL_LIB_CTX *libctx,
+ const char *propq);
+
+/*
+ * The same as CTLOG_new_ex except that the default library context and
+ * property query string are used.
+ */
+CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name);
+
+/*
+ * Creates a new CTLOG instance with the base64-encoded SubjectPublicKeyInfo DER
+ * in |pkey_base64| and associated with the given library context |libctx| and
+ * property query string |propq|. The |name| is a string to help users identify
+ * this log.
+ * Returns 1 on success, 0 on failure.
+ * Should be deleted by the caller using CTLOG_free when no longer needed.
+ */
+int CTLOG_new_from_base64_ex(CTLOG **ct_log, const char *pkey_base64,
+ const char *name, OSSL_LIB_CTX *libctx,
+ const char *propq);
+
+/*
+ * The same as CTLOG_new_from_base64_ex() except that the default
+ * library context and property query string are used.
+ * Returns 1 on success, 0 on failure.
+ */
+int CTLOG_new_from_base64(CTLOG ** ct_log,
+ const char *pkey_base64, const char *name);
+
+/*
+ * Deletes a CT log instance and its fields.
+ */
+void CTLOG_free(CTLOG *log);
+
+/* Gets the name of the CT log */
+const char *CTLOG_get0_name(const CTLOG *log);
+/* Gets the ID of the CT log */
+void CTLOG_get0_log_id(const CTLOG *log, const uint8_t **log_id,
+ size_t *log_id_len);
+/* Gets the public key of the CT log */
+EVP_PKEY *CTLOG_get0_public_key(const CTLOG *log);
+
+/**************************
+ * CT log store functions *
+ **************************/
+
+/*
+ * Creates a new CT log store and associates it with the given libctx and
+ * property query string.
+ * Should be deleted by the caller using CTLOG_STORE_free when no longer needed.
+ */
+CTLOG_STORE *CTLOG_STORE_new_ex(OSSL_LIB_CTX *libctx, const char *propq);
+
+/*
+ * Same as CTLOG_STORE_new_ex except that the default libctx and
+ * property query string are used.
+ * Should be deleted by the caller using CTLOG_STORE_free when no longer needed.
+ */
+CTLOG_STORE *CTLOG_STORE_new(void);
+
+/*
+ * Deletes a CT log store and all of the CT log instances held within.
+ */
+void CTLOG_STORE_free(CTLOG_STORE *store);
+
+/*
+ * Finds a CT log in the store based on its log ID.
+ * Returns the CT log, or NULL if no match is found.
+ */
+const CTLOG *CTLOG_STORE_get0_log_by_id(const CTLOG_STORE *store,
+ const uint8_t *log_id,
+ size_t log_id_len);
+
+/*
+ * Loads a CT log list into a |store| from a |file|.
+ * Returns 1 if loading is successful, or 0 otherwise.
+ */
+__owur int CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file);
+
+/*
+ * Loads the default CT log list into a |store|.
+ * Returns 1 if loading is successful, or 0 otherwise.
+ */
+__owur int CTLOG_STORE_load_default_file(CTLOG_STORE *store);
+
+# ifdef __cplusplus
+}
+# endif
+# endif
+#endif
diff --git a/include/openssl/cterr.h b/include/openssl/cterr.h
index feb7bc56632f..935d32d8b144 100644
--- a/include/openssl/cterr.h
+++ b/include/openssl/cterr.h
@@ -1,59 +1,24 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_CTERR_H
-# define HEADER_CTERR_H
-
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+#ifndef OPENSSL_CTERR_H
+# define OPENSSL_CTERR_H
+# pragma once
# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifndef OPENSSL_NO_CT
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_CT_strings(void);
+# ifndef OPENSSL_NO_CT
-/*
- * CT function codes.
- */
-# define CT_F_CTLOG_NEW 117
-# define CT_F_CTLOG_NEW_FROM_BASE64 118
-# define CT_F_CTLOG_NEW_FROM_CONF 119
-# define CT_F_CTLOG_STORE_LOAD_CTX_NEW 122
-# define CT_F_CTLOG_STORE_LOAD_FILE 123
-# define CT_F_CTLOG_STORE_LOAD_LOG 130
-# define CT_F_CTLOG_STORE_NEW 131
-# define CT_F_CT_BASE64_DECODE 124
-# define CT_F_CT_POLICY_EVAL_CTX_NEW 133
-# define CT_F_CT_V1_LOG_ID_FROM_PKEY 125
-# define CT_F_I2O_SCT 107
-# define CT_F_I2O_SCT_LIST 108
-# define CT_F_I2O_SCT_SIGNATURE 109
-# define CT_F_O2I_SCT 110
-# define CT_F_O2I_SCT_LIST 111
-# define CT_F_O2I_SCT_SIGNATURE 112
-# define CT_F_SCT_CTX_NEW 126
-# define CT_F_SCT_CTX_VERIFY 128
-# define CT_F_SCT_NEW 100
-# define CT_F_SCT_NEW_FROM_BASE64 127
-# define CT_F_SCT_SET0_LOG_ID 101
-# define CT_F_SCT_SET1_EXTENSIONS 114
-# define CT_F_SCT_SET1_LOG_ID 115
-# define CT_F_SCT_SET1_SIGNATURE 116
-# define CT_F_SCT_SET_LOG_ENTRY_TYPE 102
-# define CT_F_SCT_SET_SIGNATURE_NID 103
-# define CT_F_SCT_SET_VERSION 104
/*
* CT reason codes.
diff --git a/include/openssl/decoder.h b/include/openssl/decoder.h
new file mode 100644
index 000000000000..d4ee2cf41340
--- /dev/null
+++ b/include/openssl/decoder.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_DECODER_H
+# define OPENSSL_DECODER_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+
+# ifndef OPENSSL_NO_STDIO
+# include <stdio.h>
+# endif
+# include <stdarg.h>
+# include <stddef.h>
+# include <openssl/decodererr.h>
+# include <openssl/types.h>
+# include <openssl/core.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+OSSL_DECODER *OSSL_DECODER_fetch(OSSL_LIB_CTX *libctx, const char *name,
+ const char *properties);
+int OSSL_DECODER_up_ref(OSSL_DECODER *encoder);
+void OSSL_DECODER_free(OSSL_DECODER *encoder);
+
+const OSSL_PROVIDER *OSSL_DECODER_get0_provider(const OSSL_DECODER *encoder);
+const char *OSSL_DECODER_get0_properties(const OSSL_DECODER *encoder);
+const char *OSSL_DECODER_get0_name(const OSSL_DECODER *decoder);
+const char *OSSL_DECODER_get0_description(const OSSL_DECODER *decoder);
+int OSSL_DECODER_is_a(const OSSL_DECODER *encoder, const char *name);
+
+void OSSL_DECODER_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(OSSL_DECODER *encoder, void *arg),
+ void *arg);
+int OSSL_DECODER_names_do_all(const OSSL_DECODER *encoder,
+ void (*fn)(const char *name, void *data),
+ void *data);
+const OSSL_PARAM *OSSL_DECODER_gettable_params(OSSL_DECODER *decoder);
+int OSSL_DECODER_get_params(OSSL_DECODER *decoder, OSSL_PARAM params[]);
+
+const OSSL_PARAM *OSSL_DECODER_settable_ctx_params(OSSL_DECODER *encoder);
+OSSL_DECODER_CTX *OSSL_DECODER_CTX_new(void);
+int OSSL_DECODER_CTX_set_params(OSSL_DECODER_CTX *ctx,
+ const OSSL_PARAM params[]);
+void OSSL_DECODER_CTX_free(OSSL_DECODER_CTX *ctx);
+
+/* Utilities that help set specific parameters */
+int OSSL_DECODER_CTX_set_passphrase(OSSL_DECODER_CTX *ctx,
+ const unsigned char *kstr, size_t klen);
+int OSSL_DECODER_CTX_set_pem_password_cb(OSSL_DECODER_CTX *ctx,
+ pem_password_cb *cb, void *cbarg);
+int OSSL_DECODER_CTX_set_passphrase_cb(OSSL_DECODER_CTX *ctx,
+ OSSL_PASSPHRASE_CALLBACK *cb,
+ void *cbarg);
+int OSSL_DECODER_CTX_set_passphrase_ui(OSSL_DECODER_CTX *ctx,
+ const UI_METHOD *ui_method,
+ void *ui_data);
+
+/*
+ * Utilities to read the object to decode, with the result sent to cb.
+ * These will discover all provided methods
+ */
+
+int OSSL_DECODER_CTX_set_selection(OSSL_DECODER_CTX *ctx, int selection);
+int OSSL_DECODER_CTX_set_input_type(OSSL_DECODER_CTX *ctx,
+ const char *input_type);
+int OSSL_DECODER_CTX_set_input_structure(OSSL_DECODER_CTX *ctx,
+ const char *input_structure);
+int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder);
+int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int OSSL_DECODER_CTX_get_num_decoders(OSSL_DECODER_CTX *ctx);
+
+typedef struct ossl_decoder_instance_st OSSL_DECODER_INSTANCE;
+OSSL_DECODER *
+OSSL_DECODER_INSTANCE_get_decoder(OSSL_DECODER_INSTANCE *decoder_inst);
+void *
+OSSL_DECODER_INSTANCE_get_decoder_ctx(OSSL_DECODER_INSTANCE *decoder_inst);
+const char *
+OSSL_DECODER_INSTANCE_get_input_type(OSSL_DECODER_INSTANCE *decoder_inst);
+const char *
+OSSL_DECODER_INSTANCE_get_input_structure(OSSL_DECODER_INSTANCE *decoder_inst,
+ int *was_set);
+
+typedef int OSSL_DECODER_CONSTRUCT(OSSL_DECODER_INSTANCE *decoder_inst,
+ const OSSL_PARAM *params,
+ void *construct_data);
+typedef void OSSL_DECODER_CLEANUP(void *construct_data);
+
+int OSSL_DECODER_CTX_set_construct(OSSL_DECODER_CTX *ctx,
+ OSSL_DECODER_CONSTRUCT *construct);
+int OSSL_DECODER_CTX_set_construct_data(OSSL_DECODER_CTX *ctx,
+ void *construct_data);
+int OSSL_DECODER_CTX_set_cleanup(OSSL_DECODER_CTX *ctx,
+ OSSL_DECODER_CLEANUP *cleanup);
+OSSL_DECODER_CONSTRUCT *OSSL_DECODER_CTX_get_construct(OSSL_DECODER_CTX *ctx);
+void *OSSL_DECODER_CTX_get_construct_data(OSSL_DECODER_CTX *ctx);
+OSSL_DECODER_CLEANUP *OSSL_DECODER_CTX_get_cleanup(OSSL_DECODER_CTX *ctx);
+
+int OSSL_DECODER_export(OSSL_DECODER_INSTANCE *decoder_inst,
+ void *reference, size_t reference_sz,
+ OSSL_CALLBACK *export_cb, void *export_cbarg);
+
+int OSSL_DECODER_from_bio(OSSL_DECODER_CTX *ctx, BIO *in);
+#ifndef OPENSSL_NO_STDIO
+int OSSL_DECODER_from_fp(OSSL_DECODER_CTX *ctx, FILE *in);
+#endif
+int OSSL_DECODER_from_data(OSSL_DECODER_CTX *ctx, const unsigned char **pdata,
+ size_t *pdata_len);
+
+/*
+ * Create the OSSL_DECODER_CTX with an associated type. This will perform
+ * an implicit OSSL_DECODER_fetch(), suitable for the object of that type.
+ */
+OSSL_DECODER_CTX *
+OSSL_DECODER_CTX_new_for_pkey(EVP_PKEY **pkey,
+ const char *input_type,
+ const char *input_struct,
+ const char *keytype, int selection,
+ OSSL_LIB_CTX *libctx, const char *propquery);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/decodererr.h b/include/openssl/decodererr.h
new file mode 100644
index 000000000000..4212a38bca2a
--- /dev/null
+++ b/include/openssl/decodererr.h
@@ -0,0 +1,28 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_DECODERERR_H
+# define OPENSSL_DECODERERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
+
+
+
+/*
+ * OSSL_DECODER reason codes.
+ */
+# define OSSL_DECODER_R_COULD_NOT_DECODE_OBJECT 101
+# define OSSL_DECODER_R_DECODER_NOT_FOUND 102
+# define OSSL_DECODER_R_MISSING_GET_PARAMS 100
+
+#endif
diff --git a/include/openssl/des.h b/include/openssl/des.h
index be4abbdfd0e6..09798a616ffb 100644
--- a/include/openssl/des.h
+++ b/include/openssl/des.h
@@ -1,29 +1,36 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_DES_H
-# define HEADER_DES_H
+#ifndef OPENSSL_DES_H
+# define OPENSSL_DES_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_DES_H
+# endif
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_DES
-# ifdef __cplusplus
+# ifdef __cplusplus
extern "C" {
-# endif
-# include <openssl/e_os2.h>
+# endif
+# include <openssl/e_os2.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
typedef unsigned int DES_LONG;
-# ifdef OPENSSL_BUILD_SHLIBCRYPTO
-# undef OPENSSL_EXTERN
-# define OPENSSL_EXTERN OPENSSL_EXPORT
-# endif
+# ifdef OPENSSL_BUILD_SHLIBCRYPTO
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+# endif
typedef unsigned char DES_cblock[8];
typedef /* const */ unsigned char const_DES_cblock[8];
@@ -42,53 +49,62 @@ typedef struct DES_ks {
} ks[16];
} DES_key_schedule;
-# define DES_KEY_SZ (sizeof(DES_cblock))
-# define DES_SCHEDULE_SZ (sizeof(DES_key_schedule))
+# define DES_KEY_SZ (sizeof(DES_cblock))
+# define DES_SCHEDULE_SZ (sizeof(DES_key_schedule))
-# define DES_ENCRYPT 1
-# define DES_DECRYPT 0
+# define DES_ENCRYPT 1
+# define DES_DECRYPT 0
-# define DES_CBC_MODE 0
-# define DES_PCBC_MODE 1
+# define DES_CBC_MODE 0
+# define DES_PCBC_MODE 1
-# define DES_ecb2_encrypt(i,o,k1,k2,e) \
+# define DES_ecb2_encrypt(i,o,k1,k2,e) \
DES_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e))
-# define DES_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \
+# define DES_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \
DES_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e))
-# define DES_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \
+# define DES_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \
DES_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e))
-# define DES_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \
+# define DES_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \
DES_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n))
-OPENSSL_DECLARE_GLOBAL(int, DES_check_key); /* defaults to false */
-# define DES_check_key OPENSSL_GLOBAL_REF(DES_check_key)
-
-const char *DES_options(void);
+# define DES_fixup_key_parity DES_set_odd_parity
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 const char *DES_options(void);
+OSSL_DEPRECATEDIN_3_0
void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output,
DES_key_schedule *ks1, DES_key_schedule *ks2,
DES_key_schedule *ks3, int enc);
+OSSL_DEPRECATEDIN_3_0
DES_LONG DES_cbc_cksum(const unsigned char *input, DES_cblock *output,
long length, DES_key_schedule *schedule,
const_DES_cblock *ivec);
+# endif
/* DES_cbc_encrypt does not update the IV! Use DES_ncbc_encrypt instead. */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
void DES_cbc_encrypt(const unsigned char *input, unsigned char *output,
- long length, DES_key_schedule *schedule,
- DES_cblock *ivec, int enc);
+ long length, DES_key_schedule *schedule, DES_cblock *ivec,
+ int enc);
+OSSL_DEPRECATEDIN_3_0
void DES_ncbc_encrypt(const unsigned char *input, unsigned char *output,
- long length, DES_key_schedule *schedule,
- DES_cblock *ivec, int enc);
+ long length, DES_key_schedule *schedule, DES_cblock *ivec,
+ int enc);
+OSSL_DEPRECATEDIN_3_0
void DES_xcbc_encrypt(const unsigned char *input, unsigned char *output,
- long length, DES_key_schedule *schedule,
- DES_cblock *ivec, const_DES_cblock *inw,
- const_DES_cblock *outw, int enc);
+ long length, DES_key_schedule *schedule, DES_cblock *ivec,
+ const_DES_cblock *inw, const_DES_cblock *outw, int enc);
+OSSL_DEPRECATEDIN_3_0
void DES_cfb_encrypt(const unsigned char *in, unsigned char *out, int numbits,
- long length, DES_key_schedule *schedule,
- DES_cblock *ivec, int enc);
+ long length, DES_key_schedule *schedule, DES_cblock *ivec,
+ int enc);
+OSSL_DEPRECATEDIN_3_0
void DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output,
DES_key_schedule *ks, int enc);
+# endif
/*
* This is the DES encryption function that gets called by just about every
@@ -100,7 +116,10 @@ void DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output,
* long's and ks is the DES_key_schedule to use. enc, is non zero specifies
* encryption, zero if decryption.
*/
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
void DES_encrypt1(DES_LONG *data, DES_key_schedule *ks, int enc);
+# endif
/*
* This functions is the same as DES_encrypt1() except that the DES initial
@@ -110,65 +129,83 @@ void DES_encrypt1(DES_LONG *data, DES_key_schedule *ks, int enc);
* DES_encrypt2() DES_encrypt2() FP() is the same as DES_encrypt1()
* DES_encrypt1() DES_encrypt1() except faster :-).
*/
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
void DES_encrypt2(DES_LONG *data, DES_key_schedule *ks, int enc);
-
-void DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1,
- DES_key_schedule *ks2, DES_key_schedule *ks3);
-void DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1,
- DES_key_schedule *ks2, DES_key_schedule *ks3);
+OSSL_DEPRECATEDIN_3_0
+void DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1, DES_key_schedule *ks2,
+ DES_key_schedule *ks3);
+OSSL_DEPRECATEDIN_3_0
+void DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1, DES_key_schedule *ks2,
+ DES_key_schedule *ks3);
+OSSL_DEPRECATEDIN_3_0
void DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output,
- long length,
- DES_key_schedule *ks1, DES_key_schedule *ks2,
- DES_key_schedule *ks3, DES_cblock *ivec, int enc);
+ long length, DES_key_schedule *ks1,
+ DES_key_schedule *ks2, DES_key_schedule *ks3,
+ DES_cblock *ivec, int enc);
+OSSL_DEPRECATEDIN_3_0
void DES_ede3_cfb64_encrypt(const unsigned char *in, unsigned char *out,
long length, DES_key_schedule *ks1,
DES_key_schedule *ks2, DES_key_schedule *ks3,
DES_cblock *ivec, int *num, int enc);
+OSSL_DEPRECATEDIN_3_0
void DES_ede3_cfb_encrypt(const unsigned char *in, unsigned char *out,
int numbits, long length, DES_key_schedule *ks1,
DES_key_schedule *ks2, DES_key_schedule *ks3,
DES_cblock *ivec, int enc);
+OSSL_DEPRECATEDIN_3_0
void DES_ede3_ofb64_encrypt(const unsigned char *in, unsigned char *out,
long length, DES_key_schedule *ks1,
DES_key_schedule *ks2, DES_key_schedule *ks3,
DES_cblock *ivec, int *num);
+OSSL_DEPRECATEDIN_3_0
char *DES_fcrypt(const char *buf, const char *salt, char *ret);
+OSSL_DEPRECATEDIN_3_0
char *DES_crypt(const char *buf, const char *salt);
+OSSL_DEPRECATEDIN_3_0
void DES_ofb_encrypt(const unsigned char *in, unsigned char *out, int numbits,
- long length, DES_key_schedule *schedule,
- DES_cblock *ivec);
+ long length, DES_key_schedule *schedule, DES_cblock *ivec);
+OSSL_DEPRECATEDIN_3_0
void DES_pcbc_encrypt(const unsigned char *input, unsigned char *output,
long length, DES_key_schedule *schedule,
DES_cblock *ivec, int enc);
+OSSL_DEPRECATEDIN_3_0
DES_LONG DES_quad_cksum(const unsigned char *input, DES_cblock output[],
long length, int out_count, DES_cblock *seed);
-int DES_random_key(DES_cblock *ret);
-void DES_set_odd_parity(DES_cblock *key);
-int DES_check_key_parity(const_DES_cblock *key);
-int DES_is_weak_key(const_DES_cblock *key);
+OSSL_DEPRECATEDIN_3_0 int DES_random_key(DES_cblock *ret);
+OSSL_DEPRECATEDIN_3_0 void DES_set_odd_parity(DES_cblock *key);
+OSSL_DEPRECATEDIN_3_0 int DES_check_key_parity(const_DES_cblock *key);
+OSSL_DEPRECATEDIN_3_0 int DES_is_weak_key(const_DES_cblock *key);
+# endif
/*
* DES_set_key (= set_key = DES_key_sched = key_sched) calls
- * DES_set_key_checked if global variable DES_check_key is set,
- * DES_set_key_unchecked otherwise.
+ * DES_set_key_checked
*/
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
int DES_set_key(const_DES_cblock *key, DES_key_schedule *schedule);
+OSSL_DEPRECATEDIN_3_0
int DES_key_sched(const_DES_cblock *key, DES_key_schedule *schedule);
+OSSL_DEPRECATEDIN_3_0
int DES_set_key_checked(const_DES_cblock *key, DES_key_schedule *schedule);
+OSSL_DEPRECATEDIN_3_0
void DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule);
-void DES_string_to_key(const char *str, DES_cblock *key);
+OSSL_DEPRECATEDIN_3_0 void DES_string_to_key(const char *str, DES_cblock *key);
+OSSL_DEPRECATEDIN_3_0
void DES_string_to_2keys(const char *str, DES_cblock *key1, DES_cblock *key2);
+OSSL_DEPRECATEDIN_3_0
void DES_cfb64_encrypt(const unsigned char *in, unsigned char *out,
long length, DES_key_schedule *schedule,
DES_cblock *ivec, int *num, int enc);
+OSSL_DEPRECATEDIN_3_0
void DES_ofb64_encrypt(const unsigned char *in, unsigned char *out,
long length, DES_key_schedule *schedule,
DES_cblock *ivec, int *num);
+# endif
-# define DES_fixup_key_parity DES_set_odd_parity
-
-# ifdef __cplusplus
+# ifdef __cplusplus
}
-# endif
+# endif
# endif
#endif
diff --git a/include/openssl/dh.h b/include/openssl/dh.h
index 3527540cdddb..b97871eca7fa 100644
--- a/include/openssl/dh.h
+++ b/include/openssl/dh.h
@@ -1,46 +1,113 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_DH_H
-# define HEADER_DH_H
+#ifndef OPENSSL_DH_H
+# define OPENSSL_DH_H
+# pragma once
-# include <openssl/opensslconf.h>
-
-# ifndef OPENSSL_NO_DH
-# include <openssl/e_os2.h>
-# include <openssl/bio.h>
-# include <openssl/asn1.h>
-# include <openssl/ossl_typ.h>
-# if OPENSSL_API_COMPAT < 0x10100000L
-# include <openssl/bn.h>
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_DH_H
# endif
-# include <openssl/dherr.h>
+
+# include <openssl/opensslconf.h>
+# include <openssl/types.h>
# ifdef __cplusplus
extern "C" {
# endif
-# ifndef OPENSSL_DH_MAX_MODULUS_BITS
-# define OPENSSL_DH_MAX_MODULUS_BITS 10000
-# endif
+#include <stdlib.h>
+
+/* DH parameter generation types used by EVP_PKEY_CTX_set_dh_paramgen_type() */
+# define DH_PARAMGEN_TYPE_GENERATOR 0 /* Use a safe prime generator */
+# define DH_PARAMGEN_TYPE_FIPS_186_2 1 /* Use FIPS186-2 standard */
+# define DH_PARAMGEN_TYPE_FIPS_186_4 2 /* Use FIPS186-4 standard */
+# define DH_PARAMGEN_TYPE_GROUP 3 /* Use a named safe prime group */
+
+int EVP_PKEY_CTX_set_dh_paramgen_type(EVP_PKEY_CTX *ctx, int typ);
+int EVP_PKEY_CTX_set_dh_paramgen_gindex(EVP_PKEY_CTX *ctx, int gindex);
+int EVP_PKEY_CTX_set_dh_paramgen_seed(EVP_PKEY_CTX *ctx,
+ const unsigned char *seed,
+ size_t seedlen);
+int EVP_PKEY_CTX_set_dh_paramgen_prime_len(EVP_PKEY_CTX *ctx, int pbits);
+int EVP_PKEY_CTX_set_dh_paramgen_subprime_len(EVP_PKEY_CTX *ctx, int qlen);
+int EVP_PKEY_CTX_set_dh_paramgen_generator(EVP_PKEY_CTX *ctx, int gen);
+int EVP_PKEY_CTX_set_dh_nid(EVP_PKEY_CTX *ctx, int nid);
+int EVP_PKEY_CTX_set_dh_rfc5114(EVP_PKEY_CTX *ctx, int gen);
+int EVP_PKEY_CTX_set_dhx_rfc5114(EVP_PKEY_CTX *ctx, int gen);
+int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad);
+
+int EVP_PKEY_CTX_set_dh_kdf_type(EVP_PKEY_CTX *ctx, int kdf);
+int EVP_PKEY_CTX_get_dh_kdf_type(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_CTX_set0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT *oid);
+int EVP_PKEY_CTX_get0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT **oid);
+int EVP_PKEY_CTX_set_dh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
+int EVP_PKEY_CTX_get_dh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
+int EVP_PKEY_CTX_set_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int len);
+int EVP_PKEY_CTX_get_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int *len);
+int EVP_PKEY_CTX_set0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
+int EVP_PKEY_CTX_get0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **ukm);
+#endif
-# define OPENSSL_DH_FIPS_MIN_MODULUS_BITS 1024
+# define EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN (EVP_PKEY_ALG_CTRL + 1)
+# define EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR (EVP_PKEY_ALG_CTRL + 2)
+# define EVP_PKEY_CTRL_DH_RFC5114 (EVP_PKEY_ALG_CTRL + 3)
+# define EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN (EVP_PKEY_ALG_CTRL + 4)
+# define EVP_PKEY_CTRL_DH_PARAMGEN_TYPE (EVP_PKEY_ALG_CTRL + 5)
+# define EVP_PKEY_CTRL_DH_KDF_TYPE (EVP_PKEY_ALG_CTRL + 6)
+# define EVP_PKEY_CTRL_DH_KDF_MD (EVP_PKEY_ALG_CTRL + 7)
+# define EVP_PKEY_CTRL_GET_DH_KDF_MD (EVP_PKEY_ALG_CTRL + 8)
+# define EVP_PKEY_CTRL_DH_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 9)
+# define EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 10)
+# define EVP_PKEY_CTRL_DH_KDF_UKM (EVP_PKEY_ALG_CTRL + 11)
+# define EVP_PKEY_CTRL_GET_DH_KDF_UKM (EVP_PKEY_ALG_CTRL + 12)
+# define EVP_PKEY_CTRL_DH_KDF_OID (EVP_PKEY_ALG_CTRL + 13)
+# define EVP_PKEY_CTRL_GET_DH_KDF_OID (EVP_PKEY_ALG_CTRL + 14)
+# define EVP_PKEY_CTRL_DH_NID (EVP_PKEY_ALG_CTRL + 15)
+# define EVP_PKEY_CTRL_DH_PAD (EVP_PKEY_ALG_CTRL + 16)
-# define DH_FLAG_CACHE_MONT_P 0x01
+/* KDF types */
+# define EVP_PKEY_DH_KDF_NONE 1
+# define EVP_PKEY_DH_KDF_X9_42 2
-# if OPENSSL_API_COMPAT < 0x10100000L
+# ifndef OPENSSL_NO_DH
+# include <openssl/e_os2.h>
+# include <openssl/bio.h>
+# include <openssl/asn1.h>
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# include <openssl/bn.h>
+# endif
+# include <openssl/dherr.h>
+
+# ifndef OPENSSL_DH_MAX_MODULUS_BITS
+# define OPENSSL_DH_MAX_MODULUS_BITS 10000
+# endif
+
+# define OPENSSL_DH_FIPS_MIN_MODULUS_BITS 1024
+
+# define DH_FLAG_CACHE_MONT_P 0x01
+
+# define DH_FLAG_TYPE_MASK 0xF000
+# define DH_FLAG_TYPE_DH 0x0000
+# define DH_FLAG_TYPE_DHX 0x1000
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
/*
* Does nothing. Previously this switched off constant time behaviour.
*/
-# define DH_FLAG_NO_EXP_CONSTTIME 0x00
-# endif
+# define DH_FLAG_NO_EXP_CONSTTIME 0x00
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
/*
* If this flag is set the DH method is FIPS compliant and can be used in
* FIPS mode. This is set in the validated module method. If an application
@@ -48,7 +115,7 @@ extern "C" {
* result is compliant.
*/
-# define DH_FLAG_FIPS_METHOD 0x0400
+# define DH_FLAG_FIPS_METHOD 0x0400
/*
* If this flag is set the operations normally disabled in FIPS mode are
@@ -56,7 +123,8 @@ extern "C" {
* usage is compliant.
*/
-# define DH_FLAG_NON_FIPS_ALLOW 0x0400
+# define DH_FLAG_NON_FIPS_ALLOW 0x0400
+# endif
/* Already defined in ossl_typ.h */
/* typedef struct dh_st DH; */
@@ -64,277 +132,197 @@ extern "C" {
DECLARE_ASN1_ITEM(DHparams)
-# define DH_GENERATOR_2 2
-/* #define DH_GENERATOR_3 3 */
-# define DH_GENERATOR_5 5
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define DH_GENERATOR_2 2
+# define DH_GENERATOR_3 3
+# define DH_GENERATOR_5 5
/* DH_check error codes */
-# define DH_CHECK_P_NOT_PRIME 0x01
-# define DH_CHECK_P_NOT_SAFE_PRIME 0x02
-# define DH_UNABLE_TO_CHECK_GENERATOR 0x04
-# define DH_NOT_SUITABLE_GENERATOR 0x08
-# define DH_CHECK_Q_NOT_PRIME 0x10
-# define DH_CHECK_INVALID_Q_VALUE 0x20
-# define DH_CHECK_INVALID_J_VALUE 0x40
+/*
+ * NB: These values must align with the equivalently named macros in
+ * internal/ffc.h.
+ */
+# define DH_CHECK_P_NOT_PRIME 0x01
+# define DH_CHECK_P_NOT_SAFE_PRIME 0x02
+# define DH_UNABLE_TO_CHECK_GENERATOR 0x04
+# define DH_NOT_SUITABLE_GENERATOR 0x08
+# define DH_CHECK_Q_NOT_PRIME 0x10
+# define DH_CHECK_INVALID_Q_VALUE 0x20
+# define DH_CHECK_INVALID_J_VALUE 0x40
+# define DH_MODULUS_TOO_SMALL 0x80
+# define DH_MODULUS_TOO_LARGE 0x100
/* DH_check_pub_key error codes */
-# define DH_CHECK_PUBKEY_TOO_SMALL 0x01
-# define DH_CHECK_PUBKEY_TOO_LARGE 0x02
-# define DH_CHECK_PUBKEY_INVALID 0x04
+# define DH_CHECK_PUBKEY_TOO_SMALL 0x01
+# define DH_CHECK_PUBKEY_TOO_LARGE 0x02
+# define DH_CHECK_PUBKEY_INVALID 0x04
/*
* primes p where (p-1)/2 is prime too are called "safe"; we define this for
* backward compatibility:
*/
-# define DH_CHECK_P_NOT_STRONG_PRIME DH_CHECK_P_NOT_SAFE_PRIME
-
-# define d2i_DHparams_fp(fp,x) \
- (DH *)ASN1_d2i_fp((char *(*)())DH_new, \
- (char *(*)())d2i_DHparams, \
- (fp), \
- (unsigned char **)(x))
-# define i2d_DHparams_fp(fp,x) \
- ASN1_i2d_fp(i2d_DHparams,(fp), (unsigned char *)(x))
-# define d2i_DHparams_bio(bp,x) \
- ASN1_d2i_bio_of(DH, DH_new, d2i_DHparams, bp, x)
-# define i2d_DHparams_bio(bp,x) \
- ASN1_i2d_bio_of_const(DH,i2d_DHparams,bp,x)
-
-# define d2i_DHxparams_fp(fp,x) \
- (DH *)ASN1_d2i_fp((char *(*)())DH_new, \
- (char *(*)())d2i_DHxparams, \
- (fp), \
- (unsigned char **)(x))
-# define i2d_DHxparams_fp(fp,x) \
- ASN1_i2d_fp(i2d_DHxparams,(fp), (unsigned char *)(x))
-# define d2i_DHxparams_bio(bp,x) \
- ASN1_d2i_bio_of(DH, DH_new, d2i_DHxparams, bp, x)
-# define i2d_DHxparams_bio(bp,x) \
- ASN1_i2d_bio_of_const(DH, i2d_DHxparams, bp, x)
-
-DH *DHparams_dup(DH *);
-
-const DH_METHOD *DH_OpenSSL(void);
-
-void DH_set_default_method(const DH_METHOD *meth);
-const DH_METHOD *DH_get_default_method(void);
-int DH_set_method(DH *dh, const DH_METHOD *meth);
-DH *DH_new_method(ENGINE *engine);
-
-DH *DH_new(void);
-void DH_free(DH *dh);
-int DH_up_ref(DH *dh);
-int DH_bits(const DH *dh);
-int DH_size(const DH *dh);
-int DH_security_bits(const DH *dh);
-#define DH_get_ex_new_index(l, p, newf, dupf, freef) \
- CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DH, l, p, newf, dupf, freef)
-int DH_set_ex_data(DH *d, int idx, void *arg);
-void *DH_get_ex_data(DH *d, int idx);
-
-/* Deprecated version */
-DEPRECATEDIN_0_9_8(DH *DH_generate_parameters(int prime_len, int generator,
- void (*callback) (int, int,
- void *),
- void *cb_arg))
-
-/* New version */
-int DH_generate_parameters_ex(DH *dh, int prime_len, int generator,
- BN_GENCB *cb);
-
-int DH_check_params_ex(const DH *dh);
-int DH_check_ex(const DH *dh);
-int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key);
-int DH_check_params(const DH *dh, int *ret);
-int DH_check(const DH *dh, int *codes);
-int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *codes);
-int DH_generate_key(DH *dh);
-int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh);
-int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh);
-DH *d2i_DHparams(DH **a, const unsigned char **pp, long length);
-int i2d_DHparams(const DH *a, unsigned char **pp);
-DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length);
-int i2d_DHxparams(const DH *a, unsigned char **pp);
-# ifndef OPENSSL_NO_STDIO
-int DHparams_print_fp(FILE *fp, const DH *x);
-# endif
-int DHparams_print(BIO *bp, const DH *x);
+# define DH_CHECK_P_NOT_STRONG_PRIME DH_CHECK_P_NOT_SAFE_PRIME
+
+# define d2i_DHparams_fp(fp, x) \
+ (DH *)ASN1_d2i_fp((char *(*)())DH_new, \
+ (char *(*)())d2i_DHparams, \
+ (fp), \
+ (unsigned char **)(x))
+# define i2d_DHparams_fp(fp, x) \
+ ASN1_i2d_fp(i2d_DHparams,(fp), (unsigned char *)(x))
+# define d2i_DHparams_bio(bp, x) \
+ ASN1_d2i_bio_of(DH, DH_new, d2i_DHparams, bp, x)
+# define i2d_DHparams_bio(bp, x) \
+ ASN1_i2d_bio_of(DH, i2d_DHparams, bp, x)
+
+# define d2i_DHxparams_fp(fp,x) \
+ (DH *)ASN1_d2i_fp((char *(*)())DH_new, \
+ (char *(*)())d2i_DHxparams, \
+ (fp), \
+ (unsigned char **)(x))
+# define i2d_DHxparams_fp(fp, x) \
+ ASN1_i2d_fp(i2d_DHxparams,(fp), (unsigned char *)(x))
+# define d2i_DHxparams_bio(bp, x) \
+ ASN1_d2i_bio_of(DH, DH_new, d2i_DHxparams, bp, x)
+# define i2d_DHxparams_bio(bp, x) \
+ ASN1_i2d_bio_of(DH, i2d_DHxparams, bp, x)
+
+DECLARE_ASN1_DUP_FUNCTION_name_attr(OSSL_DEPRECATEDIN_3_0, DH, DHparams)
+
+OSSL_DEPRECATEDIN_3_0 const DH_METHOD *DH_OpenSSL(void);
+
+OSSL_DEPRECATEDIN_3_0 void DH_set_default_method(const DH_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 const DH_METHOD *DH_get_default_method(void);
+OSSL_DEPRECATEDIN_3_0 int DH_set_method(DH *dh, const DH_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 DH *DH_new_method(ENGINE *engine);
+
+OSSL_DEPRECATEDIN_3_0 DH *DH_new(void);
+OSSL_DEPRECATEDIN_3_0 void DH_free(DH *dh);
+OSSL_DEPRECATEDIN_3_0 int DH_up_ref(DH *dh);
+OSSL_DEPRECATEDIN_3_0 int DH_bits(const DH *dh);
+OSSL_DEPRECATEDIN_3_0 int DH_size(const DH *dh);
+OSSL_DEPRECATEDIN_3_0 int DH_security_bits(const DH *dh);
+
+# define DH_get_ex_new_index(l, p, newf, dupf, freef) \
+ CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DH, l, p, newf, dupf, freef)
+
+OSSL_DEPRECATEDIN_3_0 int DH_set_ex_data(DH *d, int idx, void *arg);
+OSSL_DEPRECATEDIN_3_0 void *DH_get_ex_data(const DH *d, int idx);
+
+OSSL_DEPRECATEDIN_3_0 int DH_generate_parameters_ex(DH *dh, int prime_len,
+ int generator,
+ BN_GENCB *cb);
+
+OSSL_DEPRECATEDIN_3_0 int DH_check_params_ex(const DH *dh);
+OSSL_DEPRECATEDIN_3_0 int DH_check_ex(const DH *dh);
+OSSL_DEPRECATEDIN_3_0 int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key);
+OSSL_DEPRECATEDIN_3_0 int DH_check_params(const DH *dh, int *ret);
+OSSL_DEPRECATEDIN_3_0 int DH_check(const DH *dh, int *codes);
+OSSL_DEPRECATEDIN_3_0 int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key,
+ int *codes);
+OSSL_DEPRECATEDIN_3_0 int DH_generate_key(DH *dh);
+OSSL_DEPRECATEDIN_3_0 int DH_compute_key(unsigned char *key,
+ const BIGNUM *pub_key, DH *dh);
+OSSL_DEPRECATEDIN_3_0 int DH_compute_key_padded(unsigned char *key,
+ const BIGNUM *pub_key, DH *dh);
+
+DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(OSSL_DEPRECATEDIN_3_0, DH, DHparams)
+DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(OSSL_DEPRECATEDIN_3_0, DH, DHxparams)
+
+# ifndef OPENSSL_NO_STDIO
+OSSL_DEPRECATEDIN_3_0 int DHparams_print_fp(FILE *fp, const DH *x);
+# endif
+OSSL_DEPRECATEDIN_3_0 int DHparams_print(BIO *bp, const DH *x);
/* RFC 5114 parameters */
-DH *DH_get_1024_160(void);
-DH *DH_get_2048_224(void);
-DH *DH_get_2048_256(void);
+OSSL_DEPRECATEDIN_3_0 DH *DH_get_1024_160(void);
+OSSL_DEPRECATEDIN_3_0 DH *DH_get_2048_224(void);
+OSSL_DEPRECATEDIN_3_0 DH *DH_get_2048_256(void);
-/* Named parameters, currently RFC7919 */
-DH *DH_new_by_nid(int nid);
-int DH_get_nid(const DH *dh);
+/* Named parameters, currently RFC7919 and RFC3526 */
+OSSL_DEPRECATEDIN_3_0 DH *DH_new_by_nid(int nid);
+OSSL_DEPRECATEDIN_3_0 int DH_get_nid(const DH *dh);
-# ifndef OPENSSL_NO_CMS
/* RFC2631 KDF */
-int DH_KDF_X9_42(unsigned char *out, size_t outlen,
- const unsigned char *Z, size_t Zlen,
- ASN1_OBJECT *key_oid,
- const unsigned char *ukm, size_t ukmlen, const EVP_MD *md);
-# endif
-
-void DH_get0_pqg(const DH *dh,
- const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
-int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
-void DH_get0_key(const DH *dh,
- const BIGNUM **pub_key, const BIGNUM **priv_key);
-int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
-const BIGNUM *DH_get0_p(const DH *dh);
-const BIGNUM *DH_get0_q(const DH *dh);
-const BIGNUM *DH_get0_g(const DH *dh);
-const BIGNUM *DH_get0_priv_key(const DH *dh);
-const BIGNUM *DH_get0_pub_key(const DH *dh);
-void DH_clear_flags(DH *dh, int flags);
-int DH_test_flags(const DH *dh, int flags);
-void DH_set_flags(DH *dh, int flags);
-ENGINE *DH_get0_engine(DH *d);
-long DH_get_length(const DH *dh);
-int DH_set_length(DH *dh, long length);
-
-DH_METHOD *DH_meth_new(const char *name, int flags);
-void DH_meth_free(DH_METHOD *dhm);
-DH_METHOD *DH_meth_dup(const DH_METHOD *dhm);
-const char *DH_meth_get0_name(const DH_METHOD *dhm);
-int DH_meth_set1_name(DH_METHOD *dhm, const char *name);
-int DH_meth_get_flags(const DH_METHOD *dhm);
-int DH_meth_set_flags(DH_METHOD *dhm, int flags);
-void *DH_meth_get0_app_data(const DH_METHOD *dhm);
-int DH_meth_set0_app_data(DH_METHOD *dhm, void *app_data);
-int (*DH_meth_get_generate_key(const DH_METHOD *dhm)) (DH *);
-int DH_meth_set_generate_key(DH_METHOD *dhm, int (*generate_key) (DH *));
-int (*DH_meth_get_compute_key(const DH_METHOD *dhm))
- (unsigned char *key, const BIGNUM *pub_key, DH *dh);
-int DH_meth_set_compute_key(DH_METHOD *dhm,
- int (*compute_key) (unsigned char *key, const BIGNUM *pub_key, DH *dh));
-int (*DH_meth_get_bn_mod_exp(const DH_METHOD *dhm))
- (const DH *, BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *,
- BN_CTX *, BN_MONT_CTX *);
-int DH_meth_set_bn_mod_exp(DH_METHOD *dhm,
- int (*bn_mod_exp) (const DH *, BIGNUM *, const BIGNUM *, const BIGNUM *,
- const BIGNUM *, BN_CTX *, BN_MONT_CTX *));
-int (*DH_meth_get_init(const DH_METHOD *dhm))(DH *);
-int DH_meth_set_init(DH_METHOD *dhm, int (*init)(DH *));
-int (*DH_meth_get_finish(const DH_METHOD *dhm)) (DH *);
-int DH_meth_set_finish(DH_METHOD *dhm, int (*finish) (DH *));
-int (*DH_meth_get_generate_params(const DH_METHOD *dhm))
- (DH *, int, int, BN_GENCB *);
-int DH_meth_set_generate_params(DH_METHOD *dhm,
- int (*generate_params) (DH *, int, int, BN_GENCB *));
-
-
-# define EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \
- EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN, len, NULL)
-
-# define EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \
- EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN, len, NULL)
-
-# define EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \
- EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, typ, NULL)
-
-# define EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, gen) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \
- EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR, gen, NULL)
-
-# define EVP_PKEY_CTX_set_dh_rfc5114(ctx, gen) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_PARAMGEN, \
- EVP_PKEY_CTRL_DH_RFC5114, gen, NULL)
-
-# define EVP_PKEY_CTX_set_dhx_rfc5114(ctx, gen) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_PARAMGEN, \
- EVP_PKEY_CTRL_DH_RFC5114, gen, NULL)
-
-# define EVP_PKEY_CTX_set_dh_nid(ctx, nid) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, \
- EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN, \
- EVP_PKEY_CTRL_DH_NID, nid, NULL)
-
-# define EVP_PKEY_CTX_set_dh_pad(ctx, pad) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_DH_PAD, pad, NULL)
-
-# define EVP_PKEY_CTX_set_dh_kdf_type(ctx, kdf) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_DH_KDF_TYPE, kdf, NULL)
-
-# define EVP_PKEY_CTX_get_dh_kdf_type(ctx) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_DH_KDF_TYPE, -2, NULL)
-
-# define EVP_PKEY_CTX_set0_dh_kdf_oid(ctx, oid) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_DH_KDF_OID, 0, (void *)(oid))
-
-# define EVP_PKEY_CTX_get0_dh_kdf_oid(ctx, poid) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_GET_DH_KDF_OID, 0, (void *)(poid))
-
-# define EVP_PKEY_CTX_set_dh_kdf_md(ctx, md) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_DH_KDF_MD, 0, (void *)(md))
-
-# define EVP_PKEY_CTX_get_dh_kdf_md(ctx, pmd) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_GET_DH_KDF_MD, 0, (void *)(pmd))
-
-# define EVP_PKEY_CTX_set_dh_kdf_outlen(ctx, len) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_DH_KDF_OUTLEN, len, NULL)
-
-# define EVP_PKEY_CTX_get_dh_kdf_outlen(ctx, plen) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN, 0, (void *)(plen))
-
-# define EVP_PKEY_CTX_set0_dh_kdf_ukm(ctx, p, plen) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_DH_KDF_UKM, plen, (void *)(p))
-
-# define EVP_PKEY_CTX_get0_dh_kdf_ukm(ctx, p) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_GET_DH_KDF_UKM, 0, (void *)(p))
-
-# define EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN (EVP_PKEY_ALG_CTRL + 1)
-# define EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR (EVP_PKEY_ALG_CTRL + 2)
-# define EVP_PKEY_CTRL_DH_RFC5114 (EVP_PKEY_ALG_CTRL + 3)
-# define EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN (EVP_PKEY_ALG_CTRL + 4)
-# define EVP_PKEY_CTRL_DH_PARAMGEN_TYPE (EVP_PKEY_ALG_CTRL + 5)
-# define EVP_PKEY_CTRL_DH_KDF_TYPE (EVP_PKEY_ALG_CTRL + 6)
-# define EVP_PKEY_CTRL_DH_KDF_MD (EVP_PKEY_ALG_CTRL + 7)
-# define EVP_PKEY_CTRL_GET_DH_KDF_MD (EVP_PKEY_ALG_CTRL + 8)
-# define EVP_PKEY_CTRL_DH_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 9)
-# define EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 10)
-# define EVP_PKEY_CTRL_DH_KDF_UKM (EVP_PKEY_ALG_CTRL + 11)
-# define EVP_PKEY_CTRL_GET_DH_KDF_UKM (EVP_PKEY_ALG_CTRL + 12)
-# define EVP_PKEY_CTRL_DH_KDF_OID (EVP_PKEY_ALG_CTRL + 13)
-# define EVP_PKEY_CTRL_GET_DH_KDF_OID (EVP_PKEY_ALG_CTRL + 14)
-# define EVP_PKEY_CTRL_DH_NID (EVP_PKEY_ALG_CTRL + 15)
-# define EVP_PKEY_CTRL_DH_PAD (EVP_PKEY_ALG_CTRL + 16)
+OSSL_DEPRECATEDIN_3_0 int DH_KDF_X9_42(unsigned char *out, size_t outlen,
+ const unsigned char *Z, size_t Zlen,
+ ASN1_OBJECT *key_oid,
+ const unsigned char *ukm,
+ size_t ukmlen, const EVP_MD *md);
+
+OSSL_DEPRECATEDIN_3_0 void DH_get0_pqg(const DH *dh, const BIGNUM **p,
+ const BIGNUM **q, const BIGNUM **g);
+OSSL_DEPRECATEDIN_3_0 int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
+OSSL_DEPRECATEDIN_3_0 void DH_get0_key(const DH *dh, const BIGNUM **pub_key,
+ const BIGNUM **priv_key);
+OSSL_DEPRECATEDIN_3_0 int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *DH_get0_p(const DH *dh);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *DH_get0_q(const DH *dh);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *DH_get0_g(const DH *dh);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *DH_get0_priv_key(const DH *dh);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *DH_get0_pub_key(const DH *dh);
+OSSL_DEPRECATEDIN_3_0 void DH_clear_flags(DH *dh, int flags);
+OSSL_DEPRECATEDIN_3_0 int DH_test_flags(const DH *dh, int flags);
+OSSL_DEPRECATEDIN_3_0 void DH_set_flags(DH *dh, int flags);
+OSSL_DEPRECATEDIN_3_0 ENGINE *DH_get0_engine(DH *d);
+OSSL_DEPRECATEDIN_3_0 long DH_get_length(const DH *dh);
+OSSL_DEPRECATEDIN_3_0 int DH_set_length(DH *dh, long length);
+
+OSSL_DEPRECATEDIN_3_0 DH_METHOD *DH_meth_new(const char *name, int flags);
+OSSL_DEPRECATEDIN_3_0 void DH_meth_free(DH_METHOD *dhm);
+OSSL_DEPRECATEDIN_3_0 DH_METHOD *DH_meth_dup(const DH_METHOD *dhm);
+OSSL_DEPRECATEDIN_3_0 const char *DH_meth_get0_name(const DH_METHOD *dhm);
+OSSL_DEPRECATEDIN_3_0 int DH_meth_set1_name(DH_METHOD *dhm, const char *name);
+OSSL_DEPRECATEDIN_3_0 int DH_meth_get_flags(const DH_METHOD *dhm);
+OSSL_DEPRECATEDIN_3_0 int DH_meth_set_flags(DH_METHOD *dhm, int flags);
+OSSL_DEPRECATEDIN_3_0 void *DH_meth_get0_app_data(const DH_METHOD *dhm);
+OSSL_DEPRECATEDIN_3_0 int DH_meth_set0_app_data(DH_METHOD *dhm, void *app_data);
+OSSL_DEPRECATEDIN_3_0 int (*DH_meth_get_generate_key(const DH_METHOD *dhm)) (DH *);
+OSSL_DEPRECATEDIN_3_0 int DH_meth_set_generate_key(DH_METHOD *dhm,
+ int (*generate_key) (DH *));
+OSSL_DEPRECATEDIN_3_0 int (*DH_meth_get_compute_key(const DH_METHOD *dhm))
+ (unsigned char *key,
+ const BIGNUM *pub_key,
+ DH *dh);
+OSSL_DEPRECATEDIN_3_0 int DH_meth_set_compute_key(DH_METHOD *dhm,
+ int (*compute_key)
+ (unsigned char *key,
+ const BIGNUM *pub_key,
+ DH *dh));
+OSSL_DEPRECATEDIN_3_0 int (*DH_meth_get_bn_mod_exp(const DH_METHOD *dhm))
+ (const DH *, BIGNUM *,
+ const BIGNUM *,
+ const BIGNUM *,
+ const BIGNUM *, BN_CTX *,
+ BN_MONT_CTX *);
+OSSL_DEPRECATEDIN_3_0 int DH_meth_set_bn_mod_exp(DH_METHOD *dhm,
+ int (*bn_mod_exp)
+ (const DH *, BIGNUM *,
+ const BIGNUM *, const BIGNUM *,
+ const BIGNUM *, BN_CTX *,
+ BN_MONT_CTX *));
+OSSL_DEPRECATEDIN_3_0 int (*DH_meth_get_init(const DH_METHOD *dhm))(DH *);
+OSSL_DEPRECATEDIN_3_0 int DH_meth_set_init(DH_METHOD *dhm, int (*init)(DH *));
+OSSL_DEPRECATEDIN_3_0 int (*DH_meth_get_finish(const DH_METHOD *dhm)) (DH *);
+OSSL_DEPRECATEDIN_3_0 int DH_meth_set_finish(DH_METHOD *dhm, int (*finish) (DH *));
+OSSL_DEPRECATEDIN_3_0 int (*DH_meth_get_generate_params(const DH_METHOD *dhm))
+ (DH *, int, int,
+ BN_GENCB *);
+OSSL_DEPRECATEDIN_3_0 int DH_meth_set_generate_params(DH_METHOD *dhm,
+ int (*generate_params)
+ (DH *, int, int,
+ BN_GENCB *));
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
+
+# ifndef OPENSSL_NO_DEPRECATED_0_9_8
+OSSL_DEPRECATEDIN_0_9_8 DH *DH_generate_parameters(int prime_len, int generator,
+ void (*callback) (int, int,
+ void *),
+ void *cb_arg);
+# endif
-/* KDF types */
-# define EVP_PKEY_DH_KDF_NONE 1
-# ifndef OPENSSL_NO_CMS
-# define EVP_PKEY_DH_KDF_X9_42 2
# endif
-
-
-# ifdef __cplusplus
+# ifdef __cplusplus
}
-# endif
# endif
#endif
diff --git a/include/openssl/dherr.h b/include/openssl/dherr.h
index 916b3bed0b59..5d2a762a96f8 100644
--- a/include/openssl/dherr.h
+++ b/include/openssl/dherr.h
@@ -1,62 +1,29 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_DHERR_H
-# define HEADER_DHERR_H
-
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+#ifndef OPENSSL_DHERR_H
+# define OPENSSL_DHERR_H
+# pragma once
# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifndef OPENSSL_NO_DH
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_DH_strings(void);
+# ifndef OPENSSL_NO_DH
-/*
- * DH function codes.
- */
-# define DH_F_COMPUTE_KEY 102
-# define DH_F_DHPARAMS_PRINT_FP 101
-# define DH_F_DH_BUILTIN_GENPARAMS 106
-# define DH_F_DH_CHECK_EX 121
-# define DH_F_DH_CHECK_PARAMS_EX 122
-# define DH_F_DH_CHECK_PUB_KEY_EX 123
-# define DH_F_DH_CMS_DECRYPT 114
-# define DH_F_DH_CMS_SET_PEERKEY 115
-# define DH_F_DH_CMS_SET_SHARED_INFO 116
-# define DH_F_DH_METH_DUP 117
-# define DH_F_DH_METH_NEW 118
-# define DH_F_DH_METH_SET1_NAME 119
-# define DH_F_DH_NEW_BY_NID 104
-# define DH_F_DH_NEW_METHOD 105
-# define DH_F_DH_PARAM_DECODE 107
-# define DH_F_DH_PKEY_PUBLIC_CHECK 124
-# define DH_F_DH_PRIV_DECODE 110
-# define DH_F_DH_PRIV_ENCODE 111
-# define DH_F_DH_PUB_DECODE 108
-# define DH_F_DH_PUB_ENCODE 109
-# define DH_F_DO_DH_PRINT 100
-# define DH_F_GENERATE_KEY 103
-# define DH_F_PKEY_DH_CTRL_STR 120
-# define DH_F_PKEY_DH_DERIVE 112
-# define DH_F_PKEY_DH_INIT 125
-# define DH_F_PKEY_DH_KEYGEN 113
/*
* DH reason codes.
*/
+# define DH_R_BAD_FFC_PARAMETERS 127
# define DH_R_BAD_GENERATOR 101
# define DH_R_BN_DECODE_ERROR 109
# define DH_R_BN_ERROR 106
@@ -72,10 +39,12 @@ int ERR_load_DH_strings(void);
# define DH_R_INVALID_PARAMETER_NAME 110
# define DH_R_INVALID_PARAMETER_NID 114
# define DH_R_INVALID_PUBKEY 102
+# define DH_R_INVALID_SECRET 128
# define DH_R_KDF_PARAMETER_ERROR 112
# define DH_R_KEYS_NOT_SET 108
# define DH_R_MISSING_PUBKEY 125
# define DH_R_MODULUS_TOO_LARGE 103
+# define DH_R_MODULUS_TOO_SMALL 126
# define DH_R_NOT_SUITABLE_GENERATOR 120
# define DH_R_NO_PARAMETERS_SET 107
# define DH_R_NO_PRIVATE_VALUE 100
diff --git a/include/openssl/dsa.h b/include/openssl/dsa.h
index 6d8a18a4ad5a..5c0e4cddfa8e 100644
--- a/include/openssl/dsa.h
+++ b/include/openssl/dsa.h
@@ -1,44 +1,80 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_DSA_H
-# define HEADER_DSA_H
+#ifndef OPENSSL_DSA_H
+# define OPENSSL_DSA_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_DSA_H
+# endif
# include <openssl/opensslconf.h>
+# include <openssl/types.h>
-# ifndef OPENSSL_NO_DSA
# ifdef __cplusplus
extern "C" {
# endif
-# include <openssl/e_os2.h>
-# include <openssl/bio.h>
-# include <openssl/crypto.h>
-# include <openssl/ossl_typ.h>
-# include <openssl/bn.h>
-# if OPENSSL_API_COMPAT < 0x10100000L
-# include <openssl/dh.h>
-# endif
-# include <openssl/dsaerr.h>
-# ifndef OPENSSL_DSA_MAX_MODULUS_BITS
-# define OPENSSL_DSA_MAX_MODULUS_BITS 10000
-# endif
+# include <stdlib.h>
-# define OPENSSL_DSA_FIPS_MIN_MODULUS_BITS 1024
+int EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX *ctx, int nbits);
+int EVP_PKEY_CTX_set_dsa_paramgen_q_bits(EVP_PKEY_CTX *ctx, int qbits);
+int EVP_PKEY_CTX_set_dsa_paramgen_md_props(EVP_PKEY_CTX *ctx,
+ const char *md_name,
+ const char *md_properties);
+int EVP_PKEY_CTX_set_dsa_paramgen_gindex(EVP_PKEY_CTX *ctx, int gindex);
+int EVP_PKEY_CTX_set_dsa_paramgen_type(EVP_PKEY_CTX *ctx, const char *name);
+int EVP_PKEY_CTX_set_dsa_paramgen_seed(EVP_PKEY_CTX *ctx,
+ const unsigned char *seed,
+ size_t seedlen);
+int EVP_PKEY_CTX_set_dsa_paramgen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
-# define DSA_FLAG_CACHE_MONT_P 0x01
-# if OPENSSL_API_COMPAT < 0x10100000L
+# define EVP_PKEY_CTRL_DSA_PARAMGEN_BITS (EVP_PKEY_ALG_CTRL + 1)
+# define EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS (EVP_PKEY_ALG_CTRL + 2)
+# define EVP_PKEY_CTRL_DSA_PARAMGEN_MD (EVP_PKEY_ALG_CTRL + 3)
+
+# ifndef OPENSSL_NO_DSA
+# include <openssl/e_os2.h>
+# include <openssl/asn1.h>
+# include <openssl/bio.h>
+# include <openssl/crypto.h>
+# include <openssl/bn.h>
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# include <openssl/dh.h>
+# endif
+# include <openssl/dsaerr.h>
+
+# ifndef OPENSSL_DSA_MAX_MODULUS_BITS
+# define OPENSSL_DSA_MAX_MODULUS_BITS 10000
+# endif
+
+# define OPENSSL_DSA_FIPS_MIN_MODULUS_BITS 1024
+
+typedef struct DSA_SIG_st DSA_SIG;
+DSA_SIG *DSA_SIG_new(void);
+void DSA_SIG_free(DSA_SIG *a);
+DECLARE_ASN1_ENCODE_FUNCTIONS_only(DSA_SIG, DSA_SIG)
+void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s);
+
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
/*
* Does nothing. Previously this switched off constant time behaviour.
*/
-# define DSA_FLAG_NO_EXP_CONSTTIME 0x00
-# endif
+# define DSA_FLAG_NO_EXP_CONSTTIME 0x00
+# endif
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define DSA_FLAG_CACHE_MONT_P 0x01
/*
* If this flag is set the DSA method is FIPS compliant and can be used in
@@ -47,7 +83,7 @@ extern "C" {
* result is compliant.
*/
-# define DSA_FLAG_FIPS_METHOD 0x0400
+# define DSA_FLAG_FIPS_METHOD 0x0400
/*
* If this flag is set the operations normally disabled in FIPS mode are
@@ -55,190 +91,185 @@ extern "C" {
* usage is compliant.
*/
-# define DSA_FLAG_NON_FIPS_ALLOW 0x0400
-# define DSA_FLAG_FIPS_CHECKED 0x0800
+# define DSA_FLAG_NON_FIPS_ALLOW 0x0400
+# define DSA_FLAG_FIPS_CHECKED 0x0800
/* Already defined in ossl_typ.h */
/* typedef struct dsa_st DSA; */
/* typedef struct dsa_method DSA_METHOD; */
-typedef struct DSA_SIG_st DSA_SIG;
-
-# define d2i_DSAparams_fp(fp,x) (DSA *)ASN1_d2i_fp((char *(*)())DSA_new, \
- (char *(*)())d2i_DSAparams,(fp),(unsigned char **)(x))
-# define i2d_DSAparams_fp(fp,x) ASN1_i2d_fp(i2d_DSAparams,(fp), \
- (unsigned char *)(x))
-# define d2i_DSAparams_bio(bp,x) ASN1_d2i_bio_of(DSA,DSA_new,d2i_DSAparams,bp,x)
-# define i2d_DSAparams_bio(bp,x) ASN1_i2d_bio_of_const(DSA,i2d_DSAparams,bp,x)
-
-DSA *DSAparams_dup(DSA *x);
-DSA_SIG *DSA_SIG_new(void);
-void DSA_SIG_free(DSA_SIG *a);
-int i2d_DSA_SIG(const DSA_SIG *a, unsigned char **pp);
-DSA_SIG *d2i_DSA_SIG(DSA_SIG **v, const unsigned char **pp, long length);
-void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
-int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s);
+# define d2i_DSAparams_fp(fp, x) \
+ (DSA *)ASN1_d2i_fp((char *(*)())DSA_new, \
+ (char *(*)())d2i_DSAparams, (fp), \
+ (unsigned char **)(x))
+# define i2d_DSAparams_fp(fp, x) \
+ ASN1_i2d_fp(i2d_DSAparams, (fp), (unsigned char *)(x))
+# define d2i_DSAparams_bio(bp, x) \
+ ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSAparams, bp, x)
+# define i2d_DSAparams_bio(bp, x) \
+ ASN1_i2d_bio_of(DSA, i2d_DSAparams, bp, x)
-DSA_SIG *DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
-int DSA_do_verify(const unsigned char *dgst, int dgst_len,
- DSA_SIG *sig, DSA *dsa);
+DECLARE_ASN1_DUP_FUNCTION_name_attr(OSSL_DEPRECATEDIN_3_0, DSA, DSAparams)
+OSSL_DEPRECATEDIN_3_0 DSA_SIG *DSA_do_sign(const unsigned char *dgst, int dlen,
+ DSA *dsa);
+OSSL_DEPRECATEDIN_3_0 int DSA_do_verify(const unsigned char *dgst, int dgst_len,
+ DSA_SIG *sig, DSA *dsa);
-const DSA_METHOD *DSA_OpenSSL(void);
+OSSL_DEPRECATEDIN_3_0 const DSA_METHOD *DSA_OpenSSL(void);
-void DSA_set_default_method(const DSA_METHOD *);
-const DSA_METHOD *DSA_get_default_method(void);
-int DSA_set_method(DSA *dsa, const DSA_METHOD *);
-const DSA_METHOD *DSA_get_method(DSA *d);
+OSSL_DEPRECATEDIN_3_0 void DSA_set_default_method(const DSA_METHOD *);
+OSSL_DEPRECATEDIN_3_0 const DSA_METHOD *DSA_get_default_method(void);
+OSSL_DEPRECATEDIN_3_0 int DSA_set_method(DSA *dsa, const DSA_METHOD *);
+OSSL_DEPRECATEDIN_3_0 const DSA_METHOD *DSA_get_method(DSA *d);
-DSA *DSA_new(void);
-DSA *DSA_new_method(ENGINE *engine);
-void DSA_free(DSA *r);
+OSSL_DEPRECATEDIN_3_0 DSA *DSA_new(void);
+OSSL_DEPRECATEDIN_3_0 DSA *DSA_new_method(ENGINE *engine);
+OSSL_DEPRECATEDIN_3_0 void DSA_free(DSA *r);
/* "up" the DSA object's reference count */
-int DSA_up_ref(DSA *r);
-int DSA_size(const DSA *);
-int DSA_bits(const DSA *d);
-int DSA_security_bits(const DSA *d);
+OSSL_DEPRECATEDIN_3_0 int DSA_up_ref(DSA *r);
+OSSL_DEPRECATEDIN_3_0 int DSA_size(const DSA *);
+OSSL_DEPRECATEDIN_3_0 int DSA_bits(const DSA *d);
+OSSL_DEPRECATEDIN_3_0 int DSA_security_bits(const DSA *d);
/* next 4 return -1 on error */
-DEPRECATEDIN_1_2_0(int DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp))
-int DSA_sign(int type, const unsigned char *dgst, int dlen,
- unsigned char *sig, unsigned int *siglen, DSA *dsa);
-int DSA_verify(int type, const unsigned char *dgst, int dgst_len,
- const unsigned char *sigbuf, int siglen, DSA *dsa);
-#define DSA_get_ex_new_index(l, p, newf, dupf, freef) \
- CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DSA, l, p, newf, dupf, freef)
-int DSA_set_ex_data(DSA *d, int idx, void *arg);
-void *DSA_get_ex_data(DSA *d, int idx);
-
-DSA *d2i_DSAPublicKey(DSA **a, const unsigned char **pp, long length);
-DSA *d2i_DSAPrivateKey(DSA **a, const unsigned char **pp, long length);
-DSA *d2i_DSAparams(DSA **a, const unsigned char **pp, long length);
+OSSL_DEPRECATEDIN_3_0 int DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in,
+ BIGNUM **kinvp, BIGNUM **rp);
+OSSL_DEPRECATEDIN_3_0 int DSA_sign(int type, const unsigned char *dgst,
+ int dlen, unsigned char *sig,
+ unsigned int *siglen, DSA *dsa);
+OSSL_DEPRECATEDIN_3_0 int DSA_verify(int type, const unsigned char *dgst,
+ int dgst_len, const unsigned char *sigbuf,
+ int siglen, DSA *dsa);
+
+# define DSA_get_ex_new_index(l, p, newf, dupf, freef) \
+ CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DSA, l, p, newf, dupf, freef)
+OSSL_DEPRECATEDIN_3_0 int DSA_set_ex_data(DSA *d, int idx, void *arg);
+OSSL_DEPRECATEDIN_3_0 void *DSA_get_ex_data(const DSA *d, int idx);
+
+DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(OSSL_DEPRECATEDIN_3_0,
+ DSA, DSAPublicKey)
+DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(OSSL_DEPRECATEDIN_3_0,
+ DSA, DSAPrivateKey)
+DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(OSSL_DEPRECATEDIN_3_0,
+ DSA, DSAparams)
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_0_9_8
/* Deprecated version */
-DEPRECATEDIN_0_9_8(DSA *DSA_generate_parameters(int bits,
- unsigned char *seed,
- int seed_len,
- int *counter_ret,
- unsigned long *h_ret, void
- (*callback) (int, int,
- void *),
- void *cb_arg))
+OSSL_DEPRECATEDIN_0_9_8
+DSA *DSA_generate_parameters(int bits, unsigned char *seed, int seed_len,
+ int *counter_ret, unsigned long *h_ret,
+ void (*callback) (int, int, void *),
+ void *cb_arg);
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
/* New version */
-int DSA_generate_parameters_ex(DSA *dsa, int bits,
- const unsigned char *seed, int seed_len,
- int *counter_ret, unsigned long *h_ret,
- BN_GENCB *cb);
-
-int DSA_generate_key(DSA *a);
-int i2d_DSAPublicKey(const DSA *a, unsigned char **pp);
-int i2d_DSAPrivateKey(const DSA *a, unsigned char **pp);
-int i2d_DSAparams(const DSA *a, unsigned char **pp);
-
-int DSAparams_print(BIO *bp, const DSA *x);
-int DSA_print(BIO *bp, const DSA *x, int off);
-# ifndef OPENSSL_NO_STDIO
-int DSAparams_print_fp(FILE *fp, const DSA *x);
-int DSA_print_fp(FILE *bp, const DSA *x, int off);
-# endif
+OSSL_DEPRECATEDIN_3_0 int DSA_generate_parameters_ex(DSA *dsa, int bits,
+ const unsigned char *seed,
+ int seed_len,
+ int *counter_ret,
+ unsigned long *h_ret,
+ BN_GENCB *cb);
-# define DSS_prime_checks 64
+OSSL_DEPRECATEDIN_3_0 int DSA_generate_key(DSA *a);
+
+OSSL_DEPRECATEDIN_3_0 int DSAparams_print(BIO *bp, const DSA *x);
+OSSL_DEPRECATEDIN_3_0 int DSA_print(BIO *bp, const DSA *x, int off);
+# ifndef OPENSSL_NO_STDIO
+OSSL_DEPRECATEDIN_3_0 int DSAparams_print_fp(FILE *fp, const DSA *x);
+OSSL_DEPRECATEDIN_3_0 int DSA_print_fp(FILE *bp, const DSA *x, int off);
+# endif
+
+# define DSS_prime_checks 64
/*
* Primality test according to FIPS PUB 186-4, Appendix C.3. Since we only
* have one value here we set the number of checks to 64 which is the 128 bit
* security level that is the highest level and valid for creating a 3072 bit
* DSA key.
*/
-# define DSA_is_prime(n, callback, cb_arg) \
- BN_is_prime(n, DSS_prime_checks, callback, NULL, cb_arg)
+# define DSA_is_prime(n, callback, cb_arg) \
+ BN_is_prime(n, DSS_prime_checks, callback, NULL, cb_arg)
-# ifndef OPENSSL_NO_DH
+# ifndef OPENSSL_NO_DH
/*
* Convert DSA structure (key or just parameters) into DH structure (be
* careful to avoid small subgroup attacks when using this!)
*/
-DH *DSA_dup_DH(const DSA *r);
-# endif
+OSSL_DEPRECATEDIN_3_0 DH *DSA_dup_DH(const DSA *r);
+# endif
-# define EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, \
- EVP_PKEY_CTRL_DSA_PARAMGEN_BITS, nbits, NULL)
-# define EVP_PKEY_CTX_set_dsa_paramgen_q_bits(ctx, qbits) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, \
- EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, qbits, NULL)
-# define EVP_PKEY_CTX_set_dsa_paramgen_md(ctx, md) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, \
- EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0, (void *)(md))
-
-# define EVP_PKEY_CTRL_DSA_PARAMGEN_BITS (EVP_PKEY_ALG_CTRL + 1)
-# define EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS (EVP_PKEY_ALG_CTRL + 2)
-# define EVP_PKEY_CTRL_DSA_PARAMGEN_MD (EVP_PKEY_ALG_CTRL + 3)
+OSSL_DEPRECATEDIN_3_0 void DSA_get0_pqg(const DSA *d, const BIGNUM **p,
+ const BIGNUM **q, const BIGNUM **g);
+OSSL_DEPRECATEDIN_3_0 int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);
+OSSL_DEPRECATEDIN_3_0 void DSA_get0_key(const DSA *d, const BIGNUM **pub_key,
+ const BIGNUM **priv_key);
+OSSL_DEPRECATEDIN_3_0 int DSA_set0_key(DSA *d, BIGNUM *pub_key,
+ BIGNUM *priv_key);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *DSA_get0_p(const DSA *d);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *DSA_get0_q(const DSA *d);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *DSA_get0_g(const DSA *d);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *DSA_get0_pub_key(const DSA *d);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *DSA_get0_priv_key(const DSA *d);
+OSSL_DEPRECATEDIN_3_0 void DSA_clear_flags(DSA *d, int flags);
+OSSL_DEPRECATEDIN_3_0 int DSA_test_flags(const DSA *d, int flags);
+OSSL_DEPRECATEDIN_3_0 void DSA_set_flags(DSA *d, int flags);
+OSSL_DEPRECATEDIN_3_0 ENGINE *DSA_get0_engine(DSA *d);
-void DSA_get0_pqg(const DSA *d,
- const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
-int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);
-void DSA_get0_key(const DSA *d,
- const BIGNUM **pub_key, const BIGNUM **priv_key);
-int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);
-const BIGNUM *DSA_get0_p(const DSA *d);
-const BIGNUM *DSA_get0_q(const DSA *d);
-const BIGNUM *DSA_get0_g(const DSA *d);
-const BIGNUM *DSA_get0_pub_key(const DSA *d);
-const BIGNUM *DSA_get0_priv_key(const DSA *d);
-void DSA_clear_flags(DSA *d, int flags);
-int DSA_test_flags(const DSA *d, int flags);
-void DSA_set_flags(DSA *d, int flags);
-ENGINE *DSA_get0_engine(DSA *d);
-
-DSA_METHOD *DSA_meth_new(const char *name, int flags);
-void DSA_meth_free(DSA_METHOD *dsam);
-DSA_METHOD *DSA_meth_dup(const DSA_METHOD *dsam);
-const char *DSA_meth_get0_name(const DSA_METHOD *dsam);
-int DSA_meth_set1_name(DSA_METHOD *dsam, const char *name);
-int DSA_meth_get_flags(const DSA_METHOD *dsam);
-int DSA_meth_set_flags(DSA_METHOD *dsam, int flags);
-void *DSA_meth_get0_app_data(const DSA_METHOD *dsam);
-int DSA_meth_set0_app_data(DSA_METHOD *dsam, void *app_data);
-DSA_SIG *(*DSA_meth_get_sign(const DSA_METHOD *dsam))
+OSSL_DEPRECATEDIN_3_0 DSA_METHOD *DSA_meth_new(const char *name, int flags);
+OSSL_DEPRECATEDIN_3_0 void DSA_meth_free(DSA_METHOD *dsam);
+OSSL_DEPRECATEDIN_3_0 DSA_METHOD *DSA_meth_dup(const DSA_METHOD *dsam);
+OSSL_DEPRECATEDIN_3_0 const char *DSA_meth_get0_name(const DSA_METHOD *dsam);
+OSSL_DEPRECATEDIN_3_0 int DSA_meth_set1_name(DSA_METHOD *dsam,
+ const char *name);
+OSSL_DEPRECATEDIN_3_0 int DSA_meth_get_flags(const DSA_METHOD *dsam);
+OSSL_DEPRECATEDIN_3_0 int DSA_meth_set_flags(DSA_METHOD *dsam, int flags);
+OSSL_DEPRECATEDIN_3_0 void *DSA_meth_get0_app_data(const DSA_METHOD *dsam);
+OSSL_DEPRECATEDIN_3_0 int DSA_meth_set0_app_data(DSA_METHOD *dsam,
+ void *app_data);
+OSSL_DEPRECATEDIN_3_0 DSA_SIG *(*DSA_meth_get_sign(const DSA_METHOD *dsam))
(const unsigned char *, int, DSA *);
-int DSA_meth_set_sign(DSA_METHOD *dsam,
+OSSL_DEPRECATEDIN_3_0 int DSA_meth_set_sign(DSA_METHOD *dsam,
DSA_SIG *(*sign) (const unsigned char *, int, DSA *));
-int (*DSA_meth_get_sign_setup(const DSA_METHOD *dsam))
+OSSL_DEPRECATEDIN_3_0 int (*DSA_meth_get_sign_setup(const DSA_METHOD *dsam))
(DSA *, BN_CTX *, BIGNUM **, BIGNUM **);
-int DSA_meth_set_sign_setup(DSA_METHOD *dsam,
+OSSL_DEPRECATEDIN_3_0 int DSA_meth_set_sign_setup(DSA_METHOD *dsam,
int (*sign_setup) (DSA *, BN_CTX *, BIGNUM **, BIGNUM **));
-int (*DSA_meth_get_verify(const DSA_METHOD *dsam))
+OSSL_DEPRECATEDIN_3_0 int (*DSA_meth_get_verify(const DSA_METHOD *dsam))
(const unsigned char *, int, DSA_SIG *, DSA *);
-int DSA_meth_set_verify(DSA_METHOD *dsam,
+OSSL_DEPRECATEDIN_3_0 int DSA_meth_set_verify(DSA_METHOD *dsam,
int (*verify) (const unsigned char *, int, DSA_SIG *, DSA *));
-int (*DSA_meth_get_mod_exp(const DSA_METHOD *dsam))
+OSSL_DEPRECATEDIN_3_0 int (*DSA_meth_get_mod_exp(const DSA_METHOD *dsam))
(DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *,
const BIGNUM *, const BIGNUM *, BN_CTX *, BN_MONT_CTX *);
-int DSA_meth_set_mod_exp(DSA_METHOD *dsam,
+OSSL_DEPRECATEDIN_3_0 int DSA_meth_set_mod_exp(DSA_METHOD *dsam,
int (*mod_exp) (DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *,
const BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *,
BN_MONT_CTX *));
-int (*DSA_meth_get_bn_mod_exp(const DSA_METHOD *dsam))
+OSSL_DEPRECATEDIN_3_0 int (*DSA_meth_get_bn_mod_exp(const DSA_METHOD *dsam))
(DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *,
BN_CTX *, BN_MONT_CTX *);
-int DSA_meth_set_bn_mod_exp(DSA_METHOD *dsam,
+OSSL_DEPRECATEDIN_3_0 int DSA_meth_set_bn_mod_exp(DSA_METHOD *dsam,
int (*bn_mod_exp) (DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *,
const BIGNUM *, BN_CTX *, BN_MONT_CTX *));
-int (*DSA_meth_get_init(const DSA_METHOD *dsam))(DSA *);
-int DSA_meth_set_init(DSA_METHOD *dsam, int (*init)(DSA *));
-int (*DSA_meth_get_finish(const DSA_METHOD *dsam)) (DSA *);
-int DSA_meth_set_finish(DSA_METHOD *dsam, int (*finish) (DSA *));
-int (*DSA_meth_get_paramgen(const DSA_METHOD *dsam))
+OSSL_DEPRECATEDIN_3_0 int (*DSA_meth_get_init(const DSA_METHOD *dsam))(DSA *);
+OSSL_DEPRECATEDIN_3_0 int DSA_meth_set_init(DSA_METHOD *dsam,
+ int (*init)(DSA *));
+OSSL_DEPRECATEDIN_3_0 int (*DSA_meth_get_finish(const DSA_METHOD *dsam))(DSA *);
+OSSL_DEPRECATEDIN_3_0 int DSA_meth_set_finish(DSA_METHOD *dsam,
+ int (*finish)(DSA *));
+OSSL_DEPRECATEDIN_3_0 int (*DSA_meth_get_paramgen(const DSA_METHOD *dsam))
(DSA *, int, const unsigned char *, int, int *, unsigned long *,
BN_GENCB *);
-int DSA_meth_set_paramgen(DSA_METHOD *dsam,
+OSSL_DEPRECATEDIN_3_0 int DSA_meth_set_paramgen(DSA_METHOD *dsam,
int (*paramgen) (DSA *, int, const unsigned char *, int, int *,
unsigned long *, BN_GENCB *));
-int (*DSA_meth_get_keygen(const DSA_METHOD *dsam)) (DSA *);
-int DSA_meth_set_keygen(DSA_METHOD *dsam, int (*keygen) (DSA *));
-
+OSSL_DEPRECATEDIN_3_0 int (*DSA_meth_get_keygen(const DSA_METHOD *dsam))(DSA *);
+OSSL_DEPRECATEDIN_3_0 int DSA_meth_set_keygen(DSA_METHOD *dsam,
+ int (*keygen) (DSA *));
-# ifdef __cplusplus
-}
# endif
# endif
+# ifdef __cplusplus
+}
+# endif
#endif
diff --git a/include/openssl/dsaerr.h b/include/openssl/dsaerr.h
index 495a1ac89d63..5f0ca8d12a30 100644
--- a/include/openssl/dsaerr.h
+++ b/include/openssl/dsaerr.h
@@ -1,59 +1,29 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_DSAERR_H
-# define HEADER_DSAERR_H
-
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+#ifndef OPENSSL_DSAERR_H
+# define OPENSSL_DSAERR_H
+# pragma once
# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifndef OPENSSL_NO_DSA
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_DSA_strings(void);
+# ifndef OPENSSL_NO_DSA
-/*
- * DSA function codes.
- */
-# define DSA_F_DSAPARAMS_PRINT 100
-# define DSA_F_DSAPARAMS_PRINT_FP 101
-# define DSA_F_DSA_BUILTIN_PARAMGEN 125
-# define DSA_F_DSA_BUILTIN_PARAMGEN2 126
-# define DSA_F_DSA_DO_SIGN 112
-# define DSA_F_DSA_DO_VERIFY 113
-# define DSA_F_DSA_METH_DUP 127
-# define DSA_F_DSA_METH_NEW 128
-# define DSA_F_DSA_METH_SET1_NAME 129
-# define DSA_F_DSA_NEW_METHOD 103
-# define DSA_F_DSA_PARAM_DECODE 119
-# define DSA_F_DSA_PRINT_FP 105
-# define DSA_F_DSA_PRIV_DECODE 115
-# define DSA_F_DSA_PRIV_ENCODE 116
-# define DSA_F_DSA_PUB_DECODE 117
-# define DSA_F_DSA_PUB_ENCODE 118
-# define DSA_F_DSA_SIGN 106
-# define DSA_F_DSA_SIGN_SETUP 107
-# define DSA_F_DSA_SIG_NEW 102
-# define DSA_F_OLD_DSA_PRIV_DECODE 122
-# define DSA_F_PKEY_DSA_CTRL 120
-# define DSA_F_PKEY_DSA_CTRL_STR 104
-# define DSA_F_PKEY_DSA_KEYGEN 121
/*
* DSA reason codes.
*/
+# define DSA_R_BAD_FFC_PARAMETERS 114
# define DSA_R_BAD_Q_VALUE 102
# define DSA_R_BN_DECODE_ERROR 108
# define DSA_R_BN_ERROR 109
@@ -65,6 +35,7 @@ int ERR_load_DSA_strings(void);
# define DSA_R_MODULUS_TOO_LARGE 103
# define DSA_R_NO_PARAMETERS_SET 107
# define DSA_R_PARAMETER_ENCODING_ERROR 105
+# define DSA_R_P_NOT_PRIME 115
# define DSA_R_Q_NOT_PRIME 113
# define DSA_R_SEED_LEN_SMALL 110
diff --git a/include/openssl/dtls1.h b/include/openssl/dtls1.h
index d55ca9c332dd..5dc6b5419c27 100644
--- a/include/openssl/dtls1.h
+++ b/include/openssl/dtls1.h
@@ -1,36 +1,42 @@
/*
- * Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_DTLS1_H
-# define HEADER_DTLS1_H
+#ifndef OPENSSL_DTLS1_H
+# define OPENSSL_DTLS1_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_DTLS1_H
+# endif
+
+# include <openssl/prov_ssl.h>
#ifdef __cplusplus
extern "C" {
#endif
-# define DTLS1_VERSION 0xFEFF
-# define DTLS1_2_VERSION 0xFEFD
-# define DTLS_MIN_VERSION DTLS1_VERSION
-# define DTLS_MAX_VERSION DTLS1_2_VERSION
-# define DTLS1_VERSION_MAJOR 0xFE
+#include <openssl/opensslconf.h>
-# define DTLS1_BAD_VER 0x0100
+/* DTLS*_VERSION constants are defined in prov_ssl.h */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define DTLS_MIN_VERSION DTLS1_VERSION
+# define DTLS_MAX_VERSION DTLS1_2_VERSION
+# endif
+# define DTLS1_VERSION_MAJOR 0xFE
/* Special value for method supporting multiple versions */
# define DTLS_ANY_VERSION 0x1FFFF
/* lengths of messages */
-/*
- * Actually the max cookie length in DTLS is 255. But we can't change this now
- * due to compatibility concerns.
- */
-# define DTLS1_COOKIE_LENGTH 256
+
+# define DTLS1_COOKIE_LENGTH 255
# define DTLS1_RT_HEADER_LENGTH 13
@@ -43,10 +49,6 @@ extern "C" {
# define DTLS1_AL_HEADER_LENGTH 2
-/* Timeout multipliers */
-# define DTLS1_TMO_READ_COUNT 2
-# define DTLS1_TMO_WRITE_COUNT 2
-
# define DTLS1_TMO_ALERT_COUNT 12
#ifdef __cplusplus
diff --git a/include/openssl/e_os2.h b/include/openssl/e_os2.h
index 5c88e5194919..67289092717a 100644
--- a/include/openssl/e_os2.h
+++ b/include/openssl/e_os2.h
@@ -1,14 +1,20 @@
/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_E_OS2_H
-# define HEADER_E_OS2_H
+#ifndef OPENSSL_E_OS2_H
+# define OPENSSL_E_OS2_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_E_OS2_H
+# endif
# include <openssl/opensslconf.h>
@@ -96,11 +102,11 @@ extern "C" {
# endif
/* ------------------------------- OpenVMS -------------------------------- */
-# if defined(__VMS) || defined(VMS) || defined(OPENSSL_SYS_VMS)
+# if defined(__VMS) || defined(VMS)
# if !defined(OPENSSL_SYS_VMS)
# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_VMS
# endif
-# define OPENSSL_SYS_VMS
# if defined(__DECC)
# define OPENSSL_SYS_VMS_DECC
# elif defined(__DECCXX)
@@ -132,19 +138,25 @@ extern "C" {
# endif
# endif
+/* ---------------------------- HP NonStop -------------------------------- */
+# ifdef __TANDEM
+# ifdef _STRING
+# include <strings.h>
+# endif
+# define OPENSSL_USE_BUILD_DATE
+# if defined(OPENSSL_THREADS) && defined(_SPT_MODEL_)
+# define SPT_THREAD_SIGNAL 1
+# define SPT_THREAD_AWARE 1
+# include <spthread.h>
+# elif defined(OPENSSL_THREADS) && defined(_PUT_MODEL_)
+# include <pthread.h>
+# endif
+# endif
+
/**
* That's it for OS-specific stuff
*****************************************************************************/
-/* Specials for I/O an exit */
-# ifdef OPENSSL_SYS_MSDOS
-# define OPENSSL_UNISTD_IO <io.h>
-# define OPENSSL_DECLARE_EXIT extern void exit(int);
-# else
-# define OPENSSL_UNISTD_IO OPENSSL_UNISTD
-# define OPENSSL_DECLARE_EXIT /* declared in unistd.h */
-# endif
-
/*-
* OPENSSL_EXTERN is normally used to declare a symbol with possible extra
* attributes to handle its presence in a shared library.
@@ -172,29 +184,6 @@ extern "C" {
# define OPENSSL_EXTERN extern
# endif
-/*-
- * Macros to allow global variables to be reached through function calls when
- * required (if a shared library version requires it, for example.
- * The way it's done allows definitions like this:
- *
- * // in foobar.c
- * OPENSSL_IMPLEMENT_GLOBAL(int,foobar,0)
- * // in foobar.h
- * OPENSSL_DECLARE_GLOBAL(int,foobar);
- * #define foobar OPENSSL_GLOBAL_REF(foobar)
- */
-# ifdef OPENSSL_EXPORT_VAR_AS_FUNCTION
-# define OPENSSL_IMPLEMENT_GLOBAL(type,name,value) \
- type *_shadow_##name(void) \
- { static type _hide_##name=value; return &_hide_##name; }
-# define OPENSSL_DECLARE_GLOBAL(type,name) type *_shadow_##name(void)
-# define OPENSSL_GLOBAL_REF(name) (*(_shadow_##name()))
-# else
-# define OPENSSL_IMPLEMENT_GLOBAL(type,name,value) type _shadow_##name=value;
-# define OPENSSL_DECLARE_GLOBAL(type,name) OPENSSL_EXPORT type _shadow_##name
-# define OPENSSL_GLOBAL_REF(name) _shadow_##name
-# endif
-
# ifdef _WIN32
# ifdef _WIN64
# define ossl_ssize_t __int64
@@ -221,13 +210,15 @@ extern "C" {
# endif
# endif
-# ifdef DEBUG_UNUSED
+# if defined(UNUSEDRESULT_DEBUG)
# define __owur __attribute__((__warn_unused_result__))
# else
# define __owur
# endif
/* Standard integer types */
+# define OPENSSL_NO_INTTYPES_H
+# define OPENSSL_NO_STDINT_H
# if defined(OPENSSL_SYS_UEFI)
typedef INT8 int8_t;
typedef UINT8 uint8_t;
@@ -241,6 +232,9 @@ typedef UINT64 uint64_t;
defined(__osf__) || defined(__sgi) || defined(__hpux) || \
defined(OPENSSL_SYS_VMS) || defined (__OpenBSD__)
# include <inttypes.h>
+# undef OPENSSL_NO_INTTYPES_H
+/* Because the specs say that inttypes.h includes stdint.h if present */
+# undef OPENSSL_NO_STDINT_H
# elif defined(_MSC_VER) && _MSC_VER<1600
/*
* minimally required typdefs for systems not supporting inttypes.h or
@@ -256,6 +250,16 @@ typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
# else
# include <stdint.h>
+# undef OPENSSL_NO_STDINT_H
+# endif
+# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
+ defined(INTMAX_MAX) && defined(UINTMAX_MAX)
+typedef intmax_t ossl_intmax_t;
+typedef uintmax_t ossl_uintmax_t;
+# else
+/* Fall back to the largest we know we require and can handle */
+typedef int64_t ossl_intmax_t;
+typedef uint64_t ossl_uintmax_t;
# endif
/* ossl_inline: portable inline definition usable in public headers */
diff --git a/include/openssl/ebcdic.h b/include/openssl/ebcdic.h
index aa0128559992..e0ae1aa84e4a 100644
--- a/include/openssl/ebcdic.h
+++ b/include/openssl/ebcdic.h
@@ -1,14 +1,20 @@
/*
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_EBCDIC_H
-# define HEADER_EBCDIC_H
+#ifndef OPENSSL_EBCDIC_H
+# define OPENSSL_EBCDIC_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_EBCDIC_H
+# endif
# include <stdlib.h>
diff --git a/include/openssl/ec.h b/include/openssl/ec.h
index 24baf53c34d6..44d71932db63 100644
--- a/include/openssl/ec.h
+++ b/include/openssl/ec.h
@@ -1,33 +1,78 @@
/*
- * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_EC_H
-# define HEADER_EC_H
+#ifndef OPENSSL_EC_H
+# define OPENSSL_EC_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_EC_H
+# endif
# include <openssl/opensslconf.h>
+# include <openssl/types.h>
+
+# include <string.h>
-# ifndef OPENSSL_NO_EC
-# include <openssl/asn1.h>
-# include <openssl/symhacks.h>
-# if OPENSSL_API_COMPAT < 0x10100000L
-# include <openssl/bn.h>
-# endif
-# include <openssl/ecerr.h>
# ifdef __cplusplus
extern "C" {
# endif
-# ifndef OPENSSL_ECC_MAX_FIELD_BITS
-# define OPENSSL_ECC_MAX_FIELD_BITS 661
+/* Values for EVP_PKEY_CTX_set_ec_param_enc() */
+# define OPENSSL_EC_EXPLICIT_CURVE 0x000
+# define OPENSSL_EC_NAMED_CURVE 0x001
+
+int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid);
+int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int param_enc);
+int EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode);
+int EVP_PKEY_CTX_get_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx);
+
+int EVP_PKEY_CTX_set_ecdh_kdf_type(EVP_PKEY_CTX *ctx, int kdf);
+int EVP_PKEY_CTX_get_ecdh_kdf_type(EVP_PKEY_CTX *ctx);
+
+int EVP_PKEY_CTX_set_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
+int EVP_PKEY_CTX_get_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
+
+int EVP_PKEY_CTX_set_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int len);
+int EVP_PKEY_CTX_get_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int *len);
+
+int EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm,
+ int len);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
+int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **ukm);
# endif
+# define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1)
+# define EVP_PKEY_CTRL_EC_PARAM_ENC (EVP_PKEY_ALG_CTRL + 2)
+# define EVP_PKEY_CTRL_EC_ECDH_COFACTOR (EVP_PKEY_ALG_CTRL + 3)
+# define EVP_PKEY_CTRL_EC_KDF_TYPE (EVP_PKEY_ALG_CTRL + 4)
+# define EVP_PKEY_CTRL_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 5)
+# define EVP_PKEY_CTRL_GET_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 6)
+# define EVP_PKEY_CTRL_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 7)
+# define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 8)
+# define EVP_PKEY_CTRL_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 9)
+# define EVP_PKEY_CTRL_GET_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 10)
+
+/* KDF types */
+# define EVP_PKEY_ECDH_KDF_NONE 1
+# define EVP_PKEY_ECDH_KDF_X9_63 2
+/*
+ * The old name for EVP_PKEY_ECDH_KDF_X9_63
+ * The ECDH KDF specification has been mistakenly attributed to ANSI X9.62,
+ * it is actually specified in ANSI X9.63.
+ * This identifier is retained for backwards compatibility
+ */
+# define EVP_PKEY_ECDH_KDF_X9_62 EVP_PKEY_ECDH_KDF_X9_63
+
/** Enum for the point conversion form as defined in X9.62 (ECDSA)
* for the encoding of a elliptic curve point (x,y) */
typedef enum {
@@ -41,7 +86,24 @@ typedef enum {
POINT_CONVERSION_HYBRID = 6
} point_conversion_form_t;
+const char *OSSL_EC_curve_nid2name(int nid);
+
+# ifndef OPENSSL_NO_EC
+# include <openssl/asn1.h>
+# include <openssl/symhacks.h>
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# include <openssl/bn.h>
+# endif
+# include <openssl/ecerr.h>
+
+# ifndef OPENSSL_ECC_MAX_FIELD_BITS
+# define OPENSSL_ECC_MAX_FIELD_BITS 661
+# endif
+
+# include <openssl/params.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
typedef struct ec_method_st EC_METHOD;
+# endif
typedef struct ec_group_st EC_GROUP;
typedef struct ec_point_st EC_POINT;
typedef struct ecpk_parameters_st ECPKPARAMETERS;
@@ -51,40 +113,41 @@ typedef struct ec_parameters_st ECPARAMETERS;
/* EC_METHODs for curves over GF(p) */
/********************************************************************/
+# ifndef OPENSSL_NO_DEPRECATED_3_0
/** Returns the basic GFp ec methods which provides the basis for the
* optimized methods.
* \return EC_METHOD object
*/
-const EC_METHOD *EC_GFp_simple_method(void);
+OSSL_DEPRECATEDIN_3_0 const EC_METHOD *EC_GFp_simple_method(void);
/** Returns GFp methods using montgomery multiplication.
* \return EC_METHOD object
*/
-const EC_METHOD *EC_GFp_mont_method(void);
+OSSL_DEPRECATEDIN_3_0 const EC_METHOD *EC_GFp_mont_method(void);
/** Returns GFp methods using optimized methods for NIST recommended curves
* \return EC_METHOD object
*/
-const EC_METHOD *EC_GFp_nist_method(void);
+OSSL_DEPRECATEDIN_3_0 const EC_METHOD *EC_GFp_nist_method(void);
-# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
+# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
/** Returns 64-bit optimized methods for nistp224
* \return EC_METHOD object
*/
-const EC_METHOD *EC_GFp_nistp224_method(void);
+OSSL_DEPRECATEDIN_3_0 const EC_METHOD *EC_GFp_nistp224_method(void);
/** Returns 64-bit optimized methods for nistp256
* \return EC_METHOD object
*/
-const EC_METHOD *EC_GFp_nistp256_method(void);
+OSSL_DEPRECATEDIN_3_0 const EC_METHOD *EC_GFp_nistp256_method(void);
/** Returns 64-bit optimized methods for nistp521
* \return EC_METHOD object
*/
-const EC_METHOD *EC_GFp_nistp521_method(void);
-# endif
+OSSL_DEPRECATEDIN_3_0 const EC_METHOD *EC_GFp_nistp521_method(void);
+# endif /* OPENSSL_NO_EC_NISTP_64_GCC_128 */
-# ifndef OPENSSL_NO_EC2M
+# ifndef OPENSSL_NO_EC2M
/********************************************************************/
/* EC_METHOD for curves over GF(2^m) */
/********************************************************************/
@@ -92,30 +155,44 @@ const EC_METHOD *EC_GFp_nistp521_method(void);
/** Returns the basic GF2m ec method
* \return EC_METHOD object
*/
-const EC_METHOD *EC_GF2m_simple_method(void);
+OSSL_DEPRECATEDIN_3_0 const EC_METHOD *EC_GF2m_simple_method(void);
-# endif
+# endif
/********************************************************************/
/* EC_GROUP functions */
/********************************************************************/
-/** Creates a new EC_GROUP object
- * \param meth EC_METHOD to use
+/**
+ * Creates a new EC_GROUP object
+ * \param meth EC_METHOD to use
* \return newly created EC_GROUP object or NULL in case of an error.
*/
-EC_GROUP *EC_GROUP_new(const EC_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 EC_GROUP *EC_GROUP_new(const EC_METHOD *meth);
+
+/** Clears and frees a EC_GROUP object
+ * \param group EC_GROUP object to be cleared and freed.
+ */
+OSSL_DEPRECATEDIN_3_0 void EC_GROUP_clear_free(EC_GROUP *group);
+
+/** Returns the EC_METHOD of the EC_GROUP object.
+ * \param group EC_GROUP object
+ * \return EC_METHOD used in this EC_GROUP object.
+ */
+OSSL_DEPRECATEDIN_3_0 const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group);
+
+/** Returns the field type of the EC_METHOD.
+ * \param meth EC_METHOD object
+ * \return NID of the underlying field type OID.
+ */
+OSSL_DEPRECATEDIN_3_0 int EC_METHOD_get_field_type(const EC_METHOD *meth);
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
/** Frees a EC_GROUP object
* \param group EC_GROUP object to be freed.
*/
void EC_GROUP_free(EC_GROUP *group);
-/** Clears and frees a EC_GROUP object
- * \param group EC_GROUP object to be cleared and freed.
- */
-void EC_GROUP_clear_free(EC_GROUP *group);
-
/** Copies EC_GROUP objects. Note: both EC_GROUPs must use the same EC_METHOD.
* \param dst destination EC_GROUP object
* \param src source EC_GROUP object
@@ -123,25 +200,13 @@ void EC_GROUP_clear_free(EC_GROUP *group);
*/
int EC_GROUP_copy(EC_GROUP *dst, const EC_GROUP *src);
-/** Creates a new EC_GROUP object and copies the copies the content
+/** Creates a new EC_GROUP object and copies the content
* form src to the newly created EC_KEY object
* \param src source EC_GROUP object
* \return newly created EC_GROUP object or NULL in case of an error.
*/
EC_GROUP *EC_GROUP_dup(const EC_GROUP *src);
-/** Returns the EC_METHOD of the EC_GROUP object.
- * \param group EC_GROUP object
- * \return EC_METHOD used in this EC_GROUP object.
- */
-const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group);
-
-/** Returns the field type of the EC_METHOD.
- * \param meth EC_METHOD object
- * \return NID of the underlying field type OID.
- */
-int EC_METHOD_get_field_type(const EC_METHOD *meth);
-
/** Sets the generator and its order/cofactor of a EC_GROUP object.
* \param group EC_GROUP object
* \param generator EC_POINT object with the generator.
@@ -212,6 +277,18 @@ void EC_GROUP_set_curve_name(EC_GROUP *group, int nid);
*/
int EC_GROUP_get_curve_name(const EC_GROUP *group);
+/** Gets the field of an EC_GROUP
+ * \param group EC_GROUP object
+ * \return the group field
+ */
+const BIGNUM *EC_GROUP_get0_field(const EC_GROUP *group);
+
+/** Returns the field type of the EC_GROUP.
+ * \param group EC_GROUP object
+ * \return NID of the underlying field type OID.
+ */
+int EC_GROUP_get_field_type(const EC_GROUP *group);
+
void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag);
int EC_GROUP_get_asn1_flag(const EC_GROUP *group);
@@ -223,7 +300,7 @@ unsigned char *EC_GROUP_get0_seed(const EC_GROUP *x);
size_t EC_GROUP_get_seed_len(const EC_GROUP *);
size_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len);
-/** Sets the parameters of a ec curve defined by y^2 = x^3 + a*x + b (for GFp)
+/** Sets the parameters of an ec curve defined by y^2 = x^3 + a*x + b (for GFp)
* or y^2 + x*y = x^3 + a*x^2 + b (for GF2m)
* \param group EC_GROUP object
* \param p BIGNUM with the prime number (GFp) or the polynomial
@@ -249,6 +326,7 @@ int EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b,
BN_CTX *ctx);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
/** Sets the parameters of an ec curve. Synonym for EC_GROUP_set_curve
* \param group EC_GROUP object
* \param p BIGNUM with the prime number (GFp) or the polynomial
@@ -258,9 +336,11 @@ int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b,
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
-DEPRECATEDIN_1_2_0(int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p,
- const BIGNUM *a, const BIGNUM *b,
- BN_CTX *ctx))
+OSSL_DEPRECATEDIN_3_0 int EC_GROUP_set_curve_GFp(EC_GROUP *group,
+ const BIGNUM *p,
+ const BIGNUM *a,
+ const BIGNUM *b,
+ BN_CTX *ctx);
/** Gets the parameters of an ec curve. Synonym for EC_GROUP_get_curve
* \param group EC_GROUP object
@@ -271,11 +351,12 @@ DEPRECATEDIN_1_2_0(int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p,
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
-DEPRECATEDIN_1_2_0(int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p,
- BIGNUM *a, BIGNUM *b,
- BN_CTX *ctx))
+OSSL_DEPRECATEDIN_3_0 int EC_GROUP_get_curve_GFp(const EC_GROUP *group,
+ BIGNUM *p,
+ BIGNUM *a, BIGNUM *b,
+ BN_CTX *ctx);
-# ifndef OPENSSL_NO_EC2M
+# ifndef OPENSSL_NO_EC2M
/** Sets the parameter of an ec curve. Synonym for EC_GROUP_set_curve
* \param group EC_GROUP object
* \param p BIGNUM with the prime number (GFp) or the polynomial
@@ -285,9 +366,11 @@ DEPRECATEDIN_1_2_0(int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p,
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
-DEPRECATEDIN_1_2_0(int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p,
- const BIGNUM *a, const BIGNUM *b,
- BN_CTX *ctx))
+OSSL_DEPRECATEDIN_3_0 int EC_GROUP_set_curve_GF2m(EC_GROUP *group,
+ const BIGNUM *p,
+ const BIGNUM *a,
+ const BIGNUM *b,
+ BN_CTX *ctx);
/** Gets the parameters of an ec curve. Synonym for EC_GROUP_get_curve
* \param group EC_GROUP object
@@ -298,10 +381,13 @@ DEPRECATEDIN_1_2_0(int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p,
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
-DEPRECATEDIN_1_2_0(int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p,
- BIGNUM *a, BIGNUM *b,
- BN_CTX *ctx))
-# endif
+OSSL_DEPRECATEDIN_3_0 int EC_GROUP_get_curve_GF2m(const EC_GROUP *group,
+ BIGNUM *p,
+ BIGNUM *a, BIGNUM *b,
+ BN_CTX *ctx);
+# endif /* OPENSSL_NO_EC2M */
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
+
/** Returns the number of bits needed to represent a field element
* \param group EC_GROUP object
* \return number of bits needed to represent a field element
@@ -345,7 +431,7 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx);
*/
EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx);
-# ifndef OPENSSL_NO_EC2M
+# ifndef OPENSSL_NO_EC2M
/** Creates a new EC_GROUP object with the specified parameters defined
* over GF2m (defined by the equation y^2 + x*y = x^3 + a*x^2 + b)
* \param p BIGNUM with the polynomial defining the underlying field
@@ -356,10 +442,38 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
*/
EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx);
-# endif
+# endif
+
+/**
+ * Creates a EC_GROUP object with a curve specified by parameters.
+ * The parameters may be explicit or a named curve,
+ * \param params A list of parameters describing the group.
+ * \param libctx The associated library context or NULL for the default
+ * context
+ * \param propq A property query string
+ * \return newly created EC_GROUP object with specified parameters or NULL
+ * if an error occurred
+ */
+EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[],
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+/**
+ * Creates a EC_GROUP object with a curve specified by a NID
+ * \param libctx The associated library context or NULL for the default
+ * context
+ * \param propq A property query string
+ * \param nid NID of the OID of the curve name
+ * \return newly created EC_GROUP object with specified curve or NULL
+ * if an error occurred
+ */
+EC_GROUP *EC_GROUP_new_by_curve_name_ex(OSSL_LIB_CTX *libctx, const char *propq,
+ int nid);
-/** Creates a EC_GROUP object with a curve specified by a NID
- * \param nid NID of the OID of the curve name
+/**
+ * Creates a EC_GROUP object with a curve specified by a NID. Same as
+ * EC_GROUP_new_by_curve_name_ex but the libctx and propq are always
+ * NULL.
+ * \param nid NID of the OID of the curve name
* \return newly created EC_GROUP object with specified curve or NULL
* if an error occurred
*/
@@ -416,6 +530,8 @@ size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems);
const char *EC_curve_nid2nist(int nid);
int EC_curve_nist2nid(const char *name);
+int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only,
+ BN_CTX *ctx);
/********************************************************************/
/* EC_POINT functions */
@@ -452,12 +568,6 @@ int EC_POINT_copy(EC_POINT *dst, const EC_POINT *src);
*/
EC_POINT *EC_POINT_dup(const EC_POINT *src, const EC_GROUP *group);
-/** Returns the EC_METHOD used in EC_POINT object
- * \param point EC_POINT object
- * \return the EC_METHOD used
- */
-const EC_METHOD *EC_POINT_method_of(const EC_POINT *point);
-
/** Sets a point to infinity (neutral element)
* \param group underlying EC_GROUP object
* \param point EC_POINT to set to infinity
@@ -465,6 +575,13 @@ const EC_METHOD *EC_POINT_method_of(const EC_POINT *point);
*/
int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+/** Returns the EC_METHOD used in EC_POINT object
+ * \param point EC_POINT object
+ * \return the EC_METHOD used
+ */
+OSSL_DEPRECATEDIN_3_0 const EC_METHOD *EC_POINT_method_of(const EC_POINT *point);
+
/** Sets the jacobian projective coordinates of a EC_POINT over GFp
* \param group underlying EC_GROUP object
* \param p EC_POINT object
@@ -474,10 +591,10 @@ int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point);
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
-int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
- EC_POINT *p, const BIGNUM *x,
- const BIGNUM *y, const BIGNUM *z,
- BN_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 int EC_POINT_set_Jprojective_coordinates_GFp
+ (const EC_GROUP *group, EC_POINT *p,
+ const BIGNUM *x, const BIGNUM *y, const BIGNUM *z,
+ BN_CTX *ctx);
/** Gets the jacobian projective coordinates of a EC_POINT over GFp
* \param group underlying EC_GROUP object
@@ -488,10 +605,10 @@ int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
-int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
- const EC_POINT *p, BIGNUM *x,
- BIGNUM *y, BIGNUM *z,
- BN_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 int EC_POINT_get_Jprojective_coordinates_GFp
+ (const EC_GROUP *group, const EC_POINT *p,
+ BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx);
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
/** Sets the affine coordinates of an EC_POINT
* \param group underlying EC_GROUP object
@@ -516,6 +633,7 @@ int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *p,
int EC_POINT_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *p,
BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
/** Sets the affine coordinates of an EC_POINT. A synonym of
* EC_POINT_set_affine_coordinates
* \param group underlying EC_GROUP object
@@ -525,11 +643,9 @@ int EC_POINT_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *p,
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
-DEPRECATEDIN_1_2_0(int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
- EC_POINT *p,
- const BIGNUM *x,
- const BIGNUM *y,
- BN_CTX *ctx))
+OSSL_DEPRECATEDIN_3_0 int EC_POINT_set_affine_coordinates_GFp
+ (const EC_GROUP *group, EC_POINT *p,
+ const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx);
/** Gets the affine coordinates of an EC_POINT. A synonym of
* EC_POINT_get_affine_coordinates
@@ -540,11 +656,10 @@ DEPRECATEDIN_1_2_0(int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
-DEPRECATEDIN_1_2_0(int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
- const EC_POINT *p,
- BIGNUM *x,
- BIGNUM *y,
- BN_CTX *ctx))
+OSSL_DEPRECATEDIN_3_0 int EC_POINT_get_affine_coordinates_GFp
+ (const EC_GROUP *group, const EC_POINT *p,
+ BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
/** Sets the x9.62 compressed coordinates of a EC_POINT
* \param group underlying EC_GROUP object
@@ -558,6 +673,7 @@ int EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *p,
const BIGNUM *x, int y_bit,
BN_CTX *ctx);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
/** Sets the x9.62 compressed coordinates of a EC_POINT. A synonym of
* EC_POINT_set_compressed_coordinates
* \param group underlying EC_GROUP object
@@ -567,12 +683,10 @@ int EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *p,
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
-DEPRECATEDIN_1_2_0(int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
- EC_POINT *p,
- const BIGNUM *x,
- int y_bit,
- BN_CTX *ctx))
-# ifndef OPENSSL_NO_EC2M
+OSSL_DEPRECATEDIN_3_0 int EC_POINT_set_compressed_coordinates_GFp
+ (const EC_GROUP *group, EC_POINT *p,
+ const BIGNUM *x, int y_bit, BN_CTX *ctx);
+# ifndef OPENSSL_NO_EC2M
/** Sets the affine coordinates of an EC_POINT. A synonym of
* EC_POINT_set_affine_coordinates
* \param group underlying EC_GROUP object
@@ -582,11 +696,9 @@ DEPRECATEDIN_1_2_0(int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *g
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
-DEPRECATEDIN_1_2_0(int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
- EC_POINT *p,
- const BIGNUM *x,
- const BIGNUM *y,
- BN_CTX *ctx))
+OSSL_DEPRECATEDIN_3_0 int EC_POINT_set_affine_coordinates_GF2m
+ (const EC_GROUP *group, EC_POINT *p,
+ const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx);
/** Gets the affine coordinates of an EC_POINT. A synonym of
* EC_POINT_get_affine_coordinates
@@ -597,11 +709,9 @@ DEPRECATEDIN_1_2_0(int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *grou
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
-DEPRECATEDIN_1_2_0(int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
- const EC_POINT *p,
- BIGNUM *x,
- BIGNUM *y,
- BN_CTX *ctx))
+OSSL_DEPRECATEDIN_3_0 int EC_POINT_get_affine_coordinates_GF2m
+ (const EC_GROUP *group, const EC_POINT *p,
+ BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
/** Sets the x9.62 compressed coordinates of a EC_POINT. A synonym of
* EC_POINT_set_compressed_coordinates
@@ -612,12 +722,12 @@ DEPRECATEDIN_1_2_0(int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *grou
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
-DEPRECATEDIN_1_2_0(int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group,
- EC_POINT *p,
- const BIGNUM *x,
- int y_bit,
- BN_CTX *ctx))
-# endif
+OSSL_DEPRECATEDIN_3_0 int EC_POINT_set_compressed_coordinates_GF2m
+ (const EC_GROUP *group, EC_POINT *p,
+ const BIGNUM *x, int y_bit, BN_CTX *ctx);
+# endif
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
+
/** Encodes a EC_POINT object to a octet string
* \param group underlying EC_GROUP object
* \param p EC_POINT object
@@ -656,10 +766,16 @@ size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point,
unsigned char **pbuf, BN_CTX *ctx);
/* other interfaces to point2oct/oct2point: */
-BIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *,
- point_conversion_form_t form, BIGNUM *, BN_CTX *);
-EC_POINT *EC_POINT_bn2point(const EC_GROUP *, const BIGNUM *,
- EC_POINT *, BN_CTX *);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 BIGNUM *EC_POINT_point2bn(const EC_GROUP *,
+ const EC_POINT *,
+ point_conversion_form_t form,
+ BIGNUM *, BN_CTX *);
+OSSL_DEPRECATEDIN_3_0 EC_POINT *EC_POINT_bn2point(const EC_GROUP *,
+ const BIGNUM *,
+ EC_POINT *, BN_CTX *);
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
+
char *EC_POINT_point2hex(const EC_GROUP *, const EC_POINT *,
point_conversion_form_t form, BN_CTX *);
EC_POINT *EC_POINT_hex2point(const EC_GROUP *, const char *,
@@ -724,9 +840,11 @@ int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
BN_CTX *ctx);
-int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx);
-int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
- EC_POINT *points[], BN_CTX *ctx);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int EC_POINT_make_affine(const EC_GROUP *group,
+ EC_POINT *point, BN_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
+ EC_POINT *points[], BN_CTX *ctx);
/** Computes r = generator * n + sum_{i=0}^{num-1} p[i] * m[i]
* \param group underlying EC_GROUP object
@@ -738,9 +856,11 @@ int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
-int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n,
- size_t num, const EC_POINT *p[], const BIGNUM *m[],
- BN_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r,
+ const BIGNUM *n, size_t num,
+ const EC_POINT *p[], const BIGNUM *m[],
+ BN_CTX *ctx);
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
/** Computes r = generator * n + q * m
* \param group underlying EC_GROUP object
@@ -754,18 +874,20 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n,
int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n,
const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
/** Stores multiples of generator for faster point multiplication
* \param group EC_GROUP object
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred
*/
-int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
/** Reports whether a precomputation has been done
* \param group EC_GROUP object
* \return 1 if a pre-computation has been done and 0 otherwise
*/
-int EC_GROUP_have_precompute_mult(const EC_GROUP *group);
+OSSL_DEPRECATEDIN_3_0 int EC_GROUP_have_precompute_mult(const EC_GROUP *group);
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
/********************************************************************/
/* ASN1 stuff */
@@ -781,101 +903,135 @@ DECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS)
* represent the field elements
*/
int EC_GROUP_get_basis_type(const EC_GROUP *);
-# ifndef OPENSSL_NO_EC2M
+# ifndef OPENSSL_NO_EC2M
int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k);
int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1,
unsigned int *k2, unsigned int *k3);
-# endif
-
-# define OPENSSL_EC_EXPLICIT_CURVE 0x000
-# define OPENSSL_EC_NAMED_CURVE 0x001
+# endif
EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len);
int i2d_ECPKParameters(const EC_GROUP *, unsigned char **out);
-# define d2i_ECPKParameters_bio(bp,x) \
+# define d2i_ECPKParameters_bio(bp,x) \
ASN1_d2i_bio_of(EC_GROUP, NULL, d2i_ECPKParameters, bp, x)
-# define i2d_ECPKParameters_bio(bp,x) \
- ASN1_i2d_bio_of_const(EC_GROUP, i2d_ECPKParameters, bp, x)
-# define d2i_ECPKParameters_fp(fp,x) \
+# define i2d_ECPKParameters_bio(bp,x) \
+ ASN1_i2d_bio_of(EC_GROUP, i2d_ECPKParameters, bp, x)
+# define d2i_ECPKParameters_fp(fp,x) \
(EC_GROUP *)ASN1_d2i_fp(NULL, (d2i_of_void *)d2i_ECPKParameters, (fp), \
(void **)(x))
-# define i2d_ECPKParameters_fp(fp,x) \
+# define i2d_ECPKParameters_fp(fp,x) \
ASN1_i2d_fp((i2d_of_void *)i2d_ECPKParameters, (fp), (void *)(x))
-int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off);
-# ifndef OPENSSL_NO_STDIO
-int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off);
-# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int ECPKParameters_print(BIO *bp, const EC_GROUP *x,
+ int off);
+# ifndef OPENSSL_NO_STDIO
+OSSL_DEPRECATEDIN_3_0 int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x,
+ int off);
+# endif
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
/********************************************************************/
/* EC_KEY functions */
/********************************************************************/
/* some values for the encoding_flag */
-# define EC_PKEY_NO_PARAMETERS 0x001
-# define EC_PKEY_NO_PUBKEY 0x002
+# define EC_PKEY_NO_PARAMETERS 0x001
+# define EC_PKEY_NO_PUBKEY 0x002
/* some values for the flags field */
-# define EC_FLAG_NON_FIPS_ALLOW 0x1
-# define EC_FLAG_FIPS_CHECKED 0x2
-# define EC_FLAG_COFACTOR_ECDH 0x1000
+# define EC_FLAG_SM2_RANGE 0x0004
+# define EC_FLAG_COFACTOR_ECDH 0x1000
+# define EC_FLAG_CHECK_NAMED_GROUP 0x2000
+# define EC_FLAG_CHECK_NAMED_GROUP_NIST 0x4000
+# define EC_FLAG_CHECK_NAMED_GROUP_MASK \
+ (EC_FLAG_CHECK_NAMED_GROUP | EC_FLAG_CHECK_NAMED_GROUP_NIST)
+
+/* Deprecated flags - it was using 0x01..0x02 */
+# define EC_FLAG_NON_FIPS_ALLOW 0x0000
+# define EC_FLAG_FIPS_CHECKED 0x0000
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+/**
+ * Creates a new EC_KEY object.
+ * \param ctx The library context for to use for this EC_KEY. May be NULL in
+ * which case the default library context is used.
+ * \return EC_KEY object or NULL if an error occurred.
+ */
+OSSL_DEPRECATEDIN_3_0 EC_KEY *EC_KEY_new_ex(OSSL_LIB_CTX *ctx, const char *propq);
-/** Creates a new EC_KEY object.
+/**
+ * Creates a new EC_KEY object. Same as calling EC_KEY_new_ex with a
+ * NULL library context
* \return EC_KEY object or NULL if an error occurred.
*/
-EC_KEY *EC_KEY_new(void);
+OSSL_DEPRECATEDIN_3_0 EC_KEY *EC_KEY_new(void);
-int EC_KEY_get_flags(const EC_KEY *key);
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_get_flags(const EC_KEY *key);
-void EC_KEY_set_flags(EC_KEY *key, int flags);
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_set_flags(EC_KEY *key, int flags);
-void EC_KEY_clear_flags(EC_KEY *key, int flags);
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_clear_flags(EC_KEY *key, int flags);
-int EC_KEY_decoded_from_explicit_params(const EC_KEY *key);
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_decoded_from_explicit_params(const EC_KEY *key);
-/** Creates a new EC_KEY object using a named curve as underlying
+/**
+ * Creates a new EC_KEY object using a named curve as underlying
* EC_GROUP object.
+ * \param ctx The library context for to use for this EC_KEY. May be NULL in
+ * which case the default library context is used.
+ * \param propq Any property query string
+ * \param nid NID of the named curve.
+ * \return EC_KEY object or NULL if an error occurred.
+ */
+OSSL_DEPRECATEDIN_3_0 EC_KEY *EC_KEY_new_by_curve_name_ex(OSSL_LIB_CTX *ctx,
+ const char *propq,
+ int nid);
+
+/**
+ * Creates a new EC_KEY object using a named curve as underlying
+ * EC_GROUP object. Same as calling EC_KEY_new_by_curve_name_ex with a NULL
+ * library context and property query string.
* \param nid NID of the named curve.
* \return EC_KEY object or NULL if an error occurred.
*/
-EC_KEY *EC_KEY_new_by_curve_name(int nid);
+OSSL_DEPRECATEDIN_3_0 EC_KEY *EC_KEY_new_by_curve_name(int nid);
/** Frees a EC_KEY object.
* \param key EC_KEY object to be freed.
*/
-void EC_KEY_free(EC_KEY *key);
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_free(EC_KEY *key);
/** Copies a EC_KEY object.
* \param dst destination EC_KEY object
* \param src src EC_KEY object
* \return dst or NULL if an error occurred.
*/
-EC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src);
+OSSL_DEPRECATEDIN_3_0 EC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src);
/** Creates a new EC_KEY object and copies the content from src to it.
* \param src the source EC_KEY object
* \return newly created EC_KEY object or NULL if an error occurred.
*/
-EC_KEY *EC_KEY_dup(const EC_KEY *src);
+OSSL_DEPRECATEDIN_3_0 EC_KEY *EC_KEY_dup(const EC_KEY *src);
/** Increases the internal reference count of a EC_KEY object.
* \param key EC_KEY object
* \return 1 on success and 0 if an error occurred.
*/
-int EC_KEY_up_ref(EC_KEY *key);
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_up_ref(EC_KEY *key);
/** Returns the ENGINE object of a EC_KEY object
* \param eckey EC_KEY object
* \return the ENGINE object (possibly NULL).
*/
-ENGINE *EC_KEY_get0_engine(const EC_KEY *eckey);
+OSSL_DEPRECATEDIN_3_0 ENGINE *EC_KEY_get0_engine(const EC_KEY *eckey);
/** Returns the EC_GROUP object of a EC_KEY object
* \param key EC_KEY object
* \return the EC_GROUP object (possibly NULL).
*/
-const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key);
+OSSL_DEPRECATEDIN_3_0 const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key);
/** Sets the EC_GROUP of a EC_KEY object.
* \param key EC_KEY object
@@ -883,13 +1039,13 @@ const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key);
* object will use an own copy of the EC_GROUP).
* \return 1 on success and 0 if an error occurred.
*/
-int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group);
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group);
/** Returns the private key of a EC_KEY object.
* \param key EC_KEY object
* \return a BIGNUM with the private key (possibly NULL).
*/
-const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key);
/** Sets the private key of a EC_KEY object.
* \param key EC_KEY object
@@ -897,13 +1053,13 @@ const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key);
* will use an own copy of the BIGNUM).
* \return 1 on success and 0 if an error occurred.
*/
-int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv);
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv);
/** Returns the public key of a EC_KEY object.
* \param key the EC_KEY object
* \return a EC_POINT object with the public key (possibly NULL)
*/
-const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key);
+OSSL_DEPRECATEDIN_3_0 const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key);
/** Sets the public key of a EC_KEY object.
* \param key EC_KEY object
@@ -911,20 +1067,24 @@ const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key);
* will use an own copy of the EC_POINT object).
* \return 1 on success and 0 if an error occurred.
*/
-int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub);
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub);
-unsigned EC_KEY_get_enc_flags(const EC_KEY *key);
-void EC_KEY_set_enc_flags(EC_KEY *eckey, unsigned int flags);
-point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key);
-void EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform);
+OSSL_DEPRECATEDIN_3_0 unsigned EC_KEY_get_enc_flags(const EC_KEY *key);
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_set_enc_flags(EC_KEY *eckey, unsigned int flags);
+OSSL_DEPRECATEDIN_3_0 point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key);
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_set_conv_form(EC_KEY *eckey,
+ point_conversion_form_t cform);
+# endif /*OPENSSL_NO_DEPRECATED_3_0 */
-#define EC_KEY_get_ex_new_index(l, p, newf, dupf, freef) \
+# define EC_KEY_get_ex_new_index(l, p, newf, dupf, freef) \
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_EC_KEY, l, p, newf, dupf, freef)
-int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg);
-void *EC_KEY_get_ex_data(const EC_KEY *key, int idx);
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg);
+OSSL_DEPRECATEDIN_3_0 void *EC_KEY_get_ex_data(const EC_KEY *key, int idx);
/* wrapper functions for the underlying EC_GROUP object */
-void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag);
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag);
/** Creates a table of pre-computed multiples of the generator to
* accelerate further EC_KEY operations.
@@ -932,25 +1092,25 @@ void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag);
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occurred.
*/
-int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx);
/** Creates a new ec private (and optional a new public) key.
* \param key EC_KEY object
* \return 1 on success and 0 if an error occurred.
*/
-int EC_KEY_generate_key(EC_KEY *key);
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_generate_key(EC_KEY *key);
/** Verifies that a private and/or public key is valid.
* \param key the EC_KEY object
* \return 1 on success and 0 otherwise.
*/
-int EC_KEY_check_key(const EC_KEY *key);
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_check_key(const EC_KEY *key);
/** Indicates if an EC_KEY can be used for signing.
* \param eckey the EC_KEY object
* \return 1 if can can sign and 0 otherwise.
*/
-int EC_KEY_can_sign(const EC_KEY *eckey);
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_can_sign(const EC_KEY *eckey);
/** Sets a public key from affine coordinates performing
* necessary NIST PKV tests.
@@ -959,8 +1119,9 @@ int EC_KEY_can_sign(const EC_KEY *eckey);
* \param y public key y coordinate
* \return 1 on success and 0 otherwise.
*/
-int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
- BIGNUM *y);
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key,
+ BIGNUM *x,
+ BIGNUM *y);
/** Encodes an EC_KEY public key to an allocated octet string
* \param key key to encode
@@ -969,8 +1130,9 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
* \param ctx BN_CTX object (optional)
* \return the length of the encoded octet string or 0 if an error occurred
*/
-size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form,
- unsigned char **pbuf, BN_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 size_t EC_KEY_key2buf(const EC_KEY *key,
+ point_conversion_form_t form,
+ unsigned char **pbuf, BN_CTX *ctx);
/** Decodes a EC_KEY public key from a octet string
* \param key key to decode
@@ -980,8 +1142,8 @@ size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form,
* \return 1 on success and 0 if an error occurred
*/
-int EC_KEY_oct2key(EC_KEY *key, const unsigned char *buf, size_t len,
- BN_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_oct2key(EC_KEY *key, const unsigned char *buf,
+ size_t len, BN_CTX *ctx);
/** Decodes an EC_KEY private key from an octet string
* \param key key to decode
@@ -990,7 +1152,8 @@ int EC_KEY_oct2key(EC_KEY *key, const unsigned char *buf, size_t len,
* \return 1 on success and 0 if an error occurred
*/
-int EC_KEY_oct2priv(EC_KEY *key, const unsigned char *buf, size_t len);
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_oct2priv(EC_KEY *key, const unsigned char *buf,
+ size_t len);
/** Encodes a EC_KEY private key to an octet string
* \param key key to encode
@@ -1000,14 +1163,16 @@ int EC_KEY_oct2priv(EC_KEY *key, const unsigned char *buf, size_t len);
* \return the length of the encoded octet string or 0 if an error occurred
*/
-size_t EC_KEY_priv2oct(const EC_KEY *key, unsigned char *buf, size_t len);
+OSSL_DEPRECATEDIN_3_0 size_t EC_KEY_priv2oct(const EC_KEY *key,
+ unsigned char *buf, size_t len);
/** Encodes an EC_KEY private key to an allocated octet string
* \param eckey key to encode
* \param pbuf returns pointer to allocated buffer
* \return the length of the encoded octet string or 0 if an error occurred
*/
-size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf);
+OSSL_DEPRECATEDIN_3_0 size_t EC_KEY_priv2buf(const EC_KEY *eckey,
+ unsigned char **pbuf);
/********************************************************************/
/* de- and encoding functions for SEC1 ECPrivateKey */
@@ -1019,7 +1184,9 @@ size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf);
* \param len length of the DER encoded private key
* \return the decoded private key or NULL if an error occurred.
*/
-EC_KEY *d2i_ECPrivateKey(EC_KEY **key, const unsigned char **in, long len);
+OSSL_DEPRECATEDIN_3_0 EC_KEY *d2i_ECPrivateKey(EC_KEY **key,
+ const unsigned char **in,
+ long len);
/** Encodes a private key object and stores the result in a buffer.
* \param key the EC_KEY object to encode
@@ -1027,7 +1194,8 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **key, const unsigned char **in, long len);
* of bytes needed).
* \return 1 on success and 0 if an error occurred.
*/
-int i2d_ECPrivateKey(EC_KEY *key, unsigned char **out);
+OSSL_DEPRECATEDIN_3_0 int i2d_ECPrivateKey(const EC_KEY *key,
+ unsigned char **out);
/********************************************************************/
/* de- and encoding functions for EC parameters */
@@ -1040,7 +1208,9 @@ int i2d_ECPrivateKey(EC_KEY *key, unsigned char **out);
* \return a EC_KEY object with the decoded parameters or NULL if an error
* occurred.
*/
-EC_KEY *d2i_ECParameters(EC_KEY **key, const unsigned char **in, long len);
+OSSL_DEPRECATEDIN_3_0 EC_KEY *d2i_ECParameters(EC_KEY **key,
+ const unsigned char **in,
+ long len);
/** Encodes ec parameter and stores the result in a buffer.
* \param key the EC_KEY object with ec parameters to encode
@@ -1048,36 +1218,38 @@ EC_KEY *d2i_ECParameters(EC_KEY **key, const unsigned char **in, long len);
* of bytes needed).
* \return 1 on success and 0 if an error occurred.
*/
-int i2d_ECParameters(EC_KEY *key, unsigned char **out);
+OSSL_DEPRECATEDIN_3_0 int i2d_ECParameters(const EC_KEY *key,
+ unsigned char **out);
/********************************************************************/
/* de- and encoding functions for EC public key */
/* (octet string, not DER -- hence 'o2i' and 'i2o') */
/********************************************************************/
-/** Decodes a ec public key from a octet string.
+/** Decodes an ec public key from a octet string.
* \param key a pointer to a EC_KEY object which should be used
* \param in memory buffer with the encoded public key
* \param len length of the encoded public key
* \return EC_KEY object with decoded public key or NULL if an error
* occurred.
*/
-EC_KEY *o2i_ECPublicKey(EC_KEY **key, const unsigned char **in, long len);
+OSSL_DEPRECATEDIN_3_0 EC_KEY *o2i_ECPublicKey(EC_KEY **key,
+ const unsigned char **in, long len);
-/** Encodes a ec public key in an octet string.
+/** Encodes an ec public key in an octet string.
* \param key the EC_KEY object with the public key
* \param out the buffer for the result (if NULL the function returns number
* of bytes needed).
* \return 1 on success and 0 if an error occurred
*/
-int i2o_ECPublicKey(const EC_KEY *key, unsigned char **out);
+OSSL_DEPRECATEDIN_3_0 int i2o_ECPublicKey(const EC_KEY *key, unsigned char **out);
/** Prints out the ec parameters on human readable form.
* \param bp BIO object to which the information is printed
* \param key EC_KEY object
* \return 1 on success and 0 if an error occurred
*/
-int ECParameters_print(BIO *bp, const EC_KEY *key);
+OSSL_DEPRECATEDIN_3_0 int ECParameters_print(BIO *bp, const EC_KEY *key);
/** Prints out the contents of a EC_KEY object
* \param bp BIO object to which the information is printed
@@ -1085,15 +1257,15 @@ int ECParameters_print(BIO *bp, const EC_KEY *key);
* \param off line offset
* \return 1 on success and 0 if an error occurred
*/
-int EC_KEY_print(BIO *bp, const EC_KEY *key, int off);
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_print(BIO *bp, const EC_KEY *key, int off);
-# ifndef OPENSSL_NO_STDIO
+# ifndef OPENSSL_NO_STDIO
/** Prints out the ec parameters on human readable form.
* \param fp file descriptor to which the information is printed
* \param key EC_KEY object
* \return 1 on success and 0 if an error occurred
*/
-int ECParameters_print_fp(FILE *fp, const EC_KEY *key);
+OSSL_DEPRECATEDIN_3_0 int ECParameters_print_fp(FILE *fp, const EC_KEY *key);
/** Prints out the contents of a EC_KEY object
* \param fp file descriptor to which the information is printed
@@ -1101,31 +1273,33 @@ int ECParameters_print_fp(FILE *fp, const EC_KEY *key);
* \param off line offset
* \return 1 on success and 0 if an error occurred
*/
-int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off);
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off);
+# endif /* OPENSSL_NO_STDIO */
-# endif
-
-const EC_KEY_METHOD *EC_KEY_OpenSSL(void);
-const EC_KEY_METHOD *EC_KEY_get_default_method(void);
-void EC_KEY_set_default_method(const EC_KEY_METHOD *meth);
-const EC_KEY_METHOD *EC_KEY_get_method(const EC_KEY *key);
-int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth);
-EC_KEY *EC_KEY_new_method(ENGINE *engine);
+OSSL_DEPRECATEDIN_3_0 const EC_KEY_METHOD *EC_KEY_OpenSSL(void);
+OSSL_DEPRECATEDIN_3_0 const EC_KEY_METHOD *EC_KEY_get_default_method(void);
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_set_default_method(const EC_KEY_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 const EC_KEY_METHOD *EC_KEY_get_method(const EC_KEY *key);
+OSSL_DEPRECATEDIN_3_0 int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 EC_KEY *EC_KEY_new_method(ENGINE *engine);
/** The old name for ecdh_KDF_X9_63
* The ECDH KDF specification has been mistakingly attributed to ANSI X9.62,
* it is actually specified in ANSI X9.63.
* This identifier is retained for backwards compatibility
*/
-int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
- const unsigned char *Z, size_t Zlen,
- const unsigned char *sinfo, size_t sinfolen,
- const EVP_MD *md);
+OSSL_DEPRECATEDIN_3_0 int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
+ const unsigned char *Z, size_t Zlen,
+ const unsigned char *sinfo,
+ size_t sinfolen, const EVP_MD *md);
-int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
- const EC_KEY *ecdh,
- void *(*KDF) (const void *in, size_t inlen,
- void *out, size_t *outlen));
+OSSL_DEPRECATEDIN_3_0 int ECDH_compute_key(void *out, size_t outlen,
+ const EC_POINT *pub_key,
+ const EC_KEY *ecdh,
+ void *(*KDF)(const void *in,
+ size_t inlen, void *out,
+ size_t *outlen));
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
typedef struct ECDSA_SIG_st ECDSA_SIG;
@@ -1139,23 +1313,22 @@ ECDSA_SIG *ECDSA_SIG_new(void);
*/
void ECDSA_SIG_free(ECDSA_SIG *sig);
-/** DER encode content of ECDSA_SIG object (note: this function modifies *pp
+/** i2d_ECDSA_SIG encodes content of ECDSA_SIG (note: this function modifies *pp
* (*pp += length of the DER encoded signature)).
* \param sig pointer to the ECDSA_SIG object
* \param pp pointer to a unsigned char pointer for the output or NULL
* \return the length of the DER encoded ECDSA_SIG object or a negative value
* on error
*/
-int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **pp);
+DECLARE_ASN1_ENCODE_FUNCTIONS_only(ECDSA_SIG, ECDSA_SIG)
-/** Decodes a DER encoded ECDSA signature (note: this function changes *pp
+/** d2i_ECDSA_SIG decodes an ECDSA signature (note: this function modifies *pp
* (*pp += len)).
* \param sig pointer to ECDSA_SIG pointer (may be NULL)
* \param pp memory buffer with the DER encoded signature
* \param len length of the buffer
* \return pointer to the decoded ECDSA_SIG structure (or NULL)
*/
-ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **sig, const unsigned char **pp, long len);
/** Accessor for r and s fields of ECDSA_SIG
* \param sig pointer to ECDSA_SIG structure
@@ -1176,11 +1349,12 @@ const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig);
/** Setter for r and s fields of ECDSA_SIG
* \param sig pointer to ECDSA_SIG structure
- * \param r pointer to BIGNUM for r (may be NULL)
- * \param s pointer to BIGNUM for s (may be NULL)
+ * \param r pointer to BIGNUM for r
+ * \param s pointer to BIGNUM for s
*/
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
/** Computes the ECDSA signature of the given hash value using
* the supplied private key and returns the created signature.
* \param dgst pointer to the hash value
@@ -1188,8 +1362,8 @@ int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
* \param eckey EC_KEY object containing a private EC key
* \return pointer to a ECDSA_SIG structure or NULL if an error occurred
*/
-ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len,
- EC_KEY *eckey);
+OSSL_DEPRECATEDIN_3_0 ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst,
+ int dgst_len, EC_KEY *eckey);
/** Computes ECDSA signature of a given hash value using the supplied
* private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
@@ -1201,9 +1375,9 @@ ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len,
* \param eckey EC_KEY object containing a private EC key
* \return pointer to a ECDSA_SIG structure or NULL if an error occurred
*/
-ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen,
- const BIGNUM *kinv, const BIGNUM *rp,
- EC_KEY *eckey);
+OSSL_DEPRECATEDIN_3_0 ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst,
+ int dgstlen, const BIGNUM *kinv,
+ const BIGNUM *rp, EC_KEY *eckey);
/** Verifies that the supplied signature is a valid ECDSA
* signature of the supplied hash value using the supplied public key.
@@ -1214,8 +1388,8 @@ ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen,
* \return 1 if the signature is valid, 0 if the signature is invalid
* and -1 on error
*/
-int ECDSA_do_verify(const unsigned char *dgst, int dgst_len,
- const ECDSA_SIG *sig, EC_KEY *eckey);
+OSSL_DEPRECATEDIN_3_0 int ECDSA_do_verify(const unsigned char *dgst, int dgst_len,
+ const ECDSA_SIG *sig, EC_KEY *eckey);
/** Precompute parts of the signing operation
* \param eckey EC_KEY object containing a private EC key
@@ -1224,7 +1398,8 @@ int ECDSA_do_verify(const unsigned char *dgst, int dgst_len,
* \param rp BIGNUM pointer for x coordinate of k * generator
* \return 1 on success and 0 otherwise
*/
-int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp);
+OSSL_DEPRECATEDIN_3_0 int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx,
+ BIGNUM **kinv, BIGNUM **rp);
/** Computes ECDSA signature of a given hash value using the supplied
* private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
@@ -1236,8 +1411,9 @@ int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp);
* \param eckey EC_KEY object containing a private EC key
* \return 1 on success and 0 otherwise
*/
-int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen,
- unsigned char *sig, unsigned int *siglen, EC_KEY *eckey);
+OSSL_DEPRECATEDIN_3_0 int ECDSA_sign(int type, const unsigned char *dgst,
+ int dgstlen, unsigned char *sig,
+ unsigned int *siglen, EC_KEY *eckey);
/** Computes ECDSA signature of a given hash value using the supplied
* private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
@@ -1252,9 +1428,10 @@ int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen,
* \param eckey EC_KEY object containing a private EC key
* \return 1 on success and 0 otherwise
*/
-int ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen,
- unsigned char *sig, unsigned int *siglen,
- const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey);
+OSSL_DEPRECATEDIN_3_0 int ECDSA_sign_ex(int type, const unsigned char *dgst,
+ int dgstlen, unsigned char *sig,
+ unsigned int *siglen, const BIGNUM *kinv,
+ const BIGNUM *rp, EC_KEY *eckey);
/** Verifies that the given signature is valid ECDSA signature
* of the supplied hash value using the specified public key.
@@ -1267,218 +1444,126 @@ int ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen,
* \return 1 if the signature is valid, 0 if the signature is invalid
* and -1 on error
*/
-int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen,
- const unsigned char *sig, int siglen, EC_KEY *eckey);
+OSSL_DEPRECATEDIN_3_0 int ECDSA_verify(int type, const unsigned char *dgst,
+ int dgstlen, const unsigned char *sig,
+ int siglen, EC_KEY *eckey);
/** Returns the maximum length of the DER encoded signature
* \param eckey EC_KEY object
* \return numbers of bytes required for the DER encoded signature
*/
-int ECDSA_size(const EC_KEY *eckey);
+OSSL_DEPRECATEDIN_3_0 int ECDSA_size(const EC_KEY *eckey);
/********************************************************************/
/* EC_KEY_METHOD constructors, destructors, writers and accessors */
/********************************************************************/
-EC_KEY_METHOD *EC_KEY_METHOD_new(const EC_KEY_METHOD *meth);
-void EC_KEY_METHOD_free(EC_KEY_METHOD *meth);
-void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth,
- int (*init)(EC_KEY *key),
- void (*finish)(EC_KEY *key),
- int (*copy)(EC_KEY *dest, const EC_KEY *src),
- int (*set_group)(EC_KEY *key, const EC_GROUP *grp),
- int (*set_private)(EC_KEY *key,
- const BIGNUM *priv_key),
- int (*set_public)(EC_KEY *key,
- const EC_POINT *pub_key));
-
-void EC_KEY_METHOD_set_keygen(EC_KEY_METHOD *meth,
- int (*keygen)(EC_KEY *key));
-
-void EC_KEY_METHOD_set_compute_key(EC_KEY_METHOD *meth,
- int (*ckey)(unsigned char **psec,
- size_t *pseclen,
- const EC_POINT *pub_key,
- const EC_KEY *ecdh));
-
-void EC_KEY_METHOD_set_sign(EC_KEY_METHOD *meth,
- int (*sign)(int type, const unsigned char *dgst,
- int dlen, unsigned char *sig,
- unsigned int *siglen,
- const BIGNUM *kinv, const BIGNUM *r,
- EC_KEY *eckey),
- int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in,
- BIGNUM **kinvp, BIGNUM **rp),
- ECDSA_SIG *(*sign_sig)(const unsigned char *dgst,
- int dgst_len,
- const BIGNUM *in_kinv,
- const BIGNUM *in_r,
- EC_KEY *eckey));
-
-void EC_KEY_METHOD_set_verify(EC_KEY_METHOD *meth,
- int (*verify)(int type, const unsigned
- char *dgst, int dgst_len,
- const unsigned char *sigbuf,
- int sig_len, EC_KEY *eckey),
- int (*verify_sig)(const unsigned char *dgst,
+OSSL_DEPRECATEDIN_3_0 EC_KEY_METHOD *EC_KEY_METHOD_new(const EC_KEY_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_METHOD_free(EC_KEY_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_METHOD_set_init
+ (EC_KEY_METHOD *meth,
+ int (*init)(EC_KEY *key),
+ void (*finish)(EC_KEY *key),
+ int (*copy)(EC_KEY *dest, const EC_KEY *src),
+ int (*set_group)(EC_KEY *key, const EC_GROUP *grp),
+ int (*set_private)(EC_KEY *key, const BIGNUM *priv_key),
+ int (*set_public)(EC_KEY *key, const EC_POINT *pub_key));
+
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_METHOD_set_keygen(EC_KEY_METHOD *meth,
+ int (*keygen)(EC_KEY *key));
+
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_METHOD_set_compute_key
+ (EC_KEY_METHOD *meth,
+ int (*ckey)(unsigned char **psec, size_t *pseclen,
+ const EC_POINT *pub_key, const EC_KEY *ecdh));
+
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_METHOD_set_sign
+ (EC_KEY_METHOD *meth,
+ int (*sign)(int type, const unsigned char *dgst,
+ int dlen, unsigned char *sig,
+ unsigned int *siglen,
+ const BIGNUM *kinv, const BIGNUM *r,
+ EC_KEY *eckey),
+ int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in,
+ BIGNUM **kinvp, BIGNUM **rp),
+ ECDSA_SIG *(*sign_sig)(const unsigned char *dgst,
+ int dgst_len,
+ const BIGNUM *in_kinv,
+ const BIGNUM *in_r,
+ EC_KEY *eckey));
+
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_METHOD_set_verify
+ (EC_KEY_METHOD *meth,
+ int (*verify)(int type, const unsigned
+ char *dgst, int dgst_len,
+ const unsigned char *sigbuf,
+ int sig_len, EC_KEY *eckey),
+ int (*verify_sig)(const unsigned char *dgst,
+ int dgst_len, const ECDSA_SIG *sig,
+ EC_KEY *eckey));
+
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_METHOD_get_init
+ (const EC_KEY_METHOD *meth,
+ int (**pinit)(EC_KEY *key),
+ void (**pfinish)(EC_KEY *key),
+ int (**pcopy)(EC_KEY *dest, const EC_KEY *src),
+ int (**pset_group)(EC_KEY *key, const EC_GROUP *grp),
+ int (**pset_private)(EC_KEY *key, const BIGNUM *priv_key),
+ int (**pset_public)(EC_KEY *key, const EC_POINT *pub_key));
+
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_METHOD_get_keygen
+ (const EC_KEY_METHOD *meth, int (**pkeygen)(EC_KEY *key));
+
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_METHOD_get_compute_key
+ (const EC_KEY_METHOD *meth,
+ int (**pck)(unsigned char **psec,
+ size_t *pseclen,
+ const EC_POINT *pub_key,
+ const EC_KEY *ecdh));
+
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_METHOD_get_sign
+ (const EC_KEY_METHOD *meth,
+ int (**psign)(int type, const unsigned char *dgst,
+ int dlen, unsigned char *sig,
+ unsigned int *siglen,
+ const BIGNUM *kinv, const BIGNUM *r,
+ EC_KEY *eckey),
+ int (**psign_setup)(EC_KEY *eckey, BN_CTX *ctx_in,
+ BIGNUM **kinvp, BIGNUM **rp),
+ ECDSA_SIG *(**psign_sig)(const unsigned char *dgst,
int dgst_len,
- const ECDSA_SIG *sig,
+ const BIGNUM *in_kinv,
+ const BIGNUM *in_r,
EC_KEY *eckey));
-void EC_KEY_METHOD_get_init(const EC_KEY_METHOD *meth,
- int (**pinit)(EC_KEY *key),
- void (**pfinish)(EC_KEY *key),
- int (**pcopy)(EC_KEY *dest, const EC_KEY *src),
- int (**pset_group)(EC_KEY *key,
- const EC_GROUP *grp),
- int (**pset_private)(EC_KEY *key,
- const BIGNUM *priv_key),
- int (**pset_public)(EC_KEY *key,
- const EC_POINT *pub_key));
-
-void EC_KEY_METHOD_get_keygen(const EC_KEY_METHOD *meth,
- int (**pkeygen)(EC_KEY *key));
-
-void EC_KEY_METHOD_get_compute_key(const EC_KEY_METHOD *meth,
- int (**pck)(unsigned char **psec,
- size_t *pseclen,
- const EC_POINT *pub_key,
- const EC_KEY *ecdh));
-
-void EC_KEY_METHOD_get_sign(const EC_KEY_METHOD *meth,
- int (**psign)(int type, const unsigned char *dgst,
- int dlen, unsigned char *sig,
- unsigned int *siglen,
- const BIGNUM *kinv, const BIGNUM *r,
- EC_KEY *eckey),
- int (**psign_setup)(EC_KEY *eckey, BN_CTX *ctx_in,
- BIGNUM **kinvp, BIGNUM **rp),
- ECDSA_SIG *(**psign_sig)(const unsigned char *dgst,
- int dgst_len,
- const BIGNUM *in_kinv,
- const BIGNUM *in_r,
- EC_KEY *eckey));
-
-void EC_KEY_METHOD_get_verify(const EC_KEY_METHOD *meth,
- int (**pverify)(int type, const unsigned
- char *dgst, int dgst_len,
- const unsigned char *sigbuf,
- int sig_len, EC_KEY *eckey),
- int (**pverify_sig)(const unsigned char *dgst,
- int dgst_len,
- const ECDSA_SIG *sig,
- EC_KEY *eckey));
-
-# define ECParameters_dup(x) ASN1_dup_of(EC_KEY,i2d_ECParameters,d2i_ECParameters,x)
-
-# ifndef __cplusplus
-# if defined(__SUNPRO_C)
-# if __SUNPRO_C >= 0x520
-# pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
+OSSL_DEPRECATEDIN_3_0 void EC_KEY_METHOD_get_verify
+ (const EC_KEY_METHOD *meth,
+ int (**pverify)(int type, const unsigned
+ char *dgst, int dgst_len,
+ const unsigned char *sigbuf,
+ int sig_len, EC_KEY *eckey),
+ int (**pverify_sig)(const unsigned char *dgst,
+ int dgst_len,
+ const ECDSA_SIG *sig,
+ EC_KEY *eckey));
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
+
+# define EVP_EC_gen(curve) \
+ EVP_PKEY_Q_keygen(NULL, NULL, "EC", (char *)(strstr(curve, "")))
+ /* strstr is used to enable type checking for the variadic string arg */
+# define ECParameters_dup(x) ASN1_dup_of(EC_KEY, i2d_ECParameters, \
+ d2i_ECParameters, x)
+
+# ifndef __cplusplus
+# if defined(__SUNPRO_C)
+# if __SUNPRO_C >= 0x520
+# pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
+# endif
# endif
# endif
-# endif
-
-# define EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
- EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \
- EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL)
-
-# define EVP_PKEY_CTX_set_ec_param_enc(ctx, flag) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
- EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \
- EVP_PKEY_CTRL_EC_PARAM_ENC, flag, NULL)
-
-# define EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, flag) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_EC_ECDH_COFACTOR, flag, NULL)
-
-# define EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_EC_ECDH_COFACTOR, -2, NULL)
-
-# define EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, kdf) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL)
-
-# define EVP_PKEY_CTX_get_ecdh_kdf_type(ctx) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL)
-
-# define EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md))
-
-# define EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, pmd) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd))
-
-# define EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, len) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_EC_KDF_OUTLEN, len, NULL)
-
-# define EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, plen) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, 0, \
- (void *)(plen))
-
-# define EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p, plen) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_EC_KDF_UKM, plen, (void *)(p))
-
-# define EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
- EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0, (void *)(p))
-
-/* SM2 will skip the operation check so no need to pass operation here */
-# define EVP_PKEY_CTX_set1_id(ctx, id, id_len) \
- EVP_PKEY_CTX_ctrl(ctx, -1, -1, \
- EVP_PKEY_CTRL_SET1_ID, (int)id_len, (void*)(id))
-
-# define EVP_PKEY_CTX_get1_id(ctx, id) \
- EVP_PKEY_CTX_ctrl(ctx, -1, -1, \
- EVP_PKEY_CTRL_GET1_ID, 0, (void*)(id))
-
-# define EVP_PKEY_CTX_get1_id_len(ctx, id_len) \
- EVP_PKEY_CTX_ctrl(ctx, -1, -1, \
- EVP_PKEY_CTRL_GET1_ID_LEN, 0, (void*)(id_len))
-
-# define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1)
-# define EVP_PKEY_CTRL_EC_PARAM_ENC (EVP_PKEY_ALG_CTRL + 2)
-# define EVP_PKEY_CTRL_EC_ECDH_COFACTOR (EVP_PKEY_ALG_CTRL + 3)
-# define EVP_PKEY_CTRL_EC_KDF_TYPE (EVP_PKEY_ALG_CTRL + 4)
-# define EVP_PKEY_CTRL_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 5)
-# define EVP_PKEY_CTRL_GET_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 6)
-# define EVP_PKEY_CTRL_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 7)
-# define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 8)
-# define EVP_PKEY_CTRL_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 9)
-# define EVP_PKEY_CTRL_GET_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 10)
-# define EVP_PKEY_CTRL_SET1_ID (EVP_PKEY_ALG_CTRL + 11)
-# define EVP_PKEY_CTRL_GET1_ID (EVP_PKEY_ALG_CTRL + 12)
-# define EVP_PKEY_CTRL_GET1_ID_LEN (EVP_PKEY_ALG_CTRL + 13)
-/* KDF types */
-# define EVP_PKEY_ECDH_KDF_NONE 1
-# define EVP_PKEY_ECDH_KDF_X9_63 2
-/** The old name for EVP_PKEY_ECDH_KDF_X9_63
- * The ECDH KDF specification has been mistakingly attributed to ANSI X9.62,
- * it is actually specified in ANSI X9.63.
- * This identifier is retained for backwards compatibility
- */
-# define EVP_PKEY_ECDH_KDF_X9_62 EVP_PKEY_ECDH_KDF_X9_63
-
-# ifdef __cplusplus
+# endif
+# ifdef __cplusplus
}
-# endif
# endif
#endif
diff --git a/include/openssl/ecdh.h b/include/openssl/ecdh.h
index 681f3d5e5574..56bd4cc2ce0d 100644
--- a/include/openssl/ecdh.h
+++ b/include/openssl/ecdh.h
@@ -1,7 +1,7 @@
/*
* Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/include/openssl/ecdsa.h b/include/openssl/ecdsa.h
index 681f3d5e5574..56bd4cc2ce0d 100644
--- a/include/openssl/ecdsa.h
+++ b/include/openssl/ecdsa.h
@@ -1,7 +1,7 @@
/*
* Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/include/openssl/ecerr.h b/include/openssl/ecerr.h
index 51738113dc7d..46405ac62d91 100644
--- a/include/openssl/ecerr.h
+++ b/include/openssl/ecerr.h
@@ -1,206 +1,24 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_ECERR_H
-# define HEADER_ECERR_H
-
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+#ifndef OPENSSL_ECERR_H
+# define OPENSSL_ECERR_H
+# pragma once
# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifndef OPENSSL_NO_EC
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_EC_strings(void);
+# ifndef OPENSSL_NO_EC
-/*
- * EC function codes.
- */
-# define EC_F_BN_TO_FELEM 224
-# define EC_F_D2I_ECPARAMETERS 144
-# define EC_F_D2I_ECPKPARAMETERS 145
-# define EC_F_D2I_ECPRIVATEKEY 146
-# define EC_F_DO_EC_KEY_PRINT 221
-# define EC_F_ECDH_CMS_DECRYPT 238
-# define EC_F_ECDH_CMS_SET_SHARED_INFO 239
-# define EC_F_ECDH_COMPUTE_KEY 246
-# define EC_F_ECDH_SIMPLE_COMPUTE_KEY 257
-# define EC_F_ECDSA_DO_SIGN_EX 251
-# define EC_F_ECDSA_DO_VERIFY 252
-# define EC_F_ECDSA_SIGN_EX 254
-# define EC_F_ECDSA_SIGN_SETUP 248
-# define EC_F_ECDSA_SIG_NEW 265
-# define EC_F_ECDSA_VERIFY 253
-# define EC_F_ECD_ITEM_VERIFY 270
-# define EC_F_ECKEY_PARAM2TYPE 223
-# define EC_F_ECKEY_PARAM_DECODE 212
-# define EC_F_ECKEY_PRIV_DECODE 213
-# define EC_F_ECKEY_PRIV_ENCODE 214
-# define EC_F_ECKEY_PUB_DECODE 215
-# define EC_F_ECKEY_PUB_ENCODE 216
-# define EC_F_ECKEY_TYPE2PARAM 220
-# define EC_F_ECPARAMETERS_PRINT 147
-# define EC_F_ECPARAMETERS_PRINT_FP 148
-# define EC_F_ECPKPARAMETERS_PRINT 149
-# define EC_F_ECPKPARAMETERS_PRINT_FP 150
-# define EC_F_ECP_NISTZ256_GET_AFFINE 240
-# define EC_F_ECP_NISTZ256_INV_MOD_ORD 275
-# define EC_F_ECP_NISTZ256_MULT_PRECOMPUTE 243
-# define EC_F_ECP_NISTZ256_POINTS_MUL 241
-# define EC_F_ECP_NISTZ256_PRE_COMP_NEW 244
-# define EC_F_ECP_NISTZ256_WINDOWED_MUL 242
-# define EC_F_ECX_KEY_OP 266
-# define EC_F_ECX_PRIV_ENCODE 267
-# define EC_F_ECX_PUB_ENCODE 268
-# define EC_F_EC_ASN1_GROUP2CURVE 153
-# define EC_F_EC_ASN1_GROUP2FIELDID 154
-# define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY 208
-# define EC_F_EC_GF2M_SIMPLE_FIELD_INV 296
-# define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT 159
-# define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE 195
-# define EC_F_EC_GF2M_SIMPLE_LADDER_POST 285
-# define EC_F_EC_GF2M_SIMPLE_LADDER_PRE 288
-# define EC_F_EC_GF2M_SIMPLE_OCT2POINT 160
-# define EC_F_EC_GF2M_SIMPLE_POINT2OCT 161
-# define EC_F_EC_GF2M_SIMPLE_POINTS_MUL 289
-# define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 162
-# define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 163
-# define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES 164
-# define EC_F_EC_GFP_MONT_FIELD_DECODE 133
-# define EC_F_EC_GFP_MONT_FIELD_ENCODE 134
-# define EC_F_EC_GFP_MONT_FIELD_INV 297
-# define EC_F_EC_GFP_MONT_FIELD_MUL 131
-# define EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE 209
-# define EC_F_EC_GFP_MONT_FIELD_SQR 132
-# define EC_F_EC_GFP_MONT_GROUP_SET_CURVE 189
-# define EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE 225
-# define EC_F_EC_GFP_NISTP224_POINTS_MUL 228
-# define EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES 226
-# define EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE 230
-# define EC_F_EC_GFP_NISTP256_POINTS_MUL 231
-# define EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES 232
-# define EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE 233
-# define EC_F_EC_GFP_NISTP521_POINTS_MUL 234
-# define EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES 235
-# define EC_F_EC_GFP_NIST_FIELD_MUL 200
-# define EC_F_EC_GFP_NIST_FIELD_SQR 201
-# define EC_F_EC_GFP_NIST_GROUP_SET_CURVE 202
-# define EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES 287
-# define EC_F_EC_GFP_SIMPLE_FIELD_INV 298
-# define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT 165
-# define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE 166
-# define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE 102
-# define EC_F_EC_GFP_SIMPLE_OCT2POINT 103
-# define EC_F_EC_GFP_SIMPLE_POINT2OCT 104
-# define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE 137
-# define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES 167
-# define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES 168
-# define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES 169
-# define EC_F_EC_GROUP_CHECK 170
-# define EC_F_EC_GROUP_CHECK_DISCRIMINANT 171
-# define EC_F_EC_GROUP_COPY 106
-# define EC_F_EC_GROUP_GET_CURVE 291
-# define EC_F_EC_GROUP_GET_CURVE_GF2M 172
-# define EC_F_EC_GROUP_GET_CURVE_GFP 130
-# define EC_F_EC_GROUP_GET_DEGREE 173
-# define EC_F_EC_GROUP_GET_ECPARAMETERS 261
-# define EC_F_EC_GROUP_GET_ECPKPARAMETERS 262
-# define EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS 193
-# define EC_F_EC_GROUP_GET_TRINOMIAL_BASIS 194
-# define EC_F_EC_GROUP_NEW 108
-# define EC_F_EC_GROUP_NEW_BY_CURVE_NAME 174
-# define EC_F_EC_GROUP_NEW_FROM_DATA 175
-# define EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS 263
-# define EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS 264
-# define EC_F_EC_GROUP_SET_CURVE 292
-# define EC_F_EC_GROUP_SET_CURVE_GF2M 176
-# define EC_F_EC_GROUP_SET_CURVE_GFP 109
-# define EC_F_EC_GROUP_SET_GENERATOR 111
-# define EC_F_EC_GROUP_SET_SEED 286
-# define EC_F_EC_KEY_CHECK_KEY 177
-# define EC_F_EC_KEY_COPY 178
-# define EC_F_EC_KEY_GENERATE_KEY 179
-# define EC_F_EC_KEY_NEW 182
-# define EC_F_EC_KEY_NEW_METHOD 245
-# define EC_F_EC_KEY_OCT2PRIV 255
-# define EC_F_EC_KEY_PRINT 180
-# define EC_F_EC_KEY_PRINT_FP 181
-# define EC_F_EC_KEY_PRIV2BUF 279
-# define EC_F_EC_KEY_PRIV2OCT 256
-# define EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES 229
-# define EC_F_EC_KEY_SIMPLE_CHECK_KEY 258
-# define EC_F_EC_KEY_SIMPLE_OCT2PRIV 259
-# define EC_F_EC_KEY_SIMPLE_PRIV2OCT 260
-# define EC_F_EC_PKEY_CHECK 273
-# define EC_F_EC_PKEY_PARAM_CHECK 274
-# define EC_F_EC_POINTS_MAKE_AFFINE 136
-# define EC_F_EC_POINTS_MUL 290
-# define EC_F_EC_POINT_ADD 112
-# define EC_F_EC_POINT_BN2POINT 280
-# define EC_F_EC_POINT_CMP 113
-# define EC_F_EC_POINT_COPY 114
-# define EC_F_EC_POINT_DBL 115
-# define EC_F_EC_POINT_GET_AFFINE_COORDINATES 293
-# define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M 183
-# define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP 116
-# define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP 117
-# define EC_F_EC_POINT_INVERT 210
-# define EC_F_EC_POINT_IS_AT_INFINITY 118
-# define EC_F_EC_POINT_IS_ON_CURVE 119
-# define EC_F_EC_POINT_MAKE_AFFINE 120
-# define EC_F_EC_POINT_NEW 121
-# define EC_F_EC_POINT_OCT2POINT 122
-# define EC_F_EC_POINT_POINT2BUF 281
-# define EC_F_EC_POINT_POINT2OCT 123
-# define EC_F_EC_POINT_SET_AFFINE_COORDINATES 294
-# define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M 185
-# define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP 124
-# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES 295
-# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M 186
-# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP 125
-# define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP 126
-# define EC_F_EC_POINT_SET_TO_INFINITY 127
-# define EC_F_EC_PRE_COMP_NEW 196
-# define EC_F_EC_SCALAR_MUL_LADDER 284
-# define EC_F_EC_WNAF_MUL 187
-# define EC_F_EC_WNAF_PRECOMPUTE_MULT 188
-# define EC_F_I2D_ECPARAMETERS 190
-# define EC_F_I2D_ECPKPARAMETERS 191
-# define EC_F_I2D_ECPRIVATEKEY 192
-# define EC_F_I2O_ECPUBLICKEY 151
-# define EC_F_NISTP224_PRE_COMP_NEW 227
-# define EC_F_NISTP256_PRE_COMP_NEW 236
-# define EC_F_NISTP521_PRE_COMP_NEW 237
-# define EC_F_O2I_ECPUBLICKEY 152
-# define EC_F_OLD_EC_PRIV_DECODE 222
-# define EC_F_OSSL_ECDH_COMPUTE_KEY 247
-# define EC_F_OSSL_ECDSA_SIGN_SIG 249
-# define EC_F_OSSL_ECDSA_VERIFY_SIG 250
-# define EC_F_PKEY_ECD_CTRL 271
-# define EC_F_PKEY_ECD_DIGESTSIGN 272
-# define EC_F_PKEY_ECD_DIGESTSIGN25519 276
-# define EC_F_PKEY_ECD_DIGESTSIGN448 277
-# define EC_F_PKEY_ECX_DERIVE 269
-# define EC_F_PKEY_EC_CTRL 197
-# define EC_F_PKEY_EC_CTRL_STR 198
-# define EC_F_PKEY_EC_DERIVE 217
-# define EC_F_PKEY_EC_INIT 282
-# define EC_F_PKEY_EC_KDF_DERIVE 283
-# define EC_F_PKEY_EC_KEYGEN 199
-# define EC_F_PKEY_EC_PARAMGEN 219
-# define EC_F_PKEY_EC_SIGN 218
-# define EC_F_VALIDATE_ECX_DERIVE 278
/*
* EC reason codes.
@@ -212,17 +30,22 @@ int ERR_load_EC_strings(void);
# define EC_R_CANNOT_INVERT 165
# define EC_R_COORDINATES_OUT_OF_RANGE 146
# define EC_R_CURVE_DOES_NOT_SUPPORT_ECDH 160
+# define EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA 170
# define EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING 159
-# define EC_R_D2I_ECPKPARAMETERS_FAILURE 117
# define EC_R_DECODE_ERROR 142
# define EC_R_DISCRIMINANT_IS_ZERO 118
# define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119
+# define EC_R_EXPLICIT_PARAMS_NOT_SUPPORTED 127
+# define EC_R_FAILED_MAKING_PUBLIC_KEY 166
# define EC_R_FIELD_TOO_LARGE 143
# define EC_R_GF2M_NOT_SUPPORTED 147
# define EC_R_GROUP2PKPARAMETERS_FAILURE 120
# define EC_R_I2D_ECPKPARAMETERS_FAILURE 121
# define EC_R_INCOMPATIBLE_OBJECTS 101
+# define EC_R_INVALID_A 168
# define EC_R_INVALID_ARGUMENT 112
+# define EC_R_INVALID_B 169
+# define EC_R_INVALID_COFACTOR 171
# define EC_R_INVALID_COMPRESSED_POINT 110
# define EC_R_INVALID_COMPRESSION_BIT 109
# define EC_R_INVALID_CURVE 141
@@ -231,12 +54,17 @@ int ERR_load_EC_strings(void);
# define EC_R_INVALID_ENCODING 102
# define EC_R_INVALID_FIELD 103
# define EC_R_INVALID_FORM 104
+# define EC_R_INVALID_GENERATOR 173
# define EC_R_INVALID_GROUP_ORDER 122
# define EC_R_INVALID_KEY 116
+# define EC_R_INVALID_LENGTH 117
+# define EC_R_INVALID_NAMED_GROUP_CONVERSION 174
# define EC_R_INVALID_OUTPUT_LENGTH 161
+# define EC_R_INVALID_P 172
# define EC_R_INVALID_PEER_KEY 133
# define EC_R_INVALID_PENTANOMIAL_BASIS 132
# define EC_R_INVALID_PRIVATE_KEY 123
+# define EC_R_INVALID_SEED 175
# define EC_R_INVALID_TRINOMIAL_BASIS 137
# define EC_R_KDF_PARAMETER_ERROR 148
# define EC_R_KEYS_NOT_SET 140
@@ -255,7 +83,6 @@ int ERR_load_EC_strings(void);
# define EC_R_OPERATION_NOT_SUPPORTED 152
# define EC_R_PASSED_NULL_PARAMETER 134
# define EC_R_PEER_KEY_ERROR 149
-# define EC_R_PKPARAMETERS2GROUP_FAILURE 127
# define EC_R_POINT_ARITHMETIC_FAILURE 155
# define EC_R_POINT_AT_INFINITY 106
# define EC_R_POINT_COORDINATES_BLIND_FAILURE 163
diff --git a/include/openssl/encoder.h b/include/openssl/encoder.h
new file mode 100644
index 000000000000..c37a6f16f23c
--- /dev/null
+++ b/include/openssl/encoder.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_ENCODER_H
+# define OPENSSL_ENCODER_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+
+# ifndef OPENSSL_NO_STDIO
+# include <stdio.h>
+# endif
+# include <stdarg.h>
+# include <stddef.h>
+# include <openssl/encodererr.h>
+# include <openssl/types.h>
+# include <openssl/core.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+OSSL_ENCODER *OSSL_ENCODER_fetch(OSSL_LIB_CTX *libctx, const char *name,
+ const char *properties);
+int OSSL_ENCODER_up_ref(OSSL_ENCODER *encoder);
+void OSSL_ENCODER_free(OSSL_ENCODER *encoder);
+
+const OSSL_PROVIDER *OSSL_ENCODER_get0_provider(const OSSL_ENCODER *encoder);
+const char *OSSL_ENCODER_get0_properties(const OSSL_ENCODER *encoder);
+const char *OSSL_ENCODER_get0_name(const OSSL_ENCODER *kdf);
+const char *OSSL_ENCODER_get0_description(const OSSL_ENCODER *kdf);
+int OSSL_ENCODER_is_a(const OSSL_ENCODER *encoder, const char *name);
+
+void OSSL_ENCODER_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(OSSL_ENCODER *encoder, void *arg),
+ void *arg);
+int OSSL_ENCODER_names_do_all(const OSSL_ENCODER *encoder,
+ void (*fn)(const char *name, void *data),
+ void *data);
+const OSSL_PARAM *OSSL_ENCODER_gettable_params(OSSL_ENCODER *encoder);
+int OSSL_ENCODER_get_params(OSSL_ENCODER *encoder, OSSL_PARAM params[]);
+
+const OSSL_PARAM *OSSL_ENCODER_settable_ctx_params(OSSL_ENCODER *encoder);
+OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new(void);
+int OSSL_ENCODER_CTX_set_params(OSSL_ENCODER_CTX *ctx,
+ const OSSL_PARAM params[]);
+void OSSL_ENCODER_CTX_free(OSSL_ENCODER_CTX *ctx);
+
+/* Utilities that help set specific parameters */
+int OSSL_ENCODER_CTX_set_passphrase(OSSL_ENCODER_CTX *ctx,
+ const unsigned char *kstr, size_t klen);
+int OSSL_ENCODER_CTX_set_pem_password_cb(OSSL_ENCODER_CTX *ctx,
+ pem_password_cb *cb, void *cbarg);
+int OSSL_ENCODER_CTX_set_passphrase_cb(OSSL_ENCODER_CTX *ctx,
+ OSSL_PASSPHRASE_CALLBACK *cb,
+ void *cbarg);
+int OSSL_ENCODER_CTX_set_passphrase_ui(OSSL_ENCODER_CTX *ctx,
+ const UI_METHOD *ui_method,
+ void *ui_data);
+int OSSL_ENCODER_CTX_set_cipher(OSSL_ENCODER_CTX *ctx,
+ const char *cipher_name,
+ const char *propquery);
+int OSSL_ENCODER_CTX_set_selection(OSSL_ENCODER_CTX *ctx, int selection);
+int OSSL_ENCODER_CTX_set_output_type(OSSL_ENCODER_CTX *ctx,
+ const char *output_type);
+int OSSL_ENCODER_CTX_set_output_structure(OSSL_ENCODER_CTX *ctx,
+ const char *output_structure);
+
+/* Utilities to add encoders */
+int OSSL_ENCODER_CTX_add_encoder(OSSL_ENCODER_CTX *ctx, OSSL_ENCODER *encoder);
+int OSSL_ENCODER_CTX_add_extra(OSSL_ENCODER_CTX *ctx,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int OSSL_ENCODER_CTX_get_num_encoders(OSSL_ENCODER_CTX *ctx);
+
+typedef struct ossl_encoder_instance_st OSSL_ENCODER_INSTANCE;
+OSSL_ENCODER *
+OSSL_ENCODER_INSTANCE_get_encoder(OSSL_ENCODER_INSTANCE *encoder_inst);
+void *
+OSSL_ENCODER_INSTANCE_get_encoder_ctx(OSSL_ENCODER_INSTANCE *encoder_inst);
+const char *
+OSSL_ENCODER_INSTANCE_get_output_type(OSSL_ENCODER_INSTANCE *encoder_inst);
+const char *
+OSSL_ENCODER_INSTANCE_get_output_structure(OSSL_ENCODER_INSTANCE *encoder_inst);
+
+typedef const void *OSSL_ENCODER_CONSTRUCT(OSSL_ENCODER_INSTANCE *encoder_inst,
+ void *construct_data);
+typedef void OSSL_ENCODER_CLEANUP(void *construct_data);
+
+int OSSL_ENCODER_CTX_set_construct(OSSL_ENCODER_CTX *ctx,
+ OSSL_ENCODER_CONSTRUCT *construct);
+int OSSL_ENCODER_CTX_set_construct_data(OSSL_ENCODER_CTX *ctx,
+ void *construct_data);
+int OSSL_ENCODER_CTX_set_cleanup(OSSL_ENCODER_CTX *ctx,
+ OSSL_ENCODER_CLEANUP *cleanup);
+
+/* Utilities to output the object to encode */
+int OSSL_ENCODER_to_bio(OSSL_ENCODER_CTX *ctx, BIO *out);
+#ifndef OPENSSL_NO_STDIO
+int OSSL_ENCODER_to_fp(OSSL_ENCODER_CTX *ctx, FILE *fp);
+#endif
+int OSSL_ENCODER_to_data(OSSL_ENCODER_CTX *ctx, unsigned char **pdata,
+ size_t *pdata_len);
+
+/*
+ * Create the OSSL_ENCODER_CTX with an associated type. This will perform
+ * an implicit OSSL_ENCODER_fetch(), suitable for the object of that type.
+ * This is more useful than calling OSSL_ENCODER_CTX_new().
+ */
+OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new_for_pkey(const EVP_PKEY *pkey,
+ int selection,
+ const char *output_type,
+ const char *output_struct,
+ const char *propquery);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/encodererr.h b/include/openssl/encodererr.h
new file mode 100644
index 000000000000..5e318b145370
--- /dev/null
+++ b/include/openssl/encodererr.h
@@ -0,0 +1,28 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_ENCODERERR_H
+# define OPENSSL_ENCODERERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
+
+
+
+/*
+ * OSSL_ENCODER reason codes.
+ */
+# define OSSL_ENCODER_R_ENCODER_NOT_FOUND 101
+# define OSSL_ENCODER_R_INCORRECT_PROPERTY_QUERY 100
+# define OSSL_ENCODER_R_MISSING_GET_PARAMS 102
+
+#endif
diff --git a/include/openssl/engine.h b/include/openssl/engine.h
index d707eaeb6ee3..c96580085555 100644
--- a/include/openssl/engine.h
+++ b/include/openssl/engine.h
@@ -2,52 +2,58 @@
* Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_ENGINE_H
-# define HEADER_ENGINE_H
+#ifndef OPENSSL_ENGINE_H
+# define OPENSSL_ENGINE_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_ENGINE_H
+# endif
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_ENGINE
-# if OPENSSL_API_COMPAT < 0x10100000L
-# include <openssl/bn.h>
-# include <openssl/rsa.h>
-# include <openssl/dsa.h>
-# include <openssl/dh.h>
-# include <openssl/ec.h>
-# include <openssl/rand.h>
-# include <openssl/ui.h>
-# include <openssl/err.h>
-# endif
-# include <openssl/ossl_typ.h>
-# include <openssl/symhacks.h>
-# include <openssl/x509.h>
-# include <openssl/engineerr.h>
-# ifdef __cplusplus
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# include <openssl/bn.h>
+# include <openssl/rsa.h>
+# include <openssl/dsa.h>
+# include <openssl/dh.h>
+# include <openssl/ec.h>
+# include <openssl/rand.h>
+# include <openssl/ui.h>
+# include <openssl/err.h>
+# endif
+# include <openssl/types.h>
+# include <openssl/symhacks.h>
+# include <openssl/x509.h>
+# include <openssl/engineerr.h>
+# ifdef __cplusplus
extern "C" {
-# endif
+# endif
/*
* These flags are used to control combinations of algorithm (methods) by
* bitwise "OR"ing.
*/
-# define ENGINE_METHOD_RSA (unsigned int)0x0001
-# define ENGINE_METHOD_DSA (unsigned int)0x0002
-# define ENGINE_METHOD_DH (unsigned int)0x0004
-# define ENGINE_METHOD_RAND (unsigned int)0x0008
-# define ENGINE_METHOD_CIPHERS (unsigned int)0x0040
-# define ENGINE_METHOD_DIGESTS (unsigned int)0x0080
-# define ENGINE_METHOD_PKEY_METHS (unsigned int)0x0200
-# define ENGINE_METHOD_PKEY_ASN1_METHS (unsigned int)0x0400
-# define ENGINE_METHOD_EC (unsigned int)0x0800
+# define ENGINE_METHOD_RSA (unsigned int)0x0001
+# define ENGINE_METHOD_DSA (unsigned int)0x0002
+# define ENGINE_METHOD_DH (unsigned int)0x0004
+# define ENGINE_METHOD_RAND (unsigned int)0x0008
+# define ENGINE_METHOD_CIPHERS (unsigned int)0x0040
+# define ENGINE_METHOD_DIGESTS (unsigned int)0x0080
+# define ENGINE_METHOD_PKEY_METHS (unsigned int)0x0200
+# define ENGINE_METHOD_PKEY_ASN1_METHS (unsigned int)0x0400
+# define ENGINE_METHOD_EC (unsigned int)0x0800
/* Obvious all-or-nothing cases. */
-# define ENGINE_METHOD_ALL (unsigned int)0xFFFF
-# define ENGINE_METHOD_NONE (unsigned int)0x0000
+# define ENGINE_METHOD_ALL (unsigned int)0xFFFF
+# define ENGINE_METHOD_NONE (unsigned int)0x0000
/*
* This(ese) flag(s) controls behaviour of the ENGINE_TABLE mechanism used
@@ -55,7 +61,7 @@ extern "C" {
* set by ENGINE_set_table_flags(). The "NOINIT" flag prevents attempts to
* initialise registered ENGINEs if they are not already initialised.
*/
-# define ENGINE_TABLE_FLAG_NOINIT (unsigned int)0x0001
+# define ENGINE_TABLE_FLAG_NOINIT (unsigned int)0x0001
/* ENGINE flags that can be set by ENGINE_set_flags(). */
/* Not used */
@@ -67,7 +73,7 @@ extern "C" {
* these control commands on behalf of the ENGINE using their "cmd_defns"
* data.
*/
-# define ENGINE_FLAGS_MANUAL_CMD_CTRL (int)0x0002
+# define ENGINE_FLAGS_MANUAL_CMD_CTRL (int)0x0002
/*
* This flag is for ENGINEs who return new duplicate structures when found
@@ -79,7 +85,7 @@ extern "C" {
* ENGINE_by_id() just increments the existing ENGINE's structural reference
* count.
*/
-# define ENGINE_FLAGS_BY_ID_COPY (int)0x0004
+# define ENGINE_FLAGS_BY_ID_COPY (int)0x0004
/*
* This flag if for an ENGINE that does not want its methods registered as
@@ -87,7 +93,7 @@ extern "C" {
* usable as default methods.
*/
-# define ENGINE_FLAGS_NO_REGISTER_ALL (int)0x0008
+# define ENGINE_FLAGS_NO_REGISTER_ALL (int)0x0008
/*
* ENGINEs can support their own command types, and these flags are used in
@@ -102,23 +108,23 @@ extern "C" {
*/
/* accepts a 'long' input value (3rd parameter to ENGINE_ctrl) */
-# define ENGINE_CMD_FLAG_NUMERIC (unsigned int)0x0001
+# define ENGINE_CMD_FLAG_NUMERIC (unsigned int)0x0001
/*
* accepts string input (cast from 'void*' to 'const char *', 4th parameter
* to ENGINE_ctrl)
*/
-# define ENGINE_CMD_FLAG_STRING (unsigned int)0x0002
+# define ENGINE_CMD_FLAG_STRING (unsigned int)0x0002
/*
* Indicates that the control command takes *no* input. Ie. the control
* command is unparameterised.
*/
-# define ENGINE_CMD_FLAG_NO_INPUT (unsigned int)0x0004
+# define ENGINE_CMD_FLAG_NO_INPUT (unsigned int)0x0004
/*
* Indicates that the control command is internal. This control command won't
* be shown in any output, and is only usable through the ENGINE_ctrl_cmd()
* function.
*/
-# define ENGINE_CMD_FLAG_INTERNAL (unsigned int)0x0008
+# define ENGINE_CMD_FLAG_INTERNAL (unsigned int)0x0008
/*
* NB: These 3 control commands are deprecated and should not be used.
@@ -137,21 +143,21 @@ extern "C" {
* sense to some engines. In such a case, they do nothing but return the
* error ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED.
*/
-# define ENGINE_CTRL_SET_LOGSTREAM 1
-# define ENGINE_CTRL_SET_PASSWORD_CALLBACK 2
-# define ENGINE_CTRL_HUP 3/* Close and reinitialise
+# define ENGINE_CTRL_SET_LOGSTREAM 1
+# define ENGINE_CTRL_SET_PASSWORD_CALLBACK 2
+# define ENGINE_CTRL_HUP 3/* Close and reinitialise
* any handles/connections
* etc. */
-# define ENGINE_CTRL_SET_USER_INTERFACE 4/* Alternative to callback */
-# define ENGINE_CTRL_SET_CALLBACK_DATA 5/* User-specific data, used
+# define ENGINE_CTRL_SET_USER_INTERFACE 4/* Alternative to callback */
+# define ENGINE_CTRL_SET_CALLBACK_DATA 5/* User-specific data, used
* when calling the password
* callback and the user
* interface */
-# define ENGINE_CTRL_LOAD_CONFIGURATION 6/* Load a configuration,
+# define ENGINE_CTRL_LOAD_CONFIGURATION 6/* Load a configuration,
* given a string that
* represents a file name
* or so */
-# define ENGINE_CTRL_LOAD_SECTION 7/* Load data from a given
+# define ENGINE_CTRL_LOAD_SECTION 7/* Load data from a given
* section in the already
* loaded configuration */
@@ -175,22 +181,22 @@ extern "C" {
* worth checking this first if the caller is trying to "discover" the
* engine's capabilities and doesn't want errors generated unnecessarily.
*/
-# define ENGINE_CTRL_HAS_CTRL_FUNCTION 10
+# define ENGINE_CTRL_HAS_CTRL_FUNCTION 10
/*
* Returns a positive command number for the first command supported by the
* engine. Returns zero if no ctrl commands are supported.
*/
-# define ENGINE_CTRL_GET_FIRST_CMD_TYPE 11
+# define ENGINE_CTRL_GET_FIRST_CMD_TYPE 11
/*
* The 'long' argument specifies a command implemented by the engine, and the
* return value is the next command supported, or zero if there are no more.
*/
-# define ENGINE_CTRL_GET_NEXT_CMD_TYPE 12
+# define ENGINE_CTRL_GET_NEXT_CMD_TYPE 12
/*
* The 'void*' argument is a command name (cast from 'const char *'), and the
* return value is the command that corresponds to it.
*/
-# define ENGINE_CTRL_GET_CMD_FROM_NAME 13
+# define ENGINE_CTRL_GET_CMD_FROM_NAME 13
/*
* The next two allow a command to be converted into its corresponding string
* form. In each case, the 'long' argument supplies the command. In the
@@ -199,23 +205,23 @@ extern "C" {
* string buffer large enough, and it will be populated with the name of the
* command (WITH a trailing EOL).
*/
-# define ENGINE_CTRL_GET_NAME_LEN_FROM_CMD 14
-# define ENGINE_CTRL_GET_NAME_FROM_CMD 15
+# define ENGINE_CTRL_GET_NAME_LEN_FROM_CMD 14
+# define ENGINE_CTRL_GET_NAME_FROM_CMD 15
/* The next two are similar but give a "short description" of a command. */
-# define ENGINE_CTRL_GET_DESC_LEN_FROM_CMD 16
-# define ENGINE_CTRL_GET_DESC_FROM_CMD 17
+# define ENGINE_CTRL_GET_DESC_LEN_FROM_CMD 16
+# define ENGINE_CTRL_GET_DESC_FROM_CMD 17
/*
* With this command, the return value is the OR'd combination of
* ENGINE_CMD_FLAG_*** values that indicate what kind of input a given
* engine-specific ctrl command expects.
*/
-# define ENGINE_CTRL_GET_CMD_FLAGS 18
+# define ENGINE_CTRL_GET_CMD_FLAGS 18
/*
* ENGINE implementations should start the numbering of their own control
* commands from this value. (ie. ENGINE_CMD_BASE, ENGINE_CMD_BASE + 1, etc).
*/
-# define ENGINE_CMD_BASE 200
+# define ENGINE_CMD_BASE 200
/*
* NB: These 2 nCipher "chil" control commands are deprecated, and their
@@ -226,17 +232,17 @@ extern "C" {
*/
/* Flags specific to the nCipher "chil" engine */
-# define ENGINE_CTRL_CHIL_SET_FORKCHECK 100
- /*
- * Depending on the value of the (long)i argument, this sets or
- * unsets the SimpleForkCheck flag in the CHIL API to enable or
- * disable checking and workarounds for applications that fork().
- */
-# define ENGINE_CTRL_CHIL_NO_LOCKING 101
- /*
- * This prevents the initialisation function from providing mutex
- * callbacks to the nCipher library.
- */
+# define ENGINE_CTRL_CHIL_SET_FORKCHECK 100
+ /*
+ * Depending on the value of the (long)i argument, this sets or
+ * unsets the SimpleForkCheck flag in the CHIL API to enable or
+ * disable checking and workarounds for applications that fork().
+ */
+# define ENGINE_CTRL_CHIL_NO_LOCKING 101
+ /*
+ * This prevents the initialisation function from providing mutex
+ * callbacks to the nCipher library.
+ */
/*
* If an ENGINE supports its own specific control commands and wishes the
@@ -308,44 +314,58 @@ typedef int (*ENGINE_PKEY_ASN1_METHS_PTR) (ENGINE *, EVP_PKEY_ASN1_METHOD **,
*/
/* Get the first/last "ENGINE" type available. */
-ENGINE *ENGINE_get_first(void);
-ENGINE *ENGINE_get_last(void);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_get_first(void);
+OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_get_last(void);
+# endif
/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
-ENGINE *ENGINE_get_next(ENGINE *e);
-ENGINE *ENGINE_get_prev(ENGINE *e);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_get_next(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_get_prev(ENGINE *e);
+# endif
/* Add another "ENGINE" type into the array. */
-int ENGINE_add(ENGINE *e);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int ENGINE_add(ENGINE *e);
+# endif
/* Remove an existing "ENGINE" type from the array. */
-int ENGINE_remove(ENGINE *e);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int ENGINE_remove(ENGINE *e);
+# endif
/* Retrieve an engine from the list by its unique "id" value. */
-ENGINE *ENGINE_by_id(const char *id);
-
-#if OPENSSL_API_COMPAT < 0x10100000L
-# define ENGINE_load_openssl() \
- OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_OPENSSL, NULL)
-# define ENGINE_load_dynamic() \
- OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_DYNAMIC, NULL)
-# ifndef OPENSSL_NO_STATIC_ENGINE
-# define ENGINE_load_padlock() \
- OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_PADLOCK, NULL)
-# define ENGINE_load_capi() \
- OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_CAPI, NULL)
-# define ENGINE_load_afalg() \
- OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_AFALG, NULL)
-# endif
-# define ENGINE_load_cryptodev() \
- OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_CRYPTODEV, NULL)
-# define ENGINE_load_rdrand() \
- OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_RDRAND, NULL)
-#endif
-void ENGINE_load_builtin_engines(void);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_by_id(const char *id);
+# endif
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define ENGINE_load_openssl() \
+ OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_OPENSSL, NULL)
+# define ENGINE_load_dynamic() \
+ OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_DYNAMIC, NULL)
+# ifndef OPENSSL_NO_STATIC_ENGINE
+# define ENGINE_load_padlock() \
+ OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_PADLOCK, NULL)
+# define ENGINE_load_capi() \
+ OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_CAPI, NULL)
+# define ENGINE_load_afalg() \
+ OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_AFALG, NULL)
+# endif
+# define ENGINE_load_cryptodev() \
+ OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_CRYPTODEV, NULL)
+# define ENGINE_load_rdrand() \
+ OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_RDRAND, NULL)
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 void ENGINE_load_builtin_engines(void);
+# endif
/*
* Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation
* "registry" handling.
*/
-unsigned int ENGINE_get_table_flags(void);
-void ENGINE_set_table_flags(unsigned int flags);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 unsigned int ENGINE_get_table_flags(void);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_set_table_flags(unsigned int flags);
+# endif
/*- Manage registration of ENGINEs per "table". For each type, there are 3
* functions;
@@ -354,42 +374,35 @@ void ENGINE_set_table_flags(unsigned int flags);
* ENGINE_register_all_***() - call ENGINE_register_***() for each 'e' in the list
* Cleanup is automatically registered from each table when required.
*/
-
-int ENGINE_register_RSA(ENGINE *e);
-void ENGINE_unregister_RSA(ENGINE *e);
-void ENGINE_register_all_RSA(void);
-
-int ENGINE_register_DSA(ENGINE *e);
-void ENGINE_unregister_DSA(ENGINE *e);
-void ENGINE_register_all_DSA(void);
-
-int ENGINE_register_EC(ENGINE *e);
-void ENGINE_unregister_EC(ENGINE *e);
-void ENGINE_register_all_EC(void);
-
-int ENGINE_register_DH(ENGINE *e);
-void ENGINE_unregister_DH(ENGINE *e);
-void ENGINE_register_all_DH(void);
-
-int ENGINE_register_RAND(ENGINE *e);
-void ENGINE_unregister_RAND(ENGINE *e);
-void ENGINE_register_all_RAND(void);
-
-int ENGINE_register_ciphers(ENGINE *e);
-void ENGINE_unregister_ciphers(ENGINE *e);
-void ENGINE_register_all_ciphers(void);
-
-int ENGINE_register_digests(ENGINE *e);
-void ENGINE_unregister_digests(ENGINE *e);
-void ENGINE_register_all_digests(void);
-
-int ENGINE_register_pkey_meths(ENGINE *e);
-void ENGINE_unregister_pkey_meths(ENGINE *e);
-void ENGINE_register_all_pkey_meths(void);
-
-int ENGINE_register_pkey_asn1_meths(ENGINE *e);
-void ENGINE_unregister_pkey_asn1_meths(ENGINE *e);
-void ENGINE_register_all_pkey_asn1_meths(void);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int ENGINE_register_RSA(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_unregister_RSA(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_register_all_RSA(void);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_register_DSA(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_unregister_DSA(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_register_all_DSA(void);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_register_EC(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_unregister_EC(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_register_all_EC(void);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_register_DH(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_unregister_DH(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_register_all_DH(void);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_register_RAND(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_unregister_RAND(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_register_all_RAND(void);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_register_ciphers(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_unregister_ciphers(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_register_all_ciphers(void);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_register_digests(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_unregister_digests(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_register_all_digests(void);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_register_pkey_meths(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_unregister_pkey_meths(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_register_all_pkey_meths(void);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_register_pkey_asn1_meths(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_unregister_pkey_asn1_meths(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_register_all_pkey_asn1_meths(void);
+# endif
/*
* These functions register all support from the above categories. Note, use
@@ -397,8 +410,10 @@ void ENGINE_register_all_pkey_asn1_meths(void);
* may not need. If you only need a subset of functionality, consider using
* more selective initialisation.
*/
-int ENGINE_register_complete(ENGINE *e);
-int ENGINE_register_all_complete(void);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int ENGINE_register_complete(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_register_all_complete(void);
+# endif
/*
* Send parameterised control commands to the engine. The possibilities to
@@ -410,7 +425,10 @@ int ENGINE_register_all_complete(void);
* commands that require an operational ENGINE, and only use functional
* references in such situations.
*/
-int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void));
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p,
+ void (*f) (void));
+# endif
/*
* This function tests if an ENGINE-specific command is usable as a
@@ -418,7 +436,9 @@ int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void));
* ENGINE_ctrl_cmd_string(). If this returns zero, it is not available to
* ENGINE_ctrl_cmd_string(), only ENGINE_ctrl().
*/
-int ENGINE_cmd_is_executable(ENGINE *e, int cmd);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int ENGINE_cmd_is_executable(ENGINE *e, int cmd);
+# endif
/*
* This function works like ENGINE_ctrl() with the exception of taking a
@@ -426,8 +446,11 @@ int ENGINE_cmd_is_executable(ENGINE *e, int cmd);
* commands. See the comment on ENGINE_ctrl_cmd_string() for an explanation
* on how to use the cmd_name and cmd_optional.
*/
-int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name,
- long i, void *p, void (*f) (void), int cmd_optional);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name,
+ long i, void *p, void (*f) (void),
+ int cmd_optional);
+# endif
/*
* This function passes a command-name and argument to an ENGINE. The
@@ -451,8 +474,11 @@ int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name,
* applications can work consistently with the same configuration for the
* same ENGINE-enabled devices, across applications.
*/
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
int cmd_optional);
+# endif
/*
* These functions are useful for manufacturing new ENGINE structures. They
@@ -462,45 +488,59 @@ int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
* These are also here so that the ENGINE structure doesn't have to be
* exposed and break binary compatibility!
*/
-ENGINE *ENGINE_new(void);
-int ENGINE_free(ENGINE *e);
-int ENGINE_up_ref(ENGINE *e);
-int ENGINE_set_id(ENGINE *e, const char *id);
-int ENGINE_set_name(ENGINE *e, const char *name);
-int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth);
-int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth);
-int ENGINE_set_EC(ENGINE *e, const EC_KEY_METHOD *ecdsa_meth);
-int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth);
-int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth);
-int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_new(void);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_free(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_up_ref(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_id(ENGINE *e, const char *id);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_name(ENGINE *e, const char *name);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_EC(ENGINE *e, const EC_KEY_METHOD *ecdsa_meth);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth);
+OSSL_DEPRECATEDIN_3_0
+int ENGINE_set_destroy_function(ENGINE *e,ENGINE_GEN_INT_FUNC_PTR destroy_f);
+OSSL_DEPRECATEDIN_3_0
int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f);
+OSSL_DEPRECATEDIN_3_0
int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f);
+OSSL_DEPRECATEDIN_3_0
int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f);
-int ENGINE_set_load_privkey_function(ENGINE *e,
- ENGINE_LOAD_KEY_PTR loadpriv_f);
+OSSL_DEPRECATEDIN_3_0
+int ENGINE_set_load_privkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpriv_f);
+OSSL_DEPRECATEDIN_3_0
int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f);
+OSSL_DEPRECATEDIN_3_0
int ENGINE_set_load_ssl_client_cert_function(ENGINE *e,
- ENGINE_SSL_CLIENT_CERT_PTR
- loadssl_f);
+ ENGINE_SSL_CLIENT_CERT_PTR loadssl_f);
+OSSL_DEPRECATEDIN_3_0
int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f);
+OSSL_DEPRECATEDIN_3_0
int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f);
+OSSL_DEPRECATEDIN_3_0
int ENGINE_set_pkey_meths(ENGINE *e, ENGINE_PKEY_METHS_PTR f);
+OSSL_DEPRECATEDIN_3_0
int ENGINE_set_pkey_asn1_meths(ENGINE *e, ENGINE_PKEY_ASN1_METHS_PTR f);
-int ENGINE_set_flags(ENGINE *e, int flags);
-int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_flags(ENGINE *e, int flags);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_cmd_defns(ENGINE *e,
+ const ENGINE_CMD_DEFN *defns);
+# endif
/* These functions allow control over any per-structure ENGINE data. */
-#define ENGINE_get_ex_new_index(l, p, newf, dupf, freef) \
+# define ENGINE_get_ex_new_index(l, p, newf, dupf, freef) \
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_ENGINE, l, p, newf, dupf, freef)
-int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg);
-void *ENGINE_get_ex_data(const ENGINE *e, int idx);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg);
+OSSL_DEPRECATEDIN_3_0 void *ENGINE_get_ex_data(const ENGINE *e, int idx);
+# endif
-#if OPENSSL_API_COMPAT < 0x10100000L
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
/*
* This function previously cleaned up anything that needs it. Auto-deinit will
* now take care of it so it is no longer required to call this function.
*/
-# define ENGINE_cleanup() while(0) continue
-#endif
+# define ENGINE_cleanup() while(0) continue
+# endif
/*
* These return values from within the ENGINE structure. These can be useful
@@ -508,37 +548,55 @@ void *ENGINE_get_ex_data(const ENGINE *e, int idx);
* which you obtained. Using the result for functional purposes if you only
* obtained a structural reference may be problematic!
*/
-const char *ENGINE_get_id(const ENGINE *e);
-const char *ENGINE_get_name(const ENGINE *e);
-const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e);
-const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e);
-const EC_KEY_METHOD *ENGINE_get_EC(const ENGINE *e);
-const DH_METHOD *ENGINE_get_DH(const ENGINE *e);
-const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 const char *ENGINE_get_id(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 const char *ENGINE_get_name(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 const EC_KEY_METHOD *ENGINE_get_EC(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 const DH_METHOD *ENGINE_get_DH(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0
ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0
ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0
ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0
ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0
ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0
ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e);
-ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE
- *e);
+OSSL_DEPRECATEDIN_3_0
+ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0
ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0
ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0
ENGINE_PKEY_METHS_PTR ENGINE_get_pkey_meths(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0
ENGINE_PKEY_ASN1_METHS_PTR ENGINE_get_pkey_asn1_meths(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0
const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid);
+OSSL_DEPRECATEDIN_3_0
const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid);
+OSSL_DEPRECATEDIN_3_0
const EVP_PKEY_METHOD *ENGINE_get_pkey_meth(ENGINE *e, int nid);
+OSSL_DEPRECATEDIN_3_0
const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid);
+OSSL_DEPRECATEDIN_3_0
const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e,
const char *str,
int len);
+OSSL_DEPRECATEDIN_3_0
const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe,
- const char *str,
- int len);
+ const char *str, int len);
+OSSL_DEPRECATEDIN_3_0
const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e);
-int ENGINE_get_flags(const ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_get_flags(const ENGINE *e);
+# endif
/*
* FUNCTIONAL functions. These functions deal with ENGINE structures that
@@ -558,27 +616,36 @@ int ENGINE_get_flags(const ENGINE *e);
* already in use). This will fail if the engine is not currently operational
* and cannot initialise.
*/
-int ENGINE_init(ENGINE *e);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int ENGINE_init(ENGINE *e);
+# endif
/*
* Free a functional reference to a engine type. This does not require a
* corresponding call to ENGINE_free as it also releases a structural
* reference.
*/
-int ENGINE_finish(ENGINE *e);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int ENGINE_finish(ENGINE *e);
+# endif
/*
* The following functions handle keys that are stored in some secondary
* location, handled by the engine. The storage may be on a card or
* whatever.
*/
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id,
UI_METHOD *ui_method, void *callback_data);
+OSSL_DEPRECATEDIN_3_0
EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id,
UI_METHOD *ui_method, void *callback_data);
-int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s,
- STACK_OF(X509_NAME) *ca_dn, X509 **pcert,
- EVP_PKEY **ppkey, STACK_OF(X509) **pother,
+OSSL_DEPRECATEDIN_3_0
+int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s, STACK_OF(X509_NAME) *ca_dn,
+ X509 **pcert, EVP_PKEY **ppkey,
+ STACK_OF(X509) **pother,
UI_METHOD *ui_method, void *callback_data);
+# endif
/*
* This returns a pointer for the current ENGINE structure that is (by
@@ -586,20 +653,26 @@ int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s,
* incremented reference, so it should be free'd (ENGINE_finish) before it is
* discarded.
*/
-ENGINE *ENGINE_get_default_RSA(void);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_get_default_RSA(void);
+# endif
/* Same for the other "methods" */
-ENGINE *ENGINE_get_default_DSA(void);
-ENGINE *ENGINE_get_default_EC(void);
-ENGINE *ENGINE_get_default_DH(void);
-ENGINE *ENGINE_get_default_RAND(void);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_get_default_DSA(void);
+OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_get_default_EC(void);
+OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_get_default_DH(void);
+OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_get_default_RAND(void);
+# endif
/*
* These functions can be used to get a functional reference to perform
* ciphering or digesting corresponding to "nid".
*/
-ENGINE *ENGINE_get_cipher_engine(int nid);
-ENGINE *ENGINE_get_digest_engine(int nid);
-ENGINE *ENGINE_get_pkey_meth_engine(int nid);
-ENGINE *ENGINE_get_pkey_asn1_meth_engine(int nid);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_get_cipher_engine(int nid);
+OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_get_digest_engine(int nid);
+OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_get_pkey_meth_engine(int nid);
+OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_get_pkey_asn1_meth_engine(int nid);
+# endif
/*
* This sets a new default ENGINE structure for performing RSA operations. If
@@ -607,17 +680,22 @@ ENGINE *ENGINE_get_pkey_asn1_meth_engine(int nid);
* its reference count up'd so the caller should still free their own
* reference 'e'.
*/
-int ENGINE_set_default_RSA(ENGINE *e);
-int ENGINE_set_default_string(ENGINE *e, const char *def_list);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_default_RSA(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_default_string(ENGINE *e,
+ const char *def_list);
+# endif
/* Same for the other "methods" */
-int ENGINE_set_default_DSA(ENGINE *e);
-int ENGINE_set_default_EC(ENGINE *e);
-int ENGINE_set_default_DH(ENGINE *e);
-int ENGINE_set_default_RAND(ENGINE *e);
-int ENGINE_set_default_ciphers(ENGINE *e);
-int ENGINE_set_default_digests(ENGINE *e);
-int ENGINE_set_default_pkey_meths(ENGINE *e);
-int ENGINE_set_default_pkey_asn1_meths(ENGINE *e);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_default_DSA(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_default_EC(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_default_DH(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_default_RAND(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_default_ciphers(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_default_digests(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_default_pkey_meths(ENGINE *e);
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_default_pkey_asn1_meths(ENGINE *e);
+# endif
/*
* The combination "set" - the flags are bitwise "OR"d from the
@@ -626,9 +704,10 @@ int ENGINE_set_default_pkey_asn1_meths(ENGINE *e);
* application requires only specific functionality, consider using more
* selective functions.
*/
-int ENGINE_set_default(ENGINE *e, unsigned int flags);
-
-void ENGINE_add_conf_module(void);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int ENGINE_set_default(ENGINE *e, unsigned int flags);
+OSSL_DEPRECATEDIN_3_0 void ENGINE_add_conf_module(void);
+# endif
/* Deprecated functions ... */
/* int ENGINE_clear_defaults(void); */
@@ -638,12 +717,12 @@ void ENGINE_add_conf_module(void);
/**************************/
/* Binary/behaviour compatibility levels */
-# define OSSL_DYNAMIC_VERSION (unsigned long)0x00030000
+# define OSSL_DYNAMIC_VERSION (unsigned long)0x00030000
/*
* Binary versions older than this are too old for us (whether we're a loader
* or a loadee)
*/
-# define OSSL_DYNAMIC_OLDEST (unsigned long)0x00030000
+# define OSSL_DYNAMIC_OLDEST (unsigned long)0x00030000
/*
* When compiling an ENGINE entirely as an external shared library, loadable
@@ -687,7 +766,7 @@ typedef struct st_dynamic_fns {
* IMPLEMENT_DYNAMIC_CHECK_FN().
*/
typedef unsigned long (*dynamic_v_check_fn) (unsigned long ossl_version);
-# define IMPLEMENT_DYNAMIC_CHECK_FN() \
+# define IMPLEMENT_DYNAMIC_CHECK_FN() \
OPENSSL_EXPORT unsigned long v_check(unsigned long v); \
OPENSSL_EXPORT unsigned long v_check(unsigned long v) { \
if (v >= OSSL_DYNAMIC_OLDEST) return OSSL_DYNAMIC_VERSION; \
@@ -713,7 +792,7 @@ typedef unsigned long (*dynamic_v_check_fn) (unsigned long ossl_version);
*/
typedef int (*dynamic_bind_engine) (ENGINE *e, const char *id,
const dynamic_fns *fns);
-# define IMPLEMENT_DYNAMIC_BIND_FN(fn) \
+# define IMPLEMENT_DYNAMIC_BIND_FN(fn) \
OPENSSL_EXPORT \
int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); \
OPENSSL_EXPORT \
@@ -740,13 +819,15 @@ typedef int (*dynamic_bind_engine) (ENGINE *e, const char *id,
*/
void *ENGINE_get_static_state(void);
-# if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
-DEPRECATEDIN_1_1_0(void ENGINE_setup_bsd_cryptodev(void))
-# endif
+# if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 void ENGINE_setup_bsd_cryptodev(void);
+# endif
+# endif
# ifdef __cplusplus
}
# endif
-# endif
-#endif
+# endif /* OPENSSL_NO_ENGINE */
+#endif /* OPENSSL_ENGINE_H */
diff --git a/include/openssl/engineerr.h b/include/openssl/engineerr.h
index 05e84bd2a241..d439b6827e60 100644
--- a/include/openssl/engineerr.h
+++ b/include/openssl/engineerr.h
@@ -1,72 +1,24 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_ENGINEERR_H
-# define HEADER_ENGINEERR_H
-
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+#ifndef OPENSSL_ENGINEERR_H
+# define OPENSSL_ENGINEERR_H
+# pragma once
# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifndef OPENSSL_NO_ENGINE
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_ENGINE_strings(void);
+# ifndef OPENSSL_NO_ENGINE
-/*
- * ENGINE function codes.
- */
-# define ENGINE_F_DIGEST_UPDATE 198
-# define ENGINE_F_DYNAMIC_CTRL 180
-# define ENGINE_F_DYNAMIC_GET_DATA_CTX 181
-# define ENGINE_F_DYNAMIC_LOAD 182
-# define ENGINE_F_DYNAMIC_SET_DATA_CTX 183
-# define ENGINE_F_ENGINE_ADD 105
-# define ENGINE_F_ENGINE_BY_ID 106
-# define ENGINE_F_ENGINE_CMD_IS_EXECUTABLE 170
-# define ENGINE_F_ENGINE_CTRL 142
-# define ENGINE_F_ENGINE_CTRL_CMD 178
-# define ENGINE_F_ENGINE_CTRL_CMD_STRING 171
-# define ENGINE_F_ENGINE_FINISH 107
-# define ENGINE_F_ENGINE_GET_CIPHER 185
-# define ENGINE_F_ENGINE_GET_DIGEST 186
-# define ENGINE_F_ENGINE_GET_FIRST 195
-# define ENGINE_F_ENGINE_GET_LAST 196
-# define ENGINE_F_ENGINE_GET_NEXT 115
-# define ENGINE_F_ENGINE_GET_PKEY_ASN1_METH 193
-# define ENGINE_F_ENGINE_GET_PKEY_METH 192
-# define ENGINE_F_ENGINE_GET_PREV 116
-# define ENGINE_F_ENGINE_INIT 119
-# define ENGINE_F_ENGINE_LIST_ADD 120
-# define ENGINE_F_ENGINE_LIST_REMOVE 121
-# define ENGINE_F_ENGINE_LOAD_PRIVATE_KEY 150
-# define ENGINE_F_ENGINE_LOAD_PUBLIC_KEY 151
-# define ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT 194
-# define ENGINE_F_ENGINE_NEW 122
-# define ENGINE_F_ENGINE_PKEY_ASN1_FIND_STR 197
-# define ENGINE_F_ENGINE_REMOVE 123
-# define ENGINE_F_ENGINE_SET_DEFAULT_STRING 189
-# define ENGINE_F_ENGINE_SET_ID 129
-# define ENGINE_F_ENGINE_SET_NAME 130
-# define ENGINE_F_ENGINE_TABLE_REGISTER 184
-# define ENGINE_F_ENGINE_UNLOCKED_FINISH 191
-# define ENGINE_F_ENGINE_UP_REF 190
-# define ENGINE_F_INT_CLEANUP_ITEM 199
-# define ENGINE_F_INT_CTRL_HELPER 172
-# define ENGINE_F_INT_ENGINE_CONFIGURE 188
-# define ENGINE_F_INT_ENGINE_MODULE_INIT 187
-# define ENGINE_F_OSSL_HMAC_INIT 200
/*
* ENGINE reason codes.
diff --git a/include/openssl/err.h b/include/openssl/err.h
deleted file mode 100644
index b49f88129e28..000000000000
--- a/include/openssl/err.h
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_ERR_H
-# define HEADER_ERR_H
-
-# include <openssl/e_os2.h>
-
-# ifndef OPENSSL_NO_STDIO
-# include <stdio.h>
-# include <stdlib.h>
-# endif
-
-# include <openssl/ossl_typ.h>
-# include <openssl/bio.h>
-# include <openssl/lhash.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-# ifndef OPENSSL_NO_ERR
-# define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,d,e)
-# else
-# define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,NULL,0)
-# endif
-
-# include <errno.h>
-
-# define ERR_TXT_MALLOCED 0x01
-# define ERR_TXT_STRING 0x02
-
-# define ERR_FLAG_MARK 0x01
-# define ERR_FLAG_CLEAR 0x02
-
-# define ERR_NUM_ERRORS 16
-typedef struct err_state_st {
- int err_flags[ERR_NUM_ERRORS];
- unsigned long err_buffer[ERR_NUM_ERRORS];
- char *err_data[ERR_NUM_ERRORS];
- int err_data_flags[ERR_NUM_ERRORS];
- const char *err_file[ERR_NUM_ERRORS];
- int err_line[ERR_NUM_ERRORS];
- int top, bottom;
-} ERR_STATE;
-
-/* library */
-# define ERR_LIB_NONE 1
-# define ERR_LIB_SYS 2
-# define ERR_LIB_BN 3
-# define ERR_LIB_RSA 4
-# define ERR_LIB_DH 5
-# define ERR_LIB_EVP 6
-# define ERR_LIB_BUF 7
-# define ERR_LIB_OBJ 8
-# define ERR_LIB_PEM 9
-# define ERR_LIB_DSA 10
-# define ERR_LIB_X509 11
-/* #define ERR_LIB_METH 12 */
-# define ERR_LIB_ASN1 13
-# define ERR_LIB_CONF 14
-# define ERR_LIB_CRYPTO 15
-# define ERR_LIB_EC 16
-# define ERR_LIB_SSL 20
-/* #define ERR_LIB_SSL23 21 */
-/* #define ERR_LIB_SSL2 22 */
-/* #define ERR_LIB_SSL3 23 */
-/* #define ERR_LIB_RSAREF 30 */
-/* #define ERR_LIB_PROXY 31 */
-# define ERR_LIB_BIO 32
-# define ERR_LIB_PKCS7 33
-# define ERR_LIB_X509V3 34
-# define ERR_LIB_PKCS12 35
-# define ERR_LIB_RAND 36
-# define ERR_LIB_DSO 37
-# define ERR_LIB_ENGINE 38
-# define ERR_LIB_OCSP 39
-# define ERR_LIB_UI 40
-# define ERR_LIB_COMP 41
-# define ERR_LIB_ECDSA 42
-# define ERR_LIB_ECDH 43
-# define ERR_LIB_OSSL_STORE 44
-# define ERR_LIB_FIPS 45
-# define ERR_LIB_CMS 46
-# define ERR_LIB_TS 47
-# define ERR_LIB_HMAC 48
-/* # define ERR_LIB_JPAKE 49 */
-# define ERR_LIB_CT 50
-# define ERR_LIB_ASYNC 51
-# define ERR_LIB_KDF 52
-# define ERR_LIB_SM2 53
-
-# define ERR_LIB_USER 128
-
-# define SYSerr(f,r) ERR_PUT_error(ERR_LIB_SYS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define BNerr(f,r) ERR_PUT_error(ERR_LIB_BN,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define RSAerr(f,r) ERR_PUT_error(ERR_LIB_RSA,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define DHerr(f,r) ERR_PUT_error(ERR_LIB_DH,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define EVPerr(f,r) ERR_PUT_error(ERR_LIB_EVP,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define BUFerr(f,r) ERR_PUT_error(ERR_LIB_BUF,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define OBJerr(f,r) ERR_PUT_error(ERR_LIB_OBJ,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define PEMerr(f,r) ERR_PUT_error(ERR_LIB_PEM,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define DSAerr(f,r) ERR_PUT_error(ERR_LIB_DSA,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define X509err(f,r) ERR_PUT_error(ERR_LIB_X509,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define ASN1err(f,r) ERR_PUT_error(ERR_LIB_ASN1,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define CONFerr(f,r) ERR_PUT_error(ERR_LIB_CONF,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define CRYPTOerr(f,r) ERR_PUT_error(ERR_LIB_CRYPTO,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define ECerr(f,r) ERR_PUT_error(ERR_LIB_EC,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define SSLerr(f,r) ERR_PUT_error(ERR_LIB_SSL,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define BIOerr(f,r) ERR_PUT_error(ERR_LIB_BIO,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define PKCS7err(f,r) ERR_PUT_error(ERR_LIB_PKCS7,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define X509V3err(f,r) ERR_PUT_error(ERR_LIB_X509V3,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define PKCS12err(f,r) ERR_PUT_error(ERR_LIB_PKCS12,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define RANDerr(f,r) ERR_PUT_error(ERR_LIB_RAND,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define DSOerr(f,r) ERR_PUT_error(ERR_LIB_DSO,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define ENGINEerr(f,r) ERR_PUT_error(ERR_LIB_ENGINE,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define OCSPerr(f,r) ERR_PUT_error(ERR_LIB_OCSP,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define UIerr(f,r) ERR_PUT_error(ERR_LIB_UI,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define COMPerr(f,r) ERR_PUT_error(ERR_LIB_COMP,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define ECDSAerr(f,r) ERR_PUT_error(ERR_LIB_ECDSA,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define ECDHerr(f,r) ERR_PUT_error(ERR_LIB_ECDH,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define OSSL_STOREerr(f,r) ERR_PUT_error(ERR_LIB_OSSL_STORE,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define FIPSerr(f,r) ERR_PUT_error(ERR_LIB_FIPS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define CMSerr(f,r) ERR_PUT_error(ERR_LIB_CMS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define TSerr(f,r) ERR_PUT_error(ERR_LIB_TS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define HMACerr(f,r) ERR_PUT_error(ERR_LIB_HMAC,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define CTerr(f,r) ERR_PUT_error(ERR_LIB_CT,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define ASYNCerr(f,r) ERR_PUT_error(ERR_LIB_ASYNC,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define KDFerr(f,r) ERR_PUT_error(ERR_LIB_KDF,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define SM2err(f,r) ERR_PUT_error(ERR_LIB_SM2,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-
-# define ERR_PACK(l,f,r) ( \
- (((unsigned int)(l) & 0x0FF) << 24L) | \
- (((unsigned int)(f) & 0xFFF) << 12L) | \
- (((unsigned int)(r) & 0xFFF) ) )
-# define ERR_GET_LIB(l) (int)(((l) >> 24L) & 0x0FFL)
-# define ERR_GET_FUNC(l) (int)(((l) >> 12L) & 0xFFFL)
-# define ERR_GET_REASON(l) (int)( (l) & 0xFFFL)
-# define ERR_FATAL_ERROR(l) (int)( (l) & ERR_R_FATAL)
-
-/* OS functions */
-# define SYS_F_FOPEN 1
-# define SYS_F_CONNECT 2
-# define SYS_F_GETSERVBYNAME 3
-# define SYS_F_SOCKET 4
-# define SYS_F_IOCTLSOCKET 5
-# define SYS_F_BIND 6
-# define SYS_F_LISTEN 7
-# define SYS_F_ACCEPT 8
-# define SYS_F_WSASTARTUP 9/* Winsock stuff */
-# define SYS_F_OPENDIR 10
-# define SYS_F_FREAD 11
-# define SYS_F_GETADDRINFO 12
-# define SYS_F_GETNAMEINFO 13
-# define SYS_F_SETSOCKOPT 14
-# define SYS_F_GETSOCKOPT 15
-# define SYS_F_GETSOCKNAME 16
-# define SYS_F_GETHOSTBYNAME 17
-# define SYS_F_FFLUSH 18
-# define SYS_F_OPEN 19
-# define SYS_F_CLOSE 20
-# define SYS_F_IOCTL 21
-# define SYS_F_STAT 22
-# define SYS_F_FCNTL 23
-# define SYS_F_FSTAT 24
-
-/* reasons */
-# define ERR_R_SYS_LIB ERR_LIB_SYS/* 2 */
-# define ERR_R_BN_LIB ERR_LIB_BN/* 3 */
-# define ERR_R_RSA_LIB ERR_LIB_RSA/* 4 */
-# define ERR_R_DH_LIB ERR_LIB_DH/* 5 */
-# define ERR_R_EVP_LIB ERR_LIB_EVP/* 6 */
-# define ERR_R_BUF_LIB ERR_LIB_BUF/* 7 */
-# define ERR_R_OBJ_LIB ERR_LIB_OBJ/* 8 */
-# define ERR_R_PEM_LIB ERR_LIB_PEM/* 9 */
-# define ERR_R_DSA_LIB ERR_LIB_DSA/* 10 */
-# define ERR_R_X509_LIB ERR_LIB_X509/* 11 */
-# define ERR_R_ASN1_LIB ERR_LIB_ASN1/* 13 */
-# define ERR_R_EC_LIB ERR_LIB_EC/* 16 */
-# define ERR_R_BIO_LIB ERR_LIB_BIO/* 32 */
-# define ERR_R_PKCS7_LIB ERR_LIB_PKCS7/* 33 */
-# define ERR_R_X509V3_LIB ERR_LIB_X509V3/* 34 */
-# define ERR_R_ENGINE_LIB ERR_LIB_ENGINE/* 38 */
-# define ERR_R_UI_LIB ERR_LIB_UI/* 40 */
-# define ERR_R_ECDSA_LIB ERR_LIB_ECDSA/* 42 */
-# define ERR_R_OSSL_STORE_LIB ERR_LIB_OSSL_STORE/* 44 */
-
-# define ERR_R_NESTED_ASN1_ERROR 58
-# define ERR_R_MISSING_ASN1_EOS 63
-
-/* fatal error */
-# define ERR_R_FATAL 64
-# define ERR_R_MALLOC_FAILURE (1|ERR_R_FATAL)
-# define ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED (2|ERR_R_FATAL)
-# define ERR_R_PASSED_NULL_PARAMETER (3|ERR_R_FATAL)
-# define ERR_R_INTERNAL_ERROR (4|ERR_R_FATAL)
-# define ERR_R_DISABLED (5|ERR_R_FATAL)
-# define ERR_R_INIT_FAIL (6|ERR_R_FATAL)
-# define ERR_R_PASSED_INVALID_ARGUMENT (7)
-# define ERR_R_OPERATION_FAIL (8|ERR_R_FATAL)
-
-/*
- * 99 is the maximum possible ERR_R_... code, higher values are reserved for
- * the individual libraries
- */
-
-typedef struct ERR_string_data_st {
- unsigned long error;
- const char *string;
-} ERR_STRING_DATA;
-
-DEFINE_LHASH_OF(ERR_STRING_DATA);
-
-void ERR_put_error(int lib, int func, int reason, const char *file, int line);
-void ERR_set_error_data(char *data, int flags);
-
-unsigned long ERR_get_error(void);
-unsigned long ERR_get_error_line(const char **file, int *line);
-unsigned long ERR_get_error_line_data(const char **file, int *line,
- const char **data, int *flags);
-unsigned long ERR_peek_error(void);
-unsigned long ERR_peek_error_line(const char **file, int *line);
-unsigned long ERR_peek_error_line_data(const char **file, int *line,
- const char **data, int *flags);
-unsigned long ERR_peek_last_error(void);
-unsigned long ERR_peek_last_error_line(const char **file, int *line);
-unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
- const char **data, int *flags);
-void ERR_clear_error(void);
-char *ERR_error_string(unsigned long e, char *buf);
-void ERR_error_string_n(unsigned long e, char *buf, size_t len);
-const char *ERR_lib_error_string(unsigned long e);
-const char *ERR_func_error_string(unsigned long e);
-const char *ERR_reason_error_string(unsigned long e);
-void ERR_print_errors_cb(int (*cb) (const char *str, size_t len, void *u),
- void *u);
-# ifndef OPENSSL_NO_STDIO
-void ERR_print_errors_fp(FILE *fp);
-# endif
-void ERR_print_errors(BIO *bp);
-void ERR_add_error_data(int num, ...);
-void ERR_add_error_vdata(int num, va_list args);
-int ERR_load_strings(int lib, ERR_STRING_DATA *str);
-int ERR_load_strings_const(const ERR_STRING_DATA *str);
-int ERR_unload_strings(int lib, ERR_STRING_DATA *str);
-int ERR_load_ERR_strings(void);
-
-#if OPENSSL_API_COMPAT < 0x10100000L
-# define ERR_load_crypto_strings() \
- OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL)
-# define ERR_free_strings() while(0) continue
-#endif
-
-DEPRECATEDIN_1_1_0(void ERR_remove_thread_state(void *))
-DEPRECATEDIN_1_0_0(void ERR_remove_state(unsigned long pid))
-ERR_STATE *ERR_get_state(void);
-
-int ERR_get_next_error_library(void);
-
-int ERR_set_mark(void);
-int ERR_pop_to_mark(void);
-int ERR_clear_last_mark(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/openssl/err.h.in b/include/openssl/err.h.in
new file mode 100644
index 000000000000..11dc21637f74
--- /dev/null
+++ b/include/openssl/err.h.in
@@ -0,0 +1,493 @@
+/*
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_lhash_macros);
+-}
+
+#ifndef OPENSSL_ERR_H
+# define OPENSSL_ERR_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_ERR_H
+# endif
+
+# include <openssl/e_os2.h>
+
+# ifndef OPENSSL_NO_STDIO
+# include <stdio.h>
+# include <stdlib.h>
+# endif
+
+# include <openssl/types.h>
+# include <openssl/bio.h>
+# include <openssl/lhash.h>
+# include <openssl/cryptoerr_legacy.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef OPENSSL_NO_FILENAMES
+# define ERR_PUT_error(l,f,r,fn,ln) ERR_put_error(l,f,r,fn,ln)
+# else
+# define ERR_PUT_error(l,f,r,fn,ln) ERR_put_error(l,f,r,NULL,0)
+# endif
+# endif
+
+# include <limits.h>
+# include <errno.h>
+
+# define ERR_TXT_MALLOCED 0x01
+# define ERR_TXT_STRING 0x02
+
+# if !defined(OPENSSL_NO_DEPRECATED_3_0) || defined(OSSL_FORCE_ERR_STATE)
+# define ERR_FLAG_MARK 0x01
+# define ERR_FLAG_CLEAR 0x02
+
+# define ERR_NUM_ERRORS 16
+struct err_state_st {
+ int err_flags[ERR_NUM_ERRORS];
+ int err_marks[ERR_NUM_ERRORS];
+ unsigned long err_buffer[ERR_NUM_ERRORS];
+ char *err_data[ERR_NUM_ERRORS];
+ size_t err_data_size[ERR_NUM_ERRORS];
+ int err_data_flags[ERR_NUM_ERRORS];
+ char *err_file[ERR_NUM_ERRORS];
+ int err_line[ERR_NUM_ERRORS];
+ char *err_func[ERR_NUM_ERRORS];
+ int top, bottom;
+};
+# endif
+
+/* library */
+# define ERR_LIB_NONE 1
+# define ERR_LIB_SYS 2
+# define ERR_LIB_BN 3
+# define ERR_LIB_RSA 4
+# define ERR_LIB_DH 5
+# define ERR_LIB_EVP 6
+# define ERR_LIB_BUF 7
+# define ERR_LIB_OBJ 8
+# define ERR_LIB_PEM 9
+# define ERR_LIB_DSA 10
+# define ERR_LIB_X509 11
+/* #define ERR_LIB_METH 12 */
+# define ERR_LIB_ASN1 13
+# define ERR_LIB_CONF 14
+# define ERR_LIB_CRYPTO 15
+# define ERR_LIB_EC 16
+# define ERR_LIB_SSL 20
+/* #define ERR_LIB_SSL23 21 */
+/* #define ERR_LIB_SSL2 22 */
+/* #define ERR_LIB_SSL3 23 */
+/* #define ERR_LIB_RSAREF 30 */
+/* #define ERR_LIB_PROXY 31 */
+# define ERR_LIB_BIO 32
+# define ERR_LIB_PKCS7 33
+# define ERR_LIB_X509V3 34
+# define ERR_LIB_PKCS12 35
+# define ERR_LIB_RAND 36
+# define ERR_LIB_DSO 37
+# define ERR_LIB_ENGINE 38
+# define ERR_LIB_OCSP 39
+# define ERR_LIB_UI 40
+# define ERR_LIB_COMP 41
+# define ERR_LIB_ECDSA 42
+# define ERR_LIB_ECDH 43
+# define ERR_LIB_OSSL_STORE 44
+# define ERR_LIB_FIPS 45
+# define ERR_LIB_CMS 46
+# define ERR_LIB_TS 47
+# define ERR_LIB_HMAC 48
+/* # define ERR_LIB_JPAKE 49 */
+# define ERR_LIB_CT 50
+# define ERR_LIB_ASYNC 51
+# define ERR_LIB_KDF 52
+# define ERR_LIB_SM2 53
+# define ERR_LIB_ESS 54
+# define ERR_LIB_PROP 55
+# define ERR_LIB_CRMF 56
+# define ERR_LIB_PROV 57
+# define ERR_LIB_CMP 58
+# define ERR_LIB_OSSL_ENCODER 59
+# define ERR_LIB_OSSL_DECODER 60
+# define ERR_LIB_HTTP 61
+
+# define ERR_LIB_USER 128
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define ASN1err(f, r) ERR_raise_data(ERR_LIB_ASN1, (r), NULL)
+# define ASYNCerr(f, r) ERR_raise_data(ERR_LIB_ASYNC, (r), NULL)
+# define BIOerr(f, r) ERR_raise_data(ERR_LIB_BIO, (r), NULL)
+# define BNerr(f, r) ERR_raise_data(ERR_LIB_BN, (r), NULL)
+# define BUFerr(f, r) ERR_raise_data(ERR_LIB_BUF, (r), NULL)
+# define CMPerr(f, r) ERR_raise_data(ERR_LIB_CMP, (r), NULL)
+# define CMSerr(f, r) ERR_raise_data(ERR_LIB_CMS, (r), NULL)
+# define COMPerr(f, r) ERR_raise_data(ERR_LIB_COMP, (r), NULL)
+# define CONFerr(f, r) ERR_raise_data(ERR_LIB_CONF, (r), NULL)
+# define CRMFerr(f, r) ERR_raise_data(ERR_LIB_CRMF, (r), NULL)
+# define CRYPTOerr(f, r) ERR_raise_data(ERR_LIB_CRYPTO, (r), NULL)
+# define CTerr(f, r) ERR_raise_data(ERR_LIB_CT, (r), NULL)
+# define DHerr(f, r) ERR_raise_data(ERR_LIB_DH, (r), NULL)
+# define DSAerr(f, r) ERR_raise_data(ERR_LIB_DSA, (r), NULL)
+# define DSOerr(f, r) ERR_raise_data(ERR_LIB_DSO, (r), NULL)
+# define ECDHerr(f, r) ERR_raise_data(ERR_LIB_ECDH, (r), NULL)
+# define ECDSAerr(f, r) ERR_raise_data(ERR_LIB_ECDSA, (r), NULL)
+# define ECerr(f, r) ERR_raise_data(ERR_LIB_EC, (r), NULL)
+# define ENGINEerr(f, r) ERR_raise_data(ERR_LIB_ENGINE, (r), NULL)
+# define ESSerr(f, r) ERR_raise_data(ERR_LIB_ESS, (r), NULL)
+# define EVPerr(f, r) ERR_raise_data(ERR_LIB_EVP, (r), NULL)
+# define FIPSerr(f, r) ERR_raise_data(ERR_LIB_FIPS, (r), NULL)
+# define HMACerr(f, r) ERR_raise_data(ERR_LIB_HMAC, (r), NULL)
+# define HTTPerr(f, r) ERR_raise_data(ERR_LIB_HTTP, (r), NULL)
+# define KDFerr(f, r) ERR_raise_data(ERR_LIB_KDF, (r), NULL)
+# define OBJerr(f, r) ERR_raise_data(ERR_LIB_OBJ, (r), NULL)
+# define OCSPerr(f, r) ERR_raise_data(ERR_LIB_OCSP, (r), NULL)
+# define OSSL_STOREerr(f, r) ERR_raise_data(ERR_LIB_OSSL_STORE, (r), NULL)
+# define PEMerr(f, r) ERR_raise_data(ERR_LIB_PEM, (r), NULL)
+# define PKCS12err(f, r) ERR_raise_data(ERR_LIB_PKCS12, (r), NULL)
+# define PKCS7err(f, r) ERR_raise_data(ERR_LIB_PKCS7, (r), NULL)
+# define PROPerr(f, r) ERR_raise_data(ERR_LIB_PROP, (r), NULL)
+# define PROVerr(f, r) ERR_raise_data(ERR_LIB_PROV, (r), NULL)
+# define RANDerr(f, r) ERR_raise_data(ERR_LIB_RAND, (r), NULL)
+# define RSAerr(f, r) ERR_raise_data(ERR_LIB_RSA, (r), NULL)
+# define KDFerr(f, r) ERR_raise_data(ERR_LIB_KDF, (r), NULL)
+# define SM2err(f, r) ERR_raise_data(ERR_LIB_SM2, (r), NULL)
+# define SSLerr(f, r) ERR_raise_data(ERR_LIB_SSL, (r), NULL)
+# define SYSerr(f, r) ERR_raise_data(ERR_LIB_SYS, (r), NULL)
+# define TSerr(f, r) ERR_raise_data(ERR_LIB_TS, (r), NULL)
+# define UIerr(f, r) ERR_raise_data(ERR_LIB_UI, (r), NULL)
+# define X509V3err(f, r) ERR_raise_data(ERR_LIB_X509V3, (r), NULL)
+# define X509err(f, r) ERR_raise_data(ERR_LIB_X509, (r), NULL)
+# endif
+
+/*-
+ * The error code packs differently depending on if it records a system
+ * error or an OpenSSL error.
+ *
+ * A system error packs like this (we follow POSIX and only allow positive
+ * numbers that fit in an |int|):
+ *
+ * +-+-------------------------------------------------------------+
+ * |1| system error number |
+ * +-+-------------------------------------------------------------+
+ *
+ * An OpenSSL error packs like this:
+ *
+ * <---------------------------- 32 bits -------------------------->
+ * <--- 8 bits ---><------------------ 23 bits ----------------->
+ * +-+---------------+---------------------------------------------+
+ * |0| library | reason |
+ * +-+---------------+---------------------------------------------+
+ *
+ * A few of the reason bits are reserved as flags with special meaning:
+ *
+ * <5 bits-<>--------- 19 bits ----------------->
+ * +-------+-+-----------------------------------+
+ * | rflags| | reason |
+ * +-------+-+-----------------------------------+
+ * ^
+ * |
+ * ERR_RFLAG_FATAL = ERR_R_FATAL
+ *
+ * The reason flags are part of the overall reason code for practical
+ * reasons, as they provide an easy way to place different types of
+ * reason codes in different numeric ranges.
+ *
+ * The currently known reason flags are:
+ *
+ * ERR_RFLAG_FATAL Flags that the reason code is considered fatal.
+ * For backward compatibility reasons, this flag
+ * is also the code for ERR_R_FATAL (that reason
+ * code served the dual purpose of flag and reason
+ * code in one in pre-3.0 OpenSSL).
+ * ERR_RFLAG_COMMON Flags that the reason code is common to all
+ * libraries. All ERR_R_ macros must use this flag,
+ * and no other _R_ macro is allowed to use it.
+ */
+
+/* Macros to help decode recorded system errors */
+# define ERR_SYSTEM_FLAG ((unsigned int)INT_MAX + 1)
+# define ERR_SYSTEM_MASK ((unsigned int)INT_MAX)
+
+/*
+ * Macros to help decode recorded OpenSSL errors
+ * As expressed above, RFLAGS and REASON overlap by one bit to allow
+ * ERR_R_FATAL to use ERR_RFLAG_FATAL as its reason code.
+ */
+# define ERR_LIB_OFFSET 23L
+# define ERR_LIB_MASK 0xFF
+# define ERR_RFLAGS_OFFSET 18L
+# define ERR_RFLAGS_MASK 0x1F
+# define ERR_REASON_MASK 0X7FFFFF
+
+/*
+ * Reason flags are defined pre-shifted to easily combine with the reason
+ * number.
+ */
+# define ERR_RFLAG_FATAL (0x1 << ERR_RFLAGS_OFFSET)
+# define ERR_RFLAG_COMMON (0x2 << ERR_RFLAGS_OFFSET)
+
+# define ERR_SYSTEM_ERROR(errcode) (((errcode) & ERR_SYSTEM_FLAG) != 0)
+
+static ossl_unused ossl_inline int ERR_GET_LIB(unsigned long errcode)
+{
+ if (ERR_SYSTEM_ERROR(errcode))
+ return ERR_LIB_SYS;
+ return (errcode >> ERR_LIB_OFFSET) & ERR_LIB_MASK;
+}
+
+static ossl_unused ossl_inline int ERR_GET_RFLAGS(unsigned long errcode)
+{
+ if (ERR_SYSTEM_ERROR(errcode))
+ return 0;
+ return errcode & (ERR_RFLAGS_MASK << ERR_RFLAGS_OFFSET);
+}
+
+static ossl_unused ossl_inline int ERR_GET_REASON(unsigned long errcode)
+{
+ if (ERR_SYSTEM_ERROR(errcode))
+ return errcode & ERR_SYSTEM_MASK;
+ return errcode & ERR_REASON_MASK;
+}
+
+static ossl_unused ossl_inline int ERR_FATAL_ERROR(unsigned long errcode)
+{
+ return (ERR_GET_RFLAGS(errcode) & ERR_RFLAG_FATAL) != 0;
+}
+
+static ossl_unused ossl_inline int ERR_COMMON_ERROR(unsigned long errcode)
+{
+ return (ERR_GET_RFLAGS(errcode) & ERR_RFLAG_COMMON) != 0;
+}
+
+/*
+ * ERR_PACK is a helper macro to properly pack OpenSSL error codes and may
+ * only be used for that purpose. System errors are packed internally.
+ * ERR_PACK takes reason flags and reason code combined in |reason|.
+ * ERR_PACK ignores |func|, that parameter is just legacy from pre-3.0 OpenSSL.
+ */
+# define ERR_PACK(lib,func,reason) \
+ ( (((unsigned long)(lib) & ERR_LIB_MASK ) << ERR_LIB_OFFSET) | \
+ (((unsigned long)(reason) & ERR_REASON_MASK)) )
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define SYS_F_FOPEN 0
+# define SYS_F_CONNECT 0
+# define SYS_F_GETSERVBYNAME 0
+# define SYS_F_SOCKET 0
+# define SYS_F_IOCTLSOCKET 0
+# define SYS_F_BIND 0
+# define SYS_F_LISTEN 0
+# define SYS_F_ACCEPT 0
+# define SYS_F_WSASTARTUP 0
+# define SYS_F_OPENDIR 0
+# define SYS_F_FREAD 0
+# define SYS_F_GETADDRINFO 0
+# define SYS_F_GETNAMEINFO 0
+# define SYS_F_SETSOCKOPT 0
+# define SYS_F_GETSOCKOPT 0
+# define SYS_F_GETSOCKNAME 0
+# define SYS_F_GETHOSTBYNAME 0
+# define SYS_F_FFLUSH 0
+# define SYS_F_OPEN 0
+# define SYS_F_CLOSE 0
+# define SYS_F_IOCTL 0
+# define SYS_F_STAT 0
+# define SYS_F_FCNTL 0
+# define SYS_F_FSTAT 0
+# define SYS_F_SENDFILE 0
+# endif
+
+/*
+ * All ERR_R_ codes must be combined with ERR_RFLAG_COMMON.
+ */
+
+/* "we came from here" global reason codes, range 1..255 */
+# define ERR_R_SYS_LIB (ERR_LIB_SYS/* 2 */ | ERR_RFLAG_COMMON)
+# define ERR_R_BN_LIB (ERR_LIB_BN/* 3 */ | ERR_RFLAG_COMMON)
+# define ERR_R_RSA_LIB (ERR_LIB_RSA/* 4 */ | ERR_RFLAG_COMMON)
+# define ERR_R_DH_LIB (ERR_LIB_DH/* 5 */ | ERR_RFLAG_COMMON)
+# define ERR_R_EVP_LIB (ERR_LIB_EVP/* 6 */ | ERR_RFLAG_COMMON)
+# define ERR_R_BUF_LIB (ERR_LIB_BUF/* 7 */ | ERR_RFLAG_COMMON)
+# define ERR_R_OBJ_LIB (ERR_LIB_OBJ/* 8 */ | ERR_RFLAG_COMMON)
+# define ERR_R_PEM_LIB (ERR_LIB_PEM/* 9 */ | ERR_RFLAG_COMMON)
+# define ERR_R_DSA_LIB (ERR_LIB_DSA/* 10 */ | ERR_RFLAG_COMMON)
+# define ERR_R_X509_LIB (ERR_LIB_X509/* 11 */ | ERR_RFLAG_COMMON)
+# define ERR_R_ASN1_LIB (ERR_LIB_ASN1/* 13 */ | ERR_RFLAG_COMMON)
+# define ERR_R_CONF_LIB (ERR_LIB_CONF/* 14 */ | ERR_RFLAG_COMMON)
+# define ERR_R_CRYPTO_LIB (ERR_LIB_CRYPTO/* 15 */ | ERR_RFLAG_COMMON)
+# define ERR_R_EC_LIB (ERR_LIB_EC/* 16 */ | ERR_RFLAG_COMMON)
+# define ERR_R_SSL_LIB (ERR_LIB_SSL/* 20 */ | ERR_RFLAG_COMMON)
+# define ERR_R_BIO_LIB (ERR_LIB_BIO/* 32 */ | ERR_RFLAG_COMMON)
+# define ERR_R_PKCS7_LIB (ERR_LIB_PKCS7/* 33 */ | ERR_RFLAG_COMMON)
+# define ERR_R_X509V3_LIB (ERR_LIB_X509V3/* 34 */ | ERR_RFLAG_COMMON)
+# define ERR_R_PKCS12_LIB (ERR_LIB_PKCS12/* 35 */ | ERR_RFLAG_COMMON)
+# define ERR_R_RAND_LIB (ERR_LIB_RAND/* 36 */ | ERR_RFLAG_COMMON)
+# define ERR_R_DSO_LIB (ERR_LIB_DSO/* 37 */ | ERR_RFLAG_COMMON)
+# define ERR_R_ENGINE_LIB (ERR_LIB_ENGINE/* 38 */ | ERR_RFLAG_COMMON)
+# define ERR_R_UI_LIB (ERR_LIB_UI/* 40 */ | ERR_RFLAG_COMMON)
+# define ERR_R_ECDSA_LIB (ERR_LIB_ECDSA/* 42 */ | ERR_RFLAG_COMMON)
+# define ERR_R_OSSL_STORE_LIB (ERR_LIB_OSSL_STORE/* 44 */ | ERR_RFLAG_COMMON)
+# define ERR_R_CMS_LIB (ERR_LIB_CMS/* 46 */ | ERR_RFLAG_COMMON)
+# define ERR_R_TS_LIB (ERR_LIB_TS/* 47 */ | ERR_RFLAG_COMMON)
+# define ERR_R_CT_LIB (ERR_LIB_CT/* 50 */ | ERR_RFLAG_COMMON)
+# define ERR_R_PROV_LIB (ERR_LIB_PROV/* 57 */ | ERR_RFLAG_COMMON)
+# define ERR_R_ESS_LIB (ERR_LIB_ESS/* 54 */ | ERR_RFLAG_COMMON)
+# define ERR_R_CMP_LIB (ERR_LIB_CMP/* 58 */ | ERR_RFLAG_COMMON)
+# define ERR_R_OSSL_ENCODER_LIB (ERR_LIB_OSSL_ENCODER/* 59 */ | ERR_RFLAG_COMMON)
+# define ERR_R_OSSL_DECODER_LIB (ERR_LIB_OSSL_DECODER/* 60 */ | ERR_RFLAG_COMMON)
+
+/* Other common error codes, range 256..2^ERR_RFLAGS_OFFSET-1 */
+# define ERR_R_FATAL (ERR_RFLAG_FATAL|ERR_RFLAG_COMMON)
+# define ERR_R_MALLOC_FAILURE (256|ERR_R_FATAL)
+# define ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED (257|ERR_R_FATAL)
+# define ERR_R_PASSED_NULL_PARAMETER (258|ERR_R_FATAL)
+# define ERR_R_INTERNAL_ERROR (259|ERR_R_FATAL)
+# define ERR_R_DISABLED (260|ERR_R_FATAL)
+# define ERR_R_INIT_FAIL (261|ERR_R_FATAL)
+# define ERR_R_PASSED_INVALID_ARGUMENT (262|ERR_RFLAG_COMMON)
+# define ERR_R_OPERATION_FAIL (263|ERR_R_FATAL)
+# define ERR_R_INVALID_PROVIDER_FUNCTIONS (264|ERR_R_FATAL)
+# define ERR_R_INTERRUPTED_OR_CANCELLED (265|ERR_RFLAG_COMMON)
+# define ERR_R_NESTED_ASN1_ERROR (266|ERR_RFLAG_COMMON)
+# define ERR_R_MISSING_ASN1_EOS (267|ERR_RFLAG_COMMON)
+# define ERR_R_UNSUPPORTED (268|ERR_RFLAG_COMMON)
+# define ERR_R_FETCH_FAILED (269|ERR_RFLAG_COMMON)
+# define ERR_R_INVALID_PROPERTY_DEFINITION (270|ERR_RFLAG_COMMON)
+# define ERR_R_UNABLE_TO_GET_READ_LOCK (271|ERR_R_FATAL)
+# define ERR_R_UNABLE_TO_GET_WRITE_LOCK (272|ERR_R_FATAL)
+
+typedef struct ERR_string_data_st {
+ unsigned long error;
+ const char *string;
+} ERR_STRING_DATA;
+
+{-
+ generate_lhash_macros("ERR_STRING_DATA");
+-}
+
+/* 12 lines and some on an 80 column terminal */
+#define ERR_MAX_DATA_SIZE 1024
+
+/* Building blocks */
+void ERR_new(void);
+void ERR_set_debug(const char *file, int line, const char *func);
+void ERR_set_error(int lib, int reason, const char *fmt, ...);
+void ERR_vset_error(int lib, int reason, const char *fmt, va_list args);
+
+/* Main error raising functions */
+# define ERR_raise(lib, reason) ERR_raise_data((lib),(reason),NULL)
+# define ERR_raise_data \
+ (ERR_new(), \
+ ERR_set_debug(OPENSSL_FILE,OPENSSL_LINE,OPENSSL_FUNC), \
+ ERR_set_error)
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+/* Backward compatibility */
+# define ERR_put_error(lib, func, reason, file, line) \
+ (ERR_new(), \
+ ERR_set_debug((file), (line), OPENSSL_FUNC), \
+ ERR_set_error((lib), (reason), NULL))
+# endif
+
+void ERR_set_error_data(char *data, int flags);
+
+unsigned long ERR_get_error(void);
+unsigned long ERR_get_error_all(const char **file, int *line,
+ const char **func,
+ const char **data, int *flags);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
+unsigned long ERR_get_error_line(const char **file, int *line);
+OSSL_DEPRECATEDIN_3_0
+unsigned long ERR_get_error_line_data(const char **file, int *line,
+ const char **data, int *flags);
+#endif
+unsigned long ERR_peek_error(void);
+unsigned long ERR_peek_error_line(const char **file, int *line);
+unsigned long ERR_peek_error_func(const char **func);
+unsigned long ERR_peek_error_data(const char **data, int *flags);
+unsigned long ERR_peek_error_all(const char **file, int *line,
+ const char **func,
+ const char **data, int *flags);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
+unsigned long ERR_peek_error_line_data(const char **file, int *line,
+ const char **data, int *flags);
+# endif
+unsigned long ERR_peek_last_error(void);
+unsigned long ERR_peek_last_error_line(const char **file, int *line);
+unsigned long ERR_peek_last_error_func(const char **func);
+unsigned long ERR_peek_last_error_data(const char **data, int *flags);
+unsigned long ERR_peek_last_error_all(const char **file, int *line,
+ const char **func,
+ const char **data, int *flags);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
+unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
+ const char **data, int *flags);
+# endif
+
+void ERR_clear_error(void);
+
+char *ERR_error_string(unsigned long e, char *buf);
+void ERR_error_string_n(unsigned long e, char *buf, size_t len);
+const char *ERR_lib_error_string(unsigned long e);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 const char *ERR_func_error_string(unsigned long e);
+# endif
+const char *ERR_reason_error_string(unsigned long e);
+
+void ERR_print_errors_cb(int (*cb) (const char *str, size_t len, void *u),
+ void *u);
+# ifndef OPENSSL_NO_STDIO
+void ERR_print_errors_fp(FILE *fp);
+# endif
+void ERR_print_errors(BIO *bp);
+
+void ERR_add_error_data(int num, ...);
+void ERR_add_error_vdata(int num, va_list args);
+void ERR_add_error_txt(const char *sepr, const char *txt);
+void ERR_add_error_mem_bio(const char *sep, BIO *bio);
+
+int ERR_load_strings(int lib, ERR_STRING_DATA *str);
+int ERR_load_strings_const(const ERR_STRING_DATA *str);
+int ERR_unload_strings(int lib, ERR_STRING_DATA *str);
+
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define ERR_load_crypto_strings() \
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL)
+# define ERR_free_strings() while(0) continue
+#endif
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 void ERR_remove_thread_state(void *);
+#endif
+#ifndef OPENSSL_NO_DEPRECATED_1_0_0
+OSSL_DEPRECATEDIN_1_0_0 void ERR_remove_state(unsigned long pid);
+#endif
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 ERR_STATE *ERR_get_state(void);
+#endif
+
+int ERR_get_next_error_library(void);
+
+int ERR_set_mark(void);
+int ERR_pop_to_mark(void);
+int ERR_clear_last_mark(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/openssl/ess.h.in b/include/openssl/ess.h.in
new file mode 100644
index 000000000000..d1a685b98e3e
--- /dev/null
+++ b/include/openssl/ess.h.in
@@ -0,0 +1,81 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_ESS_H
+# define OPENSSL_ESS_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+
+# include <openssl/safestack.h>
+# include <openssl/x509.h>
+# include <openssl/esserr.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+
+typedef struct ESS_issuer_serial ESS_ISSUER_SERIAL;
+typedef struct ESS_cert_id ESS_CERT_ID;
+typedef struct ESS_signing_cert ESS_SIGNING_CERT;
+
+{-
+ generate_stack_macros("ESS_CERT_ID");
+-}
+
+
+typedef struct ESS_signing_cert_v2_st ESS_SIGNING_CERT_V2;
+typedef struct ESS_cert_id_v2_st ESS_CERT_ID_V2;
+
+{-
+ generate_stack_macros("ESS_CERT_ID_V2");
+-}
+
+DECLARE_ASN1_ALLOC_FUNCTIONS(ESS_ISSUER_SERIAL)
+DECLARE_ASN1_ENCODE_FUNCTIONS_only(ESS_ISSUER_SERIAL, ESS_ISSUER_SERIAL)
+DECLARE_ASN1_DUP_FUNCTION(ESS_ISSUER_SERIAL)
+
+DECLARE_ASN1_ALLOC_FUNCTIONS(ESS_CERT_ID)
+DECLARE_ASN1_ENCODE_FUNCTIONS_only(ESS_CERT_ID, ESS_CERT_ID)
+DECLARE_ASN1_DUP_FUNCTION(ESS_CERT_ID)
+
+DECLARE_ASN1_FUNCTIONS(ESS_SIGNING_CERT)
+DECLARE_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT)
+
+DECLARE_ASN1_ALLOC_FUNCTIONS(ESS_CERT_ID_V2)
+DECLARE_ASN1_ENCODE_FUNCTIONS_only(ESS_CERT_ID_V2, ESS_CERT_ID_V2)
+DECLARE_ASN1_DUP_FUNCTION(ESS_CERT_ID_V2)
+
+DECLARE_ASN1_FUNCTIONS(ESS_SIGNING_CERT_V2)
+DECLARE_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT_V2)
+
+ESS_SIGNING_CERT *OSSL_ESS_signing_cert_new_init(const X509 *signcert,
+ const STACK_OF(X509) *certs,
+ int set_issuer_serial);
+ESS_SIGNING_CERT_V2 *OSSL_ESS_signing_cert_v2_new_init(const EVP_MD *hash_alg,
+ const X509 *signcert,
+ const
+ STACK_OF(X509) *certs,
+ int set_issuer_serial);
+int OSSL_ESS_check_signing_certs(const ESS_SIGNING_CERT *ss,
+ const ESS_SIGNING_CERT_V2 *ssv2,
+ const STACK_OF(X509) *chain,
+ int require_signing_cert);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/esserr.h b/include/openssl/esserr.h
new file mode 100644
index 000000000000..165ce7c43751
--- /dev/null
+++ b/include/openssl/esserr.h
@@ -0,0 +1,32 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_ESSERR_H
+# define OPENSSL_ESSERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
+
+/*
+ * ESS reason codes.
+ */
+# define ESS_R_EMPTY_ESS_CERT_ID_LIST 107
+# define ESS_R_ESS_CERT_DIGEST_ERROR 103
+# define ESS_R_ESS_CERT_ID_NOT_FOUND 104
+# define ESS_R_ESS_CERT_ID_WRONG_ORDER 105
+# define ESS_R_ESS_DIGEST_ALG_UNKNOWN 106
+# define ESS_R_ESS_SIGNING_CERTIFICATE_ERROR 102
+# define ESS_R_ESS_SIGNING_CERT_ADD_ERROR 100
+# define ESS_R_ESS_SIGNING_CERT_V2_ADD_ERROR 101
+# define ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE 108
+
+#endif
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index a411f3f2f949..49e8e1df7865 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -1,20 +1,35 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_ENVELOPE_H
-# define HEADER_ENVELOPE_H
+#ifndef OPENSSL_EVP_H
+# define OPENSSL_EVP_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_ENVELOPE_H
+# endif
+
+# include <stdarg.h>
+
+# ifndef OPENSSL_NO_STDIO
+# include <stdio.h>
+# endif
# include <openssl/opensslconf.h>
-# include <openssl/ossl_typ.h>
+# include <openssl/types.h>
+# include <openssl/core.h>
+# include <openssl/core_dispatch.h>
# include <openssl/symhacks.h>
# include <openssl/bio.h>
# include <openssl/evperr.h>
+# include <openssl/params.h>
# define EVP_MAX_MD_SIZE 64/* longest known is SHA512 */
# define EVP_MAX_KEY_LENGTH 64
@@ -27,16 +42,18 @@
# include <openssl/objects.h>
-# define EVP_PK_RSA 0x0001
-# define EVP_PK_DSA 0x0002
-# define EVP_PK_DH 0x0004
-# define EVP_PK_EC 0x0008
-# define EVP_PKT_SIGN 0x0010
-# define EVP_PKT_ENC 0x0020
-# define EVP_PKT_EXCH 0x0040
-# define EVP_PKS_RSA 0x0100
-# define EVP_PKS_DSA 0x0200
-# define EVP_PKS_EC 0x0400
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define EVP_PK_RSA 0x0001
+# define EVP_PK_DSA 0x0002
+# define EVP_PK_DH 0x0004
+# define EVP_PK_EC 0x0008
+# define EVP_PKT_SIGN 0x0010
+# define EVP_PKT_ENC 0x0020
+# define EVP_PKT_EXCH 0x0040
+# define EVP_PKS_RSA 0x0100
+# define EVP_PKS_DSA 0x0200
+# define EVP_PKS_EC 0x0400
+# endif
# define EVP_PKEY_NONE NID_undef
# define EVP_PKEY_RSA NID_rsaEncryption
@@ -62,53 +79,81 @@
# define EVP_PKEY_ED25519 NID_ED25519
# define EVP_PKEY_X448 NID_X448
# define EVP_PKEY_ED448 NID_ED448
+/* Special indicator that the object is uniquely provider side */
+# define EVP_PKEY_KEYMGMT -1
+
+/* Easy to use macros for EVP_PKEY related selections */
+# define EVP_PKEY_KEY_PARAMETERS \
+ ( OSSL_KEYMGMT_SELECT_ALL_PARAMETERS )
+# define EVP_PKEY_PUBLIC_KEY \
+ ( EVP_PKEY_KEY_PARAMETERS | OSSL_KEYMGMT_SELECT_PUBLIC_KEY )
+# define EVP_PKEY_KEYPAIR \
+ ( EVP_PKEY_PUBLIC_KEY | OSSL_KEYMGMT_SELECT_PRIVATE_KEY )
#ifdef __cplusplus
extern "C" {
#endif
+int EVP_set_default_properties(OSSL_LIB_CTX *libctx, const char *propq);
+int EVP_default_properties_is_fips_enabled(OSSL_LIB_CTX *libctx);
+int EVP_default_properties_enable_fips(OSSL_LIB_CTX *libctx, int enable);
+
# define EVP_PKEY_MO_SIGN 0x0001
# define EVP_PKEY_MO_VERIFY 0x0002
# define EVP_PKEY_MO_ENCRYPT 0x0004
# define EVP_PKEY_MO_DECRYPT 0x0008
# ifndef EVP_MD
-EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type);
-EVP_MD *EVP_MD_meth_dup(const EVP_MD *md);
-void EVP_MD_meth_free(EVP_MD *md);
-
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type);
+OSSL_DEPRECATEDIN_3_0 EVP_MD *EVP_MD_meth_dup(const EVP_MD *md);
+OSSL_DEPRECATEDIN_3_0 void EVP_MD_meth_free(EVP_MD *md);
+OSSL_DEPRECATEDIN_3_0
int EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize);
+OSSL_DEPRECATEDIN_3_0
int EVP_MD_meth_set_result_size(EVP_MD *md, int resultsize);
+OSSL_DEPRECATEDIN_3_0
int EVP_MD_meth_set_app_datasize(EVP_MD *md, int datasize);
+OSSL_DEPRECATEDIN_3_0
int EVP_MD_meth_set_flags(EVP_MD *md, unsigned long flags);
+OSSL_DEPRECATEDIN_3_0
int EVP_MD_meth_set_init(EVP_MD *md, int (*init)(EVP_MD_CTX *ctx));
+OSSL_DEPRECATEDIN_3_0
int EVP_MD_meth_set_update(EVP_MD *md, int (*update)(EVP_MD_CTX *ctx,
const void *data,
size_t count));
+OSSL_DEPRECATEDIN_3_0
int EVP_MD_meth_set_final(EVP_MD *md, int (*final)(EVP_MD_CTX *ctx,
unsigned char *md));
+OSSL_DEPRECATEDIN_3_0
int EVP_MD_meth_set_copy(EVP_MD *md, int (*copy)(EVP_MD_CTX *to,
const EVP_MD_CTX *from));
+OSSL_DEPRECATEDIN_3_0
int EVP_MD_meth_set_cleanup(EVP_MD *md, int (*cleanup)(EVP_MD_CTX *ctx));
+OSSL_DEPRECATEDIN_3_0
int EVP_MD_meth_set_ctrl(EVP_MD *md, int (*ctrl)(EVP_MD_CTX *ctx, int cmd,
int p1, void *p2));
-
-int EVP_MD_meth_get_input_blocksize(const EVP_MD *md);
-int EVP_MD_meth_get_result_size(const EVP_MD *md);
-int EVP_MD_meth_get_app_datasize(const EVP_MD *md);
-unsigned long EVP_MD_meth_get_flags(const EVP_MD *md);
+OSSL_DEPRECATEDIN_3_0 int EVP_MD_meth_get_input_blocksize(const EVP_MD *md);
+OSSL_DEPRECATEDIN_3_0 int EVP_MD_meth_get_result_size(const EVP_MD *md);
+OSSL_DEPRECATEDIN_3_0 int EVP_MD_meth_get_app_datasize(const EVP_MD *md);
+OSSL_DEPRECATEDIN_3_0 unsigned long EVP_MD_meth_get_flags(const EVP_MD *md);
+OSSL_DEPRECATEDIN_3_0
int (*EVP_MD_meth_get_init(const EVP_MD *md))(EVP_MD_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0
int (*EVP_MD_meth_get_update(const EVP_MD *md))(EVP_MD_CTX *ctx,
- const void *data,
- size_t count);
+ const void *data, size_t count);
+OSSL_DEPRECATEDIN_3_0
int (*EVP_MD_meth_get_final(const EVP_MD *md))(EVP_MD_CTX *ctx,
unsigned char *md);
+OSSL_DEPRECATEDIN_3_0
int (*EVP_MD_meth_get_copy(const EVP_MD *md))(EVP_MD_CTX *to,
const EVP_MD_CTX *from);
+OSSL_DEPRECATEDIN_3_0
int (*EVP_MD_meth_get_cleanup(const EVP_MD *md))(EVP_MD_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0
int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd,
int p1, void *p2);
-
+# endif
/* digest can only handle a single block */
# define EVP_MD_FLAG_ONESHOT 0x0001
@@ -139,6 +184,7 @@ int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd,
# define EVP_MD_CTRL_DIGALGID 0x1
# define EVP_MD_CTRL_MICALG 0x2
# define EVP_MD_CTRL_XOF_LEN 0x3
+# define EVP_MD_CTRL_TLSTREE 0x4
/* Minimum Algorithm specific ctrl value */
@@ -159,8 +205,8 @@ int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd,
* don't accidentally reuse the values for other purposes.
*/
-# define EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 0x0008/* Allow use of non FIPS
- * digest in FIPS mode */
+/* This flag has no effect from openssl-3.0 onwards */
+# define EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 0x0008
/*
* The following PAD options are also currently ignored in 1.0.0, digest
@@ -181,52 +227,68 @@ int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd,
*/
# define EVP_MD_CTX_FLAG_FINALISE 0x0200
/* NOTE: 0x0400 is reserved for internal usage */
-
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len);
+OSSL_DEPRECATEDIN_3_0
EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher);
+OSSL_DEPRECATEDIN_3_0
void EVP_CIPHER_meth_free(EVP_CIPHER *cipher);
-
+OSSL_DEPRECATEDIN_3_0
int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len);
+OSSL_DEPRECATEDIN_3_0
int EVP_CIPHER_meth_set_flags(EVP_CIPHER *cipher, unsigned long flags);
+OSSL_DEPRECATEDIN_3_0
int EVP_CIPHER_meth_set_impl_ctx_size(EVP_CIPHER *cipher, int ctx_size);
+OSSL_DEPRECATEDIN_3_0
int EVP_CIPHER_meth_set_init(EVP_CIPHER *cipher,
int (*init) (EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv,
int enc));
+OSSL_DEPRECATEDIN_3_0
int EVP_CIPHER_meth_set_do_cipher(EVP_CIPHER *cipher,
int (*do_cipher) (EVP_CIPHER_CTX *ctx,
unsigned char *out,
const unsigned char *in,
size_t inl));
+OSSL_DEPRECATEDIN_3_0
int EVP_CIPHER_meth_set_cleanup(EVP_CIPHER *cipher,
int (*cleanup) (EVP_CIPHER_CTX *));
+OSSL_DEPRECATEDIN_3_0
int EVP_CIPHER_meth_set_set_asn1_params(EVP_CIPHER *cipher,
int (*set_asn1_parameters) (EVP_CIPHER_CTX *,
ASN1_TYPE *));
+OSSL_DEPRECATEDIN_3_0
int EVP_CIPHER_meth_set_get_asn1_params(EVP_CIPHER *cipher,
int (*get_asn1_parameters) (EVP_CIPHER_CTX *,
ASN1_TYPE *));
+OSSL_DEPRECATEDIN_3_0
int EVP_CIPHER_meth_set_ctrl(EVP_CIPHER *cipher,
int (*ctrl) (EVP_CIPHER_CTX *, int type,
int arg, void *ptr));
-
-int (*EVP_CIPHER_meth_get_init(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx,
- const unsigned char *key,
- const unsigned char *iv,
- int enc);
-int (*EVP_CIPHER_meth_get_do_cipher(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx,
- unsigned char *out,
- const unsigned char *in,
- size_t inl);
-int (*EVP_CIPHER_meth_get_cleanup(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *);
-int (*EVP_CIPHER_meth_get_set_asn1_params(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
- ASN1_TYPE *);
-int (*EVP_CIPHER_meth_get_get_asn1_params(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
- ASN1_TYPE *);
-int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
- int type, int arg,
- void *ptr);
+OSSL_DEPRECATEDIN_3_0 int
+(*EVP_CIPHER_meth_get_init(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx,
+ const unsigned char *key,
+ const unsigned char *iv,
+ int enc);
+OSSL_DEPRECATEDIN_3_0 int
+(*EVP_CIPHER_meth_get_do_cipher(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx,
+ unsigned char *out,
+ const unsigned char *in,
+ size_t inl);
+OSSL_DEPRECATEDIN_3_0 int
+(*EVP_CIPHER_meth_get_cleanup(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *);
+OSSL_DEPRECATEDIN_3_0 int
+(*EVP_CIPHER_meth_get_set_asn1_params(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
+ ASN1_TYPE *);
+OSSL_DEPRECATEDIN_3_0 int
+(*EVP_CIPHER_meth_get_get_asn1_params(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
+ ASN1_TYPE *);
+OSSL_DEPRECATEDIN_3_0 int
+(*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *, int type,
+ int arg, void *ptr);
+# endif
/* Values for cipher flags */
@@ -243,6 +305,7 @@ int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
# define EVP_CIPH_XTS_MODE 0x10001
# define EVP_CIPH_WRAP_MODE 0x10002
# define EVP_CIPH_OCB_MODE 0x10003
+# define EVP_CIPH_SIV_MODE 0x10004
# define EVP_CIPH_MODE 0xF0007
/* Set if variable length cipher */
# define EVP_CIPH_VARIABLE_LENGTH 0x8
@@ -262,22 +325,32 @@ int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
# define EVP_CIPH_CUSTOM_COPY 0x400
/* Don't use standard iv length function */
# define EVP_CIPH_CUSTOM_IV_LENGTH 0x800
-/* Allow use default ASN1 get/set iv */
-# define EVP_CIPH_FLAG_DEFAULT_ASN1 0x1000
+/* Legacy and no longer relevant: Allow use default ASN1 get/set iv */
+# define EVP_CIPH_FLAG_DEFAULT_ASN1 0
+/* Free: 0x1000 */
/* Buffer length in bits not bytes: CFB1 mode only */
# define EVP_CIPH_FLAG_LENGTH_BITS 0x2000
-/* Note if suitable for use in FIPS mode */
-# define EVP_CIPH_FLAG_FIPS 0x4000
-/* Allow non FIPS cipher in FIPS mode */
-# define EVP_CIPH_FLAG_NON_FIPS_ALLOW 0x8000
+/* Deprecated FIPS flag: was 0x4000 */
+# define EVP_CIPH_FLAG_FIPS 0
+/* Deprecated FIPS flag: was 0x8000 */
+# define EVP_CIPH_FLAG_NON_FIPS_ALLOW 0
+
/*
* Cipher handles any and all padding logic as well as finalisation.
*/
+# define EVP_CIPH_FLAG_CTS 0x4000
# define EVP_CIPH_FLAG_CUSTOM_CIPHER 0x100000
# define EVP_CIPH_FLAG_AEAD_CIPHER 0x200000
# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0x400000
/* Cipher can handle pipeline operations */
# define EVP_CIPH_FLAG_PIPELINE 0X800000
+/* For provider implementations that handle ASN1 get/set param themselves */
+# define EVP_CIPH_FLAG_CUSTOM_ASN1 0x1000000
+/* For ciphers generating unprotected CMS attributes */
+# define EVP_CIPH_FLAG_CIPHER_WITH_MAC 0x2000000
+/* For supplementary wrap cipher support */
+# define EVP_CIPH_FLAG_GET_WRAP_CIPHER 0x4000000
+# define EVP_CIPH_FLAG_INVERSE_CIPHER 0x8000000
/*
* Cipher context flag to indicate we can handle wrap mode: if allowed in
@@ -350,8 +423,17 @@ int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
# define EVP_CTRL_SET_PIPELINE_INPUT_BUFS 0x23
/* Set the input buffer lengths to use for a pipelined operation */
# define EVP_CTRL_SET_PIPELINE_INPUT_LENS 0x24
-
+/* Get the IV length used by the cipher */
# define EVP_CTRL_GET_IVLEN 0x25
+/* 0x26 is unused */
+/* Tell the cipher it's doing a speed test (SIV disallows multiple ops) */
+# define EVP_CTRL_SET_SPEED 0x27
+/* Get the unprotectedAttrs from cipher ctx */
+# define EVP_CTRL_PROCESS_UNPROTECTED 0x28
+/* Get the supplementary wrap cipher */
+#define EVP_CTRL_GET_WRAP_CIPHER 0x29
+/* TLSTREE key diversification */
+#define EVP_CTRL_TLSTREE 0x2A
/* Padding modes */
#define EVP_PADDING_PKCS7 1
@@ -405,33 +487,39 @@ typedef int (EVP_PBE_KEYGEN) (EVP_CIPHER_CTX *ctx, const char *pass,
const EVP_CIPHER *cipher, const EVP_MD *md,
int en_de);
-# ifndef OPENSSL_NO_RSA
+typedef int (EVP_PBE_KEYGEN_EX) (EVP_CIPHER_CTX *ctx, const char *pass,
+ int passlen, ASN1_TYPE *param,
+ const EVP_CIPHER *cipher, const EVP_MD *md,
+ int en_de, OSSL_LIB_CTX *libctx, const char *propq);
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
# define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\
- (char *)(rsa))
+ (rsa))
# endif
# ifndef OPENSSL_NO_DSA
# define EVP_PKEY_assign_DSA(pkey,dsa) EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\
- (char *)(dsa))
+ (dsa))
# endif
-# ifndef OPENSSL_NO_DH
-# define EVP_PKEY_assign_DH(pkey,dh) EVP_PKEY_assign((pkey),EVP_PKEY_DH,\
- (char *)(dh))
+# if !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_DEPRECATED_3_0)
+# define EVP_PKEY_assign_DH(pkey,dh) EVP_PKEY_assign((pkey),EVP_PKEY_DH,(dh))
# endif
-# ifndef OPENSSL_NO_EC
-# define EVP_PKEY_assign_EC_KEY(pkey,eckey) EVP_PKEY_assign((pkey),EVP_PKEY_EC,\
- (char *)(eckey))
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef OPENSSL_NO_EC
+# define EVP_PKEY_assign_EC_KEY(pkey,eckey) \
+ EVP_PKEY_assign((pkey), EVP_PKEY_EC, (eckey))
+# endif
# endif
# ifndef OPENSSL_NO_SIPHASH
-# define EVP_PKEY_assign_SIPHASH(pkey,shkey) EVP_PKEY_assign((pkey),EVP_PKEY_SIPHASH,\
- (char *)(shkey))
+# define EVP_PKEY_assign_SIPHASH(pkey,shkey) EVP_PKEY_assign((pkey),\
+ EVP_PKEY_SIPHASH,(shkey))
# endif
# ifndef OPENSSL_NO_POLY1305
-# define EVP_PKEY_assign_POLY1305(pkey,polykey) EVP_PKEY_assign((pkey),EVP_PKEY_POLY1305,\
- (char *)(polykey))
+# define EVP_PKEY_assign_POLY1305(pkey,polykey) EVP_PKEY_assign((pkey),\
+ EVP_PKEY_POLY1305,(polykey))
# endif
/* Add some extra combinations */
@@ -440,58 +528,125 @@ typedef int (EVP_PBE_KEYGEN) (EVP_CIPHER_CTX *ctx, const char *pass,
# define EVP_get_cipherbynid(a) EVP_get_cipherbyname(OBJ_nid2sn(a))
# define EVP_get_cipherbyobj(a) EVP_get_cipherbynid(OBJ_obj2nid(a))
-int EVP_MD_type(const EVP_MD *md);
-# define EVP_MD_nid(e) EVP_MD_type(e)
-# define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_nid(e))
-int EVP_MD_pkey_type(const EVP_MD *md);
-int EVP_MD_size(const EVP_MD *md);
-int EVP_MD_block_size(const EVP_MD *md);
-unsigned long EVP_MD_flags(const EVP_MD *md);
-
+int EVP_MD_get_type(const EVP_MD *md);
+# define EVP_MD_type EVP_MD_get_type
+# define EVP_MD_nid EVP_MD_get_type
+const char *EVP_MD_get0_name(const EVP_MD *md);
+# define EVP_MD_name EVP_MD_get0_name
+const char *EVP_MD_get0_description(const EVP_MD *md);
+int EVP_MD_is_a(const EVP_MD *md, const char *name);
+int EVP_MD_names_do_all(const EVP_MD *md,
+ void (*fn)(const char *name, void *data),
+ void *data);
+const OSSL_PROVIDER *EVP_MD_get0_provider(const EVP_MD *md);
+int EVP_MD_get_pkey_type(const EVP_MD *md);
+# define EVP_MD_pkey_type EVP_MD_get_pkey_type
+int EVP_MD_get_size(const EVP_MD *md);
+# define EVP_MD_size EVP_MD_get_size
+int EVP_MD_get_block_size(const EVP_MD *md);
+# define EVP_MD_block_size EVP_MD_get_block_size
+unsigned long EVP_MD_get_flags(const EVP_MD *md);
+# define EVP_MD_flags EVP_MD_get_flags
+
+const EVP_MD *EVP_MD_CTX_get0_md(const EVP_MD_CTX *ctx);
+EVP_MD *EVP_MD_CTX_get1_md(EVP_MD_CTX *ctx);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0
int (*EVP_MD_CTX_update_fn(EVP_MD_CTX *ctx))(EVP_MD_CTX *ctx,
const void *data, size_t count);
+OSSL_DEPRECATEDIN_3_0
void EVP_MD_CTX_set_update_fn(EVP_MD_CTX *ctx,
int (*update) (EVP_MD_CTX *ctx,
const void *data, size_t count));
-# define EVP_MD_CTX_size(e) EVP_MD_size(EVP_MD_CTX_md(e))
-# define EVP_MD_CTX_block_size(e) EVP_MD_block_size(EVP_MD_CTX_md(e))
-# define EVP_MD_CTX_type(e) EVP_MD_type(EVP_MD_CTX_md(e))
-EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx);
+# endif
+# define EVP_MD_CTX_get0_name(e) EVP_MD_get0_name(EVP_MD_CTX_get0_md(e))
+# define EVP_MD_CTX_get_size(e) EVP_MD_get_size(EVP_MD_CTX_get0_md(e))
+# define EVP_MD_CTX_size EVP_MD_CTX_get_size
+# define EVP_MD_CTX_get_block_size(e) EVP_MD_get_block_size(EVP_MD_CTX_get0_md(e))
+# define EVP_MD_CTX_block_size EVP_MD_CTX_get_block_size
+# define EVP_MD_CTX_get_type(e) EVP_MD_get_type(EVP_MD_CTX_get0_md(e))
+# define EVP_MD_CTX_type EVP_MD_CTX_get_type
+EVP_PKEY_CTX *EVP_MD_CTX_get_pkey_ctx(const EVP_MD_CTX *ctx);
+# define EVP_MD_CTX_pkey_ctx EVP_MD_CTX_get_pkey_ctx
void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx);
-void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx);
-
-int EVP_CIPHER_nid(const EVP_CIPHER *cipher);
-# define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e))
-int EVP_CIPHER_block_size(const EVP_CIPHER *cipher);
+void *EVP_MD_CTX_get0_md_data(const EVP_MD_CTX *ctx);
+# define EVP_MD_CTX_md_data EVP_MD_CTX_get0_md_data
+
+int EVP_CIPHER_get_nid(const EVP_CIPHER *cipher);
+# define EVP_CIPHER_nid EVP_CIPHER_get_nid
+const char *EVP_CIPHER_get0_name(const EVP_CIPHER *cipher);
+# define EVP_CIPHER_name EVP_CIPHER_get0_name
+const char *EVP_CIPHER_get0_description(const EVP_CIPHER *cipher);
+int EVP_CIPHER_is_a(const EVP_CIPHER *cipher, const char *name);
+int EVP_CIPHER_names_do_all(const EVP_CIPHER *cipher,
+ void (*fn)(const char *name, void *data),
+ void *data);
+const OSSL_PROVIDER *EVP_CIPHER_get0_provider(const EVP_CIPHER *cipher);
+int EVP_CIPHER_get_block_size(const EVP_CIPHER *cipher);
+# define EVP_CIPHER_block_size EVP_CIPHER_get_block_size
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *cipher);
-int EVP_CIPHER_key_length(const EVP_CIPHER *cipher);
-int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher);
-unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher);
-# define EVP_CIPHER_mode(e) (EVP_CIPHER_flags(e) & EVP_CIPH_MODE)
-
+# endif
+int EVP_CIPHER_get_key_length(const EVP_CIPHER *cipher);
+# define EVP_CIPHER_key_length EVP_CIPHER_get_key_length
+int EVP_CIPHER_get_iv_length(const EVP_CIPHER *cipher);
+# define EVP_CIPHER_iv_length EVP_CIPHER_get_iv_length
+unsigned long EVP_CIPHER_get_flags(const EVP_CIPHER *cipher);
+# define EVP_CIPHER_flags EVP_CIPHER_get_flags
+int EVP_CIPHER_get_mode(const EVP_CIPHER *cipher);
+# define EVP_CIPHER_mode EVP_CIPHER_get_mode
+int EVP_CIPHER_get_type(const EVP_CIPHER *cipher);
+# define EVP_CIPHER_type EVP_CIPHER_get_type
+EVP_CIPHER *EVP_CIPHER_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties);
+int EVP_CIPHER_up_ref(EVP_CIPHER *cipher);
+void EVP_CIPHER_free(EVP_CIPHER *cipher);
+
+const EVP_CIPHER *EVP_CIPHER_CTX_get0_cipher(const EVP_CIPHER_CTX *ctx);
+EVP_CIPHER *EVP_CIPHER_CTX_get1_cipher(EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_is_encrypting(const EVP_CIPHER_CTX *ctx);
+# define EVP_CIPHER_CTX_encrypting EVP_CIPHER_CTX_is_encrypting
+int EVP_CIPHER_CTX_get_nid(const EVP_CIPHER_CTX *ctx);
+# define EVP_CIPHER_CTX_nid EVP_CIPHER_CTX_get_nid
+int EVP_CIPHER_CTX_get_block_size(const EVP_CIPHER_CTX *ctx);
+# define EVP_CIPHER_CTX_block_size EVP_CIPHER_CTX_get_block_size
+int EVP_CIPHER_CTX_get_key_length(const EVP_CIPHER_CTX *ctx);
+# define EVP_CIPHER_CTX_key_length EVP_CIPHER_CTX_get_key_length
+int EVP_CIPHER_CTX_get_iv_length(const EVP_CIPHER_CTX *ctx);
+# define EVP_CIPHER_CTX_iv_length EVP_CIPHER_CTX_get_iv_length
+int EVP_CIPHER_CTX_get_tag_length(const EVP_CIPHER_CTX *ctx);
+# define EVP_CIPHER_CTX_tag_length EVP_CIPHER_CTX_get_tag_length
+# ifndef OPENSSL_NO_DEPRECATED_3_0
const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx);
-int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx);
-int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx);
-int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx);
-int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx);
-int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx);
-const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx);
-const unsigned char *EVP_CIPHER_CTX_original_iv(const EVP_CIPHER_CTX *ctx);
-unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 const unsigned char *EVP_CIPHER_CTX_original_iv(const EVP_CIPHER_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx);
+# endif
+int EVP_CIPHER_CTX_get_updated_iv(EVP_CIPHER_CTX *ctx, void *buf, size_t len);
+int EVP_CIPHER_CTX_get_original_iv(EVP_CIPHER_CTX *ctx, void *buf, size_t len);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
unsigned char *EVP_CIPHER_CTX_buf_noconst(EVP_CIPHER_CTX *ctx);
-int EVP_CIPHER_CTX_num(const EVP_CIPHER_CTX *ctx);
-void EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num);
+# endif
+int EVP_CIPHER_CTX_get_num(const EVP_CIPHER_CTX *ctx);
+# define EVP_CIPHER_CTX_num EVP_CIPHER_CTX_get_num
+int EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num);
int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in);
void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx);
void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data);
void *EVP_CIPHER_CTX_get_cipher_data(const EVP_CIPHER_CTX *ctx);
void *EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data);
-# define EVP_CIPHER_CTX_type(c) EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c))
-# if OPENSSL_API_COMPAT < 0x10100000L
-# define EVP_CIPHER_CTX_flags(c) EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(c))
+# define EVP_CIPHER_CTX_get0_name(c) EVP_CIPHER_get0_name(EVP_CIPHER_CTX_get0_cipher(c))
+# define EVP_CIPHER_CTX_get_type(c) EVP_CIPHER_get_type(EVP_CIPHER_CTX_get0_cipher(c))
+# define EVP_CIPHER_CTX_type EVP_CIPHER_CTX_get_type
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define EVP_CIPHER_CTX_flags(c) EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(c))
# endif
-# define EVP_CIPHER_CTX_mode(c) EVP_CIPHER_mode(EVP_CIPHER_CTX_cipher(c))
+# define EVP_CIPHER_CTX_get_mode(c) EVP_CIPHER_get_mode(EVP_CIPHER_CTX_get0_cipher(c))
+# define EVP_CIPHER_CTX_mode EVP_CIPHER_CTX_get_mode
# define EVP_ENCODE_LENGTH(l) ((((l)+2)/3*4)+((l)/48+1)*2+80)
# define EVP_DECODE_LENGTH(l) (((l)+3)/4*3+80)
@@ -504,22 +659,17 @@ void *EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data);
# define EVP_VerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c)
# define EVP_OpenUpdate(a,b,c,d,e) EVP_DecryptUpdate(a,b,c,d,e)
# define EVP_SealUpdate(a,b,c,d,e) EVP_EncryptUpdate(a,b,c,d,e)
-# define EVP_DigestSignUpdate(a,b,c) EVP_DigestUpdate(a,b,c)
-# define EVP_DigestVerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c)
# ifdef CONST_STRICT
void BIO_set_md(BIO *, const EVP_MD *md);
# else
-# define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,0,(char *)(md))
+# define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,0,(void *)(md))
# endif
-# define BIO_get_md(b,mdp) BIO_ctrl(b,BIO_C_GET_MD,0,(char *)(mdp))
-# define BIO_get_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_GET_MD_CTX,0, \
- (char *)(mdcp))
-# define BIO_set_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_SET_MD_CTX,0, \
- (char *)(mdcp))
+# define BIO_get_md(b,mdp) BIO_ctrl(b,BIO_C_GET_MD,0,(mdp))
+# define BIO_get_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_GET_MD_CTX,0,(mdcp))
+# define BIO_set_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_SET_MD_CTX,0,(mdcp))
# define BIO_get_cipher_status(b) BIO_ctrl(b,BIO_C_GET_CIPHER_STATUS,0,NULL)
-# define BIO_get_cipher_ctx(b,c_pp) BIO_ctrl(b,BIO_C_GET_CIPHER_CTX,0, \
- (char *)(c_pp))
+# define BIO_get_cipher_ctx(b,c_pp) BIO_ctrl(b,BIO_C_GET_CIPHER_CTX,0,(c_pp))
/*__owur*/ int EVP_Cipher(EVP_CIPHER_CTX *c,
unsigned char *out,
@@ -534,6 +684,14 @@ void BIO_set_md(BIO *, const EVP_MD *md);
# define EVP_delete_digest_alias(alias) \
OBJ_NAME_remove(alias,OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS);
+int EVP_MD_get_params(const EVP_MD *digest, OSSL_PARAM params[]);
+int EVP_MD_CTX_set_params(EVP_MD_CTX *ctx, const OSSL_PARAM params[]);
+int EVP_MD_CTX_get_params(EVP_MD_CTX *ctx, OSSL_PARAM params[]);
+const OSSL_PARAM *EVP_MD_gettable_params(const EVP_MD *digest);
+const OSSL_PARAM *EVP_MD_settable_ctx_params(const EVP_MD *md);
+const OSSL_PARAM *EVP_MD_gettable_ctx_params(const EVP_MD *md);
+const OSSL_PARAM *EVP_MD_CTX_settable_params(EVP_MD_CTX *ctx);
+const OSSL_PARAM *EVP_MD_CTX_gettable_params(EVP_MD_CTX *ctx);
int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2);
EVP_MD_CTX *EVP_MD_CTX_new(void);
int EVP_MD_CTX_reset(EVP_MD_CTX *ctx);
@@ -545,6 +703,8 @@ __owur int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in);
void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags);
void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags);
int EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, int flags);
+__owur int EVP_DigestInit_ex2(EVP_MD_CTX *ctx, const EVP_MD *type,
+ const OSSL_PARAM params[]);
__owur int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type,
ENGINE *impl);
__owur int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d,
@@ -554,6 +714,9 @@ __owur int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md,
__owur int EVP_Digest(const void *data, size_t count,
unsigned char *md, unsigned int *size,
const EVP_MD *type, ENGINE *impl);
+__owur int EVP_Q_digest(OSSL_LIB_CTX *libctx, const char *name,
+ const char *propq, const void *data, size_t datalen,
+ unsigned char *md, size_t *mdlen);
__owur int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in);
__owur int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type);
@@ -562,6 +725,12 @@ __owur int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md,
__owur int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md,
size_t len);
+__owur EVP_MD *EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties);
+
+int EVP_MD_up_ref(EVP_MD *md);
+void EVP_MD_free(EVP_MD *md);
+
int EVP_read_pw_string(char *buf, int length, const char *prompt, int verify);
int EVP_read_pw_string_min(char *buf, int minlen, int maxlen,
const char *prompt, int verify);
@@ -583,6 +752,10 @@ __owur int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const EVP_CIPHER *cipher, ENGINE *impl,
const unsigned char *key,
const unsigned char *iv);
+__owur int EVP_EncryptInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ const unsigned char *key,
+ const unsigned char *iv,
+ const OSSL_PARAM params[]);
/*__owur*/ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
/*__owur*/ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out,
@@ -596,6 +769,10 @@ __owur int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const EVP_CIPHER *cipher, ENGINE *impl,
const unsigned char *key,
const unsigned char *iv);
+__owur int EVP_DecryptInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ const unsigned char *key,
+ const unsigned char *iv,
+ const OSSL_PARAM params[]);
/*__owur*/ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
__owur int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm,
@@ -610,6 +787,9 @@ __owur int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const EVP_CIPHER *cipher, ENGINE *impl,
const unsigned char *key,
const unsigned char *iv, int enc);
+__owur int EVP_CipherInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ const unsigned char *key, const unsigned char *iv,
+ int enc, const OSSL_PARAM params[]);
__owur int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
__owur int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm,
@@ -619,6 +799,9 @@ __owur int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm,
__owur int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s,
EVP_PKEY *pkey);
+__owur int EVP_SignFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s,
+ EVP_PKEY *pkey, OSSL_LIB_CTX *libctx,
+ const char *propq);
__owur int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret,
size_t *siglen, const unsigned char *tbs,
@@ -626,24 +809,36 @@ __owur int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret,
__owur int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
unsigned int siglen, EVP_PKEY *pkey);
+__owur int EVP_VerifyFinal_ex(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
+ unsigned int siglen, EVP_PKEY *pkey,
+ OSSL_LIB_CTX *libctx, const char *propq);
__owur int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
size_t siglen, const unsigned char *tbs,
size_t tbslen);
+int EVP_DigestSignInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+ const char *mdname, OSSL_LIB_CTX *libctx,
+ const char *props, EVP_PKEY *pkey,
+ const OSSL_PARAM params[]);
/*__owur*/ int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e,
EVP_PKEY *pkey);
+int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize);
__owur int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
size_t *siglen);
+int EVP_DigestVerifyInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+ const char *mdname, OSSL_LIB_CTX *libctx,
+ const char *props, EVP_PKEY *pkey,
+ const OSSL_PARAM params[]);
__owur int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e,
EVP_PKEY *pkey);
+int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize);
__owur int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
size_t siglen);
-# ifndef OPENSSL_NO_RSA
__owur int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
const unsigned char *ek, int ekl,
const unsigned char *iv, EVP_PKEY *priv);
@@ -653,11 +848,10 @@ __owur int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
unsigned char **ek, int *ekl, unsigned char *iv,
EVP_PKEY **pubk, int npubk);
__owur int EVP_SealFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
-# endif
EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void);
void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx);
-int EVP_ENCODE_CTX_copy(EVP_ENCODE_CTX *dctx, EVP_ENCODE_CTX *sctx);
+int EVP_ENCODE_CTX_copy(EVP_ENCODE_CTX *dctx, const EVP_ENCODE_CTX *sctx);
int EVP_ENCODE_CTX_num(EVP_ENCODE_CTX *ctx);
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx);
int EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
@@ -672,7 +866,7 @@ int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned
char *out, int *outl);
int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n);
-# if OPENSSL_API_COMPAT < 0x10100000L
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
# define EVP_CIPHER_CTX_init(c) EVP_CIPHER_CTX_reset(c)
# define EVP_CIPHER_CTX_cleanup(c) EVP_CIPHER_CTX_reset(c)
# endif
@@ -683,6 +877,14 @@ int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad);
int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key);
+int EVP_CIPHER_get_params(EVP_CIPHER *cipher, OSSL_PARAM params[]);
+int EVP_CIPHER_CTX_set_params(EVP_CIPHER_CTX *ctx, const OSSL_PARAM params[]);
+int EVP_CIPHER_CTX_get_params(EVP_CIPHER_CTX *ctx, OSSL_PARAM params[]);
+const OSSL_PARAM *EVP_CIPHER_gettable_params(const EVP_CIPHER *cipher);
+const OSSL_PARAM *EVP_CIPHER_settable_ctx_params(const EVP_CIPHER *cipher);
+const OSSL_PARAM *EVP_CIPHER_gettable_ctx_params(const EVP_CIPHER *cipher);
+const OSSL_PARAM *EVP_CIPHER_CTX_settable_params(EVP_CIPHER_CTX *ctx);
+const OSSL_PARAM *EVP_CIPHER_CTX_gettable_params(EVP_CIPHER_CTX *ctx);
const BIO_METHOD *BIO_f_md(void);
const BIO_METHOD *BIO_f_base64(void);
@@ -719,6 +921,7 @@ const EVP_MD *EVP_sha3_384(void);
const EVP_MD *EVP_sha3_512(void);
const EVP_MD *EVP_shake128(void);
const EVP_MD *EVP_shake256(void);
+
# ifndef OPENSSL_NO_MDC2
const EVP_MD *EVP_mdc2(void);
# endif
@@ -939,7 +1142,7 @@ const EVP_CIPHER *EVP_sm4_ofb(void);
const EVP_CIPHER *EVP_sm4_ctr(void);
# endif
-# if OPENSSL_API_COMPAT < 0x10100000L
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
# define OPENSSL_add_all_algorithms_conf() \
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
| OPENSSL_INIT_ADD_ALL_DIGESTS \
@@ -974,6 +1177,9 @@ void EVP_CIPHER_do_all(void (*fn) (const EVP_CIPHER *ciph,
void EVP_CIPHER_do_all_sorted(void (*fn)
(const EVP_CIPHER *ciph, const char *from,
const char *to, void *x), void *arg);
+void EVP_CIPHER_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_CIPHER *cipher, void *arg),
+ void *arg);
void EVP_MD_do_all(void (*fn) (const EVP_MD *ciph,
const char *from, const char *to, void *x),
@@ -981,81 +1187,236 @@ void EVP_MD_do_all(void (*fn) (const EVP_MD *ciph,
void EVP_MD_do_all_sorted(void (*fn)
(const EVP_MD *ciph, const char *from,
const char *to, void *x), void *arg);
-
-int EVP_PKEY_decrypt_old(unsigned char *dec_key,
- const unsigned char *enc_key, int enc_key_len,
- EVP_PKEY *private_key);
-int EVP_PKEY_encrypt_old(unsigned char *enc_key,
- const unsigned char *key, int key_len,
- EVP_PKEY *pub_key);
+void EVP_MD_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_MD *md, void *arg),
+ void *arg);
+
+/* MAC stuff */
+
+EVP_MAC *EVP_MAC_fetch(OSSL_LIB_CTX *libctx, const char *algorithm,
+ const char *properties);
+int EVP_MAC_up_ref(EVP_MAC *mac);
+void EVP_MAC_free(EVP_MAC *mac);
+const char *EVP_MAC_get0_name(const EVP_MAC *mac);
+const char *EVP_MAC_get0_description(const EVP_MAC *mac);
+int EVP_MAC_is_a(const EVP_MAC *mac, const char *name);
+const OSSL_PROVIDER *EVP_MAC_get0_provider(const EVP_MAC *mac);
+int EVP_MAC_get_params(EVP_MAC *mac, OSSL_PARAM params[]);
+
+EVP_MAC_CTX *EVP_MAC_CTX_new(EVP_MAC *mac);
+void EVP_MAC_CTX_free(EVP_MAC_CTX *ctx);
+EVP_MAC_CTX *EVP_MAC_CTX_dup(const EVP_MAC_CTX *src);
+EVP_MAC *EVP_MAC_CTX_get0_mac(EVP_MAC_CTX *ctx);
+int EVP_MAC_CTX_get_params(EVP_MAC_CTX *ctx, OSSL_PARAM params[]);
+int EVP_MAC_CTX_set_params(EVP_MAC_CTX *ctx, const OSSL_PARAM params[]);
+
+size_t EVP_MAC_CTX_get_mac_size(EVP_MAC_CTX *ctx);
+size_t EVP_MAC_CTX_get_block_size(EVP_MAC_CTX *ctx);
+unsigned char *EVP_Q_mac(OSSL_LIB_CTX *libctx, const char *name, const char *propq,
+ const char *subalg, const OSSL_PARAM *params,
+ const void *key, size_t keylen,
+ const unsigned char *data, size_t datalen,
+ unsigned char *out, size_t outsize, size_t *outlen);
+int EVP_MAC_init(EVP_MAC_CTX *ctx, const unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[]);
+int EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen);
+int EVP_MAC_final(EVP_MAC_CTX *ctx,
+ unsigned char *out, size_t *outl, size_t outsize);
+int EVP_MAC_finalXOF(EVP_MAC_CTX *ctx, unsigned char *out, size_t outsize);
+const OSSL_PARAM *EVP_MAC_gettable_params(const EVP_MAC *mac);
+const OSSL_PARAM *EVP_MAC_gettable_ctx_params(const EVP_MAC *mac);
+const OSSL_PARAM *EVP_MAC_settable_ctx_params(const EVP_MAC *mac);
+const OSSL_PARAM *EVP_MAC_CTX_gettable_params(EVP_MAC_CTX *ctx);
+const OSSL_PARAM *EVP_MAC_CTX_settable_params(EVP_MAC_CTX *ctx);
+
+void EVP_MAC_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_MAC *mac, void *arg),
+ void *arg);
+int EVP_MAC_names_do_all(const EVP_MAC *mac,
+ void (*fn)(const char *name, void *data),
+ void *data);
+
+/* RAND stuff */
+EVP_RAND *EVP_RAND_fetch(OSSL_LIB_CTX *libctx, const char *algorithm,
+ const char *properties);
+int EVP_RAND_up_ref(EVP_RAND *rand);
+void EVP_RAND_free(EVP_RAND *rand);
+const char *EVP_RAND_get0_name(const EVP_RAND *rand);
+const char *EVP_RAND_get0_description(const EVP_RAND *md);
+int EVP_RAND_is_a(const EVP_RAND *rand, const char *name);
+const OSSL_PROVIDER *EVP_RAND_get0_provider(const EVP_RAND *rand);
+int EVP_RAND_get_params(EVP_RAND *rand, OSSL_PARAM params[]);
+
+EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, EVP_RAND_CTX *parent);
+void EVP_RAND_CTX_free(EVP_RAND_CTX *ctx);
+EVP_RAND *EVP_RAND_CTX_get0_rand(EVP_RAND_CTX *ctx);
+int EVP_RAND_CTX_get_params(EVP_RAND_CTX *ctx, OSSL_PARAM params[]);
+int EVP_RAND_CTX_set_params(EVP_RAND_CTX *ctx, const OSSL_PARAM params[]);
+const OSSL_PARAM *EVP_RAND_gettable_params(const EVP_RAND *rand);
+const OSSL_PARAM *EVP_RAND_gettable_ctx_params(const EVP_RAND *rand);
+const OSSL_PARAM *EVP_RAND_settable_ctx_params(const EVP_RAND *rand);
+const OSSL_PARAM *EVP_RAND_CTX_gettable_params(EVP_RAND_CTX *ctx);
+const OSSL_PARAM *EVP_RAND_CTX_settable_params(EVP_RAND_CTX *ctx);
+
+void EVP_RAND_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_RAND *rand, void *arg),
+ void *arg);
+int EVP_RAND_names_do_all(const EVP_RAND *rand,
+ void (*fn)(const char *name, void *data),
+ void *data);
+
+__owur int EVP_RAND_instantiate(EVP_RAND_CTX *ctx, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *pstr, size_t pstr_len,
+ const OSSL_PARAM params[]);
+int EVP_RAND_uninstantiate(EVP_RAND_CTX *ctx);
+__owur int EVP_RAND_generate(EVP_RAND_CTX *ctx, unsigned char *out,
+ size_t outlen, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *addin, size_t addin_len);
+int EVP_RAND_reseed(EVP_RAND_CTX *ctx, int prediction_resistance,
+ const unsigned char *ent, size_t ent_len,
+ const unsigned char *addin, size_t addin_len);
+__owur int EVP_RAND_nonce(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen);
+__owur int EVP_RAND_enable_locking(EVP_RAND_CTX *ctx);
+
+int EVP_RAND_verify_zeroization(EVP_RAND_CTX *ctx);
+unsigned int EVP_RAND_get_strength(EVP_RAND_CTX *ctx);
+int EVP_RAND_get_state(EVP_RAND_CTX *ctx);
+
+# define EVP_RAND_STATE_UNINITIALISED 0
+# define EVP_RAND_STATE_READY 1
+# define EVP_RAND_STATE_ERROR 2
+
+/* PKEY stuff */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int EVP_PKEY_decrypt_old(unsigned char *dec_key,
+ const unsigned char *enc_key,
+ int enc_key_len,
+ EVP_PKEY *private_key);
+OSSL_DEPRECATEDIN_3_0 int EVP_PKEY_encrypt_old(unsigned char *enc_key,
+ const unsigned char *key,
+ int key_len, EVP_PKEY *pub_key);
+# endif
+int EVP_PKEY_is_a(const EVP_PKEY *pkey, const char *name);
+int EVP_PKEY_type_names_do_all(const EVP_PKEY *pkey,
+ void (*fn)(const char *name, void *data),
+ void *data);
int EVP_PKEY_type(int type);
-int EVP_PKEY_id(const EVP_PKEY *pkey);
-int EVP_PKEY_base_id(const EVP_PKEY *pkey);
-int EVP_PKEY_bits(const EVP_PKEY *pkey);
-int EVP_PKEY_security_bits(const EVP_PKEY *pkey);
-int EVP_PKEY_size(const EVP_PKEY *pkey);
+int EVP_PKEY_get_id(const EVP_PKEY *pkey);
+# define EVP_PKEY_id EVP_PKEY_get_id
+int EVP_PKEY_get_base_id(const EVP_PKEY *pkey);
+# define EVP_PKEY_base_id EVP_PKEY_get_base_id
+int EVP_PKEY_get_bits(const EVP_PKEY *pkey);
+# define EVP_PKEY_bits EVP_PKEY_get_bits
+int EVP_PKEY_get_security_bits(const EVP_PKEY *pkey);
+# define EVP_PKEY_security_bits EVP_PKEY_get_security_bits
+int EVP_PKEY_get_size(const EVP_PKEY *pkey);
+# define EVP_PKEY_size EVP_PKEY_get_size
+int EVP_PKEY_can_sign(const EVP_PKEY *pkey);
int EVP_PKEY_set_type(EVP_PKEY *pkey, int type);
int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len);
-int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type);
-# ifndef OPENSSL_NO_ENGINE
+int EVP_PKEY_set_type_by_keymgmt(EVP_PKEY *pkey, EVP_KEYMGMT *keymgmt);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef OPENSSL_NO_ENGINE
+OSSL_DEPRECATEDIN_3_0
int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e);
+OSSL_DEPRECATEDIN_3_0
ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey);
-# endif
+# endif
+OSSL_DEPRECATEDIN_3_0
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key);
+OSSL_DEPRECATEDIN_3_0
void *EVP_PKEY_get0(const EVP_PKEY *pkey);
+OSSL_DEPRECATEDIN_3_0
const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len);
-# ifndef OPENSSL_NO_POLY1305
+# ifndef OPENSSL_NO_POLY1305
+OSSL_DEPRECATEDIN_3_0
const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len);
-# endif
-# ifndef OPENSSL_NO_SIPHASH
+# endif
+# ifndef OPENSSL_NO_SIPHASH
+OSSL_DEPRECATEDIN_3_0
const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len);
-# endif
+# endif
-# ifndef OPENSSL_NO_RSA
struct rsa_st;
+OSSL_DEPRECATEDIN_3_0
int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, struct rsa_st *key);
-struct rsa_st *EVP_PKEY_get0_RSA(EVP_PKEY *pkey);
+OSSL_DEPRECATEDIN_3_0
+const struct rsa_st *EVP_PKEY_get0_RSA(const EVP_PKEY *pkey);
+OSSL_DEPRECATEDIN_3_0
struct rsa_st *EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
-# endif
-# ifndef OPENSSL_NO_DSA
+
+# ifndef OPENSSL_NO_DSA
struct dsa_st;
+OSSL_DEPRECATEDIN_3_0
int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, struct dsa_st *key);
-struct dsa_st *EVP_PKEY_get0_DSA(EVP_PKEY *pkey);
+OSSL_DEPRECATEDIN_3_0
+const struct dsa_st *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey);
+OSSL_DEPRECATEDIN_3_0
struct dsa_st *EVP_PKEY_get1_DSA(EVP_PKEY *pkey);
-# endif
-# ifndef OPENSSL_NO_DH
+# endif
+
+# ifndef OPENSSL_NO_DH
struct dh_st;
-int EVP_PKEY_set1_DH(EVP_PKEY *pkey, struct dh_st *key);
-struct dh_st *EVP_PKEY_get0_DH(EVP_PKEY *pkey);
-struct dh_st *EVP_PKEY_get1_DH(EVP_PKEY *pkey);
-# endif
-# ifndef OPENSSL_NO_EC
+OSSL_DEPRECATEDIN_3_0 int EVP_PKEY_set1_DH(EVP_PKEY *pkey, struct dh_st *key);
+OSSL_DEPRECATEDIN_3_0 const struct dh_st *EVP_PKEY_get0_DH(const EVP_PKEY *pkey);
+OSSL_DEPRECATEDIN_3_0 struct dh_st *EVP_PKEY_get1_DH(EVP_PKEY *pkey);
+# endif
+
+# ifndef OPENSSL_NO_EC
struct ec_key_st;
+OSSL_DEPRECATEDIN_3_0
int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, struct ec_key_st *key);
-struct ec_key_st *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey);
+OSSL_DEPRECATEDIN_3_0
+const struct ec_key_st *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey);
+OSSL_DEPRECATEDIN_3_0
struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey);
-# endif
+# endif
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
EVP_PKEY *EVP_PKEY_new(void);
int EVP_PKEY_up_ref(EVP_PKEY *pkey);
+EVP_PKEY *EVP_PKEY_dup(EVP_PKEY *pkey);
void EVP_PKEY_free(EVP_PKEY *pkey);
+const char *EVP_PKEY_get0_description(const EVP_PKEY *pkey);
+const OSSL_PROVIDER *EVP_PKEY_get0_provider(const EVP_PKEY *key);
EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp,
long length);
-int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp);
+int i2d_PublicKey(const EVP_PKEY *a, unsigned char **pp);
+
+EVP_PKEY *d2i_PrivateKey_ex(int type, EVP_PKEY **a, const unsigned char **pp,
+ long length, OSSL_LIB_CTX *libctx,
+ const char *propq);
EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
long length);
+EVP_PKEY *d2i_AutoPrivateKey_ex(EVP_PKEY **a, const unsigned char **pp,
+ long length, OSSL_LIB_CTX *libctx,
+ const char *propq);
EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
long length);
-int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp);
+int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp);
+
+int i2d_KeyParams(const EVP_PKEY *a, unsigned char **pp);
+EVP_PKEY *d2i_KeyParams(int type, EVP_PKEY **a, const unsigned char **pp,
+ long length);
+int i2d_KeyParams_bio(BIO *bp, const EVP_PKEY *pkey);
+EVP_PKEY *d2i_KeyParams_bio(int type, EVP_PKEY **a, BIO *in);
int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from);
int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey);
int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode);
-int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b);
+int EVP_PKEY_parameters_eq(const EVP_PKEY *a, const EVP_PKEY *b);
+int EVP_PKEY_eq(const EVP_PKEY *a, const EVP_PKEY *b);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
+int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b);
+OSSL_DEPRECATEDIN_3_0
int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b);
+# endif
int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx);
@@ -1063,14 +1424,43 @@ int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx);
int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx);
+# ifndef OPENSSL_NO_STDIO
+int EVP_PKEY_print_public_fp(FILE *fp, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx);
+int EVP_PKEY_print_private_fp(FILE *fp, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx);
+int EVP_PKEY_print_params_fp(FILE *fp, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx);
+# endif
int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid);
+int EVP_PKEY_get_default_digest_name(EVP_PKEY *pkey,
+ char *mdname, size_t mdname_sz);
+int EVP_PKEY_digestsign_supports_digest(EVP_PKEY *pkey, OSSL_LIB_CTX *libctx,
+ const char *name, const char *propq);
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+/*
+ * For backwards compatibility. Use EVP_PKEY_set1_encoded_public_key in
+ * preference
+ */
+# define EVP_PKEY_set1_tls_encodedpoint(pkey, pt, ptlen) \
+ EVP_PKEY_set1_encoded_public_key((pkey), (pt), (ptlen))
+# endif
+
+int EVP_PKEY_set1_encoded_public_key(EVP_PKEY *pkey,
+ const unsigned char *pub, size_t publen);
-int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey,
- const unsigned char *pt, size_t ptlen);
-size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *pkey, unsigned char **ppt);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+/*
+ * For backwards compatibility. Use EVP_PKEY_get1_encoded_public_key in
+ * preference
+ */
+# define EVP_PKEY_get1_tls_encodedpoint(pkey, ppt) \
+ EVP_PKEY_get1_encoded_public_key((pkey), (ppt))
+# endif
-int EVP_CIPHER_type(const EVP_CIPHER *ctx);
+size_t EVP_PKEY_get1_encoded_public_key(EVP_PKEY *pkey, unsigned char **ppub);
/* calls methods */
int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
@@ -1084,6 +1474,10 @@ int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
ASN1_TYPE *param, const EVP_CIPHER *cipher,
const EVP_MD *md, int en_de);
+int PKCS5_PBE_keyivgen_ex(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md, int en_de, OSSL_LIB_CTX *libctx,
+ const char *propq);
int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
const unsigned char *salt, int saltlen, int iter,
int keylen, unsigned char *out);
@@ -1093,16 +1487,29 @@ int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
ASN1_TYPE *param, const EVP_CIPHER *cipher,
const EVP_MD *md, int en_de);
+int PKCS5_v2_PBE_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md, int en_de,
+ OSSL_LIB_CTX *libctx, const char *propq);
#ifndef OPENSSL_NO_SCRYPT
int EVP_PBE_scrypt(const char *pass, size_t passlen,
const unsigned char *salt, size_t saltlen,
uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
unsigned char *key, size_t keylen);
+int EVP_PBE_scrypt_ex(const char *pass, size_t passlen,
+ const unsigned char *salt, size_t saltlen,
+ uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
+ unsigned char *key, size_t keylen,
+ OSSL_LIB_CTX *ctx, const char *propq);
int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
int passlen, ASN1_TYPE *param,
const EVP_CIPHER *c, const EVP_MD *md, int en_de);
+int PKCS5_v2_scrypt_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass,
+ int passlen, ASN1_TYPE *param,
+ const EVP_CIPHER *c, const EVP_MD *md, int en_de,
+ OSSL_LIB_CTX *libctx, const char *propq);
#endif
void PKCS5_PBE_add(void);
@@ -1110,6 +1517,10 @@ void PKCS5_PBE_add(void);
int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de);
+int EVP_PBE_CipherInit_ex(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
+ ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
/* PBE type */
/* Can appear as the outermost AlgorithmIdentifier */
@@ -1125,6 +1536,8 @@ int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
EVP_PBE_KEYGEN *keygen);
int EVP_PBE_find(int type, int pbe_nid, int *pcnid, int *pmnid,
EVP_PBE_KEYGEN **pkeygen);
+int EVP_PBE_find_ex(int type, int pbe_nid, int *pcnid, int *pmnid,
+ EVP_PBE_KEYGEN **pkeygen, EVP_PBE_KEYGEN_EX **pkeygen_ex);
void EVP_PBE_cleanup(void);
int EVP_PBE_get(int *ptype, int *ppbe_nid, size_t num);
@@ -1141,6 +1554,7 @@ int EVP_PBE_get(int *ptype, int *ppbe_nid, size_t num);
# define ASN1_PKEY_CTRL_SET1_TLS_ENCPT 0x9
# define ASN1_PKEY_CTRL_GET1_TLS_ENCPT 0xa
+# define ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED 0xb
int EVP_PKEY_asn1_get_count(void);
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx);
@@ -1163,7 +1577,7 @@ void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst,
void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth);
void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
int (*pub_decode) (EVP_PKEY *pk,
- X509_PUBKEY *pub),
+ const X509_PUBKEY *pub),
int (*pub_encode) (X509_PUBKEY *pub,
const EVP_PKEY *pk),
int (*pub_cmp) (const EVP_PKEY *a,
@@ -1207,13 +1621,13 @@ void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth,
int (*item_verify) (EVP_MD_CTX *ctx,
const ASN1_ITEM *it,
- void *asn,
- X509_ALGOR *a,
- ASN1_BIT_STRING *sig,
+ const void *data,
+ const X509_ALGOR *a,
+ const ASN1_BIT_STRING *sig,
EVP_PKEY *pkey),
int (*item_sign) (EVP_MD_CTX *ctx,
const ASN1_ITEM *it,
- void *asn,
+ const void *data,
X509_ALGOR *alg1,
X509_ALGOR *alg2,
ASN1_BIT_STRING *sig));
@@ -1254,17 +1668,31 @@ void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_security_bits) (const EVP_PKEY
*pk));
+int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
+int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
+
+int EVP_PKEY_CTX_set1_id(EVP_PKEY_CTX *ctx, const void *id, int len);
+int EVP_PKEY_CTX_get1_id(EVP_PKEY_CTX *ctx, void *id);
+int EVP_PKEY_CTX_get1_id_len(EVP_PKEY_CTX *ctx, size_t *id_len);
+
+int EVP_PKEY_CTX_set_kem_op(EVP_PKEY_CTX *ctx, const char *op);
+
+const char *EVP_PKEY_get0_type_name(const EVP_PKEY *key);
+
# define EVP_PKEY_OP_UNDEFINED 0
# define EVP_PKEY_OP_PARAMGEN (1<<1)
# define EVP_PKEY_OP_KEYGEN (1<<2)
-# define EVP_PKEY_OP_SIGN (1<<3)
-# define EVP_PKEY_OP_VERIFY (1<<4)
-# define EVP_PKEY_OP_VERIFYRECOVER (1<<5)
-# define EVP_PKEY_OP_SIGNCTX (1<<6)
-# define EVP_PKEY_OP_VERIFYCTX (1<<7)
-# define EVP_PKEY_OP_ENCRYPT (1<<8)
-# define EVP_PKEY_OP_DECRYPT (1<<9)
-# define EVP_PKEY_OP_DERIVE (1<<10)
+# define EVP_PKEY_OP_FROMDATA (1<<3)
+# define EVP_PKEY_OP_SIGN (1<<4)
+# define EVP_PKEY_OP_VERIFY (1<<5)
+# define EVP_PKEY_OP_VERIFYRECOVER (1<<6)
+# define EVP_PKEY_OP_SIGNCTX (1<<7)
+# define EVP_PKEY_OP_VERIFYCTX (1<<8)
+# define EVP_PKEY_OP_ENCRYPT (1<<9)
+# define EVP_PKEY_OP_DECRYPT (1<<10)
+# define EVP_PKEY_OP_DERIVE (1<<11)
+# define EVP_PKEY_OP_ENCAPSULATE (1<<12)
+# define EVP_PKEY_OP_DECAPSULATE (1<<13)
# define EVP_PKEY_OP_TYPE_SIG \
(EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY | EVP_PKEY_OP_VERIFYRECOVER \
@@ -1277,44 +1705,32 @@ void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
(EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_DERIVE)
# define EVP_PKEY_OP_TYPE_GEN \
- (EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN)
-
-# define EVP_PKEY_CTX_set_signature_md(ctx, md) \
- EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \
- EVP_PKEY_CTRL_MD, 0, (void *)(md))
+ (EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN)
-# define EVP_PKEY_CTX_get_signature_md(ctx, pmd) \
- EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \
- EVP_PKEY_CTRL_GET_MD, 0, (void *)(pmd))
-# define EVP_PKEY_CTX_set_mac_key(ctx, key, len) \
- EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_KEYGEN, \
- EVP_PKEY_CTRL_SET_MAC_KEY, len, (void *)(key))
+int EVP_PKEY_CTX_set_mac_key(EVP_PKEY_CTX *ctx, const unsigned char *key,
+ int keylen);
# define EVP_PKEY_CTRL_MD 1
# define EVP_PKEY_CTRL_PEER_KEY 2
-
-# define EVP_PKEY_CTRL_PKCS7_ENCRYPT 3
-# define EVP_PKEY_CTRL_PKCS7_DECRYPT 4
-
-# define EVP_PKEY_CTRL_PKCS7_SIGN 5
-
# define EVP_PKEY_CTRL_SET_MAC_KEY 6
-
# define EVP_PKEY_CTRL_DIGESTINIT 7
-
/* Used by GOST key encryption in TLS */
# define EVP_PKEY_CTRL_SET_IV 8
-
-# define EVP_PKEY_CTRL_CMS_ENCRYPT 9
-# define EVP_PKEY_CTRL_CMS_DECRYPT 10
-# define EVP_PKEY_CTRL_CMS_SIGN 11
-
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define EVP_PKEY_CTRL_PKCS7_ENCRYPT 3
+# define EVP_PKEY_CTRL_PKCS7_DECRYPT 4
+# define EVP_PKEY_CTRL_PKCS7_SIGN 5
+# define EVP_PKEY_CTRL_CMS_ENCRYPT 9
+# define EVP_PKEY_CTRL_CMS_DECRYPT 10
+# define EVP_PKEY_CTRL_CMS_SIGN 11
+# endif
# define EVP_PKEY_CTRL_CIPHER 12
-
# define EVP_PKEY_CTRL_GET_MD 13
-
# define EVP_PKEY_CTRL_SET_DIGEST_SIZE 14
+# define EVP_PKEY_CTRL_SET1_ID 15
+# define EVP_PKEY_CTRL_GET1_ID 16
+# define EVP_PKEY_CTRL_GET1_ID_LEN 17
# define EVP_PKEY_ALG_CTRL 0x1000
@@ -1323,23 +1739,53 @@ void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
* Method handles all operations: don't assume any digest related defaults.
*/
# define EVP_PKEY_FLAG_SIGCTX_CUSTOM 4
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type);
+OSSL_DEPRECATEDIN_3_0 EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags);
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags,
+ const EVP_PKEY_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst,
+ const EVP_PKEY_METHOD *src);
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth);
+OSSL_DEPRECATEDIN_3_0 int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth);
+OSSL_DEPRECATEDIN_3_0 int EVP_PKEY_meth_remove(const EVP_PKEY_METHOD *pmeth);
+OSSL_DEPRECATEDIN_3_0 size_t EVP_PKEY_meth_get_count(void);
+OSSL_DEPRECATEDIN_3_0 const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx);
+# endif
-const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type);
-EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags);
-void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags,
- const EVP_PKEY_METHOD *meth);
-void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src);
-void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth);
-int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth);
-int EVP_PKEY_meth_remove(const EVP_PKEY_METHOD *pmeth);
-size_t EVP_PKEY_meth_get_count(void);
-const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx);
+EVP_KEYMGMT *EVP_KEYMGMT_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties);
+int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt);
+void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt);
+const OSSL_PROVIDER *EVP_KEYMGMT_get0_provider(const EVP_KEYMGMT *keymgmt);
+const char *EVP_KEYMGMT_get0_name(const EVP_KEYMGMT *keymgmt);
+const char *EVP_KEYMGMT_get0_description(const EVP_KEYMGMT *keymgmt);
+int EVP_KEYMGMT_is_a(const EVP_KEYMGMT *keymgmt, const char *name);
+void EVP_KEYMGMT_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_KEYMGMT *keymgmt, void *arg),
+ void *arg);
+int EVP_KEYMGMT_names_do_all(const EVP_KEYMGMT *keymgmt,
+ void (*fn)(const char *name, void *data),
+ void *data);
+const OSSL_PARAM *EVP_KEYMGMT_gettable_params(const EVP_KEYMGMT *keymgmt);
+const OSSL_PARAM *EVP_KEYMGMT_settable_params(const EVP_KEYMGMT *keymgmt);
+const OSSL_PARAM *EVP_KEYMGMT_gen_settable_params(const EVP_KEYMGMT *keymgmt);
EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e);
-EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx);
+EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name(OSSL_LIB_CTX *libctx,
+ const char *name,
+ const char *propquery);
+EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OSSL_LIB_CTX *libctx,
+ EVP_PKEY *pkey, const char *propquery);
+EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *ctx);
void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_CTX_is_a(EVP_PKEY_CTX *ctx, const char *keytype);
+int EVP_PKEY_CTX_get_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params);
+const OSSL_PARAM *EVP_PKEY_CTX_gettable_params(const EVP_PKEY_CTX *ctx);
+int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, const OSSL_PARAM *params);
+const OSSL_PARAM *EVP_PKEY_CTX_settable_params(const EVP_PKEY_CTX *ctx);
int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
int cmd, int p1, void *p2);
int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
@@ -1357,9 +1803,16 @@ void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen);
EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
const unsigned char *key, int keylen);
+EVP_PKEY *EVP_PKEY_new_raw_private_key_ex(OSSL_LIB_CTX *libctx,
+ const char *keytype,
+ const char *propq,
+ const unsigned char *priv, size_t len);
EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
const unsigned char *priv,
size_t len);
+EVP_PKEY *EVP_PKEY_new_raw_public_key_ex(OSSL_LIB_CTX *libctx,
+ const char *keytype, const char *propq,
+ const unsigned char *pub, size_t len);
EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
const unsigned char *pub,
size_t len);
@@ -1368,11 +1821,14 @@ int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv,
int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub,
size_t *len);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
size_t len, const EVP_CIPHER *cipher);
+# endif
void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data);
-void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx);
+void *EVP_PKEY_CTX_get_data(const EVP_PKEY_CTX *ctx);
EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx);
EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx);
@@ -1380,285 +1836,333 @@ EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx);
void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data);
void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx);
+void EVP_SIGNATURE_free(EVP_SIGNATURE *signature);
+int EVP_SIGNATURE_up_ref(EVP_SIGNATURE *signature);
+OSSL_PROVIDER *EVP_SIGNATURE_get0_provider(const EVP_SIGNATURE *signature);
+EVP_SIGNATURE *EVP_SIGNATURE_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties);
+int EVP_SIGNATURE_is_a(const EVP_SIGNATURE *signature, const char *name);
+const char *EVP_SIGNATURE_get0_name(const EVP_SIGNATURE *signature);
+const char *EVP_SIGNATURE_get0_description(const EVP_SIGNATURE *signature);
+void EVP_SIGNATURE_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_SIGNATURE *signature,
+ void *data),
+ void *data);
+int EVP_SIGNATURE_names_do_all(const EVP_SIGNATURE *signature,
+ void (*fn)(const char *name, void *data),
+ void *data);
+const OSSL_PARAM *EVP_SIGNATURE_gettable_ctx_params(const EVP_SIGNATURE *sig);
+const OSSL_PARAM *EVP_SIGNATURE_settable_ctx_params(const EVP_SIGNATURE *sig);
+
+void EVP_ASYM_CIPHER_free(EVP_ASYM_CIPHER *cipher);
+int EVP_ASYM_CIPHER_up_ref(EVP_ASYM_CIPHER *cipher);
+OSSL_PROVIDER *EVP_ASYM_CIPHER_get0_provider(const EVP_ASYM_CIPHER *cipher);
+EVP_ASYM_CIPHER *EVP_ASYM_CIPHER_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties);
+int EVP_ASYM_CIPHER_is_a(const EVP_ASYM_CIPHER *cipher, const char *name);
+const char *EVP_ASYM_CIPHER_get0_name(const EVP_ASYM_CIPHER *cipher);
+const char *EVP_ASYM_CIPHER_get0_description(const EVP_ASYM_CIPHER *cipher);
+void EVP_ASYM_CIPHER_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_ASYM_CIPHER *cipher,
+ void *arg),
+ void *arg);
+int EVP_ASYM_CIPHER_names_do_all(const EVP_ASYM_CIPHER *cipher,
+ void (*fn)(const char *name, void *data),
+ void *data);
+const OSSL_PARAM *EVP_ASYM_CIPHER_gettable_ctx_params(const EVP_ASYM_CIPHER *ciph);
+const OSSL_PARAM *EVP_ASYM_CIPHER_settable_ctx_params(const EVP_ASYM_CIPHER *ciph);
+
+void EVP_KEM_free(EVP_KEM *wrap);
+int EVP_KEM_up_ref(EVP_KEM *wrap);
+OSSL_PROVIDER *EVP_KEM_get0_provider(const EVP_KEM *wrap);
+EVP_KEM *EVP_KEM_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties);
+int EVP_KEM_is_a(const EVP_KEM *wrap, const char *name);
+const char *EVP_KEM_get0_name(const EVP_KEM *wrap);
+const char *EVP_KEM_get0_description(const EVP_KEM *wrap);
+void EVP_KEM_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_KEM *wrap, void *arg), void *arg);
+int EVP_KEM_names_do_all(const EVP_KEM *wrap,
+ void (*fn)(const char *name, void *data), void *data);
+const OSSL_PARAM *EVP_KEM_gettable_ctx_params(const EVP_KEM *kem);
+const OSSL_PARAM *EVP_KEM_settable_ctx_params(const EVP_KEM *kem);
+
int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_sign_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen);
int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_verify_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
const unsigned char *sig, size_t siglen,
const unsigned char *tbs, size_t tbslen);
int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_verify_recover_init_ex(EVP_PKEY_CTX *ctx,
+ const OSSL_PARAM params[]);
int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx,
unsigned char *rout, size_t *routlen,
const unsigned char *sig, size_t siglen);
int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_encrypt_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
unsigned char *out, size_t *outlen,
const unsigned char *in, size_t inlen);
int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_decrypt_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
unsigned char *out, size_t *outlen,
const unsigned char *in, size_t inlen);
int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
+int EVP_PKEY_derive_set_peer_ex(EVP_PKEY_CTX *ctx, EVP_PKEY *peer,
+ int validate_peer);
int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer);
int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
+int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
+int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx,
+ unsigned char *wrappedkey, size_t *wrappedkeylen,
+ unsigned char *genkey, size_t *genkeylen);
+int EVP_PKEY_decapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
+int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx,
+ unsigned char *unwrapped, size_t *unwrappedlen,
+ const unsigned char *wrapped, size_t wrappedlen);
+
typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_fromdata_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, int selection,
+ OSSL_PARAM param[]);
+const OSSL_PARAM *EVP_PKEY_fromdata_settable(EVP_PKEY_CTX *ctx, int selection);
+
+int EVP_PKEY_todata(const EVP_PKEY *pkey, int selection, OSSL_PARAM **params);
+int EVP_PKEY_export(const EVP_PKEY *pkey, int selection,
+ OSSL_CALLBACK *export_cb, void *export_cbarg);
+
+const OSSL_PARAM *EVP_PKEY_gettable_params(const EVP_PKEY *pkey);
+int EVP_PKEY_get_params(const EVP_PKEY *pkey, OSSL_PARAM params[]);
+int EVP_PKEY_get_int_param(const EVP_PKEY *pkey, const char *key_name,
+ int *out);
+int EVP_PKEY_get_size_t_param(const EVP_PKEY *pkey, const char *key_name,
+ size_t *out);
+int EVP_PKEY_get_bn_param(const EVP_PKEY *pkey, const char *key_name,
+ BIGNUM **bn);
+int EVP_PKEY_get_utf8_string_param(const EVP_PKEY *pkey, const char *key_name,
+ char *str, size_t max_buf_sz, size_t *out_sz);
+int EVP_PKEY_get_octet_string_param(const EVP_PKEY *pkey, const char *key_name,
+ unsigned char *buf, size_t max_buf_sz,
+ size_t *out_sz);
+
+const OSSL_PARAM *EVP_PKEY_settable_params(const EVP_PKEY *pkey);
+int EVP_PKEY_set_params(EVP_PKEY *pkey, OSSL_PARAM params[]);
+int EVP_PKEY_set_int_param(EVP_PKEY *pkey, const char *key_name, int in);
+int EVP_PKEY_set_size_t_param(EVP_PKEY *pkey, const char *key_name, size_t in);
+int EVP_PKEY_set_bn_param(EVP_PKEY *pkey, const char *key_name,
+ const BIGNUM *bn);
+int EVP_PKEY_set_utf8_string_param(EVP_PKEY *pkey, const char *key_name,
+ const char *str);
+int EVP_PKEY_set_octet_string_param(EVP_PKEY *pkey, const char *key_name,
+ const unsigned char *buf, size_t bsize);
+
+int EVP_PKEY_get_ec_point_conv_form(const EVP_PKEY *pkey);
+int EVP_PKEY_get_field_type(const EVP_PKEY *pkey);
+
+EVP_PKEY *EVP_PKEY_Q_keygen(OSSL_LIB_CTX *libctx, const char *propq,
+ const char *type, ...);
int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx);
int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx);
int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
+int EVP_PKEY_generate(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
int EVP_PKEY_check(EVP_PKEY_CTX *ctx);
int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_public_check_quick(EVP_PKEY_CTX *ctx);
int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_param_check_quick(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_pairwise_check(EVP_PKEY_CTX *ctx);
+
+# define EVP_PKEY_get_ex_new_index(l, p, newf, dupf, freef) \
+ CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_EVP_PKEY, l, p, newf, dupf, freef)
+int EVP_PKEY_set_ex_data(EVP_PKEY *key, int idx, void *arg);
+void *EVP_PKEY_get_ex_data(const EVP_PKEY *key, int idx);
void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb);
EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx);
int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx);
-
-void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth,
- int (*init) (EVP_PKEY_CTX *ctx));
-
-void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth,
- int (*copy) (EVP_PKEY_CTX *dst,
- EVP_PKEY_CTX *src));
-
-void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth,
- void (*cleanup) (EVP_PKEY_CTX *ctx));
-
-void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth,
- int (*paramgen_init) (EVP_PKEY_CTX *ctx),
- int (*paramgen) (EVP_PKEY_CTX *ctx,
- EVP_PKEY *pkey));
-
-void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth,
- int (*keygen_init) (EVP_PKEY_CTX *ctx),
- int (*keygen) (EVP_PKEY_CTX *ctx,
- EVP_PKEY *pkey));
-
-void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth,
- int (*sign_init) (EVP_PKEY_CTX *ctx),
- int (*sign) (EVP_PKEY_CTX *ctx,
- unsigned char *sig, size_t *siglen,
- const unsigned char *tbs,
- size_t tbslen));
-
-void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth,
- int (*verify_init) (EVP_PKEY_CTX *ctx),
- int (*verify) (EVP_PKEY_CTX *ctx,
- const unsigned char *sig,
- size_t siglen,
- const unsigned char *tbs,
- size_t tbslen));
-
-void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth,
- int (*verify_recover_init) (EVP_PKEY_CTX
- *ctx),
- int (*verify_recover) (EVP_PKEY_CTX
- *ctx,
- unsigned char
- *sig,
- size_t *siglen,
- const unsigned
- char *tbs,
- size_t tbslen));
-
-void EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth,
- int (*signctx_init) (EVP_PKEY_CTX *ctx,
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth,
+ int (*init) (EVP_PKEY_CTX *ctx));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_copy
+ (EVP_PKEY_METHOD *pmeth, int (*copy) (EVP_PKEY_CTX *dst,
+ const EVP_PKEY_CTX *src));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_cleanup
+ (EVP_PKEY_METHOD *pmeth, void (*cleanup) (EVP_PKEY_CTX *ctx));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_paramgen
+ (EVP_PKEY_METHOD *pmeth, int (*paramgen_init) (EVP_PKEY_CTX *ctx),
+ int (*paramgen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_keygen
+ (EVP_PKEY_METHOD *pmeth, int (*keygen_init) (EVP_PKEY_CTX *ctx),
+ int (*keygen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_sign
+ (EVP_PKEY_METHOD *pmeth, int (*sign_init) (EVP_PKEY_CTX *ctx),
+ int (*sign) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
+ const unsigned char *tbs, size_t tbslen));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_verify
+ (EVP_PKEY_METHOD *pmeth, int (*verify_init) (EVP_PKEY_CTX *ctx),
+ int (*verify) (EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen,
+ const unsigned char *tbs, size_t tbslen));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_verify_recover
+ (EVP_PKEY_METHOD *pmeth, int (*verify_recover_init) (EVP_PKEY_CTX *ctx),
+ int (*verify_recover) (EVP_PKEY_CTX *ctx, unsigned char *sig,
+ size_t *siglen, const unsigned char *tbs,
+ size_t tbslen));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_signctx
+ (EVP_PKEY_METHOD *pmeth, int (*signctx_init) (EVP_PKEY_CTX *ctx,
+ EVP_MD_CTX *mctx),
+ int (*signctx) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
+ EVP_MD_CTX *mctx));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_verifyctx
+ (EVP_PKEY_METHOD *pmeth, int (*verifyctx_init) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx),
- int (*signctx) (EVP_PKEY_CTX *ctx,
- unsigned char *sig,
- size_t *siglen,
- EVP_MD_CTX *mctx));
-
-void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth,
- int (*verifyctx_init) (EVP_PKEY_CTX *ctx,
- EVP_MD_CTX *mctx),
- int (*verifyctx) (EVP_PKEY_CTX *ctx,
- const unsigned char *sig,
- int siglen,
+ int (*verifyctx) (EVP_PKEY_CTX *ctx, const unsigned char *sig, int siglen,
+ EVP_MD_CTX *mctx));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_encrypt
+ (EVP_PKEY_METHOD *pmeth, int (*encrypt_init) (EVP_PKEY_CTX *ctx),
+ int (*encryptfn) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
+ const unsigned char *in, size_t inlen));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_decrypt
+ (EVP_PKEY_METHOD *pmeth, int (*decrypt_init) (EVP_PKEY_CTX *ctx),
+ int (*decrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
+ const unsigned char *in, size_t inlen));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_derive
+ (EVP_PKEY_METHOD *pmeth, int (*derive_init) (EVP_PKEY_CTX *ctx),
+ int (*derive) (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_ctrl
+ (EVP_PKEY_METHOD *pmeth, int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1,
+ void *p2),
+ int (*ctrl_str) (EVP_PKEY_CTX *ctx, const char *type, const char *value));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_digestsign
+ (EVP_PKEY_METHOD *pmeth,
+ int (*digestsign) (EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen,
+ const unsigned char *tbs, size_t tbslen));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_digestverify
+ (EVP_PKEY_METHOD *pmeth,
+ int (*digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig,
+ size_t siglen, const unsigned char *tbs,
+ size_t tbslen));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_check
+ (EVP_PKEY_METHOD *pmeth, int (*check) (EVP_PKEY *pkey));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_public_check
+ (EVP_PKEY_METHOD *pmeth, int (*check) (EVP_PKEY *pkey));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_param_check
+ (EVP_PKEY_METHOD *pmeth, int (*check) (EVP_PKEY *pkey));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_set_digest_custom
+ (EVP_PKEY_METHOD *pmeth, int (*digest_custom) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_init
+ (const EVP_PKEY_METHOD *pmeth, int (**pinit) (EVP_PKEY_CTX *ctx));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_copy
+ (const EVP_PKEY_METHOD *pmeth, int (**pcopy) (EVP_PKEY_CTX *dst,
+ const EVP_PKEY_CTX *src));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_cleanup
+ (const EVP_PKEY_METHOD *pmeth, void (**pcleanup) (EVP_PKEY_CTX *ctx));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_paramgen
+ (const EVP_PKEY_METHOD *pmeth, int (**pparamgen_init) (EVP_PKEY_CTX *ctx),
+ int (**pparamgen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_keygen
+ (const EVP_PKEY_METHOD *pmeth, int (**pkeygen_init) (EVP_PKEY_CTX *ctx),
+ int (**pkeygen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_sign
+ (const EVP_PKEY_METHOD *pmeth, int (**psign_init) (EVP_PKEY_CTX *ctx),
+ int (**psign) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
+ const unsigned char *tbs, size_t tbslen));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_verify
+ (const EVP_PKEY_METHOD *pmeth, int (**pverify_init) (EVP_PKEY_CTX *ctx),
+ int (**pverify) (EVP_PKEY_CTX *ctx, const unsigned char *sig,
+ size_t siglen, const unsigned char *tbs, size_t tbslen));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_verify_recover
+ (const EVP_PKEY_METHOD *pmeth,
+ int (**pverify_recover_init) (EVP_PKEY_CTX *ctx),
+ int (**pverify_recover) (EVP_PKEY_CTX *ctx, unsigned char *sig,
+ size_t *siglen, const unsigned char *tbs,
+ size_t tbslen));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_signctx
+ (const EVP_PKEY_METHOD *pmeth,
+ int (**psignctx_init) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx),
+ int (**psignctx) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
+ EVP_MD_CTX *mctx));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_verifyctx
+ (const EVP_PKEY_METHOD *pmeth,
+ int (**pverifyctx_init) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx),
+ int (**pverifyctx) (EVP_PKEY_CTX *ctx, const unsigned char *sig,
+ int siglen, EVP_MD_CTX *mctx));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_encrypt
+ (const EVP_PKEY_METHOD *pmeth, int (**pencrypt_init) (EVP_PKEY_CTX *ctx),
+ int (**pencryptfn) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
+ const unsigned char *in, size_t inlen));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_decrypt
+ (const EVP_PKEY_METHOD *pmeth, int (**pdecrypt_init) (EVP_PKEY_CTX *ctx),
+ int (**pdecrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
+ const unsigned char *in, size_t inlen));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_derive
+ (const EVP_PKEY_METHOD *pmeth, int (**pderive_init) (EVP_PKEY_CTX *ctx),
+ int (**pderive) (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_ctrl
+ (const EVP_PKEY_METHOD *pmeth,
+ int (**pctrl) (EVP_PKEY_CTX *ctx, int type, int p1, void *p2),
+ int (**pctrl_str) (EVP_PKEY_CTX *ctx, const char *type,
+ const char *value));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_digestsign
+ (const EVP_PKEY_METHOD *pmeth,
+ int (**digestsign) (EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen,
+ const unsigned char *tbs, size_t tbslen));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_digestverify
+ (const EVP_PKEY_METHOD *pmeth,
+ int (**digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig,
+ size_t siglen, const unsigned char *tbs,
+ size_t tbslen));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_check
+ (const EVP_PKEY_METHOD *pmeth, int (**pcheck) (EVP_PKEY *pkey));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_public_check
+ (const EVP_PKEY_METHOD *pmeth, int (**pcheck) (EVP_PKEY *pkey));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_param_check
+ (const EVP_PKEY_METHOD *pmeth, int (**pcheck) (EVP_PKEY *pkey));
+OSSL_DEPRECATEDIN_3_0 void EVP_PKEY_meth_get_digest_custom
+ (const EVP_PKEY_METHOD *pmeth,
+ int (**pdigest_custom) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx));
+# endif
+
+void EVP_KEYEXCH_free(EVP_KEYEXCH *exchange);
+int EVP_KEYEXCH_up_ref(EVP_KEYEXCH *exchange);
+EVP_KEYEXCH *EVP_KEYEXCH_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
+ const char *properties);
+OSSL_PROVIDER *EVP_KEYEXCH_get0_provider(const EVP_KEYEXCH *exchange);
+int EVP_KEYEXCH_is_a(const EVP_KEYEXCH *keyexch, const char *name);
+const char *EVP_KEYEXCH_get0_name(const EVP_KEYEXCH *keyexch);
+const char *EVP_KEYEXCH_get0_description(const EVP_KEYEXCH *keyexch);
+void EVP_KEYEXCH_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_KEYEXCH *keyexch, void *data),
+ void *data);
+int EVP_KEYEXCH_names_do_all(const EVP_KEYEXCH *keyexch,
+ void (*fn)(const char *name, void *data),
+ void *data);
+const OSSL_PARAM *EVP_KEYEXCH_gettable_ctx_params(const EVP_KEYEXCH *keyexch);
+const OSSL_PARAM *EVP_KEYEXCH_settable_ctx_params(const EVP_KEYEXCH *keyexch);
-void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth,
- int (*encrypt_init) (EVP_PKEY_CTX *ctx),
- int (*encryptfn) (EVP_PKEY_CTX *ctx,
- unsigned char *out,
- size_t *outlen,
- const unsigned char *in,
- size_t inlen));
-
-void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth,
- int (*decrypt_init) (EVP_PKEY_CTX *ctx),
- int (*decrypt) (EVP_PKEY_CTX *ctx,
- unsigned char *out,
- size_t *outlen,
- const unsigned char *in,
- size_t inlen));
-
-void EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth,
- int (*derive_init) (EVP_PKEY_CTX *ctx),
- int (*derive) (EVP_PKEY_CTX *ctx,
- unsigned char *key,
- size_t *keylen));
-
-void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth,
- int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1,
- void *p2),
- int (*ctrl_str) (EVP_PKEY_CTX *ctx,
- const char *type,
- const char *value));
-
-void EVP_PKEY_meth_set_digestsign(EVP_PKEY_METHOD *pmeth,
- int (*digestsign) (EVP_MD_CTX *ctx,
- unsigned char *sig,
- size_t *siglen,
- const unsigned char *tbs,
- size_t tbslen));
-
-void EVP_PKEY_meth_set_digestverify(EVP_PKEY_METHOD *pmeth,
- int (*digestverify) (EVP_MD_CTX *ctx,
- const unsigned char *sig,
- size_t siglen,
- const unsigned char *tbs,
- size_t tbslen));
-
-void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth,
- int (*check) (EVP_PKEY *pkey));
-
-void EVP_PKEY_meth_set_public_check(EVP_PKEY_METHOD *pmeth,
- int (*check) (EVP_PKEY *pkey));
-
-void EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth,
- int (*check) (EVP_PKEY *pkey));
-
-void EVP_PKEY_meth_set_digest_custom(EVP_PKEY_METHOD *pmeth,
- int (*digest_custom) (EVP_PKEY_CTX *ctx,
- EVP_MD_CTX *mctx));
-
-void EVP_PKEY_meth_get_init(const EVP_PKEY_METHOD *pmeth,
- int (**pinit) (EVP_PKEY_CTX *ctx));
-
-void EVP_PKEY_meth_get_copy(const EVP_PKEY_METHOD *pmeth,
- int (**pcopy) (EVP_PKEY_CTX *dst,
- EVP_PKEY_CTX *src));
-
-void EVP_PKEY_meth_get_cleanup(const EVP_PKEY_METHOD *pmeth,
- void (**pcleanup) (EVP_PKEY_CTX *ctx));
-
-void EVP_PKEY_meth_get_paramgen(const EVP_PKEY_METHOD *pmeth,
- int (**pparamgen_init) (EVP_PKEY_CTX *ctx),
- int (**pparamgen) (EVP_PKEY_CTX *ctx,
- EVP_PKEY *pkey));
-
-void EVP_PKEY_meth_get_keygen(const EVP_PKEY_METHOD *pmeth,
- int (**pkeygen_init) (EVP_PKEY_CTX *ctx),
- int (**pkeygen) (EVP_PKEY_CTX *ctx,
- EVP_PKEY *pkey));
-
-void EVP_PKEY_meth_get_sign(const EVP_PKEY_METHOD *pmeth,
- int (**psign_init) (EVP_PKEY_CTX *ctx),
- int (**psign) (EVP_PKEY_CTX *ctx,
- unsigned char *sig, size_t *siglen,
- const unsigned char *tbs,
- size_t tbslen));
-
-void EVP_PKEY_meth_get_verify(const EVP_PKEY_METHOD *pmeth,
- int (**pverify_init) (EVP_PKEY_CTX *ctx),
- int (**pverify) (EVP_PKEY_CTX *ctx,
- const unsigned char *sig,
- size_t siglen,
- const unsigned char *tbs,
- size_t tbslen));
-
-void EVP_PKEY_meth_get_verify_recover(const EVP_PKEY_METHOD *pmeth,
- int (**pverify_recover_init) (EVP_PKEY_CTX
- *ctx),
- int (**pverify_recover) (EVP_PKEY_CTX
- *ctx,
- unsigned char
- *sig,
- size_t *siglen,
- const unsigned
- char *tbs,
- size_t tbslen));
-
-void EVP_PKEY_meth_get_signctx(const EVP_PKEY_METHOD *pmeth,
- int (**psignctx_init) (EVP_PKEY_CTX *ctx,
- EVP_MD_CTX *mctx),
- int (**psignctx) (EVP_PKEY_CTX *ctx,
- unsigned char *sig,
- size_t *siglen,
- EVP_MD_CTX *mctx));
-
-void EVP_PKEY_meth_get_verifyctx(const EVP_PKEY_METHOD *pmeth,
- int (**pverifyctx_init) (EVP_PKEY_CTX *ctx,
- EVP_MD_CTX *mctx),
- int (**pverifyctx) (EVP_PKEY_CTX *ctx,
- const unsigned char *sig,
- int siglen,
- EVP_MD_CTX *mctx));
-
-void EVP_PKEY_meth_get_encrypt(const EVP_PKEY_METHOD *pmeth,
- int (**pencrypt_init) (EVP_PKEY_CTX *ctx),
- int (**pencryptfn) (EVP_PKEY_CTX *ctx,
- unsigned char *out,
- size_t *outlen,
- const unsigned char *in,
- size_t inlen));
-
-void EVP_PKEY_meth_get_decrypt(const EVP_PKEY_METHOD *pmeth,
- int (**pdecrypt_init) (EVP_PKEY_CTX *ctx),
- int (**pdecrypt) (EVP_PKEY_CTX *ctx,
- unsigned char *out,
- size_t *outlen,
- const unsigned char *in,
- size_t inlen));
-
-void EVP_PKEY_meth_get_derive(const EVP_PKEY_METHOD *pmeth,
- int (**pderive_init) (EVP_PKEY_CTX *ctx),
- int (**pderive) (EVP_PKEY_CTX *ctx,
- unsigned char *key,
- size_t *keylen));
-
-void EVP_PKEY_meth_get_ctrl(const EVP_PKEY_METHOD *pmeth,
- int (**pctrl) (EVP_PKEY_CTX *ctx, int type, int p1,
- void *p2),
- int (**pctrl_str) (EVP_PKEY_CTX *ctx,
- const char *type,
- const char *value));
-
-void EVP_PKEY_meth_get_digestsign(EVP_PKEY_METHOD *pmeth,
- int (**digestsign) (EVP_MD_CTX *ctx,
- unsigned char *sig,
- size_t *siglen,
- const unsigned char *tbs,
- size_t tbslen));
-
-void EVP_PKEY_meth_get_digestverify(EVP_PKEY_METHOD *pmeth,
- int (**digestverify) (EVP_MD_CTX *ctx,
- const unsigned char *sig,
- size_t siglen,
- const unsigned char *tbs,
- size_t tbslen));
-
-void EVP_PKEY_meth_get_check(const EVP_PKEY_METHOD *pmeth,
- int (**pcheck) (EVP_PKEY *pkey));
-
-void EVP_PKEY_meth_get_public_check(const EVP_PKEY_METHOD *pmeth,
- int (**pcheck) (EVP_PKEY *pkey));
-
-void EVP_PKEY_meth_get_param_check(const EVP_PKEY_METHOD *pmeth,
- int (**pcheck) (EVP_PKEY *pkey));
-
-void EVP_PKEY_meth_get_digest_custom(EVP_PKEY_METHOD *pmeth,
- int (**pdigest_custom) (EVP_PKEY_CTX *ctx,
- EVP_MD_CTX *mctx));
void EVP_add_alg_module(void);
+int EVP_PKEY_CTX_set_group_name(EVP_PKEY_CTX *ctx, const char *name);
+int EVP_PKEY_CTX_get_group_name(EVP_PKEY_CTX *ctx, char *name, size_t namelen);
+int EVP_PKEY_get_group_name(const EVP_PKEY *pkey, char *name, size_t name_sz,
+ size_t *gname_len);
+
+OSSL_LIB_CTX *EVP_PKEY_CTX_get0_libctx(EVP_PKEY_CTX *ctx);
+const char *EVP_PKEY_CTX_get0_propq(const EVP_PKEY_CTX *ctx);
+const OSSL_PROVIDER *EVP_PKEY_CTX_get0_provider(const EVP_PKEY_CTX *ctx);
# ifdef __cplusplus
}
diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h
index b4ea90ae9df3..a5053f6cd23a 100644
--- a/include/openssl/evperr.h
+++ b/include/openssl/evperr.h
@@ -2,190 +2,117 @@
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_EVPERR_H
-# define HEADER_EVPERR_H
+#ifndef OPENSSL_EVPERR_H
+# define OPENSSL_EVPERR_H
+# pragma once
+# include <openssl/opensslconf.h>
# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_EVP_strings(void);
-/*
- * EVP function codes.
- */
-# define EVP_F_AESNI_INIT_KEY 165
-# define EVP_F_AESNI_XTS_INIT_KEY 207
-# define EVP_F_AES_GCM_CTRL 196
-# define EVP_F_AES_INIT_KEY 133
-# define EVP_F_AES_OCB_CIPHER 169
-# define EVP_F_AES_T4_INIT_KEY 178
-# define EVP_F_AES_T4_XTS_INIT_KEY 208
-# define EVP_F_AES_WRAP_CIPHER 170
-# define EVP_F_AES_XTS_INIT_KEY 209
-# define EVP_F_ALG_MODULE_INIT 177
-# define EVP_F_ARIA_CCM_INIT_KEY 175
-# define EVP_F_ARIA_GCM_CTRL 197
-# define EVP_F_ARIA_GCM_INIT_KEY 176
-# define EVP_F_ARIA_INIT_KEY 185
-# define EVP_F_B64_NEW 198
-# define EVP_F_CAMELLIA_INIT_KEY 159
-# define EVP_F_CHACHA20_POLY1305_CTRL 182
-# define EVP_F_CMLL_T4_INIT_KEY 179
-# define EVP_F_DES_EDE3_WRAP_CIPHER 171
-# define EVP_F_DO_SIGVER_INIT 161
-# define EVP_F_ENC_NEW 199
-# define EVP_F_EVP_CIPHERINIT_EX 123
-# define EVP_F_EVP_CIPHER_ASN1_TO_PARAM 204
-# define EVP_F_EVP_CIPHER_CTX_COPY 163
-# define EVP_F_EVP_CIPHER_CTX_CTRL 124
-# define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH 122
-# define EVP_F_EVP_CIPHER_PARAM_TO_ASN1 205
-# define EVP_F_EVP_DECRYPTFINAL_EX 101
-# define EVP_F_EVP_DECRYPTUPDATE 166
-# define EVP_F_EVP_DIGESTFINALXOF 174
-# define EVP_F_EVP_DIGESTINIT_EX 128
-# define EVP_F_EVP_ENCRYPTDECRYPTUPDATE 219
-# define EVP_F_EVP_ENCRYPTFINAL_EX 127
-# define EVP_F_EVP_ENCRYPTUPDATE 167
-# define EVP_F_EVP_MD_CTX_COPY_EX 110
-# define EVP_F_EVP_MD_SIZE 162
-# define EVP_F_EVP_OPENINIT 102
-# define EVP_F_EVP_PBE_ALG_ADD 115
-# define EVP_F_EVP_PBE_ALG_ADD_TYPE 160
-# define EVP_F_EVP_PBE_CIPHERINIT 116
-# define EVP_F_EVP_PBE_SCRYPT 181
-# define EVP_F_EVP_PKCS82PKEY 111
-# define EVP_F_EVP_PKEY2PKCS8 113
-# define EVP_F_EVP_PKEY_ASN1_ADD0 188
-# define EVP_F_EVP_PKEY_CHECK 186
-# define EVP_F_EVP_PKEY_COPY_PARAMETERS 103
-# define EVP_F_EVP_PKEY_CTX_CTRL 137
-# define EVP_F_EVP_PKEY_CTX_CTRL_STR 150
-# define EVP_F_EVP_PKEY_CTX_DUP 156
-# define EVP_F_EVP_PKEY_CTX_MD 168
-# define EVP_F_EVP_PKEY_DECRYPT 104
-# define EVP_F_EVP_PKEY_DECRYPT_INIT 138
-# define EVP_F_EVP_PKEY_DECRYPT_OLD 151
-# define EVP_F_EVP_PKEY_DERIVE 153
-# define EVP_F_EVP_PKEY_DERIVE_INIT 154
-# define EVP_F_EVP_PKEY_DERIVE_SET_PEER 155
-# define EVP_F_EVP_PKEY_ENCRYPT 105
-# define EVP_F_EVP_PKEY_ENCRYPT_INIT 139
-# define EVP_F_EVP_PKEY_ENCRYPT_OLD 152
-# define EVP_F_EVP_PKEY_GET0_DH 119
-# define EVP_F_EVP_PKEY_GET0_DSA 120
-# define EVP_F_EVP_PKEY_GET0_EC_KEY 131
-# define EVP_F_EVP_PKEY_GET0_HMAC 183
-# define EVP_F_EVP_PKEY_GET0_POLY1305 184
-# define EVP_F_EVP_PKEY_GET0_RSA 121
-# define EVP_F_EVP_PKEY_GET0_SIPHASH 172
-# define EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY 202
-# define EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY 203
-# define EVP_F_EVP_PKEY_KEYGEN 146
-# define EVP_F_EVP_PKEY_KEYGEN_INIT 147
-# define EVP_F_EVP_PKEY_METH_ADD0 194
-# define EVP_F_EVP_PKEY_METH_NEW 195
-# define EVP_F_EVP_PKEY_NEW 106
-# define EVP_F_EVP_PKEY_NEW_CMAC_KEY 193
-# define EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY 191
-# define EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY 192
-# define EVP_F_EVP_PKEY_PARAMGEN 148
-# define EVP_F_EVP_PKEY_PARAMGEN_INIT 149
-# define EVP_F_EVP_PKEY_PARAM_CHECK 189
-# define EVP_F_EVP_PKEY_PUBLIC_CHECK 190
-# define EVP_F_EVP_PKEY_SET1_ENGINE 187
-# define EVP_F_EVP_PKEY_SET_ALIAS_TYPE 206
-# define EVP_F_EVP_PKEY_SIGN 140
-# define EVP_F_EVP_PKEY_SIGN_INIT 141
-# define EVP_F_EVP_PKEY_VERIFY 142
-# define EVP_F_EVP_PKEY_VERIFY_INIT 143
-# define EVP_F_EVP_PKEY_VERIFY_RECOVER 144
-# define EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT 145
-# define EVP_F_EVP_SIGNFINAL 107
-# define EVP_F_EVP_VERIFYFINAL 108
-# define EVP_F_INT_CTX_NEW 157
-# define EVP_F_OK_NEW 200
-# define EVP_F_PKCS5_PBE_KEYIVGEN 117
-# define EVP_F_PKCS5_V2_PBE_KEYIVGEN 118
-# define EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN 164
-# define EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN 180
-# define EVP_F_PKEY_SET_TYPE 158
-# define EVP_F_RC2_MAGIC_TO_METH 109
-# define EVP_F_RC5_CTRL 125
-# define EVP_F_R_32_12_16_INIT_KEY 242
-# define EVP_F_S390X_AES_GCM_CTRL 201
-# define EVP_F_UPDATE 173
/*
* EVP reason codes.
*/
# define EVP_R_AES_KEY_SETUP_FAILED 143
# define EVP_R_ARIA_KEY_SETUP_FAILED 176
+# define EVP_R_BAD_ALGORITHM_NAME 200
# define EVP_R_BAD_DECRYPT 100
# define EVP_R_BAD_KEY_LENGTH 195
# define EVP_R_BUFFER_TOO_SMALL 155
+# define EVP_R_CACHE_CONSTANTS_FAILED 225
# define EVP_R_CAMELLIA_KEY_SETUP_FAILED 157
+# define EVP_R_CANNOT_GET_PARAMETERS 197
+# define EVP_R_CANNOT_SET_PARAMETERS 198
+# define EVP_R_CIPHER_NOT_GCM_MODE 184
# define EVP_R_CIPHER_PARAMETER_ERROR 122
# define EVP_R_COMMAND_NOT_SUPPORTED 147
+# define EVP_R_CONFLICTING_ALGORITHM_NAME 201
# define EVP_R_COPY_ERROR 173
# define EVP_R_CTRL_NOT_IMPLEMENTED 132
# define EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED 133
# define EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH 138
# define EVP_R_DECODE_ERROR 114
+# define EVP_R_DEFAULT_QUERY_PARSE_ERROR 210
# define EVP_R_DIFFERENT_KEY_TYPES 101
# define EVP_R_DIFFERENT_PARAMETERS 153
# define EVP_R_ERROR_LOADING_SECTION 165
-# define EVP_R_ERROR_SETTING_FIPS_MODE 166
# define EVP_R_EXPECTING_AN_HMAC_KEY 174
# define EVP_R_EXPECTING_AN_RSA_KEY 127
# define EVP_R_EXPECTING_A_DH_KEY 128
# define EVP_R_EXPECTING_A_DSA_KEY 129
+# define EVP_R_EXPECTING_A_ECX_KEY 219
# define EVP_R_EXPECTING_A_EC_KEY 142
# define EVP_R_EXPECTING_A_POLY1305_KEY 164
# define EVP_R_EXPECTING_A_SIPHASH_KEY 175
-# define EVP_R_FIPS_MODE_NOT_SUPPORTED 167
+# define EVP_R_FINAL_ERROR 188
+# define EVP_R_GENERATE_ERROR 214
# define EVP_R_GET_RAW_KEY_FAILED 182
# define EVP_R_ILLEGAL_SCRYPT_PARAMETERS 171
+# define EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS 204
+# define EVP_R_INACCESSIBLE_KEY 203
# define EVP_R_INITIALIZATION_ERROR 134
# define EVP_R_INPUT_NOT_INITIALIZED 111
+# define EVP_R_INVALID_CUSTOM_LENGTH 185
# define EVP_R_INVALID_DIGEST 152
-# define EVP_R_INVALID_FIPS_MODE 168
# define EVP_R_INVALID_IV_LENGTH 194
# define EVP_R_INVALID_KEY 163
# define EVP_R_INVALID_KEY_LENGTH 130
+# define EVP_R_INVALID_LENGTH 221
+# define EVP_R_INVALID_NULL_ALGORITHM 218
# define EVP_R_INVALID_OPERATION 148
-# define EVP_R_KEYGEN_FAILURE 120
+# define EVP_R_INVALID_PROVIDER_FUNCTIONS 193
+# define EVP_R_INVALID_SALT_LENGTH 186
+# define EVP_R_INVALID_SECRET_LENGTH 223
+# define EVP_R_INVALID_SEED_LENGTH 220
+# define EVP_R_INVALID_VALUE 222
+# define EVP_R_KEYMGMT_EXPORT_FAILURE 205
# define EVP_R_KEY_SETUP_FAILED 180
+# define EVP_R_LOCKING_NOT_SUPPORTED 213
# define EVP_R_MEMORY_LIMIT_EXCEEDED 172
# define EVP_R_MESSAGE_DIGEST_IS_NULL 159
# define EVP_R_METHOD_NOT_SUPPORTED 144
# define EVP_R_MISSING_PARAMETERS 103
+# define EVP_R_NOT_ABLE_TO_COPY_CTX 190
# define EVP_R_NOT_XOF_OR_INVALID_LENGTH 178
# define EVP_R_NO_CIPHER_SET 131
# define EVP_R_NO_DEFAULT_DIGEST 158
# define EVP_R_NO_DIGEST_SET 139
+# define EVP_R_NO_IMPORT_FUNCTION 206
+# define EVP_R_NO_KEYMGMT_AVAILABLE 199
+# define EVP_R_NO_KEYMGMT_PRESENT 196
# define EVP_R_NO_KEY_SET 154
# define EVP_R_NO_OPERATION_SET 149
+# define EVP_R_NULL_MAC_PKEY_CTX 208
# define EVP_R_ONLY_ONESHOT_SUPPORTED 177
+# define EVP_R_OPERATION_NOT_INITIALIZED 151
# define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 150
-# define EVP_R_OPERATON_NOT_INITIALIZED 151
-# define EVP_R_OUTPUT_WOULD_OVERFLOW 184
+# define EVP_R_OUTPUT_WOULD_OVERFLOW 202
+# define EVP_R_PARAMETER_TOO_LARGE 187
# define EVP_R_PARTIALLY_OVERLAPPING 162
# define EVP_R_PBKDF2_ERROR 181
# define EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED 179
# define EVP_R_PRIVATE_KEY_DECODE_ERROR 145
# define EVP_R_PRIVATE_KEY_ENCODE_ERROR 146
# define EVP_R_PUBLIC_KEY_NOT_RSA 106
+# define EVP_R_SETTING_XOF_FAILED 227
+# define EVP_R_SET_DEFAULT_PROPERTY_FAILURE 209
+# define EVP_R_TOO_MANY_RECORDS 183
+# define EVP_R_UNABLE_TO_ENABLE_LOCKING 212
+# define EVP_R_UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE 215
+# define EVP_R_UNABLE_TO_GET_RANDOM_STRENGTH 216
+# define EVP_R_UNABLE_TO_LOCK_CONTEXT 211
+# define EVP_R_UNABLE_TO_SET_CALLBACKS 217
# define EVP_R_UNKNOWN_CIPHER 160
# define EVP_R_UNKNOWN_DIGEST 161
+# define EVP_R_UNKNOWN_KEY_TYPE 207
# define EVP_R_UNKNOWN_OPTION 169
# define EVP_R_UNKNOWN_PBE_ALGORITHM 121
# define EVP_R_UNSUPPORTED_ALGORITHM 156
@@ -193,12 +120,15 @@ int ERR_load_EVP_strings(void);
# define EVP_R_UNSUPPORTED_KEYLENGTH 123
# define EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION 124
# define EVP_R_UNSUPPORTED_KEY_SIZE 108
+# define EVP_R_UNSUPPORTED_KEY_TYPE 224
# define EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS 135
# define EVP_R_UNSUPPORTED_PRF 125
# define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM 118
# define EVP_R_UNSUPPORTED_SALT_TYPE 126
+# define EVP_R_UPDATE_ERROR 189
# define EVP_R_WRAP_MODE_NOT_ALLOWED 170
# define EVP_R_WRONG_FINAL_BLOCK_LENGTH 109
-# define EVP_R_XTS_DUPLICATED_KEYS 183
+# define EVP_R_XTS_DATA_UNIT_IS_TOO_LARGE 191
+# define EVP_R_XTS_DUPLICATED_KEYS 192
#endif
diff --git a/include/openssl/fips_names.h b/include/openssl/fips_names.h
new file mode 100644
index 000000000000..0fdf5440c7cb
--- /dev/null
+++ b/include/openssl/fips_names.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_FIPS_NAMES_H
+# define OPENSSL_FIPS_NAMES_H
+# pragma once
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/*
+ * Parameter names that the FIPS Provider defines
+ */
+
+/*
+ * The calculated MAC of the module file (Used for FIPS Self Testing)
+ * Type: OSSL_PARAM_UTF8_STRING
+ */
+# define OSSL_PROV_FIPS_PARAM_MODULE_MAC "module-mac"
+/*
+ * A version number for the fips install process (Used for FIPS Self Testing)
+ * Type: OSSL_PARAM_UTF8_STRING
+ */
+# define OSSL_PROV_FIPS_PARAM_INSTALL_VERSION "install-version"
+/*
+ * The calculated MAC of the install status indicator (Used for FIPS Self Testing)
+ * Type: OSSL_PARAM_UTF8_STRING
+ */
+# define OSSL_PROV_FIPS_PARAM_INSTALL_MAC "install-mac"
+/*
+ * The install status indicator (Used for FIPS Self Testing)
+ * Type: OSSL_PARAM_UTF8_STRING
+ */
+# define OSSL_PROV_FIPS_PARAM_INSTALL_STATUS "install-status"
+
+/*
+ * A boolean that determines if the FIPS conditional test errors result in
+ * the module entering an error state.
+ * Type: OSSL_PARAM_UTF8_STRING
+ */
+# define OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS "conditional-errors"
+
+/*
+ * A boolean that determines if the runtime FIPS security checks are performed.
+ * Type: OSSL_PARAM_UTF8_STRING
+ */
+# define OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS "security-checks"
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif /* OPENSSL_FIPS_NAMES_H */
diff --git a/include/openssl/fipskey.h.in b/include/openssl/fipskey.h.in
new file mode 100644
index 000000000000..56b947e852e8
--- /dev/null
+++ b/include/openssl/fipskey.h.in
@@ -0,0 +1,35 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_FIPSKEY_H
+# define OPENSSL_FIPSKEY_H
+# pragma once
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/*
+ * The FIPS validation HMAC key, usable as an array initializer.
+ */
+#define FIPS_KEY_ELEMENTS \
+ {- join(', ', map { "0x$_" } unpack("(A2)*", $config{FIPSKEY})) -}
+
+/*
+ * The FIPS validation key, as a string.
+ */
+#define FIPS_KEY_STRING "{- $config{FIPSKEY} -}"
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/include/openssl/hmac.h b/include/openssl/hmac.h
index 458efc1d5181..f9e1bff3f747 100644
--- a/include/openssl/hmac.h
+++ b/include/openssl/hmac.h
@@ -1,51 +1,62 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_HMAC_H
-# define HEADER_HMAC_H
+#ifndef OPENSSL_HMAC_H
+# define OPENSSL_HMAC_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_HMAC_H
+# endif
# include <openssl/opensslconf.h>
# include <openssl/evp.h>
-# if OPENSSL_API_COMPAT < 0x10200000L
-# define HMAC_MAX_MD_CBLOCK 128 /* Deprecated */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HMAC_MAX_MD_CBLOCK 200 /* Deprecated */
# endif
-#ifdef __cplusplus
+# ifdef __cplusplus
extern "C" {
-#endif
-
-size_t HMAC_size(const HMAC_CTX *e);
-HMAC_CTX *HMAC_CTX_new(void);
-int HMAC_CTX_reset(HMAC_CTX *ctx);
-void HMAC_CTX_free(HMAC_CTX *ctx);
+# endif
-DEPRECATEDIN_1_1_0(__owur int HMAC_Init(HMAC_CTX *ctx, const void *key, int len,
- const EVP_MD *md))
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 size_t HMAC_size(const HMAC_CTX *e);
+OSSL_DEPRECATEDIN_3_0 HMAC_CTX *HMAC_CTX_new(void);
+OSSL_DEPRECATEDIN_3_0 int HMAC_CTX_reset(HMAC_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 void HMAC_CTX_free(HMAC_CTX *ctx);
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 __owur int HMAC_Init(HMAC_CTX *ctx,
+ const void *key, int len,
+ const EVP_MD *md);
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
+ const EVP_MD *md, ENGINE *impl);
+OSSL_DEPRECATEDIN_3_0 int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data,
+ size_t len);
+OSSL_DEPRECATEDIN_3_0 int HMAC_Final(HMAC_CTX *ctx, unsigned char *md,
+ unsigned int *len);
+OSSL_DEPRECATEDIN_3_0 __owur int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx);
+OSSL_DEPRECATEDIN_3_0 void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags);
+OSSL_DEPRECATEDIN_3_0 const EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx);
+# endif
-/*__owur*/ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
- const EVP_MD *md, ENGINE *impl);
-/*__owur*/ int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data,
- size_t len);
-/*__owur*/ int HMAC_Final(HMAC_CTX *ctx, unsigned char *md,
- unsigned int *len);
unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
- const unsigned char *d, size_t n, unsigned char *md,
- unsigned int *md_len);
-__owur int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx);
-
-void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags);
-const EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx);
+ const unsigned char *data, size_t data_len,
+ unsigned char *md, unsigned int *md_len);
-#ifdef __cplusplus
+# ifdef __cplusplus
}
-#endif
+# endif
#endif
diff --git a/include/openssl/http.h b/include/openssl/http.h
new file mode 100644
index 000000000000..f7ab214265e4
--- /dev/null
+++ b/include/openssl/http.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Siemens AG 2018-2020
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_HTTP_H
+# define OPENSSL_HTTP_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+
+# include <openssl/bio.h>
+# include <openssl/asn1.h>
+# include <openssl/conf.h>
+
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# define OSSL_HTTP_NAME "http"
+# define OSSL_HTTPS_NAME "https"
+# define OSSL_HTTP_PREFIX OSSL_HTTP_NAME"://"
+# define OSSL_HTTPS_PREFIX OSSL_HTTPS_NAME"://"
+# define OSSL_HTTP_PORT "80"
+# define OSSL_HTTPS_PORT "443"
+# define OPENSSL_NO_PROXY "NO_PROXY"
+# define OPENSSL_HTTP_PROXY "HTTP_PROXY"
+# define OPENSSL_HTTPS_PROXY "HTTPS_PROXY"
+
+#define OSSL_HTTP_DEFAULT_MAX_LINE_LEN (4 * 1024)
+#define OSSL_HTTP_DEFAULT_MAX_RESP_LEN (100 * 1024)
+
+/* Low-level HTTP API */
+OSSL_HTTP_REQ_CTX *OSSL_HTTP_REQ_CTX_new(BIO *wbio, BIO *rbio, int buf_size);
+void OSSL_HTTP_REQ_CTX_free(OSSL_HTTP_REQ_CTX *rctx);
+int OSSL_HTTP_REQ_CTX_set_request_line(OSSL_HTTP_REQ_CTX *rctx, int method_POST,
+ const char *server, const char *port,
+ const char *path);
+int OSSL_HTTP_REQ_CTX_add1_header(OSSL_HTTP_REQ_CTX *rctx,
+ const char *name, const char *value);
+int OSSL_HTTP_REQ_CTX_set_expected(OSSL_HTTP_REQ_CTX *rctx,
+ const char *content_type, int asn1,
+ int timeout, int keep_alive);
+int OSSL_HTTP_REQ_CTX_set1_req(OSSL_HTTP_REQ_CTX *rctx, const char *content_type,
+ const ASN1_ITEM *it, const ASN1_VALUE *req);
+int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx);
+int OSSL_HTTP_REQ_CTX_nbio_d2i(OSSL_HTTP_REQ_CTX *rctx,
+ ASN1_VALUE **pval, const ASN1_ITEM *it);
+BIO *OSSL_HTTP_REQ_CTX_exchange(OSSL_HTTP_REQ_CTX *rctx);
+BIO *OSSL_HTTP_REQ_CTX_get0_mem_bio(const OSSL_HTTP_REQ_CTX *rctx);
+size_t OSSL_HTTP_REQ_CTX_get_resp_len(const OSSL_HTTP_REQ_CTX *rctx);
+void OSSL_HTTP_REQ_CTX_set_max_response_length(OSSL_HTTP_REQ_CTX *rctx,
+ unsigned long len);
+int OSSL_HTTP_is_alive(const OSSL_HTTP_REQ_CTX *rctx);
+
+/* High-level HTTP API */
+typedef BIO *(*OSSL_HTTP_bio_cb_t)(BIO *bio, void *arg, int connect, int detail);
+OSSL_HTTP_REQ_CTX *OSSL_HTTP_open(const char *server, const char *port,
+ const char *proxy, const char *no_proxy,
+ int use_ssl, BIO *bio, BIO *rbio,
+ OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
+ int buf_size, int overall_timeout);
+int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port,
+ const char *proxyuser, const char *proxypass,
+ int timeout, BIO *bio_err, const char *prog);
+int OSSL_HTTP_set1_request(OSSL_HTTP_REQ_CTX *rctx, const char *path,
+ const STACK_OF(CONF_VALUE) *headers,
+ const char *content_type, BIO *req,
+ const char *expected_content_type, int expect_asn1,
+ size_t max_resp_len, int timeout, int keep_alive);
+BIO *OSSL_HTTP_exchange(OSSL_HTTP_REQ_CTX *rctx, char **redirection_url);
+BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy,
+ BIO *bio, BIO *rbio,
+ OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
+ int buf_size, const STACK_OF(CONF_VALUE) *headers,
+ const char *expected_content_type, int expect_asn1,
+ size_t max_resp_len, int timeout);
+BIO *OSSL_HTTP_transfer(OSSL_HTTP_REQ_CTX **prctx,
+ const char *server, const char *port,
+ const char *path, int use_ssl,
+ const char *proxy, const char *no_proxy,
+ BIO *bio, BIO *rbio,
+ OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
+ int buf_size, const STACK_OF(CONF_VALUE) *headers,
+ const char *content_type, BIO *req,
+ const char *expected_content_type, int expect_asn1,
+ size_t max_resp_len, int timeout, int keep_alive);
+int OSSL_HTTP_close(OSSL_HTTP_REQ_CTX *rctx, int ok);
+
+/* Auxiliary functions */
+int OSSL_parse_url(const char *url, char **pscheme, char **puser, char **phost,
+ char **pport, int *pport_num,
+ char **ppath, char **pquery, char **pfrag);
+int OSSL_HTTP_parse_url(const char *url, int *pssl, char **puser, char **phost,
+ char **pport, int *pport_num,
+ char **ppath, char **pquery, char **pfrag);
+const char *OSSL_HTTP_adapt_proxy(const char *proxy, const char *no_proxy,
+ const char *server, int use_ssl);
+
+# ifdef __cplusplus
+}
+# endif
+#endif /* !defined(OPENSSL_HTTP_H) */
diff --git a/include/openssl/httperr.h b/include/openssl/httperr.h
new file mode 100644
index 000000000000..ee089592034c
--- /dev/null
+++ b/include/openssl/httperr.h
@@ -0,0 +1,55 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_HTTPERR_H
+# define OPENSSL_HTTPERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
+
+
+
+/*
+ * HTTP reason codes.
+ */
+# define HTTP_R_ASN1_LEN_EXCEEDS_MAX_RESP_LEN 108
+# define HTTP_R_CONNECT_FAILURE 100
+# define HTTP_R_ERROR_PARSING_ASN1_LENGTH 109
+# define HTTP_R_ERROR_PARSING_CONTENT_LENGTH 119
+# define HTTP_R_ERROR_PARSING_URL 101
+# define HTTP_R_ERROR_RECEIVING 103
+# define HTTP_R_ERROR_SENDING 102
+# define HTTP_R_FAILED_READING_DATA 128
+# define HTTP_R_HEADER_PARSE_ERROR 126
+# define HTTP_R_INCONSISTENT_CONTENT_LENGTH 120
+# define HTTP_R_INVALID_PORT_NUMBER 123
+# define HTTP_R_INVALID_URL_PATH 125
+# define HTTP_R_INVALID_URL_SCHEME 124
+# define HTTP_R_MAX_RESP_LEN_EXCEEDED 117
+# define HTTP_R_MISSING_ASN1_ENCODING 110
+# define HTTP_R_MISSING_CONTENT_TYPE 121
+# define HTTP_R_MISSING_REDIRECT_LOCATION 111
+# define HTTP_R_RECEIVED_ERROR 105
+# define HTTP_R_RECEIVED_WRONG_HTTP_VERSION 106
+# define HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP 112
+# define HTTP_R_REDIRECTION_NOT_ENABLED 116
+# define HTTP_R_RESPONSE_LINE_TOO_LONG 113
+# define HTTP_R_RESPONSE_PARSE_ERROR 104
+# define HTTP_R_RETRY_TIMEOUT 129
+# define HTTP_R_SERVER_CANCELED_CONNECTION 127
+# define HTTP_R_SOCK_NOT_SUPPORTED 122
+# define HTTP_R_STATUS_CODE_UNSUPPORTED 114
+# define HTTP_R_TLS_NOT_ENABLED 107
+# define HTTP_R_TOO_MANY_REDIRECTIONS 115
+# define HTTP_R_UNEXPECTED_CONTENT_TYPE 118
+
+#endif
diff --git a/include/openssl/idea.h b/include/openssl/idea.h
index 4334f3ea71a6..1f9bb3b3c71f 100644
--- a/include/openssl/idea.h
+++ b/include/openssl/idea.h
@@ -1,64 +1,82 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_IDEA_H
-# define HEADER_IDEA_H
+#ifndef OPENSSL_IDEA_H
+# define OPENSSL_IDEA_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_IDEA_H
+# endif
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_IDEA
-# ifdef __cplusplus
+# ifdef __cplusplus
extern "C" {
-# endif
+# endif
-typedef unsigned int IDEA_INT;
+# define IDEA_BLOCK 8
+# define IDEA_KEY_LENGTH 16
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
-# define IDEA_ENCRYPT 1
-# define IDEA_DECRYPT 0
+typedef unsigned int IDEA_INT;
-# define IDEA_BLOCK 8
-# define IDEA_KEY_LENGTH 16
+# define IDEA_ENCRYPT 1
+# define IDEA_DECRYPT 0
typedef struct idea_key_st {
IDEA_INT data[9][6];
} IDEA_KEY_SCHEDULE;
+#endif
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 const char *IDEA_options(void);
+OSSL_DEPRECATEDIN_3_0 void IDEA_ecb_encrypt(const unsigned char *in,
+ unsigned char *out,
+ IDEA_KEY_SCHEDULE *ks);
+OSSL_DEPRECATEDIN_3_0 void IDEA_set_encrypt_key(const unsigned char *key,
+ IDEA_KEY_SCHEDULE *ks);
+OSSL_DEPRECATEDIN_3_0 void IDEA_set_decrypt_key(IDEA_KEY_SCHEDULE *ek,
+ IDEA_KEY_SCHEDULE *dk);
+OSSL_DEPRECATEDIN_3_0 void IDEA_cbc_encrypt(const unsigned char *in,
+ unsigned char *out, long length,
+ IDEA_KEY_SCHEDULE *ks,
+ unsigned char *iv, int enc);
+OSSL_DEPRECATEDIN_3_0 void IDEA_cfb64_encrypt(const unsigned char *in,
+ unsigned char *out, long length,
+ IDEA_KEY_SCHEDULE *ks,
+ unsigned char *iv, int *num,
+ int enc);
+OSSL_DEPRECATEDIN_3_0 void IDEA_ofb64_encrypt(const unsigned char *in,
+ unsigned char *out, long length,
+ IDEA_KEY_SCHEDULE *ks,
+ unsigned char *iv, int *num);
+OSSL_DEPRECATEDIN_3_0 void IDEA_encrypt(unsigned long *in,
+ IDEA_KEY_SCHEDULE *ks);
+#endif
-const char *IDEA_options(void);
-void IDEA_ecb_encrypt(const unsigned char *in, unsigned char *out,
- IDEA_KEY_SCHEDULE *ks);
-void IDEA_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks);
-void IDEA_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk);
-void IDEA_cbc_encrypt(const unsigned char *in, unsigned char *out,
- long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,
- int enc);
-void IDEA_cfb64_encrypt(const unsigned char *in, unsigned char *out,
- long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,
- int *num, int enc);
-void IDEA_ofb64_encrypt(const unsigned char *in, unsigned char *out,
- long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,
- int *num);
-void IDEA_encrypt(unsigned long *in, IDEA_KEY_SCHEDULE *ks);
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define idea_options IDEA_options
+# define idea_ecb_encrypt IDEA_ecb_encrypt
+# define idea_set_encrypt_key IDEA_set_encrypt_key
+# define idea_set_decrypt_key IDEA_set_decrypt_key
+# define idea_cbc_encrypt IDEA_cbc_encrypt
+# define idea_cfb64_encrypt IDEA_cfb64_encrypt
+# define idea_ofb64_encrypt IDEA_ofb64_encrypt
+# define idea_encrypt IDEA_encrypt
+# endif
-# if OPENSSL_API_COMPAT < 0x10100000L
-# define idea_options IDEA_options
-# define idea_ecb_encrypt IDEA_ecb_encrypt
-# define idea_set_encrypt_key IDEA_set_encrypt_key
-# define idea_set_decrypt_key IDEA_set_decrypt_key
-# define idea_cbc_encrypt IDEA_cbc_encrypt
-# define idea_cfb64_encrypt IDEA_cfb64_encrypt
-# define idea_ofb64_encrypt IDEA_ofb64_encrypt
-# define idea_encrypt IDEA_encrypt
-# endif
-
-# ifdef __cplusplus
+# ifdef __cplusplus
}
-# endif
+# endif
# endif
#endif
diff --git a/include/openssl/kdf.h b/include/openssl/kdf.h
index 5abd4c371475..0983230a488a 100644
--- a/include/openssl/kdf.h
+++ b/include/openssl/kdf.h
@@ -1,19 +1,76 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_KDF_H
-# define HEADER_KDF_H
+#ifndef OPENSSL_KDF_H
+# define OPENSSL_KDF_H
+# pragma once
-# include <openssl/kdferr.h>
-#ifdef __cplusplus
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_KDF_H
+# endif
+
+# include <stdarg.h>
+# include <stddef.h>
+# include <openssl/types.h>
+# include <openssl/core.h>
+
+# ifdef __cplusplus
extern "C" {
-#endif
+# endif
+
+int EVP_KDF_up_ref(EVP_KDF *kdf);
+void EVP_KDF_free(EVP_KDF *kdf);
+EVP_KDF *EVP_KDF_fetch(OSSL_LIB_CTX *libctx, const char *algorithm,
+ const char *properties);
+
+EVP_KDF_CTX *EVP_KDF_CTX_new(EVP_KDF *kdf);
+void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx);
+EVP_KDF_CTX *EVP_KDF_CTX_dup(const EVP_KDF_CTX *src);
+const char *EVP_KDF_get0_description(const EVP_KDF *kdf);
+int EVP_KDF_is_a(const EVP_KDF *kdf, const char *name);
+const char *EVP_KDF_get0_name(const EVP_KDF *kdf);
+const OSSL_PROVIDER *EVP_KDF_get0_provider(const EVP_KDF *kdf);
+const EVP_KDF *EVP_KDF_CTX_kdf(EVP_KDF_CTX *ctx);
+
+void EVP_KDF_CTX_reset(EVP_KDF_CTX *ctx);
+size_t EVP_KDF_CTX_get_kdf_size(EVP_KDF_CTX *ctx);
+int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[]);
+int EVP_KDF_get_params(EVP_KDF *kdf, OSSL_PARAM params[]);
+int EVP_KDF_CTX_get_params(EVP_KDF_CTX *ctx, OSSL_PARAM params[]);
+int EVP_KDF_CTX_set_params(EVP_KDF_CTX *ctx, const OSSL_PARAM params[]);
+const OSSL_PARAM *EVP_KDF_gettable_params(const EVP_KDF *kdf);
+const OSSL_PARAM *EVP_KDF_gettable_ctx_params(const EVP_KDF *kdf);
+const OSSL_PARAM *EVP_KDF_settable_ctx_params(const EVP_KDF *kdf);
+const OSSL_PARAM *EVP_KDF_CTX_gettable_params(EVP_KDF_CTX *ctx);
+const OSSL_PARAM *EVP_KDF_CTX_settable_params(EVP_KDF_CTX *ctx);
+
+void EVP_KDF_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(EVP_KDF *kdf, void *arg),
+ void *arg);
+int EVP_KDF_names_do_all(const EVP_KDF *kdf,
+ void (*fn)(const char *name, void *data),
+ void *data);
+
+# define EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND 0
+# define EVP_KDF_HKDF_MODE_EXTRACT_ONLY 1
+# define EVP_KDF_HKDF_MODE_EXPAND_ONLY 2
+
+#define EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV 65
+#define EVP_KDF_SSHKDF_TYPE_INITIAL_IV_SRV_TO_CLI 66
+#define EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_CLI_TO_SRV 67
+#define EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_SRV_TO_CLI 68
+#define EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_CLI_TO_SRV 69
+#define EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_SRV_TO_CLI 70
+
+/**** The legacy PKEY-based KDF API follows. ****/
# define EVP_PKEY_CTRL_TLS_MD (EVP_PKEY_ALG_CTRL)
# define EVP_PKEY_CTRL_TLS_SECRET (EVP_PKEY_ALG_CTRL + 1)
@@ -30,68 +87,52 @@ extern "C" {
# define EVP_PKEY_CTRL_SCRYPT_P (EVP_PKEY_ALG_CTRL + 12)
# define EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES (EVP_PKEY_ALG_CTRL + 13)
-# define EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND 0
-# define EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY 1
-# define EVP_PKEY_HKDEF_MODE_EXPAND_ONLY 2
+# define EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND \
+ EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND
+# define EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY \
+ EVP_KDF_HKDF_MODE_EXTRACT_ONLY
+# define EVP_PKEY_HKDEF_MODE_EXPAND_ONLY \
+ EVP_KDF_HKDF_MODE_EXPAND_ONLY
-# define EVP_PKEY_CTX_set_tls1_prf_md(pctx, md) \
- EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_TLS_MD, 0, (void *)(md))
+int EVP_PKEY_CTX_set_tls1_prf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
-# define EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, sec, seclen) \
- EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_TLS_SECRET, seclen, (void *)(sec))
+int EVP_PKEY_CTX_set1_tls1_prf_secret(EVP_PKEY_CTX *pctx,
+ const unsigned char *sec, int seclen);
-# define EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed, seedlen) \
- EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_TLS_SEED, seedlen, (void *)(seed))
+int EVP_PKEY_CTX_add1_tls1_prf_seed(EVP_PKEY_CTX *pctx,
+ const unsigned char *seed, int seedlen);
-# define EVP_PKEY_CTX_set_hkdf_md(pctx, md) \
- EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_HKDF_MD, 0, (void *)(md))
+int EVP_PKEY_CTX_set_hkdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
-# define EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, saltlen) \
- EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_HKDF_SALT, saltlen, (void *)(salt))
+int EVP_PKEY_CTX_set1_hkdf_salt(EVP_PKEY_CTX *ctx,
+ const unsigned char *salt, int saltlen);
-# define EVP_PKEY_CTX_set1_hkdf_key(pctx, key, keylen) \
- EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_HKDF_KEY, keylen, (void *)(key))
+int EVP_PKEY_CTX_set1_hkdf_key(EVP_PKEY_CTX *ctx,
+ const unsigned char *key, int keylen);
-# define EVP_PKEY_CTX_add1_hkdf_info(pctx, info, infolen) \
- EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_HKDF_INFO, infolen, (void *)(info))
+int EVP_PKEY_CTX_add1_hkdf_info(EVP_PKEY_CTX *ctx,
+ const unsigned char *info, int infolen);
-# define EVP_PKEY_CTX_hkdf_mode(pctx, mode) \
- EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_HKDF_MODE, mode, NULL)
+int EVP_PKEY_CTX_set_hkdf_mode(EVP_PKEY_CTX *ctx, int mode);
+# define EVP_PKEY_CTX_hkdf_mode EVP_PKEY_CTX_set_hkdf_mode
-# define EVP_PKEY_CTX_set1_pbe_pass(pctx, pass, passlen) \
- EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_PASS, passlen, (void *)(pass))
+int EVP_PKEY_CTX_set1_pbe_pass(EVP_PKEY_CTX *ctx, const char *pass,
+ int passlen);
-# define EVP_PKEY_CTX_set1_scrypt_salt(pctx, salt, saltlen) \
- EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_SCRYPT_SALT, saltlen, (void *)(salt))
+int EVP_PKEY_CTX_set1_scrypt_salt(EVP_PKEY_CTX *ctx,
+ const unsigned char *salt, int saltlen);
-# define EVP_PKEY_CTX_set_scrypt_N(pctx, n) \
- EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_SCRYPT_N, n)
+int EVP_PKEY_CTX_set_scrypt_N(EVP_PKEY_CTX *ctx, uint64_t n);
-# define EVP_PKEY_CTX_set_scrypt_r(pctx, r) \
- EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_SCRYPT_R, r)
+int EVP_PKEY_CTX_set_scrypt_r(EVP_PKEY_CTX *ctx, uint64_t r);
-# define EVP_PKEY_CTX_set_scrypt_p(pctx, p) \
- EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_SCRYPT_P, p)
+int EVP_PKEY_CTX_set_scrypt_p(EVP_PKEY_CTX *ctx, uint64_t p);
-# define EVP_PKEY_CTX_set_scrypt_maxmem_bytes(pctx, maxmem_bytes) \
- EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \
- EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES, maxmem_bytes)
+int EVP_PKEY_CTX_set_scrypt_maxmem_bytes(EVP_PKEY_CTX *ctx,
+ uint64_t maxmem_bytes);
-# ifdef __cplusplus
+# ifdef __cplusplus
}
# endif
#endif
diff --git a/include/openssl/kdferr.h b/include/openssl/kdferr.h
index 3f51bd0228ab..963d766dfc85 100644
--- a/include/openssl/kdferr.h
+++ b/include/openssl/kdferr.h
@@ -1,55 +1,16 @@
/*
- * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_KDFERR_H
-# define HEADER_KDFERR_H
+#ifndef OPENSSL_KDFERR_H
+# define OPENSSL_KDFERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+#include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_KDF_strings(void);
-
-/*
- * KDF function codes.
- */
-# define KDF_F_PKEY_HKDF_CTRL_STR 103
-# define KDF_F_PKEY_HKDF_DERIVE 102
-# define KDF_F_PKEY_HKDF_INIT 108
-# define KDF_F_PKEY_SCRYPT_CTRL_STR 104
-# define KDF_F_PKEY_SCRYPT_CTRL_UINT64 105
-# define KDF_F_PKEY_SCRYPT_DERIVE 109
-# define KDF_F_PKEY_SCRYPT_INIT 106
-# define KDF_F_PKEY_SCRYPT_SET_MEMBUF 107
-# define KDF_F_PKEY_TLS1_PRF_CTRL_STR 100
-# define KDF_F_PKEY_TLS1_PRF_DERIVE 101
-# define KDF_F_PKEY_TLS1_PRF_INIT 110
-# define KDF_F_TLS1_PRF_ALG 111
-
-/*
- * KDF reason codes.
- */
-# define KDF_R_INVALID_DIGEST 100
-# define KDF_R_MISSING_ITERATION_COUNT 109
-# define KDF_R_MISSING_KEY 104
-# define KDF_R_MISSING_MESSAGE_DIGEST 105
-# define KDF_R_MISSING_PARAMETER 101
-# define KDF_R_MISSING_PASS 110
-# define KDF_R_MISSING_SALT 111
-# define KDF_R_MISSING_SECRET 107
-# define KDF_R_MISSING_SEED 106
-# define KDF_R_UNKNOWN_PARAMETER_TYPE 103
-# define KDF_R_VALUE_ERROR 108
-# define KDF_R_VALUE_MISSING 102
-
-#endif
+#endif /* !defined(OPENSSL_KDFERR_H) */
diff --git a/include/openssl/lhash.h b/include/openssl/lhash.h
deleted file mode 100644
index 2e42d727d4d6..000000000000
--- a/include/openssl/lhash.h
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * Header for dynamic hash table routines Author - Eric Young
- */
-
-#ifndef HEADER_LHASH_H
-# define HEADER_LHASH_H
-
-# include <openssl/e_os2.h>
-# include <openssl/bio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct lhash_node_st OPENSSL_LH_NODE;
-typedef int (*OPENSSL_LH_COMPFUNC) (const void *, const void *);
-typedef unsigned long (*OPENSSL_LH_HASHFUNC) (const void *);
-typedef void (*OPENSSL_LH_DOALL_FUNC) (void *);
-typedef void (*OPENSSL_LH_DOALL_FUNCARG) (void *, void *);
-typedef struct lhash_st OPENSSL_LHASH;
-
-/*
- * Macros for declaring and implementing type-safe wrappers for LHASH
- * callbacks. This way, callbacks can be provided to LHASH structures without
- * function pointer casting and the macro-defined callbacks provide
- * per-variable casting before deferring to the underlying type-specific
- * callbacks. NB: It is possible to place a "static" in front of both the
- * DECLARE and IMPLEMENT macros if the functions are strictly internal.
- */
-
-/* First: "hash" functions */
-# define DECLARE_LHASH_HASH_FN(name, o_type) \
- unsigned long name##_LHASH_HASH(const void *);
-# define IMPLEMENT_LHASH_HASH_FN(name, o_type) \
- unsigned long name##_LHASH_HASH(const void *arg) { \
- const o_type *a = arg; \
- return name##_hash(a); }
-# define LHASH_HASH_FN(name) name##_LHASH_HASH
-
-/* Second: "compare" functions */
-# define DECLARE_LHASH_COMP_FN(name, o_type) \
- int name##_LHASH_COMP(const void *, const void *);
-# define IMPLEMENT_LHASH_COMP_FN(name, o_type) \
- int name##_LHASH_COMP(const void *arg1, const void *arg2) { \
- const o_type *a = arg1; \
- const o_type *b = arg2; \
- return name##_cmp(a,b); }
-# define LHASH_COMP_FN(name) name##_LHASH_COMP
-
-/* Fourth: "doall_arg" functions */
-# define DECLARE_LHASH_DOALL_ARG_FN(name, o_type, a_type) \
- void name##_LHASH_DOALL_ARG(void *, void *);
-# define IMPLEMENT_LHASH_DOALL_ARG_FN(name, o_type, a_type) \
- void name##_LHASH_DOALL_ARG(void *arg1, void *arg2) { \
- o_type *a = arg1; \
- a_type *b = arg2; \
- name##_doall_arg(a, b); }
-# define LHASH_DOALL_ARG_FN(name) name##_LHASH_DOALL_ARG
-
-
-# define LH_LOAD_MULT 256
-
-int OPENSSL_LH_error(OPENSSL_LHASH *lh);
-OPENSSL_LHASH *OPENSSL_LH_new(OPENSSL_LH_HASHFUNC h, OPENSSL_LH_COMPFUNC c);
-void OPENSSL_LH_free(OPENSSL_LHASH *lh);
-void *OPENSSL_LH_insert(OPENSSL_LHASH *lh, void *data);
-void *OPENSSL_LH_delete(OPENSSL_LHASH *lh, const void *data);
-void *OPENSSL_LH_retrieve(OPENSSL_LHASH *lh, const void *data);
-void OPENSSL_LH_doall(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNC func);
-void OPENSSL_LH_doall_arg(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNCARG func, void *arg);
-unsigned long OPENSSL_LH_strhash(const char *c);
-unsigned long OPENSSL_LH_num_items(const OPENSSL_LHASH *lh);
-unsigned long OPENSSL_LH_get_down_load(const OPENSSL_LHASH *lh);
-void OPENSSL_LH_set_down_load(OPENSSL_LHASH *lh, unsigned long down_load);
-
-# ifndef OPENSSL_NO_STDIO
-void OPENSSL_LH_stats(const OPENSSL_LHASH *lh, FILE *fp);
-void OPENSSL_LH_node_stats(const OPENSSL_LHASH *lh, FILE *fp);
-void OPENSSL_LH_node_usage_stats(const OPENSSL_LHASH *lh, FILE *fp);
-# endif
-void OPENSSL_LH_stats_bio(const OPENSSL_LHASH *lh, BIO *out);
-void OPENSSL_LH_node_stats_bio(const OPENSSL_LHASH *lh, BIO *out);
-void OPENSSL_LH_node_usage_stats_bio(const OPENSSL_LHASH *lh, BIO *out);
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-# define _LHASH OPENSSL_LHASH
-# define LHASH_NODE OPENSSL_LH_NODE
-# define lh_error OPENSSL_LH_error
-# define lh_new OPENSSL_LH_new
-# define lh_free OPENSSL_LH_free
-# define lh_insert OPENSSL_LH_insert
-# define lh_delete OPENSSL_LH_delete
-# define lh_retrieve OPENSSL_LH_retrieve
-# define lh_doall OPENSSL_LH_doall
-# define lh_doall_arg OPENSSL_LH_doall_arg
-# define lh_strhash OPENSSL_LH_strhash
-# define lh_num_items OPENSSL_LH_num_items
-# ifndef OPENSSL_NO_STDIO
-# define lh_stats OPENSSL_LH_stats
-# define lh_node_stats OPENSSL_LH_node_stats
-# define lh_node_usage_stats OPENSSL_LH_node_usage_stats
-# endif
-# define lh_stats_bio OPENSSL_LH_stats_bio
-# define lh_node_stats_bio OPENSSL_LH_node_stats_bio
-# define lh_node_usage_stats_bio OPENSSL_LH_node_usage_stats_bio
-# endif
-
-/* Type checking... */
-
-# define LHASH_OF(type) struct lhash_st_##type
-
-# define DEFINE_LHASH_OF(type) \
- LHASH_OF(type) { union lh_##type##_dummy { void* d1; unsigned long d2; int d3; } dummy; }; \
- static ossl_unused ossl_inline LHASH_OF(type) *lh_##type##_new(unsigned long (*hfn)(const type *), \
- int (*cfn)(const type *, const type *)) \
- { \
- return (LHASH_OF(type) *) \
- OPENSSL_LH_new((OPENSSL_LH_HASHFUNC)hfn, (OPENSSL_LH_COMPFUNC)cfn); \
- } \
- static ossl_unused ossl_inline void lh_##type##_free(LHASH_OF(type) *lh) \
- { \
- OPENSSL_LH_free((OPENSSL_LHASH *)lh); \
- } \
- static ossl_unused ossl_inline type *lh_##type##_insert(LHASH_OF(type) *lh, type *d) \
- { \
- return (type *)OPENSSL_LH_insert((OPENSSL_LHASH *)lh, d); \
- } \
- static ossl_unused ossl_inline type *lh_##type##_delete(LHASH_OF(type) *lh, const type *d) \
- { \
- return (type *)OPENSSL_LH_delete((OPENSSL_LHASH *)lh, d); \
- } \
- static ossl_unused ossl_inline type *lh_##type##_retrieve(LHASH_OF(type) *lh, const type *d) \
- { \
- return (type *)OPENSSL_LH_retrieve((OPENSSL_LHASH *)lh, d); \
- } \
- static ossl_unused ossl_inline int lh_##type##_error(LHASH_OF(type) *lh) \
- { \
- return OPENSSL_LH_error((OPENSSL_LHASH *)lh); \
- } \
- static ossl_unused ossl_inline unsigned long lh_##type##_num_items(LHASH_OF(type) *lh) \
- { \
- return OPENSSL_LH_num_items((OPENSSL_LHASH *)lh); \
- } \
- static ossl_unused ossl_inline void lh_##type##_node_stats_bio(const LHASH_OF(type) *lh, BIO *out) \
- { \
- OPENSSL_LH_node_stats_bio((const OPENSSL_LHASH *)lh, out); \
- } \
- static ossl_unused ossl_inline void lh_##type##_node_usage_stats_bio(const LHASH_OF(type) *lh, BIO *out) \
- { \
- OPENSSL_LH_node_usage_stats_bio((const OPENSSL_LHASH *)lh, out); \
- } \
- static ossl_unused ossl_inline void lh_##type##_stats_bio(const LHASH_OF(type) *lh, BIO *out) \
- { \
- OPENSSL_LH_stats_bio((const OPENSSL_LHASH *)lh, out); \
- } \
- static ossl_unused ossl_inline unsigned long lh_##type##_get_down_load(LHASH_OF(type) *lh) \
- { \
- return OPENSSL_LH_get_down_load((OPENSSL_LHASH *)lh); \
- } \
- static ossl_unused ossl_inline void lh_##type##_set_down_load(LHASH_OF(type) *lh, unsigned long dl) \
- { \
- OPENSSL_LH_set_down_load((OPENSSL_LHASH *)lh, dl); \
- } \
- static ossl_unused ossl_inline void lh_##type##_doall(LHASH_OF(type) *lh, \
- void (*doall)(type *)) \
- { \
- OPENSSL_LH_doall((OPENSSL_LHASH *)lh, (OPENSSL_LH_DOALL_FUNC)doall); \
- } \
- LHASH_OF(type)
-
-#define IMPLEMENT_LHASH_DOALL_ARG_CONST(type, argtype) \
- int_implement_lhash_doall(type, argtype, const type)
-
-#define IMPLEMENT_LHASH_DOALL_ARG(type, argtype) \
- int_implement_lhash_doall(type, argtype, type)
-
-#define int_implement_lhash_doall(type, argtype, cbargtype) \
- static ossl_unused ossl_inline void \
- lh_##type##_doall_##argtype(LHASH_OF(type) *lh, \
- void (*fn)(cbargtype *, argtype *), \
- argtype *arg) \
- { \
- OPENSSL_LH_doall_arg((OPENSSL_LHASH *)lh, (OPENSSL_LH_DOALL_FUNCARG)fn, (void *)arg); \
- } \
- LHASH_OF(type)
-
-DEFINE_LHASH_OF(OPENSSL_STRING);
-# ifdef _MSC_VER
-/*
- * push and pop this warning:
- * warning C4090: 'function': different 'const' qualifiers
- */
-# pragma warning (push)
-# pragma warning (disable: 4090)
-# endif
-
-DEFINE_LHASH_OF(OPENSSL_CSTRING);
-
-# ifdef _MSC_VER
-# pragma warning (pop)
-# endif
-
-/*
- * If called without higher optimization (min. -xO3) the Oracle Developer
- * Studio compiler generates code for the defined (static inline) functions
- * above.
- * This would later lead to the linker complaining about missing symbols when
- * this header file is included but the resulting object is not linked against
- * the Crypto library (openssl#6912).
- */
-# ifdef __SUNPRO_C
-# pragma weak OPENSSL_LH_new
-# pragma weak OPENSSL_LH_free
-# pragma weak OPENSSL_LH_insert
-# pragma weak OPENSSL_LH_delete
-# pragma weak OPENSSL_LH_retrieve
-# pragma weak OPENSSL_LH_error
-# pragma weak OPENSSL_LH_num_items
-# pragma weak OPENSSL_LH_node_stats_bio
-# pragma weak OPENSSL_LH_node_usage_stats_bio
-# pragma weak OPENSSL_LH_stats_bio
-# pragma weak OPENSSL_LH_get_down_load
-# pragma weak OPENSSL_LH_set_down_load
-# pragma weak OPENSSL_LH_doall
-# pragma weak OPENSSL_LH_doall_arg
-# endif /* __SUNPRO_C */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/openssl/lhash.h.in b/include/openssl/lhash.h.in
new file mode 100644
index 000000000000..febefa3c4ac6
--- /dev/null
+++ b/include/openssl/lhash.h.in
@@ -0,0 +1,263 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_lhash_macros);
+-}
+
+/*
+ * Header for dynamic hash table routines Author - Eric Young
+ */
+
+#ifndef OPENSSL_LHASH_H
+# define OPENSSL_LHASH_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_LHASH_H
+# endif
+
+# include <openssl/e_os2.h>
+# include <openssl/bio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct lhash_node_st OPENSSL_LH_NODE;
+typedef int (*OPENSSL_LH_COMPFUNC) (const void *, const void *);
+typedef unsigned long (*OPENSSL_LH_HASHFUNC) (const void *);
+typedef void (*OPENSSL_LH_DOALL_FUNC) (void *);
+typedef void (*OPENSSL_LH_DOALL_FUNCARG) (void *, void *);
+typedef struct lhash_st OPENSSL_LHASH;
+
+/*
+ * Macros for declaring and implementing type-safe wrappers for LHASH
+ * callbacks. This way, callbacks can be provided to LHASH structures without
+ * function pointer casting and the macro-defined callbacks provide
+ * per-variable casting before deferring to the underlying type-specific
+ * callbacks. NB: It is possible to place a "static" in front of both the
+ * DECLARE and IMPLEMENT macros if the functions are strictly internal.
+ */
+
+/* First: "hash" functions */
+# define DECLARE_LHASH_HASH_FN(name, o_type) \
+ unsigned long name##_LHASH_HASH(const void *);
+# define IMPLEMENT_LHASH_HASH_FN(name, o_type) \
+ unsigned long name##_LHASH_HASH(const void *arg) { \
+ const o_type *a = arg; \
+ return name##_hash(a); }
+# define LHASH_HASH_FN(name) name##_LHASH_HASH
+
+/* Second: "compare" functions */
+# define DECLARE_LHASH_COMP_FN(name, o_type) \
+ int name##_LHASH_COMP(const void *, const void *);
+# define IMPLEMENT_LHASH_COMP_FN(name, o_type) \
+ int name##_LHASH_COMP(const void *arg1, const void *arg2) { \
+ const o_type *a = arg1; \
+ const o_type *b = arg2; \
+ return name##_cmp(a,b); }
+# define LHASH_COMP_FN(name) name##_LHASH_COMP
+
+/* Fourth: "doall_arg" functions */
+# define DECLARE_LHASH_DOALL_ARG_FN(name, o_type, a_type) \
+ void name##_LHASH_DOALL_ARG(void *, void *);
+# define IMPLEMENT_LHASH_DOALL_ARG_FN(name, o_type, a_type) \
+ void name##_LHASH_DOALL_ARG(void *arg1, void *arg2) { \
+ o_type *a = arg1; \
+ a_type *b = arg2; \
+ name##_doall_arg(a, b); }
+# define LHASH_DOALL_ARG_FN(name) name##_LHASH_DOALL_ARG
+
+
+# define LH_LOAD_MULT 256
+
+int OPENSSL_LH_error(OPENSSL_LHASH *lh);
+OPENSSL_LHASH *OPENSSL_LH_new(OPENSSL_LH_HASHFUNC h, OPENSSL_LH_COMPFUNC c);
+void OPENSSL_LH_free(OPENSSL_LHASH *lh);
+void OPENSSL_LH_flush(OPENSSL_LHASH *lh);
+void *OPENSSL_LH_insert(OPENSSL_LHASH *lh, void *data);
+void *OPENSSL_LH_delete(OPENSSL_LHASH *lh, const void *data);
+void *OPENSSL_LH_retrieve(OPENSSL_LHASH *lh, const void *data);
+void OPENSSL_LH_doall(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNC func);
+void OPENSSL_LH_doall_arg(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNCARG func, void *arg);
+unsigned long OPENSSL_LH_strhash(const char *c);
+unsigned long OPENSSL_LH_num_items(const OPENSSL_LHASH *lh);
+unsigned long OPENSSL_LH_get_down_load(const OPENSSL_LHASH *lh);
+void OPENSSL_LH_set_down_load(OPENSSL_LHASH *lh, unsigned long down_load);
+
+# ifndef OPENSSL_NO_STDIO
+void OPENSSL_LH_stats(const OPENSSL_LHASH *lh, FILE *fp);
+void OPENSSL_LH_node_stats(const OPENSSL_LHASH *lh, FILE *fp);
+void OPENSSL_LH_node_usage_stats(const OPENSSL_LHASH *lh, FILE *fp);
+# endif
+void OPENSSL_LH_stats_bio(const OPENSSL_LHASH *lh, BIO *out);
+void OPENSSL_LH_node_stats_bio(const OPENSSL_LHASH *lh, BIO *out);
+void OPENSSL_LH_node_usage_stats_bio(const OPENSSL_LHASH *lh, BIO *out);
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define _LHASH OPENSSL_LHASH
+# define LHASH_NODE OPENSSL_LH_NODE
+# define lh_error OPENSSL_LH_error
+# define lh_new OPENSSL_LH_new
+# define lh_free OPENSSL_LH_free
+# define lh_insert OPENSSL_LH_insert
+# define lh_delete OPENSSL_LH_delete
+# define lh_retrieve OPENSSL_LH_retrieve
+# define lh_doall OPENSSL_LH_doall
+# define lh_doall_arg OPENSSL_LH_doall_arg
+# define lh_strhash OPENSSL_LH_strhash
+# define lh_num_items OPENSSL_LH_num_items
+# ifndef OPENSSL_NO_STDIO
+# define lh_stats OPENSSL_LH_stats
+# define lh_node_stats OPENSSL_LH_node_stats
+# define lh_node_usage_stats OPENSSL_LH_node_usage_stats
+# endif
+# define lh_stats_bio OPENSSL_LH_stats_bio
+# define lh_node_stats_bio OPENSSL_LH_node_stats_bio
+# define lh_node_usage_stats_bio OPENSSL_LH_node_usage_stats_bio
+# endif
+
+/* Type checking... */
+
+# define LHASH_OF(type) struct lhash_st_##type
+
+/* Helper macro for internal use */
+# define DEFINE_LHASH_OF_INTERNAL(type) \
+ LHASH_OF(type) { union lh_##type##_dummy { void* d1; unsigned long d2; int d3; } dummy; }; \
+ typedef int (*lh_##type##_compfunc)(const type *a, const type *b); \
+ typedef unsigned long (*lh_##type##_hashfunc)(const type *a); \
+ typedef void (*lh_##type##_doallfunc)(type *a); \
+ static ossl_unused ossl_inline type *ossl_check_##type##_lh_plain_type(type *ptr) \
+ { \
+ return ptr; \
+ } \
+ static ossl_unused ossl_inline const type *ossl_check_const_##type##_lh_plain_type(const type *ptr) \
+ { \
+ return ptr; \
+ } \
+ static ossl_unused ossl_inline const OPENSSL_LHASH *ossl_check_const_##type##_lh_type(const LHASH_OF(type) *lh) \
+ { \
+ return (const OPENSSL_LHASH *)lh; \
+ } \
+ static ossl_unused ossl_inline OPENSSL_LHASH *ossl_check_##type##_lh_type(LHASH_OF(type) *lh) \
+ { \
+ return (OPENSSL_LHASH *)lh; \
+ } \
+ static ossl_unused ossl_inline OPENSSL_LH_COMPFUNC ossl_check_##type##_lh_compfunc_type(lh_##type##_compfunc cmp) \
+ { \
+ return (OPENSSL_LH_COMPFUNC)cmp; \
+ } \
+ static ossl_unused ossl_inline OPENSSL_LH_HASHFUNC ossl_check_##type##_lh_hashfunc_type(lh_##type##_hashfunc hfn) \
+ { \
+ return (OPENSSL_LH_HASHFUNC)hfn; \
+ } \
+ static ossl_unused ossl_inline OPENSSL_LH_DOALL_FUNC ossl_check_##type##_lh_doallfunc_type(lh_##type##_doallfunc dfn) \
+ { \
+ return (OPENSSL_LH_DOALL_FUNC)dfn; \
+ } \
+ LHASH_OF(type)
+
+# define DEFINE_LHASH_OF(type) \
+ LHASH_OF(type) { union lh_##type##_dummy { void* d1; unsigned long d2; int d3; } dummy; }; \
+ static ossl_unused ossl_inline LHASH_OF(type) *lh_##type##_new(unsigned long (*hfn)(const type *), \
+ int (*cfn)(const type *, const type *)) \
+ { \
+ return (LHASH_OF(type) *) \
+ OPENSSL_LH_new((OPENSSL_LH_HASHFUNC)hfn, (OPENSSL_LH_COMPFUNC)cfn); \
+ } \
+ static ossl_unused ossl_inline void lh_##type##_free(LHASH_OF(type) *lh) \
+ { \
+ OPENSSL_LH_free((OPENSSL_LHASH *)lh); \
+ } \
+ static ossl_unused ossl_inline void lh_##type##_flush(LHASH_OF(type) *lh) \
+ { \
+ OPENSSL_LH_flush((OPENSSL_LHASH *)lh); \
+ } \
+ static ossl_unused ossl_inline type *lh_##type##_insert(LHASH_OF(type) *lh, type *d) \
+ { \
+ return (type *)OPENSSL_LH_insert((OPENSSL_LHASH *)lh, d); \
+ } \
+ static ossl_unused ossl_inline type *lh_##type##_delete(LHASH_OF(type) *lh, const type *d) \
+ { \
+ return (type *)OPENSSL_LH_delete((OPENSSL_LHASH *)lh, d); \
+ } \
+ static ossl_unused ossl_inline type *lh_##type##_retrieve(LHASH_OF(type) *lh, const type *d) \
+ { \
+ return (type *)OPENSSL_LH_retrieve((OPENSSL_LHASH *)lh, d); \
+ } \
+ static ossl_unused ossl_inline int lh_##type##_error(LHASH_OF(type) *lh) \
+ { \
+ return OPENSSL_LH_error((OPENSSL_LHASH *)lh); \
+ } \
+ static ossl_unused ossl_inline unsigned long lh_##type##_num_items(LHASH_OF(type) *lh) \
+ { \
+ return OPENSSL_LH_num_items((OPENSSL_LHASH *)lh); \
+ } \
+ static ossl_unused ossl_inline void lh_##type##_node_stats_bio(const LHASH_OF(type) *lh, BIO *out) \
+ { \
+ OPENSSL_LH_node_stats_bio((const OPENSSL_LHASH *)lh, out); \
+ } \
+ static ossl_unused ossl_inline void lh_##type##_node_usage_stats_bio(const LHASH_OF(type) *lh, BIO *out) \
+ { \
+ OPENSSL_LH_node_usage_stats_bio((const OPENSSL_LHASH *)lh, out); \
+ } \
+ static ossl_unused ossl_inline void lh_##type##_stats_bio(const LHASH_OF(type) *lh, BIO *out) \
+ { \
+ OPENSSL_LH_stats_bio((const OPENSSL_LHASH *)lh, out); \
+ } \
+ static ossl_unused ossl_inline unsigned long lh_##type##_get_down_load(LHASH_OF(type) *lh) \
+ { \
+ return OPENSSL_LH_get_down_load((OPENSSL_LHASH *)lh); \
+ } \
+ static ossl_unused ossl_inline void lh_##type##_set_down_load(LHASH_OF(type) *lh, unsigned long dl) \
+ { \
+ OPENSSL_LH_set_down_load((OPENSSL_LHASH *)lh, dl); \
+ } \
+ static ossl_unused ossl_inline void lh_##type##_doall(LHASH_OF(type) *lh, \
+ void (*doall)(type *)) \
+ { \
+ OPENSSL_LH_doall((OPENSSL_LHASH *)lh, (OPENSSL_LH_DOALL_FUNC)doall); \
+ } \
+ static ossl_unused ossl_inline void lh_##type##_doall_arg(LHASH_OF(type) *lh, \
+ void (*doallarg)(type *, void *), \
+ void *arg) \
+ { \
+ OPENSSL_LH_doall_arg((OPENSSL_LHASH *)lh, \
+ (OPENSSL_LH_DOALL_FUNCARG)doallarg, arg); \
+ } \
+ LHASH_OF(type)
+
+#define IMPLEMENT_LHASH_DOALL_ARG_CONST(type, argtype) \
+ int_implement_lhash_doall(type, argtype, const type)
+
+#define IMPLEMENT_LHASH_DOALL_ARG(type, argtype) \
+ int_implement_lhash_doall(type, argtype, type)
+
+#define int_implement_lhash_doall(type, argtype, cbargtype) \
+ static ossl_unused ossl_inline void \
+ lh_##type##_doall_##argtype(LHASH_OF(type) *lh, \
+ void (*fn)(cbargtype *, argtype *), \
+ argtype *arg) \
+ { \
+ OPENSSL_LH_doall_arg((OPENSSL_LHASH *)lh, (OPENSSL_LH_DOALL_FUNCARG)fn, (void *)arg); \
+ } \
+ LHASH_OF(type)
+
+{-
+ generate_lhash_macros("OPENSSL_STRING")
+ .generate_lhash_macros("OPENSSL_CSTRING");
+-}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/openssl/macros.h b/include/openssl/macros.h
new file mode 100644
index 000000000000..a6bc3f1feb04
--- /dev/null
+++ b/include/openssl/macros.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_MACROS_H
+# define OPENSSL_MACROS_H
+# pragma once
+
+#include <openssl/opensslconf.h>
+#include <openssl/opensslv.h>
+
+
+/* Helper macros for CPP string composition */
+# define OPENSSL_MSTR_HELPER(x) #x
+# define OPENSSL_MSTR(x) OPENSSL_MSTR_HELPER(x)
+
+/*
+ * Sometimes OPENSSL_NO_xxx ends up with an empty file and some compilers
+ * don't like that. This will hopefully silence them.
+ */
+# define NON_EMPTY_TRANSLATION_UNIT static void *dummy = &dummy;
+
+/*
+ * Generic deprecation macro
+ *
+ * If OPENSSL_SUPPRESS_DEPRECATED is defined, then OSSL_DEPRECATED and
+ * OSSL_DEPRECATED_FOR become no-ops
+ */
+# ifndef OSSL_DEPRECATED
+# undef OSSL_DEPRECATED_FOR
+# ifndef OPENSSL_SUPPRESS_DEPRECATED
+# if defined(_MSC_VER)
+ /*
+ * MSVC supports __declspec(deprecated) since MSVC 2003 (13.10),
+ * and __declspec(deprecated(message)) since MSVC 2005 (14.00)
+ */
+# if _MSC_VER >= 1400
+# define OSSL_DEPRECATED(since) \
+ __declspec(deprecated("Since OpenSSL " # since))
+# define OSSL_DEPRECATED_FOR(since, message) \
+ __declspec(deprecated("Since OpenSSL " # since ";" message))
+# elif _MSC_VER >= 1310
+# define OSSL_DEPRECATED(since) __declspec(deprecated)
+# define OSSL_DEPRECATED_FOR(since, message) __declspec(deprecated)
+# endif
+# elif defined(__GNUC__)
+ /*
+ * According to GCC documentation, deprecations with message appeared in
+ * GCC 4.5.0
+ */
+# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+# define OSSL_DEPRECATED(since) \
+ __attribute__((deprecated("Since OpenSSL " # since)))
+# define OSSL_DEPRECATED_FOR(since, message) \
+ __attribute__((deprecated("Since OpenSSL " # since ";" message)))
+# elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0)
+# define OSSL_DEPRECATED(since) __attribute__((deprecated))
+# define OSSL_DEPRECATED_FOR(since, message) __attribute__((deprecated))
+# endif
+# elif defined(__SUNPRO_C)
+# if (__SUNPRO_C >= 0x5130)
+# define OSSL_DEPRECATED(since) __attribute__ ((deprecated))
+# define OSSL_DEPRECATED_FOR(since, message) __attribute__ ((deprecated))
+# endif
+# endif
+# endif
+# endif
+
+/*
+ * Still not defined? Then define no-op macros. This means these macros
+ * are unsuitable for use in a typedef.
+ */
+# ifndef OSSL_DEPRECATED
+# define OSSL_DEPRECATED(since) extern
+# define OSSL_DEPRECATED_FOR(since, message) extern
+# endif
+
+/*
+ * Applications should use -DOPENSSL_API_COMPAT=<version> to suppress the
+ * declarations of functions deprecated in or before <version>. If this is
+ * undefined, the value of the macro OPENSSL_CONFIGURED_API (defined in
+ * <openssl/opensslconf.h>) is the default.
+ *
+ * For any version number up until version 1.1.x, <version> is expected to be
+ * the calculated version number 0xMNNFFPPSL.
+ * For version numbers 3.0 and on, <version> is expected to be a computation
+ * of the major and minor numbers in decimal using this formula:
+ *
+ * MAJOR * 10000 + MINOR * 100
+ *
+ * So version 3.0 becomes 30000, version 3.2 becomes 30200, etc.
+ */
+
+/*
+ * We use the OPENSSL_API_COMPAT value to define API level macros. These
+ * macros are used to enable or disable features at that API version boundary.
+ */
+
+# ifdef OPENSSL_API_LEVEL
+# error "OPENSSL_API_LEVEL must not be defined by application"
+# endif
+
+/*
+ * We figure out what API level was intended by simple numeric comparison.
+ * The lowest old style number we recognise is 0x00908000L, so we take some
+ * safety margin and assume that anything below 0x00900000L is a new style
+ * number. This allows new versions up to and including v943.71.83.
+ */
+# ifdef OPENSSL_API_COMPAT
+# if OPENSSL_API_COMPAT < 0x900000L
+# define OPENSSL_API_LEVEL (OPENSSL_API_COMPAT)
+# else
+# define OPENSSL_API_LEVEL \
+ (((OPENSSL_API_COMPAT >> 28) & 0xF) * 10000 \
+ + ((OPENSSL_API_COMPAT >> 20) & 0xFF) * 100 \
+ + ((OPENSSL_API_COMPAT >> 12) & 0xFF))
+# endif
+# endif
+
+/*
+ * If OPENSSL_API_COMPAT wasn't given, we use default numbers to set
+ * the API compatibility level.
+ */
+# ifndef OPENSSL_API_LEVEL
+# if OPENSSL_CONFIGURED_API > 0
+# define OPENSSL_API_LEVEL (OPENSSL_CONFIGURED_API)
+# else
+# define OPENSSL_API_LEVEL \
+ (OPENSSL_VERSION_MAJOR * 10000 + OPENSSL_VERSION_MINOR * 100)
+# endif
+# endif
+
+# if OPENSSL_API_LEVEL > OPENSSL_CONFIGURED_API
+# error "The requested API level higher than the configured API compatibility level"
+# endif
+
+/*
+ * Check of sane values.
+ */
+/* Can't go higher than the current version. */
+# if OPENSSL_API_LEVEL > (OPENSSL_VERSION_MAJOR * 10000 + OPENSSL_VERSION_MINOR * 100)
+# error "OPENSSL_API_COMPAT expresses an impossible API compatibility level"
+# endif
+/* OpenSSL will have no version 2.y.z */
+# if OPENSSL_API_LEVEL < 30000 && OPENSSL_API_LEVEL >= 20000
+# error "OPENSSL_API_COMPAT expresses an impossible API compatibility level"
+# endif
+/* Below 0.9.8 is unacceptably low */
+# if OPENSSL_API_LEVEL < 908
+# error "OPENSSL_API_COMPAT expresses an impossible API compatibility level"
+# endif
+
+/*
+ * Define macros for deprecation and simulated removal purposes.
+ *
+ * The macros OSSL_DEPRECATED_{major}_{minor} are always defined for
+ * all OpenSSL versions we care for. They can be used as attributes
+ * in function declarations where appropriate.
+ *
+ * The macros OPENSSL_NO_DEPRECATED_{major}_{minor} are defined for
+ * all OpenSSL versions up to or equal to the version given with
+ * OPENSSL_API_COMPAT. They are used as guards around anything that's
+ * deprecated up to that version, as an effect of the developer option
+ * 'no-deprecated'.
+ */
+
+# undef OPENSSL_NO_DEPRECATED_3_0
+# undef OPENSSL_NO_DEPRECATED_1_1_1
+# undef OPENSSL_NO_DEPRECATED_1_1_0
+# undef OPENSSL_NO_DEPRECATED_1_0_2
+# undef OPENSSL_NO_DEPRECATED_1_0_1
+# undef OPENSSL_NO_DEPRECATED_1_0_0
+# undef OPENSSL_NO_DEPRECATED_0_9_8
+
+# if OPENSSL_API_LEVEL >= 30000
+# ifndef OPENSSL_NO_DEPRECATED
+# define OSSL_DEPRECATEDIN_3_0 OSSL_DEPRECATED(3.0)
+# define OSSL_DEPRECATEDIN_3_0_FOR(msg) OSSL_DEPRECATED_FOR(3.0, msg)
+# else
+# define OPENSSL_NO_DEPRECATED_3_0
+# endif
+# else
+# define OSSL_DEPRECATEDIN_3_0
+# define OSSL_DEPRECATEDIN_3_0_FOR(msg)
+# endif
+# if OPENSSL_API_LEVEL >= 10101
+# ifndef OPENSSL_NO_DEPRECATED
+# define OSSL_DEPRECATEDIN_1_1_1 OSSL_DEPRECATED(1.1.1)
+# define OSSL_DEPRECATEDIN_1_1_1_FOR(msg) OSSL_DEPRECATED_FOR(1.1.1, msg)
+# else
+# define OPENSSL_NO_DEPRECATED_1_1_1
+# endif
+# else
+# define OSSL_DEPRECATEDIN_1_1_1
+# define OSSL_DEPRECATEDIN_1_1_1_FOR(msg)
+# endif
+# if OPENSSL_API_LEVEL >= 10100
+# ifndef OPENSSL_NO_DEPRECATED
+# define OSSL_DEPRECATEDIN_1_1_0 OSSL_DEPRECATED(1.1.0)
+# define OSSL_DEPRECATEDIN_1_1_0_FOR(msg) OSSL_DEPRECATED_FOR(1.1.0, msg)
+# else
+# define OPENSSL_NO_DEPRECATED_1_1_0
+# endif
+# else
+# define OSSL_DEPRECATEDIN_1_1_0
+# define OSSL_DEPRECATEDIN_1_1_0_FOR(msg)
+# endif
+# if OPENSSL_API_LEVEL >= 10002
+# ifndef OPENSSL_NO_DEPRECATED
+# define OSSL_DEPRECATEDIN_1_0_2 OSSL_DEPRECATED(1.0.2)
+# define OSSL_DEPRECATEDIN_1_0_2_FOR(msg) OSSL_DEPRECATED_FOR(1.0.2, msg)
+# else
+# define OPENSSL_NO_DEPRECATED_1_0_2
+# endif
+# else
+# define OSSL_DEPRECATEDIN_1_0_2
+# define OSSL_DEPRECATEDIN_1_0_2_FOR(msg)
+# endif
+# if OPENSSL_API_LEVEL >= 10001
+# ifndef OPENSSL_NO_DEPRECATED
+# define OSSL_DEPRECATEDIN_1_0_1 OSSL_DEPRECATED(1.0.1)
+# define OSSL_DEPRECATEDIN_1_0_1_FOR(msg) OSSL_DEPRECATED_FOR(1.0.1, msg)
+# else
+# define OPENSSL_NO_DEPRECATED_1_0_1
+# endif
+# else
+# define OSSL_DEPRECATEDIN_1_0_1
+# define OSSL_DEPRECATEDIN_1_0_1_FOR(msg)
+# endif
+# if OPENSSL_API_LEVEL >= 10000
+# ifndef OPENSSL_NO_DEPRECATED
+# define OSSL_DEPRECATEDIN_1_0_0 OSSL_DEPRECATED(1.0.0)
+# define OSSL_DEPRECATEDIN_1_0_0_FOR(msg) OSSL_DEPRECATED_FOR(1.0.0, msg)
+# else
+# define OPENSSL_NO_DEPRECATED_1_0_0
+# endif
+# else
+# define OSSL_DEPRECATEDIN_1_0_0
+# define OSSL_DEPRECATEDIN_1_0_0_FOR(msg)
+# endif
+# if OPENSSL_API_LEVEL >= 908
+# ifndef OPENSSL_NO_DEPRECATED
+# define OSSL_DEPRECATEDIN_0_9_8 OSSL_DEPRECATED(0.9.8)
+# define OSSL_DEPRECATEDIN_0_9_8_FOR(msg) OSSL_DEPRECATED_FOR(0.9.8, msg)
+# else
+# define OPENSSL_NO_DEPRECATED_0_9_8
+# endif
+# else
+# define OSSL_DEPRECATEDIN_0_9_8
+# define OSSL_DEPRECATEDIN_0_9_8_FOR(msg)
+# endif
+
+/*
+ * Make our own variants of __FILE__ and __LINE__, depending on configuration
+ */
+
+# ifndef OPENSSL_FILE
+# ifdef OPENSSL_NO_FILENAMES
+# define OPENSSL_FILE ""
+# define OPENSSL_LINE 0
+# else
+# define OPENSSL_FILE __FILE__
+# define OPENSSL_LINE __LINE__
+# endif
+# endif
+
+/*
+ * __func__ was standardized in C99, so for any compiler that claims
+ * to implement that language level or newer, we assume we can safely
+ * use that symbol.
+ *
+ * GNU C also provides __FUNCTION__ since version 2, which predates
+ * C99. We can, however, only use this if __STDC_VERSION__ exists,
+ * as it's otherwise not allowed according to ISO C standards (C90).
+ * (compiling with GNU C's -pedantic tells us so)
+ *
+ * If none of the above applies, we check if the compiler is MSVC,
+ * and use __FUNCTION__ if that's the case.
+ */
+# ifndef OPENSSL_FUNC
+# if defined(__STDC_VERSION__)
+# if __STDC_VERSION__ >= 199901L
+# define OPENSSL_FUNC __func__
+# elif defined(__GNUC__) && __GNUC__ >= 2
+# define OPENSSL_FUNC __FUNCTION__
+# endif
+# elif defined(_MSC_VER)
+# define OPENSSL_FUNC __FUNCTION__
+# endif
+/*
+ * If all these possibilities are exhausted, we give up and use a
+ * static string.
+ */
+# ifndef OPENSSL_FUNC
+# define OPENSSL_FUNC "(unknown function)"
+# endif
+# endif
+
+#endif /* OPENSSL_MACROS_H */
diff --git a/include/openssl/md2.h b/include/openssl/md2.h
index 7faf8e3d6566..5d4cb77e71cb 100644
--- a/include/openssl/md2.h
+++ b/include/openssl/md2.h
@@ -1,27 +1,36 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_MD2_H
-# define HEADER_MD2_H
+#ifndef OPENSSL_MD2_H
+# define OPENSSL_MD2_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_MD2_H
+# endif
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_MD2
-# include <stddef.h>
-# ifdef __cplusplus
+# include <stddef.h>
+# ifdef __cplusplus
extern "C" {
-# endif
+# endif
+
+# define MD2_DIGEST_LENGTH 16
+
+# if !defined(OPENSSL_NO_DEPRECATED_3_0)
typedef unsigned char MD2_INT;
-# define MD2_DIGEST_LENGTH 16
-# define MD2_BLOCK 16
+# define MD2_BLOCK 16
typedef struct MD2state_st {
unsigned int num;
@@ -29,16 +38,19 @@ typedef struct MD2state_st {
MD2_INT cksm[MD2_BLOCK];
MD2_INT state[MD2_BLOCK];
} MD2_CTX;
-
-const char *MD2_options(void);
-int MD2_Init(MD2_CTX *c);
-int MD2_Update(MD2_CTX *c, const unsigned char *data, size_t len);
-int MD2_Final(unsigned char *md, MD2_CTX *c);
-unsigned char *MD2(const unsigned char *d, size_t n, unsigned char *md);
-
-# ifdef __cplusplus
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 const char *MD2_options(void);
+OSSL_DEPRECATEDIN_3_0 int MD2_Init(MD2_CTX *c);
+OSSL_DEPRECATEDIN_3_0 int MD2_Update(MD2_CTX *c, const unsigned char *data,
+ size_t len);
+OSSL_DEPRECATEDIN_3_0 int MD2_Final(unsigned char *md, MD2_CTX *c);
+OSSL_DEPRECATEDIN_3_0 unsigned char *MD2(const unsigned char *d, size_t n,
+ unsigned char *md);
+# endif
+
+# ifdef __cplusplus
}
+# endif
# endif
-# endif
-
#endif
diff --git a/include/openssl/md4.h b/include/openssl/md4.h
index 940e29db409c..6c150a6cb24c 100644
--- a/include/openssl/md4.h
+++ b/include/openssl/md4.h
@@ -1,34 +1,43 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_MD4_H
-# define HEADER_MD4_H
+#ifndef OPENSSL_MD4_H
+# define OPENSSL_MD4_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_MD4_H
+# endif
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_MD4
-# include <openssl/e_os2.h>
-# include <stddef.h>
-# ifdef __cplusplus
+# include <openssl/e_os2.h>
+# include <stddef.h>
+# ifdef __cplusplus
extern "C" {
-# endif
+# endif
+
+# define MD4_DIGEST_LENGTH 16
+
+# if !defined(OPENSSL_NO_DEPRECATED_3_0)
/*-
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* ! MD4_LONG has to be at least 32 bits wide. !
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
-# define MD4_LONG unsigned int
+# define MD4_LONG unsigned int
-# define MD4_CBLOCK 64
-# define MD4_LBLOCK (MD4_CBLOCK/4)
-# define MD4_DIGEST_LENGTH 16
+# define MD4_CBLOCK 64
+# define MD4_LBLOCK (MD4_CBLOCK/4)
typedef struct MD4state_st {
MD4_LONG A, B, C, D;
@@ -36,16 +45,19 @@ typedef struct MD4state_st {
MD4_LONG data[MD4_LBLOCK];
unsigned int num;
} MD4_CTX;
-
-int MD4_Init(MD4_CTX *c);
-int MD4_Update(MD4_CTX *c, const void *data, size_t len);
-int MD4_Final(unsigned char *md, MD4_CTX *c);
-unsigned char *MD4(const unsigned char *d, size_t n, unsigned char *md);
-void MD4_Transform(MD4_CTX *c, const unsigned char *b);
-
-# ifdef __cplusplus
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int MD4_Init(MD4_CTX *c);
+OSSL_DEPRECATEDIN_3_0 int MD4_Update(MD4_CTX *c, const void *data, size_t len);
+OSSL_DEPRECATEDIN_3_0 int MD4_Final(unsigned char *md, MD4_CTX *c);
+OSSL_DEPRECATEDIN_3_0 unsigned char *MD4(const unsigned char *d, size_t n,
+ unsigned char *md);
+OSSL_DEPRECATEDIN_3_0 void MD4_Transform(MD4_CTX *c, const unsigned char *b);
+# endif
+
+# ifdef __cplusplus
}
-# endif
+# endif
# endif
#endif
diff --git a/include/openssl/md5.h b/include/openssl/md5.h
index 2deb772118f2..77a577340f71 100644
--- a/include/openssl/md5.h
+++ b/include/openssl/md5.h
@@ -1,34 +1,42 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_MD5_H
-# define HEADER_MD5_H
+#ifndef OPENSSL_MD5_H
+# define OPENSSL_MD5_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_MD5_H
+# endif
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_MD5
-# include <openssl/e_os2.h>
-# include <stddef.h>
-# ifdef __cplusplus
+# include <openssl/e_os2.h>
+# include <stddef.h>
+# ifdef __cplusplus
extern "C" {
-# endif
+# endif
+# define MD5_DIGEST_LENGTH 16
+
+# if !defined(OPENSSL_NO_DEPRECATED_3_0)
/*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* ! MD5_LONG has to be at least 32 bits wide. !
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
-# define MD5_LONG unsigned int
+# define MD5_LONG unsigned int
-# define MD5_CBLOCK 64
-# define MD5_LBLOCK (MD5_CBLOCK/4)
-# define MD5_DIGEST_LENGTH 16
+# define MD5_CBLOCK 64
+# define MD5_LBLOCK (MD5_CBLOCK/4)
typedef struct MD5state_st {
MD5_LONG A, B, C, D;
@@ -36,15 +44,19 @@ typedef struct MD5state_st {
MD5_LONG data[MD5_LBLOCK];
unsigned int num;
} MD5_CTX;
-
-int MD5_Init(MD5_CTX *c);
-int MD5_Update(MD5_CTX *c, const void *data, size_t len);
-int MD5_Final(unsigned char *md, MD5_CTX *c);
-unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md);
-void MD5_Transform(MD5_CTX *c, const unsigned char *b);
-# ifdef __cplusplus
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int MD5_Init(MD5_CTX *c);
+OSSL_DEPRECATEDIN_3_0 int MD5_Update(MD5_CTX *c, const void *data, size_t len);
+OSSL_DEPRECATEDIN_3_0 int MD5_Final(unsigned char *md, MD5_CTX *c);
+OSSL_DEPRECATEDIN_3_0 unsigned char *MD5(const unsigned char *d, size_t n,
+ unsigned char *md);
+OSSL_DEPRECATEDIN_3_0 void MD5_Transform(MD5_CTX *c, const unsigned char *b);
+# endif
+
+# ifdef __cplusplus
}
-# endif
+# endif
# endif
#endif
diff --git a/include/openssl/mdc2.h b/include/openssl/mdc2.h
index aabd2bfaad8c..5a7ee289d1d0 100644
--- a/include/openssl/mdc2.h
+++ b/include/openssl/mdc2.h
@@ -1,42 +1,55 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_MDC2_H
-# define HEADER_MDC2_H
+#ifndef OPENSSL_MDC2_H
+# define OPENSSL_MDC2_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_MDC2_H
+# endif
# include <openssl/opensslconf.h>
-#ifndef OPENSSL_NO_MDC2
-# include <stdlib.h>
-# include <openssl/des.h>
-# ifdef __cplusplus
+# ifndef OPENSSL_NO_MDC2
+# include <stdlib.h>
+# include <openssl/des.h>
+# ifdef __cplusplus
extern "C" {
-# endif
+# endif
+
+# define MDC2_DIGEST_LENGTH 16
-# define MDC2_BLOCK 8
-# define MDC2_DIGEST_LENGTH 16
+# if !defined(OPENSSL_NO_DEPRECATED_3_0)
+
+# define MDC2_BLOCK 8
typedef struct mdc2_ctx_st {
unsigned int num;
unsigned char data[MDC2_BLOCK];
DES_cblock h, hh;
- int pad_type; /* either 1 or 2, default 1 */
+ unsigned int pad_type; /* either 1 or 2, default 1 */
} MDC2_CTX;
-
-int MDC2_Init(MDC2_CTX *c);
-int MDC2_Update(MDC2_CTX *c, const unsigned char *data, size_t len);
-int MDC2_Final(unsigned char *md, MDC2_CTX *c);
-unsigned char *MDC2(const unsigned char *d, size_t n, unsigned char *md);
-
-# ifdef __cplusplus
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int MDC2_Init(MDC2_CTX *c);
+OSSL_DEPRECATEDIN_3_0 int MDC2_Update(MDC2_CTX *c, const unsigned char *data,
+ size_t len);
+OSSL_DEPRECATEDIN_3_0 int MDC2_Final(unsigned char *md, MDC2_CTX *c);
+OSSL_DEPRECATEDIN_3_0 unsigned char *MDC2(const unsigned char *d, size_t n,
+ unsigned char *md);
+# endif
+
+# ifdef __cplusplus
}
-# endif
+# endif
# endif
#endif
diff --git a/include/openssl/modes.h b/include/openssl/modes.h
index d544f98d5585..e19079912ba2 100644
--- a/include/openssl/modes.h
+++ b/include/openssl/modes.h
@@ -1,16 +1,23 @@
/*
* Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_MODES_H
-# define HEADER_MODES_H
+#ifndef OPENSSL_MODES_H
+# define OPENSSL_MODES_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_MODES_H
+# endif
# include <stddef.h>
+# include <openssl/types.h>
# ifdef __cplusplus
extern "C" {
@@ -22,6 +29,10 @@ typedef void (*cbc128_f) (const unsigned char *in, unsigned char *out,
size_t len, const void *key,
unsigned char ivec[16], int enc);
+typedef void (*ecb128_f) (const unsigned char *in, unsigned char *out,
+ size_t len, const void *key,
+ int enc);
+
typedef void (*ctr128_f) (const unsigned char *in, unsigned char *out,
size_t blocks, const void *key,
const unsigned char ivec[16]);
diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h
index 53516a06c69b..0e8602766790 100644
--- a/include/openssl/obj_mac.h
+++ b/include/openssl/obj_mac.h
@@ -2,13 +2,17 @@
* WARNING: do not edit!
* Generated by crypto/objects/objects.pl
*
- * Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#ifndef OPENSSL_OBJ_MAC_H
+# define OPENSSL_OBJ_MAC_H
+# pragma once
+
#define SN_undef "UNDEF"
#define LN_undef "undefined"
#define NID_undef 0
@@ -44,6 +48,11 @@
#define NID_identified_organization 676
#define OBJ_identified_organization OBJ_iso,3L
+#define SN_gmac "GMAC"
+#define LN_gmac "gmac"
+#define NID_gmac 1195
+#define OBJ_gmac OBJ_iso,0L,9797L,3L,4L
+
#define SN_hmac_md5 "HMAC-MD5"
#define LN_hmac_md5 "hmac-md5"
#define NID_hmac_md5 780
@@ -845,6 +854,14 @@
#define NID_id_smime_ct_authEnvelopedData 1059
#define OBJ_id_smime_ct_authEnvelopedData OBJ_id_smime_ct,23L
+#define SN_id_ct_routeOriginAuthz "id-ct-routeOriginAuthz"
+#define NID_id_ct_routeOriginAuthz 1234
+#define OBJ_id_ct_routeOriginAuthz OBJ_id_smime_ct,24L
+
+#define SN_id_ct_rpkiManifest "id-ct-rpkiManifest"
+#define NID_id_ct_rpkiManifest 1235
+#define OBJ_id_ct_rpkiManifest OBJ_id_smime_ct,26L
+
#define SN_id_ct_asciiTextWithCRLF "id-ct-asciiTextWithCRLF"
#define NID_id_ct_asciiTextWithCRLF 787
#define OBJ_id_ct_asciiTextWithCRLF OBJ_id_smime_ct,27L
@@ -853,6 +870,22 @@
#define NID_id_ct_xml 1060
#define OBJ_id_ct_xml OBJ_id_smime_ct,28L
+#define SN_id_ct_rpkiGhostbusters "id-ct-rpkiGhostbusters"
+#define NID_id_ct_rpkiGhostbusters 1236
+#define OBJ_id_ct_rpkiGhostbusters OBJ_id_smime_ct,35L
+
+#define SN_id_ct_resourceTaggedAttest "id-ct-resourceTaggedAttest"
+#define NID_id_ct_resourceTaggedAttest 1237
+#define OBJ_id_ct_resourceTaggedAttest OBJ_id_smime_ct,36L
+
+#define SN_id_ct_geofeedCSVwithCRLF "id-ct-geofeedCSVwithCRLF"
+#define NID_id_ct_geofeedCSVwithCRLF 1246
+#define OBJ_id_ct_geofeedCSVwithCRLF OBJ_id_smime_ct,47L
+
+#define SN_id_ct_signedChecklist "id-ct-signedChecklist"
+#define NID_id_ct_signedChecklist 1247
+#define OBJ_id_ct_signedChecklist OBJ_id_smime_ct,48L
+
#define SN_id_smime_aa_receiptRequest "id-smime-aa-receiptRequest"
#define NID_id_smime_aa_receiptRequest 212
#define OBJ_id_smime_aa_receiptRequest OBJ_id_smime_aa,1L
@@ -1179,6 +1212,11 @@
#define NID_sm3WithRSAEncryption 1144
#define OBJ_sm3WithRSAEncryption OBJ_sm_scheme,504L
+#define SN_SM2_with_SM3 "SM2-SM3"
+#define LN_SM2_with_SM3 "SM2-with-SM3"
+#define NID_SM2_with_SM3 1204
+#define OBJ_SM2_with_SM3 OBJ_sm_scheme,501L
+
#define LN_hmacWithSHA224 "hmacWithSHA224"
#define NID_hmacWithSHA224 798
#define OBJ_hmacWithSHA224 OBJ_rsadsi,2L,8L
@@ -1385,6 +1423,10 @@
#define NID_id_qcs 267
#define OBJ_id_qcs OBJ_id_pkix,11L
+#define SN_id_cp "id-cp"
+#define NID_id_cp 1238
+#define OBJ_id_cp OBJ_id_pkix,14L
+
#define SN_id_cct "id-cct"
#define NID_id_cct 268
#define OBJ_id_cct OBJ_id_pkix,12L
@@ -1518,6 +1560,14 @@
#define NID_tlsfeature 1020
#define OBJ_tlsfeature OBJ_id_pe,24L
+#define SN_sbgp_ipAddrBlockv2 "sbgp-ipAddrBlockv2"
+#define NID_sbgp_ipAddrBlockv2 1239
+#define OBJ_sbgp_ipAddrBlockv2 OBJ_id_pe,28L
+
+#define SN_sbgp_autonomousSysNumv2 "sbgp-autonomousSysNumv2"
+#define NID_sbgp_autonomousSysNumv2 1240
+#define OBJ_sbgp_autonomousSysNumv2 OBJ_id_pe,29L
+
#define SN_id_qt_cps "id-qt-cps"
#define LN_id_qt_cps "Policy Qualifier CPS"
#define NID_id_qt_cps 164
@@ -1637,6 +1687,26 @@
#define NID_cmcRA 1132
#define OBJ_cmcRA OBJ_id_kp,28L
+#define SN_cmcArchive "cmcArchive"
+#define LN_cmcArchive "CMC Archive Server"
+#define NID_cmcArchive 1219
+#define OBJ_cmcArchive OBJ_id_kp,29L
+
+#define SN_id_kp_bgpsec_router "id-kp-bgpsec-router"
+#define LN_id_kp_bgpsec_router "BGPsec Router"
+#define NID_id_kp_bgpsec_router 1220
+#define OBJ_id_kp_bgpsec_router OBJ_id_kp,30L
+
+#define SN_id_kp_BrandIndicatorforMessageIdentification "id-kp-BrandIndicatorforMessageIdentification"
+#define LN_id_kp_BrandIndicatorforMessageIdentification "Brand Indicator for Message Identification"
+#define NID_id_kp_BrandIndicatorforMessageIdentification 1221
+#define OBJ_id_kp_BrandIndicatorforMessageIdentification OBJ_id_kp,31L
+
+#define SN_cmKGA "cmKGA"
+#define LN_cmKGA "Certificate Management Key Generation Authority"
+#define NID_cmKGA 1222
+#define OBJ_cmKGA OBJ_id_kp,32L
+
#define SN_id_it_caProtEncCert "id-it-caProtEncCert"
#define NID_id_it_caProtEncCert 298
#define OBJ_id_it_caProtEncCert OBJ_id_it,1L
@@ -1701,6 +1771,18 @@
#define NID_id_it_suppLangTags 784
#define OBJ_id_it_suppLangTags OBJ_id_it,16L
+#define SN_id_it_caCerts "id-it-caCerts"
+#define NID_id_it_caCerts 1223
+#define OBJ_id_it_caCerts OBJ_id_it,17L
+
+#define SN_id_it_rootCaKeyUpdate "id-it-rootCaKeyUpdate"
+#define NID_id_it_rootCaKeyUpdate 1224
+#define OBJ_id_it_rootCaKeyUpdate OBJ_id_it,18L
+
+#define SN_id_it_certReqTemplate "id-it-certReqTemplate"
+#define NID_id_it_certReqTemplate 1225
+#define OBJ_id_it_certReqTemplate OBJ_id_it,19L
+
#define SN_id_regCtrl "id-regCtrl"
#define NID_id_regCtrl 313
#define OBJ_id_regCtrl OBJ_id_pkip,1L
@@ -1846,6 +1928,26 @@
#define NID_id_on_permanentIdentifier 858
#define OBJ_id_on_permanentIdentifier OBJ_id_on,3L
+#define SN_XmppAddr "id-on-xmppAddr"
+#define LN_XmppAddr "XmppAddr"
+#define NID_XmppAddr 1209
+#define OBJ_XmppAddr OBJ_id_on,5L
+
+#define SN_SRVName "id-on-dnsSRV"
+#define LN_SRVName "SRVName"
+#define NID_SRVName 1210
+#define OBJ_SRVName OBJ_id_on,7L
+
+#define SN_NAIRealm "id-on-NAIRealm"
+#define LN_NAIRealm "NAIRealm"
+#define NID_NAIRealm 1211
+#define OBJ_NAIRealm OBJ_id_on,8L
+
+#define SN_id_on_SmtpUTF8Mailbox "id-on-SmtpUTF8Mailbox"
+#define LN_id_on_SmtpUTF8Mailbox "Smtp UTF8 Mailbox"
+#define NID_id_on_SmtpUTF8Mailbox 1208
+#define OBJ_id_on_SmtpUTF8Mailbox OBJ_id_on,9L
+
#define SN_id_pda_dateOfBirth "id-pda-dateOfBirth"
#define NID_id_pda_dateOfBirth 348
#define OBJ_id_pda_dateOfBirth OBJ_id_pda,1L
@@ -1894,6 +1996,14 @@
#define NID_id_qcs_pkixQCSyntax_v1 359
#define OBJ_id_qcs_pkixQCSyntax_v1 OBJ_id_qcs,1L
+#define SN_ipAddr_asNumber "ipAddr-asNumber"
+#define NID_ipAddr_asNumber 1241
+#define OBJ_ipAddr_asNumber OBJ_id_cp,2L
+
+#define SN_ipAddr_asNumberv2 "ipAddr-asNumberv2"
+#define NID_ipAddr_asNumberv2 1242
+#define OBJ_ipAddr_asNumberv2 OBJ_id_cp,3L
+
#define SN_id_cct_crs "id-cct-crs"
#define NID_id_cct_crs 360
#define OBJ_id_cct_crs OBJ_id_cct,1L
@@ -1946,6 +2056,21 @@
#define NID_caRepository 785
#define OBJ_caRepository OBJ_id_ad,5L
+#define SN_rpkiManifest "rpkiManifest"
+#define LN_rpkiManifest "RPKI Manifest"
+#define NID_rpkiManifest 1243
+#define OBJ_rpkiManifest OBJ_id_ad,10L
+
+#define SN_signedObject "signedObject"
+#define LN_signedObject "Signed Object"
+#define NID_signedObject 1244
+#define OBJ_signedObject OBJ_id_ad,11L
+
+#define SN_rpkiNotify "rpkiNotify"
+#define LN_rpkiNotify "RPKI Notify"
+#define NID_rpkiNotify 1245
+#define OBJ_rpkiNotify OBJ_id_ad,13L
+
#define OBJ_id_pkix_OCSP OBJ_ad_OCSP
#define SN_id_pkix_OCSP_basic "basicOCSPResponse"
@@ -2113,15 +2238,25 @@
#define NID_ripemd160WithRSA 119
#define OBJ_ripemd160WithRSA 1L,3L,36L,3L,3L,1L,2L
+#define SN_blake2bmac "BLAKE2BMAC"
+#define LN_blake2bmac "blake2bmac"
+#define NID_blake2bmac 1201
+#define OBJ_blake2bmac 1L,3L,6L,1L,4L,1L,1722L,12L,2L,1L
+
+#define SN_blake2smac "BLAKE2SMAC"
+#define LN_blake2smac "blake2smac"
+#define NID_blake2smac 1202
+#define OBJ_blake2smac 1L,3L,6L,1L,4L,1L,1722L,12L,2L,2L
+
#define SN_blake2b512 "BLAKE2b512"
#define LN_blake2b512 "blake2b512"
#define NID_blake2b512 1056
-#define OBJ_blake2b512 1L,3L,6L,1L,4L,1L,1722L,12L,2L,1L,16L
+#define OBJ_blake2b512 OBJ_blake2bmac,16L
#define SN_blake2s256 "BLAKE2s256"
#define LN_blake2s256 "blake2s256"
#define NID_blake2s256 1057
-#define OBJ_blake2s256 1L,3L,6L,1L,4L,1L,1722L,12L,2L,2L,8L
+#define OBJ_blake2s256 OBJ_blake2smac,8L
#define SN_sxnet "SXNetID"
#define LN_sxnet "Strong Extranet ID"
@@ -2971,6 +3106,16 @@
#define NID_hmac_sha3_512 1105
#define OBJ_hmac_sha3_512 OBJ_nist_hashalgs,16L
+#define SN_kmac128 "KMAC128"
+#define LN_kmac128 "kmac128"
+#define NID_kmac128 1196
+#define OBJ_kmac128 OBJ_nist_hashalgs,19L
+
+#define SN_kmac256 "KMAC256"
+#define LN_kmac256 "kmac256"
+#define NID_kmac256 1197
+#define OBJ_kmac256 OBJ_nist_hashalgs,20L
+
#define OBJ_dsa_with_sha2 OBJ_nistAlgorithms,3L
#define SN_dsa_with_SHA224 "dsa_with_SHA224"
@@ -4230,25 +4375,25 @@
#define NID_id_tc26_cipher_gostr3412_2015_magma 1173
#define OBJ_id_tc26_cipher_gostr3412_2015_magma OBJ_id_tc26_cipher,1L
-#define SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm "id-tc26-cipher-gostr3412-2015-magma-ctracpkm"
-#define NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm 1174
-#define OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm OBJ_id_tc26_cipher_gostr3412_2015_magma,1L
+#define SN_magma_ctr_acpkm "magma-ctr-acpkm"
+#define NID_magma_ctr_acpkm 1174
+#define OBJ_magma_ctr_acpkm OBJ_id_tc26_cipher_gostr3412_2015_magma,1L
-#define SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac "id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac"
-#define NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac 1175
-#define OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac OBJ_id_tc26_cipher_gostr3412_2015_magma,2L
+#define SN_magma_ctr_acpkm_omac "magma-ctr-acpkm-omac"
+#define NID_magma_ctr_acpkm_omac 1175
+#define OBJ_magma_ctr_acpkm_omac OBJ_id_tc26_cipher_gostr3412_2015_magma,2L
#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik "id-tc26-cipher-gostr3412-2015-kuznyechik"
#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik 1176
#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik OBJ_id_tc26_cipher,2L
-#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm"
-#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm 1177
-#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik,1L
+#define SN_kuznyechik_ctr_acpkm "kuznyechik-ctr-acpkm"
+#define NID_kuznyechik_ctr_acpkm 1177
+#define OBJ_kuznyechik_ctr_acpkm OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik,1L
-#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac"
-#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac 1178
-#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik,2L
+#define SN_kuznyechik_ctr_acpkm_omac "kuznyechik-ctr-acpkm-omac"
+#define NID_kuznyechik_ctr_acpkm_omac 1178
+#define OBJ_kuznyechik_ctr_acpkm_omac OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik,2L
#define SN_id_tc26_agreement "id-tc26-agreement"
#define NID_id_tc26_agreement 991
@@ -4270,17 +4415,17 @@
#define NID_id_tc26_wrap_gostr3412_2015_magma 1180
#define OBJ_id_tc26_wrap_gostr3412_2015_magma OBJ_id_tc26_wrap,1L
-#define SN_id_tc26_wrap_gostr3412_2015_magma_kexp15 "id-tc26-wrap-gostr3412-2015-magma-kexp15"
-#define NID_id_tc26_wrap_gostr3412_2015_magma_kexp15 1181
-#define OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_magma,1L
+#define SN_magma_kexp15 "magma-kexp15"
+#define NID_magma_kexp15 1181
+#define OBJ_magma_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_magma,1L
#define SN_id_tc26_wrap_gostr3412_2015_kuznyechik "id-tc26-wrap-gostr3412-2015-kuznyechik"
#define NID_id_tc26_wrap_gostr3412_2015_kuznyechik 1182
#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik OBJ_id_tc26_wrap,2L
-#define SN_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15"
-#define NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1183
-#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik,1L
+#define SN_kuznyechik_kexp15 "kuznyechik-kexp15"
+#define NID_kuznyechik_kexp15 1183
+#define OBJ_kuznyechik_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik,1L
#define SN_id_tc26_constants "id-tc26-constants"
#define NID_id_tc26_constants 994
@@ -4370,6 +4515,11 @@
#define NID_SNILS 1006
#define OBJ_SNILS OBJ_member_body,643L,100L,3L
+#define SN_OGRNIP "OGRNIP"
+#define LN_OGRNIP "OGRNIP"
+#define NID_OGRNIP 1226
+#define OBJ_OGRNIP OBJ_member_body,643L,100L,5L
+
#define SN_subjectSignTool "subjectSignTool"
#define LN_subjectSignTool "Signing Tool of Subject"
#define NID_subjectSignTool 1007
@@ -4380,23 +4530,58 @@
#define NID_issuerSignTool 1008
#define OBJ_issuerSignTool OBJ_member_body,643L,100L,112L
-#define SN_grasshopper_ecb "grasshopper-ecb"
-#define NID_grasshopper_ecb 1012
+#define SN_classSignTool "classSignTool"
+#define LN_classSignTool "Class of Signing Tool"
+#define NID_classSignTool 1227
+#define OBJ_classSignTool OBJ_member_body,643L,100L,113L
+
+#define SN_classSignToolKC1 "classSignToolKC1"
+#define LN_classSignToolKC1 "Class of Signing Tool KC1"
+#define NID_classSignToolKC1 1228
+#define OBJ_classSignToolKC1 OBJ_member_body,643L,100L,113L,1L
+
+#define SN_classSignToolKC2 "classSignToolKC2"
+#define LN_classSignToolKC2 "Class of Signing Tool KC2"
+#define NID_classSignToolKC2 1229
+#define OBJ_classSignToolKC2 OBJ_member_body,643L,100L,113L,2L
-#define SN_grasshopper_ctr "grasshopper-ctr"
-#define NID_grasshopper_ctr 1013
+#define SN_classSignToolKC3 "classSignToolKC3"
+#define LN_classSignToolKC3 "Class of Signing Tool KC3"
+#define NID_classSignToolKC3 1230
+#define OBJ_classSignToolKC3 OBJ_member_body,643L,100L,113L,3L
-#define SN_grasshopper_ofb "grasshopper-ofb"
-#define NID_grasshopper_ofb 1014
+#define SN_classSignToolKB1 "classSignToolKB1"
+#define LN_classSignToolKB1 "Class of Signing Tool KB1"
+#define NID_classSignToolKB1 1231
+#define OBJ_classSignToolKB1 OBJ_member_body,643L,100L,113L,4L
-#define SN_grasshopper_cbc "grasshopper-cbc"
-#define NID_grasshopper_cbc 1015
+#define SN_classSignToolKB2 "classSignToolKB2"
+#define LN_classSignToolKB2 "Class of Signing Tool KB2"
+#define NID_classSignToolKB2 1232
+#define OBJ_classSignToolKB2 OBJ_member_body,643L,100L,113L,5L
-#define SN_grasshopper_cfb "grasshopper-cfb"
-#define NID_grasshopper_cfb 1016
+#define SN_classSignToolKA1 "classSignToolKA1"
+#define LN_classSignToolKA1 "Class of Signing Tool KA1"
+#define NID_classSignToolKA1 1233
+#define OBJ_classSignToolKA1 OBJ_member_body,643L,100L,113L,6L
-#define SN_grasshopper_mac "grasshopper-mac"
-#define NID_grasshopper_mac 1017
+#define SN_kuznyechik_ecb "kuznyechik-ecb"
+#define NID_kuznyechik_ecb 1012
+
+#define SN_kuznyechik_ctr "kuznyechik-ctr"
+#define NID_kuznyechik_ctr 1013
+
+#define SN_kuznyechik_ofb "kuznyechik-ofb"
+#define NID_kuznyechik_ofb 1014
+
+#define SN_kuznyechik_cbc "kuznyechik-cbc"
+#define NID_kuznyechik_cbc 1015
+
+#define SN_kuznyechik_cfb "kuznyechik-cfb"
+#define NID_kuznyechik_cfb 1016
+
+#define SN_kuznyechik_mac "kuznyechik-mac"
+#define NID_kuznyechik_mac 1017
#define SN_magma_ecb "magma-ecb"
#define NID_magma_ecb 1187
@@ -4970,6 +5155,22 @@
#define LN_hkdf "hkdf"
#define NID_hkdf 1036
+#define SN_sshkdf "SSHKDF"
+#define LN_sshkdf "sshkdf"
+#define NID_sshkdf 1203
+
+#define SN_sskdf "SSKDF"
+#define LN_sskdf "sskdf"
+#define NID_sskdf 1205
+
+#define SN_x942kdf "X942KDF"
+#define LN_x942kdf "x942kdf"
+#define NID_x942kdf 1207
+
+#define SN_x963kdf "X963KDF"
+#define LN_x963kdf "x963kdf"
+#define NID_x963kdf 1206
+
#define SN_id_pkinit "id-pkinit"
#define NID_id_pkinit 1031
#define OBJ_id_pkinit 1L,3L,6L,1L,5L,2L,3L
@@ -5036,6 +5237,10 @@
#define LN_kx_gost "kx-gost"
#define NID_kx_gost 1045
+#define SN_kx_gost18 "KxGOST18"
+#define LN_kx_gost18 "kx-gost18"
+#define NID_kx_gost18 1218
+
#define SN_kx_any "KxANY"
#define LN_kx_any "kx-any"
#define NID_kx_any 1063
@@ -5099,6 +5304,24 @@
#define SN_ffdhe8192 "ffdhe8192"
#define NID_ffdhe8192 1130
+#define SN_modp_1536 "modp_1536"
+#define NID_modp_1536 1212
+
+#define SN_modp_2048 "modp_2048"
+#define NID_modp_2048 1213
+
+#define SN_modp_3072 "modp_3072"
+#define NID_modp_3072 1214
+
+#define SN_modp_4096 "modp_4096"
+#define NID_modp_4096 1215
+
+#define SN_modp_6144 "modp_6144"
+#define NID_modp_6144 1216
+
+#define SN_modp_8192 "modp_8192"
+#define NID_modp_8192 1217
+
#define SN_ISO_UA "ISO-UA"
#define NID_ISO_UA 1150
#define OBJ_ISO_UA OBJ_member_body,804L
@@ -5196,3 +5419,63 @@
#define LN_uacurve9 "DSTU curve 9"
#define NID_uacurve9 1169
#define OBJ_uacurve9 OBJ_dstu4145le,2L,9L
+
+#define SN_aes_128_siv "AES-128-SIV"
+#define LN_aes_128_siv "aes-128-siv"
+#define NID_aes_128_siv 1198
+
+#define SN_aes_192_siv "AES-192-SIV"
+#define LN_aes_192_siv "aes-192-siv"
+#define NID_aes_192_siv 1199
+
+#define SN_aes_256_siv "AES-256-SIV"
+#define LN_aes_256_siv "aes-256-siv"
+#define NID_aes_256_siv 1200
+
+#endif /* OPENSSL_OBJ_MAC_H */
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+
+#define SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm SN_magma_ctr_acpkm
+#define NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm NID_magma_ctr_acpkm
+#define OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm OBJ_magma_ctr_acpkm
+
+#define SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac SN_magma_ctr_acpkm_omac
+#define NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac NID_magma_ctr_acpkm_omac
+#define OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac OBJ_magma_ctr_acpkm_omac
+
+#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm SN_kuznyechik_ctr_acpkm
+#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm NID_kuznyechik_ctr_acpkm
+#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm OBJ_kuznyechik_ctr_acpkm
+
+#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac SN_kuznyechik_ctr_acpkm_omac
+#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac NID_kuznyechik_ctr_acpkm_omac
+#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac OBJ_kuznyechik_ctr_acpkm_omac
+
+#define SN_id_tc26_wrap_gostr3412_2015_magma_kexp15 SN_magma_kexp15
+#define NID_id_tc26_wrap_gostr3412_2015_magma_kexp15 NID_magma_kexp15
+#define OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 OBJ_magma_kexp15
+
+#define SN_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 SN_kuznyechik_kexp15
+#define NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 NID_kuznyechik_kexp15
+#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 OBJ_kuznyechik_kexp15
+
+#define SN_grasshopper_ecb SN_kuznyechik_ecb
+#define NID_grasshopper_ecb NID_kuznyechik_ecb
+
+#define SN_grasshopper_ctr SN_kuznyechik_ctr
+#define NID_grasshopper_ctr NID_kuznyechik_ctr
+
+#define SN_grasshopper_ofb SN_kuznyechik_ofb
+#define NID_grasshopper_ofb NID_kuznyechik_ofb
+
+#define SN_grasshopper_cbc SN_kuznyechik_cbc
+#define NID_grasshopper_cbc NID_kuznyechik_cbc
+
+#define SN_grasshopper_cfb SN_kuznyechik_cfb
+#define NID_grasshopper_cfb NID_kuznyechik_cfb
+
+#define SN_grasshopper_mac SN_kuznyechik_mac
+#define NID_grasshopper_mac NID_kuznyechik_mac
+
+#endif /* OPENSSL_NO_DEPRECATED_3_0 */
diff --git a/include/openssl/objects.h b/include/openssl/objects.h
index 5e8b5762f872..9ea91c27c86a 100644
--- a/include/openssl/objects.h
+++ b/include/openssl/objects.h
@@ -1,14 +1,20 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_OBJECTS_H
-# define HEADER_OBJECTS_H
+#ifndef OPENSSL_OBJECTS_H
+# define OPENSSL_OBJECTS_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_OBJECTS_H
+# endif
# include <openssl/obj_mac.h>
# include <openssl/bio.h>
@@ -20,7 +26,9 @@
# define OBJ_NAME_TYPE_CIPHER_METH 0x02
# define OBJ_NAME_TYPE_PKEY_METH 0x03
# define OBJ_NAME_TYPE_COMP_METH 0x04
-# define OBJ_NAME_TYPE_NUM 0x05
+# define OBJ_NAME_TYPE_MAC_METH 0x05
+# define OBJ_NAME_TYPE_KDF_METH 0x06
+# define OBJ_NAME_TYPE_NUM 0x07
# define OBJ_NAME_ALIAS 0x8000
@@ -55,7 +63,7 @@ void OBJ_NAME_do_all_sorted(int type,
void (*fn) (const OBJ_NAME *, void *arg),
void *arg);
-ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o);
+DECLARE_ASN1_DUP_FUNCTION_name(ASN1_OBJECT, OBJ)
ASN1_OBJECT *OBJ_nid2obj(int n);
const char *OBJ_nid2ln(int n);
const char *OBJ_nid2sn(int n);
@@ -155,7 +163,7 @@ const void *OBJ_bsearch_ex_(const void *key, const void *base, int num,
int OBJ_new_nid(int num);
int OBJ_add_object(const ASN1_OBJECT *obj);
int OBJ_create(const char *oid, const char *sn, const char *ln);
-#if OPENSSL_API_COMPAT < 0x10100000L
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
# define OBJ_cleanup() while(0) continue
#endif
int OBJ_create_objects(BIO *in);
diff --git a/include/openssl/objectserr.h b/include/openssl/objectserr.h
index 02e166f1ac66..585217f6f7d1 100644
--- a/include/openssl/objectserr.h
+++ b/include/openssl/objectserr.h
@@ -1,42 +1,28 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_OBJERR_H
-# define HEADER_OBJERR_H
+#ifndef OPENSSL_OBJECTSERR_H
+# define OPENSSL_OBJECTSERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_OBJ_strings(void);
-/*
- * OBJ function codes.
- */
-# define OBJ_F_OBJ_ADD_OBJECT 105
-# define OBJ_F_OBJ_ADD_SIGID 107
-# define OBJ_F_OBJ_CREATE 100
-# define OBJ_F_OBJ_DUP 101
-# define OBJ_F_OBJ_NAME_NEW_INDEX 106
-# define OBJ_F_OBJ_NID2LN 102
-# define OBJ_F_OBJ_NID2OBJ 103
-# define OBJ_F_OBJ_NID2SN 104
-# define OBJ_F_OBJ_TXT2OBJ 108
/*
* OBJ reason codes.
*/
# define OBJ_R_OID_EXISTS 102
# define OBJ_R_UNKNOWN_NID 101
+# define OBJ_R_UNKNOWN_OBJECT_NAME 103
#endif
diff --git a/include/openssl/ocsp.h b/include/openssl/ocsp.h
deleted file mode 100644
index 4d759a49de43..000000000000
--- a/include/openssl/ocsp.h
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_OCSP_H
-# define HEADER_OCSP_H
-
-#include <openssl/opensslconf.h>
-
-/*
- * These definitions are outside the OPENSSL_NO_OCSP guard because although for
- * historical reasons they have OCSP_* names, they can actually be used
- * independently of OCSP. E.g. see RFC5280
- */
-/*-
- * CRLReason ::= ENUMERATED {
- * unspecified (0),
- * keyCompromise (1),
- * cACompromise (2),
- * affiliationChanged (3),
- * superseded (4),
- * cessationOfOperation (5),
- * certificateHold (6),
- * removeFromCRL (8) }
- */
-# define OCSP_REVOKED_STATUS_NOSTATUS -1
-# define OCSP_REVOKED_STATUS_UNSPECIFIED 0
-# define OCSP_REVOKED_STATUS_KEYCOMPROMISE 1
-# define OCSP_REVOKED_STATUS_CACOMPROMISE 2
-# define OCSP_REVOKED_STATUS_AFFILIATIONCHANGED 3
-# define OCSP_REVOKED_STATUS_SUPERSEDED 4
-# define OCSP_REVOKED_STATUS_CESSATIONOFOPERATION 5
-# define OCSP_REVOKED_STATUS_CERTIFICATEHOLD 6
-# define OCSP_REVOKED_STATUS_REMOVEFROMCRL 8
-
-
-# ifndef OPENSSL_NO_OCSP
-
-# include <openssl/ossl_typ.h>
-# include <openssl/x509.h>
-# include <openssl/x509v3.h>
-# include <openssl/safestack.h>
-# include <openssl/ocsperr.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Various flags and values */
-
-# define OCSP_DEFAULT_NONCE_LENGTH 16
-
-# define OCSP_NOCERTS 0x1
-# define OCSP_NOINTERN 0x2
-# define OCSP_NOSIGS 0x4
-# define OCSP_NOCHAIN 0x8
-# define OCSP_NOVERIFY 0x10
-# define OCSP_NOEXPLICIT 0x20
-# define OCSP_NOCASIGN 0x40
-# define OCSP_NODELEGATED 0x80
-# define OCSP_NOCHECKS 0x100
-# define OCSP_TRUSTOTHER 0x200
-# define OCSP_RESPID_KEY 0x400
-# define OCSP_NOTIME 0x800
-
-typedef struct ocsp_cert_id_st OCSP_CERTID;
-
-DEFINE_STACK_OF(OCSP_CERTID)
-
-typedef struct ocsp_one_request_st OCSP_ONEREQ;
-
-DEFINE_STACK_OF(OCSP_ONEREQ)
-
-typedef struct ocsp_req_info_st OCSP_REQINFO;
-typedef struct ocsp_signature_st OCSP_SIGNATURE;
-typedef struct ocsp_request_st OCSP_REQUEST;
-
-# define OCSP_RESPONSE_STATUS_SUCCESSFUL 0
-# define OCSP_RESPONSE_STATUS_MALFORMEDREQUEST 1
-# define OCSP_RESPONSE_STATUS_INTERNALERROR 2
-# define OCSP_RESPONSE_STATUS_TRYLATER 3
-# define OCSP_RESPONSE_STATUS_SIGREQUIRED 5
-# define OCSP_RESPONSE_STATUS_UNAUTHORIZED 6
-
-typedef struct ocsp_resp_bytes_st OCSP_RESPBYTES;
-
-# define V_OCSP_RESPID_NAME 0
-# define V_OCSP_RESPID_KEY 1
-
-DEFINE_STACK_OF(OCSP_RESPID)
-
-typedef struct ocsp_revoked_info_st OCSP_REVOKEDINFO;
-
-# define V_OCSP_CERTSTATUS_GOOD 0
-# define V_OCSP_CERTSTATUS_REVOKED 1
-# define V_OCSP_CERTSTATUS_UNKNOWN 2
-
-typedef struct ocsp_cert_status_st OCSP_CERTSTATUS;
-typedef struct ocsp_single_response_st OCSP_SINGLERESP;
-
-DEFINE_STACK_OF(OCSP_SINGLERESP)
-
-typedef struct ocsp_response_data_st OCSP_RESPDATA;
-
-typedef struct ocsp_basic_response_st OCSP_BASICRESP;
-
-typedef struct ocsp_crl_id_st OCSP_CRLID;
-typedef struct ocsp_service_locator_st OCSP_SERVICELOC;
-
-# define PEM_STRING_OCSP_REQUEST "OCSP REQUEST"
-# define PEM_STRING_OCSP_RESPONSE "OCSP RESPONSE"
-
-# define d2i_OCSP_REQUEST_bio(bp,p) ASN1_d2i_bio_of(OCSP_REQUEST,OCSP_REQUEST_new,d2i_OCSP_REQUEST,bp,p)
-
-# define d2i_OCSP_RESPONSE_bio(bp,p) ASN1_d2i_bio_of(OCSP_RESPONSE,OCSP_RESPONSE_new,d2i_OCSP_RESPONSE,bp,p)
-
-# define PEM_read_bio_OCSP_REQUEST(bp,x,cb) (OCSP_REQUEST *)PEM_ASN1_read_bio( \
- (char *(*)())d2i_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST, \
- bp,(char **)(x),cb,NULL)
-
-# define PEM_read_bio_OCSP_RESPONSE(bp,x,cb) (OCSP_RESPONSE *)PEM_ASN1_read_bio(\
- (char *(*)())d2i_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE, \
- bp,(char **)(x),cb,NULL)
-
-# define PEM_write_bio_OCSP_REQUEST(bp,o) \
- PEM_ASN1_write_bio((int (*)())i2d_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,\
- bp,(char *)(o), NULL,NULL,0,NULL,NULL)
-
-# define PEM_write_bio_OCSP_RESPONSE(bp,o) \
- PEM_ASN1_write_bio((int (*)())i2d_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,\
- bp,(char *)(o), NULL,NULL,0,NULL,NULL)
-
-# define i2d_OCSP_RESPONSE_bio(bp,o) ASN1_i2d_bio_of(OCSP_RESPONSE,i2d_OCSP_RESPONSE,bp,o)
-
-# define i2d_OCSP_REQUEST_bio(bp,o) ASN1_i2d_bio_of(OCSP_REQUEST,i2d_OCSP_REQUEST,bp,o)
-
-# define ASN1_BIT_STRING_digest(data,type,md,len) \
- ASN1_item_digest(ASN1_ITEM_rptr(ASN1_BIT_STRING),type,data,md,len)
-
-# define OCSP_CERTSTATUS_dup(cs)\
- (OCSP_CERTSTATUS*)ASN1_dup((int(*)())i2d_OCSP_CERTSTATUS,\
- (char *(*)())d2i_OCSP_CERTSTATUS,(char *)(cs))
-
-OCSP_CERTID *OCSP_CERTID_dup(OCSP_CERTID *id);
-
-OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req);
-OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req,
- int maxline);
-int OCSP_REQ_CTX_nbio(OCSP_REQ_CTX *rctx);
-int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx);
-OCSP_REQ_CTX *OCSP_REQ_CTX_new(BIO *io, int maxline);
-void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx);
-void OCSP_set_max_response_length(OCSP_REQ_CTX *rctx, unsigned long len);
-int OCSP_REQ_CTX_i2d(OCSP_REQ_CTX *rctx, const ASN1_ITEM *it,
- ASN1_VALUE *val);
-int OCSP_REQ_CTX_nbio_d2i(OCSP_REQ_CTX *rctx, ASN1_VALUE **pval,
- const ASN1_ITEM *it);
-BIO *OCSP_REQ_CTX_get0_mem_bio(OCSP_REQ_CTX *rctx);
-int OCSP_REQ_CTX_http(OCSP_REQ_CTX *rctx, const char *op, const char *path);
-int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req);
-int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx,
- const char *name, const char *value);
-
-OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject,
- const X509 *issuer);
-
-OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
- const X509_NAME *issuerName,
- const ASN1_BIT_STRING *issuerKey,
- const ASN1_INTEGER *serialNumber);
-
-OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid);
-
-int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len);
-int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len);
-int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs);
-int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req);
-
-int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm);
-int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert);
-
-int OCSP_request_sign(OCSP_REQUEST *req,
- X509 *signer,
- EVP_PKEY *key,
- const EVP_MD *dgst,
- STACK_OF(X509) *certs, unsigned long flags);
-
-int OCSP_response_status(OCSP_RESPONSE *resp);
-OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp);
-
-const ASN1_OCTET_STRING *OCSP_resp_get0_signature(const OCSP_BASICRESP *bs);
-const X509_ALGOR *OCSP_resp_get0_tbs_sigalg(const OCSP_BASICRESP *bs);
-const OCSP_RESPDATA *OCSP_resp_get0_respdata(const OCSP_BASICRESP *bs);
-int OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer,
- STACK_OF(X509) *extra_certs);
-
-int OCSP_resp_count(OCSP_BASICRESP *bs);
-OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx);
-const ASN1_GENERALIZEDTIME *OCSP_resp_get0_produced_at(const OCSP_BASICRESP* bs);
-const STACK_OF(X509) *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs);
-int OCSP_resp_get0_id(const OCSP_BASICRESP *bs,
- const ASN1_OCTET_STRING **pid,
- const X509_NAME **pname);
-int OCSP_resp_get1_id(const OCSP_BASICRESP *bs,
- ASN1_OCTET_STRING **pid,
- X509_NAME **pname);
-
-int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last);
-int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason,
- ASN1_GENERALIZEDTIME **revtime,
- ASN1_GENERALIZEDTIME **thisupd,
- ASN1_GENERALIZEDTIME **nextupd);
-int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status,
- int *reason,
- ASN1_GENERALIZEDTIME **revtime,
- ASN1_GENERALIZEDTIME **thisupd,
- ASN1_GENERALIZEDTIME **nextupd);
-int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd,
- ASN1_GENERALIZEDTIME *nextupd, long sec, long maxsec);
-
-int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs,
- X509_STORE *store, unsigned long flags);
-
-int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath,
- int *pssl);
-
-int OCSP_id_issuer_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b);
-int OCSP_id_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b);
-
-int OCSP_request_onereq_count(OCSP_REQUEST *req);
-OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i);
-OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one);
-int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd,
- ASN1_OCTET_STRING **pikeyHash,
- ASN1_INTEGER **pserial, OCSP_CERTID *cid);
-int OCSP_request_is_signed(OCSP_REQUEST *req);
-OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs);
-OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp,
- OCSP_CERTID *cid,
- int status, int reason,
- ASN1_TIME *revtime,
- ASN1_TIME *thisupd,
- ASN1_TIME *nextupd);
-int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert);
-int OCSP_basic_sign(OCSP_BASICRESP *brsp,
- X509 *signer, EVP_PKEY *key, const EVP_MD *dgst,
- STACK_OF(X509) *certs, unsigned long flags);
-int OCSP_basic_sign_ctx(OCSP_BASICRESP *brsp,
- X509 *signer, EVP_MD_CTX *ctx,
- STACK_OF(X509) *certs, unsigned long flags);
-int OCSP_RESPID_set_by_name(OCSP_RESPID *respid, X509 *cert);
-int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert);
-int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert);
-
-X509_EXTENSION *OCSP_crlID_new(const char *url, long *n, char *tim);
-
-X509_EXTENSION *OCSP_accept_responses_new(char **oids);
-
-X509_EXTENSION *OCSP_archive_cutoff_new(char *tim);
-
-X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME *issuer, const char **urls);
-
-int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x);
-int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos);
-int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, const ASN1_OBJECT *obj,
- int lastpos);
-int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos);
-X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc);
-X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc);
-void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit,
- int *idx);
-int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit,
- unsigned long flags);
-int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc);
-
-int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x);
-int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos);
-int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, const ASN1_OBJECT *obj, int lastpos);
-int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos);
-X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc);
-X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc);
-void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx);
-int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit,
- unsigned long flags);
-int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc);
-
-int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x);
-int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos);
-int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, const ASN1_OBJECT *obj,
- int lastpos);
-int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit,
- int lastpos);
-X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc);
-X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc);
-void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit,
- int *idx);
-int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value,
- int crit, unsigned long flags);
-int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc);
-
-int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x);
-int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos);
-int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, const ASN1_OBJECT *obj,
- int lastpos);
-int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit,
- int lastpos);
-X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc);
-X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc);
-void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit,
- int *idx);
-int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value,
- int crit, unsigned long flags);
-int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc);
-const OCSP_CERTID *OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *x);
-
-DECLARE_ASN1_FUNCTIONS(OCSP_SINGLERESP)
-DECLARE_ASN1_FUNCTIONS(OCSP_CERTSTATUS)
-DECLARE_ASN1_FUNCTIONS(OCSP_REVOKEDINFO)
-DECLARE_ASN1_FUNCTIONS(OCSP_BASICRESP)
-DECLARE_ASN1_FUNCTIONS(OCSP_RESPDATA)
-DECLARE_ASN1_FUNCTIONS(OCSP_RESPID)
-DECLARE_ASN1_FUNCTIONS(OCSP_RESPONSE)
-DECLARE_ASN1_FUNCTIONS(OCSP_RESPBYTES)
-DECLARE_ASN1_FUNCTIONS(OCSP_ONEREQ)
-DECLARE_ASN1_FUNCTIONS(OCSP_CERTID)
-DECLARE_ASN1_FUNCTIONS(OCSP_REQUEST)
-DECLARE_ASN1_FUNCTIONS(OCSP_SIGNATURE)
-DECLARE_ASN1_FUNCTIONS(OCSP_REQINFO)
-DECLARE_ASN1_FUNCTIONS(OCSP_CRLID)
-DECLARE_ASN1_FUNCTIONS(OCSP_SERVICELOC)
-
-const char *OCSP_response_status_str(long s);
-const char *OCSP_cert_status_str(long s);
-const char *OCSP_crl_reason_str(long s);
-
-int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST *a, unsigned long flags);
-int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE *o, unsigned long flags);
-
-int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
- X509_STORE *st, unsigned long flags);
-
-
-# ifdef __cplusplus
-}
-# endif
-# endif
-#endif
diff --git a/include/openssl/ocsp.h.in b/include/openssl/ocsp.h.in
new file mode 100644
index 000000000000..e2cc2716b56b
--- /dev/null
+++ b/include/openssl/ocsp.h.in
@@ -0,0 +1,387 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_OCSP_H
+# define OPENSSL_OCSP_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_OCSP_H
+# endif
+
+# include <openssl/opensslconf.h>
+# include <openssl/http.h>
+# include <openssl/asn1.h>
+
+/*
+ * These definitions are outside the OPENSSL_NO_OCSP guard because although for
+ * historical reasons they have OCSP_* names, they can actually be used
+ * independently of OCSP. E.g. see RFC5280
+ */
+/*-
+ * CRLReason ::= ENUMERATED {
+ * unspecified (0),
+ * keyCompromise (1),
+ * cACompromise (2),
+ * affiliationChanged (3),
+ * superseded (4),
+ * cessationOfOperation (5),
+ * certificateHold (6),
+ * -- value 7 is not used
+ * removeFromCRL (8),
+ * privilegeWithdrawn (9),
+ * aACompromise (10) }
+ */
+# define OCSP_REVOKED_STATUS_NOSTATUS -1
+# define OCSP_REVOKED_STATUS_UNSPECIFIED 0
+# define OCSP_REVOKED_STATUS_KEYCOMPROMISE 1
+# define OCSP_REVOKED_STATUS_CACOMPROMISE 2
+# define OCSP_REVOKED_STATUS_AFFILIATIONCHANGED 3
+# define OCSP_REVOKED_STATUS_SUPERSEDED 4
+# define OCSP_REVOKED_STATUS_CESSATIONOFOPERATION 5
+# define OCSP_REVOKED_STATUS_CERTIFICATEHOLD 6
+# define OCSP_REVOKED_STATUS_REMOVEFROMCRL 8
+# define OCSP_REVOKED_STATUS_PRIVILEGEWITHDRAWN 9
+# define OCSP_REVOKED_STATUS_AACOMPROMISE 10
+
+
+# ifndef OPENSSL_NO_OCSP
+
+# include <openssl/x509.h>
+# include <openssl/x509v3.h>
+# include <openssl/safestack.h>
+# include <openssl/ocsperr.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/* Various flags and values */
+
+# define OCSP_DEFAULT_NONCE_LENGTH 16
+
+# define OCSP_NOCERTS 0x1
+# define OCSP_NOINTERN 0x2
+# define OCSP_NOSIGS 0x4
+# define OCSP_NOCHAIN 0x8
+# define OCSP_NOVERIFY 0x10
+# define OCSP_NOEXPLICIT 0x20
+# define OCSP_NOCASIGN 0x40
+# define OCSP_NODELEGATED 0x80
+# define OCSP_NOCHECKS 0x100
+# define OCSP_TRUSTOTHER 0x200
+# define OCSP_RESPID_KEY 0x400
+# define OCSP_NOTIME 0x800
+# define OCSP_PARTIAL_CHAIN 0x1000
+
+typedef struct ocsp_cert_id_st OCSP_CERTID;
+typedef struct ocsp_one_request_st OCSP_ONEREQ;
+typedef struct ocsp_req_info_st OCSP_REQINFO;
+typedef struct ocsp_signature_st OCSP_SIGNATURE;
+typedef struct ocsp_request_st OCSP_REQUEST;
+
+{-
+ generate_stack_macros("OCSP_CERTID")
+ .generate_stack_macros("OCSP_ONEREQ");
+-}
+
+# define OCSP_RESPONSE_STATUS_SUCCESSFUL 0
+# define OCSP_RESPONSE_STATUS_MALFORMEDREQUEST 1
+# define OCSP_RESPONSE_STATUS_INTERNALERROR 2
+# define OCSP_RESPONSE_STATUS_TRYLATER 3
+# define OCSP_RESPONSE_STATUS_SIGREQUIRED 5
+# define OCSP_RESPONSE_STATUS_UNAUTHORIZED 6
+
+typedef struct ocsp_resp_bytes_st OCSP_RESPBYTES;
+
+# define V_OCSP_RESPID_NAME 0
+# define V_OCSP_RESPID_KEY 1
+
+{-
+ generate_stack_macros("OCSP_RESPID");
+-}
+
+typedef struct ocsp_revoked_info_st OCSP_REVOKEDINFO;
+
+# define V_OCSP_CERTSTATUS_GOOD 0
+# define V_OCSP_CERTSTATUS_REVOKED 1
+# define V_OCSP_CERTSTATUS_UNKNOWN 2
+
+typedef struct ocsp_cert_status_st OCSP_CERTSTATUS;
+typedef struct ocsp_single_response_st OCSP_SINGLERESP;
+
+{-
+ generate_stack_macros("OCSP_SINGLERESP");
+-}
+
+typedef struct ocsp_response_data_st OCSP_RESPDATA;
+
+typedef struct ocsp_basic_response_st OCSP_BASICRESP;
+
+typedef struct ocsp_crl_id_st OCSP_CRLID;
+typedef struct ocsp_service_locator_st OCSP_SERVICELOC;
+
+# define PEM_STRING_OCSP_REQUEST "OCSP REQUEST"
+# define PEM_STRING_OCSP_RESPONSE "OCSP RESPONSE"
+
+# define d2i_OCSP_REQUEST_bio(bp,p) ASN1_d2i_bio_of(OCSP_REQUEST,OCSP_REQUEST_new,d2i_OCSP_REQUEST,bp,p)
+
+# define d2i_OCSP_RESPONSE_bio(bp,p) ASN1_d2i_bio_of(OCSP_RESPONSE,OCSP_RESPONSE_new,d2i_OCSP_RESPONSE,bp,p)
+
+# define PEM_read_bio_OCSP_REQUEST(bp,x,cb) (OCSP_REQUEST *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST, \
+ bp,(char **)(x),cb,NULL)
+
+# define PEM_read_bio_OCSP_RESPONSE(bp,x,cb) (OCSP_RESPONSE *)PEM_ASN1_read_bio(\
+ (char *(*)())d2i_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE, \
+ bp,(char **)(x),cb,NULL)
+
+# define PEM_write_bio_OCSP_REQUEST(bp,o) \
+ PEM_ASN1_write_bio((int (*)())i2d_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,\
+ bp,(char *)(o), NULL,NULL,0,NULL,NULL)
+
+# define PEM_write_bio_OCSP_RESPONSE(bp,o) \
+ PEM_ASN1_write_bio((int (*)())i2d_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,\
+ bp,(char *)(o), NULL,NULL,0,NULL,NULL)
+
+# define i2d_OCSP_RESPONSE_bio(bp,o) ASN1_i2d_bio_of(OCSP_RESPONSE,i2d_OCSP_RESPONSE,bp,o)
+
+# define i2d_OCSP_REQUEST_bio(bp,o) ASN1_i2d_bio_of(OCSP_REQUEST,i2d_OCSP_REQUEST,bp,o)
+
+# define ASN1_BIT_STRING_digest(data,type,md,len) \
+ ASN1_item_digest(ASN1_ITEM_rptr(ASN1_BIT_STRING),type,data,md,len)
+
+# define OCSP_CERTSTATUS_dup(cs)\
+ (OCSP_CERTSTATUS*)ASN1_dup((i2d_of_void *)i2d_OCSP_CERTSTATUS,\
+ (d2i_of_void *)d2i_OCSP_CERTSTATUS,(char *)(cs))
+
+DECLARE_ASN1_DUP_FUNCTION(OCSP_CERTID)
+
+OSSL_HTTP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path,
+ const OCSP_REQUEST *req, int buf_size);
+OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req);
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+typedef OSSL_HTTP_REQ_CTX OCSP_REQ_CTX;
+# define OCSP_REQ_CTX_new(io, buf_size) \
+ OSSL_HTTP_REQ_CTX_new(io, io, buf_size)
+# define OCSP_REQ_CTX_free OSSL_HTTP_REQ_CTX_free
+# define OCSP_REQ_CTX_http(rctx, op, path) \
+ (OSSL_HTTP_REQ_CTX_set_expected(rctx, NULL, 1 /* asn1 */, 0, 0) && \
+ OSSL_HTTP_REQ_CTX_set_request_line(rctx, strcmp(op, "POST") == 0, \
+ NULL, NULL, path))
+# define OCSP_REQ_CTX_add1_header OSSL_HTTP_REQ_CTX_add1_header
+# define OCSP_REQ_CTX_i2d(r, it, req) \
+ OSSL_HTTP_REQ_CTX_set1_req(r, "application/ocsp-request", it, req)
+# define OCSP_REQ_CTX_set1_req(r, req) \
+ OCSP_REQ_CTX_i2d(r, ASN1_ITEM_rptr(OCSP_REQUEST), (ASN1_VALUE *)(req))
+# define OCSP_REQ_CTX_nbio OSSL_HTTP_REQ_CTX_nbio
+# define OCSP_REQ_CTX_nbio_d2i OSSL_HTTP_REQ_CTX_nbio_d2i
+# define OCSP_sendreq_nbio(p, r) \
+ OSSL_HTTP_REQ_CTX_nbio_d2i(r, (ASN1_VALUE **)(p), \
+ ASN1_ITEM_rptr(OCSP_RESPONSE))
+# define OCSP_REQ_CTX_get0_mem_bio OSSL_HTTP_REQ_CTX_get0_mem_bio
+# define OCSP_set_max_response_length OSSL_HTTP_REQ_CTX_set_max_response_length
+# endif
+
+OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject,
+ const X509 *issuer);
+
+OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
+ const X509_NAME *issuerName,
+ const ASN1_BIT_STRING *issuerKey,
+ const ASN1_INTEGER *serialNumber);
+
+OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid);
+
+int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len);
+int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len);
+int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs);
+int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req);
+
+int OCSP_request_set1_name(OCSP_REQUEST *req, const X509_NAME *nm);
+int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert);
+
+int OCSP_request_sign(OCSP_REQUEST *req,
+ X509 *signer,
+ EVP_PKEY *key,
+ const EVP_MD *dgst,
+ STACK_OF(X509) *certs, unsigned long flags);
+
+int OCSP_response_status(OCSP_RESPONSE *resp);
+OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp);
+
+const ASN1_OCTET_STRING *OCSP_resp_get0_signature(const OCSP_BASICRESP *bs);
+const X509_ALGOR *OCSP_resp_get0_tbs_sigalg(const OCSP_BASICRESP *bs);
+const OCSP_RESPDATA *OCSP_resp_get0_respdata(const OCSP_BASICRESP *bs);
+int OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer,
+ STACK_OF(X509) *extra_certs);
+
+int OCSP_resp_count(OCSP_BASICRESP *bs);
+OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx);
+const ASN1_GENERALIZEDTIME *OCSP_resp_get0_produced_at(const OCSP_BASICRESP* bs);
+const STACK_OF(X509) *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs);
+int OCSP_resp_get0_id(const OCSP_BASICRESP *bs,
+ const ASN1_OCTET_STRING **pid,
+ const X509_NAME **pname);
+int OCSP_resp_get1_id(const OCSP_BASICRESP *bs,
+ ASN1_OCTET_STRING **pid,
+ X509_NAME **pname);
+
+int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last);
+int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason,
+ ASN1_GENERALIZEDTIME **revtime,
+ ASN1_GENERALIZEDTIME **thisupd,
+ ASN1_GENERALIZEDTIME **nextupd);
+int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status,
+ int *reason,
+ ASN1_GENERALIZEDTIME **revtime,
+ ASN1_GENERALIZEDTIME **thisupd,
+ ASN1_GENERALIZEDTIME **nextupd);
+int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd,
+ ASN1_GENERALIZEDTIME *nextupd, long sec, long maxsec);
+
+int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs,
+ X509_STORE *store, unsigned long flags);
+
+# define OCSP_parse_url(url, host, port, path, ssl) \
+ OSSL_HTTP_parse_url(url, ssl, NULL, host, port, NULL, path, NULL, NULL)
+
+int OCSP_id_issuer_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b);
+int OCSP_id_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b);
+
+int OCSP_request_onereq_count(OCSP_REQUEST *req);
+OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i);
+OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one);
+int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd,
+ ASN1_OCTET_STRING **pikeyHash,
+ ASN1_INTEGER **pserial, OCSP_CERTID *cid);
+int OCSP_request_is_signed(OCSP_REQUEST *req);
+OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs);
+OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp,
+ OCSP_CERTID *cid,
+ int status, int reason,
+ ASN1_TIME *revtime,
+ ASN1_TIME *thisupd,
+ ASN1_TIME *nextupd);
+int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert);
+int OCSP_basic_sign(OCSP_BASICRESP *brsp,
+ X509 *signer, EVP_PKEY *key, const EVP_MD *dgst,
+ STACK_OF(X509) *certs, unsigned long flags);
+int OCSP_basic_sign_ctx(OCSP_BASICRESP *brsp,
+ X509 *signer, EVP_MD_CTX *ctx,
+ STACK_OF(X509) *certs, unsigned long flags);
+int OCSP_RESPID_set_by_name(OCSP_RESPID *respid, X509 *cert);
+int OCSP_RESPID_set_by_key_ex(OCSP_RESPID *respid, X509 *cert,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert);
+int OCSP_RESPID_match_ex(OCSP_RESPID *respid, X509 *cert, OSSL_LIB_CTX *libctx,
+ const char *propq);
+int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert);
+
+X509_EXTENSION *OCSP_crlID_new(const char *url, long *n, char *tim);
+
+X509_EXTENSION *OCSP_accept_responses_new(char **oids);
+
+X509_EXTENSION *OCSP_archive_cutoff_new(char *tim);
+
+X509_EXTENSION *OCSP_url_svcloc_new(const X509_NAME *issuer, const char **urls);
+
+int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x);
+int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos);
+int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, const ASN1_OBJECT *obj,
+ int lastpos);
+int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos);
+X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc);
+X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc);
+void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit,
+ int *idx);
+int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit,
+ unsigned long flags);
+int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc);
+
+int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x);
+int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos);
+int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, const ASN1_OBJECT *obj, int lastpos);
+int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos);
+X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc);
+X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc);
+void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx);
+int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit,
+ unsigned long flags);
+int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc);
+
+int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x);
+int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos);
+int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, const ASN1_OBJECT *obj,
+ int lastpos);
+int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit,
+ int lastpos);
+X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc);
+X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc);
+void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit,
+ int *idx);
+int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value,
+ int crit, unsigned long flags);
+int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc);
+
+int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x);
+int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos);
+int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, const ASN1_OBJECT *obj,
+ int lastpos);
+int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit,
+ int lastpos);
+X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc);
+X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc);
+void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit,
+ int *idx);
+int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value,
+ int crit, unsigned long flags);
+int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc);
+const OCSP_CERTID *OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *x);
+
+DECLARE_ASN1_FUNCTIONS(OCSP_SINGLERESP)
+DECLARE_ASN1_FUNCTIONS(OCSP_CERTSTATUS)
+DECLARE_ASN1_FUNCTIONS(OCSP_REVOKEDINFO)
+DECLARE_ASN1_FUNCTIONS(OCSP_BASICRESP)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPDATA)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPID)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPONSE)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPBYTES)
+DECLARE_ASN1_FUNCTIONS(OCSP_ONEREQ)
+DECLARE_ASN1_FUNCTIONS(OCSP_CERTID)
+DECLARE_ASN1_FUNCTIONS(OCSP_REQUEST)
+DECLARE_ASN1_FUNCTIONS(OCSP_SIGNATURE)
+DECLARE_ASN1_FUNCTIONS(OCSP_REQINFO)
+DECLARE_ASN1_FUNCTIONS(OCSP_CRLID)
+DECLARE_ASN1_FUNCTIONS(OCSP_SERVICELOC)
+
+const char *OCSP_response_status_str(long s);
+const char *OCSP_cert_status_str(long s);
+const char *OCSP_crl_reason_str(long s);
+
+int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST *a, unsigned long flags);
+int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE *o, unsigned long flags);
+
+int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
+ X509_STORE *st, unsigned long flags);
+
+
+# ifdef __cplusplus
+}
+# endif
+# endif /* !defined(OPENSSL_NO_OCSP) */
+#endif
diff --git a/include/openssl/ocsperr.h b/include/openssl/ocsperr.h
index 8dd9e01a172a..46a0523c2de4 100644
--- a/include/openssl/ocsperr.h
+++ b/include/openssl/ocsperr.h
@@ -1,57 +1,34 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_OCSPERR_H
-# define HEADER_OCSPERR_H
-
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+#ifndef OPENSSL_OCSPERR_H
+# define OPENSSL_OCSPERR_H
+# pragma once
# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifndef OPENSSL_NO_OCSP
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_OCSP_strings(void);
+# ifndef OPENSSL_NO_OCSP
-/*
- * OCSP function codes.
- */
-# define OCSP_F_D2I_OCSP_NONCE 102
-# define OCSP_F_OCSP_BASIC_ADD1_STATUS 103
-# define OCSP_F_OCSP_BASIC_SIGN 104
-# define OCSP_F_OCSP_BASIC_SIGN_CTX 119
-# define OCSP_F_OCSP_BASIC_VERIFY 105
-# define OCSP_F_OCSP_CERT_ID_NEW 101
-# define OCSP_F_OCSP_CHECK_DELEGATED 106
-# define OCSP_F_OCSP_CHECK_IDS 107
-# define OCSP_F_OCSP_CHECK_ISSUER 108
-# define OCSP_F_OCSP_CHECK_VALIDITY 115
-# define OCSP_F_OCSP_MATCH_ISSUERID 109
-# define OCSP_F_OCSP_PARSE_URL 114
-# define OCSP_F_OCSP_REQUEST_SIGN 110
-# define OCSP_F_OCSP_REQUEST_VERIFY 116
-# define OCSP_F_OCSP_RESPONSE_GET1_BASIC 111
-# define OCSP_F_PARSE_HTTP_LINE1 118
/*
* OCSP reason codes.
*/
# define OCSP_R_CERTIFICATE_VERIFY_ERROR 101
# define OCSP_R_DIGEST_ERR 102
+# define OCSP_R_DIGEST_NAME_ERR 106
+# define OCSP_R_DIGEST_SIZE_ERR 107
# define OCSP_R_ERROR_IN_NEXTUPDATE_FIELD 122
# define OCSP_R_ERROR_IN_THISUPDATE_FIELD 123
-# define OCSP_R_ERROR_PARSING_URL 121
# define OCSP_R_MISSING_OCSPSIGNING_USAGE 103
# define OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE 124
# define OCSP_R_NOT_BASIC_RESPONSE 104
@@ -63,8 +40,6 @@ int ERR_load_OCSP_strings(void);
# define OCSP_R_REQUEST_NOT_SIGNED 128
# define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA 111
# define OCSP_R_ROOT_CA_NOT_TRUSTED 112
-# define OCSP_R_SERVER_RESPONSE_ERROR 114
-# define OCSP_R_SERVER_RESPONSE_PARSE_ERROR 115
# define OCSP_R_SIGNATURE_FAILURE 117
# define OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND 118
# define OCSP_R_STATUS_EXPIRED 125
diff --git a/include/openssl/opensslconf.h b/include/openssl/opensslconf.h
new file mode 100644
index 000000000000..1e83371f1a43
--- /dev/null
+++ b/include/openssl/opensslconf.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_OPENSSLCONF_H
+# define OPENSSL_OPENSSLCONF_H
+# pragma once
+
+# include <openssl/configuration.h>
+# include <openssl/macros.h>
+
+#endif /* OPENSSL_OPENSSLCONF_H */
diff --git a/include/openssl/opensslconf.h.in b/include/openssl/opensslconf.h.in
deleted file mode 100644
index 06270922c2ac..000000000000
--- a/include/openssl/opensslconf.h.in
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * {- join("\n * ", @autowarntext) -}
- *
- * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <openssl/opensslv.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef OPENSSL_ALGORITHM_DEFINES
-# error OPENSSL_ALGORITHM_DEFINES no longer supported
-#endif
-
-/*
- * OpenSSL was configured with the following options:
- */
-
-{- if (@{$config{openssl_sys_defines}}) {
- foreach (@{$config{openssl_sys_defines}}) {
- $OUT .= "#ifndef $_\n";
- $OUT .= "# define $_ 1\n";
- $OUT .= "#endif\n";
- }
- }
- foreach (@{$config{openssl_api_defines}}) {
- (my $macro, my $value) = $_ =~ /^(.*?)=(.*?)$/;
- $OUT .= "#define $macro $value\n";
- }
- if (@{$config{openssl_algorithm_defines}}) {
- foreach (@{$config{openssl_algorithm_defines}}) {
- $OUT .= "#ifndef $_\n";
- $OUT .= "# define $_\n";
- $OUT .= "#endif\n";
- }
- }
- if (@{$config{openssl_thread_defines}}) {
- foreach (@{$config{openssl_thread_defines}}) {
- $OUT .= "#ifndef $_\n";
- $OUT .= "# define $_\n";
- $OUT .= "#endif\n";
- }
- }
- if (@{$config{openssl_other_defines}}) {
- foreach (@{$config{openssl_other_defines}}) {
- $OUT .= "#ifndef $_\n";
- $OUT .= "# define $_\n";
- $OUT .= "#endif\n";
- }
- }
- "";
--}
-
-/*
- * Sometimes OPENSSSL_NO_xxx ends up with an empty file and some compilers
- * don't like that. This will hopefully silence them.
- */
-#define NON_EMPTY_TRANSLATION_UNIT static void *dummy = &dummy;
-
-/*
- * Applications should use -DOPENSSL_API_COMPAT=<version> to suppress the
- * declarations of functions deprecated in or before <version>. Otherwise, they
- * still won't see them if the library has been built to disable deprecated
- * functions.
- */
-#ifndef DECLARE_DEPRECATED
-# define DECLARE_DEPRECATED(f) f;
-# ifdef __GNUC__
-# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0)
-# undef DECLARE_DEPRECATED
-# define DECLARE_DEPRECATED(f) f __attribute__ ((deprecated));
-# endif
-# elif defined(__SUNPRO_C)
-# if (__SUNPRO_C >= 0x5130)
-# undef DECLARE_DEPRECATED
-# define DECLARE_DEPRECATED(f) f __attribute__ ((deprecated));
-# endif
-# endif
-#endif
-
-#ifndef OPENSSL_FILE
-# ifdef OPENSSL_NO_FILENAMES
-# define OPENSSL_FILE ""
-# define OPENSSL_LINE 0
-# else
-# define OPENSSL_FILE __FILE__
-# define OPENSSL_LINE __LINE__
-# endif
-#endif
-
-#ifndef OPENSSL_MIN_API
-# define OPENSSL_MIN_API 0
-#endif
-
-#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < OPENSSL_MIN_API
-# undef OPENSSL_API_COMPAT
-# define OPENSSL_API_COMPAT OPENSSL_MIN_API
-#endif
-
-/*
- * Do not deprecate things to be deprecated in version 1.2.0 before the
- * OpenSSL version number matches.
- */
-#if OPENSSL_VERSION_NUMBER < 0x10200000L
-# define DEPRECATEDIN_1_2_0(f) f;
-#elif OPENSSL_API_COMPAT < 0x10200000L
-# define DEPRECATEDIN_1_2_0(f) DECLARE_DEPRECATED(f)
-#else
-# define DEPRECATEDIN_1_2_0(f)
-#endif
-
-#if OPENSSL_API_COMPAT < 0x10100000L
-# define DEPRECATEDIN_1_1_0(f) DECLARE_DEPRECATED(f)
-#else
-# define DEPRECATEDIN_1_1_0(f)
-#endif
-
-#if OPENSSL_API_COMPAT < 0x10000000L
-# define DEPRECATEDIN_1_0_0(f) DECLARE_DEPRECATED(f)
-#else
-# define DEPRECATEDIN_1_0_0(f)
-#endif
-
-#if OPENSSL_API_COMPAT < 0x00908000L
-# define DEPRECATEDIN_0_9_8(f) DECLARE_DEPRECATED(f)
-#else
-# define DEPRECATEDIN_0_9_8(f)
-#endif
-
-/* Generate 80386 code? */
-{- $config{processor} eq "386" ? "#define" : "#undef" -} I386_ONLY
-
-#undef OPENSSL_UNISTD
-#define OPENSSL_UNISTD {- $target{unistd} -}
-
-{- $config{export_var_as_fn} ? "#define" : "#undef" -} OPENSSL_EXPORT_VAR_AS_FUNCTION
-
-/*
- * The following are cipher-specific, but are part of the public API.
- */
-#if !defined(OPENSSL_SYS_UEFI)
-{- $config{bn_ll} ? "# define" : "# undef" -} BN_LLONG
-/* Only one for the following should be defined */
-{- $config{b64l} ? "# define" : "# undef" -} SIXTY_FOUR_BIT_LONG
-{- $config{b64} ? "# define" : "# undef" -} SIXTY_FOUR_BIT
-{- $config{b32} ? "# define" : "# undef" -} THIRTY_TWO_BIT
-#endif
-
-#define RC4_INT {- $config{rc4_int} -}
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/include/openssl/opensslv.h b/include/openssl/opensslv.h
deleted file mode 100644
index 7b6c212fa097..000000000000
--- a/include/openssl/opensslv.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_OPENSSLV_H
-# define HEADER_OPENSSLV_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*-
- * Numeric release version identifier:
- * MNNFFPPS: major minor fix patch status
- * The status nibble has one of the values 0 for development, 1 to e for betas
- * 1 to 14, and f for release. The patch level is exactly that.
- * For example:
- * 0.9.3-dev 0x00903000
- * 0.9.3-beta1 0x00903001
- * 0.9.3-beta2-dev 0x00903002
- * 0.9.3-beta2 0x00903002 (same as ...beta2-dev)
- * 0.9.3 0x0090300f
- * 0.9.3a 0x0090301f
- * 0.9.4 0x0090400f
- * 1.2.3z 0x102031af
- *
- * For continuity reasons (because 0.9.5 is already out, and is coded
- * 0x00905100), between 0.9.5 and 0.9.6 the coding of the patch level
- * part is slightly different, by setting the highest bit. This means
- * that 0.9.5a looks like this: 0x0090581f. At 0.9.6, we can start
- * with 0x0090600S...
- *
- * (Prior to 0.9.3-dev a different scheme was used: 0.9.2b is 0x0922.)
- * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
- * major minor fix final patch/beta)
- */
-# define OPENSSL_VERSION_NUMBER 0x1010114fL
-# define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1t 7 Feb 2023"
-
-/*-
- * The macros below are to be used for shared library (.so, .dll, ...)
- * versioning. That kind of versioning works a bit differently between
- * operating systems. The most usual scheme is to set a major and a minor
- * number, and have the runtime loader check that the major number is equal
- * to what it was at application link time, while the minor number has to
- * be greater or equal to what it was at application link time. With this
- * scheme, the version number is usually part of the file name, like this:
- *
- * libcrypto.so.0.9
- *
- * Some unixen also make a softlink with the major version number only:
- *
- * libcrypto.so.0
- *
- * On Tru64 and IRIX 6.x it works a little bit differently. There, the
- * shared library version is stored in the file, and is actually a series
- * of versions, separated by colons. The rightmost version present in the
- * library when linking an application is stored in the application to be
- * matched at run time. When the application is run, a check is done to
- * see if the library version stored in the application matches any of the
- * versions in the version string of the library itself.
- * This version string can be constructed in any way, depending on what
- * kind of matching is desired. However, to implement the same scheme as
- * the one used in the other unixen, all compatible versions, from lowest
- * to highest, should be part of the string. Consecutive builds would
- * give the following versions strings:
- *
- * 3.0
- * 3.0:3.1
- * 3.0:3.1:3.2
- * 4.0
- * 4.0:4.1
- *
- * Notice how version 4 is completely incompatible with version, and
- * therefore give the breach you can see.
- *
- * There may be other schemes as well that I haven't yet discovered.
- *
- * So, here's the way it works here: first of all, the library version
- * number doesn't need at all to match the overall OpenSSL version.
- * However, it's nice and more understandable if it actually does.
- * The current library version is stored in the macro SHLIB_VERSION_NUMBER,
- * which is just a piece of text in the format "M.m.e" (Major, minor, edit).
- * For the sake of Tru64, IRIX, and any other OS that behaves in similar ways,
- * we need to keep a history of version numbers, which is done in the
- * macro SHLIB_VERSION_HISTORY. The numbers are separated by colons and
- * should only keep the versions that are binary compatible with the current.
- */
-# define SHLIB_VERSION_HISTORY ""
-# define SHLIB_VERSION_NUMBER "1.1"
-
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* HEADER_OPENSSLV_H */
diff --git a/include/openssl/opensslv.h.in b/include/openssl/opensslv.h.in
new file mode 100644
index 000000000000..3f47a2ac08f0
--- /dev/null
+++ b/include/openssl/opensslv.h.in
@@ -0,0 +1,113 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_OPENSSLV_H
+# define OPENSSL_OPENSSLV_H
+# pragma once
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/*
+ * SECTION 1: VERSION DATA. These will change for each release
+ */
+
+/*
+ * Base version macros
+ *
+ * These macros express version number MAJOR.MINOR.PATCH exactly
+ */
+# define OPENSSL_VERSION_MAJOR {- $config{major} -}
+# define OPENSSL_VERSION_MINOR {- $config{minor} -}
+# define OPENSSL_VERSION_PATCH {- $config{patch} -}
+
+/*
+ * Additional version information
+ *
+ * These are also part of the new version scheme, but aren't part
+ * of the version number itself.
+ */
+
+/* Could be: #define OPENSSL_VERSION_PRE_RELEASE "-alpha.1" */
+# define OPENSSL_VERSION_PRE_RELEASE "{- $config{prerelease} -}"
+/* Could be: #define OPENSSL_VERSION_BUILD_METADATA "+fips" */
+/* Could be: #define OPENSSL_VERSION_BUILD_METADATA "+vendor.1" */
+# define OPENSSL_VERSION_BUILD_METADATA "{- $config{build_metadata} -}"
+
+/*
+ * Note: The OpenSSL Project will never define OPENSSL_VERSION_BUILD_METADATA
+ * to be anything but the empty string. Its use is entirely reserved for
+ * others
+ */
+
+/*
+ * Shared library version
+ *
+ * This is strictly to express ABI version, which may or may not
+ * be related to the API version expressed with the macros above.
+ * This is defined in free form.
+ */
+# define OPENSSL_SHLIB_VERSION {- $config{shlib_version} -}
+
+/*
+ * SECTION 2: USEFUL MACROS
+ */
+
+/* For checking general API compatibility when preprocessing */
+# define OPENSSL_VERSION_PREREQ(maj,min) \
+ ((OPENSSL_VERSION_MAJOR << 16) + OPENSSL_VERSION_MINOR >= ((maj) << 16) + (min))
+
+/*
+ * Macros to get the version in easily digested string form, both the short
+ * "MAJOR.MINOR.PATCH" variant (where MAJOR, MINOR and PATCH are replaced
+ * with the values from the corresponding OPENSSL_VERSION_ macros) and the
+ * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
+ * OPENSSL_VERSION_BUILD_METADATA_STR appended.
+ */
+# define OPENSSL_VERSION_STR "{- $config{version} -}"
+# define OPENSSL_FULL_VERSION_STR "{- $config{full_version} -}"
+
+/*
+ * SECTION 3: ADDITIONAL METADATA
+ *
+ * These strings are defined separately to allow them to be parsable.
+ */
+# define OPENSSL_RELEASE_DATE "{- $config{release_date} -}"
+
+/*
+ * SECTION 4: BACKWARD COMPATIBILITY
+ */
+
+# define OPENSSL_VERSION_TEXT "OpenSSL {- "$config{full_version} $config{release_date}" -}"
+
+/* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
+# ifdef OPENSSL_VERSION_PRE_RELEASE
+# define _OPENSSL_VERSION_PRE_RELEASE 0x0L
+# else
+# define _OPENSSL_VERSION_PRE_RELEASE 0xfL
+# endif
+# define OPENSSL_VERSION_NUMBER \
+ ( (OPENSSL_VERSION_MAJOR<<28) \
+ |(OPENSSL_VERSION_MINOR<<20) \
+ |(OPENSSL_VERSION_PATCH<<4) \
+ |_OPENSSL_VERSION_PRE_RELEASE )
+
+# ifdef __cplusplus
+}
+# endif
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_OPENSSLV_H
+# endif
+
+#endif /* OPENSSL_OPENSSLV_H */
diff --git a/include/openssl/ossl_typ.h b/include/openssl/ossl_typ.h
index e0edfaaf4760..82a58988ff2d 100644
--- a/include/openssl/ossl_typ.h
+++ b/include/openssl/ossl_typ.h
@@ -1,197 +1,16 @@
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_OPENSSL_TYPES_H
-# define HEADER_OPENSSL_TYPES_H
-
-#include <limits.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-# include <openssl/e_os2.h>
-
-# ifdef NO_ASN1_TYPEDEFS
-# define ASN1_INTEGER ASN1_STRING
-# define ASN1_ENUMERATED ASN1_STRING
-# define ASN1_BIT_STRING ASN1_STRING
-# define ASN1_OCTET_STRING ASN1_STRING
-# define ASN1_PRINTABLESTRING ASN1_STRING
-# define ASN1_T61STRING ASN1_STRING
-# define ASN1_IA5STRING ASN1_STRING
-# define ASN1_UTCTIME ASN1_STRING
-# define ASN1_GENERALIZEDTIME ASN1_STRING
-# define ASN1_TIME ASN1_STRING
-# define ASN1_GENERALSTRING ASN1_STRING
-# define ASN1_UNIVERSALSTRING ASN1_STRING
-# define ASN1_BMPSTRING ASN1_STRING
-# define ASN1_VISIBLESTRING ASN1_STRING
-# define ASN1_UTF8STRING ASN1_STRING
-# define ASN1_BOOLEAN int
-# define ASN1_NULL int
-# else
-typedef struct asn1_string_st ASN1_INTEGER;
-typedef struct asn1_string_st ASN1_ENUMERATED;
-typedef struct asn1_string_st ASN1_BIT_STRING;
-typedef struct asn1_string_st ASN1_OCTET_STRING;
-typedef struct asn1_string_st ASN1_PRINTABLESTRING;
-typedef struct asn1_string_st ASN1_T61STRING;
-typedef struct asn1_string_st ASN1_IA5STRING;
-typedef struct asn1_string_st ASN1_GENERALSTRING;
-typedef struct asn1_string_st ASN1_UNIVERSALSTRING;
-typedef struct asn1_string_st ASN1_BMPSTRING;
-typedef struct asn1_string_st ASN1_UTCTIME;
-typedef struct asn1_string_st ASN1_TIME;
-typedef struct asn1_string_st ASN1_GENERALIZEDTIME;
-typedef struct asn1_string_st ASN1_VISIBLESTRING;
-typedef struct asn1_string_st ASN1_UTF8STRING;
-typedef struct asn1_string_st ASN1_STRING;
-typedef int ASN1_BOOLEAN;
-typedef int ASN1_NULL;
-# endif
-
-typedef struct asn1_object_st ASN1_OBJECT;
-
-typedef struct ASN1_ITEM_st ASN1_ITEM;
-typedef struct asn1_pctx_st ASN1_PCTX;
-typedef struct asn1_sctx_st ASN1_SCTX;
-
-# ifdef _WIN32
-# undef X509_NAME
-# undef X509_EXTENSIONS
-# undef PKCS7_ISSUER_AND_SERIAL
-# undef PKCS7_SIGNER_INFO
-# undef OCSP_REQUEST
-# undef OCSP_RESPONSE
-# endif
-
-# ifdef BIGNUM
-# undef BIGNUM
-# endif
-struct dane_st;
-typedef struct bio_st BIO;
-typedef struct bignum_st BIGNUM;
-typedef struct bignum_ctx BN_CTX;
-typedef struct bn_blinding_st BN_BLINDING;
-typedef struct bn_mont_ctx_st BN_MONT_CTX;
-typedef struct bn_recp_ctx_st BN_RECP_CTX;
-typedef struct bn_gencb_st BN_GENCB;
-
-typedef struct buf_mem_st BUF_MEM;
-
-typedef struct evp_cipher_st EVP_CIPHER;
-typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;
-typedef struct evp_md_st EVP_MD;
-typedef struct evp_md_ctx_st EVP_MD_CTX;
-typedef struct evp_pkey_st EVP_PKEY;
-
-typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD;
-
-typedef struct evp_pkey_method_st EVP_PKEY_METHOD;
-typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
-
-typedef struct evp_Encode_Ctx_st EVP_ENCODE_CTX;
-
-typedef struct hmac_ctx_st HMAC_CTX;
-
-typedef struct dh_st DH;
-typedef struct dh_method DH_METHOD;
-
-typedef struct dsa_st DSA;
-typedef struct dsa_method DSA_METHOD;
-
-typedef struct rsa_st RSA;
-typedef struct rsa_meth_st RSA_METHOD;
-typedef struct rsa_pss_params_st RSA_PSS_PARAMS;
-
-typedef struct ec_key_st EC_KEY;
-typedef struct ec_key_method_st EC_KEY_METHOD;
-
-typedef struct rand_meth_st RAND_METHOD;
-typedef struct rand_drbg_st RAND_DRBG;
-
-typedef struct ssl_dane_st SSL_DANE;
-typedef struct x509_st X509;
-typedef struct X509_algor_st X509_ALGOR;
-typedef struct X509_crl_st X509_CRL;
-typedef struct x509_crl_method_st X509_CRL_METHOD;
-typedef struct x509_revoked_st X509_REVOKED;
-typedef struct X509_name_st X509_NAME;
-typedef struct X509_pubkey_st X509_PUBKEY;
-typedef struct x509_store_st X509_STORE;
-typedef struct x509_store_ctx_st X509_STORE_CTX;
-
-typedef struct x509_object_st X509_OBJECT;
-typedef struct x509_lookup_st X509_LOOKUP;
-typedef struct x509_lookup_method_st X509_LOOKUP_METHOD;
-typedef struct X509_VERIFY_PARAM_st X509_VERIFY_PARAM;
-
-typedef struct x509_sig_info_st X509_SIG_INFO;
-
-typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO;
-
-typedef struct v3_ext_ctx X509V3_CTX;
-typedef struct conf_st CONF;
-typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS;
-
-typedef struct ui_st UI;
-typedef struct ui_method_st UI_METHOD;
-
-typedef struct engine_st ENGINE;
-typedef struct ssl_st SSL;
-typedef struct ssl_ctx_st SSL_CTX;
-
-typedef struct comp_ctx_st COMP_CTX;
-typedef struct comp_method_st COMP_METHOD;
-
-typedef struct X509_POLICY_NODE_st X509_POLICY_NODE;
-typedef struct X509_POLICY_LEVEL_st X509_POLICY_LEVEL;
-typedef struct X509_POLICY_TREE_st X509_POLICY_TREE;
-typedef struct X509_POLICY_CACHE_st X509_POLICY_CACHE;
-
-typedef struct AUTHORITY_KEYID_st AUTHORITY_KEYID;
-typedef struct DIST_POINT_st DIST_POINT;
-typedef struct ISSUING_DIST_POINT_st ISSUING_DIST_POINT;
-typedef struct NAME_CONSTRAINTS_st NAME_CONSTRAINTS;
-
-typedef struct crypto_ex_data_st CRYPTO_EX_DATA;
-
-typedef struct ocsp_req_ctx_st OCSP_REQ_CTX;
-typedef struct ocsp_response_st OCSP_RESPONSE;
-typedef struct ocsp_responder_id_st OCSP_RESPID;
-
-typedef struct sct_st SCT;
-typedef struct sct_ctx_st SCT_CTX;
-typedef struct ctlog_st CTLOG;
-typedef struct ctlog_store_st CTLOG_STORE;
-typedef struct ct_policy_eval_ctx_st CT_POLICY_EVAL_CTX;
-
-typedef struct ossl_store_info_st OSSL_STORE_INFO;
-typedef struct ossl_store_search_st OSSL_STORE_SEARCH;
-
-#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
- defined(INTMAX_MAX) && defined(UINTMAX_MAX)
-typedef intmax_t ossl_intmax_t;
-typedef uintmax_t ossl_uintmax_t;
-#else
/*
- * Not long long, because the C-library can only be expected to provide
- * strtoll(), strtoull() at the same time as intmax_t and strtoimax(),
- * strtoumax(). Since we use these for parsing arguments, we need the
- * conversion functions, not just the sizes.
+ * The original <openssl/ossl_typ.h> was renamed to <openssl/types.h>
+ *
+ * This header file only exists for compatibility reasons with older
+ * applications which #include <openssl/ossl_typ.h>.
*/
-typedef long ossl_intmax_t;
-typedef unsigned long ossl_uintmax_t;
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* def HEADER_OPENSSL_TYPES_H */
+# include <openssl/types.h>
diff --git a/include/openssl/param_build.h b/include/openssl/param_build.h
new file mode 100644
index 000000000000..f29fdb2963d3
--- /dev/null
+++ b/include/openssl/param_build.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_PARAM_BUILD_H
+# define OPENSSL_PARAM_BUILD_H
+# pragma once
+
+# include <openssl/params.h>
+# include <openssl/types.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+OSSL_PARAM_BLD *OSSL_PARAM_BLD_new(void);
+OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld);
+void OSSL_PARAM_BLD_free(OSSL_PARAM_BLD *bld);
+
+int OSSL_PARAM_BLD_push_int(OSSL_PARAM_BLD *bld, const char *key, int val);
+int OSSL_PARAM_BLD_push_uint(OSSL_PARAM_BLD *bld, const char *key,
+ unsigned int val);
+int OSSL_PARAM_BLD_push_long(OSSL_PARAM_BLD *bld, const char *key,
+ long int val);
+int OSSL_PARAM_BLD_push_ulong(OSSL_PARAM_BLD *bld, const char *key,
+ unsigned long int val);
+int OSSL_PARAM_BLD_push_int32(OSSL_PARAM_BLD *bld, const char *key,
+ int32_t val);
+int OSSL_PARAM_BLD_push_uint32(OSSL_PARAM_BLD *bld, const char *key,
+ uint32_t val);
+int OSSL_PARAM_BLD_push_int64(OSSL_PARAM_BLD *bld, const char *key,
+ int64_t val);
+int OSSL_PARAM_BLD_push_uint64(OSSL_PARAM_BLD *bld, const char *key,
+ uint64_t val);
+int OSSL_PARAM_BLD_push_size_t(OSSL_PARAM_BLD *bld, const char *key,
+ size_t val);
+int OSSL_PARAM_BLD_push_time_t(OSSL_PARAM_BLD *bld, const char *key,
+ time_t val);
+int OSSL_PARAM_BLD_push_double(OSSL_PARAM_BLD *bld, const char *key,
+ double val);
+int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD *bld, const char *key,
+ const BIGNUM *bn);
+int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
+ const BIGNUM *bn, size_t sz);
+int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key,
+ const char *buf, size_t bsize);
+int OSSL_PARAM_BLD_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key,
+ char *buf, size_t bsize);
+int OSSL_PARAM_BLD_push_octet_string(OSSL_PARAM_BLD *bld, const char *key,
+ const void *buf, size_t bsize);
+int OSSL_PARAM_BLD_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key,
+ void *buf, size_t bsize);
+
+# ifdef __cplusplus
+}
+# endif
+#endif /* OPENSSL_PARAM_BUILD_H */
diff --git a/include/openssl/params.h b/include/openssl/params.h
new file mode 100644
index 000000000000..d75eab076490
--- /dev/null
+++ b/include/openssl/params.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_PARAMS_H
+# define OPENSSL_PARAMS_H
+# pragma once
+
+# include <openssl/core.h>
+# include <openssl/bn.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# define OSSL_PARAM_UNMODIFIED ((size_t)-1)
+
+# define OSSL_PARAM_END \
+ { NULL, 0, NULL, 0, 0 }
+
+# define OSSL_PARAM_DEFN(key, type, addr, sz) \
+ { (key), (type), (addr), (sz), OSSL_PARAM_UNMODIFIED }
+
+/* Basic parameter types without return sizes */
+# define OSSL_PARAM_int(key, addr) \
+ OSSL_PARAM_DEFN((key), OSSL_PARAM_INTEGER, (addr), sizeof(int))
+# define OSSL_PARAM_uint(key, addr) \
+ OSSL_PARAM_DEFN((key), OSSL_PARAM_UNSIGNED_INTEGER, (addr), \
+ sizeof(unsigned int))
+# define OSSL_PARAM_long(key, addr) \
+ OSSL_PARAM_DEFN((key), OSSL_PARAM_INTEGER, (addr), sizeof(long int))
+# define OSSL_PARAM_ulong(key, addr) \
+ OSSL_PARAM_DEFN((key), OSSL_PARAM_UNSIGNED_INTEGER, (addr), \
+ sizeof(unsigned long int))
+# define OSSL_PARAM_int32(key, addr) \
+ OSSL_PARAM_DEFN((key), OSSL_PARAM_INTEGER, (addr), sizeof(int32_t))
+# define OSSL_PARAM_uint32(key, addr) \
+ OSSL_PARAM_DEFN((key), OSSL_PARAM_UNSIGNED_INTEGER, (addr), \
+ sizeof(uint32_t))
+# define OSSL_PARAM_int64(key, addr) \
+ OSSL_PARAM_DEFN((key), OSSL_PARAM_INTEGER, (addr), sizeof(int64_t))
+# define OSSL_PARAM_uint64(key, addr) \
+ OSSL_PARAM_DEFN((key), OSSL_PARAM_UNSIGNED_INTEGER, (addr), \
+ sizeof(uint64_t))
+# define OSSL_PARAM_size_t(key, addr) \
+ OSSL_PARAM_DEFN((key), OSSL_PARAM_UNSIGNED_INTEGER, (addr), sizeof(size_t))
+# define OSSL_PARAM_time_t(key, addr) \
+ OSSL_PARAM_DEFN((key), OSSL_PARAM_INTEGER, (addr), sizeof(time_t))
+# define OSSL_PARAM_double(key, addr) \
+ OSSL_PARAM_DEFN((key), OSSL_PARAM_REAL, (addr), sizeof(double))
+
+# define OSSL_PARAM_BN(key, bn, sz) \
+ OSSL_PARAM_DEFN((key), OSSL_PARAM_UNSIGNED_INTEGER, (bn), (sz))
+# define OSSL_PARAM_utf8_string(key, addr, sz) \
+ OSSL_PARAM_DEFN((key), OSSL_PARAM_UTF8_STRING, (addr), sz)
+# define OSSL_PARAM_octet_string(key, addr, sz) \
+ OSSL_PARAM_DEFN((key), OSSL_PARAM_OCTET_STRING, (addr), sz)
+
+# define OSSL_PARAM_utf8_ptr(key, addr, sz) \
+ OSSL_PARAM_DEFN((key), OSSL_PARAM_UTF8_PTR, (addr), sz)
+# define OSSL_PARAM_octet_ptr(key, addr, sz) \
+ OSSL_PARAM_DEFN((key), OSSL_PARAM_OCTET_PTR, (addr), sz)
+
+/* Search an OSSL_PARAM array for a matching name */
+OSSL_PARAM *OSSL_PARAM_locate(OSSL_PARAM *p, const char *key);
+const OSSL_PARAM *OSSL_PARAM_locate_const(const OSSL_PARAM *p, const char *key);
+
+/* Basic parameter type run-time construction */
+OSSL_PARAM OSSL_PARAM_construct_int(const char *key, int *buf);
+OSSL_PARAM OSSL_PARAM_construct_uint(const char *key, unsigned int *buf);
+OSSL_PARAM OSSL_PARAM_construct_long(const char *key, long int *buf);
+OSSL_PARAM OSSL_PARAM_construct_ulong(const char *key, unsigned long int *buf);
+OSSL_PARAM OSSL_PARAM_construct_int32(const char *key, int32_t *buf);
+OSSL_PARAM OSSL_PARAM_construct_uint32(const char *key, uint32_t *buf);
+OSSL_PARAM OSSL_PARAM_construct_int64(const char *key, int64_t *buf);
+OSSL_PARAM OSSL_PARAM_construct_uint64(const char *key, uint64_t *buf);
+OSSL_PARAM OSSL_PARAM_construct_size_t(const char *key, size_t *buf);
+OSSL_PARAM OSSL_PARAM_construct_time_t(const char *key, time_t *buf);
+OSSL_PARAM OSSL_PARAM_construct_BN(const char *key, unsigned char *buf,
+ size_t bsize);
+OSSL_PARAM OSSL_PARAM_construct_double(const char *key, double *buf);
+OSSL_PARAM OSSL_PARAM_construct_utf8_string(const char *key, char *buf,
+ size_t bsize);
+OSSL_PARAM OSSL_PARAM_construct_utf8_ptr(const char *key, char **buf,
+ size_t bsize);
+OSSL_PARAM OSSL_PARAM_construct_octet_string(const char *key, void *buf,
+ size_t bsize);
+OSSL_PARAM OSSL_PARAM_construct_octet_ptr(const char *key, void **buf,
+ size_t bsize);
+OSSL_PARAM OSSL_PARAM_construct_end(void);
+
+int OSSL_PARAM_allocate_from_text(OSSL_PARAM *to,
+ const OSSL_PARAM *paramdefs,
+ const char *key, const char *value,
+ size_t value_n, int *found);
+
+int OSSL_PARAM_get_int(const OSSL_PARAM *p, int *val);
+int OSSL_PARAM_get_uint(const OSSL_PARAM *p, unsigned int *val);
+int OSSL_PARAM_get_long(const OSSL_PARAM *p, long int *val);
+int OSSL_PARAM_get_ulong(const OSSL_PARAM *p, unsigned long int *val);
+int OSSL_PARAM_get_int32(const OSSL_PARAM *p, int32_t *val);
+int OSSL_PARAM_get_uint32(const OSSL_PARAM *p, uint32_t *val);
+int OSSL_PARAM_get_int64(const OSSL_PARAM *p, int64_t *val);
+int OSSL_PARAM_get_uint64(const OSSL_PARAM *p, uint64_t *val);
+int OSSL_PARAM_get_size_t(const OSSL_PARAM *p, size_t *val);
+int OSSL_PARAM_get_time_t(const OSSL_PARAM *p, time_t *val);
+
+int OSSL_PARAM_set_int(OSSL_PARAM *p, int val);
+int OSSL_PARAM_set_uint(OSSL_PARAM *p, unsigned int val);
+int OSSL_PARAM_set_long(OSSL_PARAM *p, long int val);
+int OSSL_PARAM_set_ulong(OSSL_PARAM *p, unsigned long int val);
+int OSSL_PARAM_set_int32(OSSL_PARAM *p, int32_t val);
+int OSSL_PARAM_set_uint32(OSSL_PARAM *p, uint32_t val);
+int OSSL_PARAM_set_int64(OSSL_PARAM *p, int64_t val);
+int OSSL_PARAM_set_uint64(OSSL_PARAM *p, uint64_t val);
+int OSSL_PARAM_set_size_t(OSSL_PARAM *p, size_t val);
+int OSSL_PARAM_set_time_t(OSSL_PARAM *p, time_t val);
+
+int OSSL_PARAM_get_double(const OSSL_PARAM *p, double *val);
+int OSSL_PARAM_set_double(OSSL_PARAM *p, double val);
+
+int OSSL_PARAM_get_BN(const OSSL_PARAM *p, BIGNUM **val);
+int OSSL_PARAM_set_BN(OSSL_PARAM *p, const BIGNUM *val);
+
+int OSSL_PARAM_get_utf8_string(const OSSL_PARAM *p, char **val, size_t max_len);
+int OSSL_PARAM_set_utf8_string(OSSL_PARAM *p, const char *val);
+
+int OSSL_PARAM_get_octet_string(const OSSL_PARAM *p, void **val, size_t max_len,
+ size_t *used_len);
+int OSSL_PARAM_set_octet_string(OSSL_PARAM *p, const void *val, size_t len);
+
+int OSSL_PARAM_get_utf8_ptr(const OSSL_PARAM *p, const char **val);
+int OSSL_PARAM_set_utf8_ptr(OSSL_PARAM *p, const char *val);
+
+int OSSL_PARAM_get_octet_ptr(const OSSL_PARAM *p, const void **val,
+ size_t *used_len);
+int OSSL_PARAM_set_octet_ptr(OSSL_PARAM *p, const void *val,
+ size_t used_len);
+
+int OSSL_PARAM_get_utf8_string_ptr(const OSSL_PARAM *p, const char **val);
+int OSSL_PARAM_get_octet_string_ptr(const OSSL_PARAM *p, const void **val,
+ size_t *used_len);
+
+int OSSL_PARAM_modified(const OSSL_PARAM *p);
+void OSSL_PARAM_set_all_unmodified(OSSL_PARAM *p);
+
+OSSL_PARAM *OSSL_PARAM_dup(const OSSL_PARAM *p);
+OSSL_PARAM *OSSL_PARAM_merge(const OSSL_PARAM *p1, const OSSL_PARAM *p2);
+void OSSL_PARAM_free(OSSL_PARAM *p);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/pem.h b/include/openssl/pem.h
index 2ef5b5d04c6e..80940dfa969b 100644
--- a/include/openssl/pem.h
+++ b/include/openssl/pem.h
@@ -1,14 +1,20 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_PEM_H
-# define HEADER_PEM_H
+#ifndef OPENSSL_PEM_H
+# define OPENSSL_PEM_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_PEM_H
+# endif
# include <openssl/e_os2.h>
# include <openssl/bio.h>
@@ -60,98 +66,130 @@ extern "C" {
* IMPLEMENT_PEM_rw_cb(...)
*/
+# define PEM_read_cb_fnsig(name, type, INTYPE, readname) \
+ type *PEM_##readname##_##name(INTYPE *out, type **x, \
+ pem_password_cb *cb, void *u)
+# define PEM_read_cb_ex_fnsig(name, type, INTYPE, readname) \
+ type *PEM_##readname##_##name##_ex(INTYPE *out, type **x, \
+ pem_password_cb *cb, void *u, \
+ OSSL_LIB_CTX *libctx, \
+ const char *propq)
+
+# define PEM_write_fnsig(name, type, OUTTYPE, writename) \
+ int PEM_##writename##_##name(OUTTYPE *out, const type *x)
+# define PEM_write_cb_fnsig(name, type, OUTTYPE, writename) \
+ int PEM_##writename##_##name(OUTTYPE *out, const type *x, \
+ const EVP_CIPHER *enc, \
+ const unsigned char *kstr, int klen, \
+ pem_password_cb *cb, void *u)
+# define PEM_write_ex_fnsig(name, type, OUTTYPE, writename) \
+ int PEM_##writename##_##name##_ex(OUTTYPE *out, const type *x, \
+ OSSL_LIB_CTX *libctx, \
+ const char *propq)
+# define PEM_write_cb_ex_fnsig(name, type, OUTTYPE, writename) \
+ int PEM_##writename##_##name##_ex(OUTTYPE *out, const type *x, \
+ const EVP_CIPHER *enc, \
+ const unsigned char *kstr, int klen, \
+ pem_password_cb *cb, void *u, \
+ OSSL_LIB_CTX *libctx, \
+ const char *propq)
+
# ifdef OPENSSL_NO_STDIO
# define IMPLEMENT_PEM_read_fp(name, type, str, asn1) /**/
# define IMPLEMENT_PEM_write_fp(name, type, str, asn1) /**/
-# define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) /**/
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) /**/
+# endif
# define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) /**/
-# define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) /**/
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) /**/
+# endif
# else
-# define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \
-type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u)\
-{ \
-return PEM_ASN1_read((d2i_of_void *)d2i_##asn1, str,fp,(void **)x,cb,u); \
-}
-
-# define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \
-int PEM_write_##name(FILE *fp, type *x) \
-{ \
-return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,NULL,NULL,0,NULL,NULL); \
-}
-
-# define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) \
-int PEM_write_##name(FILE *fp, const type *x) \
-{ \
-return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,(void *)x,NULL,NULL,0,NULL,NULL); \
-}
+# define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \
+ type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u) \
+ { \
+ return PEM_ASN1_read((d2i_of_void *)d2i_##asn1, str, fp, \
+ (void **)x, cb, u); \
+ }
+
+# define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \
+ PEM_write_fnsig(name, type, FILE, write) \
+ { \
+ return PEM_ASN1_write((i2d_of_void *)i2d_##asn1, str, out, \
+ x, NULL, NULL, 0, NULL, NULL); \
+ }
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_fp(name, type, str, asn1)
+# endif
-# define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \
-int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
- unsigned char *kstr, int klen, pem_password_cb *cb, \
- void *u) \
- { \
- return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u); \
- }
-
-# define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) \
-int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
- unsigned char *kstr, int klen, pem_password_cb *cb, \
- void *u) \
- { \
- return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u); \
- }
+# define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \
+ PEM_write_cb_fnsig(name, type, FILE, write) \
+ { \
+ return PEM_ASN1_write((i2d_of_void *)i2d_##asn1, str, out, \
+ x, enc, kstr, klen, cb, u); \
+ }
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1)
+# endif
# endif
-# define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
-type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u)\
-{ \
-return PEM_ASN1_read_bio((d2i_of_void *)d2i_##asn1, str,bp,(void **)x,cb,u); \
-}
-
-# define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
-int PEM_write_bio_##name(BIO *bp, type *x) \
-{ \
-return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,x,NULL,NULL,0,NULL,NULL); \
-}
-
-# define IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \
-int PEM_write_bio_##name(BIO *bp, const type *x) \
-{ \
-return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(void *)x,NULL,NULL,0,NULL,NULL); \
-}
+# define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
+ type *PEM_read_bio_##name(BIO *bp, type **x, \
+ pem_password_cb *cb, void *u) \
+ { \
+ return PEM_ASN1_read_bio((d2i_of_void *)d2i_##asn1, str, bp, \
+ (void **)x, cb, u); \
+ }
+
+# define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
+ PEM_write_fnsig(name, type, BIO, write_bio) \
+ { \
+ return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1, str, out, \
+ x, NULL,NULL,0,NULL,NULL); \
+ }
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_bio(name, type, str, asn1)
+# endif
-# define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \
-int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
- unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \
- { \
- return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,x,enc,kstr,klen,cb,u); \
- }
+# define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \
+ PEM_write_cb_fnsig(name, type, BIO, write_bio) \
+ { \
+ return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1, str, out, \
+ x, enc, kstr, klen, cb, u); \
+ }
-# define IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \
-int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
- unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \
- { \
- return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(void *)x,enc,kstr,klen,cb,u); \
- }
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1)
+# endif
# define IMPLEMENT_PEM_write(name, type, str, asn1) \
IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
IMPLEMENT_PEM_write_fp(name, type, str, asn1)
-# define IMPLEMENT_PEM_write_const(name, type, str, asn1) \
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define IMPLEMENT_PEM_write_const(name, type, str, asn1) \
IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \
IMPLEMENT_PEM_write_fp_const(name, type, str, asn1)
+# endif
# define IMPLEMENT_PEM_write_cb(name, type, str, asn1) \
IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \
IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1)
-# define IMPLEMENT_PEM_write_cb_const(name, type, str, asn1) \
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define IMPLEMENT_PEM_write_cb_const(name, type, str, asn1) \
IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \
IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1)
+# endif
# define IMPLEMENT_PEM_read(name, type, str, asn1) \
IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
@@ -161,9 +199,11 @@ int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
IMPLEMENT_PEM_read(name, type, str, asn1) \
IMPLEMENT_PEM_write(name, type, str, asn1)
-# define IMPLEMENT_PEM_rw_const(name, type, str, asn1) \
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define IMPLEMENT_PEM_rw_const(name, type, str, asn1) \
IMPLEMENT_PEM_read(name, type, str, asn1) \
IMPLEMENT_PEM_write_const(name, type, str, asn1)
+# endif
# define IMPLEMENT_PEM_rw_cb(name, type, str, asn1) \
IMPLEMENT_PEM_read(name, type, str, asn1) \
@@ -171,64 +211,160 @@ int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
/* These are the same except they are for the declarations */
+/*
+ * The mysterious 'extern' that's passed to some macros is innocuous,
+ * and is there to quiet pre-C99 compilers that may complain about empty
+ * arguments in macro calls.
+ */
# if defined(OPENSSL_NO_STDIO)
-# define DECLARE_PEM_read_fp(name, type) /**/
-# define DECLARE_PEM_write_fp(name, type) /**/
-# define DECLARE_PEM_write_fp_const(name, type) /**/
-# define DECLARE_PEM_write_cb_fp(name, type) /**/
-# else
-
-# define DECLARE_PEM_read_fp(name, type) \
- type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u);
-
-# define DECLARE_PEM_write_fp(name, type) \
- int PEM_write_##name(FILE *fp, type *x);
+# define DECLARE_PEM_read_fp_attr(attr, name, type) /**/
+# define DECLARE_PEM_read_fp_ex_attr(attr, name, type) /**/
+# define DECLARE_PEM_write_fp_attr(attr, name, type) /**/
+# define DECLARE_PEM_write_fp_ex_attr(attr, name, type) /**/
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define DECLARE_PEM_write_fp_const_attr(attr, name, type) /**/
+# endif
+# define DECLARE_PEM_write_cb_fp_attr(attr, name, type) /**/
+# define DECLARE_PEM_write_cb_fp_ex_attr(attr, name, type) /**/
-# define DECLARE_PEM_write_fp_const(name, type) \
- int PEM_write_##name(FILE *fp, const type *x);
+# else
-# define DECLARE_PEM_write_cb_fp(name, type) \
- int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
- unsigned char *kstr, int klen, pem_password_cb *cb, void *u);
+# define DECLARE_PEM_read_fp_attr(attr, name, type) \
+ attr PEM_read_cb_fnsig(name, type, FILE, read);
+# define DECLARE_PEM_read_fp_ex_attr(attr, name, type) \
+ attr PEM_read_cb_fnsig(name, type, FILE, read); \
+ attr PEM_read_cb_ex_fnsig(name, type, FILE, read);
+
+# define DECLARE_PEM_write_fp_attr(attr, name, type) \
+ attr PEM_write_fnsig(name, type, FILE, write);
+# define DECLARE_PEM_write_fp_ex_attr(attr, name, type) \
+ attr PEM_write_fnsig(name, type, FILE, write); \
+ attr PEM_write_ex_fnsig(name, type, FILE, write);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define DECLARE_PEM_write_fp_const_attr(attr, name, type) \
+ attr PEM_write_fnsig(name, type, FILE, write);
+# endif
+# define DECLARE_PEM_write_cb_fp_attr(attr, name, type) \
+ attr PEM_write_cb_fnsig(name, type, FILE, write);
+# define DECLARE_PEM_write_cb_fp_ex_attr(attr, name, type) \
+ attr PEM_write_cb_fnsig(name, type, FILE, write); \
+ attr PEM_write_cb_ex_fnsig(name, type, FILE, write);
# endif
-# define DECLARE_PEM_read_bio(name, type) \
- type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u);
-
-# define DECLARE_PEM_write_bio(name, type) \
- int PEM_write_bio_##name(BIO *bp, type *x);
-
-# define DECLARE_PEM_write_bio_const(name, type) \
- int PEM_write_bio_##name(BIO *bp, const type *x);
-
-# define DECLARE_PEM_write_cb_bio(name, type) \
- int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
- unsigned char *kstr, int klen, pem_password_cb *cb, void *u);
+# define DECLARE_PEM_read_fp(name, type) \
+ DECLARE_PEM_read_fp_attr(extern, name, type)
+# define DECLARE_PEM_write_fp(name, type) \
+ DECLARE_PEM_write_fp_attr(extern, name, type)
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define DECLARE_PEM_write_fp_const(name, type) \
+ DECLARE_PEM_write_fp_const_attr(extern, name, type)
+# endif
+# define DECLARE_PEM_write_cb_fp(name, type) \
+ DECLARE_PEM_write_cb_fp_attr(extern, name, type)
+
+# define DECLARE_PEM_read_bio_attr(attr, name, type) \
+ attr PEM_read_cb_fnsig(name, type, BIO, read_bio);
+# define DECLARE_PEM_read_bio_ex_attr(attr, name, type) \
+ attr PEM_read_cb_fnsig(name, type, BIO, read_bio); \
+ attr PEM_read_cb_ex_fnsig(name, type, BIO, read_bio);
+# define DECLARE_PEM_read_bio(name, type) \
+ DECLARE_PEM_read_bio_attr(extern, name, type)
+# define DECLARE_PEM_read_bio_ex(name, type) \
+ DECLARE_PEM_read_bio_ex_attr(extern, name, type)
+
+# define DECLARE_PEM_write_bio_attr(attr, name, type) \
+ attr PEM_write_fnsig(name, type, BIO, write_bio);
+# define DECLARE_PEM_write_bio_ex_attr(attr, name, type) \
+ attr PEM_write_fnsig(name, type, BIO, write_bio); \
+ attr PEM_write_ex_fnsig(name, type, BIO, write_bio);
+# define DECLARE_PEM_write_bio(name, type) \
+ DECLARE_PEM_write_bio_attr(extern, name, type)
+# define DECLARE_PEM_write_bio_ex(name, type) \
+ DECLARE_PEM_write_bio_ex_attr(extern, name, type)
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define DECLARE_PEM_write_bio_const_attr(attr, name, type) \
+ attr PEM_write_fnsig(name, type, BIO, write_bio);
+# define DECLARE_PEM_write_bio_const(name, type) \
+ DECLARE_PEM_write_bio_const_attr(extern, name, type)
+# endif
+# define DECLARE_PEM_write_cb_bio_attr(attr, name, type) \
+ attr PEM_write_cb_fnsig(name, type, BIO, write_bio);
+# define DECLARE_PEM_write_cb_bio_ex_attr(attr, name, type) \
+ attr PEM_write_cb_fnsig(name, type, BIO, write_bio); \
+ attr PEM_write_cb_ex_fnsig(name, type, BIO, write_bio);
+# define DECLARE_PEM_write_cb_bio(name, type) \
+ DECLARE_PEM_write_cb_bio_attr(extern, name, type)
+# define DECLARE_PEM_write_cb_ex_bio(name, type) \
+ DECLARE_PEM_write_cb_bio_ex_attr(extern, name, type)
+
+# define DECLARE_PEM_write_attr(attr, name, type) \
+ DECLARE_PEM_write_bio_attr(attr, name, type) \
+ DECLARE_PEM_write_fp_attr(attr, name, type)
+# define DECLARE_PEM_write_ex_attr(attr, name, type) \
+ DECLARE_PEM_write_bio_ex_attr(attr, name, type) \
+ DECLARE_PEM_write_fp_ex_attr(attr, name, type)
# define DECLARE_PEM_write(name, type) \
- DECLARE_PEM_write_bio(name, type) \
- DECLARE_PEM_write_fp(name, type)
-# define DECLARE_PEM_write_const(name, type) \
- DECLARE_PEM_write_bio_const(name, type) \
- DECLARE_PEM_write_fp_const(name, type)
-# define DECLARE_PEM_write_cb(name, type) \
- DECLARE_PEM_write_cb_bio(name, type) \
- DECLARE_PEM_write_cb_fp(name, type)
-# define DECLARE_PEM_read(name, type) \
- DECLARE_PEM_read_bio(name, type) \
- DECLARE_PEM_read_fp(name, type)
+ DECLARE_PEM_write_attr(extern, name, type)
+# define DECLARE_PEM_write_ex(name, type) \
+ DECLARE_PEM_write_ex_attr(extern, name, type)
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define DECLARE_PEM_write_const_attr(attr, name, type) \
+ DECLARE_PEM_write_bio_const_attr(attr, name, type) \
+ DECLARE_PEM_write_fp_const_attr(attr, name, type)
+# define DECLARE_PEM_write_const(name, type) \
+ DECLARE_PEM_write_const_attr(extern, name, type)
+# endif
+# define DECLARE_PEM_write_cb_attr(attr, name, type) \
+ DECLARE_PEM_write_cb_bio_attr(attr, name, type) \
+ DECLARE_PEM_write_cb_fp_attr(attr, name, type)
+# define DECLARE_PEM_write_cb_ex_attr(attr, name, type) \
+ DECLARE_PEM_write_cb_bio_ex_attr(attr, name, type) \
+ DECLARE_PEM_write_cb_fp_ex_attr(attr, name, type)
+# define DECLARE_PEM_write_cb(name, type) \
+ DECLARE_PEM_write_cb_attr(extern, name, type)
+# define DECLARE_PEM_write_cb_ex(name, type) \
+ DECLARE_PEM_write_cb_ex_attr(extern, name, type)
+# define DECLARE_PEM_read_attr(attr, name, type) \
+ DECLARE_PEM_read_bio_attr(attr, name, type) \
+ DECLARE_PEM_read_fp_attr(attr, name, type)
+# define DECLARE_PEM_read_ex_attr(attr, name, type) \
+ DECLARE_PEM_read_bio_ex_attr(attr, name, type) \
+ DECLARE_PEM_read_fp_ex_attr(attr, name, type)
+# define DECLARE_PEM_read(name, type) \
+ DECLARE_PEM_read_attr(extern, name, type)
+# define DECLARE_PEM_read_ex(name, type) \
+ DECLARE_PEM_read_ex_attr(extern, name, type)
+# define DECLARE_PEM_rw_attr(attr, name, type) \
+ DECLARE_PEM_read_attr(attr, name, type) \
+ DECLARE_PEM_write_attr(attr, name, type)
+# define DECLARE_PEM_rw_ex_attr(attr, name, type) \
+ DECLARE_PEM_read_ex_attr(attr, name, type) \
+ DECLARE_PEM_write_ex_attr(attr, name, type)
# define DECLARE_PEM_rw(name, type) \
- DECLARE_PEM_read(name, type) \
- DECLARE_PEM_write(name, type)
-# define DECLARE_PEM_rw_const(name, type) \
- DECLARE_PEM_read(name, type) \
- DECLARE_PEM_write_const(name, type)
+ DECLARE_PEM_rw_attr(extern, name, type)
+# define DECLARE_PEM_rw_ex(name, type) \
+ DECLARE_PEM_rw_ex_attr(extern, name, type)
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define DECLARE_PEM_rw_const_attr(attr, name, type) \
+ DECLARE_PEM_read_attr(attr, name, type) \
+ DECLARE_PEM_write_const_attr(attr, name, type)
+# define DECLARE_PEM_rw_const(name, type) \
+ DECLARE_PEM_rw_const_attr(extern, name, type)
+# endif
+# define DECLARE_PEM_rw_cb_attr(attr, name, type) \
+ DECLARE_PEM_read_attr(attr, name, type) \
+ DECLARE_PEM_write_cb_attr(attr, name, type)
+# define DECLARE_PEM_rw_cb_ex_attr(attr, name, type) \
+ DECLARE_PEM_read_ex_attr(attr, name, type) \
+ DECLARE_PEM_write_cb_ex_attr(attr, name, type)
# define DECLARE_PEM_rw_cb(name, type) \
- DECLARE_PEM_read(name, type) \
- DECLARE_PEM_write_cb(name, type)
-typedef int pem_password_cb (char *buf, int size, int rwflag, void *userdata);
+ DECLARE_PEM_rw_cb_attr(extern, name, type)
+# define DECLARE_PEM_rw_cb_ex(name, type) \
+ DECLARE_PEM_rw_cb_ex_attr(extern, name, type)
int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher);
int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *len,
@@ -251,14 +387,20 @@ int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm,
void *u);
void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x,
pem_password_cb *cb, void *u);
-int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, void *x,
- const EVP_CIPHER *enc, unsigned char *kstr, int klen,
+int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
+ const void *x, const EVP_CIPHER *enc,
+ const unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
pem_password_cb *cb, void *u);
-int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
- unsigned char *kstr, int klen,
+STACK_OF(X509_INFO)
+*PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk,
+ pem_password_cb *cb, void *u, OSSL_LIB_CTX *libctx,
+ const char *propq);
+
+int PEM_X509_INFO_write_bio(BIO *bp, const X509_INFO *xi, EVP_CIPHER *enc,
+ const unsigned char *kstr, int klen,
pem_password_cb *cd, void *u);
#ifndef OPENSSL_NO_STDIO
@@ -269,21 +411,25 @@ int PEM_write(FILE *fp, const char *name, const char *hdr,
void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x,
pem_password_cb *cb, void *u);
int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp,
- void *x, const EVP_CIPHER *enc, unsigned char *kstr,
- int klen, pem_password_cb *callback, void *u);
+ const void *x, const EVP_CIPHER *enc,
+ const unsigned char *kstr, int klen,
+ pem_password_cb *callback, void *u);
STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
pem_password_cb *cb, void *u);
+STACK_OF(X509_INFO)
+*PEM_X509_INFO_read_ex(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb,
+ void *u, OSSL_LIB_CTX *libctx, const char *propq);
#endif
int PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type);
-int PEM_SignUpdate(EVP_MD_CTX *ctx, unsigned char *d, unsigned int cnt);
+int PEM_SignUpdate(EVP_MD_CTX *ctx, const unsigned char *d, unsigned int cnt);
int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
unsigned int *siglen, EVP_PKEY *pkey);
/* The default pem_password_cb that's used internally */
int PEM_def_callback(char *buf, int num, int rwflag, void *userdata);
void PEM_proc_type(char *buf, int type);
-void PEM_dek_info(char *buf, const char *type, int len, char *str);
+void PEM_dek_info(char *buf, const char *type, int len, const char *str);
# include <openssl/symhacks.h>
@@ -292,85 +438,99 @@ DECLARE_PEM_rw(X509_AUX, X509)
DECLARE_PEM_rw(X509_REQ, X509_REQ)
DECLARE_PEM_write(X509_REQ_NEW, X509_REQ)
DECLARE_PEM_rw(X509_CRL, X509_CRL)
+DECLARE_PEM_rw(X509_PUBKEY, X509_PUBKEY)
DECLARE_PEM_rw(PKCS7, PKCS7)
DECLARE_PEM_rw(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE)
DECLARE_PEM_rw(PKCS8, X509_SIG)
DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
-# ifndef OPENSSL_NO_RSA
-DECLARE_PEM_rw_cb(RSAPrivateKey, RSA)
-DECLARE_PEM_rw_const(RSAPublicKey, RSA)
-DECLARE_PEM_rw(RSA_PUBKEY, RSA)
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+DECLARE_PEM_rw_cb_attr(OSSL_DEPRECATEDIN_3_0, RSAPrivateKey, RSA)
+DECLARE_PEM_rw_attr(OSSL_DEPRECATEDIN_3_0, RSAPublicKey, RSA)
+DECLARE_PEM_rw_attr(OSSL_DEPRECATEDIN_3_0, RSA_PUBKEY, RSA)
# endif
-# ifndef OPENSSL_NO_DSA
-DECLARE_PEM_rw_cb(DSAPrivateKey, DSA)
-DECLARE_PEM_rw(DSA_PUBKEY, DSA)
-DECLARE_PEM_rw_const(DSAparams, DSA)
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef OPENSSL_NO_DSA
+DECLARE_PEM_rw_cb_attr(OSSL_DEPRECATEDIN_3_0, DSAPrivateKey, DSA)
+DECLARE_PEM_rw_attr(OSSL_DEPRECATEDIN_3_0, DSA_PUBKEY, DSA)
+DECLARE_PEM_rw_attr(OSSL_DEPRECATEDIN_3_0, DSAparams, DSA)
+# endif
# endif
-# ifndef OPENSSL_NO_EC
-DECLARE_PEM_rw_const(ECPKParameters, EC_GROUP)
-DECLARE_PEM_rw_cb(ECPrivateKey, EC_KEY)
-DECLARE_PEM_rw(EC_PUBKEY, EC_KEY)
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef OPENSSL_NO_EC
+DECLARE_PEM_rw_attr(OSSL_DEPRECATEDIN_3_0, ECPKParameters, EC_GROUP)
+DECLARE_PEM_rw_cb_attr(OSSL_DEPRECATEDIN_3_0, ECPrivateKey, EC_KEY)
+DECLARE_PEM_rw_attr(OSSL_DEPRECATEDIN_3_0, EC_PUBKEY, EC_KEY)
+# endif
# endif
+
# ifndef OPENSSL_NO_DH
-DECLARE_PEM_rw_const(DHparams, DH)
-DECLARE_PEM_write_const(DHxparams, DH)
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+DECLARE_PEM_rw_attr(OSSL_DEPRECATEDIN_3_0, DHparams, DH)
+DECLARE_PEM_write_attr(OSSL_DEPRECATEDIN_3_0, DHxparams, DH)
+# endif
# endif
-DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY)
-DECLARE_PEM_rw(PUBKEY, EVP_PKEY)
+DECLARE_PEM_rw_cb_ex(PrivateKey, EVP_PKEY)
+DECLARE_PEM_rw_ex(PUBKEY, EVP_PKEY)
-int PEM_write_bio_PrivateKey_traditional(BIO *bp, EVP_PKEY *x,
+int PEM_write_bio_PrivateKey_traditional(BIO *bp, const EVP_PKEY *x,
const EVP_CIPHER *enc,
- unsigned char *kstr, int klen,
+ const unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
-int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid,
- char *kstr, int klen,
+/* Why do these take a signed char *kstr? */
+int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, const EVP_PKEY *x, int nid,
+ const char *kstr, int klen,
pem_password_cb *cb, void *u);
-int PEM_write_bio_PKCS8PrivateKey(BIO *, EVP_PKEY *, const EVP_CIPHER *,
- char *, int, pem_password_cb *, void *);
-int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
- char *kstr, int klen,
+int PEM_write_bio_PKCS8PrivateKey(BIO *, const EVP_PKEY *, const EVP_CIPHER *,
+ const char *kstr, int klen,
+ pem_password_cb *cb, void *u);
+int i2d_PKCS8PrivateKey_bio(BIO *bp, const EVP_PKEY *x, const EVP_CIPHER *enc,
+ const char *kstr, int klen,
pem_password_cb *cb, void *u);
-int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid,
- char *kstr, int klen,
+int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, const EVP_PKEY *x, int nid,
+ const char *kstr, int klen,
pem_password_cb *cb, void *u);
EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
void *u);
# ifndef OPENSSL_NO_STDIO
-int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
- char *kstr, int klen,
+int i2d_PKCS8PrivateKey_fp(FILE *fp, const EVP_PKEY *x, const EVP_CIPHER *enc,
+ const char *kstr, int klen,
pem_password_cb *cb, void *u);
-int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid,
- char *kstr, int klen,
+int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, const EVP_PKEY *x, int nid,
+ const char *kstr, int klen,
pem_password_cb *cb, void *u);
-int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid,
- char *kstr, int klen,
+int PEM_write_PKCS8PrivateKey_nid(FILE *fp, const EVP_PKEY *x, int nid,
+ const char *kstr, int klen,
pem_password_cb *cb, void *u);
EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
void *u);
-int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
- char *kstr, int klen, pem_password_cb *cd,
- void *u);
+int PEM_write_PKCS8PrivateKey(FILE *fp, const EVP_PKEY *x, const EVP_CIPHER *enc,
+ const char *kstr, int klen,
+ pem_password_cb *cd, void *u);
# endif
+EVP_PKEY *PEM_read_bio_Parameters_ex(BIO *bp, EVP_PKEY **x,
+ OSSL_LIB_CTX *libctx, const char *propq);
EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x);
-int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x);
+int PEM_write_bio_Parameters(BIO *bp, const EVP_PKEY *x);
-# ifndef OPENSSL_NO_DSA
EVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length);
EVP_PKEY *b2i_PublicKey(const unsigned char **in, long length);
EVP_PKEY *b2i_PrivateKey_bio(BIO *in);
EVP_PKEY *b2i_PublicKey_bio(BIO *in);
-int i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk);
-int i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk);
-# ifndef OPENSSL_NO_RC4
+int i2b_PrivateKey_bio(BIO *out, const EVP_PKEY *pk);
+int i2b_PublicKey_bio(BIO *out, const EVP_PKEY *pk);
EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u);
-int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel,
+EVP_PKEY *b2i_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int i2b_PVK_bio(BIO *out, const EVP_PKEY *pk, int enclevel,
pem_password_cb *cb, void *u);
-# endif
-# endif
+int i2b_PVK_bio_ex(BIO *out, const EVP_PKEY *pk, int enclevel,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
# ifdef __cplusplus
}
diff --git a/include/openssl/pem2.h b/include/openssl/pem2.h
index 038fe790ace2..a8a5325bd4ba 100644
--- a/include/openssl/pem2.h
+++ b/include/openssl/pem2.h
@@ -1,13 +1,19 @@
/*
* Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_PEM2_H
-# define HEADER_PEM2_H
+#ifndef OPENSSL_PEM2_H
+# define OPENSSL_PEM2_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_PEM2_H
+# endif
# include <openssl/pemerr.h>
#endif
diff --git a/include/openssl/pemerr.h b/include/openssl/pemerr.h
index 4f7e3574b34a..18f6d9ef4cfd 100644
--- a/include/openssl/pemerr.h
+++ b/include/openssl/pemerr.h
@@ -1,71 +1,22 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_PEMERR_H
-# define HEADER_PEMERR_H
+#ifndef OPENSSL_PEMERR_H
+# define OPENSSL_PEMERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_PEM_strings(void);
-/*
- * PEM function codes.
- */
-# define PEM_F_B2I_DSS 127
-# define PEM_F_B2I_PVK_BIO 128
-# define PEM_F_B2I_RSA 129
-# define PEM_F_CHECK_BITLEN_DSA 130
-# define PEM_F_CHECK_BITLEN_RSA 131
-# define PEM_F_D2I_PKCS8PRIVATEKEY_BIO 120
-# define PEM_F_D2I_PKCS8PRIVATEKEY_FP 121
-# define PEM_F_DO_B2I 132
-# define PEM_F_DO_B2I_BIO 133
-# define PEM_F_DO_BLOB_HEADER 134
-# define PEM_F_DO_I2B 146
-# define PEM_F_DO_PK8PKEY 126
-# define PEM_F_DO_PK8PKEY_FP 125
-# define PEM_F_DO_PVK_BODY 135
-# define PEM_F_DO_PVK_HEADER 136
-# define PEM_F_GET_HEADER_AND_DATA 143
-# define PEM_F_GET_NAME 144
-# define PEM_F_I2B_PVK 137
-# define PEM_F_I2B_PVK_BIO 138
-# define PEM_F_LOAD_IV 101
-# define PEM_F_PEM_ASN1_READ 102
-# define PEM_F_PEM_ASN1_READ_BIO 103
-# define PEM_F_PEM_ASN1_WRITE 104
-# define PEM_F_PEM_ASN1_WRITE_BIO 105
-# define PEM_F_PEM_DEF_CALLBACK 100
-# define PEM_F_PEM_DO_HEADER 106
-# define PEM_F_PEM_GET_EVP_CIPHER_INFO 107
-# define PEM_F_PEM_READ 108
-# define PEM_F_PEM_READ_BIO 109
-# define PEM_F_PEM_READ_BIO_DHPARAMS 141
-# define PEM_F_PEM_READ_BIO_EX 145
-# define PEM_F_PEM_READ_BIO_PARAMETERS 140
-# define PEM_F_PEM_READ_BIO_PRIVATEKEY 123
-# define PEM_F_PEM_READ_DHPARAMS 142
-# define PEM_F_PEM_READ_PRIVATEKEY 124
-# define PEM_F_PEM_SIGNFINAL 112
-# define PEM_F_PEM_WRITE 113
-# define PEM_F_PEM_WRITE_BIO 114
-# define PEM_F_PEM_WRITE_BIO_PRIVATEKEY_TRADITIONAL 147
-# define PEM_F_PEM_WRITE_PRIVATEKEY 139
-# define PEM_F_PEM_X509_INFO_READ 115
-# define PEM_F_PEM_X509_INFO_READ_BIO 116
-# define PEM_F_PEM_X509_INFO_WRITE_BIO 117
/*
* PEM reason codes.
@@ -80,8 +31,10 @@ int ERR_load_PEM_strings(void);
# define PEM_R_BIO_WRITE_FAILURE 118
# define PEM_R_CIPHER_IS_NULL 127
# define PEM_R_ERROR_CONVERTING_PRIVATE_KEY 115
+# define PEM_R_EXPECTING_DSS_KEY_BLOB 131
# define PEM_R_EXPECTING_PRIVATE_KEY_BLOB 119
# define PEM_R_EXPECTING_PUBLIC_KEY_BLOB 120
+# define PEM_R_EXPECTING_RSA_KEY_BLOB 132
# define PEM_R_HEADER_TOO_LONG 128
# define PEM_R_INCONSISTENT_HEADER 121
# define PEM_R_KEYBLOB_HEADER_PARSE_ERROR 122
diff --git a/include/openssl/pkcs12.h b/include/openssl/pkcs12.h
deleted file mode 100644
index 3f43dad6d961..000000000000
--- a/include/openssl/pkcs12.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_PKCS12_H
-# define HEADER_PKCS12_H
-
-# include <openssl/bio.h>
-# include <openssl/x509.h>
-# include <openssl/pkcs12err.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-# define PKCS12_KEY_ID 1
-# define PKCS12_IV_ID 2
-# define PKCS12_MAC_ID 3
-
-/* Default iteration count */
-# ifndef PKCS12_DEFAULT_ITER
-# define PKCS12_DEFAULT_ITER PKCS5_DEFAULT_ITER
-# endif
-
-# define PKCS12_MAC_KEY_LENGTH 20
-
-# define PKCS12_SALT_LEN 8
-
-/* It's not clear if these are actually needed... */
-# define PKCS12_key_gen PKCS12_key_gen_utf8
-# define PKCS12_add_friendlyname PKCS12_add_friendlyname_utf8
-
-/* MS key usage constants */
-
-# define KEY_EX 0x10
-# define KEY_SIG 0x80
-
-typedef struct PKCS12_MAC_DATA_st PKCS12_MAC_DATA;
-
-typedef struct PKCS12_st PKCS12;
-
-typedef struct PKCS12_SAFEBAG_st PKCS12_SAFEBAG;
-
-DEFINE_STACK_OF(PKCS12_SAFEBAG)
-
-typedef struct pkcs12_bag_st PKCS12_BAGS;
-
-# define PKCS12_ERROR 0
-# define PKCS12_OK 1
-
-/* Compatibility macros */
-
-#if OPENSSL_API_COMPAT < 0x10100000L
-
-# define M_PKCS12_bag_type PKCS12_bag_type
-# define M_PKCS12_cert_bag_type PKCS12_cert_bag_type
-# define M_PKCS12_crl_bag_type PKCS12_cert_bag_type
-
-# define PKCS12_certbag2x509 PKCS12_SAFEBAG_get1_cert
-# define PKCS12_certbag2scrl PKCS12_SAFEBAG_get1_crl
-# define PKCS12_bag_type PKCS12_SAFEBAG_get_nid
-# define PKCS12_cert_bag_type PKCS12_SAFEBAG_get_bag_nid
-# define PKCS12_x5092certbag PKCS12_SAFEBAG_create_cert
-# define PKCS12_x509crl2certbag PKCS12_SAFEBAG_create_crl
-# define PKCS12_MAKE_KEYBAG PKCS12_SAFEBAG_create0_p8inf
-# define PKCS12_MAKE_SHKEYBAG PKCS12_SAFEBAG_create_pkcs8_encrypt
-
-#endif
-
-DEPRECATEDIN_1_1_0(ASN1_TYPE *PKCS12_get_attr(const PKCS12_SAFEBAG *bag, int attr_nid))
-
-ASN1_TYPE *PKCS8_get_attr(PKCS8_PRIV_KEY_INFO *p8, int attr_nid);
-int PKCS12_mac_present(const PKCS12 *p12);
-void PKCS12_get0_mac(const ASN1_OCTET_STRING **pmac,
- const X509_ALGOR **pmacalg,
- const ASN1_OCTET_STRING **psalt,
- const ASN1_INTEGER **piter,
- const PKCS12 *p12);
-
-const ASN1_TYPE *PKCS12_SAFEBAG_get0_attr(const PKCS12_SAFEBAG *bag,
- int attr_nid);
-const ASN1_OBJECT *PKCS12_SAFEBAG_get0_type(const PKCS12_SAFEBAG *bag);
-int PKCS12_SAFEBAG_get_nid(const PKCS12_SAFEBAG *bag);
-int PKCS12_SAFEBAG_get_bag_nid(const PKCS12_SAFEBAG *bag);
-
-X509 *PKCS12_SAFEBAG_get1_cert(const PKCS12_SAFEBAG *bag);
-X509_CRL *PKCS12_SAFEBAG_get1_crl(const PKCS12_SAFEBAG *bag);
-const STACK_OF(PKCS12_SAFEBAG) *
-PKCS12_SAFEBAG_get0_safes(const PKCS12_SAFEBAG *bag);
-const PKCS8_PRIV_KEY_INFO *PKCS12_SAFEBAG_get0_p8inf(const PKCS12_SAFEBAG *bag);
-const X509_SIG *PKCS12_SAFEBAG_get0_pkcs8(const PKCS12_SAFEBAG *bag);
-
-PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_cert(X509 *x509);
-PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_crl(X509_CRL *crl);
-PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_p8inf(PKCS8_PRIV_KEY_INFO *p8);
-PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_pkcs8(X509_SIG *p8);
-PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt(int pbe_nid,
- const char *pass,
- int passlen,
- unsigned char *salt,
- int saltlen, int iter,
- PKCS8_PRIV_KEY_INFO *p8inf);
-
-PKCS12_SAFEBAG *PKCS12_item_pack_safebag(void *obj, const ASN1_ITEM *it,
- int nid1, int nid2);
-PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(const X509_SIG *p8, const char *pass,
- int passlen);
-PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(const PKCS12_SAFEBAG *bag,
- const char *pass, int passlen);
-X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
- const char *pass, int passlen, unsigned char *salt,
- int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8);
-X509_SIG *PKCS8_set0_pbe(const char *pass, int passlen,
- PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe);
-PKCS7 *PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk);
-STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7);
-PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen,
- unsigned char *salt, int saltlen, int iter,
- STACK_OF(PKCS12_SAFEBAG) *bags);
-STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass,
- int passlen);
-
-int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes);
-STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12);
-
-int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name,
- int namelen);
-int PKCS12_add_friendlyname_asc(PKCS12_SAFEBAG *bag, const char *name,
- int namelen);
-int PKCS12_add_friendlyname_utf8(PKCS12_SAFEBAG *bag, const char *name,
- int namelen);
-int PKCS12_add_CSPName_asc(PKCS12_SAFEBAG *bag, const char *name,
- int namelen);
-int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag,
- const unsigned char *name, int namelen);
-int PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage);
-ASN1_TYPE *PKCS12_get_attr_gen(const STACK_OF(X509_ATTRIBUTE) *attrs,
- int attr_nid);
-char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag);
-const STACK_OF(X509_ATTRIBUTE) *
-PKCS12_SAFEBAG_get0_attrs(const PKCS12_SAFEBAG *bag);
-unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor,
- const char *pass, int passlen,
- const unsigned char *in, int inlen,
- unsigned char **data, int *datalen,
- int en_de);
-void *PKCS12_item_decrypt_d2i(const X509_ALGOR *algor, const ASN1_ITEM *it,
- const char *pass, int passlen,
- const ASN1_OCTET_STRING *oct, int zbuf);
-ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor,
- const ASN1_ITEM *it,
- const char *pass, int passlen,
- void *obj, int zbuf);
-PKCS12 *PKCS12_init(int mode);
-int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
- int saltlen, int id, int iter, int n,
- unsigned char *out, const EVP_MD *md_type);
-int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
- int saltlen, int id, int iter, int n,
- unsigned char *out, const EVP_MD *md_type);
-int PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt,
- int saltlen, int id, int iter, int n,
- unsigned char *out, const EVP_MD *md_type);
-int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
- ASN1_TYPE *param, const EVP_CIPHER *cipher,
- const EVP_MD *md_type, int en_de);
-int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
- unsigned char *mac, unsigned int *maclen);
-int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen);
-int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
- unsigned char *salt, int saltlen, int iter,
- const EVP_MD *md_type);
-int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt,
- int saltlen, const EVP_MD *md_type);
-unsigned char *OPENSSL_asc2uni(const char *asc, int asclen,
- unsigned char **uni, int *unilen);
-char *OPENSSL_uni2asc(const unsigned char *uni, int unilen);
-unsigned char *OPENSSL_utf82uni(const char *asc, int asclen,
- unsigned char **uni, int *unilen);
-char *OPENSSL_uni2utf8(const unsigned char *uni, int unilen);
-
-DECLARE_ASN1_FUNCTIONS(PKCS12)
-DECLARE_ASN1_FUNCTIONS(PKCS12_MAC_DATA)
-DECLARE_ASN1_FUNCTIONS(PKCS12_SAFEBAG)
-DECLARE_ASN1_FUNCTIONS(PKCS12_BAGS)
-
-DECLARE_ASN1_ITEM(PKCS12_SAFEBAGS)
-DECLARE_ASN1_ITEM(PKCS12_AUTHSAFES)
-
-void PKCS12_PBE_add(void);
-int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
- STACK_OF(X509) **ca);
-PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey,
- X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
- int iter, int mac_iter, int keytype);
-
-PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert);
-PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
- EVP_PKEY *key, int key_usage, int iter,
- int key_nid, const char *pass);
-int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
- int safe_nid, int iter, const char *pass);
-PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int p7_nid);
-
-int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12);
-# ifndef OPENSSL_NO_STDIO
-int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12);
-# endif
-PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12);
-# ifndef OPENSSL_NO_STDIO
-PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12);
-# endif
-int PKCS12_newpass(PKCS12 *p12, const char *oldpass, const char *newpass);
-
-# ifdef __cplusplus
-}
-# endif
-#endif
diff --git a/include/openssl/pkcs12.h.in b/include/openssl/pkcs12.h.in
new file mode 100644
index 000000000000..c98eebfb3988
--- /dev/null
+++ b/include/openssl/pkcs12.h.in
@@ -0,0 +1,327 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_PKCS12_H
+# define OPENSSL_PKCS12_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_PKCS12_H
+# endif
+
+# include <openssl/bio.h>
+# include <openssl/core.h>
+# include <openssl/x509.h>
+# include <openssl/pkcs12err.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+# define PKCS12_KEY_ID 1
+# define PKCS12_IV_ID 2
+# define PKCS12_MAC_ID 3
+
+/* Default iteration count */
+# ifndef PKCS12_DEFAULT_ITER
+# define PKCS12_DEFAULT_ITER PKCS5_DEFAULT_ITER
+# endif
+
+# define PKCS12_MAC_KEY_LENGTH 20
+
+# define PKCS12_SALT_LEN 8
+
+/* It's not clear if these are actually needed... */
+# define PKCS12_key_gen PKCS12_key_gen_utf8
+# define PKCS12_add_friendlyname PKCS12_add_friendlyname_utf8
+
+/* MS key usage constants */
+
+# define KEY_EX 0x10
+# define KEY_SIG 0x80
+
+typedef struct PKCS12_MAC_DATA_st PKCS12_MAC_DATA;
+
+typedef struct PKCS12_st PKCS12;
+
+typedef struct PKCS12_SAFEBAG_st PKCS12_SAFEBAG;
+
+{-
+ generate_stack_macros("PKCS12_SAFEBAG");
+-}
+
+typedef struct pkcs12_bag_st PKCS12_BAGS;
+
+# define PKCS12_ERROR 0
+# define PKCS12_OK 1
+
+/* Compatibility macros */
+
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
+
+# define M_PKCS12_bag_type PKCS12_bag_type
+# define M_PKCS12_cert_bag_type PKCS12_cert_bag_type
+# define M_PKCS12_crl_bag_type PKCS12_cert_bag_type
+
+# define PKCS12_certbag2x509 PKCS12_SAFEBAG_get1_cert
+# define PKCS12_certbag2scrl PKCS12_SAFEBAG_get1_crl
+# define PKCS12_bag_type PKCS12_SAFEBAG_get_nid
+# define PKCS12_cert_bag_type PKCS12_SAFEBAG_get_bag_nid
+# define PKCS12_x5092certbag PKCS12_SAFEBAG_create_cert
+# define PKCS12_x509crl2certbag PKCS12_SAFEBAG_create_crl
+# define PKCS12_MAKE_KEYBAG PKCS12_SAFEBAG_create0_p8inf
+# define PKCS12_MAKE_SHKEYBAG PKCS12_SAFEBAG_create_pkcs8_encrypt
+
+#endif
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 ASN1_TYPE *PKCS12_get_attr(const PKCS12_SAFEBAG *bag,
+ int attr_nid);
+#endif
+
+ASN1_TYPE *PKCS8_get_attr(PKCS8_PRIV_KEY_INFO *p8, int attr_nid);
+int PKCS12_mac_present(const PKCS12 *p12);
+void PKCS12_get0_mac(const ASN1_OCTET_STRING **pmac,
+ const X509_ALGOR **pmacalg,
+ const ASN1_OCTET_STRING **psalt,
+ const ASN1_INTEGER **piter,
+ const PKCS12 *p12);
+
+const ASN1_TYPE *PKCS12_SAFEBAG_get0_attr(const PKCS12_SAFEBAG *bag,
+ int attr_nid);
+const ASN1_OBJECT *PKCS12_SAFEBAG_get0_type(const PKCS12_SAFEBAG *bag);
+int PKCS12_SAFEBAG_get_nid(const PKCS12_SAFEBAG *bag);
+int PKCS12_SAFEBAG_get_bag_nid(const PKCS12_SAFEBAG *bag);
+const ASN1_TYPE *PKCS12_SAFEBAG_get0_bag_obj(const PKCS12_SAFEBAG *bag);
+const ASN1_OBJECT *PKCS12_SAFEBAG_get0_bag_type(const PKCS12_SAFEBAG *bag);
+
+X509 *PKCS12_SAFEBAG_get1_cert(const PKCS12_SAFEBAG *bag);
+X509_CRL *PKCS12_SAFEBAG_get1_crl(const PKCS12_SAFEBAG *bag);
+const STACK_OF(PKCS12_SAFEBAG) *
+PKCS12_SAFEBAG_get0_safes(const PKCS12_SAFEBAG *bag);
+const PKCS8_PRIV_KEY_INFO *PKCS12_SAFEBAG_get0_p8inf(const PKCS12_SAFEBAG *bag);
+const X509_SIG *PKCS12_SAFEBAG_get0_pkcs8(const PKCS12_SAFEBAG *bag);
+
+PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_cert(X509 *x509);
+PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_crl(X509_CRL *crl);
+PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_secret(int type, int vtype, const unsigned char *value, int len);
+PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_p8inf(PKCS8_PRIV_KEY_INFO *p8);
+PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_pkcs8(X509_SIG *p8);
+PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt(int pbe_nid,
+ const char *pass,
+ int passlen,
+ unsigned char *salt,
+ int saltlen, int iter,
+ PKCS8_PRIV_KEY_INFO *p8inf);
+PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(int pbe_nid,
+ const char *pass,
+ int passlen,
+ unsigned char *salt,
+ int saltlen, int iter,
+ PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *ctx,
+ const char *propq);
+
+PKCS12_SAFEBAG *PKCS12_item_pack_safebag(void *obj, const ASN1_ITEM *it,
+ int nid1, int nid2);
+PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(const X509_SIG *p8, const char *pass,
+ int passlen);
+PKCS8_PRIV_KEY_INFO *PKCS8_decrypt_ex(const X509_SIG *p8, const char *pass,
+ int passlen, OSSL_LIB_CTX *ctx,
+ const char *propq);
+PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(const PKCS12_SAFEBAG *bag,
+ const char *pass, int passlen);
+PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey_ex(const PKCS12_SAFEBAG *bag,
+ const char *pass, int passlen,
+ OSSL_LIB_CTX *ctx,
+ const char *propq);
+X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
+ const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8);
+X509_SIG *PKCS8_encrypt_ex(int pbe_nid, const EVP_CIPHER *cipher,
+ const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8,
+ OSSL_LIB_CTX *ctx, const char *propq);
+X509_SIG *PKCS8_set0_pbe(const char *pass, int passlen,
+ PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe);
+X509_SIG *PKCS8_set0_pbe_ex(const char *pass, int passlen,
+ PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe,
+ OSSL_LIB_CTX *ctx, const char *propq);
+PKCS7 *PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk);
+STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7);
+PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen,
+ unsigned char *salt, int saltlen, int iter,
+ STACK_OF(PKCS12_SAFEBAG) *bags);
+PKCS7 *PKCS12_pack_p7encdata_ex(int pbe_nid, const char *pass, int passlen,
+ unsigned char *salt, int saltlen, int iter,
+ STACK_OF(PKCS12_SAFEBAG) *bags,
+ OSSL_LIB_CTX *ctx, const char *propq);
+
+STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass,
+ int passlen);
+
+int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes);
+STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12);
+
+int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name,
+ int namelen);
+int PKCS12_add_friendlyname_asc(PKCS12_SAFEBAG *bag, const char *name,
+ int namelen);
+int PKCS12_add_friendlyname_utf8(PKCS12_SAFEBAG *bag, const char *name,
+ int namelen);
+int PKCS12_add_CSPName_asc(PKCS12_SAFEBAG *bag, const char *name,
+ int namelen);
+int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag,
+ const unsigned char *name, int namelen);
+int PKCS12_add1_attr_by_NID(PKCS12_SAFEBAG *bag, int nid, int type,
+ const unsigned char *bytes, int len);
+int PKCS12_add1_attr_by_txt(PKCS12_SAFEBAG *bag, const char *attrname, int type,
+ const unsigned char *bytes, int len);
+int PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage);
+ASN1_TYPE *PKCS12_get_attr_gen(const STACK_OF(X509_ATTRIBUTE) *attrs,
+ int attr_nid);
+char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag);
+const STACK_OF(X509_ATTRIBUTE) *
+PKCS12_SAFEBAG_get0_attrs(const PKCS12_SAFEBAG *bag);
+unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor,
+ const char *pass, int passlen,
+ const unsigned char *in, int inlen,
+ unsigned char **data, int *datalen,
+ int en_de);
+unsigned char *PKCS12_pbe_crypt_ex(const X509_ALGOR *algor,
+ const char *pass, int passlen,
+ const unsigned char *in, int inlen,
+ unsigned char **data, int *datalen,
+ int en_de, OSSL_LIB_CTX *libctx,
+ const char *propq);
+void *PKCS12_item_decrypt_d2i(const X509_ALGOR *algor, const ASN1_ITEM *it,
+ const char *pass, int passlen,
+ const ASN1_OCTET_STRING *oct, int zbuf);
+void *PKCS12_item_decrypt_d2i_ex(const X509_ALGOR *algor, const ASN1_ITEM *it,
+ const char *pass, int passlen,
+ const ASN1_OCTET_STRING *oct, int zbuf,
+ OSSL_LIB_CTX *libctx,
+ const char *propq);
+ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor,
+ const ASN1_ITEM *it,
+ const char *pass, int passlen,
+ void *obj, int zbuf);
+ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt_ex(X509_ALGOR *algor,
+ const ASN1_ITEM *it,
+ const char *pass, int passlen,
+ void *obj, int zbuf,
+ OSSL_LIB_CTX *ctx,
+ const char *propq);
+PKCS12 *PKCS12_init(int mode);
+PKCS12 *PKCS12_init_ex(int mode, OSSL_LIB_CTX *ctx, const char *propq);
+
+int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type);
+int PKCS12_key_gen_asc_ex(const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type,
+ OSSL_LIB_CTX *ctx, const char *propq);
+int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type);
+int PKCS12_key_gen_uni_ex(unsigned char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type,
+ OSSL_LIB_CTX *ctx, const char *propq);
+int PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type);
+int PKCS12_key_gen_utf8_ex(const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type,
+ OSSL_LIB_CTX *ctx, const char *propq);
+
+int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md_type, int en_de);
+int PKCS12_PBE_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md_type, int en_de,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
+ unsigned char *mac, unsigned int *maclen);
+int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen);
+int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
+ unsigned char *salt, int saltlen, int iter,
+ const EVP_MD *md_type);
+int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt,
+ int saltlen, const EVP_MD *md_type);
+unsigned char *OPENSSL_asc2uni(const char *asc, int asclen,
+ unsigned char **uni, int *unilen);
+char *OPENSSL_uni2asc(const unsigned char *uni, int unilen);
+unsigned char *OPENSSL_utf82uni(const char *asc, int asclen,
+ unsigned char **uni, int *unilen);
+char *OPENSSL_uni2utf8(const unsigned char *uni, int unilen);
+
+DECLARE_ASN1_FUNCTIONS(PKCS12)
+DECLARE_ASN1_FUNCTIONS(PKCS12_MAC_DATA)
+DECLARE_ASN1_FUNCTIONS(PKCS12_SAFEBAG)
+DECLARE_ASN1_FUNCTIONS(PKCS12_BAGS)
+
+DECLARE_ASN1_ITEM(PKCS12_SAFEBAGS)
+DECLARE_ASN1_ITEM(PKCS12_AUTHSAFES)
+
+void PKCS12_PBE_add(void);
+int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
+ STACK_OF(X509) **ca);
+PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey,
+ X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
+ int iter, int mac_iter, int keytype);
+PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey,
+ X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
+ int iter, int mac_iter, int keytype,
+ OSSL_LIB_CTX *ctx, const char *propq);
+
+PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert);
+PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
+ EVP_PKEY *key, int key_usage, int iter,
+ int key_nid, const char *pass);
+PKCS12_SAFEBAG *PKCS12_add_key_ex(STACK_OF(PKCS12_SAFEBAG) **pbags,
+ EVP_PKEY *key, int key_usage, int iter,
+ int key_nid, const char *pass,
+ OSSL_LIB_CTX *ctx, const char *propq);
+
+PKCS12_SAFEBAG *PKCS12_add_secret(STACK_OF(PKCS12_SAFEBAG) **pbags,
+ int nid_type, const unsigned char *value, int len);
+int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
+ int safe_nid, int iter, const char *pass);
+int PKCS12_add_safe_ex(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
+ int safe_nid, int iter, const char *pass,
+ OSSL_LIB_CTX *ctx, const char *propq);
+
+PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int p7_nid);
+PKCS12 *PKCS12_add_safes_ex(STACK_OF(PKCS7) *safes, int p7_nid,
+ OSSL_LIB_CTX *ctx, const char *propq);
+
+int i2d_PKCS12_bio(BIO *bp, const PKCS12 *p12);
+# ifndef OPENSSL_NO_STDIO
+int i2d_PKCS12_fp(FILE *fp, const PKCS12 *p12);
+# endif
+PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12);
+# ifndef OPENSSL_NO_STDIO
+PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12);
+# endif
+int PKCS12_newpass(PKCS12 *p12, const char *oldpass, const char *newpass);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/pkcs12err.h b/include/openssl/pkcs12err.h
index eff5eb260282..933c83299ae3 100644
--- a/include/openssl/pkcs12err.h
+++ b/include/openssl/pkcs12err.h
@@ -1,57 +1,22 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_PKCS12ERR_H
-# define HEADER_PKCS12ERR_H
+#ifndef OPENSSL_PKCS12ERR_H
+# define OPENSSL_PKCS12ERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_PKCS12_strings(void);
-/*
- * PKCS12 function codes.
- */
-# define PKCS12_F_OPENSSL_ASC2UNI 121
-# define PKCS12_F_OPENSSL_UNI2ASC 124
-# define PKCS12_F_OPENSSL_UNI2UTF8 127
-# define PKCS12_F_OPENSSL_UTF82UNI 129
-# define PKCS12_F_PKCS12_CREATE 105
-# define PKCS12_F_PKCS12_GEN_MAC 107
-# define PKCS12_F_PKCS12_INIT 109
-# define PKCS12_F_PKCS12_ITEM_DECRYPT_D2I 106
-# define PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT 108
-# define PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG 117
-# define PKCS12_F_PKCS12_KEY_GEN_ASC 110
-# define PKCS12_F_PKCS12_KEY_GEN_UNI 111
-# define PKCS12_F_PKCS12_KEY_GEN_UTF8 116
-# define PKCS12_F_PKCS12_NEWPASS 128
-# define PKCS12_F_PKCS12_PACK_P7DATA 114
-# define PKCS12_F_PKCS12_PACK_P7ENCDATA 115
-# define PKCS12_F_PKCS12_PARSE 118
-# define PKCS12_F_PKCS12_PBE_CRYPT 119
-# define PKCS12_F_PKCS12_PBE_KEYIVGEN 120
-# define PKCS12_F_PKCS12_SAFEBAG_CREATE0_P8INF 112
-# define PKCS12_F_PKCS12_SAFEBAG_CREATE0_PKCS8 113
-# define PKCS12_F_PKCS12_SAFEBAG_CREATE_PKCS8_ENCRYPT 133
-# define PKCS12_F_PKCS12_SETUP_MAC 122
-# define PKCS12_F_PKCS12_SET_MAC 123
-# define PKCS12_F_PKCS12_UNPACK_AUTHSAFES 130
-# define PKCS12_F_PKCS12_UNPACK_P7DATA 131
-# define PKCS12_F_PKCS12_VERIFY_MAC 126
-# define PKCS12_F_PKCS8_ENCRYPT 125
-# define PKCS12_F_PKCS8_SET0_PBE 132
/*
* PKCS12 reason codes.
@@ -64,6 +29,7 @@ int ERR_load_PKCS12_strings(void);
# define PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE 120
# define PKCS12_R_INVALID_NULL_ARGUMENT 104
# define PKCS12_R_INVALID_NULL_PKCS12_POINTER 105
+# define PKCS12_R_INVALID_TYPE 112
# define PKCS12_R_IV_GEN_ERROR 106
# define PKCS12_R_KEY_GEN_ERROR 107
# define PKCS12_R_MAC_ABSENT 108
@@ -72,9 +38,7 @@ int ERR_load_PKCS12_strings(void);
# define PKCS12_R_MAC_STRING_SET_ERROR 111
# define PKCS12_R_MAC_VERIFY_FAILURE 113
# define PKCS12_R_PARSE_ERROR 114
-# define PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR 115
# define PKCS12_R_PKCS12_CIPHERFINAL_ERROR 116
-# define PKCS12_R_PKCS12_PBE_CRYPT_ERROR 117
# define PKCS12_R_UNKNOWN_DIGEST_ALGORITHM 118
# define PKCS12_R_UNSUPPORTED_PKCS12_MODE 119
diff --git a/include/openssl/pkcs7.h b/include/openssl/pkcs7.h
deleted file mode 100644
index 9b66e002d285..000000000000
--- a/include/openssl/pkcs7.h
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_PKCS7_H
-# define HEADER_PKCS7_H
-
-# include <openssl/asn1.h>
-# include <openssl/bio.h>
-# include <openssl/e_os2.h>
-
-# include <openssl/symhacks.h>
-# include <openssl/ossl_typ.h>
-# include <openssl/pkcs7err.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*-
-Encryption_ID DES-CBC
-Digest_ID MD5
-Digest_Encryption_ID rsaEncryption
-Key_Encryption_ID rsaEncryption
-*/
-
-typedef struct pkcs7_issuer_and_serial_st {
- X509_NAME *issuer;
- ASN1_INTEGER *serial;
-} PKCS7_ISSUER_AND_SERIAL;
-
-typedef struct pkcs7_signer_info_st {
- ASN1_INTEGER *version; /* version 1 */
- PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
- X509_ALGOR *digest_alg;
- STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
- X509_ALGOR *digest_enc_alg;
- ASN1_OCTET_STRING *enc_digest;
- STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
- /* The private key to sign with */
- EVP_PKEY *pkey;
-} PKCS7_SIGNER_INFO;
-
-DEFINE_STACK_OF(PKCS7_SIGNER_INFO)
-
-typedef struct pkcs7_recip_info_st {
- ASN1_INTEGER *version; /* version 0 */
- PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
- X509_ALGOR *key_enc_algor;
- ASN1_OCTET_STRING *enc_key;
- X509 *cert; /* get the pub-key from this */
-} PKCS7_RECIP_INFO;
-
-DEFINE_STACK_OF(PKCS7_RECIP_INFO)
-
-typedef struct pkcs7_signed_st {
- ASN1_INTEGER *version; /* version 1 */
- STACK_OF(X509_ALGOR) *md_algs; /* md used */
- STACK_OF(X509) *cert; /* [ 0 ] */
- STACK_OF(X509_CRL) *crl; /* [ 1 ] */
- STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
- struct pkcs7_st *contents;
-} PKCS7_SIGNED;
-/*
- * The above structure is very very similar to PKCS7_SIGN_ENVELOPE. How about
- * merging the two
- */
-
-typedef struct pkcs7_enc_content_st {
- ASN1_OBJECT *content_type;
- X509_ALGOR *algorithm;
- ASN1_OCTET_STRING *enc_data; /* [ 0 ] */
- const EVP_CIPHER *cipher;
-} PKCS7_ENC_CONTENT;
-
-typedef struct pkcs7_enveloped_st {
- ASN1_INTEGER *version; /* version 0 */
- STACK_OF(PKCS7_RECIP_INFO) *recipientinfo;
- PKCS7_ENC_CONTENT *enc_data;
-} PKCS7_ENVELOPE;
-
-typedef struct pkcs7_signedandenveloped_st {
- ASN1_INTEGER *version; /* version 1 */
- STACK_OF(X509_ALGOR) *md_algs; /* md used */
- STACK_OF(X509) *cert; /* [ 0 ] */
- STACK_OF(X509_CRL) *crl; /* [ 1 ] */
- STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
- PKCS7_ENC_CONTENT *enc_data;
- STACK_OF(PKCS7_RECIP_INFO) *recipientinfo;
-} PKCS7_SIGN_ENVELOPE;
-
-typedef struct pkcs7_digest_st {
- ASN1_INTEGER *version; /* version 0 */
- X509_ALGOR *md; /* md used */
- struct pkcs7_st *contents;
- ASN1_OCTET_STRING *digest;
-} PKCS7_DIGEST;
-
-typedef struct pkcs7_encrypted_st {
- ASN1_INTEGER *version; /* version 0 */
- PKCS7_ENC_CONTENT *enc_data;
-} PKCS7_ENCRYPT;
-
-typedef struct pkcs7_st {
- /*
- * The following is non NULL if it contains ASN1 encoding of this
- * structure
- */
- unsigned char *asn1;
- long length;
-# define PKCS7_S_HEADER 0
-# define PKCS7_S_BODY 1
-# define PKCS7_S_TAIL 2
- int state; /* used during processing */
- int detached;
- ASN1_OBJECT *type;
- /* content as defined by the type */
- /*
- * all encryption/message digests are applied to the 'contents', leaving
- * out the 'type' field.
- */
- union {
- char *ptr;
- /* NID_pkcs7_data */
- ASN1_OCTET_STRING *data;
- /* NID_pkcs7_signed */
- PKCS7_SIGNED *sign;
- /* NID_pkcs7_enveloped */
- PKCS7_ENVELOPE *enveloped;
- /* NID_pkcs7_signedAndEnveloped */
- PKCS7_SIGN_ENVELOPE *signed_and_enveloped;
- /* NID_pkcs7_digest */
- PKCS7_DIGEST *digest;
- /* NID_pkcs7_encrypted */
- PKCS7_ENCRYPT *encrypted;
- /* Anything else */
- ASN1_TYPE *other;
- } d;
-} PKCS7;
-
-DEFINE_STACK_OF(PKCS7)
-
-# define PKCS7_OP_SET_DETACHED_SIGNATURE 1
-# define PKCS7_OP_GET_DETACHED_SIGNATURE 2
-
-# define PKCS7_get_signed_attributes(si) ((si)->auth_attr)
-# define PKCS7_get_attributes(si) ((si)->unauth_attr)
-
-# define PKCS7_type_is_signed(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_signed)
-# define PKCS7_type_is_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted)
-# define PKCS7_type_is_enveloped(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_enveloped)
-# define PKCS7_type_is_signedAndEnveloped(a) \
- (OBJ_obj2nid((a)->type) == NID_pkcs7_signedAndEnveloped)
-# define PKCS7_type_is_data(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_data)
-# define PKCS7_type_is_digest(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_digest)
-
-# define PKCS7_set_detached(p,v) \
- PKCS7_ctrl(p,PKCS7_OP_SET_DETACHED_SIGNATURE,v,NULL)
-# define PKCS7_get_detached(p) \
- PKCS7_ctrl(p,PKCS7_OP_GET_DETACHED_SIGNATURE,0,NULL)
-
-# define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7))
-
-/* S/MIME related flags */
-
-# define PKCS7_TEXT 0x1
-# define PKCS7_NOCERTS 0x2
-# define PKCS7_NOSIGS 0x4
-# define PKCS7_NOCHAIN 0x8
-# define PKCS7_NOINTERN 0x10
-# define PKCS7_NOVERIFY 0x20
-# define PKCS7_DETACHED 0x40
-# define PKCS7_BINARY 0x80
-# define PKCS7_NOATTR 0x100
-# define PKCS7_NOSMIMECAP 0x200
-# define PKCS7_NOOLDMIMETYPE 0x400
-# define PKCS7_CRLFEOL 0x800
-# define PKCS7_STREAM 0x1000
-# define PKCS7_NOCRL 0x2000
-# define PKCS7_PARTIAL 0x4000
-# define PKCS7_REUSE_DIGEST 0x8000
-# define PKCS7_NO_DUAL_CONTENT 0x10000
-
-/* Flags: for compatibility with older code */
-
-# define SMIME_TEXT PKCS7_TEXT
-# define SMIME_NOCERTS PKCS7_NOCERTS
-# define SMIME_NOSIGS PKCS7_NOSIGS
-# define SMIME_NOCHAIN PKCS7_NOCHAIN
-# define SMIME_NOINTERN PKCS7_NOINTERN
-# define SMIME_NOVERIFY PKCS7_NOVERIFY
-# define SMIME_DETACHED PKCS7_DETACHED
-# define SMIME_BINARY PKCS7_BINARY
-# define SMIME_NOATTR PKCS7_NOATTR
-
-/* CRLF ASCII canonicalisation */
-# define SMIME_ASCIICRLF 0x80000
-
-DECLARE_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL)
-
-int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data,
- const EVP_MD *type, unsigned char *md,
- unsigned int *len);
-# ifndef OPENSSL_NO_STDIO
-PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7);
-int i2d_PKCS7_fp(FILE *fp, PKCS7 *p7);
-# endif
-PKCS7 *PKCS7_dup(PKCS7 *p7);
-PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7);
-int i2d_PKCS7_bio(BIO *bp, PKCS7 *p7);
-int i2d_PKCS7_bio_stream(BIO *out, PKCS7 *p7, BIO *in, int flags);
-int PEM_write_bio_PKCS7_stream(BIO *out, PKCS7 *p7, BIO *in, int flags);
-
-DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNER_INFO)
-DECLARE_ASN1_FUNCTIONS(PKCS7_RECIP_INFO)
-DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNED)
-DECLARE_ASN1_FUNCTIONS(PKCS7_ENC_CONTENT)
-DECLARE_ASN1_FUNCTIONS(PKCS7_ENVELOPE)
-DECLARE_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE)
-DECLARE_ASN1_FUNCTIONS(PKCS7_DIGEST)
-DECLARE_ASN1_FUNCTIONS(PKCS7_ENCRYPT)
-DECLARE_ASN1_FUNCTIONS(PKCS7)
-
-DECLARE_ASN1_ITEM(PKCS7_ATTR_SIGN)
-DECLARE_ASN1_ITEM(PKCS7_ATTR_VERIFY)
-
-DECLARE_ASN1_NDEF_FUNCTION(PKCS7)
-DECLARE_ASN1_PRINT_FUNCTION(PKCS7)
-
-long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg);
-
-int PKCS7_set_type(PKCS7 *p7, int type);
-int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other);
-int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data);
-int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
- const EVP_MD *dgst);
-int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si);
-int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *p7i);
-int PKCS7_add_certificate(PKCS7 *p7, X509 *x509);
-int PKCS7_add_crl(PKCS7 *p7, X509_CRL *x509);
-int PKCS7_content_new(PKCS7 *p7, int nid);
-int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx,
- BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si);
-int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
- X509 *x509);
-
-BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio);
-int PKCS7_dataFinal(PKCS7 *p7, BIO *bio);
-BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert);
-
-PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509,
- EVP_PKEY *pkey, const EVP_MD *dgst);
-X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si);
-int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md);
-STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7);
-
-PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509);
-void PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk,
- X509_ALGOR **pdig, X509_ALGOR **psig);
-void PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc);
-int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri);
-int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509);
-int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher);
-int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7);
-
-PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx);
-ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk);
-int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int type,
- void *data);
-int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
- void *value);
-ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid);
-ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid);
-int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
- STACK_OF(X509_ATTRIBUTE) *sk);
-int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si,
- STACK_OF(X509_ATTRIBUTE) *sk);
-
-PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
- BIO *data, int flags);
-
-PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7,
- X509 *signcert, EVP_PKEY *pkey,
- const EVP_MD *md, int flags);
-
-int PKCS7_final(PKCS7 *p7, BIO *data, int flags);
-int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
- BIO *indata, BIO *out, int flags);
-STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs,
- int flags);
-PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
- int flags);
-int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data,
- int flags);
-
-int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si,
- STACK_OF(X509_ALGOR) *cap);
-STACK_OF(X509_ALGOR) *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si);
-int PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *sk, int nid, int arg);
-
-int PKCS7_add_attrib_content_type(PKCS7_SIGNER_INFO *si, ASN1_OBJECT *coid);
-int PKCS7_add0_attrib_signing_time(PKCS7_SIGNER_INFO *si, ASN1_TIME *t);
-int PKCS7_add1_attrib_digest(PKCS7_SIGNER_INFO *si,
- const unsigned char *md, int mdlen);
-
-int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags);
-PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont);
-
-BIO *BIO_new_PKCS7(BIO *out, PKCS7 *p7);
-
-# ifdef __cplusplus
-}
-# endif
-#endif
diff --git a/include/openssl/pkcs7.h.in b/include/openssl/pkcs7.h.in
new file mode 100644
index 000000000000..f5c55a3fbe57
--- /dev/null
+++ b/include/openssl/pkcs7.h.in
@@ -0,0 +1,356 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_PKCS7_H
+# define OPENSSL_PKCS7_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_PKCS7_H
+# endif
+
+# include <openssl/asn1.h>
+# include <openssl/bio.h>
+# include <openssl/e_os2.h>
+
+# include <openssl/symhacks.h>
+# include <openssl/types.h>
+# include <openssl/pkcs7err.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*-
+Encryption_ID DES-CBC
+Digest_ID MD5
+Digest_Encryption_ID rsaEncryption
+Key_Encryption_ID rsaEncryption
+*/
+
+typedef struct PKCS7_CTX_st {
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+} PKCS7_CTX;
+
+typedef struct pkcs7_issuer_and_serial_st {
+ X509_NAME *issuer;
+ ASN1_INTEGER *serial;
+} PKCS7_ISSUER_AND_SERIAL;
+
+typedef struct pkcs7_signer_info_st {
+ ASN1_INTEGER *version; /* version 1 */
+ PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
+ X509_ALGOR *digest_alg;
+ STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
+ X509_ALGOR *digest_enc_alg;
+ ASN1_OCTET_STRING *enc_digest;
+ STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
+ /* The private key to sign with */
+ EVP_PKEY *pkey;
+ const PKCS7_CTX *ctx;
+} PKCS7_SIGNER_INFO;
+{-
+ generate_stack_macros("PKCS7_SIGNER_INFO");
+-}
+
+typedef struct pkcs7_recip_info_st {
+ ASN1_INTEGER *version; /* version 0 */
+ PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
+ X509_ALGOR *key_enc_algor;
+ ASN1_OCTET_STRING *enc_key;
+ X509 *cert; /* get the pub-key from this */
+ const PKCS7_CTX *ctx;
+} PKCS7_RECIP_INFO;
+{-
+ generate_stack_macros("PKCS7_RECIP_INFO");
+-}
+
+
+typedef struct pkcs7_signed_st {
+ ASN1_INTEGER *version; /* version 1 */
+ STACK_OF(X509_ALGOR) *md_algs; /* md used */
+ STACK_OF(X509) *cert; /* [ 0 ] */
+ STACK_OF(X509_CRL) *crl; /* [ 1 ] */
+ STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
+ struct pkcs7_st *contents;
+} PKCS7_SIGNED;
+/*
+ * The above structure is very very similar to PKCS7_SIGN_ENVELOPE. How about
+ * merging the two
+ */
+
+typedef struct pkcs7_enc_content_st {
+ ASN1_OBJECT *content_type;
+ X509_ALGOR *algorithm;
+ ASN1_OCTET_STRING *enc_data; /* [ 0 ] */
+ const EVP_CIPHER *cipher;
+ const PKCS7_CTX *ctx;
+} PKCS7_ENC_CONTENT;
+
+typedef struct pkcs7_enveloped_st {
+ ASN1_INTEGER *version; /* version 0 */
+ STACK_OF(PKCS7_RECIP_INFO) *recipientinfo;
+ PKCS7_ENC_CONTENT *enc_data;
+} PKCS7_ENVELOPE;
+
+typedef struct pkcs7_signedandenveloped_st {
+ ASN1_INTEGER *version; /* version 1 */
+ STACK_OF(X509_ALGOR) *md_algs; /* md used */
+ STACK_OF(X509) *cert; /* [ 0 ] */
+ STACK_OF(X509_CRL) *crl; /* [ 1 ] */
+ STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
+ PKCS7_ENC_CONTENT *enc_data;
+ STACK_OF(PKCS7_RECIP_INFO) *recipientinfo;
+} PKCS7_SIGN_ENVELOPE;
+
+typedef struct pkcs7_digest_st {
+ ASN1_INTEGER *version; /* version 0 */
+ X509_ALGOR *md; /* md used */
+ struct pkcs7_st *contents;
+ ASN1_OCTET_STRING *digest;
+} PKCS7_DIGEST;
+
+typedef struct pkcs7_encrypted_st {
+ ASN1_INTEGER *version; /* version 0 */
+ PKCS7_ENC_CONTENT *enc_data;
+} PKCS7_ENCRYPT;
+
+typedef struct pkcs7_st {
+ /*
+ * The following is non NULL if it contains ASN1 encoding of this
+ * structure
+ */
+ unsigned char *asn1;
+ long length;
+# define PKCS7_S_HEADER 0
+# define PKCS7_S_BODY 1
+# define PKCS7_S_TAIL 2
+ int state; /* used during processing */
+ int detached;
+ ASN1_OBJECT *type;
+ /* content as defined by the type */
+ /*
+ * all encryption/message digests are applied to the 'contents', leaving
+ * out the 'type' field.
+ */
+ union {
+ char *ptr;
+ /* NID_pkcs7_data */
+ ASN1_OCTET_STRING *data;
+ /* NID_pkcs7_signed */
+ PKCS7_SIGNED *sign;
+ /* NID_pkcs7_enveloped */
+ PKCS7_ENVELOPE *enveloped;
+ /* NID_pkcs7_signedAndEnveloped */
+ PKCS7_SIGN_ENVELOPE *signed_and_enveloped;
+ /* NID_pkcs7_digest */
+ PKCS7_DIGEST *digest;
+ /* NID_pkcs7_encrypted */
+ PKCS7_ENCRYPT *encrypted;
+ /* Anything else */
+ ASN1_TYPE *other;
+ } d;
+ PKCS7_CTX ctx;
+} PKCS7;
+{-
+ generate_stack_macros("PKCS7");
+-}
+
+
+# define PKCS7_OP_SET_DETACHED_SIGNATURE 1
+# define PKCS7_OP_GET_DETACHED_SIGNATURE 2
+
+# define PKCS7_get_signed_attributes(si) ((si)->auth_attr)
+# define PKCS7_get_attributes(si) ((si)->unauth_attr)
+
+# define PKCS7_type_is_signed(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_signed)
+# define PKCS7_type_is_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted)
+# define PKCS7_type_is_enveloped(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_enveloped)
+# define PKCS7_type_is_signedAndEnveloped(a) \
+ (OBJ_obj2nid((a)->type) == NID_pkcs7_signedAndEnveloped)
+# define PKCS7_type_is_data(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_data)
+# define PKCS7_type_is_digest(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_digest)
+
+# define PKCS7_set_detached(p,v) \
+ PKCS7_ctrl(p,PKCS7_OP_SET_DETACHED_SIGNATURE,v,NULL)
+# define PKCS7_get_detached(p) \
+ PKCS7_ctrl(p,PKCS7_OP_GET_DETACHED_SIGNATURE,0,NULL)
+
+# define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7))
+
+/* S/MIME related flags */
+
+# define PKCS7_TEXT 0x1
+# define PKCS7_NOCERTS 0x2
+# define PKCS7_NOSIGS 0x4
+# define PKCS7_NOCHAIN 0x8
+# define PKCS7_NOINTERN 0x10
+# define PKCS7_NOVERIFY 0x20
+# define PKCS7_DETACHED 0x40
+# define PKCS7_BINARY 0x80
+# define PKCS7_NOATTR 0x100
+# define PKCS7_NOSMIMECAP 0x200
+# define PKCS7_NOOLDMIMETYPE 0x400
+# define PKCS7_CRLFEOL 0x800
+# define PKCS7_STREAM 0x1000
+# define PKCS7_NOCRL 0x2000
+# define PKCS7_PARTIAL 0x4000
+# define PKCS7_REUSE_DIGEST 0x8000
+# define PKCS7_NO_DUAL_CONTENT 0x10000
+
+/* Flags: for compatibility with older code */
+
+# define SMIME_TEXT PKCS7_TEXT
+# define SMIME_NOCERTS PKCS7_NOCERTS
+# define SMIME_NOSIGS PKCS7_NOSIGS
+# define SMIME_NOCHAIN PKCS7_NOCHAIN
+# define SMIME_NOINTERN PKCS7_NOINTERN
+# define SMIME_NOVERIFY PKCS7_NOVERIFY
+# define SMIME_DETACHED PKCS7_DETACHED
+# define SMIME_BINARY PKCS7_BINARY
+# define SMIME_NOATTR PKCS7_NOATTR
+
+/* CRLF ASCII canonicalisation */
+# define SMIME_ASCIICRLF 0x80000
+
+DECLARE_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL)
+
+int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data,
+ const EVP_MD *type, unsigned char *md,
+ unsigned int *len);
+# ifndef OPENSSL_NO_STDIO
+PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7);
+int i2d_PKCS7_fp(FILE *fp, const PKCS7 *p7);
+# endif
+DECLARE_ASN1_DUP_FUNCTION(PKCS7)
+PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7);
+int i2d_PKCS7_bio(BIO *bp, const PKCS7 *p7);
+int i2d_PKCS7_bio_stream(BIO *out, PKCS7 *p7, BIO *in, int flags);
+int PEM_write_bio_PKCS7_stream(BIO *out, PKCS7 *p7, BIO *in, int flags);
+
+DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNER_INFO)
+DECLARE_ASN1_FUNCTIONS(PKCS7_RECIP_INFO)
+DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNED)
+DECLARE_ASN1_FUNCTIONS(PKCS7_ENC_CONTENT)
+DECLARE_ASN1_FUNCTIONS(PKCS7_ENVELOPE)
+DECLARE_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE)
+DECLARE_ASN1_FUNCTIONS(PKCS7_DIGEST)
+DECLARE_ASN1_FUNCTIONS(PKCS7_ENCRYPT)
+DECLARE_ASN1_FUNCTIONS(PKCS7)
+PKCS7 *PKCS7_new_ex(OSSL_LIB_CTX *libctx, const char *propq);
+
+DECLARE_ASN1_ITEM(PKCS7_ATTR_SIGN)
+DECLARE_ASN1_ITEM(PKCS7_ATTR_VERIFY)
+
+DECLARE_ASN1_NDEF_FUNCTION(PKCS7)
+DECLARE_ASN1_PRINT_FUNCTION(PKCS7)
+
+long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg);
+
+int PKCS7_type_is_other(PKCS7 *p7);
+int PKCS7_set_type(PKCS7 *p7, int type);
+int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other);
+int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data);
+int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
+ const EVP_MD *dgst);
+int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si);
+int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *p7i);
+int PKCS7_add_certificate(PKCS7 *p7, X509 *x509);
+int PKCS7_add_crl(PKCS7 *p7, X509_CRL *x509);
+int PKCS7_content_new(PKCS7 *p7, int nid);
+int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx,
+ BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si);
+int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
+ X509 *x509);
+
+BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio);
+int PKCS7_dataFinal(PKCS7 *p7, BIO *bio);
+BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert);
+
+PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509,
+ EVP_PKEY *pkey, const EVP_MD *dgst);
+X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si);
+int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md);
+STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7);
+
+PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509);
+void PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk,
+ X509_ALGOR **pdig, X509_ALGOR **psig);
+void PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc);
+int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri);
+int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509);
+int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher);
+int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7);
+
+PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx);
+ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7);
+ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk);
+int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int type,
+ void *data);
+int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
+ void *value);
+ASN1_TYPE *PKCS7_get_attribute(const PKCS7_SIGNER_INFO *si, int nid);
+ASN1_TYPE *PKCS7_get_signed_attribute(const PKCS7_SIGNER_INFO *si, int nid);
+int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
+ STACK_OF(X509_ATTRIBUTE) *sk);
+int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si,
+ STACK_OF(X509_ATTRIBUTE) *sk);
+
+PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+ BIO *data, int flags);
+PKCS7 *PKCS7_sign_ex(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+ BIO *data, int flags, OSSL_LIB_CTX *libctx,
+ const char *propq);
+
+PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7,
+ X509 *signcert, EVP_PKEY *pkey,
+ const EVP_MD *md, int flags);
+
+int PKCS7_final(PKCS7 *p7, BIO *data, int flags);
+int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
+ BIO *indata, BIO *out, int flags);
+STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs,
+ int flags);
+PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
+ int flags);
+PKCS7 *PKCS7_encrypt_ex(STACK_OF(X509) *certs, BIO *in,
+ const EVP_CIPHER *cipher, int flags,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data,
+ int flags);
+
+int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si,
+ STACK_OF(X509_ALGOR) *cap);
+STACK_OF(X509_ALGOR) *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si);
+int PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *sk, int nid, int arg);
+
+int PKCS7_add_attrib_content_type(PKCS7_SIGNER_INFO *si, ASN1_OBJECT *coid);
+int PKCS7_add0_attrib_signing_time(PKCS7_SIGNER_INFO *si, ASN1_TIME *t);
+int PKCS7_add1_attrib_digest(PKCS7_SIGNER_INFO *si,
+ const unsigned char *md, int mdlen);
+
+int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags);
+PKCS7 *SMIME_read_PKCS7_ex(BIO *bio, BIO **bcont, PKCS7 **p7);
+PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont);
+
+BIO *BIO_new_PKCS7(BIO *out, PKCS7 *p7);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/pkcs7err.h b/include/openssl/pkcs7err.h
index 02e0299a3cec..ceb1a5019867 100644
--- a/include/openssl/pkcs7err.h
+++ b/include/openssl/pkcs7err.h
@@ -1,62 +1,22 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_PKCS7ERR_H
-# define HEADER_PKCS7ERR_H
+#ifndef OPENSSL_PKCS7ERR_H
+# define OPENSSL_PKCS7ERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_PKCS7_strings(void);
-/*
- * PKCS7 function codes.
- */
-# define PKCS7_F_DO_PKCS7_SIGNED_ATTRIB 136
-# define PKCS7_F_PKCS7_ADD0_ATTRIB_SIGNING_TIME 135
-# define PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP 118
-# define PKCS7_F_PKCS7_ADD_CERTIFICATE 100
-# define PKCS7_F_PKCS7_ADD_CRL 101
-# define PKCS7_F_PKCS7_ADD_RECIPIENT_INFO 102
-# define PKCS7_F_PKCS7_ADD_SIGNATURE 131
-# define PKCS7_F_PKCS7_ADD_SIGNER 103
-# define PKCS7_F_PKCS7_BIO_ADD_DIGEST 125
-# define PKCS7_F_PKCS7_COPY_EXISTING_DIGEST 138
-# define PKCS7_F_PKCS7_CTRL 104
-# define PKCS7_F_PKCS7_DATADECODE 112
-# define PKCS7_F_PKCS7_DATAFINAL 128
-# define PKCS7_F_PKCS7_DATAINIT 105
-# define PKCS7_F_PKCS7_DATAVERIFY 107
-# define PKCS7_F_PKCS7_DECRYPT 114
-# define PKCS7_F_PKCS7_DECRYPT_RINFO 133
-# define PKCS7_F_PKCS7_ENCODE_RINFO 132
-# define PKCS7_F_PKCS7_ENCRYPT 115
-# define PKCS7_F_PKCS7_FINAL 134
-# define PKCS7_F_PKCS7_FIND_DIGEST 127
-# define PKCS7_F_PKCS7_GET0_SIGNERS 124
-# define PKCS7_F_PKCS7_RECIP_INFO_SET 130
-# define PKCS7_F_PKCS7_SET_CIPHER 108
-# define PKCS7_F_PKCS7_SET_CONTENT 109
-# define PKCS7_F_PKCS7_SET_DIGEST 126
-# define PKCS7_F_PKCS7_SET_TYPE 110
-# define PKCS7_F_PKCS7_SIGN 116
-# define PKCS7_F_PKCS7_SIGNATUREVERIFY 113
-# define PKCS7_F_PKCS7_SIGNER_INFO_SET 129
-# define PKCS7_F_PKCS7_SIGNER_INFO_SIGN 139
-# define PKCS7_F_PKCS7_SIGN_ADD_SIGNER 137
-# define PKCS7_F_PKCS7_SIMPLE_SMIMECAP 119
-# define PKCS7_F_PKCS7_VERIFY 117
/*
* PKCS7 reason codes.
diff --git a/include/openssl/prov_ssl.h b/include/openssl/prov_ssl.h
new file mode 100644
index 000000000000..d3e0896c8e6f
--- /dev/null
+++ b/include/openssl/prov_ssl.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_PROV_SSL_H
+# define OPENSSL_PROV_SSL_H
+# pragma once
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/* SSL/TLS related defines useful to providers */
+
+# define SSL_MAX_MASTER_KEY_LENGTH 48
+
+# define SSL3_VERSION 0x0300
+# define TLS1_VERSION 0x0301
+# define TLS1_1_VERSION 0x0302
+# define TLS1_2_VERSION 0x0303
+# define TLS1_3_VERSION 0x0304
+# define DTLS1_VERSION 0xFEFF
+# define DTLS1_2_VERSION 0xFEFD
+# define DTLS1_BAD_VER 0x0100
+
+# ifdef __cplusplus
+}
+# endif
+#endif /* OPENSSL_PROV_SSL_H */
diff --git a/include/openssl/proverr.h b/include/openssl/proverr.h
new file mode 100644
index 000000000000..ad67a8f89727
--- /dev/null
+++ b/include/openssl/proverr.h
@@ -0,0 +1,148 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_PROVERR_H
+# define OPENSSL_PROVERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
+
+
+
+/*
+ * PROV reason codes.
+ */
+# define PROV_R_ADDITIONAL_INPUT_TOO_LONG 184
+# define PROV_R_ALGORITHM_MISMATCH 173
+# define PROV_R_ALREADY_INSTANTIATED 185
+# define PROV_R_BAD_DECRYPT 100
+# define PROV_R_BAD_ENCODING 141
+# define PROV_R_BAD_LENGTH 142
+# define PROV_R_BAD_TLS_CLIENT_VERSION 161
+# define PROV_R_BN_ERROR 160
+# define PROV_R_CIPHER_OPERATION_FAILED 102
+# define PROV_R_DERIVATION_FUNCTION_INIT_FAILED 205
+# define PROV_R_DIGEST_NOT_ALLOWED 174
+# define PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK 186
+# define PROV_R_ERROR_INSTANTIATING_DRBG 188
+# define PROV_R_ERROR_RETRIEVING_ENTROPY 189
+# define PROV_R_ERROR_RETRIEVING_NONCE 190
+# define PROV_R_FAILED_DURING_DERIVATION 164
+# define PROV_R_FAILED_TO_CREATE_LOCK 180
+# define PROV_R_FAILED_TO_DECRYPT 162
+# define PROV_R_FAILED_TO_GENERATE_KEY 121
+# define PROV_R_FAILED_TO_GET_PARAMETER 103
+# define PROV_R_FAILED_TO_SET_PARAMETER 104
+# define PROV_R_FAILED_TO_SIGN 175
+# define PROV_R_FIPS_MODULE_CONDITIONAL_ERROR 227
+# define PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE 224
+# define PROV_R_FIPS_MODULE_IN_ERROR_STATE 225
+# define PROV_R_GENERATE_ERROR 191
+# define PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 165
+# define PROV_R_INDICATOR_INTEGRITY_FAILURE 210
+# define PROV_R_INSUFFICIENT_DRBG_STRENGTH 181
+# define PROV_R_INVALID_AAD 108
+# define PROV_R_INVALID_CONFIG_DATA 211
+# define PROV_R_INVALID_CONSTANT_LENGTH 157
+# define PROV_R_INVALID_CURVE 176
+# define PROV_R_INVALID_CUSTOM_LENGTH 111
+# define PROV_R_INVALID_DATA 115
+# define PROV_R_INVALID_DIGEST 122
+# define PROV_R_INVALID_DIGEST_LENGTH 166
+# define PROV_R_INVALID_DIGEST_SIZE 218
+# define PROV_R_INVALID_INPUT_LENGTH 230
+# define PROV_R_INVALID_ITERATION_COUNT 123
+# define PROV_R_INVALID_IV_LENGTH 109
+# define PROV_R_INVALID_KEY 158
+# define PROV_R_INVALID_KEY_LENGTH 105
+# define PROV_R_INVALID_MAC 151
+# define PROV_R_INVALID_MGF1_MD 167
+# define PROV_R_INVALID_MODE 125
+# define PROV_R_INVALID_OUTPUT_LENGTH 217
+# define PROV_R_INVALID_PADDING_MODE 168
+# define PROV_R_INVALID_PUBINFO 198
+# define PROV_R_INVALID_SALT_LENGTH 112
+# define PROV_R_INVALID_SEED_LENGTH 154
+# define PROV_R_INVALID_SIGNATURE_SIZE 179
+# define PROV_R_INVALID_STATE 212
+# define PROV_R_INVALID_TAG 110
+# define PROV_R_INVALID_TAG_LENGTH 118
+# define PROV_R_INVALID_UKM_LENGTH 200
+# define PROV_R_INVALID_X931_DIGEST 170
+# define PROV_R_IN_ERROR_STATE 192
+# define PROV_R_KEY_SETUP_FAILED 101
+# define PROV_R_KEY_SIZE_TOO_SMALL 171
+# define PROV_R_LENGTH_TOO_LARGE 202
+# define PROV_R_MISMATCHING_DOMAIN_PARAMETERS 203
+# define PROV_R_MISSING_CEK_ALG 144
+# define PROV_R_MISSING_CIPHER 155
+# define PROV_R_MISSING_CONFIG_DATA 213
+# define PROV_R_MISSING_CONSTANT 156
+# define PROV_R_MISSING_KEY 128
+# define PROV_R_MISSING_MAC 150
+# define PROV_R_MISSING_MESSAGE_DIGEST 129
+# define PROV_R_MISSING_OID 209
+# define PROV_R_MISSING_PASS 130
+# define PROV_R_MISSING_SALT 131
+# define PROV_R_MISSING_SECRET 132
+# define PROV_R_MISSING_SEED 140
+# define PROV_R_MISSING_SESSION_ID 133
+# define PROV_R_MISSING_TYPE 134
+# define PROV_R_MISSING_XCGHASH 135
+# define PROV_R_MODULE_INTEGRITY_FAILURE 214
+# define PROV_R_NOT_A_PRIVATE_KEY 221
+# define PROV_R_NOT_A_PUBLIC_KEY 220
+# define PROV_R_NOT_INSTANTIATED 193
+# define PROV_R_NOT_PARAMETERS 226
+# define PROV_R_NOT_SUPPORTED 136
+# define PROV_R_NOT_XOF_OR_INVALID_LENGTH 113
+# define PROV_R_NO_KEY_SET 114
+# define PROV_R_NO_PARAMETERS_SET 177
+# define PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 178
+# define PROV_R_OUTPUT_BUFFER_TOO_SMALL 106
+# define PROV_R_PARENT_CANNOT_GENERATE_RANDOM_NUMBERS 228
+# define PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED 187
+# define PROV_R_PARENT_LOCKING_NOT_ENABLED 182
+# define PROV_R_PARENT_STRENGTH_TOO_WEAK 194
+# define PROV_R_PATH_MUST_BE_ABSOLUTE 219
+# define PROV_R_PERSONALISATION_STRING_TOO_LONG 195
+# define PROV_R_PSS_SALTLEN_TOO_SMALL 172
+# define PROV_R_REQUEST_TOO_LARGE_FOR_DRBG 196
+# define PROV_R_REQUIRE_CTR_MODE_CIPHER 206
+# define PROV_R_RESEED_ERROR 197
+# define PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES 222
+# define PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT 229
+# define PROV_R_SELF_TEST_KAT_FAILURE 215
+# define PROV_R_SELF_TEST_POST_FAILURE 216
+# define PROV_R_TAG_NOT_NEEDED 120
+# define PROV_R_TAG_NOT_SET 119
+# define PROV_R_TOO_MANY_RECORDS 126
+# define PROV_R_UNABLE_TO_FIND_CIPHERS 207
+# define PROV_R_UNABLE_TO_GET_PARENT_STRENGTH 199
+# define PROV_R_UNABLE_TO_GET_PASSPHRASE 159
+# define PROV_R_UNABLE_TO_INITIALISE_CIPHERS 208
+# define PROV_R_UNABLE_TO_LOAD_SHA256 147
+# define PROV_R_UNABLE_TO_LOCK_PARENT 201
+# define PROV_R_UNABLE_TO_RESEED 204
+# define PROV_R_UNSUPPORTED_CEK_ALG 145
+# define PROV_R_UNSUPPORTED_KEY_SIZE 153
+# define PROV_R_UNSUPPORTED_MAC_TYPE 137
+# define PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS 152
+# define PROV_R_URI_AUTHORITY_UNSUPPORTED 223
+# define PROV_R_VALUE_ERROR 138
+# define PROV_R_WRONG_FINAL_BLOCK_LENGTH 107
+# define PROV_R_WRONG_OUTPUT_BUFFER_SIZE 139
+# define PROV_R_XOF_DIGESTS_NOT_ALLOWED 183
+# define PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE 148
+# define PROV_R_XTS_DUPLICATED_KEYS 149
+
+#endif
diff --git a/include/openssl/provider.h b/include/openssl/provider.h
new file mode 100644
index 000000000000..dc86ff5878c9
--- /dev/null
+++ b/include/openssl/provider.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_PROVIDER_H
+# define OPENSSL_PROVIDER_H
+# pragma once
+
+# include <openssl/core.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/* Set the default provider search path */
+int OSSL_PROVIDER_set_default_search_path(OSSL_LIB_CTX *, const char *path);
+
+/* Load and unload a provider */
+OSSL_PROVIDER *OSSL_PROVIDER_load(OSSL_LIB_CTX *, const char *name);
+OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *, const char *name,
+ int retain_fallbacks);
+int OSSL_PROVIDER_unload(OSSL_PROVIDER *prov);
+int OSSL_PROVIDER_available(OSSL_LIB_CTX *, const char *name);
+int OSSL_PROVIDER_do_all(OSSL_LIB_CTX *ctx,
+ int (*cb)(OSSL_PROVIDER *provider, void *cbdata),
+ void *cbdata);
+
+const OSSL_PARAM *OSSL_PROVIDER_gettable_params(const OSSL_PROVIDER *prov);
+int OSSL_PROVIDER_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[]);
+int OSSL_PROVIDER_self_test(const OSSL_PROVIDER *prov);
+int OSSL_PROVIDER_get_capabilities(const OSSL_PROVIDER *prov,
+ const char *capability,
+ OSSL_CALLBACK *cb,
+ void *arg);
+
+const OSSL_ALGORITHM *OSSL_PROVIDER_query_operation(const OSSL_PROVIDER *prov,
+ int operation_id,
+ int *no_cache);
+void OSSL_PROVIDER_unquery_operation(const OSSL_PROVIDER *prov,
+ int operation_id, const OSSL_ALGORITHM *algs);
+void *OSSL_PROVIDER_get0_provider_ctx(const OSSL_PROVIDER *prov);
+const OSSL_DISPATCH *OSSL_PROVIDER_get0_dispatch(const OSSL_PROVIDER *prov);
+
+/* Add a built in providers */
+int OSSL_PROVIDER_add_builtin(OSSL_LIB_CTX *, const char *name,
+ OSSL_provider_init_fn *init_fn);
+
+/* Information */
+const char *OSSL_PROVIDER_get0_name(const OSSL_PROVIDER *prov);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/include/openssl/rand.h b/include/openssl/rand.h
index 38a2a2718f8b..ad3054fd575f 100644
--- a/include/openssl/rand.h
+++ b/include/openssl/rand.h
@@ -1,24 +1,42 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_RAND_H
-# define HEADER_RAND_H
+#ifndef OPENSSL_RAND_H
+# define OPENSSL_RAND_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_RAND_H
+# endif
# include <stdlib.h>
-# include <openssl/ossl_typ.h>
+# include <openssl/types.h>
# include <openssl/e_os2.h>
# include <openssl/randerr.h>
+# include <openssl/evp.h>
#ifdef __cplusplus
extern "C" {
#endif
+/*
+ * Default security strength (in the sense of [NIST SP 800-90Ar1])
+ *
+ * NIST SP 800-90Ar1 supports the strength of the DRBG being smaller than that
+ * of the cipher by collecting less entropy. The current DRBG implementation
+ * does not take RAND_DRBG_STRENGTH into account and sets the strength of the
+ * DRBG to that of the cipher.
+ */
+# define RAND_DRBG_STRENGTH 256
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
struct rand_meth_st {
int (*seed) (const void *buf, int num);
int (*bytes) (unsigned char *buf, int num);
@@ -28,26 +46,53 @@ struct rand_meth_st {
int (*status) (void);
};
-int RAND_set_rand_method(const RAND_METHOD *meth);
-const RAND_METHOD *RAND_get_rand_method(void);
-# ifndef OPENSSL_NO_ENGINE
-int RAND_set_rand_engine(ENGINE *engine);
-# endif
+OSSL_DEPRECATEDIN_3_0 int RAND_set_rand_method(const RAND_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 const RAND_METHOD *RAND_get_rand_method(void);
+# ifndef OPENSSL_NO_ENGINE
+OSSL_DEPRECATEDIN_3_0 int RAND_set_rand_engine(ENGINE *engine);
+# endif
-RAND_METHOD *RAND_OpenSSL(void);
+OSSL_DEPRECATEDIN_3_0 RAND_METHOD *RAND_OpenSSL(void);
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
-# if OPENSSL_API_COMPAT < 0x10100000L
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
# define RAND_cleanup() while(0) continue
# endif
int RAND_bytes(unsigned char *buf, int num);
int RAND_priv_bytes(unsigned char *buf, int num);
-DEPRECATEDIN_1_1_0(int RAND_pseudo_bytes(unsigned char *buf, int num))
+
+/*
+ * Equivalent of RAND_priv_bytes() but additionally taking an OSSL_LIB_CTX and
+ * a strength.
+ */
+int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num,
+ unsigned int strength);
+
+/*
+ * Equivalent of RAND_bytes() but additionally taking an OSSL_LIB_CTX and
+ * a strength.
+ */
+int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num,
+ unsigned int strength);
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 int RAND_pseudo_bytes(unsigned char *buf, int num);
+# endif
+
+EVP_RAND_CTX *RAND_get0_primary(OSSL_LIB_CTX *ctx);
+EVP_RAND_CTX *RAND_get0_public(OSSL_LIB_CTX *ctx);
+EVP_RAND_CTX *RAND_get0_private(OSSL_LIB_CTX *ctx);
+
+int RAND_set_DRBG_type(OSSL_LIB_CTX *ctx, const char *drbg, const char *propq,
+ const char *cipher, const char *digest);
+int RAND_set_seed_source_type(OSSL_LIB_CTX *ctx, const char *seed,
+ const char *propq);
void RAND_seed(const void *buf, int num);
void RAND_keep_random_devices_open(int keep);
# if defined(__ANDROID__) && defined(__NDK_FPABI__)
-__NDK_FPABI__ /* __attribute__((pcs("aapcs"))) on ARM */
+__NDK_FPABI__ /* __attribute__((pcs("aapcs"))) on ARM */
# endif
void RAND_add(const void *buf, int num, double randomness);
int RAND_load_file(const char *file, long max_bytes);
@@ -65,11 +110,12 @@ int RAND_poll(void);
# if defined(_WIN32) && (defined(BASETYPES) || defined(_WINDEF_H))
/* application has to include <windows.h> in order to use these */
-DEPRECATEDIN_1_1_0(void RAND_screen(void))
-DEPRECATEDIN_1_1_0(int RAND_event(UINT, WPARAM, LPARAM))
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 void RAND_screen(void);
+OSSL_DEPRECATEDIN_1_1_0 int RAND_event(UINT, WPARAM, LPARAM);
+# endif
# endif
-
#ifdef __cplusplus
}
#endif
diff --git a/include/openssl/rand_drbg.h b/include/openssl/rand_drbg.h
deleted file mode 100644
index 45b731b73c26..000000000000
--- a/include/openssl/rand_drbg.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_DRBG_RAND_H
-# define HEADER_DRBG_RAND_H
-
-# include <time.h>
-# include <openssl/ossl_typ.h>
-# include <openssl/obj_mac.h>
-
-/*
- * RAND_DRBG flags
- *
- * Note: if new flags are added, the constant `rand_drbg_used_flags`
- * in drbg_lib.c needs to be updated accordingly.
- */
-
-/* In CTR mode, disable derivation function ctr_df */
-# define RAND_DRBG_FLAG_CTR_NO_DF 0x1
-
-
-# if OPENSSL_API_COMPAT < 0x10200000L
-/* This #define was replaced by an internal constant and should not be used. */
-# define RAND_DRBG_USED_FLAGS (RAND_DRBG_FLAG_CTR_NO_DF)
-# endif
-
-/*
- * Default security strength (in the sense of [NIST SP 800-90Ar1])
- *
- * NIST SP 800-90Ar1 supports the strength of the DRBG being smaller than that
- * of the cipher by collecting less entropy. The current DRBG implementation
- * does not take RAND_DRBG_STRENGTH into account and sets the strength of the
- * DRBG to that of the cipher.
- *
- * RAND_DRBG_STRENGTH is currently only used for the legacy RAND
- * implementation.
- *
- * Currently supported ciphers are: NID_aes_128_ctr, NID_aes_192_ctr and
- * NID_aes_256_ctr
- */
-# define RAND_DRBG_STRENGTH 256
-/* Default drbg type */
-# define RAND_DRBG_TYPE NID_aes_256_ctr
-/* Default drbg flags */
-# define RAND_DRBG_FLAGS 0
-
-
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-/*
- * Object lifetime functions.
- */
-RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent);
-RAND_DRBG *RAND_DRBG_secure_new(int type, unsigned int flags, RAND_DRBG *parent);
-int RAND_DRBG_set(RAND_DRBG *drbg, int type, unsigned int flags);
-int RAND_DRBG_set_defaults(int type, unsigned int flags);
-int RAND_DRBG_instantiate(RAND_DRBG *drbg,
- const unsigned char *pers, size_t perslen);
-int RAND_DRBG_uninstantiate(RAND_DRBG *drbg);
-void RAND_DRBG_free(RAND_DRBG *drbg);
-
-/*
- * Object "use" functions.
- */
-int RAND_DRBG_reseed(RAND_DRBG *drbg,
- const unsigned char *adin, size_t adinlen,
- int prediction_resistance);
-int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
- int prediction_resistance,
- const unsigned char *adin, size_t adinlen);
-int RAND_DRBG_bytes(RAND_DRBG *drbg, unsigned char *out, size_t outlen);
-
-int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, unsigned int interval);
-int RAND_DRBG_set_reseed_time_interval(RAND_DRBG *drbg, time_t interval);
-
-int RAND_DRBG_set_reseed_defaults(
- unsigned int master_reseed_interval,
- unsigned int slave_reseed_interval,
- time_t master_reseed_time_interval,
- time_t slave_reseed_time_interval
- );
-
-RAND_DRBG *RAND_DRBG_get0_master(void);
-RAND_DRBG *RAND_DRBG_get0_public(void);
-RAND_DRBG *RAND_DRBG_get0_private(void);
-
-/*
- * EXDATA
- */
-# define RAND_DRBG_get_ex_new_index(l, p, newf, dupf, freef) \
- CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DRBG, l, p, newf, dupf, freef)
-int RAND_DRBG_set_ex_data(RAND_DRBG *drbg, int idx, void *arg);
-void *RAND_DRBG_get_ex_data(const RAND_DRBG *drbg, int idx);
-
-/*
- * Callback function typedefs
- */
-typedef size_t (*RAND_DRBG_get_entropy_fn)(RAND_DRBG *drbg,
- unsigned char **pout,
- int entropy, size_t min_len,
- size_t max_len,
- int prediction_resistance);
-typedef void (*RAND_DRBG_cleanup_entropy_fn)(RAND_DRBG *ctx,
- unsigned char *out, size_t outlen);
-typedef size_t (*RAND_DRBG_get_nonce_fn)(RAND_DRBG *drbg, unsigned char **pout,
- int entropy, size_t min_len,
- size_t max_len);
-typedef void (*RAND_DRBG_cleanup_nonce_fn)(RAND_DRBG *drbg,
- unsigned char *out, size_t outlen);
-
-int RAND_DRBG_set_callbacks(RAND_DRBG *drbg,
- RAND_DRBG_get_entropy_fn get_entropy,
- RAND_DRBG_cleanup_entropy_fn cleanup_entropy,
- RAND_DRBG_get_nonce_fn get_nonce,
- RAND_DRBG_cleanup_nonce_fn cleanup_nonce);
-
-
-# ifdef __cplusplus
-}
-# endif
-
-#endif
diff --git a/include/openssl/randerr.h b/include/openssl/randerr.h
index 79d57905e3cb..b5e08e4362de 100644
--- a/include/openssl/randerr.h
+++ b/include/openssl/randerr.h
@@ -1,54 +1,22 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_RANDERR_H
-# define HEADER_RANDERR_H
+#ifndef OPENSSL_RANDERR_H
+# define OPENSSL_RANDERR_H
+# pragma once
+# include <openssl/opensslconf.h>
# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_RAND_strings(void);
-/*
- * RAND function codes.
- */
-# define RAND_F_DATA_COLLECT_METHOD 127
-# define RAND_F_DRBG_BYTES 101
-# define RAND_F_DRBG_GET_ENTROPY 105
-# define RAND_F_DRBG_SETUP 117
-# define RAND_F_GET_ENTROPY 106
-# define RAND_F_RAND_BYTES 100
-# define RAND_F_RAND_DRBG_ENABLE_LOCKING 119
-# define RAND_F_RAND_DRBG_GENERATE 107
-# define RAND_F_RAND_DRBG_GET_ENTROPY 120
-# define RAND_F_RAND_DRBG_GET_NONCE 123
-# define RAND_F_RAND_DRBG_INSTANTIATE 108
-# define RAND_F_RAND_DRBG_NEW 109
-# define RAND_F_RAND_DRBG_RESEED 110
-# define RAND_F_RAND_DRBG_RESTART 102
-# define RAND_F_RAND_DRBG_SET 104
-# define RAND_F_RAND_DRBG_SET_DEFAULTS 121
-# define RAND_F_RAND_DRBG_UNINSTANTIATE 118
-# define RAND_F_RAND_LOAD_FILE 111
-# define RAND_F_RAND_POOL_ACQUIRE_ENTROPY 122
-# define RAND_F_RAND_POOL_ADD 103
-# define RAND_F_RAND_POOL_ADD_BEGIN 113
-# define RAND_F_RAND_POOL_ADD_END 114
-# define RAND_F_RAND_POOL_ATTACH 124
-# define RAND_F_RAND_POOL_BYTES_NEEDED 115
-# define RAND_F_RAND_POOL_GROW 125
-# define RAND_F_RAND_POOL_NEW 116
-# define RAND_F_RAND_PSEUDO_BYTES 126
-# define RAND_F_RAND_WRITE_FILE 112
/*
* RAND reason codes.
@@ -71,6 +39,7 @@ int ERR_load_RAND_strings(void);
# define RAND_R_FUNC_NOT_IMPLEMENTED 101
# define RAND_R_FWRITE_ERROR 123
# define RAND_R_GENERATE_ERROR 112
+# define RAND_R_INSUFFICIENT_DRBG_STRENGTH 139
# define RAND_R_INTERNAL_ERROR 113
# define RAND_R_IN_ERROR_STATE 114
# define RAND_R_NOT_A_REGULAR_FILE 122
@@ -88,6 +57,11 @@ int ERR_load_RAND_strings(void);
# define RAND_R_SELFTEST_FAILURE 119
# define RAND_R_TOO_LITTLE_NONCE_REQUESTED 135
# define RAND_R_TOO_MUCH_NONCE_REQUESTED 136
+# define RAND_R_UNABLE_TO_CREATE_DRBG 143
+# define RAND_R_UNABLE_TO_FETCH_DRBG 144
+# define RAND_R_UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER 141
+# define RAND_R_UNABLE_TO_GET_PARENT_STRENGTH 138
+# define RAND_R_UNABLE_TO_LOCK_PARENT 140
# define RAND_R_UNSUPPORTED_DRBG_FLAGS 132
# define RAND_R_UNSUPPORTED_DRBG_TYPE 120
diff --git a/include/openssl/rc2.h b/include/openssl/rc2.h
index 585f9e4c3806..ff633fd80f16 100644
--- a/include/openssl/rc2.h
+++ b/include/openssl/rc2.h
@@ -1,51 +1,68 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_RC2_H
-# define HEADER_RC2_H
+#ifndef OPENSSL_RC2_H
+# define OPENSSL_RC2_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_RC2_H
+# endif
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_RC2
-# ifdef __cplusplus
+# ifdef __cplusplus
extern "C" {
-# endif
+# endif
-typedef unsigned int RC2_INT;
+# define RC2_BLOCK 8
+# define RC2_KEY_LENGTH 16
-# define RC2_ENCRYPT 1
-# define RC2_DECRYPT 0
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+typedef unsigned int RC2_INT;
-# define RC2_BLOCK 8
-# define RC2_KEY_LENGTH 16
+# define RC2_ENCRYPT 1
+# define RC2_DECRYPT 0
typedef struct rc2_key_st {
RC2_INT data[64];
} RC2_KEY;
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 void RC2_set_key(RC2_KEY *key, int len,
+ const unsigned char *data, int bits);
+OSSL_DEPRECATEDIN_3_0 void RC2_ecb_encrypt(const unsigned char *in,
+ unsigned char *out, RC2_KEY *key,
+ int enc);
+OSSL_DEPRECATEDIN_3_0 void RC2_encrypt(unsigned long *data, RC2_KEY *key);
+OSSL_DEPRECATEDIN_3_0 void RC2_decrypt(unsigned long *data, RC2_KEY *key);
+OSSL_DEPRECATEDIN_3_0 void RC2_cbc_encrypt(const unsigned char *in,
+ unsigned char *out, long length,
+ RC2_KEY *ks, unsigned char *iv,
+ int enc);
+OSSL_DEPRECATEDIN_3_0 void RC2_cfb64_encrypt(const unsigned char *in,
+ unsigned char *out, long length,
+ RC2_KEY *schedule,
+ unsigned char *ivec,
+ int *num, int enc);
+OSSL_DEPRECATEDIN_3_0 void RC2_ofb64_encrypt(const unsigned char *in,
+ unsigned char *out, long length,
+ RC2_KEY *schedule,
+ unsigned char *ivec,
+ int *num);
+# endif
-void RC2_set_key(RC2_KEY *key, int len, const unsigned char *data, int bits);
-void RC2_ecb_encrypt(const unsigned char *in, unsigned char *out,
- RC2_KEY *key, int enc);
-void RC2_encrypt(unsigned long *data, RC2_KEY *key);
-void RC2_decrypt(unsigned long *data, RC2_KEY *key);
-void RC2_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
- RC2_KEY *ks, unsigned char *iv, int enc);
-void RC2_cfb64_encrypt(const unsigned char *in, unsigned char *out,
- long length, RC2_KEY *schedule, unsigned char *ivec,
- int *num, int enc);
-void RC2_ofb64_encrypt(const unsigned char *in, unsigned char *out,
- long length, RC2_KEY *schedule, unsigned char *ivec,
- int *num);
-
-# ifdef __cplusplus
+# ifdef __cplusplus
}
-# endif
+# endif
# endif
#endif
diff --git a/include/openssl/rc4.h b/include/openssl/rc4.h
index 86803b37fbe0..600b2885df1b 100644
--- a/include/openssl/rc4.h
+++ b/include/openssl/rc4.h
@@ -1,36 +1,47 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_RC4_H
-# define HEADER_RC4_H
+#ifndef OPENSSL_RC4_H
+# define OPENSSL_RC4_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_RC4_H
+# endif
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_RC4
-# include <stddef.h>
-#ifdef __cplusplus
+# include <stddef.h>
+# ifdef __cplusplus
extern "C" {
-#endif
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
typedef struct rc4_key_st {
RC4_INT x, y;
RC4_INT data[256];
} RC4_KEY;
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 const char *RC4_options(void);
+OSSL_DEPRECATEDIN_3_0 void RC4_set_key(RC4_KEY *key, int len,
+ const unsigned char *data);
+OSSL_DEPRECATEDIN_3_0 void RC4(RC4_KEY *key, size_t len,
+ const unsigned char *indata,
+ unsigned char *outdata);
+# endif
-const char *RC4_options(void);
-void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data);
-void RC4(RC4_KEY *key, size_t len, const unsigned char *indata,
- unsigned char *outdata);
-
-# ifdef __cplusplus
+# ifdef __cplusplus
}
-# endif
+# endif
# endif
#endif
diff --git a/include/openssl/rc5.h b/include/openssl/rc5.h
index 793f88e4e814..de833523102a 100644
--- a/include/openssl/rc5.h
+++ b/include/openssl/rc5.h
@@ -1,63 +1,79 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_RC5_H
-# define HEADER_RC5_H
+#ifndef OPENSSL_RC5_H
+# define OPENSSL_RC5_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_RC5_H
+# endif
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_RC5
-# ifdef __cplusplus
+# ifdef __cplusplus
extern "C" {
-# endif
+# endif
-# define RC5_ENCRYPT 1
-# define RC5_DECRYPT 0
+# define RC5_32_BLOCK 8
+# define RC5_32_KEY_LENGTH 16/* This is a default, max is 255 */
-# define RC5_32_INT unsigned int
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define RC5_ENCRYPT 1
+# define RC5_DECRYPT 0
-# define RC5_32_BLOCK 8
-# define RC5_32_KEY_LENGTH 16/* This is a default, max is 255 */
+# define RC5_32_INT unsigned int
/*
* This are the only values supported. Tweak the code if you want more The
* most supported modes will be RC5-32/12/16 RC5-32/16/8
*/
-# define RC5_8_ROUNDS 8
-# define RC5_12_ROUNDS 12
-# define RC5_16_ROUNDS 16
+# define RC5_8_ROUNDS 8
+# define RC5_12_ROUNDS 12
+# define RC5_16_ROUNDS 16
typedef struct rc5_key_st {
/* Number of rounds */
int rounds;
RC5_32_INT data[2 * (RC5_16_ROUNDS + 1)];
} RC5_32_KEY;
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int RC5_32_set_key(RC5_32_KEY *key, int len,
+ const unsigned char *data,
+ int rounds);
+OSSL_DEPRECATEDIN_3_0 void RC5_32_ecb_encrypt(const unsigned char *in,
+ unsigned char *out,
+ RC5_32_KEY *key,
+ int enc);
+OSSL_DEPRECATEDIN_3_0 void RC5_32_encrypt(unsigned long *data, RC5_32_KEY *key);
+OSSL_DEPRECATEDIN_3_0 void RC5_32_decrypt(unsigned long *data, RC5_32_KEY *key);
+OSSL_DEPRECATEDIN_3_0 void RC5_32_cbc_encrypt(const unsigned char *in,
+ unsigned char *out, long length,
+ RC5_32_KEY *ks, unsigned char *iv,
+ int enc);
+OSSL_DEPRECATEDIN_3_0 void RC5_32_cfb64_encrypt(const unsigned char *in,
+ unsigned char *out, long length,
+ RC5_32_KEY *schedule,
+ unsigned char *ivec, int *num,
+ int enc);
+OSSL_DEPRECATEDIN_3_0 void RC5_32_ofb64_encrypt(const unsigned char *in,
+ unsigned char *out, long length,
+ RC5_32_KEY *schedule,
+ unsigned char *ivec, int *num);
+# endif
-void RC5_32_set_key(RC5_32_KEY *key, int len, const unsigned char *data,
- int rounds);
-void RC5_32_ecb_encrypt(const unsigned char *in, unsigned char *out,
- RC5_32_KEY *key, int enc);
-void RC5_32_encrypt(unsigned long *data, RC5_32_KEY *key);
-void RC5_32_decrypt(unsigned long *data, RC5_32_KEY *key);
-void RC5_32_cbc_encrypt(const unsigned char *in, unsigned char *out,
- long length, RC5_32_KEY *ks, unsigned char *iv,
- int enc);
-void RC5_32_cfb64_encrypt(const unsigned char *in, unsigned char *out,
- long length, RC5_32_KEY *schedule,
- unsigned char *ivec, int *num, int enc);
-void RC5_32_ofb64_encrypt(const unsigned char *in, unsigned char *out,
- long length, RC5_32_KEY *schedule,
- unsigned char *ivec, int *num);
-
-# ifdef __cplusplus
+# ifdef __cplusplus
}
-# endif
+# endif
# endif
#endif
diff --git a/include/openssl/ripemd.h b/include/openssl/ripemd.h
index c42026aa42fe..900ee317b928 100644
--- a/include/openssl/ripemd.h
+++ b/include/openssl/ripemd.h
@@ -1,29 +1,38 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_RIPEMD_H
-# define HEADER_RIPEMD_H
+#ifndef OPENSSL_RIPEMD_H
+# define OPENSSL_RIPEMD_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_RIPEMD_H
+# endif
# include <openssl/opensslconf.h>
-#ifndef OPENSSL_NO_RMD160
-# include <openssl/e_os2.h>
-# include <stddef.h>
-# ifdef __cplusplus
+# ifndef OPENSSL_NO_RMD160
+# include <openssl/e_os2.h>
+# include <stddef.h>
+
+# define RIPEMD160_DIGEST_LENGTH 20
+
+# ifdef __cplusplus
extern "C" {
-# endif
+# endif
+# if !defined(OPENSSL_NO_DEPRECATED_3_0)
-# define RIPEMD160_LONG unsigned int
+# define RIPEMD160_LONG unsigned int
-# define RIPEMD160_CBLOCK 64
-# define RIPEMD160_LBLOCK (RIPEMD160_CBLOCK/4)
-# define RIPEMD160_DIGEST_LENGTH 20
+# define RIPEMD160_CBLOCK 64
+# define RIPEMD160_LBLOCK (RIPEMD160_CBLOCK/4)
typedef struct RIPEMD160state_st {
RIPEMD160_LONG A, B, C, D, E;
@@ -31,17 +40,20 @@ typedef struct RIPEMD160state_st {
RIPEMD160_LONG data[RIPEMD160_LBLOCK];
unsigned int num;
} RIPEMD160_CTX;
-
-int RIPEMD160_Init(RIPEMD160_CTX *c);
-int RIPEMD160_Update(RIPEMD160_CTX *c, const void *data, size_t len);
-int RIPEMD160_Final(unsigned char *md, RIPEMD160_CTX *c);
-unsigned char *RIPEMD160(const unsigned char *d, size_t n, unsigned char *md);
-void RIPEMD160_Transform(RIPEMD160_CTX *c, const unsigned char *b);
-
-# ifdef __cplusplus
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int RIPEMD160_Init(RIPEMD160_CTX *c);
+OSSL_DEPRECATEDIN_3_0 int RIPEMD160_Update(RIPEMD160_CTX *c, const void *data,
+ size_t len);
+OSSL_DEPRECATEDIN_3_0 int RIPEMD160_Final(unsigned char *md, RIPEMD160_CTX *c);
+OSSL_DEPRECATEDIN_3_0 unsigned char *RIPEMD160(const unsigned char *d, size_t n,
+ unsigned char *md);
+OSSL_DEPRECATEDIN_3_0 void RIPEMD160_Transform(RIPEMD160_CTX *c,
+ const unsigned char *b);
+# endif
+
+# ifdef __cplusplus
}
+# endif
# endif
-# endif
-
-
#endif
diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h
index 5e76365c0dfe..a55c9727c6b9 100644
--- a/include/openssl/rsa.h
+++ b/include/openssl/rsa.h
@@ -1,70 +1,75 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_RSA_H
-# define HEADER_RSA_H
+#ifndef OPENSSL_RSA_H
+# define OPENSSL_RSA_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_RSA_H
+# endif
# include <openssl/opensslconf.h>
-# ifndef OPENSSL_NO_RSA
# include <openssl/asn1.h>
# include <openssl/bio.h>
# include <openssl/crypto.h>
-# include <openssl/ossl_typ.h>
-# if OPENSSL_API_COMPAT < 0x10100000L
+# include <openssl/types.h>
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
# include <openssl/bn.h>
# endif
# include <openssl/rsaerr.h>
+# include <openssl/safestack.h>
+
# ifdef __cplusplus
extern "C" {
# endif
-/* The types RSA and RSA_METHOD are defined in ossl_typ.h */
-
# ifndef OPENSSL_RSA_MAX_MODULUS_BITS
# define OPENSSL_RSA_MAX_MODULUS_BITS 16384
# endif
-# define OPENSSL_RSA_FIPS_MIN_MODULUS_BITS 1024
+# define RSA_3 0x3L
+# define RSA_F4 0x10001L
-# ifndef OPENSSL_RSA_SMALL_MODULUS_BITS
-# define OPENSSL_RSA_SMALL_MODULUS_BITS 3072
-# endif
-# ifndef OPENSSL_RSA_MAX_PUBEXP_BITS
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+/* The types RSA and RSA_METHOD are defined in ossl_typ.h */
-/* exponent limit enforced for "large" modulus only */
-# define OPENSSL_RSA_MAX_PUBEXP_BITS 64
-# endif
+# define OPENSSL_RSA_FIPS_MIN_MODULUS_BITS 2048
-# define RSA_3 0x3L
-# define RSA_F4 0x10001L
+# ifndef OPENSSL_RSA_SMALL_MODULUS_BITS
+# define OPENSSL_RSA_SMALL_MODULUS_BITS 3072
+# endif
+/* exponent limit enforced for "large" modulus only */
+# ifndef OPENSSL_RSA_MAX_PUBEXP_BITS
+# define OPENSSL_RSA_MAX_PUBEXP_BITS 64
+# endif
/* based on RFC 8017 appendix A.1.2 */
-# define RSA_ASN1_VERSION_DEFAULT 0
-# define RSA_ASN1_VERSION_MULTI 1
-
-# define RSA_DEFAULT_PRIME_NUM 2
+# define RSA_ASN1_VERSION_DEFAULT 0
+# define RSA_ASN1_VERSION_MULTI 1
-# define RSA_METHOD_FLAG_NO_CHECK 0x0001/* don't check pub/private
- * match */
+# define RSA_DEFAULT_PRIME_NUM 2
-# define RSA_FLAG_CACHE_PUBLIC 0x0002
-# define RSA_FLAG_CACHE_PRIVATE 0x0004
-# define RSA_FLAG_BLINDING 0x0008
-# define RSA_FLAG_THREAD_SAFE 0x0010
+# define RSA_METHOD_FLAG_NO_CHECK 0x0001
+# define RSA_FLAG_CACHE_PUBLIC 0x0002
+# define RSA_FLAG_CACHE_PRIVATE 0x0004
+# define RSA_FLAG_BLINDING 0x0008
+# define RSA_FLAG_THREAD_SAFE 0x0010
/*
* This flag means the private key operations will be handled by rsa_mod_exp
* and that they do not depend on the private key components being present:
* for example a key stored in external hardware. Without this flag
* bn_mod_exp gets called when private key components are absent.
*/
-# define RSA_FLAG_EXT_PKEY 0x0020
+# define RSA_FLAG_EXT_PKEY 0x0020
/*
* new with 0.9.6j and 0.9.7b; the built-in
@@ -72,14 +77,14 @@ extern "C" {
* default (ignoring RSA_FLAG_BLINDING),
* but other engines might not need it
*/
-# define RSA_FLAG_NO_BLINDING 0x0080
-# if OPENSSL_API_COMPAT < 0x10100000L
+# define RSA_FLAG_NO_BLINDING 0x0080
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
/*
* Does nothing. Previously this switched off constant time behaviour.
*/
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
# define RSA_FLAG_NO_CONSTTIME 0x0000
# endif
-# if OPENSSL_API_COMPAT < 0x00908000L
/* deprecated name for the flag*/
/*
* new with 0.9.7h; the built-in RSA
@@ -89,18 +94,43 @@ extern "C" {
* faster variable sliding window method to
* be used for all exponents.
*/
+# ifndef OPENSSL_NO_DEPRECATED_0_9_8
# define RSA_FLAG_NO_EXP_CONSTTIME RSA_FLAG_NO_CONSTTIME
# endif
-# define EVP_PKEY_CTX_set_rsa_padding(ctx, pad) \
- RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_RSA_PADDING, pad, NULL)
-
-# define EVP_PKEY_CTX_get_rsa_padding(ctx, ppad) \
- RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_GET_RSA_PADDING, 0, ppad)
+/*-
+ * New with 3.0: use part of the flags to denote exact type of RSA key,
+ * some of which are limited to specific signature and encryption schemes.
+ * These different types share the same RSA structure, but indicate the
+ * use of certain fields in that structure.
+ * Currently known are:
+ * RSA - this is the "normal" unlimited RSA structure (typenum 0)
+ * RSASSA-PSS - indicates that the PSS parameters are used.
+ * RSAES-OAEP - no specific field used for the moment, but OAEP padding
+ * is expected. (currently unused)
+ *
+ * 4 bits allow for 16 types
+ */
+# define RSA_FLAG_TYPE_MASK 0xF000
+# define RSA_FLAG_TYPE_RSA 0x0000
+# define RSA_FLAG_TYPE_RSASSAPSS 0x1000
+# define RSA_FLAG_TYPE_RSAESOAEP 0x2000
+
+int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad_mode);
+int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad_mode);
+
+int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int saltlen);
+int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen);
+
+int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int bits);
+int EVP_PKEY_CTX_set1_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp);
+int EVP_PKEY_CTX_set_rsa_keygen_primes(EVP_PKEY_CTX *ctx, int primes);
+int EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(EVP_PKEY_CTX *ctx, int saltlen);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
+int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp);
+# endif
-# define EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, len) \
- RSA_pkey_ctx_ctrl(ctx, (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \
- EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL)
/* Salt length matches digest */
# define RSA_PSS_SALTLEN_DIGEST -1
/* Verify only: auto detect salt length */
@@ -110,58 +140,29 @@ extern "C" {
/* Old compatible max salt length for sign only */
# define RSA_PSS_SALTLEN_MAX_SIGN -2
-# define EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, len) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, \
- EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL)
-
-# define EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, plen) \
- RSA_pkey_ctx_ctrl(ctx, (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \
- EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, 0, plen)
-
-# define EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) \
- RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \
- EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL)
-
-# define EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp) \
- RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \
- EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp)
-
-# define EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, primes) \
- RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \
- EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES, primes, NULL)
-
-# define EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md) \
- RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \
- EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)(md))
-
-# define EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(ctx, md) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, \
- EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)(md))
-
-# define EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \
- EVP_PKEY_CTRL_RSA_OAEP_MD, 0, (void *)(md))
-
-# define EVP_PKEY_CTX_get_rsa_mgf1_md(ctx, pmd) \
- RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \
- EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void *)(pmd))
-
-# define EVP_PKEY_CTX_get_rsa_oaep_md(ctx, pmd) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \
- EVP_PKEY_CTRL_GET_RSA_OAEP_MD, 0, (void *)(pmd))
-
-# define EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, l, llen) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \
- EVP_PKEY_CTRL_RSA_OAEP_LABEL, llen, (void *)(l))
-
-# define EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, l) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \
- EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, 0, (void *)(l))
-
-# define EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx, md) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, \
- EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_MD, \
- 0, (void *)(md))
+int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
+int EVP_PKEY_CTX_set_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, const char *mdname,
+ const char *mdprops);
+int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
+int EVP_PKEY_CTX_get_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, char *name,
+ size_t namelen);
+int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
+int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md_name(EVP_PKEY_CTX *ctx,
+ const char *mdname);
+
+int EVP_PKEY_CTX_set_rsa_pss_keygen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
+int EVP_PKEY_CTX_set_rsa_pss_keygen_md_name(EVP_PKEY_CTX *ctx,
+ const char *mdname,
+ const char *mdprops);
+
+int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
+int EVP_PKEY_CTX_set_rsa_oaep_md_name(EVP_PKEY_CTX *ctx, const char *mdname,
+ const char *mdprops);
+int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
+int EVP_PKEY_CTX_get_rsa_oaep_md_name(EVP_PKEY_CTX *ctx, char *name,
+ size_t namelen);
+int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, void *label, int llen);
+int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char **label);
# define EVP_PKEY_CTRL_RSA_PADDING (EVP_PKEY_ALG_CTRL + 1)
# define EVP_PKEY_CTRL_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 2)
@@ -182,103 +183,134 @@ extern "C" {
# define EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES (EVP_PKEY_ALG_CTRL + 13)
-# define RSA_PKCS1_PADDING 1
-# define RSA_SSLV23_PADDING 2
-# define RSA_NO_PADDING 3
-# define RSA_PKCS1_OAEP_PADDING 4
-# define RSA_X931_PADDING 5
+# define RSA_PKCS1_PADDING 1
+# define RSA_NO_PADDING 3
+# define RSA_PKCS1_OAEP_PADDING 4
+# define RSA_X931_PADDING 5
+
/* EVP_PKEY_ only */
-# define RSA_PKCS1_PSS_PADDING 6
+# define RSA_PKCS1_PSS_PADDING 6
+# define RSA_PKCS1_WITH_TLS_PADDING 7
-# define RSA_PKCS1_PADDING_SIZE 11
+# define RSA_PKCS1_PADDING_SIZE 11
# define RSA_set_app_data(s,arg) RSA_set_ex_data(s,0,arg)
# define RSA_get_app_data(s) RSA_get_ex_data(s,0)
-RSA *RSA_new(void);
-RSA *RSA_new_method(ENGINE *engine);
-int RSA_bits(const RSA *rsa);
-int RSA_size(const RSA *rsa);
-int RSA_security_bits(const RSA *rsa);
-
-int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
-int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
-int RSA_set0_crt_params(RSA *r,BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);
-int RSA_set0_multi_prime_params(RSA *r, BIGNUM *primes[], BIGNUM *exps[],
- BIGNUM *coeffs[], int pnum);
-void RSA_get0_key(const RSA *r,
- const BIGNUM **n, const BIGNUM **e, const BIGNUM **d);
-void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q);
-int RSA_get_multi_prime_extra_count(const RSA *r);
-int RSA_get0_multi_prime_factors(const RSA *r, const BIGNUM *primes[]);
-void RSA_get0_crt_params(const RSA *r,
- const BIGNUM **dmp1, const BIGNUM **dmq1,
- const BIGNUM **iqmp);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 RSA *RSA_new(void);
+OSSL_DEPRECATEDIN_3_0 RSA *RSA_new_method(ENGINE *engine);
+OSSL_DEPRECATEDIN_3_0 int RSA_bits(const RSA *rsa);
+OSSL_DEPRECATEDIN_3_0 int RSA_size(const RSA *rsa);
+OSSL_DEPRECATEDIN_3_0 int RSA_security_bits(const RSA *rsa);
+
+OSSL_DEPRECATEDIN_3_0 int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
+OSSL_DEPRECATEDIN_3_0 int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
+OSSL_DEPRECATEDIN_3_0 int RSA_set0_crt_params(RSA *r,
+ BIGNUM *dmp1, BIGNUM *dmq1,
+ BIGNUM *iqmp);
+OSSL_DEPRECATEDIN_3_0 int RSA_set0_multi_prime_params(RSA *r,
+ BIGNUM *primes[],
+ BIGNUM *exps[],
+ BIGNUM *coeffs[],
+ int pnum);
+OSSL_DEPRECATEDIN_3_0 void RSA_get0_key(const RSA *r,
+ const BIGNUM **n, const BIGNUM **e,
+ const BIGNUM **d);
+OSSL_DEPRECATEDIN_3_0 void RSA_get0_factors(const RSA *r,
+ const BIGNUM **p, const BIGNUM **q);
+OSSL_DEPRECATEDIN_3_0 int RSA_get_multi_prime_extra_count(const RSA *r);
+OSSL_DEPRECATEDIN_3_0 int RSA_get0_multi_prime_factors(const RSA *r,
+ const BIGNUM *primes[]);
+OSSL_DEPRECATEDIN_3_0 void RSA_get0_crt_params(const RSA *r,
+ const BIGNUM **dmp1,
+ const BIGNUM **dmq1,
+ const BIGNUM **iqmp);
+OSSL_DEPRECATEDIN_3_0
int RSA_get0_multi_prime_crt_params(const RSA *r, const BIGNUM *exps[],
const BIGNUM *coeffs[]);
-const BIGNUM *RSA_get0_n(const RSA *d);
-const BIGNUM *RSA_get0_e(const RSA *d);
-const BIGNUM *RSA_get0_d(const RSA *d);
-const BIGNUM *RSA_get0_p(const RSA *d);
-const BIGNUM *RSA_get0_q(const RSA *d);
-const BIGNUM *RSA_get0_dmp1(const RSA *r);
-const BIGNUM *RSA_get0_dmq1(const RSA *r);
-const BIGNUM *RSA_get0_iqmp(const RSA *r);
-const RSA_PSS_PARAMS *RSA_get0_pss_params(const RSA *r);
-void RSA_clear_flags(RSA *r, int flags);
-int RSA_test_flags(const RSA *r, int flags);
-void RSA_set_flags(RSA *r, int flags);
-int RSA_get_version(RSA *r);
-ENGINE *RSA_get0_engine(const RSA *r);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *RSA_get0_n(const RSA *d);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *RSA_get0_e(const RSA *d);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *RSA_get0_d(const RSA *d);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *RSA_get0_p(const RSA *d);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *RSA_get0_q(const RSA *d);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *RSA_get0_dmp1(const RSA *r);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *RSA_get0_dmq1(const RSA *r);
+OSSL_DEPRECATEDIN_3_0 const BIGNUM *RSA_get0_iqmp(const RSA *r);
+OSSL_DEPRECATEDIN_3_0 const RSA_PSS_PARAMS *RSA_get0_pss_params(const RSA *r);
+OSSL_DEPRECATEDIN_3_0 void RSA_clear_flags(RSA *r, int flags);
+OSSL_DEPRECATEDIN_3_0 int RSA_test_flags(const RSA *r, int flags);
+OSSL_DEPRECATEDIN_3_0 void RSA_set_flags(RSA *r, int flags);
+OSSL_DEPRECATEDIN_3_0 int RSA_get_version(RSA *r);
+OSSL_DEPRECATEDIN_3_0 ENGINE *RSA_get0_engine(const RSA *r);
+# endif /* !OPENSSL_NO_DEPRECATED_3_0 */
+
+# define EVP_RSA_gen(bits) \
+ EVP_PKEY_Q_keygen(NULL, NULL, "RSA", (size_t)(0 + (bits)))
/* Deprecated version */
-DEPRECATEDIN_0_9_8(RSA *RSA_generate_key(int bits, unsigned long e, void
- (*callback) (int, int, void *),
- void *cb_arg))
+# ifndef OPENSSL_NO_DEPRECATED_0_9_8
+OSSL_DEPRECATEDIN_0_9_8 RSA *RSA_generate_key(int bits, unsigned long e, void
+ (*callback) (int, int, void *),
+ void *cb_arg);
+# endif
/* New version */
-int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e,
+ BN_GENCB *cb);
/* Multi-prime version */
-int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes,
- BIGNUM *e, BN_GENCB *cb);
-
-int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1,
- BIGNUM *q2, const BIGNUM *Xp1, const BIGNUM *Xp2,
- const BIGNUM *Xp, const BIGNUM *Xq1, const BIGNUM *Xq2,
- const BIGNUM *Xq, const BIGNUM *e, BN_GENCB *cb);
-int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e,
- BN_GENCB *cb);
-
-int RSA_check_key(const RSA *);
-int RSA_check_key_ex(const RSA *, BN_GENCB *cb);
+OSSL_DEPRECATEDIN_3_0 int RSA_generate_multi_prime_key(RSA *rsa, int bits,
+ int primes, BIGNUM *e,
+ BN_GENCB *cb);
+
+OSSL_DEPRECATEDIN_3_0
+int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2,
+ BIGNUM *q1, BIGNUM *q2,
+ const BIGNUM *Xp1, const BIGNUM *Xp2,
+ const BIGNUM *Xp, const BIGNUM *Xq1,
+ const BIGNUM *Xq2, const BIGNUM *Xq,
+ const BIGNUM *e, BN_GENCB *cb);
+OSSL_DEPRECATEDIN_3_0 int RSA_X931_generate_key_ex(RSA *rsa, int bits,
+ const BIGNUM *e,
+ BN_GENCB *cb);
+
+OSSL_DEPRECATEDIN_3_0 int RSA_check_key(const RSA *);
+OSSL_DEPRECATEDIN_3_0 int RSA_check_key_ex(const RSA *, BN_GENCB *cb);
/* next 4 return -1 on error */
-int RSA_public_encrypt(int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding);
-int RSA_private_encrypt(int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding);
-int RSA_public_decrypt(int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding);
-int RSA_private_decrypt(int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding);
-void RSA_free(RSA *r);
+OSSL_DEPRECATEDIN_3_0
+int RSA_public_encrypt(int flen, const unsigned char *from, unsigned char *to,
+ RSA *rsa, int padding);
+OSSL_DEPRECATEDIN_3_0
+int RSA_private_encrypt(int flen, const unsigned char *from, unsigned char *to,
+ RSA *rsa, int padding);
+OSSL_DEPRECATEDIN_3_0
+int RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to,
+ RSA *rsa, int padding);
+OSSL_DEPRECATEDIN_3_0
+int RSA_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
+ RSA *rsa, int padding);
+OSSL_DEPRECATEDIN_3_0 void RSA_free(RSA *r);
/* "up" the RSA object's reference count */
-int RSA_up_ref(RSA *r);
-
-int RSA_flags(const RSA *r);
+OSSL_DEPRECATEDIN_3_0 int RSA_up_ref(RSA *r);
+OSSL_DEPRECATEDIN_3_0 int RSA_flags(const RSA *r);
-void RSA_set_default_method(const RSA_METHOD *meth);
-const RSA_METHOD *RSA_get_default_method(void);
-const RSA_METHOD *RSA_null_method(void);
-const RSA_METHOD *RSA_get_method(const RSA *rsa);
-int RSA_set_method(RSA *rsa, const RSA_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 void RSA_set_default_method(const RSA_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 const RSA_METHOD *RSA_get_default_method(void);
+OSSL_DEPRECATEDIN_3_0 const RSA_METHOD *RSA_null_method(void);
+OSSL_DEPRECATEDIN_3_0 const RSA_METHOD *RSA_get_method(const RSA *rsa);
+OSSL_DEPRECATEDIN_3_0 int RSA_set_method(RSA *rsa, const RSA_METHOD *meth);
/* these are the actual RSA functions */
-const RSA_METHOD *RSA_PKCS1_OpenSSL(void);
+OSSL_DEPRECATEDIN_3_0 const RSA_METHOD *RSA_PKCS1_OpenSSL(void);
-int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2);
+DECLARE_ASN1_ENCODE_FUNCTIONS_name_attr(OSSL_DEPRECATEDIN_3_0,
+ RSA, RSAPublicKey)
+DECLARE_ASN1_ENCODE_FUNCTIONS_name_attr(OSSL_DEPRECATEDIN_3_0,
+ RSA, RSAPrivateKey)
+# endif /* !OPENSSL_NO_DEPRECATED_3_0 */
-DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPublicKey)
-DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPrivateKey)
+int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2);
struct rsa_pss_params_st {
X509_ALGOR *hashAlgorithm;
@@ -290,6 +322,7 @@ struct rsa_pss_params_st {
};
DECLARE_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
+DECLARE_ASN1_DUP_FUNCTION(RSA_PSS_PARAMS)
typedef struct rsa_oaep_params_st {
X509_ALGOR *hashFunc;
@@ -301,101 +334,119 @@ typedef struct rsa_oaep_params_st {
DECLARE_ASN1_FUNCTIONS(RSA_OAEP_PARAMS)
-# ifndef OPENSSL_NO_STDIO
-int RSA_print_fp(FILE *fp, const RSA *r, int offset);
-# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef OPENSSL_NO_STDIO
+OSSL_DEPRECATEDIN_3_0 int RSA_print_fp(FILE *fp, const RSA *r, int offset);
+# endif
-int RSA_print(BIO *bp, const RSA *r, int offset);
+OSSL_DEPRECATEDIN_3_0 int RSA_print(BIO *bp, const RSA *r, int offset);
/*
* The following 2 functions sign and verify a X509_SIG ASN1 object inside
* PKCS#1 padded RSA encryption
*/
-int RSA_sign(int type, const unsigned char *m, unsigned int m_length,
- unsigned char *sigret, unsigned int *siglen, RSA *rsa);
-int RSA_verify(int type, const unsigned char *m, unsigned int m_length,
- const unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
+OSSL_DEPRECATEDIN_3_0 int RSA_sign(int type, const unsigned char *m,
+ unsigned int m_length, unsigned char *sigret,
+ unsigned int *siglen, RSA *rsa);
+OSSL_DEPRECATEDIN_3_0 int RSA_verify(int type, const unsigned char *m,
+ unsigned int m_length,
+ const unsigned char *sigbuf,
+ unsigned int siglen, RSA *rsa);
/*
* The following 2 function sign and verify a ASN1_OCTET_STRING object inside
* PKCS#1 padded RSA encryption
*/
+OSSL_DEPRECATEDIN_3_0
int RSA_sign_ASN1_OCTET_STRING(int type,
const unsigned char *m, unsigned int m_length,
unsigned char *sigret, unsigned int *siglen,
RSA *rsa);
-int RSA_verify_ASN1_OCTET_STRING(int type, const unsigned char *m,
- unsigned int m_length, unsigned char *sigbuf,
- unsigned int siglen, RSA *rsa);
+OSSL_DEPRECATEDIN_3_0
+int RSA_verify_ASN1_OCTET_STRING(int type,
+ const unsigned char *m, unsigned int m_length,
+ unsigned char *sigbuf, unsigned int siglen,
+ RSA *rsa);
-int RSA_blinding_on(RSA *rsa, BN_CTX *ctx);
-void RSA_blinding_off(RSA *rsa);
-BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 int RSA_blinding_on(RSA *rsa, BN_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 void RSA_blinding_off(RSA *rsa);
+OSSL_DEPRECATEDIN_3_0 BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0
int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen,
const unsigned char *f, int fl);
+OSSL_DEPRECATEDIN_3_0
int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen,
const unsigned char *f, int fl,
int rsa_len);
+OSSL_DEPRECATEDIN_3_0
int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen,
const unsigned char *f, int fl);
+OSSL_DEPRECATEDIN_3_0
int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
const unsigned char *f, int fl,
int rsa_len);
-int PKCS1_MGF1(unsigned char *mask, long len, const unsigned char *seed,
- long seedlen, const EVP_MD *dgst);
+OSSL_DEPRECATEDIN_3_0 int PKCS1_MGF1(unsigned char *mask, long len,
+ const unsigned char *seed, long seedlen,
+ const EVP_MD *dgst);
+OSSL_DEPRECATEDIN_3_0
int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
const unsigned char *f, int fl,
const unsigned char *p, int pl);
+OSSL_DEPRECATEDIN_3_0
int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
const unsigned char *f, int fl, int rsa_len,
const unsigned char *p, int pl);
+OSSL_DEPRECATEDIN_3_0
int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
const unsigned char *from, int flen,
const unsigned char *param, int plen,
const EVP_MD *md, const EVP_MD *mgf1md);
+OSSL_DEPRECATEDIN_3_0
int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
const unsigned char *from, int flen,
- int num, const unsigned char *param,
- int plen, const EVP_MD *md,
- const EVP_MD *mgf1md);
-int RSA_padding_add_SSLv23(unsigned char *to, int tlen,
- const unsigned char *f, int fl);
-int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
- const unsigned char *f, int fl, int rsa_len);
-int RSA_padding_add_none(unsigned char *to, int tlen, const unsigned char *f,
- int fl);
-int RSA_padding_check_none(unsigned char *to, int tlen,
- const unsigned char *f, int fl, int rsa_len);
-int RSA_padding_add_X931(unsigned char *to, int tlen, const unsigned char *f,
- int fl);
-int RSA_padding_check_X931(unsigned char *to, int tlen,
- const unsigned char *f, int fl, int rsa_len);
-int RSA_X931_hash_id(int nid);
-
+ int num,
+ const unsigned char *param, int plen,
+ const EVP_MD *md, const EVP_MD *mgf1md);
+OSSL_DEPRECATEDIN_3_0 int RSA_padding_add_none(unsigned char *to, int tlen,
+ const unsigned char *f, int fl);
+OSSL_DEPRECATEDIN_3_0 int RSA_padding_check_none(unsigned char *to, int tlen,
+ const unsigned char *f, int fl,
+ int rsa_len);
+OSSL_DEPRECATEDIN_3_0 int RSA_padding_add_X931(unsigned char *to, int tlen,
+ const unsigned char *f, int fl);
+OSSL_DEPRECATEDIN_3_0 int RSA_padding_check_X931(unsigned char *to, int tlen,
+ const unsigned char *f, int fl,
+ int rsa_len);
+OSSL_DEPRECATEDIN_3_0 int RSA_X931_hash_id(int nid);
+
+OSSL_DEPRECATEDIN_3_0
int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
const EVP_MD *Hash, const unsigned char *EM,
int sLen);
+OSSL_DEPRECATEDIN_3_0
int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
const unsigned char *mHash, const EVP_MD *Hash,
int sLen);
+OSSL_DEPRECATEDIN_3_0
int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash,
const EVP_MD *Hash, const EVP_MD *mgf1Hash,
const unsigned char *EM, int sLen);
+OSSL_DEPRECATEDIN_3_0
int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
const unsigned char *mHash,
const EVP_MD *Hash, const EVP_MD *mgf1Hash,
int sLen);
-#define RSA_get_ex_new_index(l, p, newf, dupf, freef) \
+# define RSA_get_ex_new_index(l, p, newf, dupf, freef) \
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, l, p, newf, dupf, freef)
-int RSA_set_ex_data(RSA *r, int idx, void *arg);
-void *RSA_get_ex_data(const RSA *r, int idx);
+OSSL_DEPRECATEDIN_3_0 int RSA_set_ex_data(RSA *r, int idx, void *arg);
+OSSL_DEPRECATEDIN_3_0 void *RSA_get_ex_data(const RSA *r, int idx);
-RSA *RSAPublicKey_dup(RSA *rsa);
-RSA *RSAPrivateKey_dup(RSA *rsa);
+DECLARE_ASN1_DUP_FUNCTION_name_attr(OSSL_DEPRECATEDIN_3_0, RSA, RSAPublicKey)
+DECLARE_ASN1_DUP_FUNCTION_name_attr(OSSL_DEPRECATEDIN_3_0, RSA, RSAPrivateKey)
/*
* If this flag is set the RSA method is FIPS compliant and can be used in
@@ -404,7 +455,7 @@ RSA *RSAPrivateKey_dup(RSA *rsa);
* result is compliant.
*/
-# define RSA_FLAG_FIPS_METHOD 0x0400
+# define RSA_FLAG_FIPS_METHOD 0x0400
/*
* If this flag is set the operations normally disabled in FIPS mode are
@@ -412,58 +463,80 @@ RSA *RSAPrivateKey_dup(RSA *rsa);
* usage is compliant.
*/
-# define RSA_FLAG_NON_FIPS_ALLOW 0x0400
+# define RSA_FLAG_NON_FIPS_ALLOW 0x0400
/*
* Application has decided PRNG is good enough to generate a key: don't
* check.
*/
-# define RSA_FLAG_CHECKED 0x0800
-
-RSA_METHOD *RSA_meth_new(const char *name, int flags);
-void RSA_meth_free(RSA_METHOD *meth);
-RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth);
-const char *RSA_meth_get0_name(const RSA_METHOD *meth);
-int RSA_meth_set1_name(RSA_METHOD *meth, const char *name);
-int RSA_meth_get_flags(const RSA_METHOD *meth);
-int RSA_meth_set_flags(RSA_METHOD *meth, int flags);
-void *RSA_meth_get0_app_data(const RSA_METHOD *meth);
-int RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data);
-int (*RSA_meth_get_pub_enc(const RSA_METHOD *meth))
- (int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding);
+# define RSA_FLAG_CHECKED 0x0800
+
+OSSL_DEPRECATEDIN_3_0 RSA_METHOD *RSA_meth_new(const char *name, int flags);
+OSSL_DEPRECATEDIN_3_0 void RSA_meth_free(RSA_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 const char *RSA_meth_get0_name(const RSA_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 int RSA_meth_set1_name(RSA_METHOD *meth,
+ const char *name);
+OSSL_DEPRECATEDIN_3_0 int RSA_meth_get_flags(const RSA_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 int RSA_meth_set_flags(RSA_METHOD *meth, int flags);
+OSSL_DEPRECATEDIN_3_0 void *RSA_meth_get0_app_data(const RSA_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 int RSA_meth_set0_app_data(RSA_METHOD *meth,
+ void *app_data);
+OSSL_DEPRECATEDIN_3_0
+int (*RSA_meth_get_pub_enc(const RSA_METHOD *meth)) (int flen,
+ const unsigned char *from,
+ unsigned char *to,
+ RSA *rsa, int padding);
+OSSL_DEPRECATEDIN_3_0
int RSA_meth_set_pub_enc(RSA_METHOD *rsa,
int (*pub_enc) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding));
-int (*RSA_meth_get_pub_dec(const RSA_METHOD *meth))
- (int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding);
+OSSL_DEPRECATEDIN_3_0
+int (*RSA_meth_get_pub_dec(const RSA_METHOD *meth)) (int flen,
+ const unsigned char *from,
+ unsigned char *to,
+ RSA *rsa, int padding);
+OSSL_DEPRECATEDIN_3_0
int RSA_meth_set_pub_dec(RSA_METHOD *rsa,
int (*pub_dec) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding));
-int (*RSA_meth_get_priv_enc(const RSA_METHOD *meth))
- (int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding);
+OSSL_DEPRECATEDIN_3_0
+int (*RSA_meth_get_priv_enc(const RSA_METHOD *meth)) (int flen,
+ const unsigned char *from,
+ unsigned char *to,
+ RSA *rsa, int padding);
+OSSL_DEPRECATEDIN_3_0
int RSA_meth_set_priv_enc(RSA_METHOD *rsa,
int (*priv_enc) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding));
-int (*RSA_meth_get_priv_dec(const RSA_METHOD *meth))
- (int flen, const unsigned char *from,
- unsigned char *to, RSA *rsa, int padding);
+OSSL_DEPRECATEDIN_3_0
+int (*RSA_meth_get_priv_dec(const RSA_METHOD *meth)) (int flen,
+ const unsigned char *from,
+ unsigned char *to,
+ RSA *rsa, int padding);
+OSSL_DEPRECATEDIN_3_0
int RSA_meth_set_priv_dec(RSA_METHOD *rsa,
int (*priv_dec) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding));
-int (*RSA_meth_get_mod_exp(const RSA_METHOD *meth))
- (BIGNUM *r0, const BIGNUM *i, RSA *rsa, BN_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0
+int (*RSA_meth_get_mod_exp(const RSA_METHOD *meth)) (BIGNUM *r0,
+ const BIGNUM *i,
+ RSA *rsa, BN_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0
int RSA_meth_set_mod_exp(RSA_METHOD *rsa,
int (*mod_exp) (BIGNUM *r0, const BIGNUM *i, RSA *rsa,
BN_CTX *ctx));
-int (*RSA_meth_get_bn_mod_exp(const RSA_METHOD *meth))
- (BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
- const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+OSSL_DEPRECATEDIN_3_0
+int (*RSA_meth_get_bn_mod_exp(const RSA_METHOD *meth)) (BIGNUM *r,
+ const BIGNUM *a,
+ const BIGNUM *p,
+ const BIGNUM *m,
+ BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx);
+OSSL_DEPRECATEDIN_3_0
int RSA_meth_set_bn_mod_exp(RSA_METHOD *rsa,
int (*bn_mod_exp) (BIGNUM *r,
const BIGNUM *a,
@@ -471,43 +544,61 @@ int RSA_meth_set_bn_mod_exp(RSA_METHOD *rsa,
const BIGNUM *m,
BN_CTX *ctx,
BN_MONT_CTX *m_ctx));
+OSSL_DEPRECATEDIN_3_0
int (*RSA_meth_get_init(const RSA_METHOD *meth)) (RSA *rsa);
+OSSL_DEPRECATEDIN_3_0
int RSA_meth_set_init(RSA_METHOD *rsa, int (*init) (RSA *rsa));
+OSSL_DEPRECATEDIN_3_0
int (*RSA_meth_get_finish(const RSA_METHOD *meth)) (RSA *rsa);
+OSSL_DEPRECATEDIN_3_0
int RSA_meth_set_finish(RSA_METHOD *rsa, int (*finish) (RSA *rsa));
-int (*RSA_meth_get_sign(const RSA_METHOD *meth))
- (int type,
- const unsigned char *m, unsigned int m_length,
- unsigned char *sigret, unsigned int *siglen,
- const RSA *rsa);
+OSSL_DEPRECATEDIN_3_0
+int (*RSA_meth_get_sign(const RSA_METHOD *meth)) (int type,
+ const unsigned char *m,
+ unsigned int m_length,
+ unsigned char *sigret,
+ unsigned int *siglen,
+ const RSA *rsa);
+OSSL_DEPRECATEDIN_3_0
int RSA_meth_set_sign(RSA_METHOD *rsa,
int (*sign) (int type, const unsigned char *m,
unsigned int m_length,
unsigned char *sigret, unsigned int *siglen,
const RSA *rsa));
-int (*RSA_meth_get_verify(const RSA_METHOD *meth))
- (int dtype, const unsigned char *m,
- unsigned int m_length, const unsigned char *sigbuf,
- unsigned int siglen, const RSA *rsa);
+OSSL_DEPRECATEDIN_3_0
+int (*RSA_meth_get_verify(const RSA_METHOD *meth)) (int dtype,
+ const unsigned char *m,
+ unsigned int m_length,
+ const unsigned char *sigbuf,
+ unsigned int siglen,
+ const RSA *rsa);
+OSSL_DEPRECATEDIN_3_0
int RSA_meth_set_verify(RSA_METHOD *rsa,
int (*verify) (int dtype, const unsigned char *m,
unsigned int m_length,
const unsigned char *sigbuf,
unsigned int siglen, const RSA *rsa));
-int (*RSA_meth_get_keygen(const RSA_METHOD *meth))
- (RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
+OSSL_DEPRECATEDIN_3_0
+int (*RSA_meth_get_keygen(const RSA_METHOD *meth)) (RSA *rsa, int bits,
+ BIGNUM *e, BN_GENCB *cb);
+OSSL_DEPRECATEDIN_3_0
int RSA_meth_set_keygen(RSA_METHOD *rsa,
int (*keygen) (RSA *rsa, int bits, BIGNUM *e,
BN_GENCB *cb));
-int (*RSA_meth_get_multi_prime_keygen(const RSA_METHOD *meth))
- (RSA *rsa, int bits, int primes, BIGNUM *e, BN_GENCB *cb);
+OSSL_DEPRECATEDIN_3_0
+int (*RSA_meth_get_multi_prime_keygen(const RSA_METHOD *meth)) (RSA *rsa,
+ int bits,
+ int primes,
+ BIGNUM *e,
+ BN_GENCB *cb);
+OSSL_DEPRECATEDIN_3_0
int RSA_meth_set_multi_prime_keygen(RSA_METHOD *meth,
int (*keygen) (RSA *rsa, int bits,
int primes, BIGNUM *e,
BN_GENCB *cb));
+#endif /* !OPENSSL_NO_DEPRECATED_3_0 */
-# ifdef __cplusplus
+# ifdef __cplusplus
}
-# endif
# endif
#endif
diff --git a/include/openssl/rsaerr.h b/include/openssl/rsaerr.h
index 59b15e13e965..c58463c7c19f 100644
--- a/include/openssl/rsaerr.h
+++ b/include/openssl/rsaerr.h
@@ -1,91 +1,22 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_RSAERR_H
-# define HEADER_RSAERR_H
+#ifndef OPENSSL_RSAERR_H
+# define OPENSSL_RSAERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_RSA_strings(void);
-/*
- * RSA function codes.
- */
-# define RSA_F_CHECK_PADDING_MD 140
-# define RSA_F_ENCODE_PKCS1 146
-# define RSA_F_INT_RSA_VERIFY 145
-# define RSA_F_OLD_RSA_PRIV_DECODE 147
-# define RSA_F_PKEY_PSS_INIT 165
-# define RSA_F_PKEY_RSA_CTRL 143
-# define RSA_F_PKEY_RSA_CTRL_STR 144
-# define RSA_F_PKEY_RSA_SIGN 142
-# define RSA_F_PKEY_RSA_VERIFY 149
-# define RSA_F_PKEY_RSA_VERIFYRECOVER 141
-# define RSA_F_RSA_ALGOR_TO_MD 156
-# define RSA_F_RSA_BUILTIN_KEYGEN 129
-# define RSA_F_RSA_CHECK_KEY 123
-# define RSA_F_RSA_CHECK_KEY_EX 160
-# define RSA_F_RSA_CMS_DECRYPT 159
-# define RSA_F_RSA_CMS_VERIFY 158
-# define RSA_F_RSA_ITEM_VERIFY 148
-# define RSA_F_RSA_METH_DUP 161
-# define RSA_F_RSA_METH_NEW 162
-# define RSA_F_RSA_METH_SET1_NAME 163
-# define RSA_F_RSA_MGF1_TO_MD 157
-# define RSA_F_RSA_MULTIP_INFO_NEW 166
-# define RSA_F_RSA_NEW_METHOD 106
-# define RSA_F_RSA_NULL 124
-# define RSA_F_RSA_NULL_PRIVATE_DECRYPT 132
-# define RSA_F_RSA_NULL_PRIVATE_ENCRYPT 133
-# define RSA_F_RSA_NULL_PUBLIC_DECRYPT 134
-# define RSA_F_RSA_NULL_PUBLIC_ENCRYPT 135
-# define RSA_F_RSA_OSSL_PRIVATE_DECRYPT 101
-# define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT 102
-# define RSA_F_RSA_OSSL_PUBLIC_DECRYPT 103
-# define RSA_F_RSA_OSSL_PUBLIC_ENCRYPT 104
-# define RSA_F_RSA_PADDING_ADD_NONE 107
-# define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP 121
-# define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1 154
-# define RSA_F_RSA_PADDING_ADD_PKCS1_PSS 125
-# define RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1 152
-# define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1 108
-# define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2 109
-# define RSA_F_RSA_PADDING_ADD_SSLV23 110
-# define RSA_F_RSA_PADDING_ADD_X931 127
-# define RSA_F_RSA_PADDING_CHECK_NONE 111
-# define RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP 122
-# define RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1 153
-# define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1 112
-# define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2 113
-# define RSA_F_RSA_PADDING_CHECK_SSLV23 114
-# define RSA_F_RSA_PADDING_CHECK_X931 128
-# define RSA_F_RSA_PARAM_DECODE 164
-# define RSA_F_RSA_PRINT 115
-# define RSA_F_RSA_PRINT_FP 116
-# define RSA_F_RSA_PRIV_DECODE 150
-# define RSA_F_RSA_PRIV_ENCODE 138
-# define RSA_F_RSA_PSS_GET_PARAM 151
-# define RSA_F_RSA_PSS_TO_CTX 155
-# define RSA_F_RSA_PUB_DECODE 139
-# define RSA_F_RSA_SETUP_BLINDING 136
-# define RSA_F_RSA_SIGN 117
-# define RSA_F_RSA_SIGN_ASN1_OCTET_STRING 118
-# define RSA_F_RSA_VERIFY 119
-# define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING 120
-# define RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1 126
-# define RSA_F_SETUP_TBUF 167
/*
* RSA reason codes.
@@ -114,24 +45,30 @@ int ERR_load_RSA_strings(void);
# define RSA_R_INVALID_DIGEST 157
# define RSA_R_INVALID_DIGEST_LENGTH 143
# define RSA_R_INVALID_HEADER 137
+# define RSA_R_INVALID_KEYPAIR 171
+# define RSA_R_INVALID_KEY_LENGTH 173
# define RSA_R_INVALID_LABEL 160
+# define RSA_R_INVALID_LENGTH 181
# define RSA_R_INVALID_MESSAGE_LENGTH 131
# define RSA_R_INVALID_MGF1_MD 156
+# define RSA_R_INVALID_MODULUS 174
# define RSA_R_INVALID_MULTI_PRIME_KEY 167
# define RSA_R_INVALID_OAEP_PARAMETERS 161
# define RSA_R_INVALID_PADDING 138
# define RSA_R_INVALID_PADDING_MODE 141
# define RSA_R_INVALID_PSS_PARAMETERS 149
# define RSA_R_INVALID_PSS_SALTLEN 146
+# define RSA_R_INVALID_REQUEST 175
# define RSA_R_INVALID_SALT_LENGTH 150
+# define RSA_R_INVALID_STRENGTH 176
# define RSA_R_INVALID_TRAILER 139
# define RSA_R_INVALID_X931_DIGEST 142
# define RSA_R_IQMP_NOT_INVERSE_OF_Q 126
# define RSA_R_KEY_PRIME_NUM_INVALID 165
# define RSA_R_KEY_SIZE_TOO_SMALL 120
# define RSA_R_LAST_OCTET_INVALID 134
-# define RSA_R_MISSING_PRIVATE_KEY 179
# define RSA_R_MGF1_DIGEST_NOT_ALLOWED 152
+# define RSA_R_MISSING_PRIVATE_KEY 179
# define RSA_R_MODULUS_TOO_LARGE 105
# define RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R 168
# define RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D 169
@@ -143,10 +80,13 @@ int ERR_load_RSA_strings(void);
# define RSA_R_OAEP_DECODING_ERROR 121
# define RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 148
# define RSA_R_PADDING_CHECK_FAILED 114
+# define RSA_R_PAIRWISE_TEST_FAILURE 177
# define RSA_R_PKCS_DECODING_ERROR 159
# define RSA_R_PSS_SALTLEN_TOO_SMALL 164
+# define RSA_R_PUB_EXPONENT_OUT_OF_RANGE 178
# define RSA_R_P_NOT_PRIME 128
# define RSA_R_Q_NOT_PRIME 129
+# define RSA_R_RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT 180
# define RSA_R_RSA_OPERATIONS_NOT_SUPPORTED 130
# define RSA_R_SLEN_CHECK_FAILED 136
# define RSA_R_SLEN_RECOVERY_FAILED 135
diff --git a/include/openssl/safestack.h b/include/openssl/safestack.h
deleted file mode 100644
index 38b5578978cb..000000000000
--- a/include/openssl/safestack.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_SAFESTACK_H
-# define HEADER_SAFESTACK_H
-
-# include <openssl/stack.h>
-# include <openssl/e_os2.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-# define STACK_OF(type) struct stack_st_##type
-
-# define SKM_DEFINE_STACK_OF(t1, t2, t3) \
- STACK_OF(t1); \
- typedef int (*sk_##t1##_compfunc)(const t3 * const *a, const t3 *const *b); \
- typedef void (*sk_##t1##_freefunc)(t3 *a); \
- typedef t3 * (*sk_##t1##_copyfunc)(const t3 *a); \
- static ossl_unused ossl_inline int sk_##t1##_num(const STACK_OF(t1) *sk) \
- { \
- return OPENSSL_sk_num((const OPENSSL_STACK *)sk); \
- } \
- static ossl_unused ossl_inline t2 *sk_##t1##_value(const STACK_OF(t1) *sk, int idx) \
- { \
- return (t2 *)OPENSSL_sk_value((const OPENSSL_STACK *)sk, idx); \
- } \
- static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_new(sk_##t1##_compfunc compare) \
- { \
- return (STACK_OF(t1) *)OPENSSL_sk_new((OPENSSL_sk_compfunc)compare); \
- } \
- static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_new_null(void) \
- { \
- return (STACK_OF(t1) *)OPENSSL_sk_new_null(); \
- } \
- static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_new_reserve(sk_##t1##_compfunc compare, int n) \
- { \
- return (STACK_OF(t1) *)OPENSSL_sk_new_reserve((OPENSSL_sk_compfunc)compare, n); \
- } \
- static ossl_unused ossl_inline int sk_##t1##_reserve(STACK_OF(t1) *sk, int n) \
- { \
- return OPENSSL_sk_reserve((OPENSSL_STACK *)sk, n); \
- } \
- static ossl_unused ossl_inline void sk_##t1##_free(STACK_OF(t1) *sk) \
- { \
- OPENSSL_sk_free((OPENSSL_STACK *)sk); \
- } \
- static ossl_unused ossl_inline void sk_##t1##_zero(STACK_OF(t1) *sk) \
- { \
- OPENSSL_sk_zero((OPENSSL_STACK *)sk); \
- } \
- static ossl_unused ossl_inline t2 *sk_##t1##_delete(STACK_OF(t1) *sk, int i) \
- { \
- return (t2 *)OPENSSL_sk_delete((OPENSSL_STACK *)sk, i); \
- } \
- static ossl_unused ossl_inline t2 *sk_##t1##_delete_ptr(STACK_OF(t1) *sk, t2 *ptr) \
- { \
- return (t2 *)OPENSSL_sk_delete_ptr((OPENSSL_STACK *)sk, \
- (const void *)ptr); \
- } \
- static ossl_unused ossl_inline int sk_##t1##_push(STACK_OF(t1) *sk, t2 *ptr) \
- { \
- return OPENSSL_sk_push((OPENSSL_STACK *)sk, (const void *)ptr); \
- } \
- static ossl_unused ossl_inline int sk_##t1##_unshift(STACK_OF(t1) *sk, t2 *ptr) \
- { \
- return OPENSSL_sk_unshift((OPENSSL_STACK *)sk, (const void *)ptr); \
- } \
- static ossl_unused ossl_inline t2 *sk_##t1##_pop(STACK_OF(t1) *sk) \
- { \
- return (t2 *)OPENSSL_sk_pop((OPENSSL_STACK *)sk); \
- } \
- static ossl_unused ossl_inline t2 *sk_##t1##_shift(STACK_OF(t1) *sk) \
- { \
- return (t2 *)OPENSSL_sk_shift((OPENSSL_STACK *)sk); \
- } \
- static ossl_unused ossl_inline void sk_##t1##_pop_free(STACK_OF(t1) *sk, sk_##t1##_freefunc freefunc) \
- { \
- OPENSSL_sk_pop_free((OPENSSL_STACK *)sk, (OPENSSL_sk_freefunc)freefunc); \
- } \
- static ossl_unused ossl_inline int sk_##t1##_insert(STACK_OF(t1) *sk, t2 *ptr, int idx) \
- { \
- return OPENSSL_sk_insert((OPENSSL_STACK *)sk, (const void *)ptr, idx); \
- } \
- static ossl_unused ossl_inline t2 *sk_##t1##_set(STACK_OF(t1) *sk, int idx, t2 *ptr) \
- { \
- return (t2 *)OPENSSL_sk_set((OPENSSL_STACK *)sk, idx, (const void *)ptr); \
- } \
- static ossl_unused ossl_inline int sk_##t1##_find(STACK_OF(t1) *sk, t2 *ptr) \
- { \
- return OPENSSL_sk_find((OPENSSL_STACK *)sk, (const void *)ptr); \
- } \
- static ossl_unused ossl_inline int sk_##t1##_find_ex(STACK_OF(t1) *sk, t2 *ptr) \
- { \
- return OPENSSL_sk_find_ex((OPENSSL_STACK *)sk, (const void *)ptr); \
- } \
- static ossl_unused ossl_inline void sk_##t1##_sort(STACK_OF(t1) *sk) \
- { \
- OPENSSL_sk_sort((OPENSSL_STACK *)sk); \
- } \
- static ossl_unused ossl_inline int sk_##t1##_is_sorted(const STACK_OF(t1) *sk) \
- { \
- return OPENSSL_sk_is_sorted((const OPENSSL_STACK *)sk); \
- } \
- static ossl_unused ossl_inline STACK_OF(t1) * sk_##t1##_dup(const STACK_OF(t1) *sk) \
- { \
- return (STACK_OF(t1) *)OPENSSL_sk_dup((const OPENSSL_STACK *)sk); \
- } \
- static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_deep_copy(const STACK_OF(t1) *sk, \
- sk_##t1##_copyfunc copyfunc, \
- sk_##t1##_freefunc freefunc) \
- { \
- return (STACK_OF(t1) *)OPENSSL_sk_deep_copy((const OPENSSL_STACK *)sk, \
- (OPENSSL_sk_copyfunc)copyfunc, \
- (OPENSSL_sk_freefunc)freefunc); \
- } \
- static ossl_unused ossl_inline sk_##t1##_compfunc sk_##t1##_set_cmp_func(STACK_OF(t1) *sk, sk_##t1##_compfunc compare) \
- { \
- return (sk_##t1##_compfunc)OPENSSL_sk_set_cmp_func((OPENSSL_STACK *)sk, (OPENSSL_sk_compfunc)compare); \
- }
-
-# define DEFINE_SPECIAL_STACK_OF(t1, t2) SKM_DEFINE_STACK_OF(t1, t2, t2)
-# define DEFINE_STACK_OF(t) SKM_DEFINE_STACK_OF(t, t, t)
-# define DEFINE_SPECIAL_STACK_OF_CONST(t1, t2) \
- SKM_DEFINE_STACK_OF(t1, const t2, t2)
-# define DEFINE_STACK_OF_CONST(t) SKM_DEFINE_STACK_OF(t, const t, t)
-
-/*-
- * Strings are special: normally an lhash entry will point to a single
- * (somewhat) mutable object. In the case of strings:
- *
- * a) Instead of a single char, there is an array of chars, NUL-terminated.
- * b) The string may have be immutable.
- *
- * So, they need their own declarations. Especially important for
- * type-checking tools, such as Deputy.
- *
- * In practice, however, it appears to be hard to have a const
- * string. For now, I'm settling for dealing with the fact it is a
- * string at all.
- */
-typedef char *OPENSSL_STRING;
-typedef const char *OPENSSL_CSTRING;
-
-/*-
- * Confusingly, LHASH_OF(STRING) deals with char ** throughout, but
- * STACK_OF(STRING) is really more like STACK_OF(char), only, as mentioned
- * above, instead of a single char each entry is a NUL-terminated array of
- * chars. So, we have to implement STRING specially for STACK_OF. This is
- * dealt with in the autogenerated macros below.
- */
-DEFINE_SPECIAL_STACK_OF(OPENSSL_STRING, char)
-DEFINE_SPECIAL_STACK_OF_CONST(OPENSSL_CSTRING, char)
-
-/*
- * Similarly, we sometimes use a block of characters, NOT nul-terminated.
- * These should also be distinguished from "normal" stacks.
- */
-typedef void *OPENSSL_BLOCK;
-DEFINE_SPECIAL_STACK_OF(OPENSSL_BLOCK, void)
-
-/*
- * If called without higher optimization (min. -xO3) the Oracle Developer
- * Studio compiler generates code for the defined (static inline) functions
- * above.
- * This would later lead to the linker complaining about missing symbols when
- * this header file is included but the resulting object is not linked against
- * the Crypto library (openssl#6912).
- */
-# ifdef __SUNPRO_C
-# pragma weak OPENSSL_sk_num
-# pragma weak OPENSSL_sk_value
-# pragma weak OPENSSL_sk_new
-# pragma weak OPENSSL_sk_new_null
-# pragma weak OPENSSL_sk_new_reserve
-# pragma weak OPENSSL_sk_reserve
-# pragma weak OPENSSL_sk_free
-# pragma weak OPENSSL_sk_zero
-# pragma weak OPENSSL_sk_delete
-# pragma weak OPENSSL_sk_delete_ptr
-# pragma weak OPENSSL_sk_push
-# pragma weak OPENSSL_sk_unshift
-# pragma weak OPENSSL_sk_pop
-# pragma weak OPENSSL_sk_shift
-# pragma weak OPENSSL_sk_pop_free
-# pragma weak OPENSSL_sk_insert
-# pragma weak OPENSSL_sk_set
-# pragma weak OPENSSL_sk_find
-# pragma weak OPENSSL_sk_find_ex
-# pragma weak OPENSSL_sk_sort
-# pragma weak OPENSSL_sk_is_sorted
-# pragma weak OPENSSL_sk_dup
-# pragma weak OPENSSL_sk_deep_copy
-# pragma weak OPENSSL_sk_set_cmp_func
-# endif /* __SUNPRO_C */
-
-# ifdef __cplusplus
-}
-# endif
-#endif
diff --git a/include/openssl/safestack.h.in b/include/openssl/safestack.h.in
new file mode 100644
index 000000000000..6b36607928ff
--- /dev/null
+++ b/include/openssl/safestack.h.in
@@ -0,0 +1,227 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_string_macros
+ generate_stack_const_string_macros
+ generate_stack_block_macros);
+-}
+
+#ifndef OPENSSL_SAFESTACK_H
+# define OPENSSL_SAFESTACK_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_SAFESTACK_H
+# endif
+
+# include <openssl/stack.h>
+# include <openssl/e_os2.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+# define STACK_OF(type) struct stack_st_##type
+
+/* Helper macro for internal use */
+# define SKM_DEFINE_STACK_OF_INTERNAL(t1, t2, t3) \
+ STACK_OF(t1); \
+ typedef int (*sk_##t1##_compfunc)(const t3 * const *a, const t3 *const *b); \
+ typedef void (*sk_##t1##_freefunc)(t3 *a); \
+ typedef t3 * (*sk_##t1##_copyfunc)(const t3 *a); \
+ static ossl_unused ossl_inline t2 *ossl_check_##t1##_type(t2 *ptr) \
+ { \
+ return ptr; \
+ } \
+ static ossl_unused ossl_inline const OPENSSL_STACK *ossl_check_const_##t1##_sk_type(const STACK_OF(t1) *sk) \
+ { \
+ return (const OPENSSL_STACK *)sk; \
+ } \
+ static ossl_unused ossl_inline OPENSSL_STACK *ossl_check_##t1##_sk_type(STACK_OF(t1) *sk) \
+ { \
+ return (OPENSSL_STACK *)sk; \
+ } \
+ static ossl_unused ossl_inline OPENSSL_sk_compfunc ossl_check_##t1##_compfunc_type(sk_##t1##_compfunc cmp) \
+ { \
+ return (OPENSSL_sk_compfunc)cmp; \
+ } \
+ static ossl_unused ossl_inline OPENSSL_sk_copyfunc ossl_check_##t1##_copyfunc_type(sk_##t1##_copyfunc cpy) \
+ { \
+ return (OPENSSL_sk_copyfunc)cpy; \
+ } \
+ static ossl_unused ossl_inline OPENSSL_sk_freefunc ossl_check_##t1##_freefunc_type(sk_##t1##_freefunc fr) \
+ { \
+ return (OPENSSL_sk_freefunc)fr; \
+ }
+
+# define SKM_DEFINE_STACK_OF(t1, t2, t3) \
+ STACK_OF(t1); \
+ typedef int (*sk_##t1##_compfunc)(const t3 * const *a, const t3 *const *b); \
+ typedef void (*sk_##t1##_freefunc)(t3 *a); \
+ typedef t3 * (*sk_##t1##_copyfunc)(const t3 *a); \
+ static ossl_unused ossl_inline int sk_##t1##_num(const STACK_OF(t1) *sk) \
+ { \
+ return OPENSSL_sk_num((const OPENSSL_STACK *)sk); \
+ } \
+ static ossl_unused ossl_inline t2 *sk_##t1##_value(const STACK_OF(t1) *sk, int idx) \
+ { \
+ return (t2 *)OPENSSL_sk_value((const OPENSSL_STACK *)sk, idx); \
+ } \
+ static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_new(sk_##t1##_compfunc compare) \
+ { \
+ return (STACK_OF(t1) *)OPENSSL_sk_new((OPENSSL_sk_compfunc)compare); \
+ } \
+ static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_new_null(void) \
+ { \
+ return (STACK_OF(t1) *)OPENSSL_sk_new_null(); \
+ } \
+ static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_new_reserve(sk_##t1##_compfunc compare, int n) \
+ { \
+ return (STACK_OF(t1) *)OPENSSL_sk_new_reserve((OPENSSL_sk_compfunc)compare, n); \
+ } \
+ static ossl_unused ossl_inline int sk_##t1##_reserve(STACK_OF(t1) *sk, int n) \
+ { \
+ return OPENSSL_sk_reserve((OPENSSL_STACK *)sk, n); \
+ } \
+ static ossl_unused ossl_inline void sk_##t1##_free(STACK_OF(t1) *sk) \
+ { \
+ OPENSSL_sk_free((OPENSSL_STACK *)sk); \
+ } \
+ static ossl_unused ossl_inline void sk_##t1##_zero(STACK_OF(t1) *sk) \
+ { \
+ OPENSSL_sk_zero((OPENSSL_STACK *)sk); \
+ } \
+ static ossl_unused ossl_inline t2 *sk_##t1##_delete(STACK_OF(t1) *sk, int i) \
+ { \
+ return (t2 *)OPENSSL_sk_delete((OPENSSL_STACK *)sk, i); \
+ } \
+ static ossl_unused ossl_inline t2 *sk_##t1##_delete_ptr(STACK_OF(t1) *sk, t2 *ptr) \
+ { \
+ return (t2 *)OPENSSL_sk_delete_ptr((OPENSSL_STACK *)sk, \
+ (const void *)ptr); \
+ } \
+ static ossl_unused ossl_inline int sk_##t1##_push(STACK_OF(t1) *sk, t2 *ptr) \
+ { \
+ return OPENSSL_sk_push((OPENSSL_STACK *)sk, (const void *)ptr); \
+ } \
+ static ossl_unused ossl_inline int sk_##t1##_unshift(STACK_OF(t1) *sk, t2 *ptr) \
+ { \
+ return OPENSSL_sk_unshift((OPENSSL_STACK *)sk, (const void *)ptr); \
+ } \
+ static ossl_unused ossl_inline t2 *sk_##t1##_pop(STACK_OF(t1) *sk) \
+ { \
+ return (t2 *)OPENSSL_sk_pop((OPENSSL_STACK *)sk); \
+ } \
+ static ossl_unused ossl_inline t2 *sk_##t1##_shift(STACK_OF(t1) *sk) \
+ { \
+ return (t2 *)OPENSSL_sk_shift((OPENSSL_STACK *)sk); \
+ } \
+ static ossl_unused ossl_inline void sk_##t1##_pop_free(STACK_OF(t1) *sk, sk_##t1##_freefunc freefunc) \
+ { \
+ OPENSSL_sk_pop_free((OPENSSL_STACK *)sk, (OPENSSL_sk_freefunc)freefunc); \
+ } \
+ static ossl_unused ossl_inline int sk_##t1##_insert(STACK_OF(t1) *sk, t2 *ptr, int idx) \
+ { \
+ return OPENSSL_sk_insert((OPENSSL_STACK *)sk, (const void *)ptr, idx); \
+ } \
+ static ossl_unused ossl_inline t2 *sk_##t1##_set(STACK_OF(t1) *sk, int idx, t2 *ptr) \
+ { \
+ return (t2 *)OPENSSL_sk_set((OPENSSL_STACK *)sk, idx, (const void *)ptr); \
+ } \
+ static ossl_unused ossl_inline int sk_##t1##_find(STACK_OF(t1) *sk, t2 *ptr) \
+ { \
+ return OPENSSL_sk_find((OPENSSL_STACK *)sk, (const void *)ptr); \
+ } \
+ static ossl_unused ossl_inline int sk_##t1##_find_ex(STACK_OF(t1) *sk, t2 *ptr) \
+ { \
+ return OPENSSL_sk_find_ex((OPENSSL_STACK *)sk, (const void *)ptr); \
+ } \
+ static ossl_unused ossl_inline int sk_##t1##_find_all(STACK_OF(t1) *sk, t2 *ptr, int *pnum) \
+ { \
+ return OPENSSL_sk_find_all((OPENSSL_STACK *)sk, (const void *)ptr, pnum); \
+ } \
+ static ossl_unused ossl_inline void sk_##t1##_sort(STACK_OF(t1) *sk) \
+ { \
+ OPENSSL_sk_sort((OPENSSL_STACK *)sk); \
+ } \
+ static ossl_unused ossl_inline int sk_##t1##_is_sorted(const STACK_OF(t1) *sk) \
+ { \
+ return OPENSSL_sk_is_sorted((const OPENSSL_STACK *)sk); \
+ } \
+ static ossl_unused ossl_inline STACK_OF(t1) * sk_##t1##_dup(const STACK_OF(t1) *sk) \
+ { \
+ return (STACK_OF(t1) *)OPENSSL_sk_dup((const OPENSSL_STACK *)sk); \
+ } \
+ static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_deep_copy(const STACK_OF(t1) *sk, \
+ sk_##t1##_copyfunc copyfunc, \
+ sk_##t1##_freefunc freefunc) \
+ { \
+ return (STACK_OF(t1) *)OPENSSL_sk_deep_copy((const OPENSSL_STACK *)sk, \
+ (OPENSSL_sk_copyfunc)copyfunc, \
+ (OPENSSL_sk_freefunc)freefunc); \
+ } \
+ static ossl_unused ossl_inline sk_##t1##_compfunc sk_##t1##_set_cmp_func(STACK_OF(t1) *sk, sk_##t1##_compfunc compare) \
+ { \
+ return (sk_##t1##_compfunc)OPENSSL_sk_set_cmp_func((OPENSSL_STACK *)sk, (OPENSSL_sk_compfunc)compare); \
+ }
+
+# define DEFINE_STACK_OF(t) SKM_DEFINE_STACK_OF(t, t, t)
+# define DEFINE_STACK_OF_CONST(t) SKM_DEFINE_STACK_OF(t, const t, t)
+# define DEFINE_SPECIAL_STACK_OF(t1, t2) SKM_DEFINE_STACK_OF(t1, t2, t2)
+# define DEFINE_SPECIAL_STACK_OF_CONST(t1, t2) \
+ SKM_DEFINE_STACK_OF(t1, const t2, t2)
+
+/*-
+ * Strings are special: normally an lhash entry will point to a single
+ * (somewhat) mutable object. In the case of strings:
+ *
+ * a) Instead of a single char, there is an array of chars, NUL-terminated.
+ * b) The string may have be immutable.
+ *
+ * So, they need their own declarations. Especially important for
+ * type-checking tools, such as Deputy.
+ *
+ * In practice, however, it appears to be hard to have a const
+ * string. For now, I'm settling for dealing with the fact it is a
+ * string at all.
+ */
+typedef char *OPENSSL_STRING;
+typedef const char *OPENSSL_CSTRING;
+
+/*-
+ * Confusingly, LHASH_OF(STRING) deals with char ** throughout, but
+ * STACK_OF(STRING) is really more like STACK_OF(char), only, as mentioned
+ * above, instead of a single char each entry is a NUL-terminated array of
+ * chars. So, we have to implement STRING specially for STACK_OF. This is
+ * dealt with in the autogenerated macros below.
+ */
+{-
+ generate_stack_string_macros()
+ .generate_stack_const_string_macros();
+-}
+
+#if !defined(OPENSSL_NO_DEPRECATED_3_0)
+/*
+ * This is not used by OpenSSL. A block of bytes, NOT nul-terminated.
+ * These should also be distinguished from "normal" stacks.
+ */
+typedef void *OPENSSL_BLOCK;
+{-
+ generate_stack_block_macros();
+-}
+#endif
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/seed.h b/include/openssl/seed.h
index de10b0857201..edb218ae6e2d 100644
--- a/include/openssl/seed.h
+++ b/include/openssl/seed.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -32,65 +32,82 @@
* SUCH DAMAGE.
*/
-#ifndef HEADER_SEED_H
-# define HEADER_SEED_H
+#ifndef OPENSSL_SEED_H
+# define OPENSSL_SEED_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_SEED_H
+# endif
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_SEED
-# include <openssl/e_os2.h>
-# include <openssl/crypto.h>
+# include <openssl/e_os2.h>
+# include <openssl/crypto.h>
+# include <sys/types.h>
-#ifdef __cplusplus
+# ifdef __cplusplus
extern "C" {
-#endif
-
-/* look whether we need 'long' to get 32 bits */
-# ifdef AES_LONG
-# ifndef SEED_LONG
-# define SEED_LONG 1
# endif
-# endif
-# include <sys/types.h>
+# define SEED_BLOCK_SIZE 16
+# define SEED_KEY_LENGTH 16
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+/* look whether we need 'long' to get 32 bits */
+# ifdef AES_LONG
+# ifndef SEED_LONG
+# define SEED_LONG 1
+# endif
+# endif
-# define SEED_BLOCK_SIZE 16
-# define SEED_KEY_LENGTH 16
typedef struct seed_key_st {
-# ifdef SEED_LONG
+# ifdef SEED_LONG
unsigned long data[32];
-# else
+# else
unsigned int data[32];
-# endif
+# endif
} SEED_KEY_SCHEDULE;
-
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
void SEED_set_key(const unsigned char rawkey[SEED_KEY_LENGTH],
SEED_KEY_SCHEDULE *ks);
-
+OSSL_DEPRECATEDIN_3_0
void SEED_encrypt(const unsigned char s[SEED_BLOCK_SIZE],
unsigned char d[SEED_BLOCK_SIZE],
const SEED_KEY_SCHEDULE *ks);
+OSSL_DEPRECATEDIN_3_0
void SEED_decrypt(const unsigned char s[SEED_BLOCK_SIZE],
unsigned char d[SEED_BLOCK_SIZE],
const SEED_KEY_SCHEDULE *ks);
-
-void SEED_ecb_encrypt(const unsigned char *in, unsigned char *out,
+OSSL_DEPRECATEDIN_3_0
+void SEED_ecb_encrypt(const unsigned char *in,
+ unsigned char *out,
const SEED_KEY_SCHEDULE *ks, int enc);
+OSSL_DEPRECATEDIN_3_0
void SEED_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t len,
const SEED_KEY_SCHEDULE *ks,
- unsigned char ivec[SEED_BLOCK_SIZE], int enc);
+ unsigned char ivec[SEED_BLOCK_SIZE],
+ int enc);
+OSSL_DEPRECATEDIN_3_0
void SEED_cfb128_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const SEED_KEY_SCHEDULE *ks,
- unsigned char ivec[SEED_BLOCK_SIZE], int *num,
- int enc);
+ unsigned char ivec[SEED_BLOCK_SIZE],
+ int *num, int enc);
+OSSL_DEPRECATEDIN_3_0
void SEED_ofb128_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const SEED_KEY_SCHEDULE *ks,
- unsigned char ivec[SEED_BLOCK_SIZE], int *num);
+ unsigned char ivec[SEED_BLOCK_SIZE],
+ int *num);
+# endif
-# ifdef __cplusplus
+# ifdef __cplusplus
}
-# endif
+# endif
# endif
#endif
diff --git a/include/openssl/self_test.h b/include/openssl/self_test.h
new file mode 100644
index 000000000000..ee4949e5a640
--- /dev/null
+++ b/include/openssl/self_test.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_SELF_TEST_H
+# define OPENSSL_SELF_TEST_H
+# pragma once
+
+# include <openssl/core.h> /* OSSL_CALLBACK */
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/* The test event phases */
+# define OSSL_SELF_TEST_PHASE_NONE "None"
+# define OSSL_SELF_TEST_PHASE_START "Start"
+# define OSSL_SELF_TEST_PHASE_CORRUPT "Corrupt"
+# define OSSL_SELF_TEST_PHASE_PASS "Pass"
+# define OSSL_SELF_TEST_PHASE_FAIL "Fail"
+
+/* Test event categories */
+# define OSSL_SELF_TEST_TYPE_NONE "None"
+# define OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY "Module_Integrity"
+# define OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY "Install_Integrity"
+# define OSSL_SELF_TEST_TYPE_CRNG "Continuous_RNG_Test"
+# define OSSL_SELF_TEST_TYPE_PCT "Conditional_PCT"
+# define OSSL_SELF_TEST_TYPE_KAT_CIPHER "KAT_Cipher"
+# define OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER "KAT_AsymmetricCipher"
+# define OSSL_SELF_TEST_TYPE_KAT_DIGEST "KAT_Digest"
+# define OSSL_SELF_TEST_TYPE_KAT_SIGNATURE "KAT_Signature"
+# define OSSL_SELF_TEST_TYPE_PCT_SIGNATURE "PCT_Signature"
+# define OSSL_SELF_TEST_TYPE_KAT_KDF "KAT_KDF"
+# define OSSL_SELF_TEST_TYPE_KAT_KA "KAT_KA"
+# define OSSL_SELF_TEST_TYPE_DRBG "DRBG"
+
+/* Test event sub categories */
+# define OSSL_SELF_TEST_DESC_NONE "None"
+# define OSSL_SELF_TEST_DESC_INTEGRITY_HMAC "HMAC"
+# define OSSL_SELF_TEST_DESC_PCT_RSA_PKCS1 "RSA"
+# define OSSL_SELF_TEST_DESC_PCT_ECDSA "ECDSA"
+# define OSSL_SELF_TEST_DESC_PCT_DSA "DSA"
+# define OSSL_SELF_TEST_DESC_CIPHER_AES_GCM "AES_GCM"
+# define OSSL_SELF_TEST_DESC_CIPHER_AES_ECB "AES_ECB_Decrypt"
+# define OSSL_SELF_TEST_DESC_CIPHER_TDES "TDES"
+# define OSSL_SELF_TEST_DESC_ASYM_RSA_ENC "RSA_Encrypt"
+# define OSSL_SELF_TEST_DESC_ASYM_RSA_DEC "RSA_Decrypt"
+# define OSSL_SELF_TEST_DESC_MD_SHA1 "SHA1"
+# define OSSL_SELF_TEST_DESC_MD_SHA2 "SHA2"
+# define OSSL_SELF_TEST_DESC_MD_SHA3 "SHA3"
+# define OSSL_SELF_TEST_DESC_SIGN_DSA "DSA"
+# define OSSL_SELF_TEST_DESC_SIGN_RSA "RSA"
+# define OSSL_SELF_TEST_DESC_SIGN_ECDSA "ECDSA"
+# define OSSL_SELF_TEST_DESC_DRBG_CTR "CTR"
+# define OSSL_SELF_TEST_DESC_DRBG_HASH "HASH"
+# define OSSL_SELF_TEST_DESC_DRBG_HMAC "HMAC"
+# define OSSL_SELF_TEST_DESC_KA_DH "DH"
+# define OSSL_SELF_TEST_DESC_KA_ECDH "ECDH"
+# define OSSL_SELF_TEST_DESC_KDF_HKDF "HKDF"
+# define OSSL_SELF_TEST_DESC_KDF_SSKDF "SSKDF"
+# define OSSL_SELF_TEST_DESC_KDF_X963KDF "X963KDF"
+# define OSSL_SELF_TEST_DESC_KDF_X942KDF "X942KDF"
+# define OSSL_SELF_TEST_DESC_KDF_PBKDF2 "PBKDF2"
+# define OSSL_SELF_TEST_DESC_KDF_SSHKDF "SSHKDF"
+# define OSSL_SELF_TEST_DESC_KDF_TLS12_PRF "TLS12_PRF"
+# define OSSL_SELF_TEST_DESC_KDF_KBKDF "KBKDF"
+# define OSSL_SELF_TEST_DESC_KDF_TLS13_EXTRACT "TLS13_KDF_EXTRACT"
+# define OSSL_SELF_TEST_DESC_KDF_TLS13_EXPAND "TLS13_KDF_EXPAND"
+# define OSSL_SELF_TEST_DESC_RNG "RNG"
+
+void OSSL_SELF_TEST_set_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK *cb,
+ void *cbarg);
+void OSSL_SELF_TEST_get_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK **cb,
+ void **cbarg);
+
+OSSL_SELF_TEST *OSSL_SELF_TEST_new(OSSL_CALLBACK *cb, void *cbarg);
+void OSSL_SELF_TEST_free(OSSL_SELF_TEST *st);
+
+void OSSL_SELF_TEST_onbegin(OSSL_SELF_TEST *st, const char *type,
+ const char *desc);
+int OSSL_SELF_TEST_oncorrupt_byte(OSSL_SELF_TEST *st, unsigned char *bytes);
+void OSSL_SELF_TEST_onend(OSSL_SELF_TEST *st, int ret);
+
+# ifdef __cplusplus
+}
+# endif
+#endif /* OPENSSL_SELF_TEST_H */
diff --git a/include/openssl/sha.h b/include/openssl/sha.h
index 6a1eb0de8bd7..6e65a0408969 100644
--- a/include/openssl/sha.h
+++ b/include/openssl/sha.h
@@ -1,35 +1,43 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_SHA_H
-# define HEADER_SHA_H
+#ifndef OPENSSL_SHA_H
+# define OPENSSL_SHA_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_SHA_H
+# endif
# include <openssl/e_os2.h>
# include <stddef.h>
-#ifdef __cplusplus
+# ifdef __cplusplus
extern "C" {
-#endif
+# endif
+# define SHA_DIGEST_LENGTH 20
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
/*-
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* ! SHA_LONG has to be at least 32 bits wide. !
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
-# define SHA_LONG unsigned int
+# define SHA_LONG unsigned int
-# define SHA_LBLOCK 16
-# define SHA_CBLOCK (SHA_LBLOCK*4)/* SHA treats input data as a
- * contiguous array of 32 bit wide
- * big-endian values. */
-# define SHA_LAST_BLOCK (SHA_CBLOCK-8)
-# define SHA_DIGEST_LENGTH 20
+# define SHA_LBLOCK 16
+# define SHA_CBLOCK (SHA_LBLOCK*4)/* SHA treats input data as a
+ * contiguous array of 32 bit wide
+ * big-endian values. */
+# define SHA_LAST_BLOCK (SHA_CBLOCK-8)
typedef struct SHAstate_st {
SHA_LONG h0, h1, h2, h3, h4;
@@ -38,13 +46,16 @@ typedef struct SHAstate_st {
unsigned int num;
} SHA_CTX;
-int SHA1_Init(SHA_CTX *c);
-int SHA1_Update(SHA_CTX *c, const void *data, size_t len);
-int SHA1_Final(unsigned char *md, SHA_CTX *c);
+OSSL_DEPRECATEDIN_3_0 int SHA1_Init(SHA_CTX *c);
+OSSL_DEPRECATEDIN_3_0 int SHA1_Update(SHA_CTX *c, const void *data, size_t len);
+OSSL_DEPRECATEDIN_3_0 int SHA1_Final(unsigned char *md, SHA_CTX *c);
+OSSL_DEPRECATEDIN_3_0 void SHA1_Transform(SHA_CTX *c, const unsigned char *data);
+# endif
+
unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md);
-void SHA1_Transform(SHA_CTX *c, const unsigned char *data);
-# define SHA256_CBLOCK (SHA_LBLOCK*4)/* SHA-256 treats input data as a
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define SHA256_CBLOCK (SHA_LBLOCK*4)/* SHA-256 treats input data as a
* contiguous array of 32 bit wide
* big-endian values. */
@@ -55,21 +66,27 @@ typedef struct SHA256state_st {
unsigned int num, md_len;
} SHA256_CTX;
-int SHA224_Init(SHA256_CTX *c);
-int SHA224_Update(SHA256_CTX *c, const void *data, size_t len);
-int SHA224_Final(unsigned char *md, SHA256_CTX *c);
+OSSL_DEPRECATEDIN_3_0 int SHA224_Init(SHA256_CTX *c);
+OSSL_DEPRECATEDIN_3_0 int SHA224_Update(SHA256_CTX *c,
+ const void *data, size_t len);
+OSSL_DEPRECATEDIN_3_0 int SHA224_Final(unsigned char *md, SHA256_CTX *c);
+OSSL_DEPRECATEDIN_3_0 int SHA256_Init(SHA256_CTX *c);
+OSSL_DEPRECATEDIN_3_0 int SHA256_Update(SHA256_CTX *c,
+ const void *data, size_t len);
+OSSL_DEPRECATEDIN_3_0 int SHA256_Final(unsigned char *md, SHA256_CTX *c);
+OSSL_DEPRECATEDIN_3_0 void SHA256_Transform(SHA256_CTX *c,
+ const unsigned char *data);
+# endif
+
unsigned char *SHA224(const unsigned char *d, size_t n, unsigned char *md);
-int SHA256_Init(SHA256_CTX *c);
-int SHA256_Update(SHA256_CTX *c, const void *data, size_t len);
-int SHA256_Final(unsigned char *md, SHA256_CTX *c);
unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md);
-void SHA256_Transform(SHA256_CTX *c, const unsigned char *data);
# define SHA224_DIGEST_LENGTH 28
# define SHA256_DIGEST_LENGTH 32
# define SHA384_DIGEST_LENGTH 48
# define SHA512_DIGEST_LENGTH 64
+# ifndef OPENSSL_NO_DEPRECATED_3_0
/*
* Unlike 32-bit digest algorithms, SHA-512 *relies* on SHA_LONG64
* being exactly 64-bit wide. See Implementation Notes in sha512.c
@@ -80,17 +97,14 @@ void SHA256_Transform(SHA256_CTX *c, const unsigned char *data);
* contiguous array of 64 bit
* wide big-endian values.
*/
-# define SHA512_CBLOCK (SHA_LBLOCK*8)
-# if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
-# define SHA_LONG64 unsigned __int64
-# define U64(C) C##UI64
-# elif defined(__arch64__)
-# define SHA_LONG64 unsigned long
-# define U64(C) C##UL
-# else
-# define SHA_LONG64 unsigned long long
-# define U64(C) C##ULL
-# endif
+# define SHA512_CBLOCK (SHA_LBLOCK*8)
+# if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
+# define SHA_LONG64 unsigned __int64
+# elif defined(__arch64__)
+# define SHA_LONG64 unsigned long
+# else
+# define SHA_LONG64 unsigned long long
+# endif
typedef struct SHA512state_st {
SHA_LONG64 h[8];
@@ -102,18 +116,23 @@ typedef struct SHA512state_st {
unsigned int num, md_len;
} SHA512_CTX;
-int SHA384_Init(SHA512_CTX *c);
-int SHA384_Update(SHA512_CTX *c, const void *data, size_t len);
-int SHA384_Final(unsigned char *md, SHA512_CTX *c);
+OSSL_DEPRECATEDIN_3_0 int SHA384_Init(SHA512_CTX *c);
+OSSL_DEPRECATEDIN_3_0 int SHA384_Update(SHA512_CTX *c,
+ const void *data, size_t len);
+OSSL_DEPRECATEDIN_3_0 int SHA384_Final(unsigned char *md, SHA512_CTX *c);
+OSSL_DEPRECATEDIN_3_0 int SHA512_Init(SHA512_CTX *c);
+OSSL_DEPRECATEDIN_3_0 int SHA512_Update(SHA512_CTX *c,
+ const void *data, size_t len);
+OSSL_DEPRECATEDIN_3_0 int SHA512_Final(unsigned char *md, SHA512_CTX *c);
+OSSL_DEPRECATEDIN_3_0 void SHA512_Transform(SHA512_CTX *c,
+ const unsigned char *data);
+# endif
+
unsigned char *SHA384(const unsigned char *d, size_t n, unsigned char *md);
-int SHA512_Init(SHA512_CTX *c);
-int SHA512_Update(SHA512_CTX *c, const void *data, size_t len);
-int SHA512_Final(unsigned char *md, SHA512_CTX *c);
unsigned char *SHA512(const unsigned char *d, size_t n, unsigned char *md);
-void SHA512_Transform(SHA512_CTX *c, const unsigned char *data);
-#ifdef __cplusplus
+# ifdef __cplusplus
}
-#endif
+# endif
#endif
diff --git a/include/openssl/srp.h b/include/openssl/srp.h
deleted file mode 100644
index aaf13558e3cb..000000000000
--- a/include/openssl/srp.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright (c) 2004, EdelKey Project. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- *
- * Originally written by Christophe Renou and Peter Sylvester,
- * for the EdelKey project.
- */
-
-#ifndef HEADER_SRP_H
-# define HEADER_SRP_H
-
-#include <openssl/opensslconf.h>
-
-#ifndef OPENSSL_NO_SRP
-# include <stdio.h>
-# include <string.h>
-# include <openssl/safestack.h>
-# include <openssl/bn.h>
-# include <openssl/crypto.h>
-
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-typedef struct SRP_gN_cache_st {
- char *b64_bn;
- BIGNUM *bn;
-} SRP_gN_cache;
-
-
-DEFINE_STACK_OF(SRP_gN_cache)
-
-typedef struct SRP_user_pwd_st {
- /* Owned by us. */
- char *id;
- BIGNUM *s;
- BIGNUM *v;
- /* Not owned by us. */
- const BIGNUM *g;
- const BIGNUM *N;
- /* Owned by us. */
- char *info;
-} SRP_user_pwd;
-
-void SRP_user_pwd_free(SRP_user_pwd *user_pwd);
-
-DEFINE_STACK_OF(SRP_user_pwd)
-
-typedef struct SRP_VBASE_st {
- STACK_OF(SRP_user_pwd) *users_pwd;
- STACK_OF(SRP_gN_cache) *gN_cache;
-/* to simulate a user */
- char *seed_key;
- const BIGNUM *default_g;
- const BIGNUM *default_N;
-} SRP_VBASE;
-
-/*
- * Internal structure storing N and g pair
- */
-typedef struct SRP_gN_st {
- char *id;
- const BIGNUM *g;
- const BIGNUM *N;
-} SRP_gN;
-
-DEFINE_STACK_OF(SRP_gN)
-
-SRP_VBASE *SRP_VBASE_new(char *seed_key);
-void SRP_VBASE_free(SRP_VBASE *vb);
-int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file);
-
-/* This method ignores the configured seed and fails for an unknown user. */
-DEPRECATEDIN_1_1_0(SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username))
-/* NOTE: unlike in SRP_VBASE_get_by_user, caller owns the returned pointer.*/
-SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username);
-
-char *SRP_create_verifier(const char *user, const char *pass, char **salt,
- char **verifier, const char *N, const char *g);
-int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt,
- BIGNUM **verifier, const BIGNUM *N,
- const BIGNUM *g);
-
-# define SRP_NO_ERROR 0
-# define SRP_ERR_VBASE_INCOMPLETE_FILE 1
-# define SRP_ERR_VBASE_BN_LIB 2
-# define SRP_ERR_OPEN_FILE 3
-# define SRP_ERR_MEMORY 4
-
-# define DB_srptype 0
-# define DB_srpverifier 1
-# define DB_srpsalt 2
-# define DB_srpid 3
-# define DB_srpgN 4
-# define DB_srpinfo 5
-# undef DB_NUMBER
-# define DB_NUMBER 6
-
-# define DB_SRP_INDEX 'I'
-# define DB_SRP_VALID 'V'
-# define DB_SRP_REVOKED 'R'
-# define DB_SRP_MODIF 'v'
-
-/* see srp.c */
-char *SRP_check_known_gN_param(const BIGNUM *g, const BIGNUM *N);
-SRP_gN *SRP_get_default_gN(const char *id);
-
-/* server side .... */
-BIGNUM *SRP_Calc_server_key(const BIGNUM *A, const BIGNUM *v, const BIGNUM *u,
- const BIGNUM *b, const BIGNUM *N);
-BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g,
- const BIGNUM *v);
-int SRP_Verify_A_mod_N(const BIGNUM *A, const BIGNUM *N);
-BIGNUM *SRP_Calc_u(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N);
-
-/* client side .... */
-BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass);
-BIGNUM *SRP_Calc_A(const BIGNUM *a, const BIGNUM *N, const BIGNUM *g);
-BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g,
- const BIGNUM *x, const BIGNUM *a, const BIGNUM *u);
-int SRP_Verify_B_mod_N(const BIGNUM *B, const BIGNUM *N);
-
-# define SRP_MINIMAL_N 1024
-
-# ifdef __cplusplus
-}
-# endif
-# endif
-
-#endif
diff --git a/include/openssl/srp.h.in b/include/openssl/srp.h.in
new file mode 100644
index 000000000000..dfbe845b8387
--- /dev/null
+++ b/include/openssl/srp.h.in
@@ -0,0 +1,214 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2004, EdelKey Project. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Christophe Renou and Peter Sylvester,
+ * for the EdelKey project.
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_SRP_H
+# define OPENSSL_SRP_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_SRP_H
+# endif
+
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_NO_SRP
+# include <stdio.h>
+# include <string.h>
+# include <openssl/safestack.h>
+# include <openssl/bn.h>
+# include <openssl/crypto.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+
+typedef struct SRP_gN_cache_st {
+ char *b64_bn;
+ BIGNUM *bn;
+} SRP_gN_cache;
+{-
+ generate_stack_macros("SRP_gN_cache");
+-}
+
+
+typedef struct SRP_user_pwd_st {
+ /* Owned by us. */
+ char *id;
+ BIGNUM *s;
+ BIGNUM *v;
+ /* Not owned by us. */
+ const BIGNUM *g;
+ const BIGNUM *N;
+ /* Owned by us. */
+ char *info;
+} SRP_user_pwd;
+{-
+ generate_stack_macros("SRP_user_pwd");
+-}
+
+OSSL_DEPRECATEDIN_3_0
+SRP_user_pwd *SRP_user_pwd_new(void);
+OSSL_DEPRECATEDIN_3_0
+void SRP_user_pwd_free(SRP_user_pwd *user_pwd);
+
+OSSL_DEPRECATEDIN_3_0
+void SRP_user_pwd_set_gN(SRP_user_pwd *user_pwd, const BIGNUM *g,
+ const BIGNUM *N);
+OSSL_DEPRECATEDIN_3_0
+int SRP_user_pwd_set1_ids(SRP_user_pwd *user_pwd, const char *id,
+ const char *info);
+OSSL_DEPRECATEDIN_3_0
+int SRP_user_pwd_set0_sv(SRP_user_pwd *user_pwd, BIGNUM *s, BIGNUM *v);
+
+typedef struct SRP_VBASE_st {
+ STACK_OF(SRP_user_pwd) *users_pwd;
+ STACK_OF(SRP_gN_cache) *gN_cache;
+/* to simulate a user */
+ char *seed_key;
+ const BIGNUM *default_g;
+ const BIGNUM *default_N;
+} SRP_VBASE;
+
+/*
+ * Internal structure storing N and g pair
+ */
+typedef struct SRP_gN_st {
+ char *id;
+ const BIGNUM *g;
+ const BIGNUM *N;
+} SRP_gN;
+{-
+ generate_stack_macros("SRP_gN");
+-}
+
+
+OSSL_DEPRECATEDIN_3_0
+SRP_VBASE *SRP_VBASE_new(char *seed_key);
+OSSL_DEPRECATEDIN_3_0
+void SRP_VBASE_free(SRP_VBASE *vb);
+OSSL_DEPRECATEDIN_3_0
+int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file);
+
+OSSL_DEPRECATEDIN_3_0
+int SRP_VBASE_add0_user(SRP_VBASE *vb, SRP_user_pwd *user_pwd);
+
+/* NOTE: unlike in SRP_VBASE_get_by_user, caller owns the returned pointer.*/
+OSSL_DEPRECATEDIN_3_0
+SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username);
+
+OSSL_DEPRECATEDIN_3_0
+char *SRP_create_verifier_ex(const char *user, const char *pass, char **salt,
+ char **verifier, const char *N, const char *g,
+ OSSL_LIB_CTX *libctx, const char *propq);
+OSSL_DEPRECATEDIN_3_0
+char *SRP_create_verifier(const char *user, const char *pass, char **salt,
+ char **verifier, const char *N, const char *g);
+OSSL_DEPRECATEDIN_3_0
+int SRP_create_verifier_BN_ex(const char *user, const char *pass, BIGNUM **salt,
+ BIGNUM **verifier, const BIGNUM *N,
+ const BIGNUM *g, OSSL_LIB_CTX *libctx,
+ const char *propq);
+OSSL_DEPRECATEDIN_3_0
+int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt,
+ BIGNUM **verifier, const BIGNUM *N,
+ const BIGNUM *g);
+
+# define SRP_NO_ERROR 0
+# define SRP_ERR_VBASE_INCOMPLETE_FILE 1
+# define SRP_ERR_VBASE_BN_LIB 2
+# define SRP_ERR_OPEN_FILE 3
+# define SRP_ERR_MEMORY 4
+
+# define DB_srptype 0
+# define DB_srpverifier 1
+# define DB_srpsalt 2
+# define DB_srpid 3
+# define DB_srpgN 4
+# define DB_srpinfo 5
+# undef DB_NUMBER
+# define DB_NUMBER 6
+
+# define DB_SRP_INDEX 'I'
+# define DB_SRP_VALID 'V'
+# define DB_SRP_REVOKED 'R'
+# define DB_SRP_MODIF 'v'
+
+/* see srp.c */
+OSSL_DEPRECATEDIN_3_0
+char *SRP_check_known_gN_param(const BIGNUM *g, const BIGNUM *N);
+OSSL_DEPRECATEDIN_3_0
+SRP_gN *SRP_get_default_gN(const char *id);
+
+/* server side .... */
+OSSL_DEPRECATEDIN_3_0
+BIGNUM *SRP_Calc_server_key(const BIGNUM *A, const BIGNUM *v, const BIGNUM *u,
+ const BIGNUM *b, const BIGNUM *N);
+OSSL_DEPRECATEDIN_3_0
+BIGNUM *SRP_Calc_B_ex(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g,
+ const BIGNUM *v, OSSL_LIB_CTX *libctx, const char *propq);
+OSSL_DEPRECATEDIN_3_0
+BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g,
+ const BIGNUM *v);
+
+OSSL_DEPRECATEDIN_3_0
+int SRP_Verify_A_mod_N(const BIGNUM *A, const BIGNUM *N);
+OSSL_DEPRECATEDIN_3_0
+BIGNUM *SRP_Calc_u_ex(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N,
+ OSSL_LIB_CTX *libctx, const char *propq);
+OSSL_DEPRECATEDIN_3_0
+BIGNUM *SRP_Calc_u(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N);
+
+/* client side .... */
+
+OSSL_DEPRECATEDIN_3_0
+BIGNUM *SRP_Calc_x_ex(const BIGNUM *s, const char *user, const char *pass,
+ OSSL_LIB_CTX *libctx, const char *propq);
+OSSL_DEPRECATEDIN_3_0
+BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass);
+OSSL_DEPRECATEDIN_3_0
+BIGNUM *SRP_Calc_A(const BIGNUM *a, const BIGNUM *N, const BIGNUM *g);
+OSSL_DEPRECATEDIN_3_0
+BIGNUM *SRP_Calc_client_key_ex(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g,
+ const BIGNUM *x, const BIGNUM *a, const BIGNUM *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
+OSSL_DEPRECATEDIN_3_0
+BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g,
+ const BIGNUM *x, const BIGNUM *a, const BIGNUM *u);
+OSSL_DEPRECATEDIN_3_0
+int SRP_Verify_B_mod_N(const BIGNUM *B, const BIGNUM *N);
+
+# define SRP_MINIMAL_N 1024
+
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
+
+/* This method ignores the configured seed and fails for an unknown user. */
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0
+SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username);
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+# endif
+
+#endif
diff --git a/include/openssl/srtp.h b/include/openssl/srtp.h
index 0b57c2356c9e..d64606e5d9c8 100644
--- a/include/openssl/srtp.h
+++ b/include/openssl/srtp.h
@@ -1,7 +1,7 @@
/*
* Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,8 +13,14 @@
* Copyright (C) 2006, Network Resonance, Inc. Copyright (C) 2011, RTFM, Inc.
*/
-#ifndef HEADER_D1_SRTP_H
-# define HEADER_D1_SRTP_H
+#ifndef OPENSSL_SRTP_H
+# define OPENSSL_SRTP_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_D1_SRTP_H
+# endif
# include <openssl/ssl.h>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
deleted file mode 100644
index 9af0c8995ecc..000000000000
--- a/include/openssl/ssl.h
+++ /dev/null
@@ -1,2448 +0,0 @@
-/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
- * Copyright 2005 Nokia. All rights reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_SSL_H
-# define HEADER_SSL_H
-
-# include <openssl/e_os2.h>
-# include <openssl/opensslconf.h>
-# include <openssl/comp.h>
-# include <openssl/bio.h>
-# if OPENSSL_API_COMPAT < 0x10100000L
-# include <openssl/x509.h>
-# include <openssl/crypto.h>
-# include <openssl/buffer.h>
-# endif
-# include <openssl/lhash.h>
-# include <openssl/pem.h>
-# include <openssl/hmac.h>
-# include <openssl/async.h>
-
-# include <openssl/safestack.h>
-# include <openssl/symhacks.h>
-# include <openssl/ct.h>
-# include <openssl/sslerr.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* OpenSSL version number for ASN.1 encoding of the session information */
-/*-
- * Version 0 - initial version
- * Version 1 - added the optional peer certificate
- */
-# define SSL_SESSION_ASN1_VERSION 0x0001
-
-# define SSL_MAX_SSL_SESSION_ID_LENGTH 32
-# define SSL_MAX_SID_CTX_LENGTH 32
-
-# define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES (512/8)
-# define SSL_MAX_KEY_ARG_LENGTH 8
-# define SSL_MAX_MASTER_KEY_LENGTH 48
-
-/* The maximum number of encrypt/decrypt pipelines we can support */
-# define SSL_MAX_PIPELINES 32
-
-/* text strings for the ciphers */
-
-/* These are used to specify which ciphers to use and not to use */
-
-# define SSL_TXT_LOW "LOW"
-# define SSL_TXT_MEDIUM "MEDIUM"
-# define SSL_TXT_HIGH "HIGH"
-# define SSL_TXT_FIPS "FIPS"
-
-# define SSL_TXT_aNULL "aNULL"
-# define SSL_TXT_eNULL "eNULL"
-# define SSL_TXT_NULL "NULL"
-
-# define SSL_TXT_kRSA "kRSA"
-# define SSL_TXT_kDHr "kDHr"/* this cipher class has been removed */
-# define SSL_TXT_kDHd "kDHd"/* this cipher class has been removed */
-# define SSL_TXT_kDH "kDH"/* this cipher class has been removed */
-# define SSL_TXT_kEDH "kEDH"/* alias for kDHE */
-# define SSL_TXT_kDHE "kDHE"
-# define SSL_TXT_kECDHr "kECDHr"/* this cipher class has been removed */
-# define SSL_TXT_kECDHe "kECDHe"/* this cipher class has been removed */
-# define SSL_TXT_kECDH "kECDH"/* this cipher class has been removed */
-# define SSL_TXT_kEECDH "kEECDH"/* alias for kECDHE */
-# define SSL_TXT_kECDHE "kECDHE"
-# define SSL_TXT_kPSK "kPSK"
-# define SSL_TXT_kRSAPSK "kRSAPSK"
-# define SSL_TXT_kECDHEPSK "kECDHEPSK"
-# define SSL_TXT_kDHEPSK "kDHEPSK"
-# define SSL_TXT_kGOST "kGOST"
-# define SSL_TXT_kSRP "kSRP"
-
-# define SSL_TXT_aRSA "aRSA"
-# define SSL_TXT_aDSS "aDSS"
-# define SSL_TXT_aDH "aDH"/* this cipher class has been removed */
-# define SSL_TXT_aECDH "aECDH"/* this cipher class has been removed */
-# define SSL_TXT_aECDSA "aECDSA"
-# define SSL_TXT_aPSK "aPSK"
-# define SSL_TXT_aGOST94 "aGOST94"
-# define SSL_TXT_aGOST01 "aGOST01"
-# define SSL_TXT_aGOST12 "aGOST12"
-# define SSL_TXT_aGOST "aGOST"
-# define SSL_TXT_aSRP "aSRP"
-
-# define SSL_TXT_DSS "DSS"
-# define SSL_TXT_DH "DH"
-# define SSL_TXT_DHE "DHE"/* same as "kDHE:-ADH" */
-# define SSL_TXT_EDH "EDH"/* alias for DHE */
-# define SSL_TXT_ADH "ADH"
-# define SSL_TXT_RSA "RSA"
-# define SSL_TXT_ECDH "ECDH"
-# define SSL_TXT_EECDH "EECDH"/* alias for ECDHE" */
-# define SSL_TXT_ECDHE "ECDHE"/* same as "kECDHE:-AECDH" */
-# define SSL_TXT_AECDH "AECDH"
-# define SSL_TXT_ECDSA "ECDSA"
-# define SSL_TXT_PSK "PSK"
-# define SSL_TXT_SRP "SRP"
-
-# define SSL_TXT_DES "DES"
-# define SSL_TXT_3DES "3DES"
-# define SSL_TXT_RC4 "RC4"
-# define SSL_TXT_RC2 "RC2"
-# define SSL_TXT_IDEA "IDEA"
-# define SSL_TXT_SEED "SEED"
-# define SSL_TXT_AES128 "AES128"
-# define SSL_TXT_AES256 "AES256"
-# define SSL_TXT_AES "AES"
-# define SSL_TXT_AES_GCM "AESGCM"
-# define SSL_TXT_AES_CCM "AESCCM"
-# define SSL_TXT_AES_CCM_8 "AESCCM8"
-# define SSL_TXT_CAMELLIA128 "CAMELLIA128"
-# define SSL_TXT_CAMELLIA256 "CAMELLIA256"
-# define SSL_TXT_CAMELLIA "CAMELLIA"
-# define SSL_TXT_CHACHA20 "CHACHA20"
-# define SSL_TXT_GOST "GOST89"
-# define SSL_TXT_ARIA "ARIA"
-# define SSL_TXT_ARIA_GCM "ARIAGCM"
-# define SSL_TXT_ARIA128 "ARIA128"
-# define SSL_TXT_ARIA256 "ARIA256"
-
-# define SSL_TXT_MD5 "MD5"
-# define SSL_TXT_SHA1 "SHA1"
-# define SSL_TXT_SHA "SHA"/* same as "SHA1" */
-# define SSL_TXT_GOST94 "GOST94"
-# define SSL_TXT_GOST89MAC "GOST89MAC"
-# define SSL_TXT_GOST12 "GOST12"
-# define SSL_TXT_GOST89MAC12 "GOST89MAC12"
-# define SSL_TXT_SHA256 "SHA256"
-# define SSL_TXT_SHA384 "SHA384"
-
-# define SSL_TXT_SSLV3 "SSLv3"
-# define SSL_TXT_TLSV1 "TLSv1"
-# define SSL_TXT_TLSV1_1 "TLSv1.1"
-# define SSL_TXT_TLSV1_2 "TLSv1.2"
-
-# define SSL_TXT_ALL "ALL"
-
-/*-
- * COMPLEMENTOF* definitions. These identifiers are used to (de-select)
- * ciphers normally not being used.
- * Example: "RC4" will activate all ciphers using RC4 including ciphers
- * without authentication, which would normally disabled by DEFAULT (due
- * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT"
- * will make sure that it is also disabled in the specific selection.
- * COMPLEMENTOF* identifiers are portable between version, as adjustments
- * to the default cipher setup will also be included here.
- *
- * COMPLEMENTOFDEFAULT does not experience the same special treatment that
- * DEFAULT gets, as only selection is being done and no sorting as needed
- * for DEFAULT.
- */
-# define SSL_TXT_CMPALL "COMPLEMENTOFALL"
-# define SSL_TXT_CMPDEF "COMPLEMENTOFDEFAULT"
-
-/*
- * The following cipher list is used by default. It also is substituted when
- * an application-defined cipher list string starts with 'DEFAULT'.
- * This applies to ciphersuites for TLSv1.2 and below.
- */
-# define SSL_DEFAULT_CIPHER_LIST "ALL:!COMPLEMENTOFDEFAULT:!eNULL"
-/* This is the default set of TLSv1.3 ciphersuites */
-# if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
-# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \
- "TLS_CHACHA20_POLY1305_SHA256:" \
- "TLS_AES_128_GCM_SHA256"
-# else
-# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \
- "TLS_AES_128_GCM_SHA256"
-#endif
-/*
- * As of OpenSSL 1.0.0, ssl_create_cipher_list() in ssl/ssl_ciph.c always
- * starts with a reasonable order, and all we have to do for DEFAULT is
- * throwing out anonymous and unencrypted ciphersuites! (The latter are not
- * actually enabled by ALL, but "ALL:RSA" would enable some of them.)
- */
-
-/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */
-# define SSL_SENT_SHUTDOWN 1
-# define SSL_RECEIVED_SHUTDOWN 2
-
-#ifdef __cplusplus
-}
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-# define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1
-# define SSL_FILETYPE_PEM X509_FILETYPE_PEM
-
-/*
- * This is needed to stop compilers complaining about the 'struct ssl_st *'
- * function parameters used to prototype callbacks in SSL_CTX.
- */
-typedef struct ssl_st *ssl_crock_st;
-typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
-typedef struct ssl_method_st SSL_METHOD;
-typedef struct ssl_cipher_st SSL_CIPHER;
-typedef struct ssl_session_st SSL_SESSION;
-typedef struct tls_sigalgs_st TLS_SIGALGS;
-typedef struct ssl_conf_ctx_st SSL_CONF_CTX;
-typedef struct ssl_comp_st SSL_COMP;
-
-STACK_OF(SSL_CIPHER);
-STACK_OF(SSL_COMP);
-
-/* SRTP protection profiles for use with the use_srtp extension (RFC 5764)*/
-typedef struct srtp_protection_profile_st {
- const char *name;
- unsigned long id;
-} SRTP_PROTECTION_PROFILE;
-
-DEFINE_STACK_OF(SRTP_PROTECTION_PROFILE)
-
-typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data,
- int len, void *arg);
-typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len,
- STACK_OF(SSL_CIPHER) *peer_ciphers,
- const SSL_CIPHER **cipher, void *arg);
-
-/* Extension context codes */
-/* This extension is only allowed in TLS */
-#define SSL_EXT_TLS_ONLY 0x0001
-/* This extension is only allowed in DTLS */
-#define SSL_EXT_DTLS_ONLY 0x0002
-/* Some extensions may be allowed in DTLS but we don't implement them for it */
-#define SSL_EXT_TLS_IMPLEMENTATION_ONLY 0x0004
-/* Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is */
-#define SSL_EXT_SSL3_ALLOWED 0x0008
-/* Extension is only defined for TLS1.2 and below */
-#define SSL_EXT_TLS1_2_AND_BELOW_ONLY 0x0010
-/* Extension is only defined for TLS1.3 and above */
-#define SSL_EXT_TLS1_3_ONLY 0x0020
-/* Ignore this extension during parsing if we are resuming */
-#define SSL_EXT_IGNORE_ON_RESUMPTION 0x0040
-#define SSL_EXT_CLIENT_HELLO 0x0080
-/* Really means TLS1.2 or below */
-#define SSL_EXT_TLS1_2_SERVER_HELLO 0x0100
-#define SSL_EXT_TLS1_3_SERVER_HELLO 0x0200
-#define SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS 0x0400
-#define SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST 0x0800
-#define SSL_EXT_TLS1_3_CERTIFICATE 0x1000
-#define SSL_EXT_TLS1_3_NEW_SESSION_TICKET 0x2000
-#define SSL_EXT_TLS1_3_CERTIFICATE_REQUEST 0x4000
-
-/* Typedefs for handling custom extensions */
-
-typedef int (*custom_ext_add_cb)(SSL *s, unsigned int ext_type,
- const unsigned char **out, size_t *outlen,
- int *al, void *add_arg);
-
-typedef void (*custom_ext_free_cb)(SSL *s, unsigned int ext_type,
- const unsigned char *out, void *add_arg);
-
-typedef int (*custom_ext_parse_cb)(SSL *s, unsigned int ext_type,
- const unsigned char *in, size_t inlen,
- int *al, void *parse_arg);
-
-
-typedef int (*SSL_custom_ext_add_cb_ex)(SSL *s, unsigned int ext_type,
- unsigned int context,
- const unsigned char **out,
- size_t *outlen, X509 *x,
- size_t chainidx,
- int *al, void *add_arg);
-
-typedef void (*SSL_custom_ext_free_cb_ex)(SSL *s, unsigned int ext_type,
- unsigned int context,
- const unsigned char *out,
- void *add_arg);
-
-typedef int (*SSL_custom_ext_parse_cb_ex)(SSL *s, unsigned int ext_type,
- unsigned int context,
- const unsigned char *in,
- size_t inlen, X509 *x,
- size_t chainidx,
- int *al, void *parse_arg);
-
-/* Typedef for verification callback */
-typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx);
-
-/*
- * Some values are reserved until OpenSSL 1.2.0 because they were previously
- * included in SSL_OP_ALL in a 1.1.x release.
- *
- * Reserved value (until OpenSSL 1.2.0) 0x00000001U
- * Reserved value (until OpenSSL 1.2.0) 0x00000002U
- */
-/* Allow initial connection to servers that don't support RI */
-# define SSL_OP_LEGACY_SERVER_CONNECT 0x00000004U
-
-/* Reserved value (until OpenSSL 1.2.0) 0x00000008U */
-# define SSL_OP_TLSEXT_PADDING 0x00000010U
-/* Reserved value (until OpenSSL 1.2.0) 0x00000020U */
-# define SSL_OP_SAFARI_ECDHE_ECDSA_BUG 0x00000040U
-/*
- * Reserved value (until OpenSSL 1.2.0) 0x00000080U
- * Reserved value (until OpenSSL 1.2.0) 0x00000100U
- * Reserved value (until OpenSSL 1.2.0) 0x00000200U
- */
-
-/* In TLSv1.3 allow a non-(ec)dhe based kex_mode */
-# define SSL_OP_ALLOW_NO_DHE_KEX 0x00000400U
-
-/*
- * Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added in
- * OpenSSL 0.9.6d. Usually (depending on the application protocol) the
- * workaround is not needed. Unfortunately some broken SSL/TLS
- * implementations cannot handle it at all, which is why we include it in
- * SSL_OP_ALL. Added in 0.9.6e
- */
-# define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800U
-
-/* DTLS options */
-# define SSL_OP_NO_QUERY_MTU 0x00001000U
-/* Turn on Cookie Exchange (on relevant for servers) */
-# define SSL_OP_COOKIE_EXCHANGE 0x00002000U
-/* Don't use RFC4507 ticket extension */
-# define SSL_OP_NO_TICKET 0x00004000U
-# ifndef OPENSSL_NO_DTLS1_METHOD
-/* Use Cisco's "speshul" version of DTLS_BAD_VER
- * (only with deprecated DTLSv1_client_method()) */
-# define SSL_OP_CISCO_ANYCONNECT 0x00008000U
-# endif
-
-/* As server, disallow session resumption on renegotiation */
-# define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000U
-/* Don't use compression even if supported */
-# define SSL_OP_NO_COMPRESSION 0x00020000U
-/* Permit unsafe legacy renegotiation */
-# define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000U
-/* Disable encrypt-then-mac */
-# define SSL_OP_NO_ENCRYPT_THEN_MAC 0x00080000U
-
-/*
- * Enable TLSv1.3 Compatibility mode. This is on by default. A future version
- * of OpenSSL may have this disabled by default.
- */
-# define SSL_OP_ENABLE_MIDDLEBOX_COMPAT 0x00100000U
-
-/* Prioritize Chacha20Poly1305 when client does.
- * Modifies SSL_OP_CIPHER_SERVER_PREFERENCE */
-# define SSL_OP_PRIORITIZE_CHACHA 0x00200000U
-
-/*
- * Set on servers to choose the cipher according to the server's preferences
- */
-# define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000U
-/*
- * If set, a server will allow a client to issue a SSLv3.0 version number as
- * latest version supported in the premaster secret, even when TLSv1.0
- * (version 3.1) was announced in the client hello. Normally this is
- * forbidden to prevent version rollback attacks.
- */
-# define SSL_OP_TLS_ROLLBACK_BUG 0x00800000U
-
-/*
- * Switches off automatic TLSv1.3 anti-replay protection for early data. This
- * is a server-side option only (no effect on the client).
- */
-# define SSL_OP_NO_ANTI_REPLAY 0x01000000U
-
-# define SSL_OP_NO_SSLv3 0x02000000U
-# define SSL_OP_NO_TLSv1 0x04000000U
-# define SSL_OP_NO_TLSv1_2 0x08000000U
-# define SSL_OP_NO_TLSv1_1 0x10000000U
-# define SSL_OP_NO_TLSv1_3 0x20000000U
-
-# define SSL_OP_NO_DTLSv1 0x04000000U
-# define SSL_OP_NO_DTLSv1_2 0x08000000U
-
-# define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv3|\
- SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2|SSL_OP_NO_TLSv1_3)
-# define SSL_OP_NO_DTLS_MASK (SSL_OP_NO_DTLSv1|SSL_OP_NO_DTLSv1_2)
-
-/* Disallow all renegotiation */
-# define SSL_OP_NO_RENEGOTIATION 0x40000000U
-
-/*
- * Make server add server-hello extension from early version of cryptopro
- * draft, when GOST ciphersuite is negotiated. Required for interoperability
- * with CryptoPro CSP 3.x
- */
-# define SSL_OP_CRYPTOPRO_TLSEXT_BUG 0x80000000U
-
-/*
- * SSL_OP_ALL: various bug workarounds that should be rather harmless.
- * This used to be 0x000FFFFFL before 0.9.7.
- * This used to be 0x80000BFFU before 1.1.1.
- */
-# define SSL_OP_ALL (SSL_OP_CRYPTOPRO_TLSEXT_BUG|\
- SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS|\
- SSL_OP_LEGACY_SERVER_CONNECT|\
- SSL_OP_TLSEXT_PADDING|\
- SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
-
-/* OBSOLETE OPTIONS: retained for compatibility */
-
-/* Removed from OpenSSL 1.1.0. Was 0x00000001L */
-/* Related to removed SSLv2. */
-# define SSL_OP_MICROSOFT_SESS_ID_BUG 0x0
-/* Removed from OpenSSL 1.1.0. Was 0x00000002L */
-/* Related to removed SSLv2. */
-# define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x0
-/* Removed from OpenSSL 0.9.8q and 1.0.0c. Was 0x00000008L */
-/* Dead forever, see CVE-2010-4180 */
-# define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x0
-/* Removed from OpenSSL 1.0.1h and 1.0.2. Was 0x00000010L */
-/* Refers to ancient SSLREF and SSLv2. */
-# define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x0
-/* Removed from OpenSSL 1.1.0. Was 0x00000020 */
-# define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x0
-/* Removed from OpenSSL 0.9.7h and 0.9.8b. Was 0x00000040L */
-# define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x0
-/* Removed from OpenSSL 1.1.0. Was 0x00000080 */
-/* Ancient SSLeay version. */
-# define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x0
-/* Removed from OpenSSL 1.1.0. Was 0x00000100L */
-# define SSL_OP_TLS_D5_BUG 0x0
-/* Removed from OpenSSL 1.1.0. Was 0x00000200L */
-# define SSL_OP_TLS_BLOCK_PADDING_BUG 0x0
-/* Removed from OpenSSL 1.1.0. Was 0x00080000L */
-# define SSL_OP_SINGLE_ECDH_USE 0x0
-/* Removed from OpenSSL 1.1.0. Was 0x00100000L */
-# define SSL_OP_SINGLE_DH_USE 0x0
-/* Removed from OpenSSL 1.0.1k and 1.0.2. Was 0x00200000L */
-# define SSL_OP_EPHEMERAL_RSA 0x0
-/* Removed from OpenSSL 1.1.0. Was 0x01000000L */
-# define SSL_OP_NO_SSLv2 0x0
-/* Removed from OpenSSL 1.0.1. Was 0x08000000L */
-# define SSL_OP_PKCS1_CHECK_1 0x0
-/* Removed from OpenSSL 1.0.1. Was 0x10000000L */
-# define SSL_OP_PKCS1_CHECK_2 0x0
-/* Removed from OpenSSL 1.1.0. Was 0x20000000L */
-# define SSL_OP_NETSCAPE_CA_DN_BUG 0x0
-/* Removed from OpenSSL 1.1.0. Was 0x40000000L */
-# define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x0
-
-/*
- * Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
- * when just a single record has been written):
- */
-# define SSL_MODE_ENABLE_PARTIAL_WRITE 0x00000001U
-/*
- * Make it possible to retry SSL_write() with changed buffer location (buffer
- * contents must stay the same!); this is not the default to avoid the
- * misconception that non-blocking SSL_write() behaves like non-blocking
- * write():
- */
-# define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002U
-/*
- * Never bother the application with retries if the transport is blocking:
- */
-# define SSL_MODE_AUTO_RETRY 0x00000004U
-/* Don't attempt to automatically build certificate chain */
-# define SSL_MODE_NO_AUTO_CHAIN 0x00000008U
-/*
- * Save RAM by releasing read and write buffers when they're empty. (SSL3 and
- * TLS only.) Released buffers are freed.
- */
-# define SSL_MODE_RELEASE_BUFFERS 0x00000010U
-/*
- * Send the current time in the Random fields of the ClientHello and
- * ServerHello records for compatibility with hypothetical implementations
- * that require it.
- */
-# define SSL_MODE_SEND_CLIENTHELLO_TIME 0x00000020U
-# define SSL_MODE_SEND_SERVERHELLO_TIME 0x00000040U
-/*
- * Send TLS_FALLBACK_SCSV in the ClientHello. To be set only by applications
- * that reconnect with a downgraded protocol version; see
- * draft-ietf-tls-downgrade-scsv-00 for details. DO NOT ENABLE THIS if your
- * application attempts a normal handshake. Only use this in explicit
- * fallback retries, following the guidance in
- * draft-ietf-tls-downgrade-scsv-00.
- */
-# define SSL_MODE_SEND_FALLBACK_SCSV 0x00000080U
-/*
- * Support Asynchronous operation
- */
-# define SSL_MODE_ASYNC 0x00000100U
-
-/*
- * When using DTLS/SCTP, include the terminating zero in the label
- * used for computing the endpoint-pair shared secret. Required for
- * interoperability with implementations having this bug like these
- * older version of OpenSSL:
- * - OpenSSL 1.0.0 series
- * - OpenSSL 1.0.1 series
- * - OpenSSL 1.0.2 series
- * - OpenSSL 1.1.0 series
- * - OpenSSL 1.1.1 and 1.1.1a
- */
-# define SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG 0x00000400U
-
-/* Cert related flags */
-/*
- * Many implementations ignore some aspects of the TLS standards such as
- * enforcing certificate chain algorithms. When this is set we enforce them.
- */
-# define SSL_CERT_FLAG_TLS_STRICT 0x00000001U
-
-/* Suite B modes, takes same values as certificate verify flags */
-# define SSL_CERT_FLAG_SUITEB_128_LOS_ONLY 0x10000
-/* Suite B 192 bit only mode */
-# define SSL_CERT_FLAG_SUITEB_192_LOS 0x20000
-/* Suite B 128 bit mode allowing 192 bit algorithms */
-# define SSL_CERT_FLAG_SUITEB_128_LOS 0x30000
-
-/* Perform all sorts of protocol violations for testing purposes */
-# define SSL_CERT_FLAG_BROKEN_PROTOCOL 0x10000000
-
-/* Flags for building certificate chains */
-/* Treat any existing certificates as untrusted CAs */
-# define SSL_BUILD_CHAIN_FLAG_UNTRUSTED 0x1
-/* Don't include root CA in chain */
-# define SSL_BUILD_CHAIN_FLAG_NO_ROOT 0x2
-/* Just check certificates already there */
-# define SSL_BUILD_CHAIN_FLAG_CHECK 0x4
-/* Ignore verification errors */
-# define SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR 0x8
-/* Clear verification errors from queue */
-# define SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR 0x10
-
-/* Flags returned by SSL_check_chain */
-/* Certificate can be used with this session */
-# define CERT_PKEY_VALID 0x1
-/* Certificate can also be used for signing */
-# define CERT_PKEY_SIGN 0x2
-/* EE certificate signing algorithm OK */
-# define CERT_PKEY_EE_SIGNATURE 0x10
-/* CA signature algorithms OK */
-# define CERT_PKEY_CA_SIGNATURE 0x20
-/* EE certificate parameters OK */
-# define CERT_PKEY_EE_PARAM 0x40
-/* CA certificate parameters OK */
-# define CERT_PKEY_CA_PARAM 0x80
-/* Signing explicitly allowed as opposed to SHA1 fallback */
-# define CERT_PKEY_EXPLICIT_SIGN 0x100
-/* Client CA issuer names match (always set for server cert) */
-# define CERT_PKEY_ISSUER_NAME 0x200
-/* Cert type matches client types (always set for server cert) */
-# define CERT_PKEY_CERT_TYPE 0x400
-/* Cert chain suitable to Suite B */
-# define CERT_PKEY_SUITEB 0x800
-
-# define SSL_CONF_FLAG_CMDLINE 0x1
-# define SSL_CONF_FLAG_FILE 0x2
-# define SSL_CONF_FLAG_CLIENT 0x4
-# define SSL_CONF_FLAG_SERVER 0x8
-# define SSL_CONF_FLAG_SHOW_ERRORS 0x10
-# define SSL_CONF_FLAG_CERTIFICATE 0x20
-# define SSL_CONF_FLAG_REQUIRE_PRIVATE 0x40
-/* Configuration value types */
-# define SSL_CONF_TYPE_UNKNOWN 0x0
-# define SSL_CONF_TYPE_STRING 0x1
-# define SSL_CONF_TYPE_FILE 0x2
-# define SSL_CONF_TYPE_DIR 0x3
-# define SSL_CONF_TYPE_NONE 0x4
-
-/* Maximum length of the application-controlled segment of a a TLSv1.3 cookie */
-# define SSL_COOKIE_LENGTH 4096
-
-/*
- * Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, they
- * cannot be used to clear bits.
- */
-
-unsigned long SSL_CTX_get_options(const SSL_CTX *ctx);
-unsigned long SSL_get_options(const SSL *s);
-unsigned long SSL_CTX_clear_options(SSL_CTX *ctx, unsigned long op);
-unsigned long SSL_clear_options(SSL *s, unsigned long op);
-unsigned long SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op);
-unsigned long SSL_set_options(SSL *s, unsigned long op);
-
-# define SSL_CTX_set_mode(ctx,op) \
- SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
-# define SSL_CTX_clear_mode(ctx,op) \
- SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL)
-# define SSL_CTX_get_mode(ctx) \
- SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL)
-# define SSL_clear_mode(ssl,op) \
- SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL)
-# define SSL_set_mode(ssl,op) \
- SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL)
-# define SSL_get_mode(ssl) \
- SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL)
-# define SSL_set_mtu(ssl, mtu) \
- SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL)
-# define DTLS_set_link_mtu(ssl, mtu) \
- SSL_ctrl((ssl),DTLS_CTRL_SET_LINK_MTU,(mtu),NULL)
-# define DTLS_get_link_min_mtu(ssl) \
- SSL_ctrl((ssl),DTLS_CTRL_GET_LINK_MIN_MTU,0,NULL)
-
-# define SSL_get_secure_renegotiation_support(ssl) \
- SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL)
-
-# ifndef OPENSSL_NO_HEARTBEATS
-# define SSL_heartbeat(ssl) \
- SSL_ctrl((ssl),SSL_CTRL_DTLS_EXT_SEND_HEARTBEAT,0,NULL)
-# endif
-
-# define SSL_CTX_set_cert_flags(ctx,op) \
- SSL_CTX_ctrl((ctx),SSL_CTRL_CERT_FLAGS,(op),NULL)
-# define SSL_set_cert_flags(s,op) \
- SSL_ctrl((s),SSL_CTRL_CERT_FLAGS,(op),NULL)
-# define SSL_CTX_clear_cert_flags(ctx,op) \
- SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL)
-# define SSL_clear_cert_flags(s,op) \
- SSL_ctrl((s),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL)
-
-void SSL_CTX_set_msg_callback(SSL_CTX *ctx,
- void (*cb) (int write_p, int version,
- int content_type, const void *buf,
- size_t len, SSL *ssl, void *arg));
-void SSL_set_msg_callback(SSL *ssl,
- void (*cb) (int write_p, int version,
- int content_type, const void *buf,
- size_t len, SSL *ssl, void *arg));
-# define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
-# define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
-
-# define SSL_get_extms_support(s) \
- SSL_ctrl((s),SSL_CTRL_GET_EXTMS_SUPPORT,0,NULL)
-
-# ifndef OPENSSL_NO_SRP
-
-/* see tls_srp.c */
-__owur int SSL_SRP_CTX_init(SSL *s);
-__owur int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx);
-int SSL_SRP_CTX_free(SSL *ctx);
-int SSL_CTX_SRP_CTX_free(SSL_CTX *ctx);
-__owur int SSL_srp_server_param_with_username(SSL *s, int *ad);
-__owur int SRP_Calc_A_param(SSL *s);
-
-# endif
-
-/* 100k max cert list */
-# define SSL_MAX_CERT_LIST_DEFAULT 1024*100
-
-# define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (1024*20)
-
-/*
- * This callback type is used inside SSL_CTX, SSL, and in the functions that
- * set them. It is used to override the generation of SSL/TLS session IDs in
- * a server. Return value should be zero on an error, non-zero to proceed.
- * Also, callbacks should themselves check if the id they generate is unique
- * otherwise the SSL handshake will fail with an error - callbacks can do
- * this using the 'ssl' value they're passed by;
- * SSL_has_matching_session_id(ssl, id, *id_len) The length value passed in
- * is set at the maximum size the session ID can be. In SSLv3/TLSv1 it is 32
- * bytes. The callback can alter this length to be less if desired. It is
- * also an error for the callback to set the size to zero.
- */
-typedef int (*GEN_SESSION_CB) (SSL *ssl, unsigned char *id,
- unsigned int *id_len);
-
-# define SSL_SESS_CACHE_OFF 0x0000
-# define SSL_SESS_CACHE_CLIENT 0x0001
-# define SSL_SESS_CACHE_SERVER 0x0002
-# define SSL_SESS_CACHE_BOTH (SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER)
-# define SSL_SESS_CACHE_NO_AUTO_CLEAR 0x0080
-/* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */
-# define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP 0x0100
-# define SSL_SESS_CACHE_NO_INTERNAL_STORE 0x0200
-# define SSL_SESS_CACHE_NO_INTERNAL \
- (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE)
-
-LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx);
-# define SSL_CTX_sess_number(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL)
-# define SSL_CTX_sess_connect(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL)
-# define SSL_CTX_sess_connect_good(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL)
-# define SSL_CTX_sess_connect_renegotiate(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL)
-# define SSL_CTX_sess_accept(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL)
-# define SSL_CTX_sess_accept_renegotiate(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL)
-# define SSL_CTX_sess_accept_good(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL)
-# define SSL_CTX_sess_hits(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL)
-# define SSL_CTX_sess_cb_hits(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL)
-# define SSL_CTX_sess_misses(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL)
-# define SSL_CTX_sess_timeouts(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL)
-# define SSL_CTX_sess_cache_full(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL)
-
-void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
- int (*new_session_cb) (struct ssl_st *ssl,
- SSL_SESSION *sess));
-int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (struct ssl_st *ssl,
- SSL_SESSION *sess);
-void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
- void (*remove_session_cb) (struct ssl_ctx_st
- *ctx,
- SSL_SESSION *sess));
-void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (struct ssl_ctx_st *ctx,
- SSL_SESSION *sess);
-void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
- SSL_SESSION *(*get_session_cb) (struct ssl_st
- *ssl,
- const unsigned char
- *data, int len,
- int *copy));
-SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (struct ssl_st *ssl,
- const unsigned char *data,
- int len, int *copy);
-void SSL_CTX_set_info_callback(SSL_CTX *ctx,
- void (*cb) (const SSL *ssl, int type, int val));
-void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type,
- int val);
-void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
- int (*client_cert_cb) (SSL *ssl, X509 **x509,
- EVP_PKEY **pkey));
-int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509,
- EVP_PKEY **pkey);
-# ifndef OPENSSL_NO_ENGINE
-__owur int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e);
-# endif
-void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
- int (*app_gen_cookie_cb) (SSL *ssl,
- unsigned char
- *cookie,
- unsigned int
- *cookie_len));
-void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
- int (*app_verify_cookie_cb) (SSL *ssl,
- const unsigned
- char *cookie,
- unsigned int
- cookie_len));
-
-void SSL_CTX_set_stateless_cookie_generate_cb(
- SSL_CTX *ctx,
- int (*gen_stateless_cookie_cb) (SSL *ssl,
- unsigned char *cookie,
- size_t *cookie_len));
-void SSL_CTX_set_stateless_cookie_verify_cb(
- SSL_CTX *ctx,
- int (*verify_stateless_cookie_cb) (SSL *ssl,
- const unsigned char *cookie,
- size_t cookie_len));
-# ifndef OPENSSL_NO_NEXTPROTONEG
-
-typedef int (*SSL_CTX_npn_advertised_cb_func)(SSL *ssl,
- const unsigned char **out,
- unsigned int *outlen,
- void *arg);
-void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *s,
- SSL_CTX_npn_advertised_cb_func cb,
- void *arg);
-# define SSL_CTX_set_npn_advertised_cb SSL_CTX_set_next_protos_advertised_cb
-
-typedef int (*SSL_CTX_npn_select_cb_func)(SSL *s,
- unsigned char **out,
- unsigned char *outlen,
- const unsigned char *in,
- unsigned int inlen,
- void *arg);
-void SSL_CTX_set_next_proto_select_cb(SSL_CTX *s,
- SSL_CTX_npn_select_cb_func cb,
- void *arg);
-# define SSL_CTX_set_npn_select_cb SSL_CTX_set_next_proto_select_cb
-
-void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
- unsigned *len);
-# define SSL_get0_npn_negotiated SSL_get0_next_proto_negotiated
-# endif
-
-__owur int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
- const unsigned char *in, unsigned int inlen,
- const unsigned char *client,
- unsigned int client_len);
-
-# define OPENSSL_NPN_UNSUPPORTED 0
-# define OPENSSL_NPN_NEGOTIATED 1
-# define OPENSSL_NPN_NO_OVERLAP 2
-
-__owur int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos,
- unsigned int protos_len);
-__owur int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos,
- unsigned int protos_len);
-typedef int (*SSL_CTX_alpn_select_cb_func)(SSL *ssl,
- const unsigned char **out,
- unsigned char *outlen,
- const unsigned char *in,
- unsigned int inlen,
- void *arg);
-void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
- SSL_CTX_alpn_select_cb_func cb,
- void *arg);
-void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
- unsigned int *len);
-
-# ifndef OPENSSL_NO_PSK
-/*
- * the maximum length of the buffer given to callbacks containing the
- * resulting identity/psk
- */
-# define PSK_MAX_IDENTITY_LEN 128
-# define PSK_MAX_PSK_LEN 256
-typedef unsigned int (*SSL_psk_client_cb_func)(SSL *ssl,
- const char *hint,
- char *identity,
- unsigned int max_identity_len,
- unsigned char *psk,
- unsigned int max_psk_len);
-void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, SSL_psk_client_cb_func cb);
-void SSL_set_psk_client_callback(SSL *ssl, SSL_psk_client_cb_func cb);
-
-typedef unsigned int (*SSL_psk_server_cb_func)(SSL *ssl,
- const char *identity,
- unsigned char *psk,
- unsigned int max_psk_len);
-void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, SSL_psk_server_cb_func cb);
-void SSL_set_psk_server_callback(SSL *ssl, SSL_psk_server_cb_func cb);
-
-__owur int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint);
-__owur int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint);
-const char *SSL_get_psk_identity_hint(const SSL *s);
-const char *SSL_get_psk_identity(const SSL *s);
-# endif
-
-typedef int (*SSL_psk_find_session_cb_func)(SSL *ssl,
- const unsigned char *identity,
- size_t identity_len,
- SSL_SESSION **sess);
-typedef int (*SSL_psk_use_session_cb_func)(SSL *ssl, const EVP_MD *md,
- const unsigned char **id,
- size_t *idlen,
- SSL_SESSION **sess);
-
-void SSL_set_psk_find_session_callback(SSL *s, SSL_psk_find_session_cb_func cb);
-void SSL_CTX_set_psk_find_session_callback(SSL_CTX *ctx,
- SSL_psk_find_session_cb_func cb);
-void SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb);
-void SSL_CTX_set_psk_use_session_callback(SSL_CTX *ctx,
- SSL_psk_use_session_cb_func cb);
-
-/* Register callbacks to handle custom TLS Extensions for client or server. */
-
-__owur int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx,
- unsigned int ext_type);
-
-__owur int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx,
- unsigned int ext_type,
- custom_ext_add_cb add_cb,
- custom_ext_free_cb free_cb,
- void *add_arg,
- custom_ext_parse_cb parse_cb,
- void *parse_arg);
-
-__owur int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx,
- unsigned int ext_type,
- custom_ext_add_cb add_cb,
- custom_ext_free_cb free_cb,
- void *add_arg,
- custom_ext_parse_cb parse_cb,
- void *parse_arg);
-
-__owur int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
- unsigned int context,
- SSL_custom_ext_add_cb_ex add_cb,
- SSL_custom_ext_free_cb_ex free_cb,
- void *add_arg,
- SSL_custom_ext_parse_cb_ex parse_cb,
- void *parse_arg);
-
-__owur int SSL_extension_supported(unsigned int ext_type);
-
-# define SSL_NOTHING 1
-# define SSL_WRITING 2
-# define SSL_READING 3
-# define SSL_X509_LOOKUP 4
-# define SSL_ASYNC_PAUSED 5
-# define SSL_ASYNC_NO_JOBS 6
-# define SSL_CLIENT_HELLO_CB 7
-
-/* These will only be used when doing non-blocking IO */
-# define SSL_want_nothing(s) (SSL_want(s) == SSL_NOTHING)
-# define SSL_want_read(s) (SSL_want(s) == SSL_READING)
-# define SSL_want_write(s) (SSL_want(s) == SSL_WRITING)
-# define SSL_want_x509_lookup(s) (SSL_want(s) == SSL_X509_LOOKUP)
-# define SSL_want_async(s) (SSL_want(s) == SSL_ASYNC_PAUSED)
-# define SSL_want_async_job(s) (SSL_want(s) == SSL_ASYNC_NO_JOBS)
-# define SSL_want_client_hello_cb(s) (SSL_want(s) == SSL_CLIENT_HELLO_CB)
-
-# define SSL_MAC_FLAG_READ_MAC_STREAM 1
-# define SSL_MAC_FLAG_WRITE_MAC_STREAM 2
-
-/*
- * A callback for logging out TLS key material. This callback should log out
- * |line| followed by a newline.
- */
-typedef void (*SSL_CTX_keylog_cb_func)(const SSL *ssl, const char *line);
-
-/*
- * SSL_CTX_set_keylog_callback configures a callback to log key material. This
- * is intended for debugging use with tools like Wireshark. The cb function
- * should log line followed by a newline.
- */
-void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb);
-
-/*
- * SSL_CTX_get_keylog_callback returns the callback configured by
- * SSL_CTX_set_keylog_callback.
- */
-SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx);
-
-int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data);
-uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx);
-int SSL_set_max_early_data(SSL *s, uint32_t max_early_data);
-uint32_t SSL_get_max_early_data(const SSL *s);
-int SSL_CTX_set_recv_max_early_data(SSL_CTX *ctx, uint32_t recv_max_early_data);
-uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx);
-int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data);
-uint32_t SSL_get_recv_max_early_data(const SSL *s);
-
-#ifdef __cplusplus
-}
-#endif
-
-# include <openssl/ssl2.h>
-# include <openssl/ssl3.h>
-# include <openssl/tls1.h> /* This is mostly sslv3 with a few tweaks */
-# include <openssl/dtls1.h> /* Datagram TLS */
-# include <openssl/srtp.h> /* Support for the use_srtp extension */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * These need to be after the above set of includes due to a compiler bug
- * in VisualStudio 2015
- */
-DEFINE_STACK_OF_CONST(SSL_CIPHER)
-DEFINE_STACK_OF(SSL_COMP)
-
-/* compatibility */
-# define SSL_set_app_data(s,arg) (SSL_set_ex_data(s,0,(char *)(arg)))
-# define SSL_get_app_data(s) (SSL_get_ex_data(s,0))
-# define SSL_SESSION_set_app_data(s,a) (SSL_SESSION_set_ex_data(s,0, \
- (char *)(a)))
-# define SSL_SESSION_get_app_data(s) (SSL_SESSION_get_ex_data(s,0))
-# define SSL_CTX_get_app_data(ctx) (SSL_CTX_get_ex_data(ctx,0))
-# define SSL_CTX_set_app_data(ctx,arg) (SSL_CTX_set_ex_data(ctx,0, \
- (char *)(arg)))
-DEPRECATEDIN_1_1_0(void SSL_set_debug(SSL *s, int debug))
-
-/* TLSv1.3 KeyUpdate message types */
-/* -1 used so that this is an invalid value for the on-the-wire protocol */
-#define SSL_KEY_UPDATE_NONE -1
-/* Values as defined for the on-the-wire protocol */
-#define SSL_KEY_UPDATE_NOT_REQUESTED 0
-#define SSL_KEY_UPDATE_REQUESTED 1
-
-/*
- * The valid handshake states (one for each type message sent and one for each
- * type of message received). There are also two "special" states:
- * TLS = TLS or DTLS state
- * DTLS = DTLS specific state
- * CR/SR = Client Read/Server Read
- * CW/SW = Client Write/Server Write
- *
- * The "special" states are:
- * TLS_ST_BEFORE = No handshake has been initiated yet
- * TLS_ST_OK = A handshake has been successfully completed
- */
-typedef enum {
- TLS_ST_BEFORE,
- TLS_ST_OK,
- DTLS_ST_CR_HELLO_VERIFY_REQUEST,
- TLS_ST_CR_SRVR_HELLO,
- TLS_ST_CR_CERT,
- TLS_ST_CR_CERT_STATUS,
- TLS_ST_CR_KEY_EXCH,
- TLS_ST_CR_CERT_REQ,
- TLS_ST_CR_SRVR_DONE,
- TLS_ST_CR_SESSION_TICKET,
- TLS_ST_CR_CHANGE,
- TLS_ST_CR_FINISHED,
- TLS_ST_CW_CLNT_HELLO,
- TLS_ST_CW_CERT,
- TLS_ST_CW_KEY_EXCH,
- TLS_ST_CW_CERT_VRFY,
- TLS_ST_CW_CHANGE,
- TLS_ST_CW_NEXT_PROTO,
- TLS_ST_CW_FINISHED,
- TLS_ST_SW_HELLO_REQ,
- TLS_ST_SR_CLNT_HELLO,
- DTLS_ST_SW_HELLO_VERIFY_REQUEST,
- TLS_ST_SW_SRVR_HELLO,
- TLS_ST_SW_CERT,
- TLS_ST_SW_KEY_EXCH,
- TLS_ST_SW_CERT_REQ,
- TLS_ST_SW_SRVR_DONE,
- TLS_ST_SR_CERT,
- TLS_ST_SR_KEY_EXCH,
- TLS_ST_SR_CERT_VRFY,
- TLS_ST_SR_NEXT_PROTO,
- TLS_ST_SR_CHANGE,
- TLS_ST_SR_FINISHED,
- TLS_ST_SW_SESSION_TICKET,
- TLS_ST_SW_CERT_STATUS,
- TLS_ST_SW_CHANGE,
- TLS_ST_SW_FINISHED,
- TLS_ST_SW_ENCRYPTED_EXTENSIONS,
- TLS_ST_CR_ENCRYPTED_EXTENSIONS,
- TLS_ST_CR_CERT_VRFY,
- TLS_ST_SW_CERT_VRFY,
- TLS_ST_CR_HELLO_REQ,
- TLS_ST_SW_KEY_UPDATE,
- TLS_ST_CW_KEY_UPDATE,
- TLS_ST_SR_KEY_UPDATE,
- TLS_ST_CR_KEY_UPDATE,
- TLS_ST_EARLY_DATA,
- TLS_ST_PENDING_EARLY_DATA_END,
- TLS_ST_CW_END_OF_EARLY_DATA,
- TLS_ST_SR_END_OF_EARLY_DATA
-} OSSL_HANDSHAKE_STATE;
-
-/*
- * Most of the following state values are no longer used and are defined to be
- * the closest equivalent value in the current state machine code. Not all
- * defines have an equivalent and are set to a dummy value (-1). SSL_ST_CONNECT
- * and SSL_ST_ACCEPT are still in use in the definition of SSL_CB_ACCEPT_LOOP,
- * SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP and SSL_CB_CONNECT_EXIT.
- */
-
-# define SSL_ST_CONNECT 0x1000
-# define SSL_ST_ACCEPT 0x2000
-
-# define SSL_ST_MASK 0x0FFF
-
-# define SSL_CB_LOOP 0x01
-# define SSL_CB_EXIT 0x02
-# define SSL_CB_READ 0x04
-# define SSL_CB_WRITE 0x08
-# define SSL_CB_ALERT 0x4000/* used in callback */
-# define SSL_CB_READ_ALERT (SSL_CB_ALERT|SSL_CB_READ)
-# define SSL_CB_WRITE_ALERT (SSL_CB_ALERT|SSL_CB_WRITE)
-# define SSL_CB_ACCEPT_LOOP (SSL_ST_ACCEPT|SSL_CB_LOOP)
-# define SSL_CB_ACCEPT_EXIT (SSL_ST_ACCEPT|SSL_CB_EXIT)
-# define SSL_CB_CONNECT_LOOP (SSL_ST_CONNECT|SSL_CB_LOOP)
-# define SSL_CB_CONNECT_EXIT (SSL_ST_CONNECT|SSL_CB_EXIT)
-# define SSL_CB_HANDSHAKE_START 0x10
-# define SSL_CB_HANDSHAKE_DONE 0x20
-
-/* Is the SSL_connection established? */
-# define SSL_in_connect_init(a) (SSL_in_init(a) && !SSL_is_server(a))
-# define SSL_in_accept_init(a) (SSL_in_init(a) && SSL_is_server(a))
-int SSL_in_init(const SSL *s);
-int SSL_in_before(const SSL *s);
-int SSL_is_init_finished(const SSL *s);
-
-/*
- * The following 3 states are kept in ssl->rlayer.rstate when reads fail, you
- * should not need these
- */
-# define SSL_ST_READ_HEADER 0xF0
-# define SSL_ST_READ_BODY 0xF1
-# define SSL_ST_READ_DONE 0xF2
-
-/*-
- * Obtain latest Finished message
- * -- that we sent (SSL_get_finished)
- * -- that we expected from peer (SSL_get_peer_finished).
- * Returns length (0 == no Finished so far), copies up to 'count' bytes.
- */
-size_t SSL_get_finished(const SSL *s, void *buf, size_t count);
-size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
-
-/*
- * use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 3 options are
- * 'ored' with SSL_VERIFY_PEER if they are desired
- */
-# define SSL_VERIFY_NONE 0x00
-# define SSL_VERIFY_PEER 0x01
-# define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
-# define SSL_VERIFY_CLIENT_ONCE 0x04
-# define SSL_VERIFY_POST_HANDSHAKE 0x08
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-# define OpenSSL_add_ssl_algorithms() SSL_library_init()
-# define SSLeay_add_ssl_algorithms() SSL_library_init()
-# endif
-
-/* More backward compatibility */
-# define SSL_get_cipher(s) \
- SSL_CIPHER_get_name(SSL_get_current_cipher(s))
-# define SSL_get_cipher_bits(s,np) \
- SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np)
-# define SSL_get_cipher_version(s) \
- SSL_CIPHER_get_version(SSL_get_current_cipher(s))
-# define SSL_get_cipher_name(s) \
- SSL_CIPHER_get_name(SSL_get_current_cipher(s))
-# define SSL_get_time(a) SSL_SESSION_get_time(a)
-# define SSL_set_time(a,b) SSL_SESSION_set_time((a),(b))
-# define SSL_get_timeout(a) SSL_SESSION_get_timeout(a)
-# define SSL_set_timeout(a,b) SSL_SESSION_set_timeout((a),(b))
-
-# define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id)
-# define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id)
-
-DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
-# define SSL_AD_REASON_OFFSET 1000/* offset to get SSL_R_... value
- * from SSL_AD_... */
-/* These alert types are for SSLv3 and TLSv1 */
-# define SSL_AD_CLOSE_NOTIFY SSL3_AD_CLOSE_NOTIFY
-/* fatal */
-# define SSL_AD_UNEXPECTED_MESSAGE SSL3_AD_UNEXPECTED_MESSAGE
-/* fatal */
-# define SSL_AD_BAD_RECORD_MAC SSL3_AD_BAD_RECORD_MAC
-# define SSL_AD_DECRYPTION_FAILED TLS1_AD_DECRYPTION_FAILED
-# define SSL_AD_RECORD_OVERFLOW TLS1_AD_RECORD_OVERFLOW
-/* fatal */
-# define SSL_AD_DECOMPRESSION_FAILURE SSL3_AD_DECOMPRESSION_FAILURE
-/* fatal */
-# define SSL_AD_HANDSHAKE_FAILURE SSL3_AD_HANDSHAKE_FAILURE
-/* Not for TLS */
-# define SSL_AD_NO_CERTIFICATE SSL3_AD_NO_CERTIFICATE
-# define SSL_AD_BAD_CERTIFICATE SSL3_AD_BAD_CERTIFICATE
-# define SSL_AD_UNSUPPORTED_CERTIFICATE SSL3_AD_UNSUPPORTED_CERTIFICATE
-# define SSL_AD_CERTIFICATE_REVOKED SSL3_AD_CERTIFICATE_REVOKED
-# define SSL_AD_CERTIFICATE_EXPIRED SSL3_AD_CERTIFICATE_EXPIRED
-# define SSL_AD_CERTIFICATE_UNKNOWN SSL3_AD_CERTIFICATE_UNKNOWN
-/* fatal */
-# define SSL_AD_ILLEGAL_PARAMETER SSL3_AD_ILLEGAL_PARAMETER
-/* fatal */
-# define SSL_AD_UNKNOWN_CA TLS1_AD_UNKNOWN_CA
-/* fatal */
-# define SSL_AD_ACCESS_DENIED TLS1_AD_ACCESS_DENIED
-/* fatal */
-# define SSL_AD_DECODE_ERROR TLS1_AD_DECODE_ERROR
-# define SSL_AD_DECRYPT_ERROR TLS1_AD_DECRYPT_ERROR
-/* fatal */
-# define SSL_AD_EXPORT_RESTRICTION TLS1_AD_EXPORT_RESTRICTION
-/* fatal */
-# define SSL_AD_PROTOCOL_VERSION TLS1_AD_PROTOCOL_VERSION
-/* fatal */
-# define SSL_AD_INSUFFICIENT_SECURITY TLS1_AD_INSUFFICIENT_SECURITY
-/* fatal */
-# define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR
-# define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED
-# define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION
-# define SSL_AD_MISSING_EXTENSION TLS13_AD_MISSING_EXTENSION
-# define SSL_AD_CERTIFICATE_REQUIRED TLS13_AD_CERTIFICATE_REQUIRED
-# define SSL_AD_UNSUPPORTED_EXTENSION TLS1_AD_UNSUPPORTED_EXTENSION
-# define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
-# define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME
-# define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
-# define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
-/* fatal */
-# define SSL_AD_UNKNOWN_PSK_IDENTITY TLS1_AD_UNKNOWN_PSK_IDENTITY
-/* fatal */
-# define SSL_AD_INAPPROPRIATE_FALLBACK TLS1_AD_INAPPROPRIATE_FALLBACK
-# define SSL_AD_NO_APPLICATION_PROTOCOL TLS1_AD_NO_APPLICATION_PROTOCOL
-# define SSL_ERROR_NONE 0
-# define SSL_ERROR_SSL 1
-# define SSL_ERROR_WANT_READ 2
-# define SSL_ERROR_WANT_WRITE 3
-# define SSL_ERROR_WANT_X509_LOOKUP 4
-# define SSL_ERROR_SYSCALL 5/* look at error stack/return
- * value/errno */
-# define SSL_ERROR_ZERO_RETURN 6
-# define SSL_ERROR_WANT_CONNECT 7
-# define SSL_ERROR_WANT_ACCEPT 8
-# define SSL_ERROR_WANT_ASYNC 9
-# define SSL_ERROR_WANT_ASYNC_JOB 10
-# define SSL_ERROR_WANT_CLIENT_HELLO_CB 11
-# define SSL_CTRL_SET_TMP_DH 3
-# define SSL_CTRL_SET_TMP_ECDH 4
-# define SSL_CTRL_SET_TMP_DH_CB 6
-# define SSL_CTRL_GET_CLIENT_CERT_REQUEST 9
-# define SSL_CTRL_GET_NUM_RENEGOTIATIONS 10
-# define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS 11
-# define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS 12
-# define SSL_CTRL_GET_FLAGS 13
-# define SSL_CTRL_EXTRA_CHAIN_CERT 14
-# define SSL_CTRL_SET_MSG_CALLBACK 15
-# define SSL_CTRL_SET_MSG_CALLBACK_ARG 16
-/* only applies to datagram connections */
-# define SSL_CTRL_SET_MTU 17
-/* Stats */
-# define SSL_CTRL_SESS_NUMBER 20
-# define SSL_CTRL_SESS_CONNECT 21
-# define SSL_CTRL_SESS_CONNECT_GOOD 22
-# define SSL_CTRL_SESS_CONNECT_RENEGOTIATE 23
-# define SSL_CTRL_SESS_ACCEPT 24
-# define SSL_CTRL_SESS_ACCEPT_GOOD 25
-# define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE 26
-# define SSL_CTRL_SESS_HIT 27
-# define SSL_CTRL_SESS_CB_HIT 28
-# define SSL_CTRL_SESS_MISSES 29
-# define SSL_CTRL_SESS_TIMEOUTS 30
-# define SSL_CTRL_SESS_CACHE_FULL 31
-# define SSL_CTRL_MODE 33
-# define SSL_CTRL_GET_READ_AHEAD 40
-# define SSL_CTRL_SET_READ_AHEAD 41
-# define SSL_CTRL_SET_SESS_CACHE_SIZE 42
-# define SSL_CTRL_GET_SESS_CACHE_SIZE 43
-# define SSL_CTRL_SET_SESS_CACHE_MODE 44
-# define SSL_CTRL_GET_SESS_CACHE_MODE 45
-# define SSL_CTRL_GET_MAX_CERT_LIST 50
-# define SSL_CTRL_SET_MAX_CERT_LIST 51
-# define SSL_CTRL_SET_MAX_SEND_FRAGMENT 52
-/* see tls1.h for macros based on these */
-# define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53
-# define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54
-# define SSL_CTRL_SET_TLSEXT_HOSTNAME 55
-# define SSL_CTRL_SET_TLSEXT_DEBUG_CB 56
-# define SSL_CTRL_SET_TLSEXT_DEBUG_ARG 57
-# define SSL_CTRL_GET_TLSEXT_TICKET_KEYS 58
-# define SSL_CTRL_SET_TLSEXT_TICKET_KEYS 59
-/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT 60 */
-/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB 61 */
-/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG 62 */
-# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB 63
-# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 64
-# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 65
-# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 66
-# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS 67
-# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS 68
-# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 69
-# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 70
-# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 71
-# define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72
-# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB 75
-# define SSL_CTRL_SET_SRP_VERIFY_PARAM_CB 76
-# define SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB 77
-# define SSL_CTRL_SET_SRP_ARG 78
-# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME 79
-# define SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH 80
-# define SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD 81
-# ifndef OPENSSL_NO_HEARTBEATS
-# define SSL_CTRL_DTLS_EXT_SEND_HEARTBEAT 85
-# define SSL_CTRL_GET_DTLS_EXT_HEARTBEAT_PENDING 86
-# define SSL_CTRL_SET_DTLS_EXT_HEARTBEAT_NO_REQUESTS 87
-# endif
-# define DTLS_CTRL_GET_TIMEOUT 73
-# define DTLS_CTRL_HANDLE_TIMEOUT 74
-# define SSL_CTRL_GET_RI_SUPPORT 76
-# define SSL_CTRL_CLEAR_MODE 78
-# define SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB 79
-# define SSL_CTRL_GET_EXTRA_CHAIN_CERTS 82
-# define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS 83
-# define SSL_CTRL_CHAIN 88
-# define SSL_CTRL_CHAIN_CERT 89
-# define SSL_CTRL_GET_GROUPS 90
-# define SSL_CTRL_SET_GROUPS 91
-# define SSL_CTRL_SET_GROUPS_LIST 92
-# define SSL_CTRL_GET_SHARED_GROUP 93
-# define SSL_CTRL_SET_SIGALGS 97
-# define SSL_CTRL_SET_SIGALGS_LIST 98
-# define SSL_CTRL_CERT_FLAGS 99
-# define SSL_CTRL_CLEAR_CERT_FLAGS 100
-# define SSL_CTRL_SET_CLIENT_SIGALGS 101
-# define SSL_CTRL_SET_CLIENT_SIGALGS_LIST 102
-# define SSL_CTRL_GET_CLIENT_CERT_TYPES 103
-# define SSL_CTRL_SET_CLIENT_CERT_TYPES 104
-# define SSL_CTRL_BUILD_CERT_CHAIN 105
-# define SSL_CTRL_SET_VERIFY_CERT_STORE 106
-# define SSL_CTRL_SET_CHAIN_CERT_STORE 107
-# define SSL_CTRL_GET_PEER_SIGNATURE_NID 108
-# define SSL_CTRL_GET_PEER_TMP_KEY 109
-# define SSL_CTRL_GET_RAW_CIPHERLIST 110
-# define SSL_CTRL_GET_EC_POINT_FORMATS 111
-# define SSL_CTRL_GET_CHAIN_CERTS 115
-# define SSL_CTRL_SELECT_CURRENT_CERT 116
-# define SSL_CTRL_SET_CURRENT_CERT 117
-# define SSL_CTRL_SET_DH_AUTO 118
-# define DTLS_CTRL_SET_LINK_MTU 120
-# define DTLS_CTRL_GET_LINK_MIN_MTU 121
-# define SSL_CTRL_GET_EXTMS_SUPPORT 122
-# define SSL_CTRL_SET_MIN_PROTO_VERSION 123
-# define SSL_CTRL_SET_MAX_PROTO_VERSION 124
-# define SSL_CTRL_SET_SPLIT_SEND_FRAGMENT 125
-# define SSL_CTRL_SET_MAX_PIPELINES 126
-# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE 127
-# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB 128
-# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG 129
-# define SSL_CTRL_GET_MIN_PROTO_VERSION 130
-# define SSL_CTRL_GET_MAX_PROTO_VERSION 131
-# define SSL_CTRL_GET_SIGNATURE_NID 132
-# define SSL_CTRL_GET_TMP_KEY 133
-# define SSL_CTRL_GET_VERIFY_CERT_STORE 137
-# define SSL_CTRL_GET_CHAIN_CERT_STORE 138
-# define SSL_CERT_SET_FIRST 1
-# define SSL_CERT_SET_NEXT 2
-# define SSL_CERT_SET_SERVER 3
-# define DTLSv1_get_timeout(ssl, arg) \
- SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)(arg))
-# define DTLSv1_handle_timeout(ssl) \
- SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL)
-# define SSL_num_renegotiations(ssl) \
- SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL)
-# define SSL_clear_num_renegotiations(ssl) \
- SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL)
-# define SSL_total_renegotiations(ssl) \
- SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL)
-# define SSL_CTX_set_tmp_dh(ctx,dh) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)(dh))
-# define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh))
-# define SSL_CTX_set_dh_auto(ctx, onoff) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_DH_AUTO,onoff,NULL)
-# define SSL_set_dh_auto(s, onoff) \
- SSL_ctrl(s,SSL_CTRL_SET_DH_AUTO,onoff,NULL)
-# define SSL_set_tmp_dh(ssl,dh) \
- SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)(dh))
-# define SSL_set_tmp_ecdh(ssl,ecdh) \
- SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh))
-# define SSL_CTX_add_extra_chain_cert(ctx,x509) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)(x509))
-# define SSL_CTX_get_extra_chain_certs(ctx,px509) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,0,px509)
-# define SSL_CTX_get_extra_chain_certs_only(ctx,px509) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,1,px509)
-# define SSL_CTX_clear_extra_chain_certs(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS,0,NULL)
-# define SSL_CTX_set0_chain(ctx,sk) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)(sk))
-# define SSL_CTX_set1_chain(ctx,sk) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,1,(char *)(sk))
-# define SSL_CTX_add0_chain_cert(ctx,x509) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)(x509))
-# define SSL_CTX_add1_chain_cert(ctx,x509) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)(x509))
-# define SSL_CTX_get0_chain_certs(ctx,px509) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509)
-# define SSL_CTX_clear_chain_certs(ctx) \
- SSL_CTX_set0_chain(ctx,NULL)
-# define SSL_CTX_build_cert_chain(ctx, flags) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
-# define SSL_CTX_select_current_cert(ctx,x509) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)(x509))
-# define SSL_CTX_set_current_cert(ctx, op) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL)
-# define SSL_CTX_set0_verify_cert_store(ctx,st) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st))
-# define SSL_CTX_set1_verify_cert_store(ctx,st) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st))
-# define SSL_CTX_get0_verify_cert_store(ctx,st) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_GET_VERIFY_CERT_STORE,0,(char *)(st))
-# define SSL_CTX_set0_chain_cert_store(ctx,st) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st))
-# define SSL_CTX_set1_chain_cert_store(ctx,st) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st))
-# define SSL_CTX_get0_chain_cert_store(ctx,st) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERT_STORE,0,(char *)(st))
-# define SSL_set0_chain(s,sk) \
- SSL_ctrl(s,SSL_CTRL_CHAIN,0,(char *)(sk))
-# define SSL_set1_chain(s,sk) \
- SSL_ctrl(s,SSL_CTRL_CHAIN,1,(char *)(sk))
-# define SSL_add0_chain_cert(s,x509) \
- SSL_ctrl(s,SSL_CTRL_CHAIN_CERT,0,(char *)(x509))
-# define SSL_add1_chain_cert(s,x509) \
- SSL_ctrl(s,SSL_CTRL_CHAIN_CERT,1,(char *)(x509))
-# define SSL_get0_chain_certs(s,px509) \
- SSL_ctrl(s,SSL_CTRL_GET_CHAIN_CERTS,0,px509)
-# define SSL_clear_chain_certs(s) \
- SSL_set0_chain(s,NULL)
-# define SSL_build_cert_chain(s, flags) \
- SSL_ctrl(s,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
-# define SSL_select_current_cert(s,x509) \
- SSL_ctrl(s,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)(x509))
-# define SSL_set_current_cert(s,op) \
- SSL_ctrl(s,SSL_CTRL_SET_CURRENT_CERT, op, NULL)
-# define SSL_set0_verify_cert_store(s,st) \
- SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st))
-# define SSL_set1_verify_cert_store(s,st) \
- SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st))
-#define SSL_get0_verify_cert_store(s,st) \
- SSL_ctrl(s,SSL_CTRL_GET_VERIFY_CERT_STORE,0,(char *)(st))
-# define SSL_set0_chain_cert_store(s,st) \
- SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st))
-# define SSL_set1_chain_cert_store(s,st) \
- SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st))
-#define SSL_get0_chain_cert_store(s,st) \
- SSL_ctrl(s,SSL_CTRL_GET_CHAIN_CERT_STORE,0,(char *)(st))
-# define SSL_get1_groups(s, glist) \
- SSL_ctrl(s,SSL_CTRL_GET_GROUPS,0,(int*)(glist))
-# define SSL_CTX_set1_groups(ctx, glist, glistlen) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS,glistlen,(int *)(glist))
-# define SSL_CTX_set1_groups_list(ctx, s) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(s))
-# define SSL_set1_groups(s, glist, glistlen) \
- SSL_ctrl(s,SSL_CTRL_SET_GROUPS,glistlen,(char *)(glist))
-# define SSL_set1_groups_list(s, str) \
- SSL_ctrl(s,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(str))
-# define SSL_get_shared_group(s, n) \
- SSL_ctrl(s,SSL_CTRL_GET_SHARED_GROUP,n,NULL)
-# define SSL_CTX_set1_sigalgs(ctx, slist, slistlen) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS,slistlen,(int *)(slist))
-# define SSL_CTX_set1_sigalgs_list(ctx, s) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)(s))
-# define SSL_set1_sigalgs(s, slist, slistlen) \
- SSL_ctrl(s,SSL_CTRL_SET_SIGALGS,slistlen,(int *)(slist))
-# define SSL_set1_sigalgs_list(s, str) \
- SSL_ctrl(s,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)(str))
-# define SSL_CTX_set1_client_sigalgs(ctx, slist, slistlen) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS,slistlen,(int *)(slist))
-# define SSL_CTX_set1_client_sigalgs_list(ctx, s) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)(s))
-# define SSL_set1_client_sigalgs(s, slist, slistlen) \
- SSL_ctrl(s,SSL_CTRL_SET_CLIENT_SIGALGS,slistlen,(int *)(slist))
-# define SSL_set1_client_sigalgs_list(s, str) \
- SSL_ctrl(s,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)(str))
-# define SSL_get0_certificate_types(s, clist) \
- SSL_ctrl(s, SSL_CTRL_GET_CLIENT_CERT_TYPES, 0, (char *)(clist))
-# define SSL_CTX_set1_client_certificate_types(ctx, clist, clistlen) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen, \
- (char *)(clist))
-# define SSL_set1_client_certificate_types(s, clist, clistlen) \
- SSL_ctrl(s,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen,(char *)(clist))
-# define SSL_get_signature_nid(s, pn) \
- SSL_ctrl(s,SSL_CTRL_GET_SIGNATURE_NID,0,pn)
-# define SSL_get_peer_signature_nid(s, pn) \
- SSL_ctrl(s,SSL_CTRL_GET_PEER_SIGNATURE_NID,0,pn)
-# define SSL_get_peer_tmp_key(s, pk) \
- SSL_ctrl(s,SSL_CTRL_GET_PEER_TMP_KEY,0,pk)
-# define SSL_get_tmp_key(s, pk) \
- SSL_ctrl(s,SSL_CTRL_GET_TMP_KEY,0,pk)
-# define SSL_get0_raw_cipherlist(s, plst) \
- SSL_ctrl(s,SSL_CTRL_GET_RAW_CIPHERLIST,0,plst)
-# define SSL_get0_ec_point_formats(s, plst) \
- SSL_ctrl(s,SSL_CTRL_GET_EC_POINT_FORMATS,0,plst)
-# define SSL_CTX_set_min_proto_version(ctx, version) \
- SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL)
-# define SSL_CTX_set_max_proto_version(ctx, version) \
- SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL)
-# define SSL_CTX_get_min_proto_version(ctx) \
- SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL)
-# define SSL_CTX_get_max_proto_version(ctx) \
- SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL)
-# define SSL_set_min_proto_version(s, version) \
- SSL_ctrl(s, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL)
-# define SSL_set_max_proto_version(s, version) \
- SSL_ctrl(s, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL)
-# define SSL_get_min_proto_version(s) \
- SSL_ctrl(s, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL)
-# define SSL_get_max_proto_version(s) \
- SSL_ctrl(s, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL)
-
-/* Backwards compatibility, original 1.1.0 names */
-# define SSL_CTRL_GET_SERVER_TMP_KEY \
- SSL_CTRL_GET_PEER_TMP_KEY
-# define SSL_get_server_tmp_key(s, pk) \
- SSL_get_peer_tmp_key(s, pk)
-
-/*
- * The following symbol names are old and obsolete. They are kept
- * for compatibility reasons only and should not be used anymore.
- */
-# define SSL_CTRL_GET_CURVES SSL_CTRL_GET_GROUPS
-# define SSL_CTRL_SET_CURVES SSL_CTRL_SET_GROUPS
-# define SSL_CTRL_SET_CURVES_LIST SSL_CTRL_SET_GROUPS_LIST
-# define SSL_CTRL_GET_SHARED_CURVE SSL_CTRL_GET_SHARED_GROUP
-
-# define SSL_get1_curves SSL_get1_groups
-# define SSL_CTX_set1_curves SSL_CTX_set1_groups
-# define SSL_CTX_set1_curves_list SSL_CTX_set1_groups_list
-# define SSL_set1_curves SSL_set1_groups
-# define SSL_set1_curves_list SSL_set1_groups_list
-# define SSL_get_shared_curve SSL_get_shared_group
-
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-/* Provide some compatibility macros for removed functionality. */
-# define SSL_CTX_need_tmp_RSA(ctx) 0
-# define SSL_CTX_set_tmp_rsa(ctx,rsa) 1
-# define SSL_need_tmp_RSA(ssl) 0
-# define SSL_set_tmp_rsa(ssl,rsa) 1
-# define SSL_CTX_set_ecdh_auto(dummy, onoff) ((onoff) != 0)
-# define SSL_set_ecdh_auto(dummy, onoff) ((onoff) != 0)
-/*
- * We "pretend" to call the callback to avoid warnings about unused static
- * functions.
- */
-# define SSL_CTX_set_tmp_rsa_callback(ctx, cb) while(0) (cb)(NULL, 0, 0)
-# define SSL_set_tmp_rsa_callback(ssl, cb) while(0) (cb)(NULL, 0, 0)
-# endif
-__owur const BIO_METHOD *BIO_f_ssl(void);
-__owur BIO *BIO_new_ssl(SSL_CTX *ctx, int client);
-__owur BIO *BIO_new_ssl_connect(SSL_CTX *ctx);
-__owur BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx);
-__owur int BIO_ssl_copy_session_id(BIO *to, BIO *from);
-void BIO_ssl_shutdown(BIO *ssl_bio);
-
-__owur int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str);
-__owur SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth);
-int SSL_CTX_up_ref(SSL_CTX *ctx);
-void SSL_CTX_free(SSL_CTX *);
-__owur long SSL_CTX_set_timeout(SSL_CTX *ctx, long t);
-__owur long SSL_CTX_get_timeout(const SSL_CTX *ctx);
-__owur X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
-void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *);
-void SSL_CTX_set1_cert_store(SSL_CTX *, X509_STORE *);
-__owur int SSL_want(const SSL *s);
-__owur int SSL_clear(SSL *s);
-
-void SSL_CTX_flush_sessions(SSL_CTX *ctx, long tm);
-
-__owur const SSL_CIPHER *SSL_get_current_cipher(const SSL *s);
-__owur const SSL_CIPHER *SSL_get_pending_cipher(const SSL *s);
-__owur int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits);
-__owur const char *SSL_CIPHER_get_version(const SSL_CIPHER *c);
-__owur const char *SSL_CIPHER_get_name(const SSL_CIPHER *c);
-__owur const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c);
-__owur const char *OPENSSL_cipher_name(const char *rfc_name);
-__owur uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *c);
-__owur uint16_t SSL_CIPHER_get_protocol_id(const SSL_CIPHER *c);
-__owur int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c);
-__owur int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c);
-__owur const EVP_MD *SSL_CIPHER_get_handshake_digest(const SSL_CIPHER *c);
-__owur int SSL_CIPHER_is_aead(const SSL_CIPHER *c);
-
-__owur int SSL_get_fd(const SSL *s);
-__owur int SSL_get_rfd(const SSL *s);
-__owur int SSL_get_wfd(const SSL *s);
-__owur const char *SSL_get_cipher_list(const SSL *s, int n);
-__owur char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size);
-__owur int SSL_get_read_ahead(const SSL *s);
-__owur int SSL_pending(const SSL *s);
-__owur int SSL_has_pending(const SSL *s);
-# ifndef OPENSSL_NO_SOCK
-__owur int SSL_set_fd(SSL *s, int fd);
-__owur int SSL_set_rfd(SSL *s, int fd);
-__owur int SSL_set_wfd(SSL *s, int fd);
-# endif
-void SSL_set0_rbio(SSL *s, BIO *rbio);
-void SSL_set0_wbio(SSL *s, BIO *wbio);
-void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio);
-__owur BIO *SSL_get_rbio(const SSL *s);
-__owur BIO *SSL_get_wbio(const SSL *s);
-__owur int SSL_set_cipher_list(SSL *s, const char *str);
-__owur int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str);
-__owur int SSL_set_ciphersuites(SSL *s, const char *str);
-void SSL_set_read_ahead(SSL *s, int yes);
-__owur int SSL_get_verify_mode(const SSL *s);
-__owur int SSL_get_verify_depth(const SSL *s);
-__owur SSL_verify_cb SSL_get_verify_callback(const SSL *s);
-void SSL_set_verify(SSL *s, int mode, SSL_verify_cb callback);
-void SSL_set_verify_depth(SSL *s, int depth);
-void SSL_set_cert_cb(SSL *s, int (*cb) (SSL *ssl, void *arg), void *arg);
-# ifndef OPENSSL_NO_RSA
-__owur int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
-__owur int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d,
- long len);
-# endif
-__owur int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
-__owur int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, const unsigned char *d,
- long len);
-__owur int SSL_use_certificate(SSL *ssl, X509 *x);
-__owur int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
-__owur int SSL_use_cert_and_key(SSL *ssl, X509 *x509, EVP_PKEY *privatekey,
- STACK_OF(X509) *chain, int override);
-
-
-/* serverinfo file format versions */
-# define SSL_SERVERINFOV1 1
-# define SSL_SERVERINFOV2 2
-
-/* Set serverinfo data for the current active cert. */
-__owur int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,
- size_t serverinfo_length);
-__owur int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version,
- const unsigned char *serverinfo,
- size_t serverinfo_length);
-__owur int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file);
-
-#ifndef OPENSSL_NO_RSA
-__owur int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
-#endif
-
-__owur int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type);
-__owur int SSL_use_certificate_file(SSL *ssl, const char *file, int type);
-
-#ifndef OPENSSL_NO_RSA
-__owur int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file,
- int type);
-#endif
-__owur int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file,
- int type);
-__owur int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file,
- int type);
-/* PEM type */
-__owur int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file);
-__owur int SSL_use_certificate_chain_file(SSL *ssl, const char *file);
-__owur STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
-__owur int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
- const char *file);
-int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
- const char *dir);
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-# define SSL_load_error_strings() \
- OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \
- | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL)
-# endif
-
-__owur const char *SSL_state_string(const SSL *s);
-__owur const char *SSL_rstate_string(const SSL *s);
-__owur const char *SSL_state_string_long(const SSL *s);
-__owur const char *SSL_rstate_string_long(const SSL *s);
-__owur long SSL_SESSION_get_time(const SSL_SESSION *s);
-__owur long SSL_SESSION_set_time(SSL_SESSION *s, long t);
-__owur long SSL_SESSION_get_timeout(const SSL_SESSION *s);
-__owur long SSL_SESSION_set_timeout(SSL_SESSION *s, long t);
-__owur int SSL_SESSION_get_protocol_version(const SSL_SESSION *s);
-__owur int SSL_SESSION_set_protocol_version(SSL_SESSION *s, int version);
-
-__owur const char *SSL_SESSION_get0_hostname(const SSL_SESSION *s);
-__owur int SSL_SESSION_set1_hostname(SSL_SESSION *s, const char *hostname);
-void SSL_SESSION_get0_alpn_selected(const SSL_SESSION *s,
- const unsigned char **alpn,
- size_t *len);
-__owur int SSL_SESSION_set1_alpn_selected(SSL_SESSION *s,
- const unsigned char *alpn,
- size_t len);
-__owur const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *s);
-__owur int SSL_SESSION_set_cipher(SSL_SESSION *s, const SSL_CIPHER *cipher);
-__owur int SSL_SESSION_has_ticket(const SSL_SESSION *s);
-__owur unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s);
-void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick,
- size_t *len);
-__owur uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s);
-__owur int SSL_SESSION_set_max_early_data(SSL_SESSION *s,
- uint32_t max_early_data);
-__owur int SSL_copy_session_id(SSL *to, const SSL *from);
-__owur X509 *SSL_SESSION_get0_peer(SSL_SESSION *s);
-__owur int SSL_SESSION_set1_id_context(SSL_SESSION *s,
- const unsigned char *sid_ctx,
- unsigned int sid_ctx_len);
-__owur int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid,
- unsigned int sid_len);
-__owur int SSL_SESSION_is_resumable(const SSL_SESSION *s);
-
-__owur SSL_SESSION *SSL_SESSION_new(void);
-__owur SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *src);
-const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s,
- unsigned int *len);
-const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *s,
- unsigned int *len);
-__owur unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s);
-# ifndef OPENSSL_NO_STDIO
-int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *ses);
-# endif
-int SSL_SESSION_print(BIO *fp, const SSL_SESSION *ses);
-int SSL_SESSION_print_keylog(BIO *bp, const SSL_SESSION *x);
-int SSL_SESSION_up_ref(SSL_SESSION *ses);
-void SSL_SESSION_free(SSL_SESSION *ses);
-__owur int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp);
-__owur int SSL_set_session(SSL *to, SSL_SESSION *session);
-int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session);
-int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session);
-__owur int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb);
-__owur int SSL_set_generate_session_id(SSL *s, GEN_SESSION_CB cb);
-__owur int SSL_has_matching_session_id(const SSL *s,
- const unsigned char *id,
- unsigned int id_len);
-SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
- long length);
-
-# ifdef HEADER_X509_H
-__owur X509 *SSL_get_peer_certificate(const SSL *s);
-# endif
-
-__owur STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s);
-
-__owur int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
-__owur int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
-__owur SSL_verify_cb SSL_CTX_get_verify_callback(const SSL_CTX *ctx);
-void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb callback);
-void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth);
-void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
- int (*cb) (X509_STORE_CTX *, void *),
- void *arg);
-void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg),
- void *arg);
-# ifndef OPENSSL_NO_RSA
-__owur int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
-__owur int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d,
- long len);
-# endif
-__owur int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
-__owur int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx,
- const unsigned char *d, long len);
-__owur int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
-__owur int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len,
- const unsigned char *d);
-__owur int SSL_CTX_use_cert_and_key(SSL_CTX *ctx, X509 *x509, EVP_PKEY *privatekey,
- STACK_OF(X509) *chain, int override);
-
-void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
-void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
-pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx);
-void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx);
-void SSL_set_default_passwd_cb(SSL *s, pem_password_cb *cb);
-void SSL_set_default_passwd_cb_userdata(SSL *s, void *u);
-pem_password_cb *SSL_get_default_passwd_cb(SSL *s);
-void *SSL_get_default_passwd_cb_userdata(SSL *s);
-
-__owur int SSL_CTX_check_private_key(const SSL_CTX *ctx);
-__owur int SSL_check_private_key(const SSL *ctx);
-
-__owur int SSL_CTX_set_session_id_context(SSL_CTX *ctx,
- const unsigned char *sid_ctx,
- unsigned int sid_ctx_len);
-
-SSL *SSL_new(SSL_CTX *ctx);
-int SSL_up_ref(SSL *s);
-int SSL_is_dtls(const SSL *s);
-__owur int SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx,
- unsigned int sid_ctx_len);
-
-__owur int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose);
-__owur int SSL_set_purpose(SSL *ssl, int purpose);
-__owur int SSL_CTX_set_trust(SSL_CTX *ctx, int trust);
-__owur int SSL_set_trust(SSL *ssl, int trust);
-
-__owur int SSL_set1_host(SSL *s, const char *hostname);
-__owur int SSL_add1_host(SSL *s, const char *hostname);
-__owur const char *SSL_get0_peername(SSL *s);
-void SSL_set_hostflags(SSL *s, unsigned int flags);
-
-__owur int SSL_CTX_dane_enable(SSL_CTX *ctx);
-__owur int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md,
- uint8_t mtype, uint8_t ord);
-__owur int SSL_dane_enable(SSL *s, const char *basedomain);
-__owur int SSL_dane_tlsa_add(SSL *s, uint8_t usage, uint8_t selector,
- uint8_t mtype, unsigned const char *data, size_t dlen);
-__owur int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki);
-__owur int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector,
- uint8_t *mtype, unsigned const char **data,
- size_t *dlen);
-/*
- * Bridge opacity barrier between libcrypt and libssl, also needed to support
- * offline testing in test/danetest.c
- */
-SSL_DANE *SSL_get0_dane(SSL *ssl);
-/*
- * DANE flags
- */
-unsigned long SSL_CTX_dane_set_flags(SSL_CTX *ctx, unsigned long flags);
-unsigned long SSL_CTX_dane_clear_flags(SSL_CTX *ctx, unsigned long flags);
-unsigned long SSL_dane_set_flags(SSL *ssl, unsigned long flags);
-unsigned long SSL_dane_clear_flags(SSL *ssl, unsigned long flags);
-
-__owur int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm);
-__owur int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm);
-
-__owur X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx);
-__owur X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl);
-
-# ifndef OPENSSL_NO_SRP
-int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name);
-int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password);
-int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength);
-int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx,
- char *(*cb) (SSL *, void *));
-int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx,
- int (*cb) (SSL *, void *));
-int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx,
- int (*cb) (SSL *, int *, void *));
-int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg);
-
-int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
- BIGNUM *sa, BIGNUM *v, char *info);
-int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass,
- const char *grp);
-
-__owur BIGNUM *SSL_get_srp_g(SSL *s);
-__owur BIGNUM *SSL_get_srp_N(SSL *s);
-
-__owur char *SSL_get_srp_username(SSL *s);
-__owur char *SSL_get_srp_userinfo(SSL *s);
-# endif
-
-/*
- * ClientHello callback and helpers.
- */
-
-# define SSL_CLIENT_HELLO_SUCCESS 1
-# define SSL_CLIENT_HELLO_ERROR 0
-# define SSL_CLIENT_HELLO_RETRY (-1)
-
-typedef int (*SSL_client_hello_cb_fn) (SSL *s, int *al, void *arg);
-void SSL_CTX_set_client_hello_cb(SSL_CTX *c, SSL_client_hello_cb_fn cb,
- void *arg);
-int SSL_client_hello_isv2(SSL *s);
-unsigned int SSL_client_hello_get0_legacy_version(SSL *s);
-size_t SSL_client_hello_get0_random(SSL *s, const unsigned char **out);
-size_t SSL_client_hello_get0_session_id(SSL *s, const unsigned char **out);
-size_t SSL_client_hello_get0_ciphers(SSL *s, const unsigned char **out);
-size_t SSL_client_hello_get0_compression_methods(SSL *s,
- const unsigned char **out);
-int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen);
-int SSL_client_hello_get0_ext(SSL *s, unsigned int type,
- const unsigned char **out, size_t *outlen);
-
-void SSL_certs_clear(SSL *s);
-void SSL_free(SSL *ssl);
-# ifdef OSSL_ASYNC_FD
-/*
- * Windows application developer has to include windows.h to use these.
- */
-__owur int SSL_waiting_for_async(SSL *s);
-__owur int SSL_get_all_async_fds(SSL *s, OSSL_ASYNC_FD *fds, size_t *numfds);
-__owur int SSL_get_changed_async_fds(SSL *s, OSSL_ASYNC_FD *addfd,
- size_t *numaddfds, OSSL_ASYNC_FD *delfd,
- size_t *numdelfds);
-# endif
-__owur int SSL_accept(SSL *ssl);
-__owur int SSL_stateless(SSL *s);
-__owur int SSL_connect(SSL *ssl);
-__owur int SSL_read(SSL *ssl, void *buf, int num);
-__owur int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
-
-# define SSL_READ_EARLY_DATA_ERROR 0
-# define SSL_READ_EARLY_DATA_SUCCESS 1
-# define SSL_READ_EARLY_DATA_FINISH 2
-
-__owur int SSL_read_early_data(SSL *s, void *buf, size_t num,
- size_t *readbytes);
-__owur int SSL_peek(SSL *ssl, void *buf, int num);
-__owur int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
-__owur int SSL_write(SSL *ssl, const void *buf, int num);
-__owur int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written);
-__owur int SSL_write_early_data(SSL *s, const void *buf, size_t num,
- size_t *written);
-long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg);
-long SSL_callback_ctrl(SSL *, int, void (*)(void));
-long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg);
-long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void));
-
-# define SSL_EARLY_DATA_NOT_SENT 0
-# define SSL_EARLY_DATA_REJECTED 1
-# define SSL_EARLY_DATA_ACCEPTED 2
-
-__owur int SSL_get_early_data_status(const SSL *s);
-
-__owur int SSL_get_error(const SSL *s, int ret_code);
-__owur const char *SSL_get_version(const SSL *s);
-
-/* This sets the 'default' SSL version that SSL_new() will create */
-__owur int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth);
-
-# ifndef OPENSSL_NO_SSL3_METHOD
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *SSLv3_method(void)) /* SSLv3 */
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *SSLv3_server_method(void))
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *SSLv3_client_method(void))
-# endif
-
-#define SSLv23_method TLS_method
-#define SSLv23_server_method TLS_server_method
-#define SSLv23_client_method TLS_client_method
-
-/* Negotiate highest available SSL/TLS version */
-__owur const SSL_METHOD *TLS_method(void);
-__owur const SSL_METHOD *TLS_server_method(void);
-__owur const SSL_METHOD *TLS_client_method(void);
-
-# ifndef OPENSSL_NO_TLS1_METHOD
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_method(void)) /* TLSv1.0 */
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_server_method(void))
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_client_method(void))
-# endif
-
-# ifndef OPENSSL_NO_TLS1_1_METHOD
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_1_method(void)) /* TLSv1.1 */
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_1_server_method(void))
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_1_client_method(void))
-# endif
-
-# ifndef OPENSSL_NO_TLS1_2_METHOD
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_2_method(void)) /* TLSv1.2 */
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_2_server_method(void))
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_2_client_method(void))
-# endif
-
-# ifndef OPENSSL_NO_DTLS1_METHOD
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_method(void)) /* DTLSv1.0 */
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_server_method(void))
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_client_method(void))
-# endif
-
-# ifndef OPENSSL_NO_DTLS1_2_METHOD
-/* DTLSv1.2 */
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_2_method(void))
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_2_server_method(void))
-DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_2_client_method(void))
-# endif
-
-__owur const SSL_METHOD *DTLS_method(void); /* DTLS 1.0 and 1.2 */
-__owur const SSL_METHOD *DTLS_server_method(void); /* DTLS 1.0 and 1.2 */
-__owur const SSL_METHOD *DTLS_client_method(void); /* DTLS 1.0 and 1.2 */
-
-__owur size_t DTLS_get_data_mtu(const SSL *s);
-
-__owur STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
-__owur STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx);
-__owur STACK_OF(SSL_CIPHER) *SSL_get_client_ciphers(const SSL *s);
-__owur STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s);
-
-__owur int SSL_do_handshake(SSL *s);
-int SSL_key_update(SSL *s, int updatetype);
-int SSL_get_key_update_type(const SSL *s);
-int SSL_renegotiate(SSL *s);
-int SSL_renegotiate_abbreviated(SSL *s);
-__owur int SSL_renegotiate_pending(const SSL *s);
-int SSL_shutdown(SSL *s);
-__owur int SSL_verify_client_post_handshake(SSL *s);
-void SSL_CTX_set_post_handshake_auth(SSL_CTX *ctx, int val);
-void SSL_set_post_handshake_auth(SSL *s, int val);
-
-__owur const SSL_METHOD *SSL_CTX_get_ssl_method(const SSL_CTX *ctx);
-__owur const SSL_METHOD *SSL_get_ssl_method(const SSL *s);
-__owur int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method);
-__owur const char *SSL_alert_type_string_long(int value);
-__owur const char *SSL_alert_type_string(int value);
-__owur const char *SSL_alert_desc_string_long(int value);
-__owur const char *SSL_alert_desc_string(int value);
-
-void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
-void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
-__owur const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s);
-__owur const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx);
-__owur int SSL_add1_to_CA_list(SSL *ssl, const X509 *x);
-__owur int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x);
-__owur const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s);
-
-void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
-void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
-__owur STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
-__owur STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s);
-__owur int SSL_add_client_CA(SSL *ssl, X509 *x);
-__owur int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x);
-
-void SSL_set_connect_state(SSL *s);
-void SSL_set_accept_state(SSL *s);
-
-__owur long SSL_get_default_timeout(const SSL *s);
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-# define SSL_library_init() OPENSSL_init_ssl(0, NULL)
-# endif
-
-__owur char *SSL_CIPHER_description(const SSL_CIPHER *, char *buf, int size);
-__owur STACK_OF(X509_NAME) *SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk);
-
-__owur SSL *SSL_dup(SSL *ssl);
-
-__owur X509 *SSL_get_certificate(const SSL *ssl);
-/*
- * EVP_PKEY
- */
-struct evp_pkey_st *SSL_get_privatekey(const SSL *ssl);
-
-__owur X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx);
-__owur EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx);
-
-void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode);
-__owur int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx);
-void SSL_set_quiet_shutdown(SSL *ssl, int mode);
-__owur int SSL_get_quiet_shutdown(const SSL *ssl);
-void SSL_set_shutdown(SSL *ssl, int mode);
-__owur int SSL_get_shutdown(const SSL *ssl);
-__owur int SSL_version(const SSL *ssl);
-__owur int SSL_client_version(const SSL *s);
-__owur int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
-__owur int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx);
-__owur int SSL_CTX_set_default_verify_file(SSL_CTX *ctx);
-__owur int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
- const char *CApath);
-# define SSL_get0_session SSL_get_session/* just peek at pointer */
-__owur SSL_SESSION *SSL_get_session(const SSL *ssl);
-__owur SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */
-__owur SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
-SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx);
-void SSL_set_info_callback(SSL *ssl,
- void (*cb) (const SSL *ssl, int type, int val));
-void (*SSL_get_info_callback(const SSL *ssl)) (const SSL *ssl, int type,
- int val);
-__owur OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl);
-
-void SSL_set_verify_result(SSL *ssl, long v);
-__owur long SSL_get_verify_result(const SSL *ssl);
-__owur STACK_OF(X509) *SSL_get0_verified_chain(const SSL *s);
-
-__owur size_t SSL_get_client_random(const SSL *ssl, unsigned char *out,
- size_t outlen);
-__owur size_t SSL_get_server_random(const SSL *ssl, unsigned char *out,
- size_t outlen);
-__owur size_t SSL_SESSION_get_master_key(const SSL_SESSION *sess,
- unsigned char *out, size_t outlen);
-__owur int SSL_SESSION_set1_master_key(SSL_SESSION *sess,
- const unsigned char *in, size_t len);
-uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *sess);
-
-#define SSL_get_ex_new_index(l, p, newf, dupf, freef) \
- CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, l, p, newf, dupf, freef)
-__owur int SSL_set_ex_data(SSL *ssl, int idx, void *data);
-void *SSL_get_ex_data(const SSL *ssl, int idx);
-#define SSL_SESSION_get_ex_new_index(l, p, newf, dupf, freef) \
- CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, l, p, newf, dupf, freef)
-__owur int SSL_SESSION_set_ex_data(SSL_SESSION *ss, int idx, void *data);
-void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss, int idx);
-#define SSL_CTX_get_ex_new_index(l, p, newf, dupf, freef) \
- CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, l, p, newf, dupf, freef)
-__owur int SSL_CTX_set_ex_data(SSL_CTX *ssl, int idx, void *data);
-void *SSL_CTX_get_ex_data(const SSL_CTX *ssl, int idx);
-
-__owur int SSL_get_ex_data_X509_STORE_CTX_idx(void);
-
-# define SSL_CTX_sess_set_cache_size(ctx,t) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL)
-# define SSL_CTX_sess_get_cache_size(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL)
-# define SSL_CTX_set_session_cache_mode(ctx,m) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL)
-# define SSL_CTX_get_session_cache_mode(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL)
-
-# define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx)
-# define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m)
-# define SSL_CTX_get_read_ahead(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL)
-# define SSL_CTX_set_read_ahead(ctx,m) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL)
-# define SSL_CTX_get_max_cert_list(ctx) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
-# define SSL_CTX_set_max_cert_list(ctx,m) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
-# define SSL_get_max_cert_list(ssl) \
- SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
-# define SSL_set_max_cert_list(ssl,m) \
- SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
-
-# define SSL_CTX_set_max_send_fragment(ctx,m) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
-# define SSL_set_max_send_fragment(ssl,m) \
- SSL_ctrl(ssl,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
-# define SSL_CTX_set_split_send_fragment(ctx,m) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL)
-# define SSL_set_split_send_fragment(ssl,m) \
- SSL_ctrl(ssl,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL)
-# define SSL_CTX_set_max_pipelines(ctx,m) \
- SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_PIPELINES,m,NULL)
-# define SSL_set_max_pipelines(ssl,m) \
- SSL_ctrl(ssl,SSL_CTRL_SET_MAX_PIPELINES,m,NULL)
-
-void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len);
-void SSL_set_default_read_buffer_len(SSL *s, size_t len);
-
-# ifndef OPENSSL_NO_DH
-/* NB: the |keylength| is only applicable when is_export is true */
-void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
- DH *(*dh) (SSL *ssl, int is_export,
- int keylength));
-void SSL_set_tmp_dh_callback(SSL *ssl,
- DH *(*dh) (SSL *ssl, int is_export,
- int keylength));
-# endif
-
-__owur const COMP_METHOD *SSL_get_current_compression(const SSL *s);
-__owur const COMP_METHOD *SSL_get_current_expansion(const SSL *s);
-__owur const char *SSL_COMP_get_name(const COMP_METHOD *comp);
-__owur const char *SSL_COMP_get0_name(const SSL_COMP *comp);
-__owur int SSL_COMP_get_id(const SSL_COMP *comp);
-STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
-__owur STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP)
- *meths);
-# if OPENSSL_API_COMPAT < 0x10100000L
-# define SSL_COMP_free_compression_methods() while(0) continue
-# endif
-__owur int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm);
-
-const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr);
-int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *c);
-int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *c);
-int SSL_bytes_to_cipher_list(SSL *s, const unsigned char *bytes, size_t len,
- int isv2format, STACK_OF(SSL_CIPHER) **sk,
- STACK_OF(SSL_CIPHER) **scsvs);
-
-/* TLS extensions functions */
-__owur int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
-
-__owur int SSL_set_session_ticket_ext_cb(SSL *s,
- tls_session_ticket_ext_cb_fn cb,
- void *arg);
-
-/* Pre-shared secret session resumption functions */
-__owur int SSL_set_session_secret_cb(SSL *s,
- tls_session_secret_cb_fn session_secret_cb,
- void *arg);
-
-void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx,
- int (*cb) (SSL *ssl,
- int
- is_forward_secure));
-
-void SSL_set_not_resumable_session_callback(SSL *ssl,
- int (*cb) (SSL *ssl,
- int is_forward_secure));
-
-void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx,
- size_t (*cb) (SSL *ssl, int type,
- size_t len, void *arg));
-void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg);
-void *SSL_CTX_get_record_padding_callback_arg(const SSL_CTX *ctx);
-int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size);
-
-void SSL_set_record_padding_callback(SSL *ssl,
- size_t (*cb) (SSL *ssl, int type,
- size_t len, void *arg));
-void SSL_set_record_padding_callback_arg(SSL *ssl, void *arg);
-void *SSL_get_record_padding_callback_arg(const SSL *ssl);
-int SSL_set_block_padding(SSL *ssl, size_t block_size);
-
-int SSL_set_num_tickets(SSL *s, size_t num_tickets);
-size_t SSL_get_num_tickets(const SSL *s);
-int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets);
-size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx);
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-# define SSL_cache_hit(s) SSL_session_reused(s)
-# endif
-
-__owur int SSL_session_reused(const SSL *s);
-__owur int SSL_is_server(const SSL *s);
-
-__owur __owur SSL_CONF_CTX *SSL_CONF_CTX_new(void);
-int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx);
-void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx);
-unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags);
-__owur unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx,
- unsigned int flags);
-__owur int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre);
-
-void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl);
-void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx);
-
-__owur int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value);
-__owur int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv);
-__owur int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd);
-
-void SSL_add_ssl_module(void);
-int SSL_config(SSL *s, const char *name);
-int SSL_CTX_config(SSL_CTX *ctx, const char *name);
-
-# ifndef OPENSSL_NO_SSL_TRACE
-void SSL_trace(int write_p, int version, int content_type,
- const void *buf, size_t len, SSL *ssl, void *arg);
-# endif
-
-# ifndef OPENSSL_NO_SOCK
-int DTLSv1_listen(SSL *s, BIO_ADDR *client);
-# endif
-
-# ifndef OPENSSL_NO_CT
-
-/*
- * A callback for verifying that the received SCTs are sufficient.
- * Expected to return 1 if they are sufficient, otherwise 0.
- * May return a negative integer if an error occurs.
- * A connection should be aborted if the SCTs are deemed insufficient.
- */
-typedef int (*ssl_ct_validation_cb)(const CT_POLICY_EVAL_CTX *ctx,
- const STACK_OF(SCT) *scts, void *arg);
-
-/*
- * Sets a |callback| that is invoked upon receipt of ServerHelloDone to validate
- * the received SCTs.
- * If the callback returns a non-positive result, the connection is terminated.
- * Call this function before beginning a handshake.
- * If a NULL |callback| is provided, SCT validation is disabled.
- * |arg| is arbitrary userdata that will be passed to the callback whenever it
- * is invoked. Ownership of |arg| remains with the caller.
- *
- * NOTE: A side-effect of setting a CT callback is that an OCSP stapled response
- * will be requested.
- */
-int SSL_set_ct_validation_callback(SSL *s, ssl_ct_validation_cb callback,
- void *arg);
-int SSL_CTX_set_ct_validation_callback(SSL_CTX *ctx,
- ssl_ct_validation_cb callback,
- void *arg);
-#define SSL_disable_ct(s) \
- ((void) SSL_set_validation_callback((s), NULL, NULL))
-#define SSL_CTX_disable_ct(ctx) \
- ((void) SSL_CTX_set_validation_callback((ctx), NULL, NULL))
-
-/*
- * The validation type enumerates the available behaviours of the built-in SSL
- * CT validation callback selected via SSL_enable_ct() and SSL_CTX_enable_ct().
- * The underlying callback is a static function in libssl.
- */
-enum {
- SSL_CT_VALIDATION_PERMISSIVE = 0,
- SSL_CT_VALIDATION_STRICT
-};
-
-/*
- * Enable CT by setting up a callback that implements one of the built-in
- * validation variants. The SSL_CT_VALIDATION_PERMISSIVE variant always
- * continues the handshake, the application can make appropriate decisions at
- * handshake completion. The SSL_CT_VALIDATION_STRICT variant requires at
- * least one valid SCT, or else handshake termination will be requested. The
- * handshake may continue anyway if SSL_VERIFY_NONE is in effect.
- */
-int SSL_enable_ct(SSL *s, int validation_mode);
-int SSL_CTX_enable_ct(SSL_CTX *ctx, int validation_mode);
-
-/*
- * Report whether a non-NULL callback is enabled.
- */
-int SSL_ct_is_enabled(const SSL *s);
-int SSL_CTX_ct_is_enabled(const SSL_CTX *ctx);
-
-/* Gets the SCTs received from a connection */
-const STACK_OF(SCT) *SSL_get0_peer_scts(SSL *s);
-
-/*
- * Loads the CT log list from the default location.
- * If a CTLOG_STORE has previously been set using SSL_CTX_set_ctlog_store,
- * the log information loaded from this file will be appended to the
- * CTLOG_STORE.
- * Returns 1 on success, 0 otherwise.
- */
-int SSL_CTX_set_default_ctlog_list_file(SSL_CTX *ctx);
-
-/*
- * Loads the CT log list from the specified file path.
- * If a CTLOG_STORE has previously been set using SSL_CTX_set_ctlog_store,
- * the log information loaded from this file will be appended to the
- * CTLOG_STORE.
- * Returns 1 on success, 0 otherwise.
- */
-int SSL_CTX_set_ctlog_list_file(SSL_CTX *ctx, const char *path);
-
-/*
- * Sets the CT log list used by all SSL connections created from this SSL_CTX.
- * Ownership of the CTLOG_STORE is transferred to the SSL_CTX.
- */
-void SSL_CTX_set0_ctlog_store(SSL_CTX *ctx, CTLOG_STORE *logs);
-
-/*
- * Gets the CT log list used by all SSL connections created from this SSL_CTX.
- * This will be NULL unless one of the following functions has been called:
- * - SSL_CTX_set_default_ctlog_list_file
- * - SSL_CTX_set_ctlog_list_file
- * - SSL_CTX_set_ctlog_store
- */
-const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx);
-
-# endif /* OPENSSL_NO_CT */
-
-/* What the "other" parameter contains in security callback */
-/* Mask for type */
-# define SSL_SECOP_OTHER_TYPE 0xffff0000
-# define SSL_SECOP_OTHER_NONE 0
-# define SSL_SECOP_OTHER_CIPHER (1 << 16)
-# define SSL_SECOP_OTHER_CURVE (2 << 16)
-# define SSL_SECOP_OTHER_DH (3 << 16)
-# define SSL_SECOP_OTHER_PKEY (4 << 16)
-# define SSL_SECOP_OTHER_SIGALG (5 << 16)
-# define SSL_SECOP_OTHER_CERT (6 << 16)
-
-/* Indicated operation refers to peer key or certificate */
-# define SSL_SECOP_PEER 0x1000
-
-/* Values for "op" parameter in security callback */
-
-/* Called to filter ciphers */
-/* Ciphers client supports */
-# define SSL_SECOP_CIPHER_SUPPORTED (1 | SSL_SECOP_OTHER_CIPHER)
-/* Cipher shared by client/server */
-# define SSL_SECOP_CIPHER_SHARED (2 | SSL_SECOP_OTHER_CIPHER)
-/* Sanity check of cipher server selects */
-# define SSL_SECOP_CIPHER_CHECK (3 | SSL_SECOP_OTHER_CIPHER)
-/* Curves supported by client */
-# define SSL_SECOP_CURVE_SUPPORTED (4 | SSL_SECOP_OTHER_CURVE)
-/* Curves shared by client/server */
-# define SSL_SECOP_CURVE_SHARED (5 | SSL_SECOP_OTHER_CURVE)
-/* Sanity check of curve server selects */
-# define SSL_SECOP_CURVE_CHECK (6 | SSL_SECOP_OTHER_CURVE)
-/* Temporary DH key */
-# define SSL_SECOP_TMP_DH (7 | SSL_SECOP_OTHER_PKEY)
-/* SSL/TLS version */
-# define SSL_SECOP_VERSION (9 | SSL_SECOP_OTHER_NONE)
-/* Session tickets */
-# define SSL_SECOP_TICKET (10 | SSL_SECOP_OTHER_NONE)
-/* Supported signature algorithms sent to peer */
-# define SSL_SECOP_SIGALG_SUPPORTED (11 | SSL_SECOP_OTHER_SIGALG)
-/* Shared signature algorithm */
-# define SSL_SECOP_SIGALG_SHARED (12 | SSL_SECOP_OTHER_SIGALG)
-/* Sanity check signature algorithm allowed */
-# define SSL_SECOP_SIGALG_CHECK (13 | SSL_SECOP_OTHER_SIGALG)
-/* Used to get mask of supported public key signature algorithms */
-# define SSL_SECOP_SIGALG_MASK (14 | SSL_SECOP_OTHER_SIGALG)
-/* Use to see if compression is allowed */
-# define SSL_SECOP_COMPRESSION (15 | SSL_SECOP_OTHER_NONE)
-/* EE key in certificate */
-# define SSL_SECOP_EE_KEY (16 | SSL_SECOP_OTHER_CERT)
-/* CA key in certificate */
-# define SSL_SECOP_CA_KEY (17 | SSL_SECOP_OTHER_CERT)
-/* CA digest algorithm in certificate */
-# define SSL_SECOP_CA_MD (18 | SSL_SECOP_OTHER_CERT)
-/* Peer EE key in certificate */
-# define SSL_SECOP_PEER_EE_KEY (SSL_SECOP_EE_KEY | SSL_SECOP_PEER)
-/* Peer CA key in certificate */
-# define SSL_SECOP_PEER_CA_KEY (SSL_SECOP_CA_KEY | SSL_SECOP_PEER)
-/* Peer CA digest algorithm in certificate */
-# define SSL_SECOP_PEER_CA_MD (SSL_SECOP_CA_MD | SSL_SECOP_PEER)
-
-void SSL_set_security_level(SSL *s, int level);
-__owur int SSL_get_security_level(const SSL *s);
-void SSL_set_security_callback(SSL *s,
- int (*cb) (const SSL *s, const SSL_CTX *ctx,
- int op, int bits, int nid,
- void *other, void *ex));
-int (*SSL_get_security_callback(const SSL *s)) (const SSL *s,
- const SSL_CTX *ctx, int op,
- int bits, int nid, void *other,
- void *ex);
-void SSL_set0_security_ex_data(SSL *s, void *ex);
-__owur void *SSL_get0_security_ex_data(const SSL *s);
-
-void SSL_CTX_set_security_level(SSL_CTX *ctx, int level);
-__owur int SSL_CTX_get_security_level(const SSL_CTX *ctx);
-void SSL_CTX_set_security_callback(SSL_CTX *ctx,
- int (*cb) (const SSL *s, const SSL_CTX *ctx,
- int op, int bits, int nid,
- void *other, void *ex));
-int (*SSL_CTX_get_security_callback(const SSL_CTX *ctx)) (const SSL *s,
- const SSL_CTX *ctx,
- int op, int bits,
- int nid,
- void *other,
- void *ex);
-void SSL_CTX_set0_security_ex_data(SSL_CTX *ctx, void *ex);
-__owur void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx);
-
-/* OPENSSL_INIT flag 0x010000 reserved for internal use */
-# define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0x00100000L
-# define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L
-
-# define OPENSSL_INIT_SSL_DEFAULT \
- (OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS)
-
-int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
-
-# ifndef OPENSSL_NO_UNIT_TEST
-__owur const struct openssl_ssl_test_functions *SSL_test_functions(void);
-# endif
-
-__owur int SSL_free_buffers(SSL *ssl);
-__owur int SSL_alloc_buffers(SSL *ssl);
-
-/* Status codes passed to the decrypt session ticket callback. Some of these
- * are for internal use only and are never passed to the callback. */
-typedef int SSL_TICKET_STATUS;
-
-/* Support for ticket appdata */
-/* fatal error, malloc failure */
-# define SSL_TICKET_FATAL_ERR_MALLOC 0
-/* fatal error, either from parsing or decrypting the ticket */
-# define SSL_TICKET_FATAL_ERR_OTHER 1
-/* No ticket present */
-# define SSL_TICKET_NONE 2
-/* Empty ticket present */
-# define SSL_TICKET_EMPTY 3
-/* the ticket couldn't be decrypted */
-# define SSL_TICKET_NO_DECRYPT 4
-/* a ticket was successfully decrypted */
-# define SSL_TICKET_SUCCESS 5
-/* same as above but the ticket needs to be renewed */
-# define SSL_TICKET_SUCCESS_RENEW 6
-
-/* Return codes for the decrypt session ticket callback */
-typedef int SSL_TICKET_RETURN;
-
-/* An error occurred */
-#define SSL_TICKET_RETURN_ABORT 0
-/* Do not use the ticket, do not send a renewed ticket to the client */
-#define SSL_TICKET_RETURN_IGNORE 1
-/* Do not use the ticket, send a renewed ticket to the client */
-#define SSL_TICKET_RETURN_IGNORE_RENEW 2
-/* Use the ticket, do not send a renewed ticket to the client */
-#define SSL_TICKET_RETURN_USE 3
-/* Use the ticket, send a renewed ticket to the client */
-#define SSL_TICKET_RETURN_USE_RENEW 4
-
-typedef int (*SSL_CTX_generate_session_ticket_fn)(SSL *s, void *arg);
-typedef SSL_TICKET_RETURN (*SSL_CTX_decrypt_session_ticket_fn)(SSL *s, SSL_SESSION *ss,
- const unsigned char *keyname,
- size_t keyname_length,
- SSL_TICKET_STATUS status,
- void *arg);
-int SSL_CTX_set_session_ticket_cb(SSL_CTX *ctx,
- SSL_CTX_generate_session_ticket_fn gen_cb,
- SSL_CTX_decrypt_session_ticket_fn dec_cb,
- void *arg);
-int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len);
-int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len);
-
-extern const char SSL_version_str[];
-
-typedef unsigned int (*DTLS_timer_cb)(SSL *s, unsigned int timer_us);
-
-void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb);
-
-
-typedef int (*SSL_allow_early_data_cb_fn)(SSL *s, void *arg);
-void SSL_CTX_set_allow_early_data_cb(SSL_CTX *ctx,
- SSL_allow_early_data_cb_fn cb,
- void *arg);
-void SSL_set_allow_early_data_cb(SSL *s,
- SSL_allow_early_data_cb_fn cb,
- void *arg);
-
-# ifdef __cplusplus
-}
-# endif
-#endif
diff --git a/include/openssl/ssl.h.in b/include/openssl/ssl.h.in
new file mode 100644
index 000000000000..105b4a4a3c8b
--- /dev/null
+++ b/include/openssl/ssl.h.in
@@ -0,0 +1,2527 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros generate_const_stack_macros);
+-}
+
+#ifndef OPENSSL_SSL_H
+# define OPENSSL_SSL_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_SSL_H
+# endif
+
+# include <openssl/e_os2.h>
+# include <openssl/opensslconf.h>
+# include <openssl/comp.h>
+# include <openssl/bio.h>
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# include <openssl/x509.h>
+# include <openssl/crypto.h>
+# include <openssl/buffer.h>
+# endif
+# include <openssl/lhash.h>
+# include <openssl/pem.h>
+# include <openssl/hmac.h>
+# include <openssl/async.h>
+
+# include <openssl/safestack.h>
+# include <openssl/symhacks.h>
+# include <openssl/ct.h>
+# include <openssl/sslerr.h>
+# include <openssl/prov_ssl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* OpenSSL version number for ASN.1 encoding of the session information */
+/*-
+ * Version 0 - initial version
+ * Version 1 - added the optional peer certificate
+ */
+# define SSL_SESSION_ASN1_VERSION 0x0001
+
+# define SSL_MAX_SSL_SESSION_ID_LENGTH 32
+# define SSL_MAX_SID_CTX_LENGTH 32
+
+# define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES (512/8)
+# define SSL_MAX_KEY_ARG_LENGTH 8
+/* SSL_MAX_MASTER_KEY_LENGTH is defined in prov_ssl.h */
+
+/* The maximum number of encrypt/decrypt pipelines we can support */
+# define SSL_MAX_PIPELINES 32
+
+/* text strings for the ciphers */
+
+/* These are used to specify which ciphers to use and not to use */
+
+# define SSL_TXT_LOW "LOW"
+# define SSL_TXT_MEDIUM "MEDIUM"
+# define SSL_TXT_HIGH "HIGH"
+# define SSL_TXT_FIPS "FIPS"
+
+# define SSL_TXT_aNULL "aNULL"
+# define SSL_TXT_eNULL "eNULL"
+# define SSL_TXT_NULL "NULL"
+
+# define SSL_TXT_kRSA "kRSA"
+# define SSL_TXT_kDHr "kDHr"/* this cipher class has been removed */
+# define SSL_TXT_kDHd "kDHd"/* this cipher class has been removed */
+# define SSL_TXT_kDH "kDH"/* this cipher class has been removed */
+# define SSL_TXT_kEDH "kEDH"/* alias for kDHE */
+# define SSL_TXT_kDHE "kDHE"
+# define SSL_TXT_kECDHr "kECDHr"/* this cipher class has been removed */
+# define SSL_TXT_kECDHe "kECDHe"/* this cipher class has been removed */
+# define SSL_TXT_kECDH "kECDH"/* this cipher class has been removed */
+# define SSL_TXT_kEECDH "kEECDH"/* alias for kECDHE */
+# define SSL_TXT_kECDHE "kECDHE"
+# define SSL_TXT_kPSK "kPSK"
+# define SSL_TXT_kRSAPSK "kRSAPSK"
+# define SSL_TXT_kECDHEPSK "kECDHEPSK"
+# define SSL_TXT_kDHEPSK "kDHEPSK"
+# define SSL_TXT_kGOST "kGOST"
+# define SSL_TXT_kGOST18 "kGOST18"
+# define SSL_TXT_kSRP "kSRP"
+
+# define SSL_TXT_aRSA "aRSA"
+# define SSL_TXT_aDSS "aDSS"
+# define SSL_TXT_aDH "aDH"/* this cipher class has been removed */
+# define SSL_TXT_aECDH "aECDH"/* this cipher class has been removed */
+# define SSL_TXT_aECDSA "aECDSA"
+# define SSL_TXT_aPSK "aPSK"
+# define SSL_TXT_aGOST94 "aGOST94"
+# define SSL_TXT_aGOST01 "aGOST01"
+# define SSL_TXT_aGOST12 "aGOST12"
+# define SSL_TXT_aGOST "aGOST"
+# define SSL_TXT_aSRP "aSRP"
+
+# define SSL_TXT_DSS "DSS"
+# define SSL_TXT_DH "DH"
+# define SSL_TXT_DHE "DHE"/* same as "kDHE:-ADH" */
+# define SSL_TXT_EDH "EDH"/* alias for DHE */
+# define SSL_TXT_ADH "ADH"
+# define SSL_TXT_RSA "RSA"
+# define SSL_TXT_ECDH "ECDH"
+# define SSL_TXT_EECDH "EECDH"/* alias for ECDHE" */
+# define SSL_TXT_ECDHE "ECDHE"/* same as "kECDHE:-AECDH" */
+# define SSL_TXT_AECDH "AECDH"
+# define SSL_TXT_ECDSA "ECDSA"
+# define SSL_TXT_PSK "PSK"
+# define SSL_TXT_SRP "SRP"
+
+# define SSL_TXT_DES "DES"
+# define SSL_TXT_3DES "3DES"
+# define SSL_TXT_RC4 "RC4"
+# define SSL_TXT_RC2 "RC2"
+# define SSL_TXT_IDEA "IDEA"
+# define SSL_TXT_SEED "SEED"
+# define SSL_TXT_AES128 "AES128"
+# define SSL_TXT_AES256 "AES256"
+# define SSL_TXT_AES "AES"
+# define SSL_TXT_AES_GCM "AESGCM"
+# define SSL_TXT_AES_CCM "AESCCM"
+# define SSL_TXT_AES_CCM_8 "AESCCM8"
+# define SSL_TXT_CAMELLIA128 "CAMELLIA128"
+# define SSL_TXT_CAMELLIA256 "CAMELLIA256"
+# define SSL_TXT_CAMELLIA "CAMELLIA"
+# define SSL_TXT_CHACHA20 "CHACHA20"
+# define SSL_TXT_GOST "GOST89"
+# define SSL_TXT_ARIA "ARIA"
+# define SSL_TXT_ARIA_GCM "ARIAGCM"
+# define SSL_TXT_ARIA128 "ARIA128"
+# define SSL_TXT_ARIA256 "ARIA256"
+# define SSL_TXT_GOST2012_GOST8912_GOST8912 "GOST2012-GOST8912-GOST8912"
+# define SSL_TXT_CBC "CBC"
+
+# define SSL_TXT_MD5 "MD5"
+# define SSL_TXT_SHA1 "SHA1"
+# define SSL_TXT_SHA "SHA"/* same as "SHA1" */
+# define SSL_TXT_GOST94 "GOST94"
+# define SSL_TXT_GOST89MAC "GOST89MAC"
+# define SSL_TXT_GOST12 "GOST12"
+# define SSL_TXT_GOST89MAC12 "GOST89MAC12"
+# define SSL_TXT_SHA256 "SHA256"
+# define SSL_TXT_SHA384 "SHA384"
+
+# define SSL_TXT_SSLV3 "SSLv3"
+# define SSL_TXT_TLSV1 "TLSv1"
+# define SSL_TXT_TLSV1_1 "TLSv1.1"
+# define SSL_TXT_TLSV1_2 "TLSv1.2"
+
+# define SSL_TXT_ALL "ALL"
+
+/*-
+ * COMPLEMENTOF* definitions. These identifiers are used to (de-select)
+ * ciphers normally not being used.
+ * Example: "RC4" will activate all ciphers using RC4 including ciphers
+ * without authentication, which would normally disabled by DEFAULT (due
+ * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT"
+ * will make sure that it is also disabled in the specific selection.
+ * COMPLEMENTOF* identifiers are portable between version, as adjustments
+ * to the default cipher setup will also be included here.
+ *
+ * COMPLEMENTOFDEFAULT does not experience the same special treatment that
+ * DEFAULT gets, as only selection is being done and no sorting as needed
+ * for DEFAULT.
+ */
+# define SSL_TXT_CMPALL "COMPLEMENTOFALL"
+# define SSL_TXT_CMPDEF "COMPLEMENTOFDEFAULT"
+
+/*
+ * The following cipher list is used by default. It also is substituted when
+ * an application-defined cipher list string starts with 'DEFAULT'.
+ * This applies to ciphersuites for TLSv1.2 and below.
+ * DEPRECATED IN 3.0.0, in favor of OSSL_default_cipher_list()
+ * Update both macro and function simultaneously
+ */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define SSL_DEFAULT_CIPHER_LIST "ALL:!COMPLEMENTOFDEFAULT:!eNULL"
+/*
+ * This is the default set of TLSv1.3 ciphersuites
+ * DEPRECATED IN 3.0.0, in favor of OSSL_default_ciphersuites()
+ * Update both macro and function simultaneously
+ */
+# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \
+ "TLS_CHACHA20_POLY1305_SHA256:" \
+ "TLS_AES_128_GCM_SHA256"
+# endif
+/*
+ * As of OpenSSL 1.0.0, ssl_create_cipher_list() in ssl/ssl_ciph.c always
+ * starts with a reasonable order, and all we have to do for DEFAULT is
+ * throwing out anonymous and unencrypted ciphersuites! (The latter are not
+ * actually enabled by ALL, but "ALL:RSA" would enable some of them.)
+ */
+
+/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */
+# define SSL_SENT_SHUTDOWN 1
+# define SSL_RECEIVED_SHUTDOWN 2
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+# define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1
+# define SSL_FILETYPE_PEM X509_FILETYPE_PEM
+
+/*
+ * This is needed to stop compilers complaining about the 'struct ssl_st *'
+ * function parameters used to prototype callbacks in SSL_CTX.
+ */
+typedef struct ssl_st *ssl_crock_st;
+typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
+typedef struct ssl_method_st SSL_METHOD;
+typedef struct ssl_cipher_st SSL_CIPHER;
+typedef struct ssl_session_st SSL_SESSION;
+typedef struct tls_sigalgs_st TLS_SIGALGS;
+typedef struct ssl_conf_ctx_st SSL_CONF_CTX;
+typedef struct ssl_comp_st SSL_COMP;
+
+STACK_OF(SSL_CIPHER);
+STACK_OF(SSL_COMP);
+
+/* SRTP protection profiles for use with the use_srtp extension (RFC 5764)*/
+typedef struct srtp_protection_profile_st {
+ const char *name;
+ unsigned long id;
+} SRTP_PROTECTION_PROFILE;
+{-
+ generate_stack_macros("SRTP_PROTECTION_PROFILE");
+-}
+
+
+typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data,
+ int len, void *arg);
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len,
+ STACK_OF(SSL_CIPHER) *peer_ciphers,
+ const SSL_CIPHER **cipher, void *arg);
+
+/* Extension context codes */
+/* This extension is only allowed in TLS */
+#define SSL_EXT_TLS_ONLY 0x0001
+/* This extension is only allowed in DTLS */
+#define SSL_EXT_DTLS_ONLY 0x0002
+/* Some extensions may be allowed in DTLS but we don't implement them for it */
+#define SSL_EXT_TLS_IMPLEMENTATION_ONLY 0x0004
+/* Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is */
+#define SSL_EXT_SSL3_ALLOWED 0x0008
+/* Extension is only defined for TLS1.2 and below */
+#define SSL_EXT_TLS1_2_AND_BELOW_ONLY 0x0010
+/* Extension is only defined for TLS1.3 and above */
+#define SSL_EXT_TLS1_3_ONLY 0x0020
+/* Ignore this extension during parsing if we are resuming */
+#define SSL_EXT_IGNORE_ON_RESUMPTION 0x0040
+#define SSL_EXT_CLIENT_HELLO 0x0080
+/* Really means TLS1.2 or below */
+#define SSL_EXT_TLS1_2_SERVER_HELLO 0x0100
+#define SSL_EXT_TLS1_3_SERVER_HELLO 0x0200
+#define SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS 0x0400
+#define SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST 0x0800
+#define SSL_EXT_TLS1_3_CERTIFICATE 0x1000
+#define SSL_EXT_TLS1_3_NEW_SESSION_TICKET 0x2000
+#define SSL_EXT_TLS1_3_CERTIFICATE_REQUEST 0x4000
+
+/* Typedefs for handling custom extensions */
+
+typedef int (*custom_ext_add_cb)(SSL *s, unsigned int ext_type,
+ const unsigned char **out, size_t *outlen,
+ int *al, void *add_arg);
+
+typedef void (*custom_ext_free_cb)(SSL *s, unsigned int ext_type,
+ const unsigned char *out, void *add_arg);
+
+typedef int (*custom_ext_parse_cb)(SSL *s, unsigned int ext_type,
+ const unsigned char *in, size_t inlen,
+ int *al, void *parse_arg);
+
+
+typedef int (*SSL_custom_ext_add_cb_ex)(SSL *s, unsigned int ext_type,
+ unsigned int context,
+ const unsigned char **out,
+ size_t *outlen, X509 *x,
+ size_t chainidx,
+ int *al, void *add_arg);
+
+typedef void (*SSL_custom_ext_free_cb_ex)(SSL *s, unsigned int ext_type,
+ unsigned int context,
+ const unsigned char *out,
+ void *add_arg);
+
+typedef int (*SSL_custom_ext_parse_cb_ex)(SSL *s, unsigned int ext_type,
+ unsigned int context,
+ const unsigned char *in,
+ size_t inlen, X509 *x,
+ size_t chainidx,
+ int *al, void *parse_arg);
+
+/* Typedef for verification callback */
+typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx);
+
+/* Typedef for SSL async callback */
+typedef int (*SSL_async_callback_fn)(SSL *s, void *arg);
+
+#define SSL_OP_BIT(n) ((uint64_t)1 << (uint64_t)n)
+
+/*
+ * SSL/TLS connection options.
+ */
+ /* Disable Extended master secret */
+# define SSL_OP_NO_EXTENDED_MASTER_SECRET SSL_OP_BIT(0)
+ /* Cleanse plaintext copies of data delivered to the application */
+# define SSL_OP_CLEANSE_PLAINTEXT SSL_OP_BIT(1)
+ /* Allow initial connection to servers that don't support RI */
+# define SSL_OP_LEGACY_SERVER_CONNECT SSL_OP_BIT(2)
+ /* Enable support for Kernel TLS */
+# define SSL_OP_ENABLE_KTLS SSL_OP_BIT(3)
+# define SSL_OP_TLSEXT_PADDING SSL_OP_BIT(4)
+# define SSL_OP_SAFARI_ECDHE_ECDSA_BUG SSL_OP_BIT(6)
+# define SSL_OP_IGNORE_UNEXPECTED_EOF SSL_OP_BIT(7)
+# define SSL_OP_ALLOW_CLIENT_RENEGOTIATION SSL_OP_BIT(8)
+# define SSL_OP_DISABLE_TLSEXT_CA_NAMES SSL_OP_BIT(9)
+ /* In TLSv1.3 allow a non-(ec)dhe based kex_mode */
+# define SSL_OP_ALLOW_NO_DHE_KEX SSL_OP_BIT(10)
+ /*
+ * Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added
+ * in OpenSSL 0.9.6d. Usually (depending on the application protocol)
+ * the workaround is not needed. Unfortunately some broken SSL/TLS
+ * implementations cannot handle it at all, which is why we include it
+ * in SSL_OP_ALL. Added in 0.9.6e
+ */
+# define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS SSL_OP_BIT(11)
+ /* DTLS options */
+# define SSL_OP_NO_QUERY_MTU SSL_OP_BIT(12)
+ /* Turn on Cookie Exchange (on relevant for servers) */
+# define SSL_OP_COOKIE_EXCHANGE SSL_OP_BIT(13)
+ /* Don't use RFC4507 ticket extension */
+# define SSL_OP_NO_TICKET SSL_OP_BIT(14)
+# ifndef OPENSSL_NO_DTLS1_METHOD
+ /*
+ * Use Cisco's version identifier of DTLS_BAD_VER
+ * (only with deprecated DTLSv1_client_method())
+ */
+# define SSL_OP_CISCO_ANYCONNECT SSL_OP_BIT(15)
+# endif
+ /* As server, disallow session resumption on renegotiation */
+# define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION SSL_OP_BIT(16)
+ /* Don't use compression even if supported */
+# define SSL_OP_NO_COMPRESSION SSL_OP_BIT(17)
+ /* Permit unsafe legacy renegotiation */
+# define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION SSL_OP_BIT(18)
+ /* Disable encrypt-then-mac */
+# define SSL_OP_NO_ENCRYPT_THEN_MAC SSL_OP_BIT(19)
+ /*
+ * Enable TLSv1.3 Compatibility mode. This is on by default. A future
+ * version of OpenSSL may have this disabled by default.
+ */
+# define SSL_OP_ENABLE_MIDDLEBOX_COMPAT SSL_OP_BIT(20)
+ /*
+ * Prioritize Chacha20Poly1305 when client does.
+ * Modifies SSL_OP_CIPHER_SERVER_PREFERENCE
+ */
+# define SSL_OP_PRIORITIZE_CHACHA SSL_OP_BIT(21)
+ /*
+ * Set on servers to choose the cipher according to server's preferences.
+ */
+# define SSL_OP_CIPHER_SERVER_PREFERENCE SSL_OP_BIT(22)
+ /*
+ * If set, a server will allow a client to issue a SSLv3.0 version
+ * number as latest version supported in the premaster secret, even when
+ * TLSv1.0 (version 3.1) was announced in the client hello. Normally
+ * this is forbidden to prevent version rollback attacks.
+ */
+# define SSL_OP_TLS_ROLLBACK_BUG SSL_OP_BIT(23)
+ /*
+ * Switches off automatic TLSv1.3 anti-replay protection for early data.
+ * This is a server-side option only (no effect on the client).
+ */
+# define SSL_OP_NO_ANTI_REPLAY SSL_OP_BIT(24)
+# define SSL_OP_NO_SSLv3 SSL_OP_BIT(25)
+# define SSL_OP_NO_TLSv1 SSL_OP_BIT(26)
+# define SSL_OP_NO_TLSv1_2 SSL_OP_BIT(27)
+# define SSL_OP_NO_TLSv1_1 SSL_OP_BIT(28)
+# define SSL_OP_NO_TLSv1_3 SSL_OP_BIT(29)
+# define SSL_OP_NO_DTLSv1 SSL_OP_BIT(26)
+# define SSL_OP_NO_DTLSv1_2 SSL_OP_BIT(27)
+ /* Disallow all renegotiation */
+# define SSL_OP_NO_RENEGOTIATION SSL_OP_BIT(30)
+ /*
+ * Make server add server-hello extension from early version of
+ * cryptopro draft, when GOST ciphersuite is negotiated. Required for
+ * interoperability with CryptoPro CSP 3.x
+ */
+# define SSL_OP_CRYPTOPRO_TLSEXT_BUG SSL_OP_BIT(31)
+
+/*
+ * Option "collections."
+ */
+# define SSL_OP_NO_SSL_MASK \
+ ( SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 \
+ | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3 )
+# define SSL_OP_NO_DTLS_MASK \
+ ( SSL_OP_NO_DTLSv1 | SSL_OP_NO_DTLSv1_2 )
+
+/* Various bug workarounds that should be rather harmless. */
+# define SSL_OP_ALL \
+ ( SSL_OP_CRYPTOPRO_TLSEXT_BUG | SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS \
+ | SSL_OP_TLSEXT_PADDING | SSL_OP_SAFARI_ECDHE_ECDSA_BUG )
+
+/*
+ * OBSOLETE OPTIONS retained for compatibility
+ */
+
+# define SSL_OP_MICROSOFT_SESS_ID_BUG 0x0
+# define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x0
+# define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x0
+# define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x0
+# define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x0
+# define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x0
+# define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x0
+# define SSL_OP_TLS_D5_BUG 0x0
+# define SSL_OP_TLS_BLOCK_PADDING_BUG 0x0
+# define SSL_OP_SINGLE_ECDH_USE 0x0
+# define SSL_OP_SINGLE_DH_USE 0x0
+# define SSL_OP_EPHEMERAL_RSA 0x0
+# define SSL_OP_NO_SSLv2 0x0
+# define SSL_OP_PKCS1_CHECK_1 0x0
+# define SSL_OP_PKCS1_CHECK_2 0x0
+# define SSL_OP_NETSCAPE_CA_DN_BUG 0x0
+# define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x0
+
+/*
+ * Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
+ * when just a single record has been written):
+ */
+# define SSL_MODE_ENABLE_PARTIAL_WRITE 0x00000001U
+/*
+ * Make it possible to retry SSL_write() with changed buffer location (buffer
+ * contents must stay the same!); this is not the default to avoid the
+ * misconception that non-blocking SSL_write() behaves like non-blocking
+ * write():
+ */
+# define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002U
+/*
+ * Never bother the application with retries if the transport is blocking:
+ */
+# define SSL_MODE_AUTO_RETRY 0x00000004U
+/* Don't attempt to automatically build certificate chain */
+# define SSL_MODE_NO_AUTO_CHAIN 0x00000008U
+/*
+ * Save RAM by releasing read and write buffers when they're empty. (SSL3 and
+ * TLS only.) Released buffers are freed.
+ */
+# define SSL_MODE_RELEASE_BUFFERS 0x00000010U
+/*
+ * Send the current time in the Random fields of the ClientHello and
+ * ServerHello records for compatibility with hypothetical implementations
+ * that require it.
+ */
+# define SSL_MODE_SEND_CLIENTHELLO_TIME 0x00000020U
+# define SSL_MODE_SEND_SERVERHELLO_TIME 0x00000040U
+/*
+ * Send TLS_FALLBACK_SCSV in the ClientHello. To be set only by applications
+ * that reconnect with a downgraded protocol version; see
+ * draft-ietf-tls-downgrade-scsv-00 for details. DO NOT ENABLE THIS if your
+ * application attempts a normal handshake. Only use this in explicit
+ * fallback retries, following the guidance in
+ * draft-ietf-tls-downgrade-scsv-00.
+ */
+# define SSL_MODE_SEND_FALLBACK_SCSV 0x00000080U
+/*
+ * Support Asynchronous operation
+ */
+# define SSL_MODE_ASYNC 0x00000100U
+
+/*
+ * When using DTLS/SCTP, include the terminating zero in the label
+ * used for computing the endpoint-pair shared secret. Required for
+ * interoperability with implementations having this bug like these
+ * older version of OpenSSL:
+ * - OpenSSL 1.0.0 series
+ * - OpenSSL 1.0.1 series
+ * - OpenSSL 1.0.2 series
+ * - OpenSSL 1.1.0 series
+ * - OpenSSL 1.1.1 and 1.1.1a
+ */
+# define SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG 0x00000400U
+
+/* Cert related flags */
+/*
+ * Many implementations ignore some aspects of the TLS standards such as
+ * enforcing certificate chain algorithms. When this is set we enforce them.
+ */
+# define SSL_CERT_FLAG_TLS_STRICT 0x00000001U
+
+/* Suite B modes, takes same values as certificate verify flags */
+# define SSL_CERT_FLAG_SUITEB_128_LOS_ONLY 0x10000
+/* Suite B 192 bit only mode */
+# define SSL_CERT_FLAG_SUITEB_192_LOS 0x20000
+/* Suite B 128 bit mode allowing 192 bit algorithms */
+# define SSL_CERT_FLAG_SUITEB_128_LOS 0x30000
+
+/* Perform all sorts of protocol violations for testing purposes */
+# define SSL_CERT_FLAG_BROKEN_PROTOCOL 0x10000000
+
+/* Flags for building certificate chains */
+/* Treat any existing certificates as untrusted CAs */
+# define SSL_BUILD_CHAIN_FLAG_UNTRUSTED 0x1
+/* Don't include root CA in chain */
+# define SSL_BUILD_CHAIN_FLAG_NO_ROOT 0x2
+/* Just check certificates already there */
+# define SSL_BUILD_CHAIN_FLAG_CHECK 0x4
+/* Ignore verification errors */
+# define SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR 0x8
+/* Clear verification errors from queue */
+# define SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR 0x10
+
+/* Flags returned by SSL_check_chain */
+/* Certificate can be used with this session */
+# define CERT_PKEY_VALID 0x1
+/* Certificate can also be used for signing */
+# define CERT_PKEY_SIGN 0x2
+/* EE certificate signing algorithm OK */
+# define CERT_PKEY_EE_SIGNATURE 0x10
+/* CA signature algorithms OK */
+# define CERT_PKEY_CA_SIGNATURE 0x20
+/* EE certificate parameters OK */
+# define CERT_PKEY_EE_PARAM 0x40
+/* CA certificate parameters OK */
+# define CERT_PKEY_CA_PARAM 0x80
+/* Signing explicitly allowed as opposed to SHA1 fallback */
+# define CERT_PKEY_EXPLICIT_SIGN 0x100
+/* Client CA issuer names match (always set for server cert) */
+# define CERT_PKEY_ISSUER_NAME 0x200
+/* Cert type matches client types (always set for server cert) */
+# define CERT_PKEY_CERT_TYPE 0x400
+/* Cert chain suitable to Suite B */
+# define CERT_PKEY_SUITEB 0x800
+
+# define SSL_CONF_FLAG_CMDLINE 0x1
+# define SSL_CONF_FLAG_FILE 0x2
+# define SSL_CONF_FLAG_CLIENT 0x4
+# define SSL_CONF_FLAG_SERVER 0x8
+# define SSL_CONF_FLAG_SHOW_ERRORS 0x10
+# define SSL_CONF_FLAG_CERTIFICATE 0x20
+# define SSL_CONF_FLAG_REQUIRE_PRIVATE 0x40
+/* Configuration value types */
+# define SSL_CONF_TYPE_UNKNOWN 0x0
+# define SSL_CONF_TYPE_STRING 0x1
+# define SSL_CONF_TYPE_FILE 0x2
+# define SSL_CONF_TYPE_DIR 0x3
+# define SSL_CONF_TYPE_NONE 0x4
+# define SSL_CONF_TYPE_STORE 0x5
+
+/* Maximum length of the application-controlled segment of a a TLSv1.3 cookie */
+# define SSL_COOKIE_LENGTH 4096
+
+/*
+ * Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, they
+ * cannot be used to clear bits.
+ */
+
+uint64_t SSL_CTX_get_options(const SSL_CTX *ctx);
+uint64_t SSL_get_options(const SSL *s);
+uint64_t SSL_CTX_clear_options(SSL_CTX *ctx, uint64_t op);
+uint64_t SSL_clear_options(SSL *s, uint64_t op);
+uint64_t SSL_CTX_set_options(SSL_CTX *ctx, uint64_t op);
+uint64_t SSL_set_options(SSL *s, uint64_t op);
+
+# define SSL_CTX_set_mode(ctx,op) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
+# define SSL_CTX_clear_mode(ctx,op) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL)
+# define SSL_CTX_get_mode(ctx) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL)
+# define SSL_clear_mode(ssl,op) \
+ SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL)
+# define SSL_set_mode(ssl,op) \
+ SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL)
+# define SSL_get_mode(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL)
+# define SSL_set_mtu(ssl, mtu) \
+ SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL)
+# define DTLS_set_link_mtu(ssl, mtu) \
+ SSL_ctrl((ssl),DTLS_CTRL_SET_LINK_MTU,(mtu),NULL)
+# define DTLS_get_link_min_mtu(ssl) \
+ SSL_ctrl((ssl),DTLS_CTRL_GET_LINK_MIN_MTU,0,NULL)
+
+# define SSL_get_secure_renegotiation_support(ssl) \
+ SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL)
+
+# define SSL_CTX_set_cert_flags(ctx,op) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_CERT_FLAGS,(op),NULL)
+# define SSL_set_cert_flags(s,op) \
+ SSL_ctrl((s),SSL_CTRL_CERT_FLAGS,(op),NULL)
+# define SSL_CTX_clear_cert_flags(ctx,op) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL)
+# define SSL_clear_cert_flags(s,op) \
+ SSL_ctrl((s),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL)
+
+void SSL_CTX_set_msg_callback(SSL_CTX *ctx,
+ void (*cb) (int write_p, int version,
+ int content_type, const void *buf,
+ size_t len, SSL *ssl, void *arg));
+void SSL_set_msg_callback(SSL *ssl,
+ void (*cb) (int write_p, int version,
+ int content_type, const void *buf,
+ size_t len, SSL *ssl, void *arg));
+# define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
+# define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
+
+# define SSL_get_extms_support(s) \
+ SSL_ctrl((s),SSL_CTRL_GET_EXTMS_SUPPORT,0,NULL)
+
+# ifndef OPENSSL_NO_SRP
+/* see tls_srp.c */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 __owur int SSL_SRP_CTX_init(SSL *s);
+OSSL_DEPRECATEDIN_3_0 __owur int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 int SSL_SRP_CTX_free(SSL *ctx);
+OSSL_DEPRECATEDIN_3_0 int SSL_CTX_SRP_CTX_free(SSL_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0 __owur int SSL_srp_server_param_with_username(SSL *s,
+ int *ad);
+OSSL_DEPRECATEDIN_3_0 __owur int SRP_Calc_A_param(SSL *s);
+# endif
+# endif
+
+/* 100k max cert list */
+# define SSL_MAX_CERT_LIST_DEFAULT (1024*100)
+
+# define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (1024*20)
+
+/*
+ * This callback type is used inside SSL_CTX, SSL, and in the functions that
+ * set them. It is used to override the generation of SSL/TLS session IDs in
+ * a server. Return value should be zero on an error, non-zero to proceed.
+ * Also, callbacks should themselves check if the id they generate is unique
+ * otherwise the SSL handshake will fail with an error - callbacks can do
+ * this using the 'ssl' value they're passed by;
+ * SSL_has_matching_session_id(ssl, id, *id_len) The length value passed in
+ * is set at the maximum size the session ID can be. In SSLv3/TLSv1 it is 32
+ * bytes. The callback can alter this length to be less if desired. It is
+ * also an error for the callback to set the size to zero.
+ */
+typedef int (*GEN_SESSION_CB) (SSL *ssl, unsigned char *id,
+ unsigned int *id_len);
+
+# define SSL_SESS_CACHE_OFF 0x0000
+# define SSL_SESS_CACHE_CLIENT 0x0001
+# define SSL_SESS_CACHE_SERVER 0x0002
+# define SSL_SESS_CACHE_BOTH (SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER)
+# define SSL_SESS_CACHE_NO_AUTO_CLEAR 0x0080
+/* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */
+# define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP 0x0100
+# define SSL_SESS_CACHE_NO_INTERNAL_STORE 0x0200
+# define SSL_SESS_CACHE_NO_INTERNAL \
+ (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE)
+# define SSL_SESS_CACHE_UPDATE_TIME 0x0400
+
+LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx);
+# define SSL_CTX_sess_number(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL)
+# define SSL_CTX_sess_connect(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL)
+# define SSL_CTX_sess_connect_good(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL)
+# define SSL_CTX_sess_connect_renegotiate(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL)
+# define SSL_CTX_sess_accept(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL)
+# define SSL_CTX_sess_accept_renegotiate(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL)
+# define SSL_CTX_sess_accept_good(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL)
+# define SSL_CTX_sess_hits(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL)
+# define SSL_CTX_sess_cb_hits(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL)
+# define SSL_CTX_sess_misses(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL)
+# define SSL_CTX_sess_timeouts(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL)
+# define SSL_CTX_sess_cache_full(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL)
+
+void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
+ int (*new_session_cb) (struct ssl_st *ssl,
+ SSL_SESSION *sess));
+int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (struct ssl_st *ssl,
+ SSL_SESSION *sess);
+void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
+ void (*remove_session_cb) (struct ssl_ctx_st
+ *ctx,
+ SSL_SESSION *sess));
+void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (struct ssl_ctx_st *ctx,
+ SSL_SESSION *sess);
+void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
+ SSL_SESSION *(*get_session_cb) (struct ssl_st
+ *ssl,
+ const unsigned char
+ *data, int len,
+ int *copy));
+SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (struct ssl_st *ssl,
+ const unsigned char *data,
+ int len, int *copy);
+void SSL_CTX_set_info_callback(SSL_CTX *ctx,
+ void (*cb) (const SSL *ssl, int type, int val));
+void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type,
+ int val);
+void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
+ int (*client_cert_cb) (SSL *ssl, X509 **x509,
+ EVP_PKEY **pkey));
+int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509,
+ EVP_PKEY **pkey);
+# ifndef OPENSSL_NO_ENGINE
+__owur int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e);
+# endif
+void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
+ int (*app_gen_cookie_cb) (SSL *ssl,
+ unsigned char
+ *cookie,
+ unsigned int
+ *cookie_len));
+void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
+ int (*app_verify_cookie_cb) (SSL *ssl,
+ const unsigned
+ char *cookie,
+ unsigned int
+ cookie_len));
+
+void SSL_CTX_set_stateless_cookie_generate_cb(
+ SSL_CTX *ctx,
+ int (*gen_stateless_cookie_cb) (SSL *ssl,
+ unsigned char *cookie,
+ size_t *cookie_len));
+void SSL_CTX_set_stateless_cookie_verify_cb(
+ SSL_CTX *ctx,
+ int (*verify_stateless_cookie_cb) (SSL *ssl,
+ const unsigned char *cookie,
+ size_t cookie_len));
+# ifndef OPENSSL_NO_NEXTPROTONEG
+
+typedef int (*SSL_CTX_npn_advertised_cb_func)(SSL *ssl,
+ const unsigned char **out,
+ unsigned int *outlen,
+ void *arg);
+void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *s,
+ SSL_CTX_npn_advertised_cb_func cb,
+ void *arg);
+# define SSL_CTX_set_npn_advertised_cb SSL_CTX_set_next_protos_advertised_cb
+
+typedef int (*SSL_CTX_npn_select_cb_func)(SSL *s,
+ unsigned char **out,
+ unsigned char *outlen,
+ const unsigned char *in,
+ unsigned int inlen,
+ void *arg);
+void SSL_CTX_set_next_proto_select_cb(SSL_CTX *s,
+ SSL_CTX_npn_select_cb_func cb,
+ void *arg);
+# define SSL_CTX_set_npn_select_cb SSL_CTX_set_next_proto_select_cb
+
+void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
+ unsigned *len);
+# define SSL_get0_npn_negotiated SSL_get0_next_proto_negotiated
+# endif
+
+__owur int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
+ const unsigned char *in, unsigned int inlen,
+ const unsigned char *client,
+ unsigned int client_len);
+
+# define OPENSSL_NPN_UNSUPPORTED 0
+# define OPENSSL_NPN_NEGOTIATED 1
+# define OPENSSL_NPN_NO_OVERLAP 2
+
+__owur int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos,
+ unsigned int protos_len);
+__owur int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos,
+ unsigned int protos_len);
+typedef int (*SSL_CTX_alpn_select_cb_func)(SSL *ssl,
+ const unsigned char **out,
+ unsigned char *outlen,
+ const unsigned char *in,
+ unsigned int inlen,
+ void *arg);
+void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
+ SSL_CTX_alpn_select_cb_func cb,
+ void *arg);
+void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
+ unsigned int *len);
+
+# ifndef OPENSSL_NO_PSK
+/*
+ * the maximum length of the buffer given to callbacks containing the
+ * resulting identity/psk
+ */
+# define PSK_MAX_IDENTITY_LEN 256
+# define PSK_MAX_PSK_LEN 512
+typedef unsigned int (*SSL_psk_client_cb_func)(SSL *ssl,
+ const char *hint,
+ char *identity,
+ unsigned int max_identity_len,
+ unsigned char *psk,
+ unsigned int max_psk_len);
+void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, SSL_psk_client_cb_func cb);
+void SSL_set_psk_client_callback(SSL *ssl, SSL_psk_client_cb_func cb);
+
+typedef unsigned int (*SSL_psk_server_cb_func)(SSL *ssl,
+ const char *identity,
+ unsigned char *psk,
+ unsigned int max_psk_len);
+void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, SSL_psk_server_cb_func cb);
+void SSL_set_psk_server_callback(SSL *ssl, SSL_psk_server_cb_func cb);
+
+__owur int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint);
+__owur int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint);
+const char *SSL_get_psk_identity_hint(const SSL *s);
+const char *SSL_get_psk_identity(const SSL *s);
+# endif
+
+typedef int (*SSL_psk_find_session_cb_func)(SSL *ssl,
+ const unsigned char *identity,
+ size_t identity_len,
+ SSL_SESSION **sess);
+typedef int (*SSL_psk_use_session_cb_func)(SSL *ssl, const EVP_MD *md,
+ const unsigned char **id,
+ size_t *idlen,
+ SSL_SESSION **sess);
+
+void SSL_set_psk_find_session_callback(SSL *s, SSL_psk_find_session_cb_func cb);
+void SSL_CTX_set_psk_find_session_callback(SSL_CTX *ctx,
+ SSL_psk_find_session_cb_func cb);
+void SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb);
+void SSL_CTX_set_psk_use_session_callback(SSL_CTX *ctx,
+ SSL_psk_use_session_cb_func cb);
+
+/* Register callbacks to handle custom TLS Extensions for client or server. */
+
+__owur int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx,
+ unsigned int ext_type);
+
+__owur int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx,
+ unsigned int ext_type,
+ custom_ext_add_cb add_cb,
+ custom_ext_free_cb free_cb,
+ void *add_arg,
+ custom_ext_parse_cb parse_cb,
+ void *parse_arg);
+
+__owur int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx,
+ unsigned int ext_type,
+ custom_ext_add_cb add_cb,
+ custom_ext_free_cb free_cb,
+ void *add_arg,
+ custom_ext_parse_cb parse_cb,
+ void *parse_arg);
+
+__owur int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
+ unsigned int context,
+ SSL_custom_ext_add_cb_ex add_cb,
+ SSL_custom_ext_free_cb_ex free_cb,
+ void *add_arg,
+ SSL_custom_ext_parse_cb_ex parse_cb,
+ void *parse_arg);
+
+__owur int SSL_extension_supported(unsigned int ext_type);
+
+# define SSL_NOTHING 1
+# define SSL_WRITING 2
+# define SSL_READING 3
+# define SSL_X509_LOOKUP 4
+# define SSL_ASYNC_PAUSED 5
+# define SSL_ASYNC_NO_JOBS 6
+# define SSL_CLIENT_HELLO_CB 7
+# define SSL_RETRY_VERIFY 8
+
+/* These will only be used when doing non-blocking IO */
+# define SSL_want_nothing(s) (SSL_want(s) == SSL_NOTHING)
+# define SSL_want_read(s) (SSL_want(s) == SSL_READING)
+# define SSL_want_write(s) (SSL_want(s) == SSL_WRITING)
+# define SSL_want_x509_lookup(s) (SSL_want(s) == SSL_X509_LOOKUP)
+# define SSL_want_retry_verify(s) (SSL_want(s) == SSL_RETRY_VERIFY)
+# define SSL_want_async(s) (SSL_want(s) == SSL_ASYNC_PAUSED)
+# define SSL_want_async_job(s) (SSL_want(s) == SSL_ASYNC_NO_JOBS)
+# define SSL_want_client_hello_cb(s) (SSL_want(s) == SSL_CLIENT_HELLO_CB)
+
+# define SSL_MAC_FLAG_READ_MAC_STREAM 1
+# define SSL_MAC_FLAG_WRITE_MAC_STREAM 2
+# define SSL_MAC_FLAG_READ_MAC_TLSTREE 4
+# define SSL_MAC_FLAG_WRITE_MAC_TLSTREE 8
+
+/*
+ * A callback for logging out TLS key material. This callback should log out
+ * |line| followed by a newline.
+ */
+typedef void (*SSL_CTX_keylog_cb_func)(const SSL *ssl, const char *line);
+
+/*
+ * SSL_CTX_set_keylog_callback configures a callback to log key material. This
+ * is intended for debugging use with tools like Wireshark. The cb function
+ * should log line followed by a newline.
+ */
+void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb);
+
+/*
+ * SSL_CTX_get_keylog_callback returns the callback configured by
+ * SSL_CTX_set_keylog_callback.
+ */
+SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx);
+
+int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data);
+uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx);
+int SSL_set_max_early_data(SSL *s, uint32_t max_early_data);
+uint32_t SSL_get_max_early_data(const SSL *s);
+int SSL_CTX_set_recv_max_early_data(SSL_CTX *ctx, uint32_t recv_max_early_data);
+uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx);
+int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data);
+uint32_t SSL_get_recv_max_early_data(const SSL *s);
+
+#ifdef __cplusplus
+}
+#endif
+
+# include <openssl/ssl2.h>
+# include <openssl/ssl3.h>
+# include <openssl/tls1.h> /* This is mostly sslv3 with a few tweaks */
+# include <openssl/dtls1.h> /* Datagram TLS */
+# include <openssl/srtp.h> /* Support for the use_srtp extension */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * These need to be after the above set of includes due to a compiler bug
+ * in VisualStudio 2015
+ */
+{-
+ generate_const_stack_macros("SSL_CIPHER")
+ .generate_stack_macros("SSL_COMP");
+-}
+
+/* compatibility */
+# define SSL_set_app_data(s,arg) (SSL_set_ex_data(s,0,(char *)(arg)))
+# define SSL_get_app_data(s) (SSL_get_ex_data(s,0))
+# define SSL_SESSION_set_app_data(s,a) (SSL_SESSION_set_ex_data(s,0, \
+ (char *)(a)))
+# define SSL_SESSION_get_app_data(s) (SSL_SESSION_get_ex_data(s,0))
+# define SSL_CTX_get_app_data(ctx) (SSL_CTX_get_ex_data(ctx,0))
+# define SSL_CTX_set_app_data(ctx,arg) (SSL_CTX_set_ex_data(ctx,0, \
+ (char *)(arg)))
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 void SSL_set_debug(SSL *s, int debug);
+# endif
+
+/* TLSv1.3 KeyUpdate message types */
+/* -1 used so that this is an invalid value for the on-the-wire protocol */
+#define SSL_KEY_UPDATE_NONE -1
+/* Values as defined for the on-the-wire protocol */
+#define SSL_KEY_UPDATE_NOT_REQUESTED 0
+#define SSL_KEY_UPDATE_REQUESTED 1
+
+/*
+ * The valid handshake states (one for each type message sent and one for each
+ * type of message received). There are also two "special" states:
+ * TLS = TLS or DTLS state
+ * DTLS = DTLS specific state
+ * CR/SR = Client Read/Server Read
+ * CW/SW = Client Write/Server Write
+ *
+ * The "special" states are:
+ * TLS_ST_BEFORE = No handshake has been initiated yet
+ * TLS_ST_OK = A handshake has been successfully completed
+ */
+typedef enum {
+ TLS_ST_BEFORE,
+ TLS_ST_OK,
+ DTLS_ST_CR_HELLO_VERIFY_REQUEST,
+ TLS_ST_CR_SRVR_HELLO,
+ TLS_ST_CR_CERT,
+ TLS_ST_CR_CERT_STATUS,
+ TLS_ST_CR_KEY_EXCH,
+ TLS_ST_CR_CERT_REQ,
+ TLS_ST_CR_SRVR_DONE,
+ TLS_ST_CR_SESSION_TICKET,
+ TLS_ST_CR_CHANGE,
+ TLS_ST_CR_FINISHED,
+ TLS_ST_CW_CLNT_HELLO,
+ TLS_ST_CW_CERT,
+ TLS_ST_CW_KEY_EXCH,
+ TLS_ST_CW_CERT_VRFY,
+ TLS_ST_CW_CHANGE,
+ TLS_ST_CW_NEXT_PROTO,
+ TLS_ST_CW_FINISHED,
+ TLS_ST_SW_HELLO_REQ,
+ TLS_ST_SR_CLNT_HELLO,
+ DTLS_ST_SW_HELLO_VERIFY_REQUEST,
+ TLS_ST_SW_SRVR_HELLO,
+ TLS_ST_SW_CERT,
+ TLS_ST_SW_KEY_EXCH,
+ TLS_ST_SW_CERT_REQ,
+ TLS_ST_SW_SRVR_DONE,
+ TLS_ST_SR_CERT,
+ TLS_ST_SR_KEY_EXCH,
+ TLS_ST_SR_CERT_VRFY,
+ TLS_ST_SR_NEXT_PROTO,
+ TLS_ST_SR_CHANGE,
+ TLS_ST_SR_FINISHED,
+ TLS_ST_SW_SESSION_TICKET,
+ TLS_ST_SW_CERT_STATUS,
+ TLS_ST_SW_CHANGE,
+ TLS_ST_SW_FINISHED,
+ TLS_ST_SW_ENCRYPTED_EXTENSIONS,
+ TLS_ST_CR_ENCRYPTED_EXTENSIONS,
+ TLS_ST_CR_CERT_VRFY,
+ TLS_ST_SW_CERT_VRFY,
+ TLS_ST_CR_HELLO_REQ,
+ TLS_ST_SW_KEY_UPDATE,
+ TLS_ST_CW_KEY_UPDATE,
+ TLS_ST_SR_KEY_UPDATE,
+ TLS_ST_CR_KEY_UPDATE,
+ TLS_ST_EARLY_DATA,
+ TLS_ST_PENDING_EARLY_DATA_END,
+ TLS_ST_CW_END_OF_EARLY_DATA,
+ TLS_ST_SR_END_OF_EARLY_DATA
+} OSSL_HANDSHAKE_STATE;
+
+/*
+ * Most of the following state values are no longer used and are defined to be
+ * the closest equivalent value in the current state machine code. Not all
+ * defines have an equivalent and are set to a dummy value (-1). SSL_ST_CONNECT
+ * and SSL_ST_ACCEPT are still in use in the definition of SSL_CB_ACCEPT_LOOP,
+ * SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP and SSL_CB_CONNECT_EXIT.
+ */
+
+# define SSL_ST_CONNECT 0x1000
+# define SSL_ST_ACCEPT 0x2000
+
+# define SSL_ST_MASK 0x0FFF
+
+# define SSL_CB_LOOP 0x01
+# define SSL_CB_EXIT 0x02
+# define SSL_CB_READ 0x04
+# define SSL_CB_WRITE 0x08
+# define SSL_CB_ALERT 0x4000/* used in callback */
+# define SSL_CB_READ_ALERT (SSL_CB_ALERT|SSL_CB_READ)
+# define SSL_CB_WRITE_ALERT (SSL_CB_ALERT|SSL_CB_WRITE)
+# define SSL_CB_ACCEPT_LOOP (SSL_ST_ACCEPT|SSL_CB_LOOP)
+# define SSL_CB_ACCEPT_EXIT (SSL_ST_ACCEPT|SSL_CB_EXIT)
+# define SSL_CB_CONNECT_LOOP (SSL_ST_CONNECT|SSL_CB_LOOP)
+# define SSL_CB_CONNECT_EXIT (SSL_ST_CONNECT|SSL_CB_EXIT)
+# define SSL_CB_HANDSHAKE_START 0x10
+# define SSL_CB_HANDSHAKE_DONE 0x20
+
+/* Is the SSL_connection established? */
+# define SSL_in_connect_init(a) (SSL_in_init(a) && !SSL_is_server(a))
+# define SSL_in_accept_init(a) (SSL_in_init(a) && SSL_is_server(a))
+int SSL_in_init(const SSL *s);
+int SSL_in_before(const SSL *s);
+int SSL_is_init_finished(const SSL *s);
+
+/*
+ * The following 3 states are kept in ssl->rlayer.rstate when reads fail, you
+ * should not need these
+ */
+# define SSL_ST_READ_HEADER 0xF0
+# define SSL_ST_READ_BODY 0xF1
+# define SSL_ST_READ_DONE 0xF2
+
+/*-
+ * Obtain latest Finished message
+ * -- that we sent (SSL_get_finished)
+ * -- that we expected from peer (SSL_get_peer_finished).
+ * Returns length (0 == no Finished so far), copies up to 'count' bytes.
+ */
+size_t SSL_get_finished(const SSL *s, void *buf, size_t count);
+size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
+
+/*
+ * use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 3 options are
+ * 'ored' with SSL_VERIFY_PEER if they are desired
+ */
+# define SSL_VERIFY_NONE 0x00
+# define SSL_VERIFY_PEER 0x01
+# define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
+# define SSL_VERIFY_CLIENT_ONCE 0x04
+# define SSL_VERIFY_POST_HANDSHAKE 0x08
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define OpenSSL_add_ssl_algorithms() SSL_library_init()
+# define SSLeay_add_ssl_algorithms() SSL_library_init()
+# endif
+
+/* More backward compatibility */
+# define SSL_get_cipher(s) \
+ SSL_CIPHER_get_name(SSL_get_current_cipher(s))
+# define SSL_get_cipher_bits(s,np) \
+ SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np)
+# define SSL_get_cipher_version(s) \
+ SSL_CIPHER_get_version(SSL_get_current_cipher(s))
+# define SSL_get_cipher_name(s) \
+ SSL_CIPHER_get_name(SSL_get_current_cipher(s))
+# define SSL_get_time(a) SSL_SESSION_get_time(a)
+# define SSL_set_time(a,b) SSL_SESSION_set_time((a),(b))
+# define SSL_get_timeout(a) SSL_SESSION_get_timeout(a)
+# define SSL_set_timeout(a,b) SSL_SESSION_set_timeout((a),(b))
+
+# define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id)
+# define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id)
+
+DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
+# define SSL_AD_REASON_OFFSET 1000/* offset to get SSL_R_... value
+ * from SSL_AD_... */
+/* These alert types are for SSLv3 and TLSv1 */
+# define SSL_AD_CLOSE_NOTIFY SSL3_AD_CLOSE_NOTIFY
+/* fatal */
+# define SSL_AD_UNEXPECTED_MESSAGE SSL3_AD_UNEXPECTED_MESSAGE
+/* fatal */
+# define SSL_AD_BAD_RECORD_MAC SSL3_AD_BAD_RECORD_MAC
+# define SSL_AD_DECRYPTION_FAILED TLS1_AD_DECRYPTION_FAILED
+# define SSL_AD_RECORD_OVERFLOW TLS1_AD_RECORD_OVERFLOW
+/* fatal */
+# define SSL_AD_DECOMPRESSION_FAILURE SSL3_AD_DECOMPRESSION_FAILURE
+/* fatal */
+# define SSL_AD_HANDSHAKE_FAILURE SSL3_AD_HANDSHAKE_FAILURE
+/* Not for TLS */
+# define SSL_AD_NO_CERTIFICATE SSL3_AD_NO_CERTIFICATE
+# define SSL_AD_BAD_CERTIFICATE SSL3_AD_BAD_CERTIFICATE
+# define SSL_AD_UNSUPPORTED_CERTIFICATE SSL3_AD_UNSUPPORTED_CERTIFICATE
+# define SSL_AD_CERTIFICATE_REVOKED SSL3_AD_CERTIFICATE_REVOKED
+# define SSL_AD_CERTIFICATE_EXPIRED SSL3_AD_CERTIFICATE_EXPIRED
+# define SSL_AD_CERTIFICATE_UNKNOWN SSL3_AD_CERTIFICATE_UNKNOWN
+/* fatal */
+# define SSL_AD_ILLEGAL_PARAMETER SSL3_AD_ILLEGAL_PARAMETER
+/* fatal */
+# define SSL_AD_UNKNOWN_CA TLS1_AD_UNKNOWN_CA
+/* fatal */
+# define SSL_AD_ACCESS_DENIED TLS1_AD_ACCESS_DENIED
+/* fatal */
+# define SSL_AD_DECODE_ERROR TLS1_AD_DECODE_ERROR
+# define SSL_AD_DECRYPT_ERROR TLS1_AD_DECRYPT_ERROR
+/* fatal */
+# define SSL_AD_EXPORT_RESTRICTION TLS1_AD_EXPORT_RESTRICTION
+/* fatal */
+# define SSL_AD_PROTOCOL_VERSION TLS1_AD_PROTOCOL_VERSION
+/* fatal */
+# define SSL_AD_INSUFFICIENT_SECURITY TLS1_AD_INSUFFICIENT_SECURITY
+/* fatal */
+# define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR
+# define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED
+# define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION
+# define SSL_AD_MISSING_EXTENSION TLS13_AD_MISSING_EXTENSION
+# define SSL_AD_CERTIFICATE_REQUIRED TLS13_AD_CERTIFICATE_REQUIRED
+# define SSL_AD_UNSUPPORTED_EXTENSION TLS1_AD_UNSUPPORTED_EXTENSION
+# define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
+# define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME
+# define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
+# define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
+/* fatal */
+# define SSL_AD_UNKNOWN_PSK_IDENTITY TLS1_AD_UNKNOWN_PSK_IDENTITY
+/* fatal */
+# define SSL_AD_INAPPROPRIATE_FALLBACK TLS1_AD_INAPPROPRIATE_FALLBACK
+# define SSL_AD_NO_APPLICATION_PROTOCOL TLS1_AD_NO_APPLICATION_PROTOCOL
+# define SSL_ERROR_NONE 0
+# define SSL_ERROR_SSL 1
+# define SSL_ERROR_WANT_READ 2
+# define SSL_ERROR_WANT_WRITE 3
+# define SSL_ERROR_WANT_X509_LOOKUP 4
+# define SSL_ERROR_SYSCALL 5/* look at error stack/return
+ * value/errno */
+# define SSL_ERROR_ZERO_RETURN 6
+# define SSL_ERROR_WANT_CONNECT 7
+# define SSL_ERROR_WANT_ACCEPT 8
+# define SSL_ERROR_WANT_ASYNC 9
+# define SSL_ERROR_WANT_ASYNC_JOB 10
+# define SSL_ERROR_WANT_CLIENT_HELLO_CB 11
+# define SSL_ERROR_WANT_RETRY_VERIFY 12
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define SSL_CTRL_SET_TMP_DH 3
+# define SSL_CTRL_SET_TMP_ECDH 4
+# define SSL_CTRL_SET_TMP_DH_CB 6
+# endif
+
+# define SSL_CTRL_GET_CLIENT_CERT_REQUEST 9
+# define SSL_CTRL_GET_NUM_RENEGOTIATIONS 10
+# define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS 11
+# define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS 12
+# define SSL_CTRL_GET_FLAGS 13
+# define SSL_CTRL_EXTRA_CHAIN_CERT 14
+# define SSL_CTRL_SET_MSG_CALLBACK 15
+# define SSL_CTRL_SET_MSG_CALLBACK_ARG 16
+/* only applies to datagram connections */
+# define SSL_CTRL_SET_MTU 17
+/* Stats */
+# define SSL_CTRL_SESS_NUMBER 20
+# define SSL_CTRL_SESS_CONNECT 21
+# define SSL_CTRL_SESS_CONNECT_GOOD 22
+# define SSL_CTRL_SESS_CONNECT_RENEGOTIATE 23
+# define SSL_CTRL_SESS_ACCEPT 24
+# define SSL_CTRL_SESS_ACCEPT_GOOD 25
+# define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE 26
+# define SSL_CTRL_SESS_HIT 27
+# define SSL_CTRL_SESS_CB_HIT 28
+# define SSL_CTRL_SESS_MISSES 29
+# define SSL_CTRL_SESS_TIMEOUTS 30
+# define SSL_CTRL_SESS_CACHE_FULL 31
+# define SSL_CTRL_MODE 33
+# define SSL_CTRL_GET_READ_AHEAD 40
+# define SSL_CTRL_SET_READ_AHEAD 41
+# define SSL_CTRL_SET_SESS_CACHE_SIZE 42
+# define SSL_CTRL_GET_SESS_CACHE_SIZE 43
+# define SSL_CTRL_SET_SESS_CACHE_MODE 44
+# define SSL_CTRL_GET_SESS_CACHE_MODE 45
+# define SSL_CTRL_GET_MAX_CERT_LIST 50
+# define SSL_CTRL_SET_MAX_CERT_LIST 51
+# define SSL_CTRL_SET_MAX_SEND_FRAGMENT 52
+/* see tls1.h for macros based on these */
+# define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53
+# define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54
+# define SSL_CTRL_SET_TLSEXT_HOSTNAME 55
+# define SSL_CTRL_SET_TLSEXT_DEBUG_CB 56
+# define SSL_CTRL_SET_TLSEXT_DEBUG_ARG 57
+# define SSL_CTRL_GET_TLSEXT_TICKET_KEYS 58
+# define SSL_CTRL_SET_TLSEXT_TICKET_KEYS 59
+/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT 60 */
+/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB 61 */
+/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG 62 */
+# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB 63
+# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 64
+# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 65
+# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 66
+# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS 67
+# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS 68
+# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 69
+# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 70
+# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 71
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72
+# endif
+# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB 75
+# define SSL_CTRL_SET_SRP_VERIFY_PARAM_CB 76
+# define SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB 77
+# define SSL_CTRL_SET_SRP_ARG 78
+# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME 79
+# define SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH 80
+# define SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD 81
+# define DTLS_CTRL_GET_TIMEOUT 73
+# define DTLS_CTRL_HANDLE_TIMEOUT 74
+# define SSL_CTRL_GET_RI_SUPPORT 76
+# define SSL_CTRL_CLEAR_MODE 78
+# define SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB 79
+# define SSL_CTRL_GET_EXTRA_CHAIN_CERTS 82
+# define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS 83
+# define SSL_CTRL_CHAIN 88
+# define SSL_CTRL_CHAIN_CERT 89
+# define SSL_CTRL_GET_GROUPS 90
+# define SSL_CTRL_SET_GROUPS 91
+# define SSL_CTRL_SET_GROUPS_LIST 92
+# define SSL_CTRL_GET_SHARED_GROUP 93
+# define SSL_CTRL_SET_SIGALGS 97
+# define SSL_CTRL_SET_SIGALGS_LIST 98
+# define SSL_CTRL_CERT_FLAGS 99
+# define SSL_CTRL_CLEAR_CERT_FLAGS 100
+# define SSL_CTRL_SET_CLIENT_SIGALGS 101
+# define SSL_CTRL_SET_CLIENT_SIGALGS_LIST 102
+# define SSL_CTRL_GET_CLIENT_CERT_TYPES 103
+# define SSL_CTRL_SET_CLIENT_CERT_TYPES 104
+# define SSL_CTRL_BUILD_CERT_CHAIN 105
+# define SSL_CTRL_SET_VERIFY_CERT_STORE 106
+# define SSL_CTRL_SET_CHAIN_CERT_STORE 107
+# define SSL_CTRL_GET_PEER_SIGNATURE_NID 108
+# define SSL_CTRL_GET_PEER_TMP_KEY 109
+# define SSL_CTRL_GET_RAW_CIPHERLIST 110
+# define SSL_CTRL_GET_EC_POINT_FORMATS 111
+# define SSL_CTRL_GET_CHAIN_CERTS 115
+# define SSL_CTRL_SELECT_CURRENT_CERT 116
+# define SSL_CTRL_SET_CURRENT_CERT 117
+# define SSL_CTRL_SET_DH_AUTO 118
+# define DTLS_CTRL_SET_LINK_MTU 120
+# define DTLS_CTRL_GET_LINK_MIN_MTU 121
+# define SSL_CTRL_GET_EXTMS_SUPPORT 122
+# define SSL_CTRL_SET_MIN_PROTO_VERSION 123
+# define SSL_CTRL_SET_MAX_PROTO_VERSION 124
+# define SSL_CTRL_SET_SPLIT_SEND_FRAGMENT 125
+# define SSL_CTRL_SET_MAX_PIPELINES 126
+# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE 127
+# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB 128
+# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG 129
+# define SSL_CTRL_GET_MIN_PROTO_VERSION 130
+# define SSL_CTRL_GET_MAX_PROTO_VERSION 131
+# define SSL_CTRL_GET_SIGNATURE_NID 132
+# define SSL_CTRL_GET_TMP_KEY 133
+# define SSL_CTRL_GET_NEGOTIATED_GROUP 134
+# define SSL_CTRL_SET_RETRY_VERIFY 136
+# define SSL_CTRL_GET_VERIFY_CERT_STORE 137
+# define SSL_CTRL_GET_CHAIN_CERT_STORE 138
+# define SSL_CERT_SET_FIRST 1
+# define SSL_CERT_SET_NEXT 2
+# define SSL_CERT_SET_SERVER 3
+# define DTLSv1_get_timeout(ssl, arg) \
+ SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)(arg))
+# define DTLSv1_handle_timeout(ssl) \
+ SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL)
+# define SSL_num_renegotiations(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL)
+# define SSL_clear_num_renegotiations(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL)
+# define SSL_total_renegotiations(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL)
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define SSL_CTX_set_tmp_dh(ctx,dh) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)(dh))
+# endif
+# define SSL_CTX_set_dh_auto(ctx, onoff) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_DH_AUTO,onoff,NULL)
+# define SSL_set_dh_auto(s, onoff) \
+ SSL_ctrl(s,SSL_CTRL_SET_DH_AUTO,onoff,NULL)
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define SSL_set_tmp_dh(ssl,dh) \
+ SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)(dh))
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh))
+# define SSL_set_tmp_ecdh(ssl,ecdh) \
+ SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh))
+# endif
+# define SSL_CTX_add_extra_chain_cert(ctx,x509) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)(x509))
+# define SSL_CTX_get_extra_chain_certs(ctx,px509) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,0,px509)
+# define SSL_CTX_get_extra_chain_certs_only(ctx,px509) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,1,px509)
+# define SSL_CTX_clear_extra_chain_certs(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS,0,NULL)
+# define SSL_CTX_set0_chain(ctx,sk) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)(sk))
+# define SSL_CTX_set1_chain(ctx,sk) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,1,(char *)(sk))
+# define SSL_CTX_add0_chain_cert(ctx,x509) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)(x509))
+# define SSL_CTX_add1_chain_cert(ctx,x509) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)(x509))
+# define SSL_CTX_get0_chain_certs(ctx,px509) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509)
+# define SSL_CTX_clear_chain_certs(ctx) \
+ SSL_CTX_set0_chain(ctx,NULL)
+# define SSL_CTX_build_cert_chain(ctx, flags) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
+# define SSL_CTX_select_current_cert(ctx,x509) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)(x509))
+# define SSL_CTX_set_current_cert(ctx, op) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL)
+# define SSL_CTX_set0_verify_cert_store(ctx,st) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st))
+# define SSL_CTX_set1_verify_cert_store(ctx,st) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st))
+# define SSL_CTX_get0_verify_cert_store(ctx,st) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_VERIFY_CERT_STORE,0,(char *)(st))
+# define SSL_CTX_set0_chain_cert_store(ctx,st) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st))
+# define SSL_CTX_set1_chain_cert_store(ctx,st) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st))
+# define SSL_CTX_get0_chain_cert_store(ctx,st) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERT_STORE,0,(char *)(st))
+# define SSL_set0_chain(s,sk) \
+ SSL_ctrl(s,SSL_CTRL_CHAIN,0,(char *)(sk))
+# define SSL_set1_chain(s,sk) \
+ SSL_ctrl(s,SSL_CTRL_CHAIN,1,(char *)(sk))
+# define SSL_add0_chain_cert(s,x509) \
+ SSL_ctrl(s,SSL_CTRL_CHAIN_CERT,0,(char *)(x509))
+# define SSL_add1_chain_cert(s,x509) \
+ SSL_ctrl(s,SSL_CTRL_CHAIN_CERT,1,(char *)(x509))
+# define SSL_get0_chain_certs(s,px509) \
+ SSL_ctrl(s,SSL_CTRL_GET_CHAIN_CERTS,0,px509)
+# define SSL_clear_chain_certs(s) \
+ SSL_set0_chain(s,NULL)
+# define SSL_build_cert_chain(s, flags) \
+ SSL_ctrl(s,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
+# define SSL_select_current_cert(s,x509) \
+ SSL_ctrl(s,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)(x509))
+# define SSL_set_current_cert(s,op) \
+ SSL_ctrl(s,SSL_CTRL_SET_CURRENT_CERT, op, NULL)
+# define SSL_set0_verify_cert_store(s,st) \
+ SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st))
+# define SSL_set1_verify_cert_store(s,st) \
+ SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st))
+#define SSL_get0_verify_cert_store(s,st) \
+ SSL_ctrl(s,SSL_CTRL_GET_VERIFY_CERT_STORE,0,(char *)(st))
+# define SSL_set0_chain_cert_store(s,st) \
+ SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st))
+# define SSL_set1_chain_cert_store(s,st) \
+ SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st))
+#define SSL_get0_chain_cert_store(s,st) \
+ SSL_ctrl(s,SSL_CTRL_GET_CHAIN_CERT_STORE,0,(char *)(st))
+
+# define SSL_get1_groups(s, glist) \
+ SSL_ctrl(s,SSL_CTRL_GET_GROUPS,0,(int*)(glist))
+# define SSL_CTX_set1_groups(ctx, glist, glistlen) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS,glistlen,(int *)(glist))
+# define SSL_CTX_set1_groups_list(ctx, s) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(s))
+# define SSL_set1_groups(s, glist, glistlen) \
+ SSL_ctrl(s,SSL_CTRL_SET_GROUPS,glistlen,(char *)(glist))
+# define SSL_set1_groups_list(s, str) \
+ SSL_ctrl(s,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(str))
+# define SSL_get_shared_group(s, n) \
+ SSL_ctrl(s,SSL_CTRL_GET_SHARED_GROUP,n,NULL)
+# define SSL_get_negotiated_group(s) \
+ SSL_ctrl(s,SSL_CTRL_GET_NEGOTIATED_GROUP,0,NULL)
+# define SSL_CTX_set1_sigalgs(ctx, slist, slistlen) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS,slistlen,(int *)(slist))
+# define SSL_CTX_set1_sigalgs_list(ctx, s) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)(s))
+# define SSL_set1_sigalgs(s, slist, slistlen) \
+ SSL_ctrl(s,SSL_CTRL_SET_SIGALGS,slistlen,(int *)(slist))
+# define SSL_set1_sigalgs_list(s, str) \
+ SSL_ctrl(s,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)(str))
+# define SSL_CTX_set1_client_sigalgs(ctx, slist, slistlen) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS,slistlen,(int *)(slist))
+# define SSL_CTX_set1_client_sigalgs_list(ctx, s) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)(s))
+# define SSL_set1_client_sigalgs(s, slist, slistlen) \
+ SSL_ctrl(s,SSL_CTRL_SET_CLIENT_SIGALGS,slistlen,(int *)(slist))
+# define SSL_set1_client_sigalgs_list(s, str) \
+ SSL_ctrl(s,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)(str))
+# define SSL_get0_certificate_types(s, clist) \
+ SSL_ctrl(s, SSL_CTRL_GET_CLIENT_CERT_TYPES, 0, (char *)(clist))
+# define SSL_CTX_set1_client_certificate_types(ctx, clist, clistlen) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen, \
+ (char *)(clist))
+# define SSL_set1_client_certificate_types(s, clist, clistlen) \
+ SSL_ctrl(s,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen,(char *)(clist))
+# define SSL_get_signature_nid(s, pn) \
+ SSL_ctrl(s,SSL_CTRL_GET_SIGNATURE_NID,0,pn)
+# define SSL_get_peer_signature_nid(s, pn) \
+ SSL_ctrl(s,SSL_CTRL_GET_PEER_SIGNATURE_NID,0,pn)
+# define SSL_get_peer_tmp_key(s, pk) \
+ SSL_ctrl(s,SSL_CTRL_GET_PEER_TMP_KEY,0,pk)
+# define SSL_get_tmp_key(s, pk) \
+ SSL_ctrl(s,SSL_CTRL_GET_TMP_KEY,0,pk)
+# define SSL_get0_raw_cipherlist(s, plst) \
+ SSL_ctrl(s,SSL_CTRL_GET_RAW_CIPHERLIST,0,plst)
+# define SSL_get0_ec_point_formats(s, plst) \
+ SSL_ctrl(s,SSL_CTRL_GET_EC_POINT_FORMATS,0,plst)
+# define SSL_CTX_set_min_proto_version(ctx, version) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL)
+# define SSL_CTX_set_max_proto_version(ctx, version) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL)
+# define SSL_CTX_get_min_proto_version(ctx) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL)
+# define SSL_CTX_get_max_proto_version(ctx) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL)
+# define SSL_set_min_proto_version(s, version) \
+ SSL_ctrl(s, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL)
+# define SSL_set_max_proto_version(s, version) \
+ SSL_ctrl(s, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL)
+# define SSL_get_min_proto_version(s) \
+ SSL_ctrl(s, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL)
+# define SSL_get_max_proto_version(s) \
+ SSL_ctrl(s, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL)
+
+const char *SSL_group_to_name(SSL *s, int id);
+
+/* Backwards compatibility, original 1.1.0 names */
+# define SSL_CTRL_GET_SERVER_TMP_KEY \
+ SSL_CTRL_GET_PEER_TMP_KEY
+# define SSL_get_server_tmp_key(s, pk) \
+ SSL_get_peer_tmp_key(s, pk)
+
+int SSL_set0_tmp_dh_pkey(SSL *s, EVP_PKEY *dhpkey);
+int SSL_CTX_set0_tmp_dh_pkey(SSL_CTX *ctx, EVP_PKEY *dhpkey);
+
+/*
+ * The following symbol names are old and obsolete. They are kept
+ * for compatibility reasons only and should not be used anymore.
+ */
+# define SSL_CTRL_GET_CURVES SSL_CTRL_GET_GROUPS
+# define SSL_CTRL_SET_CURVES SSL_CTRL_SET_GROUPS
+# define SSL_CTRL_SET_CURVES_LIST SSL_CTRL_SET_GROUPS_LIST
+# define SSL_CTRL_GET_SHARED_CURVE SSL_CTRL_GET_SHARED_GROUP
+
+# define SSL_get1_curves SSL_get1_groups
+# define SSL_CTX_set1_curves SSL_CTX_set1_groups
+# define SSL_CTX_set1_curves_list SSL_CTX_set1_groups_list
+# define SSL_set1_curves SSL_set1_groups
+# define SSL_set1_curves_list SSL_set1_groups_list
+# define SSL_get_shared_curve SSL_get_shared_group
+
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+/* Provide some compatibility macros for removed functionality. */
+# define SSL_CTX_need_tmp_RSA(ctx) 0
+# define SSL_CTX_set_tmp_rsa(ctx,rsa) 1
+# define SSL_need_tmp_RSA(ssl) 0
+# define SSL_set_tmp_rsa(ssl,rsa) 1
+# define SSL_CTX_set_ecdh_auto(dummy, onoff) ((onoff) != 0)
+# define SSL_set_ecdh_auto(dummy, onoff) ((onoff) != 0)
+/*
+ * We "pretend" to call the callback to avoid warnings about unused static
+ * functions.
+ */
+# define SSL_CTX_set_tmp_rsa_callback(ctx, cb) while(0) (cb)(NULL, 0, 0)
+# define SSL_set_tmp_rsa_callback(ssl, cb) while(0) (cb)(NULL, 0, 0)
+# endif
+__owur const BIO_METHOD *BIO_f_ssl(void);
+__owur BIO *BIO_new_ssl(SSL_CTX *ctx, int client);
+__owur BIO *BIO_new_ssl_connect(SSL_CTX *ctx);
+__owur BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx);
+__owur int BIO_ssl_copy_session_id(BIO *to, BIO *from);
+void BIO_ssl_shutdown(BIO *ssl_bio);
+
+__owur int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str);
+__owur SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth);
+__owur SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
+ const SSL_METHOD *meth);
+int SSL_CTX_up_ref(SSL_CTX *ctx);
+void SSL_CTX_free(SSL_CTX *);
+__owur long SSL_CTX_set_timeout(SSL_CTX *ctx, long t);
+__owur long SSL_CTX_get_timeout(const SSL_CTX *ctx);
+__owur X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
+void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *);
+void SSL_CTX_set1_cert_store(SSL_CTX *, X509_STORE *);
+__owur int SSL_want(const SSL *s);
+__owur int SSL_clear(SSL *s);
+
+void SSL_CTX_flush_sessions(SSL_CTX *ctx, long tm);
+
+__owur const SSL_CIPHER *SSL_get_current_cipher(const SSL *s);
+__owur const SSL_CIPHER *SSL_get_pending_cipher(const SSL *s);
+__owur int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits);
+__owur const char *SSL_CIPHER_get_version(const SSL_CIPHER *c);
+__owur const char *SSL_CIPHER_get_name(const SSL_CIPHER *c);
+__owur const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c);
+__owur const char *OPENSSL_cipher_name(const char *rfc_name);
+__owur uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *c);
+__owur uint16_t SSL_CIPHER_get_protocol_id(const SSL_CIPHER *c);
+__owur int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c);
+__owur int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c);
+__owur const EVP_MD *SSL_CIPHER_get_handshake_digest(const SSL_CIPHER *c);
+__owur int SSL_CIPHER_is_aead(const SSL_CIPHER *c);
+
+__owur int SSL_get_fd(const SSL *s);
+__owur int SSL_get_rfd(const SSL *s);
+__owur int SSL_get_wfd(const SSL *s);
+__owur const char *SSL_get_cipher_list(const SSL *s, int n);
+__owur char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size);
+__owur int SSL_get_read_ahead(const SSL *s);
+__owur int SSL_pending(const SSL *s);
+__owur int SSL_has_pending(const SSL *s);
+# ifndef OPENSSL_NO_SOCK
+__owur int SSL_set_fd(SSL *s, int fd);
+__owur int SSL_set_rfd(SSL *s, int fd);
+__owur int SSL_set_wfd(SSL *s, int fd);
+# endif
+void SSL_set0_rbio(SSL *s, BIO *rbio);
+void SSL_set0_wbio(SSL *s, BIO *wbio);
+void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio);
+__owur BIO *SSL_get_rbio(const SSL *s);
+__owur BIO *SSL_get_wbio(const SSL *s);
+__owur int SSL_set_cipher_list(SSL *s, const char *str);
+__owur int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str);
+__owur int SSL_set_ciphersuites(SSL *s, const char *str);
+void SSL_set_read_ahead(SSL *s, int yes);
+__owur int SSL_get_verify_mode(const SSL *s);
+__owur int SSL_get_verify_depth(const SSL *s);
+__owur SSL_verify_cb SSL_get_verify_callback(const SSL *s);
+void SSL_set_verify(SSL *s, int mode, SSL_verify_cb callback);
+void SSL_set_verify_depth(SSL *s, int depth);
+void SSL_set_cert_cb(SSL *s, int (*cb) (SSL *ssl, void *arg), void *arg);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 __owur int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
+OSSL_DEPRECATEDIN_3_0
+__owur int SSL_use_RSAPrivateKey_ASN1(SSL *ssl,
+ const unsigned char *d, long len);
+# endif
+__owur int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
+__owur int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, const unsigned char *d,
+ long len);
+__owur int SSL_use_certificate(SSL *ssl, X509 *x);
+__owur int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
+__owur int SSL_use_cert_and_key(SSL *ssl, X509 *x509, EVP_PKEY *privatekey,
+ STACK_OF(X509) *chain, int override);
+
+
+/* serverinfo file format versions */
+# define SSL_SERVERINFOV1 1
+# define SSL_SERVERINFOV2 2
+
+/* Set serverinfo data for the current active cert. */
+__owur int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,
+ size_t serverinfo_length);
+__owur int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version,
+ const unsigned char *serverinfo,
+ size_t serverinfo_length);
+__owur int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file);
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
+__owur int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
+#endif
+
+__owur int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type);
+__owur int SSL_use_certificate_file(SSL *ssl, const char *file, int type);
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
+__owur int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file,
+ int type);
+#endif
+__owur int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file,
+ int type);
+__owur int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file,
+ int type);
+/* PEM type */
+__owur int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file);
+__owur int SSL_use_certificate_chain_file(SSL *ssl, const char *file);
+__owur STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
+__owur STACK_OF(X509_NAME)
+*SSL_load_client_CA_file_ex(const char *file, OSSL_LIB_CTX *libctx,
+ const char *propq);
+__owur int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
+ const char *file);
+int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
+ const char *dir);
+int SSL_add_store_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
+ const char *uri);
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define SSL_load_error_strings() \
+ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \
+ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL)
+# endif
+
+__owur const char *SSL_state_string(const SSL *s);
+__owur const char *SSL_rstate_string(const SSL *s);
+__owur const char *SSL_state_string_long(const SSL *s);
+__owur const char *SSL_rstate_string_long(const SSL *s);
+__owur long SSL_SESSION_get_time(const SSL_SESSION *s);
+__owur long SSL_SESSION_set_time(SSL_SESSION *s, long t);
+__owur long SSL_SESSION_get_timeout(const SSL_SESSION *s);
+__owur long SSL_SESSION_set_timeout(SSL_SESSION *s, long t);
+__owur int SSL_SESSION_get_protocol_version(const SSL_SESSION *s);
+__owur int SSL_SESSION_set_protocol_version(SSL_SESSION *s, int version);
+
+__owur const char *SSL_SESSION_get0_hostname(const SSL_SESSION *s);
+__owur int SSL_SESSION_set1_hostname(SSL_SESSION *s, const char *hostname);
+void SSL_SESSION_get0_alpn_selected(const SSL_SESSION *s,
+ const unsigned char **alpn,
+ size_t *len);
+__owur int SSL_SESSION_set1_alpn_selected(SSL_SESSION *s,
+ const unsigned char *alpn,
+ size_t len);
+__owur const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *s);
+__owur int SSL_SESSION_set_cipher(SSL_SESSION *s, const SSL_CIPHER *cipher);
+__owur int SSL_SESSION_has_ticket(const SSL_SESSION *s);
+__owur unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s);
+void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick,
+ size_t *len);
+__owur uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s);
+__owur int SSL_SESSION_set_max_early_data(SSL_SESSION *s,
+ uint32_t max_early_data);
+__owur int SSL_copy_session_id(SSL *to, const SSL *from);
+__owur X509 *SSL_SESSION_get0_peer(SSL_SESSION *s);
+__owur int SSL_SESSION_set1_id_context(SSL_SESSION *s,
+ const unsigned char *sid_ctx,
+ unsigned int sid_ctx_len);
+__owur int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid,
+ unsigned int sid_len);
+__owur int SSL_SESSION_is_resumable(const SSL_SESSION *s);
+
+__owur SSL_SESSION *SSL_SESSION_new(void);
+__owur SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src);
+const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s,
+ unsigned int *len);
+const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *s,
+ unsigned int *len);
+__owur unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s);
+# ifndef OPENSSL_NO_STDIO
+int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *ses);
+# endif
+int SSL_SESSION_print(BIO *fp, const SSL_SESSION *ses);
+int SSL_SESSION_print_keylog(BIO *bp, const SSL_SESSION *x);
+int SSL_SESSION_up_ref(SSL_SESSION *ses);
+void SSL_SESSION_free(SSL_SESSION *ses);
+__owur int i2d_SSL_SESSION(const SSL_SESSION *in, unsigned char **pp);
+__owur int SSL_set_session(SSL *to, SSL_SESSION *session);
+int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session);
+int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session);
+__owur int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb);
+__owur int SSL_set_generate_session_id(SSL *s, GEN_SESSION_CB cb);
+__owur int SSL_has_matching_session_id(const SSL *s,
+ const unsigned char *id,
+ unsigned int id_len);
+SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
+ long length);
+
+# ifdef OPENSSL_X509_H
+__owur X509 *SSL_get0_peer_certificate(const SSL *s);
+__owur X509 *SSL_get1_peer_certificate(const SSL *s);
+/* Deprecated in 3.0.0 */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define SSL_get_peer_certificate SSL_get1_peer_certificate
+# endif
+# endif
+
+__owur STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s);
+
+__owur int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
+__owur int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
+__owur SSL_verify_cb SSL_CTX_get_verify_callback(const SSL_CTX *ctx);
+void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb callback);
+void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth);
+void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
+ int (*cb) (X509_STORE_CTX *, void *),
+ void *arg);
+void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg),
+ void *arg);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
+__owur int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
+OSSL_DEPRECATEDIN_3_0
+__owur int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d,
+ long len);
+# endif
+__owur int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
+__owur int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx,
+ const unsigned char *d, long len);
+__owur int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
+__owur int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len,
+ const unsigned char *d);
+__owur int SSL_CTX_use_cert_and_key(SSL_CTX *ctx, X509 *x509, EVP_PKEY *privatekey,
+ STACK_OF(X509) *chain, int override);
+
+void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
+void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
+pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx);
+void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx);
+void SSL_set_default_passwd_cb(SSL *s, pem_password_cb *cb);
+void SSL_set_default_passwd_cb_userdata(SSL *s, void *u);
+pem_password_cb *SSL_get_default_passwd_cb(SSL *s);
+void *SSL_get_default_passwd_cb_userdata(SSL *s);
+
+__owur int SSL_CTX_check_private_key(const SSL_CTX *ctx);
+__owur int SSL_check_private_key(const SSL *ctx);
+
+__owur int SSL_CTX_set_session_id_context(SSL_CTX *ctx,
+ const unsigned char *sid_ctx,
+ unsigned int sid_ctx_len);
+
+SSL *SSL_new(SSL_CTX *ctx);
+int SSL_up_ref(SSL *s);
+int SSL_is_dtls(const SSL *s);
+__owur int SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx,
+ unsigned int sid_ctx_len);
+
+__owur int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose);
+__owur int SSL_set_purpose(SSL *ssl, int purpose);
+__owur int SSL_CTX_set_trust(SSL_CTX *ctx, int trust);
+__owur int SSL_set_trust(SSL *ssl, int trust);
+
+__owur int SSL_set1_host(SSL *s, const char *hostname);
+__owur int SSL_add1_host(SSL *s, const char *hostname);
+__owur const char *SSL_get0_peername(SSL *s);
+void SSL_set_hostflags(SSL *s, unsigned int flags);
+
+__owur int SSL_CTX_dane_enable(SSL_CTX *ctx);
+__owur int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md,
+ uint8_t mtype, uint8_t ord);
+__owur int SSL_dane_enable(SSL *s, const char *basedomain);
+__owur int SSL_dane_tlsa_add(SSL *s, uint8_t usage, uint8_t selector,
+ uint8_t mtype, const unsigned char *data, size_t dlen);
+__owur int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki);
+__owur int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector,
+ uint8_t *mtype, const unsigned char **data,
+ size_t *dlen);
+/*
+ * Bridge opacity barrier between libcrypt and libssl, also needed to support
+ * offline testing in test/danetest.c
+ */
+SSL_DANE *SSL_get0_dane(SSL *ssl);
+/*
+ * DANE flags
+ */
+unsigned long SSL_CTX_dane_set_flags(SSL_CTX *ctx, unsigned long flags);
+unsigned long SSL_CTX_dane_clear_flags(SSL_CTX *ctx, unsigned long flags);
+unsigned long SSL_dane_set_flags(SSL *ssl, unsigned long flags);
+unsigned long SSL_dane_clear_flags(SSL *ssl, unsigned long flags);
+
+__owur int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm);
+__owur int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm);
+
+__owur X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx);
+__owur X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl);
+
+# ifndef OPENSSL_NO_SRP
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name);
+OSSL_DEPRECATEDIN_3_0 int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password);
+OSSL_DEPRECATEDIN_3_0 int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength);
+OSSL_DEPRECATEDIN_3_0
+int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx,
+ char *(*cb) (SSL *, void *));
+OSSL_DEPRECATEDIN_3_0
+int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx,
+ int (*cb) (SSL *, void *));
+OSSL_DEPRECATEDIN_3_0
+int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx,
+ int (*cb) (SSL *, int *, void *));
+OSSL_DEPRECATEDIN_3_0 int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg);
+
+OSSL_DEPRECATEDIN_3_0
+int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
+ BIGNUM *sa, BIGNUM *v, char *info);
+OSSL_DEPRECATEDIN_3_0
+int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass,
+ const char *grp);
+
+OSSL_DEPRECATEDIN_3_0 __owur BIGNUM *SSL_get_srp_g(SSL *s);
+OSSL_DEPRECATEDIN_3_0 __owur BIGNUM *SSL_get_srp_N(SSL *s);
+
+OSSL_DEPRECATEDIN_3_0 __owur char *SSL_get_srp_username(SSL *s);
+OSSL_DEPRECATEDIN_3_0 __owur char *SSL_get_srp_userinfo(SSL *s);
+# endif
+# endif
+
+/*
+ * ClientHello callback and helpers.
+ */
+
+# define SSL_CLIENT_HELLO_SUCCESS 1
+# define SSL_CLIENT_HELLO_ERROR 0
+# define SSL_CLIENT_HELLO_RETRY (-1)
+
+typedef int (*SSL_client_hello_cb_fn) (SSL *s, int *al, void *arg);
+void SSL_CTX_set_client_hello_cb(SSL_CTX *c, SSL_client_hello_cb_fn cb,
+ void *arg);
+int SSL_client_hello_isv2(SSL *s);
+unsigned int SSL_client_hello_get0_legacy_version(SSL *s);
+size_t SSL_client_hello_get0_random(SSL *s, const unsigned char **out);
+size_t SSL_client_hello_get0_session_id(SSL *s, const unsigned char **out);
+size_t SSL_client_hello_get0_ciphers(SSL *s, const unsigned char **out);
+size_t SSL_client_hello_get0_compression_methods(SSL *s,
+ const unsigned char **out);
+int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen);
+int SSL_client_hello_get0_ext(SSL *s, unsigned int type,
+ const unsigned char **out, size_t *outlen);
+
+void SSL_certs_clear(SSL *s);
+void SSL_free(SSL *ssl);
+# ifdef OSSL_ASYNC_FD
+/*
+ * Windows application developer has to include windows.h to use these.
+ */
+__owur int SSL_waiting_for_async(SSL *s);
+__owur int SSL_get_all_async_fds(SSL *s, OSSL_ASYNC_FD *fds, size_t *numfds);
+__owur int SSL_get_changed_async_fds(SSL *s, OSSL_ASYNC_FD *addfd,
+ size_t *numaddfds, OSSL_ASYNC_FD *delfd,
+ size_t *numdelfds);
+__owur int SSL_CTX_set_async_callback(SSL_CTX *ctx, SSL_async_callback_fn callback);
+__owur int SSL_CTX_set_async_callback_arg(SSL_CTX *ctx, void *arg);
+__owur int SSL_set_async_callback(SSL *s, SSL_async_callback_fn callback);
+__owur int SSL_set_async_callback_arg(SSL *s, void *arg);
+__owur int SSL_get_async_status(SSL *s, int *status);
+
+# endif
+__owur int SSL_accept(SSL *ssl);
+__owur int SSL_stateless(SSL *s);
+__owur int SSL_connect(SSL *ssl);
+__owur int SSL_read(SSL *ssl, void *buf, int num);
+__owur int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
+
+# define SSL_READ_EARLY_DATA_ERROR 0
+# define SSL_READ_EARLY_DATA_SUCCESS 1
+# define SSL_READ_EARLY_DATA_FINISH 2
+
+__owur int SSL_read_early_data(SSL *s, void *buf, size_t num,
+ size_t *readbytes);
+__owur int SSL_peek(SSL *ssl, void *buf, int num);
+__owur int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
+__owur ossl_ssize_t SSL_sendfile(SSL *s, int fd, off_t offset, size_t size,
+ int flags);
+__owur int SSL_write(SSL *ssl, const void *buf, int num);
+__owur int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written);
+__owur int SSL_write_early_data(SSL *s, const void *buf, size_t num,
+ size_t *written);
+long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg);
+long SSL_callback_ctrl(SSL *, int, void (*)(void));
+long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg);
+long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void));
+
+# define SSL_EARLY_DATA_NOT_SENT 0
+# define SSL_EARLY_DATA_REJECTED 1
+# define SSL_EARLY_DATA_ACCEPTED 2
+
+__owur int SSL_get_early_data_status(const SSL *s);
+
+__owur int SSL_get_error(const SSL *s, int ret_code);
+__owur const char *SSL_get_version(const SSL *s);
+
+/* This sets the 'default' SSL version that SSL_new() will create */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
+__owur int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth);
+# endif
+
+# ifndef OPENSSL_NO_SSL3_METHOD
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *SSLv3_method(void); /* SSLv3 */
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *SSLv3_server_method(void);
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *SSLv3_client_method(void);
+# endif
+# endif
+
+#define SSLv23_method TLS_method
+#define SSLv23_server_method TLS_server_method
+#define SSLv23_client_method TLS_client_method
+
+/* Negotiate highest available SSL/TLS version */
+__owur const SSL_METHOD *TLS_method(void);
+__owur const SSL_METHOD *TLS_server_method(void);
+__owur const SSL_METHOD *TLS_client_method(void);
+
+# ifndef OPENSSL_NO_TLS1_METHOD
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_method(void); /* TLSv1.0 */
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_server_method(void);
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_client_method(void);
+# endif
+# endif
+
+# ifndef OPENSSL_NO_TLS1_1_METHOD
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_1_method(void); /* TLSv1.1 */
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_1_server_method(void);
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_1_client_method(void);
+# endif
+# endif
+
+# ifndef OPENSSL_NO_TLS1_2_METHOD
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_2_method(void); /* TLSv1.2 */
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_2_server_method(void);
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *TLSv1_2_client_method(void);
+# endif
+# endif
+
+# ifndef OPENSSL_NO_DTLS1_METHOD
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_method(void); /* DTLSv1.0 */
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_server_method(void);
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_client_method(void);
+# endif
+# endif
+
+# ifndef OPENSSL_NO_DTLS1_2_METHOD
+/* DTLSv1.2 */
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_2_method(void);
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_2_server_method(void);
+OSSL_DEPRECATEDIN_1_1_0 __owur const SSL_METHOD *DTLSv1_2_client_method(void);
+# endif
+# endif
+
+__owur const SSL_METHOD *DTLS_method(void); /* DTLS 1.0 and 1.2 */
+__owur const SSL_METHOD *DTLS_server_method(void); /* DTLS 1.0 and 1.2 */
+__owur const SSL_METHOD *DTLS_client_method(void); /* DTLS 1.0 and 1.2 */
+
+__owur size_t DTLS_get_data_mtu(const SSL *s);
+
+__owur STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
+__owur STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx);
+__owur STACK_OF(SSL_CIPHER) *SSL_get_client_ciphers(const SSL *s);
+__owur STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s);
+
+__owur int SSL_do_handshake(SSL *s);
+int SSL_key_update(SSL *s, int updatetype);
+int SSL_get_key_update_type(const SSL *s);
+int SSL_renegotiate(SSL *s);
+int SSL_renegotiate_abbreviated(SSL *s);
+__owur int SSL_renegotiate_pending(const SSL *s);
+int SSL_new_session_ticket(SSL *s);
+int SSL_shutdown(SSL *s);
+__owur int SSL_verify_client_post_handshake(SSL *s);
+void SSL_CTX_set_post_handshake_auth(SSL_CTX *ctx, int val);
+void SSL_set_post_handshake_auth(SSL *s, int val);
+
+__owur const SSL_METHOD *SSL_CTX_get_ssl_method(const SSL_CTX *ctx);
+__owur const SSL_METHOD *SSL_get_ssl_method(const SSL *s);
+__owur int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method);
+__owur const char *SSL_alert_type_string_long(int value);
+__owur const char *SSL_alert_type_string(int value);
+__owur const char *SSL_alert_desc_string_long(int value);
+__owur const char *SSL_alert_desc_string(int value);
+
+void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
+void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
+__owur const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s);
+__owur const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx);
+__owur int SSL_add1_to_CA_list(SSL *ssl, const X509 *x);
+__owur int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x);
+__owur const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s);
+
+void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
+void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
+__owur STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
+__owur STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s);
+__owur int SSL_add_client_CA(SSL *ssl, X509 *x);
+__owur int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x);
+
+void SSL_set_connect_state(SSL *s);
+void SSL_set_accept_state(SSL *s);
+
+__owur long SSL_get_default_timeout(const SSL *s);
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define SSL_library_init() OPENSSL_init_ssl(0, NULL)
+# endif
+
+__owur char *SSL_CIPHER_description(const SSL_CIPHER *, char *buf, int size);
+__owur STACK_OF(X509_NAME) *SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk);
+
+__owur SSL *SSL_dup(SSL *ssl);
+
+__owur X509 *SSL_get_certificate(const SSL *ssl);
+/*
+ * EVP_PKEY
+ */
+struct evp_pkey_st *SSL_get_privatekey(const SSL *ssl);
+
+__owur X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx);
+__owur EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx);
+
+void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode);
+__owur int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx);
+void SSL_set_quiet_shutdown(SSL *ssl, int mode);
+__owur int SSL_get_quiet_shutdown(const SSL *ssl);
+void SSL_set_shutdown(SSL *ssl, int mode);
+__owur int SSL_get_shutdown(const SSL *ssl);
+__owur int SSL_version(const SSL *ssl);
+__owur int SSL_client_version(const SSL *s);
+__owur int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
+__owur int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx);
+__owur int SSL_CTX_set_default_verify_file(SSL_CTX *ctx);
+__owur int SSL_CTX_set_default_verify_store(SSL_CTX *ctx);
+__owur int SSL_CTX_load_verify_file(SSL_CTX *ctx, const char *CAfile);
+__owur int SSL_CTX_load_verify_dir(SSL_CTX *ctx, const char *CApath);
+__owur int SSL_CTX_load_verify_store(SSL_CTX *ctx, const char *CAstore);
+__owur int SSL_CTX_load_verify_locations(SSL_CTX *ctx,
+ const char *CAfile,
+ const char *CApath);
+# define SSL_get0_session SSL_get_session/* just peek at pointer */
+__owur SSL_SESSION *SSL_get_session(const SSL *ssl);
+__owur SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */
+__owur SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
+SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx);
+void SSL_set_info_callback(SSL *ssl,
+ void (*cb) (const SSL *ssl, int type, int val));
+void (*SSL_get_info_callback(const SSL *ssl)) (const SSL *ssl, int type,
+ int val);
+__owur OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl);
+
+void SSL_set_verify_result(SSL *ssl, long v);
+__owur long SSL_get_verify_result(const SSL *ssl);
+__owur STACK_OF(X509) *SSL_get0_verified_chain(const SSL *s);
+
+__owur size_t SSL_get_client_random(const SSL *ssl, unsigned char *out,
+ size_t outlen);
+__owur size_t SSL_get_server_random(const SSL *ssl, unsigned char *out,
+ size_t outlen);
+__owur size_t SSL_SESSION_get_master_key(const SSL_SESSION *sess,
+ unsigned char *out, size_t outlen);
+__owur int SSL_SESSION_set1_master_key(SSL_SESSION *sess,
+ const unsigned char *in, size_t len);
+uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *sess);
+
+#define SSL_get_ex_new_index(l, p, newf, dupf, freef) \
+ CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, l, p, newf, dupf, freef)
+__owur int SSL_set_ex_data(SSL *ssl, int idx, void *data);
+void *SSL_get_ex_data(const SSL *ssl, int idx);
+#define SSL_SESSION_get_ex_new_index(l, p, newf, dupf, freef) \
+ CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, l, p, newf, dupf, freef)
+__owur int SSL_SESSION_set_ex_data(SSL_SESSION *ss, int idx, void *data);
+void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss, int idx);
+#define SSL_CTX_get_ex_new_index(l, p, newf, dupf, freef) \
+ CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, l, p, newf, dupf, freef)
+__owur int SSL_CTX_set_ex_data(SSL_CTX *ssl, int idx, void *data);
+void *SSL_CTX_get_ex_data(const SSL_CTX *ssl, int idx);
+
+__owur int SSL_get_ex_data_X509_STORE_CTX_idx(void);
+
+# define SSL_CTX_sess_set_cache_size(ctx,t) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL)
+# define SSL_CTX_sess_get_cache_size(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL)
+# define SSL_CTX_set_session_cache_mode(ctx,m) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL)
+# define SSL_CTX_get_session_cache_mode(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL)
+
+# define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx)
+# define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m)
+# define SSL_CTX_get_read_ahead(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL)
+# define SSL_CTX_set_read_ahead(ctx,m) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL)
+# define SSL_CTX_get_max_cert_list(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
+# define SSL_CTX_set_max_cert_list(ctx,m) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
+# define SSL_get_max_cert_list(ssl) \
+ SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
+# define SSL_set_max_cert_list(ssl,m) \
+ SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
+
+# define SSL_CTX_set_max_send_fragment(ctx,m) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
+# define SSL_set_max_send_fragment(ssl,m) \
+ SSL_ctrl(ssl,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
+# define SSL_CTX_set_split_send_fragment(ctx,m) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL)
+# define SSL_set_split_send_fragment(ssl,m) \
+ SSL_ctrl(ssl,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL)
+# define SSL_CTX_set_max_pipelines(ctx,m) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_PIPELINES,m,NULL)
+# define SSL_set_max_pipelines(ssl,m) \
+ SSL_ctrl(ssl,SSL_CTRL_SET_MAX_PIPELINES,m,NULL)
+# define SSL_set_retry_verify(ssl) \
+ (SSL_ctrl(ssl,SSL_CTRL_SET_RETRY_VERIFY,0,NULL) > 0)
+
+void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len);
+void SSL_set_default_read_buffer_len(SSL *s, size_t len);
+
+# ifndef OPENSSL_NO_DH
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+/* NB: the |keylength| is only applicable when is_export is true */
+OSSL_DEPRECATEDIN_3_0
+void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
+ DH *(*dh) (SSL *ssl, int is_export,
+ int keylength));
+OSSL_DEPRECATEDIN_3_0
+void SSL_set_tmp_dh_callback(SSL *ssl,
+ DH *(*dh) (SSL *ssl, int is_export,
+ int keylength));
+# endif
+# endif
+
+__owur const COMP_METHOD *SSL_get_current_compression(const SSL *s);
+__owur const COMP_METHOD *SSL_get_current_expansion(const SSL *s);
+__owur const char *SSL_COMP_get_name(const COMP_METHOD *comp);
+__owur const char *SSL_COMP_get0_name(const SSL_COMP *comp);
+__owur int SSL_COMP_get_id(const SSL_COMP *comp);
+STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
+__owur STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP)
+ *meths);
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define SSL_COMP_free_compression_methods() while(0) continue
+# endif
+__owur int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm);
+
+const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr);
+int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *c);
+int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *c);
+int SSL_bytes_to_cipher_list(SSL *s, const unsigned char *bytes, size_t len,
+ int isv2format, STACK_OF(SSL_CIPHER) **sk,
+ STACK_OF(SSL_CIPHER) **scsvs);
+
+/* TLS extensions functions */
+__owur int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
+
+__owur int SSL_set_session_ticket_ext_cb(SSL *s,
+ tls_session_ticket_ext_cb_fn cb,
+ void *arg);
+
+/* Pre-shared secret session resumption functions */
+__owur int SSL_set_session_secret_cb(SSL *s,
+ tls_session_secret_cb_fn session_secret_cb,
+ void *arg);
+
+void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx,
+ int (*cb) (SSL *ssl,
+ int
+ is_forward_secure));
+
+void SSL_set_not_resumable_session_callback(SSL *ssl,
+ int (*cb) (SSL *ssl,
+ int is_forward_secure));
+
+void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx,
+ size_t (*cb) (SSL *ssl, int type,
+ size_t len, void *arg));
+void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg);
+void *SSL_CTX_get_record_padding_callback_arg(const SSL_CTX *ctx);
+int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size);
+
+int SSL_set_record_padding_callback(SSL *ssl,
+ size_t (*cb) (SSL *ssl, int type,
+ size_t len, void *arg));
+void SSL_set_record_padding_callback_arg(SSL *ssl, void *arg);
+void *SSL_get_record_padding_callback_arg(const SSL *ssl);
+int SSL_set_block_padding(SSL *ssl, size_t block_size);
+
+int SSL_set_num_tickets(SSL *s, size_t num_tickets);
+size_t SSL_get_num_tickets(const SSL *s);
+int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets);
+size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx);
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define SSL_cache_hit(s) SSL_session_reused(s)
+# endif
+
+__owur int SSL_session_reused(const SSL *s);
+__owur int SSL_is_server(const SSL *s);
+
+__owur __owur SSL_CONF_CTX *SSL_CONF_CTX_new(void);
+int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx);
+void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx);
+unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags);
+__owur unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx,
+ unsigned int flags);
+__owur int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre);
+
+void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl);
+void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx);
+
+__owur int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value);
+__owur int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv);
+__owur int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd);
+
+void SSL_add_ssl_module(void);
+int SSL_config(SSL *s, const char *name);
+int SSL_CTX_config(SSL_CTX *ctx, const char *name);
+
+# ifndef OPENSSL_NO_SSL_TRACE
+void SSL_trace(int write_p, int version, int content_type,
+ const void *buf, size_t len, SSL *ssl, void *arg);
+# endif
+
+# ifndef OPENSSL_NO_SOCK
+int DTLSv1_listen(SSL *s, BIO_ADDR *client);
+# endif
+
+# ifndef OPENSSL_NO_CT
+
+/*
+ * A callback for verifying that the received SCTs are sufficient.
+ * Expected to return 1 if they are sufficient, otherwise 0.
+ * May return a negative integer if an error occurs.
+ * A connection should be aborted if the SCTs are deemed insufficient.
+ */
+typedef int (*ssl_ct_validation_cb)(const CT_POLICY_EVAL_CTX *ctx,
+ const STACK_OF(SCT) *scts, void *arg);
+
+/*
+ * Sets a |callback| that is invoked upon receipt of ServerHelloDone to validate
+ * the received SCTs.
+ * If the callback returns a non-positive result, the connection is terminated.
+ * Call this function before beginning a handshake.
+ * If a NULL |callback| is provided, SCT validation is disabled.
+ * |arg| is arbitrary userdata that will be passed to the callback whenever it
+ * is invoked. Ownership of |arg| remains with the caller.
+ *
+ * NOTE: A side-effect of setting a CT callback is that an OCSP stapled response
+ * will be requested.
+ */
+int SSL_set_ct_validation_callback(SSL *s, ssl_ct_validation_cb callback,
+ void *arg);
+int SSL_CTX_set_ct_validation_callback(SSL_CTX *ctx,
+ ssl_ct_validation_cb callback,
+ void *arg);
+#define SSL_disable_ct(s) \
+ ((void) SSL_set_validation_callback((s), NULL, NULL))
+#define SSL_CTX_disable_ct(ctx) \
+ ((void) SSL_CTX_set_validation_callback((ctx), NULL, NULL))
+
+/*
+ * The validation type enumerates the available behaviours of the built-in SSL
+ * CT validation callback selected via SSL_enable_ct() and SSL_CTX_enable_ct().
+ * The underlying callback is a static function in libssl.
+ */
+enum {
+ SSL_CT_VALIDATION_PERMISSIVE = 0,
+ SSL_CT_VALIDATION_STRICT
+};
+
+/*
+ * Enable CT by setting up a callback that implements one of the built-in
+ * validation variants. The SSL_CT_VALIDATION_PERMISSIVE variant always
+ * continues the handshake, the application can make appropriate decisions at
+ * handshake completion. The SSL_CT_VALIDATION_STRICT variant requires at
+ * least one valid SCT, or else handshake termination will be requested. The
+ * handshake may continue anyway if SSL_VERIFY_NONE is in effect.
+ */
+int SSL_enable_ct(SSL *s, int validation_mode);
+int SSL_CTX_enable_ct(SSL_CTX *ctx, int validation_mode);
+
+/*
+ * Report whether a non-NULL callback is enabled.
+ */
+int SSL_ct_is_enabled(const SSL *s);
+int SSL_CTX_ct_is_enabled(const SSL_CTX *ctx);
+
+/* Gets the SCTs received from a connection */
+const STACK_OF(SCT) *SSL_get0_peer_scts(SSL *s);
+
+/*
+ * Loads the CT log list from the default location.
+ * If a CTLOG_STORE has previously been set using SSL_CTX_set_ctlog_store,
+ * the log information loaded from this file will be appended to the
+ * CTLOG_STORE.
+ * Returns 1 on success, 0 otherwise.
+ */
+int SSL_CTX_set_default_ctlog_list_file(SSL_CTX *ctx);
+
+/*
+ * Loads the CT log list from the specified file path.
+ * If a CTLOG_STORE has previously been set using SSL_CTX_set_ctlog_store,
+ * the log information loaded from this file will be appended to the
+ * CTLOG_STORE.
+ * Returns 1 on success, 0 otherwise.
+ */
+int SSL_CTX_set_ctlog_list_file(SSL_CTX *ctx, const char *path);
+
+/*
+ * Sets the CT log list used by all SSL connections created from this SSL_CTX.
+ * Ownership of the CTLOG_STORE is transferred to the SSL_CTX.
+ */
+void SSL_CTX_set0_ctlog_store(SSL_CTX *ctx, CTLOG_STORE *logs);
+
+/*
+ * Gets the CT log list used by all SSL connections created from this SSL_CTX.
+ * This will be NULL unless one of the following functions has been called:
+ * - SSL_CTX_set_default_ctlog_list_file
+ * - SSL_CTX_set_ctlog_list_file
+ * - SSL_CTX_set_ctlog_store
+ */
+const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx);
+
+# endif /* OPENSSL_NO_CT */
+
+/* What the "other" parameter contains in security callback */
+/* Mask for type */
+# define SSL_SECOP_OTHER_TYPE 0xffff0000
+# define SSL_SECOP_OTHER_NONE 0
+# define SSL_SECOP_OTHER_CIPHER (1 << 16)
+# define SSL_SECOP_OTHER_CURVE (2 << 16)
+# define SSL_SECOP_OTHER_DH (3 << 16)
+# define SSL_SECOP_OTHER_PKEY (4 << 16)
+# define SSL_SECOP_OTHER_SIGALG (5 << 16)
+# define SSL_SECOP_OTHER_CERT (6 << 16)
+
+/* Indicated operation refers to peer key or certificate */
+# define SSL_SECOP_PEER 0x1000
+
+/* Values for "op" parameter in security callback */
+
+/* Called to filter ciphers */
+/* Ciphers client supports */
+# define SSL_SECOP_CIPHER_SUPPORTED (1 | SSL_SECOP_OTHER_CIPHER)
+/* Cipher shared by client/server */
+# define SSL_SECOP_CIPHER_SHARED (2 | SSL_SECOP_OTHER_CIPHER)
+/* Sanity check of cipher server selects */
+# define SSL_SECOP_CIPHER_CHECK (3 | SSL_SECOP_OTHER_CIPHER)
+/* Curves supported by client */
+# define SSL_SECOP_CURVE_SUPPORTED (4 | SSL_SECOP_OTHER_CURVE)
+/* Curves shared by client/server */
+# define SSL_SECOP_CURVE_SHARED (5 | SSL_SECOP_OTHER_CURVE)
+/* Sanity check of curve server selects */
+# define SSL_SECOP_CURVE_CHECK (6 | SSL_SECOP_OTHER_CURVE)
+/* Temporary DH key */
+# define SSL_SECOP_TMP_DH (7 | SSL_SECOP_OTHER_PKEY)
+/* SSL/TLS version */
+# define SSL_SECOP_VERSION (9 | SSL_SECOP_OTHER_NONE)
+/* Session tickets */
+# define SSL_SECOP_TICKET (10 | SSL_SECOP_OTHER_NONE)
+/* Supported signature algorithms sent to peer */
+# define SSL_SECOP_SIGALG_SUPPORTED (11 | SSL_SECOP_OTHER_SIGALG)
+/* Shared signature algorithm */
+# define SSL_SECOP_SIGALG_SHARED (12 | SSL_SECOP_OTHER_SIGALG)
+/* Sanity check signature algorithm allowed */
+# define SSL_SECOP_SIGALG_CHECK (13 | SSL_SECOP_OTHER_SIGALG)
+/* Used to get mask of supported public key signature algorithms */
+# define SSL_SECOP_SIGALG_MASK (14 | SSL_SECOP_OTHER_SIGALG)
+/* Use to see if compression is allowed */
+# define SSL_SECOP_COMPRESSION (15 | SSL_SECOP_OTHER_NONE)
+/* EE key in certificate */
+# define SSL_SECOP_EE_KEY (16 | SSL_SECOP_OTHER_CERT)
+/* CA key in certificate */
+# define SSL_SECOP_CA_KEY (17 | SSL_SECOP_OTHER_CERT)
+/* CA digest algorithm in certificate */
+# define SSL_SECOP_CA_MD (18 | SSL_SECOP_OTHER_CERT)
+/* Peer EE key in certificate */
+# define SSL_SECOP_PEER_EE_KEY (SSL_SECOP_EE_KEY | SSL_SECOP_PEER)
+/* Peer CA key in certificate */
+# define SSL_SECOP_PEER_CA_KEY (SSL_SECOP_CA_KEY | SSL_SECOP_PEER)
+/* Peer CA digest algorithm in certificate */
+# define SSL_SECOP_PEER_CA_MD (SSL_SECOP_CA_MD | SSL_SECOP_PEER)
+
+void SSL_set_security_level(SSL *s, int level);
+__owur int SSL_get_security_level(const SSL *s);
+void SSL_set_security_callback(SSL *s,
+ int (*cb) (const SSL *s, const SSL_CTX *ctx,
+ int op, int bits, int nid,
+ void *other, void *ex));
+int (*SSL_get_security_callback(const SSL *s)) (const SSL *s,
+ const SSL_CTX *ctx, int op,
+ int bits, int nid, void *other,
+ void *ex);
+void SSL_set0_security_ex_data(SSL *s, void *ex);
+__owur void *SSL_get0_security_ex_data(const SSL *s);
+
+void SSL_CTX_set_security_level(SSL_CTX *ctx, int level);
+__owur int SSL_CTX_get_security_level(const SSL_CTX *ctx);
+void SSL_CTX_set_security_callback(SSL_CTX *ctx,
+ int (*cb) (const SSL *s, const SSL_CTX *ctx,
+ int op, int bits, int nid,
+ void *other, void *ex));
+int (*SSL_CTX_get_security_callback(const SSL_CTX *ctx)) (const SSL *s,
+ const SSL_CTX *ctx,
+ int op, int bits,
+ int nid,
+ void *other,
+ void *ex);
+void SSL_CTX_set0_security_ex_data(SSL_CTX *ctx, void *ex);
+__owur void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx);
+
+/* OPENSSL_INIT flag 0x010000 reserved for internal use */
+# define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0x00100000L
+# define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L
+
+# define OPENSSL_INIT_SSL_DEFAULT \
+ (OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS)
+
+int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
+
+# ifndef OPENSSL_NO_UNIT_TEST
+__owur const struct openssl_ssl_test_functions *SSL_test_functions(void);
+# endif
+
+__owur int SSL_free_buffers(SSL *ssl);
+__owur int SSL_alloc_buffers(SSL *ssl);
+
+/* Status codes passed to the decrypt session ticket callback. Some of these
+ * are for internal use only and are never passed to the callback. */
+typedef int SSL_TICKET_STATUS;
+
+/* Support for ticket appdata */
+/* fatal error, malloc failure */
+# define SSL_TICKET_FATAL_ERR_MALLOC 0
+/* fatal error, either from parsing or decrypting the ticket */
+# define SSL_TICKET_FATAL_ERR_OTHER 1
+/* No ticket present */
+# define SSL_TICKET_NONE 2
+/* Empty ticket present */
+# define SSL_TICKET_EMPTY 3
+/* the ticket couldn't be decrypted */
+# define SSL_TICKET_NO_DECRYPT 4
+/* a ticket was successfully decrypted */
+# define SSL_TICKET_SUCCESS 5
+/* same as above but the ticket needs to be renewed */
+# define SSL_TICKET_SUCCESS_RENEW 6
+
+/* Return codes for the decrypt session ticket callback */
+typedef int SSL_TICKET_RETURN;
+
+/* An error occurred */
+#define SSL_TICKET_RETURN_ABORT 0
+/* Do not use the ticket, do not send a renewed ticket to the client */
+#define SSL_TICKET_RETURN_IGNORE 1
+/* Do not use the ticket, send a renewed ticket to the client */
+#define SSL_TICKET_RETURN_IGNORE_RENEW 2
+/* Use the ticket, do not send a renewed ticket to the client */
+#define SSL_TICKET_RETURN_USE 3
+/* Use the ticket, send a renewed ticket to the client */
+#define SSL_TICKET_RETURN_USE_RENEW 4
+
+typedef int (*SSL_CTX_generate_session_ticket_fn)(SSL *s, void *arg);
+typedef SSL_TICKET_RETURN (*SSL_CTX_decrypt_session_ticket_fn)(SSL *s, SSL_SESSION *ss,
+ const unsigned char *keyname,
+ size_t keyname_length,
+ SSL_TICKET_STATUS status,
+ void *arg);
+int SSL_CTX_set_session_ticket_cb(SSL_CTX *ctx,
+ SSL_CTX_generate_session_ticket_fn gen_cb,
+ SSL_CTX_decrypt_session_ticket_fn dec_cb,
+ void *arg);
+int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len);
+int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len);
+
+typedef unsigned int (*DTLS_timer_cb)(SSL *s, unsigned int timer_us);
+
+void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb);
+
+
+typedef int (*SSL_allow_early_data_cb_fn)(SSL *s, void *arg);
+void SSL_CTX_set_allow_early_data_cb(SSL_CTX *ctx,
+ SSL_allow_early_data_cb_fn cb,
+ void *arg);
+void SSL_set_allow_early_data_cb(SSL *s,
+ SSL_allow_early_data_cb_fn cb,
+ void *arg);
+
+/* store the default cipher strings inside the library */
+const char *OSSL_default_cipher_list(void);
+const char *OSSL_default_ciphersuites(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/ssl2.h b/include/openssl/ssl2.h
index 5321bd272cb7..428ead0540e9 100644
--- a/include/openssl/ssl2.h
+++ b/include/openssl/ssl2.h
@@ -1,14 +1,20 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_SSL2_H
-# define HEADER_SSL2_H
+#ifndef OPENSSL_SSL2_H
+# define OPENSSL_SSL2_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_SSL2_H
+# endif
#ifdef __cplusplus
extern "C" {
diff --git a/include/openssl/ssl3.h b/include/openssl/ssl3.h
index 07effba287d3..49bd51f24e32 100644
--- a/include/openssl/ssl3.h
+++ b/include/openssl/ssl3.h
@@ -1,15 +1,21 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_SSL3_H
-# define HEADER_SSL3_H
+#ifndef OPENSSL_SSL3_H
+# define OPENSSL_SSL3_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_SSL3_H
+# endif
# include <openssl/comp.h>
# include <openssl/buffer.h>
@@ -206,7 +212,7 @@ extern "C" {
# define SSL3_MD_CLIENT_FINISHED_CONST "\x43\x4C\x4E\x54"
# define SSL3_MD_SERVER_FINISHED_CONST "\x53\x52\x56\x52"
-# define SSL3_VERSION 0x0300
+/* SSL3_VERSION is defined in prov_ssl.h */
# define SSL3_VERSION_MAJOR 0x03
# define SSL3_VERSION_MINOR 0x00
@@ -214,7 +220,6 @@ extern "C" {
# define SSL3_RT_ALERT 21
# define SSL3_RT_HANDSHAKE 22
# define SSL3_RT_APPLICATION_DATA 23
-# define DTLS1_RT_HEARTBEAT 24
/* Pseudo content types to indicate additional parameters */
# define TLS1_RT_CRYPTO 0x1000
@@ -265,7 +270,7 @@ extern "C" {
* SSL3_CT_NUMBER is used to size arrays and it must be large enough to
* contain all of the cert types defined for *either* SSLv3 and TLSv1.
*/
-# define SSL3_CT_NUMBER 10
+# define SSL3_CT_NUMBER 12
# if defined(TLS_CT_NUMBER)
# if TLS_CT_NUMBER != SSL3_CT_NUMBER
diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h
index 701d61c6e9cb..b156fc2ffd7b 100644
--- a/include/openssl/sslerr.h
+++ b/include/openssl/sslerr.h
@@ -2,455 +2,21 @@
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_SSLERR_H
-# define HEADER_SSLERR_H
+#ifndef OPENSSL_SSLERR_H
+# define OPENSSL_SSLERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/sslerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_SSL_strings(void);
-/*
- * SSL function codes.
- */
-# define SSL_F_ADD_CLIENT_KEY_SHARE_EXT 438
-# define SSL_F_ADD_KEY_SHARE 512
-# define SSL_F_BYTES_TO_CIPHER_LIST 519
-# define SSL_F_CHECK_SUITEB_CIPHER_LIST 331
-# define SSL_F_CIPHERSUITE_CB 622
-# define SSL_F_CONSTRUCT_CA_NAMES 552
-# define SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS 553
-# define SSL_F_CONSTRUCT_STATEFUL_TICKET 636
-# define SSL_F_CONSTRUCT_STATELESS_TICKET 637
-# define SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH 539
-# define SSL_F_CREATE_TICKET_PREQUEL 638
-# define SSL_F_CT_MOVE_SCTS 345
-# define SSL_F_CT_STRICT 349
-# define SSL_F_CUSTOM_EXT_ADD 554
-# define SSL_F_CUSTOM_EXT_PARSE 555
-# define SSL_F_D2I_SSL_SESSION 103
-# define SSL_F_DANE_CTX_ENABLE 347
-# define SSL_F_DANE_MTYPE_SET 393
-# define SSL_F_DANE_TLSA_ADD 394
-# define SSL_F_DERIVE_SECRET_KEY_AND_IV 514
-# define SSL_F_DO_DTLS1_WRITE 245
-# define SSL_F_DO_SSL3_WRITE 104
-# define SSL_F_DTLS1_BUFFER_RECORD 247
-# define SSL_F_DTLS1_CHECK_TIMEOUT_NUM 318
-# define SSL_F_DTLS1_HEARTBEAT 305
-# define SSL_F_DTLS1_HM_FRAGMENT_NEW 623
-# define SSL_F_DTLS1_PREPROCESS_FRAGMENT 288
-# define SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS 424
-# define SSL_F_DTLS1_PROCESS_RECORD 257
-# define SSL_F_DTLS1_READ_BYTES 258
-# define SSL_F_DTLS1_READ_FAILED 339
-# define SSL_F_DTLS1_RETRANSMIT_MESSAGE 390
-# define SSL_F_DTLS1_WRITE_APP_DATA_BYTES 268
-# define SSL_F_DTLS1_WRITE_BYTES 545
-# define SSL_F_DTLSV1_LISTEN 350
-# define SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC 371
-# define SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST 385
-# define SSL_F_DTLS_GET_REASSEMBLED_MESSAGE 370
-# define SSL_F_DTLS_PROCESS_HELLO_VERIFY 386
-# define SSL_F_DTLS_RECORD_LAYER_NEW 635
-# define SSL_F_DTLS_WAIT_FOR_DRY 592
-# define SSL_F_EARLY_DATA_COUNT_OK 532
-# define SSL_F_FINAL_EARLY_DATA 556
-# define SSL_F_FINAL_EC_PT_FORMATS 485
-# define SSL_F_FINAL_EMS 486
-# define SSL_F_FINAL_KEY_SHARE 503
-# define SSL_F_FINAL_MAXFRAGMENTLEN 557
-# define SSL_F_FINAL_PSK 639
-# define SSL_F_FINAL_RENEGOTIATE 483
-# define SSL_F_FINAL_SERVER_NAME 558
-# define SSL_F_FINAL_SIG_ALGS 497
-# define SSL_F_GET_CERT_VERIFY_TBS_DATA 588
-# define SSL_F_NSS_KEYLOG_INT 500
-# define SSL_F_OPENSSL_INIT_SSL 342
-# define SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION 436
-# define SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION 598
-# define SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE 430
-# define SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE 593
-# define SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE 594
-# define SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION 417
-# define SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION 599
-# define SSL_F_OSSL_STATEM_SERVER13_READ_TRANSITION 437
-# define SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION 600
-# define SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE 431
-# define SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE 601
-# define SSL_F_OSSL_STATEM_SERVER_POST_WORK 602
-# define SSL_F_OSSL_STATEM_SERVER_PRE_WORK 640
-# define SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE 603
-# define SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION 418
-# define SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION 604
-# define SSL_F_PARSE_CA_NAMES 541
-# define SSL_F_PITEM_NEW 624
-# define SSL_F_PQUEUE_NEW 625
-# define SSL_F_PROCESS_KEY_SHARE_EXT 439
-# define SSL_F_READ_STATE_MACHINE 352
-# define SSL_F_SET_CLIENT_CIPHERSUITE 540
-# define SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET 595
-# define SSL_F_SRP_GENERATE_SERVER_MASTER_SECRET 589
-# define SSL_F_SRP_VERIFY_SERVER_PARAM 596
-# define SSL_F_SSL3_CHANGE_CIPHER_STATE 129
-# define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130
-# define SSL_F_SSL3_CTRL 213
-# define SSL_F_SSL3_CTX_CTRL 133
-# define SSL_F_SSL3_DIGEST_CACHED_RECORDS 293
-# define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC 292
-# define SSL_F_SSL3_ENC 608
-# define SSL_F_SSL3_FINAL_FINISH_MAC 285
-# define SSL_F_SSL3_FINISH_MAC 587
-# define SSL_F_SSL3_GENERATE_KEY_BLOCK 238
-# define SSL_F_SSL3_GENERATE_MASTER_SECRET 388
-# define SSL_F_SSL3_GET_RECORD 143
-# define SSL_F_SSL3_INIT_FINISHED_MAC 397
-# define SSL_F_SSL3_OUTPUT_CERT_CHAIN 147
-# define SSL_F_SSL3_READ_BYTES 148
-# define SSL_F_SSL3_READ_N 149
-# define SSL_F_SSL3_SETUP_KEY_BLOCK 157
-# define SSL_F_SSL3_SETUP_READ_BUFFER 156
-# define SSL_F_SSL3_SETUP_WRITE_BUFFER 291
-# define SSL_F_SSL3_WRITE_BYTES 158
-# define SSL_F_SSL3_WRITE_PENDING 159
-# define SSL_F_SSL_ADD_CERT_CHAIN 316
-# define SSL_F_SSL_ADD_CERT_TO_BUF 319
-# define SSL_F_SSL_ADD_CERT_TO_WPACKET 493
-# define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT 298
-# define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT 277
-# define SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT 307
-# define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK 215
-# define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK 216
-# define SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT 299
-# define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT 278
-# define SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT 308
-# define SSL_F_SSL_BAD_METHOD 160
-# define SSL_F_SSL_BUILD_CERT_CHAIN 332
-# define SSL_F_SSL_BYTES_TO_CIPHER_LIST 161
-# define SSL_F_SSL_CACHE_CIPHERLIST 520
-# define SSL_F_SSL_CERT_ADD0_CHAIN_CERT 346
-# define SSL_F_SSL_CERT_DUP 221
-# define SSL_F_SSL_CERT_NEW 162
-# define SSL_F_SSL_CERT_SET0_CHAIN 340
-# define SSL_F_SSL_CHECK_PRIVATE_KEY 163
-# define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT 280
-# define SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO 606
-# define SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG 279
-# define SSL_F_SSL_CHOOSE_CLIENT_VERSION 607
-# define SSL_F_SSL_CIPHER_DESCRIPTION 626
-# define SSL_F_SSL_CIPHER_LIST_TO_BYTES 425
-# define SSL_F_SSL_CIPHER_PROCESS_RULESTR 230
-# define SSL_F_SSL_CIPHER_STRENGTH_SORT 231
-# define SSL_F_SSL_CLEAR 164
-# define SSL_F_SSL_CLIENT_HELLO_GET1_EXTENSIONS_PRESENT 627
-# define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD 165
-# define SSL_F_SSL_CONF_CMD 334
-# define SSL_F_SSL_CREATE_CIPHER_LIST 166
-# define SSL_F_SSL_CTRL 232
-# define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY 168
-# define SSL_F_SSL_CTX_ENABLE_CT 398
-# define SSL_F_SSL_CTX_MAKE_PROFILES 309
-# define SSL_F_SSL_CTX_NEW 169
-# define SSL_F_SSL_CTX_SET_ALPN_PROTOS 343
-# define SSL_F_SSL_CTX_SET_CIPHER_LIST 269
-# define SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE 290
-# define SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK 396
-# define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT 219
-# define SSL_F_SSL_CTX_SET_SSL_VERSION 170
-# define SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH 551
-# define SSL_F_SSL_CTX_USE_CERTIFICATE 171
-# define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 172
-# define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 173
-# define SSL_F_SSL_CTX_USE_PRIVATEKEY 174
-# define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1 175
-# define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE 176
-# define SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT 272
-# define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY 177
-# define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1 178
-# define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE 179
-# define SSL_F_SSL_CTX_USE_SERVERINFO 336
-# define SSL_F_SSL_CTX_USE_SERVERINFO_EX 543
-# define SSL_F_SSL_CTX_USE_SERVERINFO_FILE 337
-# define SSL_F_SSL_DANE_DUP 403
-# define SSL_F_SSL_DANE_ENABLE 395
-# define SSL_F_SSL_DERIVE 590
-# define SSL_F_SSL_DO_CONFIG 391
-# define SSL_F_SSL_DO_HANDSHAKE 180
-# define SSL_F_SSL_DUP_CA_LIST 408
-# define SSL_F_SSL_ENABLE_CT 402
-# define SSL_F_SSL_GENERATE_PKEY_GROUP 559
-# define SSL_F_SSL_GENERATE_SESSION_ID 547
-# define SSL_F_SSL_GET_NEW_SESSION 181
-# define SSL_F_SSL_GET_PREV_SESSION 217
-# define SSL_F_SSL_GET_SERVER_CERT_INDEX 322
-# define SSL_F_SSL_GET_SIGN_PKEY 183
-# define SSL_F_SSL_HANDSHAKE_HASH 560
-# define SSL_F_SSL_INIT_WBIO_BUFFER 184
-# define SSL_F_SSL_KEY_UPDATE 515
-# define SSL_F_SSL_LOAD_CLIENT_CA_FILE 185
-# define SSL_F_SSL_LOG_MASTER_SECRET 498
-# define SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE 499
-# define SSL_F_SSL_MODULE_INIT 392
-# define SSL_F_SSL_NEW 186
-# define SSL_F_SSL_NEXT_PROTO_VALIDATE 565
-# define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT 300
-# define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT 302
-# define SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT 310
-# define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT 301
-# define SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT 303
-# define SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT 311
-# define SSL_F_SSL_PEEK 270
-# define SSL_F_SSL_PEEK_EX 432
-# define SSL_F_SSL_PEEK_INTERNAL 522
-# define SSL_F_SSL_READ 223
-# define SSL_F_SSL_READ_EARLY_DATA 529
-# define SSL_F_SSL_READ_EX 434
-# define SSL_F_SSL_READ_INTERNAL 523
-# define SSL_F_SSL_RENEGOTIATE 516
-# define SSL_F_SSL_RENEGOTIATE_ABBREVIATED 546
-# define SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT 320
-# define SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT 321
-# define SSL_F_SSL_SESSION_DUP 348
-# define SSL_F_SSL_SESSION_NEW 189
-# define SSL_F_SSL_SESSION_PRINT_FP 190
-# define SSL_F_SSL_SESSION_SET1_ID 423
-# define SSL_F_SSL_SESSION_SET1_ID_CONTEXT 312
-# define SSL_F_SSL_SET_ALPN_PROTOS 344
-# define SSL_F_SSL_SET_CERT 191
-# define SSL_F_SSL_SET_CERT_AND_KEY 621
-# define SSL_F_SSL_SET_CIPHER_LIST 271
-# define SSL_F_SSL_SET_CT_VALIDATION_CALLBACK 399
-# define SSL_F_SSL_SET_FD 192
-# define SSL_F_SSL_SET_PKEY 193
-# define SSL_F_SSL_SET_RFD 194
-# define SSL_F_SSL_SET_SESSION 195
-# define SSL_F_SSL_SET_SESSION_ID_CONTEXT 218
-# define SSL_F_SSL_SET_SESSION_TICKET_EXT 294
-# define SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH 550
-# define SSL_F_SSL_SET_WFD 196
-# define SSL_F_SSL_SHUTDOWN 224
-# define SSL_F_SSL_SRP_CTX_INIT 313
-# define SSL_F_SSL_START_ASYNC_JOB 389
-# define SSL_F_SSL_UNDEFINED_FUNCTION 197
-# define SSL_F_SSL_UNDEFINED_VOID_FUNCTION 244
-# define SSL_F_SSL_USE_CERTIFICATE 198
-# define SSL_F_SSL_USE_CERTIFICATE_ASN1 199
-# define SSL_F_SSL_USE_CERTIFICATE_FILE 200
-# define SSL_F_SSL_USE_PRIVATEKEY 201
-# define SSL_F_SSL_USE_PRIVATEKEY_ASN1 202
-# define SSL_F_SSL_USE_PRIVATEKEY_FILE 203
-# define SSL_F_SSL_USE_PSK_IDENTITY_HINT 273
-# define SSL_F_SSL_USE_RSAPRIVATEKEY 204
-# define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 205
-# define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 206
-# define SSL_F_SSL_VALIDATE_CT 400
-# define SSL_F_SSL_VERIFY_CERT_CHAIN 207
-# define SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE 616
-# define SSL_F_SSL_WRITE 208
-# define SSL_F_SSL_WRITE_EARLY_DATA 526
-# define SSL_F_SSL_WRITE_EARLY_FINISH 527
-# define SSL_F_SSL_WRITE_EX 433
-# define SSL_F_SSL_WRITE_INTERNAL 524
-# define SSL_F_STATE_MACHINE 353
-# define SSL_F_TLS12_CHECK_PEER_SIGALG 333
-# define SSL_F_TLS12_COPY_SIGALGS 533
-# define SSL_F_TLS13_CHANGE_CIPHER_STATE 440
-# define SSL_F_TLS13_ENC 609
-# define SSL_F_TLS13_FINAL_FINISH_MAC 605
-# define SSL_F_TLS13_GENERATE_SECRET 591
-# define SSL_F_TLS13_HKDF_EXPAND 561
-# define SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA 617
-# define SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA 618
-# define SSL_F_TLS13_SETUP_KEY_BLOCK 441
-# define SSL_F_TLS1_CHANGE_CIPHER_STATE 209
-# define SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS 341
-# define SSL_F_TLS1_ENC 401
-# define SSL_F_TLS1_EXPORT_KEYING_MATERIAL 314
-# define SSL_F_TLS1_GET_CURVELIST 338
-# define SSL_F_TLS1_PRF 284
-# define SSL_F_TLS1_SAVE_U16 628
-# define SSL_F_TLS1_SETUP_KEY_BLOCK 211
-# define SSL_F_TLS1_SET_GROUPS 629
-# define SSL_F_TLS1_SET_RAW_SIGALGS 630
-# define SSL_F_TLS1_SET_SERVER_SIGALGS 335
-# define SSL_F_TLS1_SET_SHARED_SIGALGS 631
-# define SSL_F_TLS1_SET_SIGALGS 632
-# define SSL_F_TLS_CHOOSE_SIGALG 513
-# define SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK 354
-# define SSL_F_TLS_COLLECT_EXTENSIONS 435
-# define SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES 542
-# define SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST 372
-# define SSL_F_TLS_CONSTRUCT_CERT_STATUS 429
-# define SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY 494
-# define SSL_F_TLS_CONSTRUCT_CERT_VERIFY 496
-# define SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC 427
-# define SSL_F_TLS_CONSTRUCT_CKE_DHE 404
-# define SSL_F_TLS_CONSTRUCT_CKE_ECDHE 405
-# define SSL_F_TLS_CONSTRUCT_CKE_GOST 406
-# define SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE 407
-# define SSL_F_TLS_CONSTRUCT_CKE_RSA 409
-# define SSL_F_TLS_CONSTRUCT_CKE_SRP 410
-# define SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE 484
-# define SSL_F_TLS_CONSTRUCT_CLIENT_HELLO 487
-# define SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE 488
-# define SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY 489
-# define SSL_F_TLS_CONSTRUCT_CTOS_ALPN 466
-# define SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE 355
-# define SSL_F_TLS_CONSTRUCT_CTOS_COOKIE 535
-# define SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA 530
-# define SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS 467
-# define SSL_F_TLS_CONSTRUCT_CTOS_EMS 468
-# define SSL_F_TLS_CONSTRUCT_CTOS_ETM 469
-# define SSL_F_TLS_CONSTRUCT_CTOS_HELLO 356
-# define SSL_F_TLS_CONSTRUCT_CTOS_KEY_EXCHANGE 357
-# define SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE 470
-# define SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN 549
-# define SSL_F_TLS_CONSTRUCT_CTOS_NPN 471
-# define SSL_F_TLS_CONSTRUCT_CTOS_PADDING 472
-# define SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH 619
-# define SSL_F_TLS_CONSTRUCT_CTOS_PSK 501
-# define SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES 509
-# define SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE 473
-# define SSL_F_TLS_CONSTRUCT_CTOS_SCT 474
-# define SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME 475
-# define SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET 476
-# define SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS 477
-# define SSL_F_TLS_CONSTRUCT_CTOS_SRP 478
-# define SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST 479
-# define SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS 480
-# define SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS 481
-# define SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP 482
-# define SSL_F_TLS_CONSTRUCT_CTOS_VERIFY 358
-# define SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS 443
-# define SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA 536
-# define SSL_F_TLS_CONSTRUCT_EXTENSIONS 447
-# define SSL_F_TLS_CONSTRUCT_FINISHED 359
-# define SSL_F_TLS_CONSTRUCT_HELLO_REQUEST 373
-# define SSL_F_TLS_CONSTRUCT_HELLO_RETRY_REQUEST 510
-# define SSL_F_TLS_CONSTRUCT_KEY_UPDATE 517
-# define SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET 428
-# define SSL_F_TLS_CONSTRUCT_NEXT_PROTO 426
-# define SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE 490
-# define SSL_F_TLS_CONSTRUCT_SERVER_HELLO 491
-# define SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE 492
-# define SSL_F_TLS_CONSTRUCT_STOC_ALPN 451
-# define SSL_F_TLS_CONSTRUCT_STOC_CERTIFICATE 374
-# define SSL_F_TLS_CONSTRUCT_STOC_COOKIE 613
-# define SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG 452
-# define SSL_F_TLS_CONSTRUCT_STOC_DONE 375
-# define SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA 531
-# define SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_INFO 525
-# define SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS 453
-# define SSL_F_TLS_CONSTRUCT_STOC_EMS 454
-# define SSL_F_TLS_CONSTRUCT_STOC_ETM 455
-# define SSL_F_TLS_CONSTRUCT_STOC_HELLO 376
-# define SSL_F_TLS_CONSTRUCT_STOC_KEY_EXCHANGE 377
-# define SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE 456
-# define SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN 548
-# define SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG 457
-# define SSL_F_TLS_CONSTRUCT_STOC_PSK 504
-# define SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE 458
-# define SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME 459
-# define SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET 460
-# define SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST 461
-# define SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS 544
-# define SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS 611
-# define SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP 462
-# define SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO 521
-# define SSL_F_TLS_FINISH_HANDSHAKE 597
-# define SSL_F_TLS_GET_MESSAGE_BODY 351
-# define SSL_F_TLS_GET_MESSAGE_HEADER 387
-# define SSL_F_TLS_HANDLE_ALPN 562
-# define SSL_F_TLS_HANDLE_STATUS_REQUEST 563
-# define SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES 566
-# define SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT 449
-# define SSL_F_TLS_PARSE_CTOS_ALPN 567
-# define SSL_F_TLS_PARSE_CTOS_COOKIE 614
-# define SSL_F_TLS_PARSE_CTOS_EARLY_DATA 568
-# define SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS 569
-# define SSL_F_TLS_PARSE_CTOS_EMS 570
-# define SSL_F_TLS_PARSE_CTOS_KEY_SHARE 463
-# define SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN 571
-# define SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH 620
-# define SSL_F_TLS_PARSE_CTOS_PSK 505
-# define SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES 572
-# define SSL_F_TLS_PARSE_CTOS_RENEGOTIATE 464
-# define SSL_F_TLS_PARSE_CTOS_SERVER_NAME 573
-# define SSL_F_TLS_PARSE_CTOS_SESSION_TICKET 574
-# define SSL_F_TLS_PARSE_CTOS_SIG_ALGS 575
-# define SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT 615
-# define SSL_F_TLS_PARSE_CTOS_SRP 576
-# define SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST 577
-# define SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS 578
-# define SSL_F_TLS_PARSE_CTOS_USE_SRTP 465
-# define SSL_F_TLS_PARSE_STOC_ALPN 579
-# define SSL_F_TLS_PARSE_STOC_COOKIE 534
-# define SSL_F_TLS_PARSE_STOC_EARLY_DATA 538
-# define SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO 528
-# define SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS 580
-# define SSL_F_TLS_PARSE_STOC_KEY_SHARE 445
-# define SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN 581
-# define SSL_F_TLS_PARSE_STOC_NPN 582
-# define SSL_F_TLS_PARSE_STOC_PSK 502
-# define SSL_F_TLS_PARSE_STOC_RENEGOTIATE 448
-# define SSL_F_TLS_PARSE_STOC_SCT 564
-# define SSL_F_TLS_PARSE_STOC_SERVER_NAME 583
-# define SSL_F_TLS_PARSE_STOC_SESSION_TICKET 584
-# define SSL_F_TLS_PARSE_STOC_STATUS_REQUEST 585
-# define SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS 612
-# define SSL_F_TLS_PARSE_STOC_USE_SRTP 446
-# define SSL_F_TLS_POST_PROCESS_CLIENT_HELLO 378
-# define SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE 384
-# define SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE 360
-# define SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST 610
-# define SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST 361
-# define SSL_F_TLS_PROCESS_CERT_STATUS 362
-# define SSL_F_TLS_PROCESS_CERT_STATUS_BODY 495
-# define SSL_F_TLS_PROCESS_CERT_VERIFY 379
-# define SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC 363
-# define SSL_F_TLS_PROCESS_CKE_DHE 411
-# define SSL_F_TLS_PROCESS_CKE_ECDHE 412
-# define SSL_F_TLS_PROCESS_CKE_GOST 413
-# define SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE 414
-# define SSL_F_TLS_PROCESS_CKE_RSA 415
-# define SSL_F_TLS_PROCESS_CKE_SRP 416
-# define SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE 380
-# define SSL_F_TLS_PROCESS_CLIENT_HELLO 381
-# define SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE 382
-# define SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS 444
-# define SSL_F_TLS_PROCESS_END_OF_EARLY_DATA 537
-# define SSL_F_TLS_PROCESS_FINISHED 364
-# define SSL_F_TLS_PROCESS_HELLO_REQ 507
-# define SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST 511
-# define SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT 442
-# define SSL_F_TLS_PROCESS_KEY_EXCHANGE 365
-# define SSL_F_TLS_PROCESS_KEY_UPDATE 518
-# define SSL_F_TLS_PROCESS_NEW_SESSION_TICKET 366
-# define SSL_F_TLS_PROCESS_NEXT_PROTO 383
-# define SSL_F_TLS_PROCESS_SERVER_CERTIFICATE 367
-# define SSL_F_TLS_PROCESS_SERVER_DONE 368
-# define SSL_F_TLS_PROCESS_SERVER_HELLO 369
-# define SSL_F_TLS_PROCESS_SKE_DHE 419
-# define SSL_F_TLS_PROCESS_SKE_ECDHE 420
-# define SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE 421
-# define SSL_F_TLS_PROCESS_SKE_SRP 422
-# define SSL_F_TLS_PSK_DO_BINDER 506
-# define SSL_F_TLS_SCAN_CLIENTHELLO_TLSEXT 450
-# define SSL_F_TLS_SETUP_HANDSHAKE 508
-# define SSL_F_USE_CERTIFICATE_CHAIN_FILE 220
-# define SSL_F_WPACKET_INTERN_INIT_LEN 633
-# define SSL_F_WPACKET_START_SUB_PACKET_LEN__ 634
-# define SSL_F_WRITE_STATE_MACHINE 586
/*
* SSL reason codes.
@@ -458,7 +24,6 @@ int ERR_load_SSL_strings(void);
# define SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY 291
# define SSL_R_APP_DATA_IN_HANDSHAKE 100
# define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
-# define SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE 143
# define SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE 158
# define SSL_R_BAD_CHANGE_CIPHER_SPEC 103
# define SSL_R_BAD_CIPHER 186
@@ -500,6 +65,7 @@ int ERR_load_SSL_strings(void);
# define SSL_R_BN_LIB 130
# define SSL_R_CALLBACK_FAILED 234
# define SSL_R_CANNOT_CHANGE_CIPHER 109
+# define SSL_R_CANNOT_GET_GROUP_NAME 299
# define SSL_R_CA_DN_LENGTH_MISMATCH 131
# define SSL_R_CA_KEY_TOO_SMALL 397
# define SSL_R_CA_MD_TOO_WEAK 398
@@ -509,7 +75,6 @@ int ERR_load_SSL_strings(void);
# define SSL_R_CERT_LENGTH_MISMATCH 135
# define SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED 218
# define SSL_R_CIPHER_CODE_WRONG_LENGTH 137
-# define SSL_R_CIPHER_OR_HASH_UNAVAILABLE 138
# define SSL_R_CLIENTHELLO_TLSEXT 226
# define SSL_R_COMPRESSED_LENGTH_TOO_LONG 140
# define SSL_R_COMPRESSION_DISABLED 343
@@ -520,6 +85,7 @@ int ERR_load_SSL_strings(void);
# define SSL_R_CONTEXT_NOT_DANE_ENABLED 167
# define SSL_R_COOKIE_GEN_CALLBACK_FAILURE 400
# define SSL_R_COOKIE_MISMATCH 308
+# define SSL_R_COPY_PARAMETERS_FAILED 296
# define SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED 206
# define SSL_R_DANE_ALREADY_ENABLED 172
# define SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL 173
@@ -584,6 +150,7 @@ int ERR_load_SSL_strings(void);
# define SSL_R_INVALID_SRP_USERNAME 357
# define SSL_R_INVALID_STATUS_RESPONSE 328
# define SSL_R_INVALID_TICKET_KEYS_LENGTH 325
+# define SSL_R_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED 333
# define SSL_R_LENGTH_MISMATCH 159
# define SSL_R_LENGTH_TOO_LONG 404
# define SSL_R_LENGTH_TOO_SHORT 160
@@ -629,13 +196,15 @@ int ERR_load_SSL_strings(void);
# define SSL_R_NO_SHARED_GROUPS 410
# define SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS 376
# define SSL_R_NO_SRTP_PROFILES 359
+# define SSL_R_NO_SUITABLE_DIGEST_ALGORITHM 297
+# define SSL_R_NO_SUITABLE_GROUPS 295
# define SSL_R_NO_SUITABLE_KEY_SHARE 101
# define SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM 118
# define SSL_R_NO_VALID_SCTS 216
# define SSL_R_NO_VERIFY_COOKIE_CALLBACK 403
# define SSL_R_NULL_SSL_CTX 195
# define SSL_R_NULL_SSL_METHOD_PASSED 196
-# define SSL_R_OCSP_CALLBACK_FAILURE 294
+# define SSL_R_OCSP_CALLBACK_FAILURE 305
# define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197
# define SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED 344
# define SSL_R_OVERFLOW_ERROR 237
@@ -724,8 +293,6 @@ int ERR_load_SSL_strings(void);
# define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE 1111
# define SSL_R_TLSV1_UNRECOGNIZED_NAME 1112
# define SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110
-# define SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT 365
-# define SSL_R_TLS_HEARTBEAT_PENDING 366
# define SSL_R_TLS_ILLEGAL_EXPORTER_LABEL 367
# define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST 157
# define SSL_R_TOO_MANY_KEY_UPDATES 132
@@ -737,6 +304,7 @@ int ERR_load_SSL_strings(void);
# define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 243
# define SSL_R_UNEXPECTED_CCS_MESSAGE 262
# define SSL_R_UNEXPECTED_END_OF_EARLY_DATA 178
+# define SSL_R_UNEXPECTED_EOF_WHILE_READING 294
# define SSL_R_UNEXPECTED_MESSAGE 244
# define SSL_R_UNEXPECTED_RECORD 245
# define SSL_R_UNINITIALIZED 276
diff --git a/include/openssl/sslerr_legacy.h b/include/openssl/sslerr_legacy.h
new file mode 100644
index 000000000000..ccf6d3b30b76
--- /dev/null
+++ b/include/openssl/sslerr_legacy.h
@@ -0,0 +1,468 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This header file preserves symbols from pre-3.0 OpenSSL.
+ * It should never be included directly, as it's already included
+ * by the public sslerr.h headers, and since it will go away some
+ * time in the future.
+ */
+
+#ifndef OPENSSL_SSLERR_LEGACY_H
+# define OPENSSL_SSLERR_LEGACY_H
+# pragma once
+
+# include <openssl/macros.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int ERR_load_SSL_strings(void);
+
+/* Collected _F_ macros from OpenSSL 1.1.1 */
+
+/*
+ * SSL function codes.
+ */
+# define SSL_F_ADD_CLIENT_KEY_SHARE_EXT 0
+# define SSL_F_ADD_KEY_SHARE 0
+# define SSL_F_BYTES_TO_CIPHER_LIST 0
+# define SSL_F_CHECK_SUITEB_CIPHER_LIST 0
+# define SSL_F_CIPHERSUITE_CB 0
+# define SSL_F_CONSTRUCT_CA_NAMES 0
+# define SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS 0
+# define SSL_F_CONSTRUCT_STATEFUL_TICKET 0
+# define SSL_F_CONSTRUCT_STATELESS_TICKET 0
+# define SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH 0
+# define SSL_F_CREATE_TICKET_PREQUEL 0
+# define SSL_F_CT_MOVE_SCTS 0
+# define SSL_F_CT_STRICT 0
+# define SSL_F_CUSTOM_EXT_ADD 0
+# define SSL_F_CUSTOM_EXT_PARSE 0
+# define SSL_F_D2I_SSL_SESSION 0
+# define SSL_F_DANE_CTX_ENABLE 0
+# define SSL_F_DANE_MTYPE_SET 0
+# define SSL_F_DANE_TLSA_ADD 0
+# define SSL_F_DERIVE_SECRET_KEY_AND_IV 0
+# define SSL_F_DO_DTLS1_WRITE 0
+# define SSL_F_DO_SSL3_WRITE 0
+# define SSL_F_DTLS1_BUFFER_RECORD 0
+# define SSL_F_DTLS1_CHECK_TIMEOUT_NUM 0
+# define SSL_F_DTLS1_HEARTBEAT 0
+# define SSL_F_DTLS1_HM_FRAGMENT_NEW 0
+# define SSL_F_DTLS1_PREPROCESS_FRAGMENT 0
+# define SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS 0
+# define SSL_F_DTLS1_PROCESS_RECORD 0
+# define SSL_F_DTLS1_READ_BYTES 0
+# define SSL_F_DTLS1_READ_FAILED 0
+# define SSL_F_DTLS1_RETRANSMIT_MESSAGE 0
+# define SSL_F_DTLS1_WRITE_APP_DATA_BYTES 0
+# define SSL_F_DTLS1_WRITE_BYTES 0
+# define SSL_F_DTLSV1_LISTEN 0
+# define SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC 0
+# define SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST 0
+# define SSL_F_DTLS_GET_REASSEMBLED_MESSAGE 0
+# define SSL_F_DTLS_PROCESS_HELLO_VERIFY 0
+# define SSL_F_DTLS_RECORD_LAYER_NEW 0
+# define SSL_F_DTLS_WAIT_FOR_DRY 0
+# define SSL_F_EARLY_DATA_COUNT_OK 0
+# define SSL_F_FINAL_EARLY_DATA 0
+# define SSL_F_FINAL_EC_PT_FORMATS 0
+# define SSL_F_FINAL_EMS 0
+# define SSL_F_FINAL_KEY_SHARE 0
+# define SSL_F_FINAL_MAXFRAGMENTLEN 0
+# define SSL_F_FINAL_RENEGOTIATE 0
+# define SSL_F_FINAL_SERVER_NAME 0
+# define SSL_F_FINAL_SIG_ALGS 0
+# define SSL_F_GET_CERT_VERIFY_TBS_DATA 0
+# define SSL_F_NSS_KEYLOG_INT 0
+# define SSL_F_OPENSSL_INIT_SSL 0
+# define SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION 0
+# define SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION 0
+# define SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE 0
+# define SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE 0
+# define SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE 0
+# define SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION 0
+# define SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION 0
+# define SSL_F_OSSL_STATEM_SERVER13_READ_TRANSITION 0
+# define SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION 0
+# define SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE 0
+# define SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE 0
+# define SSL_F_OSSL_STATEM_SERVER_POST_WORK 0
+# define SSL_F_OSSL_STATEM_SERVER_PRE_WORK 0
+# define SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE 0
+# define SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION 0
+# define SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION 0
+# define SSL_F_PARSE_CA_NAMES 0
+# define SSL_F_PITEM_NEW 0
+# define SSL_F_PQUEUE_NEW 0
+# define SSL_F_PROCESS_KEY_SHARE_EXT 0
+# define SSL_F_READ_STATE_MACHINE 0
+# define SSL_F_SET_CLIENT_CIPHERSUITE 0
+# define SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET 0
+# define SSL_F_SRP_GENERATE_SERVER_MASTER_SECRET 0
+# define SSL_F_SRP_VERIFY_SERVER_PARAM 0
+# define SSL_F_SSL3_CHANGE_CIPHER_STATE 0
+# define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 0
+# define SSL_F_SSL3_CTRL 0
+# define SSL_F_SSL3_CTX_CTRL 0
+# define SSL_F_SSL3_DIGEST_CACHED_RECORDS 0
+# define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC 0
+# define SSL_F_SSL3_ENC 0
+# define SSL_F_SSL3_FINAL_FINISH_MAC 0
+# define SSL_F_SSL3_FINISH_MAC 0
+# define SSL_F_SSL3_GENERATE_KEY_BLOCK 0
+# define SSL_F_SSL3_GENERATE_MASTER_SECRET 0
+# define SSL_F_SSL3_GET_RECORD 0
+# define SSL_F_SSL3_INIT_FINISHED_MAC 0
+# define SSL_F_SSL3_OUTPUT_CERT_CHAIN 0
+# define SSL_F_SSL3_READ_BYTES 0
+# define SSL_F_SSL3_READ_N 0
+# define SSL_F_SSL3_SETUP_KEY_BLOCK 0
+# define SSL_F_SSL3_SETUP_READ_BUFFER 0
+# define SSL_F_SSL3_SETUP_WRITE_BUFFER 0
+# define SSL_F_SSL3_WRITE_BYTES 0
+# define SSL_F_SSL3_WRITE_PENDING 0
+# define SSL_F_SSL_ADD_CERT_CHAIN 0
+# define SSL_F_SSL_ADD_CERT_TO_BUF 0
+# define SSL_F_SSL_ADD_CERT_TO_WPACKET 0
+# define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT 0
+# define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT 0
+# define SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT 0
+# define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK 0
+# define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK 0
+# define SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT 0
+# define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT 0
+# define SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT 0
+# define SSL_F_SSL_BAD_METHOD 0
+# define SSL_F_SSL_BUILD_CERT_CHAIN 0
+# define SSL_F_SSL_BYTES_TO_CIPHER_LIST 0
+# define SSL_F_SSL_CACHE_CIPHERLIST 0
+# define SSL_F_SSL_CERT_ADD0_CHAIN_CERT 0
+# define SSL_F_SSL_CERT_DUP 0
+# define SSL_F_SSL_CERT_NEW 0
+# define SSL_F_SSL_CERT_SET0_CHAIN 0
+# define SSL_F_SSL_CHECK_PRIVATE_KEY 0
+# define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT 0
+# define SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO 0
+# define SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG 0
+# define SSL_F_SSL_CHOOSE_CLIENT_VERSION 0
+# define SSL_F_SSL_CIPHER_DESCRIPTION 0
+# define SSL_F_SSL_CIPHER_LIST_TO_BYTES 0
+# define SSL_F_SSL_CIPHER_PROCESS_RULESTR 0
+# define SSL_F_SSL_CIPHER_STRENGTH_SORT 0
+# define SSL_F_SSL_CLEAR 0
+# define SSL_F_SSL_CLIENT_HELLO_GET1_EXTENSIONS_PRESENT 0
+# define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD 0
+# define SSL_F_SSL_CONF_CMD 0
+# define SSL_F_SSL_CREATE_CIPHER_LIST 0
+# define SSL_F_SSL_CTRL 0
+# define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY 0
+# define SSL_F_SSL_CTX_ENABLE_CT 0
+# define SSL_F_SSL_CTX_MAKE_PROFILES 0
+# define SSL_F_SSL_CTX_NEW 0
+# define SSL_F_SSL_CTX_SET_ALPN_PROTOS 0
+# define SSL_F_SSL_CTX_SET_CIPHER_LIST 0
+# define SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE 0
+# define SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK 0
+# define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT 0
+# define SSL_F_SSL_CTX_SET_SSL_VERSION 0
+# define SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH 0
+# define SSL_F_SSL_CTX_USE_CERTIFICATE 0
+# define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 0
+# define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 0
+# define SSL_F_SSL_CTX_USE_PRIVATEKEY 0
+# define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1 0
+# define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE 0
+# define SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT 0
+# define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY 0
+# define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1 0
+# define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE 0
+# define SSL_F_SSL_CTX_USE_SERVERINFO 0
+# define SSL_F_SSL_CTX_USE_SERVERINFO_EX 0
+# define SSL_F_SSL_CTX_USE_SERVERINFO_FILE 0
+# define SSL_F_SSL_DANE_DUP 0
+# define SSL_F_SSL_DANE_ENABLE 0
+# define SSL_F_SSL_DERIVE 0
+# define SSL_F_SSL_DO_CONFIG 0
+# define SSL_F_SSL_DO_HANDSHAKE 0
+# define SSL_F_SSL_DUP_CA_LIST 0
+# define SSL_F_SSL_ENABLE_CT 0
+# define SSL_F_SSL_GENERATE_PKEY_GROUP 0
+# define SSL_F_SSL_GENERATE_SESSION_ID 0
+# define SSL_F_SSL_GET_NEW_SESSION 0
+# define SSL_F_SSL_GET_PREV_SESSION 0
+# define SSL_F_SSL_GET_SERVER_CERT_INDEX 0
+# define SSL_F_SSL_GET_SIGN_PKEY 0
+# define SSL_F_SSL_HANDSHAKE_HASH 0
+# define SSL_F_SSL_INIT_WBIO_BUFFER 0
+# define SSL_F_SSL_KEY_UPDATE 0
+# define SSL_F_SSL_LOAD_CLIENT_CA_FILE 0
+# define SSL_F_SSL_LOG_MASTER_SECRET 0
+# define SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE 0
+# define SSL_F_SSL_MODULE_INIT 0
+# define SSL_F_SSL_NEW 0
+# define SSL_F_SSL_NEXT_PROTO_VALIDATE 0
+# define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT 0
+# define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT 0
+# define SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT 0
+# define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT 0
+# define SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT 0
+# define SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT 0
+# define SSL_F_SSL_PEEK 0
+# define SSL_F_SSL_PEEK_EX 0
+# define SSL_F_SSL_PEEK_INTERNAL 0
+# define SSL_F_SSL_READ 0
+# define SSL_F_SSL_READ_EARLY_DATA 0
+# define SSL_F_SSL_READ_EX 0
+# define SSL_F_SSL_READ_INTERNAL 0
+# define SSL_F_SSL_RENEGOTIATE 0
+# define SSL_F_SSL_RENEGOTIATE_ABBREVIATED 0
+# define SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT 0
+# define SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT 0
+# define SSL_F_SSL_SESSION_DUP 0
+# define SSL_F_SSL_SESSION_NEW 0
+# define SSL_F_SSL_SESSION_PRINT_FP 0
+# define SSL_F_SSL_SESSION_SET1_ID 0
+# define SSL_F_SSL_SESSION_SET1_ID_CONTEXT 0
+# define SSL_F_SSL_SET_ALPN_PROTOS 0
+# define SSL_F_SSL_SET_CERT 0
+# define SSL_F_SSL_SET_CERT_AND_KEY 0
+# define SSL_F_SSL_SET_CIPHER_LIST 0
+# define SSL_F_SSL_SET_CT_VALIDATION_CALLBACK 0
+# define SSL_F_SSL_SET_FD 0
+# define SSL_F_SSL_SET_PKEY 0
+# define SSL_F_SSL_SET_RFD 0
+# define SSL_F_SSL_SET_SESSION 0
+# define SSL_F_SSL_SET_SESSION_ID_CONTEXT 0
+# define SSL_F_SSL_SET_SESSION_TICKET_EXT 0
+# define SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH 0
+# define SSL_F_SSL_SET_WFD 0
+# define SSL_F_SSL_SHUTDOWN 0
+# define SSL_F_SSL_SRP_CTX_INIT 0
+# define SSL_F_SSL_START_ASYNC_JOB 0
+# define SSL_F_SSL_UNDEFINED_FUNCTION 0
+# define SSL_F_SSL_UNDEFINED_VOID_FUNCTION 0
+# define SSL_F_SSL_USE_CERTIFICATE 0
+# define SSL_F_SSL_USE_CERTIFICATE_ASN1 0
+# define SSL_F_SSL_USE_CERTIFICATE_FILE 0
+# define SSL_F_SSL_USE_PRIVATEKEY 0
+# define SSL_F_SSL_USE_PRIVATEKEY_ASN1 0
+# define SSL_F_SSL_USE_PRIVATEKEY_FILE 0
+# define SSL_F_SSL_USE_PSK_IDENTITY_HINT 0
+# define SSL_F_SSL_USE_RSAPRIVATEKEY 0
+# define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 0
+# define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 0
+# define SSL_F_SSL_VALIDATE_CT 0
+# define SSL_F_SSL_VERIFY_CERT_CHAIN 0
+# define SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE 0
+# define SSL_F_SSL_WRITE 0
+# define SSL_F_SSL_WRITE_EARLY_DATA 0
+# define SSL_F_SSL_WRITE_EARLY_FINISH 0
+# define SSL_F_SSL_WRITE_EX 0
+# define SSL_F_SSL_WRITE_INTERNAL 0
+# define SSL_F_STATE_MACHINE 0
+# define SSL_F_TLS12_CHECK_PEER_SIGALG 0
+# define SSL_F_TLS12_COPY_SIGALGS 0
+# define SSL_F_TLS13_CHANGE_CIPHER_STATE 0
+# define SSL_F_TLS13_ENC 0
+# define SSL_F_TLS13_FINAL_FINISH_MAC 0
+# define SSL_F_TLS13_GENERATE_SECRET 0
+# define SSL_F_TLS13_HKDF_EXPAND 0
+# define SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA 0
+# define SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA 0
+# define SSL_F_TLS13_SETUP_KEY_BLOCK 0
+# define SSL_F_TLS1_CHANGE_CIPHER_STATE 0
+# define SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS 0
+# define SSL_F_TLS1_ENC 0
+# define SSL_F_TLS1_EXPORT_KEYING_MATERIAL 0
+# define SSL_F_TLS1_GET_CURVELIST 0
+# define SSL_F_TLS1_PRF 0
+# define SSL_F_TLS1_SAVE_U16 0
+# define SSL_F_TLS1_SETUP_KEY_BLOCK 0
+# define SSL_F_TLS1_SET_GROUPS 0
+# define SSL_F_TLS1_SET_RAW_SIGALGS 0
+# define SSL_F_TLS1_SET_SERVER_SIGALGS 0
+# define SSL_F_TLS1_SET_SHARED_SIGALGS 0
+# define SSL_F_TLS1_SET_SIGALGS 0
+# define SSL_F_TLS_CHOOSE_SIGALG 0
+# define SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK 0
+# define SSL_F_TLS_COLLECT_EXTENSIONS 0
+# define SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES 0
+# define SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST 0
+# define SSL_F_TLS_CONSTRUCT_CERT_STATUS 0
+# define SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY 0
+# define SSL_F_TLS_CONSTRUCT_CERT_VERIFY 0
+# define SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC 0
+# define SSL_F_TLS_CONSTRUCT_CKE_DHE 0
+# define SSL_F_TLS_CONSTRUCT_CKE_ECDHE 0
+# define SSL_F_TLS_CONSTRUCT_CKE_GOST 0
+# define SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE 0
+# define SSL_F_TLS_CONSTRUCT_CKE_RSA 0
+# define SSL_F_TLS_CONSTRUCT_CKE_SRP 0
+# define SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE 0
+# define SSL_F_TLS_CONSTRUCT_CLIENT_HELLO 0
+# define SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE 0
+# define SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_ALPN 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_COOKIE 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_EMS 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_ETM 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_HELLO 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_KEY_EXCHANGE 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_NPN 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_PADDING 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_PSK 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_SCT 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_SRP 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP 0
+# define SSL_F_TLS_CONSTRUCT_CTOS_VERIFY 0
+# define SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS 0
+# define SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA 0
+# define SSL_F_TLS_CONSTRUCT_EXTENSIONS 0
+# define SSL_F_TLS_CONSTRUCT_FINISHED 0
+# define SSL_F_TLS_CONSTRUCT_HELLO_REQUEST 0
+# define SSL_F_TLS_CONSTRUCT_HELLO_RETRY_REQUEST 0
+# define SSL_F_TLS_CONSTRUCT_KEY_UPDATE 0
+# define SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET 0
+# define SSL_F_TLS_CONSTRUCT_NEXT_PROTO 0
+# define SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE 0
+# define SSL_F_TLS_CONSTRUCT_SERVER_HELLO 0
+# define SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE 0
+# define SSL_F_TLS_CONSTRUCT_STOC_ALPN 0
+# define SSL_F_TLS_CONSTRUCT_STOC_CERTIFICATE 0
+# define SSL_F_TLS_CONSTRUCT_STOC_COOKIE 0
+# define SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG 0
+# define SSL_F_TLS_CONSTRUCT_STOC_DONE 0
+# define SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA 0
+# define SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_INFO 0
+# define SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS 0
+# define SSL_F_TLS_CONSTRUCT_STOC_EMS 0
+# define SSL_F_TLS_CONSTRUCT_STOC_ETM 0
+# define SSL_F_TLS_CONSTRUCT_STOC_HELLO 0
+# define SSL_F_TLS_CONSTRUCT_STOC_KEY_EXCHANGE 0
+# define SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE 0
+# define SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN 0
+# define SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG 0
+# define SSL_F_TLS_CONSTRUCT_STOC_PSK 0
+# define SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE 0
+# define SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME 0
+# define SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET 0
+# define SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST 0
+# define SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS 0
+# define SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS 0
+# define SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP 0
+# define SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO 0
+# define SSL_F_TLS_FINISH_HANDSHAKE 0
+# define SSL_F_TLS_GET_MESSAGE_BODY 0
+# define SSL_F_TLS_GET_MESSAGE_HEADER 0
+# define SSL_F_TLS_HANDLE_ALPN 0
+# define SSL_F_TLS_HANDLE_STATUS_REQUEST 0
+# define SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES 0
+# define SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT 0
+# define SSL_F_TLS_PARSE_CTOS_ALPN 0
+# define SSL_F_TLS_PARSE_CTOS_COOKIE 0
+# define SSL_F_TLS_PARSE_CTOS_EARLY_DATA 0
+# define SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS 0
+# define SSL_F_TLS_PARSE_CTOS_EMS 0
+# define SSL_F_TLS_PARSE_CTOS_KEY_SHARE 0
+# define SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN 0
+# define SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH 0
+# define SSL_F_TLS_PARSE_CTOS_PSK 0
+# define SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES 0
+# define SSL_F_TLS_PARSE_CTOS_RENEGOTIATE 0
+# define SSL_F_TLS_PARSE_CTOS_SERVER_NAME 0
+# define SSL_F_TLS_PARSE_CTOS_SESSION_TICKET 0
+# define SSL_F_TLS_PARSE_CTOS_SIG_ALGS 0
+# define SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT 0
+# define SSL_F_TLS_PARSE_CTOS_SRP 0
+# define SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST 0
+# define SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS 0
+# define SSL_F_TLS_PARSE_CTOS_USE_SRTP 0
+# define SSL_F_TLS_PARSE_STOC_ALPN 0
+# define SSL_F_TLS_PARSE_STOC_COOKIE 0
+# define SSL_F_TLS_PARSE_STOC_EARLY_DATA 0
+# define SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO 0
+# define SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS 0
+# define SSL_F_TLS_PARSE_STOC_KEY_SHARE 0
+# define SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN 0
+# define SSL_F_TLS_PARSE_STOC_NPN 0
+# define SSL_F_TLS_PARSE_STOC_PSK 0
+# define SSL_F_TLS_PARSE_STOC_RENEGOTIATE 0
+# define SSL_F_TLS_PARSE_STOC_SCT 0
+# define SSL_F_TLS_PARSE_STOC_SERVER_NAME 0
+# define SSL_F_TLS_PARSE_STOC_SESSION_TICKET 0
+# define SSL_F_TLS_PARSE_STOC_STATUS_REQUEST 0
+# define SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS 0
+# define SSL_F_TLS_PARSE_STOC_USE_SRTP 0
+# define SSL_F_TLS_POST_PROCESS_CLIENT_HELLO 0
+# define SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE 0
+# define SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE 0
+# define SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST 0
+# define SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST 0
+# define SSL_F_TLS_PROCESS_CERT_STATUS 0
+# define SSL_F_TLS_PROCESS_CERT_STATUS_BODY 0
+# define SSL_F_TLS_PROCESS_CERT_VERIFY 0
+# define SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC 0
+# define SSL_F_TLS_PROCESS_CKE_DHE 0
+# define SSL_F_TLS_PROCESS_CKE_ECDHE 0
+# define SSL_F_TLS_PROCESS_CKE_GOST 0
+# define SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE 0
+# define SSL_F_TLS_PROCESS_CKE_RSA 0
+# define SSL_F_TLS_PROCESS_CKE_SRP 0
+# define SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE 0
+# define SSL_F_TLS_PROCESS_CLIENT_HELLO 0
+# define SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE 0
+# define SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS 0
+# define SSL_F_TLS_PROCESS_END_OF_EARLY_DATA 0
+# define SSL_F_TLS_PROCESS_FINISHED 0
+# define SSL_F_TLS_PROCESS_HELLO_REQ 0
+# define SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST 0
+# define SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT 0
+# define SSL_F_TLS_PROCESS_KEY_EXCHANGE 0
+# define SSL_F_TLS_PROCESS_KEY_UPDATE 0
+# define SSL_F_TLS_PROCESS_NEW_SESSION_TICKET 0
+# define SSL_F_TLS_PROCESS_NEXT_PROTO 0
+# define SSL_F_TLS_PROCESS_SERVER_CERTIFICATE 0
+# define SSL_F_TLS_PROCESS_SERVER_DONE 0
+# define SSL_F_TLS_PROCESS_SERVER_HELLO 0
+# define SSL_F_TLS_PROCESS_SKE_DHE 0
+# define SSL_F_TLS_PROCESS_SKE_ECDHE 0
+# define SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE 0
+# define SSL_F_TLS_PROCESS_SKE_SRP 0
+# define SSL_F_TLS_PSK_DO_BINDER 0
+# define SSL_F_TLS_SCAN_CLIENTHELLO_TLSEXT 0
+# define SSL_F_TLS_SETUP_HANDSHAKE 0
+# define SSL_F_USE_CERTIFICATE_CHAIN_FILE 0
+# define SSL_F_WPACKET_INTERN_INIT_LEN 0
+# define SSL_F_WPACKET_START_SUB_PACKET_LEN__ 0
+# define SSL_F_WRITE_STATE_MACHINE 0
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/stack.h b/include/openssl/stack.h
index cfc075057ae4..f0c5c54765af 100644
--- a/include/openssl/stack.h
+++ b/include/openssl/stack.h
@@ -1,14 +1,20 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_STACK_H
-# define HEADER_STACK_H
+#ifndef OPENSSL_STACK_H
+# define OPENSSL_STACK_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_STACK_H
+# endif
#ifdef __cplusplus
extern "C" {
@@ -39,6 +45,7 @@ void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc);
void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p);
int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data);
int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data);
+int OPENSSL_sk_find_all(OPENSSL_STACK *st, const void *data, int *pnum);
int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data);
int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data);
void *OPENSSL_sk_shift(OPENSSL_STACK *st);
@@ -50,7 +57,7 @@ OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *st);
void OPENSSL_sk_sort(OPENSSL_STACK *st);
int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st);
-# if OPENSSL_API_COMPAT < 0x10100000L
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
# define _STACK OPENSSL_STACK
# define sk_num OPENSSL_sk_num
# define sk_value OPENSSL_sk_value
diff --git a/include/openssl/store.h b/include/openssl/store.h
index a40a7339e617..3c1445e0e6ac 100644
--- a/include/openssl/store.h
+++ b/include/openssl/store.h
@@ -1,17 +1,23 @@
/*
- * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_OSSL_STORE_H
-# define HEADER_OSSL_STORE_H
+#ifndef OPENSSL_STORE_H
+# define OPENSSL_STORE_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_OSSL_STORE_H
+# endif
# include <stdarg.h>
-# include <openssl/ossl_typ.h>
+# include <openssl/types.h>
# include <openssl/pem.h>
# include <openssl/storeerr.h>
@@ -46,10 +52,16 @@ typedef OSSL_STORE_INFO *(*OSSL_STORE_post_process_info_fn)(OSSL_STORE_INFO *,
* Returns a context reference which represents the channel to communicate
* through.
*/
-OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
- void *ui_data,
- OSSL_STORE_post_process_info_fn post_process,
- void *post_process_data);
+OSSL_STORE_CTX *
+OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method, void *ui_data,
+ OSSL_STORE_post_process_info_fn post_process,
+ void *post_process_data);
+OSSL_STORE_CTX *
+OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq,
+ const UI_METHOD *ui_method, void *ui_data,
+ const OSSL_PARAM params[],
+ OSSL_STORE_post_process_info_fn post_process,
+ void *post_process_data);
/*
* Control / fine tune the OSSL_STORE channel. |cmd| determines what is to be
@@ -57,8 +69,14 @@ OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
* determine which loader is used), except for common commands (see below).
* Each command takes different arguments.
*/
-int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ... /* args */);
-int OSSL_STORE_vctrl(OSSL_STORE_CTX *ctx, int cmd, va_list args);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd,
+ ... /* args */);
+OSSL_DEPRECATEDIN_3_0 int OSSL_STORE_vctrl(OSSL_STORE_CTX *ctx, int cmd,
+ va_list args);
+# endif
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
/*
* Common ctrl commands that different loaders may choose to support.
@@ -68,6 +86,8 @@ int OSSL_STORE_vctrl(OSSL_STORE_CTX *ctx, int cmd, va_list args);
/* Where custom commands start */
# define OSSL_STORE_C_CUSTOM_START 100
+# endif
+
/*
* Read one data item (a key, a cert, a CRL) that is supported by the OSSL_STORE
* functionality, given a context.
@@ -96,6 +116,25 @@ int OSSL_STORE_error(OSSL_STORE_CTX *ctx);
*/
int OSSL_STORE_close(OSSL_STORE_CTX *ctx);
+/*
+ * Attach to a BIO. This works like OSSL_STORE_open() except it takes a
+ * BIO instead of a uri, along with a scheme to use when reading.
+ * The given UI method will be used any time the loader needs extra input,
+ * for example when a password or pin is needed, and will be passed the
+ * same user data every time it's needed in this context.
+ *
+ * Returns a context reference which represents the channel to communicate
+ * through.
+ *
+ * Note that this function is considered unsafe, all depending on what the
+ * BIO actually reads.
+ */
+OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bio, const char *scheme,
+ OSSL_LIB_CTX *libctx, const char *propq,
+ const UI_METHOD *ui_method, void *ui_data,
+ const OSSL_PARAM params[],
+ OSSL_STORE_post_process_info_fn post_process,
+ void *post_process_data);
/*-
* Extracting OpenSSL types from and creating new OSSL_STORE_INFOs
@@ -109,9 +148,10 @@ int OSSL_STORE_close(OSSL_STORE_CTX *ctx);
*/
# define OSSL_STORE_INFO_NAME 1 /* char * */
# define OSSL_STORE_INFO_PARAMS 2 /* EVP_PKEY * */
-# define OSSL_STORE_INFO_PKEY 3 /* EVP_PKEY * */
-# define OSSL_STORE_INFO_CERT 4 /* X509 * */
-# define OSSL_STORE_INFO_CRL 5 /* X509_CRL * */
+# define OSSL_STORE_INFO_PUBKEY 3 /* EVP_PKEY * */
+# define OSSL_STORE_INFO_PKEY 4 /* EVP_PKEY * */
+# define OSSL_STORE_INFO_CERT 5 /* X509 * */
+# define OSSL_STORE_INFO_CRL 6 /* X509_CRL * */
/*
* Functions to generate OSSL_STORE_INFOs, one function for each type we
@@ -120,9 +160,11 @@ int OSSL_STORE_close(OSSL_STORE_CTX *ctx);
* In all cases, ownership of the object is transferred to the OSSL_STORE_INFO
* and will therefore be freed when the OSSL_STORE_INFO is freed.
*/
+OSSL_STORE_INFO *OSSL_STORE_INFO_new(int type, void *data);
OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name);
int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc);
OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params);
+OSSL_STORE_INFO *OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY *pubkey);
OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey);
OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509);
OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl);
@@ -131,12 +173,15 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl);
* Functions to try to extract data from a OSSL_STORE_INFO.
*/
int OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO *info);
+void *OSSL_STORE_INFO_get0_data(int type, const OSSL_STORE_INFO *info);
const char *OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO *info);
char *OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO *info);
const char *OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO *info);
char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *info);
EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *info);
EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info);
+EVP_PKEY *OSSL_STORE_INFO_get0_PUBKEY(const OSSL_STORE_INFO *info);
+EVP_PKEY *OSSL_STORE_INFO_get1_PUBKEY(const OSSL_STORE_INFO *info);
EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *info);
EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info);
X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *info);
@@ -185,7 +230,7 @@ void OSSL_STORE_SEARCH_free(OSSL_STORE_SEARCH *search);
/* Search term accessors */
int OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH *criterion);
-X509_NAME *OSSL_STORE_SEARCH_get0_name(OSSL_STORE_SEARCH *criterion);
+X509_NAME *OSSL_STORE_SEARCH_get0_name(const OSSL_STORE_SEARCH *criterion);
const ASN1_INTEGER *OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH
*criterion);
const unsigned char *OSSL_STORE_SEARCH_get0_bytes(const OSSL_STORE_SEARCH
@@ -198,8 +243,34 @@ const EVP_MD *OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH *criterion);
* to the loading channel. This MUST happen before the first OSSL_STORE_load().
*/
int OSSL_STORE_expect(OSSL_STORE_CTX *ctx, int expected_type);
-int OSSL_STORE_find(OSSL_STORE_CTX *ctx, OSSL_STORE_SEARCH *search);
+int OSSL_STORE_find(OSSL_STORE_CTX *ctx, const OSSL_STORE_SEARCH *search);
+
+/*-
+ * Function to fetch a loader and extract data from it
+ * ---------------------------------------------------
+ */
+
+typedef struct ossl_store_loader_st OSSL_STORE_LOADER;
+
+OSSL_STORE_LOADER *OSSL_STORE_LOADER_fetch(OSSL_LIB_CTX *libctx,
+ const char *scheme,
+ const char *properties);
+int OSSL_STORE_LOADER_up_ref(OSSL_STORE_LOADER *loader);
+void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader);
+const OSSL_PROVIDER *OSSL_STORE_LOADER_get0_provider(const OSSL_STORE_LOADER *
+ loader);
+const char *OSSL_STORE_LOADER_get0_properties(const OSSL_STORE_LOADER *loader);
+const char *OSSL_STORE_LOADER_get0_description(const OSSL_STORE_LOADER *loader);
+int OSSL_STORE_LOADER_is_a(const OSSL_STORE_LOADER *loader,
+ const char *scheme);
+void OSSL_STORE_LOADER_do_all_provided(OSSL_LIB_CTX *libctx,
+ void (*fn)(OSSL_STORE_LOADER *loader,
+ void *arg),
+ void *arg);
+int OSSL_STORE_LOADER_names_do_all(const OSSL_STORE_LOADER *loader,
+ void (*fn)(const char *name, void *data),
+ void *data);
/*-
* Function to register a loader for the given URI scheme.
@@ -209,56 +280,88 @@ int OSSL_STORE_find(OSSL_STORE_CTX *ctx, OSSL_STORE_SEARCH *search);
* scheme.
*/
-typedef struct ossl_store_loader_st OSSL_STORE_LOADER;
-OSSL_STORE_LOADER *OSSL_STORE_LOADER_new(ENGINE *e, const char *scheme);
-const ENGINE *OSSL_STORE_LOADER_get0_engine(const OSSL_STORE_LOADER *loader);
-const char *OSSL_STORE_LOADER_get0_scheme(const OSSL_STORE_LOADER *loader);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+
/* struct ossl_store_loader_ctx_st is defined differently by each loader */
typedef struct ossl_store_loader_ctx_st OSSL_STORE_LOADER_CTX;
-typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_open_fn)(const OSSL_STORE_LOADER
- *loader,
- const char *uri,
- const UI_METHOD *ui_method,
- void *ui_data);
+typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_open_fn)
+ (const OSSL_STORE_LOADER *loader, const char *uri,
+ const UI_METHOD *ui_method, void *ui_data);
+typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_open_ex_fn)
+ (const OSSL_STORE_LOADER *loader,
+ const char *uri, OSSL_LIB_CTX *libctx, const char *propq,
+ const UI_METHOD *ui_method, void *ui_data);
+
+typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_attach_fn)
+ (const OSSL_STORE_LOADER *loader, BIO *bio,
+ OSSL_LIB_CTX *libctx, const char *propq,
+ const UI_METHOD *ui_method, void *ui_data);
+typedef int (*OSSL_STORE_ctrl_fn)
+ (OSSL_STORE_LOADER_CTX *ctx, int cmd, va_list args);
+typedef int (*OSSL_STORE_expect_fn)
+ (OSSL_STORE_LOADER_CTX *ctx, int expected);
+typedef int (*OSSL_STORE_find_fn)
+ (OSSL_STORE_LOADER_CTX *ctx, const OSSL_STORE_SEARCH *criteria);
+typedef OSSL_STORE_INFO *(*OSSL_STORE_load_fn)
+ (OSSL_STORE_LOADER_CTX *ctx, const UI_METHOD *ui_method, void *ui_data);
+typedef int (*OSSL_STORE_eof_fn)(OSSL_STORE_LOADER_CTX *ctx);
+typedef int (*OSSL_STORE_error_fn)(OSSL_STORE_LOADER_CTX *ctx);
+typedef int (*OSSL_STORE_close_fn)(OSSL_STORE_LOADER_CTX *ctx);
+
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
+OSSL_STORE_LOADER *OSSL_STORE_LOADER_new(ENGINE *e, const char *scheme);
+OSSL_DEPRECATEDIN_3_0
int OSSL_STORE_LOADER_set_open(OSSL_STORE_LOADER *loader,
OSSL_STORE_open_fn open_function);
-typedef int (*OSSL_STORE_ctrl_fn)(OSSL_STORE_LOADER_CTX *ctx, int cmd,
- va_list args);
+OSSL_DEPRECATEDIN_3_0
+int OSSL_STORE_LOADER_set_open_ex(OSSL_STORE_LOADER *loader,
+ OSSL_STORE_open_ex_fn open_ex_function);
+OSSL_DEPRECATEDIN_3_0
+int OSSL_STORE_LOADER_set_attach(OSSL_STORE_LOADER *loader,
+ OSSL_STORE_attach_fn attach_function);
+OSSL_DEPRECATEDIN_3_0
int OSSL_STORE_LOADER_set_ctrl(OSSL_STORE_LOADER *loader,
OSSL_STORE_ctrl_fn ctrl_function);
-typedef int (*OSSL_STORE_expect_fn)(OSSL_STORE_LOADER_CTX *ctx, int expected);
+OSSL_DEPRECATEDIN_3_0
int OSSL_STORE_LOADER_set_expect(OSSL_STORE_LOADER *loader,
OSSL_STORE_expect_fn expect_function);
-typedef int (*OSSL_STORE_find_fn)(OSSL_STORE_LOADER_CTX *ctx,
- OSSL_STORE_SEARCH *criteria);
+OSSL_DEPRECATEDIN_3_0
int OSSL_STORE_LOADER_set_find(OSSL_STORE_LOADER *loader,
OSSL_STORE_find_fn find_function);
-typedef OSSL_STORE_INFO *(*OSSL_STORE_load_fn)(OSSL_STORE_LOADER_CTX *ctx,
- const UI_METHOD *ui_method,
- void *ui_data);
+OSSL_DEPRECATEDIN_3_0
int OSSL_STORE_LOADER_set_load(OSSL_STORE_LOADER *loader,
OSSL_STORE_load_fn load_function);
-typedef int (*OSSL_STORE_eof_fn)(OSSL_STORE_LOADER_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0
int OSSL_STORE_LOADER_set_eof(OSSL_STORE_LOADER *loader,
OSSL_STORE_eof_fn eof_function);
-typedef int (*OSSL_STORE_error_fn)(OSSL_STORE_LOADER_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0
int OSSL_STORE_LOADER_set_error(OSSL_STORE_LOADER *loader,
OSSL_STORE_error_fn error_function);
-typedef int (*OSSL_STORE_close_fn)(OSSL_STORE_LOADER_CTX *ctx);
+OSSL_DEPRECATEDIN_3_0
int OSSL_STORE_LOADER_set_close(OSSL_STORE_LOADER *loader,
OSSL_STORE_close_fn close_function);
-void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader);
-
+OSSL_DEPRECATEDIN_3_0
+const ENGINE *OSSL_STORE_LOADER_get0_engine(const OSSL_STORE_LOADER *loader);
+OSSL_DEPRECATEDIN_3_0
+const char * OSSL_STORE_LOADER_get0_scheme(const OSSL_STORE_LOADER *loader);
+OSSL_DEPRECATEDIN_3_0
int OSSL_STORE_register_loader(OSSL_STORE_LOADER *loader);
+OSSL_DEPRECATEDIN_3_0
OSSL_STORE_LOADER *OSSL_STORE_unregister_loader(const char *scheme);
+# endif
/*-
* Functions to list STORE loaders
* -------------------------------
*/
-int OSSL_STORE_do_all_loaders(void (*do_function) (const OSSL_STORE_LOADER
- *loader, void *do_arg),
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
+int OSSL_STORE_do_all_loaders(void (*do_function)(const OSSL_STORE_LOADER *loader,
+ void *do_arg),
void *do_arg);
+# endif
# ifdef __cplusplus
}
diff --git a/include/openssl/storeerr.h b/include/openssl/storeerr.h
index 190eab07fb02..00529c88b59a 100644
--- a/include/openssl/storeerr.h
+++ b/include/openssl/storeerr.h
@@ -1,66 +1,22 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_OSSL_STOREERR_H
-# define HEADER_OSSL_STOREERR_H
+#ifndef OPENSSL_STOREERR_H
+# define OPENSSL_STOREERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_OSSL_STORE_strings(void);
-/*
- * OSSL_STORE function codes.
- */
-# define OSSL_STORE_F_FILE_CTRL 129
-# define OSSL_STORE_F_FILE_FIND 138
-# define OSSL_STORE_F_FILE_GET_PASS 118
-# define OSSL_STORE_F_FILE_LOAD 119
-# define OSSL_STORE_F_FILE_LOAD_TRY_DECODE 124
-# define OSSL_STORE_F_FILE_NAME_TO_URI 126
-# define OSSL_STORE_F_FILE_OPEN 120
-# define OSSL_STORE_F_OSSL_STORE_ATTACH_PEM_BIO 127
-# define OSSL_STORE_F_OSSL_STORE_EXPECT 130
-# define OSSL_STORE_F_OSSL_STORE_FILE_ATTACH_PEM_BIO_INT 128
-# define OSSL_STORE_F_OSSL_STORE_FIND 131
-# define OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT 100
-# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT 101
-# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL 102
-# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME 103
-# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION 135
-# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS 104
-# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY 105
-# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT 106
-# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL 107
-# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED 123
-# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME 109
-# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS 110
-# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY 111
-# define OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION 134
-# define OSSL_STORE_F_OSSL_STORE_INIT_ONCE 112
-# define OSSL_STORE_F_OSSL_STORE_LOADER_NEW 113
-# define OSSL_STORE_F_OSSL_STORE_OPEN 114
-# define OSSL_STORE_F_OSSL_STORE_OPEN_INT 115
-# define OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT 117
-# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ALIAS 132
-# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ISSUER_SERIAL 133
-# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT 136
-# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_NAME 137
-# define OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT 116
-# define OSSL_STORE_F_TRY_DECODE_PARAMS 121
-# define OSSL_STORE_F_TRY_DECODE_PKCS12 122
-# define OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED 125
/*
* OSSL_STORE reason codes.
@@ -75,9 +31,11 @@ int ERR_load_OSSL_STORE_strings(void);
# define OSSL_STORE_R_LOADING_STARTED 117
# define OSSL_STORE_R_NOT_A_CERTIFICATE 100
# define OSSL_STORE_R_NOT_A_CRL 101
-# define OSSL_STORE_R_NOT_A_KEY 102
# define OSSL_STORE_R_NOT_A_NAME 103
+# define OSSL_STORE_R_NOT_A_PRIVATE_KEY 102
+# define OSSL_STORE_R_NOT_A_PUBLIC_KEY 122
# define OSSL_STORE_R_NOT_PARAMETERS 104
+# define OSSL_STORE_R_NO_LOADERS_FOUND 123
# define OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR 114
# define OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE 108
# define OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES 119
diff --git a/include/openssl/symhacks.h b/include/openssl/symhacks.h
index 156ea6e4ee95..816f8f998910 100644
--- a/include/openssl/symhacks.h
+++ b/include/openssl/symhacks.h
@@ -1,14 +1,20 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_SYMHACKS_H
-# define HEADER_SYMHACKS_H
+#ifndef OPENSSL_SYMHACKS_H
+# define OPENSSL_SYMHACKS_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_SYMHACKS_H
+# endif
# include <openssl/e_os2.h>
@@ -28,10 +34,6 @@
# undef i2d_ECPKPARAMETERS
# define i2d_ECPKPARAMETERS i2d_UC_ECPKPARAMETERS
-/* This one clashes with CMS_data_create */
-# undef cms_Data_create
-# define cms_Data_create priv_cms_Data_create
-
# endif
#endif /* ! defined HEADER_VMS_IDHACKS_H */
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index 76d9fda46e20..d6e9331fa1e9 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -1,19 +1,26 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_TLS1_H
-# define HEADER_TLS1_H
+#ifndef OPENSSL_TLS1_H
+# define OPENSSL_TLS1_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_TLS1_H
+# endif
# include <openssl/buffer.h>
# include <openssl/x509.h>
+# include <openssl/prov_ssl.h>
#ifdef __cplusplus
extern "C" {
@@ -24,11 +31,10 @@ extern "C" {
# define OPENSSL_TLS_SECURITY_LEVEL 1
# endif
-# define TLS1_VERSION 0x0301
-# define TLS1_1_VERSION 0x0302
-# define TLS1_2_VERSION 0x0303
-# define TLS1_3_VERSION 0x0304
-# define TLS_MAX_VERSION TLS1_3_VERSION
+/* TLS*_VERSION constants are defined in prov_ssl.h */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define TLS_MAX_VERSION TLS1_3_VERSION
+# endif
/* Special value for method supporting multiple versions */
# define TLS_ANY_VERSION 0x10000
@@ -107,9 +113,6 @@ extern "C" {
/* ExtensionType value from RFC5764 */
# define TLSEXT_TYPE_use_srtp 14
-/* ExtensionType value from RFC5620 */
-# define TLSEXT_TYPE_heartbeat 15
-
/* ExtensionType value from RFC7301 */
# define TLSEXT_TYPE_application_layer_protocol_negotiation 16
@@ -322,38 +325,14 @@ __owur int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain)
# define SSL_CTX_get_tlsext_status_type(ssl) \
SSL_CTX_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE,0,NULL)
-# define SSL_CTX_set_tlsext_ticket_key_cb(ssl, cb) \
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define SSL_CTX_set_tlsext_ticket_key_cb(ssl, cb) \
SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,\
(void (*)(void))cb)
-
-# ifndef OPENSSL_NO_HEARTBEATS
-# define SSL_DTLSEXT_HB_ENABLED 0x01
-# define SSL_DTLSEXT_HB_DONT_SEND_REQUESTS 0x02
-# define SSL_DTLSEXT_HB_DONT_RECV_REQUESTS 0x04
-# define SSL_get_dtlsext_heartbeat_pending(ssl) \
- SSL_ctrl(ssl,SSL_CTRL_GET_DTLS_EXT_HEARTBEAT_PENDING,0,NULL)
-# define SSL_set_dtlsext_heartbeat_no_requests(ssl, arg) \
- SSL_ctrl(ssl,SSL_CTRL_SET_DTLS_EXT_HEARTBEAT_NO_REQUESTS,arg,NULL)
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-# define SSL_CTRL_TLS_EXT_SEND_HEARTBEAT \
- SSL_CTRL_DTLS_EXT_SEND_HEARTBEAT
-# define SSL_CTRL_GET_TLS_EXT_HEARTBEAT_PENDING \
- SSL_CTRL_GET_DTLS_EXT_HEARTBEAT_PENDING
-# define SSL_CTRL_SET_TLS_EXT_HEARTBEAT_NO_REQUESTS \
- SSL_CTRL_SET_DTLS_EXT_HEARTBEAT_NO_REQUESTS
-# define SSL_TLSEXT_HB_ENABLED \
- SSL_DTLSEXT_HB_ENABLED
-# define SSL_TLSEXT_HB_DONT_SEND_REQUESTS \
- SSL_DTLSEXT_HB_DONT_SEND_REQUESTS
-# define SSL_TLSEXT_HB_DONT_RECV_REQUESTS \
- SSL_DTLSEXT_HB_DONT_RECV_REQUESTS
-# define SSL_get_tlsext_heartbeat_pending(ssl) \
- SSL_get_dtlsext_heartbeat_pending(ssl)
-# define SSL_set_tlsext_heartbeat_no_requests(ssl, arg) \
- SSL_set_dtlsext_heartbeat_no_requests(ssl,arg)
-# endif
# endif
+int SSL_CTX_set_tlsext_ticket_key_evp_cb
+ (SSL_CTX *ctx, int (*fp)(SSL *, unsigned char *, unsigned char *,
+ EVP_CIPHER_CTX *, EVP_MAC_CTX *, int));
/* PSK ciphersuites from 4279 */
# define TLS1_CK_PSK_WITH_RC4_128_SHA 0x0300008A
@@ -1135,14 +1114,21 @@ __owur int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain)
# define TLS_CT_RSA_FIXED_ECDH 65
# define TLS_CT_ECDSA_FIXED_ECDH 66
# define TLS_CT_GOST01_SIGN 22
-# define TLS_CT_GOST12_SIGN 238
-# define TLS_CT_GOST12_512_SIGN 239
+# define TLS_CT_GOST12_IANA_SIGN 67
+# define TLS_CT_GOST12_IANA_512_SIGN 68
+# define TLS_CT_GOST12_LEGACY_SIGN 238
+# define TLS_CT_GOST12_LEGACY_512_SIGN 239
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define TLS_CT_GOST12_SIGN TLS_CT_GOST12_LEGACY_SIGN
+# define TLS_CT_GOST12_512_SIGN TLS_CT_GOST12_LEGACY_512_SIGN
+# endif
/*
* when correcting this number, correct also SSL3_CT_NUMBER in ssl3.h (see
* comment there)
*/
-# define TLS_CT_NUMBER 10
+# define TLS_CT_NUMBER 12
# if defined(SSL3_CT_NUMBER)
# if TLS_CT_NUMBER != SSL3_CT_NUMBER
diff --git a/include/openssl/trace.h b/include/openssl/trace.h
new file mode 100644
index 000000000000..ae14f6d9b911
--- /dev/null
+++ b/include/openssl/trace.h
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_TRACE_H
+# define OPENSSL_TRACE_H
+# pragma once
+
+# include <stdarg.h>
+
+# include <openssl/bio.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/*
+ * TRACE CATEGORIES
+ */
+
+/*
+ * The trace messages of the OpenSSL libraries are organized into different
+ * categories. For every trace category, the application can register a separate
+ * tracer callback. When a callback is registered, a so called trace channel is
+ * created for this category. This channel consists essentially of an internal
+ * BIO which sends all trace output it receives to the registered application
+ * callback.
+ *
+ * The ALL category can be used as a fallback category to register a single
+ * channel which receives the output from all categories. However, if the
+ * application intends to print the trace channel name in the line prefix,
+ * it is better to register channels for all categories separately.
+ * (This is how the openssl application does it.)
+ */
+# define OSSL_TRACE_CATEGORY_ALL 0 /* The fallback */
+# define OSSL_TRACE_CATEGORY_TRACE 1
+# define OSSL_TRACE_CATEGORY_INIT 2
+# define OSSL_TRACE_CATEGORY_TLS 3
+# define OSSL_TRACE_CATEGORY_TLS_CIPHER 4
+# define OSSL_TRACE_CATEGORY_CONF 5
+# define OSSL_TRACE_CATEGORY_ENGINE_TABLE 6
+# define OSSL_TRACE_CATEGORY_ENGINE_REF_COUNT 7
+# define OSSL_TRACE_CATEGORY_PKCS5V2 8
+# define OSSL_TRACE_CATEGORY_PKCS12_KEYGEN 9
+# define OSSL_TRACE_CATEGORY_PKCS12_DECRYPT 10
+# define OSSL_TRACE_CATEGORY_X509V3_POLICY 11
+# define OSSL_TRACE_CATEGORY_BN_CTX 12
+# define OSSL_TRACE_CATEGORY_CMP 13
+# define OSSL_TRACE_CATEGORY_STORE 14
+# define OSSL_TRACE_CATEGORY_DECODER 15
+# define OSSL_TRACE_CATEGORY_ENCODER 16
+# define OSSL_TRACE_CATEGORY_REF_COUNT 17
+/* Count of available categories. */
+# define OSSL_TRACE_CATEGORY_NUM 18
+
+/* Returns the trace category number for the given |name| */
+int OSSL_trace_get_category_num(const char *name);
+
+/* Returns the trace category name for the given |num| */
+const char *OSSL_trace_get_category_name(int num);
+
+/*
+ * TRACE CONSUMERS
+ */
+
+/*
+ * Enables tracing for the given |category| by providing a BIO sink
+ * as |channel|. If a null pointer is passed as |channel|, an existing
+ * trace channel is removed and tracing for the category is disabled.
+ *
+ * Returns 1 on success and 0 on failure
+ */
+int OSSL_trace_set_channel(int category, BIO* channel);
+
+/*
+ * Attach a prefix and a suffix to the given |category|, to be printed at the
+ * beginning and at the end of each trace output group, i.e. when
+ * OSSL_trace_begin() and OSSL_trace_end() are called.
+ * If a null pointer is passed as argument, the existing prefix or suffix is
+ * removed.
+ *
+ * They return 1 on success and 0 on failure
+ */
+int OSSL_trace_set_prefix(int category, const char *prefix);
+int OSSL_trace_set_suffix(int category, const char *suffix);
+
+/*
+ * OSSL_trace_cb is the type tracing callback provided by the application.
+ * It MUST return the number of bytes written, or 0 on error (in other words,
+ * it can never write zero bytes).
+ *
+ * The |buffer| will always contain text, which may consist of several lines.
+ * The |data| argument points to whatever data was provided by the application
+ * when registering the tracer function.
+ *
+ * The |category| number is given, as well as a |cmd| number, described below.
+ */
+typedef size_t (*OSSL_trace_cb)(const char *buffer, size_t count,
+ int category, int cmd, void *data);
+/*
+ * Possible |cmd| numbers.
+ */
+# define OSSL_TRACE_CTRL_BEGIN 0
+# define OSSL_TRACE_CTRL_WRITE 1
+# define OSSL_TRACE_CTRL_END 2
+
+/*
+ * Enables tracing for the given |category| by creating an internal
+ * trace channel which sends the output to the given |callback|.
+ * If a null pointer is passed as callback, an existing trace channel
+ * is removed and tracing for the category is disabled.
+ *
+ * NOTE: OSSL_trace_set_channel() and OSSL_trace_set_callback() are mutually
+ * exclusive.
+ *
+ * Returns 1 on success and 0 on failure
+ */
+int OSSL_trace_set_callback(int category, OSSL_trace_cb callback, void *data);
+
+/*
+ * TRACE PRODUCERS
+ */
+
+/*
+ * Returns 1 if tracing for the specified category is enabled, otherwise 0
+ */
+int OSSL_trace_enabled(int category);
+
+/*
+ * Wrap a group of tracing output calls. OSSL_trace_begin() locks tracing and
+ * returns the trace channel associated with the given category, or NULL if no
+ * channel is associated with the category. OSSL_trace_end() unlocks tracing.
+ *
+ * Usage:
+ *
+ * BIO *out;
+ * if ((out = OSSL_trace_begin(category)) != NULL) {
+ * ...
+ * BIO_fprintf(out, ...);
+ * ...
+ * OSSL_trace_end(category, out);
+ * }
+ *
+ * See also the convenience macros OSSL_TRACE_BEGIN and OSSL_TRACE_END below.
+ */
+BIO *OSSL_trace_begin(int category);
+void OSSL_trace_end(int category, BIO *channel);
+
+/*
+ * OSSL_TRACE* Convenience Macros
+ */
+
+/*
+ * When the tracing feature is disabled, these macros are defined to
+ * produce dead code, which a good compiler should eliminate.
+ */
+
+/*
+ * OSSL_TRACE_BEGIN, OSSL_TRACE_END - Define a Trace Group
+ *
+ * These two macros can be used to create a block which is executed only
+ * if the corresponding trace category is enabled. Inside this block, a
+ * local variable named |trc_out| is defined, which points to the channel
+ * associated with the given trace category.
+ *
+ * Usage: (using 'TLS' as an example category)
+ *
+ * OSSL_TRACE_BEGIN(TLS) {
+ *
+ * BIO_fprintf(trc_out, ... );
+ *
+ * } OSSL_TRACE_END(TLS);
+ *
+ *
+ * This expands to the following code
+ *
+ * do {
+ * BIO *trc_out = OSSL_trace_begin(OSSL_TRACE_CATEGORY_TLS);
+ * if (trc_out != NULL) {
+ * ...
+ * BIO_fprintf(trc_out, ...);
+ * }
+ * OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out);
+ * } while (0);
+ *
+ * The use of the inner '{...}' group and the trailing ';' is enforced
+ * by the definition of the macros in order to make the code look as much
+ * like C code as possible.
+ *
+ * Before returning from inside the trace block, it is necessary to
+ * call OSSL_TRACE_CANCEL(category).
+ */
+
+# if !defined OPENSSL_NO_TRACE && !defined FIPS_MODULE
+
+# define OSSL_TRACE_BEGIN(category) \
+ do { \
+ BIO *trc_out = OSSL_trace_begin(OSSL_TRACE_CATEGORY_##category); \
+ \
+ if (trc_out != NULL)
+
+# define OSSL_TRACE_END(category) \
+ OSSL_trace_end(OSSL_TRACE_CATEGORY_##category, trc_out); \
+ } while (0)
+
+# define OSSL_TRACE_CANCEL(category) \
+ OSSL_trace_end(OSSL_TRACE_CATEGORY_##category, trc_out) \
+
+# else
+
+# define OSSL_TRACE_BEGIN(category) \
+ do { \
+ BIO *trc_out = NULL; \
+ if (0)
+
+# define OSSL_TRACE_END(category) \
+ } while(0)
+
+# define OSSL_TRACE_CANCEL(category) \
+ ((void)0)
+
+# endif
+
+/*
+ * OSSL_TRACE_ENABLED() - Check whether tracing is enabled for |category|
+ *
+ * Usage:
+ *
+ * if (OSSL_TRACE_ENABLED(TLS)) {
+ * ...
+ * }
+ */
+# if !defined OPENSSL_NO_TRACE && !defined FIPS_MODULE
+
+# define OSSL_TRACE_ENABLED(category) \
+ OSSL_trace_enabled(OSSL_TRACE_CATEGORY_##category)
+
+# else
+
+# define OSSL_TRACE_ENABLED(category) (0)
+
+# endif
+
+/*
+ * OSSL_TRACE*() - OneShot Trace Macros
+ *
+ * These macros are intended to produce a simple printf-style trace output.
+ * Unfortunately, C90 macros don't support variable arguments, so the
+ * "vararg" OSSL_TRACEV() macro has a rather weird usage pattern:
+ *
+ * OSSL_TRACEV(category, (trc_out, "format string", ...args...));
+ *
+ * Where 'channel' is the literal symbol of this name, not a variable.
+ * For that reason, it is currently not intended to be used directly,
+ * but only as helper macro for the other oneshot trace macros
+ * OSSL_TRACE(), OSSL_TRACE1(), OSSL_TRACE2(), ...
+ *
+ * Usage:
+ *
+ * OSSL_TRACE(INIT, "Hello world!\n");
+ * OSSL_TRACE1(TLS, "The answer is %d\n", 42);
+ * OSSL_TRACE2(TLS, "The ultimate question to answer %d is '%s'\n",
+ * 42, "What do you get when you multiply six by nine?");
+ */
+
+# if !defined OPENSSL_NO_TRACE && !defined FIPS_MODULE
+
+# define OSSL_TRACEV(category, args) \
+ OSSL_TRACE_BEGIN(category) \
+ BIO_printf args; \
+ OSSL_TRACE_END(category)
+
+# else
+
+# define OSSL_TRACEV(category, args) ((void)0)
+
+# endif
+
+# define OSSL_TRACE(category, text) \
+ OSSL_TRACEV(category, (trc_out, "%s", text))
+
+# define OSSL_TRACE1(category, format, arg1) \
+ OSSL_TRACEV(category, (trc_out, format, arg1))
+# define OSSL_TRACE2(category, format, arg1, arg2) \
+ OSSL_TRACEV(category, (trc_out, format, arg1, arg2))
+# define OSSL_TRACE3(category, format, arg1, arg2, arg3) \
+ OSSL_TRACEV(category, (trc_out, format, arg1, arg2, arg3))
+# define OSSL_TRACE4(category, format, arg1, arg2, arg3, arg4) \
+ OSSL_TRACEV(category, (trc_out, format, arg1, arg2, arg3, arg4))
+# define OSSL_TRACE5(category, format, arg1, arg2, arg3, arg4, arg5) \
+ OSSL_TRACEV(category, (trc_out, format, arg1, arg2, arg3, arg4, arg5))
+# define OSSL_TRACE6(category, format, arg1, arg2, arg3, arg4, arg5, arg6) \
+ OSSL_TRACEV(category, (trc_out, format, arg1, arg2, arg3, arg4, arg5, arg6))
+# define OSSL_TRACE7(category, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
+ OSSL_TRACEV(category, (trc_out, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7))
+# define OSSL_TRACE8(category, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
+ OSSL_TRACEV(category, (trc_out, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8))
+# define OSSL_TRACE9(category, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
+ OSSL_TRACEV(category, (trc_out, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9))
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/include/openssl/ts.h b/include/openssl/ts.h
index 3b58aa527ede..5136e4e974af 100644
--- a/include/openssl/ts.h
+++ b/include/openssl/ts.h
@@ -1,14 +1,20 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_TS_H
-# define HEADER_TS_H
+#ifndef OPENSSL_TS_H
+# define OPENSSL_TS_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_TS_H
+# endif
# include <openssl/opensslconf.h>
@@ -23,6 +29,7 @@
# include <openssl/dsa.h>
# include <openssl/dh.h>
# include <openssl/tserr.h>
+# include <openssl/ess.h>
# ifdef __cplusplus
extern "C" {
# endif
@@ -55,126 +62,61 @@ typedef struct TS_tst_info_st TS_TST_INFO;
typedef struct TS_status_info_st TS_STATUS_INFO;
-typedef struct ESS_issuer_serial ESS_ISSUER_SERIAL;
-typedef struct ESS_cert_id ESS_CERT_ID;
-typedef struct ESS_signing_cert ESS_SIGNING_CERT;
-
-DEFINE_STACK_OF(ESS_CERT_ID)
-
-typedef struct ESS_cert_id_v2_st ESS_CERT_ID_V2;
-typedef struct ESS_signing_cert_v2_st ESS_SIGNING_CERT_V2;
-
-DEFINE_STACK_OF(ESS_CERT_ID_V2)
typedef struct TS_resp_st TS_RESP;
-TS_REQ *TS_REQ_new(void);
-void TS_REQ_free(TS_REQ *a);
-int i2d_TS_REQ(const TS_REQ *a, unsigned char **pp);
-TS_REQ *d2i_TS_REQ(TS_REQ **a, const unsigned char **pp, long length);
-
-TS_REQ *TS_REQ_dup(TS_REQ *a);
+DECLARE_ASN1_ALLOC_FUNCTIONS(TS_REQ)
+DECLARE_ASN1_ENCODE_FUNCTIONS_only(TS_REQ, TS_REQ)
+DECLARE_ASN1_DUP_FUNCTION(TS_REQ)
#ifndef OPENSSL_NO_STDIO
TS_REQ *d2i_TS_REQ_fp(FILE *fp, TS_REQ **a);
-int i2d_TS_REQ_fp(FILE *fp, TS_REQ *a);
+int i2d_TS_REQ_fp(FILE *fp, const TS_REQ *a);
#endif
TS_REQ *d2i_TS_REQ_bio(BIO *fp, TS_REQ **a);
-int i2d_TS_REQ_bio(BIO *fp, TS_REQ *a);
-
-TS_MSG_IMPRINT *TS_MSG_IMPRINT_new(void);
-void TS_MSG_IMPRINT_free(TS_MSG_IMPRINT *a);
-int i2d_TS_MSG_IMPRINT(const TS_MSG_IMPRINT *a, unsigned char **pp);
-TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT(TS_MSG_IMPRINT **a,
- const unsigned char **pp, long length);
+int i2d_TS_REQ_bio(BIO *fp, const TS_REQ *a);
-TS_MSG_IMPRINT *TS_MSG_IMPRINT_dup(TS_MSG_IMPRINT *a);
+DECLARE_ASN1_ALLOC_FUNCTIONS(TS_MSG_IMPRINT)
+DECLARE_ASN1_ENCODE_FUNCTIONS_only(TS_MSG_IMPRINT, TS_MSG_IMPRINT)
+DECLARE_ASN1_DUP_FUNCTION(TS_MSG_IMPRINT)
#ifndef OPENSSL_NO_STDIO
TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT **a);
-int i2d_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT *a);
+int i2d_TS_MSG_IMPRINT_fp(FILE *fp, const TS_MSG_IMPRINT *a);
#endif
TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_bio(BIO *bio, TS_MSG_IMPRINT **a);
-int i2d_TS_MSG_IMPRINT_bio(BIO *bio, TS_MSG_IMPRINT *a);
+int i2d_TS_MSG_IMPRINT_bio(BIO *bio, const TS_MSG_IMPRINT *a);
-TS_RESP *TS_RESP_new(void);
-void TS_RESP_free(TS_RESP *a);
-int i2d_TS_RESP(const TS_RESP *a, unsigned char **pp);
-TS_RESP *d2i_TS_RESP(TS_RESP **a, const unsigned char **pp, long length);
-TS_TST_INFO *PKCS7_to_TS_TST_INFO(PKCS7 *token);
-TS_RESP *TS_RESP_dup(TS_RESP *a);
+DECLARE_ASN1_ALLOC_FUNCTIONS(TS_RESP)
+DECLARE_ASN1_ENCODE_FUNCTIONS_only(TS_RESP, TS_RESP)
+DECLARE_ASN1_DUP_FUNCTION(TS_RESP)
#ifndef OPENSSL_NO_STDIO
TS_RESP *d2i_TS_RESP_fp(FILE *fp, TS_RESP **a);
-int i2d_TS_RESP_fp(FILE *fp, TS_RESP *a);
+int i2d_TS_RESP_fp(FILE *fp, const TS_RESP *a);
#endif
TS_RESP *d2i_TS_RESP_bio(BIO *bio, TS_RESP **a);
-int i2d_TS_RESP_bio(BIO *bio, TS_RESP *a);
-
-TS_STATUS_INFO *TS_STATUS_INFO_new(void);
-void TS_STATUS_INFO_free(TS_STATUS_INFO *a);
-int i2d_TS_STATUS_INFO(const TS_STATUS_INFO *a, unsigned char **pp);
-TS_STATUS_INFO *d2i_TS_STATUS_INFO(TS_STATUS_INFO **a,
- const unsigned char **pp, long length);
-TS_STATUS_INFO *TS_STATUS_INFO_dup(TS_STATUS_INFO *a);
-
-TS_TST_INFO *TS_TST_INFO_new(void);
-void TS_TST_INFO_free(TS_TST_INFO *a);
-int i2d_TS_TST_INFO(const TS_TST_INFO *a, unsigned char **pp);
-TS_TST_INFO *d2i_TS_TST_INFO(TS_TST_INFO **a, const unsigned char **pp,
- long length);
-TS_TST_INFO *TS_TST_INFO_dup(TS_TST_INFO *a);
+int i2d_TS_RESP_bio(BIO *bio, const TS_RESP *a);
+
+DECLARE_ASN1_ALLOC_FUNCTIONS(TS_STATUS_INFO)
+DECLARE_ASN1_ENCODE_FUNCTIONS_only(TS_STATUS_INFO, TS_STATUS_INFO)
+DECLARE_ASN1_DUP_FUNCTION(TS_STATUS_INFO)
+
+DECLARE_ASN1_ALLOC_FUNCTIONS(TS_TST_INFO)
+DECLARE_ASN1_ENCODE_FUNCTIONS_only(TS_TST_INFO, TS_TST_INFO)
+DECLARE_ASN1_DUP_FUNCTION(TS_TST_INFO)
+TS_TST_INFO *PKCS7_to_TS_TST_INFO(PKCS7 *token);
#ifndef OPENSSL_NO_STDIO
TS_TST_INFO *d2i_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO **a);
-int i2d_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO *a);
+int i2d_TS_TST_INFO_fp(FILE *fp, const TS_TST_INFO *a);
#endif
TS_TST_INFO *d2i_TS_TST_INFO_bio(BIO *bio, TS_TST_INFO **a);
-int i2d_TS_TST_INFO_bio(BIO *bio, TS_TST_INFO *a);
-
-TS_ACCURACY *TS_ACCURACY_new(void);
-void TS_ACCURACY_free(TS_ACCURACY *a);
-int i2d_TS_ACCURACY(const TS_ACCURACY *a, unsigned char **pp);
-TS_ACCURACY *d2i_TS_ACCURACY(TS_ACCURACY **a, const unsigned char **pp,
- long length);
-TS_ACCURACY *TS_ACCURACY_dup(TS_ACCURACY *a);
-
-ESS_ISSUER_SERIAL *ESS_ISSUER_SERIAL_new(void);
-void ESS_ISSUER_SERIAL_free(ESS_ISSUER_SERIAL *a);
-int i2d_ESS_ISSUER_SERIAL(const ESS_ISSUER_SERIAL *a, unsigned char **pp);
-ESS_ISSUER_SERIAL *d2i_ESS_ISSUER_SERIAL(ESS_ISSUER_SERIAL **a,
- const unsigned char **pp,
- long length);
-ESS_ISSUER_SERIAL *ESS_ISSUER_SERIAL_dup(ESS_ISSUER_SERIAL *a);
-
-ESS_CERT_ID *ESS_CERT_ID_new(void);
-void ESS_CERT_ID_free(ESS_CERT_ID *a);
-int i2d_ESS_CERT_ID(const ESS_CERT_ID *a, unsigned char **pp);
-ESS_CERT_ID *d2i_ESS_CERT_ID(ESS_CERT_ID **a, const unsigned char **pp,
- long length);
-ESS_CERT_ID *ESS_CERT_ID_dup(ESS_CERT_ID *a);
-
-ESS_SIGNING_CERT *ESS_SIGNING_CERT_new(void);
-void ESS_SIGNING_CERT_free(ESS_SIGNING_CERT *a);
-int i2d_ESS_SIGNING_CERT(const ESS_SIGNING_CERT *a, unsigned char **pp);
-ESS_SIGNING_CERT *d2i_ESS_SIGNING_CERT(ESS_SIGNING_CERT **a,
- const unsigned char **pp, long length);
-ESS_SIGNING_CERT *ESS_SIGNING_CERT_dup(ESS_SIGNING_CERT *a);
-
-ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new(void);
-void ESS_CERT_ID_V2_free(ESS_CERT_ID_V2 *a);
-int i2d_ESS_CERT_ID_V2(const ESS_CERT_ID_V2 *a, unsigned char **pp);
-ESS_CERT_ID_V2 *d2i_ESS_CERT_ID_V2(ESS_CERT_ID_V2 **a,
- const unsigned char **pp, long length);
-ESS_CERT_ID_V2 *ESS_CERT_ID_V2_dup(ESS_CERT_ID_V2 *a);
-
-ESS_SIGNING_CERT_V2 *ESS_SIGNING_CERT_V2_new(void);
-void ESS_SIGNING_CERT_V2_free(ESS_SIGNING_CERT_V2 *a);
-int i2d_ESS_SIGNING_CERT_V2(const ESS_SIGNING_CERT_V2 *a, unsigned char **pp);
-ESS_SIGNING_CERT_V2 *d2i_ESS_SIGNING_CERT_V2(ESS_SIGNING_CERT_V2 **a,
- const unsigned char **pp,
- long length);
-ESS_SIGNING_CERT_V2 *ESS_SIGNING_CERT_V2_dup(ESS_SIGNING_CERT_V2 *a);
+int i2d_TS_TST_INFO_bio(BIO *bio, const TS_TST_INFO *a);
+
+DECLARE_ASN1_ALLOC_FUNCTIONS(TS_ACCURACY)
+DECLARE_ASN1_ENCODE_FUNCTIONS_only(TS_ACCURACY, TS_ACCURACY)
+DECLARE_ASN1_DUP_FUNCTION(TS_ACCURACY)
int TS_REQ_set_version(TS_REQ *a, long version);
long TS_REQ_get_version(const TS_REQ *a);
@@ -322,10 +264,9 @@ typedef int (*TS_extension_cb) (struct TS_resp_ctx *, X509_EXTENSION *,
typedef struct TS_resp_ctx TS_RESP_CTX;
-DEFINE_STACK_OF_CONST(EVP_MD)
-
/* Creates a response context that can be used for generating responses. */
TS_RESP_CTX *TS_RESP_CTX_new(void);
+TS_RESP_CTX *TS_RESP_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq);
void TS_RESP_CTX_free(TS_RESP_CTX *ctx);
/* This parameter must be set. */
@@ -479,7 +420,10 @@ BIO *TS_VERIFY_CTX_set_data(TS_VERIFY_CTX *ctx, BIO *b);
unsigned char *TS_VERIFY_CTX_set_imprint(TS_VERIFY_CTX *ctx,
unsigned char *hexstr, long len);
X509_STORE *TS_VERIFY_CTX_set_store(TS_VERIFY_CTX *ctx, X509_STORE *s);
-STACK_OF(X509) *TS_VERIFY_CTS_set_certs(TS_VERIFY_CTX *ctx, STACK_OF(X509) *certs);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define TS_VERIFY_CTS_set_certs(ctx, cert) TS_VERIFY_CTX_set_certs(ctx,cert)
+# endif
+STACK_OF(X509) *TS_VERIFY_CTX_set_certs(TS_VERIFY_CTX *ctx, STACK_OF(X509) *certs);
/*-
* If ctx is NULL, it allocates and returns a new object, otherwise
@@ -543,7 +487,7 @@ int TS_CONF_set_def_policy(CONF *conf, const char *section,
int TS_CONF_set_policies(CONF *conf, const char *section, TS_RESP_CTX *ctx);
int TS_CONF_set_digests(CONF *conf, const char *section, TS_RESP_CTX *ctx);
int TS_CONF_set_accuracy(CONF *conf, const char *section, TS_RESP_CTX *ctx);
-int TS_CONF_set_clock_precision_digits(CONF *conf, const char *section,
+int TS_CONF_set_clock_precision_digits(const CONF *conf, const char *section,
TS_RESP_CTX *ctx);
int TS_CONF_set_ordering(CONF *conf, const char *section, TS_RESP_CTX *ctx);
int TS_CONF_set_tsa_name(CONF *conf, const char *section, TS_RESP_CTX *ctx);
diff --git a/include/openssl/tserr.h b/include/openssl/tserr.h
index 07f23339c81a..e1b943e42dbd 100644
--- a/include/openssl/tserr.h
+++ b/include/openssl/tserr.h
@@ -1,89 +1,24 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_TSERR_H
-# define HEADER_TSERR_H
-
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+#ifndef OPENSSL_TSERR_H
+# define OPENSSL_TSERR_H
+# pragma once
# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifndef OPENSSL_NO_TS
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_TS_strings(void);
+# ifndef OPENSSL_NO_TS
-/*
- * TS function codes.
- */
-# define TS_F_DEF_SERIAL_CB 110
-# define TS_F_DEF_TIME_CB 111
-# define TS_F_ESS_ADD_SIGNING_CERT 112
-# define TS_F_ESS_ADD_SIGNING_CERT_V2 147
-# define TS_F_ESS_CERT_ID_NEW_INIT 113
-# define TS_F_ESS_CERT_ID_V2_NEW_INIT 156
-# define TS_F_ESS_SIGNING_CERT_NEW_INIT 114
-# define TS_F_ESS_SIGNING_CERT_V2_NEW_INIT 157
-# define TS_F_INT_TS_RESP_VERIFY_TOKEN 149
-# define TS_F_PKCS7_TO_TS_TST_INFO 148
-# define TS_F_TS_ACCURACY_SET_MICROS 115
-# define TS_F_TS_ACCURACY_SET_MILLIS 116
-# define TS_F_TS_ACCURACY_SET_SECONDS 117
-# define TS_F_TS_CHECK_IMPRINTS 100
-# define TS_F_TS_CHECK_NONCES 101
-# define TS_F_TS_CHECK_POLICY 102
-# define TS_F_TS_CHECK_SIGNING_CERTS 103
-# define TS_F_TS_CHECK_STATUS_INFO 104
-# define TS_F_TS_COMPUTE_IMPRINT 145
-# define TS_F_TS_CONF_INVALID 151
-# define TS_F_TS_CONF_LOAD_CERT 153
-# define TS_F_TS_CONF_LOAD_CERTS 154
-# define TS_F_TS_CONF_LOAD_KEY 155
-# define TS_F_TS_CONF_LOOKUP_FAIL 152
-# define TS_F_TS_CONF_SET_DEFAULT_ENGINE 146
-# define TS_F_TS_GET_STATUS_TEXT 105
-# define TS_F_TS_MSG_IMPRINT_SET_ALGO 118
-# define TS_F_TS_REQ_SET_MSG_IMPRINT 119
-# define TS_F_TS_REQ_SET_NONCE 120
-# define TS_F_TS_REQ_SET_POLICY_ID 121
-# define TS_F_TS_RESP_CREATE_RESPONSE 122
-# define TS_F_TS_RESP_CREATE_TST_INFO 123
-# define TS_F_TS_RESP_CTX_ADD_FAILURE_INFO 124
-# define TS_F_TS_RESP_CTX_ADD_MD 125
-# define TS_F_TS_RESP_CTX_ADD_POLICY 126
-# define TS_F_TS_RESP_CTX_NEW 127
-# define TS_F_TS_RESP_CTX_SET_ACCURACY 128
-# define TS_F_TS_RESP_CTX_SET_CERTS 129
-# define TS_F_TS_RESP_CTX_SET_DEF_POLICY 130
-# define TS_F_TS_RESP_CTX_SET_SIGNER_CERT 131
-# define TS_F_TS_RESP_CTX_SET_STATUS_INFO 132
-# define TS_F_TS_RESP_GET_POLICY 133
-# define TS_F_TS_RESP_SET_GENTIME_WITH_PRECISION 134
-# define TS_F_TS_RESP_SET_STATUS_INFO 135
-# define TS_F_TS_RESP_SET_TST_INFO 150
-# define TS_F_TS_RESP_SIGN 136
-# define TS_F_TS_RESP_VERIFY_SIGNATURE 106
-# define TS_F_TS_TST_INFO_SET_ACCURACY 137
-# define TS_F_TS_TST_INFO_SET_MSG_IMPRINT 138
-# define TS_F_TS_TST_INFO_SET_NONCE 139
-# define TS_F_TS_TST_INFO_SET_POLICY_ID 140
-# define TS_F_TS_TST_INFO_SET_SERIAL 141
-# define TS_F_TS_TST_INFO_SET_TIME 142
-# define TS_F_TS_TST_INFO_SET_TSA 143
-# define TS_F_TS_VERIFY 108
-# define TS_F_TS_VERIFY_CERT 109
-# define TS_F_TS_VERIFY_CTX_NEW 144
/*
* TS reason codes.
diff --git a/include/openssl/txt_db.h b/include/openssl/txt_db.h
index ec981a439fe8..af169a309ebc 100644
--- a/include/openssl/txt_db.h
+++ b/include/openssl/txt_db.h
@@ -1,14 +1,20 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_TXT_DB_H
-# define HEADER_TXT_DB_H
+#ifndef OPENSSL_TXT_DB_H
+# define OPENSSL_TXT_DB_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_TXT_DB_H
+# endif
# include <openssl/opensslconf.h>
# include <openssl/bio.h>
diff --git a/include/openssl/types.h b/include/openssl/types.h
new file mode 100644
index 000000000000..de9f1665249f
--- /dev/null
+++ b/include/openssl/types.h
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_TYPES_H
+# define OPENSSL_TYPES_H
+# pragma once
+
+# include <limits.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# include <openssl/e_os2.h>
+# include <openssl/safestack.h>
+# include <openssl/macros.h>
+
+typedef struct ossl_provider_st OSSL_PROVIDER; /* Provider Object */
+
+# ifdef NO_ASN1_TYPEDEFS
+# define ASN1_INTEGER ASN1_STRING
+# define ASN1_ENUMERATED ASN1_STRING
+# define ASN1_BIT_STRING ASN1_STRING
+# define ASN1_OCTET_STRING ASN1_STRING
+# define ASN1_PRINTABLESTRING ASN1_STRING
+# define ASN1_T61STRING ASN1_STRING
+# define ASN1_IA5STRING ASN1_STRING
+# define ASN1_UTCTIME ASN1_STRING
+# define ASN1_GENERALIZEDTIME ASN1_STRING
+# define ASN1_TIME ASN1_STRING
+# define ASN1_GENERALSTRING ASN1_STRING
+# define ASN1_UNIVERSALSTRING ASN1_STRING
+# define ASN1_BMPSTRING ASN1_STRING
+# define ASN1_VISIBLESTRING ASN1_STRING
+# define ASN1_UTF8STRING ASN1_STRING
+# define ASN1_BOOLEAN int
+# define ASN1_NULL int
+# else
+typedef struct asn1_string_st ASN1_INTEGER;
+typedef struct asn1_string_st ASN1_ENUMERATED;
+typedef struct asn1_string_st ASN1_BIT_STRING;
+typedef struct asn1_string_st ASN1_OCTET_STRING;
+typedef struct asn1_string_st ASN1_PRINTABLESTRING;
+typedef struct asn1_string_st ASN1_T61STRING;
+typedef struct asn1_string_st ASN1_IA5STRING;
+typedef struct asn1_string_st ASN1_GENERALSTRING;
+typedef struct asn1_string_st ASN1_UNIVERSALSTRING;
+typedef struct asn1_string_st ASN1_BMPSTRING;
+typedef struct asn1_string_st ASN1_UTCTIME;
+typedef struct asn1_string_st ASN1_TIME;
+typedef struct asn1_string_st ASN1_GENERALIZEDTIME;
+typedef struct asn1_string_st ASN1_VISIBLESTRING;
+typedef struct asn1_string_st ASN1_UTF8STRING;
+typedef struct asn1_string_st ASN1_STRING;
+typedef int ASN1_BOOLEAN;
+typedef int ASN1_NULL;
+# endif
+
+typedef struct asn1_type_st ASN1_TYPE;
+typedef struct asn1_object_st ASN1_OBJECT;
+typedef struct asn1_string_table_st ASN1_STRING_TABLE;
+
+typedef struct ASN1_ITEM_st ASN1_ITEM;
+typedef struct asn1_pctx_st ASN1_PCTX;
+typedef struct asn1_sctx_st ASN1_SCTX;
+
+# ifdef _WIN32
+# undef X509_NAME
+# undef X509_EXTENSIONS
+# undef PKCS7_ISSUER_AND_SERIAL
+# undef PKCS7_SIGNER_INFO
+# undef OCSP_REQUEST
+# undef OCSP_RESPONSE
+# endif
+
+# ifdef BIGNUM
+# undef BIGNUM
+# endif
+
+typedef struct bio_st BIO;
+typedef struct bignum_st BIGNUM;
+typedef struct bignum_ctx BN_CTX;
+typedef struct bn_blinding_st BN_BLINDING;
+typedef struct bn_mont_ctx_st BN_MONT_CTX;
+typedef struct bn_recp_ctx_st BN_RECP_CTX;
+typedef struct bn_gencb_st BN_GENCB;
+
+typedef struct buf_mem_st BUF_MEM;
+
+STACK_OF(BIGNUM);
+STACK_OF(BIGNUM_const);
+
+typedef struct err_state_st ERR_STATE;
+
+typedef struct evp_cipher_st EVP_CIPHER;
+typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;
+typedef struct evp_md_st EVP_MD;
+typedef struct evp_md_ctx_st EVP_MD_CTX;
+typedef struct evp_mac_st EVP_MAC;
+typedef struct evp_mac_ctx_st EVP_MAC_CTX;
+typedef struct evp_pkey_st EVP_PKEY;
+
+typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD;
+
+typedef struct evp_pkey_method_st EVP_PKEY_METHOD;
+typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
+
+typedef struct evp_keymgmt_st EVP_KEYMGMT;
+
+typedef struct evp_kdf_st EVP_KDF;
+typedef struct evp_kdf_ctx_st EVP_KDF_CTX;
+
+typedef struct evp_rand_st EVP_RAND;
+typedef struct evp_rand_ctx_st EVP_RAND_CTX;
+
+typedef struct evp_keyexch_st EVP_KEYEXCH;
+
+typedef struct evp_signature_st EVP_SIGNATURE;
+
+typedef struct evp_asym_cipher_st EVP_ASYM_CIPHER;
+
+typedef struct evp_kem_st EVP_KEM;
+
+typedef struct evp_Encode_Ctx_st EVP_ENCODE_CTX;
+
+typedef struct hmac_ctx_st HMAC_CTX;
+
+typedef struct dh_st DH;
+typedef struct dh_method DH_METHOD;
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+typedef struct dsa_st DSA;
+typedef struct dsa_method DSA_METHOD;
+# endif
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+typedef struct rsa_st RSA;
+typedef struct rsa_meth_st RSA_METHOD;
+# endif
+typedef struct rsa_pss_params_st RSA_PSS_PARAMS;
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+typedef struct ec_key_st EC_KEY;
+typedef struct ec_key_method_st EC_KEY_METHOD;
+# endif
+
+typedef struct rand_meth_st RAND_METHOD;
+typedef struct rand_drbg_st RAND_DRBG;
+
+typedef struct ssl_dane_st SSL_DANE;
+typedef struct x509_st X509;
+typedef struct X509_algor_st X509_ALGOR;
+typedef struct X509_crl_st X509_CRL;
+typedef struct x509_crl_method_st X509_CRL_METHOD;
+typedef struct x509_revoked_st X509_REVOKED;
+typedef struct X509_name_st X509_NAME;
+typedef struct X509_pubkey_st X509_PUBKEY;
+typedef struct x509_store_st X509_STORE;
+typedef struct x509_store_ctx_st X509_STORE_CTX;
+
+typedef struct x509_object_st X509_OBJECT;
+typedef struct x509_lookup_st X509_LOOKUP;
+typedef struct x509_lookup_method_st X509_LOOKUP_METHOD;
+typedef struct X509_VERIFY_PARAM_st X509_VERIFY_PARAM;
+
+typedef struct x509_sig_info_st X509_SIG_INFO;
+
+typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO;
+
+typedef struct v3_ext_ctx X509V3_CTX;
+typedef struct conf_st CONF;
+typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS;
+
+typedef struct ui_st UI;
+typedef struct ui_method_st UI_METHOD;
+
+typedef struct engine_st ENGINE;
+typedef struct ssl_st SSL;
+typedef struct ssl_ctx_st SSL_CTX;
+
+typedef struct comp_ctx_st COMP_CTX;
+typedef struct comp_method_st COMP_METHOD;
+
+typedef struct X509_POLICY_NODE_st X509_POLICY_NODE;
+typedef struct X509_POLICY_LEVEL_st X509_POLICY_LEVEL;
+typedef struct X509_POLICY_TREE_st X509_POLICY_TREE;
+typedef struct X509_POLICY_CACHE_st X509_POLICY_CACHE;
+
+typedef struct AUTHORITY_KEYID_st AUTHORITY_KEYID;
+typedef struct DIST_POINT_st DIST_POINT;
+typedef struct ISSUING_DIST_POINT_st ISSUING_DIST_POINT;
+typedef struct NAME_CONSTRAINTS_st NAME_CONSTRAINTS;
+
+typedef struct crypto_ex_data_st CRYPTO_EX_DATA;
+
+typedef struct ossl_http_req_ctx_st OSSL_HTTP_REQ_CTX;
+typedef struct ocsp_response_st OCSP_RESPONSE;
+typedef struct ocsp_responder_id_st OCSP_RESPID;
+
+typedef struct sct_st SCT;
+typedef struct sct_ctx_st SCT_CTX;
+typedef struct ctlog_st CTLOG;
+typedef struct ctlog_store_st CTLOG_STORE;
+typedef struct ct_policy_eval_ctx_st CT_POLICY_EVAL_CTX;
+
+typedef struct ossl_store_info_st OSSL_STORE_INFO;
+typedef struct ossl_store_search_st OSSL_STORE_SEARCH;
+
+typedef struct ossl_lib_ctx_st OSSL_LIB_CTX;
+
+typedef struct ossl_dispatch_st OSSL_DISPATCH;
+typedef struct ossl_item_st OSSL_ITEM;
+typedef struct ossl_algorithm_st OSSL_ALGORITHM;
+typedef struct ossl_param_st OSSL_PARAM;
+typedef struct ossl_param_bld_st OSSL_PARAM_BLD;
+
+typedef int pem_password_cb (char *buf, int size, int rwflag, void *userdata);
+
+typedef struct ossl_encoder_st OSSL_ENCODER;
+typedef struct ossl_encoder_ctx_st OSSL_ENCODER_CTX;
+typedef struct ossl_decoder_st OSSL_DECODER;
+typedef struct ossl_decoder_ctx_st OSSL_DECODER_CTX;
+
+typedef struct ossl_self_test_st OSSL_SELF_TEST;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPENSSL_TYPES_H */
diff --git a/include/openssl/ui.h b/include/openssl/ui.h
deleted file mode 100644
index 7c721ec818dd..000000000000
--- a/include/openssl/ui.h
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_UI_H
-# define HEADER_UI_H
-
-# include <openssl/opensslconf.h>
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-# include <openssl/crypto.h>
-# endif
-# include <openssl/safestack.h>
-# include <openssl/pem.h>
-# include <openssl/ossl_typ.h>
-# include <openssl/uierr.h>
-
-/* For compatibility reasons, the macro OPENSSL_NO_UI is currently retained */
-# if OPENSSL_API_COMPAT < 0x10200000L
-# ifdef OPENSSL_NO_UI_CONSOLE
-# define OPENSSL_NO_UI
-# endif
-# endif
-
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-/*
- * All the following functions return -1 or NULL on error and in some cases
- * (UI_process()) -2 if interrupted or in some other way cancelled. When
- * everything is fine, they return 0, a positive value or a non-NULL pointer,
- * all depending on their purpose.
- */
-
-/* Creators and destructor. */
-UI *UI_new(void);
-UI *UI_new_method(const UI_METHOD *method);
-void UI_free(UI *ui);
-
-/*-
- The following functions are used to add strings to be printed and prompt
- strings to prompt for data. The names are UI_{add,dup}_<function>_string
- and UI_{add,dup}_input_boolean.
-
- UI_{add,dup}_<function>_string have the following meanings:
- add add a text or prompt string. The pointers given to these
- functions are used verbatim, no copying is done.
- dup make a copy of the text or prompt string, then add the copy
- to the collection of strings in the user interface.
- <function>
- The function is a name for the functionality that the given
- string shall be used for. It can be one of:
- input use the string as data prompt.
- verify use the string as verification prompt. This
- is used to verify a previous input.
- info use the string for informational output.
- error use the string for error output.
- Honestly, there's currently no difference between info and error for the
- moment.
-
- UI_{add,dup}_input_boolean have the same semantics for "add" and "dup",
- and are typically used when one wants to prompt for a yes/no response.
-
- All of the functions in this group take a UI and a prompt string.
- The string input and verify addition functions also take a flag argument,
- a buffer for the result to end up with, a minimum input size and a maximum
- input size (the result buffer MUST be large enough to be able to contain
- the maximum number of characters). Additionally, the verify addition
- functions takes another buffer to compare the result against.
- The boolean input functions take an action description string (which should
- be safe to ignore if the expected user action is obvious, for example with
- a dialog box with an OK button and a Cancel button), a string of acceptable
- characters to mean OK and to mean Cancel. The two last strings are checked
- to make sure they don't have common characters. Additionally, the same
- flag argument as for the string input is taken, as well as a result buffer.
- The result buffer is required to be at least one byte long. Depending on
- the answer, the first character from the OK or the Cancel character strings
- will be stored in the first byte of the result buffer. No NUL will be
- added, so the result is *not* a string.
-
- On success, the all return an index of the added information. That index
- is useful when retrieving results with UI_get0_result(). */
-int UI_add_input_string(UI *ui, const char *prompt, int flags,
- char *result_buf, int minsize, int maxsize);
-int UI_dup_input_string(UI *ui, const char *prompt, int flags,
- char *result_buf, int minsize, int maxsize);
-int UI_add_verify_string(UI *ui, const char *prompt, int flags,
- char *result_buf, int minsize, int maxsize,
- const char *test_buf);
-int UI_dup_verify_string(UI *ui, const char *prompt, int flags,
- char *result_buf, int minsize, int maxsize,
- const char *test_buf);
-int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc,
- const char *ok_chars, const char *cancel_chars,
- int flags, char *result_buf);
-int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc,
- const char *ok_chars, const char *cancel_chars,
- int flags, char *result_buf);
-int UI_add_info_string(UI *ui, const char *text);
-int UI_dup_info_string(UI *ui, const char *text);
-int UI_add_error_string(UI *ui, const char *text);
-int UI_dup_error_string(UI *ui, const char *text);
-
-/* These are the possible flags. They can be or'ed together. */
-/* Use to have echoing of input */
-# define UI_INPUT_FLAG_ECHO 0x01
-/*
- * Use a default password. Where that password is found is completely up to
- * the application, it might for example be in the user data set with
- * UI_add_user_data(). It is not recommended to have more than one input in
- * each UI being marked with this flag, or the application might get
- * confused.
- */
-# define UI_INPUT_FLAG_DEFAULT_PWD 0x02
-
-/*-
- * The user of these routines may want to define flags of their own. The core
- * UI won't look at those, but will pass them on to the method routines. They
- * must use higher bits so they don't get confused with the UI bits above.
- * UI_INPUT_FLAG_USER_BASE tells which is the lowest bit to use. A good
- * example of use is this:
- *
- * #define MY_UI_FLAG1 (0x01 << UI_INPUT_FLAG_USER_BASE)
- *
-*/
-# define UI_INPUT_FLAG_USER_BASE 16
-
-/*-
- * The following function helps construct a prompt. object_desc is a
- * textual short description of the object, for example "pass phrase",
- * and object_name is the name of the object (might be a card name or
- * a file name.
- * The returned string shall always be allocated on the heap with
- * OPENSSL_malloc(), and need to be free'd with OPENSSL_free().
- *
- * If the ui_method doesn't contain a pointer to a user-defined prompt
- * constructor, a default string is built, looking like this:
- *
- * "Enter {object_desc} for {object_name}:"
- *
- * So, if object_desc has the value "pass phrase" and object_name has
- * the value "foo.key", the resulting string is:
- *
- * "Enter pass phrase for foo.key:"
-*/
-char *UI_construct_prompt(UI *ui_method,
- const char *object_desc, const char *object_name);
-
-/*
- * The following function is used to store a pointer to user-specific data.
- * Any previous such pointer will be returned and replaced.
- *
- * For callback purposes, this function makes a lot more sense than using
- * ex_data, since the latter requires that different parts of OpenSSL or
- * applications share the same ex_data index.
- *
- * Note that the UI_OpenSSL() method completely ignores the user data. Other
- * methods may not, however.
- */
-void *UI_add_user_data(UI *ui, void *user_data);
-/*
- * Alternatively, this function is used to duplicate the user data.
- * This uses the duplicator method function. The destroy function will
- * be used to free the user data in this case.
- */
-int UI_dup_user_data(UI *ui, void *user_data);
-/* We need a user data retrieving function as well. */
-void *UI_get0_user_data(UI *ui);
-
-/* Return the result associated with a prompt given with the index i. */
-const char *UI_get0_result(UI *ui, int i);
-int UI_get_result_length(UI *ui, int i);
-
-/* When all strings have been added, process the whole thing. */
-int UI_process(UI *ui);
-
-/*
- * Give a user interface parameterised control commands. This can be used to
- * send down an integer, a data pointer or a function pointer, as well as be
- * used to get information from a UI.
- */
-int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void));
-
-/* The commands */
-/*
- * Use UI_CONTROL_PRINT_ERRORS with the value 1 to have UI_process print the
- * OpenSSL error stack before printing any info or added error messages and
- * before any prompting.
- */
-# define UI_CTRL_PRINT_ERRORS 1
-/*
- * Check if a UI_process() is possible to do again with the same instance of
- * a user interface. This makes UI_ctrl() return 1 if it is redoable, and 0
- * if not.
- */
-# define UI_CTRL_IS_REDOABLE 2
-
-/* Some methods may use extra data */
-# define UI_set_app_data(s,arg) UI_set_ex_data(s,0,arg)
-# define UI_get_app_data(s) UI_get_ex_data(s,0)
-
-# define UI_get_ex_new_index(l, p, newf, dupf, freef) \
- CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI, l, p, newf, dupf, freef)
-int UI_set_ex_data(UI *r, int idx, void *arg);
-void *UI_get_ex_data(UI *r, int idx);
-
-/* Use specific methods instead of the built-in one */
-void UI_set_default_method(const UI_METHOD *meth);
-const UI_METHOD *UI_get_default_method(void);
-const UI_METHOD *UI_get_method(UI *ui);
-const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth);
-
-# ifndef OPENSSL_NO_UI_CONSOLE
-
-/* The method with all the built-in thingies */
-UI_METHOD *UI_OpenSSL(void);
-
-# endif
-
-/*
- * NULL method. Literally does nothing, but may serve as a placeholder
- * to avoid internal default.
- */
-const UI_METHOD *UI_null(void);
-
-/* ---------- For method writers ---------- */
-/*-
- A method contains a number of functions that implement the low level
- of the User Interface. The functions are:
-
- an opener This function starts a session, maybe by opening
- a channel to a tty, or by opening a window.
- a writer This function is called to write a given string,
- maybe to the tty, maybe as a field label in a
- window.
- a flusher This function is called to flush everything that
- has been output so far. It can be used to actually
- display a dialog box after it has been built.
- a reader This function is called to read a given prompt,
- maybe from the tty, maybe from a field in a
- window. Note that it's called with all string
- structures, not only the prompt ones, so it must
- check such things itself.
- a closer This function closes the session, maybe by closing
- the channel to the tty, or closing the window.
-
- All these functions are expected to return:
-
- 0 on error.
- 1 on success.
- -1 on out-of-band events, for example if some prompting has
- been canceled (by pressing Ctrl-C, for example). This is
- only checked when returned by the flusher or the reader.
-
- The way this is used, the opener is first called, then the writer for all
- strings, then the flusher, then the reader for all strings and finally the
- closer. Note that if you want to prompt from a terminal or other command
- line interface, the best is to have the reader also write the prompts
- instead of having the writer do it. If you want to prompt from a dialog
- box, the writer can be used to build up the contents of the box, and the
- flusher to actually display the box and run the event loop until all data
- has been given, after which the reader only grabs the given data and puts
- them back into the UI strings.
-
- All method functions take a UI as argument. Additionally, the writer and
- the reader take a UI_STRING.
-*/
-
-/*
- * The UI_STRING type is the data structure that contains all the needed info
- * about a string or a prompt, including test data for a verification prompt.
- */
-typedef struct ui_string_st UI_STRING;
-DEFINE_STACK_OF(UI_STRING)
-
-/*
- * The different types of strings that are currently supported. This is only
- * needed by method authors.
- */
-enum UI_string_types {
- UIT_NONE = 0,
- UIT_PROMPT, /* Prompt for a string */
- UIT_VERIFY, /* Prompt for a string and verify */
- UIT_BOOLEAN, /* Prompt for a yes/no response */
- UIT_INFO, /* Send info to the user */
- UIT_ERROR /* Send an error message to the user */
-};
-
-/* Create and manipulate methods */
-UI_METHOD *UI_create_method(const char *name);
-void UI_destroy_method(UI_METHOD *ui_method);
-int UI_method_set_opener(UI_METHOD *method, int (*opener) (UI *ui));
-int UI_method_set_writer(UI_METHOD *method,
- int (*writer) (UI *ui, UI_STRING *uis));
-int UI_method_set_flusher(UI_METHOD *method, int (*flusher) (UI *ui));
-int UI_method_set_reader(UI_METHOD *method,
- int (*reader) (UI *ui, UI_STRING *uis));
-int UI_method_set_closer(UI_METHOD *method, int (*closer) (UI *ui));
-int UI_method_set_data_duplicator(UI_METHOD *method,
- void *(*duplicator) (UI *ui, void *ui_data),
- void (*destructor)(UI *ui, void *ui_data));
-int UI_method_set_prompt_constructor(UI_METHOD *method,
- char *(*prompt_constructor) (UI *ui,
- const char
- *object_desc,
- const char
- *object_name));
-int UI_method_set_ex_data(UI_METHOD *method, int idx, void *data);
-int (*UI_method_get_opener(const UI_METHOD *method)) (UI *);
-int (*UI_method_get_writer(const UI_METHOD *method)) (UI *, UI_STRING *);
-int (*UI_method_get_flusher(const UI_METHOD *method)) (UI *);
-int (*UI_method_get_reader(const UI_METHOD *method)) (UI *, UI_STRING *);
-int (*UI_method_get_closer(const UI_METHOD *method)) (UI *);
-char *(*UI_method_get_prompt_constructor(const UI_METHOD *method))
- (UI *, const char *, const char *);
-void *(*UI_method_get_data_duplicator(const UI_METHOD *method)) (UI *, void *);
-void (*UI_method_get_data_destructor(const UI_METHOD *method)) (UI *, void *);
-const void *UI_method_get_ex_data(const UI_METHOD *method, int idx);
-
-/*
- * The following functions are helpers for method writers to access relevant
- * data from a UI_STRING.
- */
-
-/* Return type of the UI_STRING */
-enum UI_string_types UI_get_string_type(UI_STRING *uis);
-/* Return input flags of the UI_STRING */
-int UI_get_input_flags(UI_STRING *uis);
-/* Return the actual string to output (the prompt, info or error) */
-const char *UI_get0_output_string(UI_STRING *uis);
-/*
- * Return the optional action string to output (the boolean prompt
- * instruction)
- */
-const char *UI_get0_action_string(UI_STRING *uis);
-/* Return the result of a prompt */
-const char *UI_get0_result_string(UI_STRING *uis);
-int UI_get_result_string_length(UI_STRING *uis);
-/*
- * Return the string to test the result against. Only useful with verifies.
- */
-const char *UI_get0_test_string(UI_STRING *uis);
-/* Return the required minimum size of the result */
-int UI_get_result_minsize(UI_STRING *uis);
-/* Return the required maximum size of the result */
-int UI_get_result_maxsize(UI_STRING *uis);
-/* Set the result of a UI_STRING. */
-int UI_set_result(UI *ui, UI_STRING *uis, const char *result);
-int UI_set_result_ex(UI *ui, UI_STRING *uis, const char *result, int len);
-
-/* A couple of popular utility functions */
-int UI_UTIL_read_pw_string(char *buf, int length, const char *prompt,
- int verify);
-int UI_UTIL_read_pw(char *buf, char *buff, int size, const char *prompt,
- int verify);
-UI_METHOD *UI_UTIL_wrap_read_pem_callback(pem_password_cb *cb, int rwflag);
-
-
-# ifdef __cplusplus
-}
-# endif
-#endif
diff --git a/include/openssl/ui.h.in b/include/openssl/ui.h.in
new file mode 100644
index 000000000000..eb9a580fa8f4
--- /dev/null
+++ b/include/openssl/ui.h.in
@@ -0,0 +1,384 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_UI_H
+# define OPENSSL_UI_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_UI_H
+# endif
+
+# include <openssl/opensslconf.h>
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# include <openssl/crypto.h>
+# endif
+# include <openssl/safestack.h>
+# include <openssl/pem.h>
+# include <openssl/types.h>
+# include <openssl/uierr.h>
+
+/* For compatibility reasons, the macro OPENSSL_NO_UI is currently retained */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifdef OPENSSL_NO_UI_CONSOLE
+# define OPENSSL_NO_UI
+# endif
+# endif
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/*
+ * All the following functions return -1 or NULL on error and in some cases
+ * (UI_process()) -2 if interrupted or in some other way cancelled. When
+ * everything is fine, they return 0, a positive value or a non-NULL pointer,
+ * all depending on their purpose.
+ */
+
+/* Creators and destructor. */
+UI *UI_new(void);
+UI *UI_new_method(const UI_METHOD *method);
+void UI_free(UI *ui);
+
+/*-
+ The following functions are used to add strings to be printed and prompt
+ strings to prompt for data. The names are UI_{add,dup}_<function>_string
+ and UI_{add,dup}_input_boolean.
+
+ UI_{add,dup}_<function>_string have the following meanings:
+ add add a text or prompt string. The pointers given to these
+ functions are used verbatim, no copying is done.
+ dup make a copy of the text or prompt string, then add the copy
+ to the collection of strings in the user interface.
+ <function>
+ The function is a name for the functionality that the given
+ string shall be used for. It can be one of:
+ input use the string as data prompt.
+ verify use the string as verification prompt. This
+ is used to verify a previous input.
+ info use the string for informational output.
+ error use the string for error output.
+ Honestly, there's currently no difference between info and error for the
+ moment.
+
+ UI_{add,dup}_input_boolean have the same semantics for "add" and "dup",
+ and are typically used when one wants to prompt for a yes/no response.
+
+ All of the functions in this group take a UI and a prompt string.
+ The string input and verify addition functions also take a flag argument,
+ a buffer for the result to end up with, a minimum input size and a maximum
+ input size (the result buffer MUST be large enough to be able to contain
+ the maximum number of characters). Additionally, the verify addition
+ functions takes another buffer to compare the result against.
+ The boolean input functions take an action description string (which should
+ be safe to ignore if the expected user action is obvious, for example with
+ a dialog box with an OK button and a Cancel button), a string of acceptable
+ characters to mean OK and to mean Cancel. The two last strings are checked
+ to make sure they don't have common characters. Additionally, the same
+ flag argument as for the string input is taken, as well as a result buffer.
+ The result buffer is required to be at least one byte long. Depending on
+ the answer, the first character from the OK or the Cancel character strings
+ will be stored in the first byte of the result buffer. No NUL will be
+ added, so the result is *not* a string.
+
+ On success, the all return an index of the added information. That index
+ is useful when retrieving results with UI_get0_result(). */
+int UI_add_input_string(UI *ui, const char *prompt, int flags,
+ char *result_buf, int minsize, int maxsize);
+int UI_dup_input_string(UI *ui, const char *prompt, int flags,
+ char *result_buf, int minsize, int maxsize);
+int UI_add_verify_string(UI *ui, const char *prompt, int flags,
+ char *result_buf, int minsize, int maxsize,
+ const char *test_buf);
+int UI_dup_verify_string(UI *ui, const char *prompt, int flags,
+ char *result_buf, int minsize, int maxsize,
+ const char *test_buf);
+int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc,
+ const char *ok_chars, const char *cancel_chars,
+ int flags, char *result_buf);
+int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc,
+ const char *ok_chars, const char *cancel_chars,
+ int flags, char *result_buf);
+int UI_add_info_string(UI *ui, const char *text);
+int UI_dup_info_string(UI *ui, const char *text);
+int UI_add_error_string(UI *ui, const char *text);
+int UI_dup_error_string(UI *ui, const char *text);
+
+/* These are the possible flags. They can be or'ed together. */
+/* Use to have echoing of input */
+# define UI_INPUT_FLAG_ECHO 0x01
+/*
+ * Use a default password. Where that password is found is completely up to
+ * the application, it might for example be in the user data set with
+ * UI_add_user_data(). It is not recommended to have more than one input in
+ * each UI being marked with this flag, or the application might get
+ * confused.
+ */
+# define UI_INPUT_FLAG_DEFAULT_PWD 0x02
+
+/*-
+ * The user of these routines may want to define flags of their own. The core
+ * UI won't look at those, but will pass them on to the method routines. They
+ * must use higher bits so they don't get confused with the UI bits above.
+ * UI_INPUT_FLAG_USER_BASE tells which is the lowest bit to use. A good
+ * example of use is this:
+ *
+ * #define MY_UI_FLAG1 (0x01 << UI_INPUT_FLAG_USER_BASE)
+ *
+*/
+# define UI_INPUT_FLAG_USER_BASE 16
+
+/*-
+ * The following function helps construct a prompt.
+ * phrase_desc is a textual short description of the phrase to enter,
+ * for example "pass phrase", and
+ * object_name is the name of the object
+ * (which might be a card name or a file name) or NULL.
+ * The returned string shall always be allocated on the heap with
+ * OPENSSL_malloc(), and need to be free'd with OPENSSL_free().
+ *
+ * If the ui_method doesn't contain a pointer to a user-defined prompt
+ * constructor, a default string is built, looking like this:
+ *
+ * "Enter {phrase_desc} for {object_name}:"
+ *
+ * So, if phrase_desc has the value "pass phrase" and object_name has
+ * the value "foo.key", the resulting string is:
+ *
+ * "Enter pass phrase for foo.key:"
+*/
+char *UI_construct_prompt(UI *ui_method,
+ const char *phrase_desc, const char *object_name);
+
+/*
+ * The following function is used to store a pointer to user-specific data.
+ * Any previous such pointer will be returned and replaced.
+ *
+ * For callback purposes, this function makes a lot more sense than using
+ * ex_data, since the latter requires that different parts of OpenSSL or
+ * applications share the same ex_data index.
+ *
+ * Note that the UI_OpenSSL() method completely ignores the user data. Other
+ * methods may not, however.
+ */
+void *UI_add_user_data(UI *ui, void *user_data);
+/*
+ * Alternatively, this function is used to duplicate the user data.
+ * This uses the duplicator method function. The destroy function will
+ * be used to free the user data in this case.
+ */
+int UI_dup_user_data(UI *ui, void *user_data);
+/* We need a user data retrieving function as well. */
+void *UI_get0_user_data(UI *ui);
+
+/* Return the result associated with a prompt given with the index i. */
+const char *UI_get0_result(UI *ui, int i);
+int UI_get_result_length(UI *ui, int i);
+
+/* When all strings have been added, process the whole thing. */
+int UI_process(UI *ui);
+
+/*
+ * Give a user interface parameterised control commands. This can be used to
+ * send down an integer, a data pointer or a function pointer, as well as be
+ * used to get information from a UI.
+ */
+int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void));
+
+/* The commands */
+/*
+ * Use UI_CONTROL_PRINT_ERRORS with the value 1 to have UI_process print the
+ * OpenSSL error stack before printing any info or added error messages and
+ * before any prompting.
+ */
+# define UI_CTRL_PRINT_ERRORS 1
+/*
+ * Check if a UI_process() is possible to do again with the same instance of
+ * a user interface. This makes UI_ctrl() return 1 if it is redoable, and 0
+ * if not.
+ */
+# define UI_CTRL_IS_REDOABLE 2
+
+/* Some methods may use extra data */
+# define UI_set_app_data(s,arg) UI_set_ex_data(s,0,arg)
+# define UI_get_app_data(s) UI_get_ex_data(s,0)
+
+# define UI_get_ex_new_index(l, p, newf, dupf, freef) \
+ CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI, l, p, newf, dupf, freef)
+int UI_set_ex_data(UI *r, int idx, void *arg);
+void *UI_get_ex_data(const UI *r, int idx);
+
+/* Use specific methods instead of the built-in one */
+void UI_set_default_method(const UI_METHOD *meth);
+const UI_METHOD *UI_get_default_method(void);
+const UI_METHOD *UI_get_method(UI *ui);
+const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth);
+
+# ifndef OPENSSL_NO_UI_CONSOLE
+
+/* The method with all the built-in thingies */
+UI_METHOD *UI_OpenSSL(void);
+
+# endif
+
+/*
+ * NULL method. Literally does nothing, but may serve as a placeholder
+ * to avoid internal default.
+ */
+const UI_METHOD *UI_null(void);
+
+/* ---------- For method writers ---------- */
+/*-
+ A method contains a number of functions that implement the low level
+ of the User Interface. The functions are:
+
+ an opener This function starts a session, maybe by opening
+ a channel to a tty, or by opening a window.
+ a writer This function is called to write a given string,
+ maybe to the tty, maybe as a field label in a
+ window.
+ a flusher This function is called to flush everything that
+ has been output so far. It can be used to actually
+ display a dialog box after it has been built.
+ a reader This function is called to read a given prompt,
+ maybe from the tty, maybe from a field in a
+ window. Note that it's called with all string
+ structures, not only the prompt ones, so it must
+ check such things itself.
+ a closer This function closes the session, maybe by closing
+ the channel to the tty, or closing the window.
+
+ All these functions are expected to return:
+
+ 0 on error.
+ 1 on success.
+ -1 on out-of-band events, for example if some prompting has
+ been canceled (by pressing Ctrl-C, for example). This is
+ only checked when returned by the flusher or the reader.
+
+ The way this is used, the opener is first called, then the writer for all
+ strings, then the flusher, then the reader for all strings and finally the
+ closer. Note that if you want to prompt from a terminal or other command
+ line interface, the best is to have the reader also write the prompts
+ instead of having the writer do it. If you want to prompt from a dialog
+ box, the writer can be used to build up the contents of the box, and the
+ flusher to actually display the box and run the event loop until all data
+ has been given, after which the reader only grabs the given data and puts
+ them back into the UI strings.
+
+ All method functions take a UI as argument. Additionally, the writer and
+ the reader take a UI_STRING.
+*/
+
+/*
+ * The UI_STRING type is the data structure that contains all the needed info
+ * about a string or a prompt, including test data for a verification prompt.
+ */
+typedef struct ui_string_st UI_STRING;
+
+{-
+ generate_stack_macros("UI_STRING");
+-}
+
+/*
+ * The different types of strings that are currently supported. This is only
+ * needed by method authors.
+ */
+enum UI_string_types {
+ UIT_NONE = 0,
+ UIT_PROMPT, /* Prompt for a string */
+ UIT_VERIFY, /* Prompt for a string and verify */
+ UIT_BOOLEAN, /* Prompt for a yes/no response */
+ UIT_INFO, /* Send info to the user */
+ UIT_ERROR /* Send an error message to the user */
+};
+
+/* Create and manipulate methods */
+UI_METHOD *UI_create_method(const char *name);
+void UI_destroy_method(UI_METHOD *ui_method);
+int UI_method_set_opener(UI_METHOD *method, int (*opener) (UI *ui));
+int UI_method_set_writer(UI_METHOD *method,
+ int (*writer) (UI *ui, UI_STRING *uis));
+int UI_method_set_flusher(UI_METHOD *method, int (*flusher) (UI *ui));
+int UI_method_set_reader(UI_METHOD *method,
+ int (*reader) (UI *ui, UI_STRING *uis));
+int UI_method_set_closer(UI_METHOD *method, int (*closer) (UI *ui));
+int UI_method_set_data_duplicator(UI_METHOD *method,
+ void *(*duplicator) (UI *ui, void *ui_data),
+ void (*destructor)(UI *ui, void *ui_data));
+int UI_method_set_prompt_constructor(UI_METHOD *method,
+ char *(*prompt_constructor) (UI *ui,
+ const char
+ *phrase_desc,
+ const char
+ *object_name));
+int UI_method_set_ex_data(UI_METHOD *method, int idx, void *data);
+int (*UI_method_get_opener(const UI_METHOD *method)) (UI *);
+int (*UI_method_get_writer(const UI_METHOD *method)) (UI *, UI_STRING *);
+int (*UI_method_get_flusher(const UI_METHOD *method)) (UI *);
+int (*UI_method_get_reader(const UI_METHOD *method)) (UI *, UI_STRING *);
+int (*UI_method_get_closer(const UI_METHOD *method)) (UI *);
+char *(*UI_method_get_prompt_constructor(const UI_METHOD *method))
+ (UI *, const char *, const char *);
+void *(*UI_method_get_data_duplicator(const UI_METHOD *method)) (UI *, void *);
+void (*UI_method_get_data_destructor(const UI_METHOD *method)) (UI *, void *);
+const void *UI_method_get_ex_data(const UI_METHOD *method, int idx);
+
+/*
+ * The following functions are helpers for method writers to access relevant
+ * data from a UI_STRING.
+ */
+
+/* Return type of the UI_STRING */
+enum UI_string_types UI_get_string_type(UI_STRING *uis);
+/* Return input flags of the UI_STRING */
+int UI_get_input_flags(UI_STRING *uis);
+/* Return the actual string to output (the prompt, info or error) */
+const char *UI_get0_output_string(UI_STRING *uis);
+/*
+ * Return the optional action string to output (the boolean prompt
+ * instruction)
+ */
+const char *UI_get0_action_string(UI_STRING *uis);
+/* Return the result of a prompt */
+const char *UI_get0_result_string(UI_STRING *uis);
+int UI_get_result_string_length(UI_STRING *uis);
+/*
+ * Return the string to test the result against. Only useful with verifies.
+ */
+const char *UI_get0_test_string(UI_STRING *uis);
+/* Return the required minimum size of the result */
+int UI_get_result_minsize(UI_STRING *uis);
+/* Return the required maximum size of the result */
+int UI_get_result_maxsize(UI_STRING *uis);
+/* Set the result of a UI_STRING. */
+int UI_set_result(UI *ui, UI_STRING *uis, const char *result);
+int UI_set_result_ex(UI *ui, UI_STRING *uis, const char *result, int len);
+
+/* A couple of popular utility functions */
+int UI_UTIL_read_pw_string(char *buf, int length, const char *prompt,
+ int verify);
+int UI_UTIL_read_pw(char *buf, char *buff, int size, const char *prompt,
+ int verify);
+UI_METHOD *UI_UTIL_wrap_read_pem_callback(pem_password_cb *cb, int rwflag);
+
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/uierr.h b/include/openssl/uierr.h
index bd68864d0d84..473b04ed1138 100644
--- a/include/openssl/uierr.h
+++ b/include/openssl/uierr.h
@@ -1,49 +1,22 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_UIERR_H
-# define HEADER_UIERR_H
+#ifndef OPENSSL_UIERR_H
+# define OPENSSL_UIERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_UI_strings(void);
-/*
- * UI function codes.
- */
-# define UI_F_CLOSE_CONSOLE 115
-# define UI_F_ECHO_CONSOLE 116
-# define UI_F_GENERAL_ALLOCATE_BOOLEAN 108
-# define UI_F_GENERAL_ALLOCATE_PROMPT 109
-# define UI_F_NOECHO_CONSOLE 117
-# define UI_F_OPEN_CONSOLE 114
-# define UI_F_UI_CONSTRUCT_PROMPT 121
-# define UI_F_UI_CREATE_METHOD 112
-# define UI_F_UI_CTRL 111
-# define UI_F_UI_DUP_ERROR_STRING 101
-# define UI_F_UI_DUP_INFO_STRING 102
-# define UI_F_UI_DUP_INPUT_BOOLEAN 110
-# define UI_F_UI_DUP_INPUT_STRING 103
-# define UI_F_UI_DUP_USER_DATA 118
-# define UI_F_UI_DUP_VERIFY_STRING 106
-# define UI_F_UI_GET0_RESULT 107
-# define UI_F_UI_GET_RESULT_LENGTH 119
-# define UI_F_UI_NEW_METHOD 104
-# define UI_F_UI_PROCESS 113
-# define UI_F_UI_SET_RESULT 105
-# define UI_F_UI_SET_RESULT_EX 120
/*
* UI reason codes.
diff --git a/include/openssl/whrlpool.h b/include/openssl/whrlpool.h
index 20ea3503b76f..05ba46324626 100644
--- a/include/openssl/whrlpool.h
+++ b/include/openssl/whrlpool.h
@@ -1,27 +1,36 @@
/*
- * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_WHRLPOOL_H
-# define HEADER_WHRLPOOL_H
+#ifndef OPENSSL_WHRLPOOL_H
+# define OPENSSL_WHRLPOOL_H
+# pragma once
-#include <openssl/opensslconf.h>
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_WHRLPOOL_H
+# endif
+
+# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_WHIRLPOOL
-# include <openssl/e_os2.h>
-# include <stddef.h>
-# ifdef __cplusplus
+# include <openssl/e_os2.h>
+# include <stddef.h>
+# ifdef __cplusplus
extern "C" {
-# endif
+# endif
+
+# define WHIRLPOOL_DIGEST_LENGTH (512/8)
-# define WHIRLPOOL_DIGEST_LENGTH (512/8)
-# define WHIRLPOOL_BBLOCK 512
-# define WHIRLPOOL_COUNTER (256/8)
+# if !defined(OPENSSL_NO_DEPRECATED_3_0)
+
+# define WHIRLPOOL_BBLOCK 512
+# define WHIRLPOOL_COUNTER (256/8)
typedef struct {
union {
@@ -33,16 +42,21 @@ typedef struct {
unsigned int bitoff;
size_t bitlen[WHIRLPOOL_COUNTER / sizeof(size_t)];
} WHIRLPOOL_CTX;
-
-int WHIRLPOOL_Init(WHIRLPOOL_CTX *c);
-int WHIRLPOOL_Update(WHIRLPOOL_CTX *c, const void *inp, size_t bytes);
-void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX *c, const void *inp, size_t bits);
-int WHIRLPOOL_Final(unsigned char *md, WHIRLPOOL_CTX *c);
-unsigned char *WHIRLPOOL(const void *inp, size_t bytes, unsigned char *md);
-
-# ifdef __cplusplus
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 int WHIRLPOOL_Init(WHIRLPOOL_CTX *c);
+OSSL_DEPRECATEDIN_3_0 int WHIRLPOOL_Update(WHIRLPOOL_CTX *c,
+ const void *inp, size_t bytes);
+OSSL_DEPRECATEDIN_3_0 void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX *c,
+ const void *inp, size_t bits);
+OSSL_DEPRECATEDIN_3_0 int WHIRLPOOL_Final(unsigned char *md, WHIRLPOOL_CTX *c);
+OSSL_DEPRECATEDIN_3_0 unsigned char *WHIRLPOOL(const void *inp, size_t bytes,
+ unsigned char *md);
+# endif
+
+# ifdef __cplusplus
}
-# endif
+# endif
# endif
#endif
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
deleted file mode 100644
index 3ff86ec7b54d..000000000000
--- a/include/openssl/x509.h
+++ /dev/null
@@ -1,1050 +0,0 @@
-/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_X509_H
-# define HEADER_X509_H
-
-# include <openssl/e_os2.h>
-# include <openssl/ossl_typ.h>
-# include <openssl/symhacks.h>
-# include <openssl/buffer.h>
-# include <openssl/evp.h>
-# include <openssl/bio.h>
-# include <openssl/asn1.h>
-# include <openssl/safestack.h>
-# include <openssl/ec.h>
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-# include <openssl/rsa.h>
-# include <openssl/dsa.h>
-# include <openssl/dh.h>
-# endif
-
-# include <openssl/sha.h>
-# include <openssl/x509err.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* Flags for X509_get_signature_info() */
-/* Signature info is valid */
-# define X509_SIG_INFO_VALID 0x1
-/* Signature is suitable for TLS use */
-# define X509_SIG_INFO_TLS 0x2
-
-# define X509_FILETYPE_PEM 1
-# define X509_FILETYPE_ASN1 2
-# define X509_FILETYPE_DEFAULT 3
-
-# define X509v3_KU_DIGITAL_SIGNATURE 0x0080
-# define X509v3_KU_NON_REPUDIATION 0x0040
-# define X509v3_KU_KEY_ENCIPHERMENT 0x0020
-# define X509v3_KU_DATA_ENCIPHERMENT 0x0010
-# define X509v3_KU_KEY_AGREEMENT 0x0008
-# define X509v3_KU_KEY_CERT_SIGN 0x0004
-# define X509v3_KU_CRL_SIGN 0x0002
-# define X509v3_KU_ENCIPHER_ONLY 0x0001
-# define X509v3_KU_DECIPHER_ONLY 0x8000
-# define X509v3_KU_UNDEF 0xffff
-
-struct X509_algor_st {
- ASN1_OBJECT *algorithm;
- ASN1_TYPE *parameter;
-} /* X509_ALGOR */ ;
-
-typedef STACK_OF(X509_ALGOR) X509_ALGORS;
-
-typedef struct X509_val_st {
- ASN1_TIME *notBefore;
- ASN1_TIME *notAfter;
-} X509_VAL;
-
-typedef struct X509_sig_st X509_SIG;
-
-typedef struct X509_name_entry_st X509_NAME_ENTRY;
-
-DEFINE_STACK_OF(X509_NAME_ENTRY)
-
-DEFINE_STACK_OF(X509_NAME)
-
-# define X509_EX_V_NETSCAPE_HACK 0x8000
-# define X509_EX_V_INIT 0x0001
-typedef struct X509_extension_st X509_EXTENSION;
-
-typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS;
-
-DEFINE_STACK_OF(X509_EXTENSION)
-
-typedef struct x509_attributes_st X509_ATTRIBUTE;
-
-DEFINE_STACK_OF(X509_ATTRIBUTE)
-
-typedef struct X509_req_info_st X509_REQ_INFO;
-
-typedef struct X509_req_st X509_REQ;
-
-typedef struct x509_cert_aux_st X509_CERT_AUX;
-
-typedef struct x509_cinf_st X509_CINF;
-
-DEFINE_STACK_OF(X509)
-
-/* This is used for a table of trust checking functions */
-
-typedef struct x509_trust_st {
- int trust;
- int flags;
- int (*check_trust) (struct x509_trust_st *, X509 *, int);
- char *name;
- int arg1;
- void *arg2;
-} X509_TRUST;
-
-DEFINE_STACK_OF(X509_TRUST)
-
-/* standard trust ids */
-
-# define X509_TRUST_DEFAULT 0 /* Only valid in purpose settings */
-
-# define X509_TRUST_COMPAT 1
-# define X509_TRUST_SSL_CLIENT 2
-# define X509_TRUST_SSL_SERVER 3
-# define X509_TRUST_EMAIL 4
-# define X509_TRUST_OBJECT_SIGN 5
-# define X509_TRUST_OCSP_SIGN 6
-# define X509_TRUST_OCSP_REQUEST 7
-# define X509_TRUST_TSA 8
-
-/* Keep these up to date! */
-# define X509_TRUST_MIN 1
-# define X509_TRUST_MAX 8
-
-/* trust_flags values */
-# define X509_TRUST_DYNAMIC (1U << 0)
-# define X509_TRUST_DYNAMIC_NAME (1U << 1)
-/* No compat trust if self-signed, preempts "DO_SS" */
-# define X509_TRUST_NO_SS_COMPAT (1U << 2)
-/* Compat trust if no explicit accepted trust EKUs */
-# define X509_TRUST_DO_SS_COMPAT (1U << 3)
-/* Accept "anyEKU" as a wildcard trust OID */
-# define X509_TRUST_OK_ANY_EKU (1U << 4)
-
-/* check_trust return codes */
-
-# define X509_TRUST_TRUSTED 1
-# define X509_TRUST_REJECTED 2
-# define X509_TRUST_UNTRUSTED 3
-
-/* Flags for X509_print_ex() */
-
-# define X509_FLAG_COMPAT 0
-# define X509_FLAG_NO_HEADER 1L
-# define X509_FLAG_NO_VERSION (1L << 1)
-# define X509_FLAG_NO_SERIAL (1L << 2)
-# define X509_FLAG_NO_SIGNAME (1L << 3)
-# define X509_FLAG_NO_ISSUER (1L << 4)
-# define X509_FLAG_NO_VALIDITY (1L << 5)
-# define X509_FLAG_NO_SUBJECT (1L << 6)
-# define X509_FLAG_NO_PUBKEY (1L << 7)
-# define X509_FLAG_NO_EXTENSIONS (1L << 8)
-# define X509_FLAG_NO_SIGDUMP (1L << 9)
-# define X509_FLAG_NO_AUX (1L << 10)
-# define X509_FLAG_NO_ATTRIBUTES (1L << 11)
-# define X509_FLAG_NO_IDS (1L << 12)
-
-/* Flags specific to X509_NAME_print_ex() */
-
-/* The field separator information */
-
-# define XN_FLAG_SEP_MASK (0xf << 16)
-
-# define XN_FLAG_COMPAT 0/* Traditional; use old X509_NAME_print */
-# define XN_FLAG_SEP_COMMA_PLUS (1 << 16)/* RFC2253 ,+ */
-# define XN_FLAG_SEP_CPLUS_SPC (2 << 16)/* ,+ spaced: more readable */
-# define XN_FLAG_SEP_SPLUS_SPC (3 << 16)/* ;+ spaced */
-# define XN_FLAG_SEP_MULTILINE (4 << 16)/* One line per field */
-
-# define XN_FLAG_DN_REV (1 << 20)/* Reverse DN order */
-
-/* How the field name is shown */
-
-# define XN_FLAG_FN_MASK (0x3 << 21)
-
-# define XN_FLAG_FN_SN 0/* Object short name */
-# define XN_FLAG_FN_LN (1 << 21)/* Object long name */
-# define XN_FLAG_FN_OID (2 << 21)/* Always use OIDs */
-# define XN_FLAG_FN_NONE (3 << 21)/* No field names */
-
-# define XN_FLAG_SPC_EQ (1 << 23)/* Put spaces round '=' */
-
-/*
- * This determines if we dump fields we don't recognise: RFC2253 requires
- * this.
- */
-
-# define XN_FLAG_DUMP_UNKNOWN_FIELDS (1 << 24)
-
-# define XN_FLAG_FN_ALIGN (1 << 25)/* Align field names to 20
- * characters */
-
-/* Complete set of RFC2253 flags */
-
-# define XN_FLAG_RFC2253 (ASN1_STRFLGS_RFC2253 | \
- XN_FLAG_SEP_COMMA_PLUS | \
- XN_FLAG_DN_REV | \
- XN_FLAG_FN_SN | \
- XN_FLAG_DUMP_UNKNOWN_FIELDS)
-
-/* readable oneline form */
-
-# define XN_FLAG_ONELINE (ASN1_STRFLGS_RFC2253 | \
- ASN1_STRFLGS_ESC_QUOTE | \
- XN_FLAG_SEP_CPLUS_SPC | \
- XN_FLAG_SPC_EQ | \
- XN_FLAG_FN_SN)
-
-/* readable multiline form */
-
-# define XN_FLAG_MULTILINE (ASN1_STRFLGS_ESC_CTRL | \
- ASN1_STRFLGS_ESC_MSB | \
- XN_FLAG_SEP_MULTILINE | \
- XN_FLAG_SPC_EQ | \
- XN_FLAG_FN_LN | \
- XN_FLAG_FN_ALIGN)
-
-DEFINE_STACK_OF(X509_REVOKED)
-
-typedef struct X509_crl_info_st X509_CRL_INFO;
-
-DEFINE_STACK_OF(X509_CRL)
-
-typedef struct private_key_st {
- int version;
- /* The PKCS#8 data types */
- X509_ALGOR *enc_algor;
- ASN1_OCTET_STRING *enc_pkey; /* encrypted pub key */
- /* When decrypted, the following will not be NULL */
- EVP_PKEY *dec_pkey;
- /* used to encrypt and decrypt */
- int key_length;
- char *key_data;
- int key_free; /* true if we should auto free key_data */
- /* expanded version of 'enc_algor' */
- EVP_CIPHER_INFO cipher;
-} X509_PKEY;
-
-typedef struct X509_info_st {
- X509 *x509;
- X509_CRL *crl;
- X509_PKEY *x_pkey;
- EVP_CIPHER_INFO enc_cipher;
- int enc_len;
- char *enc_data;
-} X509_INFO;
-
-DEFINE_STACK_OF(X509_INFO)
-
-/*
- * The next 2 structures and their 8 routines are used to manipulate Netscape's
- * spki structures - useful if you are writing a CA web page
- */
-typedef struct Netscape_spkac_st {
- X509_PUBKEY *pubkey;
- ASN1_IA5STRING *challenge; /* challenge sent in atlas >= PR2 */
-} NETSCAPE_SPKAC;
-
-typedef struct Netscape_spki_st {
- NETSCAPE_SPKAC *spkac; /* signed public key and challenge */
- X509_ALGOR sig_algor;
- ASN1_BIT_STRING *signature;
-} NETSCAPE_SPKI;
-
-/* Netscape certificate sequence structure */
-typedef struct Netscape_certificate_sequence {
- ASN1_OBJECT *type;
- STACK_OF(X509) *certs;
-} NETSCAPE_CERT_SEQUENCE;
-
-/*- Unused (and iv length is wrong)
-typedef struct CBCParameter_st
- {
- unsigned char iv[8];
- } CBC_PARAM;
-*/
-
-/* Password based encryption structure */
-
-typedef struct PBEPARAM_st {
- ASN1_OCTET_STRING *salt;
- ASN1_INTEGER *iter;
-} PBEPARAM;
-
-/* Password based encryption V2 structures */
-
-typedef struct PBE2PARAM_st {
- X509_ALGOR *keyfunc;
- X509_ALGOR *encryption;
-} PBE2PARAM;
-
-typedef struct PBKDF2PARAM_st {
-/* Usually OCTET STRING but could be anything */
- ASN1_TYPE *salt;
- ASN1_INTEGER *iter;
- ASN1_INTEGER *keylength;
- X509_ALGOR *prf;
-} PBKDF2PARAM;
-
-#ifndef OPENSSL_NO_SCRYPT
-typedef struct SCRYPT_PARAMS_st {
- ASN1_OCTET_STRING *salt;
- ASN1_INTEGER *costParameter;
- ASN1_INTEGER *blockSize;
- ASN1_INTEGER *parallelizationParameter;
- ASN1_INTEGER *keyLength;
-} SCRYPT_PARAMS;
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-# include <openssl/x509_vfy.h>
-# include <openssl/pkcs7.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-# define X509_EXT_PACK_UNKNOWN 1
-# define X509_EXT_PACK_STRING 2
-
-# define X509_extract_key(x) X509_get_pubkey(x)/*****/
-# define X509_REQ_extract_key(a) X509_REQ_get_pubkey(a)
-# define X509_name_cmp(a,b) X509_NAME_cmp((a),(b))
-
-void X509_CRL_set_default_method(const X509_CRL_METHOD *meth);
-X509_CRL_METHOD *X509_CRL_METHOD_new(int (*crl_init) (X509_CRL *crl),
- int (*crl_free) (X509_CRL *crl),
- int (*crl_lookup) (X509_CRL *crl,
- X509_REVOKED **ret,
- ASN1_INTEGER *ser,
- X509_NAME *issuer),
- int (*crl_verify) (X509_CRL *crl,
- EVP_PKEY *pk));
-void X509_CRL_METHOD_free(X509_CRL_METHOD *m);
-
-void X509_CRL_set_meth_data(X509_CRL *crl, void *dat);
-void *X509_CRL_get_meth_data(X509_CRL *crl);
-
-const char *X509_verify_cert_error_string(long n);
-
-int X509_verify(X509 *a, EVP_PKEY *r);
-
-int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r);
-int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r);
-int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r);
-
-NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len);
-char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *x);
-EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x);
-int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey);
-
-int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki);
-
-int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent);
-int X509_signature_print(BIO *bp, const X509_ALGOR *alg,
- const ASN1_STRING *sig);
-
-int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
-int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx);
-# ifndef OPENSSL_NO_OCSP
-int X509_http_nbio(OCSP_REQ_CTX *rctx, X509 **pcert);
-# endif
-int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md);
-int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx);
-int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md);
-int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx);
-# ifndef OPENSSL_NO_OCSP
-int X509_CRL_http_nbio(OCSP_REQ_CTX *rctx, X509_CRL **pcrl);
-# endif
-int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md);
-
-int X509_pubkey_digest(const X509 *data, const EVP_MD *type,
- unsigned char *md, unsigned int *len);
-int X509_digest(const X509 *data, const EVP_MD *type,
- unsigned char *md, unsigned int *len);
-int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type,
- unsigned char *md, unsigned int *len);
-int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type,
- unsigned char *md, unsigned int *len);
-int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type,
- unsigned char *md, unsigned int *len);
-
-# ifndef OPENSSL_NO_STDIO
-X509 *d2i_X509_fp(FILE *fp, X509 **x509);
-int i2d_X509_fp(FILE *fp, X509 *x509);
-X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl);
-int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl);
-X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req);
-int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req);
-# ifndef OPENSSL_NO_RSA
-RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa);
-int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa);
-RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa);
-int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa);
-RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa);
-int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa);
-# endif
-# ifndef OPENSSL_NO_DSA
-DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa);
-int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa);
-DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa);
-int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa);
-# endif
-# ifndef OPENSSL_NO_EC
-EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey);
-int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey);
-EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey);
-int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey);
-# endif
-X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8);
-int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8);
-PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
- PKCS8_PRIV_KEY_INFO **p8inf);
-int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf);
-int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key);
-int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey);
-EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a);
-int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey);
-EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a);
-# endif
-
-X509 *d2i_X509_bio(BIO *bp, X509 **x509);
-int i2d_X509_bio(BIO *bp, X509 *x509);
-X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl);
-int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl);
-X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req);
-int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req);
-# ifndef OPENSSL_NO_RSA
-RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa);
-int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa);
-RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa);
-int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa);
-RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa);
-int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa);
-# endif
-# ifndef OPENSSL_NO_DSA
-DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa);
-int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa);
-DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa);
-int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa);
-# endif
-# ifndef OPENSSL_NO_EC
-EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey);
-int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *eckey);
-EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey);
-int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey);
-# endif
-X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8);
-int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8);
-PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
- PKCS8_PRIV_KEY_INFO **p8inf);
-int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf);
-int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key);
-int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey);
-EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a);
-int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey);
-EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a);
-
-X509 *X509_dup(X509 *x509);
-X509_ATTRIBUTE *X509_ATTRIBUTE_dup(X509_ATTRIBUTE *xa);
-X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex);
-X509_CRL *X509_CRL_dup(X509_CRL *crl);
-X509_REVOKED *X509_REVOKED_dup(X509_REVOKED *rev);
-X509_REQ *X509_REQ_dup(X509_REQ *req);
-X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn);
-int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype,
- void *pval);
-void X509_ALGOR_get0(const ASN1_OBJECT **paobj, int *pptype,
- const void **ppval, const X509_ALGOR *algor);
-void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md);
-int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b);
-int X509_ALGOR_copy(X509_ALGOR *dest, const X509_ALGOR *src);
-
-X509_NAME *X509_NAME_dup(X509_NAME *xn);
-X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne);
-
-int X509_cmp_time(const ASN1_TIME *s, time_t *t);
-int X509_cmp_current_time(const ASN1_TIME *s);
-ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *t);
-ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s,
- int offset_day, long offset_sec, time_t *t);
-ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj);
-
-const char *X509_get_default_cert_area(void);
-const char *X509_get_default_cert_dir(void);
-const char *X509_get_default_cert_file(void);
-const char *X509_get_default_cert_dir_env(void);
-const char *X509_get_default_cert_file_env(void);
-const char *X509_get_default_private_dir(void);
-
-X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
-X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey);
-
-DECLARE_ASN1_FUNCTIONS(X509_ALGOR)
-DECLARE_ASN1_ENCODE_FUNCTIONS(X509_ALGORS, X509_ALGORS, X509_ALGORS)
-DECLARE_ASN1_FUNCTIONS(X509_VAL)
-
-DECLARE_ASN1_FUNCTIONS(X509_PUBKEY)
-
-int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey);
-EVP_PKEY *X509_PUBKEY_get0(X509_PUBKEY *key);
-EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key);
-int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain);
-long X509_get_pathlen(X509 *x);
-int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp);
-EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length);
-# ifndef OPENSSL_NO_RSA
-int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp);
-RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length);
-# endif
-# ifndef OPENSSL_NO_DSA
-int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp);
-DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length);
-# endif
-# ifndef OPENSSL_NO_EC
-int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp);
-EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length);
-# endif
-
-DECLARE_ASN1_FUNCTIONS(X509_SIG)
-void X509_SIG_get0(const X509_SIG *sig, const X509_ALGOR **palg,
- const ASN1_OCTET_STRING **pdigest);
-void X509_SIG_getm(X509_SIG *sig, X509_ALGOR **palg,
- ASN1_OCTET_STRING **pdigest);
-
-DECLARE_ASN1_FUNCTIONS(X509_REQ_INFO)
-DECLARE_ASN1_FUNCTIONS(X509_REQ)
-
-DECLARE_ASN1_FUNCTIONS(X509_ATTRIBUTE)
-X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value);
-
-DECLARE_ASN1_FUNCTIONS(X509_EXTENSION)
-DECLARE_ASN1_ENCODE_FUNCTIONS(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS)
-
-DECLARE_ASN1_FUNCTIONS(X509_NAME_ENTRY)
-
-DECLARE_ASN1_FUNCTIONS(X509_NAME)
-
-int X509_NAME_set(X509_NAME **xn, X509_NAME *name);
-
-DECLARE_ASN1_FUNCTIONS(X509_CINF)
-
-DECLARE_ASN1_FUNCTIONS(X509)
-DECLARE_ASN1_FUNCTIONS(X509_CERT_AUX)
-
-#define X509_get_ex_new_index(l, p, newf, dupf, freef) \
- CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509, l, p, newf, dupf, freef)
-int X509_set_ex_data(X509 *r, int idx, void *arg);
-void *X509_get_ex_data(X509 *r, int idx);
-int i2d_X509_AUX(X509 *a, unsigned char **pp);
-X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length);
-
-int i2d_re_X509_tbs(X509 *x, unsigned char **pp);
-
-int X509_SIG_INFO_get(const X509_SIG_INFO *siginf, int *mdnid, int *pknid,
- int *secbits, uint32_t *flags);
-void X509_SIG_INFO_set(X509_SIG_INFO *siginf, int mdnid, int pknid,
- int secbits, uint32_t flags);
-
-int X509_get_signature_info(X509 *x, int *mdnid, int *pknid, int *secbits,
- uint32_t *flags);
-
-void X509_get0_signature(const ASN1_BIT_STRING **psig,
- const X509_ALGOR **palg, const X509 *x);
-int X509_get_signature_nid(const X509 *x);
-
-int X509_trusted(const X509 *x);
-int X509_alias_set1(X509 *x, const unsigned char *name, int len);
-int X509_keyid_set1(X509 *x, const unsigned char *id, int len);
-unsigned char *X509_alias_get0(X509 *x, int *len);
-unsigned char *X509_keyid_get0(X509 *x, int *len);
-int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *,
- int);
-int X509_TRUST_set(int *t, int trust);
-int X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj);
-int X509_add1_reject_object(X509 *x, const ASN1_OBJECT *obj);
-void X509_trust_clear(X509 *x);
-void X509_reject_clear(X509 *x);
-
-STACK_OF(ASN1_OBJECT) *X509_get0_trust_objects(X509 *x);
-STACK_OF(ASN1_OBJECT) *X509_get0_reject_objects(X509 *x);
-
-DECLARE_ASN1_FUNCTIONS(X509_REVOKED)
-DECLARE_ASN1_FUNCTIONS(X509_CRL_INFO)
-DECLARE_ASN1_FUNCTIONS(X509_CRL)
-
-int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
-int X509_CRL_get0_by_serial(X509_CRL *crl,
- X509_REVOKED **ret, ASN1_INTEGER *serial);
-int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x);
-
-X509_PKEY *X509_PKEY_new(void);
-void X509_PKEY_free(X509_PKEY *a);
-
-DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKI)
-DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKAC)
-DECLARE_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE)
-
-X509_INFO *X509_INFO_new(void);
-void X509_INFO_free(X509_INFO *a);
-char *X509_NAME_oneline(const X509_NAME *a, char *buf, int size);
-
-int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *algor1,
- ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey);
-
-int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
- unsigned char *md, unsigned int *len);
-
-int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1,
- X509_ALGOR *algor2, ASN1_BIT_STRING *signature,
- char *data, EVP_PKEY *pkey, const EVP_MD *type);
-
-int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *data,
- unsigned char *md, unsigned int *len);
-
-int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1,
- ASN1_BIT_STRING *signature, void *data, EVP_PKEY *pkey);
-
-int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1,
- X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *data,
- EVP_PKEY *pkey, const EVP_MD *type);
-int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1,
- X509_ALGOR *algor2, ASN1_BIT_STRING *signature,
- void *asn, EVP_MD_CTX *ctx);
-
-long X509_get_version(const X509 *x);
-int X509_set_version(X509 *x, long version);
-int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial);
-ASN1_INTEGER *X509_get_serialNumber(X509 *x);
-const ASN1_INTEGER *X509_get0_serialNumber(const X509 *x);
-int X509_set_issuer_name(X509 *x, X509_NAME *name);
-X509_NAME *X509_get_issuer_name(const X509 *a);
-int X509_set_subject_name(X509 *x, X509_NAME *name);
-X509_NAME *X509_get_subject_name(const X509 *a);
-const ASN1_TIME * X509_get0_notBefore(const X509 *x);
-ASN1_TIME *X509_getm_notBefore(const X509 *x);
-int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm);
-const ASN1_TIME *X509_get0_notAfter(const X509 *x);
-ASN1_TIME *X509_getm_notAfter(const X509 *x);
-int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm);
-int X509_set_pubkey(X509 *x, EVP_PKEY *pkey);
-int X509_up_ref(X509 *x);
-int X509_get_signature_type(const X509 *x);
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-# define X509_get_notBefore X509_getm_notBefore
-# define X509_get_notAfter X509_getm_notAfter
-# define X509_set_notBefore X509_set1_notBefore
-# define X509_set_notAfter X509_set1_notAfter
-#endif
-
-
-/*
- * This one is only used so that a binary form can output, as in
- * i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &buf)
- */
-X509_PUBKEY *X509_get_X509_PUBKEY(const X509 *x);
-const STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x);
-void X509_get0_uids(const X509 *x, const ASN1_BIT_STRING **piuid,
- const ASN1_BIT_STRING **psuid);
-const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x);
-
-EVP_PKEY *X509_get0_pubkey(const X509 *x);
-EVP_PKEY *X509_get_pubkey(X509 *x);
-ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x);
-int X509_certificate_type(const X509 *x, const EVP_PKEY *pubkey);
-
-long X509_REQ_get_version(const X509_REQ *req);
-int X509_REQ_set_version(X509_REQ *x, long version);
-X509_NAME *X509_REQ_get_subject_name(const X509_REQ *req);
-int X509_REQ_set_subject_name(X509_REQ *req, X509_NAME *name);
-void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig,
- const X509_ALGOR **palg);
-void X509_REQ_set0_signature(X509_REQ *req, ASN1_BIT_STRING *psig);
-int X509_REQ_set1_signature_algo(X509_REQ *req, X509_ALGOR *palg);
-int X509_REQ_get_signature_nid(const X509_REQ *req);
-int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp);
-int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey);
-EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req);
-EVP_PKEY *X509_REQ_get0_pubkey(X509_REQ *req);
-X509_PUBKEY *X509_REQ_get_X509_PUBKEY(X509_REQ *req);
-int X509_REQ_extension_nid(int nid);
-int *X509_REQ_get_extension_nids(void);
-void X509_REQ_set_extension_nids(int *nids);
-STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req);
-int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts,
- int nid);
-int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts);
-int X509_REQ_get_attr_count(const X509_REQ *req);
-int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos);
-int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, const ASN1_OBJECT *obj,
- int lastpos);
-X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc);
-X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc);
-int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr);
-int X509_REQ_add1_attr_by_OBJ(X509_REQ *req,
- const ASN1_OBJECT *obj, int type,
- const unsigned char *bytes, int len);
-int X509_REQ_add1_attr_by_NID(X509_REQ *req,
- int nid, int type,
- const unsigned char *bytes, int len);
-int X509_REQ_add1_attr_by_txt(X509_REQ *req,
- const char *attrname, int type,
- const unsigned char *bytes, int len);
-
-int X509_CRL_set_version(X509_CRL *x, long version);
-int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name);
-int X509_CRL_set1_lastUpdate(X509_CRL *x, const ASN1_TIME *tm);
-int X509_CRL_set1_nextUpdate(X509_CRL *x, const ASN1_TIME *tm);
-int X509_CRL_sort(X509_CRL *crl);
-int X509_CRL_up_ref(X509_CRL *crl);
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-# define X509_CRL_set_lastUpdate X509_CRL_set1_lastUpdate
-# define X509_CRL_set_nextUpdate X509_CRL_set1_nextUpdate
-#endif
-
-long X509_CRL_get_version(const X509_CRL *crl);
-const ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *crl);
-const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl);
-DEPRECATEDIN_1_1_0(ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *crl))
-DEPRECATEDIN_1_1_0(ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *crl))
-X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl);
-const STACK_OF(X509_EXTENSION) *X509_CRL_get0_extensions(const X509_CRL *crl);
-STACK_OF(X509_REVOKED) *X509_CRL_get_REVOKED(X509_CRL *crl);
-void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig,
- const X509_ALGOR **palg);
-int X509_CRL_get_signature_nid(const X509_CRL *crl);
-int i2d_re_X509_CRL_tbs(X509_CRL *req, unsigned char **pp);
-
-const ASN1_INTEGER *X509_REVOKED_get0_serialNumber(const X509_REVOKED *x);
-int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial);
-const ASN1_TIME *X509_REVOKED_get0_revocationDate(const X509_REVOKED *x);
-int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm);
-const STACK_OF(X509_EXTENSION) *
-X509_REVOKED_get0_extensions(const X509_REVOKED *r);
-
-X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
- EVP_PKEY *skey, const EVP_MD *md, unsigned int flags);
-
-int X509_REQ_check_private_key(X509_REQ *x509, EVP_PKEY *pkey);
-
-int X509_check_private_key(const X509 *x509, const EVP_PKEY *pkey);
-int X509_chain_check_suiteb(int *perror_depth,
- X509 *x, STACK_OF(X509) *chain,
- unsigned long flags);
-int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags);
-STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain);
-
-int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b);
-unsigned long X509_issuer_and_serial_hash(X509 *a);
-
-int X509_issuer_name_cmp(const X509 *a, const X509 *b);
-unsigned long X509_issuer_name_hash(X509 *a);
-
-int X509_subject_name_cmp(const X509 *a, const X509 *b);
-unsigned long X509_subject_name_hash(X509 *x);
-
-# ifndef OPENSSL_NO_MD5
-unsigned long X509_issuer_name_hash_old(X509 *a);
-unsigned long X509_subject_name_hash_old(X509 *x);
-# endif
-
-int X509_cmp(const X509 *a, const X509 *b);
-int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b);
-unsigned long X509_NAME_hash(X509_NAME *x);
-unsigned long X509_NAME_hash_old(X509_NAME *x);
-
-int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b);
-int X509_CRL_match(const X509_CRL *a, const X509_CRL *b);
-int X509_aux_print(BIO *out, X509 *x, int indent);
-# ifndef OPENSSL_NO_STDIO
-int X509_print_ex_fp(FILE *bp, X509 *x, unsigned long nmflag,
- unsigned long cflag);
-int X509_print_fp(FILE *bp, X509 *x);
-int X509_CRL_print_fp(FILE *bp, X509_CRL *x);
-int X509_REQ_print_fp(FILE *bp, X509_REQ *req);
-int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent,
- unsigned long flags);
-# endif
-
-int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase);
-int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent,
- unsigned long flags);
-int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflag,
- unsigned long cflag);
-int X509_print(BIO *bp, X509 *x);
-int X509_ocspid_print(BIO *bp, X509 *x);
-int X509_CRL_print_ex(BIO *out, X509_CRL *x, unsigned long nmflag);
-int X509_CRL_print(BIO *bp, X509_CRL *x);
-int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflag,
- unsigned long cflag);
-int X509_REQ_print(BIO *bp, X509_REQ *req);
-
-int X509_NAME_entry_count(const X509_NAME *name);
-int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len);
-int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj,
- char *buf, int len);
-
-/*
- * NOTE: you should be passing -1, not 0 as lastpos. The functions that use
- * lastpos, search after that position on.
- */
-int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos);
-int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj,
- int lastpos);
-X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc);
-X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc);
-int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne,
- int loc, int set);
-int X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int type,
- const unsigned char *bytes, int len, int loc,
- int set);
-int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
- const unsigned char *bytes, int len, int loc,
- int set);
-X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
- const char *field, int type,
- const unsigned char *bytes,
- int len);
-X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
- int type,
- const unsigned char *bytes,
- int len);
-int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
- const unsigned char *bytes, int len, int loc,
- int set);
-X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
- const ASN1_OBJECT *obj, int type,
- const unsigned char *bytes,
- int len);
-int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj);
-int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
- const unsigned char *bytes, int len);
-ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne);
-ASN1_STRING * X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne);
-int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne);
-
-int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder,
- size_t *pderlen);
-
-int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x);
-int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x,
- int nid, int lastpos);
-int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *x,
- const ASN1_OBJECT *obj, int lastpos);
-int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *x,
- int crit, int lastpos);
-X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc);
-X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc);
-STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x,
- X509_EXTENSION *ex, int loc);
-
-int X509_get_ext_count(const X509 *x);
-int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos);
-int X509_get_ext_by_OBJ(const X509 *x, const ASN1_OBJECT *obj, int lastpos);
-int X509_get_ext_by_critical(const X509 *x, int crit, int lastpos);
-X509_EXTENSION *X509_get_ext(const X509 *x, int loc);
-X509_EXTENSION *X509_delete_ext(X509 *x, int loc);
-int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
-void *X509_get_ext_d2i(const X509 *x, int nid, int *crit, int *idx);
-int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit,
- unsigned long flags);
-
-int X509_CRL_get_ext_count(const X509_CRL *x);
-int X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, int lastpos);
-int X509_CRL_get_ext_by_OBJ(const X509_CRL *x, const ASN1_OBJECT *obj,
- int lastpos);
-int X509_CRL_get_ext_by_critical(const X509_CRL *x, int crit, int lastpos);
-X509_EXTENSION *X509_CRL_get_ext(const X509_CRL *x, int loc);
-X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc);
-int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc);
-void *X509_CRL_get_ext_d2i(const X509_CRL *x, int nid, int *crit, int *idx);
-int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit,
- unsigned long flags);
-
-int X509_REVOKED_get_ext_count(const X509_REVOKED *x);
-int X509_REVOKED_get_ext_by_NID(const X509_REVOKED *x, int nid, int lastpos);
-int X509_REVOKED_get_ext_by_OBJ(const X509_REVOKED *x, const ASN1_OBJECT *obj,
- int lastpos);
-int X509_REVOKED_get_ext_by_critical(const X509_REVOKED *x, int crit,
- int lastpos);
-X509_EXTENSION *X509_REVOKED_get_ext(const X509_REVOKED *x, int loc);
-X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc);
-int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc);
-void *X509_REVOKED_get_ext_d2i(const X509_REVOKED *x, int nid, int *crit,
- int *idx);
-int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit,
- unsigned long flags);
-
-X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex,
- int nid, int crit,
- ASN1_OCTET_STRING *data);
-X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex,
- const ASN1_OBJECT *obj, int crit,
- ASN1_OCTET_STRING *data);
-int X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj);
-int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit);
-int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data);
-ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex);
-ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne);
-int X509_EXTENSION_get_critical(const X509_EXTENSION *ex);
-
-int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x);
-int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
- int lastpos);
-int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk,
- const ASN1_OBJECT *obj, int lastpos);
-X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc);
-X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc);
-STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
- X509_ATTRIBUTE *attr);
-STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE)
- **x, const ASN1_OBJECT *obj,
- int type,
- const unsigned char *bytes,
- int len);
-STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE)
- **x, int nid, int type,
- const unsigned char *bytes,
- int len);
-STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE)
- **x, const char *attrname,
- int type,
- const unsigned char *bytes,
- int len);
-void *X509at_get0_data_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *x,
- const ASN1_OBJECT *obj, int lastpos, int type);
-X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
- int atrtype, const void *data,
- int len);
-X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
- const ASN1_OBJECT *obj,
- int atrtype, const void *data,
- int len);
-X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr,
- const char *atrname, int type,
- const unsigned char *bytes,
- int len);
-int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj);
-int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype,
- const void *data, int len);
-void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, int atrtype,
- void *data);
-int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr);
-ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr);
-ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx);
-
-int EVP_PKEY_get_attr_count(const EVP_PKEY *key);
-int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid, int lastpos);
-int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, const ASN1_OBJECT *obj,
- int lastpos);
-X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc);
-X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc);
-int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr);
-int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key,
- const ASN1_OBJECT *obj, int type,
- const unsigned char *bytes, int len);
-int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key,
- int nid, int type,
- const unsigned char *bytes, int len);
-int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key,
- const char *attrname, int type,
- const unsigned char *bytes, int len);
-
-int X509_verify_cert(X509_STORE_CTX *ctx);
-
-/* lookup a cert from a X509 STACK */
-X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name,
- ASN1_INTEGER *serial);
-X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name);
-
-DECLARE_ASN1_FUNCTIONS(PBEPARAM)
-DECLARE_ASN1_FUNCTIONS(PBE2PARAM)
-DECLARE_ASN1_FUNCTIONS(PBKDF2PARAM)
-#ifndef OPENSSL_NO_SCRYPT
-DECLARE_ASN1_FUNCTIONS(SCRYPT_PARAMS)
-#endif
-
-int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
- const unsigned char *salt, int saltlen);
-
-X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
- const unsigned char *salt, int saltlen);
-X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
- unsigned char *salt, int saltlen);
-X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
- unsigned char *salt, int saltlen,
- unsigned char *aiv, int prf_nid);
-
-#ifndef OPENSSL_NO_SCRYPT
-X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
- const unsigned char *salt, int saltlen,
- unsigned char *aiv, uint64_t N, uint64_t r,
- uint64_t p);
-#endif
-
-X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
- int prf_nid, int keylen);
-
-/* PKCS#8 utilities */
-
-DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
-
-EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8);
-PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey);
-
-int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj,
- int version, int ptype, void *pval,
- unsigned char *penc, int penclen);
-int PKCS8_pkey_get0(const ASN1_OBJECT **ppkalg,
- const unsigned char **pk, int *ppklen,
- const X509_ALGOR **pa, const PKCS8_PRIV_KEY_INFO *p8);
-
-const STACK_OF(X509_ATTRIBUTE) *
-PKCS8_pkey_get0_attrs(const PKCS8_PRIV_KEY_INFO *p8);
-int PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type,
- const unsigned char *bytes, int len);
-
-int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj,
- int ptype, void *pval,
- unsigned char *penc, int penclen);
-int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg,
- const unsigned char **pk, int *ppklen,
- X509_ALGOR **pa, X509_PUBKEY *pub);
-
-int X509_check_trust(X509 *x, int id, int flags);
-int X509_TRUST_get_count(void);
-X509_TRUST *X509_TRUST_get0(int idx);
-int X509_TRUST_get_by_id(int id);
-int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int),
- const char *name, int arg1, void *arg2);
-void X509_TRUST_cleanup(void);
-int X509_TRUST_get_flags(const X509_TRUST *xp);
-char *X509_TRUST_get0_name(const X509_TRUST *xp);
-int X509_TRUST_get_trust(const X509_TRUST *xp);
-
-# ifdef __cplusplus
-}
-# endif
-#endif
diff --git a/include/openssl/x509.h.in b/include/openssl/x509.h.in
new file mode 100644
index 000000000000..3ef741f603f7
--- /dev/null
+++ b/include/openssl/x509.h.in
@@ -0,0 +1,1082 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_X509_H
+# define OPENSSL_X509_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_X509_H
+# endif
+
+# include <openssl/e_os2.h>
+# include <openssl/types.h>
+# include <openssl/symhacks.h>
+# include <openssl/buffer.h>
+# include <openssl/evp.h>
+# include <openssl/bio.h>
+# include <openssl/asn1.h>
+# include <openssl/safestack.h>
+# include <openssl/ec.h>
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# include <openssl/rsa.h>
+# include <openssl/dsa.h>
+# include <openssl/dh.h>
+# endif
+
+# include <openssl/sha.h>
+# include <openssl/x509err.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Needed stacks for types defined in other headers */
+{-
+ generate_stack_macros("X509_NAME")
+ .generate_stack_macros("X509")
+ .generate_stack_macros("X509_REVOKED")
+ .generate_stack_macros("X509_CRL");
+-}
+
+/* Flags for X509_get_signature_info() */
+/* Signature info is valid */
+# define X509_SIG_INFO_VALID 0x1
+/* Signature is suitable for TLS use */
+# define X509_SIG_INFO_TLS 0x2
+
+# define X509_FILETYPE_PEM 1
+# define X509_FILETYPE_ASN1 2
+# define X509_FILETYPE_DEFAULT 3
+
+# define X509v3_KU_DIGITAL_SIGNATURE 0x0080
+# define X509v3_KU_NON_REPUDIATION 0x0040
+# define X509v3_KU_KEY_ENCIPHERMENT 0x0020
+# define X509v3_KU_DATA_ENCIPHERMENT 0x0010
+# define X509v3_KU_KEY_AGREEMENT 0x0008
+# define X509v3_KU_KEY_CERT_SIGN 0x0004
+# define X509v3_KU_CRL_SIGN 0x0002
+# define X509v3_KU_ENCIPHER_ONLY 0x0001
+# define X509v3_KU_DECIPHER_ONLY 0x8000
+# define X509v3_KU_UNDEF 0xffff
+
+struct X509_algor_st {
+ ASN1_OBJECT *algorithm;
+ ASN1_TYPE *parameter;
+} /* X509_ALGOR */ ;
+
+typedef STACK_OF(X509_ALGOR) X509_ALGORS;
+
+typedef struct X509_val_st {
+ ASN1_TIME *notBefore;
+ ASN1_TIME *notAfter;
+} X509_VAL;
+
+typedef struct X509_sig_st X509_SIG;
+
+typedef struct X509_name_entry_st X509_NAME_ENTRY;
+
+{-
+ generate_stack_macros("X509_NAME_ENTRY");
+-}
+
+# define X509_EX_V_NETSCAPE_HACK 0x8000
+# define X509_EX_V_INIT 0x0001
+typedef struct X509_extension_st X509_EXTENSION;
+{-
+ generate_stack_macros("X509_EXTENSION");
+-}
+typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS;
+typedef struct x509_attributes_st X509_ATTRIBUTE;
+{-
+ generate_stack_macros("X509_ATTRIBUTE");
+-}
+typedef struct X509_req_info_st X509_REQ_INFO;
+typedef struct X509_req_st X509_REQ;
+typedef struct x509_cert_aux_st X509_CERT_AUX;
+typedef struct x509_cinf_st X509_CINF;
+
+/* Flags for X509_print_ex() */
+
+# define X509_FLAG_COMPAT 0
+# define X509_FLAG_NO_HEADER 1L
+# define X509_FLAG_NO_VERSION (1L << 1)
+# define X509_FLAG_NO_SERIAL (1L << 2)
+# define X509_FLAG_NO_SIGNAME (1L << 3)
+# define X509_FLAG_NO_ISSUER (1L << 4)
+# define X509_FLAG_NO_VALIDITY (1L << 5)
+# define X509_FLAG_NO_SUBJECT (1L << 6)
+# define X509_FLAG_NO_PUBKEY (1L << 7)
+# define X509_FLAG_NO_EXTENSIONS (1L << 8)
+# define X509_FLAG_NO_SIGDUMP (1L << 9)
+# define X509_FLAG_NO_AUX (1L << 10)
+# define X509_FLAG_NO_ATTRIBUTES (1L << 11)
+# define X509_FLAG_NO_IDS (1L << 12)
+# define X509_FLAG_EXTENSIONS_ONLY_KID (1L << 13)
+
+/* Flags specific to X509_NAME_print_ex() */
+
+/* The field separator information */
+
+# define XN_FLAG_SEP_MASK (0xf << 16)
+
+# define XN_FLAG_COMPAT 0/* Traditional; use old X509_NAME_print */
+# define XN_FLAG_SEP_COMMA_PLUS (1 << 16)/* RFC2253 ,+ */
+# define XN_FLAG_SEP_CPLUS_SPC (2 << 16)/* ,+ spaced: more readable */
+# define XN_FLAG_SEP_SPLUS_SPC (3 << 16)/* ;+ spaced */
+# define XN_FLAG_SEP_MULTILINE (4 << 16)/* One line per field */
+
+# define XN_FLAG_DN_REV (1 << 20)/* Reverse DN order */
+
+/* How the field name is shown */
+
+# define XN_FLAG_FN_MASK (0x3 << 21)
+
+# define XN_FLAG_FN_SN 0/* Object short name */
+# define XN_FLAG_FN_LN (1 << 21)/* Object long name */
+# define XN_FLAG_FN_OID (2 << 21)/* Always use OIDs */
+# define XN_FLAG_FN_NONE (3 << 21)/* No field names */
+
+# define XN_FLAG_SPC_EQ (1 << 23)/* Put spaces round '=' */
+
+/*
+ * This determines if we dump fields we don't recognise: RFC2253 requires
+ * this.
+ */
+
+# define XN_FLAG_DUMP_UNKNOWN_FIELDS (1 << 24)
+
+# define XN_FLAG_FN_ALIGN (1 << 25)/* Align field names to 20
+ * characters */
+
+/* Complete set of RFC2253 flags */
+
+# define XN_FLAG_RFC2253 (ASN1_STRFLGS_RFC2253 | \
+ XN_FLAG_SEP_COMMA_PLUS | \
+ XN_FLAG_DN_REV | \
+ XN_FLAG_FN_SN | \
+ XN_FLAG_DUMP_UNKNOWN_FIELDS)
+
+/* readable oneline form */
+
+# define XN_FLAG_ONELINE (ASN1_STRFLGS_RFC2253 | \
+ ASN1_STRFLGS_ESC_QUOTE | \
+ XN_FLAG_SEP_CPLUS_SPC | \
+ XN_FLAG_SPC_EQ | \
+ XN_FLAG_FN_SN)
+
+/* readable multiline form */
+
+# define XN_FLAG_MULTILINE (ASN1_STRFLGS_ESC_CTRL | \
+ ASN1_STRFLGS_ESC_MSB | \
+ XN_FLAG_SEP_MULTILINE | \
+ XN_FLAG_SPC_EQ | \
+ XN_FLAG_FN_LN | \
+ XN_FLAG_FN_ALIGN)
+
+typedef struct X509_crl_info_st X509_CRL_INFO;
+
+typedef struct private_key_st {
+ int version;
+ /* The PKCS#8 data types */
+ X509_ALGOR *enc_algor;
+ ASN1_OCTET_STRING *enc_pkey; /* encrypted pub key */
+ /* When decrypted, the following will not be NULL */
+ EVP_PKEY *dec_pkey;
+ /* used to encrypt and decrypt */
+ int key_length;
+ char *key_data;
+ int key_free; /* true if we should auto free key_data */
+ /* expanded version of 'enc_algor' */
+ EVP_CIPHER_INFO cipher;
+} X509_PKEY;
+
+typedef struct X509_info_st {
+ X509 *x509;
+ X509_CRL *crl;
+ X509_PKEY *x_pkey;
+ EVP_CIPHER_INFO enc_cipher;
+ int enc_len;
+ char *enc_data;
+} X509_INFO;
+{-
+ generate_stack_macros("X509_INFO");
+-}
+
+/*
+ * The next 2 structures and their 8 routines are used to manipulate Netscape's
+ * spki structures - useful if you are writing a CA web page
+ */
+typedef struct Netscape_spkac_st {
+ X509_PUBKEY *pubkey;
+ ASN1_IA5STRING *challenge; /* challenge sent in atlas >= PR2 */
+} NETSCAPE_SPKAC;
+
+typedef struct Netscape_spki_st {
+ NETSCAPE_SPKAC *spkac; /* signed public key and challenge */
+ X509_ALGOR sig_algor;
+ ASN1_BIT_STRING *signature;
+} NETSCAPE_SPKI;
+
+/* Netscape certificate sequence structure */
+typedef struct Netscape_certificate_sequence {
+ ASN1_OBJECT *type;
+ STACK_OF(X509) *certs;
+} NETSCAPE_CERT_SEQUENCE;
+
+/*- Unused (and iv length is wrong)
+typedef struct CBCParameter_st
+ {
+ unsigned char iv[8];
+ } CBC_PARAM;
+*/
+
+/* Password based encryption structure */
+
+typedef struct PBEPARAM_st {
+ ASN1_OCTET_STRING *salt;
+ ASN1_INTEGER *iter;
+} PBEPARAM;
+
+/* Password based encryption V2 structures */
+
+typedef struct PBE2PARAM_st {
+ X509_ALGOR *keyfunc;
+ X509_ALGOR *encryption;
+} PBE2PARAM;
+
+typedef struct PBKDF2PARAM_st {
+/* Usually OCTET STRING but could be anything */
+ ASN1_TYPE *salt;
+ ASN1_INTEGER *iter;
+ ASN1_INTEGER *keylength;
+ X509_ALGOR *prf;
+} PBKDF2PARAM;
+
+#ifndef OPENSSL_NO_SCRYPT
+typedef struct SCRYPT_PARAMS_st {
+ ASN1_OCTET_STRING *salt;
+ ASN1_INTEGER *costParameter;
+ ASN1_INTEGER *blockSize;
+ ASN1_INTEGER *parallelizationParameter;
+ ASN1_INTEGER *keyLength;
+} SCRYPT_PARAMS;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+# include <openssl/x509_vfy.h>
+# include <openssl/pkcs7.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+# define X509_EXT_PACK_UNKNOWN 1
+# define X509_EXT_PACK_STRING 2
+
+# define X509_extract_key(x) X509_get_pubkey(x)/*****/
+# define X509_REQ_extract_key(a) X509_REQ_get_pubkey(a)
+# define X509_name_cmp(a,b) X509_NAME_cmp((a),(b))
+
+void X509_CRL_set_default_method(const X509_CRL_METHOD *meth);
+X509_CRL_METHOD *X509_CRL_METHOD_new(int (*crl_init) (X509_CRL *crl),
+ int (*crl_free) (X509_CRL *crl),
+ int (*crl_lookup) (X509_CRL *crl,
+ X509_REVOKED **ret,
+ const
+ ASN1_INTEGER *serial,
+ const
+ X509_NAME *issuer),
+ int (*crl_verify) (X509_CRL *crl,
+ EVP_PKEY *pk));
+void X509_CRL_METHOD_free(X509_CRL_METHOD *m);
+
+void X509_CRL_set_meth_data(X509_CRL *crl, void *dat);
+void *X509_CRL_get_meth_data(X509_CRL *crl);
+
+const char *X509_verify_cert_error_string(long n);
+
+int X509_verify(X509 *a, EVP_PKEY *r);
+int X509_self_signed(X509 *cert, int verify_signature);
+
+int X509_REQ_verify_ex(X509_REQ *a, EVP_PKEY *r, OSSL_LIB_CTX *libctx,
+ const char *propq);
+int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r);
+int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r);
+int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r);
+
+NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len);
+char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *x);
+EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x);
+int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey);
+
+int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki);
+
+int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent);
+int X509_signature_print(BIO *bp, const X509_ALGOR *alg,
+ const ASN1_STRING *sig);
+
+int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
+int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx);
+int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md);
+int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx);
+int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md);
+int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx);
+int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md);
+
+int X509_pubkey_digest(const X509 *data, const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+int X509_digest(const X509 *data, const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+ASN1_OCTET_STRING *X509_digest_sig(const X509 *cert,
+ EVP_MD **md_used, int *md_is_fallback);
+int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+
+X509 *X509_load_http(const char *url, BIO *bio, BIO *rbio, int timeout);
+X509_CRL *X509_CRL_load_http(const char *url, BIO *bio, BIO *rbio, int timeout);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# include <openssl/http.h> /* OSSL_HTTP_REQ_CTX_nbio_d2i */
+# define X509_http_nbio(rctx, pcert) \
+ OSSL_HTTP_REQ_CTX_nbio_d2i(rctx, pcert, ASN1_ITEM_rptr(X509))
+# define X509_CRL_http_nbio(rctx, pcrl) \
+ OSSL_HTTP_REQ_CTX_nbio_d2i(rctx, pcrl, ASN1_ITEM_rptr(X509_CRL))
+# endif
+
+# ifndef OPENSSL_NO_STDIO
+X509 *d2i_X509_fp(FILE *fp, X509 **x509);
+int i2d_X509_fp(FILE *fp, const X509 *x509);
+X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl);
+int i2d_X509_CRL_fp(FILE *fp, const X509_CRL *crl);
+X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req);
+int i2d_X509_REQ_fp(FILE *fp, const X509_REQ *req);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa);
+OSSL_DEPRECATEDIN_3_0 int i2d_RSAPrivateKey_fp(FILE *fp, const RSA *rsa);
+OSSL_DEPRECATEDIN_3_0 RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa);
+OSSL_DEPRECATEDIN_3_0 int i2d_RSAPublicKey_fp(FILE *fp, const RSA *rsa);
+OSSL_DEPRECATEDIN_3_0 RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa);
+OSSL_DEPRECATEDIN_3_0 int i2d_RSA_PUBKEY_fp(FILE *fp, const RSA *rsa);
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef OPENSSL_NO_DSA
+OSSL_DEPRECATEDIN_3_0 DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa);
+OSSL_DEPRECATEDIN_3_0 int i2d_DSA_PUBKEY_fp(FILE *fp, const DSA *dsa);
+OSSL_DEPRECATEDIN_3_0 DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa);
+OSSL_DEPRECATEDIN_3_0 int i2d_DSAPrivateKey_fp(FILE *fp, const DSA *dsa);
+# endif
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef OPENSSL_NO_EC
+OSSL_DEPRECATEDIN_3_0 EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey);
+OSSL_DEPRECATEDIN_3_0 int i2d_EC_PUBKEY_fp(FILE *fp, const EC_KEY *eckey);
+OSSL_DEPRECATEDIN_3_0 EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey);
+OSSL_DEPRECATEDIN_3_0 int i2d_ECPrivateKey_fp(FILE *fp, const EC_KEY *eckey);
+# endif /* OPENSSL_NO_EC */
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
+X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8);
+int i2d_PKCS8_fp(FILE *fp, const X509_SIG *p8);
+X509_PUBKEY *d2i_X509_PUBKEY_fp(FILE *fp, X509_PUBKEY **xpk);
+int i2d_X509_PUBKEY_fp(FILE *fp, const X509_PUBKEY *xpk);
+PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
+ PKCS8_PRIV_KEY_INFO **p8inf);
+int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, const PKCS8_PRIV_KEY_INFO *p8inf);
+int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, const EVP_PKEY *key);
+int i2d_PrivateKey_fp(FILE *fp, const EVP_PKEY *pkey);
+EVP_PKEY *d2i_PrivateKey_ex_fp(FILE *fp, EVP_PKEY **a, OSSL_LIB_CTX *libctx,
+ const char *propq);
+EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a);
+int i2d_PUBKEY_fp(FILE *fp, const EVP_PKEY *pkey);
+EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a);
+# endif
+
+X509 *d2i_X509_bio(BIO *bp, X509 **x509);
+int i2d_X509_bio(BIO *bp, const X509 *x509);
+X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl);
+int i2d_X509_CRL_bio(BIO *bp, const X509_CRL *crl);
+X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req);
+int i2d_X509_REQ_bio(BIO *bp, const X509_REQ *req);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0 RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa);
+OSSL_DEPRECATEDIN_3_0 int i2d_RSAPrivateKey_bio(BIO *bp, const RSA *rsa);
+OSSL_DEPRECATEDIN_3_0 RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa);
+OSSL_DEPRECATEDIN_3_0 int i2d_RSAPublicKey_bio(BIO *bp, const RSA *rsa);
+OSSL_DEPRECATEDIN_3_0 RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa);
+OSSL_DEPRECATEDIN_3_0 int i2d_RSA_PUBKEY_bio(BIO *bp, const RSA *rsa);
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef OPENSSL_NO_DSA
+OSSL_DEPRECATEDIN_3_0 DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa);
+OSSL_DEPRECATEDIN_3_0 int i2d_DSA_PUBKEY_bio(BIO *bp, const DSA *dsa);
+OSSL_DEPRECATEDIN_3_0 DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa);
+OSSL_DEPRECATEDIN_3_0 int i2d_DSAPrivateKey_bio(BIO *bp, const DSA *dsa);
+# endif
+# endif
+
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef OPENSSL_NO_EC
+OSSL_DEPRECATEDIN_3_0 EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey);
+OSSL_DEPRECATEDIN_3_0 int i2d_EC_PUBKEY_bio(BIO *bp, const EC_KEY *eckey);
+OSSL_DEPRECATEDIN_3_0 EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey);
+OSSL_DEPRECATEDIN_3_0 int i2d_ECPrivateKey_bio(BIO *bp, const EC_KEY *eckey);
+# endif /* OPENSSL_NO_EC */
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
+
+X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8);
+int i2d_PKCS8_bio(BIO *bp, const X509_SIG *p8);
+X509_PUBKEY *d2i_X509_PUBKEY_bio(BIO *bp, X509_PUBKEY **xpk);
+int i2d_X509_PUBKEY_bio(BIO *bp, const X509_PUBKEY *xpk);
+PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
+ PKCS8_PRIV_KEY_INFO **p8inf);
+int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, const PKCS8_PRIV_KEY_INFO *p8inf);
+int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, const EVP_PKEY *key);
+int i2d_PrivateKey_bio(BIO *bp, const EVP_PKEY *pkey);
+EVP_PKEY *d2i_PrivateKey_ex_bio(BIO *bp, EVP_PKEY **a, OSSL_LIB_CTX *libctx,
+ const char *propq);
+EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a);
+int i2d_PUBKEY_bio(BIO *bp, const EVP_PKEY *pkey);
+EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a);
+
+DECLARE_ASN1_DUP_FUNCTION(X509)
+DECLARE_ASN1_DUP_FUNCTION(X509_ALGOR)
+DECLARE_ASN1_DUP_FUNCTION(X509_ATTRIBUTE)
+DECLARE_ASN1_DUP_FUNCTION(X509_CRL)
+DECLARE_ASN1_DUP_FUNCTION(X509_EXTENSION)
+DECLARE_ASN1_DUP_FUNCTION(X509_PUBKEY)
+DECLARE_ASN1_DUP_FUNCTION(X509_REQ)
+DECLARE_ASN1_DUP_FUNCTION(X509_REVOKED)
+int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype,
+ void *pval);
+void X509_ALGOR_get0(const ASN1_OBJECT **paobj, int *pptype,
+ const void **ppval, const X509_ALGOR *algor);
+void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md);
+int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b);
+int X509_ALGOR_copy(X509_ALGOR *dest, const X509_ALGOR *src);
+
+DECLARE_ASN1_DUP_FUNCTION(X509_NAME)
+DECLARE_ASN1_DUP_FUNCTION(X509_NAME_ENTRY)
+
+int X509_cmp_time(const ASN1_TIME *s, time_t *t);
+int X509_cmp_current_time(const ASN1_TIME *s);
+int X509_cmp_timeframe(const X509_VERIFY_PARAM *vpm,
+ const ASN1_TIME *start, const ASN1_TIME *end);
+ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *t);
+ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s,
+ int offset_day, long offset_sec, time_t *t);
+ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj);
+
+const char *X509_get_default_cert_area(void);
+const char *X509_get_default_cert_dir(void);
+const char *X509_get_default_cert_file(void);
+const char *X509_get_default_cert_dir_env(void);
+const char *X509_get_default_cert_file_env(void);
+const char *X509_get_default_private_dir(void);
+
+X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
+X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey);
+
+DECLARE_ASN1_FUNCTIONS(X509_ALGOR)
+DECLARE_ASN1_ENCODE_FUNCTIONS(X509_ALGORS, X509_ALGORS, X509_ALGORS)
+DECLARE_ASN1_FUNCTIONS(X509_VAL)
+
+DECLARE_ASN1_FUNCTIONS(X509_PUBKEY)
+
+X509_PUBKEY *X509_PUBKEY_new_ex(OSSL_LIB_CTX *libctx, const char *propq);
+int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey);
+EVP_PKEY *X509_PUBKEY_get0(const X509_PUBKEY *key);
+EVP_PKEY *X509_PUBKEY_get(const X509_PUBKEY *key);
+int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain);
+long X509_get_pathlen(X509 *x);
+DECLARE_ASN1_ENCODE_FUNCTIONS_only(EVP_PKEY, PUBKEY)
+EVP_PKEY *d2i_PUBKEY_ex(EVP_PKEY **a, const unsigned char **pp, long length,
+ OSSL_LIB_CTX *libctx, const char *propq);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(OSSL_DEPRECATEDIN_3_0,RSA, RSA_PUBKEY)
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef OPENSSL_NO_DSA
+DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(OSSL_DEPRECATEDIN_3_0,DSA, DSA_PUBKEY)
+# endif
+# endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# ifndef OPENSSL_NO_EC
+DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(OSSL_DEPRECATEDIN_3_0, EC_KEY, EC_PUBKEY)
+# endif
+# endif
+
+DECLARE_ASN1_FUNCTIONS(X509_SIG)
+void X509_SIG_get0(const X509_SIG *sig, const X509_ALGOR **palg,
+ const ASN1_OCTET_STRING **pdigest);
+void X509_SIG_getm(X509_SIG *sig, X509_ALGOR **palg,
+ ASN1_OCTET_STRING **pdigest);
+
+DECLARE_ASN1_FUNCTIONS(X509_REQ_INFO)
+DECLARE_ASN1_FUNCTIONS(X509_REQ)
+X509_REQ *X509_REQ_new_ex(OSSL_LIB_CTX *libctx, const char *propq);
+
+DECLARE_ASN1_FUNCTIONS(X509_ATTRIBUTE)
+X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value);
+
+DECLARE_ASN1_FUNCTIONS(X509_EXTENSION)
+DECLARE_ASN1_ENCODE_FUNCTIONS(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS)
+
+DECLARE_ASN1_FUNCTIONS(X509_NAME_ENTRY)
+
+DECLARE_ASN1_FUNCTIONS(X509_NAME)
+
+int X509_NAME_set(X509_NAME **xn, const X509_NAME *name);
+
+DECLARE_ASN1_FUNCTIONS(X509_CINF)
+DECLARE_ASN1_FUNCTIONS(X509)
+X509 *X509_new_ex(OSSL_LIB_CTX *libctx, const char *propq);
+DECLARE_ASN1_FUNCTIONS(X509_CERT_AUX)
+
+#define X509_get_ex_new_index(l, p, newf, dupf, freef) \
+ CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509, l, p, newf, dupf, freef)
+int X509_set_ex_data(X509 *r, int idx, void *arg);
+void *X509_get_ex_data(const X509 *r, int idx);
+DECLARE_ASN1_ENCODE_FUNCTIONS_only(X509,X509_AUX)
+
+int i2d_re_X509_tbs(X509 *x, unsigned char **pp);
+
+int X509_SIG_INFO_get(const X509_SIG_INFO *siginf, int *mdnid, int *pknid,
+ int *secbits, uint32_t *flags);
+void X509_SIG_INFO_set(X509_SIG_INFO *siginf, int mdnid, int pknid,
+ int secbits, uint32_t flags);
+
+int X509_get_signature_info(X509 *x, int *mdnid, int *pknid, int *secbits,
+ uint32_t *flags);
+
+void X509_get0_signature(const ASN1_BIT_STRING **psig,
+ const X509_ALGOR **palg, const X509 *x);
+int X509_get_signature_nid(const X509 *x);
+
+void X509_set0_distinguishing_id(X509 *x, ASN1_OCTET_STRING *d_id);
+ASN1_OCTET_STRING *X509_get0_distinguishing_id(X509 *x);
+void X509_REQ_set0_distinguishing_id(X509_REQ *x, ASN1_OCTET_STRING *d_id);
+ASN1_OCTET_STRING *X509_REQ_get0_distinguishing_id(X509_REQ *x);
+
+int X509_alias_set1(X509 *x, const unsigned char *name, int len);
+int X509_keyid_set1(X509 *x, const unsigned char *id, int len);
+unsigned char *X509_alias_get0(X509 *x, int *len);
+unsigned char *X509_keyid_get0(X509 *x, int *len);
+
+DECLARE_ASN1_FUNCTIONS(X509_REVOKED)
+DECLARE_ASN1_FUNCTIONS(X509_CRL_INFO)
+DECLARE_ASN1_FUNCTIONS(X509_CRL)
+X509_CRL *X509_CRL_new_ex(OSSL_LIB_CTX *libctx, const char *propq);
+
+int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
+int X509_CRL_get0_by_serial(X509_CRL *crl,
+ X509_REVOKED **ret, const ASN1_INTEGER *serial);
+int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x);
+
+X509_PKEY *X509_PKEY_new(void);
+void X509_PKEY_free(X509_PKEY *a);
+
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKI)
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKAC)
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE)
+
+X509_INFO *X509_INFO_new(void);
+void X509_INFO_free(X509_INFO *a);
+char *X509_NAME_oneline(const X509_NAME *a, char *buf, int size);
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+OSSL_DEPRECATEDIN_3_0
+int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *algor1,
+ ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey);
+OSSL_DEPRECATEDIN_3_0
+int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
+ unsigned char *md, unsigned int *len);
+OSSL_DEPRECATEDIN_3_0
+int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
+ ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey,
+ const EVP_MD *type);
+#endif
+int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *data,
+ unsigned char *md, unsigned int *len);
+int ASN1_item_verify(const ASN1_ITEM *it, const X509_ALGOR *alg,
+ const ASN1_BIT_STRING *signature, const void *data,
+ EVP_PKEY *pkey);
+int ASN1_item_verify_ctx(const ASN1_ITEM *it, const X509_ALGOR *alg,
+ const ASN1_BIT_STRING *signature, const void *data,
+ EVP_MD_CTX *ctx);
+int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
+ ASN1_BIT_STRING *signature, const void *data,
+ EVP_PKEY *pkey, const EVP_MD *md);
+int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1,
+ X509_ALGOR *algor2, ASN1_BIT_STRING *signature,
+ const void *data, EVP_MD_CTX *ctx);
+
+#define X509_VERSION_1 0
+#define X509_VERSION_2 1
+#define X509_VERSION_3 2
+
+long X509_get_version(const X509 *x);
+int X509_set_version(X509 *x, long version);
+int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial);
+ASN1_INTEGER *X509_get_serialNumber(X509 *x);
+const ASN1_INTEGER *X509_get0_serialNumber(const X509 *x);
+int X509_set_issuer_name(X509 *x, const X509_NAME *name);
+X509_NAME *X509_get_issuer_name(const X509 *a);
+int X509_set_subject_name(X509 *x, const X509_NAME *name);
+X509_NAME *X509_get_subject_name(const X509 *a);
+const ASN1_TIME * X509_get0_notBefore(const X509 *x);
+ASN1_TIME *X509_getm_notBefore(const X509 *x);
+int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm);
+const ASN1_TIME *X509_get0_notAfter(const X509 *x);
+ASN1_TIME *X509_getm_notAfter(const X509 *x);
+int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm);
+int X509_set_pubkey(X509 *x, EVP_PKEY *pkey);
+int X509_up_ref(X509 *x);
+int X509_get_signature_type(const X509 *x);
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define X509_get_notBefore X509_getm_notBefore
+# define X509_get_notAfter X509_getm_notAfter
+# define X509_set_notBefore X509_set1_notBefore
+# define X509_set_notAfter X509_set1_notAfter
+#endif
+
+
+/*
+ * This one is only used so that a binary form can output, as in
+ * i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &buf)
+ */
+X509_PUBKEY *X509_get_X509_PUBKEY(const X509 *x);
+const STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x);
+void X509_get0_uids(const X509 *x, const ASN1_BIT_STRING **piuid,
+ const ASN1_BIT_STRING **psuid);
+const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x);
+
+EVP_PKEY *X509_get0_pubkey(const X509 *x);
+EVP_PKEY *X509_get_pubkey(X509 *x);
+ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x);
+
+#define X509_REQ_VERSION_1 0
+
+long X509_REQ_get_version(const X509_REQ *req);
+int X509_REQ_set_version(X509_REQ *x, long version);
+X509_NAME *X509_REQ_get_subject_name(const X509_REQ *req);
+int X509_REQ_set_subject_name(X509_REQ *req, const X509_NAME *name);
+void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig,
+ const X509_ALGOR **palg);
+void X509_REQ_set0_signature(X509_REQ *req, ASN1_BIT_STRING *psig);
+int X509_REQ_set1_signature_algo(X509_REQ *req, X509_ALGOR *palg);
+int X509_REQ_get_signature_nid(const X509_REQ *req);
+int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp);
+int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey);
+EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req);
+EVP_PKEY *X509_REQ_get0_pubkey(X509_REQ *req);
+X509_PUBKEY *X509_REQ_get_X509_PUBKEY(X509_REQ *req);
+int X509_REQ_extension_nid(int nid);
+int *X509_REQ_get_extension_nids(void);
+void X509_REQ_set_extension_nids(int *nids);
+STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req);
+int X509_REQ_add_extensions_nid(X509_REQ *req,
+ const STACK_OF(X509_EXTENSION) *exts, int nid);
+int X509_REQ_add_extensions(X509_REQ *req, const STACK_OF(X509_EXTENSION) *ext);
+int X509_REQ_get_attr_count(const X509_REQ *req);
+int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos);
+int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, const ASN1_OBJECT *obj,
+ int lastpos);
+X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc);
+X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc);
+int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr);
+int X509_REQ_add1_attr_by_OBJ(X509_REQ *req,
+ const ASN1_OBJECT *obj, int type,
+ const unsigned char *bytes, int len);
+int X509_REQ_add1_attr_by_NID(X509_REQ *req,
+ int nid, int type,
+ const unsigned char *bytes, int len);
+int X509_REQ_add1_attr_by_txt(X509_REQ *req,
+ const char *attrname, int type,
+ const unsigned char *bytes, int len);
+
+#define X509_CRL_VERSION_1 0
+#define X509_CRL_VERSION_2 1
+
+int X509_CRL_set_version(X509_CRL *x, long version);
+int X509_CRL_set_issuer_name(X509_CRL *x, const X509_NAME *name);
+int X509_CRL_set1_lastUpdate(X509_CRL *x, const ASN1_TIME *tm);
+int X509_CRL_set1_nextUpdate(X509_CRL *x, const ASN1_TIME *tm);
+int X509_CRL_sort(X509_CRL *crl);
+int X509_CRL_up_ref(X509_CRL *crl);
+
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define X509_CRL_set_lastUpdate X509_CRL_set1_lastUpdate
+# define X509_CRL_set_nextUpdate X509_CRL_set1_nextUpdate
+#endif
+
+long X509_CRL_get_version(const X509_CRL *crl);
+const ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *crl);
+const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl);
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
+OSSL_DEPRECATEDIN_1_1_0 ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *crl);
+OSSL_DEPRECATEDIN_1_1_0 ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *crl);
+#endif
+X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl);
+const STACK_OF(X509_EXTENSION) *X509_CRL_get0_extensions(const X509_CRL *crl);
+STACK_OF(X509_REVOKED) *X509_CRL_get_REVOKED(X509_CRL *crl);
+void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig,
+ const X509_ALGOR **palg);
+int X509_CRL_get_signature_nid(const X509_CRL *crl);
+int i2d_re_X509_CRL_tbs(X509_CRL *req, unsigned char **pp);
+
+const ASN1_INTEGER *X509_REVOKED_get0_serialNumber(const X509_REVOKED *x);
+int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial);
+const ASN1_TIME *X509_REVOKED_get0_revocationDate(const X509_REVOKED *x);
+int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm);
+const STACK_OF(X509_EXTENSION) *
+X509_REVOKED_get0_extensions(const X509_REVOKED *r);
+
+X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
+ EVP_PKEY *skey, const EVP_MD *md, unsigned int flags);
+
+int X509_REQ_check_private_key(X509_REQ *x509, EVP_PKEY *pkey);
+
+int X509_check_private_key(const X509 *x509, const EVP_PKEY *pkey);
+int X509_chain_check_suiteb(int *perror_depth,
+ X509 *x, STACK_OF(X509) *chain,
+ unsigned long flags);
+int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags);
+STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain);
+
+int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b);
+unsigned long X509_issuer_and_serial_hash(X509 *a);
+
+int X509_issuer_name_cmp(const X509 *a, const X509 *b);
+unsigned long X509_issuer_name_hash(X509 *a);
+
+int X509_subject_name_cmp(const X509 *a, const X509 *b);
+unsigned long X509_subject_name_hash(X509 *x);
+
+# ifndef OPENSSL_NO_MD5
+unsigned long X509_issuer_name_hash_old(X509 *a);
+unsigned long X509_subject_name_hash_old(X509 *x);
+# endif
+
+# define X509_ADD_FLAG_DEFAULT 0
+# define X509_ADD_FLAG_UP_REF 0x1
+# define X509_ADD_FLAG_PREPEND 0x2
+# define X509_ADD_FLAG_NO_DUP 0x4
+# define X509_ADD_FLAG_NO_SS 0x8
+int X509_add_cert(STACK_OF(X509) *sk, X509 *cert, int flags);
+int X509_add_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs, int flags);
+
+int X509_cmp(const X509 *a, const X509 *b);
+int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+# define X509_NAME_hash(x) X509_NAME_hash_ex(x, NULL, NULL, NULL)
+OSSL_DEPRECATEDIN_3_0 int X509_certificate_type(const X509 *x,
+ const EVP_PKEY *pubkey);
+#endif
+unsigned long X509_NAME_hash_ex(const X509_NAME *x, OSSL_LIB_CTX *libctx,
+ const char *propq, int *ok);
+unsigned long X509_NAME_hash_old(const X509_NAME *x);
+
+int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b);
+int X509_CRL_match(const X509_CRL *a, const X509_CRL *b);
+int X509_aux_print(BIO *out, X509 *x, int indent);
+# ifndef OPENSSL_NO_STDIO
+int X509_print_ex_fp(FILE *bp, X509 *x, unsigned long nmflag,
+ unsigned long cflag);
+int X509_print_fp(FILE *bp, X509 *x);
+int X509_CRL_print_fp(FILE *bp, X509_CRL *x);
+int X509_REQ_print_fp(FILE *bp, X509_REQ *req);
+int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent,
+ unsigned long flags);
+# endif
+
+int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase);
+int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent,
+ unsigned long flags);
+int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflag,
+ unsigned long cflag);
+int X509_print(BIO *bp, X509 *x);
+int X509_ocspid_print(BIO *bp, X509 *x);
+int X509_CRL_print_ex(BIO *out, X509_CRL *x, unsigned long nmflag);
+int X509_CRL_print(BIO *bp, X509_CRL *x);
+int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflag,
+ unsigned long cflag);
+int X509_REQ_print(BIO *bp, X509_REQ *req);
+
+int X509_NAME_entry_count(const X509_NAME *name);
+int X509_NAME_get_text_by_NID(const X509_NAME *name, int nid,
+ char *buf, int len);
+int X509_NAME_get_text_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj,
+ char *buf, int len);
+
+/*
+ * NOTE: you should be passing -1, not 0 as lastpos. The functions that use
+ * lastpos, search after that position on.
+ */
+int X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, int lastpos);
+int X509_NAME_get_index_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj,
+ int lastpos);
+X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc);
+X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc);
+int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne,
+ int loc, int set);
+int X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int type,
+ const unsigned char *bytes, int len, int loc,
+ int set);
+int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
+ const unsigned char *bytes, int len, int loc,
+ int set);
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
+ const char *field, int type,
+ const unsigned char *bytes,
+ int len);
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
+ int type,
+ const unsigned char *bytes,
+ int len);
+int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
+ const unsigned char *bytes, int len, int loc,
+ int set);
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
+ const ASN1_OBJECT *obj, int type,
+ const unsigned char *bytes,
+ int len);
+int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj);
+int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
+ const unsigned char *bytes, int len);
+ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne);
+ASN1_STRING * X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne);
+int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne);
+
+int X509_NAME_get0_der(const X509_NAME *nm, const unsigned char **pder,
+ size_t *pderlen);
+
+int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x);
+int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x,
+ int nid, int lastpos);
+int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *x,
+ const ASN1_OBJECT *obj, int lastpos);
+int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *x,
+ int crit, int lastpos);
+X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc);
+X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc);
+STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x,
+ X509_EXTENSION *ex, int loc);
+
+int X509_get_ext_count(const X509 *x);
+int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos);
+int X509_get_ext_by_OBJ(const X509 *x, const ASN1_OBJECT *obj, int lastpos);
+int X509_get_ext_by_critical(const X509 *x, int crit, int lastpos);
+X509_EXTENSION *X509_get_ext(const X509 *x, int loc);
+X509_EXTENSION *X509_delete_ext(X509 *x, int loc);
+int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
+void *X509_get_ext_d2i(const X509 *x, int nid, int *crit, int *idx);
+int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit,
+ unsigned long flags);
+
+int X509_CRL_get_ext_count(const X509_CRL *x);
+int X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, int lastpos);
+int X509_CRL_get_ext_by_OBJ(const X509_CRL *x, const ASN1_OBJECT *obj,
+ int lastpos);
+int X509_CRL_get_ext_by_critical(const X509_CRL *x, int crit, int lastpos);
+X509_EXTENSION *X509_CRL_get_ext(const X509_CRL *x, int loc);
+X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc);
+int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc);
+void *X509_CRL_get_ext_d2i(const X509_CRL *x, int nid, int *crit, int *idx);
+int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit,
+ unsigned long flags);
+
+int X509_REVOKED_get_ext_count(const X509_REVOKED *x);
+int X509_REVOKED_get_ext_by_NID(const X509_REVOKED *x, int nid, int lastpos);
+int X509_REVOKED_get_ext_by_OBJ(const X509_REVOKED *x, const ASN1_OBJECT *obj,
+ int lastpos);
+int X509_REVOKED_get_ext_by_critical(const X509_REVOKED *x, int crit,
+ int lastpos);
+X509_EXTENSION *X509_REVOKED_get_ext(const X509_REVOKED *x, int loc);
+X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc);
+int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc);
+void *X509_REVOKED_get_ext_d2i(const X509_REVOKED *x, int nid, int *crit,
+ int *idx);
+int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit,
+ unsigned long flags);
+
+X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex,
+ int nid, int crit,
+ ASN1_OCTET_STRING *data);
+X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex,
+ const ASN1_OBJECT *obj, int crit,
+ ASN1_OCTET_STRING *data);
+int X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj);
+int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit);
+int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data);
+ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex);
+ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne);
+int X509_EXTENSION_get_critical(const X509_EXTENSION *ex);
+
+int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x);
+int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
+ int lastpos);
+int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk,
+ const ASN1_OBJECT *obj, int lastpos);
+X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc);
+X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc);
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
+ X509_ATTRIBUTE *attr);
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE)
+ **x, const ASN1_OBJECT *obj,
+ int type,
+ const unsigned char *bytes,
+ int len);
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE)
+ **x, int nid, int type,
+ const unsigned char *bytes,
+ int len);
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE)
+ **x, const char *attrname,
+ int type,
+ const unsigned char *bytes,
+ int len);
+void *X509at_get0_data_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *x,
+ const ASN1_OBJECT *obj, int lastpos, int type);
+X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
+ int atrtype, const void *data,
+ int len);
+X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
+ const ASN1_OBJECT *obj,
+ int atrtype, const void *data,
+ int len);
+X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr,
+ const char *atrname, int type,
+ const unsigned char *bytes,
+ int len);
+int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj);
+int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype,
+ const void *data, int len);
+void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, int atrtype,
+ void *data);
+int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr);
+ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr);
+ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx);
+
+int EVP_PKEY_get_attr_count(const EVP_PKEY *key);
+int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid, int lastpos);
+int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, const ASN1_OBJECT *obj,
+ int lastpos);
+X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc);
+X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc);
+int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr);
+int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key,
+ const ASN1_OBJECT *obj, int type,
+ const unsigned char *bytes, int len);
+int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key,
+ int nid, int type,
+ const unsigned char *bytes, int len);
+int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key,
+ const char *attrname, int type,
+ const unsigned char *bytes, int len);
+
+/* lookup a cert from a X509 STACK */
+X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, const X509_NAME *name,
+ const ASN1_INTEGER *serial);
+X509 *X509_find_by_subject(STACK_OF(X509) *sk, const X509_NAME *name);
+
+DECLARE_ASN1_FUNCTIONS(PBEPARAM)
+DECLARE_ASN1_FUNCTIONS(PBE2PARAM)
+DECLARE_ASN1_FUNCTIONS(PBKDF2PARAM)
+#ifndef OPENSSL_NO_SCRYPT
+DECLARE_ASN1_FUNCTIONS(SCRYPT_PARAMS)
+#endif
+
+int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
+ const unsigned char *salt, int saltlen);
+int PKCS5_pbe_set0_algor_ex(X509_ALGOR *algor, int alg, int iter,
+ const unsigned char *salt, int saltlen,
+ OSSL_LIB_CTX *libctx);
+
+X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
+ const unsigned char *salt, int saltlen);
+X509_ALGOR *PKCS5_pbe_set_ex(int alg, int iter,
+ const unsigned char *salt, int saltlen,
+ OSSL_LIB_CTX *libctx);
+
+X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
+ unsigned char *salt, int saltlen);
+X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
+ unsigned char *salt, int saltlen,
+ unsigned char *aiv, int prf_nid);
+X509_ALGOR *PKCS5_pbe2_set_iv_ex(const EVP_CIPHER *cipher, int iter,
+ unsigned char *salt, int saltlen,
+ unsigned char *aiv, int prf_nid,
+ OSSL_LIB_CTX *libctx);
+
+#ifndef OPENSSL_NO_SCRYPT
+X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
+ const unsigned char *salt, int saltlen,
+ unsigned char *aiv, uint64_t N, uint64_t r,
+ uint64_t p);
+#endif
+
+X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
+ int prf_nid, int keylen);
+X509_ALGOR *PKCS5_pbkdf2_set_ex(int iter, unsigned char *salt, int saltlen,
+ int prf_nid, int keylen,
+ OSSL_LIB_CTX *libctx);
+
+/* PKCS#8 utilities */
+
+DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
+
+EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8);
+EVP_PKEY *EVP_PKCS82PKEY_ex(const PKCS8_PRIV_KEY_INFO *p8, OSSL_LIB_CTX *libctx,
+ const char *propq);
+PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(const EVP_PKEY *pkey);
+
+int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj,
+ int version, int ptype, void *pval,
+ unsigned char *penc, int penclen);
+int PKCS8_pkey_get0(const ASN1_OBJECT **ppkalg,
+ const unsigned char **pk, int *ppklen,
+ const X509_ALGOR **pa, const PKCS8_PRIV_KEY_INFO *p8);
+
+const STACK_OF(X509_ATTRIBUTE) *
+PKCS8_pkey_get0_attrs(const PKCS8_PRIV_KEY_INFO *p8);
+int PKCS8_pkey_add1_attr(PKCS8_PRIV_KEY_INFO *p8, X509_ATTRIBUTE *attr);
+int PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type,
+ const unsigned char *bytes, int len);
+int PKCS8_pkey_add1_attr_by_OBJ(PKCS8_PRIV_KEY_INFO *p8, const ASN1_OBJECT *obj,
+ int type, const unsigned char *bytes, int len);
+
+
+int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj,
+ int ptype, void *pval,
+ unsigned char *penc, int penclen);
+int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg,
+ const unsigned char **pk, int *ppklen,
+ X509_ALGOR **pa, const X509_PUBKEY *pub);
+int X509_PUBKEY_eq(const X509_PUBKEY *a, const X509_PUBKEY *b);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/x509_vfy.h b/include/openssl/x509_vfy.h
deleted file mode 100644
index 25c79f1be2f0..000000000000
--- a/include/openssl/x509_vfy.h
+++ /dev/null
@@ -1,632 +0,0 @@
-/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_X509_VFY_H
-# define HEADER_X509_VFY_H
-
-/*
- * Protect against recursion, x509.h and x509_vfy.h each include the other.
- */
-# ifndef HEADER_X509_H
-# include <openssl/x509.h>
-# endif
-
-# include <openssl/opensslconf.h>
-# include <openssl/lhash.h>
-# include <openssl/bio.h>
-# include <openssl/crypto.h>
-# include <openssl/symhacks.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*-
-SSL_CTX -> X509_STORE
- -> X509_LOOKUP
- ->X509_LOOKUP_METHOD
- -> X509_LOOKUP
- ->X509_LOOKUP_METHOD
-
-SSL -> X509_STORE_CTX
- ->X509_STORE
-
-The X509_STORE holds the tables etc for verification stuff.
-A X509_STORE_CTX is used while validating a single certificate.
-The X509_STORE has X509_LOOKUPs for looking up certs.
-The X509_STORE then calls a function to actually verify the
-certificate chain.
-*/
-
-typedef enum {
- X509_LU_NONE = 0,
- X509_LU_X509, X509_LU_CRL
-} X509_LOOKUP_TYPE;
-
-#if OPENSSL_API_COMPAT < 0x10100000L
-#define X509_LU_RETRY -1
-#define X509_LU_FAIL 0
-#endif
-
-DEFINE_STACK_OF(X509_LOOKUP)
-DEFINE_STACK_OF(X509_OBJECT)
-DEFINE_STACK_OF(X509_VERIFY_PARAM)
-
-int X509_STORE_set_depth(X509_STORE *store, int depth);
-
-typedef int (*X509_STORE_CTX_verify_cb)(int, X509_STORE_CTX *);
-typedef int (*X509_STORE_CTX_verify_fn)(X509_STORE_CTX *);
-typedef int (*X509_STORE_CTX_get_issuer_fn)(X509 **issuer,
- X509_STORE_CTX *ctx, X509 *x);
-typedef int (*X509_STORE_CTX_check_issued_fn)(X509_STORE_CTX *ctx,
- X509 *x, X509 *issuer);
-typedef int (*X509_STORE_CTX_check_revocation_fn)(X509_STORE_CTX *ctx);
-typedef int (*X509_STORE_CTX_get_crl_fn)(X509_STORE_CTX *ctx,
- X509_CRL **crl, X509 *x);
-typedef int (*X509_STORE_CTX_check_crl_fn)(X509_STORE_CTX *ctx, X509_CRL *crl);
-typedef int (*X509_STORE_CTX_cert_crl_fn)(X509_STORE_CTX *ctx,
- X509_CRL *crl, X509 *x);
-typedef int (*X509_STORE_CTX_check_policy_fn)(X509_STORE_CTX *ctx);
-typedef STACK_OF(X509) *(*X509_STORE_CTX_lookup_certs_fn)(X509_STORE_CTX *ctx,
- X509_NAME *nm);
-typedef STACK_OF(X509_CRL) *(*X509_STORE_CTX_lookup_crls_fn)(X509_STORE_CTX *ctx,
- X509_NAME *nm);
-typedef int (*X509_STORE_CTX_cleanup_fn)(X509_STORE_CTX *ctx);
-
-
-void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
-
-# define X509_STORE_CTX_set_app_data(ctx,data) \
- X509_STORE_CTX_set_ex_data(ctx,0,data)
-# define X509_STORE_CTX_get_app_data(ctx) \
- X509_STORE_CTX_get_ex_data(ctx,0)
-
-# define X509_L_FILE_LOAD 1
-# define X509_L_ADD_DIR 2
-
-# define X509_LOOKUP_load_file(x,name,type) \
- X509_LOOKUP_ctrl((x),X509_L_FILE_LOAD,(name),(long)(type),NULL)
-
-# define X509_LOOKUP_add_dir(x,name,type) \
- X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL)
-
-# define X509_V_OK 0
-# define X509_V_ERR_UNSPECIFIED 1
-# define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2
-# define X509_V_ERR_UNABLE_TO_GET_CRL 3
-# define X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE 4
-# define X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE 5
-# define X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY 6
-# define X509_V_ERR_CERT_SIGNATURE_FAILURE 7
-# define X509_V_ERR_CRL_SIGNATURE_FAILURE 8
-# define X509_V_ERR_CERT_NOT_YET_VALID 9
-# define X509_V_ERR_CERT_HAS_EXPIRED 10
-# define X509_V_ERR_CRL_NOT_YET_VALID 11
-# define X509_V_ERR_CRL_HAS_EXPIRED 12
-# define X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD 13
-# define X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD 14
-# define X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD 15
-# define X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD 16
-# define X509_V_ERR_OUT_OF_MEM 17
-# define X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT 18
-# define X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN 19
-# define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 20
-# define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21
-# define X509_V_ERR_CERT_CHAIN_TOO_LONG 22
-# define X509_V_ERR_CERT_REVOKED 23
-# define X509_V_ERR_INVALID_CA 24
-# define X509_V_ERR_PATH_LENGTH_EXCEEDED 25
-# define X509_V_ERR_INVALID_PURPOSE 26
-# define X509_V_ERR_CERT_UNTRUSTED 27
-# define X509_V_ERR_CERT_REJECTED 28
-/* These are 'informational' when looking for issuer cert */
-# define X509_V_ERR_SUBJECT_ISSUER_MISMATCH 29
-# define X509_V_ERR_AKID_SKID_MISMATCH 30
-# define X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH 31
-# define X509_V_ERR_KEYUSAGE_NO_CERTSIGN 32
-# define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER 33
-# define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34
-# define X509_V_ERR_KEYUSAGE_NO_CRL_SIGN 35
-# define X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION 36
-# define X509_V_ERR_INVALID_NON_CA 37
-# define X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED 38
-# define X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE 39
-# define X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED 40
-# define X509_V_ERR_INVALID_EXTENSION 41
-# define X509_V_ERR_INVALID_POLICY_EXTENSION 42
-# define X509_V_ERR_NO_EXPLICIT_POLICY 43
-# define X509_V_ERR_DIFFERENT_CRL_SCOPE 44
-# define X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE 45
-# define X509_V_ERR_UNNESTED_RESOURCE 46
-# define X509_V_ERR_PERMITTED_VIOLATION 47
-# define X509_V_ERR_EXCLUDED_VIOLATION 48
-# define X509_V_ERR_SUBTREE_MINMAX 49
-/* The application is not happy */
-# define X509_V_ERR_APPLICATION_VERIFICATION 50
-# define X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE 51
-# define X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX 52
-# define X509_V_ERR_UNSUPPORTED_NAME_SYNTAX 53
-# define X509_V_ERR_CRL_PATH_VALIDATION_ERROR 54
-/* Another issuer check debug option */
-# define X509_V_ERR_PATH_LOOP 55
-/* Suite B mode algorithm violation */
-# define X509_V_ERR_SUITE_B_INVALID_VERSION 56
-# define X509_V_ERR_SUITE_B_INVALID_ALGORITHM 57
-# define X509_V_ERR_SUITE_B_INVALID_CURVE 58
-# define X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM 59
-# define X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED 60
-# define X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 61
-/* Host, email and IP check errors */
-# define X509_V_ERR_HOSTNAME_MISMATCH 62
-# define X509_V_ERR_EMAIL_MISMATCH 63
-# define X509_V_ERR_IP_ADDRESS_MISMATCH 64
-/* DANE TLSA errors */
-# define X509_V_ERR_DANE_NO_MATCH 65
-/* security level errors */
-# define X509_V_ERR_EE_KEY_TOO_SMALL 66
-# define X509_V_ERR_CA_KEY_TOO_SMALL 67
-# define X509_V_ERR_CA_MD_TOO_WEAK 68
-/* Caller error */
-# define X509_V_ERR_INVALID_CALL 69
-/* Issuer lookup error */
-# define X509_V_ERR_STORE_LOOKUP 70
-/* Certificate transparency */
-# define X509_V_ERR_NO_VALID_SCTS 71
-
-# define X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION 72
-/* OCSP status errors */
-# define X509_V_ERR_OCSP_VERIFY_NEEDED 73 /* Need OCSP verification */
-# define X509_V_ERR_OCSP_VERIFY_FAILED 74 /* Couldn't verify cert through OCSP */
-# define X509_V_ERR_OCSP_CERT_UNKNOWN 75 /* Certificate wasn't recognized by the OCSP responder */
-# define X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH 76
-# define X509_V_ERR_NO_ISSUER_PUBLIC_KEY 77
-# define X509_V_ERR_UNSUPPORTED_SIGNATURE_ALGORITHM 78
-# define X509_V_ERR_EC_KEY_EXPLICIT_PARAMS 79
-
-/* Certificate verify flags */
-
-# if OPENSSL_API_COMPAT < 0x10100000L
-# define X509_V_FLAG_CB_ISSUER_CHECK 0x0 /* Deprecated */
-# endif
-/* Use check time instead of current time */
-# define X509_V_FLAG_USE_CHECK_TIME 0x2
-/* Lookup CRLs */
-# define X509_V_FLAG_CRL_CHECK 0x4
-/* Lookup CRLs for whole chain */
-# define X509_V_FLAG_CRL_CHECK_ALL 0x8
-/* Ignore unhandled critical extensions */
-# define X509_V_FLAG_IGNORE_CRITICAL 0x10
-/* Disable workarounds for broken certificates */
-# define X509_V_FLAG_X509_STRICT 0x20
-/* Enable proxy certificate validation */
-# define X509_V_FLAG_ALLOW_PROXY_CERTS 0x40
-/* Enable policy checking */
-# define X509_V_FLAG_POLICY_CHECK 0x80
-/* Policy variable require-explicit-policy */
-# define X509_V_FLAG_EXPLICIT_POLICY 0x100
-/* Policy variable inhibit-any-policy */
-# define X509_V_FLAG_INHIBIT_ANY 0x200
-/* Policy variable inhibit-policy-mapping */
-# define X509_V_FLAG_INHIBIT_MAP 0x400
-/* Notify callback that policy is OK */
-# define X509_V_FLAG_NOTIFY_POLICY 0x800
-/* Extended CRL features such as indirect CRLs, alternate CRL signing keys */
-# define X509_V_FLAG_EXTENDED_CRL_SUPPORT 0x1000
-/* Delta CRL support */
-# define X509_V_FLAG_USE_DELTAS 0x2000
-/* Check self-signed CA signature */
-# define X509_V_FLAG_CHECK_SS_SIGNATURE 0x4000
-/* Use trusted store first */
-# define X509_V_FLAG_TRUSTED_FIRST 0x8000
-/* Suite B 128 bit only mode: not normally used */
-# define X509_V_FLAG_SUITEB_128_LOS_ONLY 0x10000
-/* Suite B 192 bit only mode */
-# define X509_V_FLAG_SUITEB_192_LOS 0x20000
-/* Suite B 128 bit mode allowing 192 bit algorithms */
-# define X509_V_FLAG_SUITEB_128_LOS 0x30000
-/* Allow partial chains if at least one certificate is in trusted store */
-# define X509_V_FLAG_PARTIAL_CHAIN 0x80000
-/*
- * If the initial chain is not trusted, do not attempt to build an alternative
- * chain. Alternate chain checking was introduced in 1.1.0. Setting this flag
- * will force the behaviour to match that of previous versions.
- */
-# define X509_V_FLAG_NO_ALT_CHAINS 0x100000
-/* Do not check certificate/CRL validity against current time */
-# define X509_V_FLAG_NO_CHECK_TIME 0x200000
-
-# define X509_VP_FLAG_DEFAULT 0x1
-# define X509_VP_FLAG_OVERWRITE 0x2
-# define X509_VP_FLAG_RESET_FLAGS 0x4
-# define X509_VP_FLAG_LOCKED 0x8
-# define X509_VP_FLAG_ONCE 0x10
-
-/* Internal use: mask of policy related options */
-# define X509_V_FLAG_POLICY_MASK (X509_V_FLAG_POLICY_CHECK \
- | X509_V_FLAG_EXPLICIT_POLICY \
- | X509_V_FLAG_INHIBIT_ANY \
- | X509_V_FLAG_INHIBIT_MAP)
-
-int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
- X509_NAME *name);
-X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
- X509_LOOKUP_TYPE type,
- X509_NAME *name);
-X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
- X509_OBJECT *x);
-int X509_OBJECT_up_ref_count(X509_OBJECT *a);
-X509_OBJECT *X509_OBJECT_new(void);
-void X509_OBJECT_free(X509_OBJECT *a);
-X509_LOOKUP_TYPE X509_OBJECT_get_type(const X509_OBJECT *a);
-X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a);
-int X509_OBJECT_set1_X509(X509_OBJECT *a, X509 *obj);
-X509_CRL *X509_OBJECT_get0_X509_CRL(X509_OBJECT *a);
-int X509_OBJECT_set1_X509_CRL(X509_OBJECT *a, X509_CRL *obj);
-X509_STORE *X509_STORE_new(void);
-void X509_STORE_free(X509_STORE *v);
-int X509_STORE_lock(X509_STORE *ctx);
-int X509_STORE_unlock(X509_STORE *ctx);
-int X509_STORE_up_ref(X509_STORE *v);
-STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *v);
-
-STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *st, X509_NAME *nm);
-STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *st, X509_NAME *nm);
-int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags);
-int X509_STORE_set_purpose(X509_STORE *ctx, int purpose);
-int X509_STORE_set_trust(X509_STORE *ctx, int trust);
-int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm);
-X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx);
-
-void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify);
-#define X509_STORE_set_verify_func(ctx, func) \
- X509_STORE_set_verify((ctx),(func))
-void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx,
- X509_STORE_CTX_verify_fn verify);
-X509_STORE_CTX_verify_fn X509_STORE_get_verify(X509_STORE *ctx);
-void X509_STORE_set_verify_cb(X509_STORE *ctx,
- X509_STORE_CTX_verify_cb verify_cb);
-# define X509_STORE_set_verify_cb_func(ctx,func) \
- X509_STORE_set_verify_cb((ctx),(func))
-X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(X509_STORE *ctx);
-void X509_STORE_set_get_issuer(X509_STORE *ctx,
- X509_STORE_CTX_get_issuer_fn get_issuer);
-X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(X509_STORE *ctx);
-void X509_STORE_set_check_issued(X509_STORE *ctx,
- X509_STORE_CTX_check_issued_fn check_issued);
-X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(X509_STORE *ctx);
-void X509_STORE_set_check_revocation(X509_STORE *ctx,
- X509_STORE_CTX_check_revocation_fn check_revocation);
-X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(X509_STORE *ctx);
-void X509_STORE_set_get_crl(X509_STORE *ctx,
- X509_STORE_CTX_get_crl_fn get_crl);
-X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(X509_STORE *ctx);
-void X509_STORE_set_check_crl(X509_STORE *ctx,
- X509_STORE_CTX_check_crl_fn check_crl);
-X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(X509_STORE *ctx);
-void X509_STORE_set_cert_crl(X509_STORE *ctx,
- X509_STORE_CTX_cert_crl_fn cert_crl);
-X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(X509_STORE *ctx);
-void X509_STORE_set_check_policy(X509_STORE *ctx,
- X509_STORE_CTX_check_policy_fn check_policy);
-X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(X509_STORE *ctx);
-void X509_STORE_set_lookup_certs(X509_STORE *ctx,
- X509_STORE_CTX_lookup_certs_fn lookup_certs);
-X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(X509_STORE *ctx);
-void X509_STORE_set_lookup_crls(X509_STORE *ctx,
- X509_STORE_CTX_lookup_crls_fn lookup_crls);
-#define X509_STORE_set_lookup_crls_cb(ctx, func) \
- X509_STORE_set_lookup_crls((ctx), (func))
-X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(X509_STORE *ctx);
-void X509_STORE_set_cleanup(X509_STORE *ctx,
- X509_STORE_CTX_cleanup_fn cleanup);
-X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(X509_STORE *ctx);
-
-#define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef) \
- CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, l, p, newf, dupf, freef)
-int X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data);
-void *X509_STORE_get_ex_data(X509_STORE *ctx, int idx);
-
-X509_STORE_CTX *X509_STORE_CTX_new(void);
-
-int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
-
-void X509_STORE_CTX_free(X509_STORE_CTX *ctx);
-int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store,
- X509 *x509, STACK_OF(X509) *chain);
-void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
-void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx);
-
-X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx);
-X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx);
-STACK_OF(X509)* X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx);
-void X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
-void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
- X509_STORE_CTX_verify_cb verify);
-X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx);
-X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx);
-X509_STORE_CTX_get_issuer_fn X509_STORE_CTX_get_get_issuer(X509_STORE_CTX *ctx);
-X509_STORE_CTX_check_issued_fn X509_STORE_CTX_get_check_issued(X509_STORE_CTX *ctx);
-X509_STORE_CTX_check_revocation_fn X509_STORE_CTX_get_check_revocation(X509_STORE_CTX *ctx);
-X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(X509_STORE_CTX *ctx);
-X509_STORE_CTX_check_crl_fn X509_STORE_CTX_get_check_crl(X509_STORE_CTX *ctx);
-X509_STORE_CTX_cert_crl_fn X509_STORE_CTX_get_cert_crl(X509_STORE_CTX *ctx);
-X509_STORE_CTX_check_policy_fn X509_STORE_CTX_get_check_policy(X509_STORE_CTX *ctx);
-X509_STORE_CTX_lookup_certs_fn X509_STORE_CTX_get_lookup_certs(X509_STORE_CTX *ctx);
-X509_STORE_CTX_lookup_crls_fn X509_STORE_CTX_get_lookup_crls(X509_STORE_CTX *ctx);
-X509_STORE_CTX_cleanup_fn X509_STORE_CTX_get_cleanup(X509_STORE_CTX *ctx);
-
-#if OPENSSL_API_COMPAT < 0x10100000L
-# define X509_STORE_CTX_get_chain X509_STORE_CTX_get0_chain
-# define X509_STORE_CTX_set_chain X509_STORE_CTX_set0_untrusted
-# define X509_STORE_CTX_trusted_stack X509_STORE_CTX_set0_trusted_stack
-# define X509_STORE_get_by_subject X509_STORE_CTX_get_by_subject
-# define X509_STORE_get1_certs X509_STORE_CTX_get1_certs
-# define X509_STORE_get1_crls X509_STORE_CTX_get1_crls
-/* the following macro is misspelled; use X509_STORE_get1_certs instead */
-# define X509_STORE_get1_cert X509_STORE_CTX_get1_certs
-/* the following macro is misspelled; use X509_STORE_get1_crls instead */
-# define X509_STORE_get1_crl X509_STORE_CTX_get1_crls
-#endif
-
-X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m);
-X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void);
-X509_LOOKUP_METHOD *X509_LOOKUP_file(void);
-
-typedef int (*X509_LOOKUP_ctrl_fn)(X509_LOOKUP *ctx, int cmd, const char *argc,
- long argl, char **ret);
-typedef int (*X509_LOOKUP_get_by_subject_fn)(X509_LOOKUP *ctx,
- X509_LOOKUP_TYPE type,
- X509_NAME *name,
- X509_OBJECT *ret);
-typedef int (*X509_LOOKUP_get_by_issuer_serial_fn)(X509_LOOKUP *ctx,
- X509_LOOKUP_TYPE type,
- X509_NAME *name,
- ASN1_INTEGER *serial,
- X509_OBJECT *ret);
-typedef int (*X509_LOOKUP_get_by_fingerprint_fn)(X509_LOOKUP *ctx,
- X509_LOOKUP_TYPE type,
- const unsigned char* bytes,
- int len,
- X509_OBJECT *ret);
-typedef int (*X509_LOOKUP_get_by_alias_fn)(X509_LOOKUP *ctx,
- X509_LOOKUP_TYPE type,
- const char *str,
- int len,
- X509_OBJECT *ret);
-
-X509_LOOKUP_METHOD *X509_LOOKUP_meth_new(const char *name);
-void X509_LOOKUP_meth_free(X509_LOOKUP_METHOD *method);
-
-int X509_LOOKUP_meth_set_new_item(X509_LOOKUP_METHOD *method,
- int (*new_item) (X509_LOOKUP *ctx));
-int (*X509_LOOKUP_meth_get_new_item(const X509_LOOKUP_METHOD* method))
- (X509_LOOKUP *ctx);
-
-int X509_LOOKUP_meth_set_free(X509_LOOKUP_METHOD *method,
- void (*free_fn) (X509_LOOKUP *ctx));
-void (*X509_LOOKUP_meth_get_free(const X509_LOOKUP_METHOD* method))
- (X509_LOOKUP *ctx);
-
-int X509_LOOKUP_meth_set_init(X509_LOOKUP_METHOD *method,
- int (*init) (X509_LOOKUP *ctx));
-int (*X509_LOOKUP_meth_get_init(const X509_LOOKUP_METHOD* method))
- (X509_LOOKUP *ctx);
-
-int X509_LOOKUP_meth_set_shutdown(X509_LOOKUP_METHOD *method,
- int (*shutdown) (X509_LOOKUP *ctx));
-int (*X509_LOOKUP_meth_get_shutdown(const X509_LOOKUP_METHOD* method))
- (X509_LOOKUP *ctx);
-
-int X509_LOOKUP_meth_set_ctrl(X509_LOOKUP_METHOD *method,
- X509_LOOKUP_ctrl_fn ctrl_fn);
-X509_LOOKUP_ctrl_fn X509_LOOKUP_meth_get_ctrl(const X509_LOOKUP_METHOD *method);
-
-int X509_LOOKUP_meth_set_get_by_subject(X509_LOOKUP_METHOD *method,
- X509_LOOKUP_get_by_subject_fn fn);
-X509_LOOKUP_get_by_subject_fn X509_LOOKUP_meth_get_get_by_subject(
- const X509_LOOKUP_METHOD *method);
-
-int X509_LOOKUP_meth_set_get_by_issuer_serial(X509_LOOKUP_METHOD *method,
- X509_LOOKUP_get_by_issuer_serial_fn fn);
-X509_LOOKUP_get_by_issuer_serial_fn X509_LOOKUP_meth_get_get_by_issuer_serial(
- const X509_LOOKUP_METHOD *method);
-
-int X509_LOOKUP_meth_set_get_by_fingerprint(X509_LOOKUP_METHOD *method,
- X509_LOOKUP_get_by_fingerprint_fn fn);
-X509_LOOKUP_get_by_fingerprint_fn X509_LOOKUP_meth_get_get_by_fingerprint(
- const X509_LOOKUP_METHOD *method);
-
-int X509_LOOKUP_meth_set_get_by_alias(X509_LOOKUP_METHOD *method,
- X509_LOOKUP_get_by_alias_fn fn);
-X509_LOOKUP_get_by_alias_fn X509_LOOKUP_meth_get_get_by_alias(
- const X509_LOOKUP_METHOD *method);
-
-
-int X509_STORE_add_cert(X509_STORE *ctx, X509 *x);
-int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x);
-
-int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type,
- X509_NAME *name, X509_OBJECT *ret);
-X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs,
- X509_LOOKUP_TYPE type,
- X509_NAME *name);
-
-int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
- long argl, char **ret);
-
-int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type);
-int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type);
-int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type);
-
-X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method);
-void X509_LOOKUP_free(X509_LOOKUP *ctx);
-int X509_LOOKUP_init(X509_LOOKUP *ctx);
-int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
- X509_NAME *name, X509_OBJECT *ret);
-int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
- X509_NAME *name, ASN1_INTEGER *serial,
- X509_OBJECT *ret);
-int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
- const unsigned char *bytes, int len,
- X509_OBJECT *ret);
-int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
- const char *str, int len, X509_OBJECT *ret);
-int X509_LOOKUP_set_method_data(X509_LOOKUP *ctx, void *data);
-void *X509_LOOKUP_get_method_data(const X509_LOOKUP *ctx);
-X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx);
-int X509_LOOKUP_shutdown(X509_LOOKUP *ctx);
-
-int X509_STORE_load_locations(X509_STORE *ctx,
- const char *file, const char *dir);
-int X509_STORE_set_default_paths(X509_STORE *ctx);
-
-#define X509_STORE_CTX_get_ex_new_index(l, p, newf, dupf, freef) \
- CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, l, p, newf, dupf, freef)
-int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data);
-void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx);
-int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx);
-void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s);
-int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx);
-void X509_STORE_CTX_set_error_depth(X509_STORE_CTX *ctx, int depth);
-X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx);
-void X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x);
-X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx);
-X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx);
-X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx);
-STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx);
-STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx);
-void X509_STORE_CTX_set_cert(X509_STORE_CTX *c, X509 *x);
-void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *c, STACK_OF(X509) *sk);
-void X509_STORE_CTX_set0_crls(X509_STORE_CTX *c, STACK_OF(X509_CRL) *sk);
-int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
-int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
-int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
- int purpose, int trust);
-void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags);
-void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags,
- time_t t);
-
-X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx);
-int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx);
-int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx);
-
-X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx);
-void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param);
-int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name);
-
-/*
- * Bridge opacity barrier between libcrypt and libssl, also needed to support
- * offline testing in test/danetest.c
- */
-void X509_STORE_CTX_set0_dane(X509_STORE_CTX *ctx, SSL_DANE *dane);
-#define DANE_FLAG_NO_DANE_EE_NAMECHECKS (1L << 0)
-
-/* X509_VERIFY_PARAM functions */
-
-X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void);
-void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param);
-int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *to,
- const X509_VERIFY_PARAM *from);
-int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
- const X509_VERIFY_PARAM *from);
-int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name);
-int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param,
- unsigned long flags);
-int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
- unsigned long flags);
-unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param);
-int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose);
-int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust);
-void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth);
-void X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level);
-time_t X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param);
-void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t);
-int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
- ASN1_OBJECT *policy);
-int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
- STACK_OF(ASN1_OBJECT) *policies);
-
-int X509_VERIFY_PARAM_set_inh_flags(X509_VERIFY_PARAM *param,
- uint32_t flags);
-uint32_t X509_VERIFY_PARAM_get_inh_flags(const X509_VERIFY_PARAM *param);
-
-int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
- const char *name, size_t namelen);
-int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
- const char *name, size_t namelen);
-void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
- unsigned int flags);
-unsigned int X509_VERIFY_PARAM_get_hostflags(const X509_VERIFY_PARAM *param);
-char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *);
-void X509_VERIFY_PARAM_move_peername(X509_VERIFY_PARAM *, X509_VERIFY_PARAM *);
-int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
- const char *email, size_t emaillen);
-int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
- const unsigned char *ip, size_t iplen);
-int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param,
- const char *ipasc);
-
-int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param);
-int X509_VERIFY_PARAM_get_auth_level(const X509_VERIFY_PARAM *param);
-const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param);
-
-int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param);
-int X509_VERIFY_PARAM_get_count(void);
-const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id);
-const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name);
-void X509_VERIFY_PARAM_table_cleanup(void);
-
-/* Non positive return values are errors */
-#define X509_PCY_TREE_FAILURE -2 /* Failure to satisfy explicit policy */
-#define X509_PCY_TREE_INVALID -1 /* Inconsistent or invalid extensions */
-#define X509_PCY_TREE_INTERNAL 0 /* Internal error, most likely malloc */
-
-/*
- * Positive return values form a bit mask, all but the first are internal to
- * the library and don't appear in results from X509_policy_check().
- */
-#define X509_PCY_TREE_VALID 1 /* The policy tree is valid */
-#define X509_PCY_TREE_EMPTY 2 /* The policy tree is empty */
-#define X509_PCY_TREE_EXPLICIT 4 /* Explicit policy required */
-
-int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
- STACK_OF(X509) *certs,
- STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags);
-
-void X509_policy_tree_free(X509_POLICY_TREE *tree);
-
-int X509_policy_tree_level_count(const X509_POLICY_TREE *tree);
-X509_POLICY_LEVEL *X509_policy_tree_get0_level(const X509_POLICY_TREE *tree,
- int i);
-
-STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_policies(const
- X509_POLICY_TREE
- *tree);
-
-STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_user_policies(const
- X509_POLICY_TREE
- *tree);
-
-int X509_policy_level_node_count(X509_POLICY_LEVEL *level);
-
-X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level,
- int i);
-
-const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node);
-
-STACK_OF(POLICYQUALINFO) *X509_policy_node_get0_qualifiers(const
- X509_POLICY_NODE
- *node);
-const X509_POLICY_NODE *X509_policy_node_get0_parent(const X509_POLICY_NODE
- *node);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/include/openssl/x509_vfy.h.in b/include/openssl/x509_vfy.h.in
new file mode 100644
index 000000000000..80f18bd78751
--- /dev/null
+++ b/include/openssl/x509_vfy.h.in
@@ -0,0 +1,797 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_X509_VFY_H
+# define OPENSSL_X509_VFY_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_X509_VFY_H
+# endif
+
+/*
+ * Protect against recursion, x509.h and x509_vfy.h each include the other.
+ */
+# ifndef OPENSSL_X509_H
+# include <openssl/x509.h>
+# endif
+
+# include <openssl/opensslconf.h>
+# include <openssl/lhash.h>
+# include <openssl/bio.h>
+# include <openssl/crypto.h>
+# include <openssl/symhacks.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-
+SSL_CTX -> X509_STORE
+ -> X509_LOOKUP
+ ->X509_LOOKUP_METHOD
+ -> X509_LOOKUP
+ ->X509_LOOKUP_METHOD
+
+SSL -> X509_STORE_CTX
+ ->X509_STORE
+
+The X509_STORE holds the tables etc for verification stuff.
+A X509_STORE_CTX is used while validating a single certificate.
+The X509_STORE has X509_LOOKUPs for looking up certs.
+The X509_STORE then calls a function to actually verify the
+certificate chain.
+*/
+
+typedef enum {
+ X509_LU_NONE = 0,
+ X509_LU_X509, X509_LU_CRL
+} X509_LOOKUP_TYPE;
+
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
+#define X509_LU_RETRY -1
+#define X509_LU_FAIL 0
+#endif
+
+{-
+ generate_stack_macros("X509_LOOKUP")
+ .generate_stack_macros("X509_OBJECT")
+ .generate_stack_macros("X509_VERIFY_PARAM");
+-}
+
+/* This is used for a table of trust checking functions */
+typedef struct x509_trust_st {
+ int trust;
+ int flags;
+ int (*check_trust) (struct x509_trust_st *, X509 *, int);
+ char *name;
+ int arg1;
+ void *arg2;
+} X509_TRUST;
+{-
+ generate_stack_macros("X509_TRUST");
+-}
+
+/* standard trust ids */
+# define X509_TRUST_DEFAULT 0 /* Only valid in purpose settings */
+# define X509_TRUST_COMPAT 1
+# define X509_TRUST_SSL_CLIENT 2
+# define X509_TRUST_SSL_SERVER 3
+# define X509_TRUST_EMAIL 4
+# define X509_TRUST_OBJECT_SIGN 5
+# define X509_TRUST_OCSP_SIGN 6
+# define X509_TRUST_OCSP_REQUEST 7
+# define X509_TRUST_TSA 8
+/* Keep these up to date! */
+# define X509_TRUST_MIN 1
+# define X509_TRUST_MAX 8
+
+/* trust_flags values */
+# define X509_TRUST_DYNAMIC (1U << 0)
+# define X509_TRUST_DYNAMIC_NAME (1U << 1)
+/* No compat trust if self-signed, preempts "DO_SS" */
+# define X509_TRUST_NO_SS_COMPAT (1U << 2)
+/* Compat trust if no explicit accepted trust EKUs */
+# define X509_TRUST_DO_SS_COMPAT (1U << 3)
+/* Accept "anyEKU" as a wildcard rejection OID and as a wildcard trust OID */
+# define X509_TRUST_OK_ANY_EKU (1U << 4)
+
+/* check_trust return codes */
+# define X509_TRUST_TRUSTED 1
+# define X509_TRUST_REJECTED 2
+# define X509_TRUST_UNTRUSTED 3
+
+int X509_TRUST_set(int *t, int trust);
+int X509_TRUST_get_count(void);
+X509_TRUST *X509_TRUST_get0(int idx);
+int X509_TRUST_get_by_id(int id);
+int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int),
+ const char *name, int arg1, void *arg2);
+void X509_TRUST_cleanup(void);
+int X509_TRUST_get_flags(const X509_TRUST *xp);
+char *X509_TRUST_get0_name(const X509_TRUST *xp);
+int X509_TRUST_get_trust(const X509_TRUST *xp);
+
+int X509_trusted(const X509 *x);
+int X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj);
+int X509_add1_reject_object(X509 *x, const ASN1_OBJECT *obj);
+void X509_trust_clear(X509 *x);
+void X509_reject_clear(X509 *x);
+STACK_OF(ASN1_OBJECT) *X509_get0_trust_objects(X509 *x);
+STACK_OF(ASN1_OBJECT) *X509_get0_reject_objects(X509 *x);
+
+int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *,
+ int);
+int X509_check_trust(X509 *x, int id, int flags);
+
+int X509_verify_cert(X509_STORE_CTX *ctx);
+int X509_STORE_CTX_verify(X509_STORE_CTX *ctx);
+STACK_OF(X509) *X509_build_chain(X509 *target, STACK_OF(X509) *certs,
+ X509_STORE *store, int with_self_signed,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+int X509_STORE_set_depth(X509_STORE *store, int depth);
+
+typedef int (*X509_STORE_CTX_verify_cb)(int, X509_STORE_CTX *);
+int X509_STORE_CTX_print_verify_cb(int ok, X509_STORE_CTX *ctx);
+typedef int (*X509_STORE_CTX_verify_fn)(X509_STORE_CTX *);
+typedef int (*X509_STORE_CTX_get_issuer_fn)(X509 **issuer,
+ X509_STORE_CTX *ctx, X509 *x);
+typedef int (*X509_STORE_CTX_check_issued_fn)(X509_STORE_CTX *ctx,
+ X509 *x, X509 *issuer);
+typedef int (*X509_STORE_CTX_check_revocation_fn)(X509_STORE_CTX *ctx);
+typedef int (*X509_STORE_CTX_get_crl_fn)(X509_STORE_CTX *ctx,
+ X509_CRL **crl, X509 *x);
+typedef int (*X509_STORE_CTX_check_crl_fn)(X509_STORE_CTX *ctx, X509_CRL *crl);
+typedef int (*X509_STORE_CTX_cert_crl_fn)(X509_STORE_CTX *ctx,
+ X509_CRL *crl, X509 *x);
+typedef int (*X509_STORE_CTX_check_policy_fn)(X509_STORE_CTX *ctx);
+typedef STACK_OF(X509)
+ *(*X509_STORE_CTX_lookup_certs_fn)(X509_STORE_CTX *ctx,
+ const X509_NAME *nm);
+typedef STACK_OF(X509_CRL)
+ *(*X509_STORE_CTX_lookup_crls_fn)(const X509_STORE_CTX *ctx,
+ const X509_NAME *nm);
+typedef int (*X509_STORE_CTX_cleanup_fn)(X509_STORE_CTX *ctx);
+
+void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
+
+# define X509_STORE_CTX_set_app_data(ctx,data) \
+ X509_STORE_CTX_set_ex_data(ctx,0,data)
+# define X509_STORE_CTX_get_app_data(ctx) \
+ X509_STORE_CTX_get_ex_data(ctx,0)
+
+# define X509_L_FILE_LOAD 1
+# define X509_L_ADD_DIR 2
+# define X509_L_ADD_STORE 3
+# define X509_L_LOAD_STORE 4
+
+# define X509_LOOKUP_load_file(x,name,type) \
+ X509_LOOKUP_ctrl((x),X509_L_FILE_LOAD,(name),(long)(type),NULL)
+
+# define X509_LOOKUP_add_dir(x,name,type) \
+ X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL)
+
+# define X509_LOOKUP_add_store(x,name) \
+ X509_LOOKUP_ctrl((x),X509_L_ADD_STORE,(name),0,NULL)
+
+# define X509_LOOKUP_load_store(x,name) \
+ X509_LOOKUP_ctrl((x),X509_L_LOAD_STORE,(name),0,NULL)
+
+# define X509_LOOKUP_load_file_ex(x, name, type, libctx, propq) \
+X509_LOOKUP_ctrl_ex((x), X509_L_FILE_LOAD, (name), (long)(type), NULL,\
+ (libctx), (propq))
+
+# define X509_LOOKUP_load_store_ex(x, name, libctx, propq) \
+X509_LOOKUP_ctrl_ex((x), X509_L_LOAD_STORE, (name), 0, NULL, \
+ (libctx), (propq))
+
+# define X509_LOOKUP_add_store_ex(x, name, libctx, propq) \
+X509_LOOKUP_ctrl_ex((x), X509_L_ADD_STORE, (name), 0, NULL, \
+ (libctx), (propq))
+
+# define X509_V_OK 0
+# define X509_V_ERR_UNSPECIFIED 1
+# define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2
+# define X509_V_ERR_UNABLE_TO_GET_CRL 3
+# define X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE 4
+# define X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE 5
+# define X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY 6
+# define X509_V_ERR_CERT_SIGNATURE_FAILURE 7
+# define X509_V_ERR_CRL_SIGNATURE_FAILURE 8
+# define X509_V_ERR_CERT_NOT_YET_VALID 9
+# define X509_V_ERR_CERT_HAS_EXPIRED 10
+# define X509_V_ERR_CRL_NOT_YET_VALID 11
+# define X509_V_ERR_CRL_HAS_EXPIRED 12
+# define X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD 13
+# define X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD 14
+# define X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD 15
+# define X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD 16
+# define X509_V_ERR_OUT_OF_MEM 17
+# define X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT 18
+# define X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN 19
+# define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 20
+# define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21
+# define X509_V_ERR_CERT_CHAIN_TOO_LONG 22
+# define X509_V_ERR_CERT_REVOKED 23
+# define X509_V_ERR_NO_ISSUER_PUBLIC_KEY 24
+# define X509_V_ERR_PATH_LENGTH_EXCEEDED 25
+# define X509_V_ERR_INVALID_PURPOSE 26
+# define X509_V_ERR_CERT_UNTRUSTED 27
+# define X509_V_ERR_CERT_REJECTED 28
+
+/* These are 'informational' when looking for issuer cert */
+# define X509_V_ERR_SUBJECT_ISSUER_MISMATCH 29
+# define X509_V_ERR_AKID_SKID_MISMATCH 30
+# define X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH 31
+# define X509_V_ERR_KEYUSAGE_NO_CERTSIGN 32
+# define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER 33
+# define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34
+# define X509_V_ERR_KEYUSAGE_NO_CRL_SIGN 35
+# define X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION 36
+# define X509_V_ERR_INVALID_NON_CA 37
+# define X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED 38
+# define X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE 39
+# define X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED 40
+# define X509_V_ERR_INVALID_EXTENSION 41
+# define X509_V_ERR_INVALID_POLICY_EXTENSION 42
+# define X509_V_ERR_NO_EXPLICIT_POLICY 43
+# define X509_V_ERR_DIFFERENT_CRL_SCOPE 44
+# define X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE 45
+# define X509_V_ERR_UNNESTED_RESOURCE 46
+# define X509_V_ERR_PERMITTED_VIOLATION 47
+# define X509_V_ERR_EXCLUDED_VIOLATION 48
+# define X509_V_ERR_SUBTREE_MINMAX 49
+/* The application is not happy */
+# define X509_V_ERR_APPLICATION_VERIFICATION 50
+# define X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE 51
+# define X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX 52
+# define X509_V_ERR_UNSUPPORTED_NAME_SYNTAX 53
+# define X509_V_ERR_CRL_PATH_VALIDATION_ERROR 54
+/* Another issuer check debug option */
+# define X509_V_ERR_PATH_LOOP 55
+/* Suite B mode algorithm violation */
+# define X509_V_ERR_SUITE_B_INVALID_VERSION 56
+# define X509_V_ERR_SUITE_B_INVALID_ALGORITHM 57
+# define X509_V_ERR_SUITE_B_INVALID_CURVE 58
+# define X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM 59
+# define X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED 60
+# define X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 61
+/* Host, email and IP check errors */
+# define X509_V_ERR_HOSTNAME_MISMATCH 62
+# define X509_V_ERR_EMAIL_MISMATCH 63
+# define X509_V_ERR_IP_ADDRESS_MISMATCH 64
+/* DANE TLSA errors */
+# define X509_V_ERR_DANE_NO_MATCH 65
+/* security level errors */
+# define X509_V_ERR_EE_KEY_TOO_SMALL 66
+# define X509_V_ERR_CA_KEY_TOO_SMALL 67
+# define X509_V_ERR_CA_MD_TOO_WEAK 68
+/* Caller error */
+# define X509_V_ERR_INVALID_CALL 69
+/* Issuer lookup error */
+# define X509_V_ERR_STORE_LOOKUP 70
+/* Certificate transparency */
+# define X509_V_ERR_NO_VALID_SCTS 71
+
+# define X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION 72
+/* OCSP status errors */
+# define X509_V_ERR_OCSP_VERIFY_NEEDED 73 /* Need OCSP verification */
+# define X509_V_ERR_OCSP_VERIFY_FAILED 74 /* Couldn't verify cert through OCSP */
+# define X509_V_ERR_OCSP_CERT_UNKNOWN 75 /* Certificate wasn't recognized by the OCSP responder */
+
+# define X509_V_ERR_UNSUPPORTED_SIGNATURE_ALGORITHM 76
+# define X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH 77
+
+/* Errors in case a check in X509_V_FLAG_X509_STRICT mode fails */
+# define X509_V_ERR_SIGNATURE_ALGORITHM_INCONSISTENCY 78
+# define X509_V_ERR_INVALID_CA 79
+# define X509_V_ERR_PATHLEN_INVALID_FOR_NON_CA 80
+# define X509_V_ERR_PATHLEN_WITHOUT_KU_KEY_CERT_SIGN 81
+# define X509_V_ERR_KU_KEY_CERT_SIGN_INVALID_FOR_NON_CA 82
+# define X509_V_ERR_ISSUER_NAME_EMPTY 83
+# define X509_V_ERR_SUBJECT_NAME_EMPTY 84
+# define X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER 85
+# define X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER 86
+# define X509_V_ERR_EMPTY_SUBJECT_ALT_NAME 87
+# define X509_V_ERR_EMPTY_SUBJECT_SAN_NOT_CRITICAL 88
+# define X509_V_ERR_CA_BCONS_NOT_CRITICAL 89
+# define X509_V_ERR_AUTHORITY_KEY_IDENTIFIER_CRITICAL 90
+# define X509_V_ERR_SUBJECT_KEY_IDENTIFIER_CRITICAL 91
+# define X509_V_ERR_CA_CERT_MISSING_KEY_USAGE 92
+# define X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3 93
+# define X509_V_ERR_EC_KEY_EXPLICIT_PARAMS 94
+
+/* Certificate verify flags */
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define X509_V_FLAG_CB_ISSUER_CHECK 0x0 /* Deprecated */
+# endif
+/* Use check time instead of current time */
+# define X509_V_FLAG_USE_CHECK_TIME 0x2
+/* Lookup CRLs */
+# define X509_V_FLAG_CRL_CHECK 0x4
+/* Lookup CRLs for whole chain */
+# define X509_V_FLAG_CRL_CHECK_ALL 0x8
+/* Ignore unhandled critical extensions */
+# define X509_V_FLAG_IGNORE_CRITICAL 0x10
+/* Disable workarounds for broken certificates */
+# define X509_V_FLAG_X509_STRICT 0x20
+/* Enable proxy certificate validation */
+# define X509_V_FLAG_ALLOW_PROXY_CERTS 0x40
+/* Enable policy checking */
+# define X509_V_FLAG_POLICY_CHECK 0x80
+/* Policy variable require-explicit-policy */
+# define X509_V_FLAG_EXPLICIT_POLICY 0x100
+/* Policy variable inhibit-any-policy */
+# define X509_V_FLAG_INHIBIT_ANY 0x200
+/* Policy variable inhibit-policy-mapping */
+# define X509_V_FLAG_INHIBIT_MAP 0x400
+/* Notify callback that policy is OK */
+# define X509_V_FLAG_NOTIFY_POLICY 0x800
+/* Extended CRL features such as indirect CRLs, alternate CRL signing keys */
+# define X509_V_FLAG_EXTENDED_CRL_SUPPORT 0x1000
+/* Delta CRL support */
+# define X509_V_FLAG_USE_DELTAS 0x2000
+/* Check self-signed CA signature */
+# define X509_V_FLAG_CHECK_SS_SIGNATURE 0x4000
+/* Use trusted store first */
+# define X509_V_FLAG_TRUSTED_FIRST 0x8000
+/* Suite B 128 bit only mode: not normally used */
+# define X509_V_FLAG_SUITEB_128_LOS_ONLY 0x10000
+/* Suite B 192 bit only mode */
+# define X509_V_FLAG_SUITEB_192_LOS 0x20000
+/* Suite B 128 bit mode allowing 192 bit algorithms */
+# define X509_V_FLAG_SUITEB_128_LOS 0x30000
+/* Allow partial chains if at least one certificate is in trusted store */
+# define X509_V_FLAG_PARTIAL_CHAIN 0x80000
+/*
+ * If the initial chain is not trusted, do not attempt to build an alternative
+ * chain. Alternate chain checking was introduced in 1.1.0. Setting this flag
+ * will force the behaviour to match that of previous versions.
+ */
+# define X509_V_FLAG_NO_ALT_CHAINS 0x100000
+/* Do not check certificate/CRL validity against current time */
+# define X509_V_FLAG_NO_CHECK_TIME 0x200000
+
+# define X509_VP_FLAG_DEFAULT 0x1
+# define X509_VP_FLAG_OVERWRITE 0x2
+# define X509_VP_FLAG_RESET_FLAGS 0x4
+# define X509_VP_FLAG_LOCKED 0x8
+# define X509_VP_FLAG_ONCE 0x10
+
+/* Internal use: mask of policy related options */
+# define X509_V_FLAG_POLICY_MASK (X509_V_FLAG_POLICY_CHECK \
+ | X509_V_FLAG_EXPLICIT_POLICY \
+ | X509_V_FLAG_INHIBIT_ANY \
+ | X509_V_FLAG_INHIBIT_MAP)
+
+int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
+ const X509_NAME *name);
+X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
+ X509_LOOKUP_TYPE type,
+ const X509_NAME *name);
+X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
+ X509_OBJECT *x);
+int X509_OBJECT_up_ref_count(X509_OBJECT *a);
+X509_OBJECT *X509_OBJECT_new(void);
+void X509_OBJECT_free(X509_OBJECT *a);
+X509_LOOKUP_TYPE X509_OBJECT_get_type(const X509_OBJECT *a);
+X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a);
+int X509_OBJECT_set1_X509(X509_OBJECT *a, X509 *obj);
+X509_CRL *X509_OBJECT_get0_X509_CRL(const X509_OBJECT *a);
+int X509_OBJECT_set1_X509_CRL(X509_OBJECT *a, X509_CRL *obj);
+X509_STORE *X509_STORE_new(void);
+void X509_STORE_free(X509_STORE *v);
+int X509_STORE_lock(X509_STORE *ctx);
+int X509_STORE_unlock(X509_STORE *ctx);
+int X509_STORE_up_ref(X509_STORE *v);
+STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(const X509_STORE *v);
+STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *st);
+STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *st,
+ const X509_NAME *nm);
+STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(const X509_STORE_CTX *st,
+ const X509_NAME *nm);
+int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags);
+int X509_STORE_set_purpose(X509_STORE *ctx, int purpose);
+int X509_STORE_set_trust(X509_STORE *ctx, int trust);
+int X509_STORE_set1_param(X509_STORE *ctx, const X509_VERIFY_PARAM *pm);
+X509_VERIFY_PARAM *X509_STORE_get0_param(const X509_STORE *ctx);
+
+void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify);
+#define X509_STORE_set_verify_func(ctx, func) \
+ X509_STORE_set_verify((ctx),(func))
+void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx,
+ X509_STORE_CTX_verify_fn verify);
+X509_STORE_CTX_verify_fn X509_STORE_get_verify(const X509_STORE *ctx);
+void X509_STORE_set_verify_cb(X509_STORE *ctx,
+ X509_STORE_CTX_verify_cb verify_cb);
+# define X509_STORE_set_verify_cb_func(ctx,func) \
+ X509_STORE_set_verify_cb((ctx),(func))
+X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(const X509_STORE *ctx);
+void X509_STORE_set_get_issuer(X509_STORE *ctx,
+ X509_STORE_CTX_get_issuer_fn get_issuer);
+X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(const X509_STORE *ctx);
+void X509_STORE_set_check_issued(X509_STORE *ctx,
+ X509_STORE_CTX_check_issued_fn check_issued);
+X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(const X509_STORE *ctx);
+void X509_STORE_set_check_revocation(X509_STORE *ctx,
+ X509_STORE_CTX_check_revocation_fn check_revocation);
+X509_STORE_CTX_check_revocation_fn
+ X509_STORE_get_check_revocation(const X509_STORE *ctx);
+void X509_STORE_set_get_crl(X509_STORE *ctx,
+ X509_STORE_CTX_get_crl_fn get_crl);
+X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(const X509_STORE *ctx);
+void X509_STORE_set_check_crl(X509_STORE *ctx,
+ X509_STORE_CTX_check_crl_fn check_crl);
+X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(const X509_STORE *ctx);
+void X509_STORE_set_cert_crl(X509_STORE *ctx,
+ X509_STORE_CTX_cert_crl_fn cert_crl);
+X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(const X509_STORE *ctx);
+void X509_STORE_set_check_policy(X509_STORE *ctx,
+ X509_STORE_CTX_check_policy_fn check_policy);
+X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(const X509_STORE *ctx);
+void X509_STORE_set_lookup_certs(X509_STORE *ctx,
+ X509_STORE_CTX_lookup_certs_fn lookup_certs);
+X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(const X509_STORE *ctx);
+void X509_STORE_set_lookup_crls(X509_STORE *ctx,
+ X509_STORE_CTX_lookup_crls_fn lookup_crls);
+#define X509_STORE_set_lookup_crls_cb(ctx, func) \
+ X509_STORE_set_lookup_crls((ctx), (func))
+X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(const X509_STORE *ctx);
+void X509_STORE_set_cleanup(X509_STORE *ctx,
+ X509_STORE_CTX_cleanup_fn cleanup);
+X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(const X509_STORE *ctx);
+
+#define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef) \
+ CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, l, p, newf, dupf, freef)
+int X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data);
+void *X509_STORE_get_ex_data(const X509_STORE *ctx, int idx);
+
+X509_STORE_CTX *X509_STORE_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq);
+X509_STORE_CTX *X509_STORE_CTX_new(void);
+
+int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
+
+void X509_STORE_CTX_free(X509_STORE_CTX *ctx);
+int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *trust_store,
+ X509 *target, STACK_OF(X509) *untrusted);
+void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
+void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx);
+
+X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx);
+X509 *X509_STORE_CTX_get0_cert(const X509_STORE_CTX *ctx);
+STACK_OF(X509)* X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx);
+void X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
+void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
+ X509_STORE_CTX_verify_cb verify);
+X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(const X509_STORE_CTX *ctx);
+X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(const X509_STORE_CTX *ctx);
+X509_STORE_CTX_get_issuer_fn X509_STORE_CTX_get_get_issuer(const X509_STORE_CTX *ctx);
+X509_STORE_CTX_check_issued_fn X509_STORE_CTX_get_check_issued(const X509_STORE_CTX *ctx);
+X509_STORE_CTX_check_revocation_fn X509_STORE_CTX_get_check_revocation(const X509_STORE_CTX *ctx);
+X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(const X509_STORE_CTX *ctx);
+X509_STORE_CTX_check_crl_fn X509_STORE_CTX_get_check_crl(const X509_STORE_CTX *ctx);
+X509_STORE_CTX_cert_crl_fn X509_STORE_CTX_get_cert_crl(const X509_STORE_CTX *ctx);
+X509_STORE_CTX_check_policy_fn X509_STORE_CTX_get_check_policy(const X509_STORE_CTX *ctx);
+X509_STORE_CTX_lookup_certs_fn X509_STORE_CTX_get_lookup_certs(const X509_STORE_CTX *ctx);
+X509_STORE_CTX_lookup_crls_fn X509_STORE_CTX_get_lookup_crls(const X509_STORE_CTX *ctx);
+X509_STORE_CTX_cleanup_fn X509_STORE_CTX_get_cleanup(const X509_STORE_CTX *ctx);
+
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
+# define X509_STORE_CTX_get_chain X509_STORE_CTX_get0_chain
+# define X509_STORE_CTX_set_chain X509_STORE_CTX_set0_untrusted
+# define X509_STORE_CTX_trusted_stack X509_STORE_CTX_set0_trusted_stack
+# define X509_STORE_get_by_subject X509_STORE_CTX_get_by_subject
+# define X509_STORE_get1_certs X509_STORE_CTX_get1_certs
+# define X509_STORE_get1_crls X509_STORE_CTX_get1_crls
+/* the following macro is misspelled; use X509_STORE_get1_certs instead */
+# define X509_STORE_get1_cert X509_STORE_CTX_get1_certs
+/* the following macro is misspelled; use X509_STORE_get1_crls instead */
+# define X509_STORE_get1_crl X509_STORE_CTX_get1_crls
+#endif
+
+X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m);
+X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void);
+X509_LOOKUP_METHOD *X509_LOOKUP_file(void);
+X509_LOOKUP_METHOD *X509_LOOKUP_store(void);
+
+typedef int (*X509_LOOKUP_ctrl_fn)(X509_LOOKUP *ctx, int cmd, const char *argc,
+ long argl, char **ret);
+typedef int (*X509_LOOKUP_ctrl_ex_fn)(
+ X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+typedef int (*X509_LOOKUP_get_by_subject_fn)(X509_LOOKUP *ctx,
+ X509_LOOKUP_TYPE type,
+ const X509_NAME *name,
+ X509_OBJECT *ret);
+typedef int (*X509_LOOKUP_get_by_subject_ex_fn)(X509_LOOKUP *ctx,
+ X509_LOOKUP_TYPE type,
+ const X509_NAME *name,
+ X509_OBJECT *ret,
+ OSSL_LIB_CTX *libctx,
+ const char *propq);
+typedef int (*X509_LOOKUP_get_by_issuer_serial_fn)(X509_LOOKUP *ctx,
+ X509_LOOKUP_TYPE type,
+ const X509_NAME *name,
+ const ASN1_INTEGER *serial,
+ X509_OBJECT *ret);
+typedef int (*X509_LOOKUP_get_by_fingerprint_fn)(X509_LOOKUP *ctx,
+ X509_LOOKUP_TYPE type,
+ const unsigned char* bytes,
+ int len,
+ X509_OBJECT *ret);
+typedef int (*X509_LOOKUP_get_by_alias_fn)(X509_LOOKUP *ctx,
+ X509_LOOKUP_TYPE type,
+ const char *str,
+ int len,
+ X509_OBJECT *ret);
+
+X509_LOOKUP_METHOD *X509_LOOKUP_meth_new(const char *name);
+void X509_LOOKUP_meth_free(X509_LOOKUP_METHOD *method);
+
+int X509_LOOKUP_meth_set_new_item(X509_LOOKUP_METHOD *method,
+ int (*new_item) (X509_LOOKUP *ctx));
+int (*X509_LOOKUP_meth_get_new_item(const X509_LOOKUP_METHOD* method))
+ (X509_LOOKUP *ctx);
+
+int X509_LOOKUP_meth_set_free(X509_LOOKUP_METHOD *method,
+ void (*free_fn) (X509_LOOKUP *ctx));
+void (*X509_LOOKUP_meth_get_free(const X509_LOOKUP_METHOD* method))
+ (X509_LOOKUP *ctx);
+
+int X509_LOOKUP_meth_set_init(X509_LOOKUP_METHOD *method,
+ int (*init) (X509_LOOKUP *ctx));
+int (*X509_LOOKUP_meth_get_init(const X509_LOOKUP_METHOD* method))
+ (X509_LOOKUP *ctx);
+
+int X509_LOOKUP_meth_set_shutdown(X509_LOOKUP_METHOD *method,
+ int (*shutdown) (X509_LOOKUP *ctx));
+int (*X509_LOOKUP_meth_get_shutdown(const X509_LOOKUP_METHOD* method))
+ (X509_LOOKUP *ctx);
+
+int X509_LOOKUP_meth_set_ctrl(X509_LOOKUP_METHOD *method,
+ X509_LOOKUP_ctrl_fn ctrl_fn);
+X509_LOOKUP_ctrl_fn X509_LOOKUP_meth_get_ctrl(const X509_LOOKUP_METHOD *method);
+
+int X509_LOOKUP_meth_set_get_by_subject(X509_LOOKUP_METHOD *method,
+ X509_LOOKUP_get_by_subject_fn fn);
+X509_LOOKUP_get_by_subject_fn X509_LOOKUP_meth_get_get_by_subject(
+ const X509_LOOKUP_METHOD *method);
+
+int X509_LOOKUP_meth_set_get_by_issuer_serial(X509_LOOKUP_METHOD *method,
+ X509_LOOKUP_get_by_issuer_serial_fn fn);
+X509_LOOKUP_get_by_issuer_serial_fn X509_LOOKUP_meth_get_get_by_issuer_serial(
+ const X509_LOOKUP_METHOD *method);
+
+int X509_LOOKUP_meth_set_get_by_fingerprint(X509_LOOKUP_METHOD *method,
+ X509_LOOKUP_get_by_fingerprint_fn fn);
+X509_LOOKUP_get_by_fingerprint_fn X509_LOOKUP_meth_get_get_by_fingerprint(
+ const X509_LOOKUP_METHOD *method);
+
+int X509_LOOKUP_meth_set_get_by_alias(X509_LOOKUP_METHOD *method,
+ X509_LOOKUP_get_by_alias_fn fn);
+X509_LOOKUP_get_by_alias_fn X509_LOOKUP_meth_get_get_by_alias(
+ const X509_LOOKUP_METHOD *method);
+
+
+int X509_STORE_add_cert(X509_STORE *ctx, X509 *x);
+int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x);
+
+int X509_STORE_CTX_get_by_subject(const X509_STORE_CTX *vs,
+ X509_LOOKUP_TYPE type,
+ const X509_NAME *name, X509_OBJECT *ret);
+X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs,
+ X509_LOOKUP_TYPE type,
+ const X509_NAME *name);
+
+int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
+ long argl, char **ret);
+int X509_LOOKUP_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
+ char **ret, OSSL_LIB_CTX *libctx, const char *propq);
+
+int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type);
+int X509_load_cert_file_ex(X509_LOOKUP *ctx, const char *file, int type,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type);
+int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type);
+int X509_load_cert_crl_file_ex(X509_LOOKUP *ctx, const char *file, int type,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method);
+void X509_LOOKUP_free(X509_LOOKUP *ctx);
+int X509_LOOKUP_init(X509_LOOKUP *ctx);
+int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+ const X509_NAME *name, X509_OBJECT *ret);
+int X509_LOOKUP_by_subject_ex(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+ const X509_NAME *name, X509_OBJECT *ret,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+ const X509_NAME *name,
+ const ASN1_INTEGER *serial,
+ X509_OBJECT *ret);
+int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+ const unsigned char *bytes, int len,
+ X509_OBJECT *ret);
+int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+ const char *str, int len, X509_OBJECT *ret);
+int X509_LOOKUP_set_method_data(X509_LOOKUP *ctx, void *data);
+void *X509_LOOKUP_get_method_data(const X509_LOOKUP *ctx);
+X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx);
+int X509_LOOKUP_shutdown(X509_LOOKUP *ctx);
+
+int X509_STORE_load_file(X509_STORE *ctx, const char *file);
+int X509_STORE_load_path(X509_STORE *ctx, const char *path);
+int X509_STORE_load_store(X509_STORE *ctx, const char *store);
+int X509_STORE_load_locations(X509_STORE *ctx,
+ const char *file,
+ const char *dir);
+int X509_STORE_set_default_paths(X509_STORE *ctx);
+
+int X509_STORE_load_file_ex(X509_STORE *ctx, const char *file,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int X509_STORE_load_store_ex(X509_STORE *ctx, const char *store,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int X509_STORE_load_locations_ex(X509_STORE *ctx, const char *file,
+ const char *dir, OSSL_LIB_CTX *libctx,
+ const char *propq);
+int X509_STORE_set_default_paths_ex(X509_STORE *ctx, OSSL_LIB_CTX *libctx,
+ const char *propq);
+
+#define X509_STORE_CTX_get_ex_new_index(l, p, newf, dupf, freef) \
+ CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, l, p, newf, dupf, freef)
+int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data);
+void *X509_STORE_CTX_get_ex_data(const X509_STORE_CTX *ctx, int idx);
+int X509_STORE_CTX_get_error(const X509_STORE_CTX *ctx);
+void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s);
+int X509_STORE_CTX_get_error_depth(const X509_STORE_CTX *ctx);
+void X509_STORE_CTX_set_error_depth(X509_STORE_CTX *ctx, int depth);
+X509 *X509_STORE_CTX_get_current_cert(const X509_STORE_CTX *ctx);
+void X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x);
+X509 *X509_STORE_CTX_get0_current_issuer(const X509_STORE_CTX *ctx);
+X509_CRL *X509_STORE_CTX_get0_current_crl(const X509_STORE_CTX *ctx);
+X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(const X509_STORE_CTX *ctx);
+STACK_OF(X509) *X509_STORE_CTX_get0_chain(const X509_STORE_CTX *ctx);
+STACK_OF(X509) *X509_STORE_CTX_get1_chain(const X509_STORE_CTX *ctx);
+void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *target);
+void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *c, STACK_OF(X509) *sk);
+void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk);
+int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
+int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
+int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
+ int purpose, int trust);
+void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags);
+void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags,
+ time_t t);
+
+X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(const X509_STORE_CTX *ctx);
+int X509_STORE_CTX_get_explicit_policy(const X509_STORE_CTX *ctx);
+int X509_STORE_CTX_get_num_untrusted(const X509_STORE_CTX *ctx);
+
+X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(const X509_STORE_CTX *ctx);
+void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param);
+int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name);
+
+/*
+ * Bridge opacity barrier between libcrypt and libssl, also needed to support
+ * offline testing in test/danetest.c
+ */
+void X509_STORE_CTX_set0_dane(X509_STORE_CTX *ctx, SSL_DANE *dane);
+#define DANE_FLAG_NO_DANE_EE_NAMECHECKS (1L << 0)
+
+/* X509_VERIFY_PARAM functions */
+
+X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void);
+void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param);
+int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *to,
+ const X509_VERIFY_PARAM *from);
+int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
+ const X509_VERIFY_PARAM *from);
+int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name);
+int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param,
+ unsigned long flags);
+int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
+ unsigned long flags);
+unsigned long X509_VERIFY_PARAM_get_flags(const X509_VERIFY_PARAM *param);
+int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose);
+int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust);
+void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth);
+void X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level);
+time_t X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param);
+void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t);
+int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
+ ASN1_OBJECT *policy);
+int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
+ STACK_OF(ASN1_OBJECT) *policies);
+
+int X509_VERIFY_PARAM_set_inh_flags(X509_VERIFY_PARAM *param,
+ uint32_t flags);
+uint32_t X509_VERIFY_PARAM_get_inh_flags(const X509_VERIFY_PARAM *param);
+
+char *X509_VERIFY_PARAM_get0_host(X509_VERIFY_PARAM *param, int idx);
+int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
+ const char *name, size_t namelen);
+int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
+ const char *name, size_t namelen);
+void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
+ unsigned int flags);
+unsigned int X509_VERIFY_PARAM_get_hostflags(const X509_VERIFY_PARAM *param);
+char *X509_VERIFY_PARAM_get0_peername(const X509_VERIFY_PARAM *param);
+void X509_VERIFY_PARAM_move_peername(X509_VERIFY_PARAM *, X509_VERIFY_PARAM *);
+char *X509_VERIFY_PARAM_get0_email(X509_VERIFY_PARAM *param);
+int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
+ const char *email, size_t emaillen);
+char *X509_VERIFY_PARAM_get1_ip_asc(X509_VERIFY_PARAM *param);
+int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
+ const unsigned char *ip, size_t iplen);
+int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param,
+ const char *ipasc);
+
+int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param);
+int X509_VERIFY_PARAM_get_auth_level(const X509_VERIFY_PARAM *param);
+const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param);
+
+int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param);
+int X509_VERIFY_PARAM_get_count(void);
+const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id);
+const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name);
+void X509_VERIFY_PARAM_table_cleanup(void);
+
+/* Non positive return values are errors */
+#define X509_PCY_TREE_FAILURE -2 /* Failure to satisfy explicit policy */
+#define X509_PCY_TREE_INVALID -1 /* Inconsistent or invalid extensions */
+#define X509_PCY_TREE_INTERNAL 0 /* Internal error, most likely malloc */
+
+/*
+ * Positive return values form a bit mask, all but the first are internal to
+ * the library and don't appear in results from X509_policy_check().
+ */
+#define X509_PCY_TREE_VALID 1 /* The policy tree is valid */
+#define X509_PCY_TREE_EMPTY 2 /* The policy tree is empty */
+#define X509_PCY_TREE_EXPLICIT 4 /* Explicit policy required */
+
+int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
+ STACK_OF(X509) *certs,
+ STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags);
+
+void X509_policy_tree_free(X509_POLICY_TREE *tree);
+
+int X509_policy_tree_level_count(const X509_POLICY_TREE *tree);
+X509_POLICY_LEVEL *X509_policy_tree_get0_level(const X509_POLICY_TREE *tree,
+ int i);
+
+STACK_OF(X509_POLICY_NODE)
+ *X509_policy_tree_get0_policies(const X509_POLICY_TREE *tree);
+
+STACK_OF(X509_POLICY_NODE)
+ *X509_policy_tree_get0_user_policies(const X509_POLICY_TREE *tree);
+
+int X509_policy_level_node_count(X509_POLICY_LEVEL *level);
+
+X509_POLICY_NODE *X509_policy_level_get0_node(const X509_POLICY_LEVEL *level,
+ int i);
+
+const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node);
+
+STACK_OF(POLICYQUALINFO)
+ *X509_policy_node_get0_qualifiers(const X509_POLICY_NODE *node);
+const X509_POLICY_NODE
+ *X509_policy_node_get0_parent(const X509_POLICY_NODE *node);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/openssl/x509err.h b/include/openssl/x509err.h
index cd08673f8f69..a56facd46bf9 100644
--- a/include/openssl/x509err.h
+++ b/include/openssl/x509err.h
@@ -1,88 +1,22 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_X509ERR_H
-# define HEADER_X509ERR_H
+#ifndef OPENSSL_X509ERR_H
+# define OPENSSL_X509ERR_H
+# pragma once
+# include <openssl/opensslconf.h>
# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_X509_strings(void);
-/*
- * X509 function codes.
- */
-# define X509_F_ADD_CERT_DIR 100
-# define X509_F_BUILD_CHAIN 106
-# define X509_F_BY_FILE_CTRL 101
-# define X509_F_CHECK_NAME_CONSTRAINTS 149
-# define X509_F_CHECK_POLICY 145
-# define X509_F_DANE_I2D 107
-# define X509_F_DIR_CTRL 102
-# define X509_F_GET_CERT_BY_SUBJECT 103
-# define X509_F_I2D_X509_AUX 151
-# define X509_F_LOOKUP_CERTS_SK 152
-# define X509_F_NETSCAPE_SPKI_B64_DECODE 129
-# define X509_F_NETSCAPE_SPKI_B64_ENCODE 130
-# define X509_F_NEW_DIR 153
-# define X509_F_X509AT_ADD1_ATTR 135
-# define X509_F_X509V3_ADD_EXT 104
-# define X509_F_X509_ATTRIBUTE_CREATE_BY_NID 136
-# define X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ 137
-# define X509_F_X509_ATTRIBUTE_CREATE_BY_TXT 140
-# define X509_F_X509_ATTRIBUTE_GET0_DATA 139
-# define X509_F_X509_ATTRIBUTE_SET1_DATA 138
-# define X509_F_X509_CHECK_PRIVATE_KEY 128
-# define X509_F_X509_CRL_DIFF 105
-# define X509_F_X509_CRL_METHOD_NEW 154
-# define X509_F_X509_CRL_PRINT_FP 147
-# define X509_F_X509_EXTENSION_CREATE_BY_NID 108
-# define X509_F_X509_EXTENSION_CREATE_BY_OBJ 109
-# define X509_F_X509_GET_PUBKEY_PARAMETERS 110
-# define X509_F_X509_LOAD_CERT_CRL_FILE 132
-# define X509_F_X509_LOAD_CERT_FILE 111
-# define X509_F_X509_LOAD_CRL_FILE 112
-# define X509_F_X509_LOOKUP_METH_NEW 160
-# define X509_F_X509_LOOKUP_NEW 155
-# define X509_F_X509_NAME_ADD_ENTRY 113
-# define X509_F_X509_NAME_CANON 156
-# define X509_F_X509_NAME_ENTRY_CREATE_BY_NID 114
-# define X509_F_X509_NAME_ENTRY_CREATE_BY_TXT 131
-# define X509_F_X509_NAME_ENTRY_SET_OBJECT 115
-# define X509_F_X509_NAME_ONELINE 116
-# define X509_F_X509_NAME_PRINT 117
-# define X509_F_X509_OBJECT_NEW 150
-# define X509_F_X509_PRINT_EX_FP 118
-# define X509_F_X509_PUBKEY_DECODE 148
-# define X509_F_X509_PUBKEY_GET 161
-# define X509_F_X509_PUBKEY_GET0 119
-# define X509_F_X509_PUBKEY_SET 120
-# define X509_F_X509_REQ_CHECK_PRIVATE_KEY 144
-# define X509_F_X509_REQ_PRINT_EX 121
-# define X509_F_X509_REQ_PRINT_FP 122
-# define X509_F_X509_REQ_TO_X509 123
-# define X509_F_X509_STORE_ADD_CERT 124
-# define X509_F_X509_STORE_ADD_CRL 125
-# define X509_F_X509_STORE_ADD_LOOKUP 157
-# define X509_F_X509_STORE_CTX_GET1_ISSUER 146
-# define X509_F_X509_STORE_CTX_INIT 143
-# define X509_F_X509_STORE_CTX_NEW 142
-# define X509_F_X509_STORE_CTX_PURPOSE_INHERIT 134
-# define X509_F_X509_STORE_NEW 158
-# define X509_F_X509_TO_X509_REQ 126
-# define X509_F_X509_TRUST_ADD 133
-# define X509_F_X509_TRUST_SET 141
-# define X509_F_X509_VERIFY_CERT 127
-# define X509_F_X509_VERIFY_PARAM_NEW 159
/*
* X509 reason codes.
@@ -92,12 +26,16 @@ int ERR_load_X509_strings(void);
# define X509_R_BAD_X509_FILETYPE 100
# define X509_R_BASE64_DECODE_ERROR 118
# define X509_R_CANT_CHECK_DH_KEY 114
+# define X509_R_CERTIFICATE_VERIFICATION_FAILED 139
# define X509_R_CERT_ALREADY_IN_HASH_TABLE 101
# define X509_R_CRL_ALREADY_DELTA 127
# define X509_R_CRL_VERIFY_FAILURE 131
+# define X509_R_ERROR_GETTING_MD_BY_NID 141
+# define X509_R_ERROR_USING_SIGINF_SET 142
# define X509_R_IDP_MISMATCH 128
# define X509_R_INVALID_ATTRIBUTES 138
# define X509_R_INVALID_DIRECTORY 113
+# define X509_R_INVALID_DISTPOINT 143
# define X509_R_INVALID_FIELD_NAME 119
# define X509_R_INVALID_TRUST 123
# define X509_R_ISSUER_MISMATCH 129
@@ -121,6 +59,7 @@ int ERR_load_X509_strings(void);
# define X509_R_UNKNOWN_KEY_TYPE 117
# define X509_R_UNKNOWN_NID 109
# define X509_R_UNKNOWN_PURPOSE_ID 121
+# define X509_R_UNKNOWN_SIGID_ALGS 144
# define X509_R_UNKNOWN_TRUST_ID 120
# define X509_R_UNSUPPORTED_ALGORITHM 111
# define X509_R_WRONG_LOOKUP_TYPE 112
diff --git a/include/openssl/x509v3.h b/include/openssl/x509v3.h
deleted file mode 100644
index 3a4f04c183e9..000000000000
--- a/include/openssl/x509v3.h
+++ /dev/null
@@ -1,938 +0,0 @@
-/*
- * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef HEADER_X509V3_H
-# define HEADER_X509V3_H
-
-# include <openssl/bio.h>
-# include <openssl/x509.h>
-# include <openssl/conf.h>
-# include <openssl/x509v3err.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Forward reference */
-struct v3_ext_method;
-struct v3_ext_ctx;
-
-/* Useful typedefs */
-
-typedef void *(*X509V3_EXT_NEW)(void);
-typedef void (*X509V3_EXT_FREE) (void *);
-typedef void *(*X509V3_EXT_D2I)(void *, const unsigned char **, long);
-typedef int (*X509V3_EXT_I2D) (void *, unsigned char **);
-typedef STACK_OF(CONF_VALUE) *
- (*X509V3_EXT_I2V) (const struct v3_ext_method *method, void *ext,
- STACK_OF(CONF_VALUE) *extlist);
-typedef void *(*X509V3_EXT_V2I)(const struct v3_ext_method *method,
- struct v3_ext_ctx *ctx,
- STACK_OF(CONF_VALUE) *values);
-typedef char *(*X509V3_EXT_I2S)(const struct v3_ext_method *method,
- void *ext);
-typedef void *(*X509V3_EXT_S2I)(const struct v3_ext_method *method,
- struct v3_ext_ctx *ctx, const char *str);
-typedef int (*X509V3_EXT_I2R) (const struct v3_ext_method *method, void *ext,
- BIO *out, int indent);
-typedef void *(*X509V3_EXT_R2I)(const struct v3_ext_method *method,
- struct v3_ext_ctx *ctx, const char *str);
-
-/* V3 extension structure */
-
-struct v3_ext_method {
- int ext_nid;
- int ext_flags;
-/* If this is set the following four fields are ignored */
- ASN1_ITEM_EXP *it;
-/* Old style ASN1 calls */
- X509V3_EXT_NEW ext_new;
- X509V3_EXT_FREE ext_free;
- X509V3_EXT_D2I d2i;
- X509V3_EXT_I2D i2d;
-/* The following pair is used for string extensions */
- X509V3_EXT_I2S i2s;
- X509V3_EXT_S2I s2i;
-/* The following pair is used for multi-valued extensions */
- X509V3_EXT_I2V i2v;
- X509V3_EXT_V2I v2i;
-/* The following are used for raw extensions */
- X509V3_EXT_I2R i2r;
- X509V3_EXT_R2I r2i;
- void *usr_data; /* Any extension specific data */
-};
-
-typedef struct X509V3_CONF_METHOD_st {
- char *(*get_string) (void *db, const char *section, const char *value);
- STACK_OF(CONF_VALUE) *(*get_section) (void *db, const char *section);
- void (*free_string) (void *db, char *string);
- void (*free_section) (void *db, STACK_OF(CONF_VALUE) *section);
-} X509V3_CONF_METHOD;
-
-/* Context specific info */
-struct v3_ext_ctx {
-# define CTX_TEST 0x1
-# define X509V3_CTX_REPLACE 0x2
- int flags;
- X509 *issuer_cert;
- X509 *subject_cert;
- X509_REQ *subject_req;
- X509_CRL *crl;
- X509V3_CONF_METHOD *db_meth;
- void *db;
-/* Maybe more here */
-};
-
-typedef struct v3_ext_method X509V3_EXT_METHOD;
-
-DEFINE_STACK_OF(X509V3_EXT_METHOD)
-
-/* ext_flags values */
-# define X509V3_EXT_DYNAMIC 0x1
-# define X509V3_EXT_CTX_DEP 0x2
-# define X509V3_EXT_MULTILINE 0x4
-
-typedef BIT_STRING_BITNAME ENUMERATED_NAMES;
-
-typedef struct BASIC_CONSTRAINTS_st {
- int ca;
- ASN1_INTEGER *pathlen;
-} BASIC_CONSTRAINTS;
-
-typedef struct PKEY_USAGE_PERIOD_st {
- ASN1_GENERALIZEDTIME *notBefore;
- ASN1_GENERALIZEDTIME *notAfter;
-} PKEY_USAGE_PERIOD;
-
-typedef struct otherName_st {
- ASN1_OBJECT *type_id;
- ASN1_TYPE *value;
-} OTHERNAME;
-
-typedef struct EDIPartyName_st {
- ASN1_STRING *nameAssigner;
- ASN1_STRING *partyName;
-} EDIPARTYNAME;
-
-typedef struct GENERAL_NAME_st {
-# define GEN_OTHERNAME 0
-# define GEN_EMAIL 1
-# define GEN_DNS 2
-# define GEN_X400 3
-# define GEN_DIRNAME 4
-# define GEN_EDIPARTY 5
-# define GEN_URI 6
-# define GEN_IPADD 7
-# define GEN_RID 8
- int type;
- union {
- char *ptr;
- OTHERNAME *otherName; /* otherName */
- ASN1_IA5STRING *rfc822Name;
- ASN1_IA5STRING *dNSName;
- ASN1_STRING *x400Address;
- X509_NAME *directoryName;
- EDIPARTYNAME *ediPartyName;
- ASN1_IA5STRING *uniformResourceIdentifier;
- ASN1_OCTET_STRING *iPAddress;
- ASN1_OBJECT *registeredID;
- /* Old names */
- ASN1_OCTET_STRING *ip; /* iPAddress */
- X509_NAME *dirn; /* dirn */
- ASN1_IA5STRING *ia5; /* rfc822Name, dNSName,
- * uniformResourceIdentifier */
- ASN1_OBJECT *rid; /* registeredID */
- ASN1_TYPE *other; /* x400Address */
- } d;
-} GENERAL_NAME;
-
-typedef struct ACCESS_DESCRIPTION_st {
- ASN1_OBJECT *method;
- GENERAL_NAME *location;
-} ACCESS_DESCRIPTION;
-
-typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS;
-
-typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE;
-
-typedef STACK_OF(ASN1_INTEGER) TLS_FEATURE;
-
-DEFINE_STACK_OF(GENERAL_NAME)
-typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES;
-DEFINE_STACK_OF(GENERAL_NAMES)
-
-DEFINE_STACK_OF(ACCESS_DESCRIPTION)
-
-typedef struct DIST_POINT_NAME_st {
- int type;
- union {
- GENERAL_NAMES *fullname;
- STACK_OF(X509_NAME_ENTRY) *relativename;
- } name;
-/* If relativename then this contains the full distribution point name */
- X509_NAME *dpname;
-} DIST_POINT_NAME;
-/* All existing reasons */
-# define CRLDP_ALL_REASONS 0x807f
-
-# define CRL_REASON_NONE -1
-# define CRL_REASON_UNSPECIFIED 0
-# define CRL_REASON_KEY_COMPROMISE 1
-# define CRL_REASON_CA_COMPROMISE 2
-# define CRL_REASON_AFFILIATION_CHANGED 3
-# define CRL_REASON_SUPERSEDED 4
-# define CRL_REASON_CESSATION_OF_OPERATION 5
-# define CRL_REASON_CERTIFICATE_HOLD 6
-# define CRL_REASON_REMOVE_FROM_CRL 8
-# define CRL_REASON_PRIVILEGE_WITHDRAWN 9
-# define CRL_REASON_AA_COMPROMISE 10
-
-struct DIST_POINT_st {
- DIST_POINT_NAME *distpoint;
- ASN1_BIT_STRING *reasons;
- GENERAL_NAMES *CRLissuer;
- int dp_reasons;
-};
-
-typedef STACK_OF(DIST_POINT) CRL_DIST_POINTS;
-
-DEFINE_STACK_OF(DIST_POINT)
-
-struct AUTHORITY_KEYID_st {
- ASN1_OCTET_STRING *keyid;
- GENERAL_NAMES *issuer;
- ASN1_INTEGER *serial;
-};
-
-/* Strong extranet structures */
-
-typedef struct SXNET_ID_st {
- ASN1_INTEGER *zone;
- ASN1_OCTET_STRING *user;
-} SXNETID;
-
-DEFINE_STACK_OF(SXNETID)
-
-typedef struct SXNET_st {
- ASN1_INTEGER *version;
- STACK_OF(SXNETID) *ids;
-} SXNET;
-
-typedef struct NOTICEREF_st {
- ASN1_STRING *organization;
- STACK_OF(ASN1_INTEGER) *noticenos;
-} NOTICEREF;
-
-typedef struct USERNOTICE_st {
- NOTICEREF *noticeref;
- ASN1_STRING *exptext;
-} USERNOTICE;
-
-typedef struct POLICYQUALINFO_st {
- ASN1_OBJECT *pqualid;
- union {
- ASN1_IA5STRING *cpsuri;
- USERNOTICE *usernotice;
- ASN1_TYPE *other;
- } d;
-} POLICYQUALINFO;
-
-DEFINE_STACK_OF(POLICYQUALINFO)
-
-typedef struct POLICYINFO_st {
- ASN1_OBJECT *policyid;
- STACK_OF(POLICYQUALINFO) *qualifiers;
-} POLICYINFO;
-
-typedef STACK_OF(POLICYINFO) CERTIFICATEPOLICIES;
-
-DEFINE_STACK_OF(POLICYINFO)
-
-typedef struct POLICY_MAPPING_st {
- ASN1_OBJECT *issuerDomainPolicy;
- ASN1_OBJECT *subjectDomainPolicy;
-} POLICY_MAPPING;
-
-DEFINE_STACK_OF(POLICY_MAPPING)
-
-typedef STACK_OF(POLICY_MAPPING) POLICY_MAPPINGS;
-
-typedef struct GENERAL_SUBTREE_st {
- GENERAL_NAME *base;
- ASN1_INTEGER *minimum;
- ASN1_INTEGER *maximum;
-} GENERAL_SUBTREE;
-
-DEFINE_STACK_OF(GENERAL_SUBTREE)
-
-struct NAME_CONSTRAINTS_st {
- STACK_OF(GENERAL_SUBTREE) *permittedSubtrees;
- STACK_OF(GENERAL_SUBTREE) *excludedSubtrees;
-};
-
-typedef struct POLICY_CONSTRAINTS_st {
- ASN1_INTEGER *requireExplicitPolicy;
- ASN1_INTEGER *inhibitPolicyMapping;
-} POLICY_CONSTRAINTS;
-
-/* Proxy certificate structures, see RFC 3820 */
-typedef struct PROXY_POLICY_st {
- ASN1_OBJECT *policyLanguage;
- ASN1_OCTET_STRING *policy;
-} PROXY_POLICY;
-
-typedef struct PROXY_CERT_INFO_EXTENSION_st {
- ASN1_INTEGER *pcPathLengthConstraint;
- PROXY_POLICY *proxyPolicy;
-} PROXY_CERT_INFO_EXTENSION;
-
-DECLARE_ASN1_FUNCTIONS(PROXY_POLICY)
-DECLARE_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION)
-
-struct ISSUING_DIST_POINT_st {
- DIST_POINT_NAME *distpoint;
- int onlyuser;
- int onlyCA;
- ASN1_BIT_STRING *onlysomereasons;
- int indirectCRL;
- int onlyattr;
-};
-
-/* Values in idp_flags field */
-/* IDP present */
-# define IDP_PRESENT 0x1
-/* IDP values inconsistent */
-# define IDP_INVALID 0x2
-/* onlyuser true */
-# define IDP_ONLYUSER 0x4
-/* onlyCA true */
-# define IDP_ONLYCA 0x8
-/* onlyattr true */
-# define IDP_ONLYATTR 0x10
-/* indirectCRL true */
-# define IDP_INDIRECT 0x20
-/* onlysomereasons present */
-# define IDP_REASONS 0x40
-
-# define X509V3_conf_err(val) ERR_add_error_data(6, \
- "section:", (val)->section, \
- ",name:", (val)->name, ",value:", (val)->value)
-
-# define X509V3_set_ctx_test(ctx) \
- X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST)
-# define X509V3_set_ctx_nodb(ctx) (ctx)->db = NULL;
-
-# define EXT_BITSTRING(nid, table) { nid, 0, ASN1_ITEM_ref(ASN1_BIT_STRING), \
- 0,0,0,0, \
- 0,0, \
- (X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, \
- (X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, \
- NULL, NULL, \
- table}
-
-# define EXT_IA5STRING(nid) { nid, 0, ASN1_ITEM_ref(ASN1_IA5STRING), \
- 0,0,0,0, \
- (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, \
- (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, \
- 0,0,0,0, \
- NULL}
-
-# define EXT_END { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
-
-/* X509_PURPOSE stuff */
-
-# define EXFLAG_BCONS 0x1
-# define EXFLAG_KUSAGE 0x2
-# define EXFLAG_XKUSAGE 0x4
-# define EXFLAG_NSCERT 0x8
-
-# define EXFLAG_CA 0x10
-/* Really self issued not necessarily self signed */
-# define EXFLAG_SI 0x20
-# define EXFLAG_V1 0x40
-# define EXFLAG_INVALID 0x80
-/* EXFLAG_SET is set to indicate that some values have been precomputed */
-# define EXFLAG_SET 0x100
-# define EXFLAG_CRITICAL 0x200
-# define EXFLAG_PROXY 0x400
-
-# define EXFLAG_INVALID_POLICY 0x800
-# define EXFLAG_FRESHEST 0x1000
-# define EXFLAG_SS 0x2000 /* cert is apparently self-signed */
-
-# define EXFLAG_NO_FINGERPRINT 0x100000
-
-# define KU_DIGITAL_SIGNATURE 0x0080
-# define KU_NON_REPUDIATION 0x0040
-# define KU_KEY_ENCIPHERMENT 0x0020
-# define KU_DATA_ENCIPHERMENT 0x0010
-# define KU_KEY_AGREEMENT 0x0008
-# define KU_KEY_CERT_SIGN 0x0004
-# define KU_CRL_SIGN 0x0002
-# define KU_ENCIPHER_ONLY 0x0001
-# define KU_DECIPHER_ONLY 0x8000
-
-# define NS_SSL_CLIENT 0x80
-# define NS_SSL_SERVER 0x40
-# define NS_SMIME 0x20
-# define NS_OBJSIGN 0x10
-# define NS_SSL_CA 0x04
-# define NS_SMIME_CA 0x02
-# define NS_OBJSIGN_CA 0x01
-# define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA)
-
-# define XKU_SSL_SERVER 0x1
-# define XKU_SSL_CLIENT 0x2
-# define XKU_SMIME 0x4
-# define XKU_CODE_SIGN 0x8
-# define XKU_SGC 0x10
-# define XKU_OCSP_SIGN 0x20
-# define XKU_TIMESTAMP 0x40
-# define XKU_DVCS 0x80
-# define XKU_ANYEKU 0x100
-
-# define X509_PURPOSE_DYNAMIC 0x1
-# define X509_PURPOSE_DYNAMIC_NAME 0x2
-
-typedef struct x509_purpose_st {
- int purpose;
- int trust; /* Default trust ID */
- int flags;
- int (*check_purpose) (const struct x509_purpose_st *, const X509 *, int);
- char *name;
- char *sname;
- void *usr_data;
-} X509_PURPOSE;
-
-# define X509_PURPOSE_SSL_CLIENT 1
-# define X509_PURPOSE_SSL_SERVER 2
-# define X509_PURPOSE_NS_SSL_SERVER 3
-# define X509_PURPOSE_SMIME_SIGN 4
-# define X509_PURPOSE_SMIME_ENCRYPT 5
-# define X509_PURPOSE_CRL_SIGN 6
-# define X509_PURPOSE_ANY 7
-# define X509_PURPOSE_OCSP_HELPER 8
-# define X509_PURPOSE_TIMESTAMP_SIGN 9
-
-# define X509_PURPOSE_MIN 1
-# define X509_PURPOSE_MAX 9
-
-/* Flags for X509V3_EXT_print() */
-
-# define X509V3_EXT_UNKNOWN_MASK (0xfL << 16)
-/* Return error for unknown extensions */
-# define X509V3_EXT_DEFAULT 0
-/* Print error for unknown extensions */
-# define X509V3_EXT_ERROR_UNKNOWN (1L << 16)
-/* ASN1 parse unknown extensions */
-# define X509V3_EXT_PARSE_UNKNOWN (2L << 16)
-/* BIO_dump unknown extensions */
-# define X509V3_EXT_DUMP_UNKNOWN (3L << 16)
-
-/* Flags for X509V3_add1_i2d */
-
-# define X509V3_ADD_OP_MASK 0xfL
-# define X509V3_ADD_DEFAULT 0L
-# define X509V3_ADD_APPEND 1L
-# define X509V3_ADD_REPLACE 2L
-# define X509V3_ADD_REPLACE_EXISTING 3L
-# define X509V3_ADD_KEEP_EXISTING 4L
-# define X509V3_ADD_DELETE 5L
-# define X509V3_ADD_SILENT 0x10
-
-DEFINE_STACK_OF(X509_PURPOSE)
-
-DECLARE_ASN1_FUNCTIONS(BASIC_CONSTRAINTS)
-
-DECLARE_ASN1_FUNCTIONS(SXNET)
-DECLARE_ASN1_FUNCTIONS(SXNETID)
-
-int SXNET_add_id_asc(SXNET **psx, const char *zone, const char *user, int userlen);
-int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, const char *user,
- int userlen);
-int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *izone, const char *user,
- int userlen);
-
-ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, const char *zone);
-ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone);
-ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone);
-
-DECLARE_ASN1_FUNCTIONS(AUTHORITY_KEYID)
-
-DECLARE_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD)
-
-DECLARE_ASN1_FUNCTIONS(GENERAL_NAME)
-GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a);
-int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b);
-
-ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx,
- STACK_OF(CONF_VALUE) *nval);
-STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
- ASN1_BIT_STRING *bits,
- STACK_OF(CONF_VALUE) *extlist);
-char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5);
-ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, const char *str);
-
-STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
- GENERAL_NAME *gen,
- STACK_OF(CONF_VALUE) *ret);
-int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen);
-
-DECLARE_ASN1_FUNCTIONS(GENERAL_NAMES)
-
-STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
- GENERAL_NAMES *gen,
- STACK_OF(CONF_VALUE) *extlist);
-GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
-
-DECLARE_ASN1_FUNCTIONS(OTHERNAME)
-DECLARE_ASN1_FUNCTIONS(EDIPARTYNAME)
-int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b);
-void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value);
-void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype);
-int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
- ASN1_OBJECT *oid, ASN1_TYPE *value);
-int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen,
- ASN1_OBJECT **poid, ASN1_TYPE **pvalue);
-
-char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
- const ASN1_OCTET_STRING *ia5);
-ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, const char *str);
-
-DECLARE_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE)
-int i2a_ACCESS_DESCRIPTION(BIO *bp, const ACCESS_DESCRIPTION *a);
-
-DECLARE_ASN1_ALLOC_FUNCTIONS(TLS_FEATURE)
-
-DECLARE_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
-DECLARE_ASN1_FUNCTIONS(POLICYINFO)
-DECLARE_ASN1_FUNCTIONS(POLICYQUALINFO)
-DECLARE_ASN1_FUNCTIONS(USERNOTICE)
-DECLARE_ASN1_FUNCTIONS(NOTICEREF)
-
-DECLARE_ASN1_FUNCTIONS(CRL_DIST_POINTS)
-DECLARE_ASN1_FUNCTIONS(DIST_POINT)
-DECLARE_ASN1_FUNCTIONS(DIST_POINT_NAME)
-DECLARE_ASN1_FUNCTIONS(ISSUING_DIST_POINT)
-
-int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname);
-
-int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc);
-int NAME_CONSTRAINTS_check_CN(X509 *x, NAME_CONSTRAINTS *nc);
-
-DECLARE_ASN1_FUNCTIONS(ACCESS_DESCRIPTION)
-DECLARE_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS)
-
-DECLARE_ASN1_ITEM(POLICY_MAPPING)
-DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING)
-DECLARE_ASN1_ITEM(POLICY_MAPPINGS)
-
-DECLARE_ASN1_ITEM(GENERAL_SUBTREE)
-DECLARE_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
-
-DECLARE_ASN1_ITEM(NAME_CONSTRAINTS)
-DECLARE_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
-
-DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS)
-DECLARE_ASN1_ITEM(POLICY_CONSTRAINTS)
-
-GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
- const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, int gen_type,
- const char *value, int is_nc);
-
-# ifdef HEADER_CONF_H
-GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, CONF_VALUE *cnf);
-GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
- const X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, CONF_VALUE *cnf,
- int is_nc);
-void X509V3_conf_free(CONF_VALUE *val);
-
-X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
- const char *value);
-X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, const char *name,
- const char *value);
-int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section,
- STACK_OF(X509_EXTENSION) **sk);
-int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
- X509 *cert);
-int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
- X509_REQ *req);
-int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
- X509_CRL *crl);
-
-X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf,
- X509V3_CTX *ctx, int ext_nid,
- const char *value);
-X509_EXTENSION *X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
- const char *name, const char *value);
-int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
- const char *section, X509 *cert);
-int X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
- const char *section, X509_REQ *req);
-int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
- const char *section, X509_CRL *crl);
-
-int X509V3_add_value_bool_nf(const char *name, int asn1_bool,
- STACK_OF(CONF_VALUE) **extlist);
-int X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool);
-int X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint);
-void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf);
-void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash);
-# endif
-
-char *X509V3_get_string(X509V3_CTX *ctx, const char *name, const char *section);
-STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, const char *section);
-void X509V3_string_free(X509V3_CTX *ctx, char *str);
-void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section);
-void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subject,
- X509_REQ *req, X509_CRL *crl, int flags);
-
-int X509V3_add_value(const char *name, const char *value,
- STACK_OF(CONF_VALUE) **extlist);
-int X509V3_add_value_uchar(const char *name, const unsigned char *value,
- STACK_OF(CONF_VALUE) **extlist);
-int X509V3_add_value_bool(const char *name, int asn1_bool,
- STACK_OF(CONF_VALUE) **extlist);
-int X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint,
- STACK_OF(CONF_VALUE) **extlist);
-char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, const ASN1_INTEGER *aint);
-ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *meth, const char *value);
-char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *meth, const ASN1_ENUMERATED *aint);
-char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *meth,
- const ASN1_ENUMERATED *aint);
-int X509V3_EXT_add(X509V3_EXT_METHOD *ext);
-int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist);
-int X509V3_EXT_add_alias(int nid_to, int nid_from);
-void X509V3_EXT_cleanup(void);
-
-const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext);
-const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid);
-int X509V3_add_standard_extensions(void);
-STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line);
-void *X509V3_EXT_d2i(X509_EXTENSION *ext);
-void *X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *x, int nid, int *crit,
- int *idx);
-
-X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc);
-int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
- int crit, unsigned long flags);
-
-#if OPENSSL_API_COMPAT < 0x10100000L
-/* The new declarations are in crypto.h, but the old ones were here. */
-# define hex_to_string OPENSSL_buf2hexstr
-# define string_to_hex OPENSSL_hexstr2buf
-#endif
-
-void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
- int ml);
-int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag,
- int indent);
-#ifndef OPENSSL_NO_STDIO
-int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent);
-#endif
-int X509V3_extensions_print(BIO *out, const char *title,
- const STACK_OF(X509_EXTENSION) *exts,
- unsigned long flag, int indent);
-
-int X509_check_ca(X509 *x);
-int X509_check_purpose(X509 *x, int id, int ca);
-int X509_supported_extension(X509_EXTENSION *ex);
-int X509_PURPOSE_set(int *p, int purpose);
-int X509_check_issued(X509 *issuer, X509 *subject);
-int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid);
-void X509_set_proxy_flag(X509 *x);
-void X509_set_proxy_pathlen(X509 *x, long l);
-long X509_get_proxy_pathlen(X509 *x);
-
-uint32_t X509_get_extension_flags(X509 *x);
-uint32_t X509_get_key_usage(X509 *x);
-uint32_t X509_get_extended_key_usage(X509 *x);
-const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x);
-const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x);
-const GENERAL_NAMES *X509_get0_authority_issuer(X509 *x);
-const ASN1_INTEGER *X509_get0_authority_serial(X509 *x);
-
-int X509_PURPOSE_get_count(void);
-X509_PURPOSE *X509_PURPOSE_get0(int idx);
-int X509_PURPOSE_get_by_sname(const char *sname);
-int X509_PURPOSE_get_by_id(int id);
-int X509_PURPOSE_add(int id, int trust, int flags,
- int (*ck) (const X509_PURPOSE *, const X509 *, int),
- const char *name, const char *sname, void *arg);
-char *X509_PURPOSE_get0_name(const X509_PURPOSE *xp);
-char *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp);
-int X509_PURPOSE_get_trust(const X509_PURPOSE *xp);
-void X509_PURPOSE_cleanup(void);
-int X509_PURPOSE_get_id(const X509_PURPOSE *);
-
-STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x);
-STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x);
-void X509_email_free(STACK_OF(OPENSSL_STRING) *sk);
-STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x);
-/* Flags for X509_check_* functions */
-
-/*
- * Always check subject name for host match even if subject alt names present
- */
-# define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT 0x1
-/* Disable wildcard matching for dnsName fields and common name. */
-# define X509_CHECK_FLAG_NO_WILDCARDS 0x2
-/* Wildcards must not match a partial label. */
-# define X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS 0x4
-/* Allow (non-partial) wildcards to match multiple labels. */
-# define X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS 0x8
-/* Constraint verifier subdomain patterns to match a single labels. */
-# define X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS 0x10
-/* Never check the subject CN */
-# define X509_CHECK_FLAG_NEVER_CHECK_SUBJECT 0x20
-/*
- * Match reference identifiers starting with "." to any sub-domain.
- * This is a non-public flag, turned on implicitly when the subject
- * reference identity is a DNS name.
- */
-# define _X509_CHECK_FLAG_DOT_SUBDOMAINS 0x8000
-
-int X509_check_host(X509 *x, const char *chk, size_t chklen,
- unsigned int flags, char **peername);
-int X509_check_email(X509 *x, const char *chk, size_t chklen,
- unsigned int flags);
-int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
- unsigned int flags);
-int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags);
-
-ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc);
-ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc);
-int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
- unsigned long chtype);
-
-void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent);
-DEFINE_STACK_OF(X509_POLICY_NODE)
-
-#ifndef OPENSSL_NO_RFC3779
-typedef struct ASRange_st {
- ASN1_INTEGER *min, *max;
-} ASRange;
-
-# define ASIdOrRange_id 0
-# define ASIdOrRange_range 1
-
-typedef struct ASIdOrRange_st {
- int type;
- union {
- ASN1_INTEGER *id;
- ASRange *range;
- } u;
-} ASIdOrRange;
-
-typedef STACK_OF(ASIdOrRange) ASIdOrRanges;
-DEFINE_STACK_OF(ASIdOrRange)
-
-# define ASIdentifierChoice_inherit 0
-# define ASIdentifierChoice_asIdsOrRanges 1
-
-typedef struct ASIdentifierChoice_st {
- int type;
- union {
- ASN1_NULL *inherit;
- ASIdOrRanges *asIdsOrRanges;
- } u;
-} ASIdentifierChoice;
-
-typedef struct ASIdentifiers_st {
- ASIdentifierChoice *asnum, *rdi;
-} ASIdentifiers;
-
-DECLARE_ASN1_FUNCTIONS(ASRange)
-DECLARE_ASN1_FUNCTIONS(ASIdOrRange)
-DECLARE_ASN1_FUNCTIONS(ASIdentifierChoice)
-DECLARE_ASN1_FUNCTIONS(ASIdentifiers)
-
-typedef struct IPAddressRange_st {
- ASN1_BIT_STRING *min, *max;
-} IPAddressRange;
-
-# define IPAddressOrRange_addressPrefix 0
-# define IPAddressOrRange_addressRange 1
-
-typedef struct IPAddressOrRange_st {
- int type;
- union {
- ASN1_BIT_STRING *addressPrefix;
- IPAddressRange *addressRange;
- } u;
-} IPAddressOrRange;
-
-typedef STACK_OF(IPAddressOrRange) IPAddressOrRanges;
-DEFINE_STACK_OF(IPAddressOrRange)
-
-# define IPAddressChoice_inherit 0
-# define IPAddressChoice_addressesOrRanges 1
-
-typedef struct IPAddressChoice_st {
- int type;
- union {
- ASN1_NULL *inherit;
- IPAddressOrRanges *addressesOrRanges;
- } u;
-} IPAddressChoice;
-
-typedef struct IPAddressFamily_st {
- ASN1_OCTET_STRING *addressFamily;
- IPAddressChoice *ipAddressChoice;
-} IPAddressFamily;
-
-typedef STACK_OF(IPAddressFamily) IPAddrBlocks;
-DEFINE_STACK_OF(IPAddressFamily)
-
-DECLARE_ASN1_FUNCTIONS(IPAddressRange)
-DECLARE_ASN1_FUNCTIONS(IPAddressOrRange)
-DECLARE_ASN1_FUNCTIONS(IPAddressChoice)
-DECLARE_ASN1_FUNCTIONS(IPAddressFamily)
-
-/*
- * API tag for elements of the ASIdentifer SEQUENCE.
- */
-# define V3_ASID_ASNUM 0
-# define V3_ASID_RDI 1
-
-/*
- * AFI values, assigned by IANA. It'd be nice to make the AFI
- * handling code totally generic, but there are too many little things
- * that would need to be defined for other address families for it to
- * be worth the trouble.
- */
-# define IANA_AFI_IPV4 1
-# define IANA_AFI_IPV6 2
-
-/*
- * Utilities to construct and extract values from RFC3779 extensions,
- * since some of the encodings (particularly for IP address prefixes
- * and ranges) are a bit tedious to work with directly.
- */
-int X509v3_asid_add_inherit(ASIdentifiers *asid, int which);
-int X509v3_asid_add_id_or_range(ASIdentifiers *asid, int which,
- ASN1_INTEGER *min, ASN1_INTEGER *max);
-int X509v3_addr_add_inherit(IPAddrBlocks *addr,
- const unsigned afi, const unsigned *safi);
-int X509v3_addr_add_prefix(IPAddrBlocks *addr,
- const unsigned afi, const unsigned *safi,
- unsigned char *a, const int prefixlen);
-int X509v3_addr_add_range(IPAddrBlocks *addr,
- const unsigned afi, const unsigned *safi,
- unsigned char *min, unsigned char *max);
-unsigned X509v3_addr_get_afi(const IPAddressFamily *f);
-int X509v3_addr_get_range(IPAddressOrRange *aor, const unsigned afi,
- unsigned char *min, unsigned char *max,
- const int length);
-
-/*
- * Canonical forms.
- */
-int X509v3_asid_is_canonical(ASIdentifiers *asid);
-int X509v3_addr_is_canonical(IPAddrBlocks *addr);
-int X509v3_asid_canonize(ASIdentifiers *asid);
-int X509v3_addr_canonize(IPAddrBlocks *addr);
-
-/*
- * Tests for inheritance and containment.
- */
-int X509v3_asid_inherits(ASIdentifiers *asid);
-int X509v3_addr_inherits(IPAddrBlocks *addr);
-int X509v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b);
-int X509v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b);
-
-/*
- * Check whether RFC 3779 extensions nest properly in chains.
- */
-int X509v3_asid_validate_path(X509_STORE_CTX *);
-int X509v3_addr_validate_path(X509_STORE_CTX *);
-int X509v3_asid_validate_resource_set(STACK_OF(X509) *chain,
- ASIdentifiers *ext,
- int allow_inheritance);
-int X509v3_addr_validate_resource_set(STACK_OF(X509) *chain,
- IPAddrBlocks *ext, int allow_inheritance);
-
-#endif /* OPENSSL_NO_RFC3779 */
-
-DEFINE_STACK_OF(ASN1_STRING)
-
-/*
- * Admission Syntax
- */
-typedef struct NamingAuthority_st NAMING_AUTHORITY;
-typedef struct ProfessionInfo_st PROFESSION_INFO;
-typedef struct Admissions_st ADMISSIONS;
-typedef struct AdmissionSyntax_st ADMISSION_SYNTAX;
-DECLARE_ASN1_FUNCTIONS(NAMING_AUTHORITY)
-DECLARE_ASN1_FUNCTIONS(PROFESSION_INFO)
-DECLARE_ASN1_FUNCTIONS(ADMISSIONS)
-DECLARE_ASN1_FUNCTIONS(ADMISSION_SYNTAX)
-DEFINE_STACK_OF(ADMISSIONS)
-DEFINE_STACK_OF(PROFESSION_INFO)
-typedef STACK_OF(PROFESSION_INFO) PROFESSION_INFOS;
-
-const ASN1_OBJECT *NAMING_AUTHORITY_get0_authorityId(
- const NAMING_AUTHORITY *n);
-const ASN1_IA5STRING *NAMING_AUTHORITY_get0_authorityURL(
- const NAMING_AUTHORITY *n);
-const ASN1_STRING *NAMING_AUTHORITY_get0_authorityText(
- const NAMING_AUTHORITY *n);
-void NAMING_AUTHORITY_set0_authorityId(NAMING_AUTHORITY *n,
- ASN1_OBJECT* namingAuthorityId);
-void NAMING_AUTHORITY_set0_authorityURL(NAMING_AUTHORITY *n,
- ASN1_IA5STRING* namingAuthorityUrl);
-void NAMING_AUTHORITY_set0_authorityText(NAMING_AUTHORITY *n,
- ASN1_STRING* namingAuthorityText);
-
-const GENERAL_NAME *ADMISSION_SYNTAX_get0_admissionAuthority(
- const ADMISSION_SYNTAX *as);
-void ADMISSION_SYNTAX_set0_admissionAuthority(
- ADMISSION_SYNTAX *as, GENERAL_NAME *aa);
-const STACK_OF(ADMISSIONS) *ADMISSION_SYNTAX_get0_contentsOfAdmissions(
- const ADMISSION_SYNTAX *as);
-void ADMISSION_SYNTAX_set0_contentsOfAdmissions(
- ADMISSION_SYNTAX *as, STACK_OF(ADMISSIONS) *a);
-const GENERAL_NAME *ADMISSIONS_get0_admissionAuthority(const ADMISSIONS *a);
-void ADMISSIONS_set0_admissionAuthority(ADMISSIONS *a, GENERAL_NAME *aa);
-const NAMING_AUTHORITY *ADMISSIONS_get0_namingAuthority(const ADMISSIONS *a);
-void ADMISSIONS_set0_namingAuthority(ADMISSIONS *a, NAMING_AUTHORITY *na);
-const PROFESSION_INFOS *ADMISSIONS_get0_professionInfos(const ADMISSIONS *a);
-void ADMISSIONS_set0_professionInfos(ADMISSIONS *a, PROFESSION_INFOS *pi);
-const ASN1_OCTET_STRING *PROFESSION_INFO_get0_addProfessionInfo(
- const PROFESSION_INFO *pi);
-void PROFESSION_INFO_set0_addProfessionInfo(
- PROFESSION_INFO *pi, ASN1_OCTET_STRING *aos);
-const NAMING_AUTHORITY *PROFESSION_INFO_get0_namingAuthority(
- const PROFESSION_INFO *pi);
-void PROFESSION_INFO_set0_namingAuthority(
- PROFESSION_INFO *pi, NAMING_AUTHORITY *na);
-const STACK_OF(ASN1_STRING) *PROFESSION_INFO_get0_professionItems(
- const PROFESSION_INFO *pi);
-void PROFESSION_INFO_set0_professionItems(
- PROFESSION_INFO *pi, STACK_OF(ASN1_STRING) *as);
-const STACK_OF(ASN1_OBJECT) *PROFESSION_INFO_get0_professionOIDs(
- const PROFESSION_INFO *pi);
-void PROFESSION_INFO_set0_professionOIDs(
- PROFESSION_INFO *pi, STACK_OF(ASN1_OBJECT) *po);
-const ASN1_PRINTABLESTRING *PROFESSION_INFO_get0_registrationNumber(
- const PROFESSION_INFO *pi);
-void PROFESSION_INFO_set0_registrationNumber(
- PROFESSION_INFO *pi, ASN1_PRINTABLESTRING *rn);
-
-# ifdef __cplusplus
-}
-# endif
-#endif
diff --git a/include/openssl/x509v3.h.in b/include/openssl/x509v3.h.in
new file mode 100644
index 000000000000..fe7756df9a1a
--- /dev/null
+++ b/include/openssl/x509v3.h.in
@@ -0,0 +1,1017 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
+#ifndef OPENSSL_X509V3_H
+# define OPENSSL_X509V3_H
+# pragma once
+
+# include <openssl/macros.h>
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HEADER_X509V3_H
+# endif
+
+# include <openssl/bio.h>
+# include <openssl/x509.h>
+# include <openssl/conf.h>
+# include <openssl/x509v3err.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward reference */
+struct v3_ext_method;
+struct v3_ext_ctx;
+
+/* Useful typedefs */
+
+typedef void *(*X509V3_EXT_NEW)(void);
+typedef void (*X509V3_EXT_FREE) (void *);
+typedef void *(*X509V3_EXT_D2I)(void *, const unsigned char **, long);
+typedef int (*X509V3_EXT_I2D) (const void *, unsigned char **);
+typedef STACK_OF(CONF_VALUE) *
+ (*X509V3_EXT_I2V) (const struct v3_ext_method *method, void *ext,
+ STACK_OF(CONF_VALUE) *extlist);
+typedef void *(*X509V3_EXT_V2I)(const struct v3_ext_method *method,
+ struct v3_ext_ctx *ctx,
+ STACK_OF(CONF_VALUE) *values);
+typedef char *(*X509V3_EXT_I2S)(const struct v3_ext_method *method,
+ void *ext);
+typedef void *(*X509V3_EXT_S2I)(const struct v3_ext_method *method,
+ struct v3_ext_ctx *ctx, const char *str);
+typedef int (*X509V3_EXT_I2R) (const struct v3_ext_method *method, void *ext,
+ BIO *out, int indent);
+typedef void *(*X509V3_EXT_R2I)(const struct v3_ext_method *method,
+ struct v3_ext_ctx *ctx, const char *str);
+
+/* V3 extension structure */
+
+struct v3_ext_method {
+ int ext_nid;
+ int ext_flags;
+/* If this is set the following four fields are ignored */
+ ASN1_ITEM_EXP *it;
+/* Old style ASN1 calls */
+ X509V3_EXT_NEW ext_new;
+ X509V3_EXT_FREE ext_free;
+ X509V3_EXT_D2I d2i;
+ X509V3_EXT_I2D i2d;
+/* The following pair is used for string extensions */
+ X509V3_EXT_I2S i2s;
+ X509V3_EXT_S2I s2i;
+/* The following pair is used for multi-valued extensions */
+ X509V3_EXT_I2V i2v;
+ X509V3_EXT_V2I v2i;
+/* The following are used for raw extensions */
+ X509V3_EXT_I2R i2r;
+ X509V3_EXT_R2I r2i;
+ void *usr_data; /* Any extension specific data */
+};
+
+typedef struct X509V3_CONF_METHOD_st {
+ char *(*get_string) (void *db, const char *section, const char *value);
+ STACK_OF(CONF_VALUE) *(*get_section) (void *db, const char *section);
+ void (*free_string) (void *db, char *string);
+ void (*free_section) (void *db, STACK_OF(CONF_VALUE) *section);
+} X509V3_CONF_METHOD;
+
+/* Context specific info for producing X509 v3 extensions*/
+struct v3_ext_ctx {
+# define X509V3_CTX_TEST 0x1
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# define CTX_TEST X509V3_CTX_TEST
+# endif
+# define X509V3_CTX_REPLACE 0x2
+ int flags;
+ X509 *issuer_cert;
+ X509 *subject_cert;
+ X509_REQ *subject_req;
+ X509_CRL *crl;
+ X509V3_CONF_METHOD *db_meth;
+ void *db;
+ EVP_PKEY *issuer_pkey;
+/* Maybe more here */
+};
+
+typedef struct v3_ext_method X509V3_EXT_METHOD;
+
+{-
+ generate_stack_macros("X509V3_EXT_METHOD");
+-}
+
+/* ext_flags values */
+# define X509V3_EXT_DYNAMIC 0x1
+# define X509V3_EXT_CTX_DEP 0x2
+# define X509V3_EXT_MULTILINE 0x4
+
+typedef BIT_STRING_BITNAME ENUMERATED_NAMES;
+
+typedef struct BASIC_CONSTRAINTS_st {
+ int ca;
+ ASN1_INTEGER *pathlen;
+} BASIC_CONSTRAINTS;
+
+typedef struct PKEY_USAGE_PERIOD_st {
+ ASN1_GENERALIZEDTIME *notBefore;
+ ASN1_GENERALIZEDTIME *notAfter;
+} PKEY_USAGE_PERIOD;
+
+typedef struct otherName_st {
+ ASN1_OBJECT *type_id;
+ ASN1_TYPE *value;
+} OTHERNAME;
+
+typedef struct EDIPartyName_st {
+ ASN1_STRING *nameAssigner;
+ ASN1_STRING *partyName;
+} EDIPARTYNAME;
+
+typedef struct GENERAL_NAME_st {
+# define GEN_OTHERNAME 0
+# define GEN_EMAIL 1
+# define GEN_DNS 2
+# define GEN_X400 3
+# define GEN_DIRNAME 4
+# define GEN_EDIPARTY 5
+# define GEN_URI 6
+# define GEN_IPADD 7
+# define GEN_RID 8
+ int type;
+ union {
+ char *ptr;
+ OTHERNAME *otherName; /* otherName */
+ ASN1_IA5STRING *rfc822Name;
+ ASN1_IA5STRING *dNSName;
+ ASN1_STRING *x400Address;
+ X509_NAME *directoryName;
+ EDIPARTYNAME *ediPartyName;
+ ASN1_IA5STRING *uniformResourceIdentifier;
+ ASN1_OCTET_STRING *iPAddress;
+ ASN1_OBJECT *registeredID;
+ /* Old names */
+ ASN1_OCTET_STRING *ip; /* iPAddress */
+ X509_NAME *dirn; /* dirn */
+ ASN1_IA5STRING *ia5; /* rfc822Name, dNSName,
+ * uniformResourceIdentifier */
+ ASN1_OBJECT *rid; /* registeredID */
+ ASN1_TYPE *other; /* x400Address */
+ } d;
+} GENERAL_NAME;
+
+typedef struct ACCESS_DESCRIPTION_st {
+ ASN1_OBJECT *method;
+ GENERAL_NAME *location;
+} ACCESS_DESCRIPTION;
+
+{-
+ generate_stack_macros("ACCESS_DESCRIPTION")
+ .generate_stack_macros("GENERAL_NAME");
+-}
+
+typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS;
+typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE;
+typedef STACK_OF(ASN1_INTEGER) TLS_FEATURE;
+typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES;
+
+{-
+ generate_stack_macros("GENERAL_NAMES");
+-}
+
+typedef struct DIST_POINT_NAME_st {
+ int type;
+ union {
+ GENERAL_NAMES *fullname;
+ STACK_OF(X509_NAME_ENTRY) *relativename;
+ } name;
+/* If relativename then this contains the full distribution point name */
+ X509_NAME *dpname;
+} DIST_POINT_NAME;
+/* All existing reasons */
+# define CRLDP_ALL_REASONS 0x807f
+
+# define CRL_REASON_NONE -1
+# define CRL_REASON_UNSPECIFIED 0
+# define CRL_REASON_KEY_COMPROMISE 1
+# define CRL_REASON_CA_COMPROMISE 2
+# define CRL_REASON_AFFILIATION_CHANGED 3
+# define CRL_REASON_SUPERSEDED 4
+# define CRL_REASON_CESSATION_OF_OPERATION 5
+# define CRL_REASON_CERTIFICATE_HOLD 6
+# define CRL_REASON_REMOVE_FROM_CRL 8
+# define CRL_REASON_PRIVILEGE_WITHDRAWN 9
+# define CRL_REASON_AA_COMPROMISE 10
+
+struct DIST_POINT_st {
+ DIST_POINT_NAME *distpoint;
+ ASN1_BIT_STRING *reasons;
+ GENERAL_NAMES *CRLissuer;
+ int dp_reasons;
+};
+
+{-
+ generate_stack_macros("DIST_POINT");
+-}
+
+typedef STACK_OF(DIST_POINT) CRL_DIST_POINTS;
+
+struct AUTHORITY_KEYID_st {
+ ASN1_OCTET_STRING *keyid;
+ GENERAL_NAMES *issuer;
+ ASN1_INTEGER *serial;
+};
+
+/* Strong extranet structures */
+
+typedef struct SXNET_ID_st {
+ ASN1_INTEGER *zone;
+ ASN1_OCTET_STRING *user;
+} SXNETID;
+
+{-
+ generate_stack_macros("SXNETID");
+-}
+
+
+typedef struct SXNET_st {
+ ASN1_INTEGER *version;
+ STACK_OF(SXNETID) *ids;
+} SXNET;
+
+typedef struct ISSUER_SIGN_TOOL_st {
+ ASN1_UTF8STRING *signTool;
+ ASN1_UTF8STRING *cATool;
+ ASN1_UTF8STRING *signToolCert;
+ ASN1_UTF8STRING *cAToolCert;
+} ISSUER_SIGN_TOOL;
+
+typedef struct NOTICEREF_st {
+ ASN1_STRING *organization;
+ STACK_OF(ASN1_INTEGER) *noticenos;
+} NOTICEREF;
+
+typedef struct USERNOTICE_st {
+ NOTICEREF *noticeref;
+ ASN1_STRING *exptext;
+} USERNOTICE;
+
+typedef struct POLICYQUALINFO_st {
+ ASN1_OBJECT *pqualid;
+ union {
+ ASN1_IA5STRING *cpsuri;
+ USERNOTICE *usernotice;
+ ASN1_TYPE *other;
+ } d;
+} POLICYQUALINFO;
+
+{-
+ generate_stack_macros("POLICYQUALINFO");
+-}
+
+
+typedef struct POLICYINFO_st {
+ ASN1_OBJECT *policyid;
+ STACK_OF(POLICYQUALINFO) *qualifiers;
+} POLICYINFO;
+
+{-
+ generate_stack_macros("POLICYINFO");
+-}
+
+typedef STACK_OF(POLICYINFO) CERTIFICATEPOLICIES;
+
+typedef struct POLICY_MAPPING_st {
+ ASN1_OBJECT *issuerDomainPolicy;
+ ASN1_OBJECT *subjectDomainPolicy;
+} POLICY_MAPPING;
+
+{-
+ generate_stack_macros("POLICY_MAPPING");
+-}
+
+typedef STACK_OF(POLICY_MAPPING) POLICY_MAPPINGS;
+
+typedef struct GENERAL_SUBTREE_st {
+ GENERAL_NAME *base;
+ ASN1_INTEGER *minimum;
+ ASN1_INTEGER *maximum;
+} GENERAL_SUBTREE;
+
+{-
+ generate_stack_macros("GENERAL_SUBTREE");
+-}
+
+struct NAME_CONSTRAINTS_st {
+ STACK_OF(GENERAL_SUBTREE) *permittedSubtrees;
+ STACK_OF(GENERAL_SUBTREE) *excludedSubtrees;
+};
+
+typedef struct POLICY_CONSTRAINTS_st {
+ ASN1_INTEGER *requireExplicitPolicy;
+ ASN1_INTEGER *inhibitPolicyMapping;
+} POLICY_CONSTRAINTS;
+
+/* Proxy certificate structures, see RFC 3820 */
+typedef struct PROXY_POLICY_st {
+ ASN1_OBJECT *policyLanguage;
+ ASN1_OCTET_STRING *policy;
+} PROXY_POLICY;
+
+typedef struct PROXY_CERT_INFO_EXTENSION_st {
+ ASN1_INTEGER *pcPathLengthConstraint;
+ PROXY_POLICY *proxyPolicy;
+} PROXY_CERT_INFO_EXTENSION;
+
+DECLARE_ASN1_FUNCTIONS(PROXY_POLICY)
+DECLARE_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION)
+
+struct ISSUING_DIST_POINT_st {
+ DIST_POINT_NAME *distpoint;
+ int onlyuser;
+ int onlyCA;
+ ASN1_BIT_STRING *onlysomereasons;
+ int indirectCRL;
+ int onlyattr;
+};
+
+/* Values in idp_flags field */
+/* IDP present */
+# define IDP_PRESENT 0x1
+/* IDP values inconsistent */
+# define IDP_INVALID 0x2
+/* onlyuser true */
+# define IDP_ONLYUSER 0x4
+/* onlyCA true */
+# define IDP_ONLYCA 0x8
+/* onlyattr true */
+# define IDP_ONLYATTR 0x10
+/* indirectCRL true */
+# define IDP_INDIRECT 0x20
+/* onlysomereasons present */
+# define IDP_REASONS 0x40
+
+# define X509V3_conf_err(val) ERR_add_error_data(6, \
+ "section:", (val)->section, \
+ ",name:", (val)->name, ",value:", (val)->value)
+
+# define X509V3_set_ctx_test(ctx) \
+ X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, X509V3_CTX_TEST)
+# define X509V3_set_ctx_nodb(ctx) (ctx)->db = NULL;
+
+# define EXT_BITSTRING(nid, table) { nid, 0, ASN1_ITEM_ref(ASN1_BIT_STRING), \
+ 0,0,0,0, \
+ 0,0, \
+ (X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, \
+ (X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, \
+ NULL, NULL, \
+ table}
+
+# define EXT_IA5STRING(nid) { nid, 0, ASN1_ITEM_ref(ASN1_IA5STRING), \
+ 0,0,0,0, \
+ (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, \
+ (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, \
+ 0,0,0,0, \
+ NULL}
+
+#define EXT_UTF8STRING(nid) { nid, 0, ASN1_ITEM_ref(ASN1_UTF8STRING), \
+ 0,0,0,0, \
+ (X509V3_EXT_I2S)i2s_ASN1_UTF8STRING, \
+ (X509V3_EXT_S2I)s2i_ASN1_UTF8STRING, \
+ 0,0,0,0, \
+ NULL}
+
+# define EXT_END { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+/* X509_PURPOSE stuff */
+
+# define EXFLAG_BCONS 0x1
+# define EXFLAG_KUSAGE 0x2
+# define EXFLAG_XKUSAGE 0x4
+# define EXFLAG_NSCERT 0x8
+
+# define EXFLAG_CA 0x10
+# define EXFLAG_SI 0x20 /* self-issued, maybe not self-signed */
+# define EXFLAG_V1 0x40
+# define EXFLAG_INVALID 0x80
+/* EXFLAG_SET is set to indicate that some values have been precomputed */
+# define EXFLAG_SET 0x100
+# define EXFLAG_CRITICAL 0x200
+# define EXFLAG_PROXY 0x400
+
+# define EXFLAG_INVALID_POLICY 0x800
+# define EXFLAG_FRESHEST 0x1000
+# define EXFLAG_SS 0x2000 /* cert is apparently self-signed */
+
+# define EXFLAG_BCONS_CRITICAL 0x10000
+# define EXFLAG_AKID_CRITICAL 0x20000
+# define EXFLAG_SKID_CRITICAL 0x40000
+# define EXFLAG_SAN_CRITICAL 0x80000
+# define EXFLAG_NO_FINGERPRINT 0x100000
+
+# define KU_DIGITAL_SIGNATURE 0x0080
+# define KU_NON_REPUDIATION 0x0040
+# define KU_KEY_ENCIPHERMENT 0x0020
+# define KU_DATA_ENCIPHERMENT 0x0010
+# define KU_KEY_AGREEMENT 0x0008
+# define KU_KEY_CERT_SIGN 0x0004
+# define KU_CRL_SIGN 0x0002
+# define KU_ENCIPHER_ONLY 0x0001
+# define KU_DECIPHER_ONLY 0x8000
+
+# define NS_SSL_CLIENT 0x80
+# define NS_SSL_SERVER 0x40
+# define NS_SMIME 0x20
+# define NS_OBJSIGN 0x10
+# define NS_SSL_CA 0x04
+# define NS_SMIME_CA 0x02
+# define NS_OBJSIGN_CA 0x01
+# define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA)
+
+# define XKU_SSL_SERVER 0x1
+# define XKU_SSL_CLIENT 0x2
+# define XKU_SMIME 0x4
+# define XKU_CODE_SIGN 0x8
+# define XKU_SGC 0x10 /* Netscape or MS Server-Gated Crypto */
+# define XKU_OCSP_SIGN 0x20
+# define XKU_TIMESTAMP 0x40
+# define XKU_DVCS 0x80
+# define XKU_ANYEKU 0x100
+
+# define X509_PURPOSE_DYNAMIC 0x1
+# define X509_PURPOSE_DYNAMIC_NAME 0x2
+
+typedef struct x509_purpose_st {
+ int purpose;
+ int trust; /* Default trust ID */
+ int flags;
+ int (*check_purpose) (const struct x509_purpose_st *, const X509 *, int);
+ char *name;
+ char *sname;
+ void *usr_data;
+} X509_PURPOSE;
+
+{-
+ generate_stack_macros("X509_PURPOSE");
+-}
+
+
+# define X509_PURPOSE_SSL_CLIENT 1
+# define X509_PURPOSE_SSL_SERVER 2
+# define X509_PURPOSE_NS_SSL_SERVER 3
+# define X509_PURPOSE_SMIME_SIGN 4
+# define X509_PURPOSE_SMIME_ENCRYPT 5
+# define X509_PURPOSE_CRL_SIGN 6
+# define X509_PURPOSE_ANY 7
+# define X509_PURPOSE_OCSP_HELPER 8
+# define X509_PURPOSE_TIMESTAMP_SIGN 9
+
+# define X509_PURPOSE_MIN 1
+# define X509_PURPOSE_MAX 9
+
+/* Flags for X509V3_EXT_print() */
+
+# define X509V3_EXT_UNKNOWN_MASK (0xfL << 16)
+/* Return error for unknown extensions */
+# define X509V3_EXT_DEFAULT 0
+/* Print error for unknown extensions */
+# define X509V3_EXT_ERROR_UNKNOWN (1L << 16)
+/* ASN1 parse unknown extensions */
+# define X509V3_EXT_PARSE_UNKNOWN (2L << 16)
+/* BIO_dump unknown extensions */
+# define X509V3_EXT_DUMP_UNKNOWN (3L << 16)
+
+/* Flags for X509V3_add1_i2d */
+
+# define X509V3_ADD_OP_MASK 0xfL
+# define X509V3_ADD_DEFAULT 0L
+# define X509V3_ADD_APPEND 1L
+# define X509V3_ADD_REPLACE 2L
+# define X509V3_ADD_REPLACE_EXISTING 3L
+# define X509V3_ADD_KEEP_EXISTING 4L
+# define X509V3_ADD_DELETE 5L
+# define X509V3_ADD_SILENT 0x10
+
+DECLARE_ASN1_FUNCTIONS(BASIC_CONSTRAINTS)
+
+DECLARE_ASN1_FUNCTIONS(SXNET)
+DECLARE_ASN1_FUNCTIONS(SXNETID)
+
+DECLARE_ASN1_FUNCTIONS(ISSUER_SIGN_TOOL)
+
+int SXNET_add_id_asc(SXNET **psx, const char *zone, const char *user, int userlen);
+int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, const char *user,
+ int userlen);
+int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *izone, const char *user,
+ int userlen);
+
+ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, const char *zone);
+ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone);
+ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone);
+
+DECLARE_ASN1_FUNCTIONS(AUTHORITY_KEYID)
+
+DECLARE_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD)
+
+DECLARE_ASN1_FUNCTIONS(GENERAL_NAME)
+DECLARE_ASN1_DUP_FUNCTION(GENERAL_NAME)
+int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b);
+
+ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval);
+STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
+ ASN1_BIT_STRING *bits,
+ STACK_OF(CONF_VALUE) *extlist);
+char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5);
+ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, const char *str);
+char *i2s_ASN1_UTF8STRING(X509V3_EXT_METHOD *method, ASN1_UTF8STRING *utf8);
+ASN1_UTF8STRING *s2i_ASN1_UTF8STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, const char *str);
+
+STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
+ GENERAL_NAME *gen,
+ STACK_OF(CONF_VALUE) *ret);
+int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen);
+
+DECLARE_ASN1_FUNCTIONS(GENERAL_NAMES)
+
+STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
+ GENERAL_NAMES *gen,
+ STACK_OF(CONF_VALUE) *extlist);
+GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+
+DECLARE_ASN1_FUNCTIONS(OTHERNAME)
+DECLARE_ASN1_FUNCTIONS(EDIPARTYNAME)
+int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b);
+void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value);
+void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype);
+int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
+ ASN1_OBJECT *oid, ASN1_TYPE *value);
+int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen,
+ ASN1_OBJECT **poid, ASN1_TYPE **pvalue);
+
+char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
+ const ASN1_OCTET_STRING *ia5);
+ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, const char *str);
+
+DECLARE_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE)
+int i2a_ACCESS_DESCRIPTION(BIO *bp, const ACCESS_DESCRIPTION *a);
+
+DECLARE_ASN1_ALLOC_FUNCTIONS(TLS_FEATURE)
+
+DECLARE_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
+DECLARE_ASN1_FUNCTIONS(POLICYINFO)
+DECLARE_ASN1_FUNCTIONS(POLICYQUALINFO)
+DECLARE_ASN1_FUNCTIONS(USERNOTICE)
+DECLARE_ASN1_FUNCTIONS(NOTICEREF)
+
+DECLARE_ASN1_FUNCTIONS(CRL_DIST_POINTS)
+DECLARE_ASN1_FUNCTIONS(DIST_POINT)
+DECLARE_ASN1_FUNCTIONS(DIST_POINT_NAME)
+DECLARE_ASN1_FUNCTIONS(ISSUING_DIST_POINT)
+
+int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, const X509_NAME *iname);
+
+int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc);
+int NAME_CONSTRAINTS_check_CN(X509 *x, NAME_CONSTRAINTS *nc);
+
+DECLARE_ASN1_FUNCTIONS(ACCESS_DESCRIPTION)
+DECLARE_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS)
+
+DECLARE_ASN1_ITEM(POLICY_MAPPING)
+DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING)
+DECLARE_ASN1_ITEM(POLICY_MAPPINGS)
+
+DECLARE_ASN1_ITEM(GENERAL_SUBTREE)
+DECLARE_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
+
+DECLARE_ASN1_ITEM(NAME_CONSTRAINTS)
+DECLARE_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
+
+DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS)
+DECLARE_ASN1_ITEM(POLICY_CONSTRAINTS)
+
+GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
+ const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, int gen_type,
+ const char *value, int is_nc);
+
+# ifdef OPENSSL_CONF_H
+GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, CONF_VALUE *cnf);
+GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
+ const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, CONF_VALUE *cnf,
+ int is_nc);
+
+void X509V3_conf_free(CONF_VALUE *val);
+
+X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
+ const char *value);
+X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, const char *name,
+ const char *value);
+int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section,
+ STACK_OF(X509_EXTENSION) **sk);
+int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
+ X509 *cert);
+int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
+ X509_REQ *req);
+int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
+ X509_CRL *crl);
+
+X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf,
+ X509V3_CTX *ctx, int ext_nid,
+ const char *value);
+X509_EXTENSION *X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ const char *name, const char *value);
+int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ const char *section, X509 *cert);
+int X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ const char *section, X509_REQ *req);
+int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ const char *section, X509_CRL *crl);
+
+int X509V3_add_value_bool_nf(const char *name, int asn1_bool,
+ STACK_OF(CONF_VALUE) **extlist);
+int X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool);
+int X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint);
+void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf);
+void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash);
+# endif
+
+char *X509V3_get_string(X509V3_CTX *ctx, const char *name, const char *section);
+STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, const char *section);
+void X509V3_string_free(X509V3_CTX *ctx, char *str);
+void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section);
+void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subject,
+ X509_REQ *req, X509_CRL *crl, int flags);
+/* For API backward compatibility, this is separate from X509V3_set_ctx(): */
+int X509V3_set_issuer_pkey(X509V3_CTX *ctx, EVP_PKEY *pkey);
+
+int X509V3_add_value(const char *name, const char *value,
+ STACK_OF(CONF_VALUE) **extlist);
+int X509V3_add_value_uchar(const char *name, const unsigned char *value,
+ STACK_OF(CONF_VALUE) **extlist);
+int X509V3_add_value_bool(const char *name, int asn1_bool,
+ STACK_OF(CONF_VALUE) **extlist);
+int X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint,
+ STACK_OF(CONF_VALUE) **extlist);
+char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, const ASN1_INTEGER *aint);
+ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *meth, const char *value);
+char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *meth, const ASN1_ENUMERATED *aint);
+char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *meth,
+ const ASN1_ENUMERATED *aint);
+int X509V3_EXT_add(X509V3_EXT_METHOD *ext);
+int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist);
+int X509V3_EXT_add_alias(int nid_to, int nid_from);
+void X509V3_EXT_cleanup(void);
+
+const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext);
+const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid);
+int X509V3_add_standard_extensions(void);
+STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line);
+void *X509V3_EXT_d2i(X509_EXTENSION *ext);
+void *X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *x, int nid, int *crit,
+ int *idx);
+
+X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc);
+int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
+ int crit, unsigned long flags);
+
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
+/* The new declarations are in crypto.h, but the old ones were here. */
+# define hex_to_string OPENSSL_buf2hexstr
+# define string_to_hex OPENSSL_hexstr2buf
+#endif
+
+void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
+ int ml);
+int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag,
+ int indent);
+#ifndef OPENSSL_NO_STDIO
+int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent);
+#endif
+int X509V3_extensions_print(BIO *out, const char *title,
+ const STACK_OF(X509_EXTENSION) *exts,
+ unsigned long flag, int indent);
+
+int X509_check_ca(X509 *x);
+int X509_check_purpose(X509 *x, int id, int ca);
+int X509_supported_extension(X509_EXTENSION *ex);
+int X509_PURPOSE_set(int *p, int purpose);
+int X509_check_issued(X509 *issuer, X509 *subject);
+int X509_check_akid(const X509 *issuer, const AUTHORITY_KEYID *akid);
+void X509_set_proxy_flag(X509 *x);
+void X509_set_proxy_pathlen(X509 *x, long l);
+long X509_get_proxy_pathlen(X509 *x);
+
+uint32_t X509_get_extension_flags(X509 *x);
+uint32_t X509_get_key_usage(X509 *x);
+uint32_t X509_get_extended_key_usage(X509 *x);
+const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x);
+const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x);
+const GENERAL_NAMES *X509_get0_authority_issuer(X509 *x);
+const ASN1_INTEGER *X509_get0_authority_serial(X509 *x);
+
+int X509_PURPOSE_get_count(void);
+X509_PURPOSE *X509_PURPOSE_get0(int idx);
+int X509_PURPOSE_get_by_sname(const char *sname);
+int X509_PURPOSE_get_by_id(int id);
+int X509_PURPOSE_add(int id, int trust, int flags,
+ int (*ck) (const X509_PURPOSE *, const X509 *, int),
+ const char *name, const char *sname, void *arg);
+char *X509_PURPOSE_get0_name(const X509_PURPOSE *xp);
+char *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp);
+int X509_PURPOSE_get_trust(const X509_PURPOSE *xp);
+void X509_PURPOSE_cleanup(void);
+int X509_PURPOSE_get_id(const X509_PURPOSE *);
+
+STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x);
+STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x);
+void X509_email_free(STACK_OF(OPENSSL_STRING) *sk);
+STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x);
+/* Flags for X509_check_* functions */
+
+/*
+ * Always check subject name for host match even if subject alt names present
+ */
+# define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT 0x1
+/* Disable wildcard matching for dnsName fields and common name. */
+# define X509_CHECK_FLAG_NO_WILDCARDS 0x2
+/* Wildcards must not match a partial label. */
+# define X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS 0x4
+/* Allow (non-partial) wildcards to match multiple labels. */
+# define X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS 0x8
+/* Constraint verifier subdomain patterns to match a single labels. */
+# define X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS 0x10
+/* Never check the subject CN */
+# define X509_CHECK_FLAG_NEVER_CHECK_SUBJECT 0x20
+/*
+ * Match reference identifiers starting with "." to any sub-domain.
+ * This is a non-public flag, turned on implicitly when the subject
+ * reference identity is a DNS name.
+ */
+# define _X509_CHECK_FLAG_DOT_SUBDOMAINS 0x8000
+
+int X509_check_host(X509 *x, const char *chk, size_t chklen,
+ unsigned int flags, char **peername);
+int X509_check_email(X509 *x, const char *chk, size_t chklen,
+ unsigned int flags);
+int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
+ unsigned int flags);
+int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags);
+
+ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc);
+ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc);
+int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
+ unsigned long chtype);
+
+void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent);
+{-
+ generate_stack_macros("X509_POLICY_NODE");
+-}
+
+
+#ifndef OPENSSL_NO_RFC3779
+typedef struct ASRange_st {
+ ASN1_INTEGER *min, *max;
+} ASRange;
+
+# define ASIdOrRange_id 0
+# define ASIdOrRange_range 1
+
+typedef struct ASIdOrRange_st {
+ int type;
+ union {
+ ASN1_INTEGER *id;
+ ASRange *range;
+ } u;
+} ASIdOrRange;
+
+{-
+ generate_stack_macros("ASIdOrRange");
+-}
+
+typedef STACK_OF(ASIdOrRange) ASIdOrRanges;
+
+# define ASIdentifierChoice_inherit 0
+# define ASIdentifierChoice_asIdsOrRanges 1
+
+typedef struct ASIdentifierChoice_st {
+ int type;
+ union {
+ ASN1_NULL *inherit;
+ ASIdOrRanges *asIdsOrRanges;
+ } u;
+} ASIdentifierChoice;
+
+typedef struct ASIdentifiers_st {
+ ASIdentifierChoice *asnum, *rdi;
+} ASIdentifiers;
+
+DECLARE_ASN1_FUNCTIONS(ASRange)
+DECLARE_ASN1_FUNCTIONS(ASIdOrRange)
+DECLARE_ASN1_FUNCTIONS(ASIdentifierChoice)
+DECLARE_ASN1_FUNCTIONS(ASIdentifiers)
+
+typedef struct IPAddressRange_st {
+ ASN1_BIT_STRING *min, *max;
+} IPAddressRange;
+
+# define IPAddressOrRange_addressPrefix 0
+# define IPAddressOrRange_addressRange 1
+
+typedef struct IPAddressOrRange_st {
+ int type;
+ union {
+ ASN1_BIT_STRING *addressPrefix;
+ IPAddressRange *addressRange;
+ } u;
+} IPAddressOrRange;
+
+{-
+ generate_stack_macros("IPAddressOrRange");
+-}
+
+typedef STACK_OF(IPAddressOrRange) IPAddressOrRanges;
+
+# define IPAddressChoice_inherit 0
+# define IPAddressChoice_addressesOrRanges 1
+
+typedef struct IPAddressChoice_st {
+ int type;
+ union {
+ ASN1_NULL *inherit;
+ IPAddressOrRanges *addressesOrRanges;
+ } u;
+} IPAddressChoice;
+
+typedef struct IPAddressFamily_st {
+ ASN1_OCTET_STRING *addressFamily;
+ IPAddressChoice *ipAddressChoice;
+} IPAddressFamily;
+
+{-
+ generate_stack_macros("IPAddressFamily");
+-}
+
+
+typedef STACK_OF(IPAddressFamily) IPAddrBlocks;
+
+DECLARE_ASN1_FUNCTIONS(IPAddressRange)
+DECLARE_ASN1_FUNCTIONS(IPAddressOrRange)
+DECLARE_ASN1_FUNCTIONS(IPAddressChoice)
+DECLARE_ASN1_FUNCTIONS(IPAddressFamily)
+
+/*
+ * API tag for elements of the ASIdentifer SEQUENCE.
+ */
+# define V3_ASID_ASNUM 0
+# define V3_ASID_RDI 1
+
+/*
+ * AFI values, assigned by IANA. It'd be nice to make the AFI
+ * handling code totally generic, but there are too many little things
+ * that would need to be defined for other address families for it to
+ * be worth the trouble.
+ */
+# define IANA_AFI_IPV4 1
+# define IANA_AFI_IPV6 2
+
+/*
+ * Utilities to construct and extract values from RFC3779 extensions,
+ * since some of the encodings (particularly for IP address prefixes
+ * and ranges) are a bit tedious to work with directly.
+ */
+int X509v3_asid_add_inherit(ASIdentifiers *asid, int which);
+int X509v3_asid_add_id_or_range(ASIdentifiers *asid, int which,
+ ASN1_INTEGER *min, ASN1_INTEGER *max);
+int X509v3_addr_add_inherit(IPAddrBlocks *addr,
+ const unsigned afi, const unsigned *safi);
+int X509v3_addr_add_prefix(IPAddrBlocks *addr,
+ const unsigned afi, const unsigned *safi,
+ unsigned char *a, const int prefixlen);
+int X509v3_addr_add_range(IPAddrBlocks *addr,
+ const unsigned afi, const unsigned *safi,
+ unsigned char *min, unsigned char *max);
+unsigned X509v3_addr_get_afi(const IPAddressFamily *f);
+int X509v3_addr_get_range(IPAddressOrRange *aor, const unsigned afi,
+ unsigned char *min, unsigned char *max,
+ const int length);
+
+/*
+ * Canonical forms.
+ */
+int X509v3_asid_is_canonical(ASIdentifiers *asid);
+int X509v3_addr_is_canonical(IPAddrBlocks *addr);
+int X509v3_asid_canonize(ASIdentifiers *asid);
+int X509v3_addr_canonize(IPAddrBlocks *addr);
+
+/*
+ * Tests for inheritance and containment.
+ */
+int X509v3_asid_inherits(ASIdentifiers *asid);
+int X509v3_addr_inherits(IPAddrBlocks *addr);
+int X509v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b);
+int X509v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b);
+
+/*
+ * Check whether RFC 3779 extensions nest properly in chains.
+ */
+int X509v3_asid_validate_path(X509_STORE_CTX *);
+int X509v3_addr_validate_path(X509_STORE_CTX *);
+int X509v3_asid_validate_resource_set(STACK_OF(X509) *chain,
+ ASIdentifiers *ext,
+ int allow_inheritance);
+int X509v3_addr_validate_resource_set(STACK_OF(X509) *chain,
+ IPAddrBlocks *ext, int allow_inheritance);
+
+#endif /* OPENSSL_NO_RFC3779 */
+
+{-
+ generate_stack_macros("ASN1_STRING");
+-}
+
+/*
+ * Admission Syntax
+ */
+typedef struct NamingAuthority_st NAMING_AUTHORITY;
+typedef struct ProfessionInfo_st PROFESSION_INFO;
+typedef struct Admissions_st ADMISSIONS;
+typedef struct AdmissionSyntax_st ADMISSION_SYNTAX;
+DECLARE_ASN1_FUNCTIONS(NAMING_AUTHORITY)
+DECLARE_ASN1_FUNCTIONS(PROFESSION_INFO)
+DECLARE_ASN1_FUNCTIONS(ADMISSIONS)
+DECLARE_ASN1_FUNCTIONS(ADMISSION_SYNTAX)
+{-
+ generate_stack_macros("PROFESSION_INFO")
+ .generate_stack_macros("ADMISSIONS");
+-}
+typedef STACK_OF(PROFESSION_INFO) PROFESSION_INFOS;
+
+const ASN1_OBJECT *NAMING_AUTHORITY_get0_authorityId(
+ const NAMING_AUTHORITY *n);
+const ASN1_IA5STRING *NAMING_AUTHORITY_get0_authorityURL(
+ const NAMING_AUTHORITY *n);
+const ASN1_STRING *NAMING_AUTHORITY_get0_authorityText(
+ const NAMING_AUTHORITY *n);
+void NAMING_AUTHORITY_set0_authorityId(NAMING_AUTHORITY *n,
+ ASN1_OBJECT* namingAuthorityId);
+void NAMING_AUTHORITY_set0_authorityURL(NAMING_AUTHORITY *n,
+ ASN1_IA5STRING* namingAuthorityUrl);
+void NAMING_AUTHORITY_set0_authorityText(NAMING_AUTHORITY *n,
+ ASN1_STRING* namingAuthorityText);
+
+const GENERAL_NAME *ADMISSION_SYNTAX_get0_admissionAuthority(
+ const ADMISSION_SYNTAX *as);
+void ADMISSION_SYNTAX_set0_admissionAuthority(
+ ADMISSION_SYNTAX *as, GENERAL_NAME *aa);
+const STACK_OF(ADMISSIONS) *ADMISSION_SYNTAX_get0_contentsOfAdmissions(
+ const ADMISSION_SYNTAX *as);
+void ADMISSION_SYNTAX_set0_contentsOfAdmissions(
+ ADMISSION_SYNTAX *as, STACK_OF(ADMISSIONS) *a);
+const GENERAL_NAME *ADMISSIONS_get0_admissionAuthority(const ADMISSIONS *a);
+void ADMISSIONS_set0_admissionAuthority(ADMISSIONS *a, GENERAL_NAME *aa);
+const NAMING_AUTHORITY *ADMISSIONS_get0_namingAuthority(const ADMISSIONS *a);
+void ADMISSIONS_set0_namingAuthority(ADMISSIONS *a, NAMING_AUTHORITY *na);
+const PROFESSION_INFOS *ADMISSIONS_get0_professionInfos(const ADMISSIONS *a);
+void ADMISSIONS_set0_professionInfos(ADMISSIONS *a, PROFESSION_INFOS *pi);
+const ASN1_OCTET_STRING *PROFESSION_INFO_get0_addProfessionInfo(
+ const PROFESSION_INFO *pi);
+void PROFESSION_INFO_set0_addProfessionInfo(
+ PROFESSION_INFO *pi, ASN1_OCTET_STRING *aos);
+const NAMING_AUTHORITY *PROFESSION_INFO_get0_namingAuthority(
+ const PROFESSION_INFO *pi);
+void PROFESSION_INFO_set0_namingAuthority(
+ PROFESSION_INFO *pi, NAMING_AUTHORITY *na);
+const STACK_OF(ASN1_STRING) *PROFESSION_INFO_get0_professionItems(
+ const PROFESSION_INFO *pi);
+void PROFESSION_INFO_set0_professionItems(
+ PROFESSION_INFO *pi, STACK_OF(ASN1_STRING) *as);
+const STACK_OF(ASN1_OBJECT) *PROFESSION_INFO_get0_professionOIDs(
+ const PROFESSION_INFO *pi);
+void PROFESSION_INFO_set0_professionOIDs(
+ PROFESSION_INFO *pi, STACK_OF(ASN1_OBJECT) *po);
+const ASN1_PRINTABLESTRING *PROFESSION_INFO_get0_registrationNumber(
+ const PROFESSION_INFO *pi);
+void PROFESSION_INFO_set0_registrationNumber(
+ PROFESSION_INFO *pi, ASN1_PRINTABLESTRING *rn);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/x509v3err.h b/include/openssl/x509v3err.h
index 3b9f7139d80e..1ae3a56209ae 100644
--- a/include/openssl/x509v3err.h
+++ b/include/openssl/x509v3err.h
@@ -2,95 +2,21 @@
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_X509V3ERR_H
-# define HEADER_X509V3ERR_H
+#ifndef OPENSSL_X509V3ERR_H
+# define OPENSSL_X509V3ERR_H
+# pragma once
-# ifndef HEADER_SYMHACKS_H
-# include <openssl/symhacks.h>
-# endif
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+# include <openssl/cryptoerr_legacy.h>
-# ifdef __cplusplus
-extern "C"
-# endif
-int ERR_load_X509V3_strings(void);
-/*
- * X509V3 function codes.
- */
-# define X509V3_F_A2I_GENERAL_NAME 164
-# define X509V3_F_ADDR_VALIDATE_PATH_INTERNAL 166
-# define X509V3_F_ASIDENTIFIERCHOICE_CANONIZE 161
-# define X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL 162
-# define X509V3_F_BIGNUM_TO_STRING 167
-# define X509V3_F_COPY_EMAIL 122
-# define X509V3_F_COPY_ISSUER 123
-# define X509V3_F_DO_DIRNAME 144
-# define X509V3_F_DO_EXT_I2D 135
-# define X509V3_F_DO_EXT_NCONF 151
-# define X509V3_F_GNAMES_FROM_SECTNAME 156
-# define X509V3_F_I2S_ASN1_ENUMERATED 121
-# define X509V3_F_I2S_ASN1_IA5STRING 149
-# define X509V3_F_I2S_ASN1_INTEGER 120
-# define X509V3_F_I2V_AUTHORITY_INFO_ACCESS 138
-# define X509V3_F_I2V_AUTHORITY_KEYID 173
-# define X509V3_F_LEVEL_ADD_NODE 168
-# define X509V3_F_NOTICE_SECTION 132
-# define X509V3_F_NREF_NOS 133
-# define X509V3_F_POLICY_CACHE_CREATE 169
-# define X509V3_F_POLICY_CACHE_NEW 170
-# define X509V3_F_POLICY_DATA_NEW 171
-# define X509V3_F_POLICY_SECTION 131
-# define X509V3_F_PROCESS_PCI_VALUE 150
-# define X509V3_F_R2I_CERTPOL 130
-# define X509V3_F_R2I_PCI 155
-# define X509V3_F_S2I_ASN1_IA5STRING 100
-# define X509V3_F_S2I_ASN1_INTEGER 108
-# define X509V3_F_S2I_ASN1_OCTET_STRING 112
-# define X509V3_F_S2I_SKEY_ID 115
-# define X509V3_F_SET_DIST_POINT_NAME 158
-# define X509V3_F_SXNET_ADD_ID_ASC 125
-# define X509V3_F_SXNET_ADD_ID_INTEGER 126
-# define X509V3_F_SXNET_ADD_ID_ULONG 127
-# define X509V3_F_SXNET_GET_ID_ASC 128
-# define X509V3_F_SXNET_GET_ID_ULONG 129
-# define X509V3_F_TREE_INIT 172
-# define X509V3_F_V2I_ASIDENTIFIERS 163
-# define X509V3_F_V2I_ASN1_BIT_STRING 101
-# define X509V3_F_V2I_AUTHORITY_INFO_ACCESS 139
-# define X509V3_F_V2I_AUTHORITY_KEYID 119
-# define X509V3_F_V2I_BASIC_CONSTRAINTS 102
-# define X509V3_F_V2I_CRLD 134
-# define X509V3_F_V2I_EXTENDED_KEY_USAGE 103
-# define X509V3_F_V2I_GENERAL_NAMES 118
-# define X509V3_F_V2I_GENERAL_NAME_EX 117
-# define X509V3_F_V2I_IDP 157
-# define X509V3_F_V2I_IPADDRBLOCKS 159
-# define X509V3_F_V2I_ISSUER_ALT 153
-# define X509V3_F_V2I_NAME_CONSTRAINTS 147
-# define X509V3_F_V2I_POLICY_CONSTRAINTS 146
-# define X509V3_F_V2I_POLICY_MAPPINGS 145
-# define X509V3_F_V2I_SUBJECT_ALT 154
-# define X509V3_F_V2I_TLS_FEATURE 165
-# define X509V3_F_V3_GENERIC_EXTENSION 116
-# define X509V3_F_X509V3_ADD1_I2D 140
-# define X509V3_F_X509V3_ADD_LEN_VALUE 174
-# define X509V3_F_X509V3_ADD_VALUE 105
-# define X509V3_F_X509V3_EXT_ADD 104
-# define X509V3_F_X509V3_EXT_ADD_ALIAS 106
-# define X509V3_F_X509V3_EXT_I2D 136
-# define X509V3_F_X509V3_EXT_NCONF 152
-# define X509V3_F_X509V3_GET_SECTION 142
-# define X509V3_F_X509V3_GET_STRING 143
-# define X509V3_F_X509V3_GET_VALUE_BOOL 110
-# define X509V3_F_X509V3_PARSE_LIST 109
-# define X509V3_F_X509_PURPOSE_ADD 137
-# define X509V3_F_X509_PURPOSE_SET 141
/*
* X509V3 reason codes.
@@ -102,6 +28,7 @@ int ERR_load_X509V3_strings(void);
# define X509V3_R_DIRNAME_ERROR 149
# define X509V3_R_DISTPOINT_ALREADY_SET 160
# define X509V3_R_DUPLICATE_ZONE_ID 133
+# define X509V3_R_EMPTY_KEY_USAGE 169
# define X509V3_R_ERROR_CONVERTING_ZONE 131
# define X509V3_R_ERROR_CREATING_EXTENSION 144
# define X509V3_R_ERROR_IN_EXTENSION 128
@@ -116,13 +43,14 @@ int ERR_load_X509V3_strings(void);
# define X509V3_R_INVALID_ASNUMBER 162
# define X509V3_R_INVALID_ASRANGE 163
# define X509V3_R_INVALID_BOOLEAN_STRING 104
+# define X509V3_R_INVALID_CERTIFICATE 158
+# define X509V3_R_INVALID_EMPTY_NAME 108
# define X509V3_R_INVALID_EXTENSION_STRING 105
# define X509V3_R_INVALID_INHERITANCE 165
# define X509V3_R_INVALID_IPADDRESS 166
# define X509V3_R_INVALID_MULTIPLE_RDNS 161
# define X509V3_R_INVALID_NAME 106
# define X509V3_R_INVALID_NULL_ARGUMENT 107
-# define X509V3_R_INVALID_NULL_NAME 108
# define X509V3_R_INVALID_NULL_VALUE 109
# define X509V3_R_INVALID_NUMBER 140
# define X509V3_R_INVALID_NUMBERS 141
@@ -137,6 +65,7 @@ int ERR_load_X509V3_strings(void);
# define X509V3_R_ISSUER_DECODE_ERROR 126
# define X509V3_R_MISSING_VALUE 124
# define X509V3_R_NEED_ORGANIZATION_AND_NUMBERS 142
+# define X509V3_R_NEGATIVE_PATHLEN 168
# define X509V3_R_NO_CONFIG_DATABASE 136
# define X509V3_R_NO_ISSUER_CERTIFICATE 121
# define X509V3_R_NO_ISSUER_DETAILS 127
diff --git a/providers/baseprov.c b/providers/baseprov.c
new file mode 100644
index 000000000000..44c6e8b7e726
--- /dev/null
+++ b/providers/baseprov.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <openssl/opensslconf.h>
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include "prov/bio.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_util.h"
+#include "internal/nelem.h"
+
+/*
+ * Forward declarations to ensure that interface functions are correctly
+ * defined.
+ */
+static OSSL_FUNC_provider_gettable_params_fn base_gettable_params;
+static OSSL_FUNC_provider_get_params_fn base_get_params;
+static OSSL_FUNC_provider_query_operation_fn base_query;
+
+/* Functions provided by the core */
+static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL;
+static OSSL_FUNC_core_get_params_fn *c_get_params = NULL;
+
+/* Parameters we provide to the core */
+static const OSSL_PARAM base_param_types[] = {
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_VERSION, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_BUILDINFO, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_STATUS, OSSL_PARAM_INTEGER, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *base_gettable_params(void *provctx)
+{
+ return base_param_types;
+}
+
+static int base_get_params(void *provctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME);
+ if (p != NULL
+ && !OSSL_PARAM_set_utf8_ptr(p, "OpenSSL Base Provider"))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_VERSION);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_VERSION_STR))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_BUILDINFO);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_FULL_VERSION_STR))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_STATUS);
+ if (p != NULL && !OSSL_PARAM_set_int(p, ossl_prov_is_running()))
+ return 0;
+
+ return 1;
+}
+
+static const OSSL_ALGORITHM base_encoder[] = {
+#define ENCODER_PROVIDER "base"
+#include "encoders.inc"
+ { NULL, NULL, NULL }
+#undef ENCODER_PROVIDER
+};
+
+static const OSSL_ALGORITHM base_decoder[] = {
+#define DECODER_PROVIDER "base"
+#include "decoders.inc"
+ { NULL, NULL, NULL }
+#undef DECODER_PROVIDER
+};
+
+static const OSSL_ALGORITHM base_store[] = {
+#define STORE(name, _fips, func_table) \
+ { name, "provider=base,fips=" _fips, (func_table) },
+
+#include "stores.inc"
+ { NULL, NULL, NULL }
+#undef STORE
+};
+
+static const OSSL_ALGORITHM *base_query(void *provctx, int operation_id,
+ int *no_cache)
+{
+ *no_cache = 0;
+ switch (operation_id) {
+ case OSSL_OP_ENCODER:
+ return base_encoder;
+ case OSSL_OP_DECODER:
+ return base_decoder;
+ case OSSL_OP_STORE:
+ return base_store;
+ }
+ return NULL;
+}
+
+static void base_teardown(void *provctx)
+{
+ BIO_meth_free(ossl_prov_ctx_get0_core_bio_method(provctx));
+ ossl_prov_ctx_free(provctx);
+}
+
+/* Functions we provide to the core */
+static const OSSL_DISPATCH base_dispatch_table[] = {
+ { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))base_teardown },
+ { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS,
+ (void (*)(void))base_gettable_params },
+ { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))base_get_params },
+ { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))base_query },
+ { 0, NULL }
+};
+
+OSSL_provider_init_fn ossl_base_provider_init;
+
+int ossl_base_provider_init(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in, const OSSL_DISPATCH **out,
+ void **provctx)
+{
+ OSSL_FUNC_core_get_libctx_fn *c_get_libctx = NULL;
+ BIO_METHOD *corebiometh;
+
+ if (!ossl_prov_bio_from_dispatch(in))
+ return 0;
+ for (; in->function_id != 0; in++) {
+ switch (in->function_id) {
+ case OSSL_FUNC_CORE_GETTABLE_PARAMS:
+ c_gettable_params = OSSL_FUNC_core_gettable_params(in);
+ break;
+ case OSSL_FUNC_CORE_GET_PARAMS:
+ c_get_params = OSSL_FUNC_core_get_params(in);
+ break;
+ case OSSL_FUNC_CORE_GET_LIBCTX:
+ c_get_libctx = OSSL_FUNC_core_get_libctx(in);
+ break;
+ default:
+ /* Just ignore anything we don't understand */
+ break;
+ }
+ }
+
+ if (c_get_libctx == NULL)
+ return 0;
+
+ /*
+ * We want to make sure that all calls from this provider that requires
+ * a library context use the same context as the one used to call our
+ * functions. We do that by passing it along in the provider context.
+ *
+ * This only works for built-in providers. Most providers should
+ * create their own library context.
+ */
+ if ((*provctx = ossl_prov_ctx_new()) == NULL
+ || (corebiometh = ossl_bio_prov_init_bio_method()) == NULL) {
+ ossl_prov_ctx_free(*provctx);
+ *provctx = NULL;
+ return 0;
+ }
+ ossl_prov_ctx_set0_libctx(*provctx,
+ (OSSL_LIB_CTX *)c_get_libctx(handle));
+ ossl_prov_ctx_set0_handle(*provctx, handle);
+ ossl_prov_ctx_set0_core_bio_method(*provctx, corebiometh);
+
+ *out = base_dispatch_table;
+
+ return 1;
+}
diff --git a/providers/build.info b/providers/build.info
new file mode 100644
index 000000000000..3b211bbb2fe7
--- /dev/null
+++ b/providers/build.info
@@ -0,0 +1,177 @@
+# libcommon.a Contains common building blocks and other routines,
+# potentially needed by any of our providers.
+#
+# libfips.a Contains all algorithm implementations that should
+# go in the FIPS provider. The compilations for this
+# library are all done with FIPS_MODULE defined.
+#
+# liblegacy.a Contains all algorithm implementations that should
+# go into the legacy provider. The compilations for
+# this library are all done with STATIC_LEGACY defined.
+#
+# libdefault.a Contains all algorithm implementations that should
+# into the default or base provider.
+#
+# To be noted is that the FIPS provider shares source code with libcrypto,
+# which means that select source files from crypto/ are compiled for
+# libfips.a the sources from providers/implementations.
+#
+# This is how a provider module should be linked:
+#
+# -o {modulename}.so {object files...} lib{modulename}.a libcommon.a
+#
+# It is crucial that code that checks the FIPS_MODULE macro ends up in
+# libfips.a.
+# It is crucial that code that checks the STATIC_LEGACY macro ends up in
+# liblegacy.a.
+# It is recommended that code that is written for libcommon.a doesn't end
+# up depending on libfips.a, liblegacy.a or libdefault.a
+#
+# Code in providers/implementations/ should be written in such a way that
+# the OSSL_DISPATCH arrays (and preferably the majority of the actual code)
+# end up in either libfips.a, liblegacy.a or libdefault.a.
+
+SUBDIRS=common implementations
+
+INCLUDE[../libcrypto]=common/include
+
+# Libraries we're dealing with
+$LIBCOMMON=libcommon.a
+$LIBFIPS=libfips.a
+$LIBLEGACY=liblegacy.a
+$LIBDEFAULT=libdefault.a
+LIBS{noinst}=$LIBDEFAULT $LIBCOMMON
+
+# Enough of our implementations include prov/ciphercommon.h (present in
+# providers/implementations/include), which includes crypto/*_platform.h
+# (present in include), which in turn may include very internal header
+# files in crypto/, so let's have a common include list for them all.
+$COMMON_INCLUDES=../crypto ../include implementations/include common/include
+
+INCLUDE[$LIBCOMMON]=$COMMON_INCLUDES
+INCLUDE[$LIBFIPS]=.. $COMMON_INCLUDES
+INCLUDE[$LIBLEGACY]=.. $COMMON_INCLUDES
+INCLUDE[$LIBDEFAULT]=.. $COMMON_INCLUDES
+DEFINE[$LIBFIPS]=FIPS_MODULE
+
+# Weak dependencies to provide library order information. What is actually
+# used is determined by non-weak dependencies.
+DEPEND[$LIBCOMMON]{weak}=../libcrypto
+
+# Strong dependencies. This ensures that any time an implementation library
+# is used, libcommon gets included as well.
+# The $LIBFIPS dependency on $LIBCOMMON is extra strong, to mitigate for
+# linking problems because they are interdependent
+SOURCE[$LIBFIPS]=$LIBCOMMON
+DEPEND[$LIBLEGACY]=$LIBCOMMON
+DEPEND[$LIBDEFAULT]=$LIBCOMMON
+
+#
+# Default provider stuff
+#
+# Because the default provider is built in, it means that libcrypto must
+# include all the object files that are needed (we do that indirectly,
+# by using the appropriate libraries as source). Note that for shared
+# libraries, SOURCEd libraries are considered as if they were specified
+# with DEPEND.
+$DEFAULTGOAL=../libcrypto
+SOURCE[$DEFAULTGOAL]=$LIBDEFAULT defltprov.c
+INCLUDE[$DEFAULTGOAL]=implementations/include
+
+#
+# Base provider stuff
+#
+# Because the base provider is built in, it means that libcrypto must
+# include all of the object files that are needed, just like the default
+# provider.
+$BASEGOAL=../libcrypto
+SOURCE[$BASEGOAL]=$LIBDEFAULT baseprov.c
+INCLUDE[$BASEGOAL]=implementations/include
+
+#
+# FIPS provider stuff
+#
+# We define it this way to ensure that configdata.pm will have all the
+# necessary information even if we don't build the module. This will allow
+# us to make all kinds of checks on the source, based on what we specify in
+# diverse build.info files. libfips.a, fips.so and their sources aren't
+# built unless the proper LIBS or MODULES statement has been seen, so we
+# have those and only those within a condition.
+IF[{- !$disabled{fips} -}]
+ SUBDIRS=fips
+ $FIPSGOAL=fips
+
+ # This is the trigger to actually build the FIPS module. Without these
+ # statements, the final build file will not have a trace of it.
+ MODULES{fips}=$FIPSGOAL
+ LIBS{noinst}=$LIBFIPS
+
+ DEPEND[$FIPSGOAL]=$LIBFIPS
+ INCLUDE[$FIPSGOAL]=../include
+ DEFINE[$FIPSGOAL]=FIPS_MODULE
+ IF[{- defined $target{shared_defflag} -}]
+ SOURCE[$FIPSGOAL]=fips.ld
+ GENERATE[fips.ld]=../util/providers.num
+ ENDIF
+
+ DEPEND[|build_modules_nodep|]=fipsmodule.cnf
+ GENERATE[fipsmodule.cnf]=../util/mk-fipsmodule-cnf.pl \
+ -module $(FIPSMODULE) -section_name fips_sect -key $(FIPSKEY)
+ DEPEND[fipsmodule.cnf]=$FIPSGOAL
+
+ # Add VERSIONINFO resource for windows
+ IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}]
+ GENERATE[fips.rc]=../util/mkrc.pl fips
+ SOURCE[$FIPSGOAL]=fips.rc
+ ENDIF
+ENDIF
+
+#
+# Legacy provider stuff
+#
+IF[{- !$disabled{legacy} -}]
+ LIBS{noinst}=$LIBLEGACY
+
+ IF[{- $disabled{module} -}]
+ # Become built in
+ # In this case, we need to do the same thing a for the default provider,
+ # and make the liblegacy object files end up in libcrypto. We could also
+ # just say that for the built-in legacy, we put the source directly in
+ # libcrypto instead of going via liblegacy, but that makes writing the
+ # implementation specific build.info files harder to write, so we don't.
+ $LEGACYGOAL=../libcrypto
+ SOURCE[$LEGACYGOAL]=$LIBLEGACY
+ DEFINE[$LEGACYGOAL]=STATIC_LEGACY
+ ELSE
+ # Become a module
+ # In this case, we can work with dependencies
+ $LEGACYGOAL=legacy
+ MODULES=$LEGACYGOAL
+ DEPEND[$LEGACYGOAL]=$LIBLEGACY ../libcrypto
+ IF[{- defined $target{shared_defflag} -}]
+ SOURCE[legacy]=legacy.ld
+ GENERATE[legacy.ld]=../util/providers.num
+ ENDIF
+
+ # Add VERSIONINFO resource for windows
+ IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}]
+ GENERATE[legacy.rc]=../util/mkrc.pl legacy
+ SOURCE[$LEGACYGOAL]=legacy.rc
+ ENDIF
+
+ SOURCE[$LIBLEGACY]=prov_running.c
+ ENDIF
+
+ # Common things that are valid no matter what form the Legacy provider
+ # takes.
+ SOURCE[$LEGACYGOAL]=legacyprov.c
+ INCLUDE[$LEGACYGOAL]=../include implementations/include common/include
+ENDIF
+
+#
+# Null provider stuff
+#
+# Because the null provider is built in, it means that libcrypto must
+# include all the object files that are needed.
+$NULLGOAL=../libcrypto
+SOURCE[$NULLGOAL]=nullprov.c prov_running.c
diff --git a/providers/common/bio_prov.c b/providers/common/bio_prov.c
new file mode 100644
index 000000000000..baf923c7b3c6
--- /dev/null
+++ b/providers/common/bio_prov.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <assert.h>
+#include <openssl/core_dispatch.h>
+#include "internal/cryptlib.h"
+#include "prov/bio.h"
+
+static OSSL_FUNC_BIO_new_file_fn *c_bio_new_file = NULL;
+static OSSL_FUNC_BIO_new_membuf_fn *c_bio_new_membuf = NULL;
+static OSSL_FUNC_BIO_read_ex_fn *c_bio_read_ex = NULL;
+static OSSL_FUNC_BIO_write_ex_fn *c_bio_write_ex = NULL;
+static OSSL_FUNC_BIO_gets_fn *c_bio_gets = NULL;
+static OSSL_FUNC_BIO_puts_fn *c_bio_puts = NULL;
+static OSSL_FUNC_BIO_ctrl_fn *c_bio_ctrl = NULL;
+static OSSL_FUNC_BIO_up_ref_fn *c_bio_up_ref = NULL;
+static OSSL_FUNC_BIO_free_fn *c_bio_free = NULL;
+static OSSL_FUNC_BIO_vprintf_fn *c_bio_vprintf = NULL;
+
+int ossl_prov_bio_from_dispatch(const OSSL_DISPATCH *fns)
+{
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_BIO_NEW_FILE:
+ if (c_bio_new_file == NULL)
+ c_bio_new_file = OSSL_FUNC_BIO_new_file(fns);
+ break;
+ case OSSL_FUNC_BIO_NEW_MEMBUF:
+ if (c_bio_new_membuf == NULL)
+ c_bio_new_membuf = OSSL_FUNC_BIO_new_membuf(fns);
+ break;
+ case OSSL_FUNC_BIO_READ_EX:
+ if (c_bio_read_ex == NULL)
+ c_bio_read_ex = OSSL_FUNC_BIO_read_ex(fns);
+ break;
+ case OSSL_FUNC_BIO_WRITE_EX:
+ if (c_bio_write_ex == NULL)
+ c_bio_write_ex = OSSL_FUNC_BIO_write_ex(fns);
+ break;
+ case OSSL_FUNC_BIO_GETS:
+ if (c_bio_gets == NULL)
+ c_bio_gets = OSSL_FUNC_BIO_gets(fns);
+ break;
+ case OSSL_FUNC_BIO_PUTS:
+ if (c_bio_puts == NULL)
+ c_bio_puts = OSSL_FUNC_BIO_puts(fns);
+ break;
+ case OSSL_FUNC_BIO_CTRL:
+ if (c_bio_ctrl == NULL)
+ c_bio_ctrl = OSSL_FUNC_BIO_ctrl(fns);
+ break;
+ case OSSL_FUNC_BIO_UP_REF:
+ if (c_bio_up_ref == NULL)
+ c_bio_up_ref = OSSL_FUNC_BIO_up_ref(fns);
+ break;
+ case OSSL_FUNC_BIO_FREE:
+ if (c_bio_free == NULL)
+ c_bio_free = OSSL_FUNC_BIO_free(fns);
+ break;
+ case OSSL_FUNC_BIO_VPRINTF:
+ if (c_bio_vprintf == NULL)
+ c_bio_vprintf = OSSL_FUNC_BIO_vprintf(fns);
+ break;
+ }
+ }
+
+ return 1;
+}
+
+OSSL_CORE_BIO *ossl_prov_bio_new_file(const char *filename, const char *mode)
+{
+ if (c_bio_new_file == NULL)
+ return NULL;
+ return c_bio_new_file(filename, mode);
+}
+
+OSSL_CORE_BIO *ossl_prov_bio_new_membuf(const char *filename, int len)
+{
+ if (c_bio_new_membuf == NULL)
+ return NULL;
+ return c_bio_new_membuf(filename, len);
+}
+
+int ossl_prov_bio_read_ex(OSSL_CORE_BIO *bio, void *data, size_t data_len,
+ size_t *bytes_read)
+{
+ if (c_bio_read_ex == NULL)
+ return 0;
+ return c_bio_read_ex(bio, data, data_len, bytes_read);
+}
+
+int ossl_prov_bio_write_ex(OSSL_CORE_BIO *bio, const void *data, size_t data_len,
+ size_t *written)
+{
+ if (c_bio_write_ex == NULL)
+ return 0;
+ return c_bio_write_ex(bio, data, data_len, written);
+}
+
+int ossl_prov_bio_gets(OSSL_CORE_BIO *bio, char *buf, int size)
+{
+ if (c_bio_gets == NULL)
+ return -1;
+ return c_bio_gets(bio, buf, size);
+}
+
+int ossl_prov_bio_puts(OSSL_CORE_BIO *bio, const char *str)
+{
+ if (c_bio_puts == NULL)
+ return -1;
+ return c_bio_puts(bio, str);
+}
+
+int ossl_prov_bio_ctrl(OSSL_CORE_BIO *bio, int cmd, long num, void *ptr)
+{
+ if (c_bio_ctrl == NULL)
+ return -1;
+ return c_bio_ctrl(bio, cmd, num, ptr);
+}
+
+int ossl_prov_bio_up_ref(OSSL_CORE_BIO *bio)
+{
+ if (c_bio_up_ref == NULL)
+ return 0;
+ return c_bio_up_ref(bio);
+}
+
+int ossl_prov_bio_free(OSSL_CORE_BIO *bio)
+{
+ if (c_bio_free == NULL)
+ return 0;
+ return c_bio_free(bio);
+}
+
+int ossl_prov_bio_vprintf(OSSL_CORE_BIO *bio, const char *format, va_list ap)
+{
+ if (c_bio_vprintf == NULL)
+ return -1;
+ return c_bio_vprintf(bio, format, ap);
+}
+
+int ossl_prov_bio_printf(OSSL_CORE_BIO *bio, const char *format, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, format);
+ ret = ossl_prov_bio_vprintf(bio, format, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+#ifndef FIPS_MODULE
+
+/* No direct BIO support in the FIPS module */
+
+static int bio_core_read_ex(BIO *bio, char *data, size_t data_len,
+ size_t *bytes_read)
+{
+ return ossl_prov_bio_read_ex(BIO_get_data(bio), data, data_len, bytes_read);
+}
+
+static int bio_core_write_ex(BIO *bio, const char *data, size_t data_len,
+ size_t *written)
+{
+ return ossl_prov_bio_write_ex(BIO_get_data(bio), data, data_len, written);
+}
+
+static long bio_core_ctrl(BIO *bio, int cmd, long num, void *ptr)
+{
+ return ossl_prov_bio_ctrl(BIO_get_data(bio), cmd, num, ptr);
+}
+
+static int bio_core_gets(BIO *bio, char *buf, int size)
+{
+ return ossl_prov_bio_gets(BIO_get_data(bio), buf, size);
+}
+
+static int bio_core_puts(BIO *bio, const char *str)
+{
+ return ossl_prov_bio_puts(BIO_get_data(bio), str);
+}
+
+static int bio_core_new(BIO *bio)
+{
+ BIO_set_init(bio, 1);
+
+ return 1;
+}
+
+static int bio_core_free(BIO *bio)
+{
+ BIO_set_init(bio, 0);
+ ossl_prov_bio_free(BIO_get_data(bio));
+
+ return 1;
+}
+
+BIO_METHOD *ossl_bio_prov_init_bio_method(void)
+{
+ BIO_METHOD *corebiometh = NULL;
+
+ corebiometh = BIO_meth_new(BIO_TYPE_CORE_TO_PROV, "BIO to Core filter");
+ if (corebiometh == NULL
+ || !BIO_meth_set_write_ex(corebiometh, bio_core_write_ex)
+ || !BIO_meth_set_read_ex(corebiometh, bio_core_read_ex)
+ || !BIO_meth_set_puts(corebiometh, bio_core_puts)
+ || !BIO_meth_set_gets(corebiometh, bio_core_gets)
+ || !BIO_meth_set_ctrl(corebiometh, bio_core_ctrl)
+ || !BIO_meth_set_create(corebiometh, bio_core_new)
+ || !BIO_meth_set_destroy(corebiometh, bio_core_free)) {
+ BIO_meth_free(corebiometh);
+ return NULL;
+ }
+
+ return corebiometh;
+}
+
+BIO *ossl_bio_new_from_core_bio(PROV_CTX *provctx, OSSL_CORE_BIO *corebio)
+{
+ BIO *outbio;
+ BIO_METHOD *corebiometh = ossl_prov_ctx_get0_core_bio_method(provctx);
+
+ if (corebiometh == NULL)
+ return NULL;
+
+ if ((outbio = BIO_new(corebiometh)) == NULL)
+ return NULL;
+ if (!ossl_prov_bio_up_ref(corebio)) {
+ BIO_free(outbio);
+ return NULL;
+ }
+ BIO_set_data(outbio, corebio);
+ return outbio;
+}
+
+#endif
diff --git a/providers/common/build.info b/providers/common/build.info
new file mode 100644
index 000000000000..a14bf0903771
--- /dev/null
+++ b/providers/common/build.info
@@ -0,0 +1,10 @@
+SUBDIRS=der
+
+SOURCE[../libcommon.a]=provider_err.c provider_ctx.c
+$FIPSCOMMON=provider_util.c capabilities.c bio_prov.c digest_to_nid.c\
+ securitycheck.c provider_seeding.c
+SOURCE[../libdefault.a]=$FIPSCOMMON securitycheck_default.c
+IF[{- !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../liblegacy.a]=provider_util.c
+ENDIF
+SOURCE[../libfips.a]=$FIPSCOMMON securitycheck_fips.c
diff --git a/providers/common/capabilities.c b/providers/common/capabilities.c
new file mode 100644
index 000000000000..7223d55164cd
--- /dev/null
+++ b/providers/common/capabilities.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+/* For TLS1_VERSION etc */
+#include <openssl/prov_ssl.h>
+#include <openssl/params.h>
+#include "internal/nelem.h"
+#include "internal/tlsgroups.h"
+#include "prov/providercommon.h"
+#include "e_os.h"
+
+/* If neither ec or dh is available then we have no TLS-GROUP capabilities */
+#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
+typedef struct tls_group_constants_st {
+ unsigned int group_id; /* Group ID */
+ unsigned int secbits; /* Bits of security */
+ int mintls; /* Minimum TLS version, -1 unsupported */
+ int maxtls; /* Maximum TLS version (or 0 for undefined) */
+ int mindtls; /* Minimum DTLS version, -1 unsupported */
+ int maxdtls; /* Maximum DTLS version (or 0 for undefined) */
+} TLS_GROUP_CONSTANTS;
+
+static const TLS_GROUP_CONSTANTS group_list[35] = {
+ { OSSL_TLS_GROUP_ID_sect163k1, 80, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_sect163r1, 80, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_sect163r2, 80, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_sect193r1, 80, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_sect193r2, 80, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_sect233k1, 112, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_sect233r1, 112, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_sect239k1, 112, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_sect283k1, 128, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_sect283r1, 128, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_sect409k1, 192, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_sect409r1, 192, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_sect571k1, 256, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_sect571r1, 256, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_secp160k1, 80, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_secp160r1, 80, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_secp160r2, 80, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_secp192k1, 80, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_secp192r1, 80, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_secp224k1, 112, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_secp224r1, 112, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_secp256k1, 128, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_secp256r1, 128, TLS1_VERSION, 0, DTLS1_VERSION, 0 },
+ { OSSL_TLS_GROUP_ID_secp384r1, 192, TLS1_VERSION, 0, DTLS1_VERSION, 0 },
+ { OSSL_TLS_GROUP_ID_secp521r1, 256, TLS1_VERSION, 0, DTLS1_VERSION, 0 },
+ { OSSL_TLS_GROUP_ID_brainpoolP256r1, 128, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_brainpoolP384r1, 192, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_brainpoolP512r1, 256, TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_VERSION, DTLS1_2_VERSION },
+ { OSSL_TLS_GROUP_ID_x25519, 128, TLS1_VERSION, 0, DTLS1_VERSION, 0 },
+ { OSSL_TLS_GROUP_ID_x448, 224, TLS1_VERSION, 0, DTLS1_VERSION, 0 },
+ /* Security bit values as given by BN_security_bits() */
+ { OSSL_TLS_GROUP_ID_ffdhe2048, 112, TLS1_3_VERSION, 0, -1, -1 },
+ { OSSL_TLS_GROUP_ID_ffdhe3072, 128, TLS1_3_VERSION, 0, -1, -1 },
+ { OSSL_TLS_GROUP_ID_ffdhe4096, 128, TLS1_3_VERSION, 0, -1, -1 },
+ { OSSL_TLS_GROUP_ID_ffdhe6144, 128, TLS1_3_VERSION, 0, -1, -1 },
+ { OSSL_TLS_GROUP_ID_ffdhe8192, 192, TLS1_3_VERSION, 0, -1, -1 },
+};
+
+#define TLS_GROUP_ENTRY(tlsname, realname, algorithm, idx) \
+ { \
+ OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME, \
+ tlsname, \
+ sizeof(tlsname)), \
+ OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL, \
+ realname, \
+ sizeof(realname)), \
+ OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_ALG, \
+ algorithm, \
+ sizeof(algorithm)), \
+ OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_ID, \
+ (unsigned int *)&group_list[idx].group_id), \
+ OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS, \
+ (unsigned int *)&group_list[idx].secbits), \
+ OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_TLS, \
+ (unsigned int *)&group_list[idx].mintls), \
+ OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_TLS, \
+ (unsigned int *)&group_list[idx].maxtls), \
+ OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS, \
+ (unsigned int *)&group_list[idx].mindtls), \
+ OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS, \
+ (unsigned int *)&group_list[idx].maxdtls), \
+ OSSL_PARAM_END \
+ }
+
+static const OSSL_PARAM param_group_list[][10] = {
+# ifndef OPENSSL_NO_EC
+# ifndef OPENSSL_NO_EC2M
+ TLS_GROUP_ENTRY("sect163k1", "sect163k1", "EC", 0),
+ TLS_GROUP_ENTRY("K-163", "sect163k1", "EC", 0), /* Alias of above */
+# endif
+# ifndef FIPS_MODULE
+ TLS_GROUP_ENTRY("sect163r1", "sect163r1", "EC", 1),
+# endif
+# ifndef OPENSSL_NO_EC2M
+ TLS_GROUP_ENTRY("sect163r2", "sect163r2", "EC", 2),
+ TLS_GROUP_ENTRY("B-163", "sect163r2", "EC", 2), /* Alias of above */
+# endif
+# ifndef FIPS_MODULE
+ TLS_GROUP_ENTRY("sect193r1", "sect193r1", "EC", 3),
+ TLS_GROUP_ENTRY("sect193r2", "sect193r2", "EC", 4),
+# endif
+# ifndef OPENSSL_NO_EC2M
+ TLS_GROUP_ENTRY("sect233k1", "sect233k1", "EC", 5),
+ TLS_GROUP_ENTRY("K-233", "sect233k1", "EC", 5), /* Alias of above */
+ TLS_GROUP_ENTRY("sect233r1", "sect233r1", "EC", 6),
+ TLS_GROUP_ENTRY("B-233", "sect233r1", "EC", 6), /* Alias of above */
+# endif
+# ifndef FIPS_MODULE
+ TLS_GROUP_ENTRY("sect239k1", "sect239k1", "EC", 7),
+# endif
+# ifndef OPENSSL_NO_EC2M
+ TLS_GROUP_ENTRY("sect283k1", "sect283k1", "EC", 8),
+ TLS_GROUP_ENTRY("K-283", "sect283k1", "EC", 8), /* Alias of above */
+ TLS_GROUP_ENTRY("sect283r1", "sect283r1", "EC", 9),
+ TLS_GROUP_ENTRY("B-283", "sect283r1", "EC", 9), /* Alias of above */
+ TLS_GROUP_ENTRY("sect409k1", "sect409k1", "EC", 10),
+ TLS_GROUP_ENTRY("K-409", "sect409k1", "EC", 10), /* Alias of above */
+ TLS_GROUP_ENTRY("sect409r1", "sect409r1", "EC", 11),
+ TLS_GROUP_ENTRY("B-409", "sect409r1", "EC", 11), /* Alias of above */
+ TLS_GROUP_ENTRY("sect571k1", "sect571k1", "EC", 12),
+ TLS_GROUP_ENTRY("K-571", "sect571k1", "EC", 12), /* Alias of above */
+ TLS_GROUP_ENTRY("sect571r1", "sect571r1", "EC", 13),
+ TLS_GROUP_ENTRY("B-571", "sect571r1", "EC", 13), /* Alias of above */
+# endif
+# ifndef FIPS_MODULE
+ TLS_GROUP_ENTRY("secp160k1", "secp160k1", "EC", 14),
+ TLS_GROUP_ENTRY("secp160r1", "secp160r1", "EC", 15),
+ TLS_GROUP_ENTRY("secp160r2", "secp160r2", "EC", 16),
+ TLS_GROUP_ENTRY("secp192k1", "secp192k1", "EC", 17),
+# endif
+ TLS_GROUP_ENTRY("secp192r1", "prime192v1", "EC", 18),
+ TLS_GROUP_ENTRY("P-192", "prime192v1", "EC", 18), /* Alias of above */
+# ifndef FIPS_MODULE
+ TLS_GROUP_ENTRY("secp224k1", "secp224k1", "EC", 19),
+# endif
+ TLS_GROUP_ENTRY("secp224r1", "secp224r1", "EC", 20),
+ TLS_GROUP_ENTRY("P-224", "secp224r1", "EC", 20), /* Alias of above */
+# ifndef FIPS_MODULE
+ TLS_GROUP_ENTRY("secp256k1", "secp256k1", "EC", 21),
+# endif
+ TLS_GROUP_ENTRY("secp256r1", "prime256v1", "EC", 22),
+ TLS_GROUP_ENTRY("P-256", "prime256v1", "EC", 22), /* Alias of above */
+ TLS_GROUP_ENTRY("secp384r1", "secp384r1", "EC", 23),
+ TLS_GROUP_ENTRY("P-384", "secp384r1", "EC", 23), /* Alias of above */
+ TLS_GROUP_ENTRY("secp521r1", "secp521r1", "EC", 24),
+ TLS_GROUP_ENTRY("P-521", "secp521r1", "EC", 24), /* Alias of above */
+# ifndef FIPS_MODULE
+ TLS_GROUP_ENTRY("brainpoolP256r1", "brainpoolP256r1", "EC", 25),
+ TLS_GROUP_ENTRY("brainpoolP384r1", "brainpoolP384r1", "EC", 26),
+ TLS_GROUP_ENTRY("brainpoolP512r1", "brainpoolP512r1", "EC", 27),
+# endif
+ TLS_GROUP_ENTRY("x25519", "X25519", "X25519", 28),
+ TLS_GROUP_ENTRY("x448", "X448", "X448", 29),
+# endif /* OPENSSL_NO_EC */
+# ifndef OPENSSL_NO_DH
+ /* Security bit values for FFDHE groups are as per RFC 7919 */
+ TLS_GROUP_ENTRY("ffdhe2048", "ffdhe2048", "DH", 30),
+ TLS_GROUP_ENTRY("ffdhe3072", "ffdhe3072", "DH", 31),
+ TLS_GROUP_ENTRY("ffdhe4096", "ffdhe4096", "DH", 32),
+ TLS_GROUP_ENTRY("ffdhe6144", "ffdhe6144", "DH", 33),
+ TLS_GROUP_ENTRY("ffdhe8192", "ffdhe8192", "DH", 34),
+# endif
+};
+#endif /* !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH) */
+
+static int tls_group_capability(OSSL_CALLBACK *cb, void *arg)
+{
+#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(param_group_list); i++)
+ if (!cb(param_group_list[i], arg))
+ return 0;
+#endif
+
+ return 1;
+}
+
+int ossl_prov_get_capabilities(void *provctx, const char *capability,
+ OSSL_CALLBACK *cb, void *arg)
+{
+ if (OPENSSL_strcasecmp(capability, "TLS-GROUP") == 0)
+ return tls_group_capability(cb, arg);
+
+ /* We don't support this capability */
+ return 0;
+}
diff --git a/providers/common/der/DIGESTS.asn1 b/providers/common/der/DIGESTS.asn1
new file mode 100644
index 000000000000..7251a9e1367e
--- /dev/null
+++ b/providers/common/der/DIGESTS.asn1
@@ -0,0 +1,43 @@
+-- Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+--
+-- Licensed under the Apache License 2.0 (the "License"). You may not use
+-- this file except in compliance with the License. You can obtain a copy
+-- in the file LICENSE in the source distribution or at
+-- https://www.openssl.org/source/license.html
+
+-- -------------------------------------------------------------------
+-- From https://tools.ietf.org/html/rfc4055#section-2.1
+
+id-sha1 OBJECT IDENTIFIER ::= { iso(1)
+ identified-organization(3) oiw(14)
+ secsig(3) algorithms(2) 26 }
+
+-- -------------------------------------------------------------------
+-- From https://tools.ietf.org/html/rfc5480#appendix-A
+-- (OIDs for MD2 and MD5 are allowed only in EMSA-PKCS1-v1_5)
+
+id-md2 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 }
+
+id-md5 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 }
+
+-- -------------------------------------------------------------------
+-- From https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration
+
+id-sha256 OBJECT IDENTIFIER ::= { hashAlgs 1 }
+id-sha384 OBJECT IDENTIFIER ::= { hashAlgs 2 }
+id-sha512 OBJECT IDENTIFIER ::= { hashAlgs 3 }
+id-sha224 OBJECT IDENTIFIER ::= { hashAlgs 4 }
+id-sha512-224 OBJECT IDENTIFIER ::= { hashAlgs 5 }
+id-sha512-256 OBJECT IDENTIFIER ::= { hashAlgs 6 }
+id-sha3-224 OBJECT IDENTIFIER ::= { hashAlgs 7 }
+id-sha3-256 OBJECT IDENTIFIER ::= { hashAlgs 8 }
+id-sha3-384 OBJECT IDENTIFIER ::= { hashAlgs 9 }
+id-sha3-512 OBJECT IDENTIFIER ::= { hashAlgs 10 }
+id-shake128 OBJECT IDENTIFIER ::= { hashAlgs 11 }
+id-shake256 OBJECT IDENTIFIER ::= { hashAlgs 12 }
+id-shake128-len OBJECT IDENTIFIER ::= { hashAlgs 17 }
+id-shake256-len OBJECT IDENTIFIER ::= { hashAlgs 18 }
+id-KMACWithSHAKE128 OBJECT IDENTIFIER ::={hashAlgs 19}
+id-KMACWithSHAKE256 OBJECT IDENTIFIER ::={ hashAlgs 20}
diff --git a/providers/common/der/DSA.asn1 b/providers/common/der/DSA.asn1
new file mode 100644
index 000000000000..2c90294aefad
--- /dev/null
+++ b/providers/common/der/DSA.asn1
@@ -0,0 +1,36 @@
+-- Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+--
+-- Licensed under the Apache License 2.0 (the "License"). You may not use
+-- this file except in compliance with the License. You can obtain a copy
+-- in the file LICENSE in the source distribution or at
+-- https://www.openssl.org/source/license.html
+
+-- -------------------------------------------------------------------
+-- Taken from RFC 3279, 3 ASN.1 Module
+-- (https://www.rfc-editor.org/rfc/rfc3279.html#section-3)
+
+-- OID for DSA public key
+
+id-dsa OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) x9-57(10040) x9algorithm(4) 1 }
+
+-- OID for DSA signature generated with SHA-1 hash
+
+id-dsa-with-sha1 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) x9-57 (10040) x9algorithm(4) 3 }
+
+
+-- -------------------------------------------------------------------
+-- Taken from https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration
+
+sigAlgs OBJECT IDENTIFIER ::= { 2 16 840 1 101 3 4 3 }
+
+id-dsa-with-sha224 OBJECT IDENTIFIER ::= { sigAlgs 1 }
+id-dsa-with-sha256 OBJECT IDENTIFIER ::= { sigAlgs 2 }
+id-dsa-with-sha384 OBJECT IDENTIFIER ::= { sigAlgs 3 }
+id-dsa-with-sha512 OBJECT IDENTIFIER ::= { sigAlgs 4 }
+
+id-dsa-with-sha3-224 OBJECT IDENTIFIER ::= { sigAlgs 5 }
+id-dsa-with-sha3-256 OBJECT IDENTIFIER ::= { sigAlgs 6 }
+id-dsa-with-sha3-384 OBJECT IDENTIFIER ::= { sigAlgs 7 }
+id-dsa-with-sha3-512 OBJECT IDENTIFIER ::= { sigAlgs 8 }
diff --git a/providers/common/der/EC.asn1 b/providers/common/der/EC.asn1
new file mode 100644
index 000000000000..417103b81b83
--- /dev/null
+++ b/providers/common/der/EC.asn1
@@ -0,0 +1,90 @@
+-- Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+--
+-- Licensed under the Apache License 2.0 (the "License"). You may not use
+-- this file except in compliance with the License. You can obtain a copy
+-- in the file LICENSE in the source distribution or at
+-- https://www.openssl.org/source/license.html
+
+-- -------------------------------------------------------------------
+-- Taken from RFC 3279, 3 ASN.1 Module
+-- (https://www.rfc-editor.org/rfc/rfc3279.html#section-3)
+
+ansi-X9-62 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) 10045 }
+
+-- Arc for ECDSA signature OIDS
+
+id-ecSigType OBJECT IDENTIFIER ::= { ansi-X9-62 signatures(4) }
+
+-- OID for ECDSA signatures with SHA-1
+
+ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { id-ecSigType 1 }
+
+id-publicKeyType OBJECT IDENTIFIER ::= { ansi-X9-62 keyType(2) }
+
+id-ecPublicKey OBJECT IDENTIFIER ::= { id-publicKeyType 1 }
+
+-- Named Elliptic Curves in ANSI X9.62.
+
+ellipticCurve OBJECT IDENTIFIER ::= { ansi-X9-62 curves(3) }
+
+c-TwoCurve OBJECT IDENTIFIER ::= {
+ ellipticCurve characteristicTwo(0) }
+
+c2pnb163v1 OBJECT IDENTIFIER ::= { c-TwoCurve 1 }
+c2pnb163v2 OBJECT IDENTIFIER ::= { c-TwoCurve 2 }
+c2pnb163v3 OBJECT IDENTIFIER ::= { c-TwoCurve 3 }
+c2pnb176w1 OBJECT IDENTIFIER ::= { c-TwoCurve 4 }
+c2tnb191v1 OBJECT IDENTIFIER ::= { c-TwoCurve 5 }
+c2tnb191v2 OBJECT IDENTIFIER ::= { c-TwoCurve 6 }
+c2tnb191v3 OBJECT IDENTIFIER ::= { c-TwoCurve 7 }
+c2onb191v4 OBJECT IDENTIFIER ::= { c-TwoCurve 8 }
+c2onb191v5 OBJECT IDENTIFIER ::= { c-TwoCurve 9 }
+c2pnb208w1 OBJECT IDENTIFIER ::= { c-TwoCurve 10 }
+c2tnb239v1 OBJECT IDENTIFIER ::= { c-TwoCurve 11 }
+c2tnb239v2 OBJECT IDENTIFIER ::= { c-TwoCurve 12 }
+c2tnb239v3 OBJECT IDENTIFIER ::= { c-TwoCurve 13 }
+c2onb239v4 OBJECT IDENTIFIER ::= { c-TwoCurve 14 }
+c2onb239v5 OBJECT IDENTIFIER ::= { c-TwoCurve 15 }
+c2pnb272w1 OBJECT IDENTIFIER ::= { c-TwoCurve 16 }
+c2pnb304w1 OBJECT IDENTIFIER ::= { c-TwoCurve 17 }
+c2tnb359v1 OBJECT IDENTIFIER ::= { c-TwoCurve 18 }
+c2pnb368w1 OBJECT IDENTIFIER ::= { c-TwoCurve 19 }
+c2tnb431r1 OBJECT IDENTIFIER ::= { c-TwoCurve 20 }
+
+primeCurve OBJECT IDENTIFIER ::= { ellipticCurve prime(1) }
+
+prime192v1 OBJECT IDENTIFIER ::= { primeCurve 1 }
+prime192v2 OBJECT IDENTIFIER ::= { primeCurve 2 }
+prime192v3 OBJECT IDENTIFIER ::= { primeCurve 3 }
+prime239v1 OBJECT IDENTIFIER ::= { primeCurve 4 }
+prime239v2 OBJECT IDENTIFIER ::= { primeCurve 5 }
+prime239v3 OBJECT IDENTIFIER ::= { primeCurve 6 }
+prime256v1 OBJECT IDENTIFIER ::= { primeCurve 7 }
+
+-- -------------------------------------------------------------------
+-- Taken from RFC 5758, 3.2. ECDSA Signature Algorithm
+-- (https://www.rfc-editor.org/rfc/rfc5758.html#section-3.2)
+
+ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 1 }
+
+ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 }
+
+ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 }
+
+ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 }
+
+-- -------------------------------------------------------------------
+-- Taken from https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration
+
+sigAlgs OBJECT IDENTIFIER ::= { 2 16 840 1 101 3 4 3 }
+
+id-ecdsa-with-sha3-224 OBJECT IDENTIFIER ::= { sigAlgs 9 }
+id-ecdsa-with-sha3-256 OBJECT IDENTIFIER ::= { sigAlgs 10 }
+id-ecdsa-with-sha3-384 OBJECT IDENTIFIER ::= { sigAlgs 11 }
+id-ecdsa-with-sha3-512 OBJECT IDENTIFIER ::= { sigAlgs 12 }
+
diff --git a/providers/common/der/ECX.asn1 b/providers/common/der/ECX.asn1
new file mode 100644
index 000000000000..be258044be97
--- /dev/null
+++ b/providers/common/der/ECX.asn1
@@ -0,0 +1,17 @@
+-- Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+--
+-- Licensed under the Apache License 2.0 (the "License"). You may not use
+-- this file except in compliance with the License. You can obtain a copy
+-- in the file LICENSE in the source distribution or at
+-- https://www.openssl.org/source/license.html
+
+-- -------------------------------------------------------------------
+-- Taken from RFC 8410, 9 ASN.1 Module
+-- (https://tools.ietf.org/html/rfc8410#section-9)
+
+id-edwards-curve-algs OBJECT IDENTIFIER ::= { 1 3 101 }
+
+id-X25519 OBJECT IDENTIFIER ::= { id-edwards-curve-algs 110 }
+id-X448 OBJECT IDENTIFIER ::= { id-edwards-curve-algs 111 }
+id-Ed25519 OBJECT IDENTIFIER ::= { id-edwards-curve-algs 112 }
+id-Ed448 OBJECT IDENTIFIER ::= { id-edwards-curve-algs 113 }
diff --git a/providers/common/der/NIST.asn1 b/providers/common/der/NIST.asn1
new file mode 100644
index 000000000000..eafac3879347
--- /dev/null
+++ b/providers/common/der/NIST.asn1
@@ -0,0 +1,15 @@
+-- Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+--
+-- Licensed under the Apache License 2.0 (the "License"). You may not use
+-- this file except in compliance with the License. You can obtain a copy
+-- in the file LICENSE in the source distribution or at
+-- https://www.openssl.org/source/license.html
+
+-- -------------------------------------------------------------------
+-- Taken from https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration
+
+-- Copies of common OIDs used by other ASN.1 files.
+csor OBJECT IDENTIFIER ::= { 2 16 840 1 101 3 }
+nistAlgorithms OBJECT IDENTIFIER ::= { csor nistAlgorithm(4) }
+hashAlgs OBJECT IDENTIFIER ::= { nistAlgorithms 2 }
+sigAlgs OBJECT IDENTIFIER ::= { nistAlgorithms 3 }
diff --git a/providers/common/der/RSA.asn1 b/providers/common/der/RSA.asn1
new file mode 100644
index 000000000000..3695ee7ad14a
--- /dev/null
+++ b/providers/common/der/RSA.asn1
@@ -0,0 +1,89 @@
+-- Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+--
+-- Licensed under the Apache License 2.0 (the "License"). You may not use
+-- this file except in compliance with the License. You can obtain a copy
+-- in the file LICENSE in the source distribution or at
+-- https://www.openssl.org/source/license.html
+
+-- -------------------------------------------------------------------
+-- Taken from RFC 8017, Appendix C
+-- (https://www.rfc-editor.org/rfc/rfc8017.html#appendix-C)
+
+-- ============================
+-- Basic object identifiers
+-- ============================
+
+-- The DER encoding of this in hexadecimal is:
+-- (0x)06 08
+-- 2A 86 48 86 F7 0D 01 01
+--
+pkcs-1 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1
+}
+
+--
+-- When rsaEncryption is used in an AlgorithmIdentifier,
+-- the parameters MUST be present and MUST be NULL.
+--
+rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 }
+
+--
+-- When id-RSAES-OAEP is used in an AlgorithmIdentifier, the
+-- parameters MUST be present and MUST be RSAES-OAEP-params.
+--
+id-RSAES-OAEP OBJECT IDENTIFIER ::= { pkcs-1 7 }
+
+--
+-- When id-pSpecified is used in an AlgorithmIdentifier, the
+-- parameters MUST be an OCTET STRING.
+--
+id-pSpecified OBJECT IDENTIFIER ::= { pkcs-1 9 }
+
+--
+-- When id-RSASSA-PSS is used in an AlgorithmIdentifier, the
+-- parameters MUST be present and MUST be RSASSA-PSS-params.
+--
+id-RSASSA-PSS OBJECT IDENTIFIER ::= { pkcs-1 10 }
+
+--
+-- When the following OIDs are used in an AlgorithmIdentifier,
+-- the parameters MUST be present and MUST be NULL.
+--
+md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 }
+md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 }
+sha1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 }
+sha224WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 14 }
+sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 }
+sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 }
+sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 }
+sha512-224WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 15 }
+sha512-256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 16 }
+
+--
+-- When id-mgf1 is used in an AlgorithmIdentifier, the parameters
+-- MUST be present and MUST be a HashAlgorithm, for example, sha1.
+--
+id-mgf1 OBJECT IDENTIFIER ::= { pkcs-1 8 }
+
+-- -------------------------------------------------------------------
+-- Taken from https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration
+
+id-rsassa-pkcs1-v1_5-with-sha3-224 OBJECT IDENTIFIER ::= { sigAlgs 13 }
+id-rsassa-pkcs1-v1_5-with-sha3-256 OBJECT IDENTIFIER ::= { sigAlgs 14 }
+id-rsassa-pkcs1-v1_5-with-sha3-384 OBJECT IDENTIFIER ::= { sigAlgs 15 }
+id-rsassa-pkcs1-v1_5-with-sha3-512 OBJECT IDENTIFIER ::= { sigAlgs 16 }
+
+
+-- -------------------------------------------------------------------
+-- These OID's exist in the codebase but may need to be deprecated at some point.
+-- md5_sha1 has been omitted as it does not look like valid entry.
+
+md4WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 3 }
+
+ripemd160WithRSAEncryption OBJECT IDENTIFIER ::= {
+ iso(1) identified-organization(3) teletrust(36) algorithm(3) signatureAlgorithm(3) rsaSignature(1) 2
+}
+
+mdc2WithRSASignature OBJECT IDENTIFIER ::= {
+ iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) mdc2WithRSASignature(14)
+}
diff --git a/providers/common/der/SM2.asn1 b/providers/common/der/SM2.asn1
new file mode 100644
index 000000000000..f3f173c42c94
--- /dev/null
+++ b/providers/common/der/SM2.asn1
@@ -0,0 +1,18 @@
+-- Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+--
+-- Licensed under the Apache License 2.0 (the "License"). You may not use
+-- this file except in compliance with the License. You can obtain a copy
+-- in the file LICENSE in the source distribution or at
+-- https://www.openssl.org/source/license.html
+
+oscca OBJECT IDENTIFIER ::= { iso(1) member-body(2) cn(156) 10197 }
+
+sm-scheme OBJECT IDENTIFIER ::= { oscca 1 }
+
+-- OID for SM2 signatures with SM3
+
+sm2-with-SM3 OBJECT IDENTIFIER ::= { sm-scheme 501 }
+
+-- Named Elliptic Curves of SM2
+
+curveSM2 OBJECT IDENTIFIER ::= { sm-scheme 301 }
diff --git a/providers/common/der/build.info b/providers/common/der/build.info
new file mode 100644
index 000000000000..b81413e11beb
--- /dev/null
+++ b/providers/common/der/build.info
@@ -0,0 +1,119 @@
+$INCDIR=../include/prov
+
+#----- Digests
+$DER_DIGESTS_H=$INCDIR/der_digests.h
+$DER_DIGESTS_GEN=der_digests_gen.c
+
+GENERATE[$DER_DIGESTS_GEN]=der_digests_gen.c.in
+DEPEND[$DER_DIGESTS_GEN]=oids_to_c.pm NIST.asn1 DIGESTS.asn1
+
+DEPEND[${DER_DIGESTS_GEN/.c/.o}]=$DER_DIGESTS_H
+GENERATE[$DER_DIGESTS_H]=$INCDIR/der_digests.h.in
+DEPEND[$DER_DIGESTS_H]=oids_to_c.pm NIST.asn1 DIGESTS.asn1
+
+#----- RSA
+$DER_RSA_H=$INCDIR/der_rsa.h
+$DER_RSA_GEN=der_rsa_gen.c
+$DER_RSA_AUX=der_rsa_key.c der_rsa_sig.c
+$DER_RSA_COMMON=$DER_RSA_GEN der_rsa_key.c
+$DER_RSA_FIPSABLE=der_rsa_sig.c
+
+GENERATE[$DER_RSA_GEN]=der_rsa_gen.c.in
+DEPEND[$DER_RSA_GEN]=oids_to_c.pm NIST.asn1 RSA.asn1
+
+DEPEND[${DER_RSA_AUX/.c/.o}]=$DER_RSA_H $DER_DIGESTS_H
+DEPEND[${DER_RSA_GEN/.c/.o}]=$DER_RSA_H
+GENERATE[$DER_RSA_H]=$INCDIR/der_rsa.h.in
+DEPEND[$DER_RSA_H]=oids_to_c.pm NIST.asn1 RSA.asn1
+
+#----- DSA
+IF[{- !$disabled{dsa} -}]
+ $DER_DSA_H=$INCDIR/der_dsa.h
+ $DER_DSA_GEN=der_dsa_gen.c
+ $DER_DSA_AUX=der_dsa_key.c der_dsa_sig.c
+
+ GENERATE[$DER_DSA_GEN]=der_dsa_gen.c.in
+ DEPEND[$DER_DSA_GEN]=oids_to_c.pm DSA.asn1
+
+ DEPEND[${DER_DSA_AUX/.c/.o}]=$DER_DSA_H $DER_DIGESTS_H
+ DEPEND[${DER_DSA_GEN/.c/.o}]=$DER_DSA_H
+ GENERATE[$DER_DSA_H]=$INCDIR/der_dsa.h.in
+ DEPEND[$DER_DSA_H]=oids_to_c.pm DSA.asn1
+ENDIF
+
+#----- EC
+IF[{- !$disabled{ec} -}]
+ $DER_EC_H=$INCDIR/der_ec.h
+ $DER_EC_GEN=der_ec_gen.c
+ $DER_EC_AUX=der_ec_key.c der_ec_sig.c
+
+ GENERATE[$DER_EC_GEN]=der_ec_gen.c.in
+ DEPEND[$DER_EC_GEN]=oids_to_c.pm EC.asn1
+
+ DEPEND[${DER_EC_AUX/.c/.o}]=$DER_EC_H $DER_DIGESTS_H
+ DEPEND[${DER_EC_GEN/.c/.o}]=$DER_EC_H
+ GENERATE[$DER_EC_H]=$INCDIR/der_ec.h.in
+ DEPEND[$DER_EC_H]=oids_to_c.pm EC.asn1
+ENDIF
+
+#----- ECX
+IF[{- !$disabled{ec} -}]
+ $DER_ECX_H=$INCDIR/der_ecx.h
+ $DER_ECX_GEN=der_ecx_gen.c
+ $DER_ECX_AUX=der_ecx_key.c
+
+ GENERATE[$DER_ECX_GEN]=der_ecx_gen.c.in
+ DEPEND[$DER_ECX_GEN]=oids_to_c.pm ECX.asn1
+
+ DEPEND[${DER_ECX_AUX/.c/.o}]=$DER_ECX_H
+ DEPEND[${DER_ECX_GEN/.c/.o}]=$DER_ECX_H
+ GENERATE[$DER_ECX_H]=$INCDIR/der_ecx.h.in
+ DEPEND[$DER_ECX_H]=oids_to_c.pm ECX.asn1
+ENDIF
+
+#----- KEY WRAP
+$DER_WRAP_H=$INCDIR/der_wrap.h
+$DER_WRAP_GEN=der_wrap_gen.c
+
+GENERATE[$DER_WRAP_GEN]=der_wrap_gen.c.in
+DEPEND[$DER_WRAP_GEN]=oids_to_c.pm wrap.asn1
+
+DEPEND[${DER_WRAP_GEN/.c/.o}]=$DER_WRAP_H
+GENERATE[$DER_WRAP_H]=$INCDIR/der_wrap.h.in
+DEPEND[$DER_WRAP_H]=oids_to_c.pm wrap.asn1
+
+#----- SM2
+IF[{- !$disabled{sm2} -}]
+ $DER_SM2_H=$INCDIR/der_sm2.h
+ $DER_SM2_GEN=der_sm2_gen.c
+ $DER_SM2_AUX=der_sm2_key.c der_sm2_sig.c
+
+ GENERATE[$DER_SM2_GEN]=der_sm2_gen.c.in
+ DEPEND[$DER_SM2_GEN]=oids_to_c.pm SM2.asn1
+
+ DEPEND[${DER_SM2_AUX/.c/.o}]=$DER_SM2_H $DER_EC_H
+ DEPEND[${DER_SM2_GEN/.c/.o}]=$DER_SM2_H
+ GENERATE[$DER_SM2_H]=$INCDIR/der_sm2.h.in
+ DEPEND[$DER_SM2_H]=oids_to_c.pm SM2.asn1
+ENDIF
+
+#----- Conclusion
+
+$COMMON= $DER_RSA_COMMON $DER_DIGESTS_GEN $DER_WRAP_GEN
+
+IF[{- !$disabled{dsa} -}]
+ $COMMON = $COMMON $DER_DSA_GEN $DER_DSA_AUX
+ENDIF
+
+IF[{- !$disabled{ec} -}]
+ $COMMON = $COMMON $DER_EC_GEN $DER_EC_AUX
+ $COMMON = $COMMON $DER_ECX_GEN $DER_ECX_AUX
+ENDIF
+
+IF[{- !$disabled{sm2} -}]
+ $NONFIPS = $NONFIPS $DER_SM2_GEN $DER_SM2_AUX
+ENDIF
+
+SOURCE[../../libcommon.a]= $COMMON
+SOURCE[../../libfips.a]= $DER_RSA_FIPSABLE
+SOURCE[../../libdefault.a]= $DER_RSA_FIPSABLE $NONFIPS
diff --git a/providers/common/der/der_digests_gen.c.in b/providers/common/der/der_digests_gen.c.in
new file mode 100644
index 000000000000..9b6da1dafb1c
--- /dev/null
+++ b/providers/common/der/der_digests_gen.c.in
@@ -0,0 +1,20 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/der_digests.h"
+
+/* Well known OIDs precompiled */
+{-
+ $OUT = oids_to_c::process_leaves('providers/common/der/NIST.asn1',
+ 'providers/common/der/DIGESTS.asn1',
+ { dir => $config{sourcedir},
+ filter => \&oids_to_c::filter_to_C });
+-}
diff --git a/providers/common/der/der_dsa_gen.c.in b/providers/common/der/der_dsa_gen.c.in
new file mode 100644
index 000000000000..dd581567e87a
--- /dev/null
+++ b/providers/common/der/der_dsa_gen.c.in
@@ -0,0 +1,25 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include "prov/der_dsa.h"
+
+/* Well known OIDs precompiled */
+{-
+ $OUT = oids_to_c::process_leaves('providers/common/der/DSA.asn1',
+ { dir => $config{sourcedir},
+ filter => \&oids_to_c::filter_to_C });
+-}
diff --git a/providers/common/der/der_dsa_key.c b/providers/common/der/der_dsa_key.c
new file mode 100644
index 000000000000..dc7b2fe8faa6
--- /dev/null
+++ b/providers/common/der/der_dsa_key.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/obj_mac.h>
+#include "internal/packet.h"
+#include "prov/der_dsa.h"
+
+int ossl_DER_w_algorithmIdentifier_DSA(WPACKET *pkt, int tag, DSA *dsa)
+{
+ return ossl_DER_w_begin_sequence(pkt, tag)
+ /* No parameters (yet?) */
+ && ossl_DER_w_precompiled(pkt, -1, ossl_der_oid_id_dsa,
+ sizeof(ossl_der_oid_id_dsa))
+ && ossl_DER_w_end_sequence(pkt, tag);
+}
diff --git a/providers/common/der/der_dsa_sig.c b/providers/common/der/der_dsa_sig.c
new file mode 100644
index 000000000000..07225b7b119b
--- /dev/null
+++ b/providers/common/der/der_dsa_sig.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/obj_mac.h>
+#include "internal/packet.h"
+#include "prov/der_dsa.h"
+
+#define MD_CASE(name) \
+ case NID_##name: \
+ precompiled = ossl_der_oid_id_dsa_with_##name; \
+ precompiled_sz = sizeof(ossl_der_oid_id_dsa_with_##name); \
+ break;
+
+int ossl_DER_w_algorithmIdentifier_DSA_with_MD(WPACKET *pkt, int tag,
+ DSA *dsa, int mdnid)
+{
+ const unsigned char *precompiled = NULL;
+ size_t precompiled_sz = 0;
+
+ switch (mdnid) {
+ MD_CASE(sha1);
+ MD_CASE(sha224);
+ MD_CASE(sha256);
+ MD_CASE(sha384);
+ MD_CASE(sha512);
+ MD_CASE(sha3_224);
+ MD_CASE(sha3_256);
+ MD_CASE(sha3_384);
+ MD_CASE(sha3_512);
+ default:
+ return 0;
+ }
+
+ return ossl_DER_w_begin_sequence(pkt, tag)
+ /* No parameters (yet?) */
+ && ossl_DER_w_precompiled(pkt, -1, precompiled, precompiled_sz)
+ && ossl_DER_w_end_sequence(pkt, tag);
+}
diff --git a/providers/common/der/der_ec_gen.c.in b/providers/common/der/der_ec_gen.c.in
new file mode 100644
index 000000000000..ec47686ebe2b
--- /dev/null
+++ b/providers/common/der/der_ec_gen.c.in
@@ -0,0 +1,19 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/der_ec.h"
+
+/* Well known OIDs precompiled */
+{-
+ $OUT = oids_to_c::process_leaves('providers/common/der/EC.asn1',
+ { dir => $config{sourcedir},
+ filter => \&oids_to_c::filter_to_C });
+-}
diff --git a/providers/common/der/der_ec_key.c b/providers/common/der/der_ec_key.c
new file mode 100644
index 000000000000..ae0775af5340
--- /dev/null
+++ b/providers/common/der/der_ec_key.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/obj_mac.h>
+#include "internal/packet.h"
+#include "prov/der_ec.h"
+
+int ossl_DER_w_algorithmIdentifier_EC(WPACKET *pkt, int cont, EC_KEY *ec)
+{
+ return ossl_DER_w_begin_sequence(pkt, cont)
+ /* No parameters (yet?) */
+ && ossl_DER_w_precompiled(pkt, -1, ossl_der_oid_id_ecPublicKey,
+ sizeof(ossl_der_oid_id_ecPublicKey))
+ && ossl_DER_w_end_sequence(pkt, cont);
+}
diff --git a/providers/common/der/der_ec_sig.c b/providers/common/der/der_ec_sig.c
new file mode 100644
index 000000000000..25b672dab2f1
--- /dev/null
+++ b/providers/common/der/der_ec_sig.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/obj_mac.h>
+#include "internal/packet.h"
+#include "prov/der_ec.h"
+
+/* Aliases so we can have a uniform MD_CASE */
+#define ossl_der_oid_id_ecdsa_with_sha1 ossl_der_oid_ecdsa_with_SHA1
+#define ossl_der_oid_id_ecdsa_with_sha224 ossl_der_oid_ecdsa_with_SHA224
+#define ossl_der_oid_id_ecdsa_with_sha256 ossl_der_oid_ecdsa_with_SHA256
+#define ossl_der_oid_id_ecdsa_with_sha384 ossl_der_oid_ecdsa_with_SHA384
+#define ossl_der_oid_id_ecdsa_with_sha512 ossl_der_oid_ecdsa_with_SHA512
+
+#define MD_CASE(name) \
+ case NID_##name: \
+ precompiled = ossl_der_oid_id_ecdsa_with_##name; \
+ precompiled_sz = sizeof(ossl_der_oid_id_ecdsa_with_##name); \
+ break;
+
+int ossl_DER_w_algorithmIdentifier_ECDSA_with_MD(WPACKET *pkt, int cont,
+ EC_KEY *ec, int mdnid)
+{
+ const unsigned char *precompiled = NULL;
+ size_t precompiled_sz = 0;
+
+ switch (mdnid) {
+ MD_CASE(sha1);
+ MD_CASE(sha224);
+ MD_CASE(sha256);
+ MD_CASE(sha384);
+ MD_CASE(sha512);
+ MD_CASE(sha3_224);
+ MD_CASE(sha3_256);
+ MD_CASE(sha3_384);
+ MD_CASE(sha3_512);
+ default:
+ return 0;
+ }
+
+ return ossl_DER_w_begin_sequence(pkt, cont)
+ /* No parameters (yet?) */
+ && ossl_DER_w_precompiled(pkt, -1, precompiled, precompiled_sz)
+ && ossl_DER_w_end_sequence(pkt, cont);
+}
diff --git a/providers/common/der/der_ecx_gen.c.in b/providers/common/der/der_ecx_gen.c.in
new file mode 100644
index 000000000000..bcd45b6e4d52
--- /dev/null
+++ b/providers/common/der/der_ecx_gen.c.in
@@ -0,0 +1,19 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/der_ecx.h"
+
+/* Well known OIDs precompiled */
+{-
+ $OUT = oids_to_c::process_leaves('providers/common/der/ECX.asn1',
+ { dir => $config{sourcedir},
+ filter => \&oids_to_c::filter_to_C });
+-}
diff --git a/providers/common/der/der_ecx_key.c b/providers/common/der/der_ecx_key.c
new file mode 100644
index 000000000000..c00a11cac8ee
--- /dev/null
+++ b/providers/common/der/der_ecx_key.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/obj_mac.h>
+#include "internal/packet.h"
+#include "prov/der_ecx.h"
+
+int ossl_DER_w_algorithmIdentifier_X25519(WPACKET *pkt, int cont, ECX_KEY *ec)
+{
+ return ossl_DER_w_begin_sequence(pkt, cont)
+ /* No parameters (yet?) */
+ && ossl_DER_w_precompiled(pkt, -1, ossl_der_oid_id_X25519,
+ sizeof(ossl_der_oid_id_X25519))
+ && ossl_DER_w_end_sequence(pkt, cont);
+}
+
+int ossl_DER_w_algorithmIdentifier_X448(WPACKET *pkt, int cont, ECX_KEY *ec)
+{
+ return ossl_DER_w_begin_sequence(pkt, cont)
+ /* No parameters (yet?) */
+ && ossl_DER_w_precompiled(pkt, -1, ossl_der_oid_id_X448,
+ sizeof(ossl_der_oid_id_X448))
+ && ossl_DER_w_end_sequence(pkt, cont);
+}
+
+int ossl_DER_w_algorithmIdentifier_ED25519(WPACKET *pkt, int cont, ECX_KEY *ec)
+{
+ return ossl_DER_w_begin_sequence(pkt, cont)
+ /* No parameters (yet?) */
+ && ossl_DER_w_precompiled(pkt, -1, ossl_der_oid_id_Ed25519,
+ sizeof(ossl_der_oid_id_Ed25519))
+ && ossl_DER_w_end_sequence(pkt, cont);
+}
+
+int ossl_DER_w_algorithmIdentifier_ED448(WPACKET *pkt, int cont, ECX_KEY *ec)
+{
+ return ossl_DER_w_begin_sequence(pkt, cont)
+ /* No parameters (yet?) */
+ && ossl_DER_w_precompiled(pkt, -1, ossl_der_oid_id_Ed448,
+ sizeof(ossl_der_oid_id_Ed448))
+ && ossl_DER_w_end_sequence(pkt, cont);
+}
diff --git a/providers/common/der/der_rsa_gen.c.in b/providers/common/der/der_rsa_gen.c.in
new file mode 100644
index 000000000000..0560f649e8e0
--- /dev/null
+++ b/providers/common/der/der_rsa_gen.c.in
@@ -0,0 +1,20 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/der_rsa.h"
+
+/* Well known OIDs precompiled */
+{-
+ $OUT = oids_to_c::process_leaves('providers/common/der/NIST.asn1',
+ 'providers/common/der/RSA.asn1',
+ { dir => $config{sourcedir},
+ filter => \&oids_to_c::filter_to_C });
+-}
diff --git a/providers/common/der/der_rsa_key.c b/providers/common/der/der_rsa_key.c
new file mode 100644
index 000000000000..771150d893da
--- /dev/null
+++ b/providers/common/der/der_rsa_key.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/obj_mac.h>
+#include "internal/cryptlib.h"
+#include "prov/der_rsa.h"
+#include "prov/der_digests.h"
+
+/* More complex pre-compiled sequences. */
+
+/*-
+ * From https://tools.ietf.org/html/rfc8017#appendix-A.2.1
+ *
+ * OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-sha1 PARAMETERS NULL }|
+ * { OID id-sha224 PARAMETERS NULL }|
+ * { OID id-sha256 PARAMETERS NULL }|
+ * { OID id-sha384 PARAMETERS NULL }|
+ * { OID id-sha512 PARAMETERS NULL }|
+ * { OID id-sha512-224 PARAMETERS NULL }|
+ * { OID id-sha512-256 PARAMETERS NULL },
+ * ... -- Allows for future expansion --
+ * }
+ */
+#define DER_V_NULL DER_P_NULL, 0
+#define DER_SZ_NULL 2
+
+/*
+ * The names for the hash function AlgorithmIdentifiers are borrowed and
+ * expanded from https://tools.ietf.org/html/rfc4055#section-2.1
+ *
+ * sha1Identifier AlgorithmIdentifier ::= { id-sha1, NULL }
+ * sha224Identifier AlgorithmIdentifier ::= { id-sha224, NULL }
+ * sha256Identifier AlgorithmIdentifier ::= { id-sha256, NULL }
+ * sha384Identifier AlgorithmIdentifier ::= { id-sha384, NULL }
+ * sha512Identifier AlgorithmIdentifier ::= { id-sha512, NULL }
+ */
+/*
+ * NOTE: Some of the arrays aren't used other than inside sizeof(), which
+ * clang complains about (-Wno-unneeded-internal-declaration). To get
+ * around that, we make them non-static, and declare them an extra time to
+ * avoid compilers complaining about definitions without declarations.
+ */
+#define DER_AID_V_sha1Identifier \
+ DER_P_SEQUENCE|DER_F_CONSTRUCTED, \
+ DER_OID_SZ_id_sha1 + DER_SZ_NULL, \
+ DER_OID_V_id_sha1, \
+ DER_V_NULL
+extern const unsigned char ossl_der_aid_sha1Identifier[];
+const unsigned char ossl_der_aid_sha1Identifier[] = {
+ DER_AID_V_sha1Identifier
+};
+#define DER_AID_SZ_sha1Identifier sizeof(ossl_der_aid_sha1Identifier)
+
+#define DER_AID_V_sha224Identifier \
+ DER_P_SEQUENCE|DER_F_CONSTRUCTED, \
+ DER_OID_SZ_id_sha224 + DER_SZ_NULL, \
+ DER_OID_V_id_sha224, \
+ DER_V_NULL
+extern const unsigned char ossl_der_aid_sha224Identifier[];
+const unsigned char ossl_der_aid_sha224Identifier[] = {
+ DER_AID_V_sha224Identifier
+};
+#define DER_AID_SZ_sha224Identifier sizeof(ossl_der_aid_sha224Identifier)
+
+#define DER_AID_V_sha256Identifier \
+ DER_P_SEQUENCE|DER_F_CONSTRUCTED, \
+ DER_OID_SZ_id_sha256 + DER_SZ_NULL, \
+ DER_OID_V_id_sha256, \
+ DER_V_NULL
+extern const unsigned char ossl_der_aid_sha256Identifier[];
+const unsigned char ossl_der_aid_sha256Identifier[] = {
+ DER_AID_V_sha256Identifier
+};
+#define DER_AID_SZ_sha256Identifier sizeof(ossl_der_aid_sha256Identifier)
+
+#define DER_AID_V_sha384Identifier \
+ DER_P_SEQUENCE|DER_F_CONSTRUCTED, \
+ DER_OID_SZ_id_sha384 + DER_SZ_NULL, \
+ DER_OID_V_id_sha384, \
+ DER_V_NULL
+extern const unsigned char ossl_der_aid_sha384Identifier[];
+const unsigned char ossl_der_aid_sha384Identifier[] = {
+ DER_AID_V_sha384Identifier
+};
+#define DER_AID_SZ_sha384Identifier sizeof(ossl_der_aid_sha384Identifier)
+
+#define DER_AID_V_sha512Identifier \
+ DER_P_SEQUENCE|DER_F_CONSTRUCTED, \
+ DER_OID_SZ_id_sha512 + DER_SZ_NULL, \
+ DER_OID_V_id_sha512, \
+ DER_V_NULL
+extern const unsigned char ossl_der_aid_sha512Identifier[];
+const unsigned char ossl_der_aid_sha512Identifier[] = {
+ DER_AID_V_sha512Identifier
+};
+#define DER_AID_SZ_sha512Identifier sizeof(ossl_der_aid_sha512Identifier)
+
+#define DER_AID_V_sha512_224Identifier \
+ DER_P_SEQUENCE|DER_F_CONSTRUCTED, \
+ DER_OID_SZ_id_sha512_224 + DER_SZ_NULL, \
+ DER_OID_V_id_sha512_224, \
+ DER_V_NULL
+extern const unsigned char ossl_der_aid_sha512_224Identifier[];
+const unsigned char ossl_der_aid_sha512_224Identifier[] = {
+ DER_AID_V_sha512_224Identifier
+};
+#define DER_AID_SZ_sha512_224Identifier sizeof(ossl_der_aid_sha512_224Identifier)
+
+#define DER_AID_V_sha512_256Identifier \
+ DER_P_SEQUENCE|DER_F_CONSTRUCTED, \
+ DER_OID_SZ_id_sha512_256 + DER_SZ_NULL, \
+ DER_OID_V_id_sha512_256, \
+ DER_V_NULL
+extern const unsigned char ossl_der_aid_sha512_256Identifier[];
+const unsigned char ossl_der_aid_sha512_256Identifier[] = {
+ DER_AID_V_sha512_256Identifier
+};
+#define DER_AID_SZ_sha512_256Identifier sizeof(ossl_der_aid_sha512_256Identifier)
+
+/*-
+ * From https://tools.ietf.org/html/rfc8017#appendix-A.2.1
+ *
+ * HashAlgorithm ::= AlgorithmIdentifier {
+ * {OAEP-PSSDigestAlgorithms}
+ * }
+ *
+ * ...
+ *
+ * PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-mgf1 PARAMETERS HashAlgorithm },
+ * ... -- Allows for future expansion --
+ * }
+ */
+
+/*
+ * The names for the MGF1 AlgorithmIdentifiers are borrowed and expanded
+ * from https://tools.ietf.org/html/rfc4055#section-2.1
+ *
+ * mgf1SHA1Identifier AlgorithmIdentifier ::=
+ * { id-mgf1, sha1Identifier }
+ * mgf1SHA224Identifier AlgorithmIdentifier ::=
+ * { id-mgf1, sha224Identifier }
+ * mgf1SHA256Identifier AlgorithmIdentifier ::=
+ * { id-mgf1, sha256Identifier }
+ * mgf1SHA384Identifier AlgorithmIdentifier ::=
+ * { id-mgf1, sha384Identifier }
+ * mgf1SHA512Identifier AlgorithmIdentifier ::=
+ * { id-mgf1, sha512Identifier }
+ */
+#if 0 /* Currently unused */
+#define DER_AID_V_mgf1SHA1Identifier \
+ DER_P_SEQUENCE|DER_F_CONSTRUCTED, \
+ DER_OID_SZ_id_mgf1 + DER_AID_SZ_sha1Identifier, \
+ DER_OID_V_id_mgf1, \
+ DER_AID_V_sha1Identifier
+static const unsigned char der_aid_mgf1SHA1Identifier[] = {
+ DER_AID_V_mgf1SHA1Identifier
+};
+#define DER_AID_SZ_mgf1SHA1Identifier sizeof(der_aid_mgf1SHA1Identifier)
+#endif
+
+#define DER_AID_V_mgf1SHA224Identifier \
+ DER_P_SEQUENCE|DER_F_CONSTRUCTED, \
+ DER_OID_SZ_id_mgf1 + DER_AID_SZ_sha224Identifier, \
+ DER_OID_V_id_mgf1, \
+ DER_AID_V_sha224Identifier
+static const unsigned char der_aid_mgf1SHA224Identifier[] = {
+ DER_AID_V_mgf1SHA224Identifier
+};
+#define DER_AID_SZ_mgf1SHA224Identifier sizeof(der_aid_mgf1SHA224Identifier)
+
+#define DER_AID_V_mgf1SHA256Identifier \
+ DER_P_SEQUENCE|DER_F_CONSTRUCTED, \
+ DER_OID_SZ_id_mgf1 + DER_AID_SZ_sha256Identifier, \
+ DER_OID_V_id_mgf1, \
+ DER_AID_V_sha256Identifier
+static const unsigned char der_aid_mgf1SHA256Identifier[] = {
+ DER_AID_V_mgf1SHA256Identifier
+};
+#define DER_AID_SZ_mgf1SHA256Identifier sizeof(der_aid_mgf1SHA256Identifier)
+
+#define DER_AID_V_mgf1SHA384Identifier \
+ DER_P_SEQUENCE|DER_F_CONSTRUCTED, \
+ DER_OID_SZ_id_mgf1 + DER_AID_SZ_sha384Identifier, \
+ DER_OID_V_id_mgf1, \
+ DER_AID_V_sha384Identifier
+static const unsigned char der_aid_mgf1SHA384Identifier[] = {
+ DER_AID_V_mgf1SHA384Identifier
+};
+#define DER_AID_SZ_mgf1SHA384Identifier sizeof(der_aid_mgf1SHA384Identifier)
+
+#define DER_AID_V_mgf1SHA512Identifier \
+ DER_P_SEQUENCE|DER_F_CONSTRUCTED, \
+ DER_OID_SZ_id_mgf1 + DER_AID_SZ_sha512Identifier, \
+ DER_OID_V_id_mgf1, \
+ DER_AID_V_sha512Identifier
+static const unsigned char der_aid_mgf1SHA512Identifier[] = {
+ DER_AID_V_mgf1SHA512Identifier
+};
+#define DER_AID_SZ_mgf1SHA512Identifier sizeof(der_aid_mgf1SHA512Identifier)
+
+#define DER_AID_V_mgf1SHA512_224Identifier \
+ DER_P_SEQUENCE|DER_F_CONSTRUCTED, \
+ DER_OID_SZ_id_mgf1 + DER_AID_SZ_sha512_224Identifier, \
+ DER_OID_V_id_mgf1, \
+ DER_AID_V_sha512_224Identifier
+static const unsigned char der_aid_mgf1SHA512_224Identifier[] = {
+ DER_AID_V_mgf1SHA512_224Identifier
+};
+#define DER_AID_SZ_mgf1SHA512_224Identifier sizeof(der_aid_mgf1SHA512_224Identifier)
+
+#define DER_AID_V_mgf1SHA512_256Identifier \
+ DER_P_SEQUENCE|DER_F_CONSTRUCTED, \
+ DER_OID_SZ_id_mgf1 + DER_AID_SZ_sha512_256Identifier, \
+ DER_OID_V_id_mgf1, \
+ DER_AID_V_sha512_256Identifier
+static const unsigned char der_aid_mgf1SHA512_256Identifier[] = {
+ DER_AID_V_mgf1SHA512_256Identifier
+};
+#define DER_AID_SZ_mgf1SHA512_256Identifier sizeof(der_aid_mgf1SHA512_256Identifier)
+
+
+#define MGF1_SHA_CASE(bits, var) \
+ case NID_sha##bits: \
+ var = der_aid_mgf1SHA##bits##Identifier; \
+ var##_sz = sizeof(der_aid_mgf1SHA##bits##Identifier); \
+ break;
+
+/*-
+ * The name is borrowed from https://tools.ietf.org/html/rfc8017#appendix-A.2.1
+ *
+ * MaskGenAlgorithm ::= AlgorithmIdentifier { {PKCS1MGFAlgorithms} }
+ */
+static int DER_w_MaskGenAlgorithm(WPACKET *pkt, int tag,
+ const RSA_PSS_PARAMS_30 *pss)
+{
+ if (pss != NULL && ossl_rsa_pss_params_30_maskgenalg(pss) == NID_mgf1) {
+ int maskgenhashalg_nid = ossl_rsa_pss_params_30_maskgenhashalg(pss);
+ const unsigned char *maskgenalg = NULL;
+ size_t maskgenalg_sz = 0;
+
+ switch (maskgenhashalg_nid) {
+ case NID_sha1:
+ break;
+ MGF1_SHA_CASE(224, maskgenalg);
+ MGF1_SHA_CASE(256, maskgenalg);
+ MGF1_SHA_CASE(384, maskgenalg);
+ MGF1_SHA_CASE(512, maskgenalg);
+ MGF1_SHA_CASE(512_224, maskgenalg);
+ MGF1_SHA_CASE(512_256, maskgenalg);
+ default:
+ return 0;
+ }
+
+ /* If there is none (or it was the default), we write nothing */
+ if (maskgenalg == NULL)
+ return 1;
+
+ return ossl_DER_w_precompiled(pkt, tag, maskgenalg, maskgenalg_sz);
+ }
+ return 0;
+}
+
+#define OAEP_PSS_MD_CASE(name, var) \
+ case NID_##name: \
+ var = ossl_der_aid_##name##Identifier; \
+ var##_sz = sizeof(ossl_der_aid_##name##Identifier); \
+ break;
+
+int ossl_DER_w_RSASSA_PSS_params(WPACKET *pkt, int tag,
+ const RSA_PSS_PARAMS_30 *pss)
+{
+ int hashalg_nid, default_hashalg_nid;
+ int saltlen, default_saltlen;
+ int trailerfield, default_trailerfield;
+ const unsigned char *hashalg = NULL;
+ size_t hashalg_sz = 0;
+
+ /*
+ * For an unrestricted key, this function should not have been called;
+ * the caller must be in control, because unrestricted keys are permitted
+ * in some situations (when encoding the public key in a SubjectKeyInfo,
+ * for example) while not in others, and this function doesn't know the
+ * intent. Therefore, we assert that here, the PSS parameters must show
+ * that the key is restricted.
+ */
+ if (!ossl_assert(pss != NULL
+ && !ossl_rsa_pss_params_30_is_unrestricted(pss)))
+ return 0;
+
+ hashalg_nid = ossl_rsa_pss_params_30_hashalg(pss);
+ saltlen = ossl_rsa_pss_params_30_saltlen(pss);
+ trailerfield = ossl_rsa_pss_params_30_trailerfield(pss);
+
+ if (saltlen < 0) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_SALT_LENGTH);
+ return 0;
+ }
+ if (trailerfield != 1) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_TRAILER);
+ return 0;
+ }
+
+ /* Getting default values */
+ default_hashalg_nid = ossl_rsa_pss_params_30_hashalg(NULL);
+ default_saltlen = ossl_rsa_pss_params_30_saltlen(NULL);
+ default_trailerfield = ossl_rsa_pss_params_30_trailerfield(NULL);
+
+ /*
+ * From https://tools.ietf.org/html/rfc8017#appendix-A.2.1:
+ *
+ * OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-sha1 PARAMETERS NULL }|
+ * { OID id-sha224 PARAMETERS NULL }|
+ * { OID id-sha256 PARAMETERS NULL }|
+ * { OID id-sha384 PARAMETERS NULL }|
+ * { OID id-sha512 PARAMETERS NULL }|
+ * { OID id-sha512-224 PARAMETERS NULL }|
+ * { OID id-sha512-256 PARAMETERS NULL },
+ * ... -- Allows for future expansion --
+ * }
+ */
+ switch (hashalg_nid) {
+ OAEP_PSS_MD_CASE(sha1, hashalg);
+ OAEP_PSS_MD_CASE(sha224, hashalg);
+ OAEP_PSS_MD_CASE(sha256, hashalg);
+ OAEP_PSS_MD_CASE(sha384, hashalg);
+ OAEP_PSS_MD_CASE(sha512, hashalg);
+ OAEP_PSS_MD_CASE(sha512_224, hashalg);
+ OAEP_PSS_MD_CASE(sha512_256, hashalg);
+ default:
+ return 0;
+ }
+
+ return ossl_DER_w_begin_sequence(pkt, tag)
+ && (trailerfield == default_trailerfield
+ || ossl_DER_w_uint32(pkt, 3, (uint32_t)trailerfield))
+ && (saltlen == default_saltlen || ossl_DER_w_uint32(pkt, 2, (uint32_t)saltlen))
+ && DER_w_MaskGenAlgorithm(pkt, 1, pss)
+ && (hashalg_nid == default_hashalg_nid
+ || ossl_DER_w_precompiled(pkt, 0, hashalg, hashalg_sz))
+ && ossl_DER_w_end_sequence(pkt, tag);
+}
+
+/* Aliases so we can have a uniform RSA_CASE */
+#define ossl_der_oid_rsassaPss ossl_der_oid_id_RSASSA_PSS
+
+#define RSA_CASE(name, var) \
+ var##_nid = NID_##name; \
+ var##_oid = ossl_der_oid_##name; \
+ var##_oid_sz = sizeof(ossl_der_oid_##name); \
+ break;
+
+int ossl_DER_w_algorithmIdentifier_RSA_PSS(WPACKET *pkt, int tag,
+ int rsa_type,
+ const RSA_PSS_PARAMS_30 *pss)
+{
+ int rsa_nid = NID_undef;
+ const unsigned char *rsa_oid = NULL;
+ size_t rsa_oid_sz = 0;
+
+ switch (rsa_type) {
+ case RSA_FLAG_TYPE_RSA:
+ RSA_CASE(rsaEncryption, rsa);
+ case RSA_FLAG_TYPE_RSASSAPSS:
+ RSA_CASE(rsassaPss, rsa);
+ }
+
+ if (rsa_oid == NULL)
+ return 0;
+
+ return ossl_DER_w_begin_sequence(pkt, tag)
+ && (rsa_nid != NID_rsassaPss
+ || ossl_rsa_pss_params_30_is_unrestricted(pss)
+ || ossl_DER_w_RSASSA_PSS_params(pkt, -1, pss))
+ && ossl_DER_w_precompiled(pkt, -1, rsa_oid, rsa_oid_sz)
+ && ossl_DER_w_end_sequence(pkt, tag);
+}
+
+int ossl_DER_w_algorithmIdentifier_RSA(WPACKET *pkt, int tag, RSA *rsa)
+{
+ int rsa_type = RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK);
+ RSA_PSS_PARAMS_30 *pss_params = ossl_rsa_get0_pss_params_30(rsa);
+
+ return ossl_DER_w_algorithmIdentifier_RSA_PSS(pkt, tag, rsa_type,
+ pss_params);
+}
diff --git a/providers/common/der/der_rsa_sig.c b/providers/common/der/der_rsa_sig.c
new file mode 100644
index 000000000000..08d00641e9b3
--- /dev/null
+++ b/providers/common/der/der_rsa_sig.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/obj_mac.h>
+#include "internal/packet.h"
+#include "prov/der_rsa.h"
+#include "prov/der_digests.h"
+
+/* Aliases so we can have a uniform MD_with_RSA_CASE */
+#define ossl_der_oid_sha3_224WithRSAEncryption \
+ ossl_der_oid_id_rsassa_pkcs1_v1_5_with_sha3_224
+#define ossl_der_oid_sha3_256WithRSAEncryption \
+ ossl_der_oid_id_rsassa_pkcs1_v1_5_with_sha3_256
+#define ossl_der_oid_sha3_384WithRSAEncryption \
+ ossl_der_oid_id_rsassa_pkcs1_v1_5_with_sha3_384
+#define ossl_der_oid_sha3_512WithRSAEncryption \
+ ossl_der_oid_id_rsassa_pkcs1_v1_5_with_sha3_512
+#define ossl_der_oid_mdc2WithRSAEncryption \
+ ossl_der_oid_mdc2WithRSASignature
+
+#define MD_with_RSA_CASE(name, var) \
+ case NID_##name: \
+ var = ossl_der_oid_##name##WithRSAEncryption; \
+ var##_sz = sizeof(ossl_der_oid_##name##WithRSAEncryption); \
+ break;
+
+int ossl_DER_w_algorithmIdentifier_MDWithRSAEncryption(WPACKET *pkt, int tag,
+ int mdnid)
+{
+ const unsigned char *precompiled = NULL;
+ size_t precompiled_sz = 0;
+
+ switch (mdnid) {
+#ifndef FIPS_MODULE
+ MD_with_RSA_CASE(md2, precompiled);
+ MD_with_RSA_CASE(md5, precompiled);
+ MD_with_RSA_CASE(md4, precompiled);
+ MD_with_RSA_CASE(ripemd160, precompiled);
+ MD_with_RSA_CASE(mdc2, precompiled);
+#endif
+ MD_with_RSA_CASE(sha1, precompiled);
+ MD_with_RSA_CASE(sha224, precompiled);
+ MD_with_RSA_CASE(sha256, precompiled);
+ MD_with_RSA_CASE(sha384, precompiled);
+ MD_with_RSA_CASE(sha512, precompiled);
+ MD_with_RSA_CASE(sha512_224, precompiled);
+ MD_with_RSA_CASE(sha512_256, precompiled);
+ MD_with_RSA_CASE(sha3_224, precompiled);
+ MD_with_RSA_CASE(sha3_256, precompiled);
+ MD_with_RSA_CASE(sha3_384, precompiled);
+ MD_with_RSA_CASE(sha3_512, precompiled);
+ default:
+ /*
+ * Hash algorithms for which we do not have a valid OID
+ * such as md5sha1 will just fail to provide the der encoding.
+ * That does not prevent producing signatures if OID is not needed.
+ */
+ return -1;
+ }
+
+ return ossl_DER_w_begin_sequence(pkt, tag)
+ /* PARAMETERS, always NULL according to current standards */
+ && ossl_DER_w_null(pkt, -1)
+ /* OID */
+ && ossl_DER_w_precompiled(pkt, -1, precompiled, precompiled_sz)
+ && ossl_DER_w_end_sequence(pkt, tag);
+}
diff --git a/providers/common/der/der_sm2_gen.c.in b/providers/common/der/der_sm2_gen.c.in
new file mode 100644
index 000000000000..ac28307bfb7d
--- /dev/null
+++ b/providers/common/der/der_sm2_gen.c.in
@@ -0,0 +1,19 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/der_sm2.h"
+
+/* Well known OIDs precompiled */
+{-
+ $OUT = oids_to_c::process_leaves('providers/common/der/SM2.asn1',
+ { dir => $config{sourcedir},
+ filter => \&oids_to_c::filter_to_C });
+-}
diff --git a/providers/common/der/der_sm2_key.c b/providers/common/der/der_sm2_key.c
new file mode 100644
index 000000000000..d0b7e3aa2854
--- /dev/null
+++ b/providers/common/der/der_sm2_key.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/obj_mac.h>
+#include "internal/packet.h"
+#include "prov/der_ec.h"
+#include "prov/der_sm2.h"
+
+int ossl_DER_w_algorithmIdentifier_SM2(WPACKET *pkt, int cont, EC_KEY *ec)
+{
+ return ossl_DER_w_begin_sequence(pkt, cont)
+ /* No parameters (yet?) */
+ /* It seems SM2 identifier is the same as id_ecPublidKey */
+ && ossl_DER_w_precompiled(pkt, -1, ossl_der_oid_id_ecPublicKey,
+ sizeof(ossl_der_oid_id_ecPublicKey))
+ && ossl_DER_w_end_sequence(pkt, cont);
+}
diff --git a/providers/common/der/der_sm2_sig.c b/providers/common/der/der_sm2_sig.c
new file mode 100644
index 000000000000..085e2c7cb534
--- /dev/null
+++ b/providers/common/der/der_sm2_sig.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/obj_mac.h>
+#include "internal/packet.h"
+#include "prov/der_sm2.h"
+
+/* Aliases so we can have a uniform MD_CASE */
+#define ossl_der_oid_id_sm2_with_sm3 ossl_der_oid_sm2_with_SM3
+
+#define MD_CASE(name) \
+ case NID_##name: \
+ precompiled = ossl_der_oid_id_sm2_with_##name; \
+ precompiled_sz = sizeof(ossl_der_oid_id_sm2_with_##name); \
+ break;
+
+int ossl_DER_w_algorithmIdentifier_SM2_with_MD(WPACKET *pkt, int cont,
+ EC_KEY *ec, int mdnid)
+{
+ const unsigned char *precompiled = NULL;
+ size_t precompiled_sz = 0;
+
+ switch (mdnid) {
+ MD_CASE(sm3);
+ default:
+ return 0;
+ }
+
+ return ossl_DER_w_begin_sequence(pkt, cont)
+ /* No parameters (yet?) */
+ && ossl_DER_w_precompiled(pkt, -1, precompiled, precompiled_sz)
+ && ossl_DER_w_end_sequence(pkt, cont);
+}
diff --git a/providers/common/der/der_wrap_gen.c.in b/providers/common/der/der_wrap_gen.c.in
new file mode 100644
index 000000000000..d3a6bb909257
--- /dev/null
+++ b/providers/common/der/der_wrap_gen.c.in
@@ -0,0 +1,19 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/der_wrap.h"
+
+/* Well known OIDs precompiled */
+{-
+ $OUT = oids_to_c::process_leaves('providers/common/der/wrap.asn1',
+ { dir => $config{sourcedir},
+ filter => \&oids_to_c::filter_to_C });
+-}
diff --git a/providers/common/der/oids_to_c.pm b/providers/common/der/oids_to_c.pm
new file mode 100644
index 000000000000..6f57df09b93a
--- /dev/null
+++ b/providers/common/der/oids_to_c.pm
@@ -0,0 +1,113 @@
+#! /usr/bin/env perl
+# Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use strict;
+use warnings;
+
+package oids_to_c;
+
+use Carp;
+use File::Spec;
+use OpenSSL::OID;
+
+my $OID_name_re = qr/([a-z](?:[-_A-Za-z0-9]*[A-Za-z0-9])?)/;
+my $OID_value_re = qr/(\{.*?\})/s;
+my $OID_def_re = qr/
+ ${OID_name_re} \s+ OBJECT \s+ IDENTIFIER \s*
+ ::=
+ \s* ${OID_value_re}
+ /x;
+
+sub filter_to_H {
+ my ($name, $comment) = @{ shift() };
+ my @oid_nums = @_;
+ my $oid_size = scalar @oid_nums;
+
+ (my $C_comment = $comment) =~ s|^| * |msg;
+ $C_comment = "\n/*\n${C_comment}\n */" if $C_comment ne '';
+ (my $C_name = $name) =~ s|-|_|g;
+ my $C_bytes_size = 2 + scalar @_;
+ my $C_bytes = join(', ', map { sprintf("0x%02X", $_) } @oid_nums );
+
+ return <<"_____";
+$C_comment
+#define DER_OID_V_${C_name} DER_P_OBJECT, $oid_size, ${C_bytes}
+#define DER_OID_SZ_${C_name} ${C_bytes_size}
+extern const unsigned char ossl_der_oid_${C_name}[DER_OID_SZ_${C_name}];
+_____
+}
+
+sub filter_to_C {
+ my ($name, $comment) = @{ shift() };
+ my @oid_nums = @_;
+ my $oid_size = scalar @oid_nums;
+
+ croak "Unsupported OID size (>127 bytes)" if $oid_size > 127;
+
+ (my $C_comment = $comment) =~ s|^| * |msg;
+ $C_comment = "\n/*\n${C_comment}\n */" if $C_comment ne '';
+ (my $C_name = $name) =~ s|-|_|g;
+ my $C_bytes_size = 2 + $oid_size;
+
+ return <<"_____";
+$C_comment
+const unsigned char ossl_der_oid_${C_name}[DER_OID_SZ_${C_name}] = {
+ DER_OID_V_${C_name}
+};
+_____
+}
+
+sub _process {
+ my %opts = %{ pop @_ } if ref $_[$#_] eq 'HASH';
+
+ # To maintain input order
+ my @OID_names = ();
+
+ foreach my $file (@_) {
+ my $input = File::Spec->catfile($opts{dir}, $file);
+ open my $fh, $input or die "Reading $input: $!\n";
+
+ my $text = join('',
+ map {
+ s|--.*(\R)$|$1|;
+ $_;
+ } <$fh>);
+ # print STDERR "-----BEGIN DEBUG-----\n";
+ # print STDERR $text;
+ # print STDERR "-----END DEBUG-----\n";
+ use re 'debugcolor';
+ while ($text =~ m/${OID_def_re}/sg) {
+ my $comment = $&;
+ my $name = $1;
+ my $value = $2;
+
+ # print STDERR "-----BEGIN DEBUG $name-----\n";
+ # print STDERR $value,"\n";
+ # print STDERR "-----END DEBUG $name-----\n";
+ register_oid($name, $value);
+ push @OID_names, [ $name, $comment ];
+ }
+ }
+
+ return @OID_names;
+}
+
+sub process_leaves {
+ my %opts = %{ $_[$#_] } if ref $_[$#_] eq 'HASH';
+ my @OID_names = _process @_;
+
+ my $text = '';
+ my %leaves = map { $_ => 1 } registered_oid_leaves;
+ foreach (grep { defined $leaves{$_->[0]} } @OID_names) {
+ my $lines = $opts{filter}->($_, encode_oid($_->[0]));
+ $text .= $lines;
+ }
+ return $text;
+}
+
+1;
diff --git a/providers/common/der/wrap.asn1 b/providers/common/der/wrap.asn1
new file mode 100644
index 000000000000..07e23b440ea0
--- /dev/null
+++ b/providers/common/der/wrap.asn1
@@ -0,0 +1,26 @@
+-- Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+--
+-- Licensed under the Apache License 2.0 (the "License"). You may not use
+-- this file except in compliance with the License. You can obtain a copy
+-- in the file LICENSE in the source distribution or at
+-- https://www.openssl.org/source/license.html
+
+-- -------------------------------------------------------------------
+-- Taken from RFC 3370, Section 4.3.1 Triple-DES Key Wrap
+-- (https://tools.ietf.org/html/rfc3370)
+
+id-alg-CMS3DESwrap OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) alg(3) 6
+}
+
+-- -------------------------------------------------------------------
+-- Taken from RFC 3394, Section 3. Object Identifiers
+-- (https://tools.ietf.org/html/rfc3565)
+
+aes OBJECT IDENTIFIER ::= {
+ joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1
+}
+
+id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 }
+id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 }
+id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 }
diff --git a/providers/common/digest_to_nid.c b/providers/common/digest_to_nid.c
new file mode 100644
index 000000000000..49af04ad2a21
--- /dev/null
+++ b/providers/common/digest_to_nid.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/deprecated.h"
+
+#include <openssl/objects.h>
+#include <openssl/core_names.h>
+#include <openssl/evp.h>
+#include <openssl/core.h>
+#include "prov/securitycheck.h"
+#include "internal/nelem.h"
+
+/*
+ * Internal library code deals with NIDs, so we need to translate from a name.
+ * We do so using EVP_MD_is_a(), and therefore need a name to NID map.
+ */
+int ossl_digest_md_to_nid(const EVP_MD *md, const OSSL_ITEM *it, size_t it_len)
+{
+ size_t i;
+
+ if (md == NULL)
+ return NID_undef;
+
+ for (i = 0; i < it_len; i++)
+ if (EVP_MD_is_a(md, it[i].ptr))
+ return (int)it[i].id;
+ return NID_undef;
+}
+
+/*
+ * Retrieve one of the FIPS approved hash algorithms by nid.
+ * See FIPS 180-4 "Secure Hash Standard" and FIPS 202 - SHA-3.
+ */
+int ossl_digest_get_approved_nid(const EVP_MD *md)
+{
+ static const OSSL_ITEM name_to_nid[] = {
+ { NID_sha1, OSSL_DIGEST_NAME_SHA1 },
+ { NID_sha224, OSSL_DIGEST_NAME_SHA2_224 },
+ { NID_sha256, OSSL_DIGEST_NAME_SHA2_256 },
+ { NID_sha384, OSSL_DIGEST_NAME_SHA2_384 },
+ { NID_sha512, OSSL_DIGEST_NAME_SHA2_512 },
+ { NID_sha512_224, OSSL_DIGEST_NAME_SHA2_512_224 },
+ { NID_sha512_256, OSSL_DIGEST_NAME_SHA2_512_256 },
+ { NID_sha3_224, OSSL_DIGEST_NAME_SHA3_224 },
+ { NID_sha3_256, OSSL_DIGEST_NAME_SHA3_256 },
+ { NID_sha3_384, OSSL_DIGEST_NAME_SHA3_384 },
+ { NID_sha3_512, OSSL_DIGEST_NAME_SHA3_512 },
+ };
+
+ return ossl_digest_md_to_nid(md, name_to_nid, OSSL_NELEM(name_to_nid));
+}
diff --git a/providers/common/include/prov/__DECC_INCLUDE_EPILOGUE.H b/providers/common/include/prov/__DECC_INCLUDE_EPILOGUE.H
new file mode 100644
index 000000000000..2ab493330675
--- /dev/null
+++ b/providers/common/include/prov/__DECC_INCLUDE_EPILOGUE.H
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This file is only used by HP C/C++ on VMS, and is included automatically
+ * after each header file from this directory
+ */
+
+/*
+ * The C++ compiler doesn't understand these pragmas, even though it
+ * understands the corresponding command line qualifier.
+ */
+#ifndef __cplusplus
+/* restore state. Must correspond to the save in __decc_include_prologue.h */
+# pragma names restore
+#endif
diff --git a/providers/common/include/prov/__DECC_INCLUDE_PROLOGUE.H b/providers/common/include/prov/__DECC_INCLUDE_PROLOGUE.H
new file mode 100644
index 000000000000..8e95fa975488
--- /dev/null
+++ b/providers/common/include/prov/__DECC_INCLUDE_PROLOGUE.H
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This file is only used by HP C/C++ on VMS, and is included automatically
+ * after each header file from this directory
+ */
+
+/*
+ * The C++ compiler doesn't understand these pragmas, even though it
+ * understands the corresponding command line qualifier.
+ */
+#ifndef __cplusplus
+/* save state */
+# pragma names save
+/* have the compiler shorten symbols larger than 31 chars to 23 chars
+ * followed by a 8 hex char CRC
+ */
+# pragma names as_is,shortened
+#endif
diff --git a/providers/common/include/prov/bio.h b/providers/common/include/prov/bio.h
new file mode 100644
index 000000000000..da7e7e87f593
--- /dev/null
+++ b/providers/common/include/prov/bio.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdarg.h>
+#include <openssl/bio.h>
+#include <openssl/core.h>
+#include "prov/provider_ctx.h"
+
+int ossl_prov_bio_from_dispatch(const OSSL_DISPATCH *fns);
+
+OSSL_CORE_BIO *ossl_prov_bio_new_file(const char *filename, const char *mode);
+OSSL_CORE_BIO *ossl_prov_bio_new_membuf(const char *filename, int len);
+int ossl_prov_bio_read_ex(OSSL_CORE_BIO *bio, void *data, size_t data_len,
+ size_t *bytes_read);
+int ossl_prov_bio_write_ex(OSSL_CORE_BIO *bio, const void *data, size_t data_len,
+ size_t *written);
+int ossl_prov_bio_gets(OSSL_CORE_BIO *bio, char *buf, int size);
+int ossl_prov_bio_puts(OSSL_CORE_BIO *bio, const char *str);
+int ossl_prov_bio_ctrl(OSSL_CORE_BIO *bio, int cmd, long num, void *ptr);
+int ossl_prov_bio_up_ref(OSSL_CORE_BIO *bio);
+int ossl_prov_bio_free(OSSL_CORE_BIO *bio);
+int ossl_prov_bio_vprintf(OSSL_CORE_BIO *bio, const char *format, va_list ap);
+int ossl_prov_bio_printf(OSSL_CORE_BIO *bio, const char *format, ...);
+
+BIO_METHOD *ossl_bio_prov_init_bio_method(void);
+BIO *ossl_bio_new_from_core_bio(PROV_CTX *provctx, OSSL_CORE_BIO *corebio);
diff --git a/providers/common/include/prov/der_digests.h.in b/providers/common/include/prov/der_digests.h.in
new file mode 100644
index 000000000000..f8f89973398b
--- /dev/null
+++ b/providers/common/include/prov/der_digests.h.in
@@ -0,0 +1,20 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/der.h"
+
+/* Well known OIDs precompiled */
+{-
+ $OUT = oids_to_c::process_leaves('providers/common/der/NIST.asn1',
+ 'providers/common/der/DIGESTS.asn1',
+ { dir => $config{sourcedir},
+ filter => \&oids_to_c::filter_to_H });
+-}
diff --git a/providers/common/include/prov/der_dsa.h.in b/providers/common/include/prov/der_dsa.h.in
new file mode 100644
index 000000000000..75e44a16f176
--- /dev/null
+++ b/providers/common/include/prov/der_dsa.h.in
@@ -0,0 +1,25 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/der.h"
+
+/* Well known OIDs precompiled */
+{-
+ $OUT = oids_to_c::process_leaves('providers/common/der/DSA.asn1',
+ { dir => $config{sourcedir},
+ filter => \&oids_to_c::filter_to_H });
+-}
+
+/* Subject Public Key Info */
+int ossl_DER_w_algorithmIdentifier_DSA(WPACKET *pkt, int tag, DSA *dsa);
+/* Signature */
+int ossl_DER_w_algorithmIdentifier_DSA_with_MD(WPACKET *pkt, int tag,
+ DSA *dsa, int mdnid);
diff --git a/providers/common/include/prov/der_ec.h.in b/providers/common/include/prov/der_ec.h.in
new file mode 100644
index 000000000000..ebc9bb0310e8
--- /dev/null
+++ b/providers/common/include/prov/der_ec.h.in
@@ -0,0 +1,26 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "crypto/ec.h"
+#include "internal/der.h"
+
+/* Well known OIDs precompiled */
+{-
+ $OUT = oids_to_c::process_leaves('providers/common/der/EC.asn1',
+ { dir => $config{sourcedir},
+ filter => \&oids_to_c::filter_to_H });
+-}
+
+/* Subject Public Key Info */
+int ossl_DER_w_algorithmIdentifier_EC(WPACKET *pkt, int cont, EC_KEY *ec);
+/* Signature */
+int ossl_DER_w_algorithmIdentifier_ECDSA_with_MD(WPACKET *pkt, int cont,
+ EC_KEY *ec, int mdnid);
diff --git a/providers/common/include/prov/der_ecx.h.in b/providers/common/include/prov/der_ecx.h.in
new file mode 100644
index 000000000000..2ca86fb1dd7d
--- /dev/null
+++ b/providers/common/include/prov/der_ecx.h.in
@@ -0,0 +1,25 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/der.h"
+#include "crypto/ecx.h"
+
+/* Well known OIDs precompiled */
+{-
+ $OUT = oids_to_c::process_leaves('providers/common/der/ECX.asn1',
+ { dir => $config{sourcedir},
+ filter => \&oids_to_c::filter_to_H });
+-}
+
+int ossl_DER_w_algorithmIdentifier_ED25519(WPACKET *pkt, int cont, ECX_KEY *ec);
+int ossl_DER_w_algorithmIdentifier_ED448(WPACKET *pkt, int cont, ECX_KEY *ec);
+int ossl_DER_w_algorithmIdentifier_X25519(WPACKET *pkt, int cont, ECX_KEY *ec);
+int ossl_DER_w_algorithmIdentifier_X448(WPACKET *pkt, int cont, ECX_KEY *ec);
diff --git a/providers/common/include/prov/der_rsa.h.in b/providers/common/include/prov/der_rsa.h.in
new file mode 100644
index 000000000000..97e5377358cc
--- /dev/null
+++ b/providers/common/include/prov/der_rsa.h.in
@@ -0,0 +1,33 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "crypto/rsa.h"
+#include "internal/der.h"
+
+/* Well known OIDs precompiled */
+{-
+ $OUT = oids_to_c::process_leaves('providers/common/der/NIST.asn1',
+ 'providers/common/der/RSA.asn1',
+ { dir => $config{sourcedir},
+ filter => \&oids_to_c::filter_to_H });
+-}
+
+/* PSS parameters */
+int ossl_DER_w_RSASSA_PSS_params(WPACKET *pkt, int tag,
+ const RSA_PSS_PARAMS_30 *pss);
+/* Subject Public Key Info */
+int ossl_DER_w_algorithmIdentifier_RSA(WPACKET *pkt, int tag, RSA *rsa);
+int ossl_DER_w_algorithmIdentifier_RSA_PSS(WPACKET *pkt, int tag,
+ int rsa_type,
+ const RSA_PSS_PARAMS_30 *pss);
+/* Signature */
+int ossl_DER_w_algorithmIdentifier_MDWithRSAEncryption(WPACKET *pkt, int tag,
+ int mdnid);
diff --git a/providers/common/include/prov/der_sm2.h.in b/providers/common/include/prov/der_sm2.h.in
new file mode 100644
index 000000000000..f4f2bd72ee90
--- /dev/null
+++ b/providers/common/include/prov/der_sm2.h.in
@@ -0,0 +1,26 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "crypto/ec.h"
+#include "internal/der.h"
+
+/* Well known OIDs precompiled */
+{-
+ $OUT = oids_to_c::process_leaves('providers/common/der/SM2.asn1',
+ { dir => $config{sourcedir},
+ filter => \&oids_to_c::filter_to_H });
+-}
+
+/* Subject Public Key Info */
+int ossl_DER_w_algorithmIdentifier_SM2(WPACKET *pkt, int cont, EC_KEY *ec);
+/* Signature */
+int ossl_DER_w_algorithmIdentifier_SM2_with_MD(WPACKET *pkt, int cont,
+ EC_KEY *ec, int mdnid);
diff --git a/providers/common/include/prov/der_wrap.h.in b/providers/common/include/prov/der_wrap.h.in
new file mode 100644
index 000000000000..a20f3d45ec87
--- /dev/null
+++ b/providers/common/include/prov/der_wrap.h.in
@@ -0,0 +1,19 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/der.h"
+
+/* Well known OIDs precompiled */
+{-
+ $OUT = oids_to_c::process_leaves('providers/common/der/wrap.asn1',
+ { dir => $config{sourcedir},
+ filter => \&oids_to_c::filter_to_H });
+-}
diff --git a/providers/common/include/prov/proverr.h b/providers/common/include/prov/proverr.h
new file mode 100644
index 000000000000..5084af201e05
--- /dev/null
+++ b/providers/common/include/prov/proverr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_PROVERR_H
+# define OSSL_PROVERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_PROV_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/providers/common/include/prov/provider_ctx.h b/providers/common/include/prov/provider_ctx.h
new file mode 100644
index 000000000000..c8126e176161
--- /dev/null
+++ b/providers/common/include/prov/provider_ctx.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_PROV_PROVIDER_CTX_H
+# define OSSL_PROV_PROVIDER_CTX_H
+
+# include <openssl/types.h>
+# include <openssl/crypto.h>
+# include <openssl/bio.h>
+# include <openssl/core.h>
+
+typedef struct prov_ctx_st {
+ const OSSL_CORE_HANDLE *handle;
+ OSSL_LIB_CTX *libctx; /* For all provider modules */
+ BIO_METHOD *corebiometh;
+} PROV_CTX;
+
+/*
+ * To be used anywhere the library context needs to be passed, such as to
+ * fetching functions.
+ */
+# define PROV_LIBCTX_OF(provctx) \
+ ossl_prov_ctx_get0_libctx((provctx))
+
+PROV_CTX *ossl_prov_ctx_new(void);
+void ossl_prov_ctx_free(PROV_CTX *ctx);
+void ossl_prov_ctx_set0_libctx(PROV_CTX *ctx, OSSL_LIB_CTX *libctx);
+void ossl_prov_ctx_set0_handle(PROV_CTX *ctx, const OSSL_CORE_HANDLE *handle);
+void ossl_prov_ctx_set0_core_bio_method(PROV_CTX *ctx, BIO_METHOD *corebiometh);
+OSSL_LIB_CTX *ossl_prov_ctx_get0_libctx(PROV_CTX *ctx);
+const OSSL_CORE_HANDLE *ossl_prov_ctx_get0_handle(PROV_CTX *ctx);
+BIO_METHOD *ossl_prov_ctx_get0_core_bio_method(PROV_CTX *ctx);
+
+#endif
diff --git a/providers/common/include/prov/provider_util.h b/providers/common/include/prov/provider_util.h
new file mode 100644
index 000000000000..dfe91f29bcdb
--- /dev/null
+++ b/providers/common/include/prov/provider_util.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/provider.h>
+#include <openssl/types.h>
+
+typedef struct {
+ /*
+ * References to the underlying cipher implementation. |cipher| caches
+ * the cipher, always. |alloc_cipher| only holds a reference to an
+ * explicitly fetched cipher.
+ */
+ const EVP_CIPHER *cipher; /* cipher */
+ EVP_CIPHER *alloc_cipher; /* fetched cipher */
+
+ /* Conditions for legacy EVP_CIPHER uses */
+ ENGINE *engine; /* cipher engine */
+} PROV_CIPHER;
+
+typedef struct {
+ /*
+ * References to the underlying digest implementation. |md| caches
+ * the digest, always. |alloc_md| only holds a reference to an explicitly
+ * fetched digest.
+ */
+ const EVP_MD *md; /* digest */
+ EVP_MD *alloc_md; /* fetched digest */
+
+ /* Conditions for legacy EVP_MD uses */
+ ENGINE *engine; /* digest engine */
+} PROV_DIGEST;
+
+/* Cipher functions */
+/*
+ * Load a cipher from the specified parameters with the specified context.
+ * The params "properties", "engine" and "cipher" are used to determine the
+ * implementation used. If a provider cannot be found, it falls back to trying
+ * non-provider based implementations.
+ */
+int ossl_prov_cipher_load_from_params(PROV_CIPHER *pc,
+ const OSSL_PARAM params[],
+ OSSL_LIB_CTX *ctx);
+
+/* Reset the PROV_CIPHER fields and free any allocated cipher reference */
+void ossl_prov_cipher_reset(PROV_CIPHER *pc);
+
+/* Clone a PROV_CIPHER structure into a second */
+int ossl_prov_cipher_copy(PROV_CIPHER *dst, const PROV_CIPHER *src);
+
+/* Query the cipher and associated engine (if any) */
+const EVP_CIPHER *ossl_prov_cipher_cipher(const PROV_CIPHER *pc);
+ENGINE *ossl_prov_cipher_engine(const PROV_CIPHER *pc);
+
+/* Digest functions */
+
+/*
+ * Fetch a digest from the specified libctx using the provided mdname and
+ * propquery. Store the result in the PROV_DIGEST and return the fetched md.
+ */
+const EVP_MD *ossl_prov_digest_fetch(PROV_DIGEST *pd, OSSL_LIB_CTX *libctx,
+ const char *mdname, const char *propquery);
+
+/*
+ * Load a digest from the specified parameters with the specified context.
+ * The params "properties", "engine" and "digest" are used to determine the
+ * implementation used. If a provider cannot be found, it falls back to trying
+ * non-provider based implementations.
+ */
+int ossl_prov_digest_load_from_params(PROV_DIGEST *pd,
+ const OSSL_PARAM params[],
+ OSSL_LIB_CTX *ctx);
+
+/* Reset the PROV_DIGEST fields and free any allocated digest reference */
+void ossl_prov_digest_reset(PROV_DIGEST *pd);
+
+/* Clone a PROV_DIGEST structure into a second */
+int ossl_prov_digest_copy(PROV_DIGEST *dst, const PROV_DIGEST *src);
+
+/* Query the digest and associated engine (if any) */
+const EVP_MD *ossl_prov_digest_md(const PROV_DIGEST *pd);
+ENGINE *ossl_prov_digest_engine(const PROV_DIGEST *pd);
+
+
+/*
+ * Set the various parameters on an EVP_MAC_CTX from the supplied arguments.
+ * If any of the supplied ciphername/mdname etc are NULL then the values
+ * from the supplied params (if non NULL) are used instead.
+ */
+int ossl_prov_set_macctx(EVP_MAC_CTX *macctx,
+ const OSSL_PARAM params[],
+ const char *ciphername,
+ const char *mdname,
+ const char *engine,
+ const char *properties,
+ const unsigned char *key,
+ size_t keylen);
+
+/* MAC functions */
+/*
+ * Load an EVP_MAC_CTX* from the specified parameters with the specified
+ * library context.
+ * The params "mac" and "properties" are used to determine the implementation
+ * used, and the parameters "digest", "cipher", "engine" and "properties" are
+ * passed to the MAC via the created MAC context if they are given.
+ * If there is already a created MAC context, it will be replaced if the "mac"
+ * parameter is found, otherwise it will simply be used as is, and passed the
+ * parameters to pilfer as it sees fit.
+ *
+ * As an option, a MAC name may be explicitly given, and if it is, the "mac"
+ * parameter will be ignored.
+ * Similarly, as an option, a cipher name or a digest name may be explicitly
+ * given, and if any of them is, the "digest" and "cipher" parameters are
+ * ignored.
+ */
+int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx,
+ const OSSL_PARAM params[],
+ const char *macname,
+ const char *ciphername,
+ const char *mdname,
+ OSSL_LIB_CTX *ctx);
+
+typedef struct ag_capable_st {
+ OSSL_ALGORITHM alg;
+ int (*capable)(void);
+} OSSL_ALGORITHM_CAPABLE;
+
+/*
+ * Dynamically select algorithms by calling a capable() method.
+ * If this method is NULL or the method returns 1 then the algorithm is added.
+ */
+void ossl_prov_cache_exported_algorithms(const OSSL_ALGORITHM_CAPABLE *in,
+ OSSL_ALGORITHM *out);
diff --git a/providers/common/include/prov/providercommon.h b/providers/common/include/prov/providercommon.h
new file mode 100644
index 000000000000..6366547e7cfb
--- /dev/null
+++ b/providers/common/include/prov/providercommon.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/provider.h>
+#include <openssl/core_dispatch.h>
+
+const OSSL_CORE_HANDLE *FIPS_get_core_handle(OSSL_LIB_CTX *ctx);
+
+int ossl_cipher_capable_aes_cbc_hmac_sha1(void);
+int ossl_cipher_capable_aes_cbc_hmac_sha256(void);
+
+OSSL_FUNC_provider_get_capabilities_fn ossl_prov_get_capabilities;
+
+/* Set the error state if this is a FIPS module */
+void ossl_set_error_state(const char *type);
+
+/* Return true if the module is in a usable condition */
+int ossl_prov_is_running(void);
diff --git a/providers/common/include/prov/securitycheck.h b/providers/common/include/prov/securitycheck.h
new file mode 100644
index 000000000000..4a7f85f71186
--- /dev/null
+++ b/providers/common/include/prov/securitycheck.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "crypto/types.h"
+
+/* Functions that are common */
+int ossl_rsa_check_key(OSSL_LIB_CTX *ctx, const RSA *rsa, int operation);
+int ossl_ec_check_key(OSSL_LIB_CTX *ctx, const EC_KEY *ec, int protect);
+int ossl_dsa_check_key(OSSL_LIB_CTX *ctx, const DSA *dsa, int sign);
+int ossl_dh_check_key(OSSL_LIB_CTX *ctx, const DH *dh);
+
+int ossl_digest_is_allowed(OSSL_LIB_CTX *ctx, const EVP_MD *md);
+/* With security check enabled it can return -1 to indicate disallowed md */
+int ossl_digest_get_approved_nid_with_sha1(OSSL_LIB_CTX *ctx, const EVP_MD *md,
+ int sha1_allowed);
+
+/* Functions that are common */
+int ossl_digest_md_to_nid(const EVP_MD *md, const OSSL_ITEM *it, size_t it_len);
+int ossl_digest_get_approved_nid(const EVP_MD *md);
+
+/* Functions that have different implementations for the FIPS_MODULE */
+int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md,
+ int sha1_allowed);
+int ossl_securitycheck_enabled(OSSL_LIB_CTX *libctx);
diff --git a/providers/common/provider_ctx.c b/providers/common/provider_ctx.c
new file mode 100644
index 000000000000..9690abfd5776
--- /dev/null
+++ b/providers/common/provider_ctx.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include "prov/provider_ctx.h"
+#include "prov/bio.h"
+
+PROV_CTX *ossl_prov_ctx_new(void)
+{
+ return OPENSSL_zalloc(sizeof(PROV_CTX));
+}
+
+void ossl_prov_ctx_free(PROV_CTX *ctx)
+{
+ OPENSSL_free(ctx);
+}
+
+void ossl_prov_ctx_set0_libctx(PROV_CTX *ctx, OSSL_LIB_CTX *libctx)
+{
+ if (ctx != NULL)
+ ctx->libctx = libctx;
+}
+
+void ossl_prov_ctx_set0_handle(PROV_CTX *ctx, const OSSL_CORE_HANDLE *handle)
+{
+ if (ctx != NULL)
+ ctx->handle = handle;
+}
+
+void ossl_prov_ctx_set0_core_bio_method(PROV_CTX *ctx, BIO_METHOD *corebiometh)
+{
+ if (ctx != NULL)
+ ctx->corebiometh = corebiometh;
+}
+
+OSSL_LIB_CTX *ossl_prov_ctx_get0_libctx(PROV_CTX *ctx)
+{
+ if (ctx == NULL)
+ return NULL;
+ return ctx->libctx;
+}
+
+const OSSL_CORE_HANDLE *ossl_prov_ctx_get0_handle(PROV_CTX *ctx)
+{
+ if (ctx == NULL)
+ return NULL;
+ return ctx->handle;
+}
+
+BIO_METHOD *ossl_prov_ctx_get0_core_bio_method(PROV_CTX *ctx)
+{
+ if (ctx == NULL)
+ return NULL;
+ return ctx->corebiometh;
+}
diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c
new file mode 100644
index 000000000000..344c12211266
--- /dev/null
+++ b/providers/common/provider_err.c
@@ -0,0 +1,229 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include "include/prov/proverr.h"
+
+#ifndef OPENSSL_NO_ERR
+
+static const ERR_STRING_DATA PROV_str_reasons[] = {
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ADDITIONAL_INPUT_TOO_LONG),
+ "additional input too long"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ALGORITHM_MISMATCH),
+ "algorithm mismatch"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ALREADY_INSTANTIATED),
+ "already instantiated"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_DECRYPT), "bad decrypt"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_ENCODING), "bad encoding"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_LENGTH), "bad length"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_TLS_CLIENT_VERSION),
+ "bad tls client version"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BN_ERROR), "bn error"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_CIPHER_OPERATION_FAILED),
+ "cipher operation failed"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_DERIVATION_FUNCTION_INIT_FAILED),
+ "derivation function init failed"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_DIGEST_NOT_ALLOWED),
+ "digest not allowed"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK),
+ "entropy source strength too weak"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ERROR_INSTANTIATING_DRBG),
+ "error instantiating drbg"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ERROR_RETRIEVING_ENTROPY),
+ "error retrieving entropy"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ERROR_RETRIEVING_NONCE),
+ "error retrieving nonce"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_DURING_DERIVATION),
+ "failed during derivation"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_CREATE_LOCK),
+ "failed to create lock"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_DECRYPT), "failed to decrypt"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_GENERATE_KEY),
+ "failed to generate key"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_GET_PARAMETER),
+ "failed to get parameter"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_SET_PARAMETER),
+ "failed to set parameter"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_SIGN), "failed to sign"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FIPS_MODULE_CONDITIONAL_ERROR),
+ "fips module conditional error"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE),
+ "fips module entering error state"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FIPS_MODULE_IN_ERROR_STATE),
+ "fips module in error state"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_GENERATE_ERROR), "generate error"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE),
+ "illegal or unsupported padding mode"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INDICATOR_INTEGRITY_FAILURE),
+ "indicator integrity failure"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INSUFFICIENT_DRBG_STRENGTH),
+ "insufficient drbg strength"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_AAD), "invalid aad"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_CONFIG_DATA),
+ "invalid config data"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_CONSTANT_LENGTH),
+ "invalid constant length"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_CURVE), "invalid curve"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_CUSTOM_LENGTH),
+ "invalid custom length"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DATA), "invalid data"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST), "invalid digest"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST_LENGTH),
+ "invalid digest length"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST_SIZE),
+ "invalid digest size"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_INPUT_LENGTH),
+ "invalid input length"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_ITERATION_COUNT),
+ "invalid iteration count"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_IV_LENGTH), "invalid iv length"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEY), "invalid key"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEY_LENGTH),
+ "invalid key length"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MAC), "invalid mac"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MGF1_MD), "invalid mgf1 md"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MODE), "invalid mode"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_OUTPUT_LENGTH),
+ "invalid output length"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_PADDING_MODE),
+ "invalid padding mode"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_PUBINFO), "invalid pubinfo"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_SALT_LENGTH),
+ "invalid salt length"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_SEED_LENGTH),
+ "invalid seed length"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_SIGNATURE_SIZE),
+ "invalid signature size"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_STATE), "invalid state"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_TAG), "invalid tag"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_TAG_LENGTH),
+ "invalid tag length"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_UKM_LENGTH),
+ "invalid ukm length"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_X931_DIGEST),
+ "invalid x931 digest"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_IN_ERROR_STATE), "in error state"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_KEY_SETUP_FAILED), "key setup failed"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_KEY_SIZE_TOO_SMALL),
+ "key size too small"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_LENGTH_TOO_LARGE), "length too large"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISMATCHING_DOMAIN_PARAMETERS),
+ "mismatching domain parameters"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CEK_ALG), "missing cek alg"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CIPHER), "missing cipher"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CONFIG_DATA),
+ "missing config data"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CONSTANT), "missing constant"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_KEY), "missing key"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_MAC), "missing mac"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_MESSAGE_DIGEST),
+ "missing message digest"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_OID), "missing OID"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_PASS), "missing pass"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_SALT), "missing salt"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_SECRET), "missing secret"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_SEED), "missing seed"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_SESSION_ID),
+ "missing session id"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_TYPE), "missing type"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_XCGHASH), "missing xcghash"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MODULE_INTEGRITY_FAILURE),
+ "module integrity failure"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NOT_A_PRIVATE_KEY), "not a private key"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NOT_A_PUBLIC_KEY), "not a public key"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NOT_INSTANTIATED), "not instantiated"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NOT_PARAMETERS), "not parameters"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NOT_SUPPORTED), "not supported"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NOT_XOF_OR_INVALID_LENGTH),
+ "not xof or invalid length"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NO_KEY_SET), "no key set"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NO_PARAMETERS_SET), "no parameters set"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE),
+ "operation not supported for this keytype"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_OUTPUT_BUFFER_TOO_SMALL),
+ "output buffer too small"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PARENT_CANNOT_GENERATE_RANDOM_NUMBERS),
+ "parent cannot generate random numbers"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED),
+ "parent cannot supply entropy seed"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PARENT_LOCKING_NOT_ENABLED),
+ "parent locking not enabled"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PARENT_STRENGTH_TOO_WEAK),
+ "parent strength too weak"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PATH_MUST_BE_ABSOLUTE),
+ "path must be absolute"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PERSONALISATION_STRING_TOO_LONG),
+ "personalisation string too long"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PSS_SALTLEN_TOO_SMALL),
+ "pss saltlen too small"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_REQUEST_TOO_LARGE_FOR_DRBG),
+ "request too large for drbg"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_REQUIRE_CTR_MODE_CIPHER),
+ "require ctr mode cipher"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_RESEED_ERROR), "reseed error"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES),
+ "search only supported for directories"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT),
+ "seed sources must not have a parent"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_SELF_TEST_KAT_FAILURE),
+ "self test kat failure"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_SELF_TEST_POST_FAILURE),
+ "self test post failure"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TAG_NOT_NEEDED), "tag not needed"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TAG_NOT_SET), "tag not set"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TOO_MANY_RECORDS), "too many records"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNABLE_TO_FIND_CIPHERS),
+ "unable to find ciphers"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNABLE_TO_GET_PARENT_STRENGTH),
+ "unable to get parent strength"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNABLE_TO_GET_PASSPHRASE),
+ "unable to get passphrase"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNABLE_TO_INITIALISE_CIPHERS),
+ "unable to initialise ciphers"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNABLE_TO_LOAD_SHA256),
+ "unable to load sha256"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNABLE_TO_LOCK_PARENT),
+ "unable to lock parent"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNABLE_TO_RESEED), "unable to reseed"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNSUPPORTED_CEK_ALG),
+ "unsupported cek alg"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNSUPPORTED_KEY_SIZE),
+ "unsupported key size"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNSUPPORTED_MAC_TYPE),
+ "unsupported mac type"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS),
+ "unsupported number of rounds"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_URI_AUTHORITY_UNSUPPORTED),
+ "uri authority unsupported"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_VALUE_ERROR), "value error"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_WRONG_FINAL_BLOCK_LENGTH),
+ "wrong final block length"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_WRONG_OUTPUT_BUFFER_SIZE),
+ "wrong output buffer size"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_XOF_DIGESTS_NOT_ALLOWED),
+ "xof digests not allowed"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE),
+ "xts data unit is too large"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_XTS_DUPLICATED_KEYS),
+ "xts duplicated keys"},
+ {0, NULL}
+};
+
+#endif
+
+int ossl_err_load_PROV_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+ if (ERR_reason_error_string(PROV_str_reasons[0].error) == NULL)
+ ERR_load_strings_const(PROV_str_reasons);
+#endif
+ return 1;
+}
diff --git a/providers/common/provider_seeding.c b/providers/common/provider_seeding.c
new file mode 100644
index 000000000000..0edbb8763066
--- /dev/null
+++ b/providers/common/provider_seeding.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_dispatch.h>
+#include "prov/seeding.h"
+
+static OSSL_FUNC_get_entropy_fn *c_get_entropy = NULL;
+static OSSL_FUNC_cleanup_entropy_fn *c_cleanup_entropy = NULL;
+static OSSL_FUNC_get_nonce_fn *c_get_nonce = NULL;
+static OSSL_FUNC_cleanup_nonce_fn *c_cleanup_nonce = NULL;
+
+int ossl_prov_seeding_from_dispatch(const OSSL_DISPATCH *fns)
+{
+ for (; fns->function_id != 0; fns++) {
+ /*
+ * We do not support the scenario of an application linked against
+ * multiple versions of libcrypto (e.g. one static and one dynamic), but
+ * sharing a single fips.so. We do a simple sanity check here.
+ */
+#define set_func(c, f) \
+ do { if (c == NULL) c = f; else if (c != f) return 0; } while (0)
+ switch (fns->function_id) {
+ case OSSL_FUNC_GET_ENTROPY:
+ set_func(c_get_entropy, OSSL_FUNC_get_entropy(fns));
+ break;
+ case OSSL_FUNC_CLEANUP_ENTROPY:
+ set_func(c_cleanup_entropy, OSSL_FUNC_cleanup_entropy(fns));
+ break;
+ case OSSL_FUNC_GET_NONCE:
+ set_func(c_get_nonce, OSSL_FUNC_get_nonce(fns));
+ break;
+ case OSSL_FUNC_CLEANUP_NONCE:
+ set_func(c_cleanup_nonce, OSSL_FUNC_cleanup_nonce(fns));
+ break;
+ }
+#undef set_func
+ }
+ return 1;
+}
+
+size_t ossl_prov_get_entropy(PROV_CTX *prov_ctx, unsigned char **pout,
+ int entropy, size_t min_len, size_t max_len)
+{
+ if (c_get_entropy == NULL)
+ return 0;
+ return c_get_entropy(ossl_prov_ctx_get0_handle(prov_ctx),
+ pout, entropy, min_len, max_len);
+}
+
+void ossl_prov_cleanup_entropy(PROV_CTX *prov_ctx, unsigned char *buf,
+ size_t len)
+{
+ if (c_cleanup_entropy != NULL)
+ c_cleanup_entropy(ossl_prov_ctx_get0_handle(prov_ctx), buf, len);
+}
+
+size_t ossl_prov_get_nonce(PROV_CTX *prov_ctx, unsigned char **pout,
+ size_t min_len, size_t max_len,
+ const void *salt,size_t salt_len)
+{
+ if (c_get_nonce == NULL)
+ return 0;
+ return c_get_nonce(ossl_prov_ctx_get0_handle(prov_ctx), pout,
+ min_len, max_len, salt, salt_len);
+}
+
+void ossl_prov_cleanup_nonce(PROV_CTX *prov_ctx, unsigned char *buf, size_t len)
+{
+ if (c_cleanup_nonce != NULL)
+ c_cleanup_nonce(ossl_prov_ctx_get0_handle(prov_ctx), buf, len);
+}
diff --git a/providers/common/provider_util.c b/providers/common/provider_util.c
new file mode 100644
index 000000000000..58d4db33793f
--- /dev/null
+++ b/providers/common/provider_util.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include <openssl/evp.h>
+#include <openssl/core_names.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#ifndef FIPS_MODULE
+# include <openssl/engine.h>
+# include "crypto/evp.h"
+#endif
+#include "prov/provider_util.h"
+#include "internal/nelem.h"
+
+void ossl_prov_cipher_reset(PROV_CIPHER *pc)
+{
+ EVP_CIPHER_free(pc->alloc_cipher);
+ pc->alloc_cipher = NULL;
+ pc->cipher = NULL;
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
+ ENGINE_finish(pc->engine);
+#endif
+ pc->engine = NULL;
+}
+
+int ossl_prov_cipher_copy(PROV_CIPHER *dst, const PROV_CIPHER *src)
+{
+ if (src->alloc_cipher != NULL && !EVP_CIPHER_up_ref(src->alloc_cipher))
+ return 0;
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
+ if (src->engine != NULL && !ENGINE_init(src->engine)) {
+ EVP_CIPHER_free(src->alloc_cipher);
+ return 0;
+ }
+#endif
+ dst->engine = src->engine;
+ dst->cipher = src->cipher;
+ dst->alloc_cipher = src->alloc_cipher;
+ return 1;
+}
+
+static int load_common(const OSSL_PARAM params[], const char **propquery,
+ ENGINE **engine)
+{
+ const OSSL_PARAM *p;
+
+ *propquery = NULL;
+ p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_PROPERTIES);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+ *propquery = p->data;
+ }
+
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
+ ENGINE_finish(*engine);
+#endif
+ *engine = NULL;
+ /* Inside the FIPS module, we don't support legacy ciphers */
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
+ p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_ENGINE);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+ /* Get a structural reference */
+ *engine = ENGINE_by_id(p->data);
+ if (*engine == NULL)
+ return 0;
+ /* Get a functional reference */
+ if (!ENGINE_init(*engine)) {
+ ENGINE_free(*engine);
+ *engine = NULL;
+ return 0;
+ }
+ /* Free the structural reference */
+ ENGINE_free(*engine);
+ }
+#endif
+ return 1;
+}
+
+int ossl_prov_cipher_load_from_params(PROV_CIPHER *pc,
+ const OSSL_PARAM params[],
+ OSSL_LIB_CTX *ctx)
+{
+ const OSSL_PARAM *p;
+ const char *propquery;
+
+ if (params == NULL)
+ return 1;
+
+ if (!load_common(params, &propquery, &pc->engine))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_CIPHER);
+ if (p == NULL)
+ return 1;
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+
+ EVP_CIPHER_free(pc->alloc_cipher);
+ ERR_set_mark();
+ pc->cipher = pc->alloc_cipher = EVP_CIPHER_fetch(ctx, p->data, propquery);
+#ifndef FIPS_MODULE /* Inside the FIPS module, we don't support legacy ciphers */
+ if (pc->cipher == NULL) {
+ const EVP_CIPHER *cipher;
+
+ cipher = EVP_get_cipherbyname(p->data);
+ /* Do not use global EVP_CIPHERs */
+ if (cipher != NULL && cipher->origin != EVP_ORIG_GLOBAL)
+ pc->cipher = cipher;
+ }
+#endif
+ if (pc->cipher != NULL)
+ ERR_pop_to_mark();
+ else
+ ERR_clear_last_mark();
+ return pc->cipher != NULL;
+}
+
+const EVP_CIPHER *ossl_prov_cipher_cipher(const PROV_CIPHER *pc)
+{
+ return pc->cipher;
+}
+
+ENGINE *ossl_prov_cipher_engine(const PROV_CIPHER *pc)
+{
+ return pc->engine;
+}
+
+void ossl_prov_digest_reset(PROV_DIGEST *pd)
+{
+ EVP_MD_free(pd->alloc_md);
+ pd->alloc_md = NULL;
+ pd->md = NULL;
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
+ ENGINE_finish(pd->engine);
+#endif
+ pd->engine = NULL;
+}
+
+int ossl_prov_digest_copy(PROV_DIGEST *dst, const PROV_DIGEST *src)
+{
+ if (src->alloc_md != NULL && !EVP_MD_up_ref(src->alloc_md))
+ return 0;
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
+ if (src->engine != NULL && !ENGINE_init(src->engine)) {
+ EVP_MD_free(src->alloc_md);
+ return 0;
+ }
+#endif
+ dst->engine = src->engine;
+ dst->md = src->md;
+ dst->alloc_md = src->alloc_md;
+ return 1;
+}
+
+const EVP_MD *ossl_prov_digest_fetch(PROV_DIGEST *pd, OSSL_LIB_CTX *libctx,
+ const char *mdname, const char *propquery)
+{
+ EVP_MD_free(pd->alloc_md);
+ pd->md = pd->alloc_md = EVP_MD_fetch(libctx, mdname, propquery);
+
+ return pd->md;
+}
+
+int ossl_prov_digest_load_from_params(PROV_DIGEST *pd,
+ const OSSL_PARAM params[],
+ OSSL_LIB_CTX *ctx)
+{
+ const OSSL_PARAM *p;
+ const char *propquery;
+
+ if (params == NULL)
+ return 1;
+
+ if (!load_common(params, &propquery, &pd->engine))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST);
+ if (p == NULL)
+ return 1;
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+
+ ERR_set_mark();
+ ossl_prov_digest_fetch(pd, ctx, p->data, propquery);
+#ifndef FIPS_MODULE /* Inside the FIPS module, we don't support legacy digests */
+ if (pd->md == NULL) {
+ const EVP_MD *md;
+
+ md = EVP_get_digestbyname(p->data);
+ /* Do not use global EVP_MDs */
+ if (md != NULL && md->origin != EVP_ORIG_GLOBAL)
+ pd->md = md;
+ }
+#endif
+ if (pd->md != NULL)
+ ERR_pop_to_mark();
+ else
+ ERR_clear_last_mark();
+ return pd->md != NULL;
+}
+
+const EVP_MD *ossl_prov_digest_md(const PROV_DIGEST *pd)
+{
+ return pd->md;
+}
+
+ENGINE *ossl_prov_digest_engine(const PROV_DIGEST *pd)
+{
+ return pd->engine;
+}
+
+int ossl_prov_set_macctx(EVP_MAC_CTX *macctx,
+ const OSSL_PARAM params[],
+ const char *ciphername,
+ const char *mdname,
+ const char *engine,
+ const char *properties,
+ const unsigned char *key,
+ size_t keylen)
+{
+ const OSSL_PARAM *p;
+ OSSL_PARAM mac_params[6], *mp = mac_params;
+
+ if (params != NULL) {
+ if (mdname == NULL) {
+ if ((p = OSSL_PARAM_locate_const(params,
+ OSSL_ALG_PARAM_DIGEST)) != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+ mdname = p->data;
+ }
+ }
+ if (ciphername == NULL) {
+ if ((p = OSSL_PARAM_locate_const(params,
+ OSSL_ALG_PARAM_CIPHER)) != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+ ciphername = p->data;
+ }
+ }
+ if (engine == NULL) {
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_ENGINE))
+ != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+ engine = p->data;
+ }
+ }
+ }
+
+ if (mdname != NULL)
+ *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
+ (char *)mdname, 0);
+ if (ciphername != NULL)
+ *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER,
+ (char *)ciphername, 0);
+ if (properties != NULL)
+ *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES,
+ (char *)properties, 0);
+
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
+ if (engine != NULL)
+ *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_ENGINE,
+ (char *) engine, 0);
+#endif
+
+ if (key != NULL)
+ *mp++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ (unsigned char *)key,
+ keylen);
+
+ *mp = OSSL_PARAM_construct_end();
+
+ return EVP_MAC_CTX_set_params(macctx, mac_params);
+
+}
+
+int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx,
+ const OSSL_PARAM params[],
+ const char *macname,
+ const char *ciphername,
+ const char *mdname,
+ OSSL_LIB_CTX *libctx)
+{
+ const OSSL_PARAM *p;
+ const char *properties = NULL;
+
+ if (macname == NULL
+ && (p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_MAC)) != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+ macname = p->data;
+ }
+ if ((p = OSSL_PARAM_locate_const(params,
+ OSSL_ALG_PARAM_PROPERTIES)) != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+ properties = p->data;
+ }
+
+ /* If we got a new mac name, we make a new EVP_MAC_CTX */
+ if (macname != NULL) {
+ EVP_MAC *mac = EVP_MAC_fetch(libctx, macname, properties);
+
+ EVP_MAC_CTX_free(*macctx);
+ *macctx = mac == NULL ? NULL : EVP_MAC_CTX_new(mac);
+ /* The context holds on to the MAC */
+ EVP_MAC_free(mac);
+ if (*macctx == NULL)
+ return 0;
+ }
+
+ /*
+ * If there is no MAC yet (and therefore, no MAC context), we ignore
+ * all other parameters.
+ */
+ if (*macctx == NULL)
+ return 1;
+
+ if (ossl_prov_set_macctx(*macctx, params, ciphername, mdname, NULL,
+ properties, NULL, 0))
+ return 1;
+
+ EVP_MAC_CTX_free(*macctx);
+ *macctx = NULL;
+ return 0;
+}
+
+void ossl_prov_cache_exported_algorithms(const OSSL_ALGORITHM_CAPABLE *in,
+ OSSL_ALGORITHM *out)
+{
+ int i, j;
+
+ if (out[0].algorithm_names == NULL) {
+ for (i = j = 0; in[i].alg.algorithm_names != NULL; ++i) {
+ if (in[i].capable == NULL || in[i].capable())
+ out[j++] = in[i].alg;
+ }
+ out[j++] = in[i].alg;
+ }
+}
diff --git a/providers/common/securitycheck.c b/providers/common/securitycheck.c
new file mode 100644
index 000000000000..699ada7c529f
--- /dev/null
+++ b/providers/common/securitycheck.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/deprecated.h"
+
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#include <openssl/dh.h>
+#include <openssl/ec.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include <openssl/core_names.h>
+#include <openssl/obj_mac.h>
+#include "prov/securitycheck.h"
+
+/*
+ * FIPS requires a minimum security strength of 112 bits (for encryption or
+ * signing), and for legacy purposes 80 bits (for decryption or verifying).
+ * Set protect = 1 for encryption or signing operations, or 0 otherwise. See
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf.
+ */
+int ossl_rsa_check_key(OSSL_LIB_CTX *ctx, const RSA *rsa, int operation)
+{
+ int protect = 0;
+
+ switch (operation) {
+ case EVP_PKEY_OP_SIGN:
+ protect = 1;
+ /* fallthrough */
+ case EVP_PKEY_OP_VERIFY:
+ break;
+ case EVP_PKEY_OP_ENCAPSULATE:
+ case EVP_PKEY_OP_ENCRYPT:
+ protect = 1;
+ /* fallthrough */
+ case EVP_PKEY_OP_VERIFYRECOVER:
+ case EVP_PKEY_OP_DECAPSULATE:
+ case EVP_PKEY_OP_DECRYPT:
+ if (RSA_test_flags(rsa,
+ RSA_FLAG_TYPE_MASK) == RSA_FLAG_TYPE_RSASSAPSS) {
+ ERR_raise_data(ERR_LIB_PROV,
+ PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE,
+ "operation: %d", operation);
+ return 0;
+ }
+ break;
+ default:
+ ERR_raise_data(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR,
+ "invalid operation: %d", operation);
+ return 0;
+ }
+
+#if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
+ if (ossl_securitycheck_enabled(ctx)) {
+ int sz = RSA_bits(rsa);
+
+ if (protect ? (sz < 2048) : (sz < 1024)) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH,
+ "operation: %d", operation);
+ return 0;
+ }
+ }
+#else
+ /* make protect used */
+ (void)protect;
+#endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
+ return 1;
+}
+
+#ifndef OPENSSL_NO_EC
+/*
+ * In FIPS mode:
+ * protect should be 1 for any operations that need 112 bits of security
+ * strength (such as signing, and key exchange), or 0 for operations that allow
+ * a lower security strength (such as verify).
+ *
+ * For ECDH key agreement refer to SP800-56A
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf
+ * "Appendix D"
+ *
+ * For ECDSA signatures refer to
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf
+ * "Table 2"
+ */
+int ossl_ec_check_key(OSSL_LIB_CTX *ctx, const EC_KEY *ec, int protect)
+{
+# if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
+ if (ossl_securitycheck_enabled(ctx)) {
+ int nid, strength;
+ const char *curve_name;
+ const EC_GROUP *group = EC_KEY_get0_group(ec);
+
+ if (group == NULL) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_CURVE, "No group");
+ return 0;
+ }
+ nid = EC_GROUP_get_curve_name(group);
+ if (nid == NID_undef) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_CURVE,
+ "Explicit curves are not allowed in fips mode");
+ return 0;
+ }
+
+ curve_name = EC_curve_nid2nist(nid);
+ if (curve_name == NULL) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_CURVE,
+ "Curve %s is not approved in FIPS mode", curve_name);
+ return 0;
+ }
+
+ /*
+ * For EC the security strength is the (order_bits / 2)
+ * e.g. P-224 is 112 bits.
+ */
+ strength = EC_GROUP_order_bits(group) / 2;
+ /* The min security strength allowed for legacy verification is 80 bits */
+ if (strength < 80) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE);
+ return 0;
+ }
+
+ /*
+ * For signing or key agreement only allow curves with at least 112 bits of
+ * security strength
+ */
+ if (protect && strength < 112) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_CURVE,
+ "Curve %s cannot be used for signing", curve_name);
+ return 0;
+ }
+ }
+# endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
+ return 1;
+}
+#endif /* OPENSSL_NO_EC */
+
+#ifndef OPENSSL_NO_DSA
+/*
+ * Check for valid key sizes if fips mode. Refer to
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf
+ * "Table 2"
+ */
+int ossl_dsa_check_key(OSSL_LIB_CTX *ctx, const DSA *dsa, int sign)
+{
+# if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
+ if (ossl_securitycheck_enabled(ctx)) {
+ size_t L, N;
+ const BIGNUM *p, *q;
+
+ if (dsa == NULL)
+ return 0;
+
+ p = DSA_get0_p(dsa);
+ q = DSA_get0_q(dsa);
+ if (p == NULL || q == NULL)
+ return 0;
+
+ L = BN_num_bits(p);
+ N = BN_num_bits(q);
+
+ /*
+ * For Digital signature verification DSA keys with < 112 bits of
+ * security strength (i.e L < 2048 bits), are still allowed for legacy
+ * use. The bounds given in SP800 131Ar2 - Table 2 are
+ * (512 <= L < 2048 and 160 <= N < 224)
+ */
+ if (!sign && L < 2048)
+ return (L >= 512 && N >= 160 && N < 224);
+
+ /* Valid sizes for both sign and verify */
+ if (L == 2048 && (N == 224 || N == 256))
+ return 1;
+ return (L == 3072 && N == 256);
+ }
+# endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
+ return 1;
+}
+#endif /* OPENSSL_NO_DSA */
+
+#ifndef OPENSSL_NO_DH
+/*
+ * For DH key agreement refer to SP800-56A
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf
+ * "Section 5.5.1.1FFC Domain Parameter Selection/Generation" and
+ * "Appendix D" FFC Safe-prime Groups
+ */
+int ossl_dh_check_key(OSSL_LIB_CTX *ctx, const DH *dh)
+{
+# if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
+ if (ossl_securitycheck_enabled(ctx)) {
+ size_t L, N;
+ const BIGNUM *p, *q;
+
+ if (dh == NULL)
+ return 0;
+
+ p = DH_get0_p(dh);
+ q = DH_get0_q(dh);
+ if (p == NULL || q == NULL)
+ return 0;
+
+ L = BN_num_bits(p);
+ if (L < 2048)
+ return 0;
+
+ /* If it is a safe prime group then it is ok */
+ if (DH_get_nid(dh))
+ return 1;
+
+ /* If not then it must be FFC, which only allows certain sizes. */
+ N = BN_num_bits(q);
+
+ return (L == 2048 && (N == 224 || N == 256));
+ }
+# endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
+ return 1;
+}
+#endif /* OPENSSL_NO_DH */
+
+int ossl_digest_get_approved_nid_with_sha1(OSSL_LIB_CTX *ctx, const EVP_MD *md,
+ int sha1_allowed)
+{
+ int mdnid = ossl_digest_get_approved_nid(md);
+
+# if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
+ if (ossl_securitycheck_enabled(ctx)) {
+ if (mdnid == NID_undef || (mdnid == NID_sha1 && !sha1_allowed))
+ mdnid = -1; /* disallowed by security checks */
+ }
+# endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
+ return mdnid;
+}
+
+int ossl_digest_is_allowed(OSSL_LIB_CTX *ctx, const EVP_MD *md)
+{
+# if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
+ if (ossl_securitycheck_enabled(ctx))
+ return ossl_digest_get_approved_nid(md) != NID_undef;
+# endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
+ return 1;
+}
diff --git a/providers/common/securitycheck_default.c b/providers/common/securitycheck_default.c
new file mode 100644
index 000000000000..de7f0d3a0a57
--- /dev/null
+++ b/providers/common/securitycheck_default.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/deprecated.h"
+
+#include <openssl/rsa.h>
+#include <openssl/core.h>
+#include <openssl/core_names.h>
+#include <openssl/obj_mac.h>
+#include "prov/securitycheck.h"
+#include "internal/nelem.h"
+
+/* Disable the security checks in the default provider */
+int ossl_securitycheck_enabled(OSSL_LIB_CTX *libctx)
+{
+ return 0;
+}
+
+int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md,
+ ossl_unused int sha1_allowed)
+{
+ int mdnid;
+
+ static const OSSL_ITEM name_to_nid[] = {
+ { NID_md5, OSSL_DIGEST_NAME_MD5 },
+ { NID_md5_sha1, OSSL_DIGEST_NAME_MD5_SHA1 },
+ { NID_md2, OSSL_DIGEST_NAME_MD2 },
+ { NID_md4, OSSL_DIGEST_NAME_MD4 },
+ { NID_mdc2, OSSL_DIGEST_NAME_MDC2 },
+ { NID_ripemd160, OSSL_DIGEST_NAME_RIPEMD160 },
+ };
+
+ mdnid = ossl_digest_get_approved_nid_with_sha1(ctx, md, 1);
+ if (mdnid == NID_undef)
+ mdnid = ossl_digest_md_to_nid(md, name_to_nid, OSSL_NELEM(name_to_nid));
+ return mdnid;
+}
diff --git a/providers/common/securitycheck_fips.c b/providers/common/securitycheck_fips.c
new file mode 100644
index 000000000000..b7659bd395c3
--- /dev/null
+++ b/providers/common/securitycheck_fips.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/deprecated.h"
+
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#include <openssl/dh.h>
+#include <openssl/ec.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include <openssl/core_names.h>
+#include <openssl/obj_mac.h>
+#include "prov/securitycheck.h"
+
+int FIPS_security_check_enabled(OSSL_LIB_CTX *libctx);
+
+int ossl_securitycheck_enabled(OSSL_LIB_CTX *libctx)
+{
+#if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
+ return FIPS_security_check_enabled(libctx);
+#else
+ return 0;
+#endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
+}
+
+int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md,
+ int sha1_allowed)
+{
+#if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
+ if (ossl_securitycheck_enabled(ctx))
+ return ossl_digest_get_approved_nid_with_sha1(ctx, md, sha1_allowed);
+#endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
+ return ossl_digest_get_approved_nid(md);
+}
diff --git a/providers/decoders.inc b/providers/decoders.inc
new file mode 100644
index 000000000000..2772aad05da7
--- /dev/null
+++ b/providers/decoders.inc
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef DECODER_PROVIDER
+# error Macro DECODER_PROVIDER undefined
+#endif
+
+#define DECODER_STRUCTURE_type_specific_keypair "type-specific"
+#define DECODER_STRUCTURE_type_specific_params "type-specific"
+#define DECODER_STRUCTURE_type_specific "type-specific"
+#define DECODER_STRUCTURE_type_specific_no_pub "type-specific"
+#define DECODER_STRUCTURE_EncryptedPrivateKeyInfo "EncryptedPrivateKeyInfo"
+#define DECODER_STRUCTURE_PrivateKeyInfo "PrivateKeyInfo"
+#define DECODER_STRUCTURE_SubjectPublicKeyInfo "SubjectPublicKeyInfo"
+#define DECODER_STRUCTURE_DH "dh"
+#define DECODER_STRUCTURE_DHX "dhx"
+#define DECODER_STRUCTURE_DSA "dsa"
+#define DECODER_STRUCTURE_EC "ec"
+#define DECODER_STRUCTURE_RSA "rsa"
+
+/* Arguments are prefixed with '_' to avoid build breaks on certain platforms */
+#define DECODER(_name, _input, _output, _fips) \
+ { _name, \
+ "provider=" DECODER_PROVIDER ",fips=" #_fips ",input=" #_input, \
+ (ossl_##_input##_to_##_output##_decoder_functions) }
+#define DECODER_w_structure(_name, _input, _structure, _output, _fips) \
+ { _name, \
+ "provider=" DECODER_PROVIDER ",fips=" #_fips ",input=" #_input \
+ ",structure=" DECODER_STRUCTURE_##_structure, \
+ (ossl_##_structure##_##_input##_to_##_output##_decoder_functions) }
+
+#ifndef OPENSSL_NO_DH
+DECODER_w_structure("DH", der, PrivateKeyInfo, dh, yes),
+DECODER_w_structure("DH", der, SubjectPublicKeyInfo, dh, yes),
+DECODER_w_structure("DH", der, type_specific_params, dh, yes),
+DECODER_w_structure("DH", der, DH, dh, yes),
+DECODER_w_structure("DHX", der, PrivateKeyInfo, dhx, yes),
+DECODER_w_structure("DHX", der, SubjectPublicKeyInfo, dhx, yes),
+DECODER_w_structure("DHX", der, type_specific_params, dhx, yes),
+DECODER_w_structure("DHX", der, DHX, dhx, yes),
+#endif
+#ifndef OPENSSL_NO_DSA
+DECODER_w_structure("DSA", der, PrivateKeyInfo, dsa, yes),
+DECODER_w_structure("DSA", der, SubjectPublicKeyInfo, dsa, yes),
+DECODER_w_structure("DSA", der, type_specific, dsa, yes),
+DECODER_w_structure("DSA", der, DSA, dsa, yes),
+DECODER("DSA", msblob, dsa, yes),
+DECODER("DSA", pvk, dsa, yes),
+#endif
+#ifndef OPENSSL_NO_EC
+DECODER_w_structure("EC", der, PrivateKeyInfo, ec, yes),
+DECODER_w_structure("EC", der, SubjectPublicKeyInfo, ec, yes),
+DECODER_w_structure("EC", der, type_specific_no_pub, ec, yes),
+DECODER_w_structure("EC", der, EC, ec, yes),
+DECODER_w_structure("ED25519", der, PrivateKeyInfo, ed25519, yes),
+DECODER_w_structure("ED25519", der, SubjectPublicKeyInfo, ed25519, yes),
+DECODER_w_structure("ED448", der, PrivateKeyInfo, ed448, yes),
+DECODER_w_structure("ED448", der, SubjectPublicKeyInfo, ed448, yes),
+DECODER_w_structure("X25519", der, PrivateKeyInfo, x25519, yes),
+DECODER_w_structure("X25519", der, SubjectPublicKeyInfo, x25519, yes),
+DECODER_w_structure("X448", der, PrivateKeyInfo, x448, yes),
+DECODER_w_structure("X448", der, SubjectPublicKeyInfo, x448, yes),
+# ifndef OPENSSL_NO_SM2
+DECODER_w_structure("SM2", der, PrivateKeyInfo, sm2, no),
+DECODER_w_structure("SM2", der, SubjectPublicKeyInfo, sm2, no),
+# endif
+#endif
+DECODER_w_structure("RSA", der, PrivateKeyInfo, rsa, yes),
+DECODER_w_structure("RSA", der, SubjectPublicKeyInfo, rsa, yes),
+DECODER_w_structure("RSA", der, type_specific_keypair, rsa, yes),
+DECODER_w_structure("RSA", der, RSA, rsa, yes),
+DECODER_w_structure("RSA-PSS", der, PrivateKeyInfo, rsapss, yes),
+DECODER_w_structure("RSA-PSS", der, SubjectPublicKeyInfo, rsapss, yes),
+DECODER("RSA", msblob, rsa, yes),
+DECODER("RSA", pvk, rsa, yes),
+
+/*
+ * A decoder that takes a SubjectPublicKeyInfo and figures out the types of key
+ * that it contains. The output is the same SubjectPublicKeyInfo
+ */
+DECODER_w_structure("DER", der, SubjectPublicKeyInfo, der, yes),
+DECODER("DER", pem, der, yes),
+/*
+ * A decoder that recognises PKCS#8 EncryptedPrivateKeyInfo structure
+ * and decrypts it, passing on the unencrypted PrivateKeyInfo in DER
+ * form to the next decoder.
+ */
+DECODER_w_structure("DER", der, EncryptedPrivateKeyInfo, der, yes),
diff --git a/providers/defltprov.c b/providers/defltprov.c
new file mode 100644
index 000000000000..ed3f4799e7b4
--- /dev/null
+++ b/providers/defltprov.c
@@ -0,0 +1,596 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <openssl/opensslconf.h>
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include "prov/bio.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/names.h"
+#include "prov/provider_util.h"
+#include "prov/seeding.h"
+#include "internal/nelem.h"
+
+/*
+ * Forward declarations to ensure that interface functions are correctly
+ * defined.
+ */
+static OSSL_FUNC_provider_gettable_params_fn deflt_gettable_params;
+static OSSL_FUNC_provider_get_params_fn deflt_get_params;
+static OSSL_FUNC_provider_query_operation_fn deflt_query;
+
+#define ALGC(NAMES, FUNC, CHECK) { { NAMES, "provider=default", FUNC }, CHECK }
+#define ALG(NAMES, FUNC) ALGC(NAMES, FUNC, NULL)
+
+/* Functions provided by the core */
+static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL;
+static OSSL_FUNC_core_get_params_fn *c_get_params = NULL;
+
+/* Parameters we provide to the core */
+static const OSSL_PARAM deflt_param_types[] = {
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_VERSION, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_BUILDINFO, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_STATUS, OSSL_PARAM_INTEGER, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *deflt_gettable_params(void *provctx)
+{
+ return deflt_param_types;
+}
+
+static int deflt_get_params(void *provctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "OpenSSL Default Provider"))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_VERSION);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_VERSION_STR))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_BUILDINFO);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_FULL_VERSION_STR))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_STATUS);
+ if (p != NULL && !OSSL_PARAM_set_int(p, ossl_prov_is_running()))
+ return 0;
+ return 1;
+}
+
+/*
+ * For the algorithm names, we use the following formula for our primary
+ * names:
+ *
+ * ALGNAME[VERSION?][-SUBNAME[VERSION?]?][-SIZE?][-MODE?]
+ *
+ * VERSION is only present if there are multiple versions of
+ * an alg (MD2, MD4, MD5). It may be omitted if there is only
+ * one version (if a subsequent version is released in the future,
+ * we can always change the canonical name, and add the old name
+ * as an alias).
+ *
+ * SUBNAME may be present where we are combining multiple
+ * algorithms together, e.g. MD5-SHA1.
+ *
+ * SIZE is only present if multiple versions of an algorithm exist
+ * with different sizes (e.g. AES-128-CBC, AES-256-CBC)
+ *
+ * MODE is only present where applicable.
+ *
+ * We add diverse other names where applicable, such as the names that
+ * NIST uses, or that are used for ASN.1 OBJECT IDENTIFIERs, or names
+ * we have used historically.
+ *
+ * Algorithm names are case insensitive, but we use all caps in our "canonical"
+ * names for consistency.
+ */
+static const OSSL_ALGORITHM deflt_digests[] = {
+ /* Our primary name:NIST name[:our older names] */
+ { PROV_NAMES_SHA1, "provider=default", ossl_sha1_functions },
+ { PROV_NAMES_SHA2_224, "provider=default", ossl_sha224_functions },
+ { PROV_NAMES_SHA2_256, "provider=default", ossl_sha256_functions },
+ { PROV_NAMES_SHA2_384, "provider=default", ossl_sha384_functions },
+ { PROV_NAMES_SHA2_512, "provider=default", ossl_sha512_functions },
+ { PROV_NAMES_SHA2_512_224, "provider=default", ossl_sha512_224_functions },
+ { PROV_NAMES_SHA2_512_256, "provider=default", ossl_sha512_256_functions },
+
+ /* We agree with NIST here, so one name only */
+ { PROV_NAMES_SHA3_224, "provider=default", ossl_sha3_224_functions },
+ { PROV_NAMES_SHA3_256, "provider=default", ossl_sha3_256_functions },
+ { PROV_NAMES_SHA3_384, "provider=default", ossl_sha3_384_functions },
+ { PROV_NAMES_SHA3_512, "provider=default", ossl_sha3_512_functions },
+
+ /*
+ * KECCAK-KMAC-128 and KECCAK-KMAC-256 as hashes are mostly useful for
+ * the KMAC-128 and KMAC-256.
+ */
+ { PROV_NAMES_KECCAK_KMAC_128, "provider=default",
+ ossl_keccak_kmac_128_functions },
+ { PROV_NAMES_KECCAK_KMAC_256, "provider=default",
+ ossl_keccak_kmac_256_functions },
+
+ /* Our primary name:NIST name */
+ { PROV_NAMES_SHAKE_128, "provider=default", ossl_shake_128_functions },
+ { PROV_NAMES_SHAKE_256, "provider=default", ossl_shake_256_functions },
+
+#ifndef OPENSSL_NO_BLAKE2
+ /*
+ * https://blake2.net/ doesn't specify size variants,
+ * but mentions that Bouncy Castle uses the names
+ * BLAKE2b-160, BLAKE2b-256, BLAKE2b-384, and BLAKE2b-512
+ * If we assume that "2b" and "2s" are versions, that pattern
+ * fits with ours. We also add our historical names.
+ */
+ { PROV_NAMES_BLAKE2S_256, "provider=default", ossl_blake2s256_functions },
+ { PROV_NAMES_BLAKE2B_512, "provider=default", ossl_blake2b512_functions },
+#endif /* OPENSSL_NO_BLAKE2 */
+
+#ifndef OPENSSL_NO_SM3
+ { PROV_NAMES_SM3, "provider=default", ossl_sm3_functions },
+#endif /* OPENSSL_NO_SM3 */
+
+#ifndef OPENSSL_NO_MD5
+ { PROV_NAMES_MD5, "provider=default", ossl_md5_functions },
+ { PROV_NAMES_MD5_SHA1, "provider=default", ossl_md5_sha1_functions },
+#endif /* OPENSSL_NO_MD5 */
+
+#ifndef OPENSSL_NO_RMD160
+ { PROV_NAMES_RIPEMD_160, "provider=default", ossl_ripemd160_functions },
+#endif /* OPENSSL_NO_RMD160 */
+
+ { PROV_NAMES_NULL, "provider=default", ossl_nullmd_functions },
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM_CAPABLE deflt_ciphers[] = {
+ ALG(PROV_NAMES_NULL, ossl_null_functions),
+ ALG(PROV_NAMES_AES_256_ECB, ossl_aes256ecb_functions),
+ ALG(PROV_NAMES_AES_192_ECB, ossl_aes192ecb_functions),
+ ALG(PROV_NAMES_AES_128_ECB, ossl_aes128ecb_functions),
+ ALG(PROV_NAMES_AES_256_CBC, ossl_aes256cbc_functions),
+ ALG(PROV_NAMES_AES_192_CBC, ossl_aes192cbc_functions),
+ ALG(PROV_NAMES_AES_128_CBC, ossl_aes128cbc_functions),
+ ALG(PROV_NAMES_AES_128_CBC_CTS, ossl_aes128cbc_cts_functions),
+ ALG(PROV_NAMES_AES_192_CBC_CTS, ossl_aes192cbc_cts_functions),
+ ALG(PROV_NAMES_AES_256_CBC_CTS, ossl_aes256cbc_cts_functions),
+ ALG(PROV_NAMES_AES_256_OFB, ossl_aes256ofb_functions),
+ ALG(PROV_NAMES_AES_192_OFB, ossl_aes192ofb_functions),
+ ALG(PROV_NAMES_AES_128_OFB, ossl_aes128ofb_functions),
+ ALG(PROV_NAMES_AES_256_CFB, ossl_aes256cfb_functions),
+ ALG(PROV_NAMES_AES_192_CFB, ossl_aes192cfb_functions),
+ ALG(PROV_NAMES_AES_128_CFB, ossl_aes128cfb_functions),
+ ALG(PROV_NAMES_AES_256_CFB1, ossl_aes256cfb1_functions),
+ ALG(PROV_NAMES_AES_192_CFB1, ossl_aes192cfb1_functions),
+ ALG(PROV_NAMES_AES_128_CFB1, ossl_aes128cfb1_functions),
+ ALG(PROV_NAMES_AES_256_CFB8, ossl_aes256cfb8_functions),
+ ALG(PROV_NAMES_AES_192_CFB8, ossl_aes192cfb8_functions),
+ ALG(PROV_NAMES_AES_128_CFB8, ossl_aes128cfb8_functions),
+ ALG(PROV_NAMES_AES_256_CTR, ossl_aes256ctr_functions),
+ ALG(PROV_NAMES_AES_192_CTR, ossl_aes192ctr_functions),
+ ALG(PROV_NAMES_AES_128_CTR, ossl_aes128ctr_functions),
+ ALG(PROV_NAMES_AES_256_XTS, ossl_aes256xts_functions),
+ ALG(PROV_NAMES_AES_128_XTS, ossl_aes128xts_functions),
+#ifndef OPENSSL_NO_OCB
+ ALG(PROV_NAMES_AES_256_OCB, ossl_aes256ocb_functions),
+ ALG(PROV_NAMES_AES_192_OCB, ossl_aes192ocb_functions),
+ ALG(PROV_NAMES_AES_128_OCB, ossl_aes128ocb_functions),
+#endif /* OPENSSL_NO_OCB */
+#ifndef OPENSSL_NO_SIV
+ ALG(PROV_NAMES_AES_128_SIV, ossl_aes128siv_functions),
+ ALG(PROV_NAMES_AES_192_SIV, ossl_aes192siv_functions),
+ ALG(PROV_NAMES_AES_256_SIV, ossl_aes256siv_functions),
+#endif /* OPENSSL_NO_SIV */
+ ALG(PROV_NAMES_AES_256_GCM, ossl_aes256gcm_functions),
+ ALG(PROV_NAMES_AES_192_GCM, ossl_aes192gcm_functions),
+ ALG(PROV_NAMES_AES_128_GCM, ossl_aes128gcm_functions),
+ ALG(PROV_NAMES_AES_256_CCM, ossl_aes256ccm_functions),
+ ALG(PROV_NAMES_AES_192_CCM, ossl_aes192ccm_functions),
+ ALG(PROV_NAMES_AES_128_CCM, ossl_aes128ccm_functions),
+ ALG(PROV_NAMES_AES_256_WRAP, ossl_aes256wrap_functions),
+ ALG(PROV_NAMES_AES_192_WRAP, ossl_aes192wrap_functions),
+ ALG(PROV_NAMES_AES_128_WRAP, ossl_aes128wrap_functions),
+ ALG(PROV_NAMES_AES_256_WRAP_PAD, ossl_aes256wrappad_functions),
+ ALG(PROV_NAMES_AES_192_WRAP_PAD, ossl_aes192wrappad_functions),
+ ALG(PROV_NAMES_AES_128_WRAP_PAD, ossl_aes128wrappad_functions),
+ ALG(PROV_NAMES_AES_256_WRAP_INV, ossl_aes256wrapinv_functions),
+ ALG(PROV_NAMES_AES_192_WRAP_INV, ossl_aes192wrapinv_functions),
+ ALG(PROV_NAMES_AES_128_WRAP_INV, ossl_aes128wrapinv_functions),
+ ALG(PROV_NAMES_AES_256_WRAP_PAD_INV, ossl_aes256wrappadinv_functions),
+ ALG(PROV_NAMES_AES_192_WRAP_PAD_INV, ossl_aes192wrappadinv_functions),
+ ALG(PROV_NAMES_AES_128_WRAP_PAD_INV, ossl_aes128wrappadinv_functions),
+ ALGC(PROV_NAMES_AES_128_CBC_HMAC_SHA1, ossl_aes128cbc_hmac_sha1_functions,
+ ossl_cipher_capable_aes_cbc_hmac_sha1),
+ ALGC(PROV_NAMES_AES_256_CBC_HMAC_SHA1, ossl_aes256cbc_hmac_sha1_functions,
+ ossl_cipher_capable_aes_cbc_hmac_sha1),
+ ALGC(PROV_NAMES_AES_128_CBC_HMAC_SHA256, ossl_aes128cbc_hmac_sha256_functions,
+ ossl_cipher_capable_aes_cbc_hmac_sha256),
+ ALGC(PROV_NAMES_AES_256_CBC_HMAC_SHA256, ossl_aes256cbc_hmac_sha256_functions,
+ ossl_cipher_capable_aes_cbc_hmac_sha256),
+#ifndef OPENSSL_NO_ARIA
+ ALG(PROV_NAMES_ARIA_256_GCM, ossl_aria256gcm_functions),
+ ALG(PROV_NAMES_ARIA_192_GCM, ossl_aria192gcm_functions),
+ ALG(PROV_NAMES_ARIA_128_GCM, ossl_aria128gcm_functions),
+ ALG(PROV_NAMES_ARIA_256_CCM, ossl_aria256ccm_functions),
+ ALG(PROV_NAMES_ARIA_192_CCM, ossl_aria192ccm_functions),
+ ALG(PROV_NAMES_ARIA_128_CCM, ossl_aria128ccm_functions),
+ ALG(PROV_NAMES_ARIA_256_ECB, ossl_aria256ecb_functions),
+ ALG(PROV_NAMES_ARIA_192_ECB, ossl_aria192ecb_functions),
+ ALG(PROV_NAMES_ARIA_128_ECB, ossl_aria128ecb_functions),
+ ALG(PROV_NAMES_ARIA_256_CBC, ossl_aria256cbc_functions),
+ ALG(PROV_NAMES_ARIA_192_CBC, ossl_aria192cbc_functions),
+ ALG(PROV_NAMES_ARIA_128_CBC, ossl_aria128cbc_functions),
+ ALG(PROV_NAMES_ARIA_256_OFB, ossl_aria256ofb_functions),
+ ALG(PROV_NAMES_ARIA_192_OFB, ossl_aria192ofb_functions),
+ ALG(PROV_NAMES_ARIA_128_OFB, ossl_aria128ofb_functions),
+ ALG(PROV_NAMES_ARIA_256_CFB, ossl_aria256cfb_functions),
+ ALG(PROV_NAMES_ARIA_192_CFB, ossl_aria192cfb_functions),
+ ALG(PROV_NAMES_ARIA_128_CFB, ossl_aria128cfb_functions),
+ ALG(PROV_NAMES_ARIA_256_CFB1, ossl_aria256cfb1_functions),
+ ALG(PROV_NAMES_ARIA_192_CFB1, ossl_aria192cfb1_functions),
+ ALG(PROV_NAMES_ARIA_128_CFB1, ossl_aria128cfb1_functions),
+ ALG(PROV_NAMES_ARIA_256_CFB8, ossl_aria256cfb8_functions),
+ ALG(PROV_NAMES_ARIA_192_CFB8, ossl_aria192cfb8_functions),
+ ALG(PROV_NAMES_ARIA_128_CFB8, ossl_aria128cfb8_functions),
+ ALG(PROV_NAMES_ARIA_256_CTR, ossl_aria256ctr_functions),
+ ALG(PROV_NAMES_ARIA_192_CTR, ossl_aria192ctr_functions),
+ ALG(PROV_NAMES_ARIA_128_CTR, ossl_aria128ctr_functions),
+#endif /* OPENSSL_NO_ARIA */
+#ifndef OPENSSL_NO_CAMELLIA
+ ALG(PROV_NAMES_CAMELLIA_256_ECB, ossl_camellia256ecb_functions),
+ ALG(PROV_NAMES_CAMELLIA_192_ECB, ossl_camellia192ecb_functions),
+ ALG(PROV_NAMES_CAMELLIA_128_ECB, ossl_camellia128ecb_functions),
+ ALG(PROV_NAMES_CAMELLIA_256_CBC, ossl_camellia256cbc_functions),
+ ALG(PROV_NAMES_CAMELLIA_192_CBC, ossl_camellia192cbc_functions),
+ ALG(PROV_NAMES_CAMELLIA_128_CBC, ossl_camellia128cbc_functions),
+ ALG(PROV_NAMES_CAMELLIA_128_CBC_CTS, ossl_camellia128cbc_cts_functions),
+ ALG(PROV_NAMES_CAMELLIA_192_CBC_CTS, ossl_camellia192cbc_cts_functions),
+ ALG(PROV_NAMES_CAMELLIA_256_CBC_CTS, ossl_camellia256cbc_cts_functions),
+ ALG(PROV_NAMES_CAMELLIA_256_OFB, ossl_camellia256ofb_functions),
+ ALG(PROV_NAMES_CAMELLIA_192_OFB, ossl_camellia192ofb_functions),
+ ALG(PROV_NAMES_CAMELLIA_128_OFB, ossl_camellia128ofb_functions),
+ ALG(PROV_NAMES_CAMELLIA_256_CFB, ossl_camellia256cfb_functions),
+ ALG(PROV_NAMES_CAMELLIA_192_CFB, ossl_camellia192cfb_functions),
+ ALG(PROV_NAMES_CAMELLIA_128_CFB, ossl_camellia128cfb_functions),
+ ALG(PROV_NAMES_CAMELLIA_256_CFB1, ossl_camellia256cfb1_functions),
+ ALG(PROV_NAMES_CAMELLIA_192_CFB1, ossl_camellia192cfb1_functions),
+ ALG(PROV_NAMES_CAMELLIA_128_CFB1, ossl_camellia128cfb1_functions),
+ ALG(PROV_NAMES_CAMELLIA_256_CFB8, ossl_camellia256cfb8_functions),
+ ALG(PROV_NAMES_CAMELLIA_192_CFB8, ossl_camellia192cfb8_functions),
+ ALG(PROV_NAMES_CAMELLIA_128_CFB8, ossl_camellia128cfb8_functions),
+ ALG(PROV_NAMES_CAMELLIA_256_CTR, ossl_camellia256ctr_functions),
+ ALG(PROV_NAMES_CAMELLIA_192_CTR, ossl_camellia192ctr_functions),
+ ALG(PROV_NAMES_CAMELLIA_128_CTR, ossl_camellia128ctr_functions),
+#endif /* OPENSSL_NO_CAMELLIA */
+#ifndef OPENSSL_NO_DES
+ ALG(PROV_NAMES_DES_EDE3_ECB, ossl_tdes_ede3_ecb_functions),
+ ALG(PROV_NAMES_DES_EDE3_CBC, ossl_tdes_ede3_cbc_functions),
+ ALG(PROV_NAMES_DES_EDE3_OFB, ossl_tdes_ede3_ofb_functions),
+ ALG(PROV_NAMES_DES_EDE3_CFB, ossl_tdes_ede3_cfb_functions),
+ ALG(PROV_NAMES_DES_EDE3_CFB8, ossl_tdes_ede3_cfb8_functions),
+ ALG(PROV_NAMES_DES_EDE3_CFB1, ossl_tdes_ede3_cfb1_functions),
+ ALG(PROV_NAMES_DES3_WRAP, ossl_tdes_wrap_cbc_functions),
+ ALG(PROV_NAMES_DES_EDE_ECB, ossl_tdes_ede2_ecb_functions),
+ ALG(PROV_NAMES_DES_EDE_CBC, ossl_tdes_ede2_cbc_functions),
+ ALG(PROV_NAMES_DES_EDE_OFB, ossl_tdes_ede2_ofb_functions),
+ ALG(PROV_NAMES_DES_EDE_CFB, ossl_tdes_ede2_cfb_functions),
+#endif /* OPENSSL_NO_DES */
+#ifndef OPENSSL_NO_SM4
+ ALG(PROV_NAMES_SM4_ECB, ossl_sm4128ecb_functions),
+ ALG(PROV_NAMES_SM4_CBC, ossl_sm4128cbc_functions),
+ ALG(PROV_NAMES_SM4_CTR, ossl_sm4128ctr_functions),
+ ALG(PROV_NAMES_SM4_OFB, ossl_sm4128ofb128_functions),
+ ALG(PROV_NAMES_SM4_CFB, ossl_sm4128cfb128_functions),
+#endif /* OPENSSL_NO_SM4 */
+#ifndef OPENSSL_NO_CHACHA
+ ALG(PROV_NAMES_ChaCha20, ossl_chacha20_functions),
+# ifndef OPENSSL_NO_POLY1305
+ ALG(PROV_NAMES_ChaCha20_Poly1305, ossl_chacha20_ossl_poly1305_functions),
+# endif /* OPENSSL_NO_POLY1305 */
+#endif /* OPENSSL_NO_CHACHA */
+ { { NULL, NULL, NULL }, NULL }
+};
+static OSSL_ALGORITHM exported_ciphers[OSSL_NELEM(deflt_ciphers)];
+
+static const OSSL_ALGORITHM deflt_macs[] = {
+#ifndef OPENSSL_NO_BLAKE2
+ { PROV_NAMES_BLAKE2BMAC, "provider=default", ossl_blake2bmac_functions },
+ { PROV_NAMES_BLAKE2SMAC, "provider=default", ossl_blake2smac_functions },
+#endif
+#ifndef OPENSSL_NO_CMAC
+ { PROV_NAMES_CMAC, "provider=default", ossl_cmac_functions },
+#endif
+ { PROV_NAMES_GMAC, "provider=default", ossl_gmac_functions },
+ { PROV_NAMES_HMAC, "provider=default", ossl_hmac_functions },
+ { PROV_NAMES_KMAC_128, "provider=default", ossl_kmac128_functions },
+ { PROV_NAMES_KMAC_256, "provider=default", ossl_kmac256_functions },
+#ifndef OPENSSL_NO_SIPHASH
+ { PROV_NAMES_SIPHASH, "provider=default", ossl_siphash_functions },
+#endif
+#ifndef OPENSSL_NO_POLY1305
+ { PROV_NAMES_POLY1305, "provider=default", ossl_poly1305_functions },
+#endif
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM deflt_kdfs[] = {
+ { PROV_NAMES_HKDF, "provider=default", ossl_kdf_hkdf_functions },
+ { PROV_NAMES_TLS1_3_KDF, "provider=default",
+ ossl_kdf_tls1_3_kdf_functions },
+ { PROV_NAMES_SSKDF, "provider=default", ossl_kdf_sskdf_functions },
+ { PROV_NAMES_PBKDF2, "provider=default", ossl_kdf_pbkdf2_functions },
+ { PROV_NAMES_PKCS12KDF, "provider=default", ossl_kdf_pkcs12_functions },
+ { PROV_NAMES_SSHKDF, "provider=default", ossl_kdf_sshkdf_functions },
+ { PROV_NAMES_X963KDF, "provider=default", ossl_kdf_x963_kdf_functions },
+ { PROV_NAMES_TLS1_PRF, "provider=default", ossl_kdf_tls1_prf_functions },
+ { PROV_NAMES_KBKDF, "provider=default", ossl_kdf_kbkdf_functions },
+ { PROV_NAMES_X942KDF_ASN1, "provider=default", ossl_kdf_x942_kdf_functions },
+#ifndef OPENSSL_NO_SCRYPT
+ { PROV_NAMES_SCRYPT, "provider=default", ossl_kdf_scrypt_functions },
+#endif
+ { PROV_NAMES_KRB5KDF, "provider=default", ossl_kdf_krb5kdf_functions },
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM deflt_keyexch[] = {
+#ifndef OPENSSL_NO_DH
+ { PROV_NAMES_DH, "provider=default", ossl_dh_keyexch_functions },
+#endif
+#ifndef OPENSSL_NO_EC
+ { PROV_NAMES_ECDH, "provider=default", ossl_ecdh_keyexch_functions },
+ { PROV_NAMES_X25519, "provider=default", ossl_x25519_keyexch_functions },
+ { PROV_NAMES_X448, "provider=default", ossl_x448_keyexch_functions },
+#endif
+ { PROV_NAMES_TLS1_PRF, "provider=default", ossl_kdf_tls1_prf_keyexch_functions },
+ { PROV_NAMES_HKDF, "provider=default", ossl_kdf_hkdf_keyexch_functions },
+ { PROV_NAMES_SCRYPT, "provider=default",
+ ossl_kdf_scrypt_keyexch_functions },
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM deflt_rands[] = {
+ { PROV_NAMES_CTR_DRBG, "provider=default", ossl_drbg_ctr_functions },
+ { PROV_NAMES_HASH_DRBG, "provider=default", ossl_drbg_hash_functions },
+ { PROV_NAMES_HMAC_DRBG, "provider=default", ossl_drbg_ossl_hmac_functions },
+ { PROV_NAMES_SEED_SRC, "provider=default", ossl_seed_src_functions },
+ { PROV_NAMES_TEST_RAND, "provider=default", ossl_test_rng_functions },
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM deflt_signature[] = {
+#ifndef OPENSSL_NO_DSA
+ { PROV_NAMES_DSA, "provider=default", ossl_dsa_signature_functions },
+#endif
+ { PROV_NAMES_RSA, "provider=default", ossl_rsa_signature_functions },
+#ifndef OPENSSL_NO_EC
+ { PROV_NAMES_ED25519, "provider=default", ossl_ed25519_signature_functions },
+ { PROV_NAMES_ED448, "provider=default", ossl_ed448_signature_functions },
+ { PROV_NAMES_ECDSA, "provider=default", ossl_ecdsa_signature_functions },
+# ifndef OPENSSL_NO_SM2
+ { PROV_NAMES_SM2, "provider=default", ossl_sm2_signature_functions },
+# endif
+#endif
+ { PROV_NAMES_HMAC, "provider=default", ossl_mac_legacy_hmac_signature_functions },
+ { PROV_NAMES_SIPHASH, "provider=default",
+ ossl_mac_legacy_siphash_signature_functions },
+#ifndef OPENSSL_NO_POLY1305
+ { PROV_NAMES_POLY1305, "provider=default",
+ ossl_mac_legacy_poly1305_signature_functions },
+#endif
+#ifndef OPENSSL_NO_CMAC
+ { PROV_NAMES_CMAC, "provider=default", ossl_mac_legacy_cmac_signature_functions },
+#endif
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM deflt_asym_cipher[] = {
+ { PROV_NAMES_RSA, "provider=default", ossl_rsa_asym_cipher_functions },
+#ifndef OPENSSL_NO_SM2
+ { PROV_NAMES_SM2, "provider=default", ossl_sm2_asym_cipher_functions },
+#endif
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM deflt_asym_kem[] = {
+ { PROV_NAMES_RSA, "provider=default", ossl_rsa_asym_kem_functions },
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM deflt_keymgmt[] = {
+#ifndef OPENSSL_NO_DH
+ { PROV_NAMES_DH, "provider=default", ossl_dh_keymgmt_functions,
+ PROV_DESCS_DH },
+ { PROV_NAMES_DHX, "provider=default", ossl_dhx_keymgmt_functions,
+ PROV_DESCS_DHX },
+#endif
+#ifndef OPENSSL_NO_DSA
+ { PROV_NAMES_DSA, "provider=default", ossl_dsa_keymgmt_functions,
+ PROV_DESCS_DSA},
+#endif
+ { PROV_NAMES_RSA, "provider=default", ossl_rsa_keymgmt_functions,
+ PROV_DESCS_RSA },
+ { PROV_NAMES_RSA_PSS, "provider=default", ossl_rsapss_keymgmt_functions,
+ PROV_DESCS_RSA_PSS },
+#ifndef OPENSSL_NO_EC
+ { PROV_NAMES_EC, "provider=default", ossl_ec_keymgmt_functions,
+ PROV_DESCS_EC },
+ { PROV_NAMES_X25519, "provider=default", ossl_x25519_keymgmt_functions,
+ PROV_DESCS_X25519 },
+ { PROV_NAMES_X448, "provider=default", ossl_x448_keymgmt_functions,
+ PROV_DESCS_X448 },
+ { PROV_NAMES_ED25519, "provider=default", ossl_ed25519_keymgmt_functions,
+ PROV_DESCS_ED25519 },
+ { PROV_NAMES_ED448, "provider=default", ossl_ed448_keymgmt_functions,
+ PROV_DESCS_ED448 },
+#endif
+ { PROV_NAMES_TLS1_PRF, "provider=default", ossl_kdf_keymgmt_functions,
+ PROV_DESCS_TLS1_PRF_SIGN },
+ { PROV_NAMES_HKDF, "provider=default", ossl_kdf_keymgmt_functions,
+ PROV_DESCS_HKDF_SIGN },
+ { PROV_NAMES_SCRYPT, "provider=default", ossl_kdf_keymgmt_functions,
+ PROV_DESCS_SCRYPT_SIGN },
+ { PROV_NAMES_HMAC, "provider=default", ossl_mac_legacy_keymgmt_functions,
+ PROV_DESCS_HMAC_SIGN },
+ { PROV_NAMES_SIPHASH, "provider=default", ossl_mac_legacy_keymgmt_functions,
+ PROV_DESCS_SIPHASH_SIGN },
+#ifndef OPENSSL_NO_POLY1305
+ { PROV_NAMES_POLY1305, "provider=default", ossl_mac_legacy_keymgmt_functions,
+ PROV_DESCS_POLY1305_SIGN },
+#endif
+#ifndef OPENSSL_NO_CMAC
+ { PROV_NAMES_CMAC, "provider=default", ossl_cmac_legacy_keymgmt_functions,
+ PROV_DESCS_CMAC_SIGN },
+#endif
+#ifndef OPENSSL_NO_SM2
+ { PROV_NAMES_SM2, "provider=default", ossl_sm2_keymgmt_functions,
+ PROV_DESCS_SM2 },
+#endif
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM deflt_encoder[] = {
+#define ENCODER_PROVIDER "default"
+#include "encoders.inc"
+ { NULL, NULL, NULL }
+#undef ENCODER_PROVIDER
+};
+
+static const OSSL_ALGORITHM deflt_decoder[] = {
+#define DECODER_PROVIDER "default"
+#include "decoders.inc"
+ { NULL, NULL, NULL }
+#undef DECODER_PROVIDER
+};
+
+static const OSSL_ALGORITHM deflt_store[] = {
+#define STORE(name, _fips, func_table) \
+ { name, "provider=default,fips=" _fips, (func_table) },
+
+#include "stores.inc"
+ { NULL, NULL, NULL }
+#undef STORE
+};
+
+static const OSSL_ALGORITHM *deflt_query(void *provctx, int operation_id,
+ int *no_cache)
+{
+ *no_cache = 0;
+ switch (operation_id) {
+ case OSSL_OP_DIGEST:
+ return deflt_digests;
+ case OSSL_OP_CIPHER:
+ return exported_ciphers;
+ case OSSL_OP_MAC:
+ return deflt_macs;
+ case OSSL_OP_KDF:
+ return deflt_kdfs;
+ case OSSL_OP_RAND:
+ return deflt_rands;
+ case OSSL_OP_KEYMGMT:
+ return deflt_keymgmt;
+ case OSSL_OP_KEYEXCH:
+ return deflt_keyexch;
+ case OSSL_OP_SIGNATURE:
+ return deflt_signature;
+ case OSSL_OP_ASYM_CIPHER:
+ return deflt_asym_cipher;
+ case OSSL_OP_KEM:
+ return deflt_asym_kem;
+ case OSSL_OP_ENCODER:
+ return deflt_encoder;
+ case OSSL_OP_DECODER:
+ return deflt_decoder;
+ case OSSL_OP_STORE:
+ return deflt_store;
+ }
+ return NULL;
+}
+
+
+static void deflt_teardown(void *provctx)
+{
+ BIO_meth_free(ossl_prov_ctx_get0_core_bio_method(provctx));
+ ossl_prov_ctx_free(provctx);
+}
+
+/* Functions we provide to the core */
+static const OSSL_DISPATCH deflt_dispatch_table[] = {
+ { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))deflt_teardown },
+ { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void))deflt_gettable_params },
+ { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))deflt_get_params },
+ { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))deflt_query },
+ { OSSL_FUNC_PROVIDER_GET_CAPABILITIES,
+ (void (*)(void))ossl_prov_get_capabilities },
+ { 0, NULL }
+};
+
+OSSL_provider_init_fn ossl_default_provider_init;
+
+int ossl_default_provider_init(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in,
+ const OSSL_DISPATCH **out,
+ void **provctx)
+{
+ OSSL_FUNC_core_get_libctx_fn *c_get_libctx = NULL;
+ BIO_METHOD *corebiometh;
+
+ if (!ossl_prov_bio_from_dispatch(in)
+ || !ossl_prov_seeding_from_dispatch(in))
+ return 0;
+ for (; in->function_id != 0; in++) {
+ switch (in->function_id) {
+ case OSSL_FUNC_CORE_GETTABLE_PARAMS:
+ c_gettable_params = OSSL_FUNC_core_gettable_params(in);
+ break;
+ case OSSL_FUNC_CORE_GET_PARAMS:
+ c_get_params = OSSL_FUNC_core_get_params(in);
+ break;
+ case OSSL_FUNC_CORE_GET_LIBCTX:
+ c_get_libctx = OSSL_FUNC_core_get_libctx(in);
+ break;
+ default:
+ /* Just ignore anything we don't understand */
+ break;
+ }
+ }
+
+ if (c_get_libctx == NULL)
+ return 0;
+
+ /*
+ * We want to make sure that all calls from this provider that requires
+ * a library context use the same context as the one used to call our
+ * functions. We do that by passing it along in the provider context.
+ *
+ * This only works for built-in providers. Most providers should
+ * create their own library context.
+ */
+ if ((*provctx = ossl_prov_ctx_new()) == NULL
+ || (corebiometh = ossl_bio_prov_init_bio_method()) == NULL) {
+ ossl_prov_ctx_free(*provctx);
+ *provctx = NULL;
+ return 0;
+ }
+ ossl_prov_ctx_set0_libctx(*provctx,
+ (OSSL_LIB_CTX *)c_get_libctx(handle));
+ ossl_prov_ctx_set0_handle(*provctx, handle);
+ ossl_prov_ctx_set0_core_bio_method(*provctx, corebiometh);
+
+ *out = deflt_dispatch_table;
+ ossl_prov_cache_exported_algorithms(deflt_ciphers, exported_ciphers);
+
+ return 1;
+}
diff --git a/providers/encoders.inc b/providers/encoders.inc
new file mode 100644
index 000000000000..95e287c8b900
--- /dev/null
+++ b/providers/encoders.inc
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef ENCODER_PROVIDER
+# error Macro ENCODER_PROVIDER undefined
+#endif
+
+#define ENCODER_STRUCTURE_type_specific_keypair "type-specific"
+#define ENCODER_STRUCTURE_type_specific_params "type-specific"
+#define ENCODER_STRUCTURE_type_specific "type-specific"
+#define ENCODER_STRUCTURE_type_specific_no_pub "type-specific"
+#define ENCODER_STRUCTURE_EncryptedPrivateKeyInfo "EncryptedPrivateKeyInfo"
+#define ENCODER_STRUCTURE_PrivateKeyInfo "PrivateKeyInfo"
+#define ENCODER_STRUCTURE_SubjectPublicKeyInfo "SubjectPublicKeyInfo"
+#define ENCODER_STRUCTURE_DH "dh"
+#define ENCODER_STRUCTURE_DHX "dhx"
+#define ENCODER_STRUCTURE_DSA "dsa"
+#define ENCODER_STRUCTURE_EC "ec"
+#define ENCODER_STRUCTURE_RSA "rsa"
+#define ENCODER_STRUCTURE_PKCS1 "pkcs1"
+#define ENCODER_STRUCTURE_PKCS3 "pkcs3"
+#define ENCODER_STRUCTURE_X9_42 "X9.42"
+#define ENCODER_STRUCTURE_X9_62 "X9.62"
+
+/* Arguments are prefixed with '_' to avoid build breaks on certain platforms */
+#define ENCODER_TEXT(_name, _sym, _fips) \
+ { _name, \
+ "provider=" ENCODER_PROVIDER ",fips=" #_fips ",output=text", \
+ (ossl_##_sym##_to_text_encoder_functions) }
+#define ENCODER(_name, _sym, _fips, _output) \
+ { _name, \
+ "provider=" ENCODER_PROVIDER ",fips=" #_fips ",output=" #_output, \
+ (ossl_##_sym##_to_##_output##_encoder_functions) }
+#define ENCODER_w_structure(_name, _sym, _fips, _output, _structure) \
+ { _name, \
+ "provider=" ENCODER_PROVIDER ",fips=" #_fips ",output=" #_output \
+ ",structure=" ENCODER_STRUCTURE_##_structure, \
+ (ossl_##_sym##_to_##_structure##_##_output##_encoder_functions) }
+
+/*
+ * Entries for human text "encoders"
+ */
+ENCODER_TEXT("RSA", rsa, yes),
+ENCODER_TEXT("RSA-PSS", rsapss, yes),
+#ifndef OPENSSL_NO_DH
+ENCODER_TEXT("DH", dh, yes),
+ENCODER_TEXT("DHX", dhx, yes),
+#endif
+#ifndef OPENSSL_NO_DSA
+ENCODER_TEXT("DSA", dsa, yes),
+#endif
+#ifndef OPENSSL_NO_EC
+ENCODER_TEXT("EC", ec, yes),
+ENCODER_TEXT("ED25519", ed25519, yes),
+ENCODER_TEXT("ED448", ed448, yes),
+ENCODER_TEXT("X25519", x25519, yes),
+ENCODER_TEXT("X448", x448, yes),
+# ifndef OPENSSL_NO_SM2
+ENCODER_TEXT("SM2", sm2, no),
+# endif
+#endif
+
+/*
+ * Entries for key type specific output formats. The structure name on these
+ * is the same as the key type name. This allows us to say something like:
+ *
+ * To replace i2d_{TYPE}PrivateKey(), i2d_{TYPE}PublicKey() and
+ * i2d_{TYPE}Params(), use OSSL_ENCODER functions with an OSSL_ENCODER_CTX
+ * created like this:
+ *
+ * OSSL_ENCODER_CTX *ctx =
+ * OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, "DER", "type-specific",
+ * NULL, NULL);
+ *
+ * To replace PEM_write_bio_{TYPE}PrivateKey(), PEM_write_bio_{TYPE}PublicKey()
+ * and PEM_write_bio_{TYPE}Params(), use OSSL_ENCODER functions with an
+ * OSSL_ENCODER_CTX created like this:
+ *
+ * OSSL_ENCODER_CTX *ctx =
+ * OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, "PEM", "type-specific",
+ * NULL, NULL);
+ *
+ * We only implement those for which there are current i2d_ and PEM_write_bio
+ * implementations.
+ */
+
+/* The RSA encoders only support private key and public key output */
+ENCODER_w_structure("RSA", rsa, yes, der, type_specific_keypair),
+ENCODER_w_structure("RSA", rsa, yes, pem, type_specific_keypair),
+#ifndef OPENSSL_NO_DH
+/* DH and X9.42 DH only support key parameters output. */
+ENCODER_w_structure("DH", dh, yes, der, type_specific_params),
+ENCODER_w_structure("DH", dh, yes, pem, type_specific_params),
+ENCODER_w_structure("DHX", dhx, yes, der, type_specific_params),
+ENCODER_w_structure("DHX", dhx, yes, pem, type_specific_params),
+#endif
+#ifndef OPENSSL_NO_DSA
+ENCODER_w_structure("DSA", dsa, yes, der, type_specific),
+ENCODER_w_structure("DSA", dsa, yes, pem, type_specific),
+#endif
+#ifndef OPENSSL_NO_EC
+/* EC only supports keypair and parameters DER and PEM output. */
+ENCODER_w_structure("EC", ec, yes, der, type_specific_no_pub),
+ENCODER_w_structure("EC", ec, yes, pem, type_specific_no_pub),
+/* EC supports blob output for the public key */
+ENCODER("EC", ec, yes, blob),
+# ifndef OPENSSL_NO_SM2
+ENCODER_w_structure("SM2", sm2, no, der, type_specific_no_pub),
+ENCODER_w_structure("SM2", sm2, no, pem, type_specific_no_pub),
+ENCODER("SM2", sm2, no, blob),
+# endif
+#endif
+
+/*
+ * Entries for the output formats MSBLOB and PVK
+ */
+ENCODER("RSA", rsa, yes, msblob),
+ENCODER("RSA", rsa, yes, pvk),
+#ifndef OPENSSL_NO_DSA
+ENCODER("DSA", dsa, yes, msblob),
+ENCODER("DSA", dsa, yes, pvk),
+#endif
+
+/*
+ * Entries for encrypted PKCS#8 (EncryptedPrivateKeyInfo), unencrypted PKCS#8
+ * (PrivateKeyInfo) and SubjectPublicKeyInfo. The "der" ones are added
+ * convenience for any user that wants to use OSSL_ENCODER directly.
+ * The "pem" ones also support PEM_write_bio_PrivateKey() and
+ * PEM_write_bio_PUBKEY().
+ */
+ENCODER_w_structure("RSA", rsa, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("RSA", rsa, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("RSA", rsa, yes, der, PrivateKeyInfo),
+ENCODER_w_structure("RSA", rsa, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure("RSA", rsa, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("RSA", rsa, yes, pem, SubjectPublicKeyInfo),
+
+ENCODER_w_structure("RSA-PSS", rsapss, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("RSA-PSS", rsapss, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("RSA-PSS", rsapss, yes, der, PrivateKeyInfo),
+ENCODER_w_structure("RSA-PSS", rsapss, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure("RSA-PSS", rsapss, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("RSA-PSS", rsapss, yes, pem, SubjectPublicKeyInfo),
+
+#ifndef OPENSSL_NO_DH
+ENCODER_w_structure("DH", dh, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("DH", dh, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("DH", dh, yes, der, PrivateKeyInfo),
+ENCODER_w_structure("DH", dh, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure("DH", dh, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("DH", dh, yes, pem, SubjectPublicKeyInfo),
+
+ENCODER_w_structure("DHX", dhx, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("DHX", dhx, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("DHX", dhx, yes, der, PrivateKeyInfo),
+ENCODER_w_structure("DHX", dhx, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure("DHX", dhx, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("DHX", dhx, yes, pem, SubjectPublicKeyInfo),
+#endif
+
+#ifndef OPENSSL_NO_DSA
+ENCODER_w_structure("DSA", dsa, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("DSA", dsa, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("DSA", dsa, yes, der, PrivateKeyInfo),
+ENCODER_w_structure("DSA", dsa, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure("DSA", dsa, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("DSA", dsa, yes, pem, SubjectPublicKeyInfo),
+#endif
+
+#ifndef OPENSSL_NO_EC
+ENCODER_w_structure("EC", ec, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("EC", ec, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("EC", ec, yes, der, PrivateKeyInfo),
+ENCODER_w_structure("EC", ec, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure("EC", ec, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("EC", ec, yes, pem, SubjectPublicKeyInfo),
+
+ENCODER_w_structure("X25519", x25519, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("X25519", x25519, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("X25519", x25519, yes, der, PrivateKeyInfo),
+ENCODER_w_structure("X25519", x25519, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure("X25519", x25519, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("X25519", x25519, yes, pem, SubjectPublicKeyInfo),
+
+ENCODER_w_structure("X448", x448, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("X448", x448, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("X448", x448, yes, der, PrivateKeyInfo),
+ENCODER_w_structure("X448", x448, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure("X448", x448, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("X448", x448, yes, pem, SubjectPublicKeyInfo),
+
+ENCODER_w_structure("ED25519", ed25519, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("ED25519", ed25519, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("ED25519", ed25519, yes, der, PrivateKeyInfo),
+ENCODER_w_structure("ED25519", ed25519, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure("ED25519", ed25519, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("ED25519", ed25519, yes, pem, SubjectPublicKeyInfo),
+
+ENCODER_w_structure("ED448", ed448, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("ED448", ed448, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("ED448", ed448, yes, der, PrivateKeyInfo),
+ENCODER_w_structure("ED448", ed448, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure("ED448", ed448, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("ED448", ed448, yes, pem, SubjectPublicKeyInfo),
+
+# ifndef OPENSSL_NO_SM2
+ENCODER_w_structure("SM2", sm2, no, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("SM2", sm2, no, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("SM2", sm2, no, der, PrivateKeyInfo),
+ENCODER_w_structure("SM2", sm2, no, pem, PrivateKeyInfo),
+ENCODER_w_structure("SM2", sm2, no, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("SM2", sm2, no, pem, SubjectPublicKeyInfo),
+# endif
+#endif
+
+/*
+ * Entries for key type specific output formats. These are exactly the
+ * same as the type specific above, except that they use the key type
+ * name as structure name instead of "type-specific", in the call on
+ * OSSL_ENCODER_CTX_new_for_pkey().
+ */
+
+/* The RSA encoders only support private key and public key output */
+ENCODER_w_structure("RSA", rsa, yes, der, RSA),
+ENCODER_w_structure("RSA", rsa, yes, pem, RSA),
+#ifndef OPENSSL_NO_DH
+/* DH and X9.42 DH only support key parameters output. */
+ENCODER_w_structure("DH", dh, yes, der, DH),
+ENCODER_w_structure("DH", dh, yes, pem, DH),
+ENCODER_w_structure("DHX", dhx, yes, der, DHX),
+ENCODER_w_structure("DHX", dhx, yes, pem, DHX),
+#endif
+#ifndef OPENSSL_NO_DSA
+ENCODER_w_structure("DSA", dsa, yes, der, DSA),
+ENCODER_w_structure("DSA", dsa, yes, pem, DSA),
+#endif
+#ifndef OPENSSL_NO_EC
+ENCODER_w_structure("EC", ec, yes, der, EC),
+ENCODER_w_structure("EC", ec, yes, pem, EC),
+#endif
+
+/*
+ * Additional entries with structure names being the standard name.
+ * This is entirely for the convenience of the user that wants to use
+ * OSSL_ENCODER directly with names they may fancy. These do not impact
+ * on libcrypto functionality in any way.
+ */
+/* PKCS#1 is a well known for plain RSA keys, so we add that too */
+ENCODER_w_structure("RSA", rsa, yes, der, PKCS1),
+ENCODER_w_structure("RSA", rsa, yes, pem, PKCS1),
+ENCODER_w_structure("RSA-PSS", rsapss, yes, der, PKCS1),
+ENCODER_w_structure("RSA-PSS", rsapss, yes, pem, PKCS1),
+#ifndef OPENSSL_NO_DH
+/* PKCS#3 defines the format for DH parameters */
+ENCODER_w_structure("DH", dh, yes, der, PKCS3),
+ENCODER_w_structure("DH", dh, yes, pem, PKCS3),
+/* X9.42 defines the format for DHX parameters */
+ENCODER_w_structure("DHX", dhx, yes, der, X9_42),
+ENCODER_w_structure("DHX", dhx, yes, pem, X9_42),
+#endif
+#ifndef OPENSSL_NO_EC
+/* RFC 5915 defines the format for EC keys and parameters */
+ENCODER_w_structure("EC", ec, yes, der, X9_62),
+ENCODER_w_structure("EC", ec, yes, pem, X9_62),
+#endif
diff --git a/providers/fips-sources.checksums b/providers/fips-sources.checksums
new file mode 100644
index 000000000000..10076d9d2e05
--- /dev/null
+++ b/providers/fips-sources.checksums
@@ -0,0 +1,583 @@
+0e22ea0cf34ef3871e30df0bc302dc29352d38001d1622ddb78a27a374b6aee8 crypto/aes/aes_cbc.c
+c049a936d74100fcced225f575d46662792a6a0039777d2d4df0cf61eff90a68 crypto/aes/aes_core.c
+3fac41ce96acb9189eac2d5571425c3ff33a34c884ae7e275e1fd3068b5fc662 crypto/aes/aes_ecb.c
+c1e674d08683a25bc053f6233f73a0d0b3a90aafe591ff57b702c7da1582e4a5 crypto/aes/aes_local.h
+a2466f18da5847c7d9fbced17524633c10ce024671a72f53f9c9c55b9b9923dd crypto/aes/aes_misc.c
+6979c133f76f4623e62e6e970deae70fa025e713a72b71aead5a048d49e47f6f crypto/aes/asm/aes-586.pl
+92be9ff608331a432e95247a8f4fb9e46897d0cb76f2b6db809b61d44287964a crypto/aes/asm/aes-armv4.pl
+953897f86e2de9fa27ef411155ab3aed133af94885f1507e76449c142da78656 crypto/aes/asm/aes-c64xplus.pl
+00196f01f5218ad731e6a058d406078f7228a9756d9d73f51c0d0c2a68f885af crypto/aes/asm/aes-ia64.S
+88b6f8396cd9d86004743d5c3b0f72b7b8c3d5a2b00b0bbb761ba91ae5a7cdc8 crypto/aes/asm/aes-mips.pl
+7ff9c96ef3d591d45d776fa4b244601ea0d9328e289aeab1e1b92436ce7d02ad crypto/aes/asm/aes-parisc.pl
+f1244cdeadcb4e48f35bc5df19d4cfaf07e0086ad951b84f07ff6966501faa5b crypto/aes/asm/aes-ppc.pl
+ecbfe826f4c514810c3ee20e265f4f621149694c298554b2682e5de4f029f14f crypto/aes/asm/aes-s390x.pl
+ee4e8cacef972942d2a89c1a83c984df9cad87c61a54383403c5c4864c403ba1 crypto/aes/asm/aes-sparcv9.pl
+2b3b9ac56bf54334d053857a24bdb08592151e8a7a60b89b8195846b7f8ee7b5 crypto/aes/asm/aes-x86_64.pl
+c56c324667b67d726e040d70379efba5b270e2937f403c1b5979018b836903c7 crypto/aes/asm/aesfx-sparcv9.pl
+14359dc32b7f4e5c08227fb9ac8f9232c1287399463b233fec4a2ab0c19f68d1 crypto/aes/asm/aesni-mb-x86_64.pl
+2fe016e8098d1c959b6199ce98e91dfed9a3a543d6b068daf88d4c4c402701ec crypto/aes/asm/aesni-sha1-x86_64.pl
+1d3acabadedb88d1327eeb76201ea9b3f4814f44898018ffae6c73e3f400b89b crypto/aes/asm/aesni-sha256-x86_64.pl
+4ff74d4e629a88ef5a9e3d3f5b340fc0a4793d16d7cc7f1b70da62512a856248 crypto/aes/asm/aesni-x86.pl
+c7c6694480bb5319690f94826139a93f5c460ebea6dba101b520a76cb956ec93 crypto/aes/asm/aesni-x86_64.pl
+f3a8f3c960c0f47aaa8fc2633d18b14e7c7feeccc536b0115a08bc58333122b6 crypto/aes/asm/aesp8-ppc.pl
+e397a5781893e97dd90a5a52049633be12a43f379ec5751bca2a6350c39444c8 crypto/aes/asm/aest4-sparcv9.pl
+90d53250761de35280f57463855b1a41403c68dfe22771b2f622c5c9b3418eb4 crypto/aes/asm/aesv8-armx.pl
+15cf92ba0ea6fb216c75bb0c134fa1e1b4159a3f9d3c571b2a8319252c4ae633 crypto/aes/asm/bsaes-armv7.pl
+0726a2c4c15c27a12b2f7d5e16863df4a1b1daa7b7d9b728f621b2b224d290e6 crypto/aes/asm/bsaes-x86_64.pl
+1ff94d6bf6c8ae4809f64657eb89260fe3cb22137f649d3c73f72cb190258196 crypto/aes/asm/vpaes-armv8.pl
+c3541865cd02d81101cdbab4877ed82772e6980d2c677b9008b38fa1b26d36d4 crypto/aes/asm/vpaes-ppc.pl
+3ec24185750a995377516bc2fb2eae8b1c52094c6fff093bff591837fc12d6c3 crypto/aes/asm/vpaes-x86.pl
+060bb6620f50af9afecdf97df051b45b9a50be9daf343dfec1cbb29693ce00a4 crypto/aes/asm/vpaes-x86_64.pl
+16739d54200fb81ca7835b5814f965022a2ab41589c7787e2697e3ea72d4fafa crypto/asn1_dsa.c
+819c9fd2b0cae9aab81c3cbd1815c2e22949d75f132f649b5883812d0bbaa39a crypto/bn/asm/alpha-mont.pl
+0070595128b250b9ebdebe48ce53d2d27ca16ec4f7c6c8bd169ab2e4a913b2d1 crypto/bn/asm/armv4-gf2m.pl
+8c1c53a725b8a4f92b8a353bfeeb393be94198df41c912e3270f9e654417b250 crypto/bn/asm/armv4-mont.pl
+8d6192337fedb0012764229d600634f8357c3b74fd38bcbfe8b86ddc6ca96ea2 crypto/bn/asm/armv8-mont.pl
+cb4ad7b7461fcb8e2a0d52881158d0211b79544842d4eae36fc566869a2d62c8 crypto/bn/asm/bn-586.pl
+636da7e2a66272a81f9c99e90b36c6f132ad6236c739e8b9f2e7315f30b72edd crypto/bn/asm/c64xplus-gf2m.pl
+c86664fb974362ee52a454c83c2c4b23fd5b7d64b3c9e23ef1e0dfd130a46ee5 crypto/bn/asm/co-586.pl
+199b9b100f194a2a128c14f2a71be5a04d50d069666d90ca5b69baee1318ccb7 crypto/bn/asm/ia64-mont.pl
+a511aafbf76647a0c83705d4491c898a5584d300aa449fa6166c8803372946eb crypto/bn/asm/ia64.S
+687c5d6606fdfd0e242005972d15db74a9cbac2b8a9a54a56fcb1e99d3880ff3 crypto/bn/asm/mips-mont.pl
+8aca83d2ec45a40af15e59cff1ac2dc33737a3d25f0a0b74d401fa778a5c5eb8 crypto/bn/asm/mips.pl
+b27ec5181e387e812925bb26823b830f49d7a6e4971b6d11ea583f5632a1504b crypto/bn/asm/parisc-mont.pl
+9973523b361db963eea4938a7a8a3adc692e1a4e1aec4fa1f1e57dc93da37921 crypto/bn/asm/ppc-mont.pl
+59cd27e1e10c4984b7fb684b27f491e7634473b1bcff197a07e0ca653124aa9a crypto/bn/asm/ppc.pl
+e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 crypto/bn/asm/ppc64-mont-fixed.pl
+a25be64867ab837d93855af232e2bfa71b85b2c6f00e35e620fdc5618187fb6f crypto/bn/asm/ppc64-mont.pl
+231579e532443665020d4d522d9f11713d9c5d5c814b95b434b0f65452e16de4 crypto/bn/asm/rsaz-avx2.pl
+1657600d320ea549b527b2d878a7658533d60d26eeb38f42ea470fc612f9bb53 crypto/bn/asm/rsaz-avx512.pl
+31e84dc905b13e38850071528d3abbfcaf8910bbc8b46f38d19c2b386a5f838e crypto/bn/asm/rsaz-x86_64.pl
+30fedf48dfc5fec1c2044b6c226dd9fc42a92522cc589797a23a79d452bdd2cf crypto/bn/asm/s390x-gf2m.pl
+590388d69d7ac3a0e9af4014792f4f0fdb9552719e8fb48ebc7e5dfca2a491d4 crypto/bn/asm/s390x-mont.pl
+aa02597f3dc09cfbc190aedb75711859ba0f3efff87067ebfba1ec78ebee40d7 crypto/bn/asm/s390x.S
+2f7cbc2c3d93b1bbc4953dda38b9ae0ab3a0a8331a0418d94d9b286183736c9e crypto/bn/asm/sparct4-mont.pl
+ca21a9ccbc54e19fb7c2e6cdf286ce7cb08b0fba960c777c6edce5c57ccc2101 crypto/bn/asm/sparcv8.S
+fbc93c8dbbecefe66086f58fe9719ed87b13b2cdc61454a10e841228296fecef crypto/bn/asm/sparcv8plus.S
+127832c1e3d298aad805236776488f5f8836b6a0fdbce3f6b42678163df3909f crypto/bn/asm/sparcv9-gf2m.pl
+1622f04a8918724ac0e8804baf285fdafa0eeaaecc36c7facd459d0ff13a8cac crypto/bn/asm/sparcv9-mont.pl
+b69083f78b4b4f7097de4462d16649532fb82c453a82cdd9cc1393122661d6e2 crypto/bn/asm/sparcv9a-mont.pl
+d404375a21d33396824a3da212d6646d4f3150dd141ee4b4a250aefae3482efb crypto/bn/asm/via-mont.pl
+d24f3e97239c8eed5efc721521b025b7256c15e67a54ea6b5c4cf8f7cd0f89ea crypto/bn/asm/vis3-mont.pl
+89278854f44d95be916516609ce6f79dcd346bab52574b9b6336a9952aa94bee crypto/bn/asm/x86-gf2m.pl
+90d4ae234c08267adce9ed38d56e0edc223f7480cb9605f5d7399d0b3914c6be crypto/bn/asm/x86-mont.pl
+d444ca73875e97e0ea88b20e4c02f2fcf3850e8b9311e3b67a2d04fe2796d543 crypto/bn/asm/x86_64-gcc.c
+709ddee92e9222ee0ed27bfb90db556e85e2d302e4a9131afa25fdc14c4d858f crypto/bn/asm/x86_64-gf2m.pl
+da7f7780d27eed164797e5334cd45b35d9c113e86afaca051463aef9a8fd787c crypto/bn/asm/x86_64-mont.pl
+259fb8d7f40c0dba46920b1f169d5b37de03b0fda645463d19e3ae2b56de851d crypto/bn/asm/x86_64-mont5.pl
+0ea8185a037a2951bb3d1e590bbbdeac305176d5e618f3e43a04c09733a9de34 crypto/bn/bn_add.c
+3962dfaa0142e67115ab84f7809d46d59bd122758be09a081b08b2e0d4743b2e crypto/bn/bn_asm.c
+01a35f971062b97b4953604151d3b6a411be439743b5540aa25b638d2186db6f crypto/bn/bn_blind.c
+7b761d541e3b7f6a3f2b14a09b2b3836a079a845cf67a54db4853e3fd38277c6 crypto/bn/bn_const.c
+58b587e20404efa408b31a88ba9c357059ced709bea78c07deb91df7b687db81 crypto/bn/bn_conv.c
+2893b6d03d4850d09c15959941b0759bbb50d8c20e873bed088e7cde4e15a65a crypto/bn/bn_ctx.c
+d94295953ab91469fe2b9da2a542b8ea11ac38551ecde8f8202b7f645c2dea16 crypto/bn/bn_dh.c
+74b63a4515894592b7241fb30b91b21510beaa3d397809e3d74bc9a73e879d18 crypto/bn/bn_div.c
+a29b8b7fa8460f11e50f880e3c3c9e0755b93889bcbb5476206c4d938a9c5735 crypto/bn/bn_exp.c
+ec2b6e3af6df473a23e7f1a8522f2554cb0eb5d34e3282458c4a66d242278434 crypto/bn/bn_exp2.c
+1abab2cc5466b005b939d156e7d8664a4d42a191c9040dbb83941269d6844f0c crypto/bn/bn_gcd.c
+4d6cc7ed36978247a191df1eea0120f8ee97b639ba228793dabe5a8355a1a609 crypto/bn/bn_gf2m.c
+081e8a6abc23599307dab3b1a92113a65e0bf8717cbc40c970c7469350bc4581 crypto/bn/bn_intern.c
+602ed46fbfe12c899dfb7d9d99ff0dbfff96b454fce3cd02817f3e2488dd9192 crypto/bn/bn_kron.c
+b33295765dc6d3843e3571007e2d6dbe75564645ebf181191a91464706d9fadb crypto/bn/bn_lib.c
+0567e3881c4577f25eb7b93070ac1914251d5ef98e3ac4ebacec09a65a12868c crypto/bn/bn_local.h
+07247dc2ccc55f3be525baed92fd20031bbaa80fd0bc56155e80ee0da3fc943d crypto/bn/bn_mod.c
+f60f3d49b183b04bcdf9b82f7c961b8c1bcb00e68a2c1166fe9edd95a783356e crypto/bn/bn_mont.c
+2da73a76b746a47d8cf8ec8b3e0708c2a34e810abde4b4f1241a49e7f5bb2b60 crypto/bn/bn_mpi.c
+76982b18b0803d59b33168b260677e7412970757d3b9513de5c80025290f211d crypto/bn/bn_mul.c
+4e3bf49a788ec36cd1d919475bc410a743931aa144e7c60d603e9c0b448faab4 crypto/bn/bn_nist.c
+c6760a724d696b7209f0a71f8483fabcf4f081f7e93e2628284c32ef78f69365 crypto/bn/bn_prime.c
+c56ad3073108a0de21c5820a48beae2bccdbf5aa8075ec21738878222eb9adc3 crypto/bn/bn_prime.h
+628419eabdb88b265823e43a7a1c88fdfecef79771180836f6089050dc9eadb1 crypto/bn/bn_rand.c
+1f6e13da1d9965b341f81bc0842a987a7db9b7de0fa7f7040d49be01b92d282b crypto/bn/bn_recp.c
+626226d4dae8e19530a60d8a94b270b262740550787fc46f686b301a043c705b crypto/bn/bn_rsa_fips186_4.c
+704b0b4723e5c9e9bae5f3e35f9ae8ae8dca3383929e954de9e5169845abfdb2 crypto/bn/bn_shift.c
+622e90766b29e0d25f46474429aebda8eba2246835b9e85dc26da7cdbd49334f crypto/bn/bn_sqr.c
+42c8ce944c889abcfcf089d0ad2744b7587696d8d7785efa91b3f7ec53dc062a crypto/bn/bn_sqrt.c
+24e62baa56e02f2db6454e10168b7c7fa7638db9221b9acda1803d43f38f36e0 crypto/bn/bn_word.c
+2e69544977adab07422acab5cbb32f4efb7ab68bc160dde711e3f7a8e755b43d crypto/bn/rsa_sup_mul.c
+be27115efd36f0077a3ec26b1ff1f586b0b8969ba05d8ffa34b2ff4badf227bf crypto/bn/rsaz_exp.c
+c4d64da1cdc732ea918fccd6a7bb2746b03365dd26f7ba1e74e08c307ca4c58e crypto/bn/rsaz_exp.h
+5b82cb8dbf3087c2e671871cb0a92e4039223a51af533a2ee996f3bfd47453a7 crypto/bn/rsaz_exp_x2.c
+834db8ff36006e5cb53e09ca6c44290124bd23692f4341ea6563b66fcade4cea crypto/bsearch.c
+c39334b70e1394e43f378ae8d31b6e6dc125e4d9181e6536d38e649c4eaadb75 crypto/buffer/buffer.c
+0e1a41a2d81b5765bca3df448f60bf1fad91e485fe89dd65a7300ffc419e316d crypto/cmac/cmac.c
+ff9be205d6d7ff00b0e64508f0eb8d9ec0415fbabc0948d26e308212b3f7b2d8 crypto/context.c
+c309d81ea991ddf5be4337afad2fd132169f7443c76f863349d3f3c82f3374e4 crypto/core_algorithm.c
+f0fd9eb38bf7f196bbb4d26ce8fdf86d0a4f9db219157e66b2c0ffefb4f42005 crypto/core_fetch.c
+02670d631bf0f34cca1e3477079d7fe5de4e03c391cf3992986f44f55319597c crypto/core_namemap.c
+469e2f53b5f76cd487a60d3d4c44c8fc3a6c4d08405597ba664661ba485508d3 crypto/cpuid.c
+71f0fff881eb4c5505fb17662f0ea4bbff24c6858c045a013ad8f786b07da5c4 crypto/cryptlib.c
+66dbfc58916709d5a6913777346083247942a8d9458ee9b2bf443f0ea4988d64 crypto/ctype.c
+51e56541daea6d4a26d5bae2ea458414063bf08b045bab8df370f6695903e0a5 crypto/der_writer.c
+fea3ba4225df97aee90690adf387625b746d8edfdc5af2357ee65151a3d236ac crypto/des/des_enc.c
+4971cdc016ee262d81e31f96c1617a33a63c0d90139e440c2ff32a368ee07bbd crypto/des/des_local.h
+eeef5722ad56bf1af2ff71681bcc8b8525bc7077e973c98cee920ce9bcc66c81 crypto/des/ecb3_enc.c
+04d4cc355200b57f1e7d265a2cebdf094df1eb6e96621b533adddc3d60d31fbe crypto/des/fcrypt_b.c
+499513b3ad386fe694c4e04b3c8a9fd4c4e18fc44bb6c4f94d6bf2d9362a3a5a crypto/des/ncbc_enc.c
+61926e30dd940616e80936d1c94c5f522daf0d475fb3a40a9e589e78f322901e crypto/des/set_key.c
+8344811b14d151f6cd40a7bc45c8f4a1106252b119c1d5e6a589a023f39b107d crypto/des/spr.h
+816472a54c273906d0a2b58650e0b9d28cc2c8023d120f0d77160f1fe34c4ca3 crypto/dh/dh_backend.c
+d2d0569bea2598bd405f23b60e5283a6ce353f1145a25ff8f28cf15711743156 crypto/dh/dh_check.c
+7838e9a35870b0fbcba0aff2f52a2439f64d026e9922bce6e5978c2f22c51120 crypto/dh/dh_gen.c
+6b17861887b2535159b9e6ca4f927767dad3e71b6e8be50055bc784f78e92d64 crypto/dh/dh_group_params.c
+a5cf5cb464b40f1bc5457dc2a6f2c5ec0f050196603cd2ba7037a23ab64adbf7 crypto/dh/dh_kdf.c
+0afa7dd237f9b21b0cfb0de10505facd57eb07ded905d888d43a1de2356d4002 crypto/dh/dh_key.c
+b0046b2c4e1d74ff4e93f2486a00f63728909b8a75cbdd29b9100e607f97995c crypto/dh/dh_lib.c
+8300775d88db0a1aa26a77eb49d6c4f7252e7fee69e1440de4c40edadc9da044 crypto/dh/dh_local.h
+bbcf4fc3067ac462a27d7277973180b7dc140df9262a686c7fbe4318ca01f7b8 crypto/dsa/dsa_backend.c
+b9c5992089203123c3fae46e39bb4d05e19854087bca7a30ad1f82a3505deec7 crypto/dsa/dsa_check.c
+ae727bf6319eb57e682de35d75ea357921987953b3688365c710e7fba51c7c58 crypto/dsa/dsa_gen.c
+b1de1624e590dbf76f76953802ff162cc8de7c5e2eaba897313c866424d6902b crypto/dsa/dsa_key.c
+9e436a2e0867920c3a5ac58bc14300cad4ab2c4c8fe5e40b355dfd21bfdfe146 crypto/dsa/dsa_lib.c
+f4d52d3897219786c6046bf76abb2f174655c584caa50272bf5d281720df5022 crypto/dsa/dsa_local.h
+f88db9fd73a78e66967e56df442b55230f405b4cd804f31f8696324f0b702f15 crypto/dsa/dsa_ossl.c
+6222aa8f60d7451d974dd87c66995033919f36d7f858cbe609cf731ad1eee34e crypto/dsa/dsa_sign.c
+53fa10cc87ac63e35df661882852dc46ae68e6fee83b842f1aeefe00b8900ee1 crypto/dsa/dsa_vrf.c
+0a206e4c4de4702808cba7c9304bedb66abcbc33e513bc25574a795cd5fa3db0 crypto/ec/asm/ecp_nistp521-ppc64.pl
+78ad06b88fcc8689a3a846b82f9ee01546e5734acd1bccf2494e523b71dc74d1 crypto/ec/asm/ecp_nistz256-armv4.pl
+4617351d2de4d0b2abfd358c58050cee00702d0b4c1acca09312ec870e351c7d crypto/ec/asm/ecp_nistz256-armv8.pl
+3715ddd921425f3018741037f01455ed26a840ace08691a800708170a66cf4d2 crypto/ec/asm/ecp_nistz256-ppc64.pl
+cfe7e75a2fddc87a7251684469a8808b9da82b2f5725eafad5806920f89932bd crypto/ec/asm/ecp_nistz256-sparcv9.pl
+922725c4761cfa567af6ed9ecab04f2c7729ae2595f2fc0fa46dc67879dc87b0 crypto/ec/asm/ecp_nistz256-x86.pl
+ac327475c7ec828d11aa05628b4e3b81ec3b1400f30fe7bec01daf3cf71f2dc9 crypto/ec/asm/ecp_nistz256-x86_64.pl
+cc727533130f5f1a29229929b3d4e8454585d647be25d6344f3c6a0240998368 crypto/ec/asm/x25519-ppc64.pl
+ee897e230964511baa0d1bf95fb938312407a40a88ebe01476879c2763e5f732 crypto/ec/asm/x25519-x86_64.pl
+340336e01aa04fcde9bfd56536f90c9bc0ad56a002b6cfa321a1e421f1e93ceb crypto/ec/curve25519.c
+9a95ec8366154bb20aeb24f4767a8cbb9953ca0380708eb2f39caca6078cd59e crypto/ec/curve448/arch_32/f_impl32.c
+063dac1e4a9573c47532123e9e03e3532a7473cc3e146521ba9ec6f486ddf3b1 crypto/ec/curve448/arch_64/arch_intrinsics.h
+43423b7ee85a5c740c1d81499ee06f4a17732c7731a598e7429d5e402ee77cf4 crypto/ec/curve448/arch_64/f_impl.h
+1689097ae10e4982a8cbe50c2f6eddb03c83436f331f0b67edb98d6b58adc962 crypto/ec/curve448/arch_64/f_impl64.c
+9b408ec0d43f3b6d714ef5963147e2c2abaddc88633db7dd759193d3c56ed727 crypto/ec/curve448/curve448.c
+3c12d90e3fdd59b5d32d63186f1a6f15c75eb73f5035b844a2054356a9459780 crypto/ec/curve448/curve448_local.h
+178fb9863c33174b633c2e7607160b1bedb506d66cc06d53382d87431441f306 crypto/ec/curve448/curve448_tables.c
+f30e13bba5a136ab9ba5225c98b9b94c2cd73fb3aef60f9dcde3cd471cfa1ca4 crypto/ec/curve448/curve448utils.h
+4a45e7828831fbe9f282f933cda54b12cd393ec9bffe5c0ace8e4d1c4d5d6358 crypto/ec/curve448/ed448.h
+a1211ed3991af967c728b9f6d0774b9ea098d43cef0631ff88984a2580d2ac4f crypto/ec/curve448/eddsa.c
+450946e1cccb81e45e5601b6154e2311666b06e294aab926369995af06d1a328 crypto/ec/curve448/f_generic.c
+f6447921a0031fa5beddedd298e82096fb3fdb189b712fab328b61f6beae0c23 crypto/ec/curve448/field.h
+2ad8331e893b5db33198e27603891587686c0dfdab29706dc52a7097c5d6f219 crypto/ec/curve448/point_448.h
+1ff6e467d72530c71d21c310180d04a24f0a9cb41168fba94b43309ecdda3888 crypto/ec/curve448/scalar.c
+3052a044afae2e91b677542fc8b34b3ec9d033e0c6562b0d43098cfb34ab3c9d crypto/ec/curve448/word.h
+ae1637d89287c9d22a34bdc0d67f6e01262a2f8dcef9b61369dba8c334f5a80d crypto/ec/ec2_oct.c
+6bbbf570ce31f5b579f7e03ec9f8a774663c7c1eb5e475bd31f8fee94a021ffc crypto/ec/ec2_smpl.c
+2a71bd8dbe4f427c117d990581709a4ddce07fa8e530794b5a9574fef7c48a0c crypto/ec/ec_asn1.c
+69b1b3acb4295f5fff961b339e8ace913176ca63fcedf4af0da4c27171f24f94 crypto/ec/ec_backend.c
+86e2becf9b3870979e2abefa1bd318e1a31820d275e2b50e03b17fc287abb20a crypto/ec/ec_check.c
+265f911b9d4aada326a2d52cd8a589b556935c8b641598dcd36c6f85d29ce655 crypto/ec/ec_curve.c
+8cfd0dcfb5acbf6105691a2d5e2826dba1ff3906707bc9dd6ff9bffcc306468f crypto/ec/ec_cvt.c
+95ce53663ab8a1d05bd6f4999f30113e1edce771fb6d218a772fe02de7bdaf4d crypto/ec/ec_key.c
+7e40fc646863e0675bbb90f075b809f61bdf0600d8095c8366858d9533ab7700 crypto/ec/ec_kmeth.c
+bbd6f618c3dfe425ce0ba1c6710fe59418130e06351881162a590475e6438c44 crypto/ec/ec_lib.c
+a8a4690e42b4af60aad822aa8b16196df337906af53ea4db926707f7b596ff27 crypto/ec/ec_local.h
+fa901b996eb0e460359cd470843bdb03af7a77a2f1136c5e1d30daef70f3e4d2 crypto/ec/ec_mult.c
+129c6b42417bfcf582f4a959cfd65433e6f85b158274f4fa38f9c62615ac9166 crypto/ec/ec_oct.c
+c7fba2f2c33f67dafa23caef8c3abd12f5336274a9a07d412b83be0366969ee6 crypto/ec/ecdh_kdf.c
+b2cf8f052a5716137da7b0e857ed7a5df5fb513b6d14534199a05e32f2b5a866 crypto/ec/ecdh_ossl.c
+c3750d77c287500884a1ab01def8a6a8500c345d5de1c0f6a70e614fff1b9755 crypto/ec/ecdsa_ossl.c
+b6baa42b16e8df69a12e0ab101033100cddc808ec2682ba1574373e6ec86ae93 crypto/ec/ecdsa_sign.c
+f686cea8c8a3259d95c1e6142813d9da47b6d624c62f26c7e4a16d5607cddb35 crypto/ec/ecdsa_vrf.c
+141cfc1459214555b623517a054a9e8d5e4065a11301237b7247be2c6f397a0a crypto/ec/ecp_mont.c
+13b30f34aeeb0c98747239bfe91b5f0f14e91b2c1f11db62ebb5950c7219daa0 crypto/ec/ecp_nist.c
+f288c23b6f83740956886b2303c64d5a3098c98b530859c3bb4b698c01c1643b crypto/ec/ecp_nistz256.c
+51cb98e7e9c241e33261589f0d74103238baaa850e333c61ff1da360e127518a crypto/ec/ecp_oct.c
+b4b7c683279454ba41438f50a015cb63ef056ccb9be0168918dfbae00313dc68 crypto/ec/ecp_smpl.c
+2096e13aa2fbcb0d4b10faca3e3f5359cf66098b0397a6d74c6fca14f5dee659 crypto/ec/ecx_backend.c
+5ee19c357c318b2948ff5d9118a626a6207af2b2eade7d8536051d4a522668d3 crypto/ec/ecx_backend.h
+22c44f561ab42d1bd7fd3a3c538ebaba375a704f98056b035e7949d73963c580 crypto/ec/ecx_key.c
+28abc295dad8888b5482eb61d31cd78dd80545ecb67dc6f9446a36deb8c40a5e crypto/evp/asymcipher.c
+0e75a058dcbbb62cfe39fec6c4a85385dc1a8fce794e4278ce6cebb29763b82b crypto/evp/dh_support.c
+59d514629005748901718e82f2646ecb1d7fbedbc872726749ce9a5af0d205f2 crypto/evp/digest.c
+838277f228cd3025cf95a9cd435e5606ad1fb5d207bbb057aa29892e6a657c55 crypto/evp/ec_support.c
+1c3d1b1f800b1f1f5adb1fdbdd67cdf37ca7ea93b264d1468c72a63c140873ce crypto/evp/evp_enc.c
+7f10367f9b6191c4a8c01784130d26b2d778485a41cdac5fa17c9a1c4096f132 crypto/evp/evp_fetch.c
+ebe32b2895f7f9767710674352c8949efe93b4bbb5e7b71c27bb5d1822339b46 crypto/evp/evp_lib.c
+78f07bf50b6999611a4e9414ab3a20b219b0ab29ca2bd05002d6919a3f67b8eb crypto/evp/evp_local.h
+117e679d49d2ae87e49d3c942ff0ce768959e8b9713f84a99025cabba462ccd5 crypto/evp/evp_rand.c
+2a128617ec0178e9eeacbe41d75a5530755f41ea524cd124607543cf73456a0c crypto/evp/evp_utils.c
+ca8c6cfd30efd53f2e5d1f19bcf09a3a3d0dff6d8947c3943d07a3f4b354aa86 crypto/evp/exchange.c
+9e25042581b73e295c059c6217f3ecf809134d518eb79b1b67f34e3ca9145677 crypto/evp/kdf_lib.c
+1d72f5506984df1df8606e8c7045f041cf517223e2e1b50c4da8ba8bf1c6c186 crypto/evp/kdf_meth.c
+5179624b8e03615dc9caedc9ec16d094fa081495613dd552d71c2c39475bcd83 crypto/evp/kem.c
+5016dd7ef8b4cf7e9ea8465c18d1daa4c8808cb589261cf236058ee75bc868d7 crypto/evp/keymgmt_lib.c
+a976cf4e7bfb61e06a147360b748238010d23efb069d191fd023abc38d9a2af9 crypto/evp/keymgmt_meth.c
+e1a052839b8b70dca20dbac1282d61abd1c415bf4fb6afb56b811e8770d8a2e1 crypto/evp/m_sigver.c
+4290c95f63b43688a8da57690d122add5161a6811f9753da1444d28f46739961 crypto/evp/mac_lib.c
+e7e8eb5683cd3fbd409df888020dc353b65ac291361829cc4131d5bc86c9fcb3 crypto/evp/mac_meth.c
+b3eebfe75d050bef62a2ce6c13399a2b72bdf60bb540666d01a47691f68931b3 crypto/evp/p_lib.c
+3b4228b92eebd04616ecc3ee58684095313dd5ffd1b43cf698a7d6c202cb4622 crypto/evp/pmeth_check.c
+1f0e9e94e9b0ad322956521b438b78d44cfcd8eb974e8921d05f9e21ba1c05cf crypto/evp/pmeth_gn.c
+76511fba789089a50ef87774817a5482c33633a76a94ecf7b6e8eb915585575d crypto/evp/pmeth_lib.c
+4b2dbddf0f9ceed34c3822347138be754fb194febca1c21c46bcc3a5cce33674 crypto/evp/signature.c
+b06cb8fd4bd95aae1f66e1e145269c82169257f1a60ef0f78f80a3d4c5131fac crypto/ex_data.c
+709d40d5096497349b8b9e2917e949a0a75e6065df62798d1816866ca7e7b4ca crypto/ffc/ffc_backend.c
+a12af33e605315cdddd6d759e70cd9632f0f33682b9aa7103ed1ecd354fc7e55 crypto/ffc/ffc_dh.c
+854378f57707e31ad02cca6eec94369f91f327288d3665713e249c12f7b13211 crypto/ffc/ffc_key_generate.c
+2695c9c8ad9193a8c1ab53d5d09712d50d12c91eb8d62e8a15cbc78f327afe84 crypto/ffc/ffc_key_validate.c
+b18d5d7cfc95163defea41f5a081e90f6a7163a6b81c6cfadb8b470ef2e83fc5 crypto/ffc/ffc_params.c
+1a1d227f9a0f427d2ec93bc646c726c9cd49a84a343b4aff0c9c744fa6df05a9 crypto/ffc/ffc_params_generate.c
+73dac805abab36cd9df53a421221c71d06a366a4ce479fa788be777f11b47159 crypto/ffc/ffc_params_validate.c
+0a4fc92e408b0562cf95c480df93a9907a318a2c92356642903a5d50ed04fd88 crypto/hmac/hmac.c
+0395c1b0834f2f4a0ca1756385f4dc1a4ef6fb925b2db3743df7f57256c5166f crypto/hmac/hmac_local.h
+f897493b50f4e9dd4cacb2a7accda6683c10ece602641874cdff1dac7128a751 crypto/initthread.c
+5482c47c266523129980302426d25839fda662f1544f4b684707e6b272a952c9 crypto/lhash/lhash.c
+5d49ce00fc06df1b64cbc139ef45c71e0faf08a33f966bc608c82d574521a49e crypto/lhash/lhash_local.h
+f866aafae928db1b439ac950dc90744a2397dfe222672fe68b3798396190c8b0 crypto/mem_clr.c
+183bdca6f855182d7d2c78a5c961b34283f85ea69ac828b700605ee82546397d crypto/modes/asm/aes-gcm-armv8_64.pl
+1d686af304f94743038f916125effcb51790c025f3165d8d37b526bbeee781f0 crypto/modes/asm/aesni-gcm-x86_64.pl
+c2e874a8deb418b5d8c935b2e256370566a5150e040c9fa008cdb5b463c26904 crypto/modes/asm/ghash-alpha.pl
+6bc7d63569c73d7020ede481f2de05221ac92403c7cc11e7263ada7644f6aa9b crypto/modes/asm/ghash-armv4.pl
+097975df63370de7ebea012d17de14fc1f361fb83acf03b432a99ae7d5bceb24 crypto/modes/asm/ghash-c64xplus.pl
+fdde3bc48b37790c6e0006014da71e7a831bbb4fdbfcda2d01dbe0ceb0ba88fa crypto/modes/asm/ghash-ia64.pl
+e472d73d06933667a51a0af973479993eed333c71b43af03095450acb36dbeb4 crypto/modes/asm/ghash-parisc.pl
+6fb4332ac88113a20915ad4de1931ef88b0114b5379b16e1d967820e1229fbb0 crypto/modes/asm/ghash-s390x.pl
+6af1a05981e1d41e4dea51e58938360e3abc4a4f58e179908242466d032b1a8a crypto/modes/asm/ghash-sparcv9.pl
+26f55a57e77f774d17dfba93d757f78edfa3a03f68a71ffa37ccf3bfc468b1e2 crypto/modes/asm/ghash-x86.pl
+72744131007d2389c09665a59a862f5f6bb61b64bd3456e9b400985cb56586b8 crypto/modes/asm/ghash-x86_64.pl
+a4e9f2e496bd9362b17a1b5989aa4682647cefcff6117f0607122a9e11a9dfd9 crypto/modes/asm/ghashp8-ppc.pl
+0029b5beb1d4cd4c5ad47164c23f3e7c9d1eaff66ef54af025ee26795b11a1c7 crypto/modes/asm/ghashv8-armx.pl
+65112dfe63cd59487e7bdb1706b44acfcf48ecede12cc3ae51daa5b661f41f06 crypto/modes/cbc128.c
+1611e73dc1e01b5c2201f51756a7405b7673aa0bb872e2957d1ec80c3530486f crypto/modes/ccm128.c
+d8c2f256532a4b94db6d03aea5cb609cccc938069f644b2fc77c5015648d148d crypto/modes/cfb128.c
+af1c034152d82b29cb7c938c8516cfd136b62bac0908c1d40eb50790d23b288c crypto/modes/ctr128.c
+2413852b46ee90bcbb711c0d4fb79fc6b0cac1f837b4df4896a0003935d4211a crypto/modes/gcm128.c
+bdf25257b15eca206be4d950d2dd807ca5f058f91f54edbd7a0d312ed83eef8e crypto/modes/ofb128.c
+e55a816c356b2d526bc6e40c8b81afa02576e4d44c7d7b6bbe444fb8b01aad41 crypto/modes/wrap128.c
+608a04f387be2a509b4d4ad414b7015ab833e56b85020e692e193160f36883a2 crypto/modes/xts128.c
+8aa2504f84a0637b5122f0c963c9d82773ba248bad972ab92be7169995d162b5 crypto/o_str.c
+8ddbbdf43131c10dcd4428aef0eff2b1e98b0410accada0fad41a4925868beef crypto/packet.c
+a20bfd927d69737c86ca95d3cf636afa8cefd8fe23412d1a3897644a0da21211 crypto/param_build.c
+c2fe815fb3fd5efe9a6544cae55f9469063a0f6fb728361737b927f6182ae0bb crypto/param_build_set.c
+06e67fdd2a308bf355c8dae2e0acd9af94f6e53d428a7d31966311eb5c0aebc1 crypto/params.c
+4fda13f6af05d80b0ab89ec4f5813c274a21a9b4565be958a02d006236cef05c crypto/params_dup.c
+a0097ff2da8955fe15ba204cb54f3fd48a06f846e2b9826f507b26acf65715c3 crypto/params_from_text.c
+b4d34272a0bd1fbe6562022bf7ea6259b6a5a021a48222d415be47ef5ef2a905 crypto/property/defn_cache.c
+7da6ae864beb1a4daa4be31eb41d48141a3a7eb7a263a4937a6889e05656a595 crypto/property/property.c
+66da4f28d408133fb544b14aeb9ad4913e7c5c67e2826e53f0dc5bf4d8fada26 crypto/property/property_local.h
+921305e62749aec22da4843738bee3448b61e7e30d5309beddc7141ad07a8004 crypto/property/property_parse.c
+a7cefda6a117550e2c76e0f307565ce1e11640b11ba10c80e469a837fd1212a3 crypto/property/property_query.c
+065698c8d88a5facc0cbc02a3bd0c642c94687a8c5dd79901c942138b406067d crypto/property/property_string.c
+9653ec9c1476350a94b9cc7f8be3d99961fd803870c9ac03315298d2909a6a8e crypto/provider_core.c
+d0af10d4091b2032aac1b7db80f8c2e14fa7176592716b25b9437ab6b53c0a89 crypto/provider_local.h
+5ba2e1c74ddcd0453d02e32612299d1eef18eff8493a7606c15d0dc3738ad1d9 crypto/provider_predefined.c
+a5a4472636b8b0095ad8d4acd37e275ad79da1a67ecff7b7b5c3e46c9ebc65b7 crypto/rand/rand_lib.c
+fd03b9bb2c23470fa40880ed3bf9847bb17d50592101a78c0ad7a0f121209788 crypto/rand/rand_local.h
+f0c8792a99132e0b9c027cfa7370f45594a115934cdc9e8f23bdd64abecaf7fd crypto/rsa/rsa_acvp_test_params.c
+9e7dd6fc91d3266d4aa4f0f41b7986381122b7d98114e63ebf04c5ee298b5fda crypto/rsa/rsa_backend.c
+38a102cd1da1f6ca5a46e6a22f018237964336274385f5c70cbedcaa6997647e crypto/rsa/rsa_chk.c
+e32cfa04221a2a3ea33f7bcb93ee51b84cbeba97e94c1fbf6e420b24f97fc9ce crypto/rsa/rsa_crpt.c
+e995da1c2e5007bd7f5907f369fe45ed15f4e657143a85078c755bd5e6863d0b crypto/rsa/rsa_gen.c
+74ed75d1d8e0844800504a137bfd81c3dbcb6c4bd58b5d5fe9d0a362092b6e88 crypto/rsa/rsa_lib.c
+a65e85be5269d8cb88e86b3413c978fa8994419a671092cbf104ff1a08fda23b crypto/rsa/rsa_local.h
+cf0b75cd54b61b9b9a290ef18d0ddce9fb26a029a54eb3f720d9b25188440f00 crypto/rsa/rsa_mp_names.c
+5c60f6e05db82e13178d805deb1947b8eee4a905e6e77523d3b288da70a46bb5 crypto/rsa/rsa_none.c
+33de2accc3af530fd0a4758eb83d5e1d994bf49bac4512b01387dbae656e1a7d crypto/rsa/rsa_oaep.c
+178c98421b54ec50ee55470a7b1acb771ed22efef2c2c0e059544baa7e6d387e crypto/rsa/rsa_ossl.c
+be3f39c1fcb777d6c0122061f9ef735d10a6bee95d67fcc1ca6ae2a664022d2b crypto/rsa/rsa_pk1.c
+174a42e156be48927fe6d6bf0d95575619b8e643a99761275bff933bc3449722 crypto/rsa/rsa_pss.c
+bf6d300b7e7e9e512a47c5bd1f8713806ae3033a140d83dfae4a16ad58d11170 crypto/rsa/rsa_schemes.c
+f01af62704dbf9457e2669c3e7c1d4d740f0388faa49df93611b987a8aa2bf11 crypto/rsa/rsa_sign.c
+740c022caff3b2487c5838b581cdddcc7de2ceabb504aad72dc0dd70a67bf7cf crypto/rsa/rsa_sp800_56b_check.c
+20e54cf2a8fd23ced0962c5f358cedd8ec0c398a87d33b34f1a4326d11e4892e crypto/rsa/rsa_sp800_56b_gen.c
+1c1c2aeeb18bf1d69e8f134315b7e50d8f43d30eb1aa5bf42983eec9136a2fdc crypto/rsa/rsa_x931.c
+5fa59240ca885cbc0c1cd026934b226d44fc9c3fdf0c2e7e3a7bd7f4963ca2e5 crypto/self_test_core.c
+05c533fde7fdba0c76103e97d881b7224c8427451b453e2f6413552996063e31 crypto/sha/asm/keccak1600-armv4.pl
+ca3b2b654f9a8c4bc2fa2538c1f19d17acd4a6b9e0df6a4b81df04efa697e67e crypto/sha/asm/keccak1600-armv8.pl
+ef575a7fb4956cc3be4ef10a6aeaa10702eadfc92c86167880690320ce942b26 crypto/sha/asm/keccak1600-avx2.pl
+f1dcf75789dfb0c5d7cd35988cb8046f60097bbaf1fbdab32a9269fa5492214c crypto/sha/asm/keccak1600-avx512.pl
+63e547b100562d1142512d5b54e16efc276ecb6c743c27873dbcdd7cb917c828 crypto/sha/asm/keccak1600-avx512vl.pl
+33bdcc6f7668460c3bdf779633e43bfad62b937042a73acb007b462fc5b0a034 crypto/sha/asm/keccak1600-c64x.pl
+09fc831dd39bd90a701e9b16d9e9987cc215252a22e1e0355f5da6c495fca35a crypto/sha/asm/keccak1600-mmx.pl
+ce4a58129e5ee3ac4c9dfec5ecc010440570ebf7bf869e3e9977f2121a64b27a crypto/sha/asm/keccak1600-ppc64.pl
+a859fc8cb073b2d0012a93f3155a75fb6eb677441462b0de4f8cf8df1445e970 crypto/sha/asm/keccak1600-s390x.pl
+618dcd4891b4064d3b8aa6dcd74bea7ef55f4962a64957b05a05448f6e3e0f17 crypto/sha/asm/keccak1600-x86_64.pl
+831b8b02ab25d78ba6300ce960d96c13439bfba5844e13061e19c4e25cbacc3d crypto/sha/asm/keccak1600p8-ppc.pl
+75d832db9bf0e98e7a5c522169060a6dd276c5118cfb297fc3f1111f55cd4007 crypto/sha/asm/sha1-586.pl
+c96e87d4f5311cd73bbdf499acc03418588be12426d878e157dd67e0099e0219 crypto/sha/asm/sha1-alpha.pl
+4ba6d1c7f12fe76bf39babea966f0a4b7f8769e0c0510cbfc2c46a65dd62d45c crypto/sha/asm/sha1-armv4-large.pl
+efc69cb0d867b7fac6b3fa8985c343d1f984d552bc8e75bbbbace0adf9ee5f15 crypto/sha/asm/sha1-armv8.pl
+11d332b4e058e9fa418d6633316d2e9f9bf520a08b2d933e877bdf38b2edefcf crypto/sha/asm/sha1-c64xplus.pl
+32ff0e701a7b8f25bcfe8477b20795de54f536527bd87d3ce694fd9aaae356d4 crypto/sha/asm/sha1-ia64.pl
+471c27efca685b2a82ad7fefe329ca54172df9f49b9785da6d706b913b75e693 crypto/sha/asm/sha1-mb-x86_64.pl
+0f5c63cf09e950d1b488935ab3b5562e3e9d5cd1a563fb88a41e3dae90a35e6d crypto/sha/asm/sha1-mips.pl
+b5ffd7b6dbb04c05de7efa2945adb67ea845e7e61a3bf163a532f7b6acdf4267 crypto/sha/asm/sha1-parisc.pl
+482cd23ca6ec38d6f62b90c68f9f20643579c50f2c0fbb0dab1c10a0e35efe77 crypto/sha/asm/sha1-ppc.pl
+28cf69efd53d7a5a8c32e0f8db32c193f41b91faf44f5f59944334bc3f5aa337 crypto/sha/asm/sha1-s390x.pl
+7fd355b412ddfa1c510e0ba3284f75b1c0d621b6db2ecb1d2a935d5cdb706628 crypto/sha/asm/sha1-sparcv9.pl
+24554e68b0e7b7db7b635ff149549015f623ca0bcd9ae90439586a2076f6ae80 crypto/sha/asm/sha1-sparcv9a.pl
+74d197cdd72400cabbff7e173f72c8976723081508b095dc995e8cd1abf3daa6 crypto/sha/asm/sha1-thumb.pl
+a59a86293e28f5600609dc8af2b39c5285580ae8636520990b000eeeb67bb889 crypto/sha/asm/sha1-x86_64.pl
+c099059ef107f548ea2c2bab64a4eb8c277070ce6d74c4d32bb9808dc19c5fa3 crypto/sha/asm/sha256-586.pl
+b9cee5c5a283f61f601d2dba68a7a76e7aba10bfafffc1a5c4987f9c0aa6f87d crypto/sha/asm/sha256-armv4.pl
+93ddc97651ee3e779144a3c6b3e46a1bc4aa81e75cd7b9df068a2aef8743d25f crypto/sha/asm/sha256-c64xplus.pl
+8be5c5d69733ecb16774aa8410b4bcb3623a9f060d2be103d8aa67bf6e4c5843 crypto/sha/asm/sha256-mb-x86_64.pl
+dd82e1311703abb019975fc7b61fb87d67e1ed916dddd065aced051e851114b9 crypto/sha/asm/sha512-586.pl
+8d84164f3cfd53290c0c14bb5655510b7a9238857866328c0604d64b4e76fe21 crypto/sha/asm/sha512-armv4.pl
+dadacb6d66b160913bffb4e1a6c3e5f7be6509b26e2c099701d8d3fdb92c1be0 crypto/sha/asm/sha512-armv8.pl
+6f548a088feae3b6faa179653ba449df9d3f5cda1e0561e5b5f120b32274d1eb crypto/sha/asm/sha512-c64xplus.pl
+9fa54fbc34fd881f4b344374b9b4f8fb15b641424be7af9a31c71af89ae5d577 crypto/sha/asm/sha512-ia64.pl
+fb06844e7c3b014a58dccc8ec6020c71843cfdc5be08288bc7d204f0a840c474 crypto/sha/asm/sha512-mips.pl
+11548f06d213947104a80898e000218ec0d6ff3f6913f6582de498476482ce9f crypto/sha/asm/sha512-parisc.pl
+7c0c490ce6bb11a228853aecad5e164ce84e5bdabb8a6658ae7184782076c7d3 crypto/sha/asm/sha512-ppc.pl
+38e0455fd6a2b93a7a5385379ca92bc6526585ca1eb4af365fac4c78f7285c72 crypto/sha/asm/sha512-s390x.pl
+0611845c52091b0208dd41f22ddef9dd1e68d3d92fa4c4360738b840a6314de6 crypto/sha/asm/sha512-sparcv9.pl
+f64d16c1e5c3fa4a7969de494a8372127502171a517c14be7a1e3a43a7308699 crypto/sha/asm/sha512-x86_64.pl
+8725cabb8d695c576619f19283b034074a3fa0f1c0be952a9dbe9793be15b907 crypto/sha/asm/sha512p8-ppc.pl
+57f6cf54b1b5d2cac7a8f622b7b6bd1878f360fff3fa0f02352061c24162ebbb crypto/sha/keccak1600.c
+306cacd3f86e5cacaca74c58ef862516515e5c0cafaff48636d537fd84f1c2fb crypto/sha/sha1dgst.c
+4d8cf04f5806611e7586aab47fb28165ec1afb00168e2c9876bb36cb5c29bf8b crypto/sha/sha256.c
+3d972a11be18bfbfcd45790028635d63548bfe0a2e45d2fc56b6051b759d22f0 crypto/sha/sha3.c
+8038a5a97f826f519424db634be5b082b3f7eca3ccb89875ca40fa6bd7dfdcfd crypto/sha/sha512.c
+6c6f0e6069ac98e407a5810b84deace2d1396d252c584703bcd154d1a015c3ea crypto/sha/sha_local.h
+c50c584c55e56347bb43aca4b796b5344d70daece3061f586b79c871c21f5d1a crypto/sparse_array.c
+8da78169fa8c09dc3c29c9bf1602b22e88c5eac4815e274ba1864c166e31584b crypto/stack/stack.c
+7b4efa594d8d1f3ecbf4605cf54f72fb296a3b1d951bdc69e415aaa08f34e5c8 crypto/threads_lib.c
+a41ae93a755e2ec89b3cb5b4932e2b508fdda92ace2e025a2650a6da0e9e972c crypto/threads_none.c
+2637a8727dee790812b000f2e02b336f7907949df633dda72938bbaafdb204fe crypto/threads_pthread.c
+7959c65c27280cdb1166a30a27c931befd6cfa4ed109094c40eb5a6d253c790c crypto/threads_win.c
+fd6c27cf7c6b5449b17f2b725f4203c4c10207f1973db09fd41571efe5de08fd crypto/x86_64cpuid.pl
+0a9c484f640d96e918921f57f592e82e99ccdbe35d3138d64b10c7af839e9a07 e_os.h
+6f353dc7c8c4d8f24f7ffbf920668ccb224ebb5810805a7c80d96770cd858005 include/crypto/aes_platform.h
+8c6f308c1ca774e6127e325c3b80511dbcdc99631f032694d8db53a5c02364ee include/crypto/asn1_dsa.h
+f49a26fc4348f3b79507dc4a04fade82cf870f7c22e6c977f402c859fdd1b98b include/crypto/bn.h
+1c46818354d42bd1b1c4e5fdae9e019814936e775fd8c918ca49959c2a6416df include/crypto/bn_conf.h.in
+7a43a4898fcc8446065e6c99249bcc14e475716e8c1d40d50408c0ab179520e6 include/crypto/bn_dh.h
+e69b2b20fb415e24b970941c84a62b752b5d0175bc68126e467f7cc970495504 include/crypto/cryptlib.h
+6c72cfa9e59d276c1debcfd36a0aff277539b43d2272267147fad4165d72747c include/crypto/ctype.h
+89693e0a7528a9574e1d2f80644b29e3b895d3684111dd07c18cc5bed28b45b7 include/crypto/des_platform.h
+daf508bb7ed5783f1c8c622f0c230e179244dd3f584e1223a19ab95930fbcb4f include/crypto/dh.h
+20d99c9a740e4d7d67e23fa4ae4c6a39d114e486c66ad41b65d91a8244cd1dea include/crypto/dsa.h
+2ea47c059e84ce9d14cc31f4faf45f64d631de9e2937aa1d7a83de5571c63574 include/crypto/ec.h
+edbfae8720502a4708983b60eac72aa04f031059f197ada31627cb5e72812858 include/crypto/ecx.h
+9dab9af8b0a657fe5de46375b71aefcad7e98af272b69ed69c7c104e9e057414 include/crypto/evp.h
+bbe5e52d84e65449a13e42cd2d6adce59b8ed6e73d6950917aa77dc1f3f5dff6 include/crypto/lhash.h
+162812058c69f65a824906193057cd3edeabc22f51a4220aea7cb9064379a9b6 include/crypto/md32_common.h
+f12bfc145290444bcc7bf408874bded348e742443c145b8b5bc70ae558d96c31 include/crypto/modes.h
+f326212c978576c5346c89ae0336c2428594494b54054f6045b1f1038bfbc004 include/crypto/rand.h
+90930fc8788d6e04e57829346e0405293ac7a678c3cef23d0692c742e9586d09 include/crypto/rand_pool.h
+306abf9d327a9e63fff2cdef730275abc4d2781254a032b1f370f3428eb5a2ef include/crypto/rsa.h
+32f0149ab1d82fddbdfbbc44e3078b4a4cc6936d35187e0f8d02cc0bc19f2401 include/crypto/security_bits.h
+0f743762f646656b5480648c05632575fe8acc7506460c63e0fcdf42cf20c08a include/crypto/sha.h
+7676b02824b2d68df6bddeb251e9b8a8fa2e35a95dad9a7ebeca53f9ab8d2dad include/crypto/sparse_array.h
+7ad02c7de77304c3b298deeb038ab2550cf8b2bce03021994477c6c43dbcf86e include/crypto/types.h
+782a83d4e489fd865e2768a20bfa31e78c2071fd0ceeb9eb077276ae2bcc6590 include/internal/bio.h
+92aacb3e49288f91b44f97e41933e88fe455706e1dd21a365683c2ab545db131 include/internal/constant_time.h
+c5bb97f654984130c8b44c09a52395bce0b22985d5dbc9c4d9377d86283f11f8 include/internal/core.h
+0b572801dfb8a41cc239e3439f8097a0ad11bbdf5d54811d10ceba3175cf2f17 include/internal/cryptlib.h
+9571cfd3d5666749084b354a6d65adee443deeb5713a58c098c7b03bc69dbc63 include/internal/deprecated.h
+3325b895d15c0a6341f456a8d866a0f83e80fc8a31a01c34fcfd717715b33075 include/internal/der.h
+fd1722d6b79520ee4ac477280d5131eb1b744c3b422fd15f5e737ef966a97c3b include/internal/dso.h
+f144daebef828a5bd4416466257a50f06b894e0ce0adf1601aa381f34f25a9e7 include/internal/dsoerr.h
+70d3e0d5a1bd8db58dcc57bea4d1c3ed816c735fe0e6b2f4b07073712d2dc5ef include/internal/endian.h
+094b69aeb8f349cafa8865b577e253132088c25eabb61b910fab141e6f7d2929 include/internal/ffc.h
+100053a1bad1a85a98c5b919cf81ace0ee147b2164732963e40474d7b5fbbb99 include/internal/namemap.h
+b02701592960eb4608bb83b297eed90184004828c7fc03ea81568062f347623d include/internal/nelem.h
+ae41a2fb41bf592bbb47e4855cf4efd9ef85fc11f910a7e195ceef78fb4321dc include/internal/numbers.h
+b89cca3b727d4526b459246de11e768a20333555bf3a9ed9a9b8beb2b565dc7f include/internal/packet.h
+dd7ddecf30bef3002313e6b776ce34d660931e783b2f6edacf64c7c6e729e688 include/internal/param_build_set.h
+d4ac19b28ea61f03383364cfad1e941cac44fc36787d80882c5b76ecc9d34e29 include/internal/property.h
+727326afb3d33fdffdf26471e313f27892708318c0934089369e4b28267e2635 include/internal/propertyerr.h
+6a899ef3e360c7144d84d3c3dbbd14aa457f5d38b83b13c0be7ec7f372076595 include/internal/provider.h
+5af9a40c44def13576fe2c0eb082fb73c3565c5e00f902d51b1ed1593d481ccb include/internal/refcount.h
+11ee9893f7774c83fcfdee6e0ca593af3d28b779107883553facdbfdae3a68f5 include/internal/sha3.h
+494ab5c802716bf38032986674fb094dde927a21752fe395d82e6044d81801d1 include/internal/sizes.h
+24f41a1985fa305833c3f58030c494d2563d15fc922cdf3eeb6a7ea8c135a880 include/internal/symhacks.h
+640cc6a2aae208073a7f495c08b4c5006a69e8ac1c2d9aaaafd56b0e74d5f859 include/internal/thread_once.h
+415b725d7f949a6191ab7bb30b48931bafc01c7aa93607e529fabbc853a4ddc5 include/internal/tlsgroups.h
+fc0f9199487ef278b9fd317d1572db3e3fb95e182055f0e49c4d8faf78ed7dd2 include/internal/tsan_assist.h
+2b38fb6e65d549aca3b2c76907daf67124f395251c0261dec26faa54da8d6d73 include/openssl/aes.h
+98aa2fc5eae9ef2a36d3d0053212696d58893baa083fa1fcf720660fb4bc0a9f include/openssl/asn1.h.in
+d4733dcd490b3a2554eaf859d1ea964fe76f7d24f78e42be1094bdad6dee7429 include/openssl/asn1err.h
+1550474ee05423896ec4abfb6346f1bc44c7be22329efac9ea25de10e81d549c include/openssl/asn1t.h.in
+2cd8163cdc6c93386bc05e8ed983e5ca604d0bf9da65500cab736cfa8bc2b048 include/openssl/bio.h.in
+0a26138aaded05cafe2326e11fdc19b28408e054cfe3dda40d45ef95ce8136b0 include/openssl/bioerr.h
+7d1f9880976a926ba6e0cad08e8de6f326aae48d8350b499aa79127f63d4d108 include/openssl/bn.h
+9ad8b04764797f5138f01f549ba18b44cf698ffc7fe795fef42c1822d84a6ff4 include/openssl/bnerr.h
+93954e6c450716e158948d67f64736a451ea9473d02f3a908f3bc8a96cf049a5 include/openssl/buffer.h
+9d48e6cab2ee98ae94d7113e4c65f000d97e125fdb3445642865ace3f34d06ac include/openssl/buffererr.h
+8e772c24b051e59d2f65339f54584e3e44165a3eaf997d497faea764990130f5 include/openssl/cmac.h
+55aa91482d327d1784484922389e8277bdcdff7a7df27e84200d5c908bd40454 include/openssl/conf.h.in
+f20c3c845129a129f5e0b1dae970d86a5c96ab49f2e3f6f364734521e9e1abe3 include/openssl/conferr.h
+02a1baff7b71a298419c6c5dcb43eaa9cc13e9beeb88c03fb14854b4e84e8862 include/openssl/configuration.h.in
+6b3810dac6c9d6f5ee36a10ad6d895a5e4553afdfb9641ce9b7dc5db7eef30b7 include/openssl/conftypes.h
+df5e60af861665675e4a00d40d15e36884f940e3379c7b45c9f717eaf1942697 include/openssl/core.h
+00110e80b9b4f621c604ea99f05e7a75d3db4721fc2779224e6fa7e52f06e345 include/openssl/core_dispatch.h
+cbd9d7855ca3ba4240207fc025c22bbfef7411116446ff63511e336a0559bed0 include/openssl/core_names.h
+194f96a30bdc4dab3f65693c09326ef53c54ebfd613c2513d8258a0aa35a6996 include/openssl/crypto.h.in
+1d1697bd3e35920ff9eaec23c29472d727a7fc4d108150957f41f6f5ecf80f1a include/openssl/cryptoerr.h
+bbc82260cbcadd406091f39b9e3b5ea63146d9a4822623ead16fa12c43ab9fc6 include/openssl/cryptoerr_legacy.h
+fa3e6b6c2e6222424b9cd7005e3c5499a2334c831cd5d6a29256ce945be8cb1d include/openssl/des.h
+3a57eceec58ab781d79cb0458c2251a233f45ba0ef8f414d148c55ac2dff1bc8 include/openssl/dh.h
+836130f5a32bbdce51b97b34758ed1b03a9d06065c187418eaf323dca6adfc6d include/openssl/dherr.h
+92ae2c907fd56859e3ae28a085071611be5c9245879305cdf8bad027219e64b6 include/openssl/dsa.h
+335eb40a33cd1e95e7783bda2d031ec2bcf02cff8aa804ba3484d1354452b7ea include/openssl/dsaerr.h
+41bf49e64e1c341a8c17778147ddeba35e88dfd7ff131db6210e801ef25a8fd5 include/openssl/e_os2.h
+bc9ec2be442a4f49980ba2c63c8f0da701de1f6e23d7db35d781658f833dd7b9 include/openssl/ebcdic.h
+33b6321d1c6b7b1621198346946401bb81472054aa236b03c6f22f247248d2ad include/openssl/ec.h
+dad1943d309aaadb800be4a3056096abec611d81982b83c601b482405e11d5c0 include/openssl/ecerr.h
+61c76ee3f12ed0e42503a56421ca00f1cb9a0f4caa5f9c4421c374bcd45917d7 include/openssl/encoder.h
+69dd983f45b8ccd551f084796519446552963a18c52b70470d978b597c81b2dc include/openssl/encodererr.h
+c6ee8f17d7252bdd0807a124dc6d50a95c32c04e17688b7c2e061998570b7028 include/openssl/err.h.in
+12ec111c0e22581e0169be5e1838353a085fb51e3042ef59a7db1cee7da73c5b include/openssl/evp.h
+5bd1b5dcd14067a1fe490d49df911002793c0b4f0bd4492cd8f71cfed7bf9f2a include/openssl/evperr.h
+5381d96fe867a4ee0ebc09b9e3a262a0d7a27edc5f91dccfb010c7d713cd0820 include/openssl/fips_names.h
+b1d41beba560a41383f899a361b786e04f889106fb5960ec831b0af7996c9783 include/openssl/fipskey.h.in
+47a088c98ad536ea99f2c6a9333e372507cb61b9bdffb930c586ed52f8f261eb include/openssl/hmac.h
+faab8accc9520269dd874126ae164a43526d5784e6280521c7ab3772c02b0a0c include/openssl/kdf.h
+c6db6926e90c9efd530a7bdb018be8c62f2c2b3c2f7b90228e9f73b8437dd785 include/openssl/lhash.h.in
+fd5c049ac6c3498750fa8f8dcbf88b2a31c02fa62dfe43a33d7b490fb86f61c8 include/openssl/macros.h
+9184207c562fd1fa7bd3a4f1fadcb984130561279818f0cdfcf3e9c55be8a7d1 include/openssl/modes.h
+7c71200e35f4cc1b4011a4bc14e521e4dc037b9b2d640a74bc30ef334b813de3 include/openssl/obj_mac.h
+157797b450215f973eb10be96a04e58048ab9c131ad29427e80d0e37e230ed98 include/openssl/objects.h
+d25537af264684dff033dd8ae62b0348f868fcfec4aa51fa8f07bcfa4bd807ad include/openssl/objectserr.h
+fe6acd42c3e90db31aaafc2236a7d30ebfa53c4c07ea4d8265064c7fcb951970 include/openssl/opensslconf.h
+1bf52d136e94f727a96651c1f48ad040482f35dae152519ccd585efd410b92f0 include/openssl/opensslv.h.in
+767d9d7d5051c937a3ce8a268c702902fda93eeaa210a94dfde1f45c23277d20 include/openssl/param_build.h
+30085f4d1b4934bb25ffe7aa9a30859966318a1b4d4dcea937c426e90e6e1984 include/openssl/params.h
+097615b849375e2903967521f76c570512e5be47b8159fdbcd31e433f8a4cca7 include/openssl/prov_ssl.h
+bdadffba7b7b8294c9f7450ce2563ae31145ca0f196f5ce7b8c2f19ed7fba816 include/openssl/proverr.h
+b97e8ad49b38683817387596aefec0abd5f4d572643beef48be4f7acba26768d include/openssl/provider.h
+7c9b5f479d9b22cfc8db0976dddfc2a1ee6e757b436e01a2b4d2744bcb6d81a5 include/openssl/rand.h
+108966f56c82fedff53df76a4aa7861c82be4db1fd1ddafb59dc086ea155831c include/openssl/randerr.h
+c1015b77c444a3816d2ea7ad770f1c3b79a1e54887930af6dd662895701f3323 include/openssl/rsa.h
+2f339ba2f22b8faa406692289a6e51fdbbb04b03f85cf3ca849835e58211ad23 include/openssl/rsaerr.h
+6586f2187991731835353de0ffad0b6b57609b495e53d0f32644491ece629eb2 include/openssl/safestack.h.in
+af5cc56fb31161ccd87cf925f3d3f22119dfbca78bc39a2e2d65d78bfcf0f0c6 include/openssl/self_test.h
+2964274ab32b1ba8578a06b06663db2eda4317ae806369271d889176bb5a7d04 include/openssl/sha.h
+c169a015d7be52b7b99dd41c418a48d97e52ad21687c39c512a83a7c3f3ddb70 include/openssl/stack.h
+22d7584ad609e30e818b54dca1dfae8dea38913fffedd25cd540c550372fb9a6 include/openssl/symhacks.h
+5e452bf61d802fdf7b6a65d1c8a1e3f72a7885e4bf2f521eca6443cea69f4ce5 include/openssl/trace.h
+873d2ec2054ec24c52df4abe830cb2b9666fe4e75cc62b4de0f50ef9d20c5812 include/openssl/types.h
+c0a9551efccf43f3dd748d4fd8ec897ddaabbc629c00ec1ad76ce983e1195a13 providers/common/bio_prov.c
+4546387d6642603c81ec4cd8d5fc4af8ba60ac7359eb6f31e7d24827031e68ad providers/common/capabilities.c
+f94b7435d4ec888ec30df1c611afa8b9eedbb59e905a2c7cb17cfc8c4b9b85b8 providers/common/der/der_digests_gen.c.in
+424d7b2ece984a0904b80c73e541400c6e2d50a285c397dd323b440a4f2a8d8e providers/common/der/der_dsa_gen.c.in
+27ff361a5fbfc97cd41690ab26639708961d0507b60912f55f5919649842c6ae providers/common/der/der_dsa_key.c
+2529d253b3e45c33249461fdedb2c32b3c16a7a305fe4920f2a79e7b3f16ed3f providers/common/der/der_dsa_sig.c
+a81d36446eb8afa5c2318e24b86b52647059b4721ee52309b741e4ee78af29dd providers/common/der/der_ec_gen.c.in
+b8f2f94daeaf20c636c90e386284c246cfded0c8275411fa02fe68b534520b95 providers/common/der/der_ec_key.c
+9104cd39dddd6e1a6e8f267656482131f4d0765e96fdced1f7344817a1c8ed7e providers/common/der/der_ec_sig.c
+03a5620654438c58a8f971398e68922a3f33a519e2c92edb141d13ef4cbc4651 providers/common/der/der_ecx_gen.c.in
+f3b089fd3dcccc8e3ebfbbdbf87c47d58330f82bd0e2a1223da74977930cccf1 providers/common/der/der_ecx_key.c
+5b3b0ae8da0fad1f7ba8b5fba2206210884728bf69a8aa00644036eb51953467 providers/common/der/der_rsa_gen.c.in
+029aec80a45b477f7c8bd8d24d48e36de92f8056b421e9f128c336dc246dbc4e providers/common/der/der_rsa_key.c
+7e8d579986f53eaf1875d677e5cf4adfd4ccf79db0275368f6cac580ab6007ca providers/common/der/der_rsa_sig.c
+0b18bc007f296e16f6210956f5b6ab612b77d8a95170f12ae32764125901db6d providers/common/der/der_wrap_gen.c.in
+d447cd774869da68a2cc0bbb19c547ee6ed4858c7aee1f3d5bba7796f97823a9 providers/common/digest_to_nid.c
+440c8ce0a4ca9f63157202bbfa26e12fec25847215fbae3416274124604ada6e providers/common/include/prov/bio.h
+18ce379903b078446945da9116026da8639b4b0d81d357f86f9674a2a5cb94ef providers/common/include/prov/der_digests.h.in
+c0a020765feb7ededc7e6f20b2b140dca09f347cc72404a5c7971df82b2f9ad0 providers/common/include/prov/der_dsa.h.in
+6024645ac9e165685b0a44a20feb342355eb06c07b7c7954508a125348570aea providers/common/include/prov/der_ec.h.in
+5b6b7d8d12011c48195b7db8f65bc4bc4a48fb753763a3ce5006dc227b5139d7 providers/common/include/prov/der_ecx.h.in
+ce605f32413b09d33ce5795de9498a08183895c3347f33344f9ae5d31c29ccac providers/common/include/prov/der_rsa.h.in
+6c1fa3f229c6f049c3ac152c4c265f3eb056d94221b82df95a15400649690e93 providers/common/include/prov/der_wrap.h.in
+76087f04f4de6414c240f88807659fb2a04af914108f0c5f2515a4cb5482f655 providers/common/include/prov/proverr.h
+83a57505d88a6a9cc4f7781c9f7f4af07668e7923502dfd6c5960bb492c1d24e providers/common/include/prov/provider_ctx.h
+03fcfea9ed6e23d1df7ffd230af15f0f9b91a6aa635f77b9cbe52d5112168d09 providers/common/include/prov/provider_util.h
+e1ef8b2be828a54312d6561b37751a5b6e9d5ebdb6c3e63589728c3d8adca7dc providers/common/include/prov/providercommon.h
+73d0e15963759fcb7c5c434bb214b50bc32f6066e90ac07fb53dad11c2fd1939 providers/common/include/prov/securitycheck.h
+737cc1228106e555e9bab24e3c2438982e04e05b0d5b9ee6995d71df16c49143 providers/common/provider_ctx.c
+a8b73b10ab0100942dd2bc45f2fc9c9238b70bec0e49708ba113bc7479c8b92a providers/common/provider_err.c
+9eae3e2cac89c7b63d091fdca1b6d80c5c5d52aa79c8ba4ce0158c5437ad62f3 providers/common/provider_seeding.c
+eec462d685dd3b4764b076a3c18ecd9dd254350a0b78ddc2f8a60587829e1ce3 providers/common/provider_util.c
+ba345b0d71f74c9e3d752579e16d11cc70b4b00faa329cc674bc43dd2620e044 providers/common/securitycheck.c
+527eda471e26763a5fcf123b2d290234d5c836de7b8ef6eef2166ef439919d82 providers/common/securitycheck_fips.c
+abd5997bc33b681a4ab275978b92aebca0806a4a3f0c2f41dacf11b3b6f4e101 providers/fips/fips_entry.c
+0f761a26c8fa6ad8d5a15c817afe1741352b21769b2164a2eb7dd50e1f6fe04f providers/fips/fipsprov.c
+52b48aece6aa3592593c94b53326410c75efb95ac480697ce414679446b49943 providers/fips/self_test.c
+f822a03138e8b83ccaa910b89d72f31691da6778bf6638181f993ec7ae1167e3 providers/fips/self_test.h
+d3c95c9c6cc4e3b1a5e4b2bfb2ae735a4109d763bcda7b1e9b8f9eb253f79820 providers/fips/self_test_data.inc
+629f619ad055723e42624230c08430a3ef53e17ab405dc0fd35499e9ca4e389c providers/fips/self_test_kats.c
+6b082c1af446ef9a2bfe68a9ee4362dfa4f1f09f975f11f9ba2e5010493039c6 providers/implementations/asymciphers/rsa_enc.c
+4db1826ecce8b60cb641bcd7a61430ec8cef73d2fe3cbc06aa33526afe1c954a providers/implementations/ciphers/cipher_aes.c
+f9d4b30e7110c90064b990c07430bb79061f4436b06ccaa981b25c306cfbfaa2 providers/implementations/ciphers/cipher_aes.h
+89378cce6d31e8c2f221f9f29d0b17622624eb83e4ecec8465f7641f68352917 providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c
+7668e5c1cac474ad7b0f28aa78ca885edf44815fe4a606a6cd328b3c02fac25a providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.h
+26e0f28523b416ba4067e471061f5a11fd76f5dc8bfe57ce37a137cf5667630b providers/implementations/ciphers/cipher_aes_cbc_hmac_sha1_hw.c
+6d2ab2e059ef38fad342d4c65eebd533c08a2092bb174ff3566c6604e175c5a4 providers/implementations/ciphers/cipher_aes_cbc_hmac_sha256_hw.c
+6d6bf36329af3b77f457898294be05fea3940a61cdaf0ed60cfb8d091a94186e providers/implementations/ciphers/cipher_aes_ccm.c
+00f36bf48e522dbb5ec71df0ec13e387955fa3672e6ff90e8a412ae95c4a642f providers/implementations/ciphers/cipher_aes_ccm.h
+6337b570e0dc4e98af07aa9704254d3ab958cf605584e250fbd76cd1d2a25ac7 providers/implementations/ciphers/cipher_aes_ccm_hw.c
+302b3819ff9fdfed750185421616b248b0e1233d75b45a065490fe4762b42f55 providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc
+a8eaca99a71521ff8ac4ffcf08315e59220f7e0b7f505ecddad04fadd021ec14 providers/implementations/ciphers/cipher_aes_cts.inc
+710ee60704dd9dffa2a11e2e96596af1f7f84f915cedcedeec7292e0d978317a providers/implementations/ciphers/cipher_aes_gcm.c
+79f5a732820d2512a7f4fc2a99ece7e6e2523a51e62561eb67a4b70d5538b0c4 providers/implementations/ciphers/cipher_aes_gcm.h
+ab298c5f89f3165fa11093fad8063b7bcbff0924b43fb3107148ae66d54adcb5 providers/implementations/ciphers/cipher_aes_gcm_hw.c
+8ed4a100e4756c31c56147b4b0fab76a4c6e5292aa2f079045f37b5502fd41b9 providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc
+4c6f3a2818754a5aa7b6db36dae53e248504f9e82cc5af2ed68c723903d4f9d5 providers/implementations/ciphers/cipher_aes_hw.c
+89de794c090192459d99d95bc4a422e7782e62192cd0fdb3bdef4128cfedee68 providers/implementations/ciphers/cipher_aes_hw_aesni.inc
+0264d1ea3ece6f730b342586fb1fe00e3f0ff01e47d53f552864df986bf35573 providers/implementations/ciphers/cipher_aes_ocb.c
+88138a1aff9705e608c0557653be92eb4de65b152555a2b79ec8b2a8fae73e8f providers/implementations/ciphers/cipher_aes_ocb.h
+855869ab5a8d7a61a11674cfe5d503dfa67f59e7e393730835d1d8cf0ab85c70 providers/implementations/ciphers/cipher_aes_ocb_hw.c
+a872195161ac6c3a2cb59c3d15b212e34bb7596a41712258f5d0b5e771e25239 providers/implementations/ciphers/cipher_aes_wrp.c
+527ff9277b92606517ee7af13225a9d5fcffbbc36eb18bce39f59d594cbe4931 providers/implementations/ciphers/cipher_aes_xts.c
+c4a2499b214d7cf786dafaaee5c8c6963b3d5d1c27c144eec4b460f839074a3b providers/implementations/ciphers/cipher_aes_xts.h
+281157d1da4d7285d878978e6d42d0d33b3a6bc16e3bc5b6879e39093a7d70da providers/implementations/ciphers/cipher_aes_xts_fips.c
+f358c4121a8a223e2c6cf009fd28b8a195520279016462890214e8858880f632 providers/implementations/ciphers/cipher_aes_xts_hw.c
+46ba8271917b53fd8fdf77aee19cc326a219c950b94e043d6d118dcac25ad7ad providers/implementations/ciphers/cipher_cts.c
+74640ce402acc704af72e055fb7f27e6aa8efd417babc56f710478e571d8631c providers/implementations/ciphers/cipher_cts.h
+fcc3bb0637864252402aaa9d543209909df9a39611127f777b168bc888498dc0 providers/implementations/ciphers/cipher_tdes.c
+77709f7fc3f7c08986cd4f0ebf2ef6e44bacb975c1483ef444b3cf5e5071f9d6 providers/implementations/ciphers/cipher_tdes.h
+9e07260067083c76d26eb0dd8a8bb4a8dac678812644ff88951a0661be70d9fd providers/implementations/ciphers/cipher_tdes_common.c
+50645122f08ef4891cd96cace833bd550be7f5278ab785515fd61fe8993c8c25 providers/implementations/ciphers/cipher_tdes_hw.c
+6bb3c24bfd872e3b4c779b29e9f962348f6ae3effeb4f243c8ea66abefe8a4fa providers/implementations/ciphers/ciphercommon.c
+dd72ea861edf70b94197821ceb00e07165d550934a2e851d62afa5034b79f468 providers/implementations/ciphers/ciphercommon_block.c
+4b4106f85e36eb2c07acc5a3ca5ccd77b736b3ac46cc4af786cf57405ecd54b2 providers/implementations/ciphers/ciphercommon_ccm.c
+8b6828f188c2590c7d9c6cac13fa0eb6d38a522b0f2859e7c8a766580fa9b66e providers/implementations/ciphers/ciphercommon_ccm_hw.c
+3b83f58d6ff1ae77de1ae8bee8a44ea2e5e4491c802b156fa77783ddebd44598 providers/implementations/ciphers/ciphercommon_gcm.c
+bb67eaa7a98494ca938726f9218213870fc97dd87b56bda950626cc794baf20b providers/implementations/ciphers/ciphercommon_gcm_hw.c
+23fd89e3239e596c325a8c5d23eb1fe157a8d23aa4d90ed2c574bf06dfabd693 providers/implementations/ciphers/ciphercommon_hw.c
+c4b1cb143de15acc396ce2e03fdd165defd25ebc831de9cdfacf408ea883c666 providers/implementations/ciphers/ciphercommon_local.h
+39b47b6ef9d71852964c26e07ef0e9b23f04c7493b1b16ba7c3dba7074b6b70d providers/implementations/digests/digestcommon.c
+80551b53302d95faea257df3edbdbd02d48427ce42da2c4335f998456400d057 providers/implementations/digests/sha2_prov.c
+de342d04be6af69037922d5c97bdc40c0c27f6740636e72786a765d0d8ad9173 providers/implementations/digests/sha3_prov.c
+b5f94d597df72ca58486c59b2a70b4057d13f09528f861ed41a84b7125b54a82 providers/implementations/exchange/dh_exch.c
+9c46dc0d859875fcc0bc3d61a7b610cd3520b1bf63718775c1124f54a1fe5f24 providers/implementations/exchange/ecdh_exch.c
+9bf87b8429398a6465c7e9f749a33b84974303a458736b56f3359b30726d3969 providers/implementations/exchange/ecx_exch.c
+0cc02005660c5c340660123decac838c59b7460ef1003d9d50edc604cfd8e375 providers/implementations/exchange/kdf_exch.c
+31d3dba3d2e6b043b0d14a74caf6bf1a6c550471fb992a495ab7d3337081a526 providers/implementations/include/prov/ciphercommon.h
+6dc876a1a785420e84210f085be6e4c7aca407ffb5433dbca4cd3f1c11bb7f06 providers/implementations/include/prov/ciphercommon_aead.h
+dd07797d61988fd4124cfb920616df672938da80649fac5977bfd061c981edc5 providers/implementations/include/prov/ciphercommon_ccm.h
+0c1e99d70155402a790e4de65923228c8df8ad970741caccfe8b513837457d7f providers/implementations/include/prov/ciphercommon_gcm.h
+b9a61ce951c1904d8315b1bb26c0ab0aaadb47e71d4ead5df0a891608c728c4b providers/implementations/include/prov/digestcommon.h
+3e2558c36298cdb4fdaebe5a0cfa1dbbc78e0f60a9012f3a34e711cafb09c7b5 providers/implementations/include/prov/implementations.h
+5f09fc71874b00419d71646714f21ebbdcceda277463b6f77d3d3ea6946914e8 providers/implementations/include/prov/kdfexchange.h
+c95ce5498e724b9b3d58e3c2f4723e7e3e4beb07f9bea9422e43182cbadb43af providers/implementations/include/prov/macsignature.h
+29d1a112b799e1f45fdf8bcee8361c2ed67428c250c1cdf408a9fbb7ebf4cce1 providers/implementations/include/prov/names.h
+2187713b446d8b6d24ee986748b941ac3e24292c71e07ff9fb53a33021decdda providers/implementations/include/prov/seeding.h
+04f22d6afbad5a6e806cf3af9a25843ccfefb748e24d97a09830a1677706acd5 providers/implementations/kdfs/hkdf.c
+a62e3af09f5af84dcf36f951ba4ac90ca1694adaf3747126186020b155f94186 providers/implementations/kdfs/kbkdf.c
+e0644e727aacfea4da3cf2c4d2602d7ef0626ebb760b6467432ffd54d5fbb24d providers/implementations/kdfs/pbkdf2.c
+c0778565abff112c0c5257329a7750ec4605e62f26cc36851fa1fbee6e03c70c providers/implementations/kdfs/pbkdf2.h
+abe2b0f3711eaa34846e155cffc9242e4051c45de896f747afd5ac9d87f637dc providers/implementations/kdfs/pbkdf2_fips.c
+9cc42a4b0a8089e6d1be64637dbb9e41bd21ae5e3386022a27a8f29308ad25c9 providers/implementations/kdfs/sshkdf.c
+8571556d77d10e8edc98212473a38f09632e3f19e9995dde89ee6c95f2e84ccf providers/implementations/kdfs/sskdf.c
+589f6133799da80760e8bc3ab0191a341ab6d4d2706e92e6eb4a24b0250fefa6 providers/implementations/kdfs/tls1_prf.c
+4d4a6d9a562d2dcfec941d3f113a544663b5ac2fbe4accd89ec70c1cc11751d0 providers/implementations/kdfs/x942kdf.c
+6b6c776b12664164f3cb54c21df61e1c4477c7855d89431a16fb338cdae58d43 providers/implementations/kem/rsa_kem.c
+37120f8a420de0e44b7dc1f31b50d59520e5318cf546e83684e0c3de5c7b76c5 providers/implementations/keymgmt/dh_kmgmt.c
+2a4493c9e68f41d37d7ec69c272005c6df7b1a34db2d49663f52e836e4fd888c providers/implementations/keymgmt/dsa_kmgmt.c
+ed6825fb92d0ab30f9f858ee29dfa403caa22430cccf493f850f993fd03a975e providers/implementations/keymgmt/ec_kmgmt.c
+258ae17bb2dd87ed1511a8eb3fe99eed9b77f5c2f757215ff6b3d0e8791fc251 providers/implementations/keymgmt/ec_kmgmt_imexport.inc
+d77ece2494e6b12a6201a2806ee5fb24a6dc2fa3e1891a46012a870e0b781ab1 providers/implementations/keymgmt/ecx_kmgmt.c
+053a2be39a87f50b877ebdbbf799cf5faf8b2de33b04311d819d212ee1ea329b providers/implementations/keymgmt/kdf_legacy_kmgmt.c
+e30357311e4a3e1c78266af6315fd1fc99584bfb09f4a7cd0ddc7261cf1e17e1 providers/implementations/keymgmt/mac_legacy_kmgmt.c
+96b47ba54dcbc05f7ee98c7f78df04e9671b6dbddbc85e3ea53e74ad04663e7a providers/implementations/keymgmt/rsa_kmgmt.c
+aeb42590728ca87b916b8a3d337351b1c82ee0747213e5ce740c2350b3db7185 providers/implementations/macs/cmac_prov.c
+e69aa06f8f3c6f5a26702b9f44a844b8589b99dc0ee590953a29e8b9ef10acbe providers/implementations/macs/gmac_prov.c
+895c8dc7235b9ad5ff893be0293cbc245a5455e8850195ac7d446646e4ea71d0 providers/implementations/macs/hmac_prov.c
+f75fbfe5348f93ad610da7d310f4e8fecf18c0549f27605da25d393c33e0edc2 providers/implementations/macs/kmac_prov.c
+bf30274dd6b528ae913984775bd8f29c6c48c0ef06d464d0f738217727b7aa5c providers/implementations/rands/crngt.c
+c7236e6e2e8adce14f8206da0ceef63c7974d4ba1a7dd71b94fa100cac6b46ba providers/implementations/rands/drbg.c
+bb5f8161a80d0d1a7ee919af2b167972b00afd62e326252ca6aa93101f315f19 providers/implementations/rands/drbg_ctr.c
+a05adc3f6d9d6f948e5ead75f0522ed3164cb5b2d301169242f3cb97c4a7fac3 providers/implementations/rands/drbg_hash.c
+0876dfae991028c569631938946e458e6829cacf4cfb673d2b144ae50a3160bb providers/implementations/rands/drbg_hmac.c
+fc43558964bdf12442d3f6ab6cc3e6849f7adb42f4d0123a1279819befcf71cb providers/implementations/rands/drbg_local.h
+04339b66c10017229ef368cb48077f58a252ebfda9ab12b9f919e4149b1036ed providers/implementations/rands/test_rng.c
+cafb9e6f54ad15889fcebddac6df61336bff7d78936f7de3bb5aab8aee5728d2 providers/implementations/signature/dsa_sig.c
+a30dc6308de0ca33406e7ce909f3bcf7580fb84d863b0976b275839f866258df providers/implementations/signature/ecdsa_sig.c
+02e833a767afbe98247d6f09dfb1eb5a5cf7304a93f2c5427a9f6af9c8a3b549 providers/implementations/signature/eddsa_sig.c
+3bb0f342b4cc1b4594ed0986adc47791c0a7b5c1ae7b1888c1fb5edb268a78d9 providers/implementations/signature/mac_legacy_sig.c
+2334c8bba705032b8c1db5dd28e024a45a73b72cae82a2d815fe855445a49d10 providers/implementations/signature/rsa_sig.c
+a14e901b02fe095713624db4080b3aa3ca685d43f9ebec03041f992240973346 ssl/record/tls_pad.c
+3f2e01a98d9e3fda6cc5cb4b44dd43f6cae4ec34994e8f734d11b1e643e58636 ssl/s3_cbc.c
diff --git a/providers/fips.checksum b/providers/fips.checksum
new file mode 100644
index 000000000000..7f7abb3eaa22
--- /dev/null
+++ b/providers/fips.checksum
@@ -0,0 +1 @@
+fd6bce79efec94a99e40c919e0a5ee392514b81cac01d4d46b5c76f27fb1b839 providers/fips-sources.checksums
diff --git a/providers/fips.module.sources b/providers/fips.module.sources
new file mode 100644
index 000000000000..8861ceaca311
--- /dev/null
+++ b/providers/fips.module.sources
@@ -0,0 +1,583 @@
+crypto/aes/aes_cbc.c
+crypto/aes/aes_core.c
+crypto/aes/aes_ecb.c
+crypto/aes/aes_local.h
+crypto/aes/aes_misc.c
+crypto/aes/asm/aes-586.pl
+crypto/aes/asm/aes-armv4.pl
+crypto/aes/asm/aes-c64xplus.pl
+crypto/aes/asm/aes-ia64.S
+crypto/aes/asm/aes-mips.pl
+crypto/aes/asm/aes-parisc.pl
+crypto/aes/asm/aes-ppc.pl
+crypto/aes/asm/aes-s390x.pl
+crypto/aes/asm/aes-sparcv9.pl
+crypto/aes/asm/aes-x86_64.pl
+crypto/aes/asm/aesfx-sparcv9.pl
+crypto/aes/asm/aesni-mb-x86_64.pl
+crypto/aes/asm/aesni-sha1-x86_64.pl
+crypto/aes/asm/aesni-sha256-x86_64.pl
+crypto/aes/asm/aesni-x86.pl
+crypto/aes/asm/aesni-x86_64.pl
+crypto/aes/asm/aesp8-ppc.pl
+crypto/aes/asm/aest4-sparcv9.pl
+crypto/aes/asm/aesv8-armx.pl
+crypto/aes/asm/bsaes-armv7.pl
+crypto/aes/asm/bsaes-x86_64.pl
+crypto/aes/asm/vpaes-armv8.pl
+crypto/aes/asm/vpaes-ppc.pl
+crypto/aes/asm/vpaes-x86.pl
+crypto/aes/asm/vpaes-x86_64.pl
+crypto/asn1_dsa.c
+crypto/bn/asm/alpha-mont.pl
+crypto/bn/asm/armv4-gf2m.pl
+crypto/bn/asm/armv4-mont.pl
+crypto/bn/asm/armv8-mont.pl
+crypto/bn/asm/bn-586.pl
+crypto/bn/asm/c64xplus-gf2m.pl
+crypto/bn/asm/co-586.pl
+crypto/bn/asm/ia64-mont.pl
+crypto/bn/asm/ia64.S
+crypto/bn/asm/mips-mont.pl
+crypto/bn/asm/mips.pl
+crypto/bn/asm/parisc-mont.pl
+crypto/bn/asm/ppc-mont.pl
+crypto/bn/asm/ppc.pl
+crypto/bn/asm/ppc64-mont-fixed.pl
+crypto/bn/asm/ppc64-mont.pl
+crypto/bn/asm/rsaz-avx2.pl
+crypto/bn/asm/rsaz-avx512.pl
+crypto/bn/asm/rsaz-x86_64.pl
+crypto/bn/asm/s390x-gf2m.pl
+crypto/bn/asm/s390x-mont.pl
+crypto/bn/asm/s390x.S
+crypto/bn/asm/sparct4-mont.pl
+crypto/bn/asm/sparcv8.S
+crypto/bn/asm/sparcv8plus.S
+crypto/bn/asm/sparcv9-gf2m.pl
+crypto/bn/asm/sparcv9-mont.pl
+crypto/bn/asm/sparcv9a-mont.pl
+crypto/bn/asm/via-mont.pl
+crypto/bn/asm/vis3-mont.pl
+crypto/bn/asm/x86-gf2m.pl
+crypto/bn/asm/x86-mont.pl
+crypto/bn/asm/x86_64-gcc.c
+crypto/bn/asm/x86_64-gf2m.pl
+crypto/bn/asm/x86_64-mont.pl
+crypto/bn/asm/x86_64-mont5.pl
+crypto/bn/bn_add.c
+crypto/bn/bn_asm.c
+crypto/bn/bn_blind.c
+crypto/bn/bn_const.c
+crypto/bn/bn_conv.c
+crypto/bn/bn_ctx.c
+crypto/bn/bn_dh.c
+crypto/bn/bn_div.c
+crypto/bn/bn_exp.c
+crypto/bn/bn_exp2.c
+crypto/bn/bn_gcd.c
+crypto/bn/bn_gf2m.c
+crypto/bn/bn_intern.c
+crypto/bn/bn_kron.c
+crypto/bn/bn_lib.c
+crypto/bn/bn_local.h
+crypto/bn/bn_mod.c
+crypto/bn/bn_mont.c
+crypto/bn/bn_mpi.c
+crypto/bn/bn_mul.c
+crypto/bn/bn_nist.c
+crypto/bn/bn_prime.c
+crypto/bn/bn_prime.h
+crypto/bn/bn_rand.c
+crypto/bn/bn_recp.c
+crypto/bn/bn_rsa_fips186_4.c
+crypto/bn/bn_shift.c
+crypto/bn/bn_sqr.c
+crypto/bn/bn_sqrt.c
+crypto/bn/bn_word.c
+crypto/bn/rsa_sup_mul.c
+crypto/bn/rsaz_exp.c
+crypto/bn/rsaz_exp.h
+crypto/bn/rsaz_exp_x2.c
+crypto/bsearch.c
+crypto/buffer/buffer.c
+crypto/cmac/cmac.c
+crypto/context.c
+crypto/core_algorithm.c
+crypto/core_fetch.c
+crypto/core_namemap.c
+crypto/cpuid.c
+crypto/cryptlib.c
+crypto/ctype.c
+crypto/der_writer.c
+crypto/des/des_enc.c
+crypto/des/des_local.h
+crypto/des/ecb3_enc.c
+crypto/des/fcrypt_b.c
+crypto/des/ncbc_enc.c
+crypto/des/set_key.c
+crypto/des/spr.h
+crypto/dh/dh_backend.c
+crypto/dh/dh_check.c
+crypto/dh/dh_gen.c
+crypto/dh/dh_group_params.c
+crypto/dh/dh_kdf.c
+crypto/dh/dh_key.c
+crypto/dh/dh_lib.c
+crypto/dh/dh_local.h
+crypto/dsa/dsa_backend.c
+crypto/dsa/dsa_check.c
+crypto/dsa/dsa_gen.c
+crypto/dsa/dsa_key.c
+crypto/dsa/dsa_lib.c
+crypto/dsa/dsa_local.h
+crypto/dsa/dsa_ossl.c
+crypto/dsa/dsa_sign.c
+crypto/dsa/dsa_vrf.c
+crypto/ec/asm/ecp_nistp521-ppc64.pl
+crypto/ec/asm/ecp_nistz256-armv4.pl
+crypto/ec/asm/ecp_nistz256-armv8.pl
+crypto/ec/asm/ecp_nistz256-ppc64.pl
+crypto/ec/asm/ecp_nistz256-sparcv9.pl
+crypto/ec/asm/ecp_nistz256-x86.pl
+crypto/ec/asm/ecp_nistz256-x86_64.pl
+crypto/ec/asm/x25519-ppc64.pl
+crypto/ec/asm/x25519-x86_64.pl
+crypto/ec/curve25519.c
+crypto/ec/curve448/arch_32/f_impl32.c
+crypto/ec/curve448/arch_64/arch_intrinsics.h
+crypto/ec/curve448/arch_64/f_impl.h
+crypto/ec/curve448/arch_64/f_impl64.c
+crypto/ec/curve448/curve448.c
+crypto/ec/curve448/curve448_local.h
+crypto/ec/curve448/curve448_tables.c
+crypto/ec/curve448/curve448utils.h
+crypto/ec/curve448/ed448.h
+crypto/ec/curve448/eddsa.c
+crypto/ec/curve448/f_generic.c
+crypto/ec/curve448/field.h
+crypto/ec/curve448/point_448.h
+crypto/ec/curve448/scalar.c
+crypto/ec/curve448/word.h
+crypto/ec/ec2_oct.c
+crypto/ec/ec2_smpl.c
+crypto/ec/ec_asn1.c
+crypto/ec/ec_backend.c
+crypto/ec/ec_check.c
+crypto/ec/ec_curve.c
+crypto/ec/ec_cvt.c
+crypto/ec/ec_key.c
+crypto/ec/ec_kmeth.c
+crypto/ec/ec_lib.c
+crypto/ec/ec_local.h
+crypto/ec/ec_mult.c
+crypto/ec/ec_oct.c
+crypto/ec/ecdh_kdf.c
+crypto/ec/ecdh_ossl.c
+crypto/ec/ecdsa_ossl.c
+crypto/ec/ecdsa_sign.c
+crypto/ec/ecdsa_vrf.c
+crypto/ec/ecp_mont.c
+crypto/ec/ecp_nist.c
+crypto/ec/ecp_nistz256.c
+crypto/ec/ecp_oct.c
+crypto/ec/ecp_smpl.c
+crypto/ec/ecx_backend.c
+crypto/ec/ecx_backend.h
+crypto/ec/ecx_key.c
+crypto/evp/asymcipher.c
+crypto/evp/dh_support.c
+crypto/evp/digest.c
+crypto/evp/ec_support.c
+crypto/evp/evp_enc.c
+crypto/evp/evp_fetch.c
+crypto/evp/evp_lib.c
+crypto/evp/evp_local.h
+crypto/evp/evp_rand.c
+crypto/evp/evp_utils.c
+crypto/evp/exchange.c
+crypto/evp/kdf_lib.c
+crypto/evp/kdf_meth.c
+crypto/evp/kem.c
+crypto/evp/keymgmt_lib.c
+crypto/evp/keymgmt_meth.c
+crypto/evp/m_sigver.c
+crypto/evp/mac_lib.c
+crypto/evp/mac_meth.c
+crypto/evp/p_lib.c
+crypto/evp/pmeth_check.c
+crypto/evp/pmeth_gn.c
+crypto/evp/pmeth_lib.c
+crypto/evp/signature.c
+crypto/ex_data.c
+crypto/ffc/ffc_backend.c
+crypto/ffc/ffc_dh.c
+crypto/ffc/ffc_key_generate.c
+crypto/ffc/ffc_key_validate.c
+crypto/ffc/ffc_params.c
+crypto/ffc/ffc_params_generate.c
+crypto/ffc/ffc_params_validate.c
+crypto/hmac/hmac.c
+crypto/hmac/hmac_local.h
+crypto/initthread.c
+crypto/lhash/lhash.c
+crypto/lhash/lhash_local.h
+crypto/mem_clr.c
+crypto/modes/asm/aes-gcm-armv8_64.pl
+crypto/modes/asm/aesni-gcm-x86_64.pl
+crypto/modes/asm/ghash-alpha.pl
+crypto/modes/asm/ghash-armv4.pl
+crypto/modes/asm/ghash-c64xplus.pl
+crypto/modes/asm/ghash-ia64.pl
+crypto/modes/asm/ghash-parisc.pl
+crypto/modes/asm/ghash-s390x.pl
+crypto/modes/asm/ghash-sparcv9.pl
+crypto/modes/asm/ghash-x86.pl
+crypto/modes/asm/ghash-x86_64.pl
+crypto/modes/asm/ghashp8-ppc.pl
+crypto/modes/asm/ghashv8-armx.pl
+crypto/modes/cbc128.c
+crypto/modes/ccm128.c
+crypto/modes/cfb128.c
+crypto/modes/ctr128.c
+crypto/modes/gcm128.c
+crypto/modes/ofb128.c
+crypto/modes/wrap128.c
+crypto/modes/xts128.c
+crypto/o_str.c
+crypto/packet.c
+crypto/param_build.c
+crypto/param_build_set.c
+crypto/params.c
+crypto/params_dup.c
+crypto/params_from_text.c
+crypto/property/defn_cache.c
+crypto/property/property.c
+crypto/property/property_local.h
+crypto/property/property_parse.c
+crypto/property/property_query.c
+crypto/property/property_string.c
+crypto/provider_core.c
+crypto/provider_local.h
+crypto/provider_predefined.c
+crypto/rand/rand_lib.c
+crypto/rand/rand_local.h
+crypto/rsa/rsa_acvp_test_params.c
+crypto/rsa/rsa_backend.c
+crypto/rsa/rsa_chk.c
+crypto/rsa/rsa_crpt.c
+crypto/rsa/rsa_gen.c
+crypto/rsa/rsa_lib.c
+crypto/rsa/rsa_local.h
+crypto/rsa/rsa_mp_names.c
+crypto/rsa/rsa_none.c
+crypto/rsa/rsa_oaep.c
+crypto/rsa/rsa_ossl.c
+crypto/rsa/rsa_pk1.c
+crypto/rsa/rsa_pss.c
+crypto/rsa/rsa_schemes.c
+crypto/rsa/rsa_sign.c
+crypto/rsa/rsa_sp800_56b_check.c
+crypto/rsa/rsa_sp800_56b_gen.c
+crypto/rsa/rsa_x931.c
+crypto/self_test_core.c
+crypto/sha/asm/keccak1600-armv4.pl
+crypto/sha/asm/keccak1600-armv8.pl
+crypto/sha/asm/keccak1600-avx2.pl
+crypto/sha/asm/keccak1600-avx512.pl
+crypto/sha/asm/keccak1600-avx512vl.pl
+crypto/sha/asm/keccak1600-c64x.pl
+crypto/sha/asm/keccak1600-mmx.pl
+crypto/sha/asm/keccak1600-ppc64.pl
+crypto/sha/asm/keccak1600-s390x.pl
+crypto/sha/asm/keccak1600-x86_64.pl
+crypto/sha/asm/keccak1600p8-ppc.pl
+crypto/sha/asm/sha1-586.pl
+crypto/sha/asm/sha1-alpha.pl
+crypto/sha/asm/sha1-armv4-large.pl
+crypto/sha/asm/sha1-armv8.pl
+crypto/sha/asm/sha1-c64xplus.pl
+crypto/sha/asm/sha1-ia64.pl
+crypto/sha/asm/sha1-mb-x86_64.pl
+crypto/sha/asm/sha1-mips.pl
+crypto/sha/asm/sha1-parisc.pl
+crypto/sha/asm/sha1-ppc.pl
+crypto/sha/asm/sha1-s390x.pl
+crypto/sha/asm/sha1-sparcv9.pl
+crypto/sha/asm/sha1-sparcv9a.pl
+crypto/sha/asm/sha1-thumb.pl
+crypto/sha/asm/sha1-x86_64.pl
+crypto/sha/asm/sha256-586.pl
+crypto/sha/asm/sha256-armv4.pl
+crypto/sha/asm/sha256-c64xplus.pl
+crypto/sha/asm/sha256-mb-x86_64.pl
+crypto/sha/asm/sha512-586.pl
+crypto/sha/asm/sha512-armv4.pl
+crypto/sha/asm/sha512-armv8.pl
+crypto/sha/asm/sha512-c64xplus.pl
+crypto/sha/asm/sha512-ia64.pl
+crypto/sha/asm/sha512-mips.pl
+crypto/sha/asm/sha512-parisc.pl
+crypto/sha/asm/sha512-ppc.pl
+crypto/sha/asm/sha512-s390x.pl
+crypto/sha/asm/sha512-sparcv9.pl
+crypto/sha/asm/sha512-x86_64.pl
+crypto/sha/asm/sha512p8-ppc.pl
+crypto/sha/keccak1600.c
+crypto/sha/sha1dgst.c
+crypto/sha/sha256.c
+crypto/sha/sha3.c
+crypto/sha/sha512.c
+crypto/sha/sha_local.h
+crypto/sparse_array.c
+crypto/stack/stack.c
+crypto/threads_lib.c
+crypto/threads_none.c
+crypto/threads_pthread.c
+crypto/threads_win.c
+crypto/x86_64cpuid.pl
+e_os.h
+include/crypto/aes_platform.h
+include/crypto/asn1_dsa.h
+include/crypto/bn.h
+include/crypto/bn_conf.h.in
+include/crypto/bn_dh.h
+include/crypto/cryptlib.h
+include/crypto/ctype.h
+include/crypto/des_platform.h
+include/crypto/dh.h
+include/crypto/dsa.h
+include/crypto/ec.h
+include/crypto/ecx.h
+include/crypto/evp.h
+include/crypto/lhash.h
+include/crypto/md32_common.h
+include/crypto/modes.h
+include/crypto/rand.h
+include/crypto/rand_pool.h
+include/crypto/rsa.h
+include/crypto/security_bits.h
+include/crypto/sha.h
+include/crypto/sparse_array.h
+include/crypto/types.h
+include/internal/bio.h
+include/internal/constant_time.h
+include/internal/core.h
+include/internal/cryptlib.h
+include/internal/deprecated.h
+include/internal/der.h
+include/internal/dso.h
+include/internal/dsoerr.h
+include/internal/endian.h
+include/internal/ffc.h
+include/internal/namemap.h
+include/internal/nelem.h
+include/internal/numbers.h
+include/internal/packet.h
+include/internal/param_build_set.h
+include/internal/property.h
+include/internal/propertyerr.h
+include/internal/provider.h
+include/internal/refcount.h
+include/internal/sha3.h
+include/internal/sizes.h
+include/internal/symhacks.h
+include/internal/thread_once.h
+include/internal/tlsgroups.h
+include/internal/tsan_assist.h
+include/openssl/aes.h
+include/openssl/asn1.h.in
+include/openssl/asn1err.h
+include/openssl/asn1t.h.in
+include/openssl/bio.h.in
+include/openssl/bioerr.h
+include/openssl/bn.h
+include/openssl/bnerr.h
+include/openssl/buffer.h
+include/openssl/buffererr.h
+include/openssl/cmac.h
+include/openssl/conf.h.in
+include/openssl/conferr.h
+include/openssl/configuration.h.in
+include/openssl/conftypes.h
+include/openssl/core.h
+include/openssl/core_dispatch.h
+include/openssl/core_names.h
+include/openssl/crypto.h.in
+include/openssl/cryptoerr.h
+include/openssl/cryptoerr_legacy.h
+include/openssl/des.h
+include/openssl/dh.h
+include/openssl/dherr.h
+include/openssl/dsa.h
+include/openssl/dsaerr.h
+include/openssl/e_os2.h
+include/openssl/ebcdic.h
+include/openssl/ec.h
+include/openssl/ecerr.h
+include/openssl/encoder.h
+include/openssl/encodererr.h
+include/openssl/err.h.in
+include/openssl/evp.h
+include/openssl/evperr.h
+include/openssl/fips_names.h
+include/openssl/fipskey.h.in
+include/openssl/hmac.h
+include/openssl/kdf.h
+include/openssl/lhash.h.in
+include/openssl/macros.h
+include/openssl/modes.h
+include/openssl/obj_mac.h
+include/openssl/objects.h
+include/openssl/objectserr.h
+include/openssl/opensslconf.h
+include/openssl/opensslv.h.in
+include/openssl/param_build.h
+include/openssl/params.h
+include/openssl/prov_ssl.h
+include/openssl/proverr.h
+include/openssl/provider.h
+include/openssl/rand.h
+include/openssl/randerr.h
+include/openssl/rsa.h
+include/openssl/rsaerr.h
+include/openssl/safestack.h.in
+include/openssl/self_test.h
+include/openssl/sha.h
+include/openssl/stack.h
+include/openssl/symhacks.h
+include/openssl/trace.h
+include/openssl/types.h
+providers/common/bio_prov.c
+providers/common/capabilities.c
+providers/common/der/der_digests_gen.c.in
+providers/common/der/der_dsa_gen.c.in
+providers/common/der/der_dsa_key.c
+providers/common/der/der_dsa_sig.c
+providers/common/der/der_ec_gen.c.in
+providers/common/der/der_ec_key.c
+providers/common/der/der_ec_sig.c
+providers/common/der/der_ecx_gen.c.in
+providers/common/der/der_ecx_key.c
+providers/common/der/der_rsa_gen.c.in
+providers/common/der/der_rsa_key.c
+providers/common/der/der_rsa_sig.c
+providers/common/der/der_wrap_gen.c.in
+providers/common/digest_to_nid.c
+providers/common/include/prov/bio.h
+providers/common/include/prov/der_digests.h.in
+providers/common/include/prov/der_dsa.h.in
+providers/common/include/prov/der_ec.h.in
+providers/common/include/prov/der_ecx.h.in
+providers/common/include/prov/der_rsa.h.in
+providers/common/include/prov/der_wrap.h.in
+providers/common/include/prov/proverr.h
+providers/common/include/prov/provider_ctx.h
+providers/common/include/prov/provider_util.h
+providers/common/include/prov/providercommon.h
+providers/common/include/prov/securitycheck.h
+providers/common/provider_ctx.c
+providers/common/provider_err.c
+providers/common/provider_seeding.c
+providers/common/provider_util.c
+providers/common/securitycheck.c
+providers/common/securitycheck_fips.c
+providers/fips/fips_entry.c
+providers/fips/fipsprov.c
+providers/fips/self_test.c
+providers/fips/self_test.h
+providers/fips/self_test_data.inc
+providers/fips/self_test_kats.c
+providers/implementations/asymciphers/rsa_enc.c
+providers/implementations/ciphers/cipher_aes.c
+providers/implementations/ciphers/cipher_aes.h
+providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c
+providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.h
+providers/implementations/ciphers/cipher_aes_cbc_hmac_sha1_hw.c
+providers/implementations/ciphers/cipher_aes_cbc_hmac_sha256_hw.c
+providers/implementations/ciphers/cipher_aes_ccm.c
+providers/implementations/ciphers/cipher_aes_ccm.h
+providers/implementations/ciphers/cipher_aes_ccm_hw.c
+providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc
+providers/implementations/ciphers/cipher_aes_cts.inc
+providers/implementations/ciphers/cipher_aes_gcm.c
+providers/implementations/ciphers/cipher_aes_gcm.h
+providers/implementations/ciphers/cipher_aes_gcm_hw.c
+providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc
+providers/implementations/ciphers/cipher_aes_hw.c
+providers/implementations/ciphers/cipher_aes_hw_aesni.inc
+providers/implementations/ciphers/cipher_aes_ocb.c
+providers/implementations/ciphers/cipher_aes_ocb.h
+providers/implementations/ciphers/cipher_aes_ocb_hw.c
+providers/implementations/ciphers/cipher_aes_wrp.c
+providers/implementations/ciphers/cipher_aes_xts.c
+providers/implementations/ciphers/cipher_aes_xts.h
+providers/implementations/ciphers/cipher_aes_xts_fips.c
+providers/implementations/ciphers/cipher_aes_xts_hw.c
+providers/implementations/ciphers/cipher_cts.c
+providers/implementations/ciphers/cipher_cts.h
+providers/implementations/ciphers/cipher_tdes.c
+providers/implementations/ciphers/cipher_tdes.h
+providers/implementations/ciphers/cipher_tdes_common.c
+providers/implementations/ciphers/cipher_tdes_hw.c
+providers/implementations/ciphers/ciphercommon.c
+providers/implementations/ciphers/ciphercommon_block.c
+providers/implementations/ciphers/ciphercommon_ccm.c
+providers/implementations/ciphers/ciphercommon_ccm_hw.c
+providers/implementations/ciphers/ciphercommon_gcm.c
+providers/implementations/ciphers/ciphercommon_gcm_hw.c
+providers/implementations/ciphers/ciphercommon_hw.c
+providers/implementations/ciphers/ciphercommon_local.h
+providers/implementations/digests/digestcommon.c
+providers/implementations/digests/sha2_prov.c
+providers/implementations/digests/sha3_prov.c
+providers/implementations/exchange/dh_exch.c
+providers/implementations/exchange/ecdh_exch.c
+providers/implementations/exchange/ecx_exch.c
+providers/implementations/exchange/kdf_exch.c
+providers/implementations/include/prov/ciphercommon.h
+providers/implementations/include/prov/ciphercommon_aead.h
+providers/implementations/include/prov/ciphercommon_ccm.h
+providers/implementations/include/prov/ciphercommon_gcm.h
+providers/implementations/include/prov/digestcommon.h
+providers/implementations/include/prov/implementations.h
+providers/implementations/include/prov/kdfexchange.h
+providers/implementations/include/prov/macsignature.h
+providers/implementations/include/prov/names.h
+providers/implementations/include/prov/seeding.h
+providers/implementations/kdfs/hkdf.c
+providers/implementations/kdfs/kbkdf.c
+providers/implementations/kdfs/pbkdf2.c
+providers/implementations/kdfs/pbkdf2.h
+providers/implementations/kdfs/pbkdf2_fips.c
+providers/implementations/kdfs/sshkdf.c
+providers/implementations/kdfs/sskdf.c
+providers/implementations/kdfs/tls1_prf.c
+providers/implementations/kdfs/x942kdf.c
+providers/implementations/kem/rsa_kem.c
+providers/implementations/keymgmt/dh_kmgmt.c
+providers/implementations/keymgmt/dsa_kmgmt.c
+providers/implementations/keymgmt/ec_kmgmt.c
+providers/implementations/keymgmt/ec_kmgmt_imexport.inc
+providers/implementations/keymgmt/ecx_kmgmt.c
+providers/implementations/keymgmt/kdf_legacy_kmgmt.c
+providers/implementations/keymgmt/mac_legacy_kmgmt.c
+providers/implementations/keymgmt/rsa_kmgmt.c
+providers/implementations/macs/cmac_prov.c
+providers/implementations/macs/gmac_prov.c
+providers/implementations/macs/hmac_prov.c
+providers/implementations/macs/kmac_prov.c
+providers/implementations/rands/crngt.c
+providers/implementations/rands/drbg.c
+providers/implementations/rands/drbg_ctr.c
+providers/implementations/rands/drbg_hash.c
+providers/implementations/rands/drbg_hmac.c
+providers/implementations/rands/drbg_local.h
+providers/implementations/rands/test_rng.c
+providers/implementations/signature/dsa_sig.c
+providers/implementations/signature/ecdsa_sig.c
+providers/implementations/signature/eddsa_sig.c
+providers/implementations/signature/mac_legacy_sig.c
+providers/implementations/signature/rsa_sig.c
+ssl/record/tls_pad.c
+ssl/s3_cbc.c
diff --git a/providers/fips/build.info b/providers/fips/build.info
new file mode 100644
index 000000000000..2bfc58501e94
--- /dev/null
+++ b/providers/fips/build.info
@@ -0,0 +1,6 @@
+# We include the provider implementation into ../libfips.a, so that all
+# platforms can resolve symbols in other members of that library.
+SOURCE[../libfips.a]=fipsprov.c self_test.c self_test_kats.c
+
+# It is necessary to have an explicit entry point
+SOURCE[../fips]=fips_entry.c
diff --git a/providers/fips/fips_entry.c b/providers/fips/fips_entry.c
new file mode 100644
index 000000000000..c2c8d5de2cf7
--- /dev/null
+++ b/providers/fips/fips_entry.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core.h>
+
+OSSL_provider_init_fn OSSL_provider_init_int;
+int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in,
+ const OSSL_DISPATCH **out,
+ void **provctx)
+{
+ return OSSL_provider_init_int(handle, in, out, provctx);
+}
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
new file mode 100644
index 000000000000..6a88039423d9
--- /dev/null
+++ b/providers/fips/fipsprov.c
@@ -0,0 +1,915 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <assert.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/fips_names.h>
+#include <openssl/rand.h> /* RAND_get0_public() */
+#include <openssl/proverr.h>
+#include "internal/cryptlib.h"
+#include "prov/implementations.h"
+#include "prov/names.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+#include "prov/provider_util.h"
+#include "prov/seeding.h"
+#include "self_test.h"
+#include "internal/core.h"
+
+static const char FIPS_DEFAULT_PROPERTIES[] = "provider=fips,fips=yes";
+static const char FIPS_UNAPPROVED_PROPERTIES[] = "provider=fips,fips=no";
+
+/*
+ * Forward declarations to ensure that interface functions are correctly
+ * defined.
+ */
+static OSSL_FUNC_provider_teardown_fn fips_teardown;
+static OSSL_FUNC_provider_gettable_params_fn fips_gettable_params;
+static OSSL_FUNC_provider_get_params_fn fips_get_params;
+static OSSL_FUNC_provider_query_operation_fn fips_query;
+
+#define ALGC(NAMES, FUNC, CHECK) { { NAMES, FIPS_DEFAULT_PROPERTIES, FUNC }, CHECK }
+#define ALG(NAMES, FUNC) ALGC(NAMES, FUNC, NULL)
+
+extern OSSL_FUNC_core_thread_start_fn *c_thread_start;
+int FIPS_security_check_enabled(OSSL_LIB_CTX *libctx);
+
+/*
+ * Should these function pointers be stored in the provider side provctx? Could
+ * they ever be different from one init to the next? We assume not for now.
+ */
+
+/* Functions provided by the core */
+static OSSL_FUNC_core_gettable_params_fn *c_gettable_params;
+static OSSL_FUNC_core_get_params_fn *c_get_params;
+OSSL_FUNC_core_thread_start_fn *c_thread_start;
+static OSSL_FUNC_core_new_error_fn *c_new_error;
+static OSSL_FUNC_core_set_error_debug_fn *c_set_error_debug;
+static OSSL_FUNC_core_vset_error_fn *c_vset_error;
+static OSSL_FUNC_core_set_error_mark_fn *c_set_error_mark;
+static OSSL_FUNC_core_clear_last_error_mark_fn *c_clear_last_error_mark;
+static OSSL_FUNC_core_pop_error_to_mark_fn *c_pop_error_to_mark;
+static OSSL_FUNC_CRYPTO_malloc_fn *c_CRYPTO_malloc;
+static OSSL_FUNC_CRYPTO_zalloc_fn *c_CRYPTO_zalloc;
+static OSSL_FUNC_CRYPTO_free_fn *c_CRYPTO_free;
+static OSSL_FUNC_CRYPTO_clear_free_fn *c_CRYPTO_clear_free;
+static OSSL_FUNC_CRYPTO_realloc_fn *c_CRYPTO_realloc;
+static OSSL_FUNC_CRYPTO_clear_realloc_fn *c_CRYPTO_clear_realloc;
+static OSSL_FUNC_CRYPTO_secure_malloc_fn *c_CRYPTO_secure_malloc;
+static OSSL_FUNC_CRYPTO_secure_zalloc_fn *c_CRYPTO_secure_zalloc;
+static OSSL_FUNC_CRYPTO_secure_free_fn *c_CRYPTO_secure_free;
+static OSSL_FUNC_CRYPTO_secure_clear_free_fn *c_CRYPTO_secure_clear_free;
+static OSSL_FUNC_CRYPTO_secure_allocated_fn *c_CRYPTO_secure_allocated;
+static OSSL_FUNC_BIO_vsnprintf_fn *c_BIO_vsnprintf;
+static OSSL_FUNC_self_test_cb_fn *c_stcbfn = NULL;
+static OSSL_FUNC_core_get_libctx_fn *c_get_libctx = NULL;
+
+typedef struct fips_global_st {
+ const OSSL_CORE_HANDLE *handle;
+ SELF_TEST_POST_PARAMS selftest_params;
+ int fips_security_checks;
+ const char *fips_security_check_option;
+} FIPS_GLOBAL;
+
+static void *fips_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx)
+{
+ FIPS_GLOBAL *fgbl = OPENSSL_zalloc(sizeof(*fgbl));
+
+ if (fgbl == NULL)
+ return NULL;
+ fgbl->fips_security_checks = 1;
+ fgbl->fips_security_check_option = "1";
+
+ return fgbl;
+}
+
+static void fips_prov_ossl_ctx_free(void *fgbl)
+{
+ OPENSSL_free(fgbl);
+}
+
+static const OSSL_LIB_CTX_METHOD fips_prov_ossl_ctx_method = {
+ OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
+ fips_prov_ossl_ctx_new,
+ fips_prov_ossl_ctx_free,
+};
+
+
+/* Parameters we provide to the core */
+static const OSSL_PARAM fips_param_types[] = {
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_VERSION, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_BUILDINFO, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_STATUS, OSSL_PARAM_INTEGER, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_SECURITY_CHECKS, OSSL_PARAM_INTEGER, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static int fips_get_params_from_core(FIPS_GLOBAL *fgbl)
+{
+ /*
+ * Parameters to retrieve from the core provider - required for self testing.
+ * NOTE: inside core_get_params() these will be loaded from config items
+ * stored inside prov->parameters (except for
+ * OSSL_PROV_PARAM_CORE_MODULE_FILENAME).
+ * OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS is not a self test parameter.
+ */
+ OSSL_PARAM core_params[8], *p = core_params;
+
+ *p++ = OSSL_PARAM_construct_utf8_ptr(
+ OSSL_PROV_PARAM_CORE_MODULE_FILENAME,
+ (char **)&fgbl->selftest_params.module_filename,
+ sizeof(fgbl->selftest_params.module_filename));
+ *p++ = OSSL_PARAM_construct_utf8_ptr(
+ OSSL_PROV_FIPS_PARAM_MODULE_MAC,
+ (char **)&fgbl->selftest_params.module_checksum_data,
+ sizeof(fgbl->selftest_params.module_checksum_data));
+ *p++ = OSSL_PARAM_construct_utf8_ptr(
+ OSSL_PROV_FIPS_PARAM_INSTALL_MAC,
+ (char **)&fgbl->selftest_params.indicator_checksum_data,
+ sizeof(fgbl->selftest_params.indicator_checksum_data));
+ *p++ = OSSL_PARAM_construct_utf8_ptr(
+ OSSL_PROV_FIPS_PARAM_INSTALL_STATUS,
+ (char **)&fgbl->selftest_params.indicator_data,
+ sizeof(fgbl->selftest_params.indicator_data));
+ *p++ = OSSL_PARAM_construct_utf8_ptr(
+ OSSL_PROV_FIPS_PARAM_INSTALL_VERSION,
+ (char **)&fgbl->selftest_params.indicator_version,
+ sizeof(fgbl->selftest_params.indicator_version));
+ *p++ = OSSL_PARAM_construct_utf8_ptr(
+ OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS,
+ (char **)&fgbl->selftest_params.conditional_error_check,
+ sizeof(fgbl->selftest_params.conditional_error_check));
+ *p++ = OSSL_PARAM_construct_utf8_ptr(
+ OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS,
+ (char **)&fgbl->fips_security_check_option,
+ sizeof(fgbl->fips_security_check_option));
+ *p = OSSL_PARAM_construct_end();
+
+ if (!c_get_params(fgbl->handle, core_params)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+
+ return 1;
+}
+
+static const OSSL_PARAM *fips_gettable_params(void *provctx)
+{
+ return fips_param_types;
+}
+
+static int fips_get_params(void *provctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+ FIPS_GLOBAL *fgbl = ossl_lib_ctx_get_data(ossl_prov_ctx_get0_libctx(provctx),
+ OSSL_LIB_CTX_FIPS_PROV_INDEX,
+ &fips_prov_ossl_ctx_method);
+
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "OpenSSL FIPS Provider"))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_VERSION);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_VERSION_STR))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_BUILDINFO);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_FULL_VERSION_STR))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_STATUS);
+ if (p != NULL && !OSSL_PARAM_set_int(p, ossl_prov_is_running()))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_SECURITY_CHECKS);
+ if (p != NULL && !OSSL_PARAM_set_int(p, fgbl->fips_security_checks))
+ return 0;
+ return 1;
+}
+
+static void set_self_test_cb(FIPS_GLOBAL *fgbl)
+{
+ const OSSL_CORE_HANDLE *handle =
+ FIPS_get_core_handle(fgbl->selftest_params.libctx);
+
+ if (c_stcbfn != NULL && c_get_libctx != NULL) {
+ c_stcbfn(c_get_libctx(handle), &fgbl->selftest_params.cb,
+ &fgbl->selftest_params.cb_arg);
+ } else {
+ fgbl->selftest_params.cb = NULL;
+ fgbl->selftest_params.cb_arg = NULL;
+ }
+}
+
+static int fips_self_test(void *provctx)
+{
+ FIPS_GLOBAL *fgbl = ossl_lib_ctx_get_data(ossl_prov_ctx_get0_libctx(provctx),
+ OSSL_LIB_CTX_FIPS_PROV_INDEX,
+ &fips_prov_ossl_ctx_method);
+
+ set_self_test_cb(fgbl);
+ return SELF_TEST_post(&fgbl->selftest_params, 1) ? 1 : 0;
+}
+
+/*
+ * For the algorithm names, we use the following formula for our primary
+ * names:
+ *
+ * ALGNAME[VERSION?][-SUBNAME[VERSION?]?][-SIZE?][-MODE?]
+ *
+ * VERSION is only present if there are multiple versions of
+ * an alg (MD2, MD4, MD5). It may be omitted if there is only
+ * one version (if a subsequent version is released in the future,
+ * we can always change the canonical name, and add the old name
+ * as an alias).
+ *
+ * SUBNAME may be present where we are combining multiple
+ * algorithms together, e.g. MD5-SHA1.
+ *
+ * SIZE is only present if multiple versions of an algorithm exist
+ * with different sizes (e.g. AES-128-CBC, AES-256-CBC)
+ *
+ * MODE is only present where applicable.
+ *
+ * We add diverse other names where applicable, such as the names that
+ * NIST uses, or that are used for ASN.1 OBJECT IDENTIFIERs, or names
+ * we have used historically.
+ */
+static const OSSL_ALGORITHM fips_digests[] = {
+ /* Our primary name:NiST name[:our older names] */
+ { PROV_NAMES_SHA1, FIPS_DEFAULT_PROPERTIES, ossl_sha1_functions },
+ { PROV_NAMES_SHA2_224, FIPS_DEFAULT_PROPERTIES, ossl_sha224_functions },
+ { PROV_NAMES_SHA2_256, FIPS_DEFAULT_PROPERTIES, ossl_sha256_functions },
+ { PROV_NAMES_SHA2_384, FIPS_DEFAULT_PROPERTIES, ossl_sha384_functions },
+ { PROV_NAMES_SHA2_512, FIPS_DEFAULT_PROPERTIES, ossl_sha512_functions },
+ { PROV_NAMES_SHA2_512_224, FIPS_DEFAULT_PROPERTIES,
+ ossl_sha512_224_functions },
+ { PROV_NAMES_SHA2_512_256, FIPS_DEFAULT_PROPERTIES,
+ ossl_sha512_256_functions },
+
+ /* We agree with NIST here, so one name only */
+ { PROV_NAMES_SHA3_224, FIPS_DEFAULT_PROPERTIES, ossl_sha3_224_functions },
+ { PROV_NAMES_SHA3_256, FIPS_DEFAULT_PROPERTIES, ossl_sha3_256_functions },
+ { PROV_NAMES_SHA3_384, FIPS_DEFAULT_PROPERTIES, ossl_sha3_384_functions },
+ { PROV_NAMES_SHA3_512, FIPS_DEFAULT_PROPERTIES, ossl_sha3_512_functions },
+
+ { PROV_NAMES_SHAKE_128, FIPS_DEFAULT_PROPERTIES, ossl_shake_128_functions },
+ { PROV_NAMES_SHAKE_256, FIPS_DEFAULT_PROPERTIES, ossl_shake_256_functions },
+
+ /*
+ * KECCAK-KMAC-128 and KECCAK-KMAC-256 as hashes are mostly useful for
+ * KMAC128 and KMAC256.
+ */
+ { PROV_NAMES_KECCAK_KMAC_128, FIPS_DEFAULT_PROPERTIES,
+ ossl_keccak_kmac_128_functions },
+ { PROV_NAMES_KECCAK_KMAC_256, FIPS_DEFAULT_PROPERTIES,
+ ossl_keccak_kmac_256_functions },
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM_CAPABLE fips_ciphers[] = {
+ /* Our primary name[:ASN.1 OID name][:our older names] */
+ ALG(PROV_NAMES_AES_256_ECB, ossl_aes256ecb_functions),
+ ALG(PROV_NAMES_AES_192_ECB, ossl_aes192ecb_functions),
+ ALG(PROV_NAMES_AES_128_ECB, ossl_aes128ecb_functions),
+ ALG(PROV_NAMES_AES_256_CBC, ossl_aes256cbc_functions),
+ ALG(PROV_NAMES_AES_192_CBC, ossl_aes192cbc_functions),
+ ALG(PROV_NAMES_AES_128_CBC, ossl_aes128cbc_functions),
+ ALG(PROV_NAMES_AES_256_CBC_CTS, ossl_aes256cbc_cts_functions),
+ ALG(PROV_NAMES_AES_192_CBC_CTS, ossl_aes192cbc_cts_functions),
+ ALG(PROV_NAMES_AES_128_CBC_CTS, ossl_aes128cbc_cts_functions),
+ ALG(PROV_NAMES_AES_256_OFB, ossl_aes256ofb_functions),
+ ALG(PROV_NAMES_AES_192_OFB, ossl_aes192ofb_functions),
+ ALG(PROV_NAMES_AES_128_OFB, ossl_aes128ofb_functions),
+ ALG(PROV_NAMES_AES_256_CFB, ossl_aes256cfb_functions),
+ ALG(PROV_NAMES_AES_192_CFB, ossl_aes192cfb_functions),
+ ALG(PROV_NAMES_AES_128_CFB, ossl_aes128cfb_functions),
+ ALG(PROV_NAMES_AES_256_CFB1, ossl_aes256cfb1_functions),
+ ALG(PROV_NAMES_AES_192_CFB1, ossl_aes192cfb1_functions),
+ ALG(PROV_NAMES_AES_128_CFB1, ossl_aes128cfb1_functions),
+ ALG(PROV_NAMES_AES_256_CFB8, ossl_aes256cfb8_functions),
+ ALG(PROV_NAMES_AES_192_CFB8, ossl_aes192cfb8_functions),
+ ALG(PROV_NAMES_AES_128_CFB8, ossl_aes128cfb8_functions),
+ ALG(PROV_NAMES_AES_256_CTR, ossl_aes256ctr_functions),
+ ALG(PROV_NAMES_AES_192_CTR, ossl_aes192ctr_functions),
+ ALG(PROV_NAMES_AES_128_CTR, ossl_aes128ctr_functions),
+ ALG(PROV_NAMES_AES_256_XTS, ossl_aes256xts_functions),
+ ALG(PROV_NAMES_AES_128_XTS, ossl_aes128xts_functions),
+ ALG(PROV_NAMES_AES_256_GCM, ossl_aes256gcm_functions),
+ ALG(PROV_NAMES_AES_192_GCM, ossl_aes192gcm_functions),
+ ALG(PROV_NAMES_AES_128_GCM, ossl_aes128gcm_functions),
+ ALG(PROV_NAMES_AES_256_CCM, ossl_aes256ccm_functions),
+ ALG(PROV_NAMES_AES_192_CCM, ossl_aes192ccm_functions),
+ ALG(PROV_NAMES_AES_128_CCM, ossl_aes128ccm_functions),
+ ALG(PROV_NAMES_AES_256_WRAP, ossl_aes256wrap_functions),
+ ALG(PROV_NAMES_AES_192_WRAP, ossl_aes192wrap_functions),
+ ALG(PROV_NAMES_AES_128_WRAP, ossl_aes128wrap_functions),
+ ALG(PROV_NAMES_AES_256_WRAP_PAD, ossl_aes256wrappad_functions),
+ ALG(PROV_NAMES_AES_192_WRAP_PAD, ossl_aes192wrappad_functions),
+ ALG(PROV_NAMES_AES_128_WRAP_PAD, ossl_aes128wrappad_functions),
+ ALG(PROV_NAMES_AES_256_WRAP_INV, ossl_aes256wrapinv_functions),
+ ALG(PROV_NAMES_AES_192_WRAP_INV, ossl_aes192wrapinv_functions),
+ ALG(PROV_NAMES_AES_128_WRAP_INV, ossl_aes128wrapinv_functions),
+ ALG(PROV_NAMES_AES_256_WRAP_PAD_INV, ossl_aes256wrappadinv_functions),
+ ALG(PROV_NAMES_AES_192_WRAP_PAD_INV, ossl_aes192wrappadinv_functions),
+ ALG(PROV_NAMES_AES_128_WRAP_PAD_INV, ossl_aes128wrappadinv_functions),
+ ALGC(PROV_NAMES_AES_128_CBC_HMAC_SHA1, ossl_aes128cbc_hmac_sha1_functions,
+ ossl_cipher_capable_aes_cbc_hmac_sha1),
+ ALGC(PROV_NAMES_AES_256_CBC_HMAC_SHA1, ossl_aes256cbc_hmac_sha1_functions,
+ ossl_cipher_capable_aes_cbc_hmac_sha1),
+ ALGC(PROV_NAMES_AES_128_CBC_HMAC_SHA256, ossl_aes128cbc_hmac_sha256_functions,
+ ossl_cipher_capable_aes_cbc_hmac_sha256),
+ ALGC(PROV_NAMES_AES_256_CBC_HMAC_SHA256, ossl_aes256cbc_hmac_sha256_functions,
+ ossl_cipher_capable_aes_cbc_hmac_sha256),
+#ifndef OPENSSL_NO_DES
+ ALG(PROV_NAMES_DES_EDE3_ECB, ossl_tdes_ede3_ecb_functions),
+ ALG(PROV_NAMES_DES_EDE3_CBC, ossl_tdes_ede3_cbc_functions),
+#endif /* OPENSSL_NO_DES */
+ { { NULL, NULL, NULL }, NULL }
+};
+static OSSL_ALGORITHM exported_fips_ciphers[OSSL_NELEM(fips_ciphers)];
+
+static const OSSL_ALGORITHM fips_macs[] = {
+#ifndef OPENSSL_NO_CMAC
+ { PROV_NAMES_CMAC, FIPS_DEFAULT_PROPERTIES, ossl_cmac_functions },
+#endif
+ { PROV_NAMES_GMAC, FIPS_DEFAULT_PROPERTIES, ossl_gmac_functions },
+ { PROV_NAMES_HMAC, FIPS_DEFAULT_PROPERTIES, ossl_hmac_functions },
+ { PROV_NAMES_KMAC_128, FIPS_DEFAULT_PROPERTIES, ossl_kmac128_functions },
+ { PROV_NAMES_KMAC_256, FIPS_DEFAULT_PROPERTIES, ossl_kmac256_functions },
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM fips_kdfs[] = {
+ { PROV_NAMES_HKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_hkdf_functions },
+ { PROV_NAMES_TLS1_3_KDF, FIPS_DEFAULT_PROPERTIES,
+ ossl_kdf_tls1_3_kdf_functions },
+ { PROV_NAMES_SSKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_sskdf_functions },
+ { PROV_NAMES_PBKDF2, FIPS_DEFAULT_PROPERTIES, ossl_kdf_pbkdf2_functions },
+ { PROV_NAMES_SSHKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_sshkdf_functions },
+ { PROV_NAMES_X963KDF, FIPS_DEFAULT_PROPERTIES,
+ ossl_kdf_x963_kdf_functions },
+ { PROV_NAMES_X942KDF_ASN1, FIPS_DEFAULT_PROPERTIES,
+ ossl_kdf_x942_kdf_functions },
+ { PROV_NAMES_TLS1_PRF, FIPS_DEFAULT_PROPERTIES,
+ ossl_kdf_tls1_prf_functions },
+ { PROV_NAMES_KBKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_kbkdf_functions },
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM fips_rands[] = {
+ { PROV_NAMES_CTR_DRBG, FIPS_DEFAULT_PROPERTIES, ossl_drbg_ctr_functions },
+ { PROV_NAMES_HASH_DRBG, FIPS_DEFAULT_PROPERTIES, ossl_drbg_hash_functions },
+ { PROV_NAMES_HMAC_DRBG, FIPS_DEFAULT_PROPERTIES, ossl_drbg_ossl_hmac_functions },
+ { PROV_NAMES_TEST_RAND, FIPS_UNAPPROVED_PROPERTIES, ossl_test_rng_functions },
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM fips_keyexch[] = {
+#ifndef OPENSSL_NO_DH
+ { PROV_NAMES_DH, FIPS_DEFAULT_PROPERTIES, ossl_dh_keyexch_functions },
+#endif
+#ifndef OPENSSL_NO_EC
+ { PROV_NAMES_ECDH, FIPS_DEFAULT_PROPERTIES, ossl_ecdh_keyexch_functions },
+ { PROV_NAMES_X25519, FIPS_DEFAULT_PROPERTIES, ossl_x25519_keyexch_functions },
+ { PROV_NAMES_X448, FIPS_DEFAULT_PROPERTIES, ossl_x448_keyexch_functions },
+#endif
+ { PROV_NAMES_TLS1_PRF, FIPS_DEFAULT_PROPERTIES,
+ ossl_kdf_tls1_prf_keyexch_functions },
+ { PROV_NAMES_HKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_hkdf_keyexch_functions },
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM fips_signature[] = {
+#ifndef OPENSSL_NO_DSA
+ { PROV_NAMES_DSA, FIPS_DEFAULT_PROPERTIES, ossl_dsa_signature_functions },
+#endif
+ { PROV_NAMES_RSA, FIPS_DEFAULT_PROPERTIES, ossl_rsa_signature_functions },
+#ifndef OPENSSL_NO_EC
+ { PROV_NAMES_ED25519, FIPS_DEFAULT_PROPERTIES, ossl_ed25519_signature_functions },
+ { PROV_NAMES_ED448, FIPS_DEFAULT_PROPERTIES, ossl_ed448_signature_functions },
+ { PROV_NAMES_ECDSA, FIPS_DEFAULT_PROPERTIES, ossl_ecdsa_signature_functions },
+#endif
+ { PROV_NAMES_HMAC, FIPS_DEFAULT_PROPERTIES,
+ ossl_mac_legacy_hmac_signature_functions },
+#ifndef OPENSSL_NO_CMAC
+ { PROV_NAMES_CMAC, FIPS_DEFAULT_PROPERTIES,
+ ossl_mac_legacy_cmac_signature_functions },
+#endif
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM fips_asym_cipher[] = {
+ { PROV_NAMES_RSA, FIPS_DEFAULT_PROPERTIES, ossl_rsa_asym_cipher_functions },
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM fips_asym_kem[] = {
+ { PROV_NAMES_RSA, FIPS_DEFAULT_PROPERTIES, ossl_rsa_asym_kem_functions },
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM fips_keymgmt[] = {
+#ifndef OPENSSL_NO_DH
+ { PROV_NAMES_DH, FIPS_DEFAULT_PROPERTIES, ossl_dh_keymgmt_functions,
+ PROV_DESCS_DH },
+ { PROV_NAMES_DHX, FIPS_DEFAULT_PROPERTIES, ossl_dhx_keymgmt_functions,
+ PROV_DESCS_DHX },
+#endif
+#ifndef OPENSSL_NO_DSA
+ { PROV_NAMES_DSA, FIPS_DEFAULT_PROPERTIES, ossl_dsa_keymgmt_functions,
+ PROV_DESCS_DSA },
+#endif
+ { PROV_NAMES_RSA, FIPS_DEFAULT_PROPERTIES, ossl_rsa_keymgmt_functions,
+ PROV_DESCS_RSA },
+ { PROV_NAMES_RSA_PSS, FIPS_DEFAULT_PROPERTIES,
+ ossl_rsapss_keymgmt_functions, PROV_DESCS_RSA_PSS },
+#ifndef OPENSSL_NO_EC
+ { PROV_NAMES_EC, FIPS_DEFAULT_PROPERTIES, ossl_ec_keymgmt_functions,
+ PROV_DESCS_EC },
+ { PROV_NAMES_X25519, FIPS_DEFAULT_PROPERTIES, ossl_x25519_keymgmt_functions,
+ PROV_DESCS_X25519 },
+ { PROV_NAMES_X448, FIPS_DEFAULT_PROPERTIES, ossl_x448_keymgmt_functions,
+ PROV_DESCS_X448 },
+ { PROV_NAMES_ED25519, FIPS_DEFAULT_PROPERTIES, ossl_ed25519_keymgmt_functions,
+ PROV_DESCS_ED25519 },
+ { PROV_NAMES_ED448, FIPS_DEFAULT_PROPERTIES, ossl_ed448_keymgmt_functions,
+ PROV_DESCS_ED448 },
+#endif
+ { PROV_NAMES_TLS1_PRF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_keymgmt_functions,
+ PROV_DESCS_TLS1_PRF_SIGN },
+ { PROV_NAMES_HKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_keymgmt_functions,
+ PROV_DESCS_HKDF_SIGN },
+ { PROV_NAMES_HMAC, FIPS_DEFAULT_PROPERTIES, ossl_mac_legacy_keymgmt_functions,
+ PROV_DESCS_HMAC_SIGN },
+#ifndef OPENSSL_NO_CMAC
+ { PROV_NAMES_CMAC, FIPS_DEFAULT_PROPERTIES,
+ ossl_cmac_legacy_keymgmt_functions, PROV_DESCS_CMAC_SIGN },
+#endif
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM *fips_query(void *provctx, int operation_id,
+ int *no_cache)
+{
+ *no_cache = 0;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ switch (operation_id) {
+ case OSSL_OP_DIGEST:
+ return fips_digests;
+ case OSSL_OP_CIPHER:
+ return exported_fips_ciphers;
+ case OSSL_OP_MAC:
+ return fips_macs;
+ case OSSL_OP_KDF:
+ return fips_kdfs;
+ case OSSL_OP_RAND:
+ return fips_rands;
+ case OSSL_OP_KEYMGMT:
+ return fips_keymgmt;
+ case OSSL_OP_KEYEXCH:
+ return fips_keyexch;
+ case OSSL_OP_SIGNATURE:
+ return fips_signature;
+ case OSSL_OP_ASYM_CIPHER:
+ return fips_asym_cipher;
+ case OSSL_OP_KEM:
+ return fips_asym_kem;
+ }
+ return NULL;
+}
+
+static void fips_teardown(void *provctx)
+{
+ OSSL_LIB_CTX_free(PROV_LIBCTX_OF(provctx));
+ ossl_prov_ctx_free(provctx);
+}
+
+static void fips_intern_teardown(void *provctx)
+{
+ /*
+ * We know that the library context is the same as for the outer provider,
+ * so no need to destroy it here.
+ */
+ ossl_prov_ctx_free(provctx);
+}
+
+/* Functions we provide to the core */
+static const OSSL_DISPATCH fips_dispatch_table[] = {
+ { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))fips_teardown },
+ { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void))fips_gettable_params },
+ { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))fips_get_params },
+ { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fips_query },
+ { OSSL_FUNC_PROVIDER_GET_CAPABILITIES,
+ (void (*)(void))ossl_prov_get_capabilities },
+ { OSSL_FUNC_PROVIDER_SELF_TEST, (void (*)(void))fips_self_test },
+ { 0, NULL }
+};
+
+/* Functions we provide to ourself */
+static const OSSL_DISPATCH intern_dispatch_table[] = {
+ { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))fips_intern_teardown },
+ { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fips_query },
+ { 0, NULL }
+};
+
+/*
+ * On VMS, the provider init function name is expected to be uppercase,
+ * see the pragmas in <openssl/core.h>. Let's do the same with this
+ * internal name. This is how symbol names are treated by default
+ * by the compiler if nothing else is said, but since this is part
+ * of libfips, and we build our libraries with mixed case symbol names,
+ * we must switch back to this default explicitly here.
+ */
+#ifdef __VMS
+# pragma names save
+# pragma names uppercase,truncated
+#endif
+OSSL_provider_init_fn OSSL_provider_init_int;
+#ifdef __VMS
+# pragma names restore
+#endif
+int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in,
+ const OSSL_DISPATCH **out,
+ void **provctx)
+{
+ FIPS_GLOBAL *fgbl;
+ OSSL_LIB_CTX *libctx = NULL;
+ SELF_TEST_POST_PARAMS selftest_params;
+
+ memset(&selftest_params, 0, sizeof(selftest_params));
+
+ if (!ossl_prov_seeding_from_dispatch(in))
+ goto err;
+ for (; in->function_id != 0; in++) {
+ /*
+ * We do not support the scenario of an application linked against
+ * multiple versions of libcrypto (e.g. one static and one dynamic), but
+ * sharing a single fips.so. We do a simple sanity check here.
+ */
+#define set_func(c, f) if (c == NULL) c = f; else if (c != f) return 0;
+ switch (in->function_id) {
+ case OSSL_FUNC_CORE_GET_LIBCTX:
+ set_func(c_get_libctx, OSSL_FUNC_core_get_libctx(in));
+ break;
+ case OSSL_FUNC_CORE_GETTABLE_PARAMS:
+ set_func(c_gettable_params, OSSL_FUNC_core_gettable_params(in));
+ break;
+ case OSSL_FUNC_CORE_GET_PARAMS:
+ set_func(c_get_params, OSSL_FUNC_core_get_params(in));
+ break;
+ case OSSL_FUNC_CORE_THREAD_START:
+ set_func(c_thread_start, OSSL_FUNC_core_thread_start(in));
+ break;
+ case OSSL_FUNC_CORE_NEW_ERROR:
+ set_func(c_new_error, OSSL_FUNC_core_new_error(in));
+ break;
+ case OSSL_FUNC_CORE_SET_ERROR_DEBUG:
+ set_func(c_set_error_debug, OSSL_FUNC_core_set_error_debug(in));
+ break;
+ case OSSL_FUNC_CORE_VSET_ERROR:
+ set_func(c_vset_error, OSSL_FUNC_core_vset_error(in));
+ break;
+ case OSSL_FUNC_CORE_SET_ERROR_MARK:
+ set_func(c_set_error_mark, OSSL_FUNC_core_set_error_mark(in));
+ break;
+ case OSSL_FUNC_CORE_CLEAR_LAST_ERROR_MARK:
+ set_func(c_clear_last_error_mark,
+ OSSL_FUNC_core_clear_last_error_mark(in));
+ break;
+ case OSSL_FUNC_CORE_POP_ERROR_TO_MARK:
+ set_func(c_pop_error_to_mark, OSSL_FUNC_core_pop_error_to_mark(in));
+ break;
+ case OSSL_FUNC_CRYPTO_MALLOC:
+ set_func(c_CRYPTO_malloc, OSSL_FUNC_CRYPTO_malloc(in));
+ break;
+ case OSSL_FUNC_CRYPTO_ZALLOC:
+ set_func(c_CRYPTO_zalloc, OSSL_FUNC_CRYPTO_zalloc(in));
+ break;
+ case OSSL_FUNC_CRYPTO_FREE:
+ set_func(c_CRYPTO_free, OSSL_FUNC_CRYPTO_free(in));
+ break;
+ case OSSL_FUNC_CRYPTO_CLEAR_FREE:
+ set_func(c_CRYPTO_clear_free, OSSL_FUNC_CRYPTO_clear_free(in));
+ break;
+ case OSSL_FUNC_CRYPTO_REALLOC:
+ set_func(c_CRYPTO_realloc, OSSL_FUNC_CRYPTO_realloc(in));
+ break;
+ case OSSL_FUNC_CRYPTO_CLEAR_REALLOC:
+ set_func(c_CRYPTO_clear_realloc,
+ OSSL_FUNC_CRYPTO_clear_realloc(in));
+ break;
+ case OSSL_FUNC_CRYPTO_SECURE_MALLOC:
+ set_func(c_CRYPTO_secure_malloc,
+ OSSL_FUNC_CRYPTO_secure_malloc(in));
+ break;
+ case OSSL_FUNC_CRYPTO_SECURE_ZALLOC:
+ set_func(c_CRYPTO_secure_zalloc,
+ OSSL_FUNC_CRYPTO_secure_zalloc(in));
+ break;
+ case OSSL_FUNC_CRYPTO_SECURE_FREE:
+ set_func(c_CRYPTO_secure_free,
+ OSSL_FUNC_CRYPTO_secure_free(in));
+ break;
+ case OSSL_FUNC_CRYPTO_SECURE_CLEAR_FREE:
+ set_func(c_CRYPTO_secure_clear_free,
+ OSSL_FUNC_CRYPTO_secure_clear_free(in));
+ break;
+ case OSSL_FUNC_CRYPTO_SECURE_ALLOCATED:
+ set_func(c_CRYPTO_secure_allocated,
+ OSSL_FUNC_CRYPTO_secure_allocated(in));
+ break;
+ case OSSL_FUNC_BIO_NEW_FILE:
+ set_func(selftest_params.bio_new_file_cb,
+ OSSL_FUNC_BIO_new_file(in));
+ break;
+ case OSSL_FUNC_BIO_NEW_MEMBUF:
+ set_func(selftest_params.bio_new_buffer_cb,
+ OSSL_FUNC_BIO_new_membuf(in));
+ break;
+ case OSSL_FUNC_BIO_READ_EX:
+ set_func(selftest_params.bio_read_ex_cb,
+ OSSL_FUNC_BIO_read_ex(in));
+ break;
+ case OSSL_FUNC_BIO_FREE:
+ set_func(selftest_params.bio_free_cb, OSSL_FUNC_BIO_free(in));
+ break;
+ case OSSL_FUNC_BIO_VSNPRINTF:
+ set_func(c_BIO_vsnprintf, OSSL_FUNC_BIO_vsnprintf(in));
+ break;
+ case OSSL_FUNC_SELF_TEST_CB:
+ set_func(c_stcbfn, OSSL_FUNC_self_test_cb(in));
+ break;
+ default:
+ /* Just ignore anything we don't understand */
+ break;
+ }
+ }
+
+ /* Create a context. */
+ if ((*provctx = ossl_prov_ctx_new()) == NULL
+ || (libctx = OSSL_LIB_CTX_new()) == NULL) {
+ /*
+ * We free libctx separately here and only here because it hasn't
+ * been attached to *provctx. All other error paths below rely
+ * solely on fips_teardown.
+ */
+ OSSL_LIB_CTX_free(libctx);
+ goto err;
+ }
+
+ if ((fgbl = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_FIPS_PROV_INDEX,
+ &fips_prov_ossl_ctx_method)) == NULL)
+ goto err;
+
+ fgbl->handle = handle;
+
+ /*
+ * We did initial set up of selftest_params in a local copy, because we
+ * could not create fgbl until c_CRYPTO_zalloc was defined in the loop
+ * above.
+ */
+ fgbl->selftest_params = selftest_params;
+
+ fgbl->selftest_params.libctx = libctx;
+
+ set_self_test_cb(fgbl);
+
+ if (!fips_get_params_from_core(fgbl)) {
+ /* Error already raised */
+ goto err;
+ }
+ /*
+ * Disable the conditional error check if it's disabled in the fips config
+ * file.
+ */
+ if (fgbl->selftest_params.conditional_error_check != NULL
+ && strcmp(fgbl->selftest_params.conditional_error_check, "0") == 0)
+ SELF_TEST_disable_conditional_error_state();
+
+ /* Disable the security check if it's disabled in the fips config file. */
+ if (fgbl->fips_security_check_option != NULL
+ && strcmp(fgbl->fips_security_check_option, "0") == 0)
+ fgbl->fips_security_checks = 0;
+
+ ossl_prov_cache_exported_algorithms(fips_ciphers, exported_fips_ciphers);
+
+ if (!SELF_TEST_post(&fgbl->selftest_params, 0)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_POST_FAILURE);
+ goto err;
+ }
+
+ ossl_prov_ctx_set0_libctx(*provctx, libctx);
+ ossl_prov_ctx_set0_handle(*provctx, handle);
+
+ *out = fips_dispatch_table;
+ return 1;
+ err:
+ fips_teardown(*provctx);
+ OSSL_LIB_CTX_free(libctx);
+ *provctx = NULL;
+ return 0;
+}
+
+/*
+ * The internal init function used when the FIPS module uses EVP to call
+ * another algorithm also in the FIPS module. This is a recursive call that has
+ * been made from within the FIPS module itself. To make this work, we populate
+ * the provider context of this inner instance with the same library context
+ * that was used in the EVP call that initiated this recursive call.
+ */
+OSSL_provider_init_fn ossl_fips_intern_provider_init;
+int ossl_fips_intern_provider_init(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in,
+ const OSSL_DISPATCH **out,
+ void **provctx)
+{
+ OSSL_FUNC_core_get_libctx_fn *c_internal_get_libctx = NULL;
+
+ for (; in->function_id != 0; in++) {
+ switch (in->function_id) {
+ case OSSL_FUNC_CORE_GET_LIBCTX:
+ c_internal_get_libctx = OSSL_FUNC_core_get_libctx(in);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (c_internal_get_libctx == NULL)
+ return 0;
+
+ if ((*provctx = ossl_prov_ctx_new()) == NULL)
+ return 0;
+
+ /*
+ * Using the parent library context only works because we are a built-in
+ * internal provider. This is not something that most providers would be
+ * able to do.
+ */
+ ossl_prov_ctx_set0_libctx(*provctx,
+ (OSSL_LIB_CTX *)c_internal_get_libctx(handle));
+ ossl_prov_ctx_set0_handle(*provctx, handle);
+
+ *out = intern_dispatch_table;
+ return 1;
+}
+
+void ERR_new(void)
+{
+ c_new_error(NULL);
+}
+
+void ERR_set_debug(const char *file, int line, const char *func)
+{
+ c_set_error_debug(NULL, file, line, func);
+}
+
+void ERR_set_error(int lib, int reason, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ c_vset_error(NULL, ERR_PACK(lib, 0, reason), fmt, args);
+ va_end(args);
+}
+
+void ERR_vset_error(int lib, int reason, const char *fmt, va_list args)
+{
+ c_vset_error(NULL, ERR_PACK(lib, 0, reason), fmt, args);
+}
+
+int ERR_set_mark(void)
+{
+ return c_set_error_mark(NULL);
+}
+
+int ERR_clear_last_mark(void)
+{
+ return c_clear_last_error_mark(NULL);
+}
+
+int ERR_pop_to_mark(void)
+{
+ return c_pop_error_to_mark(NULL);
+}
+
+/*
+ * This must take a library context, since it's called from the depths
+ * of crypto/initthread.c code, where it's (correctly) assumed that the
+ * passed caller argument is an OSSL_LIB_CTX pointer (since the same routine
+ * is also called from other parts of libcrypto, which all pass around a
+ * OSSL_LIB_CTX pointer)
+ */
+const OSSL_CORE_HANDLE *FIPS_get_core_handle(OSSL_LIB_CTX *libctx)
+{
+ FIPS_GLOBAL *fgbl = ossl_lib_ctx_get_data(libctx,
+ OSSL_LIB_CTX_FIPS_PROV_INDEX,
+ &fips_prov_ossl_ctx_method);
+
+ if (fgbl == NULL)
+ return NULL;
+
+ return fgbl->handle;
+}
+
+void *CRYPTO_malloc(size_t num, const char *file, int line)
+{
+ return c_CRYPTO_malloc(num, file, line);
+}
+
+void *CRYPTO_zalloc(size_t num, const char *file, int line)
+{
+ return c_CRYPTO_zalloc(num, file, line);
+}
+
+void CRYPTO_free(void *ptr, const char *file, int line)
+{
+ c_CRYPTO_free(ptr, file, line);
+}
+
+void CRYPTO_clear_free(void *ptr, size_t num, const char *file, int line)
+{
+ c_CRYPTO_clear_free(ptr, num, file, line);
+}
+
+void *CRYPTO_realloc(void *addr, size_t num, const char *file, int line)
+{
+ return c_CRYPTO_realloc(addr, num, file, line);
+}
+
+void *CRYPTO_clear_realloc(void *addr, size_t old_num, size_t num,
+ const char *file, int line)
+{
+ return c_CRYPTO_clear_realloc(addr, old_num, num, file, line);
+}
+
+void *CRYPTO_secure_malloc(size_t num, const char *file, int line)
+{
+ return c_CRYPTO_secure_malloc(num, file, line);
+}
+
+void *CRYPTO_secure_zalloc(size_t num, const char *file, int line)
+{
+ return c_CRYPTO_secure_zalloc(num, file, line);
+}
+
+void CRYPTO_secure_free(void *ptr, const char *file, int line)
+{
+ c_CRYPTO_secure_free(ptr, file, line);
+}
+
+void CRYPTO_secure_clear_free(void *ptr, size_t num, const char *file, int line)
+{
+ c_CRYPTO_secure_clear_free(ptr, num, file, line);
+}
+
+int CRYPTO_secure_allocated(const void *ptr)
+{
+ return c_CRYPTO_secure_allocated(ptr);
+}
+
+int BIO_snprintf(char *buf, size_t n, const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+ ret = c_BIO_vsnprintf(buf, n, format, args);
+ va_end(args);
+ return ret;
+}
+
+int FIPS_security_check_enabled(OSSL_LIB_CTX *libctx)
+{
+ FIPS_GLOBAL *fgbl = ossl_lib_ctx_get_data(libctx,
+ OSSL_LIB_CTX_FIPS_PROV_INDEX,
+ &fips_prov_ossl_ctx_method);
+
+ return fgbl->fips_security_checks;
+}
+
+void OSSL_SELF_TEST_get_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK **cb,
+ void **cbarg)
+{
+ assert(libctx != NULL);
+
+ if (c_stcbfn != NULL && c_get_libctx != NULL) {
+ /* Get the parent libctx */
+ c_stcbfn(c_get_libctx(FIPS_get_core_handle(libctx)), cb, cbarg);
+ } else {
+ if (cb != NULL)
+ *cb = NULL;
+ if (cbarg != NULL)
+ *cbarg = NULL;
+ }
+}
diff --git a/providers/fips/self_test.c b/providers/fips/self_test.c
new file mode 100644
index 000000000000..80d048a847b0
--- /dev/null
+++ b/providers/fips/self_test.c
@@ -0,0 +1,412 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/params.h>
+#include <openssl/crypto.h>
+#include "internal/cryptlib.h"
+#include <openssl/fipskey.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include "e_os.h"
+#include "prov/providercommon.h"
+
+/*
+ * We're cheating here. Normally we don't allow RUN_ONCE usage inside the FIPS
+ * module because all such initialisation should be associated with an
+ * individual OSSL_LIB_CTX. That doesn't work with the self test though because
+ * it should be run once regardless of the number of OSSL_LIB_CTXs we have.
+ */
+#define ALLOW_RUN_ONCE_IN_FIPS
+#include "internal/thread_once.h"
+#include "self_test.h"
+
+#define FIPS_STATE_INIT 0
+#define FIPS_STATE_SELFTEST 1
+#define FIPS_STATE_RUNNING 2
+#define FIPS_STATE_ERROR 3
+
+/*
+ * The number of times the module will report it is in the error state
+ * before going quiet.
+ */
+#define FIPS_ERROR_REPORTING_RATE_LIMIT 10
+
+/* The size of a temp buffer used to read in data */
+#define INTEGRITY_BUF_SIZE (4096)
+#define MAX_MD_SIZE 64
+#define MAC_NAME "HMAC"
+#define DIGEST_NAME "SHA256"
+
+static int FIPS_conditional_error_check = 1;
+static CRYPTO_RWLOCK *self_test_lock = NULL;
+static CRYPTO_RWLOCK *fips_state_lock = NULL;
+static unsigned char fixed_key[32] = { FIPS_KEY_ELEMENTS };
+
+static CRYPTO_ONCE fips_self_test_init = CRYPTO_ONCE_STATIC_INIT;
+DEFINE_RUN_ONCE_STATIC(do_fips_self_test_init)
+{
+ /*
+ * These locks get freed in platform specific ways that may occur after we
+ * do mem leak checking. If we don't know how to free it for a particular
+ * platform then we just leak it deliberately.
+ */
+ self_test_lock = CRYPTO_THREAD_lock_new();
+ fips_state_lock = CRYPTO_THREAD_lock_new();
+ return self_test_lock != NULL;
+}
+
+/*
+ * Declarations for the DEP entry/exit points.
+ * Ones not required or incorrect need to be undefined or redefined respectively.
+ */
+#define DEP_INITIAL_STATE FIPS_STATE_INIT
+#define DEP_INIT_ATTRIBUTE static
+#define DEP_FINI_ATTRIBUTE static
+
+static void init(void);
+static void cleanup(void);
+
+/*
+ * This is the Default Entry Point (DEP) code.
+ * See FIPS 140-2 IG 9.10
+ */
+#if defined(_WIN32) || defined(__CYGWIN__)
+# ifdef __CYGWIN__
+/* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */
+# include <windows.h>
+/*
+ * this has side-effect of _WIN32 getting defined, which otherwise is
+ * mutually exclusive with __CYGWIN__...
+ */
+# endif
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ init();
+ break;
+ case DLL_PROCESS_DETACH:
+ cleanup();
+ break;
+ default:
+ break;
+ }
+ return TRUE;
+}
+
+#elif defined(__GNUC__) && !defined(_AIX)
+# undef DEP_INIT_ATTRIBUTE
+# undef DEP_FINI_ATTRIBUTE
+# define DEP_INIT_ATTRIBUTE static __attribute__((constructor))
+# define DEP_FINI_ATTRIBUTE static __attribute__((destructor))
+
+#elif defined(__sun)
+# pragma init(init)
+# pragma fini(cleanup)
+
+#elif defined(_AIX) && !defined(__GNUC__)
+void _init(void);
+void _cleanup(void);
+# pragma init(_init)
+# pragma fini(_cleanup)
+void _init(void)
+{
+ init();
+}
+void _cleanup(void)
+{
+ cleanup();
+}
+
+#elif defined(__hpux)
+# pragma init "init"
+# pragma fini "cleanup"
+
+#elif defined(__TANDEM)
+/* Method automatically called by the NonStop OS when the DLL loads */
+void __INIT__init(void) {
+ init();
+}
+
+/* Method automatically called by the NonStop OS prior to unloading the DLL */
+void __TERM__cleanup(void) {
+ cleanup();
+}
+
+#else
+/*
+ * This build does not support any kind of DEP.
+ * We force the self-tests to run as part of the FIPS provider initialisation
+ * rather than being triggered by the DEP.
+ */
+# undef DEP_INIT_ATTRIBUTE
+# undef DEP_FINI_ATTRIBUTE
+# undef DEP_INITIAL_STATE
+# define DEP_INITIAL_STATE FIPS_STATE_SELFTEST
+#endif
+
+static int FIPS_state = DEP_INITIAL_STATE;
+
+#if defined(DEP_INIT_ATTRIBUTE)
+DEP_INIT_ATTRIBUTE void init(void)
+{
+ FIPS_state = FIPS_STATE_SELFTEST;
+}
+#endif
+
+#if defined(DEP_FINI_ATTRIBUTE)
+DEP_FINI_ATTRIBUTE void cleanup(void)
+{
+ CRYPTO_THREAD_lock_free(self_test_lock);
+ CRYPTO_THREAD_lock_free(fips_state_lock);
+}
+#endif
+
+/*
+ * Calculate the HMAC SHA256 of data read using a BIO and read_cb, and verify
+ * the result matches the expected value.
+ * Return 1 if verified, or 0 if it fails.
+ */
+static int verify_integrity(OSSL_CORE_BIO *bio, OSSL_FUNC_BIO_read_ex_fn read_ex_cb,
+ unsigned char *expected, size_t expected_len,
+ OSSL_LIB_CTX *libctx, OSSL_SELF_TEST *ev,
+ const char *event_type)
+{
+ int ret = 0, status;
+ unsigned char out[MAX_MD_SIZE];
+ unsigned char buf[INTEGRITY_BUF_SIZE];
+ size_t bytes_read = 0, out_len = 0;
+ EVP_MAC *mac = NULL;
+ EVP_MAC_CTX *ctx = NULL;
+ OSSL_PARAM params[2], *p = params;
+
+ OSSL_SELF_TEST_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC);
+
+ mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL);
+ if (mac == NULL)
+ goto err;
+ ctx = EVP_MAC_CTX_new(mac);
+ if (ctx == NULL)
+ goto err;
+
+ *p++ = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME, 0);
+ *p = OSSL_PARAM_construct_end();
+
+ if (!EVP_MAC_init(ctx, fixed_key, sizeof(fixed_key), params))
+ goto err;
+
+ while (1) {
+ status = read_ex_cb(bio, buf, sizeof(buf), &bytes_read);
+ if (status != 1)
+ break;
+ if (!EVP_MAC_update(ctx, buf, bytes_read))
+ goto err;
+ }
+ if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out)))
+ goto err;
+
+ OSSL_SELF_TEST_oncorrupt_byte(ev, out);
+ if (expected_len != out_len
+ || memcmp(expected, out, out_len) != 0)
+ goto err;
+ ret = 1;
+err:
+ OSSL_SELF_TEST_onend(ev, ret);
+ EVP_MAC_CTX_free(ctx);
+ EVP_MAC_free(mac);
+ return ret;
+}
+
+static void set_fips_state(int state)
+{
+ if (ossl_assert(CRYPTO_THREAD_write_lock(fips_state_lock) != 0)) {
+ FIPS_state = state;
+ CRYPTO_THREAD_unlock(fips_state_lock);
+ }
+}
+
+/* This API is triggered either on loading of the FIPS module or on demand */
+int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
+{
+ int ok = 0;
+ int kats_already_passed = 0;
+ long checksum_len;
+ OSSL_CORE_BIO *bio_module = NULL, *bio_indicator = NULL;
+ unsigned char *module_checksum = NULL;
+ unsigned char *indicator_checksum = NULL;
+ int loclstate;
+ OSSL_SELF_TEST *ev = NULL;
+
+ if (!RUN_ONCE(&fips_self_test_init, do_fips_self_test_init))
+ return 0;
+
+ if (!CRYPTO_THREAD_read_lock(fips_state_lock))
+ return 0;
+ loclstate = FIPS_state;
+ CRYPTO_THREAD_unlock(fips_state_lock);
+
+ if (loclstate == FIPS_STATE_RUNNING) {
+ if (!on_demand_test)
+ return 1;
+ } else if (loclstate != FIPS_STATE_SELFTEST) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_STATE);
+ return 0;
+ }
+
+ if (!CRYPTO_THREAD_write_lock(self_test_lock))
+ return 0;
+ if (!CRYPTO_THREAD_read_lock(fips_state_lock)) {
+ CRYPTO_THREAD_unlock(self_test_lock);
+ return 0;
+ }
+ if (FIPS_state == FIPS_STATE_RUNNING) {
+ CRYPTO_THREAD_unlock(fips_state_lock);
+ if (!on_demand_test) {
+ CRYPTO_THREAD_unlock(self_test_lock);
+ return 1;
+ }
+ set_fips_state(FIPS_STATE_SELFTEST);
+ } else if (FIPS_state != FIPS_STATE_SELFTEST) {
+ CRYPTO_THREAD_unlock(fips_state_lock);
+ CRYPTO_THREAD_unlock(self_test_lock);
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_STATE);
+ return 0;
+ } else {
+ CRYPTO_THREAD_unlock(fips_state_lock);
+ }
+
+ if (st == NULL
+ || st->module_checksum_data == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CONFIG_DATA);
+ goto end;
+ }
+
+ ev = OSSL_SELF_TEST_new(st->cb, st->cb_arg);
+ if (ev == NULL)
+ goto end;
+
+ module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data,
+ &checksum_len);
+ if (module_checksum == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA);
+ goto end;
+ }
+ bio_module = (*st->bio_new_file_cb)(st->module_filename, "rb");
+
+ /* Always check the integrity of the fips module */
+ if (bio_module == NULL
+ || !verify_integrity(bio_module, st->bio_read_ex_cb,
+ module_checksum, checksum_len, st->libctx,
+ ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MODULE_INTEGRITY_FAILURE);
+ goto end;
+ }
+
+ /* This will be NULL during installation - so the self test KATS will run */
+ if (st->indicator_data != NULL) {
+ /*
+ * If the kats have already passed indicator is set - then check the
+ * integrity of the indicator.
+ */
+ if (st->indicator_checksum_data == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CONFIG_DATA);
+ goto end;
+ }
+ indicator_checksum = OPENSSL_hexstr2buf(st->indicator_checksum_data,
+ &checksum_len);
+ if (indicator_checksum == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA);
+ goto end;
+ }
+
+ bio_indicator =
+ (*st->bio_new_buffer_cb)(st->indicator_data,
+ strlen(st->indicator_data));
+ if (bio_indicator == NULL
+ || !verify_integrity(bio_indicator, st->bio_read_ex_cb,
+ indicator_checksum, checksum_len,
+ st->libctx, ev,
+ OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INDICATOR_INTEGRITY_FAILURE);
+ goto end;
+ } else {
+ kats_already_passed = 1;
+ }
+ }
+
+ /*
+ * Only runs the KAT's during installation OR on_demand().
+ * NOTE: If the installation option 'self_test_onload' is chosen then this
+ * path will always be run, since kats_already_passed will always be 0.
+ */
+ if (on_demand_test || kats_already_passed == 0) {
+ if (!SELF_TEST_kats(ev, st->libctx)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_KAT_FAILURE);
+ goto end;
+ }
+ }
+ ok = 1;
+end:
+ OSSL_SELF_TEST_free(ev);
+ OPENSSL_free(module_checksum);
+ OPENSSL_free(indicator_checksum);
+
+ if (st != NULL) {
+ (*st->bio_free_cb)(bio_indicator);
+ (*st->bio_free_cb)(bio_module);
+ }
+ if (ok)
+ set_fips_state(FIPS_STATE_RUNNING);
+ else
+ ossl_set_error_state(OSSL_SELF_TEST_TYPE_NONE);
+ CRYPTO_THREAD_unlock(self_test_lock);
+
+ return ok;
+}
+
+void SELF_TEST_disable_conditional_error_state(void)
+{
+ FIPS_conditional_error_check = 0;
+}
+
+void ossl_set_error_state(const char *type)
+{
+ int cond_test = (type != NULL && strcmp(type, OSSL_SELF_TEST_TYPE_PCT) == 0);
+
+ if (!cond_test || (FIPS_conditional_error_check == 1)) {
+ set_fips_state(FIPS_STATE_ERROR);
+ ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE);
+ } else {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_CONDITIONAL_ERROR);
+ }
+}
+
+int ossl_prov_is_running(void)
+{
+ int res;
+ static unsigned int rate_limit = 0;
+
+ if (!CRYPTO_THREAD_read_lock(fips_state_lock))
+ return 0;
+ res = FIPS_state == FIPS_STATE_RUNNING
+ || FIPS_state == FIPS_STATE_SELFTEST;
+ if (FIPS_state == FIPS_STATE_ERROR) {
+ CRYPTO_THREAD_unlock(fips_state_lock);
+ if (!CRYPTO_THREAD_write_lock(fips_state_lock))
+ return 0;
+ if (rate_limit++ < FIPS_ERROR_REPORTING_RATE_LIMIT)
+ ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_IN_ERROR_STATE);
+ }
+ CRYPTO_THREAD_unlock(fips_state_lock);
+ return res;
+}
diff --git a/providers/fips/self_test.h b/providers/fips/self_test.h
new file mode 100644
index 000000000000..ff5928eeb4b9
--- /dev/null
+++ b/providers/fips/self_test.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_dispatch.h>
+#include <openssl/types.h>
+#include <openssl/self_test.h>
+
+typedef struct self_test_post_params_st {
+ /* FIPS module integrity check parameters */
+ const char *module_filename; /* Module file to perform MAC on */
+ const char *module_checksum_data; /* Expected module MAC integrity */
+
+ /* Used for KAT install indicator integrity check */
+ const char *indicator_version; /* version - for future proofing */
+ const char *indicator_data; /* data to perform MAC on */
+ const char *indicator_checksum_data; /* Expected MAC integrity value */
+
+ /* Used for continuous tests */
+ const char *conditional_error_check;
+
+ /* BIO callbacks supplied to the FIPS provider */
+ OSSL_FUNC_BIO_new_file_fn *bio_new_file_cb;
+ OSSL_FUNC_BIO_new_membuf_fn *bio_new_buffer_cb;
+ OSSL_FUNC_BIO_read_ex_fn *bio_read_ex_cb;
+ OSSL_FUNC_BIO_free_fn *bio_free_cb;
+ OSSL_CALLBACK *cb;
+ void *cb_arg;
+ OSSL_LIB_CTX *libctx;
+
+} SELF_TEST_POST_PARAMS;
+
+int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test);
+int SELF_TEST_kats(OSSL_SELF_TEST *event, OSSL_LIB_CTX *libctx);
+
+void SELF_TEST_disable_conditional_error_state(void);
diff --git a/providers/fips/self_test_data.inc b/providers/fips/self_test_data.inc
new file mode 100644
index 000000000000..8ae8cd6f4a5a
--- /dev/null
+++ b/providers/fips/self_test_data.inc
@@ -0,0 +1,1634 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Macros to build Self test data */
+#define ITM(x) ((void *)&x), sizeof(x)
+#define ITM_STR(x) ((void *)&x), (sizeof(x) - 1)
+
+#define ST_KAT_PARAM_END() { "", 0, NULL, 0 }
+#define ST_KAT_PARAM_BIGNUM(name, data) \
+ { name, OSSL_PARAM_UNSIGNED_INTEGER, ITM(data) }
+#define ST_KAT_PARAM_OCTET(name, data) \
+ { name, OSSL_PARAM_OCTET_STRING, ITM(data) }
+#define ST_KAT_PARAM_UTF8STRING(name, data) \
+ { name, OSSL_PARAM_UTF8_STRING, ITM_STR(data) }
+#define ST_KAT_PARAM_UTF8CHAR(name, data) \
+ { name, OSSL_PARAM_UTF8_STRING, ITM(data) }
+#define ST_KAT_PARAM_INT(name, i) \
+ { name, OSSL_PARAM_INTEGER, ITM(i) }
+
+/* used to store raw parameters for keys and algorithms */
+typedef struct st_kat_param_st {
+ const char *name; /* an OSSL_PARAM name */
+ size_t type; /* the type associated with the data */
+ const void *data; /* unsigned char [], or char [] depending on the type */
+ size_t data_len; /* the length of the data */
+} ST_KAT_PARAM;
+
+typedef struct st_kat_st {
+ const char *desc;
+ const char *algorithm;
+ const unsigned char *pt;
+ size_t pt_len;
+ const unsigned char *expected;
+ size_t expected_len;
+} ST_KAT;
+
+#define CIPHER_MODE_ENCRYPT 1
+#define CIPHER_MODE_DECRYPT 2
+#define CIPHER_MODE_ALL (CIPHER_MODE_ENCRYPT | CIPHER_MODE_DECRYPT)
+
+typedef ST_KAT ST_KAT_DIGEST;
+typedef struct st_kat_cipher_st {
+ ST_KAT base;
+ int mode;
+ const unsigned char *key;
+ size_t key_len;
+ const unsigned char *iv;
+ size_t iv_len;
+ const unsigned char *aad;
+ size_t aad_len;
+ const unsigned char *tag;
+ size_t tag_len;
+} ST_KAT_CIPHER;
+
+typedef struct st_kat_kdf_st {
+ const char *desc;
+ const char *algorithm;
+ const ST_KAT_PARAM *params;
+ const unsigned char *expected;
+ size_t expected_len;
+} ST_KAT_KDF;
+
+typedef struct st_kat_drbg_st {
+ const char *desc;
+ const char *algorithm;
+ const char *param_name;
+ char *param_value;
+ const unsigned char *entropyin;
+ size_t entropyinlen;
+ const unsigned char *nonce;
+ size_t noncelen;
+ const unsigned char *persstr;
+ size_t persstrlen;
+ const unsigned char *entropyinpr1;
+ size_t entropyinpr1len;
+ const unsigned char *entropyinpr2;
+ size_t entropyinpr2len;
+ const unsigned char *entropyaddin1;
+ size_t entropyaddin1len;
+ const unsigned char *entropyaddin2;
+ size_t entropyaddin2len;
+ const unsigned char *expected;
+ size_t expectedlen;
+} ST_KAT_DRBG;
+
+typedef struct st_kat_kas_st {
+ const char *desc;
+ const char *algorithm;
+
+ const ST_KAT_PARAM *key_group;
+ const ST_KAT_PARAM *key_host_data;
+ const ST_KAT_PARAM *key_peer_data;
+
+ const unsigned char *expected;
+ size_t expected_len;
+} ST_KAT_KAS;
+
+typedef struct st_kat_sign_st {
+ const char *desc;
+ const char *algorithm;
+ const char *mdalgorithm;
+ const ST_KAT_PARAM *key;
+ const unsigned char *sig_expected; /* Set to NULL if this value changes */
+ size_t sig_expected_len;
+} ST_KAT_SIGN;
+
+typedef struct st_kat_asym_cipher_st {
+ const char *desc;
+ const char *algorithm;
+ int encrypt;
+ const ST_KAT_PARAM *key;
+ const ST_KAT_PARAM *postinit;
+ const unsigned char *in;
+ size_t in_len;
+ const unsigned char *expected;
+ size_t expected_len;
+} ST_KAT_ASYM_CIPHER;
+
+/*- DIGEST TEST DATA */
+static const unsigned char sha1_pt[] = "abc";
+static const unsigned char sha1_digest[] = {
+ 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, 0x25, 0x71,
+ 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D
+};
+
+static const unsigned char sha512_pt[] = "abc";
+static const unsigned char sha512_digest[] = {
+ 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, 0xCC, 0x41, 0x73, 0x49,
+ 0xAE, 0x20, 0x41, 0x31, 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
+ 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, 0x21, 0x92, 0x99, 0x2A,
+ 0x27, 0x4F, 0xC1, 0xA8, 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
+ 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, 0x2A, 0x9A, 0xC9, 0x4F,
+ 0xA5, 0x4C, 0xA4, 0x9F
+};
+static const unsigned char sha3_256_pt[] = { 0xe7, 0x37, 0x21, 0x05 };
+static const unsigned char sha3_256_digest[] = {
+ 0x3a, 0x42, 0xb6, 0x8a, 0xb0, 0x79, 0xf2, 0x8c, 0x4c, 0xa3, 0xc7, 0x52,
+ 0x29, 0x6f, 0x27, 0x90, 0x06, 0xc4, 0xfe, 0x78, 0xb1, 0xeb, 0x79, 0xd9,
+ 0x89, 0x77, 0x7f, 0x05, 0x1e, 0x40, 0x46, 0xae
+};
+
+static const ST_KAT_DIGEST st_kat_digest_tests[] =
+{
+ {
+ OSSL_SELF_TEST_DESC_MD_SHA1,
+ "SHA1",
+ ITM_STR(sha1_pt),
+ ITM(sha1_digest),
+ },
+ {
+ OSSL_SELF_TEST_DESC_MD_SHA2,
+ "SHA512",
+ ITM_STR(sha512_pt),
+ ITM(sha512_digest),
+ },
+ {
+ OSSL_SELF_TEST_DESC_MD_SHA3,
+ "SHA3-256",
+ ITM(sha3_256_pt),
+ ITM(sha3_256_digest),
+ },
+};
+
+
+/*- CIPHER TEST DATA */
+
+/* DES3 test data */
+static const unsigned char des_ede3_cbc_pt[] = {
+ 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+ 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
+ 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+ 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51
+};
+static const unsigned char des_ede3_cbc_key[] = {
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+ 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
+ 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
+};
+static const unsigned char des_ede3_cbc_iv[] = {
+ 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17
+};
+static const unsigned char des_ede3_cbc_ct[] = {
+ 0x20, 0x79, 0xC3, 0xD5, 0x3A, 0xA7, 0x63, 0xE1,
+ 0x93, 0xB7, 0x9E, 0x25, 0x69, 0xAB, 0x52, 0x62,
+ 0x51, 0x65, 0x70, 0x48, 0x1F, 0x25, 0xB5, 0x0F,
+ 0x73, 0xC0, 0xBD, 0xA8, 0x5C, 0x8E, 0x0D, 0xA7
+};
+
+/* AES-256 GCM test data */
+static const unsigned char aes_256_gcm_key[] = {
+ 0x92, 0xe1, 0x1d, 0xcd, 0xaa, 0x86, 0x6f, 0x5c,
+ 0xe7, 0x90, 0xfd, 0x24, 0x50, 0x1f, 0x92, 0x50,
+ 0x9a, 0xac, 0xf4, 0xcb, 0x8b, 0x13, 0x39, 0xd5,
+ 0x0c, 0x9c, 0x12, 0x40, 0x93, 0x5d, 0xd0, 0x8b
+};
+static const unsigned char aes_256_gcm_iv[] = {
+ 0xac, 0x93, 0xa1, 0xa6, 0x14, 0x52, 0x99, 0xbd,
+ 0xe9, 0x02, 0xf2, 0x1a
+};
+static const unsigned char aes_256_gcm_pt[] = {
+ 0x2d, 0x71, 0xbc, 0xfa, 0x91, 0x4e, 0x4a, 0xc0,
+ 0x45, 0xb2, 0xaa, 0x60, 0x95, 0x5f, 0xad, 0x24
+};
+static const unsigned char aes_256_gcm_aad[] = {
+ 0x1e, 0x08, 0x89, 0x01, 0x6f, 0x67, 0x60, 0x1c,
+ 0x8e, 0xbe, 0xa4, 0x94, 0x3b, 0xc2, 0x3a, 0xd6
+};
+static const unsigned char aes_256_gcm_ct[] = {
+ 0x89, 0x95, 0xae, 0x2e, 0x6d, 0xf3, 0xdb, 0xf9,
+ 0x6f, 0xac, 0x7b, 0x71, 0x37, 0xba, 0xe6, 0x7f
+};
+static const unsigned char aes_256_gcm_tag[] = {
+ 0xec, 0xa5, 0xaa, 0x77, 0xd5, 0x1d, 0x4a, 0x0a,
+ 0x14, 0xd9, 0xc5, 0x1e, 0x1d, 0xa4, 0x74, 0xab
+};
+
+/* AES-ECB test data */
+static const unsigned char aes_128_ecb_key[] = {
+ 0x10, 0xa5, 0x88, 0x69, 0xd7, 0x4b, 0xe5, 0xa3,
+ 0x74, 0xcf, 0x86, 0x7c, 0xfb, 0x47, 0x38, 0x59
+};
+static const unsigned char aes_128_ecb_pt[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+static const unsigned char aes_128_ecb_ct[] = {
+ 0x6d, 0x25, 0x1e, 0x69, 0x44, 0xb0, 0x51, 0xe0,
+ 0x4e, 0xaa, 0x6f, 0xb4, 0xdb, 0xf7, 0x84, 0x65
+};
+
+static const ST_KAT_CIPHER st_kat_cipher_tests[] = {
+#ifndef OPENSSL_NO_DES
+ {
+ {
+ OSSL_SELF_TEST_DESC_CIPHER_TDES,
+ "DES-EDE3-CBC",
+ ITM(des_ede3_cbc_pt),
+ ITM(des_ede3_cbc_ct)
+ },
+ CIPHER_MODE_ENCRYPT | CIPHER_MODE_DECRYPT,
+ ITM(des_ede3_cbc_key),
+ ITM(des_ede3_cbc_iv),
+ },
+#endif
+ {
+ {
+ OSSL_SELF_TEST_DESC_CIPHER_AES_GCM,
+ "AES-256-GCM",
+ ITM(aes_256_gcm_pt),
+ ITM(aes_256_gcm_ct)
+ },
+ CIPHER_MODE_ENCRYPT | CIPHER_MODE_DECRYPT,
+ ITM(aes_256_gcm_key),
+ ITM(aes_256_gcm_iv),
+ ITM(aes_256_gcm_aad),
+ ITM(aes_256_gcm_tag)
+ },
+ {
+ {
+ OSSL_SELF_TEST_DESC_CIPHER_AES_ECB,
+ "AES-128-ECB",
+ ITM(aes_128_ecb_pt),
+ ITM(aes_128_ecb_ct)
+ },
+ CIPHER_MODE_DECRYPT,
+ ITM(aes_128_ecb_key)
+ }
+};
+
+static const char hkdf_digest[] = "SHA256";
+static const unsigned char hkdf_secret[] = { 's', 'e', 'c', 'r', 'e', 't' };
+static const unsigned char hkdf_salt[] = { 's', 'a', 'l', 't' };
+static const unsigned char hkdf_info[] = { 'l', 'a', 'b', 'e', 'l' };
+
+static const ST_KAT_PARAM hkdf_params[] = {
+ ST_KAT_PARAM_UTF8STRING(OSSL_KDF_PARAM_DIGEST, hkdf_digest),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_KEY, hkdf_secret),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_SALT, hkdf_salt),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_INFO, hkdf_info),
+ ST_KAT_PARAM_END()
+};
+static const unsigned char hkdf_expected[] = {
+ 0x2a, 0xc4, 0x36, 0x9f, 0x52, 0x59, 0x96, 0xf8,
+ 0xde, 0x13
+};
+
+static const char sskdf_digest[] = "SHA224";
+static const unsigned char sskdf_secret[] = {
+ 0x6d, 0xbd, 0xc2, 0x3f, 0x04, 0x54, 0x88, 0xe4,
+ 0x06, 0x27, 0x57, 0xb0, 0x6b, 0x9e, 0xba, 0xe1,
+ 0x83, 0xfc, 0x5a, 0x59, 0x46, 0xd8, 0x0d, 0xb9,
+ 0x3f, 0xec, 0x6f, 0x62, 0xec, 0x07, 0xe3, 0x72,
+ 0x7f, 0x01, 0x26, 0xae, 0xd1, 0x2c, 0xe4, 0xb2,
+ 0x62, 0xf4, 0x7d, 0x48, 0xd5, 0x42, 0x87, 0xf8,
+ 0x1d, 0x47, 0x4c, 0x7c, 0x3b, 0x18, 0x50, 0xe9
+};
+static const unsigned char sskdf_otherinfo[] = {
+ 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0x43, 0x41, 0x56,
+ 0x53, 0x69, 0x64, 0x3c, 0x83, 0x2e, 0x98, 0x49,
+ 0xdc, 0xdb, 0xa7, 0x1e, 0x9a, 0x31, 0x39, 0xe6,
+ 0x06, 0xe0, 0x95, 0xde, 0x3c, 0x26, 0x4a, 0x66,
+ 0xe9, 0x8a, 0x16, 0x58, 0x54, 0xcd, 0x07, 0x98,
+ 0x9b, 0x1e, 0xe0, 0xec, 0x3f, 0x8d, 0xbe
+};
+static const unsigned char sskdf_expected[] = {
+ 0xa4, 0x62, 0xde, 0x16, 0xa8, 0x9d, 0xe8, 0x46,
+ 0x6e, 0xf5, 0x46, 0x0b, 0x47, 0xb8
+};
+static const ST_KAT_PARAM sskdf_params[] = {
+ ST_KAT_PARAM_UTF8STRING(OSSL_KDF_PARAM_DIGEST, sskdf_digest),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_KEY, sskdf_secret),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_INFO, sskdf_otherinfo),
+ ST_KAT_PARAM_END()
+};
+
+static const char x942kdf_digest[] = "SHA1";
+static const char x942kdf_cekalg[] = "AES-128-WRAP";
+static const unsigned char x942kdf_secret[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13
+};
+static const unsigned char x942kdf_expected[] = {
+ 0xd6, 0xd6, 0xb0, 0x94, 0xc1, 0x02, 0x7a, 0x7d,
+ 0xe6, 0xe3, 0x11, 0x72, 0x94, 0xa3, 0x53, 0x64
+};
+static const ST_KAT_PARAM x942kdf_params[] = {
+ ST_KAT_PARAM_UTF8STRING(OSSL_KDF_PARAM_DIGEST, x942kdf_digest),
+ ST_KAT_PARAM_UTF8STRING(OSSL_KDF_PARAM_CEK_ALG, x942kdf_cekalg),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_KEY, x942kdf_secret),
+ ST_KAT_PARAM_END()
+};
+
+static const char x963kdf_digest[] = "SHA256";
+static const unsigned char x963kdf_otherinfo[] = {
+ 0x75, 0xee, 0xf8, 0x1a, 0xa3, 0x04, 0x1e, 0x33,
+ 0xb8, 0x09, 0x71, 0x20, 0x3d, 0x2c, 0x0c, 0x52
+};
+static const unsigned char x963kdf_secret[] = {
+ 0x22, 0x51, 0x8b, 0x10, 0xe7, 0x0f, 0x2a, 0x3f,
+ 0x24, 0x38, 0x10, 0xae, 0x32, 0x54, 0x13, 0x9e,
+ 0xfb, 0xee, 0x04, 0xaa, 0x57, 0xc7, 0xaf, 0x7d
+};
+static const unsigned char x963kdf_expected[] = {
+ 0xc4, 0x98, 0xaf, 0x77, 0x16, 0x1c, 0xc5, 0x9f,
+ 0x29, 0x62, 0xb9, 0xa7, 0x13, 0xe2, 0xb2, 0x15,
+ 0x15, 0x2d, 0x13, 0x97, 0x66, 0xce, 0x34, 0xa7,
+ 0x76, 0xdf, 0x11, 0x86, 0x6a, 0x69, 0xbf, 0x2e
+};
+static const ST_KAT_PARAM x963kdf_params[] = {
+ ST_KAT_PARAM_UTF8STRING(OSSL_KDF_PARAM_DIGEST, x963kdf_digest),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_KEY, x963kdf_secret),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_INFO, x963kdf_otherinfo),
+ ST_KAT_PARAM_END()
+};
+
+static const char pbkdf2_digest[] = "SHA256";
+static const unsigned char pbkdf2_password[] = {
+ 0x70, 0x61, 0x73, 0x73, 0x00, 0x77, 0x6f, 0x72,
+ 0x64
+};
+static const unsigned char pbkdf2_salt[] = {
+ 0x73, 0x61, 0x00, 0x6c, 0x74
+};
+static const unsigned char pbkdf2_expected[] = {
+ 0x89, 0xb6, 0x9d, 0x05, 0x16, 0xf8, 0x29, 0x89,
+ 0x3c, 0x69, 0x62, 0x26, 0x65, 0x0a, 0x86, 0x87,
+};
+static int pbkdf2_iterations = 4096;
+static int pbkdf2_pkcs5 = 1;
+static const ST_KAT_PARAM pbkdf2_params[] = {
+ ST_KAT_PARAM_UTF8STRING(OSSL_KDF_PARAM_DIGEST, pbkdf2_digest),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_PASSWORD, pbkdf2_password),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_SALT, pbkdf2_salt),
+ ST_KAT_PARAM_INT(OSSL_KDF_PARAM_ITER, pbkdf2_iterations),
+ ST_KAT_PARAM_INT(OSSL_KDF_PARAM_PKCS5, pbkdf2_pkcs5),
+ ST_KAT_PARAM_END()
+};
+
+static const char sshkdf_digest[] = "SHA1";
+static const char sshkdf_type = EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV;
+static const unsigned char sshkdf_key[] = {
+ 0x00, 0x00, 0x00, 0x80, 0x55, 0xba, 0xe9, 0x31,
+ 0xc0, 0x7f, 0xd8, 0x24, 0xbf, 0x10, 0xad, 0xd1,
+ 0x90, 0x2b, 0x6f, 0xbc, 0x7c, 0x66, 0x53, 0x47,
+ 0x38, 0x34, 0x98, 0xa6, 0x86, 0x92, 0x9f, 0xf5,
+ 0xa2, 0x5f, 0x8e, 0x40, 0xcb, 0x66, 0x45, 0xea,
+ 0x81, 0x4f, 0xb1, 0xa5, 0xe0, 0xa1, 0x1f, 0x85,
+ 0x2f, 0x86, 0x25, 0x56, 0x41, 0xe5, 0xed, 0x98,
+ 0x6e, 0x83, 0xa7, 0x8b, 0xc8, 0x26, 0x94, 0x80,
+ 0xea, 0xc0, 0xb0, 0xdf, 0xd7, 0x70, 0xca, 0xb9,
+ 0x2e, 0x7a, 0x28, 0xdd, 0x87, 0xff, 0x45, 0x24,
+ 0x66, 0xd6, 0xae, 0x86, 0x7c, 0xea, 0xd6, 0x3b,
+ 0x36, 0x6b, 0x1c, 0x28, 0x6e, 0x6c, 0x48, 0x11,
+ 0xa9, 0xf1, 0x4c, 0x27, 0xae, 0xa1, 0x4c, 0x51,
+ 0x71, 0xd4, 0x9b, 0x78, 0xc0, 0x6e, 0x37, 0x35,
+ 0xd3, 0x6e, 0x6a, 0x3b, 0xe3, 0x21, 0xdd, 0x5f,
+ 0xc8, 0x23, 0x08, 0xf3, 0x4e, 0xe1, 0xcb, 0x17,
+ 0xfb, 0xa9, 0x4a, 0x59,
+};
+static const unsigned char sshkdf_xcghash[] = {
+ 0xa4, 0xeb, 0xd4, 0x59, 0x34, 0xf5, 0x67, 0x92,
+ 0xb5, 0x11, 0x2d, 0xcd, 0x75, 0xa1, 0x07, 0x5f,
+ 0xdc, 0x88, 0x92, 0x45,
+};
+static const unsigned char sshkdf_session_id[] = {
+ 0xa4, 0xeb, 0xd4, 0x59, 0x34, 0xf5, 0x67, 0x92,
+ 0xb5, 0x11, 0x2d, 0xcd, 0x75, 0xa1, 0x07, 0x5f,
+ 0xdc, 0x88, 0x92, 0x45,
+};
+static const unsigned char sshkdf_expected[] = {
+ 0xe2, 0xf6, 0x27, 0xc0, 0xb4, 0x3f, 0x1a, 0xc1,
+};
+static const ST_KAT_PARAM sshkdf_params[] = {
+ ST_KAT_PARAM_UTF8STRING(OSSL_KDF_PARAM_DIGEST, sshkdf_digest),
+ ST_KAT_PARAM_UTF8CHAR(OSSL_KDF_PARAM_SSHKDF_TYPE, sshkdf_type),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_KEY, sshkdf_key),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_SSHKDF_XCGHASH, sshkdf_xcghash),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_SSHKDF_SESSION_ID, sshkdf_session_id),
+ ST_KAT_PARAM_END()
+};
+
+static const char tls12prf_digest[] = "SHA256";
+static const unsigned char tls12prf_secret[] = {
+ 0x20, 0x2c, 0x88, 0xc0, 0x0f, 0x84, 0xa1, 0x7a,
+ 0x20, 0x02, 0x70, 0x79, 0x60, 0x47, 0x87, 0x46,
+ 0x11, 0x76, 0x45, 0x55, 0x39, 0xe7, 0x05, 0xbe,
+ 0x73, 0x08, 0x90, 0x60, 0x2c, 0x28, 0x9a, 0x50,
+ 0x01, 0xe3, 0x4e, 0xeb, 0x3a, 0x04, 0x3e, 0x5d,
+ 0x52, 0xa6, 0x5e, 0x66, 0x12, 0x51, 0x88, 0xbf,
+};
+static const unsigned char tls12prf_seed[] = {
+ 'k', 'e', 'y', ' ', 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n',
+ 0xae, 0x6c, 0x80, 0x6f, 0x8a, 0xd4, 0xd8, 0x07,
+ 0x84, 0x54, 0x9d, 0xff, 0x28, 0xa4, 0xb5, 0x8f,
+ 0xd8, 0x37, 0x68, 0x1a, 0x51, 0xd9, 0x28, 0xc3,
+ 0xe3, 0x0e, 0xe5, 0xff, 0x14, 0xf3, 0x98, 0x68,
+ 0x62, 0xe1, 0xfd, 0x91, 0xf2, 0x3f, 0x55, 0x8a,
+ 0x60, 0x5f, 0x28, 0x47, 0x8c, 0x58, 0xcf, 0x72,
+ 0x63, 0x7b, 0x89, 0x78, 0x4d, 0x95, 0x9d, 0xf7,
+ 0xe9, 0x46, 0xd3, 0xf0, 0x7b, 0xd1, 0xb6, 0x16,
+ };
+static const unsigned char tls12prf_expected[] = {
+ 0xd0, 0x61, 0x39, 0x88, 0x9f, 0xff, 0xac, 0x1e,
+ 0x3a, 0x71, 0x86, 0x5f, 0x50, 0x4a, 0xa5, 0xd0,
+ 0xd2, 0xa2, 0xe8, 0x95, 0x06, 0xc6, 0xf2, 0x27,
+ 0x9b, 0x67, 0x0c, 0x3e, 0x1b, 0x74, 0xf5, 0x31,
+ 0x01, 0x6a, 0x25, 0x30, 0xc5, 0x1a, 0x3a, 0x0f,
+ 0x7e, 0x1d, 0x65, 0x90, 0xd0, 0xf0, 0x56, 0x6b,
+ 0x2f, 0x38, 0x7f, 0x8d, 0x11, 0xfd, 0x4f, 0x73,
+ 0x1c, 0xdd, 0x57, 0x2d, 0x2e, 0xae, 0x92, 0x7f,
+ 0x6f, 0x2f, 0x81, 0x41, 0x0b, 0x25, 0xe6, 0x96,
+ 0x0b, 0xe6, 0x89, 0x85, 0xad, 0xd6, 0xc3, 0x84,
+ 0x45, 0xad, 0x9f, 0x8c, 0x64, 0xbf, 0x80, 0x68,
+ 0xbf, 0x9a, 0x66, 0x79, 0x48, 0x5d, 0x96, 0x6f,
+ 0x1a, 0xd6, 0xf6, 0x8b, 0x43, 0x49, 0x5b, 0x10,
+ 0xa6, 0x83, 0x75, 0x5e, 0xa2, 0xb8, 0x58, 0xd7,
+ 0x0c, 0xca, 0xc7, 0xec, 0x8b, 0x05, 0x3c, 0x6b,
+ 0xd4, 0x1c, 0xa2, 0x99, 0xd4, 0xe5, 0x19, 0x28,
+};
+static const ST_KAT_PARAM tls12prf_params[] = {
+ ST_KAT_PARAM_UTF8STRING(OSSL_KDF_PARAM_DIGEST, tls12prf_digest),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_SECRET, tls12prf_secret),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_SEED, tls12prf_seed),
+ ST_KAT_PARAM_END()
+};
+
+static const char kbkdf_digest[] = "SHA256";
+static const char kbkdf_mac[] = "HMAC";
+static const unsigned char kbkdf_salt[] = { 'p', 'r', 'f' };
+static const unsigned char kbkdf_prfinput[] = { 't', 'e', 's', 't' };
+static unsigned char kbkdf_key[] = {
+ 0x37, 0x05, 0xD9, 0x60, 0x80, 0xC1, 0x77, 0x28,
+ 0xA0, 0xE8, 0x00, 0xEA, 0xB6, 0xE0, 0xD2, 0x3C,
+};
+static unsigned char kbkdf_expected[] = {
+ 0x9D, 0x18, 0x86, 0x16, 0xF6, 0x38, 0x52, 0xFE,
+ 0x86, 0x91, 0x5B, 0xB8, 0x40, 0xB4, 0xA8, 0x86,
+ 0xFF, 0x3E, 0x6B, 0xB0, 0xF8, 0x19, 0xB4, 0x9B,
+ 0x89, 0x33, 0x93, 0xD3, 0x93, 0x85, 0x42, 0x95,
+};
+static const ST_KAT_PARAM kbkdf_params[] = {
+ ST_KAT_PARAM_UTF8STRING(OSSL_KDF_PARAM_DIGEST, kbkdf_digest),
+ ST_KAT_PARAM_UTF8STRING(OSSL_KDF_PARAM_MAC, kbkdf_mac),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_KEY, kbkdf_key),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_SALT, kbkdf_salt),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_INFO, kbkdf_prfinput),
+ ST_KAT_PARAM_END()
+};
+
+static const char tls13_kdf_digest[] = "SHA256";
+static int tls13_kdf_extract_mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY;
+static int tls13_kdf_expand_mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY;
+static const unsigned char tls13_kdf_prefix[] = {
+ 0x74, 0x6C, 0x73, 0x31, 0x33, 0x20 /* "tls13 " */
+};
+static const unsigned char tls13_kdf_client_early_secret_label[] = {
+ 0x63, 0x20, 0x65, 0x20, 0x74, 0x72, 0x61, 0x66,
+ 0x66, 0x69, 0x63 /* "c e traffic"*/
+};
+static const unsigned char tls13_kdf_psk[] = {
+ 0xF8, 0xAF, 0x6A, 0xEA, 0x2D, 0x39, 0x7B, 0xAF,
+ 0x29, 0x48, 0xA2, 0x5B, 0x28, 0x34, 0x20, 0x06,
+ 0x92, 0xCF, 0xF1, 0x7E, 0xEE, 0x91, 0x65, 0xE4,
+ 0xE2, 0x7B, 0xAB, 0xEE, 0x9E, 0xDE, 0xFD, 0x05
+};
+static const unsigned char tls13_kdf_client_hello_hash[] = {
+ 0x7c, 0x92, 0xf6, 0x8b, 0xd5, 0xbf, 0x36, 0x38,
+ 0xea, 0x33, 0x8a, 0x64, 0x94, 0x72, 0x2e, 0x1b,
+ 0x44, 0x12, 0x7e, 0x1b, 0x7e, 0x8a, 0xad, 0x53,
+ 0x5f, 0x23, 0x22, 0xa6, 0x44, 0xff, 0x22, 0xb3
+};
+
+static const unsigned char tls13_kdf_early_secret[] = {
+ 0x15, 0x3B, 0x63, 0x94, 0xA9, 0xC0, 0x3C, 0xF3,
+ 0xF5, 0xAC, 0xCC, 0x6E, 0x45, 0x5A, 0x76, 0x93,
+ 0x28, 0x11, 0x38, 0xA1, 0xBC, 0xFA, 0x38, 0x03,
+ 0xC2, 0x67, 0x35, 0xDD, 0x11, 0x94, 0xD2, 0x16
+};
+static const unsigned char tls13_kdf_client_early_traffic_secret[] = {
+ 0xC8, 0x05, 0x83, 0xA9, 0x0E, 0x99, 0x5C, 0x48,
+ 0x96, 0x00, 0x49, 0x2A, 0x5D, 0xA6, 0x42, 0xE6,
+ 0xB1, 0xF6, 0x79, 0xBA, 0x67, 0x48, 0x28, 0x79,
+ 0x2D, 0xF0, 0x87, 0xB9, 0x39, 0x63, 0x61, 0x71
+};
+static const ST_KAT_PARAM tls13_kdf_early_secret_params[] = {
+ ST_KAT_PARAM_INT(OSSL_KDF_PARAM_MODE, tls13_kdf_extract_mode),
+ ST_KAT_PARAM_UTF8STRING(OSSL_KDF_PARAM_DIGEST, tls13_kdf_digest),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_KEY, tls13_kdf_psk),
+ ST_KAT_PARAM_END()
+};
+static const ST_KAT_PARAM tls13_kdf_client_early_secret_params[] = {
+ ST_KAT_PARAM_INT(OSSL_KDF_PARAM_MODE, tls13_kdf_expand_mode),
+ ST_KAT_PARAM_UTF8STRING(OSSL_KDF_PARAM_DIGEST, tls13_kdf_digest),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_KEY, tls13_kdf_early_secret),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_DATA, tls13_kdf_client_hello_hash),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_PREFIX, tls13_kdf_prefix),
+ ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_LABEL,
+ tls13_kdf_client_early_secret_label),
+ ST_KAT_PARAM_END()
+};
+
+static const ST_KAT_KDF st_kat_kdf_tests[] =
+{
+ {
+ OSSL_SELF_TEST_DESC_KDF_TLS13_EXTRACT,
+ OSSL_KDF_NAME_TLS1_3_KDF,
+ tls13_kdf_early_secret_params,
+ ITM(tls13_kdf_early_secret)
+ },
+ {
+ OSSL_SELF_TEST_DESC_KDF_TLS13_EXPAND,
+ OSSL_KDF_NAME_TLS1_3_KDF,
+ tls13_kdf_client_early_secret_params,
+ ITM(tls13_kdf_client_early_traffic_secret)
+ },
+ {
+ OSSL_SELF_TEST_DESC_KDF_TLS12_PRF,
+ OSSL_KDF_NAME_TLS1_PRF,
+ tls12prf_params,
+ ITM(tls12prf_expected)
+ },
+ {
+ OSSL_SELF_TEST_DESC_KDF_PBKDF2,
+ OSSL_KDF_NAME_PBKDF2,
+ pbkdf2_params,
+ ITM(pbkdf2_expected)
+ },
+ {
+ OSSL_SELF_TEST_DESC_KDF_SSHKDF,
+ OSSL_KDF_NAME_SSHKDF,
+ sshkdf_params,
+ ITM(sshkdf_expected)
+ },
+ {
+ OSSL_SELF_TEST_DESC_KDF_KBKDF,
+ OSSL_KDF_NAME_KBKDF,
+ kbkdf_params,
+ ITM(kbkdf_expected)
+ },
+ {
+ OSSL_SELF_TEST_DESC_KDF_HKDF,
+ OSSL_KDF_NAME_HKDF,
+ hkdf_params,
+ ITM(hkdf_expected)
+ },
+ {
+ OSSL_SELF_TEST_DESC_KDF_SSKDF,
+ OSSL_KDF_NAME_SSKDF,
+ sskdf_params,
+ ITM(sskdf_expected)
+ },
+ {
+ OSSL_SELF_TEST_DESC_KDF_X963KDF,
+ OSSL_KDF_NAME_X963KDF,
+ x963kdf_params,
+ ITM(x963kdf_expected)
+ },
+ {
+ OSSL_SELF_TEST_DESC_KDF_X942KDF,
+ OSSL_KDF_NAME_X942KDF_ASN1,
+ x942kdf_params,
+ ITM(x942kdf_expected)
+ },
+};
+
+/*-
+* DRBG test vectors are a small subset of
+* https://csrc.nist.rip/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
+* Using the folder drbgvectors_pr_true
+* Generated for CAVS 14.3.
+*/
+
+/*
+ * Hash_DRBG.rsp
+ *
+ * [SHA-256]
+ * [PredictionResistance = True]
+ * [EntropyInputLen = 256]
+ * [NonceLen = 128]
+ * [PersonalizationStringLen = 256]
+ * [AdditionalInputLen = 256]
+ * [ReturnedBitsLen = 1024]
+ *
+ * COUNT = 14
+ */
+static const unsigned char drbg_hash_sha256_pr_entropyin[] = {
+ 0x06, 0x6d, 0xc8, 0xce, 0x75, 0xb2, 0x89, 0x66, 0xa6, 0x85, 0x16, 0x3f,
+ 0xe2, 0xa4, 0xd4, 0x27, 0xfb, 0xdb, 0x61, 0x66, 0x50, 0x61, 0x6b, 0xa2,
+ 0x82, 0xfc, 0x33, 0x2b, 0x4e, 0x6f, 0x12, 0x20
+};
+static const unsigned char drbg_hash_sha256_pr_nonce[] = {
+ 0x55, 0x9f, 0x7c, 0x64, 0x89, 0x70, 0x83, 0xec, 0x2d, 0x73, 0x70, 0xd9,
+ 0xf0, 0xe5, 0x07, 0x1f
+};
+static const unsigned char drbg_hash_sha256_pr_persstr[] = {
+ 0x88, 0x6f, 0x54, 0x9a, 0xad, 0x1a, 0xc6, 0x3d, 0x18, 0xcb, 0xcc, 0x66,
+ 0x85, 0xda, 0xa2, 0xc2, 0xf7, 0x9e, 0xb0, 0x89, 0x4c, 0xb4, 0xae, 0xf1,
+ 0xac, 0x54, 0x4f, 0xce, 0x57, 0xf1, 0x5e, 0x11
+};
+static const unsigned char drbg_hash_sha256_pr_entropyinpr0[] = {
+ 0xff, 0x80, 0xb7, 0xd2, 0x6a, 0x05, 0xbc, 0x8a, 0x7a, 0xbe, 0x53, 0x28,
+ 0x6b, 0x0e, 0xeb, 0x73, 0x3b, 0x71, 0x5a, 0x20, 0x5b, 0xfa, 0x4f, 0xf6,
+ 0x37, 0x03, 0xde, 0xad, 0xb6, 0xea, 0x0e, 0xf4
+};
+static const unsigned char drbg_hash_sha256_pr_entropyinpr1[] = {
+ 0xc7, 0x38, 0x32, 0x53, 0x46, 0x81, 0xed, 0xe3, 0x7e, 0x03, 0x84, 0x6d,
+ 0x3c, 0x84, 0x17, 0x67, 0x29, 0x7d, 0x24, 0x6c, 0x68, 0x92, 0x41, 0xd2,
+ 0xe7, 0x75, 0xbe, 0x7e, 0xc9, 0x96, 0x29, 0x3d
+};
+static const unsigned char drbg_hash_sha256_pr_addin0[] = {
+ 0xb7, 0x21, 0x5f, 0x14, 0xac, 0x7b, 0xaf, 0xd0, 0xa9, 0x17, 0x72, 0xba,
+ 0x22, 0xf7, 0x19, 0xaf, 0xbd, 0x20, 0xb3, 0x11, 0x63, 0x6c, 0x2b, 0x1e,
+ 0x83, 0xe4, 0xa8, 0x23, 0x35, 0x3f, 0xc6, 0xea
+};
+static const unsigned char drbg_hash_sha256_pr_addin1[] = {
+ 0xce, 0xd3, 0x1f, 0x7e, 0x0d, 0xae, 0x5b, 0xb5, 0xc0, 0x43, 0xe2, 0x46,
+ 0xb2, 0x94, 0x73, 0xe2, 0xfd, 0x39, 0x51, 0x2e, 0xad, 0x45, 0x69, 0xee,
+ 0xe3, 0xe3, 0x80, 0x33, 0x14, 0xab, 0xa7, 0xa3
+};
+static const unsigned char drbg_hash_sha256_pr_expected[] = {
+ 0x60, 0xc2, 0x34, 0xcf, 0xaf, 0xb4, 0x68, 0x03, 0x3b, 0xf1, 0x95, 0xe5,
+ 0x78, 0xce, 0x26, 0x6e, 0x14, 0x65, 0x32, 0x6a, 0x96, 0xa9, 0xe0, 0x3f,
+ 0x8b, 0x89, 0x36, 0x70, 0xef, 0x62, 0x75, 0x4d, 0x5e, 0x80, 0xd5, 0x53,
+ 0xa1, 0xf8, 0x49, 0x50, 0x20, 0x8b, 0x93, 0x43, 0x07, 0x9f, 0x2e, 0xf8,
+ 0x56, 0xe9, 0xc5, 0x70, 0x61, 0x85, 0x97, 0xb5, 0xdc, 0x82, 0xa2, 0xda,
+ 0xea, 0xa3, 0xfd, 0x9b, 0x2f, 0xd2, 0xa0, 0xd7, 0x1b, 0xc6, 0x29, 0x35,
+ 0xcc, 0xb8, 0x3d, 0xa0, 0x67, 0x98, 0x05, 0xa0, 0xe3, 0x1e, 0xfe, 0xe4,
+ 0xf0, 0xe5, 0x13, 0xb0, 0x83, 0x17, 0xfa, 0xca, 0x93, 0x5e, 0x38, 0x29,
+ 0x48, 0xd2, 0x72, 0xdb, 0x76, 0x3e, 0x6d, 0xf3, 0x25, 0x10, 0xff, 0x1b,
+ 0x99, 0xff, 0xf8, 0xc6, 0x0e, 0xb0, 0xdd, 0x29, 0x2e, 0xbc, 0xbb, 0xc8,
+ 0x0a, 0x01, 0x6e, 0xd3, 0xb0, 0x0e, 0x4e, 0xab
+};
+
+/*
+ * CTR_DRBG.rsp
+ *
+ * [AES-128 use df]
+ * [PredictionResistance = True]
+ * [EntropyInputLen = 128]
+ * [NonceLen = 64]
+ * [PersonalizationStringLen = 128]
+ * [AdditionalInputLen = 128]
+ * [ReturnedBitsLen = 512]
+ *
+ * COUNT = 0
+ */
+static const unsigned char drbg_ctr_aes128_pr_df_entropyin[] = {
+ 0x92, 0x89, 0x8f, 0x31, 0xfa, 0x1c, 0xff, 0x6d, 0x18, 0x2f, 0x26, 0x06,
+ 0x43, 0xdf, 0xf8, 0x18
+};
+static const unsigned char drbg_ctr_aes128_pr_df_nonce[] = {
+ 0xc2, 0xa4, 0xd9, 0x72, 0xc3, 0xb9, 0xb6, 0x97
+};
+static const unsigned char drbg_ctr_aes128_pr_df_persstr[] = {
+ 0xea, 0x65, 0xee, 0x60, 0x26, 0x4e, 0x7e, 0xb6, 0x0e, 0x82, 0x68, 0xc4,
+ 0x37, 0x3c, 0x5c, 0x0b
+};
+static const unsigned char drbg_ctr_aes128_pr_df_entropyinpr0[] = {
+ 0x20, 0x72, 0x8a, 0x06, 0xf8, 0x6f, 0x8d, 0xd4, 0x41, 0xe2, 0x72, 0xb7,
+ 0xc4, 0x2c, 0xe8, 0x10
+};
+static const unsigned char drbg_ctr_aes128_pr_df_entropyinpr1[] = {
+ 0x3d, 0xb0, 0xf0, 0x94, 0xf3, 0x05, 0x50, 0x33, 0x17, 0x86, 0x3e, 0x22,
+ 0x08, 0xf7, 0xa5, 0x01
+};
+static const unsigned char drbg_ctr_aes128_pr_df_addin0[] = {
+ 0x1a, 0x40, 0xfa, 0xe3, 0xcc, 0x6c, 0x7c, 0xa0, 0xf8, 0xda, 0xba, 0x59,
+ 0x23, 0x6d, 0xad, 0x1d
+};
+static const unsigned char drbg_ctr_aes128_pr_df_addin1[] = {
+ 0x9f, 0x72, 0x76, 0x6c, 0xc7, 0x46, 0xe5, 0xed, 0x2e, 0x53, 0x20, 0x12,
+ 0xbc, 0x59, 0x31, 0x8c
+};
+static const unsigned char drbg_ctr_aes128_pr_df_expected[] = {
+ 0x5a, 0x35, 0x39, 0x87, 0x0f, 0x4d, 0x22, 0xa4, 0x09, 0x24, 0xee, 0x71,
+ 0xc9, 0x6f, 0xac, 0x72, 0x0a, 0xd6, 0xf0, 0x88, 0x82, 0xd0, 0x83, 0x28,
+ 0x73, 0xec, 0x3f, 0x93, 0xd8, 0xab, 0x45, 0x23, 0xf0, 0x7e, 0xac, 0x45,
+ 0x14, 0x5e, 0x93, 0x9f, 0xb1, 0xd6, 0x76, 0x43, 0x3d, 0xb6, 0xe8, 0x08,
+ 0x88, 0xf6, 0xda, 0x89, 0x08, 0x77, 0x42, 0xfe, 0x1a, 0xf4, 0x3f, 0xc4,
+ 0x23, 0xc5, 0x1f, 0x68
+};
+
+/*
+ * HMAC_DRBG.rsp
+ *
+ * [SHA-1]
+ * [PredictionResistance = True]
+ * [EntropyInputLen = 128]
+ * [NonceLen = 64]
+ * [PersonalizationStringLen = 128]
+ * [AdditionalInputLen = 128]
+ * [ReturnedBitsLen = 640]
+ *
+ * COUNT = 0
+ */
+static const unsigned char drbg_hmac_sha1_pr_entropyin[] = {
+ 0x68, 0x0f, 0xac, 0xe9, 0x0d, 0x7b, 0xca, 0x21, 0xd4, 0xa0, 0xed, 0xb7,
+ 0x79, 0x9e, 0xe5, 0xd8
+};
+static const unsigned char drbg_hmac_sha1_pr_nonce[] = {
+ 0xb7, 0xbe, 0x9e, 0xed, 0xdd, 0x0e, 0x3b, 0x4b
+};
+static const unsigned char drbg_hmac_sha1_pr_persstr[] = {
+ 0xf5, 0x8c, 0x40, 0xae, 0x70, 0xf7, 0xa5, 0x56, 0x48, 0xa9, 0x31, 0xa0,
+ 0xa9, 0x31, 0x3d, 0xd7
+};
+static const unsigned char drbg_hmac_sha1_pr_entropyinpr0[] = {
+ 0x7c, 0xaf, 0xe2, 0x31, 0x63, 0x0a, 0xa9, 0x5a, 0x74, 0x2c, 0x4e, 0x5f,
+ 0x5f, 0x22, 0xc6, 0xa4
+};
+static const unsigned char drbg_hmac_sha1_pr_entropyinpr1[] = {
+ 0x1c, 0x0d, 0x77, 0x92, 0x89, 0x88, 0x27, 0x94, 0x8a, 0x58, 0x9f, 0x82,
+ 0x2d, 0x1a, 0xf7, 0xa6
+};
+static const unsigned char drbg_hmac_sha1_pr_addin0[] = {
+ 0xdc, 0x36, 0x63, 0xf0, 0x62, 0x78, 0x9c, 0xd1, 0x5c, 0xbb, 0x20, 0xc3,
+ 0xc1, 0x8c, 0xd9, 0xd7
+};
+static const unsigned char drbg_hmac_sha1_pr_addin1[] = {
+ 0xfe, 0x85, 0xb0, 0xab, 0x14, 0xc6, 0x96, 0xe6, 0x9c, 0x24, 0xe7, 0xb5,
+ 0xa1, 0x37, 0x12, 0x0c
+};
+static const unsigned char drbg_hmac_sha1_pr_expected[] = {
+ 0x68, 0x00, 0x4b, 0x3a, 0x28, 0xf7, 0xf0, 0x1c, 0xf9, 0xe9, 0xb5, 0x71,
+ 0x20, 0x79, 0xef, 0x80, 0x87, 0x1b, 0x08, 0xb9, 0xa9, 0x1b, 0xcd, 0x2b,
+ 0x9f, 0x09, 0x4d, 0xa4, 0x84, 0x80, 0xb3, 0x4c, 0xaf, 0xd5, 0x59, 0x6b,
+ 0x0c, 0x0a, 0x48, 0xe1, 0x48, 0xda, 0xbc, 0x6f, 0x77, 0xb8, 0xff, 0xaf,
+ 0x18, 0x70, 0x28, 0xe1, 0x04, 0x13, 0x7a, 0x4f, 0xeb, 0x1c, 0x72, 0xb0,
+ 0xc4, 0x4f, 0xe8, 0xb1, 0xaf, 0xab, 0xa5, 0xbc, 0xfd, 0x86, 0x67, 0xf2,
+ 0xf5, 0x5b, 0x46, 0x06, 0x63, 0x2e, 0x3c, 0xbc
+};
+
+static const ST_KAT_DRBG st_kat_drbg_tests[] =
+{
+ {
+ OSSL_SELF_TEST_DESC_DRBG_HASH,
+ "HASH-DRBG", "digest", "SHA256",
+ ITM(drbg_hash_sha256_pr_entropyin),
+ ITM(drbg_hash_sha256_pr_nonce),
+ ITM(drbg_hash_sha256_pr_persstr),
+ ITM(drbg_hash_sha256_pr_entropyinpr0),
+ ITM(drbg_hash_sha256_pr_entropyinpr1),
+ ITM(drbg_hash_sha256_pr_addin0),
+ ITM(drbg_hash_sha256_pr_addin1),
+ ITM(drbg_hash_sha256_pr_expected)
+ },
+ {
+ OSSL_SELF_TEST_DESC_DRBG_CTR,
+ "CTR-DRBG", "cipher", "AES-128-CTR",
+ ITM(drbg_ctr_aes128_pr_df_entropyin),
+ ITM(drbg_ctr_aes128_pr_df_nonce),
+ ITM(drbg_ctr_aes128_pr_df_persstr),
+ ITM(drbg_ctr_aes128_pr_df_entropyinpr0),
+ ITM(drbg_ctr_aes128_pr_df_entropyinpr1),
+ ITM(drbg_ctr_aes128_pr_df_addin0),
+ ITM(drbg_ctr_aes128_pr_df_addin1),
+ ITM(drbg_ctr_aes128_pr_df_expected)
+ },
+ {
+ OSSL_SELF_TEST_DESC_DRBG_HMAC,
+ "HMAC-DRBG", "digest", "SHA1",
+ ITM(drbg_hmac_sha1_pr_entropyin),
+ ITM(drbg_hmac_sha1_pr_nonce),
+ ITM(drbg_hmac_sha1_pr_persstr),
+ ITM(drbg_hmac_sha1_pr_entropyinpr0),
+ ITM(drbg_hmac_sha1_pr_entropyinpr1),
+ ITM(drbg_hmac_sha1_pr_addin0),
+ ITM(drbg_hmac_sha1_pr_addin1),
+ ITM(drbg_hmac_sha1_pr_expected)
+ }
+};
+
+/* KEY EXCHANGE TEST DATA */
+
+#ifndef OPENSSL_NO_DH
+/* DH KAT */
+static const unsigned char dh_p[] = {
+ 0xdc, 0xca, 0x15, 0x11, 0xb2, 0x31, 0x32, 0x25,
+ 0xf5, 0x21, 0x16, 0xe1, 0x54, 0x27, 0x89, 0xe0,
+ 0x01, 0xf0, 0x42, 0x5b, 0xcc, 0xc7, 0xf3, 0x66,
+ 0xf7, 0x40, 0x64, 0x07, 0xf1, 0xc9, 0xfa, 0x8b,
+ 0xe6, 0x10, 0xf1, 0x77, 0x8b, 0xb1, 0x70, 0xbe,
+ 0x39, 0xdb, 0xb7, 0x6f, 0x85, 0xbf, 0x24, 0xce,
+ 0x68, 0x80, 0xad, 0xb7, 0x62, 0x9f, 0x7c, 0x6d,
+ 0x01, 0x5e, 0x61, 0xd4, 0x3f, 0xa3, 0xee, 0x4d,
+ 0xe1, 0x85, 0xf2, 0xcf, 0xd0, 0x41, 0xff, 0xde,
+ 0x9d, 0x41, 0x84, 0x07, 0xe1, 0x51, 0x38, 0xbb,
+ 0x02, 0x1d, 0xae, 0xb3, 0x5f, 0x76, 0x2d, 0x17,
+ 0x82, 0xac, 0xc6, 0x58, 0xd3, 0x2b, 0xd4, 0xb0,
+ 0x23, 0x2c, 0x92, 0x7d, 0xd3, 0x8f, 0xa0, 0x97,
+ 0xb3, 0xd1, 0x85, 0x9f, 0xa8, 0xac, 0xaf, 0xb9,
+ 0x8f, 0x06, 0x66, 0x08, 0xfc, 0x64, 0x4e, 0xc7,
+ 0xdd, 0xb6, 0xf0, 0x85, 0x99, 0xf9, 0x2a, 0xc1,
+ 0xb5, 0x98, 0x25, 0xda, 0x84, 0x32, 0x07, 0x7d,
+ 0xef, 0x69, 0x56, 0x46, 0x06, 0x3c, 0x20, 0x82,
+ 0x3c, 0x95, 0x07, 0xab, 0x6f, 0x01, 0x76, 0xd4,
+ 0x73, 0x0d, 0x99, 0x0d, 0xbb, 0xe6, 0x36, 0x1c,
+ 0xd8, 0xb2, 0xb9, 0x4d, 0x3d, 0x2f, 0x32, 0x9b,
+ 0x82, 0x09, 0x9b, 0xd6, 0x61, 0xf4, 0x29, 0x50,
+ 0xf4, 0x03, 0xdf, 0x3e, 0xde, 0x62, 0xa3, 0x31,
+ 0x88, 0xb0, 0x27, 0x98, 0xba, 0x82, 0x3f, 0x44,
+ 0xb9, 0x46, 0xfe, 0x9d, 0xf6, 0x77, 0xa0, 0xc5,
+ 0xa1, 0x23, 0x8e, 0xaa, 0x97, 0xb7, 0x0f, 0x80,
+ 0xda, 0x8c, 0xac, 0x88, 0xe0, 0x92, 0xb1, 0x12,
+ 0x70, 0x60, 0xff, 0xbf, 0x45, 0x57, 0x99, 0x94,
+ 0x01, 0x1d, 0xc2, 0xfa, 0xa5, 0xe7, 0xf6, 0xc7,
+ 0x62, 0x45, 0xe1, 0xcc, 0x31, 0x22, 0x31, 0xc1,
+ 0x7d, 0x1c, 0xa6, 0xb1, 0x90, 0x07, 0xef, 0x0d,
+ 0xb9, 0x9f, 0x9c, 0xb6, 0x0e, 0x1d, 0x5f, 0x69
+};
+static const unsigned char dh_q[] = {
+ 0x89, 0x8b, 0x22, 0x67, 0x17, 0xef, 0x03, 0x9e,
+ 0x60, 0x3e, 0x82, 0xe5, 0xc7, 0xaf, 0xe4, 0x83,
+ 0x74, 0xac, 0x5f, 0x62, 0x5c, 0x54, 0xf1, 0xea,
+ 0x11, 0xac, 0xb5, 0x7d
+};
+static const unsigned char dh_g[] = {
+ 0x5e, 0xf7, 0xb8, 0x8f, 0x2d, 0xf6, 0x01, 0x39,
+ 0x35, 0x1d, 0xfb, 0xfe, 0x12, 0x66, 0x80, 0x5f,
+ 0xdf, 0x35, 0x6c, 0xdf, 0xd1, 0x3a, 0x4d, 0xa0,
+ 0x05, 0x0c, 0x7e, 0xde, 0x24, 0x6d, 0xf5, 0x9f,
+ 0x6a, 0xbf, 0x96, 0xad, 0xe5, 0xf2, 0xb2, 0x8f,
+ 0xfe, 0x88, 0xd6, 0xbc, 0xe7, 0xf7, 0x89, 0x4a,
+ 0x3d, 0x53, 0x5f, 0xc8, 0x21, 0x26, 0xdd, 0xd4,
+ 0x24, 0x87, 0x2e, 0x16, 0xb8, 0x38, 0xdf, 0x8c,
+ 0x51, 0xe9, 0x01, 0x6f, 0x88, 0x9c, 0x7c, 0x20,
+ 0x3e, 0x98, 0xa8, 0xb6, 0x31, 0xf9, 0xc7, 0x25,
+ 0x63, 0xd3, 0x8a, 0x49, 0x58, 0x9a, 0x07, 0x53,
+ 0xd3, 0x58, 0xe7, 0x83, 0x31, 0x8c, 0xef, 0xd9,
+ 0x67, 0x7c, 0x7b, 0x2d, 0xbb, 0x77, 0xd6, 0xdc,
+ 0xe2, 0xa1, 0x96, 0x37, 0x95, 0xca, 0x64, 0xb9,
+ 0x2d, 0x1c, 0x9a, 0xac, 0x6d, 0x0e, 0x8d, 0x43,
+ 0x1d, 0xe5, 0xe5, 0x00, 0x60, 0xdf, 0xf7, 0x86,
+ 0x89, 0xc9, 0xec, 0xa1, 0xc1, 0x24, 0x8c, 0x16,
+ 0xed, 0x09, 0xc7, 0xad, 0x41, 0x2a, 0x17, 0x40,
+ 0x6d, 0x2b, 0x52, 0x5a, 0xa1, 0xca, 0xbb, 0x23,
+ 0x7b, 0x97, 0x34, 0xec, 0x7b, 0x8c, 0xe3, 0xfa,
+ 0xe0, 0x2f, 0x29, 0xc5, 0xef, 0xed, 0x30, 0xd6,
+ 0x91, 0x87, 0xda, 0x10, 0x9c, 0x2c, 0x9f, 0xe2,
+ 0xaa, 0xdb, 0xb0, 0xc2, 0x2a, 0xf5, 0x4c, 0x61,
+ 0x66, 0x55, 0x00, 0x0c, 0x43, 0x1c, 0x6b, 0x4a,
+ 0x37, 0x97, 0x63, 0xb0, 0xa9, 0x16, 0x58, 0xef,
+ 0xc8, 0x4e, 0x8b, 0x06, 0x35, 0x8c, 0x8b, 0x4f,
+ 0x21, 0x37, 0x10, 0xfd, 0x10, 0x17, 0x2c, 0xf3,
+ 0x9b, 0x83, 0x0c, 0x2d, 0xd8, 0x4a, 0x0c, 0x8a,
+ 0xb8, 0x25, 0x16, 0xec, 0xab, 0x99, 0x5f, 0xa4,
+ 0x21, 0x5e, 0x02, 0x3e, 0x4e, 0xcf, 0x80, 0x74,
+ 0xc3, 0x9d, 0x6c, 0x88, 0xb7, 0x0d, 0x1e, 0xe4,
+ 0xe9, 0x6f, 0xdc, 0x20, 0xea, 0x11, 0x5c, 0x32
+};
+static const unsigned char dh_priv[] = {
+ 0x14, 0x33, 0xe0, 0xb5, 0xa9, 0x17, 0xb6, 0x0a,
+ 0x30, 0x23, 0xf2, 0xf8, 0xaa, 0x2c, 0x2d, 0x70,
+ 0xd2, 0x96, 0x8a, 0xba, 0x9a, 0xea, 0xc8, 0x15,
+ 0x40, 0xb8, 0xfc, 0xe6
+};
+static const unsigned char dh_pub[] = {
+ 0x95, 0xdd, 0x33, 0x8d, 0x29, 0xe5, 0x71, 0x04,
+ 0x92, 0xb9, 0x18, 0x31, 0x7b, 0x72, 0xa3, 0x69,
+ 0x36, 0xe1, 0x95, 0x1a, 0x2e, 0xe5, 0xa5, 0x59,
+ 0x16, 0x99, 0xc0, 0x48, 0x6d, 0x0d, 0x4f, 0x9b,
+ 0xdd, 0x6d, 0x5a, 0x3f, 0x6b, 0x98, 0x89, 0x0c,
+ 0x62, 0xb3, 0x76, 0x52, 0xd3, 0x6e, 0x71, 0x21,
+ 0x11, 0xe6, 0x8a, 0x73, 0x55, 0x37, 0x25, 0x06,
+ 0x99, 0xef, 0xe3, 0x30, 0x53, 0x73, 0x91, 0xfb,
+ 0xc2, 0xc5, 0x48, 0xbc, 0x5a, 0xc3, 0xe5, 0xb2,
+ 0x33, 0x86, 0xc3, 0xee, 0xf5, 0xeb, 0x43, 0xc0,
+ 0x99, 0xd7, 0x0a, 0x52, 0x02, 0x68, 0x7e, 0x83,
+ 0x96, 0x42, 0x48, 0xfc, 0xa9, 0x1f, 0x40, 0x90,
+ 0x8e, 0x8f, 0xb3, 0x31, 0x93, 0x15, 0xf6, 0xd2,
+ 0x60, 0x6d, 0x7f, 0x7c, 0xd5, 0x2c, 0xc6, 0xe7,
+ 0xc5, 0x84, 0x3a, 0xfb, 0x22, 0x51, 0x9c, 0xf0,
+ 0xf0, 0xf9, 0xd3, 0xa0, 0xa4, 0xe8, 0xc8, 0x88,
+ 0x99, 0xef, 0xed, 0xe7, 0x36, 0x43, 0x51, 0xfb,
+ 0x6a, 0x36, 0x3e, 0xe7, 0x17, 0xe5, 0x44, 0x5a,
+ 0xda, 0xb4, 0xc9, 0x31, 0xa6, 0x48, 0x39, 0x97,
+ 0xb8, 0x7d, 0xad, 0x83, 0x67, 0x7e, 0x4d, 0x1d,
+ 0x3a, 0x77, 0x75, 0xe0, 0xf6, 0xd0, 0x0f, 0xdf,
+ 0x73, 0xc7, 0xad, 0x80, 0x1e, 0x66, 0x5a, 0x0e,
+ 0x5a, 0x79, 0x6d, 0x0a, 0x03, 0x80, 0xa1, 0x9f,
+ 0xa1, 0x82, 0xef, 0xc8, 0xa0, 0x4f, 0x5e, 0x4d,
+ 0xb9, 0x0d, 0x1a, 0x86, 0x37, 0xf9, 0x5d, 0xb1,
+ 0x64, 0x36, 0xbd, 0xc8, 0xf3, 0xfc, 0x09, 0x6c,
+ 0x4f, 0xf7, 0xf2, 0x34, 0xbe, 0x8f, 0xef, 0x47,
+ 0x9a, 0xc4, 0xb0, 0xdc, 0x4b, 0x77, 0x26, 0x3e,
+ 0x07, 0xd9, 0x95, 0x9d, 0xe0, 0xf1, 0xbf, 0x3f,
+ 0x0a, 0xe3, 0xd9, 0xd5, 0x0e, 0x4b, 0x89, 0xc9,
+ 0x9e, 0x3e, 0xa1, 0x21, 0x73, 0x43, 0xdd, 0x8c,
+ 0x65, 0x81, 0xac, 0xc4, 0x95, 0x9c, 0x91, 0xd3
+};
+static const unsigned char dh_peer_pub[] = {
+ 0x1f, 0xc1, 0xda, 0x34, 0x1d, 0x1a, 0x84, 0x6a,
+ 0x96, 0xb7, 0xbe, 0x24, 0x34, 0x0f, 0x87, 0x7d,
+ 0xd0, 0x10, 0xaa, 0x03, 0x56, 0xd5, 0xad, 0x58,
+ 0xaa, 0xe9, 0xc7, 0xb0, 0x8f, 0x74, 0x9a, 0x32,
+ 0x23, 0x51, 0x10, 0xb5, 0xd8, 0x8e, 0xb5, 0xdb,
+ 0xfa, 0x97, 0x8d, 0x27, 0xec, 0xc5, 0x30, 0xf0,
+ 0x2d, 0x31, 0x14, 0x00, 0x5b, 0x64, 0xb1, 0xc0,
+ 0xe0, 0x24, 0xcb, 0x8a, 0xe2, 0x16, 0x98, 0xbc,
+ 0xa9, 0xe6, 0x0d, 0x42, 0x80, 0x86, 0x22, 0xf1,
+ 0x81, 0xc5, 0x6e, 0x1d, 0xe7, 0xa9, 0x6e, 0x6e,
+ 0xfe, 0xe9, 0xd6, 0x65, 0x67, 0xe9, 0x1b, 0x97,
+ 0x70, 0x42, 0xc7, 0xe3, 0xd0, 0x44, 0x8f, 0x05,
+ 0xfb, 0x77, 0xf5, 0x22, 0xb9, 0xbf, 0xc8, 0xd3,
+ 0x3c, 0xc3, 0xc3, 0x1e, 0xd3, 0xb3, 0x1f, 0x0f,
+ 0xec, 0xb6, 0xdb, 0x4f, 0x6e, 0xa3, 0x11, 0xe7,
+ 0x7a, 0xfd, 0xbc, 0xd4, 0x7a, 0xee, 0x1b, 0xb1,
+ 0x50, 0xf2, 0x16, 0x87, 0x35, 0x78, 0xfb, 0x96,
+ 0x46, 0x8e, 0x8f, 0x9f, 0x3d, 0xe8, 0xef, 0xbf,
+ 0xce, 0x75, 0x62, 0x4b, 0x1d, 0xf0, 0x53, 0x22,
+ 0xa3, 0x4f, 0x14, 0x63, 0xe8, 0x39, 0xe8, 0x98,
+ 0x4c, 0x4a, 0xd0, 0xa9, 0x6e, 0x1a, 0xc8, 0x42,
+ 0xe5, 0x31, 0x8c, 0xc2, 0x3c, 0x06, 0x2a, 0x8c,
+ 0xa1, 0x71, 0xb8, 0xd5, 0x75, 0x98, 0x0d, 0xde,
+ 0x7f, 0xc5, 0x6f, 0x15, 0x36, 0x52, 0x38, 0x20,
+ 0xd4, 0x31, 0x92, 0xbf, 0xd5, 0x1e, 0x8e, 0x22,
+ 0x89, 0x78, 0xac, 0xa5, 0xb9, 0x44, 0x72, 0xf3,
+ 0x39, 0xca, 0xeb, 0x99, 0x31, 0xb4, 0x2b, 0xe3,
+ 0x01, 0x26, 0x8b, 0xc9, 0x97, 0x89, 0xc9, 0xb2,
+ 0x55, 0x71, 0xc3, 0xc0, 0xe4, 0xcb, 0x3f, 0x00,
+ 0x7f, 0x1a, 0x51, 0x1c, 0xbb, 0x53, 0xc8, 0x51,
+ 0x9c, 0xdd, 0x13, 0x02, 0xab, 0xca, 0x6c, 0x0f,
+ 0x34, 0xf9, 0x67, 0x39, 0xf1, 0x7f, 0xf4, 0x8b
+};
+
+static const unsigned char dh_secret_expected[] = {
+ 0x08, 0xff, 0x33, 0xbb, 0x2e, 0xcf, 0xf4, 0x9a,
+ 0x7d, 0x4a, 0x79, 0x12, 0xae, 0xb1, 0xbb, 0x6a,
+ 0xb5, 0x11, 0x64, 0x1b, 0x4a, 0x76, 0x77, 0x0c,
+ 0x8c, 0xc1, 0xbc, 0xc2, 0x33, 0x34, 0x3d, 0xfe,
+ 0x70, 0x0d, 0x11, 0x81, 0x3d, 0x2c, 0x9e, 0xd2,
+ 0x3b, 0x21, 0x1c, 0xa9, 0xe8, 0x78, 0x69, 0x21,
+ 0xed, 0xca, 0x28, 0x3c, 0x68, 0xb1, 0x61, 0x53,
+ 0xfa, 0x01, 0xe9, 0x1a, 0xb8, 0x2c, 0x90, 0xdd,
+ 0xab, 0x4a, 0x95, 0x81, 0x67, 0x70, 0xa9, 0x87,
+ 0x10, 0xe1, 0x4c, 0x92, 0xab, 0x83, 0xb6, 0xe4,
+ 0x6e, 0x1e, 0x42, 0x6e, 0xe8, 0x52, 0x43, 0x0d,
+ 0x61, 0x87, 0xda, 0xa3, 0x72, 0x0a, 0x6b, 0xcd,
+ 0x73, 0x23, 0x5c, 0x6b, 0x0f, 0x94, 0x1f, 0x33,
+ 0x64, 0xf5, 0x04, 0x20, 0x55, 0x1a, 0x4b, 0xfe,
+ 0xaf, 0xe2, 0xbc, 0x43, 0x85, 0x05, 0xa5, 0x9a,
+ 0x4a, 0x40, 0xda, 0xca, 0x7a, 0x89, 0x5a, 0x73,
+ 0xdb, 0x57, 0x5c, 0x74, 0xc1, 0x3a, 0x23, 0xad,
+ 0x88, 0x32, 0x95, 0x7d, 0x58, 0x2d, 0x38, 0xf0,
+ 0xa6, 0x16, 0x5f, 0xb0, 0xd7, 0xe9, 0xb8, 0x79,
+ 0x9e, 0x42, 0xfd, 0x32, 0x20, 0xe3, 0x32, 0xe9,
+ 0x81, 0x85, 0xa0, 0xc9, 0x42, 0x97, 0x57, 0xb2,
+ 0xd0, 0xd0, 0x2c, 0x17, 0xdb, 0xaa, 0x1f, 0xf6,
+ 0xed, 0x93, 0xd7, 0xe7, 0x3e, 0x24, 0x1e, 0xae,
+ 0xd9, 0x0c, 0xaf, 0x39, 0x4d, 0x2b, 0xc6, 0x57,
+ 0x0f, 0x18, 0xc8, 0x1f, 0x2b, 0xe5, 0xd0, 0x1a,
+ 0x2c, 0xa9, 0x9f, 0xf1, 0x42, 0xb5, 0xd9, 0x63,
+ 0xf9, 0xf5, 0x00, 0x32, 0x5e, 0x75, 0x56, 0xf9,
+ 0x58, 0x49, 0xb3, 0xff, 0xc7, 0x47, 0x94, 0x86,
+ 0xbe, 0x1d, 0x45, 0x96, 0xa3, 0x10, 0x6b, 0xd5,
+ 0xcb, 0x4f, 0x61, 0xc5, 0x7e, 0xc5, 0xf1, 0x00,
+ 0xfb, 0x7a, 0x0c, 0x82, 0xa1, 0x0b, 0x82, 0x52,
+ 0x6a, 0x97, 0xd1, 0xd9, 0x7d, 0x98, 0xea, 0xf6
+};
+
+static const ST_KAT_PARAM dh_group[] = {
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_FFC_P, dh_p),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_FFC_Q, dh_q),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_FFC_G, dh_g),
+ ST_KAT_PARAM_END()
+};
+
+/* The host's private key */
+static const ST_KAT_PARAM dh_host_key[] = {
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_PUB_KEY, dh_pub),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_PRIV_KEY, dh_priv),
+ ST_KAT_PARAM_END()
+};
+
+/* The peer's public key */
+static const ST_KAT_PARAM dh_peer_key[] = {
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_PUB_KEY, dh_peer_pub),
+ ST_KAT_PARAM_END()
+};
+#endif /* OPENSSL_NO_DH */
+
+
+#ifndef OPENSSL_NO_EC
+static const char ecdh_curve_name[] = "prime256v1";
+static const unsigned char ecdh_privd[] = {
+ 0x33, 0xd0, 0x43, 0x83, 0xa9, 0x89, 0x56, 0x03,
+ 0xd2, 0xd7, 0xfe, 0x6b, 0x01, 0x6f, 0xe4, 0x59,
+ 0xcc, 0x0d, 0x9a, 0x24, 0x6c, 0x86, 0x1b, 0x2e,
+ 0xdc, 0x4b, 0x4d, 0x35, 0x43, 0xe1, 0x1b, 0xad
+};
+static const unsigned char ecdh_pub[] = {
+ 0x04,
+ 0x1b, 0x93, 0x67, 0x55, 0x1c, 0x55, 0x9f, 0x63,
+ 0xd1, 0x22, 0xa4, 0xd8, 0xd1, 0x0a, 0x60, 0x6d,
+ 0x02, 0xa5, 0x77, 0x57, 0xc8, 0xa3, 0x47, 0x73,
+ 0x3a, 0x6a, 0x08, 0x28, 0x39, 0xbd, 0xc9, 0xd2,
+ 0x80, 0xec, 0xe9, 0xa7, 0x08, 0x29, 0x71, 0x2f,
+ 0xc9, 0x56, 0x82, 0xee, 0x9a, 0x85, 0x0f, 0x6d,
+ 0x7f, 0x59, 0x5f, 0x8c, 0xd1, 0x96, 0x0b, 0xdf,
+ 0x29, 0x3e, 0x49, 0x07, 0x88, 0x3f, 0x9a, 0x29
+};
+static const unsigned char ecdh_peer_pub[] = {
+ 0x04,
+ 0x1f, 0x72, 0xbd, 0x2a, 0x3e, 0xeb, 0x6c, 0x76,
+ 0xe5, 0x5d, 0x69, 0x75, 0x24, 0xbf, 0x2f, 0x5b,
+ 0x96, 0xb2, 0x91, 0x62, 0x06, 0x35, 0xcc, 0xb2,
+ 0x4b, 0x31, 0x1b, 0x0c, 0x6f, 0x06, 0x9f, 0x86,
+ 0xcf, 0xc8, 0xac, 0xd5, 0x4f, 0x4d, 0x77, 0xf3,
+ 0x70, 0x4a, 0x8f, 0x04, 0x9a, 0xb1, 0x03, 0xc7,
+ 0xeb, 0xd5, 0x94, 0x78, 0x61, 0xab, 0x78, 0x0c,
+ 0x4a, 0x2d, 0x6b, 0xf3, 0x2f, 0x2e, 0x4a, 0xbc
+};
+
+static const ST_KAT_PARAM ecdh_group[] = {
+ ST_KAT_PARAM_UTF8STRING(OSSL_PKEY_PARAM_GROUP_NAME, ecdh_curve_name),
+ ST_KAT_PARAM_END()
+};
+static const ST_KAT_PARAM ecdh_host_key[] = {
+ ST_KAT_PARAM_OCTET(OSSL_PKEY_PARAM_PUB_KEY, ecdh_pub),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_PRIV_KEY, ecdh_privd),
+ ST_KAT_PARAM_END()
+};
+static const ST_KAT_PARAM ecdh_peer_key[] = {
+ ST_KAT_PARAM_OCTET(OSSL_PKEY_PARAM_PUB_KEY, ecdh_peer_pub),
+ ST_KAT_PARAM_END()
+};
+static const unsigned char ecdh_secret_expected[] = {
+ 0x45, 0x2a, 0x2f, 0x0d, 0x24, 0xe6, 0x8d, 0xd0,
+ 0xda, 0x59, 0x7b, 0x0c, 0xec, 0x9b, 0x4c, 0x38,
+ 0x41, 0xdd, 0xce, 0xb3, 0xcc, 0xf1, 0x90, 0x8e,
+ 0x30, 0xdb, 0x5b, 0x5f, 0x97, 0xea, 0xe0, 0xc2
+};
+#endif /* OPENSSL_NO_EC */
+
+#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC)
+static const ST_KAT_KAS st_kat_kas_tests[] =
+{
+# ifndef OPENSSL_NO_DH
+ {
+ OSSL_SELF_TEST_DESC_KA_DH,
+ "DH",
+ dh_group,
+ dh_host_key,
+ dh_peer_key,
+ ITM(dh_secret_expected)
+ },
+# endif /* OPENSSL_NO_DH */
+# ifndef OPENSSL_NO_EC
+ {
+ OSSL_SELF_TEST_DESC_KA_ECDH,
+ "EC",
+ ecdh_group,
+ ecdh_host_key,
+ ecdh_peer_key,
+ ITM(ecdh_secret_expected)
+ },
+# endif /* OPENSSL_NO_EC */
+};
+#endif /* !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC) */
+
+/* RSA key data */
+static const unsigned char rsa_n[] = {
+ 0xDB, 0x10, 0x1A, 0xC2, 0xA3, 0xF1, 0xDC, 0xFF,
+ 0x13, 0x6B, 0xED, 0x44, 0xDF, 0xF0, 0x02, 0x6D,
+ 0x13, 0xC7, 0x88, 0xDA, 0x70, 0x6B, 0x54, 0xF1,
+ 0xE8, 0x27, 0xDC, 0xC3, 0x0F, 0x99, 0x6A, 0xFA,
+ 0xC6, 0x67, 0xFF, 0x1D, 0x1E, 0x3C, 0x1D, 0xC1,
+ 0xB5, 0x5F, 0x6C, 0xC0, 0xB2, 0x07, 0x3A, 0x6D,
+ 0x41, 0xE4, 0x25, 0x99, 0xAC, 0xFC, 0xD2, 0x0F,
+ 0x02, 0xD3, 0xD1, 0x54, 0x06, 0x1A, 0x51, 0x77,
+ 0xBD, 0xB6, 0xBF, 0xEA, 0xA7, 0x5C, 0x06, 0xA9,
+ 0x5D, 0x69, 0x84, 0x45, 0xD7, 0xF5, 0x05, 0xBA,
+ 0x47, 0xF0, 0x1B, 0xD7, 0x2B, 0x24, 0xEC, 0xCB,
+ 0x9B, 0x1B, 0x10, 0x8D, 0x81, 0xA0, 0xBE, 0xB1,
+ 0x8C, 0x33, 0xE4, 0x36, 0xB8, 0x43, 0xEB, 0x19,
+ 0x2A, 0x81, 0x8D, 0xDE, 0x81, 0x0A, 0x99, 0x48,
+ 0xB6, 0xF6, 0xBC, 0xCD, 0x49, 0x34, 0x3A, 0x8F,
+ 0x26, 0x94, 0xE3, 0x28, 0x82, 0x1A, 0x7C, 0x8F,
+ 0x59, 0x9F, 0x45, 0xE8, 0x5D, 0x1A, 0x45, 0x76,
+ 0x04, 0x56, 0x05, 0xA1, 0xD0, 0x1B, 0x8C, 0x77,
+ 0x6D, 0xAF, 0x53, 0xFA, 0x71, 0xE2, 0x67, 0xE0,
+ 0x9A, 0xFE, 0x03, 0xA9, 0x85, 0xD2, 0xC9, 0xAA,
+ 0xBA, 0x2A, 0xBC, 0xF4, 0xA0, 0x08, 0xF5, 0x13,
+ 0x98, 0x13, 0x5D, 0xF0, 0xD9, 0x33, 0x34, 0x2A,
+ 0x61, 0xC3, 0x89, 0x55, 0xF0, 0xAE, 0x1A, 0x9C,
+ 0x22, 0xEE, 0x19, 0x05, 0x8D, 0x32, 0xFE, 0xEC,
+ 0x9C, 0x84, 0xBA, 0xB7, 0xF9, 0x6C, 0x3A, 0x4F,
+ 0x07, 0xFC, 0x45, 0xEB, 0x12, 0xE5, 0x7B, 0xFD,
+ 0x55, 0xE6, 0x29, 0x69, 0xD1, 0xC2, 0xE8, 0xB9,
+ 0x78, 0x59, 0xF6, 0x79, 0x10, 0xC6, 0x4E, 0xEB,
+ 0x6A, 0x5E, 0xB9, 0x9A, 0xC7, 0xC4, 0x5B, 0x63,
+ 0xDA, 0xA3, 0x3F, 0x5E, 0x92, 0x7A, 0x81, 0x5E,
+ 0xD6, 0xB0, 0xE2, 0x62, 0x8F, 0x74, 0x26, 0xC2,
+ 0x0C, 0xD3, 0x9A, 0x17, 0x47, 0xE6, 0x8E, 0xAB
+};
+static const unsigned char rsa_e[] = { 0x01, 0x00, 0x01 };
+static const unsigned char rsa_d[] = {
+ 0x52, 0x41, 0xF4, 0xDA, 0x7B, 0xB7, 0x59, 0x55,
+ 0xCA, 0xD4, 0x2F, 0x0F, 0x3A, 0xCB, 0xA4, 0x0D,
+ 0x93, 0x6C, 0xCC, 0x9D, 0xC1, 0xB2, 0xFB, 0xFD,
+ 0xAE, 0x40, 0x31, 0xAC, 0x69, 0x52, 0x21, 0x92,
+ 0xB3, 0x27, 0xDF, 0xEA, 0xEE, 0x2C, 0x82, 0xBB,
+ 0xF7, 0x40, 0x32, 0xD5, 0x14, 0xC4, 0x94, 0x12,
+ 0xEC, 0xB8, 0x1F, 0xCA, 0x59, 0xE3, 0xC1, 0x78,
+ 0xF3, 0x85, 0xD8, 0x47, 0xA5, 0xD7, 0x02, 0x1A,
+ 0x65, 0x79, 0x97, 0x0D, 0x24, 0xF4, 0xF0, 0x67,
+ 0x6E, 0x75, 0x2D, 0xBF, 0x10, 0x3D, 0xA8, 0x7D,
+ 0xEF, 0x7F, 0x60, 0xE4, 0xE6, 0x05, 0x82, 0x89,
+ 0x5D, 0xDF, 0xC6, 0xD2, 0x6C, 0x07, 0x91, 0x33,
+ 0x98, 0x42, 0xF0, 0x02, 0x00, 0x25, 0x38, 0xC5,
+ 0x85, 0x69, 0x8A, 0x7D, 0x2F, 0x95, 0x6C, 0x43,
+ 0x9A, 0xB8, 0x81, 0xE2, 0xD0, 0x07, 0x35, 0xAA,
+ 0x05, 0x41, 0xC9, 0x1E, 0xAF, 0xE4, 0x04, 0x3B,
+ 0x19, 0xB8, 0x73, 0xA2, 0xAC, 0x4B, 0x1E, 0x66,
+ 0x48, 0xD8, 0x72, 0x1F, 0xAC, 0xF6, 0xCB, 0xBC,
+ 0x90, 0x09, 0xCA, 0xEC, 0x0C, 0xDC, 0xF9, 0x2C,
+ 0xD7, 0xEB, 0xAE, 0xA3, 0xA4, 0x47, 0xD7, 0x33,
+ 0x2F, 0x8A, 0xCA, 0xBC, 0x5E, 0xF0, 0x77, 0xE4,
+ 0x97, 0x98, 0x97, 0xC7, 0x10, 0x91, 0x7D, 0x2A,
+ 0xA6, 0xFF, 0x46, 0x83, 0x97, 0xDE, 0xE9, 0xE2,
+ 0x17, 0x03, 0x06, 0x14, 0xE2, 0xD7, 0xB1, 0x1D,
+ 0x77, 0xAF, 0x51, 0x27, 0x5B, 0x5E, 0x69, 0xB8,
+ 0x81, 0xE6, 0x11, 0xC5, 0x43, 0x23, 0x81, 0x04,
+ 0x62, 0xFF, 0xE9, 0x46, 0xB8, 0xD8, 0x44, 0xDB,
+ 0xA5, 0xCC, 0x31, 0x54, 0x34, 0xCE, 0x3E, 0x82,
+ 0xD6, 0xBF, 0x7A, 0x0B, 0x64, 0x21, 0x6D, 0x88,
+ 0x7E, 0x5B, 0x45, 0x12, 0x1E, 0x63, 0x8D, 0x49,
+ 0xA7, 0x1D, 0xD9, 0x1E, 0x06, 0xCD, 0xE8, 0xBA,
+ 0x2C, 0x8C, 0x69, 0x32, 0xEA, 0xBE, 0x60, 0x71
+};
+static const unsigned char rsa_p[] = {
+ 0xFA, 0xAC, 0xE1, 0x37, 0x5E, 0x32, 0x11, 0x34,
+ 0xC6, 0x72, 0x58, 0x2D, 0x91, 0x06, 0x3E, 0x77,
+ 0xE7, 0x11, 0x21, 0xCD, 0x4A, 0xF8, 0xA4, 0x3F,
+ 0x0F, 0xEF, 0x31, 0xE3, 0xF3, 0x55, 0xA0, 0xB9,
+ 0xAC, 0xB6, 0xCB, 0xBB, 0x41, 0xD0, 0x32, 0x81,
+ 0x9A, 0x8F, 0x7A, 0x99, 0x30, 0x77, 0x6C, 0x68,
+ 0x27, 0xE2, 0x96, 0xB5, 0x72, 0xC9, 0xC3, 0xD4,
+ 0x42, 0xAA, 0xAA, 0xCA, 0x95, 0x8F, 0xFF, 0xC9,
+ 0x9B, 0x52, 0x34, 0x30, 0x1D, 0xCF, 0xFE, 0xCF,
+ 0x3C, 0x56, 0x68, 0x6E, 0xEF, 0xE7, 0x6C, 0xD7,
+ 0xFB, 0x99, 0xF5, 0x4A, 0xA5, 0x21, 0x1F, 0x2B,
+ 0xEA, 0x93, 0xE8, 0x98, 0x26, 0xC4, 0x6E, 0x42,
+ 0x21, 0x5E, 0xA0, 0xA1, 0x2A, 0x58, 0x35, 0xBB,
+ 0x10, 0xE7, 0xBA, 0x27, 0x0A, 0x3B, 0xB3, 0xAF,
+ 0xE2, 0x75, 0x36, 0x04, 0xAC, 0x56, 0xA0, 0xAB,
+ 0x52, 0xDE, 0xCE, 0xDD, 0x2C, 0x28, 0x77, 0x03
+};
+static const unsigned char rsa_q[] = {
+ 0xDF, 0xB7, 0x52, 0xB6, 0xD7, 0xC0, 0xE2, 0x96,
+ 0xE7, 0xC9, 0xFE, 0x5D, 0x71, 0x5A, 0xC4, 0x40,
+ 0x96, 0x2F, 0xE5, 0x87, 0xEA, 0xF3, 0xA5, 0x77,
+ 0x11, 0x67, 0x3C, 0x8D, 0x56, 0x08, 0xA7, 0xB5,
+ 0x67, 0xFA, 0x37, 0xA8, 0xB8, 0xCF, 0x61, 0xE8,
+ 0x63, 0xD8, 0x38, 0x06, 0x21, 0x2B, 0x92, 0x09,
+ 0xA6, 0x39, 0x3A, 0xEA, 0xA8, 0xB4, 0x45, 0x4B,
+ 0x36, 0x10, 0x4C, 0xE4, 0x00, 0x66, 0x71, 0x65,
+ 0xF8, 0x0B, 0x94, 0x59, 0x4F, 0x8C, 0xFD, 0xD5,
+ 0x34, 0xA2, 0xE7, 0x62, 0x84, 0x0A, 0xA7, 0xBB,
+ 0xDB, 0xD9, 0x8A, 0xCD, 0x05, 0xE1, 0xCC, 0x57,
+ 0x7B, 0xF1, 0xF1, 0x1F, 0x11, 0x9D, 0xBA, 0x3E,
+ 0x45, 0x18, 0x99, 0x1B, 0x41, 0x64, 0x43, 0xEE,
+ 0x97, 0x5D, 0x77, 0x13, 0x5B, 0x74, 0x69, 0x73,
+ 0x87, 0x95, 0x05, 0x07, 0xBE, 0x45, 0x07, 0x17,
+ 0x7E, 0x4A, 0x69, 0x22, 0xF3, 0xDB, 0x05, 0x39
+};
+static const unsigned char rsa_dp[] = {
+ 0x5E, 0xD8, 0xDC, 0xDA, 0x53, 0x44, 0xC4, 0x67,
+ 0xE0, 0x92, 0x51, 0x34, 0xE4, 0x83, 0xA5, 0x4D,
+ 0x3E, 0xDB, 0xA7, 0x9B, 0x82, 0xBB, 0x73, 0x81,
+ 0xFC, 0xE8, 0x77, 0x4B, 0x15, 0xBE, 0x17, 0x73,
+ 0x49, 0x9B, 0x5C, 0x98, 0xBC, 0xBD, 0x26, 0xEF,
+ 0x0C, 0xE9, 0x2E, 0xED, 0x19, 0x7E, 0x86, 0x41,
+ 0x1E, 0x9E, 0x48, 0x81, 0xDD, 0x2D, 0xE4, 0x6F,
+ 0xC2, 0xCD, 0xCA, 0x93, 0x9E, 0x65, 0x7E, 0xD5,
+ 0xEC, 0x73, 0xFD, 0x15, 0x1B, 0xA2, 0xA0, 0x7A,
+ 0x0F, 0x0D, 0x6E, 0xB4, 0x53, 0x07, 0x90, 0x92,
+ 0x64, 0x3B, 0x8B, 0xA9, 0x33, 0xB3, 0xC5, 0x94,
+ 0x9B, 0x4C, 0x5D, 0x9C, 0x7C, 0x46, 0xA4, 0xA5,
+ 0x56, 0xF4, 0xF3, 0xF8, 0x27, 0x0A, 0x7B, 0x42,
+ 0x0D, 0x92, 0x70, 0x47, 0xE7, 0x42, 0x51, 0xA9,
+ 0xC2, 0x18, 0xB1, 0x58, 0xB1, 0x50, 0x91, 0xB8,
+ 0x61, 0x41, 0xB6, 0xA9, 0xCE, 0xD4, 0x7C, 0xBB
+};
+static const unsigned char rsa_dq[] = {
+ 0x54, 0x09, 0x1F, 0x0F, 0x03, 0xD8, 0xB6, 0xC5,
+ 0x0C, 0xE8, 0xB9, 0x9E, 0x0C, 0x38, 0x96, 0x43,
+ 0xD4, 0xA6, 0xC5, 0x47, 0xDB, 0x20, 0x0E, 0xE5,
+ 0xBD, 0x29, 0xD4, 0x7B, 0x1A, 0xF8, 0x41, 0x57,
+ 0x49, 0x69, 0x9A, 0x82, 0xCC, 0x79, 0x4A, 0x43,
+ 0xEB, 0x4D, 0x8B, 0x2D, 0xF2, 0x43, 0xD5, 0xA5,
+ 0xBE, 0x44, 0xFD, 0x36, 0xAC, 0x8C, 0x9B, 0x02,
+ 0xF7, 0x9A, 0x03, 0xE8, 0x19, 0xA6, 0x61, 0xAE,
+ 0x76, 0x10, 0x93, 0x77, 0x41, 0x04, 0xAB, 0x4C,
+ 0xED, 0x6A, 0xCC, 0x14, 0x1B, 0x99, 0x8D, 0x0C,
+ 0x6A, 0x37, 0x3B, 0x86, 0x6C, 0x51, 0x37, 0x5B,
+ 0x1D, 0x79, 0xF2, 0xA3, 0x43, 0x10, 0xC6, 0xA7,
+ 0x21, 0x79, 0x6D, 0xF9, 0xE9, 0x04, 0x6A, 0xE8,
+ 0x32, 0xFF, 0xAE, 0xFD, 0x1C, 0x7B, 0x8C, 0x29,
+ 0x13, 0xA3, 0x0C, 0xB2, 0xAD, 0xEC, 0x6C, 0x0F,
+ 0x8D, 0x27, 0x12, 0x7B, 0x48, 0xB2, 0xDB, 0x31
+};
+static const unsigned char rsa_qInv[] = {
+ 0x8D, 0x1B, 0x05, 0xCA, 0x24, 0x1F, 0x0C, 0x53,
+ 0x19, 0x52, 0x74, 0x63, 0x21, 0xFA, 0x78, 0x46,
+ 0x79, 0xAF, 0x5C, 0xDE, 0x30, 0xA4, 0x6C, 0x20,
+ 0x38, 0xE6, 0x97, 0x39, 0xB8, 0x7A, 0x70, 0x0D,
+ 0x8B, 0x6C, 0x6D, 0x13, 0x74, 0xD5, 0x1C, 0xDE,
+ 0xA9, 0xF4, 0x60, 0x37, 0xFE, 0x68, 0x77, 0x5E,
+ 0x0B, 0x4E, 0x5E, 0x03, 0x31, 0x30, 0xDF, 0xD6,
+ 0xAE, 0x85, 0xD0, 0x81, 0xBB, 0x61, 0xC7, 0xB1,
+ 0x04, 0x5A, 0xC4, 0x6D, 0x56, 0x1C, 0xD9, 0x64,
+ 0xE7, 0x85, 0x7F, 0x88, 0x91, 0xC9, 0x60, 0x28,
+ 0x05, 0xE2, 0xC6, 0x24, 0x8F, 0xDD, 0x61, 0x64,
+ 0xD8, 0x09, 0xDE, 0x7E, 0xD3, 0x4A, 0x61, 0x1A,
+ 0xD3, 0x73, 0x58, 0x4B, 0xD8, 0xA0, 0x54, 0x25,
+ 0x48, 0x83, 0x6F, 0x82, 0x6C, 0xAF, 0x36, 0x51,
+ 0x2A, 0x5D, 0x14, 0x2F, 0x41, 0x25, 0x00, 0xDD,
+ 0xF8, 0xF3, 0x95, 0xFE, 0x31, 0x25, 0x50, 0x12
+};
+
+static const ST_KAT_PARAM rsa_crt_key[] = {
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_RSA_N, rsa_n),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_RSA_E, rsa_e),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_RSA_D, rsa_d),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_RSA_FACTOR1, rsa_p),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_RSA_FACTOR2, rsa_q),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_RSA_EXPONENT1, rsa_dp),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_RSA_EXPONENT2, rsa_dq),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, rsa_qInv),
+ ST_KAT_PARAM_END()
+};
+
+static const ST_KAT_PARAM rsa_pub_key[] = {
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_RSA_N, rsa_n),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_RSA_E, rsa_e),
+ ST_KAT_PARAM_END()
+};
+
+static const ST_KAT_PARAM rsa_priv_key[] = {
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_RSA_N, rsa_n),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_RSA_E, rsa_e),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_RSA_D, rsa_d),
+ ST_KAT_PARAM_END()
+};
+
+/*-
+ * Using OSSL_PKEY_RSA_PAD_MODE_NONE directly in the expansion of the
+ * ST_KAT_PARAM_UTF8STRING macro below causes a failure on ancient
+ * HP/UX PA-RISC compilers.
+ */
+static const char pad_mode_none[] = OSSL_PKEY_RSA_PAD_MODE_NONE;
+
+static const ST_KAT_PARAM rsa_enc_params[] = {
+ ST_KAT_PARAM_UTF8STRING(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, pad_mode_none),
+ ST_KAT_PARAM_END()
+};
+
+static const unsigned char rsa_expected_sig[256] = {
+ 0xad, 0xbe, 0x2a, 0xaf, 0x16, 0x85, 0xc5, 0x00,
+ 0x91, 0x3e, 0xd0, 0x49, 0xfb, 0x3a, 0x81, 0xb9,
+ 0x6c, 0x28, 0xbc, 0xbf, 0xea, 0x96, 0x5f, 0xe4,
+ 0x9f, 0x99, 0xf7, 0x18, 0x8c, 0xec, 0x60, 0x28,
+ 0xeb, 0x29, 0x02, 0x49, 0xfc, 0xda, 0xd7, 0x78,
+ 0x68, 0xf8, 0xe1, 0xe9, 0x4d, 0x20, 0x6d, 0x32,
+ 0xa6, 0xde, 0xfc, 0xe4, 0xda, 0xcc, 0x6c, 0x75,
+ 0x36, 0x6b, 0xff, 0x5a, 0xac, 0x01, 0xa8, 0xc2,
+ 0xa9, 0xe6, 0x8b, 0x18, 0x3e, 0xec, 0xea, 0x4c,
+ 0x4a, 0x9e, 0x00, 0x09, 0xd1, 0x8a, 0x69, 0x1b,
+ 0x8b, 0xd9, 0xad, 0x37, 0xe5, 0x7c, 0xff, 0x7d,
+ 0x59, 0x56, 0x3e, 0xa0, 0xc6, 0x32, 0xd8, 0x35,
+ 0x2f, 0xff, 0xfb, 0x05, 0x02, 0xcd, 0xd7, 0x19,
+ 0xb9, 0x00, 0x86, 0x2a, 0xcf, 0xaa, 0x78, 0x16,
+ 0x4b, 0xf1, 0xa7, 0x59, 0xef, 0x7d, 0xe8, 0x74,
+ 0x23, 0x5c, 0xb2, 0xd4, 0x8a, 0x99, 0xa5, 0xbc,
+ 0xfa, 0x63, 0xd8, 0xf7, 0xbd, 0xc6, 0x00, 0x13,
+ 0x06, 0x02, 0x9a, 0xd4, 0xa7, 0xb4, 0x3d, 0x61,
+ 0xab, 0xf1, 0xc2, 0x95, 0x59, 0x9b, 0x3d, 0x67,
+ 0x1f, 0xde, 0x57, 0xb6, 0xb6, 0x9f, 0xb0, 0x87,
+ 0xd6, 0x51, 0xd5, 0x3e, 0x00, 0xe2, 0xc9, 0xa0,
+ 0x03, 0x66, 0xbc, 0x01, 0xb3, 0x8e, 0xfa, 0xf1,
+ 0x15, 0xeb, 0x26, 0xf1, 0x5d, 0x81, 0x90, 0xb4,
+ 0x1c, 0x00, 0x7c, 0x83, 0x4a, 0xa5, 0xde, 0x64,
+ 0xae, 0xea, 0x6c, 0x43, 0xc3, 0x20, 0x77, 0x77,
+ 0x42, 0x12, 0x24, 0xf5, 0xe3, 0x70, 0xdd, 0x59,
+ 0x48, 0x9c, 0xef, 0xd4, 0x8a, 0x3c, 0x29, 0x6a,
+ 0x0c, 0x9c, 0xf2, 0x13, 0xa4, 0x1c, 0x2f, 0x49,
+ 0xcd, 0xb4, 0xaa, 0x28, 0x40, 0x34, 0xc6, 0x75,
+ 0xba, 0x30, 0xe6, 0xd8, 0x5b, 0x2f, 0x08, 0xd0,
+ 0x29, 0xa5, 0x39, 0xfb, 0x6e, 0x3b, 0x0f, 0x52,
+ 0x2c, 0x68, 0xf0, 0x37, 0xa9, 0xd2, 0x56, 0xd6
+};
+
+static const unsigned char rsa_asym_plaintext_encrypt[256] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+};
+static const unsigned char rsa_asym_expected_encrypt[256] = {
+ 0x54, 0xac, 0x23, 0x96, 0x1d, 0x82, 0x5d, 0x8b,
+ 0x8f, 0x36, 0x33, 0xd0, 0xf4, 0x02, 0xa2, 0x61,
+ 0xb1, 0x13, 0xd4, 0x4a, 0x46, 0x06, 0x37, 0x3c,
+ 0xbf, 0x40, 0x05, 0x3c, 0xc6, 0x3b, 0x64, 0xdc,
+ 0x22, 0x22, 0xaf, 0x36, 0x79, 0x62, 0x45, 0xf0,
+ 0x97, 0x82, 0x22, 0x44, 0x86, 0x4a, 0x7c, 0xfa,
+ 0xac, 0x03, 0x21, 0x84, 0x3f, 0x31, 0xad, 0x2a,
+ 0xa4, 0x6e, 0x7a, 0xc5, 0x93, 0xf3, 0x0f, 0xfc,
+ 0xf1, 0x62, 0xce, 0x82, 0x12, 0x45, 0xc9, 0x35,
+ 0xb0, 0x7a, 0xcd, 0x99, 0x8c, 0x91, 0x6b, 0x5a,
+ 0xd3, 0x46, 0xdb, 0xf9, 0x9e, 0x52, 0x49, 0xbd,
+ 0x1e, 0xe8, 0xda, 0xac, 0x61, 0x47, 0xc2, 0xda,
+ 0xfc, 0x1e, 0xfb, 0x74, 0xd7, 0xd6, 0xc1, 0x18,
+ 0x86, 0x3e, 0x20, 0x9c, 0x7a, 0xe1, 0x04, 0xb7,
+ 0x38, 0x43, 0xb1, 0x4e, 0xa0, 0xd8, 0xc1, 0x39,
+ 0x4d, 0xe1, 0xd3, 0xb0, 0xb3, 0xf1, 0x82, 0x87,
+ 0x1f, 0x74, 0xb5, 0x69, 0xfd, 0x33, 0xd6, 0x21,
+ 0x7c, 0x61, 0x60, 0x28, 0xca, 0x70, 0xdb, 0xa0,
+ 0xbb, 0xc8, 0x73, 0xa9, 0x82, 0xf8, 0x6b, 0xd8,
+ 0xf0, 0xc9, 0x7b, 0x20, 0xdf, 0x9d, 0xfb, 0x8c,
+ 0xd4, 0xa2, 0x89, 0xe1, 0x9b, 0x04, 0xad, 0xaa,
+ 0x11, 0x6c, 0x8f, 0xce, 0x83, 0x29, 0x56, 0x69,
+ 0xbb, 0x00, 0x3b, 0xef, 0xca, 0x2d, 0xcd, 0x52,
+ 0xc8, 0xf1, 0xb3, 0x9b, 0xb4, 0x4f, 0x6d, 0x9c,
+ 0x3d, 0x69, 0xcc, 0x6d, 0x1f, 0x38, 0x4d, 0xe6,
+ 0xbb, 0x0c, 0x87, 0xdc, 0x5f, 0xa9, 0x24, 0x93,
+ 0x03, 0x46, 0xa2, 0x33, 0x6c, 0xf4, 0xd8, 0x5d,
+ 0x68, 0xf3, 0xd3, 0xe0, 0xf2, 0x30, 0xdb, 0xf5,
+ 0x4f, 0x0f, 0xad, 0xc7, 0xd0, 0xaa, 0x47, 0xd9,
+ 0x9f, 0x85, 0x1b, 0x2e, 0x6c, 0x3c, 0x57, 0x04,
+ 0x29, 0xf4, 0xf5, 0x66, 0x7d, 0x93, 0x4a, 0xaa,
+ 0x05, 0x52, 0x55, 0xc1, 0xc6, 0x06, 0x90, 0xab,
+};
+
+#ifndef OPENSSL_NO_EC
+/* ECDSA key data */
+static const char ecd_prime_curve_name[] = "secp224r1";
+static const unsigned char ecd_prime_priv[] = {
+ 0x98, 0x1f, 0xb5, 0xf1, 0xfc, 0x87, 0x1d, 0x7d,
+ 0xde, 0x1e, 0x01, 0x64, 0x09, 0x9b, 0xe7, 0x1b,
+ 0x9f, 0xad, 0x63, 0xdd, 0x33, 0x01, 0xd1, 0x50,
+ 0x80, 0x93, 0x50, 0x30
+};
+static const unsigned char ecd_prime_pub[] = {
+ 0x04, 0x95, 0x47, 0x99, 0x44, 0x29, 0x8f, 0x51,
+ 0x39, 0xe2, 0x53, 0xec, 0x79, 0xb0, 0x4d, 0xde,
+ 0x87, 0x1a, 0x76, 0x54, 0xd5, 0x96, 0xb8, 0x7a,
+ 0x6d, 0xf4, 0x1c, 0x2c, 0x87, 0x91, 0x5f, 0xd5,
+ 0x31, 0xdd, 0x24, 0xe5, 0x78, 0xd9, 0x08, 0x24,
+ 0x8a, 0x49, 0x99, 0xec, 0x55, 0xf2, 0x82, 0xb3,
+ 0xc4, 0xb7, 0x33, 0x68, 0xe4, 0x24, 0xa9, 0x12,
+ 0x82
+};
+static const ST_KAT_PARAM ecdsa_prime_key[] = {
+ ST_KAT_PARAM_UTF8STRING(OSSL_PKEY_PARAM_GROUP_NAME, ecd_prime_curve_name),
+ ST_KAT_PARAM_OCTET(OSSL_PKEY_PARAM_PUB_KEY, ecd_prime_pub),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_PRIV_KEY, ecd_prime_priv),
+ ST_KAT_PARAM_END()
+};
+
+# ifndef OPENSSL_NO_EC2M
+static const char ecd_bin_curve_name[] = "sect233r1";
+static const unsigned char ecd_bin_priv[] = {
+ 0x00, 0x6d, 0xd6, 0x39, 0x9d, 0x2a, 0xa2, 0xc8,
+ 0x8c, 0xfc, 0x7b, 0x80, 0x66, 0xaa, 0xe1, 0xaa,
+ 0xba, 0xee, 0xcb, 0xfd, 0xc9, 0xe5, 0x36, 0x38,
+ 0x2e, 0xf7, 0x37, 0x6d, 0xd3, 0x20
+};
+static const unsigned char ecd_bin_pub[] = {
+ 0x04, 0x00, 0x06, 0xe2, 0x56, 0xf7, 0x37, 0xf9,
+ 0xea, 0xb6, 0xd1, 0x0f, 0x59, 0xfa, 0x23, 0xc3,
+ 0x93, 0xa8, 0xb2, 0x26, 0xe2, 0x5c, 0x08, 0xbe,
+ 0x63, 0x49, 0x26, 0xdc, 0xc7, 0x1e, 0x6f, 0x01,
+ 0x32, 0x3b, 0xe6, 0x54, 0x8d, 0xc1, 0x13, 0x3e,
+ 0x54, 0xb2, 0x66, 0x89, 0xb2, 0x82, 0x0a, 0x72,
+ 0x02, 0xa8, 0xe9, 0x6f, 0x54, 0xfd, 0x3a, 0x6b,
+ 0x99, 0xb6, 0x8f, 0x80, 0x46
+};
+static const ST_KAT_PARAM ecdsa_bin_key[] = {
+ ST_KAT_PARAM_UTF8STRING(OSSL_PKEY_PARAM_GROUP_NAME, ecd_bin_curve_name),
+ ST_KAT_PARAM_OCTET(OSSL_PKEY_PARAM_PUB_KEY, ecd_bin_pub),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_PRIV_KEY, ecd_bin_priv),
+ ST_KAT_PARAM_END()
+};
+# endif /* OPENSSL_NO_EC2M */
+#endif /* OPENSSL_NO_EC */
+
+#ifndef OPENSSL_NO_DSA
+/* dsa 2048 */
+static const unsigned char dsa_p[] = {
+ 0xa2, 0x9b, 0x88, 0x72, 0xce, 0x8b, 0x84, 0x23,
+ 0xb7, 0xd5, 0xd2, 0x1d, 0x4b, 0x02, 0xf5, 0x7e,
+ 0x03, 0xe9, 0xe6, 0xb8, 0xa2, 0x58, 0xdc, 0x16,
+ 0x61, 0x1b, 0xa0, 0x98, 0xab, 0x54, 0x34, 0x15,
+ 0xe4, 0x15, 0xf1, 0x56, 0x99, 0x7a, 0x3e, 0xe2,
+ 0x36, 0x65, 0x8f, 0xa0, 0x93, 0x26, 0x0d, 0xe3,
+ 0xad, 0x42, 0x2e, 0x05, 0xe0, 0x46, 0xf9, 0xec,
+ 0x29, 0x16, 0x1a, 0x37, 0x5f, 0x0e, 0xb4, 0xef,
+ 0xfc, 0xef, 0x58, 0x28, 0x5c, 0x5d, 0x39, 0xed,
+ 0x42, 0x5d, 0x7a, 0x62, 0xca, 0x12, 0x89, 0x6c,
+ 0x4a, 0x92, 0xcb, 0x19, 0x46, 0xf2, 0x95, 0x2a,
+ 0x48, 0x13, 0x3f, 0x07, 0xda, 0x36, 0x4d, 0x1b,
+ 0xdf, 0x6b, 0x0f, 0x71, 0x39, 0x98, 0x3e, 0x69,
+ 0x3c, 0x80, 0x05, 0x9b, 0x0e, 0xac, 0xd1, 0x47,
+ 0x9b, 0xa9, 0xf2, 0x85, 0x77, 0x54, 0xed, 0xe7,
+ 0x5f, 0x11, 0x2b, 0x07, 0xeb, 0xbf, 0x35, 0x34,
+ 0x8b, 0xbf, 0x3e, 0x01, 0xe0, 0x2f, 0x2d, 0x47,
+ 0x3d, 0xe3, 0x94, 0x53, 0xf9, 0x9d, 0xd2, 0x36,
+ 0x75, 0x41, 0xca, 0xca, 0x3b, 0xa0, 0x11, 0x66,
+ 0x34, 0x3d, 0x7b, 0x5b, 0x58, 0xa3, 0x7b, 0xd1,
+ 0xb7, 0x52, 0x1d, 0xb2, 0xf1, 0x3b, 0x86, 0x70,
+ 0x71, 0x32, 0xfe, 0x09, 0xf4, 0xcd, 0x09, 0xdc,
+ 0x16, 0x18, 0xfa, 0x34, 0x01, 0xeb, 0xf9, 0xcc,
+ 0x7b, 0x19, 0xfa, 0x94, 0xaa, 0x47, 0x20, 0x88,
+ 0x13, 0x3d, 0x6c, 0xb2, 0xd3, 0x5c, 0x11, 0x79,
+ 0xc8, 0xc8, 0xff, 0x36, 0x87, 0x58, 0xd5, 0x07,
+ 0xd9, 0xf9, 0xa1, 0x7d, 0x46, 0xc1, 0x10, 0xfe,
+ 0x31, 0x44, 0xce, 0x9b, 0x02, 0x2b, 0x42, 0xe4,
+ 0x19, 0xeb, 0x4f, 0x53, 0x88, 0x61, 0x3b, 0xfc,
+ 0x3e, 0x26, 0x24, 0x1a, 0x43, 0x2e, 0x87, 0x06,
+ 0xbc, 0x58, 0xef, 0x76, 0x11, 0x72, 0x78, 0xde,
+ 0xab, 0x6c, 0xf6, 0x92, 0x61, 0x82, 0x91, 0xb7
+};
+static const unsigned char dsa_q[] = {
+ 0xa3, 0xbf, 0xd9, 0xab, 0x78, 0x84, 0x79, 0x4e,
+ 0x38, 0x34, 0x50, 0xd5, 0x89, 0x1d, 0xc1, 0x8b,
+ 0x65, 0x15, 0x7b, 0xdc, 0xfc, 0xda, 0xc5, 0x15,
+ 0x18, 0x90, 0x28, 0x67
+};
+static const unsigned char dsa_g[] = {
+ 0x68, 0x19, 0x27, 0x88, 0x69, 0xc7, 0xfd, 0x3d,
+ 0x2d, 0x7b, 0x77, 0xf7, 0x7e, 0x81, 0x50, 0xd9,
+ 0xad, 0x43, 0x3b, 0xea, 0x3b, 0xa8, 0x5e, 0xfc,
+ 0x80, 0x41, 0x5a, 0xa3, 0x54, 0x5f, 0x78, 0xf7,
+ 0x22, 0x96, 0xf0, 0x6c, 0xb1, 0x9c, 0xed, 0xa0,
+ 0x6c, 0x94, 0xb0, 0x55, 0x1c, 0xfe, 0x6e, 0x6f,
+ 0x86, 0x3e, 0x31, 0xd1, 0xde, 0x6e, 0xed, 0x7d,
+ 0xab, 0x8b, 0x0c, 0x9d, 0xf2, 0x31, 0xe0, 0x84,
+ 0x34, 0xd1, 0x18, 0x4f, 0x91, 0xd0, 0x33, 0x69,
+ 0x6b, 0xb3, 0x82, 0xf8, 0x45, 0x5e, 0x98, 0x88,
+ 0xf5, 0xd3, 0x1d, 0x47, 0x84, 0xec, 0x40, 0x12,
+ 0x02, 0x46, 0xf4, 0xbe, 0xa6, 0x17, 0x94, 0xbb,
+ 0xa5, 0x86, 0x6f, 0x09, 0x74, 0x64, 0x63, 0xbd,
+ 0xf8, 0xe9, 0xe1, 0x08, 0xcd, 0x95, 0x29, 0xc3,
+ 0xd0, 0xf6, 0xdf, 0x80, 0x31, 0x6e, 0x2e, 0x70,
+ 0xaa, 0xeb, 0x1b, 0x26, 0xcd, 0xb8, 0xad, 0x97,
+ 0xbc, 0x3d, 0x28, 0x7e, 0x0b, 0x8d, 0x61, 0x6c,
+ 0x42, 0xe6, 0x5b, 0x87, 0xdb, 0x20, 0xde, 0xb7,
+ 0x00, 0x5b, 0xc4, 0x16, 0x74, 0x7a, 0x64, 0x70,
+ 0x14, 0x7a, 0x68, 0xa7, 0x82, 0x03, 0x88, 0xeb,
+ 0xf4, 0x4d, 0x52, 0xe0, 0x62, 0x8a, 0xf9, 0xcf,
+ 0x1b, 0x71, 0x66, 0xd0, 0x34, 0x65, 0xf3, 0x5a,
+ 0xcc, 0x31, 0xb6, 0x11, 0x0c, 0x43, 0xda, 0xbc,
+ 0x7c, 0x5d, 0x59, 0x1e, 0x67, 0x1e, 0xaf, 0x7c,
+ 0x25, 0x2c, 0x1c, 0x14, 0x53, 0x36, 0xa1, 0xa4,
+ 0xdd, 0xf1, 0x32, 0x44, 0xd5, 0x5e, 0x83, 0x56,
+ 0x80, 0xca, 0xb2, 0x53, 0x3b, 0x82, 0xdf, 0x2e,
+ 0xfe, 0x55, 0xec, 0x18, 0xc1, 0xe6, 0xcd, 0x00,
+ 0x7b, 0xb0, 0x89, 0x75, 0x8b, 0xb1, 0x7c, 0x2c,
+ 0xbe, 0x14, 0x44, 0x1b, 0xd0, 0x93, 0xae, 0x66,
+ 0xe5, 0x97, 0x6d, 0x53, 0x73, 0x3f, 0x4f, 0xa3,
+ 0x26, 0x97, 0x01, 0xd3, 0x1d, 0x23, 0xd4, 0x67
+};
+static const unsigned char dsa_pub[] = {
+ 0xa0, 0x12, 0xb3, 0xb1, 0x70, 0xb3, 0x07, 0x22,
+ 0x79, 0x57, 0xb7, 0xca, 0x20, 0x61, 0xa8, 0x16,
+ 0xac, 0x7a, 0x2b, 0x3d, 0x9a, 0xe9, 0x95, 0xa5,
+ 0x11, 0x9c, 0x38, 0x5b, 0x60, 0x3b, 0xf6, 0xf6,
+ 0xc5, 0xde, 0x4d, 0xc5, 0xec, 0xb5, 0xdf, 0xa4,
+ 0xa4, 0x1c, 0x68, 0x66, 0x2e, 0xb2, 0x5b, 0x63,
+ 0x8b, 0x7e, 0x26, 0x20, 0xba, 0x89, 0x8d, 0x07,
+ 0xda, 0x6c, 0x49, 0x91, 0xe7, 0x6c, 0xc0, 0xec,
+ 0xd1, 0xad, 0x34, 0x21, 0x07, 0x70, 0x67, 0xe4,
+ 0x7c, 0x18, 0xf5, 0x8a, 0x92, 0xa7, 0x2a, 0xd4,
+ 0x31, 0x99, 0xec, 0xb7, 0xbd, 0x84, 0xe7, 0xd3,
+ 0xaf, 0xb9, 0x01, 0x9f, 0x0e, 0x9d, 0xd0, 0xfb,
+ 0xaa, 0x48, 0x73, 0x00, 0xb1, 0x30, 0x81, 0xe3,
+ 0x3c, 0x90, 0x28, 0x76, 0x43, 0x6f, 0x7b, 0x03,
+ 0xc3, 0x45, 0x52, 0x84, 0x81, 0xd3, 0x62, 0x81,
+ 0x5e, 0x24, 0xfe, 0x59, 0xda, 0xc5, 0xac, 0x34,
+ 0x66, 0x0d, 0x4c, 0x8a, 0x76, 0xcb, 0x99, 0xa7,
+ 0xc7, 0xde, 0x93, 0xeb, 0x95, 0x6c, 0xd6, 0xbc,
+ 0x88, 0xe5, 0x8d, 0x90, 0x10, 0x34, 0x94, 0x4a,
+ 0x09, 0x4b, 0x01, 0x80, 0x3a, 0x43, 0xc6, 0x72,
+ 0xb9, 0x68, 0x8c, 0x0e, 0x01, 0xd8, 0xf4, 0xfc,
+ 0x91, 0xc6, 0x2a, 0x3f, 0x88, 0x02, 0x1f, 0x7b,
+ 0xd6, 0xa6, 0x51, 0xb1, 0xa8, 0x8f, 0x43, 0xaa,
+ 0x4e, 0xf2, 0x76, 0x53, 0xd1, 0x2b, 0xf8, 0xb7,
+ 0x09, 0x9f, 0xdf, 0x6b, 0x46, 0x10, 0x82, 0xf8,
+ 0xe9, 0x39, 0x10, 0x7b, 0xfd, 0x2f, 0x72, 0x10,
+ 0x08, 0x7d, 0x32, 0x6c, 0x37, 0x52, 0x00, 0xf1,
+ 0xf5, 0x1e, 0x7e, 0x74, 0xa3, 0x41, 0x31, 0x90,
+ 0x1b, 0xcd, 0x08, 0x63, 0x52, 0x1f, 0xf8, 0xd6,
+ 0x76, 0xc4, 0x85, 0x81, 0x86, 0x87, 0x36, 0xc5,
+ 0xe5, 0x1b, 0x16, 0xa4, 0xe3, 0x92, 0x15, 0xea,
+ 0x0b, 0x17, 0xc4, 0x73, 0x59, 0x74, 0xc5, 0x16
+};
+static const unsigned char dsa_priv[] = {
+ 0x6c, 0xca, 0xee, 0xf6, 0xd7, 0x3b, 0x4e, 0x80,
+ 0xf1, 0x1c, 0x17, 0xb8, 0xe9, 0x62, 0x7c, 0x03,
+ 0x66, 0x35, 0xba, 0xc3, 0x94, 0x23, 0x50, 0x5e,
+ 0x40, 0x7e, 0x5c, 0xb7
+};
+
+static const ST_KAT_PARAM dsa_key[] = {
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_FFC_P, dsa_p),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_FFC_Q, dsa_q),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_FFC_G, dsa_g),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_PUB_KEY, dsa_pub),
+ ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_PRIV_KEY, dsa_priv),
+ ST_KAT_PARAM_END()
+};
+#endif /* OPENSSL_NO_DSA */
+
+static const ST_KAT_SIGN st_kat_sign_tests[] = {
+ {
+ OSSL_SELF_TEST_DESC_SIGN_RSA,
+ "RSA",
+ "SHA-256",
+ rsa_crt_key,
+ ITM(rsa_expected_sig)
+ },
+#ifndef OPENSSL_NO_EC
+ {
+ OSSL_SELF_TEST_DESC_SIGN_ECDSA,
+ "EC",
+ "SHA-256",
+ ecdsa_prime_key,
+ /*
+ * The ECDSA signature changes each time due to it using a random k.
+ * So there is no expected KAT for this case.
+ */
+ },
+# ifndef OPENSSL_NO_EC2M
+ {
+ OSSL_SELF_TEST_DESC_SIGN_ECDSA,
+ "EC",
+ "SHA-256",
+ ecdsa_bin_key,
+ /*
+ * The ECDSA signature changes each time due to it using a random k.
+ * So there is no expected KAT for this case.
+ */
+ },
+# endif
+#endif /* OPENSSL_NO_EC */
+#ifndef OPENSSL_NO_DSA
+ {
+ OSSL_SELF_TEST_DESC_SIGN_DSA,
+ "DSA",
+ "SHA-256",
+ dsa_key,
+ /*
+ * The DSA signature changes each time due to it using a random k.
+ * So there is no expected KAT for this case.
+ */
+ },
+#endif /* OPENSSL_NO_DSA */
+};
+
+static const ST_KAT_ASYM_CIPHER st_kat_asym_cipher_tests[] = {
+ {
+ OSSL_SELF_TEST_DESC_ASYM_RSA_ENC,
+ "RSA",
+ 1,
+ rsa_pub_key,
+ rsa_enc_params,
+ ITM(rsa_asym_plaintext_encrypt),
+ ITM(rsa_asym_expected_encrypt),
+ },
+ {
+ OSSL_SELF_TEST_DESC_ASYM_RSA_DEC,
+ "RSA",
+ 0,
+ rsa_priv_key,
+ rsa_enc_params,
+ ITM(rsa_asym_expected_encrypt),
+ ITM(rsa_asym_plaintext_encrypt),
+ },
+ {
+ OSSL_SELF_TEST_DESC_ASYM_RSA_DEC,
+ "RSA",
+ 0,
+ rsa_crt_key,
+ rsa_enc_params,
+ ITM(rsa_asym_expected_encrypt),
+ ITM(rsa_asym_plaintext_encrypt),
+ },
+};
diff --git a/providers/fips/self_test_kats.c b/providers/fips/self_test_kats.c
new file mode 100644
index 000000000000..ad896e40d2fb
--- /dev/null
+++ b/providers/fips/self_test_kats.c
@@ -0,0 +1,725 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#include <openssl/param_build.h>
+#include "internal/cryptlib.h"
+#include "internal/nelem.h"
+#include "self_test.h"
+#include "self_test_data.inc"
+
+static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_SELF_TEST *st,
+ OSSL_LIB_CTX *libctx)
+{
+ int ok = 0;
+ unsigned char out[EVP_MAX_MD_SIZE];
+ unsigned int out_len = 0;
+ EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+ EVP_MD *md = EVP_MD_fetch(libctx, t->algorithm, NULL);
+
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_DIGEST, t->desc);
+
+ if (ctx == NULL
+ || md == NULL
+ || !EVP_DigestInit_ex(ctx, md, NULL)
+ || !EVP_DigestUpdate(ctx, t->pt, t->pt_len)
+ || !EVP_DigestFinal(ctx, out, &out_len))
+ goto err;
+
+ /* Optional corruption */
+ OSSL_SELF_TEST_oncorrupt_byte(st, out);
+
+ if (out_len != t->expected_len
+ || memcmp(out, t->expected, out_len) != 0)
+ goto err;
+ ok = 1;
+err:
+ EVP_MD_free(md);
+ EVP_MD_CTX_free(ctx);
+ OSSL_SELF_TEST_onend(st, ok);
+ return ok;
+}
+
+/*
+ * Helper function to setup a EVP_CipherInit
+ * Used to hide the complexity of Authenticated ciphers.
+ */
+static int cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ const ST_KAT_CIPHER *t, int enc)
+{
+ unsigned char *in_tag = NULL;
+ int pad = 0, tmp;
+
+ /* Flag required for Key wrapping */
+ EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
+ if (t->tag == NULL) {
+ /* Use a normal cipher init */
+ return EVP_CipherInit_ex(ctx, cipher, NULL, t->key, t->iv, enc)
+ && EVP_CIPHER_CTX_set_padding(ctx, pad);
+ }
+
+ /* The authenticated cipher init */
+ if (!enc)
+ in_tag = (unsigned char *)t->tag;
+
+ return EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)
+ && (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, t->iv_len, NULL) > 0)
+ && (in_tag == NULL
+ || EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, t->tag_len,
+ in_tag) > 0)
+ && EVP_CipherInit_ex(ctx, NULL, NULL, t->key, t->iv, enc)
+ && EVP_CIPHER_CTX_set_padding(ctx, pad)
+ && EVP_CipherUpdate(ctx, NULL, &tmp, t->aad, t->aad_len);
+}
+
+/* Test a single KAT for encrypt/decrypt */
+static int self_test_cipher(const ST_KAT_CIPHER *t, OSSL_SELF_TEST *st,
+ OSSL_LIB_CTX *libctx)
+{
+ int ret = 0, encrypt = 1, len = 0, ct_len = 0, pt_len = 0;
+ EVP_CIPHER_CTX *ctx = NULL;
+ EVP_CIPHER *cipher = NULL;
+ unsigned char ct_buf[256] = { 0 };
+ unsigned char pt_buf[256] = { 0 };
+
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_CIPHER, t->base.desc);
+
+ ctx = EVP_CIPHER_CTX_new();
+ if (ctx == NULL)
+ goto err;
+ cipher = EVP_CIPHER_fetch(libctx, t->base.algorithm, NULL);
+ if (cipher == NULL)
+ goto err;
+
+ /* Encrypt plain text message */
+ if ((t->mode & CIPHER_MODE_ENCRYPT) != 0) {
+ if (!cipher_init(ctx, cipher, t, encrypt)
+ || !EVP_CipherUpdate(ctx, ct_buf, &len, t->base.pt,
+ t->base.pt_len)
+ || !EVP_CipherFinal_ex(ctx, ct_buf + len, &ct_len))
+ goto err;
+
+ OSSL_SELF_TEST_oncorrupt_byte(st, ct_buf);
+ ct_len += len;
+ if (ct_len != (int)t->base.expected_len
+ || memcmp(t->base.expected, ct_buf, ct_len) != 0)
+ goto err;
+
+ if (t->tag != NULL) {
+ unsigned char tag[16] = { 0 };
+
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, t->tag_len,
+ tag) <= 0
+ || memcmp(tag, t->tag, t->tag_len) != 0)
+ goto err;
+ }
+ }
+
+ /* Decrypt cipher text */
+ if ((t->mode & CIPHER_MODE_DECRYPT) != 0) {
+ if (!(cipher_init(ctx, cipher, t, !encrypt)
+ && EVP_CipherUpdate(ctx, pt_buf, &len,
+ t->base.expected, t->base.expected_len)
+ && EVP_CipherFinal_ex(ctx, pt_buf + len, &pt_len)))
+ goto err;
+ OSSL_SELF_TEST_oncorrupt_byte(st, pt_buf);
+ pt_len += len;
+ if (pt_len != (int)t->base.pt_len
+ || memcmp(pt_buf, t->base.pt, pt_len) != 0)
+ goto err;
+ }
+
+ ret = 1;
+err:
+ EVP_CIPHER_free(cipher);
+ EVP_CIPHER_CTX_free(ctx);
+ OSSL_SELF_TEST_onend(st, ret);
+ return ret;
+}
+
+static int add_params(OSSL_PARAM_BLD *bld, const ST_KAT_PARAM *params,
+ BN_CTX *ctx)
+{
+ int ret = 0;
+ const ST_KAT_PARAM *p;
+
+ if (params == NULL)
+ return 1;
+ for (p = params; p->data != NULL; ++p)
+ {
+ switch (p->type) {
+ case OSSL_PARAM_UNSIGNED_INTEGER: {
+ BIGNUM *bn = BN_CTX_get(ctx);
+
+ if (bn == NULL
+ || (BN_bin2bn(p->data, p->data_len, bn) == NULL)
+ || !OSSL_PARAM_BLD_push_BN(bld, p->name, bn))
+ goto err;
+ break;
+ }
+ case OSSL_PARAM_UTF8_STRING: {
+ if (!OSSL_PARAM_BLD_push_utf8_string(bld, p->name, p->data,
+ p->data_len))
+ goto err;
+ break;
+ }
+ case OSSL_PARAM_OCTET_STRING: {
+ if (!OSSL_PARAM_BLD_push_octet_string(bld, p->name, p->data,
+ p->data_len))
+ goto err;
+ break;
+ }
+ case OSSL_PARAM_INTEGER: {
+ if (!OSSL_PARAM_BLD_push_int(bld, p->name, *(int *)p->data))
+ goto err;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ ret = 1;
+err:
+ return ret;
+}
+
+static int self_test_kdf(const ST_KAT_KDF *t, OSSL_SELF_TEST *st,
+ OSSL_LIB_CTX *libctx)
+{
+ int ret = 0;
+ unsigned char out[128];
+ EVP_KDF *kdf = NULL;
+ EVP_KDF_CTX *ctx = NULL;
+ BN_CTX *bnctx = NULL;
+ OSSL_PARAM *params = NULL;
+ OSSL_PARAM_BLD *bld = NULL;
+
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_KDF, t->desc);
+
+ bld = OSSL_PARAM_BLD_new();
+ if (bld == NULL)
+ goto err;
+
+ kdf = EVP_KDF_fetch(libctx, t->algorithm, "");
+ if (kdf == NULL)
+ goto err;
+
+ ctx = EVP_KDF_CTX_new(kdf);
+ if (ctx == NULL)
+ goto err;
+
+ bnctx = BN_CTX_new_ex(libctx);
+ if (bnctx == NULL)
+ goto err;
+ if (!add_params(bld, t->params, bnctx))
+ goto err;
+ params = OSSL_PARAM_BLD_to_param(bld);
+ if (params == NULL)
+ goto err;
+
+ if (t->expected_len > sizeof(out))
+ goto err;
+ if (EVP_KDF_derive(ctx, out, t->expected_len, params) <= 0)
+ goto err;
+
+ OSSL_SELF_TEST_oncorrupt_byte(st, out);
+
+ if (memcmp(out, t->expected, t->expected_len) != 0)
+ goto err;
+
+ ret = 1;
+err:
+ EVP_KDF_free(kdf);
+ EVP_KDF_CTX_free(ctx);
+ BN_CTX_free(bnctx);
+ OSSL_PARAM_free(params);
+ OSSL_PARAM_BLD_free(bld);
+ OSSL_SELF_TEST_onend(st, ret);
+ return ret;
+}
+
+static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st,
+ OSSL_LIB_CTX *libctx)
+{
+ int ret = 0;
+ unsigned char out[256];
+ EVP_RAND *rand;
+ EVP_RAND_CTX *test = NULL, *drbg = NULL;
+ unsigned int strength = 256;
+ int prediction_resistance = 1; /* Causes a reseed */
+ OSSL_PARAM drbg_params[3] = {
+ OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END
+ };
+
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_DRBG, t->desc);
+
+ rand = EVP_RAND_fetch(libctx, "TEST-RAND", NULL);
+ if (rand == NULL)
+ goto err;
+
+ test = EVP_RAND_CTX_new(rand, NULL);
+ EVP_RAND_free(rand);
+ if (test == NULL)
+ goto err;
+
+ drbg_params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH,
+ &strength);
+ if (!EVP_RAND_CTX_set_params(test, drbg_params))
+ goto err;
+
+ rand = EVP_RAND_fetch(libctx, t->algorithm, NULL);
+ if (rand == NULL)
+ goto err;
+
+ drbg = EVP_RAND_CTX_new(rand, test);
+ EVP_RAND_free(rand);
+ if (drbg == NULL)
+ goto err;
+
+ strength = EVP_RAND_get_strength(drbg);
+
+ drbg_params[0] = OSSL_PARAM_construct_utf8_string(t->param_name,
+ t->param_value, 0);
+ /* This is only used by HMAC-DRBG but it is ignored by the others */
+ drbg_params[1] =
+ OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_MAC, "HMAC", 0);
+ if (!EVP_RAND_CTX_set_params(drbg, drbg_params))
+ goto err;
+
+ drbg_params[0] =
+ OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY,
+ (void *)t->entropyin,
+ t->entropyinlen);
+ drbg_params[1] =
+ OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_NONCE,
+ (void *)t->nonce, t->noncelen);
+ if (!EVP_RAND_instantiate(test, strength, 0, NULL, 0, drbg_params))
+ goto err;
+ if (!EVP_RAND_instantiate(drbg, strength, 0, t->persstr, t->persstrlen,
+ NULL))
+ goto err;
+
+ drbg_params[0] =
+ OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY,
+ (void *)t->entropyinpr1,
+ t->entropyinpr1len);
+ if (!EVP_RAND_CTX_set_params(test, drbg_params))
+ goto err;
+
+ if (!EVP_RAND_generate(drbg, out, t->expectedlen, strength,
+ prediction_resistance,
+ t->entropyaddin1, t->entropyaddin1len))
+ goto err;
+
+ drbg_params[0] =
+ OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY,
+ (void *)t->entropyinpr2,
+ t->entropyinpr2len);
+ if (!EVP_RAND_CTX_set_params(test, drbg_params))
+ goto err;
+
+ /*
+ * This calls ossl_prov_drbg_reseed() internally when
+ * prediction_resistance = 1
+ */
+ if (!EVP_RAND_generate(drbg, out, t->expectedlen, strength,
+ prediction_resistance,
+ t->entropyaddin2, t->entropyaddin2len))
+ goto err;
+
+ OSSL_SELF_TEST_oncorrupt_byte(st, out);
+
+ if (memcmp(out, t->expected, t->expectedlen) != 0)
+ goto err;
+
+ if (!EVP_RAND_uninstantiate(drbg))
+ goto err;
+ /*
+ * Check that the DRBG data has been zeroized after
+ * ossl_prov_drbg_uninstantiate.
+ */
+ if (!EVP_RAND_verify_zeroization(drbg))
+ goto err;
+
+ ret = 1;
+err:
+ EVP_RAND_CTX_free(drbg);
+ EVP_RAND_CTX_free(test);
+ OSSL_SELF_TEST_onend(st, ret);
+ return ret;
+}
+
+#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC)
+static int self_test_ka(const ST_KAT_KAS *t,
+ OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
+{
+ int ret = 0;
+ EVP_PKEY_CTX *kactx = NULL, *dctx = NULL;
+ EVP_PKEY *pkey = NULL, *peerkey = NULL;
+ OSSL_PARAM *params = NULL;
+ OSSL_PARAM *params_peer = NULL;
+ unsigned char secret[256];
+ size_t secret_len = sizeof(secret);
+ OSSL_PARAM_BLD *bld = NULL;
+ BN_CTX *bnctx = NULL;
+
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_KA, t->desc);
+
+ bnctx = BN_CTX_new_ex(libctx);
+ if (bnctx == NULL)
+ goto err;
+
+ bld = OSSL_PARAM_BLD_new();
+ if (bld == NULL)
+ goto err;
+
+ if (!add_params(bld, t->key_group, bnctx)
+ || !add_params(bld, t->key_host_data, bnctx))
+ goto err;
+ params = OSSL_PARAM_BLD_to_param(bld);
+
+ if (!add_params(bld, t->key_group, bnctx)
+ || !add_params(bld, t->key_peer_data, bnctx))
+ goto err;
+
+ params_peer = OSSL_PARAM_BLD_to_param(bld);
+ if (params == NULL || params_peer == NULL)
+ goto err;
+
+ /* Create a EVP_PKEY_CTX to load the DH keys into */
+ kactx = EVP_PKEY_CTX_new_from_name(libctx, t->algorithm, "");
+ if (kactx == NULL)
+ goto err;
+ if (EVP_PKEY_fromdata_init(kactx) <= 0
+ || EVP_PKEY_fromdata(kactx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0)
+ goto err;
+ if (EVP_PKEY_fromdata_init(kactx) <= 0
+ || EVP_PKEY_fromdata(kactx, &peerkey, EVP_PKEY_KEYPAIR, params_peer) <= 0)
+ goto err;
+
+ /* Create a EVP_PKEY_CTX to perform key derivation */
+ dctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, NULL);
+ if (dctx == NULL)
+ goto err;
+
+ if (EVP_PKEY_derive_init(dctx) <= 0
+ || EVP_PKEY_derive_set_peer(dctx, peerkey) <= 0
+ || EVP_PKEY_derive(dctx, secret, &secret_len) <= 0)
+ goto err;
+
+ OSSL_SELF_TEST_oncorrupt_byte(st, secret);
+
+ if (secret_len != t->expected_len
+ || memcmp(secret, t->expected, t->expected_len) != 0)
+ goto err;
+ ret = 1;
+err:
+ BN_CTX_free(bnctx);
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_free(peerkey);
+ EVP_PKEY_CTX_free(kactx);
+ EVP_PKEY_CTX_free(dctx);
+ OSSL_PARAM_free(params_peer);
+ OSSL_PARAM_free(params);
+ OSSL_PARAM_BLD_free(bld);
+ OSSL_SELF_TEST_onend(st, ret);
+ return ret;
+}
+#endif /* !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC) */
+
+static int self_test_sign(const ST_KAT_SIGN *t,
+ OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
+{
+ int ret = 0;
+ OSSL_PARAM *params = NULL, *params_sig = NULL;
+ OSSL_PARAM_BLD *bld = NULL;
+ EVP_PKEY_CTX *sctx = NULL, *kctx = NULL;
+ EVP_PKEY *pkey = NULL;
+ unsigned char sig[256];
+ BN_CTX *bnctx = NULL;
+ size_t siglen = sizeof(sig);
+ static const unsigned char dgst[] = {
+ 0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81,
+ 0x48, 0xa1, 0xd6, 0x5d, 0xfc, 0x2d, 0x4b, 0x1f, 0xa3, 0xd6, 0x77, 0x28,
+ 0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69
+ };
+ const char *typ = OSSL_SELF_TEST_TYPE_KAT_SIGNATURE;
+
+ if (t->sig_expected == NULL)
+ typ = OSSL_SELF_TEST_TYPE_PCT_SIGNATURE;
+
+ OSSL_SELF_TEST_onbegin(st, typ, t->desc);
+
+ bnctx = BN_CTX_new_ex(libctx);
+ if (bnctx == NULL)
+ goto err;
+
+ bld = OSSL_PARAM_BLD_new();
+ if (bld == NULL)
+ goto err;
+
+ if (!add_params(bld, t->key, bnctx))
+ goto err;
+ params = OSSL_PARAM_BLD_to_param(bld);
+
+ /* Create a EVP_PKEY_CTX to load the DSA key into */
+ kctx = EVP_PKEY_CTX_new_from_name(libctx, t->algorithm, "");
+ if (kctx == NULL || params == NULL)
+ goto err;
+ if (EVP_PKEY_fromdata_init(kctx) <= 0
+ || EVP_PKEY_fromdata(kctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0)
+ goto err;
+
+ /* Create a EVP_PKEY_CTX to use for the signing operation */
+ sctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, NULL);
+ if (sctx == NULL
+ || EVP_PKEY_sign_init(sctx) <= 0)
+ goto err;
+
+ /* set signature parameters */
+ if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_SIGNATURE_PARAM_DIGEST,
+ t->mdalgorithm,
+ strlen(t->mdalgorithm) + 1))
+ goto err;
+ params_sig = OSSL_PARAM_BLD_to_param(bld);
+ if (EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0)
+ goto err;
+
+ if (EVP_PKEY_sign(sctx, sig, &siglen, dgst, sizeof(dgst)) <= 0
+ || EVP_PKEY_verify_init(sctx) <= 0
+ || EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0)
+ goto err;
+
+ /*
+ * Used by RSA, for other key types where the signature changes, we
+ * can only use the verify.
+ */
+ if (t->sig_expected != NULL
+ && (siglen != t->sig_expected_len
+ || memcmp(sig, t->sig_expected, t->sig_expected_len) != 0))
+ goto err;
+
+ OSSL_SELF_TEST_oncorrupt_byte(st, sig);
+ if (EVP_PKEY_verify(sctx, sig, siglen, dgst, sizeof(dgst)) <= 0)
+ goto err;
+ ret = 1;
+err:
+ BN_CTX_free(bnctx);
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(kctx);
+ EVP_PKEY_CTX_free(sctx);
+ OSSL_PARAM_free(params);
+ OSSL_PARAM_free(params_sig);
+ OSSL_PARAM_BLD_free(bld);
+ OSSL_SELF_TEST_onend(st, ret);
+ return ret;
+}
+
+/*
+ * Test an encrypt or decrypt KAT..
+ *
+ * FIPS 140-2 IG D.9 states that separate KAT tests are needed for encrypt
+ * and decrypt..
+ */
+static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st,
+ OSSL_LIB_CTX *libctx)
+{
+ int ret = 0;
+ OSSL_PARAM *keyparams = NULL, *initparams = NULL;
+ OSSL_PARAM_BLD *keybld = NULL, *initbld = NULL;
+ EVP_PKEY_CTX *encctx = NULL, *keyctx = NULL;
+ EVP_PKEY *key = NULL;
+ BN_CTX *bnctx = NULL;
+ unsigned char out[256];
+ size_t outlen = sizeof(out);
+
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER, t->desc);
+
+ bnctx = BN_CTX_new_ex(libctx);
+ if (bnctx == NULL)
+ goto err;
+
+ /* Load a public or private key from data */
+ keybld = OSSL_PARAM_BLD_new();
+ if (keybld == NULL
+ || !add_params(keybld, t->key, bnctx))
+ goto err;
+ keyparams = OSSL_PARAM_BLD_to_param(keybld);
+ keyctx = EVP_PKEY_CTX_new_from_name(libctx, t->algorithm, NULL);
+ if (keyctx == NULL || keyparams == NULL)
+ goto err;
+ if (EVP_PKEY_fromdata_init(keyctx) <= 0
+ || EVP_PKEY_fromdata(keyctx, &key, EVP_PKEY_KEYPAIR, keyparams) <= 0)
+ goto err;
+
+ /* Create a EVP_PKEY_CTX to use for the encrypt or decrypt operation */
+ encctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL);
+ if (encctx == NULL
+ || (t->encrypt && EVP_PKEY_encrypt_init(encctx) <= 0)
+ || (!t->encrypt && EVP_PKEY_decrypt_init(encctx) <= 0))
+ goto err;
+
+ /* Add any additional parameters such as padding */
+ if (t->postinit != NULL) {
+ initbld = OSSL_PARAM_BLD_new();
+ if (initbld == NULL)
+ goto err;
+ if (!add_params(initbld, t->postinit, bnctx))
+ goto err;
+ initparams = OSSL_PARAM_BLD_to_param(initbld);
+ if (initparams == NULL)
+ goto err;
+ if (EVP_PKEY_CTX_set_params(encctx, initparams) <= 0)
+ goto err;
+ }
+
+ if (t->encrypt) {
+ if (EVP_PKEY_encrypt(encctx, out, &outlen,
+ t->in, t->in_len) <= 0)
+ goto err;
+ } else {
+ if (EVP_PKEY_decrypt(encctx, out, &outlen,
+ t->in, t->in_len) <= 0)
+ goto err;
+ }
+ /* Check the KAT */
+ OSSL_SELF_TEST_oncorrupt_byte(st, out);
+ if (outlen != t->expected_len
+ || memcmp(out, t->expected, t->expected_len) != 0)
+ goto err;
+
+ ret = 1;
+err:
+ BN_CTX_free(bnctx);
+ EVP_PKEY_free(key);
+ EVP_PKEY_CTX_free(encctx);
+ EVP_PKEY_CTX_free(keyctx);
+ OSSL_PARAM_free(keyparams);
+ OSSL_PARAM_BLD_free(keybld);
+ OSSL_PARAM_free(initparams);
+ OSSL_PARAM_BLD_free(initbld);
+ OSSL_SELF_TEST_onend(st, ret);
+ return ret;
+}
+
+/*
+ * Test a data driven list of KAT's for digest algorithms.
+ * All tests are run regardless of if they fail or not.
+ * Return 0 if any test fails.
+ */
+static int self_test_digests(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
+{
+ int i, ret = 1;
+
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_digest_tests); ++i) {
+ if (!self_test_digest(&st_kat_digest_tests[i], st, libctx))
+ ret = 0;
+ }
+ return ret;
+}
+
+static int self_test_ciphers(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
+{
+ int i, ret = 1;
+
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_cipher_tests); ++i) {
+ if (!self_test_cipher(&st_kat_cipher_tests[i], st, libctx))
+ ret = 0;
+ }
+ return ret;
+}
+
+static int self_test_asym_ciphers(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
+{
+ int i, ret = 1;
+
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_asym_cipher_tests); ++i) {
+ if (!self_test_asym_cipher(&st_kat_asym_cipher_tests[i], st, libctx))
+ ret = 0;
+ }
+ return ret;
+}
+
+static int self_test_kdfs(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
+{
+ int i, ret = 1;
+
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_kdf_tests); ++i) {
+ if (!self_test_kdf(&st_kat_kdf_tests[i], st, libctx))
+ ret = 0;
+ }
+ return ret;
+}
+
+static int self_test_drbgs(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
+{
+ int i, ret = 1;
+
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_drbg_tests); ++i) {
+ if (!self_test_drbg(&st_kat_drbg_tests[i], st, libctx))
+ ret = 0;
+ }
+ return ret;
+}
+
+static int self_test_kas(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
+{
+ int ret = 1;
+#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC)
+ int i;
+
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_kas_tests); ++i) {
+ if (!self_test_ka(&st_kat_kas_tests[i], st, libctx))
+ ret = 0;
+ }
+#endif
+
+ return ret;
+}
+
+static int self_test_signatures(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
+{
+ int i, ret = 1;
+
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_sign_tests); ++i) {
+ if (!self_test_sign(&st_kat_sign_tests[i], st, libctx))
+ ret = 0;
+ }
+ return ret;
+}
+
+/*
+ * Run the algorithm KAT's.
+ * Return 1 is successful, otherwise return 0.
+ * This runs all the tests regardless of if any fail.
+ */
+int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
+{
+ int ret = 1;
+
+ if (!self_test_digests(st, libctx))
+ ret = 0;
+ if (!self_test_ciphers(st, libctx))
+ ret = 0;
+ if (!self_test_signatures(st, libctx))
+ ret = 0;
+ if (!self_test_kdfs(st, libctx))
+ ret = 0;
+ if (!self_test_drbgs(st, libctx))
+ ret = 0;
+ if (!self_test_kas(st, libctx))
+ ret = 0;
+ if (!self_test_asym_ciphers(st, libctx))
+ ret = 0;
+
+ return ret;
+}
diff --git a/providers/implementations/asymciphers/build.info b/providers/implementations/asymciphers/build.info
new file mode 100644
index 000000000000..dbca47368488
--- /dev/null
+++ b/providers/implementations/asymciphers/build.info
@@ -0,0 +1,11 @@
+# We make separate GOAL variables for each algorithm, to make it easy to
+# switch each to the Legacy provider when needed.
+
+$RSA_GOAL=../../libdefault.a ../../libfips.a
+$SM2_GOAL=../../libdefault.a
+
+SOURCE[$RSA_GOAL]=rsa_enc.c
+
+IF[{- !$disabled{"sm2"} -}]
+ SOURCE[$SM2_GOAL]=sm2_enc.c
+ENDIF
diff --git a/providers/implementations/asymciphers/rsa_enc.c b/providers/implementations/asymciphers/rsa_enc.c
new file mode 100644
index 000000000000..568452ec56a2
--- /dev/null
+++ b/providers/implementations/asymciphers/rsa_enc.c
@@ -0,0 +1,588 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/rsa.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+/* Just for SSL_MAX_MASTER_KEY_LENGTH */
+#include <openssl/prov_ssl.h>
+#include "internal/constant_time.h"
+#include "internal/sizes.h"
+#include "crypto/rsa.h"
+#include "prov/provider_ctx.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+#include "prov/securitycheck.h"
+
+#include <stdlib.h>
+
+static OSSL_FUNC_asym_cipher_newctx_fn rsa_newctx;
+static OSSL_FUNC_asym_cipher_encrypt_init_fn rsa_encrypt_init;
+static OSSL_FUNC_asym_cipher_encrypt_fn rsa_encrypt;
+static OSSL_FUNC_asym_cipher_decrypt_init_fn rsa_decrypt_init;
+static OSSL_FUNC_asym_cipher_decrypt_fn rsa_decrypt;
+static OSSL_FUNC_asym_cipher_freectx_fn rsa_freectx;
+static OSSL_FUNC_asym_cipher_dupctx_fn rsa_dupctx;
+static OSSL_FUNC_asym_cipher_get_ctx_params_fn rsa_get_ctx_params;
+static OSSL_FUNC_asym_cipher_gettable_ctx_params_fn rsa_gettable_ctx_params;
+static OSSL_FUNC_asym_cipher_set_ctx_params_fn rsa_set_ctx_params;
+static OSSL_FUNC_asym_cipher_settable_ctx_params_fn rsa_settable_ctx_params;
+
+static OSSL_ITEM padding_item[] = {
+ { RSA_PKCS1_PADDING, OSSL_PKEY_RSA_PAD_MODE_PKCSV15 },
+ { RSA_NO_PADDING, OSSL_PKEY_RSA_PAD_MODE_NONE },
+ { RSA_PKCS1_OAEP_PADDING, OSSL_PKEY_RSA_PAD_MODE_OAEP }, /* Correct spelling first */
+ { RSA_PKCS1_OAEP_PADDING, "oeap" },
+ { RSA_X931_PADDING, OSSL_PKEY_RSA_PAD_MODE_X931 },
+ { 0, NULL }
+};
+
+/*
+ * What's passed as an actual key is defined by the KEYMGMT interface.
+ * We happen to know that our KEYMGMT simply passes RSA structures, so
+ * we use that here too.
+ */
+
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ RSA *rsa;
+ int pad_mode;
+ int operation;
+ /* OAEP message digest */
+ EVP_MD *oaep_md;
+ /* message digest for MGF1 */
+ EVP_MD *mgf1_md;
+ /* OAEP label */
+ unsigned char *oaep_label;
+ size_t oaep_labellen;
+ /* TLS padding */
+ unsigned int client_version;
+ unsigned int alt_version;
+} PROV_RSA_CTX;
+
+static void *rsa_newctx(void *provctx)
+{
+ PROV_RSA_CTX *prsactx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+ prsactx = OPENSSL_zalloc(sizeof(PROV_RSA_CTX));
+ if (prsactx == NULL)
+ return NULL;
+ prsactx->libctx = PROV_LIBCTX_OF(provctx);
+
+ return prsactx;
+}
+
+static int rsa_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[],
+ int operation)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (!ossl_prov_is_running() || prsactx == NULL || vrsa == NULL)
+ return 0;
+
+ if (!ossl_rsa_check_key(prsactx->libctx, vrsa, operation))
+ return 0;
+
+ if (!RSA_up_ref(vrsa))
+ return 0;
+ RSA_free(prsactx->rsa);
+ prsactx->rsa = vrsa;
+ prsactx->operation = operation;
+
+ switch (RSA_test_flags(prsactx->rsa, RSA_FLAG_TYPE_MASK)) {
+ case RSA_FLAG_TYPE_RSA:
+ prsactx->pad_mode = RSA_PKCS1_PADDING;
+ break;
+ default:
+ /* This should not happen due to the check above */
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ return rsa_set_ctx_params(prsactx, params);
+}
+
+static int rsa_encrypt_init(void *vprsactx, void *vrsa,
+ const OSSL_PARAM params[])
+{
+ return rsa_init(vprsactx, vrsa, params, EVP_PKEY_OP_ENCRYPT);
+}
+
+static int rsa_decrypt_init(void *vprsactx, void *vrsa,
+ const OSSL_PARAM params[])
+{
+ return rsa_init(vprsactx, vrsa, params, EVP_PKEY_OP_DECRYPT);
+}
+
+static int rsa_encrypt(void *vprsactx, unsigned char *out, size_t *outlen,
+ size_t outsize, const unsigned char *in, size_t inlen)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ int ret;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (out == NULL) {
+ size_t len = RSA_size(prsactx->rsa);
+
+ if (len == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
+ return 0;
+ }
+ *outlen = len;
+ return 1;
+ }
+
+ if (prsactx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
+ int rsasize = RSA_size(prsactx->rsa);
+ unsigned char *tbuf;
+
+ if ((tbuf = OPENSSL_malloc(rsasize)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (prsactx->oaep_md == NULL) {
+ OPENSSL_free(tbuf);
+ prsactx->oaep_md = EVP_MD_fetch(prsactx->libctx, "SHA-1", NULL);
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ ret =
+ ossl_rsa_padding_add_PKCS1_OAEP_mgf1_ex(prsactx->libctx, tbuf,
+ rsasize, in, inlen,
+ prsactx->oaep_label,
+ prsactx->oaep_labellen,
+ prsactx->oaep_md,
+ prsactx->mgf1_md);
+
+ if (!ret) {
+ OPENSSL_free(tbuf);
+ return 0;
+ }
+ ret = RSA_public_encrypt(rsasize, tbuf, out, prsactx->rsa,
+ RSA_NO_PADDING);
+ OPENSSL_free(tbuf);
+ } else {
+ ret = RSA_public_encrypt(inlen, in, out, prsactx->rsa,
+ prsactx->pad_mode);
+ }
+ /* A ret value of 0 is not an error */
+ if (ret < 0)
+ return ret;
+ *outlen = ret;
+ return 1;
+}
+
+static int rsa_decrypt(void *vprsactx, unsigned char *out, size_t *outlen,
+ size_t outsize, const unsigned char *in, size_t inlen)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ int ret;
+ size_t len = RSA_size(prsactx->rsa);
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (prsactx->pad_mode == RSA_PKCS1_WITH_TLS_PADDING) {
+ if (out == NULL) {
+ *outlen = SSL_MAX_MASTER_KEY_LENGTH;
+ return 1;
+ }
+ if (outsize < SSL_MAX_MASTER_KEY_LENGTH) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH);
+ return 0;
+ }
+ } else {
+ if (out == NULL) {
+ if (len == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
+ return 0;
+ }
+ *outlen = len;
+ return 1;
+ }
+
+ if (outsize < len) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH);
+ return 0;
+ }
+ }
+
+ if (prsactx->pad_mode == RSA_PKCS1_OAEP_PADDING
+ || prsactx->pad_mode == RSA_PKCS1_WITH_TLS_PADDING) {
+ unsigned char *tbuf;
+
+ if ((tbuf = OPENSSL_malloc(len)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ ret = RSA_private_decrypt(inlen, in, tbuf, prsactx->rsa,
+ RSA_NO_PADDING);
+ /*
+ * With no padding then, on success ret should be len, otherwise an
+ * error occurred (non-constant time)
+ */
+ if (ret != (int)len) {
+ OPENSSL_free(tbuf);
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_DECRYPT);
+ return 0;
+ }
+ if (prsactx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
+ if (prsactx->oaep_md == NULL) {
+ prsactx->oaep_md = EVP_MD_fetch(prsactx->libctx, "SHA-1", NULL);
+ if (prsactx->oaep_md == NULL) {
+ OPENSSL_free(tbuf);
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, outsize, tbuf,
+ len, len,
+ prsactx->oaep_label,
+ prsactx->oaep_labellen,
+ prsactx->oaep_md,
+ prsactx->mgf1_md);
+ } else {
+ /* RSA_PKCS1_WITH_TLS_PADDING */
+ if (prsactx->client_version <= 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_BAD_TLS_CLIENT_VERSION);
+ OPENSSL_free(tbuf);
+ return 0;
+ }
+ ret = ossl_rsa_padding_check_PKCS1_type_2_TLS(
+ prsactx->libctx, out, outsize, tbuf, len,
+ prsactx->client_version, prsactx->alt_version);
+ }
+ OPENSSL_free(tbuf);
+ } else {
+ ret = RSA_private_decrypt(inlen, in, out, prsactx->rsa,
+ prsactx->pad_mode);
+ }
+ *outlen = constant_time_select_s(constant_time_msb_s(ret), *outlen, ret);
+ ret = constant_time_select_int(constant_time_msb(ret), 0, 1);
+ return ret;
+}
+
+static void rsa_freectx(void *vprsactx)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ RSA_free(prsactx->rsa);
+
+ EVP_MD_free(prsactx->oaep_md);
+ EVP_MD_free(prsactx->mgf1_md);
+ OPENSSL_free(prsactx->oaep_label);
+
+ OPENSSL_free(prsactx);
+}
+
+static void *rsa_dupctx(void *vprsactx)
+{
+ PROV_RSA_CTX *srcctx = (PROV_RSA_CTX *)vprsactx;
+ PROV_RSA_CTX *dstctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+ if (dstctx == NULL)
+ return NULL;
+
+ *dstctx = *srcctx;
+ if (dstctx->rsa != NULL && !RSA_up_ref(dstctx->rsa)) {
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+
+ if (dstctx->oaep_md != NULL && !EVP_MD_up_ref(dstctx->oaep_md)) {
+ RSA_free(dstctx->rsa);
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+
+ if (dstctx->mgf1_md != NULL && !EVP_MD_up_ref(dstctx->mgf1_md)) {
+ RSA_free(dstctx->rsa);
+ EVP_MD_free(dstctx->oaep_md);
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+
+ return dstctx;
+}
+
+static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ OSSL_PARAM *p;
+
+ if (prsactx == NULL)
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_PAD_MODE);
+ if (p != NULL)
+ switch (p->data_type) {
+ case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
+ if (!OSSL_PARAM_set_int(p, prsactx->pad_mode))
+ return 0;
+ break;
+ case OSSL_PARAM_UTF8_STRING:
+ {
+ int i;
+ const char *word = NULL;
+
+ for (i = 0; padding_item[i].id != 0; i++) {
+ if (prsactx->pad_mode == (int)padding_item[i].id) {
+ word = padding_item[i].ptr;
+ break;
+ }
+ }
+
+ if (word != NULL) {
+ if (!OSSL_PARAM_set_utf8_string(p, word))
+ return 0;
+ } else {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ }
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST);
+ if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->oaep_md == NULL
+ ? ""
+ : EVP_MD_get0_name(prsactx->oaep_md)))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST);
+ if (p != NULL) {
+ EVP_MD *mgf1_md = prsactx->mgf1_md == NULL ? prsactx->oaep_md
+ : prsactx->mgf1_md;
+
+ if (!OSSL_PARAM_set_utf8_string(p, mgf1_md == NULL
+ ? ""
+ : EVP_MD_get0_name(mgf1_md)))
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL);
+ if (p != NULL &&
+ !OSSL_PARAM_set_octet_ptr(p, prsactx->oaep_label,
+ prsactx->oaep_labellen))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION);
+ if (p != NULL && !OSSL_PARAM_set_uint(p, prsactx->client_version))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION);
+ if (p != NULL && !OSSL_PARAM_set_uint(p, prsactx->alt_version))
+ return 0;
+
+ return 1;
+}
+
+static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, OSSL_PARAM_OCTET_PTR,
+ NULL, 0),
+ OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, NULL),
+ OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, NULL),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *rsa_gettable_ctx_params(ossl_unused void *vprsactx,
+ ossl_unused void *provctx)
+{
+ return known_gettable_ctx_params;
+}
+
+static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ const OSSL_PARAM *p;
+ char mdname[OSSL_MAX_NAME_SIZE];
+ char mdprops[OSSL_MAX_PROPQUERY_SIZE] = { '\0' };
+ char *str = NULL;
+
+ if (prsactx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST);
+ if (p != NULL) {
+ str = mdname;
+ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdname)))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params,
+ OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS);
+ if (p != NULL) {
+ str = mdprops;
+ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops)))
+ return 0;
+ }
+
+ EVP_MD_free(prsactx->oaep_md);
+ prsactx->oaep_md = EVP_MD_fetch(prsactx->libctx, mdname, mdprops);
+
+ if (prsactx->oaep_md == NULL)
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_PAD_MODE);
+ if (p != NULL) {
+ int pad_mode = 0;
+
+ switch (p->data_type) {
+ case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
+ if (!OSSL_PARAM_get_int(p, &pad_mode))
+ return 0;
+ break;
+ case OSSL_PARAM_UTF8_STRING:
+ {
+ int i;
+
+ if (p->data == NULL)
+ return 0;
+
+ for (i = 0; padding_item[i].id != 0; i++) {
+ if (strcmp(p->data, padding_item[i].ptr) == 0) {
+ pad_mode = padding_item[i].id;
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ /*
+ * PSS padding is for signatures only so is not compatible with
+ * asymmetric cipher use.
+ */
+ if (pad_mode == RSA_PKCS1_PSS_PADDING)
+ return 0;
+ if (pad_mode == RSA_PKCS1_OAEP_PADDING && prsactx->oaep_md == NULL) {
+ prsactx->oaep_md = EVP_MD_fetch(prsactx->libctx, "SHA1", mdprops);
+ if (prsactx->oaep_md == NULL)
+ return 0;
+ }
+ prsactx->pad_mode = pad_mode;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST);
+ if (p != NULL) {
+ str = mdname;
+ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdname)))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params,
+ OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS);
+ if (p != NULL) {
+ str = mdprops;
+ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops)))
+ return 0;
+ } else {
+ str = NULL;
+ }
+
+ EVP_MD_free(prsactx->mgf1_md);
+ prsactx->mgf1_md = EVP_MD_fetch(prsactx->libctx, mdname, str);
+
+ if (prsactx->mgf1_md == NULL)
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL);
+ if (p != NULL) {
+ void *tmp_label = NULL;
+ size_t tmp_labellen;
+
+ if (!OSSL_PARAM_get_octet_string(p, &tmp_label, 0, &tmp_labellen))
+ return 0;
+ OPENSSL_free(prsactx->oaep_label);
+ prsactx->oaep_label = (unsigned char *)tmp_label;
+ prsactx->oaep_labellen = tmp_labellen;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION);
+ if (p != NULL) {
+ unsigned int client_version;
+
+ if (!OSSL_PARAM_get_uint(p, &client_version))
+ return 0;
+ prsactx->client_version = client_version;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION);
+ if (p != NULL) {
+ unsigned int alt_version;
+
+ if (!OSSL_PARAM_get_uint(p, &alt_version))
+ return 0;
+ prsactx->alt_version = alt_version;
+ }
+
+ return 1;
+}
+
+static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, NULL, 0),
+ OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, NULL),
+ OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, NULL),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *rsa_settable_ctx_params(ossl_unused void *vprsactx,
+ ossl_unused void *provctx)
+{
+ return known_settable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_rsa_asym_cipher_functions[] = {
+ { OSSL_FUNC_ASYM_CIPHER_NEWCTX, (void (*)(void))rsa_newctx },
+ { OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT, (void (*)(void))rsa_encrypt_init },
+ { OSSL_FUNC_ASYM_CIPHER_ENCRYPT, (void (*)(void))rsa_encrypt },
+ { OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT, (void (*)(void))rsa_decrypt_init },
+ { OSSL_FUNC_ASYM_CIPHER_DECRYPT, (void (*)(void))rsa_decrypt },
+ { OSSL_FUNC_ASYM_CIPHER_FREECTX, (void (*)(void))rsa_freectx },
+ { OSSL_FUNC_ASYM_CIPHER_DUPCTX, (void (*)(void))rsa_dupctx },
+ { OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS,
+ (void (*)(void))rsa_get_ctx_params },
+ { OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS,
+ (void (*)(void))rsa_gettable_ctx_params },
+ { OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS,
+ (void (*)(void))rsa_set_ctx_params },
+ { OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS,
+ (void (*)(void))rsa_settable_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/asymciphers/sm2_enc.c b/providers/implementations/asymciphers/sm2_enc.c
new file mode 100644
index 000000000000..a7c9156087cf
--- /dev/null
+++ b/providers/implementations/asymciphers/sm2_enc.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/deprecated.h"
+
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include "crypto/sm2.h"
+#include "prov/provider_ctx.h"
+#include "prov/implementations.h"
+#include "prov/provider_util.h"
+
+static OSSL_FUNC_asym_cipher_newctx_fn sm2_newctx;
+static OSSL_FUNC_asym_cipher_encrypt_init_fn sm2_init;
+static OSSL_FUNC_asym_cipher_encrypt_fn sm2_asym_encrypt;
+static OSSL_FUNC_asym_cipher_decrypt_init_fn sm2_init;
+static OSSL_FUNC_asym_cipher_decrypt_fn sm2_asym_decrypt;
+static OSSL_FUNC_asym_cipher_freectx_fn sm2_freectx;
+static OSSL_FUNC_asym_cipher_dupctx_fn sm2_dupctx;
+static OSSL_FUNC_asym_cipher_get_ctx_params_fn sm2_get_ctx_params;
+static OSSL_FUNC_asym_cipher_gettable_ctx_params_fn sm2_gettable_ctx_params;
+static OSSL_FUNC_asym_cipher_set_ctx_params_fn sm2_set_ctx_params;
+static OSSL_FUNC_asym_cipher_settable_ctx_params_fn sm2_settable_ctx_params;
+
+/*
+ * What's passed as an actual key is defined by the KEYMGMT interface.
+ * We happen to know that our KEYMGMT simply passes EC_KEY structures, so
+ * we use that here too.
+ */
+
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ EC_KEY *key;
+ PROV_DIGEST md;
+} PROV_SM2_CTX;
+
+static void *sm2_newctx(void *provctx)
+{
+ PROV_SM2_CTX *psm2ctx = OPENSSL_zalloc(sizeof(PROV_SM2_CTX));
+
+ if (psm2ctx == NULL)
+ return NULL;
+ psm2ctx->libctx = PROV_LIBCTX_OF(provctx);
+
+ return psm2ctx;
+}
+
+static int sm2_init(void *vpsm2ctx, void *vkey, const OSSL_PARAM params[])
+{
+ PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
+
+ if (psm2ctx == NULL || vkey == NULL || !EC_KEY_up_ref(vkey))
+ return 0;
+ EC_KEY_free(psm2ctx->key);
+ psm2ctx->key = vkey;
+
+ return sm2_set_ctx_params(psm2ctx, params);
+}
+
+static const EVP_MD *sm2_get_md(PROV_SM2_CTX *psm2ctx)
+{
+ const EVP_MD *md = ossl_prov_digest_md(&psm2ctx->md);
+
+ if (md == NULL)
+ md = ossl_prov_digest_fetch(&psm2ctx->md, psm2ctx->libctx, "SM3", NULL);
+
+ return md;
+}
+
+static int sm2_asym_encrypt(void *vpsm2ctx, unsigned char *out, size_t *outlen,
+ size_t outsize, const unsigned char *in,
+ size_t inlen)
+{
+ PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
+ const EVP_MD *md = sm2_get_md(psm2ctx);
+
+ if (md == NULL)
+ return 0;
+
+ if (out == NULL) {
+ if (!ossl_sm2_ciphertext_size(psm2ctx->key, md, inlen, outlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
+ return 0;
+ }
+ return 1;
+ }
+
+ return ossl_sm2_encrypt(psm2ctx->key, md, in, inlen, out, outlen);
+}
+
+static int sm2_asym_decrypt(void *vpsm2ctx, unsigned char *out, size_t *outlen,
+ size_t outsize, const unsigned char *in,
+ size_t inlen)
+{
+ PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
+ const EVP_MD *md = sm2_get_md(psm2ctx);
+
+ if (md == NULL)
+ return 0;
+
+ if (out == NULL) {
+ if (!ossl_sm2_plaintext_size(in, inlen, outlen))
+ return 0;
+ return 1;
+ }
+
+ return ossl_sm2_decrypt(psm2ctx->key, md, in, inlen, out, outlen);
+}
+
+static void sm2_freectx(void *vpsm2ctx)
+{
+ PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
+
+ EC_KEY_free(psm2ctx->key);
+ ossl_prov_digest_reset(&psm2ctx->md);
+
+ OPENSSL_free(psm2ctx);
+}
+
+static void *sm2_dupctx(void *vpsm2ctx)
+{
+ PROV_SM2_CTX *srcctx = (PROV_SM2_CTX *)vpsm2ctx;
+ PROV_SM2_CTX *dstctx;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+ if (dstctx == NULL)
+ return NULL;
+
+ *dstctx = *srcctx;
+ memset(&dstctx->md, 0, sizeof(dstctx->md));
+
+ if (dstctx->key != NULL && !EC_KEY_up_ref(dstctx->key)) {
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+
+ if (!ossl_prov_digest_copy(&dstctx->md, &srcctx->md)) {
+ sm2_freectx(dstctx);
+ return NULL;
+ }
+
+ return dstctx;
+}
+
+static int sm2_get_ctx_params(void *vpsm2ctx, OSSL_PARAM *params)
+{
+ PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
+ OSSL_PARAM *p;
+
+ if (vpsm2ctx == NULL)
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_DIGEST);
+ if (p != NULL) {
+ const EVP_MD *md = ossl_prov_digest_md(&psm2ctx->md);
+
+ if (!OSSL_PARAM_set_utf8_string(p, md == NULL ? ""
+ : EVP_MD_get0_name(md)))
+ return 0;
+ }
+
+ return 1;
+}
+
+static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *sm2_gettable_ctx_params(ossl_unused void *vpsm2ctx,
+ ossl_unused void *provctx)
+{
+ return known_gettable_ctx_params;
+}
+
+static int sm2_set_ctx_params(void *vpsm2ctx, const OSSL_PARAM params[])
+{
+ PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
+
+ if (psm2ctx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+ if (!ossl_prov_digest_load_from_params(&psm2ctx->md, params,
+ psm2ctx->libctx))
+ return 0;
+
+ return 1;
+}
+
+static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_ENGINE, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *sm2_settable_ctx_params(ossl_unused void *vpsm2ctx,
+ ossl_unused void *provctx)
+{
+ return known_settable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_sm2_asym_cipher_functions[] = {
+ { OSSL_FUNC_ASYM_CIPHER_NEWCTX, (void (*)(void))sm2_newctx },
+ { OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT, (void (*)(void))sm2_init },
+ { OSSL_FUNC_ASYM_CIPHER_ENCRYPT, (void (*)(void))sm2_asym_encrypt },
+ { OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT, (void (*)(void))sm2_init },
+ { OSSL_FUNC_ASYM_CIPHER_DECRYPT, (void (*)(void))sm2_asym_decrypt },
+ { OSSL_FUNC_ASYM_CIPHER_FREECTX, (void (*)(void))sm2_freectx },
+ { OSSL_FUNC_ASYM_CIPHER_DUPCTX, (void (*)(void))sm2_dupctx },
+ { OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS,
+ (void (*)(void))sm2_get_ctx_params },
+ { OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS,
+ (void (*)(void))sm2_gettable_ctx_params },
+ { OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS,
+ (void (*)(void))sm2_set_ctx_params },
+ { OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS,
+ (void (*)(void))sm2_settable_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/build.info b/providers/implementations/build.info
new file mode 100644
index 000000000000..a2f60653e2c2
--- /dev/null
+++ b/providers/implementations/build.info
@@ -0,0 +1,2 @@
+SUBDIRS=digests ciphers rands macs kdfs exchange keymgmt signature asymciphers \
+ encode_decode storemgmt kem
diff --git a/providers/implementations/ciphers/build.info b/providers/implementations/ciphers/build.info
new file mode 100644
index 000000000000..e4c5f4f051b6
--- /dev/null
+++ b/providers/implementations/ciphers/build.info
@@ -0,0 +1,142 @@
+# We make separate GOAL variables for each algorithm, to make it easy to
+# switch each to the Legacy provider when needed.
+#
+# $TDES_1_GOAL and $TDES_2_GOAL separate FIPSable and non-FIPSable TDES.
+# The latter may become legacy sooner, so it's comfortable to have two
+# variables already now, to switch the non-FIPSable TDES to legacy if needed.
+
+$COMMON_GOAL=../../libcommon.a
+
+$NULL_GOAL=../../libdefault.a
+$AES_GOAL=../../libdefault.a ../../libfips.a
+$TDES_1_GOAL=../../libdefault.a ../../libfips.a
+$TDES_2_GOAL=../../libdefault.a
+$ARIA_GOAL=../../libdefault.a
+$CAMELLIA_GOAL=../../libdefault.a
+$DES_GOAL=../../liblegacy.a
+$BLOWFISH_GOAL=../../liblegacy.a
+$IDEA_GOAL=../../liblegacy.a
+$CAST5_GOAL=../../liblegacy.a
+$RC2_GOAL=../../liblegacy.a
+$RC4_GOAL=../../liblegacy.a
+$RC5_GOAL=../../liblegacy.a
+$SEED_GOAL=../../liblegacy.a
+$SM4_GOAL=../../libdefault.a
+$CHACHA_GOAL=../../libdefault.a
+$CHACHAPOLY_GOAL=../../libdefault.a
+$SIV_GOAL=../../libdefault.a
+
+# This source is common building blocks for all ciphers in all our providers.
+SOURCE[$COMMON_GOAL]=\
+ ciphercommon.c ciphercommon_hw.c ciphercommon_block.c \
+ ciphercommon_gcm.c ciphercommon_gcm_hw.c \
+ ciphercommon_ccm.c ciphercommon_ccm_hw.c
+
+IF[{- !$disabled{des} -}]
+ SOURCE[$TDES_1_GOAL]=cipher_tdes.c cipher_tdes_common.c cipher_tdes_hw.c
+ENDIF
+
+SOURCE[$NULL_GOAL]=\
+ cipher_null.c
+
+SOURCE[$AES_GOAL]=\
+ cipher_aes.c cipher_aes_hw.c \
+ cipher_aes_xts.c cipher_aes_xts_hw.c \
+ cipher_aes_gcm.c cipher_aes_gcm_hw.c \
+ cipher_aes_ccm.c cipher_aes_ccm_hw.c \
+ cipher_aes_wrp.c \
+ cipher_aes_cbc_hmac_sha.c \
+ cipher_aes_cbc_hmac_sha256_hw.c cipher_aes_cbc_hmac_sha1_hw.c \
+ cipher_cts.c
+
+# Extra code to satisfy the FIPS and non-FIPS separation.
+# When the AES-xxx-XTS moves to legacy, cipher_aes_xts_fips.c can be removed.
+SOURCE[$AES_GOAL]=cipher_aes_xts_fips.c
+
+IF[{- !$disabled{siv} -}]
+ SOURCE[$SIV_GOAL]=\
+ cipher_aes_siv.c cipher_aes_siv_hw.c
+ENDIF
+
+IF[{- !$disabled{des} -}]
+ SOURCE[$TDES_2_GOAL]=\
+ cipher_tdes_default.c cipher_tdes_default_hw.c \
+ cipher_tdes_wrap.c cipher_tdes_wrap_hw.c
+ SOURCE[$DES_GOAL]=\
+ cipher_desx.c cipher_desx_hw.c \
+ cipher_des.c cipher_des_hw.c
+ IF[{- !$disabled{module} -}]
+ SOURCE[$DES_GOAL]=\
+ cipher_tdes_common.c
+ ENDIF
+ENDIF
+
+IF[{- !$disabled{aria} -}]
+ SOURCE[$ARIA_GOAL]=\
+ cipher_aria.c cipher_aria_hw.c \
+ cipher_aria_gcm.c cipher_aria_gcm_hw.c \
+ cipher_aria_ccm.c cipher_aria_ccm_hw.c
+ENDIF
+
+IF[{- !$disabled{camellia} -}]
+ SOURCE[$CAMELLIA_GOAL]=\
+ cipher_camellia.c cipher_camellia_hw.c
+ENDIF
+
+IF[{- !$disabled{bf} -}]
+ SOURCE[$BLOWFISH_GOAL]=\
+ cipher_blowfish.c cipher_blowfish_hw.c
+ENDIF
+
+IF[{- !$disabled{idea} -}]
+ SOURCE[$IDEA_GOAL]=\
+ cipher_idea.c cipher_idea_hw.c
+ENDIF
+
+IF[{- !$disabled{cast} -}]
+ SOURCE[$CAST5_GOAL]=\
+ cipher_cast5.c cipher_cast5_hw.c
+ENDIF
+
+IF[{- !$disabled{seed} -}]
+ SOURCE[$SEED_GOAL]=\
+ cipher_seed.c cipher_seed_hw.c
+ENDIF
+
+IF[{- !$disabled{sm4} -}]
+ SOURCE[$SM4_GOAL]=\
+ cipher_sm4.c cipher_sm4_hw.c
+ENDIF
+
+IF[{- !$disabled{ocb} -}]
+ SOURCE[$AES_GOAL]=\
+ cipher_aes_ocb.c cipher_aes_ocb_hw.c
+ENDIF
+
+IF[{- !$disabled{rc4} -}]
+ SOURCE[$RC4_GOAL]=\
+ cipher_rc4.c cipher_rc4_hw.c
+ IF[{- !$disabled{md5} -}]
+ SOURCE[$RC4_GOAL]=\
+ cipher_rc4_hmac_md5.c cipher_rc4_hmac_md5_hw.c
+ ENDIF
+ENDIF
+
+IF[{- !$disabled{rc5} -}]
+ SOURCE[$RC5_GOAL]=\
+ cipher_rc5.c cipher_rc5_hw.c
+ENDIF
+
+IF[{- !$disabled{rc2} -}]
+ SOURCE[$RC2_GOAL]=\
+ cipher_rc2.c cipher_rc2_hw.c
+ENDIF
+
+IF[{- !$disabled{chacha} -}]
+ SOURCE[$CHACHA_GOAL]=\
+ cipher_chacha20.c cipher_chacha20_hw.c
+ IF[{- !$disabled{poly1305} -}]
+ SOURCE[$CHACHAPOLY_GOAL]=\
+ cipher_chacha20_poly1305.c cipher_chacha20_poly1305_hw.c
+ ENDIF
+ENDIF
diff --git a/providers/implementations/ciphers/cipher_aes.c b/providers/implementations/ciphers/cipher_aes.c
new file mode 100644
index 000000000000..2f469c131a7e
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * AES low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
+/* Dispatch functions for AES cipher modes ecb, cbc, ofb, cfb, ctr */
+
+#include "cipher_aes.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+static OSSL_FUNC_cipher_freectx_fn aes_freectx;
+static OSSL_FUNC_cipher_dupctx_fn aes_dupctx;
+
+static void aes_freectx(void *vctx)
+{
+ PROV_AES_CTX *ctx = (PROV_AES_CTX *)vctx;
+
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static void *aes_dupctx(void *ctx)
+{
+ PROV_AES_CTX *in = (PROV_AES_CTX *)ctx;
+ PROV_AES_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ret = OPENSSL_malloc(sizeof(*ret));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ in->base.hw->copyctx(&ret->base, &in->base);
+
+ return ret;
+}
+
+/* ossl_aes256ecb_functions */
+IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 256, 128, 0, block)
+/* ossl_aes192ecb_functions */
+IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 192, 128, 0, block)
+/* ossl_aes128ecb_functions */
+IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 128, 128, 0, block)
+/* ossl_aes256cbc_functions */
+IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 256, 128, 128, block)
+/* ossl_aes192cbc_functions */
+IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 192, 128, 128, block)
+/* ossl_aes128cbc_functions */
+IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 128, 128, 128, block)
+/* ossl_aes256ofb_functions */
+IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 256, 8, 128, stream)
+/* ossl_aes192ofb_functions */
+IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 192, 8, 128, stream)
+/* ossl_aes128ofb_functions */
+IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 128, 8, 128, stream)
+/* ossl_aes256cfb_functions */
+IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 256, 8, 128, stream)
+/* ossl_aes192cfb_functions */
+IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 192, 8, 128, stream)
+/* ossl_aes128cfb_functions */
+IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 128, 8, 128, stream)
+/* ossl_aes256cfb1_functions */
+IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 256, 8, 128, stream)
+/* ossl_aes192cfb1_functions */
+IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 192, 8, 128, stream)
+/* ossl_aes128cfb1_functions */
+IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 128, 8, 128, stream)
+/* ossl_aes256cfb8_functions */
+IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 256, 8, 128, stream)
+/* ossl_aes192cfb8_functions */
+IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 192, 8, 128, stream)
+/* ossl_aes128cfb8_functions */
+IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 128, 8, 128, stream)
+/* ossl_aes256ctr_functions */
+IMPLEMENT_generic_cipher(aes, AES, ctr, CTR, 0, 256, 8, 128, stream)
+/* ossl_aes192ctr_functions */
+IMPLEMENT_generic_cipher(aes, AES, ctr, CTR, 0, 192, 8, 128, stream)
+/* ossl_aes128ctr_functions */
+IMPLEMENT_generic_cipher(aes, AES, ctr, CTR, 0, 128, 8, 128, stream)
+
+#include "cipher_aes_cts.inc"
diff --git a/providers/implementations/ciphers/cipher_aes.h b/providers/implementations/ciphers/cipher_aes.h
new file mode 100644
index 000000000000..7eaf76c8c47d
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/aes.h>
+#include "prov/ciphercommon.h"
+#include "crypto/aes_platform.h"
+
+typedef struct prov_aes_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ AES_KEY ks;
+ } ks;
+
+ /* Platform specific data */
+ union {
+ int dummy;
+#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
+ struct {
+ union {
+ OSSL_UNION_ALIGN;
+ /*-
+ * KM-AES parameter block - begin
+ * (see z/Architecture Principles of Operation >= SA22-7832-06)
+ */
+ struct {
+ unsigned char k[32];
+ } km;
+ /* KM-AES parameter block - end */
+ /*-
+ * KMO-AES/KMF-AES parameter block - begin
+ * (see z/Architecture Principles of Operation >= SA22-7832-08)
+ */
+ struct {
+ unsigned char cv[16];
+ unsigned char k[32];
+ } kmo_kmf;
+ /* KMO-AES/KMF-AES parameter block - end */
+ } param;
+ unsigned int fc;
+ int res;
+ } s390x;
+#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
+ } plat;
+
+} PROV_AES_CTX;
+
+#define ossl_prov_cipher_hw_aes_ofb ossl_prov_cipher_hw_aes_ofb128
+#define ossl_prov_cipher_hw_aes_cfb ossl_prov_cipher_hw_aes_cfb128
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ecb(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cbc(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ofb128(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb128(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb1(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb8(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ctr(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c
new file mode 100644
index 000000000000..f9a8a5804149
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * AES low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
+/* Dispatch functions for AES_CBC_HMAC_SHA ciphers */
+
+/* For SSL3_VERSION and TLS1_VERSION */
+#include <openssl/prov_ssl.h>
+#include <openssl/proverr.h>
+#include "cipher_aes_cbc_hmac_sha.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+#ifndef AES_CBC_HMAC_SHA_CAPABLE
+# define IMPLEMENT_CIPHER(nm, sub, kbits, blkbits, ivbits, flags) \
+const OSSL_DISPATCH ossl_##nm##kbits##sub##_functions[] = { \
+ { 0, NULL } \
+};
+#else
+
+# define AES_CBC_HMAC_SHA_FLAGS (PROV_CIPHER_FLAG_AEAD \
+ | PROV_CIPHER_FLAG_TLS1_MULTIBLOCK)
+
+static OSSL_FUNC_cipher_encrypt_init_fn aes_einit;
+static OSSL_FUNC_cipher_decrypt_init_fn aes_dinit;
+static OSSL_FUNC_cipher_freectx_fn aes_cbc_hmac_sha1_freectx;
+static OSSL_FUNC_cipher_freectx_fn aes_cbc_hmac_sha256_freectx;
+static OSSL_FUNC_cipher_get_ctx_params_fn aes_get_ctx_params;
+static OSSL_FUNC_cipher_gettable_ctx_params_fn aes_gettable_ctx_params;
+static OSSL_FUNC_cipher_set_ctx_params_fn aes_set_ctx_params;
+static OSSL_FUNC_cipher_settable_ctx_params_fn aes_settable_ctx_params;
+# define aes_gettable_params ossl_cipher_generic_gettable_params
+# define aes_update ossl_cipher_generic_stream_update
+# define aes_final ossl_cipher_generic_stream_final
+# define aes_cipher ossl_cipher_generic_cipher
+
+static int aes_einit(void *ctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ if (!ossl_cipher_generic_einit(ctx, key, keylen, iv, ivlen, NULL))
+ return 0;
+ return aes_set_ctx_params(ctx, params);
+}
+
+static int aes_dinit(void *ctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ if (!ossl_cipher_generic_dinit(ctx, key, keylen, iv, ivlen, NULL))
+ return 0;
+ return aes_set_ctx_params(ctx, params);
+}
+
+static const OSSL_PARAM cipher_aes_known_settable_ctx_params[] = {
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_MAC_KEY, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0),
+# if !defined(OPENSSL_NO_MULTIBLOCK)
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD, NULL),
+ OSSL_PARAM_uint(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE, NULL),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN, NULL, 0),
+# endif /* !defined(OPENSSL_NO_MULTIBLOCK) */
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_END
+};
+const OSSL_PARAM *aes_settable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *provctx)
+{
+ return cipher_aes_known_settable_ctx_params;
+}
+
+static int aes_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
+ PROV_CIPHER_HW_AES_HMAC_SHA *hw =
+ (PROV_CIPHER_HW_AES_HMAC_SHA *)ctx->hw;
+ const OSSL_PARAM *p;
+ int ret = 1;
+# if !defined(OPENSSL_NO_MULTIBLOCK)
+ EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
+# endif
+
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_MAC_KEY);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ hw->init_mac_key(ctx, p->data, p->data_size);
+ }
+
+# if !defined(OPENSSL_NO_MULTIBLOCK)
+ p = OSSL_PARAM_locate_const(params,
+ OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT);
+ if (p != NULL
+ && !OSSL_PARAM_get_size_t(p, &ctx->multiblock_max_send_fragment)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ /*
+ * The inputs to tls1_multiblock_aad are:
+ * mb_param->inp
+ * mb_param->len
+ * mb_param->interleave
+ * The outputs of tls1_multiblock_aad are written to:
+ * ctx->multiblock_interleave
+ * ctx->multiblock_aad_packlen
+ */
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD);
+ if (p != NULL) {
+ const OSSL_PARAM *p1 = OSSL_PARAM_locate_const(params,
+ OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE);
+ if (p->data_type != OSSL_PARAM_OCTET_STRING
+ || p1 == NULL
+ || !OSSL_PARAM_get_uint(p1, &mb_param.interleave)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ mb_param.inp = p->data;
+ mb_param.len = p->data_size;
+ if (hw->tls1_multiblock_aad(vctx, &mb_param) <= 0)
+ return 0;
+ }
+
+ /*
+ * The inputs to tls1_multiblock_encrypt are:
+ * mb_param->inp
+ * mb_param->len
+ * mb_param->interleave
+ * mb_param->out
+ * The outputs of tls1_multiblock_encrypt are:
+ * ctx->multiblock_encrypt_len
+ */
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC);
+ if (p != NULL) {
+ const OSSL_PARAM *p1 = OSSL_PARAM_locate_const(params,
+ OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE);
+ const OSSL_PARAM *pin = OSSL_PARAM_locate_const(params,
+ OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN);
+
+ if (p->data_type != OSSL_PARAM_OCTET_STRING
+ || pin == NULL
+ || pin->data_type != OSSL_PARAM_OCTET_STRING
+ || p1 == NULL
+ || !OSSL_PARAM_get_uint(p1, &mb_param.interleave)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ mb_param.out = p->data;
+ mb_param.inp = pin->data;
+ mb_param.len = pin->data_size;
+ if (hw->tls1_multiblock_encrypt(vctx, &mb_param) <= 0)
+ return 0;
+ }
+# endif /* !defined(OPENSSL_NO_MULTIBLOCK) */
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (hw->set_tls1_aad(ctx, p->data, p->data_size) <= 0)
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL) {
+ size_t keylen;
+
+ if (!OSSL_PARAM_get_size_t(p, &keylen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (ctx->base.keylen != keylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLS_VERSION);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_uint(p, &ctx->base.tlsversion)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (ctx->base.tlsversion == SSL3_VERSION
+ || ctx->base.tlsversion == TLS1_VERSION) {
+ if (!ossl_assert(ctx->base.removetlsfixed >= AES_BLOCK_SIZE)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ /*
+ * There is no explicit IV with these TLS versions, so don't attempt
+ * to remove it.
+ */
+ ctx->base.removetlsfixed -= AES_BLOCK_SIZE;
+ }
+ }
+ return ret;
+}
+
+static int aes_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
+ OSSL_PARAM *p;
+
+# if !defined(OPENSSL_NO_MULTIBLOCK)
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE);
+ if (p != NULL) {
+ PROV_CIPHER_HW_AES_HMAC_SHA *hw =
+ (PROV_CIPHER_HW_AES_HMAC_SHA *)ctx->hw;
+ size_t len = hw->tls1_multiblock_max_bufsize(ctx);
+
+ if (!OSSL_PARAM_set_size_t(p, len)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE);
+ if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->multiblock_interleave)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN);
+ if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->multiblock_aad_packlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->multiblock_encrypt_len)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+# endif /* !defined(OPENSSL_NO_MULTIBLOCK) */
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.keylen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.ivlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
+ if (p != NULL
+ && !OSSL_PARAM_set_octet_string(p, ctx->base.oiv, ctx->base.ivlen)
+ && !OSSL_PARAM_set_octet_ptr(p, &ctx->base.oiv, ctx->base.ivlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_UPDATED_IV);
+ if (p != NULL
+ && !OSSL_PARAM_set_octet_string(p, ctx->base.iv, ctx->base.ivlen)
+ && !OSSL_PARAM_set_octet_ptr(p, &ctx->base.iv, ctx->base.ivlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ return 1;
+}
+
+static const OSSL_PARAM cipher_aes_known_gettable_ctx_params[] = {
+# if !defined(OPENSSL_NO_MULTIBLOCK)
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE, NULL),
+ OSSL_PARAM_uint(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE, NULL),
+ OSSL_PARAM_uint(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN, NULL),
+# endif /* !defined(OPENSSL_NO_MULTIBLOCK) */
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_UPDATED_IV, NULL, 0),
+ OSSL_PARAM_END
+};
+const OSSL_PARAM *aes_gettable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *provctx)
+{
+ return cipher_aes_known_gettable_ctx_params;
+}
+
+static void base_init(void *provctx, PROV_AES_HMAC_SHA_CTX *ctx,
+ const PROV_CIPHER_HW_AES_HMAC_SHA *meths,
+ size_t kbits, size_t blkbits, size_t ivbits,
+ uint64_t flags)
+{
+ ossl_cipher_generic_initkey(&ctx->base, kbits, blkbits, ivbits,
+ EVP_CIPH_CBC_MODE, flags,
+ &meths->base, provctx);
+ ctx->hw = (PROV_CIPHER_HW_AES_HMAC_SHA *)ctx->base.hw;
+}
+
+static void *aes_cbc_hmac_sha1_newctx(void *provctx, size_t kbits,
+ size_t blkbits, size_t ivbits,
+ uint64_t flags)
+{
+ PROV_AES_HMAC_SHA1_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx != NULL)
+ base_init(provctx, &ctx->base_ctx,
+ ossl_prov_cipher_hw_aes_cbc_hmac_sha1(), kbits, blkbits,
+ ivbits, flags);
+ return ctx;
+}
+
+static void aes_cbc_hmac_sha1_freectx(void *vctx)
+{
+ PROV_AES_HMAC_SHA1_CTX *ctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
+
+ if (ctx != NULL) {
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+ }
+}
+
+static void *aes_cbc_hmac_sha256_newctx(void *provctx, size_t kbits,
+ size_t blkbits, size_t ivbits,
+ uint64_t flags)
+{
+ PROV_AES_HMAC_SHA256_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx != NULL)
+ base_init(provctx, &ctx->base_ctx,
+ ossl_prov_cipher_hw_aes_cbc_hmac_sha256(), kbits, blkbits,
+ ivbits, flags);
+ return ctx;
+}
+
+static void aes_cbc_hmac_sha256_freectx(void *vctx)
+{
+ PROV_AES_HMAC_SHA256_CTX *ctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
+
+ if (ctx != NULL) {
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+ }
+}
+
+# define IMPLEMENT_CIPHER(nm, sub, kbits, blkbits, ivbits, flags) \
+static OSSL_FUNC_cipher_newctx_fn nm##_##kbits##_##sub##_newctx; \
+static void *nm##_##kbits##_##sub##_newctx(void *provctx) \
+{ \
+ return nm##_##sub##_newctx(provctx, kbits, blkbits, ivbits, flags); \
+} \
+static OSSL_FUNC_cipher_get_params_fn nm##_##kbits##_##sub##_get_params; \
+static int nm##_##kbits##_##sub##_get_params(OSSL_PARAM params[]) \
+{ \
+ return ossl_cipher_generic_get_params(params, EVP_CIPH_CBC_MODE, \
+ flags, kbits, blkbits, ivbits); \
+} \
+const OSSL_DISPATCH ossl_##nm##kbits##sub##_functions[] = { \
+ { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))nm##_##kbits##_##sub##_newctx },\
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))nm##_##sub##_freectx }, \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))nm##_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))nm##_dinit }, \
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))nm##_update }, \
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))nm##_final }, \
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))nm##_cipher }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, \
+ (void (*)(void))nm##_##kbits##_##sub##_get_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))nm##_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
+ (void (*)(void))nm##_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void))nm##_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void))nm##_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))nm##_settable_ctx_params }, \
+ { 0, NULL } \
+};
+
+#endif /* AES_CBC_HMAC_SHA_CAPABLE */
+
+/* ossl_aes128cbc_hmac_sha1_functions */
+IMPLEMENT_CIPHER(aes, cbc_hmac_sha1, 128, 128, 128, AES_CBC_HMAC_SHA_FLAGS)
+/* ossl_aes256cbc_hmac_sha1_functions */
+IMPLEMENT_CIPHER(aes, cbc_hmac_sha1, 256, 128, 128, AES_CBC_HMAC_SHA_FLAGS)
+/* ossl_aes128cbc_hmac_sha256_functions */
+IMPLEMENT_CIPHER(aes, cbc_hmac_sha256, 128, 128, 128, AES_CBC_HMAC_SHA_FLAGS)
+/* ossl_aes256cbc_hmac_sha256_functions */
+IMPLEMENT_CIPHER(aes, cbc_hmac_sha256, 256, 128, 128, AES_CBC_HMAC_SHA_FLAGS)
diff --git a/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.h b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.h
new file mode 100644
index 000000000000..6aaf3f06fb49
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/ciphercommon.h"
+#include "crypto/aes_platform.h"
+
+int ossl_cipher_capable_aes_cbc_hmac_sha1(void);
+int ossl_cipher_capable_aes_cbc_hmac_sha256(void);
+
+typedef struct prov_cipher_hw_aes_hmac_sha_ctx_st {
+ PROV_CIPHER_HW base; /* must be first */
+ void (*init_mac_key)(void *ctx, const unsigned char *inkey, size_t inlen);
+ int (*set_tls1_aad)(void *ctx, unsigned char *aad_rec, int aad_len);
+# if !defined(OPENSSL_NO_MULTIBLOCK)
+ int (*tls1_multiblock_max_bufsize)(void *ctx);
+ int (*tls1_multiblock_aad)(
+ void *vctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param);
+ int (*tls1_multiblock_encrypt)(
+ void *ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param);
+# endif /* OPENSSL_NO_MULTIBLOCK) */
+} PROV_CIPHER_HW_AES_HMAC_SHA;
+
+const PROV_CIPHER_HW_AES_HMAC_SHA *ossl_prov_cipher_hw_aes_cbc_hmac_sha1(void);
+const PROV_CIPHER_HW_AES_HMAC_SHA *ossl_prov_cipher_hw_aes_cbc_hmac_sha256(void);
+
+#ifdef AES_CBC_HMAC_SHA_CAPABLE
+# include <openssl/aes.h>
+# include <openssl/sha.h>
+
+typedef struct prov_aes_hmac_sha_ctx_st {
+ PROV_CIPHER_CTX base;
+ AES_KEY ks;
+ size_t payload_length; /* AAD length in decrypt case */
+ union {
+ unsigned int tls_ver;
+ unsigned char tls_aad[16]; /* 13 used */
+ } aux;
+ const PROV_CIPHER_HW_AES_HMAC_SHA *hw;
+ /* some value that are setup by set methods - that can be retrieved */
+ unsigned int multiblock_interleave;
+ unsigned int multiblock_aad_packlen;
+ size_t multiblock_max_send_fragment;
+ size_t multiblock_encrypt_len;
+ size_t tls_aad_pad;
+} PROV_AES_HMAC_SHA_CTX;
+
+typedef struct prov_aes_hmac_sha1_ctx_st {
+ PROV_AES_HMAC_SHA_CTX base_ctx;
+ SHA_CTX head, tail, md;
+} PROV_AES_HMAC_SHA1_CTX;
+
+typedef struct prov_aes_hmac_sha256_ctx_st {
+ PROV_AES_HMAC_SHA_CTX base_ctx;
+ SHA256_CTX head, tail, md;
+} PROV_AES_HMAC_SHA256_CTX;
+
+# define NO_PAYLOAD_LENGTH ((size_t)-1)
+
+#endif /* AES_CBC_HMAC_SHA_CAPABLE */
diff --git a/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha1_hw.c b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha1_hw.c
new file mode 100644
index 000000000000..76674d530434
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha1_hw.c
@@ -0,0 +1,795 @@
+/*
+ * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * All low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_aes_cbc_hmac_sha.h"
+
+#if !defined(AES_CBC_HMAC_SHA_CAPABLE) || !defined(AESNI_CAPABLE)
+int ossl_cipher_capable_aes_cbc_hmac_sha1(void)
+{
+ return 0;
+}
+
+const PROV_CIPHER_HW_AES_HMAC_SHA *ossl_prov_cipher_hw_aes_cbc_hmac_sha1(void)
+{
+ return NULL;
+}
+#else
+
+# include <openssl/rand.h>
+# include "crypto/evp.h"
+# include "internal/constant_time.h"
+
+void sha1_block_data_order(void *c, const void *p, size_t len);
+void aesni_cbc_sha1_enc(const void *inp, void *out, size_t blocks,
+ const AES_KEY *key, unsigned char iv[16],
+ SHA_CTX *ctx, const void *in0);
+
+int ossl_cipher_capable_aes_cbc_hmac_sha1(void)
+{
+ return AESNI_CBC_HMAC_SHA_CAPABLE;
+}
+
+static int aesni_cbc_hmac_sha1_init_key(PROV_CIPHER_CTX *vctx,
+ const unsigned char *key, size_t keylen)
+{
+ int ret;
+ PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
+ PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
+
+ if (ctx->base.enc)
+ ret = aesni_set_encrypt_key(key, keylen * 8, &ctx->ks);
+ else
+ ret = aesni_set_decrypt_key(key, keylen * 8, &ctx->ks);
+
+ SHA1_Init(&sctx->head); /* handy when benchmarking */
+ sctx->tail = sctx->head;
+ sctx->md = sctx->head;
+
+ ctx->payload_length = NO_PAYLOAD_LENGTH;
+
+ vctx->removetlspad = 1;
+ vctx->removetlsfixed = SHA_DIGEST_LENGTH + AES_BLOCK_SIZE;
+
+ return ret < 0 ? 0 : 1;
+}
+
+static void sha1_update(SHA_CTX *c, const void *data, size_t len)
+{
+ const unsigned char *ptr = data;
+ size_t res;
+
+ if ((res = c->num)) {
+ res = SHA_CBLOCK - res;
+ if (len < res)
+ res = len;
+ SHA1_Update(c, ptr, res);
+ ptr += res;
+ len -= res;
+ }
+
+ res = len % SHA_CBLOCK;
+ len -= res;
+
+ if (len) {
+ sha1_block_data_order(c, ptr, len / SHA_CBLOCK);
+
+ ptr += len;
+ c->Nh += len >> 29;
+ c->Nl += len <<= 3;
+ if (c->Nl < (unsigned int)len)
+ c->Nh++;
+ }
+
+ if (res)
+ SHA1_Update(c, ptr, res);
+}
+
+# if !defined(OPENSSL_NO_MULTIBLOCK)
+
+typedef struct {
+ unsigned int A[8], B[8], C[8], D[8], E[8];
+} SHA1_MB_CTX;
+
+typedef struct {
+ const unsigned char *ptr;
+ int blocks;
+} HASH_DESC;
+
+typedef struct {
+ const unsigned char *inp;
+ unsigned char *out;
+ int blocks;
+ u64 iv[2];
+} CIPH_DESC;
+
+void sha1_multi_block(SHA1_MB_CTX *, const HASH_DESC *, int);
+void aesni_multi_cbc_encrypt(CIPH_DESC *, void *, int);
+
+static size_t tls1_multi_block_encrypt(void *vctx,
+ unsigned char *out,
+ const unsigned char *inp,
+ size_t inp_len, int n4x)
+{ /* n4x is 1 or 2 */
+ PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
+ PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
+ HASH_DESC hash_d[8], edges[8];
+ CIPH_DESC ciph_d[8];
+ unsigned char storage[sizeof(SHA1_MB_CTX) + 32];
+ union {
+ u64 q[16];
+ u32 d[32];
+ u8 c[128];
+ } blocks[8];
+ SHA1_MB_CTX *mctx;
+ unsigned int frag, last, packlen, i;
+ unsigned int x4 = 4 * n4x, minblocks, processed = 0;
+ size_t ret = 0;
+ u8 *IVs;
+# if defined(BSWAP8)
+ u64 seqnum;
+# endif
+
+ /* ask for IVs in bulk */
+ if (RAND_bytes_ex(ctx->base.libctx, (IVs = blocks[0].c), 16 * x4, 0) <= 0)
+ return 0;
+
+ mctx = (SHA1_MB_CTX *) (storage + 32 - ((size_t)storage % 32)); /* align */
+
+ frag = (unsigned int)inp_len >> (1 + n4x);
+ last = (unsigned int)inp_len + frag - (frag << (1 + n4x));
+ if (last > frag && ((last + 13 + 9) % 64) < (x4 - 1)) {
+ frag++;
+ last -= x4 - 1;
+ }
+
+ packlen = 5 + 16 + ((frag + 20 + 16) & -16);
+
+ /* populate descriptors with pointers and IVs */
+ hash_d[0].ptr = inp;
+ ciph_d[0].inp = inp;
+ /* 5+16 is place for header and explicit IV */
+ ciph_d[0].out = out + 5 + 16;
+ memcpy(ciph_d[0].out - 16, IVs, 16);
+ memcpy(ciph_d[0].iv, IVs, 16);
+ IVs += 16;
+
+ for (i = 1; i < x4; i++) {
+ ciph_d[i].inp = hash_d[i].ptr = hash_d[i - 1].ptr + frag;
+ ciph_d[i].out = ciph_d[i - 1].out + packlen;
+ memcpy(ciph_d[i].out - 16, IVs, 16);
+ memcpy(ciph_d[i].iv, IVs, 16);
+ IVs += 16;
+ }
+
+# if defined(BSWAP8)
+ memcpy(blocks[0].c, sctx->md.data, 8);
+ seqnum = BSWAP8(blocks[0].q[0]);
+# endif
+ for (i = 0; i < x4; i++) {
+ unsigned int len = (i == (x4 - 1) ? last : frag);
+# if !defined(BSWAP8)
+ unsigned int carry, j;
+# endif
+
+ mctx->A[i] = sctx->md.h0;
+ mctx->B[i] = sctx->md.h1;
+ mctx->C[i] = sctx->md.h2;
+ mctx->D[i] = sctx->md.h3;
+ mctx->E[i] = sctx->md.h4;
+
+ /* fix seqnum */
+# if defined(BSWAP8)
+ blocks[i].q[0] = BSWAP8(seqnum + i);
+# else
+ for (carry = i, j = 8; j--;) {
+ blocks[i].c[j] = ((u8 *)sctx->md.data)[j] + carry;
+ carry = (blocks[i].c[j] - carry) >> (sizeof(carry) * 8 - 1);
+ }
+# endif
+ blocks[i].c[8] = ((u8 *)sctx->md.data)[8];
+ blocks[i].c[9] = ((u8 *)sctx->md.data)[9];
+ blocks[i].c[10] = ((u8 *)sctx->md.data)[10];
+ /* fix length */
+ blocks[i].c[11] = (u8)(len >> 8);
+ blocks[i].c[12] = (u8)(len);
+
+ memcpy(blocks[i].c + 13, hash_d[i].ptr, 64 - 13);
+ hash_d[i].ptr += 64 - 13;
+ hash_d[i].blocks = (len - (64 - 13)) / 64;
+
+ edges[i].ptr = blocks[i].c;
+ edges[i].blocks = 1;
+ }
+
+ /* hash 13-byte headers and first 64-13 bytes of inputs */
+ sha1_multi_block(mctx, edges, n4x);
+ /* hash bulk inputs */
+# define MAXCHUNKSIZE 2048
+# if MAXCHUNKSIZE%64
+# error "MAXCHUNKSIZE is not divisible by 64"
+# elif MAXCHUNKSIZE
+ /*
+ * goal is to minimize pressure on L1 cache by moving in shorter steps,
+ * so that hashed data is still in the cache by the time we encrypt it
+ */
+ minblocks = ((frag <= last ? frag : last) - (64 - 13)) / 64;
+ if (minblocks > MAXCHUNKSIZE / 64) {
+ for (i = 0; i < x4; i++) {
+ edges[i].ptr = hash_d[i].ptr;
+ edges[i].blocks = MAXCHUNKSIZE / 64;
+ ciph_d[i].blocks = MAXCHUNKSIZE / 16;
+ }
+ do {
+ sha1_multi_block(mctx, edges, n4x);
+ aesni_multi_cbc_encrypt(ciph_d, &ctx->ks, n4x);
+
+ for (i = 0; i < x4; i++) {
+ edges[i].ptr = hash_d[i].ptr += MAXCHUNKSIZE;
+ hash_d[i].blocks -= MAXCHUNKSIZE / 64;
+ edges[i].blocks = MAXCHUNKSIZE / 64;
+ ciph_d[i].inp += MAXCHUNKSIZE;
+ ciph_d[i].out += MAXCHUNKSIZE;
+ ciph_d[i].blocks = MAXCHUNKSIZE / 16;
+ memcpy(ciph_d[i].iv, ciph_d[i].out - 16, 16);
+ }
+ processed += MAXCHUNKSIZE;
+ minblocks -= MAXCHUNKSIZE / 64;
+ } while (minblocks > MAXCHUNKSIZE / 64);
+ }
+# endif
+# undef MAXCHUNKSIZE
+ sha1_multi_block(mctx, hash_d, n4x);
+
+ memset(blocks, 0, sizeof(blocks));
+ for (i = 0; i < x4; i++) {
+ unsigned int len = (i == (x4 - 1) ? last : frag),
+ off = hash_d[i].blocks * 64;
+ const unsigned char *ptr = hash_d[i].ptr + off;
+
+ off = (len - processed) - (64 - 13) - off; /* remainder actually */
+ memcpy(blocks[i].c, ptr, off);
+ blocks[i].c[off] = 0x80;
+ len += 64 + 13; /* 64 is HMAC header */
+ len *= 8; /* convert to bits */
+ if (off < (64 - 8)) {
+# ifdef BSWAP4
+ blocks[i].d[15] = BSWAP4(len);
+# else
+ PUTU32(blocks[i].c + 60, len);
+# endif
+ edges[i].blocks = 1;
+ } else {
+# ifdef BSWAP4
+ blocks[i].d[31] = BSWAP4(len);
+# else
+ PUTU32(blocks[i].c + 124, len);
+# endif
+ edges[i].blocks = 2;
+ }
+ edges[i].ptr = blocks[i].c;
+ }
+
+ /* hash input tails and finalize */
+ sha1_multi_block(mctx, edges, n4x);
+
+ memset(blocks, 0, sizeof(blocks));
+ for (i = 0; i < x4; i++) {
+# ifdef BSWAP4
+ blocks[i].d[0] = BSWAP4(mctx->A[i]);
+ mctx->A[i] = sctx->tail.h0;
+ blocks[i].d[1] = BSWAP4(mctx->B[i]);
+ mctx->B[i] = sctx->tail.h1;
+ blocks[i].d[2] = BSWAP4(mctx->C[i]);
+ mctx->C[i] = sctx->tail.h2;
+ blocks[i].d[3] = BSWAP4(mctx->D[i]);
+ mctx->D[i] = sctx->tail.h3;
+ blocks[i].d[4] = BSWAP4(mctx->E[i]);
+ mctx->E[i] = sctx->tail.h4;
+ blocks[i].c[20] = 0x80;
+ blocks[i].d[15] = BSWAP4((64 + 20) * 8);
+# else
+ PUTU32(blocks[i].c + 0, mctx->A[i]);
+ mctx->A[i] = sctx->tail.h0;
+ PUTU32(blocks[i].c + 4, mctx->B[i]);
+ mctx->B[i] = sctx->tail.h1;
+ PUTU32(blocks[i].c + 8, mctx->C[i]);
+ mctx->C[i] = sctx->tail.h2;
+ PUTU32(blocks[i].c + 12, mctx->D[i]);
+ mctx->D[i] = sctx->tail.h3;
+ PUTU32(blocks[i].c + 16, mctx->E[i]);
+ mctx->E[i] = sctx->tail.h4;
+ blocks[i].c[20] = 0x80;
+ PUTU32(blocks[i].c + 60, (64 + 20) * 8);
+# endif /* BSWAP */
+ edges[i].ptr = blocks[i].c;
+ edges[i].blocks = 1;
+ }
+
+ /* finalize MACs */
+ sha1_multi_block(mctx, edges, n4x);
+
+ for (i = 0; i < x4; i++) {
+ unsigned int len = (i == (x4 - 1) ? last : frag), pad, j;
+ unsigned char *out0 = out;
+
+ memcpy(ciph_d[i].out, ciph_d[i].inp, len - processed);
+ ciph_d[i].inp = ciph_d[i].out;
+
+ out += 5 + 16 + len;
+
+ /* write MAC */
+ PUTU32(out + 0, mctx->A[i]);
+ PUTU32(out + 4, mctx->B[i]);
+ PUTU32(out + 8, mctx->C[i]);
+ PUTU32(out + 12, mctx->D[i]);
+ PUTU32(out + 16, mctx->E[i]);
+ out += 20;
+ len += 20;
+
+ /* pad */
+ pad = 15 - len % 16;
+ for (j = 0; j <= pad; j++)
+ *(out++) = pad;
+ len += pad + 1;
+
+ ciph_d[i].blocks = (len - processed) / 16;
+ len += 16; /* account for explicit iv */
+
+ /* arrange header */
+ out0[0] = ((u8 *)sctx->md.data)[8];
+ out0[1] = ((u8 *)sctx->md.data)[9];
+ out0[2] = ((u8 *)sctx->md.data)[10];
+ out0[3] = (u8)(len >> 8);
+ out0[4] = (u8)(len);
+
+ ret += len + 5;
+ inp += frag;
+ }
+
+ aesni_multi_cbc_encrypt(ciph_d, &ctx->ks, n4x);
+
+ OPENSSL_cleanse(blocks, sizeof(blocks));
+ OPENSSL_cleanse(mctx, sizeof(*mctx));
+
+ ctx->multiblock_encrypt_len = ret;
+ return ret;
+}
+# endif /* OPENSSL_NO_MULTIBLOCK */
+
+static int aesni_cbc_hmac_sha1_cipher(PROV_CIPHER_CTX *vctx,
+ unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
+ PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
+ unsigned int l;
+ size_t plen = ctx->payload_length;
+ size_t iv = 0; /* explicit IV in TLS 1.1 and later */
+ size_t aes_off = 0, blocks;
+ size_t sha_off = SHA_CBLOCK - sctx->md.num;
+
+ ctx->payload_length = NO_PAYLOAD_LENGTH;
+
+ if (len % AES_BLOCK_SIZE)
+ return 0;
+
+ if (ctx->base.enc) {
+ if (plen == NO_PAYLOAD_LENGTH)
+ plen = len;
+ else if (len !=
+ ((plen + SHA_DIGEST_LENGTH +
+ AES_BLOCK_SIZE) & -AES_BLOCK_SIZE))
+ return 0;
+ else if (ctx->aux.tls_ver >= TLS1_1_VERSION)
+ iv = AES_BLOCK_SIZE;
+
+ if (plen > (sha_off + iv)
+ && (blocks = (plen - (sha_off + iv)) / SHA_CBLOCK)) {
+ sha1_update(&sctx->md, in + iv, sha_off);
+
+ aesni_cbc_sha1_enc(in, out, blocks, &ctx->ks, ctx->base.iv,
+ &sctx->md, in + iv + sha_off);
+ blocks *= SHA_CBLOCK;
+ aes_off += blocks;
+ sha_off += blocks;
+ sctx->md.Nh += blocks >> 29;
+ sctx->md.Nl += blocks <<= 3;
+ if (sctx->md.Nl < (unsigned int)blocks)
+ sctx->md.Nh++;
+ } else {
+ sha_off = 0;
+ }
+ sha_off += iv;
+ sha1_update(&sctx->md, in + sha_off, plen - sha_off);
+
+ if (plen != len) { /* "TLS" mode of operation */
+ if (in != out)
+ memcpy(out + aes_off, in + aes_off, plen - aes_off);
+
+ /* calculate HMAC and append it to payload */
+ SHA1_Final(out + plen, &sctx->md);
+ sctx->md = sctx->tail;
+ sha1_update(&sctx->md, out + plen, SHA_DIGEST_LENGTH);
+ SHA1_Final(out + plen, &sctx->md);
+
+ /* pad the payload|hmac */
+ plen += SHA_DIGEST_LENGTH;
+ for (l = len - plen - 1; plen < len; plen++)
+ out[plen] = l;
+ /* encrypt HMAC|padding at once */
+ aesni_cbc_encrypt(out + aes_off, out + aes_off, len - aes_off,
+ &ctx->ks, ctx->base.iv, 1);
+ } else {
+ aesni_cbc_encrypt(in + aes_off, out + aes_off, len - aes_off,
+ &ctx->ks, ctx->base.iv, 1);
+ }
+ } else {
+ union {
+ unsigned int u[SHA_DIGEST_LENGTH / sizeof(unsigned int)];
+ unsigned char c[32 + SHA_DIGEST_LENGTH];
+ } mac, *pmac;
+
+ /* arrange cache line alignment */
+ pmac = (void *)(((size_t)mac.c + 31) & ((size_t)0 - 32));
+
+ if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */
+ size_t inp_len, mask, j, i;
+ unsigned int res, maxpad, pad, bitlen;
+ int ret = 1;
+ union {
+ unsigned int u[SHA_LBLOCK];
+ unsigned char c[SHA_CBLOCK];
+ } *data = (void *)sctx->md.data;
+
+ if ((ctx->aux.tls_aad[plen - 4] << 8 | ctx->aux.tls_aad[plen - 3])
+ >= TLS1_1_VERSION) {
+ if (len < (AES_BLOCK_SIZE + SHA_DIGEST_LENGTH + 1))
+ return 0;
+
+ /* omit explicit iv */
+ memcpy(ctx->base.iv, in, AES_BLOCK_SIZE);
+
+ in += AES_BLOCK_SIZE;
+ out += AES_BLOCK_SIZE;
+ len -= AES_BLOCK_SIZE;
+ } else if (len < (SHA_DIGEST_LENGTH + 1))
+ return 0;
+
+ /* decrypt HMAC|padding at once */
+ aesni_cbc_encrypt(in, out, len, &ctx->ks, ctx->base.iv, 0);
+
+ /* figure out payload length */
+ pad = out[len - 1];
+ maxpad = len - (SHA_DIGEST_LENGTH + 1);
+ maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8);
+ maxpad &= 255;
+
+ mask = constant_time_ge(maxpad, pad);
+ ret &= mask;
+ /*
+ * If pad is invalid then we will fail the above test but we must
+ * continue anyway because we are in constant time code. However,
+ * we'll use the maxpad value instead of the supplied pad to make
+ * sure we perform well defined pointer arithmetic.
+ */
+ pad = constant_time_select(mask, pad, maxpad);
+
+ inp_len = len - (SHA_DIGEST_LENGTH + pad + 1);
+
+ ctx->aux.tls_aad[plen - 2] = inp_len >> 8;
+ ctx->aux.tls_aad[plen - 1] = inp_len;
+
+ /* calculate HMAC */
+ sctx->md = sctx->head;
+ sha1_update(&sctx->md, ctx->aux.tls_aad, plen);
+
+ /* code containing lucky-13 fix */
+ len -= SHA_DIGEST_LENGTH; /* amend mac */
+ if (len >= (256 + SHA_CBLOCK)) {
+ j = (len - (256 + SHA_CBLOCK)) & (0 - SHA_CBLOCK);
+ j += SHA_CBLOCK - sctx->md.num;
+ sha1_update(&sctx->md, out, j);
+ out += j;
+ len -= j;
+ inp_len -= j;
+ }
+
+ /* but pretend as if we hashed padded payload */
+ bitlen = sctx->md.Nl + (inp_len << 3); /* at most 18 bits */
+# ifdef BSWAP4
+ bitlen = BSWAP4(bitlen);
+# else
+ mac.c[0] = 0;
+ mac.c[1] = (unsigned char)(bitlen >> 16);
+ mac.c[2] = (unsigned char)(bitlen >> 8);
+ mac.c[3] = (unsigned char)bitlen;
+ bitlen = mac.u[0];
+# endif /* BSWAP */
+
+ pmac->u[0] = 0;
+ pmac->u[1] = 0;
+ pmac->u[2] = 0;
+ pmac->u[3] = 0;
+ pmac->u[4] = 0;
+
+ for (res = sctx->md.num, j = 0; j < len; j++) {
+ size_t c = out[j];
+ mask = (j - inp_len) >> (sizeof(j) * 8 - 8);
+ c &= mask;
+ c |= 0x80 & ~mask & ~((inp_len - j) >> (sizeof(j) * 8 - 8));
+ data->c[res++] = (unsigned char)c;
+
+ if (res != SHA_CBLOCK)
+ continue;
+
+ /* j is not incremented yet */
+ mask = 0 - ((inp_len + 7 - j) >> (sizeof(j) * 8 - 1));
+ data->u[SHA_LBLOCK - 1] |= bitlen & mask;
+ sha1_block_data_order(&sctx->md, data, 1);
+ mask &= 0 - ((j - inp_len - 72) >> (sizeof(j) * 8 - 1));
+ pmac->u[0] |= sctx->md.h0 & mask;
+ pmac->u[1] |= sctx->md.h1 & mask;
+ pmac->u[2] |= sctx->md.h2 & mask;
+ pmac->u[3] |= sctx->md.h3 & mask;
+ pmac->u[4] |= sctx->md.h4 & mask;
+ res = 0;
+ }
+
+ for (i = res; i < SHA_CBLOCK; i++, j++)
+ data->c[i] = 0;
+
+ if (res > SHA_CBLOCK - 8) {
+ mask = 0 - ((inp_len + 8 - j) >> (sizeof(j) * 8 - 1));
+ data->u[SHA_LBLOCK - 1] |= bitlen & mask;
+ sha1_block_data_order(&sctx->md, data, 1);
+ mask &= 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1));
+ pmac->u[0] |= sctx->md.h0 & mask;
+ pmac->u[1] |= sctx->md.h1 & mask;
+ pmac->u[2] |= sctx->md.h2 & mask;
+ pmac->u[3] |= sctx->md.h3 & mask;
+ pmac->u[4] |= sctx->md.h4 & mask;
+
+ memset(data, 0, SHA_CBLOCK);
+ j += 64;
+ }
+ data->u[SHA_LBLOCK - 1] = bitlen;
+ sha1_block_data_order(&sctx->md, data, 1);
+ mask = 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1));
+ pmac->u[0] |= sctx->md.h0 & mask;
+ pmac->u[1] |= sctx->md.h1 & mask;
+ pmac->u[2] |= sctx->md.h2 & mask;
+ pmac->u[3] |= sctx->md.h3 & mask;
+ pmac->u[4] |= sctx->md.h4 & mask;
+
+# ifdef BSWAP4
+ pmac->u[0] = BSWAP4(pmac->u[0]);
+ pmac->u[1] = BSWAP4(pmac->u[1]);
+ pmac->u[2] = BSWAP4(pmac->u[2]);
+ pmac->u[3] = BSWAP4(pmac->u[3]);
+ pmac->u[4] = BSWAP4(pmac->u[4]);
+# else
+ for (i = 0; i < 5; i++) {
+ res = pmac->u[i];
+ pmac->c[4 * i + 0] = (unsigned char)(res >> 24);
+ pmac->c[4 * i + 1] = (unsigned char)(res >> 16);
+ pmac->c[4 * i + 2] = (unsigned char)(res >> 8);
+ pmac->c[4 * i + 3] = (unsigned char)res;
+ }
+# endif /* BSWAP4 */
+ len += SHA_DIGEST_LENGTH;
+ sctx->md = sctx->tail;
+ sha1_update(&sctx->md, pmac->c, SHA_DIGEST_LENGTH);
+ SHA1_Final(pmac->c, &sctx->md);
+
+ /* verify HMAC */
+ out += inp_len;
+ len -= inp_len;
+ /* version of code with lucky-13 fix */
+ {
+ unsigned char *p = out + len - 1 - maxpad - SHA_DIGEST_LENGTH;
+ size_t off = out - p;
+ unsigned int c, cmask;
+
+ for (res = 0, i = 0, j = 0; j < maxpad + SHA_DIGEST_LENGTH; j++) {
+ c = p[j];
+ cmask =
+ ((int)(j - off - SHA_DIGEST_LENGTH)) >> (sizeof(int) *
+ 8 - 1);
+ res |= (c ^ pad) & ~cmask; /* ... and padding */
+ cmask &= ((int)(off - 1 - j)) >> (sizeof(int) * 8 - 1);
+ res |= (c ^ pmac->c[i]) & cmask;
+ i += 1 & cmask;
+ }
+
+ res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1));
+ ret &= (int)~res;
+ }
+ return ret;
+ } else {
+ /* decrypt HMAC|padding at once */
+ aesni_cbc_encrypt(in, out, len, &ctx->ks, ctx->base.iv, 0);
+ sha1_update(&sctx->md, out, len);
+ }
+ }
+
+ return 1;
+}
+
+/* EVP_CTRL_AEAD_SET_MAC_KEY */
+static void aesni_cbc_hmac_sha1_set_mac_key(void *vctx,
+ const unsigned char *mac, size_t len)
+{
+ PROV_AES_HMAC_SHA1_CTX *ctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
+ unsigned int i;
+ unsigned char hmac_key[64];
+
+ memset(hmac_key, 0, sizeof(hmac_key));
+
+ if (len > (int)sizeof(hmac_key)) {
+ SHA1_Init(&ctx->head);
+ sha1_update(&ctx->head, mac, len);
+ SHA1_Final(hmac_key, &ctx->head);
+ } else {
+ memcpy(hmac_key, mac, len);
+ }
+
+ for (i = 0; i < sizeof(hmac_key); i++)
+ hmac_key[i] ^= 0x36; /* ipad */
+ SHA1_Init(&ctx->head);
+ sha1_update(&ctx->head, hmac_key, sizeof(hmac_key));
+
+ for (i = 0; i < sizeof(hmac_key); i++)
+ hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */
+ SHA1_Init(&ctx->tail);
+ sha1_update(&ctx->tail, hmac_key, sizeof(hmac_key));
+
+ OPENSSL_cleanse(hmac_key, sizeof(hmac_key));
+}
+
+/* EVP_CTRL_AEAD_TLS1_AAD */
+static int aesni_cbc_hmac_sha1_set_tls1_aad(void *vctx,
+ unsigned char *aad_rec, int aad_len)
+{
+ PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
+ PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
+ unsigned char *p = aad_rec;
+ unsigned int len;
+
+ if (aad_len != EVP_AEAD_TLS1_AAD_LEN)
+ return -1;
+
+ len = p[aad_len - 2] << 8 | p[aad_len - 1];
+
+ if (ctx->base.enc) {
+ ctx->payload_length = len;
+ if ((ctx->aux.tls_ver =
+ p[aad_len - 4] << 8 | p[aad_len - 3]) >= TLS1_1_VERSION) {
+ if (len < AES_BLOCK_SIZE)
+ return 0;
+ len -= AES_BLOCK_SIZE;
+ p[aad_len - 2] = len >> 8;
+ p[aad_len - 1] = len;
+ }
+ sctx->md = sctx->head;
+ sha1_update(&sctx->md, p, aad_len);
+ ctx->tls_aad_pad = (int)(((len + SHA_DIGEST_LENGTH +
+ AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)
+ - len);
+ return 1;
+ } else {
+ memcpy(ctx->aux.tls_aad, aad_rec, aad_len);
+ ctx->payload_length = aad_len;
+ ctx->tls_aad_pad = SHA_DIGEST_LENGTH;
+ return 1;
+ }
+}
+
+# if !defined(OPENSSL_NO_MULTIBLOCK)
+
+/* EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE */
+static int aesni_cbc_hmac_sha1_tls1_multiblock_max_bufsize(void *vctx)
+{
+ PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
+
+ OPENSSL_assert(ctx->multiblock_max_send_fragment != 0);
+ return (int)(5 + 16
+ + (((int)ctx->multiblock_max_send_fragment + 20 + 16) & -16));
+}
+
+/* EVP_CTRL_TLS1_1_MULTIBLOCK_AAD */
+static int aesni_cbc_hmac_sha1_tls1_multiblock_aad(
+ void *vctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param)
+{
+ PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
+ PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
+ unsigned int n4x = 1, x4;
+ unsigned int frag, last, packlen, inp_len;
+
+ inp_len = param->inp[11] << 8 | param->inp[12];
+ ctx->multiblock_interleave = param->interleave;
+
+ if (ctx->base.enc) {
+ if ((param->inp[9] << 8 | param->inp[10]) < TLS1_1_VERSION)
+ return -1;
+
+ if (inp_len) {
+ if (inp_len < 4096)
+ return 0; /* too short */
+
+ if (inp_len >= 8192 && OPENSSL_ia32cap_P[2] & (1 << 5))
+ n4x = 2; /* AVX2 */
+ } else if ((n4x = param->interleave / 4) && n4x <= 2)
+ inp_len = param->len;
+ else
+ return -1;
+
+ sctx->md = sctx->head;
+ sha1_update(&sctx->md, param->inp, 13);
+
+ x4 = 4 * n4x;
+ n4x += 1;
+
+ frag = inp_len >> n4x;
+ last = inp_len + frag - (frag << n4x);
+ if (last > frag && ((last + 13 + 9) % 64 < (x4 - 1))) {
+ frag++;
+ last -= x4 - 1;
+ }
+
+ packlen = 5 + 16 + ((frag + 20 + 16) & -16);
+ packlen = (packlen << n4x) - packlen;
+ packlen += 5 + 16 + ((last + 20 + 16) & -16);
+
+ param->interleave = x4;
+ /* The returned values used by get need to be stored */
+ ctx->multiblock_interleave = x4;
+ ctx->multiblock_aad_packlen = packlen;
+ return 1;
+ }
+ return -1; /* not yet */
+}
+
+/* EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT */
+static int aesni_cbc_hmac_sha1_tls1_multiblock_encrypt(
+ void *ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param)
+{
+ return (int)tls1_multi_block_encrypt(ctx, param->out,
+ param->inp, param->len,
+ param->interleave / 4);
+}
+
+# endif /* OPENSSL_NO_MULTIBLOCK */
+
+static const PROV_CIPHER_HW_AES_HMAC_SHA cipher_hw_aes_hmac_sha1 = {
+ {
+ aesni_cbc_hmac_sha1_init_key,
+ aesni_cbc_hmac_sha1_cipher
+ },
+ aesni_cbc_hmac_sha1_set_mac_key,
+ aesni_cbc_hmac_sha1_set_tls1_aad,
+# if !defined(OPENSSL_NO_MULTIBLOCK)
+ aesni_cbc_hmac_sha1_tls1_multiblock_max_bufsize,
+ aesni_cbc_hmac_sha1_tls1_multiblock_aad,
+ aesni_cbc_hmac_sha1_tls1_multiblock_encrypt
+# endif
+};
+
+const PROV_CIPHER_HW_AES_HMAC_SHA *ossl_prov_cipher_hw_aes_cbc_hmac_sha1(void)
+{
+ return &cipher_hw_aes_hmac_sha1;
+}
+
+#endif /* !defined(AES_CBC_HMAC_SHA_CAPABLE) || !defined(AESNI_CAPABLE) */
diff --git a/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha256_hw.c b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha256_hw.c
new file mode 100644
index 000000000000..f5b2f8b6da32
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha256_hw.c
@@ -0,0 +1,846 @@
+/*
+ * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * All low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_aes_cbc_hmac_sha.h"
+
+#if !defined(AES_CBC_HMAC_SHA_CAPABLE) || !defined(AESNI_CAPABLE)
+int ossl_cipher_capable_aes_cbc_hmac_sha256(void)
+{
+ return 0;
+}
+
+const PROV_CIPHER_HW_AES_HMAC_SHA *ossl_prov_cipher_hw_aes_cbc_hmac_sha256(void)
+{
+ return NULL;
+}
+#else
+
+# include <openssl/rand.h>
+# include "crypto/evp.h"
+# include "internal/constant_time.h"
+
+void sha256_block_data_order(void *c, const void *p, size_t len);
+int aesni_cbc_sha256_enc(const void *inp, void *out, size_t blocks,
+ const AES_KEY *key, unsigned char iv[16],
+ SHA256_CTX *ctx, const void *in0);
+
+int ossl_cipher_capable_aes_cbc_hmac_sha256(void)
+{
+ return AESNI_CBC_HMAC_SHA_CAPABLE
+ && aesni_cbc_sha256_enc(NULL, NULL, 0, NULL, NULL, NULL, NULL);
+}
+
+static int aesni_cbc_hmac_sha256_init_key(PROV_CIPHER_CTX *vctx,
+ const unsigned char *key,
+ size_t keylen)
+{
+ int ret;
+ PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
+ PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
+
+ if (ctx->base.enc)
+ ret = aesni_set_encrypt_key(key, ctx->base.keylen * 8, &ctx->ks);
+ else
+ ret = aesni_set_decrypt_key(key, ctx->base.keylen * 8, &ctx->ks);
+
+ SHA256_Init(&sctx->head); /* handy when benchmarking */
+ sctx->tail = sctx->head;
+ sctx->md = sctx->head;
+
+ ctx->payload_length = NO_PAYLOAD_LENGTH;
+
+ vctx->removetlspad = 1;
+ vctx->removetlsfixed = SHA256_DIGEST_LENGTH + AES_BLOCK_SIZE;
+
+ return ret < 0 ? 0 : 1;
+}
+
+void sha256_block_data_order(void *c, const void *p, size_t len);
+
+static void sha256_update(SHA256_CTX *c, const void *data, size_t len)
+{
+ const unsigned char *ptr = data;
+ size_t res;
+
+ if ((res = c->num)) {
+ res = SHA256_CBLOCK - res;
+ if (len < res)
+ res = len;
+ SHA256_Update(c, ptr, res);
+ ptr += res;
+ len -= res;
+ }
+
+ res = len % SHA256_CBLOCK;
+ len -= res;
+
+ if (len) {
+ sha256_block_data_order(c, ptr, len / SHA256_CBLOCK);
+
+ ptr += len;
+ c->Nh += len >> 29;
+ c->Nl += len <<= 3;
+ if (c->Nl < (unsigned int)len)
+ c->Nh++;
+ }
+
+ if (res)
+ SHA256_Update(c, ptr, res);
+}
+
+# if !defined(OPENSSL_NO_MULTIBLOCK)
+
+typedef struct {
+ unsigned int A[8], B[8], C[8], D[8], E[8], F[8], G[8], H[8];
+} SHA256_MB_CTX;
+
+typedef struct {
+ const unsigned char *ptr;
+ int blocks;
+} HASH_DESC;
+
+typedef struct {
+ const unsigned char *inp;
+ unsigned char *out;
+ int blocks;
+ u64 iv[2];
+} CIPH_DESC;
+
+void sha256_multi_block(SHA256_MB_CTX *, const HASH_DESC *, int);
+void aesni_multi_cbc_encrypt(CIPH_DESC *, void *, int);
+
+static size_t tls1_multi_block_encrypt(void *vctx,
+ unsigned char *out,
+ const unsigned char *inp,
+ size_t inp_len, int n4x)
+{ /* n4x is 1 or 2 */
+ PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
+ PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
+ HASH_DESC hash_d[8], edges[8];
+ CIPH_DESC ciph_d[8];
+ unsigned char storage[sizeof(SHA256_MB_CTX) + 32];
+ union {
+ u64 q[16];
+ u32 d[32];
+ u8 c[128];
+ } blocks[8];
+ SHA256_MB_CTX *mctx;
+ unsigned int frag, last, packlen, i;
+ unsigned int x4 = 4 * n4x, minblocks, processed = 0;
+ size_t ret = 0;
+ u8 *IVs;
+# if defined(BSWAP8)
+ u64 seqnum;
+# endif
+
+ /* ask for IVs in bulk */
+ if (RAND_bytes_ex(ctx->base.libctx, (IVs = blocks[0].c), 16 * x4, 0) <= 0)
+ return 0;
+
+ mctx = (SHA256_MB_CTX *) (storage + 32 - ((size_t)storage % 32)); /* align */
+
+ frag = (unsigned int)inp_len >> (1 + n4x);
+ last = (unsigned int)inp_len + frag - (frag << (1 + n4x));
+ if (last > frag && ((last + 13 + 9) % 64) < (x4 - 1)) {
+ frag++;
+ last -= x4 - 1;
+ }
+
+ packlen = 5 + 16 + ((frag + 32 + 16) & -16);
+
+ /* populate descriptors with pointers and IVs */
+ hash_d[0].ptr = inp;
+ ciph_d[0].inp = inp;
+ /* 5+16 is place for header and explicit IV */
+ ciph_d[0].out = out + 5 + 16;
+ memcpy(ciph_d[0].out - 16, IVs, 16);
+ memcpy(ciph_d[0].iv, IVs, 16);
+ IVs += 16;
+
+ for (i = 1; i < x4; i++) {
+ ciph_d[i].inp = hash_d[i].ptr = hash_d[i - 1].ptr + frag;
+ ciph_d[i].out = ciph_d[i - 1].out + packlen;
+ memcpy(ciph_d[i].out - 16, IVs, 16);
+ memcpy(ciph_d[i].iv, IVs, 16);
+ IVs += 16;
+ }
+
+# if defined(BSWAP8)
+ memcpy(blocks[0].c, sctx->md.data, 8);
+ seqnum = BSWAP8(blocks[0].q[0]);
+# endif
+
+ for (i = 0; i < x4; i++) {
+ unsigned int len = (i == (x4 - 1) ? last : frag);
+# if !defined(BSWAP8)
+ unsigned int carry, j;
+# endif
+
+ mctx->A[i] = sctx->md.h[0];
+ mctx->B[i] = sctx->md.h[1];
+ mctx->C[i] = sctx->md.h[2];
+ mctx->D[i] = sctx->md.h[3];
+ mctx->E[i] = sctx->md.h[4];
+ mctx->F[i] = sctx->md.h[5];
+ mctx->G[i] = sctx->md.h[6];
+ mctx->H[i] = sctx->md.h[7];
+
+ /* fix seqnum */
+# if defined(BSWAP8)
+ blocks[i].q[0] = BSWAP8(seqnum + i);
+# else
+ for (carry = i, j = 8; j--;) {
+ blocks[i].c[j] = ((u8 *)sctx->md.data)[j] + carry;
+ carry = (blocks[i].c[j] - carry) >> (sizeof(carry) * 8 - 1);
+ }
+# endif
+ blocks[i].c[8] = ((u8 *)sctx->md.data)[8];
+ blocks[i].c[9] = ((u8 *)sctx->md.data)[9];
+ blocks[i].c[10] = ((u8 *)sctx->md.data)[10];
+ /* fix length */
+ blocks[i].c[11] = (u8)(len >> 8);
+ blocks[i].c[12] = (u8)(len);
+
+ memcpy(blocks[i].c + 13, hash_d[i].ptr, 64 - 13);
+ hash_d[i].ptr += 64 - 13;
+ hash_d[i].blocks = (len - (64 - 13)) / 64;
+
+ edges[i].ptr = blocks[i].c;
+ edges[i].blocks = 1;
+ }
+
+ /* hash 13-byte headers and first 64-13 bytes of inputs */
+ sha256_multi_block(mctx, edges, n4x);
+ /* hash bulk inputs */
+# define MAXCHUNKSIZE 2048
+# if MAXCHUNKSIZE%64
+# error "MAXCHUNKSIZE is not divisible by 64"
+# elif MAXCHUNKSIZE
+ /*
+ * goal is to minimize pressure on L1 cache by moving in shorter steps,
+ * so that hashed data is still in the cache by the time we encrypt it
+ */
+ minblocks = ((frag <= last ? frag : last) - (64 - 13)) / 64;
+ if (minblocks > MAXCHUNKSIZE / 64) {
+ for (i = 0; i < x4; i++) {
+ edges[i].ptr = hash_d[i].ptr;
+ edges[i].blocks = MAXCHUNKSIZE / 64;
+ ciph_d[i].blocks = MAXCHUNKSIZE / 16;
+ }
+ do {
+ sha256_multi_block(mctx, edges, n4x);
+ aesni_multi_cbc_encrypt(ciph_d, &ctx->ks, n4x);
+
+ for (i = 0; i < x4; i++) {
+ edges[i].ptr = hash_d[i].ptr += MAXCHUNKSIZE;
+ hash_d[i].blocks -= MAXCHUNKSIZE / 64;
+ edges[i].blocks = MAXCHUNKSIZE / 64;
+ ciph_d[i].inp += MAXCHUNKSIZE;
+ ciph_d[i].out += MAXCHUNKSIZE;
+ ciph_d[i].blocks = MAXCHUNKSIZE / 16;
+ memcpy(ciph_d[i].iv, ciph_d[i].out - 16, 16);
+ }
+ processed += MAXCHUNKSIZE;
+ minblocks -= MAXCHUNKSIZE / 64;
+ } while (minblocks > MAXCHUNKSIZE / 64);
+ }
+# endif
+# undef MAXCHUNKSIZE
+ sha256_multi_block(mctx, hash_d, n4x);
+
+ memset(blocks, 0, sizeof(blocks));
+ for (i = 0; i < x4; i++) {
+ unsigned int len = (i == (x4 - 1) ? last : frag),
+ off = hash_d[i].blocks * 64;
+ const unsigned char *ptr = hash_d[i].ptr + off;
+
+ off = (len - processed) - (64 - 13) - off; /* remainder actually */
+ memcpy(blocks[i].c, ptr, off);
+ blocks[i].c[off] = 0x80;
+ len += 64 + 13; /* 64 is HMAC header */
+ len *= 8; /* convert to bits */
+ if (off < (64 - 8)) {
+# ifdef BSWAP4
+ blocks[i].d[15] = BSWAP4(len);
+# else
+ PUTU32(blocks[i].c + 60, len);
+# endif
+ edges[i].blocks = 1;
+ } else {
+# ifdef BSWAP4
+ blocks[i].d[31] = BSWAP4(len);
+# else
+ PUTU32(blocks[i].c + 124, len);
+# endif
+ edges[i].blocks = 2;
+ }
+ edges[i].ptr = blocks[i].c;
+ }
+
+ /* hash input tails and finalize */
+ sha256_multi_block(mctx, edges, n4x);
+
+ memset(blocks, 0, sizeof(blocks));
+ for (i = 0; i < x4; i++) {
+# ifdef BSWAP4
+ blocks[i].d[0] = BSWAP4(mctx->A[i]);
+ mctx->A[i] = sctx->tail.h[0];
+ blocks[i].d[1] = BSWAP4(mctx->B[i]);
+ mctx->B[i] = sctx->tail.h[1];
+ blocks[i].d[2] = BSWAP4(mctx->C[i]);
+ mctx->C[i] = sctx->tail.h[2];
+ blocks[i].d[3] = BSWAP4(mctx->D[i]);
+ mctx->D[i] = sctx->tail.h[3];
+ blocks[i].d[4] = BSWAP4(mctx->E[i]);
+ mctx->E[i] = sctx->tail.h[4];
+ blocks[i].d[5] = BSWAP4(mctx->F[i]);
+ mctx->F[i] = sctx->tail.h[5];
+ blocks[i].d[6] = BSWAP4(mctx->G[i]);
+ mctx->G[i] = sctx->tail.h[6];
+ blocks[i].d[7] = BSWAP4(mctx->H[i]);
+ mctx->H[i] = sctx->tail.h[7];
+ blocks[i].c[32] = 0x80;
+ blocks[i].d[15] = BSWAP4((64 + 32) * 8);
+# else
+ PUTU32(blocks[i].c + 0, mctx->A[i]);
+ mctx->A[i] = sctx->tail.h[0];
+ PUTU32(blocks[i].c + 4, mctx->B[i]);
+ mctx->B[i] = sctx->tail.h[1];
+ PUTU32(blocks[i].c + 8, mctx->C[i]);
+ mctx->C[i] = sctx->tail.h[2];
+ PUTU32(blocks[i].c + 12, mctx->D[i]);
+ mctx->D[i] = sctx->tail.h[3];
+ PUTU32(blocks[i].c + 16, mctx->E[i]);
+ mctx->E[i] = sctx->tail.h[4];
+ PUTU32(blocks[i].c + 20, mctx->F[i]);
+ mctx->F[i] = sctx->tail.h[5];
+ PUTU32(blocks[i].c + 24, mctx->G[i]);
+ mctx->G[i] = sctx->tail.h[6];
+ PUTU32(blocks[i].c + 28, mctx->H[i]);
+ mctx->H[i] = sctx->tail.h[7];
+ blocks[i].c[32] = 0x80;
+ PUTU32(blocks[i].c + 60, (64 + 32) * 8);
+# endif /* BSWAP */
+ edges[i].ptr = blocks[i].c;
+ edges[i].blocks = 1;
+ }
+
+ /* finalize MACs */
+ sha256_multi_block(mctx, edges, n4x);
+
+ for (i = 0; i < x4; i++) {
+ unsigned int len = (i == (x4 - 1) ? last : frag), pad, j;
+ unsigned char *out0 = out;
+
+ memcpy(ciph_d[i].out, ciph_d[i].inp, len - processed);
+ ciph_d[i].inp = ciph_d[i].out;
+
+ out += 5 + 16 + len;
+
+ /* write MAC */
+ PUTU32(out + 0, mctx->A[i]);
+ PUTU32(out + 4, mctx->B[i]);
+ PUTU32(out + 8, mctx->C[i]);
+ PUTU32(out + 12, mctx->D[i]);
+ PUTU32(out + 16, mctx->E[i]);
+ PUTU32(out + 20, mctx->F[i]);
+ PUTU32(out + 24, mctx->G[i]);
+ PUTU32(out + 28, mctx->H[i]);
+ out += 32;
+ len += 32;
+
+ /* pad */
+ pad = 15 - len % 16;
+ for (j = 0; j <= pad; j++)
+ *(out++) = pad;
+ len += pad + 1;
+
+ ciph_d[i].blocks = (len - processed) / 16;
+ len += 16; /* account for explicit iv */
+
+ /* arrange header */
+ out0[0] = ((u8 *)sctx->md.data)[8];
+ out0[1] = ((u8 *)sctx->md.data)[9];
+ out0[2] = ((u8 *)sctx->md.data)[10];
+ out0[3] = (u8)(len >> 8);
+ out0[4] = (u8)(len);
+
+ ret += len + 5;
+ inp += frag;
+ }
+
+ aesni_multi_cbc_encrypt(ciph_d, &ctx->ks, n4x);
+
+ OPENSSL_cleanse(blocks, sizeof(blocks));
+ OPENSSL_cleanse(mctx, sizeof(*mctx));
+
+ ctx->multiblock_encrypt_len = ret;
+ return ret;
+}
+# endif /* !OPENSSL_NO_MULTIBLOCK */
+
+static int aesni_cbc_hmac_sha256_cipher(PROV_CIPHER_CTX *vctx,
+ unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
+ PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
+ unsigned int l;
+ size_t plen = ctx->payload_length;
+ size_t iv = 0; /* explicit IV in TLS 1.1 and * later */
+ size_t aes_off = 0, blocks;
+ size_t sha_off = SHA256_CBLOCK - sctx->md.num;
+
+ ctx->payload_length = NO_PAYLOAD_LENGTH;
+
+ if (len % AES_BLOCK_SIZE)
+ return 0;
+
+ if (ctx->base.enc) {
+ if (plen == NO_PAYLOAD_LENGTH)
+ plen = len;
+ else if (len !=
+ ((plen + SHA256_DIGEST_LENGTH +
+ AES_BLOCK_SIZE) & -AES_BLOCK_SIZE))
+ return 0;
+ else if (ctx->aux.tls_ver >= TLS1_1_VERSION)
+ iv = AES_BLOCK_SIZE;
+
+ /*
+ * Assembly stitch handles AVX-capable processors, but its
+ * performance is not optimal on AMD Jaguar, ~40% worse, for
+ * unknown reasons. Incidentally processor in question supports
+ * AVX, but not AMD-specific XOP extension, which can be used
+ * to identify it and avoid stitch invocation. So that after we
+ * establish that current CPU supports AVX, we even see if it's
+ * either even XOP-capable Bulldozer-based or GenuineIntel one.
+ * But SHAEXT-capable go ahead...
+ */
+ if (((OPENSSL_ia32cap_P[2] & (1 << 29)) || /* SHAEXT? */
+ ((OPENSSL_ia32cap_P[1] & (1 << (60 - 32))) && /* AVX? */
+ ((OPENSSL_ia32cap_P[1] & (1 << (43 - 32))) /* XOP? */
+ | (OPENSSL_ia32cap_P[0] & (1 << 30))))) && /* "Intel CPU"? */
+ plen > (sha_off + iv) &&
+ (blocks = (plen - (sha_off + iv)) / SHA256_CBLOCK)) {
+ sha256_update(&sctx->md, in + iv, sha_off);
+
+ (void)aesni_cbc_sha256_enc(in, out, blocks, &ctx->ks,
+ ctx->base.iv,
+ &sctx->md, in + iv + sha_off);
+ blocks *= SHA256_CBLOCK;
+ aes_off += blocks;
+ sha_off += blocks;
+ sctx->md.Nh += blocks >> 29;
+ sctx->md.Nl += blocks <<= 3;
+ if (sctx->md.Nl < (unsigned int)blocks)
+ sctx->md.Nh++;
+ } else {
+ sha_off = 0;
+ }
+ sha_off += iv;
+ sha256_update(&sctx->md, in + sha_off, plen - sha_off);
+
+ if (plen != len) { /* "TLS" mode of operation */
+ if (in != out)
+ memcpy(out + aes_off, in + aes_off, plen - aes_off);
+
+ /* calculate HMAC and append it to payload */
+ SHA256_Final(out + plen, &sctx->md);
+ sctx->md = sctx->tail;
+ sha256_update(&sctx->md, out + plen, SHA256_DIGEST_LENGTH);
+ SHA256_Final(out + plen, &sctx->md);
+
+ /* pad the payload|hmac */
+ plen += SHA256_DIGEST_LENGTH;
+ for (l = len - plen - 1; plen < len; plen++)
+ out[plen] = l;
+ /* encrypt HMAC|padding at once */
+ aesni_cbc_encrypt(out + aes_off, out + aes_off, len - aes_off,
+ &ctx->ks, ctx->base.iv, 1);
+ } else {
+ aesni_cbc_encrypt(in + aes_off, out + aes_off, len - aes_off,
+ &ctx->ks, ctx->base.iv, 1);
+ }
+ } else {
+ union {
+ unsigned int u[SHA256_DIGEST_LENGTH / sizeof(unsigned int)];
+ unsigned char c[64 + SHA256_DIGEST_LENGTH];
+ } mac, *pmac;
+
+ /* arrange cache line alignment */
+ pmac = (void *)(((size_t)mac.c + 63) & ((size_t)0 - 64));
+
+ /* decrypt HMAC|padding at once */
+ aesni_cbc_encrypt(in, out, len, &ctx->ks,
+ ctx->base.iv, 0);
+
+ if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */
+ size_t inp_len, mask, j, i;
+ unsigned int res, maxpad, pad, bitlen;
+ int ret = 1;
+ union {
+ unsigned int u[SHA_LBLOCK];
+ unsigned char c[SHA256_CBLOCK];
+ } *data = (void *)sctx->md.data;
+
+ if ((ctx->aux.tls_aad[plen - 4] << 8 | ctx->aux.tls_aad[plen - 3])
+ >= TLS1_1_VERSION)
+ iv = AES_BLOCK_SIZE;
+
+ if (len < (iv + SHA256_DIGEST_LENGTH + 1))
+ return 0;
+
+ /* omit explicit iv */
+ out += iv;
+ len -= iv;
+
+ /* figure out payload length */
+ pad = out[len - 1];
+ maxpad = len - (SHA256_DIGEST_LENGTH + 1);
+ maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8);
+ maxpad &= 255;
+
+ mask = constant_time_ge(maxpad, pad);
+ ret &= mask;
+ /*
+ * If pad is invalid then we will fail the above test but we must
+ * continue anyway because we are in constant time code. However,
+ * we'll use the maxpad value instead of the supplied pad to make
+ * sure we perform well defined pointer arithmetic.
+ */
+ pad = constant_time_select(mask, pad, maxpad);
+
+ inp_len = len - (SHA256_DIGEST_LENGTH + pad + 1);
+
+ ctx->aux.tls_aad[plen - 2] = inp_len >> 8;
+ ctx->aux.tls_aad[plen - 1] = inp_len;
+
+ /* calculate HMAC */
+ sctx->md = sctx->head;
+ sha256_update(&sctx->md, ctx->aux.tls_aad, plen);
+
+ /* code with lucky-13 fix */
+ len -= SHA256_DIGEST_LENGTH; /* amend mac */
+ if (len >= (256 + SHA256_CBLOCK)) {
+ j = (len - (256 + SHA256_CBLOCK)) & (0 - SHA256_CBLOCK);
+ j += SHA256_CBLOCK - sctx->md.num;
+ sha256_update(&sctx->md, out, j);
+ out += j;
+ len -= j;
+ inp_len -= j;
+ }
+
+ /* but pretend as if we hashed padded payload */
+ bitlen = sctx->md.Nl + (inp_len << 3); /* at most 18 bits */
+# ifdef BSWAP4
+ bitlen = BSWAP4(bitlen);
+# else
+ mac.c[0] = 0;
+ mac.c[1] = (unsigned char)(bitlen >> 16);
+ mac.c[2] = (unsigned char)(bitlen >> 8);
+ mac.c[3] = (unsigned char)bitlen;
+ bitlen = mac.u[0];
+# endif /* BSWAP */
+
+ pmac->u[0] = 0;
+ pmac->u[1] = 0;
+ pmac->u[2] = 0;
+ pmac->u[3] = 0;
+ pmac->u[4] = 0;
+ pmac->u[5] = 0;
+ pmac->u[6] = 0;
+ pmac->u[7] = 0;
+
+ for (res = sctx->md.num, j = 0; j < len; j++) {
+ size_t c = out[j];
+ mask = (j - inp_len) >> (sizeof(j) * 8 - 8);
+ c &= mask;
+ c |= 0x80 & ~mask & ~((inp_len - j) >> (sizeof(j) * 8 - 8));
+ data->c[res++] = (unsigned char)c;
+
+ if (res != SHA256_CBLOCK)
+ continue;
+
+ /* j is not incremented yet */
+ mask = 0 - ((inp_len + 7 - j) >> (sizeof(j) * 8 - 1));
+ data->u[SHA_LBLOCK - 1] |= bitlen & mask;
+ sha256_block_data_order(&sctx->md, data, 1);
+ mask &= 0 - ((j - inp_len - 72) >> (sizeof(j) * 8 - 1));
+ pmac->u[0] |= sctx->md.h[0] & mask;
+ pmac->u[1] |= sctx->md.h[1] & mask;
+ pmac->u[2] |= sctx->md.h[2] & mask;
+ pmac->u[3] |= sctx->md.h[3] & mask;
+ pmac->u[4] |= sctx->md.h[4] & mask;
+ pmac->u[5] |= sctx->md.h[5] & mask;
+ pmac->u[6] |= sctx->md.h[6] & mask;
+ pmac->u[7] |= sctx->md.h[7] & mask;
+ res = 0;
+ }
+
+ for (i = res; i < SHA256_CBLOCK; i++, j++)
+ data->c[i] = 0;
+
+ if (res > SHA256_CBLOCK - 8) {
+ mask = 0 - ((inp_len + 8 - j) >> (sizeof(j) * 8 - 1));
+ data->u[SHA_LBLOCK - 1] |= bitlen & mask;
+ sha256_block_data_order(&sctx->md, data, 1);
+ mask &= 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1));
+ pmac->u[0] |= sctx->md.h[0] & mask;
+ pmac->u[1] |= sctx->md.h[1] & mask;
+ pmac->u[2] |= sctx->md.h[2] & mask;
+ pmac->u[3] |= sctx->md.h[3] & mask;
+ pmac->u[4] |= sctx->md.h[4] & mask;
+ pmac->u[5] |= sctx->md.h[5] & mask;
+ pmac->u[6] |= sctx->md.h[6] & mask;
+ pmac->u[7] |= sctx->md.h[7] & mask;
+
+ memset(data, 0, SHA256_CBLOCK);
+ j += 64;
+ }
+ data->u[SHA_LBLOCK - 1] = bitlen;
+ sha256_block_data_order(&sctx->md, data, 1);
+ mask = 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1));
+ pmac->u[0] |= sctx->md.h[0] & mask;
+ pmac->u[1] |= sctx->md.h[1] & mask;
+ pmac->u[2] |= sctx->md.h[2] & mask;
+ pmac->u[3] |= sctx->md.h[3] & mask;
+ pmac->u[4] |= sctx->md.h[4] & mask;
+ pmac->u[5] |= sctx->md.h[5] & mask;
+ pmac->u[6] |= sctx->md.h[6] & mask;
+ pmac->u[7] |= sctx->md.h[7] & mask;
+
+# ifdef BSWAP4
+ pmac->u[0] = BSWAP4(pmac->u[0]);
+ pmac->u[1] = BSWAP4(pmac->u[1]);
+ pmac->u[2] = BSWAP4(pmac->u[2]);
+ pmac->u[3] = BSWAP4(pmac->u[3]);
+ pmac->u[4] = BSWAP4(pmac->u[4]);
+ pmac->u[5] = BSWAP4(pmac->u[5]);
+ pmac->u[6] = BSWAP4(pmac->u[6]);
+ pmac->u[7] = BSWAP4(pmac->u[7]);
+# else
+ for (i = 0; i < 8; i++) {
+ res = pmac->u[i];
+ pmac->c[4 * i + 0] = (unsigned char)(res >> 24);
+ pmac->c[4 * i + 1] = (unsigned char)(res >> 16);
+ pmac->c[4 * i + 2] = (unsigned char)(res >> 8);
+ pmac->c[4 * i + 3] = (unsigned char)res;
+ }
+# endif /* BSWAP */
+ len += SHA256_DIGEST_LENGTH;
+ sctx->md = sctx->tail;
+ sha256_update(&sctx->md, pmac->c, SHA256_DIGEST_LENGTH);
+ SHA256_Final(pmac->c, &sctx->md);
+
+ /* verify HMAC */
+ out += inp_len;
+ len -= inp_len;
+ /* code containing lucky-13 fix */
+ {
+ unsigned char *p =
+ out + len - 1 - maxpad - SHA256_DIGEST_LENGTH;
+ size_t off = out - p;
+ unsigned int c, cmask;
+
+ for (res = 0, i = 0, j = 0;
+ j < maxpad + SHA256_DIGEST_LENGTH;
+ j++) {
+ c = p[j];
+ cmask =
+ ((int)(j - off - SHA256_DIGEST_LENGTH)) >>
+ (sizeof(int) * 8 - 1);
+ res |= (c ^ pad) & ~cmask; /* ... and padding */
+ cmask &= ((int)(off - 1 - j)) >> (sizeof(int) * 8 - 1);
+ res |= (c ^ pmac->c[i]) & cmask;
+ i += 1 & cmask;
+ }
+
+ res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1));
+ ret &= (int)~res;
+ }
+ return ret;
+ } else {
+ sha256_update(&sctx->md, out, len);
+ }
+ }
+
+ return 1;
+}
+
+/* EVP_CTRL_AEAD_SET_MAC_KEY */
+static void aesni_cbc_hmac_sha256_set_mac_key(void *vctx,
+ const unsigned char *mackey,
+ size_t len)
+{
+ PROV_AES_HMAC_SHA256_CTX *ctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
+ unsigned int i;
+ unsigned char hmac_key[64];
+
+ memset(hmac_key, 0, sizeof(hmac_key));
+
+ if (len > sizeof(hmac_key)) {
+ SHA256_Init(&ctx->head);
+ sha256_update(&ctx->head, mackey, len);
+ SHA256_Final(hmac_key, &ctx->head);
+ } else {
+ memcpy(hmac_key, mackey, len);
+ }
+
+ for (i = 0; i < sizeof(hmac_key); i++)
+ hmac_key[i] ^= 0x36; /* ipad */
+ SHA256_Init(&ctx->head);
+ sha256_update(&ctx->head, hmac_key, sizeof(hmac_key));
+
+ for (i = 0; i < sizeof(hmac_key); i++)
+ hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */
+ SHA256_Init(&ctx->tail);
+ sha256_update(&ctx->tail, hmac_key, sizeof(hmac_key));
+
+ OPENSSL_cleanse(hmac_key, sizeof(hmac_key));
+}
+
+/* EVP_CTRL_AEAD_TLS1_AAD */
+static int aesni_cbc_hmac_sha256_set_tls1_aad(void *vctx,
+ unsigned char *aad_rec, int aad_len)
+{
+ PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
+ PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
+ unsigned char *p = aad_rec;
+ unsigned int len;
+
+ if (aad_len != EVP_AEAD_TLS1_AAD_LEN)
+ return -1;
+
+ len = p[aad_len - 2] << 8 | p[aad_len - 1];
+
+ if (ctx->base.enc) {
+ ctx->payload_length = len;
+ if ((ctx->aux.tls_ver =
+ p[aad_len - 4] << 8 | p[aad_len - 3]) >= TLS1_1_VERSION) {
+ if (len < AES_BLOCK_SIZE)
+ return 0;
+ len -= AES_BLOCK_SIZE;
+ p[aad_len - 2] = len >> 8;
+ p[aad_len - 1] = len;
+ }
+ sctx->md = sctx->head;
+ sha256_update(&sctx->md, p, aad_len);
+ ctx->tls_aad_pad = (int)(((len + SHA256_DIGEST_LENGTH +
+ AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)
+ - len);
+ return 1;
+ } else {
+ memcpy(ctx->aux.tls_aad, p, aad_len);
+ ctx->payload_length = aad_len;
+ ctx->tls_aad_pad = SHA256_DIGEST_LENGTH;
+ return 1;
+ }
+}
+
+# if !defined(OPENSSL_NO_MULTIBLOCK)
+/* EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE */
+static int aesni_cbc_hmac_sha256_tls1_multiblock_max_bufsize(
+ void *vctx)
+{
+ PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
+
+ OPENSSL_assert(ctx->multiblock_max_send_fragment != 0);
+ return (int)(5 + 16
+ + (((int)ctx->multiblock_max_send_fragment + 32 + 16) & -16));
+}
+
+/* EVP_CTRL_TLS1_1_MULTIBLOCK_AAD */
+static int aesni_cbc_hmac_sha256_tls1_multiblock_aad(
+ void *vctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param)
+{
+ PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
+ PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
+ unsigned int n4x = 1, x4;
+ unsigned int frag, last, packlen, inp_len;
+
+ inp_len = param->inp[11] << 8 | param->inp[12];
+
+ if (ctx->base.enc) {
+ if ((param->inp[9] << 8 | param->inp[10]) < TLS1_1_VERSION)
+ return -1;
+
+ if (inp_len) {
+ if (inp_len < 4096)
+ return 0; /* too short */
+
+ if (inp_len >= 8192 && OPENSSL_ia32cap_P[2] & (1 << 5))
+ n4x = 2; /* AVX2 */
+ } else if ((n4x = param->interleave / 4) && n4x <= 2)
+ inp_len = param->len;
+ else
+ return -1;
+
+ sctx->md = sctx->head;
+ sha256_update(&sctx->md, param->inp, 13);
+
+ x4 = 4 * n4x;
+ n4x += 1;
+
+ frag = inp_len >> n4x;
+ last = inp_len + frag - (frag << n4x);
+ if (last > frag && ((last + 13 + 9) % 64 < (x4 - 1))) {
+ frag++;
+ last -= x4 - 1;
+ }
+
+ packlen = 5 + 16 + ((frag + 32 + 16) & -16);
+ packlen = (packlen << n4x) - packlen;
+ packlen += 5 + 16 + ((last + 32 + 16) & -16);
+
+ param->interleave = x4;
+ /* The returned values used by get need to be stored */
+ ctx->multiblock_interleave = x4;
+ ctx->multiblock_aad_packlen = packlen;
+ return 1;
+ }
+ return -1; /* not yet */
+}
+
+/* EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT */
+static int aesni_cbc_hmac_sha256_tls1_multiblock_encrypt(
+ void *ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param)
+{
+ return (int)tls1_multi_block_encrypt(ctx, param->out,
+ param->inp, param->len,
+ param->interleave / 4);
+}
+# endif
+
+static const PROV_CIPHER_HW_AES_HMAC_SHA cipher_hw_aes_hmac_sha256 = {
+ {
+ aesni_cbc_hmac_sha256_init_key,
+ aesni_cbc_hmac_sha256_cipher
+ },
+ aesni_cbc_hmac_sha256_set_mac_key,
+ aesni_cbc_hmac_sha256_set_tls1_aad,
+# if !defined(OPENSSL_NO_MULTIBLOCK)
+ aesni_cbc_hmac_sha256_tls1_multiblock_max_bufsize,
+ aesni_cbc_hmac_sha256_tls1_multiblock_aad,
+ aesni_cbc_hmac_sha256_tls1_multiblock_encrypt
+# endif
+};
+
+const PROV_CIPHER_HW_AES_HMAC_SHA *ossl_prov_cipher_hw_aes_cbc_hmac_sha256(void)
+{
+ return &cipher_hw_aes_hmac_sha256;
+}
+
+#endif /* !defined(AES_CBC_HMAC_SHA_CAPABLE) || !defined(AESNI_CAPABLE) */
diff --git a/providers/implementations/ciphers/cipher_aes_ccm.c b/providers/implementations/ciphers/cipher_aes_ccm.c
new file mode 100644
index 000000000000..bb4b1e1e6490
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_ccm.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * AES low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
+/* Dispatch functions for AES CCM mode */
+
+#include "cipher_aes_ccm.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+static void *aes_ccm_newctx(void *provctx, size_t keybits)
+{
+ PROV_AES_CCM_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx != NULL)
+ ossl_ccm_initctx(&ctx->base, keybits, ossl_prov_aes_hw_ccm(keybits));
+ return ctx;
+}
+
+static OSSL_FUNC_cipher_freectx_fn aes_ccm_freectx;
+static void aes_ccm_freectx(void *vctx)
+{
+ PROV_AES_CCM_CTX *ctx = (PROV_AES_CCM_CTX *)vctx;
+
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+/* ossl_aes128ccm_functions */
+IMPLEMENT_aead_cipher(aes, ccm, CCM, AEAD_FLAGS, 128, 8, 96);
+/* ossl_aes192ccm_functions */
+IMPLEMENT_aead_cipher(aes, ccm, CCM, AEAD_FLAGS, 192, 8, 96);
+/* ossl_aes256ccm_functions */
+IMPLEMENT_aead_cipher(aes, ccm, CCM, AEAD_FLAGS, 256, 8, 96);
diff --git a/providers/implementations/ciphers/cipher_aes_ccm.h b/providers/implementations/ciphers/cipher_aes_ccm.h
new file mode 100644
index 000000000000..fd35080db3dd
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_ccm.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/aes.h>
+#include "prov/ciphercommon.h"
+#include "prov/ciphercommon_ccm.h"
+#include "crypto/aes_platform.h"
+
+typedef struct prov_aes_ccm_ctx_st {
+ PROV_CCM_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ /*-
+ * Padding is chosen so that s390x.kmac.k overlaps with ks.ks and
+ * fc with ks.ks.rounds. Remember that on s390x, an AES_KEY's
+ * rounds field is used to store the function code and that the key
+ * schedule is not stored (if aes hardware support is detected).
+ */
+ struct {
+ unsigned char pad[16];
+ AES_KEY ks;
+ } ks;
+#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
+ struct {
+ S390X_KMAC_PARAMS kmac;
+ unsigned long long blocks;
+ union {
+ unsigned long long g[2];
+ unsigned char b[AES_BLOCK_SIZE];
+ } nonce;
+ union {
+ unsigned long long g[2];
+ unsigned char b[AES_BLOCK_SIZE];
+ } buf;
+ unsigned char dummy_pad[168];
+ unsigned int fc; /* fc has same offset as ks.ks.rounds */
+ } s390x;
+#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
+ } ccm;
+} PROV_AES_CCM_CTX;
+
+const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keylen);
diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw.c b/providers/implementations/ciphers/cipher_aes_ccm_hw.c
new file mode 100644
index 000000000000..263d1902817f
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_ccm_hw.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* AES CCM mode */
+
+/*
+ * This file uses the low level AES functions (which are deprecated for
+ * non-internal use) in order to implement provider AES ciphers.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_aes_ccm.h"
+
+#define AES_HW_CCM_SET_KEY_FN(fn_set_enc_key, fn_blk, fn_ccm_enc, fn_ccm_dec) \
+ fn_set_enc_key(key, keylen * 8, &actx->ccm.ks.ks); \
+ CRYPTO_ccm128_init(&ctx->ccm_ctx, ctx->m, ctx->l, &actx->ccm.ks.ks, \
+ (block128_f)fn_blk); \
+ ctx->str = ctx->enc ? (ccm128_f)fn_ccm_enc : (ccm128_f)fn_ccm_dec; \
+ ctx->key_set = 1;
+
+static int ccm_generic_aes_initkey(PROV_CCM_CTX *ctx, const unsigned char *key,
+ size_t keylen)
+{
+ PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx;
+
+#ifdef HWAES_CAPABLE
+ if (HWAES_CAPABLE) {
+ AES_HW_CCM_SET_KEY_FN(HWAES_set_encrypt_key, HWAES_encrypt, NULL, NULL);
+ } else
+#endif /* HWAES_CAPABLE */
+
+#ifdef VPAES_CAPABLE
+ if (VPAES_CAPABLE) {
+ AES_HW_CCM_SET_KEY_FN(vpaes_set_encrypt_key, vpaes_encrypt, NULL, NULL);
+ } else
+#endif
+ {
+ AES_HW_CCM_SET_KEY_FN(AES_set_encrypt_key, AES_encrypt, NULL, NULL)
+ }
+ return 1;
+}
+
+static const PROV_CCM_HW aes_ccm = {
+ ccm_generic_aes_initkey,
+ ossl_ccm_generic_setiv,
+ ossl_ccm_generic_setaad,
+ ossl_ccm_generic_auth_encrypt,
+ ossl_ccm_generic_auth_decrypt,
+ ossl_ccm_generic_gettag
+};
+
+#if defined(S390X_aes_128_CAPABLE)
+# include "cipher_aes_ccm_hw_s390x.inc"
+#elif defined(AESNI_CAPABLE)
+# include "cipher_aes_ccm_hw_aesni.inc"
+#elif defined(SPARC_AES_CAPABLE)
+# include "cipher_aes_ccm_hw_t4.inc"
+#else
+const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keybits)
+{
+ return &aes_ccm;
+}
+#endif
diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc b/providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc
new file mode 100644
index 000000000000..579e5a3d4f13
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*-
+ * AES-NI support for AES CCM.
+ * This file is included by cipher_aes_ccm_hw.c
+ */
+
+static int ccm_aesni_initkey(PROV_CCM_CTX *ctx, const unsigned char *key,
+ size_t keylen)
+{
+ PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx;
+
+ AES_HW_CCM_SET_KEY_FN(aesni_set_encrypt_key, aesni_encrypt,
+ aesni_ccm64_encrypt_blocks,
+ aesni_ccm64_decrypt_blocks);
+ return 1;
+}
+
+static const PROV_CCM_HW aesni_ccm = {
+ ccm_aesni_initkey,
+ ossl_ccm_generic_setiv,
+ ossl_ccm_generic_setaad,
+ ossl_ccm_generic_auth_encrypt,
+ ossl_ccm_generic_auth_decrypt,
+ ossl_ccm_generic_gettag
+};
+
+const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keybits)
+{
+ return AESNI_CAPABLE ? &aesni_ccm : &aes_ccm;
+}
diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw_s390x.inc b/providers/implementations/ciphers/cipher_aes_ccm_hw_s390x.inc
new file mode 100644
index 000000000000..7253f03a7ef1
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_ccm_hw_s390x.inc
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*-
+ * S390X support for AES CCM.
+ * This file is included by cipher_aes_ccm_hw.c
+ */
+
+#define S390X_CCM_AAD_FLAG 0x40
+
+static int s390x_aes_ccm_initkey(PROV_CCM_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
+
+ sctx->ccm.s390x.fc = S390X_AES_FC(keylen);
+ memcpy(&sctx->ccm.s390x.kmac.k, key, keylen);
+ /* Store encoded m and l. */
+ sctx->ccm.s390x.nonce.b[0] = ((ctx->l - 1) & 0x7)
+ | (((ctx->m - 2) >> 1) & 0x7) << 3;
+ memset(sctx->ccm.s390x.nonce.b + 1, 0, sizeof(sctx->ccm.s390x.nonce.b));
+ sctx->ccm.s390x.blocks = 0;
+ ctx->key_set = 1;
+ return 1;
+}
+
+static int s390x_aes_ccm_setiv(PROV_CCM_CTX *ctx,
+ const unsigned char *nonce, size_t noncelen,
+ size_t mlen)
+{
+ PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
+
+ sctx->ccm.s390x.nonce.b[0] &= ~S390X_CCM_AAD_FLAG;
+ sctx->ccm.s390x.nonce.g[1] = mlen;
+ memcpy(sctx->ccm.s390x.nonce.b + 1, nonce, 15 - ctx->l);
+ return 1;
+}
+
+/*-
+ * Process additional authenticated data. Code is big-endian.
+ */
+static int s390x_aes_ccm_setaad(PROV_CCM_CTX *ctx,
+ const unsigned char *aad, size_t alen)
+{
+ PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
+ unsigned char *ptr;
+ int i, rem;
+
+ if (!alen)
+ return 1;
+
+ sctx->ccm.s390x.nonce.b[0] |= S390X_CCM_AAD_FLAG;
+
+ /* Suppress 'type-punned pointer dereference' warning. */
+ ptr = sctx->ccm.s390x.buf.b;
+
+ if (alen < ((1 << 16) - (1 << 8))) {
+ *(uint16_t *)ptr = alen;
+ i = 2;
+ } else if (sizeof(alen) == 8
+ && alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) {
+ *(uint16_t *)ptr = 0xffff;
+ *(uint64_t *)(ptr + 2) = alen;
+ i = 10;
+ } else {
+ *(uint16_t *)ptr = 0xfffe;
+ *(uint32_t *)(ptr + 2) = alen;
+ i = 6;
+ }
+
+ while (i < 16 && alen) {
+ sctx->ccm.s390x.buf.b[i] = *aad;
+ ++aad;
+ --alen;
+ ++i;
+ }
+ while (i < 16) {
+ sctx->ccm.s390x.buf.b[i] = 0;
+ ++i;
+ }
+
+ sctx->ccm.s390x.kmac.icv.g[0] = 0;
+ sctx->ccm.s390x.kmac.icv.g[1] = 0;
+ s390x_kmac(sctx->ccm.s390x.nonce.b, 32, sctx->ccm.s390x.fc,
+ &sctx->ccm.s390x.kmac);
+ sctx->ccm.s390x.blocks += 2;
+
+ rem = alen & 0xf;
+ alen &= ~(size_t)0xf;
+ if (alen) {
+ s390x_kmac(aad, alen, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac);
+ sctx->ccm.s390x.blocks += alen >> 4;
+ aad += alen;
+ }
+ if (rem) {
+ for (i = 0; i < rem; i++)
+ sctx->ccm.s390x.kmac.icv.b[i] ^= aad[i];
+
+ s390x_km(sctx->ccm.s390x.kmac.icv.b, 16,
+ sctx->ccm.s390x.kmac.icv.b, sctx->ccm.s390x.fc,
+ sctx->ccm.s390x.kmac.k);
+ sctx->ccm.s390x.blocks++;
+ }
+ return 1;
+}
+
+/*-
+ * En/de-crypt plain/cipher-text. Compute tag from plaintext. Returns 1 for
+ * success.
+ */
+static int s390x_aes_ccm_auth_encdec(PROV_CCM_CTX *ctx,
+ const unsigned char *in,
+ unsigned char *out, size_t len, int enc)
+{
+ PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
+ size_t n, rem;
+ unsigned int i, l, num;
+ unsigned char flags;
+
+ flags = sctx->ccm.s390x.nonce.b[0];
+ if (!(flags & S390X_CCM_AAD_FLAG)) {
+ s390x_km(sctx->ccm.s390x.nonce.b, 16, sctx->ccm.s390x.kmac.icv.b,
+ sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k);
+ sctx->ccm.s390x.blocks++;
+ }
+ l = flags & 0x7;
+ sctx->ccm.s390x.nonce.b[0] = l;
+
+ /*-
+ * Reconstruct length from encoded length field
+ * and initialize it with counter value.
+ */
+ n = 0;
+ for (i = 15 - l; i < 15; i++) {
+ n |= sctx->ccm.s390x.nonce.b[i];
+ sctx->ccm.s390x.nonce.b[i] = 0;
+ n <<= 8;
+ }
+ n |= sctx->ccm.s390x.nonce.b[15];
+ sctx->ccm.s390x.nonce.b[15] = 1;
+
+ if (n != len)
+ return 0; /* length mismatch */
+
+ if (enc) {
+ /* Two operations per block plus one for tag encryption */
+ sctx->ccm.s390x.blocks += (((len + 15) >> 4) << 1) + 1;
+ if (sctx->ccm.s390x.blocks > (1ULL << 61))
+ return 0; /* too much data */
+ }
+
+ num = 0;
+ rem = len & 0xf;
+ len &= ~(size_t)0xf;
+
+ if (enc) {
+ /* mac-then-encrypt */
+ if (len)
+ s390x_kmac(in, len, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac);
+ if (rem) {
+ for (i = 0; i < rem; i++)
+ sctx->ccm.s390x.kmac.icv.b[i] ^= in[len + i];
+
+ s390x_km(sctx->ccm.s390x.kmac.icv.b, 16,
+ sctx->ccm.s390x.kmac.icv.b,
+ sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k);
+ }
+
+ CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &sctx->ccm.ks.ks,
+ sctx->ccm.s390x.nonce.b, sctx->ccm.s390x.buf.b,
+ &num, (ctr128_f)AES_ctr32_encrypt);
+ } else {
+ /* decrypt-then-mac */
+ CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &sctx->ccm.ks.ks,
+ sctx->ccm.s390x.nonce.b, sctx->ccm.s390x.buf.b,
+ &num, (ctr128_f)AES_ctr32_encrypt);
+
+ if (len)
+ s390x_kmac(out, len, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac);
+ if (rem) {
+ for (i = 0; i < rem; i++)
+ sctx->ccm.s390x.kmac.icv.b[i] ^= out[len + i];
+
+ s390x_km(sctx->ccm.s390x.kmac.icv.b, 16,
+ sctx->ccm.s390x.kmac.icv.b,
+ sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k);
+ }
+ }
+ /* encrypt tag */
+ for (i = 15 - l; i < 16; i++)
+ sctx->ccm.s390x.nonce.b[i] = 0;
+
+ s390x_km(sctx->ccm.s390x.nonce.b, 16, sctx->ccm.s390x.buf.b,
+ sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k);
+ sctx->ccm.s390x.kmac.icv.g[0] ^= sctx->ccm.s390x.buf.g[0];
+ sctx->ccm.s390x.kmac.icv.g[1] ^= sctx->ccm.s390x.buf.g[1];
+
+ sctx->ccm.s390x.nonce.b[0] = flags; /* restore flags field */
+ return 1;
+}
+
+
+static int s390x_aes_ccm_gettag(PROV_CCM_CTX *ctx,
+ unsigned char *tag, size_t tlen)
+{
+ PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
+
+ if (tlen > ctx->m)
+ return 0;
+ memcpy(tag, sctx->ccm.s390x.kmac.icv.b, tlen);
+ return 1;
+}
+
+static int s390x_aes_ccm_auth_encrypt(PROV_CCM_CTX *ctx,
+ const unsigned char *in,
+ unsigned char *out, size_t len,
+ unsigned char *tag, size_t taglen)
+{
+ int rv;
+
+ rv = s390x_aes_ccm_auth_encdec(ctx, in, out, len, 1);
+ if (rv && tag != NULL)
+ rv = s390x_aes_ccm_gettag(ctx, tag, taglen);
+ return rv;
+}
+
+static int s390x_aes_ccm_auth_decrypt(PROV_CCM_CTX *ctx,
+ const unsigned char *in,
+ unsigned char *out, size_t len,
+ unsigned char *expected_tag,
+ size_t taglen)
+{
+ int rv = 0;
+ PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
+
+ rv = s390x_aes_ccm_auth_encdec(ctx, in, out, len, 0);
+ if (rv) {
+ if (CRYPTO_memcmp(sctx->ccm.s390x.kmac.icv.b, expected_tag, ctx->m) != 0)
+ rv = 0;
+ }
+ if (rv == 0)
+ OPENSSL_cleanse(out, len);
+ return rv;
+}
+
+static const PROV_CCM_HW s390x_aes_ccm = {
+ s390x_aes_ccm_initkey,
+ s390x_aes_ccm_setiv,
+ s390x_aes_ccm_setaad,
+ s390x_aes_ccm_auth_encrypt,
+ s390x_aes_ccm_auth_decrypt,
+ s390x_aes_ccm_gettag
+};
+
+const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keybits)
+{
+ if ((keybits == 128 && S390X_aes_128_ccm_CAPABLE)
+ || (keybits == 192 && S390X_aes_192_ccm_CAPABLE)
+ || (keybits == 256 && S390X_aes_256_ccm_CAPABLE))
+ return &s390x_aes_ccm;
+ return &aes_ccm;
+}
diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw_t4.inc b/providers/implementations/ciphers/cipher_aes_ccm_hw_t4.inc
new file mode 100644
index 000000000000..a676d411b598
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_ccm_hw_t4.inc
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*-
+ * Fujitsu SPARC64 X support for AES CCM.
+ * This file is included by cipher_aes_ccm_hw.c
+ */
+
+static int ccm_t4_aes_initkey(PROV_CCM_CTX *ctx, const unsigned char *key,
+ size_t keylen)
+{
+ PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx;
+
+ AES_HW_CCM_SET_KEY_FN(aes_t4_set_encrypt_key, aes_t4_encrypt, NULL, NULL);
+ return 1;
+}
+
+static const PROV_CCM_HW t4_aes_ccm = {
+ ccm_t4_aes_initkey,
+ ossl_ccm_generic_setiv,
+ ossl_ccm_generic_setaad,
+ ossl_ccm_generic_auth_encrypt,
+ ossl_ccm_generic_auth_decrypt,
+ ossl_ccm_generic_gettag
+};
+
+const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keybits)
+{
+ return SPARC_AES_CAPABLE ? &t4_aes_ccm : &aes_ccm;
+}
diff --git a/providers/implementations/ciphers/cipher_aes_cts.inc b/providers/implementations/ciphers/cipher_aes_cts.inc
new file mode 100644
index 000000000000..1fb5ec3553f9
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_cts.inc
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for AES CBC CTS ciphers */
+
+#include <openssl/proverr.h>
+#include "cipher_cts.h"
+
+#define CTS_FLAGS PROV_CIPHER_FLAG_CTS
+
+static OSSL_FUNC_cipher_encrypt_init_fn aes_cbc_cts_einit;
+static OSSL_FUNC_cipher_decrypt_init_fn aes_cbc_cts_dinit;
+static OSSL_FUNC_cipher_get_ctx_params_fn aes_cbc_cts_get_ctx_params;
+static OSSL_FUNC_cipher_set_ctx_params_fn aes_cbc_cts_set_ctx_params;
+static OSSL_FUNC_cipher_gettable_ctx_params_fn aes_cbc_cts_gettable_ctx_params;
+static OSSL_FUNC_cipher_settable_ctx_params_fn aes_cbc_cts_settable_ctx_params;
+
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(aes_cbc_cts)
+OSSL_PARAM_utf8_string(OSSL_CIPHER_PARAM_CTS_MODE, NULL, 0),
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(aes_cbc_cts)
+
+static int aes_cbc_cts_einit(void *ctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ if (!ossl_cipher_generic_einit(ctx, key, keylen, iv, ivlen, NULL))
+ return 0;
+ return aes_cbc_cts_set_ctx_params(ctx, params);
+}
+
+static int aes_cbc_cts_dinit(void *ctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ if (!ossl_cipher_generic_dinit(ctx, key, keylen, iv, ivlen, NULL))
+ return 0;
+ return aes_cbc_cts_set_ctx_params(ctx, params);
+}
+
+static int aes_cbc_cts_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_CTS_MODE);
+ if (p != NULL) {
+ const char *name = ossl_cipher_cbc_cts_mode_id2name(ctx->cts_mode);
+
+ if (name == NULL || !OSSL_PARAM_set_utf8_string(p, name)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+ return ossl_cipher_generic_get_ctx_params(vctx, params);
+}
+
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(aes_cbc_cts)
+OSSL_PARAM_utf8_string(OSSL_CIPHER_PARAM_CTS_MODE, NULL, 0),
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(aes_cbc_cts)
+
+static int aes_cbc_cts_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ const OSSL_PARAM *p;
+ int id;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_CTS_MODE);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ goto err;
+ id = ossl_cipher_cbc_cts_mode_name2id(p->data);
+ if (id < 0)
+ goto err;
+
+ ctx->cts_mode = (unsigned int)id;
+ }
+ return ossl_cipher_generic_set_ctx_params(vctx, params);
+err:
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+}
+
+/* ossl_aes256cbc_cts_functions */
+IMPLEMENT_cts_cipher(aes, AES, cbc, CBC, CTS_FLAGS, 256, 128, 128, block)
+/* ossl_aes192cbc_cts_functions */
+IMPLEMENT_cts_cipher(aes, AES, cbc, CBC, CTS_FLAGS, 192, 128, 128, block)
+/* ossl_aes128cbc_cts_functions */
+IMPLEMENT_cts_cipher(aes, AES, cbc, CBC, CTS_FLAGS, 128, 128, 128, block)
diff --git a/providers/implementations/ciphers/cipher_aes_gcm.c b/providers/implementations/ciphers/cipher_aes_gcm.c
new file mode 100644
index 000000000000..0081ca6cd776
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_gcm.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * AES low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
+/* Dispatch functions for AES GCM mode */
+
+#include "cipher_aes_gcm.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+static void *aes_gcm_newctx(void *provctx, size_t keybits)
+{
+ PROV_AES_GCM_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx != NULL)
+ ossl_gcm_initctx(provctx, &ctx->base, keybits,
+ ossl_prov_aes_hw_gcm(keybits));
+ return ctx;
+}
+
+static OSSL_FUNC_cipher_freectx_fn aes_gcm_freectx;
+static void aes_gcm_freectx(void *vctx)
+{
+ PROV_AES_GCM_CTX *ctx = (PROV_AES_GCM_CTX *)vctx;
+
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+/* ossl_aes128gcm_functions */
+IMPLEMENT_aead_cipher(aes, gcm, GCM, AEAD_FLAGS, 128, 8, 96);
+/* ossl_aes192gcm_functions */
+IMPLEMENT_aead_cipher(aes, gcm, GCM, AEAD_FLAGS, 192, 8, 96);
+/* ossl_aes256gcm_functions */
+IMPLEMENT_aead_cipher(aes, gcm, GCM, AEAD_FLAGS, 256, 8, 96);
diff --git a/providers/implementations/ciphers/cipher_aes_gcm.h b/providers/implementations/ciphers/cipher_aes_gcm.h
new file mode 100644
index 000000000000..5e88ccca7b4d
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_gcm.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/aes.h>
+#include "prov/ciphercommon.h"
+#include "prov/ciphercommon_gcm.h"
+#include "crypto/aes_platform.h"
+
+typedef struct prov_aes_gcm_ctx_st {
+ PROV_GCM_CTX base; /* must be first entry in struct */
+ union {
+ OSSL_UNION_ALIGN;
+ AES_KEY ks;
+ } ks; /* AES key schedule to use */
+
+ /* Platform specific data */
+ union {
+ int dummy;
+#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
+ struct {
+ union {
+ OSSL_UNION_ALIGN;
+ S390X_KMA_PARAMS kma;
+ } param;
+ unsigned int fc;
+ unsigned int hsflag; /* hash subkey set flag */
+ unsigned char ares[16];
+ unsigned char mres[16];
+ unsigned char kres[16];
+ int areslen;
+ int mreslen;
+ int kreslen;
+ int res;
+ } s390x;
+#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
+ } plat;
+} PROV_AES_GCM_CTX;
+
+const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw.c b/providers/implementations/ciphers/cipher_aes_gcm_hw.c
new file mode 100644
index 000000000000..44fa9d4d72ea
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_gcm_hw.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for AES GCM mode */
+
+/*
+ * This file uses the low level AES functions (which are deprecated for
+ * non-internal use) in order to implement provider AES ciphers.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_aes_gcm.h"
+
+static int aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
+ size_t keylen)
+{
+ PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
+ AES_KEY *ks = &actx->ks.ks;
+
+# ifdef HWAES_CAPABLE
+ if (HWAES_CAPABLE) {
+# ifdef HWAES_ctr32_encrypt_blocks
+ GCM_HW_SET_KEY_CTR_FN(ks, HWAES_set_encrypt_key, HWAES_encrypt,
+ HWAES_ctr32_encrypt_blocks);
+# else
+ GCM_HW_SET_KEY_CTR_FN(ks, HWAES_set_encrypt_key, HWAES_encrypt, NULL);
+# endif /* HWAES_ctr32_encrypt_blocks */
+ } else
+# endif /* HWAES_CAPABLE */
+
+# ifdef BSAES_CAPABLE
+ if (BSAES_CAPABLE) {
+ GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt,
+ ossl_bsaes_ctr32_encrypt_blocks);
+ } else
+# endif /* BSAES_CAPABLE */
+
+# ifdef VPAES_CAPABLE
+ if (VPAES_CAPABLE) {
+ GCM_HW_SET_KEY_CTR_FN(ks, vpaes_set_encrypt_key, vpaes_encrypt, NULL);
+ } else
+# endif /* VPAES_CAPABLE */
+
+ {
+# ifdef AES_CTR_ASM
+ GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt,
+ AES_ctr32_encrypt);
+# else
+ GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt, NULL);
+# endif /* AES_CTR_ASM */
+ }
+ ctx->key_set = 1;
+ return 1;
+}
+
+static int generic_aes_gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
+ size_t len, unsigned char *out)
+{
+ if (ctx->enc) {
+ if (ctx->ctr != NULL) {
+#if defined(AES_GCM_ASM)
+ size_t bulk = 0;
+
+ if (len >= AES_GCM_ENC_BYTES && AES_GCM_ASM(ctx)) {
+ size_t res = (16 - ctx->gcm.mres) % 16;
+
+ if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, res))
+ return 0;
+
+ bulk = AES_gcm_encrypt(in + res, out + res, len - res,
+ ctx->gcm.key,
+ ctx->gcm.Yi.c, ctx->gcm.Xi.u);
+
+ ctx->gcm.len.u[1] += bulk;
+ bulk += res;
+ }
+ if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
+ len - bulk, ctx->ctr))
+ return 0;
+#else
+ if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
+ return 0;
+#endif /* AES_GCM_ASM */
+ } else {
+ if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len))
+ return 0;
+ }
+ } else {
+ if (ctx->ctr != NULL) {
+#if defined(AES_GCM_ASM)
+ size_t bulk = 0;
+
+ if (len >= AES_GCM_DEC_BYTES && AES_GCM_ASM(ctx)) {
+ size_t res = (16 - ctx->gcm.mres) % 16;
+
+ if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, res))
+ return -1;
+
+ bulk = AES_gcm_decrypt(in + res, out + res, len - res,
+ ctx->gcm.key,
+ ctx->gcm.Yi.c, ctx->gcm.Xi.u);
+
+ ctx->gcm.len.u[1] += bulk;
+ bulk += res;
+ }
+ if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
+ len - bulk, ctx->ctr))
+ return 0;
+#else
+ if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
+ return 0;
+#endif /* AES_GCM_ASM */
+ } else {
+ if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len))
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static const PROV_GCM_HW aes_gcm = {
+ aes_gcm_initkey,
+ ossl_gcm_setiv,
+ ossl_gcm_aad_update,
+ generic_aes_gcm_cipher_update,
+ ossl_gcm_cipher_final,
+ ossl_gcm_one_shot
+};
+
+#if defined(S390X_aes_128_CAPABLE)
+# include "cipher_aes_gcm_hw_s390x.inc"
+#elif defined(AESNI_CAPABLE)
+# include "cipher_aes_gcm_hw_aesni.inc"
+#elif defined(SPARC_AES_CAPABLE)
+# include "cipher_aes_gcm_hw_t4.inc"
+#elif defined(AES_PMULL_CAPABLE) && defined(AES_GCM_ASM)
+# include "cipher_aes_gcm_hw_armv8.inc"
+#else
+const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits)
+{
+ return &aes_gcm;
+}
+#endif
+
diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc
new file mode 100644
index 000000000000..e6aa0479dd87
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*-
+ * AES-NI support for AES GCM.
+ * This file is included by cipher_aes_gcm_hw.c
+ */
+
+static int aesni_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
+ size_t keylen)
+{
+ PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
+ AES_KEY *ks = &actx->ks.ks;
+ GCM_HW_SET_KEY_CTR_FN(ks, aesni_set_encrypt_key, aesni_encrypt,
+ aesni_ctr32_encrypt_blocks);
+ return 1;
+}
+
+static const PROV_GCM_HW aesni_gcm = {
+ aesni_gcm_initkey,
+ ossl_gcm_setiv,
+ ossl_gcm_aad_update,
+ generic_aes_gcm_cipher_update,
+ ossl_gcm_cipher_final,
+ ossl_gcm_one_shot
+};
+
+const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits)
+{
+ return AESNI_CAPABLE ? &aesni_gcm : &aes_gcm;
+}
+
diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_armv8.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_armv8.inc
new file mode 100644
index 000000000000..310f4470d6d4
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_armv8.inc
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Crypto extention support for AES GCM.
+ * This file is included by cipher_aes_gcm_hw.c
+ */
+
+size_t armv8_aes_gcm_encrypt(const unsigned char *in, unsigned char *out, size_t len,
+ const void *key, unsigned char ivec[16], u64 *Xi)
+{
+ size_t align_bytes = 0;
+ align_bytes = len - len % 16;
+
+ AES_KEY *aes_key = (AES_KEY *)key;
+
+ switch(aes_key->rounds) {
+ case 10:
+ aes_gcm_enc_128_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
+ break;
+ case 12:
+ aes_gcm_enc_192_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
+ break;
+ case 14:
+ aes_gcm_enc_256_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
+ break;
+ }
+ return align_bytes;
+}
+
+size_t armv8_aes_gcm_decrypt(const unsigned char *in, unsigned char *out, size_t len,
+ const void *key, unsigned char ivec[16], u64 *Xi)
+{
+ size_t align_bytes = 0;
+ align_bytes = len - len % 16;
+
+ AES_KEY *aes_key = (AES_KEY *)key;
+
+ switch(aes_key->rounds) {
+ case 10:
+ aes_gcm_dec_128_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
+ break;
+ case 12:
+ aes_gcm_dec_192_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
+ break;
+ case 14:
+ aes_gcm_dec_256_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
+ break;
+ }
+ return align_bytes;
+}
+
+static int armv8_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
+ size_t keylen)
+{
+ PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
+ AES_KEY *ks = &actx->ks.ks;
+
+ GCM_HW_SET_KEY_CTR_FN(ks, aes_v8_set_encrypt_key, aes_v8_encrypt,
+ aes_v8_ctr32_encrypt_blocks);
+ return 1;
+}
+
+
+static const PROV_GCM_HW armv8_aes_gcm = {
+ armv8_aes_gcm_initkey,
+ ossl_gcm_setiv,
+ ossl_gcm_aad_update,
+ generic_aes_gcm_cipher_update,
+ ossl_gcm_cipher_final,
+ ossl_gcm_one_shot
+};
+
+const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits)
+{
+ return AES_PMULL_CAPABLE ? &armv8_aes_gcm : &aes_gcm;
+}
diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_s390x.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_s390x.inc
new file mode 100644
index 000000000000..a36c48e3ec49
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_s390x.inc
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*-
+ * IBM S390X support for AES GCM.
+ * This file is included by cipher_aes_gcm_hw.c
+ */
+
+/* iv + padding length for iv lengths != 12 */
+#define S390X_gcm_ivpadlen(i) ((((i) + 15) >> 4 << 4) + 16)
+
+/* Additional flag or'ed to fc for decryption */
+#define S390X_gcm_decrypt_flag(ctx) (((ctx)->enc) ? 0 : S390X_DECRYPT)
+
+#define S390X_gcm_fc(A,C) ((A)->plat.s390x.fc | (A)->plat.s390x.hsflag |\
+ S390X_gcm_decrypt_flag((C)))
+
+static int s390x_aes_gcm_initkey(PROV_GCM_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
+
+ ctx->key_set = 1;
+ memcpy(&actx->plat.s390x.param.kma.k, key, keylen);
+ actx->plat.s390x.fc = S390X_AES_FC(keylen);
+ return 1;
+}
+
+static int s390x_aes_gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv,
+ size_t ivlen)
+{
+ PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
+ S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
+
+ kma->t.g[0] = 0;
+ kma->t.g[1] = 0;
+ kma->tpcl = 0;
+ kma->taadl = 0;
+ actx->plat.s390x.mreslen = 0;
+ actx->plat.s390x.areslen = 0;
+ actx->plat.s390x.kreslen = 0;
+
+ if (ivlen == GCM_IV_DEFAULT_SIZE) {
+ memcpy(&kma->j0, iv, ivlen);
+ kma->j0.w[3] = 1;
+ kma->cv.w = 1;
+ actx->plat.s390x.hsflag = 0;
+ } else {
+ unsigned long long ivbits = ivlen << 3;
+ size_t len = S390X_gcm_ivpadlen(ivlen);
+ unsigned char iv_zero_pad[S390X_gcm_ivpadlen(GCM_IV_MAX_SIZE)];
+ /*
+ * The IV length needs to be zero padded to be a multiple of 16 bytes
+ * followed by 8 bytes of zeros and 8 bytes for the IV length.
+ * The GHASH of this value can then be calculated.
+ */
+ memcpy(iv_zero_pad, iv, ivlen);
+ memset(iv_zero_pad + ivlen, 0, len - ivlen);
+ memcpy(iv_zero_pad + len - sizeof(ivbits), &ivbits, sizeof(ivbits));
+ /*
+ * Calculate the ghash of the iv - the result is stored into the tag
+ * param.
+ */
+ s390x_kma(iv_zero_pad, len, NULL, 0, NULL, actx->plat.s390x.fc, kma);
+ actx->plat.s390x.hsflag = S390X_KMA_HS; /* The hash subkey is set */
+
+ /* Copy the 128 bit GHASH result into J0 and clear the tag */
+ kma->j0.g[0] = kma->t.g[0];
+ kma->j0.g[1] = kma->t.g[1];
+ kma->t.g[0] = 0;
+ kma->t.g[1] = 0;
+ /* Set the 32 bit counter */
+ kma->cv.w = kma->j0.w[3];
+ }
+ return 1;
+}
+
+static int s390x_aes_gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag)
+{
+ PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
+ S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
+ unsigned char out[AES_BLOCK_SIZE];
+ unsigned int fc;
+ int rc;
+
+ kma->taadl <<= 3;
+ kma->tpcl <<= 3;
+ fc = S390X_gcm_fc(actx, ctx) | S390X_KMA_LAAD | S390X_KMA_LPC;
+ s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen,
+ actx->plat.s390x.mres, actx->plat.s390x.mreslen, out,
+ fc, kma);
+
+ /* gctx->mres already returned to the caller */
+ OPENSSL_cleanse(out, actx->plat.s390x.mreslen);
+
+ if (ctx->enc) {
+ ctx->taglen = GCM_TAG_MAX_SIZE;
+ memcpy(tag, kma->t.b, ctx->taglen);
+ rc = 1;
+ } else {
+ rc = (CRYPTO_memcmp(tag, kma->t.b, ctx->taglen) == 0);
+ }
+ return rc;
+}
+
+static int s390x_aes_gcm_one_shot(PROV_GCM_CTX *ctx,
+ unsigned char *aad, size_t aad_len,
+ const unsigned char *in, size_t in_len,
+ unsigned char *out,
+ unsigned char *tag, size_t taglen)
+{
+ PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
+ S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
+ unsigned int fc;
+ int rc;
+
+ kma->taadl = aad_len << 3;
+ kma->tpcl = in_len << 3;
+ fc = S390X_gcm_fc(actx, ctx) | S390X_KMA_LAAD | S390X_KMA_LPC;
+ s390x_kma(aad, aad_len, in, in_len, out, fc, kma);
+
+ if (ctx->enc) {
+ memcpy(tag, kma->t.b, taglen);
+ rc = 1;
+ } else {
+ rc = (CRYPTO_memcmp(tag, kma->t.b, taglen) == 0);
+ }
+ return rc;
+}
+
+/*
+ * Process additional authenticated data. Returns 1 on success. Code is
+ * big-endian.
+ */
+static int s390x_aes_gcm_aad_update(PROV_GCM_CTX *ctx,
+ const unsigned char *aad, size_t len)
+{
+ PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
+ S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
+ unsigned long long alen;
+ unsigned int fc;
+ int n, rem;
+
+ /* If already processed pt/ct then error */
+ if (kma->tpcl != 0)
+ return 0;
+
+ /* update the total aad length */
+ alen = kma->taadl + len;
+ if (alen > (U64(1) << 61) || (sizeof(len) == 8 && alen < len))
+ return 0;
+ kma->taadl = alen;
+
+ /* check if there is any existing aad data from a previous add */
+ n = actx->plat.s390x.areslen;
+ if (n) {
+ /* add additional data to a buffer until it has 16 bytes */
+ while (n && len) {
+ actx->plat.s390x.ares[n] = *aad;
+ ++aad;
+ --len;
+ n = (n + 1) & 0xf;
+ }
+ /* ctx->ares contains a complete block if offset has wrapped around */
+ if (!n) {
+ fc = S390X_gcm_fc(actx, ctx);
+ s390x_kma(actx->plat.s390x.ares, 16, NULL, 0, NULL, fc, kma);
+ actx->plat.s390x.hsflag = S390X_KMA_HS;
+ }
+ actx->plat.s390x.areslen = n;
+ }
+
+ /* If there are leftover bytes (< 128 bits) save them for next time */
+ rem = len & 0xf;
+ /* Add any remaining 16 byte blocks (128 bit each) */
+ len &= ~(size_t)0xf;
+ if (len) {
+ fc = S390X_gcm_fc(actx, ctx);
+ s390x_kma(aad, len, NULL, 0, NULL, fc, kma);
+ actx->plat.s390x.hsflag = S390X_KMA_HS;
+ aad += len;
+ }
+
+ if (rem) {
+ actx->plat.s390x.areslen = rem;
+
+ do {
+ --rem;
+ actx->plat.s390x.ares[rem] = aad[rem];
+ } while (rem);
+ }
+ return 1;
+}
+
+/*-
+ * En/de-crypt plain/cipher-text and authenticate ciphertext. Returns 1 for
+ * success. Code is big-endian.
+ */
+static int s390x_aes_gcm_cipher_update(PROV_GCM_CTX *ctx,
+ const unsigned char *in, size_t len,
+ unsigned char *out)
+{
+ PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
+ S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
+ const unsigned char *inptr;
+ unsigned long long mlen;
+ unsigned int fc;
+ union {
+ unsigned int w[4];
+ unsigned char b[16];
+ } buf;
+ size_t inlen;
+ int n, rem, i;
+
+ mlen = kma->tpcl + len;
+ if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len))
+ return 0;
+ kma->tpcl = mlen;
+
+ fc = S390X_gcm_fc(actx, ctx) | S390X_KMA_LAAD;
+ n = actx->plat.s390x.mreslen;
+ if (n) {
+ inptr = in;
+ inlen = len;
+ while (n && inlen) {
+ actx->plat.s390x.mres[n] = *inptr;
+ n = (n + 1) & 0xf;
+ ++inptr;
+ --inlen;
+ }
+ /* ctx->mres contains a complete block if offset has wrapped around */
+ if (!n) {
+ s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen,
+ actx->plat.s390x.mres, 16, buf.b, fc, kma);
+ actx->plat.s390x.hsflag = S390X_KMA_HS;
+ fc |= S390X_KMA_HS;
+ actx->plat.s390x.areslen = 0;
+
+ /* previous call already encrypted/decrypted its remainder,
+ * see comment below */
+ n = actx->plat.s390x.mreslen;
+ while (n) {
+ *out = buf.b[n];
+ n = (n + 1) & 0xf;
+ ++out;
+ ++in;
+ --len;
+ }
+ actx->plat.s390x.mreslen = 0;
+ }
+ }
+
+ rem = len & 0xf;
+
+ len &= ~(size_t)0xf;
+ if (len) {
+ s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen, in, len, out,
+ fc, kma);
+ in += len;
+ out += len;
+ actx->plat.s390x.hsflag = S390X_KMA_HS;
+ actx->plat.s390x.areslen = 0;
+ }
+
+ /*-
+ * If there is a remainder, it has to be saved such that it can be
+ * processed by kma later. However, we also have to do the for-now
+ * unauthenticated encryption/decryption part here and now...
+ */
+ if (rem) {
+ if (!actx->plat.s390x.mreslen) {
+ buf.w[0] = kma->j0.w[0];
+ buf.w[1] = kma->j0.w[1];
+ buf.w[2] = kma->j0.w[2];
+ buf.w[3] = kma->cv.w + 1;
+ s390x_km(buf.b, 16, actx->plat.s390x.kres,
+ fc & 0x1f, &kma->k);
+ }
+
+ n = actx->plat.s390x.mreslen;
+ for (i = 0; i < rem; i++) {
+ actx->plat.s390x.mres[n + i] = in[i];
+ out[i] = in[i] ^ actx->plat.s390x.kres[n + i];
+ }
+ actx->plat.s390x.mreslen += rem;
+ }
+ return 1;
+}
+
+static const PROV_GCM_HW s390x_aes_gcm = {
+ s390x_aes_gcm_initkey,
+ s390x_aes_gcm_setiv,
+ s390x_aes_gcm_aad_update,
+ s390x_aes_gcm_cipher_update,
+ s390x_aes_gcm_cipher_final,
+ s390x_aes_gcm_one_shot
+};
+
+const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits)
+{
+ if ((keybits == 128 && S390X_aes_128_gcm_CAPABLE)
+ || (keybits == 192 && S390X_aes_192_gcm_CAPABLE)
+ || (keybits == 256 && S390X_aes_256_gcm_CAPABLE))
+ return &s390x_aes_gcm;
+ return &aes_gcm;
+}
diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_t4.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_t4.inc
new file mode 100644
index 000000000000..2b3a6d1d5ea2
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_t4.inc
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*-
+ * Fujitsu SPARC64 X support for AES GCM.
+ * This file is included by cipher_aes_gcm_hw.c
+ */
+
+static int t4_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
+ size_t keylen)
+{
+ ctr128_f ctr;
+ PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
+ AES_KEY *ks = &actx->ks.ks;
+
+
+ switch (keylen) {
+ case 16:
+ ctr = (ctr128_f)aes128_t4_ctr32_encrypt;
+ break;
+ case 24:
+ ctr = (ctr128_f)aes192_t4_ctr32_encrypt;
+ break;
+ case 32:
+ ctr = (ctr128_f)aes256_t4_ctr32_encrypt;
+ break;
+ default:
+ return 0;
+ }
+
+ GCM_HW_SET_KEY_CTR_FN(ks, aes_t4_set_encrypt_key, aes_t4_encrypt, ctr);
+ return 1;
+}
+
+static const PROV_GCM_HW t4_aes_gcm = {
+ t4_aes_gcm_initkey,
+ ossl_gcm_setiv,
+ ossl_gcm_aad_update,
+ generic_aes_gcm_cipher_update,
+ ossl_gcm_cipher_final,
+ ossl_gcm_one_shot
+};
+const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits)
+{
+ return SPARC_AES_CAPABLE ? &t4_aes_gcm : &aes_gcm;
+}
diff --git a/providers/implementations/ciphers/cipher_aes_hw.c b/providers/implementations/ciphers/cipher_aes_hw.c
new file mode 100644
index 000000000000..596cdba8d307
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_hw.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This file uses the low level AES functions (which are deprecated for
+ * non-internal use) in order to implement provider AES ciphers.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/proverr.h>
+#include "cipher_aes.h"
+
+static int cipher_hw_aes_initkey(PROV_CIPHER_CTX *dat,
+ const unsigned char *key, size_t keylen)
+{
+ int ret;
+ PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
+ AES_KEY *ks = &adat->ks.ks;
+
+ dat->ks = ks;
+
+ if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
+ && !dat->enc) {
+#ifdef HWAES_CAPABLE
+ if (HWAES_CAPABLE) {
+ ret = HWAES_set_decrypt_key(key, keylen * 8, ks);
+ dat->block = (block128_f)HWAES_decrypt;
+ dat->stream.cbc = NULL;
+# ifdef HWAES_cbc_encrypt
+ if (dat->mode == EVP_CIPH_CBC_MODE)
+ dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
+# endif
+# ifdef HWAES_ecb_encrypt
+ if (dat->mode == EVP_CIPH_ECB_MODE)
+ dat->stream.ecb = (ecb128_f)HWAES_ecb_encrypt;
+# endif
+ } else
+#endif
+#ifdef BSAES_CAPABLE
+ if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CBC_MODE) {
+ ret = AES_set_decrypt_key(key, keylen * 8, ks);
+ dat->block = (block128_f)AES_decrypt;
+ dat->stream.cbc = (cbc128_f)ossl_bsaes_cbc_encrypt;
+ } else
+#endif
+#ifdef VPAES_CAPABLE
+ if (VPAES_CAPABLE) {
+ ret = vpaes_set_decrypt_key(key, keylen * 8, ks);
+ dat->block = (block128_f)vpaes_decrypt;
+ dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
+ ?(cbc128_f)vpaes_cbc_encrypt : NULL;
+ } else
+#endif
+ {
+ ret = AES_set_decrypt_key(key, keylen * 8, ks);
+ dat->block = (block128_f)AES_decrypt;
+ dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
+ ? (cbc128_f)AES_cbc_encrypt : NULL;
+ }
+ } else
+#ifdef HWAES_CAPABLE
+ if (HWAES_CAPABLE) {
+ ret = HWAES_set_encrypt_key(key, keylen * 8, ks);
+ dat->block = (block128_f)HWAES_encrypt;
+ dat->stream.cbc = NULL;
+# ifdef HWAES_cbc_encrypt
+ if (dat->mode == EVP_CIPH_CBC_MODE)
+ dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
+ else
+# endif
+# ifdef HWAES_ecb_encrypt
+ if (dat->mode == EVP_CIPH_ECB_MODE)
+ dat->stream.ecb = (ecb128_f)HWAES_ecb_encrypt;
+ else
+# endif
+# ifdef HWAES_ctr32_encrypt_blocks
+ if (dat->mode == EVP_CIPH_CTR_MODE)
+ dat->stream.ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks;
+ else
+# endif
+ (void)0; /* terminate potentially open 'else' */
+ } else
+#endif
+#ifdef BSAES_CAPABLE
+ if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CTR_MODE) {
+ ret = AES_set_encrypt_key(key, keylen * 8, ks);
+ dat->block = (block128_f)AES_encrypt;
+ dat->stream.ctr = (ctr128_f)ossl_bsaes_ctr32_encrypt_blocks;
+ } else
+#endif
+#ifdef VPAES_CAPABLE
+ if (VPAES_CAPABLE) {
+ ret = vpaes_set_encrypt_key(key, keylen * 8, ks);
+ dat->block = (block128_f)vpaes_encrypt;
+ dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
+ ? (cbc128_f)vpaes_cbc_encrypt : NULL;
+ } else
+#endif
+ {
+ ret = AES_set_encrypt_key(key, keylen * 8, ks);
+ dat->block = (block128_f)AES_encrypt;
+ dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
+ ? (cbc128_f)AES_cbc_encrypt : NULL;
+#ifdef AES_CTR_ASM
+ if (dat->mode == EVP_CIPH_CTR_MODE)
+ dat->stream.ctr = (ctr128_f)AES_ctr32_encrypt;
+#endif
+ }
+
+ if (ret < 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
+ return 0;
+ }
+
+ return 1;
+}
+
+IMPLEMENT_CIPHER_HW_COPYCTX(cipher_hw_aes_copyctx, PROV_AES_CTX)
+
+#define PROV_CIPHER_HW_aes_mode(mode) \
+static const PROV_CIPHER_HW aes_##mode = { \
+ cipher_hw_aes_initkey, \
+ ossl_cipher_hw_generic_##mode, \
+ cipher_hw_aes_copyctx \
+}; \
+PROV_CIPHER_HW_declare(mode) \
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_##mode(size_t keybits) \
+{ \
+ PROV_CIPHER_HW_select(mode) \
+ return &aes_##mode; \
+}
+
+#if defined(AESNI_CAPABLE)
+# include "cipher_aes_hw_aesni.inc"
+#elif defined(SPARC_AES_CAPABLE)
+# include "cipher_aes_hw_t4.inc"
+#elif defined(S390X_aes_128_CAPABLE)
+# include "cipher_aes_hw_s390x.inc"
+#else
+/* The generic case */
+# define PROV_CIPHER_HW_declare(mode)
+# define PROV_CIPHER_HW_select(mode)
+#endif
+
+PROV_CIPHER_HW_aes_mode(cbc)
+PROV_CIPHER_HW_aes_mode(ecb)
+PROV_CIPHER_HW_aes_mode(ofb128)
+PROV_CIPHER_HW_aes_mode(cfb128)
+PROV_CIPHER_HW_aes_mode(cfb1)
+PROV_CIPHER_HW_aes_mode(cfb8)
+PROV_CIPHER_HW_aes_mode(ctr)
diff --git a/providers/implementations/ciphers/cipher_aes_hw_aesni.inc b/providers/implementations/ciphers/cipher_aes_hw_aesni.inc
new file mode 100644
index 000000000000..33b9046054e9
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_hw_aesni.inc
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*-
+ * AES-NI support for AES modes ecb, cbc, ofb, cfb, ctr.
+ * This file is included by cipher_aes_hw.c
+ */
+
+#define cipher_hw_aesni_ofb128 ossl_cipher_hw_generic_ofb128
+#define cipher_hw_aesni_cfb128 ossl_cipher_hw_generic_cfb128
+#define cipher_hw_aesni_cfb8 ossl_cipher_hw_generic_cfb8
+#define cipher_hw_aesni_cfb1 ossl_cipher_hw_generic_cfb1
+#define cipher_hw_aesni_ctr ossl_cipher_hw_generic_ctr
+
+static int cipher_hw_aesni_initkey(PROV_CIPHER_CTX *dat,
+ const unsigned char *key, size_t keylen)
+{
+ int ret;
+ PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
+ AES_KEY *ks = &adat->ks.ks;
+
+ dat->ks = ks;
+
+ if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
+ && !dat->enc) {
+ ret = aesni_set_decrypt_key(key, keylen * 8, ks);
+ dat->block = (block128_f) aesni_decrypt;
+ dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
+ (cbc128_f) aesni_cbc_encrypt : NULL;
+ } else {
+ ret = aesni_set_encrypt_key(key, keylen * 8, ks);
+ dat->block = (block128_f) aesni_encrypt;
+ if (dat->mode == EVP_CIPH_CBC_MODE)
+ dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt;
+ else if (dat->mode == EVP_CIPH_CTR_MODE)
+ dat->stream.ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
+ else
+ dat->stream.cbc = NULL;
+ }
+
+ if (ret < 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int cipher_hw_aesni_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ const AES_KEY *ks = ctx->ks;
+
+ aesni_cbc_encrypt(in, out, len, ks, ctx->iv, ctx->enc);
+
+ return 1;
+}
+
+static int cipher_hw_aesni_ecb(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ if (len < ctx->blocksize)
+ return 1;
+
+ aesni_ecb_encrypt(in, out, len, ctx->ks, ctx->enc);
+
+ return 1;
+}
+
+#define PROV_CIPHER_HW_declare(mode) \
+static const PROV_CIPHER_HW aesni_##mode = { \
+ cipher_hw_aesni_initkey, \
+ cipher_hw_aesni_##mode, \
+ cipher_hw_aes_copyctx \
+};
+#define PROV_CIPHER_HW_select(mode) \
+if (AESNI_CAPABLE) \
+ return &aesni_##mode;
diff --git a/providers/implementations/ciphers/cipher_aes_hw_s390x.inc b/providers/implementations/ciphers/cipher_aes_hw_s390x.inc
new file mode 100644
index 000000000000..c8282dbd08a9
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_hw_s390x.inc
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * IBM S390X support for AES modes ecb, cbc, ofb, cfb, ctr.
+ * This file is included by cipher_aes_hw.c
+ */
+
+#include "s390x_arch.h"
+
+#include <stdio.h>
+
+#define s390x_aes_cbc_initkey cipher_hw_aes_initkey
+#define s390x_aes_cfb1_initkey cipher_hw_aes_initkey
+#define s390x_aes_ctr_initkey cipher_hw_aes_initkey
+#define s390x_aes_cbc_cipher_hw ossl_cipher_hw_generic_cbc
+#define s390x_aes_cfb1_cipher_hw ossl_cipher_hw_generic_cfb1
+#define s390x_aes_ctr_cipher_hw ossl_cipher_hw_generic_ctr
+
+#define S390X_aes_128_ofb128_CAPABLE S390X_aes_128_ofb_CAPABLE
+#define S390X_aes_192_ofb128_CAPABLE S390X_aes_192_ofb_CAPABLE
+#define S390X_aes_256_ofb128_CAPABLE S390X_aes_256_ofb_CAPABLE
+#define S390X_aes_128_cfb128_CAPABLE S390X_aes_128_cfb_CAPABLE
+#define S390X_aes_192_cfb128_CAPABLE S390X_aes_192_cfb_CAPABLE
+#define S390X_aes_256_cfb128_CAPABLE S390X_aes_256_cfb_CAPABLE
+
+static int s390x_aes_ecb_initkey(PROV_CIPHER_CTX *dat,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
+
+ adat->plat.s390x.fc = S390X_AES_FC(keylen);
+ memcpy(adat->plat.s390x.param.km.k, key, keylen);
+ return 1;
+}
+
+static int s390x_aes_ecb_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
+ unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT;
+
+ s390x_km(in, len, out, adat->plat.s390x.fc | modifier,
+ &adat->plat.s390x.param.km);
+ return 1;
+}
+
+static int s390x_aes_ofb128_initkey(PROV_CIPHER_CTX *dat,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
+
+ memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
+ adat->plat.s390x.fc = S390X_AES_FC(keylen);
+ adat->plat.s390x.res = 0;
+ return 1;
+}
+
+static int s390x_aes_ofb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
+ int n = adat->plat.s390x.res;
+ int rem;
+
+ memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
+ while (n && len) {
+ *out = *in ^ adat->plat.s390x.param.kmo_kmf.cv[n];
+ n = (n + 1) & 0xf;
+ --len;
+ ++in;
+ ++out;
+ }
+
+ rem = len & 0xf;
+
+ len &= ~(size_t)0xf;
+ if (len) {
+ s390x_kmo(in, len, out, adat->plat.s390x.fc,
+ &adat->plat.s390x.param.kmo_kmf);
+
+ out += len;
+ in += len;
+ }
+
+ if (rem) {
+ s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16,
+ adat->plat.s390x.param.kmo_kmf.cv,
+ adat->plat.s390x.fc,
+ adat->plat.s390x.param.kmo_kmf.k);
+
+ while (rem--) {
+ out[n] = in[n] ^ adat->plat.s390x.param.kmo_kmf.cv[n];
+ ++n;
+ }
+ }
+
+ memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
+ adat->plat.s390x.res = n;
+ return 1;
+}
+
+static int s390x_aes_cfb128_initkey(PROV_CIPHER_CTX *dat,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
+
+ adat->plat.s390x.fc = S390X_AES_FC(keylen);
+ adat->plat.s390x.fc |= 16 << 24; /* 16 bytes cipher feedback */
+ adat->plat.s390x.res = 0;
+ memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
+ return 1;
+}
+
+static int s390x_aes_cfb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
+ unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT;
+ int n = adat->plat.s390x.res;
+ int rem;
+ unsigned char tmp;
+
+ memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
+ while (n && len) {
+ tmp = *in;
+ *out = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
+ adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? *out : tmp;
+ n = (n + 1) & 0xf;
+ --len;
+ ++in;
+ ++out;
+ }
+
+ rem = len & 0xf;
+
+ len &= ~(size_t)0xf;
+ if (len) {
+ s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier,
+ &adat->plat.s390x.param.kmo_kmf);
+
+ out += len;
+ in += len;
+ }
+
+ if (rem) {
+ s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16,
+ adat->plat.s390x.param.kmo_kmf.cv,
+ S390X_AES_FC(dat->keylen),
+ adat->plat.s390x.param.kmo_kmf.k);
+
+ while (rem--) {
+ tmp = in[n];
+ out[n] = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
+ adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? out[n] : tmp;
+ ++n;
+ }
+ }
+
+ memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
+ adat->plat.s390x.res = n;
+ return 1;
+}
+
+static int s390x_aes_cfb8_initkey(PROV_CIPHER_CTX *dat,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
+
+ adat->plat.s390x.fc = S390X_AES_FC(keylen);
+ adat->plat.s390x.fc |= 1 << 24; /* 1 byte cipher feedback */
+ memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
+ return 1;
+}
+
+static int s390x_aes_cfb8_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
+ unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT;
+
+ memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
+ s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier,
+ &adat->plat.s390x.param.kmo_kmf);
+ memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
+ return 1;
+}
+
+#define PROV_CIPHER_HW_declare(mode) \
+static const PROV_CIPHER_HW s390x_aes_##mode = { \
+ s390x_aes_##mode##_initkey, \
+ s390x_aes_##mode##_cipher_hw, \
+ cipher_hw_aes_copyctx \
+};
+#define PROV_CIPHER_HW_select(mode) \
+if ((keybits == 128 && S390X_aes_128_##mode##_CAPABLE) \
+ || (keybits == 192 && S390X_aes_192_##mode##_CAPABLE) \
+ || (keybits == 256 && S390X_aes_256_##mode##_CAPABLE)) \
+ return &s390x_aes_##mode;
+
diff --git a/providers/implementations/ciphers/cipher_aes_hw_t4.inc b/providers/implementations/ciphers/cipher_aes_hw_t4.inc
new file mode 100644
index 000000000000..28454fc5089b
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_hw_t4.inc
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*-
+ * Sparc t4 support for AES modes ecb, cbc, ofb, cfb, ctr.
+ * This file is included by cipher_aes_hw.c
+ */
+
+static int cipher_hw_aes_t4_initkey(PROV_CIPHER_CTX *dat,
+ const unsigned char *key, size_t keylen)
+{
+ int ret, bits;
+ PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
+ AES_KEY *ks = &adat->ks.ks;
+
+ dat->ks = (const void *)ks; /* used by cipher_hw_generic_XXX */
+
+ bits = keylen * 8;
+ if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
+ && !dat->enc) {
+ ret = 0;
+ aes_t4_set_decrypt_key(key, bits, ks);
+ dat->block = (block128_f)aes_t4_decrypt;
+ switch (bits) {
+ case 128:
+ dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
+ (cbc128_f)aes128_t4_cbc_decrypt : NULL;
+ break;
+ case 192:
+ dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
+ (cbc128_f)aes192_t4_cbc_decrypt : NULL;
+ break;
+ case 256:
+ dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
+ (cbc128_f)aes256_t4_cbc_decrypt : NULL;
+ break;
+ default:
+ ret = -1;
+ }
+ } else {
+ ret = 0;
+ aes_t4_set_encrypt_key(key, bits, ks);
+ dat->block = (block128_f)aes_t4_encrypt;
+ switch (bits) {
+ case 128:
+ if (dat->mode == EVP_CIPH_CBC_MODE)
+ dat->stream.cbc = (cbc128_f)aes128_t4_cbc_encrypt;
+ else if (dat->mode == EVP_CIPH_CTR_MODE)
+ dat->stream.ctr = (ctr128_f)aes128_t4_ctr32_encrypt;
+ else
+ dat->stream.cbc = NULL;
+ break;
+ case 192:
+ if (dat->mode == EVP_CIPH_CBC_MODE)
+ dat->stream.cbc = (cbc128_f)aes192_t4_cbc_encrypt;
+ else if (dat->mode == EVP_CIPH_CTR_MODE)
+ dat->stream.ctr = (ctr128_f)aes192_t4_ctr32_encrypt;
+ else
+ dat->stream.cbc = NULL;
+ break;
+ case 256:
+ if (dat->mode == EVP_CIPH_CBC_MODE)
+ dat->stream.cbc = (cbc128_f)aes256_t4_cbc_encrypt;
+ else if (dat->mode == EVP_CIPH_CTR_MODE)
+ dat->stream.ctr = (ctr128_f)aes256_t4_ctr32_encrypt;
+ else
+ dat->stream.cbc = NULL;
+ break;
+ default:
+ ret = -1;
+ }
+ }
+
+ if (ret < 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
+ return 0;
+ }
+
+ return 1;
+}
+
+#define PROV_CIPHER_HW_declare(mode) \
+static const PROV_CIPHER_HW aes_t4_##mode = { \
+ cipher_hw_aes_t4_initkey, \
+ ossl_cipher_hw_generic_##mode, \
+ cipher_hw_aes_copyctx \
+};
+#define PROV_CIPHER_HW_select(mode) \
+ if (SPARC_AES_CAPABLE) \
+ return &aes_t4_##mode;
diff --git a/providers/implementations/ciphers/cipher_aes_ocb.c b/providers/implementations/ciphers/cipher_aes_ocb.c
new file mode 100644
index 000000000000..ce377ad57409
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_ocb.c
@@ -0,0 +1,559 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * AES low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/proverr.h>
+#include "cipher_aes_ocb.h"
+#include "prov/providercommon.h"
+#include "prov/ciphercommon_aead.h"
+#include "prov/implementations.h"
+
+#define AES_OCB_FLAGS AEAD_FLAGS
+
+#define OCB_DEFAULT_TAG_LEN 16
+#define OCB_DEFAULT_IV_LEN 12
+#define OCB_MIN_IV_LEN 1
+#define OCB_MAX_IV_LEN 15
+
+PROV_CIPHER_FUNC(int, ocb_cipher, (PROV_AES_OCB_CTX *ctx,
+ const unsigned char *in, unsigned char *out,
+ size_t nextblock));
+/* forward declarations */
+static OSSL_FUNC_cipher_encrypt_init_fn aes_ocb_einit;
+static OSSL_FUNC_cipher_decrypt_init_fn aes_ocb_dinit;
+static OSSL_FUNC_cipher_update_fn aes_ocb_block_update;
+static OSSL_FUNC_cipher_final_fn aes_ocb_block_final;
+static OSSL_FUNC_cipher_cipher_fn aes_ocb_cipher;
+static OSSL_FUNC_cipher_freectx_fn aes_ocb_freectx;
+static OSSL_FUNC_cipher_dupctx_fn aes_ocb_dupctx;
+static OSSL_FUNC_cipher_get_ctx_params_fn aes_ocb_get_ctx_params;
+static OSSL_FUNC_cipher_set_ctx_params_fn aes_ocb_set_ctx_params;
+static OSSL_FUNC_cipher_gettable_ctx_params_fn cipher_ocb_gettable_ctx_params;
+static OSSL_FUNC_cipher_settable_ctx_params_fn cipher_ocb_settable_ctx_params;
+
+/*
+ * The following methods could be moved into PROV_AES_OCB_HW if
+ * multiple hardware implementations are ever needed.
+ */
+static ossl_inline int aes_generic_ocb_setiv(PROV_AES_OCB_CTX *ctx,
+ const unsigned char *iv,
+ size_t ivlen, size_t taglen)
+{
+ return (CRYPTO_ocb128_setiv(&ctx->ocb, iv, ivlen, taglen) == 1);
+}
+
+static ossl_inline int aes_generic_ocb_setaad(PROV_AES_OCB_CTX *ctx,
+ const unsigned char *aad,
+ size_t alen)
+{
+ return CRYPTO_ocb128_aad(&ctx->ocb, aad, alen) == 1;
+}
+
+static ossl_inline int aes_generic_ocb_gettag(PROV_AES_OCB_CTX *ctx,
+ unsigned char *tag, size_t tlen)
+{
+ return CRYPTO_ocb128_tag(&ctx->ocb, tag, tlen) > 0;
+}
+
+static ossl_inline int aes_generic_ocb_final(PROV_AES_OCB_CTX *ctx)
+{
+ return (CRYPTO_ocb128_finish(&ctx->ocb, ctx->tag, ctx->taglen) == 0);
+}
+
+static ossl_inline void aes_generic_ocb_cleanup(PROV_AES_OCB_CTX *ctx)
+{
+ CRYPTO_ocb128_cleanup(&ctx->ocb);
+}
+
+static ossl_inline int aes_generic_ocb_cipher(PROV_AES_OCB_CTX *ctx,
+ const unsigned char *in,
+ unsigned char *out, size_t len)
+{
+ if (ctx->base.enc) {
+ if (!CRYPTO_ocb128_encrypt(&ctx->ocb, in, out, len))
+ return 0;
+ } else {
+ if (!CRYPTO_ocb128_decrypt(&ctx->ocb, in, out, len))
+ return 0;
+ }
+ return 1;
+}
+
+static ossl_inline int aes_generic_ocb_copy_ctx(PROV_AES_OCB_CTX *dst,
+ PROV_AES_OCB_CTX *src)
+{
+ return CRYPTO_ocb128_copy_ctx(&dst->ocb, &src->ocb,
+ &dst->ksenc.ks, &dst->ksdec.ks);
+}
+
+/*-
+ * Provider dispatch functions
+ */
+static int aes_ocb_init(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[], int enc)
+{
+ PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ ctx->aad_buf_len = 0;
+ ctx->data_buf_len = 0;
+ ctx->base.enc = enc;
+
+ if (iv != NULL) {
+ if (ivlen != ctx->base.ivlen) {
+ /* IV len must be 1 to 15 */
+ if (ivlen < OCB_MIN_IV_LEN || ivlen > OCB_MAX_IV_LEN) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ ctx->base.ivlen = ivlen;
+ }
+ if (!ossl_cipher_generic_initiv(&ctx->base, iv, ivlen))
+ return 0;
+ ctx->iv_state = IV_STATE_BUFFERED;
+ }
+ if (key != NULL) {
+ if (keylen != ctx->base.keylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ if (!ctx->base.hw->init(&ctx->base, key, keylen))
+ return 0;
+ }
+ return aes_ocb_set_ctx_params(ctx, params);
+}
+
+static int aes_ocb_einit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return aes_ocb_init(vctx, key, keylen, iv, ivlen, params, 1);
+}
+
+static int aes_ocb_dinit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return aes_ocb_init(vctx, key, keylen, iv, ivlen, params, 0);
+}
+
+/*
+ * Because of the way OCB works, both the AAD and data are buffered in the
+ * same way. Only the last block can be a partial block.
+ */
+static int aes_ocb_block_update_internal(PROV_AES_OCB_CTX *ctx,
+ unsigned char *buf, size_t *bufsz,
+ unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in,
+ size_t inl, OSSL_ocb_cipher_fn ciph)
+{
+ size_t nextblocks;
+ size_t outlint = 0;
+
+ if (*bufsz != 0)
+ nextblocks = ossl_cipher_fillblock(buf, bufsz, AES_BLOCK_SIZE, &in, &inl);
+ else
+ nextblocks = inl & ~(AES_BLOCK_SIZE-1);
+
+ if (*bufsz == AES_BLOCK_SIZE) {
+ if (outsize < AES_BLOCK_SIZE) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+ if (!ciph(ctx, buf, out, AES_BLOCK_SIZE)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+ *bufsz = 0;
+ outlint = AES_BLOCK_SIZE;
+ if (out != NULL)
+ out += AES_BLOCK_SIZE;
+ }
+ if (nextblocks > 0) {
+ outlint += nextblocks;
+ if (outsize < outlint) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+ if (!ciph(ctx, in, out, nextblocks)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+ in += nextblocks;
+ inl -= nextblocks;
+ }
+ if (inl != 0
+ && !ossl_cipher_trailingdata(buf, bufsz, AES_BLOCK_SIZE, &in, &inl)) {
+ /* PROVerr already called */
+ return 0;
+ }
+
+ *outl = outlint;
+ return inl == 0;
+}
+
+/* A wrapper function that has the same signature as cipher */
+static int cipher_updateaad(PROV_AES_OCB_CTX *ctx, const unsigned char *in,
+ unsigned char *out, size_t len)
+{
+ return aes_generic_ocb_setaad(ctx, in, len);
+}
+
+static int update_iv(PROV_AES_OCB_CTX *ctx)
+{
+ if (ctx->iv_state == IV_STATE_FINISHED
+ || ctx->iv_state == IV_STATE_UNINITIALISED)
+ return 0;
+ if (ctx->iv_state == IV_STATE_BUFFERED) {
+ if (!aes_generic_ocb_setiv(ctx, ctx->base.iv, ctx->base.ivlen,
+ ctx->taglen))
+ return 0;
+ ctx->iv_state = IV_STATE_COPIED;
+ }
+ return 1;
+}
+
+static int aes_ocb_block_update(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in,
+ size_t inl)
+{
+ PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
+ unsigned char *buf;
+ size_t *buflen;
+ OSSL_ocb_cipher_fn fn;
+
+ if (!ctx->key_set || !update_iv(ctx))
+ return 0;
+
+ if (inl == 0) {
+ *outl = 0;
+ return 1;
+ }
+
+ /* Are we dealing with AAD or normal data here? */
+ if (out == NULL) {
+ buf = ctx->aad_buf;
+ buflen = &ctx->aad_buf_len;
+ fn = cipher_updateaad;
+ } else {
+ buf = ctx->data_buf;
+ buflen = &ctx->data_buf_len;
+ fn = aes_generic_ocb_cipher;
+ }
+ return aes_ocb_block_update_internal(ctx, buf, buflen, out, outl, outsize,
+ in, inl, fn);
+}
+
+static int aes_ocb_block_final(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ /* If no block_update has run then the iv still needs to be set */
+ if (!ctx->key_set || !update_iv(ctx))
+ return 0;
+
+ /*
+ * Empty the buffer of any partial block that we might have been provided,
+ * both for data and AAD
+ */
+ *outl = 0;
+ if (ctx->data_buf_len > 0) {
+ if (!aes_generic_ocb_cipher(ctx, ctx->data_buf, out, ctx->data_buf_len))
+ return 0;
+ *outl = ctx->data_buf_len;
+ ctx->data_buf_len = 0;
+ }
+ if (ctx->aad_buf_len > 0) {
+ if (!aes_generic_ocb_setaad(ctx, ctx->aad_buf, ctx->aad_buf_len))
+ return 0;
+ ctx->aad_buf_len = 0;
+ }
+ if (ctx->base.enc) {
+ /* If encrypting then just get the tag */
+ if (!aes_generic_ocb_gettag(ctx, ctx->tag, ctx->taglen))
+ return 0;
+ } else {
+ /* If decrypting then verify */
+ if (ctx->taglen == 0)
+ return 0;
+ if (!aes_generic_ocb_final(ctx))
+ return 0;
+ }
+ /* Don't reuse the IV */
+ ctx->iv_state = IV_STATE_FINISHED;
+ return 1;
+}
+
+static void *aes_ocb_newctx(void *provctx, size_t kbits, size_t blkbits,
+ size_t ivbits, unsigned int mode, uint64_t flags)
+{
+ PROV_AES_OCB_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx != NULL) {
+ ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags,
+ ossl_prov_cipher_hw_aes_ocb(kbits), NULL);
+ ctx->taglen = OCB_DEFAULT_TAG_LEN;
+ }
+ return ctx;
+}
+
+static void aes_ocb_freectx(void *vctx)
+{
+ PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
+
+ if (ctx != NULL) {
+ aes_generic_ocb_cleanup(ctx);
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+ }
+}
+
+static void *aes_ocb_dupctx(void *vctx)
+{
+ PROV_AES_OCB_CTX *in = (PROV_AES_OCB_CTX *)vctx;
+ PROV_AES_OCB_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ret = OPENSSL_malloc(sizeof(*ret));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ *ret = *in;
+ if (!aes_generic_ocb_copy_ctx(ret, in)) {
+ OPENSSL_free(ret);
+ ret = NULL;
+ }
+ return ret;
+}
+
+static int aes_ocb_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
+ const OSSL_PARAM *p;
+ size_t sz;
+
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (p->data == NULL) {
+ /* Tag len must be 0 to 16 */
+ if (p->data_size > OCB_MAX_TAG_LEN)
+ return 0;
+ ctx->taglen = p->data_size;
+ } else {
+ if (p->data_size != ctx->taglen || ctx->base.enc)
+ return 0;
+ memcpy(ctx->tag, p->data, p->data_size);
+ }
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &sz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ /* IV len must be 1 to 15 */
+ if (sz < OCB_MIN_IV_LEN || sz > OCB_MAX_IV_LEN)
+ return 0;
+ ctx->base.ivlen = sz;
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL) {
+ size_t keylen;
+
+ if (!OSSL_PARAM_get_size_t(p, &keylen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (ctx->base.keylen != keylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int aes_ocb_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.ivlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.keylen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
+ if (p != NULL) {
+ if (!OSSL_PARAM_set_size_t(p, ctx->taglen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
+ if (p != NULL) {
+ if (ctx->base.ivlen > p->data_size) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ if (!OSSL_PARAM_set_octet_string(p, ctx->base.oiv, ctx->base.ivlen)
+ && !OSSL_PARAM_set_octet_ptr(p, &ctx->base.oiv, ctx->base.ivlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_UPDATED_IV);
+ if (p != NULL) {
+ if (ctx->base.ivlen > p->data_size) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ if (!OSSL_PARAM_set_octet_string(p, ctx->base.iv, ctx->base.ivlen)
+ && !OSSL_PARAM_set_octet_ptr(p, &ctx->base.iv, ctx->base.ivlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (!ctx->base.enc || p->data_size != ctx->taglen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH);
+ return 0;
+ }
+ memcpy(p->data, ctx->tag, ctx->taglen);
+ }
+ return 1;
+}
+
+static const OSSL_PARAM cipher_ocb_known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_UPDATED_IV, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *cipher_ocb_gettable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *p_ctx)
+{
+ return cipher_ocb_known_gettable_ctx_params;
+}
+
+static const OSSL_PARAM cipher_ocb_known_settable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, NULL),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *cipher_ocb_settable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *p_ctx)
+{
+ return cipher_ocb_known_settable_ctx_params;
+}
+
+static int aes_ocb_cipher(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in, size_t inl)
+{
+ PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (outsize < inl) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (!aes_generic_ocb_cipher(ctx, in, out, inl)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+
+ *outl = inl;
+ return 1;
+}
+
+#define IMPLEMENT_cipher(mode, UCMODE, flags, kbits, blkbits, ivbits) \
+static OSSL_FUNC_cipher_get_params_fn aes_##kbits##_##mode##_get_params; \
+static int aes_##kbits##_##mode##_get_params(OSSL_PARAM params[]) \
+{ \
+ return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
+ flags, kbits, blkbits, ivbits); \
+} \
+static OSSL_FUNC_cipher_newctx_fn aes_##kbits##_##mode##_newctx; \
+static void *aes_##kbits##_##mode##_newctx(void *provctx) \
+{ \
+ return aes_##mode##_newctx(provctx, kbits, blkbits, ivbits, \
+ EVP_CIPH_##UCMODE##_MODE, flags); \
+} \
+const OSSL_DISPATCH ossl_##aes##kbits##mode##_functions[] = { \
+ { OSSL_FUNC_CIPHER_NEWCTX, \
+ (void (*)(void))aes_##kbits##_##mode##_newctx }, \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_##mode##_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_##mode##_dinit }, \
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_##mode##_block_update }, \
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_##mode##_block_final }, \
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_ocb_cipher }, \
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_##mode##_freectx }, \
+ { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_##mode##_dupctx }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, \
+ (void (*)(void))aes_##kbits##_##mode##_get_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
+ (void (*)(void))aes_##mode##_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void))aes_##mode##_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void))cipher_ocb_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))cipher_ocb_settable_ctx_params }, \
+ { 0, NULL } \
+}
+
+IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 256, 128, OCB_DEFAULT_IV_LEN * 8);
+IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 192, 128, OCB_DEFAULT_IV_LEN * 8);
+IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 128, 128, OCB_DEFAULT_IV_LEN * 8);
diff --git a/providers/implementations/ciphers/cipher_aes_ocb.h b/providers/implementations/ciphers/cipher_aes_ocb.h
new file mode 100644
index 000000000000..370717b43614
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_ocb.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/aes.h>
+#include "prov/ciphercommon.h"
+#include "crypto/aes_platform.h"
+
+#define OCB_MAX_TAG_LEN AES_BLOCK_SIZE
+#define OCB_MAX_DATA_LEN AES_BLOCK_SIZE
+#define OCB_MAX_AAD_LEN AES_BLOCK_SIZE
+
+typedef struct prov_aes_ocb_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ AES_KEY ks;
+ } ksenc; /* AES key schedule to use for encryption/aad */
+ union {
+ OSSL_UNION_ALIGN;
+ AES_KEY ks;
+ } ksdec; /* AES key schedule to use for decryption */
+ OCB128_CONTEXT ocb;
+ unsigned int iv_state; /* set to one of IV_STATE_XXX */
+ unsigned int key_set : 1;
+ size_t taglen;
+ size_t data_buf_len;
+ size_t aad_buf_len;
+ unsigned char tag[OCB_MAX_TAG_LEN];
+ unsigned char data_buf[OCB_MAX_DATA_LEN]; /* Store partial data blocks */
+ unsigned char aad_buf[OCB_MAX_AAD_LEN]; /* Store partial AAD blocks */
+} PROV_AES_OCB_CTX;
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ocb(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_aes_ocb_hw.c b/providers/implementations/ciphers/cipher_aes_ocb_hw.c
new file mode 100644
index 000000000000..7aa97dc77e39
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_ocb_hw.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This file uses the low level AES functions (which are deprecated for
+ * non-internal use) in order to implement provider AES ciphers.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_aes_ocb.h"
+
+#define OCB_SET_KEY_FN(fn_set_enc_key, fn_set_dec_key, \
+ fn_block_enc, fn_block_dec, \
+ fn_stream_enc, fn_stream_dec) \
+CRYPTO_ocb128_cleanup(&ctx->ocb); \
+fn_set_enc_key(key, keylen * 8, &ctx->ksenc.ks); \
+fn_set_dec_key(key, keylen * 8, &ctx->ksdec.ks); \
+if (!CRYPTO_ocb128_init(&ctx->ocb, &ctx->ksenc.ks, &ctx->ksdec.ks, \
+ (block128_f)fn_block_enc, (block128_f)fn_block_dec, \
+ ctx->base.enc ? (ocb128_f)fn_stream_enc : \
+ (ocb128_f)fn_stream_dec)) \
+ return 0; \
+ctx->key_set = 1
+
+
+static int cipher_hw_aes_ocb_generic_initkey(PROV_CIPHER_CTX *vctx,
+ const unsigned char *key,
+ size_t keylen)
+{
+ PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
+
+/*
+ * We set both the encrypt and decrypt key here because decrypt
+ * needs both. (i.e- AAD uses encrypt).
+ */
+# ifdef HWAES_CAPABLE
+ if (HWAES_CAPABLE) {
+ OCB_SET_KEY_FN(HWAES_set_encrypt_key, HWAES_set_decrypt_key,
+ HWAES_encrypt, HWAES_decrypt,
+ HWAES_ocb_encrypt, HWAES_ocb_decrypt);
+ } else
+# endif
+# ifdef VPAES_CAPABLE
+ if (VPAES_CAPABLE) {
+ OCB_SET_KEY_FN(vpaes_set_encrypt_key, vpaes_set_decrypt_key,
+ vpaes_encrypt, vpaes_decrypt, NULL, NULL);
+ } else
+# endif
+ {
+ OCB_SET_KEY_FN(AES_set_encrypt_key, AES_set_decrypt_key,
+ AES_encrypt, AES_decrypt, NULL, NULL);
+ }
+ return 1;
+}
+
+# if defined(AESNI_CAPABLE)
+
+static int cipher_hw_aes_ocb_aesni_initkey(PROV_CIPHER_CTX *vctx,
+ const unsigned char *key,
+ size_t keylen)
+{
+ PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
+
+ OCB_SET_KEY_FN(aesni_set_encrypt_key, aesni_set_decrypt_key,
+ aesni_encrypt, aesni_decrypt,
+ aesni_ocb_encrypt, aesni_ocb_decrypt);
+ return 1;
+}
+
+# define PROV_CIPHER_HW_declare() \
+static const PROV_CIPHER_HW aesni_ocb = { \
+ cipher_hw_aes_ocb_aesni_initkey, \
+ NULL \
+};
+# define PROV_CIPHER_HW_select() \
+ if (AESNI_CAPABLE) \
+ return &aesni_ocb;
+
+#elif defined(SPARC_AES_CAPABLE)
+
+static int cipher_hw_aes_ocb_t4_initkey(PROV_CIPHER_CTX *vctx,
+ const unsigned char *key,
+ size_t keylen)
+{
+ PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
+
+ OCB_SET_KEY_FN(aes_t4_set_encrypt_key, aes_t4_set_decrypt_key,
+ aes_t4_encrypt, aes_t4_decrypt, NULL, NULL);
+ return 1;
+}
+
+# define PROV_CIPHER_HW_declare() \
+static const PROV_CIPHER_HW aes_t4_ocb = { \
+ cipher_hw_aes_ocb_t4_initkey, \
+ NULL \
+};
+# define PROV_CIPHER_HW_select() \
+ if (SPARC_AES_CAPABLE) \
+ return &aes_t4_ocb;
+#else
+# define PROV_CIPHER_HW_declare()
+# define PROV_CIPHER_HW_select()
+# endif
+
+static const PROV_CIPHER_HW aes_generic_ocb = {
+ cipher_hw_aes_ocb_generic_initkey,
+ NULL
+};
+PROV_CIPHER_HW_declare()
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ocb(size_t keybits)
+{
+ PROV_CIPHER_HW_select()
+ return &aes_generic_ocb;
+}
+
+
diff --git a/providers/implementations/ciphers/cipher_aes_siv.c b/providers/implementations/ciphers/cipher_aes_siv.c
new file mode 100644
index 000000000000..45010b90db2a
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_siv.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for AES SIV mode */
+
+/*
+ * This file uses the low level AES functions (which are deprecated for
+ * non-internal use) in order to implement provider AES ciphers.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/proverr.h>
+#include "cipher_aes_siv.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+#include "prov/ciphercommon_aead.h"
+#include "prov/provider_ctx.h"
+
+#define siv_stream_update siv_cipher
+#define SIV_FLAGS AEAD_FLAGS
+
+static OSSL_FUNC_cipher_set_ctx_params_fn aes_siv_set_ctx_params;
+
+static void *aes_siv_newctx(void *provctx, size_t keybits, unsigned int mode,
+ uint64_t flags)
+{
+ PROV_AES_SIV_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx != NULL) {
+ ctx->taglen = SIV_LEN;
+ ctx->mode = mode;
+ ctx->keylen = keybits / 8;
+ ctx->hw = ossl_prov_cipher_hw_aes_siv(keybits);
+ ctx->libctx = PROV_LIBCTX_OF(provctx);
+ }
+ return ctx;
+}
+
+static void aes_siv_freectx(void *vctx)
+{
+ PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
+
+ if (ctx != NULL) {
+ ctx->hw->cleanup(ctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+ }
+}
+
+static void *siv_dupctx(void *vctx)
+{
+ PROV_AES_SIV_CTX *in = (PROV_AES_SIV_CTX *)vctx;
+ PROV_AES_SIV_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ret = OPENSSL_malloc(sizeof(*ret));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ if (!in->hw->dupctx(in, ret)) {
+ OPENSSL_free(ret);
+ ret = NULL;
+ }
+ return ret;
+}
+
+static int siv_init(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[], int enc)
+{
+ PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ ctx->enc = enc;
+
+ if (key != NULL) {
+ if (keylen != ctx->keylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ if (!ctx->hw->initkey(ctx, key, ctx->keylen))
+ return 0;
+ }
+ return aes_siv_set_ctx_params(ctx, params);
+}
+
+static int siv_einit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return siv_init(vctx, key, keylen, iv, ivlen, params, 1);
+}
+
+static int siv_dinit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return siv_init(vctx, key, keylen, iv, ivlen, params, 0);
+}
+
+static int siv_cipher(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in, size_t inl)
+{
+ PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (inl == 0) {
+ *outl = 0;
+ return 1;
+ }
+
+ if (outsize < inl) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (ctx->hw->cipher(ctx, out, in, inl) <= 0)
+ return 0;
+
+ if (outl != NULL)
+ *outl = inl;
+ return 1;
+}
+
+static int siv_stream_final(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (!ctx->hw->cipher(vctx, out, NULL, 0))
+ return 0;
+
+ if (outl != NULL)
+ *outl = 0;
+ return 1;
+}
+
+static int aes_siv_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
+ SIV128_CONTEXT *sctx = &ctx->siv;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+ if (p != NULL && p->data_type == OSSL_PARAM_OCTET_STRING) {
+ if (!ctx->enc
+ || p->data_size != ctx->taglen
+ || !OSSL_PARAM_set_octet_string(p, &sctx->tag.byte, ctx->taglen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->taglen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ return 1;
+}
+
+static const OSSL_PARAM aes_siv_known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *aes_siv_gettable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *provctx)
+{
+ return aes_siv_known_gettable_ctx_params;
+}
+
+static int aes_siv_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
+ const OSSL_PARAM *p;
+ unsigned int speed = 0;
+
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+ if (p != NULL) {
+ if (ctx->enc)
+ return 1;
+ if (p->data_type != OSSL_PARAM_OCTET_STRING
+ || !ctx->hw->settag(ctx, p->data, p->data_size)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_SPEED);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_uint(p, &speed)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ ctx->hw->setspeed(ctx, (int)speed);
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL) {
+ size_t keylen;
+
+ if (!OSSL_PARAM_get_size_t(p, &keylen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ /* The key length can not be modified */
+ if (keylen != ctx->keylen)
+ return 0;
+ }
+ return 1;
+}
+
+static const OSSL_PARAM aes_siv_known_settable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_uint(OSSL_CIPHER_PARAM_SPEED, NULL),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *aes_siv_settable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *provctx)
+{
+ return aes_siv_known_settable_ctx_params;
+}
+
+#define IMPLEMENT_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits) \
+static OSSL_FUNC_cipher_newctx_fn alg##kbits##lc##_newctx; \
+static OSSL_FUNC_cipher_freectx_fn alg##_##lc##_freectx; \
+static OSSL_FUNC_cipher_dupctx_fn lc##_dupctx; \
+static OSSL_FUNC_cipher_encrypt_init_fn lc##_einit; \
+static OSSL_FUNC_cipher_decrypt_init_fn lc##_dinit; \
+static OSSL_FUNC_cipher_update_fn lc##_stream_update; \
+static OSSL_FUNC_cipher_final_fn lc##_stream_final; \
+static OSSL_FUNC_cipher_cipher_fn lc##_cipher; \
+static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lc##_get_params; \
+static OSSL_FUNC_cipher_get_ctx_params_fn alg##_##lc##_get_ctx_params; \
+static OSSL_FUNC_cipher_gettable_ctx_params_fn \
+ alg##_##lc##_gettable_ctx_params; \
+static OSSL_FUNC_cipher_set_ctx_params_fn alg##_##lc##_set_ctx_params; \
+static OSSL_FUNC_cipher_settable_ctx_params_fn \
+ alg##_##lc##_settable_ctx_params; \
+static int alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[]) \
+{ \
+ return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
+ flags, 2*kbits, blkbits, ivbits); \
+} \
+static void * alg##kbits##lc##_newctx(void *provctx) \
+{ \
+ return alg##_##lc##_newctx(provctx, 2*kbits, EVP_CIPH_##UCMODE##_MODE, \
+ flags); \
+} \
+const OSSL_DISPATCH ossl_##alg##kbits##lc##_functions[] = { \
+ { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))alg##kbits##lc##_newctx }, \
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))alg##_##lc##_freectx }, \
+ { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) lc##_dupctx }, \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void)) lc##_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void)) lc##_dinit }, \
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void)) lc##_stream_update }, \
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void)) lc##_stream_final }, \
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void)) lc##_cipher }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, \
+ (void (*)(void)) alg##_##kbits##_##lc##_get_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
+ (void (*)(void)) alg##_##lc##_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void)) alg##_##lc##_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void)) alg##_##lc##_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void)) alg##_##lc##_settable_ctx_params }, \
+ { 0, NULL } \
+};
+
+IMPLEMENT_cipher(aes, siv, SIV, SIV_FLAGS, 128, 8, 0)
+IMPLEMENT_cipher(aes, siv, SIV, SIV_FLAGS, 192, 8, 0)
+IMPLEMENT_cipher(aes, siv, SIV, SIV_FLAGS, 256, 8, 0)
diff --git a/providers/implementations/ciphers/cipher_aes_siv.h b/providers/implementations/ciphers/cipher_aes_siv.h
new file mode 100644
index 000000000000..4a682b77c440
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_siv.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/ciphercommon.h"
+#include "crypto/aes_platform.h"
+#include "crypto/siv.h"
+
+typedef struct prov_cipher_hw_aes_siv_st {
+ int (*initkey)(void *ctx, const uint8_t *key, size_t keylen);
+ int (*cipher)(void *ctx, unsigned char *out, const unsigned char *in,
+ size_t len);
+ void (*setspeed)(void *ctx, int speed);
+ int (*settag)(void *ctx, const unsigned char *tag, size_t tagl);
+ void (*cleanup)(void *ctx);
+ int (*dupctx)(void *src, void *dst);
+} PROV_CIPHER_HW_AES_SIV;
+
+typedef struct prov_siv_ctx_st {
+ unsigned int mode; /* The mode that we are using */
+ unsigned int enc : 1; /* Set to 1 if we are encrypting or 0 otherwise */
+ size_t keylen; /* The input keylength (twice the alg key length) */
+ size_t taglen; /* the taglen is the same as the sivlen */
+ SIV128_CONTEXT siv;
+ EVP_CIPHER *ctr; /* These are fetched - so we need to free them */
+ EVP_CIPHER *cbc;
+ const PROV_CIPHER_HW_AES_SIV *hw;
+ OSSL_LIB_CTX *libctx;
+} PROV_AES_SIV_CTX;
+
+const PROV_CIPHER_HW_AES_SIV *ossl_prov_cipher_hw_aes_siv(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_aes_siv_hw.c b/providers/implementations/ciphers/cipher_aes_siv_hw.c
new file mode 100644
index 000000000000..1e6b3d56e4bd
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_siv_hw.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This file uses the low level AES functions (which are deprecated for
+ * non-internal use) in order to implement provider AES ciphers.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_aes_siv.h"
+
+static void aes_siv_cleanup(void *vctx);
+
+static int aes_siv_initkey(void *vctx, const unsigned char *key, size_t keylen)
+{
+ PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
+ SIV128_CONTEXT *sctx = &ctx->siv;
+ size_t klen = keylen / 2;
+ OSSL_LIB_CTX *libctx = ctx->libctx;
+ const char *propq = NULL;
+
+ EVP_CIPHER_free(ctx->cbc);
+ EVP_CIPHER_free(ctx->ctr);
+ ctx->cbc = NULL;
+ ctx->ctr = NULL;
+
+ switch (klen) {
+ case 16:
+ ctx->cbc = EVP_CIPHER_fetch(libctx, "AES-128-CBC", propq);
+ ctx->ctr = EVP_CIPHER_fetch(libctx, "AES-128-CTR", propq);
+ break;
+ case 24:
+ ctx->cbc = EVP_CIPHER_fetch(libctx, "AES-192-CBC", propq);
+ ctx->ctr = EVP_CIPHER_fetch(libctx, "AES-192-CTR", propq);
+ break;
+ case 32:
+ ctx->cbc = EVP_CIPHER_fetch(libctx, "AES-256-CBC", propq);
+ ctx->ctr = EVP_CIPHER_fetch(libctx, "AES-256-CTR", propq);
+ break;
+ default:
+ break;
+ }
+ if (ctx->cbc == NULL || ctx->ctr == NULL)
+ return 0;
+ /*
+ * klen is the length of the underlying cipher, not the input key,
+ * which should be twice as long
+ */
+ return ossl_siv128_init(sctx, key, klen, ctx->cbc, ctx->ctr, libctx,
+ propq);
+}
+
+static int aes_siv_dupctx(void *in_vctx, void *out_vctx)
+{
+ PROV_AES_SIV_CTX *in = (PROV_AES_SIV_CTX *)in_vctx;
+ PROV_AES_SIV_CTX *out = (PROV_AES_SIV_CTX *)out_vctx;
+
+ *out = *in;
+ out->siv.cipher_ctx = NULL;
+ out->siv.mac_ctx_init = NULL;
+ out->siv.mac = NULL;
+ if (!ossl_siv128_copy_ctx(&out->siv, &in->siv))
+ return 0;
+ if (out->cbc != NULL)
+ EVP_CIPHER_up_ref(out->cbc);
+ if (out->ctr != NULL)
+ EVP_CIPHER_up_ref(out->ctr);
+ return 1;
+}
+
+static int aes_siv_settag(void *vctx, const unsigned char *tag, size_t tagl)
+{
+ PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
+ SIV128_CONTEXT *sctx = &ctx->siv;
+
+ return ossl_siv128_set_tag(sctx, tag, tagl);
+}
+
+static void aes_siv_setspeed(void *vctx, int speed)
+{
+ PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
+ SIV128_CONTEXT *sctx = &ctx->siv;
+
+ ossl_siv128_speed(sctx, (int)speed);
+}
+
+static void aes_siv_cleanup(void *vctx)
+{
+ PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
+ SIV128_CONTEXT *sctx = &ctx->siv;
+
+ ossl_siv128_cleanup(sctx);
+ EVP_CIPHER_free(ctx->cbc);
+ EVP_CIPHER_free(ctx->ctr);
+}
+
+static int aes_siv_cipher(void *vctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
+ SIV128_CONTEXT *sctx = &ctx->siv;
+
+ /* EncryptFinal or DecryptFinal */
+ if (in == NULL)
+ return ossl_siv128_finish(sctx) == 0;
+
+ /* Deal with associated data */
+ if (out == NULL)
+ return (ossl_siv128_aad(sctx, in, len) == 1);
+
+ if (ctx->enc)
+ return ossl_siv128_encrypt(sctx, in, out, len) > 0;
+
+ return ossl_siv128_decrypt(sctx, in, out, len) > 0;
+}
+
+static const PROV_CIPHER_HW_AES_SIV aes_siv_hw =
+{
+ aes_siv_initkey,
+ aes_siv_cipher,
+ aes_siv_setspeed,
+ aes_siv_settag,
+ aes_siv_cleanup,
+ aes_siv_dupctx,
+};
+
+const PROV_CIPHER_HW_AES_SIV *ossl_prov_cipher_hw_aes_siv(size_t keybits)
+{
+ return &aes_siv_hw;
+}
diff --git a/providers/implementations/ciphers/cipher_aes_wrp.c b/providers/implementations/ciphers/cipher_aes_wrp.c
new file mode 100644
index 000000000000..8bddf475e24d
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_wrp.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This file uses the low level AES functions (which are deprecated for
+ * non-internal use) in order to implement provider AES ciphers.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/proverr.h>
+#include "cipher_aes.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+
+/* AES wrap with padding has IV length of 4, without padding 8 */
+#define AES_WRAP_PAD_IVLEN 4
+#define AES_WRAP_NOPAD_IVLEN 8
+
+#define WRAP_FLAGS (PROV_CIPHER_FLAG_CUSTOM_IV)
+#define WRAP_FLAGS_INV (WRAP_FLAGS | PROV_CIPHER_FLAG_INVERSE_CIPHER)
+
+typedef size_t (*aeswrap_fn)(void *key, const unsigned char *iv,
+ unsigned char *out, const unsigned char *in,
+ size_t inlen, block128_f block);
+
+static OSSL_FUNC_cipher_encrypt_init_fn aes_wrap_einit;
+static OSSL_FUNC_cipher_decrypt_init_fn aes_wrap_dinit;
+static OSSL_FUNC_cipher_update_fn aes_wrap_cipher;
+static OSSL_FUNC_cipher_final_fn aes_wrap_final;
+static OSSL_FUNC_cipher_freectx_fn aes_wrap_freectx;
+static OSSL_FUNC_cipher_set_ctx_params_fn aes_wrap_set_ctx_params;
+
+typedef struct prov_aes_wrap_ctx_st {
+ PROV_CIPHER_CTX base;
+ union {
+ OSSL_UNION_ALIGN;
+ AES_KEY ks;
+ } ks;
+ aeswrap_fn wrapfn;
+
+} PROV_AES_WRAP_CTX;
+
+
+static void *aes_wrap_newctx(size_t kbits, size_t blkbits,
+ size_t ivbits, unsigned int mode, uint64_t flags)
+{
+ PROV_AES_WRAP_CTX *wctx;
+ PROV_CIPHER_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ wctx = OPENSSL_zalloc(sizeof(*wctx));
+ ctx = (PROV_CIPHER_CTX *)wctx;
+ if (ctx != NULL) {
+ ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags,
+ NULL, NULL);
+ ctx->pad = (ctx->ivlen == AES_WRAP_PAD_IVLEN);
+ }
+ return wctx;
+}
+
+static void aes_wrap_freectx(void *vctx)
+{
+ PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
+
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(wctx, sizeof(*wctx));
+}
+
+static int aes_wrap_init(void *vctx, const unsigned char *key,
+ size_t keylen, const unsigned char *iv,
+ size_t ivlen, const OSSL_PARAM params[], int enc)
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ ctx->enc = enc;
+ if (ctx->pad)
+ wctx->wrapfn = enc ? CRYPTO_128_wrap_pad : CRYPTO_128_unwrap_pad;
+ else
+ wctx->wrapfn = enc ? CRYPTO_128_wrap : CRYPTO_128_unwrap;
+
+ if (iv != NULL) {
+ if (!ossl_cipher_generic_initiv(ctx, iv, ivlen))
+ return 0;
+ }
+ if (key != NULL) {
+ int use_forward_transform;
+
+ if (keylen != ctx->keylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ /*
+ * See SP800-38F : Section 5.1
+ * The forward and inverse transformations for the AES block
+ * cipher—called “cipher” and “inverse cipher” are informally known as
+ * the AES encryption and AES decryption functions, respectively.
+ * If the designated cipher function for a key-wrap algorithm is chosen
+ * to be the AES decryption function, then CIPH-1K will be the AES
+ * encryption function.
+ */
+ if (ctx->inverse_cipher == 0)
+ use_forward_transform = ctx->enc;
+ else
+ use_forward_transform = !ctx->enc;
+ if (use_forward_transform) {
+ AES_set_encrypt_key(key, keylen * 8, &wctx->ks.ks);
+ ctx->block = (block128_f)AES_encrypt;
+ } else {
+ AES_set_decrypt_key(key, keylen * 8, &wctx->ks.ks);
+ ctx->block = (block128_f)AES_decrypt;
+ }
+ }
+ return aes_wrap_set_ctx_params(ctx, params);
+}
+
+static int aes_wrap_einit(void *ctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return aes_wrap_init(ctx, key, keylen, iv, ivlen, params, 1);
+}
+
+static int aes_wrap_dinit(void *ctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return aes_wrap_init(ctx, key, keylen, iv, ivlen, params, 0);
+}
+
+static int aes_wrap_cipher_internal(void *vctx, unsigned char *out,
+ const unsigned char *in, size_t inlen)
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
+ size_t rv;
+ int pad = ctx->pad;
+
+ /* No final operation so always return zero length */
+ if (in == NULL)
+ return 0;
+
+ /* Input length must always be non-zero */
+ if (inlen == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH);
+ return -1;
+ }
+
+ /* If decrypting need at least 16 bytes and multiple of 8 */
+ if (!ctx->enc && (inlen < 16 || inlen & 0x7)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH);
+ return -1;
+ }
+
+ /* If not padding input must be multiple of 8 */
+ if (!pad && inlen & 0x7) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH);
+ return -1;
+ }
+
+ if (out == NULL) {
+ if (ctx->enc) {
+ /* If padding round up to multiple of 8 */
+ if (pad)
+ inlen = (inlen + 7) / 8 * 8;
+ /* 8 byte prefix */
+ return inlen + 8;
+ } else {
+ /*
+ * If not padding output will be exactly 8 bytes smaller than
+ * input. If padding it will be at least 8 bytes smaller but we
+ * don't know how much.
+ */
+ return inlen - 8;
+ }
+ }
+
+ rv = wctx->wrapfn(&wctx->ks.ks, ctx->iv_set ? ctx->iv : NULL, out, in,
+ inlen, ctx->block);
+ if (!rv) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return -1;
+ }
+ if (rv > INT_MAX) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH);
+ return -1;
+ }
+ return (int)rv;
+}
+
+static int aes_wrap_final(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ if (!ossl_prov_is_running())
+ return 0;
+
+ *outl = 0;
+ return 1;
+}
+
+static int aes_wrap_cipher(void *vctx,
+ unsigned char *out, size_t *outl, size_t outsize,
+ const unsigned char *in, size_t inl)
+{
+ PROV_AES_WRAP_CTX *ctx = (PROV_AES_WRAP_CTX *)vctx;
+ size_t len;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (inl == 0) {
+ *outl = 0;
+ return 1;
+ }
+
+ if (outsize < inl) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ len = aes_wrap_cipher_internal(ctx, out, in, inl);
+ if (len <= 0)
+ return 0;
+
+ *outl = len;
+ return 1;
+}
+
+static int aes_wrap_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ const OSSL_PARAM *p;
+ size_t keylen = 0;
+
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &keylen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (ctx->keylen != keylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+#define IMPLEMENT_cipher(mode, fname, UCMODE, flags, kbits, blkbits, ivbits) \
+ static OSSL_FUNC_cipher_get_params_fn aes_##kbits##_##fname##_get_params; \
+ static int aes_##kbits##_##fname##_get_params(OSSL_PARAM params[]) \
+ { \
+ return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,\
+ flags, kbits, blkbits, ivbits); \
+ } \
+ static OSSL_FUNC_cipher_newctx_fn aes_##kbits##fname##_newctx; \
+ static void *aes_##kbits##fname##_newctx(void *provctx) \
+ { \
+ return aes_##mode##_newctx(kbits, blkbits, ivbits, \
+ EVP_CIPH_##UCMODE##_MODE, flags); \
+ } \
+ const OSSL_DISPATCH ossl_##aes##kbits##fname##_functions[] = { \
+ { OSSL_FUNC_CIPHER_NEWCTX, \
+ (void (*)(void))aes_##kbits##fname##_newctx }, \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_##mode##_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_##mode##_dinit }, \
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_##mode##_cipher }, \
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_##mode##_final }, \
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_##mode##_freectx }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, \
+ (void (*)(void))aes_##kbits##_##fname##_get_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void))aes_wrap_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_settable_ctx_params }, \
+ { 0, NULL } \
+ }
+
+IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_NOPAD_IVLEN * 8);
+IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_NOPAD_IVLEN * 8);
+IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_NOPAD_IVLEN * 8);
+IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_PAD_IVLEN * 8);
+IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_PAD_IVLEN * 8);
+IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_PAD_IVLEN * 8);
+
+IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 256, 64, AES_WRAP_NOPAD_IVLEN * 8);
+IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 192, 64, AES_WRAP_NOPAD_IVLEN * 8);
+IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 128, 64, AES_WRAP_NOPAD_IVLEN * 8);
+IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 256, 64, AES_WRAP_PAD_IVLEN * 8);
+IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 192, 64, AES_WRAP_PAD_IVLEN * 8);
+IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 128, 64, AES_WRAP_PAD_IVLEN * 8);
diff --git a/providers/implementations/ciphers/cipher_aes_xts.c b/providers/implementations/ciphers/cipher_aes_xts.c
new file mode 100644
index 000000000000..dce2032986b1
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_xts.c
@@ -0,0 +1,294 @@
+
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * AES low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/proverr.h>
+#include "cipher_aes_xts.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+#define AES_XTS_FLAGS PROV_CIPHER_FLAG_CUSTOM_IV
+#define AES_XTS_IV_BITS 128
+#define AES_XTS_BLOCK_BITS 8
+
+/* forward declarations */
+static OSSL_FUNC_cipher_encrypt_init_fn aes_xts_einit;
+static OSSL_FUNC_cipher_decrypt_init_fn aes_xts_dinit;
+static OSSL_FUNC_cipher_update_fn aes_xts_stream_update;
+static OSSL_FUNC_cipher_final_fn aes_xts_stream_final;
+static OSSL_FUNC_cipher_cipher_fn aes_xts_cipher;
+static OSSL_FUNC_cipher_freectx_fn aes_xts_freectx;
+static OSSL_FUNC_cipher_dupctx_fn aes_xts_dupctx;
+static OSSL_FUNC_cipher_set_ctx_params_fn aes_xts_set_ctx_params;
+static OSSL_FUNC_cipher_settable_ctx_params_fn aes_xts_settable_ctx_params;
+
+/*
+ * Verify that the two keys are different.
+ *
+ * This addresses the vulnerability described in Rogaway's
+ * September 2004 paper:
+ *
+ * "Efficient Instantiations of Tweakable Blockciphers and
+ * Refinements to Modes OCB and PMAC".
+ * (http://web.cs.ucdavis.edu/~rogaway/papers/offsets.pdf)
+ *
+ * FIPS 140-2 IG A.9 XTS-AES Key Generation Requirements states
+ * that:
+ * "The check for Key_1 != Key_2 shall be done at any place
+ * BEFORE using the keys in the XTS-AES algorithm to process
+ * data with them."
+ */
+static int aes_xts_check_keys_differ(const unsigned char *key, size_t bytes,
+ int enc)
+{
+ if ((!ossl_aes_xts_allow_insecure_decrypt || enc)
+ && CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DUPLICATED_KEYS);
+ return 0;
+ }
+ return 1;
+}
+
+/*-
+ * Provider dispatch functions
+ */
+static int aes_xts_init(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[], int enc)
+{
+ PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)vctx;
+ PROV_CIPHER_CTX *ctx = &xctx->base;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ ctx->enc = enc;
+
+ if (iv != NULL) {
+ if (!ossl_cipher_generic_initiv(vctx, iv, ivlen))
+ return 0;
+ }
+ if (key != NULL) {
+ if (keylen != ctx->keylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ if (!aes_xts_check_keys_differ(key, keylen / 2, enc))
+ return 0;
+ if (!ctx->hw->init(ctx, key, keylen))
+ return 0;
+ }
+ return aes_xts_set_ctx_params(ctx, params);
+}
+
+static int aes_xts_einit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return aes_xts_init(vctx, key, keylen, iv, ivlen, params, 1);
+}
+
+static int aes_xts_dinit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return aes_xts_init(vctx, key, keylen, iv, ivlen, params, 0);
+}
+
+static void *aes_xts_newctx(void *provctx, unsigned int mode, uint64_t flags,
+ size_t kbits, size_t blkbits, size_t ivbits)
+{
+ PROV_AES_XTS_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx != NULL) {
+ ossl_cipher_generic_initkey(&ctx->base, kbits, blkbits, ivbits, mode,
+ flags, ossl_prov_cipher_hw_aes_xts(kbits),
+ NULL);
+ }
+ return ctx;
+}
+
+static void aes_xts_freectx(void *vctx)
+{
+ PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;
+
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static void *aes_xts_dupctx(void *vctx)
+{
+ PROV_AES_XTS_CTX *in = (PROV_AES_XTS_CTX *)vctx;
+ PROV_AES_XTS_CTX *ret = NULL;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if (in->xts.key1 != NULL) {
+ if (in->xts.key1 != &in->ks1)
+ return NULL;
+ }
+ if (in->xts.key2 != NULL) {
+ if (in->xts.key2 != &in->ks2)
+ return NULL;
+ }
+ ret = OPENSSL_malloc(sizeof(*ret));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ in->base.hw->copyctx(&ret->base, &in->base);
+ return ret;
+}
+
+static int aes_xts_cipher(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in, size_t inl)
+{
+ PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;
+
+ if (!ossl_prov_is_running()
+ || ctx->xts.key1 == NULL
+ || ctx->xts.key2 == NULL
+ || !ctx->base.iv_set
+ || out == NULL
+ || in == NULL
+ || inl < AES_BLOCK_SIZE)
+ return 0;
+
+ /*
+ * Impose a limit of 2^20 blocks per data unit as specified by
+ * IEEE Std 1619-2018. The earlier and obsolete IEEE Std 1619-2007
+ * indicated that this was a SHOULD NOT rather than a MUST NOT.
+ * NIST SP 800-38E mandates the same limit.
+ */
+ if (inl > XTS_MAX_BLOCKS_PER_DATA_UNIT * AES_BLOCK_SIZE) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE);
+ return 0;
+ }
+
+ if (ctx->stream != NULL)
+ (*ctx->stream)(in, out, inl, ctx->xts.key1, ctx->xts.key2, ctx->base.iv);
+ else if (CRYPTO_xts128_encrypt(&ctx->xts, ctx->base.iv, in, out, inl,
+ ctx->base.enc))
+ return 0;
+
+ *outl = inl;
+ return 1;
+}
+
+static int aes_xts_stream_update(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in,
+ size_t inl)
+{
+ PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;
+
+ if (outsize < inl) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (!aes_xts_cipher(ctx, out, outl, outsize, in, inl)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int aes_xts_stream_final(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ if (!ossl_prov_is_running())
+ return 0;
+ *outl = 0;
+ return 1;
+}
+
+static const OSSL_PARAM aes_xts_known_settable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *aes_xts_settable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *provctx)
+{
+ return aes_xts_known_settable_ctx_params;
+}
+
+static int aes_xts_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ const OSSL_PARAM *p;
+
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL) {
+ size_t keylen;
+
+ if (!OSSL_PARAM_get_size_t(p, &keylen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ /* The key length can not be modified for xts mode */
+ if (keylen != ctx->keylen)
+ return 0;
+ }
+
+ return 1;
+}
+
+#define IMPLEMENT_cipher(lcmode, UCMODE, kbits, flags) \
+static OSSL_FUNC_cipher_get_params_fn aes_##kbits##_##lcmode##_get_params; \
+static int aes_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
+{ \
+ return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
+ flags, 2 * kbits, AES_XTS_BLOCK_BITS, \
+ AES_XTS_IV_BITS); \
+} \
+static OSSL_FUNC_cipher_newctx_fn aes_##kbits##_xts_newctx; \
+static void *aes_##kbits##_xts_newctx(void *provctx) \
+{ \
+ return aes_xts_newctx(provctx, EVP_CIPH_##UCMODE##_MODE, flags, 2 * kbits, \
+ AES_XTS_BLOCK_BITS, AES_XTS_IV_BITS); \
+} \
+const OSSL_DISPATCH ossl_aes##kbits##xts_functions[] = { \
+ { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##kbits##_xts_newctx }, \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_xts_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_xts_dinit }, \
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_xts_stream_update }, \
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_xts_stream_final }, \
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_xts_cipher }, \
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_xts_freectx }, \
+ { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_xts_dupctx }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, \
+ (void (*)(void))aes_##kbits##_##lcmode##_get_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void))aes_xts_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))aes_xts_settable_ctx_params }, \
+ { 0, NULL } \
+}
+
+IMPLEMENT_cipher(xts, XTS, 256, AES_XTS_FLAGS);
+IMPLEMENT_cipher(xts, XTS, 128, AES_XTS_FLAGS);
diff --git a/providers/implementations/ciphers/cipher_aes_xts.h b/providers/implementations/ciphers/cipher_aes_xts.h
new file mode 100644
index 000000000000..afc42ef444b3
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_xts.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/aes.h>
+#include "prov/ciphercommon.h"
+#include "crypto/aes_platform.h"
+
+/*
+ * Available in cipher_fips.c, and compiled with different values depending
+ * on we're in the FIPS module or not.
+ */
+extern const int ossl_aes_xts_allow_insecure_decrypt;
+
+PROV_CIPHER_FUNC(void, xts_stream,
+ (const unsigned char *in, unsigned char *out, size_t len,
+ const AES_KEY *key1, const AES_KEY *key2,
+ const unsigned char iv[16]));
+
+typedef struct prov_aes_xts_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ AES_KEY ks;
+ } ks1, ks2; /* AES key schedules to use */
+ XTS128_CONTEXT xts;
+ OSSL_xts_stream_fn stream;
+} PROV_AES_XTS_CTX;
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_aes_xts_fips.c b/providers/implementations/ciphers/cipher_aes_xts_fips.c
new file mode 100644
index 000000000000..777d928bf96f
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_xts_fips.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * AES low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_aes_xts.h"
+
+#ifdef FIPS_MODULE
+const int ossl_aes_xts_allow_insecure_decrypt = 0;
+#else
+const int ossl_aes_xts_allow_insecure_decrypt = 1;
+#endif /* FIPS_MODULE */
diff --git a/providers/implementations/ciphers/cipher_aes_xts_hw.c b/providers/implementations/ciphers/cipher_aes_xts_hw.c
new file mode 100644
index 000000000000..c71492f51f5e
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_xts_hw.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This file uses the low level AES functions (which are deprecated for
+ * non-internal use) in order to implement provider AES ciphers.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_aes_xts.h"
+
+#define XTS_SET_KEY_FN(fn_set_enc_key, fn_set_dec_key, \
+ fn_block_enc, fn_block_dec, \
+ fn_stream_enc, fn_stream_dec) { \
+ size_t bytes = keylen / 2; \
+ size_t bits = bytes * 8; \
+ \
+ if (ctx->enc) { \
+ fn_set_enc_key(key, bits, &xctx->ks1.ks); \
+ xctx->xts.block1 = (block128_f)fn_block_enc; \
+ } else { \
+ fn_set_dec_key(key, bits, &xctx->ks1.ks); \
+ xctx->xts.block1 = (block128_f)fn_block_dec; \
+ } \
+ fn_set_enc_key(key + bytes, bits, &xctx->ks2.ks); \
+ xctx->xts.block2 = (block128_f)fn_block_enc; \
+ xctx->xts.key1 = &xctx->ks1; \
+ xctx->xts.key2 = &xctx->ks2; \
+ xctx->stream = ctx->enc ? fn_stream_enc : fn_stream_dec; \
+}
+
+static int cipher_hw_aes_xts_generic_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key,
+ size_t keylen)
+{
+ PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx;
+ OSSL_xts_stream_fn stream_enc = NULL;
+ OSSL_xts_stream_fn stream_dec = NULL;
+
+#ifdef AES_XTS_ASM
+ stream_enc = AES_xts_encrypt;
+ stream_dec = AES_xts_decrypt;
+#endif /* AES_XTS_ASM */
+
+#ifdef HWAES_CAPABLE
+ if (HWAES_CAPABLE) {
+# ifdef HWAES_xts_encrypt
+ stream_enc = HWAES_xts_encrypt;
+# endif /* HWAES_xts_encrypt */
+# ifdef HWAES_xts_decrypt
+ stream_dec = HWAES_xts_decrypt;
+# endif /* HWAES_xts_decrypt */
+ XTS_SET_KEY_FN(HWAES_set_encrypt_key, HWAES_set_decrypt_key,
+ HWAES_encrypt, HWAES_decrypt,
+ stream_enc, stream_dec);
+ return 1;
+ } else
+#endif /* HWAES_CAPABLE */
+
+#ifdef BSAES_CAPABLE
+ if (BSAES_CAPABLE) {
+ stream_enc = ossl_bsaes_xts_encrypt;
+ stream_dec = ossl_bsaes_xts_decrypt;
+ } else
+#endif /* BSAES_CAPABLE */
+#ifdef VPAES_CAPABLE
+ if (VPAES_CAPABLE) {
+ XTS_SET_KEY_FN(vpaes_set_encrypt_key, vpaes_set_decrypt_key,
+ vpaes_encrypt, vpaes_decrypt, stream_enc, stream_dec);
+ return 1;
+ } else
+#endif /* VPAES_CAPABLE */
+ {
+ (void)0;
+ }
+ {
+ XTS_SET_KEY_FN(AES_set_encrypt_key, AES_set_decrypt_key,
+ AES_encrypt, AES_decrypt, stream_enc, stream_dec);
+ }
+ return 1;
+}
+
+static void cipher_hw_aes_xts_copyctx(PROV_CIPHER_CTX *dst,
+ const PROV_CIPHER_CTX *src)
+{
+ PROV_AES_XTS_CTX *sctx = (PROV_AES_XTS_CTX *)src;
+ PROV_AES_XTS_CTX *dctx = (PROV_AES_XTS_CTX *)dst;
+
+ *dctx = *sctx;
+ dctx->xts.key1 = &dctx->ks1.ks;
+ dctx->xts.key2 = &dctx->ks2.ks;
+}
+
+#if defined(AESNI_CAPABLE)
+
+static int cipher_hw_aesni_xts_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx;
+
+ XTS_SET_KEY_FN(aesni_set_encrypt_key, aesni_set_decrypt_key,
+ aesni_encrypt, aesni_decrypt,
+ aesni_xts_encrypt, aesni_xts_decrypt);
+ return 1;
+}
+
+# define PROV_CIPHER_HW_declare_xts() \
+static const PROV_CIPHER_HW aesni_xts = { \
+ cipher_hw_aesni_xts_initkey, \
+ NULL, \
+ cipher_hw_aes_xts_copyctx \
+};
+# define PROV_CIPHER_HW_select_xts() \
+if (AESNI_CAPABLE) \
+ return &aesni_xts;
+
+# elif defined(SPARC_AES_CAPABLE)
+
+static int cipher_hw_aes_xts_t4_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx;
+ OSSL_xts_stream_fn stream_enc = NULL;
+ OSSL_xts_stream_fn stream_dec = NULL;
+
+ /* Note: keylen is the size of 2 keys */
+ switch (keylen) {
+ case 32:
+ stream_enc = aes128_t4_xts_encrypt;
+ stream_dec = aes128_t4_xts_decrypt;
+ break;
+ case 64:
+ stream_enc = aes256_t4_xts_encrypt;
+ stream_dec = aes256_t4_xts_decrypt;
+ break;
+ default:
+ return 0;
+ }
+
+ XTS_SET_KEY_FN(aes_t4_set_encrypt_key, aes_t4_set_decrypt_key,
+ aes_t4_encrypt, aes_t4_decrypt,
+ stream_enc, stream_dec);
+ return 1;
+}
+
+# define PROV_CIPHER_HW_declare_xts() \
+static const PROV_CIPHER_HW aes_xts_t4 = { \
+ cipher_hw_aes_xts_t4_initkey, \
+ NULL, \
+ cipher_hw_aes_xts_copyctx \
+};
+# define PROV_CIPHER_HW_select_xts() \
+if (SPARC_AES_CAPABLE) \
+ return &aes_xts_t4;
+# else
+/* The generic case */
+# define PROV_CIPHER_HW_declare_xts()
+# define PROV_CIPHER_HW_select_xts()
+#endif
+
+static const PROV_CIPHER_HW aes_generic_xts = {
+ cipher_hw_aes_xts_generic_initkey,
+ NULL,
+ cipher_hw_aes_xts_copyctx
+};
+PROV_CIPHER_HW_declare_xts()
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts(size_t keybits)
+{
+ PROV_CIPHER_HW_select_xts()
+ return &aes_generic_xts;
+}
diff --git a/providers/implementations/ciphers/cipher_aria.c b/providers/implementations/ciphers/cipher_aria.c
new file mode 100644
index 000000000000..be69c39baba3
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aria.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for ARIA cipher modes ecb, cbc, ofb, cfb, ctr */
+
+#include "cipher_aria.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+static OSSL_FUNC_cipher_freectx_fn aria_freectx;
+static OSSL_FUNC_cipher_dupctx_fn aria_dupctx;
+
+static void aria_freectx(void *vctx)
+{
+ PROV_ARIA_CTX *ctx = (PROV_ARIA_CTX *)vctx;
+
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static void *aria_dupctx(void *ctx)
+{
+ PROV_ARIA_CTX *in = (PROV_ARIA_CTX *)ctx;
+ PROV_ARIA_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ret = OPENSSL_malloc(sizeof(*ret));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ in->base.hw->copyctx(&ret->base, &in->base);
+
+ return ret;
+}
+
+/* ossl_aria256ecb_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, ecb, ECB, 0, 256, 128, 0, block)
+/* ossl_aria192ecb_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, ecb, ECB, 0, 192, 128, 0, block)
+/* ossl_aria128ecb_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, ecb, ECB, 0, 128, 128, 0, block)
+/* ossl_aria256cbc_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, cbc, CBC, 0, 256, 128, 128, block)
+/* ossl_aria192cbc_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, cbc, CBC, 0, 192, 128, 128, block)
+/* ossl_aria128cbc_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, cbc, CBC, 0, 128, 128, 128, block)
+/* ossl_aria256ofb_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, ofb, OFB, 0, 256, 8, 128, stream)
+/* ossl_aria192ofb_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, ofb, OFB, 0, 192, 8, 128, stream)
+/* ossl_aria128ofb_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, ofb, OFB, 0, 128, 8, 128, stream)
+/* ossl_aria256cfb_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, cfb, CFB, 0, 256, 8, 128, stream)
+/* ossl_aria192cfb_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, cfb, CFB, 0, 192, 8, 128, stream)
+/* ossl_aria128cfb_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, cfb, CFB, 0, 128, 8, 128, stream)
+/* ossl_aria256cfb1_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, cfb1, CFB, 0, 256, 8, 128, stream)
+/* ossl_aria192cfb1_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, cfb1, CFB, 0, 192, 8, 128, stream)
+/* ossl_aria128cfb1_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, cfb1, CFB, 0, 128, 8, 128, stream)
+/* ossl_aria256cfb8_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, cfb8, CFB, 0, 256, 8, 128, stream)
+/* ossl_aria192cfb8_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, cfb8, CFB, 0, 192, 8, 128, stream)
+/* ossl_aria128cfb8_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, cfb8, CFB, 0, 128, 8, 128, stream)
+/* ossl_aria256ctr_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, ctr, CTR, 0, 256, 8, 128, stream)
+/* ossl_aria192ctr_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, ctr, CTR, 0, 192, 8, 128, stream)
+/* ossl_aria128ctr_functions */
+IMPLEMENT_generic_cipher(aria, ARIA, ctr, CTR, 0, 128, 8, 128, stream)
diff --git a/providers/implementations/ciphers/cipher_aria.h b/providers/implementations/ciphers/cipher_aria.h
new file mode 100644
index 000000000000..39f84d3b4321
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aria.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "crypto/aria.h"
+#include "prov/ciphercommon.h"
+
+typedef struct prov_aria_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ ARIA_KEY ks;
+ } ks;
+} PROV_ARIA_CTX;
+
+
+#define ossl_prov_cipher_hw_aria_ofb ossl_prov_cipher_hw_aria_ofb128
+#define ossl_prov_cipher_hw_aria_cfb ossl_prov_cipher_hw_aria_cfb128
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aria_ecb(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aria_cbc(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aria_ofb128(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aria_cfb128(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aria_cfb1(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aria_cfb8(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aria_ctr(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_aria_ccm.c b/providers/implementations/ciphers/cipher_aria_ccm.c
new file mode 100644
index 000000000000..d6b5517ee096
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aria_ccm.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for ARIA CCM mode */
+
+#include "cipher_aria_ccm.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+static OSSL_FUNC_cipher_freectx_fn aria_ccm_freectx;
+
+static void *aria_ccm_newctx(void *provctx, size_t keybits)
+{
+ PROV_ARIA_CCM_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx != NULL)
+ ossl_ccm_initctx(&ctx->base, keybits, ossl_prov_aria_hw_ccm(keybits));
+ return ctx;
+}
+
+static void aria_ccm_freectx(void *vctx)
+{
+ PROV_ARIA_CCM_CTX *ctx = (PROV_ARIA_CCM_CTX *)vctx;
+
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+/* aria128ccm functions */
+IMPLEMENT_aead_cipher(aria, ccm, CCM, AEAD_FLAGS, 128, 8, 96);
+/* aria192ccm functions */
+IMPLEMENT_aead_cipher(aria, ccm, CCM, AEAD_FLAGS, 192, 8, 96);
+/* aria256ccm functions */
+IMPLEMENT_aead_cipher(aria, ccm, CCM, AEAD_FLAGS, 256, 8, 96);
+
diff --git a/providers/implementations/ciphers/cipher_aria_ccm.h b/providers/implementations/ciphers/cipher_aria_ccm.h
new file mode 100644
index 000000000000..558da4973fa2
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aria_ccm.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "crypto/aria.h"
+#include "prov/ciphercommon.h"
+#include "prov/ciphercommon_ccm.h"
+
+typedef struct prov_aria_ccm_ctx_st {
+ PROV_CCM_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ ARIA_KEY ks;
+ } ks; /* ARIA key schedule to use */
+} PROV_ARIA_CCM_CTX;
+
+const PROV_CCM_HW *ossl_prov_aria_hw_ccm(size_t keylen);
diff --git a/providers/implementations/ciphers/cipher_aria_ccm_hw.c b/providers/implementations/ciphers/cipher_aria_ccm_hw.c
new file mode 100644
index 000000000000..e56ec8fb0865
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aria_ccm_hw.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*-
+ * Generic support for ARIA CCM.
+ */
+
+#include "cipher_aria_ccm.h"
+
+static int ccm_aria_initkey(PROV_CCM_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_ARIA_CCM_CTX *actx = (PROV_ARIA_CCM_CTX *)ctx;
+
+ ossl_aria_set_encrypt_key(key, keylen * 8, &actx->ks.ks);
+ CRYPTO_ccm128_init(&ctx->ccm_ctx, ctx->m, ctx->l, &actx->ks.ks,
+ (block128_f)ossl_aria_encrypt);
+ ctx->str = NULL;
+ ctx->key_set = 1;
+ return 1;
+}
+
+static const PROV_CCM_HW ccm_aria = {
+ ccm_aria_initkey,
+ ossl_ccm_generic_setiv,
+ ossl_ccm_generic_setaad,
+ ossl_ccm_generic_auth_encrypt,
+ ossl_ccm_generic_auth_decrypt,
+ ossl_ccm_generic_gettag
+};
+const PROV_CCM_HW *ossl_prov_aria_hw_ccm(size_t keybits)
+{
+ return &ccm_aria;
+}
diff --git a/providers/implementations/ciphers/cipher_aria_gcm.c b/providers/implementations/ciphers/cipher_aria_gcm.c
new file mode 100644
index 000000000000..b412bd3202f8
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aria_gcm.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for ARIA GCM mode */
+
+#include "cipher_aria_gcm.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+static void *aria_gcm_newctx(void *provctx, size_t keybits)
+{
+ PROV_ARIA_GCM_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx != NULL)
+ ossl_gcm_initctx(provctx, &ctx->base, keybits,
+ ossl_prov_aria_hw_gcm(keybits));
+ return ctx;
+}
+
+static OSSL_FUNC_cipher_freectx_fn aria_gcm_freectx;
+static void aria_gcm_freectx(void *vctx)
+{
+ PROV_ARIA_GCM_CTX *ctx = (PROV_ARIA_GCM_CTX *)vctx;
+
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+/* ossl_aria128gcm_functions */
+IMPLEMENT_aead_cipher(aria, gcm, GCM, AEAD_FLAGS, 128, 8, 96);
+/* ossl_aria192gcm_functions */
+IMPLEMENT_aead_cipher(aria, gcm, GCM, AEAD_FLAGS, 192, 8, 96);
+/* ossl_aria256gcm_functions */
+IMPLEMENT_aead_cipher(aria, gcm, GCM, AEAD_FLAGS, 256, 8, 96);
+
diff --git a/providers/implementations/ciphers/cipher_aria_gcm.h b/providers/implementations/ciphers/cipher_aria_gcm.h
new file mode 100644
index 000000000000..6251e8322f36
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aria_gcm.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "crypto/aria.h"
+#include "prov/ciphercommon.h"
+#include "prov/ciphercommon_gcm.h"
+
+typedef struct prov_aria_gcm_ctx_st {
+ PROV_GCM_CTX base; /* must be first entry in struct */
+ union {
+ OSSL_UNION_ALIGN;
+ ARIA_KEY ks;
+ } ks;
+} PROV_ARIA_GCM_CTX;
+
+const PROV_GCM_HW *ossl_prov_aria_hw_gcm(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_aria_gcm_hw.c b/providers/implementations/ciphers/cipher_aria_gcm_hw.c
new file mode 100644
index 000000000000..927327c29c77
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aria_gcm_hw.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*-
+ * Generic support for ARIA GCM.
+ */
+
+#include "cipher_aria_gcm.h"
+
+static int aria_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
+ size_t keylen)
+{
+ PROV_ARIA_GCM_CTX *actx = (PROV_ARIA_GCM_CTX *)ctx;
+ ARIA_KEY *ks = &actx->ks.ks;
+
+ GCM_HW_SET_KEY_CTR_FN(ks, ossl_aria_set_encrypt_key, ossl_aria_encrypt, NULL);
+ return 1;
+}
+
+static const PROV_GCM_HW aria_gcm = {
+ aria_gcm_initkey,
+ ossl_gcm_setiv,
+ ossl_gcm_aad_update,
+ ossl_gcm_cipher_update,
+ ossl_gcm_cipher_final,
+ ossl_gcm_one_shot
+};
+const PROV_GCM_HW *ossl_prov_aria_hw_gcm(size_t keybits)
+{
+ return &aria_gcm;
+}
diff --git a/providers/implementations/ciphers/cipher_aria_hw.c b/providers/implementations/ciphers/cipher_aria_hw.c
new file mode 100644
index 000000000000..425d87a65eca
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aria_hw.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/proverr.h>
+#include "cipher_aria.h"
+
+static int cipher_hw_aria_initkey(PROV_CIPHER_CTX *dat,
+ const unsigned char *key, size_t keylen)
+{
+ int ret, mode = dat->mode;
+ PROV_ARIA_CTX *adat = (PROV_ARIA_CTX *)dat;
+ ARIA_KEY *ks = &adat->ks.ks;
+
+ if (dat->enc || (mode != EVP_CIPH_ECB_MODE && mode != EVP_CIPH_CBC_MODE))
+ ret = ossl_aria_set_encrypt_key(key, keylen * 8, ks);
+ else
+ ret = ossl_aria_set_decrypt_key(key, keylen * 8, ks);
+ if (ret < 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
+ return 0;
+ }
+ dat->ks = ks;
+ dat->block = (block128_f)ossl_aria_encrypt;
+ return 1;
+}
+
+IMPLEMENT_CIPHER_HW_COPYCTX(cipher_hw_aria_copyctx, PROV_ARIA_CTX)
+
+# define PROV_CIPHER_HW_aria_mode(mode) \
+static const PROV_CIPHER_HW aria_##mode = { \
+ cipher_hw_aria_initkey, \
+ ossl_cipher_hw_chunked_##mode, \
+ cipher_hw_aria_copyctx \
+}; \
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aria_##mode(size_t keybits) \
+{ \
+ return &aria_##mode; \
+}
+
+PROV_CIPHER_HW_aria_mode(cbc)
+PROV_CIPHER_HW_aria_mode(ecb)
+PROV_CIPHER_HW_aria_mode(ofb128)
+PROV_CIPHER_HW_aria_mode(cfb128)
+PROV_CIPHER_HW_aria_mode(cfb1)
+PROV_CIPHER_HW_aria_mode(cfb8)
+PROV_CIPHER_HW_aria_mode(ctr)
diff --git a/providers/implementations/ciphers/cipher_blowfish.c b/providers/implementations/ciphers/cipher_blowfish.c
new file mode 100644
index 000000000000..748028d3f32b
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_blowfish.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for Blowfish cipher modes ecb, cbc, ofb, cfb */
+
+/*
+ * BF low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_blowfish.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+#define BF_FLAGS PROV_CIPHER_FLAG_VARIABLE_LENGTH
+
+static OSSL_FUNC_cipher_freectx_fn blowfish_freectx;
+static OSSL_FUNC_cipher_dupctx_fn blowfish_dupctx;
+
+static void blowfish_freectx(void *vctx)
+{
+ PROV_BLOWFISH_CTX *ctx = (PROV_BLOWFISH_CTX *)vctx;
+
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static void *blowfish_dupctx(void *ctx)
+{
+ PROV_BLOWFISH_CTX *in = (PROV_BLOWFISH_CTX *)ctx;
+ PROV_BLOWFISH_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ret = OPENSSL_malloc(sizeof(*ret));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ *ret = *in;
+
+ return ret;
+}
+
+/* bf_ecb_functions */
+IMPLEMENT_var_keylen_cipher(blowfish, BLOWFISH, ecb, ECB, BF_FLAGS, 128, 64, 0, block)
+/* bf_cbc_functions */
+IMPLEMENT_var_keylen_cipher(blowfish, BLOWFISH, cbc, CBC, BF_FLAGS, 128, 64, 64, block)
+/* bf_ofb_functions */
+IMPLEMENT_var_keylen_cipher(blowfish, BLOWFISH, ofb64, OFB, BF_FLAGS, 128, 8, 64, stream)
+/* bf_cfb_functions */
+IMPLEMENT_var_keylen_cipher(blowfish, BLOWFISH, cfb64, CFB, BF_FLAGS, 128, 8, 64, stream)
diff --git a/providers/implementations/ciphers/cipher_blowfish.h b/providers/implementations/ciphers/cipher_blowfish.h
new file mode 100644
index 000000000000..bbdc9da3789d
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_blowfish.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/blowfish.h>
+#include "prov/ciphercommon.h"
+
+typedef struct prov_blowfish_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ BF_KEY ks;
+ } ks;
+} PROV_BLOWFISH_CTX;
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_blowfish_cbc(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_blowfish_ecb(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_blowfish_ofb64(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_blowfish_cfb64(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_blowfish_hw.c b/providers/implementations/ciphers/cipher_blowfish_hw.c
new file mode 100644
index 000000000000..4855a71f6871
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_blowfish_hw.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * BF low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_blowfish.h"
+
+static int cipher_hw_blowfish_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_BLOWFISH_CTX *bctx = (PROV_BLOWFISH_CTX *)ctx;
+
+ BF_set_key(&bctx->ks.ks, keylen, key);
+ return 1;
+}
+
+# define PROV_CIPHER_HW_blowfish_mode(mode, UCMODE) \
+IMPLEMENT_CIPHER_HW_##UCMODE(mode, blowfish, PROV_BLOWFISH_CTX, BF_KEY, \
+ BF_##mode) \
+static const PROV_CIPHER_HW bf_##mode = { \
+ cipher_hw_blowfish_initkey, \
+ cipher_hw_blowfish_##mode##_cipher \
+}; \
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_blowfish_##mode(size_t keybits) \
+{ \
+ return &bf_##mode; \
+}
+
+PROV_CIPHER_HW_blowfish_mode(cbc, CBC)
+PROV_CIPHER_HW_blowfish_mode(ecb, ECB)
+PROV_CIPHER_HW_blowfish_mode(ofb64, OFB)
+PROV_CIPHER_HW_blowfish_mode(cfb64, CFB)
diff --git a/providers/implementations/ciphers/cipher_camellia.c b/providers/implementations/ciphers/cipher_camellia.c
new file mode 100644
index 000000000000..b119666aa8b0
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_camellia.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Camellia low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+/* Dispatch functions for CAMELLIA cipher modes ecb, cbc, ofb, cfb, ctr */
+
+#include "cipher_camellia.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+static OSSL_FUNC_cipher_freectx_fn camellia_freectx;
+static OSSL_FUNC_cipher_dupctx_fn camellia_dupctx;
+
+static void camellia_freectx(void *vctx)
+{
+ PROV_CAMELLIA_CTX *ctx = (PROV_CAMELLIA_CTX *)vctx;
+
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static void *camellia_dupctx(void *ctx)
+{
+ PROV_CAMELLIA_CTX *in = (PROV_CAMELLIA_CTX *)ctx;
+ PROV_CAMELLIA_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ret = OPENSSL_malloc(sizeof(*ret));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ in->base.hw->copyctx(&ret->base, &in->base);
+
+ return ret;
+}
+
+/* ossl_camellia256ecb_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, ecb, ECB, 0, 256, 128, 0, block)
+/* ossl_camellia192ecb_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, ecb, ECB, 0, 192, 128, 0, block)
+/* ossl_camellia128ecb_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, ecb, ECB, 0, 128, 128, 0, block)
+/* ossl_camellia256cbc_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, cbc, CBC, 0, 256, 128, 128, block)
+/* ossl_camellia192cbc_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, cbc, CBC, 0, 192, 128, 128, block)
+/* ossl_camellia128cbc_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, cbc, CBC, 0, 128, 128, 128, block)
+/* ossl_camellia256ofb_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, ofb, OFB, 0, 256, 8, 128, stream)
+/* ossl_camellia192ofb_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, ofb, OFB, 0, 192, 8, 128, stream)
+/* ossl_camellia128ofb_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, ofb, OFB, 0, 128, 8, 128, stream)
+/* ossl_camellia256cfb_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb, CFB, 0, 256, 8, 128, stream)
+/* ossl_camellia192cfb_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb, CFB, 0, 192, 8, 128, stream)
+/* ossl_camellia128cfb_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb, CFB, 0, 128, 8, 128, stream)
+/* ossl_camellia256cfb1_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb1, CFB, 0, 256, 8, 128, stream)
+/* ossl_camellia192cfb1_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb1, CFB, 0, 192, 8, 128, stream)
+/* ossl_camellia128cfb1_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb1, CFB, 0, 128, 8, 128, stream)
+/* ossl_camellia256cfb8_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb8, CFB, 0, 256, 8, 128, stream)
+/* ossl_camellia192cfb8_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb8, CFB, 0, 192, 8, 128, stream)
+/* ossl_camellia128cfb8_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb8, CFB, 0, 128, 8, 128, stream)
+/* ossl_camellia256ctr_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, ctr, CTR, 0, 256, 8, 128, stream)
+/* ossl_camellia192ctr_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, ctr, CTR, 0, 192, 8, 128, stream)
+/* ossl_camellia128ctr_functions */
+IMPLEMENT_generic_cipher(camellia, CAMELLIA, ctr, CTR, 0, 128, 8, 128, stream)
+
+#include "cipher_camellia_cts.inc"
diff --git a/providers/implementations/ciphers/cipher_camellia.h b/providers/implementations/ciphers/cipher_camellia.h
new file mode 100644
index 000000000000..953ea74c0b5d
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_camellia.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/camellia.h>
+#include "prov/ciphercommon.h"
+#include "crypto/cmll_platform.h"
+
+typedef struct prov_camellia_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ CAMELLIA_KEY ks;
+ } ks;
+} PROV_CAMELLIA_CTX;
+
+#define ossl_prov_cipher_hw_camellia_ofb ossl_prov_cipher_hw_camellia_ofb128
+#define ossl_prov_cipher_hw_camellia_cfb ossl_prov_cipher_hw_camellia_cfb128
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_camellia_ecb(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_camellia_cbc(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_camellia_ofb128(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_camellia_cfb128(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_camellia_cfb1(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_camellia_cfb8(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_camellia_ctr(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_camellia_cts.inc b/providers/implementations/ciphers/cipher_camellia_cts.inc
new file mode 100644
index 000000000000..84ea992b8da9
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_camellia_cts.inc
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for CAMELLIA CBC CTS ciphers */
+
+#include <openssl/proverr.h>
+#include "cipher_cts.h"
+
+#define CTS_FLAGS PROV_CIPHER_FLAG_CTS
+
+static OSSL_FUNC_cipher_encrypt_init_fn camellia_cbc_cts_einit;
+static OSSL_FUNC_cipher_decrypt_init_fn camellia_cbc_cts_dinit;
+static OSSL_FUNC_cipher_get_ctx_params_fn camellia_cbc_cts_get_ctx_params;
+static OSSL_FUNC_cipher_set_ctx_params_fn camellia_cbc_cts_set_ctx_params;
+static OSSL_FUNC_cipher_gettable_ctx_params_fn camellia_cbc_cts_gettable_ctx_params;
+static OSSL_FUNC_cipher_settable_ctx_params_fn camellia_cbc_cts_settable_ctx_params;
+
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(camellia_cbc_cts)
+OSSL_PARAM_utf8_string(OSSL_CIPHER_PARAM_CTS_MODE, NULL, 0),
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(camellia_cbc_cts)
+
+static int camellia_cbc_cts_einit(void *ctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ if (!ossl_cipher_generic_einit(ctx, key, keylen, iv, ivlen, NULL))
+ return 0;
+ return camellia_cbc_cts_set_ctx_params(ctx, params);
+}
+
+static int camellia_cbc_cts_dinit(void *ctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ if (!ossl_cipher_generic_dinit(ctx, key, keylen, iv, ivlen, NULL))
+ return 0;
+ return camellia_cbc_cts_set_ctx_params(ctx, params);
+}
+
+static int camellia_cbc_cts_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_CTS_MODE);
+ if (p != NULL) {
+ const char *name = ossl_cipher_cbc_cts_mode_id2name(ctx->cts_mode);
+
+ if (name == NULL || !OSSL_PARAM_set_utf8_string(p, name)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+ return ossl_cipher_generic_get_ctx_params(vctx, params);
+}
+
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(camellia_cbc_cts)
+OSSL_PARAM_utf8_string(OSSL_CIPHER_PARAM_CTS_MODE, NULL, 0),
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(camellia_cbc_cts)
+
+static int camellia_cbc_cts_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ const OSSL_PARAM *p;
+ int id;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_CTS_MODE);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ goto err;
+ id = ossl_cipher_cbc_cts_mode_name2id(p->data);
+ if (id < 0)
+ goto err;
+
+ ctx->cts_mode = (unsigned int)id;
+ }
+ return ossl_cipher_generic_set_ctx_params(vctx, params);
+err:
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+}
+
+/* ossl_camellia256cbc_cts_functions */
+IMPLEMENT_cts_cipher(camellia, CAMELLIA, cbc, CBC, CTS_FLAGS, 256, 128, 128, block)
+/* ossl_camellia192cbc_cts_functions */
+IMPLEMENT_cts_cipher(camellia, CAMELLIA, cbc, CBC, CTS_FLAGS, 192, 128, 128, block)
+/* ossl_camellia128cbc_cts_functions */
+IMPLEMENT_cts_cipher(camellia, CAMELLIA, cbc, CBC, CTS_FLAGS, 128, 128, 128, block)
diff --git a/providers/implementations/ciphers/cipher_camellia_hw.c b/providers/implementations/ciphers/cipher_camellia_hw.c
new file mode 100644
index 000000000000..3ebf5b8d4612
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_camellia_hw.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Camellia low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/camellia.h>
+#include <openssl/proverr.h>
+#include "cipher_camellia.h"
+
+static int cipher_hw_camellia_initkey(PROV_CIPHER_CTX *dat,
+ const unsigned char *key, size_t keylen)
+{
+ int ret, mode = dat->mode;
+ PROV_CAMELLIA_CTX *adat = (PROV_CAMELLIA_CTX *)dat;
+ CAMELLIA_KEY *ks = &adat->ks.ks;
+
+ dat->ks = ks;
+ ret = Camellia_set_key(key, keylen * 8, ks);
+ if (ret < 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
+ return 0;
+ }
+ if (dat->enc || (mode != EVP_CIPH_ECB_MODE && mode != EVP_CIPH_CBC_MODE)) {
+ dat->block = (block128_f) Camellia_encrypt;
+ dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
+ (cbc128_f) Camellia_cbc_encrypt : NULL;
+ } else {
+ dat->block = (block128_f) Camellia_decrypt;
+ dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
+ (cbc128_f) Camellia_cbc_encrypt : NULL;
+ }
+ return 1;
+}
+
+IMPLEMENT_CIPHER_HW_COPYCTX(cipher_hw_camellia_copyctx, PROV_CAMELLIA_CTX)
+
+# if defined(SPARC_CMLL_CAPABLE)
+# include "cipher_camellia_hw_t4.inc"
+# else
+/* The generic case */
+# define PROV_CIPHER_HW_declare(mode)
+# define PROV_CIPHER_HW_select(mode)
+# endif /* SPARC_CMLL_CAPABLE */
+
+#define PROV_CIPHER_HW_camellia_mode(mode) \
+static const PROV_CIPHER_HW camellia_##mode = { \
+ cipher_hw_camellia_initkey, \
+ ossl_cipher_hw_generic_##mode, \
+ cipher_hw_camellia_copyctx \
+}; \
+PROV_CIPHER_HW_declare(mode) \
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_camellia_##mode(size_t keybits) \
+{ \
+ PROV_CIPHER_HW_select(mode) \
+ return &camellia_##mode; \
+}
+
+PROV_CIPHER_HW_camellia_mode(cbc)
+PROV_CIPHER_HW_camellia_mode(ecb)
+PROV_CIPHER_HW_camellia_mode(ofb128)
+PROV_CIPHER_HW_camellia_mode(cfb128)
+PROV_CIPHER_HW_camellia_mode(cfb1)
+PROV_CIPHER_HW_camellia_mode(cfb8)
+PROV_CIPHER_HW_camellia_mode(ctr)
diff --git a/providers/implementations/ciphers/cipher_camellia_hw_t4.inc b/providers/implementations/ciphers/cipher_camellia_hw_t4.inc
new file mode 100644
index 000000000000..2dcf3fa18eb5
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_camellia_hw_t4.inc
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*-
+ * Fujitsu SPARC64 X support for camellia modes.
+ * This file is included by cipher_camellia_hw.c
+ */
+
+static int cipher_hw_camellia_t4_initkey(PROV_CIPHER_CTX *dat,
+ const unsigned char *key,
+ size_t keylen)
+{
+ int ret = 0, bits, mode = dat->mode;
+ PROV_CAMELLIA_CTX *adat = (PROV_CAMELLIA_CTX *)dat;
+ CAMELLIA_KEY *ks = &adat->ks.ks;
+
+ dat->ks = ks;
+ bits = keylen * 8;
+
+ cmll_t4_set_key(key, bits, ks);
+
+ if (dat->enc || (mode != EVP_CIPH_ECB_MODE && mode != EVP_CIPH_CBC_MODE)) {
+ dat->block = (block128_f) cmll_t4_encrypt;
+ switch (bits) {
+ case 128:
+ if (mode == EVP_CIPH_CBC_MODE)
+ dat->stream.cbc = (cbc128_f) cmll128_t4_cbc_encrypt;
+ else if (mode == EVP_CIPH_CTR_MODE)
+ dat->stream.ctr = (ctr128_f) cmll128_t4_ctr32_encrypt;
+ else
+ dat->stream.cbc = NULL;
+ break;
+ case 192:
+ case 256:
+ if (mode == EVP_CIPH_CBC_MODE)
+ dat->stream.cbc = (cbc128_f) cmll256_t4_cbc_encrypt;
+ else if (mode == EVP_CIPH_CTR_MODE)
+ dat->stream.ctr = (ctr128_f) cmll256_t4_ctr32_encrypt;
+ else
+ dat->stream.cbc = NULL;
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ } else {
+ dat->block = (block128_f) cmll_t4_decrypt;
+ switch (bits) {
+ case 128:
+ dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
+ (cbc128_f) cmll128_t4_cbc_decrypt : NULL;
+ break;
+ case 192:
+ case 256:
+ dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
+ (cbc128_f) cmll256_t4_cbc_decrypt : NULL;
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ }
+ if (ret < 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
+ return 0;
+ }
+ return 1;
+}
+
+#define PROV_CIPHER_HW_declare(mode) \
+static const PROV_CIPHER_HW t4_camellia_##mode = { \
+ cipher_hw_camellia_t4_initkey, \
+ ossl_cipher_hw_generic_##mode, \
+ cipher_hw_camellia_copyctx \
+};
+#define PROV_CIPHER_HW_select(mode) \
+if (SPARC_CMLL_CAPABLE) \
+ return &t4_camellia_##mode;
diff --git a/providers/implementations/ciphers/cipher_cast.h b/providers/implementations/ciphers/cipher_cast.h
new file mode 100644
index 000000000000..84b58621c1bc
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_cast.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/cast.h>
+#include "prov/ciphercommon.h"
+
+typedef struct prov_cast_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ CAST_KEY ks;
+ } ks;
+} PROV_CAST_CTX;
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_cast5_cbc(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_cast5_ecb(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_cast5_ofb64(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_cast5_cfb64(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_cast5.c b/providers/implementations/ciphers/cipher_cast5.c
new file mode 100644
index 000000000000..55081ccbe958
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_cast5.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * CAST low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+/* Dispatch functions for cast cipher modes ecb, cbc, ofb, cfb */
+
+#include <openssl/proverr.h>
+#include "cipher_cast.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+#define CAST5_FLAGS PROV_CIPHER_FLAG_VARIABLE_LENGTH
+
+static OSSL_FUNC_cipher_freectx_fn cast5_freectx;
+static OSSL_FUNC_cipher_dupctx_fn cast5_dupctx;
+
+static void cast5_freectx(void *vctx)
+{
+ PROV_CAST_CTX *ctx = (PROV_CAST_CTX *)vctx;
+
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static void *cast5_dupctx(void *ctx)
+{
+ PROV_CAST_CTX *in = (PROV_CAST_CTX *)ctx;
+ PROV_CAST_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ret = OPENSSL_malloc(sizeof(*ret));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ *ret = *in;
+
+ return ret;
+}
+
+/* ossl_cast5128ecb_functions */
+IMPLEMENT_var_keylen_cipher(cast5, CAST, ecb, ECB, CAST5_FLAGS, 128, 64, 0, block)
+/* ossl_cast5128cbc_functions */
+IMPLEMENT_var_keylen_cipher(cast5, CAST, cbc, CBC, CAST5_FLAGS, 128, 64, 64, block)
+/* ossl_cast5128ofb64_functions */
+IMPLEMENT_var_keylen_cipher(cast5, CAST, ofb64, OFB, CAST5_FLAGS, 128, 8, 64, stream)
+/* ossl_cast5128cfb64_functions */
+IMPLEMENT_var_keylen_cipher(cast5, CAST, cfb64, CFB, CAST5_FLAGS, 128, 8, 64, stream)
diff --git a/providers/implementations/ciphers/cipher_cast5_hw.c b/providers/implementations/ciphers/cipher_cast5_hw.c
new file mode 100644
index 000000000000..73f0628e578b
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_cast5_hw.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * CAST low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_cast.h"
+
+static int cipher_hw_cast5_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_CAST_CTX *bctx = (PROV_CAST_CTX *)ctx;
+
+ CAST_set_key(&(bctx->ks.ks), keylen, key);
+ return 1;
+}
+
+# define PROV_CIPHER_HW_cast_mode(mode, UCMODE) \
+IMPLEMENT_CIPHER_HW_##UCMODE(mode, cast5, PROV_CAST_CTX, CAST_KEY, \
+ CAST_##mode) \
+static const PROV_CIPHER_HW cast5_##mode = { \
+ cipher_hw_cast5_initkey, \
+ cipher_hw_cast5_##mode##_cipher \
+}; \
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_cast5_##mode(size_t keybits) \
+{ \
+ return &cast5_##mode; \
+}
+
+PROV_CIPHER_HW_cast_mode(cbc, CBC)
+PROV_CIPHER_HW_cast_mode(ecb, ECB)
+PROV_CIPHER_HW_cast_mode(ofb64, OFB)
+PROV_CIPHER_HW_cast_mode(cfb64, CFB)
diff --git a/providers/implementations/ciphers/cipher_chacha20.c b/providers/implementations/ciphers/cipher_chacha20.c
new file mode 100644
index 000000000000..386c865d832e
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_chacha20.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for chacha20 cipher */
+
+#include <openssl/proverr.h>
+#include "cipher_chacha20.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+#define CHACHA20_KEYLEN (CHACHA_KEY_SIZE)
+#define CHACHA20_BLKLEN (1)
+#define CHACHA20_IVLEN (CHACHA_CTR_SIZE)
+#define CHACHA20_FLAGS (PROV_CIPHER_FLAG_CUSTOM_IV)
+
+static OSSL_FUNC_cipher_newctx_fn chacha20_newctx;
+static OSSL_FUNC_cipher_freectx_fn chacha20_freectx;
+static OSSL_FUNC_cipher_get_params_fn chacha20_get_params;
+static OSSL_FUNC_cipher_get_ctx_params_fn chacha20_get_ctx_params;
+static OSSL_FUNC_cipher_set_ctx_params_fn chacha20_set_ctx_params;
+static OSSL_FUNC_cipher_gettable_ctx_params_fn chacha20_gettable_ctx_params;
+static OSSL_FUNC_cipher_settable_ctx_params_fn chacha20_settable_ctx_params;
+#define chacha20_cipher ossl_cipher_generic_cipher
+#define chacha20_update ossl_cipher_generic_stream_update
+#define chacha20_final ossl_cipher_generic_stream_final
+#define chacha20_gettable_params ossl_cipher_generic_gettable_params
+
+void ossl_chacha20_initctx(PROV_CHACHA20_CTX *ctx)
+{
+ ossl_cipher_generic_initkey(ctx, CHACHA20_KEYLEN * 8,
+ CHACHA20_BLKLEN * 8,
+ CHACHA20_IVLEN * 8,
+ 0, CHACHA20_FLAGS,
+ ossl_prov_cipher_hw_chacha20(CHACHA20_KEYLEN * 8),
+ NULL);
+}
+
+static void *chacha20_newctx(void *provctx)
+{
+ PROV_CHACHA20_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx != NULL)
+ ossl_chacha20_initctx(ctx);
+ return ctx;
+}
+
+static void chacha20_freectx(void *vctx)
+{
+ PROV_CHACHA20_CTX *ctx = (PROV_CHACHA20_CTX *)vctx;
+
+ if (ctx != NULL) {
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+ }
+}
+
+static int chacha20_get_params(OSSL_PARAM params[])
+{
+ return ossl_cipher_generic_get_params(params, 0, CHACHA20_FLAGS,
+ CHACHA20_KEYLEN * 8,
+ CHACHA20_BLKLEN * 8,
+ CHACHA20_IVLEN * 8);
+}
+
+static int chacha20_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, CHACHA20_IVLEN)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, CHACHA20_KEYLEN)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+
+ return 1;
+}
+
+static const OSSL_PARAM chacha20_known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
+ OSSL_PARAM_END
+};
+const OSSL_PARAM *chacha20_gettable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *provctx)
+{
+ return chacha20_known_gettable_ctx_params;
+}
+
+static int chacha20_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ size_t len;
+
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &len)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (len != CHACHA20_KEYLEN) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &len)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (len != CHACHA20_IVLEN) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static const OSSL_PARAM chacha20_known_settable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
+ OSSL_PARAM_END
+};
+const OSSL_PARAM *chacha20_settable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *provctx)
+{
+ return chacha20_known_settable_ctx_params;
+}
+
+int ossl_chacha20_einit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ int ret;
+
+ /* The generic function checks for ossl_prov_is_running() */
+ ret = ossl_cipher_generic_einit(vctx, key, keylen, iv, ivlen, NULL);
+ if (ret && iv != NULL) {
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ PROV_CIPHER_HW_CHACHA20 *hw = (PROV_CIPHER_HW_CHACHA20 *)ctx->hw;
+
+ hw->initiv(ctx);
+ }
+ if (ret && !chacha20_set_ctx_params(vctx, params))
+ ret = 0;
+ return ret;
+}
+
+int ossl_chacha20_dinit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ int ret;
+
+ /* The generic function checks for ossl_prov_is_running() */
+ ret = ossl_cipher_generic_dinit(vctx, key, keylen, iv, ivlen, NULL);
+ if (ret && iv != NULL) {
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ PROV_CIPHER_HW_CHACHA20 *hw = (PROV_CIPHER_HW_CHACHA20 *)ctx->hw;
+
+ hw->initiv(ctx);
+ }
+ if (ret && !chacha20_set_ctx_params(vctx, params))
+ ret = 0;
+ return ret;
+}
+
+/* ossl_chacha20_functions */
+const OSSL_DISPATCH ossl_chacha20_functions[] = {
+ { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))chacha20_newctx },
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))chacha20_freectx },
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_chacha20_einit },
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_chacha20_dinit },
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))chacha20_update },
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))chacha20_final },
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))chacha20_cipher},
+ { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))chacha20_get_params },
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,(void (*)(void))chacha20_gettable_params },
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))chacha20_get_ctx_params },
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
+ (void (*)(void))chacha20_gettable_ctx_params },
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (void (*)(void))chacha20_set_ctx_params },
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
+ (void (*)(void))chacha20_settable_ctx_params },
+ { 0, NULL }
+};
+
diff --git a/providers/implementations/ciphers/cipher_chacha20.h b/providers/implementations/ciphers/cipher_chacha20.h
new file mode 100644
index 000000000000..9db8ed9cb424
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_chacha20.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "include/crypto/chacha.h"
+#include "prov/ciphercommon.h"
+
+typedef struct {
+ PROV_CIPHER_CTX base; /* must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ unsigned int d[CHACHA_KEY_SIZE / 4];
+ } key;
+ unsigned int counter[CHACHA_CTR_SIZE / 4];
+ unsigned char buf[CHACHA_BLK_SIZE];
+ unsigned int partial_len;
+} PROV_CHACHA20_CTX;
+
+typedef struct prov_cipher_hw_chacha20_st {
+ PROV_CIPHER_HW base; /* must be first */
+ int (*initiv)(PROV_CIPHER_CTX *ctx);
+
+} PROV_CIPHER_HW_CHACHA20;
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_chacha20(size_t keybits);
+
+OSSL_FUNC_cipher_encrypt_init_fn ossl_chacha20_einit;
+OSSL_FUNC_cipher_decrypt_init_fn ossl_chacha20_dinit;
+void ossl_chacha20_initctx(PROV_CHACHA20_CTX *ctx);
diff --git a/providers/implementations/ciphers/cipher_chacha20_hw.c b/providers/implementations/ciphers/cipher_chacha20_hw.c
new file mode 100644
index 000000000000..3b03bc81ed5a
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_chacha20_hw.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* chacha20 cipher implementation */
+
+#include "cipher_chacha20.h"
+
+static int chacha20_initkey(PROV_CIPHER_CTX *bctx, const uint8_t *key,
+ size_t keylen)
+{
+ PROV_CHACHA20_CTX *ctx = (PROV_CHACHA20_CTX *)bctx;
+ unsigned int i;
+
+ if (key != NULL) {
+ for (i = 0; i < CHACHA_KEY_SIZE; i += 4)
+ ctx->key.d[i / 4] = CHACHA_U8TOU32(key + i);
+ }
+ ctx->partial_len = 0;
+ return 1;
+}
+
+static int chacha20_initiv(PROV_CIPHER_CTX *bctx)
+{
+ PROV_CHACHA20_CTX *ctx = (PROV_CHACHA20_CTX *)bctx;
+ unsigned int i;
+
+ if (bctx->iv_set) {
+ for (i = 0; i < CHACHA_CTR_SIZE; i += 4)
+ ctx->counter[i / 4] = CHACHA_U8TOU32(bctx->oiv + i);
+ }
+ ctx->partial_len = 0;
+ return 1;
+}
+
+static int chacha20_cipher(PROV_CIPHER_CTX *bctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ PROV_CHACHA20_CTX *ctx = (PROV_CHACHA20_CTX *)bctx;
+ unsigned int n, rem, ctr32;
+
+ n = ctx->partial_len;
+ if (n > 0) {
+ while (inl > 0 && n < CHACHA_BLK_SIZE) {
+ *out++ = *in++ ^ ctx->buf[n++];
+ inl--;
+ }
+ ctx->partial_len = n;
+
+ if (inl == 0)
+ return 1;
+
+ if (n == CHACHA_BLK_SIZE) {
+ ctx->partial_len = 0;
+ ctx->counter[0]++;
+ if (ctx->counter[0] == 0)
+ ctx->counter[1]++;
+ }
+ }
+
+ rem = (unsigned int)(inl % CHACHA_BLK_SIZE);
+ inl -= rem;
+ ctr32 = ctx->counter[0];
+ while (inl >= CHACHA_BLK_SIZE) {
+ size_t blocks = inl / CHACHA_BLK_SIZE;
+
+ /*
+ * 1<<28 is just a not-so-small yet not-so-large number...
+ * Below condition is practically never met, but it has to
+ * be checked for code correctness.
+ */
+ if (sizeof(size_t) > sizeof(unsigned int) && blocks > (1U << 28))
+ blocks = (1U << 28);
+
+ /*
+ * As ChaCha20_ctr32 operates on 32-bit counter, caller
+ * has to handle overflow. 'if' below detects the
+ * overflow, which is then handled by limiting the
+ * amount of blocks to the exact overflow point...
+ */
+ ctr32 += (unsigned int)blocks;
+ if (ctr32 < blocks) {
+ blocks -= ctr32;
+ ctr32 = 0;
+ }
+ blocks *= CHACHA_BLK_SIZE;
+ ChaCha20_ctr32(out, in, blocks, ctx->key.d, ctx->counter);
+ inl -= blocks;
+ in += blocks;
+ out += blocks;
+
+ ctx->counter[0] = ctr32;
+ if (ctr32 == 0) ctx->counter[1]++;
+ }
+
+ if (rem > 0) {
+ memset(ctx->buf, 0, sizeof(ctx->buf));
+ ChaCha20_ctr32(ctx->buf, ctx->buf, CHACHA_BLK_SIZE,
+ ctx->key.d, ctx->counter);
+ for (n = 0; n < rem; n++)
+ out[n] = in[n] ^ ctx->buf[n];
+ ctx->partial_len = rem;
+ }
+
+ return 1;
+}
+
+static const PROV_CIPHER_HW_CHACHA20 chacha20_hw = {
+ { chacha20_initkey, chacha20_cipher },
+ chacha20_initiv
+};
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_chacha20(size_t keybits)
+{
+ return (PROV_CIPHER_HW *)&chacha20_hw;
+}
+
diff --git a/providers/implementations/ciphers/cipher_chacha20_poly1305.c b/providers/implementations/ciphers/cipher_chacha20_poly1305.c
new file mode 100644
index 000000000000..abe670add7a8
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_chacha20_poly1305.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for chacha20_poly1305 cipher */
+
+#include <openssl/proverr.h>
+#include "cipher_chacha20_poly1305.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+#define CHACHA20_POLY1305_KEYLEN CHACHA_KEY_SIZE
+#define CHACHA20_POLY1305_BLKLEN 1
+#define CHACHA20_POLY1305_MAX_IVLEN 12
+#define CHACHA20_POLY1305_MODE 0
+#define CHACHA20_POLY1305_FLAGS (PROV_CIPHER_FLAG_AEAD \
+ | PROV_CIPHER_FLAG_CUSTOM_IV)
+
+static OSSL_FUNC_cipher_newctx_fn chacha20_poly1305_newctx;
+static OSSL_FUNC_cipher_freectx_fn chacha20_poly1305_freectx;
+static OSSL_FUNC_cipher_encrypt_init_fn chacha20_poly1305_einit;
+static OSSL_FUNC_cipher_decrypt_init_fn chacha20_poly1305_dinit;
+static OSSL_FUNC_cipher_get_params_fn chacha20_poly1305_get_params;
+static OSSL_FUNC_cipher_get_ctx_params_fn chacha20_poly1305_get_ctx_params;
+static OSSL_FUNC_cipher_set_ctx_params_fn chacha20_poly1305_set_ctx_params;
+static OSSL_FUNC_cipher_cipher_fn chacha20_poly1305_cipher;
+static OSSL_FUNC_cipher_final_fn chacha20_poly1305_final;
+static OSSL_FUNC_cipher_gettable_ctx_params_fn chacha20_poly1305_gettable_ctx_params;
+#define chacha20_poly1305_settable_ctx_params ossl_cipher_aead_settable_ctx_params
+#define chacha20_poly1305_gettable_params ossl_cipher_generic_gettable_params
+#define chacha20_poly1305_update chacha20_poly1305_cipher
+
+static void *chacha20_poly1305_newctx(void *provctx)
+{
+ PROV_CHACHA20_POLY1305_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx != NULL) {
+ ossl_cipher_generic_initkey(&ctx->base, CHACHA20_POLY1305_KEYLEN * 8,
+ CHACHA20_POLY1305_BLKLEN * 8,
+ CHACHA20_POLY1305_IVLEN * 8,
+ CHACHA20_POLY1305_MODE,
+ CHACHA20_POLY1305_FLAGS,
+ ossl_prov_cipher_hw_chacha20_poly1305(
+ CHACHA20_POLY1305_KEYLEN * 8),
+ NULL);
+ ctx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
+ ossl_chacha20_initctx(&ctx->chacha);
+ }
+ return ctx;
+}
+
+static void chacha20_poly1305_freectx(void *vctx)
+{
+ PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)vctx;
+
+ if (ctx != NULL) {
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+ }
+}
+
+static int chacha20_poly1305_get_params(OSSL_PARAM params[])
+{
+ return ossl_cipher_generic_get_params(params, 0, CHACHA20_POLY1305_FLAGS,
+ CHACHA20_POLY1305_KEYLEN * 8,
+ CHACHA20_POLY1305_BLKLEN * 8,
+ CHACHA20_POLY1305_IVLEN * 8);
+}
+
+static int chacha20_poly1305_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)vctx;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL) {
+ if (!OSSL_PARAM_set_size_t(p, CHACHA20_POLY1305_IVLEN)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, CHACHA20_POLY1305_KEYLEN)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tag_len)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ if (!ctx->base.enc) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_SET);
+ return 0;
+ }
+ if (p->data_size == 0 || p->data_size > POLY1305_BLOCK_SIZE) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH);
+ return 0;
+ }
+ memcpy(p->data, ctx->tag, p->data_size);
+ }
+
+ return 1;
+}
+
+static const OSSL_PARAM chacha20_poly1305_known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *chacha20_poly1305_gettable_ctx_params
+ (ossl_unused void *cctx, ossl_unused void *provctx)
+{
+ return chacha20_poly1305_known_gettable_ctx_params;
+}
+
+static int chacha20_poly1305_set_ctx_params(void *vctx,
+ const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ size_t len;
+ PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)vctx;
+ PROV_CIPHER_HW_CHACHA20_POLY1305 *hw =
+ (PROV_CIPHER_HW_CHACHA20_POLY1305 *)ctx->base.hw;
+
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &len)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (len != CHACHA20_POLY1305_KEYLEN) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &len)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (len != CHACHA20_POLY1305_MAX_IVLEN) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (p->data_size == 0 || p->data_size > POLY1305_BLOCK_SIZE) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH);
+ return 0;
+ }
+ if (p->data != NULL) {
+ if (ctx->base.enc) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_NEEDED);
+ return 0;
+ }
+ memcpy(ctx->tag, p->data, p->data_size);
+ }
+ ctx->tag_len = p->data_size;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ len = hw->tls_init(&ctx->base, p->data, p->data_size);
+ if (len == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA);
+ return 0;
+ }
+ ctx->tls_aad_pad_sz = len;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (hw->tls_iv_set_fixed(&ctx->base, p->data, p->data_size) == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ }
+ /* ignore OSSL_CIPHER_PARAM_AEAD_MAC_KEY */
+ return 1;
+}
+
+static int chacha20_poly1305_einit(void *vctx, const unsigned char *key,
+ size_t keylen, const unsigned char *iv,
+ size_t ivlen, const OSSL_PARAM params[])
+{
+ int ret;
+
+ /* The generic function checks for ossl_prov_is_running() */
+ ret = ossl_cipher_generic_einit(vctx, key, keylen, iv, ivlen, NULL);
+ if (ret && iv != NULL) {
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ PROV_CIPHER_HW_CHACHA20_POLY1305 *hw =
+ (PROV_CIPHER_HW_CHACHA20_POLY1305 *)ctx->hw;
+
+ hw->initiv(ctx);
+ }
+ if (ret && !chacha20_poly1305_set_ctx_params(vctx, params))
+ ret = 0;
+ return ret;
+}
+
+static int chacha20_poly1305_dinit(void *vctx, const unsigned char *key,
+ size_t keylen, const unsigned char *iv,
+ size_t ivlen, const OSSL_PARAM params[])
+{
+ int ret;
+
+ /* The generic function checks for ossl_prov_is_running() */
+ ret = ossl_cipher_generic_dinit(vctx, key, keylen, iv, ivlen, NULL);
+ if (ret && iv != NULL) {
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ PROV_CIPHER_HW_CHACHA20_POLY1305 *hw =
+ (PROV_CIPHER_HW_CHACHA20_POLY1305 *)ctx->hw;
+
+ hw->initiv(ctx);
+ }
+ if (ret && !chacha20_poly1305_set_ctx_params(vctx, params))
+ ret = 0;
+ return ret;
+}
+
+static int chacha20_poly1305_cipher(void *vctx, unsigned char *out,
+ size_t *outl, size_t outsize,
+ const unsigned char *in, size_t inl)
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ PROV_CIPHER_HW_CHACHA20_POLY1305 *hw =
+ (PROV_CIPHER_HW_CHACHA20_POLY1305 *)ctx->hw;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (inl == 0) {
+ *outl = 0;
+ return 1;
+ }
+
+ if (outsize < inl) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (!hw->aead_cipher(ctx, out, outl, in, inl))
+ return 0;
+
+ return 1;
+}
+
+static int chacha20_poly1305_final(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ PROV_CIPHER_HW_CHACHA20_POLY1305 *hw =
+ (PROV_CIPHER_HW_CHACHA20_POLY1305 *)ctx->hw;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (hw->aead_cipher(ctx, out, outl, NULL, 0) <= 0)
+ return 0;
+
+ *outl = 0;
+ return 1;
+}
+
+/* ossl_chacha20_ossl_poly1305_functions */
+const OSSL_DISPATCH ossl_chacha20_ossl_poly1305_functions[] = {
+ { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))chacha20_poly1305_newctx },
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))chacha20_poly1305_freectx },
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))chacha20_poly1305_einit },
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))chacha20_poly1305_dinit },
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))chacha20_poly1305_update },
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))chacha20_poly1305_final },
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))chacha20_poly1305_cipher },
+ { OSSL_FUNC_CIPHER_GET_PARAMS,
+ (void (*)(void))chacha20_poly1305_get_params },
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,
+ (void (*)(void))chacha20_poly1305_gettable_params },
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,
+ (void (*)(void))chacha20_poly1305_get_ctx_params },
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
+ (void (*)(void))chacha20_poly1305_gettable_ctx_params },
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,
+ (void (*)(void))chacha20_poly1305_set_ctx_params },
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
+ (void (*)(void))chacha20_poly1305_settable_ctx_params },
+ { 0, NULL }
+};
+
diff --git a/providers/implementations/ciphers/cipher_chacha20_poly1305.h b/providers/implementations/ciphers/cipher_chacha20_poly1305.h
new file mode 100644
index 000000000000..f2ea26a77f3a
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_chacha20_poly1305.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for chacha20_poly1305 cipher */
+
+#include "include/crypto/poly1305.h"
+#include "cipher_chacha20.h"
+
+#define NO_TLS_PAYLOAD_LENGTH ((size_t)-1)
+#define CHACHA20_POLY1305_IVLEN 12
+
+typedef struct {
+ PROV_CIPHER_CTX base; /* must be first */
+ PROV_CHACHA20_CTX chacha;
+ POLY1305 poly1305;
+ unsigned int nonce[12 / 4];
+ unsigned char tag[POLY1305_BLOCK_SIZE];
+ unsigned char tls_aad[POLY1305_BLOCK_SIZE];
+ struct { uint64_t aad, text; } len;
+ unsigned int aad : 1;
+ unsigned int mac_inited : 1;
+ size_t tag_len;
+ size_t tls_payload_length;
+ size_t tls_aad_pad_sz;
+} PROV_CHACHA20_POLY1305_CTX;
+
+typedef struct prov_cipher_hw_chacha_aead_st {
+ PROV_CIPHER_HW base; /* must be first */
+ int (*aead_cipher)(PROV_CIPHER_CTX *dat, unsigned char *out, size_t *outl,
+ const unsigned char *in, size_t len);
+ int (*initiv)(PROV_CIPHER_CTX *ctx);
+ int (*tls_init)(PROV_CIPHER_CTX *ctx, unsigned char *aad, size_t alen);
+ int (*tls_iv_set_fixed)(PROV_CIPHER_CTX *ctx, unsigned char *fixed,
+ size_t flen);
+} PROV_CIPHER_HW_CHACHA20_POLY1305;
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_chacha20_poly1305(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c b/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c
new file mode 100644
index 000000000000..8173663e5e7e
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* chacha20_poly1305 cipher implementation */
+
+#include "internal/endian.h"
+#include "cipher_chacha20_poly1305.h"
+
+static int chacha_poly1305_tls_init(PROV_CIPHER_CTX *bctx,
+ unsigned char *aad, size_t alen)
+{
+ unsigned int len;
+ PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)bctx;
+
+ if (alen != EVP_AEAD_TLS1_AAD_LEN)
+ return 0;
+
+ memcpy(ctx->tls_aad, aad, EVP_AEAD_TLS1_AAD_LEN);
+ len = aad[EVP_AEAD_TLS1_AAD_LEN - 2] << 8 | aad[EVP_AEAD_TLS1_AAD_LEN - 1];
+ aad = ctx->tls_aad;
+ if (!bctx->enc) {
+ if (len < POLY1305_BLOCK_SIZE)
+ return 0;
+ len -= POLY1305_BLOCK_SIZE; /* discount attached tag */
+ aad[EVP_AEAD_TLS1_AAD_LEN - 2] = (unsigned char)(len >> 8);
+ aad[EVP_AEAD_TLS1_AAD_LEN - 1] = (unsigned char)len;
+ }
+ ctx->tls_payload_length = len;
+
+ /* merge record sequence number as per RFC7905 */
+ ctx->chacha.counter[1] = ctx->nonce[0];
+ ctx->chacha.counter[2] = ctx->nonce[1] ^ CHACHA_U8TOU32(aad);
+ ctx->chacha.counter[3] = ctx->nonce[2] ^ CHACHA_U8TOU32(aad+4);
+ ctx->mac_inited = 0;
+
+ return POLY1305_BLOCK_SIZE; /* tag length */
+}
+
+static int chacha_poly1305_tls_iv_set_fixed(PROV_CIPHER_CTX *bctx,
+ unsigned char *fixed, size_t flen)
+{
+ PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)bctx;
+
+ if (flen != CHACHA20_POLY1305_IVLEN)
+ return 0;
+ ctx->nonce[0] = ctx->chacha.counter[1] = CHACHA_U8TOU32(fixed);
+ ctx->nonce[1] = ctx->chacha.counter[2] = CHACHA_U8TOU32(fixed + 4);
+ ctx->nonce[2] = ctx->chacha.counter[3] = CHACHA_U8TOU32(fixed + 8);
+ return 1;
+}
+
+static int chacha20_poly1305_initkey(PROV_CIPHER_CTX *bctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)bctx;
+
+ ctx->len.aad = 0;
+ ctx->len.text = 0;
+ ctx->aad = 0;
+ ctx->mac_inited = 0;
+ ctx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
+
+ if (bctx->enc)
+ return ossl_chacha20_einit(&ctx->chacha, key, keylen, NULL, 0, NULL);
+ else
+ return ossl_chacha20_dinit(&ctx->chacha, key, keylen, NULL, 0, NULL);
+}
+
+static int chacha20_poly1305_initiv(PROV_CIPHER_CTX *bctx)
+{
+ PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)bctx;
+ unsigned char tempiv[CHACHA_CTR_SIZE] = { 0 };
+ int ret = 1;
+ size_t noncelen = CHACHA20_POLY1305_IVLEN;
+
+ ctx->len.aad = 0;
+ ctx->len.text = 0;
+ ctx->aad = 0;
+ ctx->mac_inited = 0;
+ ctx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
+
+ /* pad on the left */
+ memcpy(tempiv + CHACHA_CTR_SIZE - noncelen, bctx->oiv,
+ noncelen);
+
+ if (bctx->enc)
+ ret = ossl_chacha20_einit(&ctx->chacha, NULL, 0,
+ tempiv, sizeof(tempiv), NULL);
+ else
+ ret = ossl_chacha20_dinit(&ctx->chacha, NULL, 0,
+ tempiv, sizeof(tempiv), NULL);
+ ctx->nonce[0] = ctx->chacha.counter[1];
+ ctx->nonce[1] = ctx->chacha.counter[2];
+ ctx->nonce[2] = ctx->chacha.counter[3];
+ bctx->iv_set = 1;
+ return ret;
+}
+
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+
+# if defined(POLY1305_ASM) && (defined(__x86_64) || defined(__x86_64__) \
+ || defined(_M_AMD64) || defined(_M_X64))
+# define XOR128_HELPERS
+void *xor128_encrypt_n_pad(void *out, const void *inp, void *otp, size_t len);
+void *xor128_decrypt_n_pad(void *out, const void *inp, void *otp, size_t len);
+static const unsigned char zero[4 * CHACHA_BLK_SIZE] = { 0 };
+# else
+static const unsigned char zero[2 * CHACHA_BLK_SIZE] = { 0 };
+# endif
+
+static int chacha20_poly1305_tls_cipher(PROV_CIPHER_CTX *bctx,
+ unsigned char *out,
+ size_t *out_padlen,
+ const unsigned char *in, size_t len)
+{
+ PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)bctx;
+ POLY1305 *poly = &ctx->poly1305;
+ size_t tail, tohash_len, buf_len, plen = ctx->tls_payload_length;
+ unsigned char *buf, *tohash, *ctr, storage[sizeof(zero) + 32];
+
+ DECLARE_IS_ENDIAN;
+
+ buf = storage + ((0 - (size_t)storage) & 15); /* align */
+ ctr = buf + CHACHA_BLK_SIZE;
+ tohash = buf + CHACHA_BLK_SIZE - POLY1305_BLOCK_SIZE;
+
+# ifdef XOR128_HELPERS
+ if (plen <= 3 * CHACHA_BLK_SIZE) {
+ ctx->chacha.counter[0] = 0;
+ buf_len = (plen + 2 * CHACHA_BLK_SIZE - 1) & (0 - CHACHA_BLK_SIZE);
+ ChaCha20_ctr32(buf, zero, buf_len, ctx->chacha.key.d, ctx->chacha.counter);
+ Poly1305_Init(poly, buf);
+ ctx->chacha.partial_len = 0;
+ memcpy(tohash, ctx->tls_aad, POLY1305_BLOCK_SIZE);
+ tohash_len = POLY1305_BLOCK_SIZE;
+ ctx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
+ ctx->len.text = plen;
+
+ if (plen) {
+ if (bctx->enc)
+ ctr = xor128_encrypt_n_pad(out, in, ctr, plen);
+ else
+ ctr = xor128_decrypt_n_pad(out, in, ctr, plen);
+
+ in += plen;
+ out += plen;
+ tohash_len = (size_t)(ctr - tohash);
+ }
+ }
+# else
+ if (plen <= CHACHA_BLK_SIZE) {
+ size_t i;
+
+ ctx->chacha.counter[0] = 0;
+ ChaCha20_ctr32(buf, zero, (buf_len = 2 * CHACHA_BLK_SIZE),
+ ctx->chacha.key.d, ctx->chacha.counter);
+ Poly1305_Init(poly, buf);
+ ctx->chacha.partial_len = 0;
+ memcpy(tohash, ctx->tls_aad, POLY1305_BLOCK_SIZE);
+ tohash_len = POLY1305_BLOCK_SIZE;
+ ctx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
+ ctx->len.text = plen;
+
+ if (bctx->enc) {
+ for (i = 0; i < plen; i++)
+ out[i] = ctr[i] ^= in[i];
+ } else {
+ for (i = 0; i < plen; i++) {
+ unsigned char c = in[i];
+
+ out[i] = ctr[i] ^ c;
+ ctr[i] = c;
+ }
+ }
+
+ in += i;
+ out += i;
+
+ tail = (0 - i) & (POLY1305_BLOCK_SIZE - 1);
+ memset(ctr + i, 0, tail);
+ ctr += i + tail;
+ tohash_len += i + tail;
+ }
+# endif
+ else {
+ ctx->chacha.counter[0] = 0;
+ ChaCha20_ctr32(buf, zero, (buf_len = CHACHA_BLK_SIZE),
+ ctx->chacha.key.d, ctx->chacha.counter);
+ Poly1305_Init(poly, buf);
+ ctx->chacha.counter[0] = 1;
+ ctx->chacha.partial_len = 0;
+ Poly1305_Update(poly, ctx->tls_aad, POLY1305_BLOCK_SIZE);
+ tohash = ctr;
+ tohash_len = 0;
+ ctx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
+ ctx->len.text = plen;
+
+ if (bctx->enc) {
+ ChaCha20_ctr32(out, in, plen, ctx->chacha.key.d, ctx->chacha.counter);
+ Poly1305_Update(poly, out, plen);
+ } else {
+ Poly1305_Update(poly, in, plen);
+ ChaCha20_ctr32(out, in, plen, ctx->chacha.key.d, ctx->chacha.counter);
+ }
+
+ in += plen;
+ out += plen;
+ tail = (0 - plen) & (POLY1305_BLOCK_SIZE - 1);
+ Poly1305_Update(poly, zero, tail);
+ }
+
+ if (IS_LITTLE_ENDIAN) {
+ memcpy(ctr, (unsigned char *)&ctx->len, POLY1305_BLOCK_SIZE);
+ } else {
+ ctr[0] = (unsigned char)(ctx->len.aad);
+ ctr[1] = (unsigned char)(ctx->len.aad>>8);
+ ctr[2] = (unsigned char)(ctx->len.aad>>16);
+ ctr[3] = (unsigned char)(ctx->len.aad>>24);
+ ctr[4] = (unsigned char)(ctx->len.aad>>32);
+ ctr[5] = (unsigned char)(ctx->len.aad>>40);
+ ctr[6] = (unsigned char)(ctx->len.aad>>48);
+ ctr[7] = (unsigned char)(ctx->len.aad>>56);
+
+ ctr[8] = (unsigned char)(ctx->len.text);
+ ctr[9] = (unsigned char)(ctx->len.text>>8);
+ ctr[10] = (unsigned char)(ctx->len.text>>16);
+ ctr[11] = (unsigned char)(ctx->len.text>>24);
+ ctr[12] = (unsigned char)(ctx->len.text>>32);
+ ctr[13] = (unsigned char)(ctx->len.text>>40);
+ ctr[14] = (unsigned char)(ctx->len.text>>48);
+ ctr[15] = (unsigned char)(ctx->len.text>>56);
+ }
+ tohash_len += POLY1305_BLOCK_SIZE;
+
+ Poly1305_Update(poly, tohash, tohash_len);
+ OPENSSL_cleanse(buf, buf_len);
+ Poly1305_Final(poly, bctx->enc ? ctx->tag : tohash);
+
+ ctx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
+
+ if (bctx->enc) {
+ memcpy(out, ctx->tag, POLY1305_BLOCK_SIZE);
+ } else {
+ if (CRYPTO_memcmp(tohash, in, POLY1305_BLOCK_SIZE)) {
+ if (len > POLY1305_BLOCK_SIZE)
+ memset(out - (len - POLY1305_BLOCK_SIZE), 0,
+ len - POLY1305_BLOCK_SIZE);
+ return 0;
+ }
+ /* Strip the tag */
+ len -= POLY1305_BLOCK_SIZE;
+ }
+
+ *out_padlen = len;
+ return 1;
+}
+#else
+static const unsigned char zero[CHACHA_BLK_SIZE] = { 0 };
+#endif /* OPENSSL_SMALL_FOOTPRINT */
+
+static int chacha20_poly1305_aead_cipher(PROV_CIPHER_CTX *bctx,
+ unsigned char *out, size_t *outl,
+ const unsigned char *in, size_t inl)
+{
+ PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)bctx;
+ POLY1305 *poly = &ctx->poly1305;
+ size_t rem, plen = ctx->tls_payload_length;
+ size_t olen = 0;
+ int rv = 0;
+
+ DECLARE_IS_ENDIAN;
+
+ if (!ctx->mac_inited) {
+ if (plen != NO_TLS_PAYLOAD_LENGTH && out != NULL) {
+ if (inl != plen + POLY1305_BLOCK_SIZE)
+ return 0;
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+ return chacha20_poly1305_tls_cipher(bctx, out, outl, in, inl);
+#endif
+ }
+
+ ctx->chacha.counter[0] = 0;
+ ChaCha20_ctr32(ctx->chacha.buf, zero, CHACHA_BLK_SIZE,
+ ctx->chacha.key.d, ctx->chacha.counter);
+ Poly1305_Init(poly, ctx->chacha.buf);
+ ctx->chacha.counter[0] = 1;
+ ctx->chacha.partial_len = 0;
+ ctx->len.aad = ctx->len.text = 0;
+ ctx->mac_inited = 1;
+ if (plen != NO_TLS_PAYLOAD_LENGTH) {
+ Poly1305_Update(poly, ctx->tls_aad, EVP_AEAD_TLS1_AAD_LEN);
+ ctx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
+ ctx->aad = 1;
+ }
+ }
+
+ if (in != NULL) { /* aad or text */
+ if (out == NULL) { /* aad */
+ Poly1305_Update(poly, in, inl);
+ ctx->len.aad += inl;
+ ctx->aad = 1;
+ goto finish;
+ } else { /* plain- or ciphertext */
+ if (ctx->aad) { /* wrap up aad */
+ if ((rem = (size_t)ctx->len.aad % POLY1305_BLOCK_SIZE))
+ Poly1305_Update(poly, zero, POLY1305_BLOCK_SIZE - rem);
+ ctx->aad = 0;
+ }
+
+ ctx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
+ if (plen == NO_TLS_PAYLOAD_LENGTH)
+ plen = inl;
+ else if (inl != plen + POLY1305_BLOCK_SIZE)
+ goto err;
+
+ if (bctx->enc) { /* plaintext */
+ ctx->chacha.base.hw->cipher(&ctx->chacha.base, out, in, plen);
+ Poly1305_Update(poly, out, plen);
+ in += plen;
+ out += plen;
+ ctx->len.text += plen;
+ } else { /* ciphertext */
+ Poly1305_Update(poly, in, plen);
+ ctx->chacha.base.hw->cipher(&ctx->chacha.base, out, in, plen);
+ in += plen;
+ out += plen;
+ ctx->len.text += plen;
+ }
+ }
+ }
+ /* explicit final, or tls mode */
+ if (in == NULL || inl != plen) {
+
+ unsigned char temp[POLY1305_BLOCK_SIZE];
+
+ if (ctx->aad) { /* wrap up aad */
+ if ((rem = (size_t)ctx->len.aad % POLY1305_BLOCK_SIZE))
+ Poly1305_Update(poly, zero, POLY1305_BLOCK_SIZE - rem);
+ ctx->aad = 0;
+ }
+
+ if ((rem = (size_t)ctx->len.text % POLY1305_BLOCK_SIZE))
+ Poly1305_Update(poly, zero, POLY1305_BLOCK_SIZE - rem);
+
+ if (IS_LITTLE_ENDIAN) {
+ Poly1305_Update(poly, (unsigned char *)&ctx->len,
+ POLY1305_BLOCK_SIZE);
+ } else {
+ temp[0] = (unsigned char)(ctx->len.aad);
+ temp[1] = (unsigned char)(ctx->len.aad>>8);
+ temp[2] = (unsigned char)(ctx->len.aad>>16);
+ temp[3] = (unsigned char)(ctx->len.aad>>24);
+ temp[4] = (unsigned char)(ctx->len.aad>>32);
+ temp[5] = (unsigned char)(ctx->len.aad>>40);
+ temp[6] = (unsigned char)(ctx->len.aad>>48);
+ temp[7] = (unsigned char)(ctx->len.aad>>56);
+ temp[8] = (unsigned char)(ctx->len.text);
+ temp[9] = (unsigned char)(ctx->len.text>>8);
+ temp[10] = (unsigned char)(ctx->len.text>>16);
+ temp[11] = (unsigned char)(ctx->len.text>>24);
+ temp[12] = (unsigned char)(ctx->len.text>>32);
+ temp[13] = (unsigned char)(ctx->len.text>>40);
+ temp[14] = (unsigned char)(ctx->len.text>>48);
+ temp[15] = (unsigned char)(ctx->len.text>>56);
+ Poly1305_Update(poly, temp, POLY1305_BLOCK_SIZE);
+ }
+ Poly1305_Final(poly, bctx->enc ? ctx->tag : temp);
+ ctx->mac_inited = 0;
+
+ if (in != NULL && inl != plen) {
+ if (bctx->enc) {
+ memcpy(out, ctx->tag, POLY1305_BLOCK_SIZE);
+ } else {
+ if (CRYPTO_memcmp(temp, in, POLY1305_BLOCK_SIZE)) {
+ memset(out - plen, 0, plen);
+ goto err;
+ }
+ /* Strip the tag */
+ inl -= POLY1305_BLOCK_SIZE;
+ }
+ }
+ else if (!bctx->enc) {
+ if (CRYPTO_memcmp(temp, ctx->tag, ctx->tag_len))
+ goto err;
+ }
+ }
+finish:
+ olen = inl;
+ rv = 1;
+err:
+ *outl = olen;
+ return rv;
+}
+
+static const PROV_CIPHER_HW_CHACHA20_POLY1305 chacha20poly1305_hw =
+{
+ { chacha20_poly1305_initkey, NULL },
+ chacha20_poly1305_aead_cipher,
+ chacha20_poly1305_initiv,
+ chacha_poly1305_tls_init,
+ chacha_poly1305_tls_iv_set_fixed
+};
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_chacha20_poly1305(size_t keybits)
+{
+ return (PROV_CIPHER_HW *)&chacha20poly1305_hw;
+}
diff --git a/providers/implementations/ciphers/cipher_cts.c b/providers/implementations/ciphers/cipher_cts.c
new file mode 100644
index 000000000000..6a596508da69
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_cts.c
@@ -0,0 +1,378 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Helper functions for 128 bit CBC CTS ciphers (Currently AES and Camellia).
+ *
+ * The function dispatch tables are embedded into cipher_aes.c
+ * and cipher_camellia.c using cipher_aes_cts.inc and cipher_camellia_cts.inc
+ */
+
+/*
+ * Refer to SP800-38A-Addendum
+ *
+ * Ciphertext stealing encrypts plaintext using a block cipher, without padding
+ * the message to a multiple of the block size, so the ciphertext is the same
+ * size as the plaintext.
+ * It does this by altering processing of the last two blocks of the message.
+ * The processing of all but the last two blocks is unchanged, but a portion of
+ * the second-last block's ciphertext is "stolen" to pad the last plaintext
+ * block. The padded final block is then encrypted as usual.
+ * The final ciphertext for the last two blocks, consists of the partial block
+ * (with the "stolen" portion omitted) plus the full final block,
+ * which are the same size as the original plaintext.
+ * Decryption requires decrypting the final block first, then restoring the
+ * stolen ciphertext to the partial block, which can then be decrypted as usual.
+
+ * AES_CBC_CTS has 3 variants:
+ * (1) CS1 The NIST variant.
+ * If the length is a multiple of the blocksize it is the same as CBC mode.
+ * otherwise it produces C1||C2||(C(n-1))*||Cn.
+ * Where C(n-1)* is a partial block.
+ * (2) CS2
+ * If the length is a multiple of the blocksize it is the same as CBC mode.
+ * otherwise it produces C1||C2||Cn||(C(n-1))*.
+ * Where C(n-1)* is a partial block.
+ * (3) CS3 The Kerberos5 variant.
+ * Produces C1||C2||Cn||(C(n-1))* regardless of the length.
+ * If the length is a multiple of the blocksize it looks similar to CBC mode
+ * with the last 2 blocks swapped.
+ * Otherwise it is the same as CS2.
+ */
+
+#include <openssl/core_names.h>
+#include "prov/ciphercommon.h"
+#include "internal/nelem.h"
+#include "cipher_cts.h"
+
+/* The value assigned to 0 is the default */
+#define CTS_CS1 0
+#define CTS_CS2 1
+#define CTS_CS3 2
+
+#define CTS_BLOCK_SIZE 16
+
+typedef union {
+ size_t align;
+ unsigned char c[CTS_BLOCK_SIZE];
+} aligned_16bytes;
+
+typedef struct cts_mode_name2id_st {
+ unsigned int id;
+ const char *name;
+} CTS_MODE_NAME2ID;
+
+static CTS_MODE_NAME2ID cts_modes[] =
+{
+ { CTS_CS1, OSSL_CIPHER_CTS_MODE_CS1 },
+ { CTS_CS2, OSSL_CIPHER_CTS_MODE_CS2 },
+ { CTS_CS3, OSSL_CIPHER_CTS_MODE_CS3 },
+};
+
+const char *ossl_cipher_cbc_cts_mode_id2name(unsigned int id)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(cts_modes); ++i) {
+ if (cts_modes[i].id == id)
+ return cts_modes[i].name;
+ }
+ return NULL;
+}
+
+int ossl_cipher_cbc_cts_mode_name2id(const char *name)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(cts_modes); ++i) {
+ if (OPENSSL_strcasecmp(name, cts_modes[i].name) == 0)
+ return (int)cts_modes[i].id;
+ }
+ return -1;
+}
+
+static size_t cts128_cs1_encrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
+ unsigned char *out, size_t len)
+{
+ aligned_16bytes tmp_in;
+ size_t residue;
+
+ residue = len % CTS_BLOCK_SIZE;
+ len -= residue;
+ if (!ctx->hw->cipher(ctx, out, in, len))
+ return 0;
+
+ if (residue == 0)
+ return len;
+
+ in += len;
+ out += len;
+
+ memset(tmp_in.c, 0, sizeof(tmp_in));
+ memcpy(tmp_in.c, in, residue);
+ if (!ctx->hw->cipher(ctx, out - CTS_BLOCK_SIZE + residue, tmp_in.c,
+ CTS_BLOCK_SIZE))
+ return 0;
+ return len + residue;
+}
+
+static void do_xor(const unsigned char *in1, const unsigned char *in2,
+ size_t len, unsigned char *out)
+{
+ size_t i;
+
+ for (i = 0; i < len; ++i)
+ out[i] = in1[i] ^ in2[i];
+}
+
+static size_t cts128_cs1_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
+ unsigned char *out, size_t len)
+{
+ aligned_16bytes mid_iv, ct_mid, cn, pt_last;
+ size_t residue;
+
+ residue = len % CTS_BLOCK_SIZE;
+ if (residue == 0) {
+ /* If there are no partial blocks then it is the same as CBC mode */
+ if (!ctx->hw->cipher(ctx, out, in, len))
+ return 0;
+ return len;
+ }
+ /* Process blocks at the start - but leave the last 2 blocks */
+ len -= CTS_BLOCK_SIZE + residue;
+ if (len > 0) {
+ if (!ctx->hw->cipher(ctx, out, in, len))
+ return 0;
+ in += len;
+ out += len;
+ }
+ /* Save the iv that will be used by the second last block */
+ memcpy(mid_iv.c, ctx->iv, CTS_BLOCK_SIZE);
+ /* Save the C(n) block */
+ memcpy(cn.c, in + residue, CTS_BLOCK_SIZE);
+
+ /* Decrypt the last block first using an iv of zero */
+ memset(ctx->iv, 0, CTS_BLOCK_SIZE);
+ if (!ctx->hw->cipher(ctx, pt_last.c, in + residue, CTS_BLOCK_SIZE))
+ return 0;
+
+ /*
+ * Rebuild the ciphertext of the second last block as a combination of
+ * the decrypted last block + replace the start with the ciphertext bytes
+ * of the partial second last block.
+ */
+ memcpy(ct_mid.c, in, residue);
+ memcpy(ct_mid.c + residue, pt_last.c + residue, CTS_BLOCK_SIZE - residue);
+ /*
+ * Restore the last partial ciphertext block.
+ * Now that we have the cipher text of the second last block, apply
+ * that to the partial plaintext end block. We have already decrypted the
+ * block using an IV of zero. For decryption the IV is just XORed after
+ * doing an Cipher CBC block - so just XOR in the cipher text.
+ */
+ do_xor(ct_mid.c, pt_last.c, residue, out + CTS_BLOCK_SIZE);
+
+ /* Restore the iv needed by the second last block */
+ memcpy(ctx->iv, mid_iv.c, CTS_BLOCK_SIZE);
+
+ /*
+ * Decrypt the second last plaintext block now that we have rebuilt the
+ * ciphertext.
+ */
+ if (!ctx->hw->cipher(ctx, out, ct_mid.c, CTS_BLOCK_SIZE))
+ return 0;
+
+ /* The returned iv is the C(n) block */
+ memcpy(ctx->iv, cn.c, CTS_BLOCK_SIZE);
+ return len + CTS_BLOCK_SIZE + residue;
+}
+
+static size_t cts128_cs3_encrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
+ unsigned char *out, size_t len)
+{
+ aligned_16bytes tmp_in;
+ size_t residue;
+
+ if (len < CTS_BLOCK_SIZE) /* CS3 requires at least one block */
+ return 0;
+
+ /* If we only have one block then just process the aligned block */
+ if (len == CTS_BLOCK_SIZE)
+ return ctx->hw->cipher(ctx, out, in, len) ? len : 0;
+
+ residue = len % CTS_BLOCK_SIZE;
+ if (residue == 0)
+ residue = CTS_BLOCK_SIZE;
+ len -= residue;
+
+ if (!ctx->hw->cipher(ctx, out, in, len))
+ return 0;
+
+ in += len;
+ out += len;
+
+ memset(tmp_in.c, 0, sizeof(tmp_in));
+ memcpy(tmp_in.c, in, residue);
+ memcpy(out, out - CTS_BLOCK_SIZE, residue);
+ if (!ctx->hw->cipher(ctx, out - CTS_BLOCK_SIZE, tmp_in.c, CTS_BLOCK_SIZE))
+ return 0;
+ return len + residue;
+}
+
+/*
+ * Note:
+ * The cipher text (in) is of the form C(0), C(1), ., C(n), C(n-1)* where
+ * C(n) is a full block and C(n-1)* can be a partial block
+ * (but could be a full block).
+ * This means that the output plaintext (out) needs to swap the plaintext of
+ * the last two decoded ciphertext blocks.
+ */
+static size_t cts128_cs3_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
+ unsigned char *out, size_t len)
+{
+ aligned_16bytes mid_iv, ct_mid, cn, pt_last;
+ size_t residue;
+
+ if (len < CTS_BLOCK_SIZE) /* CS3 requires at least one block */
+ return 0;
+
+ /* If we only have one block then just process the aligned block */
+ if (len == CTS_BLOCK_SIZE)
+ return ctx->hw->cipher(ctx, out, in, len) ? len : 0;
+
+ /* Process blocks at the start - but leave the last 2 blocks */
+ residue = len % CTS_BLOCK_SIZE;
+ if (residue == 0)
+ residue = CTS_BLOCK_SIZE;
+ len -= CTS_BLOCK_SIZE + residue;
+
+ if (len > 0) {
+ if (!ctx->hw->cipher(ctx, out, in, len))
+ return 0;
+ in += len;
+ out += len;
+ }
+ /* Save the iv that will be used by the second last block */
+ memcpy(mid_iv.c, ctx->iv, CTS_BLOCK_SIZE);
+ /* Save the C(n) block : For CS3 it is C(1)||...||C(n-2)||C(n)||C(n-1)* */
+ memcpy(cn.c, in, CTS_BLOCK_SIZE);
+
+ /* Decrypt the C(n) block first using an iv of zero */
+ memset(ctx->iv, 0, CTS_BLOCK_SIZE);
+ if (!ctx->hw->cipher(ctx, pt_last.c, in, CTS_BLOCK_SIZE))
+ return 0;
+
+ /*
+ * Rebuild the ciphertext of C(n-1) as a combination of
+ * the decrypted C(n) block + replace the start with the ciphertext bytes
+ * of the partial last block.
+ */
+ memcpy(ct_mid.c, in + CTS_BLOCK_SIZE, residue);
+ if (residue != CTS_BLOCK_SIZE)
+ memcpy(ct_mid.c + residue, pt_last.c + residue, CTS_BLOCK_SIZE - residue);
+ /*
+ * Restore the last partial ciphertext block.
+ * Now that we have the cipher text of the second last block, apply
+ * that to the partial plaintext end block. We have already decrypted the
+ * block using an IV of zero. For decryption the IV is just XORed after
+ * doing an AES block - so just XOR in the ciphertext.
+ */
+ do_xor(ct_mid.c, pt_last.c, residue, out + CTS_BLOCK_SIZE);
+
+ /* Restore the iv needed by the second last block */
+ memcpy(ctx->iv, mid_iv.c, CTS_BLOCK_SIZE);
+ /*
+ * Decrypt the second last plaintext block now that we have rebuilt the
+ * ciphertext.
+ */
+ if (!ctx->hw->cipher(ctx, out, ct_mid.c, CTS_BLOCK_SIZE))
+ return 0;
+
+ /* The returned iv is the C(n) block */
+ memcpy(ctx->iv, cn.c, CTS_BLOCK_SIZE);
+ return len + CTS_BLOCK_SIZE + residue;
+}
+
+static size_t cts128_cs2_encrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
+ unsigned char *out, size_t len)
+{
+ if (len % CTS_BLOCK_SIZE == 0) {
+ /* If there are no partial blocks then it is the same as CBC mode */
+ if (!ctx->hw->cipher(ctx, out, in, len))
+ return 0;
+ return len;
+ }
+ /* For partial blocks CS2 is equivalent to CS3 */
+ return cts128_cs3_encrypt(ctx, in, out, len);
+}
+
+static size_t cts128_cs2_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
+ unsigned char *out, size_t len)
+{
+ if (len % CTS_BLOCK_SIZE == 0) {
+ /* If there are no partial blocks then it is the same as CBC mode */
+ if (!ctx->hw->cipher(ctx, out, in, len))
+ return 0;
+ return len;
+ }
+ /* For partial blocks CS2 is equivalent to CS3 */
+ return cts128_cs3_decrypt(ctx, in, out, len);
+}
+
+int ossl_cipher_cbc_cts_block_update(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in,
+ size_t inl)
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ size_t sz = 0;
+
+ if (inl < CTS_BLOCK_SIZE) /* There must be at least one block for CTS mode */
+ return 0;
+ if (outsize < inl)
+ return 0;
+ if (out == NULL) {
+ *outl = inl;
+ return 1;
+ }
+
+ /*
+ * Return an error if the update is called multiple times, only one shot
+ * is supported.
+ */
+ if (ctx->updated == 1)
+ return 0;
+
+ if (ctx->enc) {
+ if (ctx->cts_mode == CTS_CS1)
+ sz = cts128_cs1_encrypt(ctx, in, out, inl);
+ else if (ctx->cts_mode == CTS_CS2)
+ sz = cts128_cs2_encrypt(ctx, in, out, inl);
+ else if (ctx->cts_mode == CTS_CS3)
+ sz = cts128_cs3_encrypt(ctx, in, out, inl);
+ } else {
+ if (ctx->cts_mode == CTS_CS1)
+ sz = cts128_cs1_decrypt(ctx, in, out, inl);
+ else if (ctx->cts_mode == CTS_CS2)
+ sz = cts128_cs2_decrypt(ctx, in, out, inl);
+ else if (ctx->cts_mode == CTS_CS3)
+ sz = cts128_cs3_decrypt(ctx, in, out, inl);
+ }
+ if (sz == 0)
+ return 0;
+ ctx->updated = 1; /* Stop multiple updates being allowed */
+ *outl = sz;
+ return 1;
+}
+
+int ossl_cipher_cbc_cts_block_final(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ *outl = 0;
+ return 1;
+}
diff --git a/providers/implementations/ciphers/cipher_cts.h b/providers/implementations/ciphers/cipher_cts.h
new file mode 100644
index 000000000000..9473fbde886c
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_cts.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "crypto/evp.h"
+
+/* NOTE: The underlying block cipher is CBC so we reuse most of the code */
+#define IMPLEMENT_cts_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \
+ blkbits, ivbits, typ) \
+static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lcmode##_get_params; \
+static int alg##_cts_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
+{ \
+ return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
+ flags, kbits, blkbits, ivbits); \
+} \
+const OSSL_DISPATCH ossl_##alg##kbits##lcmode##_cts_functions[] = { \
+ { OSSL_FUNC_CIPHER_NEWCTX, \
+ (void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \
+ { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void)) alg##_cbc_cts_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void)) alg##_cbc_cts_dinit }, \
+ { OSSL_FUNC_CIPHER_UPDATE, \
+ (void (*)(void)) ossl_cipher_cbc_cts_block_update }, \
+ { OSSL_FUNC_CIPHER_FINAL, \
+ (void (*)(void)) ossl_cipher_cbc_cts_block_final }, \
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_cipher_generic_cipher }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, \
+ (void (*)(void)) alg##_cts_##kbits##_##lcmode##_get_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
+ (void (*)(void)) alg##_cbc_cts_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void)) alg##_cbc_cts_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void)) alg##_cbc_cts_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void)) alg##_cbc_cts_settable_ctx_params }, \
+ { 0, NULL } \
+};
+
+OSSL_FUNC_cipher_update_fn ossl_cipher_cbc_cts_block_update;
+OSSL_FUNC_cipher_final_fn ossl_cipher_cbc_cts_block_final;
+
+const char *ossl_cipher_cbc_cts_mode_id2name(unsigned int id);
+int ossl_cipher_cbc_cts_mode_name2id(const char *name);
diff --git a/providers/implementations/ciphers/cipher_des.c b/providers/implementations/ciphers/cipher_des.c
new file mode 100644
index 000000000000..c6d13466f79d
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_des.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/rand.h>
+#include <openssl/proverr.h>
+#include "prov/ciphercommon.h"
+#include "cipher_des.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+#define DES_FLAGS PROV_CIPHER_FLAG_RAND_KEY
+
+static OSSL_FUNC_cipher_freectx_fn des_freectx;
+static OSSL_FUNC_cipher_encrypt_init_fn des_einit;
+static OSSL_FUNC_cipher_decrypt_init_fn des_dinit;
+static OSSL_FUNC_cipher_get_ctx_params_fn des_get_ctx_params;
+static OSSL_FUNC_cipher_gettable_ctx_params_fn des_gettable_ctx_params;
+
+static void *des_newctx(void *provctx, size_t kbits, size_t blkbits,
+ size_t ivbits, unsigned int mode, uint64_t flags,
+ const PROV_CIPHER_HW *hw)
+{
+ PROV_DES_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx != NULL)
+ ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags,
+ hw, provctx);
+ return ctx;
+}
+
+static void *des_dupctx(void *ctx)
+{
+ PROV_DES_CTX *in = (PROV_DES_CTX *)ctx;
+ PROV_DES_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ret = OPENSSL_malloc(sizeof(*ret));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ in->base.hw->copyctx(&ret->base, &in->base);
+
+ return ret;
+}
+
+static void des_freectx(void *vctx)
+{
+ PROV_DES_CTX *ctx = (PROV_DES_CTX *)vctx;
+
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static int des_init(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[], int enc)
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ ctx->num = 0;
+ ctx->bufsz = 0;
+ ctx->enc = enc;
+
+ if (iv != NULL) {
+ if (!ossl_cipher_generic_initiv(ctx, iv, ivlen))
+ return 0;
+ } else if (ctx->iv_set) {
+ /* reset IV to keep compatibility with 1.1.1 */
+ memcpy(ctx->iv, ctx->oiv, ctx->ivlen);
+ }
+
+ if (key != NULL) {
+ if (keylen != ctx->keylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ if (!ctx->hw->init(ctx, key, keylen))
+ return 0;
+ }
+ return ossl_cipher_generic_set_ctx_params(ctx, params);
+}
+
+static int des_einit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return des_init(vctx, key, keylen, iv, ivlen, params, 1);
+}
+
+static int des_dinit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return des_init(vctx, key, keylen, iv, ivlen, params, 0);
+}
+
+static int des_generatekey(PROV_CIPHER_CTX *ctx, void *ptr)
+{
+
+ DES_cblock *deskey = ptr;
+ size_t kl = ctx->keylen;
+
+ if (kl == 0 || RAND_priv_bytes_ex(ctx->libctx, ptr, kl, 0) <= 0)
+ return 0;
+ DES_set_odd_parity(deskey);
+ return 1;
+}
+
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(des)
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_RANDOM_KEY, NULL, 0),
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(des)
+
+static int des_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ OSSL_PARAM *p;
+
+ if (!ossl_cipher_generic_get_ctx_params(vctx, params))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_RANDOM_KEY);
+ if (p != NULL && !des_generatekey(ctx, p->data)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GENERATE_KEY);
+ return 0;
+ }
+ return 1;
+}
+
+#define IMPLEMENT_des_cipher(type, lcmode, UCMODE, flags, \
+ kbits, blkbits, ivbits, block) \
+static OSSL_FUNC_cipher_newctx_fn type##_##lcmode##_newctx; \
+static void *des_##lcmode##_newctx(void *provctx) \
+{ \
+ return des_newctx(provctx, kbits, blkbits, ivbits, \
+ EVP_CIPH_##UCMODE##_MODE, flags, \
+ ossl_prov_cipher_hw_des_##lcmode()); \
+} \
+static OSSL_FUNC_cipher_get_params_fn des_##lcmode##_get_params; \
+static int des_##lcmode##_get_params(OSSL_PARAM params[]) \
+{ \
+ return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
+ flags, kbits, blkbits, ivbits); \
+} \
+const OSSL_DISPATCH ossl_##des_##lcmode##_functions[] = { \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))des_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))des_dinit }, \
+ { OSSL_FUNC_CIPHER_UPDATE, \
+ (void (*)(void))ossl_cipher_generic_##block##_update }, \
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_cipher_generic_##block##_final },\
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_cipher_generic_cipher }, \
+ { OSSL_FUNC_CIPHER_NEWCTX, \
+ (void (*)(void))des_##lcmode##_newctx }, \
+ { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))des_dupctx }, \
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))des_freectx }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, \
+ (void (*)(void))des_##lcmode##_get_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))des_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void))des_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_settable_ctx_params }, \
+ { 0, NULL } \
+}
+
+/* ossl_des_ecb_functions */
+IMPLEMENT_des_cipher(des, ecb, ECB, DES_FLAGS, 64, 64, 0, block);
+/* ossl_des_cbc_functions */
+IMPLEMENT_des_cipher(des, cbc, CBC, DES_FLAGS, 64, 64, 64, block);
+/* ossl_des_ofb64_functions */
+IMPLEMENT_des_cipher(des, ofb64, OFB, DES_FLAGS, 64, 8, 64, stream);
+/* ossl_des_cfb64_functions */
+IMPLEMENT_des_cipher(des, cfb64, CFB, DES_FLAGS, 64, 8, 64, stream);
+/* ossl_des_cfb1_functions */
+IMPLEMENT_des_cipher(des, cfb1, CFB, DES_FLAGS, 64, 8, 64, stream);
+/* ossl_des_cfb8_functions */
+IMPLEMENT_des_cipher(des, cfb8, CFB, DES_FLAGS, 64, 8, 64, stream);
diff --git a/providers/implementations/ciphers/cipher_des.h b/providers/implementations/ciphers/cipher_des.h
new file mode 100644
index 000000000000..ad10f63d8b16
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_des.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/des.h>
+#include "crypto/des_platform.h"
+
+#define TDES_FLAGS 0
+
+typedef struct prov_des_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ DES_key_schedule ks;
+ } dks;
+ union {
+ void (*cbc) (const void *, void *, size_t,
+ const DES_key_schedule *, unsigned char *);
+ } dstream;
+
+} PROV_DES_CTX;
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_des_cbc(void);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_des_ecb(void);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_des_ofb64(void);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_des_cfb64(void);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_des_cfb1(void);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_des_cfb8(void);
diff --git a/providers/implementations/ciphers/cipher_des_hw.c b/providers/implementations/ciphers/cipher_des_hw.c
new file mode 100644
index 000000000000..a77fcc681a4a
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_des_hw.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include "prov/ciphercommon.h"
+#include "cipher_des.h"
+
+static int cipher_hw_des_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_DES_CTX *dctx = (PROV_DES_CTX *)ctx;
+ DES_cblock *deskey = (DES_cblock *)key;
+ DES_key_schedule *ks = &dctx->dks.ks;
+
+ dctx->dstream.cbc = NULL;
+#if defined(SPARC_DES_CAPABLE)
+ if (SPARC_DES_CAPABLE) {
+ if (ctx->mode == EVP_CIPH_CBC_MODE) {
+ des_t4_key_expand(&deskey[0], ks);
+ dctx->dstream.cbc = ctx->enc ? des_t4_cbc_encrypt :
+ des_t4_cbc_decrypt;
+ return 1;
+ }
+ }
+#endif
+ DES_set_key_unchecked(deskey, ks);
+ return 1;
+}
+
+static void cipher_hw_des_copyctx(PROV_CIPHER_CTX *dst,
+ const PROV_CIPHER_CTX *src)
+{
+ PROV_DES_CTX *sctx = (PROV_DES_CTX *)src;
+ PROV_DES_CTX *dctx = (PROV_DES_CTX *)dst;
+
+ *dctx = *sctx;
+ dst->ks = &dctx->dks.ks;
+}
+
+static int cipher_hw_des_ecb_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ size_t i, bl = ctx->blocksize;
+ DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
+
+ if (len < bl)
+ return 1;
+ for (i = 0, len -= bl; i <= len; i += bl)
+ DES_ecb_encrypt((const_DES_cblock *)(in + i),
+ (const_DES_cblock *)(out + i), key, ctx->enc);
+ return 1;
+}
+
+static int cipher_hw_des_cbc_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ PROV_DES_CTX *dctx = (PROV_DES_CTX *)ctx;
+ DES_key_schedule *key = &(dctx->dks.ks);
+
+ if (dctx->dstream.cbc != NULL) {
+ (*dctx->dstream.cbc) (in, out, len, key, ctx->iv);
+ return 1;
+ }
+
+ while (len >= MAXCHUNK) {
+ DES_ncbc_encrypt(in, out, MAXCHUNK, key, (DES_cblock *)ctx->iv,
+ ctx->enc);
+ len -= MAXCHUNK;
+ in += MAXCHUNK;
+ out += MAXCHUNK;
+ }
+ if (len > 0)
+ DES_ncbc_encrypt(in, out, (long)len, key, (DES_cblock *)ctx->iv,
+ ctx->enc);
+ return 1;
+}
+
+static int cipher_hw_des_ofb64_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ int num = ctx->num;
+ DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
+
+ while (len >= MAXCHUNK) {
+ DES_ofb64_encrypt(in, out, MAXCHUNK, key, (DES_cblock *)ctx->iv, &num);
+ len -= MAXCHUNK;
+ in += MAXCHUNK;
+ out += MAXCHUNK;
+ }
+ if (len > 0) {
+ DES_ofb64_encrypt(in, out, (long)len, key, (DES_cblock *)ctx->iv, &num);
+ }
+ ctx->num = num;
+ return 1;
+}
+
+static int cipher_hw_des_cfb64_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ size_t chunk = MAXCHUNK;
+ DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
+ int num = ctx->num;
+
+ if (len < chunk)
+ chunk = len;
+ while (len > 0 && len >= chunk) {
+ DES_cfb64_encrypt(in, out, (long)chunk, key, (DES_cblock *)ctx->iv,
+ &num, ctx->enc);
+ len -= chunk;
+ in += chunk;
+ out += chunk;
+ if (len < chunk)
+ chunk = len;
+ }
+ ctx->num = num;
+ return 1;
+}
+
+/*
+ * Although we have a CFB-r implementation for DES, it doesn't pack the right
+ * way, so wrap it here
+ */
+static int cipher_hw_des_cfb1_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ size_t n, chunk = MAXCHUNK / 8;
+ DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
+ unsigned char c[1], d[1];
+
+ if (inl < chunk)
+ chunk = inl;
+
+ while (inl && inl >= chunk) {
+ for (n = 0; n < chunk * 8; ++n) {
+ c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0;
+ DES_cfb_encrypt(c, d, 1, 1, key, (DES_cblock *)ctx->iv, ctx->enc);
+ out[n / 8] =
+ (out[n / 8] & ~(0x80 >> (unsigned int)(n % 8))) |
+ ((d[0] & 0x80) >> (unsigned int)(n % 8));
+ }
+ inl -= chunk;
+ in += chunk;
+ out += chunk;
+ if (inl < chunk)
+ chunk = inl;
+ }
+
+ return 1;
+}
+
+static int cipher_hw_des_cfb8_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
+
+ while (inl >= MAXCHUNK) {
+ DES_cfb_encrypt(in, out, 8, (long)MAXCHUNK, key,
+ (DES_cblock *)ctx->iv, ctx->enc);
+ inl -= MAXCHUNK;
+ in += MAXCHUNK;
+ out += MAXCHUNK;
+ }
+ if (inl > 0)
+ DES_cfb_encrypt(in, out, 8, (long)inl, key,
+ (DES_cblock *)ctx->iv, ctx->enc);
+ return 1;
+}
+
+#define PROV_CIPHER_HW_des_mode(mode) \
+static const PROV_CIPHER_HW des_##mode = { \
+ cipher_hw_des_initkey, \
+ cipher_hw_des_##mode##_cipher, \
+ cipher_hw_des_copyctx \
+}; \
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_des_##mode(void) \
+{ \
+ return &des_##mode; \
+}
+
+PROV_CIPHER_HW_des_mode(ecb)
+PROV_CIPHER_HW_des_mode(cbc)
+PROV_CIPHER_HW_des_mode(ofb64)
+PROV_CIPHER_HW_des_mode(cfb64)
+PROV_CIPHER_HW_des_mode(cfb1)
+PROV_CIPHER_HW_des_mode(cfb8)
diff --git a/providers/implementations/ciphers/cipher_desx.c b/providers/implementations/ciphers/cipher_desx.c
new file mode 100644
index 000000000000..41596554435e
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_desx.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_tdes_default.h"
+#include "prov/implementations.h"
+
+/* desx_cbc_functions */
+IMPLEMENT_tdes_cipher(desx, DESX, cbc, CBC, TDES_FLAGS, 64*3, 64, 64, block);
+
diff --git a/providers/implementations/ciphers/cipher_desx_hw.c b/providers/implementations/ciphers/cipher_desx_hw.c
new file mode 100644
index 000000000000..7dc4c50ef55a
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_desx_hw.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/des.h>
+#include "cipher_tdes_default.h"
+
+/*
+ * Note the PROV_TDES_CTX has been used for the DESX cipher, just to reduce
+ * code size.
+ */
+#define ks1 tks.ks[0]
+#define ks2 tks.ks[1].ks[0].cblock
+#define ks3 tks.ks[2].ks[0].cblock
+
+static int cipher_hw_desx_cbc_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
+ DES_cblock *deskey = (DES_cblock *)key;
+
+ DES_set_key_unchecked(deskey, &tctx->ks1);
+ memcpy(&tctx->ks2, &key[8], 8);
+ memcpy(&tctx->ks3, &key[16], 8);
+
+ return 1;
+}
+
+static void cipher_hw_desx_copyctx(PROV_CIPHER_CTX *dst,
+ const PROV_CIPHER_CTX *src)
+{
+ PROV_TDES_CTX *sctx = (PROV_TDES_CTX *)src;
+ PROV_TDES_CTX *dctx = (PROV_TDES_CTX *)dst;
+
+ *dctx = *sctx;
+ dst->ks = &dctx->tks.ks;
+}
+
+static int cipher_hw_desx_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
+
+ while (inl >= MAXCHUNK) {
+ DES_xcbc_encrypt(in, out, (long)MAXCHUNK, &tctx->ks1,
+ (DES_cblock *)ctx->iv, &tctx->ks2, &tctx->ks3,
+ ctx->enc);
+ inl -= MAXCHUNK;
+ in += MAXCHUNK;
+ out += MAXCHUNK;
+ }
+ if (inl > 0)
+ DES_xcbc_encrypt(in, out, (long)inl, &tctx->ks1,
+ (DES_cblock *)ctx->iv, &tctx->ks2, &tctx->ks3,
+ ctx->enc);
+ return 1;
+}
+
+static const PROV_CIPHER_HW desx_cbc =
+{
+ cipher_hw_desx_cbc_initkey,
+ cipher_hw_desx_cbc,
+ cipher_hw_desx_copyctx
+};
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_tdes_desx_cbc(void)
+{
+ return &desx_cbc;
+}
diff --git a/providers/implementations/ciphers/cipher_idea.c b/providers/implementations/ciphers/cipher_idea.c
new file mode 100644
index 000000000000..bc716290a48a
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_idea.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * IDEA low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
+/* Dispatch functions for Idea cipher modes ecb, cbc, ofb, cfb */
+
+#include "cipher_idea.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+static OSSL_FUNC_cipher_freectx_fn idea_freectx;
+static OSSL_FUNC_cipher_dupctx_fn idea_dupctx;
+
+static void idea_freectx(void *vctx)
+{
+ PROV_IDEA_CTX *ctx = (PROV_IDEA_CTX *)vctx;
+
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static void *idea_dupctx(void *ctx)
+{
+ PROV_IDEA_CTX *in = (PROV_IDEA_CTX *)ctx;
+ PROV_IDEA_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ret = OPENSSL_malloc(sizeof(*ret));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ *ret = *in;
+
+ return ret;
+}
+
+/* ossl_idea128ecb_functions */
+IMPLEMENT_generic_cipher(idea, IDEA, ecb, ECB, 0, 128, 64, 0, block)
+/* ossl_idea128cbc_functions */
+IMPLEMENT_generic_cipher(idea, IDEA, cbc, CBC, 0, 128, 64, 64, block)
+/* ossl_idea128ofb64_functions */
+IMPLEMENT_generic_cipher(idea, IDEA, ofb64, OFB, 0, 128, 8, 64, stream)
+/* ossl_idea128cfb64_functions */
+IMPLEMENT_generic_cipher(idea, IDEA, cfb64, CFB, 0, 128, 8, 64, stream)
diff --git a/providers/implementations/ciphers/cipher_idea.h b/providers/implementations/ciphers/cipher_idea.h
new file mode 100644
index 000000000000..212efa8af575
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_idea.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/idea.h>
+#include "prov/ciphercommon.h"
+
+typedef struct prov_idea_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ IDEA_KEY_SCHEDULE ks;
+ } ks;
+} PROV_IDEA_CTX;
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_idea_cbc(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_idea_ecb(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_idea_ofb64(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_idea_cfb64(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_idea_hw.c b/providers/implementations/ciphers/cipher_idea_hw.c
new file mode 100644
index 000000000000..1c451b77edc4
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_idea_hw.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * IDEA low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_idea.h"
+
+static int cipher_hw_idea_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_IDEA_CTX *ictx = (PROV_IDEA_CTX *)ctx;
+ IDEA_KEY_SCHEDULE *ks = &(ictx->ks.ks);
+
+ if (ctx->enc
+ || ctx->mode == EVP_CIPH_OFB_MODE
+ || ctx->mode == EVP_CIPH_CFB_MODE) {
+ IDEA_set_encrypt_key(key, ks);
+ } else {
+ IDEA_KEY_SCHEDULE tmp;
+
+ IDEA_set_encrypt_key(key, &tmp);
+ IDEA_set_decrypt_key(&tmp, ks);
+ OPENSSL_cleanse((unsigned char *)&tmp, sizeof(IDEA_KEY_SCHEDULE));
+ }
+ return 1;
+}
+
+# define PROV_CIPHER_HW_idea_mode_ex(mode, UCMODE, fname) \
+IMPLEMENT_CIPHER_HW_##UCMODE(mode, idea, PROV_IDEA_CTX, IDEA_KEY_SCHEDULE, \
+ fname) \
+static const PROV_CIPHER_HW idea_##mode = { \
+ cipher_hw_idea_initkey, \
+ cipher_hw_idea_##mode##_cipher \
+}; \
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_idea_##mode(size_t keybits) \
+{ \
+ return &idea_##mode; \
+}
+
+# define PROV_CIPHER_HW_idea_mode(mode, UCMODE) \
+ PROV_CIPHER_HW_idea_mode_ex(mode, UCMODE, IDEA_##mode)
+
+PROV_CIPHER_HW_idea_mode(cbc, CBC)
+PROV_CIPHER_HW_idea_mode(ofb64, OFB)
+PROV_CIPHER_HW_idea_mode(cfb64, CFB)
+/*
+ * IDEA_ecb_encrypt() does not have a enc parameter - so we create a macro
+ * that ignores this parameter when IMPLEMENT_CIPHER_HW_ecb() is called.
+ */
+#define IDEA2_ecb_encrypt(in, out, ks, enc) IDEA_ecb_encrypt(in, out, ks)
+
+PROV_CIPHER_HW_idea_mode_ex(ecb, ECB, IDEA2_ecb)
diff --git a/providers/implementations/ciphers/cipher_null.c b/providers/implementations/ciphers/cipher_null.c
new file mode 100644
index 000000000000..0df97a7f8bc3
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_null.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/proverr.h>
+#include "prov/implementations.h"
+#include "prov/ciphercommon.h"
+#include "prov/providercommon.h"
+
+typedef struct prov_cipher_null_ctx_st {
+ int enc;
+ size_t tlsmacsize;
+ const unsigned char *tlsmac;
+} PROV_CIPHER_NULL_CTX;
+
+static OSSL_FUNC_cipher_newctx_fn null_newctx;
+static void *null_newctx(void *provctx)
+{
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ return OPENSSL_zalloc(sizeof(PROV_CIPHER_NULL_CTX));
+}
+
+static OSSL_FUNC_cipher_freectx_fn null_freectx;
+static void null_freectx(void *vctx)
+{
+ OPENSSL_free(vctx);
+}
+
+static OSSL_FUNC_cipher_encrypt_init_fn null_einit;
+static int null_einit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ PROV_CIPHER_NULL_CTX *ctx = (PROV_CIPHER_NULL_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ ctx->enc = 1;
+ return 1;
+}
+
+static OSSL_FUNC_cipher_decrypt_init_fn null_dinit;
+static int null_dinit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ if (!ossl_prov_is_running())
+ return 0;
+
+ return 1;
+}
+
+static OSSL_FUNC_cipher_cipher_fn null_cipher;
+static int null_cipher(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in, size_t inl)
+{
+ PROV_CIPHER_NULL_CTX *ctx = (PROV_CIPHER_NULL_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (!ctx->enc && ctx->tlsmacsize > 0) {
+ /*
+ * TLS NULL cipher as per:
+ * https://tools.ietf.org/html/rfc5246#section-6.2.3.1
+ */
+ if (inl < ctx->tlsmacsize)
+ return 0;
+ ctx->tlsmac = in + inl - ctx->tlsmacsize;
+ inl -= ctx->tlsmacsize;
+ }
+ if (outsize < inl)
+ return 0;
+ if (in != out)
+ memcpy(out, in, inl);
+ *outl = inl;
+ return 1;
+}
+
+static OSSL_FUNC_cipher_final_fn null_final;
+static int null_final(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ if (!ossl_prov_is_running())
+ return 0;
+
+ *outl = 0;
+ return 1;
+}
+
+static OSSL_FUNC_cipher_get_params_fn null_get_params;
+static int null_get_params(OSSL_PARAM params[])
+{
+ return ossl_cipher_generic_get_params(params, 0, 0, 0, 8, 0);
+}
+
+static const OSSL_PARAM null_known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
+ { OSSL_CIPHER_PARAM_TLS_MAC, OSSL_PARAM_OCTET_PTR, NULL, 0, OSSL_PARAM_UNMODIFIED },
+ OSSL_PARAM_END
+};
+
+static OSSL_FUNC_cipher_gettable_ctx_params_fn null_gettable_ctx_params;
+static const OSSL_PARAM *null_gettable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *provctx)
+{
+ return null_known_gettable_ctx_params;
+}
+
+static OSSL_FUNC_cipher_get_ctx_params_fn null_get_ctx_params;
+static int null_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_CIPHER_NULL_CTX *ctx = (PROV_CIPHER_NULL_CTX *)vctx;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, 0)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, 0)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS_MAC);
+ if (p != NULL
+ && !OSSL_PARAM_set_octet_ptr(p, ctx->tlsmac, ctx->tlsmacsize)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ return 1;
+}
+
+static const OSSL_PARAM null_known_settable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS_MAC_SIZE, NULL),
+ OSSL_PARAM_END
+};
+
+static OSSL_FUNC_cipher_settable_ctx_params_fn null_settable_ctx_params;
+static const OSSL_PARAM *null_settable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *provctx)
+{
+ return null_known_settable_ctx_params;
+}
+
+
+static OSSL_FUNC_cipher_set_ctx_params_fn null_set_ctx_params;
+static int null_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_CIPHER_NULL_CTX *ctx = (PROV_CIPHER_NULL_CTX *)vctx;
+ const OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLS_MAC_SIZE);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &ctx->tlsmacsize)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+const OSSL_DISPATCH ossl_null_functions[] = {
+ { OSSL_FUNC_CIPHER_NEWCTX,
+ (void (*)(void)) null_newctx },
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) null_freectx },
+ { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) null_newctx },
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))null_einit },
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))null_dinit },
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))null_cipher },
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))null_final },
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))null_cipher },
+ { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void)) null_get_params },
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,
+ (void (*)(void))ossl_cipher_generic_gettable_params },
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))null_get_ctx_params },
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
+ (void (*)(void))null_gettable_ctx_params },
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (void (*)(void))null_set_ctx_params },
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
+ (void (*)(void))null_settable_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/ciphers/cipher_rc2.c b/providers/implementations/ciphers/cipher_rc2.c
new file mode 100644
index 000000000000..106f47e8667a
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_rc2.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for RC2 cipher modes ecb, cbc, ofb, cfb */
+
+/*
+ * RC2 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/proverr.h>
+#include "cipher_rc2.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+#define RC2_40_MAGIC 0xa0
+#define RC2_64_MAGIC 0x78
+#define RC2_128_MAGIC 0x3a
+#define RC2_FLAGS PROV_CIPHER_FLAG_VARIABLE_LENGTH
+
+static OSSL_FUNC_cipher_encrypt_init_fn rc2_einit;
+static OSSL_FUNC_cipher_decrypt_init_fn rc2_dinit;
+static OSSL_FUNC_cipher_freectx_fn rc2_freectx;
+static OSSL_FUNC_cipher_dupctx_fn rc2_dupctx;
+static OSSL_FUNC_cipher_gettable_ctx_params_fn rc2_gettable_ctx_params;
+static OSSL_FUNC_cipher_settable_ctx_params_fn rc2_settable_ctx_params;
+static OSSL_FUNC_cipher_set_ctx_params_fn rc2_set_ctx_params;
+
+static void rc2_freectx(void *vctx)
+{
+ PROV_RC2_CTX *ctx = (PROV_RC2_CTX *)vctx;
+
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static void *rc2_dupctx(void *ctx)
+{
+ PROV_RC2_CTX *in = (PROV_RC2_CTX *)ctx;
+ PROV_RC2_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ret = OPENSSL_malloc(sizeof(*ret));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ *ret = *in;
+
+ return ret;
+}
+
+static int rc2_keybits_to_magic(int keybits)
+{
+ switch (keybits) {
+ case 128:
+ return RC2_128_MAGIC;
+ case 64:
+ return RC2_64_MAGIC;
+ case 40:
+ return RC2_40_MAGIC;
+ }
+ ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_KEY_SIZE);
+ return 0;
+}
+
+static int rc2_magic_to_keybits(int magic)
+{
+ switch (magic) {
+ case RC2_128_MAGIC:
+ return 128;
+ case RC2_64_MAGIC:
+ return 64;
+ case RC2_40_MAGIC:
+ return 40;
+ }
+ ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_KEY_SIZE);
+ return 0;
+}
+
+static int rc2_einit(void *ctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ if (!ossl_cipher_generic_einit(ctx, key, keylen, iv, ivlen, NULL))
+ return 0;
+ return rc2_set_ctx_params(ctx, params);
+}
+
+static int rc2_dinit(void *ctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ if (!ossl_cipher_generic_dinit(ctx, key, keylen, iv, ivlen, NULL))
+ return 0;
+ return rc2_set_ctx_params(ctx, params);
+}
+
+static int rc2_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_RC2_CTX *ctx = (PROV_RC2_CTX *)vctx;
+ OSSL_PARAM *p;
+
+ if (!ossl_cipher_generic_get_ctx_params(vctx, params))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_RC2_KEYBITS);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->key_bits)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS);
+ if (p != NULL) {
+ long num;
+ int i;
+ ASN1_TYPE *type;
+ unsigned char *d = p->data;
+ unsigned char **dd = d == NULL ? NULL : &d;
+
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ if ((type = ASN1_TYPE_new()) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ /* Is this the original IV or the running IV? */
+ num = rc2_keybits_to_magic(ctx->key_bits);
+ if (!ASN1_TYPE_set_int_octetstring(type, num,
+ ctx->base.iv, ctx->base.ivlen)) {
+ ASN1_TYPE_free(type);
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ /*
+ * IF the caller has a buffer, we pray to the gods they got the
+ * size right. There's no way to tell the i2d functions...
+ */
+ i = i2d_ASN1_TYPE(type, dd);
+ if (i >= 0)
+ p->return_size = (size_t)i;
+
+ ASN1_TYPE_free(type);
+ if (i < 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int rc2_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_RC2_CTX *ctx = (PROV_RC2_CTX *)vctx;
+ const OSSL_PARAM *p;
+
+ if (params == NULL)
+ return 1;
+
+ if (!ossl_cipher_var_keylen_set_ctx_params(vctx, params))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_RC2_KEYBITS);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &ctx->key_bits)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS);
+ if (p != NULL) {
+ ASN1_TYPE *type = NULL;
+ long num = 0;
+ const unsigned char *d = p->data;
+ int ret = 1;
+ unsigned char iv[16];
+
+ if (p->data_type != OSSL_PARAM_OCTET_STRING
+ || ctx->base.ivlen > sizeof(iv)
+ || (type = d2i_ASN1_TYPE(NULL, &d, p->data_size)) == NULL
+ || ((size_t)ASN1_TYPE_get_int_octetstring(type, &num, iv,
+ ctx->base.ivlen)
+ != ctx->base.ivlen)
+ || !ossl_cipher_generic_initiv(&ctx->base, iv, ctx->base.ivlen)
+ || (ctx->key_bits = rc2_magic_to_keybits(num)) == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ ret = 0;
+ }
+ ASN1_TYPE_free(type);
+ if (ret == 0)
+ return 0;
+ /*
+ * This code assumes that the caller will call
+ * EVP_CipherInit_ex() with a non NULL key in order to setup a key that
+ * uses the keylen and keybits that were set here.
+ */
+ ctx->base.keylen = ctx->key_bits / 8;
+ }
+ return 1;
+}
+
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(rc2)
+OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_RC2_KEYBITS, NULL),
+OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS, NULL, 0),
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(rc2)
+
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(rc2)
+OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_RC2_KEYBITS, NULL),
+OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS, NULL, 0),
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(rc2)
+
+#define IMPLEMENT_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, blkbits, \
+ ivbits, typ) \
+static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lcmode##_get_params; \
+static int alg##_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
+{ \
+ return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
+ flags, kbits, blkbits, ivbits); \
+} \
+static OSSL_FUNC_cipher_newctx_fn alg##_##kbits##_##lcmode##_newctx; \
+static void * alg##_##kbits##_##lcmode##_newctx(void *provctx) \
+{ \
+ PROV_##UCALG##_CTX *ctx; \
+ if (!ossl_prov_is_running()) \
+ return NULL; \
+ ctx = OPENSSL_zalloc(sizeof(*ctx)); \
+ if (ctx != NULL) { \
+ ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, \
+ EVP_CIPH_##UCMODE##_MODE, flags, \
+ ossl_prov_cipher_hw_##alg##_##lcmode(kbits), \
+ NULL); \
+ ctx->key_bits = kbits; \
+ } \
+ return ctx; \
+} \
+const OSSL_DISPATCH ossl_##alg##kbits##lcmode##_functions[] = { \
+ { OSSL_FUNC_CIPHER_NEWCTX, \
+ (void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \
+ { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))rc2_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))rc2_dinit }, \
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_cipher_generic_##typ##_update },\
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_cipher_generic_##typ##_final }, \
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_cipher_generic_cipher }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, \
+ (void (*)(void)) alg##_##kbits##_##lcmode##_get_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
+ (void (*)(void))rc2_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void))rc2_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void))rc2_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))rc2_settable_ctx_params }, \
+ { 0, NULL } \
+};
+
+/* ossl_rc2128ecb_functions */
+IMPLEMENT_cipher(rc2, RC2, ecb, ECB, RC2_FLAGS, 128, 64, 0, block)
+/* ossl_rc2128cbc_functions */
+IMPLEMENT_cipher(rc2, RC2, cbc, CBC, RC2_FLAGS, 128, 64, 64, block)
+/* ossl_rc240cbc_functions */
+IMPLEMENT_cipher(rc2, RC2, cbc, CBC, RC2_FLAGS, 40, 64, 64, block)
+/* ossl_rc264cbc_functions */
+IMPLEMENT_cipher(rc2, RC2, cbc, CBC, RC2_FLAGS, 64, 64, 64, block)
+
+/* ossl_rc2128ofb128_functions */
+IMPLEMENT_cipher(rc2, RC2, ofb128, OFB, RC2_FLAGS, 128, 8, 64, stream)
+/* ossl_rc2128cfb128_functions */
+IMPLEMENT_cipher(rc2, RC2, cfb128, CFB, RC2_FLAGS, 128, 8, 64, stream)
diff --git a/providers/implementations/ciphers/cipher_rc2.h b/providers/implementations/ciphers/cipher_rc2.h
new file mode 100644
index 000000000000..7a4bea5ac404
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_rc2.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/rc2.h>
+#include "prov/ciphercommon.h"
+
+typedef struct prov_rc2_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ RC2_KEY ks;
+ } ks;
+ size_t key_bits;
+} PROV_RC2_CTX;
+
+#define ossl_prov_cipher_hw_rc2_ofb128 ossl_prov_cipher_hw_rc2_ofb64
+#define ossl_prov_cipher_hw_rc2_cfb128 ossl_prov_cipher_hw_rc2_cfb64
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc2_cbc(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc2_ecb(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc2_ofb64(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc2_cfb64(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_rc2_hw.c b/providers/implementations/ciphers/cipher_rc2_hw.c
new file mode 100644
index 000000000000..da9ff729cda0
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_rc2_hw.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * RC2 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_rc2.h"
+
+static int cipher_hw_rc2_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_RC2_CTX *rctx = (PROV_RC2_CTX *)ctx;
+ RC2_KEY *ks = &(rctx->ks.ks);
+
+ RC2_set_key(ks, (int)ctx->keylen, key, (int)rctx->key_bits);
+ return 1;
+}
+
+# define PROV_CIPHER_HW_rc2_mode(mode, UCMODE) \
+IMPLEMENT_CIPHER_HW_##UCMODE(mode, rc2, PROV_RC2_CTX, RC2_KEY, \
+ RC2_##mode) \
+static const PROV_CIPHER_HW rc2_##mode = { \
+ cipher_hw_rc2_initkey, \
+ cipher_hw_rc2_##mode##_cipher \
+}; \
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc2_##mode(size_t keybits) \
+{ \
+ return &rc2_##mode; \
+}
+
+PROV_CIPHER_HW_rc2_mode(cbc, CBC)
+PROV_CIPHER_HW_rc2_mode(ecb, ECB)
+PROV_CIPHER_HW_rc2_mode(ofb64, OFB)
+PROV_CIPHER_HW_rc2_mode(cfb64, CFB)
diff --git a/providers/implementations/ciphers/cipher_rc4.c b/providers/implementations/ciphers/cipher_rc4.c
new file mode 100644
index 000000000000..a548beafaf5f
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_rc4.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for RC4 ciphers */
+
+/*
+ * RC4 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_rc4.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+#define RC4_FLAGS PROV_CIPHER_FLAG_VARIABLE_LENGTH
+
+static OSSL_FUNC_cipher_encrypt_init_fn rc4_einit;
+static OSSL_FUNC_cipher_decrypt_init_fn rc4_dinit;
+static OSSL_FUNC_cipher_freectx_fn rc4_freectx;
+static OSSL_FUNC_cipher_dupctx_fn rc4_dupctx;
+
+static void rc4_freectx(void *vctx)
+{
+ PROV_RC4_CTX *ctx = (PROV_RC4_CTX *)vctx;
+
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static void *rc4_dupctx(void *ctx)
+{
+ PROV_RC4_CTX *in = (PROV_RC4_CTX *)ctx;
+ PROV_RC4_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ret = OPENSSL_malloc(sizeof(*ret));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ *ret = *in;
+
+ return ret;
+}
+
+static int rc4_einit(void *ctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ if (!ossl_cipher_generic_einit(ctx, key, keylen, iv, ivlen, NULL))
+ return 0;
+ return ossl_cipher_var_keylen_set_ctx_params(ctx, params);
+}
+
+static int rc4_dinit(void *ctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ if (!ossl_cipher_generic_dinit(ctx, key, keylen, iv, ivlen, NULL))
+ return 0;
+ return ossl_cipher_var_keylen_set_ctx_params(ctx, params);
+}
+
+#define IMPLEMENT_cipher(alg, UCALG, flags, kbits, blkbits, ivbits, typ) \
+static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_get_params; \
+static int alg##_##kbits##_get_params(OSSL_PARAM params[]) \
+{ \
+ return ossl_cipher_generic_get_params(params, 0, flags, \
+ kbits, blkbits, ivbits); \
+} \
+static OSSL_FUNC_cipher_newctx_fn alg##_##kbits##_newctx; \
+static void * alg##_##kbits##_newctx(void *provctx) \
+{ \
+ PROV_##UCALG##_CTX *ctx; \
+ if (!ossl_prov_is_running()) \
+ return NULL; \
+ ctx = OPENSSL_zalloc(sizeof(*ctx)); \
+ if (ctx != NULL) { \
+ ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, 0, flags, \
+ ossl_prov_cipher_hw_##alg(kbits), NULL); \
+ } \
+ return ctx; \
+} \
+const OSSL_DISPATCH ossl_##alg##kbits##_functions[] = { \
+ { OSSL_FUNC_CIPHER_NEWCTX, \
+ (void (*)(void)) alg##_##kbits##_newctx }, \
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \
+ { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))rc4_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))rc4_dinit }, \
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_cipher_generic_##typ##_update },\
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_cipher_generic_##typ##_final }, \
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_cipher_generic_cipher }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, \
+ (void (*)(void)) alg##_##kbits##_get_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_var_keylen_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_var_keylen_settable_ctx_params }, \
+ { 0, NULL } \
+};
+
+/* ossl_rc440_functions */
+IMPLEMENT_cipher(rc4, RC4, RC4_FLAGS, 40, 8, 0, stream)
+/* ossl_rc4128_functions */
+IMPLEMENT_cipher(rc4, RC4, RC4_FLAGS, 128, 8, 0, stream)
diff --git a/providers/implementations/ciphers/cipher_rc4.h b/providers/implementations/ciphers/cipher_rc4.h
new file mode 100644
index 000000000000..40d822ceb2ef
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_rc4.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/rc4.h>
+#include "prov/ciphercommon.h"
+
+typedef struct prov_rc4_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ RC4_KEY ks;
+ } ks;
+} PROV_RC4_CTX;
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc4(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_rc4_hmac_md5.c b/providers/implementations/ciphers/cipher_rc4_hmac_md5.c
new file mode 100644
index 000000000000..c46c6eab63e0
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_rc4_hmac_md5.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for RC4_HMAC_MD5 cipher */
+
+/*
+ * MD5 and RC4 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/proverr.h>
+#include "cipher_rc4_hmac_md5.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+#define RC4_HMAC_MD5_FLAGS (PROV_CIPHER_FLAG_VARIABLE_LENGTH \
+ | PROV_CIPHER_FLAG_AEAD)
+
+#define RC4_HMAC_MD5_KEY_BITS (16 * 8)
+#define RC4_HMAC_MD5_BLOCK_BITS (1 * 8)
+#define RC4_HMAC_MD5_IV_BITS 0
+#define RC4_HMAC_MD5_MODE 0
+
+#define GET_HW(ctx) ((PROV_CIPHER_HW_RC4_HMAC_MD5 *)ctx->base.hw)
+
+static OSSL_FUNC_cipher_encrypt_init_fn rc4_hmac_md5_einit;
+static OSSL_FUNC_cipher_decrypt_init_fn rc4_hmac_md5_dinit;
+static OSSL_FUNC_cipher_newctx_fn rc4_hmac_md5_newctx;
+static OSSL_FUNC_cipher_freectx_fn rc4_hmac_md5_freectx;
+static OSSL_FUNC_cipher_get_ctx_params_fn rc4_hmac_md5_get_ctx_params;
+static OSSL_FUNC_cipher_gettable_ctx_params_fn rc4_hmac_md5_gettable_ctx_params;
+static OSSL_FUNC_cipher_set_ctx_params_fn rc4_hmac_md5_set_ctx_params;
+static OSSL_FUNC_cipher_settable_ctx_params_fn rc4_hmac_md5_settable_ctx_params;
+static OSSL_FUNC_cipher_get_params_fn rc4_hmac_md5_get_params;
+#define rc4_hmac_md5_gettable_params ossl_cipher_generic_gettable_params
+#define rc4_hmac_md5_update ossl_cipher_generic_stream_update
+#define rc4_hmac_md5_final ossl_cipher_generic_stream_final
+#define rc4_hmac_md5_cipher ossl_cipher_generic_cipher
+
+static void *rc4_hmac_md5_newctx(void *provctx)
+{
+ PROV_RC4_HMAC_MD5_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx != NULL)
+ ossl_cipher_generic_initkey(ctx, RC4_HMAC_MD5_KEY_BITS,
+ RC4_HMAC_MD5_BLOCK_BITS,
+ RC4_HMAC_MD5_IV_BITS,
+ RC4_HMAC_MD5_MODE, RC4_HMAC_MD5_FLAGS,
+ ossl_prov_cipher_hw_rc4_hmac_md5(
+ RC4_HMAC_MD5_KEY_BITS
+ ), NULL);
+ return ctx;
+}
+
+static void rc4_hmac_md5_freectx(void *vctx)
+{
+ PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)vctx;
+
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static int rc4_hmac_md5_einit(void *ctx, const unsigned char *key,
+ size_t keylen, const unsigned char *iv,
+ size_t ivlen, const OSSL_PARAM params[])
+{
+ if (!ossl_cipher_generic_einit(ctx, key, keylen, iv, ivlen, NULL))
+ return 0;
+ return rc4_hmac_md5_set_ctx_params(ctx, params);
+}
+
+static int rc4_hmac_md5_dinit(void *ctx, const unsigned char *key,
+ size_t keylen, const unsigned char *iv,
+ size_t ivlen, const OSSL_PARAM params[])
+{
+ if (!ossl_cipher_generic_dinit(ctx, key, keylen, iv, ivlen, NULL))
+ return 0;
+ return rc4_hmac_md5_set_ctx_params(ctx, params);
+}
+
+static const OSSL_PARAM rc4_hmac_md5_known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL),
+ OSSL_PARAM_END
+};
+const OSSL_PARAM *rc4_hmac_md5_gettable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *provctx)
+{
+ return rc4_hmac_md5_known_gettable_ctx_params;
+}
+
+static int rc4_hmac_md5_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)vctx;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.keylen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.ivlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ return 1;
+}
+
+static const OSSL_PARAM rc4_hmac_md5_known_settable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0),
+ OSSL_PARAM_END
+};
+const OSSL_PARAM *rc4_hmac_md5_settable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *provctx)
+{
+ return rc4_hmac_md5_known_settable_ctx_params;
+}
+
+static int rc4_hmac_md5_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)vctx;
+ const OSSL_PARAM *p;
+ size_t sz;
+
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &sz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (ctx->base.keylen != sz) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &sz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (ctx->base.ivlen != sz) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ sz = GET_HW(ctx)->tls_init(&ctx->base, p->data, p->data_size);
+ if (sz == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA);
+ return 0;
+ }
+ ctx->tls_aad_pad_sz = sz;
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_MAC_KEY);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ GET_HW(ctx)->init_mackey(&ctx->base, p->data, p->data_size);
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLS_VERSION);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_uint(p, &ctx->base.tlsversion)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int rc4_hmac_md5_get_params(OSSL_PARAM params[])
+{
+ return ossl_cipher_generic_get_params(params, RC4_HMAC_MD5_MODE,
+ RC4_HMAC_MD5_FLAGS,
+ RC4_HMAC_MD5_KEY_BITS,
+ RC4_HMAC_MD5_BLOCK_BITS,
+ RC4_HMAC_MD5_IV_BITS);
+}
+
+const OSSL_DISPATCH ossl_rc4_hmac_ossl_md5_functions[] = {
+ { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))rc4_hmac_md5_newctx },
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))rc4_hmac_md5_freectx },
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))rc4_hmac_md5_einit },
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))rc4_hmac_md5_dinit },
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))rc4_hmac_md5_update },
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))rc4_hmac_md5_final },
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))rc4_hmac_md5_cipher },
+ { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))rc4_hmac_md5_get_params },
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,
+ (void (*)(void))rc4_hmac_md5_gettable_params },
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,
+ (void (*)(void))rc4_hmac_md5_get_ctx_params },
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
+ (void (*)(void))rc4_hmac_md5_gettable_ctx_params },
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,
+ (void (*)(void))rc4_hmac_md5_set_ctx_params },
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
+ (void (*)(void))rc4_hmac_md5_settable_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/ciphers/cipher_rc4_hmac_md5.h b/providers/implementations/ciphers/cipher_rc4_hmac_md5.h
new file mode 100644
index 000000000000..1697aabbf39b
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_rc4_hmac_md5.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/rc4.h>
+#include <openssl/md5.h>
+#include "prov/ciphercommon.h"
+
+typedef struct prov_rc4_hmac_md5_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ RC4_KEY ks;
+ } ks;
+ MD5_CTX head, tail, md;
+ size_t payload_length;
+ size_t tls_aad_pad_sz;
+} PROV_RC4_HMAC_MD5_CTX;
+
+typedef struct prov_cipher_hw_rc4_hmac_md5_st {
+ PROV_CIPHER_HW base; /* Must be first */
+ int (*tls_init)(PROV_CIPHER_CTX *ctx, unsigned char *aad, size_t aad_len);
+ void (*init_mackey)(PROV_CIPHER_CTX *ctx, const unsigned char *key,
+ size_t len);
+
+} PROV_CIPHER_HW_RC4_HMAC_MD5;
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc4_hmac_md5(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_rc4_hmac_md5_hw.c b/providers/implementations/ciphers/cipher_rc4_hmac_md5_hw.c
new file mode 100644
index 000000000000..8cce02b1c5af
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_rc4_hmac_md5_hw.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* RC4_HMAC_MD5 cipher implementation */
+
+/*
+ * MD5 and RC4 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_rc4_hmac_md5.h"
+
+#define NO_PAYLOAD_LENGTH ((size_t)-1)
+
+#if defined(RC4_ASM) \
+ && defined(MD5_ASM) \
+ && (defined(__x86_64) \
+ || defined(__x86_64__) \
+ || defined(_M_AMD64) \
+ || defined(_M_X64))
+# define STITCHED_CALL
+# define MOD 32 /* 32 is $MOD from rc4_md5-x86_64.pl */
+#else
+# define rc4_off 0
+# define md5_off 0
+#endif
+
+static int cipher_hw_rc4_hmac_md5_initkey(PROV_CIPHER_CTX *bctx,
+ const uint8_t *key, size_t keylen)
+{
+ PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)bctx;
+
+ RC4_set_key(&ctx->ks.ks, keylen, key);
+ MD5_Init(&ctx->head); /* handy when benchmarking */
+ ctx->tail = ctx->head;
+ ctx->md = ctx->head;
+ ctx->payload_length = NO_PAYLOAD_LENGTH;
+ bctx->removetlsfixed = MD5_DIGEST_LENGTH;
+ return 1;
+}
+
+static int cipher_hw_rc4_hmac_md5_cipher(PROV_CIPHER_CTX *bctx,
+ unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)bctx;
+ RC4_KEY *ks = &ctx->ks.ks;
+
+#if defined(STITCHED_CALL)
+ size_t rc4_off = MOD - 1 - (ks->x & (MOD - 1));
+ size_t md5_off = MD5_CBLOCK - ctx->md.num, blocks;
+ unsigned int l;
+#endif
+ size_t plen = ctx->payload_length;
+
+ if (plen != NO_PAYLOAD_LENGTH && len != (plen + MD5_DIGEST_LENGTH))
+ return 0;
+
+ if (ctx->base.enc) {
+ if (plen == NO_PAYLOAD_LENGTH)
+ plen = len;
+#if defined(STITCHED_CALL)
+ /* cipher has to "fall behind" */
+ if (rc4_off > md5_off)
+ md5_off += MD5_CBLOCK;
+
+ if (plen > md5_off
+ && (blocks = (plen - md5_off) / MD5_CBLOCK)
+ && (OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) {
+ MD5_Update(&ctx->md, in, md5_off);
+ RC4(ks, rc4_off, in, out);
+
+ rc4_md5_enc(ks, in + rc4_off, out + rc4_off,
+ &ctx->md, in + md5_off, blocks);
+ blocks *= MD5_CBLOCK;
+ rc4_off += blocks;
+ md5_off += blocks;
+ ctx->md.Nh += blocks >> 29;
+ ctx->md.Nl += blocks <<= 3;
+ if (ctx->md.Nl < (unsigned int)blocks)
+ ctx->md.Nh++;
+ } else {
+ rc4_off = 0;
+ md5_off = 0;
+ }
+#endif
+ MD5_Update(&ctx->md, in + md5_off, plen - md5_off);
+
+ if (plen != len) { /* "TLS" mode of operation */
+ if (in != out)
+ memcpy(out + rc4_off, in + rc4_off, plen - rc4_off);
+
+ /* calculate HMAC and append it to payload */
+ MD5_Final(out + plen, &ctx->md);
+ ctx->md = ctx->tail;
+ MD5_Update(&ctx->md, out + plen, MD5_DIGEST_LENGTH);
+ MD5_Final(out + plen, &ctx->md);
+ /* encrypt HMAC at once */
+ RC4(ks, len - rc4_off, out + rc4_off, out + rc4_off);
+ } else {
+ RC4(ks, len - rc4_off, in + rc4_off, out + rc4_off);
+ }
+ } else {
+ unsigned char mac[MD5_DIGEST_LENGTH];
+
+#if defined(STITCHED_CALL)
+ /* digest has to "fall behind" */
+ if (md5_off > rc4_off)
+ rc4_off += 2 * MD5_CBLOCK;
+ else
+ rc4_off += MD5_CBLOCK;
+
+ if (len > rc4_off
+ && (blocks = (len - rc4_off) / MD5_CBLOCK)
+ && (OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) {
+ RC4(ks, rc4_off, in, out);
+ MD5_Update(&ctx->md, out, md5_off);
+
+ rc4_md5_enc(ks, in + rc4_off, out + rc4_off,
+ &ctx->md, out + md5_off, blocks);
+ blocks *= MD5_CBLOCK;
+ rc4_off += blocks;
+ md5_off += blocks;
+ l = (ctx->md.Nl + (blocks << 3)) & 0xffffffffU;
+ if (l < ctx->md.Nl)
+ ctx->md.Nh++;
+ ctx->md.Nl = l;
+ ctx->md.Nh += blocks >> 29;
+ } else {
+ md5_off = 0;
+ rc4_off = 0;
+ }
+#endif
+ /* decrypt HMAC at once */
+ RC4(ks, len - rc4_off, in + rc4_off, out + rc4_off);
+ if (plen != NO_PAYLOAD_LENGTH) {
+ /* "TLS" mode of operation */
+ MD5_Update(&ctx->md, out + md5_off, plen - md5_off);
+
+ /* calculate HMAC and verify it */
+ MD5_Final(mac, &ctx->md);
+ ctx->md = ctx->tail;
+ MD5_Update(&ctx->md, mac, MD5_DIGEST_LENGTH);
+ MD5_Final(mac, &ctx->md);
+
+ if (CRYPTO_memcmp(out + plen, mac, MD5_DIGEST_LENGTH))
+ return 0;
+ } else {
+ MD5_Update(&ctx->md, out + md5_off, len - md5_off);
+ }
+ }
+
+ ctx->payload_length = NO_PAYLOAD_LENGTH;
+
+ return 1;
+}
+
+static int cipher_hw_rc4_hmac_md5_tls_init(PROV_CIPHER_CTX *bctx,
+ unsigned char *aad, size_t aad_len)
+{
+ PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)bctx;
+ unsigned int len;
+
+ if (aad_len != EVP_AEAD_TLS1_AAD_LEN)
+ return 0;
+
+ len = aad[aad_len - 2] << 8 | aad[aad_len - 1];
+
+ if (!bctx->enc) {
+ if (len < MD5_DIGEST_LENGTH)
+ return 0;
+ len -= MD5_DIGEST_LENGTH;
+ aad[aad_len - 2] = len >> 8;
+ aad[aad_len - 1] = len;
+ }
+ ctx->payload_length = len;
+ ctx->md = ctx->head;
+ MD5_Update(&ctx->md, aad, aad_len);
+
+ return MD5_DIGEST_LENGTH;
+}
+
+static void cipher_hw_rc4_hmac_md5_init_mackey(PROV_CIPHER_CTX *bctx,
+ const unsigned char *key,
+ size_t len)
+{
+ PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)bctx;
+ unsigned int i;
+ unsigned char hmac_key[64];
+
+ memset(hmac_key, 0, sizeof(hmac_key));
+
+ if (len > (int)sizeof(hmac_key)) {
+ MD5_Init(&ctx->head);
+ MD5_Update(&ctx->head, key, len);
+ MD5_Final(hmac_key, &ctx->head);
+ } else {
+ memcpy(hmac_key, key, len);
+ }
+
+ for (i = 0; i < sizeof(hmac_key); i++)
+ hmac_key[i] ^= 0x36; /* ipad */
+ MD5_Init(&ctx->head);
+ MD5_Update(&ctx->head, hmac_key, sizeof(hmac_key));
+
+ for (i = 0; i < sizeof(hmac_key); i++)
+ hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */
+ MD5_Init(&ctx->tail);
+ MD5_Update(&ctx->tail, hmac_key, sizeof(hmac_key));
+
+ OPENSSL_cleanse(hmac_key, sizeof(hmac_key));
+}
+
+static const PROV_CIPHER_HW_RC4_HMAC_MD5 rc4_hmac_md5_hw = {
+ {
+ cipher_hw_rc4_hmac_md5_initkey,
+ cipher_hw_rc4_hmac_md5_cipher
+ },
+ cipher_hw_rc4_hmac_md5_tls_init,
+ cipher_hw_rc4_hmac_md5_init_mackey
+};
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc4_hmac_md5(size_t keybits)
+{
+ return (PROV_CIPHER_HW *)&rc4_hmac_md5_hw;
+}
diff --git a/providers/implementations/ciphers/cipher_rc4_hw.c b/providers/implementations/ciphers/cipher_rc4_hw.c
new file mode 100644
index 000000000000..09192b5d5e14
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_rc4_hw.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * RC4 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_rc4.h"
+
+static int cipher_hw_rc4_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_RC4_CTX *rctx = (PROV_RC4_CTX *)ctx;
+
+ RC4_set_key(&rctx->ks.ks, keylen, key);
+ return 1;
+}
+
+static int cipher_hw_rc4_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ PROV_RC4_CTX *rctx = (PROV_RC4_CTX *)ctx;
+
+ RC4(&rctx->ks.ks, len, in, out);
+ return 1;
+}
+
+static const PROV_CIPHER_HW rc4_hw = {
+ cipher_hw_rc4_initkey,
+ cipher_hw_rc4_cipher
+};
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc4(size_t keybits)
+{
+ return &rc4_hw;
+}
+
diff --git a/providers/implementations/ciphers/cipher_rc5.c b/providers/implementations/ciphers/cipher_rc5.c
new file mode 100644
index 000000000000..5c7d2b1721c0
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_rc5.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for RC5 cipher modes ecb, cbc, ofb, cfb */
+
+/*
+ * RC5 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/proverr.h>
+#include "cipher_rc5.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+#define RC5_FLAGS PROV_CIPHER_FLAG_VARIABLE_LENGTH
+
+static OSSL_FUNC_cipher_encrypt_init_fn rc5_einit;
+static OSSL_FUNC_cipher_decrypt_init_fn rc5_dinit;
+static OSSL_FUNC_cipher_freectx_fn rc5_freectx;
+static OSSL_FUNC_cipher_dupctx_fn rc5_dupctx;
+OSSL_FUNC_cipher_gettable_ctx_params_fn rc5_gettable_ctx_params;
+OSSL_FUNC_cipher_settable_ctx_params_fn rc5_settable_ctx_params;
+static OSSL_FUNC_cipher_set_ctx_params_fn rc5_set_ctx_params;
+
+static void rc5_freectx(void *vctx)
+{
+ PROV_RC5_CTX *ctx = (PROV_RC5_CTX *)vctx;
+
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static void *rc5_dupctx(void *ctx)
+{
+ PROV_RC5_CTX *in = (PROV_RC5_CTX *)ctx;
+ PROV_RC5_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ret = OPENSSL_malloc(sizeof(*ret));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ *ret = *in;
+
+ return ret;
+}
+
+static int rc5_einit(void *ctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ if (!ossl_cipher_generic_einit(ctx, key, keylen, iv, ivlen, NULL))
+ return 0;
+ return rc5_set_ctx_params(ctx, params);
+}
+
+static int rc5_dinit(void *ctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ if (!ossl_cipher_generic_dinit(ctx, key, keylen, iv, ivlen, NULL))
+ return 0;
+ return rc5_set_ctx_params(ctx, params);
+}
+
+static int rc5_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_RC5_CTX *ctx = (PROV_RC5_CTX *)vctx;
+ const OSSL_PARAM *p;
+
+ if (params == NULL)
+ return 1;
+
+ if (!ossl_cipher_var_keylen_set_ctx_params(vctx, params))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_ROUNDS);
+ if (p != NULL) {
+ unsigned int rounds;
+
+ if (!OSSL_PARAM_get_uint(p, &rounds)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (rounds != RC5_8_ROUNDS
+ && rounds != RC5_12_ROUNDS
+ && rounds != RC5_16_ROUNDS) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS);
+ return 0;
+ }
+ ctx->rounds = rounds;
+ }
+ return 1;
+}
+
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(rc5)
+ OSSL_PARAM_uint(OSSL_CIPHER_PARAM_ROUNDS, NULL),
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(rc5)
+
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(rc5)
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_uint(OSSL_CIPHER_PARAM_ROUNDS, NULL),
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(rc5)
+
+
+static int rc5_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_RC5_CTX *ctx = (PROV_RC5_CTX *)vctx;
+ OSSL_PARAM *p;
+
+ if (!ossl_cipher_generic_get_ctx_params(vctx, params))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_ROUNDS);
+ if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->rounds)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ return 1;
+}
+
+#define IMPLEMENT_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \
+ blkbits, ivbits, typ) \
+static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lcmode##_get_params; \
+static int alg##_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
+{ \
+ return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
+ flags, kbits, blkbits, ivbits); \
+} \
+static OSSL_FUNC_cipher_newctx_fn alg##_##kbits##_##lcmode##_newctx; \
+static void * alg##_##kbits##_##lcmode##_newctx(void *provctx) \
+{ \
+ PROV_##UCALG##_CTX *ctx; \
+ if (!ossl_prov_is_running()) \
+ return NULL; \
+ ctx = OPENSSL_zalloc(sizeof(*ctx)); \
+ if (ctx != NULL) { \
+ ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, \
+ EVP_CIPH_##UCMODE##_MODE, flags, \
+ ossl_prov_cipher_hw_##alg##_##lcmode(kbits),\
+ NULL); \
+ ctx->rounds = RC5_12_ROUNDS; \
+ } \
+ return ctx; \
+} \
+const OSSL_DISPATCH ossl_##alg##kbits##lcmode##_functions[] = { \
+ { OSSL_FUNC_CIPHER_NEWCTX, \
+ (void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \
+ { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))rc5_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))rc5_dinit }, \
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_cipher_generic_##typ##_update },\
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_cipher_generic_##typ##_final }, \
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_cipher_generic_cipher }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, \
+ (void (*)(void)) alg##_##kbits##_##lcmode##_get_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
+ (void (*)(void))rc5_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void))rc5_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void))rc5_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))rc5_settable_ctx_params }, \
+ { 0, NULL } \
+};
+
+/* ossl_rc5128ecb_functions */
+IMPLEMENT_cipher(rc5, RC5, ecb, ECB, RC5_FLAGS, 128, 64, 0, block)
+/* ossl_rc5128cbc_functions */
+IMPLEMENT_cipher(rc5, RC5, cbc, CBC, RC5_FLAGS, 128, 64, 64, block)
+/* ossl_rc5128ofb64_functions */
+IMPLEMENT_cipher(rc5, RC5, ofb64, OFB, RC5_FLAGS, 128, 8, 64, stream)
+/* ossl_rc5128cfb64_functions */
+IMPLEMENT_cipher(rc5, RC5, cfb64, CFB, RC5_FLAGS, 128, 8, 64, stream)
diff --git a/providers/implementations/ciphers/cipher_rc5.h b/providers/implementations/ciphers/cipher_rc5.h
new file mode 100644
index 000000000000..c630e7c87bf9
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_rc5.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/rc5.h>
+#include "prov/ciphercommon.h"
+
+typedef struct prov_blowfish_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ RC5_32_KEY ks; /* key schedule */
+ } ks;
+ unsigned int rounds; /* number of rounds */
+} PROV_RC5_CTX;
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc5_cbc(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc5_ecb(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc5_ofb64(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc5_cfb64(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_rc5_hw.c b/providers/implementations/ciphers/cipher_rc5_hw.c
new file mode 100644
index 000000000000..898bd383f95a
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_rc5_hw.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * RC5 low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_rc5.h"
+
+static int cipher_hw_rc5_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_RC5_CTX *rctx = (PROV_RC5_CTX *)ctx;
+
+ return RC5_32_set_key(&rctx->ks.ks, keylen, key, rctx->rounds);
+}
+
+# define PROV_CIPHER_HW_rc5_mode(mode, UCMODE) \
+IMPLEMENT_CIPHER_HW_##UCMODE(mode, rc5, PROV_RC5_CTX, RC5_32_KEY, \
+ RC5_32_##mode) \
+static const PROV_CIPHER_HW rc5_##mode = { \
+ cipher_hw_rc5_initkey, \
+ cipher_hw_rc5_##mode##_cipher \
+}; \
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc5_##mode(size_t keybits) \
+{ \
+ return &rc5_##mode; \
+}
+
+PROV_CIPHER_HW_rc5_mode(cbc, CBC)
+PROV_CIPHER_HW_rc5_mode(ecb, ECB)
+PROV_CIPHER_HW_rc5_mode(ofb64, OFB)
+PROV_CIPHER_HW_rc5_mode(cfb64, CFB)
diff --git a/providers/implementations/ciphers/cipher_seed.c b/providers/implementations/ciphers/cipher_seed.c
new file mode 100644
index 000000000000..bae6a8e530ba
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_seed.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for Seed cipher modes ecb, cbc, ofb, cfb */
+
+/*
+ * SEED low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_seed.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+static OSSL_FUNC_cipher_freectx_fn seed_freectx;
+static OSSL_FUNC_cipher_dupctx_fn seed_dupctx;
+
+static void seed_freectx(void *vctx)
+{
+ PROV_SEED_CTX *ctx = (PROV_SEED_CTX *)vctx;
+
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static void *seed_dupctx(void *ctx)
+{
+ PROV_SEED_CTX *in = (PROV_SEED_CTX *)ctx;
+ PROV_SEED_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ret = OPENSSL_malloc(sizeof(*ret));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ *ret = *in;
+
+ return ret;
+}
+
+/* ossl_seed128ecb_functions */
+IMPLEMENT_generic_cipher(seed, SEED, ecb, ECB, 0, 128, 128, 0, block)
+/* ossl_seed128cbc_functions */
+IMPLEMENT_generic_cipher(seed, SEED, cbc, CBC, 0, 128, 128, 128, block)
+/* ossl_seed128ofb128_functions */
+IMPLEMENT_generic_cipher(seed, SEED, ofb128, OFB, 0, 128, 8, 128, stream)
+/* ossl_seed128cfb128_functions */
+IMPLEMENT_generic_cipher(seed, SEED, cfb128, CFB, 0, 128, 8, 128, stream)
diff --git a/providers/implementations/ciphers/cipher_seed.h b/providers/implementations/ciphers/cipher_seed.h
new file mode 100644
index 000000000000..9006a9183b55
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_seed.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/seed.h>
+#include "prov/ciphercommon.h"
+
+typedef struct prov_seed_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ SEED_KEY_SCHEDULE ks;
+ } ks;
+} PROV_SEED_CTX;
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_seed_cbc(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_seed_ecb(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_seed_ofb128(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_seed_cfb128(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_seed_hw.c b/providers/implementations/ciphers/cipher_seed_hw.c
new file mode 100644
index 000000000000..2d1dba92bc73
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_seed_hw.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * SEED low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_seed.h"
+
+static int cipher_hw_seed_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_SEED_CTX *sctx = (PROV_SEED_CTX *)ctx;
+
+ SEED_set_key(key, &(sctx->ks.ks));
+ return 1;
+}
+
+# define PROV_CIPHER_HW_seed_mode(mode, UCMODE) \
+IMPLEMENT_CIPHER_HW_##UCMODE(mode, seed, PROV_SEED_CTX, SEED_KEY_SCHEDULE, \
+ SEED_##mode) \
+static const PROV_CIPHER_HW seed_##mode = { \
+ cipher_hw_seed_initkey, \
+ cipher_hw_seed_##mode##_cipher \
+}; \
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_seed_##mode(size_t keybits) \
+{ \
+ return &seed_##mode; \
+}
+
+PROV_CIPHER_HW_seed_mode(cbc, CBC)
+PROV_CIPHER_HW_seed_mode(ecb, ECB)
+PROV_CIPHER_HW_seed_mode(ofb128, OFB)
+PROV_CIPHER_HW_seed_mode(cfb128, CFB)
diff --git a/providers/implementations/ciphers/cipher_sm4.c b/providers/implementations/ciphers/cipher_sm4.c
new file mode 100644
index 000000000000..6cf2731c6d5d
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_sm4.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for cast cipher modes ecb, cbc, ofb, cfb */
+
+#include "cipher_sm4.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+static OSSL_FUNC_cipher_freectx_fn sm4_freectx;
+static OSSL_FUNC_cipher_dupctx_fn sm4_dupctx;
+
+static void sm4_freectx(void *vctx)
+{
+ PROV_SM4_CTX *ctx = (PROV_SM4_CTX *)vctx;
+
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static void *sm4_dupctx(void *ctx)
+{
+ PROV_SM4_CTX *in = (PROV_SM4_CTX *)ctx;
+ PROV_SM4_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ret = OPENSSL_malloc(sizeof(*ret));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ in->base.hw->copyctx(&ret->base, &in->base);
+
+ return ret;
+}
+
+/* ossl_sm4128ecb_functions */
+IMPLEMENT_generic_cipher(sm4, SM4, ecb, ECB, 0, 128, 128, 0, block)
+/* ossl_sm4128cbc_functions */
+IMPLEMENT_generic_cipher(sm4, SM4, cbc, CBC, 0, 128, 128, 128, block)
+/* ossl_sm4128ctr_functions */
+IMPLEMENT_generic_cipher(sm4, SM4, ctr, CTR, 0, 128, 8, 128, stream)
+/* ossl_sm4128ofb128_functions */
+IMPLEMENT_generic_cipher(sm4, SM4, ofb128, OFB, 0, 128, 8, 128, stream)
+/* ossl_sm4128cfb128_functions */
+IMPLEMENT_generic_cipher(sm4, SM4, cfb128, CFB, 0, 128, 8, 128, stream)
diff --git a/providers/implementations/ciphers/cipher_sm4.h b/providers/implementations/ciphers/cipher_sm4.h
new file mode 100644
index 000000000000..f7f833fcb4cf
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_sm4.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/ciphercommon.h"
+#include "crypto/sm4.h"
+
+typedef struct prov_cast_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ SM4_KEY ks;
+ } ks;
+} PROV_SM4_CTX;
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_sm4_cbc(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_sm4_ecb(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_sm4_ctr(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_sm4_ofb128(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_sm4_cfb128(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_sm4_hw.c b/providers/implementations/ciphers/cipher_sm4_hw.c
new file mode 100644
index 000000000000..0db04b1a743b
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_sm4_hw.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "cipher_sm4.h"
+
+static int cipher_hw_sm4_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_SM4_CTX *sctx = (PROV_SM4_CTX *)ctx;
+ SM4_KEY *ks = &sctx->ks.ks;
+
+ ossl_sm4_set_key(key, ks);
+ ctx->ks = ks;
+ if (ctx->enc
+ || (ctx->mode != EVP_CIPH_ECB_MODE
+ && ctx->mode != EVP_CIPH_CBC_MODE))
+ ctx->block = (block128_f)ossl_sm4_encrypt;
+ else
+ ctx->block = (block128_f)ossl_sm4_decrypt;
+ return 1;
+}
+
+IMPLEMENT_CIPHER_HW_COPYCTX(cipher_hw_sm4_copyctx, PROV_SM4_CTX)
+
+# define PROV_CIPHER_HW_sm4_mode(mode) \
+static const PROV_CIPHER_HW sm4_##mode = { \
+ cipher_hw_sm4_initkey, \
+ ossl_cipher_hw_chunked_##mode, \
+ cipher_hw_sm4_copyctx \
+}; \
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_sm4_##mode(size_t keybits) \
+{ \
+ return &sm4_##mode; \
+}
+
+PROV_CIPHER_HW_sm4_mode(cbc)
+PROV_CIPHER_HW_sm4_mode(ecb)
+PROV_CIPHER_HW_sm4_mode(ofb128)
+PROV_CIPHER_HW_sm4_mode(cfb128)
+PROV_CIPHER_HW_sm4_mode(ctr)
diff --git a/providers/implementations/ciphers/cipher_tdes.c b/providers/implementations/ciphers/cipher_tdes.c
new file mode 100644
index 000000000000..2e5f8c3f05bb
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_tdes.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/rand.h>
+#include <openssl/proverr.h>
+#include "prov/ciphercommon.h"
+#include "cipher_tdes.h"
+#include "prov/implementations.h"
+
+/* ossl_tdes_ede3_ecb_functions */
+IMPLEMENT_tdes_cipher(ede3, EDE3, ecb, ECB, TDES_FLAGS, 64*3, 64, 0, block);
+/* ossl_tdes_ede3_cbc_functions */
+IMPLEMENT_tdes_cipher(ede3, EDE3, cbc, CBC, TDES_FLAGS, 64*3, 64, 64, block);
diff --git a/providers/implementations/ciphers/cipher_tdes.h b/providers/implementations/ciphers/cipher_tdes.h
new file mode 100644
index 000000000000..93f9d1744dc9
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_tdes.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/des.h>
+#include <openssl/core_dispatch.h>
+#include "crypto/des_platform.h"
+
+#define DES_BLOCK_SIZE 8
+#define TDES_IVLEN 8
+#define TDES_FLAGS PROV_CIPHER_FLAG_RAND_KEY
+
+typedef struct prov_tdes_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ DES_key_schedule ks[3];
+ } tks;
+ union {
+ void (*cbc) (const void *, void *, size_t,
+ const DES_key_schedule *, unsigned char *);
+ } tstream;
+
+} PROV_TDES_CTX;
+
+#define IMPLEMENT_tdes_cipher(type, UCTYPE, lcmode, UCMODE, flags, \
+ kbits, blkbits, ivbits, block) \
+static OSSL_FUNC_cipher_newctx_fn tdes_##type##_##lcmode##_newctx; \
+static void *tdes_##type##_##lcmode##_newctx(void *provctx) \
+{ \
+ return ossl_tdes_newctx(provctx, EVP_CIPH_##UCMODE##_MODE, kbits, blkbits, \
+ ivbits, flags, \
+ ossl_prov_cipher_hw_tdes_##type##_##lcmode()); \
+} \
+static OSSL_FUNC_cipher_get_params_fn tdes_##type##_##lcmode##_get_params; \
+static int tdes_##type##_##lcmode##_get_params(OSSL_PARAM params[]) \
+{ \
+ return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
+ flags, kbits, blkbits, ivbits); \
+} \
+const OSSL_DISPATCH ossl_tdes_##type##_##lcmode##_functions[] = { \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_tdes_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_tdes_dinit }, \
+ { OSSL_FUNC_CIPHER_UPDATE, \
+ (void (*)(void))ossl_cipher_generic_##block##_update }, \
+ { OSSL_FUNC_CIPHER_FINAL, \
+ (void (*)(void))ossl_cipher_generic_##block##_final }, \
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_cipher_generic_cipher }, \
+ { OSSL_FUNC_CIPHER_NEWCTX, \
+ (void (*)(void))tdes_##type##_##lcmode##_newctx }, \
+ { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))ossl_tdes_dupctx }, \
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))ossl_tdes_freectx }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, \
+ (void (*)(void))tdes_##type##_##lcmode##_get_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
+ (void (*)(void))ossl_tdes_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void))ossl_tdes_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_settable_ctx_params }, \
+ { 0, NULL } \
+}
+
+void *ossl_tdes_newctx(void *provctx, int mode, size_t kbits, size_t blkbits,
+ size_t ivbits, uint64_t flags, const PROV_CIPHER_HW *hw);
+OSSL_FUNC_cipher_dupctx_fn ossl_tdes_dupctx;
+OSSL_FUNC_cipher_freectx_fn ossl_tdes_freectx;
+OSSL_FUNC_cipher_encrypt_init_fn ossl_tdes_einit;
+OSSL_FUNC_cipher_decrypt_init_fn ossl_tdes_dinit;
+OSSL_FUNC_cipher_get_ctx_params_fn ossl_tdes_get_ctx_params;
+OSSL_FUNC_cipher_gettable_ctx_params_fn ossl_tdes_gettable_ctx_params;
+
+#define PROV_CIPHER_HW_tdes_mode(type, mode) \
+static const PROV_CIPHER_HW type##_##mode = { \
+ ossl_cipher_hw_tdes_##type##_initkey, \
+ ossl_cipher_hw_tdes_##mode, \
+ ossl_cipher_hw_tdes_copyctx \
+}; \
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_tdes_##type##_##mode(void) \
+{ \
+ return &type##_##mode; \
+}
+
+int ossl_cipher_hw_tdes_ede3_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key, size_t keylen);
+void ossl_cipher_hw_tdes_copyctx(PROV_CIPHER_CTX *dst,
+ const PROV_CIPHER_CTX *src);
+int ossl_cipher_hw_tdes_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl);
+int ossl_cipher_hw_tdes_ecb(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_tdes_ede3_cbc(void);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_tdes_ede3_ecb(void);
diff --git a/providers/implementations/ciphers/cipher_tdes_common.c b/providers/implementations/ciphers/cipher_tdes_common.c
new file mode 100644
index 000000000000..346aec05a1cc
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_tdes_common.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/rand.h>
+#include <openssl/proverr.h>
+#include "prov/ciphercommon.h"
+#include "cipher_tdes.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+void *ossl_tdes_newctx(void *provctx, int mode, size_t kbits, size_t blkbits,
+ size_t ivbits, uint64_t flags, const PROV_CIPHER_HW *hw)
+{
+ PROV_TDES_CTX *tctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ tctx = OPENSSL_zalloc(sizeof(*tctx));
+ if (tctx != NULL)
+ ossl_cipher_generic_initkey(tctx, kbits, blkbits, ivbits, mode, flags,
+ hw, provctx);
+ return tctx;
+}
+
+void *ossl_tdes_dupctx(void *ctx)
+{
+ PROV_TDES_CTX *in = (PROV_TDES_CTX *)ctx;
+ PROV_TDES_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ret = OPENSSL_malloc(sizeof(*ret));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ in->base.hw->copyctx(&ret->base, &in->base);
+
+ return ret;
+}
+
+void ossl_tdes_freectx(void *vctx)
+{
+ PROV_TDES_CTX *ctx = (PROV_TDES_CTX *)vctx;
+
+ ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static int tdes_init(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[], int enc)
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ ctx->num = 0;
+ ctx->bufsz = 0;
+ ctx->enc = enc;
+
+ if (iv != NULL) {
+ if (!ossl_cipher_generic_initiv(ctx, iv, ivlen))
+ return 0;
+ } else if (ctx->iv_set
+ && (ctx->mode == EVP_CIPH_CBC_MODE
+ || ctx->mode == EVP_CIPH_CFB_MODE
+ || ctx->mode == EVP_CIPH_OFB_MODE)) {
+ /* reset IV to keep compatibility with 1.1.1 */
+ memcpy(ctx->iv, ctx->oiv, ctx->ivlen);
+ }
+
+ if (key != NULL) {
+ if (keylen != ctx->keylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ if (!ctx->hw->init(ctx, key, ctx->keylen))
+ return 0;
+ }
+ return ossl_cipher_generic_set_ctx_params(ctx, params);
+}
+
+int ossl_tdes_einit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return tdes_init(vctx, key, keylen, iv, ivlen, params, 1);
+}
+
+int ossl_tdes_dinit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return tdes_init(vctx, key, keylen, iv, ivlen, params, 0);
+}
+
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(ossl_tdes)
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_RANDOM_KEY, NULL, 0),
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(ossl_tdes)
+
+static int tdes_generatekey(PROV_CIPHER_CTX *ctx, void *ptr)
+{
+
+ DES_cblock *deskey = ptr;
+ size_t kl = ctx->keylen;
+
+ if (kl == 0 || RAND_priv_bytes_ex(ctx->libctx, ptr, kl, 0) <= 0)
+ return 0;
+ DES_set_odd_parity(deskey);
+ if (kl >= 16)
+ DES_set_odd_parity(deskey + 1);
+ if (kl >= 24) {
+ DES_set_odd_parity(deskey + 2);
+ return 1;
+ }
+ return 0;
+}
+
+int ossl_tdes_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ OSSL_PARAM *p;
+
+ if (!ossl_cipher_generic_get_ctx_params(vctx, params))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_RANDOM_KEY);
+ if (p != NULL && !tdes_generatekey(ctx, p->data)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GENERATE_KEY);
+ return 0;
+ }
+ return 1;
+}
diff --git a/providers/implementations/ciphers/cipher_tdes_default.c b/providers/implementations/ciphers/cipher_tdes_default.c
new file mode 100644
index 000000000000..3b8908ff3988
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_tdes_default.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_tdes_default.h"
+#include "prov/implementations.h"
+
+/* ossl_tdes_ede3_ofb_functions */
+IMPLEMENT_tdes_cipher(ede3, EDE3, ofb, OFB, TDES_FLAGS, 64*3, 8, 64, stream);
+/* ossl_tdes_ede3_cfb_functions */
+IMPLEMENT_tdes_cipher(ede3, EDE3, cfb, CFB, TDES_FLAGS, 64*3, 8, 64, stream);
+/* ossl_tdes_ede3_cfb1_functions */
+IMPLEMENT_tdes_cipher(ede3, EDE3, cfb1, CFB, TDES_FLAGS, 64*3, 8, 64, stream);
+/* ossl_tdes_ede3_cfb8_functions */
+IMPLEMENT_tdes_cipher(ede3, EDE3, cfb8, CFB, TDES_FLAGS, 64*3, 8, 64, stream);
+
+/* ossl_tdes_ede2_ecb_functions */
+IMPLEMENT_tdes_cipher(ede2, EDE2, ecb, ECB, TDES_FLAGS, 64*2, 64, 0, block);
+/* ossl_tdes_ede2_cbc_functions */
+IMPLEMENT_tdes_cipher(ede2, EDE2, cbc, CBC, TDES_FLAGS, 64*2, 64, 64, block);
+/* ossl_tdes_ede2_ofb_functions */
+IMPLEMENT_tdes_cipher(ede2, EDE2, ofb, OFB, TDES_FLAGS, 64*2, 8, 64, stream);
+/* ossl_tdes_ede2_cfb_functions */
+IMPLEMENT_tdes_cipher(ede2, EDE2, cfb, CFB, TDES_FLAGS, 64*2, 8, 64, stream);
diff --git a/providers/implementations/ciphers/cipher_tdes_default.h b/providers/implementations/ciphers/cipher_tdes_default.h
new file mode 100644
index 000000000000..dc8458b5dafa
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_tdes_default.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/ciphercommon.h"
+#include "cipher_tdes.h"
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_tdes_ede3_ofb(void);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_tdes_ede3_cfb(void);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_tdes_ede3_cfb1(void);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_tdes_ede3_cfb8(void);
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_tdes_ede2_cbc(void);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_tdes_ede2_ecb(void);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_tdes_ede2_ofb(void);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_tdes_ede2_cfb(void);
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_tdes_desx_cbc(void);
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_tdes_wrap_cbc(void);
diff --git a/providers/implementations/ciphers/cipher_tdes_default_hw.c b/providers/implementations/ciphers/cipher_tdes_default_hw.c
new file mode 100644
index 000000000000..53cbbad57191
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_tdes_default_hw.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_tdes_default.h"
+
+#define ks1 tks.ks[0]
+#define ks2 tks.ks[1]
+#define ks3 tks.ks[2]
+
+static int ossl_cipher_hw_tdes_ede2_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key,
+ size_t keylen)
+{
+ PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
+ DES_cblock *deskey = (DES_cblock *)key;
+
+ tctx->tstream.cbc = NULL;
+# if defined(SPARC_DES_CAPABLE)
+ if (SPARC_DES_CAPABLE) {
+ if (ctx->mode == EVP_CIPH_CBC_MODE) {
+ des_t4_key_expand(&deskey[0], &tctx->ks1);
+ des_t4_key_expand(&deskey[1], &tctx->ks2);
+ memcpy(&tctx->ks3, &tctx->ks1, sizeof(tctx->ks1));
+ tctx->tstream.cbc = ctx->enc ? des_t4_ede3_cbc_encrypt :
+ des_t4_ede3_cbc_decrypt;
+ return 1;
+ }
+ }
+# endif
+ DES_set_key_unchecked(&deskey[0], &tctx->ks1);
+ DES_set_key_unchecked(&deskey[1], &tctx->ks2);
+ memcpy(&tctx->ks3, &tctx->ks1, sizeof(tctx->ks1));
+ return 1;
+}
+
+static int ossl_cipher_hw_tdes_ofb(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
+ int num = ctx->num;
+
+ while (inl >= MAXCHUNK) {
+ DES_ede3_ofb64_encrypt(in, out, (long)MAXCHUNK, &tctx->ks1, &tctx->ks2,
+ &tctx->ks3, (DES_cblock *)ctx->iv, &num);
+ inl -= MAXCHUNK;
+ in += MAXCHUNK;
+ out += MAXCHUNK;
+ }
+ if (inl > 0) {
+ DES_ede3_ofb64_encrypt(in, out, (long)inl, &tctx->ks1, &tctx->ks2,
+ &tctx->ks3, (DES_cblock *)ctx->iv, &num);
+ }
+ ctx->num = num;
+ return 1;
+}
+
+static int ossl_cipher_hw_tdes_cfb(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
+ int num = ctx->num;
+
+ while (inl >= MAXCHUNK) {
+
+ DES_ede3_cfb64_encrypt(in, out, (long)MAXCHUNK,
+ &tctx->ks1, &tctx->ks2, &tctx->ks3,
+ (DES_cblock *)ctx->iv, &num, ctx->enc);
+ inl -= MAXCHUNK;
+ in += MAXCHUNK;
+ out += MAXCHUNK;
+ }
+ if (inl > 0) {
+ DES_ede3_cfb64_encrypt(in, out, (long)inl,
+ &tctx->ks1, &tctx->ks2, &tctx->ks3,
+ (DES_cblock *)ctx->iv, &num, ctx->enc);
+ }
+ ctx->num = num;
+ return 1;
+}
+
+/*
+ * Although we have a CFB-r implementation for 3-DES, it doesn't pack the
+ * right way, so wrap it here
+ */
+static int ossl_cipher_hw_tdes_cfb1(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
+ size_t n;
+ unsigned char c[1], d[1];
+
+ if (ctx->use_bits == 0)
+ inl *= 8;
+ for (n = 0; n < inl; ++n) {
+ c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0;
+ DES_ede3_cfb_encrypt(c, d, 1, 1,
+ &tctx->ks1, &tctx->ks2, &tctx->ks3,
+ (DES_cblock *)ctx->iv, ctx->enc);
+ out[n / 8] = (out[n / 8] & ~(0x80 >> (unsigned int)(n % 8)))
+ | ((d[0] & 0x80) >> (unsigned int)(n % 8));
+ }
+
+ return 1;
+}
+
+static int ossl_cipher_hw_tdes_cfb8(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
+
+ while (inl >= MAXCHUNK) {
+ DES_ede3_cfb_encrypt(in, out, 8, (long)MAXCHUNK,
+ &tctx->ks1, &tctx->ks2, &tctx->ks3,
+ (DES_cblock *)ctx->iv, ctx->enc);
+ inl -= MAXCHUNK;
+ in += MAXCHUNK;
+ out += MAXCHUNK;
+ }
+ if (inl > 0)
+ DES_ede3_cfb_encrypt(in, out, 8, (long)inl,
+ &tctx->ks1, &tctx->ks2, &tctx->ks3,
+ (DES_cblock *)ctx->iv, ctx->enc);
+ return 1;
+}
+
+PROV_CIPHER_HW_tdes_mode(ede3, ofb)
+PROV_CIPHER_HW_tdes_mode(ede3, cfb)
+PROV_CIPHER_HW_tdes_mode(ede3, cfb1)
+PROV_CIPHER_HW_tdes_mode(ede3, cfb8)
+
+PROV_CIPHER_HW_tdes_mode(ede2, ecb)
+PROV_CIPHER_HW_tdes_mode(ede2, cbc)
+PROV_CIPHER_HW_tdes_mode(ede2, ofb)
+PROV_CIPHER_HW_tdes_mode(ede2, cfb)
+
diff --git a/providers/implementations/ciphers/cipher_tdes_hw.c b/providers/implementations/ciphers/cipher_tdes_hw.c
new file mode 100644
index 000000000000..4382969f44bb
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_tdes_hw.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include "prov/ciphercommon.h"
+#include "cipher_tdes.h"
+
+#define ks1 tks.ks[0]
+#define ks2 tks.ks[1]
+#define ks3 tks.ks[2]
+
+int ossl_cipher_hw_tdes_ede3_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
+ DES_cblock *deskey = (DES_cblock *)key;
+
+ tctx->tstream.cbc = NULL;
+# if defined(SPARC_DES_CAPABLE)
+ if (SPARC_DES_CAPABLE) {
+ if (ctx->mode == EVP_CIPH_CBC_MODE) {
+ des_t4_key_expand(&deskey[0], &tctx->ks1);
+ des_t4_key_expand(&deskey[1], &tctx->ks2);
+ des_t4_key_expand(&deskey[2], &tctx->ks3);
+ tctx->tstream.cbc = ctx->enc ? des_t4_ede3_cbc_encrypt :
+ des_t4_ede3_cbc_decrypt;
+ return 1;
+ }
+ }
+# endif
+ DES_set_key_unchecked(&deskey[0], &tctx->ks1);
+ DES_set_key_unchecked(&deskey[1], &tctx->ks2);
+ DES_set_key_unchecked(&deskey[2], &tctx->ks3);
+ return 1;
+}
+
+void ossl_cipher_hw_tdes_copyctx(PROV_CIPHER_CTX *dst,
+ const PROV_CIPHER_CTX *src)
+{
+ PROV_TDES_CTX *sctx = (PROV_TDES_CTX *)src;
+ PROV_TDES_CTX *dctx = (PROV_TDES_CTX *)dst;
+
+ *dctx = *sctx;
+ dst->ks = &dctx->tks.ks;
+}
+
+int ossl_cipher_hw_tdes_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
+
+ if (tctx->tstream.cbc != NULL) {
+ (*tctx->tstream.cbc) (in, out, inl, tctx->tks.ks, ctx->iv);
+ return 1;
+ }
+
+ while (inl >= MAXCHUNK) {
+ DES_ede3_cbc_encrypt(in, out, (long)MAXCHUNK, &tctx->ks1, &tctx->ks2,
+ &tctx->ks3, (DES_cblock *)ctx->iv, ctx->enc);
+ inl -= MAXCHUNK;
+ in += MAXCHUNK;
+ out += MAXCHUNK;
+ }
+ if (inl > 0)
+ DES_ede3_cbc_encrypt(in, out, (long)inl, &tctx->ks1, &tctx->ks2,
+ &tctx->ks3, (DES_cblock *)ctx->iv, ctx->enc);
+ return 1;
+}
+
+int ossl_cipher_hw_tdes_ecb(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ size_t i;
+ PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
+
+ if (len < DES_BLOCK_SIZE)
+ return 1;
+
+ for (i = 0, len -= DES_BLOCK_SIZE; i <= len; i += DES_BLOCK_SIZE) {
+ DES_ecb3_encrypt((const_DES_cblock *)(in + i), (DES_cblock *)(out + i),
+ &tctx->ks1, &tctx->ks2, &tctx->ks3, ctx->enc);
+ }
+ return 1;
+}
+
+PROV_CIPHER_HW_tdes_mode(ede3, ecb)
+PROV_CIPHER_HW_tdes_mode(ede3, cbc)
diff --git a/providers/implementations/ciphers/cipher_tdes_wrap.c b/providers/implementations/ciphers/cipher_tdes_wrap.c
new file mode 100644
index 000000000000..1b4539a64ce3
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_tdes_wrap.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DES and SHA-1 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/sha.h>
+#include <openssl/rand.h>
+#include <openssl/proverr.h>
+#include "cipher_tdes_default.h"
+#include "crypto/evp.h"
+#include "crypto/sha.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+#define TDES_WRAP_FLAGS PROV_CIPHER_FLAG_CUSTOM_IV | PROV_CIPHER_FLAG_RAND_KEY
+
+static OSSL_FUNC_cipher_update_fn tdes_wrap_update;
+static OSSL_FUNC_cipher_cipher_fn tdes_wrap_cipher;
+
+static const unsigned char wrap_iv[8] =
+{
+ 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05
+};
+
+static int des_ede3_unwrap(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ unsigned char icv[8], iv[TDES_IVLEN], sha1tmp[SHA_DIGEST_LENGTH];
+ int rv = -1;
+
+ if (inl < 24)
+ return -1;
+ if (out == NULL)
+ return inl - 16;
+
+ memcpy(ctx->iv, wrap_iv, 8);
+ /* Decrypt first block which will end up as icv */
+ ctx->hw->cipher(ctx, icv, in, 8);
+ /* Decrypt central blocks */
+ /*
+ * If decrypting in place move whole output along a block so the next
+ * des_ede_cbc_cipher is in place.
+ */
+ if (out == in) {
+ memmove(out, out + 8, inl - 8);
+ in -= 8;
+ }
+ ctx->hw->cipher(ctx, out, in + 8, inl - 16);
+ /* Decrypt final block which will be IV */
+ ctx->hw->cipher(ctx, iv, in + inl - 8, 8);
+ /* Reverse order of everything */
+ BUF_reverse(icv, NULL, 8);
+ BUF_reverse(out, NULL, inl - 16);
+ BUF_reverse(ctx->iv, iv, 8);
+ /* Decrypt again using new IV */
+ ctx->hw->cipher(ctx, out, out, inl - 16);
+ ctx->hw->cipher(ctx, icv, icv, 8);
+ if (ossl_sha1(out, inl - 16, sha1tmp) /* Work out hash of first portion */
+ && CRYPTO_memcmp(sha1tmp, icv, 8) == 0)
+ rv = inl - 16;
+ OPENSSL_cleanse(icv, 8);
+ OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH);
+ OPENSSL_cleanse(iv, 8);
+ OPENSSL_cleanse(ctx->iv, sizeof(ctx->iv));
+ if (rv == -1)
+ OPENSSL_cleanse(out, inl - 16);
+
+ return rv;
+}
+
+static int des_ede3_wrap(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ unsigned char sha1tmp[SHA_DIGEST_LENGTH];
+ size_t ivlen = TDES_IVLEN;
+ size_t icvlen = TDES_IVLEN;
+ size_t len = inl + ivlen + icvlen;
+
+ if (out == NULL)
+ return len;
+
+ /* Copy input to output buffer + 8 so we have space for IV */
+ memmove(out + ivlen, in, inl);
+ /* Work out ICV */
+ if (!ossl_sha1(in, inl, sha1tmp))
+ return 0;
+ memcpy(out + inl + ivlen, sha1tmp, icvlen);
+ OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH);
+ /* Generate random IV */
+ if (RAND_bytes_ex(ctx->libctx, ctx->iv, ivlen, 0) <= 0)
+ return 0;
+ memcpy(out, ctx->iv, ivlen);
+ /* Encrypt everything after IV in place */
+ ctx->hw->cipher(ctx, out + ivlen, out + ivlen, inl + ivlen);
+ BUF_reverse(out, NULL, len);
+ memcpy(ctx->iv, wrap_iv, ivlen);
+ ctx->hw->cipher(ctx, out, out, len);
+ return len;
+}
+
+static int tdes_wrap_cipher_internal(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ /*
+ * Sanity check input length: we typically only wrap keys so EVP_MAXCHUNK
+ * is more than will ever be needed. Also input length must be a multiple
+ * of 8 bits.
+ */
+ if (inl >= EVP_MAXCHUNK || inl % 8)
+ return -1;
+ if (ctx->enc)
+ return des_ede3_wrap(ctx, out, in, inl);
+ else
+ return des_ede3_unwrap(ctx, out, in, inl);
+}
+
+static int tdes_wrap_cipher(void *vctx,
+ unsigned char *out, size_t *outl, size_t outsize,
+ const unsigned char *in, size_t inl)
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ int ret;
+
+ *outl = 0;
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (outsize < inl) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ ret = tdes_wrap_cipher_internal(ctx, out, in, inl);
+ if (ret <= 0)
+ return 0;
+
+ *outl = ret;
+ return 1;
+}
+
+static int tdes_wrap_update(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in,
+ size_t inl)
+{
+ *outl = 0;
+ if (inl == 0)
+ return 1;
+ if (outsize < inl) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (!tdes_wrap_cipher(vctx, out, outl, outsize, in, inl)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+ return 1;
+}
+
+
+# define IMPLEMENT_WRAP_CIPHER(flags, kbits, blkbits, ivbits) \
+static OSSL_FUNC_cipher_newctx_fn tdes_wrap_newctx; \
+static void *tdes_wrap_newctx(void *provctx) \
+{ \
+ return ossl_tdes_newctx(provctx, EVP_CIPH_WRAP_MODE, kbits, blkbits, \
+ ivbits, flags, \
+ ossl_prov_cipher_hw_tdes_wrap_cbc()); \
+} \
+static OSSL_FUNC_cipher_get_params_fn tdes_wrap_get_params; \
+static int tdes_wrap_get_params(OSSL_PARAM params[]) \
+{ \
+ return ossl_cipher_generic_get_params(params, EVP_CIPH_WRAP_MODE, flags, \
+ kbits, blkbits, ivbits); \
+} \
+const OSSL_DISPATCH ossl_tdes_wrap_cbc_functions[] = \
+{ \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void)) ossl_tdes_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void)) ossl_tdes_dinit }, \
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))tdes_wrap_cipher }, \
+ { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))tdes_wrap_newctx }, \
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))ossl_tdes_freectx }, \
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))tdes_wrap_update }, \
+ { OSSL_FUNC_CIPHER_FINAL, \
+ (void (*)(void))ossl_cipher_generic_stream_final }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))tdes_wrap_get_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
+ (void (*)(void))ossl_tdes_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void))ossl_tdes_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_settable_ctx_params }, \
+ { 0, NULL } \
+}
+
+/* ossl_tdes_wrap_cbc_functions */
+IMPLEMENT_WRAP_CIPHER(TDES_WRAP_FLAGS, 64*3, 64, 0);
diff --git a/providers/implementations/ciphers/cipher_tdes_wrap_hw.c b/providers/implementations/ciphers/cipher_tdes_wrap_hw.c
new file mode 100644
index 000000000000..3c8c83332070
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_tdes_wrap_hw.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include "cipher_tdes_default.h"
+
+#define ossl_cipher_hw_tdes_wrap_initkey ossl_cipher_hw_tdes_ede3_initkey
+
+PROV_CIPHER_HW_tdes_mode(wrap, cbc)
diff --git a/providers/implementations/ciphers/ciphercommon.c b/providers/implementations/ciphers/ciphercommon.c
new file mode 100644
index 000000000000..fa383165d83c
--- /dev/null
+++ b/providers/implementations/ciphers/ciphercommon.c
@@ -0,0 +1,680 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Generic dispatch table functions for ciphers.
+ */
+
+/* For SSL3_VERSION */
+#include <openssl/prov_ssl.h>
+#include <openssl/proverr.h>
+#include "ciphercommon_local.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+
+/*-
+ * Generic cipher functions for OSSL_PARAM gettables and settables
+ */
+static const OSSL_PARAM cipher_known_gettable_params[] = {
+ OSSL_PARAM_uint(OSSL_CIPHER_PARAM_MODE, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_BLOCK_SIZE, NULL),
+ OSSL_PARAM_int(OSSL_CIPHER_PARAM_AEAD, NULL),
+ OSSL_PARAM_int(OSSL_CIPHER_PARAM_CUSTOM_IV, NULL),
+ OSSL_PARAM_int(OSSL_CIPHER_PARAM_CTS, NULL),
+ OSSL_PARAM_int(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK, NULL),
+ OSSL_PARAM_int(OSSL_CIPHER_PARAM_HAS_RAND_KEY, NULL),
+ OSSL_PARAM_END
+};
+const OSSL_PARAM *ossl_cipher_generic_gettable_params(ossl_unused void *provctx)
+{
+ return cipher_known_gettable_params;
+}
+
+int ossl_cipher_generic_get_params(OSSL_PARAM params[], unsigned int md,
+ uint64_t flags,
+ size_t kbits, size_t blkbits, size_t ivbits)
+{
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE);
+ if (p != NULL && !OSSL_PARAM_set_uint(p, md)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD);
+ if (p != NULL
+ && !OSSL_PARAM_set_int(p, (flags & PROV_CIPHER_FLAG_AEAD) != 0)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_CUSTOM_IV);
+ if (p != NULL
+ && !OSSL_PARAM_set_int(p, (flags & PROV_CIPHER_FLAG_CUSTOM_IV) != 0)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_CTS);
+ if (p != NULL
+ && !OSSL_PARAM_set_int(p, (flags & PROV_CIPHER_FLAG_CTS) != 0)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK);
+ if (p != NULL
+ && !OSSL_PARAM_set_int(p, (flags & PROV_CIPHER_FLAG_TLS1_MULTIBLOCK) != 0)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_HAS_RAND_KEY);
+ if (p != NULL
+ && !OSSL_PARAM_set_int(p, (flags & PROV_CIPHER_FLAG_RAND_KEY) != 0)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, kbits / 8)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, blkbits / 8)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ivbits / 8)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ return 1;
+}
+
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(ossl_cipher_generic)
+{ OSSL_CIPHER_PARAM_TLS_MAC, OSSL_PARAM_OCTET_PTR, NULL, 0, OSSL_PARAM_UNMODIFIED },
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(ossl_cipher_generic)
+
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(ossl_cipher_generic)
+OSSL_PARAM_uint(OSSL_CIPHER_PARAM_USE_BITS, NULL),
+OSSL_PARAM_uint(OSSL_CIPHER_PARAM_TLS_VERSION, NULL),
+OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS_MAC_SIZE, NULL),
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(ossl_cipher_generic)
+
+/*
+ * Variable key length cipher functions for OSSL_PARAM settables
+ */
+int ossl_cipher_var_keylen_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ const OSSL_PARAM *p;
+
+ if (params == NULL)
+ return 1;
+
+ if (!ossl_cipher_generic_set_ctx_params(vctx, params))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL) {
+ size_t keylen;
+
+ if (!OSSL_PARAM_get_size_t(p, &keylen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ ctx->keylen = keylen;
+ }
+ return 1;
+}
+
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(ossl_cipher_var_keylen)
+OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(ossl_cipher_var_keylen)
+
+/*-
+ * AEAD cipher functions for OSSL_PARAM gettables and settables
+ */
+static const OSSL_PARAM cipher_aead_known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_UPDATED_IV, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN, NULL, 0),
+ OSSL_PARAM_END
+};
+const OSSL_PARAM *ossl_cipher_aead_gettable_ctx_params(
+ ossl_unused void *cctx, ossl_unused void *provctx
+ )
+{
+ return cipher_aead_known_gettable_ctx_params;
+}
+
+static const OSSL_PARAM cipher_aead_known_settable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, NULL),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV, NULL, 0),
+ OSSL_PARAM_END
+};
+const OSSL_PARAM *ossl_cipher_aead_settable_ctx_params(
+ ossl_unused void *cctx, ossl_unused void *provctx
+ )
+{
+ return cipher_aead_known_settable_ctx_params;
+}
+
+void ossl_cipher_generic_reset_ctx(PROV_CIPHER_CTX *ctx)
+{
+ if (ctx != NULL && ctx->alloced) {
+ OPENSSL_free(ctx->tlsmac);
+ ctx->alloced = 0;
+ ctx->tlsmac = NULL;
+ }
+}
+
+static int cipher_generic_init_internal(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[], int enc)
+{
+ ctx->num = 0;
+ ctx->bufsz = 0;
+ ctx->updated = 0;
+ ctx->enc = enc ? 1 : 0;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (iv != NULL && ctx->mode != EVP_CIPH_ECB_MODE) {
+ if (!ossl_cipher_generic_initiv(ctx, iv, ivlen))
+ return 0;
+ }
+ if (iv == NULL && ctx->iv_set
+ && (ctx->mode == EVP_CIPH_CBC_MODE
+ || ctx->mode == EVP_CIPH_CFB_MODE
+ || ctx->mode == EVP_CIPH_OFB_MODE))
+ /* reset IV for these modes to keep compatibility with 1.1.1 */
+ memcpy(ctx->iv, ctx->oiv, ctx->ivlen);
+
+ if (key != NULL) {
+ if (ctx->variable_keylength == 0) {
+ if (keylen != ctx->keylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ } else {
+ ctx->keylen = keylen;
+ }
+ if (!ctx->hw->init(ctx, key, ctx->keylen))
+ return 0;
+ }
+ return ossl_cipher_generic_set_ctx_params(ctx, params);
+}
+
+int ossl_cipher_generic_einit(void *vctx, const unsigned char *key,
+ size_t keylen, const unsigned char *iv,
+ size_t ivlen, const OSSL_PARAM params[])
+{
+ return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx, key, keylen,
+ iv, ivlen, params, 1);
+}
+
+int ossl_cipher_generic_dinit(void *vctx, const unsigned char *key,
+ size_t keylen, const unsigned char *iv,
+ size_t ivlen, const OSSL_PARAM params[])
+{
+ return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx, key, keylen,
+ iv, ivlen, params, 0);
+}
+
+/* Max padding including padding length byte */
+#define MAX_PADDING 256
+
+int ossl_cipher_generic_block_update(void *vctx, unsigned char *out,
+ size_t *outl, size_t outsize,
+ const unsigned char *in, size_t inl)
+{
+ size_t outlint = 0;
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ size_t blksz = ctx->blocksize;
+ size_t nextblocks;
+
+ if (ctx->tlsversion > 0) {
+ /*
+ * Each update call corresponds to a TLS record and is individually
+ * padded
+ */
+
+ /* Sanity check inputs */
+ if (in == NULL
+ || in != out
+ || outsize < inl
+ || !ctx->pad) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+
+ if (ctx->enc) {
+ unsigned char padval;
+ size_t padnum, loop;
+
+ /* Add padding */
+
+ padnum = blksz - (inl % blksz);
+
+ if (outsize < inl + padnum) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+
+ if (padnum > MAX_PADDING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+ padval = (unsigned char)(padnum - 1);
+ if (ctx->tlsversion == SSL3_VERSION) {
+ if (padnum > 1)
+ memset(out + inl, 0, padnum - 1);
+ *(out + inl + padnum - 1) = padval;
+ } else {
+ /* we need to add 'padnum' padding bytes of value padval */
+ for (loop = inl; loop < inl + padnum; loop++)
+ out[loop] = padval;
+ }
+ inl += padnum;
+ }
+
+ if ((inl % blksz) != 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+
+
+ /* Shouldn't normally fail */
+ if (!ctx->hw->cipher(ctx, out, in, inl)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+
+ if (ctx->alloced) {
+ OPENSSL_free(ctx->tlsmac);
+ ctx->alloced = 0;
+ ctx->tlsmac = NULL;
+ }
+
+ /* This only fails if padding is publicly invalid */
+ *outl = inl;
+ if (!ctx->enc
+ && !ossl_cipher_tlsunpadblock(ctx->libctx, ctx->tlsversion,
+ out, outl,
+ blksz, &ctx->tlsmac, &ctx->alloced,
+ ctx->tlsmacsize, 0)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+ return 1;
+ }
+
+ if (ctx->bufsz != 0)
+ nextblocks = ossl_cipher_fillblock(ctx->buf, &ctx->bufsz, blksz,
+ &in, &inl);
+ else
+ nextblocks = inl & ~(blksz-1);
+
+ /*
+ * If we're decrypting and we end an update on a block boundary we hold
+ * the last block back in case this is the last update call and the last
+ * block is padded.
+ */
+ if (ctx->bufsz == blksz && (ctx->enc || inl > 0 || !ctx->pad)) {
+ if (outsize < blksz) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+ if (!ctx->hw->cipher(ctx, out, ctx->buf, blksz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+ ctx->bufsz = 0;
+ outlint = blksz;
+ out += blksz;
+ }
+ if (nextblocks > 0) {
+ if (!ctx->enc && ctx->pad && nextblocks == inl) {
+ if (!ossl_assert(inl >= blksz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+ nextblocks -= blksz;
+ }
+ outlint += nextblocks;
+ if (outsize < outlint) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+ }
+ if (nextblocks > 0) {
+ if (!ctx->hw->cipher(ctx, out, in, nextblocks)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+ in += nextblocks;
+ inl -= nextblocks;
+ }
+ if (inl != 0
+ && !ossl_cipher_trailingdata(ctx->buf, &ctx->bufsz, blksz, &in, &inl)) {
+ /* ERR_raise already called */
+ return 0;
+ }
+
+ *outl = outlint;
+ return inl == 0;
+}
+
+int ossl_cipher_generic_block_final(void *vctx, unsigned char *out,
+ size_t *outl, size_t outsize)
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ size_t blksz = ctx->blocksize;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (ctx->tlsversion > 0) {
+ /* We never finalize TLS, so this is an error */
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+
+ if (ctx->enc) {
+ if (ctx->pad) {
+ ossl_cipher_padblock(ctx->buf, &ctx->bufsz, blksz);
+ } else if (ctx->bufsz == 0) {
+ *outl = 0;
+ return 1;
+ } else if (ctx->bufsz != blksz) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
+ return 0;
+ }
+
+ if (outsize < blksz) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+ if (!ctx->hw->cipher(ctx, out, ctx->buf, blksz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+ ctx->bufsz = 0;
+ *outl = blksz;
+ return 1;
+ }
+
+ /* Decrypting */
+ if (ctx->bufsz != blksz) {
+ if (ctx->bufsz == 0 && !ctx->pad) {
+ *outl = 0;
+ return 1;
+ }
+ ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
+ return 0;
+ }
+
+ if (!ctx->hw->cipher(ctx, ctx->buf, ctx->buf, blksz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+
+ if (ctx->pad && !ossl_cipher_unpadblock(ctx->buf, &ctx->bufsz, blksz)) {
+ /* ERR_raise already called */
+ return 0;
+ }
+
+ if (outsize < ctx->bufsz) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+ memcpy(out, ctx->buf, ctx->bufsz);
+ *outl = ctx->bufsz;
+ ctx->bufsz = 0;
+ return 1;
+}
+
+int ossl_cipher_generic_stream_update(void *vctx, unsigned char *out,
+ size_t *outl, size_t outsize,
+ const unsigned char *in, size_t inl)
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+
+ if (inl == 0) {
+ *outl = 0;
+ return 1;
+ }
+
+ if (outsize < inl) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (!ctx->hw->cipher(ctx, out, in, inl)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+
+ *outl = inl;
+ if (!ctx->enc && ctx->tlsversion > 0) {
+ /*
+ * Remove any TLS padding. Only used by cipher_aes_cbc_hmac_sha1_hw.c and
+ * cipher_aes_cbc_hmac_sha256_hw.c
+ */
+ if (ctx->removetlspad) {
+ /*
+ * We should have already failed in the cipher() call above if this
+ * isn't true.
+ */
+ if (!ossl_assert(*outl >= (size_t)(out[inl - 1] + 1)))
+ return 0;
+ /* The actual padding length */
+ *outl -= out[inl - 1] + 1;
+ }
+
+ /* TLS MAC and explicit IV if relevant. We should have already failed
+ * in the cipher() call above if *outl is too short.
+ */
+ if (!ossl_assert(*outl >= ctx->removetlsfixed))
+ return 0;
+ *outl -= ctx->removetlsfixed;
+
+ /* Extract the MAC if there is one */
+ if (ctx->tlsmacsize > 0) {
+ if (*outl < ctx->tlsmacsize)
+ return 0;
+
+ ctx->tlsmac = out + *outl - ctx->tlsmacsize;
+ *outl -= ctx->tlsmacsize;
+ }
+ }
+
+ return 1;
+}
+int ossl_cipher_generic_stream_final(void *vctx, unsigned char *out,
+ size_t *outl, size_t outsize)
+{
+ if (!ossl_prov_is_running())
+ return 0;
+
+ *outl = 0;
+ return 1;
+}
+
+int ossl_cipher_generic_cipher(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in,
+ size_t inl)
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (outsize < inl) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (!ctx->hw->cipher(ctx, out, in, inl)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+
+ *outl = inl;
+ return 1;
+}
+
+int ossl_cipher_generic_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING);
+ if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->pad)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
+ if (p != NULL
+ && !OSSL_PARAM_set_octet_ptr(p, &ctx->oiv, ctx->ivlen)
+ && !OSSL_PARAM_set_octet_string(p, &ctx->oiv, ctx->ivlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_UPDATED_IV);
+ if (p != NULL
+ && !OSSL_PARAM_set_octet_ptr(p, &ctx->iv, ctx->ivlen)
+ && !OSSL_PARAM_set_octet_string(p, &ctx->iv, ctx->ivlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_NUM);
+ if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->num)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS_MAC);
+ if (p != NULL
+ && !OSSL_PARAM_set_octet_ptr(p, ctx->tlsmac, ctx->tlsmacsize)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ return 1;
+}
+
+int ossl_cipher_generic_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ const OSSL_PARAM *p;
+
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_PADDING);
+ if (p != NULL) {
+ unsigned int pad;
+
+ if (!OSSL_PARAM_get_uint(p, &pad)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ ctx->pad = pad ? 1 : 0;
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_USE_BITS);
+ if (p != NULL) {
+ unsigned int bits;
+
+ if (!OSSL_PARAM_get_uint(p, &bits)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ ctx->use_bits = bits ? 1 : 0;
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLS_VERSION);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_uint(p, &ctx->tlsversion)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLS_MAC_SIZE);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &ctx->tlsmacsize)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_NUM);
+ if (p != NULL) {
+ unsigned int num;
+
+ if (!OSSL_PARAM_get_uint(p, &num)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ ctx->num = num;
+ }
+ return 1;
+}
+
+int ossl_cipher_generic_initiv(PROV_CIPHER_CTX *ctx, const unsigned char *iv,
+ size_t ivlen)
+{
+ if (ivlen != ctx->ivlen
+ || ivlen > sizeof(ctx->iv)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ ctx->iv_set = 1;
+ memcpy(ctx->iv, iv, ivlen);
+ memcpy(ctx->oiv, iv, ivlen);
+ return 1;
+}
+
+void ossl_cipher_generic_initkey(void *vctx, size_t kbits, size_t blkbits,
+ size_t ivbits, unsigned int mode,
+ uint64_t flags, const PROV_CIPHER_HW *hw,
+ void *provctx)
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+
+ if ((flags & PROV_CIPHER_FLAG_INVERSE_CIPHER) != 0)
+ ctx->inverse_cipher = 1;
+ if ((flags & PROV_CIPHER_FLAG_VARIABLE_LENGTH) != 0)
+ ctx->variable_keylength = 1;
+
+ ctx->pad = 1;
+ ctx->keylen = ((kbits) / 8);
+ ctx->ivlen = ((ivbits) / 8);
+ ctx->hw = hw;
+ ctx->mode = mode;
+ ctx->blocksize = blkbits / 8;
+ if (provctx != NULL)
+ ctx->libctx = PROV_LIBCTX_OF(provctx); /* used for rand */
+}
diff --git a/providers/implementations/ciphers/ciphercommon_block.c b/providers/implementations/ciphers/ciphercommon_block.c
new file mode 100644
index 000000000000..6e6bb091e76b
--- /dev/null
+++ b/providers/implementations/ciphers/ciphercommon_block.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <assert.h>
+/* For SSL3_VERSION, TLS1_VERSION etc */
+#include <openssl/prov_ssl.h>
+#include <openssl/rand.h>
+#include <openssl/proverr.h>
+#include "internal/constant_time.h"
+#include "ciphercommon_local.h"
+
+/* Functions defined in ssl/tls_pad.c */
+int ssl3_cbc_remove_padding_and_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
+ unsigned char **mac,
+ int *alloced,
+ size_t block_size, size_t mac_size,
+ OSSL_LIB_CTX *libctx);
+
+int tls1_cbc_remove_padding_and_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
+ unsigned char **mac,
+ int *alloced,
+ size_t block_size, size_t mac_size,
+ int aead,
+ OSSL_LIB_CTX *libctx);
+
+/*
+ * Fills a single block of buffered data from the input, and returns the amount
+ * of data remaining in the input that is a multiple of the blocksize. The buffer
+ * is only filled if it already has some data in it, isn't full already or we
+ * don't have at least one block in the input.
+ *
+ * buf: a buffer of blocksize bytes
+ * buflen: contains the amount of data already in buf on entry. Updated with the
+ * amount of data in buf at the end. On entry *buflen must always be
+ * less than the blocksize
+ * blocksize: size of a block. Must be greater than 0 and a power of 2
+ * in: pointer to a pointer containing the input data
+ * inlen: amount of input data available
+ *
+ * On return buf is filled with as much data as possible up to a full block,
+ * *buflen is updated containing the amount of data in buf. *in is updated to
+ * the new location where input data should be read from, *inlen is updated with
+ * the remaining amount of data in *in. Returns the largest value <= *inlen
+ * which is a multiple of the blocksize.
+ */
+size_t ossl_cipher_fillblock(unsigned char *buf, size_t *buflen,
+ size_t blocksize,
+ const unsigned char **in, size_t *inlen)
+{
+ size_t blockmask = ~(blocksize - 1);
+ size_t bufremain = blocksize - *buflen;
+
+ assert(*buflen <= blocksize);
+ assert(blocksize > 0 && (blocksize & (blocksize - 1)) == 0);
+
+ if (*inlen < bufremain)
+ bufremain = *inlen;
+ memcpy(buf + *buflen, *in, bufremain);
+ *in += bufremain;
+ *inlen -= bufremain;
+ *buflen += bufremain;
+
+ return *inlen & blockmask;
+}
+
+/*
+ * Fills the buffer with trailing data from an encryption/decryption that didn't
+ * fit into a full block.
+ */
+int ossl_cipher_trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize,
+ const unsigned char **in, size_t *inlen)
+{
+ if (*inlen == 0)
+ return 1;
+
+ if (*buflen + *inlen > blocksize) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ memcpy(buf + *buflen, *in, *inlen);
+ *buflen += *inlen;
+ *inlen = 0;
+
+ return 1;
+}
+
+/* Pad the final block for encryption */
+void ossl_cipher_padblock(unsigned char *buf, size_t *buflen, size_t blocksize)
+{
+ size_t i;
+ unsigned char pad = (unsigned char)(blocksize - *buflen);
+
+ for (i = *buflen; i < blocksize; i++)
+ buf[i] = pad;
+}
+
+int ossl_cipher_unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize)
+{
+ size_t pad, i;
+ size_t len = *buflen;
+
+ if(len != blocksize) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /*
+ * The following assumes that the ciphertext has been authenticated.
+ * Otherwise it provides a padding oracle.
+ */
+ pad = buf[blocksize - 1];
+ if (pad == 0 || pad > blocksize) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT);
+ return 0;
+ }
+ for (i = 0; i < pad; i++) {
+ if (buf[--len] != pad) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT);
+ return 0;
+ }
+ }
+ *buflen = len;
+ return 1;
+}
+
+/*-
+ * ossl_cipher_tlsunpadblock removes the CBC padding from the decrypted, TLS, CBC
+ * record in constant time. Also removes the MAC from the record in constant
+ * time.
+ *
+ * libctx: Our library context
+ * tlsversion: The TLS version in use, e.g. SSL3_VERSION, TLS1_VERSION, etc
+ * buf: The decrypted TLS record data
+ * buflen: The length of the decrypted TLS record data. Updated with the new
+ * length after the padding is removed
+ * block_size: the block size of the cipher used to encrypt the record.
+ * mac: Location to store the pointer to the MAC
+ * alloced: Whether the MAC is stored in a newly allocated buffer, or whether
+ * *mac points into *buf
+ * macsize: the size of the MAC inside the record (or 0 if there isn't one)
+ * aead: whether this is an aead cipher
+ * returns:
+ * 0: (in non-constant time) if the record is publicly invalid.
+ * 1: (in constant time) Record is publicly valid. If padding is invalid then
+ * the mac is random
+ */
+int ossl_cipher_tlsunpadblock(OSSL_LIB_CTX *libctx, unsigned int tlsversion,
+ unsigned char *buf, size_t *buflen,
+ size_t blocksize,
+ unsigned char **mac, int *alloced, size_t macsize,
+ int aead)
+{
+ int ret;
+
+ switch (tlsversion) {
+ case SSL3_VERSION:
+ return ssl3_cbc_remove_padding_and_mac(buflen, *buflen, buf, mac,
+ alloced, blocksize, macsize,
+ libctx);
+
+ case TLS1_2_VERSION:
+ case DTLS1_2_VERSION:
+ case TLS1_1_VERSION:
+ case DTLS1_VERSION:
+ case DTLS1_BAD_VER:
+ /* Remove the explicit IV */
+ buf += blocksize;
+ *buflen -= blocksize;
+ /* Fall through */
+ case TLS1_VERSION:
+ ret = tls1_cbc_remove_padding_and_mac(buflen, *buflen, buf, mac,
+ alloced, blocksize, macsize,
+ aead, libctx);
+ return ret;
+
+ default:
+ return 0;
+ }
+}
diff --git a/providers/implementations/ciphers/ciphercommon_ccm.c b/providers/implementations/ciphers/ciphercommon_ccm.c
new file mode 100644
index 000000000000..ce3f7527f31e
--- /dev/null
+++ b/providers/implementations/ciphers/ciphercommon_ccm.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for ccm mode */
+
+#include <openssl/proverr.h>
+#include "prov/ciphercommon.h"
+#include "prov/ciphercommon_ccm.h"
+#include "prov/providercommon.h"
+
+static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out,
+ size_t *padlen, const unsigned char *in,
+ size_t len);
+
+static int ccm_tls_init(PROV_CCM_CTX *ctx, unsigned char *aad, size_t alen)
+{
+ size_t len;
+
+ if (!ossl_prov_is_running() || alen != EVP_AEAD_TLS1_AAD_LEN)
+ return 0;
+
+ /* Save the aad for later use. */
+ memcpy(ctx->buf, aad, alen);
+ ctx->tls_aad_len = alen;
+
+ len = ctx->buf[alen - 2] << 8 | ctx->buf[alen - 1];
+ if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN)
+ return 0;
+
+ /* Correct length for explicit iv. */
+ len -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
+
+ if (!ctx->enc) {
+ if (len < ctx->m)
+ return 0;
+ /* Correct length for tag. */
+ len -= ctx->m;
+ }
+ ctx->buf[alen - 2] = (unsigned char)(len >> 8);
+ ctx->buf[alen - 1] = (unsigned char)(len & 0xff);
+
+ /* Extra padding: tag appended to record. */
+ return ctx->m;
+}
+
+static int ccm_tls_iv_set_fixed(PROV_CCM_CTX *ctx, unsigned char *fixed,
+ size_t flen)
+{
+ if (flen != EVP_CCM_TLS_FIXED_IV_LEN)
+ return 0;
+
+ /* Copy to first part of the iv. */
+ memcpy(ctx->iv, fixed, flen);
+ return 1;
+}
+
+static size_t ccm_get_ivlen(PROV_CCM_CTX *ctx)
+{
+ return 15 - ctx->l;
+}
+
+int ossl_ccm_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
+ const OSSL_PARAM *p;
+ size_t sz;
+
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if ((p->data_size & 1) || (p->data_size < 4) || p->data_size > 16) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH);
+ return 0;
+ }
+
+ if (p->data != NULL) {
+ if (ctx->enc) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_NEEDED);
+ return 0;
+ }
+ memcpy(ctx->buf, p->data, p->data_size);
+ ctx->tag_set = 1;
+ }
+ ctx->m = p->data_size;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN);
+ if (p != NULL) {
+ size_t ivlen;
+
+ if (!OSSL_PARAM_get_size_t(p, &sz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ ivlen = 15 - sz;
+ if (ivlen < 2 || ivlen > 8) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ ctx->l = ivlen;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ sz = ccm_tls_init(ctx, p->data, p->data_size);
+ if (sz == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA);
+ return 0;
+ }
+ ctx->tls_aad_pad_sz = sz;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (ccm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int ossl_ccm_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ccm_get_ivlen(ctx))) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
+ if (p != NULL) {
+ size_t m = ctx->m;
+
+ if (!OSSL_PARAM_set_size_t(p, m)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
+ if (p != NULL) {
+ if (ccm_get_ivlen(ctx) > p->data_size) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ if (!OSSL_PARAM_set_octet_string(p, ctx->iv, p->data_size)
+ && !OSSL_PARAM_set_octet_ptr(p, &ctx->iv, p->data_size)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_UPDATED_IV);
+ if (p != NULL) {
+ if (ccm_get_ivlen(ctx) > p->data_size) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ if (!OSSL_PARAM_set_octet_string(p, ctx->iv, p->data_size)
+ && !OSSL_PARAM_set_octet_ptr(p, &ctx->iv, p->data_size)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+ if (p != NULL) {
+ if (!ctx->enc || !ctx->tag_set) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_SET);
+ return 0;
+ }
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ if (!ctx->hw->gettag(ctx, p->data, p->data_size))
+ return 0;
+ ctx->tag_set = 0;
+ ctx->iv_set = 0;
+ ctx->len_set = 0;
+ }
+ return 1;
+}
+
+static int ccm_init(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[], int enc)
+{
+ PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ ctx->enc = enc;
+
+ if (iv != NULL) {
+ if (ivlen != ccm_get_ivlen(ctx)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ memcpy(ctx->iv, iv, ivlen);
+ ctx->iv_set = 1;
+ }
+ if (key != NULL) {
+ if (keylen != ctx->keylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ if (!ctx->hw->setkey(ctx, key, keylen))
+ return 0;
+ }
+ return ossl_ccm_set_ctx_params(ctx, params);
+}
+
+int ossl_ccm_einit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return ccm_init(vctx, key, keylen, iv, ivlen, params, 1);
+}
+
+int ossl_ccm_dinit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return ccm_init(vctx, key, keylen, iv, ivlen, params, 0);
+}
+
+int ossl_ccm_stream_update(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in,
+ size_t inl)
+{
+ PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
+
+ if (outsize < inl) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (!ccm_cipher_internal(ctx, out, outl, in, inl)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+ return 1;
+}
+
+int ossl_ccm_stream_final(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
+ int i;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ i = ccm_cipher_internal(ctx, out, outl, NULL, 0);
+ if (i <= 0)
+ return 0;
+
+ *outl = 0;
+ return 1;
+}
+
+int ossl_ccm_cipher(void *vctx, unsigned char *out, size_t *outl, size_t outsize,
+ const unsigned char *in, size_t inl)
+{
+ PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (outsize < inl) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (ccm_cipher_internal(ctx, out, outl, in, inl) <= 0)
+ return 0;
+
+ *outl = inl;
+ return 1;
+}
+
+/* Copy the buffered iv */
+static int ccm_set_iv(PROV_CCM_CTX *ctx, size_t mlen)
+{
+ const PROV_CCM_HW *hw = ctx->hw;
+
+ if (!hw->setiv(ctx, ctx->iv, ccm_get_ivlen(ctx), mlen))
+ return 0;
+ ctx->len_set = 1;
+ return 1;
+}
+
+static int ccm_tls_cipher(PROV_CCM_CTX *ctx,
+ unsigned char *out, size_t *padlen,
+ const unsigned char *in, size_t len)
+{
+ int rv = 0;
+ size_t olen = 0;
+
+ if (!ossl_prov_is_running())
+ goto err;
+
+ /* Encrypt/decrypt must be performed in place */
+ if (in == NULL || out != in || len < EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m)
+ goto err;
+
+ /* If encrypting set explicit IV from sequence number (start of AAD) */
+ if (ctx->enc)
+ memcpy(out, ctx->buf, EVP_CCM_TLS_EXPLICIT_IV_LEN);
+ /* Get rest of IV from explicit IV */
+ memcpy(ctx->iv + EVP_CCM_TLS_FIXED_IV_LEN, in, EVP_CCM_TLS_EXPLICIT_IV_LEN);
+ /* Correct length value */
+ len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m;
+ if (!ccm_set_iv(ctx, len))
+ goto err;
+
+ /* Use saved AAD */
+ if (!ctx->hw->setaad(ctx, ctx->buf, ctx->tls_aad_len))
+ goto err;
+
+ /* Fix buffer to point to payload */
+ in += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ out += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ if (ctx->enc) {
+ if (!ctx->hw->auth_encrypt(ctx, in, out, len, out + len, ctx->m))
+ goto err;
+ olen = len + EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m;
+ } else {
+ if (!ctx->hw->auth_decrypt(ctx, in, out, len,
+ (unsigned char *)in + len, ctx->m))
+ goto err;
+ olen = len;
+ }
+ rv = 1;
+err:
+ *padlen = olen;
+ return rv;
+}
+
+static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out,
+ size_t *padlen, const unsigned char *in,
+ size_t len)
+{
+ int rv = 0;
+ size_t olen = 0;
+ const PROV_CCM_HW *hw = ctx->hw;
+
+ /* If no key set, return error */
+ if (!ctx->key_set)
+ return 0;
+
+ if (ctx->tls_aad_len != UNINITIALISED_SIZET)
+ return ccm_tls_cipher(ctx, out, padlen, in, len);
+
+ /* EVP_*Final() doesn't return any data */
+ if (in == NULL && out != NULL)
+ goto finish;
+
+ if (!ctx->iv_set)
+ goto err;
+
+ if (out == NULL) {
+ if (in == NULL) {
+ if (!ccm_set_iv(ctx, len))
+ goto err;
+ } else {
+ /* If we have AAD, we need a message length */
+ if (!ctx->len_set && len)
+ goto err;
+ if (!hw->setaad(ctx, in, len))
+ goto err;
+ }
+ } else {
+ /* If not set length yet do it */
+ if (!ctx->len_set && !ccm_set_iv(ctx, len))
+ goto err;
+
+ if (ctx->enc) {
+ if (!hw->auth_encrypt(ctx, in, out, len, NULL, 0))
+ goto err;
+ ctx->tag_set = 1;
+ } else {
+ /* The tag must be set before actually decrypting data */
+ if (!ctx->tag_set)
+ goto err;
+
+ if (!hw->auth_decrypt(ctx, in, out, len, ctx->buf, ctx->m))
+ goto err;
+ /* Finished - reset flags so calling this method again will fail */
+ ctx->iv_set = 0;
+ ctx->tag_set = 0;
+ ctx->len_set = 0;
+ }
+ }
+ olen = len;
+finish:
+ rv = 1;
+err:
+ *padlen = olen;
+ return rv;
+}
+
+void ossl_ccm_initctx(PROV_CCM_CTX *ctx, size_t keybits, const PROV_CCM_HW *hw)
+{
+ ctx->keylen = keybits / 8;
+ ctx->key_set = 0;
+ ctx->iv_set = 0;
+ ctx->tag_set = 0;
+ ctx->len_set = 0;
+ ctx->l = 8;
+ ctx->m = 12;
+ ctx->tls_aad_len = UNINITIALISED_SIZET;
+ ctx->hw = hw;
+}
diff --git a/providers/implementations/ciphers/ciphercommon_ccm_hw.c b/providers/implementations/ciphers/ciphercommon_ccm_hw.c
new file mode 100644
index 000000000000..ad3fbc59e4fc
--- /dev/null
+++ b/providers/implementations/ciphers/ciphercommon_ccm_hw.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/ciphercommon.h"
+#include "prov/ciphercommon_ccm.h"
+
+int ossl_ccm_generic_setiv(PROV_CCM_CTX *ctx, const unsigned char *nonce,
+ size_t nlen, size_t mlen)
+{
+ return CRYPTO_ccm128_setiv(&ctx->ccm_ctx, nonce, nlen, mlen) == 0;
+}
+
+int ossl_ccm_generic_setaad(PROV_CCM_CTX *ctx, const unsigned char *aad,
+ size_t alen)
+{
+ CRYPTO_ccm128_aad(&ctx->ccm_ctx, aad, alen);
+ return 1;
+}
+
+int ossl_ccm_generic_gettag(PROV_CCM_CTX *ctx, unsigned char *tag, size_t tlen)
+{
+ return CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, tlen) > 0;
+}
+
+int ossl_ccm_generic_auth_encrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
+ unsigned char *out, size_t len,
+ unsigned char *tag, size_t taglen)
+{
+ int rv;
+
+ if (ctx->str != NULL)
+ rv = CRYPTO_ccm128_encrypt_ccm64(&ctx->ccm_ctx, in,
+ out, len, ctx->str) == 0;
+ else
+ rv = CRYPTO_ccm128_encrypt(&ctx->ccm_ctx, in, out, len) == 0;
+
+ if (rv == 1 && tag != NULL)
+ rv = (CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, taglen) > 0);
+ return rv;
+}
+
+int ossl_ccm_generic_auth_decrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
+ unsigned char *out, size_t len,
+ unsigned char *expected_tag, size_t taglen)
+{
+ int rv = 0;
+
+ if (ctx->str != NULL)
+ rv = CRYPTO_ccm128_decrypt_ccm64(&ctx->ccm_ctx, in, out, len,
+ ctx->str) == 0;
+ else
+ rv = CRYPTO_ccm128_decrypt(&ctx->ccm_ctx, in, out, len) == 0;
+ if (rv) {
+ unsigned char tag[16];
+
+ if (!CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, taglen)
+ || CRYPTO_memcmp(tag, expected_tag, taglen) != 0)
+ rv = 0;
+ }
+ if (rv == 0)
+ OPENSSL_cleanse(out, len);
+ return rv;
+}
diff --git a/providers/implementations/ciphers/ciphercommon_gcm.c b/providers/implementations/ciphers/ciphercommon_gcm.c
new file mode 100644
index 000000000000..ed95c97ff473
--- /dev/null
+++ b/providers/implementations/ciphers/ciphercommon_gcm.c
@@ -0,0 +1,568 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for gcm mode */
+
+#include <openssl/rand.h>
+#include <openssl/proverr.h>
+#include "prov/ciphercommon.h"
+#include "prov/ciphercommon_gcm.h"
+#include "prov/providercommon.h"
+#include "prov/provider_ctx.h"
+
+static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len);
+static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv,
+ size_t len);
+static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen,
+ const unsigned char *in, size_t len);
+static int gcm_cipher_internal(PROV_GCM_CTX *ctx, unsigned char *out,
+ size_t *padlen, const unsigned char *in,
+ size_t len);
+
+/*
+ * Called from EVP_CipherInit when there is currently no context via
+ * the new_ctx() function
+ */
+void ossl_gcm_initctx(void *provctx, PROV_GCM_CTX *ctx, size_t keybits,
+ const PROV_GCM_HW *hw)
+{
+ ctx->pad = 1;
+ ctx->mode = EVP_CIPH_GCM_MODE;
+ ctx->taglen = UNINITIALISED_SIZET;
+ ctx->tls_aad_len = UNINITIALISED_SIZET;
+ ctx->ivlen = (EVP_GCM_TLS_FIXED_IV_LEN + EVP_GCM_TLS_EXPLICIT_IV_LEN);
+ ctx->keylen = keybits / 8;
+ ctx->hw = hw;
+ ctx->libctx = PROV_LIBCTX_OF(provctx);
+}
+
+/*
+ * Called by EVP_CipherInit via the _einit and _dinit functions
+ */
+static int gcm_init(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[], int enc)
+{
+ PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ ctx->enc = enc;
+
+ if (iv != NULL) {
+ if (ivlen == 0 || ivlen > sizeof(ctx->iv)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ ctx->ivlen = ivlen;
+ memcpy(ctx->iv, iv, ivlen);
+ ctx->iv_state = IV_STATE_BUFFERED;
+ }
+
+ if (key != NULL) {
+ if (keylen != ctx->keylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ if (!ctx->hw->setkey(ctx, key, ctx->keylen))
+ return 0;
+ ctx->tls_enc_records = 0;
+ }
+ return ossl_gcm_set_ctx_params(ctx, params);
+}
+
+int ossl_gcm_einit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return gcm_init(vctx, key, keylen, iv, ivlen, params, 1);
+}
+
+int ossl_gcm_dinit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return gcm_init(vctx, key, keylen, iv, ivlen, params, 0);
+}
+
+/* increment counter (64-bit int) by 1 */
+static void ctr64_inc(unsigned char *counter)
+{
+ int n = 8;
+ unsigned char c;
+
+ do {
+ --n;
+ c = counter[n];
+ ++c;
+ counter[n] = c;
+ if (c > 0)
+ return;
+ } while (n > 0);
+}
+
+static int getivgen(PROV_GCM_CTX *ctx, unsigned char *out, size_t olen)
+{
+ if (!ctx->iv_gen
+ || !ctx->key_set
+ || !ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen))
+ return 0;
+ if (olen == 0 || olen > ctx->ivlen)
+ olen = ctx->ivlen;
+ memcpy(out, ctx->iv + ctx->ivlen - olen, olen);
+ /*
+ * Invocation field will be at least 8 bytes in size and so no need
+ * to check wrap around or increment more than last 8 bytes.
+ */
+ ctr64_inc(ctx->iv + ctx->ivlen - 8);
+ ctx->iv_state = IV_STATE_COPIED;
+ return 1;
+}
+
+static int setivinv(PROV_GCM_CTX *ctx, unsigned char *in, size_t inl)
+{
+ if (!ctx->iv_gen
+ || !ctx->key_set
+ || ctx->enc)
+ return 0;
+
+ memcpy(ctx->iv + ctx->ivlen - inl, in, inl);
+ if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen))
+ return 0;
+ ctx->iv_state = IV_STATE_COPIED;
+ return 1;
+}
+
+int ossl_gcm_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
+ OSSL_PARAM *p;
+ size_t sz;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
+ if (p != NULL) {
+ size_t taglen = (ctx->taglen != UNINITIALISED_SIZET) ? ctx->taglen :
+ GCM_TAG_MAX_SIZE;
+
+ if (!OSSL_PARAM_set_size_t(p, taglen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
+ if (p != NULL) {
+ if (ctx->iv_state == IV_STATE_UNINITIALISED)
+ return 0;
+ if (ctx->ivlen > p->data_size) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ if (!OSSL_PARAM_set_octet_string(p, ctx->iv, ctx->ivlen)
+ && !OSSL_PARAM_set_octet_ptr(p, &ctx->iv, ctx->ivlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_UPDATED_IV);
+ if (p != NULL) {
+ if (ctx->iv_state == IV_STATE_UNINITIALISED)
+ return 0;
+ if (ctx->ivlen > p->data_size) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ if (!OSSL_PARAM_set_octet_string(p, ctx->iv, ctx->ivlen)
+ && !OSSL_PARAM_set_octet_ptr(p, &ctx->iv, ctx->ivlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+ if (p != NULL) {
+ sz = p->data_size;
+ if (sz == 0
+ || sz > EVP_GCM_TLS_TAG_LEN
+ || !ctx->enc
+ || ctx->taglen == UNINITIALISED_SIZET) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG);
+ return 0;
+ }
+ if (!OSSL_PARAM_set_octet_string(p, ctx->buf, sz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN);
+ if (p != NULL) {
+ if (p->data == NULL
+ || p->data_type != OSSL_PARAM_OCTET_STRING
+ || !getivgen(ctx, p->data, p->data_size))
+ return 0;
+ }
+ return 1;
+}
+
+int ossl_gcm_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
+ const OSSL_PARAM *p;
+ size_t sz;
+ void *vp;
+
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+ if (p != NULL) {
+ vp = ctx->buf;
+ if (!OSSL_PARAM_get_octet_string(p, &vp, EVP_GCM_TLS_TAG_LEN, &sz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (sz == 0 || ctx->enc) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG);
+ return 0;
+ }
+ ctx->taglen = sz;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &sz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (sz == 0 || sz > sizeof(ctx->iv)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ ctx->ivlen = sz;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ sz = gcm_tls_init(ctx, p->data, p->data_size);
+ if (sz == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_AAD);
+ return 0;
+ }
+ ctx->tls_aad_pad_sz = sz;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (gcm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV);
+ if (p != NULL) {
+ if (p->data == NULL
+ || p->data_type != OSSL_PARAM_OCTET_STRING
+ || !setivinv(ctx, p->data, p->data_size))
+ return 0;
+ }
+
+
+ return 1;
+}
+
+int ossl_gcm_stream_update(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in, size_t inl)
+{
+ PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
+
+ if (inl == 0) {
+ *outl = 0;
+ return 1;
+ }
+
+ if (outsize < inl) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (gcm_cipher_internal(ctx, out, outl, in, inl) <= 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+ return 0;
+ }
+ return 1;
+}
+
+int ossl_gcm_stream_final(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
+ int i;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ i = gcm_cipher_internal(ctx, out, outl, NULL, 0);
+ if (i <= 0)
+ return 0;
+
+ *outl = 0;
+ return 1;
+}
+
+int ossl_gcm_cipher(void *vctx,
+ unsigned char *out, size_t *outl, size_t outsize,
+ const unsigned char *in, size_t inl)
+{
+ PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (outsize < inl) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (gcm_cipher_internal(ctx, out, outl, in, inl) <= 0)
+ return 0;
+
+ *outl = inl;
+ return 1;
+}
+
+/*
+ * See SP800-38D (GCM) Section 8 "Uniqueness requirement on IVS and keys"
+ *
+ * See also 8.2.2 RBG-based construction.
+ * Random construction consists of a free field (which can be NULL) and a
+ * random field which will use a DRBG that can return at least 96 bits of
+ * entropy strength. (The DRBG must be seeded by the FIPS module).
+ */
+static int gcm_iv_generate(PROV_GCM_CTX *ctx, int offset)
+{
+ int sz = ctx->ivlen - offset;
+
+ /* Must be at least 96 bits */
+ if (sz <= 0 || ctx->ivlen < GCM_IV_DEFAULT_SIZE)
+ return 0;
+
+ /* Use DRBG to generate random iv */
+ if (RAND_bytes_ex(ctx->libctx, ctx->iv + offset, sz, 0) <= 0)
+ return 0;
+ ctx->iv_state = IV_STATE_BUFFERED;
+ ctx->iv_gen_rand = 1;
+ return 1;
+}
+
+static int gcm_cipher_internal(PROV_GCM_CTX *ctx, unsigned char *out,
+ size_t *padlen, const unsigned char *in,
+ size_t len)
+{
+ size_t olen = 0;
+ int rv = 0;
+ const PROV_GCM_HW *hw = ctx->hw;
+
+ if (ctx->tls_aad_len != UNINITIALISED_SIZET)
+ return gcm_tls_cipher(ctx, out, padlen, in, len);
+
+ if (!ctx->key_set || ctx->iv_state == IV_STATE_FINISHED)
+ goto err;
+
+ /*
+ * FIPS requires generation of AES-GCM IV's inside the FIPS module.
+ * The IV can still be set externally (the security policy will state that
+ * this is not FIPS compliant). There are some applications
+ * where setting the IV externally is the only option available.
+ */
+ if (ctx->iv_state == IV_STATE_UNINITIALISED) {
+ if (!ctx->enc || !gcm_iv_generate(ctx, 0))
+ goto err;
+ }
+
+ if (ctx->iv_state == IV_STATE_BUFFERED) {
+ if (!hw->setiv(ctx, ctx->iv, ctx->ivlen))
+ goto err;
+ ctx->iv_state = IV_STATE_COPIED;
+ }
+
+ if (in != NULL) {
+ /* The input is AAD if out is NULL */
+ if (out == NULL) {
+ if (!hw->aadupdate(ctx, in, len))
+ goto err;
+ } else {
+ /* The input is ciphertext OR plaintext */
+ if (!hw->cipherupdate(ctx, in, len, out))
+ goto err;
+ }
+ } else {
+ /* The tag must be set before actually decrypting data */
+ if (!ctx->enc && ctx->taglen == UNINITIALISED_SIZET)
+ goto err;
+ if (!hw->cipherfinal(ctx, ctx->buf))
+ goto err;
+ ctx->iv_state = IV_STATE_FINISHED; /* Don't reuse the IV */
+ goto finish;
+ }
+ olen = len;
+finish:
+ rv = 1;
+err:
+ *padlen = olen;
+ return rv;
+}
+
+static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len)
+{
+ unsigned char *buf;
+ size_t len;
+
+ if (!ossl_prov_is_running() || aad_len != EVP_AEAD_TLS1_AAD_LEN)
+ return 0;
+
+ /* Save the aad for later use. */
+ buf = dat->buf;
+ memcpy(buf, aad, aad_len);
+ dat->tls_aad_len = aad_len;
+
+ len = buf[aad_len - 2] << 8 | buf[aad_len - 1];
+ /* Correct length for explicit iv. */
+ if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN)
+ return 0;
+ len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
+
+ /* If decrypting correct for tag too. */
+ if (!dat->enc) {
+ if (len < EVP_GCM_TLS_TAG_LEN)
+ return 0;
+ len -= EVP_GCM_TLS_TAG_LEN;
+ }
+ buf[aad_len - 2] = (unsigned char)(len >> 8);
+ buf[aad_len - 1] = (unsigned char)(len & 0xff);
+ /* Extra padding: tag appended to record. */
+ return EVP_GCM_TLS_TAG_LEN;
+}
+
+static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv,
+ size_t len)
+{
+ /* Special case: -1 length restores whole IV */
+ if (len == (size_t)-1) {
+ memcpy(ctx->iv, iv, ctx->ivlen);
+ ctx->iv_gen = 1;
+ ctx->iv_state = IV_STATE_BUFFERED;
+ return 1;
+ }
+ /* Fixed field must be at least 4 bytes and invocation field at least 8 */
+ if ((len < EVP_GCM_TLS_FIXED_IV_LEN)
+ || (ctx->ivlen - (int)len) < EVP_GCM_TLS_EXPLICIT_IV_LEN)
+ return 0;
+ if (len > 0)
+ memcpy(ctx->iv, iv, len);
+ if (ctx->enc
+ && RAND_bytes_ex(ctx->libctx, ctx->iv + len, ctx->ivlen - len, 0) <= 0)
+ return 0;
+ ctx->iv_gen = 1;
+ ctx->iv_state = IV_STATE_BUFFERED;
+ return 1;
+}
+
+/*
+ * Handle TLS GCM packet format. This consists of the last portion of the IV
+ * followed by the payload and finally the tag. On encrypt generate IV,
+ * encrypt payload and write the tag. On verify retrieve IV, decrypt payload
+ * and verify tag.
+ */
+static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen,
+ const unsigned char *in, size_t len)
+{
+ int rv = 0;
+ size_t arg = EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ size_t plen = 0;
+ unsigned char *tag = NULL;
+
+ if (!ossl_prov_is_running() || !ctx->key_set)
+ goto err;
+
+ /* Encrypt/decrypt must be performed in place */
+ if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
+ goto err;
+
+ /*
+ * Check for too many keys as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness
+ * Requirements from SP 800-38D". The requirements is for one party to the
+ * communication to fail after 2^64 - 1 keys. We do this on the encrypting
+ * side only.
+ */
+ if (ctx->enc && ++ctx->tls_enc_records == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_TOO_MANY_RECORDS);
+ goto err;
+ }
+
+ /*
+ * Set IV from start of buffer or generate IV and write to start of
+ * buffer.
+ */
+ if (ctx->enc) {
+ if (!getivgen(ctx, out, arg))
+ goto err;
+ } else {
+ if (!setivinv(ctx, out, arg))
+ goto err;
+ }
+
+ /* Fix buffer and length to point to payload */
+ in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
+
+ tag = ctx->enc ? out + len : (unsigned char *)in + len;
+ if (!ctx->hw->oneshot(ctx, ctx->buf, ctx->tls_aad_len, in, len, out, tag,
+ EVP_GCM_TLS_TAG_LEN)) {
+ if (!ctx->enc)
+ OPENSSL_cleanse(out, len);
+ goto err;
+ }
+ if (ctx->enc)
+ plen = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
+ else
+ plen = len;
+
+ rv = 1;
+err:
+ ctx->iv_state = IV_STATE_FINISHED;
+ ctx->tls_aad_len = UNINITIALISED_SIZET;
+ *padlen = plen;
+ return rv;
+}
diff --git a/providers/implementations/ciphers/ciphercommon_gcm_hw.c b/providers/implementations/ciphers/ciphercommon_gcm_hw.c
new file mode 100644
index 000000000000..c0a7399640fd
--- /dev/null
+++ b/providers/implementations/ciphers/ciphercommon_gcm_hw.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/ciphercommon.h"
+#include "prov/ciphercommon_gcm.h"
+
+
+int ossl_gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, size_t ivlen)
+{
+ CRYPTO_gcm128_setiv(&ctx->gcm, iv, ivlen);
+ return 1;
+}
+
+int ossl_gcm_aad_update(PROV_GCM_CTX *ctx, const unsigned char *aad,
+ size_t aad_len)
+{
+ return CRYPTO_gcm128_aad(&ctx->gcm, aad, aad_len) == 0;
+}
+
+int ossl_gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
+ size_t len, unsigned char *out)
+{
+ if (ctx->enc) {
+ if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len))
+ return 0;
+ } else {
+ if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len))
+ return 0;
+ }
+ return 1;
+}
+
+int ossl_gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag)
+{
+ if (ctx->enc) {
+ CRYPTO_gcm128_tag(&ctx->gcm, tag, GCM_TAG_MAX_SIZE);
+ ctx->taglen = GCM_TAG_MAX_SIZE;
+ } else {
+ if (CRYPTO_gcm128_finish(&ctx->gcm, tag, ctx->taglen) != 0)
+ return 0;
+ }
+ return 1;
+}
+
+int ossl_gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len,
+ const unsigned char *in, size_t in_len,
+ unsigned char *out, unsigned char *tag, size_t tag_len)
+{
+ int ret = 0;
+
+ /* Use saved AAD */
+ if (!ctx->hw->aadupdate(ctx, aad, aad_len))
+ goto err;
+ if (!ctx->hw->cipherupdate(ctx, in, in_len, out))
+ goto err;
+ ctx->taglen = GCM_TAG_MAX_SIZE;
+ if (!ctx->hw->cipherfinal(ctx, tag))
+ goto err;
+ ret = 1;
+
+err:
+ return ret;
+}
diff --git a/providers/implementations/ciphers/ciphercommon_hw.c b/providers/implementations/ciphers/ciphercommon_hw.c
new file mode 100644
index 000000000000..e73416a1c5c8
--- /dev/null
+++ b/providers/implementations/ciphers/ciphercommon_hw.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/ciphercommon.h"
+
+/*-
+ * The generic cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr.
+ * Used if there is no special hardware implementations.
+ */
+int ossl_cipher_hw_generic_cbc(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ if (dat->stream.cbc)
+ (*dat->stream.cbc) (in, out, len, dat->ks, dat->iv, dat->enc);
+ else if (dat->enc)
+ CRYPTO_cbc128_encrypt(in, out, len, dat->ks, dat->iv, dat->block);
+ else
+ CRYPTO_cbc128_decrypt(in, out, len, dat->ks, dat->iv, dat->block);
+
+ return 1;
+}
+
+int ossl_cipher_hw_generic_ecb(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ size_t i, bl = dat->blocksize;
+
+ if (len < bl)
+ return 1;
+
+ if (dat->stream.ecb) {
+ (*dat->stream.ecb) (in, out, len, dat->ks, dat->enc);
+ }
+ else {
+ for (i = 0, len -= bl; i <= len; i += bl)
+ (*dat->block) (in + i, out + i, dat->ks);
+ }
+
+ return 1;
+}
+
+int ossl_cipher_hw_generic_ofb128(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ int num = dat->num;
+
+ CRYPTO_ofb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->block);
+ dat->num = num;
+
+ return 1;
+}
+
+int ossl_cipher_hw_generic_cfb128(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ int num = dat->num;
+
+ CRYPTO_cfb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc,
+ dat->block);
+ dat->num = num;
+
+ return 1;
+}
+
+int ossl_cipher_hw_generic_cfb8(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ int num = dat->num;
+
+ CRYPTO_cfb128_8_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc,
+ dat->block);
+ dat->num = num;
+
+ return 1;
+}
+
+int ossl_cipher_hw_generic_cfb1(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ int num = dat->num;
+
+ if (dat->use_bits) {
+ CRYPTO_cfb128_1_encrypt(in, out, len, dat->ks, dat->iv, &num,
+ dat->enc, dat->block);
+ dat->num = num;
+ return 1;
+ }
+
+ while (len >= MAXBITCHUNK) {
+ CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, dat->ks,
+ dat->iv, &num, dat->enc, dat->block);
+ len -= MAXBITCHUNK;
+ out += MAXBITCHUNK;
+ in += MAXBITCHUNK;
+ }
+ if (len)
+ CRYPTO_cfb128_1_encrypt(in, out, len * 8, dat->ks, dat->iv, &num,
+ dat->enc, dat->block);
+
+ dat->num = num;
+
+ return 1;
+}
+
+int ossl_cipher_hw_generic_ctr(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ unsigned int num = dat->num;
+
+ if (dat->stream.ctr)
+ CRYPTO_ctr128_encrypt_ctr32(in, out, len, dat->ks, dat->iv, dat->buf,
+ &num, dat->stream.ctr);
+ else
+ CRYPTO_ctr128_encrypt(in, out, len, dat->ks, dat->iv, dat->buf,
+ &num, dat->block);
+ dat->num = num;
+
+ return 1;
+}
+
+/*-
+ * The chunked cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr.
+ * Used if there is no special hardware implementations.
+ */
+
+int ossl_cipher_hw_chunked_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ while (inl >= MAXCHUNK) {
+ ossl_cipher_hw_generic_cbc(ctx, out, in, MAXCHUNK);
+ inl -= MAXCHUNK;
+ in += MAXCHUNK;
+ out += MAXCHUNK;
+ }
+ if (inl > 0)
+ ossl_cipher_hw_generic_cbc(ctx, out, in, inl);
+ return 1;
+}
+
+int ossl_cipher_hw_chunked_cfb8(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ size_t chunk = MAXCHUNK;
+
+ if (inl < chunk)
+ chunk = inl;
+ while (inl > 0 && inl >= chunk) {
+ ossl_cipher_hw_generic_cfb8(ctx, out, in, inl);
+ inl -= chunk;
+ in += chunk;
+ out += chunk;
+ if (inl < chunk)
+ chunk = inl;
+ }
+ return 1;
+}
+
+int ossl_cipher_hw_chunked_cfb128(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ size_t chunk = MAXCHUNK;
+
+ if (inl < chunk)
+ chunk = inl;
+ while (inl > 0 && inl >= chunk) {
+ ossl_cipher_hw_generic_cfb128(ctx, out, in, inl);
+ inl -= chunk;
+ in += chunk;
+ out += chunk;
+ if (inl < chunk)
+ chunk = inl;
+ }
+ return 1;
+}
+
+int ossl_cipher_hw_chunked_ofb128(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ while (inl >= MAXCHUNK) {
+ ossl_cipher_hw_generic_ofb128(ctx, out, in, MAXCHUNK);
+ inl -= MAXCHUNK;
+ in += MAXCHUNK;
+ out += MAXCHUNK;
+ }
+ if (inl > 0)
+ ossl_cipher_hw_generic_ofb128(ctx, out, in, inl);
+ return 1;
+}
diff --git a/providers/implementations/ciphers/ciphercommon_local.h b/providers/implementations/ciphers/ciphercommon_local.h
new file mode 100644
index 000000000000..11cb6116a815
--- /dev/null
+++ b/providers/implementations/ciphers/ciphercommon_local.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/ciphercommon.h"
+
+void ossl_cipher_padblock(unsigned char *buf, size_t *buflen, size_t blocksize);
+int ossl_cipher_unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize);
+int ossl_cipher_tlsunpadblock(OSSL_LIB_CTX *libctx, unsigned int tlsversion,
+ unsigned char *buf, size_t *buflen, size_t blocksize,
+ unsigned char **mac, int *alloced, size_t macsize, int aead);
diff --git a/providers/implementations/digests/blake2_impl.h b/providers/implementations/digests/blake2_impl.h
new file mode 100644
index 000000000000..e7c31474a364
--- /dev/null
+++ b/providers/implementations/digests/blake2_impl.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Derived from the BLAKE2 reference implementation written by Samuel Neves.
+ * Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
+ * More information about the BLAKE2 hash function and its implementations
+ * can be found at https://blake2.net.
+ */
+
+#include <string.h>
+#include "internal/endian.h"
+
+static ossl_inline uint32_t load32(const uint8_t *src)
+{
+ DECLARE_IS_ENDIAN;
+
+ if (IS_LITTLE_ENDIAN) {
+ uint32_t w;
+ memcpy(&w, src, sizeof(w));
+ return w;
+ } else {
+ uint32_t w = ((uint32_t)src[0])
+ | ((uint32_t)src[1] << 8)
+ | ((uint32_t)src[2] << 16)
+ | ((uint32_t)src[3] << 24);
+ return w;
+ }
+}
+
+static ossl_inline uint64_t load64(const uint8_t *src)
+{
+ DECLARE_IS_ENDIAN;
+
+ if (IS_LITTLE_ENDIAN) {
+ uint64_t w;
+ memcpy(&w, src, sizeof(w));
+ return w;
+ } else {
+ uint64_t w = ((uint64_t)src[0])
+ | ((uint64_t)src[1] << 8)
+ | ((uint64_t)src[2] << 16)
+ | ((uint64_t)src[3] << 24)
+ | ((uint64_t)src[4] << 32)
+ | ((uint64_t)src[5] << 40)
+ | ((uint64_t)src[6] << 48)
+ | ((uint64_t)src[7] << 56);
+ return w;
+ }
+}
+
+static ossl_inline void store32(uint8_t *dst, uint32_t w)
+{
+ DECLARE_IS_ENDIAN;
+
+ if (IS_LITTLE_ENDIAN) {
+ memcpy(dst, &w, sizeof(w));
+ } else {
+ uint8_t *p = (uint8_t *)dst;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ p[i] = (uint8_t)(w >> (8 * i));
+ }
+}
+
+static ossl_inline void store64(uint8_t *dst, uint64_t w)
+{
+ DECLARE_IS_ENDIAN;
+
+ if (IS_LITTLE_ENDIAN) {
+ memcpy(dst, &w, sizeof(w));
+ } else {
+ uint8_t *p = (uint8_t *)dst;
+ int i;
+
+ for (i = 0; i < 8; i++)
+ p[i] = (uint8_t)(w >> (8 * i));
+ }
+}
+
+static ossl_inline uint64_t load48(const uint8_t *src)
+{
+ uint64_t w = ((uint64_t)src[0])
+ | ((uint64_t)src[1] << 8)
+ | ((uint64_t)src[2] << 16)
+ | ((uint64_t)src[3] << 24)
+ | ((uint64_t)src[4] << 32)
+ | ((uint64_t)src[5] << 40);
+ return w;
+}
+
+static ossl_inline void store48(uint8_t *dst, uint64_t w)
+{
+ uint8_t *p = (uint8_t *)dst;
+ p[0] = (uint8_t)w;
+ p[1] = (uint8_t)(w>>8);
+ p[2] = (uint8_t)(w>>16);
+ p[3] = (uint8_t)(w>>24);
+ p[4] = (uint8_t)(w>>32);
+ p[5] = (uint8_t)(w>>40);
+}
+
+static ossl_inline uint32_t rotr32(const uint32_t w, const unsigned int c)
+{
+ return (w >> c) | (w << (32 - c));
+}
+
+static ossl_inline uint64_t rotr64(const uint64_t w, const unsigned int c)
+{
+ return (w >> c) | (w << (64 - c));
+}
diff --git a/providers/implementations/digests/blake2_prov.c b/providers/implementations/digests/blake2_prov.c
new file mode 100644
index 000000000000..25342eedb832
--- /dev/null
+++ b/providers/implementations/digests/blake2_prov.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include "prov/blake2.h"
+#include "prov/digestcommon.h"
+#include "prov/implementations.h"
+
+int ossl_blake2s256_init(void *ctx)
+{
+ BLAKE2S_PARAM P;
+
+ ossl_blake2s_param_init(&P);
+ return ossl_blake2s_init((BLAKE2S_CTX *)ctx, &P);
+}
+
+int ossl_blake2b512_init(void *ctx)
+{
+ BLAKE2B_PARAM P;
+
+ ossl_blake2b_param_init(&P);
+ return ossl_blake2b_init((BLAKE2B_CTX *)ctx, &P);
+}
+
+/* ossl_blake2s256_functions */
+IMPLEMENT_digest_functions(blake2s256, BLAKE2S_CTX,
+ BLAKE2S_BLOCKBYTES, BLAKE2S_DIGEST_LENGTH, 0,
+ ossl_blake2s256_init, ossl_blake2s_update,
+ ossl_blake2s_final)
+
+/* ossl_blake2b512_functions */
+IMPLEMENT_digest_functions(blake2b512, BLAKE2B_CTX,
+ BLAKE2B_BLOCKBYTES, BLAKE2B_DIGEST_LENGTH, 0,
+ ossl_blake2b512_init, ossl_blake2b_update,
+ ossl_blake2b_final)
diff --git a/providers/implementations/digests/blake2b_prov.c b/providers/implementations/digests/blake2b_prov.c
new file mode 100644
index 000000000000..11271e1b59d3
--- /dev/null
+++ b/providers/implementations/digests/blake2b_prov.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Derived from the BLAKE2 reference implementation written by Samuel Neves.
+ * Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
+ * More information about the BLAKE2 hash function and its implementations
+ * can be found at https://blake2.net.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <openssl/crypto.h>
+#include "blake2_impl.h"
+#include "prov/blake2.h"
+
+static const uint64_t blake2b_IV[8] =
+{
+ 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+};
+
+static const uint8_t blake2b_sigma[12][16] =
+{
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
+ { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
+ { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
+ { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
+ { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
+ { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
+ { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
+ { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
+ { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
+};
+
+/* Set that it's the last block we'll compress */
+static ossl_inline void blake2b_set_lastblock(BLAKE2B_CTX *S)
+{
+ S->f[0] = -1;
+}
+
+/* Initialize the hashing state. */
+static ossl_inline void blake2b_init0(BLAKE2B_CTX *S)
+{
+ int i;
+
+ memset(S, 0, sizeof(BLAKE2B_CTX));
+ for (i = 0; i < 8; ++i) {
+ S->h[i] = blake2b_IV[i];
+ }
+}
+
+/* init xors IV with input parameter block and sets the output length */
+static void blake2b_init_param(BLAKE2B_CTX *S, const BLAKE2B_PARAM *P)
+{
+ size_t i;
+ const uint8_t *p = (const uint8_t *)(P);
+
+ blake2b_init0(S);
+ S->outlen = P->digest_length;
+
+ /* The param struct is carefully hand packed, and should be 64 bytes on
+ * every platform. */
+ assert(sizeof(BLAKE2B_PARAM) == 64);
+ /* IV XOR ParamBlock */
+ for (i = 0; i < 8; ++i) {
+ S->h[i] ^= load64(p + sizeof(S->h[i]) * i);
+ }
+}
+
+/* Initialize the parameter block with default values */
+void ossl_blake2b_param_init(BLAKE2B_PARAM *P)
+{
+ P->digest_length = BLAKE2B_DIGEST_LENGTH;
+ P->key_length = 0;
+ P->fanout = 1;
+ P->depth = 1;
+ store32(P->leaf_length, 0);
+ store64(P->node_offset, 0);
+ P->node_depth = 0;
+ P->inner_length = 0;
+ memset(P->reserved, 0, sizeof(P->reserved));
+ memset(P->salt, 0, sizeof(P->salt));
+ memset(P->personal, 0, sizeof(P->personal));
+}
+
+void ossl_blake2b_param_set_digest_length(BLAKE2B_PARAM *P, uint8_t outlen)
+{
+ P->digest_length = outlen;
+}
+
+void ossl_blake2b_param_set_key_length(BLAKE2B_PARAM *P, uint8_t keylen)
+{
+ P->key_length = keylen;
+}
+
+void ossl_blake2b_param_set_personal(BLAKE2B_PARAM *P, const uint8_t *personal,
+ size_t len)
+{
+ memcpy(P->personal, personal, len);
+ memset(P->personal + len, 0, BLAKE2B_PERSONALBYTES - len);
+}
+
+void ossl_blake2b_param_set_salt(BLAKE2B_PARAM *P, const uint8_t *salt,
+ size_t len)
+{
+ memcpy(P->salt, salt, len);
+ memset(P->salt + len, 0, BLAKE2B_SALTBYTES - len);
+}
+
+/*
+ * Initialize the hashing context with the given parameter block.
+ * Always returns 1.
+ */
+int ossl_blake2b_init(BLAKE2B_CTX *c, const BLAKE2B_PARAM *P)
+{
+ blake2b_init_param(c, P);
+ return 1;
+}
+
+/*
+ * Initialize the hashing context with the given parameter block and key.
+ * Always returns 1.
+ */
+int ossl_blake2b_init_key(BLAKE2B_CTX *c, const BLAKE2B_PARAM *P,
+ const void *key)
+{
+ blake2b_init_param(c, P);
+
+ /* Pad the key to form first data block */
+ {
+ uint8_t block[BLAKE2B_BLOCKBYTES] = {0};
+
+ memcpy(block, key, P->key_length);
+ ossl_blake2b_update(c, block, BLAKE2B_BLOCKBYTES);
+ OPENSSL_cleanse(block, BLAKE2B_BLOCKBYTES);
+ }
+
+ return 1;
+}
+
+/* Permute the state while xoring in the block of data. */
+static void blake2b_compress(BLAKE2B_CTX *S,
+ const uint8_t *blocks,
+ size_t len)
+{
+ uint64_t m[16];
+ uint64_t v[16];
+ int i;
+ size_t increment;
+
+ /*
+ * There are two distinct usage vectors for this function:
+ *
+ * a) BLAKE2b_Update uses it to process complete blocks,
+ * possibly more than one at a time;
+ *
+ * b) BLAK2b_Final uses it to process last block, always
+ * single but possibly incomplete, in which case caller
+ * pads input with zeros.
+ */
+ assert(len < BLAKE2B_BLOCKBYTES || len % BLAKE2B_BLOCKBYTES == 0);
+
+ /*
+ * Since last block is always processed with separate call,
+ * |len| not being multiple of complete blocks can be observed
+ * only with |len| being less than BLAKE2B_BLOCKBYTES ("less"
+ * including even zero), which is why following assignment doesn't
+ * have to reside inside the main loop below.
+ */
+ increment = len < BLAKE2B_BLOCKBYTES ? len : BLAKE2B_BLOCKBYTES;
+
+ for (i = 0; i < 8; ++i) {
+ v[i] = S->h[i];
+ }
+
+ do {
+ for (i = 0; i < 16; ++i) {
+ m[i] = load64(blocks + i * sizeof(m[i]));
+ }
+
+ /* blake2b_increment_counter */
+ S->t[0] += increment;
+ S->t[1] += (S->t[0] < increment);
+
+ v[8] = blake2b_IV[0];
+ v[9] = blake2b_IV[1];
+ v[10] = blake2b_IV[2];
+ v[11] = blake2b_IV[3];
+ v[12] = S->t[0] ^ blake2b_IV[4];
+ v[13] = S->t[1] ^ blake2b_IV[5];
+ v[14] = S->f[0] ^ blake2b_IV[6];
+ v[15] = S->f[1] ^ blake2b_IV[7];
+#define G(r,i,a,b,c,d) \
+ do { \
+ a = a + b + m[blake2b_sigma[r][2*i+0]]; \
+ d = rotr64(d ^ a, 32); \
+ c = c + d; \
+ b = rotr64(b ^ c, 24); \
+ a = a + b + m[blake2b_sigma[r][2*i+1]]; \
+ d = rotr64(d ^ a, 16); \
+ c = c + d; \
+ b = rotr64(b ^ c, 63); \
+ } while (0)
+#define ROUND(r) \
+ do { \
+ G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
+ G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
+ G(r,2,v[ 2],v[ 6],v[10],v[14]); \
+ G(r,3,v[ 3],v[ 7],v[11],v[15]); \
+ G(r,4,v[ 0],v[ 5],v[10],v[15]); \
+ G(r,5,v[ 1],v[ 6],v[11],v[12]); \
+ G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
+ G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
+ } while (0)
+#if defined(OPENSSL_SMALL_FOOTPRINT)
+ /* 3x size reduction on x86_64, almost 7x on ARMv8, 9x on ARMv4 */
+ for (i = 0; i < 12; i++) {
+ ROUND(i);
+ }
+#else
+ ROUND(0);
+ ROUND(1);
+ ROUND(2);
+ ROUND(3);
+ ROUND(4);
+ ROUND(5);
+ ROUND(6);
+ ROUND(7);
+ ROUND(8);
+ ROUND(9);
+ ROUND(10);
+ ROUND(11);
+#endif
+
+ for (i = 0; i < 8; ++i) {
+ S->h[i] = v[i] ^= v[i + 8] ^ S->h[i];
+ }
+#undef G
+#undef ROUND
+ blocks += increment;
+ len -= increment;
+ } while (len);
+}
+
+/* Absorb the input data into the hash state. Always returns 1. */
+int ossl_blake2b_update(BLAKE2B_CTX *c, const void *data, size_t datalen)
+{
+ const uint8_t *in = data;
+ size_t fill;
+
+ /*
+ * Intuitively one would expect intermediate buffer, c->buf, to
+ * store incomplete blocks. But in this case we are interested to
+ * temporarily stash even complete blocks, because last one in the
+ * stream has to be treated in special way, and at this point we
+ * don't know if last block in *this* call is last one "ever". This
+ * is the reason for why |datalen| is compared as >, and not >=.
+ */
+ fill = sizeof(c->buf) - c->buflen;
+ if (datalen > fill) {
+ if (c->buflen) {
+ memcpy(c->buf + c->buflen, in, fill); /* Fill buffer */
+ blake2b_compress(c, c->buf, BLAKE2B_BLOCKBYTES);
+ c->buflen = 0;
+ in += fill;
+ datalen -= fill;
+ }
+ if (datalen > BLAKE2B_BLOCKBYTES) {
+ size_t stashlen = datalen % BLAKE2B_BLOCKBYTES;
+ /*
+ * If |datalen| is a multiple of the blocksize, stash
+ * last complete block, it can be final one...
+ */
+ stashlen = stashlen ? stashlen : BLAKE2B_BLOCKBYTES;
+ datalen -= stashlen;
+ blake2b_compress(c, in, datalen);
+ in += datalen;
+ datalen = stashlen;
+ }
+ }
+
+ assert(datalen <= BLAKE2B_BLOCKBYTES);
+
+ memcpy(c->buf + c->buflen, in, datalen);
+ c->buflen += datalen; /* Be lazy, do not compress */
+
+ return 1;
+}
+
+/*
+ * Calculate the final hash and save it in md.
+ * Always returns 1.
+ */
+int ossl_blake2b_final(unsigned char *md, BLAKE2B_CTX *c)
+{
+ uint8_t outbuffer[BLAKE2B_OUTBYTES] = {0};
+ uint8_t *target = outbuffer;
+ int iter = (c->outlen + 7) / 8;
+ int i;
+
+ /* Avoid writing to the temporary buffer if possible */
+ if ((c->outlen % sizeof(c->h[0])) == 0)
+ target = md;
+
+ blake2b_set_lastblock(c);
+ /* Padding */
+ memset(c->buf + c->buflen, 0, sizeof(c->buf) - c->buflen);
+ blake2b_compress(c, c->buf, c->buflen);
+
+ /* Output full hash to buffer */
+ for (i = 0; i < iter; ++i)
+ store64(target + sizeof(c->h[i]) * i, c->h[i]);
+
+ if (target != md)
+ memcpy(md, target, c->outlen);
+
+ OPENSSL_cleanse(c, sizeof(BLAKE2B_CTX));
+ return 1;
+}
diff --git a/providers/implementations/digests/blake2s_prov.c b/providers/implementations/digests/blake2s_prov.c
new file mode 100644
index 000000000000..a9a8f9d048a2
--- /dev/null
+++ b/providers/implementations/digests/blake2s_prov.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Derived from the BLAKE2 reference implementation written by Samuel Neves.
+ * Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
+ * More information about the BLAKE2 hash function and its implementations
+ * can be found at https://blake2.net.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <openssl/crypto.h>
+#include "blake2_impl.h"
+#include "prov/blake2.h"
+
+static const uint32_t blake2s_IV[8] =
+{
+ 0x6A09E667U, 0xBB67AE85U, 0x3C6EF372U, 0xA54FF53AU,
+ 0x510E527FU, 0x9B05688CU, 0x1F83D9ABU, 0x5BE0CD19U
+};
+
+static const uint8_t blake2s_sigma[10][16] =
+{
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
+ { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
+ { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
+ { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
+ { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
+ { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
+ { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
+ { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
+ { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
+};
+
+/* Set that it's the last block we'll compress */
+static ossl_inline void blake2s_set_lastblock(BLAKE2S_CTX *S)
+{
+ S->f[0] = -1;
+}
+
+/* Initialize the hashing state. */
+static ossl_inline void blake2s_init0(BLAKE2S_CTX *S)
+{
+ int i;
+
+ memset(S, 0, sizeof(BLAKE2S_CTX));
+ for (i = 0; i < 8; ++i) {
+ S->h[i] = blake2s_IV[i];
+ }
+}
+
+/* init xors IV with input parameter block and sets the output length */
+static void blake2s_init_param(BLAKE2S_CTX *S, const BLAKE2S_PARAM *P)
+{
+ size_t i;
+ const uint8_t *p = (const uint8_t *)(P);
+
+ blake2s_init0(S);
+ S->outlen = P->digest_length;
+
+ /* The param struct is carefully hand packed, and should be 32 bytes on
+ * every platform. */
+ assert(sizeof(BLAKE2S_PARAM) == 32);
+ /* IV XOR ParamBlock */
+ for (i = 0; i < 8; ++i) {
+ S->h[i] ^= load32(&p[i*4]);
+ }
+}
+
+void ossl_blake2s_param_init(BLAKE2S_PARAM *P)
+{
+ P->digest_length = BLAKE2S_DIGEST_LENGTH;
+ P->key_length = 0;
+ P->fanout = 1;
+ P->depth = 1;
+ store32(P->leaf_length, 0);
+ store48(P->node_offset, 0);
+ P->node_depth = 0;
+ P->inner_length = 0;
+ memset(P->salt, 0, sizeof(P->salt));
+ memset(P->personal, 0, sizeof(P->personal));
+}
+
+void ossl_blake2s_param_set_digest_length(BLAKE2S_PARAM *P, uint8_t outlen)
+{
+ P->digest_length = outlen;
+}
+
+void ossl_blake2s_param_set_key_length(BLAKE2S_PARAM *P, uint8_t keylen)
+{
+ P->key_length = keylen;
+}
+
+void ossl_blake2s_param_set_personal(BLAKE2S_PARAM *P, const uint8_t *personal,
+ size_t len)
+{
+ memcpy(P->personal, personal, len);
+ memset(P->personal + len, 0, BLAKE2S_PERSONALBYTES - len);
+}
+
+void ossl_blake2s_param_set_salt(BLAKE2S_PARAM *P, const uint8_t *salt,
+ size_t len)
+{
+ memcpy(P->salt, salt, len);
+ memset(P->salt + len, 0, BLAKE2S_SALTBYTES - len);}
+
+/*
+ * Initialize the hashing context with the given parameter block.
+ * Always returns 1.
+ */
+int ossl_blake2s_init(BLAKE2S_CTX *c, const BLAKE2S_PARAM *P)
+{
+ blake2s_init_param(c, P);
+ return 1;
+}
+
+/*
+ * Initialize the hashing context with the given parameter block and key.
+ * Always returns 1.
+ */
+int ossl_blake2s_init_key(BLAKE2S_CTX *c, const BLAKE2S_PARAM *P,
+ const void *key)
+{
+ blake2s_init_param(c, P);
+
+ /* Pad the key to form first data block */
+ {
+ uint8_t block[BLAKE2S_BLOCKBYTES] = {0};
+
+ memcpy(block, key, P->key_length);
+ ossl_blake2s_update(c, block, BLAKE2S_BLOCKBYTES);
+ OPENSSL_cleanse(block, BLAKE2S_BLOCKBYTES);
+ }
+
+ return 1;
+}
+
+/* Permute the state while xoring in the block of data. */
+static void blake2s_compress(BLAKE2S_CTX *S,
+ const uint8_t *blocks,
+ size_t len)
+{
+ uint32_t m[16];
+ uint32_t v[16];
+ size_t i;
+ size_t increment;
+
+ /*
+ * There are two distinct usage vectors for this function:
+ *
+ * a) BLAKE2s_Update uses it to process complete blocks,
+ * possibly more than one at a time;
+ *
+ * b) BLAK2s_Final uses it to process last block, always
+ * single but possibly incomplete, in which case caller
+ * pads input with zeros.
+ */
+ assert(len < BLAKE2S_BLOCKBYTES || len % BLAKE2S_BLOCKBYTES == 0);
+
+ /*
+ * Since last block is always processed with separate call,
+ * |len| not being multiple of complete blocks can be observed
+ * only with |len| being less than BLAKE2S_BLOCKBYTES ("less"
+ * including even zero), which is why following assignment doesn't
+ * have to reside inside the main loop below.
+ */
+ increment = len < BLAKE2S_BLOCKBYTES ? len : BLAKE2S_BLOCKBYTES;
+
+ for (i = 0; i < 8; ++i) {
+ v[i] = S->h[i];
+ }
+
+ do {
+ for (i = 0; i < 16; ++i) {
+ m[i] = load32(blocks + i * sizeof(m[i]));
+ }
+
+ /* blake2s_increment_counter */
+ S->t[0] += increment;
+ S->t[1] += (S->t[0] < increment);
+
+ v[ 8] = blake2s_IV[0];
+ v[ 9] = blake2s_IV[1];
+ v[10] = blake2s_IV[2];
+ v[11] = blake2s_IV[3];
+ v[12] = S->t[0] ^ blake2s_IV[4];
+ v[13] = S->t[1] ^ blake2s_IV[5];
+ v[14] = S->f[0] ^ blake2s_IV[6];
+ v[15] = S->f[1] ^ blake2s_IV[7];
+#define G(r,i,a,b,c,d) \
+ do { \
+ a = a + b + m[blake2s_sigma[r][2*i+0]]; \
+ d = rotr32(d ^ a, 16); \
+ c = c + d; \
+ b = rotr32(b ^ c, 12); \
+ a = a + b + m[blake2s_sigma[r][2*i+1]]; \
+ d = rotr32(d ^ a, 8); \
+ c = c + d; \
+ b = rotr32(b ^ c, 7); \
+ } while (0)
+#define ROUND(r) \
+ do { \
+ G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
+ G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
+ G(r,2,v[ 2],v[ 6],v[10],v[14]); \
+ G(r,3,v[ 3],v[ 7],v[11],v[15]); \
+ G(r,4,v[ 0],v[ 5],v[10],v[15]); \
+ G(r,5,v[ 1],v[ 6],v[11],v[12]); \
+ G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
+ G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
+ } while (0)
+#if defined(OPENSSL_SMALL_FOOTPRINT)
+ /* almost 3x reduction on x86_64, 4.5x on ARMv8, 4x on ARMv4 */
+ for (i = 0; i < 10; i++) {
+ ROUND(i);
+ }
+#else
+ ROUND(0);
+ ROUND(1);
+ ROUND(2);
+ ROUND(3);
+ ROUND(4);
+ ROUND(5);
+ ROUND(6);
+ ROUND(7);
+ ROUND(8);
+ ROUND(9);
+#endif
+
+ for (i = 0; i < 8; ++i) {
+ S->h[i] = v[i] ^= v[i + 8] ^ S->h[i];
+ }
+#undef G
+#undef ROUND
+ blocks += increment;
+ len -= increment;
+ } while (len);
+}
+
+/* Absorb the input data into the hash state. Always returns 1. */
+int ossl_blake2s_update(BLAKE2S_CTX *c, const void *data, size_t datalen)
+{
+ const uint8_t *in = data;
+ size_t fill;
+
+ /*
+ * Intuitively one would expect intermediate buffer, c->buf, to
+ * store incomplete blocks. But in this case we are interested to
+ * temporarily stash even complete blocks, because last one in the
+ * stream has to be treated in special way, and at this point we
+ * don't know if last block in *this* call is last one "ever". This
+ * is the reason for why |datalen| is compared as >, and not >=.
+ */
+ fill = sizeof(c->buf) - c->buflen;
+ if (datalen > fill) {
+ if (c->buflen) {
+ memcpy(c->buf + c->buflen, in, fill); /* Fill buffer */
+ blake2s_compress(c, c->buf, BLAKE2S_BLOCKBYTES);
+ c->buflen = 0;
+ in += fill;
+ datalen -= fill;
+ }
+ if (datalen > BLAKE2S_BLOCKBYTES) {
+ size_t stashlen = datalen % BLAKE2S_BLOCKBYTES;
+ /*
+ * If |datalen| is a multiple of the blocksize, stash
+ * last complete block, it can be final one...
+ */
+ stashlen = stashlen ? stashlen : BLAKE2S_BLOCKBYTES;
+ datalen -= stashlen;
+ blake2s_compress(c, in, datalen);
+ in += datalen;
+ datalen = stashlen;
+ }
+ }
+
+ assert(datalen <= BLAKE2S_BLOCKBYTES);
+
+ memcpy(c->buf + c->buflen, in, datalen);
+ c->buflen += datalen; /* Be lazy, do not compress */
+
+ return 1;
+}
+
+/*
+ * Calculate the final hash and save it in md.
+ * Always returns 1.
+ */
+int ossl_blake2s_final(unsigned char *md, BLAKE2S_CTX *c)
+{
+ uint8_t outbuffer[BLAKE2S_OUTBYTES] = {0};
+ uint8_t *target = outbuffer;
+ int iter = (c->outlen + 3) / 4;
+ int i;
+
+ /* Avoid writing to the temporary buffer if possible */
+ if ((c->outlen % sizeof(c->h[0])) == 0)
+ target = md;
+
+ blake2s_set_lastblock(c);
+ /* Padding */
+ memset(c->buf + c->buflen, 0, sizeof(c->buf) - c->buflen);
+ blake2s_compress(c, c->buf, c->buflen);
+
+ /* Output full hash to buffer */
+ for (i = 0; i < iter; ++i)
+ store32(target + sizeof(c->h[i]) * i, c->h[i]);
+
+ if (target != md)
+ memcpy(md, target, c->outlen);
+
+ OPENSSL_cleanse(c, sizeof(BLAKE2S_CTX));
+ return 1;
+}
diff --git a/providers/implementations/digests/build.info b/providers/implementations/digests/build.info
new file mode 100644
index 000000000000..d30975028e9f
--- /dev/null
+++ b/providers/implementations/digests/build.info
@@ -0,0 +1,62 @@
+# We make separate GOAL variables for each algorithm, to make it easy to
+# switch each to the Legacy provider when needed.
+
+$COMMON_GOAL=../../libcommon.a
+
+$SHA1_GOAL=../../libdefault.a ../../libfips.a
+$SHA2_GOAL=../../libdefault.a ../../libfips.a
+$SHA3_GOAL=../../libdefault.a ../../libfips.a
+$BLAKE2_GOAL=../../libdefault.a
+$SM3_GOAL=../../libdefault.a
+$MD5_GOAL=../../libdefault.a
+$NULL_GOAL=../../libdefault.a
+
+$MD2_GOAL=../../liblegacy.a
+$MD4_GOAL=../../liblegacy.a
+$MDC2_GOAL=../../liblegacy.a
+$WHIRLPOOL_GOAL=../../liblegacy.a
+IF[{- !$disabled{module} -}]
+ $RIPEMD_GOAL=../../libdefault.a ../../liblegacy.a
+ELSE
+ $RIPEMD_GOAL=../../libdefault.a
+ENDIF
+
+# This source is common for all digests in all our providers.
+SOURCE[$COMMON_GOAL]=digestcommon.c
+
+SOURCE[$SHA2_GOAL]=sha2_prov.c
+SOURCE[$SHA3_GOAL]=sha3_prov.c
+
+SOURCE[$NULL_GOAL]=null_prov.c
+
+IF[{- !$disabled{blake2} -}]
+ SOURCE[$BLAKE2_GOAL]=blake2_prov.c blake2b_prov.c blake2s_prov.c
+ENDIF
+
+IF[{- !$disabled{sm3} -}]
+ SOURCE[$SM3_GOAL]=sm3_prov.c
+ENDIF
+
+IF[{- !$disabled{md5} -}]
+ SOURCE[$MD5_GOAL]=md5_prov.c md5_sha1_prov.c
+ENDIF
+
+IF[{- !$disabled{md2} -}]
+ SOURCE[$MD2_GOAL]=md2_prov.c
+ENDIF
+
+IF[{- !$disabled{md4} -}]
+ SOURCE[$MD4_GOAL]=md4_prov.c
+ENDIF
+
+IF[{- !$disabled{mdc2} -}]
+ SOURCE[$MDC2_GOAL]=mdc2_prov.c
+ENDIF
+
+IF[{- !$disabled{whirlpool} -}]
+ SOURCE[$WHIRLPOOL_GOAL]=wp_prov.c
+ENDIF
+
+IF[{- !$disabled{rmd160} -}]
+ SOURCE[$RIPEMD_GOAL]=ripemd_prov.c
+ENDIF
diff --git a/providers/implementations/digests/digestcommon.c b/providers/implementations/digests/digestcommon.c
new file mode 100644
index 000000000000..5cd1d1620062
--- /dev/null
+++ b/providers/implementations/digests/digestcommon.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include "prov/digestcommon.h"
+
+int ossl_digest_default_get_params(OSSL_PARAM params[], size_t blksz,
+ size_t paramsz, unsigned long flags)
+{
+ OSSL_PARAM *p = NULL;
+
+ p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_BLOCK_SIZE);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, blksz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_SIZE);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, paramsz)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_XOF);
+ if (p != NULL
+ && !OSSL_PARAM_set_int(p, (flags & PROV_DIGEST_FLAG_XOF) != 0)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_ALGID_ABSENT);
+ if (p != NULL
+ && !OSSL_PARAM_set_int(p, (flags & PROV_DIGEST_FLAG_ALGID_ABSENT) != 0)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ return 1;
+}
+
+static const OSSL_PARAM digest_default_known_gettable_params[] = {
+ OSSL_PARAM_size_t(OSSL_DIGEST_PARAM_BLOCK_SIZE, NULL),
+ OSSL_PARAM_size_t(OSSL_DIGEST_PARAM_SIZE, NULL),
+ OSSL_PARAM_int(OSSL_DIGEST_PARAM_XOF, NULL),
+ OSSL_PARAM_int(OSSL_DIGEST_PARAM_ALGID_ABSENT, NULL),
+ OSSL_PARAM_END
+};
+const OSSL_PARAM *ossl_digest_default_gettable_params(void *provctx)
+{
+ return digest_default_known_gettable_params;
+}
diff --git a/providers/implementations/digests/md2_prov.c b/providers/implementations/digests/md2_prov.c
new file mode 100644
index 000000000000..a41a02c19890
--- /dev/null
+++ b/providers/implementations/digests/md2_prov.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * MD2 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/crypto.h>
+#include <openssl/md2.h>
+#include "prov/digestcommon.h"
+#include "prov/implementations.h"
+
+/* ossl_md2_functions */
+IMPLEMENT_digest_functions(md2, MD2_CTX,
+ MD2_BLOCK, MD2_DIGEST_LENGTH, 0,
+ MD2_Init, MD2_Update, MD2_Final)
diff --git a/providers/implementations/digests/md4_prov.c b/providers/implementations/digests/md4_prov.c
new file mode 100644
index 000000000000..97f73018c275
--- /dev/null
+++ b/providers/implementations/digests/md4_prov.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * MD4 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/crypto.h>
+#include <openssl/md4.h>
+#include "prov/digestcommon.h"
+#include "prov/implementations.h"
+
+/* ossl_md4_functions */
+IMPLEMENT_digest_functions(md4, MD4_CTX,
+ MD4_CBLOCK, MD4_DIGEST_LENGTH, 0,
+ MD4_Init, MD4_Update, MD4_Final)
diff --git a/providers/implementations/digests/md5_prov.c b/providers/implementations/digests/md5_prov.c
new file mode 100644
index 000000000000..a330e057f547
--- /dev/null
+++ b/providers/implementations/digests/md5_prov.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * MD5 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/crypto.h>
+#include <openssl/md5.h>
+#include "prov/digestcommon.h"
+#include "prov/implementations.h"
+
+/* ossl_md5_functions */
+IMPLEMENT_digest_functions(md5, MD5_CTX,
+ MD5_CBLOCK, MD5_DIGEST_LENGTH, 0,
+ MD5_Init, MD5_Update, MD5_Final)
diff --git a/providers/implementations/digests/md5_sha1_prov.c b/providers/implementations/digests/md5_sha1_prov.c
new file mode 100644
index 000000000000..e7b8389b2b5c
--- /dev/null
+++ b/providers/implementations/digests/md5_sha1_prov.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * MD5 and SHA-1 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
+#include "prov/md5_sha1.h"
+#include "prov/digestcommon.h"
+#include "prov/implementations.h"
+
+static OSSL_FUNC_digest_set_ctx_params_fn md5_sha1_set_ctx_params;
+static OSSL_FUNC_digest_settable_ctx_params_fn md5_sha1_settable_ctx_params;
+
+static const OSSL_PARAM known_md5_sha1_settable_ctx_params[] = {
+ {OSSL_DIGEST_PARAM_SSL3_MS, OSSL_PARAM_OCTET_STRING, NULL, 0, 0},
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *md5_sha1_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ return known_md5_sha1_settable_ctx_params;
+}
+
+/* Special set_params method for SSL3 */
+static int md5_sha1_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ MD5_SHA1_CTX *ctx = (MD5_SHA1_CTX *)vctx;
+
+ if (ctx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_DIGEST_PARAM_SSL3_MS);
+ if (p != NULL && p->data_type == OSSL_PARAM_OCTET_STRING)
+ return ossl_md5_sha1_ctrl(ctx, EVP_CTRL_SSL3_MASTER_SECRET,
+ p->data_size, p->data);
+ return 1;
+}
+
+/* ossl_md5_sha1_functions */
+IMPLEMENT_digest_functions_with_settable_ctx(
+ md5_sha1, MD5_SHA1_CTX, MD5_SHA1_CBLOCK, MD5_SHA1_DIGEST_LENGTH, 0,
+ ossl_md5_sha1_init, ossl_md5_sha1_update, ossl_md5_sha1_final,
+ md5_sha1_settable_ctx_params, md5_sha1_set_ctx_params)
diff --git a/providers/implementations/digests/mdc2_prov.c b/providers/implementations/digests/mdc2_prov.c
new file mode 100644
index 000000000000..de39f8a10482
--- /dev/null
+++ b/providers/implementations/digests/mdc2_prov.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * MDC2 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/crypto.h>
+#include <openssl/params.h>
+#include <openssl/mdc2.h>
+#include <openssl/core_names.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include "prov/digestcommon.h"
+#include "prov/implementations.h"
+
+static OSSL_FUNC_digest_set_ctx_params_fn mdc2_set_ctx_params;
+static OSSL_FUNC_digest_settable_ctx_params_fn mdc2_settable_ctx_params;
+
+static const OSSL_PARAM known_mdc2_settable_ctx_params[] = {
+ OSSL_PARAM_uint(OSSL_DIGEST_PARAM_PAD_TYPE, NULL),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *mdc2_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ return known_mdc2_settable_ctx_params;
+}
+
+static int mdc2_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ MDC2_CTX *ctx = (MDC2_CTX *)vctx;
+
+ if (ctx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_DIGEST_PARAM_PAD_TYPE);
+ if (p != NULL && !OSSL_PARAM_get_uint(p, &ctx->pad_type)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ return 1;
+}
+
+/* ossl_mdc2_functions */
+IMPLEMENT_digest_functions_with_settable_ctx(
+ mdc2, MDC2_CTX, MDC2_BLOCK, MDC2_DIGEST_LENGTH, 0,
+ MDC2_Init, MDC2_Update, MDC2_Final,
+ mdc2_settable_ctx_params, mdc2_set_ctx_params)
diff --git a/providers/implementations/digests/null_prov.c b/providers/implementations/digests/null_prov.c
new file mode 100644
index 000000000000..b220a1966ff7
--- /dev/null
+++ b/providers/implementations/digests/null_prov.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include "prov/digestcommon.h"
+#include "prov/implementations.h"
+
+typedef struct {
+ unsigned char nothing;
+} NULLMD_CTX;
+
+static int null_init(NULLMD_CTX *ctx)
+{
+ return 1;
+}
+
+static int null_update(NULLMD_CTX *ctx, const void *data, size_t datalen)
+{
+ return 1;
+}
+
+static int null_final(unsigned char *md, NULLMD_CTX *ctx)
+{
+ return 1;
+}
+
+/*
+ * We must override the PROV_FUNC_DIGEST_FINAL as dgstsize == 0
+ * and that would cause compilation warnings with the default implementation.
+ */
+#undef PROV_FUNC_DIGEST_FINAL
+#define PROV_FUNC_DIGEST_FINAL(name, dgstsize, fin) \
+static OSSL_FUNC_digest_final_fn name##_internal_final; \
+static int name##_internal_final(void *ctx, unsigned char *out, size_t *outl, \
+ size_t outsz) \
+{ \
+ if (ossl_prov_is_running() && fin(out, ctx)) { \
+ *outl = dgstsize; \
+ return 1; \
+ } \
+ return 0; \
+}
+
+IMPLEMENT_digest_functions(nullmd, NULLMD_CTX,
+ 0, 0, 0,
+ null_init, null_update, null_final)
diff --git a/providers/implementations/digests/ripemd_prov.c b/providers/implementations/digests/ripemd_prov.c
new file mode 100644
index 000000000000..526706c06dcc
--- /dev/null
+++ b/providers/implementations/digests/ripemd_prov.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * RIPEMD160 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/crypto.h>
+#include <openssl/ripemd.h>
+#include "prov/digestcommon.h"
+#include "prov/implementations.h"
+
+/* ossl_ripemd160_functions */
+IMPLEMENT_digest_functions(ripemd160, RIPEMD160_CTX,
+ RIPEMD160_CBLOCK, RIPEMD160_DIGEST_LENGTH, 0,
+ RIPEMD160_Init, RIPEMD160_Update, RIPEMD160_Final)
diff --git a/providers/implementations/digests/sha2_prov.c b/providers/implementations/digests/sha2_prov.c
new file mode 100644
index 000000000000..3b731796bdc4
--- /dev/null
+++ b/providers/implementations/digests/sha2_prov.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * SHA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/crypto.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+#include <openssl/evp.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
+#include "prov/digestcommon.h"
+#include "prov/implementations.h"
+#include "crypto/sha.h"
+
+#define SHA2_FLAGS PROV_DIGEST_FLAG_ALGID_ABSENT
+
+static OSSL_FUNC_digest_set_ctx_params_fn sha1_set_ctx_params;
+static OSSL_FUNC_digest_settable_ctx_params_fn sha1_settable_ctx_params;
+
+static const OSSL_PARAM known_sha1_settable_ctx_params[] = {
+ {OSSL_DIGEST_PARAM_SSL3_MS, OSSL_PARAM_OCTET_STRING, NULL, 0, 0},
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *sha1_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ return known_sha1_settable_ctx_params;
+}
+
+/* Special set_params method for SSL3 */
+static int sha1_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ SHA_CTX *ctx = (SHA_CTX *)vctx;
+
+ if (ctx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_DIGEST_PARAM_SSL3_MS);
+ if (p != NULL && p->data_type == OSSL_PARAM_OCTET_STRING)
+ return ossl_sha1_ctrl(ctx, EVP_CTRL_SSL3_MASTER_SECRET,
+ p->data_size, p->data);
+ return 1;
+}
+
+/* ossl_sha1_functions */
+IMPLEMENT_digest_functions_with_settable_ctx(
+ sha1, SHA_CTX, SHA_CBLOCK, SHA_DIGEST_LENGTH, SHA2_FLAGS,
+ SHA1_Init, SHA1_Update, SHA1_Final,
+ sha1_settable_ctx_params, sha1_set_ctx_params)
+
+/* ossl_sha224_functions */
+IMPLEMENT_digest_functions(sha224, SHA256_CTX,
+ SHA256_CBLOCK, SHA224_DIGEST_LENGTH, SHA2_FLAGS,
+ SHA224_Init, SHA224_Update, SHA224_Final)
+
+/* ossl_sha256_functions */
+IMPLEMENT_digest_functions(sha256, SHA256_CTX,
+ SHA256_CBLOCK, SHA256_DIGEST_LENGTH, SHA2_FLAGS,
+ SHA256_Init, SHA256_Update, SHA256_Final)
+
+/* ossl_sha384_functions */
+IMPLEMENT_digest_functions(sha384, SHA512_CTX,
+ SHA512_CBLOCK, SHA384_DIGEST_LENGTH, SHA2_FLAGS,
+ SHA384_Init, SHA384_Update, SHA384_Final)
+
+/* ossl_sha512_functions */
+IMPLEMENT_digest_functions(sha512, SHA512_CTX,
+ SHA512_CBLOCK, SHA512_DIGEST_LENGTH, SHA2_FLAGS,
+ SHA512_Init, SHA512_Update, SHA512_Final)
+
+/* ossl_sha512_224_functions */
+IMPLEMENT_digest_functions(sha512_224, SHA512_CTX,
+ SHA512_CBLOCK, SHA224_DIGEST_LENGTH, SHA2_FLAGS,
+ sha512_224_init, SHA512_Update, SHA512_Final)
+
+/* ossl_sha512_256_functions */
+IMPLEMENT_digest_functions(sha512_256, SHA512_CTX,
+ SHA512_CBLOCK, SHA256_DIGEST_LENGTH, SHA2_FLAGS,
+ sha512_256_init, SHA512_Update, SHA512_Final)
+
diff --git a/providers/implementations/digests/sha3_prov.c b/providers/implementations/digests/sha3_prov.c
new file mode 100644
index 000000000000..168825d47564
--- /dev/null
+++ b/providers/implementations/digests/sha3_prov.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/core_names.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include "internal/sha3.h"
+#include "prov/digestcommon.h"
+#include "prov/implementations.h"
+
+#define SHA3_FLAGS PROV_DIGEST_FLAG_ALGID_ABSENT
+#define SHAKE_FLAGS PROV_DIGEST_FLAG_XOF
+#define KMAC_FLAGS PROV_DIGEST_FLAG_XOF
+
+/*
+ * Forward declaration of any unique methods implemented here. This is not strictly
+ * necessary for the compiler, but provides an assurance that the signatures
+ * of the functions in the dispatch table are correct.
+ */
+static OSSL_FUNC_digest_init_fn keccak_init;
+static OSSL_FUNC_digest_init_fn keccak_init_params;
+static OSSL_FUNC_digest_update_fn keccak_update;
+static OSSL_FUNC_digest_final_fn keccak_final;
+static OSSL_FUNC_digest_freectx_fn keccak_freectx;
+static OSSL_FUNC_digest_dupctx_fn keccak_dupctx;
+static OSSL_FUNC_digest_set_ctx_params_fn shake_set_ctx_params;
+static OSSL_FUNC_digest_settable_ctx_params_fn shake_settable_ctx_params;
+static sha3_absorb_fn generic_sha3_absorb;
+static sha3_final_fn generic_sha3_final;
+
+#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) && defined(KECCAK1600_ASM)
+/*
+ * IBM S390X support
+ */
+# include "s390x_arch.h"
+# define S390_SHA3 1
+# define S390_SHA3_CAPABLE(name) \
+ ((OPENSSL_s390xcap_P.kimd[0] & S390X_CAPBIT(S390X_##name)) && \
+ (OPENSSL_s390xcap_P.klmd[0] & S390X_CAPBIT(S390X_##name)))
+
+#endif
+
+static int keccak_init(void *vctx, ossl_unused const OSSL_PARAM params[])
+{
+ if (!ossl_prov_is_running())
+ return 0;
+ /* The newctx() handles most of the ctx fixed setup. */
+ ossl_sha3_reset((KECCAK1600_CTX *)vctx);
+ return 1;
+}
+
+static int keccak_init_params(void *vctx, const OSSL_PARAM params[])
+{
+ return keccak_init(vctx, NULL)
+ && shake_set_ctx_params(vctx, params);
+}
+
+static int keccak_update(void *vctx, const unsigned char *inp, size_t len)
+{
+ KECCAK1600_CTX *ctx = vctx;
+ const size_t bsz = ctx->block_size;
+ size_t num, rem;
+
+ if (len == 0)
+ return 1;
+
+ /* Is there anything in the buffer already ? */
+ if ((num = ctx->bufsz) != 0) {
+ /* Calculate how much space is left in the buffer */
+ rem = bsz - num;
+ /* If the new input does not fill the buffer then just add it */
+ if (len < rem) {
+ memcpy(ctx->buf + num, inp, len);
+ ctx->bufsz += len;
+ return 1;
+ }
+ /* otherwise fill up the buffer and absorb the buffer */
+ memcpy(ctx->buf + num, inp, rem);
+ /* Update the input pointer */
+ inp += rem;
+ len -= rem;
+ ctx->meth.absorb(ctx, ctx->buf, bsz);
+ ctx->bufsz = 0;
+ }
+ /* Absorb the input - rem = leftover part of the input < blocksize) */
+ rem = ctx->meth.absorb(ctx, inp, len);
+ /* Copy the leftover bit of the input into the buffer */
+ if (rem) {
+ memcpy(ctx->buf, inp + len - rem, rem);
+ ctx->bufsz = rem;
+ }
+ return 1;
+}
+
+static int keccak_final(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsz)
+{
+ int ret = 1;
+ KECCAK1600_CTX *ctx = vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+ if (outsz > 0)
+ ret = ctx->meth.final(out, ctx);
+
+ *outl = ctx->md_size;
+ return ret;
+}
+
+/*-
+ * Generic software version of the absorb() and final().
+ */
+static size_t generic_sha3_absorb(void *vctx, const void *inp, size_t len)
+{
+ KECCAK1600_CTX *ctx = vctx;
+
+ return SHA3_absorb(ctx->A, inp, len, ctx->block_size);
+}
+
+static int generic_sha3_final(unsigned char *md, void *vctx)
+{
+ return ossl_sha3_final(md, (KECCAK1600_CTX *)vctx);
+}
+
+static PROV_SHA3_METHOD sha3_generic_md =
+{
+ generic_sha3_absorb,
+ generic_sha3_final
+};
+
+#if defined(S390_SHA3)
+
+static sha3_absorb_fn s390x_sha3_absorb;
+static sha3_final_fn s390x_sha3_final;
+static sha3_final_fn s390x_shake_final;
+
+/*-
+ * The platform specific parts of the absorb() and final() for S390X.
+ */
+static size_t s390x_sha3_absorb(void *vctx, const void *inp, size_t len)
+{
+ KECCAK1600_CTX *ctx = vctx;
+ size_t rem = len % ctx->block_size;
+
+ s390x_kimd(inp, len - rem, ctx->pad, ctx->A);
+ return rem;
+}
+
+static int s390x_sha3_final(unsigned char *md, void *vctx)
+{
+ KECCAK1600_CTX *ctx = vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+ s390x_klmd(ctx->buf, ctx->bufsz, NULL, 0, ctx->pad, ctx->A);
+ memcpy(md, ctx->A, ctx->md_size);
+ return 1;
+}
+
+static int s390x_shake_final(unsigned char *md, void *vctx)
+{
+ KECCAK1600_CTX *ctx = vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+ s390x_klmd(ctx->buf, ctx->bufsz, md, ctx->md_size, ctx->pad, ctx->A);
+ return 1;
+}
+
+static PROV_SHA3_METHOD sha3_s390x_md =
+{
+ s390x_sha3_absorb,
+ s390x_sha3_final
+};
+
+static PROV_SHA3_METHOD shake_s390x_md =
+{
+ s390x_sha3_absorb,
+ s390x_shake_final
+};
+
+# define SHA3_SET_MD(uname, typ) \
+ if (S390_SHA3_CAPABLE(uname)) { \
+ ctx->pad = S390X_##uname; \
+ ctx->meth = typ##_s390x_md; \
+ } else { \
+ ctx->meth = sha3_generic_md; \
+ }
+#else
+# define SHA3_SET_MD(uname, typ) ctx->meth = sha3_generic_md;
+#endif /* S390_SHA3 */
+
+#define SHA3_newctx(typ, uname, name, bitlen, pad) \
+static OSSL_FUNC_digest_newctx_fn name##_newctx; \
+static void *name##_newctx(void *provctx) \
+{ \
+ KECCAK1600_CTX *ctx = ossl_prov_is_running() ? OPENSSL_zalloc(sizeof(*ctx)) \
+ : NULL; \
+ \
+ if (ctx == NULL) \
+ return NULL; \
+ ossl_sha3_init(ctx, pad, bitlen); \
+ SHA3_SET_MD(uname, typ) \
+ return ctx; \
+}
+
+#define KMAC_newctx(uname, bitlen, pad) \
+static OSSL_FUNC_digest_newctx_fn uname##_newctx; \
+static void *uname##_newctx(void *provctx) \
+{ \
+ KECCAK1600_CTX *ctx = ossl_prov_is_running() ? OPENSSL_zalloc(sizeof(*ctx)) \
+ : NULL; \
+ \
+ if (ctx == NULL) \
+ return NULL; \
+ ossl_keccak_kmac_init(ctx, pad, bitlen); \
+ ctx->meth = sha3_generic_md; \
+ return ctx; \
+}
+
+#define PROV_FUNC_SHA3_DIGEST_COMMON(name, bitlen, blksize, dgstsize, flags) \
+PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags) \
+const OSSL_DISPATCH ossl_##name##_functions[] = { \
+ { OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))name##_newctx }, \
+ { OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))keccak_update }, \
+ { OSSL_FUNC_DIGEST_FINAL, (void (*)(void))keccak_final }, \
+ { OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))keccak_freectx }, \
+ { OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))keccak_dupctx }, \
+ PROV_DISPATCH_FUNC_DIGEST_GET_PARAMS(name)
+
+#define PROV_FUNC_SHA3_DIGEST(name, bitlen, blksize, dgstsize, flags) \
+ PROV_FUNC_SHA3_DIGEST_COMMON(name, bitlen, blksize, dgstsize, flags), \
+ { OSSL_FUNC_DIGEST_INIT, (void (*)(void))keccak_init }, \
+ PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END
+
+#define PROV_FUNC_SHAKE_DIGEST(name, bitlen, blksize, dgstsize, flags) \
+ PROV_FUNC_SHA3_DIGEST_COMMON(name, bitlen, blksize, dgstsize, flags), \
+ { OSSL_FUNC_DIGEST_INIT, (void (*)(void))keccak_init_params }, \
+ { OSSL_FUNC_DIGEST_SET_CTX_PARAMS, (void (*)(void))shake_set_ctx_params }, \
+ { OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))shake_settable_ctx_params }, \
+ PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END
+
+static void keccak_freectx(void *vctx)
+{
+ KECCAK1600_CTX *ctx = (KECCAK1600_CTX *)vctx;
+
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static void *keccak_dupctx(void *ctx)
+{
+ KECCAK1600_CTX *in = (KECCAK1600_CTX *)ctx;
+ KECCAK1600_CTX *ret = ossl_prov_is_running() ? OPENSSL_malloc(sizeof(*ret))
+ : NULL;
+
+ if (ret != NULL)
+ *ret = *in;
+ return ret;
+}
+
+static const OSSL_PARAM known_shake_settable_ctx_params[] = {
+ {OSSL_DIGEST_PARAM_XOFLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0},
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *shake_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ return known_shake_settable_ctx_params;
+}
+
+static int shake_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ KECCAK1600_CTX *ctx = (KECCAK1600_CTX *)vctx;
+
+ if (ctx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_DIGEST_PARAM_XOFLEN);
+ if (p != NULL && !OSSL_PARAM_get_size_t(p, &ctx->md_size)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ return 1;
+}
+
+#define IMPLEMENT_SHA3_functions(bitlen) \
+ SHA3_newctx(sha3, SHA3_##bitlen, sha3_##bitlen, bitlen, '\x06') \
+ PROV_FUNC_SHA3_DIGEST(sha3_##bitlen, bitlen, \
+ SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen), \
+ SHA3_FLAGS)
+
+#define IMPLEMENT_SHAKE_functions(bitlen) \
+ SHA3_newctx(shake, SHAKE_##bitlen, shake_##bitlen, bitlen, '\x1f') \
+ PROV_FUNC_SHAKE_DIGEST(shake_##bitlen, bitlen, \
+ SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen), \
+ SHAKE_FLAGS)
+#define IMPLEMENT_KMAC_functions(bitlen) \
+ KMAC_newctx(keccak_kmac_##bitlen, bitlen, '\x04') \
+ PROV_FUNC_SHAKE_DIGEST(keccak_kmac_##bitlen, bitlen, \
+ SHA3_BLOCKSIZE(bitlen), KMAC_MDSIZE(bitlen), \
+ KMAC_FLAGS)
+
+/* ossl_sha3_224_functions */
+IMPLEMENT_SHA3_functions(224)
+/* ossl_sha3_256_functions */
+IMPLEMENT_SHA3_functions(256)
+/* ossl_sha3_384_functions */
+IMPLEMENT_SHA3_functions(384)
+/* ossl_sha3_512_functions */
+IMPLEMENT_SHA3_functions(512)
+/* ossl_shake_128_functions */
+IMPLEMENT_SHAKE_functions(128)
+/* ossl_shake_256_functions */
+IMPLEMENT_SHAKE_functions(256)
+/* ossl_keccak_kmac_128_functions */
+IMPLEMENT_KMAC_functions(128)
+/* ossl_keccak_kmac_256_functions */
+IMPLEMENT_KMAC_functions(256)
diff --git a/providers/implementations/digests/sm3_prov.c b/providers/implementations/digests/sm3_prov.c
new file mode 100644
index 000000000000..9d6de5b6ac19
--- /dev/null
+++ b/providers/implementations/digests/sm3_prov.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include "internal/sm3.h"
+#include "prov/digestcommon.h"
+#include "prov/implementations.h"
+
+/* ossl_sm3_functions */
+IMPLEMENT_digest_functions(sm3, SM3_CTX,
+ SM3_CBLOCK, SM3_DIGEST_LENGTH, 0,
+ ossl_sm3_init, ossl_sm3_update, ossl_sm3_final)
diff --git a/providers/implementations/digests/wp_prov.c b/providers/implementations/digests/wp_prov.c
new file mode 100644
index 000000000000..2af70b337281
--- /dev/null
+++ b/providers/implementations/digests/wp_prov.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Whirlpool low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/crypto.h>
+#include <openssl/whrlpool.h>
+#include "prov/digestcommon.h"
+#include "prov/implementations.h"
+
+/* ossl_wp_functions */
+IMPLEMENT_digest_functions(wp, WHIRLPOOL_CTX,
+ WHIRLPOOL_BBLOCK / 8, WHIRLPOOL_DIGEST_LENGTH, 0,
+ WHIRLPOOL_Init, WHIRLPOOL_Update, WHIRLPOOL_Final)
diff --git a/providers/implementations/encode_decode/build.info b/providers/implementations/encode_decode/build.info
new file mode 100644
index 000000000000..d3f6ca4abdef
--- /dev/null
+++ b/providers/implementations/encode_decode/build.info
@@ -0,0 +1,20 @@
+# We make separate GOAL variables for each algorithm, to make it easy to
+# switch each to the Legacy provider when needed.
+
+$ENCODER_GOAL=../../libdefault.a
+$DECODER_GOAL=../../libdefault.a
+
+SOURCE[$ENCODER_GOAL]=endecoder_common.c
+
+SOURCE[$DECODER_GOAL]=decode_der2key.c decode_epki2pki.c decode_pem2der.c \
+ decode_msblob2key.c decode_pvk2key.c \
+ decode_spki2typespki.c
+
+SOURCE[$ENCODER_GOAL]=encode_key2any.c encode_key2text.c encode_key2ms.c
+# encode_key2blob.c is only being included when EC is enabled, because we
+# currently only define a "blob" output type for EC public keys. This may
+# change in the future.
+IF[{- !$disabled{ec} -}]
+ SOURCE[$ENCODER_GOAL]=encode_key2blob.c
+ENDIF
+DEPEND[encode_key2any.o]=../../common/include/prov/der_rsa.h
diff --git a/providers/implementations/encode_decode/decode_der2key.c b/providers/implementations/encode_decode/decode_der2key.c
new file mode 100644
index 000000000000..b9cee2571bf3
--- /dev/null
+++ b/providers/implementations/encode_decode/decode_der2key.c
@@ -0,0 +1,793 @@
+/*
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/core_object.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/params.h>
+#include <openssl/pem.h> /* PEM_BUFSIZE and public PEM functions */
+#include <openssl/pkcs12.h>
+#include <openssl/x509.h>
+#include <openssl/proverr.h>
+#include "internal/cryptlib.h" /* ossl_assert() */
+#include "internal/asn1.h"
+#include "crypto/dh.h"
+#include "crypto/dsa.h"
+#include "crypto/ec.h"
+#include "crypto/evp.h"
+#include "crypto/ecx.h"
+#include "crypto/rsa.h"
+#include "crypto/x509.h"
+#include "prov/bio.h"
+#include "prov/implementations.h"
+#include "endecoder_local.h"
+
+struct der2key_ctx_st; /* Forward declaration */
+typedef int check_key_fn(void *, struct der2key_ctx_st *ctx);
+typedef void adjust_key_fn(void *, struct der2key_ctx_st *ctx);
+typedef void free_key_fn(void *);
+typedef void *d2i_PKCS8_fn(void **, const unsigned char **, long,
+ struct der2key_ctx_st *);
+struct keytype_desc_st {
+ const char *keytype_name;
+ const OSSL_DISPATCH *fns; /* Keymgmt (to pilfer functions from) */
+
+ /* The input structure name */
+ const char *structure_name;
+
+ /*
+ * The EVP_PKEY_xxx type macro. Should be zero for type specific
+ * structures, non-zero when the outermost structure is PKCS#8 or
+ * SubjectPublicKeyInfo. This determines which of the function
+ * pointers below will be used.
+ */
+ int evp_type;
+
+ /* The selection mask for OSSL_FUNC_decoder_does_selection() */
+ int selection_mask;
+
+ /* For type specific decoders, we use the corresponding d2i */
+ d2i_of_void *d2i_private_key; /* From type-specific DER */
+ d2i_of_void *d2i_public_key; /* From type-specific DER */
+ d2i_of_void *d2i_key_params; /* From type-specific DER */
+ d2i_PKCS8_fn *d2i_PKCS8; /* Wrapped in a PrivateKeyInfo */
+ d2i_of_void *d2i_PUBKEY; /* Wrapped in a SubjectPublicKeyInfo */
+
+ /*
+ * For any key, we may need to check that the key meets expectations.
+ * This is useful when the same functions can decode several variants
+ * of a key.
+ */
+ check_key_fn *check_key;
+
+ /*
+ * For any key, we may need to make provider specific adjustments, such
+ * as ensure the key carries the correct library context.
+ */
+ adjust_key_fn *adjust_key;
+ /* {type}_free() */
+ free_key_fn *free_key;
+};
+
+/*
+ * Context used for DER to key decoding.
+ */
+struct der2key_ctx_st {
+ PROV_CTX *provctx;
+ const struct keytype_desc_st *desc;
+ /* The selection that is passed to der2key_decode() */
+ int selection;
+ /* Flag used to signal that a failure is fatal */
+ unsigned int flag_fatal : 1;
+};
+
+typedef void *key_from_pkcs8_t(const PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *libctx, const char *propq);
+static void *der2key_decode_p8(const unsigned char **input_der,
+ long input_der_len, struct der2key_ctx_st *ctx,
+ key_from_pkcs8_t *key_from_pkcs8)
+{
+ PKCS8_PRIV_KEY_INFO *p8inf = NULL;
+ const X509_ALGOR *alg = NULL;
+ void *key = NULL;
+
+ if ((p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, input_der, input_der_len)) != NULL
+ && PKCS8_pkey_get0(NULL, NULL, NULL, &alg, p8inf)
+ && OBJ_obj2nid(alg->algorithm) == ctx->desc->evp_type)
+ key = key_from_pkcs8(p8inf, PROV_LIBCTX_OF(ctx->provctx), NULL);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+
+ return key;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static OSSL_FUNC_decoder_freectx_fn der2key_freectx;
+static OSSL_FUNC_decoder_decode_fn der2key_decode;
+static OSSL_FUNC_decoder_export_object_fn der2key_export_object;
+
+static struct der2key_ctx_st *
+der2key_newctx(void *provctx, const struct keytype_desc_st *desc)
+{
+ struct der2key_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx != NULL) {
+ ctx->provctx = provctx;
+ ctx->desc = desc;
+ }
+ return ctx;
+}
+
+static void der2key_freectx(void *vctx)
+{
+ struct der2key_ctx_st *ctx = vctx;
+
+ OPENSSL_free(ctx);
+}
+
+static int der2key_check_selection(int selection,
+ const struct keytype_desc_st *desc)
+{
+ /*
+ * The selections are kinda sorta "levels", i.e. each selection given
+ * here is assumed to include those following.
+ */
+ int checks[] = {
+ OSSL_KEYMGMT_SELECT_PRIVATE_KEY,
+ OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
+ OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
+ };
+ size_t i;
+
+ /* The decoder implementations made here support guessing */
+ if (selection == 0)
+ return 1;
+
+ for (i = 0; i < OSSL_NELEM(checks); i++) {
+ int check1 = (selection & checks[i]) != 0;
+ int check2 = (desc->selection_mask & checks[i]) != 0;
+
+ /*
+ * If the caller asked for the currently checked bit(s), return
+ * whether the decoder description says it's supported.
+ */
+ if (check1)
+ return check2;
+ }
+
+ /* This should be dead code, but just to be safe... */
+ return 0;
+}
+
+static int der2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
+ OSSL_CALLBACK *data_cb, void *data_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+ struct der2key_ctx_st *ctx = vctx;
+ unsigned char *der = NULL;
+ const unsigned char *derp;
+ long der_len = 0;
+ void *key = NULL;
+ int ok = 0;
+
+ ctx->selection = selection;
+ /*
+ * The caller is allowed to specify 0 as a selection mark, to have the
+ * structure and key type guessed. For type-specific structures, this
+ * is not recommended, as some structures are very similar.
+ * Note that 0 isn't the same as OSSL_KEYMGMT_SELECT_ALL, as the latter
+ * signifies a private key structure, where everything else is assumed
+ * to be present as well.
+ */
+ if (selection == 0)
+ selection = ctx->desc->selection_mask;
+ if ((selection & ctx->desc->selection_mask) == 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ ok = ossl_read_der(ctx->provctx, cin, &der, &der_len);
+ if (!ok)
+ goto next;
+
+ ok = 0; /* Assume that we fail */
+
+ ERR_set_mark();
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ derp = der;
+ if (ctx->desc->d2i_PKCS8 != NULL) {
+ key = ctx->desc->d2i_PKCS8(NULL, &derp, der_len, ctx);
+ if (ctx->flag_fatal) {
+ ERR_clear_last_mark();
+ goto end;
+ }
+ } else if (ctx->desc->d2i_private_key != NULL) {
+ key = ctx->desc->d2i_private_key(NULL, &derp, der_len);
+ }
+ if (key == NULL && ctx->selection != 0) {
+ ERR_clear_last_mark();
+ goto next;
+ }
+ }
+ if (key == NULL && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ derp = der;
+ if (ctx->desc->d2i_PUBKEY != NULL)
+ key = ctx->desc->d2i_PUBKEY(NULL, &derp, der_len);
+ else if (ctx->desc->d2i_public_key != NULL)
+ key = ctx->desc->d2i_public_key(NULL, &derp, der_len);
+ if (key == NULL && ctx->selection != 0) {
+ ERR_clear_last_mark();
+ goto next;
+ }
+ }
+ if (key == NULL && (selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) {
+ derp = der;
+ if (ctx->desc->d2i_key_params != NULL)
+ key = ctx->desc->d2i_key_params(NULL, &derp, der_len);
+ if (key == NULL && ctx->selection != 0) {
+ ERR_clear_last_mark();
+ goto next;
+ }
+ }
+ if (key == NULL)
+ ERR_clear_last_mark();
+ else
+ ERR_pop_to_mark();
+
+ /*
+ * Last minute check to see if this was the correct type of key. This
+ * should never lead to a fatal error, i.e. the decoding itself was
+ * correct, it was just an unexpected key type. This is generally for
+ * classes of key types that have subtle variants, like RSA-PSS keys as
+ * opposed to plain RSA keys.
+ */
+ if (key != NULL
+ && ctx->desc->check_key != NULL
+ && !ctx->desc->check_key(key, ctx)) {
+ ctx->desc->free_key(key);
+ key = NULL;
+ }
+
+ if (key != NULL && ctx->desc->adjust_key != NULL)
+ ctx->desc->adjust_key(key, ctx);
+
+ next:
+ /*
+ * Indicated that we successfully decoded something, or not at all.
+ * Ending up "empty handed" is not an error.
+ */
+ ok = 1;
+
+ /*
+ * We free memory here so it's not held up during the callback, because
+ * we know the process is recursive and the allocated chunks of memory
+ * add up.
+ */
+ OPENSSL_free(der);
+ der = NULL;
+
+ if (key != NULL) {
+ OSSL_PARAM params[4];
+ int object_type = OSSL_OBJECT_PKEY;
+
+ params[0] =
+ OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &object_type);
+ params[1] =
+ OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
+ (char *)ctx->desc->keytype_name,
+ 0);
+ /* The address of the key becomes the octet string */
+ params[2] =
+ OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_REFERENCE,
+ &key, sizeof(key));
+ params[3] = OSSL_PARAM_construct_end();
+
+ ok = data_cb(params, data_cbarg);
+ }
+
+ end:
+ ctx->desc->free_key(key);
+ OPENSSL_free(der);
+
+ return ok;
+}
+
+static int der2key_export_object(void *vctx,
+ const void *reference, size_t reference_sz,
+ OSSL_CALLBACK *export_cb, void *export_cbarg)
+{
+ struct der2key_ctx_st *ctx = vctx;
+ OSSL_FUNC_keymgmt_export_fn *export =
+ ossl_prov_get_keymgmt_export(ctx->desc->fns);
+ void *keydata;
+
+ if (reference_sz == sizeof(keydata) && export != NULL) {
+ /* The contents of the reference is the address to our object */
+ keydata = *(void **)reference;
+
+ return export(keydata, ctx->selection, export_cb, export_cbarg);
+ }
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+#ifndef OPENSSL_NO_DH
+# define dh_evp_type EVP_PKEY_DH
+# define dh_d2i_private_key NULL
+# define dh_d2i_public_key NULL
+# define dh_d2i_key_params (d2i_of_void *)d2i_DHparams
+
+static void *dh_d2i_PKCS8(void **key, const unsigned char **der, long der_len,
+ struct der2key_ctx_st *ctx)
+{
+ return der2key_decode_p8(der, der_len, ctx,
+ (key_from_pkcs8_t *)ossl_dh_key_from_pkcs8);
+}
+
+# define dh_d2i_PUBKEY (d2i_of_void *)ossl_d2i_DH_PUBKEY
+# define dh_free (free_key_fn *)DH_free
+# define dh_check NULL
+
+static void dh_adjust(void *key, struct der2key_ctx_st *ctx)
+{
+ ossl_dh_set0_libctx(key, PROV_LIBCTX_OF(ctx->provctx));
+}
+
+# define dhx_evp_type EVP_PKEY_DHX
+# define dhx_d2i_private_key NULL
+# define dhx_d2i_public_key NULL
+# define dhx_d2i_key_params (d2i_of_void *)d2i_DHxparams
+# define dhx_d2i_PKCS8 dh_d2i_PKCS8
+# define dhx_d2i_PUBKEY (d2i_of_void *)ossl_d2i_DHx_PUBKEY
+# define dhx_free (free_key_fn *)DH_free
+# define dhx_check NULL
+# define dhx_adjust dh_adjust
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+#ifndef OPENSSL_NO_DSA
+# define dsa_evp_type EVP_PKEY_DSA
+# define dsa_d2i_private_key (d2i_of_void *)d2i_DSAPrivateKey
+# define dsa_d2i_public_key (d2i_of_void *)d2i_DSAPublicKey
+# define dsa_d2i_key_params (d2i_of_void *)d2i_DSAparams
+
+static void *dsa_d2i_PKCS8(void **key, const unsigned char **der, long der_len,
+ struct der2key_ctx_st *ctx)
+{
+ return der2key_decode_p8(der, der_len, ctx,
+ (key_from_pkcs8_t *)ossl_dsa_key_from_pkcs8);
+}
+
+# define dsa_d2i_PUBKEY (d2i_of_void *)ossl_d2i_DSA_PUBKEY
+# define dsa_free (free_key_fn *)DSA_free
+# define dsa_check NULL
+
+static void dsa_adjust(void *key, struct der2key_ctx_st *ctx)
+{
+ ossl_dsa_set0_libctx(key, PROV_LIBCTX_OF(ctx->provctx));
+}
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+#ifndef OPENSSL_NO_EC
+# define ec_evp_type EVP_PKEY_EC
+# define ec_d2i_private_key (d2i_of_void *)d2i_ECPrivateKey
+# define ec_d2i_public_key NULL
+# define ec_d2i_key_params (d2i_of_void *)d2i_ECParameters
+
+static void *ec_d2i_PKCS8(void **key, const unsigned char **der, long der_len,
+ struct der2key_ctx_st *ctx)
+{
+ return der2key_decode_p8(der, der_len, ctx,
+ (key_from_pkcs8_t *)ossl_ec_key_from_pkcs8);
+}
+
+# define ec_d2i_PUBKEY (d2i_of_void *)d2i_EC_PUBKEY
+# define ec_free (free_key_fn *)EC_KEY_free
+
+static int ec_check(void *key, struct der2key_ctx_st *ctx)
+{
+ /* We're trying to be clever by comparing two truths */
+
+ int sm2 = (EC_KEY_get_flags(key) & EC_FLAG_SM2_RANGE) != 0;
+
+ return sm2 == (ctx->desc->evp_type == EVP_PKEY_SM2);
+}
+
+static void ec_adjust(void *key, struct der2key_ctx_st *ctx)
+{
+ ossl_ec_key_set0_libctx(key, PROV_LIBCTX_OF(ctx->provctx));
+}
+
+/*
+ * ED25519, ED448, X25519, X448 only implement PKCS#8 and SubjectPublicKeyInfo,
+ * so no d2i functions to be had.
+ */
+
+static void *ecx_d2i_PKCS8(void **key, const unsigned char **der, long der_len,
+ struct der2key_ctx_st *ctx)
+{
+ return der2key_decode_p8(der, der_len, ctx,
+ (key_from_pkcs8_t *)ossl_ecx_key_from_pkcs8);
+}
+
+static void ecx_key_adjust(void *key, struct der2key_ctx_st *ctx)
+{
+ ossl_ecx_key_set0_libctx(key, PROV_LIBCTX_OF(ctx->provctx));
+}
+
+# define ed25519_evp_type EVP_PKEY_ED25519
+# define ed25519_d2i_private_key NULL
+# define ed25519_d2i_public_key NULL
+# define ed25519_d2i_key_params NULL
+# define ed25519_d2i_PKCS8 ecx_d2i_PKCS8
+# define ed25519_d2i_PUBKEY (d2i_of_void *)ossl_d2i_ED25519_PUBKEY
+# define ed25519_free (free_key_fn *)ossl_ecx_key_free
+# define ed25519_check NULL
+# define ed25519_adjust ecx_key_adjust
+
+# define ed448_evp_type EVP_PKEY_ED448
+# define ed448_d2i_private_key NULL
+# define ed448_d2i_public_key NULL
+# define ed448_d2i_key_params NULL
+# define ed448_d2i_PKCS8 ecx_d2i_PKCS8
+# define ed448_d2i_PUBKEY (d2i_of_void *)ossl_d2i_ED448_PUBKEY
+# define ed448_free (free_key_fn *)ossl_ecx_key_free
+# define ed448_check NULL
+# define ed448_adjust ecx_key_adjust
+
+# define x25519_evp_type EVP_PKEY_X25519
+# define x25519_d2i_private_key NULL
+# define x25519_d2i_public_key NULL
+# define x25519_d2i_key_params NULL
+# define x25519_d2i_PKCS8 ecx_d2i_PKCS8
+# define x25519_d2i_PUBKEY (d2i_of_void *)ossl_d2i_X25519_PUBKEY
+# define x25519_free (free_key_fn *)ossl_ecx_key_free
+# define x25519_check NULL
+# define x25519_adjust ecx_key_adjust
+
+# define x448_evp_type EVP_PKEY_X448
+# define x448_d2i_private_key NULL
+# define x448_d2i_public_key NULL
+# define x448_d2i_key_params NULL
+# define x448_d2i_PKCS8 ecx_d2i_PKCS8
+# define x448_d2i_PUBKEY (d2i_of_void *)ossl_d2i_X448_PUBKEY
+# define x448_free (free_key_fn *)ossl_ecx_key_free
+# define x448_check NULL
+# define x448_adjust ecx_key_adjust
+
+# ifndef OPENSSL_NO_SM2
+# define sm2_evp_type EVP_PKEY_SM2
+# define sm2_d2i_private_key (d2i_of_void *)d2i_ECPrivateKey
+# define sm2_d2i_public_key NULL
+# define sm2_d2i_key_params (d2i_of_void *)d2i_ECParameters
+
+static void *sm2_d2i_PKCS8(void **key, const unsigned char **der, long der_len,
+ struct der2key_ctx_st *ctx)
+{
+ return der2key_decode_p8(der, der_len, ctx,
+ (key_from_pkcs8_t *)ossl_ec_key_from_pkcs8);
+}
+
+# define sm2_d2i_PUBKEY (d2i_of_void *)d2i_EC_PUBKEY
+# define sm2_free (free_key_fn *)EC_KEY_free
+# define sm2_check ec_check
+# define sm2_adjust ec_adjust
+# endif
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+#define rsa_evp_type EVP_PKEY_RSA
+#define rsa_d2i_private_key (d2i_of_void *)d2i_RSAPrivateKey
+#define rsa_d2i_public_key (d2i_of_void *)d2i_RSAPublicKey
+#define rsa_d2i_key_params NULL
+
+static void *rsa_d2i_PKCS8(void **key, const unsigned char **der, long der_len,
+ struct der2key_ctx_st *ctx)
+{
+ return der2key_decode_p8(der, der_len, ctx,
+ (key_from_pkcs8_t *)ossl_rsa_key_from_pkcs8);
+}
+
+#define rsa_d2i_PUBKEY (d2i_of_void *)d2i_RSA_PUBKEY
+#define rsa_free (free_key_fn *)RSA_free
+
+static int rsa_check(void *key, struct der2key_ctx_st *ctx)
+{
+ switch (RSA_test_flags(key, RSA_FLAG_TYPE_MASK)) {
+ case RSA_FLAG_TYPE_RSA:
+ return ctx->desc->evp_type == EVP_PKEY_RSA;
+ case RSA_FLAG_TYPE_RSASSAPSS:
+ return ctx->desc->evp_type == EVP_PKEY_RSA_PSS;
+ }
+
+ /* Currently unsupported RSA key type */
+ return 0;
+}
+
+static void rsa_adjust(void *key, struct der2key_ctx_st *ctx)
+{
+ ossl_rsa_set0_libctx(key, PROV_LIBCTX_OF(ctx->provctx));
+}
+
+#define rsapss_evp_type EVP_PKEY_RSA_PSS
+#define rsapss_d2i_private_key (d2i_of_void *)d2i_RSAPrivateKey
+#define rsapss_d2i_public_key (d2i_of_void *)d2i_RSAPublicKey
+#define rsapss_d2i_key_params NULL
+#define rsapss_d2i_PKCS8 rsa_d2i_PKCS8
+#define rsapss_d2i_PUBKEY (d2i_of_void *)d2i_RSA_PUBKEY
+#define rsapss_free (free_key_fn *)RSA_free
+#define rsapss_check rsa_check
+#define rsapss_adjust rsa_adjust
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * The DO_ macros help define the selection mask and the method functions
+ * for each kind of object we want to decode.
+ */
+#define DO_type_specific_keypair(keytype) \
+ "type-specific", keytype##_evp_type, \
+ ( OSSL_KEYMGMT_SELECT_KEYPAIR ), \
+ keytype##_d2i_private_key, \
+ keytype##_d2i_public_key, \
+ NULL, \
+ NULL, \
+ NULL, \
+ keytype##_check, \
+ keytype##_adjust, \
+ keytype##_free
+
+#define DO_type_specific_pub(keytype) \
+ "type-specific", keytype##_evp_type, \
+ ( OSSL_KEYMGMT_SELECT_PUBLIC_KEY ), \
+ NULL, \
+ keytype##_d2i_public_key, \
+ NULL, \
+ NULL, \
+ NULL, \
+ keytype##_check, \
+ keytype##_adjust, \
+ keytype##_free
+
+#define DO_type_specific_priv(keytype) \
+ "type-specific", keytype##_evp_type, \
+ ( OSSL_KEYMGMT_SELECT_PRIVATE_KEY ), \
+ keytype##_d2i_private_key, \
+ NULL, \
+ NULL, \
+ NULL, \
+ NULL, \
+ keytype##_check, \
+ keytype##_adjust, \
+ keytype##_free
+
+#define DO_type_specific_params(keytype) \
+ "type-specific", keytype##_evp_type, \
+ ( OSSL_KEYMGMT_SELECT_ALL_PARAMETERS ), \
+ NULL, \
+ NULL, \
+ keytype##_d2i_key_params, \
+ NULL, \
+ NULL, \
+ keytype##_check, \
+ keytype##_adjust, \
+ keytype##_free
+
+#define DO_type_specific(keytype) \
+ "type-specific", keytype##_evp_type, \
+ ( OSSL_KEYMGMT_SELECT_ALL ), \
+ keytype##_d2i_private_key, \
+ keytype##_d2i_public_key, \
+ keytype##_d2i_key_params, \
+ NULL, \
+ NULL, \
+ keytype##_check, \
+ keytype##_adjust, \
+ keytype##_free
+
+#define DO_type_specific_no_pub(keytype) \
+ "type-specific", keytype##_evp_type, \
+ ( OSSL_KEYMGMT_SELECT_PRIVATE_KEY \
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS ), \
+ keytype##_d2i_private_key, \
+ NULL, \
+ keytype##_d2i_key_params, \
+ NULL, \
+ NULL, \
+ keytype##_check, \
+ keytype##_adjust, \
+ keytype##_free
+
+#define DO_PrivateKeyInfo(keytype) \
+ "PrivateKeyInfo", keytype##_evp_type, \
+ ( OSSL_KEYMGMT_SELECT_PRIVATE_KEY ), \
+ NULL, \
+ NULL, \
+ NULL, \
+ keytype##_d2i_PKCS8, \
+ NULL, \
+ keytype##_check, \
+ keytype##_adjust, \
+ keytype##_free
+
+#define DO_SubjectPublicKeyInfo(keytype) \
+ "SubjectPublicKeyInfo", keytype##_evp_type, \
+ ( OSSL_KEYMGMT_SELECT_PUBLIC_KEY ), \
+ NULL, \
+ NULL, \
+ NULL, \
+ NULL, \
+ keytype##_d2i_PUBKEY, \
+ keytype##_check, \
+ keytype##_adjust, \
+ keytype##_free
+
+#define DO_DH(keytype) \
+ "DH", keytype##_evp_type, \
+ ( OSSL_KEYMGMT_SELECT_ALL_PARAMETERS ), \
+ NULL, \
+ NULL, \
+ keytype##_d2i_key_params, \
+ NULL, \
+ NULL, \
+ keytype##_check, \
+ keytype##_adjust, \
+ keytype##_free
+
+#define DO_DHX(keytype) \
+ "DHX", keytype##_evp_type, \
+ ( OSSL_KEYMGMT_SELECT_ALL_PARAMETERS ), \
+ NULL, \
+ NULL, \
+ keytype##_d2i_key_params, \
+ NULL, \
+ NULL, \
+ keytype##_check, \
+ keytype##_adjust, \
+ keytype##_free
+
+#define DO_DSA(keytype) \
+ "DSA", keytype##_evp_type, \
+ ( OSSL_KEYMGMT_SELECT_ALL ), \
+ keytype##_d2i_private_key, \
+ keytype##_d2i_public_key, \
+ keytype##_d2i_key_params, \
+ NULL, \
+ NULL, \
+ keytype##_check, \
+ keytype##_adjust, \
+ keytype##_free
+
+#define DO_EC(keytype) \
+ "EC", keytype##_evp_type, \
+ ( OSSL_KEYMGMT_SELECT_PRIVATE_KEY \
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS ), \
+ keytype##_d2i_private_key, \
+ NULL, \
+ keytype##_d2i_key_params, \
+ NULL, \
+ NULL, \
+ keytype##_check, \
+ keytype##_adjust, \
+ keytype##_free
+
+#define DO_RSA(keytype) \
+ "RSA", keytype##_evp_type, \
+ ( OSSL_KEYMGMT_SELECT_KEYPAIR ), \
+ keytype##_d2i_private_key, \
+ keytype##_d2i_public_key, \
+ NULL, \
+ NULL, \
+ NULL, \
+ keytype##_check, \
+ keytype##_adjust, \
+ keytype##_free
+
+/*
+ * MAKE_DECODER is the single driver for creating OSSL_DISPATCH tables.
+ * It takes the following arguments:
+ *
+ * keytype_name The implementation key type as a string.
+ * keytype The implementation key type. This must correspond exactly
+ * to our existing keymgmt keytype names... in other words,
+ * there must exist an ossl_##keytype##_keymgmt_functions.
+ * type The type name for the set of functions that implement the
+ * decoder for the key type. This isn't necessarily the same
+ * as keytype. For example, the key types ed25519, ed448,
+ * x25519 and x448 are all handled by the same functions with
+ * the common type name ecx.
+ * kind The kind of support to implement. This translates into
+ * the DO_##kind macros above, to populate the keytype_desc_st
+ * structure.
+ */
+#define MAKE_DECODER(keytype_name, keytype, type, kind) \
+ static const struct keytype_desc_st kind##_##keytype##_desc = \
+ { keytype_name, ossl_##keytype##_keymgmt_functions, \
+ DO_##kind(keytype) }; \
+ \
+ static OSSL_FUNC_decoder_newctx_fn kind##_der2##keytype##_newctx; \
+ \
+ static void *kind##_der2##keytype##_newctx(void *provctx) \
+ { \
+ return der2key_newctx(provctx, &kind##_##keytype##_desc); \
+ } \
+ static int kind##_der2##keytype##_does_selection(void *provctx, \
+ int selection) \
+ { \
+ return der2key_check_selection(selection, \
+ &kind##_##keytype##_desc); \
+ } \
+ const OSSL_DISPATCH \
+ ossl_##kind##_der_to_##keytype##_decoder_functions[] = { \
+ { OSSL_FUNC_DECODER_NEWCTX, \
+ (void (*)(void))kind##_der2##keytype##_newctx }, \
+ { OSSL_FUNC_DECODER_FREECTX, \
+ (void (*)(void))der2key_freectx }, \
+ { OSSL_FUNC_DECODER_DOES_SELECTION, \
+ (void (*)(void))kind##_der2##keytype##_does_selection }, \
+ { OSSL_FUNC_DECODER_DECODE, \
+ (void (*)(void))der2key_decode }, \
+ { OSSL_FUNC_DECODER_EXPORT_OBJECT, \
+ (void (*)(void))der2key_export_object }, \
+ { 0, NULL } \
+ }
+
+#ifndef OPENSSL_NO_DH
+MAKE_DECODER("DH", dh, dh, PrivateKeyInfo);
+MAKE_DECODER("DH", dh, dh, SubjectPublicKeyInfo);
+MAKE_DECODER("DH", dh, dh, type_specific_params);
+MAKE_DECODER("DH", dh, dh, DH);
+MAKE_DECODER("DHX", dhx, dhx, PrivateKeyInfo);
+MAKE_DECODER("DHX", dhx, dhx, SubjectPublicKeyInfo);
+MAKE_DECODER("DHX", dhx, dhx, type_specific_params);
+MAKE_DECODER("DHX", dhx, dhx, DHX);
+#endif
+#ifndef OPENSSL_NO_DSA
+MAKE_DECODER("DSA", dsa, dsa, PrivateKeyInfo);
+MAKE_DECODER("DSA", dsa, dsa, SubjectPublicKeyInfo);
+MAKE_DECODER("DSA", dsa, dsa, type_specific);
+MAKE_DECODER("DSA", dsa, dsa, DSA);
+#endif
+#ifndef OPENSSL_NO_EC
+MAKE_DECODER("EC", ec, ec, PrivateKeyInfo);
+MAKE_DECODER("EC", ec, ec, SubjectPublicKeyInfo);
+MAKE_DECODER("EC", ec, ec, type_specific_no_pub);
+MAKE_DECODER("EC", ec, ec, EC);
+MAKE_DECODER("X25519", x25519, ecx, PrivateKeyInfo);
+MAKE_DECODER("X25519", x25519, ecx, SubjectPublicKeyInfo);
+MAKE_DECODER("X448", x448, ecx, PrivateKeyInfo);
+MAKE_DECODER("X448", x448, ecx, SubjectPublicKeyInfo);
+MAKE_DECODER("ED25519", ed25519, ecx, PrivateKeyInfo);
+MAKE_DECODER("ED25519", ed25519, ecx, SubjectPublicKeyInfo);
+MAKE_DECODER("ED448", ed448, ecx, PrivateKeyInfo);
+MAKE_DECODER("ED448", ed448, ecx, SubjectPublicKeyInfo);
+# ifndef OPENSSL_NO_SM2
+MAKE_DECODER("SM2", sm2, ec, PrivateKeyInfo);
+MAKE_DECODER("SM2", sm2, ec, SubjectPublicKeyInfo);
+# endif
+#endif
+MAKE_DECODER("RSA", rsa, rsa, PrivateKeyInfo);
+MAKE_DECODER("RSA", rsa, rsa, SubjectPublicKeyInfo);
+MAKE_DECODER("RSA", rsa, rsa, type_specific_keypair);
+MAKE_DECODER("RSA", rsa, rsa, RSA);
+MAKE_DECODER("RSA-PSS", rsapss, rsapss, PrivateKeyInfo);
+MAKE_DECODER("RSA-PSS", rsapss, rsapss, SubjectPublicKeyInfo);
diff --git a/providers/implementations/encode_decode/decode_epki2pki.c b/providers/implementations/encode_decode/decode_epki2pki.c
new file mode 100644
index 000000000000..9cea80b616d6
--- /dev/null
+++ b/providers/implementations/encode_decode/decode_epki2pki.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/core_object.h>
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/objects.h>
+#include <openssl/pkcs12.h>
+#include <openssl/x509.h>
+#include <openssl/proverr.h>
+#include "internal/asn1.h"
+#include "internal/sizes.h"
+#include "prov/bio.h"
+#include "prov/implementations.h"
+#include "endecoder_local.h"
+
+static OSSL_FUNC_decoder_newctx_fn epki2pki_newctx;
+static OSSL_FUNC_decoder_freectx_fn epki2pki_freectx;
+static OSSL_FUNC_decoder_decode_fn epki2pki_decode;
+
+/*
+ * Context used for EncryptedPrivateKeyInfo to PrivateKeyInfo decoding.
+ */
+struct epki2pki_ctx_st {
+ PROV_CTX *provctx;
+};
+
+static void *epki2pki_newctx(void *provctx)
+{
+ struct epki2pki_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx != NULL)
+ ctx->provctx = provctx;
+ return ctx;
+}
+
+static void epki2pki_freectx(void *vctx)
+{
+ struct epki2pki_ctx_st *ctx = vctx;
+
+ OPENSSL_free(ctx);
+}
+
+/*
+ * The selection parameter in epki2pki_decode() is not used by this function
+ * because it's not relevant just to decode EncryptedPrivateKeyInfo to
+ * PrivateKeyInfo.
+ */
+static int epki2pki_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
+ OSSL_CALLBACK *data_cb, void *data_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+ struct epki2pki_ctx_st *ctx = vctx;
+ BUF_MEM *mem = NULL;
+ unsigned char *der = NULL;
+ const unsigned char *pder = NULL;
+ long der_len = 0;
+ X509_SIG *p8 = NULL;
+ PKCS8_PRIV_KEY_INFO *p8inf = NULL;
+ const X509_ALGOR *alg = NULL;
+ BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin);
+ int ok = 0;
+
+ if (in == NULL)
+ return 0;
+
+ ok = (asn1_d2i_read_bio(in, &mem) >= 0);
+ BIO_free(in);
+
+ /* We return "empty handed". This is not an error. */
+ if (!ok)
+ return 1;
+
+ pder = der = (unsigned char *)mem->data;
+ der_len = (long)mem->length;
+ OPENSSL_free(mem);
+
+ ok = 1; /* Assume good */
+ ERR_set_mark();
+ if ((p8 = d2i_X509_SIG(NULL, &pder, der_len)) != NULL) {
+ char pbuf[1024];
+ size_t plen = 0;
+
+ ERR_clear_last_mark();
+
+ if (!pw_cb(pbuf, sizeof(pbuf), &plen, NULL, pw_cbarg)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PASSPHRASE);
+ ok = 0;
+ } else {
+ const ASN1_OCTET_STRING *oct;
+ unsigned char *new_der = NULL;
+ int new_der_len = 0;
+
+ X509_SIG_get0(p8, &alg, &oct);
+ if (!PKCS12_pbe_crypt_ex(alg, pbuf, plen,
+ oct->data, oct->length,
+ &new_der, &new_der_len, 0,
+ PROV_LIBCTX_OF(ctx->provctx), NULL)) {
+ ok = 0;
+ } else {
+ OPENSSL_free(der);
+ der = new_der;
+ der_len = new_der_len;
+ }
+ alg = NULL;
+ }
+ X509_SIG_free(p8);
+ } else {
+ ERR_pop_to_mark();
+ }
+
+ ERR_set_mark();
+ pder = der;
+ p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &pder, der_len);
+ ERR_pop_to_mark();
+
+ if (p8inf != NULL && PKCS8_pkey_get0(NULL, NULL, NULL, &alg, p8inf)) {
+ /*
+ * We have something and recognised it as PrivateKeyInfo, so let's
+ * pass all the applicable data to the callback.
+ */
+ char keytype[OSSL_MAX_NAME_SIZE];
+ OSSL_PARAM params[5], *p = params;
+ int objtype = OSSL_OBJECT_PKEY;
+
+ OBJ_obj2txt(keytype, sizeof(keytype), alg->algorithm, 0);
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
+ keytype, 0);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE,
+ "PrivateKeyInfo", 0);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA,
+ der, der_len);
+ *p++ = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype);
+ *p = OSSL_PARAM_construct_end();
+
+ ok = data_cb(params, data_cbarg);
+ }
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ OPENSSL_free(der);
+ return ok;
+}
+
+const OSSL_DISPATCH ossl_EncryptedPrivateKeyInfo_der_to_der_decoder_functions[] = {
+ { OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))epki2pki_newctx },
+ { OSSL_FUNC_DECODER_FREECTX, (void (*)(void))epki2pki_freectx },
+ { OSSL_FUNC_DECODER_DECODE, (void (*)(void))epki2pki_decode },
+ { 0, NULL }
+};
diff --git a/providers/implementations/encode_decode/decode_msblob2key.c b/providers/implementations/encode_decode/decode_msblob2key.c
new file mode 100644
index 000000000000..501957faba01
--- /dev/null
+++ b/providers/implementations/encode_decode/decode_msblob2key.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h>
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/core_object.h>
+#include <openssl/crypto.h>
+#include <openssl/params.h>
+#include <openssl/pem.h> /* For public PVK functions */
+#include <openssl/x509.h>
+#include <openssl/err.h>
+#include "internal/passphrase.h"
+#include "crypto/pem.h" /* For internal PVK and "blob" headers */
+#include "crypto/rsa.h"
+#include "prov/bio.h"
+#include "prov/implementations.h"
+#include "endecoder_local.h"
+
+struct msblob2key_ctx_st; /* Forward declaration */
+typedef void *b2i_of_void_fn(const unsigned char **in, unsigned int bitlen,
+ int ispub);
+typedef void adjust_key_fn(void *, struct msblob2key_ctx_st *ctx);
+typedef void free_key_fn(void *);
+struct keytype_desc_st {
+ int type; /* EVP key type */
+ const char *name; /* Keytype */
+ const OSSL_DISPATCH *fns; /* Keymgmt (to pilfer functions from) */
+
+ b2i_of_void_fn *read_private_key;
+ b2i_of_void_fn *read_public_key;
+ adjust_key_fn *adjust_key;
+ free_key_fn *free_key;
+};
+
+static OSSL_FUNC_decoder_freectx_fn msblob2key_freectx;
+static OSSL_FUNC_decoder_decode_fn msblob2key_decode;
+static OSSL_FUNC_decoder_export_object_fn msblob2key_export_object;
+
+/*
+ * Context used for DER to key decoding.
+ */
+struct msblob2key_ctx_st {
+ PROV_CTX *provctx;
+ const struct keytype_desc_st *desc;
+ /* The selection that is passed to msblob2key_decode() */
+ int selection;
+};
+
+static struct msblob2key_ctx_st *
+msblob2key_newctx(void *provctx, const struct keytype_desc_st *desc)
+{
+ struct msblob2key_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx != NULL) {
+ ctx->provctx = provctx;
+ ctx->desc = desc;
+ }
+ return ctx;
+}
+
+static void msblob2key_freectx(void *vctx)
+{
+ struct msblob2key_ctx_st *ctx = vctx;
+
+ OPENSSL_free(ctx);
+}
+
+static int msblob2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
+ OSSL_CALLBACK *data_cb, void *data_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+ struct msblob2key_ctx_st *ctx = vctx;
+ BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin);
+ const unsigned char *p;
+ unsigned char hdr_buf[16], *buf = NULL;
+ unsigned int bitlen, magic, length;
+ int isdss = -1;
+ int ispub = -1;
+ void *key = NULL;
+ int ok = 0;
+
+ if (in == NULL)
+ return 0;
+
+ if (BIO_read(in, hdr_buf, 16) != 16) {
+ ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT);
+ goto next;
+ }
+ ERR_set_mark();
+ p = hdr_buf;
+ ok = ossl_do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) > 0;
+ ERR_pop_to_mark();
+ if (!ok)
+ goto next;
+
+ ctx->selection = selection;
+ ok = 0; /* Assume that we fail */
+
+ if ((isdss && ctx->desc->type != EVP_PKEY_DSA)
+ || (!isdss && ctx->desc->type != EVP_PKEY_RSA))
+ goto next;
+
+ length = ossl_blob_length(bitlen, isdss, ispub);
+ if (length > BLOB_MAX_LENGTH) {
+ ERR_raise(ERR_LIB_PEM, PEM_R_HEADER_TOO_LONG);
+ goto next;
+ }
+ buf = OPENSSL_malloc(length);
+ if (buf == NULL) {
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+ p = buf;
+ if (BIO_read(in, buf, length) != (int)length) {
+ ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT);
+ goto next;
+ }
+
+ if ((selection == 0
+ || (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ && !ispub
+ && ctx->desc->read_private_key != NULL) {
+ struct ossl_passphrase_data_st pwdata;
+
+ memset(&pwdata, 0, sizeof(pwdata));
+ if (!ossl_pw_set_ossl_passphrase_cb(&pwdata, pw_cb, pw_cbarg))
+ goto end;
+ p = buf;
+ key = ctx->desc->read_private_key(&p, bitlen, ispub);
+ if (selection != 0 && key == NULL)
+ goto next;
+ }
+ if (key == NULL && (selection == 0
+ || (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ && ispub
+ && ctx->desc->read_public_key != NULL) {
+ p = buf;
+ key = ctx->desc->read_public_key(&p, bitlen, ispub);
+ if (selection != 0 && key == NULL)
+ goto next;
+ }
+
+ if (key != NULL && ctx->desc->adjust_key != NULL)
+ ctx->desc->adjust_key(key, ctx);
+
+ next:
+ /*
+ * Indicated that we successfully decoded something, or not at all.
+ * Ending up "empty handed" is not an error.
+ */
+ ok = 1;
+
+ /*
+ * We free resources here so it's not held up during the callback, because
+ * we know the process is recursive and the allocated chunks of memory
+ * add up.
+ */
+ OPENSSL_free(buf);
+ BIO_free(in);
+ buf = NULL;
+ in = NULL;
+
+ if (key != NULL) {
+ OSSL_PARAM params[4];
+ int object_type = OSSL_OBJECT_PKEY;
+
+ params[0] =
+ OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &object_type);
+ params[1] =
+ OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
+ (char *)ctx->desc->name, 0);
+ /* The address of the key becomes the octet string */
+ params[2] =
+ OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_REFERENCE,
+ &key, sizeof(key));
+ params[3] = OSSL_PARAM_construct_end();
+
+ ok = data_cb(params, data_cbarg);
+ }
+
+ end:
+ BIO_free(in);
+ OPENSSL_free(buf);
+ ctx->desc->free_key(key);
+
+ return ok;
+}
+
+static int
+msblob2key_export_object(void *vctx,
+ const void *reference, size_t reference_sz,
+ OSSL_CALLBACK *export_cb, void *export_cbarg)
+{
+ struct msblob2key_ctx_st *ctx = vctx;
+ OSSL_FUNC_keymgmt_export_fn *export =
+ ossl_prov_get_keymgmt_export(ctx->desc->fns);
+ void *keydata;
+
+ if (reference_sz == sizeof(keydata) && export != NULL) {
+ /* The contents of the reference is the address to our object */
+ keydata = *(void **)reference;
+
+ return export(keydata, ctx->selection, export_cb, export_cbarg);
+ }
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+#define dsa_decode_private_key (b2i_of_void_fn *)ossl_b2i_DSA_after_header
+#define dsa_decode_public_key (b2i_of_void_fn *)ossl_b2i_DSA_after_header
+#define dsa_adjust NULL
+#define dsa_free (void (*)(void *))DSA_free
+
+/* ---------------------------------------------------------------------- */
+
+#define rsa_decode_private_key (b2i_of_void_fn *)ossl_b2i_RSA_after_header
+#define rsa_decode_public_key (b2i_of_void_fn *)ossl_b2i_RSA_after_header
+
+static void rsa_adjust(void *key, struct msblob2key_ctx_st *ctx)
+{
+ ossl_rsa_set0_libctx(key, PROV_LIBCTX_OF(ctx->provctx));
+}
+
+#define rsa_free (void (*)(void *))RSA_free
+
+/* ---------------------------------------------------------------------- */
+
+#define IMPLEMENT_MSBLOB(KEYTYPE, keytype) \
+ static const struct keytype_desc_st mstype##2##keytype##_desc = { \
+ EVP_PKEY_##KEYTYPE, #KEYTYPE, \
+ ossl_##keytype##_keymgmt_functions, \
+ keytype##_decode_private_key, \
+ keytype##_decode_public_key, \
+ keytype##_adjust, \
+ keytype##_free \
+ }; \
+ static OSSL_FUNC_decoder_newctx_fn msblob2##keytype##_newctx; \
+ static void *msblob2##keytype##_newctx(void *provctx) \
+ { \
+ return msblob2key_newctx(provctx, &mstype##2##keytype##_desc); \
+ } \
+ const OSSL_DISPATCH \
+ ossl_msblob_to_##keytype##_decoder_functions[] = { \
+ { OSSL_FUNC_DECODER_NEWCTX, \
+ (void (*)(void))msblob2##keytype##_newctx }, \
+ { OSSL_FUNC_DECODER_FREECTX, \
+ (void (*)(void))msblob2key_freectx }, \
+ { OSSL_FUNC_DECODER_DECODE, \
+ (void (*)(void))msblob2key_decode }, \
+ { OSSL_FUNC_DECODER_EXPORT_OBJECT, \
+ (void (*)(void))msblob2key_export_object }, \
+ { 0, NULL } \
+ }
+
+#ifndef OPENSSL_NO_DSA
+IMPLEMENT_MSBLOB(DSA, dsa);
+#endif
+IMPLEMENT_MSBLOB(RSA, rsa);
diff --git a/providers/implementations/encode_decode/decode_pem2der.c b/providers/implementations/encode_decode/decode_pem2der.c
new file mode 100644
index 000000000000..bc937ffb9d27
--- /dev/null
+++ b/providers/implementations/encode_decode/decode_pem2der.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h>
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/core_object.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/params.h>
+#include <openssl/pem.h>
+#include <openssl/proverr.h>
+#include "internal/nelem.h"
+#include "prov/bio.h"
+#include "prov/implementations.h"
+#include "endecoder_local.h"
+
+static int read_pem(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
+ char **pem_name, char **pem_header,
+ unsigned char **data, long *len)
+{
+ BIO *in = ossl_bio_new_from_core_bio(provctx, cin);
+ int ok;
+
+ if (in == NULL)
+ return 0;
+ ok = (PEM_read_bio(in, pem_name, pem_header, data, len) > 0);
+
+ BIO_free(in);
+ return ok;
+}
+
+static OSSL_FUNC_decoder_newctx_fn pem2der_newctx;
+static OSSL_FUNC_decoder_freectx_fn pem2der_freectx;
+static OSSL_FUNC_decoder_decode_fn pem2der_decode;
+
+/*
+ * Context used for PEM to DER decoding.
+ */
+struct pem2der_ctx_st {
+ PROV_CTX *provctx;
+};
+
+static void *pem2der_newctx(void *provctx)
+{
+ struct pem2der_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx != NULL)
+ ctx->provctx = provctx;
+ return ctx;
+}
+
+static void pem2der_freectx(void *vctx)
+{
+ struct pem2der_ctx_st *ctx = vctx;
+
+ OPENSSL_free(ctx);
+}
+
+/* pem_password_cb compatible function */
+struct pem2der_pass_data_st {
+ OSSL_PASSPHRASE_CALLBACK *cb;
+ void *cbarg;
+};
+
+static int pem2der_pass_helper(char *buf, int num, int w, void *data)
+{
+ struct pem2der_pass_data_st *pass_data = data;
+ size_t plen;
+
+ if (pass_data == NULL
+ || pass_data->cb == NULL
+ || !pass_data->cb(buf, num, &plen, NULL, pass_data->cbarg))
+ return -1;
+ return (int)plen;
+}
+
+/*
+ * The selection parameter in pem2der_decode() is not used by this function
+ * because it's not relevant just to decode PEM to DER.
+ */
+static int pem2der_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
+ OSSL_CALLBACK *data_cb, void *data_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+ /*
+ * PEM names we recognise. Other PEM names should be recognised by
+ * other decoder implementations.
+ */
+ static struct pem_name_map_st {
+ const char *pem_name;
+ int object_type;
+ const char *data_type;
+ const char *data_structure;
+ } pem_name_map[] = {
+ /* PKCS#8 and SubjectPublicKeyInfo */
+ { PEM_STRING_PKCS8, OSSL_OBJECT_PKEY, NULL, "EncryptedPrivateKeyInfo" },
+ { PEM_STRING_PKCS8INF, OSSL_OBJECT_PKEY, NULL, "PrivateKeyInfo" },
+ { PEM_STRING_PUBLIC, OSSL_OBJECT_PKEY, NULL, "SubjectPublicKeyInfo" },
+
+ /* Our set of type specific PEM types */
+ { PEM_STRING_DHPARAMS, OSSL_OBJECT_PKEY, "DH", "type-specific" },
+ { PEM_STRING_DHXPARAMS, OSSL_OBJECT_PKEY, "X9.42 DH", "type-specific" },
+ { PEM_STRING_DSA, OSSL_OBJECT_PKEY, "DSA", "type-specific" },
+ { PEM_STRING_DSA_PUBLIC, OSSL_OBJECT_PKEY, "DSA", "type-specific" },
+ { PEM_STRING_DSAPARAMS, OSSL_OBJECT_PKEY, "DSA", "type-specific" },
+ { PEM_STRING_ECPRIVATEKEY, OSSL_OBJECT_PKEY, "EC", "type-specific" },
+ { PEM_STRING_ECPARAMETERS, OSSL_OBJECT_PKEY, "EC", "type-specific" },
+ { PEM_STRING_RSA, OSSL_OBJECT_PKEY, "RSA", "type-specific" },
+ { PEM_STRING_RSA_PUBLIC, OSSL_OBJECT_PKEY, "RSA", "type-specific" },
+
+ /*
+ * A few others that there is at least have an object type for, even
+ * though there is no provider interface to handle such objects, yet.
+ * However, this is beneficial for the OSSL_STORE result handler.
+ */
+ { PEM_STRING_X509, OSSL_OBJECT_CERT, NULL, "Certificate" },
+ { PEM_STRING_X509_TRUSTED, OSSL_OBJECT_CERT, NULL, "Certificate" },
+ { PEM_STRING_X509_OLD, OSSL_OBJECT_CERT, NULL, "Certificate" },
+ { PEM_STRING_X509_CRL, OSSL_OBJECT_CRL, NULL, "CertificateList" }
+ };
+ struct pem2der_ctx_st *ctx = vctx;
+ char *pem_name = NULL, *pem_header = NULL;
+ size_t i;
+ unsigned char *der = NULL;
+ long der_len = 0;
+ int ok = 0;
+ int objtype = OSSL_OBJECT_UNKNOWN;
+
+ ok = read_pem(ctx->provctx, cin, &pem_name, &pem_header,
+ &der, &der_len) > 0;
+ /* We return "empty handed". This is not an error. */
+ if (!ok)
+ return 1;
+
+ /*
+ * 10 is the number of characters in "Proc-Type:", which
+ * PEM_get_EVP_CIPHER_INFO() requires to be present.
+ * If the PEM header has less characters than that, it's
+ * not worth spending cycles on it.
+ */
+ if (strlen(pem_header) > 10) {
+ EVP_CIPHER_INFO cipher;
+ struct pem2der_pass_data_st pass_data;
+
+ ok = 0; /* Assume that we fail */
+ pass_data.cb = pw_cb;
+ pass_data.cbarg = pw_cbarg;
+ if (!PEM_get_EVP_CIPHER_INFO(pem_header, &cipher)
+ || !PEM_do_header(&cipher, der, &der_len,
+ pem2der_pass_helper, &pass_data))
+ goto end;
+ }
+
+ /*
+ * Indicated that we successfully decoded something, or not at all.
+ * Ending up "empty handed" is not an error.
+ */
+ ok = 1;
+
+ /* Have a look to see if we recognise anything */
+ for (i = 0; i < OSSL_NELEM(pem_name_map); i++)
+ if (strcmp(pem_name, pem_name_map[i].pem_name) == 0)
+ break;
+
+ if (i < OSSL_NELEM(pem_name_map)) {
+ OSSL_PARAM params[5], *p = params;
+ /* We expect these to be read only so casting away the const is ok */
+ char *data_type = (char *)pem_name_map[i].data_type;
+ char *data_structure = (char *)pem_name_map[i].data_structure;
+
+ objtype = pem_name_map[i].object_type;
+ if (data_type != NULL)
+ *p++ =
+ OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
+ data_type, 0);
+
+ /* We expect this to be read only so casting away the const is ok */
+ if (data_structure != NULL)
+ *p++ =
+ OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE,
+ data_structure, 0);
+ *p++ =
+ OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA,
+ der, der_len);
+ *p++ =
+ OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype);
+
+ *p = OSSL_PARAM_construct_end();
+
+ ok = data_cb(params, data_cbarg);
+ }
+
+ end:
+ OPENSSL_free(pem_name);
+ OPENSSL_free(pem_header);
+ OPENSSL_free(der);
+ return ok;
+}
+
+const OSSL_DISPATCH ossl_pem_to_der_decoder_functions[] = {
+ { OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))pem2der_newctx },
+ { OSSL_FUNC_DECODER_FREECTX, (void (*)(void))pem2der_freectx },
+ { OSSL_FUNC_DECODER_DECODE, (void (*)(void))pem2der_decode },
+ { 0, NULL }
+};
diff --git a/providers/implementations/encode_decode/decode_pvk2key.c b/providers/implementations/encode_decode/decode_pvk2key.c
new file mode 100644
index 000000000000..c6424165b03b
--- /dev/null
+++ b/providers/implementations/encode_decode/decode_pvk2key.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h>
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/core_object.h>
+#include <openssl/crypto.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#include <openssl/pem.h> /* For public PVK functions */
+#include <openssl/x509.h>
+#include "internal/passphrase.h"
+#include "crypto/pem.h" /* For internal PVK and "blob" headers */
+#include "crypto/rsa.h"
+#include "prov/bio.h"
+#include "prov/implementations.h"
+#include "endecoder_local.h"
+
+struct pvk2key_ctx_st; /* Forward declaration */
+typedef int check_key_fn(void *, struct pvk2key_ctx_st *ctx);
+typedef void adjust_key_fn(void *, struct pvk2key_ctx_st *ctx);
+typedef void *b2i_PVK_of_bio_pw_fn(BIO *in, pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
+typedef void free_key_fn(void *);
+struct keytype_desc_st {
+ int type; /* EVP key type */
+ const char *name; /* Keytype */
+ const OSSL_DISPATCH *fns; /* Keymgmt (to pilfer functions from) */
+
+ b2i_PVK_of_bio_pw_fn *read_private_key;
+ adjust_key_fn *adjust_key;
+ free_key_fn *free_key;
+};
+
+static OSSL_FUNC_decoder_freectx_fn pvk2key_freectx;
+static OSSL_FUNC_decoder_decode_fn pvk2key_decode;
+static OSSL_FUNC_decoder_export_object_fn pvk2key_export_object;
+
+/*
+ * Context used for DER to key decoding.
+ */
+struct pvk2key_ctx_st {
+ PROV_CTX *provctx;
+ const struct keytype_desc_st *desc;
+ /* The selection that is passed to der2key_decode() */
+ int selection;
+};
+
+static struct pvk2key_ctx_st *
+pvk2key_newctx(void *provctx, const struct keytype_desc_st *desc)
+{
+ struct pvk2key_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx != NULL) {
+ ctx->provctx = provctx;
+ ctx->desc = desc;
+ }
+ return ctx;
+}
+
+static void pvk2key_freectx(void *vctx)
+{
+ struct pvk2key_ctx_st *ctx = vctx;
+
+ OPENSSL_free(ctx);
+}
+
+static int pvk2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
+ OSSL_CALLBACK *data_cb, void *data_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+ struct pvk2key_ctx_st *ctx = vctx;
+ BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin);
+ void *key = NULL;
+ int ok = 0;
+
+ if (in == NULL)
+ return 0;
+
+ ctx->selection = selection;
+
+ if ((selection == 0
+ || (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ && ctx->desc->read_private_key != NULL) {
+ struct ossl_passphrase_data_st pwdata;
+ int err, lib, reason;
+
+ memset(&pwdata, 0, sizeof(pwdata));
+ if (!ossl_pw_set_ossl_passphrase_cb(&pwdata, pw_cb, pw_cbarg))
+ goto end;
+
+ key = ctx->desc->read_private_key(in, ossl_pw_pvk_password, &pwdata,
+ PROV_LIBCTX_OF(ctx->provctx), NULL);
+
+ /*
+ * Because the PVK API doesn't have a separate decrypt call, we need
+ * to check the error queue for certain well known errors that are
+ * considered fatal and which we pass through, while the rest gets
+ * thrown away.
+ */
+ err = ERR_peek_last_error();
+ lib = ERR_GET_LIB(err);
+ reason = ERR_GET_REASON(err);
+ if (lib == ERR_LIB_PEM
+ && (reason == PEM_R_BAD_PASSWORD_READ
+ || reason == PEM_R_BAD_DECRYPT)) {
+ ERR_clear_last_mark();
+ goto end;
+ }
+
+ if (selection != 0 && key == NULL)
+ goto next;
+ }
+
+ if (key != NULL && ctx->desc->adjust_key != NULL)
+ ctx->desc->adjust_key(key, ctx);
+
+ next:
+ /*
+ * Indicated that we successfully decoded something, or not at all.
+ * Ending up "empty handed" is not an error.
+ */
+ ok = 1;
+
+ /*
+ * We free resources here so it's not held up during the callback, because
+ * we know the process is recursive and the allocated chunks of memory
+ * add up.
+ */
+ BIO_free(in);
+ in = NULL;
+
+ if (key != NULL) {
+ OSSL_PARAM params[4];
+ int object_type = OSSL_OBJECT_PKEY;
+
+ params[0] =
+ OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &object_type);
+ params[1] =
+ OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
+ (char *)ctx->desc->name, 0);
+ /* The address of the key becomes the octet string */
+ params[2] =
+ OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_REFERENCE,
+ &key, sizeof(key));
+ params[3] = OSSL_PARAM_construct_end();
+
+ ok = data_cb(params, data_cbarg);
+ }
+
+ end:
+ BIO_free(in);
+ ctx->desc->free_key(key);
+
+ return ok;
+}
+
+static int pvk2key_export_object(void *vctx,
+ const void *reference, size_t reference_sz,
+ OSSL_CALLBACK *export_cb, void *export_cbarg)
+{
+ struct pvk2key_ctx_st *ctx = vctx;
+ OSSL_FUNC_keymgmt_export_fn *export =
+ ossl_prov_get_keymgmt_export(ctx->desc->fns);
+ void *keydata;
+
+ if (reference_sz == sizeof(keydata) && export != NULL) {
+ /* The contents of the reference is the address to our object */
+ keydata = *(void **)reference;
+
+ return export(keydata, ctx->selection, export_cb, export_cbarg);
+ }
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+#define dsa_private_key_bio (b2i_PVK_of_bio_pw_fn *)b2i_DSA_PVK_bio_ex
+#define dsa_adjust NULL
+#define dsa_free (void (*)(void *))DSA_free
+
+/* ---------------------------------------------------------------------- */
+
+#define rsa_private_key_bio (b2i_PVK_of_bio_pw_fn *)b2i_RSA_PVK_bio_ex
+
+static void rsa_adjust(void *key, struct pvk2key_ctx_st *ctx)
+{
+ ossl_rsa_set0_libctx(key, PROV_LIBCTX_OF(ctx->provctx));
+}
+
+#define rsa_free (void (*)(void *))RSA_free
+
+/* ---------------------------------------------------------------------- */
+
+#define IMPLEMENT_MS(KEYTYPE, keytype) \
+ static const struct keytype_desc_st \
+ pvk2##keytype##_desc = { \
+ EVP_PKEY_##KEYTYPE, #KEYTYPE, \
+ ossl_##keytype##_keymgmt_functions, \
+ keytype##_private_key_bio, \
+ keytype##_adjust, \
+ keytype##_free \
+ }; \
+ static OSSL_FUNC_decoder_newctx_fn pvk2##keytype##_newctx; \
+ static void *pvk2##keytype##_newctx(void *provctx) \
+ { \
+ return pvk2key_newctx(provctx, &pvk2##keytype##_desc); \
+ } \
+ const OSSL_DISPATCH \
+ ossl_##pvk_to_##keytype##_decoder_functions[] = { \
+ { OSSL_FUNC_DECODER_NEWCTX, \
+ (void (*)(void))pvk2##keytype##_newctx }, \
+ { OSSL_FUNC_DECODER_FREECTX, \
+ (void (*)(void))pvk2key_freectx }, \
+ { OSSL_FUNC_DECODER_DECODE, \
+ (void (*)(void))pvk2key_decode }, \
+ { OSSL_FUNC_DECODER_EXPORT_OBJECT, \
+ (void (*)(void))pvk2key_export_object }, \
+ { 0, NULL } \
+ }
+
+#ifndef OPENSSL_NO_DSA
+IMPLEMENT_MS(DSA, dsa);
+#endif
+IMPLEMENT_MS(RSA, rsa);
diff --git a/providers/implementations/encode_decode/decode_spki2typespki.c b/providers/implementations/encode_decode/decode_spki2typespki.c
new file mode 100644
index 000000000000..a5dbbb31adf8
--- /dev/null
+++ b/providers/implementations/encode_decode/decode_spki2typespki.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/asn1t.h>
+#include <openssl/core_names.h>
+#include <openssl/core_object.h>
+#include <openssl/params.h>
+#include <openssl/x509.h>
+#include "internal/sizes.h"
+#include "crypto/x509.h"
+#include "crypto/ec.h"
+#include "prov/bio.h"
+#include "prov/implementations.h"
+#include "endecoder_local.h"
+
+static OSSL_FUNC_decoder_newctx_fn spki2typespki_newctx;
+static OSSL_FUNC_decoder_freectx_fn spki2typespki_freectx;
+static OSSL_FUNC_decoder_decode_fn spki2typespki_decode;
+
+/*
+ * Context used for SubjectPublicKeyInfo to Type specific SubjectPublicKeyInfo
+ * decoding.
+ */
+struct spki2typespki_ctx_st {
+ PROV_CTX *provctx;
+};
+
+static void *spki2typespki_newctx(void *provctx)
+{
+ struct spki2typespki_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx != NULL)
+ ctx->provctx = provctx;
+ return ctx;
+}
+
+static void spki2typespki_freectx(void *vctx)
+{
+ struct spki2typespki_ctx_st *ctx = vctx;
+
+ OPENSSL_free(ctx);
+}
+
+static int spki2typespki_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
+ OSSL_CALLBACK *data_cb, void *data_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+ struct spki2typespki_ctx_st *ctx = vctx;
+ unsigned char *der, *derp;
+ long len;
+ int ok = 0;
+ int objtype = OSSL_OBJECT_PKEY;
+ X509_PUBKEY *xpub = NULL;
+ X509_ALGOR *algor = NULL;
+ const ASN1_OBJECT *oid = NULL;
+ char dataname[OSSL_MAX_NAME_SIZE];
+ OSSL_PARAM params[5], *p = params;
+
+ if (!ossl_read_der(ctx->provctx, cin, &der, &len))
+ return 1;
+ derp = der;
+ xpub = ossl_d2i_X509_PUBKEY_INTERNAL((const unsigned char **)&derp, len,
+ PROV_LIBCTX_OF(ctx->provctx));
+
+
+ if (xpub == NULL) {
+ /* We return "empty handed". This is not an error. */
+ ok = 1;
+ goto end;
+ }
+
+ if (!X509_PUBKEY_get0_param(NULL, NULL, NULL, &algor, xpub))
+ goto end;
+ X509_ALGOR_get0(&oid, NULL, NULL, algor);
+
+#ifndef OPENSSL_NO_EC
+ /* SM2 abuses the EC oid, so this could actually be SM2 */
+ if (OBJ_obj2nid(oid) == NID_X9_62_id_ecPublicKey
+ && ossl_x509_algor_is_sm2(algor))
+ strcpy(dataname, "SM2");
+ else
+#endif
+ if (OBJ_obj2txt(dataname, sizeof(dataname), oid, 0) <= 0)
+ goto end;
+
+ ossl_X509_PUBKEY_INTERNAL_free(xpub);
+ xpub = NULL;
+
+ *p++ =
+ OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
+ dataname, 0);
+
+ *p++ =
+ OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE,
+ "SubjectPublicKeyInfo",
+ 0);
+ *p++ =
+ OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA, der, len);
+ *p++ =
+ OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype);
+
+ *p = OSSL_PARAM_construct_end();
+
+ ok = data_cb(params, data_cbarg);
+
+ end:
+ ossl_X509_PUBKEY_INTERNAL_free(xpub);
+ OPENSSL_free(der);
+ return ok;
+}
+
+const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_der_decoder_functions[] = {
+ { OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))spki2typespki_newctx },
+ { OSSL_FUNC_DECODER_FREECTX, (void (*)(void))spki2typespki_freectx },
+ { OSSL_FUNC_DECODER_DECODE, (void (*)(void))spki2typespki_decode },
+ { 0, NULL }
+};
diff --git a/providers/implementations/encode_decode/encode_key2any.c b/providers/implementations/encode_decode/encode_key2any.c
new file mode 100644
index 000000000000..c7b01cb2b3e5
--- /dev/null
+++ b/providers/implementations/encode_decode/encode_key2any.c
@@ -0,0 +1,1465 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Low level APIs are deprecated for public use, but still ok for internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/crypto.h>
+#include <openssl/params.h>
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+#include <openssl/pkcs12.h> /* PKCS8_encrypt() */
+#include <openssl/dh.h>
+#include <openssl/dsa.h>
+#include <openssl/ec.h>
+#include <openssl/proverr.h>
+#include "internal/passphrase.h"
+#include "internal/cryptlib.h"
+#include "crypto/ecx.h"
+#include "crypto/rsa.h"
+#include "prov/implementations.h"
+#include "prov/bio.h"
+#include "prov/provider_ctx.h"
+#include "prov/der_rsa.h"
+#include "endecoder_local.h"
+
+#if defined(OPENSSL_NO_DH) && defined(OPENSSL_NO_DSA) && defined(OPENSSL_NO_EC)
+# define OPENSSL_NO_KEYPARAMS
+#endif
+
+struct key2any_ctx_st {
+ PROV_CTX *provctx;
+
+ /* Set to 0 if parameters should not be saved (dsa only) */
+ int save_parameters;
+
+ /* Set to 1 if intending to encrypt/decrypt, otherwise 0 */
+ int cipher_intent;
+
+ EVP_CIPHER *cipher;
+
+ struct ossl_passphrase_data_st pwdata;
+};
+
+typedef int check_key_type_fn(const void *key, int nid);
+typedef int key_to_paramstring_fn(const void *key, int nid, int save,
+ void **str, int *strtype);
+typedef int key_to_der_fn(BIO *out, const void *key,
+ int key_nid, const char *pemname,
+ key_to_paramstring_fn *p2s, i2d_of_void *k2d,
+ struct key2any_ctx_st *ctx);
+typedef int write_bio_of_void_fn(BIO *bp, const void *x);
+
+
+/* Free the blob allocated during key_to_paramstring_fn */
+static void free_asn1_data(int type, void *data)
+{
+ switch(type) {
+ case V_ASN1_OBJECT:
+ ASN1_OBJECT_free(data);
+ break;
+ case V_ASN1_SEQUENCE:
+ ASN1_STRING_free(data);
+ break;
+ }
+}
+
+static PKCS8_PRIV_KEY_INFO *key_to_p8info(const void *key, int key_nid,
+ void *params, int params_type,
+ i2d_of_void *k2d)
+{
+ /* der, derlen store the key DER output and its length */
+ unsigned char *der = NULL;
+ int derlen;
+ /* The final PKCS#8 info */
+ PKCS8_PRIV_KEY_INFO *p8info = NULL;
+
+ if ((p8info = PKCS8_PRIV_KEY_INFO_new()) == NULL
+ || (derlen = k2d(key, &der)) <= 0
+ || !PKCS8_pkey_set0(p8info, OBJ_nid2obj(key_nid), 0,
+ params_type, params, der, derlen)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ PKCS8_PRIV_KEY_INFO_free(p8info);
+ OPENSSL_free(der);
+ p8info = NULL;
+ }
+
+ return p8info;
+}
+
+static X509_SIG *p8info_to_encp8(PKCS8_PRIV_KEY_INFO *p8info,
+ struct key2any_ctx_st *ctx)
+{
+ X509_SIG *p8 = NULL;
+ char kstr[PEM_BUFSIZE];
+ size_t klen = 0;
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
+
+ if (ctx->cipher == NULL)
+ return NULL;
+
+ if (!ossl_pw_get_passphrase(kstr, sizeof(kstr), &klen, NULL, 1,
+ &ctx->pwdata)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PASSPHRASE);
+ return NULL;
+ }
+ /* First argument == -1 means "standard" */
+ p8 = PKCS8_encrypt_ex(-1, ctx->cipher, kstr, klen, NULL, 0, 0, p8info, libctx, NULL);
+ OPENSSL_cleanse(kstr, klen);
+ return p8;
+}
+
+static X509_SIG *key_to_encp8(const void *key, int key_nid,
+ void *params, int params_type,
+ i2d_of_void *k2d, struct key2any_ctx_st *ctx)
+{
+ PKCS8_PRIV_KEY_INFO *p8info =
+ key_to_p8info(key, key_nid, params, params_type, k2d);
+ X509_SIG *p8 = NULL;
+
+ if (p8info == NULL) {
+ free_asn1_data(params_type, params);
+ } else {
+ p8 = p8info_to_encp8(p8info, ctx);
+ PKCS8_PRIV_KEY_INFO_free(p8info);
+ }
+ return p8;
+}
+
+static X509_PUBKEY *key_to_pubkey(const void *key, int key_nid,
+ void *params, int params_type,
+ i2d_of_void k2d)
+{
+ /* der, derlen store the key DER output and its length */
+ unsigned char *der = NULL;
+ int derlen;
+ /* The final X509_PUBKEY */
+ X509_PUBKEY *xpk = NULL;
+
+
+ if ((xpk = X509_PUBKEY_new()) == NULL
+ || (derlen = k2d(key, &der)) <= 0
+ || !X509_PUBKEY_set0_param(xpk, OBJ_nid2obj(key_nid),
+ params_type, params, der, derlen)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ X509_PUBKEY_free(xpk);
+ OPENSSL_free(der);
+ xpk = NULL;
+ }
+
+ return xpk;
+}
+
+/*
+ * key_to_epki_* produce encoded output with the private key data in a
+ * EncryptedPrivateKeyInfo structure (defined by PKCS#8). They require
+ * that there's an intent to encrypt, anything else is an error.
+ *
+ * key_to_pki_* primarly produce encoded output with the private key data
+ * in a PrivateKeyInfo structure (also defined by PKCS#8). However, if
+ * there is an intent to encrypt the data, the corresponding key_to_epki_*
+ * function is used instead.
+ *
+ * key_to_spki_* produce encoded output with the public key data in an
+ * X.509 SubjectPublicKeyInfo.
+ *
+ * Key parameters don't have any defined envelopment of this kind, but are
+ * included in some manner in the output from the functions described above,
+ * either in the AlgorithmIdentifier's parameter field, or as part of the
+ * key data itself.
+ */
+
+static int key_to_epki_der_priv_bio(BIO *out, const void *key,
+ int key_nid,
+ ossl_unused const char *pemname,
+ key_to_paramstring_fn *p2s,
+ i2d_of_void *k2d,
+ struct key2any_ctx_st *ctx)
+{
+ int ret = 0;
+ void *str = NULL;
+ int strtype = V_ASN1_UNDEF;
+ X509_SIG *p8;
+
+ if (!ctx->cipher_intent)
+ return 0;
+
+ if (p2s != NULL && !p2s(key, key_nid, ctx->save_parameters,
+ &str, &strtype))
+ return 0;
+
+ p8 = key_to_encp8(key, key_nid, str, strtype, k2d, ctx);
+ if (p8 != NULL)
+ ret = i2d_PKCS8_bio(out, p8);
+
+ X509_SIG_free(p8);
+
+ return ret;
+}
+
+static int key_to_epki_pem_priv_bio(BIO *out, const void *key,
+ int key_nid,
+ ossl_unused const char *pemname,
+ key_to_paramstring_fn *p2s,
+ i2d_of_void *k2d,
+ struct key2any_ctx_st *ctx)
+{
+ int ret = 0;
+ void *str = NULL;
+ int strtype = V_ASN1_UNDEF;
+ X509_SIG *p8;
+
+ if (!ctx->cipher_intent)
+ return 0;
+
+ if (p2s != NULL && !p2s(key, key_nid, ctx->save_parameters,
+ &str, &strtype))
+ return 0;
+
+ p8 = key_to_encp8(key, key_nid, str, strtype, k2d, ctx);
+ if (p8 != NULL)
+ ret = PEM_write_bio_PKCS8(out, p8);
+
+ X509_SIG_free(p8);
+
+ return ret;
+}
+
+static int key_to_pki_der_priv_bio(BIO *out, const void *key,
+ int key_nid,
+ ossl_unused const char *pemname,
+ key_to_paramstring_fn *p2s,
+ i2d_of_void *k2d,
+ struct key2any_ctx_st *ctx)
+{
+ int ret = 0;
+ void *str = NULL;
+ int strtype = V_ASN1_UNDEF;
+ PKCS8_PRIV_KEY_INFO *p8info;
+
+ if (ctx->cipher_intent)
+ return key_to_epki_der_priv_bio(out, key, key_nid, pemname,
+ p2s, k2d, ctx);
+
+ if (p2s != NULL && !p2s(key, key_nid, ctx->save_parameters,
+ &str, &strtype))
+ return 0;
+
+ p8info = key_to_p8info(key, key_nid, str, strtype, k2d);
+
+ if (p8info != NULL)
+ ret = i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8info);
+ else
+ free_asn1_data(strtype, str);
+
+ PKCS8_PRIV_KEY_INFO_free(p8info);
+
+ return ret;
+}
+
+static int key_to_pki_pem_priv_bio(BIO *out, const void *key,
+ int key_nid,
+ ossl_unused const char *pemname,
+ key_to_paramstring_fn *p2s,
+ i2d_of_void *k2d,
+ struct key2any_ctx_st *ctx)
+{
+ int ret = 0;
+ void *str = NULL;
+ int strtype = V_ASN1_UNDEF;
+ PKCS8_PRIV_KEY_INFO *p8info;
+
+ if (ctx->cipher_intent)
+ return key_to_epki_pem_priv_bio(out, key, key_nid, pemname,
+ p2s, k2d, ctx);
+
+ if (p2s != NULL && !p2s(key, key_nid, ctx->save_parameters,
+ &str, &strtype))
+ return 0;
+
+ p8info = key_to_p8info(key, key_nid, str, strtype, k2d);
+
+ if (p8info != NULL)
+ ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8info);
+ else
+ free_asn1_data(strtype, str);
+
+ PKCS8_PRIV_KEY_INFO_free(p8info);
+
+ return ret;
+}
+
+static int key_to_spki_der_pub_bio(BIO *out, const void *key,
+ int key_nid,
+ ossl_unused const char *pemname,
+ key_to_paramstring_fn *p2s,
+ i2d_of_void *k2d,
+ struct key2any_ctx_st *ctx)
+{
+ int ret = 0;
+ void *str = NULL;
+ int strtype = V_ASN1_UNDEF;
+ X509_PUBKEY *xpk = NULL;
+
+ if (p2s != NULL && !p2s(key, key_nid, ctx->save_parameters,
+ &str, &strtype))
+ return 0;
+
+ xpk = key_to_pubkey(key, key_nid, str, strtype, k2d);
+
+ if (xpk != NULL)
+ ret = i2d_X509_PUBKEY_bio(out, xpk);
+
+ /* Also frees |str| */
+ X509_PUBKEY_free(xpk);
+ return ret;
+}
+
+static int key_to_spki_pem_pub_bio(BIO *out, const void *key,
+ int key_nid,
+ ossl_unused const char *pemname,
+ key_to_paramstring_fn *p2s,
+ i2d_of_void *k2d,
+ struct key2any_ctx_st *ctx)
+{
+ int ret = 0;
+ void *str = NULL;
+ int strtype = V_ASN1_UNDEF;
+ X509_PUBKEY *xpk = NULL;
+
+ if (p2s != NULL && !p2s(key, key_nid, ctx->save_parameters,
+ &str, &strtype))
+ return 0;
+
+ xpk = key_to_pubkey(key, key_nid, str, strtype, k2d);
+
+ if (xpk != NULL)
+ ret = PEM_write_bio_X509_PUBKEY(out, xpk);
+ else
+ free_asn1_data(strtype, str);
+
+ /* Also frees |str| */
+ X509_PUBKEY_free(xpk);
+ return ret;
+}
+
+/*
+ * key_to_type_specific_* produce encoded output with type specific key data,
+ * no envelopment; the same kind of output as the type specific i2d_ and
+ * PEM_write_ functions, which is often a simple SEQUENCE of INTEGER.
+ *
+ * OpenSSL tries to discourage production of new keys in this form, because
+ * of the ambiguity when trying to recognise them, but can't deny that PKCS#1
+ * et al still are live standards.
+ *
+ * Note that these functions completely ignore p2s, and rather rely entirely
+ * on k2d to do the complete work.
+ */
+static int key_to_type_specific_der_bio(BIO *out, const void *key,
+ int key_nid,
+ ossl_unused const char *pemname,
+ key_to_paramstring_fn *p2s,
+ i2d_of_void *k2d,
+ struct key2any_ctx_st *ctx)
+{
+ unsigned char *der = NULL;
+ int derlen;
+ int ret;
+
+ if ((derlen = k2d(key, &der)) <= 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ ret = BIO_write(out, der, derlen);
+ OPENSSL_free(der);
+ return ret > 0;
+}
+#define key_to_type_specific_der_priv_bio key_to_type_specific_der_bio
+#define key_to_type_specific_der_pub_bio key_to_type_specific_der_bio
+#define key_to_type_specific_der_param_bio key_to_type_specific_der_bio
+
+static int key_to_type_specific_pem_bio_cb(BIO *out, const void *key,
+ int key_nid, const char *pemname,
+ key_to_paramstring_fn *p2s,
+ i2d_of_void *k2d,
+ struct key2any_ctx_st *ctx,
+ pem_password_cb *cb, void *cbarg)
+{
+ return
+ PEM_ASN1_write_bio(k2d, pemname, out, key, ctx->cipher,
+ NULL, 0, cb, cbarg) > 0;
+}
+
+static int key_to_type_specific_pem_priv_bio(BIO *out, const void *key,
+ int key_nid, const char *pemname,
+ key_to_paramstring_fn *p2s,
+ i2d_of_void *k2d,
+ struct key2any_ctx_st *ctx)
+{
+ return key_to_type_specific_pem_bio_cb(out, key, key_nid, pemname,
+ p2s, k2d, ctx,
+ ossl_pw_pem_password, &ctx->pwdata);
+}
+
+static int key_to_type_specific_pem_pub_bio(BIO *out, const void *key,
+ int key_nid, const char *pemname,
+ key_to_paramstring_fn *p2s,
+ i2d_of_void *k2d,
+ struct key2any_ctx_st *ctx)
+{
+ return key_to_type_specific_pem_bio_cb(out, key, key_nid, pemname,
+ p2s, k2d, ctx, NULL, NULL);
+}
+
+#ifndef OPENSSL_NO_KEYPARAMS
+static int key_to_type_specific_pem_param_bio(BIO *out, const void *key,
+ int key_nid, const char *pemname,
+ key_to_paramstring_fn *p2s,
+ i2d_of_void *k2d,
+ struct key2any_ctx_st *ctx)
+{
+ return key_to_type_specific_pem_bio_cb(out, key, key_nid, pemname,
+ p2s, k2d, ctx, NULL, NULL);
+}
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+#ifndef OPENSSL_NO_DH
+static int prepare_dh_params(const void *dh, int nid, int save,
+ void **pstr, int *pstrtype)
+{
+ ASN1_STRING *params = ASN1_STRING_new();
+
+ if (params == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (nid == EVP_PKEY_DHX)
+ params->length = i2d_DHxparams(dh, &params->data);
+ else
+ params->length = i2d_DHparams(dh, &params->data);
+
+ if (params->length <= 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ ASN1_STRING_free(params);
+ return 0;
+ }
+ params->type = V_ASN1_SEQUENCE;
+
+ *pstr = params;
+ *pstrtype = V_ASN1_SEQUENCE;
+ return 1;
+}
+
+static int dh_spki_pub_to_der(const void *dh, unsigned char **pder)
+{
+ const BIGNUM *bn = NULL;
+ ASN1_INTEGER *pub_key = NULL;
+ int ret;
+
+ if ((bn = DH_get0_pub_key(dh)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
+ return 0;
+ }
+ if ((pub_key = BN_to_ASN1_INTEGER(bn, NULL)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_BN_ERROR);
+ return 0;
+ }
+
+ ret = i2d_ASN1_INTEGER(pub_key, pder);
+
+ ASN1_STRING_clear_free(pub_key);
+ return ret;
+}
+
+static int dh_pki_priv_to_der(const void *dh, unsigned char **pder)
+{
+ const BIGNUM *bn = NULL;
+ ASN1_INTEGER *priv_key = NULL;
+ int ret;
+
+ if ((bn = DH_get0_priv_key(dh)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
+ return 0;
+ }
+ if ((priv_key = BN_to_ASN1_INTEGER(bn, NULL)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_BN_ERROR);
+ return 0;
+ }
+
+ ret = i2d_ASN1_INTEGER(priv_key, pder);
+
+ ASN1_STRING_clear_free(priv_key);
+ return ret;
+}
+
+# define dh_epki_priv_to_der dh_pki_priv_to_der
+
+static int dh_type_specific_params_to_der(const void *dh, unsigned char **pder)
+{
+ if (DH_test_flags(dh, DH_FLAG_TYPE_DHX))
+ return i2d_DHxparams(dh, pder);
+ return i2d_DHparams(dh, pder);
+}
+
+/*
+ * DH doesn't have i2d_DHPrivateKey or i2d_DHPublicKey, so we can't make
+ * corresponding functions here.
+ */
+# define dh_type_specific_priv_to_der NULL
+# define dh_type_specific_pub_to_der NULL
+
+static int dh_check_key_type(const void *dh, int expected_type)
+{
+ int type =
+ DH_test_flags(dh, DH_FLAG_TYPE_DHX) ? EVP_PKEY_DHX : EVP_PKEY_DH;
+
+ return type == expected_type;
+}
+
+# define dh_evp_type EVP_PKEY_DH
+# define dhx_evp_type EVP_PKEY_DHX
+# define dh_input_type "DH"
+# define dhx_input_type "DHX"
+# define dh_pem_type "DH"
+# define dhx_pem_type "X9.42 DH"
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+#ifndef OPENSSL_NO_DSA
+static int encode_dsa_params(const void *dsa, int nid,
+ void **pstr, int *pstrtype)
+{
+ ASN1_STRING *params = ASN1_STRING_new();
+
+ if (params == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ params->length = i2d_DSAparams(dsa, &params->data);
+
+ if (params->length <= 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ ASN1_STRING_free(params);
+ return 0;
+ }
+
+ *pstrtype = V_ASN1_SEQUENCE;
+ *pstr = params;
+ return 1;
+}
+
+static int prepare_dsa_params(const void *dsa, int nid, int save,
+ void **pstr, int *pstrtype)
+{
+ const BIGNUM *p = DSA_get0_p(dsa);
+ const BIGNUM *q = DSA_get0_q(dsa);
+ const BIGNUM *g = DSA_get0_g(dsa);
+
+ if (save && p != NULL && q != NULL && g != NULL)
+ return encode_dsa_params(dsa, nid, pstr, pstrtype);
+
+ *pstr = NULL;
+ *pstrtype = V_ASN1_UNDEF;
+ return 1;
+}
+
+static int dsa_spki_pub_to_der(const void *dsa, unsigned char **pder)
+{
+ const BIGNUM *bn = NULL;
+ ASN1_INTEGER *pub_key = NULL;
+ int ret;
+
+ if ((bn = DSA_get0_pub_key(dsa)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
+ return 0;
+ }
+ if ((pub_key = BN_to_ASN1_INTEGER(bn, NULL)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_BN_ERROR);
+ return 0;
+ }
+
+ ret = i2d_ASN1_INTEGER(pub_key, pder);
+
+ ASN1_STRING_clear_free(pub_key);
+ return ret;
+}
+
+static int dsa_pki_priv_to_der(const void *dsa, unsigned char **pder)
+{
+ const BIGNUM *bn = NULL;
+ ASN1_INTEGER *priv_key = NULL;
+ int ret;
+
+ if ((bn = DSA_get0_priv_key(dsa)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
+ return 0;
+ }
+ if ((priv_key = BN_to_ASN1_INTEGER(bn, NULL)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_BN_ERROR);
+ return 0;
+ }
+
+ ret = i2d_ASN1_INTEGER(priv_key, pder);
+
+ ASN1_STRING_clear_free(priv_key);
+ return ret;
+}
+
+# define dsa_epki_priv_to_der dsa_pki_priv_to_der
+
+# define dsa_type_specific_priv_to_der (i2d_of_void *)i2d_DSAPrivateKey
+# define dsa_type_specific_pub_to_der (i2d_of_void *)i2d_DSAPublicKey
+# define dsa_type_specific_params_to_der (i2d_of_void *)i2d_DSAparams
+
+# define dsa_check_key_type NULL
+# define dsa_evp_type EVP_PKEY_DSA
+# define dsa_input_type "DSA"
+# define dsa_pem_type "DSA"
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+#ifndef OPENSSL_NO_EC
+static int prepare_ec_explicit_params(const void *eckey,
+ void **pstr, int *pstrtype)
+{
+ ASN1_STRING *params = ASN1_STRING_new();
+
+ if (params == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ params->length = i2d_ECParameters(eckey, &params->data);
+ if (params->length <= 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ ASN1_STRING_free(params);
+ return 0;
+ }
+
+ *pstrtype = V_ASN1_SEQUENCE;
+ *pstr = params;
+ return 1;
+}
+
+/*
+ * This implements EcpkParameters, where the CHOICE is based on whether there
+ * is a curve name (curve nid) to be found or not. See RFC 3279 for details.
+ */
+static int prepare_ec_params(const void *eckey, int nid, int save,
+ void **pstr, int *pstrtype)
+{
+ int curve_nid;
+ const EC_GROUP *group = EC_KEY_get0_group(eckey);
+ ASN1_OBJECT *params = NULL;
+
+ if (group == NULL)
+ return 0;
+ curve_nid = EC_GROUP_get_curve_name(group);
+ if (curve_nid != NID_undef) {
+ params = OBJ_nid2obj(curve_nid);
+ if (params == NULL)
+ return 0;
+ }
+
+ if (curve_nid != NID_undef
+ && (EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE)) {
+ /* The CHOICE came to namedCurve */
+ if (OBJ_length(params) == 0) {
+ /* Some curves might not have an associated OID */
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_OID);
+ ASN1_OBJECT_free(params);
+ return 0;
+ }
+ *pstr = params;
+ *pstrtype = V_ASN1_OBJECT;
+ return 1;
+ } else {
+ /* The CHOICE came to ecParameters */
+ return prepare_ec_explicit_params(eckey, pstr, pstrtype);
+ }
+}
+
+static int ec_spki_pub_to_der(const void *eckey, unsigned char **pder)
+{
+ if (EC_KEY_get0_public_key(eckey) == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
+ return 0;
+ }
+ return i2o_ECPublicKey(eckey, pder);
+}
+
+static int ec_pki_priv_to_der(const void *veckey, unsigned char **pder)
+{
+ EC_KEY *eckey = (EC_KEY *)veckey;
+ unsigned int old_flags;
+ int ret = 0;
+
+ /*
+ * For PKCS8 the curve name appears in the PKCS8_PRIV_KEY_INFO object
+ * as the pkeyalg->parameter field. (For a named curve this is an OID)
+ * The pkey field is an octet string that holds the encoded
+ * ECPrivateKey SEQUENCE with the optional parameters field omitted.
+ * We omit this by setting the EC_PKEY_NO_PARAMETERS flag.
+ */
+ old_flags = EC_KEY_get_enc_flags(eckey); /* save old flags */
+ EC_KEY_set_enc_flags(eckey, old_flags | EC_PKEY_NO_PARAMETERS);
+ ret = i2d_ECPrivateKey(eckey, pder);
+ EC_KEY_set_enc_flags(eckey, old_flags); /* restore old flags */
+ return ret; /* return the length of the der encoded data */
+}
+
+# define ec_epki_priv_to_der ec_pki_priv_to_der
+
+# define ec_type_specific_params_to_der (i2d_of_void *)i2d_ECParameters
+/* No ec_type_specific_pub_to_der, there simply is no such thing */
+# define ec_type_specific_priv_to_der (i2d_of_void *)i2d_ECPrivateKey
+
+# define ec_check_key_type NULL
+# define ec_evp_type EVP_PKEY_EC
+# define ec_input_type "EC"
+# define ec_pem_type "EC"
+
+# ifndef OPENSSL_NO_SM2
+# define sm2_evp_type EVP_PKEY_SM2
+# define sm2_input_type "SM2"
+# define sm2_pem_type "SM2"
+# endif
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+#ifndef OPENSSL_NO_EC
+# define prepare_ecx_params NULL
+
+static int ecx_spki_pub_to_der(const void *vecxkey, unsigned char **pder)
+{
+ const ECX_KEY *ecxkey = vecxkey;
+ unsigned char *keyblob;
+
+ if (ecxkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ keyblob = OPENSSL_memdup(ecxkey->pubkey, ecxkey->keylen);
+ if (keyblob == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ *pder = keyblob;
+ return ecxkey->keylen;
+}
+
+static int ecx_pki_priv_to_der(const void *vecxkey, unsigned char **pder)
+{
+ const ECX_KEY *ecxkey = vecxkey;
+ ASN1_OCTET_STRING oct;
+ int keybloblen;
+
+ if (ecxkey == NULL || ecxkey->privkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ oct.data = ecxkey->privkey;
+ oct.length = ecxkey->keylen;
+ oct.flags = 0;
+
+ keybloblen = i2d_ASN1_OCTET_STRING(&oct, pder);
+ if (keybloblen < 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ return keybloblen;
+}
+
+# define ecx_epki_priv_to_der ecx_pki_priv_to_der
+
+/*
+ * ED25519, ED448, X25519 and X448 only has PKCS#8 / SubjectPublicKeyInfo
+ * representation, so we don't define ecx_type_specific_[priv,pub,params]_to_der.
+ */
+
+# define ecx_check_key_type NULL
+
+# define ed25519_evp_type EVP_PKEY_ED25519
+# define ed448_evp_type EVP_PKEY_ED448
+# define x25519_evp_type EVP_PKEY_X25519
+# define x448_evp_type EVP_PKEY_X448
+# define ed25519_input_type "ED25519"
+# define ed448_input_type "ED448"
+# define x25519_input_type "X25519"
+# define x448_input_type "X448"
+# define ed25519_pem_type "ED25519"
+# define ed448_pem_type "ED448"
+# define x25519_pem_type "X25519"
+# define x448_pem_type "X448"
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * Helper functions to prepare RSA-PSS params for encoding. We would
+ * have simply written the whole AlgorithmIdentifier, but existing libcrypto
+ * functionality doesn't allow that.
+ */
+
+static int prepare_rsa_params(const void *rsa, int nid, int save,
+ void **pstr, int *pstrtype)
+{
+ const RSA_PSS_PARAMS_30 *pss = ossl_rsa_get0_pss_params_30((RSA *)rsa);
+
+ *pstr = NULL;
+
+ switch (RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK)) {
+ case RSA_FLAG_TYPE_RSA:
+ /* If plain RSA, the parameters shall be NULL */
+ *pstrtype = V_ASN1_NULL;
+ return 1;
+ case RSA_FLAG_TYPE_RSASSAPSS:
+ if (ossl_rsa_pss_params_30_is_unrestricted(pss)) {
+ *pstrtype = V_ASN1_UNDEF;
+ return 1;
+ } else {
+ ASN1_STRING *astr = NULL;
+ WPACKET pkt;
+ unsigned char *str = NULL;
+ size_t str_sz = 0;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ switch (i) {
+ case 0:
+ if (!WPACKET_init_null_der(&pkt))
+ goto err;
+ break;
+ case 1:
+ if ((str = OPENSSL_malloc(str_sz)) == NULL
+ || !WPACKET_init_der(&pkt, str, str_sz)) {
+ goto err;
+ }
+ break;
+ }
+ if (!ossl_DER_w_RSASSA_PSS_params(&pkt, -1, pss)
+ || !WPACKET_finish(&pkt)
+ || !WPACKET_get_total_written(&pkt, &str_sz))
+ goto err;
+ WPACKET_cleanup(&pkt);
+
+ /*
+ * If no PSS parameters are going to be written, there's no
+ * point going for another iteration.
+ * This saves us from getting |str| allocated just to have it
+ * immediately de-allocated.
+ */
+ if (str_sz == 0)
+ break;
+ }
+
+ if ((astr = ASN1_STRING_new()) == NULL)
+ goto err;
+ *pstrtype = V_ASN1_SEQUENCE;
+ ASN1_STRING_set0(astr, str, (int)str_sz);
+ *pstr = astr;
+
+ return 1;
+ err:
+ OPENSSL_free(str);
+ return 0;
+ }
+ }
+
+ /* Currently unsupported RSA key type */
+ return 0;
+}
+
+/*
+ * RSA is extremely simple, as PKCS#1 is used for the PKCS#8 |privateKey|
+ * field as well as the SubjectPublicKeyInfo |subjectPublicKey| field.
+ */
+#define rsa_pki_priv_to_der rsa_type_specific_priv_to_der
+#define rsa_epki_priv_to_der rsa_type_specific_priv_to_der
+#define rsa_spki_pub_to_der rsa_type_specific_pub_to_der
+#define rsa_type_specific_priv_to_der (i2d_of_void *)i2d_RSAPrivateKey
+#define rsa_type_specific_pub_to_der (i2d_of_void *)i2d_RSAPublicKey
+#define rsa_type_specific_params_to_der NULL
+
+static int rsa_check_key_type(const void *rsa, int expected_type)
+{
+ switch (RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK)) {
+ case RSA_FLAG_TYPE_RSA:
+ return expected_type == EVP_PKEY_RSA;
+ case RSA_FLAG_TYPE_RSASSAPSS:
+ return expected_type == EVP_PKEY_RSA_PSS;
+ }
+
+ /* Currently unsupported RSA key type */
+ return EVP_PKEY_NONE;
+}
+
+#define rsa_evp_type EVP_PKEY_RSA
+#define rsapss_evp_type EVP_PKEY_RSA_PSS
+#define rsa_input_type "RSA"
+#define rsapss_input_type "RSA-PSS"
+#define rsa_pem_type "RSA"
+#define rsapss_pem_type "RSA-PSS"
+
+/* ---------------------------------------------------------------------- */
+
+static OSSL_FUNC_decoder_newctx_fn key2any_newctx;
+static OSSL_FUNC_decoder_freectx_fn key2any_freectx;
+
+static void *key2any_newctx(void *provctx)
+{
+ struct key2any_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx != NULL) {
+ ctx->provctx = provctx;
+ ctx->save_parameters = 1;
+ }
+
+ return ctx;
+}
+
+static void key2any_freectx(void *vctx)
+{
+ struct key2any_ctx_st *ctx = vctx;
+
+ ossl_pw_clear_passphrase_data(&ctx->pwdata);
+ EVP_CIPHER_free(ctx->cipher);
+ OPENSSL_free(ctx);
+}
+
+static const OSSL_PARAM *key2any_settable_ctx_params(ossl_unused void *provctx)
+{
+ static const OSSL_PARAM settables[] = {
+ OSSL_PARAM_utf8_string(OSSL_ENCODER_PARAM_CIPHER, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_ENCODER_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_END,
+ };
+
+ return settables;
+}
+
+static int key2any_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ struct key2any_ctx_st *ctx = vctx;
+ OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(ctx->provctx);
+ const OSSL_PARAM *cipherp =
+ OSSL_PARAM_locate_const(params, OSSL_ENCODER_PARAM_CIPHER);
+ const OSSL_PARAM *propsp =
+ OSSL_PARAM_locate_const(params, OSSL_ENCODER_PARAM_PROPERTIES);
+ const OSSL_PARAM *save_paramsp =
+ OSSL_PARAM_locate_const(params, OSSL_ENCODER_PARAM_SAVE_PARAMETERS);
+
+ if (cipherp != NULL) {
+ const char *ciphername = NULL;
+ const char *props = NULL;
+
+ if (!OSSL_PARAM_get_utf8_string_ptr(cipherp, &ciphername))
+ return 0;
+ if (propsp != NULL && !OSSL_PARAM_get_utf8_string_ptr(propsp, &props))
+ return 0;
+
+ EVP_CIPHER_free(ctx->cipher);
+ ctx->cipher = NULL;
+ ctx->cipher_intent = ciphername != NULL;
+ if (ciphername != NULL
+ && ((ctx->cipher =
+ EVP_CIPHER_fetch(libctx, ciphername, props)) == NULL))
+ return 0;
+ }
+
+ if (save_paramsp != NULL) {
+ if (!OSSL_PARAM_get_int(save_paramsp, &ctx->save_parameters))
+ return 0;
+ }
+ return 1;
+}
+
+static int key2any_check_selection(int selection, int selection_mask)
+{
+ /*
+ * The selections are kinda sorta "levels", i.e. each selection given
+ * here is assumed to include those following.
+ */
+ int checks[] = {
+ OSSL_KEYMGMT_SELECT_PRIVATE_KEY,
+ OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
+ OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
+ };
+ size_t i;
+
+ /* The decoder implementations made here support guessing */
+ if (selection == 0)
+ return 1;
+
+ for (i = 0; i < OSSL_NELEM(checks); i++) {
+ int check1 = (selection & checks[i]) != 0;
+ int check2 = (selection_mask & checks[i]) != 0;
+
+ /*
+ * If the caller asked for the currently checked bit(s), return
+ * whether the decoder description says it's supported.
+ */
+ if (check1)
+ return check2;
+ }
+
+ /* This should be dead code, but just to be safe... */
+ return 0;
+}
+
+static int key2any_encode(struct key2any_ctx_st *ctx, OSSL_CORE_BIO *cout,
+ const void *key, int type, const char *pemname,
+ check_key_type_fn *checker,
+ key_to_der_fn *writer,
+ OSSL_PASSPHRASE_CALLBACK *pwcb, void *pwcbarg,
+ key_to_paramstring_fn *key2paramstring,
+ i2d_of_void *key2der)
+{
+ int ret = 0;
+
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
+ } else if (writer != NULL
+ && (checker == NULL || checker(key, type))) {
+ BIO *out = ossl_bio_new_from_core_bio(ctx->provctx, cout);
+
+ if (out != NULL
+ && (pwcb == NULL
+ || ossl_pw_set_ossl_passphrase_cb(&ctx->pwdata, pwcb, pwcbarg)))
+ ret =
+ writer(out, key, type, pemname, key2paramstring, key2der, ctx);
+
+ BIO_free(out);
+ } else {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
+ }
+ return ret;
+}
+
+#define DO_PRIVATE_KEY_selection_mask OSSL_KEYMGMT_SELECT_PRIVATE_KEY
+#define DO_PRIVATE_KEY(impl, type, kind, output) \
+ if ((selection & DO_PRIVATE_KEY_selection_mask) != 0) \
+ return key2any_encode(ctx, cout, key, impl##_evp_type, \
+ impl##_pem_type " PRIVATE KEY", \
+ type##_check_key_type, \
+ key_to_##kind##_##output##_priv_bio, \
+ cb, cbarg, prepare_##type##_params, \
+ type##_##kind##_priv_to_der);
+
+#define DO_PUBLIC_KEY_selection_mask OSSL_KEYMGMT_SELECT_PUBLIC_KEY
+#define DO_PUBLIC_KEY(impl, type, kind, output) \
+ if ((selection & DO_PUBLIC_KEY_selection_mask) != 0) \
+ return key2any_encode(ctx, cout, key, impl##_evp_type, \
+ impl##_pem_type " PUBLIC KEY", \
+ type##_check_key_type, \
+ key_to_##kind##_##output##_pub_bio, \
+ cb, cbarg, prepare_##type##_params, \
+ type##_##kind##_pub_to_der);
+
+#define DO_PARAMETERS_selection_mask OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
+#define DO_PARAMETERS(impl, type, kind, output) \
+ if ((selection & DO_PARAMETERS_selection_mask) != 0) \
+ return key2any_encode(ctx, cout, key, impl##_evp_type, \
+ impl##_pem_type " PARAMETERS", \
+ type##_check_key_type, \
+ key_to_##kind##_##output##_param_bio, \
+ NULL, NULL, NULL, \
+ type##_##kind##_params_to_der);
+
+/*-
+ * Implement the kinds of output structure that can be produced. They are
+ * referred to by name, and for each name, the following macros are defined
+ * (braces not included):
+ *
+ * DO_{kind}_selection_mask
+ *
+ * A mask of selection bits that must not be zero. This is used as a
+ * selection criterion for each implementation.
+ * This mask must never be zero.
+ *
+ * DO_{kind}
+ *
+ * The performing macro. It must use the DO_ macros defined above,
+ * always in this order:
+ *
+ * - DO_PRIVATE_KEY
+ * - DO_PUBLIC_KEY
+ * - DO_PARAMETERS
+ *
+ * Any of those may be omitted, but the relative order must still be
+ * the same.
+ */
+
+/*
+ * PKCS#8 defines two structures for private keys only:
+ * - PrivateKeyInfo (raw unencrypted form)
+ * - EncryptedPrivateKeyInfo (encrypted wrapping)
+ *
+ * To allow a certain amount of flexibility, we allow the routines
+ * for PrivateKeyInfo to also produce EncryptedPrivateKeyInfo if a
+ * passphrase callback has been passed to them.
+ */
+#define DO_PrivateKeyInfo_selection_mask DO_PRIVATE_KEY_selection_mask
+#define DO_PrivateKeyInfo(impl, type, output) \
+ DO_PRIVATE_KEY(impl, type, pki, output)
+
+#define DO_EncryptedPrivateKeyInfo_selection_mask DO_PRIVATE_KEY_selection_mask
+#define DO_EncryptedPrivateKeyInfo(impl, type, output) \
+ DO_PRIVATE_KEY(impl, type, epki, output)
+
+/* SubjectPublicKeyInfo is a structure for public keys only */
+#define DO_SubjectPublicKeyInfo_selection_mask DO_PUBLIC_KEY_selection_mask
+#define DO_SubjectPublicKeyInfo(impl, type, output) \
+ DO_PUBLIC_KEY(impl, type, spki, output)
+
+/*
+ * "type-specific" is a uniform name for key type specific output for private
+ * and public keys as well as key parameters. This is used internally in
+ * libcrypto so it doesn't have to have special knowledge about select key
+ * types, but also when no better name has been found. If there are more
+ * expressive DO_ names above, those are preferred.
+ *
+ * Three forms exist:
+ *
+ * - type_specific_keypair Only supports private and public key
+ * - type_specific_params Only supports parameters
+ * - type_specific Supports all parts of an EVP_PKEY
+ * - type_specific_no_pub Supports all parts of an EVP_PKEY
+ * except public key
+ */
+#define DO_type_specific_params_selection_mask DO_PARAMETERS_selection_mask
+#define DO_type_specific_params(impl, type, output) \
+ DO_PARAMETERS(impl, type, type_specific, output)
+#define DO_type_specific_keypair_selection_mask \
+ ( DO_PRIVATE_KEY_selection_mask | DO_PUBLIC_KEY_selection_mask )
+#define DO_type_specific_keypair(impl, type, output) \
+ DO_PRIVATE_KEY(impl, type, type_specific, output) \
+ DO_PUBLIC_KEY(impl, type, type_specific, output)
+#define DO_type_specific_selection_mask \
+ ( DO_type_specific_keypair_selection_mask \
+ | DO_type_specific_params_selection_mask )
+#define DO_type_specific(impl, type, output) \
+ DO_type_specific_keypair(impl, type, output) \
+ DO_type_specific_params(impl, type, output)
+#define DO_type_specific_no_pub_selection_mask \
+ ( DO_PRIVATE_KEY_selection_mask | DO_PARAMETERS_selection_mask)
+#define DO_type_specific_no_pub(impl, type, output) \
+ DO_PRIVATE_KEY(impl, type, type_specific, output) \
+ DO_type_specific_params(impl, type, output)
+
+/*
+ * Type specific aliases for the cases where we need to refer to them by
+ * type name.
+ * This only covers key types that are represented with i2d_{TYPE}PrivateKey,
+ * i2d_{TYPE}PublicKey and i2d_{TYPE}params / i2d_{TYPE}Parameters.
+ */
+#define DO_RSA_selection_mask DO_type_specific_keypair_selection_mask
+#define DO_RSA(impl, type, output) DO_type_specific_keypair(impl, type, output)
+
+#define DO_DH_selection_mask DO_type_specific_params_selection_mask
+#define DO_DH(impl, type, output) DO_type_specific_params(impl, type, output)
+
+#define DO_DHX_selection_mask DO_type_specific_params_selection_mask
+#define DO_DHX(impl, type, output) DO_type_specific_params(impl, type, output)
+
+#define DO_DSA_selection_mask DO_type_specific_selection_mask
+#define DO_DSA(impl, type, output) DO_type_specific(impl, type, output)
+
+#define DO_EC_selection_mask DO_type_specific_no_pub_selection_mask
+#define DO_EC(impl, type, output) DO_type_specific_no_pub(impl, type, output)
+
+#define DO_SM2_selection_mask DO_type_specific_no_pub_selection_mask
+#define DO_SM2(impl, type, output) DO_type_specific_no_pub(impl, type, output)
+
+/* PKCS#1 defines a structure for RSA private and public keys */
+#define DO_PKCS1_selection_mask DO_RSA_selection_mask
+#define DO_PKCS1(impl, type, output) DO_RSA(impl, type, output)
+
+/* PKCS#3 defines a structure for DH parameters */
+#define DO_PKCS3_selection_mask DO_DH_selection_mask
+#define DO_PKCS3(impl, type, output) DO_DH(impl, type, output)
+/* X9.42 defines a structure for DHx parameters */
+#define DO_X9_42_selection_mask DO_DHX_selection_mask
+#define DO_X9_42(impl, type, output) DO_DHX(impl, type, output)
+
+/* X9.62 defines a structure for EC keys and parameters */
+#define DO_X9_62_selection_mask DO_EC_selection_mask
+#define DO_X9_62(impl, type, output) DO_EC(impl, type, output)
+
+/*
+ * MAKE_ENCODER is the single driver for creating OSSL_DISPATCH tables.
+ * It takes the following arguments:
+ *
+ * impl This is the key type name that's being implemented.
+ * type This is the type name for the set of functions that implement
+ * the key type. For example, ed25519, ed448, x25519 and x448
+ * are all implemented with the exact same set of functions.
+ * evp_type The corresponding EVP_PKEY_xxx type macro for each key.
+ * Necessary because we currently use EVP_PKEY with legacy
+ * native keys internally. This will need to be refactored
+ * when that legacy support goes away.
+ * kind What kind of support to implement. These translate into
+ * the DO_##kind macros above.
+ * output The output type to implement. may be der or pem.
+ *
+ * The resulting OSSL_DISPATCH array gets the following name (expressed in
+ * C preprocessor terms) from those arguments:
+ *
+ * ossl_##impl##_to_##kind##_##output##_encoder_functions
+ */
+#define MAKE_ENCODER(impl, type, evp_type, kind, output) \
+ static OSSL_FUNC_encoder_import_object_fn \
+ impl##_to_##kind##_##output##_import_object; \
+ static OSSL_FUNC_encoder_free_object_fn \
+ impl##_to_##kind##_##output##_free_object; \
+ static OSSL_FUNC_encoder_encode_fn \
+ impl##_to_##kind##_##output##_encode; \
+ \
+ static void * \
+ impl##_to_##kind##_##output##_import_object(void *vctx, int selection, \
+ const OSSL_PARAM params[]) \
+ { \
+ struct key2any_ctx_st *ctx = vctx; \
+ \
+ return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \
+ ctx->provctx, selection, params); \
+ } \
+ static void impl##_to_##kind##_##output##_free_object(void *key) \
+ { \
+ ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \
+ } \
+ static int impl##_to_##kind##_##output##_does_selection(void *ctx, \
+ int selection) \
+ { \
+ return key2any_check_selection(selection, \
+ DO_##kind##_selection_mask); \
+ } \
+ static int \
+ impl##_to_##kind##_##output##_encode(void *ctx, OSSL_CORE_BIO *cout, \
+ const void *key, \
+ const OSSL_PARAM key_abstract[], \
+ int selection, \
+ OSSL_PASSPHRASE_CALLBACK *cb, \
+ void *cbarg) \
+ { \
+ /* We don't deal with abstract objects */ \
+ if (key_abstract != NULL) { \
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \
+ return 0; \
+ } \
+ DO_##kind(impl, type, output) \
+ \
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \
+ return 0; \
+ } \
+ const OSSL_DISPATCH \
+ ossl_##impl##_to_##kind##_##output##_encoder_functions[] = { \
+ { OSSL_FUNC_ENCODER_NEWCTX, \
+ (void (*)(void))key2any_newctx }, \
+ { OSSL_FUNC_ENCODER_FREECTX, \
+ (void (*)(void))key2any_freectx }, \
+ { OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))key2any_settable_ctx_params }, \
+ { OSSL_FUNC_ENCODER_SET_CTX_PARAMS, \
+ (void (*)(void))key2any_set_ctx_params }, \
+ { OSSL_FUNC_ENCODER_DOES_SELECTION, \
+ (void (*)(void))impl##_to_##kind##_##output##_does_selection }, \
+ { OSSL_FUNC_ENCODER_IMPORT_OBJECT, \
+ (void (*)(void))impl##_to_##kind##_##output##_import_object }, \
+ { OSSL_FUNC_ENCODER_FREE_OBJECT, \
+ (void (*)(void))impl##_to_##kind##_##output##_free_object }, \
+ { OSSL_FUNC_ENCODER_ENCODE, \
+ (void (*)(void))impl##_to_##kind##_##output##_encode }, \
+ { 0, NULL } \
+ }
+
+/*
+ * Replacements for i2d_{TYPE}PrivateKey, i2d_{TYPE}PublicKey,
+ * i2d_{TYPE}params, as they exist.
+ */
+MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, type_specific_keypair, der);
+#ifndef OPENSSL_NO_DH
+MAKE_ENCODER(dh, dh, EVP_PKEY_DH, type_specific_params, der);
+MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, type_specific_params, der);
+#endif
+#ifndef OPENSSL_NO_DSA
+MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, type_specific, der);
+#endif
+#ifndef OPENSSL_NO_EC
+MAKE_ENCODER(ec, ec, EVP_PKEY_EC, type_specific_no_pub, der);
+# ifndef OPENSSL_NO_SM2
+MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, type_specific_no_pub, der);
+# endif
+#endif
+
+/*
+ * Replacements for PEM_write_bio_{TYPE}PrivateKey,
+ * PEM_write_bio_{TYPE}PublicKey, PEM_write_bio_{TYPE}params, as they exist.
+ */
+MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, type_specific_keypair, pem);
+#ifndef OPENSSL_NO_DH
+MAKE_ENCODER(dh, dh, EVP_PKEY_DH, type_specific_params, pem);
+MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, type_specific_params, pem);
+#endif
+#ifndef OPENSSL_NO_DSA
+MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, type_specific, pem);
+#endif
+#ifndef OPENSSL_NO_EC
+MAKE_ENCODER(ec, ec, EVP_PKEY_EC, type_specific_no_pub, pem);
+# ifndef OPENSSL_NO_SM2
+MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, type_specific_no_pub, pem);
+# endif
+#endif
+
+/*
+ * PKCS#8 and SubjectPublicKeyInfo support. This may duplicate some of the
+ * implementations specified above, but are more specific.
+ * The SubjectPublicKeyInfo implementations also replace the
+ * PEM_write_bio_{TYPE}_PUBKEY functions.
+ * For PEM, these are expected to be used by PEM_write_bio_PrivateKey(),
+ * PEM_write_bio_PUBKEY() and PEM_write_bio_Parameters().
+ */
+MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, PrivateKeyInfo, der);
+MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, PrivateKeyInfo, pem);
+MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, SubjectPublicKeyInfo, pem);
+MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, PrivateKeyInfo, der);
+MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, PrivateKeyInfo, pem);
+MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, SubjectPublicKeyInfo, pem);
+#ifndef OPENSSL_NO_DH
+MAKE_ENCODER(dh, dh, EVP_PKEY_DH, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(dh, dh, EVP_PKEY_DH, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(dh, dh, EVP_PKEY_DH, PrivateKeyInfo, der);
+MAKE_ENCODER(dh, dh, EVP_PKEY_DH, PrivateKeyInfo, pem);
+MAKE_ENCODER(dh, dh, EVP_PKEY_DH, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(dh, dh, EVP_PKEY_DH, SubjectPublicKeyInfo, pem);
+MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, PrivateKeyInfo, der);
+MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, PrivateKeyInfo, pem);
+MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, SubjectPublicKeyInfo, pem);
+#endif
+#ifndef OPENSSL_NO_DSA
+MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, PrivateKeyInfo, der);
+MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, PrivateKeyInfo, pem);
+MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, SubjectPublicKeyInfo, pem);
+#endif
+#ifndef OPENSSL_NO_EC
+MAKE_ENCODER(ec, ec, EVP_PKEY_EC, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(ec, ec, EVP_PKEY_EC, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(ec, ec, EVP_PKEY_EC, PrivateKeyInfo, der);
+MAKE_ENCODER(ec, ec, EVP_PKEY_EC, PrivateKeyInfo, pem);
+MAKE_ENCODER(ec, ec, EVP_PKEY_EC, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(ec, ec, EVP_PKEY_EC, SubjectPublicKeyInfo, pem);
+# ifndef OPENSSL_NO_SM2
+MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, PrivateKeyInfo, der);
+MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, PrivateKeyInfo, pem);
+MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, SubjectPublicKeyInfo, pem);
+# endif
+MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, PrivateKeyInfo, der);
+MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, PrivateKeyInfo, pem);
+MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, SubjectPublicKeyInfo, pem);
+MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, PrivateKeyInfo, der);
+MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, PrivateKeyInfo, pem);
+MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, SubjectPublicKeyInfo, pem);
+MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, PrivateKeyInfo, der);
+MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, PrivateKeyInfo, pem);
+MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, SubjectPublicKeyInfo, pem);
+MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, PrivateKeyInfo, der);
+MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, PrivateKeyInfo, pem);
+MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, SubjectPublicKeyInfo, pem);
+#endif
+
+/*
+ * Support for key type specific output formats. Not all key types have
+ * this, we only aim to duplicate what is available in 1.1.1 as
+ * i2d_TYPEPrivateKey(), i2d_TYPEPublicKey() and i2d_TYPEparams().
+ * For example, there are no publicly available i2d_ function for
+ * ED25519, ED448, X25519 or X448, and they therefore only have PKCS#8
+ * and SubjectPublicKeyInfo implementations as implemented above.
+ */
+MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, RSA, der);
+MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, RSA, pem);
+#ifndef OPENSSL_NO_DH
+MAKE_ENCODER(dh, dh, EVP_PKEY_DH, DH, der);
+MAKE_ENCODER(dh, dh, EVP_PKEY_DH, DH, pem);
+MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, DHX, der);
+MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, DHX, pem);
+#endif
+#ifndef OPENSSL_NO_DSA
+MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, DSA, der);
+MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, DSA, pem);
+#endif
+#ifndef OPENSSL_NO_EC
+MAKE_ENCODER(ec, ec, EVP_PKEY_EC, EC, der);
+MAKE_ENCODER(ec, ec, EVP_PKEY_EC, EC, pem);
+# ifndef OPENSSL_NO_SM2
+MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, SM2, der);
+MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, SM2, pem);
+# endif
+#endif
+
+/* Convenience structure names */
+MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, PKCS1, der);
+MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, PKCS1, pem);
+MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, PKCS1, der);
+MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, PKCS1, pem);
+#ifndef OPENSSL_NO_DH
+MAKE_ENCODER(dh, dh, EVP_PKEY_DH, PKCS3, der); /* parameters only */
+MAKE_ENCODER(dh, dh, EVP_PKEY_DH, PKCS3, pem); /* parameters only */
+MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, X9_42, der); /* parameters only */
+MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, X9_42, pem); /* parameters only */
+#endif
+#ifndef OPENSSL_NO_EC
+MAKE_ENCODER(ec, ec, EVP_PKEY_EC, X9_62, der);
+MAKE_ENCODER(ec, ec, EVP_PKEY_EC, X9_62, pem);
+#endif
diff --git a/providers/implementations/encode_decode/encode_key2blob.c b/providers/implementations/encode_decode/encode_key2blob.c
new file mode 100644
index 000000000000..550bceb09f58
--- /dev/null
+++ b/providers/implementations/encode_decode/encode_key2blob.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Low level APIs are deprecated for public use, but still ok for internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/ec.h>
+#include "internal/passphrase.h"
+#include "internal/nelem.h"
+#include "prov/implementations.h"
+#include "prov/bio.h"
+#include "prov/provider_ctx.h"
+#include "endecoder_local.h"
+
+static int write_blob(void *provctx, OSSL_CORE_BIO *cout,
+ void *data, int len)
+{
+ BIO *out = ossl_bio_new_from_core_bio(provctx, cout);
+ int ret;
+
+ if (out == NULL)
+ return 0;
+ ret = BIO_write(out, data, len);
+
+ BIO_free(out);
+ return ret;
+}
+
+static OSSL_FUNC_encoder_newctx_fn key2blob_newctx;
+static OSSL_FUNC_encoder_freectx_fn key2blob_freectx;
+
+static void *key2blob_newctx(void *provctx)
+{
+ return provctx;
+}
+
+static void key2blob_freectx(void *vctx)
+{
+}
+
+static int key2blob_check_selection(int selection, int selection_mask)
+{
+ /*
+ * The selections are kinda sorta "levels", i.e. each selection given
+ * here is assumed to include those following.
+ */
+ int checks[] = {
+ OSSL_KEYMGMT_SELECT_PRIVATE_KEY,
+ OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
+ OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
+ };
+ size_t i;
+
+ /* The decoder implementations made here support guessing */
+ if (selection == 0)
+ return 1;
+
+ for (i = 0; i < OSSL_NELEM(checks); i++) {
+ int check1 = (selection & checks[i]) != 0;
+ int check2 = (selection_mask & checks[i]) != 0;
+
+ /*
+ * If the caller asked for the currently checked bit(s), return
+ * whether the decoder description says it's supported.
+ */
+ if (check1)
+ return check2;
+ }
+
+ /* This should be dead code, but just to be safe... */
+ return 0;
+}
+
+static int key2blob_encode(void *vctx, const void *key, int selection,
+ OSSL_CORE_BIO *cout)
+{
+ int pubkey_len = 0, ok = 0;
+ unsigned char *pubkey = NULL;
+
+ pubkey_len = i2o_ECPublicKey(key, &pubkey);
+ if (pubkey_len > 0 && pubkey != NULL)
+ ok = write_blob(vctx, cout, pubkey, pubkey_len);
+ OPENSSL_free(pubkey);
+ return ok;
+}
+
+/*
+ * MAKE_BLOB_ENCODER() Makes an OSSL_DISPATCH table for a particular key->blob
+ * encoder
+ *
+ * impl: The keytype to encode
+ * type: The C structure type holding the key data
+ * selection_name: The acceptable selections. This translates into
+ * the macro EVP_PKEY_##selection_name.
+ *
+ * The selection is understood as a "level" rather than an exact set of
+ * requests from the caller. The encoder has to decide what contents fit
+ * the encoded format. For example, the EC public key blob will only contain
+ * the encoded public key itself, no matter if the selection bits include
+ * OSSL_KEYMGMT_SELECT_PARAMETERS or not. However, if the selection includes
+ * OSSL_KEYMGMT_SELECT_PRIVATE_KEY, the same encoder will simply refuse to
+ * cooperate, because it cannot output the private key.
+ *
+ * EVP_PKEY_##selection_name are convenience macros that combine "typical"
+ * OSSL_KEYMGMT_SELECT_ macros for a certain type of EVP_PKEY content.
+ */
+#define MAKE_BLOB_ENCODER(impl, type, selection_name) \
+ static OSSL_FUNC_encoder_import_object_fn \
+ impl##2blob_import_object; \
+ static OSSL_FUNC_encoder_free_object_fn impl##2blob_free_object; \
+ static OSSL_FUNC_encoder_does_selection_fn \
+ impl##2blob_does_selection; \
+ static OSSL_FUNC_encoder_encode_fn impl##2blob_encode; \
+ \
+ static void *impl##2blob_import_object(void *ctx, int selection, \
+ const OSSL_PARAM params[]) \
+ { \
+ return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \
+ ctx, selection, params); \
+ } \
+ static void impl##2blob_free_object(void *key) \
+ { \
+ ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \
+ } \
+ static int impl##2blob_does_selection(void *ctx, int selection) \
+ { \
+ return key2blob_check_selection(selection, \
+ EVP_PKEY_##selection_name); \
+ } \
+ static int impl##2blob_encode(void *vctx, OSSL_CORE_BIO *cout, \
+ const void *key, \
+ const OSSL_PARAM key_abstract[], \
+ int selection, \
+ OSSL_PASSPHRASE_CALLBACK *cb, \
+ void *cbarg) \
+ { \
+ /* We don't deal with abstract objects */ \
+ if (key_abstract != NULL) { \
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \
+ return 0; \
+ } \
+ return key2blob_encode(vctx, key, selection, cout); \
+ } \
+ const OSSL_DISPATCH ossl_##impl##_to_blob_encoder_functions[] = { \
+ { OSSL_FUNC_ENCODER_NEWCTX, \
+ (void (*)(void))key2blob_newctx }, \
+ { OSSL_FUNC_ENCODER_FREECTX, \
+ (void (*)(void))key2blob_freectx }, \
+ { OSSL_FUNC_ENCODER_DOES_SELECTION, \
+ (void (*)(void))impl##2blob_does_selection }, \
+ { OSSL_FUNC_ENCODER_IMPORT_OBJECT, \
+ (void (*)(void))impl##2blob_import_object }, \
+ { OSSL_FUNC_ENCODER_FREE_OBJECT, \
+ (void (*)(void))impl##2blob_free_object }, \
+ { OSSL_FUNC_ENCODER_ENCODE, \
+ (void (*)(void))impl##2blob_encode }, \
+ { 0, NULL } \
+ }
+
+#ifndef OPENSSL_NO_EC
+MAKE_BLOB_ENCODER(ec, ec, PUBLIC_KEY);
+# ifndef OPENSSL_NO_SM2
+MAKE_BLOB_ENCODER(sm2, ec, PUBLIC_KEY);
+# endif
+#endif
diff --git a/providers/implementations/encode_decode/encode_key2ms.c b/providers/implementations/encode_decode/encode_key2ms.c
new file mode 100644
index 000000000000..fe8c2dce4316
--- /dev/null
+++ b/providers/implementations/encode_decode/encode_key2ms.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Low level APIs are deprecated for public use, but still ok for internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h>
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#include <openssl/pem.h> /* Functions for writing MSBLOB and PVK */
+#include <openssl/dsa.h>
+#include "internal/passphrase.h"
+#include "crypto/rsa.h"
+#include "prov/implementations.h"
+#include "prov/bio.h"
+#include "prov/provider_ctx.h"
+#include "endecoder_local.h"
+
+struct key2ms_ctx_st {
+ PROV_CTX *provctx;
+
+ int pvk_encr_level;
+
+ struct ossl_passphrase_data_st pwdata;
+};
+
+static int write_msblob(struct key2ms_ctx_st *ctx, OSSL_CORE_BIO *cout,
+ EVP_PKEY *pkey, int ispub)
+{
+ BIO *out = ossl_bio_new_from_core_bio(ctx->provctx, cout);
+ int ret;
+
+ if (out == NULL)
+ return 0;
+ ret = ispub ? i2b_PublicKey_bio(out, pkey) : i2b_PrivateKey_bio(out, pkey);
+
+ BIO_free(out);
+ return ret;
+}
+
+static int write_pvk(struct key2ms_ctx_st *ctx, OSSL_CORE_BIO *cout,
+ EVP_PKEY *pkey)
+{
+ BIO *out = NULL;
+ int ret;
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
+
+ out = ossl_bio_new_from_core_bio(ctx->provctx, cout);
+ if (out == NULL)
+ return 0;
+ ret = i2b_PVK_bio_ex(out, pkey, ctx->pvk_encr_level,
+ ossl_pw_pvk_password, &ctx->pwdata, libctx, NULL);
+ BIO_free(out);
+ return ret;
+}
+
+static OSSL_FUNC_encoder_freectx_fn key2ms_freectx;
+static OSSL_FUNC_encoder_does_selection_fn key2ms_does_selection;
+
+static struct key2ms_ctx_st *key2ms_newctx(void *provctx)
+{
+ struct key2ms_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx != NULL) {
+ ctx->provctx = provctx;
+ /* This is the strongest encryption level */
+ ctx->pvk_encr_level = 2;
+ }
+ return ctx;
+}
+
+static void key2ms_freectx(void *vctx)
+{
+ struct key2ms_ctx_st *ctx = vctx;
+
+ ossl_pw_clear_passphrase_data(&ctx->pwdata);
+ OPENSSL_free(ctx);
+}
+
+static const OSSL_PARAM *key2pvk_settable_ctx_params(ossl_unused void *provctx)
+{
+ static const OSSL_PARAM settables[] = {
+ OSSL_PARAM_int(OSSL_ENCODER_PARAM_ENCRYPT_LEVEL, NULL),
+ OSSL_PARAM_END,
+ };
+
+ return settables;
+}
+
+static int key2pvk_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ struct key2ms_ctx_st *ctx = vctx;
+ const OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_ENCODER_PARAM_ENCRYPT_LEVEL);
+ if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->pvk_encr_level))
+ return 0;
+ return 1;
+}
+
+static int key2ms_does_selection(void *vctx, int selection)
+{
+ return (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0;
+}
+
+/*
+ * The real EVP_PKEY_set1_TYPE() functions take a non-const key, while the key
+ * pointer in the encode function is a const pointer. We violate the constness
+ * knowingly, since we know that the key comes from the same provider, is never
+ * actually const, and the implied reference count change is safe.
+ *
+ * EVP_PKEY_assign() can't be used, because there's no way to clear the internal
+ * key using that function without freeing the existing internal key.
+ */
+typedef int evp_pkey_set1_fn(EVP_PKEY *, const void *key);
+
+static int key2msblob_encode(void *vctx, const void *key, int selection,
+ OSSL_CORE_BIO *cout, evp_pkey_set1_fn *set1_key,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+ struct key2ms_ctx_st *ctx = vctx;
+ int ispub = -1;
+ EVP_PKEY *pkey = NULL;
+ int ok = 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ispub = 0;
+ else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ispub = 1;
+ else
+ return 0; /* Error */
+
+ if ((pkey = EVP_PKEY_new()) != NULL && set1_key(pkey, key))
+ ok = write_msblob(ctx, cout, pkey, ispub);
+ EVP_PKEY_free(pkey);
+ return ok;
+}
+
+static int key2pvk_encode(void *vctx, const void *key, int selection,
+ OSSL_CORE_BIO *cout, evp_pkey_set1_fn *set1_key,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+ struct key2ms_ctx_st *ctx = vctx;
+ EVP_PKEY *pkey = NULL;
+ int ok = 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) == 0)
+ return 0; /* Error */
+
+ if ((pkey = EVP_PKEY_new()) != NULL && set1_key(pkey, key)
+ && (pw_cb == NULL
+ || ossl_pw_set_ossl_passphrase_cb(&ctx->pwdata, pw_cb, pw_cbarg)))
+ ok = write_pvk(ctx, cout, pkey);
+ EVP_PKEY_free(pkey);
+ return ok;
+}
+
+#define dsa_set1 (evp_pkey_set1_fn *)EVP_PKEY_set1_DSA
+#define rsa_set1 (evp_pkey_set1_fn *)EVP_PKEY_set1_RSA
+
+#define msblob_set_params
+#define pvk_set_params \
+ { OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))key2pvk_settable_ctx_params }, \
+ { OSSL_FUNC_ENCODER_SET_CTX_PARAMS, \
+ (void (*)(void))key2pvk_set_ctx_params },
+
+#define MAKE_MS_ENCODER(impl, output, type) \
+ static OSSL_FUNC_encoder_import_object_fn \
+ impl##2##output##_import_object; \
+ static OSSL_FUNC_encoder_free_object_fn impl##2##output##_free_object; \
+ static OSSL_FUNC_encoder_encode_fn impl##2##output##_encode; \
+ \
+ static void * \
+ impl##2##output##_import_object(void *ctx, int selection, \
+ const OSSL_PARAM params[]) \
+ { \
+ return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \
+ ctx, selection, params); \
+ } \
+ static void impl##2##output##_free_object(void *key) \
+ { \
+ ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \
+ } \
+ static int impl##2##output##_encode(void *vctx, OSSL_CORE_BIO *cout, \
+ const void *key, \
+ const OSSL_PARAM key_abstract[], \
+ int selection, \
+ OSSL_PASSPHRASE_CALLBACK *cb, \
+ void *cbarg) \
+ { \
+ /* We don't deal with abstract objects */ \
+ if (key_abstract != NULL) { \
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \
+ return 0; \
+ } \
+ return key2##output##_encode(vctx, key, selection, cout, type##_set1, \
+ cb, cbarg); \
+ } \
+ const OSSL_DISPATCH ossl_##impl##_to_##output##_encoder_functions[] = { \
+ { OSSL_FUNC_ENCODER_NEWCTX, \
+ (void (*)(void))key2ms_newctx }, \
+ { OSSL_FUNC_ENCODER_FREECTX, \
+ (void (*)(void))key2ms_freectx }, \
+ output##_set_params \
+ { OSSL_FUNC_ENCODER_DOES_SELECTION, \
+ (void (*)(void))key2ms_does_selection }, \
+ { OSSL_FUNC_ENCODER_IMPORT_OBJECT, \
+ (void (*)(void))impl##2##output##_import_object }, \
+ { OSSL_FUNC_ENCODER_FREE_OBJECT, \
+ (void (*)(void))impl##2##output##_free_object }, \
+ { OSSL_FUNC_ENCODER_ENCODE, \
+ (void (*)(void))impl##2##output##_encode }, \
+ { 0, NULL } \
+ }
+
+#ifndef OPENSSL_NO_DSA
+MAKE_MS_ENCODER(dsa, pvk, dsa);
+MAKE_MS_ENCODER(dsa, msblob, dsa);
+#endif
+
+MAKE_MS_ENCODER(rsa, pvk, rsa);
+MAKE_MS_ENCODER(rsa, msblob, rsa);
diff --git a/providers/implementations/encode_decode/encode_key2text.c b/providers/implementations/encode_decode/encode_key2text.c
new file mode 100644
index 000000000000..7d983f5e51c6
--- /dev/null
+++ b/providers/implementations/encode_decode/encode_key2text.c
@@ -0,0 +1,889 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Low level APIs are deprecated for public use, but still ok for internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <ctype.h>
+
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/safestack.h>
+#include <openssl/proverr.h>
+#include "internal/ffc.h"
+#include "crypto/bn.h" /* bn_get_words() */
+#include "crypto/dh.h" /* ossl_dh_get0_params() */
+#include "crypto/dsa.h" /* ossl_dsa_get0_params() */
+#include "crypto/ec.h" /* ossl_ec_key_get_libctx */
+#include "crypto/ecx.h" /* ECX_KEY, etc... */
+#include "crypto/rsa.h" /* RSA_PSS_PARAMS_30, etc... */
+#include "prov/bio.h"
+#include "prov/implementations.h"
+#include "endecoder_local.h"
+
+DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
+
+# ifdef SIXTY_FOUR_BIT_LONG
+# define BN_FMTu "%lu"
+# define BN_FMTx "%lx"
+# endif
+
+# ifdef SIXTY_FOUR_BIT
+# define BN_FMTu "%llu"
+# define BN_FMTx "%llx"
+# endif
+
+# ifdef THIRTY_TWO_BIT
+# define BN_FMTu "%u"
+# define BN_FMTx "%x"
+# endif
+
+static int print_labeled_bignum(BIO *out, const char *label, const BIGNUM *bn)
+{
+ int ret = 0, use_sep = 0;
+ char *hex_str = NULL, *p;
+ const char spaces[] = " ";
+ const char *post_label_spc = " ";
+
+ const char *neg = "";
+ int bytes;
+
+ if (bn == NULL)
+ return 0;
+ if (label == NULL) {
+ label = "";
+ post_label_spc = "";
+ }
+
+ if (BN_is_zero(bn))
+ return BIO_printf(out, "%s%s0\n", label, post_label_spc);
+
+ if (BN_num_bytes(bn) <= BN_BYTES) {
+ BN_ULONG *words = bn_get_words(bn);
+
+ if (BN_is_negative(bn))
+ neg = "-";
+
+ return BIO_printf(out, "%s%s%s" BN_FMTu " (%s0x" BN_FMTx ")\n",
+ label, post_label_spc, neg, words[0], neg, words[0]);
+ }
+
+ hex_str = BN_bn2hex(bn);
+ if (hex_str == NULL)
+ return 0;
+
+ p = hex_str;
+ if (*p == '-') {
+ ++p;
+ neg = " (Negative)";
+ }
+ if (BIO_printf(out, "%s%s\n", label, neg) <= 0)
+ goto err;
+
+ /* Keep track of how many bytes we have printed out so far */
+ bytes = 0;
+
+ if (BIO_printf(out, "%s", spaces) <= 0)
+ goto err;
+
+ /* Add a leading 00 if the top bit is set */
+ if (*p >= '8') {
+ if (BIO_printf(out, "%02x", 0) <= 0)
+ goto err;
+ ++bytes;
+ use_sep = 1;
+ }
+ while (*p != '\0') {
+ /* Do a newline after every 15 hex bytes + add the space indent */
+ if ((bytes % 15) == 0 && bytes > 0) {
+ if (BIO_printf(out, ":\n%s", spaces) <= 0)
+ goto err;
+ use_sep = 0; /* The first byte on the next line doesnt have a : */
+ }
+ if (BIO_printf(out, "%s%c%c", use_sep ? ":" : "",
+ tolower(p[0]), tolower(p[1])) <= 0)
+ goto err;
+ ++bytes;
+ p += 2;
+ use_sep = 1;
+ }
+ if (BIO_printf(out, "\n") <= 0)
+ goto err;
+ ret = 1;
+err:
+ OPENSSL_free(hex_str);
+ return ret;
+}
+
+/* Number of octets per line */
+#define LABELED_BUF_PRINT_WIDTH 15
+
+#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC)
+static int print_labeled_buf(BIO *out, const char *label,
+ const unsigned char *buf, size_t buflen)
+{
+ size_t i;
+
+ if (BIO_printf(out, "%s\n", label) <= 0)
+ return 0;
+
+ for (i = 0; i < buflen; i++) {
+ if ((i % LABELED_BUF_PRINT_WIDTH) == 0) {
+ if (i > 0 && BIO_printf(out, "\n") <= 0)
+ return 0;
+ if (BIO_printf(out, " ") <= 0)
+ return 0;
+ }
+
+ if (BIO_printf(out, "%02x%s", buf[i],
+ (i == buflen - 1) ? "" : ":") <= 0)
+ return 0;
+ }
+ if (BIO_printf(out, "\n") <= 0)
+ return 0;
+
+ return 1;
+}
+#endif
+
+#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_DSA)
+static int ffc_params_to_text(BIO *out, const FFC_PARAMS *ffc)
+{
+ if (ffc->nid != NID_undef) {
+#ifndef OPENSSL_NO_DH
+ const DH_NAMED_GROUP *group = ossl_ffc_uid_to_dh_named_group(ffc->nid);
+ const char *name = ossl_ffc_named_group_get_name(group);
+
+ if (name == NULL)
+ goto err;
+ if (BIO_printf(out, "GROUP: %s\n", name) <= 0)
+ goto err;
+ return 1;
+#else
+ /* How could this be? We should not have a nid in a no-dh build. */
+ goto err;
+#endif
+ }
+
+ if (!print_labeled_bignum(out, "P: ", ffc->p))
+ goto err;
+ if (ffc->q != NULL) {
+ if (!print_labeled_bignum(out, "Q: ", ffc->q))
+ goto err;
+ }
+ if (!print_labeled_bignum(out, "G: ", ffc->g))
+ goto err;
+ if (ffc->j != NULL) {
+ if (!print_labeled_bignum(out, "J: ", ffc->j))
+ goto err;
+ }
+ if (ffc->seed != NULL) {
+ if (!print_labeled_buf(out, "SEED:", ffc->seed, ffc->seedlen))
+ goto err;
+ }
+ if (ffc->gindex != -1) {
+ if (BIO_printf(out, "gindex: %d\n", ffc->gindex) <= 0)
+ goto err;
+ }
+ if (ffc->pcounter != -1) {
+ if (BIO_printf(out, "pcounter: %d\n", ffc->pcounter) <= 0)
+ goto err;
+ }
+ if (ffc->h != 0) {
+ if (BIO_printf(out, "h: %d\n", ffc->h) <= 0)
+ goto err;
+ }
+ return 1;
+err:
+ return 0;
+}
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+#ifndef OPENSSL_NO_DH
+static int dh_to_text(BIO *out, const void *key, int selection)
+{
+ const DH *dh = key;
+ const char *type_label = NULL;
+ const BIGNUM *priv_key = NULL, *pub_key = NULL;
+ const FFC_PARAMS *params = NULL;
+ const BIGNUM *p = NULL;
+ long length;
+
+ if (out == NULL || dh == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ type_label = "DH Private-Key";
+ else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ type_label = "DH Public-Key";
+ else if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+ type_label = "DH Parameters";
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ priv_key = DH_get0_priv_key(dh);
+ if (priv_key == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
+ return 0;
+ }
+ }
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ pub_key = DH_get0_pub_key(dh);
+ if (pub_key == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
+ return 0;
+ }
+ }
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
+ params = ossl_dh_get0_params((DH *)dh);
+ if (params == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_PARAMETERS);
+ return 0;
+ }
+ }
+
+ p = DH_get0_p(dh);
+ if (p == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
+ return 0;
+ }
+
+ if (BIO_printf(out, "%s: (%d bit)\n", type_label, BN_num_bits(p)) <= 0)
+ return 0;
+ if (priv_key != NULL
+ && !print_labeled_bignum(out, "private-key:", priv_key))
+ return 0;
+ if (pub_key != NULL
+ && !print_labeled_bignum(out, "public-key:", pub_key))
+ return 0;
+ if (params != NULL
+ && !ffc_params_to_text(out, params))
+ return 0;
+ length = DH_get_length(dh);
+ if (length > 0
+ && BIO_printf(out, "recommended-private-length: %ld bits\n",
+ length) <= 0)
+ return 0;
+
+ return 1;
+}
+
+# define dh_input_type "DH"
+# define dhx_input_type "DHX"
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+#ifndef OPENSSL_NO_DSA
+static int dsa_to_text(BIO *out, const void *key, int selection)
+{
+ const DSA *dsa = key;
+ const char *type_label = NULL;
+ const BIGNUM *priv_key = NULL, *pub_key = NULL;
+ const FFC_PARAMS *params = NULL;
+ const BIGNUM *p = NULL;
+
+ if (out == NULL || dsa == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ type_label = "Private-Key";
+ else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ type_label = "Public-Key";
+ else if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+ type_label = "DSA-Parameters";
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ priv_key = DSA_get0_priv_key(dsa);
+ if (priv_key == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
+ return 0;
+ }
+ }
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ pub_key = DSA_get0_pub_key(dsa);
+ if (pub_key == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
+ return 0;
+ }
+ }
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
+ params = ossl_dsa_get0_params((DSA *)dsa);
+ if (params == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_PARAMETERS);
+ return 0;
+ }
+ }
+
+ p = DSA_get0_p(dsa);
+ if (p == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
+ return 0;
+ }
+
+ if (BIO_printf(out, "%s: (%d bit)\n", type_label, BN_num_bits(p)) <= 0)
+ return 0;
+ if (priv_key != NULL
+ && !print_labeled_bignum(out, "priv:", priv_key))
+ return 0;
+ if (pub_key != NULL
+ && !print_labeled_bignum(out, "pub: ", pub_key))
+ return 0;
+ if (params != NULL
+ && !ffc_params_to_text(out, params))
+ return 0;
+
+ return 1;
+}
+
+# define dsa_input_type "DSA"
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+#ifndef OPENSSL_NO_EC
+static int ec_param_explicit_curve_to_text(BIO *out, const EC_GROUP *group,
+ BN_CTX *ctx)
+{
+ const char *plabel = "Prime:";
+ BIGNUM *p = NULL, *a = NULL, *b = NULL;
+
+ p = BN_CTX_get(ctx);
+ a = BN_CTX_get(ctx);
+ b = BN_CTX_get(ctx);
+ if (b == NULL
+ || !EC_GROUP_get_curve(group, p, a, b, ctx))
+ return 0;
+
+ if (EC_GROUP_get_field_type(group) == NID_X9_62_characteristic_two_field) {
+ int basis_type = EC_GROUP_get_basis_type(group);
+
+ /* print the 'short name' of the base type OID */
+ if (basis_type == NID_undef
+ || BIO_printf(out, "Basis Type: %s\n", OBJ_nid2sn(basis_type)) <= 0)
+ return 0;
+ plabel = "Polynomial:";
+ }
+ return print_labeled_bignum(out, plabel, p)
+ && print_labeled_bignum(out, "A: ", a)
+ && print_labeled_bignum(out, "B: ", b);
+}
+
+static int ec_param_explicit_gen_to_text(BIO *out, const EC_GROUP *group,
+ BN_CTX *ctx)
+{
+ int ret;
+ size_t buflen;
+ point_conversion_form_t form;
+ const EC_POINT *point = NULL;
+ const char *glabel = NULL;
+ unsigned char *buf = NULL;
+
+ form = EC_GROUP_get_point_conversion_form(group);
+ point = EC_GROUP_get0_generator(group);
+
+ if (point == NULL)
+ return 0;
+
+ switch (form) {
+ case POINT_CONVERSION_COMPRESSED:
+ glabel = "Generator (compressed):";
+ break;
+ case POINT_CONVERSION_UNCOMPRESSED:
+ glabel = "Generator (uncompressed):";
+ break;
+ case POINT_CONVERSION_HYBRID:
+ glabel = "Generator (hybrid):";
+ break;
+ default:
+ return 0;
+ }
+
+ buflen = EC_POINT_point2buf(group, point, form, &buf, ctx);
+ if (buflen == 0)
+ return 0;
+
+ ret = print_labeled_buf(out, glabel, buf, buflen);
+ OPENSSL_clear_free(buf, buflen);
+ return ret;
+}
+
+/* Print explicit parameters */
+static int ec_param_explicit_to_text(BIO *out, const EC_GROUP *group,
+ OSSL_LIB_CTX *libctx)
+{
+ int ret = 0, tmp_nid;
+ BN_CTX *ctx = NULL;
+ const BIGNUM *order = NULL, *cofactor = NULL;
+ const unsigned char *seed;
+ size_t seed_len = 0;
+
+ ctx = BN_CTX_new_ex(libctx);
+ if (ctx == NULL)
+ return 0;
+ BN_CTX_start(ctx);
+
+ tmp_nid = EC_GROUP_get_field_type(group);
+ order = EC_GROUP_get0_order(group);
+ if (order == NULL)
+ goto err;
+
+ seed = EC_GROUP_get0_seed(group);
+ if (seed != NULL)
+ seed_len = EC_GROUP_get_seed_len(group);
+ cofactor = EC_GROUP_get0_cofactor(group);
+
+ /* print the 'short name' of the field type */
+ if (BIO_printf(out, "Field Type: %s\n", OBJ_nid2sn(tmp_nid)) <= 0
+ || !ec_param_explicit_curve_to_text(out, group, ctx)
+ || !ec_param_explicit_gen_to_text(out, group, ctx)
+ || !print_labeled_bignum(out, "Order: ", order)
+ || (cofactor != NULL
+ && !print_labeled_bignum(out, "Cofactor: ", cofactor))
+ || (seed != NULL
+ && !print_labeled_buf(out, "Seed:", seed, seed_len)))
+ goto err;
+ ret = 1;
+err:
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ return ret;
+}
+
+static int ec_param_to_text(BIO *out, const EC_GROUP *group,
+ OSSL_LIB_CTX *libctx)
+{
+ if (EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE) {
+ const char *curve_name;
+ int curve_nid = EC_GROUP_get_curve_name(group);
+
+ /* Explicit parameters */
+ if (curve_nid == NID_undef)
+ return 0;
+
+ if (BIO_printf(out, "%s: %s\n", "ASN1 OID", OBJ_nid2sn(curve_nid)) <= 0)
+ return 0;
+
+ curve_name = EC_curve_nid2nist(curve_nid);
+ return (curve_name == NULL
+ || BIO_printf(out, "%s: %s\n", "NIST CURVE", curve_name) > 0);
+ } else {
+ return ec_param_explicit_to_text(out, group, libctx);
+ }
+}
+
+static int ec_to_text(BIO *out, const void *key, int selection)
+{
+ const EC_KEY *ec = key;
+ const char *type_label = NULL;
+ unsigned char *priv = NULL, *pub = NULL;
+ size_t priv_len = 0, pub_len = 0;
+ const EC_GROUP *group;
+ int ret = 0;
+
+ if (out == NULL || ec == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if ((group = EC_KEY_get0_group(ec)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
+ return 0;
+ }
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ type_label = "Private-Key";
+ else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ type_label = "Public-Key";
+ else if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+ type_label = "EC-Parameters";
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ const BIGNUM *priv_key = EC_KEY_get0_private_key(ec);
+
+ if (priv_key == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
+ goto err;
+ }
+ priv_len = EC_KEY_priv2buf(ec, &priv);
+ if (priv_len == 0)
+ goto err;
+ }
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ const EC_POINT *pub_pt = EC_KEY_get0_public_key(ec);
+
+ if (pub_pt == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
+ goto err;
+ }
+
+ pub_len = EC_KEY_key2buf(ec, EC_KEY_get_conv_form(ec), &pub, NULL);
+ if (pub_len == 0)
+ goto err;
+ }
+
+ if (BIO_printf(out, "%s: (%d bit)\n", type_label,
+ EC_GROUP_order_bits(group)) <= 0)
+ goto err;
+ if (priv != NULL
+ && !print_labeled_buf(out, "priv:", priv, priv_len))
+ goto err;
+ if (pub != NULL
+ && !print_labeled_buf(out, "pub:", pub, pub_len))
+ goto err;
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+ ret = ec_param_to_text(out, group, ossl_ec_key_get_libctx(ec));
+err:
+ OPENSSL_clear_free(priv, priv_len);
+ OPENSSL_free(pub);
+ return ret;
+}
+
+# define ec_input_type "EC"
+
+# ifndef OPENSSL_NO_SM2
+# define sm2_input_type "SM2"
+# endif
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+#ifndef OPENSSL_NO_EC
+static int ecx_to_text(BIO *out, const void *key, int selection)
+{
+ const ECX_KEY *ecx = key;
+ const char *type_label = NULL;
+
+ if (out == NULL || ecx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ if (ecx->privkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
+ return 0;
+ }
+
+ switch (ecx->type) {
+ case ECX_KEY_TYPE_X25519:
+ type_label = "X25519 Private-Key";
+ break;
+ case ECX_KEY_TYPE_X448:
+ type_label = "X448 Private-Key";
+ break;
+ case ECX_KEY_TYPE_ED25519:
+ type_label = "ED25519 Private-Key";
+ break;
+ case ECX_KEY_TYPE_ED448:
+ type_label = "ED448 Private-Key";
+ break;
+ }
+ } else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ /* ecx->pubkey is an array, not a pointer... */
+ if (!ecx->haspubkey) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
+ return 0;
+ }
+
+ switch (ecx->type) {
+ case ECX_KEY_TYPE_X25519:
+ type_label = "X25519 Public-Key";
+ break;
+ case ECX_KEY_TYPE_X448:
+ type_label = "X448 Public-Key";
+ break;
+ case ECX_KEY_TYPE_ED25519:
+ type_label = "ED25519 Public-Key";
+ break;
+ case ECX_KEY_TYPE_ED448:
+ type_label = "ED448 Public-Key";
+ break;
+ }
+ }
+
+ if (BIO_printf(out, "%s:\n", type_label) <= 0)
+ return 0;
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
+ && !print_labeled_buf(out, "priv:", ecx->privkey, ecx->keylen))
+ return 0;
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0
+ && !print_labeled_buf(out, "pub:", ecx->pubkey, ecx->keylen))
+ return 0;
+
+ return 1;
+}
+
+# define ed25519_input_type "ED25519"
+# define ed448_input_type "ED448"
+# define x25519_input_type "X25519"
+# define x448_input_type "X448"
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+static int rsa_to_text(BIO *out, const void *key, int selection)
+{
+ const RSA *rsa = key;
+ const char *type_label = "RSA key";
+ const char *modulus_label = NULL;
+ const char *exponent_label = NULL;
+ const BIGNUM *rsa_d = NULL, *rsa_n = NULL, *rsa_e = NULL;
+ STACK_OF(BIGNUM_const) *factors = NULL;
+ STACK_OF(BIGNUM_const) *exps = NULL;
+ STACK_OF(BIGNUM_const) *coeffs = NULL;
+ int primes;
+ const RSA_PSS_PARAMS_30 *pss_params = ossl_rsa_get0_pss_params_30((RSA *)rsa);
+ int ret = 0;
+
+ if (out == NULL || rsa == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
+ goto err;
+ }
+
+ factors = sk_BIGNUM_const_new_null();
+ exps = sk_BIGNUM_const_new_null();
+ coeffs = sk_BIGNUM_const_new_null();
+
+ if (factors == NULL || exps == NULL || coeffs == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ type_label = "Private-Key";
+ modulus_label = "modulus:";
+ exponent_label = "publicExponent:";
+ } else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ type_label = "Public-Key";
+ modulus_label = "Modulus:";
+ exponent_label = "Exponent:";
+ }
+
+ RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d);
+ ossl_rsa_get0_all_params((RSA *)rsa, factors, exps, coeffs);
+ primes = sk_BIGNUM_const_num(factors);
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ if (BIO_printf(out, "%s: (%d bit, %d primes)\n",
+ type_label, BN_num_bits(rsa_n), primes) <= 0)
+ goto err;
+ } else {
+ if (BIO_printf(out, "%s: (%d bit)\n",
+ type_label, BN_num_bits(rsa_n)) <= 0)
+ goto err;
+ }
+
+ if (!print_labeled_bignum(out, modulus_label, rsa_n))
+ goto err;
+ if (!print_labeled_bignum(out, exponent_label, rsa_e))
+ goto err;
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ int i;
+
+ if (!print_labeled_bignum(out, "privateExponent:", rsa_d))
+ goto err;
+ if (!print_labeled_bignum(out, "prime1:",
+ sk_BIGNUM_const_value(factors, 0)))
+ goto err;
+ if (!print_labeled_bignum(out, "prime2:",
+ sk_BIGNUM_const_value(factors, 1)))
+ goto err;
+ if (!print_labeled_bignum(out, "exponent1:",
+ sk_BIGNUM_const_value(exps, 0)))
+ goto err;
+ if (!print_labeled_bignum(out, "exponent2:",
+ sk_BIGNUM_const_value(exps, 1)))
+ goto err;
+ if (!print_labeled_bignum(out, "coefficient:",
+ sk_BIGNUM_const_value(coeffs, 0)))
+ goto err;
+ for (i = 2; i < sk_BIGNUM_const_num(factors); i++) {
+ if (BIO_printf(out, "prime%d:", i + 1) <= 0)
+ goto err;
+ if (!print_labeled_bignum(out, NULL,
+ sk_BIGNUM_const_value(factors, i)))
+ goto err;
+ if (BIO_printf(out, "exponent%d:", i + 1) <= 0)
+ goto err;
+ if (!print_labeled_bignum(out, NULL,
+ sk_BIGNUM_const_value(exps, i)))
+ goto err;
+ if (BIO_printf(out, "coefficient%d:", i + 1) <= 0)
+ goto err;
+ if (!print_labeled_bignum(out, NULL,
+ sk_BIGNUM_const_value(coeffs, i - 1)))
+ goto err;
+ }
+ }
+
+ if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0) {
+ switch (RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK)) {
+ case RSA_FLAG_TYPE_RSA:
+ if (!ossl_rsa_pss_params_30_is_unrestricted(pss_params)) {
+ if (BIO_printf(out, "(INVALID PSS PARAMETERS)\n") <= 0)
+ goto err;
+ }
+ break;
+ case RSA_FLAG_TYPE_RSASSAPSS:
+ if (ossl_rsa_pss_params_30_is_unrestricted(pss_params)) {
+ if (BIO_printf(out, "No PSS parameter restrictions\n") <= 0)
+ goto err;
+ } else {
+ int hashalg_nid = ossl_rsa_pss_params_30_hashalg(pss_params);
+ int maskgenalg_nid =
+ ossl_rsa_pss_params_30_maskgenalg(pss_params);
+ int maskgenhashalg_nid =
+ ossl_rsa_pss_params_30_maskgenhashalg(pss_params);
+ int saltlen = ossl_rsa_pss_params_30_saltlen(pss_params);
+ int trailerfield =
+ ossl_rsa_pss_params_30_trailerfield(pss_params);
+
+ if (BIO_printf(out, "PSS parameter restrictions:\n") <= 0)
+ goto err;
+ if (BIO_printf(out, " Hash Algorithm: %s%s\n",
+ ossl_rsa_oaeppss_nid2name(hashalg_nid),
+ (hashalg_nid == NID_sha1
+ ? " (default)" : "")) <= 0)
+ goto err;
+ if (BIO_printf(out, " Mask Algorithm: %s with %s%s\n",
+ ossl_rsa_mgf_nid2name(maskgenalg_nid),
+ ossl_rsa_oaeppss_nid2name(maskgenhashalg_nid),
+ (maskgenalg_nid == NID_mgf1
+ && maskgenhashalg_nid == NID_sha1
+ ? " (default)" : "")) <= 0)
+ goto err;
+ if (BIO_printf(out, " Minimum Salt Length: %d%s\n",
+ saltlen,
+ (saltlen == 20 ? " (default)" : "")) <= 0)
+ goto err;
+ if (BIO_printf(out, " Trailer Field: 0x%x%s\n",
+ trailerfield,
+ (trailerfield == 1 ? " (default)" : "")) <= 0)
+ goto err;
+ }
+ break;
+ }
+ }
+
+ ret = 1;
+ err:
+ sk_BIGNUM_const_free(factors);
+ sk_BIGNUM_const_free(exps);
+ sk_BIGNUM_const_free(coeffs);
+ return ret;
+}
+
+#define rsa_input_type "RSA"
+#define rsapss_input_type "RSA-PSS"
+
+/* ---------------------------------------------------------------------- */
+
+static void *key2text_newctx(void *provctx)
+{
+ return provctx;
+}
+
+static void key2text_freectx(ossl_unused void *vctx)
+{
+}
+
+static int key2text_encode(void *vctx, const void *key, int selection,
+ OSSL_CORE_BIO *cout,
+ int (*key2text)(BIO *out, const void *key,
+ int selection),
+ OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+{
+ BIO *out = ossl_bio_new_from_core_bio(vctx, cout);
+ int ret;
+
+ if (out == NULL)
+ return 0;
+
+ ret = key2text(out, key, selection);
+ BIO_free(out);
+
+ return ret;
+}
+
+#define MAKE_TEXT_ENCODER(impl, type) \
+ static OSSL_FUNC_encoder_import_object_fn \
+ impl##2text_import_object; \
+ static OSSL_FUNC_encoder_free_object_fn \
+ impl##2text_free_object; \
+ static OSSL_FUNC_encoder_encode_fn impl##2text_encode; \
+ \
+ static void *impl##2text_import_object(void *ctx, int selection, \
+ const OSSL_PARAM params[]) \
+ { \
+ return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \
+ ctx, selection, params); \
+ } \
+ static void impl##2text_free_object(void *key) \
+ { \
+ ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \
+ } \
+ static int impl##2text_encode(void *vctx, OSSL_CORE_BIO *cout, \
+ const void *key, \
+ const OSSL_PARAM key_abstract[], \
+ int selection, \
+ OSSL_PASSPHRASE_CALLBACK *cb, \
+ void *cbarg) \
+ { \
+ /* We don't deal with abstract objects */ \
+ if (key_abstract != NULL) { \
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \
+ return 0; \
+ } \
+ return key2text_encode(vctx, key, selection, cout, \
+ type##_to_text, cb, cbarg); \
+ } \
+ const OSSL_DISPATCH ossl_##impl##_to_text_encoder_functions[] = { \
+ { OSSL_FUNC_ENCODER_NEWCTX, \
+ (void (*)(void))key2text_newctx }, \
+ { OSSL_FUNC_ENCODER_FREECTX, \
+ (void (*)(void))key2text_freectx }, \
+ { OSSL_FUNC_ENCODER_IMPORT_OBJECT, \
+ (void (*)(void))impl##2text_import_object }, \
+ { OSSL_FUNC_ENCODER_FREE_OBJECT, \
+ (void (*)(void))impl##2text_free_object }, \
+ { OSSL_FUNC_ENCODER_ENCODE, \
+ (void (*)(void))impl##2text_encode }, \
+ { 0, NULL } \
+ }
+
+#ifndef OPENSSL_NO_DH
+MAKE_TEXT_ENCODER(dh, dh);
+MAKE_TEXT_ENCODER(dhx, dh);
+#endif
+#ifndef OPENSSL_NO_DSA
+MAKE_TEXT_ENCODER(dsa, dsa);
+#endif
+#ifndef OPENSSL_NO_EC
+MAKE_TEXT_ENCODER(ec, ec);
+# ifndef OPENSSL_NO_SM2
+MAKE_TEXT_ENCODER(sm2, ec);
+# endif
+MAKE_TEXT_ENCODER(ed25519, ecx);
+MAKE_TEXT_ENCODER(ed448, ecx);
+MAKE_TEXT_ENCODER(x25519, ecx);
+MAKE_TEXT_ENCODER(x448, ecx);
+#endif
+MAKE_TEXT_ENCODER(rsa, rsa);
+MAKE_TEXT_ENCODER(rsapss, rsa);
diff --git a/providers/implementations/encode_decode/endecoder_common.c b/providers/implementations/encode_decode/endecoder_common.c
new file mode 100644
index 000000000000..c4ea2f853cfc
--- /dev/null
+++ b/providers/implementations/encode_decode/endecoder_common.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core.h>
+#include <openssl/buffer.h>
+#include "internal/asn1.h"
+#include "prov/bio.h"
+#include "endecoder_local.h"
+
+OSSL_FUNC_keymgmt_new_fn *
+ossl_prov_get_keymgmt_new(const OSSL_DISPATCH *fns)
+{
+ /* Pilfer the keymgmt dispatch table */
+ for (; fns->function_id != 0; fns++)
+ if (fns->function_id == OSSL_FUNC_KEYMGMT_NEW)
+ return OSSL_FUNC_keymgmt_new(fns);
+
+ return NULL;
+}
+
+OSSL_FUNC_keymgmt_free_fn *
+ossl_prov_get_keymgmt_free(const OSSL_DISPATCH *fns)
+{
+ /* Pilfer the keymgmt dispatch table */
+ for (; fns->function_id != 0; fns++)
+ if (fns->function_id == OSSL_FUNC_KEYMGMT_FREE)
+ return OSSL_FUNC_keymgmt_free(fns);
+
+ return NULL;
+}
+
+OSSL_FUNC_keymgmt_import_fn *
+ossl_prov_get_keymgmt_import(const OSSL_DISPATCH *fns)
+{
+ /* Pilfer the keymgmt dispatch table */
+ for (; fns->function_id != 0; fns++)
+ if (fns->function_id == OSSL_FUNC_KEYMGMT_IMPORT)
+ return OSSL_FUNC_keymgmt_import(fns);
+
+ return NULL;
+}
+
+OSSL_FUNC_keymgmt_export_fn *
+ossl_prov_get_keymgmt_export(const OSSL_DISPATCH *fns)
+{
+ /* Pilfer the keymgmt dispatch table */
+ for (; fns->function_id != 0; fns++)
+ if (fns->function_id == OSSL_FUNC_KEYMGMT_EXPORT)
+ return OSSL_FUNC_keymgmt_export(fns);
+
+ return NULL;
+}
+
+void *ossl_prov_import_key(const OSSL_DISPATCH *fns, void *provctx,
+ int selection, const OSSL_PARAM params[])
+{
+ OSSL_FUNC_keymgmt_new_fn *kmgmt_new = ossl_prov_get_keymgmt_new(fns);
+ OSSL_FUNC_keymgmt_free_fn *kmgmt_free = ossl_prov_get_keymgmt_free(fns);
+ OSSL_FUNC_keymgmt_import_fn *kmgmt_import =
+ ossl_prov_get_keymgmt_import(fns);
+ void *key = NULL;
+
+ if (kmgmt_new != NULL && kmgmt_import != NULL && kmgmt_free != NULL) {
+ if ((key = kmgmt_new(provctx)) == NULL
+ || !kmgmt_import(key, selection, params)) {
+ kmgmt_free(key);
+ key = NULL;
+ }
+ }
+ return key;
+}
+
+void ossl_prov_free_key(const OSSL_DISPATCH *fns, void *key)
+{
+ OSSL_FUNC_keymgmt_free_fn *kmgmt_free = ossl_prov_get_keymgmt_free(fns);
+
+ if (kmgmt_free != NULL)
+ kmgmt_free(key);
+}
+
+int ossl_read_der(PROV_CTX *provctx, OSSL_CORE_BIO *cin, unsigned char **data,
+ long *len)
+{
+ BUF_MEM *mem = NULL;
+ BIO *in = ossl_bio_new_from_core_bio(provctx, cin);
+ int ok;
+
+ if (in == NULL)
+ return 0;
+ ok = (asn1_d2i_read_bio(in, &mem) >= 0);
+ if (ok) {
+ *data = (unsigned char *)mem->data;
+ *len = (long)mem->length;
+ OPENSSL_free(mem);
+ }
+ BIO_free(in);
+ return ok;
+}
diff --git a/providers/implementations/encode_decode/endecoder_local.h b/providers/implementations/encode_decode/endecoder_local.h
new file mode 100644
index 000000000000..a65d05ffaeac
--- /dev/null
+++ b/providers/implementations/encode_decode/endecoder_local.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/types.h>
+#include "prov/provider_ctx.h"
+
+OSSL_FUNC_keymgmt_new_fn *ossl_prov_get_keymgmt_new(const OSSL_DISPATCH *fns);
+OSSL_FUNC_keymgmt_free_fn *ossl_prov_get_keymgmt_free(const OSSL_DISPATCH *fns);
+OSSL_FUNC_keymgmt_import_fn *ossl_prov_get_keymgmt_import(const OSSL_DISPATCH *fns);
+OSSL_FUNC_keymgmt_export_fn *ossl_prov_get_keymgmt_export(const OSSL_DISPATCH *fns);
+
+int ossl_prov_der_from_p8(unsigned char **new_der, long *new_der_len,
+ unsigned char *input_der, long input_der_len,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg);
+
+void *ossl_prov_import_key(const OSSL_DISPATCH *fns, void *provctx,
+ int selection, const OSSL_PARAM params[]);
+void ossl_prov_free_key(const OSSL_DISPATCH *fns, void *key);
+int ossl_read_der(PROV_CTX *provctx, OSSL_CORE_BIO *cin, unsigned char **data,
+ long *len);
diff --git a/providers/implementations/exchange/build.info b/providers/implementations/exchange/build.info
new file mode 100644
index 000000000000..3c1e5c58f1e3
--- /dev/null
+++ b/providers/implementations/exchange/build.info
@@ -0,0 +1,29 @@
+# We make separate GOAL variables for each algorithm, to make it easy to
+# switch each to the Legacy provider when needed.
+
+$DH_GOAL=../../libdefault.a ../../libfips.a
+$ECDH_GOAL=../../libdefault.a ../../libfips.a
+$ECX_GOAL=../../libdefault.a ../../libfips.a
+$KDF_GOAL=../../libdefault.a ../../libfips.a
+
+IF[{- !$disabled{dh} -}]
+ SOURCE[$DH_GOAL]=dh_exch.c
+ENDIF
+
+IF[{- !$disabled{asm} -}]
+ $ECDEF_s390x=S390X_EC_ASM
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+ IF[$ECASM_{- $target{asm_arch} -}]
+ $ECDEF=$ECDEF_{- $target{asm_arch} -}
+ ENDIF
+ENDIF
+
+IF[{- !$disabled{ec} -}]
+ SOURCE[$ECX_GOAL]=ecx_exch.c
+ DEFINE[$ECX_GOAL]=$ECDEF
+ SOURCE[$ECDH_GOAL]=ecdh_exch.c
+ENDIF
+
+SOURCE[$KDF_GOAL]=kdf_exch.c
diff --git a/providers/implementations/exchange/dh_exch.c b/providers/implementations/exchange/dh_exch.c
new file mode 100644
index 000000000000..1d8a2e27b30e
--- /dev/null
+++ b/providers/implementations/exchange/dh_exch.c
@@ -0,0 +1,512 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/dh.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include <openssl/params.h>
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/securitycheck.h"
+#include "crypto/dh.h"
+
+static OSSL_FUNC_keyexch_newctx_fn dh_newctx;
+static OSSL_FUNC_keyexch_init_fn dh_init;
+static OSSL_FUNC_keyexch_set_peer_fn dh_set_peer;
+static OSSL_FUNC_keyexch_derive_fn dh_derive;
+static OSSL_FUNC_keyexch_freectx_fn dh_freectx;
+static OSSL_FUNC_keyexch_dupctx_fn dh_dupctx;
+static OSSL_FUNC_keyexch_set_ctx_params_fn dh_set_ctx_params;
+static OSSL_FUNC_keyexch_settable_ctx_params_fn dh_settable_ctx_params;
+static OSSL_FUNC_keyexch_get_ctx_params_fn dh_get_ctx_params;
+static OSSL_FUNC_keyexch_gettable_ctx_params_fn dh_gettable_ctx_params;
+
+/*
+ * This type is only really used to handle some legacy related functionality.
+ * If you need to use other KDF's (such as SSKDF) just use PROV_DH_KDF_NONE
+ * here and then create and run a KDF after the key is derived.
+ * Note that X942 has 2 variants of key derivation:
+ * (1) DH_KDF_X9_42_ASN1 - which contains an ANS1 encoded object that has
+ * the counter embedded in it.
+ * (2) DH_KDF_X941_CONCAT - which is the same as ECDH_X963_KDF (which can be
+ * done by creating a "X963KDF".
+ */
+enum kdf_type {
+ PROV_DH_KDF_NONE = 0,
+ PROV_DH_KDF_X9_42_ASN1
+};
+
+/*
+ * What's passed as an actual key is defined by the KEYMGMT interface.
+ * We happen to know that our KEYMGMT simply passes DH structures, so
+ * we use that here too.
+ */
+
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ DH *dh;
+ DH *dhpeer;
+ unsigned int pad : 1;
+
+ /* DH KDF */
+ /* KDF (if any) to use for DH */
+ enum kdf_type kdf_type;
+ /* Message digest to use for key derivation */
+ EVP_MD *kdf_md;
+ /* User key material */
+ unsigned char *kdf_ukm;
+ size_t kdf_ukmlen;
+ /* KDF output length */
+ size_t kdf_outlen;
+ char *kdf_cekalg;
+} PROV_DH_CTX;
+
+static void *dh_newctx(void *provctx)
+{
+ PROV_DH_CTX *pdhctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ pdhctx = OPENSSL_zalloc(sizeof(PROV_DH_CTX));
+ if (pdhctx == NULL)
+ return NULL;
+ pdhctx->libctx = PROV_LIBCTX_OF(provctx);
+ pdhctx->kdf_type = PROV_DH_KDF_NONE;
+ return pdhctx;
+}
+
+static int dh_init(void *vpdhctx, void *vdh, const OSSL_PARAM params[])
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+
+ if (!ossl_prov_is_running()
+ || pdhctx == NULL
+ || vdh == NULL
+ || !DH_up_ref(vdh))
+ return 0;
+ DH_free(pdhctx->dh);
+ pdhctx->dh = vdh;
+ pdhctx->kdf_type = PROV_DH_KDF_NONE;
+ return dh_set_ctx_params(pdhctx, params)
+ && ossl_dh_check_key(pdhctx->libctx, vdh);
+}
+
+/* The 2 parties must share the same domain parameters */
+static int dh_match_params(DH *priv, DH *peer)
+{
+ int ret;
+ FFC_PARAMS *dhparams_priv = ossl_dh_get0_params(priv);
+ FFC_PARAMS *dhparams_peer = ossl_dh_get0_params(peer);
+
+ ret = dhparams_priv != NULL
+ && dhparams_peer != NULL
+ && ossl_ffc_params_cmp(dhparams_priv, dhparams_peer, 1);
+ if (!ret)
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISMATCHING_DOMAIN_PARAMETERS);
+ return ret;
+}
+
+static int dh_set_peer(void *vpdhctx, void *vdh)
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+
+ if (!ossl_prov_is_running()
+ || pdhctx == NULL
+ || vdh == NULL
+ || !dh_match_params(vdh, pdhctx->dh)
+ || !DH_up_ref(vdh))
+ return 0;
+ DH_free(pdhctx->dhpeer);
+ pdhctx->dhpeer = vdh;
+ return 1;
+}
+
+static int dh_plain_derive(void *vpdhctx,
+ unsigned char *secret, size_t *secretlen,
+ size_t outlen, unsigned int pad)
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+ int ret;
+ size_t dhsize;
+ const BIGNUM *pub_key = NULL;
+
+ if (pdhctx->dh == NULL || pdhctx->dhpeer == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
+ return 0;
+ }
+
+ dhsize = (size_t)DH_size(pdhctx->dh);
+ if (secret == NULL) {
+ *secretlen = dhsize;
+ return 1;
+ }
+ if (outlen < dhsize) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ DH_get0_key(pdhctx->dhpeer, &pub_key, NULL);
+ if (pad)
+ ret = DH_compute_key_padded(secret, pub_key, pdhctx->dh);
+ else
+ ret = DH_compute_key(secret, pub_key, pdhctx->dh);
+ if (ret <= 0)
+ return 0;
+
+ *secretlen = ret;
+ return 1;
+}
+
+static int dh_X9_42_kdf_derive(void *vpdhctx, unsigned char *secret,
+ size_t *secretlen, size_t outlen)
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+ unsigned char *stmp = NULL;
+ size_t stmplen;
+ int ret = 0;
+
+ if (secret == NULL) {
+ *secretlen = pdhctx->kdf_outlen;
+ return 1;
+ }
+
+ if (pdhctx->kdf_outlen > outlen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+ if (!dh_plain_derive(pdhctx, NULL, &stmplen, 0, 1))
+ return 0;
+ if ((stmp = OPENSSL_secure_malloc(stmplen)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (!dh_plain_derive(pdhctx, stmp, &stmplen, stmplen, 1))
+ goto err;
+
+ /* Do KDF stuff */
+ if (pdhctx->kdf_type == PROV_DH_KDF_X9_42_ASN1) {
+ if (!ossl_dh_kdf_X9_42_asn1(secret, pdhctx->kdf_outlen,
+ stmp, stmplen,
+ pdhctx->kdf_cekalg,
+ pdhctx->kdf_ukm,
+ pdhctx->kdf_ukmlen,
+ pdhctx->kdf_md,
+ pdhctx->libctx, NULL))
+ goto err;
+ }
+ *secretlen = pdhctx->kdf_outlen;
+ ret = 1;
+err:
+ OPENSSL_secure_clear_free(stmp, stmplen);
+ return ret;
+}
+
+static int dh_derive(void *vpdhctx, unsigned char *secret,
+ size_t *psecretlen, size_t outlen)
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ switch (pdhctx->kdf_type) {
+ case PROV_DH_KDF_NONE:
+ return dh_plain_derive(pdhctx, secret, psecretlen, outlen,
+ pdhctx->pad);
+ case PROV_DH_KDF_X9_42_ASN1:
+ return dh_X9_42_kdf_derive(pdhctx, secret, psecretlen, outlen);
+ default:
+ break;
+ }
+ return 0;
+}
+
+static void dh_freectx(void *vpdhctx)
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+
+ OPENSSL_free(pdhctx->kdf_cekalg);
+ DH_free(pdhctx->dh);
+ DH_free(pdhctx->dhpeer);
+ EVP_MD_free(pdhctx->kdf_md);
+ OPENSSL_clear_free(pdhctx->kdf_ukm, pdhctx->kdf_ukmlen);
+
+ OPENSSL_free(pdhctx);
+}
+
+static void *dh_dupctx(void *vpdhctx)
+{
+ PROV_DH_CTX *srcctx = (PROV_DH_CTX *)vpdhctx;
+ PROV_DH_CTX *dstctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+ if (dstctx == NULL)
+ return NULL;
+
+ *dstctx = *srcctx;
+ dstctx->dh = NULL;
+ dstctx->dhpeer = NULL;
+ dstctx->kdf_md = NULL;
+ dstctx->kdf_ukm = NULL;
+ dstctx->kdf_cekalg = NULL;
+
+ if (srcctx->dh != NULL && !DH_up_ref(srcctx->dh))
+ goto err;
+ else
+ dstctx->dh = srcctx->dh;
+
+ if (srcctx->dhpeer != NULL && !DH_up_ref(srcctx->dhpeer))
+ goto err;
+ else
+ dstctx->dhpeer = srcctx->dhpeer;
+
+ if (srcctx->kdf_md != NULL && !EVP_MD_up_ref(srcctx->kdf_md))
+ goto err;
+ else
+ dstctx->kdf_md = srcctx->kdf_md;
+
+ /* Duplicate UKM data if present */
+ if (srcctx->kdf_ukm != NULL && srcctx->kdf_ukmlen > 0) {
+ dstctx->kdf_ukm = OPENSSL_memdup(srcctx->kdf_ukm,
+ srcctx->kdf_ukmlen);
+ if (dstctx->kdf_ukm == NULL)
+ goto err;
+ }
+
+ if (srcctx->kdf_cekalg != NULL) {
+ dstctx->kdf_cekalg = OPENSSL_strdup(srcctx->kdf_cekalg);
+ if (dstctx->kdf_cekalg == NULL)
+ goto err;
+ }
+
+ return dstctx;
+err:
+ dh_freectx(dstctx);
+ return NULL;
+}
+
+static int dh_set_ctx_params(void *vpdhctx, const OSSL_PARAM params[])
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+ const OSSL_PARAM *p;
+ unsigned int pad;
+ char name[80] = { '\0' }; /* should be big enough */
+ char *str = NULL;
+
+ if (pdhctx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_TYPE);
+ if (p != NULL) {
+ str = name;
+ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
+ return 0;
+
+ if (name[0] == '\0')
+ pdhctx->kdf_type = PROV_DH_KDF_NONE;
+ else if (strcmp(name, OSSL_KDF_NAME_X942KDF_ASN1) == 0)
+ pdhctx->kdf_type = PROV_DH_KDF_X9_42_ASN1;
+ else
+ return 0;
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST);
+ if (p != NULL) {
+ char mdprops[80] = { '\0' }; /* should be big enough */
+
+ str = name;
+ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
+ return 0;
+
+ str = mdprops;
+ p = OSSL_PARAM_locate_const(params,
+ OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS);
+
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops)))
+ return 0;
+ }
+
+ EVP_MD_free(pdhctx->kdf_md);
+ pdhctx->kdf_md = EVP_MD_fetch(pdhctx->libctx, name, mdprops);
+ if (!ossl_digest_is_allowed(pdhctx->libctx, pdhctx->kdf_md)) {
+ EVP_MD_free(pdhctx->kdf_md);
+ pdhctx->kdf_md = NULL;
+ }
+ if (pdhctx->kdf_md == NULL)
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN);
+ if (p != NULL) {
+ size_t outlen;
+
+ if (!OSSL_PARAM_get_size_t(p, &outlen))
+ return 0;
+ pdhctx->kdf_outlen = outlen;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_UKM);
+ if (p != NULL) {
+ void *tmp_ukm = NULL;
+ size_t tmp_ukmlen;
+
+ OPENSSL_free(pdhctx->kdf_ukm);
+ pdhctx->kdf_ukm = NULL;
+ pdhctx->kdf_ukmlen = 0;
+ /* ukm is an optional field so it can be NULL */
+ if (p->data != NULL && p->data_size != 0) {
+ if (!OSSL_PARAM_get_octet_string(p, &tmp_ukm, 0, &tmp_ukmlen))
+ return 0;
+ pdhctx->kdf_ukm = tmp_ukm;
+ pdhctx->kdf_ukmlen = tmp_ukmlen;
+ }
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_PAD);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_uint(p, &pad))
+ return 0;
+ pdhctx->pad = pad ? 1 : 0;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_CEK_ALG);
+ if (p != NULL) {
+ str = name;
+
+ OPENSSL_free(pdhctx->kdf_cekalg);
+ pdhctx->kdf_cekalg = NULL;
+ if (p->data != NULL && p->data_size != 0) {
+ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
+ return 0;
+ pdhctx->kdf_cekalg = OPENSSL_strdup(name);
+ if (pdhctx->kdf_cekalg == NULL)
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_PAD, NULL),
+ OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS, NULL, 0),
+ OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
+ OSSL_PARAM_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *dh_settable_ctx_params(ossl_unused void *vpdhctx,
+ ossl_unused void *provctx)
+{
+ return known_settable_ctx_params;
+}
+
+static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
+ OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
+ OSSL_PARAM_DEFN(OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR,
+ NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *dh_gettable_ctx_params(ossl_unused void *vpdhctx,
+ ossl_unused void *provctx)
+{
+ return known_gettable_ctx_params;
+}
+
+static int dh_get_ctx_params(void *vpdhctx, OSSL_PARAM params[])
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+ OSSL_PARAM *p;
+
+ if (pdhctx == NULL)
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_TYPE);
+ if (p != NULL) {
+ const char *kdf_type = NULL;
+
+ switch (pdhctx->kdf_type) {
+ case PROV_DH_KDF_NONE:
+ kdf_type = "";
+ break;
+ case PROV_DH_KDF_X9_42_ASN1:
+ kdf_type = OSSL_KDF_NAME_X942KDF_ASN1;
+ break;
+ default:
+ return 0;
+ }
+
+ if (!OSSL_PARAM_set_utf8_string(p, kdf_type))
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST);
+ if (p != NULL
+ && !OSSL_PARAM_set_utf8_string(p, pdhctx->kdf_md == NULL
+ ? ""
+ : EVP_MD_get0_name(pdhctx->kdf_md))){
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, pdhctx->kdf_outlen))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_UKM);
+ if (p != NULL
+ && !OSSL_PARAM_set_octet_ptr(p, pdhctx->kdf_ukm, pdhctx->kdf_ukmlen))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_CEK_ALG);
+ if (p != NULL
+ && !OSSL_PARAM_set_utf8_string(p, pdhctx->kdf_cekalg == NULL
+ ? "" : pdhctx->kdf_cekalg))
+ return 0;
+
+ return 1;
+}
+
+const OSSL_DISPATCH ossl_dh_keyexch_functions[] = {
+ { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))dh_newctx },
+ { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))dh_init },
+ { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))dh_derive },
+ { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))dh_set_peer },
+ { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))dh_freectx },
+ { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))dh_dupctx },
+ { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))dh_set_ctx_params },
+ { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS,
+ (void (*)(void))dh_settable_ctx_params },
+ { OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))dh_get_ctx_params },
+ { OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS,
+ (void (*)(void))dh_gettable_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/exchange/ecdh_exch.c b/providers/implementations/exchange/ecdh_exch.c
new file mode 100644
index 000000000000..35d665fb9105
--- /dev/null
+++ b/providers/implementations/exchange/ecdh_exch.c
@@ -0,0 +1,580 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * ECDH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/ec.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/securitycheck.h"
+#include "crypto/ec.h" /* ossl_ecdh_kdf_X9_63() */
+
+static OSSL_FUNC_keyexch_newctx_fn ecdh_newctx;
+static OSSL_FUNC_keyexch_init_fn ecdh_init;
+static OSSL_FUNC_keyexch_set_peer_fn ecdh_set_peer;
+static OSSL_FUNC_keyexch_derive_fn ecdh_derive;
+static OSSL_FUNC_keyexch_freectx_fn ecdh_freectx;
+static OSSL_FUNC_keyexch_dupctx_fn ecdh_dupctx;
+static OSSL_FUNC_keyexch_set_ctx_params_fn ecdh_set_ctx_params;
+static OSSL_FUNC_keyexch_settable_ctx_params_fn ecdh_settable_ctx_params;
+static OSSL_FUNC_keyexch_get_ctx_params_fn ecdh_get_ctx_params;
+static OSSL_FUNC_keyexch_gettable_ctx_params_fn ecdh_gettable_ctx_params;
+
+enum kdf_type {
+ PROV_ECDH_KDF_NONE = 0,
+ PROV_ECDH_KDF_X9_63
+};
+
+/*
+ * What's passed as an actual key is defined by the KEYMGMT interface.
+ * We happen to know that our KEYMGMT simply passes EC_KEY structures, so
+ * we use that here too.
+ */
+
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+
+ EC_KEY *k;
+ EC_KEY *peerk;
+
+ /*
+ * ECDH cofactor mode:
+ *
+ * . 0 disabled
+ * . 1 enabled
+ * . -1 use cofactor mode set for k
+ */
+ int cofactor_mode;
+
+ /************
+ * ECDH KDF *
+ ************/
+ /* KDF (if any) to use for ECDH */
+ enum kdf_type kdf_type;
+ /* Message digest to use for key derivation */
+ EVP_MD *kdf_md;
+ /* User key material */
+ unsigned char *kdf_ukm;
+ size_t kdf_ukmlen;
+ /* KDF output length */
+ size_t kdf_outlen;
+} PROV_ECDH_CTX;
+
+static
+void *ecdh_newctx(void *provctx)
+{
+ PROV_ECDH_CTX *pectx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ pectx = OPENSSL_zalloc(sizeof(*pectx));
+ if (pectx == NULL)
+ return NULL;
+
+ pectx->libctx = PROV_LIBCTX_OF(provctx);
+ pectx->cofactor_mode = -1;
+ pectx->kdf_type = PROV_ECDH_KDF_NONE;
+
+ return (void *)pectx;
+}
+
+static
+int ecdh_init(void *vpecdhctx, void *vecdh, const OSSL_PARAM params[])
+{
+ PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
+
+ if (!ossl_prov_is_running()
+ || pecdhctx == NULL
+ || vecdh == NULL
+ || !EC_KEY_up_ref(vecdh))
+ return 0;
+ EC_KEY_free(pecdhctx->k);
+ pecdhctx->k = vecdh;
+ pecdhctx->cofactor_mode = -1;
+ pecdhctx->kdf_type = PROV_ECDH_KDF_NONE;
+ return ecdh_set_ctx_params(pecdhctx, params)
+ && ossl_ec_check_key(pecdhctx->libctx, vecdh, 1);
+}
+
+static
+int ecdh_match_params(const EC_KEY *priv, const EC_KEY *peer)
+{
+ int ret;
+ BN_CTX *ctx = NULL;
+ const EC_GROUP *group_priv = EC_KEY_get0_group(priv);
+ const EC_GROUP *group_peer = EC_KEY_get0_group(peer);
+
+ ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(priv));
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ ret = group_priv != NULL
+ && group_peer != NULL
+ && EC_GROUP_cmp(group_priv, group_peer, ctx) == 0;
+ if (!ret)
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISMATCHING_DOMAIN_PARAMETERS);
+ BN_CTX_free(ctx);
+ return ret;
+}
+
+static
+int ecdh_set_peer(void *vpecdhctx, void *vecdh)
+{
+ PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
+
+ if (!ossl_prov_is_running()
+ || pecdhctx == NULL
+ || vecdh == NULL
+ || !ecdh_match_params(pecdhctx->k, vecdh)
+ || !ossl_ec_check_key(pecdhctx->libctx, vecdh, 1)
+ || !EC_KEY_up_ref(vecdh))
+ return 0;
+
+ EC_KEY_free(pecdhctx->peerk);
+ pecdhctx->peerk = vecdh;
+ return 1;
+}
+
+static
+void ecdh_freectx(void *vpecdhctx)
+{
+ PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
+
+ EC_KEY_free(pecdhctx->k);
+ EC_KEY_free(pecdhctx->peerk);
+
+ EVP_MD_free(pecdhctx->kdf_md);
+ OPENSSL_clear_free(pecdhctx->kdf_ukm, pecdhctx->kdf_ukmlen);
+
+ OPENSSL_free(pecdhctx);
+}
+
+static
+void *ecdh_dupctx(void *vpecdhctx)
+{
+ PROV_ECDH_CTX *srcctx = (PROV_ECDH_CTX *)vpecdhctx;
+ PROV_ECDH_CTX *dstctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+ if (dstctx == NULL)
+ return NULL;
+
+ *dstctx = *srcctx;
+
+ /* clear all pointers */
+
+ dstctx->k= NULL;
+ dstctx->peerk = NULL;
+ dstctx->kdf_md = NULL;
+ dstctx->kdf_ukm = NULL;
+
+ /* up-ref all ref-counted objects referenced in dstctx */
+
+ if (srcctx->k != NULL && !EC_KEY_up_ref(srcctx->k))
+ goto err;
+ else
+ dstctx->k = srcctx->k;
+
+ if (srcctx->peerk != NULL && !EC_KEY_up_ref(srcctx->peerk))
+ goto err;
+ else
+ dstctx->peerk = srcctx->peerk;
+
+ if (srcctx->kdf_md != NULL && !EVP_MD_up_ref(srcctx->kdf_md))
+ goto err;
+ else
+ dstctx->kdf_md = srcctx->kdf_md;
+
+ /* Duplicate UKM data if present */
+ if (srcctx->kdf_ukm != NULL && srcctx->kdf_ukmlen > 0) {
+ dstctx->kdf_ukm = OPENSSL_memdup(srcctx->kdf_ukm,
+ srcctx->kdf_ukmlen);
+ if (dstctx->kdf_ukm == NULL)
+ goto err;
+ }
+
+ return dstctx;
+
+ err:
+ ecdh_freectx(dstctx);
+ return NULL;
+}
+
+static
+int ecdh_set_ctx_params(void *vpecdhctx, const OSSL_PARAM params[])
+{
+ char name[80] = { '\0' }; /* should be big enough */
+ char *str = NULL;
+ PROV_ECDH_CTX *pectx = (PROV_ECDH_CTX *)vpecdhctx;
+ const OSSL_PARAM *p;
+
+ if (pectx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE);
+ if (p != NULL) {
+ int mode;
+
+ if (!OSSL_PARAM_get_int(p, &mode))
+ return 0;
+
+ if (mode < -1 || mode > 1)
+ return 0;
+
+ pectx->cofactor_mode = mode;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_TYPE);
+ if (p != NULL) {
+ str = name;
+ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
+ return 0;
+
+ if (name[0] == '\0')
+ pectx->kdf_type = PROV_ECDH_KDF_NONE;
+ else if (strcmp(name, OSSL_KDF_NAME_X963KDF) == 0)
+ pectx->kdf_type = PROV_ECDH_KDF_X9_63;
+ else
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST);
+ if (p != NULL) {
+ char mdprops[80] = { '\0' }; /* should be big enough */
+
+ str = name;
+ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
+ return 0;
+
+ str = mdprops;
+ p = OSSL_PARAM_locate_const(params,
+ OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS);
+
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops)))
+ return 0;
+ }
+
+ EVP_MD_free(pectx->kdf_md);
+ pectx->kdf_md = EVP_MD_fetch(pectx->libctx, name, mdprops);
+ if (!ossl_digest_is_allowed(pectx->libctx, pectx->kdf_md)) {
+ EVP_MD_free(pectx->kdf_md);
+ pectx->kdf_md = NULL;
+ }
+ if (pectx->kdf_md == NULL)
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN);
+ if (p != NULL) {
+ size_t outlen;
+
+ if (!OSSL_PARAM_get_size_t(p, &outlen))
+ return 0;
+ pectx->kdf_outlen = outlen;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_UKM);
+ if (p != NULL) {
+ void *tmp_ukm = NULL;
+ size_t tmp_ukmlen;
+
+ if (!OSSL_PARAM_get_octet_string(p, &tmp_ukm, 0, &tmp_ukmlen))
+ return 0;
+ OPENSSL_free(pectx->kdf_ukm);
+ pectx->kdf_ukm = tmp_ukm;
+ pectx->kdf_ukmlen = tmp_ukmlen;
+ }
+
+ return 1;
+}
+
+static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, NULL),
+ OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS, NULL, 0),
+ OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
+ OSSL_PARAM_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static
+const OSSL_PARAM *ecdh_settable_ctx_params(ossl_unused void *vpecdhctx,
+ ossl_unused void *provctx)
+{
+ return known_settable_ctx_params;
+}
+
+static
+int ecdh_get_ctx_params(void *vpecdhctx, OSSL_PARAM params[])
+{
+ PROV_ECDH_CTX *pectx = (PROV_ECDH_CTX *)vpecdhctx;
+ OSSL_PARAM *p;
+
+ if (pectx == NULL)
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE);
+ if (p != NULL) {
+ int mode = pectx->cofactor_mode;
+
+ if (mode == -1) {
+ /* check what is the default for pecdhctx->k */
+ mode = EC_KEY_get_flags(pectx->k) & EC_FLAG_COFACTOR_ECDH ? 1 : 0;
+ }
+
+ if (!OSSL_PARAM_set_int(p, mode))
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_TYPE);
+ if (p != NULL) {
+ const char *kdf_type = NULL;
+
+ switch (pectx->kdf_type) {
+ case PROV_ECDH_KDF_NONE:
+ kdf_type = "";
+ break;
+ case PROV_ECDH_KDF_X9_63:
+ kdf_type = OSSL_KDF_NAME_X963KDF;
+ break;
+ default:
+ return 0;
+ }
+
+ if (!OSSL_PARAM_set_utf8_string(p, kdf_type))
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST);
+ if (p != NULL
+ && !OSSL_PARAM_set_utf8_string(p, pectx->kdf_md == NULL
+ ? ""
+ : EVP_MD_get0_name(pectx->kdf_md))){
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, pectx->kdf_outlen))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_UKM);
+ if (p != NULL &&
+ !OSSL_PARAM_set_octet_ptr(p, pectx->kdf_ukm, pectx->kdf_ukmlen))
+ return 0;
+
+ return 1;
+}
+
+static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, NULL),
+ OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
+ OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
+ OSSL_PARAM_DEFN(OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR,
+ NULL, 0),
+ OSSL_PARAM_END
+};
+
+static
+const OSSL_PARAM *ecdh_gettable_ctx_params(ossl_unused void *vpecdhctx,
+ ossl_unused void *provctx)
+{
+ return known_gettable_ctx_params;
+}
+
+static ossl_inline
+size_t ecdh_size(const EC_KEY *k)
+{
+ size_t degree = 0;
+ const EC_GROUP *group;
+
+ if (k == NULL
+ || (group = EC_KEY_get0_group(k)) == NULL)
+ return 0;
+
+ degree = EC_GROUP_get_degree(group);
+
+ return (degree + 7) / 8;
+}
+
+static ossl_inline
+int ecdh_plain_derive(void *vpecdhctx, unsigned char *secret,
+ size_t *psecretlen, size_t outlen)
+{
+ PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
+ int retlen, ret = 0;
+ size_t ecdhsize, size;
+ const EC_POINT *ppubkey = NULL;
+ EC_KEY *privk = NULL;
+ const EC_GROUP *group;
+ const BIGNUM *cofactor;
+ int key_cofactor_mode;
+
+ if (pecdhctx->k == NULL || pecdhctx->peerk == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
+ return 0;
+ }
+
+ ecdhsize = ecdh_size(pecdhctx->k);
+ if (secret == NULL) {
+ *psecretlen = ecdhsize;
+ return 1;
+ }
+
+ if ((group = EC_KEY_get0_group(pecdhctx->k)) == NULL
+ || (cofactor = EC_GROUP_get0_cofactor(group)) == NULL )
+ return 0;
+
+ /*
+ * NB: unlike PKCS#3 DH, if outlen is less than maximum size this is not
+ * an error, the result is truncated.
+ */
+ size = outlen < ecdhsize ? outlen : ecdhsize;
+
+ /*
+ * The ctx->cofactor_mode flag has precedence over the
+ * cofactor_mode flag set on ctx->k.
+ *
+ * - if ctx->cofactor_mode == -1, use ctx->k directly
+ * - if ctx->cofactor_mode == key_cofactor_mode, use ctx->k directly
+ * - if ctx->cofactor_mode != key_cofactor_mode:
+ * - if ctx->k->cofactor == 1, the cofactor_mode flag is irrelevant, use
+ * ctx->k directly
+ * - if ctx->k->cofactor != 1, use a duplicate of ctx->k with the flag
+ * set to ctx->cofactor_mode
+ */
+ key_cofactor_mode =
+ (EC_KEY_get_flags(pecdhctx->k) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
+ if (pecdhctx->cofactor_mode != -1
+ && pecdhctx->cofactor_mode != key_cofactor_mode
+ && !BN_is_one(cofactor)) {
+ if ((privk = EC_KEY_dup(pecdhctx->k)) == NULL)
+ return 0;
+
+ if (pecdhctx->cofactor_mode == 1)
+ EC_KEY_set_flags(privk, EC_FLAG_COFACTOR_ECDH);
+ else
+ EC_KEY_clear_flags(privk, EC_FLAG_COFACTOR_ECDH);
+ } else {
+ privk = pecdhctx->k;
+ }
+
+ ppubkey = EC_KEY_get0_public_key(pecdhctx->peerk);
+
+ retlen = ECDH_compute_key(secret, size, ppubkey, privk, NULL);
+
+ if (retlen <= 0)
+ goto end;
+
+ *psecretlen = retlen;
+ ret = 1;
+
+ end:
+ if (privk != pecdhctx->k)
+ EC_KEY_free(privk);
+ return ret;
+}
+
+static ossl_inline
+int ecdh_X9_63_kdf_derive(void *vpecdhctx, unsigned char *secret,
+ size_t *psecretlen, size_t outlen)
+{
+ PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
+ unsigned char *stmp = NULL;
+ size_t stmplen;
+ int ret = 0;
+
+ if (secret == NULL) {
+ *psecretlen = pecdhctx->kdf_outlen;
+ return 1;
+ }
+
+ if (pecdhctx->kdf_outlen > outlen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+ if (!ecdh_plain_derive(vpecdhctx, NULL, &stmplen, 0))
+ return 0;
+ if ((stmp = OPENSSL_secure_malloc(stmplen)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (!ecdh_plain_derive(vpecdhctx, stmp, &stmplen, stmplen))
+ goto err;
+
+ /* Do KDF stuff */
+ if (!ossl_ecdh_kdf_X9_63(secret, pecdhctx->kdf_outlen,
+ stmp, stmplen,
+ pecdhctx->kdf_ukm,
+ pecdhctx->kdf_ukmlen,
+ pecdhctx->kdf_md,
+ pecdhctx->libctx, NULL))
+ goto err;
+ *psecretlen = pecdhctx->kdf_outlen;
+ ret = 1;
+
+ err:
+ OPENSSL_secure_clear_free(stmp, stmplen);
+ return ret;
+}
+
+static
+int ecdh_derive(void *vpecdhctx, unsigned char *secret,
+ size_t *psecretlen, size_t outlen)
+{
+ PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
+
+ switch (pecdhctx->kdf_type) {
+ case PROV_ECDH_KDF_NONE:
+ return ecdh_plain_derive(vpecdhctx, secret, psecretlen, outlen);
+ case PROV_ECDH_KDF_X9_63:
+ return ecdh_X9_63_kdf_derive(vpecdhctx, secret, psecretlen, outlen);
+ default:
+ break;
+ }
+ return 0;
+}
+
+const OSSL_DISPATCH ossl_ecdh_keyexch_functions[] = {
+ { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))ecdh_newctx },
+ { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))ecdh_init },
+ { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))ecdh_derive },
+ { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))ecdh_set_peer },
+ { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))ecdh_freectx },
+ { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))ecdh_dupctx },
+ { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))ecdh_set_ctx_params },
+ { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS,
+ (void (*)(void))ecdh_settable_ctx_params },
+ { OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))ecdh_get_ctx_params },
+ { OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS,
+ (void (*)(void))ecdh_gettable_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/exchange/ecx_exch.c b/providers/implementations/exchange/ecx_exch.c
new file mode 100644
index 000000000000..2ba9090c8b5a
--- /dev/null
+++ b/providers/implementations/exchange/ecx_exch.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include "internal/cryptlib.h"
+#include "crypto/ecx.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+#ifdef S390X_EC_ASM
+# include "s390x_arch.h"
+#endif
+
+static OSSL_FUNC_keyexch_newctx_fn x25519_newctx;
+static OSSL_FUNC_keyexch_newctx_fn x448_newctx;
+static OSSL_FUNC_keyexch_init_fn ecx_init;
+static OSSL_FUNC_keyexch_set_peer_fn ecx_set_peer;
+static OSSL_FUNC_keyexch_derive_fn ecx_derive;
+static OSSL_FUNC_keyexch_freectx_fn ecx_freectx;
+static OSSL_FUNC_keyexch_dupctx_fn ecx_dupctx;
+
+/*
+ * What's passed as an actual key is defined by the KEYMGMT interface.
+ * We happen to know that our KEYMGMT simply passes ECX_KEY structures, so
+ * we use that here too.
+ */
+
+typedef struct {
+ size_t keylen;
+ ECX_KEY *key;
+ ECX_KEY *peerkey;
+} PROV_ECX_CTX;
+
+static void *ecx_newctx(void *provctx, size_t keylen)
+{
+ PROV_ECX_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(PROV_ECX_CTX));
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ ctx->keylen = keylen;
+
+ return ctx;
+}
+
+static void *x25519_newctx(void *provctx)
+{
+ return ecx_newctx(provctx, X25519_KEYLEN);
+}
+
+static void *x448_newctx(void *provctx)
+{
+ return ecx_newctx(provctx, X448_KEYLEN);
+}
+
+static int ecx_init(void *vecxctx, void *vkey,
+ ossl_unused const OSSL_PARAM params[])
+{
+ PROV_ECX_CTX *ecxctx = (PROV_ECX_CTX *)vecxctx;
+ ECX_KEY *key = vkey;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (ecxctx == NULL
+ || key == NULL
+ || key->keylen != ecxctx->keylen
+ || !ossl_ecx_key_up_ref(key)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ ossl_ecx_key_free(ecxctx->key);
+ ecxctx->key = key;
+
+ return 1;
+}
+
+static int ecx_set_peer(void *vecxctx, void *vkey)
+{
+ PROV_ECX_CTX *ecxctx = (PROV_ECX_CTX *)vecxctx;
+ ECX_KEY *key = vkey;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (ecxctx == NULL
+ || key == NULL
+ || key->keylen != ecxctx->keylen
+ || !ossl_ecx_key_up_ref(key)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ ossl_ecx_key_free(ecxctx->peerkey);
+ ecxctx->peerkey = key;
+
+ return 1;
+}
+
+static int ecx_derive(void *vecxctx, unsigned char *secret, size_t *secretlen,
+ size_t outlen)
+{
+ PROV_ECX_CTX *ecxctx = (PROV_ECX_CTX *)vecxctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (ecxctx->key == NULL
+ || ecxctx->key->privkey == NULL
+ || ecxctx->peerkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
+ return 0;
+ }
+
+ if (!ossl_assert(ecxctx->keylen == X25519_KEYLEN
+ || ecxctx->keylen == X448_KEYLEN)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+
+ if (secret == NULL) {
+ *secretlen = ecxctx->keylen;
+ return 1;
+ }
+ if (outlen < ecxctx->keylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (ecxctx->keylen == X25519_KEYLEN) {
+#ifdef S390X_EC_ASM
+ if (OPENSSL_s390xcap_P.pcc[1]
+ & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519)) {
+ if (s390x_x25519_mul(secret, ecxctx->peerkey->pubkey,
+ ecxctx->key->privkey) == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_DURING_DERIVATION);
+ return 0;
+ }
+ } else
+#endif
+ if (ossl_x25519(secret, ecxctx->key->privkey,
+ ecxctx->peerkey->pubkey) == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_DURING_DERIVATION);
+ return 0;
+ }
+ } else {
+#ifdef S390X_EC_ASM
+ if (OPENSSL_s390xcap_P.pcc[1]
+ & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448)) {
+ if (s390x_x448_mul(secret, ecxctx->peerkey->pubkey,
+ ecxctx->key->privkey) == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_DURING_DERIVATION);
+ return 0;
+ }
+ } else
+#endif
+ if (ossl_x448(secret, ecxctx->key->privkey,
+ ecxctx->peerkey->pubkey) == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_DURING_DERIVATION);
+ return 0;
+ }
+ }
+
+ *secretlen = ecxctx->keylen;
+ return 1;
+}
+
+static void ecx_freectx(void *vecxctx)
+{
+ PROV_ECX_CTX *ecxctx = (PROV_ECX_CTX *)vecxctx;
+
+ ossl_ecx_key_free(ecxctx->key);
+ ossl_ecx_key_free(ecxctx->peerkey);
+
+ OPENSSL_free(ecxctx);
+}
+
+static void *ecx_dupctx(void *vecxctx)
+{
+ PROV_ECX_CTX *srcctx = (PROV_ECX_CTX *)vecxctx;
+ PROV_ECX_CTX *dstctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+ if (dstctx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ *dstctx = *srcctx;
+ if (dstctx->key != NULL && !ossl_ecx_key_up_ref(dstctx->key)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+
+ if (dstctx->peerkey != NULL && !ossl_ecx_key_up_ref(dstctx->peerkey)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ ossl_ecx_key_free(dstctx->key);
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+
+ return dstctx;
+}
+
+const OSSL_DISPATCH ossl_x25519_keyexch_functions[] = {
+ { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))x25519_newctx },
+ { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))ecx_init },
+ { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))ecx_derive },
+ { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))ecx_set_peer },
+ { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))ecx_freectx },
+ { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))ecx_dupctx },
+ { 0, NULL }
+};
+
+const OSSL_DISPATCH ossl_x448_keyexch_functions[] = {
+ { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))x448_newctx },
+ { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))ecx_init },
+ { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))ecx_derive },
+ { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))ecx_set_peer },
+ { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))ecx_freectx },
+ { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))ecx_dupctx },
+ { 0, NULL }
+};
diff --git a/providers/implementations/exchange/kdf_exch.c b/providers/implementations/exchange/kdf_exch.c
new file mode 100644
index 000000000000..527a866c3d8d
--- /dev/null
+++ b/providers/implementations/exchange/kdf_exch.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/kdf.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include <openssl/params.h>
+#include "internal/numbers.h"
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/kdfexchange.h"
+#include "prov/providercommon.h"
+
+static OSSL_FUNC_keyexch_newctx_fn kdf_tls1_prf_newctx;
+static OSSL_FUNC_keyexch_newctx_fn kdf_hkdf_newctx;
+static OSSL_FUNC_keyexch_newctx_fn kdf_scrypt_newctx;
+static OSSL_FUNC_keyexch_init_fn kdf_init;
+static OSSL_FUNC_keyexch_derive_fn kdf_derive;
+static OSSL_FUNC_keyexch_freectx_fn kdf_freectx;
+static OSSL_FUNC_keyexch_dupctx_fn kdf_dupctx;
+static OSSL_FUNC_keyexch_set_ctx_params_fn kdf_set_ctx_params;
+static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_tls1_prf_settable_ctx_params;
+static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_hkdf_settable_ctx_params;
+static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_scrypt_settable_ctx_params;
+
+typedef struct {
+ void *provctx;
+ EVP_KDF_CTX *kdfctx;
+ KDF_DATA *kdfdata;
+} PROV_KDF_CTX;
+
+static void *kdf_newctx(const char *kdfname, void *provctx)
+{
+ PROV_KDF_CTX *kdfctx;
+ EVP_KDF *kdf = NULL;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ kdfctx = OPENSSL_zalloc(sizeof(PROV_KDF_CTX));
+ if (kdfctx == NULL)
+ return NULL;
+
+ kdfctx->provctx = provctx;
+
+ kdf = EVP_KDF_fetch(PROV_LIBCTX_OF(provctx), kdfname, NULL);
+ if (kdf == NULL)
+ goto err;
+ kdfctx->kdfctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+
+ if (kdfctx->kdfctx == NULL)
+ goto err;
+
+ return kdfctx;
+err:
+ OPENSSL_free(kdfctx);
+ return NULL;
+}
+
+#define KDF_NEWCTX(funcname, kdfname) \
+ static void *kdf_##funcname##_newctx(void *provctx) \
+ { \
+ return kdf_newctx(kdfname, provctx); \
+ }
+
+KDF_NEWCTX(tls1_prf, "TLS1-PRF")
+KDF_NEWCTX(hkdf, "HKDF")
+KDF_NEWCTX(scrypt, "SCRYPT")
+
+static int kdf_init(void *vpkdfctx, void *vkdf, const OSSL_PARAM params[])
+{
+ PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
+
+ if (!ossl_prov_is_running()
+ || pkdfctx == NULL
+ || vkdf == NULL
+ || !ossl_kdf_data_up_ref(vkdf))
+ return 0;
+ pkdfctx->kdfdata = vkdf;
+
+ return kdf_set_ctx_params(pkdfctx, params);
+}
+
+static int kdf_derive(void *vpkdfctx, unsigned char *secret, size_t *secretlen,
+ size_t outlen)
+{
+ PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
+ size_t kdfsize;
+ int ret;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ kdfsize = EVP_KDF_CTX_get_kdf_size(pkdfctx->kdfctx);
+
+ if (secret == NULL) {
+ *secretlen = kdfsize;
+ return 1;
+ }
+
+ if (kdfsize != SIZE_MAX) {
+ if (outlen < kdfsize) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+ outlen = kdfsize;
+ }
+
+ ret = EVP_KDF_derive(pkdfctx->kdfctx, secret, outlen, NULL);
+ if (ret <= 0)
+ return 0;
+
+ *secretlen = outlen;
+ return 1;
+}
+
+static void kdf_freectx(void *vpkdfctx)
+{
+ PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
+
+ EVP_KDF_CTX_free(pkdfctx->kdfctx);
+ ossl_kdf_data_free(pkdfctx->kdfdata);
+
+ OPENSSL_free(pkdfctx);
+}
+
+static void *kdf_dupctx(void *vpkdfctx)
+{
+ PROV_KDF_CTX *srcctx = (PROV_KDF_CTX *)vpkdfctx;
+ PROV_KDF_CTX *dstctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+ if (dstctx == NULL)
+ return NULL;
+
+ *dstctx = *srcctx;
+
+ dstctx->kdfctx = EVP_KDF_CTX_dup(srcctx->kdfctx);
+ if (dstctx->kdfctx == NULL) {
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+ if (!ossl_kdf_data_up_ref(dstctx->kdfdata)) {
+ EVP_KDF_CTX_free(dstctx->kdfctx);
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+
+ return dstctx;
+}
+
+static int kdf_set_ctx_params(void *vpkdfctx, const OSSL_PARAM params[])
+{
+ PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
+
+ return EVP_KDF_CTX_set_params(pkdfctx->kdfctx, params);
+}
+
+static const OSSL_PARAM *kdf_settable_ctx_params(ossl_unused void *vpkdfctx,
+ void *provctx,
+ const char *kdfname)
+{
+ EVP_KDF *kdf = EVP_KDF_fetch(PROV_LIBCTX_OF(provctx), kdfname,
+ NULL);
+ const OSSL_PARAM *params;
+
+ if (kdf == NULL)
+ return NULL;
+
+ params = EVP_KDF_settable_ctx_params(kdf);
+ EVP_KDF_free(kdf);
+
+ return params;
+}
+
+#define KDF_SETTABLE_CTX_PARAMS(funcname, kdfname) \
+ static const OSSL_PARAM *kdf_##funcname##_settable_ctx_params(void *vpkdfctx, \
+ void *provctx) \
+ { \
+ return kdf_settable_ctx_params(vpkdfctx, provctx, kdfname); \
+ }
+
+KDF_SETTABLE_CTX_PARAMS(tls1_prf, "TLS1-PRF")
+KDF_SETTABLE_CTX_PARAMS(hkdf, "HKDF")
+KDF_SETTABLE_CTX_PARAMS(scrypt, "SCRYPT")
+
+#define KDF_KEYEXCH_FUNCTIONS(funcname) \
+ const OSSL_DISPATCH ossl_kdf_##funcname##_keyexch_functions[] = { \
+ { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))kdf_##funcname##_newctx }, \
+ { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))kdf_init }, \
+ { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))kdf_derive }, \
+ { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))kdf_freectx }, \
+ { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))kdf_dupctx }, \
+ { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))kdf_set_ctx_params }, \
+ { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))kdf_##funcname##_settable_ctx_params }, \
+ { 0, NULL } \
+ };
+
+KDF_KEYEXCH_FUNCTIONS(tls1_prf)
+KDF_KEYEXCH_FUNCTIONS(hkdf)
+KDF_KEYEXCH_FUNCTIONS(scrypt)
diff --git a/providers/implementations/include/prov/__DECC_INCLUDE_EPILOGUE.H b/providers/implementations/include/prov/__DECC_INCLUDE_EPILOGUE.H
new file mode 100644
index 000000000000..2ab493330675
--- /dev/null
+++ b/providers/implementations/include/prov/__DECC_INCLUDE_EPILOGUE.H
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This file is only used by HP C/C++ on VMS, and is included automatically
+ * after each header file from this directory
+ */
+
+/*
+ * The C++ compiler doesn't understand these pragmas, even though it
+ * understands the corresponding command line qualifier.
+ */
+#ifndef __cplusplus
+/* restore state. Must correspond to the save in __decc_include_prologue.h */
+# pragma names restore
+#endif
diff --git a/providers/implementations/include/prov/__DECC_INCLUDE_PROLOGUE.H b/providers/implementations/include/prov/__DECC_INCLUDE_PROLOGUE.H
new file mode 100644
index 000000000000..8e95fa975488
--- /dev/null
+++ b/providers/implementations/include/prov/__DECC_INCLUDE_PROLOGUE.H
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This file is only used by HP C/C++ on VMS, and is included automatically
+ * after each header file from this directory
+ */
+
+/*
+ * The C++ compiler doesn't understand these pragmas, even though it
+ * understands the corresponding command line qualifier.
+ */
+#ifndef __cplusplus
+/* save state */
+# pragma names save
+/* have the compiler shorten symbols larger than 31 chars to 23 chars
+ * followed by a 8 hex char CRC
+ */
+# pragma names as_is,shortened
+#endif
diff --git a/providers/implementations/include/prov/blake2.h b/providers/implementations/include/prov/blake2.h
new file mode 100644
index 000000000000..d18cbc708c4f
--- /dev/null
+++ b/providers/implementations/include/prov/blake2.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_PROV_BLAKE2_H
+# define OSSL_PROV_BLAKE2_H
+
+# include <openssl/opensslconf.h>
+
+# include <openssl/e_os2.h>
+# include <stddef.h>
+
+# define BLAKE2S_BLOCKBYTES 64
+# define BLAKE2S_OUTBYTES 32
+# define BLAKE2S_KEYBYTES 32
+# define BLAKE2S_SALTBYTES 8
+# define BLAKE2S_PERSONALBYTES 8
+
+# define BLAKE2B_BLOCKBYTES 128
+# define BLAKE2B_OUTBYTES 64
+# define BLAKE2B_KEYBYTES 64
+# define BLAKE2B_SALTBYTES 16
+# define BLAKE2B_PERSONALBYTES 16
+
+struct blake2s_param_st {
+ uint8_t digest_length; /* 1 */
+ uint8_t key_length; /* 2 */
+ uint8_t fanout; /* 3 */
+ uint8_t depth; /* 4 */
+ uint8_t leaf_length[4];/* 8 */
+ uint8_t node_offset[6];/* 14 */
+ uint8_t node_depth; /* 15 */
+ uint8_t inner_length; /* 16 */
+ uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
+ uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
+};
+
+typedef struct blake2s_param_st BLAKE2S_PARAM;
+
+struct blake2s_ctx_st {
+ uint32_t h[8];
+ uint32_t t[2];
+ uint32_t f[2];
+ uint8_t buf[BLAKE2S_BLOCKBYTES];
+ size_t buflen;
+ size_t outlen;
+};
+
+struct blake2b_param_st {
+ uint8_t digest_length; /* 1 */
+ uint8_t key_length; /* 2 */
+ uint8_t fanout; /* 3 */
+ uint8_t depth; /* 4 */
+ uint8_t leaf_length[4];/* 8 */
+ uint8_t node_offset[8];/* 16 */
+ uint8_t node_depth; /* 17 */
+ uint8_t inner_length; /* 18 */
+ uint8_t reserved[14]; /* 32 */
+ uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
+ uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
+};
+
+typedef struct blake2b_param_st BLAKE2B_PARAM;
+
+struct blake2b_ctx_st {
+ uint64_t h[8];
+ uint64_t t[2];
+ uint64_t f[2];
+ uint8_t buf[BLAKE2B_BLOCKBYTES];
+ size_t buflen;
+ size_t outlen;
+};
+
+#define BLAKE2B_DIGEST_LENGTH 64
+#define BLAKE2S_DIGEST_LENGTH 32
+
+typedef struct blake2s_ctx_st BLAKE2S_CTX;
+typedef struct blake2b_ctx_st BLAKE2B_CTX;
+
+int ossl_blake2s256_init(void *ctx);
+int ossl_blake2b512_init(void *ctx);
+
+int ossl_blake2b_init(BLAKE2B_CTX *c, const BLAKE2B_PARAM *P);
+int ossl_blake2b_init_key(BLAKE2B_CTX *c, const BLAKE2B_PARAM *P,
+ const void *key);
+int ossl_blake2b_update(BLAKE2B_CTX *c, const void *data, size_t datalen);
+int ossl_blake2b_final(unsigned char *md, BLAKE2B_CTX *c);
+
+/*
+ * These setters are internal and do not check the validity of their parameters.
+ * See blake2b_mac_ctrl for validation logic.
+ */
+
+void ossl_blake2b_param_init(BLAKE2B_PARAM *P);
+void ossl_blake2b_param_set_digest_length(BLAKE2B_PARAM *P, uint8_t outlen);
+void ossl_blake2b_param_set_key_length(BLAKE2B_PARAM *P, uint8_t keylen);
+void ossl_blake2b_param_set_personal(BLAKE2B_PARAM *P, const uint8_t *personal,
+ size_t length);
+void ossl_blake2b_param_set_salt(BLAKE2B_PARAM *P, const uint8_t *salt,
+ size_t length);
+int ossl_blake2s_init(BLAKE2S_CTX *c, const BLAKE2S_PARAM *P);
+int ossl_blake2s_init_key(BLAKE2S_CTX *c, const BLAKE2S_PARAM *P,
+ const void *key);
+int ossl_blake2s_update(BLAKE2S_CTX *c, const void *data, size_t datalen);
+int ossl_blake2s_final(unsigned char *md, BLAKE2S_CTX *c);
+
+void ossl_blake2s_param_init(BLAKE2S_PARAM *P);
+void ossl_blake2s_param_set_digest_length(BLAKE2S_PARAM *P, uint8_t outlen);
+void ossl_blake2s_param_set_key_length(BLAKE2S_PARAM *P, uint8_t keylen);
+void ossl_blake2s_param_set_personal(BLAKE2S_PARAM *P, const uint8_t *personal,
+ size_t length);
+void ossl_blake2s_param_set_salt(BLAKE2S_PARAM *P, const uint8_t *salt,
+ size_t length);
+
+#endif /* OSSL_PROV_BLAKE2_H */
diff --git a/providers/implementations/include/prov/ciphercommon.h b/providers/implementations/include/prov/ciphercommon.h
new file mode 100644
index 000000000000..8153872cba26
--- /dev/null
+++ b/providers/implementations/include/prov/ciphercommon.h
@@ -0,0 +1,361 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/params.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/evp.h>
+#include "internal/cryptlib.h"
+#include "crypto/modes.h"
+
+# define MAXCHUNK ((size_t)1 << 30)
+# define MAXBITCHUNK ((size_t)1 << (sizeof(size_t) * 8 - 4))
+
+#define GENERIC_BLOCK_SIZE 16
+#define IV_STATE_UNINITIALISED 0 /* initial state is not initialized */
+#define IV_STATE_BUFFERED 1 /* iv has been copied to the iv buffer */
+#define IV_STATE_COPIED 2 /* iv has been copied from the iv buffer */
+#define IV_STATE_FINISHED 3 /* the iv has been used - so don't reuse it */
+
+#define PROV_CIPHER_FUNC(type, name, args) typedef type (* OSSL_##name##_fn)args
+
+typedef struct prov_cipher_hw_st PROV_CIPHER_HW;
+typedef struct prov_cipher_ctx_st PROV_CIPHER_CTX;
+
+typedef int (PROV_CIPHER_HW_FN)(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+/* Internal flags that can be queried */
+#define PROV_CIPHER_FLAG_AEAD 0x0001
+#define PROV_CIPHER_FLAG_CUSTOM_IV 0x0002
+#define PROV_CIPHER_FLAG_CTS 0x0004
+#define PROV_CIPHER_FLAG_TLS1_MULTIBLOCK 0x0008
+#define PROV_CIPHER_FLAG_RAND_KEY 0x0010
+/* Internal flags that are only used within the provider */
+#define PROV_CIPHER_FLAG_VARIABLE_LENGTH 0x0100
+#define PROV_CIPHER_FLAG_INVERSE_CIPHER 0x0200
+
+struct prov_cipher_ctx_st {
+ block128_f block;
+ union {
+ cbc128_f cbc;
+ ctr128_f ctr;
+ ecb128_f ecb;
+ } stream;
+
+ unsigned int mode;
+ size_t keylen; /* key size (in bytes) */
+ size_t ivlen;
+ size_t blocksize;
+ size_t bufsz; /* Number of bytes in buf */
+ unsigned int cts_mode; /* Use to set the type for CTS modes */
+ unsigned int pad : 1; /* Whether padding should be used or not */
+ unsigned int enc : 1; /* Set to 1 for encrypt, or 0 otherwise */
+ unsigned int iv_set : 1; /* Set when the iv is copied to the iv/oiv buffers */
+ unsigned int updated : 1; /* Set to 1 during update for one shot ciphers */
+ unsigned int variable_keylength : 1;
+ unsigned int inverse_cipher : 1; /* set to 1 to use inverse cipher */
+ unsigned int use_bits : 1; /* Set to 0 for cfb1 to use bits instead of bytes */
+
+ unsigned int tlsversion; /* If TLS padding is in use the TLS version number */
+ unsigned char *tlsmac; /* tls MAC extracted from the last record */
+ int alloced; /*
+ * Whether the tlsmac data has been allocated or
+ * points into the user buffer.
+ */
+ size_t tlsmacsize; /* Size of the TLS MAC */
+ int removetlspad; /* Whether TLS padding should be removed or not */
+ size_t removetlsfixed; /*
+ * Length of the fixed size data to remove when
+ * processing TLS data (equals mac size plus
+ * IV size if applicable)
+ */
+
+ /*
+ * num contains the number of bytes of |iv| which are valid for modes that
+ * manage partial blocks themselves.
+ */
+ unsigned int num;
+
+ /* The original value of the iv */
+ unsigned char oiv[GENERIC_BLOCK_SIZE];
+ /* Buffer of partial blocks processed via update calls */
+ unsigned char buf[GENERIC_BLOCK_SIZE];
+ unsigned char iv[GENERIC_BLOCK_SIZE];
+ const PROV_CIPHER_HW *hw; /* hardware specific functions */
+ const void *ks; /* Pointer to algorithm specific key data */
+ OSSL_LIB_CTX *libctx;
+};
+
+struct prov_cipher_hw_st {
+ int (*init)(PROV_CIPHER_CTX *dat, const uint8_t *key, size_t keylen);
+ PROV_CIPHER_HW_FN *cipher;
+ void (*copyctx)(PROV_CIPHER_CTX *dst, const PROV_CIPHER_CTX *src);
+};
+
+void ossl_cipher_generic_reset_ctx(PROV_CIPHER_CTX *ctx);
+OSSL_FUNC_cipher_encrypt_init_fn ossl_cipher_generic_einit;
+OSSL_FUNC_cipher_decrypt_init_fn ossl_cipher_generic_dinit;
+OSSL_FUNC_cipher_update_fn ossl_cipher_generic_block_update;
+OSSL_FUNC_cipher_final_fn ossl_cipher_generic_block_final;
+OSSL_FUNC_cipher_update_fn ossl_cipher_generic_stream_update;
+OSSL_FUNC_cipher_final_fn ossl_cipher_generic_stream_final;
+OSSL_FUNC_cipher_cipher_fn ossl_cipher_generic_cipher;
+OSSL_FUNC_cipher_get_ctx_params_fn ossl_cipher_generic_get_ctx_params;
+OSSL_FUNC_cipher_set_ctx_params_fn ossl_cipher_generic_set_ctx_params;
+OSSL_FUNC_cipher_gettable_params_fn ossl_cipher_generic_gettable_params;
+OSSL_FUNC_cipher_gettable_ctx_params_fn ossl_cipher_generic_gettable_ctx_params;
+OSSL_FUNC_cipher_settable_ctx_params_fn ossl_cipher_generic_settable_ctx_params;
+OSSL_FUNC_cipher_set_ctx_params_fn ossl_cipher_var_keylen_set_ctx_params;
+OSSL_FUNC_cipher_settable_ctx_params_fn ossl_cipher_var_keylen_settable_ctx_params;
+OSSL_FUNC_cipher_gettable_ctx_params_fn ossl_cipher_aead_gettable_ctx_params;
+OSSL_FUNC_cipher_settable_ctx_params_fn ossl_cipher_aead_settable_ctx_params;
+
+int ossl_cipher_generic_get_params(OSSL_PARAM params[], unsigned int md,
+ uint64_t flags,
+ size_t kbits, size_t blkbits, size_t ivbits);
+void ossl_cipher_generic_initkey(void *vctx, size_t kbits, size_t blkbits,
+ size_t ivbits, unsigned int mode,
+ uint64_t flags,
+ const PROV_CIPHER_HW *hw, void *provctx);
+
+#define IMPLEMENT_generic_cipher_func(alg, UCALG, lcmode, UCMODE, flags, kbits,\
+ blkbits, ivbits, typ) \
+const OSSL_DISPATCH ossl_##alg##kbits##lcmode##_functions[] = { \
+ { OSSL_FUNC_CIPHER_NEWCTX, \
+ (void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \
+ { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_cipher_generic_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_cipher_generic_dinit }, \
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_cipher_generic_##typ##_update },\
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_cipher_generic_##typ##_final }, \
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_cipher_generic_cipher }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, \
+ (void (*)(void)) alg##_##kbits##_##lcmode##_get_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_settable_ctx_params }, \
+ { 0, NULL } \
+};
+
+#define IMPLEMENT_var_keylen_cipher_func(alg, UCALG, lcmode, UCMODE, flags, \
+ kbits, blkbits, ivbits, typ) \
+const OSSL_DISPATCH ossl_##alg##kbits##lcmode##_functions[] = { \
+ { OSSL_FUNC_CIPHER_NEWCTX, \
+ (void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \
+ { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_cipher_generic_einit },\
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_cipher_generic_dinit },\
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_cipher_generic_##typ##_update },\
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_cipher_generic_##typ##_final }, \
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_cipher_generic_cipher }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, \
+ (void (*)(void)) alg##_##kbits##_##lcmode##_get_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_var_keylen_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_var_keylen_settable_ctx_params }, \
+ { 0, NULL } \
+};
+
+
+#define IMPLEMENT_generic_cipher_genfn(alg, UCALG, lcmode, UCMODE, flags, \
+ kbits, blkbits, ivbits, typ) \
+static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lcmode##_get_params; \
+static int alg##_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
+{ \
+ return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
+ flags, kbits, blkbits, ivbits); \
+} \
+static OSSL_FUNC_cipher_newctx_fn alg##_##kbits##_##lcmode##_newctx; \
+static void * alg##_##kbits##_##lcmode##_newctx(void *provctx) \
+{ \
+ PROV_##UCALG##_CTX *ctx = ossl_prov_is_running() ? OPENSSL_zalloc(sizeof(*ctx))\
+ : NULL; \
+ if (ctx != NULL) { \
+ ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, \
+ EVP_CIPH_##UCMODE##_MODE, flags, \
+ ossl_prov_cipher_hw_##alg##_##lcmode(kbits),\
+ provctx); \
+ } \
+ return ctx; \
+} \
+
+#define IMPLEMENT_generic_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \
+ blkbits, ivbits, typ) \
+IMPLEMENT_generic_cipher_genfn(alg, UCALG, lcmode, UCMODE, flags, kbits, \
+ blkbits, ivbits, typ) \
+IMPLEMENT_generic_cipher_func(alg, UCALG, lcmode, UCMODE, flags, kbits, \
+ blkbits, ivbits, typ)
+
+#define IMPLEMENT_var_keylen_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \
+ blkbits, ivbits, typ) \
+IMPLEMENT_generic_cipher_genfn(alg, UCALG, lcmode, UCMODE, flags, kbits, \
+ blkbits, ivbits, typ) \
+IMPLEMENT_var_keylen_cipher_func(alg, UCALG, lcmode, UCMODE, flags, kbits, \
+ blkbits, ivbits, typ)
+
+PROV_CIPHER_HW_FN ossl_cipher_hw_generic_cbc;
+PROV_CIPHER_HW_FN ossl_cipher_hw_generic_ecb;
+PROV_CIPHER_HW_FN ossl_cipher_hw_generic_ofb128;
+PROV_CIPHER_HW_FN ossl_cipher_hw_generic_cfb128;
+PROV_CIPHER_HW_FN ossl_cipher_hw_generic_cfb8;
+PROV_CIPHER_HW_FN ossl_cipher_hw_generic_cfb1;
+PROV_CIPHER_HW_FN ossl_cipher_hw_generic_ctr;
+PROV_CIPHER_HW_FN ossl_cipher_hw_chunked_cbc;
+PROV_CIPHER_HW_FN ossl_cipher_hw_chunked_cfb8;
+PROV_CIPHER_HW_FN ossl_cipher_hw_chunked_cfb128;
+PROV_CIPHER_HW_FN ossl_cipher_hw_chunked_ofb128;
+#define ossl_cipher_hw_chunked_ecb ossl_cipher_hw_generic_ecb
+#define ossl_cipher_hw_chunked_ctr ossl_cipher_hw_generic_ctr
+#define ossl_cipher_hw_chunked_cfb1 ossl_cipher_hw_generic_cfb1
+
+#define IMPLEMENT_CIPHER_HW_OFB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \
+static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \
+ unsigned char *out, \
+ const unsigned char *in, size_t len) \
+{ \
+ int num = ctx->num; \
+ KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \
+ \
+ while (len >= MAXCHUNK) { \
+ FUNC_PREFIX##_encrypt(in, out, MAXCHUNK, key, ctx->iv, &num); \
+ len -= MAXCHUNK; \
+ in += MAXCHUNK; \
+ out += MAXCHUNK; \
+ } \
+ if (len > 0) { \
+ FUNC_PREFIX##_encrypt(in, out, (long)len, key, ctx->iv, &num); \
+ } \
+ ctx->num = num; \
+ return 1; \
+}
+
+#define IMPLEMENT_CIPHER_HW_ECB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \
+static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \
+ unsigned char *out, \
+ const unsigned char *in, size_t len) \
+{ \
+ size_t i, bl = ctx->blocksize; \
+ KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \
+ \
+ if (len < bl) \
+ return 1; \
+ for (i = 0, len -= bl; i <= len; i += bl) \
+ FUNC_PREFIX##_encrypt(in + i, out + i, key, ctx->enc); \
+ return 1; \
+}
+
+#define IMPLEMENT_CIPHER_HW_CBC(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \
+static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \
+ unsigned char *out, \
+ const unsigned char *in, size_t len) \
+{ \
+ KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \
+ \
+ while (len >= MAXCHUNK) { \
+ FUNC_PREFIX##_encrypt(in, out, MAXCHUNK, key, ctx->iv, ctx->enc); \
+ len -= MAXCHUNK; \
+ in += MAXCHUNK; \
+ out += MAXCHUNK; \
+ } \
+ if (len > 0) \
+ FUNC_PREFIX##_encrypt(in, out, (long)len, key, ctx->iv, ctx->enc); \
+ return 1; \
+}
+
+#define IMPLEMENT_CIPHER_HW_CFB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \
+static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \
+ unsigned char *out, \
+ const unsigned char *in, size_t len) \
+{ \
+ size_t chunk = MAXCHUNK; \
+ KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \
+ int num = ctx->num; \
+ \
+ if (len < chunk) \
+ chunk = len; \
+ while (len > 0 && len >= chunk) { \
+ FUNC_PREFIX##_encrypt(in, out, (long)chunk, key, ctx->iv, &num, \
+ ctx->enc); \
+ len -= chunk; \
+ in += chunk; \
+ out += chunk; \
+ if (len < chunk) \
+ chunk = len; \
+ } \
+ ctx->num = num; \
+ return 1; \
+}
+
+#define IMPLEMENT_CIPHER_HW_COPYCTX(name, CTX_TYPE) \
+static void name(PROV_CIPHER_CTX *dst, const PROV_CIPHER_CTX *src) \
+{ \
+ CTX_TYPE *sctx = (CTX_TYPE *)src; \
+ CTX_TYPE *dctx = (CTX_TYPE *)dst; \
+ \
+ *dctx = *sctx; \
+ dst->ks = &dctx->ks.ks; \
+}
+
+#define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(name) \
+static const OSSL_PARAM name##_known_gettable_ctx_params[] = { \
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), \
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), \
+ OSSL_PARAM_uint(OSSL_CIPHER_PARAM_PADDING, NULL), \
+ OSSL_PARAM_uint(OSSL_CIPHER_PARAM_NUM, NULL), \
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0), \
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_UPDATED_IV, NULL, 0),
+
+#define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(name) \
+ OSSL_PARAM_END \
+}; \
+const OSSL_PARAM * name##_gettable_ctx_params(ossl_unused void *cctx, \
+ ossl_unused void *provctx) \
+{ \
+ return name##_known_gettable_ctx_params; \
+}
+
+#define CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(name) \
+static const OSSL_PARAM name##_known_settable_ctx_params[] = { \
+ OSSL_PARAM_uint(OSSL_CIPHER_PARAM_PADDING, NULL), \
+ OSSL_PARAM_uint(OSSL_CIPHER_PARAM_NUM, NULL),
+#define CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(name) \
+ OSSL_PARAM_END \
+}; \
+const OSSL_PARAM * name##_settable_ctx_params(ossl_unused void *cctx, \
+ ossl_unused void *provctx) \
+{ \
+ return name##_known_settable_ctx_params; \
+}
+
+int ossl_cipher_generic_initiv(PROV_CIPHER_CTX *ctx, const unsigned char *iv,
+ size_t ivlen);
+
+size_t ossl_cipher_fillblock(unsigned char *buf, size_t *buflen,
+ size_t blocksize,
+ const unsigned char **in, size_t *inlen);
+int ossl_cipher_trailingdata(unsigned char *buf, size_t *buflen,
+ size_t blocksize,
+ const unsigned char **in, size_t *inlen);
diff --git a/providers/implementations/include/prov/ciphercommon_aead.h b/providers/implementations/include/prov/ciphercommon_aead.h
new file mode 100644
index 000000000000..1d017175d320
--- /dev/null
+++ b/providers/implementations/include/prov/ciphercommon_aead.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#define UNINITIALISED_SIZET ((size_t)-1)
+
+#define AEAD_FLAGS (PROV_CIPHER_FLAG_AEAD | PROV_CIPHER_FLAG_CUSTOM_IV)
+
+#define IMPLEMENT_aead_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits) \
+static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lc##_get_params; \
+static int alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[]) \
+{ \
+ return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
+ flags, kbits, blkbits, ivbits); \
+} \
+static OSSL_FUNC_cipher_newctx_fn alg##kbits##lc##_newctx; \
+static void * alg##kbits##lc##_newctx(void *provctx) \
+{ \
+ return alg##_##lc##_newctx(provctx, kbits); \
+} \
+const OSSL_DISPATCH ossl_##alg##kbits##lc##_functions[] = { \
+ { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))alg##kbits##lc##_newctx }, \
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))alg##_##lc##_freectx }, \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_##lc##_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_##lc##_dinit }, \
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_##lc##_stream_update }, \
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_##lc##_stream_final }, \
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_##lc##_cipher }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, \
+ (void (*)(void)) alg##_##kbits##_##lc##_get_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
+ (void (*)(void)) ossl_##lc##_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void)) ossl_##lc##_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))ossl_cipher_generic_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_aead_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))ossl_cipher_aead_settable_ctx_params }, \
+ { 0, NULL } \
+}
diff --git a/providers/implementations/include/prov/ciphercommon_ccm.h b/providers/implementations/include/prov/ciphercommon_ccm.h
new file mode 100644
index 000000000000..4c184b395f44
--- /dev/null
+++ b/providers/implementations/include/prov/ciphercommon_ccm.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "ciphercommon_aead.h"
+
+typedef struct prov_ccm_hw_st PROV_CCM_HW;
+
+#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
+/*-
+ * KMAC-AES parameter block - begin
+ * (see z/Architecture Principles of Operation >= SA22-7832-08)
+ */
+typedef struct S390X_kmac_params_st {
+ union {
+ unsigned long long g[2];
+ unsigned char b[16];
+ } icv;
+ unsigned char k[32];
+} S390X_KMAC_PARAMS;
+/* KMAC-AES parameter block - end */
+#endif
+
+/* Base structure that is shared by AES & ARIA for CCM MODE */
+typedef struct prov_ccm_st {
+ unsigned int enc : 1;
+ unsigned int key_set : 1; /* Set if key initialised */
+ unsigned int iv_set : 1; /* Set if an iv is set */
+ unsigned int tag_set : 1; /* Set if tag is valid */
+ unsigned int len_set : 1; /* Set if message length set */
+ size_t l, m; /* L and M parameters from RFC3610 */
+ size_t keylen;
+ size_t tls_aad_len; /* TLS AAD length */
+ size_t tls_aad_pad_sz;
+ unsigned char iv[GENERIC_BLOCK_SIZE];
+ unsigned char buf[GENERIC_BLOCK_SIZE];
+ CCM128_CONTEXT ccm_ctx;
+ ccm128_f str;
+ const PROV_CCM_HW *hw; /* hardware specific methods */
+} PROV_CCM_CTX;
+
+PROV_CIPHER_FUNC(int, CCM_cipher, (PROV_CCM_CTX *ctx, unsigned char *out, \
+ size_t *padlen, const unsigned char *in, \
+ size_t len));
+PROV_CIPHER_FUNC(int, CCM_setkey, (PROV_CCM_CTX *ctx, \
+ const unsigned char *key, size_t keylen));
+PROV_CIPHER_FUNC(int, CCM_setiv, (PROV_CCM_CTX *dat, \
+ const unsigned char *iv, size_t ivlen, \
+ size_t mlen));
+PROV_CIPHER_FUNC(int, CCM_setaad, (PROV_CCM_CTX *ctx, \
+ const unsigned char *aad, size_t aadlen));
+PROV_CIPHER_FUNC(int, CCM_auth_encrypt, (PROV_CCM_CTX *ctx, \
+ const unsigned char *in, \
+ unsigned char *out, size_t len, \
+ unsigned char *tag, size_t taglen));
+PROV_CIPHER_FUNC(int, CCM_auth_decrypt, (PROV_CCM_CTX *ctx, \
+ const unsigned char *in, \
+ unsigned char *out, size_t len, \
+ unsigned char *tag, size_t taglen));
+PROV_CIPHER_FUNC(int, CCM_gettag, (PROV_CCM_CTX *ctx, \
+ unsigned char *tag, size_t taglen));
+
+/*
+ * CCM Mode internal method table used to handle hardware specific differences,
+ * (and different algorithms).
+ */
+struct prov_ccm_hw_st {
+ OSSL_CCM_setkey_fn setkey;
+ OSSL_CCM_setiv_fn setiv;
+ OSSL_CCM_setaad_fn setaad;
+ OSSL_CCM_auth_encrypt_fn auth_encrypt;
+ OSSL_CCM_auth_decrypt_fn auth_decrypt;
+ OSSL_CCM_gettag_fn gettag;
+};
+
+OSSL_FUNC_cipher_encrypt_init_fn ossl_ccm_einit;
+OSSL_FUNC_cipher_decrypt_init_fn ossl_ccm_dinit;
+OSSL_FUNC_cipher_get_ctx_params_fn ossl_ccm_get_ctx_params;
+OSSL_FUNC_cipher_set_ctx_params_fn ossl_ccm_set_ctx_params;
+OSSL_FUNC_cipher_update_fn ossl_ccm_stream_update;
+OSSL_FUNC_cipher_final_fn ossl_ccm_stream_final;
+OSSL_FUNC_cipher_cipher_fn ossl_ccm_cipher;
+void ossl_ccm_initctx(PROV_CCM_CTX *ctx, size_t keybits, const PROV_CCM_HW *hw);
+
+int ossl_ccm_generic_setiv(PROV_CCM_CTX *ctx, const unsigned char *nonce,
+ size_t nlen, size_t mlen);
+int ossl_ccm_generic_setaad(PROV_CCM_CTX *ctx, const unsigned char *aad,
+ size_t alen);
+int ossl_ccm_generic_gettag(PROV_CCM_CTX *ctx, unsigned char *tag, size_t tlen);
+int ossl_ccm_generic_auth_encrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
+ unsigned char *out, size_t len,
+ unsigned char *tag, size_t taglen);
+int ossl_ccm_generic_auth_decrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
+ unsigned char *out, size_t len,
+ unsigned char *expected_tag, size_t taglen);
diff --git a/providers/implementations/include/prov/ciphercommon_gcm.h b/providers/implementations/include/prov/ciphercommon_gcm.h
new file mode 100644
index 000000000000..7c4a548f9d44
--- /dev/null
+++ b/providers/implementations/include/prov/ciphercommon_gcm.h
@@ -0,0 +1,129 @@
+
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/aes.h>
+#include "ciphercommon_aead.h"
+
+typedef struct prov_gcm_hw_st PROV_GCM_HW;
+
+#define GCM_IV_DEFAULT_SIZE 12 /* IV's for AES_GCM should normally be 12 bytes */
+#define GCM_IV_MAX_SIZE (1024 / 8)
+#define GCM_TAG_MAX_SIZE 16
+
+#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
+/*-
+ * KMA-GCM-AES parameter block - begin
+ * (see z/Architecture Principles of Operation >= SA22-7832-11)
+ */
+typedef struct S390X_kma_params_st {
+ unsigned char reserved[12];
+ union {
+ unsigned int w;
+ unsigned char b[4];
+ } cv; /* 32 bit counter value */
+ union {
+ unsigned long long g[2];
+ unsigned char b[16];
+ } t; /* tag */
+ unsigned char h[16]; /* hash subkey */
+ unsigned long long taadl; /* total AAD length */
+ unsigned long long tpcl; /* total plaintxt/ciphertxt len */
+ union {
+ unsigned long long g[2];
+ unsigned int w[4];
+ } j0; /* initial counter value */
+ unsigned char k[32]; /* key */
+} S390X_KMA_PARAMS;
+
+#endif
+
+typedef struct prov_gcm_ctx_st {
+ unsigned int mode; /* The mode that we are using */
+ size_t keylen;
+ size_t ivlen;
+ size_t taglen;
+ size_t tls_aad_pad_sz;
+ size_t tls_aad_len; /* TLS AAD length */
+ uint64_t tls_enc_records; /* Number of TLS records encrypted */
+
+ /*
+ * num contains the number of bytes of |iv| which are valid for modes that
+ * manage partial blocks themselves.
+ */
+ size_t num;
+ size_t bufsz; /* Number of bytes in buf */
+ uint64_t flags;
+
+ unsigned int iv_state; /* set to one of IV_STATE_XXX */
+ unsigned int enc:1; /* Set to 1 if we are encrypting or 0 otherwise */
+ unsigned int pad:1; /* Whether padding should be used or not */
+ unsigned int key_set:1; /* Set if key initialised */
+ unsigned int iv_gen_rand:1; /* No IV was specified, so generate a rand IV */
+ unsigned int iv_gen:1; /* It is OK to generate IVs */
+
+ unsigned char iv[GCM_IV_MAX_SIZE]; /* Buffer to use for IV's */
+ unsigned char buf[AES_BLOCK_SIZE]; /* Buffer of partial blocks processed via update calls */
+
+ OSSL_LIB_CTX *libctx; /* needed for rand calls */
+ const PROV_GCM_HW *hw; /* hardware specific methods */
+ GCM128_CONTEXT gcm;
+ ctr128_f ctr;
+ const void *ks;
+} PROV_GCM_CTX;
+
+PROV_CIPHER_FUNC(int, GCM_setkey, (PROV_GCM_CTX *ctx, const unsigned char *key,
+ size_t keylen));
+PROV_CIPHER_FUNC(int, GCM_setiv, (PROV_GCM_CTX *dat, const unsigned char *iv,
+ size_t ivlen));
+PROV_CIPHER_FUNC(int, GCM_aadupdate, (PROV_GCM_CTX *ctx,
+ const unsigned char *aad, size_t aadlen));
+PROV_CIPHER_FUNC(int, GCM_cipherupdate, (PROV_GCM_CTX *ctx,
+ const unsigned char *in, size_t len,
+ unsigned char *out));
+PROV_CIPHER_FUNC(int, GCM_cipherfinal, (PROV_GCM_CTX *ctx, unsigned char *tag));
+PROV_CIPHER_FUNC(int, GCM_oneshot, (PROV_GCM_CTX *ctx, unsigned char *aad,
+ size_t aad_len, const unsigned char *in,
+ size_t in_len, unsigned char *out,
+ unsigned char *tag, size_t taglen));
+struct prov_gcm_hw_st {
+ OSSL_GCM_setkey_fn setkey;
+ OSSL_GCM_setiv_fn setiv;
+ OSSL_GCM_aadupdate_fn aadupdate;
+ OSSL_GCM_cipherupdate_fn cipherupdate;
+ OSSL_GCM_cipherfinal_fn cipherfinal;
+ OSSL_GCM_oneshot_fn oneshot;
+};
+
+OSSL_FUNC_cipher_encrypt_init_fn ossl_gcm_einit;
+OSSL_FUNC_cipher_decrypt_init_fn ossl_gcm_dinit;
+OSSL_FUNC_cipher_get_ctx_params_fn ossl_gcm_get_ctx_params;
+OSSL_FUNC_cipher_set_ctx_params_fn ossl_gcm_set_ctx_params;
+OSSL_FUNC_cipher_cipher_fn ossl_gcm_cipher;
+OSSL_FUNC_cipher_update_fn ossl_gcm_stream_update;
+OSSL_FUNC_cipher_final_fn ossl_gcm_stream_final;
+void ossl_gcm_initctx(void *provctx, PROV_GCM_CTX *ctx, size_t keybits,
+ const PROV_GCM_HW *hw);
+
+int ossl_gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, size_t ivlen);
+int ossl_gcm_aad_update(PROV_GCM_CTX *ctx, const unsigned char *aad,
+ size_t aad_len);
+int ossl_gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag);
+int ossl_gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len,
+ const unsigned char *in, size_t in_len,
+ unsigned char *out, unsigned char *tag, size_t tag_len);
+int ossl_gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
+ size_t len, unsigned char *out);
+
+#define GCM_HW_SET_KEY_CTR_FN(ks, fn_set_enc_key, fn_block, fn_ctr) \
+ ctx->ks = ks; \
+ fn_set_enc_key(key, keylen * 8, ks); \
+ CRYPTO_gcm128_init(&ctx->gcm, ks, (block128_f)fn_block); \
+ ctx->ctr = (ctr128_f)fn_ctr; \
+ ctx->key_set = 1;
diff --git a/providers/implementations/include/prov/digestcommon.h b/providers/implementations/include/prov/digestcommon.h
new file mode 100644
index 000000000000..abdb8bb2ad55
--- /dev/null
+++ b/providers/implementations/include/prov/digestcommon.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_PROVIDERS_DIGESTCOMMON_H
+# define OSSL_PROVIDERS_DIGESTCOMMON_H
+
+# include <openssl/core_dispatch.h>
+# include <openssl/core_names.h>
+# include <openssl/params.h>
+# include "prov/providercommon.h"
+
+/* Internal flags that can be queried */
+#define PROV_DIGEST_FLAG_XOF 0x0001
+#define PROV_DIGEST_FLAG_ALGID_ABSENT 0x0002
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+#define PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags) \
+static OSSL_FUNC_digest_get_params_fn name##_get_params; \
+static int name##_get_params(OSSL_PARAM params[]) \
+{ \
+ return ossl_digest_default_get_params(params, blksize, dgstsize, flags); \
+}
+
+#define PROV_DISPATCH_FUNC_DIGEST_GET_PARAMS(name) \
+{ OSSL_FUNC_DIGEST_GET_PARAMS, (void (*)(void))name##_get_params }, \
+{ OSSL_FUNC_DIGEST_GETTABLE_PARAMS, \
+ (void (*)(void))ossl_digest_default_gettable_params }
+
+# define PROV_FUNC_DIGEST_FINAL(name, dgstsize, fin) \
+static OSSL_FUNC_digest_final_fn name##_internal_final; \
+static int name##_internal_final(void *ctx, unsigned char *out, size_t *outl, \
+ size_t outsz) \
+{ \
+ if (ossl_prov_is_running() && outsz >= dgstsize && fin(out, ctx)) { \
+ *outl = dgstsize; \
+ return 1; \
+ } \
+ return 0; \
+}
+
+# define PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_START( \
+ name, CTX, blksize, dgstsize, flags, upd, fin) \
+static OSSL_FUNC_digest_newctx_fn name##_newctx; \
+static OSSL_FUNC_digest_freectx_fn name##_freectx; \
+static OSSL_FUNC_digest_dupctx_fn name##_dupctx; \
+static void *name##_newctx(void *prov_ctx) \
+{ \
+ CTX *ctx = ossl_prov_is_running() ? OPENSSL_zalloc(sizeof(*ctx)) : NULL; \
+ return ctx; \
+} \
+static void name##_freectx(void *vctx) \
+{ \
+ CTX *ctx = (CTX *)vctx; \
+ OPENSSL_clear_free(ctx, sizeof(*ctx)); \
+} \
+static void *name##_dupctx(void *ctx) \
+{ \
+ CTX *in = (CTX *)ctx; \
+ CTX *ret = ossl_prov_is_running() ? OPENSSL_malloc(sizeof(*ret)) : NULL; \
+ if (ret != NULL) \
+ *ret = *in; \
+ return ret; \
+} \
+PROV_FUNC_DIGEST_FINAL(name, dgstsize, fin) \
+PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags) \
+const OSSL_DISPATCH ossl_##name##_functions[] = { \
+ { OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))name##_newctx }, \
+ { OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))upd }, \
+ { OSSL_FUNC_DIGEST_FINAL, (void (*)(void))name##_internal_final }, \
+ { OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))name##_freectx }, \
+ { OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))name##_dupctx }, \
+ PROV_DISPATCH_FUNC_DIGEST_GET_PARAMS(name)
+
+# define PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END \
+ { 0, NULL } \
+};
+
+# define IMPLEMENT_digest_functions( \
+ name, CTX, blksize, dgstsize, flags, init, upd, fin) \
+static OSSL_FUNC_digest_init_fn name##_internal_init; \
+static int name##_internal_init(void *ctx, \
+ ossl_unused const OSSL_PARAM params[]) \
+{ \
+ return ossl_prov_is_running() && init(ctx); \
+} \
+PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_START(name, CTX, blksize, dgstsize, flags, \
+ upd, fin), \
+ { OSSL_FUNC_DIGEST_INIT, (void (*)(void))name##_internal_init }, \
+PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END
+
+# define IMPLEMENT_digest_functions_with_settable_ctx( \
+ name, CTX, blksize, dgstsize, flags, init, upd, fin, \
+ settable_ctx_params, set_ctx_params) \
+static OSSL_FUNC_digest_init_fn name##_internal_init; \
+static int name##_internal_init(void *ctx, const OSSL_PARAM params[]) \
+{ \
+ return ossl_prov_is_running() \
+ && init(ctx) \
+ && set_ctx_params(ctx, params); \
+} \
+PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_START(name, CTX, blksize, dgstsize, flags, \
+ upd, fin), \
+ { OSSL_FUNC_DIGEST_INIT, (void (*)(void))name##_internal_init }, \
+ { OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS, (void (*)(void))settable_ctx_params }, \
+ { OSSL_FUNC_DIGEST_SET_CTX_PARAMS, (void (*)(void))set_ctx_params }, \
+PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END
+
+
+const OSSL_PARAM *ossl_digest_default_gettable_params(void *provctx);
+int ossl_digest_default_get_params(OSSL_PARAM params[], size_t blksz,
+ size_t paramsz, unsigned long flags);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif /* OSSL_PROVIDERS_DIGESTCOMMON_H */
diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h
new file mode 100644
index 000000000000..3f6dd7ee16b6
--- /dev/null
+++ b/providers/implementations/include/prov/implementations.h
@@ -0,0 +1,517 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core.h>
+#include <openssl/types.h>
+
+/* Digests */
+extern const OSSL_DISPATCH ossl_sha1_functions[];
+extern const OSSL_DISPATCH ossl_sha224_functions[];
+extern const OSSL_DISPATCH ossl_sha256_functions[];
+extern const OSSL_DISPATCH ossl_sha384_functions[];
+extern const OSSL_DISPATCH ossl_sha512_functions[];
+extern const OSSL_DISPATCH ossl_sha512_224_functions[];
+extern const OSSL_DISPATCH ossl_sha512_256_functions[];
+extern const OSSL_DISPATCH ossl_sha3_224_functions[];
+extern const OSSL_DISPATCH ossl_sha3_256_functions[];
+extern const OSSL_DISPATCH ossl_sha3_384_functions[];
+extern const OSSL_DISPATCH ossl_sha3_512_functions[];
+extern const OSSL_DISPATCH ossl_keccak_kmac_128_functions[];
+extern const OSSL_DISPATCH ossl_keccak_kmac_256_functions[];
+extern const OSSL_DISPATCH ossl_shake_128_functions[];
+extern const OSSL_DISPATCH ossl_shake_256_functions[];
+extern const OSSL_DISPATCH ossl_blake2s256_functions[];
+extern const OSSL_DISPATCH ossl_blake2b512_functions[];
+extern const OSSL_DISPATCH ossl_md5_functions[];
+extern const OSSL_DISPATCH ossl_md5_sha1_functions[];
+extern const OSSL_DISPATCH ossl_sm3_functions[];
+extern const OSSL_DISPATCH ossl_md2_functions[];
+extern const OSSL_DISPATCH ossl_md4_functions[];
+extern const OSSL_DISPATCH ossl_mdc2_functions[];
+extern const OSSL_DISPATCH ossl_wp_functions[];
+extern const OSSL_DISPATCH ossl_ripemd160_functions[];
+extern const OSSL_DISPATCH ossl_nullmd_functions[];
+
+/* Ciphers */
+extern const OSSL_DISPATCH ossl_null_functions[];
+extern const OSSL_DISPATCH ossl_aes256ecb_functions[];
+extern const OSSL_DISPATCH ossl_aes192ecb_functions[];
+extern const OSSL_DISPATCH ossl_aes128ecb_functions[];
+extern const OSSL_DISPATCH ossl_aes256cbc_functions[];
+extern const OSSL_DISPATCH ossl_aes192cbc_functions[];
+extern const OSSL_DISPATCH ossl_aes128cbc_functions[];
+extern const OSSL_DISPATCH ossl_aes256cbc_cts_functions[];
+extern const OSSL_DISPATCH ossl_aes192cbc_cts_functions[];
+extern const OSSL_DISPATCH ossl_aes128cbc_cts_functions[];
+extern const OSSL_DISPATCH ossl_aes256ofb_functions[];
+extern const OSSL_DISPATCH ossl_aes192ofb_functions[];
+extern const OSSL_DISPATCH ossl_aes128ofb_functions[];
+extern const OSSL_DISPATCH ossl_aes256cfb_functions[];
+extern const OSSL_DISPATCH ossl_aes192cfb_functions[];
+extern const OSSL_DISPATCH ossl_aes128cfb_functions[];
+extern const OSSL_DISPATCH ossl_aes256cfb1_functions[];
+extern const OSSL_DISPATCH ossl_aes192cfb1_functions[];
+extern const OSSL_DISPATCH ossl_aes128cfb1_functions[];
+extern const OSSL_DISPATCH ossl_aes256cfb8_functions[];
+extern const OSSL_DISPATCH ossl_aes192cfb8_functions[];
+extern const OSSL_DISPATCH ossl_aes128cfb8_functions[];
+extern const OSSL_DISPATCH ossl_aes256ctr_functions[];
+extern const OSSL_DISPATCH ossl_aes192ctr_functions[];
+extern const OSSL_DISPATCH ossl_aes128ctr_functions[];
+extern const OSSL_DISPATCH ossl_aes256xts_functions[];
+extern const OSSL_DISPATCH ossl_aes128xts_functions[];
+#ifndef OPENSSL_NO_OCB
+extern const OSSL_DISPATCH ossl_aes256ocb_functions[];
+extern const OSSL_DISPATCH ossl_aes192ocb_functions[];
+extern const OSSL_DISPATCH ossl_aes128ocb_functions[];
+#endif /* OPENSSL_NO_OCB */
+extern const OSSL_DISPATCH ossl_aes256gcm_functions[];
+extern const OSSL_DISPATCH ossl_aes192gcm_functions[];
+extern const OSSL_DISPATCH ossl_aes128gcm_functions[];
+extern const OSSL_DISPATCH ossl_aes256ccm_functions[];
+extern const OSSL_DISPATCH ossl_aes192ccm_functions[];
+extern const OSSL_DISPATCH ossl_aes128ccm_functions[];
+extern const OSSL_DISPATCH ossl_aes256wrap_functions[];
+extern const OSSL_DISPATCH ossl_aes192wrap_functions[];
+extern const OSSL_DISPATCH ossl_aes128wrap_functions[];
+extern const OSSL_DISPATCH ossl_aes256wrappad_functions[];
+extern const OSSL_DISPATCH ossl_aes192wrappad_functions[];
+extern const OSSL_DISPATCH ossl_aes128wrappad_functions[];
+extern const OSSL_DISPATCH ossl_aes256wrapinv_functions[];
+extern const OSSL_DISPATCH ossl_aes192wrapinv_functions[];
+extern const OSSL_DISPATCH ossl_aes128wrapinv_functions[];
+extern const OSSL_DISPATCH ossl_aes256wrappadinv_functions[];
+extern const OSSL_DISPATCH ossl_aes192wrappadinv_functions[];
+extern const OSSL_DISPATCH ossl_aes128wrappadinv_functions[];
+extern const OSSL_DISPATCH ossl_aes256cbc_hmac_sha1_functions[];
+extern const OSSL_DISPATCH ossl_aes128cbc_hmac_sha1_functions[];
+extern const OSSL_DISPATCH ossl_aes256cbc_hmac_sha256_functions[];
+extern const OSSL_DISPATCH ossl_aes128cbc_hmac_sha256_functions[];
+
+#ifndef OPENSSL_NO_ARIA
+extern const OSSL_DISPATCH ossl_aria256gcm_functions[];
+extern const OSSL_DISPATCH ossl_aria192gcm_functions[];
+extern const OSSL_DISPATCH ossl_aria128gcm_functions[];
+extern const OSSL_DISPATCH ossl_aria256ccm_functions[];
+extern const OSSL_DISPATCH ossl_aria192ccm_functions[];
+extern const OSSL_DISPATCH ossl_aria128ccm_functions[];
+extern const OSSL_DISPATCH ossl_aria256ecb_functions[];
+extern const OSSL_DISPATCH ossl_aria192ecb_functions[];
+extern const OSSL_DISPATCH ossl_aria128ecb_functions[];
+extern const OSSL_DISPATCH ossl_aria256cbc_functions[];
+extern const OSSL_DISPATCH ossl_aria192cbc_functions[];
+extern const OSSL_DISPATCH ossl_aria128cbc_functions[];
+extern const OSSL_DISPATCH ossl_aria256ofb_functions[];
+extern const OSSL_DISPATCH ossl_aria192ofb_functions[];
+extern const OSSL_DISPATCH ossl_aria128ofb_functions[];
+extern const OSSL_DISPATCH ossl_aria256cfb_functions[];
+extern const OSSL_DISPATCH ossl_aria192cfb_functions[];
+extern const OSSL_DISPATCH ossl_aria128cfb_functions[];
+extern const OSSL_DISPATCH ossl_aria256cfb1_functions[];
+extern const OSSL_DISPATCH ossl_aria192cfb1_functions[];
+extern const OSSL_DISPATCH ossl_aria128cfb1_functions[];
+extern const OSSL_DISPATCH ossl_aria256cfb8_functions[];
+extern const OSSL_DISPATCH ossl_aria192cfb8_functions[];
+extern const OSSL_DISPATCH ossl_aria128cfb8_functions[];
+extern const OSSL_DISPATCH ossl_aria256ctr_functions[];
+extern const OSSL_DISPATCH ossl_aria192ctr_functions[];
+extern const OSSL_DISPATCH ossl_aria128ctr_functions[];
+#endif /* OPENSSL_NO_ARIA */
+#ifndef OPENSSL_NO_CAMELLIA
+extern const OSSL_DISPATCH ossl_camellia256ecb_functions[];
+extern const OSSL_DISPATCH ossl_camellia192ecb_functions[];
+extern const OSSL_DISPATCH ossl_camellia128ecb_functions[];
+extern const OSSL_DISPATCH ossl_camellia256cbc_functions[];
+extern const OSSL_DISPATCH ossl_camellia192cbc_functions[];
+extern const OSSL_DISPATCH ossl_camellia128cbc_functions[];
+extern const OSSL_DISPATCH ossl_camellia256cbc_cts_functions[];
+extern const OSSL_DISPATCH ossl_camellia192cbc_cts_functions[];
+extern const OSSL_DISPATCH ossl_camellia128cbc_cts_functions[];
+extern const OSSL_DISPATCH ossl_camellia256ofb_functions[];
+extern const OSSL_DISPATCH ossl_camellia192ofb_functions[];
+extern const OSSL_DISPATCH ossl_camellia128ofb_functions[];
+extern const OSSL_DISPATCH ossl_camellia256cfb_functions[];
+extern const OSSL_DISPATCH ossl_camellia192cfb_functions[];
+extern const OSSL_DISPATCH ossl_camellia128cfb_functions[];
+extern const OSSL_DISPATCH ossl_camellia256cfb1_functions[];
+extern const OSSL_DISPATCH ossl_camellia192cfb1_functions[];
+extern const OSSL_DISPATCH ossl_camellia128cfb1_functions[];
+extern const OSSL_DISPATCH ossl_camellia256cfb8_functions[];
+extern const OSSL_DISPATCH ossl_camellia192cfb8_functions[];
+extern const OSSL_DISPATCH ossl_camellia128cfb8_functions[];
+extern const OSSL_DISPATCH ossl_camellia256ctr_functions[];
+extern const OSSL_DISPATCH ossl_camellia192ctr_functions[];
+extern const OSSL_DISPATCH ossl_camellia128ctr_functions[];
+#endif /* OPENSSL_NO_CAMELLIA */
+#ifndef OPENSSL_NO_BF
+extern const OSSL_DISPATCH ossl_blowfish128ecb_functions[];
+extern const OSSL_DISPATCH ossl_blowfish128cbc_functions[];
+extern const OSSL_DISPATCH ossl_blowfish128ofb64_functions[];
+extern const OSSL_DISPATCH ossl_blowfish128cfb64_functions[];
+#endif /* OPENSSL_NO_BF */
+#ifndef OPENSSL_NO_IDEA
+extern const OSSL_DISPATCH ossl_idea128ecb_functions[];
+extern const OSSL_DISPATCH ossl_idea128cbc_functions[];
+extern const OSSL_DISPATCH ossl_idea128ofb64_functions[];
+extern const OSSL_DISPATCH ossl_idea128cfb64_functions[];
+#endif /* OPENSSL_NO_IDEA */
+#ifndef OPENSSL_NO_CAST
+extern const OSSL_DISPATCH ossl_cast5128ecb_functions[];
+extern const OSSL_DISPATCH ossl_cast5128cbc_functions[];
+extern const OSSL_DISPATCH ossl_cast5128ofb64_functions[];
+extern const OSSL_DISPATCH ossl_cast5128cfb64_functions[];
+#endif /* OPENSSL_NO_CAST */
+#ifndef OPENSSL_NO_SEED
+extern const OSSL_DISPATCH ossl_seed128ecb_functions[];
+extern const OSSL_DISPATCH ossl_seed128cbc_functions[];
+extern const OSSL_DISPATCH ossl_seed128ofb128_functions[];
+extern const OSSL_DISPATCH ossl_seed128cfb128_functions[];
+#endif /* OPENSSL_NO_SEED */
+#ifndef OPENSSL_NO_SM4
+extern const OSSL_DISPATCH ossl_sm4128ecb_functions[];
+extern const OSSL_DISPATCH ossl_sm4128cbc_functions[];
+extern const OSSL_DISPATCH ossl_sm4128ctr_functions[];
+extern const OSSL_DISPATCH ossl_sm4128ofb128_functions[];
+extern const OSSL_DISPATCH ossl_sm4128cfb128_functions[];
+#endif /* OPENSSL_NO_SM4 */
+#ifndef OPENSSL_NO_RC5
+extern const OSSL_DISPATCH ossl_rc5128ecb_functions[];
+extern const OSSL_DISPATCH ossl_rc5128cbc_functions[];
+extern const OSSL_DISPATCH ossl_rc5128ofb64_functions[];
+extern const OSSL_DISPATCH ossl_rc5128cfb64_functions[];
+#endif /* OPENSSL_NO_RC5 */
+#ifndef OPENSSL_NO_RC2
+extern const OSSL_DISPATCH ossl_rc2128ecb_functions[];
+extern const OSSL_DISPATCH ossl_rc2128cbc_functions[];
+extern const OSSL_DISPATCH ossl_rc240cbc_functions[];
+extern const OSSL_DISPATCH ossl_rc264cbc_functions[];
+extern const OSSL_DISPATCH ossl_rc2128cfb128_functions[];
+extern const OSSL_DISPATCH ossl_rc2128ofb128_functions[];
+#endif /* OPENSSL_NO_RC2 */
+#ifndef OPENSSL_NO_DES
+extern const OSSL_DISPATCH ossl_tdes_ede3_ecb_functions[];
+extern const OSSL_DISPATCH ossl_tdes_ede3_cbc_functions[];
+# ifndef FIPS_MODULE
+extern const OSSL_DISPATCH ossl_tdes_ede3_ofb_functions[];
+extern const OSSL_DISPATCH ossl_tdes_ede3_cfb_functions[];
+extern const OSSL_DISPATCH ossl_tdes_ede3_cfb8_functions[];
+extern const OSSL_DISPATCH ossl_tdes_ede3_cfb1_functions[];
+
+extern const OSSL_DISPATCH ossl_tdes_ede2_ecb_functions[];
+extern const OSSL_DISPATCH ossl_tdes_ede2_cbc_functions[];
+extern const OSSL_DISPATCH ossl_tdes_ede2_ofb_functions[];
+extern const OSSL_DISPATCH ossl_tdes_ede2_cfb_functions[];
+
+extern const OSSL_DISPATCH ossl_tdes_desx_cbc_functions[];
+extern const OSSL_DISPATCH ossl_tdes_wrap_cbc_functions[];
+
+extern const OSSL_DISPATCH ossl_des_ecb_functions[];
+extern const OSSL_DISPATCH ossl_des_cbc_functions[];
+extern const OSSL_DISPATCH ossl_des_ofb64_functions[];
+extern const OSSL_DISPATCH ossl_des_cfb64_functions[];
+extern const OSSL_DISPATCH ossl_des_cfb1_functions[];
+extern const OSSL_DISPATCH ossl_des_cfb8_functions[];
+# endif /* FIPS_MODULE */
+#endif /* OPENSSL_NO_DES */
+
+#ifndef OPENSSL_NO_RC4
+extern const OSSL_DISPATCH ossl_rc440_functions[];
+extern const OSSL_DISPATCH ossl_rc4128_functions[];
+# ifndef OPENSSL_NO_MD5
+extern const OSSL_DISPATCH ossl_rc4_hmac_ossl_md5_functions[];
+# endif /* OPENSSL_NO_MD5 */
+#endif /* OPENSSL_NO_RC4 */
+#ifndef OPENSSL_NO_CHACHA
+extern const OSSL_DISPATCH ossl_chacha20_functions[];
+# ifndef OPENSSL_NO_POLY1305
+extern const OSSL_DISPATCH ossl_chacha20_ossl_poly1305_functions[];
+# endif /* OPENSSL_NO_POLY1305 */
+#endif /* OPENSSL_NO_CHACHA */
+
+
+#ifndef OPENSSL_NO_SIV
+extern const OSSL_DISPATCH ossl_aes128siv_functions[];
+extern const OSSL_DISPATCH ossl_aes192siv_functions[];
+extern const OSSL_DISPATCH ossl_aes256siv_functions[];
+#endif /* OPENSSL_NO_SIV */
+
+/* MACs */
+extern const OSSL_DISPATCH ossl_blake2bmac_functions[];
+extern const OSSL_DISPATCH ossl_blake2smac_functions[];
+extern const OSSL_DISPATCH ossl_cmac_functions[];
+extern const OSSL_DISPATCH ossl_gmac_functions[];
+extern const OSSL_DISPATCH ossl_hmac_functions[];
+extern const OSSL_DISPATCH ossl_kmac128_functions[];
+extern const OSSL_DISPATCH ossl_kmac256_functions[];
+extern const OSSL_DISPATCH ossl_siphash_functions[];
+extern const OSSL_DISPATCH ossl_poly1305_functions[];
+
+/* KDFs / PRFs */
+extern const OSSL_DISPATCH ossl_kdf_pbkdf1_functions[];
+extern const OSSL_DISPATCH ossl_kdf_pbkdf2_functions[];
+extern const OSSL_DISPATCH ossl_kdf_pkcs12_functions[];
+#ifndef OPENSSL_NO_SCRYPT
+extern const OSSL_DISPATCH ossl_kdf_scrypt_functions[];
+#endif
+extern const OSSL_DISPATCH ossl_kdf_tls1_prf_functions[];
+extern const OSSL_DISPATCH ossl_kdf_hkdf_functions[];
+extern const OSSL_DISPATCH ossl_kdf_tls1_3_kdf_functions[];
+extern const OSSL_DISPATCH ossl_kdf_sshkdf_functions[];
+extern const OSSL_DISPATCH ossl_kdf_sskdf_functions[];
+extern const OSSL_DISPATCH ossl_kdf_x963_kdf_functions[];
+extern const OSSL_DISPATCH ossl_kdf_kbkdf_functions[];
+extern const OSSL_DISPATCH ossl_kdf_x942_kdf_functions[];
+extern const OSSL_DISPATCH ossl_kdf_krb5kdf_functions[];
+
+/* RNGs */
+extern const OSSL_DISPATCH ossl_test_rng_functions[];
+extern const OSSL_DISPATCH ossl_seed_src_functions[];
+extern const OSSL_DISPATCH ossl_drbg_hash_functions[];
+extern const OSSL_DISPATCH ossl_drbg_ossl_hmac_functions[];
+extern const OSSL_DISPATCH ossl_drbg_ctr_functions[];
+extern const OSSL_DISPATCH crngt_functions[];
+
+/* Key management */
+extern const OSSL_DISPATCH ossl_dh_keymgmt_functions[];
+extern const OSSL_DISPATCH ossl_dhx_keymgmt_functions[];
+extern const OSSL_DISPATCH ossl_dsa_keymgmt_functions[];
+extern const OSSL_DISPATCH ossl_rsa_keymgmt_functions[];
+extern const OSSL_DISPATCH ossl_rsapss_keymgmt_functions[];
+extern const OSSL_DISPATCH ossl_x25519_keymgmt_functions[];
+extern const OSSL_DISPATCH ossl_x448_keymgmt_functions[];
+extern const OSSL_DISPATCH ossl_ed25519_keymgmt_functions[];
+extern const OSSL_DISPATCH ossl_ed448_keymgmt_functions[];
+extern const OSSL_DISPATCH ossl_ec_keymgmt_functions[];
+extern const OSSL_DISPATCH ossl_kdf_keymgmt_functions[];
+extern const OSSL_DISPATCH ossl_mac_legacy_keymgmt_functions[];
+extern const OSSL_DISPATCH ossl_cmac_legacy_keymgmt_functions[];
+#ifndef OPENSSL_NO_SM2
+extern const OSSL_DISPATCH ossl_sm2_keymgmt_functions[];
+#endif
+
+/* Key Exchange */
+extern const OSSL_DISPATCH ossl_dh_keyexch_functions[];
+extern const OSSL_DISPATCH ossl_x25519_keyexch_functions[];
+extern const OSSL_DISPATCH ossl_x448_keyexch_functions[];
+extern const OSSL_DISPATCH ossl_ecdh_keyexch_functions[];
+extern const OSSL_DISPATCH ossl_kdf_tls1_prf_keyexch_functions[];
+extern const OSSL_DISPATCH ossl_kdf_hkdf_keyexch_functions[];
+extern const OSSL_DISPATCH ossl_kdf_scrypt_keyexch_functions[];
+
+/* Signature */
+extern const OSSL_DISPATCH ossl_dsa_signature_functions[];
+extern const OSSL_DISPATCH ossl_rsa_signature_functions[];
+extern const OSSL_DISPATCH ossl_ed25519_signature_functions[];
+extern const OSSL_DISPATCH ossl_ed448_signature_functions[];
+extern const OSSL_DISPATCH ossl_ecdsa_signature_functions[];
+extern const OSSL_DISPATCH ossl_mac_legacy_hmac_signature_functions[];
+extern const OSSL_DISPATCH ossl_mac_legacy_siphash_signature_functions[];
+extern const OSSL_DISPATCH ossl_mac_legacy_poly1305_signature_functions[];
+extern const OSSL_DISPATCH ossl_mac_legacy_cmac_signature_functions[];
+extern const OSSL_DISPATCH ossl_sm2_signature_functions[];
+
+/* Asym Cipher */
+extern const OSSL_DISPATCH ossl_rsa_asym_cipher_functions[];
+#ifndef OPENSSL_NO_SM2
+extern const OSSL_DISPATCH ossl_sm2_asym_cipher_functions[];
+#endif
+
+/* Asym Key encapsulation */
+extern const OSSL_DISPATCH ossl_rsa_asym_kem_functions[];
+
+/* Encoders */
+extern const OSSL_DISPATCH ossl_rsa_to_PKCS1_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsa_to_PKCS1_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsa_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsa_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsa_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsa_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsa_to_RSA_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsa_to_RSA_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsa_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsa_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsa_to_msblob_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsa_to_pvk_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsa_to_text_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsa_to_type_specific_keypair_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsa_to_type_specific_keypair_pem_encoder_functions[];
+
+extern const OSSL_DISPATCH ossl_rsapss_to_PKCS1_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsapss_to_PKCS1_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsapss_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsapss_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsapss_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsapss_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsapss_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsapss_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_rsapss_to_text_encoder_functions[];
+
+extern const OSSL_DISPATCH ossl_dh_to_DH_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dh_to_DH_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dh_to_PKCS3_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dh_to_PKCS3_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dh_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dh_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dh_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dh_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dh_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dh_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dh_to_type_specific_params_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dh_to_type_specific_params_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dh_to_text_encoder_functions[];
+
+extern const OSSL_DISPATCH ossl_dhx_to_DHX_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dhx_to_DHX_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dhx_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dhx_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dhx_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dhx_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dhx_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dhx_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dhx_to_X9_42_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dhx_to_X9_42_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dhx_to_type_specific_params_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dhx_to_type_specific_params_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dhx_to_text_encoder_functions[];
+
+extern const OSSL_DISPATCH ossl_dsa_to_DSA_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dsa_to_DSA_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dsa_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dsa_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dsa_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dsa_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dsa_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dsa_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dsa_to_type_specific_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dsa_to_type_specific_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dsa_to_msblob_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dsa_to_pvk_encoder_functions[];
+extern const OSSL_DISPATCH ossl_dsa_to_text_encoder_functions[];
+
+extern const OSSL_DISPATCH ossl_ec_to_EC_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ec_to_EC_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ec_to_blob_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ec_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ec_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ec_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ec_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ec_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ec_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ec_to_X9_62_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ec_to_X9_62_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ec_to_type_specific_no_pub_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ec_to_type_specific_no_pub_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ec_to_text_encoder_functions[];
+
+#ifndef OPENSSL_NO_SM2
+extern const OSSL_DISPATCH ossl_sm2_to_SM2_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_sm2_to_SM2_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_sm2_to_blob_encoder_functions[];
+extern const OSSL_DISPATCH ossl_sm2_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_sm2_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_sm2_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_sm2_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_sm2_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_sm2_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_sm2_to_type_specific_no_pub_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_sm2_to_type_specific_no_pub_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_sm2_to_text_encoder_functions[];
+#endif
+
+extern const OSSL_DISPATCH ossl_ed25519_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ed25519_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ed25519_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ed25519_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ed25519_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ed25519_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ed25519_to_OSSL_current_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ed25519_to_text_encoder_functions[];
+
+extern const OSSL_DISPATCH ossl_ed448_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ed448_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ed448_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ed448_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ed448_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ed448_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ed448_to_OSSL_current_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_ed448_to_text_encoder_functions[];
+
+extern const OSSL_DISPATCH ossl_x25519_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_x25519_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_x25519_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_x25519_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_x25519_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_x25519_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_x25519_to_OSSL_current_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_x25519_to_text_encoder_functions[];
+
+extern const OSSL_DISPATCH ossl_x448_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_x448_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_x448_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_x448_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_x448_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_x448_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_x448_to_OSSL_current_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_x448_to_text_encoder_functions[];
+
+/* Decoders */
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_dh_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_dh_decoder_functions[];
+extern const OSSL_DISPATCH ossl_type_specific_params_der_to_dh_decoder_functions[];
+extern const OSSL_DISPATCH ossl_DH_der_to_dh_decoder_functions[];
+
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_dhx_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_dhx_decoder_functions[];
+extern const OSSL_DISPATCH ossl_type_specific_params_der_to_dhx_decoder_functions[];
+extern const OSSL_DISPATCH ossl_DHX_der_to_dhx_decoder_functions[];
+
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_dsa_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_dsa_decoder_functions[];
+extern const OSSL_DISPATCH ossl_type_specific_der_to_dsa_decoder_functions[];
+extern const OSSL_DISPATCH ossl_DSA_der_to_dsa_decoder_functions[];
+extern const OSSL_DISPATCH ossl_msblob_to_dsa_decoder_functions[];
+extern const OSSL_DISPATCH ossl_pvk_to_dsa_decoder_functions[];
+
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_ec_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_ec_decoder_functions[];
+extern const OSSL_DISPATCH ossl_type_specific_no_pub_der_to_ec_decoder_functions[];
+extern const OSSL_DISPATCH ossl_EC_der_to_ec_decoder_functions[];
+
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_x25519_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_x25519_decoder_functions[];
+
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_x448_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_x448_decoder_functions[];
+
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_ed25519_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_ed25519_decoder_functions[];
+
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_ed448_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_ed448_decoder_functions[];
+
+#ifndef OPENSSL_NO_SM2
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_sm2_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_sm2_decoder_functions[];
+#endif
+
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_rsa_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_rsa_decoder_functions[];
+extern const OSSL_DISPATCH ossl_type_specific_keypair_der_to_rsa_decoder_functions[];
+extern const OSSL_DISPATCH ossl_RSA_der_to_rsa_decoder_functions[];
+extern const OSSL_DISPATCH ossl_msblob_to_rsa_decoder_functions[];
+extern const OSSL_DISPATCH ossl_pvk_to_rsa_decoder_functions[];
+
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_rsapss_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_rsapss_decoder_functions[];
+
+extern const OSSL_DISPATCH ossl_EncryptedPrivateKeyInfo_der_to_der_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_der_decoder_functions[];
+extern const OSSL_DISPATCH ossl_pem_to_der_decoder_functions[];
+
+extern const OSSL_DISPATCH ossl_file_store_functions[];
diff --git a/providers/implementations/include/prov/kdfexchange.h b/providers/implementations/include/prov/kdfexchange.h
new file mode 100644
index 000000000000..bfedd3afd364
--- /dev/null
+++ b/providers/implementations/include/prov/kdfexchange.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include <openssl/crypto.h>
+#include "internal/refcount.h"
+
+struct kdf_data_st {
+ OSSL_LIB_CTX *libctx;
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+};
+
+typedef struct kdf_data_st KDF_DATA;
+
+KDF_DATA *ossl_kdf_data_new(void *provctx);
+void ossl_kdf_data_free(KDF_DATA *kdfdata);
+int ossl_kdf_data_up_ref(KDF_DATA *kdfdata);
diff --git a/providers/implementations/include/prov/macsignature.h b/providers/implementations/include/prov/macsignature.h
new file mode 100644
index 000000000000..9bfaaf9b6e63
--- /dev/null
+++ b/providers/implementations/include/prov/macsignature.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include <openssl/crypto.h>
+#include "internal/refcount.h"
+#include "prov/provider_util.h"
+
+struct mac_key_st {
+ CRYPTO_RWLOCK *lock;
+ OSSL_LIB_CTX *libctx;
+ CRYPTO_REF_COUNT refcnt;
+ unsigned char *priv_key;
+ size_t priv_key_len;
+ PROV_CIPHER cipher;
+ char *properties;
+ int cmac;
+};
+
+typedef struct mac_key_st MAC_KEY;
+
+MAC_KEY *ossl_mac_key_new(OSSL_LIB_CTX *libctx, int cmac);
+void ossl_mac_key_free(MAC_KEY *mackey);
+int ossl_mac_key_up_ref(MAC_KEY *mackey);
diff --git a/providers/implementations/include/prov/md5_sha1.h b/providers/implementations/include/prov/md5_sha1.h
new file mode 100644
index 000000000000..181267d6b19f
--- /dev/null
+++ b/providers/implementations/include/prov/md5_sha1.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_PROV_MD5_SHA1_H
+# define OSSL_PROV_MD5_SHA1_H
+
+# include <openssl/opensslconf.h>
+
+# ifndef OPENSSL_NO_MD5
+# include <openssl/e_os2.h>
+# include <stddef.h>
+# include <openssl/md5.h>
+# include <openssl/sha.h>
+
+# define MD5_SHA1_DIGEST_LENGTH (MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH)
+# define MD5_SHA1_CBLOCK MD5_CBLOCK
+
+typedef struct md5_sha1_st {
+ MD5_CTX md5;
+ SHA_CTX sha1;
+} MD5_SHA1_CTX;
+
+int ossl_md5_sha1_init(MD5_SHA1_CTX *mctx);
+int ossl_md5_sha1_update(MD5_SHA1_CTX *mctx, const void *data, size_t count);
+int ossl_md5_sha1_final(unsigned char *md, MD5_SHA1_CTX *mctx);
+int ossl_md5_sha1_ctrl(MD5_SHA1_CTX *mctx, int cmd, int mslen, void *ms);
+
+# endif /* OPENSSL_NO_MD5 */
+
+#endif /* OSSL_PROV_MD5_SHA1_H */
diff --git a/providers/implementations/include/prov/names.h b/providers/implementations/include/prov/names.h
new file mode 100644
index 000000000000..e0dbb69a9d8c
--- /dev/null
+++ b/providers/implementations/include/prov/names.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Macros for use as names and descriptions in our providers' OSSL_ALGORITHM.
+ *
+ * All the strings are formatted the same way:
+ *
+ * Our primary name[:other names][:numeric OID]
+ *
+ * 'other names' include historical OpenSSL names, NIST names, ASN.1 OBJECT
+ * IDENTIFIER names, and commonly known aliases.
+ *
+ * Where it matters, our primary names follow this format:
+ *
+ * ALGNAME[VERSION?][-SUBNAME[VERSION?]?][-SIZE?][-MODE?]
+ *
+ * VERSION is only present if there are multiple versions of
+ * an alg (MD2, MD4, MD5). It may be omitted if there is only
+ * one version (if a subsequent version is released in the future,
+ * we can always change the canonical name, and add the old name
+ * as an alias).
+ *
+ * SUBNAME may be present where we are combining multiple
+ * algorithms together, e.g. MD5-SHA1.
+ *
+ * SIZE is only present if multiple versions of an algorithm exist
+ * with different sizes (e.g. AES-128-CBC, AES-256-CBC)
+ *
+ * MODE is only present where applicable.
+ */
+
+/*-
+ * Symmetric ciphers
+ * -----------------
+ */
+#define PROV_NAMES_AES_256_ECB "AES-256-ECB:2.16.840.1.101.3.4.1.41"
+#define PROV_NAMES_AES_192_ECB "AES-192-ECB:2.16.840.1.101.3.4.1.21"
+#define PROV_NAMES_AES_128_ECB "AES-128-ECB:2.16.840.1.101.3.4.1.1"
+#define PROV_NAMES_AES_256_CBC "AES-256-CBC:AES256:2.16.840.1.101.3.4.1.42"
+#define PROV_NAMES_AES_192_CBC "AES-192-CBC:AES192:2.16.840.1.101.3.4.1.22"
+#define PROV_NAMES_AES_128_CBC "AES-128-CBC:AES128:2.16.840.1.101.3.4.1.2"
+#define PROV_NAMES_AES_256_CBC_CTS "AES-256-CBC-CTS"
+#define PROV_NAMES_AES_192_CBC_CTS "AES-192-CBC-CTS"
+#define PROV_NAMES_AES_128_CBC_CTS "AES-128-CBC-CTS"
+#define PROV_NAMES_AES_256_OFB "AES-256-OFB:2.16.840.1.101.3.4.1.43"
+#define PROV_NAMES_AES_192_OFB "AES-192-OFB:2.16.840.1.101.3.4.1.23"
+#define PROV_NAMES_AES_128_OFB "AES-128-OFB:2.16.840.1.101.3.4.1.3"
+#define PROV_NAMES_AES_256_CFB "AES-256-CFB:2.16.840.1.101.3.4.1.44"
+#define PROV_NAMES_AES_192_CFB "AES-192-CFB:2.16.840.1.101.3.4.1.24"
+#define PROV_NAMES_AES_128_CFB "AES-128-CFB:2.16.840.1.101.3.4.1.4"
+#define PROV_NAMES_AES_256_CFB1 "AES-256-CFB1"
+#define PROV_NAMES_AES_192_CFB1 "AES-192-CFB1"
+#define PROV_NAMES_AES_128_CFB1 "AES-128-CFB1"
+#define PROV_NAMES_AES_256_CFB8 "AES-256-CFB8"
+#define PROV_NAMES_AES_192_CFB8 "AES-192-CFB8"
+#define PROV_NAMES_AES_128_CFB8 "AES-128-CFB8"
+#define PROV_NAMES_AES_256_CTR "AES-256-CTR"
+#define PROV_NAMES_AES_192_CTR "AES-192-CTR"
+#define PROV_NAMES_AES_128_CTR "AES-128-CTR"
+#define PROV_NAMES_AES_256_XTS "AES-256-XTS:1.3.111.2.1619.0.1.2"
+#define PROV_NAMES_AES_128_XTS "AES-128-XTS:1.3.111.2.1619.0.1.1"
+#define PROV_NAMES_AES_256_GCM "AES-256-GCM:id-aes256-GCM:2.16.840.1.101.3.4.1.46"
+#define PROV_NAMES_AES_192_GCM "AES-192-GCM:id-aes192-GCM:2.16.840.1.101.3.4.1.26"
+#define PROV_NAMES_AES_128_GCM "AES-128-GCM:id-aes128-GCM:2.16.840.1.101.3.4.1.6"
+#define PROV_NAMES_AES_256_CCM "AES-256-CCM:id-aes256-CCM:2.16.840.1.101.3.4.1.47"
+#define PROV_NAMES_AES_192_CCM "AES-192-CCM:id-aes192-CCM:2.16.840.1.101.3.4.1.27"
+#define PROV_NAMES_AES_128_CCM "AES-128-CCM:id-aes128-CCM:2.16.840.1.101.3.4.1.7"
+#define PROV_NAMES_AES_256_WRAP "AES-256-WRAP:id-aes256-wrap:AES256-WRAP:2.16.840.1.101.3.4.1.45"
+#define PROV_NAMES_AES_192_WRAP "AES-192-WRAP:id-aes192-wrap:AES192-WRAP:2.16.840.1.101.3.4.1.25"
+#define PROV_NAMES_AES_128_WRAP "AES-128-WRAP:id-aes128-wrap:AES128-WRAP:2.16.840.1.101.3.4.1.5"
+#define PROV_NAMES_AES_256_WRAP_PAD "AES-256-WRAP-PAD:id-aes256-wrap-pad:AES256-WRAP-PAD:2.16.840.1.101.3.4.1.48"
+#define PROV_NAMES_AES_192_WRAP_PAD "AES-192-WRAP-PAD:id-aes192-wrap-pad:AES192-WRAP-PAD:2.16.840.1.101.3.4.1.28"
+#define PROV_NAMES_AES_128_WRAP_PAD "AES-128-WRAP-PAD:id-aes128-wrap-pad:AES128-WRAP-PAD:2.16.840.1.101.3.4.1.8"
+#define PROV_NAMES_AES_256_WRAP_INV "AES-256-WRAP-INV:AES256-WRAP-INV"
+#define PROV_NAMES_AES_192_WRAP_INV "AES-192-WRAP-INV:AES192-WRAP-INV"
+#define PROV_NAMES_AES_128_WRAP_INV "AES-128-WRAP-INV:AES128-WRAP-INV"
+#define PROV_NAMES_AES_256_WRAP_PAD_INV "AES-256-WRAP-PAD-INV:AES256-WRAP-PAD-INV"
+#define PROV_NAMES_AES_192_WRAP_PAD_INV "AES-192-WRAP-PAD-INV:AES192-WRAP-PAD-INV"
+#define PROV_NAMES_AES_128_WRAP_PAD_INV "AES-128-WRAP-PAD-INV:AES128-WRAP-PAD-INV"
+#define PROV_NAMES_AES_128_CBC_HMAC_SHA1 "AES-128-CBC-HMAC-SHA1"
+#define PROV_NAMES_AES_256_CBC_HMAC_SHA1 "AES-256-CBC-HMAC-SHA1"
+#define PROV_NAMES_AES_128_CBC_HMAC_SHA256 "AES-128-CBC-HMAC-SHA256"
+#define PROV_NAMES_AES_256_CBC_HMAC_SHA256 "AES-256-CBC-HMAC-SHA256"
+#define PROV_NAMES_DES_EDE3_ECB "DES-EDE3-ECB:DES-EDE3"
+#define PROV_NAMES_DES_EDE3_CBC "DES-EDE3-CBC:DES3:1.2.840.113549.3.7"
+#define PROV_NAMES_NULL "NULL"
+#define PROV_NAMES_AES_256_OCB "AES-256-OCB"
+#define PROV_NAMES_AES_192_OCB "AES-192-OCB"
+#define PROV_NAMES_AES_128_OCB "AES-128-OCB"
+#define PROV_NAMES_AES_128_SIV "AES-128-SIV"
+#define PROV_NAMES_AES_192_SIV "AES-192-SIV"
+#define PROV_NAMES_AES_256_SIV "AES-256-SIV"
+#define PROV_NAMES_ARIA_256_GCM "ARIA-256-GCM:1.2.410.200046.1.1.36"
+#define PROV_NAMES_ARIA_192_GCM "ARIA-192-GCM:1.2.410.200046.1.1.35"
+#define PROV_NAMES_ARIA_128_GCM "ARIA-128-GCM:1.2.410.200046.1.1.34"
+#define PROV_NAMES_ARIA_256_CCM "ARIA-256-CCM:1.2.410.200046.1.1.39"
+#define PROV_NAMES_ARIA_192_CCM "ARIA-192-CCM:1.2.410.200046.1.1.38"
+#define PROV_NAMES_ARIA_128_CCM "ARIA-128-CCM:1.2.410.200046.1.1.37"
+#define PROV_NAMES_ARIA_256_ECB "ARIA-256-ECB:1.2.410.200046.1.1.11"
+#define PROV_NAMES_ARIA_192_ECB "ARIA-192-ECB:1.2.410.200046.1.1.6"
+#define PROV_NAMES_ARIA_128_ECB "ARIA-128-ECB:1.2.410.200046.1.1.1"
+#define PROV_NAMES_ARIA_256_CBC "ARIA-256-CBC:ARIA256:1.2.410.200046.1.1.12"
+#define PROV_NAMES_ARIA_192_CBC "ARIA-192-CBC:ARIA192:1.2.410.200046.1.1.7"
+#define PROV_NAMES_ARIA_128_CBC "ARIA-128-CBC:ARIA128:1.2.410.200046.1.1.2"
+#define PROV_NAMES_ARIA_256_OFB "ARIA-256-OFB:1.2.410.200046.1.1.14"
+#define PROV_NAMES_ARIA_192_OFB "ARIA-192-OFB:1.2.410.200046.1.1.9"
+#define PROV_NAMES_ARIA_128_OFB "ARIA-128-OFB:1.2.410.200046.1.1.4"
+#define PROV_NAMES_ARIA_256_CFB "ARIA-256-CFB:1.2.410.200046.1.1.13"
+#define PROV_NAMES_ARIA_192_CFB "ARIA-192-CFB:1.2.410.200046.1.1.8"
+#define PROV_NAMES_ARIA_128_CFB "ARIA-128-CFB:1.2.410.200046.1.1.3"
+#define PROV_NAMES_ARIA_256_CFB1 "ARIA-256-CFB1"
+#define PROV_NAMES_ARIA_192_CFB1 "ARIA-192-CFB1"
+#define PROV_NAMES_ARIA_128_CFB1 "ARIA-128-CFB1"
+#define PROV_NAMES_ARIA_256_CFB8 "ARIA-256-CFB8"
+#define PROV_NAMES_ARIA_192_CFB8 "ARIA-192-CFB8"
+#define PROV_NAMES_ARIA_128_CFB8 "ARIA-128-CFB8"
+#define PROV_NAMES_ARIA_256_CTR "ARIA-256-CTR:1.2.410.200046.1.1.15"
+#define PROV_NAMES_ARIA_192_CTR "ARIA-192-CTR:1.2.410.200046.1.1.10"
+#define PROV_NAMES_ARIA_128_CTR "ARIA-128-CTR:1.2.410.200046.1.1.5"
+#define PROV_NAMES_CAMELLIA_256_ECB "CAMELLIA-256-ECB:0.3.4401.5.3.1.9.41"
+#define PROV_NAMES_CAMELLIA_192_ECB "CAMELLIA-192-ECB:0.3.4401.5.3.1.9.21"
+#define PROV_NAMES_CAMELLIA_128_ECB "CAMELLIA-128-ECB:0.3.4401.5.3.1.9.1"
+#define PROV_NAMES_CAMELLIA_256_CBC "CAMELLIA-256-CBC:CAMELLIA256:1.2.392.200011.61.1.1.1.4"
+#define PROV_NAMES_CAMELLIA_192_CBC "CAMELLIA-192-CBC:CAMELLIA192:1.2.392.200011.61.1.1.1.3"
+#define PROV_NAMES_CAMELLIA_128_CBC "CAMELLIA-128-CBC:CAMELLIA128:1.2.392.200011.61.1.1.1.2"
+#define PROV_NAMES_CAMELLIA_256_CBC_CTS "CAMELLIA-256-CBC-CTS"
+#define PROV_NAMES_CAMELLIA_192_CBC_CTS "CAMELLIA-192-CBC-CTS"
+#define PROV_NAMES_CAMELLIA_128_CBC_CTS "CAMELLIA-128-CBC-CTS"
+#define PROV_NAMES_CAMELLIA_256_OFB "CAMELLIA-256-OFB:0.3.4401.5.3.1.9.43"
+#define PROV_NAMES_CAMELLIA_192_OFB "CAMELLIA-192-OFB:0.3.4401.5.3.1.9.23"
+#define PROV_NAMES_CAMELLIA_128_OFB "CAMELLIA-128-OFB:0.3.4401.5.3.1.9.3"
+#define PROV_NAMES_CAMELLIA_256_CFB "CAMELLIA-256-CFB:0.3.4401.5.3.1.9.44"
+#define PROV_NAMES_CAMELLIA_192_CFB "CAMELLIA-192-CFB:0.3.4401.5.3.1.9.24"
+#define PROV_NAMES_CAMELLIA_128_CFB "CAMELLIA-128-CFB:0.3.4401.5.3.1.9.4"
+#define PROV_NAMES_CAMELLIA_256_CFB1 "CAMELLIA-256-CFB1"
+#define PROV_NAMES_CAMELLIA_192_CFB1 "CAMELLIA-192-CFB1"
+#define PROV_NAMES_CAMELLIA_128_CFB1 "CAMELLIA-128-CFB1"
+#define PROV_NAMES_CAMELLIA_256_CFB8 "CAMELLIA-256-CFB8"
+#define PROV_NAMES_CAMELLIA_192_CFB8 "CAMELLIA-192-CFB8"
+#define PROV_NAMES_CAMELLIA_128_CFB8 "CAMELLIA-128-CFB8"
+#define PROV_NAMES_CAMELLIA_256_CTR "CAMELLIA-256-CTR:0.3.4401.5.3.1.9.49"
+#define PROV_NAMES_CAMELLIA_192_CTR "CAMELLIA-192-CTR:0.3.4401.5.3.1.9.29"
+#define PROV_NAMES_CAMELLIA_128_CTR "CAMELLIA-128-CTR:0.3.4401.5.3.1.9.9"
+#define PROV_NAMES_DES_EDE3_OFB "DES-EDE3-OFB"
+#define PROV_NAMES_DES_EDE3_CFB "DES-EDE3-CFB"
+#define PROV_NAMES_DES_EDE3_CFB8 "DES-EDE3-CFB8"
+#define PROV_NAMES_DES_EDE3_CFB1 "DES-EDE3-CFB1"
+#define PROV_NAMES_DES3_WRAP "DES3-WRAP:id-smime-alg-CMS3DESwrap:1.2.840.113549.1.9.16.3.6"
+#define PROV_NAMES_DES_EDE_ECB "DES-EDE-ECB:DES-EDE:1.3.14.3.2.17"
+#define PROV_NAMES_DES_EDE_CBC "DES-EDE-CBC"
+#define PROV_NAMES_DES_EDE_OFB "DES-EDE-OFB"
+#define PROV_NAMES_DES_EDE_CFB "DES-EDE-CFB"
+#define PROV_NAMES_SM4_ECB "SM4-ECB:1.2.156.10197.1.104.1"
+#define PROV_NAMES_SM4_CBC "SM4-CBC:SM4:1.2.156.10197.1.104.2"
+#define PROV_NAMES_SM4_CTR "SM4-CTR:1.2.156.10197.1.104.7"
+#define PROV_NAMES_SM4_OFB "SM4-OFB:SM4-OFB128:1.2.156.10197.1.104.3"
+#define PROV_NAMES_SM4_CFB "SM4-CFB:SM4-CFB128:1.2.156.10197.1.104.4"
+#define PROV_NAMES_ChaCha20 "ChaCha20"
+#define PROV_NAMES_ChaCha20_Poly1305 "ChaCha20-Poly1305"
+#define PROV_NAMES_CAST5_ECB "CAST5-ECB"
+#define PROV_NAMES_CAST5_CBC "CAST5-CBC:CAST-CBC:CAST:1.2.840.113533.7.66.10"
+#define PROV_NAMES_CAST5_OFB "CAST5-OFB"
+#define PROV_NAMES_CAST5_CFB "CAST5-CFB"
+#define PROV_NAMES_BF_ECB "BF-ECB"
+#define PROV_NAMES_BF_CBC "BF-CBC:BF:BLOWFISH:1.3.6.1.4.1.3029.1.2"
+#define PROV_NAMES_BF_OFB "BF-OFB"
+#define PROV_NAMES_BF_CFB "BF-CFB"
+#define PROV_NAMES_IDEA_ECB "IDEA-ECB"
+#define PROV_NAMES_IDEA_CBC "IDEA-CBC:IDEA:1.3.6.1.4.1.188.7.1.1.2"
+#define PROV_NAMES_IDEA_OFB "IDEA-OFB:IDEA-OFB64"
+#define PROV_NAMES_IDEA_CFB "IDEA-CFB:IDEA-CFB64"
+#define PROV_NAMES_SEED_ECB "SEED-ECB:1.2.410.200004.1.3"
+#define PROV_NAMES_SEED_CBC "SEED-CBC:SEED:1.2.410.200004.1.4"
+#define PROV_NAMES_SEED_OFB "SEED-OFB:SEED-OFB128:1.2.410.200004.1.6"
+#define PROV_NAMES_SEED_CFB "SEED-CFB:SEED-CFB128:1.2.410.200004.1.5"
+#define PROV_NAMES_RC2_ECB "RC2-ECB"
+#define PROV_NAMES_RC2_CBC "RC2-CBC:RC2:RC2-128:1.2.840.113549.3.2"
+#define PROV_NAMES_RC2_40_CBC "RC2-40-CBC:RC2-40"
+#define PROV_NAMES_RC2_64_CBC "RC2-64-CBC:RC2-64"
+#define PROV_NAMES_RC2_CFB "RC2-CFB"
+#define PROV_NAMES_RC2_OFB "RC2-OFB"
+#define PROV_NAMES_RC4 "RC4:1.2.840.113549.3.4"
+#define PROV_NAMES_RC4_40 "RC4-40"
+#define PROV_NAMES_RC4_HMAC_MD5 "RC4-HMAC-MD5"
+#define PROV_NAMES_RC5_ECB "RC5-ECB"
+#define PROV_NAMES_RC5_CBC "RC5-CBC:RC5:1.2.840.113549.3.8"
+#define PROV_NAMES_RC5_OFB "RC5-OFB"
+#define PROV_NAMES_RC5_CFB "RC5-CFB"
+#define PROV_NAMES_DESX_CBC "DESX-CBC:DESX"
+#define PROV_NAMES_DES_ECB "DES-ECB:1.3.14.3.2.6"
+#define PROV_NAMES_DES_CBC "DES-CBC:DES:1.3.14.3.2.7"
+#define PROV_NAMES_DES_OFB "DES-OFB:1.3.14.3.2.8"
+#define PROV_NAMES_DES_CFB "DES-CFB:1.3.14.3.2.9"
+#define PROV_NAMES_DES_CFB1 "DES-CFB1"
+#define PROV_NAMES_DES_CFB8 "DES-CFB8"
+
+/*-
+ * Digests
+ * -------
+ */
+#define PROV_NAMES_SHA1 "SHA1:SHA-1:SSL3-SHA1:1.3.14.3.2.26"
+#define PROV_NAMES_SHA2_224 "SHA2-224:SHA-224:SHA224:2.16.840.1.101.3.4.2.4"
+#define PROV_NAMES_SHA2_256 "SHA2-256:SHA-256:SHA256:2.16.840.1.101.3.4.2.1"
+#define PROV_NAMES_SHA2_384 "SHA2-384:SHA-384:SHA384:2.16.840.1.101.3.4.2.2"
+#define PROV_NAMES_SHA2_512 "SHA2-512:SHA-512:SHA512:2.16.840.1.101.3.4.2.3"
+#define PROV_NAMES_SHA2_512_224 "SHA2-512/224:SHA-512/224:SHA512-224:2.16.840.1.101.3.4.2.5"
+#define PROV_NAMES_SHA2_512_256 "SHA2-512/256:SHA-512/256:SHA512-256:2.16.840.1.101.3.4.2.6"
+
+/* We agree with NIST here, so one name only */
+#define PROV_NAMES_SHA3_224 "SHA3-224:2.16.840.1.101.3.4.2.7"
+#define PROV_NAMES_SHA3_256 "SHA3-256:2.16.840.1.101.3.4.2.8"
+#define PROV_NAMES_SHA3_384 "SHA3-384:2.16.840.1.101.3.4.2.9"
+#define PROV_NAMES_SHA3_512 "SHA3-512:2.16.840.1.101.3.4.2.10"
+
+#define PROV_NAMES_SHAKE_128 "SHAKE-128:SHAKE128:2.16.840.1.101.3.4.2.11"
+#define PROV_NAMES_SHAKE_256 "SHAKE-256:SHAKE256:2.16.840.1.101.3.4.2.12"
+
+/*
+ * KECCAK-KMAC-128 and KECCAK-KMAC-256 as hashes are mostly useful for
+ * KMAC128 and KMAC256.
+ */
+#define PROV_NAMES_KECCAK_KMAC_128 "KECCAK-KMAC-128:KECCAK-KMAC128"
+#define PROV_NAMES_KECCAK_KMAC_256 "KECCAK-KMAC-256:KECCAK-KMAC256"
+/*
+ * https://blake2.net/ doesn't specify size variants, but mentions that
+ * Bouncy Castle uses the names BLAKE2b-160, BLAKE2b-256, BLAKE2b-384, and
+ * BLAKE2b-512
+ * If we assume that "2b" and "2s" are versions, that pattern fits with ours.
+ * We also add our historical names.
+ */
+#define PROV_NAMES_BLAKE2S_256 "BLAKE2S-256:BLAKE2s256:1.3.6.1.4.1.1722.12.2.2.8"
+#define PROV_NAMES_BLAKE2B_512 "BLAKE2B-512:BLAKE2b512:1.3.6.1.4.1.1722.12.2.1.16"
+#define PROV_NAMES_SM3 "SM3:1.2.156.10197.1.401"
+#define PROV_NAMES_MD5 "MD5:SSL3-MD5:1.2.840.113549.2.5"
+#define PROV_NAMES_MD5_SHA1 "MD5-SHA1"
+#define PROV_NAMES_MD2 "MD2:1.2.840.113549.2.2"
+#define PROV_NAMES_MD4 "MD4:1.2.840.113549.2.4"
+#define PROV_NAMES_MDC2 "MDC2:2.5.8.3.101"
+#define PROV_NAMES_WHIRLPOOL "WHIRLPOOL:1.0.10118.3.0.55"
+#define PROV_NAMES_RIPEMD_160 "RIPEMD-160:RIPEMD160:RIPEMD:RMD160:1.3.36.3.2.1"
+
+/*-
+ * KDFs / PRFs
+ * -----------
+ */
+#define PROV_NAMES_HKDF "HKDF"
+#define PROV_DESCS_HKDF_SIGN "OpenSSL HKDF via EVP_PKEY implementation"
+#define PROV_NAMES_TLS1_3_KDF "TLS13-KDF"
+#define PROV_NAMES_SSKDF "SSKDF"
+#define PROV_NAMES_PBKDF1 "PBKDF1"
+#define PROV_NAMES_PBKDF2 "PBKDF2:1.2.840.113549.1.5.12"
+#define PROV_NAMES_SSHKDF "SSHKDF"
+#define PROV_NAMES_X963KDF "X963KDF:X942KDF-CONCAT"
+#define PROV_NAMES_X942KDF_ASN1 "X942KDF-ASN1:X942KDF"
+#define PROV_NAMES_TLS1_PRF "TLS1-PRF"
+#define PROV_DESCS_TLS1_PRF_SIGN "OpenSSL TLS1_PRF via EVP_PKEY implementation"
+#define PROV_NAMES_KBKDF "KBKDF"
+#define PROV_NAMES_PKCS12KDF "PKCS12KDF"
+#define PROV_NAMES_SCRYPT "SCRYPT:id-scrypt:1.3.6.1.4.1.11591.4.11"
+#define PROV_DESCS_SCRYPT_SIGN "OpenSSL SCRYPT via EVP_PKEY implementation"
+#define PROV_NAMES_KRB5KDF "KRB5KDF"
+
+/*-
+ * MACs
+ * ----
+ */
+#define PROV_NAMES_HMAC "HMAC"
+#define PROV_DESCS_HMAC_SIGN "OpenSSL HMAC via EVP_PKEY implementation"
+#define PROV_NAMES_CMAC "CMAC"
+#define PROV_DESCS_CMAC_SIGN "OpenSSL CMAC via EVP_PKEY implementation"
+#define PROV_NAMES_SIPHASH "SIPHASH"
+#define PROV_DESCS_SIPHASH_SIGN "OpenSSL SIPHASH via EVP_PKEY implementation"
+#define PROV_NAMES_POLY1305 "POLY1305"
+#define PROV_DESCS_POLY1305_SIGN "OpenSSL POLY1305 via EVP_PKEY implementation"
+#define PROV_NAMES_GMAC "GMAC:1.0.9797.3.4"
+#define PROV_NAMES_KMAC_128 "KMAC-128:KMAC128:2.16.840.1.101.3.4.2.19"
+#define PROV_NAMES_KMAC_256 "KMAC-256:KMAC256:2.16.840.1.101.3.4.2.20"
+#define PROV_NAMES_BLAKE2BMAC "BLAKE2BMAC:1.3.6.1.4.1.1722.12.2.1"
+#define PROV_NAMES_BLAKE2SMAC "BLAKE2SMAC:1.3.6.1.4.1.1722.12.2.2"
+
+/*-
+ * RANDs
+ * -----
+ */
+#define PROV_NAMES_CTR_DRBG "CTR-DRBG"
+#define PROV_NAMES_HASH_DRBG "HASH-DRBG"
+#define PROV_NAMES_HMAC_DRBG "HMAC-DRBG"
+#define PROV_NAMES_TEST_RAND "TEST-RAND"
+#define PROV_NAMES_SEED_SRC "SEED-SRC"
+
+/*-
+ * Asymmetric algos
+ * ----------------
+ */
+#define PROV_NAMES_EC "EC:id-ecPublicKey:1.2.840.10045.2.1"
+#define PROV_DESCS_EC "OpenSSL EC implementation"
+#define PROV_NAMES_ECDH "ECDH"
+#define PROV_DESCS_ECDH "OpenSSL ECDH implementation"
+#define PROV_NAMES_ECDSA "ECDSA"
+#define PROV_DESCS_ECDSA "OpenSSL ECDSA implementation"
+#define PROV_NAMES_X25519 "X25519:1.3.101.110"
+#define PROV_DESCS_X25519 "OpenSSL X25519 implementation"
+#define PROV_NAMES_X448 "X448:1.3.101.111"
+#define PROV_DESCS_X448 "OpenSSL X448 implementation"
+#define PROV_NAMES_ED25519 "ED25519:1.3.101.112"
+#define PROV_DESCS_ED25519 "OpenSSL ED25519 implementation"
+#define PROV_NAMES_ED448 "ED448:1.3.101.113"
+#define PROV_DESCS_ED448 "OpenSSL ED448 implementation"
+#define PROV_NAMES_DH "DH:dhKeyAgreement:1.2.840.113549.1.3.1"
+#define PROV_DESCS_DH "OpenSSL PKCS#3 DH implementation"
+#define PROV_NAMES_DHX "DHX:X9.42 DH:dhpublicnumber:1.2.840.10046.2.1"
+#define PROV_DESCS_DHX "OpenSSL X9.42 DH implementation"
+#define PROV_NAMES_DSA "DSA:dsaEncryption:1.2.840.10040.4.1"
+#define PROV_DESCS_DSA "OpenSSL DSA implementation"
+#define PROV_NAMES_RSA "RSA:rsaEncryption:1.2.840.113549.1.1.1"
+#define PROV_DESCS_RSA "OpenSSL RSA implementation"
+#define PROV_NAMES_RSA_PSS "RSA-PSS:RSASSA-PSS:1.2.840.113549.1.1.10"
+#define PROV_DESCS_RSA_PSS "OpenSSL RSA-PSS implementation"
+#define PROV_NAMES_SM2 "SM2:1.2.156.10197.1.301"
+#define PROV_DESCS_SM2 "OpenSSL SM2 implementation"
diff --git a/providers/implementations/include/prov/seeding.h b/providers/implementations/include/prov/seeding.h
new file mode 100644
index 000000000000..637b921b2b52
--- /dev/null
+++ b/providers/implementations/include/prov/seeding.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/provider_ctx.h"
+#include "crypto/rand_pool.h"
+
+/* Hardware-based seeding functions. */
+size_t ossl_prov_acquire_entropy_from_tsc(RAND_POOL *pool);
+size_t ossl_prov_acquire_entropy_from_cpu(RAND_POOL *pool);
+
+/*
+ * Add some platform specific additional data
+ *
+ * This function is platform specific and adds some random noise to the
+ * additional data used for generating random bytes and for reseeding
+ * the drbg.
+ *
+ * Returns 1 on success and 0 on failure.
+ */
+int ossl_rand_pool_add_additional_data(RAND_POOL *pool);
+
+/*
+ * External seeding functions from the core dispatch table.
+ */
+int ossl_prov_seeding_from_dispatch(const OSSL_DISPATCH *fns);
+
+size_t ossl_prov_get_entropy(PROV_CTX *prov_ctx, unsigned char **pout,
+ int entropy, size_t min_len, size_t max_len);
+void ossl_prov_cleanup_entropy(PROV_CTX *prov_ctx, unsigned char *buf,
+ size_t len);
+size_t ossl_prov_get_nonce(PROV_CTX *prov_ctx, unsigned char **pout,
+ size_t min_len, size_t max_len,
+ const void *salt, size_t salt_len);
+void ossl_prov_cleanup_nonce(PROV_CTX *prov_ctx, unsigned char *buf,
+ size_t len);
diff --git a/providers/implementations/kdfs/build.info b/providers/implementations/kdfs/build.info
new file mode 100644
index 000000000000..f4620adce2df
--- /dev/null
+++ b/providers/implementations/kdfs/build.info
@@ -0,0 +1,38 @@
+# We make separate GOAL variables for each algorithm, to make it easy to
+# switch each to the Legacy provider when needed.
+
+$TLS1_PRF_GOAL=../../libdefault.a ../../libfips.a
+$HKDF_GOAL=../../libdefault.a ../../libfips.a
+$KBKDF_GOAL=../../libdefault.a ../../libfips.a
+$KRB5KDF_GOAL=../../libdefault.a
+$PBKDF1_GOAL=../../liblegacy.a
+$PBKDF2_GOAL=../../libdefault.a ../../libfips.a
+$PKCS12KDF_GOAL=../../libdefault.a
+$SSKDF_GOAL=../../libdefault.a ../../libfips.a
+$SCRYPT_GOAL=../../libdefault.a
+$SSHKDF_GOAL=../../libdefault.a ../../libfips.a
+$X942KDF_GOAL=../../libdefault.a ../../libfips.a
+
+SOURCE[$TLS1_PRF_GOAL]=tls1_prf.c
+
+SOURCE[$HKDF_GOAL]=hkdf.c
+
+SOURCE[$KBKDF_GOAL]=kbkdf.c
+
+SOURCE[$KRB5KDF_GOAL]=krb5kdf.c
+
+SOURCE[$PBKDF1_GOAL]=pbkdf1.c
+
+SOURCE[$PBKDF2_GOAL]=pbkdf2.c
+# Extra code to satisfy the FIPS and non-FIPS separation.
+# When the PBKDF2 moves to legacy, this can be removed.
+SOURCE[$PBKDF2_GOAL]=pbkdf2_fips.c
+
+SOURCE[$PKCS12KDF_GOAL]=pkcs12kdf.c
+
+SOURCE[$SSKDF_GOAL]=sskdf.c
+
+SOURCE[$SCRYPT_GOAL]=scrypt.c
+SOURCE[$SSHKDF_GOAL]=sshkdf.c
+SOURCE[$X942KDF_GOAL]=x942kdf.c
+DEPEND[x942kdf.o]=../../common/include/prov/der_wrap.h
diff --git a/providers/implementations/kdfs/hkdf.c b/providers/implementations/kdfs/hkdf.c
new file mode 100644
index 000000000000..dfa7786bde0c
--- /dev/null
+++ b/providers/implementations/kdfs/hkdf.c
@@ -0,0 +1,783 @@
+/*
+ * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * HMAC low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#include <openssl/proverr.h>
+#include "internal/cryptlib.h"
+#include "internal/numbers.h"
+#include "internal/packet.h"
+#include "crypto/evp.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_util.h"
+#include "e_os.h"
+
+#define HKDF_MAXBUF 2048
+#define HKDF_MAXINFO (32*1024)
+
+static OSSL_FUNC_kdf_newctx_fn kdf_hkdf_new;
+static OSSL_FUNC_kdf_freectx_fn kdf_hkdf_free;
+static OSSL_FUNC_kdf_reset_fn kdf_hkdf_reset;
+static OSSL_FUNC_kdf_derive_fn kdf_hkdf_derive;
+static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_hkdf_settable_ctx_params;
+static OSSL_FUNC_kdf_set_ctx_params_fn kdf_hkdf_set_ctx_params;
+static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_hkdf_gettable_ctx_params;
+static OSSL_FUNC_kdf_get_ctx_params_fn kdf_hkdf_get_ctx_params;
+static OSSL_FUNC_kdf_derive_fn kdf_tls1_3_derive;
+static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_tls1_3_settable_ctx_params;
+static OSSL_FUNC_kdf_set_ctx_params_fn kdf_tls1_3_set_ctx_params;
+
+static int HKDF(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
+ const unsigned char *salt, size_t salt_len,
+ const unsigned char *key, size_t key_len,
+ const unsigned char *info, size_t info_len,
+ unsigned char *okm, size_t okm_len);
+static int HKDF_Extract(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
+ const unsigned char *salt, size_t salt_len,
+ const unsigned char *ikm, size_t ikm_len,
+ unsigned char *prk, size_t prk_len);
+static int HKDF_Expand(const EVP_MD *evp_md,
+ const unsigned char *prk, size_t prk_len,
+ const unsigned char *info, size_t info_len,
+ unsigned char *okm, size_t okm_len);
+
+/* Settable context parameters that are common across HKDF and the TLS KDF */
+#define HKDF_COMMON_SETTABLES \
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0), \
+ OSSL_PARAM_int(OSSL_KDF_PARAM_MODE, NULL), \
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), \
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), \
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), \
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0)
+
+typedef struct {
+ void *provctx;
+ int mode;
+ PROV_DIGEST digest;
+ unsigned char *salt;
+ size_t salt_len;
+ unsigned char *key;
+ size_t key_len;
+ unsigned char *prefix;
+ size_t prefix_len;
+ unsigned char *label;
+ size_t label_len;
+ unsigned char *data;
+ size_t data_len;
+ unsigned char *info;
+ size_t info_len;
+} KDF_HKDF;
+
+static void *kdf_hkdf_new(void *provctx)
+{
+ KDF_HKDF *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL)
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ else
+ ctx->provctx = provctx;
+ return ctx;
+}
+
+static void kdf_hkdf_free(void *vctx)
+{
+ KDF_HKDF *ctx = (KDF_HKDF *)vctx;
+
+ if (ctx != NULL) {
+ kdf_hkdf_reset(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+static void kdf_hkdf_reset(void *vctx)
+{
+ KDF_HKDF *ctx = (KDF_HKDF *)vctx;
+ void *provctx = ctx->provctx;
+
+ ossl_prov_digest_reset(&ctx->digest);
+ OPENSSL_free(ctx->salt);
+ OPENSSL_free(ctx->prefix);
+ OPENSSL_free(ctx->label);
+ OPENSSL_clear_free(ctx->data, ctx->data_len);
+ OPENSSL_clear_free(ctx->key, ctx->key_len);
+ OPENSSL_clear_free(ctx->info, ctx->info_len);
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->provctx = provctx;
+}
+
+static size_t kdf_hkdf_size(KDF_HKDF *ctx)
+{
+ int sz;
+ const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
+
+ if (ctx->mode != EVP_KDF_HKDF_MODE_EXTRACT_ONLY)
+ return SIZE_MAX;
+
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
+ return 0;
+ }
+ sz = EVP_MD_get_size(md);
+ if (sz < 0)
+ return 0;
+
+ return sz;
+}
+
+static int kdf_hkdf_derive(void *vctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ KDF_HKDF *ctx = (KDF_HKDF *)vctx;
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
+ const EVP_MD *md;
+
+ if (!ossl_prov_is_running() || !kdf_hkdf_set_ctx_params(ctx, params))
+ return 0;
+
+ md = ossl_prov_digest_md(&ctx->digest);
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
+ return 0;
+ }
+ if (ctx->key == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
+ return 0;
+ }
+ if (keylen == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+
+ switch (ctx->mode) {
+ case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND:
+ default:
+ return HKDF(libctx, md, ctx->salt, ctx->salt_len,
+ ctx->key, ctx->key_len, ctx->info, ctx->info_len, key, keylen);
+
+ case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
+ return HKDF_Extract(libctx, md, ctx->salt, ctx->salt_len,
+ ctx->key, ctx->key_len, key, keylen);
+
+ case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
+ return HKDF_Expand(md, ctx->key, ctx->key_len, ctx->info,
+ ctx->info_len, key, keylen);
+ }
+}
+
+static int hkdf_common_set_ctx_params(KDF_HKDF *ctx, const OSSL_PARAM params[])
+{
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
+ const OSSL_PARAM *p;
+ int n;
+
+ if (params == NULL)
+ return 1;
+
+ if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE)) != NULL) {
+ if (p->data_type == OSSL_PARAM_UTF8_STRING) {
+ if (OPENSSL_strcasecmp(p->data, "EXTRACT_AND_EXPAND") == 0) {
+ ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND;
+ } else if (OPENSSL_strcasecmp(p->data, "EXTRACT_ONLY") == 0) {
+ ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY;
+ } else if (OPENSSL_strcasecmp(p->data, "EXPAND_ONLY") == 0) {
+ ctx->mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY;
+ } else {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
+ return 0;
+ }
+ } else if (OSSL_PARAM_get_int(p, &n)) {
+ if (n != EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND
+ && n != EVP_KDF_HKDF_MODE_EXTRACT_ONLY
+ && n != EVP_KDF_HKDF_MODE_EXPAND_ONLY) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
+ return 0;
+ }
+ ctx->mode = n;
+ } else {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
+ return 0;
+ }
+ }
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) {
+ OPENSSL_clear_free(ctx->key, ctx->key_len);
+ ctx->key = NULL;
+ if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->key, 0,
+ &ctx->key_len))
+ return 0;
+ }
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) {
+ if (p->data_size != 0 && p->data != NULL) {
+ OPENSSL_free(ctx->salt);
+ ctx->salt = NULL;
+ if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->salt, 0,
+ &ctx->salt_len))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * Use WPACKET to concat one or more OSSL_KDF_PARAM_INFO fields into a fixed
+ * out buffer of size *outlen.
+ * If out is NULL then outlen is used to return the required buffer size.
+ */
+static int setinfo_fromparams(const OSSL_PARAM *p, unsigned char *out, size_t *outlen)
+{
+ int ret = 0;
+ WPACKET pkt;
+
+ if (out == NULL) {
+ if (!WPACKET_init_null(&pkt, 0))
+ return 0;
+ } else {
+ if (!WPACKET_init_static_len(&pkt, out, *outlen, 0))
+ return 0;
+ }
+
+ for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1, OSSL_KDF_PARAM_INFO)) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING)
+ goto err;
+ if (p->data != NULL
+ && p->data_size != 0
+ && !WPACKET_memcpy(&pkt, p->data, p->data_size))
+ goto err;
+ }
+ if (!WPACKET_get_total_written(&pkt, outlen)
+ || !WPACKET_finish(&pkt))
+ goto err;
+ ret = 1;
+err:
+ WPACKET_cleanup(&pkt);
+ return ret;
+}
+
+static int kdf_hkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ KDF_HKDF *ctx = vctx;
+
+ if (params == NULL)
+ return 1;
+
+ if (!hkdf_common_set_ctx_params(ctx, params))
+ return 0;
+
+ /* The info fields concatenate, so process them all */
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO)) != NULL) {
+ size_t sz = 0;
+
+ /* calculate the total size */
+ if (!setinfo_fromparams(p, NULL, &sz))
+ return 0;
+ if (sz > HKDF_MAXINFO)
+ return 0;
+
+ OPENSSL_clear_free(ctx->info, ctx->info_len);
+ ctx->info = NULL;
+ if (sz == 0)
+ return 1;
+ /* Alloc the buffer */
+ ctx->info = OPENSSL_malloc(sz);
+ if (ctx->info == NULL)
+ return 0;
+ ctx->info_len = sz;
+ /* Concat one or more OSSL_KDF_PARAM_INFO fields */
+ if (!setinfo_fromparams(p, ctx->info, &sz))
+ return 0;
+ }
+ return 1;
+}
+
+static const OSSL_PARAM *kdf_hkdf_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ HKDF_COMMON_SETTABLES,
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0),
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+static int kdf_hkdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ KDF_HKDF *ctx = (KDF_HKDF *)vctx;
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) {
+ size_t sz = kdf_hkdf_size(ctx);
+
+ if (sz == 0)
+ return 0;
+ return OSSL_PARAM_set_size_t(p, sz);
+ }
+ return -2;
+}
+
+static const OSSL_PARAM *kdf_hkdf_gettable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_kdf_hkdf_functions[] = {
+ { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new },
+ { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free },
+ { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset },
+ { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_hkdf_derive },
+ { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_hkdf_settable_ctx_params },
+ { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_hkdf_set_ctx_params },
+ { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_hkdf_gettable_ctx_params },
+ { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_hkdf_get_ctx_params },
+ { 0, NULL }
+};
+
+/*
+ * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"
+ * Section 2 (https://tools.ietf.org/html/rfc5869#section-2) and
+ * "Cryptographic Extraction and Key Derivation: The HKDF Scheme"
+ * Section 4.2 (https://eprint.iacr.org/2010/264.pdf).
+ *
+ * From the paper:
+ * The scheme HKDF is specified as:
+ * HKDF(XTS, SKM, CTXinfo, L) = K(1) | K(2) | ... | K(t)
+ *
+ * where:
+ * SKM is source key material
+ * XTS is extractor salt (which may be null or constant)
+ * CTXinfo is context information (may be null)
+ * L is the number of key bits to be produced by KDF
+ * k is the output length in bits of the hash function used with HMAC
+ * t = ceil(L/k)
+ * the value K(t) is truncated to its first d = L mod k bits.
+ *
+ * From RFC 5869:
+ * 2.2. Step 1: Extract
+ * HKDF-Extract(salt, IKM) -> PRK
+ * 2.3. Step 2: Expand
+ * HKDF-Expand(PRK, info, L) -> OKM
+ */
+static int HKDF(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
+ const unsigned char *salt, size_t salt_len,
+ const unsigned char *ikm, size_t ikm_len,
+ const unsigned char *info, size_t info_len,
+ unsigned char *okm, size_t okm_len)
+{
+ unsigned char prk[EVP_MAX_MD_SIZE];
+ int ret, sz;
+ size_t prk_len;
+
+ sz = EVP_MD_get_size(evp_md);
+ if (sz < 0)
+ return 0;
+ prk_len = (size_t)sz;
+
+ /* Step 1: HKDF-Extract(salt, IKM) -> PRK */
+ if (!HKDF_Extract(libctx, evp_md,
+ salt, salt_len, ikm, ikm_len, prk, prk_len))
+ return 0;
+
+ /* Step 2: HKDF-Expand(PRK, info, L) -> OKM */
+ ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len);
+ OPENSSL_cleanse(prk, sizeof(prk));
+
+ return ret;
+}
+
+/*
+ * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"
+ * Section 2.2 (https://tools.ietf.org/html/rfc5869#section-2.2).
+ *
+ * 2.2. Step 1: Extract
+ *
+ * HKDF-Extract(salt, IKM) -> PRK
+ *
+ * Options:
+ * Hash a hash function; HashLen denotes the length of the
+ * hash function output in octets
+ *
+ * Inputs:
+ * salt optional salt value (a non-secret random value);
+ * if not provided, it is set to a string of HashLen zeros.
+ * IKM input keying material
+ *
+ * Output:
+ * PRK a pseudorandom key (of HashLen octets)
+ *
+ * The output PRK is calculated as follows:
+ *
+ * PRK = HMAC-Hash(salt, IKM)
+ */
+static int HKDF_Extract(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
+ const unsigned char *salt, size_t salt_len,
+ const unsigned char *ikm, size_t ikm_len,
+ unsigned char *prk, size_t prk_len)
+{
+ int sz = EVP_MD_get_size(evp_md);
+
+ if (sz < 0)
+ return 0;
+ if (prk_len != (size_t)sz) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_OUTPUT_BUFFER_SIZE);
+ return 0;
+ }
+ /* calc: PRK = HMAC-Hash(salt, IKM) */
+ return
+ EVP_Q_mac(libctx, "HMAC", NULL, EVP_MD_get0_name(evp_md), NULL, salt,
+ salt_len, ikm, ikm_len, prk, EVP_MD_get_size(evp_md), NULL)
+ != NULL;
+}
+
+/*
+ * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"
+ * Section 2.3 (https://tools.ietf.org/html/rfc5869#section-2.3).
+ *
+ * 2.3. Step 2: Expand
+ *
+ * HKDF-Expand(PRK, info, L) -> OKM
+ *
+ * Options:
+ * Hash a hash function; HashLen denotes the length of the
+ * hash function output in octets
+ *
+ * Inputs:
+ * PRK a pseudorandom key of at least HashLen octets
+ * (usually, the output from the extract step)
+ * info optional context and application specific information
+ * (can be a zero-length string)
+ * L length of output keying material in octets
+ * (<= 255*HashLen)
+ *
+ * Output:
+ * OKM output keying material (of L octets)
+ *
+ * The output OKM is calculated as follows:
+ *
+ * N = ceil(L/HashLen)
+ * T = T(1) | T(2) | T(3) | ... | T(N)
+ * OKM = first L octets of T
+ *
+ * where:
+ * T(0) = empty string (zero length)
+ * T(1) = HMAC-Hash(PRK, T(0) | info | 0x01)
+ * T(2) = HMAC-Hash(PRK, T(1) | info | 0x02)
+ * T(3) = HMAC-Hash(PRK, T(2) | info | 0x03)
+ * ...
+ *
+ * (where the constant concatenated to the end of each T(n) is a
+ * single octet.)
+ */
+static int HKDF_Expand(const EVP_MD *evp_md,
+ const unsigned char *prk, size_t prk_len,
+ const unsigned char *info, size_t info_len,
+ unsigned char *okm, size_t okm_len)
+{
+ HMAC_CTX *hmac;
+ int ret = 0, sz;
+ unsigned int i;
+ unsigned char prev[EVP_MAX_MD_SIZE];
+ size_t done_len = 0, dig_len, n;
+
+ sz = EVP_MD_get_size(evp_md);
+ if (sz <= 0)
+ return 0;
+ dig_len = (size_t)sz;
+
+ /* calc: N = ceil(L/HashLen) */
+ n = okm_len / dig_len;
+ if (okm_len % dig_len)
+ n++;
+
+ if (n > 255 || okm == NULL)
+ return 0;
+
+ if ((hmac = HMAC_CTX_new()) == NULL)
+ return 0;
+
+ if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
+ goto err;
+
+ for (i = 1; i <= n; i++) {
+ size_t copy_len;
+ const unsigned char ctr = i;
+
+ /* calc: T(i) = HMAC-Hash(PRK, T(i - 1) | info | i) */
+ if (i > 1) {
+ if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL))
+ goto err;
+
+ if (!HMAC_Update(hmac, prev, dig_len))
+ goto err;
+ }
+
+ if (!HMAC_Update(hmac, info, info_len))
+ goto err;
+
+ if (!HMAC_Update(hmac, &ctr, 1))
+ goto err;
+
+ if (!HMAC_Final(hmac, prev, NULL))
+ goto err;
+
+ copy_len = (done_len + dig_len > okm_len) ?
+ okm_len - done_len :
+ dig_len;
+
+ memcpy(okm + done_len, prev, copy_len);
+
+ done_len += copy_len;
+ }
+ ret = 1;
+
+ err:
+ OPENSSL_cleanse(prev, sizeof(prev));
+ HMAC_CTX_free(hmac);
+ return ret;
+}
+
+/*
+ * TLS uses slight variations of the above and for FIPS validation purposes,
+ * they need to be present here.
+ * Refer to RFC 8446 section 7 for specific details.
+ */
+
+/*
+ * Given a |secret|; a |label| of length |labellen|; and |data| of length
+ * |datalen| (e.g. typically a hash of the handshake messages), derive a new
+ * secret |outlen| bytes long and store it in the location pointed to be |out|.
+ * The |data| value may be zero length. Returns 1 on success and 0 on failure.
+ */
+static int prov_tls13_hkdf_expand(const EVP_MD *md,
+ const unsigned char *key, size_t keylen,
+ const unsigned char *prefix, size_t prefixlen,
+ const unsigned char *label, size_t labellen,
+ const unsigned char *data, size_t datalen,
+ unsigned char *out, size_t outlen)
+{
+ size_t hkdflabellen;
+ unsigned char hkdflabel[HKDF_MAXBUF];
+ WPACKET pkt;
+
+ /*
+ * 2 bytes for length of derived secret + 1 byte for length of combined
+ * prefix and label + bytes for the label itself + 1 byte length of hash
+ * + bytes for the hash itself. We've got the maximum the KDF can handle
+ * which should always be sufficient.
+ */
+ if (!WPACKET_init_static_len(&pkt, hkdflabel, sizeof(hkdflabel), 0)
+ || !WPACKET_put_bytes_u16(&pkt, outlen)
+ || !WPACKET_start_sub_packet_u8(&pkt)
+ || !WPACKET_memcpy(&pkt, prefix, prefixlen)
+ || !WPACKET_memcpy(&pkt, label, labellen)
+ || !WPACKET_close(&pkt)
+ || !WPACKET_sub_memcpy_u8(&pkt, data, (data == NULL) ? 0 : datalen)
+ || !WPACKET_get_total_written(&pkt, &hkdflabellen)
+ || !WPACKET_finish(&pkt)) {
+ WPACKET_cleanup(&pkt);
+ return 0;
+ }
+
+ return HKDF_Expand(md, key, keylen, hkdflabel, hkdflabellen,
+ out, outlen);
+}
+
+static int prov_tls13_hkdf_generate_secret(OSSL_LIB_CTX *libctx,
+ const EVP_MD *md,
+ const unsigned char *prevsecret,
+ size_t prevsecretlen,
+ const unsigned char *insecret,
+ size_t insecretlen,
+ const unsigned char *prefix,
+ size_t prefixlen,
+ const unsigned char *label,
+ size_t labellen,
+ unsigned char *out, size_t outlen)
+{
+ size_t mdlen;
+ int ret;
+ unsigned char preextractsec[EVP_MAX_MD_SIZE];
+ /* Always filled with zeros */
+ static const unsigned char default_zeros[EVP_MAX_MD_SIZE];
+
+ ret = EVP_MD_get_size(md);
+ /* Ensure cast to size_t is safe */
+ if (ret <= 0)
+ return 0;
+ mdlen = (size_t)ret;
+
+ if (insecret == NULL) {
+ insecret = default_zeros;
+ insecretlen = mdlen;
+ }
+ if (prevsecret == NULL) {
+ prevsecret = default_zeros;
+ prevsecretlen = 0;
+ } else {
+ EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+ unsigned char hash[EVP_MAX_MD_SIZE];
+
+ /* The pre-extract derive step uses a hash of no messages */
+ if (mctx == NULL
+ || EVP_DigestInit_ex(mctx, md, NULL) <= 0
+ || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
+ EVP_MD_CTX_free(mctx);
+ return 0;
+ }
+ EVP_MD_CTX_free(mctx);
+
+ /* Generate the pre-extract secret */
+ if (!prov_tls13_hkdf_expand(md, prevsecret, mdlen,
+ prefix, prefixlen, label, labellen,
+ hash, mdlen, preextractsec, mdlen))
+ return 0;
+ prevsecret = preextractsec;
+ prevsecretlen = mdlen;
+ }
+
+ ret = HKDF_Extract(libctx, md, prevsecret, prevsecretlen,
+ insecret, insecretlen, out, outlen);
+
+ if (prevsecret == preextractsec)
+ OPENSSL_cleanse(preextractsec, mdlen);
+ return ret;
+}
+
+static int kdf_tls1_3_derive(void *vctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ KDF_HKDF *ctx = (KDF_HKDF *)vctx;
+ const EVP_MD *md;
+
+ if (!ossl_prov_is_running() || !kdf_tls1_3_set_ctx_params(ctx, params))
+ return 0;
+
+ md = ossl_prov_digest_md(&ctx->digest);
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
+ return 0;
+ }
+
+ switch (ctx->mode) {
+ default:
+ return 0;
+
+ case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
+ return prov_tls13_hkdf_generate_secret(PROV_LIBCTX_OF(ctx->provctx),
+ md,
+ ctx->salt, ctx->salt_len,
+ ctx->key, ctx->key_len,
+ ctx->prefix, ctx->prefix_len,
+ ctx->label, ctx->label_len,
+ key, keylen);
+
+ case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
+ return prov_tls13_hkdf_expand(md, ctx->key, ctx->key_len,
+ ctx->prefix, ctx->prefix_len,
+ ctx->label, ctx->label_len,
+ ctx->data, ctx->data_len,
+ key, keylen);
+ }
+}
+
+static int kdf_tls1_3_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ KDF_HKDF *ctx = vctx;
+
+ if (params == NULL)
+ return 1;
+
+ if (!hkdf_common_set_ctx_params(ctx, params))
+ return 0;
+
+ if (ctx->mode == EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
+ return 0;
+ }
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PREFIX)) != NULL) {
+ OPENSSL_free(ctx->prefix);
+ ctx->prefix = NULL;
+ if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->prefix, 0,
+ &ctx->prefix_len))
+ return 0;
+ }
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_LABEL)) != NULL) {
+ OPENSSL_free(ctx->label);
+ ctx->label = NULL;
+ if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->label, 0,
+ &ctx->label_len))
+ return 0;
+ }
+
+ OPENSSL_clear_free(ctx->data, ctx->data_len);
+ ctx->data = NULL;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DATA)) != NULL
+ && !OSSL_PARAM_get_octet_string(p, (void **)&ctx->data, 0,
+ &ctx->data_len))
+ return 0;
+ return 1;
+}
+
+static const OSSL_PARAM *kdf_tls1_3_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ HKDF_COMMON_SETTABLES,
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PREFIX, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_LABEL, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_DATA, NULL, 0),
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_kdf_tls1_3_kdf_functions[] = {
+ { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new },
+ { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free },
+ { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset },
+ { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_tls1_3_derive },
+ { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_tls1_3_settable_ctx_params },
+ { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_tls1_3_set_ctx_params },
+ { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_hkdf_gettable_ctx_params },
+ { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_hkdf_get_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/kdfs/kbkdf.c b/providers/implementations/kdfs/kbkdf.c
new file mode 100644
index 000000000000..a542f84dfa5b
--- /dev/null
+++ b/providers/implementations/kdfs/kbkdf.c
@@ -0,0 +1,395 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019 Red Hat, Inc.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This implements https://csrc.nist.gov/publications/detail/sp/800-108/final
+ * section 5.1 ("counter mode") and section 5.2 ("feedback mode") in both HMAC
+ * and CMAC. That document does not name the KDFs it defines; the name is
+ * derived from
+ * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Key-Derivation
+ *
+ * Note that section 5.3 ("double-pipeline mode") is not implemented, though
+ * it would be possible to do so in the future.
+ *
+ * These versions all assume the counter is used. It would be relatively
+ * straightforward to expose a configuration handle should the need arise.
+ *
+ * Variable names attempt to match those of SP800-108.
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/core_names.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/kdf.h>
+#include <openssl/params.h>
+#include <openssl/proverr.h>
+
+#include "internal/cryptlib.h"
+#include "crypto/evp.h"
+#include "internal/numbers.h"
+#include "internal/endian.h"
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/provider_util.h"
+#include "prov/providercommon.h"
+
+#include "e_os.h"
+
+#define ossl_min(a, b) ((a) < (b)) ? (a) : (b)
+
+typedef enum {
+ COUNTER = 0,
+ FEEDBACK
+} kbkdf_mode;
+
+/* Our context structure. */
+typedef struct {
+ void *provctx;
+ kbkdf_mode mode;
+ EVP_MAC_CTX *ctx_init;
+
+ /* Names are lowercased versions of those found in SP800-108. */
+ unsigned char *ki;
+ size_t ki_len;
+ unsigned char *label;
+ size_t label_len;
+ unsigned char *context;
+ size_t context_len;
+ unsigned char *iv;
+ size_t iv_len;
+ int use_l;
+ int use_separator;
+} KBKDF;
+
+/* Definitions needed for typechecking. */
+static OSSL_FUNC_kdf_newctx_fn kbkdf_new;
+static OSSL_FUNC_kdf_freectx_fn kbkdf_free;
+static OSSL_FUNC_kdf_reset_fn kbkdf_reset;
+static OSSL_FUNC_kdf_derive_fn kbkdf_derive;
+static OSSL_FUNC_kdf_settable_ctx_params_fn kbkdf_settable_ctx_params;
+static OSSL_FUNC_kdf_set_ctx_params_fn kbkdf_set_ctx_params;
+static OSSL_FUNC_kdf_gettable_ctx_params_fn kbkdf_gettable_ctx_params;
+static OSSL_FUNC_kdf_get_ctx_params_fn kbkdf_get_ctx_params;
+
+/* Not all platforms have htobe32(). */
+static uint32_t be32(uint32_t host)
+{
+ uint32_t big = 0;
+ DECLARE_IS_ENDIAN;
+
+ if (!IS_LITTLE_ENDIAN)
+ return host;
+
+ big |= (host & 0xff000000) >> 24;
+ big |= (host & 0x00ff0000) >> 8;
+ big |= (host & 0x0000ff00) << 8;
+ big |= (host & 0x000000ff) << 24;
+ return big;
+}
+
+static void init(KBKDF *ctx)
+{
+ ctx->use_l = 1;
+ ctx->use_separator = 1;
+}
+
+static void *kbkdf_new(void *provctx)
+{
+ KBKDF *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ ctx->provctx = provctx;
+ init(ctx);
+ return ctx;
+}
+
+static void kbkdf_free(void *vctx)
+{
+ KBKDF *ctx = (KBKDF *)vctx;
+
+ if (ctx != NULL) {
+ kbkdf_reset(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+static void kbkdf_reset(void *vctx)
+{
+ KBKDF *ctx = (KBKDF *)vctx;
+ void *provctx = ctx->provctx;
+
+ EVP_MAC_CTX_free(ctx->ctx_init);
+ OPENSSL_clear_free(ctx->context, ctx->context_len);
+ OPENSSL_clear_free(ctx->label, ctx->label_len);
+ OPENSSL_clear_free(ctx->ki, ctx->ki_len);
+ OPENSSL_clear_free(ctx->iv, ctx->iv_len);
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->provctx = provctx;
+ init(ctx);
+}
+
+/* SP800-108 section 5.1 or section 5.2 depending on mode. */
+static int derive(EVP_MAC_CTX *ctx_init, kbkdf_mode mode, unsigned char *iv,
+ size_t iv_len, unsigned char *label, size_t label_len,
+ unsigned char *context, size_t context_len,
+ unsigned char *k_i, size_t h, uint32_t l, int has_separator,
+ unsigned char *ko, size_t ko_len)
+{
+ int ret = 0;
+ EVP_MAC_CTX *ctx = NULL;
+ size_t written = 0, to_write, k_i_len = iv_len;
+ const unsigned char zero = 0;
+ uint32_t counter, i;
+ /*
+ * From SP800-108:
+ * The fixed input data is a concatenation of a Label,
+ * a separation indicator 0x00, the Context, and L.
+ * One or more of these fixed input data fields may be omitted.
+ *
+ * has_separator == 0 means that the separator is omitted.
+ * Passing a value of l == 0 means that L is omitted.
+ * The Context and L are omitted automatically if a NULL buffer is passed.
+ */
+ int has_l = (l != 0);
+
+ /* Setup K(0) for feedback mode. */
+ if (iv_len > 0)
+ memcpy(k_i, iv, iv_len);
+
+ for (counter = 1; written < ko_len; counter++) {
+ i = be32(counter);
+
+ ctx = EVP_MAC_CTX_dup(ctx_init);
+ if (ctx == NULL)
+ goto done;
+
+ /* Perform feedback, if appropriate. */
+ if (mode == FEEDBACK && !EVP_MAC_update(ctx, k_i, k_i_len))
+ goto done;
+
+ if (!EVP_MAC_update(ctx, (unsigned char *)&i, 4)
+ || !EVP_MAC_update(ctx, label, label_len)
+ || (has_separator && !EVP_MAC_update(ctx, &zero, 1))
+ || !EVP_MAC_update(ctx, context, context_len)
+ || (has_l && !EVP_MAC_update(ctx, (unsigned char *)&l, 4))
+ || !EVP_MAC_final(ctx, k_i, NULL, h))
+ goto done;
+
+ to_write = ko_len - written;
+ memcpy(ko + written, k_i, ossl_min(to_write, h));
+ written += h;
+
+ k_i_len = h;
+ EVP_MAC_CTX_free(ctx);
+ ctx = NULL;
+ }
+
+ ret = 1;
+done:
+ EVP_MAC_CTX_free(ctx);
+ return ret;
+}
+
+static int kbkdf_derive(void *vctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ KBKDF *ctx = (KBKDF *)vctx;
+ int ret = 0;
+ unsigned char *k_i = NULL;
+ uint32_t l = 0;
+ size_t h = 0;
+
+ if (!ossl_prov_is_running() || !kbkdf_set_ctx_params(ctx, params))
+ return 0;
+
+ /* label, context, and iv are permitted to be empty. Check everything
+ * else. */
+ if (ctx->ctx_init == NULL) {
+ if (ctx->ki_len == 0 || ctx->ki == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
+ return 0;
+ }
+ /* Could either be missing MAC or missing message digest or missing
+ * cipher - arbitrarily, I pick this one. */
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MAC);
+ return 0;
+ }
+
+ /* Fail if the output length is zero */
+ if (keylen == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+
+ h = EVP_MAC_CTX_get_mac_size(ctx->ctx_init);
+ if (h == 0)
+ goto done;
+ if (ctx->iv_len != 0 && ctx->iv_len != h) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SEED_LENGTH);
+ goto done;
+ }
+
+ if (ctx->use_l != 0)
+ l = be32(keylen * 8);
+
+ k_i = OPENSSL_zalloc(h);
+ if (k_i == NULL)
+ goto done;
+
+ ret = derive(ctx->ctx_init, ctx->mode, ctx->iv, ctx->iv_len, ctx->label,
+ ctx->label_len, ctx->context, ctx->context_len, k_i, h, l,
+ ctx->use_separator, key, keylen);
+done:
+ if (ret != 1)
+ OPENSSL_cleanse(key, keylen);
+ OPENSSL_clear_free(k_i, h);
+ return ret;
+}
+
+static int kbkdf_set_buffer(unsigned char **out, size_t *out_len,
+ const OSSL_PARAM *p)
+{
+ if (p->data == NULL || p->data_size == 0)
+ return 1;
+
+ OPENSSL_clear_free(*out, *out_len);
+ *out = NULL;
+ return OSSL_PARAM_get_octet_string(p, (void **)out, 0, out_len);
+}
+
+static int kbkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ KBKDF *ctx = (KBKDF *)vctx;
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
+ const OSSL_PARAM *p;
+
+ if (params == NULL)
+ return 1;
+
+ if (!ossl_prov_macctx_load_from_params(&ctx->ctx_init, params, NULL,
+ NULL, NULL, libctx))
+ return 0;
+ else if (ctx->ctx_init != NULL
+ && !EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->ctx_init),
+ OSSL_MAC_NAME_HMAC)
+ && !EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->ctx_init),
+ OSSL_MAC_NAME_CMAC)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MAC);
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE);
+ if (p != NULL
+ && OPENSSL_strncasecmp("counter", p->data, p->data_size) == 0) {
+ ctx->mode = COUNTER;
+ } else if (p != NULL
+ && OPENSSL_strncasecmp("feedback", p->data, p->data_size) == 0) {
+ ctx->mode = FEEDBACK;
+ } else if (p != NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY);
+ if (p != NULL && !kbkdf_set_buffer(&ctx->ki, &ctx->ki_len, p))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT);
+ if (p != NULL && !kbkdf_set_buffer(&ctx->label, &ctx->label_len, p))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO);
+ if (p != NULL && !kbkdf_set_buffer(&ctx->context, &ctx->context_len, p))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SEED);
+ if (p != NULL && !kbkdf_set_buffer(&ctx->iv, &ctx->iv_len, p))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KBKDF_USE_L);
+ if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->use_l))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR);
+ if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->use_separator))
+ return 0;
+
+ /* Set up digest context, if we can. */
+ if (ctx->ctx_init != NULL && ctx->ki_len != 0
+ && !EVP_MAC_init(ctx->ctx_init, ctx->ki, ctx->ki_len, NULL))
+ return 0;
+ return 1;
+}
+
+static const OSSL_PARAM *kbkdf_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SEED, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CIPHER, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MAC, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_int(OSSL_KDF_PARAM_KBKDF_USE_L, NULL),
+ OSSL_PARAM_int(OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR, NULL),
+ OSSL_PARAM_END,
+ };
+ return known_settable_ctx_params;
+}
+
+static int kbkdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE);
+ if (p == NULL)
+ return -2;
+
+ /* KBKDF can produce results as large as you like. */
+ return OSSL_PARAM_set_size_t(p, SIZE_MAX);
+}
+
+static const OSSL_PARAM *kbkdf_gettable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] =
+ { OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), OSSL_PARAM_END };
+ return known_gettable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_kdf_kbkdf_functions[] = {
+ { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kbkdf_new },
+ { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kbkdf_free },
+ { OSSL_FUNC_KDF_RESET, (void(*)(void))kbkdf_reset },
+ { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kbkdf_derive },
+ { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
+ (void(*)(void))kbkdf_settable_ctx_params },
+ { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kbkdf_set_ctx_params },
+ { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
+ (void(*)(void))kbkdf_gettable_ctx_params },
+ { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kbkdf_get_ctx_params },
+ { 0, NULL },
+};
diff --git a/providers/implementations/kdfs/krb5kdf.c b/providers/implementations/kdfs/krb5kdf.c
new file mode 100644
index 000000000000..8516a3f824af
--- /dev/null
+++ b/providers/implementations/kdfs/krb5kdf.c
@@ -0,0 +1,467 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DES low level APIs are deprecated for public use, but still ok for internal
+ * use. We access the DES_set_odd_parity(3) function here.
+ */
+#include "internal/deprecated.h"
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <openssl/core_names.h>
+#include <openssl/des.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/proverr.h>
+
+#include "internal/cryptlib.h"
+#include "crypto/evp.h"
+#include "internal/numbers.h"
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/provider_util.h"
+#include "prov/providercommon.h"
+
+/* KRB5 KDF defined in RFC 3961, Section 5.1 */
+
+static OSSL_FUNC_kdf_newctx_fn krb5kdf_new;
+static OSSL_FUNC_kdf_freectx_fn krb5kdf_free;
+static OSSL_FUNC_kdf_reset_fn krb5kdf_reset;
+static OSSL_FUNC_kdf_derive_fn krb5kdf_derive;
+static OSSL_FUNC_kdf_settable_ctx_params_fn krb5kdf_settable_ctx_params;
+static OSSL_FUNC_kdf_set_ctx_params_fn krb5kdf_set_ctx_params;
+static OSSL_FUNC_kdf_gettable_ctx_params_fn krb5kdf_gettable_ctx_params;
+static OSSL_FUNC_kdf_get_ctx_params_fn krb5kdf_get_ctx_params;
+
+static int KRB5KDF(const EVP_CIPHER *cipher, ENGINE *engine,
+ const unsigned char *key, size_t key_len,
+ const unsigned char *constant, size_t constant_len,
+ unsigned char *okey, size_t okey_len);
+
+typedef struct {
+ void *provctx;
+ PROV_CIPHER cipher;
+ unsigned char *key;
+ size_t key_len;
+ unsigned char *constant;
+ size_t constant_len;
+} KRB5KDF_CTX;
+
+static void *krb5kdf_new(void *provctx)
+{
+ KRB5KDF_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ ctx->provctx = provctx;
+ return ctx;
+}
+
+static void krb5kdf_free(void *vctx)
+{
+ KRB5KDF_CTX *ctx = (KRB5KDF_CTX *)vctx;
+
+ if (ctx != NULL) {
+ krb5kdf_reset(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+static void krb5kdf_reset(void *vctx)
+{
+ KRB5KDF_CTX *ctx = (KRB5KDF_CTX *)vctx;
+ void *provctx = ctx->provctx;
+
+ ossl_prov_cipher_reset(&ctx->cipher);
+ OPENSSL_clear_free(ctx->key, ctx->key_len);
+ OPENSSL_clear_free(ctx->constant, ctx->constant_len);
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->provctx = provctx;
+}
+
+static int krb5kdf_set_membuf(unsigned char **dst, size_t *dst_len,
+ const OSSL_PARAM *p)
+{
+ OPENSSL_clear_free(*dst, *dst_len);
+ *dst = NULL;
+ *dst_len = 0;
+ return OSSL_PARAM_get_octet_string(p, (void **)dst, 0, dst_len);
+}
+
+static int krb5kdf_derive(void *vctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ KRB5KDF_CTX *ctx = (KRB5KDF_CTX *)vctx;
+ const EVP_CIPHER *cipher;
+ ENGINE *engine;
+
+ if (!ossl_prov_is_running() || !krb5kdf_set_ctx_params(ctx, params))
+ return 0;
+
+ cipher = ossl_prov_cipher_cipher(&ctx->cipher);
+ if (cipher == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CIPHER);
+ return 0;
+ }
+ if (ctx->key == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
+ return 0;
+ }
+ if (ctx->constant == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CONSTANT);
+ return 0;
+ }
+ engine = ossl_prov_cipher_engine(&ctx->cipher);
+ return KRB5KDF(cipher, engine, ctx->key, ctx->key_len,
+ ctx->constant, ctx->constant_len,
+ key, keylen);
+}
+
+static int krb5kdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ KRB5KDF_CTX *ctx = vctx;
+ OSSL_LIB_CTX *provctx = PROV_LIBCTX_OF(ctx->provctx);
+
+ if (params == NULL)
+ return 1;
+
+ if (!ossl_prov_cipher_load_from_params(&ctx->cipher, params, provctx))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL)
+ if (!krb5kdf_set_membuf(&ctx->key, &ctx->key_len, p))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_CONSTANT))
+ != NULL)
+ if (!krb5kdf_set_membuf(&ctx->constant, &ctx->constant_len, p))
+ return 0;
+
+ return 1;
+}
+
+static const OSSL_PARAM *krb5kdf_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CIPHER, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_CONSTANT, NULL, 0),
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+static int krb5kdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ KRB5KDF_CTX *ctx = (KRB5KDF_CTX *)vctx;
+ const EVP_CIPHER *cipher;
+ size_t len;
+ OSSL_PARAM *p;
+
+ cipher = ossl_prov_cipher_cipher(&ctx->cipher);
+ if (cipher)
+ len = EVP_CIPHER_get_key_length(cipher);
+ else
+ len = EVP_MAX_KEY_LENGTH;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
+ return OSSL_PARAM_set_size_t(p, len);
+ return -2;
+}
+
+static const OSSL_PARAM *krb5kdf_gettable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_kdf_krb5kdf_functions[] = {
+ { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))krb5kdf_new },
+ { OSSL_FUNC_KDF_FREECTX, (void(*)(void))krb5kdf_free },
+ { OSSL_FUNC_KDF_RESET, (void(*)(void))krb5kdf_reset },
+ { OSSL_FUNC_KDF_DERIVE, (void(*)(void))krb5kdf_derive },
+ { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
+ (void(*)(void))krb5kdf_settable_ctx_params },
+ { OSSL_FUNC_KDF_SET_CTX_PARAMS,
+ (void(*)(void))krb5kdf_set_ctx_params },
+ { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
+ (void(*)(void))krb5kdf_gettable_ctx_params },
+ { OSSL_FUNC_KDF_GET_CTX_PARAMS,
+ (void(*)(void))krb5kdf_get_ctx_params },
+ { 0, NULL }
+};
+
+#ifndef OPENSSL_NO_DES
+/*
+ * DES3 is a special case, it requires a random-to-key function and its
+ * input truncated to 21 bytes of the 24 produced by the cipher.
+ * See RFC3961 6.3.1
+ */
+static int fixup_des3_key(unsigned char *key)
+{
+ unsigned char *cblock;
+ int i, j;
+
+ for (i = 2; i >= 0; i--) {
+ cblock = &key[i * 8];
+ memmove(cblock, &key[i * 7], 7);
+ cblock[7] = 0;
+ for (j = 0; j < 7; j++)
+ cblock[7] |= (cblock[j] & 1) << (j + 1);
+ DES_set_odd_parity((DES_cblock *)cblock);
+ }
+
+ /* fail if keys are such that triple des degrades to single des */
+ if (CRYPTO_memcmp(&key[0], &key[8], 8) == 0 ||
+ CRYPTO_memcmp(&key[8], &key[16], 8) == 0) {
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+/*
+ * N-fold(K) where blocksize is N, and constant_len is K
+ * Note: Here |= denotes concatenation
+ *
+ * L = lcm(N,K)
+ * R = L/K
+ *
+ * for r: 1 -> R
+ * s |= constant rot 13*(r-1))
+ *
+ * block = 0
+ * for k: 1 -> K
+ * block += s[N(k-1)..(N-1)k] (one's complement addition)
+ *
+ * Optimizing for space we compute:
+ * for each l in L-1 -> 0:
+ * s[l] = (constant rot 13*(l/K))[l%k]
+ * block[l % N] += s[l] (with carry)
+ * finally add carry if any
+ */
+static void n_fold(unsigned char *block, unsigned int blocksize,
+ const unsigned char *constant, size_t constant_len)
+{
+ unsigned int tmp, gcd, remainder, lcm, carry;
+ int b, l;
+
+ if (constant_len == blocksize) {
+ memcpy(block, constant, constant_len);
+ return;
+ }
+
+ /* Least Common Multiple of lengths: LCM(a,b)*/
+ gcd = blocksize;
+ remainder = constant_len;
+ /* Calculate Great Common Divisor first GCD(a,b) */
+ while (remainder != 0) {
+ tmp = gcd % remainder;
+ gcd = remainder;
+ remainder = tmp;
+ }
+ /* resulting a is the GCD, LCM(a,b) = |a*b|/GCD(a,b) */
+ lcm = blocksize * constant_len / gcd;
+
+ /* now spread out the bits */
+ memset(block, 0, blocksize);
+
+ /* last to first to be able to bring carry forward */
+ carry = 0;
+ for (l = lcm - 1; l >= 0; l--) {
+ unsigned int rotbits, rshift, rbyte;
+
+ /* destination byte in block is l % N */
+ b = l % blocksize;
+ /* Our virtual s buffer is R = L/K long (K = constant_len) */
+ /* So we rotate backwards from R-1 to 0 (none) rotations */
+ rotbits = 13 * (l / constant_len);
+ /* find the byte on s where rotbits falls onto */
+ rbyte = l - (rotbits / 8);
+ /* calculate how much shift on that byte */
+ rshift = rotbits & 0x07;
+ /* rbyte % constant_len gives us the unrotated byte in the
+ * constant buffer, get also the previous byte then
+ * appropriately shift them to get the rotated byte we need */
+ tmp = (constant[(rbyte-1) % constant_len] << (8 - rshift)
+ | constant[rbyte % constant_len] >> rshift)
+ & 0xff;
+ /* add with carry to any value placed by previous passes */
+ tmp += carry + block[b];
+ block[b] = tmp & 0xff;
+ /* save any carry that may be left */
+ carry = tmp >> 8;
+ }
+
+ /* if any carry is left at the end, add it through the number */
+ for (b = blocksize - 1; b >= 0 && carry != 0; b--) {
+ carry += block[b];
+ block[b] = carry & 0xff;
+ carry >>= 8;
+ }
+}
+
+static int cipher_init(EVP_CIPHER_CTX *ctx,
+ const EVP_CIPHER *cipher, ENGINE *engine,
+ const unsigned char *key, size_t key_len)
+{
+ int klen, ret;
+
+ ret = EVP_EncryptInit_ex(ctx, cipher, engine, key, NULL);
+ if (!ret)
+ goto out;
+ /* set the key len for the odd variable key len cipher */
+ klen = EVP_CIPHER_CTX_get_key_length(ctx);
+ if (key_len != (size_t)klen) {
+ ret = EVP_CIPHER_CTX_set_key_length(ctx, key_len);
+ if (ret <= 0) {
+ ret = 0;
+ goto out;
+ }
+ }
+ /* we never want padding, either the length requested is a multiple of
+ * the cipher block size or we are passed a cipher that can cope with
+ * partial blocks via techniques like cipher text stealing */
+ ret = EVP_CIPHER_CTX_set_padding(ctx, 0);
+ if (!ret)
+ goto out;
+
+out:
+ return ret;
+}
+
+static int KRB5KDF(const EVP_CIPHER *cipher, ENGINE *engine,
+ const unsigned char *key, size_t key_len,
+ const unsigned char *constant, size_t constant_len,
+ unsigned char *okey, size_t okey_len)
+{
+ EVP_CIPHER_CTX *ctx = NULL;
+ unsigned char block[EVP_MAX_BLOCK_LENGTH * 2];
+ unsigned char *plainblock, *cipherblock;
+ size_t blocksize;
+ size_t cipherlen;
+ size_t osize;
+#ifndef OPENSSL_NO_DES
+ int des3_no_fixup = 0;
+#endif
+ int ret;
+
+ if (key_len != okey_len) {
+#ifndef OPENSSL_NO_DES
+ /* special case for 3des, where the caller may be requesting
+ * the random raw key, instead of the fixed up key */
+ if (EVP_CIPHER_get_nid(cipher) == NID_des_ede3_cbc &&
+ key_len == 24 && okey_len == 21) {
+ des3_no_fixup = 1;
+ } else {
+#endif
+ ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_OUTPUT_BUFFER_SIZE);
+ return 0;
+#ifndef OPENSSL_NO_DES
+ }
+#endif
+ }
+
+ ctx = EVP_CIPHER_CTX_new();
+ if (ctx == NULL)
+ return 0;
+
+ ret = cipher_init(ctx, cipher, engine, key, key_len);
+ if (!ret)
+ goto out;
+
+ /* Initialize input block */
+ blocksize = EVP_CIPHER_CTX_get_block_size(ctx);
+
+ if (constant_len > blocksize) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONSTANT_LENGTH);
+ ret = 0;
+ goto out;
+ }
+
+ n_fold(block, blocksize, constant, constant_len);
+ plainblock = block;
+ cipherblock = block + EVP_MAX_BLOCK_LENGTH;
+
+ for (osize = 0; osize < okey_len; osize += cipherlen) {
+ int olen;
+
+ ret = EVP_EncryptUpdate(ctx, cipherblock, &olen,
+ plainblock, blocksize);
+ if (!ret)
+ goto out;
+ cipherlen = olen;
+ ret = EVP_EncryptFinal_ex(ctx, cipherblock, &olen);
+ if (!ret)
+ goto out;
+ if (olen != 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
+ ret = 0;
+ goto out;
+ }
+
+ /* write cipherblock out */
+ if (cipherlen > okey_len - osize)
+ cipherlen = okey_len - osize;
+ memcpy(okey + osize, cipherblock, cipherlen);
+
+ if (okey_len > osize + cipherlen) {
+ /* we need to reinitialize cipher context per spec */
+ ret = EVP_CIPHER_CTX_reset(ctx);
+ if (!ret)
+ goto out;
+ ret = cipher_init(ctx, cipher, engine, key, key_len);
+ if (!ret)
+ goto out;
+
+ /* also swap block offsets so last ciphertext becomes new
+ * plaintext */
+ plainblock = cipherblock;
+ if (cipherblock == block) {
+ cipherblock += EVP_MAX_BLOCK_LENGTH;
+ } else {
+ cipherblock = block;
+ }
+ }
+ }
+
+#ifndef OPENSSL_NO_DES
+ if (EVP_CIPHER_get_nid(cipher) == NID_des_ede3_cbc && !des3_no_fixup) {
+ ret = fixup_des3_key(okey);
+ if (!ret) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GENERATE_KEY);
+ goto out;
+ }
+ }
+#endif
+
+ ret = 1;
+
+out:
+ EVP_CIPHER_CTX_free(ctx);
+ OPENSSL_cleanse(block, EVP_MAX_BLOCK_LENGTH * 2);
+ return ret;
+}
+
diff --git a/providers/implementations/kdfs/pbkdf1.c b/providers/implementations/kdfs/pbkdf1.c
new file mode 100644
index 000000000000..1a042bac9f52
--- /dev/null
+++ b/providers/implementations/kdfs/pbkdf1.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/trace.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#include <openssl/proverr.h>
+#include "internal/cryptlib.h"
+#include "internal/numbers.h"
+#include "crypto/evp.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_util.h"
+
+static OSSL_FUNC_kdf_newctx_fn kdf_pbkdf1_new;
+static OSSL_FUNC_kdf_freectx_fn kdf_pbkdf1_free;
+static OSSL_FUNC_kdf_reset_fn kdf_pbkdf1_reset;
+static OSSL_FUNC_kdf_derive_fn kdf_pbkdf1_derive;
+static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_pbkdf1_settable_ctx_params;
+static OSSL_FUNC_kdf_set_ctx_params_fn kdf_pbkdf1_set_ctx_params;
+static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_pbkdf1_gettable_ctx_params;
+static OSSL_FUNC_kdf_get_ctx_params_fn kdf_pbkdf1_get_ctx_params;
+
+typedef struct {
+ void *provctx;
+ PROV_DIGEST digest;
+ unsigned char *pass;
+ size_t pass_len;
+ unsigned char *salt;
+ size_t salt_len;
+ uint64_t iter;
+} KDF_PBKDF1;
+
+/*
+ * PKCS5 PBKDF1 compatible key/IV generation as specified in:
+ * https://tools.ietf.org/html/rfc8018#page-10
+ */
+
+static int kdf_pbkdf1_do_derive(const unsigned char *pass, size_t passlen,
+ const unsigned char *salt, size_t saltlen,
+ uint64_t iter, const EVP_MD *md_type,
+ unsigned char *out, size_t n)
+{
+ uint64_t i;
+ int mdsize, ret = 0;
+ unsigned char md_tmp[EVP_MAX_MD_SIZE];
+ EVP_MD_CTX *ctx = NULL;
+
+ ctx = EVP_MD_CTX_new();
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EVP_DigestInit_ex(ctx, md_type, NULL)
+ || !EVP_DigestUpdate(ctx, pass, passlen)
+ || !EVP_DigestUpdate(ctx, salt, saltlen)
+ || !EVP_DigestFinal_ex(ctx, md_tmp, NULL))
+ goto err;
+ mdsize = EVP_MD_size(md_type);
+ if (mdsize < 0)
+ goto err;
+ for (i = 1; i < iter; i++) {
+ if (!EVP_DigestInit_ex(ctx, md_type, NULL))
+ goto err;
+ if (!EVP_DigestUpdate(ctx, md_tmp, mdsize))
+ goto err;
+ if (!EVP_DigestFinal_ex(ctx, md_tmp, NULL))
+ goto err;
+ }
+
+ memcpy(out, md_tmp, n);
+ ret = 1;
+err:
+ EVP_MD_CTX_free(ctx);
+ return ret;
+}
+
+static void *kdf_pbkdf1_new(void *provctx)
+{
+ KDF_PBKDF1 *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ ctx->provctx = provctx;
+ return ctx;
+}
+
+static void kdf_pbkdf1_cleanup(KDF_PBKDF1 *ctx)
+{
+ ossl_prov_digest_reset(&ctx->digest);
+ OPENSSL_free(ctx->salt);
+ OPENSSL_clear_free(ctx->pass, ctx->pass_len);
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+static void kdf_pbkdf1_free(void *vctx)
+{
+ KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
+
+ if (ctx != NULL) {
+ kdf_pbkdf1_cleanup(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+static void kdf_pbkdf1_reset(void *vctx)
+{
+ KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
+ void *provctx = ctx->provctx;
+
+ kdf_pbkdf1_cleanup(ctx);
+ ctx->provctx = provctx;
+}
+
+static int kdf_pbkdf1_set_membuf(unsigned char **buffer, size_t *buflen,
+ const OSSL_PARAM *p)
+{
+ OPENSSL_clear_free(*buffer, *buflen);
+ *buffer = NULL;
+ *buflen = 0;
+
+ if (p->data_size == 0) {
+ if ((*buffer = OPENSSL_malloc(1)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else if (p->data != NULL) {
+ if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen))
+ return 0;
+ }
+ return 1;
+}
+
+static int kdf_pbkdf1_derive(void *vctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
+ const EVP_MD *md;
+
+ if (!ossl_prov_is_running() || !kdf_pbkdf1_set_ctx_params(ctx, params))
+ return 0;
+
+ if (ctx->pass == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);
+ return 0;
+ }
+
+ if (ctx->salt == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
+ return 0;
+ }
+
+ md = ossl_prov_digest_md(&ctx->digest);
+ return kdf_pbkdf1_do_derive(ctx->pass, ctx->pass_len, ctx->salt, ctx->salt_len,
+ ctx->iter, md, key, keylen);
+}
+
+static int kdf_pbkdf1_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ KDF_PBKDF1 *ctx = vctx;
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
+
+ if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)
+ if (!kdf_pbkdf1_set_membuf(&ctx->pass, &ctx->pass_len, p))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)
+ if (!kdf_pbkdf1_set_membuf(&ctx->salt, &ctx->salt_len,p))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ITER)) != NULL)
+ if (!OSSL_PARAM_get_uint64(p, &ctx->iter))
+ return 0;
+ return 1;
+}
+
+static const OSSL_PARAM *kdf_pbkdf1_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *p_ctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
+ OSSL_PARAM_uint64(OSSL_KDF_PARAM_ITER, NULL),
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+static int kdf_pbkdf1_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
+ return OSSL_PARAM_set_size_t(p, SIZE_MAX);
+ return -2;
+}
+
+static const OSSL_PARAM *kdf_pbkdf1_gettable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *p_ctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_kdf_pbkdf1_functions[] = {
+ { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pbkdf1_new },
+ { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pbkdf1_free },
+ { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pbkdf1_reset },
+ { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pbkdf1_derive },
+ { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_pbkdf1_settable_ctx_params },
+ { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pbkdf1_set_ctx_params },
+ { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_pbkdf1_gettable_ctx_params },
+ { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pbkdf1_get_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/kdfs/pbkdf2.c b/providers/implementations/kdfs/pbkdf2.c
new file mode 100644
index 000000000000..2a0ae63acc32
--- /dev/null
+++ b/providers/implementations/kdfs/pbkdf2.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * HMAC low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#include <openssl/proverr.h>
+#include "internal/cryptlib.h"
+#include "internal/numbers.h"
+#include "crypto/evp.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_util.h"
+#include "pbkdf2.h"
+
+/* Constants specified in SP800-132 */
+#define KDF_PBKDF2_MIN_KEY_LEN_BITS 112
+#define KDF_PBKDF2_MAX_KEY_LEN_DIGEST_RATIO 0xFFFFFFFF
+#define KDF_PBKDF2_MIN_ITERATIONS 1000
+#define KDF_PBKDF2_MIN_SALT_LEN (128 / 8)
+
+static OSSL_FUNC_kdf_newctx_fn kdf_pbkdf2_new;
+static OSSL_FUNC_kdf_freectx_fn kdf_pbkdf2_free;
+static OSSL_FUNC_kdf_reset_fn kdf_pbkdf2_reset;
+static OSSL_FUNC_kdf_derive_fn kdf_pbkdf2_derive;
+static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_pbkdf2_settable_ctx_params;
+static OSSL_FUNC_kdf_set_ctx_params_fn kdf_pbkdf2_set_ctx_params;
+static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_pbkdf2_gettable_ctx_params;
+static OSSL_FUNC_kdf_get_ctx_params_fn kdf_pbkdf2_get_ctx_params;
+
+static int pbkdf2_derive(const char *pass, size_t passlen,
+ const unsigned char *salt, int saltlen, uint64_t iter,
+ const EVP_MD *digest, unsigned char *key,
+ size_t keylen, int extra_checks);
+
+typedef struct {
+ void *provctx;
+ unsigned char *pass;
+ size_t pass_len;
+ unsigned char *salt;
+ size_t salt_len;
+ uint64_t iter;
+ PROV_DIGEST digest;
+ int lower_bound_checks;
+} KDF_PBKDF2;
+
+static void kdf_pbkdf2_init(KDF_PBKDF2 *ctx);
+
+static void *kdf_pbkdf2_new(void *provctx)
+{
+ KDF_PBKDF2 *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ ctx->provctx = provctx;
+ kdf_pbkdf2_init(ctx);
+ return ctx;
+}
+
+static void kdf_pbkdf2_cleanup(KDF_PBKDF2 *ctx)
+{
+ ossl_prov_digest_reset(&ctx->digest);
+ OPENSSL_free(ctx->salt);
+ OPENSSL_clear_free(ctx->pass, ctx->pass_len);
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+static void kdf_pbkdf2_free(void *vctx)
+{
+ KDF_PBKDF2 *ctx = (KDF_PBKDF2 *)vctx;
+
+ if (ctx != NULL) {
+ kdf_pbkdf2_cleanup(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+static void kdf_pbkdf2_reset(void *vctx)
+{
+ KDF_PBKDF2 *ctx = (KDF_PBKDF2 *)vctx;
+ void *provctx = ctx->provctx;
+
+ kdf_pbkdf2_cleanup(ctx);
+ ctx->provctx = provctx;
+ kdf_pbkdf2_init(ctx);
+}
+
+static void kdf_pbkdf2_init(KDF_PBKDF2 *ctx)
+{
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ OSSL_LIB_CTX *provctx = PROV_LIBCTX_OF(ctx->provctx);
+
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ SN_sha1, 0);
+ if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
+ /* This is an error, but there is no way to indicate such directly */
+ ossl_prov_digest_reset(&ctx->digest);
+ ctx->iter = PKCS5_DEFAULT_ITER;
+ ctx->lower_bound_checks = ossl_kdf_pbkdf2_default_checks;
+}
+
+static int pbkdf2_set_membuf(unsigned char **buffer, size_t *buflen,
+ const OSSL_PARAM *p)
+{
+ OPENSSL_clear_free(*buffer, *buflen);
+ *buffer = NULL;
+ *buflen = 0;
+
+ if (p->data_size == 0) {
+ if ((*buffer = OPENSSL_malloc(1)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else if (p->data != NULL) {
+ if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen))
+ return 0;
+ }
+ return 1;
+}
+
+static int kdf_pbkdf2_derive(void *vctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ KDF_PBKDF2 *ctx = (KDF_PBKDF2 *)vctx;
+ const EVP_MD *md;
+
+ if (!ossl_prov_is_running() || !kdf_pbkdf2_set_ctx_params(ctx, params))
+ return 0;
+
+ if (ctx->pass == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);
+ return 0;
+ }
+
+ if (ctx->salt == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
+ return 0;
+ }
+
+ md = ossl_prov_digest_md(&ctx->digest);
+ return pbkdf2_derive((char *)ctx->pass, ctx->pass_len,
+ ctx->salt, ctx->salt_len, ctx->iter,
+ md, key, keylen, ctx->lower_bound_checks);
+}
+
+static int kdf_pbkdf2_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ KDF_PBKDF2 *ctx = vctx;
+ OSSL_LIB_CTX *provctx = PROV_LIBCTX_OF(ctx->provctx);
+ int pkcs5;
+ uint64_t iter, min_iter;
+
+ if (params == NULL)
+ return 1;
+
+ if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PKCS5)) != NULL) {
+ if (!OSSL_PARAM_get_int(p, &pkcs5))
+ return 0;
+ ctx->lower_bound_checks = pkcs5 == 0;
+ }
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)
+ if (!pbkdf2_set_membuf(&ctx->pass, &ctx->pass_len, p))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) {
+ if (ctx->lower_bound_checks != 0
+ && p->data_size < KDF_PBKDF2_MIN_SALT_LEN) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH);
+ return 0;
+ }
+ if (!pbkdf2_set_membuf(&ctx->salt, &ctx->salt_len,p))
+ return 0;
+ }
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ITER)) != NULL) {
+ if (!OSSL_PARAM_get_uint64(p, &iter))
+ return 0;
+ min_iter = ctx->lower_bound_checks != 0 ? KDF_PBKDF2_MIN_ITERATIONS : 1;
+ if (iter < min_iter) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT);
+ return 0;
+ }
+ ctx->iter = iter;
+ }
+ return 1;
+}
+
+static const OSSL_PARAM *kdf_pbkdf2_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *p_ctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
+ OSSL_PARAM_uint64(OSSL_KDF_PARAM_ITER, NULL),
+ OSSL_PARAM_int(OSSL_KDF_PARAM_PKCS5, NULL),
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+static int kdf_pbkdf2_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
+ return OSSL_PARAM_set_size_t(p, SIZE_MAX);
+ return -2;
+}
+
+static const OSSL_PARAM *kdf_pbkdf2_gettable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *p_ctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_kdf_pbkdf2_functions[] = {
+ { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pbkdf2_new },
+ { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pbkdf2_free },
+ { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pbkdf2_reset },
+ { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pbkdf2_derive },
+ { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_pbkdf2_settable_ctx_params },
+ { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pbkdf2_set_ctx_params },
+ { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_pbkdf2_gettable_ctx_params },
+ { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pbkdf2_get_ctx_params },
+ { 0, NULL }
+};
+
+/*
+ * This is an implementation of PKCS#5 v2.0 password based encryption key
+ * derivation function PBKDF2. SHA1 version verified against test vectors
+ * posted by Peter Gutmann to the PKCS-TNG mailing list.
+ *
+ * The constraints specified by SP800-132 have been added i.e.
+ * - Check the range of the key length.
+ * - Minimum iteration count of 1000.
+ * - Randomly-generated portion of the salt shall be at least 128 bits.
+ */
+static int pbkdf2_derive(const char *pass, size_t passlen,
+ const unsigned char *salt, int saltlen, uint64_t iter,
+ const EVP_MD *digest, unsigned char *key,
+ size_t keylen, int lower_bound_checks)
+{
+ int ret = 0;
+ unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
+ int cplen, k, tkeylen, mdlen;
+ uint64_t j;
+ unsigned long i = 1;
+ HMAC_CTX *hctx_tpl = NULL, *hctx = NULL;
+
+ mdlen = EVP_MD_get_size(digest);
+ if (mdlen <= 0)
+ return 0;
+
+ /*
+ * This check should always be done because keylen / mdlen >= (2^32 - 1)
+ * results in an overflow of the loop counter 'i'.
+ */
+ if ((keylen / mdlen) >= KDF_PBKDF2_MAX_KEY_LEN_DIGEST_RATIO) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+
+ if (lower_bound_checks) {
+ if ((keylen * 8) < KDF_PBKDF2_MIN_KEY_LEN_BITS) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL);
+ return 0;
+ }
+ if (saltlen < KDF_PBKDF2_MIN_SALT_LEN) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH);
+ return 0;
+ }
+ if (iter < KDF_PBKDF2_MIN_ITERATIONS) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT);
+ return 0;
+ }
+ }
+
+ hctx_tpl = HMAC_CTX_new();
+ if (hctx_tpl == NULL)
+ return 0;
+ p = key;
+ tkeylen = keylen;
+ if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL))
+ goto err;
+ hctx = HMAC_CTX_new();
+ if (hctx == NULL)
+ goto err;
+ while (tkeylen) {
+ if (tkeylen > mdlen)
+ cplen = mdlen;
+ else
+ cplen = tkeylen;
+ /*
+ * We are unlikely to ever use more than 256 blocks (5120 bits!) but
+ * just in case...
+ */
+ itmp[0] = (unsigned char)((i >> 24) & 0xff);
+ itmp[1] = (unsigned char)((i >> 16) & 0xff);
+ itmp[2] = (unsigned char)((i >> 8) & 0xff);
+ itmp[3] = (unsigned char)(i & 0xff);
+ if (!HMAC_CTX_copy(hctx, hctx_tpl))
+ goto err;
+ if (!HMAC_Update(hctx, salt, saltlen)
+ || !HMAC_Update(hctx, itmp, 4)
+ || !HMAC_Final(hctx, digtmp, NULL))
+ goto err;
+ memcpy(p, digtmp, cplen);
+ for (j = 1; j < iter; j++) {
+ if (!HMAC_CTX_copy(hctx, hctx_tpl))
+ goto err;
+ if (!HMAC_Update(hctx, digtmp, mdlen)
+ || !HMAC_Final(hctx, digtmp, NULL))
+ goto err;
+ for (k = 0; k < cplen; k++)
+ p[k] ^= digtmp[k];
+ }
+ tkeylen -= cplen;
+ i++;
+ p += cplen;
+ }
+ ret = 1;
+
+err:
+ HMAC_CTX_free(hctx);
+ HMAC_CTX_free(hctx_tpl);
+ return ret;
+}
diff --git a/providers/implementations/kdfs/pbkdf2.h b/providers/implementations/kdfs/pbkdf2.h
new file mode 100644
index 000000000000..7759c03136d5
--- /dev/null
+++ b/providers/implementations/kdfs/pbkdf2.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Available in pbkdfe_fips.c, and compiled with different values depending
+ * on we're in the FIPS module or not.
+ */
+extern const int ossl_kdf_pbkdf2_default_checks;
diff --git a/providers/implementations/kdfs/pbkdf2_fips.c b/providers/implementations/kdfs/pbkdf2_fips.c
new file mode 100644
index 000000000000..e43ef16455f1
--- /dev/null
+++ b/providers/implementations/kdfs/pbkdf2_fips.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "pbkdf2.h"
+
+/*
+ * For backwards compatibility reasons,
+ * Extra checks are done by default in fips mode only.
+ */
+#ifdef FIPS_MODULE
+const int ossl_kdf_pbkdf2_default_checks = 1;
+#else
+const int ossl_kdf_pbkdf2_default_checks = 0;
+#endif /* FIPS_MODULE */
diff --git a/providers/implementations/kdfs/pkcs12kdf.c b/providers/implementations/kdfs/pkcs12kdf.c
new file mode 100644
index 000000000000..3218daa781e9
--- /dev/null
+++ b/providers/implementations/kdfs/pkcs12kdf.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/trace.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#include <openssl/proverr.h>
+#include "internal/cryptlib.h"
+#include "internal/numbers.h"
+#include "crypto/evp.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_util.h"
+
+static OSSL_FUNC_kdf_newctx_fn kdf_pkcs12_new;
+static OSSL_FUNC_kdf_freectx_fn kdf_pkcs12_free;
+static OSSL_FUNC_kdf_reset_fn kdf_pkcs12_reset;
+static OSSL_FUNC_kdf_derive_fn kdf_pkcs12_derive;
+static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_pkcs12_settable_ctx_params;
+static OSSL_FUNC_kdf_set_ctx_params_fn kdf_pkcs12_set_ctx_params;
+static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_pkcs12_gettable_ctx_params;
+static OSSL_FUNC_kdf_get_ctx_params_fn kdf_pkcs12_get_ctx_params;
+
+typedef struct {
+ void *provctx;
+ PROV_DIGEST digest;
+ unsigned char *pass;
+ size_t pass_len;
+ unsigned char *salt;
+ size_t salt_len;
+ uint64_t iter;
+ int id;
+} KDF_PKCS12;
+
+/* PKCS12 compatible key/IV generation */
+
+static int pkcs12kdf_derive(const unsigned char *pass, size_t passlen,
+ const unsigned char *salt, size_t saltlen,
+ int id, uint64_t iter, const EVP_MD *md_type,
+ unsigned char *out, size_t n)
+{
+ unsigned char *B = NULL, *D = NULL, *I = NULL, *p = NULL, *Ai = NULL;
+ size_t Slen, Plen, Ilen;
+ size_t i, j, k, u, v;
+ uint64_t iter_cnt;
+ int ret = 0, ui, vi;
+ EVP_MD_CTX *ctx = NULL;
+
+ ctx = EVP_MD_CTX_new();
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+ vi = EVP_MD_get_block_size(md_type);
+ ui = EVP_MD_get_size(md_type);
+ if (ui <= 0 || vi <= 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_SIZE);
+ goto end;
+ }
+ u = (size_t)ui;
+ v = (size_t)vi;
+ D = OPENSSL_malloc(v);
+ Ai = OPENSSL_malloc(u);
+ B = OPENSSL_malloc(v + 1);
+ Slen = v * ((saltlen + v - 1) / v);
+ if (passlen != 0)
+ Plen = v * ((passlen + v - 1) / v);
+ else
+ Plen = 0;
+ Ilen = Slen + Plen;
+ I = OPENSSL_malloc(Ilen);
+ if (D == NULL || Ai == NULL || B == NULL || I == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+ for (i = 0; i < v; i++)
+ D[i] = id;
+ p = I;
+ for (i = 0; i < Slen; i++)
+ *p++ = salt[i % saltlen];
+ for (i = 0; i < Plen; i++)
+ *p++ = pass[i % passlen];
+ for (;;) {
+ if (!EVP_DigestInit_ex(ctx, md_type, NULL)
+ || !EVP_DigestUpdate(ctx, D, v)
+ || !EVP_DigestUpdate(ctx, I, Ilen)
+ || !EVP_DigestFinal_ex(ctx, Ai, NULL))
+ goto end;
+ for (iter_cnt = 1; iter_cnt < iter; iter_cnt++) {
+ if (!EVP_DigestInit_ex(ctx, md_type, NULL)
+ || !EVP_DigestUpdate(ctx, Ai, u)
+ || !EVP_DigestFinal_ex(ctx, Ai, NULL))
+ goto end;
+ }
+ memcpy(out, Ai, n < u ? n : u);
+ if (u >= n) {
+ ret = 1;
+ break;
+ }
+ n -= u;
+ out += u;
+ for (j = 0; j < v; j++)
+ B[j] = Ai[j % u];
+ for (j = 0; j < Ilen; j += v) {
+ unsigned char *Ij = I + j;
+ uint16_t c = 1;
+
+ /* Work out Ij = Ij + B + 1 */
+ for (k = v; k > 0;) {
+ k--;
+ c += Ij[k] + B[k];
+ Ij[k] = (unsigned char)c;
+ c >>= 8;
+ }
+ }
+ }
+
+ end:
+ OPENSSL_free(Ai);
+ OPENSSL_free(B);
+ OPENSSL_free(D);
+ OPENSSL_free(I);
+ EVP_MD_CTX_free(ctx);
+ return ret;
+}
+
+static void *kdf_pkcs12_new(void *provctx)
+{
+ KDF_PKCS12 *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ ctx->provctx = provctx;
+ return ctx;
+}
+
+static void kdf_pkcs12_cleanup(KDF_PKCS12 *ctx)
+{
+ ossl_prov_digest_reset(&ctx->digest);
+ OPENSSL_free(ctx->salt);
+ OPENSSL_clear_free(ctx->pass, ctx->pass_len);
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+static void kdf_pkcs12_free(void *vctx)
+{
+ KDF_PKCS12 *ctx = (KDF_PKCS12 *)vctx;
+
+ if (ctx != NULL) {
+ kdf_pkcs12_cleanup(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+static void kdf_pkcs12_reset(void *vctx)
+{
+ KDF_PKCS12 *ctx = (KDF_PKCS12 *)vctx;
+ void *provctx = ctx->provctx;
+
+ kdf_pkcs12_cleanup(ctx);
+ ctx->provctx = provctx;
+}
+
+static int pkcs12kdf_set_membuf(unsigned char **buffer, size_t *buflen,
+ const OSSL_PARAM *p)
+{
+ OPENSSL_clear_free(*buffer, *buflen);
+ *buffer = NULL;
+ *buflen = 0;
+
+ if (p->data_size == 0) {
+ if ((*buffer = OPENSSL_malloc(1)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else if (p->data != NULL) {
+ if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen))
+ return 0;
+ }
+ return 1;
+}
+
+static int kdf_pkcs12_derive(void *vctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ KDF_PKCS12 *ctx = (KDF_PKCS12 *)vctx;
+ const EVP_MD *md;
+
+ if (!ossl_prov_is_running() || !kdf_pkcs12_set_ctx_params(ctx, params))
+ return 0;
+
+ if (ctx->pass == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);
+ return 0;
+ }
+
+ if (ctx->salt == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
+ return 0;
+ }
+
+ md = ossl_prov_digest_md(&ctx->digest);
+ return pkcs12kdf_derive(ctx->pass, ctx->pass_len, ctx->salt, ctx->salt_len,
+ ctx->id, ctx->iter, md, key, keylen);
+}
+
+static int kdf_pkcs12_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ KDF_PKCS12 *ctx = vctx;
+ OSSL_LIB_CTX *provctx = PROV_LIBCTX_OF(ctx->provctx);
+
+ if (params == NULL)
+ return 1;
+
+ if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)
+ if (!pkcs12kdf_set_membuf(&ctx->pass, &ctx->pass_len, p))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)
+ if (!pkcs12kdf_set_membuf(&ctx->salt, &ctx->salt_len,p))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PKCS12_ID)) != NULL)
+ if (!OSSL_PARAM_get_int(p, &ctx->id))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ITER)) != NULL)
+ if (!OSSL_PARAM_get_uint64(p, &ctx->iter))
+ return 0;
+ return 1;
+}
+
+static const OSSL_PARAM *kdf_pkcs12_settable_ctx_params(
+ ossl_unused void *ctx, ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
+ OSSL_PARAM_uint64(OSSL_KDF_PARAM_ITER, NULL),
+ OSSL_PARAM_int(OSSL_KDF_PARAM_PKCS12_ID, NULL),
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+static int kdf_pkcs12_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
+ return OSSL_PARAM_set_size_t(p, SIZE_MAX);
+ return -2;
+}
+
+static const OSSL_PARAM *kdf_pkcs12_gettable_ctx_params(
+ ossl_unused void *ctx, ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_kdf_pkcs12_functions[] = {
+ { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pkcs12_new },
+ { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pkcs12_free },
+ { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pkcs12_reset },
+ { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pkcs12_derive },
+ { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_pkcs12_settable_ctx_params },
+ { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pkcs12_set_ctx_params },
+ { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_pkcs12_gettable_ctx_params },
+ { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pkcs12_get_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/kdfs/scrypt.c b/providers/implementations/kdfs/scrypt.c
new file mode 100644
index 000000000000..a7072f785f08
--- /dev/null
+++ b/providers/implementations/kdfs/scrypt.c
@@ -0,0 +1,517 @@
+/*
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/err.h>
+#include <openssl/core_names.h>
+#include <openssl/proverr.h>
+#include "crypto/evp.h"
+#include "internal/numbers.h"
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+
+#ifndef OPENSSL_NO_SCRYPT
+
+static OSSL_FUNC_kdf_newctx_fn kdf_scrypt_new;
+static OSSL_FUNC_kdf_freectx_fn kdf_scrypt_free;
+static OSSL_FUNC_kdf_reset_fn kdf_scrypt_reset;
+static OSSL_FUNC_kdf_derive_fn kdf_scrypt_derive;
+static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_scrypt_settable_ctx_params;
+static OSSL_FUNC_kdf_set_ctx_params_fn kdf_scrypt_set_ctx_params;
+static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_scrypt_gettable_ctx_params;
+static OSSL_FUNC_kdf_get_ctx_params_fn kdf_scrypt_get_ctx_params;
+
+static int scrypt_alg(const char *pass, size_t passlen,
+ const unsigned char *salt, size_t saltlen,
+ uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
+ unsigned char *key, size_t keylen, EVP_MD *sha256,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+ unsigned char *pass;
+ size_t pass_len;
+ unsigned char *salt;
+ size_t salt_len;
+ uint64_t N;
+ uint64_t r, p;
+ uint64_t maxmem_bytes;
+ EVP_MD *sha256;
+} KDF_SCRYPT;
+
+static void kdf_scrypt_init(KDF_SCRYPT *ctx);
+
+static void *kdf_scrypt_new(void *provctx)
+{
+ KDF_SCRYPT *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ ctx->libctx = PROV_LIBCTX_OF(provctx);
+ kdf_scrypt_init(ctx);
+ return ctx;
+}
+
+static void kdf_scrypt_free(void *vctx)
+{
+ KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx;
+
+ if (ctx != NULL) {
+ OPENSSL_free(ctx->propq);
+ EVP_MD_free(ctx->sha256);
+ kdf_scrypt_reset(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+static void kdf_scrypt_reset(void *vctx)
+{
+ KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx;
+
+ OPENSSL_free(ctx->salt);
+ OPENSSL_clear_free(ctx->pass, ctx->pass_len);
+ kdf_scrypt_init(ctx);
+}
+
+static void kdf_scrypt_init(KDF_SCRYPT *ctx)
+{
+ /* Default values are the most conservative recommendation given in the
+ * original paper of C. Percival. Derivation uses roughly 1 GiB of memory
+ * for this parameter choice (approx. 128 * r * N * p bytes).
+ */
+ ctx->N = 1 << 20;
+ ctx->r = 8;
+ ctx->p = 1;
+ ctx->maxmem_bytes = 1025 * 1024 * 1024;
+}
+
+static int scrypt_set_membuf(unsigned char **buffer, size_t *buflen,
+ const OSSL_PARAM *p)
+{
+ OPENSSL_clear_free(*buffer, *buflen);
+ *buffer = NULL;
+ *buflen = 0;
+
+ if (p->data_size == 0) {
+ if ((*buffer = OPENSSL_malloc(1)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else if (p->data != NULL) {
+ if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen))
+ return 0;
+ }
+ return 1;
+}
+
+static int set_digest(KDF_SCRYPT *ctx)
+{
+ EVP_MD_free(ctx->sha256);
+ ctx->sha256 = EVP_MD_fetch(ctx->libctx, "sha256", ctx->propq);
+ if (ctx->sha256 == NULL) {
+ OPENSSL_free(ctx);
+ ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOAD_SHA256);
+ return 0;
+ }
+ return 1;
+}
+
+static int set_property_query(KDF_SCRYPT *ctx, const char *propq)
+{
+ OPENSSL_free(ctx->propq);
+ ctx->propq = NULL;
+ if (propq != NULL) {
+ ctx->propq = OPENSSL_strdup(propq);
+ if (ctx->propq == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int kdf_scrypt_derive(void *vctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx;
+
+ if (!ossl_prov_is_running() || !kdf_scrypt_set_ctx_params(ctx, params))
+ return 0;
+
+ if (ctx->pass == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);
+ return 0;
+ }
+
+ if (ctx->salt == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
+ return 0;
+ }
+
+ if (ctx->sha256 == NULL && !set_digest(ctx))
+ return 0;
+
+ return scrypt_alg((char *)ctx->pass, ctx->pass_len, ctx->salt,
+ ctx->salt_len, ctx->N, ctx->r, ctx->p,
+ ctx->maxmem_bytes, key, keylen, ctx->sha256,
+ ctx->libctx, ctx->propq);
+}
+
+static int is_power_of_two(uint64_t value)
+{
+ return (value != 0) && ((value & (value - 1)) == 0);
+}
+
+static int kdf_scrypt_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ KDF_SCRYPT *ctx = vctx;
+ uint64_t u64_value;
+
+ if (params == NULL)
+ return 1;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)
+ if (!scrypt_set_membuf(&ctx->pass, &ctx->pass_len, p))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)
+ if (!scrypt_set_membuf(&ctx->salt, &ctx->salt_len, p))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_N))
+ != NULL) {
+ if (!OSSL_PARAM_get_uint64(p, &u64_value)
+ || u64_value <= 1
+ || !is_power_of_two(u64_value))
+ return 0;
+ ctx->N = u64_value;
+ }
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_R))
+ != NULL) {
+ if (!OSSL_PARAM_get_uint64(p, &u64_value) || u64_value < 1)
+ return 0;
+ ctx->r = u64_value;
+ }
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_P))
+ != NULL) {
+ if (!OSSL_PARAM_get_uint64(p, &u64_value) || u64_value < 1)
+ return 0;
+ ctx->p = u64_value;
+ }
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_MAXMEM))
+ != NULL) {
+ if (!OSSL_PARAM_get_uint64(p, &u64_value) || u64_value < 1)
+ return 0;
+ ctx->maxmem_bytes = u64_value;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING
+ || !set_property_query(ctx, p->data)
+ || !set_digest(ctx))
+ return 0;
+ }
+ return 1;
+}
+
+static const OSSL_PARAM *kdf_scrypt_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *p_ctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
+ OSSL_PARAM_uint64(OSSL_KDF_PARAM_SCRYPT_N, NULL),
+ OSSL_PARAM_uint32(OSSL_KDF_PARAM_SCRYPT_R, NULL),
+ OSSL_PARAM_uint32(OSSL_KDF_PARAM_SCRYPT_P, NULL),
+ OSSL_PARAM_uint64(OSSL_KDF_PARAM_SCRYPT_MAXMEM, NULL),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+static int kdf_scrypt_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
+ return OSSL_PARAM_set_size_t(p, SIZE_MAX);
+ return -2;
+}
+
+static const OSSL_PARAM *kdf_scrypt_gettable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *p_ctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_kdf_scrypt_functions[] = {
+ { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_scrypt_new },
+ { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_scrypt_free },
+ { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_scrypt_reset },
+ { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_scrypt_derive },
+ { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_scrypt_settable_ctx_params },
+ { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_scrypt_set_ctx_params },
+ { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_scrypt_gettable_ctx_params },
+ { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_scrypt_get_ctx_params },
+ { 0, NULL }
+};
+
+#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
+static void salsa208_word_specification(uint32_t inout[16])
+{
+ int i;
+ uint32_t x[16];
+
+ memcpy(x, inout, sizeof(x));
+ for (i = 8; i > 0; i -= 2) {
+ x[4] ^= R(x[0] + x[12], 7);
+ x[8] ^= R(x[4] + x[0], 9);
+ x[12] ^= R(x[8] + x[4], 13);
+ x[0] ^= R(x[12] + x[8], 18);
+ x[9] ^= R(x[5] + x[1], 7);
+ x[13] ^= R(x[9] + x[5], 9);
+ x[1] ^= R(x[13] + x[9], 13);
+ x[5] ^= R(x[1] + x[13], 18);
+ x[14] ^= R(x[10] + x[6], 7);
+ x[2] ^= R(x[14] + x[10], 9);
+ x[6] ^= R(x[2] + x[14], 13);
+ x[10] ^= R(x[6] + x[2], 18);
+ x[3] ^= R(x[15] + x[11], 7);
+ x[7] ^= R(x[3] + x[15], 9);
+ x[11] ^= R(x[7] + x[3], 13);
+ x[15] ^= R(x[11] + x[7], 18);
+ x[1] ^= R(x[0] + x[3], 7);
+ x[2] ^= R(x[1] + x[0], 9);
+ x[3] ^= R(x[2] + x[1], 13);
+ x[0] ^= R(x[3] + x[2], 18);
+ x[6] ^= R(x[5] + x[4], 7);
+ x[7] ^= R(x[6] + x[5], 9);
+ x[4] ^= R(x[7] + x[6], 13);
+ x[5] ^= R(x[4] + x[7], 18);
+ x[11] ^= R(x[10] + x[9], 7);
+ x[8] ^= R(x[11] + x[10], 9);
+ x[9] ^= R(x[8] + x[11], 13);
+ x[10] ^= R(x[9] + x[8], 18);
+ x[12] ^= R(x[15] + x[14], 7);
+ x[13] ^= R(x[12] + x[15], 9);
+ x[14] ^= R(x[13] + x[12], 13);
+ x[15] ^= R(x[14] + x[13], 18);
+ }
+ for (i = 0; i < 16; ++i)
+ inout[i] += x[i];
+ OPENSSL_cleanse(x, sizeof(x));
+}
+
+static void scryptBlockMix(uint32_t *B_, uint32_t *B, uint64_t r)
+{
+ uint64_t i, j;
+ uint32_t X[16], *pB;
+
+ memcpy(X, B + (r * 2 - 1) * 16, sizeof(X));
+ pB = B;
+ for (i = 0; i < r * 2; i++) {
+ for (j = 0; j < 16; j++)
+ X[j] ^= *pB++;
+ salsa208_word_specification(X);
+ memcpy(B_ + (i / 2 + (i & 1) * r) * 16, X, sizeof(X));
+ }
+ OPENSSL_cleanse(X, sizeof(X));
+}
+
+static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N,
+ uint32_t *X, uint32_t *T, uint32_t *V)
+{
+ unsigned char *pB;
+ uint32_t *pV;
+ uint64_t i, k;
+
+ /* Convert from little endian input */
+ for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) {
+ *pV = *pB++;
+ *pV |= *pB++ << 8;
+ *pV |= *pB++ << 16;
+ *pV |= (uint32_t)*pB++ << 24;
+ }
+
+ for (i = 1; i < N; i++, pV += 32 * r)
+ scryptBlockMix(pV, pV - 32 * r, r);
+
+ scryptBlockMix(X, V + (N - 1) * 32 * r, r);
+
+ for (i = 0; i < N; i++) {
+ uint32_t j;
+ j = X[16 * (2 * r - 1)] % N;
+ pV = V + 32 * r * j;
+ for (k = 0; k < 32 * r; k++)
+ T[k] = X[k] ^ *pV++;
+ scryptBlockMix(X, T, r);
+ }
+ /* Convert output to little endian */
+ for (i = 0, pB = B; i < 32 * r; i++) {
+ uint32_t xtmp = X[i];
+ *pB++ = xtmp & 0xff;
+ *pB++ = (xtmp >> 8) & 0xff;
+ *pB++ = (xtmp >> 16) & 0xff;
+ *pB++ = (xtmp >> 24) & 0xff;
+ }
+}
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t)-1)
+#endif
+
+/*
+ * Maximum power of two that will fit in uint64_t: this should work on
+ * most (all?) platforms.
+ */
+
+#define LOG2_UINT64_MAX (sizeof(uint64_t) * 8 - 1)
+
+/*
+ * Maximum value of p * r:
+ * p <= ((2^32-1) * hLen) / MFLen =>
+ * p <= ((2^32-1) * 32) / (128 * r) =>
+ * p * r <= (2^30-1)
+ */
+
+#define SCRYPT_PR_MAX ((1 << 30) - 1)
+
+static int scrypt_alg(const char *pass, size_t passlen,
+ const unsigned char *salt, size_t saltlen,
+ uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
+ unsigned char *key, size_t keylen, EVP_MD *sha256,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ int rv = 0;
+ unsigned char *B;
+ uint32_t *X, *V, *T;
+ uint64_t i, Blen, Vlen;
+
+ /* Sanity check parameters */
+ /* initial check, r,p must be non zero, N >= 2 and a power of 2 */
+ if (r == 0 || p == 0 || N < 2 || (N & (N - 1)))
+ return 0;
+ /* Check p * r < SCRYPT_PR_MAX avoiding overflow */
+ if (p > SCRYPT_PR_MAX / r) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
+ return 0;
+ }
+
+ /*
+ * Need to check N: if 2^(128 * r / 8) overflows limit this is
+ * automatically satisfied since N <= UINT64_MAX.
+ */
+
+ if (16 * r <= LOG2_UINT64_MAX) {
+ if (N >= (((uint64_t)1) << (16 * r))) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
+ return 0;
+ }
+ }
+
+ /* Memory checks: check total allocated buffer size fits in uint64_t */
+
+ /*
+ * B size in section 5 step 1.S
+ * Note: we know p * 128 * r < UINT64_MAX because we already checked
+ * p * r < SCRYPT_PR_MAX
+ */
+ Blen = p * 128 * r;
+ /*
+ * Yet we pass it as integer to PKCS5_PBKDF2_HMAC... [This would
+ * have to be revised when/if PKCS5_PBKDF2_HMAC accepts size_t.]
+ */
+ if (Blen > INT_MAX) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
+ return 0;
+ }
+
+ /*
+ * Check 32 * r * (N + 2) * sizeof(uint32_t) fits in uint64_t
+ * This is combined size V, X and T (section 4)
+ */
+ i = UINT64_MAX / (32 * sizeof(uint32_t));
+ if (N + 2 > i / r) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
+ return 0;
+ }
+ Vlen = 32 * r * (N + 2) * sizeof(uint32_t);
+
+ /* check total allocated size fits in uint64_t */
+ if (Blen > UINT64_MAX - Vlen) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
+ return 0;
+ }
+
+ /* Check that the maximum memory doesn't exceed a size_t limits */
+ if (maxmem > SIZE_MAX)
+ maxmem = SIZE_MAX;
+
+ if (Blen + Vlen > maxmem) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
+ return 0;
+ }
+
+ /* If no key return to indicate parameters are OK */
+ if (key == NULL)
+ return 1;
+
+ B = OPENSSL_malloc((size_t)(Blen + Vlen));
+ if (B == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ X = (uint32_t *)(B + Blen);
+ T = X + 32 * r;
+ V = T + 32 * r;
+ if (ossl_pkcs5_pbkdf2_hmac_ex(pass, passlen, salt, saltlen, 1, sha256,
+ (int)Blen, B, libctx, propq) == 0)
+ goto err;
+
+ for (i = 0; i < p; i++)
+ scryptROMix(B + 128 * r * i, r, N, X, T, V);
+
+ if (ossl_pkcs5_pbkdf2_hmac_ex(pass, passlen, B, (int)Blen, 1, sha256,
+ keylen, key, libctx, propq) == 0)
+ goto err;
+ rv = 1;
+ err:
+ if (rv == 0)
+ ERR_raise(ERR_LIB_EVP, EVP_R_PBKDF2_ERROR);
+
+ OPENSSL_clear_free(B, (size_t)(Blen + Vlen));
+ return rv;
+}
+
+#endif
diff --git a/providers/implementations/kdfs/sshkdf.c b/providers/implementations/kdfs/sshkdf.c
new file mode 100644
index 000000000000..c592ba72f1e0
--- /dev/null
+++ b/providers/implementations/kdfs/sshkdf.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#include <openssl/proverr.h>
+#include "internal/cryptlib.h"
+#include "internal/numbers.h"
+#include "crypto/evp.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_util.h"
+
+/* See RFC 4253, Section 7.2 */
+static OSSL_FUNC_kdf_newctx_fn kdf_sshkdf_new;
+static OSSL_FUNC_kdf_freectx_fn kdf_sshkdf_free;
+static OSSL_FUNC_kdf_reset_fn kdf_sshkdf_reset;
+static OSSL_FUNC_kdf_derive_fn kdf_sshkdf_derive;
+static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_sshkdf_settable_ctx_params;
+static OSSL_FUNC_kdf_set_ctx_params_fn kdf_sshkdf_set_ctx_params;
+static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_sshkdf_gettable_ctx_params;
+static OSSL_FUNC_kdf_get_ctx_params_fn kdf_sshkdf_get_ctx_params;
+
+static int SSHKDF(const EVP_MD *evp_md,
+ const unsigned char *key, size_t key_len,
+ const unsigned char *xcghash, size_t xcghash_len,
+ const unsigned char *session_id, size_t session_id_len,
+ char type, unsigned char *okey, size_t okey_len);
+
+typedef struct {
+ void *provctx;
+ PROV_DIGEST digest;
+ unsigned char *key; /* K */
+ size_t key_len;
+ unsigned char *xcghash; /* H */
+ size_t xcghash_len;
+ char type; /* X */
+ unsigned char *session_id;
+ size_t session_id_len;
+} KDF_SSHKDF;
+
+static void *kdf_sshkdf_new(void *provctx)
+{
+ KDF_SSHKDF *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL)
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ else
+ ctx->provctx = provctx;
+ return ctx;
+}
+
+static void kdf_sshkdf_free(void *vctx)
+{
+ KDF_SSHKDF *ctx = (KDF_SSHKDF *)vctx;
+
+ if (ctx != NULL) {
+ kdf_sshkdf_reset(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+static void kdf_sshkdf_reset(void *vctx)
+{
+ KDF_SSHKDF *ctx = (KDF_SSHKDF *)vctx;
+ void *provctx = ctx->provctx;
+
+ ossl_prov_digest_reset(&ctx->digest);
+ OPENSSL_clear_free(ctx->key, ctx->key_len);
+ OPENSSL_clear_free(ctx->xcghash, ctx->xcghash_len);
+ OPENSSL_clear_free(ctx->session_id, ctx->session_id_len);
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->provctx = provctx;
+}
+
+static int sshkdf_set_membuf(unsigned char **dst, size_t *dst_len,
+ const OSSL_PARAM *p)
+{
+ OPENSSL_clear_free(*dst, *dst_len);
+ *dst = NULL;
+ *dst_len = 0;
+ return OSSL_PARAM_get_octet_string(p, (void **)dst, 0, dst_len);
+}
+
+static int kdf_sshkdf_derive(void *vctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ KDF_SSHKDF *ctx = (KDF_SSHKDF *)vctx;
+ const EVP_MD *md;
+
+ if (!ossl_prov_is_running() || !kdf_sshkdf_set_ctx_params(ctx, params))
+ return 0;
+
+ md = ossl_prov_digest_md(&ctx->digest);
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
+ return 0;
+ }
+ if (ctx->key == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
+ return 0;
+ }
+ if (ctx->xcghash == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_XCGHASH);
+ return 0;
+ }
+ if (ctx->session_id == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SESSION_ID);
+ return 0;
+ }
+ if (ctx->type == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_TYPE);
+ return 0;
+ }
+ return SSHKDF(md, ctx->key, ctx->key_len,
+ ctx->xcghash, ctx->xcghash_len,
+ ctx->session_id, ctx->session_id_len,
+ ctx->type, key, keylen);
+}
+
+static int kdf_sshkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ KDF_SSHKDF *ctx = vctx;
+ OSSL_LIB_CTX *provctx = PROV_LIBCTX_OF(ctx->provctx);
+
+ if (params == NULL)
+ return 1;
+
+ if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL)
+ if (!sshkdf_set_membuf(&ctx->key, &ctx->key_len, p))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SSHKDF_XCGHASH))
+ != NULL)
+ if (!sshkdf_set_membuf(&ctx->xcghash, &ctx->xcghash_len, p))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SSHKDF_SESSION_ID))
+ != NULL)
+ if (!sshkdf_set_membuf(&ctx->session_id, &ctx->session_id_len, p))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SSHKDF_TYPE))
+ != NULL) {
+ const char *kdftype;
+
+ if (!OSSL_PARAM_get_utf8_string_ptr(p, &kdftype))
+ return 0;
+ /* Expect one character (byte in this case) */
+ if (kdftype == NULL || p->data_size != 1)
+ return 0;
+ if (kdftype[0] < 65 || kdftype[0] > 70) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_VALUE_ERROR);
+ return 0;
+ }
+ ctx->type = kdftype[0];
+ }
+ return 1;
+}
+
+static const OSSL_PARAM *kdf_sshkdf_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *p_ctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SSHKDF_XCGHASH, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SSHKDF_SESSION_ID, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_SSHKDF_TYPE, NULL, 0),
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+static int kdf_sshkdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
+ return OSSL_PARAM_set_size_t(p, SIZE_MAX);
+ return -2;
+}
+
+static const OSSL_PARAM *kdf_sshkdf_gettable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *p_ctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_kdf_sshkdf_functions[] = {
+ { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_sshkdf_new },
+ { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_sshkdf_free },
+ { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_sshkdf_reset },
+ { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_sshkdf_derive },
+ { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_sshkdf_settable_ctx_params },
+ { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_sshkdf_set_ctx_params },
+ { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_sshkdf_gettable_ctx_params },
+ { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_sshkdf_get_ctx_params },
+ { 0, NULL }
+};
+
+static int SSHKDF(const EVP_MD *evp_md,
+ const unsigned char *key, size_t key_len,
+ const unsigned char *xcghash, size_t xcghash_len,
+ const unsigned char *session_id, size_t session_id_len,
+ char type, unsigned char *okey, size_t okey_len)
+{
+ EVP_MD_CTX *md = NULL;
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ unsigned int dsize = 0;
+ size_t cursize = 0;
+ int ret = 0;
+
+ md = EVP_MD_CTX_new();
+ if (md == NULL)
+ return 0;
+
+ if (!EVP_DigestInit_ex(md, evp_md, NULL))
+ goto out;
+
+ if (!EVP_DigestUpdate(md, key, key_len))
+ goto out;
+
+ if (!EVP_DigestUpdate(md, xcghash, xcghash_len))
+ goto out;
+
+ if (!EVP_DigestUpdate(md, &type, 1))
+ goto out;
+
+ if (!EVP_DigestUpdate(md, session_id, session_id_len))
+ goto out;
+
+ if (!EVP_DigestFinal_ex(md, digest, &dsize))
+ goto out;
+
+ if (okey_len < dsize) {
+ memcpy(okey, digest, okey_len);
+ ret = 1;
+ goto out;
+ }
+
+ memcpy(okey, digest, dsize);
+
+ for (cursize = dsize; cursize < okey_len; cursize += dsize) {
+
+ if (!EVP_DigestInit_ex(md, evp_md, NULL))
+ goto out;
+
+ if (!EVP_DigestUpdate(md, key, key_len))
+ goto out;
+
+ if (!EVP_DigestUpdate(md, xcghash, xcghash_len))
+ goto out;
+
+ if (!EVP_DigestUpdate(md, okey, cursize))
+ goto out;
+
+ if (!EVP_DigestFinal_ex(md, digest, &dsize))
+ goto out;
+
+ if (okey_len < cursize + dsize) {
+ memcpy(okey + cursize, digest, okey_len - cursize);
+ ret = 1;
+ goto out;
+ }
+
+ memcpy(okey + cursize, digest, dsize);
+ }
+
+ ret = 1;
+
+out:
+ EVP_MD_CTX_free(md);
+ OPENSSL_cleanse(digest, EVP_MAX_MD_SIZE);
+ return ret;
+}
+
diff --git a/providers/implementations/kdfs/sskdf.c b/providers/implementations/kdfs/sskdf.c
new file mode 100644
index 000000000000..eb54972e1c44
--- /dev/null
+++ b/providers/implementations/kdfs/sskdf.c
@@ -0,0 +1,559 @@
+/*
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final
+ * Section 4.1.
+ *
+ * The Single Step KDF algorithm is given by:
+ *
+ * Result(0) = empty bit string (i.e., the null string).
+ * For i = 1 to reps, do the following:
+ * Increment counter by 1.
+ * Result(i) = Result(i - 1) || H(counter || Z || FixedInfo).
+ * DKM = LeftmostBits(Result(reps), L))
+ *
+ * NOTES:
+ * Z is a shared secret required to produce the derived key material.
+ * counter is a 4 byte buffer.
+ * FixedInfo is a bit string containing context specific data.
+ * DKM is the output derived key material.
+ * L is the required size of the DKM.
+ * reps = [L / H_outputBits]
+ * H(x) is the auxiliary function that can be either a hash, HMAC or KMAC.
+ * H_outputBits is the length of the output of the auxiliary function H(x).
+ *
+ * Currently there is not a comprehensive list of test vectors for this
+ * algorithm, especially for H(x) = HMAC and H(x) = KMAC.
+ * Test vectors for H(x) = Hash are indirectly used by CAVS KAS tests.
+ */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/proverr.h>
+#include "internal/cryptlib.h"
+#include "internal/numbers.h"
+#include "crypto/evp.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_util.h"
+
+typedef struct {
+ void *provctx;
+ EVP_MAC_CTX *macctx; /* H(x) = HMAC_hash OR H(x) = KMAC */
+ PROV_DIGEST digest; /* H(x) = hash(x) */
+ unsigned char *secret;
+ size_t secret_len;
+ unsigned char *info;
+ size_t info_len;
+ unsigned char *salt;
+ size_t salt_len;
+ size_t out_len; /* optional KMAC parameter */
+ int is_kmac;
+} KDF_SSKDF;
+
+#define SSKDF_MAX_INLEN (1<<30)
+#define SSKDF_KMAC128_DEFAULT_SALT_SIZE (168 - 4)
+#define SSKDF_KMAC256_DEFAULT_SALT_SIZE (136 - 4)
+
+/* KMAC uses a Customisation string of 'KDF' */
+static const unsigned char kmac_custom_str[] = { 0x4B, 0x44, 0x46 };
+
+static OSSL_FUNC_kdf_newctx_fn sskdf_new;
+static OSSL_FUNC_kdf_freectx_fn sskdf_free;
+static OSSL_FUNC_kdf_reset_fn sskdf_reset;
+static OSSL_FUNC_kdf_derive_fn sskdf_derive;
+static OSSL_FUNC_kdf_derive_fn x963kdf_derive;
+static OSSL_FUNC_kdf_settable_ctx_params_fn sskdf_settable_ctx_params;
+static OSSL_FUNC_kdf_set_ctx_params_fn sskdf_set_ctx_params;
+static OSSL_FUNC_kdf_gettable_ctx_params_fn sskdf_gettable_ctx_params;
+static OSSL_FUNC_kdf_get_ctx_params_fn sskdf_get_ctx_params;
+
+/*
+ * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final
+ * Section 4. One-Step Key Derivation using H(x) = hash(x)
+ * Note: X9.63 also uses this code with the only difference being that the
+ * counter is appended to the secret 'z'.
+ * i.e.
+ * result[i] = Hash(counter || z || info) for One Step OR
+ * result[i] = Hash(z || counter || info) for X9.63.
+ */
+static int SSKDF_hash_kdm(const EVP_MD *kdf_md,
+ const unsigned char *z, size_t z_len,
+ const unsigned char *info, size_t info_len,
+ unsigned int append_ctr,
+ unsigned char *derived_key, size_t derived_key_len)
+{
+ int ret = 0, hlen;
+ size_t counter, out_len, len = derived_key_len;
+ unsigned char c[4];
+ unsigned char mac[EVP_MAX_MD_SIZE];
+ unsigned char *out = derived_key;
+ EVP_MD_CTX *ctx = NULL, *ctx_init = NULL;
+
+ if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN
+ || derived_key_len > SSKDF_MAX_INLEN
+ || derived_key_len == 0)
+ return 0;
+
+ hlen = EVP_MD_get_size(kdf_md);
+ if (hlen <= 0)
+ return 0;
+ out_len = (size_t)hlen;
+
+ ctx = EVP_MD_CTX_create();
+ ctx_init = EVP_MD_CTX_create();
+ if (ctx == NULL || ctx_init == NULL)
+ goto end;
+
+ if (!EVP_DigestInit(ctx_init, kdf_md))
+ goto end;
+
+ for (counter = 1;; counter++) {
+ c[0] = (unsigned char)((counter >> 24) & 0xff);
+ c[1] = (unsigned char)((counter >> 16) & 0xff);
+ c[2] = (unsigned char)((counter >> 8) & 0xff);
+ c[3] = (unsigned char)(counter & 0xff);
+
+ if (!(EVP_MD_CTX_copy_ex(ctx, ctx_init)
+ && (append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c)))
+ && EVP_DigestUpdate(ctx, z, z_len)
+ && (!append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c)))
+ && EVP_DigestUpdate(ctx, info, info_len)))
+ goto end;
+ if (len >= out_len) {
+ if (!EVP_DigestFinal_ex(ctx, out, NULL))
+ goto end;
+ out += out_len;
+ len -= out_len;
+ if (len == 0)
+ break;
+ } else {
+ if (!EVP_DigestFinal_ex(ctx, mac, NULL))
+ goto end;
+ memcpy(out, mac, len);
+ break;
+ }
+ }
+ ret = 1;
+end:
+ EVP_MD_CTX_destroy(ctx);
+ EVP_MD_CTX_destroy(ctx_init);
+ OPENSSL_cleanse(mac, sizeof(mac));
+ return ret;
+}
+
+static int kmac_init(EVP_MAC_CTX *ctx, const unsigned char *custom,
+ size_t custom_len, size_t kmac_out_len,
+ size_t derived_key_len, unsigned char **out)
+{
+ OSSL_PARAM params[2];
+
+ /* Only KMAC has custom data - so return if not KMAC */
+ if (custom == NULL)
+ return 1;
+
+ params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_CUSTOM,
+ (void *)custom, custom_len);
+ params[1] = OSSL_PARAM_construct_end();
+
+ if (!EVP_MAC_CTX_set_params(ctx, params))
+ return 0;
+
+ /* By default only do one iteration if kmac_out_len is not specified */
+ if (kmac_out_len == 0)
+ kmac_out_len = derived_key_len;
+ /* otherwise check the size is valid */
+ else if (!(kmac_out_len == derived_key_len
+ || kmac_out_len == 20
+ || kmac_out_len == 28
+ || kmac_out_len == 32
+ || kmac_out_len == 48
+ || kmac_out_len == 64))
+ return 0;
+
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE,
+ &kmac_out_len);
+
+ if (EVP_MAC_CTX_set_params(ctx, params) <= 0)
+ return 0;
+
+ /*
+ * For kmac the output buffer can be larger than EVP_MAX_MD_SIZE: so
+ * alloc a buffer for this case.
+ */
+ if (kmac_out_len > EVP_MAX_MD_SIZE) {
+ *out = OPENSSL_zalloc(kmac_out_len);
+ if (*out == NULL)
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final
+ * Section 4. One-Step Key Derivation using MAC: i.e either
+ * H(x) = HMAC-hash(salt, x) OR
+ * H(x) = KMAC#(salt, x, outbits, CustomString='KDF')
+ */
+static int SSKDF_mac_kdm(EVP_MAC_CTX *ctx_init,
+ const unsigned char *kmac_custom,
+ size_t kmac_custom_len, size_t kmac_out_len,
+ const unsigned char *salt, size_t salt_len,
+ const unsigned char *z, size_t z_len,
+ const unsigned char *info, size_t info_len,
+ unsigned char *derived_key, size_t derived_key_len)
+{
+ int ret = 0;
+ size_t counter, out_len, len;
+ unsigned char c[4];
+ unsigned char mac_buf[EVP_MAX_MD_SIZE];
+ unsigned char *out = derived_key;
+ EVP_MAC_CTX *ctx = NULL;
+ unsigned char *mac = mac_buf, *kmac_buffer = NULL;
+
+ if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN
+ || derived_key_len > SSKDF_MAX_INLEN
+ || derived_key_len == 0)
+ return 0;
+
+ if (!kmac_init(ctx_init, kmac_custom, kmac_custom_len, kmac_out_len,
+ derived_key_len, &kmac_buffer))
+ goto end;
+ if (kmac_buffer != NULL)
+ mac = kmac_buffer;
+
+ if (!EVP_MAC_init(ctx_init, salt, salt_len, NULL))
+ goto end;
+
+ out_len = EVP_MAC_CTX_get_mac_size(ctx_init); /* output size */
+ if (out_len <= 0 || (mac == mac_buf && out_len > sizeof(mac_buf)))
+ goto end;
+ len = derived_key_len;
+
+ for (counter = 1;; counter++) {
+ c[0] = (unsigned char)((counter >> 24) & 0xff);
+ c[1] = (unsigned char)((counter >> 16) & 0xff);
+ c[2] = (unsigned char)((counter >> 8) & 0xff);
+ c[3] = (unsigned char)(counter & 0xff);
+
+ ctx = EVP_MAC_CTX_dup(ctx_init);
+ if (!(ctx != NULL
+ && EVP_MAC_update(ctx, c, sizeof(c))
+ && EVP_MAC_update(ctx, z, z_len)
+ && EVP_MAC_update(ctx, info, info_len)))
+ goto end;
+ if (len >= out_len) {
+ if (!EVP_MAC_final(ctx, out, NULL, len))
+ goto end;
+ out += out_len;
+ len -= out_len;
+ if (len == 0)
+ break;
+ } else {
+ if (!EVP_MAC_final(ctx, mac, NULL, out_len))
+ goto end;
+ memcpy(out, mac, len);
+ break;
+ }
+ EVP_MAC_CTX_free(ctx);
+ ctx = NULL;
+ }
+ ret = 1;
+end:
+ if (kmac_buffer != NULL)
+ OPENSSL_clear_free(kmac_buffer, kmac_out_len);
+ else
+ OPENSSL_cleanse(mac_buf, sizeof(mac_buf));
+
+ EVP_MAC_CTX_free(ctx);
+ return ret;
+}
+
+static void *sskdf_new(void *provctx)
+{
+ KDF_SSKDF *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL)
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ ctx->provctx = provctx;
+ return ctx;
+}
+
+static void sskdf_reset(void *vctx)
+{
+ KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
+ void *provctx = ctx->provctx;
+
+ EVP_MAC_CTX_free(ctx->macctx);
+ ossl_prov_digest_reset(&ctx->digest);
+ OPENSSL_clear_free(ctx->secret, ctx->secret_len);
+ OPENSSL_clear_free(ctx->info, ctx->info_len);
+ OPENSSL_clear_free(ctx->salt, ctx->salt_len);
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->provctx = provctx;
+}
+
+static void sskdf_free(void *vctx)
+{
+ KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
+
+ if (ctx != NULL) {
+ sskdf_reset(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+static int sskdf_set_buffer(unsigned char **out, size_t *out_len,
+ const OSSL_PARAM *p)
+{
+ if (p->data == NULL || p->data_size == 0)
+ return 1;
+ OPENSSL_free(*out);
+ *out = NULL;
+ return OSSL_PARAM_get_octet_string(p, (void **)out, 0, out_len);
+}
+
+static size_t sskdf_size(KDF_SSKDF *ctx)
+{
+ int len;
+ const EVP_MD *md = NULL;
+
+ if (ctx->is_kmac)
+ return SIZE_MAX;
+
+ md = ossl_prov_digest_md(&ctx->digest);
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
+ return 0;
+ }
+ len = EVP_MD_get_size(md);
+ return (len <= 0) ? 0 : (size_t)len;
+}
+
+static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
+ const EVP_MD *md;
+
+ if (!ossl_prov_is_running() || !sskdf_set_ctx_params(ctx, params))
+ return 0;
+ if (ctx->secret == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET);
+ return 0;
+ }
+ md = ossl_prov_digest_md(&ctx->digest);
+
+ if (ctx->macctx != NULL) {
+ /* H(x) = KMAC or H(x) = HMAC */
+ int ret;
+ const unsigned char *custom = NULL;
+ size_t custom_len = 0;
+ int default_salt_len;
+ EVP_MAC *mac = EVP_MAC_CTX_get0_mac(ctx->macctx);
+
+ if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_HMAC)) {
+ /* H(x) = HMAC(x, salt, hash) */
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
+ return 0;
+ }
+ default_salt_len = EVP_MD_get_size(md);
+ if (default_salt_len <= 0)
+ return 0;
+ } else if (ctx->is_kmac) {
+ /* H(x) = KMACzzz(x, salt, custom) */
+ custom = kmac_custom_str;
+ custom_len = sizeof(kmac_custom_str);
+ if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC128))
+ default_salt_len = SSKDF_KMAC128_DEFAULT_SALT_SIZE;
+ else
+ default_salt_len = SSKDF_KMAC256_DEFAULT_SALT_SIZE;
+ } else {
+ ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_MAC_TYPE);
+ return 0;
+ }
+ /* If no salt is set then use a default_salt of zeros */
+ if (ctx->salt == NULL || ctx->salt_len <= 0) {
+ ctx->salt = OPENSSL_zalloc(default_salt_len);
+ if (ctx->salt == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ ctx->salt_len = default_salt_len;
+ }
+ ret = SSKDF_mac_kdm(ctx->macctx,
+ custom, custom_len, ctx->out_len,
+ ctx->salt, ctx->salt_len,
+ ctx->secret, ctx->secret_len,
+ ctx->info, ctx->info_len, key, keylen);
+ return ret;
+ } else {
+ /* H(x) = hash */
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
+ return 0;
+ }
+ return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len,
+ ctx->info, ctx->info_len, 0, key, keylen);
+ }
+}
+
+static int x963kdf_derive(void *vctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
+ const EVP_MD *md;
+
+ if (!ossl_prov_is_running() || !sskdf_set_ctx_params(ctx, params))
+ return 0;
+
+ if (ctx->secret == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET);
+ return 0;
+ }
+
+ if (ctx->macctx != NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED);
+ return 0;
+ }
+
+ /* H(x) = hash */
+ md = ossl_prov_digest_md(&ctx->digest);
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
+ return 0;
+ }
+
+ return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len,
+ ctx->info, ctx->info_len, 1, key, keylen);
+}
+
+static int sskdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ KDF_SSKDF *ctx = vctx;
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
+ size_t sz;
+
+ if (params == NULL)
+ return 1;
+
+ if (!ossl_prov_macctx_load_from_params(&ctx->macctx, params,
+ NULL, NULL, NULL, libctx))
+ return 0;
+ if (ctx->macctx != NULL) {
+ if (EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->macctx),
+ OSSL_MAC_NAME_KMAC128)
+ || EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->macctx),
+ OSSL_MAC_NAME_KMAC256)) {
+ ctx->is_kmac = 1;
+ }
+ }
+
+ if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL
+ || (p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL)
+ if (!sskdf_set_buffer(&ctx->secret, &ctx->secret_len, p))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO)) != NULL)
+ if (!sskdf_set_buffer(&ctx->info, &ctx->info_len, p))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)
+ if (!sskdf_set_buffer(&ctx->salt, &ctx->salt_len, p))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MAC_SIZE))
+ != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &sz) || sz == 0)
+ return 0;
+ ctx->out_len = sz;
+ }
+ return 1;
+}
+
+static const OSSL_PARAM *sskdf_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MAC, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
+ OSSL_PARAM_size_t(OSSL_KDF_PARAM_MAC_SIZE, NULL),
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+static int sskdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
+ return OSSL_PARAM_set_size_t(p, sskdf_size(ctx));
+ return -2;
+}
+
+static const OSSL_PARAM *sskdf_gettable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_kdf_sskdf_functions[] = {
+ { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new },
+ { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free },
+ { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset },
+ { OSSL_FUNC_KDF_DERIVE, (void(*)(void))sskdf_derive },
+ { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
+ (void(*)(void))sskdf_settable_ctx_params },
+ { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))sskdf_set_ctx_params },
+ { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
+ (void(*)(void))sskdf_gettable_ctx_params },
+ { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))sskdf_get_ctx_params },
+ { 0, NULL }
+};
+
+const OSSL_DISPATCH ossl_kdf_x963_kdf_functions[] = {
+ { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new },
+ { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free },
+ { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset },
+ { OSSL_FUNC_KDF_DERIVE, (void(*)(void))x963kdf_derive },
+ { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
+ (void(*)(void))sskdf_settable_ctx_params },
+ { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))sskdf_set_ctx_params },
+ { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
+ (void(*)(void))sskdf_gettable_ctx_params },
+ { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))sskdf_get_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/kdfs/tls1_prf.c b/providers/implementations/kdfs/tls1_prf.c
new file mode 100644
index 000000000000..a4d64b935222
--- /dev/null
+++ b/providers/implementations/kdfs/tls1_prf.c
@@ -0,0 +1,411 @@
+/*
+ * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Refer to "The TLS Protocol Version 1.0" Section 5
+ * (https://tools.ietf.org/html/rfc2246#section-5) and
+ * "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5
+ * (https://tools.ietf.org/html/rfc5246#section-5).
+ *
+ * For TLS v1.0 and TLS v1.1 the TLS PRF algorithm is given by:
+ *
+ * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
+ * P_SHA-1(S2, label + seed)
+ *
+ * where P_MD5 and P_SHA-1 are defined by P_<hash>, below, and S1 and S2 are
+ * two halves of the secret (with the possibility of one shared byte, in the
+ * case where the length of the original secret is odd). S1 is taken from the
+ * first half of the secret, S2 from the second half.
+ *
+ * For TLS v1.2 the TLS PRF algorithm is given by:
+ *
+ * PRF(secret, label, seed) = P_<hash>(secret, label + seed)
+ *
+ * where hash is SHA-256 for all cipher suites defined in RFC 5246 as well as
+ * those published prior to TLS v1.2 while the TLS v1.2 protocol is in effect,
+ * unless defined otherwise by the cipher suite.
+ *
+ * P_<hash> is an expansion function that uses a single hash function to expand
+ * a secret and seed into an arbitrary quantity of output:
+ *
+ * P_<hash>(secret, seed) = HMAC_<hash>(secret, A(1) + seed) +
+ * HMAC_<hash>(secret, A(2) + seed) +
+ * HMAC_<hash>(secret, A(3) + seed) + ...
+ *
+ * where + indicates concatenation. P_<hash> can be iterated as many times as
+ * is necessary to produce the required quantity of data.
+ *
+ * A(i) is defined as:
+ * A(0) = seed
+ * A(i) = HMAC_<hash>(secret, A(i-1))
+ */
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/proverr.h>
+#include "internal/cryptlib.h"
+#include "internal/numbers.h"
+#include "crypto/evp.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_util.h"
+#include "e_os.h"
+
+static OSSL_FUNC_kdf_newctx_fn kdf_tls1_prf_new;
+static OSSL_FUNC_kdf_freectx_fn kdf_tls1_prf_free;
+static OSSL_FUNC_kdf_reset_fn kdf_tls1_prf_reset;
+static OSSL_FUNC_kdf_derive_fn kdf_tls1_prf_derive;
+static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_tls1_prf_settable_ctx_params;
+static OSSL_FUNC_kdf_set_ctx_params_fn kdf_tls1_prf_set_ctx_params;
+static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_tls1_prf_gettable_ctx_params;
+static OSSL_FUNC_kdf_get_ctx_params_fn kdf_tls1_prf_get_ctx_params;
+
+static int tls1_prf_alg(EVP_MAC_CTX *mdctx, EVP_MAC_CTX *sha1ctx,
+ const unsigned char *sec, size_t slen,
+ const unsigned char *seed, size_t seed_len,
+ unsigned char *out, size_t olen);
+
+#define TLS1_PRF_MAXBUF 1024
+
+/* TLS KDF kdf context structure */
+typedef struct {
+ void *provctx;
+
+ /* MAC context for the main digest */
+ EVP_MAC_CTX *P_hash;
+ /* MAC context for SHA1 for the MD5/SHA-1 combined PRF */
+ EVP_MAC_CTX *P_sha1;
+
+ /* Secret value to use for PRF */
+ unsigned char *sec;
+ size_t seclen;
+ /* Buffer of concatenated seed data */
+ unsigned char seed[TLS1_PRF_MAXBUF];
+ size_t seedlen;
+} TLS1_PRF;
+
+static void *kdf_tls1_prf_new(void *provctx)
+{
+ TLS1_PRF *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ ctx->provctx = provctx;
+ return ctx;
+}
+
+static void kdf_tls1_prf_free(void *vctx)
+{
+ TLS1_PRF *ctx = (TLS1_PRF *)vctx;
+
+ if (ctx != NULL) {
+ kdf_tls1_prf_reset(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+static void kdf_tls1_prf_reset(void *vctx)
+{
+ TLS1_PRF *ctx = (TLS1_PRF *)vctx;
+ void *provctx = ctx->provctx;
+
+ EVP_MAC_CTX_free(ctx->P_hash);
+ EVP_MAC_CTX_free(ctx->P_sha1);
+ OPENSSL_clear_free(ctx->sec, ctx->seclen);
+ OPENSSL_cleanse(ctx->seed, ctx->seedlen);
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->provctx = provctx;
+}
+
+static int kdf_tls1_prf_derive(void *vctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ TLS1_PRF *ctx = (TLS1_PRF *)vctx;
+
+ if (!ossl_prov_is_running() || !kdf_tls1_prf_set_ctx_params(ctx, params))
+ return 0;
+
+ if (ctx->P_hash == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
+ return 0;
+ }
+ if (ctx->sec == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET);
+ return 0;
+ }
+ if (ctx->seedlen == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SEED);
+ return 0;
+ }
+ if (keylen == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+
+ return tls1_prf_alg(ctx->P_hash, ctx->P_sha1,
+ ctx->sec, ctx->seclen,
+ ctx->seed, ctx->seedlen,
+ key, keylen);
+}
+
+static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ TLS1_PRF *ctx = vctx;
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
+
+ if (params == NULL)
+ return 1;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) {
+ if (OPENSSL_strcasecmp(p->data, SN_md5_sha1) == 0) {
+ if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params,
+ OSSL_MAC_NAME_HMAC,
+ NULL, SN_md5, libctx)
+ || !ossl_prov_macctx_load_from_params(&ctx->P_sha1, params,
+ OSSL_MAC_NAME_HMAC,
+ NULL, SN_sha1, libctx))
+ return 0;
+ } else {
+ EVP_MAC_CTX_free(ctx->P_sha1);
+ if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params,
+ OSSL_MAC_NAME_HMAC,
+ NULL, NULL, libctx))
+ return 0;
+ }
+ }
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL) {
+ OPENSSL_clear_free(ctx->sec, ctx->seclen);
+ ctx->sec = NULL;
+ if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->sec, 0, &ctx->seclen))
+ return 0;
+ }
+ /* The seed fields concatenate, so process them all */
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SEED)) != NULL) {
+ for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1,
+ OSSL_KDF_PARAM_SEED)) {
+ const void *q = ctx->seed + ctx->seedlen;
+ size_t sz = 0;
+
+ if (p->data_size != 0
+ && p->data != NULL
+ && !OSSL_PARAM_get_octet_string(p, (void **)&q,
+ TLS1_PRF_MAXBUF - ctx->seedlen,
+ &sz))
+ return 0;
+ ctx->seedlen += sz;
+ }
+ }
+ return 1;
+}
+
+static const OSSL_PARAM *kdf_tls1_prf_settable_ctx_params(
+ ossl_unused void *ctx, ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SEED, NULL, 0),
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+static int kdf_tls1_prf_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
+ return OSSL_PARAM_set_size_t(p, SIZE_MAX);
+ return -2;
+}
+
+static const OSSL_PARAM *kdf_tls1_prf_gettable_ctx_params(
+ ossl_unused void *ctx, ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_kdf_tls1_prf_functions[] = {
+ { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_tls1_prf_new },
+ { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_tls1_prf_free },
+ { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_tls1_prf_reset },
+ { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_tls1_prf_derive },
+ { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_tls1_prf_settable_ctx_params },
+ { OSSL_FUNC_KDF_SET_CTX_PARAMS,
+ (void(*)(void))kdf_tls1_prf_set_ctx_params },
+ { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_tls1_prf_gettable_ctx_params },
+ { OSSL_FUNC_KDF_GET_CTX_PARAMS,
+ (void(*)(void))kdf_tls1_prf_get_ctx_params },
+ { 0, NULL }
+};
+
+/*
+ * Refer to "The TLS Protocol Version 1.0" Section 5
+ * (https://tools.ietf.org/html/rfc2246#section-5) and
+ * "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5
+ * (https://tools.ietf.org/html/rfc5246#section-5).
+ *
+ * P_<hash> is an expansion function that uses a single hash function to expand
+ * a secret and seed into an arbitrary quantity of output:
+ *
+ * P_<hash>(secret, seed) = HMAC_<hash>(secret, A(1) + seed) +
+ * HMAC_<hash>(secret, A(2) + seed) +
+ * HMAC_<hash>(secret, A(3) + seed) + ...
+ *
+ * where + indicates concatenation. P_<hash> can be iterated as many times as
+ * is necessary to produce the required quantity of data.
+ *
+ * A(i) is defined as:
+ * A(0) = seed
+ * A(i) = HMAC_<hash>(secret, A(i-1))
+ */
+static int tls1_prf_P_hash(EVP_MAC_CTX *ctx_init,
+ const unsigned char *sec, size_t sec_len,
+ const unsigned char *seed, size_t seed_len,
+ unsigned char *out, size_t olen)
+{
+ size_t chunk;
+ EVP_MAC_CTX *ctx = NULL, *ctx_Ai = NULL;
+ unsigned char Ai[EVP_MAX_MD_SIZE];
+ size_t Ai_len;
+ int ret = 0;
+
+ if (!EVP_MAC_init(ctx_init, sec, sec_len, NULL))
+ goto err;
+ chunk = EVP_MAC_CTX_get_mac_size(ctx_init);
+ if (chunk == 0)
+ goto err;
+ /* A(0) = seed */
+ ctx_Ai = EVP_MAC_CTX_dup(ctx_init);
+ if (ctx_Ai == NULL)
+ goto err;
+ if (seed != NULL && !EVP_MAC_update(ctx_Ai, seed, seed_len))
+ goto err;
+
+ for (;;) {
+ /* calc: A(i) = HMAC_<hash>(secret, A(i-1)) */
+ if (!EVP_MAC_final(ctx_Ai, Ai, &Ai_len, sizeof(Ai)))
+ goto err;
+ EVP_MAC_CTX_free(ctx_Ai);
+ ctx_Ai = NULL;
+
+ /* calc next chunk: HMAC_<hash>(secret, A(i) + seed) */
+ ctx = EVP_MAC_CTX_dup(ctx_init);
+ if (ctx == NULL)
+ goto err;
+ if (!EVP_MAC_update(ctx, Ai, Ai_len))
+ goto err;
+ /* save state for calculating next A(i) value */
+ if (olen > chunk) {
+ ctx_Ai = EVP_MAC_CTX_dup(ctx);
+ if (ctx_Ai == NULL)
+ goto err;
+ }
+ if (seed != NULL && !EVP_MAC_update(ctx, seed, seed_len))
+ goto err;
+ if (olen <= chunk) {
+ /* last chunk - use Ai as temp bounce buffer */
+ if (!EVP_MAC_final(ctx, Ai, &Ai_len, sizeof(Ai)))
+ goto err;
+ memcpy(out, Ai, olen);
+ break;
+ }
+ if (!EVP_MAC_final(ctx, out, NULL, olen))
+ goto err;
+ EVP_MAC_CTX_free(ctx);
+ ctx = NULL;
+ out += chunk;
+ olen -= chunk;
+ }
+ ret = 1;
+ err:
+ EVP_MAC_CTX_free(ctx);
+ EVP_MAC_CTX_free(ctx_Ai);
+ OPENSSL_cleanse(Ai, sizeof(Ai));
+ return ret;
+}
+
+/*
+ * Refer to "The TLS Protocol Version 1.0" Section 5
+ * (https://tools.ietf.org/html/rfc2246#section-5) and
+ * "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5
+ * (https://tools.ietf.org/html/rfc5246#section-5).
+ *
+ * For TLS v1.0 and TLS v1.1:
+ *
+ * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
+ * P_SHA-1(S2, label + seed)
+ *
+ * S1 is taken from the first half of the secret, S2 from the second half.
+ *
+ * L_S = length in bytes of secret;
+ * L_S1 = L_S2 = ceil(L_S / 2);
+ *
+ * For TLS v1.2:
+ *
+ * PRF(secret, label, seed) = P_<hash>(secret, label + seed)
+ */
+static int tls1_prf_alg(EVP_MAC_CTX *mdctx, EVP_MAC_CTX *sha1ctx,
+ const unsigned char *sec, size_t slen,
+ const unsigned char *seed, size_t seed_len,
+ unsigned char *out, size_t olen)
+{
+ if (sha1ctx != NULL) {
+ /* TLS v1.0 and TLS v1.1 */
+ size_t i;
+ unsigned char *tmp;
+ /* calc: L_S1 = L_S2 = ceil(L_S / 2) */
+ size_t L_S1 = (slen + 1) / 2;
+ size_t L_S2 = L_S1;
+
+ if (!tls1_prf_P_hash(mdctx, sec, L_S1,
+ seed, seed_len, out, olen))
+ return 0;
+
+ if ((tmp = OPENSSL_malloc(olen)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (!tls1_prf_P_hash(sha1ctx, sec + slen - L_S2, L_S2,
+ seed, seed_len, tmp, olen)) {
+ OPENSSL_clear_free(tmp, olen);
+ return 0;
+ }
+ for (i = 0; i < olen; i++)
+ out[i] ^= tmp[i];
+ OPENSSL_clear_free(tmp, olen);
+ return 1;
+ }
+
+ /* TLS v1.2 */
+ if (!tls1_prf_P_hash(mdctx, sec, slen, seed, seed_len, out, olen))
+ return 0;
+
+ return 1;
+}
diff --git a/providers/implementations/kdfs/x942kdf.c b/providers/implementations/kdfs/x942kdf.c
new file mode 100644
index 000000000000..b1bc6f7e1ba5
--- /dev/null
+++ b/providers/implementations/kdfs/x942kdf.c
@@ -0,0 +1,594 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "e_os.h"
+#include <openssl/core_names.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/params.h>
+#include <openssl/proverr.h>
+#include "internal/packet.h"
+#include "internal/der.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_util.h"
+#include "prov/der_wrap.h"
+
+#define X942KDF_MAX_INLEN (1 << 30)
+
+static OSSL_FUNC_kdf_newctx_fn x942kdf_new;
+static OSSL_FUNC_kdf_freectx_fn x942kdf_free;
+static OSSL_FUNC_kdf_reset_fn x942kdf_reset;
+static OSSL_FUNC_kdf_derive_fn x942kdf_derive;
+static OSSL_FUNC_kdf_settable_ctx_params_fn x942kdf_settable_ctx_params;
+static OSSL_FUNC_kdf_set_ctx_params_fn x942kdf_set_ctx_params;
+static OSSL_FUNC_kdf_gettable_ctx_params_fn x942kdf_gettable_ctx_params;
+static OSSL_FUNC_kdf_get_ctx_params_fn x942kdf_get_ctx_params;
+
+typedef struct {
+ void *provctx;
+ PROV_DIGEST digest;
+ unsigned char *secret;
+ size_t secret_len;
+ unsigned char *acvpinfo;
+ size_t acvpinfo_len;
+ unsigned char *partyuinfo, *partyvinfo, *supp_pubinfo, *supp_privinfo;
+ size_t partyuinfo_len, partyvinfo_len, supp_pubinfo_len, supp_privinfo_len;
+ size_t dkm_len;
+ const unsigned char *cek_oid;
+ size_t cek_oid_len;
+ int use_keybits;
+} KDF_X942;
+
+/*
+ * A table of allowed wrapping algorithms, oids and the associated output
+ * lengths.
+ * NOTE: RC2wrap and camellia128_wrap have been removed as there are no
+ * corresponding ciphers for these operations.
+ */
+static const struct {
+ const char *name;
+ const unsigned char *oid;
+ size_t oid_len;
+ size_t keklen; /* size in bytes */
+} kek_algs[] = {
+ { "AES-128-WRAP", ossl_der_oid_id_aes128_wrap, DER_OID_SZ_id_aes128_wrap,
+ 16 },
+ { "AES-192-WRAP", ossl_der_oid_id_aes192_wrap, DER_OID_SZ_id_aes192_wrap,
+ 24 },
+ { "AES-256-WRAP", ossl_der_oid_id_aes256_wrap, DER_OID_SZ_id_aes256_wrap,
+ 32 },
+#ifndef FIPS_MODULE
+ { "DES3-WRAP", ossl_der_oid_id_alg_CMS3DESwrap,
+ DER_OID_SZ_id_alg_CMS3DESwrap, 24 },
+#endif
+};
+
+static int find_alg_id(OSSL_LIB_CTX *libctx, const char *algname,
+ const char *propq, size_t *id)
+{
+ int ret = 1;
+ size_t i;
+ EVP_CIPHER *cipher;
+
+ cipher = EVP_CIPHER_fetch(libctx, algname, propq);
+ if (cipher != NULL) {
+ for (i = 0; i < OSSL_NELEM(kek_algs); i++) {
+ if (EVP_CIPHER_is_a(cipher, kek_algs[i].name)) {
+ *id = i;
+ goto end;
+ }
+ }
+ }
+ ret = 0;
+ ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_CEK_ALG);
+end:
+ EVP_CIPHER_free(cipher);
+ return ret;
+}
+
+static int DER_w_keyinfo(WPACKET *pkt,
+ const unsigned char *der_oid, size_t der_oidlen,
+ unsigned char **pcounter)
+{
+ return ossl_DER_w_begin_sequence(pkt, -1)
+ /* Store the initial value of 1 into the counter */
+ && ossl_DER_w_octet_string_uint32(pkt, -1, 1)
+ /* Remember where we stored the counter in the buffer */
+ && (pcounter == NULL
+ || (*pcounter = WPACKET_get_curr(pkt)) != NULL)
+ && ossl_DER_w_precompiled(pkt, -1, der_oid, der_oidlen)
+ && ossl_DER_w_end_sequence(pkt, -1);
+}
+
+static int der_encode_sharedinfo(WPACKET *pkt, unsigned char *buf, size_t buflen,
+ const unsigned char *der_oid, size_t der_oidlen,
+ const unsigned char *acvp, size_t acvplen,
+ const unsigned char *partyu, size_t partyulen,
+ const unsigned char *partyv, size_t partyvlen,
+ const unsigned char *supp_pub, size_t supp_publen,
+ const unsigned char *supp_priv, size_t supp_privlen,
+ uint32_t keylen_bits, unsigned char **pcounter)
+{
+ return (buf != NULL ? WPACKET_init_der(pkt, buf, buflen) :
+ WPACKET_init_null_der(pkt))
+ && ossl_DER_w_begin_sequence(pkt, -1)
+ && (supp_priv == NULL
+ || ossl_DER_w_octet_string(pkt, 3, supp_priv, supp_privlen))
+ && (supp_pub == NULL
+ || ossl_DER_w_octet_string(pkt, 2, supp_pub, supp_publen))
+ && (keylen_bits == 0
+ || ossl_DER_w_octet_string_uint32(pkt, 2, keylen_bits))
+ && (partyv == NULL || ossl_DER_w_octet_string(pkt, 1, partyv, partyvlen))
+ && (partyu == NULL || ossl_DER_w_octet_string(pkt, 0, partyu, partyulen))
+ && (acvp == NULL || ossl_DER_w_precompiled(pkt, -1, acvp, acvplen))
+ && DER_w_keyinfo(pkt, der_oid, der_oidlen, pcounter)
+ && ossl_DER_w_end_sequence(pkt, -1)
+ && WPACKET_finish(pkt);
+}
+
+/*
+ * Encode the other info structure.
+ *
+ * The ANS X9.42-2003 standard uses OtherInfo:
+ *
+ * OtherInfo ::= SEQUENCE {
+ * keyInfo KeySpecificInfo,
+ * partyUInfo [0] OCTET STRING OPTIONAL,
+ * partyVInfo [1] OCTET STRING OPTIONAL,
+ * suppPubInfo [2] OCTET STRING OPTIONAL,
+ * suppPrivInfo [3] OCTET STRING OPTIONAL
+ * }
+ *
+ * KeySpecificInfo ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * counter OCTET STRING SIZE (4..4)
+ * }
+ *
+ * RFC2631 Section 2.1.2 Contains the following definition for OtherInfo
+ *
+ * OtherInfo ::= SEQUENCE {
+ * keyInfo KeySpecificInfo,
+ * partyAInfo [0] OCTET STRING OPTIONAL,
+ * suppPubInfo [2] OCTET STRING
+ * }
+ * Where suppPubInfo is the key length (in bits) (stored into 4 bytes)
+ *
+ * |keylen| is the length (in bytes) of the generated KEK. It is stored into
+ * suppPubInfo (in bits). It is ignored if the value is 0.
+ * |cek_oid| The oid of the key wrapping algorithm.
+ * |cek_oidlen| The length (in bytes) of the key wrapping algorithm oid,
+ * |acvp| is the optional blob of DER data representing one or more of the
+ * OtherInfo fields related to |partyu|, |partyv|, |supp_pub| and |supp_priv|.
+ * This field should noramlly be NULL. If |acvp| is non NULL then |partyu|,
+ * |partyv|, |supp_pub| and |supp_priv| should all be NULL.
+ * |acvp_len| is the |acvp| length (in bytes).
+ * |partyu| is the optional public info contributed by the initiator.
+ * It can be NULL. (It is also used as the ukm by CMS).
+ * |partyu_len| is the |partyu| length (in bytes).
+ * |partyv| is the optional public info contributed by the responder.
+ * It can be NULL.
+ * |partyv_len| is the |partyv| length (in bytes).
+ * |supp_pub| is the optional additional, mutually-known public information.
+ * It can be NULL. |keylen| should be 0 if this is not NULL.
+ * |supp_pub_len| is the |supp_pub| length (in bytes).
+ * |supp_priv| is the optional additional, mutually-known private information.
+ * It can be NULL.
+ * |supp_priv_len| is the |supp_priv| length (in bytes).
+ * |der| is the returned encoded data. It must be freed by the caller.
+ * |der_len| is the returned size of the encoded data.
+ * |out_ctr| returns a pointer to the counter data which is embedded inside the
+ * encoded data. This allows the counter bytes to be updated without
+ * re-encoding.
+ *
+ * Returns: 1 if successfully encoded, or 0 otherwise.
+ * Assumptions: |der|, |der_len| & |out_ctr| are not NULL.
+ */
+static int
+x942_encode_otherinfo(size_t keylen,
+ const unsigned char *cek_oid, size_t cek_oid_len,
+ const unsigned char *acvp, size_t acvp_len,
+ const unsigned char *partyu, size_t partyu_len,
+ const unsigned char *partyv, size_t partyv_len,
+ const unsigned char *supp_pub, size_t supp_pub_len,
+ const unsigned char *supp_priv, size_t supp_priv_len,
+ unsigned char **der, size_t *der_len,
+ unsigned char **out_ctr)
+{
+ int ret = 0;
+ unsigned char *pcounter = NULL, *der_buf = NULL;
+ size_t der_buflen = 0;
+ WPACKET pkt;
+ uint32_t keylen_bits;
+
+ /* keylenbits must fit into 4 bytes */
+ if (keylen > 0xFFFFFF)
+ return 0;
+ keylen_bits = 8 * keylen;
+
+ /* Calculate the size of the buffer */
+ if (!der_encode_sharedinfo(&pkt, NULL, 0, cek_oid, cek_oid_len,
+ acvp, acvp_len,
+ partyu, partyu_len, partyv, partyv_len,
+ supp_pub, supp_pub_len, supp_priv, supp_priv_len,
+ keylen_bits, NULL)
+ || !WPACKET_get_total_written(&pkt, &der_buflen))
+ goto err;
+ WPACKET_cleanup(&pkt);
+ /* Alloc the buffer */
+ der_buf = OPENSSL_zalloc(der_buflen);
+ if (der_buf == NULL)
+ goto err;
+ /* Encode into the buffer */
+ if (!der_encode_sharedinfo(&pkt, der_buf, der_buflen, cek_oid, cek_oid_len,
+ acvp, acvp_len,
+ partyu, partyu_len, partyv, partyv_len,
+ supp_pub, supp_pub_len, supp_priv, supp_priv_len,
+ keylen_bits, &pcounter))
+ goto err;
+ /*
+ * Since we allocated the exact size required, the buffer should point to the
+ * start of the alllocated buffer at this point.
+ */
+ if (WPACKET_get_curr(&pkt) != der_buf)
+ goto err;
+
+ /*
+ * The data for the DER encoded octet string of a 32 bit counter = 1
+ * should be 04 04 00 00 00 01
+ * So just check the header is correct and skip over it.
+ * This counter will be incremented in the kdf update loop.
+ */
+ if (pcounter == NULL
+ || pcounter[0] != 0x04
+ || pcounter[1] != 0x04)
+ goto err;
+ *out_ctr = (pcounter + 2);
+ *der = der_buf;
+ *der_len = der_buflen;
+ ret = 1;
+err:
+ WPACKET_cleanup(&pkt);
+ return ret;
+}
+
+static int x942kdf_hash_kdm(const EVP_MD *kdf_md,
+ const unsigned char *z, size_t z_len,
+ const unsigned char *other, size_t other_len,
+ unsigned char *ctr,
+ unsigned char *derived_key, size_t derived_key_len)
+{
+ int ret = 0, hlen;
+ size_t counter, out_len, len = derived_key_len;
+ unsigned char mac[EVP_MAX_MD_SIZE];
+ unsigned char *out = derived_key;
+ EVP_MD_CTX *ctx = NULL, *ctx_init = NULL;
+
+ if (z_len > X942KDF_MAX_INLEN
+ || other_len > X942KDF_MAX_INLEN
+ || derived_key_len > X942KDF_MAX_INLEN
+ || derived_key_len == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH);
+ return 0;
+ }
+
+ hlen = EVP_MD_get_size(kdf_md);
+ if (hlen <= 0)
+ return 0;
+ out_len = (size_t)hlen;
+
+ ctx = EVP_MD_CTX_create();
+ ctx_init = EVP_MD_CTX_create();
+ if (ctx == NULL || ctx_init == NULL)
+ goto end;
+
+ if (!EVP_DigestInit(ctx_init, kdf_md))
+ goto end;
+
+ for (counter = 1;; counter++) {
+ /* updating the ctr modifies 4 bytes in the 'other' buffer */
+ ctr[0] = (unsigned char)((counter >> 24) & 0xff);
+ ctr[1] = (unsigned char)((counter >> 16) & 0xff);
+ ctr[2] = (unsigned char)((counter >> 8) & 0xff);
+ ctr[3] = (unsigned char)(counter & 0xff);
+
+ if (!EVP_MD_CTX_copy_ex(ctx, ctx_init)
+ || !EVP_DigestUpdate(ctx, z, z_len)
+ || !EVP_DigestUpdate(ctx, other, other_len))
+ goto end;
+ if (len >= out_len) {
+ if (!EVP_DigestFinal_ex(ctx, out, NULL))
+ goto end;
+ out += out_len;
+ len -= out_len;
+ if (len == 0)
+ break;
+ } else {
+ if (!EVP_DigestFinal_ex(ctx, mac, NULL))
+ goto end;
+ memcpy(out, mac, len);
+ break;
+ }
+ }
+ ret = 1;
+end:
+ EVP_MD_CTX_free(ctx);
+ EVP_MD_CTX_free(ctx_init);
+ OPENSSL_cleanse(mac, sizeof(mac));
+ return ret;
+}
+
+static void *x942kdf_new(void *provctx)
+{
+ KDF_X942 *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ ctx->provctx = provctx;
+ ctx->use_keybits = 1;
+ return ctx;
+}
+
+static void x942kdf_reset(void *vctx)
+{
+ KDF_X942 *ctx = (KDF_X942 *)vctx;
+ void *provctx = ctx->provctx;
+
+ ossl_prov_digest_reset(&ctx->digest);
+ OPENSSL_clear_free(ctx->secret, ctx->secret_len);
+ OPENSSL_clear_free(ctx->acvpinfo, ctx->acvpinfo_len);
+ OPENSSL_clear_free(ctx->partyuinfo, ctx->partyuinfo_len);
+ OPENSSL_clear_free(ctx->partyvinfo, ctx->partyvinfo_len);
+ OPENSSL_clear_free(ctx->supp_pubinfo, ctx->supp_pubinfo_len);
+ OPENSSL_clear_free(ctx->supp_privinfo, ctx->supp_privinfo_len);
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->provctx = provctx;
+ ctx->use_keybits = 1;
+}
+
+static void x942kdf_free(void *vctx)
+{
+ KDF_X942 *ctx = (KDF_X942 *)vctx;
+
+ if (ctx != NULL) {
+ x942kdf_reset(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+static int x942kdf_set_buffer(unsigned char **out, size_t *out_len,
+ const OSSL_PARAM *p)
+{
+ if (p->data_size == 0 || p->data == NULL)
+ return 1;
+
+ OPENSSL_free(*out);
+ *out = NULL;
+ return OSSL_PARAM_get_octet_string(p, (void **)out, 0, out_len);
+}
+
+static size_t x942kdf_size(KDF_X942 *ctx)
+{
+ int len;
+ const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
+
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
+ return 0;
+ }
+ len = EVP_MD_get_size(md);
+ return (len <= 0) ? 0 : (size_t)len;
+}
+
+static int x942kdf_derive(void *vctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ KDF_X942 *ctx = (KDF_X942 *)vctx;
+ const EVP_MD *md;
+ int ret = 0;
+ unsigned char *ctr;
+ unsigned char *der = NULL;
+ size_t der_len = 0;
+
+ if (!ossl_prov_is_running() || !x942kdf_set_ctx_params(ctx, params))
+ return 0;
+
+ /*
+ * These 2 options encode to the same field so only one of them should be
+ * active at once.
+ */
+ if (ctx->use_keybits && ctx->supp_pubinfo != NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PUBINFO);
+ return 0;
+ }
+ /*
+ * If the blob of acvp data is used then the individual info fields that it
+ * replaces should not also be defined.
+ */
+ if (ctx->acvpinfo != NULL
+ && (ctx->partyuinfo != NULL
+ || ctx->partyvinfo != NULL
+ || ctx->supp_pubinfo != NULL
+ || ctx->supp_privinfo != NULL)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA);
+ return 0;
+ }
+ if (ctx->secret == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET);
+ return 0;
+ }
+ md = ossl_prov_digest_md(&ctx->digest);
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
+ return 0;
+ }
+ if (ctx->cek_oid == NULL || ctx->cek_oid_len == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CEK_ALG);
+ return 0;
+ }
+ if (ctx->partyuinfo != NULL && ctx->partyuinfo_len >= X942KDF_MAX_INLEN) {
+ /*
+ * Note the ukm length MUST be 512 bits if it is used.
+ * For backwards compatibility the old check is being done.
+ */
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_UKM_LENGTH);
+ return 0;
+ }
+ /* generate the otherinfo der */
+ if (!x942_encode_otherinfo(ctx->use_keybits ? ctx->dkm_len : 0,
+ ctx->cek_oid, ctx->cek_oid_len,
+ ctx->acvpinfo, ctx->acvpinfo_len,
+ ctx->partyuinfo, ctx->partyuinfo_len,
+ ctx->partyvinfo, ctx->partyvinfo_len,
+ ctx->supp_pubinfo, ctx->supp_pubinfo_len,
+ ctx->supp_privinfo, ctx->supp_privinfo_len,
+ &der, &der_len, &ctr)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_BAD_ENCODING);
+ return 0;
+ }
+ ret = x942kdf_hash_kdm(md, ctx->secret, ctx->secret_len,
+ der, der_len, ctr, key, keylen);
+ OPENSSL_free(der);
+ return ret;
+}
+
+static int x942kdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p, *pq;
+ KDF_X942 *ctx = vctx;
+ OSSL_LIB_CTX *provctx = PROV_LIBCTX_OF(ctx->provctx);
+ const char *propq = NULL;
+ size_t id;
+
+ if (params == NULL)
+ return 1;
+ if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET);
+ if (p == NULL)
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY);
+ if (p != NULL && !x942kdf_set_buffer(&ctx->secret, &ctx->secret_len, p))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_X942_ACVPINFO);
+ if (p != NULL
+ && !x942kdf_set_buffer(&ctx->acvpinfo, &ctx->acvpinfo_len, p))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_X942_PARTYUINFO);
+ if (p == NULL)
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_UKM);
+ if (p != NULL
+ && !x942kdf_set_buffer(&ctx->partyuinfo, &ctx->partyuinfo_len, p))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_X942_PARTYVINFO);
+ if (p != NULL
+ && !x942kdf_set_buffer(&ctx->partyvinfo, &ctx->partyvinfo_len, p))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_X942_USE_KEYBITS);
+ if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->use_keybits))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_X942_SUPP_PUBINFO);
+ if (p != NULL) {
+ if (!x942kdf_set_buffer(&ctx->supp_pubinfo, &ctx->supp_pubinfo_len, p))
+ return 0;
+ ctx->use_keybits = 0;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_X942_SUPP_PRIVINFO);
+ if (p != NULL
+ && !x942kdf_set_buffer(&ctx->supp_privinfo, &ctx->supp_privinfo_len, p))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_CEK_ALG);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+ pq = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_PROPERTIES);
+ /*
+ * We already grab the properties during ossl_prov_digest_load_from_params()
+ * so there is no need to check the validity again..
+ */
+ if (pq != NULL)
+ propq = p->data;
+ if (find_alg_id(provctx, p->data, propq, &id) == 0)
+ return 0;
+ ctx->cek_oid = kek_algs[id].oid;
+ ctx->cek_oid_len = kek_algs[id].oid_len;
+ ctx->dkm_len = kek_algs[id].keklen;
+ }
+ return 1;
+}
+
+static const OSSL_PARAM *x942kdf_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_UKM, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_X942_ACVPINFO, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_X942_PARTYUINFO, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_X942_PARTYVINFO, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_X942_SUPP_PUBINFO, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_X942_SUPP_PRIVINFO, NULL, 0),
+ OSSL_PARAM_int(OSSL_KDF_PARAM_X942_USE_KEYBITS, NULL),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0),
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+static int x942kdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ KDF_X942 *ctx = (KDF_X942 *)vctx;
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
+ return OSSL_PARAM_set_size_t(p, x942kdf_size(ctx));
+ return -2;
+}
+
+static const OSSL_PARAM *x942kdf_gettable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_kdf_x942_kdf_functions[] = {
+ { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))x942kdf_new },
+ { OSSL_FUNC_KDF_FREECTX, (void(*)(void))x942kdf_free },
+ { OSSL_FUNC_KDF_RESET, (void(*)(void))x942kdf_reset },
+ { OSSL_FUNC_KDF_DERIVE, (void(*)(void))x942kdf_derive },
+ { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
+ (void(*)(void))x942kdf_settable_ctx_params },
+ { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))x942kdf_set_ctx_params },
+ { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
+ (void(*)(void))x942kdf_gettable_ctx_params },
+ { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))x942kdf_get_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/kem/build.info b/providers/implementations/kem/build.info
new file mode 100644
index 000000000000..dbb1b7d750d9
--- /dev/null
+++ b/providers/implementations/kem/build.info
@@ -0,0 +1,6 @@
+# We make separate GOAL variables for each algorithm, to make it easy to
+# switch each to the Legacy provider when needed.
+
+$RSA_KEM_GOAL=../../libdefault.a ../../libfips.a
+
+SOURCE[$RSA_KEM_GOAL]=rsa_kem.c
diff --git a/providers/implementations/kem/rsa_kem.c b/providers/implementations/kem/rsa_kem.c
new file mode 100644
index 000000000000..882cf161258a
--- /dev/null
+++ b/providers/implementations/kem/rsa_kem.c
@@ -0,0 +1,364 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+#include "internal/nelem.h"
+
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/rsa.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#include "crypto/rsa.h"
+#include <openssl/proverr.h>
+#include "prov/provider_ctx.h"
+#include "prov/implementations.h"
+#include "prov/securitycheck.h"
+
+static OSSL_FUNC_kem_newctx_fn rsakem_newctx;
+static OSSL_FUNC_kem_encapsulate_init_fn rsakem_encapsulate_init;
+static OSSL_FUNC_kem_encapsulate_fn rsakem_generate;
+static OSSL_FUNC_kem_decapsulate_init_fn rsakem_decapsulate_init;
+static OSSL_FUNC_kem_decapsulate_fn rsakem_recover;
+static OSSL_FUNC_kem_freectx_fn rsakem_freectx;
+static OSSL_FUNC_kem_dupctx_fn rsakem_dupctx;
+static OSSL_FUNC_kem_get_ctx_params_fn rsakem_get_ctx_params;
+static OSSL_FUNC_kem_gettable_ctx_params_fn rsakem_gettable_ctx_params;
+static OSSL_FUNC_kem_set_ctx_params_fn rsakem_set_ctx_params;
+static OSSL_FUNC_kem_settable_ctx_params_fn rsakem_settable_ctx_params;
+
+/*
+ * Only the KEM for RSASVE as defined in SP800-56b r2 is implemented
+ * currently.
+ */
+#define KEM_OP_UNDEFINED -1
+#define KEM_OP_RSASVE 0
+
+/*
+ * What's passed as an actual key is defined by the KEYMGMT interface.
+ * We happen to know that our KEYMGMT simply passes RSA structures, so
+ * we use that here too.
+ */
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ RSA *rsa;
+ int op;
+} PROV_RSA_CTX;
+
+static const OSSL_ITEM rsakem_opname_id_map[] = {
+ { KEM_OP_RSASVE, OSSL_KEM_PARAM_OPERATION_RSASVE },
+};
+
+static int name2id(const char *name, const OSSL_ITEM *map, size_t sz)
+{
+ size_t i;
+
+ if (name == NULL)
+ return -1;
+
+ for (i = 0; i < sz; ++i) {
+ if (OPENSSL_strcasecmp(map[i].ptr, name) == 0)
+ return map[i].id;
+ }
+ return -1;
+}
+
+static int rsakem_opname2id(const char *name)
+{
+ return name2id(name, rsakem_opname_id_map, OSSL_NELEM(rsakem_opname_id_map));
+}
+
+static void *rsakem_newctx(void *provctx)
+{
+ PROV_RSA_CTX *prsactx = OPENSSL_zalloc(sizeof(PROV_RSA_CTX));
+
+ if (prsactx == NULL)
+ return NULL;
+ prsactx->libctx = PROV_LIBCTX_OF(provctx);
+ prsactx->op = KEM_OP_UNDEFINED;
+
+ return prsactx;
+}
+
+static void rsakem_freectx(void *vprsactx)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ RSA_free(prsactx->rsa);
+ OPENSSL_free(prsactx);
+}
+
+static void *rsakem_dupctx(void *vprsactx)
+{
+ PROV_RSA_CTX *srcctx = (PROV_RSA_CTX *)vprsactx;
+ PROV_RSA_CTX *dstctx;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+ if (dstctx == NULL)
+ return NULL;
+
+ *dstctx = *srcctx;
+ if (dstctx->rsa != NULL && !RSA_up_ref(dstctx->rsa)) {
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+ return dstctx;
+}
+
+static int rsakem_init(void *vprsactx, void *vrsa,
+ const OSSL_PARAM params[], int operation)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (prsactx == NULL || vrsa == NULL)
+ return 0;
+
+ if (!ossl_rsa_check_key(prsactx->libctx, vrsa, operation))
+ return 0;
+
+ if (!RSA_up_ref(vrsa))
+ return 0;
+ RSA_free(prsactx->rsa);
+ prsactx->rsa = vrsa;
+
+ return rsakem_set_ctx_params(prsactx, params);
+}
+
+static int rsakem_encapsulate_init(void *vprsactx, void *vrsa,
+ const OSSL_PARAM params[])
+{
+ return rsakem_init(vprsactx, vrsa, params, EVP_PKEY_OP_ENCAPSULATE);
+}
+
+static int rsakem_decapsulate_init(void *vprsactx, void *vrsa,
+ const OSSL_PARAM params[])
+{
+ return rsakem_init(vprsactx, vrsa, params, EVP_PKEY_OP_DECAPSULATE);
+}
+
+static int rsakem_get_ctx_params(void *vprsactx, OSSL_PARAM *params)
+{
+ PROV_RSA_CTX *ctx = (PROV_RSA_CTX *)vprsactx;
+
+ return ctx != NULL;
+}
+
+static const OSSL_PARAM known_gettable_rsakem_ctx_params[] = {
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *rsakem_gettable_ctx_params(ossl_unused void *vprsactx,
+ ossl_unused void *provctx)
+{
+ return known_gettable_rsakem_ctx_params;
+}
+
+static int rsakem_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ const OSSL_PARAM *p;
+ int op;
+
+ if (prsactx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KEM_PARAM_OPERATION);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+ op = rsakem_opname2id(p->data);
+ if (op < 0)
+ return 0;
+ prsactx->op = op;
+ }
+ return 1;
+}
+
+static const OSSL_PARAM known_settable_rsakem_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_KEM_PARAM_OPERATION, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *rsakem_settable_ctx_params(ossl_unused void *vprsactx,
+ ossl_unused void *provctx)
+{
+ return known_settable_rsakem_ctx_params;
+}
+
+/*
+ * NIST.SP.800-56Br2
+ * 7.2.1.2 RSASVE Generate Operation (RSASVE.GENERATE).
+ *
+ * Generate a random in the range 1 < z < (n – 1)
+ */
+static int rsasve_gen_rand_bytes(RSA *rsa_pub,
+ unsigned char *out, int outlen)
+{
+ int ret = 0;
+ BN_CTX *bnctx;
+ BIGNUM *z, *nminus3;
+
+ bnctx = BN_CTX_secure_new_ex(ossl_rsa_get0_libctx(rsa_pub));
+ if (bnctx == NULL)
+ return 0;
+
+ /*
+ * Generate a random in the range 1 < z < (n – 1).
+ * Since BN_priv_rand_range_ex() returns a value in range 0 <= r < max
+ * We can achieve this by adding 2.. but then we need to subtract 3 from
+ * the upper bound i.e: 2 + (0 <= r < (n - 3))
+ */
+ BN_CTX_start(bnctx);
+ nminus3 = BN_CTX_get(bnctx);
+ z = BN_CTX_get(bnctx);
+ ret = (z != NULL
+ && (BN_copy(nminus3, RSA_get0_n(rsa_pub)) != NULL)
+ && BN_sub_word(nminus3, 3)
+ && BN_priv_rand_range_ex(z, nminus3, 0, bnctx)
+ && BN_add_word(z, 2)
+ && (BN_bn2binpad(z, out, outlen) == outlen));
+ BN_CTX_end(bnctx);
+ BN_CTX_free(bnctx);
+ return ret;
+}
+
+/*
+ * NIST.SP.800-56Br2
+ * 7.2.1.2 RSASVE Generate Operation (RSASVE.GENERATE).
+ */
+static int rsasve_generate(PROV_RSA_CTX *prsactx,
+ unsigned char *out, size_t *outlen,
+ unsigned char *secret, size_t *secretlen)
+{
+ int ret;
+ size_t nlen;
+
+ /* Step (1): nlen = Ceil(len(n)/8) */
+ nlen = RSA_size(prsactx->rsa);
+
+ if (out == NULL) {
+ if (nlen == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
+ return 0;
+ }
+ if (outlen == NULL && secretlen == NULL)
+ return 0;
+ if (outlen != NULL)
+ *outlen = nlen;
+ if (secretlen != NULL)
+ *secretlen = nlen;
+ return 1;
+ }
+ /*
+ * Step (2): Generate a random byte string z of nlen bytes where
+ * 1 < z < n - 1
+ */
+ if (!rsasve_gen_rand_bytes(prsactx->rsa, secret, nlen))
+ return 0;
+
+ /* Step(3): out = RSAEP((n,e), z) */
+ ret = RSA_public_encrypt(nlen, secret, out, prsactx->rsa, RSA_NO_PADDING);
+ if (ret) {
+ ret = 1;
+ if (outlen != NULL)
+ *outlen = nlen;
+ if (secretlen != NULL)
+ *secretlen = nlen;
+ } else {
+ OPENSSL_cleanse(secret, nlen);
+ }
+ return ret;
+}
+
+/*
+ * NIST.SP.800-56Br2
+ * 7.2.1.3 RSASVE Recovery Operation (RSASVE.RECOVER).
+ */
+static int rsasve_recover(PROV_RSA_CTX *prsactx,
+ unsigned char *out, size_t *outlen,
+ const unsigned char *in, size_t inlen)
+{
+ size_t nlen;
+
+ /* Step (1): get the byte length of n */
+ nlen = RSA_size(prsactx->rsa);
+
+ if (out == NULL) {
+ if (nlen == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
+ return 0;
+ }
+ *outlen = nlen;
+ return 1;
+ }
+
+ /* Step (2): check the input ciphertext 'inlen' matches the nlen */
+ if (inlen != nlen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH);
+ return 0;
+ }
+ /* Step (3): out = RSADP((n,d), in) */
+ return (RSA_private_decrypt(inlen, in, out, prsactx->rsa, RSA_NO_PADDING) > 0);
+}
+
+static int rsakem_generate(void *vprsactx, unsigned char *out, size_t *outlen,
+ unsigned char *secret, size_t *secretlen)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ switch (prsactx->op) {
+ case KEM_OP_RSASVE:
+ return rsasve_generate(prsactx, out, outlen, secret, secretlen);
+ default:
+ return -2;
+ }
+}
+
+static int rsakem_recover(void *vprsactx, unsigned char *out, size_t *outlen,
+ const unsigned char *in, size_t inlen)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ switch (prsactx->op) {
+ case KEM_OP_RSASVE:
+ return rsasve_recover(prsactx, out, outlen, in, inlen);
+ default:
+ return -2;
+ }
+}
+
+const OSSL_DISPATCH ossl_rsa_asym_kem_functions[] = {
+ { OSSL_FUNC_KEM_NEWCTX, (void (*)(void))rsakem_newctx },
+ { OSSL_FUNC_KEM_ENCAPSULATE_INIT,
+ (void (*)(void))rsakem_encapsulate_init },
+ { OSSL_FUNC_KEM_ENCAPSULATE, (void (*)(void))rsakem_generate },
+ { OSSL_FUNC_KEM_DECAPSULATE_INIT,
+ (void (*)(void))rsakem_decapsulate_init },
+ { OSSL_FUNC_KEM_DECAPSULATE, (void (*)(void))rsakem_recover },
+ { OSSL_FUNC_KEM_FREECTX, (void (*)(void))rsakem_freectx },
+ { OSSL_FUNC_KEM_DUPCTX, (void (*)(void))rsakem_dupctx },
+ { OSSL_FUNC_KEM_GET_CTX_PARAMS,
+ (void (*)(void))rsakem_get_ctx_params },
+ { OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS,
+ (void (*)(void))rsakem_gettable_ctx_params },
+ { OSSL_FUNC_KEM_SET_CTX_PARAMS,
+ (void (*)(void))rsakem_set_ctx_params },
+ { OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS,
+ (void (*)(void))rsakem_settable_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/keymgmt/build.info b/providers/implementations/keymgmt/build.info
new file mode 100644
index 000000000000..0d86907aed69
--- /dev/null
+++ b/providers/implementations/keymgmt/build.info
@@ -0,0 +1,41 @@
+# We make separate GOAL variables for each algorithm, to make it easy to
+# switch each to the Legacy provider when needed.
+
+$DH_GOAL=../../libdefault.a ../../libfips.a
+$DSA_GOAL=../../libdefault.a ../../libfips.a
+$EC_GOAL=../../libdefault.a ../../libfips.a
+$ECX_GOAL=../../libdefault.a ../../libfips.a
+$KDF_GOAL=../../libdefault.a ../../libfips.a
+$MAC_GOAL=../../libdefault.a ../../libfips.a
+$RSA_GOAL=../../libdefault.a ../../libfips.a
+
+IF[{- !$disabled{dh} -}]
+ SOURCE[$DH_GOAL]=dh_kmgmt.c
+ENDIF
+IF[{- !$disabled{dsa} -}]
+ SOURCE[$DSA_GOAL]=dsa_kmgmt.c
+ENDIF
+IF[{- !$disabled{ec} -}]
+ SOURCE[$EC_GOAL]=ec_kmgmt.c
+ENDIF
+
+IF[{- !$disabled{asm} -}]
+ $ECDEF_s390x=S390X_EC_ASM
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+ IF[$ECASM_{- $target{asm_arch} -}]
+ $ECDEF=$ECDEF_{- $target{asm_arch} -}
+ ENDIF
+ENDIF
+
+IF[{- !$disabled{ec} -}]
+ SOURCE[$ECX_GOAL]=ecx_kmgmt.c
+ DEFINE[$ECX_GOAL]=$ECDEF
+ENDIF
+
+SOURCE[$RSA_GOAL]=rsa_kmgmt.c
+
+SOURCE[$KDF_GOAL]=kdf_legacy_kmgmt.c
+
+SOURCE[$MAC_GOAL]=mac_legacy_kmgmt.c
diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c
new file mode 100644
index 000000000000..9a7dde7c6627
--- /dev/null
+++ b/providers/implementations/keymgmt/dh_kmgmt.c
@@ -0,0 +1,881 @@
+/*
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h> /* strcmp */
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+#include "prov/provider_ctx.h"
+#include "crypto/dh.h"
+#include "internal/sizes.h"
+
+static OSSL_FUNC_keymgmt_new_fn dh_newdata;
+static OSSL_FUNC_keymgmt_free_fn dh_freedata;
+static OSSL_FUNC_keymgmt_gen_init_fn dh_gen_init;
+static OSSL_FUNC_keymgmt_gen_init_fn dhx_gen_init;
+static OSSL_FUNC_keymgmt_gen_set_template_fn dh_gen_set_template;
+static OSSL_FUNC_keymgmt_gen_set_params_fn dh_gen_set_params;
+static OSSL_FUNC_keymgmt_gen_settable_params_fn dh_gen_settable_params;
+static OSSL_FUNC_keymgmt_gen_fn dh_gen;
+static OSSL_FUNC_keymgmt_gen_cleanup_fn dh_gen_cleanup;
+static OSSL_FUNC_keymgmt_load_fn dh_load;
+static OSSL_FUNC_keymgmt_get_params_fn dh_get_params;
+static OSSL_FUNC_keymgmt_gettable_params_fn dh_gettable_params;
+static OSSL_FUNC_keymgmt_set_params_fn dh_set_params;
+static OSSL_FUNC_keymgmt_settable_params_fn dh_settable_params;
+static OSSL_FUNC_keymgmt_has_fn dh_has;
+static OSSL_FUNC_keymgmt_match_fn dh_match;
+static OSSL_FUNC_keymgmt_validate_fn dh_validate;
+static OSSL_FUNC_keymgmt_import_fn dh_import;
+static OSSL_FUNC_keymgmt_import_types_fn dh_import_types;
+static OSSL_FUNC_keymgmt_export_fn dh_export;
+static OSSL_FUNC_keymgmt_export_types_fn dh_export_types;
+static OSSL_FUNC_keymgmt_dup_fn dh_dup;
+
+#define DH_POSSIBLE_SELECTIONS \
+ (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)
+
+struct dh_gen_ctx {
+ OSSL_LIB_CTX *libctx;
+
+ FFC_PARAMS *ffc_params;
+ int selection;
+ /* All these parameters are used for parameter generation only */
+ /* If there is a group name then the remaining parameters are not needed */
+ int group_nid;
+ size_t pbits;
+ size_t qbits;
+ unsigned char *seed; /* optional FIPS186-4 param for testing */
+ size_t seedlen;
+ int gindex; /* optional FIPS186-4 generator index (ignored if -1) */
+ int gen_type; /* see dhtype2id */
+ int generator; /* Used by DH_PARAMGEN_TYPE_GENERATOR in non fips mode only */
+ int pcounter;
+ int hindex;
+ int priv_len;
+
+ char *mdname;
+ char *mdprops;
+ OSSL_CALLBACK *cb;
+ void *cbarg;
+ int dh_type;
+};
+
+static int dh_gen_type_name2id_w_default(const char *name, int type)
+{
+ if (strcmp(name, "default") == 0) {
+#ifdef FIPS_MODULE
+ if (type == DH_FLAG_TYPE_DHX)
+ return DH_PARAMGEN_TYPE_FIPS_186_4;
+
+ return DH_PARAMGEN_TYPE_GROUP;
+#else
+ if (type == DH_FLAG_TYPE_DHX)
+ return DH_PARAMGEN_TYPE_FIPS_186_2;
+
+ return DH_PARAMGEN_TYPE_GENERATOR;
+#endif
+ }
+
+ return ossl_dh_gen_type_name2id(name, type);
+}
+
+static void *dh_newdata(void *provctx)
+{
+ DH *dh = NULL;
+
+ if (ossl_prov_is_running()) {
+ dh = ossl_dh_new_ex(PROV_LIBCTX_OF(provctx));
+ if (dh != NULL) {
+ DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
+ DH_set_flags(dh, DH_FLAG_TYPE_DH);
+ }
+ }
+ return dh;
+}
+
+static void *dhx_newdata(void *provctx)
+{
+ DH *dh = NULL;
+
+ dh = ossl_dh_new_ex(PROV_LIBCTX_OF(provctx));
+ if (dh != NULL) {
+ DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
+ DH_set_flags(dh, DH_FLAG_TYPE_DHX);
+ }
+ return dh;
+}
+
+static void dh_freedata(void *keydata)
+{
+ DH_free(keydata);
+}
+
+static int dh_has(const void *keydata, int selection)
+{
+ const DH *dh = keydata;
+ int ok = 1;
+
+ if (!ossl_prov_is_running() || dh == NULL)
+ return 0;
+ if ((selection & DH_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* the selection is not missing */
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && (DH_get0_pub_key(dh) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && (DH_get0_priv_key(dh) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+ ok = ok && (DH_get0_p(dh) != NULL && DH_get0_g(dh) != NULL);
+ return ok;
+}
+
+static int dh_match(const void *keydata1, const void *keydata2, int selection)
+{
+ const DH *dh1 = keydata1;
+ const DH *dh2 = keydata2;
+ int ok = 1;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ int key_checked = 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ const BIGNUM *pa = DH_get0_pub_key(dh1);
+ const BIGNUM *pb = DH_get0_pub_key(dh2);
+
+ if (pa != NULL && pb != NULL) {
+ ok = ok && BN_cmp(pa, pb) == 0;
+ key_checked = 1;
+ }
+ }
+ if (!key_checked
+ && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ const BIGNUM *pa = DH_get0_priv_key(dh1);
+ const BIGNUM *pb = DH_get0_priv_key(dh2);
+
+ if (pa != NULL && pb != NULL) {
+ ok = ok && BN_cmp(pa, pb) == 0;
+ key_checked = 1;
+ }
+ }
+ ok = ok && key_checked;
+ }
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
+ FFC_PARAMS *dhparams1 = ossl_dh_get0_params((DH *)dh1);
+ FFC_PARAMS *dhparams2 = ossl_dh_get0_params((DH *)dh2);
+
+ ok = ok && ossl_ffc_params_cmp(dhparams1, dhparams2, 1);
+ }
+ return ok;
+}
+
+static int dh_import(void *keydata, int selection, const OSSL_PARAM params[])
+{
+ DH *dh = keydata;
+ int ok = 1;
+
+ if (!ossl_prov_is_running() || dh == NULL)
+ return 0;
+
+ if ((selection & DH_POSSIBLE_SELECTIONS) == 0)
+ return 0;
+
+ /* a key without parameters is meaningless */
+ ok = ok && ossl_dh_params_fromdata(dh, params);
+
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ int include_private =
+ selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
+
+ ok = ok && ossl_dh_key_fromdata(dh, params, include_private);
+ }
+
+ return ok;
+}
+
+static int dh_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
+ void *cbarg)
+{
+ DH *dh = keydata;
+ OSSL_PARAM_BLD *tmpl = NULL;
+ OSSL_PARAM *params = NULL;
+ int ok = 1;
+
+ if (!ossl_prov_is_running() || dh == NULL)
+ return 0;
+
+ tmpl = OSSL_PARAM_BLD_new();
+ if (tmpl == NULL)
+ return 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
+ ok = ok && ossl_dh_params_todata(dh, tmpl, NULL);
+
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ int include_private =
+ selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
+
+ ok = ok && ossl_dh_key_todata(dh, tmpl, NULL, include_private);
+ }
+
+ if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
+ ok = 0;
+ goto err;
+ }
+
+ ok = param_cb(params, cbarg);
+ OSSL_PARAM_free(params);
+err:
+ OSSL_PARAM_BLD_free(tmpl);
+ return ok;
+}
+
+/* IMEXPORT = IMPORT + EXPORT */
+
+# define DH_IMEXPORTABLE_PARAMETERS \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0), \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_Q, NULL, 0), \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0), \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_COFACTOR, NULL, 0), \
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL), \
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL), \
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL), \
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL), \
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0), \
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0)
+# define DH_IMEXPORTABLE_PUBLIC_KEY \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
+# define DH_IMEXPORTABLE_PRIVATE_KEY \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
+static const OSSL_PARAM dh_all_types[] = {
+ DH_IMEXPORTABLE_PARAMETERS,
+ DH_IMEXPORTABLE_PUBLIC_KEY,
+ DH_IMEXPORTABLE_PRIVATE_KEY,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM dh_parameter_types[] = {
+ DH_IMEXPORTABLE_PARAMETERS,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM dh_key_types[] = {
+ DH_IMEXPORTABLE_PUBLIC_KEY,
+ DH_IMEXPORTABLE_PRIVATE_KEY,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *dh_types[] = {
+ NULL, /* Index 0 = none of them */
+ dh_parameter_types, /* Index 1 = parameter types */
+ dh_key_types, /* Index 2 = key types */
+ dh_all_types /* Index 3 = 1 + 2 */
+};
+
+static const OSSL_PARAM *dh_imexport_types(int selection)
+{
+ int type_select = 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
+ type_select += 1;
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+ type_select += 2;
+ return dh_types[type_select];
+}
+
+static const OSSL_PARAM *dh_import_types(int selection)
+{
+ return dh_imexport_types(selection);
+}
+
+static const OSSL_PARAM *dh_export_types(int selection)
+{
+ return dh_imexport_types(selection);
+}
+
+static ossl_inline int dh_get_params(void *key, OSSL_PARAM params[])
+{
+ DH *dh = key;
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
+ && !OSSL_PARAM_set_int(p, DH_bits(dh)))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
+ && !OSSL_PARAM_set_int(p, DH_security_bits(dh)))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
+ && !OSSL_PARAM_set_int(p, DH_size(dh)))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING)
+ return 0;
+ p->return_size = ossl_dh_key2buf(dh, (unsigned char **)&p->data,
+ p->data_size, 0);
+ if (p->return_size == 0)
+ return 0;
+ }
+
+ return ossl_dh_params_todata(dh, NULL, params)
+ && ossl_dh_key_todata(dh, NULL, params, 1);
+}
+
+static const OSSL_PARAM dh_params[] = {
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
+ DH_IMEXPORTABLE_PARAMETERS,
+ DH_IMEXPORTABLE_PUBLIC_KEY,
+ DH_IMEXPORTABLE_PRIVATE_KEY,
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *dh_gettable_params(void *provctx)
+{
+ return dh_params;
+}
+
+static const OSSL_PARAM dh_known_settable_params[] = {
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *dh_settable_params(void *provctx)
+{
+ return dh_known_settable_params;
+}
+
+static int dh_set_params(void *key, const OSSL_PARAM params[])
+{
+ DH *dh = key;
+ const OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
+ if (p != NULL
+ && (p->data_type != OSSL_PARAM_OCTET_STRING
+ || !ossl_dh_buf2key(dh, p->data, p->data_size)))
+ return 0;
+
+ return 1;
+}
+
+static int dh_validate_public(const DH *dh, int checktype)
+{
+ const BIGNUM *pub_key = NULL;
+ int res = 0;
+
+ DH_get0_key(dh, &pub_key, NULL);
+ if (pub_key == NULL)
+ return 0;
+
+ /* The partial test is only valid for named group's with q = (p - 1) / 2 */
+ if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK
+ && ossl_dh_is_named_safe_prime_group(dh))
+ return ossl_dh_check_pub_key_partial(dh, pub_key, &res);
+
+ return DH_check_pub_key(dh, pub_key, &res);
+}
+
+static int dh_validate_private(const DH *dh)
+{
+ int status = 0;
+ const BIGNUM *priv_key = NULL;
+
+ DH_get0_key(dh, NULL, &priv_key);
+ if (priv_key == NULL)
+ return 0;
+ return ossl_dh_check_priv_key(dh, priv_key, &status);;
+}
+
+static int dh_validate(const void *keydata, int selection, int checktype)
+{
+ const DH *dh = keydata;
+ int ok = 1;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if ((selection & DH_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* nothing to validate */
+
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
+ /*
+ * Both of these functions check parameters. DH_check_params_ex()
+ * performs a lightweight check (e.g. it does not check that p is a
+ * safe prime)
+ */
+ if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)
+ ok = ok && DH_check_params_ex(dh);
+ else
+ ok = ok && DH_check_ex(dh);
+ }
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && dh_validate_public(dh, checktype);
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && dh_validate_private(dh);
+
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR)
+ == OSSL_KEYMGMT_SELECT_KEYPAIR)
+ ok = ok && ossl_dh_check_pairwise(dh);
+ return ok;
+}
+
+static void *dh_gen_init_base(void *provctx, int selection,
+ const OSSL_PARAM params[], int type)
+{
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
+ struct dh_gen_ctx *gctx = NULL;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if ((selection & (OSSL_KEYMGMT_SELECT_KEYPAIR
+ | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)) == 0)
+ return NULL;
+
+ if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
+ gctx->selection = selection;
+ gctx->libctx = libctx;
+ gctx->pbits = 2048;
+ gctx->qbits = 224;
+ gctx->mdname = NULL;
+#ifdef FIPS_MODULE
+ gctx->gen_type = (type == DH_FLAG_TYPE_DHX)
+ ? DH_PARAMGEN_TYPE_FIPS_186_4
+ : DH_PARAMGEN_TYPE_GROUP;
+#else
+ gctx->gen_type = (type == DH_FLAG_TYPE_DHX)
+ ? DH_PARAMGEN_TYPE_FIPS_186_2
+ : DH_PARAMGEN_TYPE_GENERATOR;
+#endif
+ gctx->gindex = -1;
+ gctx->hindex = 0;
+ gctx->pcounter = -1;
+ gctx->generator = DH_GENERATOR_2;
+ gctx->dh_type = type;
+ }
+ if (!dh_gen_set_params(gctx, params)) {
+ OPENSSL_free(gctx);
+ gctx = NULL;
+ }
+ return gctx;
+}
+
+static void *dh_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[])
+{
+ return dh_gen_init_base(provctx, selection, params, DH_FLAG_TYPE_DH);
+}
+
+static void *dhx_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[])
+{
+ return dh_gen_init_base(provctx, selection, params, DH_FLAG_TYPE_DHX);
+}
+
+static int dh_gen_set_template(void *genctx, void *templ)
+{
+ struct dh_gen_ctx *gctx = genctx;
+ DH *dh = templ;
+
+ if (!ossl_prov_is_running() || gctx == NULL || dh == NULL)
+ return 0;
+ gctx->ffc_params = ossl_dh_get0_params(dh);
+ return 1;
+}
+
+static int dh_set_gen_seed(struct dh_gen_ctx *gctx, unsigned char *seed,
+ size_t seedlen)
+{
+ OPENSSL_clear_free(gctx->seed, gctx->seedlen);
+ gctx->seed = NULL;
+ gctx->seedlen = 0;
+ if (seed != NULL && seedlen > 0) {
+ gctx->seed = OPENSSL_memdup(seed, seedlen);
+ if (gctx->seed == NULL)
+ return 0;
+ gctx->seedlen = seedlen;
+ }
+ return 1;
+}
+
+static int dh_gen_common_set_params(void *genctx, const OSSL_PARAM params[])
+{
+ struct dh_gen_ctx *gctx = genctx;
+ const OSSL_PARAM *p;
+
+ if (gctx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_TYPE);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING
+ || ((gctx->gen_type =
+ dh_gen_type_name2id_w_default(p->data, gctx->dh_type)) == -1)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
+ if (p != NULL) {
+ const DH_NAMED_GROUP *group = NULL;
+
+ if (p->data_type != OSSL_PARAM_UTF8_STRING
+ || p->data == NULL
+ || (group = ossl_ffc_name_to_dh_named_group(p->data)) == NULL
+ || ((gctx->group_nid =
+ ossl_ffc_named_group_get_uid(group)) == NID_undef)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ }
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PBITS)) != NULL
+ && !OSSL_PARAM_get_size_t(p, &gctx->pbits))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_LEN);
+ if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->priv_len))
+ return 0;
+ return 1;
+}
+
+static const OSSL_PARAM *dh_gen_settable_params(ossl_unused void *genctx,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM dh_gen_settable[] = {
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL),
+ OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_PBITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_GENERATOR, NULL),
+ OSSL_PARAM_END
+ };
+ return dh_gen_settable;
+}
+
+static const OSSL_PARAM *dhx_gen_settable_params(ossl_unused void *genctx,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM dhx_gen_settable[] = {
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL),
+ OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_PBITS, NULL),
+ OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_QBITS, NULL),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST_PROPS, NULL, 0),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL),
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL),
+ OSSL_PARAM_END
+ };
+ return dhx_gen_settable;
+}
+
+static int dhx_gen_set_params(void *genctx, const OSSL_PARAM params[])
+{
+ struct dh_gen_ctx *gctx = genctx;
+ const OSSL_PARAM *p;
+
+ if (!dh_gen_common_set_params(genctx, params))
+ return 0;
+
+ /* Parameters related to fips186-4 and fips186-2 */
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GINDEX);
+ if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->gindex))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PCOUNTER);
+ if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->pcounter))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_H);
+ if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->hindex))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_SEED);
+ if (p != NULL
+ && (p->data_type != OSSL_PARAM_OCTET_STRING
+ || !dh_set_gen_seed(gctx, p->data, p->data_size)))
+ return 0;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_QBITS)) != NULL
+ && !OSSL_PARAM_get_size_t(p, &gctx->qbits))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+ OPENSSL_free(gctx->mdname);
+ gctx->mdname = OPENSSL_strdup(p->data);
+ if (gctx->mdname == NULL)
+ return 0;
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+ OPENSSL_free(gctx->mdprops);
+ gctx->mdprops = OPENSSL_strdup(p->data);
+ if (gctx->mdprops == NULL)
+ return 0;
+ }
+
+ /* Parameters that are not allowed for DHX */
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_GENERATOR);
+ if (p != NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_UNSUPPORTED);
+ return 0;
+ }
+ return 1;
+}
+
+static int dh_gen_set_params(void *genctx, const OSSL_PARAM params[])
+{
+ struct dh_gen_ctx *gctx = genctx;
+ const OSSL_PARAM *p;
+
+ if (!dh_gen_common_set_params(genctx, params))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_GENERATOR);
+ if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->generator))
+ return 0;
+
+ /* Parameters that are not allowed for DH */
+ if (OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GINDEX) != NULL
+ || OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PCOUNTER) != NULL
+ || OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_H) != NULL
+ || OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_SEED) != NULL
+ || OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_QBITS) != NULL
+ || OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST) != NULL
+ || OSSL_PARAM_locate_const(params,
+ OSSL_PKEY_PARAM_FFC_DIGEST_PROPS) != NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ return 1;
+}
+
+static int dh_gencb(int p, int n, BN_GENCB *cb)
+{
+ struct dh_gen_ctx *gctx = BN_GENCB_get_arg(cb);
+ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p);
+ params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n);
+
+ return gctx->cb(params, gctx->cbarg);
+}
+
+static void *dh_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
+{
+ int ret = 0;
+ struct dh_gen_ctx *gctx = genctx;
+ DH *dh = NULL;
+ BN_GENCB *gencb = NULL;
+ FFC_PARAMS *ffc;
+
+ if (!ossl_prov_is_running() || gctx == NULL)
+ return NULL;
+
+ /*
+ * If a group name is selected then the type is group regardless of what the
+ * the user selected. This overrides rather than errors for backwards
+ * compatibility.
+ */
+ if (gctx->group_nid != NID_undef)
+ gctx->gen_type = DH_PARAMGEN_TYPE_GROUP;
+
+ /* For parameter generation - If there is a group name just create it */
+ if (gctx->gen_type == DH_PARAMGEN_TYPE_GROUP
+ && gctx->ffc_params == NULL) {
+ /* Select a named group if there is not one already */
+ if (gctx->group_nid == NID_undef)
+ gctx->group_nid = ossl_dh_get_named_group_uid_from_size(gctx->pbits);
+ if (gctx->group_nid == NID_undef)
+ return NULL;
+ dh = ossl_dh_new_by_nid_ex(gctx->libctx, gctx->group_nid);
+ if (dh == NULL)
+ return NULL;
+ ffc = ossl_dh_get0_params(dh);
+ } else {
+ dh = ossl_dh_new_ex(gctx->libctx);
+ if (dh == NULL)
+ return NULL;
+ ffc = ossl_dh_get0_params(dh);
+
+ /* Copy the template value if one was passed */
+ if (gctx->ffc_params != NULL
+ && !ossl_ffc_params_copy(ffc, gctx->ffc_params))
+ goto end;
+
+ if (!ossl_ffc_params_set_seed(ffc, gctx->seed, gctx->seedlen))
+ goto end;
+ if (gctx->gindex != -1) {
+ ossl_ffc_params_set_gindex(ffc, gctx->gindex);
+ if (gctx->pcounter != -1)
+ ossl_ffc_params_set_pcounter(ffc, gctx->pcounter);
+ } else if (gctx->hindex != 0) {
+ ossl_ffc_params_set_h(ffc, gctx->hindex);
+ }
+ if (gctx->mdname != NULL) {
+ if (!ossl_ffc_set_digest(ffc, gctx->mdname, gctx->mdprops))
+ goto end;
+ }
+ gctx->cb = osslcb;
+ gctx->cbarg = cbarg;
+ gencb = BN_GENCB_new();
+ if (gencb != NULL)
+ BN_GENCB_set(gencb, dh_gencb, genctx);
+
+ if ((gctx->selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
+ /*
+ * NOTE: The old safe prime generator code is not used in fips mode,
+ * (i.e internally it ignores the generator and chooses a named
+ * group based on pbits.
+ */
+ if (gctx->gen_type == DH_PARAMGEN_TYPE_GENERATOR)
+ ret = DH_generate_parameters_ex(dh, gctx->pbits,
+ gctx->generator, gencb);
+ else
+ ret = ossl_dh_generate_ffc_parameters(dh, gctx->gen_type,
+ gctx->pbits, gctx->qbits,
+ gencb);
+ if (ret <= 0)
+ goto end;
+ }
+ }
+
+ if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ if (ffc->p == NULL || ffc->g == NULL)
+ goto end;
+ if (gctx->priv_len > 0)
+ DH_set_length(dh, (long)gctx->priv_len);
+ ossl_ffc_params_enable_flags(ffc, FFC_PARAM_FLAG_VALIDATE_LEGACY,
+ gctx->gen_type == DH_PARAMGEN_TYPE_FIPS_186_2);
+ if (DH_generate_key(dh) <= 0)
+ goto end;
+ }
+ DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
+ DH_set_flags(dh, gctx->dh_type);
+
+ ret = 1;
+end:
+ if (ret <= 0) {
+ DH_free(dh);
+ dh = NULL;
+ }
+ BN_GENCB_free(gencb);
+ return dh;
+}
+
+static void dh_gen_cleanup(void *genctx)
+{
+ struct dh_gen_ctx *gctx = genctx;
+
+ if (gctx == NULL)
+ return;
+
+ OPENSSL_free(gctx->mdname);
+ OPENSSL_free(gctx->mdprops);
+ OPENSSL_clear_free(gctx->seed, gctx->seedlen);
+ OPENSSL_free(gctx);
+}
+
+static void *dh_load(const void *reference, size_t reference_sz)
+{
+ DH *dh = NULL;
+
+ if (ossl_prov_is_running() && reference_sz == sizeof(dh)) {
+ /* The contents of the reference is the address to our object */
+ dh = *(DH **)reference;
+ /* We grabbed, so we detach it */
+ *(DH **)reference = NULL;
+ return dh;
+ }
+ return NULL;
+}
+
+static void *dh_dup(const void *keydata_from, int selection)
+{
+ if (ossl_prov_is_running())
+ return ossl_dh_dup(keydata_from, selection);
+ return NULL;
+}
+
+const OSSL_DISPATCH ossl_dh_keymgmt_functions[] = {
+ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dh_newdata },
+ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dh_gen_init },
+ { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))dh_gen_set_template },
+ { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))dh_gen_set_params },
+ { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
+ (void (*)(void))dh_gen_settable_params },
+ { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))dh_gen },
+ { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))dh_gen_cleanup },
+ { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))dh_load },
+ { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dh_freedata },
+ { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params },
+ { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params },
+ { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))dh_set_params },
+ { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))dh_settable_params },
+ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dh_has },
+ { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dh_match },
+ { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))dh_validate },
+ { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dh_import },
+ { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types },
+ { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export },
+ { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types },
+ { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))dh_dup },
+ { 0, NULL }
+};
+
+/* For any DH key, we use the "DH" algorithms regardless of sub-type. */
+static const char *dhx_query_operation_name(int operation_id)
+{
+ return "DH";
+}
+
+const OSSL_DISPATCH ossl_dhx_keymgmt_functions[] = {
+ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dhx_newdata },
+ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dhx_gen_init },
+ { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))dh_gen_set_template },
+ { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))dhx_gen_set_params },
+ { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
+ (void (*)(void))dhx_gen_settable_params },
+ { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))dh_gen },
+ { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))dh_gen_cleanup },
+ { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))dh_load },
+ { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dh_freedata },
+ { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params },
+ { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params },
+ { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))dh_set_params },
+ { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))dh_settable_params },
+ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dh_has },
+ { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dh_match },
+ { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))dh_validate },
+ { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dh_import },
+ { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types },
+ { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export },
+ { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types },
+ { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
+ (void (*)(void))dhx_query_operation_name },
+ { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))dh_dup },
+ { 0, NULL }
+};
diff --git a/providers/implementations/keymgmt/dsa_kmgmt.c b/providers/implementations/keymgmt/dsa_kmgmt.c
new file mode 100644
index 000000000000..cd8b4410b0db
--- /dev/null
+++ b/providers/implementations/keymgmt/dsa_kmgmt.c
@@ -0,0 +1,677 @@
+/*
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "crypto/dsa.h"
+#include "internal/sizes.h"
+#include "internal/nelem.h"
+#include "internal/param_build_set.h"
+
+static OSSL_FUNC_keymgmt_new_fn dsa_newdata;
+static OSSL_FUNC_keymgmt_free_fn dsa_freedata;
+static OSSL_FUNC_keymgmt_gen_init_fn dsa_gen_init;
+static OSSL_FUNC_keymgmt_gen_set_template_fn dsa_gen_set_template;
+static OSSL_FUNC_keymgmt_gen_set_params_fn dsa_gen_set_params;
+static OSSL_FUNC_keymgmt_gen_settable_params_fn dsa_gen_settable_params;
+static OSSL_FUNC_keymgmt_gen_fn dsa_gen;
+static OSSL_FUNC_keymgmt_gen_cleanup_fn dsa_gen_cleanup;
+static OSSL_FUNC_keymgmt_load_fn dsa_load;
+static OSSL_FUNC_keymgmt_get_params_fn dsa_get_params;
+static OSSL_FUNC_keymgmt_gettable_params_fn dsa_gettable_params;
+static OSSL_FUNC_keymgmt_has_fn dsa_has;
+static OSSL_FUNC_keymgmt_match_fn dsa_match;
+static OSSL_FUNC_keymgmt_validate_fn dsa_validate;
+static OSSL_FUNC_keymgmt_import_fn dsa_import;
+static OSSL_FUNC_keymgmt_import_types_fn dsa_import_types;
+static OSSL_FUNC_keymgmt_export_fn dsa_export;
+static OSSL_FUNC_keymgmt_export_types_fn dsa_export_types;
+static OSSL_FUNC_keymgmt_dup_fn dsa_dup;
+
+#define DSA_DEFAULT_MD "SHA256"
+#define DSA_POSSIBLE_SELECTIONS \
+ (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)
+
+struct dsa_gen_ctx {
+ OSSL_LIB_CTX *libctx;
+
+ FFC_PARAMS *ffc_params;
+ int selection;
+ /* All these parameters are used for parameter generation only */
+ size_t pbits;
+ size_t qbits;
+ unsigned char *seed; /* optional FIPS186-4 param for testing */
+ size_t seedlen;
+ int gindex; /* optional FIPS186-4 generator index (ignored if -1) */
+ int gen_type; /* DSA_PARAMGEN_TYPE_FIPS_186_2 or DSA_PARAMGEN_TYPE_FIPS_186_4 */
+ int pcounter;
+ int hindex;
+ char *mdname;
+ char *mdprops;
+ OSSL_CALLBACK *cb;
+ void *cbarg;
+};
+typedef struct dh_name2id_st{
+ const char *name;
+ int id;
+} DSA_GENTYPE_NAME2ID;
+
+static const DSA_GENTYPE_NAME2ID dsatype2id[]=
+{
+#ifdef FIPS_MODULE
+ { "default", DSA_PARAMGEN_TYPE_FIPS_186_4 },
+#else
+ { "default", DSA_PARAMGEN_TYPE_FIPS_DEFAULT },
+#endif
+ { "fips186_4", DSA_PARAMGEN_TYPE_FIPS_186_4 },
+ { "fips186_2", DSA_PARAMGEN_TYPE_FIPS_186_2 },
+};
+
+static int dsa_gen_type_name2id(const char *name)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(dsatype2id); ++i) {
+ if (OPENSSL_strcasecmp(dsatype2id[i].name, name) == 0)
+ return dsatype2id[i].id;
+ }
+ return -1;
+}
+
+static int dsa_key_todata(DSA *dsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[],
+ int include_private)
+{
+ const BIGNUM *priv = NULL, *pub = NULL;
+
+ if (dsa == NULL)
+ return 0;
+
+ DSA_get0_key(dsa, &pub, &priv);
+ if (include_private
+ && priv != NULL
+ && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PRIV_KEY, priv))
+ return 0;
+ if (pub != NULL
+ && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PUB_KEY, pub))
+ return 0;
+
+ return 1;
+}
+
+static void *dsa_newdata(void *provctx)
+{
+ if (!ossl_prov_is_running())
+ return NULL;
+ return ossl_dsa_new(PROV_LIBCTX_OF(provctx));
+}
+
+static void dsa_freedata(void *keydata)
+{
+ DSA_free(keydata);
+}
+
+static int dsa_has(const void *keydata, int selection)
+{
+ const DSA *dsa = keydata;
+ int ok = 1;
+
+ if (!ossl_prov_is_running() || dsa == NULL)
+ return 0;
+ if ((selection & DSA_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* the selection is not missing */
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && (DSA_get0_pub_key(dsa) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && (DSA_get0_priv_key(dsa) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+ ok = ok && (DSA_get0_p(dsa) != NULL && DSA_get0_g(dsa) != NULL);
+ return ok;
+}
+
+static int dsa_match(const void *keydata1, const void *keydata2, int selection)
+{
+ const DSA *dsa1 = keydata1;
+ const DSA *dsa2 = keydata2;
+ int ok = 1;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ int key_checked = 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ const BIGNUM *pa = DSA_get0_pub_key(dsa1);
+ const BIGNUM *pb = DSA_get0_pub_key(dsa2);
+
+ if (pa != NULL && pb != NULL) {
+ ok = ok && BN_cmp(pa, pb) == 0;
+ key_checked = 1;
+ }
+ }
+ if (!key_checked
+ && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ const BIGNUM *pa = DSA_get0_priv_key(dsa1);
+ const BIGNUM *pb = DSA_get0_priv_key(dsa2);
+
+ if (pa != NULL && pb != NULL) {
+ ok = ok && BN_cmp(pa, pb) == 0;
+ key_checked = 1;
+ }
+ }
+ ok = ok && key_checked;
+ }
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
+ FFC_PARAMS *dsaparams1 = ossl_dsa_get0_params((DSA *)dsa1);
+ FFC_PARAMS *dsaparams2 = ossl_dsa_get0_params((DSA *)dsa2);
+
+ ok = ok && ossl_ffc_params_cmp(dsaparams1, dsaparams2, 1);
+ }
+ return ok;
+}
+
+static int dsa_import(void *keydata, int selection, const OSSL_PARAM params[])
+{
+ DSA *dsa = keydata;
+ int ok = 1;
+
+ if (!ossl_prov_is_running() || dsa == NULL)
+ return 0;
+
+ if ((selection & DSA_POSSIBLE_SELECTIONS) == 0)
+ return 0;
+
+ /* a key without parameters is meaningless */
+ ok = ok && ossl_dsa_ffc_params_fromdata(dsa, params);
+
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ int include_private =
+ selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
+
+ ok = ok && ossl_dsa_key_fromdata(dsa, params, include_private);
+ }
+
+ return ok;
+}
+
+static int dsa_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
+ void *cbarg)
+{
+ DSA *dsa = keydata;
+ OSSL_PARAM_BLD *tmpl;
+ OSSL_PARAM *params = NULL;
+ int ok = 1;
+
+ if (!ossl_prov_is_running() || dsa == NULL)
+ return 0;
+
+ tmpl = OSSL_PARAM_BLD_new();
+ if (tmpl == NULL)
+ return 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
+ ok = ok && ossl_ffc_params_todata(ossl_dsa_get0_params(dsa), tmpl, NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ int include_private =
+ selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
+
+ ok = ok && dsa_key_todata(dsa, tmpl, NULL, include_private);
+ }
+
+ if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
+ ok = 0;
+ goto err;
+ }
+
+ ok = param_cb(params, cbarg);
+ OSSL_PARAM_free(params);
+err:
+ OSSL_PARAM_BLD_free(tmpl);
+ return ok;
+}
+
+/* IMEXPORT = IMPORT + EXPORT */
+
+# define DSA_IMEXPORTABLE_PARAMETERS \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0), \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_Q, NULL, 0), \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0), \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_COFACTOR, NULL, 0), \
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL), \
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL), \
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL), \
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0)
+# define DSA_IMEXPORTABLE_PUBLIC_KEY \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
+# define DSA_IMEXPORTABLE_PRIVATE_KEY \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
+static const OSSL_PARAM dsa_all_types[] = {
+ DSA_IMEXPORTABLE_PARAMETERS,
+ DSA_IMEXPORTABLE_PUBLIC_KEY,
+ DSA_IMEXPORTABLE_PRIVATE_KEY,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM dsa_parameter_types[] = {
+ DSA_IMEXPORTABLE_PARAMETERS,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM dsa_key_types[] = {
+ DSA_IMEXPORTABLE_PUBLIC_KEY,
+ DSA_IMEXPORTABLE_PRIVATE_KEY,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *dsa_types[] = {
+ NULL, /* Index 0 = none of them */
+ dsa_parameter_types, /* Index 1 = parameter types */
+ dsa_key_types, /* Index 2 = key types */
+ dsa_all_types /* Index 3 = 1 + 2 */
+};
+
+static const OSSL_PARAM *dsa_imexport_types(int selection)
+{
+ int type_select = 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
+ type_select += 1;
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+ type_select += 2;
+ return dsa_types[type_select];
+}
+
+static const OSSL_PARAM *dsa_import_types(int selection)
+{
+ return dsa_imexport_types(selection);
+}
+
+static const OSSL_PARAM *dsa_export_types(int selection)
+{
+ return dsa_imexport_types(selection);
+}
+
+static ossl_inline int dsa_get_params(void *key, OSSL_PARAM params[])
+{
+ DSA *dsa = key;
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
+ && !OSSL_PARAM_set_int(p, DSA_bits(dsa)))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
+ && !OSSL_PARAM_set_int(p, DSA_security_bits(dsa)))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
+ && !OSSL_PARAM_set_int(p, DSA_size(dsa)))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
+ && !OSSL_PARAM_set_utf8_string(p, DSA_DEFAULT_MD))
+ return 0;
+ return ossl_ffc_params_todata(ossl_dsa_get0_params(dsa), NULL, params)
+ && dsa_key_todata(dsa, NULL, params, 1);
+}
+
+static const OSSL_PARAM dsa_params[] = {
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
+ DSA_IMEXPORTABLE_PARAMETERS,
+ DSA_IMEXPORTABLE_PUBLIC_KEY,
+ DSA_IMEXPORTABLE_PRIVATE_KEY,
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *dsa_gettable_params(void *provctx)
+{
+ return dsa_params;
+}
+
+static int dsa_validate_domparams(const DSA *dsa, int checktype)
+{
+ int status = 0;
+
+ return ossl_dsa_check_params(dsa, checktype, &status);
+}
+
+static int dsa_validate_public(const DSA *dsa)
+{
+ int status = 0;
+ const BIGNUM *pub_key = NULL;
+
+ DSA_get0_key(dsa, &pub_key, NULL);
+ if (pub_key == NULL)
+ return 0;
+ return ossl_dsa_check_pub_key(dsa, pub_key, &status);
+}
+
+static int dsa_validate_private(const DSA *dsa)
+{
+ int status = 0;
+ const BIGNUM *priv_key = NULL;
+
+ DSA_get0_key(dsa, NULL, &priv_key);
+ if (priv_key == NULL)
+ return 0;
+ return ossl_dsa_check_priv_key(dsa, priv_key, &status);
+}
+
+static int dsa_validate(const void *keydata, int selection, int checktype)
+{
+ const DSA *dsa = keydata;
+ int ok = 1;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if ((selection & DSA_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* nothing to validate */
+
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+ ok = ok && dsa_validate_domparams(dsa, checktype);
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && dsa_validate_public(dsa);
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && dsa_validate_private(dsa);
+
+ /* If the whole key is selected, we do a pairwise validation */
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR)
+ == OSSL_KEYMGMT_SELECT_KEYPAIR)
+ ok = ok && ossl_dsa_check_pairwise(dsa);
+ return ok;
+}
+
+static void *dsa_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[])
+{
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
+ struct dsa_gen_ctx *gctx = NULL;
+
+ if (!ossl_prov_is_running() || (selection & DSA_POSSIBLE_SELECTIONS) == 0)
+ return NULL;
+
+ if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
+ gctx->selection = selection;
+ gctx->libctx = libctx;
+ gctx->pbits = 2048;
+ gctx->qbits = 224;
+#ifdef FIPS_MODULE
+ gctx->gen_type = DSA_PARAMGEN_TYPE_FIPS_186_4;
+#else
+ gctx->gen_type = DSA_PARAMGEN_TYPE_FIPS_DEFAULT;
+#endif
+ gctx->gindex = -1;
+ gctx->pcounter = -1;
+ gctx->hindex = 0;
+ }
+ if (!dsa_gen_set_params(gctx, params)) {
+ OPENSSL_free(gctx);
+ gctx = NULL;
+ }
+ return gctx;
+}
+
+static int dsa_gen_set_template(void *genctx, void *templ)
+{
+ struct dsa_gen_ctx *gctx = genctx;
+ DSA *dsa = templ;
+
+ if (!ossl_prov_is_running() || gctx == NULL || dsa == NULL)
+ return 0;
+ gctx->ffc_params = ossl_dsa_get0_params(dsa);
+ return 1;
+}
+
+static int dsa_set_gen_seed(struct dsa_gen_ctx *gctx, unsigned char *seed,
+ size_t seedlen)
+{
+ OPENSSL_clear_free(gctx->seed, gctx->seedlen);
+ gctx->seed = NULL;
+ gctx->seedlen = 0;
+ if (seed != NULL && seedlen > 0) {
+ gctx->seed = OPENSSL_memdup(seed, seedlen);
+ if (gctx->seed == NULL)
+ return 0;
+ gctx->seedlen = seedlen;
+ }
+ return 1;
+}
+
+static int dsa_gen_set_params(void *genctx, const OSSL_PARAM params[])
+{
+ struct dsa_gen_ctx *gctx = genctx;
+ const OSSL_PARAM *p;
+
+ if (gctx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_TYPE);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING
+ || ((gctx->gen_type = dsa_gen_type_name2id(p->data)) == -1)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GINDEX);
+ if (p != NULL
+ && !OSSL_PARAM_get_int(p, &gctx->gindex))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PCOUNTER);
+ if (p != NULL
+ && !OSSL_PARAM_get_int(p, &gctx->pcounter))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_H);
+ if (p != NULL
+ && !OSSL_PARAM_get_int(p, &gctx->hindex))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_SEED);
+ if (p != NULL
+ && (p->data_type != OSSL_PARAM_OCTET_STRING
+ || !dsa_set_gen_seed(gctx, p->data, p->data_size)))
+ return 0;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PBITS)) != NULL
+ && !OSSL_PARAM_get_size_t(p, &gctx->pbits))
+ return 0;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_QBITS)) != NULL
+ && !OSSL_PARAM_get_size_t(p, &gctx->qbits))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+ OPENSSL_free(gctx->mdname);
+ gctx->mdname = OPENSSL_strdup(p->data);
+ if (gctx->mdname == NULL)
+ return 0;
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+ OPENSSL_free(gctx->mdprops);
+ gctx->mdprops = OPENSSL_strdup(p->data);
+ if (gctx->mdprops == NULL)
+ return 0;
+ }
+ return 1;
+}
+
+static const OSSL_PARAM *dsa_gen_settable_params(ossl_unused void *genctx,
+ ossl_unused void *provctx)
+{
+ static OSSL_PARAM settable[] = {
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE, NULL, 0),
+ OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_PBITS, NULL),
+ OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_QBITS, NULL),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST_PROPS, NULL, 0),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL),
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL),
+ OSSL_PARAM_END
+ };
+ return settable;
+}
+
+static int dsa_gencb(int p, int n, BN_GENCB *cb)
+{
+ struct dsa_gen_ctx *gctx = BN_GENCB_get_arg(cb);
+ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p);
+ params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n);
+
+ return gctx->cb(params, gctx->cbarg);
+}
+
+static void *dsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
+{
+ struct dsa_gen_ctx *gctx = genctx;
+ DSA *dsa = NULL;
+ BN_GENCB *gencb = NULL;
+ int ret = 0;
+ FFC_PARAMS *ffc;
+
+ if (!ossl_prov_is_running() || gctx == NULL)
+ return NULL;
+ dsa = ossl_dsa_new(gctx->libctx);
+ if (dsa == NULL)
+ return NULL;
+
+ if (gctx->gen_type == DSA_PARAMGEN_TYPE_FIPS_DEFAULT)
+ gctx->gen_type = (gctx->pbits >= 2048 ? DSA_PARAMGEN_TYPE_FIPS_186_4 :
+ DSA_PARAMGEN_TYPE_FIPS_186_2);
+
+ gctx->cb = osslcb;
+ gctx->cbarg = cbarg;
+ gencb = BN_GENCB_new();
+ if (gencb != NULL)
+ BN_GENCB_set(gencb, dsa_gencb, genctx);
+
+ ffc = ossl_dsa_get0_params(dsa);
+ /* Copy the template value if one was passed */
+ if (gctx->ffc_params != NULL
+ && !ossl_ffc_params_copy(ffc, gctx->ffc_params))
+ goto end;
+
+ if (gctx->seed != NULL
+ && !ossl_ffc_params_set_seed(ffc, gctx->seed, gctx->seedlen))
+ goto end;
+ if (gctx->gindex != -1) {
+ ossl_ffc_params_set_gindex(ffc, gctx->gindex);
+ if (gctx->pcounter != -1)
+ ossl_ffc_params_set_pcounter(ffc, gctx->pcounter);
+ } else if (gctx->hindex != 0) {
+ ossl_ffc_params_set_h(ffc, gctx->hindex);
+ }
+ if (gctx->mdname != NULL) {
+ if (!ossl_ffc_set_digest(ffc, gctx->mdname, gctx->mdprops))
+ goto end;
+ }
+ if ((gctx->selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
+
+ if (ossl_dsa_generate_ffc_parameters(dsa, gctx->gen_type,
+ gctx->pbits, gctx->qbits,
+ gencb) <= 0)
+ goto end;
+ }
+ ossl_ffc_params_enable_flags(ffc, FFC_PARAM_FLAG_VALIDATE_LEGACY,
+ gctx->gen_type == DSA_PARAMGEN_TYPE_FIPS_186_2);
+ if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ if (ffc->p == NULL
+ || ffc->q == NULL
+ || ffc->g == NULL)
+ goto end;
+ if (DSA_generate_key(dsa) <= 0)
+ goto end;
+ }
+ ret = 1;
+end:
+ if (ret <= 0) {
+ DSA_free(dsa);
+ dsa = NULL;
+ }
+ BN_GENCB_free(gencb);
+ return dsa;
+}
+
+static void dsa_gen_cleanup(void *genctx)
+{
+ struct dsa_gen_ctx *gctx = genctx;
+
+ if (gctx == NULL)
+ return;
+
+ OPENSSL_free(gctx->mdname);
+ OPENSSL_free(gctx->mdprops);
+ OPENSSL_clear_free(gctx->seed, gctx->seedlen);
+ OPENSSL_free(gctx);
+}
+
+static void *dsa_load(const void *reference, size_t reference_sz)
+{
+ DSA *dsa = NULL;
+
+ if (ossl_prov_is_running() && reference_sz == sizeof(dsa)) {
+ /* The contents of the reference is the address to our object */
+ dsa = *(DSA **)reference;
+ /* We grabbed, so we detach it */
+ *(DSA **)reference = NULL;
+ return dsa;
+ }
+ return NULL;
+}
+
+static void *dsa_dup(const void *keydata_from, int selection)
+{
+ if (ossl_prov_is_running())
+ return ossl_dsa_dup(keydata_from, selection);
+ return NULL;
+}
+
+const OSSL_DISPATCH ossl_dsa_keymgmt_functions[] = {
+ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dsa_newdata },
+ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dsa_gen_init },
+ { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))dsa_gen_set_template },
+ { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))dsa_gen_set_params },
+ { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
+ (void (*)(void))dsa_gen_settable_params },
+ { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))dsa_gen },
+ { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))dsa_gen_cleanup },
+ { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))dsa_load },
+ { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dsa_freedata },
+ { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dsa_get_params },
+ { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dsa_gettable_params },
+ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dsa_has },
+ { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dsa_match },
+ { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))dsa_validate },
+ { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dsa_import },
+ { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dsa_import_types },
+ { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dsa_export },
+ { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dsa_export_types },
+ { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))dsa_dup },
+ { 0, NULL }
+};
diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c
new file mode 100644
index 000000000000..3f1dc9e191be
--- /dev/null
+++ b/providers/implementations/keymgmt/ec_kmgmt.c
@@ -0,0 +1,1467 @@
+/*
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * ECDH/ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/objects.h>
+#include <openssl/proverr.h>
+#include "crypto/bn.h"
+#include "crypto/ec.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+#include "prov/provider_ctx.h"
+#include "internal/param_build_set.h"
+
+#ifndef FIPS_MODULE
+# ifndef OPENSSL_NO_SM2
+# include "crypto/sm2.h"
+# endif
+#endif
+
+static OSSL_FUNC_keymgmt_new_fn ec_newdata;
+static OSSL_FUNC_keymgmt_gen_init_fn ec_gen_init;
+static OSSL_FUNC_keymgmt_gen_set_template_fn ec_gen_set_template;
+static OSSL_FUNC_keymgmt_gen_set_params_fn ec_gen_set_params;
+static OSSL_FUNC_keymgmt_gen_settable_params_fn ec_gen_settable_params;
+static OSSL_FUNC_keymgmt_gen_fn ec_gen;
+static OSSL_FUNC_keymgmt_gen_cleanup_fn ec_gen_cleanup;
+static OSSL_FUNC_keymgmt_load_fn ec_load;
+static OSSL_FUNC_keymgmt_free_fn ec_freedata;
+static OSSL_FUNC_keymgmt_get_params_fn ec_get_params;
+static OSSL_FUNC_keymgmt_gettable_params_fn ec_gettable_params;
+static OSSL_FUNC_keymgmt_set_params_fn ec_set_params;
+static OSSL_FUNC_keymgmt_settable_params_fn ec_settable_params;
+static OSSL_FUNC_keymgmt_has_fn ec_has;
+static OSSL_FUNC_keymgmt_match_fn ec_match;
+static OSSL_FUNC_keymgmt_validate_fn ec_validate;
+static OSSL_FUNC_keymgmt_import_fn ec_import;
+static OSSL_FUNC_keymgmt_import_types_fn ec_import_types;
+static OSSL_FUNC_keymgmt_export_fn ec_export;
+static OSSL_FUNC_keymgmt_export_types_fn ec_export_types;
+static OSSL_FUNC_keymgmt_query_operation_name_fn ec_query_operation_name;
+static OSSL_FUNC_keymgmt_dup_fn ec_dup;
+#ifndef FIPS_MODULE
+# ifndef OPENSSL_NO_SM2
+static OSSL_FUNC_keymgmt_new_fn sm2_newdata;
+static OSSL_FUNC_keymgmt_gen_init_fn sm2_gen_init;
+static OSSL_FUNC_keymgmt_gen_fn sm2_gen;
+static OSSL_FUNC_keymgmt_get_params_fn sm2_get_params;
+static OSSL_FUNC_keymgmt_gettable_params_fn sm2_gettable_params;
+static OSSL_FUNC_keymgmt_settable_params_fn sm2_settable_params;
+static OSSL_FUNC_keymgmt_import_fn sm2_import;
+static OSSL_FUNC_keymgmt_query_operation_name_fn sm2_query_operation_name;
+static OSSL_FUNC_keymgmt_validate_fn sm2_validate;
+# endif
+#endif
+
+#define EC_DEFAULT_MD "SHA256"
+#define EC_POSSIBLE_SELECTIONS \
+ (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS)
+#define SM2_DEFAULT_MD "SM3"
+
+static
+const char *ec_query_operation_name(int operation_id)
+{
+ switch (operation_id) {
+ case OSSL_OP_KEYEXCH:
+ return "ECDH";
+ case OSSL_OP_SIGNATURE:
+ return "ECDSA";
+ }
+ return NULL;
+}
+
+#ifndef FIPS_MODULE
+# ifndef OPENSSL_NO_SM2
+static
+const char *sm2_query_operation_name(int operation_id)
+{
+ switch (operation_id) {
+ case OSSL_OP_SIGNATURE:
+ return "SM2";
+ }
+ return NULL;
+}
+# endif
+#endif
+
+/*
+ * Callers of key_to_params MUST make sure that domparams_to_params is also
+ * called!
+ *
+ * This function only exports the bare keypair, domain parameters and other
+ * parameters are exported separately.
+ */
+static ossl_inline
+int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl,
+ OSSL_PARAM params[], int include_private,
+ unsigned char **pub_key)
+{
+ BIGNUM *x = NULL, *y = NULL;
+ const BIGNUM *priv_key = NULL;
+ const EC_POINT *pub_point = NULL;
+ const EC_GROUP *ecg = NULL;
+ size_t pub_key_len = 0;
+ int ret = 0;
+ BN_CTX *bnctx = NULL;
+
+ if (eckey == NULL
+ || (ecg = EC_KEY_get0_group(eckey)) == NULL)
+ return 0;
+
+ priv_key = EC_KEY_get0_private_key(eckey);
+ pub_point = EC_KEY_get0_public_key(eckey);
+
+ if (pub_point != NULL) {
+ OSSL_PARAM *p = NULL, *px = NULL, *py = NULL;
+ /*
+ * EC_POINT_point2buf() can generate random numbers in some
+ * implementations so we need to ensure we use the correct libctx.
+ */
+ bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eckey));
+ if (bnctx == NULL)
+ goto err;
+
+
+ /* If we are doing a get then check first before decoding the point */
+ if (tmpl == NULL) {
+ p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY);
+ px = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_PUB_X);
+ py = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_PUB_Y);
+ }
+
+ if (p != NULL || tmpl != NULL) {
+ /* convert pub_point to a octet string according to the SECG standard */
+ point_conversion_form_t format = EC_KEY_get_conv_form(eckey);
+
+ if ((pub_key_len = EC_POINT_point2buf(ecg, pub_point,
+ format,
+ pub_key, bnctx)) == 0
+ || !ossl_param_build_set_octet_string(tmpl, p,
+ OSSL_PKEY_PARAM_PUB_KEY,
+ *pub_key, pub_key_len))
+ goto err;
+ }
+ if (px != NULL || py != NULL) {
+ if (px != NULL) {
+ x = BN_CTX_get(bnctx);
+ if (x == NULL)
+ goto err;
+ }
+ if (py != NULL) {
+ y = BN_CTX_get(bnctx);
+ if (y == NULL)
+ goto err;
+ }
+
+ if (!EC_POINT_get_affine_coordinates(ecg, pub_point, x, y, bnctx))
+ goto err;
+ if (px != NULL
+ && !ossl_param_build_set_bn(tmpl, px,
+ OSSL_PKEY_PARAM_EC_PUB_X, x))
+ goto err;
+ if (py != NULL
+ && !ossl_param_build_set_bn(tmpl, py,
+ OSSL_PKEY_PARAM_EC_PUB_Y, y))
+ goto err;
+ }
+ }
+
+ if (priv_key != NULL && include_private) {
+ size_t sz;
+ int ecbits;
+
+ /*
+ * Key import/export should never leak the bit length of the secret
+ * scalar in the key.
+ *
+ * For this reason, on export we use padded BIGNUMs with fixed length.
+ *
+ * When importing we also should make sure that, even if short lived,
+ * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
+ * soon as possible, so that any processing of this BIGNUM might opt for
+ * constant time implementations in the backend.
+ *
+ * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
+ * to preallocate the BIGNUM internal buffer to a fixed public size big
+ * enough that operations performed during the processing never trigger
+ * a realloc which would leak the size of the scalar through memory
+ * accesses.
+ *
+ * Fixed Length
+ * ------------
+ *
+ * The order of the large prime subgroup of the curve is our choice for
+ * a fixed public size, as that is generally the upper bound for
+ * generating a private key in EC cryptosystems and should fit all valid
+ * secret scalars.
+ *
+ * For padding on export we just use the bit length of the order
+ * converted to bytes (rounding up).
+ *
+ * For preallocating the BIGNUM storage we look at the number of "words"
+ * required for the internal representation of the order, and we
+ * preallocate 2 extra "words" in case any of the subsequent processing
+ * might temporarily overflow the order length.
+ */
+ ecbits = EC_GROUP_order_bits(ecg);
+ if (ecbits <= 0)
+ goto err;
+ sz = (ecbits + 7 ) / 8;
+
+ if (!ossl_param_build_set_bn_pad(tmpl, params,
+ OSSL_PKEY_PARAM_PRIV_KEY,
+ priv_key, sz))
+ goto err;
+ }
+ ret = 1;
+ err:
+ BN_CTX_free(bnctx);
+ return ret;
+}
+
+static ossl_inline
+int otherparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl,
+ OSSL_PARAM params[])
+{
+ int ecdh_cofactor_mode = 0, group_check = 0;
+ const char *name = NULL;
+ point_conversion_form_t format;
+
+ if (ec == NULL)
+ return 0;
+
+ format = EC_KEY_get_conv_form(ec);
+ name = ossl_ec_pt_format_id2name((int)format);
+ if (name != NULL
+ && !ossl_param_build_set_utf8_string(tmpl, params,
+ OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
+ name))
+ return 0;
+
+ group_check = EC_KEY_get_flags(ec) & EC_FLAG_CHECK_NAMED_GROUP_MASK;
+ name = ossl_ec_check_group_type_id2name(group_check);
+ if (name != NULL
+ && !ossl_param_build_set_utf8_string(tmpl, params,
+ OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE,
+ name))
+ return 0;
+
+ if ((EC_KEY_get_enc_flags(ec) & EC_PKEY_NO_PUBKEY) != 0
+ && !ossl_param_build_set_int(tmpl, params,
+ OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 0))
+ return 0;
+
+ ecdh_cofactor_mode =
+ (EC_KEY_get_flags(ec) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
+ return ossl_param_build_set_int(tmpl, params,
+ OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
+ ecdh_cofactor_mode);
+}
+
+static
+void *ec_newdata(void *provctx)
+{
+ if (!ossl_prov_is_running())
+ return NULL;
+ return EC_KEY_new_ex(PROV_LIBCTX_OF(provctx), NULL);
+}
+
+#ifndef FIPS_MODULE
+# ifndef OPENSSL_NO_SM2
+static
+void *sm2_newdata(void *provctx)
+{
+ if (!ossl_prov_is_running())
+ return NULL;
+ return EC_KEY_new_by_curve_name_ex(PROV_LIBCTX_OF(provctx), NULL, NID_sm2);
+}
+# endif
+#endif
+
+static
+void ec_freedata(void *keydata)
+{
+ EC_KEY_free(keydata);
+}
+
+static
+int ec_has(const void *keydata, int selection)
+{
+ const EC_KEY *ec = keydata;
+ int ok = 1;
+
+ if (!ossl_prov_is_running() || ec == NULL)
+ return 0;
+ if ((selection & EC_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* the selection is not missing */
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && (EC_KEY_get0_public_key(ec) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && (EC_KEY_get0_private_key(ec) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+ ok = ok && (EC_KEY_get0_group(ec) != NULL);
+ /*
+ * We consider OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS to always be
+ * available, so no extra check is needed other than the previous one
+ * against EC_POSSIBLE_SELECTIONS.
+ */
+ return ok;
+}
+
+static int ec_match(const void *keydata1, const void *keydata2, int selection)
+{
+ const EC_KEY *ec1 = keydata1;
+ const EC_KEY *ec2 = keydata2;
+ const EC_GROUP *group_a = EC_KEY_get0_group(ec1);
+ const EC_GROUP *group_b = EC_KEY_get0_group(ec2);
+ BN_CTX *ctx = NULL;
+ int ok = 1;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec1));
+ if (ctx == NULL)
+ return 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+ ok = ok && group_a != NULL && group_b != NULL
+ && EC_GROUP_cmp(group_a, group_b, ctx) == 0;
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ int key_checked = 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ const EC_POINT *pa = EC_KEY_get0_public_key(ec1);
+ const EC_POINT *pb = EC_KEY_get0_public_key(ec2);
+
+ if (pa != NULL && pb != NULL) {
+ ok = ok && EC_POINT_cmp(group_b, pa, pb, ctx) == 0;
+ key_checked = 1;
+ }
+ }
+ if (!key_checked
+ && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ const BIGNUM *pa = EC_KEY_get0_private_key(ec1);
+ const BIGNUM *pb = EC_KEY_get0_private_key(ec2);
+
+ if (pa != NULL && pb != NULL) {
+ ok = ok && BN_cmp(pa, pb) == 0;
+ key_checked = 1;
+ }
+ }
+ ok = ok && key_checked;
+ }
+ BN_CTX_free(ctx);
+ return ok;
+}
+
+static int common_check_sm2(const EC_KEY *ec, int sm2_wanted)
+{
+ const EC_GROUP *ecg = NULL;
+
+ /*
+ * sm2_wanted: import the keys or domparams only on SM2 Curve
+ * !sm2_wanted: import the keys or domparams only not on SM2 Curve
+ */
+ if ((ecg = EC_KEY_get0_group(ec)) == NULL
+ || (sm2_wanted ^ (EC_GROUP_get_curve_name(ecg) == NID_sm2)))
+ return 0;
+ return 1;
+}
+
+static
+int common_import(void *keydata, int selection, const OSSL_PARAM params[],
+ int sm2_wanted)
+{
+ EC_KEY *ec = keydata;
+ int ok = 1;
+
+ if (!ossl_prov_is_running() || ec == NULL)
+ return 0;
+
+ /*
+ * In this implementation, we can export/import only keydata in the
+ * following combinations:
+ * - domain parameters (+optional other params)
+ * - public key with associated domain parameters (+optional other params)
+ * - private key with associated domain parameters and optional public key
+ * (+optional other params)
+ *
+ * This means:
+ * - domain parameters must always be requested
+ * - private key must be requested alongside public key
+ * - other parameters are always optional
+ */
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
+ return 0;
+
+ ok = ok && ossl_ec_group_fromdata(ec, params);
+
+ if (!common_check_sm2(ec, sm2_wanted))
+ return 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ int include_private =
+ selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
+
+ ok = ok && ossl_ec_key_fromdata(ec, params, include_private);
+ }
+ if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
+ ok = ok && ossl_ec_key_otherparams_fromdata(ec, params);
+
+ return ok;
+}
+
+static
+int ec_import(void *keydata, int selection, const OSSL_PARAM params[])
+{
+ return common_import(keydata, selection, params, 0);
+}
+
+#ifndef FIPS_MODULE
+# ifndef OPENSSL_NO_SM2
+static
+int sm2_import(void *keydata, int selection, const OSSL_PARAM params[])
+{
+ return common_import(keydata, selection, params, 1);
+}
+# endif
+#endif
+
+static
+int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
+ void *cbarg)
+{
+ EC_KEY *ec = keydata;
+ OSSL_PARAM_BLD *tmpl = NULL;
+ OSSL_PARAM *params = NULL;
+ unsigned char *pub_key = NULL, *genbuf = NULL;
+ BN_CTX *bnctx = NULL;
+ int ok = 1;
+
+ if (!ossl_prov_is_running() || ec == NULL)
+ return 0;
+
+ /*
+ * In this implementation, we can export/import only keydata in the
+ * following combinations:
+ * - domain parameters (+optional other params)
+ * - public key with associated domain parameters (+optional other params)
+ * - private key with associated public key and domain parameters
+ * (+optional other params)
+ *
+ * This means:
+ * - domain parameters must always be requested
+ * - private key must be requested alongside public key
+ * - other parameters are always optional
+ */
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
+ return 0;
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
+ && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
+ return 0;
+
+ tmpl = OSSL_PARAM_BLD_new();
+ if (tmpl == NULL)
+ return 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
+ bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec));
+ if (bnctx == NULL) {
+ ok = 0;
+ goto end;
+ }
+ BN_CTX_start(bnctx);
+ ok = ok && ossl_ec_group_todata(EC_KEY_get0_group(ec), tmpl, NULL,
+ ossl_ec_key_get_libctx(ec),
+ ossl_ec_key_get0_propq(ec),
+ bnctx, &genbuf);
+ }
+
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ int include_private =
+ selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
+
+ ok = ok && key_to_params(ec, tmpl, NULL, include_private, &pub_key);
+ }
+ if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
+ ok = ok && otherparams_to_params(ec, tmpl, NULL);
+
+ if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
+ ok = 0;
+ goto end;
+ }
+
+ ok = param_cb(params, cbarg);
+ OSSL_PARAM_free(params);
+end:
+ OSSL_PARAM_BLD_free(tmpl);
+ OPENSSL_free(pub_key);
+ OPENSSL_free(genbuf);
+ BN_CTX_end(bnctx);
+ BN_CTX_free(bnctx);
+ return ok;
+}
+
+/* IMEXPORT = IMPORT + EXPORT */
+
+# define EC_IMEXPORTABLE_DOM_PARAMETERS \
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), \
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), \
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),\
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, NULL, 0), \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_P, NULL, 0), \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_A, NULL, 0), \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_B, NULL, 0), \
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0), \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0), \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0), \
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0), \
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL)
+
+# define EC_IMEXPORTABLE_PUBLIC_KEY \
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
+# define EC_IMEXPORTABLE_PRIVATE_KEY \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
+# define EC_IMEXPORTABLE_OTHER_PARAMETERS \
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), \
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL)
+
+/*
+ * Include all the possible combinations of OSSL_PARAM arrays for
+ * ec_imexport_types().
+ *
+ * They are in a separate file as it is ~100 lines of unreadable and
+ * uninteresting machine generated stuff.
+ */
+#include "ec_kmgmt_imexport.inc"
+
+static ossl_inline
+const OSSL_PARAM *ec_imexport_types(int selection)
+{
+ int type_select = 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ type_select += 1;
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ type_select += 2;
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+ type_select += 4;
+ if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
+ type_select += 8;
+ return ec_types[type_select];
+}
+
+static
+const OSSL_PARAM *ec_import_types(int selection)
+{
+ return ec_imexport_types(selection);
+}
+
+static
+const OSSL_PARAM *ec_export_types(int selection)
+{
+ return ec_imexport_types(selection);
+}
+
+static int ec_get_ecm_params(const EC_GROUP *group, OSSL_PARAM params[])
+{
+#ifdef OPENSSL_NO_EC2M
+ return 1;
+#else
+ int ret = 0, m;
+ unsigned int k1 = 0, k2 = 0, k3 = 0;
+ int basis_nid;
+ const char *basis_name = NULL;
+ int fid = EC_GROUP_get_field_type(group);
+
+ if (fid != NID_X9_62_characteristic_two_field)
+ return 1;
+
+ basis_nid = EC_GROUP_get_basis_type(group);
+ if (basis_nid == NID_X9_62_tpBasis)
+ basis_name = SN_X9_62_tpBasis;
+ else if (basis_nid == NID_X9_62_ppBasis)
+ basis_name = SN_X9_62_ppBasis;
+ else
+ goto err;
+
+ m = EC_GROUP_get_degree(group);
+ if (!ossl_param_build_set_int(NULL, params, OSSL_PKEY_PARAM_EC_CHAR2_M, m)
+ || !ossl_param_build_set_utf8_string(NULL, params,
+ OSSL_PKEY_PARAM_EC_CHAR2_TYPE,
+ basis_name))
+ goto err;
+
+ if (basis_nid == NID_X9_62_tpBasis) {
+ if (!EC_GROUP_get_trinomial_basis(group, &k1)
+ || !ossl_param_build_set_int(NULL, params,
+ OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS,
+ (int)k1))
+ goto err;
+ } else {
+ if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3)
+ || !ossl_param_build_set_int(NULL, params,
+ OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, (int)k1)
+ || !ossl_param_build_set_int(NULL, params,
+ OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, (int)k2)
+ || !ossl_param_build_set_int(NULL, params,
+ OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, (int)k3))
+ goto err;
+ }
+ ret = 1;
+err:
+ return ret;
+#endif /* OPENSSL_NO_EC2M */
+}
+
+static
+int common_get_params(void *key, OSSL_PARAM params[], int sm2)
+{
+ int ret = 0;
+ EC_KEY *eck = key;
+ const EC_GROUP *ecg = NULL;
+ OSSL_PARAM *p;
+ unsigned char *pub_key = NULL, *genbuf = NULL;
+ OSSL_LIB_CTX *libctx;
+ const char *propq;
+ BN_CTX *bnctx = NULL;
+
+ ecg = EC_KEY_get0_group(eck);
+ if (ecg == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET);
+ return 0;
+ }
+
+ libctx = ossl_ec_key_get_libctx(eck);
+ propq = ossl_ec_key_get0_propq(eck);
+
+ bnctx = BN_CTX_new_ex(libctx);
+ if (bnctx == NULL)
+ return 0;
+ BN_CTX_start(bnctx);
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
+ && !OSSL_PARAM_set_int(p, ECDSA_size(eck)))
+ goto err;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
+ && !OSSL_PARAM_set_int(p, EC_GROUP_order_bits(ecg)))
+ goto err;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL) {
+ int ecbits, sec_bits;
+
+ ecbits = EC_GROUP_order_bits(ecg);
+
+ /*
+ * The following estimates are based on the values published
+ * in Table 2 of "NIST Special Publication 800-57 Part 1 Revision 4"
+ * at http://dx.doi.org/10.6028/NIST.SP.800-57pt1r4 .
+ *
+ * Note that the above reference explicitly categorizes algorithms in a
+ * discrete set of values {80, 112, 128, 192, 256}, and that it is
+ * relevant only for NIST approved Elliptic Curves, while OpenSSL
+ * applies the same logic also to other curves.
+ *
+ * Classifications produced by other standardazing bodies might differ,
+ * so the results provided for "bits of security" by this provider are
+ * to be considered merely indicative, and it is the users'
+ * responsibility to compare these values against the normative
+ * references that may be relevant for their intent and purposes.
+ */
+ if (ecbits >= 512)
+ sec_bits = 256;
+ else if (ecbits >= 384)
+ sec_bits = 192;
+ else if (ecbits >= 256)
+ sec_bits = 128;
+ else if (ecbits >= 224)
+ sec_bits = 112;
+ else if (ecbits >= 160)
+ sec_bits = 80;
+ else
+ sec_bits = ecbits / 2;
+
+ if (!OSSL_PARAM_set_int(p, sec_bits))
+ goto err;
+ }
+
+ if ((p = OSSL_PARAM_locate(params,
+ OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS))
+ != NULL) {
+ int explicitparams = EC_KEY_decoded_from_explicit_params(eck);
+
+ if (explicitparams < 0
+ || !OSSL_PARAM_set_int(p, explicitparams))
+ goto err;
+ }
+
+ if (!sm2) {
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
+ && !OSSL_PARAM_set_utf8_string(p, EC_DEFAULT_MD))
+ goto err;
+ } else {
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
+ && !OSSL_PARAM_set_utf8_string(p, SM2_DEFAULT_MD))
+ goto err;
+ }
+
+ /* SM2 doesn't support this PARAM */
+ if (!sm2) {
+ p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
+ if (p != NULL) {
+ int ecdh_cofactor_mode = 0;
+
+ ecdh_cofactor_mode =
+ (EC_KEY_get_flags(eck) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
+
+ if (!OSSL_PARAM_set_int(p, ecdh_cofactor_mode))
+ goto err;
+ }
+ }
+ if ((p = OSSL_PARAM_locate(params,
+ OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) {
+ const EC_POINT *ecp = EC_KEY_get0_public_key(key);
+
+ if (ecp == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
+ goto err;
+ }
+ p->return_size = EC_POINT_point2oct(ecg, ecp,
+ POINT_CONVERSION_UNCOMPRESSED,
+ p->data, p->return_size, bnctx);
+ if (p->return_size == 0)
+ goto err;
+ }
+
+ ret = ec_get_ecm_params(ecg, params)
+ && ossl_ec_group_todata(ecg, NULL, params, libctx, propq, bnctx,
+ &genbuf)
+ && key_to_params(eck, NULL, params, 1, &pub_key)
+ && otherparams_to_params(eck, NULL, params);
+err:
+ OPENSSL_free(genbuf);
+ OPENSSL_free(pub_key);
+ BN_CTX_end(bnctx);
+ BN_CTX_free(bnctx);
+ return ret;
+}
+
+static
+int ec_get_params(void *key, OSSL_PARAM params[])
+{
+ return common_get_params(key, params, 0);
+}
+
+#ifndef OPENSSL_NO_EC2M
+# define EC2M_GETTABLE_DOM_PARAMS \
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_M, NULL), \
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_CHAR2_TYPE, NULL, 0), \
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS, NULL), \
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, NULL), \
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, NULL), \
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, NULL),
+#else
+# define EC2M_GETTABLE_DOM_PARAMS
+#endif
+
+static const OSSL_PARAM ec_known_gettable_params[] = {
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL),
+ EC_IMEXPORTABLE_DOM_PARAMETERS,
+ EC2M_GETTABLE_DOM_PARAMS
+ EC_IMEXPORTABLE_PUBLIC_KEY,
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0),
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0),
+ EC_IMEXPORTABLE_PRIVATE_KEY,
+ EC_IMEXPORTABLE_OTHER_PARAMETERS,
+ OSSL_PARAM_END
+};
+
+static
+const OSSL_PARAM *ec_gettable_params(void *provctx)
+{
+ return ec_known_gettable_params;
+}
+
+static const OSSL_PARAM ec_known_settable_params[] = {
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static
+const OSSL_PARAM *ec_settable_params(void *provctx)
+{
+ return ec_known_settable_params;
+}
+
+static
+int ec_set_params(void *key, const OSSL_PARAM params[])
+{
+ EC_KEY *eck = key;
+ const OSSL_PARAM *p;
+
+ if (key == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+
+ if (!ossl_ec_group_set_params((EC_GROUP *)EC_KEY_get0_group(key), params))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
+ if (p != NULL) {
+ BN_CTX *ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(key));
+ int ret = 1;
+
+ if (ctx == NULL
+ || p->data_type != OSSL_PARAM_OCTET_STRING
+ || !EC_KEY_oct2key(key, p->data, p->data_size, ctx))
+ ret = 0;
+ BN_CTX_free(ctx);
+ if (!ret)
+ return 0;
+ }
+
+ return ossl_ec_key_otherparams_fromdata(eck, params);
+}
+
+#ifndef FIPS_MODULE
+# ifndef OPENSSL_NO_SM2
+static
+int sm2_get_params(void *key, OSSL_PARAM params[])
+{
+ return common_get_params(key, params, 1);
+}
+
+static const OSSL_PARAM sm2_known_gettable_params[] = {
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL),
+ EC_IMEXPORTABLE_DOM_PARAMETERS,
+ EC_IMEXPORTABLE_PUBLIC_KEY,
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0),
+ EC_IMEXPORTABLE_PRIVATE_KEY,
+ OSSL_PARAM_END
+};
+
+static
+const OSSL_PARAM *sm2_gettable_params(ossl_unused void *provctx)
+{
+ return sm2_known_gettable_params;
+}
+
+static const OSSL_PARAM sm2_known_settable_params[] = {
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static
+const OSSL_PARAM *sm2_settable_params(ossl_unused void *provctx)
+{
+ return sm2_known_settable_params;
+}
+
+static
+int sm2_validate(const void *keydata, int selection, int checktype)
+{
+ const EC_KEY *eck = keydata;
+ int ok = 1;
+ BN_CTX *ctx = NULL;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if ((selection & EC_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* nothing to validate */
+
+ ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eck));
+ if (ctx == NULL)
+ return 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+ ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)
+ ok = ok && ossl_ec_key_public_check_quick(eck, ctx);
+ else
+ ok = ok && ossl_ec_key_public_check(eck, ctx);
+ }
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && ossl_sm2_key_private_check(eck);
+
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
+ ok = ok && ossl_ec_key_pairwise_check(eck, ctx);
+
+ BN_CTX_free(ctx);
+ return ok;
+}
+# endif
+#endif
+
+static
+int ec_validate(const void *keydata, int selection, int checktype)
+{
+ const EC_KEY *eck = keydata;
+ int ok = 1;
+ BN_CTX *ctx = NULL;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if ((selection & EC_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* nothing to validate */
+
+ ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eck));
+ if (ctx == NULL)
+ return 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
+ int flags = EC_KEY_get_flags(eck);
+
+ if ((flags & EC_FLAG_CHECK_NAMED_GROUP) != 0)
+ ok = ok && EC_GROUP_check_named_curve(EC_KEY_get0_group(eck),
+ (flags & EC_FLAG_CHECK_NAMED_GROUP_NIST) != 0, ctx) > 0;
+ else
+ ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);
+ }
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)
+ ok = ok && ossl_ec_key_public_check_quick(eck, ctx);
+ else
+ ok = ok && ossl_ec_key_public_check(eck, ctx);
+ }
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && ossl_ec_key_private_check(eck);
+
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
+ ok = ok && ossl_ec_key_pairwise_check(eck, ctx);
+
+ BN_CTX_free(ctx);
+ return ok;
+}
+
+struct ec_gen_ctx {
+ OSSL_LIB_CTX *libctx;
+ char *group_name;
+ char *encoding;
+ char *pt_format;
+ char *group_check;
+ char *field_type;
+ BIGNUM *p, *a, *b, *order, *cofactor;
+ unsigned char *gen, *seed;
+ size_t gen_len, seed_len;
+ int selection;
+ int ecdh_mode;
+ EC_GROUP *gen_group;
+};
+
+static void *ec_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[])
+{
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
+ struct ec_gen_ctx *gctx = NULL;
+
+ if (!ossl_prov_is_running() || (selection & (EC_POSSIBLE_SELECTIONS)) == 0)
+ return NULL;
+
+ if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
+ gctx->libctx = libctx;
+ gctx->selection = selection;
+ gctx->ecdh_mode = 0;
+ if (!ec_gen_set_params(gctx, params)) {
+ OPENSSL_free(gctx);
+ gctx = NULL;
+ }
+ }
+ return gctx;
+}
+
+#ifndef FIPS_MODULE
+# ifndef OPENSSL_NO_SM2
+static void *sm2_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[])
+{
+ struct ec_gen_ctx *gctx = ec_gen_init(provctx, selection, params);
+
+ if (gctx != NULL) {
+ if (gctx->group_name != NULL)
+ return gctx;
+ if ((gctx->group_name = OPENSSL_strdup("sm2")) != NULL)
+ return gctx;
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ ec_gen_cleanup(gctx);
+ }
+ return NULL;
+}
+# endif
+#endif
+
+static int ec_gen_set_group(void *genctx, const EC_GROUP *src)
+{
+ struct ec_gen_ctx *gctx = genctx;
+ EC_GROUP *group;
+
+ group = EC_GROUP_dup(src);
+ if (group == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE);
+ return 0;
+ }
+ EC_GROUP_free(gctx->gen_group);
+ gctx->gen_group = group;
+ return 1;
+}
+
+static int ec_gen_set_template(void *genctx, void *templ)
+{
+ struct ec_gen_ctx *gctx = genctx;
+ EC_KEY *ec = templ;
+ const EC_GROUP *ec_group;
+
+ if (!ossl_prov_is_running() || gctx == NULL || ec == NULL)
+ return 0;
+ if ((ec_group = EC_KEY_get0_group(ec)) == NULL)
+ return 0;
+ return ec_gen_set_group(gctx, ec_group);
+}
+
+#define COPY_INT_PARAM(params, key, val) \
+p = OSSL_PARAM_locate_const(params, key); \
+if (p != NULL && !OSSL_PARAM_get_int(p, &val)) \
+ goto err;
+
+#define COPY_UTF8_PARAM(params, key, val) \
+p = OSSL_PARAM_locate_const(params, key); \
+if (p != NULL) { \
+ if (p->data_type != OSSL_PARAM_UTF8_STRING) \
+ goto err; \
+ OPENSSL_free(val); \
+ val = OPENSSL_strdup(p->data); \
+ if (val == NULL) \
+ goto err; \
+}
+
+#define COPY_OCTET_PARAM(params, key, val, len) \
+p = OSSL_PARAM_locate_const(params, key); \
+if (p != NULL) { \
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) \
+ goto err; \
+ OPENSSL_free(val); \
+ len = p->data_size; \
+ val = OPENSSL_memdup(p->data, p->data_size); \
+ if (val == NULL) \
+ goto err; \
+}
+
+#define COPY_BN_PARAM(params, key, bn) \
+p = OSSL_PARAM_locate_const(params, key); \
+if (p != NULL) { \
+ if (bn == NULL) \
+ bn = BN_new(); \
+ if (bn == NULL || !OSSL_PARAM_get_BN(p, &bn)) \
+ goto err; \
+}
+
+static int ec_gen_set_params(void *genctx, const OSSL_PARAM params[])
+{
+ int ret = 0;
+ struct ec_gen_ctx *gctx = genctx;
+ const OSSL_PARAM *p;
+ EC_GROUP *group = NULL;
+
+ COPY_INT_PARAM(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, gctx->ecdh_mode);
+
+ COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_GROUP_NAME, gctx->group_name);
+ COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE, gctx->field_type);
+ COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_ENCODING, gctx->encoding);
+ COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, gctx->pt_format);
+ COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE, gctx->group_check);
+
+ COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_P, gctx->p);
+ COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_A, gctx->a);
+ COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_B, gctx->b);
+ COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_ORDER, gctx->order);
+ COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_COFACTOR, gctx->cofactor);
+
+ COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_EC_SEED, gctx->seed, gctx->seed_len);
+ COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_EC_GENERATOR, gctx->gen,
+ gctx->gen_len);
+
+ ret = 1;
+err:
+ EC_GROUP_free(group);
+ return ret;
+}
+
+static int ec_gen_set_group_from_params(struct ec_gen_ctx *gctx)
+{
+ int ret = 0;
+ OSSL_PARAM_BLD *bld;
+ OSSL_PARAM *params = NULL;
+ EC_GROUP *group = NULL;
+
+ bld = OSSL_PARAM_BLD_new();
+ if (bld == NULL)
+ return 0;
+
+ if (gctx->encoding != NULL
+ && !OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_ENCODING,
+ gctx->encoding, 0))
+ goto err;
+
+ if (gctx->pt_format != NULL
+ && !OSSL_PARAM_BLD_push_utf8_string(bld,
+ OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
+ gctx->pt_format, 0))
+ goto err;
+
+ if (gctx->group_name != NULL) {
+ if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME,
+ gctx->group_name, 0))
+ goto err;
+ /* Ignore any other parameters if there is a group name */
+ goto build;
+ } else if (gctx->field_type != NULL) {
+ if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_FIELD_TYPE,
+ gctx->field_type, 0))
+ goto err;
+ } else {
+ goto err;
+ }
+ if (gctx->p == NULL
+ || gctx->a == NULL
+ || gctx->b == NULL
+ || gctx->order == NULL
+ || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_P, gctx->p)
+ || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_A, gctx->a)
+ || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_B, gctx->b)
+ || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_ORDER, gctx->order))
+ goto err;
+
+ if (gctx->cofactor != NULL
+ && !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_COFACTOR,
+ gctx->cofactor))
+ goto err;
+
+ if (gctx->seed != NULL
+ && !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_SEED,
+ gctx->seed, gctx->seed_len))
+ goto err;
+
+ if (gctx->gen == NULL
+ || !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_GENERATOR,
+ gctx->gen, gctx->gen_len))
+ goto err;
+build:
+ params = OSSL_PARAM_BLD_to_param(bld);
+ if (params == NULL)
+ goto err;
+ group = EC_GROUP_new_from_params(params, gctx->libctx, NULL);
+ if (group == NULL)
+ goto err;
+
+ EC_GROUP_free(gctx->gen_group);
+ gctx->gen_group = group;
+
+ ret = 1;
+err:
+ OSSL_PARAM_free(params);
+ OSSL_PARAM_BLD_free(bld);
+ return ret;
+}
+
+static const OSSL_PARAM *ec_gen_settable_params(ossl_unused void *genctx,
+ ossl_unused void *provctx)
+{
+ static OSSL_PARAM settable[] = {
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, NULL, 0),
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_P, NULL, 0),
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_A, NULL, 0),
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_B, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0),
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0),
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0),
+ OSSL_PARAM_END
+ };
+
+ return settable;
+}
+
+static int ec_gen_assign_group(EC_KEY *ec, EC_GROUP *group)
+{
+ if (group == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET);
+ return 0;
+ }
+ return EC_KEY_set_group(ec, group) > 0;
+}
+
+/*
+ * The callback arguments (osslcb & cbarg) are not used by EC_KEY generation
+ */
+static void *ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
+{
+ struct ec_gen_ctx *gctx = genctx;
+ EC_KEY *ec = NULL;
+ int ret = 0;
+
+ if (!ossl_prov_is_running()
+ || gctx == NULL
+ || (ec = EC_KEY_new_ex(gctx->libctx, NULL)) == NULL)
+ return NULL;
+
+ if (gctx->gen_group == NULL) {
+ if (!ec_gen_set_group_from_params(gctx))
+ goto err;
+ } else {
+ if (gctx->encoding != NULL) {
+ int flags = ossl_ec_encoding_name2id(gctx->encoding);
+
+ if (flags < 0)
+ goto err;
+ EC_GROUP_set_asn1_flag(gctx->gen_group, flags);
+ }
+ if (gctx->pt_format != NULL) {
+ int format = ossl_ec_pt_format_name2id(gctx->pt_format);
+
+ if (format < 0)
+ goto err;
+ EC_GROUP_set_point_conversion_form(gctx->gen_group, format);
+ }
+ }
+
+ /* We must always assign a group, no matter what */
+ ret = ec_gen_assign_group(ec, gctx->gen_group);
+
+ /* Whether you want it or not, you get a keypair, not just one half */
+ if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+ ret = ret && EC_KEY_generate_key(ec);
+
+ if (gctx->ecdh_mode != -1)
+ ret = ret && ossl_ec_set_ecdh_cofactor_mode(ec, gctx->ecdh_mode);
+
+ if (gctx->group_check != NULL)
+ ret = ret && ossl_ec_set_check_group_type_from_name(ec, gctx->group_check);
+ if (ret)
+ return ec;
+err:
+ /* Something went wrong, throw the key away */
+ EC_KEY_free(ec);
+ return NULL;
+}
+
+#ifndef FIPS_MODULE
+# ifndef OPENSSL_NO_SM2
+/*
+ * The callback arguments (osslcb & cbarg) are not used by EC_KEY generation
+ */
+static void *sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
+{
+ struct ec_gen_ctx *gctx = genctx;
+ EC_KEY *ec = NULL;
+ int ret = 1;
+
+ if (gctx == NULL
+ || (ec = EC_KEY_new_ex(gctx->libctx, NULL)) == NULL)
+ return NULL;
+
+ if (gctx->gen_group == NULL) {
+ if (!ec_gen_set_group_from_params(gctx))
+ goto err;
+ } else {
+ if (gctx->encoding) {
+ int flags = ossl_ec_encoding_name2id(gctx->encoding);
+
+ if (flags < 0)
+ goto err;
+ EC_GROUP_set_asn1_flag(gctx->gen_group, flags);
+ }
+ if (gctx->pt_format != NULL) {
+ int format = ossl_ec_pt_format_name2id(gctx->pt_format);
+
+ if (format < 0)
+ goto err;
+ EC_GROUP_set_point_conversion_form(gctx->gen_group, format);
+ }
+ }
+
+ /* We must always assign a group, no matter what */
+ ret = ec_gen_assign_group(ec, gctx->gen_group);
+
+ /* Whether you want it or not, you get a keypair, not just one half */
+ if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+ ret = ret && EC_KEY_generate_key(ec);
+
+ if (ret)
+ return ec;
+err:
+ /* Something went wrong, throw the key away */
+ EC_KEY_free(ec);
+ return NULL;
+}
+# endif
+#endif
+
+static void ec_gen_cleanup(void *genctx)
+{
+ struct ec_gen_ctx *gctx = genctx;
+
+ if (gctx == NULL)
+ return;
+
+ EC_GROUP_free(gctx->gen_group);
+ BN_free(gctx->p);
+ BN_free(gctx->a);
+ BN_free(gctx->b);
+ BN_free(gctx->order);
+ BN_free(gctx->cofactor);
+ OPENSSL_free(gctx->group_name);
+ OPENSSL_free(gctx->field_type);
+ OPENSSL_free(gctx->pt_format);
+ OPENSSL_free(gctx->encoding);
+ OPENSSL_free(gctx->seed);
+ OPENSSL_free(gctx->gen);
+ OPENSSL_free(gctx);
+}
+
+static void *common_load(const void *reference, size_t reference_sz,
+ int sm2_wanted)
+{
+ EC_KEY *ec = NULL;
+
+ if (ossl_prov_is_running() && reference_sz == sizeof(ec)) {
+ /* The contents of the reference is the address to our object */
+ ec = *(EC_KEY **)reference;
+
+ if (!common_check_sm2(ec, sm2_wanted))
+ return NULL;
+
+ /* We grabbed, so we detach it */
+ *(EC_KEY **)reference = NULL;
+ return ec;
+ }
+ return NULL;
+}
+
+static void *ec_load(const void *reference, size_t reference_sz)
+{
+ return common_load(reference, reference_sz, 0);
+}
+
+#ifndef FIPS_MODULE
+# ifndef OPENSSL_NO_SM2
+static void *sm2_load(const void *reference, size_t reference_sz)
+{
+ return common_load(reference, reference_sz, 1);
+}
+# endif
+#endif
+
+static void *ec_dup(const void *keydata_from, int selection)
+{
+ if (ossl_prov_is_running())
+ return ossl_ec_key_dup(keydata_from, selection);
+ return NULL;
+}
+
+const OSSL_DISPATCH ossl_ec_keymgmt_functions[] = {
+ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },
+ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init },
+ { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
+ (void (*)(void))ec_gen_set_template },
+ { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params },
+ { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
+ (void (*)(void))ec_gen_settable_params },
+ { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))ec_gen },
+ { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },
+ { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ec_load },
+ { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
+ { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ec_get_params },
+ { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ec_gettable_params },
+ { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
+ { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))ec_settable_params },
+ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
+ { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
+ { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))ec_validate },
+ { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ec_import },
+ { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
+ { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
+ { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
+ { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
+ (void (*)(void))ec_query_operation_name },
+ { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup },
+ { 0, NULL }
+};
+
+#ifndef FIPS_MODULE
+# ifndef OPENSSL_NO_SM2
+const OSSL_DISPATCH ossl_sm2_keymgmt_functions[] = {
+ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))sm2_newdata },
+ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))sm2_gen_init },
+ { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
+ (void (*)(void))ec_gen_set_template },
+ { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params },
+ { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
+ (void (*)(void))ec_gen_settable_params },
+ { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))sm2_gen },
+ { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },
+ { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))sm2_load },
+ { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
+ { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))sm2_get_params },
+ { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))sm2_gettable_params },
+ { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
+ { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))sm2_settable_params },
+ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
+ { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
+ { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))sm2_validate },
+ { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))sm2_import },
+ { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
+ { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
+ { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
+ { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
+ (void (*)(void))sm2_query_operation_name },
+ { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup },
+ { 0, NULL }
+};
+# endif
+#endif
diff --git a/providers/implementations/keymgmt/ec_kmgmt_imexport.inc b/providers/implementations/keymgmt/ec_kmgmt_imexport.inc
new file mode 100644
index 000000000000..b142e0df0c46
--- /dev/null
+++ b/providers/implementations/keymgmt/ec_kmgmt_imexport.inc
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+*/
+
+/*
+ * This file is meant to be included from ec_kmgmt.c
+ */
+
+static const OSSL_PARAM ec_private_key_types[] = {
+ EC_IMEXPORTABLE_PRIVATE_KEY,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM ec_public_key_types[] = {
+ EC_IMEXPORTABLE_PUBLIC_KEY,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM ec_key_types[] = {
+ EC_IMEXPORTABLE_PRIVATE_KEY,
+ EC_IMEXPORTABLE_PUBLIC_KEY,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM ec_dom_parameters_types[] = {
+ EC_IMEXPORTABLE_DOM_PARAMETERS,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM ec_5_types[] = {
+ EC_IMEXPORTABLE_PRIVATE_KEY,
+ EC_IMEXPORTABLE_DOM_PARAMETERS,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM ec_6_types[] = {
+ EC_IMEXPORTABLE_PUBLIC_KEY,
+ EC_IMEXPORTABLE_DOM_PARAMETERS,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM ec_key_domp_types[] = {
+ EC_IMEXPORTABLE_PRIVATE_KEY,
+ EC_IMEXPORTABLE_PUBLIC_KEY,
+ EC_IMEXPORTABLE_DOM_PARAMETERS,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM ec_other_parameters_types[] = {
+ EC_IMEXPORTABLE_OTHER_PARAMETERS,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM ec_9_types[] = {
+ EC_IMEXPORTABLE_PRIVATE_KEY,
+ EC_IMEXPORTABLE_OTHER_PARAMETERS,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM ec_10_types[] = {
+ EC_IMEXPORTABLE_PUBLIC_KEY,
+ EC_IMEXPORTABLE_OTHER_PARAMETERS,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM ec_11_types[] = {
+ EC_IMEXPORTABLE_PRIVATE_KEY,
+ EC_IMEXPORTABLE_PUBLIC_KEY,
+ EC_IMEXPORTABLE_OTHER_PARAMETERS,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM ec_all_parameters_types[] = {
+ EC_IMEXPORTABLE_DOM_PARAMETERS,
+ EC_IMEXPORTABLE_OTHER_PARAMETERS,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM ec_13_types[] = {
+ EC_IMEXPORTABLE_PRIVATE_KEY,
+ EC_IMEXPORTABLE_DOM_PARAMETERS,
+ EC_IMEXPORTABLE_OTHER_PARAMETERS,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM ec_14_types[] = {
+ EC_IMEXPORTABLE_PUBLIC_KEY,
+ EC_IMEXPORTABLE_DOM_PARAMETERS,
+ EC_IMEXPORTABLE_OTHER_PARAMETERS,
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM ec_all_types[] = {
+ EC_IMEXPORTABLE_PRIVATE_KEY,
+ EC_IMEXPORTABLE_PUBLIC_KEY,
+ EC_IMEXPORTABLE_DOM_PARAMETERS,
+ EC_IMEXPORTABLE_OTHER_PARAMETERS,
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *ec_types[] = {
+ NULL,
+ ec_private_key_types,
+ ec_public_key_types,
+ ec_key_types,
+ ec_dom_parameters_types,
+ ec_5_types,
+ ec_6_types,
+ ec_key_domp_types,
+ ec_other_parameters_types,
+ ec_9_types,
+ ec_10_types,
+ ec_11_types,
+ ec_all_parameters_types,
+ ec_13_types,
+ ec_14_types,
+ ec_all_types
+};
diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c
new file mode 100644
index 000000000000..2a7f867aa56b
--- /dev/null
+++ b/providers/implementations/keymgmt/ecx_kmgmt.c
@@ -0,0 +1,1056 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include "internal/param_build_set.h"
+#include <openssl/param_build.h>
+#include "crypto/ecx.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+#include "prov/provider_ctx.h"
+#ifdef S390X_EC_ASM
+# include "s390x_arch.h"
+# include <openssl/sha.h> /* For SHA512_DIGEST_LENGTH */
+#endif
+
+static OSSL_FUNC_keymgmt_new_fn x25519_new_key;
+static OSSL_FUNC_keymgmt_new_fn x448_new_key;
+static OSSL_FUNC_keymgmt_new_fn ed25519_new_key;
+static OSSL_FUNC_keymgmt_new_fn ed448_new_key;
+static OSSL_FUNC_keymgmt_gen_init_fn x25519_gen_init;
+static OSSL_FUNC_keymgmt_gen_init_fn x448_gen_init;
+static OSSL_FUNC_keymgmt_gen_init_fn ed25519_gen_init;
+static OSSL_FUNC_keymgmt_gen_init_fn ed448_gen_init;
+static OSSL_FUNC_keymgmt_gen_fn x25519_gen;
+static OSSL_FUNC_keymgmt_gen_fn x448_gen;
+static OSSL_FUNC_keymgmt_gen_fn ed25519_gen;
+static OSSL_FUNC_keymgmt_gen_fn ed448_gen;
+static OSSL_FUNC_keymgmt_gen_cleanup_fn ecx_gen_cleanup;
+static OSSL_FUNC_keymgmt_gen_set_params_fn ecx_gen_set_params;
+static OSSL_FUNC_keymgmt_gen_settable_params_fn ecx_gen_settable_params;
+static OSSL_FUNC_keymgmt_load_fn ecx_load;
+static OSSL_FUNC_keymgmt_get_params_fn x25519_get_params;
+static OSSL_FUNC_keymgmt_get_params_fn x448_get_params;
+static OSSL_FUNC_keymgmt_get_params_fn ed25519_get_params;
+static OSSL_FUNC_keymgmt_get_params_fn ed448_get_params;
+static OSSL_FUNC_keymgmt_gettable_params_fn x25519_gettable_params;
+static OSSL_FUNC_keymgmt_gettable_params_fn x448_gettable_params;
+static OSSL_FUNC_keymgmt_gettable_params_fn ed25519_gettable_params;
+static OSSL_FUNC_keymgmt_gettable_params_fn ed448_gettable_params;
+static OSSL_FUNC_keymgmt_set_params_fn x25519_set_params;
+static OSSL_FUNC_keymgmt_set_params_fn x448_set_params;
+static OSSL_FUNC_keymgmt_set_params_fn ed25519_set_params;
+static OSSL_FUNC_keymgmt_set_params_fn ed448_set_params;
+static OSSL_FUNC_keymgmt_settable_params_fn x25519_settable_params;
+static OSSL_FUNC_keymgmt_settable_params_fn x448_settable_params;
+static OSSL_FUNC_keymgmt_settable_params_fn ed25519_settable_params;
+static OSSL_FUNC_keymgmt_settable_params_fn ed448_settable_params;
+static OSSL_FUNC_keymgmt_has_fn ecx_has;
+static OSSL_FUNC_keymgmt_match_fn ecx_match;
+static OSSL_FUNC_keymgmt_validate_fn x25519_validate;
+static OSSL_FUNC_keymgmt_validate_fn x448_validate;
+static OSSL_FUNC_keymgmt_validate_fn ed25519_validate;
+static OSSL_FUNC_keymgmt_validate_fn ed448_validate;
+static OSSL_FUNC_keymgmt_import_fn ecx_import;
+static OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types;
+static OSSL_FUNC_keymgmt_export_fn ecx_export;
+static OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types;
+static OSSL_FUNC_keymgmt_dup_fn ecx_dup;
+
+#define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
+
+struct ecx_gen_ctx {
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+ ECX_KEY_TYPE type;
+ int selection;
+};
+
+#ifdef S390X_EC_ASM
+static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx);
+static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx);
+static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx);
+static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
+#endif
+
+static void *x25519_new_key(void *provctx)
+{
+ if (!ossl_prov_is_running())
+ return 0;
+ return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0,
+ NULL);
+}
+
+static void *x448_new_key(void *provctx)
+{
+ if (!ossl_prov_is_running())
+ return 0;
+ return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X448, 0,
+ NULL);
+}
+
+static void *ed25519_new_key(void *provctx)
+{
+ if (!ossl_prov_is_running())
+ return 0;
+ return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED25519, 0,
+ NULL);
+}
+
+static void *ed448_new_key(void *provctx)
+{
+ if (!ossl_prov_is_running())
+ return 0;
+ return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED448, 0,
+ NULL);
+}
+
+static int ecx_has(const void *keydata, int selection)
+{
+ const ECX_KEY *key = keydata;
+ int ok = 0;
+
+ if (ossl_prov_is_running() && key != NULL) {
+ /*
+ * ECX keys always have all the parameters they need (i.e. none).
+ * Therefore we always return with 1, if asked about parameters.
+ */
+ ok = 1;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && key->haspubkey;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && key->privkey != NULL;
+ }
+ return ok;
+}
+
+static int ecx_match(const void *keydata1, const void *keydata2, int selection)
+{
+ const ECX_KEY *key1 = keydata1;
+ const ECX_KEY *key2 = keydata2;
+ int ok = 1;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+ ok = ok && key1->type == key2->type;
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ int key_checked = 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ const unsigned char *pa = key1->haspubkey ? key1->pubkey : NULL;
+ const unsigned char *pb = key2->haspubkey ? key2->pubkey : NULL;
+ size_t pal = key1->keylen;
+ size_t pbl = key2->keylen;
+
+ if (pa != NULL && pb != NULL) {
+ ok = ok
+ && key1->type == key2->type
+ && pal == pbl
+ && CRYPTO_memcmp(pa, pb, pal) == 0;
+ key_checked = 1;
+ }
+ }
+ if (!key_checked
+ && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ const unsigned char *pa = key1->privkey;
+ const unsigned char *pb = key2->privkey;
+ size_t pal = key1->keylen;
+ size_t pbl = key2->keylen;
+
+ if (pa != NULL && pb != NULL) {
+ ok = ok
+ && key1->type == key2->type
+ && pal == pbl
+ && CRYPTO_memcmp(pa, pb, pal) == 0;
+ key_checked = 1;
+ }
+ }
+ ok = ok && key_checked;
+ }
+ return ok;
+}
+
+static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
+{
+ ECX_KEY *key = keydata;
+ int ok = 1;
+ int include_private;
+
+ if (!ossl_prov_is_running() || key == NULL)
+ return 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
+ return 0;
+
+ include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
+ ok = ok && ossl_ecx_key_fromdata(key, params, include_private);
+
+ return ok;
+}
+
+static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
+ OSSL_PARAM params[], int include_private)
+{
+ if (key == NULL)
+ return 0;
+
+ if (!ossl_param_build_set_octet_string(tmpl, params,
+ OSSL_PKEY_PARAM_PUB_KEY,
+ key->pubkey, key->keylen))
+ return 0;
+
+ if (include_private
+ && key->privkey != NULL
+ && !ossl_param_build_set_octet_string(tmpl, params,
+ OSSL_PKEY_PARAM_PRIV_KEY,
+ key->privkey, key->keylen))
+ return 0;
+
+ return 1;
+}
+
+static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
+ void *cbarg)
+{
+ ECX_KEY *key = keydata;
+ OSSL_PARAM_BLD *tmpl;
+ OSSL_PARAM *params = NULL;
+ int ret = 0;
+
+ if (!ossl_prov_is_running() || key == NULL)
+ return 0;
+
+ tmpl = OSSL_PARAM_BLD_new();
+ if (tmpl == NULL)
+ return 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
+
+ if (!key_to_params(key, tmpl, NULL, include_private))
+ goto err;
+ }
+
+ params = OSSL_PARAM_BLD_to_param(tmpl);
+ if (params == NULL)
+ goto err;
+
+ ret = param_cb(params, cbarg);
+ OSSL_PARAM_free(params);
+err:
+ OSSL_PARAM_BLD_free(tmpl);
+ return ret;
+}
+
+#define ECX_KEY_TYPES() \
+OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \
+OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
+
+static const OSSL_PARAM ecx_key_types[] = {
+ ECX_KEY_TYPES(),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *ecx_imexport_types(int selection)
+{
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+ return ecx_key_types;
+ return NULL;
+}
+
+static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
+ int size)
+{
+ ECX_KEY *ecx = key;
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
+ && !OSSL_PARAM_set_int(p, bits))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
+ && !OSSL_PARAM_set_int(p, secbits))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
+ && !OSSL_PARAM_set_int(p, size))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL
+ && (ecx->type == ECX_KEY_TYPE_X25519
+ || ecx->type == ECX_KEY_TYPE_X448)) {
+ if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen))
+ return 0;
+ }
+
+ return key_to_params(ecx, NULL, params, 1);
+}
+
+static int ed_get_params(void *key, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params,
+ OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL
+ && !OSSL_PARAM_set_utf8_string(p, ""))
+ return 0;
+ return 1;
+}
+
+static int x25519_get_params(void *key, OSSL_PARAM params[])
+{
+ return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
+ X25519_KEYLEN);
+}
+
+static int x448_get_params(void *key, OSSL_PARAM params[])
+{
+ return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
+ X448_KEYLEN);
+}
+
+static int ed25519_get_params(void *key, OSSL_PARAM params[])
+{
+ return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
+ ED25519_SIGSIZE)
+ && ed_get_params(key, params);
+}
+
+static int ed448_get_params(void *key, OSSL_PARAM params[])
+{
+ return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
+ ED448_SIGSIZE)
+ && ed_get_params(key, params);
+}
+
+static const OSSL_PARAM ecx_gettable_params[] = {
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
+ ECX_KEY_TYPES(),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM ed_gettable_params[] = {
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
+ ECX_KEY_TYPES(),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *x25519_gettable_params(void *provctx)
+{
+ return ecx_gettable_params;
+}
+
+static const OSSL_PARAM *x448_gettable_params(void *provctx)
+{
+ return ecx_gettable_params;
+}
+
+static const OSSL_PARAM *ed25519_gettable_params(void *provctx)
+{
+ return ed_gettable_params;
+}
+
+static const OSSL_PARAM *ed448_gettable_params(void *provctx)
+{
+ return ed_gettable_params;
+}
+
+static int set_property_query(ECX_KEY *ecxkey, const char *propq)
+{
+ OPENSSL_free(ecxkey->propq);
+ ecxkey->propq = NULL;
+ if (propq != NULL) {
+ ecxkey->propq = OPENSSL_strdup(propq);
+ if (ecxkey->propq == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int ecx_set_params(void *key, const OSSL_PARAM params[])
+{
+ ECX_KEY *ecxkey = key;
+ const OSSL_PARAM *p;
+
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
+ if (p != NULL) {
+ void *buf = ecxkey->pubkey;
+
+ if (p->data_size != ecxkey->keylen
+ || !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey),
+ NULL))
+ return 0;
+ OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
+ ecxkey->privkey = NULL;
+ ecxkey->haspubkey = 1;
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING
+ || !set_property_query(ecxkey, p->data))
+ return 0;
+ }
+
+ return 1;
+}
+
+static int x25519_set_params(void *key, const OSSL_PARAM params[])
+{
+ return ecx_set_params(key, params);
+}
+
+static int x448_set_params(void *key, const OSSL_PARAM params[])
+{
+ return ecx_set_params(key, params);
+}
+
+static int ed25519_set_params(void *key, const OSSL_PARAM params[])
+{
+ return 1;
+}
+
+static int ed448_set_params(void *key, const OSSL_PARAM params[])
+{
+ return 1;
+}
+
+static const OSSL_PARAM ecx_settable_params[] = {
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM ed_settable_params[] = {
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *x25519_settable_params(void *provctx)
+{
+ return ecx_settable_params;
+}
+
+static const OSSL_PARAM *x448_settable_params(void *provctx)
+{
+ return ecx_settable_params;
+}
+
+static const OSSL_PARAM *ed25519_settable_params(void *provctx)
+{
+ return ed_settable_params;
+}
+
+static const OSSL_PARAM *ed448_settable_params(void *provctx)
+{
+ return ed_settable_params;
+}
+
+static void *ecx_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[], ECX_KEY_TYPE type)
+{
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
+ struct ecx_gen_ctx *gctx = NULL;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
+ gctx->libctx = libctx;
+ gctx->type = type;
+ gctx->selection = selection;
+ }
+ if (!ecx_gen_set_params(gctx, params)) {
+ OPENSSL_free(gctx);
+ gctx = NULL;
+ }
+ return gctx;
+}
+
+static void *x25519_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[])
+{
+ return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519);
+}
+
+static void *x448_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[])
+{
+ return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448);
+}
+
+static void *ed25519_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[])
+{
+ return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED25519);
+}
+
+static void *ed448_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[])
+{
+ return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED448);
+}
+
+static int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[])
+{
+ struct ecx_gen_ctx *gctx = genctx;
+ const OSSL_PARAM *p;
+
+ if (gctx == NULL)
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
+ if (p != NULL) {
+ const char *groupname = NULL;
+
+ /*
+ * We optionally allow setting a group name - but each algorithm only
+ * support one such name, so all we do is verify that it is the one we
+ * expected.
+ */
+ switch (gctx->type) {
+ case ECX_KEY_TYPE_X25519:
+ groupname = "x25519";
+ break;
+ case ECX_KEY_TYPE_X448:
+ groupname = "x448";
+ break;
+ default:
+ /* We only support this for key exchange at the moment */
+ break;
+ }
+ if (p->data_type != OSSL_PARAM_UTF8_STRING
+ || groupname == NULL
+ || OPENSSL_strcasecmp(p->data, groupname) != 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+ OPENSSL_free(gctx->propq);
+ gctx->propq = OPENSSL_strdup(p->data);
+ if (gctx->propq == NULL)
+ return 0;
+ }
+
+ return 1;
+}
+
+static const OSSL_PARAM *ecx_gen_settable_params(ossl_unused void *genctx,
+ ossl_unused void *provctx)
+{
+ static OSSL_PARAM settable[] = {
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_END
+ };
+ return settable;
+}
+
+static void *ecx_gen(struct ecx_gen_ctx *gctx)
+{
+ ECX_KEY *key;
+ unsigned char *privkey;
+
+ if (gctx == NULL)
+ return NULL;
+ if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
+ gctx->propq)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ /* If we're doing parameter generation then we just return a blank key */
+ if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
+ return key;
+
+ if ((privkey = ossl_ecx_key_allocate_privkey(key)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
+ goto err;
+ switch (gctx->type) {
+ case ECX_KEY_TYPE_X25519:
+ privkey[0] &= 248;
+ privkey[X25519_KEYLEN - 1] &= 127;
+ privkey[X25519_KEYLEN - 1] |= 64;
+ ossl_x25519_public_from_private(key->pubkey, privkey);
+ break;
+ case ECX_KEY_TYPE_X448:
+ privkey[0] &= 252;
+ privkey[X448_KEYLEN - 1] |= 128;
+ ossl_x448_public_from_private(key->pubkey, privkey);
+ break;
+ case ECX_KEY_TYPE_ED25519:
+ if (!ossl_ed25519_public_from_private(gctx->libctx, key->pubkey, privkey,
+ gctx->propq))
+ goto err;
+ break;
+ case ECX_KEY_TYPE_ED448:
+ if (!ossl_ed448_public_from_private(gctx->libctx, key->pubkey, privkey,
+ gctx->propq))
+ goto err;
+ break;
+ }
+ key->haspubkey = 1;
+ return key;
+err:
+ ossl_ecx_key_free(key);
+ return NULL;
+}
+
+static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
+{
+ struct ecx_gen_ctx *gctx = genctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+#ifdef S390X_EC_ASM
+ if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
+ return s390x_ecx_keygen25519(gctx);
+#endif
+ return ecx_gen(gctx);
+}
+
+static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
+{
+ struct ecx_gen_ctx *gctx = genctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+#ifdef S390X_EC_ASM
+ if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
+ return s390x_ecx_keygen448(gctx);
+#endif
+ return ecx_gen(gctx);
+}
+
+static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
+{
+ struct ecx_gen_ctx *gctx = genctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+#ifdef S390X_EC_ASM
+ if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
+ && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
+ && OPENSSL_s390xcap_P.kdsa[0]
+ & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
+ return s390x_ecd_keygen25519(gctx);
+#endif
+ return ecx_gen(gctx);
+}
+
+static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
+{
+ struct ecx_gen_ctx *gctx = genctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+#ifdef S390X_EC_ASM
+ if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
+ && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
+ && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
+ return s390x_ecd_keygen448(gctx);
+#endif
+ return ecx_gen(gctx);
+}
+
+static void ecx_gen_cleanup(void *genctx)
+{
+ struct ecx_gen_ctx *gctx = genctx;
+
+ OPENSSL_free(gctx->propq);
+ OPENSSL_free(gctx);
+}
+
+void *ecx_load(const void *reference, size_t reference_sz)
+{
+ ECX_KEY *key = NULL;
+
+ if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
+ /* The contents of the reference is the address to our object */
+ key = *(ECX_KEY **)reference;
+ /* We grabbed, so we detach it */
+ *(ECX_KEY **)reference = NULL;
+ return key;
+ }
+ return NULL;
+}
+
+static void *ecx_dup(const void *keydata_from, int selection)
+{
+ if (ossl_prov_is_running())
+ return ossl_ecx_key_dup(keydata_from, selection);
+ return NULL;
+}
+
+static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
+{
+ uint8_t pub[64];
+
+ switch (type) {
+ case ECX_KEY_TYPE_X25519:
+ ossl_x25519_public_from_private(pub, ecx->privkey);
+ break;
+ case ECX_KEY_TYPE_X448:
+ ossl_x448_public_from_private(pub, ecx->privkey);
+ break;
+ case ECX_KEY_TYPE_ED25519:
+ if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
+ ecx->propq))
+ return 0;
+ break;
+ case ECX_KEY_TYPE_ED448:
+ if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
+ ecx->propq))
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+ return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
+}
+
+static int ecx_validate(const void *keydata, int selection, int type, size_t keylen)
+{
+ const ECX_KEY *ecx = keydata;
+ int ok = keylen == ecx->keylen;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* nothing to validate */
+
+ if (!ok) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
+ return 0;
+ }
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && ecx->haspubkey;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && ecx->privkey != NULL;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
+ ok = ok && ecx_key_pairwise_check(ecx, type);
+
+ return ok;
+}
+
+static int x25519_validate(const void *keydata, int selection, int checktype)
+{
+ return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
+}
+
+static int x448_validate(const void *keydata, int selection, int checktype)
+{
+ return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
+}
+
+static int ed25519_validate(const void *keydata, int selection, int checktype)
+{
+ return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
+}
+
+static int ed448_validate(const void *keydata, int selection, int checktype)
+{
+ return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
+}
+
+#define MAKE_KEYMGMT_FUNCTIONS(alg) \
+ const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = { \
+ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
+ { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ossl_ecx_key_free }, \
+ { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
+ { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
+ { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))alg##_set_params }, \
+ { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))alg##_settable_params }, \
+ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
+ { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \
+ { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate }, \
+ { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
+ { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
+ { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
+ { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
+ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
+ { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params }, \
+ { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, \
+ (void (*)(void))ecx_gen_settable_params }, \
+ { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
+ { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
+ { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \
+ { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ecx_dup }, \
+ { 0, NULL } \
+ };
+
+MAKE_KEYMGMT_FUNCTIONS(x25519)
+MAKE_KEYMGMT_FUNCTIONS(x448)
+MAKE_KEYMGMT_FUNCTIONS(ed25519)
+MAKE_KEYMGMT_FUNCTIONS(ed448)
+
+#ifdef S390X_EC_ASM
+# include "s390x_arch.h"
+
+static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
+{
+ static const unsigned char generator[] = {
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1,
+ gctx->propq);
+ unsigned char *privkey = NULL, *pubkey;
+
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* If we're doing parameter generation then we just return a blank key */
+ if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
+ return key;
+
+ pubkey = key->pubkey;
+
+ privkey = ossl_ecx_key_allocate_privkey(key);
+ if (privkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
+ goto err;
+
+ privkey[0] &= 248;
+ privkey[31] &= 127;
+ privkey[31] |= 64;
+
+ if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
+ goto err;
+ key->haspubkey = 1;
+ return key;
+ err:
+ ossl_ecx_key_free(key);
+ return NULL;
+}
+
+static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
+{
+ static const unsigned char generator[] = {
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1,
+ gctx->propq);
+ unsigned char *privkey = NULL, *pubkey;
+
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* If we're doing parameter generation then we just return a blank key */
+ if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
+ return key;
+
+ pubkey = key->pubkey;
+
+ privkey = ossl_ecx_key_allocate_privkey(key);
+ if (privkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
+ goto err;
+
+ privkey[0] &= 252;
+ privkey[55] |= 128;
+
+ if (s390x_x448_mul(pubkey, generator, privkey) != 1)
+ goto err;
+ key->haspubkey = 1;
+ return key;
+ err:
+ ossl_ecx_key_free(key);
+ return NULL;
+}
+
+static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
+{
+ static const unsigned char generator_x[] = {
+ 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
+ 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
+ 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
+ };
+ static const unsigned char generator_y[] = {
+ 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ };
+ unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
+ ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1,
+ gctx->propq);
+ unsigned char *privkey = NULL, *pubkey;
+ unsigned int sz;
+ EVP_MD *sha = NULL;
+ int j;
+
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* If we're doing parameter generation then we just return a blank key */
+ if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
+ return key;
+
+ pubkey = key->pubkey;
+
+ privkey = ossl_ecx_key_allocate_privkey(key);
+ if (privkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
+ goto err;
+
+ sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq);
+ if (sha == NULL)
+ goto err;
+ j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
+ EVP_MD_free(sha);
+ if (!j)
+ goto err;
+
+ buff[0] &= 248;
+ buff[31] &= 63;
+ buff[31] |= 64;
+
+ if (s390x_ed25519_mul(x_dst, pubkey,
+ generator_x, generator_y, buff) != 1)
+ goto err;
+
+ pubkey[31] |= ((x_dst[0] & 0x01) << 7);
+ key->haspubkey = 1;
+ return key;
+ err:
+ ossl_ecx_key_free(key);
+ return NULL;
+}
+
+static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
+{
+ static const unsigned char generator_x[] = {
+ 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
+ 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
+ 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
+ 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
+ 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
+ };
+ static const unsigned char generator_y[] = {
+ 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
+ 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
+ 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
+ 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
+ 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
+ };
+ unsigned char x_dst[57], buff[114];
+ ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1,
+ gctx->propq);
+ unsigned char *privkey = NULL, *pubkey;
+ EVP_MD_CTX *hashctx = NULL;
+ EVP_MD *shake = NULL;
+
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* If we're doing parameter generation then we just return a blank key */
+ if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
+ return key;
+
+ pubkey = key->pubkey;
+
+ privkey = ossl_ecx_key_allocate_privkey(key);
+ if (privkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq);
+ if (shake == NULL)
+ goto err;
+ if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
+ goto err;
+
+ hashctx = EVP_MD_CTX_new();
+ if (hashctx == NULL)
+ goto err;
+ if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
+ goto err;
+ if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
+ goto err;
+ if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
+ goto err;
+
+ buff[0] &= -4;
+ buff[55] |= 0x80;
+ buff[56] = 0;
+
+ if (s390x_ed448_mul(x_dst, pubkey,
+ generator_x, generator_y, buff) != 1)
+ goto err;
+
+ pubkey[56] |= ((x_dst[0] & 0x01) << 7);
+ EVP_MD_CTX_free(hashctx);
+ EVP_MD_free(shake);
+ key->haspubkey = 1;
+ return key;
+ err:
+ ossl_ecx_key_free(key);
+ EVP_MD_CTX_free(hashctx);
+ EVP_MD_free(shake);
+ return NULL;
+}
+#endif
diff --git a/providers/implementations/keymgmt/kdf_legacy_kmgmt.c b/providers/implementations/keymgmt/kdf_legacy_kmgmt.c
new file mode 100644
index 000000000000..0b301c333b09
--- /dev/null
+++ b/providers/implementations/keymgmt/kdf_legacy_kmgmt.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This implemments a dummy key manager for legacy KDFs that still support the
+ * old way of performing a KDF via EVP_PKEY_derive(). New KDFs should not be
+ * implemented this way. In reality there is no key data for such KDFs, so this
+ * key manager does very little.
+ */
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/err.h>
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+#include "prov/provider_ctx.h"
+#include "prov/kdfexchange.h"
+
+static OSSL_FUNC_keymgmt_new_fn kdf_newdata;
+static OSSL_FUNC_keymgmt_free_fn kdf_freedata;
+static OSSL_FUNC_keymgmt_has_fn kdf_has;
+
+KDF_DATA *ossl_kdf_data_new(void *provctx)
+{
+ KDF_DATA *kdfdata;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ kdfdata = OPENSSL_zalloc(sizeof(*kdfdata));
+ if (kdfdata == NULL)
+ return NULL;
+
+ kdfdata->lock = CRYPTO_THREAD_lock_new();
+ if (kdfdata->lock == NULL) {
+ OPENSSL_free(kdfdata);
+ return NULL;
+ }
+ kdfdata->libctx = PROV_LIBCTX_OF(provctx);
+ kdfdata->refcnt = 1;
+
+ return kdfdata;
+}
+
+void ossl_kdf_data_free(KDF_DATA *kdfdata)
+{
+ int ref = 0;
+
+ if (kdfdata == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&kdfdata->refcnt, &ref, kdfdata->lock);
+ if (ref > 0)
+ return;
+
+ CRYPTO_THREAD_lock_free(kdfdata->lock);
+ OPENSSL_free(kdfdata);
+}
+
+int ossl_kdf_data_up_ref(KDF_DATA *kdfdata)
+{
+ int ref = 0;
+
+ /* This is effectively doing a new operation on the KDF_DATA and should be
+ * adequately guarded again modules' error states. However, both current
+ * calls here are guarded propery in exchange/kdf_exch.c. Thus, it
+ * could be removed here. The concern is that something in the future
+ * might call this function without adequate guards. It's a cheap call,
+ * it seems best to leave it even though it is currently redundant.
+ */
+ if (!ossl_prov_is_running())
+ return 0;
+
+ CRYPTO_UP_REF(&kdfdata->refcnt, &ref, kdfdata->lock);
+ return 1;
+}
+
+static void *kdf_newdata(void *provctx)
+{
+ return ossl_kdf_data_new(provctx);
+}
+
+static void kdf_freedata(void *kdfdata)
+{
+ ossl_kdf_data_free(kdfdata);
+}
+
+static int kdf_has(const void *keydata, int selection)
+{
+ return 1; /* nothing is missing */
+}
+
+const OSSL_DISPATCH ossl_kdf_keymgmt_functions[] = {
+ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))kdf_newdata },
+ { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))kdf_freedata },
+ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))kdf_has },
+ { 0, NULL }
+};
diff --git a/providers/implementations/keymgmt/mac_legacy_kmgmt.c b/providers/implementations/keymgmt/mac_legacy_kmgmt.c
new file mode 100644
index 000000000000..c934ff164094
--- /dev/null
+++ b/providers/implementations/keymgmt/mac_legacy_kmgmt.c
@@ -0,0 +1,575 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include <string.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/proverr.h>
+#include <openssl/param_build.h>
+#ifndef FIPS_MODULE
+# include <openssl/engine.h>
+#endif
+#include "internal/param_build_set.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+#include "prov/provider_ctx.h"
+#include "prov/macsignature.h"
+
+static OSSL_FUNC_keymgmt_new_fn mac_new;
+static OSSL_FUNC_keymgmt_free_fn mac_free;
+static OSSL_FUNC_keymgmt_gen_init_fn mac_gen_init;
+static OSSL_FUNC_keymgmt_gen_fn mac_gen;
+static OSSL_FUNC_keymgmt_gen_cleanup_fn mac_gen_cleanup;
+static OSSL_FUNC_keymgmt_gen_set_params_fn mac_gen_set_params;
+static OSSL_FUNC_keymgmt_gen_settable_params_fn mac_gen_settable_params;
+static OSSL_FUNC_keymgmt_get_params_fn mac_get_params;
+static OSSL_FUNC_keymgmt_gettable_params_fn mac_gettable_params;
+static OSSL_FUNC_keymgmt_set_params_fn mac_set_params;
+static OSSL_FUNC_keymgmt_settable_params_fn mac_settable_params;
+static OSSL_FUNC_keymgmt_has_fn mac_has;
+static OSSL_FUNC_keymgmt_match_fn mac_match;
+static OSSL_FUNC_keymgmt_import_fn mac_import;
+static OSSL_FUNC_keymgmt_import_types_fn mac_imexport_types;
+static OSSL_FUNC_keymgmt_export_fn mac_export;
+static OSSL_FUNC_keymgmt_export_types_fn mac_imexport_types;
+
+static OSSL_FUNC_keymgmt_new_fn mac_new_cmac;
+static OSSL_FUNC_keymgmt_gettable_params_fn cmac_gettable_params;
+static OSSL_FUNC_keymgmt_import_types_fn cmac_imexport_types;
+static OSSL_FUNC_keymgmt_export_types_fn cmac_imexport_types;
+static OSSL_FUNC_keymgmt_gen_init_fn cmac_gen_init;
+static OSSL_FUNC_keymgmt_gen_set_params_fn cmac_gen_set_params;
+static OSSL_FUNC_keymgmt_gen_settable_params_fn cmac_gen_settable_params;
+
+struct mac_gen_ctx {
+ OSSL_LIB_CTX *libctx;
+ int selection;
+ unsigned char *priv_key;
+ size_t priv_key_len;
+ PROV_CIPHER cipher;
+};
+
+MAC_KEY *ossl_mac_key_new(OSSL_LIB_CTX *libctx, int cmac)
+{
+ MAC_KEY *mackey;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ mackey = OPENSSL_zalloc(sizeof(*mackey));
+ if (mackey == NULL)
+ return NULL;
+
+ mackey->lock = CRYPTO_THREAD_lock_new();
+ if (mackey->lock == NULL) {
+ OPENSSL_free(mackey);
+ return NULL;
+ }
+ mackey->libctx = libctx;
+ mackey->refcnt = 1;
+ mackey->cmac = cmac;
+
+ return mackey;
+}
+
+void ossl_mac_key_free(MAC_KEY *mackey)
+{
+ int ref = 0;
+
+ if (mackey == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&mackey->refcnt, &ref, mackey->lock);
+ if (ref > 0)
+ return;
+
+ OPENSSL_secure_clear_free(mackey->priv_key, mackey->priv_key_len);
+ OPENSSL_free(mackey->properties);
+ ossl_prov_cipher_reset(&mackey->cipher);
+ CRYPTO_THREAD_lock_free(mackey->lock);
+ OPENSSL_free(mackey);
+}
+
+int ossl_mac_key_up_ref(MAC_KEY *mackey)
+{
+ int ref = 0;
+
+ /* This is effectively doing a new operation on the MAC_KEY and should be
+ * adequately guarded again modules' error states. However, both current
+ * calls here are guarded propery in signature/mac_legacy.c. Thus, it
+ * could be removed here. The concern is that something in the future
+ * might call this function without adequate guards. It's a cheap call,
+ * it seems best to leave it even though it is currently redundant.
+ */
+ if (!ossl_prov_is_running())
+ return 0;
+
+ CRYPTO_UP_REF(&mackey->refcnt, &ref, mackey->lock);
+ return 1;
+}
+
+static void *mac_new(void *provctx)
+{
+ return ossl_mac_key_new(PROV_LIBCTX_OF(provctx), 0);
+}
+
+static void *mac_new_cmac(void *provctx)
+{
+ return ossl_mac_key_new(PROV_LIBCTX_OF(provctx), 1);
+}
+
+static void mac_free(void *mackey)
+{
+ ossl_mac_key_free(mackey);
+}
+
+static int mac_has(const void *keydata, int selection)
+{
+ const MAC_KEY *key = keydata;
+ int ok = 0;
+
+ if (ossl_prov_is_running() && key != NULL) {
+ /*
+ * MAC keys always have all the parameters they need (i.e. none).
+ * Therefore we always return with 1, if asked about parameters.
+ * Similarly for public keys.
+ */
+ ok = 1;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = key->priv_key != NULL;
+ }
+ return ok;
+}
+
+static int mac_match(const void *keydata1, const void *keydata2, int selection)
+{
+ const MAC_KEY *key1 = keydata1;
+ const MAC_KEY *key2 = keydata2;
+ int ok = 1;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ if ((key1->priv_key == NULL && key2->priv_key != NULL)
+ || (key1->priv_key != NULL && key2->priv_key == NULL)
+ || key1->priv_key_len != key2->priv_key_len
+ || (key1->cipher.cipher == NULL && key2->cipher.cipher != NULL)
+ || (key1->cipher.cipher != NULL && key2->cipher.cipher == NULL))
+ ok = 0;
+ else
+ ok = ok && (key1->priv_key == NULL /* implies key2->privkey == NULL */
+ || CRYPTO_memcmp(key1->priv_key, key2->priv_key,
+ key1->priv_key_len) == 0);
+ if (key1->cipher.cipher != NULL)
+ ok = ok && EVP_CIPHER_is_a(key1->cipher.cipher,
+ EVP_CIPHER_get0_name(key2->cipher.cipher));
+ }
+ return ok;
+}
+
+static int mac_key_fromdata(MAC_KEY *key, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ OPENSSL_secure_clear_free(key->priv_key, key->priv_key_len);
+ /* allocate at least one byte to distinguish empty key from no key set */
+ key->priv_key = OPENSSL_secure_malloc(p->data_size > 0 ? p->data_size : 1);
+ if (key->priv_key == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ memcpy(key->priv_key, p->data, p->data_size);
+ key->priv_key_len = p->data_size;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ OPENSSL_free(key->properties);
+ key->properties = OPENSSL_strdup(p->data);
+ if (key->properties == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+
+ if (key->cmac && !ossl_prov_cipher_load_from_params(&key->cipher, params,
+ key->libctx)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ if (key->priv_key != NULL)
+ return 1;
+
+ return 0;
+}
+
+static int mac_import(void *keydata, int selection, const OSSL_PARAM params[])
+{
+ MAC_KEY *key = keydata;
+
+ if (!ossl_prov_is_running() || key == NULL)
+ return 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) == 0)
+ return 0;
+
+ return mac_key_fromdata(key, params);
+}
+
+static int key_to_params(MAC_KEY *key, OSSL_PARAM_BLD *tmpl,
+ OSSL_PARAM params[])
+{
+ if (key == NULL)
+ return 0;
+
+ if (key->priv_key != NULL
+ && !ossl_param_build_set_octet_string(tmpl, params,
+ OSSL_PKEY_PARAM_PRIV_KEY,
+ key->priv_key, key->priv_key_len))
+ return 0;
+
+ if (key->cipher.cipher != NULL
+ && !ossl_param_build_set_utf8_string(tmpl, params,
+ OSSL_PKEY_PARAM_CIPHER,
+ EVP_CIPHER_get0_name(key->cipher.cipher)))
+ return 0;
+
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
+ if (key->cipher.engine != NULL
+ && !ossl_param_build_set_utf8_string(tmpl, params,
+ OSSL_PKEY_PARAM_ENGINE,
+ ENGINE_get_id(key->cipher.engine)))
+ return 0;
+#endif
+
+ return 1;
+}
+
+static int mac_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
+ void *cbarg)
+{
+ MAC_KEY *key = keydata;
+ OSSL_PARAM_BLD *tmpl;
+ OSSL_PARAM *params = NULL;
+ int ret = 0;
+
+ if (!ossl_prov_is_running() || key == NULL)
+ return 0;
+
+ tmpl = OSSL_PARAM_BLD_new();
+ if (tmpl == NULL)
+ return 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
+ && !key_to_params(key, tmpl, NULL))
+ goto err;
+
+ params = OSSL_PARAM_BLD_to_param(tmpl);
+ if (params == NULL)
+ goto err;
+
+ ret = param_cb(params, cbarg);
+ OSSL_PARAM_free(params);
+err:
+ OSSL_PARAM_BLD_free(tmpl);
+ return ret;
+}
+
+static const OSSL_PARAM mac_key_types[] = {
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *mac_imexport_types(int selection)
+{
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ return mac_key_types;
+ return NULL;
+}
+
+static const OSSL_PARAM cmac_key_types[] = {
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_CIPHER, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_ENGINE, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *cmac_imexport_types(int selection)
+{
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ return cmac_key_types;
+ return NULL;
+}
+
+static int mac_get_params(void *key, OSSL_PARAM params[])
+{
+ return key_to_params(key, NULL, params);
+}
+
+static const OSSL_PARAM *mac_gettable_params(void *provctx)
+{
+ static const OSSL_PARAM gettable_params[] = {
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
+ OSSL_PARAM_END
+ };
+ return gettable_params;
+}
+
+static const OSSL_PARAM *cmac_gettable_params(void *provctx)
+{
+ static const OSSL_PARAM gettable_params[] = {
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_CIPHER, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_ENGINE, NULL, 0),
+ OSSL_PARAM_END
+ };
+ return gettable_params;
+}
+
+static int mac_set_params(void *keydata, const OSSL_PARAM params[])
+{
+ MAC_KEY *key = keydata;
+ const OSSL_PARAM *p;
+
+ if (key == NULL)
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
+ if (p != NULL)
+ return mac_key_fromdata(key, params);
+
+ return 1;
+}
+
+static const OSSL_PARAM *mac_settable_params(void *provctx)
+{
+ static const OSSL_PARAM settable_params[] = {
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
+ OSSL_PARAM_END
+ };
+ return settable_params;
+}
+
+static void *mac_gen_init_common(void *provctx, int selection)
+{
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
+ struct mac_gen_ctx *gctx = NULL;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
+ gctx->libctx = libctx;
+ gctx->selection = selection;
+ }
+ return gctx;
+}
+
+static void *mac_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[])
+{
+ struct mac_gen_ctx *gctx = mac_gen_init_common(provctx, selection);
+
+ if (gctx != NULL && !mac_gen_set_params(gctx, params)) {
+ OPENSSL_free(gctx);
+ gctx = NULL;
+ }
+ return gctx;
+}
+
+static void *cmac_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[])
+{
+ struct mac_gen_ctx *gctx = mac_gen_init_common(provctx, selection);
+
+ if (gctx != NULL && !cmac_gen_set_params(gctx, params)) {
+ OPENSSL_free(gctx);
+ gctx = NULL;
+ }
+ return gctx;
+}
+
+static int mac_gen_set_params(void *genctx, const OSSL_PARAM params[])
+{
+ struct mac_gen_ctx *gctx = genctx;
+ const OSSL_PARAM *p;
+
+ if (gctx == NULL)
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ gctx->priv_key = OPENSSL_secure_malloc(p->data_size);
+ if (gctx->priv_key == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ memcpy(gctx->priv_key, p->data, p->data_size);
+ gctx->priv_key_len = p->data_size;
+ }
+
+ return 1;
+}
+
+static int cmac_gen_set_params(void *genctx, const OSSL_PARAM params[])
+{
+ struct mac_gen_ctx *gctx = genctx;
+
+ if (!mac_gen_set_params(genctx, params))
+ return 0;
+
+ if (!ossl_prov_cipher_load_from_params(&gctx->cipher, params,
+ gctx->libctx)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ return 1;
+}
+
+static const OSSL_PARAM *mac_gen_settable_params(ossl_unused void *genctx,
+ ossl_unused void *provctx)
+{
+ static OSSL_PARAM settable[] = {
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
+ OSSL_PARAM_END
+ };
+ return settable;
+}
+
+static const OSSL_PARAM *cmac_gen_settable_params(ossl_unused void *genctx,
+ ossl_unused void *provctx)
+{
+ static OSSL_PARAM settable[] = {
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_CIPHER, NULL, 0),
+ OSSL_PARAM_END
+ };
+ return settable;
+}
+
+static void *mac_gen(void *genctx, OSSL_CALLBACK *cb, void *cbarg)
+{
+ struct mac_gen_ctx *gctx = genctx;
+ MAC_KEY *key;
+
+ if (!ossl_prov_is_running() || gctx == NULL)
+ return NULL;
+
+ if ((key = ossl_mac_key_new(gctx->libctx, 0)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ /* If we're doing parameter generation then we just return a blank key */
+ if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
+ return key;
+
+ if (gctx->priv_key == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
+ ossl_mac_key_free(key);
+ return NULL;
+ }
+
+ /*
+ * This is horrible but required for backwards compatibility. We don't
+ * actually do real key generation at all. We simply copy the key that was
+ * previously set in the gctx. Hopefully at some point in the future all
+ * of this can be removed and we will only support the EVP_KDF APIs.
+ */
+ if (!ossl_prov_cipher_copy(&key->cipher, &gctx->cipher)) {
+ ossl_mac_key_free(key);
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+ ossl_prov_cipher_reset(&gctx->cipher);
+ key->priv_key = gctx->priv_key;
+ key->priv_key_len = gctx->priv_key_len;
+ gctx->priv_key_len = 0;
+ gctx->priv_key = NULL;
+
+ return key;
+}
+
+static void mac_gen_cleanup(void *genctx)
+{
+ struct mac_gen_ctx *gctx = genctx;
+
+ OPENSSL_secure_clear_free(gctx->priv_key, gctx->priv_key_len);
+ ossl_prov_cipher_reset(&gctx->cipher);
+ OPENSSL_free(gctx);
+}
+
+const OSSL_DISPATCH ossl_mac_legacy_keymgmt_functions[] = {
+ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))mac_new },
+ { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))mac_free },
+ { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))mac_get_params },
+ { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))mac_gettable_params },
+ { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))mac_set_params },
+ { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))mac_settable_params },
+ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))mac_has },
+ { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))mac_match },
+ { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))mac_import },
+ { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))mac_imexport_types },
+ { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))mac_export },
+ { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))mac_imexport_types },
+ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))mac_gen_init },
+ { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))mac_gen_set_params },
+ { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
+ (void (*)(void))mac_gen_settable_params },
+ { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))mac_gen },
+ { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))mac_gen_cleanup },
+ { 0, NULL }
+};
+
+const OSSL_DISPATCH ossl_cmac_legacy_keymgmt_functions[] = {
+ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))mac_new_cmac },
+ { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))mac_free },
+ { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))mac_get_params },
+ { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))cmac_gettable_params },
+ { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))mac_set_params },
+ { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))mac_settable_params },
+ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))mac_has },
+ { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))mac_match },
+ { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))mac_import },
+ { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))cmac_imexport_types },
+ { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))mac_export },
+ { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))cmac_imexport_types },
+ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))cmac_gen_init },
+ { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))cmac_gen_set_params },
+ { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
+ (void (*)(void))cmac_gen_settable_params },
+ { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))mac_gen },
+ { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))mac_gen_cleanup },
+ { 0, NULL }
+};
+
diff --git a/providers/implementations/keymgmt/rsa_kmgmt.c b/providers/implementations/keymgmt/rsa_kmgmt.c
new file mode 100644
index 000000000000..b76835ccc437
--- /dev/null
+++ b/providers/implementations/keymgmt/rsa_kmgmt.c
@@ -0,0 +1,744 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#include <openssl/proverr.h>
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+#include "prov/provider_ctx.h"
+#include "crypto/rsa.h"
+#include "crypto/cryptlib.h"
+#include "internal/param_build_set.h"
+
+static OSSL_FUNC_keymgmt_new_fn rsa_newdata;
+static OSSL_FUNC_keymgmt_new_fn rsapss_newdata;
+static OSSL_FUNC_keymgmt_gen_init_fn rsa_gen_init;
+static OSSL_FUNC_keymgmt_gen_init_fn rsapss_gen_init;
+static OSSL_FUNC_keymgmt_gen_set_params_fn rsa_gen_set_params;
+static OSSL_FUNC_keymgmt_gen_settable_params_fn rsa_gen_settable_params;
+static OSSL_FUNC_keymgmt_gen_settable_params_fn rsapss_gen_settable_params;
+static OSSL_FUNC_keymgmt_gen_fn rsa_gen;
+static OSSL_FUNC_keymgmt_gen_cleanup_fn rsa_gen_cleanup;
+static OSSL_FUNC_keymgmt_load_fn rsa_load;
+static OSSL_FUNC_keymgmt_load_fn rsapss_load;
+static OSSL_FUNC_keymgmt_free_fn rsa_freedata;
+static OSSL_FUNC_keymgmt_get_params_fn rsa_get_params;
+static OSSL_FUNC_keymgmt_gettable_params_fn rsa_gettable_params;
+static OSSL_FUNC_keymgmt_has_fn rsa_has;
+static OSSL_FUNC_keymgmt_match_fn rsa_match;
+static OSSL_FUNC_keymgmt_validate_fn rsa_validate;
+static OSSL_FUNC_keymgmt_import_fn rsa_import;
+static OSSL_FUNC_keymgmt_import_types_fn rsa_import_types;
+static OSSL_FUNC_keymgmt_export_fn rsa_export;
+static OSSL_FUNC_keymgmt_export_types_fn rsa_export_types;
+static OSSL_FUNC_keymgmt_query_operation_name_fn rsa_query_operation_name;
+static OSSL_FUNC_keymgmt_dup_fn rsa_dup;
+
+#define RSA_DEFAULT_MD "SHA256"
+#define RSA_PSS_DEFAULT_MD OSSL_DIGEST_NAME_SHA1
+#define RSA_POSSIBLE_SELECTIONS \
+ (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS)
+
+DEFINE_STACK_OF(BIGNUM)
+DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
+
+static int pss_params_fromdata(RSA_PSS_PARAMS_30 *pss_params, int *defaults_set,
+ const OSSL_PARAM params[], int rsa_type,
+ OSSL_LIB_CTX *libctx)
+{
+ if (!ossl_rsa_pss_params_30_fromdata(pss_params, defaults_set,
+ params, libctx))
+ return 0;
+
+ /* If not a PSS type RSA, sending us PSS parameters is wrong */
+ if (rsa_type != RSA_FLAG_TYPE_RSASSAPSS
+ && !ossl_rsa_pss_params_30_is_unrestricted(pss_params))
+ return 0;
+
+ return 1;
+}
+
+static void *rsa_newdata(void *provctx)
+{
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
+ RSA *rsa;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ rsa = ossl_rsa_new_with_ctx(libctx);
+ if (rsa != NULL) {
+ RSA_clear_flags(rsa, RSA_FLAG_TYPE_MASK);
+ RSA_set_flags(rsa, RSA_FLAG_TYPE_RSA);
+ }
+ return rsa;
+}
+
+static void *rsapss_newdata(void *provctx)
+{
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
+ RSA *rsa;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ rsa = ossl_rsa_new_with_ctx(libctx);
+ if (rsa != NULL) {
+ RSA_clear_flags(rsa, RSA_FLAG_TYPE_MASK);
+ RSA_set_flags(rsa, RSA_FLAG_TYPE_RSASSAPSS);
+ }
+ return rsa;
+}
+
+static void rsa_freedata(void *keydata)
+{
+ RSA_free(keydata);
+}
+
+static int rsa_has(const void *keydata, int selection)
+{
+ const RSA *rsa = keydata;
+ int ok = 1;
+
+ if (rsa == NULL || !ossl_prov_is_running())
+ return 0;
+ if ((selection & RSA_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* the selection is not missing */
+
+ /* OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS are always available even if empty */
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+ ok = ok && (RSA_get0_e(rsa) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && (RSA_get0_n(rsa) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && (RSA_get0_d(rsa) != NULL);
+ return ok;
+}
+
+static int rsa_match(const void *keydata1, const void *keydata2, int selection)
+{
+ const RSA *rsa1 = keydata1;
+ const RSA *rsa2 = keydata2;
+ int ok = 1;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ /* There is always an |e| */
+ ok = ok && BN_cmp(RSA_get0_e(rsa1), RSA_get0_e(rsa2)) == 0;
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ int key_checked = 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+ const BIGNUM *pa = RSA_get0_n(rsa1);
+ const BIGNUM *pb = RSA_get0_n(rsa2);
+
+ if (pa != NULL && pb != NULL) {
+ ok = ok && BN_cmp(pa, pb) == 0;
+ key_checked = 1;
+ }
+ }
+ if (!key_checked
+ && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ const BIGNUM *pa = RSA_get0_d(rsa1);
+ const BIGNUM *pb = RSA_get0_d(rsa2);
+
+ if (pa != NULL && pb != NULL) {
+ ok = ok && BN_cmp(pa, pb) == 0;
+ key_checked = 1;
+ }
+ }
+ ok = ok && key_checked;
+ }
+ return ok;
+}
+
+static int rsa_import(void *keydata, int selection, const OSSL_PARAM params[])
+{
+ RSA *rsa = keydata;
+ int rsa_type;
+ int ok = 1;
+ int pss_defaults_set = 0;
+
+ if (!ossl_prov_is_running() || rsa == NULL)
+ return 0;
+
+ if ((selection & RSA_POSSIBLE_SELECTIONS) == 0)
+ return 0;
+
+ rsa_type = RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK);
+
+ if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
+ ok = ok && pss_params_fromdata(ossl_rsa_get0_pss_params_30(rsa),
+ &pss_defaults_set,
+ params, rsa_type,
+ ossl_rsa_get0_libctx(rsa));
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ int include_private =
+ selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
+
+ ok = ok && ossl_rsa_fromdata(rsa, params, include_private);
+ }
+
+ return ok;
+}
+
+static int rsa_export(void *keydata, int selection,
+ OSSL_CALLBACK *param_callback, void *cbarg)
+{
+ RSA *rsa = keydata;
+ const RSA_PSS_PARAMS_30 *pss_params = ossl_rsa_get0_pss_params_30(rsa);
+ OSSL_PARAM_BLD *tmpl;
+ OSSL_PARAM *params = NULL;
+ int ok = 1;
+
+ if (!ossl_prov_is_running() || rsa == NULL)
+ return 0;
+
+ if ((selection & RSA_POSSIBLE_SELECTIONS) == 0)
+ return 0;
+
+ tmpl = OSSL_PARAM_BLD_new();
+ if (tmpl == NULL)
+ return 0;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
+ ok = ok && (ossl_rsa_pss_params_30_is_unrestricted(pss_params)
+ || ossl_rsa_pss_params_30_todata(pss_params, tmpl, NULL));
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
+ int include_private =
+ selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
+
+ ok = ok && ossl_rsa_todata(rsa, tmpl, NULL, include_private);
+ }
+
+ if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
+ ok = 0;
+ goto err;
+ }
+
+ ok = param_callback(params, cbarg);
+ OSSL_PARAM_free(params);
+err:
+ OSSL_PARAM_BLD_free(tmpl);
+ return ok;
+}
+
+#ifdef FIPS_MODULE
+/* In fips mode there are no multi-primes. */
+# define RSA_KEY_MP_TYPES() \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR1, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR2, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT1, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT2, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, NULL, 0),
+#else
+/*
+ * We allow up to 10 prime factors (starting with p, q).
+ * NOTE: there is only 9 OSSL_PKEY_PARAM_RSA_COEFFICIENT
+ */
+# define RSA_KEY_MP_TYPES() \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR1, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR2, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR3, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR4, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR5, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR6, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR7, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR8, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR9, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR10, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT1, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT2, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT3, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT4, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT5, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT6, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT7, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT8, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT9, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT10, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT2, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT3, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT4, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT5, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT6, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT7, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT8, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT9, NULL, 0),
+#endif
+
+#define RSA_KEY_TYPES() \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_N, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0), \
+OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_D, NULL, 0), \
+RSA_KEY_MP_TYPES()
+
+/*
+ * This provider can export everything in an RSA key, so we use the exact
+ * same type description for export as for import. Other providers might
+ * choose to import full keys, but only export the public parts, and will
+ * therefore have the importkey_types and importkey_types functions return
+ * different arrays.
+ */
+static const OSSL_PARAM rsa_key_types[] = {
+ RSA_KEY_TYPES()
+ OSSL_PARAM_END
+};
+/*
+ * We lied about the amount of factors, exponents and coefficients, the
+ * export and import functions can really deal with an infinite amount
+ * of these numbers. However, RSA keys with too many primes are futile,
+ * so we at least pretend to have some limits.
+ */
+
+static const OSSL_PARAM *rsa_imexport_types(int selection)
+{
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+ return rsa_key_types;
+ return NULL;
+}
+
+static const OSSL_PARAM *rsa_import_types(int selection)
+{
+ return rsa_imexport_types(selection);
+}
+
+static const OSSL_PARAM *rsa_export_types(int selection)
+{
+ return rsa_imexport_types(selection);
+}
+
+static int rsa_get_params(void *key, OSSL_PARAM params[])
+{
+ RSA *rsa = key;
+ const RSA_PSS_PARAMS_30 *pss_params = ossl_rsa_get0_pss_params_30(rsa);
+ int rsa_type = RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK);
+ OSSL_PARAM *p;
+ int empty = RSA_get0_n(rsa) == NULL;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
+ && (empty || !OSSL_PARAM_set_int(p, RSA_bits(rsa))))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
+ && (empty || !OSSL_PARAM_set_int(p, RSA_security_bits(rsa))))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
+ && (empty || !OSSL_PARAM_set_int(p, RSA_size(rsa))))
+ return 0;
+
+ /*
+ * For restricted RSA-PSS keys, we ignore the default digest request.
+ * With RSA-OAEP keys, this may need to be amended.
+ */
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
+ && (rsa_type != RSA_FLAG_TYPE_RSASSAPSS
+ || ossl_rsa_pss_params_30_is_unrestricted(pss_params))) {
+ if (!OSSL_PARAM_set_utf8_string(p, RSA_DEFAULT_MD))
+ return 0;
+ }
+
+ /*
+ * For non-RSA-PSS keys, we ignore the mandatory digest request.
+ * With RSA-OAEP keys, this may need to be amended.
+ */
+ if ((p = OSSL_PARAM_locate(params,
+ OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL
+ && rsa_type == RSA_FLAG_TYPE_RSASSAPSS
+ && !ossl_rsa_pss_params_30_is_unrestricted(pss_params)) {
+ const char *mdname =
+ ossl_rsa_oaeppss_nid2name(ossl_rsa_pss_params_30_hashalg(pss_params));
+
+ if (mdname == NULL || !OSSL_PARAM_set_utf8_string(p, mdname))
+ return 0;
+ }
+ return (rsa_type != RSA_FLAG_TYPE_RSASSAPSS
+ || ossl_rsa_pss_params_30_todata(pss_params, NULL, params))
+ && ossl_rsa_todata(rsa, NULL, params, 1);
+}
+
+static const OSSL_PARAM rsa_params[] = {
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
+ RSA_KEY_TYPES()
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *rsa_gettable_params(void *provctx)
+{
+ return rsa_params;
+}
+
+static int rsa_validate(const void *keydata, int selection, int checktype)
+{
+ const RSA *rsa = keydata;
+ int ok = 1;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if ((selection & RSA_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* nothing to validate */
+
+ /* If the whole key is selected, we do a pairwise validation */
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR)
+ == OSSL_KEYMGMT_SELECT_KEYPAIR) {
+ ok = ok && ossl_rsa_validate_pairwise(rsa);
+ } else {
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && ossl_rsa_validate_private(rsa);
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && ossl_rsa_validate_public(rsa);
+ }
+ return ok;
+}
+
+struct rsa_gen_ctx {
+ OSSL_LIB_CTX *libctx;
+ const char *propq;
+
+ int rsa_type;
+
+ size_t nbits;
+ BIGNUM *pub_exp;
+ size_t primes;
+
+ /* For PSS */
+ RSA_PSS_PARAMS_30 pss_params;
+ int pss_defaults_set;
+
+ /* For generation callback */
+ OSSL_CALLBACK *cb;
+ void *cbarg;
+
+#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+ /* ACVP test parameters */
+ OSSL_PARAM *acvp_test_params;
+#endif
+};
+
+static int rsa_gencb(int p, int n, BN_GENCB *cb)
+{
+ struct rsa_gen_ctx *gctx = BN_GENCB_get_arg(cb);
+ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p);
+ params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n);
+ return gctx->cb(params, gctx->cbarg);
+}
+
+static void *gen_init(void *provctx, int selection, int rsa_type,
+ const OSSL_PARAM params[])
+{
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
+ struct rsa_gen_ctx *gctx = NULL;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
+ return NULL;
+
+ if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
+ gctx->libctx = libctx;
+ if ((gctx->pub_exp = BN_new()) == NULL
+ || !BN_set_word(gctx->pub_exp, RSA_F4)) {
+ goto err;
+ }
+ gctx->nbits = 2048;
+ gctx->primes = RSA_DEFAULT_PRIME_NUM;
+ gctx->rsa_type = rsa_type;
+ } else {
+ goto err;
+ }
+
+ if (!rsa_gen_set_params(gctx, params))
+ goto err;
+ return gctx;
+
+err:
+ if (gctx != NULL)
+ BN_free(gctx->pub_exp);
+ OPENSSL_free(gctx);
+ return NULL;
+}
+
+static void *rsa_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[])
+{
+ return gen_init(provctx, selection, RSA_FLAG_TYPE_RSA, params);
+}
+
+static void *rsapss_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[])
+{
+ return gen_init(provctx, selection, RSA_FLAG_TYPE_RSASSAPSS, params);
+}
+
+/*
+ * This function is common for all RSA sub-types, to detect possible
+ * misuse, such as PSS parameters being passed when a plain RSA key
+ * is generated.
+ */
+static int rsa_gen_set_params(void *genctx, const OSSL_PARAM params[])
+{
+ struct rsa_gen_ctx *gctx = genctx;
+ const OSSL_PARAM *p;
+
+ if (params == NULL)
+ return 1;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_BITS)) != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &gctx->nbits))
+ return 0;
+ if (gctx->nbits < RSA_MIN_MODULUS_BITS) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL);
+ return 0;
+ }
+ }
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_PRIMES)) != NULL
+ && !OSSL_PARAM_get_size_t(p, &gctx->primes))
+ return 0;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E)) != NULL
+ && !OSSL_PARAM_get_BN(p, &gctx->pub_exp))
+ return 0;
+ /* Only attempt to get PSS parameters when generating an RSA-PSS key */
+ if (gctx->rsa_type == RSA_FLAG_TYPE_RSASSAPSS
+ && !pss_params_fromdata(&gctx->pss_params, &gctx->pss_defaults_set, params,
+ gctx->rsa_type, gctx->libctx))
+ return 0;
+#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+ /* Any ACVP test related parameters are copied into a params[] */
+ if (!ossl_rsa_acvp_test_gen_params_new(&gctx->acvp_test_params, params))
+ return 0;
+#endif
+ return 1;
+}
+
+#define rsa_gen_basic \
+ OSSL_PARAM_size_t(OSSL_PKEY_PARAM_RSA_BITS, NULL), \
+ OSSL_PARAM_size_t(OSSL_PKEY_PARAM_RSA_PRIMES, NULL), \
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0)
+
+/*
+ * The following must be kept in sync with ossl_rsa_pss_params_30_fromdata()
+ * in crypto/rsa/rsa_backend.c
+ */
+#define rsa_gen_pss \
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST, NULL, 0), \
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST_PROPS, NULL, 0), \
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_MASKGENFUNC, NULL, 0), \
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_MGF1_DIGEST, NULL, 0), \
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_RSA_PSS_SALTLEN, NULL)
+
+static const OSSL_PARAM *rsa_gen_settable_params(ossl_unused void *genctx,
+ ossl_unused void *provctx)
+{
+ static OSSL_PARAM settable[] = {
+ rsa_gen_basic,
+ OSSL_PARAM_END
+ };
+
+ return settable;
+}
+
+static const OSSL_PARAM *rsapss_gen_settable_params(ossl_unused void *genctx,
+ ossl_unused void *provctx)
+{
+ static OSSL_PARAM settable[] = {
+ rsa_gen_basic,
+ rsa_gen_pss,
+ OSSL_PARAM_END
+ };
+
+ return settable;
+}
+
+static void *rsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
+{
+ struct rsa_gen_ctx *gctx = genctx;
+ RSA *rsa = NULL, *rsa_tmp = NULL;
+ BN_GENCB *gencb = NULL;
+
+ if (!ossl_prov_is_running() || gctx == NULL)
+ return NULL;
+
+ switch (gctx->rsa_type) {
+ case RSA_FLAG_TYPE_RSA:
+ /* For plain RSA keys, PSS parameters must not be set */
+ if (!ossl_rsa_pss_params_30_is_unrestricted(&gctx->pss_params))
+ goto err;
+ break;
+ case RSA_FLAG_TYPE_RSASSAPSS:
+ /*
+ * For plain RSA-PSS keys, PSS parameters may be set but don't have
+ * to, so not check.
+ */
+ break;
+ default:
+ /* Unsupported RSA key sub-type... */
+ return NULL;
+ }
+
+ if ((rsa_tmp = ossl_rsa_new_with_ctx(gctx->libctx)) == NULL)
+ return NULL;
+
+ gctx->cb = osslcb;
+ gctx->cbarg = cbarg;
+ gencb = BN_GENCB_new();
+ if (gencb != NULL)
+ BN_GENCB_set(gencb, rsa_gencb, genctx);
+
+#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+ if (gctx->acvp_test_params != NULL) {
+ if (!ossl_rsa_acvp_test_set_params(rsa_tmp, gctx->acvp_test_params))
+ goto err;
+ }
+#endif
+
+ if (!RSA_generate_multi_prime_key(rsa_tmp,
+ (int)gctx->nbits, (int)gctx->primes,
+ gctx->pub_exp, gencb))
+ goto err;
+
+ if (!ossl_rsa_pss_params_30_copy(ossl_rsa_get0_pss_params_30(rsa_tmp),
+ &gctx->pss_params))
+ goto err;
+
+ RSA_clear_flags(rsa_tmp, RSA_FLAG_TYPE_MASK);
+ RSA_set_flags(rsa_tmp, gctx->rsa_type);
+
+ rsa = rsa_tmp;
+ rsa_tmp = NULL;
+ err:
+ BN_GENCB_free(gencb);
+ RSA_free(rsa_tmp);
+ return rsa;
+}
+
+static void rsa_gen_cleanup(void *genctx)
+{
+ struct rsa_gen_ctx *gctx = genctx;
+
+ if (gctx == NULL)
+ return;
+#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+ ossl_rsa_acvp_test_gen_params_free(gctx->acvp_test_params);
+ gctx->acvp_test_params = NULL;
+#endif
+ BN_clear_free(gctx->pub_exp);
+ OPENSSL_free(gctx);
+}
+
+static void *common_load(const void *reference, size_t reference_sz,
+ int expected_rsa_type)
+{
+ RSA *rsa = NULL;
+
+ if (ossl_prov_is_running() && reference_sz == sizeof(rsa)) {
+ /* The contents of the reference is the address to our object */
+ rsa = *(RSA **)reference;
+
+ if (RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK) != expected_rsa_type)
+ return NULL;
+
+ /* We grabbed, so we detach it */
+ *(RSA **)reference = NULL;
+ return rsa;
+ }
+ return NULL;
+}
+
+static void *rsa_load(const void *reference, size_t reference_sz)
+{
+ return common_load(reference, reference_sz, RSA_FLAG_TYPE_RSA);
+}
+
+static void *rsapss_load(const void *reference, size_t reference_sz)
+{
+ return common_load(reference, reference_sz, RSA_FLAG_TYPE_RSASSAPSS);
+}
+
+static void *rsa_dup(const void *keydata_from, int selection)
+{
+ if (ossl_prov_is_running()
+ /* do not allow creating empty keys by duplication */
+ && (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+ return ossl_rsa_dup(keydata_from, selection);
+ return NULL;
+}
+
+/* For any RSA key, we use the "RSA" algorithms regardless of sub-type. */
+static const char *rsa_query_operation_name(int operation_id)
+{
+ return "RSA";
+}
+
+const OSSL_DISPATCH ossl_rsa_keymgmt_functions[] = {
+ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))rsa_newdata },
+ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))rsa_gen_init },
+ { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS,
+ (void (*)(void))rsa_gen_set_params },
+ { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
+ (void (*)(void))rsa_gen_settable_params },
+ { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))rsa_gen },
+ { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))rsa_gen_cleanup },
+ { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))rsa_load },
+ { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))rsa_freedata },
+ { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))rsa_get_params },
+ { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))rsa_gettable_params },
+ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))rsa_has },
+ { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))rsa_match },
+ { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))rsa_validate },
+ { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))rsa_import },
+ { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))rsa_import_types },
+ { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))rsa_export },
+ { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))rsa_export_types },
+ { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))rsa_dup },
+ { 0, NULL }
+};
+
+const OSSL_DISPATCH ossl_rsapss_keymgmt_functions[] = {
+ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))rsapss_newdata },
+ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))rsapss_gen_init },
+ { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))rsa_gen_set_params },
+ { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
+ (void (*)(void))rsapss_gen_settable_params },
+ { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))rsa_gen },
+ { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))rsa_gen_cleanup },
+ { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))rsapss_load },
+ { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))rsa_freedata },
+ { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))rsa_get_params },
+ { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))rsa_gettable_params },
+ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))rsa_has },
+ { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))rsa_match },
+ { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))rsa_validate },
+ { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))rsa_import },
+ { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))rsa_import_types },
+ { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))rsa_export },
+ { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))rsa_export_types },
+ { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
+ (void (*)(void))rsa_query_operation_name },
+ { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))rsa_dup },
+ { 0, NULL }
+};
diff --git a/providers/implementations/macs/blake2_mac_impl.c b/providers/implementations/macs/blake2_mac_impl.c
new file mode 100644
index 000000000000..3c6b0c2c0c07
--- /dev/null
+++ b/providers/implementations/macs/blake2_mac_impl.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/proverr.h>
+
+#include "prov/blake2.h"
+#include "internal/cryptlib.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+/*
+ * Forward declaration of everything implemented here. This is not strictly
+ * necessary for the compiler, but provides an assurance that the signatures
+ * of the functions in the dispatch table are correct.
+ */
+static OSSL_FUNC_mac_newctx_fn blake2_mac_new;
+static OSSL_FUNC_mac_dupctx_fn blake2_mac_dup;
+static OSSL_FUNC_mac_freectx_fn blake2_mac_free;
+static OSSL_FUNC_mac_gettable_ctx_params_fn blake2_gettable_ctx_params;
+static OSSL_FUNC_mac_get_ctx_params_fn blake2_get_ctx_params;
+static OSSL_FUNC_mac_settable_ctx_params_fn blake2_mac_settable_ctx_params;
+static OSSL_FUNC_mac_set_ctx_params_fn blake2_mac_set_ctx_params;
+static OSSL_FUNC_mac_init_fn blake2_mac_init;
+static OSSL_FUNC_mac_update_fn blake2_mac_update;
+static OSSL_FUNC_mac_final_fn blake2_mac_final;
+
+struct blake2_mac_data_st {
+ BLAKE2_CTX ctx;
+ BLAKE2_PARAM params;
+ unsigned char key[BLAKE2_KEYBYTES];
+};
+
+static void *blake2_mac_new(void *unused_provctx)
+{
+ struct blake2_mac_data_st *macctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ macctx = OPENSSL_zalloc(sizeof(*macctx));
+ if (macctx != NULL) {
+ BLAKE2_PARAM_INIT(&macctx->params);
+ /* ctx initialization is deferred to BLAKE2b_Init() */
+ }
+ return macctx;
+}
+
+static void *blake2_mac_dup(void *vsrc)
+{
+ struct blake2_mac_data_st *dst;
+ struct blake2_mac_data_st *src = vsrc;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ dst = OPENSSL_zalloc(sizeof(*dst));
+ if (dst == NULL)
+ return NULL;
+
+ *dst = *src;
+ return dst;
+}
+
+static void blake2_mac_free(void *vmacctx)
+{
+ struct blake2_mac_data_st *macctx = vmacctx;
+
+ if (macctx != NULL) {
+ OPENSSL_cleanse(macctx->key, sizeof(macctx->key));
+ OPENSSL_free(macctx);
+ }
+}
+
+static size_t blake2_mac_size(void *vmacctx)
+{
+ struct blake2_mac_data_st *macctx = vmacctx;
+
+ return macctx->params.digest_length;
+}
+
+static int blake2_setkey(struct blake2_mac_data_st *macctx,
+ const unsigned char *key, size_t keylen)
+{
+ if (keylen > BLAKE2_KEYBYTES || keylen == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ memcpy(macctx->key, key, keylen);
+ /* Pad with zeroes at the end if required */
+ if (keylen < BLAKE2_KEYBYTES)
+ memset(macctx->key + keylen, 0, BLAKE2_KEYBYTES - keylen);
+ BLAKE2_PARAM_SET_KEY_LENGTH(&macctx->params, (uint8_t)keylen);
+ return 1;
+}
+
+static int blake2_mac_init(void *vmacctx, const unsigned char *key,
+ size_t keylen, const OSSL_PARAM params[])
+{
+ struct blake2_mac_data_st *macctx = vmacctx;
+
+ if (!ossl_prov_is_running() || !blake2_mac_set_ctx_params(macctx, params))
+ return 0;
+ if (key != NULL) {
+ if (!blake2_setkey(macctx, key, keylen))
+ return 0;
+ } else if (macctx->params.key_length == 0) {
+ /* Check key has been set */
+ ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
+ return 0;
+ }
+ return BLAKE2_INIT_KEY(&macctx->ctx, &macctx->params, macctx->key);
+}
+
+static int blake2_mac_update(void *vmacctx,
+ const unsigned char *data, size_t datalen)
+{
+ struct blake2_mac_data_st *macctx = vmacctx;
+
+ if (datalen == 0)
+ return 1;
+
+ return BLAKE2_UPDATE(&macctx->ctx, data, datalen);
+}
+
+static int blake2_mac_final(void *vmacctx,
+ unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ struct blake2_mac_data_st *macctx = vmacctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ *outl = blake2_mac_size(macctx);
+ return BLAKE2_FINAL(out, &macctx->ctx);
+}
+
+static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
+ OSSL_PARAM_size_t(OSSL_MAC_PARAM_BLOCK_SIZE, NULL),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *blake2_gettable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ return known_gettable_ctx_params;
+}
+
+static int blake2_get_ctx_params(void *vmacctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL
+ && !OSSL_PARAM_set_size_t(p, blake2_mac_size(vmacctx)))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_BLOCK_SIZE)) != NULL
+ && !OSSL_PARAM_set_size_t(p, BLAKE2_BLOCKBYTES))
+ return 0;
+
+ return 1;
+}
+
+static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
+ OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_MAC_PARAM_CUSTOM, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_MAC_PARAM_SALT, NULL, 0),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *blake2_mac_settable_ctx_params(
+ ossl_unused void *ctx, ossl_unused void *p_ctx)
+{
+ return known_settable_ctx_params;
+}
+
+/*
+ * ALL parameters should be set before init().
+ */
+static int blake2_mac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])
+{
+ struct blake2_mac_data_st *macctx = vmacctx;
+ const OSSL_PARAM *p;
+
+ if (params == NULL)
+ return 1;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_SIZE)) != NULL) {
+ size_t size;
+
+ if (!OSSL_PARAM_get_size_t(p, &size)
+ || size < 1
+ || size > BLAKE2_OUTBYTES) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_XOF_OR_INVALID_LENGTH);
+ return 0;
+ }
+ BLAKE2_PARAM_SET_DIGEST_LENGTH(&macctx->params, (uint8_t)size);
+ }
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL
+ && !blake2_setkey(macctx, p->data, p->data_size))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_CUSTOM))
+ != NULL) {
+ /*
+ * The OSSL_PARAM API doesn't provide direct pointer use, so we
+ * must handle the OSSL_PARAM structure ourselves here
+ */
+ if (p->data_size > BLAKE2_PERSONALBYTES) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CUSTOM_LENGTH);
+ return 0;
+ }
+ BLAKE2_PARAM_SET_PERSONAL(&macctx->params, p->data, p->data_size);
+ }
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_SALT)) != NULL) {
+ /*
+ * The OSSL_PARAM API doesn't provide direct pointer use, so we
+ * must handle the OSSL_PARAM structure ourselves here as well
+ */
+ if (p->data_size > BLAKE2_SALTBYTES) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH);
+ return 0;
+ }
+ BLAKE2_PARAM_SET_SALT(&macctx->params, p->data, p->data_size);
+ }
+ return 1;
+}
+
+const OSSL_DISPATCH BLAKE2_FUNCTIONS[] = {
+ { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))blake2_mac_new },
+ { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))blake2_mac_dup },
+ { OSSL_FUNC_MAC_FREECTX, (void (*)(void))blake2_mac_free },
+ { OSSL_FUNC_MAC_INIT, (void (*)(void))blake2_mac_init },
+ { OSSL_FUNC_MAC_UPDATE, (void (*)(void))blake2_mac_update },
+ { OSSL_FUNC_MAC_FINAL, (void (*)(void))blake2_mac_final },
+ { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS,
+ (void (*)(void))blake2_gettable_ctx_params },
+ { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))blake2_get_ctx_params },
+ { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
+ (void (*)(void))blake2_mac_settable_ctx_params },
+ { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))blake2_mac_set_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/macs/blake2b_mac.c b/providers/implementations/macs/blake2b_mac.c
new file mode 100644
index 000000000000..b445cbd57875
--- /dev/null
+++ b/providers/implementations/macs/blake2b_mac.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Constants */
+#define BLAKE2_CTX BLAKE2B_CTX
+#define BLAKE2_PARAM BLAKE2B_PARAM
+#define BLAKE2_KEYBYTES BLAKE2B_KEYBYTES
+#define BLAKE2_OUTBYTES BLAKE2B_OUTBYTES
+#define BLAKE2_PERSONALBYTES BLAKE2B_PERSONALBYTES
+#define BLAKE2_SALTBYTES BLAKE2B_SALTBYTES
+#define BLAKE2_BLOCKBYTES BLAKE2B_BLOCKBYTES
+
+/* Function names */
+#define BLAKE2_PARAM_INIT ossl_blake2b_param_init
+#define BLAKE2_INIT_KEY ossl_blake2b_init_key
+#define BLAKE2_UPDATE ossl_blake2b_update
+#define BLAKE2_FINAL ossl_blake2b_final
+#define BLAKE2_PARAM_SET_DIGEST_LENGTH ossl_blake2b_param_set_digest_length
+#define BLAKE2_PARAM_SET_KEY_LENGTH ossl_blake2b_param_set_key_length
+#define BLAKE2_PARAM_SET_PERSONAL ossl_blake2b_param_set_personal
+#define BLAKE2_PARAM_SET_SALT ossl_blake2b_param_set_salt
+
+/* OSSL_DISPATCH symbol */
+#define BLAKE2_FUNCTIONS ossl_blake2bmac_functions
+
+#include "blake2_mac_impl.c"
+
diff --git a/providers/implementations/macs/blake2s_mac.c b/providers/implementations/macs/blake2s_mac.c
new file mode 100644
index 000000000000..6b3fa28bd36b
--- /dev/null
+++ b/providers/implementations/macs/blake2s_mac.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Constants */
+#define BLAKE2_CTX BLAKE2S_CTX
+#define BLAKE2_PARAM BLAKE2S_PARAM
+#define BLAKE2_KEYBYTES BLAKE2S_KEYBYTES
+#define BLAKE2_OUTBYTES BLAKE2S_OUTBYTES
+#define BLAKE2_PERSONALBYTES BLAKE2S_PERSONALBYTES
+#define BLAKE2_SALTBYTES BLAKE2S_SALTBYTES
+#define BLAKE2_BLOCKBYTES BLAKE2S_BLOCKBYTES
+
+/* Function names */
+#define BLAKE2_PARAM_INIT ossl_blake2s_param_init
+#define BLAKE2_INIT_KEY ossl_blake2s_init_key
+#define BLAKE2_UPDATE ossl_blake2s_update
+#define BLAKE2_FINAL ossl_blake2s_final
+#define BLAKE2_PARAM_SET_DIGEST_LENGTH ossl_blake2s_param_set_digest_length
+#define BLAKE2_PARAM_SET_KEY_LENGTH ossl_blake2s_param_set_key_length
+#define BLAKE2_PARAM_SET_PERSONAL ossl_blake2s_param_set_personal
+#define BLAKE2_PARAM_SET_SALT ossl_blake2s_param_set_salt
+
+/* OSSL_DISPATCH symbol */
+#define BLAKE2_FUNCTIONS ossl_blake2smac_functions
+
+#include "blake2_mac_impl.c"
diff --git a/providers/implementations/macs/build.info b/providers/implementations/macs/build.info
new file mode 100644
index 000000000000..35db66bf23bd
--- /dev/null
+++ b/providers/implementations/macs/build.info
@@ -0,0 +1,30 @@
+# We make separate GOAL variables for each algorithm, to make it easy to
+# switch each to the Legacy provider when needed.
+
+$GMAC_GOAL=../../libdefault.a ../../libfips.a
+$HMAC_GOAL=../../libdefault.a ../../libfips.a
+$KMAC_GOAL=../../libdefault.a ../../libfips.a
+$CMAC_GOAL=../../libdefault.a ../../libfips.a
+$BLAKE2_GOAL=../../libdefault.a
+$SIPHASH_GOAL=../../libdefault.a
+$POLY1305_GOAL=../../libdefault.a
+
+SOURCE[$GMAC_GOAL]=gmac_prov.c
+SOURCE[$HMAC_GOAL]=hmac_prov.c
+SOURCE[$KMAC_GOAL]=kmac_prov.c
+
+IF[{- !$disabled{cmac} -}]
+ SOURCE[$CMAC_GOAL]=cmac_prov.c
+ENDIF
+
+IF[{- !$disabled{blake2} -}]
+ SOURCE[$BLAKE2_GOAL]=blake2b_mac.c blake2s_mac.c
+ENDIF
+
+IF[{- !$disabled{siphash} -}]
+ SOURCE[$SIPHASH_GOAL]=siphash_prov.c
+ENDIF
+
+IF[{- !$disabled{poly1305} -}]
+ SOURCE[$POLY1305_GOAL]=poly1305_prov.c
+ENDIF
diff --git a/providers/implementations/macs/cmac_prov.c b/providers/implementations/macs/cmac_prov.c
new file mode 100644
index 000000000000..96da429e844a
--- /dev/null
+++ b/providers/implementations/macs/cmac_prov.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * CMAC low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/evp.h>
+#include <openssl/cmac.h>
+
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/provider_util.h"
+#include "prov/providercommon.h"
+
+/*
+ * Forward declaration of everything implemented here. This is not strictly
+ * necessary for the compiler, but provides an assurance that the signatures
+ * of the functions in the dispatch table are correct.
+ */
+static OSSL_FUNC_mac_newctx_fn cmac_new;
+static OSSL_FUNC_mac_dupctx_fn cmac_dup;
+static OSSL_FUNC_mac_freectx_fn cmac_free;
+static OSSL_FUNC_mac_gettable_ctx_params_fn cmac_gettable_ctx_params;
+static OSSL_FUNC_mac_get_ctx_params_fn cmac_get_ctx_params;
+static OSSL_FUNC_mac_settable_ctx_params_fn cmac_settable_ctx_params;
+static OSSL_FUNC_mac_set_ctx_params_fn cmac_set_ctx_params;
+static OSSL_FUNC_mac_init_fn cmac_init;
+static OSSL_FUNC_mac_update_fn cmac_update;
+static OSSL_FUNC_mac_final_fn cmac_final;
+
+/* local CMAC data */
+
+struct cmac_data_st {
+ void *provctx;
+ CMAC_CTX *ctx;
+ PROV_CIPHER cipher;
+};
+
+static void *cmac_new(void *provctx)
+{
+ struct cmac_data_st *macctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL
+ || (macctx->ctx = CMAC_CTX_new()) == NULL) {
+ OPENSSL_free(macctx);
+ macctx = NULL;
+ } else {
+ macctx->provctx = provctx;
+ }
+
+ return macctx;
+}
+
+static void cmac_free(void *vmacctx)
+{
+ struct cmac_data_st *macctx = vmacctx;
+
+ if (macctx != NULL) {
+ CMAC_CTX_free(macctx->ctx);
+ ossl_prov_cipher_reset(&macctx->cipher);
+ OPENSSL_free(macctx);
+ }
+}
+
+static void *cmac_dup(void *vsrc)
+{
+ struct cmac_data_st *src = vsrc;
+ struct cmac_data_st *dst;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ dst = cmac_new(src->provctx);
+ if (dst == NULL)
+ return NULL;
+ if (!CMAC_CTX_copy(dst->ctx, src->ctx)
+ || !ossl_prov_cipher_copy(&dst->cipher, &src->cipher)) {
+ cmac_free(dst);
+ return NULL;
+ }
+ return dst;
+}
+
+static size_t cmac_size(void *vmacctx)
+{
+ struct cmac_data_st *macctx = vmacctx;
+
+ return EVP_CIPHER_CTX_get_block_size(CMAC_CTX_get0_cipher_ctx(macctx->ctx));
+}
+
+static int cmac_setkey(struct cmac_data_st *macctx,
+ const unsigned char *key, size_t keylen)
+{
+ int rv = CMAC_Init(macctx->ctx, key, keylen,
+ ossl_prov_cipher_cipher(&macctx->cipher),
+ ossl_prov_cipher_engine(&macctx->cipher));
+ ossl_prov_cipher_reset(&macctx->cipher);
+ return rv;
+}
+
+static int cmac_init(void *vmacctx, const unsigned char *key,
+ size_t keylen, const OSSL_PARAM params[])
+{
+ struct cmac_data_st *macctx = vmacctx;
+
+ if (!ossl_prov_is_running() || !cmac_set_ctx_params(macctx, params))
+ return 0;
+ if (key != NULL)
+ return cmac_setkey(macctx, key, keylen);
+ /* Reinitialize the CMAC context */
+ return CMAC_Init(macctx->ctx, NULL, 0, NULL, NULL);
+}
+
+static int cmac_update(void *vmacctx, const unsigned char *data,
+ size_t datalen)
+{
+ struct cmac_data_st *macctx = vmacctx;
+
+ return CMAC_Update(macctx->ctx, data, datalen);
+}
+
+static int cmac_final(void *vmacctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ struct cmac_data_st *macctx = vmacctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ return CMAC_Final(macctx->ctx, out, outl);
+}
+
+static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
+ OSSL_PARAM_size_t(OSSL_MAC_PARAM_BLOCK_SIZE, NULL),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *cmac_gettable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ return known_gettable_ctx_params;
+}
+
+static int cmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL
+ && !OSSL_PARAM_set_size_t(p, cmac_size(vmacctx)))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_BLOCK_SIZE)) != NULL
+ && !OSSL_PARAM_set_size_t(p, cmac_size(vmacctx)))
+ return 0;
+
+ return 1;
+}
+
+static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_CIPHER, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *cmac_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ return known_settable_ctx_params;
+}
+
+/*
+ * ALL parameters should be set before init().
+ */
+static int cmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])
+{
+ struct cmac_data_st *macctx = vmacctx;
+ OSSL_LIB_CTX *ctx = PROV_LIBCTX_OF(macctx->provctx);
+ const OSSL_PARAM *p;
+
+ if (params == NULL)
+ return 1;
+
+ if (!ossl_prov_cipher_load_from_params(&macctx->cipher, params, ctx))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING)
+ return 0;
+ return cmac_setkey(macctx, p->data, p->data_size);
+ }
+ return 1;
+}
+
+const OSSL_DISPATCH ossl_cmac_functions[] = {
+ { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))cmac_new },
+ { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))cmac_dup },
+ { OSSL_FUNC_MAC_FREECTX, (void (*)(void))cmac_free },
+ { OSSL_FUNC_MAC_INIT, (void (*)(void))cmac_init },
+ { OSSL_FUNC_MAC_UPDATE, (void (*)(void))cmac_update },
+ { OSSL_FUNC_MAC_FINAL, (void (*)(void))cmac_final },
+ { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS,
+ (void (*)(void))cmac_gettable_ctx_params },
+ { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))cmac_get_ctx_params },
+ { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
+ (void (*)(void))cmac_settable_ctx_params },
+ { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))cmac_set_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/macs/gmac_prov.c b/providers/implementations/macs/gmac_prov.c
new file mode 100644
index 000000000000..3dd38ecd7ca7
--- /dev/null
+++ b/providers/implementations/macs/gmac_prov.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/provider_util.h"
+#include "prov/providercommon.h"
+
+/*
+ * Forward declaration of everything implemented here. This is not strictly
+ * necessary for the compiler, but provides an assurance that the signatures
+ * of the functions in the dispatch table are correct.
+ */
+static OSSL_FUNC_mac_newctx_fn gmac_new;
+static OSSL_FUNC_mac_dupctx_fn gmac_dup;
+static OSSL_FUNC_mac_freectx_fn gmac_free;
+static OSSL_FUNC_mac_gettable_params_fn gmac_gettable_params;
+static OSSL_FUNC_mac_get_params_fn gmac_get_params;
+static OSSL_FUNC_mac_settable_ctx_params_fn gmac_settable_ctx_params;
+static OSSL_FUNC_mac_set_ctx_params_fn gmac_set_ctx_params;
+static OSSL_FUNC_mac_init_fn gmac_init;
+static OSSL_FUNC_mac_update_fn gmac_update;
+static OSSL_FUNC_mac_final_fn gmac_final;
+
+/* local GMAC pkey structure */
+
+struct gmac_data_st {
+ void *provctx;
+ EVP_CIPHER_CTX *ctx; /* Cipher context */
+ PROV_CIPHER cipher;
+};
+
+static void gmac_free(void *vmacctx)
+{
+ struct gmac_data_st *macctx = vmacctx;
+
+ if (macctx != NULL) {
+ EVP_CIPHER_CTX_free(macctx->ctx);
+ ossl_prov_cipher_reset(&macctx->cipher);
+ OPENSSL_free(macctx);
+ }
+}
+
+static void *gmac_new(void *provctx)
+{
+ struct gmac_data_st *macctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL
+ || (macctx->ctx = EVP_CIPHER_CTX_new()) == NULL) {
+ gmac_free(macctx);
+ return NULL;
+ }
+ macctx->provctx = provctx;
+
+ return macctx;
+}
+
+static void *gmac_dup(void *vsrc)
+{
+ struct gmac_data_st *src = vsrc;
+ struct gmac_data_st *dst;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ dst = gmac_new(src->provctx);
+ if (dst == NULL)
+ return NULL;
+
+ if (!EVP_CIPHER_CTX_copy(dst->ctx, src->ctx)
+ || !ossl_prov_cipher_copy(&dst->cipher, &src->cipher)) {
+ gmac_free(dst);
+ return NULL;
+ }
+ return dst;
+}
+
+static size_t gmac_size(void)
+{
+ return EVP_GCM_TLS_TAG_LEN;
+}
+
+static int gmac_setkey(struct gmac_data_st *macctx,
+ const unsigned char *key, size_t keylen)
+{
+ EVP_CIPHER_CTX *ctx = macctx->ctx;
+
+ if (keylen != (size_t)EVP_CIPHER_CTX_get_key_length(ctx)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL))
+ return 0;
+ return 1;
+}
+
+static int gmac_init(void *vmacctx, const unsigned char *key,
+ size_t keylen, const OSSL_PARAM params[])
+{
+ struct gmac_data_st *macctx = vmacctx;
+
+ if (!ossl_prov_is_running() || !gmac_set_ctx_params(macctx, params))
+ return 0;
+ if (key != NULL)
+ return gmac_setkey(macctx, key, keylen);
+ return EVP_EncryptInit_ex(macctx->ctx, NULL, NULL, NULL, NULL);
+}
+
+static int gmac_update(void *vmacctx, const unsigned char *data,
+ size_t datalen)
+{
+ struct gmac_data_st *macctx = vmacctx;
+ EVP_CIPHER_CTX *ctx = macctx->ctx;
+ int outlen;
+
+ if (datalen == 0)
+ return 1;
+
+ while (datalen > INT_MAX) {
+ if (!EVP_EncryptUpdate(ctx, NULL, &outlen, data, INT_MAX))
+ return 0;
+ data += INT_MAX;
+ datalen -= INT_MAX;
+ }
+ return EVP_EncryptUpdate(ctx, NULL, &outlen, data, datalen);
+}
+
+static int gmac_final(void *vmacctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ struct gmac_data_st *macctx = vmacctx;
+ int hlen = 0;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (!EVP_EncryptFinal_ex(macctx->ctx, out, &hlen))
+ return 0;
+
+ hlen = gmac_size();
+ params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
+ out, (size_t)hlen);
+ if (!EVP_CIPHER_CTX_get_params(macctx->ctx, params))
+ return 0;
+
+ *outl = hlen;
+ return 1;
+}
+
+static const OSSL_PARAM known_gettable_params[] = {
+ OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *gmac_gettable_params(void *provctx)
+{
+ return known_gettable_params;
+}
+
+static int gmac_get_params(OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL)
+ return OSSL_PARAM_set_size_t(p, gmac_size());
+
+ return 1;
+}
+
+static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_CIPHER, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_MAC_PARAM_IV, NULL, 0),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *gmac_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ return known_settable_ctx_params;
+}
+
+/*
+ * ALL parameters should be set before init().
+ */
+static int gmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])
+{
+ struct gmac_data_st *macctx = vmacctx;
+ EVP_CIPHER_CTX *ctx = macctx->ctx;
+ OSSL_LIB_CTX *provctx = PROV_LIBCTX_OF(macctx->provctx);
+ const OSSL_PARAM *p;
+
+ if (params == NULL)
+ return 1;
+ if (ctx == NULL)
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_CIPHER)) != NULL) {
+ if (!ossl_prov_cipher_load_from_params(&macctx->cipher, params, provctx))
+ return 0;
+ if (EVP_CIPHER_get_mode(ossl_prov_cipher_cipher(&macctx->cipher))
+ != EVP_CIPH_GCM_MODE) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
+ return 0;
+ }
+ if (!EVP_EncryptInit_ex(ctx, ossl_prov_cipher_cipher(&macctx->cipher),
+ ossl_prov_cipher_engine(&macctx->cipher), NULL,
+ NULL))
+ return 0;
+ }
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL)
+ if (p->data_type != OSSL_PARAM_OCTET_STRING
+ || !gmac_setkey(macctx, p->data, p->data_size))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_IV)) != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING)
+ return 0;
+
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN,
+ p->data_size, NULL) <= 0
+ || !EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, p->data))
+ return 0;
+ }
+ return 1;
+}
+
+const OSSL_DISPATCH ossl_gmac_functions[] = {
+ { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))gmac_new },
+ { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))gmac_dup },
+ { OSSL_FUNC_MAC_FREECTX, (void (*)(void))gmac_free },
+ { OSSL_FUNC_MAC_INIT, (void (*)(void))gmac_init },
+ { OSSL_FUNC_MAC_UPDATE, (void (*)(void))gmac_update },
+ { OSSL_FUNC_MAC_FINAL, (void (*)(void))gmac_final },
+ { OSSL_FUNC_MAC_GETTABLE_PARAMS, (void (*)(void))gmac_gettable_params },
+ { OSSL_FUNC_MAC_GET_PARAMS, (void (*)(void))gmac_get_params },
+ { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
+ (void (*)(void))gmac_settable_ctx_params },
+ { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))gmac_set_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/macs/hmac_prov.c b/providers/implementations/macs/hmac_prov.c
new file mode 100644
index 000000000000..52ebb08b8f62
--- /dev/null
+++ b/providers/implementations/macs/hmac_prov.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * HMAC low level APIs are deprecated for public use, but still ok for internal
+ * use.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h>
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/provider_util.h"
+#include "prov/providercommon.h"
+
+/*
+ * Forward declaration of everything implemented here. This is not strictly
+ * necessary for the compiler, but provides an assurance that the signatures
+ * of the functions in the dispatch table are correct.
+ */
+static OSSL_FUNC_mac_newctx_fn hmac_new;
+static OSSL_FUNC_mac_dupctx_fn hmac_dup;
+static OSSL_FUNC_mac_freectx_fn hmac_free;
+static OSSL_FUNC_mac_gettable_ctx_params_fn hmac_gettable_ctx_params;
+static OSSL_FUNC_mac_get_ctx_params_fn hmac_get_ctx_params;
+static OSSL_FUNC_mac_settable_ctx_params_fn hmac_settable_ctx_params;
+static OSSL_FUNC_mac_set_ctx_params_fn hmac_set_ctx_params;
+static OSSL_FUNC_mac_init_fn hmac_init;
+static OSSL_FUNC_mac_update_fn hmac_update;
+static OSSL_FUNC_mac_final_fn hmac_final;
+
+/* local HMAC context structure */
+
+/* typedef EVP_MAC_IMPL */
+struct hmac_data_st {
+ void *provctx;
+ HMAC_CTX *ctx; /* HMAC context */
+ PROV_DIGEST digest;
+ unsigned char *key;
+ size_t keylen;
+ /* Length of full TLS record including the MAC and any padding */
+ size_t tls_data_size;
+ unsigned char tls_header[13];
+ int tls_header_set;
+ unsigned char tls_mac_out[EVP_MAX_MD_SIZE];
+ size_t tls_mac_out_size;
+};
+
+/* Defined in ssl/s3_cbc.c */
+int ssl3_cbc_digest_record(const EVP_MD *md,
+ unsigned char *md_out,
+ size_t *md_out_size,
+ const unsigned char header[13],
+ const unsigned char *data,
+ size_t data_size,
+ size_t data_plus_mac_plus_padding_size,
+ const unsigned char *mac_secret,
+ size_t mac_secret_length, char is_sslv3);
+
+static void *hmac_new(void *provctx)
+{
+ struct hmac_data_st *macctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL
+ || (macctx->ctx = HMAC_CTX_new()) == NULL) {
+ OPENSSL_free(macctx);
+ return NULL;
+ }
+ macctx->provctx = provctx;
+
+ return macctx;
+}
+
+static void hmac_free(void *vmacctx)
+{
+ struct hmac_data_st *macctx = vmacctx;
+
+ if (macctx != NULL) {
+ HMAC_CTX_free(macctx->ctx);
+ ossl_prov_digest_reset(&macctx->digest);
+ OPENSSL_secure_clear_free(macctx->key, macctx->keylen);
+ OPENSSL_free(macctx);
+ }
+}
+
+static void *hmac_dup(void *vsrc)
+{
+ struct hmac_data_st *src = vsrc;
+ struct hmac_data_st *dst;
+ HMAC_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+ dst = hmac_new(src->provctx);
+ if (dst == NULL)
+ return NULL;
+
+ ctx = dst->ctx;
+ *dst = *src;
+ dst->ctx = ctx;
+ dst->key = NULL;
+ memset(&dst->digest, 0, sizeof(dst->digest));
+
+ if (!HMAC_CTX_copy(dst->ctx, src->ctx)
+ || !ossl_prov_digest_copy(&dst->digest, &src->digest)) {
+ hmac_free(dst);
+ return NULL;
+ }
+ if (src->key != NULL) {
+ /* There is no "secure" OPENSSL_memdup */
+ dst->key = OPENSSL_secure_malloc(src->keylen > 0 ? src->keylen : 1);
+ if (dst->key == NULL) {
+ hmac_free(dst);
+ return 0;
+ }
+ memcpy(dst->key, src->key, src->keylen);
+ }
+ return dst;
+}
+
+static size_t hmac_size(struct hmac_data_st *macctx)
+{
+ return HMAC_size(macctx->ctx);
+}
+
+static int hmac_block_size(struct hmac_data_st *macctx)
+{
+ const EVP_MD *md = ossl_prov_digest_md(&macctx->digest);
+
+ if (md == NULL)
+ return 0;
+ return EVP_MD_block_size(md);
+}
+
+static int hmac_setkey(struct hmac_data_st *macctx,
+ const unsigned char *key, size_t keylen)
+{
+ const EVP_MD *digest;
+
+ if (macctx->key != NULL)
+ OPENSSL_secure_clear_free(macctx->key, macctx->keylen);
+ /* Keep a copy of the key in case we need it for TLS HMAC */
+ macctx->key = OPENSSL_secure_malloc(keylen > 0 ? keylen : 1);
+ if (macctx->key == NULL)
+ return 0;
+ memcpy(macctx->key, key, keylen);
+ macctx->keylen = keylen;
+
+ digest = ossl_prov_digest_md(&macctx->digest);
+ /* HMAC_Init_ex doesn't tolerate all zero params, so we must be careful */
+ if (key != NULL || (macctx->tls_data_size == 0 && digest != NULL))
+ return HMAC_Init_ex(macctx->ctx, key, keylen, digest,
+ ossl_prov_digest_engine(&macctx->digest));
+ return 1;
+}
+
+static int hmac_init(void *vmacctx, const unsigned char *key,
+ size_t keylen, const OSSL_PARAM params[])
+{
+ struct hmac_data_st *macctx = vmacctx;
+
+ if (!ossl_prov_is_running() || !hmac_set_ctx_params(macctx, params))
+ return 0;
+
+ if (key != NULL)
+ return hmac_setkey(macctx, key, keylen);
+
+ /* Just reinit the HMAC context */
+ return HMAC_Init_ex(macctx->ctx, NULL, 0, NULL, NULL);
+}
+
+static int hmac_update(void *vmacctx, const unsigned char *data,
+ size_t datalen)
+{
+ struct hmac_data_st *macctx = vmacctx;
+
+ if (macctx->tls_data_size > 0) {
+ /* We're doing a TLS HMAC */
+ if (!macctx->tls_header_set) {
+ /* We expect the first update call to contain the TLS header */
+ if (datalen != sizeof(macctx->tls_header))
+ return 0;
+ memcpy(macctx->tls_header, data, datalen);
+ macctx->tls_header_set = 1;
+ return 1;
+ }
+ /* macctx->tls_data_size is datalen plus the padding length */
+ if (macctx->tls_data_size < datalen)
+ return 0;
+
+ return ssl3_cbc_digest_record(ossl_prov_digest_md(&macctx->digest),
+ macctx->tls_mac_out,
+ &macctx->tls_mac_out_size,
+ macctx->tls_header,
+ data,
+ datalen,
+ macctx->tls_data_size,
+ macctx->key,
+ macctx->keylen,
+ 0);
+ }
+
+ return HMAC_Update(macctx->ctx, data, datalen);
+}
+
+static int hmac_final(void *vmacctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ unsigned int hlen;
+ struct hmac_data_st *macctx = vmacctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+ if (macctx->tls_data_size > 0) {
+ if (macctx->tls_mac_out_size == 0)
+ return 0;
+ if (outl != NULL)
+ *outl = macctx->tls_mac_out_size;
+ memcpy(out, macctx->tls_mac_out, macctx->tls_mac_out_size);
+ return 1;
+ }
+ if (!HMAC_Final(macctx->ctx, out, &hlen))
+ return 0;
+ *outl = hlen;
+ return 1;
+}
+
+static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
+ OSSL_PARAM_size_t(OSSL_MAC_PARAM_BLOCK_SIZE, NULL),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *hmac_gettable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ return known_gettable_ctx_params;
+}
+
+static int hmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[])
+{
+ struct hmac_data_st *macctx = vmacctx;
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL
+ && !OSSL_PARAM_set_size_t(p, hmac_size(macctx)))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_BLOCK_SIZE)) != NULL
+ && !OSSL_PARAM_set_int(p, hmac_block_size(macctx)))
+ return 0;
+
+ return 1;
+}
+
+static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),
+ OSSL_PARAM_int(OSSL_MAC_PARAM_DIGEST_NOINIT, NULL),
+ OSSL_PARAM_int(OSSL_MAC_PARAM_DIGEST_ONESHOT, NULL),
+ OSSL_PARAM_size_t(OSSL_MAC_PARAM_TLS_DATA_SIZE, NULL),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *hmac_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ return known_settable_ctx_params;
+}
+
+static int set_flag(const OSSL_PARAM params[], const char *key, int mask,
+ int *flags)
+{
+ const OSSL_PARAM *p = OSSL_PARAM_locate_const(params, key);
+ int flag = 0;
+
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_int(p, &flag))
+ return 0;
+ if (flag == 0)
+ *flags &= ~mask;
+ else
+ *flags |= mask;
+ }
+ return 1;
+}
+
+/*
+ * ALL parameters should be set before init().
+ */
+static int hmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])
+{
+ struct hmac_data_st *macctx = vmacctx;
+ OSSL_LIB_CTX *ctx = PROV_LIBCTX_OF(macctx->provctx);
+ const OSSL_PARAM *p;
+ int flags = 0;
+
+ if (params == NULL)
+ return 1;
+
+ if (!ossl_prov_digest_load_from_params(&macctx->digest, params, ctx))
+ return 0;
+
+ if (!set_flag(params, OSSL_MAC_PARAM_DIGEST_NOINIT, EVP_MD_CTX_FLAG_NO_INIT,
+ &flags))
+ return 0;
+ if (!set_flag(params, OSSL_MAC_PARAM_DIGEST_ONESHOT, EVP_MD_CTX_FLAG_ONESHOT,
+ &flags))
+ return 0;
+ if (flags)
+ HMAC_CTX_set_flags(macctx->ctx, flags);
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING)
+ return 0;
+ if (!hmac_setkey(macctx, p->data, p->data_size))
+ return 0;
+ }
+
+ if ((p = OSSL_PARAM_locate_const(params,
+ OSSL_MAC_PARAM_TLS_DATA_SIZE)) != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &macctx->tls_data_size))
+ return 0;
+ }
+ return 1;
+}
+
+const OSSL_DISPATCH ossl_hmac_functions[] = {
+ { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))hmac_new },
+ { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))hmac_dup },
+ { OSSL_FUNC_MAC_FREECTX, (void (*)(void))hmac_free },
+ { OSSL_FUNC_MAC_INIT, (void (*)(void))hmac_init },
+ { OSSL_FUNC_MAC_UPDATE, (void (*)(void))hmac_update },
+ { OSSL_FUNC_MAC_FINAL, (void (*)(void))hmac_final },
+ { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS,
+ (void (*)(void))hmac_gettable_ctx_params },
+ { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))hmac_get_ctx_params },
+ { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
+ (void (*)(void))hmac_settable_ctx_params },
+ { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))hmac_set_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/macs/kmac_prov.c b/providers/implementations/macs/kmac_prov.c
new file mode 100644
index 000000000000..b2f85398b4e2
--- /dev/null
+++ b/providers/implementations/macs/kmac_prov.c
@@ -0,0 +1,627 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * See SP800-185 "Appendix A - KMAC, .... in Terms of Keccak[c]"
+ *
+ * Inputs are:
+ * K = Key (len(K) < 2^2040 bits)
+ * X = Input
+ * L = Output length (0 <= L < 2^2040 bits)
+ * S = Customization String Default="" (len(S) < 2^2040 bits)
+ *
+ * KMAC128(K, X, L, S)
+ * {
+ * newX = bytepad(encode_string(K), 168) || X || right_encode(L).
+ * T = bytepad(encode_string("KMAC") || encode_string(S), 168).
+ * return KECCAK[256](T || newX || 00, L).
+ * }
+ *
+ * KMAC256(K, X, L, S)
+ * {
+ * newX = bytepad(encode_string(K), 136) || X || right_encode(L).
+ * T = bytepad(encode_string("KMAC") || encode_string(S), 136).
+ * return KECCAK[512](T || newX || 00, L).
+ * }
+ *
+ * KMAC128XOF(K, X, L, S)
+ * {
+ * newX = bytepad(encode_string(K), 168) || X || right_encode(0).
+ * T = bytepad(encode_string("KMAC") || encode_string(S), 168).
+ * return KECCAK[256](T || newX || 00, L).
+ * }
+ *
+ * KMAC256XOF(K, X, L, S)
+ * {
+ * newX = bytepad(encode_string(K), 136) || X || right_encode(0).
+ * T = bytepad(encode_string("KMAC") || encode_string(S), 136).
+ * return KECCAK[512](T || newX || 00, L).
+ * }
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/provider_util.h"
+#include "prov/providercommon.h"
+#include "internal/cryptlib.h" /* ossl_assert */
+
+/*
+ * Forward declaration of everything implemented here. This is not strictly
+ * necessary for the compiler, but provides an assurance that the signatures
+ * of the functions in the dispatch table are correct.
+ */
+static OSSL_FUNC_mac_newctx_fn kmac128_new;
+static OSSL_FUNC_mac_newctx_fn kmac256_new;
+static OSSL_FUNC_mac_dupctx_fn kmac_dup;
+static OSSL_FUNC_mac_freectx_fn kmac_free;
+static OSSL_FUNC_mac_gettable_ctx_params_fn kmac_gettable_ctx_params;
+static OSSL_FUNC_mac_get_ctx_params_fn kmac_get_ctx_params;
+static OSSL_FUNC_mac_settable_ctx_params_fn kmac_settable_ctx_params;
+static OSSL_FUNC_mac_set_ctx_params_fn kmac_set_ctx_params;
+static OSSL_FUNC_mac_init_fn kmac_init;
+static OSSL_FUNC_mac_update_fn kmac_update;
+static OSSL_FUNC_mac_final_fn kmac_final;
+
+#define KMAC_MAX_BLOCKSIZE ((1600 - 128 * 2) / 8) /* 168 */
+
+/*
+ * Length encoding will be a 1 byte size + length in bits (3 bytes max)
+ * This gives a range of 0..0XFFFFFF bits = 2097151 bytes).
+ */
+#define KMAC_MAX_OUTPUT_LEN (0xFFFFFF / 8)
+#define KMAC_MAX_ENCODED_HEADER_LEN (1 + 3)
+
+/*
+ * Restrict the maximum length of the customisation string. This must not
+ * exceed 64 bits = 8k bytes.
+ */
+#define KMAC_MAX_CUSTOM 512
+
+/* Maximum size of encoded custom string */
+#define KMAC_MAX_CUSTOM_ENCODED (KMAC_MAX_CUSTOM + KMAC_MAX_ENCODED_HEADER_LEN)
+
+/* Maximum key size in bytes = 512 (4096 bits) */
+#define KMAC_MAX_KEY 512
+#define KMAC_MIN_KEY 4
+
+/*
+ * Maximum Encoded Key size will be padded to a multiple of the blocksize
+ * i.e KMAC_MAX_KEY + KMAC_MAX_ENCODED_HEADER_LEN = 512 + 4
+ * Padded to a multiple of KMAC_MAX_BLOCKSIZE
+ */
+#define KMAC_MAX_KEY_ENCODED (KMAC_MAX_BLOCKSIZE * 4)
+
+/* Fixed value of encode_string("KMAC") */
+static const unsigned char kmac_string[] = {
+ 0x01, 0x20, 0x4B, 0x4D, 0x41, 0x43
+};
+
+#define KMAC_FLAG_XOF_MODE 1
+
+struct kmac_data_st {
+ void *provctx;
+ EVP_MD_CTX *ctx;
+ PROV_DIGEST digest;
+ size_t out_len;
+ size_t key_len;
+ size_t custom_len;
+ /* If xof_mode = 1 then we use right_encode(0) */
+ int xof_mode;
+ /* key and custom are stored in encoded form */
+ unsigned char key[KMAC_MAX_KEY_ENCODED];
+ unsigned char custom[KMAC_MAX_CUSTOM_ENCODED];
+};
+
+static int encode_string(unsigned char *out, size_t out_max_len, size_t *out_len,
+ const unsigned char *in, size_t in_len);
+static int right_encode(unsigned char *out, size_t out_max_len, size_t *out_len,
+ size_t bits);
+static int bytepad(unsigned char *out, size_t *out_len,
+ const unsigned char *in1, size_t in1_len,
+ const unsigned char *in2, size_t in2_len,
+ size_t w);
+static int kmac_bytepad_encode_key(unsigned char *out, size_t out_max_len,
+ size_t *out_len,
+ const unsigned char *in, size_t in_len,
+ size_t w);
+
+static void kmac_free(void *vmacctx)
+{
+ struct kmac_data_st *kctx = vmacctx;
+
+ if (kctx != NULL) {
+ EVP_MD_CTX_free(kctx->ctx);
+ ossl_prov_digest_reset(&kctx->digest);
+ OPENSSL_cleanse(kctx->key, kctx->key_len);
+ OPENSSL_cleanse(kctx->custom, kctx->custom_len);
+ OPENSSL_free(kctx);
+ }
+}
+
+/*
+ * We have KMAC implemented as a hash, which we can use instead of
+ * reimplementing the EVP functionality with direct use of
+ * keccak_mac_init() and friends.
+ */
+static struct kmac_data_st *kmac_new(void *provctx)
+{
+ struct kmac_data_st *kctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL
+ || (kctx->ctx = EVP_MD_CTX_new()) == NULL) {
+ kmac_free(kctx);
+ return NULL;
+ }
+ kctx->provctx = provctx;
+ return kctx;
+}
+
+static void *kmac_fetch_new(void *provctx, const OSSL_PARAM *params)
+{
+ struct kmac_data_st *kctx = kmac_new(provctx);
+
+ if (kctx == NULL)
+ return 0;
+ if (!ossl_prov_digest_load_from_params(&kctx->digest, params,
+ PROV_LIBCTX_OF(provctx))) {
+ kmac_free(kctx);
+ return 0;
+ }
+
+ kctx->out_len = EVP_MD_get_size(ossl_prov_digest_md(&kctx->digest));
+ return kctx;
+}
+
+static void *kmac128_new(void *provctx)
+{
+ static const OSSL_PARAM kmac128_params[] = {
+ OSSL_PARAM_utf8_string("digest", OSSL_DIGEST_NAME_KECCAK_KMAC128,
+ sizeof(OSSL_DIGEST_NAME_KECCAK_KMAC128)),
+ OSSL_PARAM_END
+ };
+ return kmac_fetch_new(provctx, kmac128_params);
+}
+
+static void *kmac256_new(void *provctx)
+{
+ static const OSSL_PARAM kmac256_params[] = {
+ OSSL_PARAM_utf8_string("digest", OSSL_DIGEST_NAME_KECCAK_KMAC256,
+ sizeof(OSSL_DIGEST_NAME_KECCAK_KMAC256)),
+ OSSL_PARAM_END
+ };
+ return kmac_fetch_new(provctx, kmac256_params);
+}
+
+static void *kmac_dup(void *vsrc)
+{
+ struct kmac_data_st *src = vsrc;
+ struct kmac_data_st *dst;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ dst = kmac_new(src->provctx);
+ if (dst == NULL)
+ return NULL;
+
+ if (!EVP_MD_CTX_copy(dst->ctx, src->ctx)
+ || !ossl_prov_digest_copy(&dst->digest, &src->digest)) {
+ kmac_free(dst);
+ return NULL;
+ }
+
+ dst->out_len = src->out_len;
+ dst->key_len = src->key_len;
+ dst->custom_len = src->custom_len;
+ dst->xof_mode = src->xof_mode;
+ memcpy(dst->key, src->key, src->key_len);
+ memcpy(dst->custom, src->custom, dst->custom_len);
+
+ return dst;
+}
+
+static int kmac_setkey(struct kmac_data_st *kctx, const unsigned char *key,
+ size_t keylen)
+{
+ const EVP_MD *digest = ossl_prov_digest_md(&kctx->digest);
+ int w = EVP_MD_get_block_size(digest);
+
+ if (keylen < KMAC_MIN_KEY || keylen > KMAC_MAX_KEY) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ if (w < 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
+ return 0;
+ }
+ if (!kmac_bytepad_encode_key(kctx->key, sizeof(kctx->key), &kctx->key_len,
+ key, keylen, (size_t)w))
+ return 0;
+ return 1;
+}
+
+/*
+ * The init() assumes that any ctrl methods are set beforehand for
+ * md, key and custom. Setting the fields afterwards will have no
+ * effect on the output mac.
+ */
+static int kmac_init(void *vmacctx, const unsigned char *key,
+ size_t keylen, const OSSL_PARAM params[])
+{
+ struct kmac_data_st *kctx = vmacctx;
+ EVP_MD_CTX *ctx = kctx->ctx;
+ unsigned char *out;
+ size_t out_len, block_len;
+ int res, t;
+
+ if (!ossl_prov_is_running() || !kmac_set_ctx_params(kctx, params))
+ return 0;
+
+ if (key != NULL) {
+ if (!kmac_setkey(kctx, key, keylen))
+ return 0;
+ } else if (kctx->key_len == 0) {
+ /* Check key has been set */
+ ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
+ return 0;
+ }
+ if (!EVP_DigestInit_ex(kctx->ctx, ossl_prov_digest_md(&kctx->digest),
+ NULL))
+ return 0;
+
+ t = EVP_MD_get_block_size(ossl_prov_digest_md(&kctx->digest));
+ if (t < 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
+ return 0;
+ }
+ block_len = t;
+
+ /* Set default custom string if it is not already set */
+ if (kctx->custom_len == 0) {
+ const OSSL_PARAM cparams[] = {
+ OSSL_PARAM_octet_string(OSSL_MAC_PARAM_CUSTOM, "", 0),
+ OSSL_PARAM_END
+ };
+ (void)kmac_set_ctx_params(kctx, cparams);
+ }
+
+ if (!bytepad(NULL, &out_len, kmac_string, sizeof(kmac_string),
+ kctx->custom, kctx->custom_len, block_len)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ out = OPENSSL_malloc(out_len);
+ if (out == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ res = bytepad(out, NULL, kmac_string, sizeof(kmac_string),
+ kctx->custom, kctx->custom_len, block_len)
+ && EVP_DigestUpdate(ctx, out, out_len)
+ && EVP_DigestUpdate(ctx, kctx->key, kctx->key_len);
+ OPENSSL_free(out);
+ return res;
+}
+
+static int kmac_update(void *vmacctx, const unsigned char *data,
+ size_t datalen)
+{
+ struct kmac_data_st *kctx = vmacctx;
+
+ return EVP_DigestUpdate(kctx->ctx, data, datalen);
+}
+
+static int kmac_final(void *vmacctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ struct kmac_data_st *kctx = vmacctx;
+ EVP_MD_CTX *ctx = kctx->ctx;
+ size_t lbits, len;
+ unsigned char encoded_outlen[KMAC_MAX_ENCODED_HEADER_LEN];
+ int ok;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ /* KMAC XOF mode sets the encoded length to 0 */
+ lbits = (kctx->xof_mode ? 0 : (kctx->out_len * 8));
+
+ ok = right_encode(encoded_outlen, sizeof(encoded_outlen), &len, lbits)
+ && EVP_DigestUpdate(ctx, encoded_outlen, len)
+ && EVP_DigestFinalXOF(ctx, out, kctx->out_len);
+ *outl = kctx->out_len;
+ return ok;
+}
+
+static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
+ OSSL_PARAM_size_t(OSSL_MAC_PARAM_BLOCK_SIZE, NULL),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *kmac_gettable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ return known_gettable_ctx_params;
+}
+
+static int kmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[])
+{
+ struct kmac_data_st *kctx = vmacctx;
+ OSSL_PARAM *p;
+ int sz;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL
+ && !OSSL_PARAM_set_size_t(p, kctx->out_len))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_BLOCK_SIZE)) != NULL) {
+ sz = EVP_MD_block_size(ossl_prov_digest_md(&kctx->digest));
+ if (!OSSL_PARAM_set_int(p, sz))
+ return 0;
+ }
+
+ return 1;
+}
+
+static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_int(OSSL_MAC_PARAM_XOF, NULL),
+ OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
+ OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_MAC_PARAM_CUSTOM, NULL, 0),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *kmac_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ return known_settable_ctx_params;
+}
+
+/*
+ * The following params can be set any time before final():
+ * - "outlen" or "size": The requested output length.
+ * - "xof": If set, this indicates that right_encoded(0)
+ * is part of the digested data, otherwise it
+ * uses right_encoded(requested output length).
+ *
+ * All other params should be set before init().
+ */
+static int kmac_set_ctx_params(void *vmacctx, const OSSL_PARAM *params)
+{
+ struct kmac_data_st *kctx = vmacctx;
+ const OSSL_PARAM *p;
+
+ if (params == NULL)
+ return 1;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_XOF)) != NULL
+ && !OSSL_PARAM_get_int(p, &kctx->xof_mode))
+ return 0;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_SIZE)) != NULL) {
+ size_t sz = 0;
+
+ if (!OSSL_PARAM_get_size_t(p, &sz))
+ return 0;
+ if (sz > KMAC_MAX_OUTPUT_LEN) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH);
+ return 0;
+ }
+ kctx->out_len = sz;
+ }
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL
+ && !kmac_setkey(kctx, p->data, p->data_size))
+ return 0;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_CUSTOM))
+ != NULL) {
+ if (p->data_size > KMAC_MAX_CUSTOM) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CUSTOM_LENGTH);
+ return 0;
+ }
+ if (!encode_string(kctx->custom, sizeof(kctx->custom), &kctx->custom_len,
+ p->data, p->data_size))
+ return 0;
+ }
+ return 1;
+}
+
+/* Encoding/Padding Methods. */
+
+/* Returns the number of bytes required to store 'bits' into a byte array */
+static unsigned int get_encode_size(size_t bits)
+{
+ unsigned int cnt = 0, sz = sizeof(size_t);
+
+ while (bits && (cnt < sz)) {
+ ++cnt;
+ bits >>= 8;
+ }
+ /* If bits is zero 1 byte is required */
+ if (cnt == 0)
+ cnt = 1;
+ return cnt;
+}
+
+/*
+ * Convert an integer into bytes . The number of bytes is appended
+ * to the end of the buffer. Returns an array of bytes 'out' of size
+ * *out_len.
+ *
+ * e.g if bits = 32, out[2] = { 0x20, 0x01 }
+ */
+static int right_encode(unsigned char *out, size_t out_max_len, size_t *out_len,
+ size_t bits)
+{
+ unsigned int len = get_encode_size(bits);
+ int i;
+
+ if (len >= out_max_len) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE);
+ return 0;
+ }
+
+ /* MSB's are at the start of the bytes array */
+ for (i = len - 1; i >= 0; --i) {
+ out[i] = (unsigned char)(bits & 0xFF);
+ bits >>= 8;
+ }
+ /* Tack the length onto the end */
+ out[len] = (unsigned char)len;
+
+ /* The Returned length includes the tacked on byte */
+ *out_len = len + 1;
+ return 1;
+}
+
+/*
+ * Encodes a string with a left encoded length added. Note that the
+ * in_len is converted to bits (*8).
+ *
+ * e.g- in="KMAC" gives out[6] = { 0x01, 0x20, 0x4B, 0x4D, 0x41, 0x43 }
+ * len bits K M A C
+ */
+static int encode_string(unsigned char *out, size_t out_max_len, size_t *out_len,
+ const unsigned char *in, size_t in_len)
+{
+ if (in == NULL) {
+ *out_len = 0;
+ } else {
+ size_t i, bits, len, sz;
+
+ bits = 8 * in_len;
+ len = get_encode_size(bits);
+ sz = 1 + len + in_len;
+
+ if (sz > out_max_len) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE);
+ return 0;
+ }
+
+ out[0] = (unsigned char)len;
+ for (i = len; i > 0; --i) {
+ out[i] = (bits & 0xFF);
+ bits >>= 8;
+ }
+ memcpy(out + len + 1, in, in_len);
+ *out_len = sz;
+ }
+ return 1;
+}
+
+/*
+ * Returns a zero padded encoding of the inputs in1 and an optional
+ * in2 (can be NULL). The padded output must be a multiple of the blocksize 'w'.
+ * The value of w is in bytes (< 256).
+ *
+ * The returned output is:
+ * zero_padded(multiple of w, (left_encode(w) || in1 [|| in2])
+ */
+static int bytepad(unsigned char *out, size_t *out_len,
+ const unsigned char *in1, size_t in1_len,
+ const unsigned char *in2, size_t in2_len, size_t w)
+{
+ int len;
+ unsigned char *p = out;
+ int sz = w;
+
+ if (out == NULL) {
+ if (out_len == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ sz = 2 + in1_len + (in2 != NULL ? in2_len : 0);
+ *out_len = (sz + w - 1) / w * w;
+ return 1;
+ }
+
+ if (!ossl_assert(w <= 255))
+ return 0;
+
+ /* Left encoded w */
+ *p++ = 1;
+ *p++ = (unsigned char)w;
+ /* || in1 */
+ memcpy(p, in1, in1_len);
+ p += in1_len;
+ /* [ || in2 ] */
+ if (in2 != NULL && in2_len > 0) {
+ memcpy(p, in2, in2_len);
+ p += in2_len;
+ }
+ /* Figure out the pad size (divisible by w) */
+ len = p - out;
+ sz = (len + w - 1) / w * w;
+ /* zero pad the end of the buffer */
+ if (sz != len)
+ memset(p, 0, sz - len);
+ if (out_len != NULL)
+ *out_len = sz;
+ return 1;
+}
+
+/* Returns out = bytepad(encode_string(in), w) */
+static int kmac_bytepad_encode_key(unsigned char *out, size_t out_max_len,
+ size_t *out_len,
+ const unsigned char *in, size_t in_len,
+ size_t w)
+{
+ unsigned char tmp[KMAC_MAX_KEY + KMAC_MAX_ENCODED_HEADER_LEN];
+ size_t tmp_len;
+
+ if (!encode_string(tmp, sizeof(tmp), &tmp_len, in, in_len))
+ return 0;
+ if (!bytepad(NULL, out_len, tmp, tmp_len, NULL, 0, w))
+ return 0;
+ if (!ossl_assert(*out_len <= out_max_len))
+ return 0;
+ return bytepad(out, NULL, tmp, tmp_len, NULL, 0, w);
+}
+
+const OSSL_DISPATCH ossl_kmac128_functions[] = {
+ { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))kmac128_new },
+ { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))kmac_dup },
+ { OSSL_FUNC_MAC_FREECTX, (void (*)(void))kmac_free },
+ { OSSL_FUNC_MAC_INIT, (void (*)(void))kmac_init },
+ { OSSL_FUNC_MAC_UPDATE, (void (*)(void))kmac_update },
+ { OSSL_FUNC_MAC_FINAL, (void (*)(void))kmac_final },
+ { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS,
+ (void (*)(void))kmac_gettable_ctx_params },
+ { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))kmac_get_ctx_params },
+ { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
+ (void (*)(void))kmac_settable_ctx_params },
+ { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))kmac_set_ctx_params },
+ { 0, NULL }
+};
+
+const OSSL_DISPATCH ossl_kmac256_functions[] = {
+ { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))kmac256_new },
+ { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))kmac_dup },
+ { OSSL_FUNC_MAC_FREECTX, (void (*)(void))kmac_free },
+ { OSSL_FUNC_MAC_INIT, (void (*)(void))kmac_init },
+ { OSSL_FUNC_MAC_UPDATE, (void (*)(void))kmac_update },
+ { OSSL_FUNC_MAC_FINAL, (void (*)(void))kmac_final },
+ { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS,
+ (void (*)(void))kmac_gettable_ctx_params },
+ { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))kmac_get_ctx_params },
+ { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
+ (void (*)(void))kmac_settable_ctx_params },
+ { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))kmac_set_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/macs/poly1305_prov.c b/providers/implementations/macs/poly1305_prov.c
new file mode 100644
index 000000000000..f922802ea79c
--- /dev/null
+++ b/providers/implementations/macs/poly1305_prov.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+
+#include "crypto/poly1305.h"
+
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+/*
+ * Forward declaration of everything implemented here. This is not strictly
+ * necessary for the compiler, but provides an assurance that the signatures
+ * of the functions in the dispatch table are correct.
+ */
+static OSSL_FUNC_mac_newctx_fn poly1305_new;
+static OSSL_FUNC_mac_dupctx_fn poly1305_dup;
+static OSSL_FUNC_mac_freectx_fn poly1305_free;
+static OSSL_FUNC_mac_gettable_params_fn poly1305_gettable_params;
+static OSSL_FUNC_mac_get_params_fn poly1305_get_params;
+static OSSL_FUNC_mac_settable_ctx_params_fn poly1305_settable_ctx_params;
+static OSSL_FUNC_mac_set_ctx_params_fn poly1305_set_ctx_params;
+static OSSL_FUNC_mac_init_fn poly1305_init;
+static OSSL_FUNC_mac_update_fn poly1305_update;
+static OSSL_FUNC_mac_final_fn poly1305_final;
+
+struct poly1305_data_st {
+ void *provctx;
+ int updated;
+ POLY1305 poly1305; /* Poly1305 data */
+};
+
+static void *poly1305_new(void *provctx)
+{
+ struct poly1305_data_st *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx != NULL)
+ ctx->provctx = provctx;
+ return ctx;
+}
+
+static void poly1305_free(void *vmacctx)
+{
+ OPENSSL_free(vmacctx);
+}
+
+static void *poly1305_dup(void *vsrc)
+{
+ struct poly1305_data_st *src = vsrc;
+ struct poly1305_data_st *dst;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+ dst = OPENSSL_malloc(sizeof(*dst));
+ if (dst == NULL)
+ return NULL;
+
+ *dst = *src;
+ return dst;
+}
+
+static size_t poly1305_size(void)
+{
+ return POLY1305_DIGEST_SIZE;
+}
+
+static int poly1305_setkey(struct poly1305_data_st *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ if (keylen != POLY1305_KEY_SIZE) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ Poly1305_Init(&ctx->poly1305, key);
+ ctx->updated = 0;
+ return 1;
+}
+
+static int poly1305_init(void *vmacctx, const unsigned char *key,
+ size_t keylen, const OSSL_PARAM params[])
+{
+ struct poly1305_data_st *ctx = vmacctx;
+
+ /* initialize the context in MAC_ctrl function */
+ if (!ossl_prov_is_running() || !poly1305_set_ctx_params(ctx, params))
+ return 0;
+ if (key != NULL)
+ return poly1305_setkey(ctx, key, keylen);
+ /* no reinitialization of context with the same key is allowed */
+ return ctx->updated == 0;
+}
+
+static int poly1305_update(void *vmacctx, const unsigned char *data,
+ size_t datalen)
+{
+ struct poly1305_data_st *ctx = vmacctx;
+
+ ctx->updated = 1;
+ if (datalen == 0)
+ return 1;
+
+ /* poly1305 has nothing to return in its update function */
+ Poly1305_Update(&ctx->poly1305, data, datalen);
+ return 1;
+}
+
+static int poly1305_final(void *vmacctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ struct poly1305_data_st *ctx = vmacctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+ ctx->updated = 1;
+ Poly1305_Final(&ctx->poly1305, out);
+ *outl = poly1305_size();
+ return 1;
+}
+
+static const OSSL_PARAM known_gettable_params[] = {
+ OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *poly1305_gettable_params(void *provctx)
+{
+ return known_gettable_params;
+}
+
+static int poly1305_get_params(OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL)
+ return OSSL_PARAM_set_size_t(p, poly1305_size());
+
+ return 1;
+}
+
+static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *poly1305_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ return known_settable_ctx_params;
+}
+
+static int poly1305_set_ctx_params(void *vmacctx, const OSSL_PARAM *params)
+{
+ struct poly1305_data_st *ctx = vmacctx;
+ const OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL
+ && !poly1305_setkey(ctx, p->data, p->data_size))
+ return 0;
+ return 1;
+}
+
+const OSSL_DISPATCH ossl_poly1305_functions[] = {
+ { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))poly1305_new },
+ { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))poly1305_dup },
+ { OSSL_FUNC_MAC_FREECTX, (void (*)(void))poly1305_free },
+ { OSSL_FUNC_MAC_INIT, (void (*)(void))poly1305_init },
+ { OSSL_FUNC_MAC_UPDATE, (void (*)(void))poly1305_update },
+ { OSSL_FUNC_MAC_FINAL, (void (*)(void))poly1305_final },
+ { OSSL_FUNC_MAC_GETTABLE_PARAMS, (void (*)(void))poly1305_gettable_params },
+ { OSSL_FUNC_MAC_GET_PARAMS, (void (*)(void))poly1305_get_params },
+ { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
+ (void (*)(void))poly1305_settable_ctx_params },
+ { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))poly1305_set_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/macs/siphash_prov.c b/providers/implementations/macs/siphash_prov.c
new file mode 100644
index 000000000000..a28cdb33ac20
--- /dev/null
+++ b/providers/implementations/macs/siphash_prov.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+
+#include "crypto/siphash.h"
+
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+/*
+ * Forward declaration of everything implemented here. This is not strictly
+ * necessary for the compiler, but provides an assurance that the signatures
+ * of the functions in the dispatch table are correct.
+ */
+static OSSL_FUNC_mac_newctx_fn siphash_new;
+static OSSL_FUNC_mac_dupctx_fn siphash_dup;
+static OSSL_FUNC_mac_freectx_fn siphash_free;
+static OSSL_FUNC_mac_gettable_ctx_params_fn siphash_gettable_ctx_params;
+static OSSL_FUNC_mac_get_ctx_params_fn siphash_get_ctx_params;
+static OSSL_FUNC_mac_settable_ctx_params_fn siphash_settable_ctx_params;
+static OSSL_FUNC_mac_set_ctx_params_fn siphash_set_params;
+static OSSL_FUNC_mac_init_fn siphash_init;
+static OSSL_FUNC_mac_update_fn siphash_update;
+static OSSL_FUNC_mac_final_fn siphash_final;
+
+struct siphash_data_st {
+ void *provctx;
+ SIPHASH siphash; /* Siphash data */
+ SIPHASH sipcopy; /* Siphash data copy for reinitialization */
+ unsigned int crounds, drounds;
+};
+
+static unsigned int crounds(struct siphash_data_st *ctx)
+{
+ return ctx->crounds != 0 ? ctx->crounds : SIPHASH_C_ROUNDS;
+}
+
+static unsigned int drounds(struct siphash_data_st *ctx)
+{
+ return ctx->drounds != 0 ? ctx->drounds : SIPHASH_D_ROUNDS;
+}
+
+static void *siphash_new(void *provctx)
+{
+ struct siphash_data_st *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx != NULL)
+ ctx->provctx = provctx;
+ return ctx;
+}
+
+static void siphash_free(void *vmacctx)
+{
+ OPENSSL_free(vmacctx);
+}
+
+static void *siphash_dup(void *vsrc)
+{
+ struct siphash_data_st *ssrc = vsrc;
+ struct siphash_data_st *sdst;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+ sdst = OPENSSL_malloc(sizeof(*sdst));
+ if (sdst == NULL)
+ return NULL;
+
+ *sdst = *ssrc;
+ return sdst;
+}
+
+static size_t siphash_size(void *vmacctx)
+{
+ struct siphash_data_st *ctx = vmacctx;
+
+ return SipHash_hash_size(&ctx->siphash);
+}
+
+static int siphash_setkey(struct siphash_data_st *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ int ret;
+
+ if (keylen != SIPHASH_KEY_SIZE)
+ return 0;
+ ret = SipHash_Init(&ctx->siphash, key, crounds(ctx), drounds(ctx));
+ if (ret)
+ ctx->sipcopy = ctx->siphash;
+ return ret;
+}
+
+static int siphash_init(void *vmacctx, const unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ struct siphash_data_st *ctx = vmacctx;
+
+ if (!ossl_prov_is_running() || !siphash_set_params(ctx, params))
+ return 0;
+ /*
+ * Without a key, there is not much to do here,
+ * The actual initialization happens through controls.
+ */
+ if (key == NULL) {
+ ctx->siphash = ctx->sipcopy;
+ return 1;
+ }
+ return siphash_setkey(ctx, key, keylen);
+}
+
+static int siphash_update(void *vmacctx, const unsigned char *data,
+ size_t datalen)
+{
+ struct siphash_data_st *ctx = vmacctx;
+
+ if (datalen == 0)
+ return 1;
+
+ SipHash_Update(&ctx->siphash, data, datalen);
+ return 1;
+}
+
+static int siphash_final(void *vmacctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ struct siphash_data_st *ctx = vmacctx;
+ size_t hlen = siphash_size(ctx);
+
+ if (!ossl_prov_is_running() || outsize < hlen)
+ return 0;
+
+ *outl = hlen;
+ return SipHash_Final(&ctx->siphash, out, hlen);
+}
+
+static const OSSL_PARAM *siphash_gettable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
+ OSSL_PARAM_uint(OSSL_MAC_PARAM_C_ROUNDS, NULL),
+ OSSL_PARAM_uint(OSSL_MAC_PARAM_D_ROUNDS, NULL),
+ OSSL_PARAM_END
+ };
+
+ return known_gettable_ctx_params;
+}
+
+static int siphash_get_ctx_params(void *vmacctx, OSSL_PARAM params[])
+{
+ struct siphash_data_st *ctx = vmacctx;
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL
+ && !OSSL_PARAM_set_size_t(p, siphash_size(vmacctx)))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_C_ROUNDS)) != NULL
+ && !OSSL_PARAM_set_uint(p, crounds(ctx)))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_D_ROUNDS)) != NULL
+ && !OSSL_PARAM_set_uint(p, drounds(ctx)))
+ return 0;
+ return 1;
+}
+
+static const OSSL_PARAM *siphash_settable_ctx_params(ossl_unused void *ctx,
+ void *provctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
+ OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),
+ OSSL_PARAM_uint(OSSL_MAC_PARAM_C_ROUNDS, NULL),
+ OSSL_PARAM_uint(OSSL_MAC_PARAM_D_ROUNDS, NULL),
+ OSSL_PARAM_END
+ };
+
+ return known_settable_ctx_params;
+}
+
+static int siphash_set_params(void *vmacctx, const OSSL_PARAM *params)
+{
+ struct siphash_data_st *ctx = vmacctx;
+ const OSSL_PARAM *p = NULL;
+ size_t size;
+
+ if (params == NULL)
+ return 1;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_SIZE)) != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &size)
+ || !SipHash_set_hash_size(&ctx->siphash, size)
+ || !SipHash_set_hash_size(&ctx->sipcopy, size))
+ return 0;
+ }
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_C_ROUNDS)) != NULL
+ && !OSSL_PARAM_get_uint(p, &ctx->crounds))
+ return 0;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_D_ROUNDS)) != NULL
+ && !OSSL_PARAM_get_uint(p, &ctx->drounds))
+ return 0;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL)
+ if (p->data_type != OSSL_PARAM_OCTET_STRING
+ || !siphash_setkey(ctx, p->data, p->data_size))
+ return 0;
+ return 1;
+}
+
+const OSSL_DISPATCH ossl_siphash_functions[] = {
+ { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))siphash_new },
+ { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))siphash_dup },
+ { OSSL_FUNC_MAC_FREECTX, (void (*)(void))siphash_free },
+ { OSSL_FUNC_MAC_INIT, (void (*)(void))siphash_init },
+ { OSSL_FUNC_MAC_UPDATE, (void (*)(void))siphash_update },
+ { OSSL_FUNC_MAC_FINAL, (void (*)(void))siphash_final },
+ { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS,
+ (void (*)(void))siphash_gettable_ctx_params },
+ { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))siphash_get_ctx_params },
+ { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
+ (void (*)(void))siphash_settable_ctx_params },
+ { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))siphash_set_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/rands/build.info b/providers/implementations/rands/build.info
new file mode 100644
index 000000000000..8bcac43be7cc
--- /dev/null
+++ b/providers/implementations/rands/build.info
@@ -0,0 +1,6 @@
+SUBDIRS=seeding
+
+$RANDS_GOAL=../../libdefault.a ../../libfips.a
+
+SOURCE[$RANDS_GOAL]=drbg.c test_rng.c drbg_ctr.c drbg_hash.c drbg_hmac.c crngt.c
+SOURCE[../../libdefault.a]=seed_src.c
diff --git a/providers/implementations/rands/crngt.c b/providers/implementations/rands/crngt.c
new file mode 100644
index 000000000000..4095994bda11
--- /dev/null
+++ b/providers/implementations/rands/crngt.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Implementation of the FIPS 140-2 section 4.9.2 Conditional Tests.
+ */
+
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/params.h>
+#include <openssl/self_test.h>
+#include "prov/providercommon.h"
+#include "prov/provider_ctx.h"
+#include "internal/cryptlib.h"
+#include "crypto/rand_pool.h"
+#include "drbg_local.h"
+#include "prov/seeding.h"
+
+typedef struct crng_test_global_st {
+ unsigned char crngt_prev[EVP_MAX_MD_SIZE];
+ EVP_MD *md;
+ int preloaded;
+ CRYPTO_RWLOCK *lock;
+} CRNG_TEST_GLOBAL;
+
+static int crngt_get_entropy(PROV_CTX *provctx, const EVP_MD *digest,
+ unsigned char *buf, unsigned char *md,
+ unsigned int *md_size)
+{
+ int r;
+ size_t n;
+ unsigned char *p;
+
+ n = ossl_prov_get_entropy(provctx, &p, 0, CRNGT_BUFSIZ, CRNGT_BUFSIZ);
+ if (n == CRNGT_BUFSIZ) {
+ r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, digest, NULL);
+ if (r != 0)
+ memcpy(buf, p, CRNGT_BUFSIZ);
+ ossl_prov_cleanup_entropy(provctx, p, n);
+ return r != 0;
+ }
+ if (n != 0)
+ ossl_prov_cleanup_entropy(provctx, p, n);
+ return 0;
+}
+
+static void rand_crng_ossl_ctx_free(void *vcrngt_glob)
+{
+ CRNG_TEST_GLOBAL *crngt_glob = vcrngt_glob;
+
+ CRYPTO_THREAD_lock_free(crngt_glob->lock);
+ EVP_MD_free(crngt_glob->md);
+ OPENSSL_free(crngt_glob);
+}
+
+static void *rand_crng_ossl_ctx_new(OSSL_LIB_CTX *ctx)
+{
+ CRNG_TEST_GLOBAL *crngt_glob = OPENSSL_zalloc(sizeof(*crngt_glob));
+
+ if (crngt_glob == NULL)
+ return NULL;
+
+ if ((crngt_glob->md = EVP_MD_fetch(ctx, "SHA256", "")) == NULL) {
+ OPENSSL_free(crngt_glob);
+ return NULL;
+ }
+
+ if ((crngt_glob->lock = CRYPTO_THREAD_lock_new()) == NULL) {
+ EVP_MD_free(crngt_glob->md);
+ OPENSSL_free(crngt_glob);
+ return NULL;
+ }
+
+ return crngt_glob;
+}
+
+static const OSSL_LIB_CTX_METHOD rand_crng_ossl_ctx_method = {
+ OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
+ rand_crng_ossl_ctx_new,
+ rand_crng_ossl_ctx_free,
+};
+
+static int prov_crngt_compare_previous(const unsigned char *prev,
+ const unsigned char *cur,
+ size_t sz)
+{
+ const int res = memcmp(prev, cur, sz) != 0;
+
+ if (!res)
+ ossl_set_error_state(OSSL_SELF_TEST_TYPE_CRNG);
+ return res;
+}
+
+size_t ossl_crngt_get_entropy(PROV_DRBG *drbg,
+ unsigned char **pout,
+ int entropy, size_t min_len, size_t max_len,
+ int prediction_resistance)
+{
+ unsigned char md[EVP_MAX_MD_SIZE];
+ unsigned char buf[CRNGT_BUFSIZ];
+ unsigned char *ent, *entp, *entbuf;
+ unsigned int sz;
+ size_t bytes_needed;
+ size_t r = 0, s, t;
+ int crng_test_pass = 1;
+ OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(drbg->provctx);
+ CRNG_TEST_GLOBAL *crngt_glob
+ = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_RAND_CRNGT_INDEX,
+ &rand_crng_ossl_ctx_method);
+ OSSL_CALLBACK *stcb = NULL;
+ void *stcbarg = NULL;
+ OSSL_SELF_TEST *st = NULL;
+
+ if (crngt_glob == NULL)
+ return 0;
+
+ if (!CRYPTO_THREAD_write_lock(crngt_glob->lock))
+ return 0;
+
+ if (!crngt_glob->preloaded) {
+ if (!crngt_get_entropy(drbg->provctx, crngt_glob->md, buf,
+ crngt_glob->crngt_prev, NULL)) {
+ OPENSSL_cleanse(buf, sizeof(buf));
+ goto unlock_return;
+ }
+ crngt_glob->preloaded = 1;
+ }
+
+ /*
+ * Calculate how many bytes of seed material we require, rounded up
+ * to the nearest byte. If the entropy is of less than full quality,
+ * the amount required should be scaled up appropriately here.
+ */
+ bytes_needed = (entropy + 7) / 8;
+ if (bytes_needed < min_len)
+ bytes_needed = min_len;
+ if (bytes_needed > max_len)
+ goto unlock_return;
+ entp = ent = OPENSSL_secure_malloc(bytes_needed);
+ if (ent == NULL)
+ goto unlock_return;
+
+ OSSL_SELF_TEST_get_callback(libctx, &stcb, &stcbarg);
+ if (stcb != NULL) {
+ st = OSSL_SELF_TEST_new(stcb, stcbarg);
+ if (st == NULL)
+ goto err;
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_CRNG,
+ OSSL_SELF_TEST_DESC_RNG);
+ }
+
+ for (t = bytes_needed; t > 0;) {
+ /* Care needs to be taken to avoid overrunning the buffer */
+ s = t >= CRNGT_BUFSIZ ? CRNGT_BUFSIZ : t;
+ entbuf = t >= CRNGT_BUFSIZ ? entp : buf;
+ if (!crngt_get_entropy(drbg->provctx, crngt_glob->md, entbuf, md, &sz))
+ goto err;
+ if (t < CRNGT_BUFSIZ)
+ memcpy(entp, buf, t);
+ /* Force a failure here if the callback returns 1 */
+ if (OSSL_SELF_TEST_oncorrupt_byte(st, md))
+ memcpy(md, crngt_glob->crngt_prev, sz);
+ if (!prov_crngt_compare_previous(crngt_glob->crngt_prev, md, sz)) {
+ crng_test_pass = 0;
+ goto err;
+ }
+ /* Update for next block */
+ memcpy(crngt_glob->crngt_prev, md, sz);
+ entp += s;
+ t -= s;
+ }
+ r = bytes_needed;
+ *pout = ent;
+ ent = NULL;
+
+ err:
+ OSSL_SELF_TEST_onend(st, crng_test_pass);
+ OSSL_SELF_TEST_free(st);
+ OPENSSL_secure_clear_free(ent, bytes_needed);
+
+ unlock_return:
+ CRYPTO_THREAD_unlock(crngt_glob->lock);
+ return r;
+}
+
+void ossl_crngt_cleanup_entropy(ossl_unused PROV_DRBG *drbg,
+ unsigned char *out, size_t outlen)
+{
+ OPENSSL_secure_clear_free(out, outlen);
+}
diff --git a/providers/implementations/rands/drbg.c b/providers/implementations/rands/drbg.c
new file mode 100644
index 000000000000..c8fe66aa573f
--- /dev/null
+++ b/providers/implementations/rands/drbg.c
@@ -0,0 +1,934 @@
+/*
+ * Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/evp.h>
+#include "crypto/rand.h"
+#include <openssl/proverr.h>
+#include "drbg_local.h"
+#include "internal/thread_once.h"
+#include "crypto/cryptlib.h"
+#include "prov/seeding.h"
+#include "crypto/rand_pool.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+
+/*
+ * Support framework for NIST SP 800-90A DRBG
+ *
+ * See manual page PROV_DRBG(7) for a general overview.
+ *
+ * The OpenSSL model is to have new and free functions, and that new
+ * does all initialization. That is not the NIST model, which has
+ * instantiation and un-instantiate, and re-use within a new/free
+ * lifecycle. (No doubt this comes from the desire to support hardware
+ * DRBG, where allocation of resources on something like an HSM is
+ * a much bigger deal than just re-setting an allocated resource.)
+ */
+
+/* NIST SP 800-90A DRBG recommends the use of a personalization string. */
+static const char ossl_pers_string[] = DRBG_DEFAULT_PERS_STRING;
+
+static const OSSL_DISPATCH *find_call(const OSSL_DISPATCH *dispatch,
+ int function);
+
+static int rand_drbg_restart(PROV_DRBG *drbg);
+
+int ossl_drbg_lock(void *vctx)
+{
+ PROV_DRBG *drbg = vctx;
+
+ if (drbg == NULL || drbg->lock == NULL)
+ return 1;
+ return CRYPTO_THREAD_write_lock(drbg->lock);
+}
+
+void ossl_drbg_unlock(void *vctx)
+{
+ PROV_DRBG *drbg = vctx;
+
+ if (drbg != NULL && drbg->lock != NULL)
+ CRYPTO_THREAD_unlock(drbg->lock);
+}
+
+static int ossl_drbg_lock_parent(PROV_DRBG *drbg)
+{
+ void *parent = drbg->parent;
+
+ if (parent != NULL
+ && drbg->parent_lock != NULL
+ && !drbg->parent_lock(parent)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_LOCKING_NOT_ENABLED);
+ return 0;
+ }
+ return 1;
+}
+
+static void ossl_drbg_unlock_parent(PROV_DRBG *drbg)
+{
+ void *parent = drbg->parent;
+
+ if (parent != NULL && drbg->parent_unlock != NULL)
+ drbg->parent_unlock(parent);
+}
+
+static int get_parent_strength(PROV_DRBG *drbg, unsigned int *str)
+{
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ void *parent = drbg->parent;
+ int res;
+
+ if (drbg->parent_get_ctx_params == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PARENT_STRENGTH);
+ return 0;
+ }
+
+ *params = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, str);
+ if (!ossl_drbg_lock_parent(drbg)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOCK_PARENT);
+ return 0;
+ }
+ res = drbg->parent_get_ctx_params(parent, params);
+ ossl_drbg_unlock_parent(drbg);
+ if (!res) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PARENT_STRENGTH);
+ return 0;
+ }
+ return 1;
+}
+
+static unsigned int get_parent_reseed_count(PROV_DRBG *drbg)
+{
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ void *parent = drbg->parent;
+ unsigned int r = 0;
+
+ *params = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_COUNTER, &r);
+ if (!ossl_drbg_lock_parent(drbg)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOCK_PARENT);
+ goto err;
+ }
+ if (!drbg->parent_get_ctx_params(parent, params))
+ r = 0;
+ ossl_drbg_unlock_parent(drbg);
+ return r;
+
+ err:
+ r = tsan_load(&drbg->reseed_counter) - 2;
+ if (r == 0)
+ r = UINT_MAX;
+ return r;
+}
+
+/*
+ * Implements the get_entropy() callback
+ *
+ * If the DRBG has a parent, then the required amount of entropy input
+ * is fetched using the parent's ossl_prov_drbg_generate().
+ *
+ * Otherwise, the entropy is polled from the system entropy sources
+ * using ossl_pool_acquire_entropy().
+ *
+ * If a random pool has been added to the DRBG using RAND_add(), then
+ * its entropy will be used up first.
+ */
+size_t ossl_drbg_get_seed(void *vdrbg, unsigned char **pout,
+ int entropy, size_t min_len,
+ size_t max_len, int prediction_resistance,
+ const unsigned char *adin, size_t adin_len)
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+ size_t bytes_needed;
+ unsigned char *buffer;
+
+ /* Figure out how many bytes we need */
+ bytes_needed = entropy >= 0 ? (entropy + 7) / 8 : 0;
+ if (bytes_needed < min_len)
+ bytes_needed = min_len;
+ if (bytes_needed > max_len)
+ bytes_needed = max_len;
+
+ /* Allocate storage */
+ buffer = OPENSSL_secure_malloc(bytes_needed);
+ if (buffer == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ /*
+ * Get random data. Include our DRBG address as
+ * additional input, in order to provide a distinction between
+ * different DRBG child instances.
+ *
+ * Note: using the sizeof() operator on a pointer triggers
+ * a warning in some static code analyzers, but it's
+ * intentional and correct here.
+ */
+ if (!ossl_prov_drbg_generate(drbg, buffer, bytes_needed,
+ drbg->strength, prediction_resistance,
+ (unsigned char *)&drbg, sizeof(drbg))) {
+ OPENSSL_secure_clear_free(buffer, bytes_needed);
+ ERR_raise(ERR_LIB_PROV, PROV_R_GENERATE_ERROR);
+ return 0;
+ }
+ *pout = buffer;
+ return bytes_needed;
+}
+
+/* Implements the cleanup_entropy() callback */
+void ossl_drbg_clear_seed(ossl_unused void *vdrbg,
+ unsigned char *out, size_t outlen)
+{
+ OPENSSL_secure_clear_free(out, outlen);
+}
+
+static size_t get_entropy(PROV_DRBG *drbg, unsigned char **pout, int entropy,
+ size_t min_len, size_t max_len,
+ int prediction_resistance)
+{
+ size_t bytes;
+ unsigned int p_str;
+
+ if (drbg->parent == NULL)
+#ifdef FIPS_MODULE
+ return ossl_crngt_get_entropy(drbg, pout, entropy, min_len, max_len,
+ prediction_resistance);
+#else
+ return ossl_prov_get_entropy(drbg->provctx, pout, entropy, min_len,
+ max_len);
+#endif
+
+ if (drbg->parent_get_seed == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED);
+ return 0;
+ }
+ if (!get_parent_strength(drbg, &p_str))
+ return 0;
+ if (drbg->strength > p_str) {
+ /*
+ * We currently don't support the algorithm from NIST SP 800-90C
+ * 10.1.2 to use a weaker DRBG as source
+ */
+ ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_STRENGTH_TOO_WEAK);
+ return 0;
+ }
+
+ /*
+ * Our lock is already held, but we need to lock our parent before
+ * generating bits from it. Note: taking the lock will be a no-op
+ * if locking is not required (while drbg->parent->lock == NULL).
+ */
+ if (!ossl_drbg_lock_parent(drbg))
+ return 0;
+ /*
+ * Get random data from parent. Include our DRBG address as
+ * additional input, in order to provide a distinction between
+ * different DRBG child instances.
+ *
+ * Note: using the sizeof() operator on a pointer triggers
+ * a warning in some static code analyzers, but it's
+ * intentional and correct here.
+ */
+ bytes = drbg->parent_get_seed(drbg->parent, pout, drbg->strength,
+ min_len, max_len, prediction_resistance,
+ (unsigned char *)&drbg, sizeof(drbg));
+ ossl_drbg_unlock_parent(drbg);
+ return bytes;
+}
+
+static void cleanup_entropy(PROV_DRBG *drbg, unsigned char *out, size_t outlen)
+{
+ if (drbg->parent == NULL) {
+#ifdef FIPS_MODULE
+ ossl_crngt_cleanup_entropy(drbg, out, outlen);
+#else
+ ossl_prov_cleanup_entropy(drbg->provctx, out, outlen);
+#endif
+ } else if (drbg->parent_clear_seed != NULL) {
+ if (!ossl_drbg_lock_parent(drbg))
+ return;
+ drbg->parent_clear_seed(drbg, out, outlen);
+ ossl_drbg_unlock_parent(drbg);
+ }
+}
+
+#ifndef PROV_RAND_GET_RANDOM_NONCE
+typedef struct prov_drbg_nonce_global_st {
+ CRYPTO_RWLOCK *rand_nonce_lock;
+ int rand_nonce_count;
+} PROV_DRBG_NONCE_GLOBAL;
+
+/*
+ * drbg_ossl_ctx_new() calls drgb_setup() which calls rand_drbg_get_nonce()
+ * which needs to get the rand_nonce_lock out of the OSSL_LIB_CTX...but since
+ * drbg_ossl_ctx_new() hasn't finished running yet we need the rand_nonce_lock
+ * to be in a different global data object. Otherwise we will go into an
+ * infinite recursion loop.
+ */
+static void *prov_drbg_nonce_ossl_ctx_new(OSSL_LIB_CTX *libctx)
+{
+ PROV_DRBG_NONCE_GLOBAL *dngbl = OPENSSL_zalloc(sizeof(*dngbl));
+
+ if (dngbl == NULL)
+ return NULL;
+
+ dngbl->rand_nonce_lock = CRYPTO_THREAD_lock_new();
+ if (dngbl->rand_nonce_lock == NULL) {
+ OPENSSL_free(dngbl);
+ return NULL;
+ }
+
+ return dngbl;
+}
+
+static void prov_drbg_nonce_ossl_ctx_free(void *vdngbl)
+{
+ PROV_DRBG_NONCE_GLOBAL *dngbl = vdngbl;
+
+ if (dngbl == NULL)
+ return;
+
+ CRYPTO_THREAD_lock_free(dngbl->rand_nonce_lock);
+
+ OPENSSL_free(dngbl);
+}
+
+static const OSSL_LIB_CTX_METHOD drbg_nonce_ossl_ctx_method = {
+ OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
+ prov_drbg_nonce_ossl_ctx_new,
+ prov_drbg_nonce_ossl_ctx_free,
+};
+
+/* Get a nonce from the operating system */
+static size_t prov_drbg_get_nonce(PROV_DRBG *drbg, unsigned char **pout,
+ size_t min_len, size_t max_len)
+{
+ size_t ret = 0, n;
+ unsigned char *buf = NULL;
+ OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(drbg->provctx);
+ PROV_DRBG_NONCE_GLOBAL *dngbl
+ = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_NONCE_INDEX,
+ &drbg_nonce_ossl_ctx_method);
+ struct {
+ void *drbg;
+ int count;
+ } data;
+
+ if (dngbl == NULL)
+ return 0;
+
+ if (drbg->parent != NULL && drbg->parent_nonce != NULL) {
+ n = drbg->parent_nonce(drbg->parent, NULL, 0, drbg->min_noncelen,
+ drbg->max_noncelen);
+ if (n > 0 && (buf = OPENSSL_malloc(n)) != NULL) {
+ ret = drbg->parent_nonce(drbg->parent, buf, 0,
+ drbg->min_noncelen, drbg->max_noncelen);
+ if (ret == n) {
+ *pout = buf;
+ return ret;
+ }
+ OPENSSL_free(buf);
+ }
+ }
+
+ /* Use the built in nonce source plus some of our specifics */
+ memset(&data, 0, sizeof(data));
+ data.drbg = drbg;
+ CRYPTO_atomic_add(&dngbl->rand_nonce_count, 1, &data.count,
+ dngbl->rand_nonce_lock);
+ return ossl_prov_get_nonce(drbg->provctx, pout, min_len, max_len,
+ &data, sizeof(data));
+}
+#endif /* PROV_RAND_GET_RANDOM_NONCE */
+
+/*
+ * Instantiate |drbg|, after it has been initialized. Use |pers| and
+ * |perslen| as prediction-resistance input.
+ *
+ * Requires that drbg->lock is already locked for write, if non-null.
+ *
+ * Returns 1 on success, 0 on failure.
+ */
+int ossl_prov_drbg_instantiate(PROV_DRBG *drbg, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *pers, size_t perslen)
+{
+ unsigned char *nonce = NULL, *entropy = NULL;
+ size_t noncelen = 0, entropylen = 0;
+ size_t min_entropy, min_entropylen, max_entropylen;
+
+ if (strength > drbg->strength) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INSUFFICIENT_DRBG_STRENGTH);
+ goto end;
+ }
+ min_entropy = drbg->strength;
+ min_entropylen = drbg->min_entropylen;
+ max_entropylen = drbg->max_entropylen;
+
+ if (pers == NULL) {
+ pers = (const unsigned char *)ossl_pers_string;
+ perslen = sizeof(ossl_pers_string);
+ }
+ if (perslen > drbg->max_perslen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_PERSONALISATION_STRING_TOO_LONG);
+ goto end;
+ }
+
+ if (drbg->state != EVP_RAND_STATE_UNINITIALISED) {
+ if (drbg->state == EVP_RAND_STATE_ERROR)
+ ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);
+ else
+ ERR_raise(ERR_LIB_PROV, PROV_R_ALREADY_INSTANTIATED);
+ goto end;
+ }
+
+ drbg->state = EVP_RAND_STATE_ERROR;
+
+ if (drbg->min_noncelen > 0) {
+ if (drbg->parent_nonce != NULL) {
+ noncelen = drbg->parent_nonce(drbg->parent, NULL, drbg->strength,
+ drbg->min_noncelen,
+ drbg->max_noncelen);
+ if (noncelen == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);
+ goto end;
+ }
+ nonce = OPENSSL_malloc(noncelen);
+ if (nonce == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);
+ goto end;
+ }
+ if (noncelen != drbg->parent_nonce(drbg->parent, nonce,
+ drbg->strength,
+ drbg->min_noncelen,
+ drbg->max_noncelen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);
+ goto end;
+ }
+#ifndef PROV_RAND_GET_RANDOM_NONCE
+ } else if (drbg->parent != NULL) {
+#endif
+ /*
+ * NIST SP800-90Ar1 section 9.1 says you can combine getting
+ * the entropy and nonce in 1 call by increasing the entropy
+ * with 50% and increasing the minimum length to accommodate
+ * the length of the nonce. We do this in case a nonce is
+ * required and there is no parental nonce capability.
+ */
+ min_entropy += drbg->strength / 2;
+ min_entropylen += drbg->min_noncelen;
+ max_entropylen += drbg->max_noncelen;
+ }
+#ifndef PROV_RAND_GET_RANDOM_NONCE
+ else { /* parent == NULL */
+ noncelen = prov_drbg_get_nonce(drbg, &nonce, drbg->min_noncelen,
+ drbg->max_noncelen);
+ if (noncelen < drbg->min_noncelen
+ || noncelen > drbg->max_noncelen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);
+ goto end;
+ }
+ }
+#endif
+ }
+
+ drbg->reseed_next_counter = tsan_load(&drbg->reseed_counter);
+ if (drbg->reseed_next_counter) {
+ drbg->reseed_next_counter++;
+ if (!drbg->reseed_next_counter)
+ drbg->reseed_next_counter = 1;
+ }
+
+ entropylen = get_entropy(drbg, &entropy, min_entropy,
+ min_entropylen, max_entropylen,
+ prediction_resistance);
+ if (entropylen < min_entropylen
+ || entropylen > max_entropylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_ENTROPY);
+ goto end;
+ }
+
+ if (!drbg->instantiate(drbg, entropy, entropylen, nonce, noncelen,
+ pers, perslen)) {
+ cleanup_entropy(drbg, entropy, entropylen);
+ ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_INSTANTIATING_DRBG);
+ goto end;
+ }
+ cleanup_entropy(drbg, entropy, entropylen);
+
+ drbg->state = EVP_RAND_STATE_READY;
+ drbg->generate_counter = 1;
+ drbg->reseed_time = time(NULL);
+ tsan_store(&drbg->reseed_counter, drbg->reseed_next_counter);
+
+ end:
+ if (nonce != NULL)
+ ossl_prov_cleanup_nonce(drbg->provctx, nonce, noncelen);
+ if (drbg->state == EVP_RAND_STATE_READY)
+ return 1;
+ return 0;
+}
+
+/*
+ * Uninstantiate |drbg|. Must be instantiated before it can be used.
+ *
+ * Requires that drbg->lock is already locked for write, if non-null.
+ *
+ * Returns 1 on success, 0 on failure.
+ */
+int ossl_prov_drbg_uninstantiate(PROV_DRBG *drbg)
+{
+ drbg->state = EVP_RAND_STATE_UNINITIALISED;
+ return 1;
+}
+
+/*
+ * Reseed |drbg|, mixing in the specified data
+ *
+ * Requires that drbg->lock is already locked for write, if non-null.
+ *
+ * Returns 1 on success, 0 on failure.
+ */
+int ossl_prov_drbg_reseed(PROV_DRBG *drbg, int prediction_resistance,
+ const unsigned char *ent, size_t ent_len,
+ const unsigned char *adin, size_t adinlen)
+{
+ unsigned char *entropy = NULL;
+ size_t entropylen = 0;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (drbg->state != EVP_RAND_STATE_READY) {
+ /* try to recover from previous errors */
+ rand_drbg_restart(drbg);
+
+ if (drbg->state == EVP_RAND_STATE_ERROR) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);
+ return 0;
+ }
+ if (drbg->state == EVP_RAND_STATE_UNINITIALISED) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_INSTANTIATED);
+ return 0;
+ }
+ }
+
+ if (ent != NULL) {
+ if (ent_len < drbg->min_entropylen) {
+ ERR_raise(ERR_LIB_RAND, RAND_R_ENTROPY_OUT_OF_RANGE);
+ drbg->state = EVP_RAND_STATE_ERROR;
+ return 0;
+ }
+ if (ent_len > drbg->max_entropylen) {
+ ERR_raise(ERR_LIB_RAND, RAND_R_ENTROPY_INPUT_TOO_LONG);
+ drbg->state = EVP_RAND_STATE_ERROR;
+ return 0;
+ }
+ }
+
+ if (adin == NULL) {
+ adinlen = 0;
+ } else if (adinlen > drbg->max_adinlen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_ADDITIONAL_INPUT_TOO_LONG);
+ return 0;
+ }
+
+ drbg->state = EVP_RAND_STATE_ERROR;
+
+ drbg->reseed_next_counter = tsan_load(&drbg->reseed_counter);
+ if (drbg->reseed_next_counter) {
+ drbg->reseed_next_counter++;
+ if (!drbg->reseed_next_counter)
+ drbg->reseed_next_counter = 1;
+ }
+
+ if (ent != NULL) {
+#ifdef FIPS_MODULE
+ /*
+ * NIST SP-800-90A mandates that entropy *shall not* be provided
+ * by the consuming application. Instead the data is added as additional
+ * input.
+ *
+ * (NIST SP-800-90Ar1, Sections 9.1 and 9.2)
+ */
+ if (!drbg->reseed(drbg, NULL, 0, ent, ent_len)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_RESEED);
+ return 0;
+ }
+#else
+ if (!drbg->reseed(drbg, ent, ent_len, adin, adinlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_RESEED);
+ return 0;
+ }
+ /* There isn't much point adding the same additional input twice */
+ adin = NULL;
+ adinlen = 0;
+#endif
+ }
+
+ /* Reseed using our sources in addition */
+ entropylen = get_entropy(drbg, &entropy, drbg->strength,
+ drbg->min_entropylen, drbg->max_entropylen,
+ prediction_resistance);
+ if (entropylen < drbg->min_entropylen
+ || entropylen > drbg->max_entropylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_ENTROPY);
+ goto end;
+ }
+
+ if (!drbg->reseed(drbg, entropy, entropylen, adin, adinlen))
+ goto end;
+
+ drbg->state = EVP_RAND_STATE_READY;
+ drbg->generate_counter = 1;
+ drbg->reseed_time = time(NULL);
+ tsan_store(&drbg->reseed_counter, drbg->reseed_next_counter);
+ if (drbg->parent != NULL)
+ drbg->parent_reseed_counter = get_parent_reseed_count(drbg);
+
+ end:
+ cleanup_entropy(drbg, entropy, entropylen);
+ if (drbg->state == EVP_RAND_STATE_READY)
+ return 1;
+ return 0;
+}
+
+/*
+ * Generate |outlen| bytes into the buffer at |out|. Reseed if we need
+ * to or if |prediction_resistance| is set. Additional input can be
+ * sent in |adin| and |adinlen|.
+ *
+ * Requires that drbg->lock is already locked for write, if non-null.
+ *
+ * Returns 1 on success, 0 on failure.
+ *
+ */
+int ossl_prov_drbg_generate(PROV_DRBG *drbg, unsigned char *out, size_t outlen,
+ unsigned int strength, int prediction_resistance,
+ const unsigned char *adin, size_t adinlen)
+{
+ int fork_id;
+ int reseed_required = 0;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (drbg->state != EVP_RAND_STATE_READY) {
+ /* try to recover from previous errors */
+ rand_drbg_restart(drbg);
+
+ if (drbg->state == EVP_RAND_STATE_ERROR) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);
+ return 0;
+ }
+ if (drbg->state == EVP_RAND_STATE_UNINITIALISED) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_INSTANTIATED);
+ return 0;
+ }
+ }
+ if (strength > drbg->strength) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INSUFFICIENT_DRBG_STRENGTH);
+ return 0;
+ }
+
+ if (outlen > drbg->max_request) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_REQUEST_TOO_LARGE_FOR_DRBG);
+ return 0;
+ }
+ if (adinlen > drbg->max_adinlen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_ADDITIONAL_INPUT_TOO_LONG);
+ return 0;
+ }
+
+ fork_id = openssl_get_fork_id();
+
+ if (drbg->fork_id != fork_id) {
+ drbg->fork_id = fork_id;
+ reseed_required = 1;
+ }
+
+ if (drbg->reseed_interval > 0) {
+ if (drbg->generate_counter >= drbg->reseed_interval)
+ reseed_required = 1;
+ }
+ if (drbg->reseed_time_interval > 0) {
+ time_t now = time(NULL);
+ if (now < drbg->reseed_time
+ || now - drbg->reseed_time >= drbg->reseed_time_interval)
+ reseed_required = 1;
+ }
+ if (drbg->parent != NULL
+ && get_parent_reseed_count(drbg) != drbg->parent_reseed_counter)
+ reseed_required = 1;
+
+ if (reseed_required || prediction_resistance) {
+ if (!ossl_prov_drbg_reseed(drbg, prediction_resistance, NULL, 0,
+ adin, adinlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_RESEED_ERROR);
+ return 0;
+ }
+ adin = NULL;
+ adinlen = 0;
+ }
+
+ if (!drbg->generate(drbg, out, outlen, adin, adinlen)) {
+ drbg->state = EVP_RAND_STATE_ERROR;
+ ERR_raise(ERR_LIB_PROV, PROV_R_GENERATE_ERROR);
+ return 0;
+ }
+
+ drbg->generate_counter++;
+
+ return 1;
+}
+
+/*
+ * Restart |drbg|, using the specified entropy or additional input
+ *
+ * Tries its best to get the drbg instantiated by all means,
+ * regardless of its current state.
+ *
+ * Optionally, a |buffer| of |len| random bytes can be passed,
+ * which is assumed to contain at least |entropy| bits of entropy.
+ *
+ * If |entropy| > 0, the buffer content is used as entropy input.
+ *
+ * If |entropy| == 0, the buffer content is used as additional input
+ *
+ * Returns 1 on success, 0 on failure.
+ *
+ * This function is used internally only.
+ */
+static int rand_drbg_restart(PROV_DRBG *drbg)
+{
+ /* repair error state */
+ if (drbg->state == EVP_RAND_STATE_ERROR)
+ drbg->uninstantiate(drbg);
+
+ /* repair uninitialized state */
+ if (drbg->state == EVP_RAND_STATE_UNINITIALISED)
+ /* reinstantiate drbg */
+ ossl_prov_drbg_instantiate(drbg, drbg->strength, 0, NULL, 0);
+
+ return drbg->state == EVP_RAND_STATE_READY;
+}
+
+/* Provider support from here down */
+static const OSSL_DISPATCH *find_call(const OSSL_DISPATCH *dispatch,
+ int function)
+{
+ if (dispatch != NULL)
+ while (dispatch->function_id != 0) {
+ if (dispatch->function_id == function)
+ return dispatch;
+ dispatch++;
+ }
+ return NULL;
+}
+
+int ossl_drbg_enable_locking(void *vctx)
+{
+ PROV_DRBG *drbg = vctx;
+
+ if (drbg != NULL && drbg->lock == NULL) {
+ if (drbg->parent_enable_locking != NULL)
+ if (!drbg->parent_enable_locking(drbg->parent)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_LOCKING_NOT_ENABLED);
+ return 0;
+ }
+ drbg->lock = CRYPTO_THREAD_lock_new();
+ if (drbg->lock == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_CREATE_LOCK);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * Allocate memory and initialize a new DRBG. The DRBG is allocated on
+ * the secure heap if |secure| is nonzero and the secure heap is enabled.
+ * The |parent|, if not NULL, will be used as random source for reseeding.
+ * This also requires the parent's provider context and the parent's lock.
+ *
+ * Returns a pointer to the new DRBG instance on success, NULL on failure.
+ */
+PROV_DRBG *ossl_rand_drbg_new
+ (void *provctx, void *parent, const OSSL_DISPATCH *p_dispatch,
+ int (*dnew)(PROV_DRBG *ctx),
+ int (*instantiate)(PROV_DRBG *drbg,
+ const unsigned char *entropy, size_t entropylen,
+ const unsigned char *nonce, size_t noncelen,
+ const unsigned char *pers, size_t perslen),
+ int (*uninstantiate)(PROV_DRBG *ctx),
+ int (*reseed)(PROV_DRBG *drbg, const unsigned char *ent, size_t ent_len,
+ const unsigned char *adin, size_t adin_len),
+ int (*generate)(PROV_DRBG *, unsigned char *out, size_t outlen,
+ const unsigned char *adin, size_t adin_len))
+{
+ PROV_DRBG *drbg;
+ unsigned int p_str;
+ const OSSL_DISPATCH *pfunc;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ drbg = OPENSSL_zalloc(sizeof(*drbg));
+ if (drbg == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ drbg->provctx = provctx;
+ drbg->instantiate = instantiate;
+ drbg->uninstantiate = uninstantiate;
+ drbg->reseed = reseed;
+ drbg->generate = generate;
+ drbg->fork_id = openssl_get_fork_id();
+
+ /* Extract parent's functions */
+ drbg->parent = parent;
+ if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_ENABLE_LOCKING)) != NULL)
+ drbg->parent_enable_locking = OSSL_FUNC_rand_enable_locking(pfunc);
+ if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_LOCK)) != NULL)
+ drbg->parent_lock = OSSL_FUNC_rand_lock(pfunc);
+ if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_UNLOCK)) != NULL)
+ drbg->parent_unlock = OSSL_FUNC_rand_unlock(pfunc);
+ if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GET_CTX_PARAMS)) != NULL)
+ drbg->parent_get_ctx_params = OSSL_FUNC_rand_get_ctx_params(pfunc);
+ if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_NONCE)) != NULL)
+ drbg->parent_nonce = OSSL_FUNC_rand_nonce(pfunc);
+ if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GET_SEED)) != NULL)
+ drbg->parent_get_seed = OSSL_FUNC_rand_get_seed(pfunc);
+ if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_CLEAR_SEED)) != NULL)
+ drbg->parent_clear_seed = OSSL_FUNC_rand_clear_seed(pfunc);
+
+ /* Set some default maximums up */
+ drbg->max_entropylen = DRBG_MAX_LENGTH;
+ drbg->max_noncelen = DRBG_MAX_LENGTH;
+ drbg->max_perslen = DRBG_MAX_LENGTH;
+ drbg->max_adinlen = DRBG_MAX_LENGTH;
+ drbg->generate_counter = 1;
+ drbg->reseed_counter = 1;
+ drbg->reseed_interval = RESEED_INTERVAL;
+ drbg->reseed_time_interval = TIME_INTERVAL;
+
+ if (!dnew(drbg))
+ goto err;
+
+ if (parent != NULL) {
+ if (!get_parent_strength(drbg, &p_str))
+ goto err;
+ if (drbg->strength > p_str) {
+ /*
+ * We currently don't support the algorithm from NIST SP 800-90C
+ * 10.1.2 to use a weaker DRBG as source
+ */
+ ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_STRENGTH_TOO_WEAK);
+ goto err;
+ }
+ }
+#ifdef TSAN_REQUIRES_LOCKING
+ if (!ossl_drbg_enable_locking(drbg))
+ goto err;
+#endif
+ return drbg;
+
+ err:
+ ossl_rand_drbg_free(drbg);
+ return NULL;
+}
+
+void ossl_rand_drbg_free(PROV_DRBG *drbg)
+{
+ if (drbg == NULL)
+ return;
+
+ CRYPTO_THREAD_lock_free(drbg->lock);
+ OPENSSL_free(drbg);
+}
+
+int ossl_drbg_get_ctx_params(PROV_DRBG *drbg, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE);
+ if (p != NULL && !OSSL_PARAM_set_int(p, drbg->state))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH);
+ if (p != NULL && !OSSL_PARAM_set_int(p, drbg->strength))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_request))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MIN_ENTROPYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->min_entropylen))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_ENTROPYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_entropylen))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MIN_NONCELEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->min_noncelen))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_NONCELEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_noncelen))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_PERSLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_perslen))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_ADINLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_adinlen))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_REQUESTS);
+ if (p != NULL && !OSSL_PARAM_set_uint(p, drbg->reseed_interval))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_TIME);
+ if (p != NULL && !OSSL_PARAM_set_time_t(p, drbg->reseed_time))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL);
+ if (p != NULL && !OSSL_PARAM_set_time_t(p, drbg->reseed_time_interval))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_COUNTER);
+ if (p != NULL
+ && !OSSL_PARAM_set_uint(p, tsan_load(&drbg->reseed_counter)))
+ return 0;
+ return 1;
+}
+
+int ossl_drbg_set_ctx_params(PROV_DRBG *drbg, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_RESEED_REQUESTS);
+ if (p != NULL && !OSSL_PARAM_get_uint(p, &drbg->reseed_interval))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL);
+ if (p != NULL && !OSSL_PARAM_get_time_t(p, &drbg->reseed_time_interval))
+ return 0;
+ return 1;
+}
diff --git a/providers/implementations/rands/drbg_ctr.c b/providers/implementations/rands/drbg_ctr.c
new file mode 100644
index 000000000000..451113c4d162
--- /dev/null
+++ b/providers/implementations/rands/drbg_ctr.c
@@ -0,0 +1,755 @@
+/*
+ * Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/aes.h>
+#include <openssl/proverr.h>
+#include "crypto/modes.h"
+#include "internal/thread_once.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+#include "prov/provider_ctx.h"
+#include "drbg_local.h"
+
+static OSSL_FUNC_rand_newctx_fn drbg_ctr_new_wrapper;
+static OSSL_FUNC_rand_freectx_fn drbg_ctr_free;
+static OSSL_FUNC_rand_instantiate_fn drbg_ctr_instantiate_wrapper;
+static OSSL_FUNC_rand_uninstantiate_fn drbg_ctr_uninstantiate_wrapper;
+static OSSL_FUNC_rand_generate_fn drbg_ctr_generate_wrapper;
+static OSSL_FUNC_rand_reseed_fn drbg_ctr_reseed_wrapper;
+static OSSL_FUNC_rand_settable_ctx_params_fn drbg_ctr_settable_ctx_params;
+static OSSL_FUNC_rand_set_ctx_params_fn drbg_ctr_set_ctx_params;
+static OSSL_FUNC_rand_gettable_ctx_params_fn drbg_ctr_gettable_ctx_params;
+static OSSL_FUNC_rand_get_ctx_params_fn drbg_ctr_get_ctx_params;
+static OSSL_FUNC_rand_verify_zeroization_fn drbg_ctr_verify_zeroization;
+
+/*
+ * The state of a DRBG AES-CTR.
+ */
+typedef struct rand_drbg_ctr_st {
+ EVP_CIPHER_CTX *ctx_ecb;
+ EVP_CIPHER_CTX *ctx_ctr;
+ EVP_CIPHER_CTX *ctx_df;
+ EVP_CIPHER *cipher_ecb;
+ EVP_CIPHER *cipher_ctr;
+ size_t keylen;
+ int use_df;
+ unsigned char K[32];
+ unsigned char V[16];
+ /* Temporary block storage used by ctr_df */
+ unsigned char bltmp[16];
+ size_t bltmp_pos;
+ unsigned char KX[48];
+} PROV_DRBG_CTR;
+
+/*
+ * Implementation of NIST SP 800-90A CTR DRBG.
+ */
+static void inc_128(PROV_DRBG_CTR *ctr)
+{
+ unsigned char *p = &ctr->V[0];
+ u32 n = 16, c = 1;
+
+ do {
+ --n;
+ c += p[n];
+ p[n] = (u8)c;
+ c >>= 8;
+ } while (n);
+}
+
+static void ctr_XOR(PROV_DRBG_CTR *ctr, const unsigned char *in, size_t inlen)
+{
+ size_t i, n;
+
+ if (in == NULL || inlen == 0)
+ return;
+
+ /*
+ * Any zero padding will have no effect on the result as we
+ * are XORing. So just process however much input we have.
+ */
+ n = inlen < ctr->keylen ? inlen : ctr->keylen;
+ for (i = 0; i < n; i++)
+ ctr->K[i] ^= in[i];
+ if (inlen <= ctr->keylen)
+ return;
+
+ n = inlen - ctr->keylen;
+ if (n > 16) {
+ /* Should never happen */
+ n = 16;
+ }
+ for (i = 0; i < n; i++)
+ ctr->V[i] ^= in[i + ctr->keylen];
+}
+
+/*
+ * Process a complete block using BCC algorithm of SP 800-90A 10.3.3
+ */
+__owur static int ctr_BCC_block(PROV_DRBG_CTR *ctr, unsigned char *out,
+ const unsigned char *in, int len)
+{
+ int i, outlen = AES_BLOCK_SIZE;
+
+ for (i = 0; i < len; i++)
+ out[i] ^= in[i];
+
+ if (!EVP_CipherUpdate(ctr->ctx_df, out, &outlen, out, len)
+ || outlen != len)
+ return 0;
+ return 1;
+}
+
+
+/*
+ * Handle several BCC operations for as much data as we need for K and X
+ */
+__owur static int ctr_BCC_blocks(PROV_DRBG_CTR *ctr, const unsigned char *in)
+{
+ unsigned char in_tmp[48];
+ unsigned char num_of_blk = 2;
+
+ memcpy(in_tmp, in, 16);
+ memcpy(in_tmp + 16, in, 16);
+ if (ctr->keylen != 16) {
+ memcpy(in_tmp + 32, in, 16);
+ num_of_blk = 3;
+ }
+ return ctr_BCC_block(ctr, ctr->KX, in_tmp, AES_BLOCK_SIZE * num_of_blk);
+}
+
+/*
+ * Initialise BCC blocks: these have the value 0,1,2 in leftmost positions:
+ * see 10.3.1 stage 7.
+ */
+__owur static int ctr_BCC_init(PROV_DRBG_CTR *ctr)
+{
+ unsigned char bltmp[48] = {0};
+ unsigned char num_of_blk;
+
+ memset(ctr->KX, 0, 48);
+ num_of_blk = ctr->keylen == 16 ? 2 : 3;
+ bltmp[(AES_BLOCK_SIZE * 1) + 3] = 1;
+ bltmp[(AES_BLOCK_SIZE * 2) + 3] = 2;
+ return ctr_BCC_block(ctr, ctr->KX, bltmp, num_of_blk * AES_BLOCK_SIZE);
+}
+
+/*
+ * Process several blocks into BCC algorithm, some possibly partial
+ */
+__owur static int ctr_BCC_update(PROV_DRBG_CTR *ctr,
+ const unsigned char *in, size_t inlen)
+{
+ if (in == NULL || inlen == 0)
+ return 1;
+
+ /* If we have partial block handle it first */
+ if (ctr->bltmp_pos) {
+ size_t left = 16 - ctr->bltmp_pos;
+
+ /* If we now have a complete block process it */
+ if (inlen >= left) {
+ memcpy(ctr->bltmp + ctr->bltmp_pos, in, left);
+ if (!ctr_BCC_blocks(ctr, ctr->bltmp))
+ return 0;
+ ctr->bltmp_pos = 0;
+ inlen -= left;
+ in += left;
+ }
+ }
+
+ /* Process zero or more complete blocks */
+ for (; inlen >= 16; in += 16, inlen -= 16) {
+ if (!ctr_BCC_blocks(ctr, in))
+ return 0;
+ }
+
+ /* Copy any remaining partial block to the temporary buffer */
+ if (inlen > 0) {
+ memcpy(ctr->bltmp + ctr->bltmp_pos, in, inlen);
+ ctr->bltmp_pos += inlen;
+ }
+ return 1;
+}
+
+__owur static int ctr_BCC_final(PROV_DRBG_CTR *ctr)
+{
+ if (ctr->bltmp_pos) {
+ memset(ctr->bltmp + ctr->bltmp_pos, 0, 16 - ctr->bltmp_pos);
+ if (!ctr_BCC_blocks(ctr, ctr->bltmp))
+ return 0;
+ }
+ return 1;
+}
+
+__owur static int ctr_df(PROV_DRBG_CTR *ctr,
+ const unsigned char *in1, size_t in1len,
+ const unsigned char *in2, size_t in2len,
+ const unsigned char *in3, size_t in3len)
+{
+ static unsigned char c80 = 0x80;
+ size_t inlen;
+ unsigned char *p = ctr->bltmp;
+ int outlen = AES_BLOCK_SIZE;
+
+ if (!ctr_BCC_init(ctr))
+ return 0;
+ if (in1 == NULL)
+ in1len = 0;
+ if (in2 == NULL)
+ in2len = 0;
+ if (in3 == NULL)
+ in3len = 0;
+ inlen = in1len + in2len + in3len;
+ /* Initialise L||N in temporary block */
+ *p++ = (inlen >> 24) & 0xff;
+ *p++ = (inlen >> 16) & 0xff;
+ *p++ = (inlen >> 8) & 0xff;
+ *p++ = inlen & 0xff;
+
+ /* NB keylen is at most 32 bytes */
+ *p++ = 0;
+ *p++ = 0;
+ *p++ = 0;
+ *p = (unsigned char)((ctr->keylen + 16) & 0xff);
+ ctr->bltmp_pos = 8;
+ if (!ctr_BCC_update(ctr, in1, in1len)
+ || !ctr_BCC_update(ctr, in2, in2len)
+ || !ctr_BCC_update(ctr, in3, in3len)
+ || !ctr_BCC_update(ctr, &c80, 1)
+ || !ctr_BCC_final(ctr))
+ return 0;
+ /* Set up key K */
+ if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->KX, NULL, -1))
+ return 0;
+ /* X follows key K */
+ if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX, &outlen, ctr->KX + ctr->keylen,
+ AES_BLOCK_SIZE)
+ || outlen != AES_BLOCK_SIZE)
+ return 0;
+ if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX + 16, &outlen, ctr->KX,
+ AES_BLOCK_SIZE)
+ || outlen != AES_BLOCK_SIZE)
+ return 0;
+ if (ctr->keylen != 16)
+ if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX + 32, &outlen,
+ ctr->KX + 16, AES_BLOCK_SIZE)
+ || outlen != AES_BLOCK_SIZE)
+ return 0;
+ return 1;
+}
+
+/*
+ * NB the no-df Update in SP800-90A specifies a constant input length
+ * of seedlen, however other uses of this algorithm pad the input with
+ * zeroes if necessary and have up to two parameters XORed together,
+ * so we handle both cases in this function instead.
+ */
+__owur static int ctr_update(PROV_DRBG *drbg,
+ const unsigned char *in1, size_t in1len,
+ const unsigned char *in2, size_t in2len,
+ const unsigned char *nonce, size_t noncelen)
+{
+ PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
+ int outlen = AES_BLOCK_SIZE;
+ unsigned char V_tmp[48], out[48];
+ unsigned char len;
+
+ /* correct key is already set up. */
+ memcpy(V_tmp, ctr->V, 16);
+ inc_128(ctr);
+ memcpy(V_tmp + 16, ctr->V, 16);
+ if (ctr->keylen == 16) {
+ len = 32;
+ } else {
+ inc_128(ctr);
+ memcpy(V_tmp + 32, ctr->V, 16);
+ len = 48;
+ }
+ if (!EVP_CipherUpdate(ctr->ctx_ecb, out, &outlen, V_tmp, len)
+ || outlen != len)
+ return 0;
+ memcpy(ctr->K, out, ctr->keylen);
+ memcpy(ctr->V, out + ctr->keylen, 16);
+
+ if (ctr->use_df) {
+ /* If no input reuse existing derived value */
+ if (in1 != NULL || nonce != NULL || in2 != NULL)
+ if (!ctr_df(ctr, in1, in1len, nonce, noncelen, in2, in2len))
+ return 0;
+ /* If this a reuse input in1len != 0 */
+ if (in1len)
+ ctr_XOR(ctr, ctr->KX, drbg->seedlen);
+ } else {
+ ctr_XOR(ctr, in1, in1len);
+ ctr_XOR(ctr, in2, in2len);
+ }
+
+ if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->K, NULL, -1)
+ || !EVP_CipherInit_ex(ctr->ctx_ctr, NULL, NULL, ctr->K, NULL, -1))
+ return 0;
+ return 1;
+}
+
+static int drbg_ctr_instantiate(PROV_DRBG *drbg,
+ const unsigned char *entropy, size_t entropylen,
+ const unsigned char *nonce, size_t noncelen,
+ const unsigned char *pers, size_t perslen)
+{
+ PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
+
+ if (entropy == NULL)
+ return 0;
+
+ memset(ctr->K, 0, sizeof(ctr->K));
+ memset(ctr->V, 0, sizeof(ctr->V));
+ if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->K, NULL, -1))
+ return 0;
+
+ inc_128(ctr);
+ if (!ctr_update(drbg, entropy, entropylen, pers, perslen, nonce, noncelen))
+ return 0;
+ return 1;
+}
+
+static int drbg_ctr_instantiate_wrapper(void *vdrbg, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *pstr,
+ size_t pstr_len,
+ const OSSL_PARAM params[])
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+
+ if (!ossl_prov_is_running() || !drbg_ctr_set_ctx_params(drbg, params))
+ return 0;
+ return ossl_prov_drbg_instantiate(drbg, strength, prediction_resistance,
+ pstr, pstr_len);
+}
+
+static int drbg_ctr_reseed(PROV_DRBG *drbg,
+ const unsigned char *entropy, size_t entropylen,
+ const unsigned char *adin, size_t adinlen)
+{
+ PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
+
+ if (entropy == NULL)
+ return 0;
+
+ inc_128(ctr);
+ if (!ctr_update(drbg, entropy, entropylen, adin, adinlen, NULL, 0))
+ return 0;
+ return 1;
+}
+
+static int drbg_ctr_reseed_wrapper(void *vdrbg, int prediction_resistance,
+ const unsigned char *ent, size_t ent_len,
+ const unsigned char *adin, size_t adin_len)
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+
+ return ossl_prov_drbg_reseed(drbg, prediction_resistance, ent, ent_len,
+ adin, adin_len);
+}
+
+static void ctr96_inc(unsigned char *counter)
+{
+ u32 n = 12, c = 1;
+
+ do {
+ --n;
+ c += counter[n];
+ counter[n] = (u8)c;
+ c >>= 8;
+ } while (n);
+}
+
+static int drbg_ctr_generate(PROV_DRBG *drbg,
+ unsigned char *out, size_t outlen,
+ const unsigned char *adin, size_t adinlen)
+{
+ PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
+ unsigned int ctr32, blocks;
+ int outl, buflen;
+
+ if (adin != NULL && adinlen != 0) {
+ inc_128(ctr);
+
+ if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
+ return 0;
+ /* This means we reuse derived value */
+ if (ctr->use_df) {
+ adin = NULL;
+ adinlen = 1;
+ }
+ } else {
+ adinlen = 0;
+ }
+
+ inc_128(ctr);
+
+ if (outlen == 0) {
+ inc_128(ctr);
+
+ if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
+ return 0;
+ return 1;
+ }
+
+ memset(out, 0, outlen);
+
+ do {
+ if (!EVP_CipherInit_ex(ctr->ctx_ctr,
+ NULL, NULL, NULL, ctr->V, -1))
+ return 0;
+
+ /*-
+ * outlen has type size_t while EVP_CipherUpdate takes an
+ * int argument and thus cannot be guaranteed to process more
+ * than 2^31-1 bytes at a time. We process such huge generate
+ * requests in 2^30 byte chunks, which is the greatest multiple
+ * of AES block size lower than or equal to 2^31-1.
+ */
+ buflen = outlen > (1U << 30) ? (1U << 30) : outlen;
+ blocks = (buflen + 15) / 16;
+
+ ctr32 = GETU32(ctr->V + 12) + blocks;
+ if (ctr32 < blocks) {
+ /* 32-bit counter overflow into V. */
+ if (ctr32 != 0) {
+ blocks -= ctr32;
+ buflen = blocks * 16;
+ ctr32 = 0;
+ }
+ ctr96_inc(ctr->V);
+ }
+ PUTU32(ctr->V + 12, ctr32);
+
+ if (!EVP_CipherUpdate(ctr->ctx_ctr, out, &outl, out, buflen)
+ || outl != buflen)
+ return 0;
+
+ out += buflen;
+ outlen -= buflen;
+ } while (outlen);
+
+ if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
+ return 0;
+ return 1;
+}
+
+static int drbg_ctr_generate_wrapper
+ (void *vdrbg, unsigned char *out, size_t outlen,
+ unsigned int strength, int prediction_resistance,
+ const unsigned char *adin, size_t adin_len)
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+
+ return ossl_prov_drbg_generate(drbg, out, outlen, strength,
+ prediction_resistance, adin, adin_len);
+}
+
+static int drbg_ctr_uninstantiate(PROV_DRBG *drbg)
+{
+ PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
+
+ OPENSSL_cleanse(ctr->K, sizeof(ctr->K));
+ OPENSSL_cleanse(ctr->V, sizeof(ctr->V));
+ OPENSSL_cleanse(ctr->bltmp, sizeof(ctr->bltmp));
+ OPENSSL_cleanse(ctr->KX, sizeof(ctr->KX));
+ ctr->bltmp_pos = 0;
+ return ossl_prov_drbg_uninstantiate(drbg);
+}
+
+static int drbg_ctr_uninstantiate_wrapper(void *vdrbg)
+{
+ return drbg_ctr_uninstantiate((PROV_DRBG *)vdrbg);
+}
+
+static int drbg_ctr_verify_zeroization(void *vdrbg)
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+ PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
+
+ PROV_DRBG_VERYIFY_ZEROIZATION(ctr->K);
+ PROV_DRBG_VERYIFY_ZEROIZATION(ctr->V);
+ PROV_DRBG_VERYIFY_ZEROIZATION(ctr->bltmp);
+ PROV_DRBG_VERYIFY_ZEROIZATION(ctr->KX);
+ if (ctr->bltmp_pos != 0)
+ return 0;
+ return 1;
+}
+
+static int drbg_ctr_init_lengths(PROV_DRBG *drbg)
+{
+ PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
+ int res = 1;
+
+ /* Maximum number of bits per request = 2^19 = 2^16 bytes */
+ drbg->max_request = 1 << 16;
+ if (ctr->use_df) {
+ drbg->min_entropylen = 0;
+ drbg->max_entropylen = DRBG_MAX_LENGTH;
+ drbg->min_noncelen = 0;
+ drbg->max_noncelen = DRBG_MAX_LENGTH;
+ drbg->max_perslen = DRBG_MAX_LENGTH;
+ drbg->max_adinlen = DRBG_MAX_LENGTH;
+
+ if (ctr->keylen > 0) {
+ drbg->min_entropylen = ctr->keylen;
+ drbg->min_noncelen = drbg->min_entropylen / 2;
+ }
+ } else {
+ const size_t len = ctr->keylen > 0 ? drbg->seedlen : DRBG_MAX_LENGTH;
+
+ drbg->min_entropylen = len;
+ drbg->max_entropylen = len;
+ /* Nonce not used */
+ drbg->min_noncelen = 0;
+ drbg->max_noncelen = 0;
+ drbg->max_perslen = len;
+ drbg->max_adinlen = len;
+ }
+ return res;
+}
+
+static int drbg_ctr_init(PROV_DRBG *drbg)
+{
+ PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
+ size_t keylen;
+
+ if (ctr->cipher_ctr == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CIPHER);
+ return 0;
+ }
+ ctr->keylen = keylen = EVP_CIPHER_get_key_length(ctr->cipher_ctr);
+ if (ctr->ctx_ecb == NULL)
+ ctr->ctx_ecb = EVP_CIPHER_CTX_new();
+ if (ctr->ctx_ctr == NULL)
+ ctr->ctx_ctr = EVP_CIPHER_CTX_new();
+ if (ctr->ctx_ecb == NULL || ctr->ctx_ctr == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EVP_CipherInit_ex(ctr->ctx_ecb,
+ ctr->cipher_ecb, NULL, NULL, NULL, 1)
+ || !EVP_CipherInit_ex(ctr->ctx_ctr,
+ ctr->cipher_ctr, NULL, NULL, NULL, 1)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_INITIALISE_CIPHERS);
+ goto err;
+ }
+
+ drbg->strength = keylen * 8;
+ drbg->seedlen = keylen + 16;
+
+ if (ctr->use_df) {
+ /* df initialisation */
+ static const unsigned char df_key[32] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
+ };
+
+ if (ctr->ctx_df == NULL)
+ ctr->ctx_df = EVP_CIPHER_CTX_new();
+ if (ctr->ctx_df == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ /* Set key schedule for df_key */
+ if (!EVP_CipherInit_ex(ctr->ctx_df,
+ ctr->cipher_ecb, NULL, df_key, NULL, 1)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_DERIVATION_FUNCTION_INIT_FAILED);
+ goto err;
+ }
+ }
+ return drbg_ctr_init_lengths(drbg);
+
+err:
+ EVP_CIPHER_CTX_free(ctr->ctx_ecb);
+ EVP_CIPHER_CTX_free(ctr->ctx_ctr);
+ ctr->ctx_ecb = ctr->ctx_ctr = NULL;
+ return 0;
+}
+
+static int drbg_ctr_new(PROV_DRBG *drbg)
+{
+ PROV_DRBG_CTR *ctr;
+
+ ctr = OPENSSL_secure_zalloc(sizeof(*ctr));
+ if (ctr == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ ctr->use_df = 1;
+ drbg->data = ctr;
+ return drbg_ctr_init_lengths(drbg);
+}
+
+static void *drbg_ctr_new_wrapper(void *provctx, void *parent,
+ const OSSL_DISPATCH *parent_dispatch)
+{
+ return ossl_rand_drbg_new(provctx, parent, parent_dispatch, &drbg_ctr_new,
+ &drbg_ctr_instantiate, &drbg_ctr_uninstantiate,
+ &drbg_ctr_reseed, &drbg_ctr_generate);
+}
+
+static void drbg_ctr_free(void *vdrbg)
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+ PROV_DRBG_CTR *ctr;
+
+ if (drbg != NULL && (ctr = (PROV_DRBG_CTR *)drbg->data) != NULL) {
+ EVP_CIPHER_CTX_free(ctr->ctx_ecb);
+ EVP_CIPHER_CTX_free(ctr->ctx_ctr);
+ EVP_CIPHER_CTX_free(ctr->ctx_df);
+ EVP_CIPHER_free(ctr->cipher_ecb);
+ EVP_CIPHER_free(ctr->cipher_ctr);
+
+ OPENSSL_secure_clear_free(ctr, sizeof(*ctr));
+ }
+ ossl_rand_drbg_free(drbg);
+}
+
+static int drbg_ctr_get_ctx_params(void *vdrbg, OSSL_PARAM params[])
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+ PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_USE_DF);
+ if (p != NULL && !OSSL_PARAM_set_int(p, ctr->use_df))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_CIPHER);
+ if (p != NULL) {
+ if (ctr->cipher_ctr == NULL
+ || !OSSL_PARAM_set_utf8_string(p,
+ EVP_CIPHER_get0_name(ctr->cipher_ctr)))
+ return 0;
+ }
+
+ return ossl_drbg_get_ctx_params(drbg, params);
+}
+
+static const OSSL_PARAM *drbg_ctr_gettable_ctx_params(ossl_unused void *vctx,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_CIPHER, NULL, 0),
+ OSSL_PARAM_int(OSSL_DRBG_PARAM_USE_DF, NULL),
+ OSSL_PARAM_DRBG_GETTABLE_CTX_COMMON,
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+static int drbg_ctr_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_DRBG *ctx = (PROV_DRBG *)vctx;
+ PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)ctx->data;
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
+ const OSSL_PARAM *p;
+ char *ecb;
+ const char *propquery = NULL;
+ int i, cipher_init = 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_USE_DF)) != NULL
+ && OSSL_PARAM_get_int(p, &i)) {
+ /* FIPS errors out in the drbg_ctr_init() call later */
+ ctr->use_df = i != 0;
+ cipher_init = 1;
+ }
+
+ if ((p = OSSL_PARAM_locate_const(params,
+ OSSL_DRBG_PARAM_PROPERTIES)) != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return 0;
+ propquery = (const char *)p->data;
+ }
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_CIPHER)) != NULL) {
+ const char *base = (const char *)p->data;
+ size_t ctr_str_len = sizeof("CTR") - 1;
+ size_t ecb_str_len = sizeof("ECB") - 1;
+
+ if (p->data_type != OSSL_PARAM_UTF8_STRING
+ || p->data_size < ctr_str_len)
+ return 0;
+ if (OPENSSL_strcasecmp("CTR", base + p->data_size - ctr_str_len) != 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_REQUIRE_CTR_MODE_CIPHER);
+ return 0;
+ }
+ if ((ecb = OPENSSL_strndup(base, p->data_size)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ strcpy(ecb + p->data_size - ecb_str_len, "ECB");
+ EVP_CIPHER_free(ctr->cipher_ecb);
+ EVP_CIPHER_free(ctr->cipher_ctr);
+ ctr->cipher_ctr = EVP_CIPHER_fetch(libctx, base, propquery);
+ ctr->cipher_ecb = EVP_CIPHER_fetch(libctx, ecb, propquery);
+ OPENSSL_free(ecb);
+ if (ctr->cipher_ctr == NULL || ctr->cipher_ecb == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_FIND_CIPHERS);
+ return 0;
+ }
+ cipher_init = 1;
+ }
+
+ if (cipher_init && !drbg_ctr_init(ctx))
+ return 0;
+
+ return ossl_drbg_set_ctx_params(ctx, params);
+}
+
+static const OSSL_PARAM *drbg_ctr_settable_ctx_params(ossl_unused void *vctx,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_CIPHER, NULL, 0),
+ OSSL_PARAM_int(OSSL_DRBG_PARAM_USE_DF, NULL),
+ OSSL_PARAM_DRBG_SETTABLE_CTX_COMMON,
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_drbg_ctr_functions[] = {
+ { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))drbg_ctr_new_wrapper },
+ { OSSL_FUNC_RAND_FREECTX, (void(*)(void))drbg_ctr_free },
+ { OSSL_FUNC_RAND_INSTANTIATE,
+ (void(*)(void))drbg_ctr_instantiate_wrapper },
+ { OSSL_FUNC_RAND_UNINSTANTIATE,
+ (void(*)(void))drbg_ctr_uninstantiate_wrapper },
+ { OSSL_FUNC_RAND_GENERATE, (void(*)(void))drbg_ctr_generate_wrapper },
+ { OSSL_FUNC_RAND_RESEED, (void(*)(void))drbg_ctr_reseed_wrapper },
+ { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))ossl_drbg_enable_locking },
+ { OSSL_FUNC_RAND_LOCK, (void(*)(void))ossl_drbg_lock },
+ { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))ossl_drbg_unlock },
+ { OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS,
+ (void(*)(void))drbg_ctr_settable_ctx_params },
+ { OSSL_FUNC_RAND_SET_CTX_PARAMS, (void(*)(void))drbg_ctr_set_ctx_params },
+ { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
+ (void(*)(void))drbg_ctr_gettable_ctx_params },
+ { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))drbg_ctr_get_ctx_params },
+ { OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
+ (void(*)(void))drbg_ctr_verify_zeroization },
+ { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))ossl_drbg_get_seed },
+ { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))ossl_drbg_clear_seed },
+ { 0, NULL }
+};
diff --git a/providers/implementations/rands/drbg_hash.c b/providers/implementations/rands/drbg_hash.c
new file mode 100644
index 000000000000..6deb0a29256b
--- /dev/null
+++ b/providers/implementations/rands/drbg_hash.c
@@ -0,0 +1,529 @@
+/*
+ * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <openssl/sha.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/proverr.h>
+#include "internal/thread_once.h"
+#include "prov/providercommon.h"
+#include "prov/provider_ctx.h"
+#include "prov/provider_util.h"
+#include "prov/implementations.h"
+#include "drbg_local.h"
+
+static OSSL_FUNC_rand_newctx_fn drbg_hash_new_wrapper;
+static OSSL_FUNC_rand_freectx_fn drbg_hash_free;
+static OSSL_FUNC_rand_instantiate_fn drbg_hash_instantiate_wrapper;
+static OSSL_FUNC_rand_uninstantiate_fn drbg_hash_uninstantiate_wrapper;
+static OSSL_FUNC_rand_generate_fn drbg_hash_generate_wrapper;
+static OSSL_FUNC_rand_reseed_fn drbg_hash_reseed_wrapper;
+static OSSL_FUNC_rand_settable_ctx_params_fn drbg_hash_settable_ctx_params;
+static OSSL_FUNC_rand_set_ctx_params_fn drbg_hash_set_ctx_params;
+static OSSL_FUNC_rand_gettable_ctx_params_fn drbg_hash_gettable_ctx_params;
+static OSSL_FUNC_rand_get_ctx_params_fn drbg_hash_get_ctx_params;
+static OSSL_FUNC_rand_verify_zeroization_fn drbg_hash_verify_zeroization;
+
+/* 888 bits from SP800-90Ar1 10.1 table 2 */
+#define HASH_PRNG_MAX_SEEDLEN (888/8)
+
+/* 440 bits from SP800-90Ar1 10.1 table 2 */
+#define HASH_PRNG_SMALL_SEEDLEN (440/8)
+
+/* Determine what seedlen to use based on the block length */
+#define MAX_BLOCKLEN_USING_SMALL_SEEDLEN (256/8)
+#define INBYTE_IGNORE ((unsigned char)0xFF)
+
+typedef struct rand_drbg_hash_st {
+ PROV_DIGEST digest;
+ EVP_MD_CTX *ctx;
+ size_t blocklen;
+ unsigned char V[HASH_PRNG_MAX_SEEDLEN];
+ unsigned char C[HASH_PRNG_MAX_SEEDLEN];
+ /* Temporary value storage: should always exceed max digest length */
+ unsigned char vtmp[HASH_PRNG_MAX_SEEDLEN];
+} PROV_DRBG_HASH;
+
+/*
+ * SP800-90Ar1 10.3.1 Derivation function using a Hash Function (Hash_df).
+ * The input string used is composed of:
+ * inbyte - An optional leading byte (ignore if equal to INBYTE_IGNORE)
+ * in - input string 1 (A Non NULL value).
+ * in2 - optional input string (Can be NULL).
+ * in3 - optional input string (Can be NULL).
+ * These are concatenated as part of the DigestUpdate process.
+ */
+static int hash_df(PROV_DRBG *drbg, unsigned char *out,
+ const unsigned char inbyte,
+ const unsigned char *in, size_t inlen,
+ const unsigned char *in2, size_t in2len,
+ const unsigned char *in3, size_t in3len)
+{
+ PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
+ EVP_MD_CTX *ctx = hash->ctx;
+ unsigned char *vtmp = hash->vtmp;
+ /* tmp = counter || num_bits_returned || [inbyte] */
+ unsigned char tmp[1 + 4 + 1];
+ int tmp_sz = 0;
+ size_t outlen = drbg->seedlen;
+ size_t num_bits_returned = outlen * 8;
+ /*
+ * No need to check outlen size here, as the standard only ever needs
+ * seedlen bytes which is always less than the maximum permitted.
+ */
+
+ /* (Step 3) counter = 1 (tmp[0] is the 8 bit counter) */
+ tmp[tmp_sz++] = 1;
+ /* tmp[1..4] is the fixed 32 bit no_of_bits_to_return */
+ tmp[tmp_sz++] = (unsigned char)((num_bits_returned >> 24) & 0xff);
+ tmp[tmp_sz++] = (unsigned char)((num_bits_returned >> 16) & 0xff);
+ tmp[tmp_sz++] = (unsigned char)((num_bits_returned >> 8) & 0xff);
+ tmp[tmp_sz++] = (unsigned char)(num_bits_returned & 0xff);
+ /* Tack the additional input byte onto the end of tmp if it exists */
+ if (inbyte != INBYTE_IGNORE)
+ tmp[tmp_sz++] = inbyte;
+
+ /* (Step 4) */
+ for (;;) {
+ /*
+ * (Step 4.1) out = out || Hash(tmp || in || [in2] || [in3])
+ * (where tmp = counter || num_bits_returned || [inbyte])
+ */
+ if (!(EVP_DigestInit_ex(ctx, ossl_prov_digest_md(&hash->digest), NULL)
+ && EVP_DigestUpdate(ctx, tmp, tmp_sz)
+ && EVP_DigestUpdate(ctx, in, inlen)
+ && (in2 == NULL || EVP_DigestUpdate(ctx, in2, in2len))
+ && (in3 == NULL || EVP_DigestUpdate(ctx, in3, in3len))))
+ return 0;
+
+ if (outlen < hash->blocklen) {
+ if (!EVP_DigestFinal(ctx, vtmp, NULL))
+ return 0;
+ memcpy(out, vtmp, outlen);
+ OPENSSL_cleanse(vtmp, hash->blocklen);
+ break;
+ } else if(!EVP_DigestFinal(ctx, out, NULL)) {
+ return 0;
+ }
+
+ outlen -= hash->blocklen;
+ if (outlen == 0)
+ break;
+ /* (Step 4.2) counter++ */
+ tmp[0]++;
+ out += hash->blocklen;
+ }
+ return 1;
+}
+
+/* Helper function that just passes 2 input parameters to hash_df() */
+static int hash_df1(PROV_DRBG *drbg, unsigned char *out,
+ const unsigned char in_byte,
+ const unsigned char *in1, size_t in1len)
+{
+ return hash_df(drbg, out, in_byte, in1, in1len, NULL, 0, NULL, 0);
+}
+
+/*
+ * Add 2 byte buffers together. The first elements in each buffer are the top
+ * most bytes. The result is stored in the dst buffer.
+ * The final carry is ignored i.e: dst = (dst + in) mod (2^seedlen_bits).
+ * where dst size is drbg->seedlen, and inlen <= drbg->seedlen.
+ */
+static int add_bytes(PROV_DRBG *drbg, unsigned char *dst,
+ unsigned char *in, size_t inlen)
+{
+ size_t i;
+ int result;
+ const unsigned char *add;
+ unsigned char carry = 0, *d;
+
+ assert(drbg->seedlen >= 1 && inlen >= 1 && inlen <= drbg->seedlen);
+
+ d = &dst[drbg->seedlen - 1];
+ add = &in[inlen - 1];
+
+ for (i = inlen; i > 0; i--, d--, add--) {
+ result = *d + *add + carry;
+ carry = (unsigned char)(result >> 8);
+ *d = (unsigned char)(result & 0xff);
+ }
+
+ if (carry != 0) {
+ /* Add the carry to the top of the dst if inlen is not the same size */
+ for (i = drbg->seedlen - inlen; i > 0; --i, d--) {
+ *d += 1; /* Carry can only be 1 */
+ if (*d != 0) /* exit if carry doesnt propagate to the next byte */
+ break;
+ }
+ }
+ return 1;
+}
+
+/* V = (V + Hash(inbyte || V || [additional_input]) mod (2^seedlen) */
+static int add_hash_to_v(PROV_DRBG *drbg, unsigned char inbyte,
+ const unsigned char *adin, size_t adinlen)
+{
+ PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
+ EVP_MD_CTX *ctx = hash->ctx;
+
+ return EVP_DigestInit_ex(ctx, ossl_prov_digest_md(&hash->digest), NULL)
+ && EVP_DigestUpdate(ctx, &inbyte, 1)
+ && EVP_DigestUpdate(ctx, hash->V, drbg->seedlen)
+ && (adin == NULL || EVP_DigestUpdate(ctx, adin, adinlen))
+ && EVP_DigestFinal(ctx, hash->vtmp, NULL)
+ && add_bytes(drbg, hash->V, hash->vtmp, hash->blocklen);
+}
+
+/*
+ * The Hashgen() as listed in SP800-90Ar1 10.1.1.4 Hash_DRBG_Generate_Process.
+ *
+ * drbg contains the current value of V.
+ * outlen is the requested number of bytes.
+ * out is a buffer to return the generated bits.
+ *
+ * The algorithm to generate the bits is:
+ * data = V
+ * w = NULL
+ * for (i = 1 to m) {
+ * W = W || Hash(data)
+ * data = (data + 1) mod (2^seedlen)
+ * }
+ * out = Leftmost(W, outlen)
+ *
+ * Returns zero if an error occurs otherwise it returns 1.
+ */
+static int hash_gen(PROV_DRBG *drbg, unsigned char *out, size_t outlen)
+{
+ PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
+ unsigned char one = 1;
+
+ if (outlen == 0)
+ return 1;
+ memcpy(hash->vtmp, hash->V, drbg->seedlen);
+ for(;;) {
+ if (!EVP_DigestInit_ex(hash->ctx, ossl_prov_digest_md(&hash->digest),
+ NULL)
+ || !EVP_DigestUpdate(hash->ctx, hash->vtmp, drbg->seedlen))
+ return 0;
+
+ if (outlen < hash->blocklen) {
+ if (!EVP_DigestFinal(hash->ctx, hash->vtmp, NULL))
+ return 0;
+ memcpy(out, hash->vtmp, outlen);
+ return 1;
+ } else {
+ if (!EVP_DigestFinal(hash->ctx, out, NULL))
+ return 0;
+ outlen -= hash->blocklen;
+ if (outlen == 0)
+ break;
+ out += hash->blocklen;
+ }
+ add_bytes(drbg, hash->vtmp, &one, 1);
+ }
+ return 1;
+}
+
+/*
+ * SP800-90Ar1 10.1.1.2 Hash_DRBG_Instantiate_Process:
+ *
+ * ent is entropy input obtained from a randomness source of length ent_len.
+ * nonce is a string of bytes of length nonce_len.
+ * pstr is a personalization string received from an application. May be NULL.
+ *
+ * Returns zero if an error occurs otherwise it returns 1.
+ */
+static int drbg_hash_instantiate(PROV_DRBG *drbg,
+ const unsigned char *ent, size_t ent_len,
+ const unsigned char *nonce, size_t nonce_len,
+ const unsigned char *pstr, size_t pstr_len)
+{
+ PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
+
+ EVP_MD_CTX_free(hash->ctx);
+ hash->ctx = EVP_MD_CTX_new();
+
+ /* (Step 1-3) V = Hash_df(entropy||nonce||pers, seedlen) */
+ return hash->ctx != NULL
+ && hash_df(drbg, hash->V, INBYTE_IGNORE,
+ ent, ent_len, nonce, nonce_len, pstr, pstr_len)
+ /* (Step 4) C = Hash_df(0x00||V, seedlen) */
+ && hash_df1(drbg, hash->C, 0x00, hash->V, drbg->seedlen);
+}
+
+static int drbg_hash_instantiate_wrapper(void *vdrbg, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *pstr,
+ size_t pstr_len,
+ const OSSL_PARAM params[])
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+
+ if (!ossl_prov_is_running() || !drbg_hash_set_ctx_params(drbg, params))
+ return 0;
+ return ossl_prov_drbg_instantiate(drbg, strength, prediction_resistance,
+ pstr, pstr_len);
+}
+
+/*
+ * SP800-90Ar1 10.1.1.3 Hash_DRBG_Reseed_Process:
+ *
+ * ent is entropy input bytes obtained from a randomness source.
+ * addin is additional input received from an application. May be NULL.
+ *
+ * Returns zero if an error occurs otherwise it returns 1.
+ */
+static int drbg_hash_reseed(PROV_DRBG *drbg,
+ const unsigned char *ent, size_t ent_len,
+ const unsigned char *adin, size_t adin_len)
+{
+ PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
+
+ /* (Step 1-2) V = Hash_df(0x01 || V || entropy_input || additional_input) */
+ /* V about to be updated so use C as output instead */
+ if (!hash_df(drbg, hash->C, 0x01, hash->V, drbg->seedlen, ent, ent_len,
+ adin, adin_len))
+ return 0;
+ memcpy(hash->V, hash->C, drbg->seedlen);
+ /* (Step 4) C = Hash_df(0x00||V, seedlen) */
+ return hash_df1(drbg, hash->C, 0x00, hash->V, drbg->seedlen);
+}
+
+static int drbg_hash_reseed_wrapper(void *vdrbg, int prediction_resistance,
+ const unsigned char *ent, size_t ent_len,
+ const unsigned char *adin, size_t adin_len)
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+
+ return ossl_prov_drbg_reseed(drbg, prediction_resistance, ent, ent_len,
+ adin, adin_len);
+}
+
+/*
+ * SP800-90Ar1 10.1.1.4 Hash_DRBG_Generate_Process:
+ *
+ * Generates pseudo random bytes using the drbg.
+ * out is a buffer to fill with outlen bytes of pseudo random data.
+ * addin is additional input received from an application. May be NULL.
+ *
+ * Returns zero if an error occurs otherwise it returns 1.
+ */
+static int drbg_hash_generate(PROV_DRBG *drbg,
+ unsigned char *out, size_t outlen,
+ const unsigned char *adin, size_t adin_len)
+{
+ PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
+ unsigned char counter[4];
+ int reseed_counter = drbg->generate_counter;
+
+ counter[0] = (unsigned char)((reseed_counter >> 24) & 0xff);
+ counter[1] = (unsigned char)((reseed_counter >> 16) & 0xff);
+ counter[2] = (unsigned char)((reseed_counter >> 8) & 0xff);
+ counter[3] = (unsigned char)(reseed_counter & 0xff);
+
+ return hash->ctx != NULL
+ && (adin == NULL
+ /* (Step 2) if adin != NULL then V = V + Hash(0x02||V||adin) */
+ || adin_len == 0
+ || add_hash_to_v(drbg, 0x02, adin, adin_len))
+ /* (Step 3) Hashgen(outlen, V) */
+ && hash_gen(drbg, out, outlen)
+ /* (Step 4/5) H = V = (V + Hash(0x03||V) mod (2^seedlen_bits) */
+ && add_hash_to_v(drbg, 0x03, NULL, 0)
+ /* (Step 5) V = (V + H + C + reseed_counter) mod (2^seedlen_bits) */
+ /* V = (V + C) mod (2^seedlen_bits) */
+ && add_bytes(drbg, hash->V, hash->C, drbg->seedlen)
+ /* V = (V + reseed_counter) mod (2^seedlen_bits) */
+ && add_bytes(drbg, hash->V, counter, 4);
+}
+
+static int drbg_hash_generate_wrapper
+ (void *vdrbg, unsigned char *out, size_t outlen, unsigned int strength,
+ int prediction_resistance, const unsigned char *adin, size_t adin_len)
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+
+ return ossl_prov_drbg_generate(drbg, out, outlen, strength,
+ prediction_resistance, adin, adin_len);
+}
+
+static int drbg_hash_uninstantiate(PROV_DRBG *drbg)
+{
+ PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
+
+ OPENSSL_cleanse(hash->V, sizeof(hash->V));
+ OPENSSL_cleanse(hash->C, sizeof(hash->C));
+ OPENSSL_cleanse(hash->vtmp, sizeof(hash->vtmp));
+ return ossl_prov_drbg_uninstantiate(drbg);
+}
+
+static int drbg_hash_uninstantiate_wrapper(void *vdrbg)
+{
+ return drbg_hash_uninstantiate((PROV_DRBG *)vdrbg);
+}
+
+static int drbg_hash_verify_zeroization(void *vdrbg)
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+ PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
+
+ PROV_DRBG_VERYIFY_ZEROIZATION(hash->V);
+ PROV_DRBG_VERYIFY_ZEROIZATION(hash->C);
+ PROV_DRBG_VERYIFY_ZEROIZATION(hash->vtmp);
+ return 1;
+}
+
+static int drbg_hash_new(PROV_DRBG *ctx)
+{
+ PROV_DRBG_HASH *hash;
+
+ hash = OPENSSL_secure_zalloc(sizeof(*hash));
+ if (hash == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ ctx->data = hash;
+ ctx->seedlen = HASH_PRNG_MAX_SEEDLEN;
+ ctx->max_entropylen = DRBG_MAX_LENGTH;
+ ctx->max_noncelen = DRBG_MAX_LENGTH;
+ ctx->max_perslen = DRBG_MAX_LENGTH;
+ ctx->max_adinlen = DRBG_MAX_LENGTH;
+
+ /* Maximum number of bits per request = 2^19 = 2^16 bytes */
+ ctx->max_request = 1 << 16;
+ return 1;
+}
+
+static void *drbg_hash_new_wrapper(void *provctx, void *parent,
+ const OSSL_DISPATCH *parent_dispatch)
+{
+ return ossl_rand_drbg_new(provctx, parent, parent_dispatch, &drbg_hash_new,
+ &drbg_hash_instantiate, &drbg_hash_uninstantiate,
+ &drbg_hash_reseed, &drbg_hash_generate);
+}
+
+static void drbg_hash_free(void *vdrbg)
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+ PROV_DRBG_HASH *hash;
+
+ if (drbg != NULL && (hash = (PROV_DRBG_HASH *)drbg->data) != NULL) {
+ EVP_MD_CTX_free(hash->ctx);
+ ossl_prov_digest_reset(&hash->digest);
+ OPENSSL_secure_clear_free(hash, sizeof(*hash));
+ }
+ ossl_rand_drbg_free(drbg);
+}
+
+static int drbg_hash_get_ctx_params(void *vdrbg, OSSL_PARAM params[])
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+ PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
+ const EVP_MD *md;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_DIGEST);
+ if (p != NULL) {
+ md = ossl_prov_digest_md(&hash->digest);
+ if (md == NULL || !OSSL_PARAM_set_utf8_string(p, EVP_MD_get0_name(md)))
+ return 0;
+ }
+
+ return ossl_drbg_get_ctx_params(drbg, params);
+}
+
+static const OSSL_PARAM *drbg_hash_gettable_ctx_params(ossl_unused void *vctx,
+ ossl_unused void *p_ctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_DRBG_GETTABLE_CTX_COMMON,
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+static int drbg_hash_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_DRBG *ctx = (PROV_DRBG *)vctx;
+ PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)ctx->data;
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
+ const EVP_MD *md;
+
+ if (!ossl_prov_digest_load_from_params(&hash->digest, params, libctx))
+ return 0;
+
+ md = ossl_prov_digest_md(&hash->digest);
+ if (md != NULL) {
+ if ((EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF) != 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED);
+ return 0;
+ }
+
+ /* These are taken from SP 800-90 10.1 Table 2 */
+ hash->blocklen = EVP_MD_get_size(md);
+ /* See SP800-57 Part1 Rev4 5.6.1 Table 3 */
+ ctx->strength = 64 * (hash->blocklen >> 3);
+ if (ctx->strength > 256)
+ ctx->strength = 256;
+ if (hash->blocklen > MAX_BLOCKLEN_USING_SMALL_SEEDLEN)
+ ctx->seedlen = HASH_PRNG_MAX_SEEDLEN;
+ else
+ ctx->seedlen = HASH_PRNG_SMALL_SEEDLEN;
+
+ ctx->min_entropylen = ctx->strength / 8;
+ ctx->min_noncelen = ctx->min_entropylen / 2;
+ }
+
+ return ossl_drbg_set_ctx_params(ctx, params);
+}
+
+static const OSSL_PARAM *drbg_hash_settable_ctx_params(ossl_unused void *vctx,
+ ossl_unused void *p_ctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_DRBG_SETTABLE_CTX_COMMON,
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_drbg_hash_functions[] = {
+ { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))drbg_hash_new_wrapper },
+ { OSSL_FUNC_RAND_FREECTX, (void(*)(void))drbg_hash_free },
+ { OSSL_FUNC_RAND_INSTANTIATE,
+ (void(*)(void))drbg_hash_instantiate_wrapper },
+ { OSSL_FUNC_RAND_UNINSTANTIATE,
+ (void(*)(void))drbg_hash_uninstantiate_wrapper },
+ { OSSL_FUNC_RAND_GENERATE, (void(*)(void))drbg_hash_generate_wrapper },
+ { OSSL_FUNC_RAND_RESEED, (void(*)(void))drbg_hash_reseed_wrapper },
+ { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))ossl_drbg_enable_locking },
+ { OSSL_FUNC_RAND_LOCK, (void(*)(void))ossl_drbg_lock },
+ { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))ossl_drbg_unlock },
+ { OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS,
+ (void(*)(void))drbg_hash_settable_ctx_params },
+ { OSSL_FUNC_RAND_SET_CTX_PARAMS, (void(*)(void))drbg_hash_set_ctx_params },
+ { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
+ (void(*)(void))drbg_hash_gettable_ctx_params },
+ { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))drbg_hash_get_ctx_params },
+ { OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
+ (void(*)(void))drbg_hash_verify_zeroization },
+ { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))ossl_drbg_get_seed },
+ { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))ossl_drbg_clear_seed },
+ { 0, NULL }
+};
diff --git a/providers/implementations/rands/drbg_hmac.c b/providers/implementations/rands/drbg_hmac.c
new file mode 100644
index 000000000000..e68465a78cd9
--- /dev/null
+++ b/providers/implementations/rands/drbg_hmac.c
@@ -0,0 +1,432 @@
+/*
+ * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/proverr.h>
+#include "prov/provider_util.h"
+#include "internal/thread_once.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "drbg_local.h"
+
+static OSSL_FUNC_rand_newctx_fn drbg_hmac_new_wrapper;
+static OSSL_FUNC_rand_freectx_fn drbg_hmac_free;
+static OSSL_FUNC_rand_instantiate_fn drbg_hmac_instantiate_wrapper;
+static OSSL_FUNC_rand_uninstantiate_fn drbg_hmac_uninstantiate_wrapper;
+static OSSL_FUNC_rand_generate_fn drbg_hmac_generate_wrapper;
+static OSSL_FUNC_rand_reseed_fn drbg_hmac_reseed_wrapper;
+static OSSL_FUNC_rand_settable_ctx_params_fn drbg_hmac_settable_ctx_params;
+static OSSL_FUNC_rand_set_ctx_params_fn drbg_hmac_set_ctx_params;
+static OSSL_FUNC_rand_gettable_ctx_params_fn drbg_hmac_gettable_ctx_params;
+static OSSL_FUNC_rand_get_ctx_params_fn drbg_hmac_get_ctx_params;
+static OSSL_FUNC_rand_verify_zeroization_fn drbg_hmac_verify_zeroization;
+
+typedef struct rand_drbg_hmac_st {
+ EVP_MAC_CTX *ctx; /* H(x) = HMAC_hash OR H(x) = KMAC */
+ PROV_DIGEST digest; /* H(x) = hash(x) */
+ size_t blocklen;
+ unsigned char K[EVP_MAX_MD_SIZE];
+ unsigned char V[EVP_MAX_MD_SIZE];
+} PROV_DRBG_HMAC;
+
+/*
+ * Called twice by SP800-90Ar1 10.1.2.2 HMAC_DRBG_Update_Process.
+ *
+ * hmac is an object that holds the input/output Key and Value (K and V).
+ * inbyte is 0x00 on the first call and 0x01 on the second call.
+ * in1, in2, in3 are optional inputs that can be NULL.
+ * in1len, in2len, in3len are the lengths of the input buffers.
+ *
+ * The returned K,V is:
+ * hmac->K = HMAC(hmac->K, hmac->V || inbyte || [in1] || [in2] || [in3])
+ * hmac->V = HMAC(hmac->K, hmac->V)
+ *
+ * Returns zero if an error occurs otherwise it returns 1.
+ */
+static int do_hmac(PROV_DRBG_HMAC *hmac, unsigned char inbyte,
+ const unsigned char *in1, size_t in1len,
+ const unsigned char *in2, size_t in2len,
+ const unsigned char *in3, size_t in3len)
+{
+ EVP_MAC_CTX *ctx = hmac->ctx;
+
+ if (!EVP_MAC_init(ctx, hmac->K, hmac->blocklen, NULL)
+ /* K = HMAC(K, V || inbyte || [in1] || [in2] || [in3]) */
+ || !EVP_MAC_update(ctx, hmac->V, hmac->blocklen)
+ || !EVP_MAC_update(ctx, &inbyte, 1)
+ || !(in1 == NULL || in1len == 0 || EVP_MAC_update(ctx, in1, in1len))
+ || !(in2 == NULL || in2len == 0 || EVP_MAC_update(ctx, in2, in2len))
+ || !(in3 == NULL || in3len == 0 || EVP_MAC_update(ctx, in3, in3len))
+ || !EVP_MAC_final(ctx, hmac->K, NULL, sizeof(hmac->K)))
+ return 0;
+
+ /* V = HMAC(K, V) */
+ return EVP_MAC_init(ctx, hmac->K, hmac->blocklen, NULL)
+ && EVP_MAC_update(ctx, hmac->V, hmac->blocklen)
+ && EVP_MAC_final(ctx, hmac->V, NULL, sizeof(hmac->V));
+}
+
+/*
+ * SP800-90Ar1 10.1.2.2 HMAC_DRBG_Update_Process
+ *
+ *
+ * Updates the drbg objects Key(K) and Value(V) using the following algorithm:
+ * K,V = do_hmac(hmac, 0, in1, in2, in3)
+ * if (any input is not NULL)
+ * K,V = do_hmac(hmac, 1, in1, in2, in3)
+ *
+ * where in1, in2, in3 are optional input buffers that can be NULL.
+ * in1len, in2len, in3len are the lengths of the input buffers.
+ *
+ * Returns zero if an error occurs otherwise it returns 1.
+ */
+static int drbg_hmac_update(PROV_DRBG *drbg,
+ const unsigned char *in1, size_t in1len,
+ const unsigned char *in2, size_t in2len,
+ const unsigned char *in3, size_t in3len)
+{
+ PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
+
+ /* (Steps 1-2) K = HMAC(K, V||0x00||provided_data). V = HMAC(K,V) */
+ if (!do_hmac(hmac, 0x00, in1, in1len, in2, in2len, in3, in3len))
+ return 0;
+ /* (Step 3) If provided_data == NULL then return (K,V) */
+ if (in1len == 0 && in2len == 0 && in3len == 0)
+ return 1;
+ /* (Steps 4-5) K = HMAC(K, V||0x01||provided_data). V = HMAC(K,V) */
+ return do_hmac(hmac, 0x01, in1, in1len, in2, in2len, in3, in3len);
+}
+
+/*
+ * SP800-90Ar1 10.1.2.3 HMAC_DRBG_Instantiate_Process:
+ *
+ * This sets the drbg Key (K) to all zeros, and Value (V) to all 1's.
+ * and then calls (K,V) = drbg_hmac_update() with input parameters:
+ * ent = entropy data (Can be NULL) of length ent_len.
+ * nonce = nonce data (Can be NULL) of length nonce_len.
+ * pstr = personalization data (Can be NULL) of length pstr_len.
+ *
+ * Returns zero if an error occurs otherwise it returns 1.
+ */
+static int drbg_hmac_instantiate(PROV_DRBG *drbg,
+ const unsigned char *ent, size_t ent_len,
+ const unsigned char *nonce, size_t nonce_len,
+ const unsigned char *pstr, size_t pstr_len)
+{
+ PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
+
+ if (hmac->ctx == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MAC);
+ return 0;
+ }
+
+ /* (Step 2) Key = 0x00 00...00 */
+ memset(hmac->K, 0x00, hmac->blocklen);
+ /* (Step 3) V = 0x01 01...01 */
+ memset(hmac->V, 0x01, hmac->blocklen);
+ /* (Step 4) (K,V) = HMAC_DRBG_Update(entropy||nonce||pers string, K, V) */
+ return drbg_hmac_update(drbg, ent, ent_len, nonce, nonce_len, pstr,
+ pstr_len);
+}
+
+static int drbg_hmac_instantiate_wrapper(void *vdrbg, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *pstr,
+ size_t pstr_len,
+ const OSSL_PARAM params[])
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+
+ if (!ossl_prov_is_running() || !drbg_hmac_set_ctx_params(drbg, params))
+ return 0;
+ return ossl_prov_drbg_instantiate(drbg, strength, prediction_resistance,
+ pstr, pstr_len);
+}
+
+/*
+ * SP800-90Ar1 10.1.2.4 HMAC_DRBG_Reseed_Process:
+ *
+ * Reseeds the drbg's Key (K) and Value (V) by calling
+ * (K,V) = drbg_hmac_update() with the following input parameters:
+ * ent = entropy input data (Can be NULL) of length ent_len.
+ * adin = additional input data (Can be NULL) of length adin_len.
+ *
+ * Returns zero if an error occurs otherwise it returns 1.
+ */
+static int drbg_hmac_reseed(PROV_DRBG *drbg,
+ const unsigned char *ent, size_t ent_len,
+ const unsigned char *adin, size_t adin_len)
+{
+ /* (Step 2) (K,V) = HMAC_DRBG_Update(entropy||additional_input, K, V) */
+ return drbg_hmac_update(drbg, ent, ent_len, adin, adin_len, NULL, 0);
+}
+
+static int drbg_hmac_reseed_wrapper(void *vdrbg, int prediction_resistance,
+ const unsigned char *ent, size_t ent_len,
+ const unsigned char *adin, size_t adin_len)
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+
+ return ossl_prov_drbg_reseed(drbg, prediction_resistance, ent, ent_len,
+ adin, adin_len);
+}
+
+/*
+ * SP800-90Ar1 10.1.2.5 HMAC_DRBG_Generate_Process:
+ *
+ * Generates pseudo random bytes and updates the internal K,V for the drbg.
+ * out is a buffer to fill with outlen bytes of pseudo random data.
+ * adin is an additional_input string of size adin_len that may be NULL.
+ *
+ * Returns zero if an error occurs otherwise it returns 1.
+ */
+static int drbg_hmac_generate(PROV_DRBG *drbg,
+ unsigned char *out, size_t outlen,
+ const unsigned char *adin, size_t adin_len)
+{
+ PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
+ EVP_MAC_CTX *ctx = hmac->ctx;
+ const unsigned char *temp = hmac->V;
+
+ /* (Step 2) if adin != NULL then (K,V) = HMAC_DRBG_Update(adin, K, V) */
+ if (adin != NULL
+ && adin_len > 0
+ && !drbg_hmac_update(drbg, adin, adin_len, NULL, 0, NULL, 0))
+ return 0;
+
+ /*
+ * (Steps 3-5) temp = NULL
+ * while (len(temp) < outlen) {
+ * V = HMAC(K, V)
+ * temp = temp || V
+ * }
+ */
+ for (;;) {
+ if (!EVP_MAC_init(ctx, hmac->K, hmac->blocklen, NULL)
+ || !EVP_MAC_update(ctx, temp, hmac->blocklen))
+ return 0;
+
+ if (outlen > hmac->blocklen) {
+ if (!EVP_MAC_final(ctx, out, NULL, outlen))
+ return 0;
+ temp = out;
+ } else {
+ if (!EVP_MAC_final(ctx, hmac->V, NULL, sizeof(hmac->V)))
+ return 0;
+ memcpy(out, hmac->V, outlen);
+ break;
+ }
+ out += hmac->blocklen;
+ outlen -= hmac->blocklen;
+ }
+ /* (Step 6) (K,V) = HMAC_DRBG_Update(adin, K, V) */
+ if (!drbg_hmac_update(drbg, adin, adin_len, NULL, 0, NULL, 0))
+ return 0;
+
+ return 1;
+}
+
+static int drbg_hmac_generate_wrapper
+ (void *vdrbg, unsigned char *out, size_t outlen, unsigned int strength,
+ int prediction_resistance, const unsigned char *adin, size_t adin_len)
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+
+ return ossl_prov_drbg_generate(drbg, out, outlen, strength,
+ prediction_resistance, adin, adin_len);
+}
+
+static int drbg_hmac_uninstantiate(PROV_DRBG *drbg)
+{
+ PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
+
+ OPENSSL_cleanse(hmac->K, sizeof(hmac->K));
+ OPENSSL_cleanse(hmac->V, sizeof(hmac->V));
+ return ossl_prov_drbg_uninstantiate(drbg);
+}
+
+static int drbg_hmac_uninstantiate_wrapper(void *vdrbg)
+{
+ return drbg_hmac_uninstantiate((PROV_DRBG *)vdrbg);
+}
+
+static int drbg_hmac_verify_zeroization(void *vdrbg)
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+ PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
+
+ PROV_DRBG_VERYIFY_ZEROIZATION(hmac->K);
+ PROV_DRBG_VERYIFY_ZEROIZATION(hmac->V);
+ return 1;
+}
+
+static int drbg_hmac_new(PROV_DRBG *drbg)
+{
+ PROV_DRBG_HMAC *hmac;
+
+ hmac = OPENSSL_secure_zalloc(sizeof(*hmac));
+ if (hmac == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ drbg->data = hmac;
+ /* See SP800-57 Part1 Rev4 5.6.1 Table 3 */
+ drbg->max_entropylen = DRBG_MAX_LENGTH;
+ drbg->max_noncelen = DRBG_MAX_LENGTH;
+ drbg->max_perslen = DRBG_MAX_LENGTH;
+ drbg->max_adinlen = DRBG_MAX_LENGTH;
+
+ /* Maximum number of bits per request = 2^19 = 2^16 bytes */
+ drbg->max_request = 1 << 16;
+ return 1;
+}
+
+static void *drbg_hmac_new_wrapper(void *provctx, void *parent,
+ const OSSL_DISPATCH *parent_dispatch)
+{
+ return ossl_rand_drbg_new(provctx, parent, parent_dispatch, &drbg_hmac_new,
+ &drbg_hmac_instantiate, &drbg_hmac_uninstantiate,
+ &drbg_hmac_reseed, &drbg_hmac_generate);
+}
+
+static void drbg_hmac_free(void *vdrbg)
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+ PROV_DRBG_HMAC *hmac;
+
+ if (drbg != NULL && (hmac = (PROV_DRBG_HMAC *)drbg->data) != NULL) {
+ EVP_MAC_CTX_free(hmac->ctx);
+ ossl_prov_digest_reset(&hmac->digest);
+ OPENSSL_secure_clear_free(hmac, sizeof(*hmac));
+ }
+ ossl_rand_drbg_free(drbg);
+}
+
+static int drbg_hmac_get_ctx_params(void *vdrbg, OSSL_PARAM params[])
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+ PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
+ const char *name;
+ const EVP_MD *md;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAC);
+ if (p != NULL) {
+ if (hmac->ctx == NULL)
+ return 0;
+ name = EVP_MAC_get0_name(EVP_MAC_CTX_get0_mac(hmac->ctx));
+ if (!OSSL_PARAM_set_utf8_string(p, name))
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_DIGEST);
+ if (p != NULL) {
+ md = ossl_prov_digest_md(&hmac->digest);
+ if (md == NULL || !OSSL_PARAM_set_utf8_string(p, EVP_MD_get0_name(md)))
+ return 0;
+ }
+
+ return ossl_drbg_get_ctx_params(drbg, params);
+}
+
+static const OSSL_PARAM *drbg_hmac_gettable_ctx_params(ossl_unused void *vctx,
+ ossl_unused void *p_ctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_MAC, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_DRBG_GETTABLE_CTX_COMMON,
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+static int drbg_hmac_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_DRBG *ctx = (PROV_DRBG *)vctx;
+ PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)ctx->data;
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
+ const EVP_MD *md;
+
+ if (!ossl_prov_digest_load_from_params(&hmac->digest, params, libctx))
+ return 0;
+
+ /*
+ * Confirm digest is allowed. We allow all digests that are not XOF
+ * (such as SHAKE). In FIPS mode, the fetch will fail for non-approved
+ * digests.
+ */
+ md = ossl_prov_digest_md(&hmac->digest);
+ if (md != NULL && (EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF) != 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED);
+ return 0;
+ }
+
+ if (!ossl_prov_macctx_load_from_params(&hmac->ctx, params,
+ NULL, NULL, NULL, libctx))
+ return 0;
+
+ if (hmac->ctx != NULL) {
+ /* These are taken from SP 800-90 10.1 Table 2 */
+ hmac->blocklen = EVP_MD_get_size(md);
+ /* See SP800-57 Part1 Rev4 5.6.1 Table 3 */
+ ctx->strength = 64 * (int)(hmac->blocklen >> 3);
+ if (ctx->strength > 256)
+ ctx->strength = 256;
+ ctx->seedlen = hmac->blocklen;
+ ctx->min_entropylen = ctx->strength / 8;
+ ctx->min_noncelen = ctx->min_entropylen / 2;
+ }
+
+ return ossl_drbg_set_ctx_params(ctx, params);
+}
+
+static const OSSL_PARAM *drbg_hmac_settable_ctx_params(ossl_unused void *vctx,
+ ossl_unused void *p_ctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_MAC, NULL, 0),
+ OSSL_PARAM_DRBG_SETTABLE_CTX_COMMON,
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_drbg_ossl_hmac_functions[] = {
+ { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))drbg_hmac_new_wrapper },
+ { OSSL_FUNC_RAND_FREECTX, (void(*)(void))drbg_hmac_free },
+ { OSSL_FUNC_RAND_INSTANTIATE,
+ (void(*)(void))drbg_hmac_instantiate_wrapper },
+ { OSSL_FUNC_RAND_UNINSTANTIATE,
+ (void(*)(void))drbg_hmac_uninstantiate_wrapper },
+ { OSSL_FUNC_RAND_GENERATE, (void(*)(void))drbg_hmac_generate_wrapper },
+ { OSSL_FUNC_RAND_RESEED, (void(*)(void))drbg_hmac_reseed_wrapper },
+ { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))ossl_drbg_enable_locking },
+ { OSSL_FUNC_RAND_LOCK, (void(*)(void))ossl_drbg_lock },
+ { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))ossl_drbg_unlock },
+ { OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS,
+ (void(*)(void))drbg_hmac_settable_ctx_params },
+ { OSSL_FUNC_RAND_SET_CTX_PARAMS, (void(*)(void))drbg_hmac_set_ctx_params },
+ { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
+ (void(*)(void))drbg_hmac_gettable_ctx_params },
+ { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))drbg_hmac_get_ctx_params },
+ { OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
+ (void(*)(void))drbg_hmac_verify_zeroization },
+ { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))ossl_drbg_get_seed },
+ { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))ossl_drbg_clear_seed },
+ { 0, NULL }
+};
diff --git a/providers/implementations/rands/drbg_local.h b/providers/implementations/rands/drbg_local.h
new file mode 100644
index 000000000000..8bc5df89c236
--- /dev/null
+++ b/providers/implementations/rands/drbg_local.h
@@ -0,0 +1,259 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_PROV_LOCAL_H
+# define OSSL_CRYPTO_PROV_LOCAL_H
+
+# include <openssl/evp.h>
+# include <openssl/core_dispatch.h>
+# include <openssl/core_names.h>
+# include <openssl/params.h>
+# include "internal/tsan_assist.h"
+# include "internal/nelem.h"
+# include "internal/numbers.h"
+# include "prov/provider_ctx.h"
+
+/* How many times to read the TSC as a randomness source. */
+# define TSC_READ_COUNT 4
+
+/* Maximum reseed intervals */
+# define MAX_RESEED_INTERVAL (1 << 24)
+# define MAX_RESEED_TIME_INTERVAL (1 << 20) /* approx. 12 days */
+
+/* Default reseed intervals */
+# define RESEED_INTERVAL (1 << 8)
+# define TIME_INTERVAL (60*60) /* 1 hour */
+
+/*
+ * The number of bytes that constitutes an atomic lump of entropy with respect
+ * to the FIPS 140-2 section 4.9.2 Conditional Tests. The size is somewhat
+ * arbitrary, the smaller the value, the less entropy is consumed on first
+ * read but the higher the probability of the test failing by accident.
+ *
+ * The value is in bytes.
+ */
+#define CRNGT_BUFSIZ 16
+
+/*
+ * Maximum input size for the DRBG (entropy, nonce, personalization string)
+ *
+ * NIST SP800 90Ar1 allows a maximum of (1 << 35) bits i.e., (1 << 32) bytes.
+ *
+ * We lower it to 'only' INT32_MAX bytes, which is equivalent to 2 gigabytes.
+ */
+# define DRBG_MAX_LENGTH INT32_MAX
+
+/* The default nonce */
+#ifdef CHARSET_EBCDIC
+# define DRBG_DEFAULT_PERS_STRING { 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x53, \
+ 0x4c, 0x20, 0x4e, 0x49, 0x53, 0x54, 0x20, 0x53, 0x50, 0x20, 0x38, 0x30, \
+ 0x30, 0x2d, 0x39, 0x30, 0x41, 0x20, 0x44, 0x52, 0x42, 0x47, 0x00};
+#else
+# define DRBG_DEFAULT_PERS_STRING "OpenSSL NIST SP 800-90A DRBG"
+#endif
+
+typedef struct prov_drbg_st PROV_DRBG;
+
+/* DRBG status values */
+typedef enum drbg_status_e {
+ DRBG_UNINITIALISED,
+ DRBG_READY,
+ DRBG_ERROR
+} DRBG_STATUS;
+
+/*
+ * The state of all types of DRBGs.
+ */
+struct prov_drbg_st {
+ CRYPTO_RWLOCK *lock;
+ PROV_CTX *provctx;
+
+ /* Virtual functions are cache here */
+ int (*instantiate)(PROV_DRBG *drbg,
+ const unsigned char *entropy, size_t entropylen,
+ const unsigned char *nonce, size_t noncelen,
+ const unsigned char *pers, size_t perslen);
+ int (*uninstantiate)(PROV_DRBG *ctx);
+ int (*reseed)(PROV_DRBG *drbg, const unsigned char *ent, size_t ent_len,
+ const unsigned char *adin, size_t adin_len);
+ int (*generate)(PROV_DRBG *, unsigned char *out, size_t outlen,
+ const unsigned char *adin, size_t adin_len);
+
+ /* Parent PROV_RAND and its dispatch table functions */
+ void *parent;
+ OSSL_FUNC_rand_enable_locking_fn *parent_enable_locking;
+ OSSL_FUNC_rand_lock_fn *parent_lock;
+ OSSL_FUNC_rand_unlock_fn *parent_unlock;
+ OSSL_FUNC_rand_get_ctx_params_fn *parent_get_ctx_params;
+ OSSL_FUNC_rand_nonce_fn *parent_nonce;
+ OSSL_FUNC_rand_get_seed_fn *parent_get_seed;
+ OSSL_FUNC_rand_clear_seed_fn *parent_clear_seed;
+
+ const OSSL_DISPATCH *parent_dispatch;
+
+ /*
+ * Stores the return value of openssl_get_fork_id() as of when we last
+ * reseeded. The DRBG reseeds automatically whenever drbg->fork_id !=
+ * openssl_get_fork_id(). Used to provide fork-safety and reseed this
+ * DRBG in the child process.
+ */
+ int fork_id;
+ unsigned short flags; /* various external flags */
+
+ /*
+ * The following parameters are setup by the per-type "init" function.
+ *
+ * The supported types and their init functions are:
+ * (1) CTR_DRBG: drbg_ctr_init().
+ * (2) HMAC_DRBG: drbg_hmac_init().
+ * (3) HASH_DRBG: drbg_hash_init().
+ *
+ * The parameters are closely related to the ones described in
+ * section '10.2.1 CTR_DRBG' of [NIST SP 800-90Ar1], with one
+ * crucial difference: In the NIST standard, all counts are given
+ * in bits, whereas in OpenSSL entropy counts are given in bits
+ * and buffer lengths are given in bytes.
+ *
+ * Since this difference has lead to some confusion in the past,
+ * (see [GitHub Issue #2443], formerly [rt.openssl.org #4055])
+ * the 'len' suffix has been added to all buffer sizes for
+ * clarification.
+ */
+
+ unsigned int strength;
+ size_t max_request;
+ size_t min_entropylen, max_entropylen;
+ size_t min_noncelen, max_noncelen;
+ size_t max_perslen, max_adinlen;
+
+ /*
+ * Counts the number of generate requests since the last reseed
+ * (Starts at 1). This value is the reseed_counter as defined in
+ * NIST SP 800-90Ar1
+ */
+ unsigned int generate_counter;
+ /*
+ * Maximum number of generate requests until a reseed is required.
+ * This value is ignored if it is zero.
+ */
+ unsigned int reseed_interval;
+ /* Stores the time when the last reseeding occurred */
+ time_t reseed_time;
+ /*
+ * Specifies the maximum time interval (in seconds) between reseeds.
+ * This value is ignored if it is zero.
+ */
+ time_t reseed_time_interval;
+ /*
+ * Counts the number of reseeds since instantiation.
+ * This value is ignored if it is zero.
+ *
+ * This counter is used only for seed propagation from the <master> DRBG
+ * to its two children, the <public> and <private> DRBG. This feature is
+ * very special and its sole purpose is to ensure that any randomness which
+ * is added by PROV_add() or PROV_seed() will have an immediate effect on
+ * the output of PROV_bytes() resp. PROV_priv_bytes().
+ */
+ TSAN_QUALIFIER unsigned int reseed_counter;
+ unsigned int reseed_next_counter;
+ unsigned int parent_reseed_counter;
+
+ size_t seedlen;
+ DRBG_STATUS state;
+
+ /* DRBG specific data */
+ void *data;
+
+ /* Entropy and nonce gathering callbacks */
+ void *callback_arg;
+ OSSL_INOUT_CALLBACK *get_entropy_fn;
+ OSSL_CALLBACK *cleanup_entropy_fn;
+ OSSL_INOUT_CALLBACK *get_nonce_fn;
+ OSSL_CALLBACK *cleanup_nonce_fn;
+};
+
+PROV_DRBG *ossl_rand_drbg_new
+ (void *provctx, void *parent, const OSSL_DISPATCH *parent_dispatch,
+ int (*dnew)(PROV_DRBG *ctx),
+ int (*instantiate)(PROV_DRBG *drbg,
+ const unsigned char *entropy, size_t entropylen,
+ const unsigned char *nonce, size_t noncelen,
+ const unsigned char *pers, size_t perslen),
+ int (*uninstantiate)(PROV_DRBG *ctx),
+ int (*reseed)(PROV_DRBG *drbg, const unsigned char *ent, size_t ent_len,
+ const unsigned char *adin, size_t adin_len),
+ int (*generate)(PROV_DRBG *, unsigned char *out, size_t outlen,
+ const unsigned char *adin, size_t adin_len));
+void ossl_rand_drbg_free(PROV_DRBG *drbg);
+
+int ossl_prov_drbg_instantiate(PROV_DRBG *drbg, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *pers, size_t perslen);
+
+int ossl_prov_drbg_uninstantiate(PROV_DRBG *drbg);
+
+int ossl_prov_drbg_reseed(PROV_DRBG *drbg, int prediction_resistance,
+ const unsigned char *ent, size_t ent_len,
+ const unsigned char *adin, size_t adinlen);
+
+int ossl_prov_drbg_generate(PROV_DRBG *drbg, unsigned char *out, size_t outlen,
+ unsigned int strength, int prediction_resistance,
+ const unsigned char *adin, size_t adinlen);
+
+/* Seeding api */
+OSSL_FUNC_rand_get_seed_fn ossl_drbg_get_seed;
+OSSL_FUNC_rand_clear_seed_fn ossl_drbg_clear_seed;
+
+/* Verify that an array of numeric values is all zero */
+#define PROV_DRBG_VERYIFY_ZEROIZATION(v) \
+ { \
+ size_t i; \
+ \
+ for (i = 0; i < OSSL_NELEM(v); i++) \
+ if ((v)[i] != 0) \
+ return 0; \
+ }
+
+/* locking api */
+OSSL_FUNC_rand_enable_locking_fn ossl_drbg_enable_locking;
+OSSL_FUNC_rand_lock_fn ossl_drbg_lock;
+OSSL_FUNC_rand_unlock_fn ossl_drbg_unlock;
+
+/* Common parameters for all of our DRBGs */
+int ossl_drbg_get_ctx_params(PROV_DRBG *drbg, OSSL_PARAM params[]);
+int ossl_drbg_set_ctx_params(PROV_DRBG *drbg, const OSSL_PARAM params[]);
+
+#define OSSL_PARAM_DRBG_SETTABLE_CTX_COMMON \
+ OSSL_PARAM_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS, NULL), \
+ OSSL_PARAM_uint64(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL, NULL)
+
+#define OSSL_PARAM_DRBG_GETTABLE_CTX_COMMON \
+ OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL), \
+ OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL), \
+ OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL), \
+ OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MIN_ENTROPYLEN, NULL), \
+ OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MAX_ENTROPYLEN, NULL), \
+ OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MIN_NONCELEN, NULL), \
+ OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MAX_NONCELEN, NULL), \
+ OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MAX_PERSLEN, NULL), \
+ OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MAX_ADINLEN, NULL), \
+ OSSL_PARAM_uint(OSSL_DRBG_PARAM_RESEED_COUNTER, NULL), \
+ OSSL_PARAM_time_t(OSSL_DRBG_PARAM_RESEED_TIME, NULL), \
+ OSSL_PARAM_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS, NULL), \
+ OSSL_PARAM_uint64(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL, NULL)
+
+/* Continuous test "entropy" calls */
+size_t ossl_crngt_get_entropy(PROV_DRBG *drbg,
+ unsigned char **pout,
+ int entropy, size_t min_len, size_t max_len,
+ int prediction_resistance);
+void ossl_crngt_cleanup_entropy(PROV_DRBG *drbg,
+ unsigned char *out, size_t outlen);
+
+#endif
diff --git a/providers/implementations/rands/seed_src.c b/providers/implementations/rands/seed_src.c
new file mode 100644
index 000000000000..7a4b780bb469
--- /dev/null
+++ b/providers/implementations/rands/seed_src.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/rand.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/e_os2.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/randerr.h>
+#include <openssl/proverr.h>
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "crypto/rand.h"
+#include "crypto/rand_pool.h"
+
+static OSSL_FUNC_rand_newctx_fn seed_src_new;
+static OSSL_FUNC_rand_freectx_fn seed_src_free;
+static OSSL_FUNC_rand_instantiate_fn seed_src_instantiate;
+static OSSL_FUNC_rand_uninstantiate_fn seed_src_uninstantiate;
+static OSSL_FUNC_rand_generate_fn seed_src_generate;
+static OSSL_FUNC_rand_reseed_fn seed_src_reseed;
+static OSSL_FUNC_rand_gettable_ctx_params_fn seed_src_gettable_ctx_params;
+static OSSL_FUNC_rand_get_ctx_params_fn seed_src_get_ctx_params;
+static OSSL_FUNC_rand_verify_zeroization_fn seed_src_verify_zeroization;
+static OSSL_FUNC_rand_enable_locking_fn seed_src_enable_locking;
+static OSSL_FUNC_rand_lock_fn seed_src_lock;
+static OSSL_FUNC_rand_unlock_fn seed_src_unlock;
+static OSSL_FUNC_rand_get_seed_fn seed_get_seed;
+static OSSL_FUNC_rand_clear_seed_fn seed_clear_seed;
+
+typedef struct {
+ void *provctx;
+ int state;
+} PROV_SEED_SRC;
+
+static void *seed_src_new(void *provctx, void *parent,
+ const OSSL_DISPATCH *parent_dispatch)
+{
+ PROV_SEED_SRC *s;
+
+ if (parent != NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT);
+ return NULL;
+ }
+
+ s = OPENSSL_zalloc(sizeof(*s));
+ if (s == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ s->provctx = provctx;
+ s->state = EVP_RAND_STATE_UNINITIALISED;
+ return s;
+}
+
+static void seed_src_free(void *vseed)
+{
+ OPENSSL_free(vseed);
+}
+
+static int seed_src_instantiate(void *vseed, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *pstr, size_t pstr_len,
+ ossl_unused const OSSL_PARAM params[])
+{
+ PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed;
+
+ s->state = EVP_RAND_STATE_READY;
+ return 1;
+}
+
+static int seed_src_uninstantiate(void *vseed)
+{
+ PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed;
+
+ s->state = EVP_RAND_STATE_UNINITIALISED;
+ return 1;
+}
+
+static int seed_src_generate(void *vseed, unsigned char *out, size_t outlen,
+ unsigned int strength,
+ ossl_unused int prediction_resistance,
+ ossl_unused const unsigned char *adin,
+ ossl_unused size_t adin_len)
+{
+ PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed;
+ size_t entropy_available;
+ RAND_POOL *pool;
+
+ if (s->state != EVP_RAND_STATE_READY) {
+ ERR_raise(ERR_LIB_PROV,
+ s->state == EVP_RAND_STATE_ERROR ? PROV_R_IN_ERROR_STATE
+ : PROV_R_NOT_INSTANTIATED);
+ return 0;
+ }
+
+ pool = ossl_rand_pool_new(strength, 1, outlen, outlen);
+ if (pool == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ /* Get entropy by polling system entropy sources. */
+ entropy_available = ossl_pool_acquire_entropy(pool);
+
+ if (entropy_available > 0)
+ memcpy(out, ossl_rand_pool_buffer(pool), ossl_rand_pool_length(pool));
+
+ ossl_rand_pool_free(pool);
+ return entropy_available > 0;
+}
+
+static int seed_src_reseed(void *vseed,
+ ossl_unused int prediction_resistance,
+ ossl_unused const unsigned char *ent,
+ ossl_unused size_t ent_len,
+ ossl_unused const unsigned char *adin,
+ ossl_unused size_t adin_len)
+{
+ PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed;
+
+ if (s->state != EVP_RAND_STATE_READY) {
+ ERR_raise(ERR_LIB_PROV,
+ s->state == EVP_RAND_STATE_ERROR ? PROV_R_IN_ERROR_STATE
+ : PROV_R_NOT_INSTANTIATED);
+ return 0;
+ }
+ return 1;
+}
+
+static int seed_src_get_ctx_params(void *vseed, OSSL_PARAM params[])
+{
+ PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE);
+ if (p != NULL && !OSSL_PARAM_set_int(p, s->state))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH);
+ if (p != NULL && !OSSL_PARAM_set_int(p, 1024))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, 128))
+ return 0;
+ return 1;
+}
+
+static const OSSL_PARAM *seed_src_gettable_ctx_params(ossl_unused void *vseed,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL),
+ OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL),
+ OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL),
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+static int seed_src_verify_zeroization(ossl_unused void *vseed)
+{
+ return 1;
+}
+
+static size_t seed_get_seed(void *vseed, unsigned char **pout,
+ int entropy, size_t min_len, size_t max_len,
+ int prediction_resistance,
+ const unsigned char *adin, size_t adin_len)
+{
+ size_t bytes_needed;
+ unsigned char *p;
+
+ /*
+ * Figure out how many bytes we need.
+ * This assumes that the seed sources provide eight bits of entropy
+ * per byte. For lower quality sources, the formula will need to be
+ * different.
+ */
+ bytes_needed = entropy >= 0 ? (entropy + 7) / 8 : 0;
+ if (bytes_needed < min_len)
+ bytes_needed = min_len;
+ if (bytes_needed > max_len) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK);
+ return 0;
+ }
+
+ p = OPENSSL_secure_malloc(bytes_needed);
+ if (p == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (seed_src_generate(vseed, p, bytes_needed, 0, prediction_resistance,
+ adin, adin_len) != 0) {
+ *pout = p;
+ return bytes_needed;
+ }
+ OPENSSL_secure_clear_free(p, bytes_needed);
+ return 0;
+}
+
+static void seed_clear_seed(ossl_unused void *vdrbg,
+ unsigned char *out, size_t outlen)
+{
+ OPENSSL_secure_clear_free(out, outlen);
+}
+
+static int seed_src_enable_locking(ossl_unused void *vseed)
+{
+ return 1;
+}
+
+int seed_src_lock(ossl_unused void *vctx)
+{
+ return 1;
+}
+
+void seed_src_unlock(ossl_unused void *vctx)
+{
+}
+
+const OSSL_DISPATCH ossl_seed_src_functions[] = {
+ { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))seed_src_new },
+ { OSSL_FUNC_RAND_FREECTX, (void(*)(void))seed_src_free },
+ { OSSL_FUNC_RAND_INSTANTIATE,
+ (void(*)(void))seed_src_instantiate },
+ { OSSL_FUNC_RAND_UNINSTANTIATE,
+ (void(*)(void))seed_src_uninstantiate },
+ { OSSL_FUNC_RAND_GENERATE, (void(*)(void))seed_src_generate },
+ { OSSL_FUNC_RAND_RESEED, (void(*)(void))seed_src_reseed },
+ { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))seed_src_enable_locking },
+ { OSSL_FUNC_RAND_LOCK, (void(*)(void))seed_src_lock },
+ { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))seed_src_unlock },
+ { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
+ (void(*)(void))seed_src_gettable_ctx_params },
+ { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))seed_src_get_ctx_params },
+ { OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
+ (void(*)(void))seed_src_verify_zeroization },
+ { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))seed_get_seed },
+ { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))seed_clear_seed },
+ { 0, NULL }
+};
diff --git a/providers/implementations/rands/seeding/build.info b/providers/implementations/rands/seeding/build.info
new file mode 100644
index 000000000000..2788146ad42a
--- /dev/null
+++ b/providers/implementations/rands/seeding/build.info
@@ -0,0 +1,10 @@
+$COMMON=rand_unix.c rand_win.c rand_tsc.c rand_cpu_x86.c
+IF[{- $config{target} =~ /vxworks/i -}]
+ $COMMON=$COMMON rand_vxworks.c
+ENDIF
+IF[{- $config{target} =~ /vms/i -}]
+ $COMMON=$COMMON rand_vms.c
+ENDIF
+
+SOURCE[../../../libdefault.a]=$COMMON
+
diff --git a/providers/implementations/rands/seeding/rand_cpu_x86.c b/providers/implementations/rands/seeding/rand_cpu_x86.c
new file mode 100644
index 000000000000..0e062fa45aa2
--- /dev/null
+++ b/providers/implementations/rands/seeding/rand_cpu_x86.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/cryptlib.h"
+#include <openssl/opensslconf.h>
+#include "crypto/rand_pool.h"
+#include "prov/seeding.h"
+
+#ifdef OPENSSL_RAND_SEED_RDCPU
+# if defined(OPENSSL_SYS_TANDEM) && defined(_TNS_X_TARGET)
+# include <builtin.h> /* _rdrand64 */
+# include <string.h> /* memcpy */
+# else
+size_t OPENSSL_ia32_rdseed_bytes(unsigned char *buf, size_t len);
+size_t OPENSSL_ia32_rdrand_bytes(unsigned char *buf, size_t len);
+# endif
+
+static size_t get_hardware_random_value(unsigned char *buf, size_t len);
+
+/*
+ * Acquire entropy using Intel-specific cpu instructions
+ *
+ * Uses the RDSEED instruction if available, otherwise uses
+ * RDRAND if available.
+ *
+ * For the differences between RDSEED and RDRAND, and why RDSEED
+ * is the preferred choice, see https://goo.gl/oK3KcN
+ *
+ * Returns the total entropy count, if it exceeds the requested
+ * entropy count. Otherwise, returns an entropy count of 0.
+ */
+size_t ossl_prov_acquire_entropy_from_cpu(RAND_POOL *pool)
+{
+ size_t bytes_needed;
+ unsigned char *buffer;
+
+ bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
+ if (bytes_needed > 0) {
+ buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
+
+ if (buffer != NULL) {
+ if (get_hardware_random_value(buffer, bytes_needed) == bytes_needed) {
+ ossl_rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed);
+ } else {
+ ossl_rand_pool_add_end(pool, 0, 0);
+ }
+ }
+ }
+
+ return ossl_rand_pool_entropy_available(pool);
+}
+
+#if defined(OPENSSL_SYS_TANDEM) && defined(_TNS_X_TARGET)
+/* Obtain random bytes from the x86 hardware random function in 64 bit chunks */
+static size_t get_hardware_random_value(unsigned char *buf, size_t len)
+{
+ size_t bytes_remaining = len;
+
+ while (bytes_remaining > 0) {
+ /* Always use 64 bit fetch, then use the lower bytes as needed. */
+ /* The platform is big-endian. */
+ uint64_t random_value = 0;
+
+ if (_rdrand64(&random_value) != 0) {
+ unsigned char *random_buffer = (unsigned char *)&random_value;
+
+ if (bytes_remaining >= sizeof(random_value)) {
+ memcpy(buf, random_buffer, sizeof(random_value));
+ bytes_remaining -= sizeof(random_value);
+ buf += sizeof(random_value);
+ } else {
+ memcpy(buf,
+ random_buffer + (sizeof(random_value) - bytes_remaining),
+ bytes_remaining);
+ bytes_remaining = 0; /* This will terminate the loop */
+ }
+ } else
+ break;
+ }
+ if (bytes_remaining == 0)
+ return len;
+ return 0;
+}
+#else
+static size_t get_hardware_random_value(unsigned char *buf, size_t len) {
+ /* Whichever comes first, use RDSEED, RDRAND or nothing */
+ if ((OPENSSL_ia32cap_P[2] & (1 << 18)) != 0) {
+ if (OPENSSL_ia32_rdseed_bytes(buf, len) != len)
+ return 0;
+ } else if ((OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) != 0) {
+ if (OPENSSL_ia32_rdrand_bytes(buf, len) != len)
+ return 0;
+ } else
+ return 0;
+ return len;
+}
+#endif
+
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/providers/implementations/rands/seeding/rand_tsc.c b/providers/implementations/rands/seeding/rand_tsc.c
new file mode 100644
index 000000000000..98dd836b24d9
--- /dev/null
+++ b/providers/implementations/rands/seeding/rand_tsc.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/cryptlib.h"
+#include <openssl/opensslconf.h>
+#include "crypto/rand_pool.h"
+#include "prov/seeding.h"
+
+#ifdef OPENSSL_RAND_SEED_RDTSC
+/*
+ * IMPORTANT NOTE: It is not currently possible to use this code
+ * because we are not sure about the amount of randomness it provides.
+ * Some SP800-90B tests have been run, but there is internal skepticism.
+ * So for now this code is not used.
+ */
+# error "RDTSC enabled? Should not be possible!"
+
+/*
+ * Acquire entropy from high-speed clock
+ *
+ * Since we get some randomness from the low-order bits of the
+ * high-speed clock, it can help.
+ *
+ * Returns the total entropy count, if it exceeds the requested
+ * entropy count. Otherwise, returns an entropy count of 0.
+ */
+size_t ossl_prov_acquire_entropy_from_tsc(RAND_POOL *pool)
+{
+ unsigned char c;
+ int i;
+
+ if ((OPENSSL_ia32cap_P[0] & (1 << 4)) != 0) {
+ for (i = 0; i < TSC_READ_COUNT; i++) {
+ c = (unsigned char)(OPENSSL_rdtsc() & 0xFF);
+ ossl_rand_pool_add(pool, &c, 1, 4);
+ }
+ }
+ return ossl_rand_pool_entropy_available(pool);
+}
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/providers/implementations/rands/seeding/rand_unix.c b/providers/implementations/rands/seeding/rand_unix.c
new file mode 100644
index 000000000000..750afca58ed7
--- /dev/null
+++ b/providers/implementations/rands/seeding/rand_unix.c
@@ -0,0 +1,882 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+#include "../e_os.h"
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/rand.h>
+#include <openssl/crypto.h>
+#include "crypto/rand_pool.h"
+#include "crypto/rand.h"
+#include <stdio.h>
+#include "internal/dso.h"
+#include "prov/seeding.h"
+
+#ifdef __linux
+# include <sys/syscall.h>
+# ifdef DEVRANDOM_WAIT
+# include <sys/shm.h>
+# include <sys/utsname.h>
+# endif
+#endif
+#if (defined(__FreeBSD__) || defined(__NetBSD__)) && !defined(OPENSSL_SYS_UEFI)
+# include <sys/types.h>
+# include <sys/sysctl.h>
+# include <sys/param.h>
+#endif
+#if defined(__OpenBSD__)
+# include <sys/param.h>
+#endif
+#if defined(__DragonFly__)
+# include <sys/param.h>
+# include <sys/random.h>
+#endif
+
+#if (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS)) \
+ || defined(__DJGPP__)
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+# include <unistd.h>
+# include <sys/time.h>
+
+static uint64_t get_time_stamp(void);
+static uint64_t get_timer_bits(void);
+
+/* Macro to convert two thirty two bit values into a sixty four bit one */
+# define TWO32TO64(a, b) ((((uint64_t)(a)) << 32) + (b))
+
+/*
+ * Check for the existence and support of POSIX timers. The standard
+ * says that the _POSIX_TIMERS macro will have a positive value if they
+ * are available.
+ *
+ * However, we want an additional constraint: that the timer support does
+ * not require an extra library dependency. Early versions of glibc
+ * require -lrt to be specified on the link line to access the timers,
+ * so this needs to be checked for.
+ *
+ * It is worse because some libraries define __GLIBC__ but don't
+ * support the version testing macro (e.g. uClibc). This means
+ * an extra check is needed.
+ *
+ * The final condition is:
+ * "have posix timers and either not glibc or glibc without -lrt"
+ *
+ * The nested #if sequences are required to avoid using a parameterised
+ * macro that might be undefined.
+ */
+# undef OSSL_POSIX_TIMER_OKAY
+/* On some systems, _POSIX_TIMERS is defined but empty.
+ * Subtracting by 0 when comparing avoids an error in this case. */
+# if defined(_POSIX_TIMERS) && _POSIX_TIMERS -0 > 0
+# if defined(__GLIBC__)
+# if defined(__GLIBC_PREREQ)
+# if __GLIBC_PREREQ(2, 17)
+# define OSSL_POSIX_TIMER_OKAY
+# endif
+# endif
+# else
+# define OSSL_POSIX_TIMER_OKAY
+# endif
+# endif
+#endif /* (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS))
+ || defined(__DJGPP__) */
+
+#if defined(OPENSSL_RAND_SEED_NONE)
+/* none means none. this simplifies the following logic */
+# undef OPENSSL_RAND_SEED_OS
+# undef OPENSSL_RAND_SEED_GETRANDOM
+# undef OPENSSL_RAND_SEED_LIBRANDOM
+# undef OPENSSL_RAND_SEED_DEVRANDOM
+# undef OPENSSL_RAND_SEED_RDTSC
+# undef OPENSSL_RAND_SEED_RDCPU
+# undef OPENSSL_RAND_SEED_EGD
+#endif
+
+#if defined(OPENSSL_SYS_UEFI) && !defined(OPENSSL_RAND_SEED_NONE)
+# error "UEFI only supports seeding NONE"
+#endif
+
+#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) \
+ || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_VXWORKS) \
+ || defined(OPENSSL_SYS_UEFI))
+
+# if defined(OPENSSL_SYS_VOS)
+
+# ifndef OPENSSL_RAND_SEED_OS
+# error "Unsupported seeding method configured; must be os"
+# endif
+
+# if defined(OPENSSL_SYS_VOS_HPPA) && defined(OPENSSL_SYS_VOS_IA32)
+# error "Unsupported HP-PA and IA32 at the same time."
+# endif
+# if !defined(OPENSSL_SYS_VOS_HPPA) && !defined(OPENSSL_SYS_VOS_IA32)
+# error "Must have one of HP-PA or IA32"
+# endif
+
+/*
+ * The following algorithm repeatedly samples the real-time clock (RTC) to
+ * generate a sequence of unpredictable data. The algorithm relies upon the
+ * uneven execution speed of the code (due to factors such as cache misses,
+ * interrupts, bus activity, and scheduling) and upon the rather large
+ * relative difference between the speed of the clock and the rate at which
+ * it can be read. If it is ported to an environment where execution speed
+ * is more constant or where the RTC ticks at a much slower rate, or the
+ * clock can be read with fewer instructions, it is likely that the results
+ * would be far more predictable. This should only be used for legacy
+ * platforms.
+ *
+ * As a precaution, we assume only 2 bits of entropy per byte.
+ */
+size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
+{
+ short int code;
+ int i, k;
+ size_t bytes_needed;
+ struct timespec ts;
+ unsigned char v;
+# ifdef OPENSSL_SYS_VOS_HPPA
+ long duration;
+ extern void s$sleep(long *_duration, short int *_code);
+# else
+ long long duration;
+ extern void s$sleep2(long long *_duration, short int *_code);
+# endif
+
+ bytes_needed = ossl_rand_pool_bytes_needed(pool, 4 /*entropy_factor*/);
+
+ for (i = 0; i < bytes_needed; i++) {
+ /*
+ * burn some cpu; hope for interrupts, cache collisions, bus
+ * interference, etc.
+ */
+ for (k = 0; k < 99; k++)
+ ts.tv_nsec = random();
+
+# ifdef OPENSSL_SYS_VOS_HPPA
+ /* sleep for 1/1024 of a second (976 us). */
+ duration = 1;
+ s$sleep(&duration, &code);
+# else
+ /* sleep for 1/65536 of a second (15 us). */
+ duration = 1;
+ s$sleep2(&duration, &code);
+# endif
+
+ /* Get wall clock time, take 8 bits. */
+ clock_gettime(CLOCK_REALTIME, &ts);
+ v = (unsigned char)(ts.tv_nsec & 0xFF);
+ ossl_rand_pool_add(pool, arg, &v, sizeof(v) , 2);
+ }
+ return ossl_rand_pool_entropy_available(pool);
+}
+
+void ossl_rand_pool_cleanup(void)
+{
+}
+
+void ossl_rand_pool_keep_random_devices_open(int keep)
+{
+}
+
+# else
+
+# if defined(OPENSSL_RAND_SEED_EGD) && \
+ (defined(OPENSSL_NO_EGD) || !defined(DEVRANDOM_EGD))
+# error "Seeding uses EGD but EGD is turned off or no device given"
+# endif
+
+# if defined(OPENSSL_RAND_SEED_DEVRANDOM) && !defined(DEVRANDOM)
+# error "Seeding uses urandom but DEVRANDOM is not configured"
+# endif
+
+# if defined(OPENSSL_RAND_SEED_OS)
+# if !defined(DEVRANDOM)
+# error "OS seeding requires DEVRANDOM to be configured"
+# endif
+# define OPENSSL_RAND_SEED_GETRANDOM
+# define OPENSSL_RAND_SEED_DEVRANDOM
+# endif
+
+# if defined(OPENSSL_RAND_SEED_LIBRANDOM)
+# error "librandom not (yet) supported"
+# endif
+
+# if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
+/*
+ * sysctl_random(): Use sysctl() to read a random number from the kernel
+ * Returns the number of bytes returned in buf on success, -1 on failure.
+ */
+static ssize_t sysctl_random(char *buf, size_t buflen)
+{
+ int mib[2];
+ size_t done = 0;
+ size_t len;
+
+ /*
+ * Note: sign conversion between size_t and ssize_t is safe even
+ * without a range check, see comment in syscall_random()
+ */
+
+ /*
+ * On FreeBSD old implementations returned longs, newer versions support
+ * variable sizes up to 256 byte. The code below would not work properly
+ * when the sysctl returns long and we want to request something not a
+ * multiple of longs, which should never be the case.
+ */
+#if defined(__FreeBSD__)
+ if (!ossl_assert(buflen % sizeof(long) == 0)) {
+ errno = EINVAL;
+ return -1;
+ }
+#endif
+
+ /*
+ * On NetBSD before 4.0 KERN_ARND was an alias for KERN_URND, and only
+ * filled in an int, leaving the rest uninitialized. Since NetBSD 4.0
+ * it returns a variable number of bytes with the current version supporting
+ * up to 256 bytes.
+ * Just return an error on older NetBSD versions.
+ */
+#if defined(__NetBSD__) && __NetBSD_Version__ < 400000000
+ errno = ENOSYS;
+ return -1;
+#endif
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_ARND;
+
+ do {
+ len = buflen > 256 ? 256 : buflen;
+ if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)
+ return done > 0 ? done : -1;
+ done += len;
+ buf += len;
+ buflen -= len;
+ } while (buflen > 0);
+
+ return done;
+}
+# endif
+
+# if defined(OPENSSL_RAND_SEED_GETRANDOM)
+
+# if defined(__linux) && !defined(__NR_getrandom)
+# if defined(__arm__)
+# define __NR_getrandom (__NR_SYSCALL_BASE+384)
+# elif defined(__i386__)
+# define __NR_getrandom 355
+# elif defined(__x86_64__)
+# if defined(__ILP32__)
+# define __NR_getrandom (__X32_SYSCALL_BIT + 318)
+# else
+# define __NR_getrandom 318
+# endif
+# elif defined(__xtensa__)
+# define __NR_getrandom 338
+# elif defined(__s390__) || defined(__s390x__)
+# define __NR_getrandom 349
+# elif defined(__bfin__)
+# define __NR_getrandom 389
+# elif defined(__powerpc__)
+# define __NR_getrandom 359
+# elif defined(__mips__) || defined(__mips64)
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+# define __NR_getrandom (__NR_Linux + 353)
+# elif _MIPS_SIM == _MIPS_SIM_ABI64
+# define __NR_getrandom (__NR_Linux + 313)
+# elif _MIPS_SIM == _MIPS_SIM_NABI32
+# define __NR_getrandom (__NR_Linux + 317)
+# endif
+# elif defined(__hppa__)
+# define __NR_getrandom (__NR_Linux + 339)
+# elif defined(__sparc__)
+# define __NR_getrandom 347
+# elif defined(__ia64__)
+# define __NR_getrandom 1339
+# elif defined(__alpha__)
+# define __NR_getrandom 511
+# elif defined(__sh__)
+# if defined(__SH5__)
+# define __NR_getrandom 373
+# else
+# define __NR_getrandom 384
+# endif
+# elif defined(__avr32__)
+# define __NR_getrandom 317
+# elif defined(__microblaze__)
+# define __NR_getrandom 385
+# elif defined(__m68k__)
+# define __NR_getrandom 352
+# elif defined(__cris__)
+# define __NR_getrandom 356
+# elif defined(__aarch64__)
+# define __NR_getrandom 278
+# else /* generic */
+# define __NR_getrandom 278
+# endif
+# endif
+
+/*
+ * syscall_random(): Try to get random data using a system call
+ * returns the number of bytes returned in buf, or < 0 on error.
+ */
+static ssize_t syscall_random(void *buf, size_t buflen)
+{
+ /*
+ * Note: 'buflen' equals the size of the buffer which is used by the
+ * get_entropy() callback of the RAND_DRBG. It is roughly bounded by
+ *
+ * 2 * RAND_POOL_FACTOR * (RAND_DRBG_STRENGTH / 8) = 2^14
+ *
+ * which is way below the OSSL_SSIZE_MAX limit. Therefore sign conversion
+ * between size_t and ssize_t is safe even without a range check.
+ */
+
+ /*
+ * Do runtime detection to find getentropy().
+ *
+ * Known OSs that should support this:
+ * - Darwin since 16 (OSX 10.12, IOS 10.0).
+ * - Solaris since 11.3
+ * - OpenBSD since 5.6
+ * - Linux since 3.17 with glibc 2.25
+ * - FreeBSD since 12.0 (1200061)
+ *
+ * Note: Sometimes getentropy() can be provided but not implemented
+ * internally. So we need to check errno for ENOSYS
+ */
+# if !defined(__DragonFly__) && !defined(__NetBSD__)
+# if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux)
+ extern int getentropy(void *buffer, size_t length) __attribute__((weak));
+
+ if (getentropy != NULL) {
+ if (getentropy(buf, buflen) == 0)
+ return (ssize_t)buflen;
+ if (errno != ENOSYS)
+ return -1;
+ }
+# elif defined(OPENSSL_APPLE_CRYPTO_RANDOM)
+
+ if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess)
+ return (ssize_t)buflen;
+
+ return -1;
+# else
+ union {
+ void *p;
+ int (*f)(void *buffer, size_t length);
+ } p_getentropy;
+
+ /*
+ * We could cache the result of the lookup, but we normally don't
+ * call this function often.
+ */
+ ERR_set_mark();
+ p_getentropy.p = DSO_global_lookup("getentropy");
+ ERR_pop_to_mark();
+ if (p_getentropy.p != NULL)
+ return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1;
+# endif
+# endif /* !__DragonFly__ */
+
+ /* Linux supports this since version 3.17 */
+# if defined(__linux) && defined(__NR_getrandom)
+ return syscall(__NR_getrandom, buf, buflen, 0);
+# elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
+ return sysctl_random(buf, buflen);
+# elif (defined(__DragonFly__) && __DragonFly_version >= 500700) \
+ || (defined(__NetBSD__) && __NetBSD_Version >= 1000000000)
+ return getrandom(buf, buflen, 0);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+# endif /* defined(OPENSSL_RAND_SEED_GETRANDOM) */
+
+# if defined(OPENSSL_RAND_SEED_DEVRANDOM)
+static const char *random_device_paths[] = { DEVRANDOM };
+static struct random_device {
+ int fd;
+ dev_t dev;
+ ino_t ino;
+ mode_t mode;
+ dev_t rdev;
+} random_devices[OSSL_NELEM(random_device_paths)];
+static int keep_random_devices_open = 1;
+
+# if defined(__linux) && defined(DEVRANDOM_WAIT) \
+ && defined(OPENSSL_RAND_SEED_GETRANDOM)
+static void *shm_addr;
+
+static void cleanup_shm(void)
+{
+ shmdt(shm_addr);
+}
+
+/*
+ * Ensure that the system randomness source has been adequately seeded.
+ * This is done by having the first start of libcrypto, wait until the device
+ * /dev/random becomes able to supply a byte of entropy. Subsequent starts
+ * of the library and later reseedings do not need to do this.
+ */
+static int wait_random_seeded(void)
+{
+ static int seeded = OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID < 0;
+ static const int kernel_version[] = { DEVRANDOM_SAFE_KERNEL };
+ int kernel[2];
+ int shm_id, fd, r;
+ char c, *p;
+ struct utsname un;
+ fd_set fds;
+
+ if (!seeded) {
+ /* See if anything has created the global seeded indication */
+ if ((shm_id = shmget(OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID, 1, 0)) == -1) {
+ /*
+ * Check the kernel's version and fail if it is too recent.
+ *
+ * Linux kernels from 4.8 onwards do not guarantee that
+ * /dev/urandom is properly seeded when /dev/random becomes
+ * readable. However, such kernels support the getentropy(2)
+ * system call and this should always succeed which renders
+ * this alternative but essentially identical source moot.
+ */
+ if (uname(&un) == 0) {
+ kernel[0] = atoi(un.release);
+ p = strchr(un.release, '.');
+ kernel[1] = p == NULL ? 0 : atoi(p + 1);
+ if (kernel[0] > kernel_version[0]
+ || (kernel[0] == kernel_version[0]
+ && kernel[1] >= kernel_version[1])) {
+ return 0;
+ }
+ }
+ /* Open /dev/random and wait for it to be readable */
+ if ((fd = open(DEVRANDOM_WAIT, O_RDONLY)) != -1) {
+ if (DEVRANDM_WAIT_USE_SELECT && fd < FD_SETSIZE) {
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+ while ((r = select(fd + 1, &fds, NULL, NULL, NULL)) < 0
+ && errno == EINTR);
+ } else {
+ while ((r = read(fd, &c, 1)) < 0 && errno == EINTR);
+ }
+ close(fd);
+ if (r == 1) {
+ seeded = 1;
+ /* Create the shared memory indicator */
+ shm_id = shmget(OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID, 1,
+ IPC_CREAT | S_IRUSR | S_IRGRP | S_IROTH);
+ }
+ }
+ }
+ if (shm_id != -1) {
+ seeded = 1;
+ /*
+ * Map the shared memory to prevent its premature destruction.
+ * If this call fails, it isn't a big problem.
+ */
+ shm_addr = shmat(shm_id, NULL, SHM_RDONLY);
+ if (shm_addr != (void *)-1)
+ OPENSSL_atexit(&cleanup_shm);
+ }
+ }
+ return seeded;
+}
+# else /* defined __linux && DEVRANDOM_WAIT && OPENSSL_RAND_SEED_GETRANDOM */
+static int wait_random_seeded(void)
+{
+ return 1;
+}
+# endif
+
+/*
+ * Verify that the file descriptor associated with the random source is
+ * still valid. The rationale for doing this is the fact that it is not
+ * uncommon for daemons to close all open file handles when daemonizing.
+ * So the handle might have been closed or even reused for opening
+ * another file.
+ */
+static int check_random_device(struct random_device * rd)
+{
+ struct stat st;
+
+ return rd->fd != -1
+ && fstat(rd->fd, &st) != -1
+ && rd->dev == st.st_dev
+ && rd->ino == st.st_ino
+ && ((rd->mode ^ st.st_mode) & ~(S_IRWXU | S_IRWXG | S_IRWXO)) == 0
+ && rd->rdev == st.st_rdev;
+}
+
+/*
+ * Open a random device if required and return its file descriptor or -1 on error
+ */
+static int get_random_device(size_t n)
+{
+ struct stat st;
+ struct random_device * rd = &random_devices[n];
+
+ /* reuse existing file descriptor if it is (still) valid */
+ if (check_random_device(rd))
+ return rd->fd;
+
+ /* open the random device ... */
+ if ((rd->fd = open(random_device_paths[n], O_RDONLY)) == -1)
+ return rd->fd;
+
+ /* ... and cache its relevant stat(2) data */
+ if (fstat(rd->fd, &st) != -1) {
+ rd->dev = st.st_dev;
+ rd->ino = st.st_ino;
+ rd->mode = st.st_mode;
+ rd->rdev = st.st_rdev;
+ } else {
+ close(rd->fd);
+ rd->fd = -1;
+ }
+
+ return rd->fd;
+}
+
+/*
+ * Close a random device making sure it is a random device
+ */
+static void close_random_device(size_t n)
+{
+ struct random_device * rd = &random_devices[n];
+
+ if (check_random_device(rd))
+ close(rd->fd);
+ rd->fd = -1;
+}
+
+int ossl_rand_pool_init(void)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(random_devices); i++)
+ random_devices[i].fd = -1;
+
+ return 1;
+}
+
+void ossl_rand_pool_cleanup(void)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(random_devices); i++)
+ close_random_device(i);
+}
+
+void ossl_rand_pool_keep_random_devices_open(int keep)
+{
+ if (!keep)
+ ossl_rand_pool_cleanup();
+
+ keep_random_devices_open = keep;
+}
+
+# else /* !defined(OPENSSL_RAND_SEED_DEVRANDOM) */
+
+int ossl_rand_pool_init(void)
+{
+ return 1;
+}
+
+void ossl_rand_pool_cleanup(void)
+{
+}
+
+void ossl_rand_pool_keep_random_devices_open(int keep)
+{
+}
+
+# endif /* defined(OPENSSL_RAND_SEED_DEVRANDOM) */
+
+/*
+ * Try the various seeding methods in turn, exit when successful.
+ *
+ * If more than one entropy source is available, is it
+ * preferable to stop as soon as enough entropy has been collected
+ * (as favored by @rsalz) or should one rather be defensive and add
+ * more entropy than requested and/or from different sources?
+ *
+ * Currently, the user can select multiple entropy sources in the
+ * configure step, yet in practice only the first available source
+ * will be used. A more flexible solution has been requested, but
+ * currently it is not clear how this can be achieved without
+ * overengineering the problem. There are many parameters which
+ * could be taken into account when selecting the order and amount
+ * of input from the different entropy sources (trust, quality,
+ * possibility of blocking).
+ */
+size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
+{
+# if defined(OPENSSL_RAND_SEED_NONE)
+ return ossl_rand_pool_entropy_available(pool);
+# else
+ size_t entropy_available = 0;
+
+ (void)entropy_available; /* avoid compiler warning */
+
+# if defined(OPENSSL_RAND_SEED_GETRANDOM)
+ {
+ size_t bytes_needed;
+ unsigned char *buffer;
+ ssize_t bytes;
+ /* Maximum allowed number of consecutive unsuccessful attempts */
+ int attempts = 3;
+
+ bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
+ while (bytes_needed != 0 && attempts-- > 0) {
+ buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
+ bytes = syscall_random(buffer, bytes_needed);
+ if (bytes > 0) {
+ ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
+ bytes_needed -= bytes;
+ attempts = 3; /* reset counter after successful attempt */
+ } else if (bytes < 0 && errno != EINTR) {
+ break;
+ }
+ }
+ }
+ entropy_available = ossl_rand_pool_entropy_available(pool);
+ if (entropy_available > 0)
+ return entropy_available;
+# endif
+
+# if defined(OPENSSL_RAND_SEED_LIBRANDOM)
+ {
+ /* Not yet implemented. */
+ }
+# endif
+
+# if defined(OPENSSL_RAND_SEED_DEVRANDOM)
+ if (wait_random_seeded()) {
+ size_t bytes_needed;
+ unsigned char *buffer;
+ size_t i;
+
+ bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
+ for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths);
+ i++) {
+ ssize_t bytes = 0;
+ /* Maximum number of consecutive unsuccessful attempts */
+ int attempts = 3;
+ const int fd = get_random_device(i);
+
+ if (fd == -1)
+ continue;
+
+ while (bytes_needed != 0 && attempts-- > 0) {
+ buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
+ bytes = read(fd, buffer, bytes_needed);
+
+ if (bytes > 0) {
+ ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
+ bytes_needed -= bytes;
+ attempts = 3; /* reset counter on successful attempt */
+ } else if (bytes < 0 && errno != EINTR) {
+ break;
+ }
+ }
+ if (bytes < 0 || !keep_random_devices_open)
+ close_random_device(i);
+
+ bytes_needed = ossl_rand_pool_bytes_needed(pool, 1);
+ }
+ entropy_available = ossl_rand_pool_entropy_available(pool);
+ if (entropy_available > 0)
+ return entropy_available;
+ }
+# endif
+
+# if defined(OPENSSL_RAND_SEED_RDTSC)
+ entropy_available = ossl_prov_acquire_entropy_from_tsc(pool);
+ if (entropy_available > 0)
+ return entropy_available;
+# endif
+
+# if defined(OPENSSL_RAND_SEED_RDCPU)
+ entropy_available = ossl_prov_acquire_entropy_from_cpu(pool);
+ if (entropy_available > 0)
+ return entropy_available;
+# endif
+
+# if defined(OPENSSL_RAND_SEED_EGD)
+ {
+ static const char *paths[] = { DEVRANDOM_EGD, NULL };
+ size_t bytes_needed;
+ unsigned char *buffer;
+ int i;
+
+ bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
+ for (i = 0; bytes_needed > 0 && paths[i] != NULL; i++) {
+ size_t bytes = 0;
+ int num;
+
+ buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
+ num = RAND_query_egd_bytes(paths[i],
+ buffer, (int)bytes_needed);
+ if (num == (int)bytes_needed)
+ bytes = bytes_needed;
+
+ ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
+ bytes_needed = ossl_rand_pool_bytes_needed(pool, 1);
+ }
+ entropy_available = ossl_rand_pool_entropy_available(pool);
+ if (entropy_available > 0)
+ return entropy_available;
+ }
+# endif
+
+ return ossl_rand_pool_entropy_available(pool);
+# endif
+}
+# endif
+#endif
+
+#if (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS)) \
+ || defined(__DJGPP__)
+int ossl_pool_add_nonce_data(RAND_POOL *pool)
+{
+ struct {
+ pid_t pid;
+ CRYPTO_THREAD_ID tid;
+ uint64_t time;
+ } data;
+
+ /* Erase the entire structure including any padding */
+ memset(&data, 0, sizeof(data));
+
+ /*
+ * Add process id, thread id, and a high resolution timestamp to
+ * ensure that the nonce is unique with high probability for
+ * different process instances.
+ */
+ data.pid = getpid();
+ data.tid = CRYPTO_THREAD_get_current_id();
+ data.time = get_time_stamp();
+
+ return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
+}
+
+int ossl_rand_pool_add_additional_data(RAND_POOL *pool)
+{
+ struct {
+ int fork_id;
+ CRYPTO_THREAD_ID tid;
+ uint64_t time;
+ } data;
+
+ /* Erase the entire structure including any padding */
+ memset(&data, 0, sizeof(data));
+
+ /*
+ * Add some noise from the thread id and a high resolution timer.
+ * The fork_id adds some extra fork-safety.
+ * The thread id adds a little randomness if the drbg is accessed
+ * concurrently (which is the case for the <master> drbg).
+ */
+ data.fork_id = openssl_get_fork_id();
+ data.tid = CRYPTO_THREAD_get_current_id();
+ data.time = get_timer_bits();
+
+ return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
+}
+
+
+/*
+ * Get the current time with the highest possible resolution
+ *
+ * The time stamp is added to the nonce, so it is optimized for not repeating.
+ * The current time is ideal for this purpose, provided the computer's clock
+ * is synchronized.
+ */
+static uint64_t get_time_stamp(void)
+{
+# if defined(OSSL_POSIX_TIMER_OKAY)
+ {
+ struct timespec ts;
+
+ if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
+ return TWO32TO64(ts.tv_sec, ts.tv_nsec);
+ }
+# endif
+# if defined(__unix__) \
+ || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
+ {
+ struct timeval tv;
+
+ if (gettimeofday(&tv, NULL) == 0)
+ return TWO32TO64(tv.tv_sec, tv.tv_usec);
+ }
+# endif
+ return time(NULL);
+}
+
+/*
+ * Get an arbitrary timer value of the highest possible resolution
+ *
+ * The timer value is added as random noise to the additional data,
+ * which is not considered a trusted entropy sourec, so any result
+ * is acceptable.
+ */
+static uint64_t get_timer_bits(void)
+{
+ uint64_t res = OPENSSL_rdtsc();
+
+ if (res != 0)
+ return res;
+
+# if defined(__sun) || defined(__hpux)
+ return gethrtime();
+# elif defined(_AIX)
+ {
+ timebasestruct_t t;
+
+ read_wall_time(&t, TIMEBASE_SZ);
+ return TWO32TO64(t.tb_high, t.tb_low);
+ }
+# elif defined(OSSL_POSIX_TIMER_OKAY)
+ {
+ struct timespec ts;
+
+# ifdef CLOCK_BOOTTIME
+# define CLOCK_TYPE CLOCK_BOOTTIME
+# elif defined(_POSIX_MONOTONIC_CLOCK)
+# define CLOCK_TYPE CLOCK_MONOTONIC
+# else
+# define CLOCK_TYPE CLOCK_REALTIME
+# endif
+
+ if (clock_gettime(CLOCK_TYPE, &ts) == 0)
+ return TWO32TO64(ts.tv_sec, ts.tv_nsec);
+ }
+# endif
+# if defined(__unix__) \
+ || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
+ {
+ struct timeval tv;
+
+ if (gettimeofday(&tv, NULL) == 0)
+ return TWO32TO64(tv.tv_sec, tv.tv_usec);
+ }
+# endif
+ return time(NULL);
+}
+#endif /* (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS))
+ || defined(__DJGPP__) */
diff --git a/providers/implementations/rands/seeding/rand_vms.c b/providers/implementations/rands/seeding/rand_vms.c
new file mode 100644
index 000000000000..f12ecb3b075e
--- /dev/null
+++ b/providers/implementations/rands/seeding/rand_vms.c
@@ -0,0 +1,615 @@
+/*
+ * Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "e_os.h"
+
+#define __NEW_STARLET 1 /* New starlet definitions since VMS 7.0 */
+#include <unistd.h>
+#include "internal/cryptlib.h"
+#include <openssl/rand.h>
+#include "crypto/rand.h"
+#include "crypto/rand_pool.h"
+#include "prov/seeding.h"
+#include <descrip.h>
+#include <dvidef.h>
+#include <jpidef.h>
+#include <rmidef.h>
+#include <syidef.h>
+#include <ssdef.h>
+#include <starlet.h>
+#include <efndef.h>
+#include <gen64def.h>
+#include <iosbdef.h>
+#include <iledef.h>
+#include <lib$routines.h>
+#ifdef __DECC
+# pragma message disable DOLLARID
+#endif
+
+#include <dlfcn.h> /* SYS$GET_ENTROPY presence */
+
+#ifndef OPENSSL_RAND_SEED_OS
+# error "Unsupported seeding method configured; must be os"
+#endif
+
+/*
+ * DATA COLLECTION METHOD
+ * ======================
+ *
+ * This is a method to get low quality entropy.
+ * It works by collecting all kinds of statistical data that
+ * VMS offers and using them as random seed.
+ */
+
+/* We need to make sure we have the right size pointer in some cases */
+#if __INITIAL_POINTER_SIZE == 64
+# pragma pointer_size save
+# pragma pointer_size 32
+#endif
+typedef uint32_t *uint32_t__ptr32;
+#if __INITIAL_POINTER_SIZE == 64
+# pragma pointer_size restore
+#endif
+
+struct item_st {
+ short length, code; /* length is number of bytes */
+};
+
+static const struct item_st DVI_item_data[] = {
+ {4, DVI$_ERRCNT},
+ {4, DVI$_REFCNT},
+};
+
+static const struct item_st JPI_item_data[] = {
+ {4, JPI$_BUFIO},
+ {4, JPI$_CPUTIM},
+ {4, JPI$_DIRIO},
+ {4, JPI$_IMAGECOUNT},
+ {4, JPI$_PAGEFLTS},
+ {4, JPI$_PID},
+ {4, JPI$_PPGCNT},
+ {4, JPI$_WSPEAK},
+ /*
+ * Note: the direct result is just a 32-bit address. However, it points
+ * to a list of 4 32-bit words, so we make extra space for them so we can
+ * do in-place replacement of values
+ */
+ {16, JPI$_FINALEXC},
+};
+
+static const struct item_st JPI_item_data_64bit[] = {
+ {8, JPI$_LAST_LOGIN_I},
+ {8, JPI$_LOGINTIM},
+};
+
+static const struct item_st RMI_item_data[] = {
+ {4, RMI$_COLPG},
+ {4, RMI$_MWAIT},
+ {4, RMI$_CEF},
+ {4, RMI$_PFW},
+ {4, RMI$_LEF},
+ {4, RMI$_LEFO},
+ {4, RMI$_HIB},
+ {4, RMI$_HIBO},
+ {4, RMI$_SUSP},
+ {4, RMI$_SUSPO},
+ {4, RMI$_FPG},
+ {4, RMI$_COM},
+ {4, RMI$_COMO},
+ {4, RMI$_CUR},
+#if defined __alpha
+ {4, RMI$_FRLIST},
+ {4, RMI$_MODLIST},
+#endif
+ {4, RMI$_FAULTS},
+ {4, RMI$_PREADS},
+ {4, RMI$_PWRITES},
+ {4, RMI$_PWRITIO},
+ {4, RMI$_PREADIO},
+ {4, RMI$_GVALFLTS},
+ {4, RMI$_WRTINPROG},
+ {4, RMI$_FREFLTS},
+ {4, RMI$_DZROFLTS},
+ {4, RMI$_SYSFAULTS},
+ {4, RMI$_ISWPCNT},
+ {4, RMI$_DIRIO},
+ {4, RMI$_BUFIO},
+ {4, RMI$_MBREADS},
+ {4, RMI$_MBWRITES},
+ {4, RMI$_LOGNAM},
+ {4, RMI$_FCPCALLS},
+ {4, RMI$_FCPREAD},
+ {4, RMI$_FCPWRITE},
+ {4, RMI$_FCPCACHE},
+ {4, RMI$_FCPCPU},
+ {4, RMI$_FCPHIT},
+ {4, RMI$_FCPSPLIT},
+ {4, RMI$_FCPFAULT},
+ {4, RMI$_ENQNEW},
+ {4, RMI$_ENQCVT},
+ {4, RMI$_DEQ},
+ {4, RMI$_BLKAST},
+ {4, RMI$_ENQWAIT},
+ {4, RMI$_ENQNOTQD},
+ {4, RMI$_DLCKSRCH},
+ {4, RMI$_DLCKFND},
+ {4, RMI$_NUMLOCKS},
+ {4, RMI$_NUMRES},
+ {4, RMI$_ARRLOCPK},
+ {4, RMI$_DEPLOCPK},
+ {4, RMI$_ARRTRAPK},
+ {4, RMI$_TRCNGLOS},
+ {4, RMI$_RCVBUFFL},
+ {4, RMI$_ENQNEWLOC},
+ {4, RMI$_ENQNEWIN},
+ {4, RMI$_ENQNEWOUT},
+ {4, RMI$_ENQCVTLOC},
+ {4, RMI$_ENQCVTIN},
+ {4, RMI$_ENQCVTOUT},
+ {4, RMI$_DEQLOC},
+ {4, RMI$_DEQIN},
+ {4, RMI$_DEQOUT},
+ {4, RMI$_BLKLOC},
+ {4, RMI$_BLKIN},
+ {4, RMI$_BLKOUT},
+ {4, RMI$_DIRIN},
+ {4, RMI$_DIROUT},
+ /* We currently get a fault when trying these */
+#if 0
+ {140, RMI$_MSCP_EVERYTHING}, /* 35 32-bit words */
+ {152, RMI$_DDTM_ALL}, /* 38 32-bit words */
+ {80, RMI$_TMSCP_EVERYTHING} /* 20 32-bit words */
+#endif
+ {4, RMI$_LPZ_PAGCNT},
+ {4, RMI$_LPZ_HITS},
+ {4, RMI$_LPZ_MISSES},
+ {4, RMI$_LPZ_EXPCNT},
+ {4, RMI$_LPZ_ALLOCF},
+ {4, RMI$_LPZ_ALLOC2},
+ {4, RMI$_ACCESS},
+ {4, RMI$_ALLOC},
+ {4, RMI$_FCPCREATE},
+ {4, RMI$_VOLWAIT},
+ {4, RMI$_FCPTURN},
+ {4, RMI$_FCPERASE},
+ {4, RMI$_OPENS},
+ {4, RMI$_FIDHIT},
+ {4, RMI$_FIDMISS},
+ {4, RMI$_FILHDR_HIT},
+ {4, RMI$_DIRFCB_HIT},
+ {4, RMI$_DIRFCB_MISS},
+ {4, RMI$_DIRDATA_HIT},
+ {4, RMI$_EXTHIT},
+ {4, RMI$_EXTMISS},
+ {4, RMI$_QUOHIT},
+ {4, RMI$_QUOMISS},
+ {4, RMI$_STORAGMAP_HIT},
+ {4, RMI$_VOLLCK},
+ {4, RMI$_SYNCHLCK},
+ {4, RMI$_SYNCHWAIT},
+ {4, RMI$_ACCLCK},
+ {4, RMI$_XQPCACHEWAIT},
+ {4, RMI$_DIRDATA_MISS},
+ {4, RMI$_FILHDR_MISS},
+ {4, RMI$_STORAGMAP_MISS},
+ {4, RMI$_PROCCNTMAX},
+ {4, RMI$_PROCBATCNT},
+ {4, RMI$_PROCINTCNT},
+ {4, RMI$_PROCNETCNT},
+ {4, RMI$_PROCSWITCHCNT},
+ {4, RMI$_PROCBALSETCNT},
+ {4, RMI$_PROCLOADCNT},
+ {4, RMI$_BADFLTS},
+ {4, RMI$_EXEFAULTS},
+ {4, RMI$_HDRINSWAPS},
+ {4, RMI$_HDROUTSWAPS},
+ {4, RMI$_IOPAGCNT},
+ {4, RMI$_ISWPCNTPG},
+ {4, RMI$_OSWPCNT},
+ {4, RMI$_OSWPCNTPG},
+ {4, RMI$_RDFAULTS},
+ {4, RMI$_TRANSFLTS},
+ {4, RMI$_WRTFAULTS},
+#if defined __alpha
+ {4, RMI$_USERPAGES},
+#endif
+ {4, RMI$_VMSPAGES},
+ {4, RMI$_TTWRITES},
+ {4, RMI$_BUFOBJPAG},
+ {4, RMI$_BUFOBJPAGPEAK},
+ {4, RMI$_BUFOBJPAGS01},
+ {4, RMI$_BUFOBJPAGS2},
+ {4, RMI$_BUFOBJPAGMAXS01},
+ {4, RMI$_BUFOBJPAGMAXS2},
+ {4, RMI$_BUFOBJPAGPEAKS01},
+ {4, RMI$_BUFOBJPAGPEAKS2},
+ {4, RMI$_BUFOBJPGLTMAXS01},
+ {4, RMI$_BUFOBJPGLTMAXS2},
+ {4, RMI$_DLCK_INCMPLT},
+ {4, RMI$_DLCKMSGS_IN},
+ {4, RMI$_DLCKMSGS_OUT},
+ {4, RMI$_MCHKERRS},
+ {4, RMI$_MEMERRS},
+};
+
+static const struct item_st RMI_item_data_64bit[] = {
+#if defined __ia64
+ {8, RMI$_FRLIST},
+ {8, RMI$_MODLIST},
+#endif
+ {8, RMI$_LCKMGR_REQCNT},
+ {8, RMI$_LCKMGR_REQTIME},
+ {8, RMI$_LCKMGR_SPINCNT},
+ {8, RMI$_LCKMGR_SPINTIME},
+ {8, RMI$_CPUINTSTK},
+ {8, RMI$_CPUMPSYNCH},
+ {8, RMI$_CPUKERNEL},
+ {8, RMI$_CPUEXEC},
+ {8, RMI$_CPUSUPER},
+ {8, RMI$_CPUUSER},
+#if defined __ia64
+ {8, RMI$_USERPAGES},
+#endif
+ {8, RMI$_TQETOTAL},
+ {8, RMI$_TQESYSUB},
+ {8, RMI$_TQEUSRTIMR},
+ {8, RMI$_TQEUSRWAKE},
+};
+
+static const struct item_st SYI_item_data[] = {
+ {4, SYI$_PAGEFILE_FREE},
+};
+
+/*
+ * Input:
+ * items_data - an array of lengths and codes
+ * items_data_num - number of elements in that array
+ *
+ * Output:
+ * items - pre-allocated ILE3 array to be filled.
+ * It's assumed to have items_data_num elements plus
+ * one extra for the terminating NULL element
+ * databuffer - pre-allocated 32-bit word array.
+ *
+ * Returns the number of elements used in databuffer
+ */
+static size_t prepare_item_list(const struct item_st *items_input,
+ size_t items_input_num,
+ ILE3 *items,
+ uint32_t__ptr32 databuffer)
+{
+ size_t data_sz = 0;
+
+ for (; items_input_num-- > 0; items_input++, items++) {
+
+ items->ile3$w_code = items_input->code;
+ /* Special treatment of JPI$_FINALEXC */
+ if (items->ile3$w_code == JPI$_FINALEXC)
+ items->ile3$w_length = 4;
+ else
+ items->ile3$w_length = items_input->length;
+
+ items->ile3$ps_bufaddr = databuffer;
+ items->ile3$ps_retlen_addr = 0;
+
+ databuffer += items_input->length / sizeof(databuffer[0]);
+ data_sz += items_input->length;
+ }
+ /* Terminating NULL entry */
+ items->ile3$w_length = items->ile3$w_code = 0;
+ items->ile3$ps_bufaddr = items->ile3$ps_retlen_addr = NULL;
+
+ return data_sz / sizeof(databuffer[0]);
+}
+
+static void massage_JPI(ILE3 *items)
+{
+ /*
+ * Special treatment of JPI$_FINALEXC
+ * The result of that item's data buffer is a 32-bit address to a list of
+ * 4 32-bit words.
+ */
+ for (; items->ile3$w_length != 0; items++) {
+ if (items->ile3$w_code == JPI$_FINALEXC) {
+ uint32_t *data = items->ile3$ps_bufaddr;
+ uint32_t *ptr = (uint32_t *)*data;
+ size_t j;
+
+ /*
+ * We know we made space for 4 32-bit words, so we can do in-place
+ * replacement.
+ */
+ for (j = 0; j < 4; j++)
+ data[j] = ptr[j];
+
+ break;
+ }
+ }
+}
+
+/*
+ * This number expresses how many bits of data contain 1 bit of entropy.
+ *
+ * For the moment, we assume about 0.05 entropy bits per data bit, or 1
+ * bit of entropy per 20 data bits.
+ */
+#define ENTROPY_FACTOR 20
+
+size_t data_collect_method(RAND_POOL *pool)
+{
+ ILE3 JPI_items_64bit[OSSL_NELEM(JPI_item_data_64bit) + 1];
+ ILE3 RMI_items_64bit[OSSL_NELEM(RMI_item_data_64bit) + 1];
+ ILE3 DVI_items[OSSL_NELEM(DVI_item_data) + 1];
+ ILE3 JPI_items[OSSL_NELEM(JPI_item_data) + 1];
+ ILE3 RMI_items[OSSL_NELEM(RMI_item_data) + 1];
+ ILE3 SYI_items[OSSL_NELEM(SYI_item_data) + 1];
+ union {
+ /* This ensures buffer starts at 64 bit boundary */
+ uint64_t dummy;
+ uint32_t buffer[OSSL_NELEM(JPI_item_data_64bit) * 2
+ + OSSL_NELEM(RMI_item_data_64bit) * 2
+ + OSSL_NELEM(DVI_item_data)
+ + OSSL_NELEM(JPI_item_data)
+ + OSSL_NELEM(RMI_item_data)
+ + OSSL_NELEM(SYI_item_data)
+ + 4 /* For JPI$_FINALEXC */];
+ } data;
+ size_t total_elems = 0;
+ size_t total_length = 0;
+ size_t bytes_needed = ossl_rand_pool_bytes_needed(pool, ENTROPY_FACTOR);
+ size_t bytes_remaining = ossl_rand_pool_bytes_remaining(pool);
+
+ /* Take all the 64-bit items first, to ensure proper alignment of data */
+ total_elems +=
+ prepare_item_list(JPI_item_data_64bit, OSSL_NELEM(JPI_item_data_64bit),
+ JPI_items_64bit, &data.buffer[total_elems]);
+ total_elems +=
+ prepare_item_list(RMI_item_data_64bit, OSSL_NELEM(RMI_item_data_64bit),
+ RMI_items_64bit, &data.buffer[total_elems]);
+ /* Now the 32-bit items */
+ total_elems += prepare_item_list(DVI_item_data, OSSL_NELEM(DVI_item_data),
+ DVI_items, &data.buffer[total_elems]);
+ total_elems += prepare_item_list(JPI_item_data, OSSL_NELEM(JPI_item_data),
+ JPI_items, &data.buffer[total_elems]);
+ total_elems += prepare_item_list(RMI_item_data, OSSL_NELEM(RMI_item_data),
+ RMI_items, &data.buffer[total_elems]);
+ total_elems += prepare_item_list(SYI_item_data, OSSL_NELEM(SYI_item_data),
+ SYI_items, &data.buffer[total_elems]);
+ total_length = total_elems * sizeof(data.buffer[0]);
+
+ /* Fill data.buffer with various info bits from this process */
+ {
+ uint32_t status;
+ uint32_t efn;
+ IOSB iosb;
+ $DESCRIPTOR(SYSDEVICE,"SYS$SYSDEVICE:");
+
+ if ((status = sys$getdviw(EFN$C_ENF, 0, &SYSDEVICE, DVI_items,
+ 0, 0, 0, 0, 0)) != SS$_NORMAL) {
+ lib$signal(status);
+ return 0;
+ }
+ if ((status = sys$getjpiw(EFN$C_ENF, 0, 0, JPI_items_64bit, 0, 0, 0))
+ != SS$_NORMAL) {
+ lib$signal(status);
+ return 0;
+ }
+ if ((status = sys$getjpiw(EFN$C_ENF, 0, 0, JPI_items, 0, 0, 0))
+ != SS$_NORMAL) {
+ lib$signal(status);
+ return 0;
+ }
+ if ((status = sys$getsyiw(EFN$C_ENF, 0, 0, SYI_items, 0, 0, 0))
+ != SS$_NORMAL) {
+ lib$signal(status);
+ return 0;
+ }
+ /*
+ * The RMI service is a bit special, as there is no synchronous
+ * variant, so we MUST create an event flag to synchronise on.
+ */
+ if ((status = lib$get_ef(&efn)) != SS$_NORMAL) {
+ lib$signal(status);
+ return 0;
+ }
+ if ((status = sys$getrmi(efn, 0, 0, RMI_items_64bit, &iosb, 0, 0))
+ != SS$_NORMAL) {
+ lib$signal(status);
+ return 0;
+ }
+ if ((status = sys$synch(efn, &iosb)) != SS$_NORMAL) {
+ lib$signal(status);
+ return 0;
+ }
+ if (iosb.iosb$l_getxxi_status != SS$_NORMAL) {
+ lib$signal(iosb.iosb$l_getxxi_status);
+ return 0;
+ }
+ if ((status = sys$getrmi(efn, 0, 0, RMI_items, &iosb, 0, 0))
+ != SS$_NORMAL) {
+ lib$signal(status);
+ return 0;
+ }
+ if ((status = sys$synch(efn, &iosb)) != SS$_NORMAL) {
+ lib$signal(status);
+ return 0;
+ }
+ if (iosb.iosb$l_getxxi_status != SS$_NORMAL) {
+ lib$signal(iosb.iosb$l_getxxi_status);
+ return 0;
+ }
+ if ((status = lib$free_ef(&efn)) != SS$_NORMAL) {
+ lib$signal(status);
+ return 0;
+ }
+ }
+
+ massage_JPI(JPI_items);
+
+ /*
+ * If we can't feed the requirements from the caller, we're in deep trouble.
+ */
+ if (!ossl_assert(total_length >= bytes_needed)) {
+ ERR_raise_data(ERR_LIB_RAND, RAND_R_RANDOM_POOL_UNDERFLOW,
+ "Needed: %zu, Available: %zu",
+ bytes_needed, total_length);
+ return 0;
+ }
+
+ /*
+ * Try not to overfeed the pool
+ */
+ if (total_length > bytes_remaining)
+ total_length = bytes_remaining;
+
+ /* We give the pessimistic value for the amount of entropy */
+ ossl_rand_pool_add(pool, (unsigned char *)data.buffer, total_length,
+ 8 * total_length / ENTROPY_FACTOR);
+ return ossl_rand_pool_entropy_available(pool);
+}
+
+/*
+ * SYS$GET_ENTROPY METHOD
+ * ======================
+ *
+ * This is a high entropy method based on a new system service that is
+ * based on getentropy() from FreeBSD 12. It's only used if available,
+ * and its availability is detected at run-time.
+ *
+ * We assume that this function provides full entropy random output.
+ */
+#define PUBLIC_VECTORS "SYS$LIBRARY:SYS$PUBLIC_VECTORS.EXE"
+#define GET_ENTROPY "SYS$GET_ENTROPY"
+
+static int get_entropy_address_flag = 0;
+static int (*get_entropy_address)(void *buffer, size_t buffer_size) = NULL;
+static int init_get_entropy_address(void)
+{
+ if (get_entropy_address_flag == 0)
+ get_entropy_address = dlsym(dlopen(PUBLIC_VECTORS, 0), GET_ENTROPY);
+ get_entropy_address_flag = 1;
+ return get_entropy_address != NULL;
+}
+
+size_t get_entropy_method(RAND_POOL *pool)
+{
+ /*
+ * The documentation says that SYS$GET_ENTROPY will give a maximum of
+ * 256 bytes of data.
+ */
+ unsigned char buffer[256];
+ size_t bytes_needed;
+ size_t bytes_to_get = 0;
+ uint32_t status;
+
+ for (bytes_needed = ossl_rand_pool_bytes_needed(pool, 1);
+ bytes_needed > 0;
+ bytes_needed -= bytes_to_get) {
+ bytes_to_get =
+ bytes_needed > sizeof(buffer) ? sizeof(buffer) : bytes_needed;
+
+ status = get_entropy_address(buffer, bytes_to_get);
+ if (status == SS$_RETRY) {
+ /* Set to zero so the loop doesn't diminish |bytes_needed| */
+ bytes_to_get = 0;
+ /* Should sleep some amount of time */
+ continue;
+ }
+
+ if (status != SS$_NORMAL) {
+ lib$signal(status);
+ return 0;
+ }
+
+ ossl_rand_pool_add(pool, buffer, bytes_to_get, 8 * bytes_to_get);
+ }
+
+ return ossl_rand_pool_entropy_available(pool);
+}
+
+/*
+ * MAIN ENTROPY ACQUISITION FUNCTIONS
+ * ==================================
+ *
+ * These functions are called by the RAND / DRBG functions
+ */
+
+size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
+{
+ if (init_get_entropy_address())
+ return get_entropy_method(pool);
+ return data_collect_method(pool);
+}
+
+int ossl_pool_add_nonce_data(RAND_POOL *pool)
+{
+ /*
+ * Two variables to ensure that two nonces won't ever be the same
+ */
+ static unsigned __int64 last_time = 0;
+ static unsigned __int32 last_seq = 0;
+
+ struct {
+ pid_t pid;
+ CRYPTO_THREAD_ID tid;
+ unsigned __int64 time;
+ unsigned __int32 seq;
+ } data;
+
+ /* Erase the entire structure including any padding */
+ memset(&data, 0, sizeof(data));
+
+ /*
+ * Add process id, thread id, a timestamp, and a sequence number in case
+ * the same time stamp is repeated, to ensure that the nonce is unique
+ * with high probability for different process instances.
+ *
+ * The normal OpenVMS time is specified to be high granularity (100ns),
+ * but the time update granularity given by sys$gettim() may be lower.
+ *
+ * OpenVMS version 8.4 (which is the latest for Alpha and Itanium) and
+ * on have sys$gettim_prec() as well, which is supposedly having a better
+ * time update granularity, but tests on Itanium (and even Alpha) have
+ * shown that compared with sys$gettim(), the difference is marginal,
+ * so of very little significance in terms of entropy.
+ * Given that, and that it's a high ask to expect everyone to have
+ * upgraded to OpenVMS version 8.4, only sys$gettim() is used, and a
+ * sequence number is added as well, in case sys$gettim() returns the
+ * same time value more than once.
+ *
+ * This function is assumed to be called under thread lock, and does
+ * therefore not take concurrency into account.
+ */
+ data.pid = getpid();
+ data.tid = CRYPTO_THREAD_get_current_id();
+ data.seq = 0;
+ sys$gettim((void*)&data.time);
+
+ if (data.time == last_time) {
+ data.seq = ++last_seq;
+ } else {
+ last_time = data.time;
+ last_seq = 0;
+ }
+
+ return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
+}
+
+int ossl_rand_pool_init(void)
+{
+ return 1;
+}
+
+void ossl_rand_pool_cleanup(void)
+{
+}
+
+void ossl_rand_pool_keep_random_devices_open(int keep)
+{
+}
diff --git a/providers/implementations/rands/seeding/rand_vxworks.c b/providers/implementations/rands/seeding/rand_vxworks.c
new file mode 100644
index 000000000000..12be9357bf28
--- /dev/null
+++ b/providers/implementations/rands/seeding/rand_vxworks.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+
+#include <openssl/rand.h>
+#include "crypto/rand_pool.h"
+#include "crypto/rand.h"
+#include "internal/cryptlib.h"
+#include "prov/seeding.h"
+#include <version.h>
+#include <taskLib.h>
+
+#if defined(OPENSSL_RAND_SEED_NONE)
+/* none means none */
+# undef OPENSSL_RAND_SEED_OS
+#endif
+
+#if defined(OPENSSL_RAND_SEED_OS)
+# if _WRS_VXWORKS_MAJOR >= 7
+# define RAND_SEED_VXRANDLIB
+# else
+# error "VxWorks <7 only support RAND_SEED_NONE"
+# endif
+#endif
+
+#if defined(RAND_SEED_VXRANDLIB)
+# include <randomNumGen.h>
+#endif
+
+/* Macro to convert two thirty two bit values into a sixty four bit one */
+#define TWO32TO64(a, b) ((((uint64_t)(a)) << 32) + (b))
+
+static uint64_t get_time_stamp(void)
+{
+ struct timespec ts;
+
+ if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
+ return TWO32TO64(ts.tv_sec, ts.tv_nsec);
+ return time(NULL);
+}
+
+static uint64_t get_timer_bits(void)
+{
+ uint64_t res = OPENSSL_rdtsc();
+ struct timespec ts;
+
+ if (res != 0)
+ return res;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
+ return TWO32TO64(ts.tv_sec, ts.tv_nsec);
+ return time(NULL);
+}
+
+/*
+ * empty implementation
+ * vxworks does not need to init/cleanup or keep open the random lib
+ */
+int ossl_rand_pool_init(void)
+{
+ return 1;
+}
+
+void ossl_rand_pool_cleanup(void)
+{
+}
+
+void ossl_rand_pool_keep_random_devices_open(int keep)
+{
+}
+
+int ossl_rand_pool_add_additional_data(RAND_POOL *pool)
+{
+ struct {
+ CRYPTO_THREAD_ID tid;
+ uint64_t time;
+ } data;
+
+ memset(&data, 0, sizeof(data));
+
+ /*
+ * Add some noise from the thread id and a high resolution timer.
+ * The thread id adds a little randomness if the drbg is accessed
+ * concurrently (which is the case for the <master> drbg).
+ */
+ data.tid = CRYPTO_THREAD_get_current_id();
+ data.time = get_timer_bits();
+
+ return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
+}
+
+int ossl_pool_add_nonce_data(RAND_POOL *pool)
+{
+ struct {
+ pid_t pid;
+ CRYPTO_THREAD_ID tid;
+ uint64_t time;
+ } data;
+
+ memset(&data, 0, sizeof(data));
+
+ /*
+ * Add process id, thread id, and a high resolution timestamp to
+ * ensure that the nonce is unique with high probability for
+ * different process instances.
+ */
+ data.pid = getpid();
+ data.tid = CRYPTO_THREAD_get_current_id();
+ data.time = get_time_stamp();
+
+ return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
+}
+
+size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
+{
+#if defined(RAND_SEED_VXRANDLIB)
+ /* vxRandLib based entropy method */
+ size_t bytes_needed;
+
+ bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
+ if (bytes_needed > 0)
+ {
+ int retryCount = 0;
+ STATUS result = ERROR;
+ unsigned char *buffer;
+
+ buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
+ while ((result != OK) && (retryCount < 10)) {
+ RANDOM_NUM_GEN_STATUS status = randStatus();
+
+ if ((status == RANDOM_NUM_GEN_ENOUGH_ENTROPY)
+ || (status == RANDOM_NUM_GEN_MAX_ENTROPY) ) {
+ result = randBytes(buffer, bytes_needed);
+ if (result == OK)
+ ossl_rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed);
+ /*
+ * no else here: randStatus said ok, if randBytes failed
+ * it will result in another loop or no entropy
+ */
+ } else {
+ /*
+ * give a minimum delay here to allow OS to collect more
+ * entropy. taskDelay duration will depend on the system tick,
+ * this is by design as the sw-random lib uses interrupts
+ * which will at least happen during ticks
+ */
+ taskDelay(5);
+ }
+ retryCount++;
+ }
+ }
+ return ossl_rand_pool_entropy_available(pool);
+#else
+ /*
+ * SEED_NONE means none, without randlib we dont have entropy and
+ * rely on it being added externally
+ */
+ return ossl_rand_pool_entropy_available(pool);
+#endif /* defined(RAND_SEED_VXRANDLIB) */
+}
diff --git a/providers/implementations/rands/seeding/rand_win.c b/providers/implementations/rands/seeding/rand_win.c
new file mode 100644
index 000000000000..cf903f3cb5a2
--- /dev/null
+++ b/providers/implementations/rands/seeding/rand_win.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/cryptlib.h"
+#include <openssl/rand.h>
+#include "crypto/rand_pool.h"
+#include "crypto/rand.h"
+#include "prov/seeding.h"
+
+#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
+
+# ifndef OPENSSL_RAND_SEED_OS
+# error "Unsupported seeding method configured; must be os"
+# endif
+
+# include <windows.h>
+/* On Windows Vista or higher use BCrypt instead of the legacy CryptoAPI */
+# if defined(_MSC_VER) && _MSC_VER > 1500 /* 1500 = Visual Studio 2008 */ \
+ && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600
+# define USE_BCRYPTGENRANDOM
+# endif
+
+# ifdef USE_BCRYPTGENRANDOM
+# include <bcrypt.h>
+# ifdef _MSC_VER
+# pragma comment(lib, "bcrypt.lib")
+# endif
+# ifndef STATUS_SUCCESS
+# define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
+# endif
+# else
+# include <wincrypt.h>
+/*
+ * Intel hardware RNG CSP -- available from
+ * http://developer.intel.com/design/security/rng/redist_license.htm
+ */
+# define PROV_INTEL_SEC 22
+# define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider"
+# endif
+
+size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
+{
+# ifndef USE_BCRYPTGENRANDOM
+ HCRYPTPROV hProvider;
+# endif
+ unsigned char *buffer;
+ size_t bytes_needed;
+ size_t entropy_available = 0;
+
+
+# ifdef OPENSSL_RAND_SEED_RDTSC
+ entropy_available = ossl_prov_acquire_entropy_from_tsc(pool);
+ if (entropy_available > 0)
+ return entropy_available;
+# endif
+
+# ifdef OPENSSL_RAND_SEED_RDCPU
+ entropy_available = ossl_prov_acquire_entropy_from_cpu(pool);
+ if (entropy_available > 0)
+ return entropy_available;
+# endif
+
+# ifdef USE_BCRYPTGENRANDOM
+ bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
+ buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
+ if (buffer != NULL) {
+ size_t bytes = 0;
+ if (BCryptGenRandom(NULL, buffer, bytes_needed,
+ BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS)
+ bytes = bytes_needed;
+
+ ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
+ entropy_available = ossl_rand_pool_entropy_available(pool);
+ }
+ if (entropy_available > 0)
+ return entropy_available;
+# else
+ bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
+ buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
+ if (buffer != NULL) {
+ size_t bytes = 0;
+ /* poll the CryptoAPI PRNG */
+ if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) {
+ if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0)
+ bytes = bytes_needed;
+
+ CryptReleaseContext(hProvider, 0);
+ }
+
+ ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
+ entropy_available = ossl_rand_pool_entropy_available(pool);
+ }
+ if (entropy_available > 0)
+ return entropy_available;
+
+ bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
+ buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
+ if (buffer != NULL) {
+ size_t bytes = 0;
+ /* poll the Pentium PRG with CryptoAPI */
+ if (CryptAcquireContextW(&hProvider, NULL,
+ INTEL_DEF_PROV, PROV_INTEL_SEC,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) {
+ if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0)
+ bytes = bytes_needed;
+
+ CryptReleaseContext(hProvider, 0);
+ }
+ ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
+ entropy_available = ossl_rand_pool_entropy_available(pool);
+ }
+ if (entropy_available > 0)
+ return entropy_available;
+# endif
+
+ return ossl_rand_pool_entropy_available(pool);
+}
+
+
+int ossl_pool_add_nonce_data(RAND_POOL *pool)
+{
+ struct {
+ DWORD pid;
+ DWORD tid;
+ FILETIME time;
+ } data;
+
+ /* Erase the entire structure including any padding */
+ memset(&data, 0, sizeof(data));
+
+ /*
+ * Add process id, thread id, and a high resolution timestamp to
+ * ensure that the nonce is unique with high probability for
+ * different process instances.
+ */
+ data.pid = GetCurrentProcessId();
+ data.tid = GetCurrentThreadId();
+ GetSystemTimeAsFileTime(&data.time);
+
+ return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
+}
+
+int ossl_rand_pool_add_additional_data(RAND_POOL *pool)
+{
+ struct {
+ DWORD tid;
+ LARGE_INTEGER time;
+ } data;
+
+ /* Erase the entire structure including any padding */
+ memset(&data, 0, sizeof(data));
+
+ /*
+ * Add some noise from the thread id and a high resolution timer.
+ * The thread id adds a little randomness if the drbg is accessed
+ * concurrently (which is the case for the <master> drbg).
+ */
+ data.tid = GetCurrentThreadId();
+ QueryPerformanceCounter(&data.time);
+ return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
+}
+
+int ossl_rand_pool_init(void)
+{
+ return 1;
+}
+
+void ossl_rand_pool_cleanup(void)
+{
+}
+
+void ossl_rand_pool_keep_random_devices_open(int keep)
+{
+}
+
+#endif
diff --git a/providers/implementations/rands/test_rng.c b/providers/implementations/rands/test_rng.c
new file mode 100644
index 000000000000..4e7fed0fc7b1
--- /dev/null
+++ b/providers/implementations/rands/test_rng.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/e_os2.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/randerr.h>
+#include "prov/providercommon.h"
+#include "prov/provider_ctx.h"
+#include "prov/provider_util.h"
+#include "prov/implementations.h"
+
+static OSSL_FUNC_rand_newctx_fn test_rng_new;
+static OSSL_FUNC_rand_freectx_fn test_rng_free;
+static OSSL_FUNC_rand_instantiate_fn test_rng_instantiate;
+static OSSL_FUNC_rand_uninstantiate_fn test_rng_uninstantiate;
+static OSSL_FUNC_rand_generate_fn test_rng_generate;
+static OSSL_FUNC_rand_reseed_fn test_rng_reseed;
+static OSSL_FUNC_rand_nonce_fn test_rng_nonce;
+static OSSL_FUNC_rand_settable_ctx_params_fn test_rng_settable_ctx_params;
+static OSSL_FUNC_rand_set_ctx_params_fn test_rng_set_ctx_params;
+static OSSL_FUNC_rand_gettable_ctx_params_fn test_rng_gettable_ctx_params;
+static OSSL_FUNC_rand_get_ctx_params_fn test_rng_get_ctx_params;
+static OSSL_FUNC_rand_verify_zeroization_fn test_rng_verify_zeroization;
+static OSSL_FUNC_rand_enable_locking_fn test_rng_enable_locking;
+static OSSL_FUNC_rand_lock_fn test_rng_lock;
+static OSSL_FUNC_rand_unlock_fn test_rng_unlock;
+static OSSL_FUNC_rand_get_seed_fn test_rng_get_seed;
+
+typedef struct {
+ void *provctx;
+ int state;
+ unsigned int strength;
+ size_t max_request;
+ unsigned char *entropy, *nonce;
+ size_t entropy_len, entropy_pos, nonce_len;
+ CRYPTO_RWLOCK *lock;
+} PROV_TEST_RNG;
+
+static void *test_rng_new(void *provctx, void *parent,
+ const OSSL_DISPATCH *parent_dispatch)
+{
+ PROV_TEST_RNG *t;
+
+ t = OPENSSL_zalloc(sizeof(*t));
+ if (t == NULL)
+ return NULL;
+
+ t->max_request = INT_MAX;
+ t->provctx = provctx;
+ t->state = EVP_RAND_STATE_UNINITIALISED;
+ return t;
+}
+
+static void test_rng_free(void *vtest)
+{
+ PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest;
+
+ if (t == NULL)
+ return;
+ OPENSSL_free(t->entropy);
+ OPENSSL_free(t->nonce);
+ CRYPTO_THREAD_lock_free(t->lock);
+ OPENSSL_free(t);
+}
+
+static int test_rng_instantiate(void *vtest, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *pstr, size_t pstr_len,
+ const OSSL_PARAM params[])
+{
+ PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest;
+
+ if (!test_rng_set_ctx_params(t, params) || strength > t->strength)
+ return 0;
+
+ t->state = EVP_RAND_STATE_READY;
+ t->entropy_pos = 0;
+
+ return 1;
+}
+
+static int test_rng_uninstantiate(void *vtest)
+{
+ PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest;
+
+ t->entropy_pos = 0;
+ t->state = EVP_RAND_STATE_UNINITIALISED;
+ return 1;
+}
+
+static int test_rng_generate(void *vtest, unsigned char *out, size_t outlen,
+ unsigned int strength, int prediction_resistance,
+ const unsigned char *adin, size_t adin_len)
+{
+ PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest;
+
+ if (strength > t->strength || t->entropy_len - t->entropy_pos < outlen)
+ return 0;
+ memcpy(out, t->entropy + t->entropy_pos, outlen);
+ t->entropy_pos += outlen;
+ return 1;
+}
+
+static int test_rng_reseed(ossl_unused void *vtest,
+ ossl_unused int prediction_resistance,
+ ossl_unused const unsigned char *ent,
+ ossl_unused size_t ent_len,
+ ossl_unused const unsigned char *adin,
+ ossl_unused size_t adin_len)
+{
+ return 1;
+}
+
+static size_t test_rng_nonce(void *vtest, unsigned char *out,
+ unsigned int strength,
+ ossl_unused size_t min_noncelen,
+ ossl_unused size_t max_noncelen)
+{
+ PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest;
+
+ if (t->nonce == NULL || strength > t->strength)
+ return 0;
+
+ if (out != NULL)
+ memcpy(out, t->nonce, t->nonce_len);
+ return t->nonce_len;
+}
+
+static int test_rng_get_ctx_params(void *vtest, OSSL_PARAM params[])
+{
+ PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE);
+ if (p != NULL && !OSSL_PARAM_set_int(p, t->state))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH);
+ if (p != NULL && !OSSL_PARAM_set_int(p, t->strength))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, t->max_request))
+ return 0;
+ return 1;
+}
+
+static const OSSL_PARAM *test_rng_gettable_ctx_params(ossl_unused void *vtest,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL),
+ OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL),
+ OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL),
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+static int test_rng_set_ctx_params(void *vtest, const OSSL_PARAM params[])
+{
+ PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest;
+ const OSSL_PARAM *p;
+ void *ptr = NULL;
+ size_t size = 0;
+
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_RAND_PARAM_STRENGTH);
+ if (p != NULL && !OSSL_PARAM_get_uint(p, &t->strength))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_RAND_PARAM_TEST_ENTROPY);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_octet_string(p, &ptr, 0, &size))
+ return 0;
+ OPENSSL_free(t->entropy);
+ t->entropy = ptr;
+ t->entropy_len = size;
+ t->entropy_pos = 0;
+ ptr = NULL;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_RAND_PARAM_TEST_NONCE);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_octet_string(p, &ptr, 0, &size))
+ return 0;
+ OPENSSL_free(t->nonce);
+ t->nonce = ptr;
+ t->nonce_len = size;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_RAND_PARAM_MAX_REQUEST);
+ if (p != NULL && !OSSL_PARAM_get_size_t(p, &t->max_request))
+ return 0;
+
+ return 1;
+}
+
+static const OSSL_PARAM *test_rng_settable_ctx_params(ossl_unused void *vtest,
+ ossl_unused void *provctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_RAND_PARAM_TEST_NONCE, NULL, 0),
+ OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL),
+ OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL),
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+static int test_rng_verify_zeroization(ossl_unused void *vtest)
+{
+ return 1;
+}
+
+static size_t test_rng_get_seed(void *vtest, unsigned char **pout,
+ int entropy, size_t min_len, size_t max_len,
+ ossl_unused int prediction_resistance,
+ ossl_unused const unsigned char *adin,
+ ossl_unused size_t adin_len)
+{
+ PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest;
+
+ *pout = t->entropy;
+ return t->entropy_len > max_len ? max_len : t->entropy_len;
+}
+
+static int test_rng_enable_locking(void *vtest)
+{
+ PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest;
+
+ if (t != NULL && t->lock == NULL) {
+ t->lock = CRYPTO_THREAD_lock_new();
+ if (t->lock == NULL) {
+ ERR_raise(ERR_LIB_PROV, RAND_R_FAILED_TO_CREATE_LOCK);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int test_rng_lock(void *vtest)
+{
+ PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest;
+
+ if (t == NULL || t->lock == NULL)
+ return 1;
+ return CRYPTO_THREAD_write_lock(t->lock);
+}
+
+static void test_rng_unlock(void *vtest)
+{
+ PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest;
+
+ if (t != NULL && t->lock != NULL)
+ CRYPTO_THREAD_unlock(t->lock);
+}
+
+const OSSL_DISPATCH ossl_test_rng_functions[] = {
+ { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))test_rng_new },
+ { OSSL_FUNC_RAND_FREECTX, (void(*)(void))test_rng_free },
+ { OSSL_FUNC_RAND_INSTANTIATE,
+ (void(*)(void))test_rng_instantiate },
+ { OSSL_FUNC_RAND_UNINSTANTIATE,
+ (void(*)(void))test_rng_uninstantiate },
+ { OSSL_FUNC_RAND_GENERATE, (void(*)(void))test_rng_generate },
+ { OSSL_FUNC_RAND_RESEED, (void(*)(void))test_rng_reseed },
+ { OSSL_FUNC_RAND_NONCE, (void(*)(void))test_rng_nonce },
+ { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))test_rng_enable_locking },
+ { OSSL_FUNC_RAND_LOCK, (void(*)(void))test_rng_lock },
+ { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))test_rng_unlock },
+ { OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS,
+ (void(*)(void))test_rng_settable_ctx_params },
+ { OSSL_FUNC_RAND_SET_CTX_PARAMS, (void(*)(void))test_rng_set_ctx_params },
+ { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
+ (void(*)(void))test_rng_gettable_ctx_params },
+ { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))test_rng_get_ctx_params },
+ { OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
+ (void(*)(void))test_rng_verify_zeroization },
+ { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))test_rng_get_seed },
+ { 0, NULL }
+};
diff --git a/providers/implementations/signature/build.info b/providers/implementations/signature/build.info
new file mode 100644
index 000000000000..fd3be7f3b9dd
--- /dev/null
+++ b/providers/implementations/signature/build.info
@@ -0,0 +1,30 @@
+# We make separate GOAL variables for each algorithm, to make it easy to
+# switch each to the Legacy provider when needed.
+
+$DSA_GOAL=../../libdefault.a ../../libfips.a
+$EC_GOAL=../../libdefault.a ../../libfips.a
+$MAC_GOAL=../../libdefault.a ../../libfips.a
+$RSA_GOAL=../../libdefault.a ../../libfips.a
+$SM2_GOAL=../../libdefault.a
+
+IF[{- !$disabled{dsa} -}]
+ SOURCE[$DSA_GOAL]=dsa_sig.c
+ENDIF
+
+IF[{- !$disabled{ec} -}]
+ SOURCE[$EC_GOAL]=eddsa_sig.c ecdsa_sig.c
+ENDIF
+
+IF[{- !$disabled{sm2} -}]
+ SOURCE[$SM2_GOAL]=sm2_sig.c
+ENDIF
+
+SOURCE[$RSA_GOAL]=rsa_sig.c
+
+DEPEND[rsa_sig.o]=../../common/include/prov/der_rsa.h
+DEPEND[dsa_sig.o]=../../common/include/prov/der_dsa.h
+DEPEND[ecdsa_sig.o]=../../common/include/prov/der_ec.h
+DEPEND[eddsa_sig.o]=../../common/include/prov/der_ecx.h
+DEPEND[sm2_sig.o]=../../common/include/prov/der_sm2.h
+
+SOURCE[$MAC_GOAL]=mac_legacy_sig.c
diff --git a/providers/implementations/signature/dsa_sig.c b/providers/implementations/signature/dsa_sig.c
new file mode 100644
index 000000000000..28fd7c498e99
--- /dev/null
+++ b/providers/implementations/signature/dsa_sig.c
@@ -0,0 +1,601 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/err.h>
+#include <openssl/dsa.h>
+#include <openssl/params.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include "internal/nelem.h"
+#include "internal/sizes.h"
+#include "internal/cryptlib.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/securitycheck.h"
+#include "crypto/dsa.h"
+#include "prov/der_dsa.h"
+
+static OSSL_FUNC_signature_newctx_fn dsa_newctx;
+static OSSL_FUNC_signature_sign_init_fn dsa_sign_init;
+static OSSL_FUNC_signature_verify_init_fn dsa_verify_init;
+static OSSL_FUNC_signature_sign_fn dsa_sign;
+static OSSL_FUNC_signature_verify_fn dsa_verify;
+static OSSL_FUNC_signature_digest_sign_init_fn dsa_digest_sign_init;
+static OSSL_FUNC_signature_digest_sign_update_fn dsa_digest_signverify_update;
+static OSSL_FUNC_signature_digest_sign_final_fn dsa_digest_sign_final;
+static OSSL_FUNC_signature_digest_verify_init_fn dsa_digest_verify_init;
+static OSSL_FUNC_signature_digest_verify_update_fn dsa_digest_signverify_update;
+static OSSL_FUNC_signature_digest_verify_final_fn dsa_digest_verify_final;
+static OSSL_FUNC_signature_freectx_fn dsa_freectx;
+static OSSL_FUNC_signature_dupctx_fn dsa_dupctx;
+static OSSL_FUNC_signature_get_ctx_params_fn dsa_get_ctx_params;
+static OSSL_FUNC_signature_gettable_ctx_params_fn dsa_gettable_ctx_params;
+static OSSL_FUNC_signature_set_ctx_params_fn dsa_set_ctx_params;
+static OSSL_FUNC_signature_settable_ctx_params_fn dsa_settable_ctx_params;
+static OSSL_FUNC_signature_get_ctx_md_params_fn dsa_get_ctx_md_params;
+static OSSL_FUNC_signature_gettable_ctx_md_params_fn dsa_gettable_ctx_md_params;
+static OSSL_FUNC_signature_set_ctx_md_params_fn dsa_set_ctx_md_params;
+static OSSL_FUNC_signature_settable_ctx_md_params_fn dsa_settable_ctx_md_params;
+
+/*
+ * What's passed as an actual key is defined by the KEYMGMT interface.
+ * We happen to know that our KEYMGMT simply passes DSA structures, so
+ * we use that here too.
+ */
+
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+ DSA *dsa;
+
+ /*
+ * Flag to determine if the hash function can be changed (1) or not (0)
+ * Because it's dangerous to change during a DigestSign or DigestVerify
+ * operation, this flag is cleared by their Init function, and set again
+ * by their Final function.
+ */
+ unsigned int flag_allow_md : 1;
+
+ char mdname[OSSL_MAX_NAME_SIZE];
+
+ /* The Algorithm Identifier of the combined signature algorithm */
+ unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];
+ unsigned char *aid;
+ size_t aid_len;
+
+ /* main digest */
+ EVP_MD *md;
+ EVP_MD_CTX *mdctx;
+ int operation;
+} PROV_DSA_CTX;
+
+
+static size_t dsa_get_md_size(const PROV_DSA_CTX *pdsactx)
+{
+ if (pdsactx->md != NULL)
+ return EVP_MD_get_size(pdsactx->md);
+ return 0;
+}
+
+static void *dsa_newctx(void *provctx, const char *propq)
+{
+ PROV_DSA_CTX *pdsactx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ pdsactx = OPENSSL_zalloc(sizeof(PROV_DSA_CTX));
+ if (pdsactx == NULL)
+ return NULL;
+
+ pdsactx->libctx = PROV_LIBCTX_OF(provctx);
+ pdsactx->flag_allow_md = 1;
+ if (propq != NULL && (pdsactx->propq = OPENSSL_strdup(propq)) == NULL) {
+ OPENSSL_free(pdsactx);
+ pdsactx = NULL;
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ }
+ return pdsactx;
+}
+
+static int dsa_setup_md(PROV_DSA_CTX *ctx,
+ const char *mdname, const char *mdprops)
+{
+ if (mdprops == NULL)
+ mdprops = ctx->propq;
+
+ if (mdname != NULL) {
+ int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN);
+ WPACKET pkt;
+ EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
+ int md_nid = ossl_digest_get_approved_nid_with_sha1(ctx->libctx, md,
+ sha1_allowed);
+ size_t mdname_len = strlen(mdname);
+
+ if (md == NULL || md_nid < 0) {
+ if (md == NULL)
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
+ "%s could not be fetched", mdname);
+ if (md_nid < 0)
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
+ "digest=%s", mdname);
+ if (mdname_len >= sizeof(ctx->mdname))
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
+ "%s exceeds name buffer length", mdname);
+ EVP_MD_free(md);
+ return 0;
+ }
+
+ if (!ctx->flag_allow_md) {
+ if (ctx->mdname[0] != '\0' && !EVP_MD_is_a(md, ctx->mdname)) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
+ "digest %s != %s", mdname, ctx->mdname);
+ EVP_MD_free(md);
+ return 0;
+ }
+ EVP_MD_free(md);
+ return 1;
+ }
+
+ EVP_MD_CTX_free(ctx->mdctx);
+ EVP_MD_free(ctx->md);
+
+ /*
+ * We do not care about DER writing errors.
+ * All it really means is that for some reason, there's no
+ * AlgorithmIdentifier to be had, but the operation itself is
+ * still valid, just as long as it's not used to construct
+ * anything that needs an AlgorithmIdentifier.
+ */
+ ctx->aid_len = 0;
+ if (WPACKET_init_der(&pkt, ctx->aid_buf, sizeof(ctx->aid_buf))
+ && ossl_DER_w_algorithmIdentifier_DSA_with_MD(&pkt, -1, ctx->dsa,
+ md_nid)
+ && WPACKET_finish(&pkt)) {
+ WPACKET_get_total_written(&pkt, &ctx->aid_len);
+ ctx->aid = WPACKET_get_curr(&pkt);
+ }
+ WPACKET_cleanup(&pkt);
+
+ ctx->mdctx = NULL;
+ ctx->md = md;
+ OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname));
+ }
+ return 1;
+}
+
+static int dsa_signverify_init(void *vpdsactx, void *vdsa,
+ const OSSL_PARAM params[], int operation)
+{
+ PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
+
+ if (!ossl_prov_is_running()
+ || pdsactx == NULL)
+ return 0;
+
+ if (vdsa == NULL && pdsactx->dsa == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
+ return 0;
+ }
+
+ if (vdsa != NULL) {
+ if (!ossl_dsa_check_key(pdsactx->libctx, vdsa,
+ operation == EVP_PKEY_OP_SIGN)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ if (!DSA_up_ref(vdsa))
+ return 0;
+ DSA_free(pdsactx->dsa);
+ pdsactx->dsa = vdsa;
+ }
+
+ pdsactx->operation = operation;
+
+ if (!dsa_set_ctx_params(pdsactx, params))
+ return 0;
+
+ return 1;
+}
+
+static int dsa_sign_init(void *vpdsactx, void *vdsa, const OSSL_PARAM params[])
+{
+ return dsa_signverify_init(vpdsactx, vdsa, params, EVP_PKEY_OP_SIGN);
+}
+
+static int dsa_verify_init(void *vpdsactx, void *vdsa,
+ const OSSL_PARAM params[])
+{
+ return dsa_signverify_init(vpdsactx, vdsa, params, EVP_PKEY_OP_VERIFY);
+}
+
+static int dsa_sign(void *vpdsactx, unsigned char *sig, size_t *siglen,
+ size_t sigsize, const unsigned char *tbs, size_t tbslen)
+{
+ PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
+ int ret;
+ unsigned int sltmp;
+ size_t dsasize = DSA_size(pdsactx->dsa);
+ size_t mdsize = dsa_get_md_size(pdsactx);
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (sig == NULL) {
+ *siglen = dsasize;
+ return 1;
+ }
+
+ if (sigsize < (size_t)dsasize)
+ return 0;
+
+ if (mdsize != 0 && tbslen != mdsize)
+ return 0;
+
+ ret = ossl_dsa_sign_int(0, tbs, tbslen, sig, &sltmp, pdsactx->dsa);
+ if (ret <= 0)
+ return 0;
+
+ *siglen = sltmp;
+ return 1;
+}
+
+static int dsa_verify(void *vpdsactx, const unsigned char *sig, size_t siglen,
+ const unsigned char *tbs, size_t tbslen)
+{
+ PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
+ size_t mdsize = dsa_get_md_size(pdsactx);
+
+ if (!ossl_prov_is_running() || (mdsize != 0 && tbslen != mdsize))
+ return 0;
+
+ return DSA_verify(0, tbs, tbslen, sig, siglen, pdsactx->dsa);
+}
+
+static int dsa_digest_signverify_init(void *vpdsactx, const char *mdname,
+ void *vdsa, const OSSL_PARAM params[],
+ int operation)
+{
+ PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (!dsa_signverify_init(vpdsactx, vdsa, params, operation))
+ return 0;
+
+ if (!dsa_setup_md(pdsactx, mdname, NULL))
+ return 0;
+
+ pdsactx->flag_allow_md = 0;
+
+ if (pdsactx->mdctx == NULL) {
+ pdsactx->mdctx = EVP_MD_CTX_new();
+ if (pdsactx->mdctx == NULL)
+ goto error;
+ }
+
+ if (!EVP_DigestInit_ex2(pdsactx->mdctx, pdsactx->md, params))
+ goto error;
+
+ return 1;
+
+ error:
+ EVP_MD_CTX_free(pdsactx->mdctx);
+ pdsactx->mdctx = NULL;
+ return 0;
+}
+
+static int dsa_digest_sign_init(void *vpdsactx, const char *mdname,
+ void *vdsa, const OSSL_PARAM params[])
+{
+ return dsa_digest_signverify_init(vpdsactx, mdname, vdsa, params,
+ EVP_PKEY_OP_SIGN);
+}
+
+static int dsa_digest_verify_init(void *vpdsactx, const char *mdname,
+ void *vdsa, const OSSL_PARAM params[])
+{
+ return dsa_digest_signverify_init(vpdsactx, mdname, vdsa, params,
+ EVP_PKEY_OP_VERIFY);
+}
+
+int dsa_digest_signverify_update(void *vpdsactx, const unsigned char *data,
+ size_t datalen)
+{
+ PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
+
+ if (pdsactx == NULL || pdsactx->mdctx == NULL)
+ return 0;
+
+ return EVP_DigestUpdate(pdsactx->mdctx, data, datalen);
+}
+
+int dsa_digest_sign_final(void *vpdsactx, unsigned char *sig, size_t *siglen,
+ size_t sigsize)
+{
+ PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ unsigned int dlen = 0;
+
+ if (!ossl_prov_is_running() || pdsactx == NULL || pdsactx->mdctx == NULL)
+ return 0;
+
+ /*
+ * If sig is NULL then we're just finding out the sig size. Other fields
+ * are ignored. Defer to dsa_sign.
+ */
+ if (sig != NULL) {
+ /*
+ * There is the possibility that some externally provided
+ * digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow -
+ * but that problem is much larger than just in DSA.
+ */
+ if (!EVP_DigestFinal_ex(pdsactx->mdctx, digest, &dlen))
+ return 0;
+ }
+
+ pdsactx->flag_allow_md = 1;
+
+ return dsa_sign(vpdsactx, sig, siglen, sigsize, digest, (size_t)dlen);
+}
+
+
+int dsa_digest_verify_final(void *vpdsactx, const unsigned char *sig,
+ size_t siglen)
+{
+ PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ unsigned int dlen = 0;
+
+ if (!ossl_prov_is_running() || pdsactx == NULL || pdsactx->mdctx == NULL)
+ return 0;
+
+ /*
+ * There is the possibility that some externally provided
+ * digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow -
+ * but that problem is much larger than just in DSA.
+ */
+ if (!EVP_DigestFinal_ex(pdsactx->mdctx, digest, &dlen))
+ return 0;
+
+ pdsactx->flag_allow_md = 1;
+
+ return dsa_verify(vpdsactx, sig, siglen, digest, (size_t)dlen);
+}
+
+static void dsa_freectx(void *vpdsactx)
+{
+ PROV_DSA_CTX *ctx = (PROV_DSA_CTX *)vpdsactx;
+
+ OPENSSL_free(ctx->propq);
+ EVP_MD_CTX_free(ctx->mdctx);
+ EVP_MD_free(ctx->md);
+ ctx->propq = NULL;
+ ctx->mdctx = NULL;
+ ctx->md = NULL;
+ DSA_free(ctx->dsa);
+ OPENSSL_free(ctx);
+}
+
+static void *dsa_dupctx(void *vpdsactx)
+{
+ PROV_DSA_CTX *srcctx = (PROV_DSA_CTX *)vpdsactx;
+ PROV_DSA_CTX *dstctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+ if (dstctx == NULL)
+ return NULL;
+
+ *dstctx = *srcctx;
+ dstctx->dsa = NULL;
+ dstctx->md = NULL;
+ dstctx->mdctx = NULL;
+ dstctx->propq = NULL;
+
+ if (srcctx->dsa != NULL && !DSA_up_ref(srcctx->dsa))
+ goto err;
+ dstctx->dsa = srcctx->dsa;
+
+ if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md))
+ goto err;
+ dstctx->md = srcctx->md;
+
+ if (srcctx->mdctx != NULL) {
+ dstctx->mdctx = EVP_MD_CTX_new();
+ if (dstctx->mdctx == NULL
+ || !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx))
+ goto err;
+ }
+ if (srcctx->propq != NULL) {
+ dstctx->propq = OPENSSL_strdup(srcctx->propq);
+ if (dstctx->propq == NULL)
+ goto err;
+ }
+
+ return dstctx;
+ err:
+ dsa_freectx(dstctx);
+ return NULL;
+}
+
+static int dsa_get_ctx_params(void *vpdsactx, OSSL_PARAM *params)
+{
+ PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
+ OSSL_PARAM *p;
+
+ if (pdsactx == NULL)
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
+ if (p != NULL
+ && !OSSL_PARAM_set_octet_string(p, pdsactx->aid, pdsactx->aid_len))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST);
+ if (p != NULL && !OSSL_PARAM_set_utf8_string(p, pdsactx->mdname))
+ return 0;
+
+ return 1;
+}
+
+static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *dsa_gettable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *provctx)
+{
+ return known_gettable_ctx_params;
+}
+
+static int dsa_set_ctx_params(void *vpdsactx, const OSSL_PARAM params[])
+{
+ PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
+ const OSSL_PARAM *p;
+
+ if (pdsactx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST);
+ if (p != NULL) {
+ char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = mdname;
+ char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = mdprops;
+ const OSSL_PARAM *propsp =
+ OSSL_PARAM_locate_const(params,
+ OSSL_SIGNATURE_PARAM_PROPERTIES);
+
+ if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname)))
+ return 0;
+ if (propsp != NULL
+ && !OSSL_PARAM_get_utf8_string(propsp, &pmdprops, sizeof(mdprops)))
+ return 0;
+ if (!dsa_setup_md(pdsactx, mdname, mdprops))
+ return 0;
+ }
+
+ return 1;
+}
+
+static const OSSL_PARAM settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM settable_ctx_params_no_digest[] = {
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *dsa_settable_ctx_params(void *vpdsactx,
+ ossl_unused void *provctx)
+{
+ PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
+
+ if (pdsactx != NULL && !pdsactx->flag_allow_md)
+ return settable_ctx_params_no_digest;
+ return settable_ctx_params;
+}
+
+static int dsa_get_ctx_md_params(void *vpdsactx, OSSL_PARAM *params)
+{
+ PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
+
+ if (pdsactx->mdctx == NULL)
+ return 0;
+
+ return EVP_MD_CTX_get_params(pdsactx->mdctx, params);
+}
+
+static const OSSL_PARAM *dsa_gettable_ctx_md_params(void *vpdsactx)
+{
+ PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
+
+ if (pdsactx->md == NULL)
+ return 0;
+
+ return EVP_MD_gettable_ctx_params(pdsactx->md);
+}
+
+static int dsa_set_ctx_md_params(void *vpdsactx, const OSSL_PARAM params[])
+{
+ PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
+
+ if (pdsactx->mdctx == NULL)
+ return 0;
+
+ return EVP_MD_CTX_set_params(pdsactx->mdctx, params);
+}
+
+static const OSSL_PARAM *dsa_settable_ctx_md_params(void *vpdsactx)
+{
+ PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
+
+ if (pdsactx->md == NULL)
+ return 0;
+
+ return EVP_MD_settable_ctx_params(pdsactx->md);
+}
+
+const OSSL_DISPATCH ossl_dsa_signature_functions[] = {
+ { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))dsa_newctx },
+ { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))dsa_sign_init },
+ { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))dsa_sign },
+ { OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))dsa_verify_init },
+ { OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))dsa_verify },
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
+ (void (*)(void))dsa_digest_sign_init },
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
+ (void (*)(void))dsa_digest_signverify_update },
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
+ (void (*)(void))dsa_digest_sign_final },
+ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
+ (void (*)(void))dsa_digest_verify_init },
+ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
+ (void (*)(void))dsa_digest_signverify_update },
+ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
+ (void (*)(void))dsa_digest_verify_final },
+ { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))dsa_freectx },
+ { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))dsa_dupctx },
+ { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))dsa_get_ctx_params },
+ { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
+ (void (*)(void))dsa_gettable_ctx_params },
+ { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))dsa_set_ctx_params },
+ { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
+ (void (*)(void))dsa_settable_ctx_params },
+ { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS,
+ (void (*)(void))dsa_get_ctx_md_params },
+ { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS,
+ (void (*)(void))dsa_gettable_ctx_md_params },
+ { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS,
+ (void (*)(void))dsa_set_ctx_md_params },
+ { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS,
+ (void (*)(void))dsa_settable_ctx_md_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/signature/ecdsa_sig.c b/providers/implementations/signature/ecdsa_sig.c
new file mode 100644
index 000000000000..865d49d1004f
--- /dev/null
+++ b/providers/implementations/signature/ecdsa_sig.c
@@ -0,0 +1,619 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h> /* memcpy */
+#include <openssl/crypto.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/dsa.h>
+#include <openssl/params.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include "internal/nelem.h"
+#include "internal/sizes.h"
+#include "internal/cryptlib.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/securitycheck.h"
+#include "crypto/ec.h"
+#include "prov/der_ec.h"
+
+static OSSL_FUNC_signature_newctx_fn ecdsa_newctx;
+static OSSL_FUNC_signature_sign_init_fn ecdsa_sign_init;
+static OSSL_FUNC_signature_verify_init_fn ecdsa_verify_init;
+static OSSL_FUNC_signature_sign_fn ecdsa_sign;
+static OSSL_FUNC_signature_verify_fn ecdsa_verify;
+static OSSL_FUNC_signature_digest_sign_init_fn ecdsa_digest_sign_init;
+static OSSL_FUNC_signature_digest_sign_update_fn ecdsa_digest_signverify_update;
+static OSSL_FUNC_signature_digest_sign_final_fn ecdsa_digest_sign_final;
+static OSSL_FUNC_signature_digest_verify_init_fn ecdsa_digest_verify_init;
+static OSSL_FUNC_signature_digest_verify_update_fn ecdsa_digest_signverify_update;
+static OSSL_FUNC_signature_digest_verify_final_fn ecdsa_digest_verify_final;
+static OSSL_FUNC_signature_freectx_fn ecdsa_freectx;
+static OSSL_FUNC_signature_dupctx_fn ecdsa_dupctx;
+static OSSL_FUNC_signature_get_ctx_params_fn ecdsa_get_ctx_params;
+static OSSL_FUNC_signature_gettable_ctx_params_fn ecdsa_gettable_ctx_params;
+static OSSL_FUNC_signature_set_ctx_params_fn ecdsa_set_ctx_params;
+static OSSL_FUNC_signature_settable_ctx_params_fn ecdsa_settable_ctx_params;
+static OSSL_FUNC_signature_get_ctx_md_params_fn ecdsa_get_ctx_md_params;
+static OSSL_FUNC_signature_gettable_ctx_md_params_fn ecdsa_gettable_ctx_md_params;
+static OSSL_FUNC_signature_set_ctx_md_params_fn ecdsa_set_ctx_md_params;
+static OSSL_FUNC_signature_settable_ctx_md_params_fn ecdsa_settable_ctx_md_params;
+
+/*
+ * What's passed as an actual key is defined by the KEYMGMT interface.
+ * We happen to know that our KEYMGMT simply passes DSA structures, so
+ * we use that here too.
+ */
+
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+ EC_KEY *ec;
+ char mdname[OSSL_MAX_NAME_SIZE];
+
+ /*
+ * Flag to determine if the hash function can be changed (1) or not (0)
+ * Because it's dangerous to change during a DigestSign or DigestVerify
+ * operation, this flag is cleared by their Init function, and set again
+ * by their Final function.
+ */
+ unsigned int flag_allow_md : 1;
+
+ /* The Algorithm Identifier of the combined signature algorithm */
+ unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];
+ unsigned char *aid;
+ size_t aid_len;
+ size_t mdsize;
+ int operation;
+
+ EVP_MD *md;
+ EVP_MD_CTX *mdctx;
+ /*
+ * Internally used to cache the results of calling the EC group
+ * sign_setup() methods which are then passed to the sign operation.
+ * This is used by CAVS failure tests to terminate a loop if the signature
+ * is not valid.
+ * This could of also been done with a simple flag.
+ */
+ BIGNUM *kinv;
+ BIGNUM *r;
+#if !defined(OPENSSL_NO_ACVP_TESTS)
+ /*
+ * This indicates that KAT (CAVS) test is running. Externally an app will
+ * override the random callback such that the generated private key and k
+ * are known.
+ * Normal operation will loop to choose a new k if the signature is not
+ * valid - but for this mode of operation it forces a failure instead.
+ */
+ unsigned int kattest;
+#endif
+} PROV_ECDSA_CTX;
+
+static void *ecdsa_newctx(void *provctx, const char *propq)
+{
+ PROV_ECDSA_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(PROV_ECDSA_CTX));
+ if (ctx == NULL)
+ return NULL;
+
+ ctx->flag_allow_md = 1;
+ ctx->libctx = PROV_LIBCTX_OF(provctx);
+ if (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL) {
+ OPENSSL_free(ctx);
+ ctx = NULL;
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ }
+ return ctx;
+}
+
+static int ecdsa_signverify_init(void *vctx, void *ec,
+ const OSSL_PARAM params[], int operation)
+{
+ PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
+
+ if (!ossl_prov_is_running()
+ || ctx == NULL)
+ return 0;
+
+ if (ec == NULL && ctx->ec == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
+ return 0;
+ }
+
+ if (ec != NULL) {
+ if (!ossl_ec_check_key(ctx->libctx, ec, operation == EVP_PKEY_OP_SIGN))
+ return 0;
+ if (!EC_KEY_up_ref(ec))
+ return 0;
+ EC_KEY_free(ctx->ec);
+ ctx->ec = ec;
+ }
+
+ ctx->operation = operation;
+
+ if (!ecdsa_set_ctx_params(ctx, params))
+ return 0;
+
+ return 1;
+}
+
+static int ecdsa_sign_init(void *vctx, void *ec, const OSSL_PARAM params[])
+{
+ return ecdsa_signverify_init(vctx, ec, params, EVP_PKEY_OP_SIGN);
+}
+
+static int ecdsa_verify_init(void *vctx, void *ec, const OSSL_PARAM params[])
+{
+ return ecdsa_signverify_init(vctx, ec, params, EVP_PKEY_OP_VERIFY);
+}
+
+static int ecdsa_sign(void *vctx, unsigned char *sig, size_t *siglen,
+ size_t sigsize, const unsigned char *tbs, size_t tbslen)
+{
+ PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
+ int ret;
+ unsigned int sltmp;
+ size_t ecsize = ECDSA_size(ctx->ec);
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (sig == NULL) {
+ *siglen = ecsize;
+ return 1;
+ }
+
+#if !defined(OPENSSL_NO_ACVP_TESTS)
+ if (ctx->kattest && !ECDSA_sign_setup(ctx->ec, NULL, &ctx->kinv, &ctx->r))
+ return 0;
+#endif
+
+ if (sigsize < (size_t)ecsize)
+ return 0;
+
+ if (ctx->mdsize != 0 && tbslen != ctx->mdsize)
+ return 0;
+
+ ret = ECDSA_sign_ex(0, tbs, tbslen, sig, &sltmp, ctx->kinv, ctx->r, ctx->ec);
+ if (ret <= 0)
+ return 0;
+
+ *siglen = sltmp;
+ return 1;
+}
+
+static int ecdsa_verify(void *vctx, const unsigned char *sig, size_t siglen,
+ const unsigned char *tbs, size_t tbslen)
+{
+ PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
+
+ if (!ossl_prov_is_running() || (ctx->mdsize != 0 && tbslen != ctx->mdsize))
+ return 0;
+
+ return ECDSA_verify(0, tbs, tbslen, sig, siglen, ctx->ec);
+}
+
+static int ecdsa_setup_md(PROV_ECDSA_CTX *ctx, const char *mdname,
+ const char *mdprops)
+{
+ EVP_MD *md = NULL;
+ size_t mdname_len;
+ int md_nid, sha1_allowed;
+ WPACKET pkt;
+
+ if (mdname == NULL)
+ return 1;
+
+ mdname_len = strlen(mdname);
+ if (mdname_len >= sizeof(ctx->mdname)) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
+ "%s exceeds name buffer length", mdname);
+ return 0;
+ }
+ if (mdprops == NULL)
+ mdprops = ctx->propq;
+ md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
+ if (md == NULL) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
+ "%s could not be fetched", mdname);
+ return 0;
+ }
+ sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN);
+ md_nid = ossl_digest_get_approved_nid_with_sha1(ctx->libctx, md,
+ sha1_allowed);
+ if (md_nid < 0) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
+ "digest=%s", mdname);
+ EVP_MD_free(md);
+ return 0;
+ }
+
+ if (!ctx->flag_allow_md) {
+ if (ctx->mdname[0] != '\0' && !EVP_MD_is_a(md, ctx->mdname)) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
+ "digest %s != %s", mdname, ctx->mdname);
+ EVP_MD_free(md);
+ return 0;
+ }
+ EVP_MD_free(md);
+ return 1;
+ }
+
+ EVP_MD_CTX_free(ctx->mdctx);
+ EVP_MD_free(ctx->md);
+
+ ctx->aid_len = 0;
+ if (WPACKET_init_der(&pkt, ctx->aid_buf, sizeof(ctx->aid_buf))
+ && ossl_DER_w_algorithmIdentifier_ECDSA_with_MD(&pkt, -1, ctx->ec,
+ md_nid)
+ && WPACKET_finish(&pkt)) {
+ WPACKET_get_total_written(&pkt, &ctx->aid_len);
+ ctx->aid = WPACKET_get_curr(&pkt);
+ }
+ WPACKET_cleanup(&pkt);
+ ctx->mdctx = NULL;
+ ctx->md = md;
+ ctx->mdsize = EVP_MD_get_size(ctx->md);
+ OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname));
+
+ return 1;
+}
+
+static int ecdsa_digest_signverify_init(void *vctx, const char *mdname,
+ void *ec, const OSSL_PARAM params[],
+ int operation)
+{
+ PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (!ecdsa_signverify_init(vctx, ec, params, operation)
+ || !ecdsa_setup_md(ctx, mdname, NULL))
+ return 0;
+
+ ctx->flag_allow_md = 0;
+
+ if (ctx->mdctx == NULL) {
+ ctx->mdctx = EVP_MD_CTX_new();
+ if (ctx->mdctx == NULL)
+ goto error;
+ }
+
+ if (!EVP_DigestInit_ex2(ctx->mdctx, ctx->md, params))
+ goto error;
+ return 1;
+error:
+ EVP_MD_CTX_free(ctx->mdctx);
+ ctx->mdctx = NULL;
+ return 0;
+}
+
+static int ecdsa_digest_sign_init(void *vctx, const char *mdname, void *ec,
+ const OSSL_PARAM params[])
+{
+ return ecdsa_digest_signverify_init(vctx, mdname, ec, params,
+ EVP_PKEY_OP_SIGN);
+}
+
+static int ecdsa_digest_verify_init(void *vctx, const char *mdname, void *ec,
+ const OSSL_PARAM params[])
+{
+ return ecdsa_digest_signverify_init(vctx, mdname, ec, params,
+ EVP_PKEY_OP_VERIFY);
+}
+
+int ecdsa_digest_signverify_update(void *vctx, const unsigned char *data,
+ size_t datalen)
+{
+ PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
+
+ if (ctx == NULL || ctx->mdctx == NULL)
+ return 0;
+
+ return EVP_DigestUpdate(ctx->mdctx, data, datalen);
+}
+
+int ecdsa_digest_sign_final(void *vctx, unsigned char *sig, size_t *siglen,
+ size_t sigsize)
+{
+ PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ unsigned int dlen = 0;
+
+ if (!ossl_prov_is_running() || ctx == NULL || ctx->mdctx == NULL)
+ return 0;
+
+ /*
+ * If sig is NULL then we're just finding out the sig size. Other fields
+ * are ignored. Defer to ecdsa_sign.
+ */
+ if (sig != NULL
+ && !EVP_DigestFinal_ex(ctx->mdctx, digest, &dlen))
+ return 0;
+ ctx->flag_allow_md = 1;
+ return ecdsa_sign(vctx, sig, siglen, sigsize, digest, (size_t)dlen);
+}
+
+int ecdsa_digest_verify_final(void *vctx, const unsigned char *sig,
+ size_t siglen)
+{
+ PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ unsigned int dlen = 0;
+
+ if (!ossl_prov_is_running() || ctx == NULL || ctx->mdctx == NULL)
+ return 0;
+
+ if (!EVP_DigestFinal_ex(ctx->mdctx, digest, &dlen))
+ return 0;
+ ctx->flag_allow_md = 1;
+ return ecdsa_verify(ctx, sig, siglen, digest, (size_t)dlen);
+}
+
+static void ecdsa_freectx(void *vctx)
+{
+ PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
+
+ OPENSSL_free(ctx->propq);
+ EVP_MD_CTX_free(ctx->mdctx);
+ EVP_MD_free(ctx->md);
+ ctx->propq = NULL;
+ ctx->mdctx = NULL;
+ ctx->md = NULL;
+ ctx->mdsize = 0;
+ EC_KEY_free(ctx->ec);
+ BN_clear_free(ctx->kinv);
+ BN_clear_free(ctx->r);
+ OPENSSL_free(ctx);
+}
+
+static void *ecdsa_dupctx(void *vctx)
+{
+ PROV_ECDSA_CTX *srcctx = (PROV_ECDSA_CTX *)vctx;
+ PROV_ECDSA_CTX *dstctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+ if (dstctx == NULL)
+ return NULL;
+
+ *dstctx = *srcctx;
+ dstctx->ec = NULL;
+ dstctx->md = NULL;
+ dstctx->mdctx = NULL;
+ dstctx->propq = NULL;
+
+ if (srcctx->ec != NULL && !EC_KEY_up_ref(srcctx->ec))
+ goto err;
+ /* Test KATS should not need to be supported */
+ if (srcctx->kinv != NULL || srcctx->r != NULL)
+ goto err;
+ dstctx->ec = srcctx->ec;
+
+ if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md))
+ goto err;
+ dstctx->md = srcctx->md;
+
+ if (srcctx->mdctx != NULL) {
+ dstctx->mdctx = EVP_MD_CTX_new();
+ if (dstctx->mdctx == NULL
+ || !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx))
+ goto err;
+ }
+
+ if (srcctx->propq != NULL) {
+ dstctx->propq = OPENSSL_strdup(srcctx->propq);
+ if (dstctx->propq == NULL)
+ goto err;
+ }
+
+ return dstctx;
+ err:
+ ecdsa_freectx(dstctx);
+ return NULL;
+}
+
+static int ecdsa_get_ctx_params(void *vctx, OSSL_PARAM *params)
+{
+ PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
+ OSSL_PARAM *p;
+
+ if (ctx == NULL)
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
+ if (p != NULL && !OSSL_PARAM_set_octet_string(p, ctx->aid, ctx->aid_len))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->mdsize))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST);
+ if (p != NULL && !OSSL_PARAM_set_utf8_string(p, ctx->md == NULL
+ ? ctx->mdname
+ : EVP_MD_get0_name(ctx->md)))
+ return 0;
+
+ return 1;
+}
+
+static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
+ OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *ecdsa_gettable_ctx_params(ossl_unused void *vctx,
+ ossl_unused void *provctx)
+{
+ return known_gettable_ctx_params;
+}
+
+static int ecdsa_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
+ const OSSL_PARAM *p;
+ size_t mdsize = 0;
+
+ if (ctx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+#if !defined(OPENSSL_NO_ACVP_TESTS)
+ p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_KAT);
+ if (p != NULL && !OSSL_PARAM_get_uint(p, &ctx->kattest))
+ return 0;
+#endif
+
+ p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST);
+ if (p != NULL) {
+ char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = mdname;
+ char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = mdprops;
+ const OSSL_PARAM *propsp =
+ OSSL_PARAM_locate_const(params,
+ OSSL_SIGNATURE_PARAM_PROPERTIES);
+
+ if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname)))
+ return 0;
+ if (propsp != NULL
+ && !OSSL_PARAM_get_utf8_string(propsp, &pmdprops, sizeof(mdprops)))
+ return 0;
+ if (!ecdsa_setup_md(ctx, mdname, mdprops))
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_size_t(p, &mdsize)
+ || (!ctx->flag_allow_md && mdsize != ctx->mdsize))
+ return 0;
+ ctx->mdsize = mdsize;
+ }
+
+ return 1;
+}
+
+static const OSSL_PARAM settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_KAT, NULL),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM settable_ctx_params_no_digest[] = {
+ OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_KAT, NULL),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *ecdsa_settable_ctx_params(void *vctx,
+ ossl_unused void *provctx)
+{
+ PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
+
+ if (ctx != NULL && !ctx->flag_allow_md)
+ return settable_ctx_params_no_digest;
+ return settable_ctx_params;
+}
+
+static int ecdsa_get_ctx_md_params(void *vctx, OSSL_PARAM *params)
+{
+ PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
+
+ if (ctx->mdctx == NULL)
+ return 0;
+
+ return EVP_MD_CTX_get_params(ctx->mdctx, params);
+}
+
+static const OSSL_PARAM *ecdsa_gettable_ctx_md_params(void *vctx)
+{
+ PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
+
+ if (ctx->md == NULL)
+ return 0;
+
+ return EVP_MD_gettable_ctx_params(ctx->md);
+}
+
+static int ecdsa_set_ctx_md_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
+
+ if (ctx->mdctx == NULL)
+ return 0;
+
+ return EVP_MD_CTX_set_params(ctx->mdctx, params);
+}
+
+static const OSSL_PARAM *ecdsa_settable_ctx_md_params(void *vctx)
+{
+ PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
+
+ if (ctx->md == NULL)
+ return 0;
+
+ return EVP_MD_settable_ctx_params(ctx->md);
+}
+
+const OSSL_DISPATCH ossl_ecdsa_signature_functions[] = {
+ { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))ecdsa_newctx },
+ { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))ecdsa_sign_init },
+ { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))ecdsa_sign },
+ { OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))ecdsa_verify_init },
+ { OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))ecdsa_verify },
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
+ (void (*)(void))ecdsa_digest_sign_init },
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
+ (void (*)(void))ecdsa_digest_signverify_update },
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
+ (void (*)(void))ecdsa_digest_sign_final },
+ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
+ (void (*)(void))ecdsa_digest_verify_init },
+ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
+ (void (*)(void))ecdsa_digest_signverify_update },
+ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
+ (void (*)(void))ecdsa_digest_verify_final },
+ { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))ecdsa_freectx },
+ { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))ecdsa_dupctx },
+ { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))ecdsa_get_ctx_params },
+ { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
+ (void (*)(void))ecdsa_gettable_ctx_params },
+ { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))ecdsa_set_ctx_params },
+ { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
+ (void (*)(void))ecdsa_settable_ctx_params },
+ { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS,
+ (void (*)(void))ecdsa_get_ctx_md_params },
+ { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS,
+ (void (*)(void))ecdsa_gettable_ctx_md_params },
+ { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS,
+ (void (*)(void))ecdsa_set_ctx_md_params },
+ { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS,
+ (void (*)(void))ecdsa_settable_ctx_md_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/signature/eddsa_sig.c b/providers/implementations/signature/eddsa_sig.c
new file mode 100644
index 000000000000..c78f1fbb5fa6
--- /dev/null
+++ b/providers/implementations/signature/eddsa_sig.c
@@ -0,0 +1,468 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/err.h>
+#include <openssl/params.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include "internal/nelem.h"
+#include "internal/sizes.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/der_ecx.h"
+#include "crypto/ecx.h"
+
+#ifdef S390X_EC_ASM
+# include "s390x_arch.h"
+
+# define S390X_CAN_SIGN(edtype) \
+((OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_##edtype)) \
+&& (OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_##edtype)) \
+&& (OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_##edtype)))
+
+static int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,
+ const unsigned char *tbs, size_t tbslen);
+static int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,
+ const unsigned char *tbs, size_t tbslen);
+static int s390x_ed25519_digestverify(const ECX_KEY *edkey,
+ const unsigned char *sig,
+ const unsigned char *tbs, size_t tbslen);
+static int s390x_ed448_digestverify(const ECX_KEY *edkey,
+ const unsigned char *sig,
+ const unsigned char *tbs, size_t tbslen);
+
+#endif /* S390X_EC_ASM */
+
+static OSSL_FUNC_signature_newctx_fn eddsa_newctx;
+static OSSL_FUNC_signature_digest_sign_init_fn eddsa_digest_signverify_init;
+static OSSL_FUNC_signature_digest_sign_fn ed25519_digest_sign;
+static OSSL_FUNC_signature_digest_sign_fn ed448_digest_sign;
+static OSSL_FUNC_signature_digest_verify_fn ed25519_digest_verify;
+static OSSL_FUNC_signature_digest_verify_fn ed448_digest_verify;
+static OSSL_FUNC_signature_freectx_fn eddsa_freectx;
+static OSSL_FUNC_signature_dupctx_fn eddsa_dupctx;
+static OSSL_FUNC_signature_get_ctx_params_fn eddsa_get_ctx_params;
+static OSSL_FUNC_signature_gettable_ctx_params_fn eddsa_gettable_ctx_params;
+
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ ECX_KEY *key;
+
+ /* The Algorithm Identifier of the signature algorithm */
+ unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];
+ unsigned char *aid;
+ size_t aid_len;
+} PROV_EDDSA_CTX;
+
+static void *eddsa_newctx(void *provctx, const char *propq_unused)
+{
+ PROV_EDDSA_CTX *peddsactx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ peddsactx = OPENSSL_zalloc(sizeof(PROV_EDDSA_CTX));
+ if (peddsactx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ peddsactx->libctx = PROV_LIBCTX_OF(provctx);
+
+ return peddsactx;
+}
+
+static int eddsa_digest_signverify_init(void *vpeddsactx, const char *mdname,
+ void *vedkey,
+ ossl_unused const OSSL_PARAM params[])
+{
+ PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
+ ECX_KEY *edkey = (ECX_KEY *)vedkey;
+ WPACKET pkt;
+ int ret;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (mdname != NULL && mdname[0] != '\0') {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
+ return 0;
+ }
+
+ if (edkey == NULL) {
+ if (peddsactx->key != NULL)
+ /* there is nothing to do on reinit */
+ return 1;
+ ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
+ return 0;
+ }
+
+ if (!ossl_ecx_key_up_ref(edkey)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /*
+ * We do not care about DER writing errors.
+ * All it really means is that for some reason, there's no
+ * AlgorithmIdentifier to be had, but the operation itself is
+ * still valid, just as long as it's not used to construct
+ * anything that needs an AlgorithmIdentifier.
+ */
+ peddsactx->aid_len = 0;
+ ret = WPACKET_init_der(&pkt, peddsactx->aid_buf, sizeof(peddsactx->aid_buf));
+ switch (edkey->type) {
+ case ECX_KEY_TYPE_ED25519:
+ ret = ret && ossl_DER_w_algorithmIdentifier_ED25519(&pkt, -1, edkey);
+ break;
+ case ECX_KEY_TYPE_ED448:
+ ret = ret && ossl_DER_w_algorithmIdentifier_ED448(&pkt, -1, edkey);
+ break;
+ default:
+ /* Should never happen */
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ ossl_ecx_key_free(edkey);
+ return 0;
+ }
+ if (ret && WPACKET_finish(&pkt)) {
+ WPACKET_get_total_written(&pkt, &peddsactx->aid_len);
+ peddsactx->aid = WPACKET_get_curr(&pkt);
+ }
+ WPACKET_cleanup(&pkt);
+
+ peddsactx->key = edkey;
+
+ return 1;
+}
+
+int ed25519_digest_sign(void *vpeddsactx, unsigned char *sigret,
+ size_t *siglen, size_t sigsize,
+ const unsigned char *tbs, size_t tbslen)
+{
+ PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
+ const ECX_KEY *edkey = peddsactx->key;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (sigret == NULL) {
+ *siglen = ED25519_SIGSIZE;
+ return 1;
+ }
+ if (sigsize < ED25519_SIGSIZE) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+ if (edkey->privkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
+ return 0;
+ }
+#ifdef S390X_EC_ASM
+ if (S390X_CAN_SIGN(ED25519)) {
+ if (s390x_ed25519_digestsign(edkey, sigret, tbs, tbslen) == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
+ return 0;
+ }
+ *siglen = ED25519_SIGSIZE;
+ return 1;
+ }
+#endif /* S390X_EC_ASM */
+ if (ossl_ed25519_sign(sigret, tbs, tbslen, edkey->pubkey, edkey->privkey,
+ peddsactx->libctx, NULL) == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
+ return 0;
+ }
+ *siglen = ED25519_SIGSIZE;
+ return 1;
+}
+
+int ed448_digest_sign(void *vpeddsactx, unsigned char *sigret,
+ size_t *siglen, size_t sigsize,
+ const unsigned char *tbs, size_t tbslen)
+{
+ PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
+ const ECX_KEY *edkey = peddsactx->key;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (sigret == NULL) {
+ *siglen = ED448_SIGSIZE;
+ return 1;
+ }
+ if (sigsize < ED448_SIGSIZE) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+ if (edkey->privkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
+ return 0;
+ }
+#ifdef S390X_EC_ASM
+ if (S390X_CAN_SIGN(ED448)) {
+ if (s390x_ed448_digestsign(edkey, sigret, tbs, tbslen) == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
+ return 0;
+ }
+ *siglen = ED448_SIGSIZE;
+ return 1;
+ }
+#endif /* S390X_EC_ASM */
+ if (ossl_ed448_sign(peddsactx->libctx, sigret, tbs, tbslen, edkey->pubkey,
+ edkey->privkey, NULL, 0, edkey->propq) == 0) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
+ return 0;
+ }
+ *siglen = ED448_SIGSIZE;
+ return 1;
+}
+
+int ed25519_digest_verify(void *vpeddsactx, const unsigned char *sig,
+ size_t siglen, const unsigned char *tbs,
+ size_t tbslen)
+{
+ PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
+ const ECX_KEY *edkey = peddsactx->key;
+
+ if (!ossl_prov_is_running() || siglen != ED25519_SIGSIZE)
+ return 0;
+
+#ifdef S390X_EC_ASM
+ if (S390X_CAN_SIGN(ED25519))
+ return s390x_ed25519_digestverify(edkey, sig, tbs, tbslen);
+#endif /* S390X_EC_ASM */
+
+ return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
+ peddsactx->libctx, edkey->propq);
+}
+
+int ed448_digest_verify(void *vpeddsactx, const unsigned char *sig,
+ size_t siglen, const unsigned char *tbs,
+ size_t tbslen)
+{
+ PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
+ const ECX_KEY *edkey = peddsactx->key;
+
+ if (!ossl_prov_is_running() || siglen != ED448_SIGSIZE)
+ return 0;
+
+#ifdef S390X_EC_ASM
+ if (S390X_CAN_SIGN(ED448))
+ return s390x_ed448_digestverify(edkey, sig, tbs, tbslen);
+#endif /* S390X_EC_ASM */
+
+ return ossl_ed448_verify(peddsactx->libctx, tbs, tbslen, sig, edkey->pubkey,
+ NULL, 0, edkey->propq);
+}
+
+static void eddsa_freectx(void *vpeddsactx)
+{
+ PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
+
+ ossl_ecx_key_free(peddsactx->key);
+
+ OPENSSL_free(peddsactx);
+}
+
+static void *eddsa_dupctx(void *vpeddsactx)
+{
+ PROV_EDDSA_CTX *srcctx = (PROV_EDDSA_CTX *)vpeddsactx;
+ PROV_EDDSA_CTX *dstctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+ if (dstctx == NULL)
+ return NULL;
+
+ *dstctx = *srcctx;
+ dstctx->key = NULL;
+
+ if (srcctx->key != NULL && !ossl_ecx_key_up_ref(srcctx->key)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ dstctx->key = srcctx->key;
+
+ return dstctx;
+ err:
+ eddsa_freectx(dstctx);
+ return NULL;
+}
+
+static int eddsa_get_ctx_params(void *vpeddsactx, OSSL_PARAM *params)
+{
+ PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
+ OSSL_PARAM *p;
+
+ if (peddsactx == NULL)
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
+ if (p != NULL && !OSSL_PARAM_set_octet_string(p, peddsactx->aid,
+ peddsactx->aid_len))
+ return 0;
+
+ return 1;
+}
+
+static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *eddsa_gettable_ctx_params(ossl_unused void *vpeddsactx,
+ ossl_unused void *provctx)
+{
+ return known_gettable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_ed25519_signature_functions[] = {
+ { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
+ (void (*)(void))eddsa_digest_signverify_init },
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN,
+ (void (*)(void))ed25519_digest_sign },
+ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
+ (void (*)(void))eddsa_digest_signverify_init },
+ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,
+ (void (*)(void))ed25519_digest_verify },
+ { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx },
+ { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },
+ { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params },
+ { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
+ (void (*)(void))eddsa_gettable_ctx_params },
+ { 0, NULL }
+};
+
+const OSSL_DISPATCH ossl_ed448_signature_functions[] = {
+ { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
+ (void (*)(void))eddsa_digest_signverify_init },
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN,
+ (void (*)(void))ed448_digest_sign },
+ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
+ (void (*)(void))eddsa_digest_signverify_init },
+ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,
+ (void (*)(void))ed448_digest_verify },
+ { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx },
+ { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },
+ { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params },
+ { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
+ (void (*)(void))eddsa_gettable_ctx_params },
+ { 0, NULL }
+};
+
+#ifdef S390X_EC_ASM
+
+static int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,
+ const unsigned char *tbs, size_t tbslen)
+{
+ int rc;
+ union {
+ struct {
+ unsigned char sig[64];
+ unsigned char priv[32];
+ } ed25519;
+ unsigned long long buff[512];
+ } param;
+
+ memset(&param, 0, sizeof(param));
+ memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
+
+ rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
+ OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
+ if (rc != 0)
+ return 0;
+
+ s390x_flip_endian32(sig, param.ed25519.sig);
+ s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
+ return 1;
+}
+
+static int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,
+ const unsigned char *tbs, size_t tbslen)
+{
+ int rc;
+ union {
+ struct {
+ unsigned char sig[128];
+ unsigned char priv[64];
+ } ed448;
+ unsigned long long buff[512];
+ } param;
+
+ memset(&param, 0, sizeof(param));
+ memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
+
+ rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
+ OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
+ if (rc != 0)
+ return 0;
+
+ s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
+ s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
+ memcpy(sig, param.ed448.sig, 57);
+ memcpy(sig + 57, param.ed448.sig + 64, 57);
+ return 1;
+}
+
+static int s390x_ed25519_digestverify(const ECX_KEY *edkey,
+ const unsigned char *sig,
+ const unsigned char *tbs, size_t tbslen)
+{
+ union {
+ struct {
+ unsigned char sig[64];
+ unsigned char pub[32];
+ } ed25519;
+ unsigned long long buff[512];
+ } param;
+
+ memset(&param, 0, sizeof(param));
+ s390x_flip_endian32(param.ed25519.sig, sig);
+ s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
+ s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
+
+ return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
+ &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
+}
+
+static int s390x_ed448_digestverify(const ECX_KEY *edkey,
+ const unsigned char *sig,
+ const unsigned char *tbs,
+ size_t tbslen)
+{
+ union {
+ struct {
+ unsigned char sig[128];
+ unsigned char pub[64];
+ } ed448;
+ unsigned long long buff[512];
+ } param;
+
+ memset(&param, 0, sizeof(param));
+ memcpy(param.ed448.sig, sig, 57);
+ s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
+ memcpy(param.ed448.sig + 64, sig + 57, 57);
+ s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
+ memcpy(param.ed448.pub, edkey->pubkey, 57);
+ s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
+
+ return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
+ &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
+}
+
+#endif /* S390X_EC_ASM */
diff --git a/providers/implementations/signature/mac_legacy_sig.c b/providers/implementations/signature/mac_legacy_sig.c
new file mode 100644
index 000000000000..6be605c8c60f
--- /dev/null
+++ b/providers/implementations/signature/mac_legacy_sig.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#ifndef FIPS_MODULE
+# include <openssl/engine.h>
+#endif
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/macsignature.h"
+#include "prov/providercommon.h"
+
+static OSSL_FUNC_signature_newctx_fn mac_hmac_newctx;
+static OSSL_FUNC_signature_newctx_fn mac_siphash_newctx;
+static OSSL_FUNC_signature_newctx_fn mac_poly1305_newctx;
+static OSSL_FUNC_signature_newctx_fn mac_cmac_newctx;
+static OSSL_FUNC_signature_digest_sign_init_fn mac_digest_sign_init;
+static OSSL_FUNC_signature_digest_sign_update_fn mac_digest_sign_update;
+static OSSL_FUNC_signature_digest_sign_final_fn mac_digest_sign_final;
+static OSSL_FUNC_signature_freectx_fn mac_freectx;
+static OSSL_FUNC_signature_dupctx_fn mac_dupctx;
+static OSSL_FUNC_signature_set_ctx_params_fn mac_set_ctx_params;
+static OSSL_FUNC_signature_settable_ctx_params_fn mac_hmac_settable_ctx_params;
+static OSSL_FUNC_signature_settable_ctx_params_fn mac_siphash_settable_ctx_params;
+static OSSL_FUNC_signature_settable_ctx_params_fn mac_poly1305_settable_ctx_params;
+static OSSL_FUNC_signature_settable_ctx_params_fn mac_cmac_settable_ctx_params;
+
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+ MAC_KEY *key;
+ EVP_MAC_CTX *macctx;
+} PROV_MAC_CTX;
+
+static void *mac_newctx(void *provctx, const char *propq, const char *macname)
+{
+ PROV_MAC_CTX *pmacctx;
+ EVP_MAC *mac = NULL;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ pmacctx = OPENSSL_zalloc(sizeof(PROV_MAC_CTX));
+ if (pmacctx == NULL)
+ return NULL;
+
+ pmacctx->libctx = PROV_LIBCTX_OF(provctx);
+ if (propq != NULL && (pmacctx->propq = OPENSSL_strdup(propq)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ mac = EVP_MAC_fetch(pmacctx->libctx, macname, propq);
+ if (mac == NULL)
+ goto err;
+
+ pmacctx->macctx = EVP_MAC_CTX_new(mac);
+ if (pmacctx->macctx == NULL)
+ goto err;
+
+ EVP_MAC_free(mac);
+
+ return pmacctx;
+
+ err:
+ OPENSSL_free(pmacctx->propq);
+ OPENSSL_free(pmacctx);
+ EVP_MAC_free(mac);
+ return NULL;
+}
+
+#define MAC_NEWCTX(funcname, macname) \
+ static void *mac_##funcname##_newctx(void *provctx, const char *propq) \
+ { \
+ return mac_newctx(provctx, propq, macname); \
+ }
+
+MAC_NEWCTX(hmac, "HMAC")
+MAC_NEWCTX(siphash, "SIPHASH")
+MAC_NEWCTX(poly1305, "POLY1305")
+MAC_NEWCTX(cmac, "CMAC")
+
+static int mac_digest_sign_init(void *vpmacctx, const char *mdname, void *vkey,
+ const OSSL_PARAM params[])
+{
+ PROV_MAC_CTX *pmacctx = (PROV_MAC_CTX *)vpmacctx;
+ const char *ciphername = NULL, *engine = NULL;
+
+ if (!ossl_prov_is_running()
+ || pmacctx == NULL)
+ return 0;
+
+ if (pmacctx->key == NULL && vkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
+ return 0;
+ }
+
+ if (vkey != NULL) {
+ if (!ossl_mac_key_up_ref(vkey))
+ return 0;
+ ossl_mac_key_free(pmacctx->key);
+ pmacctx->key = vkey;
+ }
+
+ if (pmacctx->key->cipher.cipher != NULL)
+ ciphername = (char *)EVP_CIPHER_get0_name(pmacctx->key->cipher.cipher);
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
+ if (pmacctx->key->cipher.engine != NULL)
+ engine = (char *)ENGINE_get_id(pmacctx->key->cipher.engine);
+#endif
+
+ if (!ossl_prov_set_macctx(pmacctx->macctx, NULL,
+ (char *)ciphername,
+ (char *)mdname,
+ (char *)engine,
+ pmacctx->key->properties,
+ NULL, 0))
+ return 0;
+
+ if (!EVP_MAC_init(pmacctx->macctx, pmacctx->key->priv_key,
+ pmacctx->key->priv_key_len, params))
+ return 0;
+
+ return 1;
+}
+
+int mac_digest_sign_update(void *vpmacctx, const unsigned char *data,
+ size_t datalen)
+{
+ PROV_MAC_CTX *pmacctx = (PROV_MAC_CTX *)vpmacctx;
+
+ if (pmacctx == NULL || pmacctx->macctx == NULL)
+ return 0;
+
+ return EVP_MAC_update(pmacctx->macctx, data, datalen);
+}
+
+int mac_digest_sign_final(void *vpmacctx, unsigned char *mac, size_t *maclen,
+ size_t macsize)
+{
+ PROV_MAC_CTX *pmacctx = (PROV_MAC_CTX *)vpmacctx;
+
+ if (!ossl_prov_is_running() || pmacctx == NULL || pmacctx->macctx == NULL)
+ return 0;
+
+ return EVP_MAC_final(pmacctx->macctx, mac, maclen, macsize);
+}
+
+static void mac_freectx(void *vpmacctx)
+{
+ PROV_MAC_CTX *ctx = (PROV_MAC_CTX *)vpmacctx;
+
+ OPENSSL_free(ctx->propq);
+ EVP_MAC_CTX_free(ctx->macctx);
+ ossl_mac_key_free(ctx->key);
+ OPENSSL_free(ctx);
+}
+
+static void *mac_dupctx(void *vpmacctx)
+{
+ PROV_MAC_CTX *srcctx = (PROV_MAC_CTX *)vpmacctx;
+ PROV_MAC_CTX *dstctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+ if (dstctx == NULL)
+ return NULL;
+
+ *dstctx = *srcctx;
+ dstctx->propq = NULL;
+ dstctx->key = NULL;
+ dstctx->macctx = NULL;
+
+ if (srcctx->propq != NULL && (dstctx->propq = OPENSSL_strdup(srcctx->propq)) == NULL)
+ goto err;
+
+ if (srcctx->key != NULL && !ossl_mac_key_up_ref(srcctx->key))
+ goto err;
+ dstctx->key = srcctx->key;
+
+ if (srcctx->macctx != NULL) {
+ dstctx->macctx = EVP_MAC_CTX_dup(srcctx->macctx);
+ if (dstctx->macctx == NULL)
+ goto err;
+ }
+
+ return dstctx;
+ err:
+ mac_freectx(dstctx);
+ return NULL;
+}
+
+static int mac_set_ctx_params(void *vpmacctx, const OSSL_PARAM params[])
+{
+ PROV_MAC_CTX *ctx = (PROV_MAC_CTX *)vpmacctx;
+
+ return EVP_MAC_CTX_set_params(ctx->macctx, params);
+}
+
+static const OSSL_PARAM *mac_settable_ctx_params(ossl_unused void *ctx,
+ void *provctx,
+ const char *macname)
+{
+ EVP_MAC *mac = EVP_MAC_fetch(PROV_LIBCTX_OF(provctx), macname,
+ NULL);
+ const OSSL_PARAM *params;
+
+ if (mac == NULL)
+ return NULL;
+
+ params = EVP_MAC_settable_ctx_params(mac);
+ EVP_MAC_free(mac);
+
+ return params;
+}
+
+#define MAC_SETTABLE_CTX_PARAMS(funcname, macname) \
+ static const OSSL_PARAM *mac_##funcname##_settable_ctx_params(void *ctx, \
+ void *provctx) \
+ { \
+ return mac_settable_ctx_params(ctx, provctx, macname); \
+ }
+
+MAC_SETTABLE_CTX_PARAMS(hmac, "HMAC")
+MAC_SETTABLE_CTX_PARAMS(siphash, "SIPHASH")
+MAC_SETTABLE_CTX_PARAMS(poly1305, "POLY1305")
+MAC_SETTABLE_CTX_PARAMS(cmac, "CMAC")
+
+#define MAC_SIGNATURE_FUNCTIONS(funcname) \
+ const OSSL_DISPATCH ossl_mac_legacy_##funcname##_signature_functions[] = { \
+ { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))mac_##funcname##_newctx }, \
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, \
+ (void (*)(void))mac_digest_sign_init }, \
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, \
+ (void (*)(void))mac_digest_sign_update }, \
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, \
+ (void (*)(void))mac_digest_sign_final }, \
+ { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))mac_freectx }, \
+ { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))mac_dupctx }, \
+ { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, \
+ (void (*)(void))mac_set_ctx_params }, \
+ { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))mac_##funcname##_settable_ctx_params }, \
+ { 0, NULL } \
+ };
+
+MAC_SIGNATURE_FUNCTIONS(hmac)
+MAC_SIGNATURE_FUNCTIONS(siphash)
+MAC_SIGNATURE_FUNCTIONS(poly1305)
+MAC_SIGNATURE_FUNCTIONS(cmac)
diff --git a/providers/implementations/signature/rsa_sig.c b/providers/implementations/signature/rsa_sig.c
new file mode 100644
index 000000000000..7023a866131e
--- /dev/null
+++ b/providers/implementations/signature/rsa_sig.c
@@ -0,0 +1,1474 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+#include <openssl/params.h>
+#include <openssl/evp.h>
+#include <openssl/proverr.h>
+#include "internal/cryptlib.h"
+#include "internal/nelem.h"
+#include "internal/sizes.h"
+#include "crypto/rsa.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/der_rsa.h"
+#include "prov/securitycheck.h"
+
+#define RSA_DEFAULT_DIGEST_NAME OSSL_DIGEST_NAME_SHA1
+
+static OSSL_FUNC_signature_newctx_fn rsa_newctx;
+static OSSL_FUNC_signature_sign_init_fn rsa_sign_init;
+static OSSL_FUNC_signature_verify_init_fn rsa_verify_init;
+static OSSL_FUNC_signature_verify_recover_init_fn rsa_verify_recover_init;
+static OSSL_FUNC_signature_sign_fn rsa_sign;
+static OSSL_FUNC_signature_verify_fn rsa_verify;
+static OSSL_FUNC_signature_verify_recover_fn rsa_verify_recover;
+static OSSL_FUNC_signature_digest_sign_init_fn rsa_digest_sign_init;
+static OSSL_FUNC_signature_digest_sign_update_fn rsa_digest_signverify_update;
+static OSSL_FUNC_signature_digest_sign_final_fn rsa_digest_sign_final;
+static OSSL_FUNC_signature_digest_verify_init_fn rsa_digest_verify_init;
+static OSSL_FUNC_signature_digest_verify_update_fn rsa_digest_signverify_update;
+static OSSL_FUNC_signature_digest_verify_final_fn rsa_digest_verify_final;
+static OSSL_FUNC_signature_freectx_fn rsa_freectx;
+static OSSL_FUNC_signature_dupctx_fn rsa_dupctx;
+static OSSL_FUNC_signature_get_ctx_params_fn rsa_get_ctx_params;
+static OSSL_FUNC_signature_gettable_ctx_params_fn rsa_gettable_ctx_params;
+static OSSL_FUNC_signature_set_ctx_params_fn rsa_set_ctx_params;
+static OSSL_FUNC_signature_settable_ctx_params_fn rsa_settable_ctx_params;
+static OSSL_FUNC_signature_get_ctx_md_params_fn rsa_get_ctx_md_params;
+static OSSL_FUNC_signature_gettable_ctx_md_params_fn rsa_gettable_ctx_md_params;
+static OSSL_FUNC_signature_set_ctx_md_params_fn rsa_set_ctx_md_params;
+static OSSL_FUNC_signature_settable_ctx_md_params_fn rsa_settable_ctx_md_params;
+
+static OSSL_ITEM padding_item[] = {
+ { RSA_PKCS1_PADDING, OSSL_PKEY_RSA_PAD_MODE_PKCSV15 },
+ { RSA_NO_PADDING, OSSL_PKEY_RSA_PAD_MODE_NONE },
+ { RSA_X931_PADDING, OSSL_PKEY_RSA_PAD_MODE_X931 },
+ { RSA_PKCS1_PSS_PADDING, OSSL_PKEY_RSA_PAD_MODE_PSS },
+ { 0, NULL }
+};
+
+/*
+ * What's passed as an actual key is defined by the KEYMGMT interface.
+ * We happen to know that our KEYMGMT simply passes RSA structures, so
+ * we use that here too.
+ */
+
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+ RSA *rsa;
+ int operation;
+
+ /*
+ * Flag to determine if the hash function can be changed (1) or not (0)
+ * Because it's dangerous to change during a DigestSign or DigestVerify
+ * operation, this flag is cleared by their Init function, and set again
+ * by their Final function.
+ */
+ unsigned int flag_allow_md : 1;
+ unsigned int mgf1_md_set : 1;
+
+ /* main digest */
+ EVP_MD *md;
+ EVP_MD_CTX *mdctx;
+ int mdnid;
+ char mdname[OSSL_MAX_NAME_SIZE]; /* Purely informational */
+
+ /* RSA padding mode */
+ int pad_mode;
+ /* message digest for MGF1 */
+ EVP_MD *mgf1_md;
+ int mgf1_mdnid;
+ char mgf1_mdname[OSSL_MAX_NAME_SIZE]; /* Purely informational */
+ /* PSS salt length */
+ int saltlen;
+ /* Minimum salt length or -1 if no PSS parameter restriction */
+ int min_saltlen;
+
+ /* Temp buffer */
+ unsigned char *tbuf;
+
+} PROV_RSA_CTX;
+
+/* True if PSS parameters are restricted */
+#define rsa_pss_restricted(prsactx) (prsactx->min_saltlen != -1)
+
+static size_t rsa_get_md_size(const PROV_RSA_CTX *prsactx)
+{
+ if (prsactx->md != NULL)
+ return EVP_MD_get_size(prsactx->md);
+ return 0;
+}
+
+static int rsa_check_padding(const PROV_RSA_CTX *prsactx,
+ const char *mdname, const char *mgf1_mdname,
+ int mdnid)
+{
+ switch(prsactx->pad_mode) {
+ case RSA_NO_PADDING:
+ if (mdname != NULL || mdnid != NID_undef) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE);
+ return 0;
+ }
+ break;
+ case RSA_X931_PADDING:
+ if (RSA_X931_hash_id(mdnid) == -1) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_X931_DIGEST);
+ return 0;
+ }
+ break;
+ case RSA_PKCS1_PSS_PADDING:
+ if (rsa_pss_restricted(prsactx))
+ if ((mdname != NULL && !EVP_MD_is_a(prsactx->md, mdname))
+ || (mgf1_mdname != NULL
+ && !EVP_MD_is_a(prsactx->mgf1_md, mgf1_mdname))) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 1;
+}
+
+static int rsa_check_parameters(PROV_RSA_CTX *prsactx, int min_saltlen)
+{
+ if (prsactx->pad_mode == RSA_PKCS1_PSS_PADDING) {
+ int max_saltlen;
+
+ /* See if minimum salt length exceeds maximum possible */
+ max_saltlen = RSA_size(prsactx->rsa) - EVP_MD_get_size(prsactx->md);
+ if ((RSA_bits(prsactx->rsa) & 0x7) == 1)
+ max_saltlen--;
+ if (min_saltlen < 0 || min_saltlen > max_saltlen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH);
+ return 0;
+ }
+ prsactx->min_saltlen = min_saltlen;
+ }
+ return 1;
+}
+
+static void *rsa_newctx(void *provctx, const char *propq)
+{
+ PROV_RSA_CTX *prsactx = NULL;
+ char *propq_copy = NULL;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if ((prsactx = OPENSSL_zalloc(sizeof(PROV_RSA_CTX))) == NULL
+ || (propq != NULL
+ && (propq_copy = OPENSSL_strdup(propq)) == NULL)) {
+ OPENSSL_free(prsactx);
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ prsactx->libctx = PROV_LIBCTX_OF(provctx);
+ prsactx->flag_allow_md = 1;
+ prsactx->propq = propq_copy;
+ /* Maximum for sign, auto for verify */
+ prsactx->saltlen = RSA_PSS_SALTLEN_AUTO;
+ prsactx->min_saltlen = -1;
+ return prsactx;
+}
+
+static int rsa_pss_compute_saltlen(PROV_RSA_CTX *ctx)
+{
+ int saltlen = ctx->saltlen;
+
+ if (saltlen == RSA_PSS_SALTLEN_DIGEST) {
+ saltlen = EVP_MD_get_size(ctx->md);
+ } else if (saltlen == RSA_PSS_SALTLEN_AUTO || saltlen == RSA_PSS_SALTLEN_MAX) {
+ saltlen = RSA_size(ctx->rsa) - EVP_MD_get_size(ctx->md) - 2;
+ if ((RSA_bits(ctx->rsa) & 0x7) == 1)
+ saltlen--;
+ }
+ if (saltlen < 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ return -1;
+ } else if (saltlen < ctx->min_saltlen) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL,
+ "minimum salt length: %d, actual salt length: %d",
+ ctx->min_saltlen, saltlen);
+ return -1;
+ }
+ return saltlen;
+}
+
+static unsigned char *rsa_generate_signature_aid(PROV_RSA_CTX *ctx,
+ unsigned char *aid_buf,
+ size_t buf_len,
+ size_t *aid_len)
+{
+ WPACKET pkt;
+ unsigned char *aid = NULL;
+ int saltlen;
+ RSA_PSS_PARAMS_30 pss_params;
+ int ret;
+
+ if (!WPACKET_init_der(&pkt, aid_buf, buf_len)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ switch(ctx->pad_mode) {
+ case RSA_PKCS1_PADDING:
+ ret = ossl_DER_w_algorithmIdentifier_MDWithRSAEncryption(&pkt, -1,
+ ctx->mdnid);
+
+ if (ret > 0) {
+ break;
+ } else if (ret == 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ goto cleanup;
+ }
+ ERR_raise_data(ERR_LIB_PROV, ERR_R_UNSUPPORTED,
+ "Algorithm ID generation - md NID: %d",
+ ctx->mdnid);
+ goto cleanup;
+ case RSA_PKCS1_PSS_PADDING:
+ saltlen = rsa_pss_compute_saltlen(ctx);
+ if (saltlen < 0)
+ goto cleanup;
+ if (!ossl_rsa_pss_params_30_set_defaults(&pss_params)
+ || !ossl_rsa_pss_params_30_set_hashalg(&pss_params, ctx->mdnid)
+ || !ossl_rsa_pss_params_30_set_maskgenhashalg(&pss_params,
+ ctx->mgf1_mdnid)
+ || !ossl_rsa_pss_params_30_set_saltlen(&pss_params, saltlen)
+ || !ossl_DER_w_algorithmIdentifier_RSA_PSS(&pkt, -1,
+ RSA_FLAG_TYPE_RSASSAPSS,
+ &pss_params)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ goto cleanup;
+ }
+ break;
+ default:
+ ERR_raise_data(ERR_LIB_PROV, ERR_R_UNSUPPORTED,
+ "Algorithm ID generation - pad mode: %d",
+ ctx->pad_mode);
+ goto cleanup;
+ }
+ if (WPACKET_finish(&pkt)) {
+ WPACKET_get_total_written(&pkt, aid_len);
+ aid = WPACKET_get_curr(&pkt);
+ }
+ cleanup:
+ WPACKET_cleanup(&pkt);
+ return aid;
+}
+
+static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname,
+ const char *mdprops)
+{
+ if (mdprops == NULL)
+ mdprops = ctx->propq;
+
+ if (mdname != NULL) {
+ EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
+ int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN);
+ int md_nid = ossl_digest_rsa_sign_get_md_nid(ctx->libctx, md,
+ sha1_allowed);
+ size_t mdname_len = strlen(mdname);
+
+ if (md == NULL
+ || md_nid <= 0
+ || !rsa_check_padding(ctx, mdname, NULL, md_nid)
+ || mdname_len >= sizeof(ctx->mdname)) {
+ if (md == NULL)
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
+ "%s could not be fetched", mdname);
+ if (md_nid <= 0)
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
+ "digest=%s", mdname);
+ if (mdname_len >= sizeof(ctx->mdname))
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
+ "%s exceeds name buffer length", mdname);
+ EVP_MD_free(md);
+ return 0;
+ }
+
+ if (!ctx->flag_allow_md) {
+ if (ctx->mdname[0] != '\0' && !EVP_MD_is_a(md, ctx->mdname)) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
+ "digest %s != %s", mdname, ctx->mdname);
+ EVP_MD_free(md);
+ return 0;
+ }
+ EVP_MD_free(md);
+ return 1;
+ }
+
+ if (!ctx->mgf1_md_set) {
+ if (!EVP_MD_up_ref(md)) {
+ EVP_MD_free(md);
+ return 0;
+ }
+ EVP_MD_free(ctx->mgf1_md);
+ ctx->mgf1_md = md;
+ ctx->mgf1_mdnid = md_nid;
+ OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname));
+ }
+
+ EVP_MD_CTX_free(ctx->mdctx);
+ EVP_MD_free(ctx->md);
+
+ ctx->mdctx = NULL;
+ ctx->md = md;
+ ctx->mdnid = md_nid;
+ OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname));
+ }
+
+ return 1;
+}
+
+static int rsa_setup_mgf1_md(PROV_RSA_CTX *ctx, const char *mdname,
+ const char *mdprops)
+{
+ size_t len;
+ EVP_MD *md = NULL;
+ int mdnid;
+
+ if (mdprops == NULL)
+ mdprops = ctx->propq;
+
+ if ((md = EVP_MD_fetch(ctx->libctx, mdname, mdprops)) == NULL) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
+ "%s could not be fetched", mdname);
+ return 0;
+ }
+ /* The default for mgf1 is SHA1 - so allow SHA1 */
+ if ((mdnid = ossl_digest_rsa_sign_get_md_nid(ctx->libctx, md, 1)) <= 0
+ || !rsa_check_padding(ctx, NULL, mdname, mdnid)) {
+ if (mdnid <= 0)
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
+ "digest=%s", mdname);
+ EVP_MD_free(md);
+ return 0;
+ }
+ len = OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname));
+ if (len >= sizeof(ctx->mgf1_mdname)) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
+ "%s exceeds name buffer length", mdname);
+ EVP_MD_free(md);
+ return 0;
+ }
+
+ EVP_MD_free(ctx->mgf1_md);
+ ctx->mgf1_md = md;
+ ctx->mgf1_mdnid = mdnid;
+ ctx->mgf1_md_set = 1;
+ return 1;
+}
+
+static int rsa_signverify_init(void *vprsactx, void *vrsa,
+ const OSSL_PARAM params[], int operation)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (!ossl_prov_is_running() || prsactx == NULL)
+ return 0;
+
+ if (vrsa == NULL && prsactx->rsa == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
+ return 0;
+ }
+
+ if (vrsa != NULL) {
+ if (!ossl_rsa_check_key(prsactx->libctx, vrsa, operation))
+ return 0;
+
+ if (!RSA_up_ref(vrsa))
+ return 0;
+ RSA_free(prsactx->rsa);
+ prsactx->rsa = vrsa;
+ }
+
+ prsactx->operation = operation;
+
+ /* Maximum for sign, auto for verify */
+ prsactx->saltlen = RSA_PSS_SALTLEN_AUTO;
+ prsactx->min_saltlen = -1;
+
+ switch (RSA_test_flags(prsactx->rsa, RSA_FLAG_TYPE_MASK)) {
+ case RSA_FLAG_TYPE_RSA:
+ prsactx->pad_mode = RSA_PKCS1_PADDING;
+ break;
+ case RSA_FLAG_TYPE_RSASSAPSS:
+ prsactx->pad_mode = RSA_PKCS1_PSS_PADDING;
+
+ {
+ const RSA_PSS_PARAMS_30 *pss =
+ ossl_rsa_get0_pss_params_30(prsactx->rsa);
+
+ if (!ossl_rsa_pss_params_30_is_unrestricted(pss)) {
+ int md_nid = ossl_rsa_pss_params_30_hashalg(pss);
+ int mgf1md_nid = ossl_rsa_pss_params_30_maskgenhashalg(pss);
+ int min_saltlen = ossl_rsa_pss_params_30_saltlen(pss);
+ const char *mdname, *mgf1mdname;
+ size_t len;
+
+ mdname = ossl_rsa_oaeppss_nid2name(md_nid);
+ mgf1mdname = ossl_rsa_oaeppss_nid2name(mgf1md_nid);
+
+ if (mdname == NULL) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
+ "PSS restrictions lack hash algorithm");
+ return 0;
+ }
+ if (mgf1mdname == NULL) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
+ "PSS restrictions lack MGF1 hash algorithm");
+ return 0;
+ }
+
+ len = OPENSSL_strlcpy(prsactx->mdname, mdname,
+ sizeof(prsactx->mdname));
+ if (len >= sizeof(prsactx->mdname)) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
+ "hash algorithm name too long");
+ return 0;
+ }
+ len = OPENSSL_strlcpy(prsactx->mgf1_mdname, mgf1mdname,
+ sizeof(prsactx->mgf1_mdname));
+ if (len >= sizeof(prsactx->mgf1_mdname)) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
+ "MGF1 hash algorithm name too long");
+ return 0;
+ }
+ prsactx->saltlen = min_saltlen;
+
+ /* call rsa_setup_mgf1_md before rsa_setup_md to avoid duplication */
+ if (!rsa_setup_mgf1_md(prsactx, mgf1mdname, prsactx->propq)
+ || !rsa_setup_md(prsactx, mdname, prsactx->propq)
+ || !rsa_check_parameters(prsactx, min_saltlen))
+ return 0;
+ }
+ }
+
+ break;
+ default:
+ ERR_raise(ERR_LIB_RSA, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+
+ if (!rsa_set_ctx_params(prsactx, params))
+ return 0;
+
+ return 1;
+}
+
+static int setup_tbuf(PROV_RSA_CTX *ctx)
+{
+ if (ctx->tbuf != NULL)
+ return 1;
+ if ((ctx->tbuf = OPENSSL_malloc(RSA_size(ctx->rsa))) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ return 1;
+}
+
+static void clean_tbuf(PROV_RSA_CTX *ctx)
+{
+ if (ctx->tbuf != NULL)
+ OPENSSL_cleanse(ctx->tbuf, RSA_size(ctx->rsa));
+}
+
+static void free_tbuf(PROV_RSA_CTX *ctx)
+{
+ clean_tbuf(ctx);
+ OPENSSL_free(ctx->tbuf);
+ ctx->tbuf = NULL;
+}
+
+static int rsa_sign_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[])
+{
+ if (!ossl_prov_is_running())
+ return 0;
+ return rsa_signverify_init(vprsactx, vrsa, params, EVP_PKEY_OP_SIGN);
+}
+
+static int rsa_sign(void *vprsactx, unsigned char *sig, size_t *siglen,
+ size_t sigsize, const unsigned char *tbs, size_t tbslen)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ int ret;
+ size_t rsasize = RSA_size(prsactx->rsa);
+ size_t mdsize = rsa_get_md_size(prsactx);
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (sig == NULL) {
+ *siglen = rsasize;
+ return 1;
+ }
+
+ if (sigsize < rsasize) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SIGNATURE_SIZE,
+ "is %zu, should be at least %zu", sigsize, rsasize);
+ return 0;
+ }
+
+ if (mdsize != 0) {
+ if (tbslen != mdsize) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
+ return 0;
+ }
+
+#ifndef FIPS_MODULE
+ if (EVP_MD_is_a(prsactx->md, OSSL_DIGEST_NAME_MDC2)) {
+ unsigned int sltmp;
+
+ if (prsactx->pad_mode != RSA_PKCS1_PADDING) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
+ "only PKCS#1 padding supported with MDC2");
+ return 0;
+ }
+ ret = RSA_sign_ASN1_OCTET_STRING(0, tbs, tbslen, sig, &sltmp,
+ prsactx->rsa);
+
+ if (ret <= 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
+ return 0;
+ }
+ ret = sltmp;
+ goto end;
+ }
+#endif
+ switch (prsactx->pad_mode) {
+ case RSA_X931_PADDING:
+ if ((size_t)RSA_size(prsactx->rsa) < tbslen + 1) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL,
+ "RSA key size = %d, expected minimum = %d",
+ RSA_size(prsactx->rsa), tbslen + 1);
+ return 0;
+ }
+ if (!setup_tbuf(prsactx)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ memcpy(prsactx->tbuf, tbs, tbslen);
+ prsactx->tbuf[tbslen] = RSA_X931_hash_id(prsactx->mdnid);
+ ret = RSA_private_encrypt(tbslen + 1, prsactx->tbuf,
+ sig, prsactx->rsa, RSA_X931_PADDING);
+ clean_tbuf(prsactx);
+ break;
+
+ case RSA_PKCS1_PADDING:
+ {
+ unsigned int sltmp;
+
+ ret = RSA_sign(prsactx->mdnid, tbs, tbslen, sig, &sltmp,
+ prsactx->rsa);
+ if (ret <= 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
+ return 0;
+ }
+ ret = sltmp;
+ }
+ break;
+
+ case RSA_PKCS1_PSS_PADDING:
+ /* Check PSS restrictions */
+ if (rsa_pss_restricted(prsactx)) {
+ switch (prsactx->saltlen) {
+ case RSA_PSS_SALTLEN_DIGEST:
+ if (prsactx->min_saltlen > EVP_MD_get_size(prsactx->md)) {
+ ERR_raise_data(ERR_LIB_PROV,
+ PROV_R_PSS_SALTLEN_TOO_SMALL,
+ "minimum salt length set to %d, "
+ "but the digest only gives %d",
+ prsactx->min_saltlen,
+ EVP_MD_get_size(prsactx->md));
+ return 0;
+ }
+ /* FALLTHRU */
+ default:
+ if (prsactx->saltlen >= 0
+ && prsactx->saltlen < prsactx->min_saltlen) {
+ ERR_raise_data(ERR_LIB_PROV,
+ PROV_R_PSS_SALTLEN_TOO_SMALL,
+ "minimum salt length set to %d, but the"
+ "actual salt length is only set to %d",
+ prsactx->min_saltlen,
+ prsactx->saltlen);
+ return 0;
+ }
+ break;
+ }
+ }
+ if (!setup_tbuf(prsactx))
+ return 0;
+ if (!RSA_padding_add_PKCS1_PSS_mgf1(prsactx->rsa,
+ prsactx->tbuf, tbs,
+ prsactx->md, prsactx->mgf1_md,
+ prsactx->saltlen)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
+ return 0;
+ }
+ ret = RSA_private_encrypt(RSA_size(prsactx->rsa), prsactx->tbuf,
+ sig, prsactx->rsa, RSA_NO_PADDING);
+ clean_tbuf(prsactx);
+ break;
+
+ default:
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
+ "Only X.931, PKCS#1 v1.5 or PSS padding allowed");
+ return 0;
+ }
+ } else {
+ ret = RSA_private_encrypt(tbslen, tbs, sig, prsactx->rsa,
+ prsactx->pad_mode);
+ }
+
+#ifndef FIPS_MODULE
+ end:
+#endif
+ if (ret <= 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
+ return 0;
+ }
+
+ *siglen = ret;
+ return 1;
+}
+
+static int rsa_verify_recover_init(void *vprsactx, void *vrsa,
+ const OSSL_PARAM params[])
+{
+ if (!ossl_prov_is_running())
+ return 0;
+ return rsa_signverify_init(vprsactx, vrsa, params,
+ EVP_PKEY_OP_VERIFYRECOVER);
+}
+
+static int rsa_verify_recover(void *vprsactx,
+ unsigned char *rout,
+ size_t *routlen,
+ size_t routsize,
+ const unsigned char *sig,
+ size_t siglen)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ int ret;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (rout == NULL) {
+ *routlen = RSA_size(prsactx->rsa);
+ return 1;
+ }
+
+ if (prsactx->md != NULL) {
+ switch (prsactx->pad_mode) {
+ case RSA_X931_PADDING:
+ if (!setup_tbuf(prsactx))
+ return 0;
+ ret = RSA_public_decrypt(siglen, sig, prsactx->tbuf, prsactx->rsa,
+ RSA_X931_PADDING);
+ if (ret < 1) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
+ return 0;
+ }
+ ret--;
+ if (prsactx->tbuf[ret] != RSA_X931_hash_id(prsactx->mdnid)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
+ return 0;
+ }
+ if (ret != EVP_MD_get_size(prsactx->md)) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH,
+ "Should be %d, but got %d",
+ EVP_MD_get_size(prsactx->md), ret);
+ return 0;
+ }
+
+ *routlen = ret;
+ if (rout != prsactx->tbuf) {
+ if (routsize < (size_t)ret) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL,
+ "buffer size is %d, should be %d",
+ routsize, ret);
+ return 0;
+ }
+ memcpy(rout, prsactx->tbuf, ret);
+ }
+ break;
+
+ case RSA_PKCS1_PADDING:
+ {
+ size_t sltmp;
+
+ ret = ossl_rsa_verify(prsactx->mdnid, NULL, 0, rout, &sltmp,
+ sig, siglen, prsactx->rsa);
+ if (ret <= 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
+ return 0;
+ }
+ ret = sltmp;
+ }
+ break;
+
+ default:
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
+ "Only X.931 or PKCS#1 v1.5 padding allowed");
+ return 0;
+ }
+ } else {
+ ret = RSA_public_decrypt(siglen, sig, rout, prsactx->rsa,
+ prsactx->pad_mode);
+ if (ret < 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
+ return 0;
+ }
+ }
+ *routlen = ret;
+ return 1;
+}
+
+static int rsa_verify_init(void *vprsactx, void *vrsa,
+ const OSSL_PARAM params[])
+{
+ if (!ossl_prov_is_running())
+ return 0;
+ return rsa_signverify_init(vprsactx, vrsa, params, EVP_PKEY_OP_VERIFY);
+}
+
+static int rsa_verify(void *vprsactx, const unsigned char *sig, size_t siglen,
+ const unsigned char *tbs, size_t tbslen)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ size_t rslen;
+
+ if (!ossl_prov_is_running())
+ return 0;
+ if (prsactx->md != NULL) {
+ switch (prsactx->pad_mode) {
+ case RSA_PKCS1_PADDING:
+ if (!RSA_verify(prsactx->mdnid, tbs, tbslen, sig, siglen,
+ prsactx->rsa)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
+ return 0;
+ }
+ return 1;
+ case RSA_X931_PADDING:
+ if (!setup_tbuf(prsactx))
+ return 0;
+ if (rsa_verify_recover(prsactx, prsactx->tbuf, &rslen, 0,
+ sig, siglen) <= 0)
+ return 0;
+ break;
+ case RSA_PKCS1_PSS_PADDING:
+ {
+ int ret;
+ size_t mdsize;
+
+ /*
+ * We need to check this for the RSA_verify_PKCS1_PSS_mgf1()
+ * call
+ */
+ mdsize = rsa_get_md_size(prsactx);
+ if (tbslen != mdsize) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH,
+ "Should be %d, but got %d",
+ mdsize, tbslen);
+ return 0;
+ }
+
+ if (!setup_tbuf(prsactx))
+ return 0;
+ ret = RSA_public_decrypt(siglen, sig, prsactx->tbuf,
+ prsactx->rsa, RSA_NO_PADDING);
+ if (ret <= 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
+ return 0;
+ }
+ ret = RSA_verify_PKCS1_PSS_mgf1(prsactx->rsa, tbs,
+ prsactx->md, prsactx->mgf1_md,
+ prsactx->tbuf,
+ prsactx->saltlen);
+ if (ret <= 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
+ return 0;
+ }
+ return 1;
+ }
+ default:
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
+ "Only X.931, PKCS#1 v1.5 or PSS padding allowed");
+ return 0;
+ }
+ } else {
+ if (!setup_tbuf(prsactx))
+ return 0;
+ rslen = RSA_public_decrypt(siglen, sig, prsactx->tbuf, prsactx->rsa,
+ prsactx->pad_mode);
+ if (rslen == 0) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
+ return 0;
+ }
+ }
+
+ if ((rslen != tbslen) || memcmp(tbs, prsactx->tbuf, rslen))
+ return 0;
+
+ return 1;
+}
+
+static int rsa_digest_signverify_init(void *vprsactx, const char *mdname,
+ void *vrsa, const OSSL_PARAM params[],
+ int operation)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (!rsa_signverify_init(vprsactx, vrsa, params, operation))
+ return 0;
+
+ if (mdname != NULL
+ /* was rsa_setup_md already called in rsa_signverify_init()? */
+ && (mdname[0] == '\0' || OPENSSL_strcasecmp(prsactx->mdname, mdname) != 0)
+ && !rsa_setup_md(prsactx, mdname, prsactx->propq))
+ return 0;
+
+ prsactx->flag_allow_md = 0;
+
+ if (prsactx->mdctx == NULL) {
+ prsactx->mdctx = EVP_MD_CTX_new();
+ if (prsactx->mdctx == NULL)
+ goto error;
+ }
+
+ if (!EVP_DigestInit_ex2(prsactx->mdctx, prsactx->md, params))
+ goto error;
+
+ return 1;
+
+ error:
+ EVP_MD_CTX_free(prsactx->mdctx);
+ prsactx->mdctx = NULL;
+ return 0;
+}
+
+static int rsa_digest_signverify_update(void *vprsactx,
+ const unsigned char *data,
+ size_t datalen)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (prsactx == NULL || prsactx->mdctx == NULL)
+ return 0;
+
+ return EVP_DigestUpdate(prsactx->mdctx, data, datalen);
+}
+
+static int rsa_digest_sign_init(void *vprsactx, const char *mdname,
+ void *vrsa, const OSSL_PARAM params[])
+{
+ if (!ossl_prov_is_running())
+ return 0;
+ return rsa_digest_signverify_init(vprsactx, mdname, vrsa,
+ params, EVP_PKEY_OP_SIGN);
+}
+
+static int rsa_digest_sign_final(void *vprsactx, unsigned char *sig,
+ size_t *siglen, size_t sigsize)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ unsigned int dlen = 0;
+
+ if (!ossl_prov_is_running() || prsactx == NULL)
+ return 0;
+ prsactx->flag_allow_md = 1;
+ if (prsactx->mdctx == NULL)
+ return 0;
+ /*
+ * If sig is NULL then we're just finding out the sig size. Other fields
+ * are ignored. Defer to rsa_sign.
+ */
+ if (sig != NULL) {
+ /*
+ * The digests used here are all known (see rsa_get_md_nid()), so they
+ * should not exceed the internal buffer size of EVP_MAX_MD_SIZE.
+ */
+ if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen))
+ return 0;
+ }
+
+ return rsa_sign(vprsactx, sig, siglen, sigsize, digest, (size_t)dlen);
+}
+
+static int rsa_digest_verify_init(void *vprsactx, const char *mdname,
+ void *vrsa, const OSSL_PARAM params[])
+{
+ if (!ossl_prov_is_running())
+ return 0;
+ return rsa_digest_signverify_init(vprsactx, mdname, vrsa,
+ params, EVP_PKEY_OP_VERIFY);
+}
+
+int rsa_digest_verify_final(void *vprsactx, const unsigned char *sig,
+ size_t siglen)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ unsigned int dlen = 0;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (prsactx == NULL)
+ return 0;
+ prsactx->flag_allow_md = 1;
+ if (prsactx->mdctx == NULL)
+ return 0;
+
+ /*
+ * The digests used here are all known (see rsa_get_md_nid()), so they
+ * should not exceed the internal buffer size of EVP_MAX_MD_SIZE.
+ */
+ if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen))
+ return 0;
+
+ return rsa_verify(vprsactx, sig, siglen, digest, (size_t)dlen);
+}
+
+static void rsa_freectx(void *vprsactx)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (prsactx == NULL)
+ return;
+
+ EVP_MD_CTX_free(prsactx->mdctx);
+ EVP_MD_free(prsactx->md);
+ EVP_MD_free(prsactx->mgf1_md);
+ OPENSSL_free(prsactx->propq);
+ free_tbuf(prsactx);
+ RSA_free(prsactx->rsa);
+
+ OPENSSL_clear_free(prsactx, sizeof(*prsactx));
+}
+
+static void *rsa_dupctx(void *vprsactx)
+{
+ PROV_RSA_CTX *srcctx = (PROV_RSA_CTX *)vprsactx;
+ PROV_RSA_CTX *dstctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+ if (dstctx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ *dstctx = *srcctx;
+ dstctx->rsa = NULL;
+ dstctx->md = NULL;
+ dstctx->mdctx = NULL;
+ dstctx->tbuf = NULL;
+ dstctx->propq = NULL;
+
+ if (srcctx->rsa != NULL && !RSA_up_ref(srcctx->rsa))
+ goto err;
+ dstctx->rsa = srcctx->rsa;
+
+ if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md))
+ goto err;
+ dstctx->md = srcctx->md;
+
+ if (srcctx->mgf1_md != NULL && !EVP_MD_up_ref(srcctx->mgf1_md))
+ goto err;
+ dstctx->mgf1_md = srcctx->mgf1_md;
+
+ if (srcctx->mdctx != NULL) {
+ dstctx->mdctx = EVP_MD_CTX_new();
+ if (dstctx->mdctx == NULL
+ || !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx))
+ goto err;
+ }
+
+ if (srcctx->propq != NULL) {
+ dstctx->propq = OPENSSL_strdup(srcctx->propq);
+ if (dstctx->propq == NULL)
+ goto err;
+ }
+
+ return dstctx;
+ err:
+ rsa_freectx(dstctx);
+ return NULL;
+}
+
+static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ OSSL_PARAM *p;
+
+ if (prsactx == NULL)
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
+ if (p != NULL) {
+ /* The Algorithm Identifier of the combined signature algorithm */
+ unsigned char aid_buf[128];
+ unsigned char *aid;
+ size_t aid_len;
+
+ aid = rsa_generate_signature_aid(prsactx, aid_buf,
+ sizeof(aid_buf), &aid_len);
+ if (aid == NULL || !OSSL_PARAM_set_octet_string(p, aid, aid_len))
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PAD_MODE);
+ if (p != NULL)
+ switch (p->data_type) {
+ case OSSL_PARAM_INTEGER:
+ if (!OSSL_PARAM_set_int(p, prsactx->pad_mode))
+ return 0;
+ break;
+ case OSSL_PARAM_UTF8_STRING:
+ {
+ int i;
+ const char *word = NULL;
+
+ for (i = 0; padding_item[i].id != 0; i++) {
+ if (prsactx->pad_mode == (int)padding_item[i].id) {
+ word = padding_item[i].ptr;
+ break;
+ }
+ }
+
+ if (word != NULL) {
+ if (!OSSL_PARAM_set_utf8_string(p, word))
+ return 0;
+ } else {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ }
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST);
+ if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->mdname))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST);
+ if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->mgf1_mdname))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN);
+ if (p != NULL) {
+ if (p->data_type == OSSL_PARAM_INTEGER) {
+ if (!OSSL_PARAM_set_int(p, prsactx->saltlen))
+ return 0;
+ } else if (p->data_type == OSSL_PARAM_UTF8_STRING) {
+ const char *value = NULL;
+
+ switch (prsactx->saltlen) {
+ case RSA_PSS_SALTLEN_DIGEST:
+ value = OSSL_PKEY_RSA_PSS_SALT_LEN_DIGEST;
+ break;
+ case RSA_PSS_SALTLEN_MAX:
+ value = OSSL_PKEY_RSA_PSS_SALT_LEN_MAX;
+ break;
+ case RSA_PSS_SALTLEN_AUTO:
+ value = OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO;
+ break;
+ default:
+ {
+ int len = BIO_snprintf(p->data, p->data_size, "%d",
+ prsactx->saltlen);
+
+ if (len <= 0)
+ return 0;
+ p->return_size = len;
+ break;
+ }
+ }
+ if (value != NULL
+ && !OSSL_PARAM_set_utf8_string(p, value))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *rsa_gettable_ctx_params(ossl_unused void *vprsactx,
+ ossl_unused void *provctx)
+{
+ return known_gettable_ctx_params;
+}
+
+static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ const OSSL_PARAM *p;
+ int pad_mode;
+ int saltlen;
+ char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = NULL;
+ char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = NULL;
+ char mgf1mdname[OSSL_MAX_NAME_SIZE] = "", *pmgf1mdname = NULL;
+ char mgf1mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmgf1mdprops = NULL;
+
+ if (prsactx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+ pad_mode = prsactx->pad_mode;
+ saltlen = prsactx->saltlen;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST);
+ if (p != NULL) {
+ const OSSL_PARAM *propsp =
+ OSSL_PARAM_locate_const(params,
+ OSSL_SIGNATURE_PARAM_PROPERTIES);
+
+ pmdname = mdname;
+ if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname)))
+ return 0;
+
+ if (propsp != NULL) {
+ pmdprops = mdprops;
+ if (!OSSL_PARAM_get_utf8_string(propsp,
+ &pmdprops, sizeof(mdprops)))
+ return 0;
+ }
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PAD_MODE);
+ if (p != NULL) {
+ const char *err_extra_text = NULL;
+
+ switch (p->data_type) {
+ case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
+ if (!OSSL_PARAM_get_int(p, &pad_mode))
+ return 0;
+ break;
+ case OSSL_PARAM_UTF8_STRING:
+ {
+ int i;
+
+ if (p->data == NULL)
+ return 0;
+
+ for (i = 0; padding_item[i].id != 0; i++) {
+ if (strcmp(p->data, padding_item[i].ptr) == 0) {
+ pad_mode = padding_item[i].id;
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ switch (pad_mode) {
+ case RSA_PKCS1_OAEP_PADDING:
+ /*
+ * OAEP padding is for asymmetric cipher only so is not compatible
+ * with signature use.
+ */
+ err_extra_text = "OAEP padding not allowed for signing / verifying";
+ goto bad_pad;
+ case RSA_PKCS1_PSS_PADDING:
+ if ((prsactx->operation
+ & (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY)) == 0) {
+ err_extra_text =
+ "PSS padding only allowed for sign and verify operations";
+ goto bad_pad;
+ }
+ break;
+ case RSA_PKCS1_PADDING:
+ err_extra_text = "PKCS#1 padding not allowed with RSA-PSS";
+ goto cont;
+ case RSA_NO_PADDING:
+ err_extra_text = "No padding not allowed with RSA-PSS";
+ goto cont;
+ case RSA_X931_PADDING:
+ err_extra_text = "X.931 padding not allowed with RSA-PSS";
+ cont:
+ if (RSA_test_flags(prsactx->rsa,
+ RSA_FLAG_TYPE_MASK) == RSA_FLAG_TYPE_RSA)
+ break;
+ /* FALLTHRU */
+ default:
+ bad_pad:
+ if (err_extra_text == NULL)
+ ERR_raise(ERR_LIB_PROV,
+ PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
+ else
+ ERR_raise_data(ERR_LIB_PROV,
+ PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE,
+ err_extra_text);
+ return 0;
+ }
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN);
+ if (p != NULL) {
+ if (pad_mode != RSA_PKCS1_PSS_PADDING) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED,
+ "PSS saltlen can only be specified if "
+ "PSS padding has been specified first");
+ return 0;
+ }
+
+ switch (p->data_type) {
+ case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
+ if (!OSSL_PARAM_get_int(p, &saltlen))
+ return 0;
+ break;
+ case OSSL_PARAM_UTF8_STRING:
+ if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_DIGEST) == 0)
+ saltlen = RSA_PSS_SALTLEN_DIGEST;
+ else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_MAX) == 0)
+ saltlen = RSA_PSS_SALTLEN_MAX;
+ else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO) == 0)
+ saltlen = RSA_PSS_SALTLEN_AUTO;
+ else
+ saltlen = atoi(p->data);
+ break;
+ default:
+ return 0;
+ }
+
+ /*
+ * RSA_PSS_SALTLEN_MAX seems curiously named in this check.
+ * Contrary to what it's name suggests, it's the currently
+ * lowest saltlen number possible.
+ */
+ if (saltlen < RSA_PSS_SALTLEN_MAX) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH);
+ return 0;
+ }
+
+ if (rsa_pss_restricted(prsactx)) {
+ switch (saltlen) {
+ case RSA_PSS_SALTLEN_AUTO:
+ if (prsactx->operation == EVP_PKEY_OP_VERIFY) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH,
+ "Cannot use autodetected salt length");
+ return 0;
+ }
+ break;
+ case RSA_PSS_SALTLEN_DIGEST:
+ if (prsactx->min_saltlen > EVP_MD_get_size(prsactx->md)) {
+ ERR_raise_data(ERR_LIB_PROV,
+ PROV_R_PSS_SALTLEN_TOO_SMALL,
+ "Should be more than %d, but would be "
+ "set to match digest size (%d)",
+ prsactx->min_saltlen,
+ EVP_MD_get_size(prsactx->md));
+ return 0;
+ }
+ break;
+ default:
+ if (saltlen >= 0 && saltlen < prsactx->min_saltlen) {
+ ERR_raise_data(ERR_LIB_PROV,
+ PROV_R_PSS_SALTLEN_TOO_SMALL,
+ "Should be more than %d, "
+ "but would be set to %d",
+ prsactx->min_saltlen, saltlen);
+ return 0;
+ }
+ }
+ }
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST);
+ if (p != NULL) {
+ const OSSL_PARAM *propsp =
+ OSSL_PARAM_locate_const(params,
+ OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES);
+
+ pmgf1mdname = mgf1mdname;
+ if (!OSSL_PARAM_get_utf8_string(p, &pmgf1mdname, sizeof(mgf1mdname)))
+ return 0;
+
+ if (propsp != NULL) {
+ pmgf1mdprops = mgf1mdprops;
+ if (!OSSL_PARAM_get_utf8_string(propsp,
+ &pmgf1mdprops, sizeof(mgf1mdprops)))
+ return 0;
+ }
+
+ if (pad_mode != RSA_PKCS1_PSS_PADDING) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MGF1_MD);
+ return 0;
+ }
+ }
+
+ prsactx->saltlen = saltlen;
+ prsactx->pad_mode = pad_mode;
+
+ if (prsactx->md == NULL && pmdname == NULL
+ && pad_mode == RSA_PKCS1_PSS_PADDING)
+ pmdname = RSA_DEFAULT_DIGEST_NAME;
+
+ if (pmgf1mdname != NULL
+ && !rsa_setup_mgf1_md(prsactx, pmgf1mdname, pmgf1mdprops))
+ return 0;
+
+ if (pmdname != NULL) {
+ if (!rsa_setup_md(prsactx, pmdname, pmdprops))
+ return 0;
+ } else {
+ if (!rsa_check_padding(prsactx, NULL, NULL, prsactx->mdnid))
+ return 0;
+ }
+ return 1;
+}
+
+static const OSSL_PARAM settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM settable_ctx_params_no_digest[] = {
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *rsa_settable_ctx_params(void *vprsactx,
+ ossl_unused void *provctx)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (prsactx != NULL && !prsactx->flag_allow_md)
+ return settable_ctx_params_no_digest;
+ return settable_ctx_params;
+}
+
+static int rsa_get_ctx_md_params(void *vprsactx, OSSL_PARAM *params)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (prsactx->mdctx == NULL)
+ return 0;
+
+ return EVP_MD_CTX_get_params(prsactx->mdctx, params);
+}
+
+static const OSSL_PARAM *rsa_gettable_ctx_md_params(void *vprsactx)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (prsactx->md == NULL)
+ return 0;
+
+ return EVP_MD_gettable_ctx_params(prsactx->md);
+}
+
+static int rsa_set_ctx_md_params(void *vprsactx, const OSSL_PARAM params[])
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (prsactx->mdctx == NULL)
+ return 0;
+
+ return EVP_MD_CTX_set_params(prsactx->mdctx, params);
+}
+
+static const OSSL_PARAM *rsa_settable_ctx_md_params(void *vprsactx)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (prsactx->md == NULL)
+ return 0;
+
+ return EVP_MD_settable_ctx_params(prsactx->md);
+}
+
+const OSSL_DISPATCH ossl_rsa_signature_functions[] = {
+ { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))rsa_newctx },
+ { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))rsa_sign_init },
+ { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))rsa_sign },
+ { OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))rsa_verify_init },
+ { OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))rsa_verify },
+ { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT,
+ (void (*)(void))rsa_verify_recover_init },
+ { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER,
+ (void (*)(void))rsa_verify_recover },
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
+ (void (*)(void))rsa_digest_sign_init },
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
+ (void (*)(void))rsa_digest_signverify_update },
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
+ (void (*)(void))rsa_digest_sign_final },
+ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
+ (void (*)(void))rsa_digest_verify_init },
+ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
+ (void (*)(void))rsa_digest_signverify_update },
+ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
+ (void (*)(void))rsa_digest_verify_final },
+ { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))rsa_freectx },
+ { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))rsa_dupctx },
+ { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))rsa_get_ctx_params },
+ { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
+ (void (*)(void))rsa_gettable_ctx_params },
+ { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))rsa_set_ctx_params },
+ { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
+ (void (*)(void))rsa_settable_ctx_params },
+ { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS,
+ (void (*)(void))rsa_get_ctx_md_params },
+ { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS,
+ (void (*)(void))rsa_gettable_ctx_md_params },
+ { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS,
+ (void (*)(void))rsa_set_ctx_md_params },
+ { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS,
+ (void (*)(void))rsa_settable_ctx_md_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/signature/sm2_sig.c b/providers/implementations/signature/sm2_sig.c
new file mode 100644
index 000000000000..fffb280c776a
--- /dev/null
+++ b/providers/implementations/signature/sm2_sig.c
@@ -0,0 +1,564 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use - SM2 implemetation uses ECDSA_size() function.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h> /* memcpy */
+#include <openssl/crypto.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/dsa.h>
+#include <openssl/params.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+#include "internal/nelem.h"
+#include "internal/sizes.h"
+#include "internal/cryptlib.h"
+#include "internal/sm3.h"
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+#include "prov/provider_ctx.h"
+#include "crypto/ec.h"
+#include "crypto/sm2.h"
+#include "prov/der_sm2.h"
+
+static OSSL_FUNC_signature_newctx_fn sm2sig_newctx;
+static OSSL_FUNC_signature_sign_init_fn sm2sig_signature_init;
+static OSSL_FUNC_signature_verify_init_fn sm2sig_signature_init;
+static OSSL_FUNC_signature_sign_fn sm2sig_sign;
+static OSSL_FUNC_signature_verify_fn sm2sig_verify;
+static OSSL_FUNC_signature_digest_sign_init_fn sm2sig_digest_signverify_init;
+static OSSL_FUNC_signature_digest_sign_update_fn sm2sig_digest_signverify_update;
+static OSSL_FUNC_signature_digest_sign_final_fn sm2sig_digest_sign_final;
+static OSSL_FUNC_signature_digest_verify_init_fn sm2sig_digest_signverify_init;
+static OSSL_FUNC_signature_digest_verify_update_fn sm2sig_digest_signverify_update;
+static OSSL_FUNC_signature_digest_verify_final_fn sm2sig_digest_verify_final;
+static OSSL_FUNC_signature_freectx_fn sm2sig_freectx;
+static OSSL_FUNC_signature_dupctx_fn sm2sig_dupctx;
+static OSSL_FUNC_signature_get_ctx_params_fn sm2sig_get_ctx_params;
+static OSSL_FUNC_signature_gettable_ctx_params_fn sm2sig_gettable_ctx_params;
+static OSSL_FUNC_signature_set_ctx_params_fn sm2sig_set_ctx_params;
+static OSSL_FUNC_signature_settable_ctx_params_fn sm2sig_settable_ctx_params;
+static OSSL_FUNC_signature_get_ctx_md_params_fn sm2sig_get_ctx_md_params;
+static OSSL_FUNC_signature_gettable_ctx_md_params_fn sm2sig_gettable_ctx_md_params;
+static OSSL_FUNC_signature_set_ctx_md_params_fn sm2sig_set_ctx_md_params;
+static OSSL_FUNC_signature_settable_ctx_md_params_fn sm2sig_settable_ctx_md_params;
+
+/*
+ * What's passed as an actual key is defined by the KEYMGMT interface.
+ * We happen to know that our KEYMGMT simply passes EC structures, so
+ * we use that here too.
+ */
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+ EC_KEY *ec;
+
+ /*
+ * Flag to termine if the 'z' digest needs to be computed and fed to the
+ * hash function.
+ * This flag should be set on initialization and the compuation should
+ * be performed only once, on first update.
+ */
+ unsigned int flag_compute_z_digest : 1;
+
+ char mdname[OSSL_MAX_NAME_SIZE];
+
+ /* The Algorithm Identifier of the combined signature algorithm */
+ unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];
+ unsigned char *aid;
+ size_t aid_len;
+
+ /* main digest */
+ EVP_MD *md;
+ EVP_MD_CTX *mdctx;
+ size_t mdsize;
+
+ /* SM2 ID used for calculating the Z value */
+ unsigned char *id;
+ size_t id_len;
+} PROV_SM2_CTX;
+
+static int sm2sig_set_mdname(PROV_SM2_CTX *psm2ctx, const char *mdname)
+{
+ if (psm2ctx->md == NULL) /* We need an SM3 md to compare with */
+ psm2ctx->md = EVP_MD_fetch(psm2ctx->libctx, psm2ctx->mdname,
+ psm2ctx->propq);
+ if (psm2ctx->md == NULL)
+ return 0;
+
+ if (mdname == NULL)
+ return 1;
+
+ if (strlen(mdname) >= sizeof(psm2ctx->mdname)
+ || !EVP_MD_is_a(psm2ctx->md, mdname)) {
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST, "digest=%s",
+ mdname);
+ return 0;
+ }
+
+ OPENSSL_strlcpy(psm2ctx->mdname, mdname, sizeof(psm2ctx->mdname));
+ return 1;
+}
+
+static void *sm2sig_newctx(void *provctx, const char *propq)
+{
+ PROV_SM2_CTX *ctx = OPENSSL_zalloc(sizeof(PROV_SM2_CTX));
+
+ if (ctx == NULL)
+ return NULL;
+
+ ctx->libctx = PROV_LIBCTX_OF(provctx);
+ if (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL) {
+ OPENSSL_free(ctx);
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ ctx->mdsize = SM3_DIGEST_LENGTH;
+ strcpy(ctx->mdname, OSSL_DIGEST_NAME_SM3);
+ return ctx;
+}
+
+static int sm2sig_signature_init(void *vpsm2ctx, void *ec,
+ const OSSL_PARAM params[])
+{
+ PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
+
+ if (!ossl_prov_is_running()
+ || psm2ctx == NULL)
+ return 0;
+
+ if (ec == NULL && psm2ctx->ec == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
+ return 0;
+ }
+
+ if (ec != NULL) {
+ if (!EC_KEY_up_ref(ec))
+ return 0;
+ EC_KEY_free(psm2ctx->ec);
+ psm2ctx->ec = ec;
+ }
+
+ return sm2sig_set_ctx_params(psm2ctx, params);
+}
+
+static int sm2sig_sign(void *vpsm2ctx, unsigned char *sig, size_t *siglen,
+ size_t sigsize, const unsigned char *tbs, size_t tbslen)
+{
+ PROV_SM2_CTX *ctx = (PROV_SM2_CTX *)vpsm2ctx;
+ int ret;
+ unsigned int sltmp;
+ /* SM2 uses ECDSA_size as well */
+ size_t ecsize = ECDSA_size(ctx->ec);
+
+ if (sig == NULL) {
+ *siglen = ecsize;
+ return 1;
+ }
+
+ if (sigsize < (size_t)ecsize)
+ return 0;
+
+ if (ctx->mdsize != 0 && tbslen != ctx->mdsize)
+ return 0;
+
+ ret = ossl_sm2_internal_sign(tbs, tbslen, sig, &sltmp, ctx->ec);
+ if (ret <= 0)
+ return 0;
+
+ *siglen = sltmp;
+ return 1;
+}
+
+static int sm2sig_verify(void *vpsm2ctx, const unsigned char *sig, size_t siglen,
+ const unsigned char *tbs, size_t tbslen)
+{
+ PROV_SM2_CTX *ctx = (PROV_SM2_CTX *)vpsm2ctx;
+
+ if (ctx->mdsize != 0 && tbslen != ctx->mdsize)
+ return 0;
+
+ return ossl_sm2_internal_verify(tbs, tbslen, sig, siglen, ctx->ec);
+}
+
+static void free_md(PROV_SM2_CTX *ctx)
+{
+ EVP_MD_CTX_free(ctx->mdctx);
+ EVP_MD_free(ctx->md);
+ ctx->mdctx = NULL;
+ ctx->md = NULL;
+}
+
+static int sm2sig_digest_signverify_init(void *vpsm2ctx, const char *mdname,
+ void *ec, const OSSL_PARAM params[])
+{
+ PROV_SM2_CTX *ctx = (PROV_SM2_CTX *)vpsm2ctx;
+ int md_nid;
+ WPACKET pkt;
+ int ret = 0;
+
+ if (!sm2sig_signature_init(vpsm2ctx, ec, params)
+ || !sm2sig_set_mdname(ctx, mdname))
+ return ret;
+
+ if (ctx->mdctx == NULL) {
+ ctx->mdctx = EVP_MD_CTX_new();
+ if (ctx->mdctx == NULL)
+ goto error;
+ }
+
+ md_nid = EVP_MD_get_type(ctx->md);
+
+ /*
+ * We do not care about DER writing errors.
+ * All it really means is that for some reason, there's no
+ * AlgorithmIdentifier to be had, but the operation itself is
+ * still valid, just as long as it's not used to construct
+ * anything that needs an AlgorithmIdentifier.
+ */
+ ctx->aid_len = 0;
+ if (WPACKET_init_der(&pkt, ctx->aid_buf, sizeof(ctx->aid_buf))
+ && ossl_DER_w_algorithmIdentifier_SM2_with_MD(&pkt, -1, ctx->ec, md_nid)
+ && WPACKET_finish(&pkt)) {
+ WPACKET_get_total_written(&pkt, &ctx->aid_len);
+ ctx->aid = WPACKET_get_curr(&pkt);
+ }
+ WPACKET_cleanup(&pkt);
+
+ if (!EVP_DigestInit_ex2(ctx->mdctx, ctx->md, params))
+ goto error;
+
+ ctx->flag_compute_z_digest = 1;
+
+ ret = 1;
+
+ error:
+ return ret;
+}
+
+static int sm2sig_compute_z_digest(PROV_SM2_CTX *ctx)
+{
+ uint8_t *z = NULL;
+ int ret = 1;
+
+ if (ctx->flag_compute_z_digest) {
+ /* Only do this once */
+ ctx->flag_compute_z_digest = 0;
+
+ if ((z = OPENSSL_zalloc(ctx->mdsize)) == NULL
+ /* get hashed prefix 'z' of tbs message */
+ || !ossl_sm2_compute_z_digest(z, ctx->md, ctx->id, ctx->id_len,
+ ctx->ec)
+ || !EVP_DigestUpdate(ctx->mdctx, z, ctx->mdsize))
+ ret = 0;
+ OPENSSL_free(z);
+ }
+
+ return ret;
+}
+
+int sm2sig_digest_signverify_update(void *vpsm2ctx, const unsigned char *data,
+ size_t datalen)
+{
+ PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
+
+ if (psm2ctx == NULL || psm2ctx->mdctx == NULL)
+ return 0;
+
+ return sm2sig_compute_z_digest(psm2ctx)
+ && EVP_DigestUpdate(psm2ctx->mdctx, data, datalen);
+}
+
+int sm2sig_digest_sign_final(void *vpsm2ctx, unsigned char *sig, size_t *siglen,
+ size_t sigsize)
+{
+ PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ unsigned int dlen = 0;
+
+ if (psm2ctx == NULL || psm2ctx->mdctx == NULL)
+ return 0;
+
+ /*
+ * If sig is NULL then we're just finding out the sig size. Other fields
+ * are ignored. Defer to sm2sig_sign.
+ */
+ if (sig != NULL) {
+ if (!(sm2sig_compute_z_digest(psm2ctx)
+ && EVP_DigestFinal_ex(psm2ctx->mdctx, digest, &dlen)))
+ return 0;
+ }
+
+ return sm2sig_sign(vpsm2ctx, sig, siglen, sigsize, digest, (size_t)dlen);
+}
+
+
+int sm2sig_digest_verify_final(void *vpsm2ctx, const unsigned char *sig,
+ size_t siglen)
+{
+ PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ unsigned int dlen = 0;
+
+ if (psm2ctx == NULL
+ || psm2ctx->mdctx == NULL
+ || EVP_MD_get_size(psm2ctx->md) > (int)sizeof(digest))
+ return 0;
+
+ if (!(sm2sig_compute_z_digest(psm2ctx)
+ && EVP_DigestFinal_ex(psm2ctx->mdctx, digest, &dlen)))
+ return 0;
+
+ return sm2sig_verify(vpsm2ctx, sig, siglen, digest, (size_t)dlen);
+}
+
+static void sm2sig_freectx(void *vpsm2ctx)
+{
+ PROV_SM2_CTX *ctx = (PROV_SM2_CTX *)vpsm2ctx;
+
+ free_md(ctx);
+ EC_KEY_free(ctx->ec);
+ OPENSSL_free(ctx->id);
+ OPENSSL_free(ctx);
+}
+
+static void *sm2sig_dupctx(void *vpsm2ctx)
+{
+ PROV_SM2_CTX *srcctx = (PROV_SM2_CTX *)vpsm2ctx;
+ PROV_SM2_CTX *dstctx;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+ if (dstctx == NULL)
+ return NULL;
+
+ *dstctx = *srcctx;
+ dstctx->ec = NULL;
+ dstctx->md = NULL;
+ dstctx->mdctx = NULL;
+
+ if (srcctx->ec != NULL && !EC_KEY_up_ref(srcctx->ec))
+ goto err;
+ dstctx->ec = srcctx->ec;
+
+ if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md))
+ goto err;
+ dstctx->md = srcctx->md;
+
+ if (srcctx->mdctx != NULL) {
+ dstctx->mdctx = EVP_MD_CTX_new();
+ if (dstctx->mdctx == NULL
+ || !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx))
+ goto err;
+ }
+
+ if (srcctx->id != NULL) {
+ dstctx->id = OPENSSL_malloc(srcctx->id_len);
+ if (dstctx->id == NULL)
+ goto err;
+ dstctx->id_len = srcctx->id_len;
+ memcpy(dstctx->id, srcctx->id, srcctx->id_len);
+ }
+
+ return dstctx;
+ err:
+ sm2sig_freectx(dstctx);
+ return NULL;
+}
+
+static int sm2sig_get_ctx_params(void *vpsm2ctx, OSSL_PARAM *params)
+{
+ PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
+ OSSL_PARAM *p;
+
+ if (psm2ctx == NULL)
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
+ if (p != NULL
+ && !OSSL_PARAM_set_octet_string(p, psm2ctx->aid, psm2ctx->aid_len))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, psm2ctx->mdsize))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST);
+ if (p != NULL && !OSSL_PARAM_set_utf8_string(p, psm2ctx->md == NULL
+ ? psm2ctx->mdname
+ : EVP_MD_get0_name(psm2ctx->md)))
+ return 0;
+
+ return 1;
+}
+
+static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
+ OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *sm2sig_gettable_ctx_params(ossl_unused void *vpsm2ctx,
+ ossl_unused void *provctx)
+{
+ return known_gettable_ctx_params;
+}
+
+static int sm2sig_set_ctx_params(void *vpsm2ctx, const OSSL_PARAM params[])
+{
+ PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
+ const OSSL_PARAM *p;
+ size_t mdsize;
+
+ if (psm2ctx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DIST_ID);
+ if (p != NULL) {
+ void *tmp_id = NULL;
+ size_t tmp_idlen = 0;
+
+ /*
+ * If the 'z' digest has already been computed, the ID is set too late
+ */
+ if (!psm2ctx->flag_compute_z_digest)
+ return 0;
+
+ if (p->data_size != 0
+ && !OSSL_PARAM_get_octet_string(p, &tmp_id, 0, &tmp_idlen))
+ return 0;
+ OPENSSL_free(psm2ctx->id);
+ psm2ctx->id = tmp_id;
+ psm2ctx->id_len = tmp_idlen;
+ }
+
+ /*
+ * The following code checks that the size is the same as the SM3 digest
+ * size returning an error otherwise.
+ * If there is ever any different digest algorithm allowed with SM2
+ * this needs to be adjusted accordingly.
+ */
+ p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
+ if (p != NULL && (!OSSL_PARAM_get_size_t(p, &mdsize)
+ || mdsize != psm2ctx->mdsize))
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST);
+ if (p != NULL) {
+ char *mdname = NULL;
+
+ if (!OSSL_PARAM_get_utf8_string(p, &mdname, 0))
+ return 0;
+ if (!sm2sig_set_mdname(psm2ctx, mdname)) {
+ OPENSSL_free(mdname);
+ return 0;
+ }
+ OPENSSL_free(mdname);
+ }
+
+ return 1;
+}
+
+static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
+ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_DIST_ID, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *sm2sig_settable_ctx_params(ossl_unused void *vpsm2ctx,
+ ossl_unused void *provctx)
+{
+ return known_settable_ctx_params;
+}
+
+static int sm2sig_get_ctx_md_params(void *vpsm2ctx, OSSL_PARAM *params)
+{
+ PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
+
+ if (psm2ctx->mdctx == NULL)
+ return 0;
+
+ return EVP_MD_CTX_get_params(psm2ctx->mdctx, params);
+}
+
+static const OSSL_PARAM *sm2sig_gettable_ctx_md_params(void *vpsm2ctx)
+{
+ PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
+
+ if (psm2ctx->md == NULL)
+ return 0;
+
+ return EVP_MD_gettable_ctx_params(psm2ctx->md);
+}
+
+static int sm2sig_set_ctx_md_params(void *vpsm2ctx, const OSSL_PARAM params[])
+{
+ PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
+
+ if (psm2ctx->mdctx == NULL)
+ return 0;
+
+ return EVP_MD_CTX_set_params(psm2ctx->mdctx, params);
+}
+
+static const OSSL_PARAM *sm2sig_settable_ctx_md_params(void *vpsm2ctx)
+{
+ PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
+
+ if (psm2ctx->md == NULL)
+ return 0;
+
+ return EVP_MD_settable_ctx_params(psm2ctx->md);
+}
+
+const OSSL_DISPATCH ossl_sm2_signature_functions[] = {
+ { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))sm2sig_newctx },
+ { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))sm2sig_signature_init },
+ { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))sm2sig_sign },
+ { OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))sm2sig_signature_init },
+ { OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))sm2sig_verify },
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
+ (void (*)(void))sm2sig_digest_signverify_init },
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
+ (void (*)(void))sm2sig_digest_signverify_update },
+ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
+ (void (*)(void))sm2sig_digest_sign_final },
+ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
+ (void (*)(void))sm2sig_digest_signverify_init },
+ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
+ (void (*)(void))sm2sig_digest_signverify_update },
+ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
+ (void (*)(void))sm2sig_digest_verify_final },
+ { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))sm2sig_freectx },
+ { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))sm2sig_dupctx },
+ { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))sm2sig_get_ctx_params },
+ { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
+ (void (*)(void))sm2sig_gettable_ctx_params },
+ { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))sm2sig_set_ctx_params },
+ { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
+ (void (*)(void))sm2sig_settable_ctx_params },
+ { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS,
+ (void (*)(void))sm2sig_get_ctx_md_params },
+ { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS,
+ (void (*)(void))sm2sig_gettable_ctx_md_params },
+ { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS,
+ (void (*)(void))sm2sig_set_ctx_md_params },
+ { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS,
+ (void (*)(void))sm2sig_settable_ctx_md_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/storemgmt/build.info b/providers/implementations/storemgmt/build.info
new file mode 100644
index 000000000000..8e6445a4e7cf
--- /dev/null
+++ b/providers/implementations/storemgmt/build.info
@@ -0,0 +1,6 @@
+# We make separate GOAL variables for each algorithm, to make it easy to
+# switch each to the Legacy provider when needed.
+
+$STORE_GOAL=../../libdefault.a
+
+SOURCE[$STORE_GOAL]=file_store.c file_store_any2obj.c
diff --git a/providers/implementations/storemgmt/file_store.c b/providers/implementations/storemgmt/file_store.c
new file mode 100644
index 000000000000..6d6312659bea
--- /dev/null
+++ b/providers/implementations/storemgmt/file_store.c
@@ -0,0 +1,790 @@
+/*
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* This file has quite some overlap with engines/e_loader_attic.c */
+
+#include <string.h>
+#include <sys/stat.h>
+#include <ctype.h> /* isdigit */
+#include <assert.h>
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/core_object.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/params.h>
+#include <openssl/decoder.h>
+#include <openssl/proverr.h>
+#include <openssl/store.h> /* The OSSL_STORE_INFO type numbers */
+#include "internal/cryptlib.h"
+#include "internal/o_dir.h"
+#include "crypto/decoder.h"
+#include "crypto/ctype.h" /* ossl_isdigit() */
+#include "prov/implementations.h"
+#include "prov/bio.h"
+#include "file_store_local.h"
+
+DEFINE_STACK_OF(OSSL_STORE_INFO)
+
+#ifdef _WIN32
+# define stat _stat
+#endif
+
+#ifndef S_ISDIR
+# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
+#endif
+
+static OSSL_FUNC_store_open_fn file_open;
+static OSSL_FUNC_store_attach_fn file_attach;
+static OSSL_FUNC_store_settable_ctx_params_fn file_settable_ctx_params;
+static OSSL_FUNC_store_set_ctx_params_fn file_set_ctx_params;
+static OSSL_FUNC_store_load_fn file_load;
+static OSSL_FUNC_store_eof_fn file_eof;
+static OSSL_FUNC_store_close_fn file_close;
+
+/*
+ * This implementation makes full use of OSSL_DECODER, and then some.
+ * It uses its own internal decoder implementation that reads DER and
+ * passes that on to the data callback; this decoder is created with
+ * internal OpenSSL functions, thereby bypassing the need for a surrounding
+ * provider. This is ok, since this is a local decoder, not meant for
+ * public consumption. It also uses the libcrypto internal decoder
+ * setup function ossl_decoder_ctx_setup_for_pkey(), to allow the
+ * last resort decoder to be added first (and thereby be executed last).
+ * Finally, it sets up its own construct and cleanup functions.
+ *
+ * Essentially, that makes this implementation a kind of glorified decoder.
+ */
+
+struct file_ctx_st {
+ void *provctx;
+ char *uri; /* The URI we currently try to load */
+ enum {
+ IS_FILE = 0, /* Read file and pass results */
+ IS_DIR /* Pass directory entry names */
+ } type;
+
+ union {
+ /* Used with |IS_FILE| */
+ struct {
+ BIO *file;
+
+ OSSL_DECODER_CTX *decoderctx;
+ char *input_type;
+ char *propq; /* The properties we got as a parameter */
+ } file;
+
+ /* Used with |IS_DIR| */
+ struct {
+ OPENSSL_DIR_CTX *ctx;
+ int end_reached;
+
+ /*
+ * When a search expression is given, these are filled in.
+ * |search_name| contains the file basename to look for.
+ * The string is exactly 8 characters long.
+ */
+ char search_name[9];
+
+ /*
+ * The directory reading utility we have combines opening with
+ * reading the first name. To make sure we can detect the end
+ * at the right time, we read early and cache the name.
+ */
+ const char *last_entry;
+ int last_errno;
+ } dir;
+ } _;
+
+ /* Expected object type. May be unspecified */
+ int expected_type;
+};
+
+static void free_file_ctx(struct file_ctx_st *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ OPENSSL_free(ctx->uri);
+ if (ctx->type != IS_DIR) {
+ OSSL_DECODER_CTX_free(ctx->_.file.decoderctx);
+ OPENSSL_free(ctx->_.file.propq);
+ OPENSSL_free(ctx->_.file.input_type);
+ }
+ OPENSSL_free(ctx);
+}
+
+static struct file_ctx_st *new_file_ctx(int type, const char *uri,
+ void *provctx)
+{
+ struct file_ctx_st *ctx = NULL;
+
+ if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) != NULL
+ && (uri == NULL || (ctx->uri = OPENSSL_strdup(uri)) != NULL)) {
+ ctx->type = type;
+ ctx->provctx = provctx;
+ return ctx;
+ }
+ free_file_ctx(ctx);
+ return NULL;
+}
+
+static OSSL_DECODER_CONSTRUCT file_load_construct;
+static OSSL_DECODER_CLEANUP file_load_cleanup;
+
+/*-
+ * Opening / attaching streams and directories
+ * -------------------------------------------
+ */
+
+/*
+ * Function to service both file_open() and file_attach()
+ *
+ *
+ */
+static struct file_ctx_st *file_open_stream(BIO *source, const char *uri,
+ void *provctx)
+{
+ struct file_ctx_st *ctx;
+
+ if ((ctx = new_file_ctx(IS_FILE, uri, provctx)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ ctx->_.file.file = source;
+
+ return ctx;
+ err:
+ free_file_ctx(ctx);
+ return NULL;
+}
+
+static void *file_open_dir(const char *path, const char *uri, void *provctx)
+{
+ struct file_ctx_st *ctx;
+
+ if ((ctx = new_file_ctx(IS_DIR, uri, provctx)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx, path);
+ ctx->_.dir.last_errno = errno;
+ if (ctx->_.dir.last_entry == NULL) {
+ if (ctx->_.dir.last_errno != 0) {
+ ERR_raise_data(ERR_LIB_SYS, ctx->_.dir.last_errno,
+ "Calling OPENSSL_DIR_read(\"%s\")", path);
+ goto err;
+ }
+ ctx->_.dir.end_reached = 1;
+ }
+ return ctx;
+ err:
+ file_close(ctx);
+ return NULL;
+}
+
+static void *file_open(void *provctx, const char *uri)
+{
+ struct file_ctx_st *ctx = NULL;
+ struct stat st;
+ struct {
+ const char *path;
+ unsigned int check_absolute:1;
+ } path_data[2];
+ size_t path_data_n = 0, i;
+ const char *path;
+ BIO *bio;
+
+ ERR_set_mark();
+
+ /*
+ * First step, just take the URI as is.
+ */
+ path_data[path_data_n].check_absolute = 0;
+ path_data[path_data_n++].path = uri;
+
+ /*
+ * Second step, if the URI appears to start with the 'file' scheme,
+ * extract the path and make that the second path to check.
+ * There's a special case if the URI also contains an authority, then
+ * the full URI shouldn't be used as a path anywhere.
+ */
+ if (OPENSSL_strncasecmp(uri, "file:", 5) == 0) {
+ const char *p = &uri[5];
+
+ if (strncmp(&uri[5], "//", 2) == 0) {
+ path_data_n--; /* Invalidate using the full URI */
+ if (OPENSSL_strncasecmp(&uri[7], "localhost/", 10) == 0) {
+ p = &uri[16];
+ } else if (uri[7] == '/') {
+ p = &uri[7];
+ } else {
+ ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_PROV, PROV_R_URI_AUTHORITY_UNSUPPORTED);
+ return NULL;
+ }
+ }
+
+ path_data[path_data_n].check_absolute = 1;
+#ifdef _WIN32
+ /* Windows file: URIs with a drive letter start with a / */
+ if (p[0] == '/' && p[2] == ':' && p[3] == '/') {
+ char c = tolower(p[1]);
+
+ if (c >= 'a' && c <= 'z') {
+ p++;
+ /* We know it's absolute, so no need to check */
+ path_data[path_data_n].check_absolute = 0;
+ }
+ }
+#endif
+ path_data[path_data_n++].path = p;
+ }
+
+
+ for (i = 0, path = NULL; path == NULL && i < path_data_n; i++) {
+ /*
+ * If the scheme "file" was an explicit part of the URI, the path must
+ * be absolute. So says RFC 8089
+ */
+ if (path_data[i].check_absolute && path_data[i].path[0] != '/') {
+ ERR_clear_last_mark();
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_PATH_MUST_BE_ABSOLUTE,
+ "Given path=%s", path_data[i].path);
+ return NULL;
+ }
+
+ if (stat(path_data[i].path, &st) < 0) {
+ ERR_raise_data(ERR_LIB_SYS, errno,
+ "calling stat(%s)",
+ path_data[i].path);
+ } else {
+ path = path_data[i].path;
+ }
+ }
+ if (path == NULL) {
+ ERR_clear_last_mark();
+ return NULL;
+ }
+
+ /* Successfully found a working path, clear possible collected errors */
+ ERR_pop_to_mark();
+
+ if (S_ISDIR(st.st_mode))
+ ctx = file_open_dir(path, uri, provctx);
+ else if ((bio = BIO_new_file(path, "rb")) == NULL
+ || (ctx = file_open_stream(bio, uri, provctx)) == NULL)
+ BIO_free_all(bio);
+
+ return ctx;
+}
+
+void *file_attach(void *provctx, OSSL_CORE_BIO *cin)
+{
+ struct file_ctx_st *ctx;
+ BIO *new_bio = ossl_bio_new_from_core_bio(provctx, cin);
+
+ if (new_bio == NULL)
+ return NULL;
+
+ ctx = file_open_stream(new_bio, NULL, provctx);
+ if (ctx == NULL)
+ BIO_free(new_bio);
+ return ctx;
+}
+
+/*-
+ * Setting parameters
+ * ------------------
+ */
+
+static const OSSL_PARAM *file_settable_ctx_params(void *provctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_STORE_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_int(OSSL_STORE_PARAM_EXPECT, NULL),
+ OSSL_PARAM_octet_string(OSSL_STORE_PARAM_SUBJECT, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_STORE_PARAM_INPUT_TYPE, NULL, 0),
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+static int file_set_ctx_params(void *loaderctx, const OSSL_PARAM params[])
+{
+ struct file_ctx_st *ctx = loaderctx;
+ const OSSL_PARAM *p;
+
+ if (params == NULL)
+ return 1;
+
+ if (ctx->type != IS_DIR) {
+ /* these parameters are ignored for directories */
+ p = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_PROPERTIES);
+ if (p != NULL) {
+ OPENSSL_free(ctx->_.file.propq);
+ ctx->_.file.propq = NULL;
+ if (!OSSL_PARAM_get_utf8_string(p, &ctx->_.file.propq, 0))
+ return 0;
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_INPUT_TYPE);
+ if (p != NULL) {
+ OPENSSL_free(ctx->_.file.input_type);
+ ctx->_.file.input_type = NULL;
+ if (!OSSL_PARAM_get_utf8_string(p, &ctx->_.file.input_type, 0))
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_EXPECT);
+ if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->expected_type))
+ return 0;
+ p = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_SUBJECT);
+ if (p != NULL) {
+ const unsigned char *der = NULL;
+ size_t der_len = 0;
+ X509_NAME *x509_name;
+ unsigned long hash;
+ int ok;
+
+ if (ctx->type != IS_DIR) {
+ ERR_raise(ERR_LIB_PROV,
+ PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES);
+ return 0;
+ }
+
+ if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&der, &der_len)
+ || (x509_name = d2i_X509_NAME(NULL, &der, der_len)) == NULL)
+ return 0;
+ hash = X509_NAME_hash_ex(x509_name,
+ ossl_prov_ctx_get0_libctx(ctx->provctx), NULL,
+ &ok);
+ BIO_snprintf(ctx->_.dir.search_name, sizeof(ctx->_.dir.search_name),
+ "%08lx", hash);
+ X509_NAME_free(x509_name);
+ if (ok == 0)
+ return 0;
+ }
+ return 1;
+}
+
+/*-
+ * Loading an object from a stream
+ * -------------------------------
+ */
+
+struct file_load_data_st {
+ OSSL_CALLBACK *object_cb;
+ void *object_cbarg;
+};
+
+static int file_load_construct(OSSL_DECODER_INSTANCE *decoder_inst,
+ const OSSL_PARAM *params, void *construct_data)
+{
+ struct file_load_data_st *data = construct_data;
+
+ /*
+ * At some point, we may find it justifiable to recognise PKCS#12 and
+ * handle it specially here, making |file_load()| return pass its
+ * contents one piece at ta time, like |e_loader_attic.c| does.
+ *
+ * However, that currently means parsing them out, which converts the
+ * DER encoded PKCS#12 into a bunch of EVP_PKEYs and X509s, just to
+ * have to re-encode them into DER to create an object abstraction for
+ * each of them.
+ * It's much simpler (less churn) to pass on the object abstraction we
+ * get to the load_result callback and leave it to that one to do the
+ * work. If that's libcrypto code, we know that it has much better
+ * possibilities to handle the EVP_PKEYs and X509s without the extra
+ * churn.
+ */
+
+ return data->object_cb(params, data->object_cbarg);
+}
+
+void file_load_cleanup(void *construct_data)
+{
+ /* Nothing to do */
+}
+
+static int file_setup_decoders(struct file_ctx_st *ctx)
+{
+ OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(ctx->provctx);
+ const OSSL_ALGORITHM *to_algo = NULL;
+ int ok = 0;
+
+ /* Setup for this session, so only if not already done */
+ if (ctx->_.file.decoderctx == NULL) {
+ if ((ctx->_.file.decoderctx = OSSL_DECODER_CTX_new()) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* Make sure the input type is set */
+ if (!OSSL_DECODER_CTX_set_input_type(ctx->_.file.decoderctx,
+ ctx->_.file.input_type)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
+ goto err;
+ }
+
+ /*
+ * Where applicable, set the outermost structure name.
+ * The goal is to avoid the STORE object types that are
+ * potentially password protected but aren't interesting
+ * for this load.
+ */
+ switch (ctx->expected_type) {
+ case OSSL_STORE_INFO_CERT:
+ if (!OSSL_DECODER_CTX_set_input_structure(ctx->_.file.decoderctx,
+ "Certificate")) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
+ goto err;
+ }
+ break;
+ case OSSL_STORE_INFO_CRL:
+ if (!OSSL_DECODER_CTX_set_input_structure(ctx->_.file.decoderctx,
+ "CertificateList")) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
+ goto err;
+ }
+ break;
+ default:
+ break;
+ }
+
+ for (to_algo = ossl_any_to_obj_algorithm;
+ to_algo->algorithm_names != NULL;
+ to_algo++) {
+ OSSL_DECODER *to_obj = NULL;
+ OSSL_DECODER_INSTANCE *to_obj_inst = NULL;
+
+ /*
+ * Create the internal last resort decoder implementation
+ * together with a "decoder instance".
+ * The decoder doesn't need any identification or to be
+ * attached to any provider, since it's only used locally.
+ */
+ to_obj = ossl_decoder_from_algorithm(0, to_algo, NULL);
+ if (to_obj != NULL)
+ to_obj_inst = ossl_decoder_instance_new(to_obj, ctx->provctx);
+ OSSL_DECODER_free(to_obj);
+ if (to_obj_inst == NULL)
+ goto err;
+
+ if (!ossl_decoder_ctx_add_decoder_inst(ctx->_.file.decoderctx,
+ to_obj_inst)) {
+ ossl_decoder_instance_free(to_obj_inst);
+ ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
+ goto err;
+ }
+ }
+ /* Add on the usual extra decoders */
+ if (!OSSL_DECODER_CTX_add_extra(ctx->_.file.decoderctx,
+ libctx, ctx->_.file.propq)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
+ goto err;
+ }
+
+ /*
+ * Then install our constructor hooks, which just passes decoded
+ * data to the load callback
+ */
+ if (!OSSL_DECODER_CTX_set_construct(ctx->_.file.decoderctx,
+ file_load_construct)
+ || !OSSL_DECODER_CTX_set_cleanup(ctx->_.file.decoderctx,
+ file_load_cleanup)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
+ goto err;
+ }
+ }
+
+ ok = 1;
+ err:
+ return ok;
+}
+
+static int file_load_file(struct file_ctx_st *ctx,
+ OSSL_CALLBACK *object_cb, void *object_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+ struct file_load_data_st data;
+ int ret, err;
+
+ /* Setup the decoders (one time shot per session */
+
+ if (!file_setup_decoders(ctx))
+ return 0;
+
+ /* Setup for this object */
+
+ data.object_cb = object_cb;
+ data.object_cbarg = object_cbarg;
+ OSSL_DECODER_CTX_set_construct_data(ctx->_.file.decoderctx, &data);
+ OSSL_DECODER_CTX_set_passphrase_cb(ctx->_.file.decoderctx, pw_cb, pw_cbarg);
+
+ /* Launch */
+
+ ERR_set_mark();
+ ret = OSSL_DECODER_from_bio(ctx->_.file.decoderctx, ctx->_.file.file);
+ if (BIO_eof(ctx->_.file.file)
+ && ((err = ERR_peek_last_error()) != 0)
+ && ERR_GET_LIB(err) == ERR_LIB_OSSL_DECODER
+ && ERR_GET_REASON(err) == ERR_R_UNSUPPORTED)
+ ERR_pop_to_mark();
+ else
+ ERR_clear_last_mark();
+ return ret;
+}
+
+/*-
+ * Loading a name object from a directory
+ * --------------------------------------
+ */
+
+static char *file_name_to_uri(struct file_ctx_st *ctx, const char *name)
+{
+ char *data = NULL;
+
+ assert(name != NULL);
+ {
+ const char *pathsep = ossl_ends_with_dirsep(ctx->uri) ? "" : "/";
+ long calculated_length = strlen(ctx->uri) + strlen(pathsep)
+ + strlen(name) + 1 /* \0 */;
+
+ data = OPENSSL_zalloc(calculated_length);
+ if (data == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ OPENSSL_strlcat(data, ctx->uri, calculated_length);
+ OPENSSL_strlcat(data, pathsep, calculated_length);
+ OPENSSL_strlcat(data, name, calculated_length);
+ }
+ return data;
+}
+
+static int file_name_check(struct file_ctx_st *ctx, const char *name)
+{
+ const char *p = NULL;
+ size_t len = strlen(ctx->_.dir.search_name);
+
+ /* If there are no search criteria, all names are accepted */
+ if (ctx->_.dir.search_name[0] == '\0')
+ return 1;
+
+ /* If the expected type isn't supported, no name is accepted */
+ if (ctx->expected_type != 0
+ && ctx->expected_type != OSSL_STORE_INFO_CERT
+ && ctx->expected_type != OSSL_STORE_INFO_CRL)
+ return 0;
+
+ /*
+ * First, check the basename
+ */
+ if (OPENSSL_strncasecmp(name, ctx->_.dir.search_name, len) != 0
+ || name[len] != '.')
+ return 0;
+ p = &name[len + 1];
+
+ /*
+ * Then, if the expected type is a CRL, check that the extension starts
+ * with 'r'
+ */
+ if (*p == 'r') {
+ p++;
+ if (ctx->expected_type != 0
+ && ctx->expected_type != OSSL_STORE_INFO_CRL)
+ return 0;
+ } else if (ctx->expected_type == OSSL_STORE_INFO_CRL) {
+ return 0;
+ }
+
+ /*
+ * Last, check that the rest of the extension is a decimal number, at
+ * least one digit long.
+ */
+ if (!isdigit(*p))
+ return 0;
+ while (isdigit(*p))
+ p++;
+
+#ifdef __VMS
+ /*
+ * One extra step here, check for a possible generation number.
+ */
+ if (*p == ';')
+ for (p++; *p != '\0'; p++)
+ if (!ossl_isdigit(*p))
+ break;
+#endif
+
+ /*
+ * If we've reached the end of the string at this point, we've successfully
+ * found a fitting file name.
+ */
+ return *p == '\0';
+}
+
+static int file_load_dir_entry(struct file_ctx_st *ctx,
+ OSSL_CALLBACK *object_cb, void *object_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+ /* Prepare as much as possible in advance */
+ static const int object_type = OSSL_OBJECT_NAME;
+ OSSL_PARAM object[] = {
+ OSSL_PARAM_int(OSSL_OBJECT_PARAM_TYPE, (int *)&object_type),
+ OSSL_PARAM_utf8_string(OSSL_OBJECT_PARAM_DATA, NULL, 0),
+ OSSL_PARAM_END
+ };
+ char *newname = NULL;
+ int ok;
+
+ /* Loop until we get an error or until we have a suitable name */
+ do {
+ if (ctx->_.dir.last_entry == NULL) {
+ if (!ctx->_.dir.end_reached) {
+ assert(ctx->_.dir.last_errno != 0);
+ ERR_raise(ERR_LIB_SYS, ctx->_.dir.last_errno);
+ }
+ /* file_eof() will tell if EOF was reached */
+ return 0;
+ }
+
+ /* flag acceptable names */
+ if (ctx->_.dir.last_entry[0] != '.'
+ && file_name_check(ctx, ctx->_.dir.last_entry)) {
+
+ /* If we can't allocate the new name, we fail */
+ if ((newname =
+ file_name_to_uri(ctx, ctx->_.dir.last_entry)) == NULL)
+ return 0;
+ }
+
+ /*
+ * On the first call (with a NULL context), OPENSSL_DIR_read()
+ * cares about the second argument. On the following calls, it
+ * only cares that it isn't NULL. Therefore, we can safely give
+ * it our URI here.
+ */
+ ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx, ctx->uri);
+ ctx->_.dir.last_errno = errno;
+ if (ctx->_.dir.last_entry == NULL && ctx->_.dir.last_errno == 0)
+ ctx->_.dir.end_reached = 1;
+ } while (newname == NULL);
+
+ object[1].data = newname;
+ object[1].data_size = strlen(newname);
+ ok = object_cb(object, object_cbarg);
+ OPENSSL_free(newname);
+ return ok;
+}
+
+/*-
+ * Loading, local dispatcher
+ * -------------------------
+ */
+
+static int file_load(void *loaderctx,
+ OSSL_CALLBACK *object_cb, void *object_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+ struct file_ctx_st *ctx = loaderctx;
+
+ switch (ctx->type) {
+ case IS_FILE:
+ return file_load_file(ctx, object_cb, object_cbarg, pw_cb, pw_cbarg);
+ case IS_DIR:
+ return
+ file_load_dir_entry(ctx, object_cb, object_cbarg, pw_cb, pw_cbarg);
+ default:
+ break;
+ }
+
+ /* ctx->type has an unexpected value */
+ assert(0);
+ return 0;
+}
+
+/*-
+ * Eof detection and closing
+ * -------------------------
+ */
+
+static int file_eof(void *loaderctx)
+{
+ struct file_ctx_st *ctx = loaderctx;
+
+ switch (ctx->type) {
+ case IS_DIR:
+ return ctx->_.dir.end_reached;
+ case IS_FILE:
+ /*
+ * BIO_pending() checks any filter BIO.
+ * BIO_eof() checks the source BIO.
+ */
+ return !BIO_pending(ctx->_.file.file)
+ && BIO_eof(ctx->_.file.file);
+ }
+
+ /* ctx->type has an unexpected value */
+ assert(0);
+ return 1;
+}
+
+static int file_close_dir(struct file_ctx_st *ctx)
+{
+ if (ctx->_.dir.ctx != NULL)
+ OPENSSL_DIR_end(&ctx->_.dir.ctx);
+ free_file_ctx(ctx);
+ return 1;
+}
+
+static int file_close_stream(struct file_ctx_st *ctx)
+{
+ /*
+ * This frees either the provider BIO filter (for file_attach()) OR
+ * the allocated file BIO (for file_open()).
+ */
+ BIO_free(ctx->_.file.file);
+ ctx->_.file.file = NULL;
+
+ free_file_ctx(ctx);
+ return 1;
+}
+
+static int file_close(void *loaderctx)
+{
+ struct file_ctx_st *ctx = loaderctx;
+
+ switch (ctx->type) {
+ case IS_DIR:
+ return file_close_dir(ctx);
+ case IS_FILE:
+ return file_close_stream(ctx);
+ }
+
+ /* ctx->type has an unexpected value */
+ assert(0);
+ return 1;
+}
+
+const OSSL_DISPATCH ossl_file_store_functions[] = {
+ { OSSL_FUNC_STORE_OPEN, (void (*)(void))file_open },
+ { OSSL_FUNC_STORE_ATTACH, (void (*)(void))file_attach },
+ { OSSL_FUNC_STORE_SETTABLE_CTX_PARAMS,
+ (void (*)(void))file_settable_ctx_params },
+ { OSSL_FUNC_STORE_SET_CTX_PARAMS, (void (*)(void))file_set_ctx_params },
+ { OSSL_FUNC_STORE_LOAD, (void (*)(void))file_load },
+ { OSSL_FUNC_STORE_EOF, (void (*)(void))file_eof },
+ { OSSL_FUNC_STORE_CLOSE, (void (*)(void))file_close },
+ { 0, NULL },
+};
diff --git a/providers/implementations/storemgmt/file_store_any2obj.c b/providers/implementations/storemgmt/file_store_any2obj.c
new file mode 100644
index 000000000000..28601683bf6e
--- /dev/null
+++ b/providers/implementations/storemgmt/file_store_any2obj.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This is a decoder that's completely internal to the 'file:' store
+ * implementation. Only code in file_store.c know about this one. Because
+ * of this close relationship, we can cut certain corners, such as making
+ * assumptions about the "provider context", which is currently simply the
+ * provider context that the file_store.c code operates within.
+ *
+ * All this does is to read known binary encodings (currently: DER, MSBLOB,
+ * PVK) from the input if it can, and passes it on to the data callback as
+ * an object abstraction, leaving it to the callback to figure out what it
+ * actually is.
+ *
+ * This MUST be made the last decoder in a chain, leaving it to other more
+ * specialized decoders to recognise and process their stuff first.
+ */
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/core_object.h>
+#include <openssl/bio.h>
+#include <openssl/buffer.h>
+#include <openssl/err.h>
+#include <openssl/asn1err.h>
+#include <openssl/params.h>
+#include "internal/asn1.h"
+#include "crypto/pem.h" /* For internal PVK and "blob" headers */
+#include "prov/bio.h"
+#include "file_store_local.h"
+
+/*
+ * newctx and freectx are not strictly necessary. However, the method creator,
+ * ossl_decoder_from_algorithm(), demands that they exist, so we make sure to
+ * oblige.
+ */
+
+static OSSL_FUNC_decoder_newctx_fn any2obj_newctx;
+static OSSL_FUNC_decoder_freectx_fn any2obj_freectx;
+
+static void *any2obj_newctx(void *provctx)
+{
+ return provctx;
+}
+
+static void any2obj_freectx(void *vctx)
+{
+}
+
+static int any2obj_decode_final(void *provctx, int objtype, BUF_MEM *mem,
+ OSSL_CALLBACK *data_cb, void *data_cbarg)
+{
+ /*
+ * 1 indicates that we successfully decoded something, or not at all.
+ * Ending up "empty handed" is not an error.
+ */
+ int ok = 1;
+
+ if (mem != NULL) {
+ OSSL_PARAM params[3];
+
+ params[0] =
+ OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype);
+ params[1] =
+ OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA,
+ mem->data, mem->length);
+ params[2] = OSSL_PARAM_construct_end();
+
+ ok = data_cb(params, data_cbarg);
+ BUF_MEM_free(mem);
+ }
+ return ok;
+}
+
+static OSSL_FUNC_decoder_decode_fn der2obj_decode;
+static int der2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection,
+ OSSL_CALLBACK *data_cb, void *data_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+ BIO *in = ossl_bio_new_from_core_bio(provctx, cin);
+ BUF_MEM *mem = NULL;
+ int ok;
+
+ if (in == NULL)
+ return 0;
+
+ ERR_set_mark();
+ ok = (asn1_d2i_read_bio(in, &mem) >= 0);
+ ERR_pop_to_mark();
+ if (!ok && mem != NULL) {
+ BUF_MEM_free(mem);
+ mem = NULL;
+ }
+ BIO_free(in);
+
+ /* any2obj_decode_final() frees |mem| for us */
+ return any2obj_decode_final(provctx, OSSL_OBJECT_UNKNOWN, mem,
+ data_cb, data_cbarg);
+}
+
+static OSSL_FUNC_decoder_decode_fn msblob2obj_decode;
+static int msblob2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection,
+ OSSL_CALLBACK *data_cb, void *data_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+ BIO *in = ossl_bio_new_from_core_bio(provctx, cin);
+ BUF_MEM *mem = NULL;
+ size_t mem_len = 0, mem_want;
+ const unsigned char *p;
+ unsigned int bitlen, magic;
+ int isdss = -1;
+ int ispub = -1;
+ int ok = 0;
+
+ if (in == NULL)
+ goto err;
+
+ mem_want = 16; /* The size of the MSBLOB header */
+ if ((mem = BUF_MEM_new()) == NULL
+ || !BUF_MEM_grow(mem, mem_want)) {
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ ERR_set_mark();
+ ok = BIO_read(in, &mem->data[0], mem_want) == (int)mem_want;
+ mem_len += mem_want;
+ ERR_pop_to_mark();
+ if (!ok)
+ goto next;
+
+
+ ERR_set_mark();
+ p = (unsigned char *)&mem->data[0];
+ ok = ossl_do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) > 0;
+ ERR_pop_to_mark();
+ if (!ok)
+ goto next;
+
+ ok = 0;
+ mem_want = ossl_blob_length(bitlen, isdss, ispub);
+ if (!BUF_MEM_grow(mem, mem_len + mem_want)) {
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ ERR_set_mark();
+ ok = BIO_read(in, &mem->data[mem_len], mem_want) == (int)mem_want;
+ mem_len += mem_want;
+ ERR_pop_to_mark();
+
+ next:
+ /* Free resources we no longer need. */
+ BIO_free(in);
+ if (!ok && mem != NULL) {
+ BUF_MEM_free(mem);
+ mem = NULL;
+ }
+
+ /* any2obj_decode_final() frees |mem| for us */
+ return any2obj_decode_final(provctx, OSSL_OBJECT_PKEY, mem,
+ data_cb, data_cbarg);
+
+ err:
+ BIO_free(in);
+ BUF_MEM_free(mem);
+ return 0;
+}
+
+static OSSL_FUNC_decoder_decode_fn pvk2obj_decode;
+static int pvk2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection,
+ OSSL_CALLBACK *data_cb, void *data_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+ BIO *in = ossl_bio_new_from_core_bio(provctx, cin);
+ BUF_MEM *mem = NULL;
+ size_t mem_len = 0, mem_want;
+ const unsigned char *p;
+ unsigned int saltlen, keylen;
+ int ok = 0;
+
+ if (in == NULL)
+ goto err;
+
+ mem_want = 24; /* The size of the PVK header */
+ if ((mem = BUF_MEM_new()) == NULL
+ || !BUF_MEM_grow(mem, mem_want)) {
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ ERR_set_mark();
+ ok = BIO_read(in, &mem->data[0], mem_want) == (int)mem_want;
+ mem_len += mem_want;
+ ERR_pop_to_mark();
+ if (!ok)
+ goto next;
+
+
+ ERR_set_mark();
+ p = (unsigned char *)&mem->data[0];
+ ok = ossl_do_PVK_header(&p, 24, 0, &saltlen, &keylen) > 0;
+ ERR_pop_to_mark();
+ if (!ok)
+ goto next;
+
+ ok = 0;
+ mem_want = saltlen + keylen;
+ if (!BUF_MEM_grow(mem, mem_len + mem_want)) {
+ ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ ERR_set_mark();
+ ok = BIO_read(in, &mem->data[mem_len], mem_want) == (int)mem_want;
+ mem_len += mem_want;
+ ERR_pop_to_mark();
+
+ next:
+ /* Free resources we no longer need. */
+ BIO_free(in);
+ if (!ok && mem != NULL) {
+ BUF_MEM_free(mem);
+ mem = NULL;
+ }
+
+ /* any2obj_decode_final() frees |mem| for us */
+ return any2obj_decode_final(provctx, OSSL_OBJECT_PKEY, mem,
+ data_cb, data_cbarg);
+
+ err:
+ BIO_free(in);
+ BUF_MEM_free(mem);
+ return 0;
+}
+
+#define MAKE_DECODER(fromtype, objtype) \
+ static const OSSL_DISPATCH fromtype##_to_obj_decoder_functions[] = { \
+ { OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))any2obj_newctx }, \
+ { OSSL_FUNC_DECODER_FREECTX, (void (*)(void))any2obj_freectx }, \
+ { OSSL_FUNC_DECODER_DECODE, (void (*)(void))fromtype##2obj_decode }, \
+ { 0, NULL } \
+ }
+
+MAKE_DECODER(der, OSSL_OBJECT_UNKNOWN);
+MAKE_DECODER(msblob, OSSL_OBJECT_PKEY);
+MAKE_DECODER(pvk, OSSL_OBJECT_PKEY);
+
+const OSSL_ALGORITHM ossl_any_to_obj_algorithm[] = {
+ { "obj", "input=DER", der_to_obj_decoder_functions },
+ { "obj", "input=MSBLOB", msblob_to_obj_decoder_functions },
+ { "obj", "input=PVK", pvk_to_obj_decoder_functions },
+ { NULL, }
+};
diff --git a/providers/implementations/storemgmt/file_store_local.h b/providers/implementations/storemgmt/file_store_local.h
new file mode 100644
index 000000000000..b7d9e585163e
--- /dev/null
+++ b/providers/implementations/storemgmt/file_store_local.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+extern const OSSL_ALGORITHM ossl_any_to_obj_algorithm[];
+
diff --git a/providers/legacyprov.c b/providers/legacyprov.c
new file mode 100644
index 000000000000..38505d86c678
--- /dev/null
+++ b/providers/legacyprov.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include "prov/provider_ctx.h"
+#include "prov/implementations.h"
+#include "prov/names.h"
+#include "prov/providercommon.h"
+
+/*
+ * Forward declarations to ensure that interface functions are correctly
+ * defined.
+ */
+static OSSL_FUNC_provider_gettable_params_fn legacy_gettable_params;
+static OSSL_FUNC_provider_get_params_fn legacy_get_params;
+static OSSL_FUNC_provider_query_operation_fn legacy_query;
+
+#define ALG(NAMES, FUNC) { NAMES, "provider=legacy", FUNC }
+
+#ifdef STATIC_LEGACY
+OSSL_provider_init_fn ossl_legacy_provider_init;
+# define OSSL_provider_init ossl_legacy_provider_init
+#endif
+
+/* Parameters we provide to the core */
+static const OSSL_PARAM legacy_param_types[] = {
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_VERSION, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_BUILDINFO, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_STATUS, OSSL_PARAM_INTEGER, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *legacy_gettable_params(void *provctx)
+{
+ return legacy_param_types;
+}
+
+static int legacy_get_params(void *provctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "OpenSSL Legacy Provider"))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_VERSION);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_VERSION_STR))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_BUILDINFO);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_FULL_VERSION_STR))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_STATUS);
+ if (p != NULL && !OSSL_PARAM_set_int(p, ossl_prov_is_running()))
+ return 0;
+ return 1;
+}
+
+static const OSSL_ALGORITHM legacy_digests[] = {
+#ifndef OPENSSL_NO_MD2
+ ALG(PROV_NAMES_MD2, ossl_md2_functions),
+#endif
+#ifndef OPENSSL_NO_MD4
+ ALG(PROV_NAMES_MD4, ossl_md4_functions),
+#endif
+#ifndef OPENSSL_NO_MDC2
+ ALG(PROV_NAMES_MDC2, ossl_mdc2_functions),
+#endif /* OPENSSL_NO_MDC2 */
+#ifndef OPENSSL_NO_WHIRLPOOL
+ ALG(PROV_NAMES_WHIRLPOOL, ossl_wp_functions),
+#endif /* OPENSSL_NO_WHIRLPOOL */
+#ifndef OPENSSL_NO_RMD160
+ ALG(PROV_NAMES_RIPEMD_160, ossl_ripemd160_functions),
+#endif /* OPENSSL_NO_RMD160 */
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM legacy_ciphers[] = {
+#ifndef OPENSSL_NO_CAST
+ ALG(PROV_NAMES_CAST5_ECB, ossl_cast5128ecb_functions),
+ ALG(PROV_NAMES_CAST5_CBC, ossl_cast5128cbc_functions),
+ ALG(PROV_NAMES_CAST5_OFB, ossl_cast5128ofb64_functions),
+ ALG(PROV_NAMES_CAST5_CFB, ossl_cast5128cfb64_functions),
+#endif /* OPENSSL_NO_CAST */
+#ifndef OPENSSL_NO_BF
+ ALG(PROV_NAMES_BF_ECB, ossl_blowfish128ecb_functions),
+ ALG(PROV_NAMES_BF_CBC, ossl_blowfish128cbc_functions),
+ ALG(PROV_NAMES_BF_OFB, ossl_blowfish128ofb64_functions),
+ ALG(PROV_NAMES_BF_CFB, ossl_blowfish128cfb64_functions),
+#endif /* OPENSSL_NO_BF */
+#ifndef OPENSSL_NO_IDEA
+ ALG(PROV_NAMES_IDEA_ECB, ossl_idea128ecb_functions),
+ ALG(PROV_NAMES_IDEA_CBC, ossl_idea128cbc_functions),
+ ALG(PROV_NAMES_IDEA_OFB, ossl_idea128ofb64_functions),
+ ALG(PROV_NAMES_IDEA_CFB, ossl_idea128cfb64_functions),
+#endif /* OPENSSL_NO_IDEA */
+#ifndef OPENSSL_NO_SEED
+ ALG(PROV_NAMES_SEED_ECB, ossl_seed128ecb_functions),
+ ALG(PROV_NAMES_SEED_CBC, ossl_seed128cbc_functions),
+ ALG(PROV_NAMES_SEED_OFB, ossl_seed128ofb128_functions),
+ ALG(PROV_NAMES_SEED_CFB, ossl_seed128cfb128_functions),
+#endif /* OPENSSL_NO_SEED */
+#ifndef OPENSSL_NO_RC2
+ ALG(PROV_NAMES_RC2_ECB, ossl_rc2128ecb_functions),
+ ALG(PROV_NAMES_RC2_CBC, ossl_rc2128cbc_functions),
+ ALG(PROV_NAMES_RC2_40_CBC, ossl_rc240cbc_functions),
+ ALG(PROV_NAMES_RC2_64_CBC, ossl_rc264cbc_functions),
+ ALG(PROV_NAMES_RC2_CFB, ossl_rc2128cfb128_functions),
+ ALG(PROV_NAMES_RC2_OFB, ossl_rc2128ofb128_functions),
+#endif /* OPENSSL_NO_RC2 */
+#ifndef OPENSSL_NO_RC4
+ ALG(PROV_NAMES_RC4, ossl_rc4128_functions),
+ ALG(PROV_NAMES_RC4_40, ossl_rc440_functions),
+# ifndef OPENSSL_NO_MD5
+ ALG(PROV_NAMES_RC4_HMAC_MD5, ossl_rc4_hmac_ossl_md5_functions),
+# endif /* OPENSSL_NO_MD5 */
+#endif /* OPENSSL_NO_RC4 */
+#ifndef OPENSSL_NO_RC5
+ ALG(PROV_NAMES_RC5_ECB, ossl_rc5128ecb_functions),
+ ALG(PROV_NAMES_RC5_CBC, ossl_rc5128cbc_functions),
+ ALG(PROV_NAMES_RC5_OFB, ossl_rc5128ofb64_functions),
+ ALG(PROV_NAMES_RC5_CFB, ossl_rc5128cfb64_functions),
+#endif /* OPENSSL_NO_RC5 */
+#ifndef OPENSSL_NO_DES
+ ALG(PROV_NAMES_DESX_CBC, ossl_tdes_desx_cbc_functions),
+ ALG(PROV_NAMES_DES_ECB, ossl_des_ecb_functions),
+ ALG(PROV_NAMES_DES_CBC, ossl_des_cbc_functions),
+ ALG(PROV_NAMES_DES_OFB, ossl_des_ofb64_functions),
+ ALG(PROV_NAMES_DES_CFB, ossl_des_cfb64_functions),
+ ALG(PROV_NAMES_DES_CFB1, ossl_des_cfb1_functions),
+ ALG(PROV_NAMES_DES_CFB8, ossl_des_cfb8_functions),
+#endif /* OPENSSL_NO_DES */
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM legacy_kdfs[] = {
+ ALG(PROV_NAMES_PBKDF1, ossl_kdf_pbkdf1_functions),
+ { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM *legacy_query(void *provctx, int operation_id,
+ int *no_cache)
+{
+ *no_cache = 0;
+ switch (operation_id) {
+ case OSSL_OP_DIGEST:
+ return legacy_digests;
+ case OSSL_OP_CIPHER:
+ return legacy_ciphers;
+ case OSSL_OP_KDF:
+ return legacy_kdfs;
+ }
+ return NULL;
+}
+
+static void legacy_teardown(void *provctx)
+{
+ OSSL_LIB_CTX_free(PROV_LIBCTX_OF(provctx));
+ ossl_prov_ctx_free(provctx);
+}
+
+/* Functions we provide to the core */
+static const OSSL_DISPATCH legacy_dispatch_table[] = {
+ { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))legacy_teardown },
+ { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void))legacy_gettable_params },
+ { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))legacy_get_params },
+ { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))legacy_query },
+ { 0, NULL }
+};
+
+int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in,
+ const OSSL_DISPATCH **out,
+ void **provctx)
+{
+ OSSL_LIB_CTX *libctx = NULL;
+
+ if ((*provctx = ossl_prov_ctx_new()) == NULL
+ || (libctx = OSSL_LIB_CTX_new_child(handle, in)) == NULL) {
+ OSSL_LIB_CTX_free(libctx);
+ legacy_teardown(*provctx);
+ *provctx = NULL;
+ return 0;
+ }
+ ossl_prov_ctx_set0_libctx(*provctx, libctx);
+ ossl_prov_ctx_set0_handle(*provctx, handle);
+
+ *out = legacy_dispatch_table;
+
+ return 1;
+}
diff --git a/providers/nullprov.c b/providers/nullprov.c
new file mode 100644
index 000000000000..d5b4c05d9321
--- /dev/null
+++ b/providers/nullprov.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <openssl/core.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+
+OSSL_provider_init_fn ossl_null_provider_init;
+
+/* Parameters we provide to the core */
+static const OSSL_PARAM null_param_types[] = {
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_VERSION, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_BUILDINFO, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_STATUS, OSSL_PARAM_INTEGER, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *null_gettable_params(const OSSL_PROVIDER *prov)
+{
+ return null_param_types;
+}
+
+static int null_get_params(const OSSL_PROVIDER *provctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "OpenSSL Null Provider"))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_VERSION);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_VERSION_STR))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_BUILDINFO);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_FULL_VERSION_STR))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_STATUS);
+ if (p != NULL && !OSSL_PARAM_set_int(p, ossl_prov_is_running()))
+ return 0;
+ return 1;
+}
+
+static const OSSL_ALGORITHM *null_query(OSSL_PROVIDER *prov,
+ int operation_id,
+ int *no_cache)
+{
+ *no_cache = 0;
+ return NULL;
+}
+
+/* Functions we provide to the core */
+static const OSSL_DISPATCH null_dispatch_table[] = {
+ { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void))null_gettable_params },
+ { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))null_get_params },
+ { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))null_query },
+ { 0, NULL }
+};
+
+int ossl_null_provider_init(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in,
+ const OSSL_DISPATCH **out,
+ void **provctx)
+{
+ *out = null_dispatch_table;
+
+ /* Could be anything - we don't use it */
+ *provctx = (void *)handle;
+ return 1;
+}
diff --git a/providers/prov_running.c b/providers/prov_running.c
new file mode 100644
index 000000000000..379fd5d25c7c
--- /dev/null
+++ b/providers/prov_running.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/e_os2.h>
+#include "prov/providercommon.h"
+
+/* By default, our providers don't have an error state */
+void ossl_set_error_state(const char *type)
+{
+}
+
+/* By default, our providers are always in a happy state */
+int ossl_prov_is_running(void)
+{
+ return 1;
+}
diff --git a/providers/stores.inc b/providers/stores.inc
new file mode 100644
index 000000000000..4c1ec8f28778
--- /dev/null
+++ b/providers/stores.inc
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef STORE
+# error Macro STORE undefined
+#endif
+
+STORE("file", "yes", ossl_file_store_functions)
diff --git a/ssl/bio_ssl.c b/ssl/bio_ssl.c
index 67097d5cca41..401178f0c2e4 100644
--- a/ssl/bio_ssl.c
+++ b/ssl/bio_ssl.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -58,7 +58,7 @@ static int ssl_new(BIO *bi)
BIO_SSL *bs = OPENSSL_zalloc(sizeof(*bs));
if (bs == NULL) {
- BIOerr(BIO_F_SSL_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
BIO_set_init(bi, 0);
diff --git a/ssl/build.info b/ssl/build.info
index bb2f1deb5300..0851357f81eb 100644
--- a/ssl/build.info
+++ b/ssl/build.info
@@ -1,15 +1,44 @@
LIBS=../libssl
+
+#Needed for the multiblock code in rec_layer_s3.c
+IF[{- !$disabled{asm} -}]
+ $AESDEF_x86=AES_ASM
+ $AESDEF_x86_64=AES_ASM
+
+ IF[$AESDEF_{- $target{asm_arch} -}]
+ $AESDEF=$AESDEF_{- $target{asm_arch} -}
+ ENDIF
+ENDIF
+
+$KTLSSRC=
+IF[{- !$disabled{ktls} -}]
+ $KTLSSRC=ktls.c
+ENDIF
+
SOURCE[../libssl]=\
- pqueue.c packet.c \
+ pqueue.c \
statem/statem_srvr.c statem/statem_clnt.c s3_lib.c s3_enc.c record/rec_layer_s3.c \
statem/statem_lib.c statem/extensions.c statem/extensions_srvr.c \
- statem/extensions_clnt.c statem/extensions_cust.c s3_cbc.c s3_msg.c \
+ statem/extensions_clnt.c statem/extensions_cust.c s3_msg.c \
methods.c t1_lib.c t1_enc.c tls13_enc.c \
d1_lib.c record/rec_layer_d1.c d1_msg.c \
statem/statem_dtls.c d1_srtp.c \
ssl_lib.c ssl_cert.c ssl_sess.c \
ssl_ciph.c ssl_stat.c ssl_rsa.c \
ssl_asn1.c ssl_txt.c ssl_init.c ssl_conf.c ssl_mcnf.c \
- bio_ssl.c ssl_err.c tls_srp.c t1_trce.c ssl_utst.c \
+ bio_ssl.c ssl_err.c ssl_err_legacy.c tls_srp.c t1_trce.c ssl_utst.c \
record/ssl3_buffer.c record/ssl3_record.c record/dtls1_bitmap.c \
- statem/statem.c record/ssl3_record_tls13.c
+ statem/statem.c record/ssl3_record_tls13.c \
+ tls_depr.c $KTLSSRC
+# For shared builds we need to include the libcrypto packet.c and sources
+# needed in providers (s3_cbc.c and record/tls_pad.c) in libssl as well.
+SHARED_SOURCE[../libssl]=record/tls_pad.c ../crypto/packet.c
+IF[{- !$disabled{'deprecated-3.0'} -}]
+ SHARED_SOURCE[../libssl]=s3_cbc.c
+ SOURCE[../libssl]=ssl_rsa_legacy.c
+ENDIF
+
+DEFINE[../libssl]=$AESDEF
+
+SOURCE[../providers/libcommon.a]=record/tls_pad.c
+SOURCE[../providers/libdefault.a ../providers/libfips.a]=s3_cbc.c
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index 05b85c1078c0..95a34093c91b 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -1,7 +1,7 @@
/*
* Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -193,7 +193,7 @@ int dtls1_clear(SSL *s)
return 0;
if (s->method->version == DTLS_ANY_VERSION)
- s->version = DTLS_MAX_VERSION;
+ s->version = DTLS_MAX_VERSION_INTERNAL;
#ifndef OPENSSL_NO_DTLS1_METHOD
else if (s->options & SSL_OP_CISCO_ANYCONNECT)
s->client_version = s->version = DTLS1_BAD_VER;
@@ -352,7 +352,7 @@ static void dtls1_double_timeout(SSL *s)
void dtls1_stop_timer(SSL *s)
{
/* Reset everything */
- memset(&s->d1->timeout, 0, sizeof(s->d1->timeout));
+ s->d1->timeout_num_alerts = 0;
memset(&s->d1->next_timeout, 0, sizeof(s->d1->next_timeout));
s->d1->timeout_duration_us = 1000000;
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
@@ -365,10 +365,10 @@ int dtls1_check_timeout_num(SSL *s)
{
size_t mtu;
- s->d1->timeout.num_alerts++;
+ s->d1->timeout_num_alerts++;
/* Reduce MTU after 2 unsuccessful retransmissions */
- if (s->d1->timeout.num_alerts > 2
+ if (s->d1->timeout_num_alerts > 2
&& !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
mtu =
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);
@@ -376,10 +376,9 @@ int dtls1_check_timeout_num(SSL *s)
s->d1->mtu = mtu;
}
- if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) {
+ if (s->d1->timeout_num_alerts > DTLS1_TMO_ALERT_COUNT) {
/* fail the connection, enough alerts have been sent */
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS1_CHECK_TIMEOUT_NUM,
- SSL_R_READ_TIMEOUT_EXPIRED);
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_R_READ_TIMEOUT_EXPIRED);
return -1;
}
@@ -403,11 +402,6 @@ int dtls1_handle_timeout(SSL *s)
return -1;
}
- s->d1->timeout.read_timeouts++;
- if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) {
- s->d1->timeout.read_timeouts = 1;
- }
-
dtls1_start_timer(s);
/* Calls SSLfatal() if required */
return dtls1_retransmit_buffered_messages(s);
@@ -471,7 +465,7 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
wbio = SSL_get_wbio(s);
if (!rbio || !wbio) {
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BIO_NOT_SET);
+ ERR_raise(ERR_LIB_SSL, SSL_R_BIO_NOT_SET);
return -1;
}
@@ -483,12 +477,12 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
* SSL_accept)
*/
if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) {
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNSUPPORTED_SSL_VERSION);
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNSUPPORTED_SSL_VERSION);
return -1;
}
if (!ssl3_setup_buffers(s)) {
- /* SSLerr already called */
+ /* ERR_raise() already called */
return -1;
}
buf = RECORD_LAYER_get_rbuf(&s->rlayer)->buf;
@@ -522,7 +516,7 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
}
if (!PACKET_buf_init(&pkt, buf, n)) {
- SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return -1;
}
@@ -537,7 +531,7 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
/* this packet contained a partial record, dump it */
if (n < DTLS1_RT_HEADER_LENGTH) {
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_RECORD_TOO_SMALL);
+ ERR_raise(ERR_LIB_SSL, SSL_R_RECORD_TOO_SMALL);
goto end;
}
@@ -548,12 +542,12 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
/* Get the record header */
if (!PACKET_get_1(&pkt, &rectype)
|| !PACKET_get_1(&pkt, &versmajor)) {
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_LENGTH_MISMATCH);
goto end;
}
if (rectype != SSL3_RT_HANDSHAKE) {
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNEXPECTED_MESSAGE);
goto end;
}
@@ -562,7 +556,7 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
* the same.
*/
if (versmajor != DTLS1_VERSION_MAJOR) {
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
goto end;
}
@@ -570,7 +564,7 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
/* Save the sequence number: 64 bits, with top 2 bytes = epoch */
|| !PACKET_copy_bytes(&pkt, seq, SEQ_NUM_SIZE)
|| !PACKET_get_length_prefixed_2(&pkt, &msgpkt)) {
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_LENGTH_MISMATCH);
goto end;
}
reclen = PACKET_remaining(&msgpkt);
@@ -581,7 +575,7 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
/* This is an initial ClientHello so the epoch has to be 0 */
if (seq[0] != 0 || seq[1] != 0) {
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNEXPECTED_MESSAGE);
goto end;
}
@@ -596,18 +590,18 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
|| !PACKET_get_net_3_len(&msgpkt, &fraglen)
|| !PACKET_get_sub_packet(&msgpkt, &msgpayload, fraglen)
|| PACKET_remaining(&msgpkt) != 0) {
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_LENGTH_MISMATCH);
goto end;
}
if (msgtype != SSL3_MT_CLIENT_HELLO) {
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNEXPECTED_MESSAGE);
goto end;
}
/* Message sequence number can only be 0 or 1 */
if (msgseq > 2) {
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_INVALID_SEQUENCE_NUMBER);
+ ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_SEQUENCE_NUMBER);
goto end;
}
@@ -620,7 +614,7 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
*/
if (fragoff != 0 || fraglen > msglen) {
/* Non initial ClientHello fragment (or bad fragment) */
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_FRAGMENTED_CLIENT_HELLO);
+ ERR_raise(ERR_LIB_SSL, SSL_R_FRAGMENTED_CLIENT_HELLO);
goto end;
}
@@ -630,7 +624,7 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
s->msg_callback_arg);
if (!PACKET_get_net_2(&msgpayload, &clientvers)) {
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_LENGTH_MISMATCH);
goto end;
}
@@ -639,7 +633,7 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
*/
if (DTLS_VERSION_LT(clientvers, (unsigned int)s->method->version) &&
s->method->version != DTLS_ANY_VERSION) {
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_WRONG_VERSION_NUMBER);
+ ERR_raise(ERR_LIB_SSL, SSL_R_WRONG_VERSION_NUMBER);
goto end;
}
@@ -650,7 +644,7 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
* Could be malformed or the cookie does not fit within the initial
* ClientHello fragment. Either way we can't handle it.
*/
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_LENGTH_MISMATCH);
goto end;
}
@@ -665,7 +659,7 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
* We have a cookie, so lets check it.
*/
if (s->ctx->app_verify_cookie_cb == NULL) {
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_NO_VERIFY_COOKIE_CALLBACK);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_VERIFY_COOKIE_CALLBACK);
/* This is fatal */
return -1;
}
@@ -697,7 +691,7 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
if (s->ctx->app_gen_cookie_cb == NULL ||
s->ctx->app_gen_cookie_cb(s, cookie, &cookielen) == 0 ||
cookielen > 255) {
- SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
/* This is fatal */
return -1;
}
@@ -760,7 +754,7 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
|| !WPACKET_close(&wpkt)
|| !WPACKET_get_total_written(&wpkt, &wreclen)
|| !WPACKET_finish(&wpkt)) {
- SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
WPACKET_cleanup(&wpkt);
/* This is fatal */
return -1;
@@ -782,7 +776,7 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);
if ((tmpclient = BIO_ADDR_new()) == NULL) {
- SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto end;
}
@@ -797,7 +791,6 @@ int DTLSv1_listen(SSL *s, BIO_ADDR *client)
BIO_ADDR_free(tmpclient);
tmpclient = NULL;
- /* TODO(size_t): convert this call */
if (BIO_write(wbio, wbuf, wreclen) < (int)wreclen) {
if (BIO_should_retry(wbio)) {
/*
diff --git a/ssl/d1_msg.c b/ssl/d1_msg.c
index 8a31064ae13f..10438a395545 100644
--- a/ssl/d1_msg.c
+++ b/ssl/d1_msg.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2005-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -19,14 +19,13 @@ int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, size_t len,
if (i < 0)
return i;
if (i == 0) {
- SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES,
- SSL_R_SSL_HANDSHAKE_FAILURE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
return -1;
}
}
if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
- SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES, SSL_R_DTLS_MESSAGE_TOO_BIG);
+ ERR_raise(ERR_LIB_SSL, SSL_R_DTLS_MESSAGE_TOO_BIG);
return -1;
}
@@ -41,21 +40,21 @@ int dtls1_dispatch_alert(SSL *s)
unsigned char *ptr = &buf[0];
size_t written;
- s->s3->alert_dispatch = 0;
+ s->s3.alert_dispatch = 0;
memset(buf, 0, sizeof(buf));
- *ptr++ = s->s3->send_alert[0];
- *ptr++ = s->s3->send_alert[1];
+ *ptr++ = s->s3.send_alert[0];
+ *ptr++ = s->s3.send_alert[1];
i = do_dtls1_write(s, SSL3_RT_ALERT, &buf[0], sizeof(buf), 0, &written);
if (i <= 0) {
- s->s3->alert_dispatch = 1;
+ s->s3.alert_dispatch = 1;
/* fprintf( stderr, "not done with alert\n" ); */
} else {
(void)BIO_flush(s->wbio);
if (s->msg_callback)
- s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert,
+ s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3.send_alert,
2, s, s->msg_callback_arg);
if (s->info_callback != NULL)
@@ -64,7 +63,7 @@ int dtls1_dispatch_alert(SSL *s)
cb = s->ctx->info_callback;
if (cb != NULL) {
- j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1];
+ j = (s->s3.send_alert[0] << 8) | s->s3.send_alert[1];
cb(s, SSL_CB_WRITE_ALERT, j);
}
}
diff --git a/ssl/d1_srtp.c b/ssl/d1_srtp.c
index c05a77e34668..23007533826a 100644
--- a/ssl/d1_srtp.c
+++ b/ssl/d1_srtp.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -68,8 +68,7 @@ static int ssl_ctx_make_profiles(const char *profiles_string,
SRTP_PROTECTION_PROFILE *p;
if ((profiles = sk_SRTP_PROTECTION_PROFILE_new_null()) == NULL) {
- SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,
- SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES);
+ ERR_raise(ERR_LIB_SSL, SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES);
return 1;
}
@@ -79,19 +78,16 @@ static int ssl_ctx_make_profiles(const char *profiles_string,
if (!find_profile_by_name(ptr, &p, col ? (size_t)(col - ptr)
: strlen(ptr))) {
if (sk_SRTP_PROTECTION_PROFILE_find(profiles, p) >= 0) {
- SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,
- SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
goto err;
}
if (!sk_SRTP_PROTECTION_PROFILE_push(profiles, p)) {
- SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,
- SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES);
+ ERR_raise(ERR_LIB_SSL, SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES);
goto err;
}
} else {
- SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,
- SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE);
goto err;
}
diff --git a/ssl/ktls.c b/ssl/ktls.c
new file mode 100644
index 000000000000..ddbfd1447c54
--- /dev/null
+++ b/ssl/ktls.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "ssl_local.h"
+#include "internal/ktls.h"
+
+#if defined(__FreeBSD__)
+# include "crypto/cryptodev.h"
+
+/*-
+ * Check if a given cipher is supported by the KTLS interface.
+ * The kernel might still fail the setsockopt() if no suitable
+ * provider is found, but this checks if the socket option
+ * supports the cipher suite used at all.
+ */
+int ktls_check_supported_cipher(const SSL *s, const EVP_CIPHER *c,
+ const EVP_CIPHER_CTX *dd)
+{
+
+ switch (s->version) {
+ case TLS1_VERSION:
+ case TLS1_1_VERSION:
+ case TLS1_2_VERSION:
+ case TLS1_3_VERSION:
+ break;
+ default:
+ return 0;
+ }
+
+ switch (s->s3.tmp.new_cipher->algorithm_enc) {
+ case SSL_AES128GCM:
+ case SSL_AES256GCM:
+ return 1;
+ case SSL_AES128:
+ case SSL_AES256:
+ if (s->ext.use_etm)
+ return 0;
+ switch (s->s3.tmp.new_cipher->algorithm_mac) {
+ case SSL_SHA1:
+ case SSL_SHA256:
+ case SSL_SHA384:
+ return 1;
+ default:
+ return 0;
+ }
+ default:
+ return 0;
+ }
+}
+
+/* Function to configure kernel TLS structure */
+int ktls_configure_crypto(const SSL *s, const EVP_CIPHER *c, EVP_CIPHER_CTX *dd,
+ void *rl_sequence, ktls_crypto_info_t *crypto_info,
+ unsigned char **rec_seq, unsigned char *iv,
+ unsigned char *key, unsigned char *mac_key,
+ size_t mac_secret_size)
+{
+ memset(crypto_info, 0, sizeof(*crypto_info));
+ switch (s->s3.tmp.new_cipher->algorithm_enc) {
+ case SSL_AES128GCM:
+ case SSL_AES256GCM:
+ crypto_info->cipher_algorithm = CRYPTO_AES_NIST_GCM_16;
+ if (s->version == TLS1_3_VERSION) {
+ crypto_info->iv_len = EVP_CIPHER_CTX_get_iv_length(dd);
+ if (crypto_info->iv_len < 0)
+ return 0;
+ }
+ else
+ crypto_info->iv_len = EVP_GCM_TLS_FIXED_IV_LEN;
+ break;
+ case SSL_AES128:
+ case SSL_AES256:
+ switch (s->s3.tmp.new_cipher->algorithm_mac) {
+ case SSL_SHA1:
+ crypto_info->auth_algorithm = CRYPTO_SHA1_HMAC;
+ break;
+ case SSL_SHA256:
+ crypto_info->auth_algorithm = CRYPTO_SHA2_256_HMAC;
+ break;
+ case SSL_SHA384:
+ crypto_info->auth_algorithm = CRYPTO_SHA2_384_HMAC;
+ break;
+ default:
+ return 0;
+ }
+ crypto_info->cipher_algorithm = CRYPTO_AES_CBC;
+ crypto_info->iv_len = EVP_CIPHER_get_iv_length(c);
+ crypto_info->auth_key = mac_key;
+ crypto_info->auth_key_len = mac_secret_size;
+ break;
+ default:
+ return 0;
+ }
+ crypto_info->cipher_key = key;
+ crypto_info->cipher_key_len = EVP_CIPHER_get_key_length(c);
+ crypto_info->iv = iv;
+ crypto_info->tls_vmajor = (s->version >> 8) & 0x000000ff;
+ crypto_info->tls_vminor = (s->version & 0x000000ff);
+# ifdef TCP_RXTLS_ENABLE
+ memcpy(crypto_info->rec_seq, rl_sequence, sizeof(crypto_info->rec_seq));
+ if (rec_seq != NULL)
+ *rec_seq = crypto_info->rec_seq;
+# else
+ if (rec_seq != NULL)
+ *rec_seq = NULL;
+# endif
+ return 1;
+};
+
+#endif /* __FreeBSD__ */
+
+#if defined(OPENSSL_SYS_LINUX)
+
+/* Function to check supported ciphers in Linux */
+int ktls_check_supported_cipher(const SSL *s, const EVP_CIPHER *c,
+ const EVP_CIPHER_CTX *dd)
+{
+ switch (s->version) {
+ case TLS1_2_VERSION:
+ case TLS1_3_VERSION:
+ break;
+ default:
+ return 0;
+ }
+
+ /* check that cipher is AES_GCM_128, AES_GCM_256, AES_CCM_128
+ * or Chacha20-Poly1305
+ */
+# ifdef OPENSSL_KTLS_AES_CCM_128
+ if (EVP_CIPHER_is_a(c, "AES-128-CCM")) {
+ if (s->version == TLS_1_3_VERSION /* broken on 5.x kernels */
+ || EVP_CIPHER_CTX_get_tag_length(dd) != EVP_CCM_TLS_TAG_LEN)
+ return 0;
+ return 1;
+ } else
+# endif
+ if (0
+# ifdef OPENSSL_KTLS_AES_GCM_128
+ || EVP_CIPHER_is_a(c, "AES-128-GCM")
+# endif
+# ifdef OPENSSL_KTLS_AES_GCM_256
+ || EVP_CIPHER_is_a(c, "AES-256-GCM")
+# endif
+# ifdef OPENSSL_KTLS_CHACHA20_POLY1305
+ || EVP_CIPHER_is_a(c, "ChaCha20-Poly1305")
+# endif
+ ) {
+ return 1;
+ }
+ return 0;
+}
+
+/* Function to configure kernel TLS structure */
+int ktls_configure_crypto(const SSL *s, const EVP_CIPHER *c, EVP_CIPHER_CTX *dd,
+ void *rl_sequence, ktls_crypto_info_t *crypto_info,
+ unsigned char **rec_seq, unsigned char *iv,
+ unsigned char *key, unsigned char *mac_key,
+ size_t mac_secret_size)
+{
+ unsigned char geniv[12];
+ unsigned char *iiv = iv;
+
+ if (s->version == TLS1_2_VERSION &&
+ EVP_CIPHER_get_mode(c) == EVP_CIPH_GCM_MODE) {
+ if (!EVP_CIPHER_CTX_get_updated_iv(dd, geniv,
+ EVP_GCM_TLS_FIXED_IV_LEN
+ + EVP_GCM_TLS_EXPLICIT_IV_LEN))
+ return 0;
+ iiv = geniv;
+ }
+
+ memset(crypto_info, 0, sizeof(*crypto_info));
+ switch (EVP_CIPHER_get_nid(c))
+ {
+# ifdef OPENSSL_KTLS_AES_GCM_128
+ case NID_aes_128_gcm:
+ crypto_info->gcm128.info.cipher_type = TLS_CIPHER_AES_GCM_128;
+ crypto_info->gcm128.info.version = s->version;
+ crypto_info->tls_crypto_info_len = sizeof(crypto_info->gcm128);
+ memcpy(crypto_info->gcm128.iv, iiv + EVP_GCM_TLS_FIXED_IV_LEN,
+ TLS_CIPHER_AES_GCM_128_IV_SIZE);
+ memcpy(crypto_info->gcm128.salt, iiv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
+ memcpy(crypto_info->gcm128.key, key, EVP_CIPHER_get_key_length(c));
+ memcpy(crypto_info->gcm128.rec_seq, rl_sequence,
+ TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
+ if (rec_seq != NULL)
+ *rec_seq = crypto_info->gcm128.rec_seq;
+ return 1;
+# endif
+# ifdef OPENSSL_KTLS_AES_GCM_256
+ case NID_aes_256_gcm:
+ crypto_info->gcm256.info.cipher_type = TLS_CIPHER_AES_GCM_256;
+ crypto_info->gcm256.info.version = s->version;
+ crypto_info->tls_crypto_info_len = sizeof(crypto_info->gcm256);
+ memcpy(crypto_info->gcm256.iv, iiv + EVP_GCM_TLS_FIXED_IV_LEN,
+ TLS_CIPHER_AES_GCM_256_IV_SIZE);
+ memcpy(crypto_info->gcm256.salt, iiv, TLS_CIPHER_AES_GCM_256_SALT_SIZE);
+ memcpy(crypto_info->gcm256.key, key, EVP_CIPHER_get_key_length(c));
+ memcpy(crypto_info->gcm256.rec_seq, rl_sequence,
+ TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE);
+ if (rec_seq != NULL)
+ *rec_seq = crypto_info->gcm256.rec_seq;
+ return 1;
+# endif
+# ifdef OPENSSL_KTLS_AES_CCM_128
+ case NID_aes_128_ccm:
+ crypto_info->ccm128.info.cipher_type = TLS_CIPHER_AES_CCM_128;
+ crypto_info->ccm128.info.version = s->version;
+ crypto_info->tls_crypto_info_len = sizeof(crypto_info->ccm128);
+ memcpy(crypto_info->ccm128.iv, iiv + EVP_CCM_TLS_FIXED_IV_LEN,
+ TLS_CIPHER_AES_CCM_128_IV_SIZE);
+ memcpy(crypto_info->ccm128.salt, iiv, TLS_CIPHER_AES_CCM_128_SALT_SIZE);
+ memcpy(crypto_info->ccm128.key, key, EVP_CIPHER_get_key_length(c));
+ memcpy(crypto_info->ccm128.rec_seq, rl_sequence,
+ TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE);
+ if (rec_seq != NULL)
+ *rec_seq = crypto_info->ccm128.rec_seq;
+ return 1;
+# endif
+# ifdef OPENSSL_KTLS_CHACHA20_POLY1305
+ case NID_chacha20_poly1305:
+ crypto_info->chacha20poly1305.info.cipher_type = TLS_CIPHER_CHACHA20_POLY1305;
+ crypto_info->chacha20poly1305.info.version = s->version;
+ crypto_info->tls_crypto_info_len = sizeof(crypto_info->chacha20poly1305);
+ memcpy(crypto_info->chacha20poly1305.iv, iiv,
+ TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
+ memcpy(crypto_info->chacha20poly1305.key, key,
+ EVP_CIPHER_get_key_length(c));
+ memcpy(crypto_info->chacha20poly1305.rec_seq, rl_sequence,
+ TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE);
+ if (rec_seq != NULL)
+ *rec_seq = crypto_info->chacha20poly1305.rec_seq;
+ return 1;
+# endif
+ default:
+ return 0;
+ }
+
+}
+
+#endif /* OPENSSL_SYS_LINUX */
diff --git a/ssl/methods.c b/ssl/methods.c
index c5e8898364cd..525f59e91231 100644
--- a/ssl/methods.c
+++ b/ssl/methods.c
@@ -1,13 +1,14 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
+#include <openssl/macros.h>
#include <openssl/objects.h>
#include "ssl_local.h"
@@ -172,7 +173,7 @@ IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, 0, 0,
DTLS_client_method,
ssl_undefined_function,
ossl_statem_connect, DTLSv1_2_enc_data)
-#if OPENSSL_API_COMPAT < 0x10100000L
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
# ifndef OPENSSL_NO_TLS1_2_METHOD
const SSL_METHOD *TLSv1_2_method(void)
{
diff --git a/ssl/packet.c b/ssl/packet.c
deleted file mode 100644
index d6357495f53e..000000000000
--- a/ssl/packet.c
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "internal/cryptlib.h"
-#include "packet_local.h"
-#include <openssl/sslerr.h>
-
-#define DEFAULT_BUF_SIZE 256
-
-int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
-{
- if (!WPACKET_reserve_bytes(pkt, len, allocbytes))
- return 0;
-
- pkt->written += len;
- pkt->curr += len;
- return 1;
-}
-
-int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len,
- unsigned char **allocbytes, size_t lenbytes)
-{
- if (!WPACKET_start_sub_packet_len__(pkt, lenbytes)
- || !WPACKET_allocate_bytes(pkt, len, allocbytes)
- || !WPACKET_close(pkt))
- return 0;
-
- return 1;
-}
-
-#define GETBUF(p) (((p)->staticbuf != NULL) \
- ? (p)->staticbuf : (unsigned char *)(p)->buf->data)
-
-int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
-{
- /* Internal API, so should not fail */
- if (!ossl_assert(pkt->subs != NULL && len != 0))
- return 0;
-
- if (pkt->maxsize - pkt->written < len)
- return 0;
-
- if (pkt->staticbuf == NULL && (pkt->buf->length - pkt->written < len)) {
- size_t newlen;
- size_t reflen;
-
- reflen = (len > pkt->buf->length) ? len : pkt->buf->length;
-
- if (reflen > SIZE_MAX / 2) {
- newlen = SIZE_MAX;
- } else {
- newlen = reflen * 2;
- if (newlen < DEFAULT_BUF_SIZE)
- newlen = DEFAULT_BUF_SIZE;
- }
- if (BUF_MEM_grow(pkt->buf, newlen) == 0)
- return 0;
- }
- if (allocbytes != NULL)
- *allocbytes = WPACKET_get_curr(pkt);
-
- return 1;
-}
-
-int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len,
- unsigned char **allocbytes, size_t lenbytes)
-{
- if (!WPACKET_reserve_bytes(pkt, lenbytes + len, allocbytes))
- return 0;
-
- *allocbytes += lenbytes;
-
- return 1;
-}
-
-static size_t maxmaxsize(size_t lenbytes)
-{
- if (lenbytes >= sizeof(size_t) || lenbytes == 0)
- return SIZE_MAX;
-
- return ((size_t)1 << (lenbytes * 8)) - 1 + lenbytes;
-}
-
-static int wpacket_intern_init_len(WPACKET *pkt, size_t lenbytes)
-{
- unsigned char *lenchars;
-
- pkt->curr = 0;
- pkt->written = 0;
-
- if ((pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs))) == NULL) {
- SSLerr(SSL_F_WPACKET_INTERN_INIT_LEN, ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- if (lenbytes == 0)
- return 1;
-
- pkt->subs->pwritten = lenbytes;
- pkt->subs->lenbytes = lenbytes;
-
- if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars)) {
- OPENSSL_free(pkt->subs);
- pkt->subs = NULL;
- return 0;
- }
- pkt->subs->packet_len = lenchars - GETBUF(pkt);
-
- return 1;
-}
-
-int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len,
- size_t lenbytes)
-{
- size_t max = maxmaxsize(lenbytes);
-
- /* Internal API, so should not fail */
- if (!ossl_assert(buf != NULL && len > 0))
- return 0;
-
- pkt->staticbuf = buf;
- pkt->buf = NULL;
- pkt->maxsize = (max < len) ? max : len;
-
- return wpacket_intern_init_len(pkt, lenbytes);
-}
-
-int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes)
-{
- /* Internal API, so should not fail */
- if (!ossl_assert(buf != NULL))
- return 0;
-
- pkt->staticbuf = NULL;
- pkt->buf = buf;
- pkt->maxsize = maxmaxsize(lenbytes);
-
- return wpacket_intern_init_len(pkt, lenbytes);
-}
-
-int WPACKET_init(WPACKET *pkt, BUF_MEM *buf)
-{
- return WPACKET_init_len(pkt, buf, 0);
-}
-
-int WPACKET_set_flags(WPACKET *pkt, unsigned int flags)
-{
- /* Internal API, so should not fail */
- if (!ossl_assert(pkt->subs != NULL))
- return 0;
-
- pkt->subs->flags = flags;
-
- return 1;
-}
-
-/* Store the |value| of length |len| at location |data| */
-static int put_value(unsigned char *data, uint64_t value, size_t len)
-{
- for (data += len - 1; len > 0; len--) {
- *data = (unsigned char)(value & 0xff);
- data--;
- value >>= 8;
- }
-
- /* Check whether we could fit the value in the assigned number of bytes */
- if (value > 0)
- return 0;
-
- return 1;
-}
-
-
-/*
- * Internal helper function used by WPACKET_close(), WPACKET_finish() and
- * WPACKET_fill_lengths() to close a sub-packet and write out its length if
- * necessary. If |doclose| is 0 then it goes through the motions of closing
- * (i.e. it fills in all the lengths), but doesn't actually close anything.
- */
-static int wpacket_intern_close(WPACKET *pkt, WPACKET_SUB *sub, int doclose)
-{
- size_t packlen = pkt->written - sub->pwritten;
-
- if (packlen == 0
- && (sub->flags & WPACKET_FLAGS_NON_ZERO_LENGTH) != 0)
- return 0;
-
- if (packlen == 0
- && sub->flags & WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH) {
- /* We can't handle this case. Return an error */
- if (!doclose)
- return 0;
-
- /* Deallocate any bytes allocated for the length of the WPACKET */
- if ((pkt->curr - sub->lenbytes) == sub->packet_len) {
- pkt->written -= sub->lenbytes;
- pkt->curr -= sub->lenbytes;
- }
-
- /* Don't write out the packet length */
- sub->packet_len = 0;
- sub->lenbytes = 0;
- }
-
- /* Write out the WPACKET length if needed */
- if (sub->lenbytes > 0
- && !put_value(&GETBUF(pkt)[sub->packet_len], packlen,
- sub->lenbytes))
- return 0;
-
- if (doclose) {
- pkt->subs = sub->parent;
- OPENSSL_free(sub);
- }
-
- return 1;
-}
-
-int WPACKET_fill_lengths(WPACKET *pkt)
-{
- WPACKET_SUB *sub;
-
- if (!ossl_assert(pkt->subs != NULL))
- return 0;
-
- for (sub = pkt->subs; sub != NULL; sub = sub->parent) {
- if (!wpacket_intern_close(pkt, sub, 0))
- return 0;
- }
-
- return 1;
-}
-
-int WPACKET_close(WPACKET *pkt)
-{
- /*
- * Internal API, so should not fail - but we do negative testing of this
- * so no assert (otherwise the tests fail)
- */
- if (pkt->subs == NULL || pkt->subs->parent == NULL)
- return 0;
-
- return wpacket_intern_close(pkt, pkt->subs, 1);
-}
-
-int WPACKET_finish(WPACKET *pkt)
-{
- int ret;
-
- /*
- * Internal API, so should not fail - but we do negative testing of this
- * so no assert (otherwise the tests fail)
- */
- if (pkt->subs == NULL || pkt->subs->parent != NULL)
- return 0;
-
- ret = wpacket_intern_close(pkt, pkt->subs, 1);
- if (ret) {
- OPENSSL_free(pkt->subs);
- pkt->subs = NULL;
- }
-
- return ret;
-}
-
-int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes)
-{
- WPACKET_SUB *sub;
- unsigned char *lenchars;
-
- /* Internal API, so should not fail */
- if (!ossl_assert(pkt->subs != NULL))
- return 0;
-
- if ((sub = OPENSSL_zalloc(sizeof(*sub))) == NULL) {
- SSLerr(SSL_F_WPACKET_START_SUB_PACKET_LEN__, ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- sub->parent = pkt->subs;
- pkt->subs = sub;
- sub->pwritten = pkt->written + lenbytes;
- sub->lenbytes = lenbytes;
-
- if (lenbytes == 0) {
- sub->packet_len = 0;
- return 1;
- }
-
- if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars))
- return 0;
- /* Convert to an offset in case the underlying BUF_MEM gets realloc'd */
- sub->packet_len = lenchars - GETBUF(pkt);
-
- return 1;
-}
-
-int WPACKET_start_sub_packet(WPACKET *pkt)
-{
- return WPACKET_start_sub_packet_len__(pkt, 0);
-}
-
-int WPACKET_put_bytes__(WPACKET *pkt, uint64_t val, size_t size)
-{
- unsigned char *data;
-
- /* Internal API, so should not fail */
- if (!ossl_assert(size <= sizeof(uint64_t))
- || !WPACKET_allocate_bytes(pkt, size, &data)
- || !put_value(data, val, size))
- return 0;
-
- return 1;
-}
-
-int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize)
-{
- WPACKET_SUB *sub;
- size_t lenbytes;
-
- /* Internal API, so should not fail */
- if (!ossl_assert(pkt->subs != NULL))
- return 0;
-
- /* Find the WPACKET_SUB for the top level */
- for (sub = pkt->subs; sub->parent != NULL; sub = sub->parent)
- continue;
-
- lenbytes = sub->lenbytes;
- if (lenbytes == 0)
- lenbytes = sizeof(pkt->maxsize);
-
- if (maxmaxsize(lenbytes) < maxsize || maxsize < pkt->written)
- return 0;
-
- pkt->maxsize = maxsize;
-
- return 1;
-}
-
-int WPACKET_memset(WPACKET *pkt, int ch, size_t len)
-{
- unsigned char *dest;
-
- if (len == 0)
- return 1;
-
- if (!WPACKET_allocate_bytes(pkt, len, &dest))
- return 0;
-
- memset(dest, ch, len);
-
- return 1;
-}
-
-int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len)
-{
- unsigned char *dest;
-
- if (len == 0)
- return 1;
-
- if (!WPACKET_allocate_bytes(pkt, len, &dest))
- return 0;
-
- memcpy(dest, src, len);
-
- return 1;
-}
-
-int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len,
- size_t lenbytes)
-{
- if (!WPACKET_start_sub_packet_len__(pkt, lenbytes)
- || !WPACKET_memcpy(pkt, src, len)
- || !WPACKET_close(pkt))
- return 0;
-
- return 1;
-}
-
-int WPACKET_get_total_written(WPACKET *pkt, size_t *written)
-{
- /* Internal API, so should not fail */
- if (!ossl_assert(written != NULL))
- return 0;
-
- *written = pkt->written;
-
- return 1;
-}
-
-int WPACKET_get_length(WPACKET *pkt, size_t *len)
-{
- /* Internal API, so should not fail */
- if (!ossl_assert(pkt->subs != NULL && len != NULL))
- return 0;
-
- *len = pkt->written - pkt->subs->pwritten;
-
- return 1;
-}
-
-unsigned char *WPACKET_get_curr(WPACKET *pkt)
-{
- return GETBUF(pkt) + pkt->curr;
-}
-
-void WPACKET_cleanup(WPACKET *pkt)
-{
- WPACKET_SUB *sub, *parent;
-
- for (sub = pkt->subs; sub != NULL; sub = parent) {
- parent = sub->parent;
- OPENSSL_free(sub);
- }
- pkt->subs = NULL;
-}
diff --git a/ssl/packet_local.h b/ssl/packet_local.h
deleted file mode 100644
index 5b1d3fe56edb..000000000000
--- a/ssl/packet_local.h
+++ /dev/null
@@ -1,909 +0,0 @@
-/*
- * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef OSSL_SSL_PACKET_LOCAL_H
-# define OSSL_SSL_PACKET_LOCAL_H
-
-# include <string.h>
-# include <openssl/bn.h>
-# include <openssl/buffer.h>
-# include <openssl/crypto.h>
-# include <openssl/e_os2.h>
-
-# include "internal/numbers.h"
-
-typedef struct {
- /* Pointer to where we are currently reading from */
- const unsigned char *curr;
- /* Number of bytes remaining */
- size_t remaining;
-} PACKET;
-
-/* Internal unchecked shorthand; don't use outside this file. */
-static ossl_inline void packet_forward(PACKET *pkt, size_t len)
-{
- pkt->curr += len;
- pkt->remaining -= len;
-}
-
-/*
- * Returns the number of bytes remaining to be read in the PACKET
- */
-static ossl_inline size_t PACKET_remaining(const PACKET *pkt)
-{
- return pkt->remaining;
-}
-
-/*
- * Returns a pointer to the first byte after the packet data.
- * Useful for integrating with non-PACKET parsing code.
- * Specifically, we use PACKET_end() to verify that a d2i_... call
- * has consumed the entire packet contents.
- */
-static ossl_inline const unsigned char *PACKET_end(const PACKET *pkt)
-{
- return pkt->curr + pkt->remaining;
-}
-
-/*
- * Returns a pointer to the PACKET's current position.
- * For use in non-PACKETized APIs.
- */
-static ossl_inline const unsigned char *PACKET_data(const PACKET *pkt)
-{
- return pkt->curr;
-}
-
-/*
- * Initialise a PACKET with |len| bytes held in |buf|. This does not make a
- * copy of the data so |buf| must be present for the whole time that the PACKET
- * is being used.
- */
-__owur static ossl_inline int PACKET_buf_init(PACKET *pkt,
- const unsigned char *buf,
- size_t len)
-{
- /* Sanity check for negative values. */
- if (len > (size_t)(SIZE_MAX / 2))
- return 0;
-
- pkt->curr = buf;
- pkt->remaining = len;
- return 1;
-}
-
-/* Initialize a PACKET to hold zero bytes. */
-static ossl_inline void PACKET_null_init(PACKET *pkt)
-{
- pkt->curr = NULL;
- pkt->remaining = 0;
-}
-
-/*
- * Returns 1 if the packet has length |num| and its contents equal the |num|
- * bytes read from |ptr|. Returns 0 otherwise (lengths or contents not equal).
- * If lengths are equal, performs the comparison in constant time.
- */
-__owur static ossl_inline int PACKET_equal(const PACKET *pkt, const void *ptr,
- size_t num)
-{
- if (PACKET_remaining(pkt) != num)
- return 0;
- return CRYPTO_memcmp(pkt->curr, ptr, num) == 0;
-}
-
-/*
- * Peek ahead and initialize |subpkt| with the next |len| bytes read from |pkt|.
- * Data is not copied: the |subpkt| packet will share its underlying buffer with
- * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
- */
-__owur static ossl_inline int PACKET_peek_sub_packet(const PACKET *pkt,
- PACKET *subpkt, size_t len)
-{
- if (PACKET_remaining(pkt) < len)
- return 0;
-
- return PACKET_buf_init(subpkt, pkt->curr, len);
-}
-
-/*
- * Initialize |subpkt| with the next |len| bytes read from |pkt|. Data is not
- * copied: the |subpkt| packet will share its underlying buffer with the
- * original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
- */
-__owur static ossl_inline int PACKET_get_sub_packet(PACKET *pkt,
- PACKET *subpkt, size_t len)
-{
- if (!PACKET_peek_sub_packet(pkt, subpkt, len))
- return 0;
-
- packet_forward(pkt, len);
-
- return 1;
-}
-
-/*
- * Peek ahead at 2 bytes in network order from |pkt| and store the value in
- * |*data|
- */
-__owur static ossl_inline int PACKET_peek_net_2(const PACKET *pkt,
- unsigned int *data)
-{
- if (PACKET_remaining(pkt) < 2)
- return 0;
-
- *data = ((unsigned int)(*pkt->curr)) << 8;
- *data |= *(pkt->curr + 1);
-
- return 1;
-}
-
-/* Equivalent of n2s */
-/* Get 2 bytes in network order from |pkt| and store the value in |*data| */
-__owur static ossl_inline int PACKET_get_net_2(PACKET *pkt, unsigned int *data)
-{
- if (!PACKET_peek_net_2(pkt, data))
- return 0;
-
- packet_forward(pkt, 2);
-
- return 1;
-}
-
-/* Same as PACKET_get_net_2() but for a size_t */
-__owur static ossl_inline int PACKET_get_net_2_len(PACKET *pkt, size_t *data)
-{
- unsigned int i;
- int ret = PACKET_get_net_2(pkt, &i);
-
- if (ret)
- *data = (size_t)i;
-
- return ret;
-}
-
-/*
- * Peek ahead at 3 bytes in network order from |pkt| and store the value in
- * |*data|
- */
-__owur static ossl_inline int PACKET_peek_net_3(const PACKET *pkt,
- unsigned long *data)
-{
- if (PACKET_remaining(pkt) < 3)
- return 0;
-
- *data = ((unsigned long)(*pkt->curr)) << 16;
- *data |= ((unsigned long)(*(pkt->curr + 1))) << 8;
- *data |= *(pkt->curr + 2);
-
- return 1;
-}
-
-/* Equivalent of n2l3 */
-/* Get 3 bytes in network order from |pkt| and store the value in |*data| */
-__owur static ossl_inline int PACKET_get_net_3(PACKET *pkt, unsigned long *data)
-{
- if (!PACKET_peek_net_3(pkt, data))
- return 0;
-
- packet_forward(pkt, 3);
-
- return 1;
-}
-
-/* Same as PACKET_get_net_3() but for a size_t */
-__owur static ossl_inline int PACKET_get_net_3_len(PACKET *pkt, size_t *data)
-{
- unsigned long i;
- int ret = PACKET_get_net_3(pkt, &i);
-
- if (ret)
- *data = (size_t)i;
-
- return ret;
-}
-
-/*
- * Peek ahead at 4 bytes in network order from |pkt| and store the value in
- * |*data|
- */
-__owur static ossl_inline int PACKET_peek_net_4(const PACKET *pkt,
- unsigned long *data)
-{
- if (PACKET_remaining(pkt) < 4)
- return 0;
-
- *data = ((unsigned long)(*pkt->curr)) << 24;
- *data |= ((unsigned long)(*(pkt->curr + 1))) << 16;
- *data |= ((unsigned long)(*(pkt->curr + 2))) << 8;
- *data |= *(pkt->curr + 3);
-
- return 1;
-}
-
-/*
- * Peek ahead at 8 bytes in network order from |pkt| and store the value in
- * |*data|
- */
-__owur static ossl_inline int PACKET_peek_net_8(const PACKET *pkt,
- uint64_t *data)
-{
- if (PACKET_remaining(pkt) < 8)
- return 0;
-
- *data = ((uint64_t)(*pkt->curr)) << 56;
- *data |= ((uint64_t)(*(pkt->curr + 1))) << 48;
- *data |= ((uint64_t)(*(pkt->curr + 2))) << 40;
- *data |= ((uint64_t)(*(pkt->curr + 3))) << 32;
- *data |= ((uint64_t)(*(pkt->curr + 4))) << 24;
- *data |= ((uint64_t)(*(pkt->curr + 5))) << 16;
- *data |= ((uint64_t)(*(pkt->curr + 6))) << 8;
- *data |= *(pkt->curr + 7);
-
- return 1;
-}
-
-/* Equivalent of n2l */
-/* Get 4 bytes in network order from |pkt| and store the value in |*data| */
-__owur static ossl_inline int PACKET_get_net_4(PACKET *pkt, unsigned long *data)
-{
- if (!PACKET_peek_net_4(pkt, data))
- return 0;
-
- packet_forward(pkt, 4);
-
- return 1;
-}
-
-/* Same as PACKET_get_net_4() but for a size_t */
-__owur static ossl_inline int PACKET_get_net_4_len(PACKET *pkt, size_t *data)
-{
- unsigned long i;
- int ret = PACKET_get_net_4(pkt, &i);
-
- if (ret)
- *data = (size_t)i;
-
- return ret;
-}
-
-/* Get 8 bytes in network order from |pkt| and store the value in |*data| */
-__owur static ossl_inline int PACKET_get_net_8(PACKET *pkt, uint64_t *data)
-{
- if (!PACKET_peek_net_8(pkt, data))
- return 0;
-
- packet_forward(pkt, 8);
-
- return 1;
-}
-
-/* Peek ahead at 1 byte from |pkt| and store the value in |*data| */
-__owur static ossl_inline int PACKET_peek_1(const PACKET *pkt,
- unsigned int *data)
-{
- if (!PACKET_remaining(pkt))
- return 0;
-
- *data = *pkt->curr;
-
- return 1;
-}
-
-/* Get 1 byte from |pkt| and store the value in |*data| */
-__owur static ossl_inline int PACKET_get_1(PACKET *pkt, unsigned int *data)
-{
- if (!PACKET_peek_1(pkt, data))
- return 0;
-
- packet_forward(pkt, 1);
-
- return 1;
-}
-
-/* Same as PACKET_get_1() but for a size_t */
-__owur static ossl_inline int PACKET_get_1_len(PACKET *pkt, size_t *data)
-{
- unsigned int i;
- int ret = PACKET_get_1(pkt, &i);
-
- if (ret)
- *data = (size_t)i;
-
- return ret;
-}
-
-/*
- * Peek ahead at 4 bytes in reverse network order from |pkt| and store the value
- * in |*data|
- */
-__owur static ossl_inline int PACKET_peek_4(const PACKET *pkt,
- unsigned long *data)
-{
- if (PACKET_remaining(pkt) < 4)
- return 0;
-
- *data = *pkt->curr;
- *data |= ((unsigned long)(*(pkt->curr + 1))) << 8;
- *data |= ((unsigned long)(*(pkt->curr + 2))) << 16;
- *data |= ((unsigned long)(*(pkt->curr + 3))) << 24;
-
- return 1;
-}
-
-/* Equivalent of c2l */
-/*
- * Get 4 bytes in reverse network order from |pkt| and store the value in
- * |*data|
- */
-__owur static ossl_inline int PACKET_get_4(PACKET *pkt, unsigned long *data)
-{
- if (!PACKET_peek_4(pkt, data))
- return 0;
-
- packet_forward(pkt, 4);
-
- return 1;
-}
-
-/*
- * Peek ahead at |len| bytes from the |pkt| and store a pointer to them in
- * |*data|. This just points at the underlying buffer that |pkt| is using. The
- * caller should not free this data directly (it will be freed when the
- * underlying buffer gets freed
- */
-__owur static ossl_inline int PACKET_peek_bytes(const PACKET *pkt,
- const unsigned char **data,
- size_t len)
-{
- if (PACKET_remaining(pkt) < len)
- return 0;
-
- *data = pkt->curr;
-
- return 1;
-}
-
-/*
- * Read |len| bytes from the |pkt| and store a pointer to them in |*data|. This
- * just points at the underlying buffer that |pkt| is using. The caller should
- * not free this data directly (it will be freed when the underlying buffer gets
- * freed
- */
-__owur static ossl_inline int PACKET_get_bytes(PACKET *pkt,
- const unsigned char **data,
- size_t len)
-{
- if (!PACKET_peek_bytes(pkt, data, len))
- return 0;
-
- packet_forward(pkt, len);
-
- return 1;
-}
-
-/* Peek ahead at |len| bytes from |pkt| and copy them to |data| */
-__owur static ossl_inline int PACKET_peek_copy_bytes(const PACKET *pkt,
- unsigned char *data,
- size_t len)
-{
- if (PACKET_remaining(pkt) < len)
- return 0;
-
- memcpy(data, pkt->curr, len);
-
- return 1;
-}
-
-/*
- * Read |len| bytes from |pkt| and copy them to |data|.
- * The caller is responsible for ensuring that |data| can hold |len| bytes.
- */
-__owur static ossl_inline int PACKET_copy_bytes(PACKET *pkt,
- unsigned char *data, size_t len)
-{
- if (!PACKET_peek_copy_bytes(pkt, data, len))
- return 0;
-
- packet_forward(pkt, len);
-
- return 1;
-}
-
-/*
- * Copy packet data to |dest|, and set |len| to the number of copied bytes.
- * If the packet has more than |dest_len| bytes, nothing is copied.
- * Returns 1 if the packet data fits in |dest_len| bytes, 0 otherwise.
- * Does not forward PACKET position (because it is typically the last thing
- * done with a given PACKET).
- */
-__owur static ossl_inline int PACKET_copy_all(const PACKET *pkt,
- unsigned char *dest,
- size_t dest_len, size_t *len)
-{
- if (PACKET_remaining(pkt) > dest_len) {
- *len = 0;
- return 0;
- }
- *len = pkt->remaining;
- memcpy(dest, pkt->curr, pkt->remaining);
- return 1;
-}
-
-/*
- * Copy |pkt| bytes to a newly allocated buffer and store a pointer to the
- * result in |*data|, and the length in |len|.
- * If |*data| is not NULL, the old data is OPENSSL_free'd.
- * If the packet is empty, or malloc fails, |*data| will be set to NULL.
- * Returns 1 if the malloc succeeds and 0 otherwise.
- * Does not forward PACKET position (because it is typically the last thing
- * done with a given PACKET).
- */
-__owur static ossl_inline int PACKET_memdup(const PACKET *pkt,
- unsigned char **data, size_t *len)
-{
- size_t length;
-
- OPENSSL_free(*data);
- *data = NULL;
- *len = 0;
-
- length = PACKET_remaining(pkt);
-
- if (length == 0)
- return 1;
-
- *data = OPENSSL_memdup(pkt->curr, length);
- if (*data == NULL)
- return 0;
-
- *len = length;
- return 1;
-}
-
-/*
- * Read a C string from |pkt| and copy to a newly allocated, NUL-terminated
- * buffer. Store a pointer to the result in |*data|.
- * If |*data| is not NULL, the old data is OPENSSL_free'd.
- * If the data in |pkt| does not contain a NUL-byte, the entire data is
- * copied and NUL-terminated.
- * Returns 1 if the malloc succeeds and 0 otherwise.
- * Does not forward PACKET position (because it is typically the last thing done
- * with a given PACKET).
- */
-__owur static ossl_inline int PACKET_strndup(const PACKET *pkt, char **data)
-{
- OPENSSL_free(*data);
-
- /* This will succeed on an empty packet, unless pkt->curr == NULL. */
- *data = OPENSSL_strndup((const char *)pkt->curr, PACKET_remaining(pkt));
- return (*data != NULL);
-}
-
-/* Returns 1 if |pkt| contains at least one 0-byte, 0 otherwise. */
-static ossl_inline int PACKET_contains_zero_byte(const PACKET *pkt)
-{
- return memchr(pkt->curr, 0, pkt->remaining) != NULL;
-}
-
-/* Move the current reading position forward |len| bytes */
-__owur static ossl_inline int PACKET_forward(PACKET *pkt, size_t len)
-{
- if (PACKET_remaining(pkt) < len)
- return 0;
-
- packet_forward(pkt, len);
-
- return 1;
-}
-
-/*
- * Reads a variable-length vector prefixed with a one-byte length, and stores
- * the contents in |subpkt|. |pkt| can equal |subpkt|.
- * Data is not copied: the |subpkt| packet will share its underlying buffer with
- * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
- * Upon failure, the original |pkt| and |subpkt| are not modified.
- */
-__owur static ossl_inline int PACKET_get_length_prefixed_1(PACKET *pkt,
- PACKET *subpkt)
-{
- unsigned int length;
- const unsigned char *data;
- PACKET tmp = *pkt;
- if (!PACKET_get_1(&tmp, &length) ||
- !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
- return 0;
- }
-
- *pkt = tmp;
- subpkt->curr = data;
- subpkt->remaining = length;
-
- return 1;
-}
-
-/*
- * Like PACKET_get_length_prefixed_1, but additionally, fails when there are
- * leftover bytes in |pkt|.
- */
-__owur static ossl_inline int PACKET_as_length_prefixed_1(PACKET *pkt,
- PACKET *subpkt)
-{
- unsigned int length;
- const unsigned char *data;
- PACKET tmp = *pkt;
- if (!PACKET_get_1(&tmp, &length) ||
- !PACKET_get_bytes(&tmp, &data, (size_t)length) ||
- PACKET_remaining(&tmp) != 0) {
- return 0;
- }
-
- *pkt = tmp;
- subpkt->curr = data;
- subpkt->remaining = length;
-
- return 1;
-}
-
-/*
- * Reads a variable-length vector prefixed with a two-byte length, and stores
- * the contents in |subpkt|. |pkt| can equal |subpkt|.
- * Data is not copied: the |subpkt| packet will share its underlying buffer with
- * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
- * Upon failure, the original |pkt| and |subpkt| are not modified.
- */
-__owur static ossl_inline int PACKET_get_length_prefixed_2(PACKET *pkt,
- PACKET *subpkt)
-{
- unsigned int length;
- const unsigned char *data;
- PACKET tmp = *pkt;
-
- if (!PACKET_get_net_2(&tmp, &length) ||
- !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
- return 0;
- }
-
- *pkt = tmp;
- subpkt->curr = data;
- subpkt->remaining = length;
-
- return 1;
-}
-
-/*
- * Like PACKET_get_length_prefixed_2, but additionally, fails when there are
- * leftover bytes in |pkt|.
- */
-__owur static ossl_inline int PACKET_as_length_prefixed_2(PACKET *pkt,
- PACKET *subpkt)
-{
- unsigned int length;
- const unsigned char *data;
- PACKET tmp = *pkt;
-
- if (!PACKET_get_net_2(&tmp, &length) ||
- !PACKET_get_bytes(&tmp, &data, (size_t)length) ||
- PACKET_remaining(&tmp) != 0) {
- return 0;
- }
-
- *pkt = tmp;
- subpkt->curr = data;
- subpkt->remaining = length;
-
- return 1;
-}
-
-/*
- * Reads a variable-length vector prefixed with a three-byte length, and stores
- * the contents in |subpkt|. |pkt| can equal |subpkt|.
- * Data is not copied: the |subpkt| packet will share its underlying buffer with
- * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
- * Upon failure, the original |pkt| and |subpkt| are not modified.
- */
-__owur static ossl_inline int PACKET_get_length_prefixed_3(PACKET *pkt,
- PACKET *subpkt)
-{
- unsigned long length;
- const unsigned char *data;
- PACKET tmp = *pkt;
- if (!PACKET_get_net_3(&tmp, &length) ||
- !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
- return 0;
- }
-
- *pkt = tmp;
- subpkt->curr = data;
- subpkt->remaining = length;
-
- return 1;
-}
-
-/* Writeable packets */
-
-typedef struct wpacket_sub WPACKET_SUB;
-struct wpacket_sub {
- /* The parent WPACKET_SUB if we have one or NULL otherwise */
- WPACKET_SUB *parent;
-
- /*
- * Offset into the buffer where the length of this WPACKET goes. We use an
- * offset in case the buffer grows and gets reallocated.
- */
- size_t packet_len;
-
- /* Number of bytes in the packet_len or 0 if we don't write the length */
- size_t lenbytes;
-
- /* Number of bytes written to the buf prior to this packet starting */
- size_t pwritten;
-
- /* Flags for this sub-packet */
- unsigned int flags;
-};
-
-typedef struct wpacket_st WPACKET;
-struct wpacket_st {
- /* The buffer where we store the output data */
- BUF_MEM *buf;
-
- /* Fixed sized buffer which can be used as an alternative to buf */
- unsigned char *staticbuf;
-
- /*
- * Offset into the buffer where we are currently writing. We use an offset
- * in case the buffer grows and gets reallocated.
- */
- size_t curr;
-
- /* Number of bytes written so far */
- size_t written;
-
- /* Maximum number of bytes we will allow to be written to this WPACKET */
- size_t maxsize;
-
- /* Our sub-packets (always at least one if not finished) */
- WPACKET_SUB *subs;
-};
-
-/* Flags */
-
-/* Default */
-#define WPACKET_FLAGS_NONE 0
-
-/* Error on WPACKET_close() if no data written to the WPACKET */
-#define WPACKET_FLAGS_NON_ZERO_LENGTH 1
-
-/*
- * Abandon all changes on WPACKET_close() if no data written to the WPACKET,
- * i.e. this does not write out a zero packet length
- */
-#define WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH 2
-
-
-/*
- * Initialise a WPACKET with the buffer in |buf|. The buffer must exist
- * for the whole time that the WPACKET is being used. Additionally |lenbytes| of
- * data is preallocated at the start of the buffer to store the length of the
- * WPACKET once we know it.
- */
-int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes);
-
-/*
- * Same as WPACKET_init_len except there is no preallocation of the WPACKET
- * length.
- */
-int WPACKET_init(WPACKET *pkt, BUF_MEM *buf);
-
-/*
- * Same as WPACKET_init_len except we do not use a growable BUF_MEM structure.
- * A fixed buffer of memory |buf| of size |len| is used instead. A failure will
- * occur if you attempt to write beyond the end of the buffer
- */
-int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len,
- size_t lenbytes);
-/*
- * Set the flags to be applied to the current sub-packet
- */
-int WPACKET_set_flags(WPACKET *pkt, unsigned int flags);
-
-/*
- * Closes the most recent sub-packet. It also writes out the length of the
- * packet to the required location (normally the start of the WPACKET) if
- * appropriate. The top level WPACKET should be closed using WPACKET_finish()
- * instead of this function.
- */
-int WPACKET_close(WPACKET *pkt);
-
-/*
- * The same as WPACKET_close() but only for the top most WPACKET. Additionally
- * frees memory resources for this WPACKET.
- */
-int WPACKET_finish(WPACKET *pkt);
-
-/*
- * Iterate through all the sub-packets and write out their lengths as if they
- * were being closed. The lengths will be overwritten with the final lengths
- * when the sub-packets are eventually closed (which may be different if more
- * data is added to the WPACKET). This function fails if a sub-packet is of 0
- * length and WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH is set.
- */
-int WPACKET_fill_lengths(WPACKET *pkt);
-
-/*
- * Initialise a new sub-packet. Additionally |lenbytes| of data is preallocated
- * at the start of the sub-packet to store its length once we know it. Don't
- * call this directly. Use the convenience macros below instead.
- */
-int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes);
-
-/*
- * Convenience macros for calling WPACKET_start_sub_packet_len with different
- * lengths
- */
-#define WPACKET_start_sub_packet_u8(pkt) \
- WPACKET_start_sub_packet_len__((pkt), 1)
-#define WPACKET_start_sub_packet_u16(pkt) \
- WPACKET_start_sub_packet_len__((pkt), 2)
-#define WPACKET_start_sub_packet_u24(pkt) \
- WPACKET_start_sub_packet_len__((pkt), 3)
-#define WPACKET_start_sub_packet_u32(pkt) \
- WPACKET_start_sub_packet_len__((pkt), 4)
-
-/*
- * Same as WPACKET_start_sub_packet_len__() except no bytes are pre-allocated
- * for the sub-packet length.
- */
-int WPACKET_start_sub_packet(WPACKET *pkt);
-
-/*
- * Allocate bytes in the WPACKET for the output. This reserves the bytes
- * and counts them as "written", but doesn't actually do the writing. A pointer
- * to the allocated bytes is stored in |*allocbytes|. |allocbytes| may be NULL.
- * WARNING: the allocated bytes must be filled in immediately, without further
- * WPACKET_* calls. If not then the underlying buffer may be realloc'd and
- * change its location.
- */
-int WPACKET_allocate_bytes(WPACKET *pkt, size_t len,
- unsigned char **allocbytes);
-
-/*
- * The same as WPACKET_allocate_bytes() except additionally a new sub-packet is
- * started for the allocated bytes, and then closed immediately afterwards. The
- * number of length bytes for the sub-packet is in |lenbytes|. Don't call this
- * directly. Use the convenience macros below instead.
- */
-int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len,
- unsigned char **allocbytes, size_t lenbytes);
-
-/*
- * Convenience macros for calling WPACKET_sub_allocate_bytes with different
- * lengths
- */
-#define WPACKET_sub_allocate_bytes_u8(pkt, len, bytes) \
- WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 1)
-#define WPACKET_sub_allocate_bytes_u16(pkt, len, bytes) \
- WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 2)
-#define WPACKET_sub_allocate_bytes_u24(pkt, len, bytes) \
- WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 3)
-#define WPACKET_sub_allocate_bytes_u32(pkt, len, bytes) \
- WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 4)
-
-/*
- * The same as WPACKET_allocate_bytes() except the reserved bytes are not
- * actually counted as written. Typically this will be for when we don't know
- * how big arbitrary data is going to be up front, but we do know what the
- * maximum size will be. If this function is used, then it should be immediately
- * followed by a WPACKET_allocate_bytes() call before any other WPACKET
- * functions are called (unless the write to the allocated bytes is abandoned).
- *
- * For example: If we are generating a signature, then the size of that
- * signature may not be known in advance. We can use WPACKET_reserve_bytes() to
- * handle this:
- *
- * if (!WPACKET_sub_reserve_bytes_u16(&pkt, EVP_PKEY_size(pkey), &sigbytes1)
- * || EVP_SignFinal(md_ctx, sigbytes1, &siglen, pkey) <= 0
- * || !WPACKET_sub_allocate_bytes_u16(&pkt, siglen, &sigbytes2)
- * || sigbytes1 != sigbytes2)
- * goto err;
- */
-int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes);
-
-/*
- * The "reserve_bytes" equivalent of WPACKET_sub_allocate_bytes__()
- */
-int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len,
- unsigned char **allocbytes, size_t lenbytes);
-
-/*
- * Convenience macros for WPACKET_sub_reserve_bytes with different lengths
- */
-#define WPACKET_sub_reserve_bytes_u8(pkt, len, bytes) \
- WPACKET_reserve_bytes__((pkt), (len), (bytes), 1)
-#define WPACKET_sub_reserve_bytes_u16(pkt, len, bytes) \
- WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 2)
-#define WPACKET_sub_reserve_bytes_u24(pkt, len, bytes) \
- WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 3)
-#define WPACKET_sub_reserve_bytes_u32(pkt, len, bytes) \
- WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 4)
-
-/*
- * Write the value stored in |val| into the WPACKET. The value will consume
- * |bytes| amount of storage. An error will occur if |val| cannot be
- * accommodated in |bytes| storage, e.g. attempting to write the value 256 into
- * 1 byte will fail. Don't call this directly. Use the convenience macros below
- * instead.
- */
-int WPACKET_put_bytes__(WPACKET *pkt, uint64_t val, size_t bytes);
-
-/*
- * Convenience macros for calling WPACKET_put_bytes with different
- * lengths
- */
-#define WPACKET_put_bytes_u8(pkt, val) \
- WPACKET_put_bytes__((pkt), (val), 1)
-#define WPACKET_put_bytes_u16(pkt, val) \
- WPACKET_put_bytes__((pkt), (val), 2)
-#define WPACKET_put_bytes_u24(pkt, val) \
- WPACKET_put_bytes__((pkt), (val), 3)
-#define WPACKET_put_bytes_u32(pkt, val) \
- WPACKET_put_bytes__((pkt), (val), 4)
-#define WPACKET_put_bytes_u64(pkt, val) \
- WPACKET_put_bytes__((pkt), (val), 8)
-
-/* Set a maximum size that we will not allow the WPACKET to grow beyond */
-int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize);
-
-/* Copy |len| bytes of data from |*src| into the WPACKET. */
-int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len);
-
-/* Set |len| bytes of data to |ch| into the WPACKET. */
-int WPACKET_memset(WPACKET *pkt, int ch, size_t len);
-
-/*
- * Copy |len| bytes of data from |*src| into the WPACKET and prefix with its
- * length (consuming |lenbytes| of data for the length). Don't call this
- * directly. Use the convenience macros below instead.
- */
-int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len,
- size_t lenbytes);
-
-/* Convenience macros for calling WPACKET_sub_memcpy with different lengths */
-#define WPACKET_sub_memcpy_u8(pkt, src, len) \
- WPACKET_sub_memcpy__((pkt), (src), (len), 1)
-#define WPACKET_sub_memcpy_u16(pkt, src, len) \
- WPACKET_sub_memcpy__((pkt), (src), (len), 2)
-#define WPACKET_sub_memcpy_u24(pkt, src, len) \
- WPACKET_sub_memcpy__((pkt), (src), (len), 3)
-#define WPACKET_sub_memcpy_u32(pkt, src, len) \
- WPACKET_sub_memcpy__((pkt), (src), (len), 4)
-
-/*
- * Return the total number of bytes written so far to the underlying buffer
- * including any storage allocated for length bytes
- */
-int WPACKET_get_total_written(WPACKET *pkt, size_t *written);
-
-/*
- * Returns the length of the current sub-packet. This excludes any bytes
- * allocated for the length itself.
- */
-int WPACKET_get_length(WPACKET *pkt, size_t *len);
-
-/*
- * Returns a pointer to the current write location, but does not allocate any
- * bytes.
- */
-unsigned char *WPACKET_get_curr(WPACKET *pkt);
-
-/* Release resources in a WPACKET if a failure has occurred. */
-void WPACKET_cleanup(WPACKET *pkt);
-
-#endif /* OSSL_SSL_PACKET_LOCAL_H */
diff --git a/ssl/pqueue.c b/ssl/pqueue.c
index 758440217d45..0852aceacff7 100644
--- a/ssl/pqueue.c
+++ b/ssl/pqueue.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -20,7 +20,7 @@ pitem *pitem_new(unsigned char *prio64be, void *data)
pitem *item = OPENSSL_malloc(sizeof(*item));
if (item == NULL) {
- SSLerr(SSL_F_PITEM_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -40,7 +40,7 @@ pqueue *pqueue_new(void)
pqueue *pq = OPENSSL_zalloc(sizeof(*pq));
if (pq == NULL)
- SSLerr(SSL_F_PQUEUE_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return pq;
}
diff --git a/ssl/record/README b/ssl/record/README
deleted file mode 100644
index 630fe8027af1..000000000000
--- a/ssl/record/README
+++ /dev/null
@@ -1,74 +0,0 @@
-Record Layer Design
-===================
-
-This file provides some guidance on the thinking behind the design of the
-record layer code to aid future maintenance.
-
-The record layer is divided into a number of components. At the time of writing
-there are four: SSL3_RECORD, SSL3_BUFFER, DLTS1_BITMAP and RECORD_LAYER. Each
-of these components is defined by:
-1) A struct definition of the same name as the component
-2) A set of source files that define the functions for that component
-3) A set of accessor macros
-
-All struct definitions are in record.h. The functions and macros are either
-defined in record.h or record_local.h dependent on whether they are intended to
-be private to the record layer, or whether they form part of the API to the rest
-of libssl.
-
-The source files map to components as follows:
-
-dtls1_bitmap.c -> DTLS1_BITMAP component
-ssl3_buffer.c -> SSL3_BUFFER component
-ssl3_record.c -> SSL3_RECORD component
-rec_layer_s3.c, rec_layer_d1.c -> RECORD_LAYER component
-
-The RECORD_LAYER component is a facade pattern, i.e. it provides a simplified
-interface to the record layer for the rest of libssl. The other 3 components are
-entirely private to the record layer and therefore should never be accessed
-directly by libssl.
-
-Any component can directly access its own members - they are private to that
-component, e.g. ssl3_buffer.c can access members of the SSL3_BUFFER struct
-without using a macro. No component can directly access the members of another
-component, e.g. ssl3_buffer cannot reach inside the RECORD_LAYER component to
-directly access its members. Instead components use accessor macros, so if code
-in ssl3_buffer.c wants to access the members of the RECORD_LAYER it uses the
-RECORD_LAYER_* macros.
-
-Conceptually it looks like this:
-
- libssl
- |
----------------------------|-----record.h--------------------------------------
- |
- _______V______________
- | |
- | RECORD_LAYER |
- | |
- | rec_layer_s3.c |
- | ^ |
- | _________|__________ |
- || ||
- || DTLS1_RECORD_LAYER ||
- || ||
- || rec_layer_d1.c ||
- ||____________________||
- |______________________|
- record_local.h ^ ^ ^
- _________________| | |_________________
- | | |
- _____V_________ ______V________ _______V________
- | | | | | |
- | SSL3_BUFFER | | SSL3_RECORD | | DTLS1_BITMAP |
- | |--->| | | |
- | ssl3_buffer.c | | ssl3_record.c | | dtls1_bitmap.c |
- |_______________| |_______________| |________________|
-
-
-The two RECORD_LAYER source files build on each other, i.e.
-the main one is rec_layer_s3.c which provides the core SSL/TLS layer. The second
-one is rec_layer_d1.c which builds off of the SSL/TLS code to provide DTLS
-specific capabilities. It uses some DTLS specific RECORD_LAYER component members
-which should only be accessed from rec_layer_d1.c. These are held in the
-DTLS1_RECORD_LAYER struct.
diff --git a/ssl/record/README.md b/ssl/record/README.md
new file mode 100644
index 000000000000..263f257c84c4
--- /dev/null
+++ b/ssl/record/README.md
@@ -0,0 +1,73 @@
+Record Layer Design
+===================
+
+This file provides some guidance on the thinking behind the design of the
+record layer code to aid future maintenance.
+
+The record layer is divided into a number of components. At the time of writing
+there are four: SSL3_RECORD, SSL3_BUFFER, DLTS1_BITMAP and RECORD_LAYER. Each
+of these components is defined by:
+1) A struct definition of the same name as the component
+2) A set of source files that define the functions for that component
+3) A set of accessor macros
+
+All struct definitions are in record.h. The functions and macros are either
+defined in record.h or record_local.h dependent on whether they are intended to
+be private to the record layer, or whether they form part of the API to the rest
+of libssl.
+
+The source files map to components as follows:
+
+ dtls1_bitmap.c -> DTLS1_BITMAP component
+ ssl3_buffer.c -> SSL3_BUFFER component
+ ssl3_record.c -> SSL3_RECORD component
+ rec_layer_s3.c, rec_layer_d1.c -> RECORD_LAYER component
+
+The RECORD_LAYER component is a facade pattern, i.e. it provides a simplified
+interface to the record layer for the rest of libssl. The other 3 components are
+entirely private to the record layer and therefore should never be accessed
+directly by libssl.
+
+Any component can directly access its own members - they are private to that
+component, e.g. ssl3_buffer.c can access members of the SSL3_BUFFER struct
+without using a macro. No component can directly access the members of another
+component, e.g. ssl3_buffer cannot reach inside the RECORD_LAYER component to
+directly access its members. Instead components use accessor macros, so if code
+in ssl3_buffer.c wants to access the members of the RECORD_LAYER it uses the
+RECORD_LAYER_* macros.
+
+Conceptually it looks like this:
+
+ libssl
+ |
+ -------------------------|-----record.h------------------------------------
+ |
+ _______V______________
+ | |
+ | RECORD_LAYER |
+ | |
+ | rec_layer_s3.c |
+ | ^ |
+ | _________|__________ |
+ || ||
+ || DTLS1_RECORD_LAYER ||
+ || ||
+ || rec_layer_d1.c ||
+ ||____________________||
+ |______________________|
+ record_local.h ^ ^ ^
+ _________________| | |_________________
+ | | |
+ _____V_________ ______V________ _______V________
+ | | | | | |
+ | SSL3_BUFFER | | SSL3_RECORD | | DTLS1_BITMAP |
+ | |--->| | | |
+ | ssl3_buffer.c | | ssl3_record.c | | dtls1_bitmap.c |
+ |_______________| |_______________| |________________|
+
+The two RECORD_LAYER source files build on each other, i.e.
+the main one is rec_layer_s3.c which provides the core SSL/TLS layer. The second
+one is rec_layer_d1.c which builds off of the SSL/TLS code to provide DTLS
+specific capabilities. It uses some DTLS specific RECORD_LAYER component members
+which should only be accessed from rec_layer_d1.c. These are held in the
+DTLS1_RECORD_LAYER struct.
diff --git a/ssl/record/dtls1_bitmap.c b/ssl/record/dtls1_bitmap.c
index 8167b4183404..4733a62a9663 100644
--- a/ssl/record/dtls1_bitmap.c
+++ b/ssl/record/dtls1_bitmap.c
@@ -1,7 +1,7 @@
/*
* Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/ssl/record/rec_layer_d1.c b/ssl/record/rec_layer_d1.c
index 78d29594c666..7f3d1a7f0ddf 100644
--- a/ssl/record/rec_layer_d1.c
+++ b/ssl/record/rec_layer_d1.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -13,7 +13,7 @@
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include "record_local.h"
-#include "../packet_local.h"
+#include "internal/packet.h"
#include "internal/cryptlib.h"
int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl)
@@ -21,7 +21,7 @@ int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl)
DTLS_RECORD_LAYER *d;
if ((d = OPENSSL_malloc(sizeof(*d))) == NULL) {
- SSLerr(SSL_F_DTLS_RECORD_LAYER_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -77,6 +77,8 @@ void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl)
while ((item = pqueue_pop(d->processed_rcds.q)) != NULL) {
rdata = (DTLS1_RECORD_DATA *)item->data;
+ if (rl->s->options & SSL_OP_CLEANSE_PLAINTEXT)
+ OPENSSL_cleanse(rdata->rbuf.buf, rdata->rbuf.len);
OPENSSL_free(rdata->rbuf.buf);
OPENSSL_free(item->data);
pitem_free(item);
@@ -84,6 +86,8 @@ void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl)
while ((item = pqueue_pop(d->buffered_app_data.q)) != NULL) {
rdata = (DTLS1_RECORD_DATA *)item->data;
+ if (rl->s->options & SSL_OP_CLEANSE_PLAINTEXT)
+ OPENSSL_cleanse(rdata->rbuf.buf, rdata->rbuf.len);
OPENSSL_free(rdata->rbuf.buf);
OPENSSL_free(item->data);
pitem_free(item);
@@ -153,8 +157,7 @@ int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
if (rdata == NULL || item == NULL) {
OPENSSL_free(rdata);
pitem_free(item);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_BUFFER_RECORD,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
@@ -262,9 +265,7 @@ int dtls1_process_buffered_records(SSL *s)
* current record is from a different epoch. But that cannot
* be the case because we already checked the epoch above
*/
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
#ifndef OPENSSL_NO_SCTP
@@ -284,7 +285,7 @@ int dtls1_process_buffered_records(SSL *s)
if (!replayok || !dtls1_process_record(s, bitmap)) {
if (ossl_statem_in_error(s)) {
/* dtls1_process_record called SSLfatal() */
- return -1;
+ return 0;
}
/* dump this record */
rr->length = 0;
@@ -358,8 +359,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
if ((type && (type != SSL3_RT_APPLICATION_DATA) &&
(type != SSL3_RT_HANDSHAKE)) ||
(peek && (type != SSL3_RT_APPLICATION_DATA))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_READ_BYTES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
@@ -377,10 +377,10 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
s->rwstate = SSL_NOTHING;
/*-
- * s->s3->rrec.type - is the type of record
- * s->s3->rrec.data, - data
- * s->s3->rrec.off, - offset into 'data' for next read
- * s->s3->rrec.length, - number of bytes.
+ * s->s3.rrec.type - is the type of record
+ * s->s3.rrec.data, - data
+ * s->s3.rrec.off, - offset into 'data' for next read
+ * s->s3.rrec.length, - number of bytes.
*/
rr = s->rlayer.rrec;
@@ -445,8 +445,8 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
/* we now have a packet which can be read and processed */
- if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
- * reset by ssl3_get_finished */
+ if (s->s3.change_cipher_spec /* set when we receive ChangeCipherSpec,
+ * reset by ssl3_get_finished */
&& (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE)) {
/*
* We now have application data between CCS and Finished. Most likely
@@ -488,7 +488,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
*/
if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
(s->enc_read_ctx == NULL)) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES,
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_APP_DATA_IN_HANDSHAKE);
return -1;
}
@@ -517,6 +517,8 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
if (SSL3_RECORD_get_length(rr) == 0)
SSL3_RECORD_set_read(rr);
} else {
+ if (s->options & SSL_OP_CLEANSE_PLAINTEXT)
+ OPENSSL_cleanse(&(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n);
SSL3_RECORD_sub_length(rr, n);
SSL3_RECORD_add_off(rr, n);
if (SSL3_RECORD_get_length(rr) == 0) {
@@ -533,7 +535,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
*/
if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
s->d1->shutdown_received
- && !BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) {
+ && BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)) <= 0) {
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
return 0;
}
@@ -557,8 +559,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
|| !PACKET_get_1(&alert, &alert_level)
|| !PACKET_get_1(&alert, &alert_descr)
|| PACKET_remaining(&alert) != 0) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES,
- SSL_R_INVALID_ALERT);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_INVALID_ALERT);
return -1;
}
@@ -577,12 +578,12 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
}
if (alert_level == SSL3_AL_WARNING) {
- s->s3->warn_alert = alert_descr;
+ s->s3.warn_alert = alert_descr;
SSL3_RECORD_set_read(rr);
s->rlayer.alert_count++;
if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES,
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_TOO_MANY_WARN_ALERTS);
return -1;
}
@@ -595,7 +596,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
* that nothing gets discarded.
*/
if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
- BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) {
+ BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)) > 0) {
s->d1->shutdown_received = 1;
s->rwstate = SSL_READING;
BIO_clear_retry_flags(SSL_get_rbio(s));
@@ -607,21 +608,17 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
return 0;
}
} else if (alert_level == SSL3_AL_FATAL) {
- char tmp[16];
-
s->rwstate = SSL_NOTHING;
- s->s3->fatal_alert = alert_descr;
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS1_READ_BYTES,
- SSL_AD_REASON_OFFSET + alert_descr);
- BIO_snprintf(tmp, sizeof tmp, "%d", alert_descr);
- ERR_add_error_data(2, "SSL alert number ", tmp);
+ s->s3.fatal_alert = alert_descr;
+ SSLfatal_data(s, SSL_AD_NO_ALERT,
+ SSL_AD_REASON_OFFSET + alert_descr,
+ "SSL alert number %d", alert_descr);
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
SSL3_RECORD_set_read(rr);
SSL_CTX_remove_session(s->session_ctx, s->session);
return 0;
} else {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_READ_BYTES,
- SSL_R_UNKNOWN_ALERT_TYPE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_UNKNOWN_ALERT_TYPE);
return -1;
}
@@ -705,8 +702,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
* finished
*/
if (!ossl_assert(SSL_is_init_finished(s))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_READ_BYTES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
@@ -742,8 +738,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
switch (SSL3_RECORD_get_type(rr)) {
default:
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES,
- SSL_R_UNEXPECTED_RECORD);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_RECORD);
return -1;
case SSL3_RT_CHANGE_CIPHER_SPEC:
case SSL3_RT_ALERT:
@@ -753,8 +748,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
* SSL3_RT_HANDSHAKE when ossl_statem_get_in_handshake(s) is true, but
* that should not happen when type != rr->type
*/
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, ERR_R_INTERNAL_ERROR);
return -1;
case SSL3_RT_APPLICATION_DATA:
/*
@@ -764,14 +758,13 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
* application data at this point (session renegotiation not yet
* started), we will indulge it.
*/
- if (s->s3->in_read_app_data &&
- (s->s3->total_renegotiations != 0) &&
+ if (s->s3.in_read_app_data &&
+ (s->s3.total_renegotiations != 0) &&
ossl_statem_app_data_allowed(s)) {
- s->s3->in_read_app_data = 2;
+ s->s3.in_read_app_data = 2;
return -1;
} else {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES,
- SSL_R_UNEXPECTED_RECORD);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_RECORD);
return -1;
}
}
@@ -788,8 +781,7 @@ int dtls1_write_bytes(SSL *s, int type, const void *buf, size_t len,
int i;
if (!ossl_assert(len <= SSL3_RT_MAX_PLAIN_LENGTH)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_WRITE_BYTES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
s->rwstate = SSL_NOTHING;
@@ -815,13 +807,12 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
* the buffer.
*/
if (!ossl_assert(SSL3_BUFFER_get_left(wb) == 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
/* If we have an alert to send, lets send it */
- if (s->s3->alert_dispatch) {
+ if (s->s3.alert_dispatch) {
i = s->method->ssl_dispatch_alert(s);
if (i <= 0)
return i;
@@ -832,23 +823,23 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
return 0;
if (len > ssl_get_max_send_fragment(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE,
- SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE);
return 0;
}
sess = s->session;
- if ((sess == NULL) ||
- (s->enc_write_ctx == NULL) || (EVP_MD_CTX_md(s->write_hash) == NULL))
+ if ((sess == NULL)
+ || (s->enc_write_ctx == NULL)
+ || (EVP_MD_CTX_get0_md(s->write_hash) == NULL))
clear = 1;
if (clear)
mac_size = 0;
else {
- mac_size = EVP_MD_CTX_size(s->write_hash);
+ mac_size = EVP_MD_CTX_get_size(s->write_hash);
if (mac_size < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE,
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE);
return -1;
}
@@ -880,9 +871,13 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
/* Explicit IV length, block ciphers appropriate version flag */
if (s->enc_write_ctx) {
- int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx);
+ int mode = EVP_CIPHER_CTX_get_mode(s->enc_write_ctx);
if (mode == EVP_CIPH_CBC_MODE) {
- eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx);
+ eivlen = EVP_CIPHER_CTX_get_iv_length(s->enc_write_ctx);
+ if (eivlen < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_LIBRARY_BUG);
+ return -1;
+ }
if (eivlen <= 1)
eivlen = 0;
}
@@ -908,8 +903,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
/* first we compress */
if (s->compress != NULL) {
if (!ssl3_do_compress(s, &wr)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE,
- SSL_R_COMPRESSION_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_COMPRESSION_FAILURE);
return -1;
}
} else {
@@ -928,8 +922,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
if (!s->method->ssl3_enc->mac(s, &wr,
&(p[SSL3_RECORD_get_length(&wr) + eivlen]),
1)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
SSL3_RECORD_add_length(&wr, mac_size);
@@ -942,10 +935,9 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
if (eivlen)
SSL3_RECORD_add_length(&wr, eivlen);
- if (s->method->ssl3_enc->enc(s, &wr, 1, 1) < 1) {
+ if (s->method->ssl3_enc->enc(s, &wr, 1, 1, NULL, mac_size) < 1) {
if (!ossl_statem_in_error(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
}
return -1;
}
@@ -953,8 +945,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
if (SSL_WRITE_ETM(s) && mac_size != 0) {
if (!s->method->ssl3_enc->mac(s, &wr,
&(p[SSL3_RECORD_get_length(&wr)]), 1)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
SSL3_RECORD_add_length(&wr, mac_size);
diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c
index 1db1712a0986..4121f3b2ae1c 100644
--- a/ssl/record/rec_layer_s3.c
+++ b/ssl/record/rec_layer_s3.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -15,11 +15,11 @@
#include <openssl/buffer.h>
#include <openssl/rand.h>
#include "record_local.h"
-#include "../packet_local.h"
+#include "internal/packet.h"
#include "internal/cryptlib.h"
#if defined(OPENSSL_SMALL_FOOTPRINT) || \
- !( defined(AESNI_ASM) && ( \
+ !( defined(AES_ASM) && ( \
defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64) ) \
)
@@ -276,16 +276,19 @@ int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold,
if (n > rb->len - rb->offset) {
/* does not happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_N,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
- /* We always act like read_ahead is set for DTLS */
- if (!s->rlayer.read_ahead && !SSL_IS_DTLS(s))
+ /*
+ * Ktls always reads full records.
+ * Also, we always act like read_ahead is set for DTLS.
+ */
+ if (!BIO_get_ktls_recv(s->rbio) && !s->rlayer.read_ahead
+ && !SSL_IS_DTLS(s)) {
/* ignore max parameter */
max = n;
- else {
+ } else {
if (max < n)
max = n;
if (max > rb->len - rb->offset)
@@ -297,7 +300,7 @@ int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold,
int ret;
/*
- * Now we have len+left bytes at the front of s->s3->rbuf.buf and
+ * Now we have len+left bytes at the front of s->s3.rbuf.buf and
* need to read in more until we have len+n (up to len+max if
* possible)
*/
@@ -305,13 +308,22 @@ int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold,
clear_sys_error();
if (s->rbio != NULL) {
s->rwstate = SSL_READING;
- /* TODO(size_t): Convert this function */
ret = BIO_read(s->rbio, pkt + len + left, max - left);
if (ret >= 0)
bioread = ret;
+ if (ret <= 0
+ && !BIO_should_retry(s->rbio)
+ && BIO_eof(s->rbio)) {
+ if (s->options & SSL_OP_IGNORE_UNEXPECTED_EOF) {
+ SSL_set_shutdown(s, SSL_RECEIVED_SHUTDOWN);
+ s->s3.warn_alert = SSL_AD_CLOSE_NOTIFY;
+ } else {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_R_UNEXPECTED_EOF_WHILE_READING);
+ }
+ }
} else {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_N,
- SSL_R_READ_BIO_NOT_SET);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_READ_BIO_NOT_SET);
ret = -1;
}
@@ -373,8 +385,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
*/
if ((len < s->rlayer.wnum)
|| ((wb->left != 0) && (len < (s->rlayer.wnum + s->rlayer.wpend_tot)))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_WRITE_BYTES,
- SSL_R_BAD_LENGTH);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_LENGTH);
return -1;
}
@@ -387,10 +398,12 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
s->rlayer.wnum = 0;
/*
- * If we are supposed to be sending a KeyUpdate then go into init unless we
- * have writes pending - in which case we should finish doing that first.
+ * If we are supposed to be sending a KeyUpdate or NewSessionTicket then go
+ * into init unless we have writes pending - in which case we should finish
+ * doing that first.
*/
- if (wb->left == 0 && s->key_update != SSL_KEY_UPDATE_NONE)
+ if (wb->left == 0 && (s->key_update != SSL_KEY_UPDATE_NONE
+ || s->ext.extra_tickets_expected > 0))
ossl_statem_set_in_init(s, 1);
/*
@@ -431,12 +444,15 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
* jumbo buffer to accommodate up to 8 records, but the
* compromise is considered worthy.
*/
- if (type == SSL3_RT_APPLICATION_DATA &&
- len >= 4 * (max_send_fragment = ssl_get_max_send_fragment(s)) &&
- s->compress == NULL && s->msg_callback == NULL &&
- !SSL_WRITE_ETM(s) && SSL_USE_EXPLICIT_IV(s) &&
- EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) &
- EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) {
+ if (type == SSL3_RT_APPLICATION_DATA
+ && len >= 4 * (max_send_fragment = ssl_get_max_send_fragment(s))
+ && s->compress == NULL
+ && s->msg_callback == NULL
+ && !SSL_WRITE_ETM(s)
+ && SSL_USE_EXPLICIT_IV(s)
+ && BIO_get_ktls_send(s->wbio) == 0
+ && (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx))
+ & EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) != 0) {
unsigned char aad[13];
EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
size_t packlen;
@@ -477,7 +493,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
break;
}
- if (s->s3->alert_dispatch) {
+ if (s->s3.alert_dispatch) {
i = s->method->ssl_dispatch_alert(s);
if (i <= 0) {
/* SSLfatal() already called if appropriate */
@@ -579,24 +595,23 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
* We should have prevented this when we set max_pipelines so we
* shouldn't get here
*/
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_WRITE_BYTES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
if (maxpipes == 0
|| s->enc_write_ctx == NULL
- || !(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx))
- & EVP_CIPH_FLAG_PIPELINE)
+ || (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx))
+ & EVP_CIPH_FLAG_PIPELINE) == 0
|| !SSL_USE_EXPLICIT_IV(s))
maxpipes = 1;
- if (max_send_fragment == 0 || split_send_fragment == 0
- || split_send_fragment > max_send_fragment) {
+ if (max_send_fragment == 0
+ || split_send_fragment == 0
+ || split_send_fragment > max_send_fragment) {
/*
* We should have prevented this when we set/get the split and max send
* fragments so we shouldn't get here
*/
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_WRITE_BYTES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
@@ -646,7 +661,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
* next chunk of data should get another prepended empty fragment
* in ciphersuites with known-IV weakness:
*/
- s->s3->empty_fragment_done = 0;
+ s->s3.empty_fragment_done = 0;
if (tmpwrit == n
&& (s->mode & SSL_MODE_RELEASE_BUFFERS) != 0
@@ -692,7 +707,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
}
/* If we have an alert to send, lets send it */
- if (s->s3->alert_dispatch) {
+ if (s->s3.alert_dispatch) {
i = s->method->ssl_dispatch_alert(s);
if (i <= 0) {
/* SSLfatal() already called if appropriate */
@@ -713,16 +728,15 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
sess = s->session;
- if ((sess == NULL) ||
- (s->enc_write_ctx == NULL) || (EVP_MD_CTX_md(s->write_hash) == NULL)) {
+ if ((sess == NULL)
+ || (s->enc_write_ctx == NULL)
+ || (EVP_MD_CTX_get0_md(s->write_hash) == NULL)) {
clear = s->enc_write_ctx ? 0 : 1; /* must be AEAD cipher */
mac_size = 0;
} else {
- /* TODO(siz_t): Convert me */
- mac_size = EVP_MD_CTX_size(s->write_hash);
+ mac_size = EVP_MD_CTX_get_size(s->write_hash);
if (mac_size < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
}
@@ -730,13 +744,13 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
/*
* 'create_empty_fragment' is true only when this function calls itself
*/
- if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done) {
+ if (!clear && !create_empty_fragment && !s->s3.empty_fragment_done) {
/*
* countermeasure against known-IV weakness in CBC ciphersuites (see
* http://www.openssl.org/~bodo/tls-cbc.txt)
*/
- if (s->s3->need_empty_fragments && type == SSL3_RT_APPLICATION_DATA) {
+ if (s->s3.need_empty_fragments && type == SSL3_RT_APPLICATION_DATA) {
/*
* recursive function call with 'create_empty_fragment' set; this
* prepares and buffers the data for an empty fragment (these
@@ -755,13 +769,25 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
if (prefix_len >
(SSL3_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD)) {
/* insufficient space */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
}
- s->s3->empty_fragment_done = 1;
+ s->s3.empty_fragment_done = 1;
+ }
+
+ if (BIO_get_ktls_send(s->wbio)) {
+ /*
+ * ktls doesn't modify the buffer, but to avoid a warning we need to
+ * discard the const qualifier.
+ * This doesn't leak memory because the buffers have been released when
+ * switching to ktls.
+ */
+ SSL3_BUFFER_set_buf(&s->rlayer.wbuf[0], (unsigned char *)buf);
+ SSL3_BUFFER_set_offset(&s->rlayer.wbuf[0], 0);
+ SSL3_BUFFER_set_app_buffer(&s->rlayer.wbuf[0], 1);
+ goto wpacket_init_complete;
}
if (create_empty_fragment) {
@@ -779,8 +805,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
if (!WPACKET_init_static_len(&pkt[0], SSL3_BUFFER_get_buf(wb),
SSL3_BUFFER_get_len(wb), 0)
|| !WPACKET_allocate_bytes(&pkt[0], align, NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
wpinited = 1;
@@ -791,8 +816,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
SSL3_BUFFER_get_len(wb), 0)
|| !WPACKET_allocate_bytes(&pkt[0], SSL3_BUFFER_get_offset(wb)
+ prefix_len, NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
wpinited = 1;
@@ -809,8 +833,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
if (!WPACKET_init_static_len(thispkt, SSL3_BUFFER_get_buf(wb),
SSL3_BUFFER_get_len(wb), 0)
|| !WPACKET_allocate_bytes(thispkt, align, NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
wpinited++;
@@ -819,10 +842,13 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
/* Explicit IV length, block ciphers appropriate version flag */
if (s->enc_write_ctx && SSL_USE_EXPLICIT_IV(s) && !SSL_TREAT_AS_TLS13(s)) {
- int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx);
+ int mode = EVP_CIPHER_CTX_get_mode(s->enc_write_ctx);
if (mode == EVP_CIPH_CBC_MODE) {
- /* TODO(size_t): Convert me */
- eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx);
+ eivlen = EVP_CIPHER_CTX_get_iv_length(s->enc_write_ctx);
+ if (eivlen < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_LIBRARY_BUG);
+ goto err;
+ }
if (eivlen <= 1)
eivlen = 0;
} else if (mode == EVP_CIPH_GCM_MODE) {
@@ -833,6 +859,8 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
}
}
+ wpacket_init_complete:
+
totlen = 0;
/* Clear our SSL3_RECORD structures */
memset(wr, 0, sizeof(wr));
@@ -874,17 +902,20 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
if (s->compress != NULL)
maxcomplen += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
- /* write the header */
- if (!WPACKET_put_bytes_u8(thispkt, rectype)
+ /*
+ * When using offload kernel will write the header.
+ * Otherwise write the header now
+ */
+ if (!BIO_get_ktls_send(s->wbio)
+ && (!WPACKET_put_bytes_u8(thispkt, rectype)
|| !WPACKET_put_bytes_u16(thispkt, version)
|| !WPACKET_start_sub_packet_u16(thispkt)
|| (eivlen > 0
&& !WPACKET_allocate_bytes(thispkt, eivlen, NULL))
|| (maxcomplen > 0
&& !WPACKET_reserve_bytes(thispkt, maxcomplen,
- &compressdata))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ &compressdata)))) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -903,28 +934,30 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
if (s->compress != NULL) {
if (!ssl3_do_compress(s, thiswr)
|| !WPACKET_allocate_bytes(thispkt, thiswr->length, NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- SSL_R_COMPRESSION_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_COMPRESSION_FAILURE);
goto err;
}
} else {
- if (!WPACKET_memcpy(thispkt, thiswr->input, thiswr->length)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
- goto err;
+ if (BIO_get_ktls_send(s->wbio)) {
+ SSL3_RECORD_reset_data(&wr[j]);
+ } else {
+ if (!WPACKET_memcpy(thispkt, thiswr->input, thiswr->length)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ SSL3_RECORD_reset_input(&wr[j]);
}
- SSL3_RECORD_reset_input(&wr[j]);
}
if (SSL_TREAT_AS_TLS13(s)
+ && !BIO_get_ktls_send(s->wbio)
&& s->enc_write_ctx != NULL
&& (s->statem.enc_write_state != ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
|| type != SSL3_RT_ALERT)) {
size_t rlen, max_send_fragment;
if (!WPACKET_put_bytes_u8(thispkt, type)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
SSL3_RECORD_add_length(thiswr, 1);
@@ -957,7 +990,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
if (padding > max_padding)
padding = max_padding;
if (!WPACKET_memset(thispkt, 0, padding)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -972,13 +1005,12 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
* in the wb->buf
*/
- if (!SSL_WRITE_ETM(s) && mac_size != 0) {
+ if (!BIO_get_ktls_send(s->wbio) && !SSL_WRITE_ETM(s) && mac_size != 0) {
unsigned char *mac;
if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac)
|| !s->method->ssl3_enc->mac(s, thiswr, mac, 1)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
}
@@ -989,26 +1021,25 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
* max encrypted overhead does not need to include an allocation for that
* MAC
*/
- if (!WPACKET_reserve_bytes(thispkt,
- SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD
- - mac_size,
- NULL)
- /*
- * We also need next the amount of bytes written to this
- * sub-packet
- */
+ if (!BIO_get_ktls_send(s->wbio)) {
+ if (!WPACKET_reserve_bytes(thispkt,
+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD
+ - mac_size, NULL)
+ /*
+ * We also need next the amount of bytes written to this
+ * sub-packet
+ */
|| !WPACKET_get_length(thispkt, &len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
- }
-
- /* Get a pointer to the start of this record excluding header */
- recordstart = WPACKET_get_curr(thispkt) - len;
+ }
- SSL3_RECORD_set_data(thiswr, recordstart);
- SSL3_RECORD_reset_input(thiswr);
- SSL3_RECORD_set_length(thiswr, len);
+ /* Get a pointer to the start of this record excluding header */
+ recordstart = WPACKET_get_curr(thispkt) - len;
+ SSL3_RECORD_set_data(thiswr, recordstart);
+ SSL3_RECORD_reset_input(thiswr);
+ SSL3_RECORD_set_length(thiswr, len);
+ }
}
if (s->statem.enc_write_state == ENC_WRITE_STATE_WRITE_PLAIN_ALERTS) {
@@ -1016,20 +1047,21 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
* We haven't actually negotiated the version yet, but we're trying to
* send early data - so we need to use the tls13enc function.
*/
- if (tls13_enc(s, wr, numpipes, 1) < 1) {
+ if (tls13_enc(s, wr, numpipes, 1, NULL, mac_size) < 1) {
if (!ossl_statem_in_error(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
}
goto err;
}
} else {
- if (s->method->ssl3_enc->enc(s, wr, numpipes, 1) < 1) {
- if (!ossl_statem_in_error(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ if (!BIO_get_ktls_send(s->wbio)) {
+ if (s->method->ssl3_enc->enc(s, wr, numpipes, 1, NULL,
+ mac_size) < 1) {
+ if (!ossl_statem_in_error(s)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ }
+ goto err;
}
- goto err;
}
}
@@ -1039,6 +1071,9 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
thispkt = &pkt[j];
thiswr = &wr[j];
+ if (BIO_get_ktls_send(s->wbio))
+ goto mac_done;
+
/* Allocate bytes for the encryption overhead */
if (!WPACKET_get_length(thispkt, &origlen)
/* Check we allowed enough room for the encryption growth */
@@ -1048,9 +1083,9 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|| origlen > thiswr->length
|| (thiswr->length > origlen
&& !WPACKET_allocate_bytes(thispkt,
- thiswr->length - origlen, NULL))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ thiswr->length - origlen,
+ NULL))) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (SSL_WRITE_ETM(s) && mac_size != 0) {
@@ -1058,8 +1093,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac)
|| !s->method->ssl3_enc->mac(s, thiswr, mac, 1)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
SSL3_RECORD_add_length(thiswr, mac_size);
@@ -1067,39 +1101,32 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
if (!WPACKET_get_length(thispkt, &len)
|| !WPACKET_close(thispkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (s->msg_callback) {
recordstart = WPACKET_get_curr(thispkt) - len
- SSL3_RT_HEADER_LENGTH;
- s->msg_callback(1, 0, SSL3_RT_HEADER, recordstart,
+ s->msg_callback(1, thiswr->rec_version, SSL3_RT_HEADER, recordstart,
SSL3_RT_HEADER_LENGTH, s,
s->msg_callback_arg);
if (SSL_TREAT_AS_TLS13(s) && s->enc_write_ctx != NULL) {
unsigned char ctype = type;
- s->msg_callback(1, s->version, SSL3_RT_INNER_CONTENT_TYPE,
+ s->msg_callback(1, thiswr->rec_version, SSL3_RT_INNER_CONTENT_TYPE,
&ctype, 1, s, s->msg_callback_arg);
}
}
if (!WPACKET_finish(thispkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- /*
- * we should now have thiswr->data pointing to the encrypted data, which
- * is thiswr->length long
- */
- SSL3_RECORD_set_type(thiswr, type); /* not needed but helps for
- * debugging */
- SSL3_RECORD_add_length(thiswr, SSL3_RT_HEADER_LENGTH);
+ /* header is added by the kernel when using offload */
+ SSL3_RECORD_add_length(&wr[j], SSL3_RT_HEADER_LENGTH);
if (create_empty_fragment) {
/*
@@ -1108,14 +1135,21 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
*/
if (j > 0) {
/* We should never be pipelining an empty fragment!! */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
*written = SSL3_RECORD_get_length(thiswr);
return 1;
}
+ mac_done:
+ /*
+ * we should now have thiswr->data pointing to the encrypted data, which
+ * is thiswr->length long
+ */
+ SSL3_RECORD_set_type(thiswr, type); /* not needed but helps for
+ * debugging */
+
/* now let's set up wb */
SSL3_BUFFER_set_left(&s->rlayer.wbuf[j],
prefix_len + SSL3_RECORD_get_length(thiswr));
@@ -1138,7 +1172,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
return -1;
}
-/* if s->s3->wbuf.left != 0, we need to call this
+/* if s->s3.wbuf.left != 0, we need to call this
*
* Return values are as per SSL_write()
*/
@@ -1154,8 +1188,7 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len,
|| (!(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)
&& (s->rlayer.wpend_buf != buf))
|| (s->rlayer.wpend_type != type)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_WRITE_PENDING,
- SSL_R_BAD_WRITE_RETRY);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_WRITE_RETRY);
return -1;
}
@@ -1169,7 +1202,17 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len,
clear_sys_error();
if (s->wbio != NULL) {
s->rwstate = SSL_WRITING;
- /* TODO(size_t): Convert this call */
+
+ /*
+ * To prevent coalescing of control and data messages,
+ * such as in buffer_write, we flush the BIO
+ */
+ if (BIO_get_ktls_send(s->wbio) && type != SSL3_RT_APPLICATION_DATA) {
+ i = BIO_flush(s->wbio);
+ if (i <= 0)
+ return i;
+ BIO_set_ktls_ctrl_msg(s->wbio, type);
+ }
i = BIO_write(s->wbio, (char *)
&(SSL3_BUFFER_get_buf(&wb[currbuf])
[SSL3_BUFFER_get_offset(&wb[currbuf])]),
@@ -1177,11 +1220,18 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len,
if (i >= 0)
tmpwrit = i;
} else {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_WRITE_PENDING,
- SSL_R_BIO_NOT_SET);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BIO_NOT_SET);
i = -1;
}
- if (i > 0 && tmpwrit == SSL3_BUFFER_get_left(&wb[currbuf])) {
+
+ /*
+ * When an empty fragment is sent on a connection using KTLS,
+ * it is sent as a write of zero bytes. If this zero byte
+ * write succeeds, i will be 0 rather than a non-zero value.
+ * Treat i == 0 as success rather than an error for zero byte
+ * writes to permit this case.
+ */
+ if (i >= 0 && tmpwrit == SSL3_BUFFER_get_left(&wb[currbuf])) {
SSL3_BUFFER_set_left(&wb[currbuf], 0);
SSL3_BUFFER_add_offset(&wb[currbuf], tmpwrit);
if (currbuf + 1 < s->rlayer.numwpipes)
@@ -1217,7 +1267,7 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len,
*
* This function must handle any surprises the peer may have for us, such as
* Alert records (e.g. close_notify) or renegotiation requests. ChangeCipherSpec
- * messages are treated as if they were handshake messages *if* the |recd_type|
+ * messages are treated as if they were handshake messages *if* the |recvd_type|
* argument is non NULL.
* Also if record payloads contain fragments too small to process, we store
* them until there is enough for the respective protocol (the record protocol
@@ -1257,8 +1307,7 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
&& (type != SSL3_RT_HANDSHAKE)) || (peek
&& (type !=
SSL3_RT_APPLICATION_DATA))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_BYTES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
@@ -1325,8 +1374,7 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
num_recs = RECORD_LAYER_get_numrpipes(&s->rlayer);
if (num_recs == 0) {
/* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_BYTES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
}
@@ -1345,7 +1393,7 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
if (s->rlayer.handshake_fragment_len > 0
&& SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE
&& SSL_IS_TLS13(s)) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES,
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA);
return -1;
}
@@ -1360,10 +1408,10 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
/* we now have a packet which can be read and processed */
- if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
- * reset by ssl3_get_finished */
+ if (s->s3.change_cipher_spec /* set when we receive ChangeCipherSpec,
+ * reset by ssl3_get_finished */
&& (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE)) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES,
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_DATA_BETWEEN_CCS_AND_FINISHED);
return -1;
}
@@ -1393,16 +1441,14 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
*/
if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
(s->enc_read_ctx == NULL)) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES,
- SSL_R_APP_DATA_IN_HANDSHAKE);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_APP_DATA_IN_HANDSHAKE);
return -1;
}
if (type == SSL3_RT_HANDSHAKE
&& SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC
&& s->rlayer.handshake_fragment_len > 0) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES,
- SSL_R_CCS_RECEIVED_EARLY);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_CCS_RECEIVED_EARLY);
return -1;
}
@@ -1434,6 +1480,8 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
if (SSL3_RECORD_get_length(rr) == 0)
SSL3_RECORD_set_read(rr);
} else {
+ if (s->options & SSL_OP_CLEANSE_PLAINTEXT)
+ OPENSSL_cleanse(&(rr->data[rr->off]), n);
SSL3_RECORD_sub_length(rr, n);
SSL3_RECORD_add_off(rr, n);
if (SSL3_RECORD_get_length(rr) == 0) {
@@ -1478,8 +1526,7 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
* initial ClientHello. Therefore |type| should always be equal to
* |rr->type|. If not then something has gone horribly wrong
*/
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_BYTES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
@@ -1487,13 +1534,12 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
&& (s->server || rr->type != SSL3_RT_ALERT)) {
/*
* If we've got this far and still haven't decided on what version
- * we're using then this must be a client side alert we're dealing with
- * (we don't allow heartbeats yet). We shouldn't be receiving anything
- * other than a ClientHello if we are a server.
+ * we're using then this must be a client side alert we're dealing
+ * with. We shouldn't be receiving anything other than a ClientHello
+ * if we are a server.
*/
s->version = rr->rec_version;
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES,
- SSL_R_UNEXPECTED_MESSAGE);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
return -1;
}
@@ -1512,8 +1558,7 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
|| !PACKET_get_1(&alert, &alert_level)
|| !PACKET_get_1(&alert, &alert_descr)
|| PACKET_remaining(&alert) != 0) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES,
- SSL_R_INVALID_ALERT);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_INVALID_ALERT);
return -1;
}
@@ -1533,12 +1578,12 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
if (alert_level == SSL3_AL_WARNING
|| (is_tls13 && alert_descr == SSL_AD_USER_CANCELLED)) {
- s->s3->warn_alert = alert_descr;
+ s->s3.warn_alert = alert_descr;
SSL3_RECORD_set_read(rr);
s->rlayer.alert_count++;
if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES,
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_TOO_MANY_WARN_ALERTS);
return -1;
}
@@ -1555,14 +1600,11 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
return 0;
} else if (alert_level == SSL3_AL_FATAL || is_tls13) {
- char tmp[16];
-
s->rwstate = SSL_NOTHING;
- s->s3->fatal_alert = alert_descr;
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_READ_BYTES,
- SSL_AD_REASON_OFFSET + alert_descr);
- BIO_snprintf(tmp, sizeof tmp, "%d", alert_descr);
- ERR_add_error_data(2, "SSL alert number ", tmp);
+ s->s3.fatal_alert = alert_descr;
+ SSLfatal_data(s, SSL_AD_NO_ALERT,
+ SSL_AD_REASON_OFFSET + alert_descr,
+ "SSL alert number %d", alert_descr);
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
SSL3_RECORD_set_read(rr);
SSL_CTX_remove_session(s->session_ctx, s->session);
@@ -1576,16 +1618,14 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
* future we might have a renegotiation where we don't care if
* the peer refused it where we carry on.
*/
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_SSL3_READ_BYTES,
- SSL_R_NO_RENEGOTIATION);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_NO_RENEGOTIATION);
return -1;
} else if (alert_level == SSL3_AL_WARNING) {
/* We ignore any other warning alert in TLSv1.2 and below */
goto start;
}
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL3_READ_BYTES,
- SSL_R_UNKNOWN_ALERT_TYPE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_UNKNOWN_ALERT_TYPE);
return -1;
}
@@ -1623,7 +1663,7 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
*/
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_READ_BYTES,
+ SSLfatal(s, SSL_AD_NO_ALERT,
SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY);
return -1;
}
@@ -1658,8 +1698,7 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
}
if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES,
- SSL_R_CCS_RECEIVED_EARLY);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_CCS_RECEIVED_EARLY);
return -1;
}
@@ -1719,8 +1758,7 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
* no progress is being made and the peer continually sends unrecognised
* record types, using up resources processing them.
*/
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES,
- SSL_R_UNEXPECTED_RECORD);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_RECORD);
return -1;
case SSL3_RT_CHANGE_CIPHER_SPEC:
case SSL3_RT_ALERT:
@@ -1730,8 +1768,7 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
* SSL3_RT_HANDSHAKE when ossl_statem_get_in_handshake(s) is true, but
* that should not happen when type != rr->type
*/
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, ERR_R_INTERNAL_ERROR);
return -1;
case SSL3_RT_APPLICATION_DATA:
/*
@@ -1742,7 +1779,7 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
* started), we will indulge it.
*/
if (ossl_statem_app_data_allowed(s)) {
- s->s3->in_read_app_data = 2;
+ s->s3.in_read_app_data = 2;
return -1;
} else if (ossl_statem_skip_early_data(s)) {
/*
@@ -1762,8 +1799,7 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
SSL3_RECORD_set_read(rr);
goto start;
} else {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES,
- SSL_R_UNEXPECTED_RECORD);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_RECORD);
return -1;
}
}
diff --git a/ssl/record/record.h b/ssl/record/record.h
index af56206e07c9..234656bf9394 100644
--- a/ssl/record/record.h
+++ b/ssl/record/record.h
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -25,6 +25,8 @@ typedef struct ssl3_buffer_st {
size_t offset;
/* how many bytes left */
size_t left;
+ /* 'buf' is from application for KTLS */
+ int app_buffer;
} SSL3_BUFFER;
#define SEQ_NUM_SIZE 8
@@ -176,6 +178,12 @@ typedef struct record_layer_st {
* *
*****************************************************************************/
+struct ssl_mac_buf_st {
+ unsigned char *mac;
+ int alloced;
+};
+typedef struct ssl_mac_buf_st SSL_MAC_BUF;
+
#define MIN_SSL2_RECORD_LEN 9
#define RECORD_LAYER_set_read_ahead(rl, ra) ((rl)->read_ahead = (ra))
@@ -211,13 +219,16 @@ __owur int ssl3_read_bytes(SSL *s, int type, int *recvd_type,
unsigned char *buf, size_t len, int peek,
size_t *readbytes);
__owur int ssl3_setup_buffers(SSL *s);
-__owur int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int send);
+__owur int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int send,
+ SSL_MAC_BUF *mac, size_t macsize);
__owur int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send);
__owur int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len,
size_t *written);
-__owur int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int send);
+__owur int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending,
+ SSL_MAC_BUF *mac, size_t macsize);
__owur int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send);
-__owur int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int send);
+__owur int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int send,
+ SSL_MAC_BUF *mac, size_t macsize);
int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl);
void DTLS_RECORD_LAYER_free(RECORD_LAYER *rl);
void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl);
diff --git a/ssl/record/record_local.h b/ssl/record/record_local.h
index 5e8dd7f70442..0a929c696a55 100644
--- a/ssl/record/record_local.h
+++ b/ssl/record/record_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -65,6 +65,8 @@ void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap);
#define SSL3_BUFFER_add_offset(b, o) ((b)->offset += (o))
#define SSL3_BUFFER_is_initialised(b) ((b)->buf != NULL)
#define SSL3_BUFFER_set_default_len(b, l) ((b)->default_len = (l))
+#define SSL3_BUFFER_set_app_buffer(b, l) ((b)->app_buffer = (l))
+#define SSL3_BUFFER_is_app_buffer(b) ((b)->app_buffer)
void SSL3_BUFFER_clear(SSL3_BUFFER *b);
void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, size_t n);
@@ -88,6 +90,7 @@ int ssl3_release_write_buffer(SSL *s);
#define SSL3_RECORD_get_input(r) ((r)->input)
#define SSL3_RECORD_set_input(r, i) ((r)->input = (i))
#define SSL3_RECORD_reset_input(r) ((r)->input = (r)->data)
+#define SSL3_RECORD_reset_data(r) ((r)->data = (r)->input)
#define SSL3_RECORD_get_seq_num(r) ((r)->seq_num)
#define SSL3_RECORD_get_off(r) ((r)->off)
#define SSL3_RECORD_set_off(r, o) ((r)->off = (o))
@@ -104,13 +107,21 @@ void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num);
int ssl3_get_record(SSL *s);
__owur int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr);
__owur int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr);
-int ssl3_cbc_copy_mac(unsigned char *out,
- const SSL3_RECORD *rec, size_t md_size);
-__owur int ssl3_cbc_remove_padding(SSL3_RECORD *rec,
- size_t block_size, size_t mac_size);
-__owur int tls1_cbc_remove_padding(const SSL *s,
- SSL3_RECORD *rec,
- size_t block_size, size_t mac_size);
+__owur int ssl3_cbc_remove_padding_and_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
+ unsigned char **mac,
+ int *alloced,
+ size_t block_size, size_t mac_size,
+ OSSL_LIB_CTX *libctx);
+__owur int tls1_cbc_remove_padding_and_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
+ unsigned char **mac,
+ int *alloced,
+ size_t block_size, size_t mac_size,
+ int aead,
+ OSSL_LIB_CTX *libctx);
int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap);
__owur int dtls1_get_record(SSL *s);
int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send);
diff --git a/ssl/record/ssl3_buffer.c b/ssl/record/ssl3_buffer.c
index fa597c274671..f631829ef646 100644
--- a/ssl/record/ssl3_buffer.c
+++ b/ssl/record/ssl3_buffer.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -66,8 +66,7 @@ int ssl3_setup_read_buffer(SSL *s)
* We assume we're so doomed that we won't even be able to send an
* alert.
*/
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_SETUP_READ_BUFFER,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_NO_ALERT, ERR_R_MALLOC_FAILURE);
return 0;
}
b->buf = p;
@@ -115,23 +114,26 @@ int ssl3_setup_write_buffer(SSL *s, size_t numwpipes, size_t len)
for (currpipe = 0; currpipe < numwpipes; currpipe++) {
SSL3_BUFFER *thiswb = &wb[currpipe];
- if (thiswb->buf != NULL && thiswb->len != len) {
+ if (thiswb->len != len) {
OPENSSL_free(thiswb->buf);
thiswb->buf = NULL; /* force reallocation */
}
if (thiswb->buf == NULL) {
- p = OPENSSL_malloc(len);
- if (p == NULL) {
- s->rlayer.numwpipes = currpipe;
- /*
- * We've got a malloc failure, and we're still initialising
- * buffers. We assume we're so doomed that we won't even be able
- * to send an alert.
- */
- SSLfatal(s, SSL_AD_NO_ALERT,
- SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE);
- return 0;
+ if (s->wbio == NULL || !BIO_get_ktls_send(s->wbio)) {
+ p = OPENSSL_malloc(len);
+ if (p == NULL) {
+ s->rlayer.numwpipes = currpipe;
+ /*
+ * We've got a malloc failure, and we're still initialising
+ * buffers. We assume we're so doomed that we won't even be able
+ * to send an alert.
+ */
+ SSLfatal(s, SSL_AD_NO_ALERT, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else {
+ p = NULL;
}
memset(thiswb, 0, sizeof(SSL3_BUFFER));
thiswb->buf = p;
@@ -164,7 +166,10 @@ int ssl3_release_write_buffer(SSL *s)
while (pipes > 0) {
wb = &RECORD_LAYER_get_wbuf(&s->rlayer)[pipes - 1];
- OPENSSL_free(wb->buf);
+ if (SSL3_BUFFER_is_app_buffer(wb))
+ SSL3_BUFFER_set_app_buffer(wb, 0);
+ else
+ OPENSSL_free(wb->buf);
wb->buf = NULL;
pipes--;
}
@@ -177,6 +182,8 @@ int ssl3_release_read_buffer(SSL *s)
SSL3_BUFFER *b;
b = RECORD_LAYER_get_rbuf(&s->rlayer);
+ if (s->options & SSL_OP_CLEANSE_PLAINTEXT)
+ OPENSSL_cleanse(b->buf, b->len);
OPENSSL_free(b->buf);
b->buf = NULL;
return 1;
diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c
index 47c7369ed549..1867f001179f 100644
--- a/ssl/record/ssl3_record.c
+++ b/ssl/record/ssl3_record.c
@@ -1,15 +1,16 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "../ssl_local.h"
-#include "internal/constant_time.h"
+#include <openssl/trace.h>
#include <openssl/rand.h>
+#include <openssl/core_names.h>
#include "record_local.h"
#include "internal/cryptlib.h"
@@ -114,8 +115,7 @@ int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send)
if (!s->server && sess->ext.max_early_data == 0) {
if (!ossl_assert(s->psksession != NULL
&& s->psksession->ext.max_early_data > 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_EARLY_DATA_COUNT_OK,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
sess = s->psksession;
@@ -131,7 +131,7 @@ int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send)
if (max_early_data == 0) {
SSLfatal(s, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_EARLY_DATA_COUNT_OK, SSL_R_TOO_MUCH_EARLY_DATA);
+ SSL_R_TOO_MUCH_EARLY_DATA);
return 0;
}
@@ -140,7 +140,7 @@ int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send)
if (s->early_data_count + length > max_early_data) {
SSLfatal(s, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_EARLY_DATA_COUNT_OK, SSL_R_TOO_MUCH_EARLY_DATA);
+ SSL_R_TOO_MUCH_EARLY_DATA);
return 0;
}
s->early_data_count += length;
@@ -181,14 +181,17 @@ int ssl3_get_record(SSL *s)
unsigned char *p;
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int version;
- size_t mac_size;
+ size_t mac_size = 0;
int imac_size;
size_t num_recs = 0, max_recs, j;
PACKET pkt, sslv2pkt;
- size_t first_rec_len;
+ int is_ktls_left;
+ SSL_MAC_BUF *macbufs = NULL;
+ int ret = -1;
rr = RECORD_LAYER_get_rrec(&s->rlayer);
rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
+ is_ktls_left = (SSL3_BUFFER_get_left(rbuf) > 0);
max_recs = s->max_pipelines;
if (max_recs == 0)
max_recs = 1;
@@ -207,22 +210,41 @@ int ssl3_get_record(SSL *s)
rret = ssl3_read_n(s, SSL3_RT_HEADER_LENGTH,
SSL3_BUFFER_get_len(rbuf), 0,
num_recs == 0 ? 1 : 0, &n);
- if (rret <= 0)
- return rret; /* error or non-blocking */
+ if (rret <= 0) {
+#ifndef OPENSSL_NO_KTLS
+ if (!BIO_get_ktls_recv(s->rbio) || rret == 0)
+ return rret; /* error or non-blocking */
+ switch (errno) {
+ case EBADMSG:
+ SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
+ SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+ break;
+ case EMSGSIZE:
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
+ SSL_R_PACKET_LENGTH_TOO_LONG);
+ break;
+ case EINVAL:
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+ SSL_R_WRONG_VERSION_NUMBER);
+ break;
+ default:
+ break;
+ }
+#endif
+ return rret;
+ }
RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
p = RECORD_LAYER_get_packet(&s->rlayer);
if (!PACKET_buf_init(&pkt, RECORD_LAYER_get_packet(&s->rlayer),
RECORD_LAYER_get_packet_length(&s->rlayer))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GET_RECORD,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
sslv2pkt = pkt;
if (!PACKET_get_net_2_len(&sslv2pkt, &sslv2len)
|| !PACKET_get_1(&sslv2pkt, &type)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
/*
@@ -247,33 +269,35 @@ int ssl3_get_record(SSL *s)
if (thisrr->length > SSL3_BUFFER_get_len(rbuf)
- SSL2_RT_HEADER_LENGTH) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_PACKET_LENGTH_TOO_LONG);
return -1;
}
if (thisrr->length < MIN_SSL2_RECORD_LEN) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
- SSL_R_LENGTH_TOO_SHORT);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
return -1;
}
} else {
/* SSLv3+ style record */
- if (s->msg_callback)
- s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s,
- s->msg_callback_arg);
/* Pull apart the header into the SSL3_RECORD */
if (!PACKET_get_1(&pkt, &type)
|| !PACKET_get_net_2(&pkt, &version)
|| !PACKET_get_net_2_len(&pkt, &thisrr->length)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
- ERR_R_INTERNAL_ERROR);
+ if (s->msg_callback)
+ s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s,
+ s->msg_callback_arg);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
thisrr->type = type;
thisrr->rec_version = version;
+ if (s->msg_callback)
+ s->msg_callback(0, version, SSL3_RT_HEADER, p, 5, s,
+ s->msg_callback_arg);
+
/*
* Lets check version. In TLSv1.3 we only check this field
* when encryption is occurring (see later check). For the
@@ -295,7 +319,7 @@ int ssl3_get_record(SSL *s)
* shouldn't send a fatal alert back. We'll just
* end.
*/
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_NO_ALERT,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
}
@@ -304,7 +328,7 @@ int ssl3_get_record(SSL *s)
*/
s->version = (unsigned short)version;
}
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
}
@@ -318,22 +342,20 @@ int ssl3_get_record(SSL *s)
strncmp((char *)p, "POST ", 5) == 0 ||
strncmp((char *)p, "HEAD ", 5) == 0 ||
strncmp((char *)p, "PUT ", 4) == 0) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_GET_RECORD,
- SSL_R_HTTP_REQUEST);
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_R_HTTP_REQUEST);
return -1;
} else if (strncmp((char *)p, "CONNE", 5) == 0) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_NO_ALERT,
SSL_R_HTTPS_PROXY_REQUEST);
return -1;
}
/* Doesn't look like TLS - don't send an alert */
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_NO_ALERT,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
} else {
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_SSL3_GET_RECORD,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
}
@@ -347,11 +369,11 @@ int ssl3_get_record(SSL *s)
|| s->statem.enc_read_state
!= ENC_READ_STATE_ALLOW_PLAIN_ALERTS)) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_SSL3_GET_RECORD, SSL_R_BAD_RECORD_TYPE);
+ SSL_R_BAD_RECORD_TYPE);
return -1;
}
if (thisrr->rec_version != TLS1_2_VERSION) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
}
@@ -359,7 +381,7 @@ int ssl3_get_record(SSL *s)
if (thisrr->length >
SSL3_BUFFER_get_len(rbuf) - SSL3_RT_HEADER_LENGTH) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_PACKET_LENGTH_TOO_LONG);
return -1;
}
@@ -370,7 +392,7 @@ int ssl3_get_record(SSL *s)
if (SSL_IS_TLS13(s)) {
if (thisrr->length > SSL3_RT_MAX_TLS13_ENCRYPTED_LENGTH) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
return -1;
}
@@ -386,8 +408,12 @@ int ssl3_get_record(SSL *s)
len -= SSL3_RT_MAX_COMPRESSED_OVERHEAD;
#endif
+ /* KTLS may use all of the buffer */
+ if (BIO_get_ktls_recv(s->rbio) && !is_ktls_left)
+ len = SSL3_BUFFER_get_left(rbuf);
+
if (thisrr->length > len) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
return -1;
}
@@ -404,6 +430,7 @@ int ssl3_get_record(SSL *s)
} else {
more = thisrr->length;
}
+
if (more > 0) {
/* now s->rlayer.packet_length == SSL3_RT_HEADER_LENGTH */
@@ -457,8 +484,8 @@ int ssl3_get_record(SSL *s)
&& thisrr->type == SSL3_RT_APPLICATION_DATA
&& SSL_USE_EXPLICIT_IV(s)
&& s->enc_read_ctx != NULL
- && (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_read_ctx))
- & EVP_CIPH_FLAG_PIPELINE)
+ && (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(s->enc_read_ctx))
+ & EVP_CIPH_FLAG_PIPELINE) != 0
&& ssl3_record_app_data_waiting(s));
if (num_recs == 1
@@ -469,7 +496,7 @@ int ssl3_get_record(SSL *s)
* CCS messages must be exactly 1 byte long, containing the value 0x01
*/
if (thisrr->length != 1 || thisrr->data[0] != 0x01) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_INVALID_CCS_MESSAGE);
return -1;
}
@@ -481,7 +508,7 @@ int ssl3_get_record(SSL *s)
RECORD_LAYER_inc_empty_record_count(&s->rlayer);
if (RECORD_LAYER_get_empty_record_count(&s->rlayer)
> MAX_EMPTY_RECORDS) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_UNEXPECTED_CCS_MESSAGE);
return -1;
}
@@ -492,57 +519,80 @@ int ssl3_get_record(SSL *s)
}
/*
+ * KTLS reads full records. If there is any data left,
+ * then it is from before enabling ktls
+ */
+ if (BIO_get_ktls_recv(s->rbio) && !is_ktls_left)
+ goto skip_decryption;
+
+ if (s->read_hash != NULL) {
+ const EVP_MD *tmpmd = EVP_MD_CTX_get0_md(s->read_hash);
+
+ if (tmpmd != NULL) {
+ imac_size = EVP_MD_get_size(tmpmd);
+ if (!ossl_assert(imac_size >= 0 && imac_size <= EVP_MAX_MD_SIZE)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ return -1;
+ }
+ mac_size = (size_t)imac_size;
+ }
+ }
+
+ /*
* If in encrypt-then-mac mode calculate mac from encrypted record. All
* the details below are public so no timing details can leak.
*/
if (SSL_READ_ETM(s) && s->read_hash) {
unsigned char *mac;
- /* TODO(size_t): convert this to do size_t properly */
- imac_size = EVP_MD_CTX_size(s->read_hash);
- if (!ossl_assert(imac_size >= 0 && imac_size <= EVP_MAX_MD_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GET_RECORD,
- ERR_LIB_EVP);
- return -1;
- }
- mac_size = (size_t)imac_size;
+
for (j = 0; j < num_recs; j++) {
thisrr = &rr[j];
if (thisrr->length < mac_size) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
- SSL_R_LENGTH_TOO_SHORT);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
return -1;
}
thisrr->length -= mac_size;
mac = thisrr->data + thisrr->length;
i = s->method->ssl3_enc->mac(s, thisrr, md, 0 /* not send */ );
if (i == 0 || CRYPTO_memcmp(md, mac, mac_size) != 0) {
- SSLfatal(s, SSL_AD_BAD_RECORD_MAC, SSL_F_SSL3_GET_RECORD,
- SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+ SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
+ SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
return -1;
}
}
+ /*
+ * We've handled the mac now - there is no MAC inside the encrypted
+ * record
+ */
+ mac_size = 0;
}
- first_rec_len = rr[0].length;
+ if (mac_size > 0) {
+ macbufs = OPENSSL_zalloc(sizeof(*macbufs) * num_recs);
+ if (macbufs == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ }
- enc_err = s->method->ssl3_enc->enc(s, rr, num_recs, 0);
+ enc_err = s->method->ssl3_enc->enc(s, rr, num_recs, 0, macbufs, mac_size);
/*-
* enc_err is:
- * 0: (in non-constant time) if the record is publicly invalid.
- * 1: if the padding is valid
- * -1: if the padding is invalid
+ * 0: if the record is publicly invalid, or an internal error, or AEAD
+ * decryption failed, or ETM decryption failed.
+ * 1: Success or MTE decryption failed (MAC will be randomised)
*/
if (enc_err == 0) {
if (ossl_statem_in_error(s)) {
/* SSLfatal() already got called */
- return -1;
+ goto end;
}
if (num_recs == 1 && ossl_statem_skip_early_data(s)) {
/*
- * Valid early_data that we cannot decrypt might fail here as
- * publicly invalid. We treat it like an empty record.
+ * Valid early_data that we cannot decrypt will fail here. We treat
+ * it like an empty record.
*/
thisrr = &rr[0];
@@ -550,121 +600,48 @@ int ssl3_get_record(SSL *s)
if (!early_data_count_ok(s, thisrr->length,
EARLY_DATA_CIPHERTEXT_OVERHEAD, 0)) {
/* SSLfatal() already called */
- return -1;
+ goto end;
}
thisrr->length = 0;
thisrr->read = 1;
RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
RECORD_LAYER_reset_read_sequence(&s->rlayer);
- return 1;
+ ret = 1;
+ goto end;
}
- SSLfatal(s, SSL_AD_BAD_RECORD_MAC, SSL_F_SSL3_GET_RECORD,
- SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
- return -1;
- }
-#ifdef SSL_DEBUG
- printf("dec %lu\n", (unsigned long)rr[0].length);
- {
- size_t z;
- for (z = 0; z < rr[0].length; z++)
- printf("%02X%c", rr[0].data[z], ((z + 1) % 16) ? ' ' : '\n');
+ SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
+ SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+ goto end;
}
- printf("\n");
-#endif
+ OSSL_TRACE_BEGIN(TLS) {
+ BIO_printf(trc_out, "dec %lu\n", (unsigned long)rr[0].length);
+ BIO_dump_indent(trc_out, rr[0].data, rr[0].length, 4);
+ } OSSL_TRACE_END(TLS);
/* r->length is now the compressed data plus mac */
- if ((sess != NULL) &&
- (s->enc_read_ctx != NULL) &&
- (!SSL_READ_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL)) {
+ if ((sess != NULL)
+ && (s->enc_read_ctx != NULL)
+ && (!SSL_READ_ETM(s) && EVP_MD_CTX_get0_md(s->read_hash) != NULL)) {
/* s->read_hash != NULL => mac_size != -1 */
- unsigned char *mac = NULL;
- unsigned char mac_tmp[EVP_MAX_MD_SIZE];
-
- mac_size = EVP_MD_CTX_size(s->read_hash);
- if (!ossl_assert(mac_size <= EVP_MAX_MD_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GET_RECORD,
- ERR_R_INTERNAL_ERROR);
- return -1;
- }
for (j = 0; j < num_recs; j++) {
+ SSL_MAC_BUF *thismb = &macbufs[j];
thisrr = &rr[j];
- /*
- * orig_len is the length of the record before any padding was
- * removed. This is public information, as is the MAC in use,
- * therefore we can safely process the record in a different amount
- * of time if it's too short to possibly contain a MAC.
- */
- if (thisrr->orig_len < mac_size ||
- /* CBC records must have a padding length byte too. */
- (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
- thisrr->orig_len < mac_size + 1)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
- SSL_R_LENGTH_TOO_SHORT);
- return -1;
- }
-
- if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) {
- /*
- * We update the length so that the TLS header bytes can be
- * constructed correctly but we need to extract the MAC in
- * constant time from within the record, without leaking the
- * contents of the padding bytes.
- */
- mac = mac_tmp;
- if (!ssl3_cbc_copy_mac(mac_tmp, thisrr, mac_size)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GET_RECORD,
- ERR_R_INTERNAL_ERROR);
- return -1;
- }
- thisrr->length -= mac_size;
- } else {
- /*
- * In this case there's no padding, so |rec->orig_len| equals
- * |rec->length| and we checked that there's enough bytes for
- * |mac_size| above.
- */
- thisrr->length -= mac_size;
- mac = &thisrr->data[thisrr->length];
- }
i = s->method->ssl3_enc->mac(s, thisrr, md, 0 /* not send */ );
- if (i == 0 || mac == NULL
- || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
- enc_err = -1;
+ if (i == 0 || thismb == NULL || thismb->mac == NULL
+ || CRYPTO_memcmp(md, thismb->mac, (size_t)mac_size) != 0)
+ enc_err = 0;
if (thisrr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
- enc_err = -1;
+ enc_err = 0;
}
}
- if (enc_err < 0) {
+ if (enc_err == 0) {
if (ossl_statem_in_error(s)) {
/* We already called SSLfatal() */
- return -1;
- }
- if (num_recs == 1 && ossl_statem_skip_early_data(s)) {
- /*
- * We assume this is unreadable early_data - we treat it like an
- * empty record
- */
-
- /*
- * The record length may have been modified by the mac check above
- * so we use the previously saved value
- */
- if (!early_data_count_ok(s, first_rec_len,
- EARLY_DATA_CIPHERTEXT_OVERHEAD, 0)) {
- /* SSLfatal() already called */
- return -1;
- }
-
- thisrr = &rr[0];
- thisrr->length = 0;
- thisrr->read = 1;
- RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
- RECORD_LAYER_reset_read_sequence(&s->rlayer);
- return 1;
+ goto end;
}
/*
* A separate 'decryption_failed' alert was introduced with TLS 1.0,
@@ -673,25 +650,27 @@ int ssl3_get_record(SSL *s)
* not reveal which kind of error occurred -- this might become
* visible to an attacker (e.g. via a logfile)
*/
- SSLfatal(s, SSL_AD_BAD_RECORD_MAC, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
- return -1;
+ goto end;
}
+ skip_decryption:
+
for (j = 0; j < num_recs; j++) {
thisrr = &rr[j];
/* thisrr->length is now just compressed */
if (s->expand != NULL) {
if (thisrr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_COMPRESSED_LENGTH_TOO_LONG);
- return -1;
+ goto end;
}
if (!ssl3_do_uncompress(s, thisrr)) {
- SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE,
SSL_R_BAD_DECOMPRESSION);
- return -1;
+ goto end;
}
}
@@ -702,9 +681,8 @@ int ssl3_get_record(SSL *s)
if (thisrr->length == 0
|| thisrr->type != SSL3_RT_APPLICATION_DATA) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD,
- SSL_R_BAD_RECORD_TYPE);
- return -1;
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_RECORD_TYPE);
+ goto end;
}
/* Strip trailing padding */
@@ -717,9 +695,8 @@ int ssl3_get_record(SSL *s)
if (thisrr->type != SSL3_RT_APPLICATION_DATA
&& thisrr->type != SSL3_RT_ALERT
&& thisrr->type != SSL3_RT_HANDSHAKE) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD,
- SSL_R_BAD_RECORD_TYPE);
- return -1;
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_RECORD_TYPE);
+ goto end;
}
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_INNER_CONTENT_TYPE,
@@ -734,23 +711,33 @@ int ssl3_get_record(SSL *s)
&& (thisrr->type == SSL3_RT_HANDSHAKE
|| thisrr->type == SSL3_RT_ALERT)
&& thisrr->length == 0) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD,
- SSL_R_BAD_LENGTH);
- return -1;
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_LENGTH);
+ goto end;
}
- if (thisrr->length > SSL3_RT_MAX_PLAIN_LENGTH) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
- SSL_R_DATA_LENGTH_TOO_LONG);
- return -1;
+ /*
+ * Usually thisrr->length is the length of a single record, but when
+ * KTLS handles the decryption, thisrr->length may be larger than
+ * SSL3_RT_MAX_PLAIN_LENGTH because the kernel may have coalesced
+ * multiple records.
+ * Therefore we have to rely on KTLS to check the plaintext length
+ * limit in the kernel.
+ */
+ if (thisrr->length > SSL3_RT_MAX_PLAIN_LENGTH
+ && (!BIO_get_ktls_recv(s->rbio) || is_ktls_left)) {
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
+ goto end;
}
- /* If received packet overflows current Max Fragment Length setting */
+ /*
+ * Check if the received packet overflows the current
+ * Max Fragment Length setting.
+ * Note: USE_MAX_FRAGMENT_LENGTH_EXT and KTLS are mutually exclusive.
+ */
if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
&& thisrr->length > GET_MAX_FRAGMENT_LENGTH(s->session)) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
- SSL_R_DATA_LENGTH_TOO_LONG);
- return -1;
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
+ goto end;
}
thisrr->off = 0;
@@ -767,9 +754,8 @@ int ssl3_get_record(SSL *s)
RECORD_LAYER_inc_empty_record_count(&s->rlayer);
if (RECORD_LAYER_get_empty_record_count(&s->rlayer)
> MAX_EMPTY_RECORDS) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD,
- SSL_R_RECORD_TOO_SMALL);
- return -1;
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_RECORD_TOO_SMALL);
+ goto end;
}
} else {
RECORD_LAYER_reset_empty_record_count(&s->rlayer);
@@ -781,12 +767,21 @@ int ssl3_get_record(SSL *s)
if (thisrr->type == SSL3_RT_APPLICATION_DATA
&& !early_data_count_ok(s, thisrr->length, 0, 0)) {
/* SSLfatal already called */
- return -1;
+ goto end;
}
}
RECORD_LAYER_set_numrpipes(&s->rlayer, num_recs);
- return 1;
+ ret = 1;
+ end:
+ if (macbufs != NULL) {
+ for (j = 0; j < num_recs; j++) {
+ if (macbufs[j].alloced)
+ OPENSSL_free(macbufs[j].mac);
+ }
+ OPENSSL_free(macbufs);
+ }
+ return ret;
}
int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr)
@@ -801,7 +796,6 @@ int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr)
if (rr->comp == NULL)
return 0;
- /* TODO(size_t): Convert this call */
i = COMP_expand_block(ssl->expand, rr->comp,
SSL3_RT_MAX_PLAIN_LENGTH, rr->data, (int)rr->length);
if (i < 0)
@@ -818,7 +812,6 @@ int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr)
#ifndef OPENSSL_NO_COMP
int i;
- /* TODO(size_t): Convert this call */
i = COMP_compress_block(ssl->compress, wr->data,
(int)(wr->length + SSL3_RT_MAX_COMPRESSED_OVERHEAD),
wr->input, (int)wr->length);
@@ -833,23 +826,21 @@ int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr)
}
/*-
- * ssl3_enc encrypts/decrypts |n_recs| records in |inrecs|. Will call
- * SSLfatal() for internal errors, but not otherwise.
+ * ssl3_enc encrypts/decrypts |n_recs| records in |inrecs|. Calls SSLfatal on
+ * internal error, but not otherwise. It is the responsibility of the caller to
+ * report a bad_record_mac
*
* Returns:
- * 0: (in non-constant time) if the record is publicly invalid (i.e. too
- * short etc).
- * 1: if the record's padding is valid / the encryption was successful.
- * -1: if the record's padding is invalid or, if sending, an internal error
- * occurred.
+ * 0: if the record is publicly invalid, or an internal error
+ * 1: Success or Mac-then-encrypt decryption failed (MAC will be randomised)
*/
-int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int sending)
+int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int sending,
+ SSL_MAC_BUF *mac, size_t macsize)
{
SSL3_RECORD *rec;
EVP_CIPHER_CTX *ds;
size_t l, i;
- size_t bs, mac_size = 0;
- int imac_size;
+ size_t bs;
const EVP_CIPHER *enc;
rec = inrecs;
@@ -863,26 +854,31 @@ int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int sending)
if (s->enc_write_ctx == NULL)
enc = NULL;
else
- enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
+ enc = EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx);
} else {
ds = s->enc_read_ctx;
if (s->enc_read_ctx == NULL)
enc = NULL;
else
- enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
+ enc = EVP_CIPHER_CTX_get0_cipher(s->enc_read_ctx);
}
if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) {
memmove(rec->data, rec->input, rec->length);
rec->input = rec->data;
} else {
+ int provided = (EVP_CIPHER_get0_provider(enc) != NULL);
+
l = rec->length;
- /* TODO(size_t): Convert this call */
- bs = EVP_CIPHER_CTX_block_size(ds);
+ bs = EVP_CIPHER_CTX_get_block_size(ds);
/* COMPRESS */
- if ((bs != 1) && sending) {
+ if ((bs != 1) && sending && !provided) {
+ /*
+ * We only do this for legacy ciphers. Provided ciphers add the
+ * padding on the provider side.
+ */
i = bs - (l % bs);
/* we need to add 'i-1' padding bytes */
@@ -897,67 +893,95 @@ int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int sending)
}
if (!sending) {
- if (l == 0 || l % bs != 0)
+ if (l == 0 || l % bs != 0) {
+ /* Publicly invalid */
return 0;
+ }
/* otherwise, rec->length >= bs */
}
- /* TODO(size_t): Convert this call */
- if (EVP_Cipher(ds, rec->data, rec->input, (unsigned int)l) < 1)
- return -1;
+ if (EVP_CIPHER_get0_provider(enc) != NULL) {
+ int outlen;
- if (EVP_MD_CTX_md(s->read_hash) != NULL) {
- /* TODO(size_t): convert me */
- imac_size = EVP_MD_CTX_size(s->read_hash);
- if (imac_size < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ if (!EVP_CipherUpdate(ds, rec->data, &outlen, rec->input,
+ (unsigned int)l))
+ return 0;
+ rec->length = outlen;
+
+ if (!sending && mac != NULL) {
+ /* Now get a pointer to the MAC */
+ OSSL_PARAM params[2], *p = params;
+
+ /* Get the MAC */
+ mac->alloced = 0;
+
+ *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_TLS_MAC,
+ (void **)&mac->mac,
+ macsize);
+ *p = OSSL_PARAM_construct_end();
+
+ if (!EVP_CIPHER_CTX_get_params(ds, params)) {
+ /* Shouldn't normally happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
}
- mac_size = (size_t)imac_size;
+ } else {
+ if (EVP_Cipher(ds, rec->data, rec->input, (unsigned int)l) < 1) {
+ /* Shouldn't happen */
+ SSLfatal(s, SSL_AD_BAD_RECORD_MAC, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (!sending)
+ return ssl3_cbc_remove_padding_and_mac(&rec->length,
+ rec->orig_len,
+ rec->data,
+ (mac != NULL) ? &mac->mac : NULL,
+ (mac != NULL) ? &mac->alloced : NULL,
+ bs,
+ macsize,
+ s->ctx->libctx);
}
- if ((bs != 1) && !sending)
- return ssl3_cbc_remove_padding(rec, bs, mac_size);
}
return 1;
}
#define MAX_PADDING 256
/*-
- * tls1_enc encrypts/decrypts |n_recs| in |recs|. Will call SSLfatal() for
- * internal errors, but not otherwise.
+ * tls1_enc encrypts/decrypts |n_recs| in |recs|. Calls SSLfatal on internal
+ * error, but not otherwise. It is the responsibility of the caller to report
+ * a bad_record_mac - if appropriate (DTLS just drops the record).
*
* Returns:
- * 0: (in non-constant time) if the record is publicly invalid (i.e. too
- * short etc).
- * 1: if the record's padding is valid / the encryption was successful.
- * -1: if the record's padding/AEAD-authenticator is invalid or, if sending,
- * an internal error occurred.
+ * 0: if the record is publicly invalid, or an internal error, or AEAD
+ * decryption failed, or Encrypt-then-mac decryption failed.
+ * 1: Success or Mac-then-encrypt decryption failed (MAC will be randomised)
*/
-int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
+int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending,
+ SSL_MAC_BUF *macs, size_t macsize)
{
EVP_CIPHER_CTX *ds;
size_t reclen[SSL_MAX_PIPELINES];
unsigned char buf[SSL_MAX_PIPELINES][EVP_AEAD_TLS1_AAD_LEN];
- int i, pad = 0, ret, tmpr;
- size_t bs, mac_size = 0, ctr, padnum, loop;
+ int i, pad = 0, tmpr;
+ size_t bs, ctr, padnum, loop;
unsigned char padval;
- int imac_size;
const EVP_CIPHER *enc;
+ int tlstree_enc = sending ? (s->mac_flags & SSL_MAC_FLAG_WRITE_MAC_TLSTREE)
+ : (s->mac_flags & SSL_MAC_FLAG_READ_MAC_TLSTREE);
if (n_recs == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (sending) {
- if (EVP_MD_CTX_md(s->write_hash)) {
- int n = EVP_MD_CTX_size(s->write_hash);
+ if (EVP_MD_CTX_get0_md(s->write_hash)) {
+ int n = EVP_MD_CTX_get_size(s->write_hash);
if (!ossl_assert(n >= 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
}
ds = s->enc_write_ctx;
@@ -965,11 +989,12 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
enc = NULL;
else {
int ivlen;
- enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
+
+ enc = EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx);
/* For TLSv1.1 and later explicit IV */
if (SSL_USE_EXPLICIT_IV(s)
- && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE)
- ivlen = EVP_CIPHER_iv_length(enc);
+ && EVP_CIPHER_get_mode(enc) == EVP_CIPH_CBC_MODE)
+ ivlen = EVP_CIPHER_get_iv_length(enc);
else
ivlen = 0;
if (ivlen > 1) {
@@ -979,31 +1004,29 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
* we can't write into the input stream: Can this ever
* happen?? (steve)
*/
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
- } else if (RAND_bytes(recs[ctr].input, ivlen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ } else if (RAND_bytes_ex(s->ctx->libctx, recs[ctr].input,
+ ivlen, 0) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
}
}
}
} else {
- if (EVP_MD_CTX_md(s->read_hash)) {
- int n = EVP_MD_CTX_size(s->read_hash);
+ if (EVP_MD_CTX_get0_md(s->read_hash)) {
+ int n = EVP_MD_CTX_get_size(s->read_hash);
if (!ossl_assert(n >= 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
}
ds = s->enc_read_ctx;
if (s->enc_read_ctx == NULL)
enc = NULL;
else
- enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
+ enc = EVP_CIPHER_CTX_get0_cipher(s->enc_read_ctx);
}
if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) {
@@ -1011,27 +1034,27 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
memmove(recs[ctr].data, recs[ctr].input, recs[ctr].length);
recs[ctr].input = recs[ctr].data;
}
- ret = 1;
} else {
- bs = EVP_CIPHER_block_size(EVP_CIPHER_CTX_cipher(ds));
+ int provided = (EVP_CIPHER_get0_provider(enc) != NULL);
+
+ bs = EVP_CIPHER_get_block_size(EVP_CIPHER_CTX_get0_cipher(ds));
if (n_recs > 1) {
- if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds))
- & EVP_CIPH_FLAG_PIPELINE)) {
+ if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ds))
+ & EVP_CIPH_FLAG_PIPELINE) == 0) {
/*
* We shouldn't have been called with pipeline data if the
* cipher doesn't support pipelining
*/
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- SSL_R_PIPELINE_FAILURE);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_PIPELINE_FAILURE);
+ return 0;
}
}
for (ctr = 0; ctr < n_recs; ctr++) {
reclen[ctr] = recs[ctr].length;
- if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds))
- & EVP_CIPH_FLAG_AEAD_CIPHER) {
+ if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ds))
+ & EVP_CIPH_FLAG_AEAD_CIPHER) != 0) {
unsigned char *seq;
seq = sending ? RECORD_LAYER_get_write_sequence(&s->rlayer)
@@ -1062,9 +1085,8 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD,
EVP_AEAD_TLS1_AAD_LEN, buf[ctr]);
if (pad <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
if (sending) {
@@ -1072,15 +1094,18 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
recs[ctr].length += pad;
}
- } else if ((bs != 1) && sending) {
+ } else if ((bs != 1) && sending && !provided) {
+ /*
+ * We only do this for legacy ciphers. Provided ciphers add the
+ * padding on the provider side.
+ */
padnum = bs - (reclen[ctr] % bs);
/* Add weird padding of up to 256 bytes */
if (padnum > MAX_PADDING) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
/* we need to add 'padnum' padding bytes of value padval */
padval = (unsigned char)(padnum - 1);
@@ -1091,8 +1116,10 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
}
if (!sending) {
- if (reclen[ctr] == 0 || reclen[ctr] % bs != 0)
+ if (reclen[ctr] == 0 || reclen[ctr] % bs != 0) {
+ /* Publicly invalid */
return 0;
+ }
}
}
if (n_recs > 1) {
@@ -1104,9 +1131,8 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
}
if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS,
(int)n_recs, data) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- SSL_R_PIPELINE_FAILURE);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_PIPELINE_FAILURE);
+ return 0;
}
/* Set the input buffers */
for (ctr = 0; ctr < n_recs; ctr++) {
@@ -1116,69 +1142,156 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
(int)n_recs, data) <= 0
|| EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_INPUT_LENS,
(int)n_recs, reclen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- SSL_R_PIPELINE_FAILURE);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_PIPELINE_FAILURE);
+ return 0;
}
}
- /* TODO(size_t): Convert this call */
- tmpr = EVP_Cipher(ds, recs[0].data, recs[0].input,
- (unsigned int)reclen[0]);
- if ((EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds))
- & EVP_CIPH_FLAG_CUSTOM_CIPHER)
- ? (tmpr < 0)
- : (tmpr == 0))
- return -1; /* AEAD can fail to verify MAC */
-
- if (sending == 0) {
- if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE) {
- for (ctr = 0; ctr < n_recs; ctr++) {
- recs[ctr].data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
- recs[ctr].input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
- recs[ctr].length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
- }
- } else if (EVP_CIPHER_mode(enc) == EVP_CIPH_CCM_MODE) {
- for (ctr = 0; ctr < n_recs; ctr++) {
- recs[ctr].data += EVP_CCM_TLS_EXPLICIT_IV_LEN;
- recs[ctr].input += EVP_CCM_TLS_EXPLICIT_IV_LEN;
- recs[ctr].length -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
- }
+ if (!SSL_IS_DTLS(s) && tlstree_enc) {
+ unsigned char *seq;
+ int decrement_seq = 0;
+
+ /*
+ * When sending, seq is incremented after MAC calculation.
+ * So if we are in ETM mode, we use seq 'as is' in the ctrl-function.
+ * Otherwise we have to decrease it in the implementation
+ */
+ if (sending && !SSL_WRITE_ETM(s))
+ decrement_seq = 1;
+
+ seq = sending ? RECORD_LAYER_get_write_sequence(&s->rlayer)
+ : RECORD_LAYER_get_read_sequence(&s->rlayer);
+ if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_TLSTREE, decrement_seq, seq) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
}
- ret = 1;
- if (!SSL_READ_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL) {
- imac_size = EVP_MD_CTX_size(s->read_hash);
- if (imac_size < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ if (provided) {
+ int outlen;
+
+ /* Provided cipher - we do not support pipelining on this path */
+ if (n_recs > 1) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
- mac_size = (size_t)imac_size;
- }
- if ((bs != 1) && !sending) {
- int tmpret;
- for (ctr = 0; ctr < n_recs; ctr++) {
- tmpret = tls1_cbc_remove_padding(s, &recs[ctr], bs, mac_size);
- /*
- * If tmpret == 0 then this means publicly invalid so we can
- * short circuit things here. Otherwise we must respect constant
- * time behaviour.
- */
- if (tmpret == 0)
- return 0;
- ret = constant_time_select_int(constant_time_eq_int(tmpret, 1),
- ret, -1);
+
+ if (!EVP_CipherUpdate(ds, recs[0].data, &outlen, recs[0].input,
+ (unsigned int)reclen[0]))
+ return 0;
+ recs[0].length = outlen;
+
+ /*
+ * The length returned from EVP_CipherUpdate above is the actual
+ * payload length. We need to adjust the data/input ptr to skip over
+ * any explicit IV
+ */
+ if (!sending) {
+ if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_GCM_MODE) {
+ recs[0].data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ recs[0].input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ } else if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_CCM_MODE) {
+ recs[0].data += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ recs[0].input += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ } else if (bs != 1 && SSL_USE_EXPLICIT_IV(s)) {
+ recs[0].data += bs;
+ recs[0].input += bs;
+ recs[0].orig_len -= bs;
+ }
+
+ /* Now get a pointer to the MAC (if applicable) */
+ if (macs != NULL) {
+ OSSL_PARAM params[2], *p = params;
+
+ /* Get the MAC */
+ macs[0].alloced = 0;
+
+ *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_TLS_MAC,
+ (void **)&macs[0].mac,
+ macsize);
+ *p = OSSL_PARAM_construct_end();
+
+ if (!EVP_CIPHER_CTX_get_params(ds, params)) {
+ /* Shouldn't normally happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
}
- }
- if (pad && !sending) {
- for (ctr = 0; ctr < n_recs; ctr++) {
- recs[ctr].length -= pad;
+ } else {
+ /* Legacy cipher */
+
+ tmpr = EVP_Cipher(ds, recs[0].data, recs[0].input,
+ (unsigned int)reclen[0]);
+ if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ds))
+ & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0
+ ? (tmpr < 0)
+ : (tmpr == 0)) {
+ /* AEAD can fail to verify MAC */
+ return 0;
+ }
+
+ if (!sending) {
+ for (ctr = 0; ctr < n_recs; ctr++) {
+ /* Adjust the record to remove the explicit IV/MAC/Tag */
+ if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_GCM_MODE) {
+ recs[ctr].data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ recs[ctr].input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ recs[ctr].length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ } else if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_CCM_MODE) {
+ recs[ctr].data += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ recs[ctr].input += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ recs[ctr].length -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ } else if (bs != 1 && SSL_USE_EXPLICIT_IV(s)) {
+ if (recs[ctr].length < bs)
+ return 0;
+ recs[ctr].data += bs;
+ recs[ctr].input += bs;
+ recs[ctr].length -= bs;
+ recs[ctr].orig_len -= bs;
+ }
+
+ /*
+ * If using Mac-then-encrypt, then this will succeed but
+ * with a random MAC if padding is invalid
+ */
+ if (!tls1_cbc_remove_padding_and_mac(&recs[ctr].length,
+ recs[ctr].orig_len,
+ recs[ctr].data,
+ (macs != NULL) ? &macs[ctr].mac : NULL,
+ (macs != NULL) ? &macs[ctr].alloced
+ : NULL,
+ bs,
+ pad ? (size_t)pad : macsize,
+ (EVP_CIPHER_get_flags(enc)
+ & EVP_CIPH_FLAG_AEAD_CIPHER) != 0,
+ s->ctx->libctx))
+ return 0;
+ }
}
}
}
- return ret;
+ return 1;
+}
+
+/*
+ * ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function
+ * which ssl3_cbc_digest_record supports.
+ */
+char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
+{
+ switch (EVP_MD_CTX_get_type(ctx)) {
+ case NID_md5:
+ case NID_sha1:
+ case NID_sha224:
+ case NID_sha256:
+ case NID_sha384:
+ case NID_sha512:
+ return 1;
+ default:
+ return 0;
+ }
}
int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
@@ -1191,24 +1304,27 @@ int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
int t;
if (sending) {
- mac_sec = &(ssl->s3->write_mac_secret[0]);
+ mac_sec = &(ssl->s3.write_mac_secret[0]);
seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer);
hash = ssl->write_hash;
} else {
- mac_sec = &(ssl->s3->read_mac_secret[0]);
+ mac_sec = &(ssl->s3.read_mac_secret[0]);
seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer);
hash = ssl->read_hash;
}
- t = EVP_MD_CTX_size(hash);
- if (t < 0)
+ t = EVP_MD_CTX_get_size(hash);
+ if (t <= 0)
return 0;
md_size = t;
npad = (48 / md_size) * md_size;
- if (!sending &&
- EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
- ssl3_cbc_record_digest_supported(hash)) {
+ if (!sending
+ && EVP_CIPHER_CTX_get_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE
+ && ssl3_cbc_record_digest_supported(hash)) {
+#ifdef OPENSSL_NO_DEPRECATED_3_0
+ return 0;
+#else
/*
* This is a CBC-encrypted record. We must avoid leaking any
* timing-side channel information about how many blocks of data we
@@ -1236,12 +1352,13 @@ int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
header[j++] = (unsigned char)(rec->length & 0xff);
/* Final param == is SSLv3 */
- if (ssl3_cbc_digest_record(hash,
+ if (ssl3_cbc_digest_record(EVP_MD_CTX_get0_md(hash),
md, &md_size,
header, rec->input,
- rec->length + md_size, rec->orig_len,
+ rec->length, rec->orig_len,
mac_sec, md_size, 1) <= 0)
return 0;
+#endif
} else {
unsigned int md_size_u;
/* Chop the digest off the end :-) */
@@ -1285,9 +1402,12 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
int i;
EVP_MD_CTX *hmac = NULL, *mac_ctx;
unsigned char header[13];
- int stream_mac = (sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM)
- : (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM));
+ int stream_mac = sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM)
+ : (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM);
+ int tlstree_mac = sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_TLSTREE)
+ : (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_TLSTREE);
int t;
+ int ret = 0;
if (sending) {
seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer);
@@ -1297,7 +1417,7 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
hash = ssl->read_hash;
}
- t = EVP_MD_CTX_size(hash);
+ t = EVP_MD_CTX_get_size(hash);
if (!ossl_assert(t >= 0))
return 0;
md_size = t;
@@ -1308,12 +1428,15 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
} else {
hmac = EVP_MD_CTX_new();
if (hmac == NULL || !EVP_MD_CTX_copy(hmac, hash)) {
- EVP_MD_CTX_free(hmac);
- return 0;
+ goto end;
}
mac_ctx = hmac;
}
+ if (!SSL_IS_DTLS(ssl) && tlstree_mac && EVP_MD_CTX_ctrl(mac_ctx, EVP_MD_CTRL_TLSTREE, 0, seq) <= 0) {
+ goto end;
+ }
+
if (SSL_IS_DTLS(ssl)) {
unsigned char dtlsseq[8], *p = dtlsseq;
@@ -1331,52 +1454,33 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
header[11] = (unsigned char)(rec->length >> 8);
header[12] = (unsigned char)(rec->length & 0xff);
- if (!sending && !SSL_READ_ETM(ssl) &&
- EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
- ssl3_cbc_record_digest_supported(mac_ctx)) {
- /*
- * This is a CBC-encrypted record. We must avoid leaking any
- * timing-side channel information about how many blocks of data we
- * are hashing because that gives an attacker a timing-oracle.
- */
- /* Final param == not SSLv3 */
- if (ssl3_cbc_digest_record(mac_ctx,
- md, &md_size,
- header, rec->input,
- rec->length + md_size, rec->orig_len,
- ssl->s3->read_mac_secret,
- ssl->s3->read_mac_secret_size, 0) <= 0) {
- EVP_MD_CTX_free(hmac);
- return 0;
- }
- } else {
- /* TODO(size_t): Convert these calls */
- if (EVP_DigestSignUpdate(mac_ctx, header, sizeof(header)) <= 0
- || EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length) <= 0
- || EVP_DigestSignFinal(mac_ctx, md, &md_size) <= 0) {
- EVP_MD_CTX_free(hmac);
- return 0;
- }
- }
+ if (!sending && !SSL_READ_ETM(ssl)
+ && EVP_CIPHER_CTX_get_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE
+ && ssl3_cbc_record_digest_supported(mac_ctx)) {
+ OSSL_PARAM tls_hmac_params[2], *p = tls_hmac_params;
- EVP_MD_CTX_free(hmac);
+ *p++ = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_TLS_DATA_SIZE,
+ &rec->orig_len);
+ *p++ = OSSL_PARAM_construct_end();
-#ifdef SSL_DEBUG
- fprintf(stderr, "seq=");
- {
- int z;
- for (z = 0; z < 8; z++)
- fprintf(stderr, "%02X ", seq[z]);
- fprintf(stderr, "\n");
+ if (!EVP_PKEY_CTX_set_params(EVP_MD_CTX_get_pkey_ctx(mac_ctx),
+ tls_hmac_params)) {
+ goto end;
+ }
}
- fprintf(stderr, "rec=");
- {
- size_t z;
- for (z = 0; z < rec->length; z++)
- fprintf(stderr, "%02X ", rec->data[z]);
- fprintf(stderr, "\n");
+
+ if (EVP_DigestSignUpdate(mac_ctx, header, sizeof(header)) <= 0
+ || EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length) <= 0
+ || EVP_DigestSignFinal(mac_ctx, md, &md_size) <= 0) {
+ goto end;
}
-#endif
+
+ OSSL_TRACE_BEGIN(TLS) {
+ BIO_printf(trc_out, "seq:\n");
+ BIO_dump_indent(trc_out, seq, 8, 4);
+ BIO_printf(trc_out, "rec:\n");
+ BIO_dump_indent(trc_out, rec->data, rec->length, 4);
+ } OSSL_TRACE_END(TLS);
if (!SSL_IS_DTLS(ssl)) {
for (i = 7; i >= 0; i--) {
@@ -1385,228 +1489,14 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
break;
}
}
-#ifdef SSL_DEBUG
- {
- unsigned int z;
- for (z = 0; z < md_size; z++)
- fprintf(stderr, "%02X ", md[z]);
- fprintf(stderr, "\n");
- }
-#endif
- return 1;
-}
-
-/*-
- * ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC
- * record in |rec| by updating |rec->length| in constant time.
- *
- * block_size: the block size of the cipher used to encrypt the record.
- * returns:
- * 0: (in non-constant time) if the record is publicly invalid.
- * 1: if the padding was valid
- * -1: otherwise.
- */
-int ssl3_cbc_remove_padding(SSL3_RECORD *rec,
- size_t block_size, size_t mac_size)
-{
- size_t padding_length;
- size_t good;
- const size_t overhead = 1 /* padding length byte */ + mac_size;
-
- /*
- * These lengths are all public so we can test them in non-constant time.
- */
- if (overhead > rec->length)
- return 0;
-
- padding_length = rec->data[rec->length - 1];
- good = constant_time_ge_s(rec->length, padding_length + overhead);
- /* SSLv3 requires that the padding is minimal. */
- good &= constant_time_ge_s(block_size, padding_length + 1);
- rec->length -= good & (padding_length + 1);
- return constant_time_select_int_s(good, 1, -1);
-}
-
-/*-
- * tls1_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC
- * record in |rec| in constant time and returns 1 if the padding is valid and
- * -1 otherwise. It also removes any explicit IV from the start of the record
- * without leaking any timing about whether there was enough space after the
- * padding was removed.
- *
- * block_size: the block size of the cipher used to encrypt the record.
- * returns:
- * 0: (in non-constant time) if the record is publicly invalid.
- * 1: if the padding was valid
- * -1: otherwise.
- */
-int tls1_cbc_remove_padding(const SSL *s,
- SSL3_RECORD *rec,
- size_t block_size, size_t mac_size)
-{
- size_t good;
- size_t padding_length, to_check, i;
- const size_t overhead = 1 /* padding length byte */ + mac_size;
- /* Check if version requires explicit IV */
- if (SSL_USE_EXPLICIT_IV(s)) {
- /*
- * These lengths are all public so we can test them in non-constant
- * time.
- */
- if (overhead + block_size > rec->length)
- return 0;
- /* We can now safely skip explicit IV */
- rec->data += block_size;
- rec->input += block_size;
- rec->length -= block_size;
- rec->orig_len -= block_size;
- } else if (overhead > rec->length)
- return 0;
-
- padding_length = rec->data[rec->length - 1];
-
- if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_read_ctx)) &
- EVP_CIPH_FLAG_AEAD_CIPHER) {
- /* padding is already verified */
- rec->length -= padding_length + 1;
- return 1;
- }
-
- good = constant_time_ge_s(rec->length, overhead + padding_length);
- /*
- * The padding consists of a length byte at the end of the record and
- * then that many bytes of padding, all with the same value as the length
- * byte. Thus, with the length byte included, there are i+1 bytes of
- * padding. We can't check just |padding_length+1| bytes because that
- * leaks decrypted information. Therefore we always have to check the
- * maximum amount of padding possible. (Again, the length of the record
- * is public information so we can use it.)
- */
- to_check = 256; /* maximum amount of padding, inc length byte. */
- if (to_check > rec->length)
- to_check = rec->length;
-
- for (i = 0; i < to_check; i++) {
- unsigned char mask = constant_time_ge_8_s(padding_length, i);
- unsigned char b = rec->data[rec->length - 1 - i];
- /*
- * The final |padding_length+1| bytes should all have the value
- * |padding_length|. Therefore the XOR should be zero.
- */
- good &= ~(mask & (padding_length ^ b));
- }
-
- /*
- * If any of the final |padding_length+1| bytes had the wrong value, one
- * or more of the lower eight bits of |good| will be cleared.
- */
- good = constant_time_eq_s(0xff, good & 0xff);
- rec->length -= good & (padding_length + 1);
-
- return constant_time_select_int_s(good, 1, -1);
-}
-
-/*-
- * ssl3_cbc_copy_mac copies |md_size| bytes from the end of |rec| to |out| in
- * constant time (independent of the concrete value of rec->length, which may
- * vary within a 256-byte window).
- *
- * ssl3_cbc_remove_padding or tls1_cbc_remove_padding must be called prior to
- * this function.
- *
- * On entry:
- * rec->orig_len >= md_size
- * md_size <= EVP_MAX_MD_SIZE
- *
- * If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with
- * variable accesses in a 64-byte-aligned buffer. Assuming that this fits into
- * a single or pair of cache-lines, then the variable memory accesses don't
- * actually affect the timing. CPUs with smaller cache-lines [if any] are
- * not multi-core and are not considered vulnerable to cache-timing attacks.
- */
-#define CBC_MAC_ROTATE_IN_PLACE
-
-int ssl3_cbc_copy_mac(unsigned char *out,
- const SSL3_RECORD *rec, size_t md_size)
-{
-#if defined(CBC_MAC_ROTATE_IN_PLACE)
- unsigned char rotated_mac_buf[64 + EVP_MAX_MD_SIZE];
- unsigned char *rotated_mac;
- char aux1, aux2, aux3, mask;
-#else
- unsigned char rotated_mac[EVP_MAX_MD_SIZE];
-#endif
-
- /*
- * mac_end is the index of |rec->data| just after the end of the MAC.
- */
- size_t mac_end = rec->length;
- size_t mac_start = mac_end - md_size;
- size_t in_mac;
- /*
- * scan_start contains the number of bytes that we can ignore because the
- * MAC's position can only vary by 255 bytes.
- */
- size_t scan_start = 0;
- size_t i, j;
- size_t rotate_offset;
-
- if (!ossl_assert(rec->orig_len >= md_size
- && md_size <= EVP_MAX_MD_SIZE))
- return 0;
-
-#if defined(CBC_MAC_ROTATE_IN_PLACE)
- rotated_mac = rotated_mac_buf + ((0 - (size_t)rotated_mac_buf) & 63);
-#endif
-
- /* This information is public so it's safe to branch based on it. */
- if (rec->orig_len > md_size + 255 + 1)
- scan_start = rec->orig_len - (md_size + 255 + 1);
-
- in_mac = 0;
- rotate_offset = 0;
- memset(rotated_mac, 0, md_size);
- for (i = scan_start, j = 0; i < rec->orig_len; i++) {
- size_t mac_started = constant_time_eq_s(i, mac_start);
- size_t mac_ended = constant_time_lt_s(i, mac_end);
- unsigned char b = rec->data[i];
-
- in_mac |= mac_started;
- in_mac &= mac_ended;
- rotate_offset |= j & mac_started;
- rotated_mac[j++] |= b & in_mac;
- j &= constant_time_lt_s(j, md_size);
- }
-
- /* Now rotate the MAC */
-#if defined(CBC_MAC_ROTATE_IN_PLACE)
- j = 0;
- for (i = 0; i < md_size; i++) {
- /*
- * in case cache-line is 32 bytes,
- * load from both lines and select appropriately
- */
- aux1 = rotated_mac[rotate_offset & ~32];
- aux2 = rotated_mac[rotate_offset | 32];
- mask = constant_time_eq_8(rotate_offset & ~32, rotate_offset);
- aux3 = constant_time_select_8(mask, aux1, aux2);
- out[j++] = aux3;
- rotate_offset++;
- rotate_offset &= constant_time_lt_s(rotate_offset, md_size);
- }
-#else
- memset(out, 0, md_size);
- rotate_offset = md_size - rotate_offset;
- rotate_offset &= constant_time_lt_s(rotate_offset, md_size);
- for (i = 0; i < md_size; i++) {
- for (j = 0; j < md_size; j++)
- out[j] |= rotated_mac[i] & constant_time_eq_8_s(j, rotate_offset);
- rotate_offset++;
- rotate_offset &= constant_time_lt_s(rotate_offset, md_size);
- }
-#endif
-
- return 1;
+ OSSL_TRACE_BEGIN(TLS) {
+ BIO_printf(trc_out, "md:\n");
+ BIO_dump_indent(trc_out, md, md_size, 4);
+ } OSSL_TRACE_END(TLS);
+ ret = 1;
+ end:
+ EVP_MD_CTX_free(hmac);
+ return ret;
}
int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
@@ -1616,9 +1506,11 @@ int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
SSL_SESSION *sess;
SSL3_RECORD *rr;
int imac_size;
- size_t mac_size;
+ size_t mac_size = 0;
unsigned char md[EVP_MAX_MD_SIZE];
size_t max_plain_length = SSL3_RT_MAX_PLAIN_LENGTH;
+ SSL_MAC_BUF macbuf = { NULL, 0 };
+ int ret = 0;
rr = RECORD_LAYER_get_rrec(&s->rlayer);
sess = s->session;
@@ -1643,8 +1535,7 @@ int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
/* check is not needed I believe */
if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_DTLS1_PROCESS_RECORD,
- SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
return 0;
}
@@ -1652,142 +1543,104 @@ int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
rr->data = rr->input;
rr->orig_len = rr->length;
+ if (s->read_hash != NULL) {
+ const EVP_MD *tmpmd = EVP_MD_CTX_get0_md(s->read_hash);
+
+ if (tmpmd != NULL) {
+ imac_size = EVP_MD_get_size(tmpmd);
+ if (!ossl_assert(imac_size >= 0 && imac_size <= EVP_MAX_MD_SIZE)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ return 0;
+ }
+ mac_size = (size_t)imac_size;
+ }
+ }
+
if (SSL_READ_ETM(s) && s->read_hash) {
unsigned char *mac;
- mac_size = EVP_MD_CTX_size(s->read_hash);
- if (!ossl_assert(mac_size <= EVP_MAX_MD_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
+
if (rr->orig_len < mac_size) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
- SSL_R_LENGTH_TOO_SHORT);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
return 0;
}
rr->length -= mac_size;
mac = rr->data + rr->length;
i = s->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
if (i == 0 || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) {
- SSLfatal(s, SSL_AD_BAD_RECORD_MAC, SSL_F_DTLS1_PROCESS_RECORD,
- SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+ SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
+ SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
return 0;
}
+ /*
+ * We've handled the mac now - there is no MAC inside the encrypted
+ * record
+ */
+ mac_size = 0;
}
- enc_err = s->method->ssl3_enc->enc(s, rr, 1, 0);
+ /*
+ * Set a mark around the packet decryption attempt. This is DTLS, so
+ * bad packets are just ignored, and we don't want to leave stray
+ * errors in the queue from processing bogus junk that we ignored.
+ */
+ ERR_set_mark();
+ enc_err = s->method->ssl3_enc->enc(s, rr, 1, 0, &macbuf, mac_size);
+
/*-
* enc_err is:
- * 0: (in non-constant time) if the record is publicly invalid.
- * 1: if the padding is valid
- * -1: if the padding is invalid
+ * 0: if the record is publicly invalid, or an internal error, or AEAD
+ * decryption failed, or ETM decryption failed.
+ * 1: Success or MTE decryption failed (MAC will be randomised)
*/
if (enc_err == 0) {
+ ERR_pop_to_mark();
if (ossl_statem_in_error(s)) {
/* SSLfatal() got called */
- return 0;
+ goto end;
}
/* For DTLS we simply ignore bad packets. */
rr->length = 0;
RECORD_LAYER_reset_packet_length(&s->rlayer);
- return 0;
- }
-#ifdef SSL_DEBUG
- printf("dec %ld\n", rr->length);
- {
- size_t z;
- for (z = 0; z < rr->length; z++)
- printf("%02X%c", rr->data[z], ((z + 1) % 16) ? ' ' : '\n');
+ goto end;
}
- printf("\n");
-#endif
+ ERR_clear_last_mark();
+ OSSL_TRACE_BEGIN(TLS) {
+ BIO_printf(trc_out, "dec %zd\n", rr->length);
+ BIO_dump_indent(trc_out, rr->data, rr->length, 4);
+ } OSSL_TRACE_END(TLS);
/* r->length is now the compressed data plus mac */
- if ((sess != NULL) && !SSL_READ_ETM(s) &&
- (s->enc_read_ctx != NULL) && (EVP_MD_CTX_md(s->read_hash) != NULL)) {
+ if ((sess != NULL)
+ && !SSL_READ_ETM(s)
+ && (s->enc_read_ctx != NULL)
+ && (EVP_MD_CTX_get0_md(s->read_hash) != NULL)) {
/* s->read_hash != NULL => mac_size != -1 */
- unsigned char *mac = NULL;
- unsigned char mac_tmp[EVP_MAX_MD_SIZE];
-
- /* TODO(size_t): Convert this to do size_t properly */
- imac_size = EVP_MD_CTX_size(s->read_hash);
- if (imac_size < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
- ERR_LIB_EVP);
- return 0;
- }
- mac_size = (size_t)imac_size;
- if (!ossl_assert(mac_size <= EVP_MAX_MD_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /*
- * orig_len is the length of the record before any padding was
- * removed. This is public information, as is the MAC in use,
- * therefore we can safely process the record in a different amount
- * of time if it's too short to possibly contain a MAC.
- */
- if (rr->orig_len < mac_size ||
- /* CBC records must have a padding length byte too. */
- (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
- rr->orig_len < mac_size + 1)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
- SSL_R_LENGTH_TOO_SHORT);
- return 0;
- }
-
- if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) {
- /*
- * We update the length so that the TLS header bytes can be
- * constructed correctly but we need to extract the MAC in
- * constant time from within the record, without leaking the
- * contents of the padding bytes.
- */
- mac = mac_tmp;
- if (!ssl3_cbc_copy_mac(mac_tmp, rr, mac_size)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- rr->length -= mac_size;
- } else {
- /*
- * In this case there's no padding, so |rec->orig_len| equals
- * |rec->length| and we checked that there's enough bytes for
- * |mac_size| above.
- */
- rr->length -= mac_size;
- mac = &rr->data[rr->length];
- }
i = s->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
- if (i == 0 || mac == NULL
- || CRYPTO_memcmp(md, mac, mac_size) != 0)
- enc_err = -1;
+ if (i == 0 || macbuf.mac == NULL
+ || CRYPTO_memcmp(md, macbuf.mac, mac_size) != 0)
+ enc_err = 0;
if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
- enc_err = -1;
+ enc_err = 0;
}
- if (enc_err < 0) {
+ if (enc_err == 0) {
/* decryption failed, silently discard message */
rr->length = 0;
RECORD_LAYER_reset_packet_length(&s->rlayer);
- return 0;
+ goto end;
}
/* r->length is now just compressed */
if (s->expand != NULL) {
if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_DTLS1_PROCESS_RECORD,
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_COMPRESSED_LENGTH_TOO_LONG);
- return 0;
+ goto end;
}
if (!ssl3_do_uncompress(s, rr)) {
- SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE,
- SSL_F_DTLS1_PROCESS_RECORD, SSL_R_BAD_DECOMPRESSION);
- return 0;
+ SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE, SSL_R_BAD_DECOMPRESSION);
+ goto end;
}
}
@@ -1797,19 +1650,18 @@ int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
/* send overflow if the plaintext is too long now it has passed MAC */
if (rr->length > max_plain_length) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_DTLS1_PROCESS_RECORD,
- SSL_R_DATA_LENGTH_TOO_LONG);
- return 0;
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
+ goto end;
}
rr->off = 0;
/*-
* So at this point the following is true
- * ssl->s3->rrec.type is the type of record
- * ssl->s3->rrec.length == number of bytes in record
- * ssl->s3->rrec.off == offset to first valid byte
- * ssl->s3->rrec.data == where to take bytes from, increment
- * after use :-).
+ * ssl->s3.rrec.type is the type of record
+ * ssl->s3.rrec.length == number of bytes in record
+ * ssl->s3.rrec.off == offset to first valid byte
+ * ssl->s3.rrec.data == where to take bytes from, increment
+ * after use :-).
*/
/* we have pulled in a full packet so zero things */
@@ -1818,7 +1670,11 @@ int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
/* Mark receipt of record. */
dtls1_record_bitmap_update(s, bitmap);
- return 1;
+ ret = 1;
+ end:
+ if (macbuf.alloced)
+ OPENSSL_free(macbuf.mac);
+ return ret;
}
/*
@@ -1833,9 +1689,9 @@ int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
* It will return <= 0 if more data is needed, normally due to an error
* or non-blocking IO.
* When it finishes, one packet has been decoded and can be found in
- * ssl->s3->rrec.type - is the type of record
- * ssl->s3->rrec.data, - data
- * ssl->s3->rrec.length, - number of bytes
+ * ssl->s3.rrec.type - is the type of record
+ * ssl->s3.rrec.data - data
+ * ssl->s3.rrec.length - number of bytes
*/
/* used only by dtls1_read_bytes */
int dtls1_get_record(SSL *s)
@@ -1990,10 +1846,6 @@ int dtls1_get_record(SSL *s)
if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) {
#endif
/* Check whether this is a repeat, or aged record. */
- /*
- * TODO: Does it make sense to have replay protection in epoch 0 where
- * we have no integrity negotiated yet?
- */
if (!dtls1_record_replay_check(s, bitmap)) {
rr->length = 0;
rr->read = 1;
diff --git a/ssl/record/ssl3_record_tls13.c b/ssl/record/ssl3_record_tls13.c
index ab50e3762499..c605fa74d217 100644
--- a/ssl/record/ssl3_record_tls13.c
+++ b/ssl/record/ssl3_record_tls13.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,21 +12,21 @@
#include "internal/cryptlib.h"
/*-
- * tls13_enc encrypts/decrypts |n_recs| in |recs|. Will call SSLfatal() for
- * internal errors, but not otherwise.
+ * tls13_enc encrypts/decrypts |n_recs| in |recs|. Calls SSLfatal on internal
+ * error, but not otherwise. It is the responsibility of the caller to report
+ * a bad_record_mac.
*
* Returns:
- * 0: (in non-constant time) if the record is publicly invalid (i.e. too
- * short etc).
- * 1: if the record encryption was successful.
- * -1: if the record's AEAD-authenticator is invalid or, if sending,
- * an internal error occurred.
+ * 0: On failure
+ * 1: if the record encryption/decryption was successful.
*/
-int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
+int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending,
+ ossl_unused SSL_MAC_BUF *mac, ossl_unused size_t macsize)
{
EVP_CIPHER_CTX *ctx;
unsigned char iv[EVP_MAX_IV_LENGTH], recheader[SSL3_RT_HEADER_LENGTH];
- size_t ivlen, taglen, offset, loop, hdrlen;
+ size_t taglen, offset, loop, hdrlen;
+ int ivlen;
unsigned char *staticiv;
unsigned char *seq;
int lenu, lenf;
@@ -36,10 +36,8 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
if (n_recs != 1) {
/* Should not happen */
- /* TODO(TLS1.3): Support pipelining */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
if (sending) {
@@ -64,7 +62,11 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
return 1;
}
- ivlen = EVP_CIPHER_CTX_iv_length(ctx);
+ ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
+ if (ivlen < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
if (s->early_data_state == SSL_EARLY_DATA_WRITING
|| s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
@@ -73,9 +75,8 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
} else {
if (!ossl_assert(s->psksession != NULL
&& s->psksession->ext.max_early_data > 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
alg_enc = s->psksession->cipher->algorithm_enc;
}
@@ -84,12 +85,11 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
* To get here we must have selected a ciphersuite - otherwise ctx would
* be NULL
*/
- if (!ossl_assert(s->s3->tmp.new_cipher != NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ if (!ossl_assert(s->s3.tmp.new_cipher != NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
- alg_enc = s->s3->tmp.new_cipher->algorithm_enc;
+ alg_enc = s->s3.tmp.new_cipher->algorithm_enc;
}
if (alg_enc & SSL_AESCCM) {
@@ -99,18 +99,16 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
taglen = EVP_CCM_TLS_TAG_LEN;
if (sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen,
NULL) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
} else if (alg_enc & SSL_AESGCM) {
taglen = EVP_GCM_TLS_TAG_LEN;
} else if (alg_enc & SSL_CHACHA20) {
taglen = EVP_CHACHAPOLY_TLS_TAG_LEN;
} else {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
if (!sending) {
@@ -126,9 +124,8 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
/* Set up IV */
if (ivlen < SEQ_NUM_SIZE) {
/* Should not happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
offset = ivlen - SEQ_NUM_SIZE;
memcpy(iv, staticiv, offset);
@@ -143,15 +140,15 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
}
if (loop == 0) {
/* Sequence has wrapped */
- return -1;
+ return 0;
}
- /* TODO(size_t): lenu/lenf should be a size_t but EVP doesn't support it */
if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, sending) <= 0
|| (!sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
taglen,
rec->data + rec->length) <= 0)) {
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
/* Set up the AAD */
@@ -162,8 +159,9 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
|| !WPACKET_get_total_written(&wpkt, &hdrlen)
|| hdrlen != SSL3_RT_HEADER_LENGTH
|| !WPACKET_finish(&wpkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
WPACKET_cleanup(&wpkt);
- return -1;
+ return 0;
}
/*
@@ -179,15 +177,14 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
(unsigned int)rec->length) <= 0
|| EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0
|| (size_t)(lenu + lenf) != rec->length) {
- return -1;
+ return 0;
}
if (sending) {
/* Add the tag */
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen,
rec->data + rec->length) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
rec->length += taglen;
}
diff --git a/ssl/record/tls_pad.c b/ssl/record/tls_pad.c
new file mode 100644
index 000000000000..d79c4e9f6315
--- /dev/null
+++ b/ssl/record/tls_pad.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/rand.h>
+#include <openssl/evp.h>
+#include "internal/constant_time.h"
+#include "internal/cryptlib.h"
+
+/*
+ * This file has no dependencies on the rest of libssl because it is shared
+ * with the providers. It contains functions for low level CBC TLS padding
+ * removal. Responsibility for this lies with the cipher implementations in the
+ * providers. However there are legacy code paths in libssl which also need to
+ * do this. In time those legacy code paths can be removed and this file can be
+ * moved out of libssl.
+ */
+
+static int ssl3_cbc_copy_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
+ unsigned char **mac,
+ int *alloced,
+ size_t block_size,
+ size_t mac_size,
+ size_t good,
+ OSSL_LIB_CTX *libctx);
+
+int ssl3_cbc_remove_padding_and_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
+ unsigned char **mac,
+ int *alloced,
+ size_t block_size, size_t mac_size,
+ OSSL_LIB_CTX *libctx);
+
+int tls1_cbc_remove_padding_and_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
+ unsigned char **mac,
+ int *alloced,
+ size_t block_size, size_t mac_size,
+ int aead,
+ OSSL_LIB_CTX *libctx);
+
+/*-
+ * ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC
+ * record in |recdata| by updating |reclen| in constant time. It also extracts
+ * the MAC from the underlying record and places a pointer to it in |mac|. The
+ * MAC data can either be newly allocated memory, or a pointer inside the
+ * |recdata| buffer. If allocated then |*alloced| is set to 1, otherwise it is
+ * set to 0.
+ *
+ * origreclen: the original record length before any changes were made
+ * block_size: the block size of the cipher used to encrypt the record.
+ * mac_size: the size of the MAC to be extracted
+ * aead: 1 if an AEAD cipher is in use, or 0 otherwise
+ * returns:
+ * 0: if the record is publicly invalid.
+ * 1: if the record is publicly valid. If the padding removal fails then the
+ * MAC returned is random.
+ */
+int ssl3_cbc_remove_padding_and_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
+ unsigned char **mac,
+ int *alloced,
+ size_t block_size, size_t mac_size,
+ OSSL_LIB_CTX *libctx)
+{
+ size_t padding_length;
+ size_t good;
+ const size_t overhead = 1 /* padding length byte */ + mac_size;
+
+ /*
+ * These lengths are all public so we can test them in non-constant time.
+ */
+ if (overhead > *reclen)
+ return 0;
+
+ padding_length = recdata[*reclen - 1];
+ good = constant_time_ge_s(*reclen, padding_length + overhead);
+ /* SSLv3 requires that the padding is minimal. */
+ good &= constant_time_ge_s(block_size, padding_length + 1);
+ *reclen -= good & (padding_length + 1);
+
+ return ssl3_cbc_copy_mac(reclen, origreclen, recdata, mac, alloced,
+ block_size, mac_size, good, libctx);
+}
+
+/*-
+ * tls1_cbc_remove_padding_and_mac removes padding from the decrypted, TLS, CBC
+ * record in |recdata| by updating |reclen| in constant time. It also extracts
+ * the MAC from the underlying record and places a pointer to it in |mac|. The
+ * MAC data can either be newly allocated memory, or a pointer inside the
+ * |recdata| buffer. If allocated then |*alloced| is set to 1, otherwise it is
+ * set to 0.
+ *
+ * origreclen: the original record length before any changes were made
+ * block_size: the block size of the cipher used to encrypt the record.
+ * mac_size: the size of the MAC to be extracted
+ * aead: 1 if an AEAD cipher is in use, or 0 otherwise
+ * returns:
+ * 0: if the record is publicly invalid.
+ * 1: if the record is publicly valid. If the padding removal fails then the
+ * MAC returned is random.
+ */
+int tls1_cbc_remove_padding_and_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
+ unsigned char **mac,
+ int *alloced,
+ size_t block_size, size_t mac_size,
+ int aead,
+ OSSL_LIB_CTX *libctx)
+{
+ size_t good = -1;
+ size_t padding_length, to_check, i;
+ size_t overhead = ((block_size == 1) ? 0 : 1) /* padding length byte */
+ + mac_size;
+
+ /*
+ * These lengths are all public so we can test them in non-constant
+ * time.
+ */
+ if (overhead > *reclen)
+ return 0;
+
+ if (block_size != 1) {
+
+ padding_length = recdata[*reclen - 1];
+
+ if (aead) {
+ /* padding is already verified and we don't need to check the MAC */
+ *reclen -= padding_length + 1 + mac_size;
+ return 1;
+ }
+
+ good = constant_time_ge_s(*reclen, overhead + padding_length);
+ /*
+ * The padding consists of a length byte at the end of the record and
+ * then that many bytes of padding, all with the same value as the
+ * length byte. Thus, with the length byte included, there are i+1 bytes
+ * of padding. We can't check just |padding_length+1| bytes because that
+ * leaks decrypted information. Therefore we always have to check the
+ * maximum amount of padding possible. (Again, the length of the record
+ * is public information so we can use it.)
+ */
+ to_check = 256; /* maximum amount of padding, inc length byte. */
+ if (to_check > *reclen)
+ to_check = *reclen;
+
+ for (i = 0; i < to_check; i++) {
+ unsigned char mask = constant_time_ge_8_s(padding_length, i);
+ unsigned char b = recdata[*reclen - 1 - i];
+ /*
+ * The final |padding_length+1| bytes should all have the value
+ * |padding_length|. Therefore the XOR should be zero.
+ */
+ good &= ~(mask & (padding_length ^ b));
+ }
+
+ /*
+ * If any of the final |padding_length+1| bytes had the wrong value, one
+ * or more of the lower eight bits of |good| will be cleared.
+ */
+ good = constant_time_eq_s(0xff, good & 0xff);
+ *reclen -= good & (padding_length + 1);
+ }
+
+ return ssl3_cbc_copy_mac(reclen, origreclen, recdata, mac, alloced,
+ block_size, mac_size, good, libctx);
+}
+
+/*-
+ * ssl3_cbc_copy_mac copies |md_size| bytes from the end of the record in
+ * |recdata| to |*mac| in constant time (independent of the concrete value of
+ * the record length |reclen|, which may vary within a 256-byte window).
+ *
+ * On entry:
+ * origreclen >= mac_size
+ * mac_size <= EVP_MAX_MD_SIZE
+ *
+ * If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with
+ * variable accesses in a 64-byte-aligned buffer. Assuming that this fits into
+ * a single or pair of cache-lines, then the variable memory accesses don't
+ * actually affect the timing. CPUs with smaller cache-lines [if any] are
+ * not multi-core and are not considered vulnerable to cache-timing attacks.
+ */
+#define CBC_MAC_ROTATE_IN_PLACE
+
+static int ssl3_cbc_copy_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
+ unsigned char **mac,
+ int *alloced,
+ size_t block_size,
+ size_t mac_size,
+ size_t good,
+ OSSL_LIB_CTX *libctx)
+{
+#if defined(CBC_MAC_ROTATE_IN_PLACE)
+ unsigned char rotated_mac_buf[64 + EVP_MAX_MD_SIZE];
+ unsigned char *rotated_mac;
+ char aux1, aux2, aux3, mask;
+#else
+ unsigned char rotated_mac[EVP_MAX_MD_SIZE];
+#endif
+ unsigned char randmac[EVP_MAX_MD_SIZE];
+ unsigned char *out;
+
+ /*
+ * mac_end is the index of |recdata| just after the end of the MAC.
+ */
+ size_t mac_end = *reclen;
+ size_t mac_start = mac_end - mac_size;
+ size_t in_mac;
+ /*
+ * scan_start contains the number of bytes that we can ignore because the
+ * MAC's position can only vary by 255 bytes.
+ */
+ size_t scan_start = 0;
+ size_t i, j;
+ size_t rotate_offset;
+
+ if (!ossl_assert(origreclen >= mac_size
+ && mac_size <= EVP_MAX_MD_SIZE))
+ return 0;
+
+ /* If no MAC then nothing to be done */
+ if (mac_size == 0) {
+ /* No MAC so we can do this in non-constant time */
+ if (good == 0)
+ return 0;
+ return 1;
+ }
+
+ *reclen -= mac_size;
+
+ if (block_size == 1) {
+ /* There's no padding so the position of the MAC is fixed */
+ if (mac != NULL)
+ *mac = &recdata[*reclen];
+ if (alloced != NULL)
+ *alloced = 0;
+ return 1;
+ }
+
+ /* Create the random MAC we will emit if padding is bad */
+ if (RAND_bytes_ex(libctx, randmac, mac_size, 0) <= 0)
+ return 0;
+
+ if (!ossl_assert(mac != NULL && alloced != NULL))
+ return 0;
+ *mac = out = OPENSSL_malloc(mac_size);
+ if (*mac == NULL)
+ return 0;
+ *alloced = 1;
+
+#if defined(CBC_MAC_ROTATE_IN_PLACE)
+ rotated_mac = rotated_mac_buf + ((0 - (size_t)rotated_mac_buf) & 63);
+#endif
+
+ /* This information is public so it's safe to branch based on it. */
+ if (origreclen > mac_size + 255 + 1)
+ scan_start = origreclen - (mac_size + 255 + 1);
+
+ in_mac = 0;
+ rotate_offset = 0;
+ memset(rotated_mac, 0, mac_size);
+ for (i = scan_start, j = 0; i < origreclen; i++) {
+ size_t mac_started = constant_time_eq_s(i, mac_start);
+ size_t mac_ended = constant_time_lt_s(i, mac_end);
+ unsigned char b = recdata[i];
+
+ in_mac |= mac_started;
+ in_mac &= mac_ended;
+ rotate_offset |= j & mac_started;
+ rotated_mac[j++] |= b & in_mac;
+ j &= constant_time_lt_s(j, mac_size);
+ }
+
+ /* Now rotate the MAC */
+#if defined(CBC_MAC_ROTATE_IN_PLACE)
+ j = 0;
+ for (i = 0; i < mac_size; i++) {
+ /*
+ * in case cache-line is 32 bytes,
+ * load from both lines and select appropriately
+ */
+ aux1 = rotated_mac[rotate_offset & ~32];
+ aux2 = rotated_mac[rotate_offset | 32];
+ mask = constant_time_eq_8(rotate_offset & ~32, rotate_offset);
+ aux3 = constant_time_select_8(mask, aux1, aux2);
+ rotate_offset++;
+
+ /* If the padding wasn't good we emit a random MAC */
+ out[j++] = constant_time_select_8((unsigned char)(good & 0xff),
+ aux3,
+ randmac[i]);
+ rotate_offset &= constant_time_lt_s(rotate_offset, mac_size);
+ }
+#else
+ memset(out, 0, mac_size);
+ rotate_offset = mac_size - rotate_offset;
+ rotate_offset &= constant_time_lt_s(rotate_offset, mac_size);
+ for (i = 0; i < mac_size; i++) {
+ for (j = 0; j < mac_size; j++)
+ out[j] |= rotated_mac[i] & constant_time_eq_8_s(j, rotate_offset);
+ rotate_offset++;
+ rotate_offset &= constant_time_lt_s(rotate_offset, mac_size);
+
+ /* If the padding wasn't good we emit a random MAC */
+ out[i] = constant_time_select_8((unsigned char)(good & 0xff), out[i],
+ randmac[i]);
+ }
+#endif
+
+ return 1;
+}
diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c
index c95dcd9fdec1..85f296b80783 100644
--- a/ssl/s3_cbc.c
+++ b/ssl/s3_cbc.c
@@ -1,19 +1,69 @@
/*
* Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+/*
+ * This file has no dependencies on the rest of libssl because it is shared
+ * with the providers. It contains functions for low level MAC calculations.
+ * Responsibility for this lies with the HMAC implementation in the
+ * providers. However there are legacy code paths in libssl which also need to
+ * do this. In time those legacy code paths can be removed and this file can be
+ * moved out of libssl.
+ */
+
+
+/*
+ * MD5 and SHA-1 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include "internal/constant_time.h"
-#include "ssl_local.h"
#include "internal/cryptlib.h"
-#include <openssl/md5.h>
+#include <openssl/evp.h>
+#ifndef FIPS_MODULE
+# include <openssl/md5.h>
+#endif
#include <openssl/sha.h>
+char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx);
+int ssl3_cbc_digest_record(const EVP_MD *md,
+ unsigned char *md_out,
+ size_t *md_out_size,
+ const unsigned char *header,
+ const unsigned char *data,
+ size_t data_size,
+ size_t data_plus_mac_plus_padding_size,
+ const unsigned char *mac_secret,
+ size_t mac_secret_length, char is_sslv3);
+
+# define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+ *((c)++)=(unsigned char)(((l) )&0xff))
+
+# define l2n6(l,c) (*((c)++)=(unsigned char)(((l)>>40)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>32)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>24)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+ *((c)++)=(unsigned char)(((l) )&0xff))
+
+# define l2n8(l,c) (*((c)++)=(unsigned char)(((l)>>56)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>48)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>40)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>32)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>24)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+ *((c)++)=(unsigned char)(((l) )&0xff))
+
/*
* MAX_HASH_BIT_COUNT_BYTES is the maximum number of bytes in the hash's
* length field. (SHA-384/512 have 128-bit length.)
@@ -27,15 +77,16 @@
*/
#define MAX_HASH_BLOCK_SIZE 128
+#ifndef FIPS_MODULE
/*
- * u32toLE serialises an unsigned, 32-bit number (n) as four bytes at (p) in
+ * u32toLE serializes an unsigned, 32-bit number (n) as four bytes at (p) in
* little-endian order. The value of p is advanced by four.
*/
-#define u32toLE(n, p) \
- (*((p)++)=(unsigned char)(n), \
- *((p)++)=(unsigned char)(n>>8), \
- *((p)++)=(unsigned char)(n>>16), \
- *((p)++)=(unsigned char)(n>>24))
+# define u32toLE(n, p) \
+ (*((p)++)=(unsigned char)(n), \
+ *((p)++)=(unsigned char)(n>>8), \
+ *((p)++)=(unsigned char)(n>>16), \
+ *((p)++)=(unsigned char)(n>>24))
/*
* These functions serialize the state of a hash and thus perform the
@@ -50,6 +101,7 @@ static void tls1_md5_final_raw(void *ctx, unsigned char *md_out)
u32toLE(md5->C, md_out);
u32toLE(md5->D, md_out);
}
+#endif /* FIPS_MODULE */
static void tls1_sha1_final_raw(void *ctx, unsigned char *md_out)
{
@@ -84,25 +136,6 @@ static void tls1_sha512_final_raw(void *ctx, unsigned char *md_out)
#undef LARGEST_DIGEST_CTX
#define LARGEST_DIGEST_CTX SHA512_CTX
-/*
- * ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function
- * which ssl3_cbc_digest_record supports.
- */
-char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
-{
- switch (EVP_MD_CTX_type(ctx)) {
- case NID_md5:
- case NID_sha1:
- case NID_sha224:
- case NID_sha256:
- case NID_sha384:
- case NID_sha512:
- return 1;
- default:
- return 0;
- }
-}
-
/*-
* ssl3_cbc_digest_record computes the MAC of a decrypted, padded SSLv3/TLS
* record.
@@ -113,30 +146,27 @@ char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
* md_out_size: if non-NULL, the number of output bytes is written here.
* header: the 13-byte, TLS record header.
* data: the record data itself, less any preceding explicit IV.
- * data_plus_mac_size: the secret, reported length of the data and MAC
- * once the padding has been removed.
+ * data_size: the secret, reported length of the data once the MAC and padding
+ * has been removed.
* data_plus_mac_plus_padding_size: the public length of the whole
- * record, including padding.
+ * record, including MAC and padding.
* is_sslv3: non-zero if we are to use SSLv3. Otherwise, TLS.
*
- * On entry: by virtue of having been through one of the remove_padding
- * functions, above, we know that data_plus_mac_size is large enough to contain
- * a padding byte and MAC. (If the padding was invalid, it might contain the
- * padding too. )
+ * On entry: we know that data is data_plus_mac_plus_padding_size in length
* Returns 1 on success or 0 on error
*/
-int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
+int ssl3_cbc_digest_record(const EVP_MD *md,
unsigned char *md_out,
size_t *md_out_size,
const unsigned char *header,
const unsigned char *data,
- size_t data_plus_mac_size,
+ size_t data_size,
size_t data_plus_mac_plus_padding_size,
const unsigned char *mac_secret,
size_t mac_secret_length, char is_sslv3)
{
union {
- double align;
+ OSSL_UNION_ALIGN;
unsigned char c[sizeof(LARGEST_DIGEST_CTX)];
} md_state;
void (*md_final_raw) (void *ctx, unsigned char *md_out);
@@ -160,7 +190,7 @@ int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
*/
size_t md_length_size = 8;
char length_is_big_endian = 1;
- int ret;
+ int ret = 0;
/*
* This is a, hopefully redundant, check that allows us to forget about
@@ -169,8 +199,10 @@ int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
if (!ossl_assert(data_plus_mac_plus_padding_size < 1024 * 1024))
return 0;
- switch (EVP_MD_CTX_type(ctx)) {
- case NID_md5:
+ if (EVP_MD_is_a(md, "MD5")) {
+#ifdef FIPS_MODULE
+ return 0;
+#else
if (MD5_Init((MD5_CTX *)md_state.c) <= 0)
return 0;
md_final_raw = tls1_md5_final_raw;
@@ -179,32 +211,29 @@ int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
md_size = 16;
sslv3_pad_length = 48;
length_is_big_endian = 0;
- break;
- case NID_sha1:
+#endif
+ } else if (EVP_MD_is_a(md, "SHA1")) {
if (SHA1_Init((SHA_CTX *)md_state.c) <= 0)
return 0;
md_final_raw = tls1_sha1_final_raw;
md_transform =
(void (*)(void *ctx, const unsigned char *block))SHA1_Transform;
md_size = 20;
- break;
- case NID_sha224:
+ } else if (EVP_MD_is_a(md, "SHA2-224")) {
if (SHA224_Init((SHA256_CTX *)md_state.c) <= 0)
return 0;
md_final_raw = tls1_sha256_final_raw;
md_transform =
(void (*)(void *ctx, const unsigned char *block))SHA256_Transform;
md_size = 224 / 8;
- break;
- case NID_sha256:
+ } else if (EVP_MD_is_a(md, "SHA2-256")) {
if (SHA256_Init((SHA256_CTX *)md_state.c) <= 0)
return 0;
md_final_raw = tls1_sha256_final_raw;
md_transform =
(void (*)(void *ctx, const unsigned char *block))SHA256_Transform;
md_size = 32;
- break;
- case NID_sha384:
+ } else if (EVP_MD_is_a(md, "SHA2-384")) {
if (SHA384_Init((SHA512_CTX *)md_state.c) <= 0)
return 0;
md_final_raw = tls1_sha512_final_raw;
@@ -213,8 +242,7 @@ int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
md_size = 384 / 8;
md_block_size = 128;
md_length_size = 16;
- break;
- case NID_sha512:
+ } else if (EVP_MD_is_a(md, "SHA2-512")) {
if (SHA512_Init((SHA512_CTX *)md_state.c) <= 0)
return 0;
md_final_raw = tls1_sha512_final_raw;
@@ -223,8 +251,7 @@ int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
md_size = 64;
md_block_size = 128;
md_length_size = 16;
- break;
- default:
+ } else {
/*
* ssl3_cbc_record_digest_supported should have been called first to
* check that the hash function is supported.
@@ -295,7 +322,7 @@ int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
/*
* mac_end_offset is the index just past the end of the data to be MACed.
*/
- mac_end_offset = data_plus_mac_size + header_length - md_size;
+ mac_end_offset = data_size + header_length;
/*
* c is the index of the 0x80 byte in the final hash block that contains
* application data.
@@ -455,7 +482,8 @@ int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
md_ctx = EVP_MD_CTX_new();
if (md_ctx == NULL)
goto err;
- if (EVP_DigestInit_ex(md_ctx, EVP_MD_CTX_md(ctx), NULL /* engine */ ) <= 0)
+
+ if (EVP_DigestInit_ex(md_ctx, md, NULL /* engine */ ) <= 0)
goto err;
if (is_sslv3) {
/* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */
@@ -474,14 +502,12 @@ int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
|| EVP_DigestUpdate(md_ctx, mac_out, md_size) <= 0)
goto err;
}
- /* TODO(size_t): Convert me */
ret = EVP_DigestFinal(md_ctx, md_out, &md_out_size_u);
if (ret && md_out_size)
*md_out_size = md_out_size_u;
- EVP_MD_CTX_free(md_ctx);
- return 1;
+ ret = 1;
err:
EVP_MD_CTX_free(md_ctx);
- return 0;
+ return ret;
}
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
index 7b119b452fd7..2ca3f74ae771 100644
--- a/ssl/s3_enc.c
+++ b/ssl/s3_enc.c
@@ -1,8 +1,8 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,67 +12,64 @@
#include "ssl_local.h"
#include <openssl/evp.h>
#include <openssl/md5.h>
+#include <openssl/core_names.h>
#include "internal/cryptlib.h"
static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num)
{
+ const EVP_MD *md5 = NULL, *sha1 = NULL;
EVP_MD_CTX *m5;
EVP_MD_CTX *s1;
unsigned char buf[16], smd[SHA_DIGEST_LENGTH];
unsigned char c = 'A';
- unsigned int i, j, k;
+ unsigned int i, k;
int ret = 0;
#ifdef CHARSET_EBCDIC
c = os_toascii[c]; /* 'A' in ASCII */
#endif
k = 0;
+ md5 = ssl_evp_md_fetch(s->ctx->libctx, NID_md5, s->ctx->propq);
+ sha1 = ssl_evp_md_fetch(s->ctx->libctx, NID_sha1, s->ctx->propq);
m5 = EVP_MD_CTX_new();
s1 = EVP_MD_CTX_new();
- if (m5 == NULL || s1 == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_KEY_BLOCK,
- ERR_R_MALLOC_FAILURE);
+ if (md5 == NULL || sha1 == NULL || m5 == NULL || s1 == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
- EVP_MD_CTX_set_flags(m5, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
for (i = 0; (int)i < num; i += MD5_DIGEST_LENGTH) {
k++;
if (k > sizeof(buf)) {
/* bug: 'buf' is too small for this ciphersuite */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_KEY_BLOCK,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- for (j = 0; j < k; j++)
- buf[j] = c;
+ memset(buf, c, k);
c++;
- if (!EVP_DigestInit_ex(s1, EVP_sha1(), NULL)
+ if (!EVP_DigestInit_ex(s1, sha1, NULL)
|| !EVP_DigestUpdate(s1, buf, k)
|| !EVP_DigestUpdate(s1, s->session->master_key,
s->session->master_key_length)
- || !EVP_DigestUpdate(s1, s->s3->server_random, SSL3_RANDOM_SIZE)
- || !EVP_DigestUpdate(s1, s->s3->client_random, SSL3_RANDOM_SIZE)
+ || !EVP_DigestUpdate(s1, s->s3.server_random, SSL3_RANDOM_SIZE)
+ || !EVP_DigestUpdate(s1, s->s3.client_random, SSL3_RANDOM_SIZE)
|| !EVP_DigestFinal_ex(s1, smd, NULL)
- || !EVP_DigestInit_ex(m5, EVP_md5(), NULL)
+ || !EVP_DigestInit_ex(m5, md5, NULL)
|| !EVP_DigestUpdate(m5, s->session->master_key,
s->session->master_key_length)
|| !EVP_DigestUpdate(m5, smd, SHA_DIGEST_LENGTH)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_KEY_BLOCK,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if ((int)(i + MD5_DIGEST_LENGTH) > num) {
if (!EVP_DigestFinal_ex(m5, smd, NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
memcpy(km, smd, (num - i));
} else {
if (!EVP_DigestFinal_ex(m5, km, NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
}
@@ -84,6 +81,8 @@ static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num)
err:
EVP_MD_CTX_free(m5);
EVP_MD_CTX_free(s1);
+ ssl_evp_md_free(md5);
+ ssl_evp_md_free(sha1);
return ret;
}
@@ -101,27 +100,25 @@ int ssl3_change_cipher_state(SSL *s, int which)
size_t n, i, j, k, cl;
int reuse_dd = 0;
- c = s->s3->tmp.new_sym_enc;
- m = s->s3->tmp.new_hash;
+ c = s->s3.tmp.new_sym_enc;
+ m = s->s3.tmp.new_hash;
/* m == NULL will lead to a crash later */
if (!ossl_assert(m != NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
#ifndef OPENSSL_NO_COMP
- if (s->s3->tmp.new_compression == NULL)
+ if (s->s3.tmp.new_compression == NULL)
comp = NULL;
else
- comp = s->s3->tmp.new_compression->method;
+ comp = s->s3.tmp.new_compression->method;
#endif
if (which & SSL3_CC_READ) {
if (s->enc_read_ctx != NULL) {
reuse_dd = 1;
} else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
} else {
/*
@@ -132,8 +129,7 @@ int ssl3_change_cipher_state(SSL *s, int which)
dd = s->enc_read_ctx;
if (ssl_replace_hash(&s->read_hash, m) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
#ifndef OPENSSL_NO_COMP
@@ -144,21 +140,19 @@ int ssl3_change_cipher_state(SSL *s, int which)
s->expand = COMP_CTX_new(comp);
if (s->expand == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_SSL3_CHANGE_CIPHER_STATE,
SSL_R_COMPRESSION_LIBRARY_ERROR);
goto err;
}
}
#endif
RECORD_LAYER_reset_read_sequence(&s->rlayer);
- mac_secret = &(s->s3->read_mac_secret[0]);
+ mac_secret = &(s->s3.read_mac_secret[0]);
} else {
s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
if (s->enc_write_ctx != NULL) {
reuse_dd = 1;
} else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
} else {
/*
@@ -168,8 +162,7 @@ int ssl3_change_cipher_state(SSL *s, int which)
}
dd = s->enc_write_ctx;
if (ssl_replace_hash(&s->write_hash, m) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
#ifndef OPENSSL_NO_COMP
@@ -180,30 +173,28 @@ int ssl3_change_cipher_state(SSL *s, int which)
s->compress = COMP_CTX_new(comp);
if (s->compress == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_SSL3_CHANGE_CIPHER_STATE,
SSL_R_COMPRESSION_LIBRARY_ERROR);
goto err;
}
}
#endif
RECORD_LAYER_reset_write_sequence(&s->rlayer);
- mac_secret = &(s->s3->write_mac_secret[0]);
+ mac_secret = &(s->s3.write_mac_secret[0]);
}
if (reuse_dd)
EVP_CIPHER_CTX_reset(dd);
- p = s->s3->tmp.key_block;
- mdi = EVP_MD_size(m);
+ p = s->s3.tmp.key_block;
+ mdi = EVP_MD_get_size(m);
if (mdi < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
i = mdi;
- cl = EVP_CIPHER_key_length(c);
+ cl = EVP_CIPHER_get_key_length(c);
j = cl;
- k = EVP_CIPHER_iv_length(c);
+ k = EVP_CIPHER_get_iv_length(c);
if ((which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
(which == SSL3_CHANGE_CIPHER_SERVER_READ)) {
ms = &(p[0]);
@@ -222,17 +213,21 @@ int ssl3_change_cipher_state(SSL *s, int which)
n += k;
}
- if (n > s->s3->tmp.key_block_length) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
- ERR_R_INTERNAL_ERROR);
+ if (n > s->s3.tmp.key_block_length) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
memcpy(mac_secret, ms, i);
if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (EVP_CIPHER_get0_provider(c) != NULL
+ && !tls_provider_set_tls_params(s, dd, c, m)) {
+ /* SSLfatal already called */
goto err;
}
@@ -251,40 +246,42 @@ int ssl3_setup_key_block(SSL *s)
int ret = 0;
SSL_COMP *comp;
- if (s->s3->tmp.key_block_length != 0)
+ if (s->s3.tmp.key_block_length != 0)
return 1;
- if (!ssl_cipher_get_evp(s->session, &c, &hash, NULL, NULL, &comp, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_SETUP_KEY_BLOCK,
- SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
+ if (!ssl_cipher_get_evp(s->ctx, s->session, &c, &hash, NULL, NULL, &comp,
+ 0)) {
+ /* Error is already recorded */
+ SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
return 0;
}
- s->s3->tmp.new_sym_enc = c;
- s->s3->tmp.new_hash = hash;
+ ssl_evp_cipher_free(s->s3.tmp.new_sym_enc);
+ s->s3.tmp.new_sym_enc = c;
+ ssl_evp_md_free(s->s3.tmp.new_hash);
+ s->s3.tmp.new_hash = hash;
#ifdef OPENSSL_NO_COMP
- s->s3->tmp.new_compression = NULL;
+ s->s3.tmp.new_compression = NULL;
#else
- s->s3->tmp.new_compression = comp;
+ s->s3.tmp.new_compression = comp;
#endif
- num = EVP_MD_size(hash);
+ num = EVP_MD_get_size(hash);
if (num < 0)
return 0;
- num = EVP_CIPHER_key_length(c) + num + EVP_CIPHER_iv_length(c);
+ num = EVP_CIPHER_get_key_length(c) + num + EVP_CIPHER_get_iv_length(c);
num *= 2;
ssl3_cleanup_key_block(s);
if ((p = OPENSSL_malloc(num)) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_SETUP_KEY_BLOCK,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
- s->s3->tmp.key_block_length = num;
- s->s3->tmp.key_block = p;
+ s->s3.tmp.key_block_length = num;
+ s->s3.tmp.key_block = p;
/* Calls SSLfatal() as required */
ret = ssl3_generate_key_block(s, p, num);
@@ -294,16 +291,14 @@ int ssl3_setup_key_block(SSL *s)
* enable vulnerability countermeasure for CBC ciphers with known-IV
* problem (http://www.openssl.org/~bodo/tls-cbc.txt)
*/
- s->s3->need_empty_fragments = 1;
+ s->s3.need_empty_fragments = 1;
if (s->session->cipher != NULL) {
if (s->session->cipher->algorithm_enc == SSL_eNULL)
- s->s3->need_empty_fragments = 0;
+ s->s3.need_empty_fragments = 0;
-#ifndef OPENSSL_NO_RC4
if (s->session->cipher->algorithm_enc == SSL_RC4)
- s->s3->need_empty_fragments = 0;
-#endif
+ s->s3.need_empty_fragments = 0;
}
}
@@ -312,9 +307,9 @@ int ssl3_setup_key_block(SSL *s)
void ssl3_cleanup_key_block(SSL *s)
{
- OPENSSL_clear_free(s->s3->tmp.key_block, s->s3->tmp.key_block_length);
- s->s3->tmp.key_block = NULL;
- s->s3->tmp.key_block_length = 0;
+ OPENSSL_clear_free(s->s3.tmp.key_block, s->s3.tmp.key_block_length);
+ s->s3.tmp.key_block = NULL;
+ s->s3.tmp.key_block_length = 0;
}
int ssl3_init_finished_mac(SSL *s)
@@ -322,13 +317,12 @@ int ssl3_init_finished_mac(SSL *s)
BIO *buf = BIO_new(BIO_s_mem());
if (buf == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_INIT_FINISHED_MAC,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
ssl3_free_digest_list(s);
- s->s3->handshake_buffer = buf;
- (void)BIO_set_close(s->s3->handshake_buffer, BIO_CLOSE);
+ s->s3.handshake_buffer = buf;
+ (void)BIO_set_close(s->s3.handshake_buffer, BIO_CLOSE);
return 1;
}
@@ -339,34 +333,31 @@ int ssl3_init_finished_mac(SSL *s)
void ssl3_free_digest_list(SSL *s)
{
- BIO_free(s->s3->handshake_buffer);
- s->s3->handshake_buffer = NULL;
- EVP_MD_CTX_free(s->s3->handshake_dgst);
- s->s3->handshake_dgst = NULL;
+ BIO_free(s->s3.handshake_buffer);
+ s->s3.handshake_buffer = NULL;
+ EVP_MD_CTX_free(s->s3.handshake_dgst);
+ s->s3.handshake_dgst = NULL;
}
int ssl3_finish_mac(SSL *s, const unsigned char *buf, size_t len)
{
int ret;
- if (s->s3->handshake_dgst == NULL) {
+ if (s->s3.handshake_dgst == NULL) {
/* Note: this writes to a memory BIO so a failure is a fatal error */
if (len > INT_MAX) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC,
- SSL_R_OVERFLOW_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_OVERFLOW_ERROR);
return 0;
}
- ret = BIO_write(s->s3->handshake_buffer, (void *)buf, (int)len);
+ ret = BIO_write(s->s3.handshake_buffer, (void *)buf, (int)len);
if (ret <= 0 || ret != (int)len) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
} else {
- ret = EVP_DigestUpdate(s->s3->handshake_dgst, buf, len);
+ ret = EVP_DigestUpdate(s->s3.handshake_dgst, buf, len);
if (!ret) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
@@ -379,37 +370,49 @@ int ssl3_digest_cached_records(SSL *s, int keep)
long hdatalen;
void *hdata;
- if (s->s3->handshake_dgst == NULL) {
- hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+ if (s->s3.handshake_dgst == NULL) {
+ hdatalen = BIO_get_mem_data(s->s3.handshake_buffer, &hdata);
if (hdatalen <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS,
- SSL_R_BAD_HANDSHAKE_LENGTH);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_HANDSHAKE_LENGTH);
return 0;
}
- s->s3->handshake_dgst = EVP_MD_CTX_new();
- if (s->s3->handshake_dgst == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS,
- ERR_R_MALLOC_FAILURE);
+ s->s3.handshake_dgst = EVP_MD_CTX_new();
+ if (s->s3.handshake_dgst == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
md = ssl_handshake_md(s);
- if (md == NULL || !EVP_DigestInit_ex(s->s3->handshake_dgst, md, NULL)
- || !EVP_DigestUpdate(s->s3->handshake_dgst, hdata, hdatalen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS,
- ERR_R_INTERNAL_ERROR);
+ if (md == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_R_NO_SUITABLE_DIGEST_ALGORITHM);
+ return 0;
+ }
+ if (!EVP_DigestInit_ex(s->s3.handshake_dgst, md, NULL)
+ || !EVP_DigestUpdate(s->s3.handshake_dgst, hdata, hdatalen)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
if (keep == 0) {
- BIO_free(s->s3->handshake_buffer);
- s->s3->handshake_buffer = NULL;
+ BIO_free(s->s3.handshake_buffer);
+ s->s3.handshake_buffer = NULL;
}
return 1;
}
+void ssl3_digest_master_key_set_params(const SSL_SESSION *session,
+ OSSL_PARAM params[])
+{
+ int n = 0;
+ params[n++] = OSSL_PARAM_construct_octet_string(OSSL_DIGEST_PARAM_SSL3_MS,
+ (void *)session->master_key,
+ session->master_key_length);
+ params[n++] = OSSL_PARAM_construct_end();
+}
+
size_t ssl3_final_finish_mac(SSL *s, const char *sender, size_t len,
unsigned char *p)
{
@@ -421,41 +424,40 @@ size_t ssl3_final_finish_mac(SSL *s, const char *sender, size_t len,
return 0;
}
- if (EVP_MD_CTX_type(s->s3->handshake_dgst) != NID_md5_sha1) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
- SSL_R_NO_REQUIRED_DIGEST);
+ if (EVP_MD_CTX_get_type(s->s3.handshake_dgst) != NID_md5_sha1) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_NO_REQUIRED_DIGEST);
return 0;
}
ctx = EVP_MD_CTX_new();
if (ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
- if (!EVP_MD_CTX_copy_ex(ctx, s->s3->handshake_dgst)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
- ERR_R_INTERNAL_ERROR);
+ if (!EVP_MD_CTX_copy_ex(ctx, s->s3.handshake_dgst)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
ret = 0;
goto err;
}
- ret = EVP_MD_CTX_size(ctx);
+ ret = EVP_MD_CTX_get_size(ctx);
if (ret < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
ret = 0;
goto err;
}
- if ((sender != NULL && EVP_DigestUpdate(ctx, sender, len) <= 0)
- || EVP_MD_CTX_ctrl(ctx, EVP_CTRL_SSL3_MASTER_SECRET,
- (int)s->session->master_key_length,
- s->session->master_key) <= 0
- || EVP_DigestFinal_ex(ctx, p, NULL) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
- ERR_R_INTERNAL_ERROR);
- ret = 0;
+ if (sender != NULL) {
+ OSSL_PARAM digest_cmd_params[3];
+
+ ssl3_digest_master_key_set_params(s->session, digest_cmd_params);
+
+ if (EVP_DigestUpdate(ctx, sender, len) <= 0
+ || EVP_MD_CTX_set_params(ctx, digest_cmd_params) <= 0
+ || EVP_DigestFinal_ex(ctx, p, NULL) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ ret = 0;
+ }
}
err:
@@ -485,8 +487,7 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
size_t ret_secret_size = 0;
if (ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_MASTER_SECRET,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
for (i = 0; i < 3; i++) {
@@ -494,18 +495,16 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
|| EVP_DigestUpdate(ctx, salt[i],
strlen((const char *)salt[i])) <= 0
|| EVP_DigestUpdate(ctx, p, len) <= 0
- || EVP_DigestUpdate(ctx, &(s->s3->client_random[0]),
+ || EVP_DigestUpdate(ctx, &(s->s3.client_random[0]),
SSL3_RANDOM_SIZE) <= 0
- || EVP_DigestUpdate(ctx, &(s->s3->server_random[0]),
+ || EVP_DigestUpdate(ctx, &(s->s3.server_random[0]),
SSL3_RANDOM_SIZE) <= 0
- /* TODO(size_t) : convert me */
|| EVP_DigestFinal_ex(ctx, buf, &n) <= 0
|| EVP_DigestInit_ex(ctx, s->ctx->md5, NULL) <= 0
|| EVP_DigestUpdate(ctx, p, len) <= 0
|| EVP_DigestUpdate(ctx, buf, n) <= 0
|| EVP_DigestFinal_ex(ctx, out, &n) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_SSL3_GENERATE_MASTER_SECRET, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
ret = 0;
break;
}
@@ -589,7 +588,7 @@ int ssl3_alert_code(int code)
return TLS1_AD_NO_APPLICATION_PROTOCOL;
case SSL_AD_CERTIFICATE_REQUIRED:
return SSL_AD_HANDSHAKE_FAILURE;
- case SSL_AD_MISSING_EXTENSION:
+ case TLS13_AD_MISSING_EXTENSION:
return SSL_AD_HANDSHAKE_FAILURE;
default:
return -1;
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 32f9b257106b..78d4f040565d 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -3,7 +3,7 @@
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -16,6 +16,9 @@
#include <openssl/md5.h>
#include <openssl/dh.h>
#include <openssl/rand.h>
+#include <openssl/trace.h>
+#include <openssl/x509v3.h>
+#include <openssl/core_names.h>
#include "internal/cryptlib.h"
#define TLS13_NUM_CIPHERS OSSL_NELEM(tls13_ciphers)
@@ -63,7 +66,6 @@ static SSL_CIPHER tls13_ciphers[] = {
256,
256,
},
-#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
{
1,
TLS1_3_RFC_CHACHA20_POLY1305_SHA256,
@@ -80,7 +82,6 @@ static SSL_CIPHER tls13_ciphers[] = {
256,
256,
},
-#endif
{
1,
TLS1_3_RFC_AES_128_CCM_SHA256,
@@ -2033,7 +2034,6 @@ static SSL_CIPHER ssl3_ciphers[] = {
256,
},
-#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
{
1,
TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305,
@@ -2146,10 +2146,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
256,
256,
},
-#endif /* !defined(OPENSSL_NO_CHACHA) &&
- * !defined(OPENSSL_NO_POLY1305) */
-#ifndef OPENSSL_NO_CAMELLIA
{
1,
TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA256,
@@ -2598,7 +2595,6 @@ static SSL_CIPHER ssl3_ciphers[] = {
256,
256,
},
-#endif /* OPENSSL_NO_CAMELLIA */
#ifndef OPENSSL_NO_GOST
{
@@ -2635,7 +2631,23 @@ static SSL_CIPHER ssl3_ciphers[] = {
},
{
1,
- "GOST2012-GOST8912-GOST8912",
+ "IANA-GOST2012-GOST8912-GOST8912",
+ NULL,
+ 0x0300c102,
+ SSL_kGOST,
+ SSL_aGOST12 | SSL_aGOST01,
+ SSL_eGOST2814789CNT12,
+ SSL_GOST89MAC12,
+ TLS1_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_STREAM_MAC,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ "LEGACY-GOST2012-GOST8912-GOST8912",
NULL,
0x0300ff85,
SSL_kGOST,
@@ -2665,9 +2677,40 @@ static SSL_CIPHER ssl3_ciphers[] = {
0,
0,
},
+ {
+ 1,
+ "GOST2012-KUZNYECHIK-KUZNYECHIKOMAC",
+ NULL,
+ 0x0300C100,
+ SSL_kGOST18,
+ SSL_aGOST12,
+ SSL_KUZNYECHIK,
+ SSL_KUZNYECHIKOMAC,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_TLSTREE,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ "GOST2012-MAGMA-MAGMAOMAC",
+ NULL,
+ 0x0300C101,
+ SSL_kGOST18,
+ SSL_aGOST12,
+ SSL_MAGMA,
+ SSL_MAGMAOMAC,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_TLSTREE,
+ 256,
+ 256,
+ },
#endif /* OPENSSL_NO_GOST */
-#ifndef OPENSSL_NO_IDEA
{
1,
SSL3_TXT_RSA_IDEA_128_SHA,
@@ -2684,9 +2727,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
128,
128,
},
-#endif
-#ifndef OPENSSL_NO_SEED
{
1,
TLS1_TXT_RSA_WITH_SEED_SHA,
@@ -2751,7 +2792,6 @@ static SSL_CIPHER ssl3_ciphers[] = {
128,
128,
},
-#endif /* OPENSSL_NO_SEED */
#ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
{
@@ -2916,7 +2956,6 @@ static SSL_CIPHER ssl3_ciphers[] = {
},
#endif /* OPENSSL_NO_WEAK_SSL_CIPHERS */
-#ifndef OPENSSL_NO_ARIA
{
1,
TLS1_TXT_RSA_WITH_ARIA_128_GCM_SHA256,
@@ -3173,7 +3212,6 @@ static SSL_CIPHER ssl3_ciphers[] = {
256,
256,
},
-#endif /* OPENSSL_NO_ARIA */
};
/*
@@ -3291,78 +3329,68 @@ int ssl3_handshake_write(SSL *s)
int ssl3_new(SSL *s)
{
- SSL3_STATE *s3;
-
- if ((s3 = OPENSSL_zalloc(sizeof(*s3))) == NULL)
- goto err;
- s->s3 = s3;
-
#ifndef OPENSSL_NO_SRP
- if (!SSL_SRP_CTX_init(s))
- goto err;
+ if (!ssl_srp_ctx_init_intern(s))
+ return 0;
#endif
if (!s->method->ssl_clear(s))
return 0;
return 1;
- err:
- return 0;
}
void ssl3_free(SSL *s)
{
- if (s == NULL || s->s3 == NULL)
+ if (s == NULL)
return;
ssl3_cleanup_key_block(s);
-#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
- EVP_PKEY_free(s->s3->peer_tmp);
- s->s3->peer_tmp = NULL;
- EVP_PKEY_free(s->s3->tmp.pkey);
- s->s3->tmp.pkey = NULL;
-#endif
+ EVP_PKEY_free(s->s3.peer_tmp);
+ s->s3.peer_tmp = NULL;
+ EVP_PKEY_free(s->s3.tmp.pkey);
+ s->s3.tmp.pkey = NULL;
+
+ ssl_evp_cipher_free(s->s3.tmp.new_sym_enc);
+ ssl_evp_md_free(s->s3.tmp.new_hash);
- OPENSSL_free(s->s3->tmp.ctype);
- sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free);
- OPENSSL_free(s->s3->tmp.ciphers_raw);
- OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
- OPENSSL_free(s->s3->tmp.peer_sigalgs);
- OPENSSL_free(s->s3->tmp.peer_cert_sigalgs);
+ OPENSSL_free(s->s3.tmp.ctype);
+ sk_X509_NAME_pop_free(s->s3.tmp.peer_ca_names, X509_NAME_free);
+ OPENSSL_free(s->s3.tmp.ciphers_raw);
+ OPENSSL_clear_free(s->s3.tmp.pms, s->s3.tmp.pmslen);
+ OPENSSL_free(s->s3.tmp.peer_sigalgs);
+ OPENSSL_free(s->s3.tmp.peer_cert_sigalgs);
ssl3_free_digest_list(s);
- OPENSSL_free(s->s3->alpn_selected);
- OPENSSL_free(s->s3->alpn_proposed);
+ OPENSSL_free(s->s3.alpn_selected);
+ OPENSSL_free(s->s3.alpn_proposed);
#ifndef OPENSSL_NO_SRP
- SSL_SRP_CTX_free(s);
+ ssl_srp_ctx_free_intern(s);
#endif
- OPENSSL_clear_free(s->s3, sizeof(*s->s3));
- s->s3 = NULL;
+ memset(&s->s3, 0, sizeof(s->s3));
}
int ssl3_clear(SSL *s)
{
ssl3_cleanup_key_block(s);
- OPENSSL_free(s->s3->tmp.ctype);
- sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free);
- OPENSSL_free(s->s3->tmp.ciphers_raw);
- OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
- OPENSSL_free(s->s3->tmp.peer_sigalgs);
- OPENSSL_free(s->s3->tmp.peer_cert_sigalgs);
-
-#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
- EVP_PKEY_free(s->s3->tmp.pkey);
- EVP_PKEY_free(s->s3->peer_tmp);
-#endif /* !OPENSSL_NO_EC */
+ OPENSSL_free(s->s3.tmp.ctype);
+ sk_X509_NAME_pop_free(s->s3.tmp.peer_ca_names, X509_NAME_free);
+ OPENSSL_free(s->s3.tmp.ciphers_raw);
+ OPENSSL_clear_free(s->s3.tmp.pms, s->s3.tmp.pmslen);
+ OPENSSL_free(s->s3.tmp.peer_sigalgs);
+ OPENSSL_free(s->s3.tmp.peer_cert_sigalgs);
+
+ EVP_PKEY_free(s->s3.tmp.pkey);
+ EVP_PKEY_free(s->s3.peer_tmp);
ssl3_free_digest_list(s);
- OPENSSL_free(s->s3->alpn_selected);
- OPENSSL_free(s->s3->alpn_proposed);
+ OPENSSL_free(s->s3.alpn_selected);
+ OPENSSL_free(s->s3.alpn_proposed);
/* NULL/zero-out everything in the s3 struct */
- memset(s->s3, 0, sizeof(*s->s3));
+ memset(&s->s3, 0, sizeof(s->s3));
if (!ssl_free_wbio_buffer(s))
return 0;
@@ -3395,79 +3423,61 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
case SSL_CTRL_GET_CLIENT_CERT_REQUEST:
break;
case SSL_CTRL_GET_NUM_RENEGOTIATIONS:
- ret = s->s3->num_renegotiations;
+ ret = s->s3.num_renegotiations;
break;
case SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS:
- ret = s->s3->num_renegotiations;
- s->s3->num_renegotiations = 0;
+ ret = s->s3.num_renegotiations;
+ s->s3.num_renegotiations = 0;
break;
case SSL_CTRL_GET_TOTAL_RENEGOTIATIONS:
- ret = s->s3->total_renegotiations;
+ ret = s->s3.total_renegotiations;
break;
case SSL_CTRL_GET_FLAGS:
- ret = (int)(s->s3->flags);
+ ret = (int)(s->s3.flags);
break;
-#ifndef OPENSSL_NO_DH
+#if !defined(OPENSSL_NO_DEPRECATED_3_0)
case SSL_CTRL_SET_TMP_DH:
{
- DH *dh = (DH *)parg;
EVP_PKEY *pkdh = NULL;
- if (dh == NULL) {
- SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER);
- return ret;
+ if (parg == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
}
- pkdh = ssl_dh_to_pkey(dh);
+ pkdh = ssl_dh_to_pkey(parg);
if (pkdh == NULL) {
- SSLerr(SSL_F_SSL3_CTRL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
- if (!ssl_security(s, SSL_SECOP_TMP_DH,
- EVP_PKEY_security_bits(pkdh), 0, pkdh)) {
- SSLerr(SSL_F_SSL3_CTRL, SSL_R_DH_KEY_TOO_SMALL);
+ if (!SSL_set0_tmp_dh_pkey(s, pkdh)) {
EVP_PKEY_free(pkdh);
- return ret;
+ return 0;
}
- EVP_PKEY_free(s->cert->dh_tmp);
- s->cert->dh_tmp = pkdh;
- ret = 1;
+ return 1;
}
break;
case SSL_CTRL_SET_TMP_DH_CB:
{
- SSLerr(SSL_F_SSL3_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return ret;
}
+#endif
case SSL_CTRL_SET_DH_AUTO:
s->cert->dh_tmp_auto = larg;
return 1;
-#endif
-#ifndef OPENSSL_NO_EC
+#if !defined(OPENSSL_NO_DEPRECATED_3_0)
case SSL_CTRL_SET_TMP_ECDH:
{
- const EC_GROUP *group = NULL;
- int nid;
-
if (parg == NULL) {
- SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
- group = EC_KEY_get0_group((const EC_KEY *)parg);
- if (group == NULL) {
- SSLerr(SSL_F_SSL3_CTRL, EC_R_MISSING_PARAMETERS);
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
- nid = EC_GROUP_get_curve_name(group);
- if (nid == NID_undef)
- return 0;
- return tls1_set_groups(&s->ext.supportedgroups,
- &s->ext.supportedgroups_len,
- &nid, 1);
+ return ssl_set_tmp_ecdh_groups(&s->ext.supportedgroups,
+ &s->ext.supportedgroups_len,
+ parg);
}
- break;
-#endif /* !OPENSSL_NO_EC */
+#endif /* !OPENSSL_NO_DEPRECATED_3_0 */
case SSL_CTRL_SET_TLSEXT_HOSTNAME:
/*
- * TODO(OpenSSL1.2)
* This API is only used for a client to set what SNI it will request
* from the server, but we currently allow it to be used on servers
* as well, which is a programming error. Currently we just clear
@@ -3486,15 +3496,15 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
break;
len = strlen((char *)parg);
if (len == 0 || len > TLSEXT_MAXLEN_host_name) {
- SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME);
+ ERR_raise(ERR_LIB_SSL, SSL_R_SSL3_EXT_INVALID_SERVERNAME);
return 0;
}
if ((s->ext.hostname = OPENSSL_strdup((char *)parg)) == NULL) {
- SSLerr(SSL_F_SSL3_CTRL, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
} else {
- SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE);
return 0;
}
break;
@@ -3546,13 +3556,6 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
ret = 1;
break;
-#ifndef OPENSSL_NO_HEARTBEATS
- case SSL_CTRL_DTLS_EXT_SEND_HEARTBEAT:
- case SSL_CTRL_GET_DTLS_EXT_HEARTBEAT_PENDING:
- case SSL_CTRL_SET_DTLS_EXT_HEARTBEAT_NO_REQUESTS:
- break;
-#endif
-
case SSL_CTRL_CHAIN:
if (larg)
return ssl_cert_set1_chain(s, NULL, (STACK_OF(X509) *)parg);
@@ -3578,7 +3581,7 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
const SSL_CIPHER *cipher;
if (!s->server)
return 0;
- cipher = s->s3->tmp.new_cipher;
+ cipher = s->s3.tmp.new_cipher;
if (cipher == NULL)
return 0;
/*
@@ -3587,14 +3590,13 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
*/
if (cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
return 2;
- if (s->s3->tmp.cert == NULL)
+ if (s->s3.tmp.cert == NULL)
return 0;
- s->cert->key = s->s3->tmp.cert;
+ s->cert->key = s->s3.tmp.cert;
return 1;
}
return ssl_cert_set_current(s->cert, larg);
-#ifndef OPENSSL_NO_EC
case SSL_CTRL_GET_GROUPS:
{
uint16_t *clist;
@@ -3609,10 +3611,11 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
int *cptr = parg;
for (i = 0; i < clistlen; i++) {
- const TLS_GROUP_INFO *cinf = tls1_group_id_lookup(clist[i]);
+ const TLS_GROUP_INFO *cinf
+ = tls1_group_id_lookup(s->ctx, clist[i]);
if (cinf != NULL)
- cptr[i] = cinf->nid;
+ cptr[i] = tls1_group_id2nid(cinf->group_id, 1);
else
cptr[i] = TLSEXT_nid_unknown | clist[i];
}
@@ -3625,21 +3628,28 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
&s->ext.supportedgroups_len, parg, larg);
case SSL_CTRL_SET_GROUPS_LIST:
- return tls1_set_groups_list(&s->ext.supportedgroups,
+ return tls1_set_groups_list(s->ctx, &s->ext.supportedgroups,
&s->ext.supportedgroups_len, parg);
case SSL_CTRL_GET_SHARED_GROUP:
{
uint16_t id = tls1_shared_group(s, larg);
- if (larg != -1) {
- const TLS_GROUP_INFO *ginf = tls1_group_id_lookup(id);
-
- return ginf == NULL ? 0 : ginf->nid;
- }
+ if (larg != -1)
+ return tls1_group_id2nid(id, 1);
return id;
}
-#endif
+ case SSL_CTRL_GET_NEGOTIATED_GROUP:
+ {
+ unsigned int id;
+
+ if (SSL_IS_TLS13(s) && s->s3.did_kex)
+ id = s->s3.group_id;
+ else
+ id = s->session->kex_group;
+ ret = tls1_group_id2nid(id, 1);
+ break;
+ }
case SSL_CTRL_SET_SIGALGS:
return tls1_set_sigalgs(s->cert, parg, larg, 0);
@@ -3655,11 +3665,11 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
case SSL_CTRL_GET_CLIENT_CERT_TYPES:
{
const unsigned char **pctype = parg;
- if (s->server || !s->s3->tmp.cert_req)
+ if (s->server || !s->s3.tmp.cert_req)
return 0;
if (pctype)
- *pctype = s->s3->tmp.ctype;
- return s->s3->tmp.ctype_len;
+ *pctype = s->s3.tmp.ctype;
+ return s->s3.tmp.ctype_len;
}
case SSL_CTRL_SET_CLIENT_CERT_TYPES:
@@ -3683,44 +3693,35 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
return ssl_cert_get_cert_store(s->cert, parg, 1);
case SSL_CTRL_GET_PEER_SIGNATURE_NID:
- if (s->s3->tmp.peer_sigalg == NULL)
+ if (s->s3.tmp.peer_sigalg == NULL)
return 0;
- *(int *)parg = s->s3->tmp.peer_sigalg->hash;
+ *(int *)parg = s->s3.tmp.peer_sigalg->hash;
return 1;
case SSL_CTRL_GET_SIGNATURE_NID:
- if (s->s3->tmp.sigalg == NULL)
+ if (s->s3.tmp.sigalg == NULL)
return 0;
- *(int *)parg = s->s3->tmp.sigalg->hash;
+ *(int *)parg = s->s3.tmp.sigalg->hash;
return 1;
case SSL_CTRL_GET_PEER_TMP_KEY:
-#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC)
- if (s->session == NULL || s->s3->peer_tmp == NULL) {
+ if (s->session == NULL || s->s3.peer_tmp == NULL) {
return 0;
} else {
- EVP_PKEY_up_ref(s->s3->peer_tmp);
- *(EVP_PKEY **)parg = s->s3->peer_tmp;
+ EVP_PKEY_up_ref(s->s3.peer_tmp);
+ *(EVP_PKEY **)parg = s->s3.peer_tmp;
return 1;
}
-#else
- return 0;
-#endif
case SSL_CTRL_GET_TMP_KEY:
-#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC)
- if (s->session == NULL || s->s3->tmp.pkey == NULL) {
+ if (s->session == NULL || s->s3.tmp.pkey == NULL) {
return 0;
} else {
- EVP_PKEY_up_ref(s->s3->tmp.pkey);
- *(EVP_PKEY **)parg = s->s3->tmp.pkey;
+ EVP_PKEY_up_ref(s->s3.tmp.pkey);
+ *(EVP_PKEY **)parg = s->s3.tmp.pkey;
return 1;
}
-#else
- return 0;
-#endif
-#ifndef OPENSSL_NO_EC
case SSL_CTRL_GET_EC_POINT_FORMATS:
{
const unsigned char **pformat = parg;
@@ -3730,7 +3731,6 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
*pformat = s->ext.peer_ecpointformats;
return (int)s->ext.peer_ecpointformats_len;
}
-#endif
default:
break;
@@ -3743,22 +3743,21 @@ long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp) (void))
int ret = 0;
switch (cmd) {
-#ifndef OPENSSL_NO_DH
+#if !defined(OPENSSL_NO_DEPRECATED_3_0)
case SSL_CTRL_SET_TMP_DH_CB:
- {
- s->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp;
- }
+ s->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp;
+ ret = 1;
break;
#endif
case SSL_CTRL_SET_TLSEXT_DEBUG_CB:
s->ext.debug_cb = (void (*)(SSL *, int, int,
const unsigned char *, int, void *))fp;
+ ret = 1;
break;
case SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB:
- {
- s->not_resumable_session_cb = (int (*)(SSL *, int))fp;
- }
+ s->not_resumable_session_cb = (int (*)(SSL *, int))fp;
+ ret = 1;
break;
default:
break;
@@ -3769,62 +3768,46 @@ long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp) (void))
long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
{
switch (cmd) {
-#ifndef OPENSSL_NO_DH
+#if !defined(OPENSSL_NO_DEPRECATED_3_0)
case SSL_CTRL_SET_TMP_DH:
{
- DH *dh = (DH *)parg;
EVP_PKEY *pkdh = NULL;
- if (dh == NULL) {
- SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+ if (parg == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
- pkdh = ssl_dh_to_pkey(dh);
+ pkdh = ssl_dh_to_pkey(parg);
if (pkdh == NULL) {
- SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
- if (!ssl_ctx_security(ctx, SSL_SECOP_TMP_DH,
- EVP_PKEY_security_bits(pkdh), 0, pkdh)) {
- SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_DH_KEY_TOO_SMALL);
+ if (!SSL_CTX_set0_tmp_dh_pkey(ctx, pkdh)) {
EVP_PKEY_free(pkdh);
return 0;
}
- EVP_PKEY_free(ctx->cert->dh_tmp);
- ctx->cert->dh_tmp = pkdh;
return 1;
}
case SSL_CTRL_SET_TMP_DH_CB:
{
- SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
+#endif
case SSL_CTRL_SET_DH_AUTO:
ctx->cert->dh_tmp_auto = larg;
return 1;
-#endif
-#ifndef OPENSSL_NO_EC
+#if !defined(OPENSSL_NO_DEPRECATED_3_0)
case SSL_CTRL_SET_TMP_ECDH:
{
- const EC_GROUP *group = NULL;
- int nid;
-
if (parg == NULL) {
- SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
- group = EC_KEY_get0_group((const EC_KEY *)parg);
- if (group == NULL) {
- SSLerr(SSL_F_SSL3_CTX_CTRL, EC_R_MISSING_PARAMETERS);
- return 0;
- }
- nid = EC_GROUP_get_curve_name(group);
- if (nid == NID_undef)
- return 0;
- return tls1_set_groups(&ctx->ext.supportedgroups,
- &ctx->ext.supportedgroups_len,
- &nid, 1);
+ return ssl_set_tmp_ecdh_groups(&ctx->ext.supportedgroups,
+ &ctx->ext.supportedgroups_len,
+ parg);
}
-#endif /* !OPENSSL_NO_EC */
+#endif /* !OPENSSL_NO_DEPRECATED_3_0 */
case SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG:
ctx->ext.servername_arg = parg;
break;
@@ -3838,7 +3821,7 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
if (keys == NULL)
return tick_keylen;
if (larg != tick_keylen) {
- SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_INVALID_TICKET_KEYS_LENGTH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH);
return 0;
}
if (cmd == SSL_CTRL_SET_TLSEXT_TICKET_KEYS) {
@@ -3892,11 +3875,11 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
if (parg == NULL)
break;
if (strlen((const char *)parg) > 255 || strlen((const char *)parg) < 1) {
- SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_INVALID_SRP_USERNAME);
+ ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_SRP_USERNAME);
return 0;
}
if ((ctx->srp_ctx.login = OPENSSL_strdup((char *)parg)) == NULL) {
- SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
break;
@@ -3905,8 +3888,8 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
srp_password_from_info_cb;
if (ctx->srp_ctx.info != NULL)
OPENSSL_free(ctx->srp_ctx.info);
- if ((ctx->srp_ctx.info = BUF_strdup((char *)parg)) == NULL) {
- SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_INTERNAL_ERROR);
+ if ((ctx->srp_ctx.info = OPENSSL_strdup((char *)parg)) == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
break;
@@ -3920,17 +3903,16 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
break;
#endif
-#ifndef OPENSSL_NO_EC
case SSL_CTRL_SET_GROUPS:
return tls1_set_groups(&ctx->ext.supportedgroups,
&ctx->ext.supportedgroups_len,
parg, larg);
case SSL_CTRL_SET_GROUPS_LIST:
- return tls1_set_groups_list(&ctx->ext.supportedgroups,
+ return tls1_set_groups_list(ctx, &ctx->ext.supportedgroups,
&ctx->ext.supportedgroups_len,
parg);
-#endif
+
case SSL_CTRL_SET_SIGALGS:
return tls1_set_sigalgs(ctx->cert, parg, larg, 0);
@@ -3965,12 +3947,12 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
case SSL_CTRL_EXTRA_CHAIN_CERT:
if (ctx->extra_certs == NULL) {
if ((ctx->extra_certs = sk_X509_new_null()) == NULL) {
- SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
}
if (!sk_X509_push(ctx->extra_certs, (X509 *)parg)) {
- SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
break;
@@ -4018,7 +4000,7 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void))
{
switch (cmd) {
-#ifndef OPENSSL_NO_DH
+#if !defined(OPENSSL_NO_DEPRECATED_3_0)
case SSL_CTRL_SET_TMP_DH_CB:
{
ctx->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp;
@@ -4033,12 +4015,14 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void))
ctx->ext.status_cb = (int (*)(SSL *, void *))fp;
break;
+# ifndef OPENSSL_NO_DEPRECATED_3_0
case SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB:
ctx->ext.ticket_key_cb = (int (*)(SSL *, unsigned char *,
unsigned char *,
EVP_CIPHER_CTX *,
HMAC_CTX *, int))fp;
break;
+#endif
#ifndef OPENSSL_NO_SRP
case SSL_CTRL_SET_SRP_VERIFY_PARAM_CB:
@@ -4067,6 +4051,14 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void))
return 1;
}
+int SSL_CTX_set_tlsext_ticket_key_evp_cb
+ (SSL_CTX *ctx, int (*fp)(SSL *, unsigned char *, unsigned char *,
+ EVP_CIPHER_CTX *, EVP_MAC_CTX *, int))
+{
+ ctx->ext.ticket_key_evp_cb = fp;
+ return 1;
+}
+
const SSL_CIPHER *ssl3_get_cipher_by_id(uint32_t id)
{
SSL_CIPHER c;
@@ -4142,10 +4134,7 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
STACK_OF(SSL_CIPHER) *prio, *allow;
int i, ii, ok, prefer_sha256 = 0;
unsigned long alg_k = 0, alg_a = 0, mask_k = 0, mask_a = 0;
- const EVP_MD *mdsha256 = EVP_sha256();
-#ifndef OPENSSL_NO_CHACHA
STACK_OF(SSL_CIPHER) *prio_chacha = NULL;
-#endif
/* Let's see which ciphers we can support */
@@ -4156,20 +4145,20 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
* pay with the price of sk_SSL_CIPHER_dup().
*/
-#ifdef CIPHER_DEBUG
- fprintf(stderr, "Server has %d from %p:\n", sk_SSL_CIPHER_num(srvr),
- (void *)srvr);
- for (i = 0; i < sk_SSL_CIPHER_num(srvr); ++i) {
- c = sk_SSL_CIPHER_value(srvr, i);
- fprintf(stderr, "%p:%s\n", (void *)c, c->name);
- }
- fprintf(stderr, "Client sent %d from %p:\n", sk_SSL_CIPHER_num(clnt),
- (void *)clnt);
- for (i = 0; i < sk_SSL_CIPHER_num(clnt); ++i) {
- c = sk_SSL_CIPHER_value(clnt, i);
- fprintf(stderr, "%p:%s\n", (void *)c, c->name);
- }
-#endif
+ OSSL_TRACE_BEGIN(TLS_CIPHER) {
+ BIO_printf(trc_out, "Server has %d from %p:\n",
+ sk_SSL_CIPHER_num(srvr), (void *)srvr);
+ for (i = 0; i < sk_SSL_CIPHER_num(srvr); ++i) {
+ c = sk_SSL_CIPHER_value(srvr, i);
+ BIO_printf(trc_out, "%p:%s\n", (void *)c, c->name);
+ }
+ BIO_printf(trc_out, "Client sent %d from %p:\n",
+ sk_SSL_CIPHER_num(clnt), (void *)clnt);
+ for (i = 0; i < sk_SSL_CIPHER_num(clnt); ++i) {
+ c = sk_SSL_CIPHER_value(clnt, i);
+ BIO_printf(trc_out, "%p:%s\n", (void *)c, c->name);
+ }
+ } OSSL_TRACE_END(TLS_CIPHER);
/* SUITE-B takes precedence over server preference and ChaCha priortiy */
if (tls1_suiteb(s)) {
@@ -4178,7 +4167,7 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
} else if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
prio = srvr;
allow = clnt;
-#ifndef OPENSSL_NO_CHACHA
+
/* If ChaCha20 is at the top of the client preference list,
and there are ChaCha20 ciphers in the server list, then
temporarily prioritize all ChaCha20 ciphers in the servers list. */
@@ -4217,7 +4206,6 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
}
}
}
-# endif
} else {
prio = clnt;
allow = srvr;
@@ -4264,8 +4252,8 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
* key exchange scheme skip tests.
*/
if (!SSL_IS_TLS13(s)) {
- mask_k = s->s3->tmp.mask_k;
- mask_a = s->s3->tmp.mask_a;
+ mask_k = s->s3.tmp.mask_k;
+ mask_a = s->s3.tmp.mask_a;
#ifndef OPENSSL_NO_SRP
if (s->srp_ctx.srp_Mask & SSL_kSRP) {
mask_k |= SSL_kSRP;
@@ -4283,19 +4271,16 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
#endif /* OPENSSL_NO_PSK */
ok = (alg_k & mask_k) && (alg_a & mask_a);
-#ifdef CIPHER_DEBUG
- fprintf(stderr, "%d:[%08lX:%08lX:%08lX:%08lX]%p:%s\n", ok, alg_k,
- alg_a, mask_k, mask_a, (void *)c, c->name);
-#endif
+ OSSL_TRACE7(TLS_CIPHER,
+ "%d:[%08lX:%08lX:%08lX:%08lX]%p:%s\n",
+ ok, alg_k, alg_a, mask_k, mask_a, (void *)c, c->name);
-#ifndef OPENSSL_NO_EC
/*
* if we are considering an ECC cipher suite that uses an ephemeral
* EC key check it
*/
if (alg_k & SSL_kECDHE)
ok = ok && tls1_check_ec_tmp_key(s, c->id);
-#endif /* OPENSSL_NO_EC */
if (!ok)
continue;
@@ -4306,18 +4291,20 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
if (!ssl_security(s, SSL_SECOP_CIPHER_SHARED,
c->strength_bits, 0, (void *)c))
continue;
-#if !defined(OPENSSL_NO_EC)
+
if ((alg_k & SSL_kECDHE) && (alg_a & SSL_aECDSA)
- && s->s3->is_probably_safari) {
+ && s->s3.is_probably_safari) {
if (!ret)
ret = sk_SSL_CIPHER_value(allow, ii);
continue;
}
-#endif
+
if (prefer_sha256) {
const SSL_CIPHER *tmp = sk_SSL_CIPHER_value(allow, ii);
+ const EVP_MD *md = ssl_md(s->ctx, tmp->algorithm2);
- if (ssl_md(tmp->algorithm2) == mdsha256) {
+ if (md != NULL
+ && EVP_MD_is_a(md, OSSL_DIGEST_NAME_SHA2_256)) {
ret = tmp;
break;
}
@@ -4329,9 +4316,9 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
break;
}
}
-#ifndef OPENSSL_NO_CHACHA
+
sk_SSL_CIPHER_free(prio_chacha);
-#endif
+
return ret;
}
@@ -4345,36 +4332,35 @@ int ssl3_get_req_cert_type(SSL *s, WPACKET *pkt)
/* Get mask of algorithms disabled by signature list */
ssl_set_sig_mask(&alg_a, s, SSL_SECOP_SIGALG_MASK);
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
#ifndef OPENSSL_NO_GOST
if (s->version >= TLS1_VERSION && (alg_k & SSL_kGOST))
- return WPACKET_put_bytes_u8(pkt, TLS_CT_GOST01_SIGN)
- && WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_SIGN)
- && WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_512_SIGN);
+ if (!WPACKET_put_bytes_u8(pkt, TLS_CT_GOST01_SIGN)
+ || !WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_IANA_SIGN)
+ || !WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_IANA_512_SIGN)
+ || !WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_LEGACY_SIGN)
+ || !WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_LEGACY_512_SIGN))
+ return 0;
+
+ if (s->version >= TLS1_2_VERSION && (alg_k & SSL_kGOST18))
+ if (!WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_IANA_SIGN)
+ || !WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_IANA_512_SIGN))
+ return 0;
#endif
if ((s->version == SSL3_VERSION) && (alg_k & SSL_kDHE)) {
-#ifndef OPENSSL_NO_DH
-# ifndef OPENSSL_NO_RSA
if (!WPACKET_put_bytes_u8(pkt, SSL3_CT_RSA_EPHEMERAL_DH))
return 0;
-# endif
-# ifndef OPENSSL_NO_DSA
- if (!WPACKET_put_bytes_u8(pkt, SSL3_CT_DSS_EPHEMERAL_DH))
+ if (!(alg_a & SSL_aDSS)
+ && !WPACKET_put_bytes_u8(pkt, SSL3_CT_DSS_EPHEMERAL_DH))
return 0;
-# endif
-#endif /* !OPENSSL_NO_DH */
}
-#ifndef OPENSSL_NO_RSA
if (!(alg_a & SSL_aRSA) && !WPACKET_put_bytes_u8(pkt, SSL3_CT_RSA_SIGN))
return 0;
-#endif
-#ifndef OPENSSL_NO_DSA
if (!(alg_a & SSL_aDSS) && !WPACKET_put_bytes_u8(pkt, SSL3_CT_DSS_SIGN))
return 0;
-#endif
-#ifndef OPENSSL_NO_EC
+
/*
* ECDSA certs can be used with RSA cipher suites too so we don't
* need to check for SSL_kECDH or SSL_kECDHE
@@ -4383,7 +4369,7 @@ int ssl3_get_req_cert_type(SSL *s, WPACKET *pkt)
&& !(alg_a & SSL_aECDSA)
&& !WPACKET_put_bytes_u8(pkt, TLS_CT_ECDSA_SIGN))
return 0;
-#endif
+
return 1;
}
@@ -4421,11 +4407,11 @@ int ssl3_shutdown(SSL *s)
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_CLOSE_NOTIFY);
/*
* our shutdown alert has been sent now, and if it still needs to be
- * written, s->s3->alert_dispatch will be true
+ * written, s->s3.alert_dispatch will be true
*/
- if (s->s3->alert_dispatch)
+ if (s->s3.alert_dispatch)
return -1; /* return WANT_WRITE */
- } else if (s->s3->alert_dispatch) {
+ } else if (s->s3.alert_dispatch) {
/* resend it if not sent */
ret = s->method->ssl_dispatch_alert(s);
if (ret == -1) {
@@ -4448,7 +4434,7 @@ int ssl3_shutdown(SSL *s)
}
if ((s->shutdown == (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN)) &&
- !s->s3->alert_dispatch)
+ !s->s3.alert_dispatch)
return 1;
else
return 0;
@@ -4457,7 +4443,7 @@ int ssl3_shutdown(SSL *s)
int ssl3_write(SSL *s, const void *buf, size_t len, size_t *written)
{
clear_sys_error();
- if (s->s3->renegotiate)
+ if (s->s3.renegotiate)
ssl3_renegotiate_check(s, 0);
return s->method->ssl_write_bytes(s, SSL3_RT_APPLICATION_DATA, buf, len,
@@ -4470,13 +4456,13 @@ static int ssl3_read_internal(SSL *s, void *buf, size_t len, int peek,
int ret;
clear_sys_error();
- if (s->s3->renegotiate)
+ if (s->s3.renegotiate)
ssl3_renegotiate_check(s, 0);
- s->s3->in_read_app_data = 1;
+ s->s3.in_read_app_data = 1;
ret =
s->method->ssl_read_bytes(s, SSL3_RT_APPLICATION_DATA, NULL, buf, len,
peek, readbytes);
- if ((ret == -1) && (s->s3->in_read_app_data == 2)) {
+ if ((ret == -1) && (s->s3.in_read_app_data == 2)) {
/*
* ssl3_read_bytes decided to call s->handshake_func, which called
* ssl3_read_bytes to read handshake data. However, ssl3_read_bytes
@@ -4490,7 +4476,7 @@ static int ssl3_read_internal(SSL *s, void *buf, size_t len, int peek,
len, peek, readbytes);
ossl_statem_set_in_handshake(s, 0);
} else
- s->s3->in_read_app_data = 0;
+ s->s3.in_read_app_data = 0;
return ret;
}
@@ -4510,7 +4496,7 @@ int ssl3_renegotiate(SSL *s)
if (s->handshake_func == NULL)
return 1;
- s->s3->renegotiate = 1;
+ s->s3.renegotiate = 1;
return 1;
}
@@ -4526,7 +4512,7 @@ int ssl3_renegotiate_check(SSL *s, int initok)
{
int ret = 0;
- if (s->s3->renegotiate) {
+ if (s->s3.renegotiate) {
if (!RECORD_LAYER_read_pending(&s->rlayer)
&& !RECORD_LAYER_write_pending(&s->rlayer)
&& (initok || !SSL_in_init(s))) {
@@ -4536,9 +4522,9 @@ int ssl3_renegotiate_check(SSL *s, int initok)
* state.
*/
ossl_statem_set_renegotiate(s);
- s->s3->renegotiate = 0;
- s->s3->num_renegotiations++;
- s->s3->total_renegotiations++;
+ s->s3.renegotiate = 0;
+ s->s3.num_renegotiations++;
+ s->s3.total_renegotiations++;
ret = 1;
}
}
@@ -4554,13 +4540,13 @@ int ssl3_renegotiate_check(SSL *s, int initok)
long ssl_get_algorithm2(SSL *s)
{
long alg2;
- if (s->s3 == NULL || s->s3->tmp.new_cipher == NULL)
+ if (s->s3.tmp.new_cipher == NULL)
return -1;
- alg2 = s->s3->tmp.new_cipher->algorithm2;
+ alg2 = s->s3.tmp.new_cipher->algorithm2;
if (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_SHA256_PRF) {
if (alg2 == (SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF))
return SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256;
- } else if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK) {
+ } else if (s->s3.tmp.new_cipher->algorithm_mkey & SSL_PSK) {
if (alg2 == (SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384))
return SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF;
}
@@ -4587,9 +4573,9 @@ int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, size_t len,
unsigned char *p = result;
l2n(Time, p);
- ret = RAND_bytes(p, len - 4);
+ ret = RAND_bytes_ex(s->ctx->libctx, p, len - 4, 0);
} else {
- ret = RAND_bytes(result, len);
+ ret = RAND_bytes_ex(s->ctx->libctx, result, len, 0);
}
if (ret > 0) {
@@ -4610,13 +4596,13 @@ int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, size_t len,
int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
int free_pms)
{
- unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ unsigned long alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
int ret = 0;
if (alg_k & SSL_PSK) {
#ifndef OPENSSL_NO_PSK
unsigned char *pskpms, *t;
- size_t psklen = s->s3->tmp.psklen;
+ size_t psklen = s->s3.tmp.psklen;
size_t pskpmslen;
/* create PSK premaster_secret */
@@ -4637,11 +4623,11 @@ int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
memcpy(t, pms, pmslen);
t += pmslen;
s2n(psklen, t);
- memcpy(t, s->s3->tmp.psk, psklen);
+ memcpy(t, s->s3.tmp.psk, psklen);
- OPENSSL_clear_free(s->s3->tmp.psk, psklen);
- s->s3->tmp.psk = NULL;
- s->s3->tmp.psklen = 0;
+ OPENSSL_clear_free(s->s3.tmp.psk, psklen);
+ s->s3.tmp.psk = NULL;
+ s->s3.tmp.psklen = 0;
if (!s->method->ssl3_enc->generate_master_secret(s,
s->session->master_key, pskpms, pskpmslen,
&s->session->master_key_length)) {
@@ -4672,21 +4658,21 @@ int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
OPENSSL_cleanse(pms, pmslen);
}
if (s->server == 0) {
- s->s3->tmp.pms = NULL;
- s->s3->tmp.pmslen = 0;
+ s->s3.tmp.pms = NULL;
+ s->s3.tmp.pmslen = 0;
}
return ret;
}
/* Generate a private key from parameters */
-EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm)
+EVP_PKEY *ssl_generate_pkey(SSL *s, EVP_PKEY *pm)
{
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *pkey = NULL;
if (pm == NULL)
return NULL;
- pctx = EVP_PKEY_CTX_new(pm, NULL);
+ pctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, pm, s->ctx->propq);
if (pctx == NULL)
goto err;
if (EVP_PKEY_keygen_init(pctx) <= 0)
@@ -4700,44 +4686,36 @@ EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm)
EVP_PKEY_CTX_free(pctx);
return pkey;
}
-#ifndef OPENSSL_NO_EC
+
/* Generate a private key from a group ID */
EVP_PKEY *ssl_generate_pkey_group(SSL *s, uint16_t id)
{
+ const TLS_GROUP_INFO *ginf = tls1_group_id_lookup(s->ctx, id);
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *pkey = NULL;
- const TLS_GROUP_INFO *ginf = tls1_group_id_lookup(id);
- uint16_t gtype;
if (ginf == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- gtype = ginf->flags & TLS_CURVE_TYPE;
- if (gtype == TLS_CURVE_CUSTOM)
- pctx = EVP_PKEY_CTX_new_id(ginf->nid, NULL);
- else
- pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
+
+ pctx = EVP_PKEY_CTX_new_from_name(s->ctx->libctx, ginf->algorithm,
+ s->ctx->propq);
+
if (pctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_PKEY_keygen_init(pctx) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP,
- ERR_R_EVP_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
- if (gtype != TLS_CURVE_CUSTOM
- && EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ginf->nid) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP,
- ERR_R_EVP_LIB);
+ if (EVP_PKEY_CTX_set_group_name(pctx, ginf->realname) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
if (EVP_PKEY_keygen(pctx, &pkey) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP,
- ERR_R_EVP_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
EVP_PKEY_free(pkey);
pkey = NULL;
}
@@ -4750,30 +4728,26 @@ EVP_PKEY *ssl_generate_pkey_group(SSL *s, uint16_t id)
/*
* Generate parameters from a group ID
*/
-EVP_PKEY *ssl_generate_param_group(uint16_t id)
+EVP_PKEY *ssl_generate_param_group(SSL *s, uint16_t id)
{
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *pkey = NULL;
- const TLS_GROUP_INFO *ginf = tls1_group_id_lookup(id);
+ const TLS_GROUP_INFO *ginf = tls1_group_id_lookup(s->ctx, id);
if (ginf == NULL)
goto err;
- if ((ginf->flags & TLS_CURVE_TYPE) == TLS_CURVE_CUSTOM) {
- pkey = EVP_PKEY_new();
- if (pkey != NULL && EVP_PKEY_set_type(pkey, ginf->nid))
- return pkey;
- EVP_PKEY_free(pkey);
- return NULL;
- }
+ pctx = EVP_PKEY_CTX_new_from_name(s->ctx->libctx, ginf->algorithm,
+ s->ctx->propq);
- pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
if (pctx == NULL)
goto err;
if (EVP_PKEY_paramgen_init(pctx) <= 0)
goto err;
- if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ginf->nid) <= 0)
+ if (EVP_PKEY_CTX_set_group_name(pctx, ginf->realname) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
+ }
if (EVP_PKEY_paramgen(pctx, &pkey) <= 0) {
EVP_PKEY_free(pkey);
pkey = NULL;
@@ -4783,7 +4757,32 @@ EVP_PKEY *ssl_generate_param_group(uint16_t id)
EVP_PKEY_CTX_free(pctx);
return pkey;
}
-#endif
+
+/* Generate secrets from pms */
+int ssl_gensecret(SSL *s, unsigned char *pms, size_t pmslen)
+{
+ int rv = 0;
+
+ /* SSLfatal() called as appropriate in the below functions */
+ if (SSL_IS_TLS13(s)) {
+ /*
+ * If we are resuming then we already generated the early secret
+ * when we created the ClientHello, so don't recreate it.
+ */
+ if (!s->hit)
+ rv = tls13_generate_secret(s, ssl_handshake_md(s), NULL, NULL,
+ 0,
+ (unsigned char *)&s->early_secret);
+ else
+ rv = 1;
+
+ rv = rv && tls13_generate_handshake_secret(s, pms, pmslen);
+ } else {
+ rv = ssl_generate_master_secret(s, pms, pmslen, 0);
+ }
+
+ return rv;
+}
/* Derive secrets for ECDH/DH */
int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey, int gensecret)
@@ -4794,56 +4793,91 @@ int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey, int gensecret)
EVP_PKEY_CTX *pctx;
if (privkey == NULL || pubkey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DERIVE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
- pctx = EVP_PKEY_CTX_new(privkey, NULL);
+ pctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, privkey, s->ctx->propq);
if (EVP_PKEY_derive_init(pctx) <= 0
|| EVP_PKEY_derive_set_peer(pctx, pubkey) <= 0
|| EVP_PKEY_derive(pctx, NULL, &pmslen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DERIVE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
+ if (SSL_IS_TLS13(s) && EVP_PKEY_is_a(privkey, "DH"))
+ EVP_PKEY_CTX_set_dh_pad(pctx, 1);
+
pms = OPENSSL_malloc(pmslen);
if (pms == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DERIVE,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_PKEY_derive(pctx, pms, &pmslen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DERIVE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (gensecret) {
/* SSLfatal() called as appropriate in the below functions */
- if (SSL_IS_TLS13(s)) {
- /*
- * If we are resuming then we already generated the early secret
- * when we created the ClientHello, so don't recreate it.
- */
- if (!s->hit)
- rv = tls13_generate_secret(s, ssl_handshake_md(s), NULL, NULL,
- 0,
- (unsigned char *)&s->early_secret);
- else
- rv = 1;
+ rv = ssl_gensecret(s, pms, pmslen);
+ } else {
+ /* Save premaster secret */
+ s->s3.tmp.pms = pms;
+ s->s3.tmp.pmslen = pmslen;
+ pms = NULL;
+ rv = 1;
+ }
- rv = rv && tls13_generate_handshake_secret(s, pms, pmslen);
- } else {
- rv = ssl_generate_master_secret(s, pms, pmslen, 0);
- }
+ err:
+ OPENSSL_clear_free(pms, pmslen);
+ EVP_PKEY_CTX_free(pctx);
+ return rv;
+}
+
+/* Decapsulate secrets for KEM */
+int ssl_decapsulate(SSL *s, EVP_PKEY *privkey,
+ const unsigned char *ct, size_t ctlen,
+ int gensecret)
+{
+ int rv = 0;
+ unsigned char *pms = NULL;
+ size_t pmslen = 0;
+ EVP_PKEY_CTX *pctx;
+
+ if (privkey == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ pctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, privkey, s->ctx->propq);
+
+ if (EVP_PKEY_decapsulate_init(pctx, NULL) <= 0
+ || EVP_PKEY_decapsulate(pctx, NULL, &pmslen, ct, ctlen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ pms = OPENSSL_malloc(pmslen);
+ if (pms == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (EVP_PKEY_decapsulate(pctx, pms, &pmslen, ct, ctlen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (gensecret) {
+ /* SSLfatal() called as appropriate in the below functions */
+ rv = ssl_gensecret(s, pms, pmslen);
} else {
/* Save premaster secret */
- s->s3->tmp.pms = pms;
- s->s3->tmp.pmslen = pmslen;
+ s->s3.tmp.pms = pms;
+ s->s3.tmp.pmslen = pmslen;
pms = NULL;
rv = 1;
}
@@ -4854,17 +4888,80 @@ int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey, int gensecret)
return rv;
}
-#ifndef OPENSSL_NO_DH
-EVP_PKEY *ssl_dh_to_pkey(DH *dh)
+int ssl_encapsulate(SSL *s, EVP_PKEY *pubkey,
+ unsigned char **ctp, size_t *ctlenp,
+ int gensecret)
{
- EVP_PKEY *ret;
- if (dh == NULL)
- return NULL;
- ret = EVP_PKEY_new();
- if (EVP_PKEY_set1_DH(ret, dh) <= 0) {
- EVP_PKEY_free(ret);
- return NULL;
+ int rv = 0;
+ unsigned char *pms = NULL, *ct = NULL;
+ size_t pmslen = 0, ctlen = 0;
+ EVP_PKEY_CTX *pctx;
+
+ if (pubkey == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
- return ret;
+
+ pctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, pubkey, s->ctx->propq);
+
+ if (EVP_PKEY_encapsulate_init(pctx, NULL) <= 0
+ || EVP_PKEY_encapsulate(pctx, NULL, &ctlen, NULL, &pmslen) <= 0
+ || pmslen == 0 || ctlen == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ pms = OPENSSL_malloc(pmslen);
+ ct = OPENSSL_malloc(ctlen);
+ if (pms == NULL || ct == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (EVP_PKEY_encapsulate(pctx, ct, &ctlen, pms, &pmslen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (gensecret) {
+ /* SSLfatal() called as appropriate in the below functions */
+ rv = ssl_gensecret(s, pms, pmslen);
+ } else {
+ /* Save premaster secret */
+ s->s3.tmp.pms = pms;
+ s->s3.tmp.pmslen = pmslen;
+ pms = NULL;
+ rv = 1;
+ }
+
+ if (rv > 0) {
+ /* Pass ownership of ct to caller */
+ *ctp = ct;
+ *ctlenp = ctlen;
+ ct = NULL;
+ }
+
+ err:
+ OPENSSL_clear_free(pms, pmslen);
+ OPENSSL_free(ct);
+ EVP_PKEY_CTX_free(pctx);
+ return rv;
+}
+
+const char *SSL_group_to_name(SSL *s, int nid) {
+ int group_id = 0;
+ const TLS_GROUP_INFO *cinf = NULL;
+
+ /* first convert to real group id for internal and external IDs */
+ if (nid & TLSEXT_nid_unknown)
+ group_id = nid & 0xFFFF;
+ else
+ group_id = tls1_nid2group_id(nid);
+
+ /* then look up */
+ cinf = tls1_group_id_lookup(s->ctx, group_id);
+
+ if (cinf != NULL)
+ return cinf->tlsname;
+ return NULL;
}
-#endif
diff --git a/ssl/s3_msg.c b/ssl/s3_msg.c
index 707e962d73d4..c0f0dbc17dcc 100644
--- a/ssl/s3_msg.c
+++ b/ssl/s3_msg.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -18,20 +18,24 @@ int ssl3_do_change_cipher_spec(SSL *s)
else
i = SSL3_CHANGE_CIPHER_CLIENT_READ;
- if (s->s3->tmp.key_block == NULL) {
+ if (s->s3.tmp.key_block == NULL) {
if (s->session == NULL || s->session->master_key_length == 0) {
/* might happen if dtls1_read_bytes() calls this */
- SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY);
+ ERR_raise(ERR_LIB_SSL, SSL_R_CCS_RECEIVED_EARLY);
return 0;
}
- s->session->cipher = s->s3->tmp.new_cipher;
- if (!s->method->ssl3_enc->setup_key_block(s))
+ s->session->cipher = s->s3.tmp.new_cipher;
+ if (!s->method->ssl3_enc->setup_key_block(s)) {
+ /* SSLfatal() already called */
return 0;
+ }
}
- if (!s->method->ssl3_enc->change_cipher_state(s, i))
+ if (!s->method->ssl3_enc->change_cipher_state(s, i)) {
+ /* SSLfatal() already called */
return 0;
+ }
return 1;
}
@@ -54,9 +58,9 @@ int ssl3_send_alert(SSL *s, int level, int desc)
if ((level == SSL3_AL_FATAL) && (s->session != NULL))
SSL_CTX_remove_session(s->session_ctx, s->session);
- s->s3->alert_dispatch = 1;
- s->s3->send_alert[0] = level;
- s->s3->send_alert[1] = desc;
+ s->s3.alert_dispatch = 1;
+ s->s3.send_alert[0] = level;
+ s->s3.send_alert[1] = desc;
if (!RECORD_LAYER_write_pending(&s->rlayer)) {
/* data still being written out? */
return s->method->ssl_dispatch_alert(s);
@@ -75,12 +79,12 @@ int ssl3_dispatch_alert(SSL *s)
void (*cb) (const SSL *ssl, int type, int val) = NULL;
size_t written;
- s->s3->alert_dispatch = 0;
+ s->s3.alert_dispatch = 0;
alertlen = 2;
- i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], &alertlen, 1, 0,
+ i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3.send_alert[0], &alertlen, 1, 0,
&written);
if (i <= 0) {
- s->s3->alert_dispatch = 1;
+ s->s3.alert_dispatch = 1;
} else {
/*
* Alert sent to BIO - now flush. If the message does not get sent due
@@ -89,7 +93,7 @@ int ssl3_dispatch_alert(SSL *s)
(void)BIO_flush(s->wbio);
if (s->msg_callback)
- s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert,
+ s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3.send_alert,
2, s, s->msg_callback_arg);
if (s->info_callback != NULL)
@@ -98,7 +102,7 @@ int ssl3_dispatch_alert(SSL *s)
cb = s->ctx->info_callback;
if (cb != NULL) {
- j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1];
+ j = (s->s3.send_alert[0] << 8) | s->s3.send_alert[1];
cb(s, SSL_CB_WRITE_ALERT, j);
}
}
diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c
index 926436410050..3503fdc21060 100644
--- a/ssl/ssl_asn1.c
+++ b/ssl/ssl_asn1.c
@@ -2,7 +2,7 @@
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -43,6 +43,7 @@ typedef struct {
ASN1_OCTET_STRING *alpn_selected;
uint32_t tlsext_max_fragment_len_mode;
ASN1_OCTET_STRING *ticket_appdata;
+ uint32_t kex_group;
} SSL_SESSION_ASN1;
ASN1_SEQUENCE(SSL_SESSION_ASN1) = {
@@ -73,7 +74,8 @@ ASN1_SEQUENCE(SSL_SESSION_ASN1) = {
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, max_early_data, ZUINT32, 15),
ASN1_EXP_OPT(SSL_SESSION_ASN1, alpn_selected, ASN1_OCTET_STRING, 16),
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, tlsext_max_fragment_len_mode, ZUINT32, 17),
- ASN1_EXP_OPT(SSL_SESSION_ASN1, ticket_appdata, ASN1_OCTET_STRING, 18)
+ ASN1_EXP_OPT(SSL_SESSION_ASN1, ticket_appdata, ASN1_OCTET_STRING, 18),
+ ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, kex_group, UINT32, 19)
} static_ASN1_SEQUENCE_END(SSL_SESSION_ASN1)
IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(SSL_SESSION_ASN1)
@@ -83,9 +85,9 @@ IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(SSL_SESSION_ASN1)
/* Initialise OCTET STRING from buffer and length */
static void ssl_session_oinit(ASN1_OCTET_STRING **dest, ASN1_OCTET_STRING *os,
- unsigned char *data, size_t len)
+ const unsigned char *data, size_t len)
{
- os->data = data;
+ os->data = (unsigned char *)data; /* justified cast: data is not modified */
os->length = (int)len;
os->flags = 0;
*dest = os;
@@ -93,15 +95,15 @@ static void ssl_session_oinit(ASN1_OCTET_STRING **dest, ASN1_OCTET_STRING *os,
/* Initialise OCTET STRING from string */
static void ssl_session_sinit(ASN1_OCTET_STRING **dest, ASN1_OCTET_STRING *os,
- char *data)
+ const char *data)
{
if (data != NULL)
- ssl_session_oinit(dest, os, (unsigned char *)data, strlen(data));
+ ssl_session_oinit(dest, os, (const unsigned char *)data, strlen(data));
else
*dest = NULL;
}
-int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
+int i2d_SSL_SESSION(const SSL_SESSION *in, unsigned char **pp)
{
SSL_SESSION_ASN1 as;
@@ -134,6 +136,8 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
as.version = SSL_SESSION_ASN1_VERSION;
as.ssl_version = in->ssl_version;
+ as.kex_group = in->kex_group;
+
if (in->cipher == NULL)
l = in->cipher_id;
else
@@ -159,8 +163,8 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
ssl_session_oinit(&as.session_id_context, &sid_ctx,
in->sid_ctx, in->sid_ctx_length);
- as.time = in->time;
- as.timeout = in->timeout;
+ as.time = (int64_t)in->time;
+ as.timeout = (int64_t)in->timeout;
as.verify_result = in->verify_result;
as.peer = in->peer;
@@ -250,7 +254,7 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
if (as == NULL)
goto err;
- if (!a || !*a) {
+ if (a == NULL || *a == NULL) {
ret = SSL_SESSION_new();
if (ret == NULL)
goto err;
@@ -259,21 +263,23 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
}
if (as->version != SSL_SESSION_ASN1_VERSION) {
- SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_UNKNOWN_SSL_VERSION);
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNKNOWN_SSL_VERSION);
goto err;
}
if ((as->ssl_version >> 8) != SSL3_VERSION_MAJOR
&& (as->ssl_version >> 8) != DTLS1_VERSION_MAJOR
&& as->ssl_version != DTLS1_BAD_VER) {
- SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_UNSUPPORTED_SSL_VERSION);
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNSUPPORTED_SSL_VERSION);
goto err;
}
ret->ssl_version = (int)as->ssl_version;
+ ret->kex_group = as->kex_group;
+
if (as->cipher->length != 2) {
- SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_CIPHER_CODE_WRONG_LENGTH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_CIPHER_CODE_WRONG_LENGTH);
goto err;
}
@@ -296,14 +302,15 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
ret->master_key_length = tmpl;
if (as->time != 0)
- ret->time = (long)as->time;
+ ret->time = (time_t)as->time;
else
- ret->time = (long)time(NULL);
+ ret->time = time(NULL);
if (as->timeout != 0)
- ret->timeout = (long)as->timeout;
+ ret->timeout = (time_t)as->timeout;
else
ret->timeout = 3;
+ ssl_session_calculate_timeout(ret);
X509_free(ret->peer);
ret->peer = as->peer;
@@ -339,7 +346,7 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
#ifndef OPENSSL_NO_COMP
if (as->comp_id) {
if (as->comp_id->length != 1) {
- SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_BAD_LENGTH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_LENGTH);
goto err;
}
ret->compress_meth = as->comp_id->data[0];
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index b615e7048da4..e4168e74c276 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -2,7 +2,7 @@
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -15,6 +15,7 @@
#include "internal/o_dir.h"
#include <openssl/bio.h>
#include <openssl/pem.h>
+#include <openssl/store.h>
#include <openssl/x509v3.h>
#include <openssl/dh.h>
#include <openssl/bn.h>
@@ -52,7 +53,7 @@ CERT *ssl_cert_new(void)
CERT *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- SSLerr(SSL_F_SSL_CERT_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -63,7 +64,7 @@ CERT *ssl_cert_new(void)
ret->sec_ex = NULL;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
- SSLerr(SSL_F_SSL_CERT_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
@@ -77,7 +78,7 @@ CERT *ssl_cert_dup(CERT *cert)
int i;
if (ret == NULL) {
- SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -85,18 +86,18 @@ CERT *ssl_cert_dup(CERT *cert)
ret->key = &ret->pkeys[cert->key - cert->pkeys];
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
- SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
-#ifndef OPENSSL_NO_DH
+
if (cert->dh_tmp != NULL) {
ret->dh_tmp = cert->dh_tmp;
EVP_PKEY_up_ref(ret->dh_tmp);
}
+
ret->dh_tmp_cb = cert->dh_tmp_cb;
ret->dh_tmp_auto = cert->dh_tmp_auto;
-#endif
for (i = 0; i < SSL_PKEY_NUM; i++) {
CERT_PKEY *cpk = cert->pkeys + i;
@@ -114,7 +115,7 @@ CERT *ssl_cert_dup(CERT *cert)
if (cpk->chain) {
rpk->chain = X509_chain_up_ref(cpk->chain);
if (!rpk->chain) {
- SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -123,7 +124,7 @@ CERT *ssl_cert_dup(CERT *cert)
ret->pkeys[i].serverinfo =
OPENSSL_malloc(cert->pkeys[i].serverinfo_length);
if (ret->pkeys[i].serverinfo == NULL) {
- SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->pkeys[i].serverinfo_length = cert->pkeys[i].serverinfo_length;
@@ -231,9 +232,7 @@ void ssl_cert_free(CERT *c)
return;
REF_ASSERT_ISNT(i < 0);
-#ifndef OPENSSL_NO_DH
EVP_PKEY_free(c->dh_tmp);
-#endif
ssl_cert_clear_certs(c);
OPENSSL_free(c->conf_sigalgs);
@@ -252,13 +251,16 @@ void ssl_cert_free(CERT *c)
int ssl_cert_set0_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain)
{
int i, r;
- CERT_PKEY *cpk = s ? s->cert->key : ctx->cert->key;
+ CERT_PKEY *cpk = s != NULL ? s->cert->key : ctx->cert->key;
+
if (!cpk)
return 0;
for (i = 0; i < sk_X509_num(chain); i++) {
- r = ssl_security_cert(s, ctx, sk_X509_value(chain, i), 0, 0);
+ X509 *x = sk_X509_value(chain, i);
+
+ r = ssl_security_cert(s, ctx, x, 0, 0);
if (r != 1) {
- SSLerr(SSL_F_SSL_CERT_SET0_CHAIN, r);
+ ERR_raise(ERR_LIB_SSL, r);
return 0;
}
}
@@ -290,7 +292,7 @@ int ssl_cert_add0_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x)
return 0;
r = ssl_security_cert(s, ctx, x, 0, 0);
if (r != 1) {
- SSLerr(SSL_F_SSL_CERT_ADD0_CHAIN_CERT, r);
+ ERR_raise(ERR_LIB_SSL, r);
return 0;
}
if (!cpk->chain)
@@ -360,6 +362,13 @@ void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg)
c->cert_cb_arg = arg;
}
+/*
+ * Verify a certificate chain
+ * Return codes:
+ * 1: Verify success
+ * 0: Verify failure or error
+ * -1: Retry required
+ */
int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
{
X509 *x;
@@ -376,15 +385,15 @@ int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
else
verify_store = s->ctx->cert_store;
- ctx = X509_STORE_CTX_new();
+ ctx = X509_STORE_CTX_new_ex(s->ctx->libctx, s->ctx->propq);
if (ctx == NULL) {
- SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
x = sk_X509_value(sk, 0);
if (!X509_STORE_CTX_init(ctx, verify_store, x, sk)) {
- SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_X509_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_X509_LIB);
goto end;
}
param = X509_STORE_CTX_get0_param(ctx);
@@ -421,10 +430,14 @@ int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
if (s->verify_callback)
X509_STORE_CTX_set_verify_cb(ctx, s->verify_callback);
- if (s->ctx->app_verify_callback != NULL)
+ if (s->ctx->app_verify_callback != NULL) {
i = s->ctx->app_verify_callback(ctx, s->ctx->app_verify_arg);
- else
+ } else {
i = X509_verify_cert(ctx);
+ /* We treat an error in the same way as a failure to verify */
+ if (i < 0)
+ i = 0;
+ }
s->verify_result = X509_STORE_CTX_get_error(ctx);
sk_X509_pop_free(s->verified_chain, X509_free);
@@ -432,7 +445,7 @@ int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
if (X509_STORE_CTX_get0_chain(ctx) != NULL) {
s->verified_chain = X509_STORE_CTX_get1_chain(ctx);
if (s->verified_chain == NULL) {
- SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
i = 0;
}
}
@@ -461,13 +474,13 @@ STACK_OF(X509_NAME) *SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk)
ret = sk_X509_NAME_new_reserve(NULL, num);
if (ret == NULL) {
- SSLerr(SSL_F_SSL_DUP_CA_LIST, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
for (i = 0; i < num; i++) {
name = X509_NAME_dup(sk_X509_NAME_value(sk, i));
if (name == NULL) {
- SSLerr(SSL_F_SSL_DUP_CA_LIST, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
sk_X509_NAME_pop_free(ret, X509_NAME_free);
return NULL;
}
@@ -513,13 +526,13 @@ void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list)
const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s)
{
- return s->s3 != NULL ? s->s3->tmp.peer_ca_names : NULL;
+ return s->s3.tmp.peer_ca_names;
}
STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s)
{
if (!s->server)
- return s->s3 != NULL ? s->s3->tmp.peer_ca_names : NULL;
+ return s->s3.tmp.peer_ca_names;
return s->client_ca_names != NULL ? s->client_ca_names
: s->ctx->client_ca_names;
}
@@ -598,32 +611,43 @@ static int xname_sk_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
static unsigned long xname_hash(const X509_NAME *a)
{
- return X509_NAME_hash((X509_NAME *)a);
+ /* This returns 0 also if SHA1 is not available */
+ return X509_NAME_hash_ex((X509_NAME *)a, NULL, NULL, NULL);
}
-STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
+STACK_OF(X509_NAME) *SSL_load_client_CA_file_ex(const char *file,
+ OSSL_LIB_CTX *libctx,
+ const char *propq)
{
BIO *in = BIO_new(BIO_s_file());
X509 *x = NULL;
X509_NAME *xn = NULL;
STACK_OF(X509_NAME) *ret = NULL;
LHASH_OF(X509_NAME) *name_hash = lh_X509_NAME_new(xname_hash, xname_cmp);
+ OSSL_LIB_CTX *prev_libctx = NULL;
if ((name_hash == NULL) || (in == NULL)) {
- SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (!BIO_read_filename(in, file))
+ x = X509_new_ex(libctx, propq);
+ if (x == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (BIO_read_filename(in, file) <= 0)
goto err;
+ /* Internally lh_X509_NAME_retrieve() needs the libctx to retrieve SHA1 */
+ prev_libctx = OSSL_LIB_CTX_set0_default(libctx);
for (;;) {
if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
break;
if (ret == NULL) {
ret = sk_X509_NAME_new_null();
if (ret == NULL) {
- SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -650,6 +674,8 @@ STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
sk_X509_NAME_pop_free(ret, X509_NAME_free);
ret = NULL;
done:
+ /* restore the old libctx */
+ OSSL_LIB_CTX_set0_default(prev_libctx);
BIO_free(in);
X509_free(x);
lh_X509_NAME_free(name_hash);
@@ -658,6 +684,11 @@ STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
return ret;
}
+STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
+{
+ return SSL_load_client_CA_file_ex(file, NULL, NULL);
+}
+
int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
const char *file)
{
@@ -672,11 +703,11 @@ int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
in = BIO_new(BIO_s_file());
if (in == NULL) {
- SSLerr(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (!BIO_read_filename(in, file))
+ if (BIO_read_filename(in, file) <= 0)
goto err;
for (;;) {
@@ -722,8 +753,7 @@ int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
int r;
if (strlen(dir) + strlen(filename) + 2 > sizeof(buf)) {
- SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,
- SSL_R_PATH_TOO_LONG);
+ ERR_raise(ERR_LIB_SSL, SSL_R_PATH_TOO_LONG);
goto err;
}
#ifdef OPENSSL_SYS_VMS
@@ -738,9 +768,9 @@ int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
}
if (errno) {
- SYSerr(SYS_F_OPENDIR, get_last_sys_error());
- ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')");
- SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB);
+ ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
+ "calling OPENSSL_dir_read(%s)", dir);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB);
goto err;
}
@@ -753,6 +783,71 @@ int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
return ret;
}
+static int add_uris_recursive(STACK_OF(X509_NAME) *stack,
+ const char *uri, int depth)
+{
+ int ok = 1;
+ OSSL_STORE_CTX *ctx = NULL;
+ X509 *x = NULL;
+ X509_NAME *xn = NULL;
+
+ if ((ctx = OSSL_STORE_open(uri, NULL, NULL, NULL, NULL)) == NULL)
+ goto err;
+
+ while (!OSSL_STORE_eof(ctx) && !OSSL_STORE_error(ctx)) {
+ OSSL_STORE_INFO *info = OSSL_STORE_load(ctx);
+ int infotype = info == 0 ? 0 : OSSL_STORE_INFO_get_type(info);
+
+ if (info == NULL)
+ continue;
+
+ if (infotype == OSSL_STORE_INFO_NAME) {
+ /*
+ * This is an entry in the "directory" represented by the current
+ * uri. if |depth| allows, dive into it.
+ */
+ if (depth > 0)
+ ok = add_uris_recursive(stack, OSSL_STORE_INFO_get0_NAME(info),
+ depth - 1);
+ } else if (infotype == OSSL_STORE_INFO_CERT) {
+ if ((x = OSSL_STORE_INFO_get0_CERT(info)) == NULL
+ || (xn = X509_get_subject_name(x)) == NULL
+ || (xn = X509_NAME_dup(xn)) == NULL)
+ goto err;
+ if (sk_X509_NAME_find(stack, xn) >= 0) {
+ /* Duplicate. */
+ X509_NAME_free(xn);
+ } else if (!sk_X509_NAME_push(stack, xn)) {
+ X509_NAME_free(xn);
+ goto err;
+ }
+ }
+
+ OSSL_STORE_INFO_free(info);
+ }
+
+ ERR_clear_error();
+ goto done;
+
+ err:
+ ok = 0;
+ done:
+ OSSL_STORE_close(ctx);
+
+ return ok;
+}
+
+int SSL_add_store_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
+ const char *store)
+{
+ int (*oldcmp) (const X509_NAME *const *a, const X509_NAME *const *b)
+ = sk_X509_NAME_set_cmp_func(stack, xname_sk_cmp);
+ int ret = add_uris_recursive(stack, store, 1);
+
+ (void)sk_X509_NAME_set_cmp_func(stack, oldcmp);
+ return ret;
+}
+
/* Build a certificate chain for current certificate */
int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags)
{
@@ -762,10 +857,11 @@ int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags)
X509_STORE_CTX *xs_ctx = NULL;
STACK_OF(X509) *chain = NULL, *untrusted = NULL;
X509 *x;
+ SSL_CTX *real_ctx = (s == NULL) ? ctx : s->ctx;
int i, rv = 0;
if (!cpk->x509) {
- SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_NO_CERTIFICATE_SET);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_SET);
goto err;
}
/* Rearranging and check the chain: add everything to a store */
@@ -793,13 +889,13 @@ int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags)
untrusted = cpk->chain;
}
- xs_ctx = X509_STORE_CTX_new();
+ xs_ctx = X509_STORE_CTX_new_ex(real_ctx->libctx, real_ctx->propq);
if (xs_ctx == NULL) {
- SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!X509_STORE_CTX_init(xs_ctx, chain_store, cpk->x509, untrusted)) {
- SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_X509_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_X509_LIB);
goto err;
}
/* Set suite B flags if needed */
@@ -816,10 +912,9 @@ int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags)
if (i > 0)
chain = X509_STORE_CTX_get1_chain(xs_ctx);
if (i <= 0) {
- SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_CERTIFICATE_VERIFY_FAILED);
i = X509_STORE_CTX_get_error(xs_ctx);
- ERR_add_error_data(2, "Verify error:",
- X509_verify_cert_error_string(i));
+ ERR_raise_data(ERR_LIB_SSL, SSL_R_CERTIFICATE_VERIFY_FAILED,
+ "Verify error:%s", X509_verify_cert_error_string(i));
goto err;
}
@@ -844,7 +939,7 @@ int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags)
x = sk_X509_value(chain, i);
rv = ssl_security_cert(s, ctx, x, 0, 0);
if (rv != 1) {
- SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, rv);
+ ERR_raise(ERR_LIB_SSL, rv);
sk_X509_pop_free(chain, X509_free);
rv = 0;
goto err;
@@ -885,6 +980,11 @@ int ssl_cert_get_cert_store(CERT *c, X509_STORE **pstore, int chain)
int ssl_get_security_level_bits(const SSL *s, const SSL_CTX *ctx, int *levelp)
{
int level;
+ /*
+ * note that there's a corresponding minbits_table
+ * in crypto/x509/x509_vfy.c that's used for checking the security level
+ * of RSA and DSA keys
+ */
static const int minbits_table[5 + 1] = { 0, 80, 112, 128, 192, 256 };
if (ctx != NULL)
@@ -1008,19 +1108,20 @@ int ssl_cert_lookup_by_nid(int nid, size_t *pidx)
const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, size_t *pidx)
{
- int nid = EVP_PKEY_id(pk);
- size_t tmpidx;
-
- if (nid == NID_undef)
- return NULL;
+ size_t i;
- if (!ssl_cert_lookup_by_nid(nid, &tmpidx))
- return NULL;
+ for (i = 0; i < OSSL_NELEM(ssl_cert_info); i++) {
+ const SSL_CERT_LOOKUP *tmp_lu = &ssl_cert_info[i];
- if (pidx != NULL)
- *pidx = tmpidx;
+ if (EVP_PKEY_is_a(pk, OBJ_nid2sn(tmp_lu->nid))
+ || EVP_PKEY_is_a(pk, OBJ_nid2ln(tmp_lu->nid))) {
+ if (pidx != NULL)
+ *pidx = i;
+ return tmp_lu;
+ }
+ }
- return &ssl_cert_info[tmpidx];
+ return NULL;
}
const SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx)
diff --git a/ssl/ssl_cert_table.h b/ssl/ssl_cert_table.h
index 0c47241c02b8..f66c5fe39075 100644
--- a/ssl/ssl_cert_table.h
+++ b/ssl/ssl_cert_table.h
@@ -1,7 +1,7 @@
/*
* Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index a3ca5294be2e..73a821289d43 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -3,7 +3,7 @@
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -16,35 +16,12 @@
#include <openssl/engine.h>
#include <openssl/crypto.h>
#include <openssl/conf.h>
+#include <openssl/trace.h>
#include "internal/nelem.h"
#include "ssl_local.h"
#include "internal/thread_once.h"
#include "internal/cryptlib.h"
-#define SSL_ENC_DES_IDX 0
-#define SSL_ENC_3DES_IDX 1
-#define SSL_ENC_RC4_IDX 2
-#define SSL_ENC_RC2_IDX 3
-#define SSL_ENC_IDEA_IDX 4
-#define SSL_ENC_NULL_IDX 5
-#define SSL_ENC_AES128_IDX 6
-#define SSL_ENC_AES256_IDX 7
-#define SSL_ENC_CAMELLIA128_IDX 8
-#define SSL_ENC_CAMELLIA256_IDX 9
-#define SSL_ENC_GOST89_IDX 10
-#define SSL_ENC_SEED_IDX 11
-#define SSL_ENC_AES128GCM_IDX 12
-#define SSL_ENC_AES256GCM_IDX 13
-#define SSL_ENC_AES128CCM_IDX 14
-#define SSL_ENC_AES256CCM_IDX 15
-#define SSL_ENC_AES128CCM8_IDX 16
-#define SSL_ENC_AES256CCM8_IDX 17
-#define SSL_ENC_GOST8912_IDX 18
-#define SSL_ENC_CHACHA_IDX 19
-#define SSL_ENC_ARIA128GCM_IDX 20
-#define SSL_ENC_ARIA256GCM_IDX 21
-#define SSL_ENC_NUM_IDX 22
-
/* NB: make sure indices in these tables match values above */
typedef struct {
@@ -76,10 +53,10 @@ static const ssl_cipher_table ssl_cipher_table_cipher[SSL_ENC_NUM_IDX] = {
{SSL_CHACHA20POLY1305, NID_chacha20_poly1305}, /* SSL_ENC_CHACHA_IDX 19 */
{SSL_ARIA128GCM, NID_aria_128_gcm}, /* SSL_ENC_ARIA128GCM_IDX 20 */
{SSL_ARIA256GCM, NID_aria_256_gcm}, /* SSL_ENC_ARIA256GCM_IDX 21 */
+ {SSL_MAGMA, NID_magma_ctr_acpkm}, /* SSL_ENC_MAGMA_IDX */
+ {SSL_KUZNYECHIK, NID_kuznyechik_ctr_acpkm}, /* SSL_ENC_KUZNYECHIK_IDX */
};
-static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX];
-
#define SSL_COMP_NULL_IDX 0
#define SSL_COMP_ZLIB_IDX 1
#define SSL_COMP_NUM_IDX 2
@@ -90,13 +67,6 @@ static STACK_OF(SSL_COMP) *ssl_comp_methods = NULL;
static CRYPTO_ONCE ssl_load_builtin_comp_once = CRYPTO_ONCE_STATIC_INIT;
#endif
-/*
- * Constant SSL_MAX_DIGEST equal to size of digests array should be defined
- * in the ssl_local.h
- */
-
-#define SSL_MD_NUM_IDX SSL_MAX_DIGEST
-
/* NB: make sure indices in this table matches values above */
static const ssl_cipher_table ssl_cipher_table_mac[SSL_MD_NUM_IDX] = {
{SSL_MD5, NID_md5}, /* SSL_MD_MD5_IDX 0 */
@@ -110,11 +80,9 @@ static const ssl_cipher_table ssl_cipher_table_mac[SSL_MD_NUM_IDX] = {
{SSL_GOST12_512, NID_id_GostR3411_2012_512}, /* SSL_MD_GOST12_512_IDX 8 */
{0, NID_md5_sha1}, /* SSL_MD_MD5_SHA1_IDX 9 */
{0, NID_sha224}, /* SSL_MD_SHA224_IDX 10 */
- {0, NID_sha512} /* SSL_MD_SHA512_IDX 11 */
-};
-
-static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX] = {
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+ {0, NID_sha512}, /* SSL_MD_SHA512_IDX 11 */
+ {SSL_MAGMAOMAC, NID_magma_mac}, /* sSL_MD_MAGMAOMAC_IDX */
+ {SSL_KUZNYECHIKOMAC, NID_kuznyechik_mac} /* SSL_MD_KUZNYECHIKOMAC_IDX */
};
/* *INDENT-OFF* */
@@ -128,6 +96,7 @@ static const ssl_cipher_table ssl_cipher_table_kx[] = {
{SSL_kPSK, NID_kx_psk},
{SSL_kSRP, NID_kx_srp},
{SSL_kGOST, NID_kx_gost},
+ {SSL_kGOST18, NID_kx_gost18},
{SSL_kANY, NID_kx_any}
};
@@ -164,19 +133,17 @@ static int ssl_cipher_info_find(const ssl_cipher_table * table,
* is engine-provided, we'll fill it only if corresponding EVP_PKEY_METHOD is
* found
*/
-static int ssl_mac_pkey_id[SSL_MD_NUM_IDX] = {
+static const int default_mac_pkey_id[SSL_MD_NUM_IDX] = {
/* MD5, SHA, GOST94, MAC89 */
EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC, NID_undef,
/* SHA256, SHA384, GOST2012_256, MAC89-12 */
EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC, NID_undef,
/* GOST2012_512 */
EVP_PKEY_HMAC,
- /* MD5/SHA1, SHA224, SHA512 */
- NID_undef, NID_undef, NID_undef
+ /* MD5/SHA1, SHA224, SHA512, MAGMAOMAC, KUZNYECHIKOMAC */
+ NID_undef, NID_undef, NID_undef, NID_undef, NID_undef
};
-static size_t ssl_mac_secret_size[SSL_MD_NUM_IDX];
-
#define CIPHER_ADD 1
#define CIPHER_KILL 2
#define CIPHER_DEL 3
@@ -228,6 +195,7 @@ static const SSL_CIPHER cipher_aliases[] = {
{0, SSL_TXT_kDHEPSK, NULL, 0, SSL_kDHEPSK},
{0, SSL_TXT_kSRP, NULL, 0, SSL_kSRP},
{0, SSL_TXT_kGOST, NULL, 0, SSL_kGOST},
+ {0, SSL_TXT_kGOST18, NULL, 0, SSL_kGOST18},
/* server authentication aliases */
{0, SSL_TXT_aRSA, NULL, 0, 0, SSL_aRSA},
@@ -261,7 +229,8 @@ static const SSL_CIPHER cipher_aliases[] = {
{0, SSL_TXT_IDEA, NULL, 0, 0, 0, SSL_IDEA},
{0, SSL_TXT_SEED, NULL, 0, 0, 0, SSL_SEED},
{0, SSL_TXT_eNULL, NULL, 0, 0, 0, SSL_eNULL},
- {0, SSL_TXT_GOST, NULL, 0, 0, 0, SSL_eGOST2814789CNT | SSL_eGOST2814789CNT12},
+ {0, SSL_TXT_GOST, NULL, 0, 0, 0,
+ SSL_eGOST2814789CNT | SSL_eGOST2814789CNT12 | SSL_MAGMA | SSL_KUZNYECHIK},
{0, SSL_TXT_AES128, NULL, 0, 0, 0,
SSL_AES128 | SSL_AES128GCM | SSL_AES128CCM | SSL_AES128CCM8},
{0, SSL_TXT_AES256, NULL, 0, 0, 0,
@@ -275,11 +244,13 @@ static const SSL_CIPHER cipher_aliases[] = {
{0, SSL_TXT_CAMELLIA256, NULL, 0, 0, 0, SSL_CAMELLIA256},
{0, SSL_TXT_CAMELLIA, NULL, 0, 0, 0, SSL_CAMELLIA},
{0, SSL_TXT_CHACHA20, NULL, 0, 0, 0, SSL_CHACHA20},
+ {0, SSL_TXT_GOST2012_GOST8912_GOST8912, NULL, 0, 0, 0, SSL_eGOST2814789CNT12},
{0, SSL_TXT_ARIA, NULL, 0, 0, 0, SSL_ARIA},
{0, SSL_TXT_ARIA_GCM, NULL, 0, 0, 0, SSL_ARIA128GCM | SSL_ARIA256GCM},
{0, SSL_TXT_ARIA128, NULL, 0, 0, 0, SSL_ARIA128GCM},
{0, SSL_TXT_ARIA256, NULL, 0, 0, 0, SSL_ARIA256GCM},
+ {0, SSL_TXT_CBC, NULL, 0, 0, 0, SSL_CBC},
/* MAC aliases */
{0, SSL_TXT_MD5, NULL, 0, 0, 0, 0, SSL_MD5},
@@ -342,108 +313,134 @@ static int get_optional_pkey_id(const char *pkey_name)
ameth) <= 0)
pkey_id = 0;
}
- ENGINE_finish(tmpeng);
+ tls_engine_finish(tmpeng);
return pkey_id;
}
#endif
-/* masks of disabled algorithms */
-static uint32_t disabled_enc_mask;
-static uint32_t disabled_mac_mask;
-static uint32_t disabled_mkey_mask;
-static uint32_t disabled_auth_mask;
-
-int ssl_load_ciphers(void)
+int ssl_load_ciphers(SSL_CTX *ctx)
{
size_t i;
const ssl_cipher_table *t;
+ EVP_KEYEXCH *kex = NULL;
+ EVP_SIGNATURE *sig = NULL;
- disabled_enc_mask = 0;
- ssl_sort_cipher_list();
+ ctx->disabled_enc_mask = 0;
for (i = 0, t = ssl_cipher_table_cipher; i < SSL_ENC_NUM_IDX; i++, t++) {
- if (t->nid == NID_undef) {
- ssl_cipher_methods[i] = NULL;
- } else {
- const EVP_CIPHER *cipher = EVP_get_cipherbynid(t->nid);
- ssl_cipher_methods[i] = cipher;
+ if (t->nid != NID_undef) {
+ const EVP_CIPHER *cipher
+ = ssl_evp_cipher_fetch(ctx->libctx, t->nid, ctx->propq);
+
+ ctx->ssl_cipher_methods[i] = cipher;
if (cipher == NULL)
- disabled_enc_mask |= t->mask;
+ ctx->disabled_enc_mask |= t->mask;
}
}
- disabled_mac_mask = 0;
+ ctx->disabled_mac_mask = 0;
for (i = 0, t = ssl_cipher_table_mac; i < SSL_MD_NUM_IDX; i++, t++) {
- const EVP_MD *md = EVP_get_digestbynid(t->nid);
- ssl_digest_methods[i] = md;
+ const EVP_MD *md
+ = ssl_evp_md_fetch(ctx->libctx, t->nid, ctx->propq);
+
+ ctx->ssl_digest_methods[i] = md;
if (md == NULL) {
- disabled_mac_mask |= t->mask;
+ ctx->disabled_mac_mask |= t->mask;
} else {
- int tmpsize = EVP_MD_size(md);
+ int tmpsize = EVP_MD_get_size(md);
if (!ossl_assert(tmpsize >= 0))
return 0;
- ssl_mac_secret_size[i] = tmpsize;
+ ctx->ssl_mac_secret_size[i] = tmpsize;
}
}
- /* Make sure we can access MD5 and SHA1 */
- if (!ossl_assert(ssl_digest_methods[SSL_MD_MD5_IDX] != NULL))
- return 0;
- if (!ossl_assert(ssl_digest_methods[SSL_MD_SHA1_IDX] != NULL))
- return 0;
- disabled_mkey_mask = 0;
- disabled_auth_mask = 0;
+ ctx->disabled_mkey_mask = 0;
+ ctx->disabled_auth_mask = 0;
+
+ /*
+ * We ignore any errors from the fetches below. They are expected to fail
+ * if theose algorithms are not available.
+ */
+ ERR_set_mark();
+ sig = EVP_SIGNATURE_fetch(ctx->libctx, "DSA", ctx->propq);
+ if (sig == NULL)
+ ctx->disabled_auth_mask |= SSL_aDSS;
+ else
+ EVP_SIGNATURE_free(sig);
+ kex = EVP_KEYEXCH_fetch(ctx->libctx, "DH", ctx->propq);
+ if (kex == NULL)
+ ctx->disabled_mkey_mask |= SSL_kDHE | SSL_kDHEPSK;
+ else
+ EVP_KEYEXCH_free(kex);
+ kex = EVP_KEYEXCH_fetch(ctx->libctx, "ECDH", ctx->propq);
+ if (kex == NULL)
+ ctx->disabled_mkey_mask |= SSL_kECDHE | SSL_kECDHEPSK;
+ else
+ EVP_KEYEXCH_free(kex);
+ sig = EVP_SIGNATURE_fetch(ctx->libctx, "ECDSA", ctx->propq);
+ if (sig == NULL)
+ ctx->disabled_auth_mask |= SSL_aECDSA;
+ else
+ EVP_SIGNATURE_free(sig);
+ ERR_pop_to_mark();
-#ifdef OPENSSL_NO_RSA
- disabled_mkey_mask |= SSL_kRSA | SSL_kRSAPSK;
- disabled_auth_mask |= SSL_aRSA;
-#endif
-#ifdef OPENSSL_NO_DSA
- disabled_auth_mask |= SSL_aDSS;
-#endif
-#ifdef OPENSSL_NO_DH
- disabled_mkey_mask |= SSL_kDHE | SSL_kDHEPSK;
-#endif
-#ifdef OPENSSL_NO_EC
- disabled_mkey_mask |= SSL_kECDHE | SSL_kECDHEPSK;
- disabled_auth_mask |= SSL_aECDSA;
-#endif
#ifdef OPENSSL_NO_PSK
- disabled_mkey_mask |= SSL_PSK;
- disabled_auth_mask |= SSL_aPSK;
+ ctx->disabled_mkey_mask |= SSL_PSK;
+ ctx->disabled_auth_mask |= SSL_aPSK;
#endif
#ifdef OPENSSL_NO_SRP
- disabled_mkey_mask |= SSL_kSRP;
+ ctx->disabled_mkey_mask |= SSL_kSRP;
#endif
/*
* Check for presence of GOST 34.10 algorithms, and if they are not
* present, disable appropriate auth and key exchange
*/
- ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX] = get_optional_pkey_id("gost-mac");
- if (ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX])
- ssl_mac_secret_size[SSL_MD_GOST89MAC_IDX] = 32;
+ memcpy(ctx->ssl_mac_pkey_id, default_mac_pkey_id,
+ sizeof(ctx->ssl_mac_pkey_id));
+
+ ctx->ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX] =
+ get_optional_pkey_id(SN_id_Gost28147_89_MAC);
+ if (ctx->ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX])
+ ctx->ssl_mac_secret_size[SSL_MD_GOST89MAC_IDX] = 32;
+ else
+ ctx->disabled_mac_mask |= SSL_GOST89MAC;
+
+ ctx->ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX] =
+ get_optional_pkey_id(SN_gost_mac_12);
+ if (ctx->ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX])
+ ctx->ssl_mac_secret_size[SSL_MD_GOST89MAC12_IDX] = 32;
else
- disabled_mac_mask |= SSL_GOST89MAC;
+ ctx->disabled_mac_mask |= SSL_GOST89MAC12;
- ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX] =
- get_optional_pkey_id("gost-mac-12");
- if (ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX])
- ssl_mac_secret_size[SSL_MD_GOST89MAC12_IDX] = 32;
+ ctx->ssl_mac_pkey_id[SSL_MD_MAGMAOMAC_IDX] =
+ get_optional_pkey_id(SN_magma_mac);
+ if (ctx->ssl_mac_pkey_id[SSL_MD_MAGMAOMAC_IDX])
+ ctx->ssl_mac_secret_size[SSL_MD_MAGMAOMAC_IDX] = 32;
else
- disabled_mac_mask |= SSL_GOST89MAC12;
-
- if (!get_optional_pkey_id("gost2001"))
- disabled_auth_mask |= SSL_aGOST01 | SSL_aGOST12;
- if (!get_optional_pkey_id("gost2012_256"))
- disabled_auth_mask |= SSL_aGOST12;
- if (!get_optional_pkey_id("gost2012_512"))
- disabled_auth_mask |= SSL_aGOST12;
+ ctx->disabled_mac_mask |= SSL_MAGMAOMAC;
+
+ ctx->ssl_mac_pkey_id[SSL_MD_KUZNYECHIKOMAC_IDX] =
+ get_optional_pkey_id(SN_kuznyechik_mac);
+ if (ctx->ssl_mac_pkey_id[SSL_MD_KUZNYECHIKOMAC_IDX])
+ ctx->ssl_mac_secret_size[SSL_MD_KUZNYECHIKOMAC_IDX] = 32;
+ else
+ ctx->disabled_mac_mask |= SSL_KUZNYECHIKOMAC;
+
+ if (!get_optional_pkey_id(SN_id_GostR3410_2001))
+ ctx->disabled_auth_mask |= SSL_aGOST01 | SSL_aGOST12;
+ if (!get_optional_pkey_id(SN_id_GostR3410_2012_256))
+ ctx->disabled_auth_mask |= SSL_aGOST12;
+ if (!get_optional_pkey_id(SN_id_GostR3410_2012_512))
+ ctx->disabled_auth_mask |= SSL_aGOST12;
/*
* Disable GOST key exchange if no GOST signature algs are available *
*/
- if ((disabled_auth_mask & (SSL_aGOST01 | SSL_aGOST12)) ==
+ if ((ctx->disabled_auth_mask & (SSL_aGOST01 | SSL_aGOST12)) ==
(SSL_aGOST01 | SSL_aGOST12))
- disabled_mkey_mask |= SSL_kGOST;
+ ctx->disabled_mkey_mask |= SSL_kGOST;
+
+ if ((ctx->disabled_auth_mask & SSL_aGOST12) == SSL_aGOST12)
+ ctx->disabled_mkey_mask |= SSL_kGOST18;
return 1;
}
@@ -460,7 +457,6 @@ DEFINE_RUN_ONCE_STATIC(do_load_builtin_compressions)
SSL_COMP *comp = NULL;
COMP_METHOD *method = COMP_zlib();
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
ssl_comp_methods = sk_SSL_COMP_new(sk_comp_cmp);
if (COMP_get_type(method) != NID_undef && ssl_comp_methods != NULL) {
@@ -473,7 +469,6 @@ DEFINE_RUN_ONCE_STATIC(do_load_builtin_compressions)
sk_SSL_COMP_sort(ssl_comp_methods);
}
}
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
return 1;
}
@@ -483,9 +478,39 @@ static int load_builtin_compressions(void)
}
#endif
-int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
- const EVP_MD **md, int *mac_pkey_type,
- size_t *mac_secret_size, SSL_COMP **comp, int use_etm)
+int ssl_cipher_get_evp_cipher(SSL_CTX *ctx, const SSL_CIPHER *sslc,
+ const EVP_CIPHER **enc)
+{
+ int i = ssl_cipher_info_lookup(ssl_cipher_table_cipher, sslc->algorithm_enc);
+
+ if (i == -1) {
+ *enc = NULL;
+ } else {
+ if (i == SSL_ENC_NULL_IDX) {
+ /*
+ * We assume we don't care about this coming from an ENGINE so
+ * just do a normal EVP_CIPHER_fetch instead of
+ * ssl_evp_cipher_fetch()
+ */
+ *enc = EVP_CIPHER_fetch(ctx->libctx, "NULL", ctx->propq);
+ if (*enc == NULL)
+ return 0;
+ } else {
+ const EVP_CIPHER *cipher = ctx->ssl_cipher_methods[i];
+
+ if (cipher == NULL
+ || !ssl_evp_cipher_up_ref(cipher))
+ return 0;
+ *enc = ctx->ssl_cipher_methods[i];
+ }
+ }
+ return 1;
+}
+
+int ssl_cipher_get_evp(SSL_CTX *ctx, const SSL_SESSION *s,
+ const EVP_CIPHER **enc, const EVP_MD **md,
+ int *mac_pkey_type, size_t *mac_secret_size,
+ SSL_COMP **comp, int use_etm)
{
int i;
const SSL_CIPHER *c;
@@ -507,7 +532,8 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
ctmp.id = s->compress_meth;
if (ssl_comp_methods != NULL) {
i = sk_SSL_COMP_find(ssl_comp_methods, &ctmp);
- *comp = sk_SSL_COMP_value(ssl_comp_methods, i);
+ if (i >= 0)
+ *comp = sk_SSL_COMP_value(ssl_comp_methods, i);
}
/* If were only interested in comp then return success */
if ((enc == NULL) && (md == NULL))
@@ -517,16 +543,8 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
if ((enc == NULL) || (md == NULL))
return 0;
- i = ssl_cipher_info_lookup(ssl_cipher_table_cipher, c->algorithm_enc);
-
- if (i == -1) {
- *enc = NULL;
- } else {
- if (i == SSL_ENC_NULL_IDX)
- *enc = EVP_enc_null();
- else
- *enc = ssl_cipher_methods[i];
- }
+ if (!ssl_cipher_get_evp_cipher(ctx, c, enc))
+ return 0;
i = ssl_cipher_info_lookup(ssl_cipher_table_mac, c->algorithm_mac);
if (i == -1) {
@@ -538,67 +556,84 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
if (c->algorithm_mac == SSL_AEAD)
mac_pkey_type = NULL;
} else {
- *md = ssl_digest_methods[i];
+ const EVP_MD *digest = ctx->ssl_digest_methods[i];
+
+ if (digest == NULL
+ || !ssl_evp_md_up_ref(digest)) {
+ ssl_evp_cipher_free(*enc);
+ return 0;
+ }
+ *md = digest;
if (mac_pkey_type != NULL)
- *mac_pkey_type = ssl_mac_pkey_id[i];
+ *mac_pkey_type = ctx->ssl_mac_pkey_id[i];
if (mac_secret_size != NULL)
- *mac_secret_size = ssl_mac_secret_size[i];
+ *mac_secret_size = ctx->ssl_mac_secret_size[i];
}
- if ((*enc != NULL) &&
- (*md != NULL || (EVP_CIPHER_flags(*enc) & EVP_CIPH_FLAG_AEAD_CIPHER))
+ if ((*enc != NULL)
+ && (*md != NULL
+ || (EVP_CIPHER_get_flags(*enc) & EVP_CIPH_FLAG_AEAD_CIPHER))
&& (!mac_pkey_type || *mac_pkey_type != NID_undef)) {
- const EVP_CIPHER *evp;
+ const EVP_CIPHER *evp = NULL;
- if (use_etm)
+ if (use_etm
+ || s->ssl_version >> 8 != TLS1_VERSION_MAJOR
+ || s->ssl_version < TLS1_VERSION)
return 1;
- if (s->ssl_version >> 8 != TLS1_VERSION_MAJOR ||
- s->ssl_version < TLS1_VERSION)
- return 1;
-
- if (c->algorithm_enc == SSL_RC4 &&
- c->algorithm_mac == SSL_MD5 &&
- (evp = EVP_get_cipherbyname("RC4-HMAC-MD5")))
- *enc = evp, *md = NULL;
- else if (c->algorithm_enc == SSL_AES128 &&
- c->algorithm_mac == SSL_SHA1 &&
- (evp = EVP_get_cipherbyname("AES-128-CBC-HMAC-SHA1")))
- *enc = evp, *md = NULL;
- else if (c->algorithm_enc == SSL_AES256 &&
- c->algorithm_mac == SSL_SHA1 &&
- (evp = EVP_get_cipherbyname("AES-256-CBC-HMAC-SHA1")))
- *enc = evp, *md = NULL;
- else if (c->algorithm_enc == SSL_AES128 &&
- c->algorithm_mac == SSL_SHA256 &&
- (evp = EVP_get_cipherbyname("AES-128-CBC-HMAC-SHA256")))
- *enc = evp, *md = NULL;
- else if (c->algorithm_enc == SSL_AES256 &&
- c->algorithm_mac == SSL_SHA256 &&
- (evp = EVP_get_cipherbyname("AES-256-CBC-HMAC-SHA256")))
- *enc = evp, *md = NULL;
+ if (c->algorithm_enc == SSL_RC4
+ && c->algorithm_mac == SSL_MD5)
+ evp = ssl_evp_cipher_fetch(ctx->libctx, NID_rc4_hmac_md5,
+ ctx->propq);
+ else if (c->algorithm_enc == SSL_AES128
+ && c->algorithm_mac == SSL_SHA1)
+ evp = ssl_evp_cipher_fetch(ctx->libctx,
+ NID_aes_128_cbc_hmac_sha1,
+ ctx->propq);
+ else if (c->algorithm_enc == SSL_AES256
+ && c->algorithm_mac == SSL_SHA1)
+ evp = ssl_evp_cipher_fetch(ctx->libctx,
+ NID_aes_256_cbc_hmac_sha1,
+ ctx->propq);
+ else if (c->algorithm_enc == SSL_AES128
+ && c->algorithm_mac == SSL_SHA256)
+ evp = ssl_evp_cipher_fetch(ctx->libctx,
+ NID_aes_128_cbc_hmac_sha256,
+ ctx->propq);
+ else if (c->algorithm_enc == SSL_AES256
+ && c->algorithm_mac == SSL_SHA256)
+ evp = ssl_evp_cipher_fetch(ctx->libctx,
+ NID_aes_256_cbc_hmac_sha256,
+ ctx->propq);
+
+ if (evp != NULL) {
+ ssl_evp_cipher_free(*enc);
+ ssl_evp_md_free(*md);
+ *enc = evp;
+ *md = NULL;
+ }
return 1;
- } else {
- return 0;
}
+
+ return 0;
}
-const EVP_MD *ssl_md(int idx)
+const EVP_MD *ssl_md(SSL_CTX *ctx, int idx)
{
idx &= SSL_HANDSHAKE_MAC_MASK;
if (idx < 0 || idx >= SSL_MD_NUM_IDX)
return NULL;
- return ssl_digest_methods[idx];
+ return ctx->ssl_digest_methods[idx];
}
const EVP_MD *ssl_handshake_md(SSL *s)
{
- return ssl_md(ssl_get_algorithm2(s));
+ return ssl_md(s->ctx, ssl_get_algorithm2(s));
}
const EVP_MD *ssl_prf_md(SSL *s)
{
- return ssl_md(ssl_get_algorithm2(s) >> TLS1_PRF_DGST_SHIFT);
+ return ssl_md(s->ctx, ssl_get_algorithm2(s) >> TLS1_PRF_DGST_SHIFT);
}
#define ITEM_SEP(a) \
@@ -781,12 +816,12 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
const SSL_CIPHER *cp;
int reverse = 0;
-#ifdef CIPHER_DEBUG
- fprintf(stderr,
- "Applying rule %d with %08x/%08x/%08x/%08x/%08x %08x (%d)\n",
- rule, alg_mkey, alg_auth, alg_enc, alg_mac, min_tls,
- algo_strength, strength_bits);
-#endif
+ OSSL_TRACE_BEGIN(TLS_CIPHER){
+ BIO_printf(trc_out,
+ "Applying rule %d with %08x/%08x/%08x/%08x/%08x %08x (%d)\n",
+ rule, alg_mkey, alg_auth, alg_enc, alg_mac, min_tls,
+ algo_strength, strength_bits);
+ }
if (rule == CIPHER_DEL || rule == CIPHER_BUMP)
reverse = 1; /* needed to maintain sorting between currently
@@ -825,13 +860,14 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
if (strength_bits != cp->strength_bits)
continue;
} else {
-#ifdef CIPHER_DEBUG
- fprintf(stderr,
- "\nName: %s:\nAlgo = %08x/%08x/%08x/%08x/%08x Algo_strength = %08x\n",
- cp->name, cp->algorithm_mkey, cp->algorithm_auth,
- cp->algorithm_enc, cp->algorithm_mac, cp->min_tls,
- cp->algo_strength);
-#endif
+ if (trc_out != NULL) {
+ BIO_printf(trc_out,
+ "\nName: %s:"
+ "\nAlgo = %08x/%08x/%08x/%08x/%08x Algo_strength = %08x\n",
+ cp->name, cp->algorithm_mkey, cp->algorithm_auth,
+ cp->algorithm_enc, cp->algorithm_mac, cp->min_tls,
+ cp->algo_strength);
+ }
if (cipher_id != 0 && (cipher_id != cp->id))
continue;
if (alg_mkey && !(alg_mkey & cp->algorithm_mkey))
@@ -852,9 +888,8 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
continue;
}
-#ifdef CIPHER_DEBUG
- fprintf(stderr, "Action = %d\n", rule);
-#endif
+ if (trc_out != NULL)
+ BIO_printf(trc_out, "Action = %d\n", rule);
/* add the cipher if it has not been added yet. */
if (rule == CIPHER_ADD) {
@@ -904,6 +939,8 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
*head_p = head;
*tail_p = tail;
+
+ OSSL_TRACE_END(TLS_CIPHER);
}
static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p,
@@ -928,7 +965,7 @@ static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p,
number_uses = OPENSSL_zalloc(sizeof(int) * (max_strength_bits + 1));
if (number_uses == NULL) {
- SSLerr(SSL_F_SSL_CIPHER_STRENGTH_SORT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -1025,7 +1062,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
* it is no command or separator nor
* alphanumeric, so we call this an error.
*/
- SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND);
+ ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_COMMAND);
return 0;
}
@@ -1181,14 +1218,13 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
} else if (buflen == 10 && strncmp(buf, "SECLEVEL=", 9) == 0) {
int level = buf[9] - '0';
if (level < 0 || level > 5) {
- SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
- SSL_R_INVALID_COMMAND);
+ ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_COMMAND);
} else {
c->sec_level = level;
ok = 1;
}
} else {
- SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND);
+ ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_COMMAND);
}
if (ok == 0)
retval = 0;
@@ -1216,7 +1252,6 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
return retval;
}
-#ifndef OPENSSL_NO_EC
static int check_suiteb_cipher_list(const SSL_METHOD *meth, CERT *c,
const char **prule_str)
{
@@ -1244,11 +1279,10 @@ static int check_suiteb_cipher_list(const SSL_METHOD *meth, CERT *c,
/* Check version: if TLS 1.2 ciphers allowed we can use Suite B */
if (!(meth->ssl3_enc->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS)) {
- SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST,
- SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE);
return 0;
}
-# ifndef OPENSSL_NO_EC
+
switch (suiteb_flags) {
case SSL_CERT_FLAG_SUITEB_128_LOS:
if (suiteb_comb2)
@@ -1265,12 +1299,7 @@ static int check_suiteb_cipher_list(const SSL_METHOD *meth, CERT *c,
break;
}
return 1;
-# else
- SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST, SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE);
- return 0;
-# endif
}
-#endif
static int ciphersuite_cb(const char *elem, int len, void *arg)
{
@@ -1279,22 +1308,20 @@ static int ciphersuite_cb(const char *elem, int len, void *arg)
/* Arbitrary sized temp buffer for the cipher name. Should be big enough */
char name[80];
- if (len > (int)(sizeof(name) - 1)) {
- SSLerr(SSL_F_CIPHERSUITE_CB, SSL_R_NO_CIPHER_MATCH);
- return 0;
- }
+ if (len > (int)(sizeof(name) - 1))
+ /* Anyway return 1 so we can parse rest of the list */
+ return 1;
memcpy(name, elem, len);
name[len] = '\0';
cipher = ssl3_get_cipher_by_std_name(name);
- if (cipher == NULL) {
- SSLerr(SSL_F_CIPHERSUITE_CB, SSL_R_NO_CIPHER_MATCH);
- return 0;
- }
+ if (cipher == NULL)
+ /* Ciphersuite not found but return 1 to parse rest of the list */
+ return 1;
if (!sk_SSL_CIPHER_push(ciphersuites, cipher)) {
- SSLerr(SSL_F_CIPHERSUITE_CB, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -1310,7 +1337,9 @@ static __owur int set_ciphersuites(STACK_OF(SSL_CIPHER) **currciphers, const cha
/* Parse the list. We explicitly allow an empty list */
if (*str != '\0'
- && !CONF_parse_list(str, ':', 1, ciphersuite_cb, newciphers)) {
+ && (CONF_parse_list(str, ':', 1, ciphersuite_cb, newciphers) <= 0
+ || sk_SSL_CIPHER_num(newciphers) == 0)) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_CIPHER_MATCH);
sk_SSL_CIPHER_free(newciphers);
return 0;
}
@@ -1338,7 +1367,8 @@ static int update_cipher_list_by_id(STACK_OF(SSL_CIPHER) **cipher_list_by_id,
return 1;
}
-static int update_cipher_list(STACK_OF(SSL_CIPHER) **cipher_list,
+static int update_cipher_list(SSL_CTX *ctx,
+ STACK_OF(SSL_CIPHER) **cipher_list,
STACK_OF(SSL_CIPHER) **cipher_list_by_id,
STACK_OF(SSL_CIPHER) *tls13_ciphersuites)
{
@@ -1355,15 +1385,25 @@ static int update_cipher_list(STACK_OF(SSL_CIPHER) **cipher_list,
while (sk_SSL_CIPHER_num(tmp_cipher_list) > 0
&& sk_SSL_CIPHER_value(tmp_cipher_list, 0)->min_tls
== TLS1_3_VERSION)
- sk_SSL_CIPHER_delete(tmp_cipher_list, 0);
+ (void)sk_SSL_CIPHER_delete(tmp_cipher_list, 0);
/* Insert the new TLSv1.3 ciphersuites */
- for (i = 0; i < sk_SSL_CIPHER_num(tls13_ciphersuites); i++)
- sk_SSL_CIPHER_insert(tmp_cipher_list,
- sk_SSL_CIPHER_value(tls13_ciphersuites, i), i);
+ for (i = sk_SSL_CIPHER_num(tls13_ciphersuites) - 1; i >= 0; i--) {
+ const SSL_CIPHER *sslc = sk_SSL_CIPHER_value(tls13_ciphersuites, i);
+
+ /* Don't include any TLSv1.3 ciphersuites that are disabled */
+ if ((sslc->algorithm_enc & ctx->disabled_enc_mask) == 0
+ && (ssl_cipher_table_mac[sslc->algorithm2
+ & SSL_HANDSHAKE_MAC_MASK].mask
+ & ctx->disabled_mac_mask) == 0) {
+ sk_SSL_CIPHER_unshift(tmp_cipher_list, sslc);
+ }
+ }
- if (!update_cipher_list_by_id(cipher_list_by_id, tmp_cipher_list))
+ if (!update_cipher_list_by_id(cipher_list_by_id, tmp_cipher_list)) {
+ sk_SSL_CIPHER_free(tmp_cipher_list);
return 0;
+ }
sk_SSL_CIPHER_free(*cipher_list);
*cipher_list = tmp_cipher_list;
@@ -1376,7 +1416,7 @@ int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str)
int ret = set_ciphersuites(&(ctx->tls13_ciphersuites), str);
if (ret && ctx->cipher_list != NULL)
- return update_cipher_list(&ctx->cipher_list, &ctx->cipher_list_by_id,
+ return update_cipher_list(ctx, &ctx->cipher_list, &ctx->cipher_list_by_id,
ctx->tls13_ciphersuites);
return ret;
@@ -1392,13 +1432,13 @@ int SSL_set_ciphersuites(SSL *s, const char *str)
s->cipher_list = sk_SSL_CIPHER_dup(cipher_list);
}
if (ret && s->cipher_list != NULL)
- return update_cipher_list(&s->cipher_list, &s->cipher_list_by_id,
+ return update_cipher_list(s->ctx, &s->cipher_list, &s->cipher_list_by_id,
s->tls13_ciphersuites);
return ret;
}
-STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
+STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(SSL_CTX *ctx,
STACK_OF(SSL_CIPHER) *tls13_ciphersuites,
STACK_OF(SSL_CIPHER) **cipher_list,
STACK_OF(SSL_CIPHER) **cipher_list_by_id,
@@ -1411,26 +1451,26 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
const char *rule_p;
CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
const SSL_CIPHER **ca_list = NULL;
+ const SSL_METHOD *ssl_method = ctx->method;
/*
* Return with error if nothing to do.
*/
if (rule_str == NULL || cipher_list == NULL || cipher_list_by_id == NULL)
return NULL;
-#ifndef OPENSSL_NO_EC
+
if (!check_suiteb_cipher_list(ssl_method, c, &rule_str))
return NULL;
-#endif
/*
* To reduce the work to do we only want to process the compiled
* in algorithms, so we first get the mask of disabled ciphers.
*/
- disabled_mkey = disabled_mkey_mask;
- disabled_auth = disabled_auth_mask;
- disabled_enc = disabled_enc_mask;
- disabled_mac = disabled_mac_mask;
+ disabled_mkey = ctx->disabled_mkey_mask;
+ disabled_auth = ctx->disabled_auth_mask;
+ disabled_enc = ctx->disabled_enc_mask;
+ disabled_mac = ctx->disabled_mac_mask;
/*
* Now we have to collect the available ciphers from the compiled
@@ -1441,7 +1481,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
co_list = OPENSSL_malloc(sizeof(*co_list) * num_of_ciphers);
if (co_list == NULL) {
- SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return NULL; /* Failure */
}
@@ -1514,7 +1554,6 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
/*
* Partially overrule strength sort to prefer TLS 1.2 ciphers/PRFs.
- * TODO(openssl-team): is there an easier way to accomplish all this?
*/
ssl_cipher_apply_rule(0, 0, 0, 0, 0, TLS1_2_VERSION, 0, CIPHER_BUMP, -1,
&head, &tail);
@@ -1555,7 +1594,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
ca_list = OPENSSL_malloc(sizeof(*ca_list) * num_of_alias_max);
if (ca_list == NULL) {
OPENSSL_free(co_list);
- SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return NULL; /* Failure */
}
ssl_cipher_collect_aliases(ca_list, num_of_group_aliases,
@@ -1569,14 +1608,14 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
ok = 1;
rule_p = rule_str;
if (strncmp(rule_str, "DEFAULT", 7) == 0) {
- ok = ssl_cipher_process_rulestr(SSL_DEFAULT_CIPHER_LIST,
+ ok = ssl_cipher_process_rulestr(OSSL_default_cipher_list(),
&head, &tail, ca_list, c);
rule_p += 7;
if (*rule_p == ':')
rule_p++;
}
- if (ok && (strlen(rule_p) > 0))
+ if (ok && (rule_p[0] != '\0'))
ok = ssl_cipher_process_rulestr(rule_p, &head, &tail, ca_list, c);
OPENSSL_free(ca_list); /* Not needed anymore */
@@ -1597,14 +1636,28 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
/* Add TLSv1.3 ciphers first - we always prefer those if possible */
for (i = 0; i < sk_SSL_CIPHER_num(tls13_ciphersuites); i++) {
- if (!sk_SSL_CIPHER_push(cipherstack,
- sk_SSL_CIPHER_value(tls13_ciphersuites, i))) {
+ const SSL_CIPHER *sslc = sk_SSL_CIPHER_value(tls13_ciphersuites, i);
+
+ /* Don't include any TLSv1.3 ciphers that are disabled */
+ if ((sslc->algorithm_enc & disabled_enc) != 0
+ || (ssl_cipher_table_mac[sslc->algorithm2
+ & SSL_HANDSHAKE_MAC_MASK].mask
+ & ctx->disabled_mac_mask) != 0) {
+ sk_SSL_CIPHER_delete(tls13_ciphersuites, i);
+ i--;
+ continue;
+ }
+
+ if (!sk_SSL_CIPHER_push(cipherstack, sslc)) {
OPENSSL_free(co_list);
sk_SSL_CIPHER_free(cipherstack);
return NULL;
}
}
+ OSSL_TRACE_BEGIN(TLS_CIPHER) {
+ BIO_printf(trc_out, "cipher selection:\n");
+ }
/*
* The cipher selection for the list is done. The ciphers are added
* to the resulting precedence to the STACK_OF(SSL_CIPHER).
@@ -1614,14 +1667,15 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
if (!sk_SSL_CIPHER_push(cipherstack, curr->cipher)) {
OPENSSL_free(co_list);
sk_SSL_CIPHER_free(cipherstack);
+ OSSL_TRACE_CANCEL(TLS_CIPHER);
return NULL;
}
-#ifdef CIPHER_DEBUG
- fprintf(stderr, "<%s>\n", curr->cipher->name);
-#endif
+ if (trc_out != NULL)
+ BIO_printf(trc_out, "<%s>\n", curr->cipher->name);
}
}
OPENSSL_free(co_list); /* Not needed any longer */
+ OSSL_TRACE_END(TLS_CIPHER);
if (!update_cipher_list_by_id(cipher_list_by_id, cipherstack)) {
sk_SSL_CIPHER_free(cipherstack);
@@ -1638,12 +1692,12 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
const char *ver;
const char *kx, *au, *enc, *mac;
uint32_t alg_mkey, alg_auth, alg_enc, alg_mac;
- static const char *format = "%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s\n";
+ static const char *format = "%-30s %-7s Kx=%-8s Au=%-5s Enc=%-22s Mac=%-4s\n";
if (buf == NULL) {
len = 128;
if ((buf = OPENSSL_malloc(len)) == NULL) {
- SSLerr(SSL_F_SSL_CIPHER_DESCRIPTION, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else if (len < 128) {
@@ -1685,6 +1739,9 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
case SSL_kGOST:
kx = "GOST";
break;
+ case SSL_kGOST18:
+ kx = "GOST18";
+ break;
case SSL_kANY:
kx = "any";
break;
@@ -1788,6 +1845,12 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
case SSL_eGOST2814789CNT12:
enc = "GOST89(256)";
break;
+ case SSL_MAGMA:
+ enc = "MAGMA";
+ break;
+ case SSL_KUZNYECHIK:
+ enc = "KUZNYECHIK";
+ break;
case SSL_CHACHA20POLY1305:
enc = "CHACHA20/POLY1305(256)";
break;
@@ -1973,16 +2036,13 @@ int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm)
* 193 to 255: reserved for private use
*/
if (id < 193 || id > 255) {
- SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,
- SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE);
return 1;
}
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
comp = OPENSSL_malloc(sizeof(*comp));
if (comp == NULL) {
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
- SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 1;
}
@@ -1991,18 +2051,14 @@ int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm)
load_builtin_compressions();
if (ssl_comp_methods && sk_SSL_COMP_find(ssl_comp_methods, comp) >= 0) {
OPENSSL_free(comp);
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
- SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,
- SSL_R_DUPLICATE_COMPRESSION_ID);
+ ERR_raise(ERR_LIB_SSL, SSL_R_DUPLICATE_COMPRESSION_ID);
return 1;
}
if (ssl_comp_methods == NULL || !sk_SSL_COMP_push(ssl_comp_methods, comp)) {
OPENSSL_free(comp);
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
- SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 1;
}
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
return 0;
}
#endif
@@ -2093,7 +2149,7 @@ const EVP_MD *SSL_CIPHER_get_handshake_digest(const SSL_CIPHER *c)
if (idx < 0 || idx >= SSL_MD_NUM_IDX)
return NULL;
- return ssl_digest_methods[idx];
+ return EVP_get_digestbynid(ssl_cipher_table_mac[idx].nid);
}
int SSL_CIPHER_is_aead(const SSL_CIPHER *c)
@@ -2128,7 +2184,7 @@ int ssl_cipher_get_overhead(const SSL_CIPHER *c, size_t *mac_overhead,
if (e_md == NULL)
return 0;
- mac = EVP_MD_size(e_md);
+ mac = EVP_MD_get_size(e_md);
if (c->algorithm_enc != SSL_eNULL) {
int cipher_nid = SSL_CIPHER_get_cipher_nid(c);
const EVP_CIPHER *e_ciph = EVP_get_cipherbynid(cipher_nid);
@@ -2136,12 +2192,12 @@ int ssl_cipher_get_overhead(const SSL_CIPHER *c, size_t *mac_overhead,
/* If it wasn't AEAD or SSL_eNULL, we expect it to be a
known CBC cipher. */
if (e_ciph == NULL ||
- EVP_CIPHER_mode(e_ciph) != EVP_CIPH_CBC_MODE)
+ EVP_CIPHER_get_mode(e_ciph) != EVP_CIPH_CBC_MODE)
return 0;
in = 1; /* padding length byte */
- out = EVP_CIPHER_iv_length(e_ciph);
- blk = EVP_CIPHER_block_size(e_ciph);
+ out = EVP_CIPHER_get_iv_length(e_ciph);
+ blk = EVP_CIPHER_get_block_size(e_ciph);
}
}
@@ -2153,11 +2209,33 @@ int ssl_cipher_get_overhead(const SSL_CIPHER *c, size_t *mac_overhead,
return 1;
}
-int ssl_cert_is_disabled(size_t idx)
+int ssl_cert_is_disabled(SSL_CTX *ctx, size_t idx)
{
const SSL_CERT_LOOKUP *cl = ssl_cert_lookup_by_idx(idx);
- if (cl == NULL || (cl->amask & disabled_auth_mask) != 0)
+ if (cl == NULL || (cl->amask & ctx->disabled_auth_mask) != 0)
return 1;
return 0;
}
+
+/*
+ * Default list of TLSv1.2 (and earlier) ciphers
+ * SSL_DEFAULT_CIPHER_LIST deprecated in 3.0.0
+ * Update both macro and function simultaneously
+ */
+const char *OSSL_default_cipher_list(void)
+{
+ return "ALL:!COMPLEMENTOFDEFAULT:!eNULL";
+}
+
+/*
+ * Default list of TLSv1.3 (and later) ciphers
+ * TLS_DEFAULT_CIPHERSUITES deprecated in 3.0.0
+ * Update both macro and function simultaneously
+ */
+const char *OSSL_default_ciphersuites(void)
+{
+ return "TLS_AES_256_GCM_SHA384:"
+ "TLS_CHACHA20_POLY1305_SHA256:"
+ "TLS_AES_128_GCM_SHA256";
+}
diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c
index 0a3fef7c8c14..5146cedb96ec 100644
--- a/ssl/ssl_conf.c
+++ b/ssl/ssl_conf.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2012-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,7 +11,8 @@
#include "ssl_local.h"
#include <openssl/conf.h>
#include <openssl/objects.h>
-#include <openssl/dh.h>
+#include <openssl/decoder.h>
+#include <openssl/core_dispatch.h>
#include "internal/nelem.h"
/*
@@ -23,12 +24,12 @@ typedef struct {
const char *name;
int namelen;
unsigned int name_flags;
- unsigned long option_value;
+ uint64_t option_value;
} ssl_flag_tbl;
/* Switch table: use for single command line switches like no_tls2 */
typedef struct {
- unsigned long option_value;
+ uint64_t option_value;
unsigned int name_flags;
} ssl_switch_tbl;
@@ -83,7 +84,7 @@ struct ssl_conf_ctx_st {
SSL_CTX *ctx;
SSL *ssl;
/* Pointer to SSL or SSL_CTX options field or NULL if none */
- uint32_t *poptions;
+ uint64_t *poptions;
/* Certificate filenames for each type */
char *cert_filename[SSL_PKEY_NUM];
/* Pointer to SSL or SSL_CTX cert_flags or NULL if none */
@@ -103,9 +104,10 @@ struct ssl_conf_ctx_st {
};
static void ssl_set_option(SSL_CONF_CTX *cctx, unsigned int name_flags,
- unsigned long option_value, int onoff)
+ uint64_t option_value, int onoff)
{
uint32_t *pflags;
+
if (cctx->poptions == NULL)
return;
if (name_flags & SSL_TFLAG_INV)
@@ -121,8 +123,11 @@ static void ssl_set_option(SSL_CONF_CTX *cctx, unsigned int name_flags,
break;
case SSL_TFLAG_OPTION:
- pflags = cctx->poptions;
- break;
+ if (onoff)
+ *cctx->poptions |= option_value;
+ else
+ *cctx->poptions &= ~option_value;
+ return;
default:
return;
@@ -143,7 +148,8 @@ static int ssl_match_option(SSL_CONF_CTX *cctx, const ssl_flag_tbl *tbl,
if (namelen == -1) {
if (strcmp(tbl->name, name))
return 0;
- } else if (tbl->namelen != namelen || strncasecmp(tbl->name, name, namelen))
+ } else if (tbl->namelen != namelen
+ || OPENSSL_strncasecmp(tbl->name, name, namelen))
return 0;
ssl_set_option(cctx, tbl->name_flags, tbl->option_value, onoff);
return 1;
@@ -220,40 +226,32 @@ static int cmd_Curves(SSL_CONF_CTX *cctx, const char *value)
return cmd_Groups(cctx, value);
}
-#ifndef OPENSSL_NO_EC
/* ECDH temporary parameters */
static int cmd_ECDHParameters(SSL_CONF_CTX *cctx, const char *value)
{
int rv = 1;
- EC_KEY *ecdh;
- int nid;
/* Ignore values supported by 1.0.2 for the automatic selection */
if ((cctx->flags & SSL_CONF_FLAG_FILE)
- && (strcasecmp(value, "+automatic") == 0
- || strcasecmp(value, "automatic") == 0))
+ && (OPENSSL_strcasecmp(value, "+automatic") == 0
+ || OPENSSL_strcasecmp(value, "automatic") == 0))
return 1;
if ((cctx->flags & SSL_CONF_FLAG_CMDLINE) &&
strcmp(value, "auto") == 0)
return 1;
- nid = EC_curve_nist2nid(value);
- if (nid == NID_undef)
- nid = OBJ_sn2nid(value);
- if (nid == 0)
- return 0;
- ecdh = EC_KEY_new_by_curve_name(nid);
- if (!ecdh)
+ /* ECDHParameters accepts a single group name */
+ if (strstr(value, ":") != NULL)
return 0;
+
if (cctx->ctx)
- rv = SSL_CTX_set_tmp_ecdh(cctx->ctx, ecdh);
+ rv = SSL_CTX_set1_groups_list(cctx->ctx, value);
else if (cctx->ssl)
- rv = SSL_set_tmp_ecdh(cctx->ssl, ecdh);
- EC_KEY_free(ecdh);
+ rv = SSL_set1_groups_list(cctx->ssl, value);
return rv > 0;
}
-#endif
+
static int cmd_CipherString(SSL_CONF_CTX *cctx, const char *value)
{
int rv = 1;
@@ -386,12 +384,19 @@ static int cmd_Options(SSL_CONF_CTX *cctx, const char *value)
SSL_FLAG_TBL_SRV("ECDHSingle", SSL_OP_SINGLE_ECDH_USE),
SSL_FLAG_TBL("UnsafeLegacyRenegotiation",
SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION),
+ SSL_FLAG_TBL("UnsafeLegacyServerConnect",
+ SSL_OP_LEGACY_SERVER_CONNECT),
+ SSL_FLAG_TBL("ClientRenegotiation",
+ SSL_OP_ALLOW_CLIENT_RENEGOTIATION),
SSL_FLAG_TBL_INV("EncryptThenMac", SSL_OP_NO_ENCRYPT_THEN_MAC),
SSL_FLAG_TBL("NoRenegotiation", SSL_OP_NO_RENEGOTIATION),
SSL_FLAG_TBL("AllowNoDHEKEX", SSL_OP_ALLOW_NO_DHE_KEX),
SSL_FLAG_TBL("PrioritizeChaCha", SSL_OP_PRIORITIZE_CHACHA),
SSL_FLAG_TBL("MiddleboxCompat", SSL_OP_ENABLE_MIDDLEBOX_COMPAT),
- SSL_FLAG_TBL_INV("AntiReplay", SSL_OP_NO_ANTI_REPLAY)
+ SSL_FLAG_TBL_INV("AntiReplay", SSL_OP_NO_ANTI_REPLAY),
+ SSL_FLAG_TBL_INV("ExtendedMasterSecret", SSL_OP_NO_EXTENDED_MASTER_SECRET),
+ SSL_FLAG_TBL_INV("CANames", SSL_OP_DISABLE_TLSEXT_CA_NAMES),
+ SSL_FLAG_TBL("KTLS", SSL_OP_ENABLE_KTLS)
};
if (value == NULL)
return -3;
@@ -437,7 +442,7 @@ static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value)
char **pfilename = &cctx->cert_filename[c->key - c->pkeys];
OPENSSL_free(*pfilename);
*pfilename = OPENSSL_strdup(value);
- if (!*pfilename)
+ if (*pfilename == NULL)
rv = 0;
}
@@ -465,43 +470,73 @@ static int cmd_ServerInfoFile(SSL_CONF_CTX *cctx, const char *value)
}
static int do_store(SSL_CONF_CTX *cctx,
- const char *CAfile, const char *CApath, int verify_store)
+ const char *CAfile, const char *CApath, const char *CAstore,
+ int verify_store)
{
CERT *cert;
X509_STORE **st;
- if (cctx->ctx)
+ SSL_CTX *ctx;
+ OSSL_LIB_CTX *libctx = NULL;
+ const char *propq = NULL;
+
+ if (cctx->ctx != NULL) {
cert = cctx->ctx->cert;
- else if (cctx->ssl)
+ ctx = cctx->ctx;
+ } else if (cctx->ssl != NULL) {
cert = cctx->ssl->cert;
- else
+ ctx = cctx->ssl->ctx;
+ } else {
return 1;
+ }
+ if (ctx != NULL) {
+ libctx = ctx->libctx;
+ propq = ctx->propq;
+ }
st = verify_store ? &cert->verify_store : &cert->chain_store;
if (*st == NULL) {
*st = X509_STORE_new();
if (*st == NULL)
return 0;
}
- return X509_STORE_load_locations(*st, CAfile, CApath) > 0;
+
+ if (CAfile != NULL && !X509_STORE_load_file_ex(*st, CAfile, libctx, propq))
+ return 0;
+ if (CApath != NULL && !X509_STORE_load_path(*st, CApath))
+ return 0;
+ if (CAstore != NULL && !X509_STORE_load_store_ex(*st, CAstore, libctx,
+ propq))
+ return 0;
+ return 1;
}
static int cmd_ChainCAPath(SSL_CONF_CTX *cctx, const char *value)
{
- return do_store(cctx, NULL, value, 0);
+ return do_store(cctx, NULL, value, NULL, 0);
}
static int cmd_ChainCAFile(SSL_CONF_CTX *cctx, const char *value)
{
- return do_store(cctx, value, NULL, 0);
+ return do_store(cctx, value, NULL, NULL, 0);
+}
+
+static int cmd_ChainCAStore(SSL_CONF_CTX *cctx, const char *value)
+{
+ return do_store(cctx, NULL, NULL, value, 0);
}
static int cmd_VerifyCAPath(SSL_CONF_CTX *cctx, const char *value)
{
- return do_store(cctx, NULL, value, 1);
+ return do_store(cctx, NULL, value, NULL, 1);
}
static int cmd_VerifyCAFile(SSL_CONF_CTX *cctx, const char *value)
{
- return do_store(cctx, value, NULL, 1);
+ return do_store(cctx, value, NULL, NULL, 1);
+}
+
+static int cmd_VerifyCAStore(SSL_CONF_CTX *cctx, const char *value)
+{
+ return do_store(cctx, NULL, NULL, value, 1);
}
static int cmd_RequestCAFile(SSL_CONF_CTX *cctx, const char *value)
@@ -532,33 +567,69 @@ static int cmd_ClientCAPath(SSL_CONF_CTX *cctx, const char *value)
return cmd_RequestCAPath(cctx, value);
}
-#ifndef OPENSSL_NO_DH
+static int cmd_RequestCAStore(SSL_CONF_CTX *cctx, const char *value)
+{
+ if (cctx->canames == NULL)
+ cctx->canames = sk_X509_NAME_new_null();
+ if (cctx->canames == NULL)
+ return 0;
+ return SSL_add_store_cert_subjects_to_stack(cctx->canames, value);
+}
+
+static int cmd_ClientCAStore(SSL_CONF_CTX *cctx, const char *value)
+{
+ return cmd_RequestCAStore(cctx, value);
+}
+
static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value)
{
int rv = 0;
- DH *dh = NULL;
+ EVP_PKEY *dhpkey = NULL;
BIO *in = NULL;
- if (cctx->ctx || cctx->ssl) {
+ SSL_CTX *sslctx = (cctx->ssl != NULL) ? cctx->ssl->ctx : cctx->ctx;
+ OSSL_DECODER_CTX *decoderctx = NULL;
+
+ if (cctx->ctx != NULL || cctx->ssl != NULL) {
in = BIO_new(BIO_s_file());
if (in == NULL)
goto end;
if (BIO_read_filename(in, value) <= 0)
goto end;
- dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
- if (dh == NULL)
+
+ decoderctx
+ = OSSL_DECODER_CTX_new_for_pkey(&dhpkey, "PEM", NULL, "DH",
+ OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ sslctx->libctx, sslctx->propq);
+ if (decoderctx == NULL)
+ goto end;
+ ERR_set_mark();
+ while (!OSSL_DECODER_from_bio(decoderctx, in)
+ && dhpkey == NULL
+ && !BIO_eof(in));
+ OSSL_DECODER_CTX_free(decoderctx);
+
+ if (dhpkey == NULL) {
+ ERR_clear_last_mark();
goto end;
- } else
+ }
+ ERR_pop_to_mark();
+ } else {
return 1;
- if (cctx->ctx)
- rv = SSL_CTX_set_tmp_dh(cctx->ctx, dh);
- if (cctx->ssl)
- rv = SSL_set_tmp_dh(cctx->ssl, dh);
+ }
+
+ if (cctx->ctx != NULL) {
+ if ((rv = SSL_CTX_set0_tmp_dh_pkey(cctx->ctx, dhpkey)) > 0)
+ dhpkey = NULL;
+ }
+ if (cctx->ssl != NULL) {
+ if ((rv = SSL_set0_tmp_dh_pkey(cctx->ssl, dhpkey)) > 0)
+ dhpkey = NULL;
+ }
end:
- DH_free(dh);
+ EVP_PKEY_free(dhpkey);
BIO_free(in);
return rv > 0;
}
-#endif
static int cmd_RecordPadding(SSL_CONF_CTX *cctx, const char *value)
{
@@ -612,7 +683,8 @@ typedef struct {
#define SSL_CONF_CMD_SWITCH(name, flags) \
{0, NULL, name, flags, SSL_CONF_TYPE_NONE}
-/* See apps/apps.h if you change this table. */
+/* See apps/include/opt.h if you change this table. */
+/* The SSL_CONF_CMD_SWITCH should be the same order as ssl_cmd_switches */
static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
SSL_CONF_CMD_SWITCH("no_ssl3", 0),
SSL_CONF_CMD_SWITCH("no_tls1", 0),
@@ -626,23 +698,23 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
SSL_CONF_CMD_SWITCH("no_ticket", 0),
SSL_CONF_CMD_SWITCH("serverpref", SSL_CONF_FLAG_SERVER),
SSL_CONF_CMD_SWITCH("legacy_renegotiation", 0),
- SSL_CONF_CMD_SWITCH("legacy_server_connect", SSL_CONF_FLAG_SERVER),
+ SSL_CONF_CMD_SWITCH("client_renegotiation", SSL_CONF_FLAG_SERVER),
+ SSL_CONF_CMD_SWITCH("legacy_server_connect", SSL_CONF_FLAG_CLIENT),
SSL_CONF_CMD_SWITCH("no_renegotiation", 0),
SSL_CONF_CMD_SWITCH("no_resumption_on_reneg", SSL_CONF_FLAG_SERVER),
- SSL_CONF_CMD_SWITCH("no_legacy_server_connect", SSL_CONF_FLAG_SERVER),
+ SSL_CONF_CMD_SWITCH("no_legacy_server_connect", SSL_CONF_FLAG_CLIENT),
SSL_CONF_CMD_SWITCH("allow_no_dhe_kex", 0),
SSL_CONF_CMD_SWITCH("prioritize_chacha", SSL_CONF_FLAG_SERVER),
SSL_CONF_CMD_SWITCH("strict", 0),
SSL_CONF_CMD_SWITCH("no_middlebox", 0),
SSL_CONF_CMD_SWITCH("anti_replay", SSL_CONF_FLAG_SERVER),
SSL_CONF_CMD_SWITCH("no_anti_replay", SSL_CONF_FLAG_SERVER),
+ SSL_CONF_CMD_SWITCH("no_etm", 0),
SSL_CONF_CMD_STRING(SignatureAlgorithms, "sigalgs", 0),
SSL_CONF_CMD_STRING(ClientSignatureAlgorithms, "client_sigalgs", 0),
SSL_CONF_CMD_STRING(Curves, "curves", 0),
SSL_CONF_CMD_STRING(Groups, "groups", 0),
-#ifndef OPENSSL_NO_EC
SSL_CONF_CMD_STRING(ECDHParameters, "named_curve", SSL_CONF_FLAG_SERVER),
-#endif
SSL_CONF_CMD_STRING(CipherString, "cipher", 0),
SSL_CONF_CMD_STRING(Ciphersuites, "ciphersuites", 0),
SSL_CONF_CMD_STRING(Protocol, NULL, 0),
@@ -661,10 +733,14 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
SSL_CONF_TYPE_DIR),
SSL_CONF_CMD(ChainCAFile, "chainCAfile", SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_FILE),
+ SSL_CONF_CMD(ChainCAStore, "chainCAstore", SSL_CONF_FLAG_CERTIFICATE,
+ SSL_CONF_TYPE_STORE),
SSL_CONF_CMD(VerifyCAPath, "verifyCApath", SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_DIR),
SSL_CONF_CMD(VerifyCAFile, "verifyCAfile", SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_FILE),
+ SSL_CONF_CMD(VerifyCAStore, "verifyCAstore", SSL_CONF_FLAG_CERTIFICATE,
+ SSL_CONF_TYPE_STORE),
SSL_CONF_CMD(RequestCAFile, "requestCAFile", SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_FILE),
SSL_CONF_CMD(ClientCAFile, NULL,
@@ -675,11 +751,14 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
SSL_CONF_CMD(ClientCAPath, NULL,
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_DIR),
-#ifndef OPENSSL_NO_DH
+ SSL_CONF_CMD(RequestCAStore, "requestCAStore", SSL_CONF_FLAG_CERTIFICATE,
+ SSL_CONF_TYPE_STORE),
+ SSL_CONF_CMD(ClientCAStore, NULL,
+ SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
+ SSL_CONF_TYPE_STORE),
SSL_CONF_CMD(DHParameters, "dhparam",
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_FILE),
-#endif
SSL_CONF_CMD_STRING(RecordPadding, "record_padding", 0),
SSL_CONF_CMD_STRING(NumTickets, "num_tickets", SSL_CONF_FLAG_SERVER),
};
@@ -699,6 +778,8 @@ static const ssl_switch_tbl ssl_cmd_switches[] = {
{SSL_OP_CIPHER_SERVER_PREFERENCE, 0}, /* serverpref */
/* legacy_renegotiation */
{SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION, 0},
+ /* Allow client renegotiation */
+ {SSL_OP_ALLOW_CLIENT_RENEGOTIATION, 0},
/* legacy_server_connect */
{SSL_OP_LEGACY_SERVER_CONNECT, 0},
/* no_renegotiation */
@@ -718,11 +799,13 @@ static const ssl_switch_tbl ssl_cmd_switches[] = {
{SSL_OP_NO_ANTI_REPLAY, SSL_TFLAG_INV},
/* no_anti_replay */
{SSL_OP_NO_ANTI_REPLAY, 0},
+ /* no Encrypt-then-Mac */
+ {SSL_OP_NO_ENCRYPT_THEN_MAC, 0},
};
static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd)
{
- if (!pcmd || !*pcmd)
+ if (pcmd == NULL || *pcmd == NULL)
return 0;
/* If a prefix is set, check and skip */
if (cctx->prefix) {
@@ -732,7 +815,7 @@ static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd)
strncmp(*pcmd, cctx->prefix, cctx->prefixlen))
return 0;
if (cctx->flags & SSL_CONF_FLAG_FILE &&
- strncasecmp(*pcmd, cctx->prefix, cctx->prefixlen))
+ OPENSSL_strncasecmp(*pcmd, cctx->prefix, cctx->prefixlen))
return 0;
*pcmd += cctx->prefixlen;
} else if (cctx->flags & SSL_CONF_FLAG_CMDLINE) {
@@ -774,7 +857,7 @@ static const ssl_conf_cmd_tbl *ssl_conf_cmd_lookup(SSL_CONF_CTX *cctx,
return t;
}
if (cctx->flags & SSL_CONF_FLAG_FILE) {
- if (t->str_file && strcasecmp(t->str_file, cmd) == 0)
+ if (t->str_file && OPENSSL_strcasecmp(t->str_file, cmd) == 0)
return t;
}
}
@@ -800,7 +883,7 @@ int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value)
{
const ssl_conf_cmd_tbl *runcmd;
if (cmd == NULL) {
- SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_INVALID_NULL_CMD_NAME);
+ ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_NULL_CMD_NAME);
return 0;
}
@@ -821,17 +904,14 @@ int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value)
return 2;
if (rv == -2)
return -2;
- if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) {
- SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_BAD_VALUE);
- ERR_add_error_data(4, "cmd=", cmd, ", value=", value);
- }
+ if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS)
+ ERR_raise_data(ERR_LIB_SSL, SSL_R_BAD_VALUE,
+ "cmd=%s, value=%s", cmd, value);
return 0;
}
- if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) {
- SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_UNKNOWN_CMD_NAME);
- ERR_add_error_data(2, "cmd=", cmd);
- }
+ if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS)
+ ERR_raise_data(ERR_LIB_SSL, SSL_R_UNKNOWN_CMD_NAME, "cmd=%s", cmd);
return -2;
}
@@ -840,13 +920,14 @@ int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv)
{
int rv;
const char *arg = NULL, *argn;
- if (pargc && *pargc == 0)
+
+ if (pargc != NULL && *pargc == 0)
return 0;
- if (!pargc || *pargc > 0)
+ if (pargc == NULL || *pargc > 0)
arg = **pargv;
if (arg == NULL)
return 0;
- if (!pargc || *pargc > 1)
+ if (pargc == NULL || *pargc > 1)
argn = (*pargv)[1];
else
argn = NULL;
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 324f2ccbb0de..41898844ff97 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -2,7 +2,7 @@
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,722 +10,10 @@
#include <openssl/err.h>
#include <openssl/sslerr.h>
+#include "sslerr.h"
#ifndef OPENSSL_NO_ERR
-static const ERR_STRING_DATA SSL_str_functs[] = {
- {ERR_PACK(ERR_LIB_SSL, SSL_F_ADD_CLIENT_KEY_SHARE_EXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_ADD_KEY_SHARE, 0), "add_key_share"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_BYTES_TO_CIPHER_LIST, 0),
- "bytes_to_cipher_list"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_CHECK_SUITEB_CIPHER_LIST, 0),
- "check_suiteb_cipher_list"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_CIPHERSUITE_CB, 0), "ciphersuite_cb"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_CA_NAMES, 0), "construct_ca_names"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS, 0),
- "construct_key_exchange_tbs"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_STATEFUL_TICKET, 0),
- "construct_stateful_ticket"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_STATELESS_TICKET, 0),
- "construct_stateless_ticket"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH, 0),
- "create_synthetic_message_hash"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_CREATE_TICKET_PREQUEL, 0),
- "create_ticket_prequel"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_CT_MOVE_SCTS, 0), "ct_move_scts"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_CT_STRICT, 0), "ct_strict"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_CUSTOM_EXT_ADD, 0), "custom_ext_add"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_CUSTOM_EXT_PARSE, 0), "custom_ext_parse"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_D2I_SSL_SESSION, 0), "d2i_SSL_SESSION"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DANE_CTX_ENABLE, 0), "dane_ctx_enable"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DANE_MTYPE_SET, 0), "dane_mtype_set"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DANE_TLSA_ADD, 0), "dane_tlsa_add"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DERIVE_SECRET_KEY_AND_IV, 0),
- "derive_secret_key_and_iv"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DO_DTLS1_WRITE, 0), "do_dtls1_write"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DO_SSL3_WRITE, 0), "do_ssl3_write"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_BUFFER_RECORD, 0),
- "dtls1_buffer_record"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_CHECK_TIMEOUT_NUM, 0),
- "dtls1_check_timeout_num"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_HEARTBEAT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_HM_FRAGMENT_NEW, 0),
- "dtls1_hm_fragment_new"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_PREPROCESS_FRAGMENT, 0),
- "dtls1_preprocess_fragment"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS, 0),
- "dtls1_process_buffered_records"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_PROCESS_RECORD, 0),
- "dtls1_process_record"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_READ_BYTES, 0), "dtls1_read_bytes"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_READ_FAILED, 0), "dtls1_read_failed"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_RETRANSMIT_MESSAGE, 0),
- "dtls1_retransmit_message"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_WRITE_APP_DATA_BYTES, 0),
- "dtls1_write_app_data_bytes"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_WRITE_BYTES, 0), "dtls1_write_bytes"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLSV1_LISTEN, 0), "DTLSv1_listen"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC, 0),
- "dtls_construct_change_cipher_spec"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST, 0),
- "dtls_construct_hello_verify_request"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, 0),
- "dtls_get_reassembled_message"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS_PROCESS_HELLO_VERIFY, 0),
- "dtls_process_hello_verify"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS_RECORD_LAYER_NEW, 0),
- "DTLS_RECORD_LAYER_new"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS_WAIT_FOR_DRY, 0), "dtls_wait_for_dry"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_EARLY_DATA_COUNT_OK, 0),
- "early_data_count_ok"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_EARLY_DATA, 0), "final_early_data"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_EC_PT_FORMATS, 0),
- "final_ec_pt_formats"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_EMS, 0), "final_ems"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_KEY_SHARE, 0), "final_key_share"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_MAXFRAGMENTLEN, 0),
- "final_maxfragmentlen"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_PSK, 0), "final_psk"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_RENEGOTIATE, 0), "final_renegotiate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_SERVER_NAME, 0), "final_server_name"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_SIG_ALGS, 0), "final_sig_algs"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_GET_CERT_VERIFY_TBS_DATA, 0),
- "get_cert_verify_tbs_data"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_NSS_KEYLOG_INT, 0), "nss_keylog_int"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OPENSSL_INIT_SSL, 0), "OPENSSL_init_ssl"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION, 0),
- "ossl_statem_client13_write_transition"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE, 0),
- "ossl_statem_client_post_process_message"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE, 0),
- "ossl_statem_client_process_message"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION, 0),
- "ossl_statem_client_read_transition"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION, 0),
- "ossl_statem_client_write_transition"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER13_READ_TRANSITION, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION, 0),
- "ossl_statem_server13_write_transition"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE, 0),
- "ossl_statem_server_post_process_message"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_POST_WORK, 0),
- "ossl_statem_server_post_work"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE, 0),
- "ossl_statem_server_process_message"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION, 0),
- "ossl_statem_server_read_transition"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION, 0),
- "ossl_statem_server_write_transition"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_PARSE_CA_NAMES, 0), "parse_ca_names"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_PITEM_NEW, 0), "pitem_new"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_PQUEUE_NEW, 0), "pqueue_new"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_PROCESS_KEY_SHARE_EXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_READ_STATE_MACHINE, 0), "read_state_machine"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SET_CLIENT_CIPHERSUITE, 0),
- "set_client_ciphersuite"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET, 0),
- "srp_generate_client_master_secret"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SRP_GENERATE_SERVER_MASTER_SECRET, 0),
- "srp_generate_server_master_secret"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SRP_VERIFY_SERVER_PARAM, 0),
- "srp_verify_server_param"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_CHANGE_CIPHER_STATE, 0),
- "ssl3_change_cipher_state"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, 0),
- "ssl3_check_cert_and_algorithm"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_CTRL, 0), "ssl3_ctrl"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_CTX_CTRL, 0), "ssl3_ctx_ctrl"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_DIGEST_CACHED_RECORDS, 0),
- "ssl3_digest_cached_records"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC, 0),
- "ssl3_do_change_cipher_spec"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_ENC, 0), "ssl3_enc"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_FINAL_FINISH_MAC, 0),
- "ssl3_final_finish_mac"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_FINISH_MAC, 0), "ssl3_finish_mac"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_GENERATE_KEY_BLOCK, 0),
- "ssl3_generate_key_block"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_GENERATE_MASTER_SECRET, 0),
- "ssl3_generate_master_secret"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_GET_RECORD, 0), "ssl3_get_record"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_INIT_FINISHED_MAC, 0),
- "ssl3_init_finished_mac"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_OUTPUT_CERT_CHAIN, 0),
- "ssl3_output_cert_chain"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_READ_BYTES, 0), "ssl3_read_bytes"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_READ_N, 0), "ssl3_read_n"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_SETUP_KEY_BLOCK, 0),
- "ssl3_setup_key_block"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_SETUP_READ_BUFFER, 0),
- "ssl3_setup_read_buffer"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_SETUP_WRITE_BUFFER, 0),
- "ssl3_setup_write_buffer"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_WRITE_BYTES, 0), "ssl3_write_bytes"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_WRITE_PENDING, 0), "ssl3_write_pending"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_CERT_CHAIN, 0), "ssl_add_cert_chain"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_CERT_TO_BUF, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_CERT_TO_WPACKET, 0),
- "ssl_add_cert_to_wpacket"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, 0),
- "SSL_add_dir_cert_subjects_to_stack"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK, 0),
- "SSL_add_file_cert_subjects_to_stack"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_BAD_METHOD, 0), "ssl_bad_method"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_BUILD_CERT_CHAIN, 0),
- "ssl_build_cert_chain"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_BYTES_TO_CIPHER_LIST, 0),
- "SSL_bytes_to_cipher_list"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CACHE_CIPHERLIST, 0),
- "ssl_cache_cipherlist"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CERT_ADD0_CHAIN_CERT, 0),
- "ssl_cert_add0_chain_cert"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CERT_DUP, 0), "ssl_cert_dup"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CERT_NEW, 0), "ssl_cert_new"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CERT_SET0_CHAIN, 0),
- "ssl_cert_set0_chain"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CHECK_PRIVATE_KEY, 0),
- "SSL_check_private_key"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO, 0),
- "ssl_check_srp_ext_ClientHello"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, 0),
- "ssl_check_srvr_ecc_cert_and_alg"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CHOOSE_CLIENT_VERSION, 0),
- "ssl_choose_client_version"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CIPHER_DESCRIPTION, 0),
- "SSL_CIPHER_description"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CIPHER_LIST_TO_BYTES, 0),
- "ssl_cipher_list_to_bytes"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CIPHER_PROCESS_RULESTR, 0),
- "ssl_cipher_process_rulestr"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CIPHER_STRENGTH_SORT, 0),
- "ssl_cipher_strength_sort"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CLEAR, 0), "SSL_clear"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CLIENT_HELLO_GET1_EXTENSIONS_PRESENT, 0),
- "SSL_client_hello_get1_extensions_present"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD, 0),
- "SSL_COMP_add_compression_method"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CONF_CMD, 0), "SSL_CONF_cmd"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CREATE_CIPHER_LIST, 0),
- "ssl_create_cipher_list"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTRL, 0), "SSL_ctrl"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_CHECK_PRIVATE_KEY, 0),
- "SSL_CTX_check_private_key"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_ENABLE_CT, 0), "SSL_CTX_enable_ct"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_MAKE_PROFILES, 0),
- "ssl_ctx_make_profiles"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_NEW, 0), "SSL_CTX_new"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_ALPN_PROTOS, 0),
- "SSL_CTX_set_alpn_protos"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_CIPHER_LIST, 0),
- "SSL_CTX_set_cipher_list"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, 0),
- "SSL_CTX_set_client_cert_engine"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK, 0),
- "SSL_CTX_set_ct_validation_callback"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT, 0),
- "SSL_CTX_set_session_id_context"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_SSL_VERSION, 0),
- "SSL_CTX_set_ssl_version"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH, 0),
- "SSL_CTX_set_tlsext_max_fragment_length"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_CERTIFICATE, 0),
- "SSL_CTX_use_certificate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1, 0),
- "SSL_CTX_use_certificate_ASN1"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, 0),
- "SSL_CTX_use_certificate_file"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_PRIVATEKEY, 0),
- "SSL_CTX_use_PrivateKey"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1, 0),
- "SSL_CTX_use_PrivateKey_ASN1"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, 0),
- "SSL_CTX_use_PrivateKey_file"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT, 0),
- "SSL_CTX_use_psk_identity_hint"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_RSAPRIVATEKEY, 0),
- "SSL_CTX_use_RSAPrivateKey"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1, 0),
- "SSL_CTX_use_RSAPrivateKey_ASN1"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, 0),
- "SSL_CTX_use_RSAPrivateKey_file"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_SERVERINFO, 0),
- "SSL_CTX_use_serverinfo"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_SERVERINFO_EX, 0),
- "SSL_CTX_use_serverinfo_ex"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_SERVERINFO_FILE, 0),
- "SSL_CTX_use_serverinfo_file"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DANE_DUP, 0), "ssl_dane_dup"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DANE_ENABLE, 0), "SSL_dane_enable"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DERIVE, 0), "ssl_derive"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DO_CONFIG, 0), "ssl_do_config"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DO_HANDSHAKE, 0), "SSL_do_handshake"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DUP_CA_LIST, 0), "SSL_dup_CA_list"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ENABLE_CT, 0), "SSL_enable_ct"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GENERATE_PKEY_GROUP, 0),
- "ssl_generate_pkey_group"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GENERATE_SESSION_ID, 0),
- "ssl_generate_session_id"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GET_NEW_SESSION, 0),
- "ssl_get_new_session"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GET_PREV_SESSION, 0),
- "ssl_get_prev_session"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GET_SERVER_CERT_INDEX, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GET_SIGN_PKEY, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_HANDSHAKE_HASH, 0), "ssl_handshake_hash"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_INIT_WBIO_BUFFER, 0),
- "ssl_init_wbio_buffer"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_KEY_UPDATE, 0), "SSL_key_update"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_LOAD_CLIENT_CA_FILE, 0),
- "SSL_load_client_CA_file"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_LOG_MASTER_SECRET, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE, 0),
- "ssl_log_rsa_client_key_exchange"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_MODULE_INIT, 0), "ssl_module_init"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_NEW, 0), "SSL_new"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_NEXT_PROTO_VALIDATE, 0),
- "ssl_next_proto_validate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PEEK, 0), "SSL_peek"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PEEK_EX, 0), "SSL_peek_ex"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PEEK_INTERNAL, 0), "ssl_peek_internal"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_READ, 0), "SSL_read"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_READ_EARLY_DATA, 0),
- "SSL_read_early_data"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_READ_EX, 0), "SSL_read_ex"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_READ_INTERNAL, 0), "ssl_read_internal"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_RENEGOTIATE, 0), "SSL_renegotiate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_RENEGOTIATE_ABBREVIATED, 0),
- "SSL_renegotiate_abbreviated"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_DUP, 0), "ssl_session_dup"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_NEW, 0), "SSL_SESSION_new"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_PRINT_FP, 0),
- "SSL_SESSION_print_fp"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_SET1_ID, 0),
- "SSL_SESSION_set1_id"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_SET1_ID_CONTEXT, 0),
- "SSL_SESSION_set1_id_context"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_ALPN_PROTOS, 0),
- "SSL_set_alpn_protos"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_CERT, 0), "ssl_set_cert"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_CERT_AND_KEY, 0),
- "ssl_set_cert_and_key"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_CIPHER_LIST, 0),
- "SSL_set_cipher_list"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_CT_VALIDATION_CALLBACK, 0),
- "SSL_set_ct_validation_callback"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_FD, 0), "SSL_set_fd"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_PKEY, 0), "ssl_set_pkey"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_RFD, 0), "SSL_set_rfd"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_SESSION, 0), "SSL_set_session"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_SESSION_ID_CONTEXT, 0),
- "SSL_set_session_id_context"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_SESSION_TICKET_EXT, 0),
- "SSL_set_session_ticket_ext"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH, 0),
- "SSL_set_tlsext_max_fragment_length"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_WFD, 0), "SSL_set_wfd"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SHUTDOWN, 0), "SSL_shutdown"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SRP_CTX_INIT, 0), "SSL_SRP_CTX_init"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_START_ASYNC_JOB, 0),
- "ssl_start_async_job"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_UNDEFINED_FUNCTION, 0),
- "ssl_undefined_function"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_UNDEFINED_VOID_FUNCTION, 0),
- "ssl_undefined_void_function"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_CERTIFICATE, 0),
- "SSL_use_certificate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_CERTIFICATE_ASN1, 0),
- "SSL_use_certificate_ASN1"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_CERTIFICATE_FILE, 0),
- "SSL_use_certificate_file"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_PRIVATEKEY, 0), "SSL_use_PrivateKey"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_PRIVATEKEY_ASN1, 0),
- "SSL_use_PrivateKey_ASN1"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_PRIVATEKEY_FILE, 0),
- "SSL_use_PrivateKey_file"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_PSK_IDENTITY_HINT, 0),
- "SSL_use_psk_identity_hint"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_RSAPRIVATEKEY, 0),
- "SSL_use_RSAPrivateKey"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1, 0),
- "SSL_use_RSAPrivateKey_ASN1"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, 0),
- "SSL_use_RSAPrivateKey_file"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_VALIDATE_CT, 0), "ssl_validate_ct"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_VERIFY_CERT_CHAIN, 0),
- "ssl_verify_cert_chain"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, 0),
- "SSL_verify_client_post_handshake"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE, 0), "SSL_write"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE_EARLY_DATA, 0),
- "SSL_write_early_data"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE_EARLY_FINISH, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE_EX, 0), "SSL_write_ex"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE_INTERNAL, 0), "ssl_write_internal"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_STATE_MACHINE, 0), "state_machine"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS12_CHECK_PEER_SIGALG, 0),
- "tls12_check_peer_sigalg"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS12_COPY_SIGALGS, 0), "tls12_copy_sigalgs"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_CHANGE_CIPHER_STATE, 0),
- "tls13_change_cipher_state"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_ENC, 0), "tls13_enc"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_FINAL_FINISH_MAC, 0),
- "tls13_final_finish_mac"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_GENERATE_SECRET, 0),
- "tls13_generate_secret"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_HKDF_EXPAND, 0), "tls13_hkdf_expand"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA, 0),
- "tls13_restore_handshake_digest_for_pha"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA, 0),
- "tls13_save_handshake_digest_for_pha"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_SETUP_KEY_BLOCK, 0),
- "tls13_setup_key_block"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_CHANGE_CIPHER_STATE, 0),
- "tls1_change_cipher_state"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_ENC, 0), "tls1_enc"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_EXPORT_KEYING_MATERIAL, 0),
- "tls1_export_keying_material"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_GET_CURVELIST, 0), "tls1_get_curvelist"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_PRF, 0), "tls1_PRF"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SAVE_U16, 0), "tls1_save_u16"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SETUP_KEY_BLOCK, 0),
- "tls1_setup_key_block"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SET_GROUPS, 0), "tls1_set_groups"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SET_RAW_SIGALGS, 0),
- "tls1_set_raw_sigalgs"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SET_SERVER_SIGALGS, 0),
- "tls1_set_server_sigalgs"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SET_SHARED_SIGALGS, 0),
- "tls1_set_shared_sigalgs"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SET_SIGALGS, 0), "tls1_set_sigalgs"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CHOOSE_SIGALG, 0), "tls_choose_sigalg"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, 0),
- "tls_client_key_exchange_post_work"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_COLLECT_EXTENSIONS, 0),
- "tls_collect_extensions"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES, 0),
- "tls_construct_certificate_authorities"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, 0),
- "tls_construct_certificate_request"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CERT_STATUS, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY, 0),
- "tls_construct_cert_status_body"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, 0),
- "tls_construct_cert_verify"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC, 0),
- "tls_construct_change_cipher_spec"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CKE_DHE, 0),
- "tls_construct_cke_dhe"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CKE_ECDHE, 0),
- "tls_construct_cke_ecdhe"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CKE_GOST, 0),
- "tls_construct_cke_gost"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, 0),
- "tls_construct_cke_psk_preamble"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CKE_RSA, 0),
- "tls_construct_cke_rsa"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CKE_SRP, 0),
- "tls_construct_cke_srp"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, 0),
- "tls_construct_client_certificate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, 0),
- "tls_construct_client_hello"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, 0),
- "tls_construct_client_key_exchange"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_ALPN, 0),
- "tls_construct_ctos_alpn"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_COOKIE, 0),
- "tls_construct_ctos_cookie"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, 0),
- "tls_construct_ctos_early_data"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS, 0),
- "tls_construct_ctos_ec_pt_formats"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_EMS, 0),
- "tls_construct_ctos_ems"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_ETM, 0),
- "tls_construct_ctos_etm"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_HELLO, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_KEY_EXCHANGE, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, 0),
- "tls_construct_ctos_key_share"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN, 0),
- "tls_construct_ctos_maxfragmentlen"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_NPN, 0),
- "tls_construct_ctos_npn"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_PADDING, 0),
- "tls_construct_ctos_padding"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH, 0),
- "tls_construct_ctos_post_handshake_auth"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_PSK, 0),
- "tls_construct_ctos_psk"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES, 0),
- "tls_construct_ctos_psk_kex_modes"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE, 0),
- "tls_construct_ctos_renegotiate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_SCT, 0),
- "tls_construct_ctos_sct"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME, 0),
- "tls_construct_ctos_server_name"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET, 0),
- "tls_construct_ctos_session_ticket"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS, 0),
- "tls_construct_ctos_sig_algs"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_SRP, 0),
- "tls_construct_ctos_srp"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, 0),
- "tls_construct_ctos_status_request"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS, 0),
- "tls_construct_ctos_supported_groups"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, 0),
- "tls_construct_ctos_supported_versions"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP, 0),
- "tls_construct_ctos_use_srtp"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_VERIFY, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS, 0),
- "tls_construct_encrypted_extensions"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA, 0),
- "tls_construct_end_of_early_data"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_EXTENSIONS, 0),
- "tls_construct_extensions"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_FINISHED, 0),
- "tls_construct_finished"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_HELLO_REQUEST, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_HELLO_RETRY_REQUEST, 0),
- "tls_construct_hello_retry_request"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_KEY_UPDATE, 0),
- "tls_construct_key_update"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, 0),
- "tls_construct_new_session_ticket"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_NEXT_PROTO, 0),
- "tls_construct_next_proto"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, 0),
- "tls_construct_server_certificate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_SERVER_HELLO, 0),
- "tls_construct_server_hello"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, 0),
- "tls_construct_server_key_exchange"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_ALPN, 0),
- "tls_construct_stoc_alpn"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_CERTIFICATE, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_COOKIE, 0),
- "tls_construct_stoc_cookie"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG, 0),
- "tls_construct_stoc_cryptopro_bug"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_DONE, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, 0),
- "tls_construct_stoc_early_data"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_INFO, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS, 0),
- "tls_construct_stoc_ec_pt_formats"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_EMS, 0),
- "tls_construct_stoc_ems"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_ETM, 0),
- "tls_construct_stoc_etm"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_HELLO, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_KEY_EXCHANGE, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, 0),
- "tls_construct_stoc_key_share"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN, 0),
- "tls_construct_stoc_maxfragmentlen"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG, 0),
- "tls_construct_stoc_next_proto_neg"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_PSK, 0),
- "tls_construct_stoc_psk"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE, 0),
- "tls_construct_stoc_renegotiate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME, 0),
- "tls_construct_stoc_server_name"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET, 0),
- "tls_construct_stoc_session_ticket"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, 0),
- "tls_construct_stoc_status_request"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, 0),
- "tls_construct_stoc_supported_groups"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS, 0),
- "tls_construct_stoc_supported_versions"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP, 0),
- "tls_construct_stoc_use_srtp"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, 0),
- "tls_early_post_process_client_hello"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_FINISH_HANDSHAKE, 0),
- "tls_finish_handshake"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_GET_MESSAGE_BODY, 0),
- "tls_get_message_body"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_GET_MESSAGE_HEADER, 0),
- "tls_get_message_header"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_HANDLE_ALPN, 0), "tls_handle_alpn"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_HANDLE_STATUS_REQUEST, 0),
- "tls_handle_status_request"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES, 0),
- "tls_parse_certificate_authorities"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_ALPN, 0),
- "tls_parse_ctos_alpn"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_COOKIE, 0),
- "tls_parse_ctos_cookie"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_EARLY_DATA, 0),
- "tls_parse_ctos_early_data"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS, 0),
- "tls_parse_ctos_ec_pt_formats"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_EMS, 0), "tls_parse_ctos_ems"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, 0),
- "tls_parse_ctos_key_share"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN, 0),
- "tls_parse_ctos_maxfragmentlen"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH, 0),
- "tls_parse_ctos_post_handshake_auth"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_PSK, 0), "tls_parse_ctos_psk"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES, 0),
- "tls_parse_ctos_psk_kex_modes"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE, 0),
- "tls_parse_ctos_renegotiate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SERVER_NAME, 0),
- "tls_parse_ctos_server_name"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SESSION_TICKET, 0),
- "tls_parse_ctos_session_ticket"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SIG_ALGS, 0),
- "tls_parse_ctos_sig_algs"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, 0),
- "tls_parse_ctos_sig_algs_cert"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SRP, 0), "tls_parse_ctos_srp"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, 0),
- "tls_parse_ctos_status_request"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, 0),
- "tls_parse_ctos_supported_groups"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_USE_SRTP, 0),
- "tls_parse_ctos_use_srtp"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_ALPN, 0),
- "tls_parse_stoc_alpn"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_COOKIE, 0),
- "tls_parse_stoc_cookie"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_EARLY_DATA, 0),
- "tls_parse_stoc_early_data"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, 0),
- "tls_parse_stoc_ec_pt_formats"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_KEY_SHARE, 0),
- "tls_parse_stoc_key_share"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN, 0),
- "tls_parse_stoc_maxfragmentlen"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_NPN, 0), "tls_parse_stoc_npn"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_PSK, 0), "tls_parse_stoc_psk"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_RENEGOTIATE, 0),
- "tls_parse_stoc_renegotiate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_SCT, 0), "tls_parse_stoc_sct"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_SERVER_NAME, 0),
- "tls_parse_stoc_server_name"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_SESSION_TICKET, 0),
- "tls_parse_stoc_session_ticket"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, 0),
- "tls_parse_stoc_status_request"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS, 0),
- "tls_parse_stoc_supported_versions"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_USE_SRTP, 0),
- "tls_parse_stoc_use_srtp"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, 0),
- "tls_post_process_client_hello"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE, 0),
- "tls_post_process_client_key_exchange"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE, 0),
- "tls_prepare_client_certificate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST, 0),
- "tls_process_as_hello_retry_request"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, 0),
- "tls_process_certificate_request"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CERT_STATUS, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CERT_STATUS_BODY, 0),
- "tls_process_cert_status_body"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CERT_VERIFY, 0),
- "tls_process_cert_verify"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, 0),
- "tls_process_change_cipher_spec"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CKE_DHE, 0),
- "tls_process_cke_dhe"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CKE_ECDHE, 0),
- "tls_process_cke_ecdhe"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CKE_GOST, 0),
- "tls_process_cke_gost"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, 0),
- "tls_process_cke_psk_preamble"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CKE_RSA, 0),
- "tls_process_cke_rsa"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CKE_SRP, 0),
- "tls_process_cke_srp"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, 0),
- "tls_process_client_certificate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CLIENT_HELLO, 0),
- "tls_process_client_hello"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, 0),
- "tls_process_client_key_exchange"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS, 0),
- "tls_process_encrypted_extensions"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA, 0),
- "tls_process_end_of_early_data"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_FINISHED, 0),
- "tls_process_finished"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_HELLO_REQ, 0),
- "tls_process_hello_req"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST, 0),
- "tls_process_hello_retry_request"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT, 0),
- "tls_process_initial_server_flight"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_KEY_EXCHANGE, 0),
- "tls_process_key_exchange"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_KEY_UPDATE, 0),
- "tls_process_key_update"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, 0),
- "tls_process_new_session_ticket"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_NEXT_PROTO, 0),
- "tls_process_next_proto"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, 0),
- "tls_process_server_certificate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_SERVER_DONE, 0),
- "tls_process_server_done"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_SERVER_HELLO, 0),
- "tls_process_server_hello"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_SKE_DHE, 0),
- "tls_process_ske_dhe"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_SKE_ECDHE, 0),
- "tls_process_ske_ecdhe"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE, 0),
- "tls_process_ske_psk_preamble"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_SKE_SRP, 0),
- "tls_process_ske_srp"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PSK_DO_BINDER, 0), "tls_psk_do_binder"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_SCAN_CLIENTHELLO_TLSEXT, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_SETUP_HANDSHAKE, 0),
- "tls_setup_handshake"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_USE_CERTIFICATE_CHAIN_FILE, 0),
- "use_certificate_chain_file"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_WPACKET_INTERN_INIT_LEN, 0),
- "wpacket_intern_init_len"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_WPACKET_START_SUB_PACKET_LEN__, 0),
- "WPACKET_start_sub_packet_len__"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_WRITE_STATE_MACHINE, 0),
- "write_state_machine"},
- {0, NULL}
-};
-
static const ERR_STRING_DATA SSL_str_reasons[] = {
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY),
"application data after close notify"},
@@ -733,8 +21,6 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
"app data in handshake"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT),
"attempt to reuse session in different context"},
- {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE),
- "at least TLS 1.0 needed in FIPS mode"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE),
"at least (D)TLS 1.2 needed in Suite B mode"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_CHANGE_CIPHER_SPEC),
@@ -786,6 +72,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CALLBACK_FAILED), "callback failed"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CANNOT_CHANGE_CIPHER),
"cannot change cipher"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CANNOT_GET_GROUP_NAME),
+ "cannot get group name"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CA_DN_LENGTH_MISMATCH),
"ca dn length mismatch"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CA_KEY_TOO_SMALL), "ca key too small"},
@@ -800,8 +88,6 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
"ciphersuite digest has changed"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CIPHER_CODE_WRONG_LENGTH),
"cipher code wrong length"},
- {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CIPHER_OR_HASH_UNAVAILABLE),
- "cipher or hash unavailable"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CLIENTHELLO_TLSEXT), "clienthello tlsext"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COMPRESSED_LENGTH_TOO_LONG),
"compressed length too long"},
@@ -820,6 +106,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COOKIE_GEN_CALLBACK_FAILURE),
"cookie gen callback failure"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COOKIE_MISMATCH), "cookie mismatch"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COPY_PARAMETERS_FAILED),
+ "copy parameters failed"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED),
"custom ext handler already installed"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DANE_ALREADY_ENABLED),
@@ -937,6 +225,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
"invalid status response"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_TICKET_KEYS_LENGTH),
"invalid ticket keys length"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED),
+ "legacy sigalg disallowed or unsupported"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_LENGTH_MISMATCH), "length mismatch"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_LENGTH_TOO_LONG), "length too long"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_LENGTH_TOO_SHORT), "length too short"},
@@ -1011,6 +301,9 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS),
"no shared signature algorithms"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SRTP_PROFILES), "no srtp profiles"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_DIGEST_ALGORITHM),
+ "no suitable digest algorithm"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_GROUPS), "no suitable groups"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_KEY_SHARE),
"no suitable key share"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM),
@@ -1184,10 +477,6 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
"tlsv1 unrecognized name"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_UNSUPPORTED_EXTENSION),
"tlsv1 unsupported extension"},
- {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT),
- "peer does not accept heartbeats"},
- {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_HEARTBEAT_PENDING),
- "heartbeat request already pending"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL),
"tls illegal exporter label"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST),
@@ -1210,6 +499,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
"unexpected ccs message"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_END_OF_EARLY_DATA),
"unexpected end of early data"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_EOF_WHILE_READING),
+ "unexpected eof while reading"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_MESSAGE), "unexpected message"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_RECORD), "unexpected record"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNINITIALIZED), "uninitialized"},
@@ -1270,13 +561,11 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
#endif
-int ERR_load_SSL_strings(void)
+int ossl_err_load_SSL_strings(void)
{
#ifndef OPENSSL_NO_ERR
- if (ERR_func_error_string(SSL_str_functs[0].error) == NULL) {
- ERR_load_strings_const(SSL_str_functs);
+ if (ERR_reason_error_string(SSL_str_reasons[0].error) == NULL)
ERR_load_strings_const(SSL_str_reasons);
- }
#endif
return 1;
}
diff --git a/ssl/ssl_err_legacy.c b/ssl/ssl_err_legacy.c
new file mode 100644
index 000000000000..7ce25e1f1112
--- /dev/null
+++ b/ssl/ssl_err_legacy.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* This is the C source file where we include this header directly */
+#include <openssl/sslerr_legacy.h>
+#include "sslerr.h"
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+int ERR_load_SSL_strings(void)
+{
+ return ossl_err_load_SSL_strings();
+}
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
diff --git a/ssl/ssl_init.c b/ssl/ssl_init.c
index a5d45480c9e0..db0234d7a423 100644
--- a/ssl/ssl_init.c
+++ b/ssl/ssl_init.c
@@ -1,7 +1,7 @@
/*
* Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,7 +12,9 @@
#include "internal/err.h"
#include <openssl/crypto.h>
#include <openssl/evp.h>
+#include <openssl/trace.h>
#include "ssl_local.h"
+#include "sslerr.h"
#include "internal/thread_once.h"
static int stopped;
@@ -23,89 +25,17 @@ static CRYPTO_ONCE ssl_base = CRYPTO_ONCE_STATIC_INIT;
static int ssl_base_inited = 0;
DEFINE_RUN_ONCE_STATIC(ossl_init_ssl_base)
{
-#ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_ssl_base: "
- "Adding SSL ciphers and digests\n");
-#endif
-#ifndef OPENSSL_NO_DES
- EVP_add_cipher(EVP_des_cbc());
- EVP_add_cipher(EVP_des_ede3_cbc());
-#endif
-#ifndef OPENSSL_NO_IDEA
- EVP_add_cipher(EVP_idea_cbc());
-#endif
-#ifndef OPENSSL_NO_RC4
- EVP_add_cipher(EVP_rc4());
-# ifndef OPENSSL_NO_MD5
- EVP_add_cipher(EVP_rc4_hmac_md5());
-# endif
-#endif
-#ifndef OPENSSL_NO_RC2
- EVP_add_cipher(EVP_rc2_cbc());
- /*
- * Not actually used for SSL/TLS but this makes PKCS#12 work if an
- * application only calls SSL_library_init().
- */
- EVP_add_cipher(EVP_rc2_40_cbc());
-#endif
- EVP_add_cipher(EVP_aes_128_cbc());
- EVP_add_cipher(EVP_aes_192_cbc());
- EVP_add_cipher(EVP_aes_256_cbc());
- EVP_add_cipher(EVP_aes_128_gcm());
- EVP_add_cipher(EVP_aes_256_gcm());
- EVP_add_cipher(EVP_aes_128_ccm());
- EVP_add_cipher(EVP_aes_256_ccm());
- EVP_add_cipher(EVP_aes_128_cbc_hmac_sha1());
- EVP_add_cipher(EVP_aes_256_cbc_hmac_sha1());
- EVP_add_cipher(EVP_aes_128_cbc_hmac_sha256());
- EVP_add_cipher(EVP_aes_256_cbc_hmac_sha256());
-#ifndef OPENSSL_NO_ARIA
- EVP_add_cipher(EVP_aria_128_gcm());
- EVP_add_cipher(EVP_aria_256_gcm());
-#endif
-#ifndef OPENSSL_NO_CAMELLIA
- EVP_add_cipher(EVP_camellia_128_cbc());
- EVP_add_cipher(EVP_camellia_256_cbc());
-#endif
-#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
- EVP_add_cipher(EVP_chacha20_poly1305());
-#endif
-
-#ifndef OPENSSL_NO_SEED
- EVP_add_cipher(EVP_seed_cbc());
-#endif
-
-#ifndef OPENSSL_NO_MD5
- EVP_add_digest(EVP_md5());
- EVP_add_digest_alias(SN_md5, "ssl3-md5");
- EVP_add_digest(EVP_md5_sha1());
-#endif
- EVP_add_digest(EVP_sha1()); /* RSA with sha1 */
- EVP_add_digest_alias(SN_sha1, "ssl3-sha1");
- EVP_add_digest_alias(SN_sha1WithRSAEncryption, SN_sha1WithRSA);
- EVP_add_digest(EVP_sha224());
- EVP_add_digest(EVP_sha256());
- EVP_add_digest(EVP_sha384());
- EVP_add_digest(EVP_sha512());
#ifndef OPENSSL_NO_COMP
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_ssl_base: "
- "SSL_COMP_get_compression_methods()\n");
-# endif
+ OSSL_TRACE(INIT, "ossl_init_ssl_base: "
+ "SSL_COMP_get_compression_methods()\n");
/*
* This will initialise the built-in compression algorithms. The value
* returned is a STACK_OF(SSL_COMP), but that can be discarded safely
*/
SSL_COMP_get_compression_methods();
#endif
- /* initialize cipher/digest methods table */
- if (!ssl_load_ciphers())
- return 0;
-
-#ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_ssl_base: "
- "SSL_add_ssl_module()\n");
-#endif
+ ssl_sort_cipher_list();
+ OSSL_TRACE(INIT,"ossl_init_ssl_base: SSL_add_ssl_module()\n");
/*
* We ignore an error return here. Not much we can do - but not that bad
* either. We can still safely continue.
@@ -124,11 +54,8 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_ssl_strings)
* pulling in all the error strings during static linking
*/
#if !defined(OPENSSL_NO_ERR) && !defined(OPENSSL_NO_AUTOERRINIT)
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ossl_init_load_ssl_strings: "
- "ERR_load_SSL_strings()\n");
-# endif
- ERR_load_SSL_strings();
+ OSSL_TRACE(INIT, "ossl_init_load_ssl_strings: ossl_err_load_SSL_strings()\n");
+ ossl_err_load_SSL_strings();
#endif
return 1;
}
@@ -149,10 +76,8 @@ static void ssl_library_stop(void)
if (ssl_base_inited) {
#ifndef OPENSSL_NO_COMP
-# ifdef OPENSSL_INIT_DEBUG
- fprintf(stderr, "OPENSSL_INIT: ssl_library_stop: "
- "ssl_comp_free_compression_methods_int()\n");
-# endif
+ OSSL_TRACE(INIT, "ssl_library_stop: "
+ "ssl_comp_free_compression_methods_int()\n");
ssl_comp_free_compression_methods_int();
#endif
}
@@ -175,7 +100,7 @@ int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS * settings)
* sets an error etc
*/
stoperrset = 1;
- SSLerr(SSL_F_OPENSSL_INIT_SSL, ERR_R_INIT_FAIL);
+ ERR_raise(ERR_LIB_SSL, ERR_R_INIT_FAIL);
}
return 0;
}
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 47adc3211c85..214884b0f1ef 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -3,7 +3,7 @@
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,65 +11,51 @@
#include <stdio.h>
#include "ssl_local.h"
+#include "e_os.h"
#include <openssl/objects.h>
#include <openssl/x509v3.h>
#include <openssl/rand.h>
-#include <openssl/rand_drbg.h>
#include <openssl/ocsp.h>
#include <openssl/dh.h>
#include <openssl/engine.h>
#include <openssl/async.h>
#include <openssl/ct.h>
+#include <openssl/trace.h>
#include "internal/cryptlib.h"
#include "internal/refcount.h"
+#include "internal/ktls.h"
-const char SSL_version_str[] = OPENSSL_VERSION_TEXT;
-
-static int ssl_undefined_function_1(SSL *ssl, SSL3_RECORD *r, size_t s, int t)
+static int ssl_undefined_function_1(SSL *ssl, SSL3_RECORD *r, size_t s, int t,
+ SSL_MAC_BUF *mac, size_t macsize)
{
- (void)r;
- (void)s;
- (void)t;
return ssl_undefined_function(ssl);
}
static int ssl_undefined_function_2(SSL *ssl, SSL3_RECORD *r, unsigned char *s,
int t)
{
- (void)r;
- (void)s;
- (void)t;
return ssl_undefined_function(ssl);
}
static int ssl_undefined_function_3(SSL *ssl, unsigned char *r,
unsigned char *s, size_t t, size_t *u)
{
- (void)r;
- (void)s;
- (void)t;
- (void)u;
return ssl_undefined_function(ssl);
}
static int ssl_undefined_function_4(SSL *ssl, int r)
{
- (void)r;
return ssl_undefined_function(ssl);
}
static size_t ssl_undefined_function_5(SSL *ssl, const char *r, size_t s,
unsigned char *t)
{
- (void)r;
- (void)s;
- (void)t;
return ssl_undefined_function(ssl);
}
static int ssl_undefined_function_6(int r)
{
- (void)r;
return ssl_undefined_function(NULL);
}
@@ -77,13 +63,6 @@ static int ssl_undefined_function_7(SSL *ssl, unsigned char *r, size_t s,
const char *t, size_t u,
const unsigned char *v, size_t w, int x)
{
- (void)r;
- (void)s;
- (void)t;
- (void)u;
- (void)v;
- (void)w;
- (void)x;
return ssl_undefined_function(ssl);
}
@@ -147,7 +126,7 @@ static int dane_ctx_enable(struct dane_ctx_st *dctx)
if (mdord == NULL || mdevp == NULL) {
OPENSSL_free(mdord);
OPENSSL_free(mdevp);
- SSLerr(SSL_F_DANE_CTX_ENABLE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -221,7 +200,7 @@ static int ssl_dane_dup(SSL *to, SSL *from)
to->dane.trecs = sk_danetls_record_new_reserve(NULL, num);
if (to->dane.trecs == NULL) {
- SSLerr(SSL_F_SSL_DANE_DUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -241,7 +220,7 @@ static int dane_mtype_set(struct dane_ctx_st *dctx,
int i;
if (mtype == DANETLS_MATCHING_FULL && md != NULL) {
- SSLerr(SSL_F_DANE_MTYPE_SET, SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL);
+ ERR_raise(ERR_LIB_SSL, SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL);
return 0;
}
@@ -252,14 +231,14 @@ static int dane_mtype_set(struct dane_ctx_st *dctx,
mdevp = OPENSSL_realloc(dctx->mdevp, n * sizeof(*mdevp));
if (mdevp == NULL) {
- SSLerr(SSL_F_DANE_MTYPE_SET, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return -1;
}
dctx->mdevp = mdevp;
mdord = OPENSSL_realloc(dctx->mdord, n * sizeof(*mdord));
if (mdord == NULL) {
- SSLerr(SSL_F_DANE_MTYPE_SET, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return -1;
}
dctx->mdord = mdord;
@@ -290,7 +269,7 @@ static const EVP_MD *tlsa_md_get(SSL_DANE *dane, uint8_t mtype)
static int dane_tlsa_add(SSL_DANE *dane,
uint8_t usage,
uint8_t selector,
- uint8_t mtype, unsigned const char *data, size_t dlen)
+ uint8_t mtype, const unsigned char *data, size_t dlen)
{
danetls_record *t;
const EVP_MD *md = NULL;
@@ -299,44 +278,44 @@ static int dane_tlsa_add(SSL_DANE *dane,
int num;
if (dane->trecs == NULL) {
- SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_NOT_ENABLED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_DANE_NOT_ENABLED);
return -1;
}
if (ilen < 0 || dlen != (size_t)ilen) {
- SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_DATA_LENGTH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_DATA_LENGTH);
return 0;
}
if (usage > DANETLS_USAGE_LAST) {
- SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE);
return 0;
}
if (selector > DANETLS_SELECTOR_LAST) {
- SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_SELECTOR);
+ ERR_raise(ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_SELECTOR);
return 0;
}
if (mtype != DANETLS_MATCHING_FULL) {
md = tlsa_md_get(dane, mtype);
if (md == NULL) {
- SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_MATCHING_TYPE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_MATCHING_TYPE);
return 0;
}
}
- if (md != NULL && dlen != (size_t)EVP_MD_size(md)) {
- SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH);
+ if (md != NULL && dlen != (size_t)EVP_MD_get_size(md)) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH);
return 0;
}
if (!data) {
- SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_NULL_DATA);
+ ERR_raise(ERR_LIB_SSL, SSL_R_DANE_TLSA_NULL_DATA);
return 0;
}
if ((t = OPENSSL_zalloc(sizeof(*t))) == NULL) {
- SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return -1;
}
@@ -346,7 +325,7 @@ static int dane_tlsa_add(SSL_DANE *dane,
t->data = OPENSSL_malloc(dlen);
if (t->data == NULL) {
tlsa_free(t);
- SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return -1;
}
memcpy(t->data, data, dlen);
@@ -363,12 +342,12 @@ static int dane_tlsa_add(SSL_DANE *dane,
if (!d2i_X509(&cert, &p, ilen) || p < data ||
dlen != (size_t)(p - data)) {
tlsa_free(t);
- SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_CERTIFICATE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_CERTIFICATE);
return 0;
}
if (X509_get0_pubkey(cert) == NULL) {
tlsa_free(t);
- SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_CERTIFICATE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_CERTIFICATE);
return 0;
}
@@ -387,7 +366,7 @@ static int dane_tlsa_add(SSL_DANE *dane,
if ((dane->certs == NULL &&
(dane->certs = sk_X509_new_null()) == NULL) ||
!sk_X509_push(dane->certs, cert)) {
- SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
X509_free(cert);
tlsa_free(t);
return -1;
@@ -398,7 +377,7 @@ static int dane_tlsa_add(SSL_DANE *dane,
if (!d2i_PUBKEY(&pkey, &p, ilen) || p < data ||
dlen != (size_t)(p - data)) {
tlsa_free(t);
- SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_PUBLIC_KEY);
+ ERR_raise(ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_PUBLIC_KEY);
return 0;
}
@@ -448,7 +427,7 @@ static int dane_tlsa_add(SSL_DANE *dane,
if (!sk_danetls_record_insert(dane->trecs, t, i)) {
tlsa_free(t);
- SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return -1;
}
dane->umask |= DANETLS_USAGE_BIT(usage);
@@ -566,6 +545,19 @@ static int ssl_check_allowed_versions(int min_version, int max_version)
return 1;
}
+#if defined(__TANDEM) && defined(OPENSSL_VPROC)
+/*
+ * Define a VPROC function for HP NonStop build ssl library.
+ * This is used by platform version identification tools.
+ * Do not inline this procedure or make it static.
+ */
+# define OPENSSL_VPROC_STRING_(x) x##_SSL
+# define OPENSSL_VPROC_STRING(x) OPENSSL_VPROC_STRING_(x)
+# define OPENSSL_VPROC_FUNC OPENSSL_VPROC_STRING(OPENSSL_VPROC)
+void OPENSSL_VPROC_FUNC(void) {}
+#endif
+
+
static void clear_ciphers(SSL *s)
{
/* clear the current cipher */
@@ -577,7 +569,7 @@ static void clear_ciphers(SSL *s)
int SSL_clear(SSL *s)
{
if (s->method == NULL) {
- SSLerr(SSL_F_SSL_CLEAR, SSL_R_NO_METHOD_SPECIFIED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_METHOD_SPECIFIED);
return 0;
}
@@ -598,7 +590,7 @@ int SSL_clear(SSL *s)
s->shutdown = 0;
if (s->renegotiate) {
- SSLerr(SSL_F_SSL_CLEAR, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -652,6 +644,7 @@ int SSL_clear(SSL *s)
return 1;
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
/** Used to change an SSL_CTXs default SSL method type */
int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth)
{
@@ -659,32 +652,33 @@ int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth)
ctx->method = meth;
- if (!SSL_CTX_set_ciphersuites(ctx, TLS_DEFAULT_CIPHERSUITES)) {
- SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);
+ if (!SSL_CTX_set_ciphersuites(ctx, OSSL_default_ciphersuites())) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);
return 0;
}
- sk = ssl_create_cipher_list(ctx->method,
+ sk = ssl_create_cipher_list(ctx,
ctx->tls13_ciphersuites,
&(ctx->cipher_list),
&(ctx->cipher_list_by_id),
- SSL_DEFAULT_CIPHER_LIST, ctx->cert);
+ OSSL_default_cipher_list(), ctx->cert);
if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0)) {
- SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);
+ ERR_raise(ERR_LIB_SSL, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);
return 0;
}
return 1;
}
+#endif
SSL *SSL_new(SSL_CTX *ctx)
{
SSL *s;
if (ctx == NULL) {
- SSLerr(SSL_F_SSL_NEW, SSL_R_NULL_SSL_CTX);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NULL_SSL_CTX);
return NULL;
}
if (ctx->method == NULL) {
- SSLerr(SSL_F_SSL_NEW, SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION);
+ ERR_raise(ERR_LIB_SSL, SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION);
return NULL;
}
@@ -774,7 +768,6 @@ SSL *SSL_new(SSL_CTX *ctx)
s->ext.ocsp.resp_len = 0;
SSL_CTX_up_ref(ctx);
s->session_ctx = ctx;
-#ifndef OPENSSL_NO_EC
if (ctx->ext.ecpointformats) {
s->ext.ecpointformats =
OPENSSL_memdup(ctx->ext.ecpointformats,
@@ -797,7 +790,7 @@ SSL *SSL_new(SSL_CTX *ctx)
}
s->ext.supportedgroups_len = ctx->ext.supportedgroups_len;
}
-#endif
+
#ifndef OPENSSL_NO_NEXTPROTONEG
s->ext.npn = NULL;
#endif
@@ -843,6 +836,9 @@ SSL *SSL_new(SSL_CTX *ctx)
s->psk_find_session_cb = ctx->psk_find_session_cb;
s->psk_use_session_cb = ctx->psk_use_session_cb;
+ s->async_cb = ctx->async_cb;
+ s->async_cb_arg = ctx->async_cb_arg;
+
s->job = NULL;
#ifndef OPENSSL_NO_CT
@@ -854,7 +850,7 @@ SSL *SSL_new(SSL_CTX *ctx)
return s;
err:
SSL_free(s);
- SSLerr(SSL_F_SSL_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -879,8 +875,7 @@ int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx,
unsigned int sid_ctx_len)
{
if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
- SSLerr(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT,
- SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
+ ERR_raise(ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
return 0;
}
ctx->sid_ctx_length = sid_ctx_len;
@@ -893,8 +888,7 @@ int SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx,
unsigned int sid_ctx_len)
{
if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
- SSLerr(SSL_F_SSL_SET_SESSION_ID_CONTEXT,
- SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
+ ERR_raise(ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
return 0;
}
ssl->sid_ctx_length = sid_ctx_len;
@@ -905,7 +899,8 @@ int SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx,
int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb)
{
- CRYPTO_THREAD_write_lock(ctx->lock);
+ if (!CRYPTO_THREAD_write_lock(ctx->lock))
+ return 0;
ctx->generate_session_id = cb;
CRYPTO_THREAD_unlock(ctx->lock);
return 1;
@@ -913,7 +908,8 @@ int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb)
int SSL_set_generate_session_id(SSL *ssl, GEN_SESSION_CB cb)
{
- CRYPTO_THREAD_write_lock(ssl->lock);
+ if (!CRYPTO_THREAD_write_lock(ssl->lock))
+ return 0;
ssl->generate_session_id = cb;
CRYPTO_THREAD_unlock(ssl->lock);
return 1;
@@ -938,7 +934,8 @@ int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id,
r.session_id_length = id_len;
memcpy(r.session_id, id, id_len);
- CRYPTO_THREAD_read_lock(ssl->session_ctx->lock);
+ if (!CRYPTO_THREAD_read_lock(ssl->session_ctx->lock))
+ return 0;
p = lh_SSL_SESSION_retrieve(ssl->session_ctx->sessions, &r);
CRYPTO_THREAD_unlock(ssl->session_ctx->lock);
return (p != NULL);
@@ -966,11 +963,40 @@ int SSL_set_trust(SSL *s, int trust)
int SSL_set1_host(SSL *s, const char *hostname)
{
+ /* If a hostname is provided and parses as an IP address,
+ * treat it as such. */
+ if (hostname && X509_VERIFY_PARAM_set1_ip_asc(s->param, hostname) == 1)
+ return 1;
+
return X509_VERIFY_PARAM_set1_host(s->param, hostname, 0);
}
int SSL_add1_host(SSL *s, const char *hostname)
{
+ /* If a hostname is provided and parses as an IP address,
+ * treat it as such. */
+ if (hostname)
+ {
+ ASN1_OCTET_STRING *ip;
+ char *old_ip;
+
+ ip = a2i_IPADDRESS(hostname);
+ if (ip) {
+ /* We didn't want it; only to check if it *is* an IP address */
+ ASN1_OCTET_STRING_free(ip);
+
+ old_ip = X509_VERIFY_PARAM_get1_ip_asc(s->param);
+ if (old_ip)
+ {
+ OPENSSL_free(old_ip);
+ /* There can be only one IP address */
+ return 0;
+ }
+
+ return X509_VERIFY_PARAM_set1_ip_asc(s->param, hostname);
+ }
+ }
+
return X509_VERIFY_PARAM_add1_host(s->param, hostname, 0);
}
@@ -1010,11 +1036,11 @@ int SSL_dane_enable(SSL *s, const char *basedomain)
SSL_DANE *dane = &s->dane;
if (s->ctx->dane.mdmax == 0) {
- SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_CONTEXT_NOT_DANE_ENABLED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_CONTEXT_NOT_DANE_ENABLED);
return 0;
}
if (dane->trecs != NULL) {
- SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_DANE_ALREADY_ENABLED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_DANE_ALREADY_ENABLED);
return 0;
}
@@ -1025,14 +1051,14 @@ int SSL_dane_enable(SSL *s, const char *basedomain)
*/
if (s->ext.hostname == NULL) {
if (!SSL_set_tlsext_host_name(s, basedomain)) {
- SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN);
+ ERR_raise(ERR_LIB_SSL, SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN);
return -1;
}
}
/* Primary RFC6125 reference identifier */
if (!X509_VERIFY_PARAM_set1_host(s->param, basedomain, 0)) {
- SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN);
+ ERR_raise(ERR_LIB_SSL, SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN);
return -1;
}
@@ -1042,7 +1068,7 @@ int SSL_dane_enable(SSL *s, const char *basedomain)
dane->trecs = sk_danetls_record_new_null();
if (dane->trecs == NULL) {
- SSLerr(SSL_F_SSL_DANE_ENABLE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return -1;
}
return 1;
@@ -1080,7 +1106,7 @@ int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki)
}
int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector,
- uint8_t *mtype, unsigned const char **data, size_t *dlen)
+ uint8_t *mtype, const unsigned char **data, size_t *dlen)
{
SSL_DANE *dane = &s->dane;
@@ -1107,7 +1133,7 @@ SSL_DANE *SSL_get0_dane(SSL *s)
}
int SSL_dane_tlsa_add(SSL *s, uint8_t usage, uint8_t selector,
- uint8_t mtype, unsigned const char *data, size_t dlen)
+ uint8_t mtype, const unsigned char *data, size_t dlen)
{
return dane_tlsa_add(&s->dane, usage, selector, mtype, data, dlen);
}
@@ -1159,11 +1185,15 @@ void SSL_free(SSL *s)
dane_final(&s->dane);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data);
+ RECORD_LAYER_release(&s->rlayer);
+
/* Ignore return value */
ssl_free_wbio_buffer(s);
BIO_free_all(s->wbio);
+ s->wbio = NULL;
BIO_free_all(s->rbio);
+ s->rbio = NULL;
BUF_MEM_free(s->init_buf);
@@ -1189,12 +1219,10 @@ void SSL_free(SSL *s)
OPENSSL_free(s->ext.hostname);
SSL_CTX_free(s->session_ctx);
-#ifndef OPENSSL_NO_EC
OPENSSL_free(s->ext.ecpointformats);
OPENSSL_free(s->ext.peer_ecpointformats);
OPENSSL_free(s->ext.supportedgroups);
OPENSSL_free(s->ext.peer_supportedgroups);
-#endif /* OPENSSL_NO_EC */
sk_X509_EXTENSION_pop_free(s->ext.ocsp.exts, X509_EXTENSION_free);
#ifndef OPENSSL_NO_OCSP
sk_OCSP_RESPID_pop_free(s->ext.ocsp.ids, OCSP_RESPID_free);
@@ -1220,8 +1248,6 @@ void SSL_free(SSL *s)
if (s->method != NULL)
s->method->ssl_free(s);
- RECORD_LAYER_release(&s->rlayer);
-
SSL_CTX_free(s->ctx);
ASYNC_WAIT_CTX_free(s->waitctx);
@@ -1356,11 +1382,20 @@ int SSL_set_fd(SSL *s, int fd)
bio = BIO_new(BIO_s_socket());
if (bio == NULL) {
- SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB);
goto err;
}
BIO_set_fd(bio, fd, BIO_NOCLOSE);
SSL_set_bio(s, bio, bio);
+#ifndef OPENSSL_NO_KTLS
+ /*
+ * The new socket is created successfully regardless of ktls_enable.
+ * ktls_enable doesn't change any functionality of the socket, except
+ * changing the setsockopt to enable the processing of ktls_start.
+ * Thus, it is not a problem to call it for non-TLS sockets.
+ */
+ ktls_enable(fd);
+#endif /* OPENSSL_NO_KTLS */
ret = 1;
err:
return ret;
@@ -1375,11 +1410,20 @@ int SSL_set_wfd(SSL *s, int fd)
BIO *bio = BIO_new(BIO_s_socket());
if (bio == NULL) {
- SSLerr(SSL_F_SSL_SET_WFD, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fd(bio, fd, BIO_NOCLOSE);
SSL_set0_wbio(s, bio);
+#ifndef OPENSSL_NO_KTLS
+ /*
+ * The new socket is created successfully regardless of ktls_enable.
+ * ktls_enable doesn't change any functionality of the socket, except
+ * changing the setsockopt to enable the processing of ktls_start.
+ * Thus, it is not a problem to call it for non-TLS sockets.
+ */
+ ktls_enable(fd);
+#endif /* OPENSSL_NO_KTLS */
} else {
BIO_up_ref(rbio);
SSL_set0_wbio(s, rbio);
@@ -1396,7 +1440,7 @@ int SSL_set_rfd(SSL *s, int fd)
BIO *bio = BIO_new(BIO_s_socket());
if (bio == NULL) {
- SSLerr(SSL_F_SSL_SET_RFD, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fd(bio, fd, BIO_NOCLOSE);
@@ -1415,12 +1459,10 @@ size_t SSL_get_finished(const SSL *s, void *buf, size_t count)
{
size_t ret = 0;
- if (s->s3 != NULL) {
- ret = s->s3->tmp.finish_md_len;
- if (count > ret)
- count = ret;
- memcpy(buf, s->s3->tmp.finish_md, count);
- }
+ ret = s->s3.tmp.finish_md_len;
+ if (count > ret)
+ count = ret;
+ memcpy(buf, s->s3.tmp.finish_md, count);
return ret;
}
@@ -1429,12 +1471,10 @@ size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count)
{
size_t ret = 0;
- if (s->s3 != NULL) {
- ret = s->s3->tmp.peer_finish_md_len;
- if (count > ret)
- count = ret;
- memcpy(buf, s->s3->tmp.peer_finish_md, count);
- }
+ ret = s->s3.tmp.peer_finish_md_len;
+ if (count > ret)
+ count = ret;
+ memcpy(buf, s->s3.tmp.peer_finish_md, count);
return ret;
}
@@ -1536,23 +1576,24 @@ int SSL_has_pending(const SSL *s)
return RECORD_LAYER_read_pending(&s->rlayer);
}
-X509 *SSL_get_peer_certificate(const SSL *s)
+X509 *SSL_get1_peer_certificate(const SSL *s)
{
- X509 *r;
-
- if ((s == NULL) || (s->session == NULL))
- r = NULL;
- else
- r = s->session->peer;
-
- if (r == NULL)
- return r;
+ X509 *r = SSL_get0_peer_certificate(s);
- X509_up_ref(r);
+ if (r != NULL)
+ X509_up_ref(r);
return r;
}
+X509 *SSL_get0_peer_certificate(const SSL *s)
+{
+ if ((s == NULL) || (s->session == NULL))
+ return NULL;
+ else
+ return s->session->peer;
+}
+
STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s)
{
STACK_OF(X509) *r;
@@ -1577,7 +1618,7 @@ STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s)
int SSL_copy_session_id(SSL *t, const SSL *f)
{
int i;
- /* Do we need to to SSL locking? */
+ /* Do we need to do SSL locking? */
if (!SSL_set_session(t, SSL_get_session(f))) {
return 0;
}
@@ -1606,11 +1647,11 @@ int SSL_copy_session_id(SSL *t, const SSL *f)
int SSL_CTX_check_private_key(const SSL_CTX *ctx)
{
if ((ctx == NULL) || (ctx->cert->key->x509 == NULL)) {
- SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY, SSL_R_NO_CERTIFICATE_ASSIGNED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_ASSIGNED);
return 0;
}
if (ctx->cert->key->privatekey == NULL) {
- SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY, SSL_R_NO_PRIVATE_KEY_ASSIGNED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_PRIVATE_KEY_ASSIGNED);
return 0;
}
return X509_check_private_key
@@ -1621,15 +1662,15 @@ int SSL_CTX_check_private_key(const SSL_CTX *ctx)
int SSL_check_private_key(const SSL *ssl)
{
if (ssl == NULL) {
- SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (ssl->cert->key->x509 == NULL) {
- SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY, SSL_R_NO_CERTIFICATE_ASSIGNED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_ASSIGNED);
return 0;
}
if (ssl->cert->key->privatekey == NULL) {
- SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY, SSL_R_NO_PRIVATE_KEY_ASSIGNED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_PRIVATE_KEY_ASSIGNED);
return 0;
}
return X509_check_private_key(ssl->cert->key->x509,
@@ -1664,6 +1705,40 @@ int SSL_get_changed_async_fds(SSL *s, OSSL_ASYNC_FD *addfd, size_t *numaddfds,
numdelfds);
}
+int SSL_CTX_set_async_callback(SSL_CTX *ctx, SSL_async_callback_fn callback)
+{
+ ctx->async_cb = callback;
+ return 1;
+}
+
+int SSL_CTX_set_async_callback_arg(SSL_CTX *ctx, void *arg)
+{
+ ctx->async_cb_arg = arg;
+ return 1;
+}
+
+int SSL_set_async_callback(SSL *s, SSL_async_callback_fn callback)
+{
+ s->async_cb = callback;
+ return 1;
+}
+
+int SSL_set_async_callback_arg(SSL *s, void *arg)
+{
+ s->async_cb_arg = arg;
+ return 1;
+}
+
+int SSL_get_async_status(SSL *s, int *status)
+{
+ ASYNC_WAIT_CTX *ctx = s->waitctx;
+
+ if (ctx == NULL)
+ return 0;
+ *status = ASYNC_WAIT_CTX_get_status(ctx);
+ return 1;
+}
+
int SSL_accept(SSL *s)
{
if (s->handshake_func == NULL) {
@@ -1689,6 +1764,13 @@ long SSL_get_default_timeout(const SSL *s)
return s->method->get_timeout();
}
+static int ssl_async_wait_ctx_cb(void *arg)
+{
+ SSL *s = (SSL *)arg;
+
+ return s->async_cb(s, s->async_cb_arg);
+}
+
static int ssl_start_async_job(SSL *s, struct ssl_async_args *args,
int (*func) (void *))
{
@@ -1697,6 +1779,10 @@ static int ssl_start_async_job(SSL *s, struct ssl_async_args *args,
s->waitctx = ASYNC_WAIT_CTX_new();
if (s->waitctx == NULL)
return -1;
+ if (s->async_cb != NULL
+ && !ASYNC_WAIT_CTX_set_callback
+ (s->waitctx, ssl_async_wait_ctx_cb, s))
+ return -1;
}
s->rwstate = SSL_NOTHING;
@@ -1704,7 +1790,7 @@ static int ssl_start_async_job(SSL *s, struct ssl_async_args *args,
sizeof(struct ssl_async_args))) {
case ASYNC_ERR:
s->rwstate = SSL_NOTHING;
- SSLerr(SSL_F_SSL_START_ASYNC_JOB, SSL_R_FAILED_TO_INIT_ASYNC);
+ ERR_raise(ERR_LIB_SSL, SSL_R_FAILED_TO_INIT_ASYNC);
return -1;
case ASYNC_PAUSE:
s->rwstate = SSL_ASYNC_PAUSED;
@@ -1717,7 +1803,7 @@ static int ssl_start_async_job(SSL *s, struct ssl_async_args *args,
return ret;
default:
s->rwstate = SSL_NOTHING;
- SSLerr(SSL_F_SSL_START_ASYNC_JOB, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
/* Shouldn't happen */
return -1;
}
@@ -1748,7 +1834,7 @@ static int ssl_io_intern(void *vargs)
int ssl_read_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
{
if (s->handshake_func == NULL) {
- SSLerr(SSL_F_SSL_READ_INTERNAL, SSL_R_UNINITIALIZED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNINITIALIZED);
return -1;
}
@@ -1759,7 +1845,7 @@ int ssl_read_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
if (s->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY
|| s->early_data_state == SSL_EARLY_DATA_ACCEPT_RETRY) {
- SSLerr(SSL_F_SSL_READ_INTERNAL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
/*
@@ -1792,7 +1878,7 @@ int SSL_read(SSL *s, void *buf, int num)
size_t readbytes;
if (num < 0) {
- SSLerr(SSL_F_SSL_READ, SSL_R_BAD_LENGTH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_LENGTH);
return -1;
}
@@ -1822,15 +1908,14 @@ int SSL_read_early_data(SSL *s, void *buf, size_t num, size_t *readbytes)
int ret;
if (!s->server) {
- SSLerr(SSL_F_SSL_READ_EARLY_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return SSL_READ_EARLY_DATA_ERROR;
}
switch (s->early_data_state) {
case SSL_EARLY_DATA_NONE:
if (!SSL_in_before(s)) {
- SSLerr(SSL_F_SSL_READ_EARLY_DATA,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return SSL_READ_EARLY_DATA_ERROR;
}
/* fall through */
@@ -1867,7 +1952,7 @@ int SSL_read_early_data(SSL *s, void *buf, size_t num, size_t *readbytes)
return SSL_READ_EARLY_DATA_FINISH;
default:
- SSLerr(SSL_F_SSL_READ_EARLY_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return SSL_READ_EARLY_DATA_ERROR;
}
}
@@ -1880,7 +1965,7 @@ int SSL_get_early_data_status(const SSL *s)
static int ssl_peek_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
{
if (s->handshake_func == NULL) {
- SSLerr(SSL_F_SSL_PEEK_INTERNAL, SSL_R_UNINITIALIZED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNINITIALIZED);
return -1;
}
@@ -1911,7 +1996,7 @@ int SSL_peek(SSL *s, void *buf, int num)
size_t readbytes;
if (num < 0) {
- SSLerr(SSL_F_SSL_PEEK, SSL_R_BAD_LENGTH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_LENGTH);
return -1;
}
@@ -1940,20 +2025,20 @@ int SSL_peek_ex(SSL *s, void *buf, size_t num, size_t *readbytes)
int ssl_write_internal(SSL *s, const void *buf, size_t num, size_t *written)
{
if (s->handshake_func == NULL) {
- SSLerr(SSL_F_SSL_WRITE_INTERNAL, SSL_R_UNINITIALIZED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNINITIALIZED);
return -1;
}
if (s->shutdown & SSL_SENT_SHUTDOWN) {
s->rwstate = SSL_NOTHING;
- SSLerr(SSL_F_SSL_WRITE_INTERNAL, SSL_R_PROTOCOL_IS_SHUTDOWN);
+ ERR_raise(ERR_LIB_SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
return -1;
}
if (s->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY
|| s->early_data_state == SSL_EARLY_DATA_ACCEPT_RETRY
|| s->early_data_state == SSL_EARLY_DATA_READ_RETRY) {
- SSLerr(SSL_F_SSL_WRITE_INTERNAL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
/* If we are a client and haven't sent the Finished we better do that */
@@ -1977,13 +2062,77 @@ int ssl_write_internal(SSL *s, const void *buf, size_t num, size_t *written)
}
}
+ossl_ssize_t SSL_sendfile(SSL *s, int fd, off_t offset, size_t size, int flags)
+{
+ ossl_ssize_t ret;
+
+ if (s->handshake_func == NULL) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNINITIALIZED);
+ return -1;
+ }
+
+ if (s->shutdown & SSL_SENT_SHUTDOWN) {
+ s->rwstate = SSL_NOTHING;
+ ERR_raise(ERR_LIB_SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
+ return -1;
+ }
+
+ if (!BIO_get_ktls_send(s->wbio)) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNINITIALIZED);
+ return -1;
+ }
+
+ /* If we have an alert to send, lets send it */
+ if (s->s3.alert_dispatch) {
+ ret = (ossl_ssize_t)s->method->ssl_dispatch_alert(s);
+ if (ret <= 0) {
+ /* SSLfatal() already called if appropriate */
+ return ret;
+ }
+ /* if it went, fall through and send more stuff */
+ }
+
+ s->rwstate = SSL_WRITING;
+ if (BIO_flush(s->wbio) <= 0) {
+ if (!BIO_should_retry(s->wbio)) {
+ s->rwstate = SSL_NOTHING;
+ } else {
+#ifdef EAGAIN
+ set_sys_error(EAGAIN);
+#endif
+ }
+ return -1;
+ }
+
+#ifdef OPENSSL_NO_KTLS
+ ERR_raise_data(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR,
+ "can't call ktls_sendfile(), ktls disabled");
+ return -1;
+#else
+ ret = ktls_sendfile(SSL_get_wfd(s), fd, offset, size, flags);
+ if (ret < 0) {
+#if defined(EAGAIN) && defined(EINTR) && defined(EBUSY)
+ if ((get_last_sys_error() == EAGAIN) ||
+ (get_last_sys_error() == EINTR) ||
+ (get_last_sys_error() == EBUSY))
+ BIO_set_retry_write(s->wbio);
+ else
+#endif
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNINITIALIZED);
+ return ret;
+ }
+ s->rwstate = SSL_NOTHING;
+ return ret;
+#endif
+}
+
int SSL_write(SSL *s, const void *buf, int num)
{
int ret;
size_t written;
if (num < 0) {
- SSLerr(SSL_F_SSL_WRITE, SSL_R_BAD_LENGTH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_LENGTH);
return -1;
}
@@ -2020,8 +2169,7 @@ int SSL_write_early_data(SSL *s, const void *buf, size_t num, size_t *written)
|| !SSL_in_before(s)
|| ((s->session == NULL || s->session->ext.max_early_data == 0)
&& (s->psk_use_session_cb == NULL))) {
- SSLerr(SSL_F_SSL_WRITE_EARLY_DATA,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
/* fall through */
@@ -2075,7 +2223,7 @@ int SSL_write_early_data(SSL *s, const void *buf, size_t num, size_t *written)
return ret;
default:
- SSLerr(SSL_F_SSL_WRITE_EARLY_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
}
@@ -2090,7 +2238,7 @@ int SSL_shutdown(SSL *s)
*/
if (s->handshake_func == NULL) {
- SSLerr(SSL_F_SSL_SHUTDOWN, SSL_R_UNINITIALIZED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNINITIALIZED);
return -1;
}
@@ -2108,36 +2256,31 @@ int SSL_shutdown(SSL *s)
return s->method->ssl_shutdown(s);
}
} else {
- SSLerr(SSL_F_SSL_SHUTDOWN, SSL_R_SHUTDOWN_WHILE_IN_INIT);
+ ERR_raise(ERR_LIB_SSL, SSL_R_SHUTDOWN_WHILE_IN_INIT);
return -1;
}
}
int SSL_key_update(SSL *s, int updatetype)
{
- /*
- * TODO(TLS1.3): How will applications know whether TLSv1.3 has been
- * negotiated, and that it is appropriate to call SSL_key_update() instead
- * of SSL_renegotiate().
- */
if (!SSL_IS_TLS13(s)) {
- SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_WRONG_SSL_VERSION);
+ ERR_raise(ERR_LIB_SSL, SSL_R_WRONG_SSL_VERSION);
return 0;
}
if (updatetype != SSL_KEY_UPDATE_NOT_REQUESTED
&& updatetype != SSL_KEY_UPDATE_REQUESTED) {
- SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_INVALID_KEY_UPDATE_TYPE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_KEY_UPDATE_TYPE);
return 0;
}
if (!SSL_is_init_finished(s)) {
- SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_STILL_IN_INIT);
+ ERR_raise(ERR_LIB_SSL, SSL_R_STILL_IN_INIT);
return 0;
}
if (RECORD_LAYER_write_pending(&s->rlayer)) {
- SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_BAD_WRITE_RETRY);
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_WRITE_RETRY);
return 0;
}
@@ -2151,39 +2294,42 @@ int SSL_get_key_update_type(const SSL *s)
return s->key_update;
}
-int SSL_renegotiate(SSL *s)
+/*
+ * Can we accept a renegotiation request? If yes, set the flag and
+ * return 1 if yes. If not, raise error and return 0.
+ */
+static int can_renegotiate(const SSL *s)
{
if (SSL_IS_TLS13(s)) {
- SSLerr(SSL_F_SSL_RENEGOTIATE, SSL_R_WRONG_SSL_VERSION);
+ ERR_raise(ERR_LIB_SSL, SSL_R_WRONG_SSL_VERSION);
return 0;
}
- if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
- SSLerr(SSL_F_SSL_RENEGOTIATE, SSL_R_NO_RENEGOTIATION);
+ if ((s->options & SSL_OP_NO_RENEGOTIATION) != 0) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_RENEGOTIATION);
return 0;
}
+ return 1;
+}
+
+int SSL_renegotiate(SSL *s)
+{
+ if (!can_renegotiate(s))
+ return 0;
+
s->renegotiate = 1;
s->new_session = 1;
-
return s->method->ssl_renegotiate(s);
}
int SSL_renegotiate_abbreviated(SSL *s)
{
- if (SSL_IS_TLS13(s)) {
- SSLerr(SSL_F_SSL_RENEGOTIATE_ABBREVIATED, SSL_R_WRONG_SSL_VERSION);
+ if (!can_renegotiate(s))
return 0;
- }
-
- if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
- SSLerr(SSL_F_SSL_RENEGOTIATE_ABBREVIATED, SSL_R_NO_RENEGOTIATION);
- return 0;
- }
s->renegotiate = 1;
s->new_session = 0;
-
return s->method->ssl_renegotiate(s);
}
@@ -2196,6 +2342,19 @@ int SSL_renegotiate_pending(const SSL *s)
return (s->renegotiate != 0);
}
+int SSL_new_session_ticket(SSL *s)
+{
+ /* If we are in init because we're sending tickets, okay to send more. */
+ if ((SSL_in_init(s) && s->ext.extra_tickets_expected == 0)
+ || SSL_IS_FIRST_HANDSHAKE(s) || !s->server
+ || !SSL_IS_TLS13(s))
+ return 0;
+ s->ext.extra_tickets_expected++;
+ if (!RECORD_LAYER_write_pending(&s->rlayer) && !SSL_in_init(s))
+ ossl_statem_set_in_init(s, 1);
+ return 1;
+}
+
long SSL_ctrl(SSL *s, int cmd, long larg, void *parg)
{
long l;
@@ -2227,6 +2386,10 @@ long SSL_ctrl(SSL *s, int cmd, long larg, void *parg)
case SSL_CTRL_SET_MAX_SEND_FRAGMENT:
if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH)
return 0;
+#ifndef OPENSSL_NO_KTLS
+ if (s->wbio != NULL && BIO_get_ktls_send(s->wbio))
+ return 0;
+#endif /* OPENSSL_NO_KTLS */
s->max_send_fragment = larg;
if (s->max_send_fragment < s->split_send_fragment)
s->split_send_fragment = s->max_send_fragment;
@@ -2244,10 +2407,10 @@ long SSL_ctrl(SSL *s, int cmd, long larg, void *parg)
RECORD_LAYER_set_read_ahead(&s->rlayer, 1);
return 1;
case SSL_CTRL_GET_RI_SUPPORT:
- if (s->s3)
- return s->s3->send_connection_binding;
- else
- return 0;
+ return s->s3.send_connection_binding;
+ case SSL_CTRL_SET_RETRY_VERIFY:
+ s->rwstate = SSL_RETRY_VERIFY;
+ return 1;
case SSL_CTRL_CERT_FLAGS:
return (s->cert->cert_flags |= larg);
case SSL_CTRL_CLEAR_CERT_FLAGS:
@@ -2255,10 +2418,10 @@ long SSL_ctrl(SSL *s, int cmd, long larg, void *parg)
case SSL_CTRL_GET_RAW_CIPHERLIST:
if (parg) {
- if (s->s3->tmp.ciphers_raw == NULL)
+ if (s->s3.tmp.ciphers_raw == NULL)
return 0;
- *(unsigned char **)parg = s->s3->tmp.ciphers_raw;
- return (int)s->s3->tmp.ciphers_rawlen;
+ *(unsigned char **)parg = s->s3.tmp.ciphers_raw;
+ return (int)s->s3.tmp.ciphers_rawlen;
} else {
return TLS_CIPHER_LEN;
}
@@ -2306,16 +2469,25 @@ LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx)
return ctx->sessions;
}
+static int ssl_tsan_load(SSL_CTX *ctx, TSAN_QUALIFIER int *stat)
+{
+ int res = 0;
+
+ if (ssl_tsan_lock(ctx)) {
+ res = tsan_load(stat);
+ ssl_tsan_unlock(ctx);
+ }
+ return res;
+}
+
long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
{
long l;
/* For some cases with ctx == NULL perform syntax checks */
if (ctx == NULL) {
switch (cmd) {
-#ifndef OPENSSL_NO_EC
case SSL_CTRL_SET_GROUPS_LIST:
- return tls1_set_groups_list(NULL, NULL, parg);
-#endif
+ return tls1_set_groups_list(ctx, NULL, NULL, parg);
case SSL_CTRL_SET_SIGALGS_LIST:
case SSL_CTRL_SET_CLIENT_SIGALGS_LIST:
return tls1_set_sigalgs_list(NULL, parg, 0);
@@ -2363,27 +2535,27 @@ long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
case SSL_CTRL_SESS_NUMBER:
return lh_SSL_SESSION_num_items(ctx->sessions);
case SSL_CTRL_SESS_CONNECT:
- return tsan_load(&ctx->stats.sess_connect);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_connect);
case SSL_CTRL_SESS_CONNECT_GOOD:
- return tsan_load(&ctx->stats.sess_connect_good);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_connect_good);
case SSL_CTRL_SESS_CONNECT_RENEGOTIATE:
- return tsan_load(&ctx->stats.sess_connect_renegotiate);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_connect_renegotiate);
case SSL_CTRL_SESS_ACCEPT:
- return tsan_load(&ctx->stats.sess_accept);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_accept);
case SSL_CTRL_SESS_ACCEPT_GOOD:
- return tsan_load(&ctx->stats.sess_accept_good);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_accept_good);
case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE:
- return tsan_load(&ctx->stats.sess_accept_renegotiate);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_accept_renegotiate);
case SSL_CTRL_SESS_HIT:
- return tsan_load(&ctx->stats.sess_hit);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_hit);
case SSL_CTRL_SESS_CB_HIT:
- return tsan_load(&ctx->stats.sess_cb_hit);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_cb_hit);
case SSL_CTRL_SESS_MISSES:
- return tsan_load(&ctx->stats.sess_miss);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_miss);
case SSL_CTRL_SESS_TIMEOUTS:
- return tsan_load(&ctx->stats.sess_timeout);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_timeout);
case SSL_CTRL_SESS_CACHE_FULL:
- return tsan_load(&ctx->stats.sess_cache_full);
+ return ssl_tsan_load(ctx, &ctx->stats.sess_cache_full);
case SSL_CTRL_MODE:
return (ctx->mode |= larg);
case SSL_CTRL_CLEAR_MODE:
@@ -2572,7 +2744,7 @@ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str)
{
STACK_OF(SSL_CIPHER) *sk;
- sk = ssl_create_cipher_list(ctx->method, ctx->tls13_ciphersuites,
+ sk = ssl_create_cipher_list(ctx, ctx->tls13_ciphersuites,
&ctx->cipher_list, &ctx->cipher_list_by_id, str,
ctx->cert);
/*
@@ -2585,7 +2757,7 @@ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str)
if (sk == NULL)
return 0;
else if (cipher_list_tls12_num(sk) == 0) {
- SSLerr(SSL_F_SSL_CTX_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_CIPHER_MATCH);
return 0;
}
return 1;
@@ -2596,14 +2768,14 @@ int SSL_set_cipher_list(SSL *s, const char *str)
{
STACK_OF(SSL_CIPHER) *sk;
- sk = ssl_create_cipher_list(s->ctx->method, s->tls13_ciphersuites,
+ sk = ssl_create_cipher_list(s->ctx, s->tls13_ciphersuites,
&s->cipher_list, &s->cipher_list_by_id, str,
s->cert);
/* see comment in SSL_CTX_set_cipher_list */
if (sk == NULL)
return 0;
else if (cipher_list_tls12_num(sk) == 0) {
- SSLerr(SSL_F_SSL_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_CIPHER_MATCH);
return 0;
}
return 1;
@@ -2807,7 +2979,7 @@ void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
unsigned *len)
{
*data = s->ext.npn;
- if (!*data) {
+ if (*data == NULL) {
*len = 0;
} else {
*len = (unsigned int)s->ext.npn_len;
@@ -2886,7 +3058,7 @@ int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos,
alpn = OPENSSL_memdup(protos, protos_len);
if (alpn == NULL) {
- SSLerr(SSL_F_SSL_CTX_SET_ALPN_PROTOS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 1;
}
OPENSSL_free(ctx->ext.alpn);
@@ -2918,7 +3090,7 @@ int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos,
alpn = OPENSSL_memdup(protos, protos_len);
if (alpn == NULL) {
- SSLerr(SSL_F_SSL_SET_ALPN_PROTOS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 1;
}
OPENSSL_free(ssl->ext.alpn);
@@ -2950,13 +3122,11 @@ void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
unsigned int *len)
{
- *data = NULL;
- if (ssl->s3)
- *data = ssl->s3->alpn_selected;
+ *data = ssl->s3.alpn_selected;
if (*data == NULL)
*len = 0;
else
- *len = (unsigned int)ssl->s3->alpn_selected_len;
+ *len = (unsigned int)ssl->s3.alpn_selected_len;
}
int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen,
@@ -3028,12 +3198,13 @@ static int ssl_session_cmp(const SSL_SESSION *a, const SSL_SESSION *b)
* via ssl.h.
*/
-SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
+SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
+ const SSL_METHOD *meth)
{
SSL_CTX *ret = NULL;
if (meth == NULL) {
- SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_NULL_SSL_METHOD_PASSED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NULL_SSL_METHOD_PASSED);
return NULL;
}
@@ -3041,13 +3212,37 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
return NULL;
if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0) {
- SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS);
+ ERR_raise(ERR_LIB_SSL, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS);
goto err;
}
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL)
goto err;
+ /* Init the reference counting before any call to SSL_CTX_free */
+ ret->references = 1;
+ ret->lock = CRYPTO_THREAD_lock_new();
+ if (ret->lock == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(ret);
+ return NULL;
+ }
+
+#ifdef TSAN_REQUIRES_LOCKING
+ ret->tsan_lock = CRYPTO_THREAD_lock_new();
+ if (ret->tsan_lock == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+#endif
+
+ ret->libctx = libctx;
+ if (propq != NULL) {
+ ret->propq = OPENSSL_strdup(propq);
+ if (ret->propq == NULL)
+ goto err;
+ }
+
ret->method = meth;
ret->min_proto_version = 0;
ret->max_proto_version = 0;
@@ -3056,13 +3251,6 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
ret->session_cache_size = SSL_SESSION_CACHE_MAX_SIZE_DEFAULT;
/* We take the system default. */
ret->session_timeout = meth->get_timeout();
- ret->references = 1;
- ret->lock = CRYPTO_THREAD_lock_new();
- if (ret->lock == NULL) {
- SSLerr(SSL_F_SSL_CTX_NEW, ERR_R_MALLOC_FAILURE);
- OPENSSL_free(ret);
- return NULL;
- }
ret->max_cert_list = SSL_MAX_CERT_LIST_DEFAULT;
ret->verify_mode = SSL_VERIFY_NONE;
if ((ret->cert = ssl_cert_new()) == NULL)
@@ -3075,20 +3263,31 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
if (ret->cert_store == NULL)
goto err;
#ifndef OPENSSL_NO_CT
- ret->ctlog_store = CTLOG_STORE_new();
+ ret->ctlog_store = CTLOG_STORE_new_ex(libctx, propq);
if (ret->ctlog_store == NULL)
goto err;
#endif
- if (!SSL_CTX_set_ciphersuites(ret, TLS_DEFAULT_CIPHERSUITES))
+ /* initialize cipher/digest methods table */
+ if (!ssl_load_ciphers(ret))
+ goto err2;
+ /* initialise sig algs */
+ if (!ssl_setup_sig_algs(ret))
+ goto err2;
+
+
+ if (!ssl_load_groups(ret))
+ goto err2;
+
+ if (!SSL_CTX_set_ciphersuites(ret, OSSL_default_ciphersuites()))
goto err;
- if (!ssl_create_cipher_list(ret->method,
+ if (!ssl_create_cipher_list(ret,
ret->tls13_ciphersuites,
&ret->cipher_list, &ret->cipher_list_by_id,
- SSL_DEFAULT_CIPHER_LIST, ret->cert)
+ OSSL_default_cipher_list(), ret->cert)
|| sk_SSL_CIPHER_num(ret->cipher_list) <= 0) {
- SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_LIBRARY_HAS_NO_CIPHERS);
+ ERR_raise(ERR_LIB_SSL, SSL_R_LIBRARY_HAS_NO_CIPHERS);
goto err2;
}
@@ -3096,14 +3295,12 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
if (ret->param == NULL)
goto err;
- if ((ret->md5 = EVP_get_digestbyname("ssl3-md5")) == NULL) {
- SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES);
- goto err2;
- }
- if ((ret->sha1 = EVP_get_digestbyname("ssl3-sha1")) == NULL) {
- SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES);
- goto err2;
- }
+ /*
+ * If these aren't available from the provider we'll get NULL returns.
+ * That's fine but will cause errors later if SSLv3 is negotiated
+ */
+ ret->md5 = ssl_evp_md_fetch(libctx, NID_md5, propq);
+ ret->sha1 = ssl_evp_md_fetch(libctx, NID_sha1, propq);
if ((ret->ca_names = sk_X509_NAME_new_null()) == NULL)
goto err;
@@ -3125,20 +3322,20 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
ret->split_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
/* Setup RFC5077 ticket keys */
- if ((RAND_bytes(ret->ext.tick_key_name,
- sizeof(ret->ext.tick_key_name)) <= 0)
- || (RAND_priv_bytes(ret->ext.secure->tick_hmac_key,
- sizeof(ret->ext.secure->tick_hmac_key)) <= 0)
- || (RAND_priv_bytes(ret->ext.secure->tick_aes_key,
- sizeof(ret->ext.secure->tick_aes_key)) <= 0))
+ if ((RAND_bytes_ex(libctx, ret->ext.tick_key_name,
+ sizeof(ret->ext.tick_key_name), 0) <= 0)
+ || (RAND_priv_bytes_ex(libctx, ret->ext.secure->tick_hmac_key,
+ sizeof(ret->ext.secure->tick_hmac_key), 0) <= 0)
+ || (RAND_priv_bytes_ex(libctx, ret->ext.secure->tick_aes_key,
+ sizeof(ret->ext.secure->tick_aes_key), 0) <= 0))
ret->options |= SSL_OP_NO_TICKET;
- if (RAND_priv_bytes(ret->ext.cookie_hmac_key,
- sizeof(ret->ext.cookie_hmac_key)) <= 0)
+ if (RAND_priv_bytes_ex(libctx, ret->ext.cookie_hmac_key,
+ sizeof(ret->ext.cookie_hmac_key), 0) <= 0)
goto err;
#ifndef OPENSSL_NO_SRP
- if (!SSL_CTX_SRP_CTX_init(ret))
+ if (!ssl_ctx_srp_ctx_init_intern(ret))
goto err;
#endif
#ifndef OPENSSL_NO_ENGINE
@@ -3160,11 +3357,6 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
# endif
#endif
/*
- * Default is to connect to non-RI servers. When RI is more widely
- * deployed might change this.
- */
- ret->options |= SSL_OP_LEGACY_SERVER_CONNECT;
- /*
* Disable compression by default to prevent CRIME. Applications can
* re-enable compression by configuring
* SSL_CTX_clear_options(ctx, SSL_OP_NO_COMPRESSION);
@@ -3211,12 +3403,17 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
return ret;
err:
- SSLerr(SSL_F_SSL_CTX_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
err2:
SSL_CTX_free(ret);
return NULL;
}
+SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
+{
+ return SSL_CTX_new_ex(NULL, NULL, meth);
+}
+
int SSL_CTX_up_ref(SSL_CTX *ctx)
{
int i;
@@ -3232,6 +3429,7 @@ int SSL_CTX_up_ref(SSL_CTX *ctx)
void SSL_CTX_free(SSL_CTX *a)
{
int i;
+ size_t j;
if (a == NULL)
return;
@@ -3275,20 +3473,40 @@ void SSL_CTX_free(SSL_CTX *a)
sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles);
#endif
#ifndef OPENSSL_NO_SRP
- SSL_CTX_SRP_CTX_free(a);
+ ssl_ctx_srp_ctx_free_intern(a);
#endif
#ifndef OPENSSL_NO_ENGINE
- ENGINE_finish(a->client_cert_engine);
+ tls_engine_finish(a->client_cert_engine);
#endif
-#ifndef OPENSSL_NO_EC
OPENSSL_free(a->ext.ecpointformats);
OPENSSL_free(a->ext.supportedgroups);
-#endif
+ OPENSSL_free(a->ext.supported_groups_default);
OPENSSL_free(a->ext.alpn);
OPENSSL_secure_free(a->ext.secure);
+ ssl_evp_md_free(a->md5);
+ ssl_evp_md_free(a->sha1);
+
+ for (j = 0; j < SSL_ENC_NUM_IDX; j++)
+ ssl_evp_cipher_free(a->ssl_cipher_methods[j]);
+ for (j = 0; j < SSL_MD_NUM_IDX; j++)
+ ssl_evp_md_free(a->ssl_digest_methods[j]);
+ for (j = 0; j < a->group_list_len; j++) {
+ OPENSSL_free(a->group_list[j].tlsname);
+ OPENSSL_free(a->group_list[j].realname);
+ OPENSSL_free(a->group_list[j].algorithm);
+ }
+ OPENSSL_free(a->group_list);
+
+ OPENSSL_free(a->sigalg_lookup_cache);
+
CRYPTO_THREAD_lock_free(a->lock);
+#ifdef TSAN_REQUIRES_LOCKING
+ CRYPTO_THREAD_lock_free(a->tsan_lock);
+#endif
+
+ OPENSSL_free(a->propq);
OPENSSL_free(a);
}
@@ -3366,42 +3584,35 @@ void SSL_set_cert_cb(SSL *s, int (*cb) (SSL *ssl, void *arg), void *arg)
void ssl_set_masks(SSL *s)
{
CERT *c = s->cert;
- uint32_t *pvalid = s->s3->tmp.valid_flags;
+ uint32_t *pvalid = s->s3.tmp.valid_flags;
int rsa_enc, rsa_sign, dh_tmp, dsa_sign;
unsigned long mask_k, mask_a;
-#ifndef OPENSSL_NO_EC
int have_ecc_cert, ecdsa_ok;
-#endif
+
if (c == NULL)
return;
-#ifndef OPENSSL_NO_DH
- dh_tmp = (c->dh_tmp != NULL || c->dh_tmp_cb != NULL || c->dh_tmp_auto);
-#else
- dh_tmp = 0;
-#endif
+ dh_tmp = (c->dh_tmp != NULL
+ || c->dh_tmp_cb != NULL
+ || c->dh_tmp_auto);
rsa_enc = pvalid[SSL_PKEY_RSA] & CERT_PKEY_VALID;
rsa_sign = pvalid[SSL_PKEY_RSA] & CERT_PKEY_VALID;
dsa_sign = pvalid[SSL_PKEY_DSA_SIGN] & CERT_PKEY_VALID;
-#ifndef OPENSSL_NO_EC
have_ecc_cert = pvalid[SSL_PKEY_ECC] & CERT_PKEY_VALID;
-#endif
mask_k = 0;
mask_a = 0;
-#ifdef CIPHER_DEBUG
- fprintf(stderr, "dht=%d re=%d rs=%d ds=%d\n",
- dh_tmp, rsa_enc, rsa_sign, dsa_sign);
-#endif
+ OSSL_TRACE4(TLS_CIPHER, "dh_tmp=%d rsa_enc=%d rsa_sign=%d dsa_sign=%d\n",
+ dh_tmp, rsa_enc, rsa_sign, dsa_sign);
#ifndef OPENSSL_NO_GOST
if (ssl_has_cert(s, SSL_PKEY_GOST12_512)) {
- mask_k |= SSL_kGOST;
+ mask_k |= SSL_kGOST | SSL_kGOST18;
mask_a |= SSL_aGOST12;
}
if (ssl_has_cert(s, SSL_PKEY_GOST12_256)) {
- mask_k |= SSL_kGOST;
+ mask_k |= SSL_kGOST | SSL_kGOST18;
mask_a |= SSL_aGOST12;
}
if (ssl_has_cert(s, SSL_PKEY_GOST01)) {
@@ -3436,7 +3647,6 @@ void ssl_set_masks(SSL *s)
* An ECC certificate may be usable for ECDH and/or ECDSA cipher suites
* depending on the key usage extension.
*/
-#ifndef OPENSSL_NO_EC
if (have_ecc_cert) {
uint32_t ex_kusage;
ex_kusage = X509_get_key_usage(c->pkeys[SSL_PKEY_ECC].x509);
@@ -3457,11 +3667,8 @@ void ssl_set_masks(SSL *s)
&& pvalid[SSL_PKEY_ED448] & CERT_PKEY_EXPLICIT_SIGN
&& TLS1_get_version(s) == TLS1_2_VERSION)
mask_a |= SSL_aECDSA;
-#endif
-#ifndef OPENSSL_NO_EC
mask_k |= SSL_kECDHE;
-#endif
#ifndef OPENSSL_NO_PSK
mask_k |= SSL_kPSK;
@@ -3474,31 +3681,26 @@ void ssl_set_masks(SSL *s)
mask_k |= SSL_kECDHEPSK;
#endif
- s->s3->tmp.mask_k = mask_k;
- s->s3->tmp.mask_a = mask_a;
+ s->s3.tmp.mask_k = mask_k;
+ s->s3.tmp.mask_a = mask_a;
}
-#ifndef OPENSSL_NO_EC
-
int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s)
{
- if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aECDSA) {
+ if (s->s3.tmp.new_cipher->algorithm_auth & SSL_aECDSA) {
/* key usage, if present, must allow signing */
if (!(X509_get_key_usage(x) & X509v3_KU_DIGITAL_SIGNATURE)) {
- SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG,
- SSL_R_ECC_CERT_NOT_FOR_SIGNING);
+ ERR_raise(ERR_LIB_SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
return 0;
}
}
return 1; /* all checks are ok */
}
-#endif
-
int ssl_get_server_cert_serverinfo(SSL *s, const unsigned char **serverinfo,
size_t *serverinfo_length)
{
- CERT_PKEY *cpk = s->s3->tmp.cert;
+ CERT_PKEY *cpk = s->s3.tmp.cert;
*serverinfo_length = 0;
if (cpk == NULL || cpk->serverinfo == NULL)
@@ -3571,11 +3773,12 @@ void ssl_update_cache(SSL *s, int mode)
/* auto flush every 255 connections */
if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) {
TSAN_QUALIFIER int *stat;
+
if (mode & SSL_SESS_CACHE_CLIENT)
stat = &s->session_ctx->stats.sess_connect_good;
else
stat = &s->session_ctx->stats.sess_accept_good;
- if ((tsan_load(stat) & 0xff) == 0xff)
+ if ((ssl_tsan_load(s->session_ctx, stat) & 0xff) == 0xff)
SSL_CTX_flush_sessions(s->session_ctx, (unsigned long)time(NULL));
}
}
@@ -3682,6 +3885,8 @@ int SSL_get_error(const SSL *s, int i)
}
if (SSL_want_x509_lookup(s))
return SSL_ERROR_WANT_X509_LOOKUP;
+ if (SSL_want_retry_verify(s))
+ return SSL_ERROR_WANT_RETRY_VERIFY;
if (SSL_want_async(s))
return SSL_ERROR_WANT_ASYNC;
if (SSL_want_async_job(s))
@@ -3690,7 +3895,7 @@ int SSL_get_error(const SSL *s, int i)
return SSL_ERROR_WANT_CLIENT_HELLO_CB;
if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) &&
- (s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY))
+ (s->s3.warn_alert == SSL_AD_CLOSE_NOTIFY))
return SSL_ERROR_ZERO_RETURN;
return SSL_ERROR_SYSCALL;
@@ -3712,7 +3917,7 @@ int SSL_do_handshake(SSL *s)
int ret = 1;
if (s->handshake_func == NULL) {
- SSLerr(SSL_F_SSL_DO_HANDSHAKE, SSL_R_CONNECTION_TYPE_NOT_SET);
+ ERR_raise(ERR_LIB_SSL, SSL_R_CONNECTION_TYPE_NOT_SET);
return -1;
}
@@ -3755,14 +3960,13 @@ void SSL_set_connect_state(SSL *s)
int ssl_undefined_function(SSL *s)
{
- SSLerr(SSL_F_SSL_UNDEFINED_FUNCTION, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
int ssl_undefined_void_function(void)
{
- SSLerr(SSL_F_SSL_UNDEFINED_VOID_FUNCTION,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
@@ -3773,7 +3977,7 @@ int ssl_undefined_const_function(const SSL *s)
const SSL_METHOD *ssl_bad_method(int ver)
{
- SSLerr(SSL_F_SSL_BAD_METHOD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return NULL;
}
@@ -4008,7 +4212,7 @@ const SSL_CIPHER *SSL_get_current_cipher(const SSL *s)
const SSL_CIPHER *SSL_get_pending_cipher(const SSL *s)
{
- return s->s3->tmp.new_cipher;
+ return s->s3.tmp.new_cipher;
}
const COMP_METHOD *SSL_get_current_compression(const SSL *s)
@@ -4039,9 +4243,9 @@ int ssl_init_wbio_buffer(SSL *s)
}
bbio = BIO_new(BIO_f_buffer());
- if (bbio == NULL || !BIO_set_read_buffer_size(bbio, 1)) {
+ if (bbio == NULL || BIO_set_read_buffer_size(bbio, 1) <= 0) {
BIO_free(bbio);
- SSLerr(SSL_F_SSL_INIT_WBIO_BUFFER, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB);
return 0;
}
s->bbio = bbio;
@@ -4157,7 +4361,8 @@ SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx)
int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx)
{
- return X509_STORE_set_default_paths(ctx->cert_store);
+ return X509_STORE_set_default_paths_ex(ctx->cert_store, ctx->libctx,
+ ctx->propq);
}
int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx)
@@ -4167,10 +4372,13 @@ int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx)
lookup = X509_STORE_add_lookup(ctx->cert_store, X509_LOOKUP_hash_dir());
if (lookup == NULL)
return 0;
+
+ /* We ignore errors, in case the directory doesn't exist */
+ ERR_set_mark();
+
X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
- /* Clear any errors if the default directory does not exist */
- ERR_clear_error();
+ ERR_pop_to_mark();
return 1;
}
@@ -4183,18 +4391,62 @@ int SSL_CTX_set_default_verify_file(SSL_CTX *ctx)
if (lookup == NULL)
return 0;
- X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
+ /* We ignore errors, in case the file doesn't exist */
+ ERR_set_mark();
- /* Clear any errors if the default file does not exist */
- ERR_clear_error();
+ X509_LOOKUP_load_file_ex(lookup, NULL, X509_FILETYPE_DEFAULT, ctx->libctx,
+ ctx->propq);
+
+ ERR_pop_to_mark();
return 1;
}
+int SSL_CTX_set_default_verify_store(SSL_CTX *ctx)
+{
+ X509_LOOKUP *lookup;
+
+ lookup = X509_STORE_add_lookup(ctx->cert_store, X509_LOOKUP_store());
+ if (lookup == NULL)
+ return 0;
+
+ /* We ignore errors, in case the directory doesn't exist */
+ ERR_set_mark();
+
+ X509_LOOKUP_add_store_ex(lookup, NULL, ctx->libctx, ctx->propq);
+
+ ERR_pop_to_mark();
+
+ return 1;
+}
+
+int SSL_CTX_load_verify_file(SSL_CTX *ctx, const char *CAfile)
+{
+ return X509_STORE_load_file_ex(ctx->cert_store, CAfile, ctx->libctx,
+ ctx->propq);
+}
+
+int SSL_CTX_load_verify_dir(SSL_CTX *ctx, const char *CApath)
+{
+ return X509_STORE_load_path(ctx->cert_store, CApath);
+}
+
+int SSL_CTX_load_verify_store(SSL_CTX *ctx, const char *CAstore)
+{
+ return X509_STORE_load_store_ex(ctx->cert_store, CAstore, ctx->libctx,
+ ctx->propq);
+}
+
int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
const char *CApath)
{
- return X509_STORE_load_locations(ctx->cert_store, CAfile, CApath);
+ if (CAfile == NULL && CApath == NULL)
+ return 0;
+ if (CAfile != NULL && !SSL_CTX_load_verify_file(ctx, CAfile))
+ return 0;
+ if (CApath != NULL && !SSL_CTX_load_verify_dir(ctx, CApath))
+ return 0;
+ return 1;
}
void SSL_set_info_callback(SSL *ssl,
@@ -4226,20 +4478,20 @@ long SSL_get_verify_result(const SSL *ssl)
size_t SSL_get_client_random(const SSL *ssl, unsigned char *out, size_t outlen)
{
if (outlen == 0)
- return sizeof(ssl->s3->client_random);
- if (outlen > sizeof(ssl->s3->client_random))
- outlen = sizeof(ssl->s3->client_random);
- memcpy(out, ssl->s3->client_random, outlen);
+ return sizeof(ssl->s3.client_random);
+ if (outlen > sizeof(ssl->s3.client_random))
+ outlen = sizeof(ssl->s3.client_random);
+ memcpy(out, ssl->s3.client_random, outlen);
return outlen;
}
size_t SSL_get_server_random(const SSL *ssl, unsigned char *out, size_t outlen)
{
if (outlen == 0)
- return sizeof(ssl->s3->server_random);
- if (outlen > sizeof(ssl->s3->server_random))
- outlen = sizeof(ssl->s3->server_random);
- memcpy(out, ssl->s3->server_random, outlen);
+ return sizeof(ssl->s3.server_random);
+ if (outlen > sizeof(ssl->s3.server_random))
+ outlen = sizeof(ssl->s3.server_random);
+ memcpy(out, ssl->s3.server_random, outlen);
return outlen;
}
@@ -4309,32 +4561,11 @@ int SSL_want(const SSL *s)
return s->rwstate;
}
-/**
- * \brief Set the callback for generating temporary DH keys.
- * \param ctx the SSL context.
- * \param dh the callback
- */
-
-#ifndef OPENSSL_NO_DH
-void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
- DH *(*dh) (SSL *ssl, int is_export,
- int keylength))
-{
- SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TMP_DH_CB, (void (*)(void))dh);
-}
-
-void SSL_set_tmp_dh_callback(SSL *ssl, DH *(*dh) (SSL *ssl, int is_export,
- int keylength))
-{
- SSL_callback_ctrl(ssl, SSL_CTRL_SET_TMP_DH_CB, (void (*)(void))dh);
-}
-#endif
-
#ifndef OPENSSL_NO_PSK
int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint)
{
if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) {
- SSLerr(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
+ ERR_raise(ERR_LIB_SSL, SSL_R_DATA_LENGTH_TOO_LONG);
return 0;
}
OPENSSL_free(ctx->cert->psk_identity_hint);
@@ -4353,7 +4584,7 @@ int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint)
return 0;
if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) {
- SSLerr(SSL_F_SSL_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
+ ERR_raise(ERR_LIB_SSL, SSL_R_DATA_LENGTH_TOO_LONG);
return 0;
}
OPENSSL_free(s->cert->psk_identity_hint);
@@ -4485,11 +4716,18 @@ int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size)
return 1;
}
-void SSL_set_record_padding_callback(SSL *ssl,
+int SSL_set_record_padding_callback(SSL *ssl,
size_t (*cb) (SSL *ssl, int type,
size_t len, void *arg))
{
- ssl->record_padding_cb = cb;
+ BIO *b;
+
+ b = SSL_get_wbio(ssl);
+ if (b == NULL || !BIO_get_ktls_send(b)) {
+ ssl->record_padding_cb = cb;
+ return 1;
+ }
+ return 0;
}
void SSL_set_record_padding_callback_arg(SSL *ssl, void *arg)
@@ -4569,27 +4807,24 @@ int ssl_handshake_hash(SSL *s, unsigned char *out, size_t outlen,
size_t *hashlen)
{
EVP_MD_CTX *ctx = NULL;
- EVP_MD_CTX *hdgst = s->s3->handshake_dgst;
- int hashleni = EVP_MD_CTX_size(hdgst);
+ EVP_MD_CTX *hdgst = s->s3.handshake_dgst;
+ int hashleni = EVP_MD_CTX_get_size(hdgst);
int ret = 0;
if (hashleni < 0 || (size_t)hashleni > outlen) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_HANDSHAKE_HASH,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
ctx = EVP_MD_CTX_new();
if (ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_HANDSHAKE_HASH,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (!EVP_MD_CTX_copy_ex(ctx, hdgst)
|| EVP_DigestFinal_ex(ctx, out, NULL) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_HANDSHAKE_HASH,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -4611,7 +4846,7 @@ int SSL_is_server(const SSL *s)
return s->server;
}
-#if OPENSSL_API_COMPAT < 0x10100000L
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
void SSL_set_debug(SSL *s, int debug)
{
/* Old function was do-nothing anyway... */
@@ -4692,37 +4927,32 @@ void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx)
return ctx->cert->sec_ex;
}
-/*
- * Get/Set/Clear options in SSL_CTX or SSL, formerly macros, now functions that
- * can return unsigned long, instead of the generic long return value from the
- * control interface.
- */
-unsigned long SSL_CTX_get_options(const SSL_CTX *ctx)
+uint64_t SSL_CTX_get_options(const SSL_CTX *ctx)
{
return ctx->options;
}
-unsigned long SSL_get_options(const SSL *s)
+uint64_t SSL_get_options(const SSL *s)
{
return s->options;
}
-unsigned long SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op)
+uint64_t SSL_CTX_set_options(SSL_CTX *ctx, uint64_t op)
{
return ctx->options |= op;
}
-unsigned long SSL_set_options(SSL *s, unsigned long op)
+uint64_t SSL_set_options(SSL *s, uint64_t op)
{
return s->options |= op;
}
-unsigned long SSL_CTX_clear_options(SSL_CTX *ctx, unsigned long op)
+uint64_t SSL_CTX_clear_options(SSL_CTX *ctx, uint64_t op)
{
return ctx->options &= ~op;
}
-unsigned long SSL_clear_options(SSL *s, unsigned long op)
+uint64_t SSL_clear_options(SSL *s, uint64_t op)
{
return s->options &= ~op;
}
@@ -4752,7 +4982,7 @@ static int ct_move_scts(STACK_OF(SCT) **dst, STACK_OF(SCT) *src,
if (*dst == NULL) {
*dst = sk_SCT_new_null();
if (*dst == NULL) {
- SSLerr(SSL_F_CT_MOVE_SCTS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -4909,7 +5139,7 @@ static int ct_strict(const CT_POLICY_EVAL_CTX * ctx,
if (status == SCT_VALIDATION_STATUS_VALID)
return 1;
}
- SSLerr(SSL_F_CT_STRICT, SSL_R_NO_VALID_SCTS);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_VALID_SCTS);
return 0;
}
@@ -4923,8 +5153,7 @@ int SSL_set_ct_validation_callback(SSL *s, ssl_ct_validation_cb callback,
if (callback != NULL && SSL_CTX_has_client_custom_ext(s->ctx,
TLSEXT_TYPE_signed_certificate_timestamp))
{
- SSLerr(SSL_F_SSL_SET_CT_VALIDATION_CALLBACK,
- SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED);
return 0;
}
@@ -4952,8 +5181,7 @@ int SSL_CTX_set_ct_validation_callback(SSL_CTX *ctx,
if (callback != NULL && SSL_CTX_has_client_custom_ext(ctx,
TLSEXT_TYPE_signed_certificate_timestamp))
{
- SSLerr(SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK,
- SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED);
return 0;
}
@@ -5009,10 +5237,9 @@ int ssl_validate_ct(SSL *s)
}
}
- ctx = CT_POLICY_EVAL_CTX_new();
+ ctx = CT_POLICY_EVAL_CTX_new_ex(s->ctx->libctx, s->ctx->propq);
if (ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_VALIDATE_CT,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto end;
}
@@ -5040,8 +5267,7 @@ int ssl_validate_ct(SSL *s)
* ought to correspond to an inability to carry out its duties.
*/
if (SCT_LIST_validate(scts, ctx) < 0) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_SSL_VALIDATE_CT,
- SSL_R_SCT_VERIFICATION_FAILED);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_SCT_VERIFICATION_FAILED);
goto end;
}
@@ -5049,8 +5275,7 @@ int ssl_validate_ct(SSL *s)
if (ret < 0)
ret = 0; /* This function returns 0 on failure */
if (!ret)
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_SSL_VALIDATE_CT,
- SSL_R_CALLBACK_FAILED);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_CALLBACK_FAILED);
end:
CT_POLICY_EVAL_CTX_free(ctx);
@@ -5078,7 +5303,7 @@ int SSL_CTX_enable_ct(SSL_CTX *ctx, int validation_mode)
{
switch (validation_mode) {
default:
- SSLerr(SSL_F_SSL_CTX_ENABLE_CT, SSL_R_INVALID_CT_VALIDATION_TYPE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_CT_VALIDATION_TYPE);
return 0;
case SSL_CT_VALIDATION_PERMISSIVE:
return SSL_CTX_set_ct_validation_callback(ctx, ct_permissive, NULL);
@@ -5091,7 +5316,7 @@ int SSL_enable_ct(SSL *s, int validation_mode)
{
switch (validation_mode) {
default:
- SSLerr(SSL_F_SSL_ENABLE_CT, SSL_R_INVALID_CT_VALIDATION_TYPE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_CT_VALIDATION_TYPE);
return 0;
case SSL_CT_VALIDATION_PERMISSIVE:
return SSL_set_ct_validation_callback(s, ct_permissive, NULL);
@@ -5199,8 +5424,7 @@ int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen)
return 1;
}
if ((present = OPENSSL_malloc(sizeof(*present) * num)) == NULL) {
- SSLerr(SSL_F_SSL_CLIENT_HELLO_GET1_EXTENSIONS_PRESENT,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
for (i = 0; i < s->clienthello->pre_proc_exts_len; i++) {
@@ -5293,8 +5517,7 @@ static int nss_keylog_int(const char *prefix,
prefix_len = strlen(prefix);
out_len = prefix_len + (2 * parameter_1_len) + (2 * parameter_2_len) + 3;
if ((out = cursor = OPENSSL_malloc(out_len)) == NULL) {
- SSLfatal(ssl, SSL_AD_INTERNAL_ERROR, SSL_F_NSS_KEYLOG_INT,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(ssl, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -5327,8 +5550,7 @@ int ssl_log_rsa_client_key_exchange(SSL *ssl,
size_t premaster_len)
{
if (encrypted_premaster_len < 8) {
- SSLfatal(ssl, SSL_AD_INTERNAL_ERROR,
- SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ SSLfatal(ssl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -5348,7 +5570,7 @@ int ssl_log_secret(SSL *ssl,
{
return nss_keylog_int(label,
ssl,
- ssl->s3->client_random,
+ ssl->s3.client_random,
SSL3_RANDOM_SIZE,
secret,
secret_len);
@@ -5363,20 +5585,18 @@ int ssl_cache_cipherlist(SSL *s, PACKET *cipher_suites, int sslv2format)
n = sslv2format ? SSLV2_CIPHER_LEN : TLS_CIPHER_LEN;
if (PACKET_remaining(cipher_suites) == 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL_CACHE_CIPHERLIST,
- SSL_R_NO_CIPHERS_SPECIFIED);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_NO_CIPHERS_SPECIFIED);
return 0;
}
if (PACKET_remaining(cipher_suites) % n != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_CACHE_CIPHERLIST,
- SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
return 0;
}
- OPENSSL_free(s->s3->tmp.ciphers_raw);
- s->s3->tmp.ciphers_raw = NULL;
- s->s3->tmp.ciphers_rawlen = 0;
+ OPENSSL_free(s->s3.tmp.ciphers_raw);
+ s->s3.tmp.ciphers_raw = NULL;
+ s->s3.tmp.ciphers_rawlen = 0;
if (sslv2format) {
size_t numciphers = PACKET_remaining(cipher_suites) / n;
@@ -5392,13 +5612,12 @@ int ssl_cache_cipherlist(SSL *s, PACKET *cipher_suites, int sslv2format)
* problem.
*/
raw = OPENSSL_malloc(numciphers * TLS_CIPHER_LEN);
- s->s3->tmp.ciphers_raw = raw;
+ s->s3.tmp.ciphers_raw = raw;
if (raw == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CACHE_CIPHERLIST,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
- for (s->s3->tmp.ciphers_rawlen = 0;
+ for (s->s3.tmp.ciphers_rawlen = 0;
PACKET_remaining(&sslv2ciphers) > 0;
raw += TLS_CIPHER_LEN) {
if (!PACKET_get_1(&sslv2ciphers, &leadbyte)
@@ -5407,20 +5626,18 @@ int ssl_cache_cipherlist(SSL *s, PACKET *cipher_suites, int sslv2format)
TLS_CIPHER_LEN))
|| (leadbyte != 0
&& !PACKET_forward(&sslv2ciphers, TLS_CIPHER_LEN))) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_CACHE_CIPHERLIST,
- SSL_R_BAD_PACKET);
- OPENSSL_free(s->s3->tmp.ciphers_raw);
- s->s3->tmp.ciphers_raw = NULL;
- s->s3->tmp.ciphers_rawlen = 0;
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_PACKET);
+ OPENSSL_free(s->s3.tmp.ciphers_raw);
+ s->s3.tmp.ciphers_raw = NULL;
+ s->s3.tmp.ciphers_rawlen = 0;
return 0;
}
if (leadbyte == 0)
- s->s3->tmp.ciphers_rawlen += TLS_CIPHER_LEN;
+ s->s3.tmp.ciphers_rawlen += TLS_CIPHER_LEN;
}
- } else if (!PACKET_memdup(cipher_suites, &s->s3->tmp.ciphers_raw,
- &s->s3->tmp.ciphers_rawlen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CACHE_CIPHERLIST,
- ERR_R_INTERNAL_ERROR);
+ } else if (!PACKET_memdup(cipher_suites, &s->s3.tmp.ciphers_raw,
+ &s->s3.tmp.ciphers_rawlen)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
@@ -5453,20 +5670,18 @@ int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites,
if (PACKET_remaining(cipher_suites) == 0) {
if (fatal)
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_BYTES_TO_CIPHER_LIST,
- SSL_R_NO_CIPHERS_SPECIFIED);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_NO_CIPHERS_SPECIFIED);
else
- SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, SSL_R_NO_CIPHERS_SPECIFIED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_CIPHERS_SPECIFIED);
return 0;
}
if (PACKET_remaining(cipher_suites) % n != 0) {
if (fatal)
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_BYTES_TO_CIPHER_LIST,
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
else
- SSLerr(SSL_F_BYTES_TO_CIPHER_LIST,
- SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
+ ERR_raise(ERR_LIB_SSL, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
return 0;
}
@@ -5474,10 +5689,9 @@ int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites,
scsvs = sk_SSL_CIPHER_new_null();
if (sk == NULL || scsvs == NULL) {
if (fatal)
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_BYTES_TO_CIPHER_LIST,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
else
- SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -5496,20 +5710,18 @@ int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites,
if ((c->valid && !sk_SSL_CIPHER_push(sk, c)) ||
(!c->valid && !sk_SSL_CIPHER_push(scsvs, c))) {
if (fatal)
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
else
- SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
}
}
if (PACKET_remaining(cipher_suites) > 0) {
if (fatal)
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_BYTES_TO_CIPHER_LIST,
- SSL_R_BAD_LENGTH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_LENGTH);
else
- SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, SSL_R_BAD_LENGTH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_LENGTH);
goto err;
}
@@ -5611,9 +5823,9 @@ int SSL_stateless(SSL *s)
ERR_clear_error();
- s->s3->flags |= TLS1_FLAGS_STATELESS;
+ s->s3.flags |= TLS1_FLAGS_STATELESS;
ret = SSL_accept(s);
- s->s3->flags &= ~TLS1_FLAGS_STATELESS;
+ s->s3.flags &= ~TLS1_FLAGS_STATELESS;
if (ret > 0 && s->ext.cookieok)
return 1;
@@ -5637,34 +5849,34 @@ void SSL_set_post_handshake_auth(SSL *ssl, int val)
int SSL_verify_client_post_handshake(SSL *ssl)
{
if (!SSL_IS_TLS13(ssl)) {
- SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_WRONG_SSL_VERSION);
+ ERR_raise(ERR_LIB_SSL, SSL_R_WRONG_SSL_VERSION);
return 0;
}
if (!ssl->server) {
- SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_NOT_SERVER);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NOT_SERVER);
return 0;
}
if (!SSL_is_init_finished(ssl)) {
- SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_STILL_IN_INIT);
+ ERR_raise(ERR_LIB_SSL, SSL_R_STILL_IN_INIT);
return 0;
}
switch (ssl->post_handshake_auth) {
case SSL_PHA_NONE:
- SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_EXTENSION_NOT_RECEIVED);
+ ERR_raise(ERR_LIB_SSL, SSL_R_EXTENSION_NOT_RECEIVED);
return 0;
default:
case SSL_PHA_EXT_SENT:
- SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return 0;
case SSL_PHA_EXT_RECEIVED:
break;
case SSL_PHA_REQUEST_PENDING:
- SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_REQUEST_PENDING);
+ ERR_raise(ERR_LIB_SSL, SSL_R_REQUEST_PENDING);
return 0;
case SSL_PHA_REQUESTED:
- SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_REQUEST_SENT);
+ ERR_raise(ERR_LIB_SSL, SSL_R_REQUEST_SENT);
return 0;
}
@@ -5673,7 +5885,7 @@ int SSL_verify_client_post_handshake(SSL *ssl)
/* checks verify_mode and algorithm_auth */
if (!send_certificate_request(ssl)) {
ssl->post_handshake_auth = SSL_PHA_EXT_RECEIVED; /* restore on error */
- SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_INVALID_CONFIG);
+ ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_CONFIG);
return 0;
}
@@ -5707,3 +5919,119 @@ void SSL_set_allow_early_data_cb(SSL *s,
s->allow_early_data_cb = cb;
s->allow_early_data_cb_data = arg;
}
+
+const EVP_CIPHER *ssl_evp_cipher_fetch(OSSL_LIB_CTX *libctx,
+ int nid,
+ const char *properties)
+{
+ const EVP_CIPHER *ciph;
+
+ ciph = tls_get_cipher_from_engine(nid);
+ if (ciph != NULL)
+ return ciph;
+
+ /*
+ * If there is no engine cipher then we do an explicit fetch. This may fail
+ * and that could be ok
+ */
+ ERR_set_mark();
+ ciph = EVP_CIPHER_fetch(libctx, OBJ_nid2sn(nid), properties);
+ ERR_pop_to_mark();
+ return ciph;
+}
+
+
+int ssl_evp_cipher_up_ref(const EVP_CIPHER *cipher)
+{
+ /* Don't up-ref an implicit EVP_CIPHER */
+ if (EVP_CIPHER_get0_provider(cipher) == NULL)
+ return 1;
+
+ /*
+ * The cipher was explicitly fetched and therefore it is safe to cast
+ * away the const
+ */
+ return EVP_CIPHER_up_ref((EVP_CIPHER *)cipher);
+}
+
+void ssl_evp_cipher_free(const EVP_CIPHER *cipher)
+{
+ if (cipher == NULL)
+ return;
+
+ if (EVP_CIPHER_get0_provider(cipher) != NULL) {
+ /*
+ * The cipher was explicitly fetched and therefore it is safe to cast
+ * away the const
+ */
+ EVP_CIPHER_free((EVP_CIPHER *)cipher);
+ }
+}
+
+const EVP_MD *ssl_evp_md_fetch(OSSL_LIB_CTX *libctx,
+ int nid,
+ const char *properties)
+{
+ const EVP_MD *md;
+
+ md = tls_get_digest_from_engine(nid);
+ if (md != NULL)
+ return md;
+
+ /* Otherwise we do an explicit fetch */
+ ERR_set_mark();
+ md = EVP_MD_fetch(libctx, OBJ_nid2sn(nid), properties);
+ ERR_pop_to_mark();
+ return md;
+}
+
+int ssl_evp_md_up_ref(const EVP_MD *md)
+{
+ /* Don't up-ref an implicit EVP_MD */
+ if (EVP_MD_get0_provider(md) == NULL)
+ return 1;
+
+ /*
+ * The digest was explicitly fetched and therefore it is safe to cast
+ * away the const
+ */
+ return EVP_MD_up_ref((EVP_MD *)md);
+}
+
+void ssl_evp_md_free(const EVP_MD *md)
+{
+ if (md == NULL)
+ return;
+
+ if (EVP_MD_get0_provider(md) != NULL) {
+ /*
+ * The digest was explicitly fetched and therefore it is safe to cast
+ * away the const
+ */
+ EVP_MD_free((EVP_MD *)md);
+ }
+}
+
+int SSL_set0_tmp_dh_pkey(SSL *s, EVP_PKEY *dhpkey)
+{
+ if (!ssl_security(s, SSL_SECOP_TMP_DH,
+ EVP_PKEY_get_security_bits(dhpkey), 0, dhpkey)) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_DH_KEY_TOO_SMALL);
+ return 0;
+ }
+ EVP_PKEY_free(s->cert->dh_tmp);
+ s->cert->dh_tmp = dhpkey;
+ return 1;
+}
+
+int SSL_CTX_set0_tmp_dh_pkey(SSL_CTX *ctx, EVP_PKEY *dhpkey)
+{
+ if (!ssl_ctx_security(ctx, SSL_SECOP_TMP_DH,
+ EVP_PKEY_get_security_bits(dhpkey), 0, dhpkey)) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_DH_KEY_TOO_SMALL);
+ return 0;
+ }
+ EVP_PKEY_free(ctx->cert->dh_tmp);
+ ctx->cert->dh_tmp = dhpkey;
+ return 1;
+}
diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h
index 5c7921542310..5fb1feb80163 100644
--- a/ssl/ssl_local.h
+++ b/ssl/ssl_local.h
@@ -3,7 +3,7 @@
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -21,7 +21,6 @@
# include <openssl/buffer.h>
# include <openssl/comp.h>
# include <openssl/bio.h>
-# include <openssl/rsa.h>
# include <openssl/dsa.h>
# include <openssl/err.h>
# include <openssl/ssl.h>
@@ -30,10 +29,12 @@
# include <openssl/ct.h>
# include "record/record.h"
# include "statem/statem.h"
-# include "packet_local.h"
+# include "internal/packet.h"
# include "internal/dane.h"
# include "internal/refcount.h"
# include "internal/tsan_assist.h"
+# include "internal/bio.h"
+# include "internal/ktls.h"
# ifdef OPENSSL_BUILD_SHLIBSSL
# undef OPENSSL_EXTERN
@@ -130,6 +131,9 @@
(c)[1]=(unsigned char)(((l)>> 8)&0xff), \
(c)[2]=(unsigned char)(((l) )&0xff)),(c)+=3)
+# define TLS_MAX_VERSION_INTERNAL TLS1_3_VERSION
+# define DTLS_MAX_VERSION_INTERNAL DTLS1_2_VERSION
+
/*
* DTLS version numbers are strange because they're inverted. Except for
* DTLS1_BAD_VER, which should be considered "lower" than the rest.
@@ -176,6 +180,8 @@
# define SSL_kRSAPSK 0x00000040U
# define SSL_kECDHEPSK 0x00000080U
# define SSL_kDHEPSK 0x00000100U
+/* GOST KDF key exchange, draft-smyshlyaev-tls12-gost-suites */
+# define SSL_kGOST18 0x00000200U
/* all PSK */
@@ -230,6 +236,8 @@
# define SSL_CHACHA20POLY1305 0x00080000U
# define SSL_ARIA128GCM 0x00100000U
# define SSL_ARIA256GCM 0x00200000U
+# define SSL_MAGMA 0x00400000U
+# define SSL_KUZNYECHIK 0x00800000U
# define SSL_AESGCM (SSL_AES128GCM | SSL_AES256GCM)
# define SSL_AESCCM (SSL_AES128CCM | SSL_AES256CCM | SSL_AES128CCM8 | SSL_AES256CCM8)
@@ -238,6 +246,9 @@
# define SSL_CHACHA20 (SSL_CHACHA20POLY1305)
# define SSL_ARIAGCM (SSL_ARIA128GCM | SSL_ARIA256GCM)
# define SSL_ARIA (SSL_ARIAGCM)
+# define SSL_CBC (SSL_DES | SSL_3DES | SSL_RC2 | SSL_IDEA \
+ | SSL_AES128 | SSL_AES256 | SSL_CAMELLIA128 \
+ | SSL_CAMELLIA256 | SSL_SEED)
/* Bits for algorithm_mac (symmetric authentication) */
@@ -252,6 +263,8 @@
# define SSL_GOST12_256 0x00000080U
# define SSL_GOST89MAC12 0x00000100U
# define SSL_GOST12_512 0x00000200U
+# define SSL_MAGMAOMAC 0x00000400U
+# define SSL_KUZNYECHIKOMAC 0x00000800U
/*
* When adding new digest in the ssl_ciph.c and increment SSL_MD_NUM_IDX make
@@ -270,7 +283,11 @@
# define SSL_MD_MD5_SHA1_IDX 9
# define SSL_MD_SHA224_IDX 10
# define SSL_MD_SHA512_IDX 11
-# define SSL_MAX_DIGEST 12
+# define SSL_MD_MAGMAOMAC_IDX 12
+# define SSL_MD_KUZNYECHIKOMAC_IDX 13
+# define SSL_MAX_DIGEST 14
+
+#define SSL_MD_NUM_IDX SSL_MAX_DIGEST
/* Bits for algorithm2 (handshake digests and other extra flags) */
@@ -299,6 +316,11 @@
* goes into algorithm2)
*/
# define TLS1_STREAM_MAC 0x10000
+/*
+ * TLSTREE cipher/mac key derivation from draft-smyshlyaev-tls12-gost-suites
+ * (currently this also goes into algorithm2)
+ */
+# define TLS1_TLSTREE 0x20000
# define SSL_STRONG_MASK 0x0000001FU
# define SSL_DEFAULT_MASK 0X00000020U
@@ -330,8 +352,8 @@
|| (s)->early_data_state == SSL_EARLY_DATA_WRITE_RETRY \
|| (s)->hello_retry_request == SSL_HRR_PENDING)
-# define SSL_IS_FIRST_HANDSHAKE(S) ((s)->s3->tmp.finish_md_len == 0 \
- || (s)->s3->tmp.peer_finish_md_len == 0)
+# define SSL_IS_FIRST_HANDSHAKE(S) ((s)->s3.tmp.finish_md_len == 0 \
+ || (s)->s3.tmp.peer_finish_md_len == 0)
/* See if we need explicit IV */
# define SSL_USE_EXPLICIT_IV(s) \
@@ -370,8 +392,8 @@
# define GET_MAX_FRAGMENT_LENGTH(session) \
(512U << (session->ext.max_fragment_len_mode - 1))
-# define SSL_READ_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC_READ)
-# define SSL_WRITE_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE)
+# define SSL_READ_ETM(s) (s->s3.flags & TLS1_FLAGS_ENCRYPT_THEN_MAC_READ)
+# define SSL_WRITE_ETM(s) (s->s3.flags & TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE)
/* Mostly for SSLv3 */
# define SSL_PKEY_RSA 0
@@ -385,6 +407,32 @@
# define SSL_PKEY_ED448 8
# define SSL_PKEY_NUM 9
+# define SSL_ENC_DES_IDX 0
+# define SSL_ENC_3DES_IDX 1
+# define SSL_ENC_RC4_IDX 2
+# define SSL_ENC_RC2_IDX 3
+# define SSL_ENC_IDEA_IDX 4
+# define SSL_ENC_NULL_IDX 5
+# define SSL_ENC_AES128_IDX 6
+# define SSL_ENC_AES256_IDX 7
+# define SSL_ENC_CAMELLIA128_IDX 8
+# define SSL_ENC_CAMELLIA256_IDX 9
+# define SSL_ENC_GOST89_IDX 10
+# define SSL_ENC_SEED_IDX 11
+# define SSL_ENC_AES128GCM_IDX 12
+# define SSL_ENC_AES256GCM_IDX 13
+# define SSL_ENC_AES128CCM_IDX 14
+# define SSL_ENC_AES256CCM_IDX 15
+# define SSL_ENC_AES128CCM8_IDX 16
+# define SSL_ENC_AES256CCM8_IDX 17
+# define SSL_ENC_GOST8912_IDX 18
+# define SSL_ENC_CHACHA_IDX 19
+# define SSL_ENC_ARIA128GCM_IDX 20
+# define SSL_ENC_ARIA256GCM_IDX 21
+# define SSL_ENC_MAGMA_IDX 22
+# define SSL_ENC_KUZNYECHIK_IDX 23
+# define SSL_ENC_NUM_IDX 24
+
/*-
* SSL_kRSA <- RSA_ENC
* SSL_kDH <- DH_ENC & (RSA_ENC | RSA_SIGN | DSA_SIGN)
@@ -475,7 +523,7 @@ struct ssl_method_st {
* Matches the length of PSK_MAX_PSK_LEN. We keep it the same value for
* consistency, even in the event of OPENSSL_NO_PSK being defined.
*/
-# define TLS13_MAX_RESUMPTION_PSK_LENGTH 256
+# define TLS13_MAX_RESUMPTION_PSK_LENGTH 512
/*-
* Lets make this into an ASN.1 type structure as follows
@@ -545,12 +593,15 @@ struct ssl_session_st {
*/
long verify_result; /* only for servers */
CRYPTO_REF_COUNT references;
- long timeout;
- long time;
+ time_t timeout;
+ time_t time;
+ time_t calc_timeout;
+ int timeout_ovf;
unsigned int compress_meth; /* Need to lookup the method */
const SSL_CIPHER *cipher;
unsigned long cipher_id; /* when ASN.1 loaded, this needs to be used to
* load the 'cipher' structure */
+ unsigned int kex_group; /* TLS group from key exchange */
CRYPTO_EX_DATA ex_data; /* application specific data */
/*
* These are used to make removal of session-ids more efficient and to
@@ -585,6 +636,7 @@ struct ssl_session_st {
unsigned char *ticket_appdata;
size_t ticket_appdata_len;
uint32_t flags;
+ SSL_CTX *owner;
CRYPTO_RWLOCK *lock;
};
@@ -732,7 +784,63 @@ typedef struct ssl_ctx_ext_secure_st {
unsigned char tick_aes_key[TLSEXT_TICK_KEY_LENGTH];
} SSL_CTX_EXT_SECURE;
+/*
+ * Helper function for HMAC
+ * The structure should be considered opaque, it will change once the low
+ * level deprecated calls are removed. At that point it can be replaced
+ * by EVP_MAC_CTX and most of the functions converted to macros or inlined
+ * directly.
+ */
+typedef struct ssl_hmac_st {
+ EVP_MAC_CTX *ctx;
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+ HMAC_CTX *old_ctx;
+# endif
+} SSL_HMAC;
+
+SSL_HMAC *ssl_hmac_new(const SSL_CTX *ctx);
+void ssl_hmac_free(SSL_HMAC *ctx);
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+HMAC_CTX *ssl_hmac_get0_HMAC_CTX(SSL_HMAC *ctx);
+# endif
+EVP_MAC_CTX *ssl_hmac_get0_EVP_MAC_CTX(SSL_HMAC *ctx);
+int ssl_hmac_init(SSL_HMAC *ctx, void *key, size_t len, char *md);
+int ssl_hmac_update(SSL_HMAC *ctx, const unsigned char *data, size_t len);
+int ssl_hmac_final(SSL_HMAC *ctx, unsigned char *md, size_t *len,
+ size_t max_size);
+size_t ssl_hmac_size(const SSL_HMAC *ctx);
+
+int ssl_get_EC_curve_nid(const EVP_PKEY *pkey);
+__owur int tls13_set_encoded_pub_key(EVP_PKEY *pkey,
+ const unsigned char *enckey,
+ size_t enckeylen);
+
+typedef struct tls_group_info_st {
+ char *tlsname; /* Curve Name as in TLS specs */
+ char *realname; /* Curve Name according to provider */
+ char *algorithm; /* Algorithm name to fetch */
+ unsigned int secbits; /* Bits of security (from SP800-57) */
+ uint16_t group_id; /* Group ID */
+ int mintls; /* Minimum TLS version, -1 unsupported */
+ int maxtls; /* Maximum TLS version (or 0 for undefined) */
+ int mindtls; /* Minimum DTLS version, -1 unsupported */
+ int maxdtls; /* Maximum DTLS version (or 0 for undefined) */
+ char is_kem; /* Mode for this Group: 0 is KEX, 1 is KEM */
+} TLS_GROUP_INFO;
+
+/* flags values */
+# define TLS_GROUP_TYPE 0x0000000FU /* Mask for group type */
+# define TLS_GROUP_CURVE_PRIME 0x00000001U
+# define TLS_GROUP_CURVE_CHAR2 0x00000002U
+# define TLS_GROUP_CURVE_CUSTOM 0x00000004U
+# define TLS_GROUP_FFDHE 0x00000008U
+# define TLS_GROUP_ONLY_FOR_TLS1_3 0x00000010U
+
+# define TLS_GROUP_FFDHE_FOR_TLS1_3 (TLS_GROUP_FFDHE|TLS_GROUP_ONLY_FOR_TLS1_3)
+
struct ssl_ctx_st {
+ OSSL_LIB_CTX *libctx;
+
const SSL_METHOD *method;
STACK_OF(SSL_CIPHER) *cipher_list;
/* same as above but sorted for lookup */
@@ -793,6 +901,9 @@ struct ssl_ctx_st {
* other processes - spooky
* :-) */
} stats;
+#ifdef TSAN_REQUIRES_LOCKING
+ CRYPTO_RWLOCK *tsan_lock;
+#endif
CRYPTO_REF_COUNT references;
@@ -832,7 +943,7 @@ struct ssl_ctx_st {
CRYPTO_EX_DATA ex_data;
const EVP_MD *md5; /* For SSLv3/TLSv1 'ssl3-md5' */
- const EVP_MD *sha1; /* For SSLv3/TLSv1 'ssl3->sha1' */
+ const EVP_MD *sha1; /* For SSLv3/TLSv1 'ssl3-sha1' */
STACK_OF(X509) *extra_certs;
STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */
@@ -856,7 +967,7 @@ struct ssl_ctx_st {
* SSL_new)
*/
- uint32_t options;
+ uint64_t options;
uint32_t mode;
int min_proto_version;
int max_proto_version;
@@ -929,10 +1040,16 @@ struct ssl_ctx_st {
/* RFC 4507 session ticket keys */
unsigned char tick_key_name[TLSEXT_KEYNAME_LENGTH];
SSL_CTX_EXT_SECURE *secure;
+# ifndef OPENSSL_NO_DEPRECATED_3_0
/* Callback to support customisation of ticket key setting */
int (*ticket_key_cb) (SSL *ssl,
unsigned char *name, unsigned char *iv,
EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc);
+#endif
+ int (*ticket_key_evp_cb) (SSL *ssl,
+ unsigned char *name, unsigned char *iv,
+ EVP_CIPHER_CTX *ectx, EVP_MAC_CTX *hctx,
+ int enc);
/* certificate status request info */
/* Callback for status request */
@@ -943,14 +1060,15 @@ struct ssl_ctx_st {
/* RFC 4366 Maximum Fragment Length Negotiation */
uint8_t max_fragment_len_mode;
-# ifndef OPENSSL_NO_EC
/* EC extension values inherited by SSL structure */
size_t ecpointformats_len;
unsigned char *ecpointformats;
+
size_t supportedgroups_len;
uint16_t *supportedgroups;
-# endif /* OPENSSL_NO_EC */
+ uint16_t *supported_groups_default;
+ size_t supported_groups_default_len;
/*
* ALPN information (we are in the process of transitioning from NPN to
* ALPN.)
@@ -1063,8 +1181,34 @@ struct ssl_ctx_st {
/* Do we advertise Post-handshake auth support? */
int pha_enabled;
+
+ /* Callback for SSL async handling */
+ SSL_async_callback_fn async_cb;
+ void *async_cb_arg;
+
+ char *propq;
+
+ int ssl_mac_pkey_id[SSL_MD_NUM_IDX];
+ const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX];
+ const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX];
+ size_t ssl_mac_secret_size[SSL_MD_NUM_IDX];
+
+ /* Cache of all sigalgs we know and whether they are available or not */
+ struct sigalg_lookup_st *sigalg_lookup_cache;
+
+ TLS_GROUP_INFO *group_list;
+ size_t group_list_len;
+ size_t group_list_max_len;
+
+ /* masks of disabled algorithms */
+ uint32_t disabled_enc_mask;
+ uint32_t disabled_mac_mask;
+ uint32_t disabled_mkey_mask;
+ uint32_t disabled_auth_mask;
};
+typedef struct cert_pkey_st CERT_PKEY;
+
struct ssl_st {
/*
* protocol version (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION,
@@ -1118,7 +1262,179 @@ struct ssl_st {
* ssl3_get_message() */
size_t init_num; /* amount read/written */
size_t init_off; /* amount read/written */
- struct ssl3_state_st *s3; /* SSLv3 variables */
+
+ struct {
+ long flags;
+ size_t read_mac_secret_size;
+ unsigned char read_mac_secret[EVP_MAX_MD_SIZE];
+ size_t write_mac_secret_size;
+ unsigned char write_mac_secret[EVP_MAX_MD_SIZE];
+ unsigned char server_random[SSL3_RANDOM_SIZE];
+ unsigned char client_random[SSL3_RANDOM_SIZE];
+ /* flags for countermeasure against known-IV weakness */
+ int need_empty_fragments;
+ int empty_fragment_done;
+ /* used during startup, digest all incoming/outgoing packets */
+ BIO *handshake_buffer;
+ /*
+ * When handshake digest is determined, buffer is hashed and
+ * freed and MD_CTX for the required digest is stored here.
+ */
+ EVP_MD_CTX *handshake_dgst;
+ /*
+ * Set whenever an expected ChangeCipherSpec message is processed.
+ * Unset when the peer's Finished message is received.
+ * Unexpected ChangeCipherSpec messages trigger a fatal alert.
+ */
+ int change_cipher_spec;
+ int warn_alert;
+ int fatal_alert;
+ /*
+ * we allow one fatal and one warning alert to be outstanding, send close
+ * alert via the warning alert
+ */
+ int alert_dispatch;
+ unsigned char send_alert[2];
+ /*
+ * This flag is set when we should renegotiate ASAP, basically when there
+ * is no more data in the read or write buffers
+ */
+ int renegotiate;
+ int total_renegotiations;
+ int num_renegotiations;
+ int in_read_app_data;
+ struct {
+ /* actually only need to be 16+20 for SSLv3 and 12 for TLS */
+ unsigned char finish_md[EVP_MAX_MD_SIZE * 2];
+ size_t finish_md_len;
+ unsigned char peer_finish_md[EVP_MAX_MD_SIZE * 2];
+ size_t peer_finish_md_len;
+ size_t message_size;
+ int message_type;
+ /* used to hold the new cipher we are going to use */
+ const SSL_CIPHER *new_cipher;
+ EVP_PKEY *pkey; /* holds short lived key exchange key */
+ /* used for certificate requests */
+ int cert_req;
+ /* Certificate types in certificate request message. */
+ uint8_t *ctype;
+ size_t ctype_len;
+ /* Certificate authorities list peer sent */
+ STACK_OF(X509_NAME) *peer_ca_names;
+ size_t key_block_length;
+ unsigned char *key_block;
+ const EVP_CIPHER *new_sym_enc;
+ const EVP_MD *new_hash;
+ int new_mac_pkey_type;
+ size_t new_mac_secret_size;
+# ifndef OPENSSL_NO_COMP
+ const SSL_COMP *new_compression;
+# else
+ char *new_compression;
+# endif
+ int cert_request;
+ /* Raw values of the cipher list from a client */
+ unsigned char *ciphers_raw;
+ size_t ciphers_rawlen;
+ /* Temporary storage for premaster secret */
+ unsigned char *pms;
+ size_t pmslen;
+# ifndef OPENSSL_NO_PSK
+ /* Temporary storage for PSK key */
+ unsigned char *psk;
+ size_t psklen;
+# endif
+ /* Signature algorithm we actually use */
+ const struct sigalg_lookup_st *sigalg;
+ /* Pointer to certificate we use */
+ CERT_PKEY *cert;
+ /*
+ * signature algorithms peer reports: e.g. supported signature
+ * algorithms extension for server or as part of a certificate
+ * request for client.
+ * Keep track of the algorithms for TLS and X.509 usage separately.
+ */
+ uint16_t *peer_sigalgs;
+ uint16_t *peer_cert_sigalgs;
+ /* Size of above arrays */
+ size_t peer_sigalgslen;
+ size_t peer_cert_sigalgslen;
+ /* Sigalg peer actually uses */
+ const struct sigalg_lookup_st *peer_sigalg;
+ /*
+ * Set if corresponding CERT_PKEY can be used with current
+ * SSL session: e.g. appropriate curve, signature algorithms etc.
+ * If zero it can't be used at all.
+ */
+ uint32_t valid_flags[SSL_PKEY_NUM];
+ /*
+ * For servers the following masks are for the key and auth algorithms
+ * that are supported by the certs below. For clients they are masks of
+ * *disabled* algorithms based on the current session.
+ */
+ uint32_t mask_k;
+ uint32_t mask_a;
+ /*
+ * The following are used by the client to see if a cipher is allowed or
+ * not. It contains the minimum and maximum version the client's using
+ * based on what it knows so far.
+ */
+ int min_ver;
+ int max_ver;
+ } tmp;
+
+ /* Connection binding to prevent renegotiation attacks */
+ unsigned char previous_client_finished[EVP_MAX_MD_SIZE];
+ size_t previous_client_finished_len;
+ unsigned char previous_server_finished[EVP_MAX_MD_SIZE];
+ size_t previous_server_finished_len;
+ int send_connection_binding;
+
+# ifndef OPENSSL_NO_NEXTPROTONEG
+ /*
+ * Set if we saw the Next Protocol Negotiation extension from our peer.
+ */
+ int npn_seen;
+# endif
+
+ /*
+ * ALPN information (we are in the process of transitioning from NPN to
+ * ALPN.)
+ */
+
+ /*
+ * In a server these point to the selected ALPN protocol after the
+ * ClientHello has been processed. In a client these contain the protocol
+ * that the server selected once the ServerHello has been processed.
+ */
+ unsigned char *alpn_selected;
+ size_t alpn_selected_len;
+ /* used by the server to know what options were proposed */
+ unsigned char *alpn_proposed;
+ size_t alpn_proposed_len;
+ /* used by the client to know if it actually sent alpn */
+ int alpn_sent;
+
+ /*
+ * This is set to true if we believe that this is a version of Safari
+ * running on OS X 10.6 or newer. We wish to know this because Safari on
+ * 10.8 .. 10.8.3 has broken ECDHE-ECDSA support.
+ */
+ char is_probably_safari;
+
+ /*
+ * Track whether we did a key exchange this handshake or not, so
+ * SSL_get_negotiated_group() knows whether to fall back to the
+ * value in the SSL_SESSION.
+ */
+ char did_kex;
+ /* For clients: peer temporary key */
+ /* The group_id for the key exchange key */
+ uint16_t group_id;
+ EVP_PKEY *peer_tmp;
+
+ } s3;
+
struct dtls1_state_st *d1; /* DTLSv1 variables */
/* callback that allows applications to peek at protocol messages */
void (*msg_callback) (int write_p, int version, int content_type,
@@ -1235,7 +1551,7 @@ struct ssl_st {
STACK_OF(X509_NAME) *client_ca_names;
CRYPTO_REF_COUNT references;
/* protocol behaviour */
- uint32_t options;
+ uint64_t options;
/* API behaviour */
uint32_t mode;
int min_proto_version;
@@ -1289,7 +1605,8 @@ struct ssl_st {
/* RFC4507 session ticket expected to be received or sent */
int ticket_expected;
-# ifndef OPENSSL_NO_EC
+ /* TLS 1.3 tickets requested by the application. */
+ int extra_tickets_expected;
size_t ecpointformats_len;
/* our list */
unsigned char *ecpointformats;
@@ -1297,7 +1614,6 @@ struct ssl_st {
size_t peer_ecpointformats_len;
/* peer's list */
unsigned char *peer_ecpointformats;
-# endif /* OPENSSL_NO_EC */
size_t supportedgroups_len;
/* our list */
uint16_t *supportedgroups;
@@ -1473,6 +1789,10 @@ struct ssl_st {
SSL_allow_early_data_cb_fn allow_early_data_cb;
void *allow_early_data_cb_data;
+ /* Callback for SSL async handling */
+ SSL_async_callback_fn async_cb;
+ void *async_cb_arg;
+
/*
* Signature algorithms shared by client and server: cached because these
* are used most often.
@@ -1502,22 +1822,10 @@ typedef struct sigalg_lookup_st {
int sigandhash;
/* Required public key curve (ECDSA only) */
int curve;
+ /* Whether this signature algorithm is actually available for use */
+ int enabled;
} SIGALG_LOOKUP;
-typedef struct tls_group_info_st {
- int nid; /* Curve NID */
- int secbits; /* Bits of security (from SP800-57) */
- uint16_t flags; /* Flags: currently just group type */
-} TLS_GROUP_INFO;
-
-/* flags values */
-# define TLS_CURVE_TYPE 0x3 /* Mask for group type */
-# define TLS_CURVE_PRIME 0x0
-# define TLS_CURVE_CHAR2 0x1
-# define TLS_CURVE_CUSTOM 0x2
-
-typedef struct cert_pkey_st CERT_PKEY;
-
/*
* Structure containing table entry of certificate info corresponding to
* CERT_PKEY entries
@@ -1527,178 +1835,6 @@ typedef struct {
uint32_t amask; /* authmask corresponding to key type */
} SSL_CERT_LOOKUP;
-typedef struct ssl3_state_st {
- long flags;
- size_t read_mac_secret_size;
- unsigned char read_mac_secret[EVP_MAX_MD_SIZE];
- size_t write_mac_secret_size;
- unsigned char write_mac_secret[EVP_MAX_MD_SIZE];
- unsigned char server_random[SSL3_RANDOM_SIZE];
- unsigned char client_random[SSL3_RANDOM_SIZE];
- /* flags for countermeasure against known-IV weakness */
- int need_empty_fragments;
- int empty_fragment_done;
- /* used during startup, digest all incoming/outgoing packets */
- BIO *handshake_buffer;
- /*
- * When handshake digest is determined, buffer is hashed and
- * freed and MD_CTX for the required digest is stored here.
- */
- EVP_MD_CTX *handshake_dgst;
- /*
- * Set whenever an expected ChangeCipherSpec message is processed.
- * Unset when the peer's Finished message is received.
- * Unexpected ChangeCipherSpec messages trigger a fatal alert.
- */
- int change_cipher_spec;
- int warn_alert;
- int fatal_alert;
- /*
- * we allow one fatal and one warning alert to be outstanding, send close
- * alert via the warning alert
- */
- int alert_dispatch;
- unsigned char send_alert[2];
- /*
- * This flag is set when we should renegotiate ASAP, basically when there
- * is no more data in the read or write buffers
- */
- int renegotiate;
- int total_renegotiations;
- int num_renegotiations;
- int in_read_app_data;
- struct {
- /* actually only need to be 16+20 for SSLv3 and 12 for TLS */
- unsigned char finish_md[EVP_MAX_MD_SIZE * 2];
- size_t finish_md_len;
- unsigned char peer_finish_md[EVP_MAX_MD_SIZE * 2];
- size_t peer_finish_md_len;
- size_t message_size;
- int message_type;
- /* used to hold the new cipher we are going to use */
- const SSL_CIPHER *new_cipher;
-# if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
- EVP_PKEY *pkey; /* holds short lived DH/ECDH key */
-# endif
- /* used for certificate requests */
- int cert_req;
- /* Certificate types in certificate request message. */
- uint8_t *ctype;
- size_t ctype_len;
- /* Certificate authorities list peer sent */
- STACK_OF(X509_NAME) *peer_ca_names;
- size_t key_block_length;
- unsigned char *key_block;
- const EVP_CIPHER *new_sym_enc;
- const EVP_MD *new_hash;
- int new_mac_pkey_type;
- size_t new_mac_secret_size;
-# ifndef OPENSSL_NO_COMP
- const SSL_COMP *new_compression;
-# else
- char *new_compression;
-# endif
- int cert_request;
- /* Raw values of the cipher list from a client */
- unsigned char *ciphers_raw;
- size_t ciphers_rawlen;
- /* Temporary storage for premaster secret */
- unsigned char *pms;
- size_t pmslen;
-# ifndef OPENSSL_NO_PSK
- /* Temporary storage for PSK key */
- unsigned char *psk;
- size_t psklen;
-# endif
- /* Signature algorithm we actually use */
- const SIGALG_LOOKUP *sigalg;
- /* Pointer to certificate we use */
- CERT_PKEY *cert;
- /*
- * signature algorithms peer reports: e.g. supported signature
- * algorithms extension for server or as part of a certificate
- * request for client.
- * Keep track of the algorithms for TLS and X.509 usage separately.
- */
- uint16_t *peer_sigalgs;
- uint16_t *peer_cert_sigalgs;
- /* Size of above arrays */
- size_t peer_sigalgslen;
- size_t peer_cert_sigalgslen;
- /* Sigalg peer actually uses */
- const SIGALG_LOOKUP *peer_sigalg;
- /*
- * Set if corresponding CERT_PKEY can be used with current
- * SSL session: e.g. appropriate curve, signature algorithms etc.
- * If zero it can't be used at all.
- */
- uint32_t valid_flags[SSL_PKEY_NUM];
- /*
- * For servers the following masks are for the key and auth algorithms
- * that are supported by the certs below. For clients they are masks of
- * *disabled* algorithms based on the current session.
- */
- uint32_t mask_k;
- uint32_t mask_a;
- /*
- * The following are used by the client to see if a cipher is allowed or
- * not. It contains the minimum and maximum version the client's using
- * based on what it knows so far.
- */
- int min_ver;
- int max_ver;
- } tmp;
-
- /* Connection binding to prevent renegotiation attacks */
- unsigned char previous_client_finished[EVP_MAX_MD_SIZE];
- size_t previous_client_finished_len;
- unsigned char previous_server_finished[EVP_MAX_MD_SIZE];
- size_t previous_server_finished_len;
- int send_connection_binding; /* TODOEKR */
-
-# ifndef OPENSSL_NO_NEXTPROTONEG
- /*
- * Set if we saw the Next Protocol Negotiation extension from our peer.
- */
- int npn_seen;
-# endif
-
- /*
- * ALPN information (we are in the process of transitioning from NPN to
- * ALPN.)
- */
-
- /*
- * In a server these point to the selected ALPN protocol after the
- * ClientHello has been processed. In a client these contain the protocol
- * that the server selected once the ServerHello has been processed.
- */
- unsigned char *alpn_selected;
- size_t alpn_selected_len;
- /* used by the server to know what options were proposed */
- unsigned char *alpn_proposed;
- size_t alpn_proposed_len;
- /* used by the client to know if it actually sent alpn */
- int alpn_sent;
-
-# ifndef OPENSSL_NO_EC
- /*
- * This is set to true if we believe that this is a version of Safari
- * running on OS X 10.6 or newer. We wish to know this because Safari on
- * 10.8 .. 10.8.3 has broken ECDHE-ECDSA support.
- */
- char is_probably_safari;
-# endif /* !OPENSSL_NO_EC */
-
- /* For clients: peer temporary key */
-# if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
- /* The group_id for the DH/ECDH key */
- uint16_t group_id;
- EVP_PKEY *peer_tmp;
-# endif
-
-} SSL3_STATE;
-
/* DTLS structures */
# ifndef OPENSSL_NO_SCTP
@@ -1732,15 +1868,6 @@ struct hm_header_st {
struct dtls1_retransmit_state saved_retransmit_state;
};
-struct dtls1_timeout_st {
- /* Number of read timeouts so far */
- unsigned int read_timeouts;
- /* Number of write timeouts so far */
- unsigned int write_timeouts;
- /* Number of alerts received so far */
- unsigned int num_alerts;
-};
-
typedef struct hm_fragment_st {
struct hm_header_st msg_header;
unsigned char *fragment;
@@ -1786,7 +1913,8 @@ typedef struct dtls1_state_st {
size_t mtu; /* max DTLS packet size */
struct hm_header_st w_msg_hdr;
struct hm_header_st r_msg_hdr;
- struct dtls1_timeout_st timeout;
+ /* Number of alerts received so far */
+ unsigned int timeout_num_alerts;
/*
* Indicates when the last handshake msg sent will timeout
*/
@@ -1803,14 +1931,12 @@ typedef struct dtls1_state_st {
} DTLS1_STATE;
-# ifndef OPENSSL_NO_EC
/*
* From ECC-TLS draft, used in encoding the curve type in ECParameters
*/
# define EXPLICIT_PRIME_CURVE_TYPE 1
# define EXPLICIT_CHAR2_CURVE_TYPE 2
# define NAMED_CURVE_TYPE 3
-# endif /* OPENSSL_NO_EC */
struct cert_pkey_st {
X509 *x509;
@@ -1883,11 +2009,10 @@ typedef struct cert_st {
* an index, not a pointer.
*/
CERT_PKEY *key;
-# ifndef OPENSSL_NO_DH
+
EVP_PKEY *dh_tmp;
DH *(*dh_tmp_cb) (SSL *ssl, int is_export, int keysize);
int dh_tmp_auto;
-# endif
/* Flags related to certificates */
uint32_t cert_flags;
CERT_PKEY pkeys[SSL_PKEY_NUM];
@@ -1950,7 +2075,7 @@ typedef struct cert_st {
* of a mess of functions, but hell, think of it as an opaque structure :-)
*/
typedef struct ssl3_enc_method {
- int (*enc) (SSL *, SSL3_RECORD *, size_t, int);
+ int (*enc) (SSL *, SSL3_RECORD *, size_t, int, SSL_MAC_BUF *, size_t);
int (*mac) (SSL *, SSL3_RECORD *, unsigned char *, int);
int (*setup_key_block) (SSL *);
int (*generate_master_secret) (SSL *, unsigned char *, unsigned char *,
@@ -2042,6 +2167,8 @@ typedef enum downgrade_en {
#define TLSEXT_SIGALG_dsa_sha512 0x0602
#define TLSEXT_SIGALG_dsa_sha224 0x0302
#define TLSEXT_SIGALG_dsa_sha1 0x0202
+#define TLSEXT_SIGALG_gostr34102012_256_intrinsic 0x0840
+#define TLSEXT_SIGALG_gostr34102012_512_intrinsic 0x0841
#define TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 0xeeee
#define TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 0xefef
#define TLSEXT_SIGALG_gostr34102001_gostr3411 0xeded
@@ -2060,8 +2187,8 @@ typedef enum downgrade_en {
#define TLSEXT_KEX_MODE_FLAG_KE 1
#define TLSEXT_KEX_MODE_FLAG_KE_DHE 2
-#define SSL_USE_PSS(s) (s->s3->tmp.peer_sigalg != NULL && \
- s->s3->tmp.peer_sigalg->sig == EVP_PKEY_RSA_PSS)
+#define SSL_USE_PSS(s) (s->s3.tmp.peer_sigalg != NULL && \
+ s->s3.tmp.peer_sigalg->sig == EVP_PKEY_RSA_PSS)
/* A dummy signature value not valid for TLSv1.2 signature algs */
#define TLSEXT_signature_rsa_pss 0x0101
@@ -2261,12 +2388,12 @@ __owur int ssl_get_new_session(SSL *s, int session);
__owur SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id,
size_t sess_id_len);
__owur int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello);
-__owur SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
+__owur SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket);
__owur int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b);
DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, ssl_cipher_id);
__owur int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap,
const SSL_CIPHER *const *bp);
-__owur STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
+__owur STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(SSL_CTX *ctx,
STACK_OF(SSL_CIPHER) *tls13_ciphersuites,
STACK_OF(SSL_CIPHER) **cipher_list,
STACK_OF(SSL_CIPHER) **cipher_list_by_id,
@@ -2278,14 +2405,16 @@ __owur int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites,
STACK_OF(SSL_CIPHER) **scsvs, int sslv2format,
int fatal);
void ssl_update_cache(SSL *s, int mode);
-__owur int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
- const EVP_MD **md, int *mac_pkey_type,
- size_t *mac_secret_size, SSL_COMP **comp,
- int use_etm);
+__owur int ssl_cipher_get_evp_cipher(SSL_CTX *ctx, const SSL_CIPHER *sslc,
+ const EVP_CIPHER **enc);
+__owur int ssl_cipher_get_evp(SSL_CTX *ctxc, const SSL_SESSION *s,
+ const EVP_CIPHER **enc, const EVP_MD **md,
+ int *mac_pkey_type, size_t *mac_secret_size,
+ SSL_COMP **comp, int use_etm);
__owur int ssl_cipher_get_overhead(const SSL_CIPHER *c, size_t *mac_overhead,
size_t *int_overhead, size_t *blocksize,
size_t *ext_overhead);
-__owur int ssl_cert_is_disabled(size_t idx);
+__owur int ssl_cert_is_disabled(SSL_CTX *ctx, size_t idx);
__owur const SSL_CIPHER *ssl_get_cipher_by_char(SSL *ssl,
const unsigned char *ptr,
int all);
@@ -2323,15 +2452,26 @@ void ssl_set_masks(SSL *s);
__owur STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
__owur int ssl_x509err2alert(int type);
void ssl_sort_cipher_list(void);
-int ssl_load_ciphers(void);
+int ssl_load_ciphers(SSL_CTX *ctx);
+__owur int ssl_setup_sig_algs(SSL_CTX *ctx);
+int ssl_load_groups(SSL_CTX *ctx);
__owur int ssl_fill_hello_random(SSL *s, int server, unsigned char *field,
size_t len, DOWNGRADE dgrd);
__owur int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
int free_pms);
-__owur EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm);
+__owur EVP_PKEY *ssl_generate_pkey(SSL *s, EVP_PKEY *pm);
+__owur int ssl_gensecret(SSL *s, unsigned char *pms, size_t pmslen);
__owur int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey,
int genmaster);
+__owur int ssl_decapsulate(SSL *s, EVP_PKEY *privkey,
+ const unsigned char *ct, size_t ctlen,
+ int gensecret);
+__owur int ssl_encapsulate(SSL *s, EVP_PKEY *pubkey,
+ unsigned char **ctp, size_t *ctlenp,
+ int gensecret);
__owur EVP_PKEY *ssl_dh_to_pkey(DH *dh);
+__owur int ssl_set_tmp_ecdh_groups(uint16_t **pext, size_t *pextlen,
+ void *key);
__owur unsigned int ssl_get_max_send_fragment(const SSL *ssl);
__owur unsigned int ssl_get_split_send_fragment(const SSL *ssl);
@@ -2354,6 +2494,8 @@ __owur int ssl3_num_ciphers(void);
__owur const SSL_CIPHER *ssl3_get_cipher(unsigned int u);
int ssl3_renegotiate(SSL *ssl);
int ssl3_renegotiate_check(SSL *ssl, int initok);
+void ssl3_digest_master_key_set_params(const SSL_SESSION *session,
+ OSSL_PARAM params[]);
__owur int ssl3_dispatch_alert(SSL *s);
__owur size_t ssl3_final_finish_mac(SSL *s, const char *sender, size_t slen,
unsigned char *p);
@@ -2503,29 +2645,28 @@ __owur int tls1_alert_code(int code);
__owur int tls13_alert_code(int code);
__owur int ssl3_alert_code(int code);
-# ifndef OPENSSL_NO_EC
__owur int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s);
-# endif
SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n);
-# ifndef OPENSSL_NO_EC
-
-__owur const TLS_GROUP_INFO *tls1_group_id_lookup(uint16_t curve_id);
+__owur const TLS_GROUP_INFO *tls1_group_id_lookup(SSL_CTX *ctx, uint16_t curve_id);
+__owur int tls1_group_id2nid(uint16_t group_id, int include_unknown);
+__owur uint16_t tls1_nid2group_id(int nid);
__owur int tls1_check_group_id(SSL *s, uint16_t group_id, int check_own_curves);
__owur uint16_t tls1_shared_group(SSL *s, int nmatch);
__owur int tls1_set_groups(uint16_t **pext, size_t *pextlen,
int *curves, size_t ncurves);
-__owur int tls1_set_groups_list(uint16_t **pext, size_t *pextlen,
+__owur int tls1_set_groups_list(SSL_CTX *ctx, uint16_t **pext, size_t *pextlen,
const char *str);
+__owur EVP_PKEY *ssl_generate_pkey_group(SSL *s, uint16_t id);
+__owur int tls_valid_group(SSL *s, uint16_t group_id, int minversion,
+ int maxversion, int isec, int *okfortls13);
+__owur EVP_PKEY *ssl_generate_param_group(SSL *s, uint16_t id);
void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
size_t *num_formats);
__owur int tls1_check_ec_tmp_key(SSL *s, unsigned long id);
-__owur EVP_PKEY *ssl_generate_pkey_group(SSL *s, uint16_t id);
-__owur EVP_PKEY *ssl_generate_param_group(uint16_t id);
-# endif /* OPENSSL_NO_EC */
-__owur int tls_curve_allowed(SSL *s, uint16_t curve, int op);
+__owur int tls_group_allowed(SSL *s, uint16_t curve, int op);
void tls1_get_supported_groups(SSL *s, const uint16_t **pgroups,
size_t *pgroupslen);
@@ -2555,9 +2696,7 @@ void tls1_set_cert_validity(SSL *s);
__owur int ssl_validate_ct(SSL *s);
# endif
-# ifndef OPENSSL_NO_DH
-__owur DH *ssl_get_auto_dh(SSL *s);
-# endif
+__owur EVP_PKEY *ssl_get_auto_dh(SSL *s);
__owur int ssl_security_cert(SSL *s, SSL_CTX *ctx, X509 *x, int vfy, int is_ee);
__owur int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *ex,
@@ -2574,18 +2713,17 @@ __owur int tls1_save_u16(PACKET *pkt, uint16_t **pdest, size_t *pdestlen);
__owur int tls1_save_sigalgs(SSL *s, PACKET *pkt, int cert);
__owur int tls1_process_sigalgs(SSL *s);
__owur int tls1_set_peer_legacy_sigalg(SSL *s, const EVP_PKEY *pkey);
-__owur int tls1_lookup_md(const SIGALG_LOOKUP *lu, const EVP_MD **pmd);
+__owur int tls1_lookup_md(SSL_CTX *ctx, const SIGALG_LOOKUP *lu,
+ const EVP_MD **pmd);
__owur size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs);
-# ifndef OPENSSL_NO_EC
__owur int tls_check_sigalg_curve(const SSL *s, int curve);
-# endif
__owur int tls12_check_peer_sigalg(SSL *s, uint16_t, EVP_PKEY *pkey);
__owur int ssl_set_client_disabled(SSL *s);
__owur int ssl_cipher_disabled(const SSL *s, const SSL_CIPHER *c, int op, int echde);
__owur int ssl_handshake_hash(SSL *s, unsigned char *out, size_t outlen,
size_t *hashlen);
-__owur const EVP_MD *ssl_md(int idx);
+__owur const EVP_MD *ssl_md(SSL_CTX *ctx, int idx);
__owur const EVP_MD *ssl_handshake_md(SSL *s);
__owur const EVP_MD *ssl_prf_md(SSL *s);
@@ -2614,18 +2752,31 @@ __owur int ssl_log_secret(SSL *ssl, const char *label,
#define CLIENT_HANDSHAKE_LABEL "CLIENT_HANDSHAKE_TRAFFIC_SECRET"
#define SERVER_HANDSHAKE_LABEL "SERVER_HANDSHAKE_TRAFFIC_SECRET"
#define CLIENT_APPLICATION_LABEL "CLIENT_TRAFFIC_SECRET_0"
+#define CLIENT_APPLICATION_N_LABEL "CLIENT_TRAFFIC_SECRET_N"
#define SERVER_APPLICATION_LABEL "SERVER_TRAFFIC_SECRET_0"
+#define SERVER_APPLICATION_N_LABEL "SERVER_TRAFFIC_SECRET_N"
#define EARLY_EXPORTER_SECRET_LABEL "EARLY_EXPORTER_SECRET"
#define EXPORTER_SECRET_LABEL "EXPORTER_SECRET"
+# ifndef OPENSSL_NO_KTLS
+/* ktls.c */
+int ktls_check_supported_cipher(const SSL *s, const EVP_CIPHER *c,
+ const EVP_CIPHER_CTX *dd);
+int ktls_configure_crypto(const SSL *s, const EVP_CIPHER *c, EVP_CIPHER_CTX *dd,
+ void *rl_sequence, ktls_crypto_info_t *crypto_info,
+ unsigned char **rec_seq, unsigned char *iv,
+ unsigned char *key, unsigned char *mac_key,
+ size_t mac_secret_size);
+# endif
+
/* s3_cbc.c */
__owur char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx);
-__owur int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
+__owur int ssl3_cbc_digest_record(const EVP_MD *md,
unsigned char *md_out,
size_t *md_out_size,
const unsigned char *header,
const unsigned char *data,
- size_t data_plus_mac_size,
+ size_t data_size,
size_t data_plus_mac_plus_padding_size,
const unsigned char *mac_secret,
size_t mac_secret_length, char is_sslv3);
@@ -2663,10 +2814,73 @@ void ssl_comp_free_compression_methods_int(void);
/* ssl_mcnf.c */
void ssl_ctx_system_config(SSL_CTX *ctx);
+const EVP_CIPHER *ssl_evp_cipher_fetch(OSSL_LIB_CTX *libctx,
+ int nid,
+ const char *properties);
+int ssl_evp_cipher_up_ref(const EVP_CIPHER *cipher);
+void ssl_evp_cipher_free(const EVP_CIPHER *cipher);
+const EVP_MD *ssl_evp_md_fetch(OSSL_LIB_CTX *libctx,
+ int nid,
+ const char *properties);
+int ssl_evp_md_up_ref(const EVP_MD *md);
+void ssl_evp_md_free(const EVP_MD *md);
+
+int tls_provider_set_tls_params(SSL *s, EVP_CIPHER_CTX *ctx,
+ const EVP_CIPHER *ciph,
+ const EVP_MD *md);
+
+void tls_engine_finish(ENGINE *e);
+const EVP_CIPHER *tls_get_cipher_from_engine(int nid);
+const EVP_MD *tls_get_digest_from_engine(int nid);
+int tls_engine_load_ssl_client_cert(SSL *s, X509 **px509, EVP_PKEY **ppkey);
+int ssl_hmac_old_new(SSL_HMAC *ret);
+void ssl_hmac_old_free(SSL_HMAC *ctx);
+int ssl_hmac_old_init(SSL_HMAC *ctx, void *key, size_t len, char *md);
+int ssl_hmac_old_update(SSL_HMAC *ctx, const unsigned char *data, size_t len);
+int ssl_hmac_old_final(SSL_HMAC *ctx, unsigned char *md, size_t *len);
+size_t ssl_hmac_old_size(const SSL_HMAC *ctx);
+
+int ssl_ctx_srp_ctx_free_intern(SSL_CTX *ctx);
+int ssl_ctx_srp_ctx_init_intern(SSL_CTX *ctx);
+int ssl_srp_ctx_free_intern(SSL *s);
+int ssl_srp_ctx_init_intern(SSL *s);
+
+int ssl_srp_calc_a_param_intern(SSL *s);
+int ssl_srp_server_param_with_username_intern(SSL *s, int *ad);
+
+void ssl_session_calculate_timeout(SSL_SESSION* ss);
+
# else /* OPENSSL_UNIT_TEST */
# define ssl_init_wbio_buffer SSL_test_functions()->p_ssl_init_wbio_buffer
# define ssl3_setup_buffers SSL_test_functions()->p_ssl3_setup_buffers
# endif
+
+/* Some helper routines to support TSAN operations safely */
+static ossl_unused ossl_inline int ssl_tsan_lock(const SSL_CTX *ctx)
+{
+#ifdef TSAN_REQUIRES_LOCKING
+ if (!CRYPTO_THREAD_write_lock(ctx->tsan_lock))
+ return 0;
+#endif
+ return 1;
+}
+
+static ossl_unused ossl_inline void ssl_tsan_unlock(const SSL_CTX *ctx)
+{
+#ifdef TSAN_REQUIRES_LOCKING
+ CRYPTO_THREAD_unlock(ctx->tsan_lock);
+#endif
+}
+
+static ossl_unused ossl_inline void ssl_tsan_counter(const SSL_CTX *ctx,
+ TSAN_QUALIFIER int *stat)
+{
+ if (ssl_tsan_lock(ctx)) {
+ tsan_counter(stat);
+ ssl_tsan_unlock(ctx);
+ }
+}
+
#endif
diff --git a/ssl/ssl_mcnf.c b/ssl/ssl_mcnf.c
index 583df4166908..c2366e41e365 100644
--- a/ssl/ssl_mcnf.c
+++ b/ssl/ssl_mcnf.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -28,19 +28,20 @@ static int ssl_do_config(SSL *s, SSL_CTX *ctx, const char *name, int system)
unsigned int flags;
const SSL_METHOD *meth;
const SSL_CONF_CMD *cmds;
+ OSSL_LIB_CTX *prev_libctx = NULL;
+ OSSL_LIB_CTX *libctx = NULL;
if (s == NULL && ctx == NULL) {
- SSLerr(SSL_F_SSL_DO_CONFIG, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
goto err;
}
if (name == NULL && system)
name = "system_default";
if (!conf_ssl_name_find(name, &idx)) {
- if (!system) {
- SSLerr(SSL_F_SSL_DO_CONFIG, SSL_R_INVALID_CONFIGURATION_NAME);
- ERR_add_error_data(2, "name=", name);
- }
+ if (!system)
+ ERR_raise_data(ERR_LIB_SSL, SSL_R_INVALID_CONFIGURATION_NAME,
+ "name=%s", name);
goto err;
}
cmds = conf_ssl_get(idx, &name, &cmd_count);
@@ -53,32 +54,34 @@ static int ssl_do_config(SSL *s, SSL_CTX *ctx, const char *name, int system)
if (s != NULL) {
meth = s->method;
SSL_CONF_CTX_set_ssl(cctx, s);
+ libctx = s->ctx->libctx;
} else {
meth = ctx->method;
SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
+ libctx = ctx->libctx;
}
if (meth->ssl_accept != ssl_undefined_function)
flags |= SSL_CONF_FLAG_SERVER;
if (meth->ssl_connect != ssl_undefined_function)
flags |= SSL_CONF_FLAG_CLIENT;
SSL_CONF_CTX_set_flags(cctx, flags);
+ prev_libctx = OSSL_LIB_CTX_set0_default(libctx);
for (i = 0; i < cmd_count; i++) {
char *cmdstr, *arg;
conf_ssl_get_cmd(cmds, i, &cmdstr, &arg);
rv = SSL_CONF_cmd(cctx, cmdstr, arg);
if (rv <= 0) {
- if (rv == -2)
- SSLerr(SSL_F_SSL_DO_CONFIG, SSL_R_UNKNOWN_COMMAND);
- else
- SSLerr(SSL_F_SSL_DO_CONFIG, SSL_R_BAD_VALUE);
- ERR_add_error_data(6, "section=", name, ", cmd=", cmdstr,
- ", arg=", arg);
+ int errcode = rv == -2 ? SSL_R_UNKNOWN_COMMAND : SSL_R_BAD_VALUE;
+
+ ERR_raise_data(ERR_LIB_SSL, errcode,
+ "section=%s, cmd=%s, arg=%s", name, cmdstr, arg);
goto err;
}
}
rv = SSL_CONF_CTX_finish(cctx);
err:
+ OSSL_LIB_CTX_set0_default(prev_libctx);
SSL_CONF_CTX_free(cctx);
return rv <= 0 ? 0 : 1;
}
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
index 2df07bea6782..4f45e60535d2 100644
--- a/ssl/ssl_rsa.c
+++ b/ssl/ssl_rsa.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,11 +9,12 @@
#include <stdio.h>
#include "ssl_local.h"
-#include "packet_local.h"
+#include "internal/packet.h"
#include <openssl/bio.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
+#include <openssl/x509v3.h>
#include <openssl/pem.h>
static int ssl_set_cert(CERT *c, X509 *x509);
@@ -28,12 +29,13 @@ int SSL_use_certificate(SSL *ssl, X509 *x)
{
int rv;
if (x == NULL) {
- SSLerr(SSL_F_SSL_USE_CERTIFICATE, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
+
rv = ssl_security_cert(ssl, NULL, x, 0, 1);
if (rv != 1) {
- SSLerr(SSL_F_SSL_USE_CERTIFICATE, rv);
+ ERR_raise(ERR_LIB_SSL, rv);
return 0;
}
@@ -45,32 +47,42 @@ int SSL_use_certificate_file(SSL *ssl, const char *file, int type)
int j;
BIO *in;
int ret = 0;
- X509 *x = NULL;
+ X509 *cert = NULL, *x = NULL;
in = BIO_new(BIO_s_file());
if (in == NULL) {
- SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB);
goto end;
}
if (BIO_read_filename(in, file) <= 0) {
- SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, ERR_R_SYS_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB);
+ goto end;
+ }
+
+ if (type != SSL_FILETYPE_ASN1 && type != SSL_FILETYPE_PEM) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+ x = X509_new_ex(ssl->ctx->libctx, ssl->ctx->propq);
+ if (x == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto end;
}
if (type == SSL_FILETYPE_ASN1) {
j = ERR_R_ASN1_LIB;
- x = d2i_X509_bio(in, NULL);
+ cert = d2i_X509_bio(in, &x);
} else if (type == SSL_FILETYPE_PEM) {
j = ERR_R_PEM_LIB;
- x = PEM_read_bio_X509(in, NULL, ssl->default_passwd_callback,
- ssl->default_passwd_callback_userdata);
+ cert = PEM_read_bio_X509(in, &x, ssl->default_passwd_callback,
+ ssl->default_passwd_callback_userdata);
} else {
- SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, SSL_R_BAD_SSL_FILETYPE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE);
goto end;
}
- if (x == NULL) {
- SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, j);
+ if (cert == NULL) {
+ ERR_raise(ERR_LIB_SSL, j);
goto end;
}
@@ -86,74 +98,35 @@ int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len)
X509 *x;
int ret;
- x = d2i_X509(NULL, &d, (long)len);
+ x = X509_new_ex(ssl->ctx->libctx, ssl->ctx->propq);
if (x == NULL) {
- SSLerr(SSL_F_SSL_USE_CERTIFICATE_ASN1, ERR_R_ASN1_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
- ret = SSL_use_certificate(ssl, x);
- X509_free(x);
- return ret;
-}
-
-#ifndef OPENSSL_NO_RSA
-int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa)
-{
- EVP_PKEY *pkey;
- int ret;
-
- if (rsa == NULL) {
- SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
- if ((pkey = EVP_PKEY_new()) == NULL) {
- SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY, ERR_R_EVP_LIB);
+ if (d2i_X509(&x, &d, (long)len)== NULL) {
+ X509_free(x);
+ ERR_raise(ERR_LIB_SSL, ERR_R_ASN1_LIB);
return 0;
}
- RSA_up_ref(rsa);
- if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) {
- RSA_free(rsa);
- EVP_PKEY_free(pkey);
- return 0;
- }
-
- ret = ssl_set_pkey(ssl->cert, pkey);
- EVP_PKEY_free(pkey);
+ ret = SSL_use_certificate(ssl, x);
+ X509_free(x);
return ret;
}
-#endif
static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey)
{
size_t i;
if (ssl_cert_lookup_by_pkey(pkey, &i) == NULL) {
- SSLerr(SSL_F_SSL_SET_PKEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
return 0;
}
- if (c->pkeys[i].x509 != NULL) {
- EVP_PKEY *pktmp;
- pktmp = X509_get0_pubkey(c->pkeys[i].x509);
- if (pktmp == NULL) {
- SSLerr(SSL_F_SSL_SET_PKEY, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- /*
- * The return code from EVP_PKEY_copy_parameters is deliberately
- * ignored. Some EVP_PKEY types cannot do this.
- */
- EVP_PKEY_copy_parameters(pktmp, pkey);
- ERR_clear_error();
-
- if (!X509_check_private_key(c->pkeys[i].x509, pkey)) {
- X509_free(c->pkeys[i].x509);
- c->pkeys[i].x509 = NULL;
- return 0;
- }
- }
+ if (c->pkeys[i].x509 != NULL
+ && !X509_check_private_key(c->pkeys[i].x509, pkey))
+ return 0;
EVP_PKEY_free(c->pkeys[i].privatekey);
EVP_PKEY_up_ref(pkey);
@@ -162,70 +135,12 @@ static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey)
return 1;
}
-#ifndef OPENSSL_NO_RSA
-int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type)
-{
- int j, ret = 0;
- BIO *in;
- RSA *rsa = NULL;
-
- in = BIO_new(BIO_s_file());
- if (in == NULL) {
- SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, ERR_R_BUF_LIB);
- goto end;
- }
-
- if (BIO_read_filename(in, file) <= 0) {
- SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, ERR_R_SYS_LIB);
- goto end;
- }
- if (type == SSL_FILETYPE_ASN1) {
- j = ERR_R_ASN1_LIB;
- rsa = d2i_RSAPrivateKey_bio(in, NULL);
- } else if (type == SSL_FILETYPE_PEM) {
- j = ERR_R_PEM_LIB;
- rsa = PEM_read_bio_RSAPrivateKey(in, NULL,
- ssl->default_passwd_callback,
- ssl->default_passwd_callback_userdata);
- } else {
- SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE);
- goto end;
- }
- if (rsa == NULL) {
- SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, j);
- goto end;
- }
- ret = SSL_use_RSAPrivateKey(ssl, rsa);
- RSA_free(rsa);
- end:
- BIO_free(in);
- return ret;
-}
-
-int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d, long len)
-{
- int ret;
- const unsigned char *p;
- RSA *rsa;
-
- p = d;
- if ((rsa = d2i_RSAPrivateKey(NULL, &p, (long)len)) == NULL) {
- SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1, ERR_R_ASN1_LIB);
- return 0;
- }
-
- ret = SSL_use_RSAPrivateKey(ssl, rsa);
- RSA_free(rsa);
- return ret;
-}
-#endif /* !OPENSSL_NO_RSA */
-
int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey)
{
int ret;
if (pkey == NULL) {
- SSLerr(SSL_F_SSL_USE_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
ret = ssl_set_pkey(ssl->cert, pkey);
@@ -240,28 +155,31 @@ int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type)
in = BIO_new(BIO_s_file());
if (in == NULL) {
- SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB);
goto end;
}
if (BIO_read_filename(in, file) <= 0) {
- SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, ERR_R_SYS_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB);
goto end;
}
if (type == SSL_FILETYPE_PEM) {
j = ERR_R_PEM_LIB;
- pkey = PEM_read_bio_PrivateKey(in, NULL,
- ssl->default_passwd_callback,
- ssl->default_passwd_callback_userdata);
+ pkey = PEM_read_bio_PrivateKey_ex(in, NULL,
+ ssl->default_passwd_callback,
+ ssl->default_passwd_callback_userdata,
+ ssl->ctx->libctx,
+ ssl->ctx->propq);
} else if (type == SSL_FILETYPE_ASN1) {
j = ERR_R_ASN1_LIB;
- pkey = d2i_PrivateKey_bio(in, NULL);
+ pkey = d2i_PrivateKey_ex_bio(in, NULL, ssl->ctx->libctx,
+ ssl->ctx->propq);
} else {
- SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE);
goto end;
}
if (pkey == NULL) {
- SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, j);
+ ERR_raise(ERR_LIB_SSL, j);
goto end;
}
ret = SSL_use_PrivateKey(ssl, pkey);
@@ -279,8 +197,9 @@ int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d,
EVP_PKEY *pkey;
p = d;
- if ((pkey = d2i_PrivateKey(type, NULL, &p, (long)len)) == NULL) {
- SSLerr(SSL_F_SSL_USE_PRIVATEKEY_ASN1, ERR_R_ASN1_LIB);
+ if ((pkey = d2i_PrivateKey_ex(type, NULL, &p, (long)len, ssl->ctx->libctx,
+ ssl->ctx->propq)) == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_ASN1_LIB);
return 0;
}
@@ -293,12 +212,13 @@ int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x)
{
int rv;
if (x == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
+
rv = ssl_security_cert(NULL, ctx, x, 0, 1);
if (rv != 1) {
- SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE, rv);
+ ERR_raise(ERR_LIB_SSL, rv);
return 0;
}
return ssl_set_cert(ctx->cert, x);
@@ -311,20 +231,20 @@ static int ssl_set_cert(CERT *c, X509 *x)
pkey = X509_get0_pubkey(x);
if (pkey == NULL) {
- SSLerr(SSL_F_SSL_SET_CERT, SSL_R_X509_LIB);
+ ERR_raise(ERR_LIB_SSL, SSL_R_X509_LIB);
return 0;
}
if (ssl_cert_lookup_by_pkey(pkey, &i) == NULL) {
- SSLerr(SSL_F_SSL_SET_CERT, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
return 0;
}
-#ifndef OPENSSL_NO_EC
- if (i == SSL_PKEY_ECC && !EC_KEY_can_sign(EVP_PKEY_get0_EC_KEY(pkey))) {
- SSLerr(SSL_F_SSL_SET_CERT, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
+
+ if (i == SSL_PKEY_ECC && !EVP_PKEY_can_sign(pkey)) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
return 0;
}
-#endif
+
if (c->pkeys[i].privatekey != NULL) {
/*
* The return code from EVP_PKEY_copy_parameters is deliberately
@@ -356,35 +276,40 @@ static int ssl_set_cert(CERT *c, X509 *x)
int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type)
{
- int j;
+ int j = SSL_R_BAD_VALUE;
BIO *in;
int ret = 0;
- X509 *x = NULL;
+ X509 *x = NULL, *cert = NULL;
in = BIO_new(BIO_s_file());
if (in == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB);
goto end;
}
if (BIO_read_filename(in, file) <= 0) {
- SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_SYS_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB);
+ goto end;
+ }
+ if (type != SSL_FILETYPE_ASN1 && type != SSL_FILETYPE_PEM) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+ x = X509_new_ex(ctx->libctx, ctx->propq);
+ if (x == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto end;
}
if (type == SSL_FILETYPE_ASN1) {
j = ERR_R_ASN1_LIB;
- x = d2i_X509_bio(in, NULL);
+ cert = d2i_X509_bio(in, &x);
} else if (type == SSL_FILETYPE_PEM) {
j = ERR_R_PEM_LIB;
- x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
- ctx->default_passwd_callback_userdata);
- } else {
- SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, SSL_R_BAD_SSL_FILETYPE);
- goto end;
+ cert = PEM_read_bio_X509(in, &x, ctx->default_passwd_callback,
+ ctx->default_passwd_callback_userdata);
}
-
- if (x == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, j);
+ if (cert == NULL) {
+ ERR_raise(ERR_LIB_SSL, j);
goto end;
}
@@ -400,106 +325,27 @@ int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d)
X509 *x;
int ret;
- x = d2i_X509(NULL, &d, (long)len);
+ x = X509_new_ex(ctx->libctx, ctx->propq);
if (x == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1, ERR_R_ASN1_LIB);
- return 0;
- }
-
- ret = SSL_CTX_use_certificate(ctx, x);
- X509_free(x);
- return ret;
-}
-
-#ifndef OPENSSL_NO_RSA
-int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa)
-{
- int ret;
- EVP_PKEY *pkey;
-
- if (rsa == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
- if ((pkey = EVP_PKEY_new()) == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY, ERR_R_EVP_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
- RSA_up_ref(rsa);
- if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) {
- RSA_free(rsa);
- EVP_PKEY_free(pkey);
+ if (d2i_X509(&x, &d, (long)len) == NULL) {
+ X509_free(x);
+ ERR_raise(ERR_LIB_SSL, ERR_R_ASN1_LIB);
return 0;
}
- ret = ssl_set_pkey(ctx->cert, pkey);
- EVP_PKEY_free(pkey);
- return ret;
-}
-
-int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type)
-{
- int j, ret = 0;
- BIO *in;
- RSA *rsa = NULL;
-
- in = BIO_new(BIO_s_file());
- if (in == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, ERR_R_BUF_LIB);
- goto end;
- }
-
- if (BIO_read_filename(in, file) <= 0) {
- SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, ERR_R_SYS_LIB);
- goto end;
- }
- if (type == SSL_FILETYPE_ASN1) {
- j = ERR_R_ASN1_LIB;
- rsa = d2i_RSAPrivateKey_bio(in, NULL);
- } else if (type == SSL_FILETYPE_PEM) {
- j = ERR_R_PEM_LIB;
- rsa = PEM_read_bio_RSAPrivateKey(in, NULL,
- ctx->default_passwd_callback,
- ctx->default_passwd_callback_userdata);
- } else {
- SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE);
- goto end;
- }
- if (rsa == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, j);
- goto end;
- }
- ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
- RSA_free(rsa);
- end:
- BIO_free(in);
- return ret;
-}
-
-int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d,
- long len)
-{
- int ret;
- const unsigned char *p;
- RSA *rsa;
-
- p = d;
- if ((rsa = d2i_RSAPrivateKey(NULL, &p, (long)len)) == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1, ERR_R_ASN1_LIB);
- return 0;
- }
-
- ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
- RSA_free(rsa);
+ ret = SSL_CTX_use_certificate(ctx, x);
+ X509_free(x);
return ret;
}
-#endif /* !OPENSSL_NO_RSA */
int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey)
{
if (pkey == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
return ssl_set_pkey(ctx->cert, pkey);
@@ -513,28 +359,29 @@ int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
in = BIO_new(BIO_s_file());
if (in == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB);
goto end;
}
if (BIO_read_filename(in, file) <= 0) {
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_SYS_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB);
goto end;
}
if (type == SSL_FILETYPE_PEM) {
j = ERR_R_PEM_LIB;
- pkey = PEM_read_bio_PrivateKey(in, NULL,
+ pkey = PEM_read_bio_PrivateKey_ex(in, NULL,
ctx->default_passwd_callback,
- ctx->default_passwd_callback_userdata);
+ ctx->default_passwd_callback_userdata,
+ ctx->libctx, ctx->propq);
} else if (type == SSL_FILETYPE_ASN1) {
j = ERR_R_ASN1_LIB;
- pkey = d2i_PrivateKey_bio(in, NULL);
+ pkey = d2i_PrivateKey_ex_bio(in, NULL, ctx->libctx, ctx->propq);
} else {
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE);
goto end;
}
if (pkey == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, j);
+ ERR_raise(ERR_LIB_SSL, j);
goto end;
}
ret = SSL_CTX_use_PrivateKey(ctx, pkey);
@@ -552,8 +399,9 @@ int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx,
EVP_PKEY *pkey;
p = d;
- if ((pkey = d2i_PrivateKey(type, NULL, &p, (long)len)) == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1, ERR_R_ASN1_LIB);
+ if ((pkey = d2i_PrivateKey_ex(type, NULL, &p, (long)len, ctx->libctx,
+ ctx->propq)) == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_ASN1_LIB);
return 0;
}
@@ -574,6 +422,10 @@ static int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file)
X509 *x = NULL;
pem_password_cb *passwd_callback;
void *passwd_callback_userdata;
+ SSL_CTX *real_ctx = (ssl == NULL) ? ctx : ssl->ctx;
+
+ if (ctx == NULL && ssl == NULL)
+ return 0;
ERR_clear_error(); /* clear error stack for
* SSL_CTX_use_certificate() */
@@ -588,19 +440,23 @@ static int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file)
in = BIO_new(BIO_s_file());
if (in == NULL) {
- SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB);
goto end;
}
if (BIO_read_filename(in, file) <= 0) {
- SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_SYS_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB);
goto end;
}
- x = PEM_read_bio_X509_AUX(in, NULL, passwd_callback,
- passwd_callback_userdata);
+ x = X509_new_ex(real_ctx->libctx, real_ctx->propq);
if (x == NULL) {
- SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+ if (PEM_read_bio_X509_AUX(in, &x, passwd_callback,
+ passwd_callback_userdata) == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_PEM_LIB);
goto end;
}
@@ -631,23 +487,32 @@ static int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file)
goto end;
}
- while ((ca = PEM_read_bio_X509(in, NULL, passwd_callback,
- passwd_callback_userdata))
- != NULL) {
- if (ctx)
- r = SSL_CTX_add0_chain_cert(ctx, ca);
- else
- r = SSL_add0_chain_cert(ssl, ca);
- /*
- * Note that we must not free ca if it was successfully added to
- * the chain (while we must free the main certificate, since its
- * reference count is increased by SSL_CTX_use_certificate).
- */
- if (!r) {
- X509_free(ca);
- ret = 0;
+ while (1) {
+ ca = X509_new_ex(real_ctx->libctx, real_ctx->propq);
+ if (ca == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto end;
}
+ if (PEM_read_bio_X509(in, &ca, passwd_callback,
+ passwd_callback_userdata) != NULL) {
+ if (ctx)
+ r = SSL_CTX_add0_chain_cert(ctx, ca);
+ else
+ r = SSL_add0_chain_cert(ssl, ca);
+ /*
+ * Note that we must not free ca if it was successfully added to
+ * the chain (while we must free the main certificate, since its
+ * reference count is increased by SSL_CTX_use_certificate).
+ */
+ if (!r) {
+ X509_free(ca);
+ ret = 0;
+ goto end;
+ }
+ } else {
+ X509_free(ca);
+ break;
+ }
}
/* When the while loop ends, it's usually just EOF. */
err = ERR_peek_last_error();
@@ -727,34 +592,6 @@ static int serverinfoex_srv_parse_cb(SSL *s, unsigned int ext_type,
return 1;
}
-static size_t extension_contextoff(unsigned int version)
-{
- return version == SSL_SERVERINFOV1 ? 4 : 0;
-}
-
-static size_t extension_append_length(unsigned int version, size_t extension_length)
-{
- return extension_length + extension_contextoff(version);
-}
-
-static void extension_append(unsigned int version,
- const unsigned char *extension,
- const size_t extension_length,
- unsigned char *serverinfo)
-{
- const size_t contextoff = extension_contextoff(version);
-
- if (contextoff > 0) {
- /* We know this only uses the last 2 bytes */
- serverinfo[0] = 0;
- serverinfo[1] = 0;
- serverinfo[2] = (SYNTHV1CONTEXT >> 8) & 0xff;
- serverinfo[3] = SYNTHV1CONTEXT & 0xff;
- }
-
- memcpy(serverinfo + contextoff, extension, extension_length);
-}
-
static int serverinfo_srv_parse_cb(SSL *s, unsigned int ext_type,
const unsigned char *in,
size_t inlen, int *al, void *arg)
@@ -866,6 +703,34 @@ static int serverinfo_process_buffer(unsigned int version,
return 1;
}
+static size_t extension_contextoff(unsigned int version)
+{
+ return version == SSL_SERVERINFOV1 ? 4 : 0;
+}
+
+static size_t extension_append_length(unsigned int version, size_t extension_length)
+{
+ return extension_length + extension_contextoff(version);
+}
+
+static void extension_append(unsigned int version,
+ const unsigned char *extension,
+ const size_t extension_length,
+ unsigned char *serverinfo)
+{
+ const size_t contextoff = extension_contextoff(version);
+
+ if (contextoff > 0) {
+ /* We know this only uses the last 2 bytes */
+ serverinfo[0] = 0;
+ serverinfo[1] = 0;
+ serverinfo[2] = (SYNTHV1CONTEXT >> 8) & 0xff;
+ serverinfo[3] = SYNTHV1CONTEXT & 0xff;
+ }
+
+ memcpy(serverinfo + contextoff, extension, extension_length);
+}
+
int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version,
const unsigned char *serverinfo,
size_t serverinfo_length)
@@ -873,7 +738,7 @@ int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version,
unsigned char *new_serverinfo = NULL;
if (ctx == NULL || serverinfo == NULL || serverinfo_length == 0) {
- SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (version == SSL_SERVERINFOV1) {
@@ -888,7 +753,7 @@ int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version,
sinfo = OPENSSL_malloc(sinfo_length);
if (sinfo == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -902,17 +767,17 @@ int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version,
}
if (!serverinfo_process_buffer(version, serverinfo, serverinfo_length,
NULL)) {
- SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, SSL_R_INVALID_SERVERINFO_DATA);
+ ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_SERVERINFO_DATA);
return 0;
}
if (ctx->cert->key == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
new_serverinfo = OPENSSL_realloc(ctx->cert->key->serverinfo,
serverinfo_length);
if (new_serverinfo == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
ctx->cert->key->serverinfo = new_serverinfo;
@@ -925,7 +790,7 @@ int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version,
*/
if (!serverinfo_process_buffer(version, serverinfo, serverinfo_length,
ctx)) {
- SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, SSL_R_INVALID_SERVERINFO_DATA);
+ ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_SERVERINFO_DATA);
return 0;
}
return 1;
@@ -947,24 +812,25 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file)
long extension_length = 0;
char *name = NULL;
char *header = NULL;
- char namePrefix1[] = "SERVERINFO FOR ";
- char namePrefix2[] = "SERVERINFOV2 FOR ";
+ static const char namePrefix1[] = "SERVERINFO FOR ";
+ static const char namePrefix2[] = "SERVERINFOV2 FOR ";
+ unsigned int name_len;
int ret = 0;
BIO *bin = NULL;
size_t num_extensions = 0;
if (ctx == NULL || file == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_PASSED_NULL_PARAMETER);
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
goto end;
}
bin = BIO_new(BIO_s_file());
if (bin == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB);
goto end;
}
if (BIO_read_filename(bin, file) <= 0) {
- SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_SYS_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB);
goto end;
}
@@ -978,28 +844,26 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file)
* There must be at least one extension in this file
*/
if (num_extensions == 0) {
- SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE,
- SSL_R_NO_PEM_EXTENSIONS);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_PEM_EXTENSIONS);
goto end;
} else /* End of file, we're done */
break;
}
/* Check that PEM name starts with "BEGIN SERVERINFO FOR " */
- if (strlen(name) < strlen(namePrefix1)) {
- SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_PEM_NAME_TOO_SHORT);
+ name_len = strlen(name);
+ if (name_len < sizeof(namePrefix1) - 1) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_PEM_NAME_TOO_SHORT);
goto end;
}
- if (strncmp(name, namePrefix1, strlen(namePrefix1)) == 0) {
+ if (strncmp(name, namePrefix1, sizeof(namePrefix1) - 1) == 0) {
version = SSL_SERVERINFOV1;
} else {
- if (strlen(name) < strlen(namePrefix2)) {
- SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE,
- SSL_R_PEM_NAME_TOO_SHORT);
+ if (name_len < sizeof(namePrefix2) - 1) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_PEM_NAME_TOO_SHORT);
goto end;
}
- if (strncmp(name, namePrefix2, strlen(namePrefix2)) != 0) {
- SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE,
- SSL_R_PEM_NAME_BAD_PREFIX);
+ if (strncmp(name, namePrefix2, sizeof(namePrefix2) - 1) != 0) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_PEM_NAME_BAD_PREFIX);
goto end;
}
version = SSL_SERVERINFOV2;
@@ -1012,7 +876,7 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file)
if (extension_length < 4
|| (extension[2] << 8) + extension[3]
!= extension_length - 4) {
- SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_BAD_DATA);
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_DATA);
goto end;
}
} else {
@@ -1020,7 +884,7 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file)
if (extension_length < 8
|| (extension[6] << 8) + extension[7]
!= extension_length - 8) {
- SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_BAD_DATA);
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_DATA);
goto end;
}
}
@@ -1028,7 +892,7 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file)
append_length = extension_append_length(version, extension_length);
tmp = OPENSSL_realloc(serverinfo, serverinfo_length + append_length);
if (tmp == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto end;
}
serverinfo = tmp;
@@ -1070,13 +934,13 @@ static int ssl_set_cert_and_key(SSL *ssl, SSL_CTX *ctx, X509 *x509, EVP_PKEY *pr
/* Do all security checks before anything else */
rv = ssl_security_cert(ssl, ctx, x509, 0, 1);
if (rv != 1) {
- SSLerr(SSL_F_SSL_SET_CERT_AND_KEY, rv);
+ ERR_raise(ERR_LIB_SSL, rv);
goto out;
}
for (j = 0; j < sk_X509_num(chain); j++) {
rv = ssl_security_cert(ssl, ctx, sk_X509_value(chain, j), 0, 0);
if (rv != 1) {
- SSLerr(SSL_F_SSL_SET_CERT_AND_KEY, rv);
+ ERR_raise(ERR_LIB_SSL, rv);
goto out;
}
}
@@ -1091,25 +955,31 @@ static int ssl_set_cert_and_key(SSL *ssl, SSL_CTX *ctx, X509 *x509, EVP_PKEY *pr
if (EVP_PKEY_missing_parameters(privatekey)) {
if (EVP_PKEY_missing_parameters(pubkey)) {
/* nobody has parameters? - error */
- SSLerr(SSL_F_SSL_SET_CERT_AND_KEY, SSL_R_MISSING_PARAMETERS);
+ ERR_raise(ERR_LIB_SSL, SSL_R_MISSING_PARAMETERS);
goto out;
} else {
/* copy to privatekey from pubkey */
- EVP_PKEY_copy_parameters(privatekey, pubkey);
+ if (!EVP_PKEY_copy_parameters(privatekey, pubkey)) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_COPY_PARAMETERS_FAILED);
+ goto out;
+ }
}
} else if (EVP_PKEY_missing_parameters(pubkey)) {
/* copy to pubkey from privatekey */
- EVP_PKEY_copy_parameters(pubkey, privatekey);
+ if (!EVP_PKEY_copy_parameters(pubkey, privatekey)) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_COPY_PARAMETERS_FAILED);
+ goto out;
+ }
} /* else both have parameters */
/* check that key <-> cert match */
- if (EVP_PKEY_cmp(pubkey, privatekey) != 1) {
- SSLerr(SSL_F_SSL_SET_CERT_AND_KEY, SSL_R_PRIVATE_KEY_MISMATCH);
+ if (EVP_PKEY_eq(pubkey, privatekey) != 1) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_PRIVATE_KEY_MISMATCH);
goto out;
}
}
if (ssl_cert_lookup_by_pkey(pubkey, &i) == NULL) {
- SSLerr(SSL_F_SSL_SET_CERT_AND_KEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
goto out;
}
@@ -1117,14 +987,14 @@ static int ssl_set_cert_and_key(SSL *ssl, SSL_CTX *ctx, X509 *x509, EVP_PKEY *pr
|| c->pkeys[i].privatekey != NULL
|| c->pkeys[i].chain != NULL)) {
/* No override, and something already there */
- SSLerr(SSL_F_SSL_SET_CERT_AND_KEY, SSL_R_NOT_REPLACING_CERTIFICATE);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NOT_REPLACING_CERTIFICATE);
goto out;
}
if (chain != NULL) {
dup_chain = X509_chain_up_ref(chain);
if (dup_chain == NULL) {
- SSLerr(SSL_F_SSL_SET_CERT_AND_KEY, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto out;
}
}
diff --git a/ssl/ssl_rsa_legacy.c b/ssl/ssl_rsa_legacy.c
new file mode 100644
index 000000000000..49cd7a3bbaa5
--- /dev/null
+++ b/ssl/ssl_rsa_legacy.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* We need to use the deprecated RSA low level calls */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+#include <openssl/ssl.h>
+
+int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa)
+{
+ EVP_PKEY *pkey;
+ int ret;
+
+ if (rsa == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if ((pkey = EVP_PKEY_new()) == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
+ return 0;
+ }
+
+ RSA_up_ref(rsa);
+ if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) {
+ RSA_free(rsa);
+ EVP_PKEY_free(pkey);
+ return 0;
+ }
+
+ ret = SSL_use_PrivateKey(ssl, pkey);
+ EVP_PKEY_free(pkey);
+ return ret;
+}
+
+int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type)
+{
+ int j, ret = 0;
+ BIO *in;
+ RSA *rsa = NULL;
+
+ in = BIO_new(BIO_s_file());
+ if (in == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(in, file) <= 0) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB);
+ goto end;
+ }
+ if (type == SSL_FILETYPE_ASN1) {
+ j = ERR_R_ASN1_LIB;
+ rsa = d2i_RSAPrivateKey_bio(in, NULL);
+ } else if (type == SSL_FILETYPE_PEM) {
+ j = ERR_R_PEM_LIB;
+ rsa = PEM_read_bio_RSAPrivateKey(in, NULL,
+ SSL_get_default_passwd_cb(ssl),
+ SSL_get_default_passwd_cb_userdata(ssl));
+ } else {
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+ if (rsa == NULL) {
+ ERR_raise(ERR_LIB_SSL, j);
+ goto end;
+ }
+ ret = SSL_use_RSAPrivateKey(ssl, rsa);
+ RSA_free(rsa);
+ end:
+ BIO_free(in);
+ return ret;
+}
+
+int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d, long len)
+{
+ int ret;
+ const unsigned char *p;
+ RSA *rsa;
+
+ p = d;
+ if ((rsa = d2i_RSAPrivateKey(NULL, &p, (long)len)) == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_ASN1_LIB);
+ return 0;
+ }
+
+ ret = SSL_use_RSAPrivateKey(ssl, rsa);
+ RSA_free(rsa);
+ return ret;
+}
+
+int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa)
+{
+ int ret;
+ EVP_PKEY *pkey;
+
+ if (rsa == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if ((pkey = EVP_PKEY_new()) == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
+ return 0;
+ }
+
+ RSA_up_ref(rsa);
+ if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) {
+ RSA_free(rsa);
+ EVP_PKEY_free(pkey);
+ return 0;
+ }
+
+ ret = SSL_CTX_use_PrivateKey(ctx, pkey);
+ EVP_PKEY_free(pkey);
+ return ret;
+}
+
+int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type)
+{
+ int j, ret = 0;
+ BIO *in;
+ RSA *rsa = NULL;
+
+ in = BIO_new(BIO_s_file());
+ if (in == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(in, file) <= 0) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB);
+ goto end;
+ }
+ if (type == SSL_FILETYPE_ASN1) {
+ j = ERR_R_ASN1_LIB;
+ rsa = d2i_RSAPrivateKey_bio(in, NULL);
+ } else if (type == SSL_FILETYPE_PEM) {
+ j = ERR_R_PEM_LIB;
+ rsa = PEM_read_bio_RSAPrivateKey(in, NULL,
+ SSL_CTX_get_default_passwd_cb(ctx),
+ SSL_CTX_get_default_passwd_cb_userdata(ctx));
+ } else {
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+ if (rsa == NULL) {
+ ERR_raise(ERR_LIB_SSL, j);
+ goto end;
+ }
+ ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
+ RSA_free(rsa);
+ end:
+ BIO_free(in);
+ return ret;
+}
+
+int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d,
+ long len)
+{
+ int ret;
+ const unsigned char *p;
+ RSA *rsa;
+
+ p = d;
+ if ((rsa = d2i_RSAPrivateKey(NULL, &p, (long)len)) == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_ASN1_LIB);
+ return 0;
+ }
+
+ ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
+ RSA_free(rsa);
+ return ret;
+}
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index cda6b7cc5bcf..68b57a532bfe 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -1,13 +1,17 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#if defined(__TANDEM) && defined(_SPT_MODEL_)
+# include <spthread.h>
+# include <spt_extensions.h> /* timeval */
+#endif
#include <stdio.h>
#include <openssl/rand.h>
#include <openssl/engine.h>
@@ -20,6 +24,58 @@ static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s);
static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
+DEFINE_STACK_OF(SSL_SESSION)
+
+__owur static int sess_timedout(time_t t, SSL_SESSION *ss)
+{
+ /* if timeout overflowed, it can never timeout! */
+ if (ss->timeout_ovf)
+ return 0;
+ return t > ss->calc_timeout;
+}
+
+/*
+ * Returns -1/0/+1 as other XXXcmp-type functions
+ * Takes overflow of calculated timeout into consideration
+ */
+__owur static int timeoutcmp(SSL_SESSION *a, SSL_SESSION *b)
+{
+ /* if only one overflowed, then it is greater */
+ if (a->timeout_ovf && !b->timeout_ovf)
+ return 1;
+ if (!a->timeout_ovf && b->timeout_ovf)
+ return -1;
+ /* No overflow, or both overflowed, so straight compare is safe */
+ if (a->calc_timeout < b->calc_timeout)
+ return -1;
+ if (a->calc_timeout > b->calc_timeout)
+ return 1;
+ return 0;
+}
+
+/*
+ * Calculates effective timeout, saving overflow state
+ * Locking must be done by the caller of this function
+ */
+void ssl_session_calculate_timeout(SSL_SESSION *ss)
+{
+ /* Force positive timeout */
+ if (ss->timeout < 0)
+ ss->timeout = 0;
+ ss->calc_timeout = ss->time + ss->timeout;
+ /*
+ * |timeout| is always zero or positive, so the check for
+ * overflow only needs to consider if |time| is positive
+ */
+ ss->timeout_ovf = ss->time > 0 && ss->calc_timeout < ss->time;
+ /*
+ * N.B. Realistic overflow can only occur in our lifetimes on a
+ * 32-bit machine in January 2038.
+ * However, There are no controls to limit the |timeout|
+ * value, except to keep it positive.
+ */
+}
+
/*
* SSL_get_session() and SSL_get1_session() are problematic in TLS1.3 because,
* unlike in earlier protocol versions, the session ticket may not have been
@@ -44,7 +100,8 @@ SSL_SESSION *SSL_get1_session(SSL *ssl)
* somebody doesn't free ssl->session between when we check it's non-null
* and when we up the reference count.
*/
- CRYPTO_THREAD_read_lock(ssl->lock);
+ if (!CRYPTO_THREAD_read_lock(ssl->lock))
+ return NULL;
sess = ssl->session;
if (sess)
SSL_SESSION_up_ref(sess);
@@ -71,17 +128,18 @@ SSL_SESSION *SSL_SESSION_new(void)
ss = OPENSSL_zalloc(sizeof(*ss));
if (ss == NULL) {
- SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
ss->references = 1;
ss->timeout = 60 * 5 + 4; /* 5 minute timeout by default */
- ss->time = (unsigned long)time(NULL);
+ ss->time = time(NULL);
+ ssl_session_calculate_timeout(ss);
ss->lock = CRYPTO_THREAD_lock_new();
if (ss->lock == NULL) {
- SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ss);
return NULL;
}
@@ -94,7 +152,7 @@ SSL_SESSION *SSL_SESSION_new(void)
return ss;
}
-SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *src)
+SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src)
{
return ssl_session_dup(src, 1);
}
@@ -103,7 +161,7 @@ SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *src)
* Create a new SSL_SESSION and duplicate the contents of |src| into it. If
* ticket == 0 then no ticket information is duplicated, otherwise it is.
*/
-SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
+SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket)
{
SSL_SESSION *dest;
@@ -218,7 +276,7 @@ SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
return dest;
err:
- SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
SSL_SESSION_free(dest);
return NULL;
}
@@ -259,7 +317,7 @@ static int def_generate_session_id(SSL *ssl, unsigned char *id,
{
unsigned int retry = 0;
do
- if (RAND_bytes(id, *id_len) <= 0)
+ if (RAND_bytes_ex(ssl->ctx->libctx, id, *id_len, 0) <= 0)
return 0;
while (SSL_has_matching_session_id(ssl, id, *id_len) &&
(++retry < MAX_SESS_ID_ATTEMPTS)) ;
@@ -294,8 +352,7 @@ int ssl_generate_session_id(SSL *s, SSL_SESSION *ss)
ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
break;
default:
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID,
- SSL_R_UNSUPPORTED_SSL_VERSION);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_UNSUPPORTED_SSL_VERSION);
return 0;
}
@@ -320,8 +377,14 @@ int ssl_generate_session_id(SSL *s, SSL_SESSION *ss)
}
/* Choose which callback will set the session ID */
- CRYPTO_THREAD_read_lock(s->lock);
- CRYPTO_THREAD_read_lock(s->session_ctx->lock);
+ if (!CRYPTO_THREAD_read_lock(s->lock))
+ return 0;
+ if (!CRYPTO_THREAD_read_lock(s->session_ctx->lock)) {
+ CRYPTO_THREAD_unlock(s->lock);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
+ return 0;
+ }
if (s->generate_session_id)
cb = s->generate_session_id;
else if (s->session_ctx->generate_session_id)
@@ -333,7 +396,7 @@ int ssl_generate_session_id(SSL *s, SSL_SESSION *ss)
tmp = (int)ss->session_id_length;
if (!cb(s, ss->session_id, &tmp)) {
/* The callback failed */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID,
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
return 0;
}
@@ -343,7 +406,7 @@ int ssl_generate_session_id(SSL *s, SSL_SESSION *ss)
*/
if (tmp == 0 || tmp > ss->session_id_length) {
/* The callback set an illegal length */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID,
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
return 0;
}
@@ -351,8 +414,7 @@ int ssl_generate_session_id(SSL *s, SSL_SESSION *ss)
/* Finally, check for a conflict */
if (SSL_has_matching_session_id(s, ss->session_id,
(unsigned int)ss->session_id_length)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID,
- SSL_R_SSL_SESSION_ID_CONFLICT);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_SSL_SESSION_ID_CONFLICT);
return 0;
}
@@ -366,8 +428,7 @@ int ssl_get_new_session(SSL *s, int session)
SSL_SESSION *ss = NULL;
if ((ss = SSL_SESSION_new()) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -376,6 +437,7 @@ int ssl_get_new_session(SSL *s, int session)
ss->timeout = SSL_get_default_timeout(s);
else
ss->timeout = s->session_ctx->session_timeout;
+ ssl_session_calculate_timeout(ss);
SSL_SESSION_free(s->session);
s->session = NULL;
@@ -398,8 +460,7 @@ int ssl_get_new_session(SSL *s, int session)
}
if (s->sid_ctx_length > sizeof(ss->sid_ctx)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
SSL_SESSION_free(ss);
return 0;
}
@@ -410,7 +471,7 @@ int ssl_get_new_session(SSL *s, int session)
ss->verify_result = X509_V_OK;
/* If client supports extended master secret set it in session */
- if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS)
+ if (s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS)
ss->flags |= SSL_SESS_FLAG_EXTMS;
return 1;
@@ -432,7 +493,8 @@ SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id,
memcpy(data.session_id, sess_id, sess_id_len);
data.session_id_length = sess_id_len;
- CRYPTO_THREAD_read_lock(s->session_ctx->lock);
+ if (!CRYPTO_THREAD_read_lock(s->session_ctx->lock))
+ return NULL;
ret = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data);
if (ret != NULL) {
/* don't allow other threads to steal it: */
@@ -440,7 +502,7 @@ SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id,
}
CRYPTO_THREAD_unlock(s->session_ctx->lock);
if (ret == NULL)
- tsan_counter(&s->session_ctx->stats.sess_miss);
+ ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_miss);
}
if (ret == NULL && s->session_ctx->get_session_cb != NULL) {
@@ -449,7 +511,8 @@ SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id,
ret = s->session_ctx->get_session_cb(s, sess_id, sess_id_len, &copy);
if (ret != NULL) {
- tsan_counter(&s->session_ctx->stats.sess_cb_hit);
+ ssl_tsan_counter(s->session_ctx,
+ &s->session_ctx->stats.sess_cb_hit);
/*
* Increment reference count now if the session callback asks us
@@ -527,8 +590,7 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello)
case SSL_TICKET_FATAL_ERR_MALLOC:
case SSL_TICKET_FATAL_ERR_OTHER:
fatal = 1;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_PREV_SESSION,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
case SSL_TICKET_NONE:
case SSL_TICKET_EMPTY:
@@ -574,14 +636,14 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello)
* noticing).
*/
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_PREV_SESSION,
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
fatal = 1;
goto err;
}
- if (ret->timeout < (long)(time(NULL) - ret->time)) { /* timeout */
- tsan_counter(&s->session_ctx->stats.sess_timeout);
+ if (sess_timedout(time(NULL), ret)) {
+ ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_timeout);
if (try_session_cache) {
/* session was from the cache, so remove it */
SSL_CTX_remove_session(s->session_ctx, ret);
@@ -592,13 +654,12 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello)
/* Check extended master secret extension consistency */
if (ret->flags & SSL_SESS_FLAG_EXTMS) {
/* If old session includes extms, but new does not: abort handshake */
- if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL_GET_PREV_SESSION,
- SSL_R_INCONSISTENT_EXTMS);
+ if (!(s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_INCONSISTENT_EXTMS);
fatal = 1;
goto err;
}
- } else if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) {
+ } else if (s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS) {
/* If new session includes extms, but old does not: do not resume */
goto err;
}
@@ -609,7 +670,7 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello)
s->session = ret;
}
- tsan_counter(&s->session_ctx->stats.sess_hit);
+ ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_hit);
s->verify_result = s->session->verify_result;
return 1;
@@ -649,7 +710,10 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
* if session c is in already in cache, we take back the increment later
*/
- CRYPTO_THREAD_write_lock(ctx->lock);
+ if (!CRYPTO_THREAD_write_lock(ctx->lock)) {
+ SSL_SESSION_free(c);
+ return 0;
+ }
s = lh_SSL_SESSION_insert(ctx->sessions, c);
/*
@@ -679,34 +743,41 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
s = c;
}
- /* Put at the head of the queue unless it is already in the cache */
- if (s == NULL)
- SSL_SESSION_list_add(ctx, c);
+ /* Adjust last used time, and add back into the cache at the appropriate spot */
+ if (ctx->session_cache_mode & SSL_SESS_CACHE_UPDATE_TIME) {
+ c->time = time(NULL);
+ ssl_session_calculate_timeout(c);
+ }
- if (s != NULL) {
- /*
- * existing cache entry -- decrement previously incremented reference
- * count because it already takes into account the cache
- */
-
- SSL_SESSION_free(s); /* s == c */
- ret = 0;
- } else {
+ if (s == NULL) {
/*
* new cache entry -- remove old ones if cache has become too large
+ * delete cache entry *before* add, so we don't remove the one we're adding!
*/
ret = 1;
if (SSL_CTX_sess_get_cache_size(ctx) > 0) {
- while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) {
+ while (SSL_CTX_sess_number(ctx) >= SSL_CTX_sess_get_cache_size(ctx)) {
if (!remove_session_lock(ctx, ctx->session_cache_tail, 0))
break;
else
- tsan_counter(&ctx->stats.sess_cache_full);
+ ssl_tsan_counter(ctx, &ctx->stats.sess_cache_full);
}
}
}
+
+ SSL_SESSION_list_add(ctx, c);
+
+ if (s != NULL) {
+ /*
+ * existing cache entry -- decrement previously incremented reference
+ * count because it already takes into account the cache
+ */
+
+ SSL_SESSION_free(s); /* s == c */
+ ret = 0;
+ }
CRYPTO_THREAD_unlock(ctx->lock);
return ret;
}
@@ -722,8 +793,10 @@ static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck)
int ret = 0;
if ((c != NULL) && (c->session_id_length != 0)) {
- if (lck)
- CRYPTO_THREAD_write_lock(ctx->lock);
+ if (lck) {
+ if (!CRYPTO_THREAD_write_lock(ctx->lock))
+ return 0;
+ }
if ((r = lh_SSL_SESSION_retrieve(ctx->sessions, c)) != NULL) {
ret = 1;
r = lh_SSL_SESSION_delete(ctx->sessions, r);
@@ -739,8 +812,7 @@ static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck)
if (ret)
SSL_SESSION_free(r);
- } else
- ret = 0;
+ }
return ret;
}
@@ -811,8 +883,7 @@ int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid,
unsigned int sid_len)
{
if (sid_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
- SSLerr(SSL_F_SSL_SESSION_SET1_ID,
- SSL_R_SSL_SESSION_ID_TOO_LONG);
+ ERR_raise(ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_TOO_LONG);
return 0;
}
s->session_id_length = sid_len;
@@ -823,9 +894,21 @@ int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid,
long SSL_SESSION_set_timeout(SSL_SESSION *s, long t)
{
- if (s == NULL)
+ time_t new_timeout = (time_t)t;
+
+ if (s == NULL || t < 0)
return 0;
- s->timeout = t;
+ if (s->owner != NULL) {
+ if (!CRYPTO_THREAD_write_lock(s->owner->lock))
+ return 0;
+ s->timeout = new_timeout;
+ ssl_session_calculate_timeout(s);
+ SSL_SESSION_list_add(s->owner, s);
+ CRYPTO_THREAD_unlock(s->owner->lock);
+ } else {
+ s->timeout = new_timeout;
+ ssl_session_calculate_timeout(s);
+ }
return 1;
}
@@ -833,21 +916,33 @@ long SSL_SESSION_get_timeout(const SSL_SESSION *s)
{
if (s == NULL)
return 0;
- return s->timeout;
+ return (long)s->timeout;
}
long SSL_SESSION_get_time(const SSL_SESSION *s)
{
if (s == NULL)
return 0;
- return s->time;
+ return (long)s->time;
}
long SSL_SESSION_set_time(SSL_SESSION *s, long t)
{
+ time_t new_time = (time_t)t;
+
if (s == NULL)
return 0;
- s->time = t;
+ if (s->owner != NULL) {
+ if (!CRYPTO_THREAD_write_lock(s->owner->lock))
+ return 0;
+ s->time = new_time;
+ ssl_session_calculate_timeout(s);
+ SSL_SESSION_list_add(s->owner, s);
+ CRYPTO_THREAD_unlock(s->owner->lock);
+ } else {
+ s->time = new_time;
+ ssl_session_calculate_timeout(s);
+ }
return t;
}
@@ -956,8 +1051,7 @@ int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx,
unsigned int sid_ctx_len)
{
if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
- SSLerr(SSL_F_SSL_SESSION_SET1_ID_CONTEXT,
- SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
+ ERR_raise(ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
return 0;
}
s->sid_ctx_length = sid_ctx_len;
@@ -1023,7 +1117,7 @@ int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
s->ext.session_ticket =
OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
if (s->ext.session_ticket == NULL) {
- SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -1042,46 +1136,52 @@ int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
return 0;
}
-typedef struct timeout_param_st {
- SSL_CTX *ctx;
- long time;
- LHASH_OF(SSL_SESSION) *cache;
-} TIMEOUT_PARAM;
-
-static void timeout_cb(SSL_SESSION *s, TIMEOUT_PARAM *p)
-{
- if ((p->time == 0) || (p->time > (s->time + s->timeout))) { /* timeout */
- /*
- * The reason we don't call SSL_CTX_remove_session() is to save on
- * locking overhead
- */
- (void)lh_SSL_SESSION_delete(p->cache, s);
- SSL_SESSION_list_remove(p->ctx, s);
- s->not_resumable = 1;
- if (p->ctx->remove_session_cb != NULL)
- p->ctx->remove_session_cb(p->ctx, s);
- SSL_SESSION_free(s);
- }
-}
-
-IMPLEMENT_LHASH_DOALL_ARG(SSL_SESSION, TIMEOUT_PARAM);
-
void SSL_CTX_flush_sessions(SSL_CTX *s, long t)
{
+ STACK_OF(SSL_SESSION) *sk;
+ SSL_SESSION *current;
unsigned long i;
- TIMEOUT_PARAM tp;
- tp.ctx = s;
- tp.cache = s->sessions;
- if (tp.cache == NULL)
+ if (!CRYPTO_THREAD_write_lock(s->lock))
return;
- tp.time = t;
- CRYPTO_THREAD_write_lock(s->lock);
+
+ sk = sk_SSL_SESSION_new_null();
i = lh_SSL_SESSION_get_down_load(s->sessions);
lh_SSL_SESSION_set_down_load(s->sessions, 0);
- lh_SSL_SESSION_doall_TIMEOUT_PARAM(tp.cache, timeout_cb, &tp);
+
+ /*
+ * Iterate over the list from the back (oldest), and stop
+ * when a session can no longer be removed.
+ * Add the session to a temporary list to be freed outside
+ * the SSL_CTX lock.
+ * But still do the remove_session_cb() within the lock.
+ */
+ while (s->session_cache_tail != NULL) {
+ current = s->session_cache_tail;
+ if (t == 0 || sess_timedout((time_t)t, current)) {
+ lh_SSL_SESSION_delete(s->sessions, current);
+ SSL_SESSION_list_remove(s, current);
+ current->not_resumable = 1;
+ if (s->remove_session_cb != NULL)
+ s->remove_session_cb(s, current);
+ /*
+ * Throw the session on a stack, it's entirely plausible
+ * that while freeing outside the critical section, the
+ * session could be re-added, so avoid using the next/prev
+ * pointers. If the stack failed to create, or the session
+ * couldn't be put on the stack, just free it here
+ */
+ if (sk == NULL || !sk_SSL_SESSION_push(sk, current))
+ SSL_SESSION_free(current);
+ } else {
+ break;
+ }
+ }
+
lh_SSL_SESSION_set_down_load(s->sessions, i);
CRYPTO_THREAD_unlock(s->lock);
+
+ sk_SSL_SESSION_pop_free(sk, SSL_SESSION_free);
}
int ssl_clear_bad_session(SSL *s)
@@ -1123,10 +1223,13 @@ static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s)
}
}
s->prev = s->next = NULL;
+ s->owner = NULL;
}
static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s)
{
+ SSL_SESSION *next;
+
if ((s->next != NULL) && (s->prev != NULL))
SSL_SESSION_list_remove(ctx, s);
@@ -1136,11 +1239,40 @@ static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s)
s->prev = (SSL_SESSION *)&(ctx->session_cache_head);
s->next = (SSL_SESSION *)&(ctx->session_cache_tail);
} else {
- s->next = ctx->session_cache_head;
- s->next->prev = s;
- s->prev = (SSL_SESSION *)&(ctx->session_cache_head);
- ctx->session_cache_head = s;
+ if (timeoutcmp(s, ctx->session_cache_head) >= 0) {
+ /*
+ * if we timeout after (or the same time as) the first
+ * session, put us first - usual case
+ */
+ s->next = ctx->session_cache_head;
+ s->next->prev = s;
+ s->prev = (SSL_SESSION *)&(ctx->session_cache_head);
+ ctx->session_cache_head = s;
+ } else if (timeoutcmp(s, ctx->session_cache_tail) < 0) {
+ /* if we timeout before the last session, put us last */
+ s->prev = ctx->session_cache_tail;
+ s->prev->next = s;
+ s->next = (SSL_SESSION *)&(ctx->session_cache_tail);
+ ctx->session_cache_tail = s;
+ } else {
+ /*
+ * we timeout somewhere in-between - if there is only
+ * one session in the cache it will be caught above
+ */
+ next = ctx->session_cache_head->next;
+ while (next != (SSL_SESSION*)&(ctx->session_cache_tail)) {
+ if (timeoutcmp(s, next) >= 0) {
+ s->next = next;
+ s->prev = next->prev;
+ next->prev->next = s;
+ next->prev = s;
+ break;
+ }
+ next = next->next;
+ }
+ }
}
+ s->owner = ctx;
}
void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
@@ -1202,24 +1334,6 @@ int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509,
return ctx->client_cert_cb;
}
-#ifndef OPENSSL_NO_ENGINE
-int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e)
-{
- if (!ENGINE_init(e)) {
- SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, ERR_R_ENGINE_LIB);
- return 0;
- }
- if (!ENGINE_get_ssl_client_cert_function(e)) {
- SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE,
- SSL_R_NO_CLIENT_CERT_METHOD);
- ENGINE_finish(e);
- return 0;
- }
- ctx->client_cert_engine = e;
- return 1;
-}
-#endif
-
void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
int (*cb) (SSL *ssl,
unsigned char *cookie,
diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c
index ca51c0331c22..f2316f7c9850 100644
--- a/ssl/ssl_stat.c
+++ b/ssl/ssl_stat.c
@@ -1,8 +1,8 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -137,9 +137,9 @@ const char *SSL_state_string(const SSL *s)
case TLS_ST_CW_NEXT_PROTO:
return "TWNP";
case TLS_ST_BEFORE:
- return "PINIT ";
+ return "PINIT";
case TLS_ST_OK:
- return "SSLOK ";
+ return "SSLOK";
case TLS_ST_CW_CLNT_HELLO:
return "TWCH";
case TLS_ST_CR_SRVR_HELLO:
@@ -201,7 +201,7 @@ const char *SSL_state_string(const SSL *s)
case TLS_ST_CR_CERT_VRFY:
return "TRSCV";
case TLS_ST_SW_CERT_VRFY:
- return "TRSCV";
+ return "TWSCV";
case TLS_ST_CR_HELLO_REQ:
return "TRHR";
case TLS_ST_SW_KEY_UPDATE:
@@ -221,7 +221,7 @@ const char *SSL_state_string(const SSL *s)
case TLS_ST_SR_END_OF_EARLY_DATA:
return "TWEOED";
default:
- return "UNKWN ";
+ return "UNKWN";
}
}
diff --git a/ssl/ssl_txt.c b/ssl/ssl_txt.c
index 759e1873e6b1..212fe00962ea 100644
--- a/ssl/ssl_txt.c
+++ b/ssl/ssl_txt.c
@@ -2,7 +2,7 @@
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -19,7 +19,7 @@ int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *x)
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
- SSLerr(SSL_F_SSL_SESSION_PRINT_FP, ERR_R_BUF_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
@@ -107,7 +107,6 @@ int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
if (x->ext.tick) {
if (BIO_puts(bp, "\n TLS session ticket:\n") <= 0)
goto err;
- /* TODO(size_t): Convert this call */
if (BIO_dump_indent
(bp, (const char *)x->ext.tick, (int)x->ext.ticklen, 4)
<= 0)
@@ -117,7 +116,7 @@ int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
if (x->compress_meth != 0) {
SSL_COMP *comp = NULL;
- if (!ssl_cipher_get_evp(x, NULL, NULL, NULL, NULL, &comp, 0))
+ if (!ssl_cipher_get_evp(NULL, x, NULL, NULL, NULL, NULL, &comp, 0))
goto err;
if (comp == NULL) {
if (BIO_printf(bp, "\n Compression: %d", x->compress_meth) <= 0)
diff --git a/ssl/ssl_utst.c b/ssl/ssl_utst.c
index 487f56e53935..690db6d49746 100644
--- a/ssl/ssl_utst.c
+++ b/ssl/ssl_utst.c
@@ -1,7 +1,7 @@
/*
* Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
diff --git a/ssl/sslerr.h b/ssl/sslerr.h
new file mode 100644
index 000000000000..5c5b760e3821
--- /dev/null
+++ b/ssl/sslerr.h
@@ -0,0 +1,27 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_SSLERR_H
+# define OSSL_SSLERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+int ossl_err_load_SSL_strings(void);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/ssl/statem/README b/ssl/statem/README
deleted file mode 100644
index bafe33060c92..000000000000
--- a/ssl/statem/README
+++ /dev/null
@@ -1,63 +0,0 @@
-State Machine Design
-====================
-
-This file provides some guidance on the thinking behind the design of the
-state machine code to aid future maintenance.
-
-The state machine code replaces an older state machine present in OpenSSL
-versions 1.0.2 and below. The new state machine has the following objectives:
- - Remove duplication of state code between client and server
- - Remove duplication of state code between TLS and DTLS
- - Simplify transitions and bring the logic together in a single location
- so that it is easier to validate
- - Remove duplication of code between each of the message handling functions
- - Receive a message first and then work out whether that is a valid
- transition - not the other way around (the other way causes lots of issues
- where we are expecting one type of message next but actually get something
- else)
- - Separate message flow state from handshake state (in order to better
- understand each)
- - message flow state = when to flush buffers; handling restarts in the
- event of NBIO events; handling the common flow of steps for reading a
- message and the common flow of steps for writing a message etc
- - handshake state = what handshake message are we working on now
- - Control complexity: only the state machine can change state: keep all
- the state changes local to the state machine component
-
-The message flow state machine is divided into a reading sub-state machine and a
-writing sub-state machine. See the source comments in statem.c for a more
-detailed description of the various states and transitions possible.
-
-Conceptually the state machine component is designed as follows:
-
- libssl
- |
----------------------------|-----statem.h--------------------------------------
- |
- _______V____________________
- | |
- | statem.c |
- | |
- | Core state machine code |
- |____________________________|
- statem_local.h ^ ^
- _________| |_______
- | |
- _____________|____________ _____________|____________
- | | | |
- | statem_clnt.c | | statem_srvr.c |
- | | | |
- | TLS/DTLS client specific | | TLS/DTLS server specific |
- | state machine code | | state machine code |
- |__________________________| |__________________________|
- | |_______________|__ |
- | ________________| | |
- | | | |
- ____________V_______V________ ________V______V_______________
- | | | |
- | statem_lib.c | | statem_dtls.c |
- | | | |
- | Non core functions common | | Non core functions common to |
- | to both servers and clients | | both DTLS servers and clients |
- |_____________________________| |_______________________________|
-
diff --git a/ssl/statem/README.md b/ssl/statem/README.md
new file mode 100644
index 000000000000..ee49ed986371
--- /dev/null
+++ b/ssl/statem/README.md
@@ -0,0 +1,63 @@
+State Machine Design
+====================
+
+This file provides some guidance on the thinking behind the design of the
+state machine code to aid future maintenance.
+
+The state machine code replaces an older state machine present in OpenSSL
+versions 1.0.2 and below. The new state machine has the following objectives:
+
+ - Remove duplication of state code between client and server
+ - Remove duplication of state code between TLS and DTLS
+ - Simplify transitions and bring the logic together in a single location
+ so that it is easier to validate
+ - Remove duplication of code between each of the message handling functions
+ - Receive a message first and then work out whether that is a valid
+ transition - not the other way around (the other way causes lots of issues
+ where we are expecting one type of message next but actually get something
+ else)
+ - Separate message flow state from handshake state (in order to better
+ understand each)
+ * message flow state = when to flush buffers; handling restarts in the
+ event of NBIO events; handling the common flow of steps for reading a
+ message and the common flow of steps for writing a message etc
+ * handshake state = what handshake message are we working on now
+ - Control complexity: only the state machine can change state: keep all
+ the state changes local to the state machine component
+
+The message flow state machine is divided into a reading sub-state machine and a
+writing sub-state machine. See the source comments in statem.c for a more
+detailed description of the various states and transitions possible.
+
+Conceptually the state machine component is designed as follows:
+
+ libssl
+ |
+ -------------------------|-----statem.h------------------------------------
+ |
+ _______V____________________
+ | |
+ | statem.c |
+ | |
+ | Core state machine code |
+ |____________________________|
+ statem_local.h ^ ^
+ _________| |_______
+ | |
+ _____________|____________ _____________|____________
+ | | | |
+ | statem_clnt.c | | statem_srvr.c |
+ | | | |
+ | TLS/DTLS client specific | | TLS/DTLS server specific |
+ | state machine code | | state machine code |
+ |__________________________| |__________________________|
+ | |_______________|__ |
+ | ________________| | |
+ | | | |
+ ____________V_______V________ ________V______V_______________
+ | | | |
+ | statem_lib.c | | statem_dtls.c |
+ | | | |
+ | Non core functions common | | Non core functions common to |
+ | to both servers and clients | | both DTLS servers and clients |
+ |_____________________________| |_______________________________|
diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c
index 0f39275baa01..8c9c16ec2120 100644
--- a/ssl/statem/extensions.c
+++ b/ssl/statem/extensions.c
@@ -1,12 +1,17 @@
/*
- * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#if defined(__TANDEM) && defined(_SPT_MODEL_)
+# include <spthread.h>
+# include <spt_extensions.h> /* timeval */
+#endif
+
#include <string.h>
#include "internal/nelem.h"
#include "internal/cryptlib.h"
@@ -17,10 +22,7 @@
static int final_renegotiate(SSL *s, unsigned int context, int sent);
static int init_server_name(SSL *s, unsigned int context);
static int final_server_name(SSL *s, unsigned int context, int sent);
-#ifndef OPENSSL_NO_EC
-static int init_ec_point_formats(SSL *s, unsigned int context);
static int final_ec_pt_formats(SSL *s, unsigned int context, int sent);
-#endif
static int init_session_ticket(SSL *s, unsigned int context);
#ifndef OPENSSL_NO_OCSP
static int init_status_request(SSL *s, unsigned int context);
@@ -43,13 +45,12 @@ static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt,
#ifndef OPENSSL_NO_SRP
static int init_srp(SSL *s, unsigned int context);
#endif
+static int init_ec_point_formats(SSL *s, unsigned int context);
static int init_etm(SSL *s, unsigned int context);
static int init_ems(SSL *s, unsigned int context);
static int final_ems(SSL *s, unsigned int context, int sent);
static int init_psk_kex_modes(SSL *s, unsigned int context);
-#ifndef OPENSSL_NO_EC
static int final_key_share(SSL *s, unsigned int context, int sent);
-#endif
#ifndef OPENSSL_NO_SRTP
static int init_srtp(SSL *s, unsigned int context);
#endif
@@ -97,6 +98,9 @@ typedef struct extensions_definition_st {
* Definitions of all built-in extensions. NOTE: Changes in the number or order
* of these extensions should be mirrored with equivalent changes to the
* indexes ( TLSEXT_IDX_* ) defined in ssl_local.h.
+ * Extensions should be added to test/ext_internal_test.c as well, as that
+ * tests the ordering of the extensions.
+ *
* Each extension has an initialiser, a client and
* server side parser and a finaliser. The initialiser is called (if the
* extension is relevant to the given context) even if we did not see the
@@ -114,12 +118,10 @@ typedef struct extensions_definition_st {
* messages the extension is relevant to. These flags also specify whether the
* extension is relevant to a particular protocol or protocol version.
*
- * TODO(TLS1.3): Make sure we have a test to check the consistency of these
- *
* NOTE: WebSphere Application Server 7+ cannot handle empty extensions at
* the end, keep these extensions before signature_algorithm.
*/
-#define INVALID_EXTENSION { 0x10000, 0, NULL, NULL, NULL, NULL, NULL, NULL }
+#define INVALID_EXTENSION { TLSEXT_TYPE_invalid, 0, NULL, NULL, NULL, NULL, NULL, NULL }
static const EXTENSION_DEFINITION ext_defs[] = {
{
TLSEXT_TYPE_renegotiate,
@@ -155,7 +157,6 @@ static const EXTENSION_DEFINITION ext_defs[] = {
#else
INVALID_EXTENSION,
#endif
-#ifndef OPENSSL_NO_EC
{
TLSEXT_TYPE_ec_point_formats,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
@@ -197,10 +198,6 @@ static const EXTENSION_DEFINITION ext_defs[] = {
tls_construct_stoc_supported_groups,
tls_construct_ctos_supported_groups, NULL
},
-#else
- INVALID_EXTENSION,
- INVALID_EXTENSION,
-#endif
{
TLSEXT_TYPE_session_ticket,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
@@ -324,7 +321,6 @@ static const EXTENSION_DEFINITION ext_defs[] = {
init_psk_kex_modes, tls_parse_ctos_psk_kex_modes, NULL, NULL,
tls_construct_ctos_psk_kex_modes, NULL
},
-#ifndef OPENSSL_NO_EC
{
/*
* Must be in this list after supported_groups. We need that to have
@@ -338,9 +334,6 @@ static const EXTENSION_DEFINITION ext_defs[] = {
tls_construct_stoc_key_share, tls_construct_ctos_key_share,
final_key_share
},
-#else
- INVALID_EXTENSION,
-#endif
{
/* Must be after key_share */
TLSEXT_TYPE_cookie,
@@ -395,6 +388,17 @@ static const EXTENSION_DEFINITION ext_defs[] = {
}
};
+/* Returns a TLSEXT_TYPE for the given index */
+unsigned int ossl_get_extension_type(size_t idx)
+{
+ size_t num_exts = OSSL_NELEM(ext_defs);
+
+ if (idx >= num_exts)
+ return TLSEXT_TYPE_out_of_range;
+
+ return ext_defs[idx].type;
+}
+
/* Check whether an extension's context matches the current context */
static int validate_context(SSL *s, unsigned int extctx, unsigned int thisctx)
{
@@ -576,8 +580,7 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
num_exts = OSSL_NELEM(ext_defs) + (exts != NULL ? exts->meths_count : 0);
raw_extensions = OPENSSL_zalloc(num_exts * sizeof(*raw_extensions));
if (raw_extensions == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -589,8 +592,7 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
if (!PACKET_get_net_2(&extensions, &type) ||
!PACKET_get_length_prefixed_2(&extensions, &extension)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
goto err;
}
/*
@@ -603,8 +605,7 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
|| (type == TLSEXT_TYPE_psk
&& (context & SSL_EXT_CLIENT_HELLO) != 0
&& PACKET_remaining(&extensions) != 0)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_COLLECT_EXTENSIONS,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_EXTENSION);
goto err;
}
idx = thisex - raw_extensions;
@@ -634,9 +635,9 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
&& !((context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0
&& type == TLSEXT_TYPE_cryptopro_bug)
#endif
- ) {
+ ) {
SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
- SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_UNSOLICITED_EXTENSION);
+ SSL_R_UNSOLICITED_EXTENSION);
goto err;
}
if (thisex != NULL) {
@@ -815,16 +816,14 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
(SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0
&& !WPACKET_set_flags(pkt,
WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
reason = ssl_get_min_max_version(s, &min_version, &max_version, NULL);
if (reason != 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
- reason);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, reason);
return 0;
}
}
@@ -867,8 +866,7 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
}
if (!WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -892,7 +890,7 @@ static int final_renegotiate(SSL *s, unsigned int context, int sent)
if (!(s->options & SSL_OP_LEGACY_SERVER_CONNECT)
&& !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
&& !sent) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE,
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
return 0;
}
@@ -904,7 +902,7 @@ static int final_renegotiate(SSL *s, unsigned int context, int sent)
if (s->renegotiate
&& !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
&& !sent) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE,
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
return 0;
}
@@ -913,6 +911,15 @@ static int final_renegotiate(SSL *s, unsigned int context, int sent)
return 1;
}
+static ossl_inline void ssl_tsan_decr(const SSL_CTX *ctx,
+ TSAN_QUALIFIER int *stat)
+{
+ if (ssl_tsan_lock(ctx)) {
+ tsan_decr(stat);
+ ssl_tsan_unlock(ctx);
+ }
+}
+
static int init_server_name(SSL *s, unsigned int context)
{
if (s->server) {
@@ -932,8 +939,7 @@ static int final_server_name(SSL *s, unsigned int context, int sent)
int was_ticket = (SSL_get_options(s) & SSL_OP_NO_TICKET) == 0;
if (!ossl_assert(s->ctx != NULL) || !ossl_assert(s->session_ctx != NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -958,8 +964,7 @@ static int final_server_name(SSL *s, unsigned int context, int sent)
OPENSSL_free(s->session->ext.hostname);
s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname);
if (s->session->ext.hostname == NULL && s->ext.hostname != NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
}
}
}
@@ -971,9 +976,9 @@ static int final_server_name(SSL *s, unsigned int context, int sent)
* exceed sess_accept (zero) for the new context.
*/
if (SSL_IS_FIRST_HANDSHAKE(s) && s->ctx != s->session_ctx
- && s->hello_retry_request == SSL_HRR_NONE) {
- tsan_counter(&s->ctx->stats.sess_accept);
- tsan_decr(&s->session_ctx->stats.sess_accept);
+ && s->hello_retry_request == SSL_HRR_NONE) {
+ ssl_tsan_counter(s->ctx, &s->ctx->stats.sess_accept);
+ ssl_tsan_decr(s->session_ctx, &s->session_ctx->stats.sess_accept);
}
/*
@@ -994,13 +999,11 @@ static int final_server_name(SSL *s, unsigned int context, int sent)
ss->ext.tick_lifetime_hint = 0;
ss->ext.tick_age_add = 0;
if (!ssl_generate_session_id(s, ss)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
} else {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
@@ -1008,7 +1011,7 @@ static int final_server_name(SSL *s, unsigned int context, int sent)
switch (ret) {
case SSL_TLSEXT_ERR_ALERT_FATAL:
- SSLfatal(s, altmp, SSL_F_FINAL_SERVER_NAME, SSL_R_CALLBACK_FAILED);
+ SSLfatal(s, altmp, SSL_R_CALLBACK_FAILED);
return 0;
case SSL_TLSEXT_ERR_ALERT_WARNING:
@@ -1027,16 +1030,6 @@ static int final_server_name(SSL *s, unsigned int context, int sent)
}
}
-#ifndef OPENSSL_NO_EC
-static int init_ec_point_formats(SSL *s, unsigned int context)
-{
- OPENSSL_free(s->ext.peer_ecpointformats);
- s->ext.peer_ecpointformats = NULL;
- s->ext.peer_ecpointformats_len = 0;
-
- return 1;
-}
-
static int final_ec_pt_formats(SSL *s, unsigned int context, int sent)
{
unsigned long alg_k, alg_a;
@@ -1044,8 +1037,8 @@ static int final_ec_pt_formats(SSL *s, unsigned int context, int sent)
if (s->server)
return 1;
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
- alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+ alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
+ alg_a = s->s3.tmp.new_cipher->algorithm_auth;
/*
* If we are client and using an elliptic curve cryptography cipher
@@ -1066,7 +1059,7 @@ static int final_ec_pt_formats(SSL *s, unsigned int context, int sent)
break;
}
if (i == s->ext.peer_ecpointformats_len) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EC_PT_FORMATS,
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
return 0;
}
@@ -1074,7 +1067,6 @@ static int final_ec_pt_formats(SSL *s, unsigned int context, int sent)
return 1;
}
-#endif
static int init_session_ticket(SSL *s, unsigned int context)
{
@@ -1106,7 +1098,7 @@ static int init_status_request(SSL *s, unsigned int context)
#ifndef OPENSSL_NO_NEXTPROTONEG
static int init_npn(SSL *s, unsigned int context)
{
- s->s3->npn_seen = 0;
+ s->s3.npn_seen = 0;
return 1;
}
@@ -1114,13 +1106,13 @@ static int init_npn(SSL *s, unsigned int context)
static int init_alpn(SSL *s, unsigned int context)
{
- OPENSSL_free(s->s3->alpn_selected);
- s->s3->alpn_selected = NULL;
- s->s3->alpn_selected_len = 0;
+ OPENSSL_free(s->s3.alpn_selected);
+ s->s3.alpn_selected = NULL;
+ s->s3.alpn_selected_len = 0;
if (s->server) {
- OPENSSL_free(s->s3->alpn_proposed);
- s->s3->alpn_proposed = NULL;
- s->s3->alpn_proposed_len = 0;
+ OPENSSL_free(s->s3.alpn_proposed);
+ s->s3.alpn_proposed = NULL;
+ s->s3.alpn_proposed_len = 0;
}
return 1;
}
@@ -1148,19 +1140,19 @@ static int final_alpn(SSL *s, unsigned int context, int sent)
static int init_sig_algs(SSL *s, unsigned int context)
{
/* Clear any signature algorithms extension received */
- OPENSSL_free(s->s3->tmp.peer_sigalgs);
- s->s3->tmp.peer_sigalgs = NULL;
- s->s3->tmp.peer_sigalgslen = 0;
+ OPENSSL_free(s->s3.tmp.peer_sigalgs);
+ s->s3.tmp.peer_sigalgs = NULL;
+ s->s3.tmp.peer_sigalgslen = 0;
return 1;
}
-static int init_sig_algs_cert(SSL *s, unsigned int context)
+static int init_sig_algs_cert(SSL *s, ossl_unused unsigned int context)
{
/* Clear any signature algorithms extension received */
- OPENSSL_free(s->s3->tmp.peer_cert_sigalgs);
- s->s3->tmp.peer_cert_sigalgs = NULL;
- s->s3->tmp.peer_cert_sigalgslen = 0;
+ OPENSSL_free(s->s3.tmp.peer_cert_sigalgs);
+ s->s3.tmp.peer_cert_sigalgs = NULL;
+ s->s3.tmp.peer_cert_sigalgslen = 0;
return 1;
}
@@ -1175,6 +1167,15 @@ static int init_srp(SSL *s, unsigned int context)
}
#endif
+static int init_ec_point_formats(SSL *s, unsigned int context)
+{
+ OPENSSL_free(s->ext.peer_ecpointformats);
+ s->ext.peer_ecpointformats = NULL;
+ s->ext.peer_ecpointformats_len = 0;
+
+ return 1;
+}
+
static int init_etm(SSL *s, unsigned int context)
{
s->ext.use_etm = 0;
@@ -1184,9 +1185,9 @@ static int init_etm(SSL *s, unsigned int context)
static int init_ems(SSL *s, unsigned int context)
{
- if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) {
- s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
- s->s3->flags |= TLS1_FLAGS_REQUIRED_EXTMS;
+ if (s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS) {
+ s->s3.flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
+ s->s3.flags |= TLS1_FLAGS_REQUIRED_EXTMS;
}
return 1;
@@ -1198,10 +1199,9 @@ static int final_ems(SSL *s, unsigned int context, int sent)
* Check extended master secret extension is not dropped on
* renegotiation.
*/
- if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS)
- && (s->s3->flags & TLS1_FLAGS_REQUIRED_EXTMS)) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_EMS,
- SSL_R_INCONSISTENT_EXTMS);
+ if (!(s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS)
+ && (s->s3.flags & TLS1_FLAGS_REQUIRED_EXTMS)) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_INCONSISTENT_EXTMS);
return 0;
}
if (!s->server && s->hit) {
@@ -1209,10 +1209,9 @@ static int final_ems(SSL *s, unsigned int context, int sent)
* Check extended master secret extension is consistent with
* original session.
*/
- if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) !=
+ if (!(s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS) !=
!(s->session->flags & SSL_SESS_FLAG_EXTMS)) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_EMS,
- SSL_R_INCONSISTENT_EXTMS);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_INCONSISTENT_EXTMS);
return 0;
}
}
@@ -1222,8 +1221,8 @@ static int final_ems(SSL *s, unsigned int context, int sent)
static int init_certificate_authorities(SSL *s, unsigned int context)
{
- sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free);
- s->s3->tmp.peer_ca_names = NULL;
+ sk_X509_NAME_pop_free(s->s3.tmp.peer_ca_names, X509_NAME_free);
+ s->s3.tmp.peer_ca_names = NULL;
return 1;
}
@@ -1239,9 +1238,7 @@ static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_certificate_authorities)
|| !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1251,9 +1248,7 @@ static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
}
if (!WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1267,8 +1262,7 @@ static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt,
if (!parse_ca_names(s, pkt))
return 0;
if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
return 1;
@@ -1287,7 +1281,7 @@ static int init_srtp(SSL *s, unsigned int context)
static int final_sig_algs(SSL *s, unsigned int context, int sent)
{
if (!sent && SSL_IS_TLS13(s) && !s->hit) {
- SSLfatal(s, TLS13_AD_MISSING_EXTENSION, SSL_F_FINAL_SIG_ALGS,
+ SSLfatal(s, TLS13_AD_MISSING_EXTENSION,
SSL_R_MISSING_SIGALGS_EXTENSION);
return 0;
}
@@ -1295,9 +1289,9 @@ static int final_sig_algs(SSL *s, unsigned int context, int sent)
return 1;
}
-#ifndef OPENSSL_NO_EC
static int final_key_share(SSL *s, unsigned int context, int sent)
{
+#if !defined(OPENSSL_NO_TLS1_3)
if (!SSL_IS_TLS13(s))
return 1;
@@ -1321,8 +1315,7 @@ static int final_key_share(SSL *s, unsigned int context, int sent)
&& (!s->hit
|| (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0)) {
/* Nothing left we can do - just fail */
- SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_KEY_SHARE,
- SSL_R_NO_SUITABLE_KEY_SHARE);
+ SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_R_NO_SUITABLE_KEY_SHARE);
return 0;
}
/*
@@ -1360,9 +1353,9 @@ static int final_key_share(SSL *s, unsigned int context, int sent)
* send a HelloRetryRequest
*/
if (s->server) {
- if (s->s3->peer_tmp != NULL) {
+ if (s->s3.peer_tmp != NULL) {
/* We have a suitable key_share */
- if ((s->s3->flags & TLS1_FLAGS_STATELESS) != 0
+ if ((s->s3.flags & TLS1_FLAGS_STATELESS) != 0
&& !s->ext.cookieok) {
if (!ossl_assert(s->hello_retry_request == SSL_HRR_NONE)) {
/*
@@ -1370,8 +1363,7 @@ static int final_key_share(SSL *s, unsigned int context, int sent)
* previously sent HRR - so how can this be anything other
* than 0?
*/
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
s->hello_retry_request = SSL_HRR_PENDING;
@@ -1406,7 +1398,7 @@ static int final_key_share(SSL *s, unsigned int context, int sent)
if (i < num_groups) {
/* A shared group exists so send a HelloRetryRequest */
- s->s3->group_id = group_id;
+ s->s3.group_id = group_id;
s->hello_retry_request = SSL_HRR_PENDING;
return 1;
}
@@ -1416,11 +1408,11 @@ static int final_key_share(SSL *s, unsigned int context, int sent)
/* Nothing left we can do - just fail */
SSLfatal(s, sent ? SSL_AD_HANDSHAKE_FAILURE
: SSL_AD_MISSING_EXTENSION,
- SSL_F_FINAL_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE);
+ SSL_R_NO_SUITABLE_KEY_SHARE);
return 0;
}
- if ((s->s3->flags & TLS1_FLAGS_STATELESS) != 0
+ if ((s->s3.flags & TLS1_FLAGS_STATELESS) != 0
&& !s->ext.cookieok) {
if (!ossl_assert(s->hello_retry_request == SSL_HRR_NONE)) {
/*
@@ -1428,8 +1420,7 @@ static int final_key_share(SSL *s, unsigned int context, int sent)
* previously sent HRR - so how can this be anything other
* than 0?
*/
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
s->hello_retry_request = SSL_HRR_PENDING;
@@ -1450,15 +1441,13 @@ static int final_key_share(SSL *s, unsigned int context, int sent)
* processing).
*/
if (!sent && !tls13_generate_handshake_secret(s, NULL, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
-
+#endif /* !defined(OPENSSL_NO_TLS1_3) */
return 1;
}
-#endif
static int init_psk_kex_modes(SSL *s, unsigned int context)
{
@@ -1485,14 +1474,13 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
#endif
const unsigned char *label;
size_t bindersize, labelsize, hashsize;
- int hashsizei = EVP_MD_size(md);
+ int hashsizei = EVP_MD_get_size(md);
int ret = -1;
int usepskfored = 0;
/* Ensure cast to size_t is safe */
if (!ossl_assert(hashsizei >= 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
hashsize = (size_t)hashsizei;
@@ -1538,8 +1526,7 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
if (mctx == NULL
|| EVP_DigestInit_ex(mctx, md, NULL) <= 0
|| EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -1557,8 +1544,7 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
}
if (EVP_DigestInit_ex(mctx, md, NULL) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -1573,10 +1559,9 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
void *hdata;
hdatalen = hdatalen_l =
- BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+ BIO_get_mem_data(s->s3.handshake_buffer, &hdata);
if (hdatalen_l <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- SSL_R_BAD_HANDSHAKE_LENGTH);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_HANDSHAKE_LENGTH);
goto err;
}
@@ -1593,32 +1578,29 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
|| !PACKET_get_length_prefixed_3(&hashprefix, &msg)
|| !PACKET_forward(&hashprefix, 1)
|| !PACKET_get_length_prefixed_3(&hashprefix, &msg)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
hdatalen -= PACKET_remaining(&hashprefix);
}
if (EVP_DigestUpdate(mctx, hdata, hdatalen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (EVP_DigestUpdate(mctx, msgstart, binderoffset) <= 0
|| EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- mackey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finishedkey,
- hashsize);
+ mackey = EVP_PKEY_new_raw_private_key_ex(s->ctx->libctx, "HMAC",
+ s->ctx->propq, finishedkey,
+ hashsize);
if (mackey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -1626,12 +1608,12 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
binderout = tmpbinder;
bindersize = hashsize;
- if (EVP_DigestSignInit(mctx, NULL, md, NULL, mackey) <= 0
+ if (EVP_DigestSignInit_ex(mctx, NULL, EVP_MD_get0_name(md), s->ctx->libctx,
+ s->ctx->propq, mackey, NULL) <= 0
|| EVP_DigestSignUpdate(mctx, hash, hashsize) <= 0
|| EVP_DigestSignFinal(mctx, binderout, &bindersize) <= 0
|| bindersize != hashsize) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -1641,8 +1623,7 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
/* HMAC keys can't do EVP_DigestVerify* - use CRYPTO_memcmp instead */
ret = (CRYPTO_memcmp(binderin, binderout, hashsize) == 0);
if (!ret)
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PSK_DO_BINDER,
- SSL_R_BINDER_DOES_NOT_VERIFY);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BINDER_DOES_NOT_VERIFY);
}
err:
@@ -1668,8 +1649,7 @@ static int final_early_data(SSL *s, unsigned int context, int sent)
* later realised that it shouldn't have done (e.g. inconsistent
* ALPN)
*/
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EARLY_DATA,
- SSL_R_BAD_EARLY_DATA);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_EARLY_DATA);
return 0;
}
@@ -1706,8 +1686,7 @@ static int final_maxfragmentlen(SSL *s, unsigned int context, int sent)
*/
if (s->server && s->hit && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
&& !sent ) {
- SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_MAXFRAGMENTLEN,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -1723,7 +1702,7 @@ static int final_maxfragmentlen(SSL *s, unsigned int context, int sent)
return 1;
}
-static int init_post_handshake_auth(SSL *s, unsigned int context)
+static int init_post_handshake_auth(SSL *s, ossl_unused unsigned int context)
{
s->post_handshake_auth = SSL_PHA_NONE;
@@ -1738,7 +1717,7 @@ static int final_psk(SSL *s, unsigned int context, int sent)
{
if (s->server && sent && s->clienthello != NULL
&& !s->clienthello->pre_proc_exts[TLSEXT_IDX_psk_kex_modes].present) {
- SSLfatal(s, TLS13_AD_MISSING_EXTENSION, SSL_F_FINAL_PSK,
+ SSLfatal(s, TLS13_AD_MISSING_EXTENSION,
SSL_R_MISSING_PSK_KEX_MODES_EXTENSION);
return 0;
}
diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c
index 1cbaefa9f123..842be0722bd0 100644
--- a/ssl/statem/extensions_clnt.c
+++ b/ssl/statem/extensions_clnt.c
@@ -1,7 +1,7 @@
/*
* Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -22,11 +22,10 @@ EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt,
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
|| !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_sub_memcpy_u8(pkt, s->s3->previous_client_finished,
- s->s3->previous_client_finished_len)
+ || !WPACKET_sub_memcpy_u8(pkt, s->s3.previous_client_finished,
+ s->s3.previous_client_finished_len)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -51,8 +50,7 @@ EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt,
strlen(s->ext.hostname))
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -77,8 +75,7 @@ EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt,
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u8(pkt, s->ext.max_fragment_len_mode)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -103,8 +100,7 @@ EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context,
strlen(s->srp_ctx.login))
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SRP,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -112,8 +108,7 @@ EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context,
}
#endif
-#ifndef OPENSSL_NO_EC
-static int use_ecc(SSL *s)
+static int use_ecc(SSL *s, int min_version, int max_version)
{
int i, end, ret = 0;
unsigned long alg_k, alg_a;
@@ -139,7 +134,6 @@ static int use_ecc(SSL *s)
break;
}
}
-
sk_SSL_CIPHER_free(cipher_stack);
if (!ret)
return 0;
@@ -149,7 +143,8 @@ static int use_ecc(SSL *s)
for (j = 0; j < num_groups; j++) {
uint16_t ctmp = pgroups[j];
- if (tls_curve_allowed(s, ctmp, SSL_SECOP_CURVE_SUPPORTED))
+ if (tls_valid_group(s, ctmp, min_version, max_version, 1, NULL)
+ && tls_group_allowed(s, ctmp, SSL_SECOP_CURVE_SUPPORTED))
return 1;
}
@@ -162,8 +157,14 @@ EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt,
{
const unsigned char *pformats;
size_t num_formats;
+ int reason, min_version, max_version;
- if (!use_ecc(s))
+ reason = ssl_get_min_max_version(s, &min_version, &max_version, NULL);
+ if (reason != 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, reason);
+ return EXT_RETURN_FAIL;
+ }
+ if (!use_ecc(s, min_version, max_version))
return EXT_RETURN_NOT_SENT;
/* Add TLS extension ECPointFormats to the ClientHello message */
@@ -174,8 +175,7 @@ EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt,
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_sub_memcpy_u8(pkt, pformats, num_formats)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -187,49 +187,69 @@ EXT_RETURN tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt,
size_t chainidx)
{
const uint16_t *pgroups = NULL;
- size_t num_groups = 0, i;
+ size_t num_groups = 0, i, tls13added = 0, added = 0;
+ int min_version, max_version, reason;
- if (!use_ecc(s))
+ reason = ssl_get_min_max_version(s, &min_version, &max_version, NULL);
+ if (reason != 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, reason);
+ return EXT_RETURN_FAIL;
+ }
+
+ /*
+ * We only support EC groups in TLSv1.2 or below, and in DTLS. Therefore
+ * if we don't have EC support then we don't send this extension.
+ */
+ if (!use_ecc(s, min_version, max_version)
+ && (SSL_IS_DTLS(s) || max_version < TLS1_3_VERSION))
return EXT_RETURN_NOT_SENT;
/*
* Add TLS extension supported_groups to the ClientHello message
*/
- /* TODO(TLS1.3): Add support for DHE groups */
tls1_get_supported_groups(s, &pgroups, &num_groups);
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups)
/* Sub-packet for supported_groups extension */
|| !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
- ERR_R_INTERNAL_ERROR);
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
- /* Copy curve ID if supported */
+ /* Copy group ID if supported */
for (i = 0; i < num_groups; i++) {
uint16_t ctmp = pgroups[i];
+ int okfortls13;
- if (tls_curve_allowed(s, ctmp, SSL_SECOP_CURVE_SUPPORTED)) {
+ if (tls_valid_group(s, ctmp, min_version, max_version, 0, &okfortls13)
+ && tls_group_allowed(s, ctmp, SSL_SECOP_CURVE_SUPPORTED)) {
if (!WPACKET_put_bytes_u16(pkt, ctmp)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ if (okfortls13 && max_version == TLS1_3_VERSION)
+ tls13added++;
+ added++;
}
}
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
- ERR_R_INTERNAL_ERROR);
+ if (added == 0)
+ SSLfatal_data(s, SSL_AD_INTERNAL_ERROR, SSL_R_NO_SUITABLE_GROUPS,
+ "No groups enabled for max supported SSL/TLS version");
+ else
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ if (tls13added == 0 && max_version == TLS1_3_VERSION) {
+ SSLfatal_data(s, SSL_AD_INTERNAL_ERROR, SSL_R_NO_SUITABLE_GROUPS,
+ "No groups enabled for max supported SSL/TLS version");
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
-#endif
EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
@@ -249,9 +269,7 @@ EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt,
ticklen = s->ext.session_ticket->length;
s->session->ext.tick = OPENSSL_malloc(ticklen);
if (s->session->ext.tick == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
memcpy(s->session->ext.tick,
@@ -267,8 +285,7 @@ EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt,
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
|| !WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick, ticklen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -294,8 +311,7 @@ EXT_RETURN tls_construct_ctos_sig_algs(SSL *s, WPACKET *pkt,
|| !tls12_copy_sigalgs(s, pkt, salg, salglen)
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -322,8 +338,7 @@ EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt,
|| !WPACKET_put_bytes_u8(pkt, TLSEXT_STATUSTYPE_ocsp)
/* Sub-packet for the ids */
|| !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
for (i = 0; i < sk_OCSP_RESPID_num(s->ext.ocsp.ids); i++) {
@@ -335,16 +350,13 @@ EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt,
/* Sub-packet for an individual id */
|| !WPACKET_sub_allocate_bytes_u16(pkt, idlen, &idbytes)
|| i2d_OCSP_RESPID(id, &idbytes) != idlen) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
}
if (!WPACKET_close(pkt)
|| !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
if (s->ext.ocsp.exts) {
@@ -352,23 +364,18 @@ EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt,
int extlen = i2d_X509_EXTENSIONS(s->ext.ocsp.exts, NULL);
if (extlen < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
if (!WPACKET_allocate_bytes(pkt, extlen, &extbytes)
|| i2d_X509_EXTENSIONS(s->ext.ocsp.exts, &extbytes)
!= extlen) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
}
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -389,8 +396,7 @@ EXT_RETURN tls_construct_ctos_npn(SSL *s, WPACKET *pkt, unsigned int context,
*/
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_NPN,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -401,7 +407,7 @@ EXT_RETURN tls_construct_ctos_npn(SSL *s, WPACKET *pkt, unsigned int context,
EXT_RETURN tls_construct_ctos_alpn(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
- s->s3->alpn_sent = 0;
+ s->s3.alpn_sent = 0;
if (s->ext.alpn == NULL || !SSL_IS_FIRST_HANDSHAKE(s))
return EXT_RETURN_NOT_SENT;
@@ -412,11 +418,10 @@ EXT_RETURN tls_construct_ctos_alpn(SSL *s, WPACKET *pkt, unsigned int context,
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_sub_memcpy_u16(pkt, s->ext.alpn, s->ext.alpn_len)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_ALPN,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
- s->s3->alpn_sent = 1;
+ s->s3.alpn_sent = 1;
return EXT_RETURN_SENT;
}
@@ -438,8 +443,7 @@ EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt,
|| !WPACKET_start_sub_packet_u16(pkt)
/* Sub-packet for the protection profile list */
|| !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -449,8 +453,7 @@ EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt,
sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
if (prof == NULL || !WPACKET_put_bytes_u16(pkt, prof->id)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
}
@@ -458,8 +461,7 @@ EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt,
/* Add an empty use_mki value */
|| !WPACKET_put_bytes_u8(pkt, 0)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -475,8 +477,7 @@ EXT_RETURN tls_construct_ctos_etm(SSL *s, WPACKET *pkt, unsigned int context,
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_ETM,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -496,8 +497,7 @@ EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context,
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signed_certificate_timestamp)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SCT,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -508,10 +508,12 @@ EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context,
EXT_RETURN tls_construct_ctos_ems(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
+ if (s->options & SSL_OP_NO_EXTENDED_MASTER_SECRET)
+ return EXT_RETURN_NOT_SENT;
+
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EMS,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -526,8 +528,7 @@ EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt,
reason = ssl_get_min_max_version(s, &min_version, &max_version, NULL);
if (reason != 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, reason);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, reason);
return EXT_RETURN_FAIL;
}
@@ -541,24 +542,18 @@ EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt,
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u8(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
for (currv = max_version; currv >= min_version; currv--) {
if (!WPACKET_put_bytes_u16(pkt, currv)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
}
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -582,8 +577,7 @@ EXT_RETURN tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt,
|| (nodhe && !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE))
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -602,16 +596,15 @@ static int add_key_share(SSL *s, WPACKET *pkt, unsigned int curve_id)
EVP_PKEY *key_share_key = NULL;
size_t encodedlen;
- if (s->s3->tmp.pkey != NULL) {
+ if (s->s3.tmp.pkey != NULL) {
if (!ossl_assert(s->hello_retry_request == SSL_HRR_PENDING)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
/*
* Could happen if we got an HRR that wasn't requesting a new key_share
*/
- key_share_key = s->s3->tmp.pkey;
+ key_share_key = s->s3.tmp.pkey;
} else {
key_share_key = ssl_generate_pkey_group(s, curve_id);
if (key_share_key == NULL) {
@@ -621,33 +614,32 @@ static int add_key_share(SSL *s, WPACKET *pkt, unsigned int curve_id)
}
/* Encode the public key. */
- encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key,
- &encoded_point);
+ encodedlen = EVP_PKEY_get1_encoded_public_key(key_share_key,
+ &encoded_point);
if (encodedlen == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE, ERR_R_EC_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EC_LIB);
goto err;
}
/* Create KeyShareEntry */
if (!WPACKET_put_bytes_u16(pkt, curve_id)
|| !WPACKET_sub_memcpy_u16(pkt, encoded_point, encodedlen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
/*
- * TODO(TLS1.3): When changing to send more than one key_share we're
+ * When changing to send more than one key_share we're
* going to need to be able to save more than one EVP_PKEY. For now
* we reuse the existing tmp.pkey
*/
- s->s3->tmp.pkey = key_share_key;
- s->s3->group_id = curve_id;
+ s->s3.tmp.pkey = key_share_key;
+ s->s3.group_id = curve_id;
OPENSSL_free(encoded_point);
return 1;
err:
- if (s->s3->tmp.pkey == NULL)
+ if (s->s3.tmp.pkey == NULL)
EVP_PKEY_free(key_share_key);
OPENSSL_free(encoded_point);
return 0;
@@ -669,23 +661,26 @@ EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt,
|| !WPACKET_start_sub_packet_u16(pkt)
/* KeyShare list sub-packet */
|| !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
tls1_get_supported_groups(s, &pgroups, &num_groups);
/*
- * TODO(TLS1.3): Make the number of key_shares sent configurable. For
- * now, just send one
+ * Make the number of key_shares sent configurable. For
+ * now, we just send one
*/
- if (s->s3->group_id != 0) {
- curve_id = s->s3->group_id;
+ if (s->s3.group_id != 0) {
+ curve_id = s->s3.group_id;
} else {
for (i = 0; i < num_groups; i++) {
- if (!tls_curve_allowed(s, pgroups[i], SSL_SECOP_CURVE_SUPPORTED))
+ if (!tls_group_allowed(s, pgroups[i], SSL_SECOP_CURVE_SUPPORTED))
+ continue;
+
+ if (!tls_valid_group(s, pgroups[i], TLS1_3_VERSION, TLS1_3_VERSION,
+ 0, NULL))
continue;
curve_id = pgroups[i];
@@ -694,8 +689,7 @@ EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt,
}
if (curve_id == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
- SSL_R_NO_SUITABLE_KEY_SHARE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_NO_SUITABLE_KEY_SHARE);
return EXT_RETURN_FAIL;
}
@@ -705,8 +699,7 @@ EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt,
}
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
@@ -730,8 +723,7 @@ EXT_RETURN tls_construct_ctos_cookie(SSL *s, WPACKET *pkt, unsigned int context,
|| !WPACKET_sub_memcpy_u16(pkt, s->ext.tls13_cookie,
s->ext.tls13_cookie_len)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_COOKIE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto end;
}
@@ -765,8 +757,7 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
|| (psksess != NULL
&& psksess->ssl_version != TLS1_3_VERSION))) {
SSL_SESSION_free(psksess);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
- SSL_R_BAD_PSK);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_PSK);
return EXT_RETURN_FAIL;
}
@@ -780,8 +771,7 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
psk, sizeof(psk));
if (psklen > PSK_MAX_PSK_LEN) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
} else if (psklen > 0) {
const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 };
@@ -789,9 +779,7 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
idlen = strlen(identity);
if (idlen > PSK_MAX_IDENTITY_LEN) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
id = (unsigned char *)identity;
@@ -802,9 +790,7 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
*/
cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id);
if (cipher == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -813,9 +799,7 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
|| !SSL_SESSION_set1_master_key(psksess, psk, psklen)
|| !SSL_SESSION_set_cipher(psksess, cipher)
|| !SSL_SESSION_set_protocol_version(psksess, TLS1_3_VERSION)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
OPENSSL_cleanse(psk, psklen);
return EXT_RETURN_FAIL;
}
@@ -831,8 +815,7 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
s->psksession_id = OPENSSL_memdup(id, idlen);
if (s->psksession_id == NULL) {
s->psksession_id_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
s->psksession_id_len = idlen;
@@ -852,15 +835,13 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
|| (s->ext.hostname != NULL
&& strcmp(s->ext.hostname, edsess->ext.hostname) != 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
SSL_R_INCONSISTENT_EARLY_DATA_SNI);
return EXT_RETURN_FAIL;
}
}
if ((s->ext.alpn == NULL && edsess->ext.alpn_selected != NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
- SSL_R_INCONSISTENT_EARLY_DATA_ALPN);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_INCONSISTENT_EARLY_DATA_ALPN);
return EXT_RETURN_FAIL;
}
@@ -873,8 +854,7 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
int found = 0;
if (!PACKET_buf_init(&prots, s->ext.alpn, s->ext.alpn_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
while (PACKET_get_length_prefixed_1(&prots, &alpnpkt)) {
@@ -886,7 +866,6 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
}
if (!found) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
SSL_R_INCONSISTENT_EARLY_DATA_ALPN);
return EXT_RETURN_FAIL;
}
@@ -895,8 +874,7 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -944,8 +922,7 @@ EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt,
* this extension MUST always appear second to last.
*/
if (!WPACKET_get_total_written(pkt, &hlen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PADDING,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -956,7 +933,7 @@ EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt,
if (s->session->ssl_version == TLS1_3_VERSION
&& s->session->ext.ticklen != 0
&& s->session->cipher != NULL) {
- const EVP_MD *md = ssl_md(s->session->cipher->algorithm2);
+ const EVP_MD *md = ssl_md(s->ctx, s->session->cipher->algorithm2);
if (md != NULL) {
/*
@@ -964,7 +941,7 @@ EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt,
* length.
*/
hlen += PSK_PRE_BINDER_OVERHEAD + s->session->ext.ticklen
- + EVP_MD_size(md);
+ + EVP_MD_get_size(md);
}
}
@@ -985,8 +962,7 @@ EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt,
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_padding)
|| !WPACKET_sub_allocate_bytes_u16(pkt, hlen, &padbytes)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PADDING,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
memset(padbytes, 0, hlen);
@@ -1030,11 +1006,10 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
if (s->session->ext.ticklen != 0) {
/* Get the digest associated with the ciphersuite in the session */
if (s->session->cipher == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
- mdres = ssl_md(s->session->cipher->algorithm2);
+ mdres = ssl_md(s->ctx, s->session->cipher->algorithm2);
if (mdres == NULL) {
/*
* Don't recognize this cipher so we can't use the session.
@@ -1096,7 +1071,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
*/
agems += s->session->ext.tick_age_add;
- reshashsize = EVP_MD_size(mdres);
+ reshashsize = EVP_MD_get_size(mdres);
s->ext.tick_identity++;
dores = 1;
}
@@ -1106,14 +1081,13 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
return EXT_RETURN_NOT_SENT;
if (s->psksession != NULL) {
- mdpsk = ssl_md(s->psksession->cipher->algorithm2);
+ mdpsk = ssl_md(s->ctx, s->psksession->cipher->algorithm2);
if (mdpsk == NULL) {
/*
* Don't recognize this cipher so we can't use the session.
* If this happens it's an application bug.
*/
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
- SSL_R_BAD_PSK);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_PSK);
return EXT_RETURN_FAIL;
}
@@ -1122,20 +1096,18 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
* Selected ciphersuite hash does not match the hash for the PSK
* session. This is an application bug.
*/
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
- SSL_R_BAD_PSK);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_PSK);
return EXT_RETURN_FAIL;
}
- pskhashsize = EVP_MD_size(mdpsk);
+ pskhashsize = EVP_MD_get_size(mdpsk);
}
/* Create the extension, but skip over the binder for now */
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1143,8 +1115,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
if (!WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick,
s->session->ext.ticklen)
|| !WPACKET_put_bytes_u32(pkt, agems)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
}
@@ -1153,8 +1124,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
if (!WPACKET_sub_memcpy_u16(pkt, s->psksession_id,
s->psksession_id_len)
|| !WPACKET_put_bytes_u32(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
s->ext.tick_identity++;
@@ -1175,8 +1145,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
* calculate the HMAC of the message up to the binders
*/
|| !WPACKET_fill_lengths(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1203,8 +1172,9 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
}
EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt,
- unsigned int context,
- X509 *x, size_t chainidx)
+ ossl_unused unsigned int context,
+ ossl_unused X509 *x,
+ ossl_unused size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
if (!s->pha_enabled)
@@ -1214,9 +1184,7 @@ EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt,
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_post_handshake_auth)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1235,58 +1203,52 @@ EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt,
int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
- size_t expected_len = s->s3->previous_client_finished_len
- + s->s3->previous_server_finished_len;
+ size_t expected_len = s->s3.previous_client_finished_len
+ + s->s3.previous_server_finished_len;
size_t ilen;
const unsigned char *data;
/* Check for logic errors */
if (!ossl_assert(expected_len == 0
- || s->s3->previous_client_finished_len != 0)
+ || s->s3.previous_client_finished_len != 0)
|| !ossl_assert(expected_len == 0
- || s->s3->previous_server_finished_len != 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
- ERR_R_INTERNAL_ERROR);
+ || s->s3.previous_server_finished_len != 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
/* Parse the length byte */
if (!PACKET_get_1_len(pkt, &ilen)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
- SSL_R_RENEGOTIATION_ENCODING_ERR);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_RENEGOTIATION_ENCODING_ERR);
return 0;
}
/* Consistency check */
if (PACKET_remaining(pkt) != ilen) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
- SSL_R_RENEGOTIATION_ENCODING_ERR);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_RENEGOTIATION_ENCODING_ERR);
return 0;
}
/* Check that the extension matches */
if (ilen != expected_len) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
- SSL_R_RENEGOTIATION_MISMATCH);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_RENEGOTIATION_MISMATCH);
return 0;
}
- if (!PACKET_get_bytes(pkt, &data, s->s3->previous_client_finished_len)
- || memcmp(data, s->s3->previous_client_finished,
- s->s3->previous_client_finished_len) != 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
- SSL_R_RENEGOTIATION_MISMATCH);
+ if (!PACKET_get_bytes(pkt, &data, s->s3.previous_client_finished_len)
+ || memcmp(data, s->s3.previous_client_finished,
+ s->s3.previous_client_finished_len) != 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_RENEGOTIATION_MISMATCH);
return 0;
}
- if (!PACKET_get_bytes(pkt, &data, s->s3->previous_server_finished_len)
- || memcmp(data, s->s3->previous_server_finished,
- s->s3->previous_server_finished_len) != 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
- SSL_R_RENEGOTIATION_MISMATCH);
+ if (!PACKET_get_bytes(pkt, &data, s->s3.previous_server_finished_len)
+ || memcmp(data, s->s3.previous_server_finished,
+ s->s3.previous_server_finished_len) != 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_RENEGOTIATION_MISMATCH);
return 0;
}
- s->s3->send_connection_binding = 1;
+ s->s3.send_connection_binding = 1;
return 1;
}
@@ -1298,15 +1260,13 @@ int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
unsigned int value;
if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
/* |value| should contains a valid max-fragment-length code. */
if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
@@ -1319,7 +1279,6 @@ int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
*/
if (value != s->ext.max_fragment_len_mode) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
@@ -1337,27 +1296,23 @@ int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (s->ext.hostname == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (PACKET_remaining(pkt) > 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->hit) {
if (s->session->ext.hostname != NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname);
if (s->session->ext.hostname == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
@@ -1365,7 +1320,6 @@ int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
return 1;
}
-#ifndef OPENSSL_NO_EC
int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
@@ -1373,15 +1327,13 @@ int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
PACKET ecptformatlist;
if (!PACKET_as_length_prefixed_1(pkt, &ecptformatlist)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->hit) {
ecpointformats_len = PACKET_remaining(&ecptformatlist);
if (ecpointformats_len == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, SSL_R_BAD_LENGTH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_LENGTH);
return 0;
}
@@ -1390,8 +1342,7 @@ int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
s->ext.peer_ecpointformats = OPENSSL_malloc(ecpointformats_len);
if (s->ext.peer_ecpointformats == NULL) {
s->ext.peer_ecpointformats_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -1400,15 +1351,13 @@ int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
if (!PACKET_copy_bytes(&ecptformatlist,
s->ext.peer_ecpointformats,
ecpointformats_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
return 1;
}
-#endif
int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
@@ -1417,19 +1366,16 @@ int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
!s->ext.session_ticket_cb(s, PACKET_data(pkt),
PACKET_remaining(pkt),
s->ext.session_ticket_cb_arg)) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_BAD_EXTENSION);
return 0;
}
if (!tls_use_ticket(s)) {
- SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
- SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_R_BAD_EXTENSION);
return 0;
}
if (PACKET_remaining(pkt) > 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -1444,7 +1390,6 @@ int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context,
{
if (context == SSL_EXT_TLS1_3_CERTIFICATE_REQUEST) {
/* We ignore this if the server sends a CertificateRequest */
- /* TODO(TLS1.3): Add support for this */
return 1;
}
@@ -1453,13 +1398,11 @@ int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context,
* request message. In TLS <= 1.2 it must also be empty.
*/
if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) {
- SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
- SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_R_BAD_EXTENSION);
return 0;
}
if (!SSL_IS_TLS13(s) && PACKET_remaining(pkt) > 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -1488,7 +1431,6 @@ int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
{
if (context == SSL_EXT_TLS1_3_CERTIFICATE_REQUEST) {
/* We ignore this if the server sends it in a CertificateRequest */
- /* TODO(TLS1.3): Add support for this */
return 1;
}
@@ -1509,13 +1451,11 @@ int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
s->ext.scts = OPENSSL_malloc(size);
if (s->ext.scts == NULL) {
s->ext.scts_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SCT,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!PACKET_copy_bytes(pkt, s->ext.scts, size)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SCT,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
@@ -1530,8 +1470,7 @@ int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
if (custom_ext_find(&s->cert->custext, role,
TLSEXT_TYPE_signed_certificate_timestamp,
NULL) == NULL) {
- SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_SCT,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -1562,8 +1501,7 @@ static int ssl_next_proto_validate(SSL *s, PACKET *pkt)
while (PACKET_remaining(pkt)) {
if (!PACKET_get_length_prefixed_1(pkt, &tmp_protocol)
|| PACKET_remaining(&tmp_protocol) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_NEXT_PROTO_VALIDATE,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
}
@@ -1584,8 +1522,7 @@ int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
/* We must have requested it. */
if (s->ctx->ext.npn_select_cb == NULL) {
- SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_NPN,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -1600,8 +1537,7 @@ int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
PACKET_remaining(pkt),
s->ctx->ext.npn_select_cb_arg) !=
SSL_TLSEXT_ERR_OK) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_STOC_NPN,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -1613,14 +1549,13 @@ int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
s->ext.npn = OPENSSL_malloc(selected_len);
if (s->ext.npn == NULL) {
s->ext.npn_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_NPN,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
memcpy(s->ext.npn, selected, selected_len);
s->ext.npn_len = selected_len;
- s->s3->npn_seen = 1;
+ s->s3.npn_seen = 1;
return 1;
}
@@ -1632,9 +1567,8 @@ int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t len;
/* We must have requested it. */
- if (!s->s3->alpn_sent) {
- SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_ALPN,
- SSL_R_BAD_EXTENSION);
+ if (!s->s3.alpn_sent) {
+ SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_R_BAD_EXTENSION);
return 0;
}
/*-
@@ -1646,28 +1580,25 @@ int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
if (!PACKET_get_net_2_len(pkt, &len)
|| PACKET_remaining(pkt) != len || !PACKET_get_1_len(pkt, &len)
|| PACKET_remaining(pkt) != len) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
- OPENSSL_free(s->s3->alpn_selected);
- s->s3->alpn_selected = OPENSSL_malloc(len);
- if (s->s3->alpn_selected == NULL) {
- s->s3->alpn_selected_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
- ERR_R_INTERNAL_ERROR);
+ OPENSSL_free(s->s3.alpn_selected);
+ s->s3.alpn_selected = OPENSSL_malloc(len);
+ if (s->s3.alpn_selected == NULL) {
+ s->s3.alpn_selected_len = 0;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
- if (!PACKET_copy_bytes(pkt, s->s3->alpn_selected, len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
- SSL_R_BAD_EXTENSION);
+ if (!PACKET_copy_bytes(pkt, s->s3.alpn_selected, len)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
- s->s3->alpn_selected_len = len;
+ s->s3.alpn_selected_len = len;
if (s->session->ext.alpn_selected == NULL
|| s->session->ext.alpn_selected_len != len
- || memcmp(s->session->ext.alpn_selected, s->s3->alpn_selected, len)
+ || memcmp(s->session->ext.alpn_selected, s->s3.alpn_selected, len)
!= 0) {
/* ALPN not consistent with the old session so cannot use early_data */
s->ext.early_data_ok = 0;
@@ -1678,19 +1609,17 @@ int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
* initialised to NULL. We should update it with the selected ALPN.
*/
if (!ossl_assert(s->session->ext.alpn_selected == NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
s->session->ext.alpn_selected =
- OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len);
+ OPENSSL_memdup(s->s3.alpn_selected, s->s3.alpn_selected_len);
if (s->session->ext.alpn_selected == NULL) {
s->session->ext.alpn_selected_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
- s->session->ext.alpn_selected_len = s->s3->alpn_selected_len;
+ s->session->ext.alpn_selected_len = s->s3.alpn_selected_len;
}
return 1;
@@ -1709,23 +1638,21 @@ int tls_parse_stoc_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|| !PACKET_get_net_2(pkt, &id)
|| !PACKET_get_1(pkt, &mki)
|| PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
return 0;
}
if (mki != 0) {
/* Must be no MKI, since we never offer one */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_USE_SRTP,
- SSL_R_BAD_SRTP_MKI_VALUE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_SRTP_MKI_VALUE);
return 0;
}
/* Throw an error if the server gave us an unsolicited extension */
clnt = SSL_get_srtp_profiles(s);
if (clnt == NULL) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
- SSL_R_NO_SRTP_PROFILES);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_NO_SRTP_PROFILES);
return 0;
}
@@ -1742,7 +1669,7 @@ int tls_parse_stoc_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
}
}
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
return 0;
}
@@ -1753,10 +1680,12 @@ int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
{
/* Ignore if inappropriate ciphersuite */
if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)
- && s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD
- && s->s3->tmp.new_cipher->algorithm_enc != SSL_RC4
- && s->s3->tmp.new_cipher->algorithm_enc != SSL_eGOST2814789CNT
- && s->s3->tmp.new_cipher->algorithm_enc != SSL_eGOST2814789CNT12)
+ && s->s3.tmp.new_cipher->algorithm_mac != SSL_AEAD
+ && s->s3.tmp.new_cipher->algorithm_enc != SSL_RC4
+ && s->s3.tmp.new_cipher->algorithm_enc != SSL_eGOST2814789CNT
+ && s->s3.tmp.new_cipher->algorithm_enc != SSL_eGOST2814789CNT12
+ && s->s3.tmp.new_cipher->algorithm_enc != SSL_MAGMA
+ && s->s3.tmp.new_cipher->algorithm_enc != SSL_KUZNYECHIK)
s->ext.use_etm = 1;
return 1;
@@ -1765,7 +1694,9 @@ int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
- s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
+ if (s->options & SSL_OP_NO_EXTENDED_MASTER_SECRET)
+ return 1;
+ s->s3.flags |= TLS1_FLAGS_RECEIVED_EXTMS;
if (!s->hit)
s->session->flags |= SSL_SESS_FLAG_EXTMS;
@@ -1779,9 +1710,7 @@ int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context,
if (!PACKET_get_net_2(pkt, &version)
|| PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
@@ -1791,7 +1720,6 @@ int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context,
*/
if (version != TLS1_3_VERSION) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS,
SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
return 0;
}
@@ -1812,18 +1740,17 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
#ifndef OPENSSL_NO_TLS1_3
unsigned int group_id;
PACKET encoded_pt;
- EVP_PKEY *ckey = s->s3->tmp.pkey, *skey = NULL;
+ EVP_PKEY *ckey = s->s3.tmp.pkey, *skey = NULL;
+ const TLS_GROUP_INFO *ginf = NULL;
/* Sanity check */
- if (ckey == NULL || s->s3->peer_tmp != NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
+ if (ckey == NULL || s->s3.peer_tmp != NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!PACKET_get_net_2(pkt, &group_id)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
@@ -1832,8 +1759,7 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t i, num_groups;
if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
@@ -1841,9 +1767,8 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
* It is an error if the HelloRetryRequest wants a key_share that we
* already sent in the first ClientHello
*/
- if (group_id == s->s3->group_id) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
+ if (group_id == s->s3.group_id) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE);
return 0;
}
@@ -1854,56 +1779,94 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
break;
}
if (i >= num_groups
- || !tls_curve_allowed(s, group_id, SSL_SECOP_CURVE_SUPPORTED)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
+ || !tls_group_allowed(s, group_id, SSL_SECOP_CURVE_SUPPORTED)
+ || !tls_valid_group(s, group_id, TLS1_3_VERSION, TLS1_3_VERSION,
+ 0, NULL)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE);
return 0;
}
- s->s3->group_id = group_id;
- EVP_PKEY_free(s->s3->tmp.pkey);
- s->s3->tmp.pkey = NULL;
+ s->s3.group_id = group_id;
+ EVP_PKEY_free(s->s3.tmp.pkey);
+ s->s3.tmp.pkey = NULL;
return 1;
}
- if (group_id != s->s3->group_id) {
+ if (group_id != s->s3.group_id) {
/*
* This isn't for the group that we sent in the original
* key_share!
*/
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
- SSL_R_BAD_KEY_SHARE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE);
return 0;
}
+ /* Retain this group in the SSL_SESSION */
+ if (!s->hit) {
+ s->session->kex_group = group_id;
+ } else if (group_id != s->session->kex_group) {
+ /*
+ * If this is a resumption but changed what group was used, we need
+ * to record the new group in the session, but the session is not
+ * a new session and could be in use by other threads. So, make
+ * a copy of the session to record the new information so that it's
+ * useful for any sessions resumed from tickets issued on this
+ * connection.
+ */
+ SSL_SESSION *new_sess;
- if (!PACKET_as_length_prefixed_2(pkt, &encoded_pt)
- || PACKET_remaining(&encoded_pt) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
+ if ((new_sess = ssl_session_dup(s->session, 0)) == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ SSL_SESSION_free(s->session);
+ s->session = new_sess;
+ s->session->kex_group = group_id;
}
- skey = EVP_PKEY_new();
- if (skey == NULL || EVP_PKEY_copy_parameters(skey, ckey) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
- ERR_R_MALLOC_FAILURE);
- EVP_PKEY_free(skey);
+ if ((ginf = tls1_group_id_lookup(s->ctx, group_id)) == NULL) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE);
return 0;
}
- if (!EVP_PKEY_set1_tls_encodedpoint(skey, PACKET_data(&encoded_pt),
- PACKET_remaining(&encoded_pt))) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
- SSL_R_BAD_ECPOINT);
- EVP_PKEY_free(skey);
+
+ if (!PACKET_as_length_prefixed_2(pkt, &encoded_pt)
+ || PACKET_remaining(&encoded_pt) == 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
- if (ssl_derive(s, ckey, skey, 1) == 0) {
- /* SSLfatal() already called */
- EVP_PKEY_free(skey);
- return 0;
+ if (!ginf->is_kem) {
+ /* Regular KEX */
+ skey = EVP_PKEY_new();
+ if (skey == NULL || EVP_PKEY_copy_parameters(skey, ckey) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_COPY_PARAMETERS_FAILED);
+ EVP_PKEY_free(skey);
+ return 0;
+ }
+
+ if (tls13_set_encoded_pub_key(skey, PACKET_data(&encoded_pt),
+ PACKET_remaining(&encoded_pt)) <= 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_ECPOINT);
+ EVP_PKEY_free(skey);
+ return 0;
+ }
+
+ if (ssl_derive(s, ckey, skey, 1) == 0) {
+ /* SSLfatal() already called */
+ EVP_PKEY_free(skey);
+ return 0;
+ }
+ s->s3.peer_tmp = skey;
+ } else {
+ /* KEM Mode */
+ const unsigned char *ct = PACKET_data(&encoded_pt);
+ size_t ctlen = PACKET_remaining(&encoded_pt);
+
+ if (ssl_decapsulate(s, ckey, ct, ctlen, 1) == 0) {
+ /* SSLfatal() already called */
+ return 0;
+ }
}
- s->s3->peer_tmp = skey;
+ s->s3.did_kex = 1;
#endif
return 1;
@@ -1917,8 +1880,7 @@ int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
if (!PACKET_as_length_prefixed_2(pkt, &cookie)
|| !PACKET_memdup(&cookie, &s->ext.tls13_cookie,
&s->ext.tls13_cookie_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_COOKIE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
@@ -1933,8 +1895,7 @@ int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
if (!PACKET_get_net_4(pkt, &max_early_data)
|| PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
- SSL_R_INVALID_MAX_EARLY_DATA);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_INVALID_MAX_EARLY_DATA);
return 0;
}
@@ -1944,8 +1905,7 @@ int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
}
if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -1956,8 +1916,7 @@ int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
* using the first identity, or the SNI/ALPN is not consistent so the
* server should not be accepting it.
*/
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -1973,14 +1932,12 @@ int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
unsigned int identity;
if (!PACKET_get_net_2(pkt, &identity) || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_PSK,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
if (identity >= (unsigned int)s->ext.tick_identity) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_PSK,
- SSL_R_BAD_PSK_IDENTITY);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_PSK_IDENTITY);
return 0;
}
@@ -1998,8 +1955,7 @@ int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
if (s->psksession == NULL) {
/* Should never happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_PSK,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
diff --git a/ssl/statem/extensions_cust.c b/ssl/statem/extensions_cust.c
index 1fe226f9f264..401a4c5c76b1 100644
--- a/ssl/statem/extensions_cust.c
+++ b/ssl/statem/extensions_cust.c
@@ -1,7 +1,7 @@
/*
* Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -139,8 +139,7 @@ int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type,
* extensions not sent in ClientHello.
*/
if ((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0) {
- SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_CUSTOM_EXT_PARSE,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_R_BAD_EXTENSION);
return 0;
}
}
@@ -160,7 +159,7 @@ int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type,
if (meth->parse_cb(s, ext_type, context, ext_data, ext_size, x, chainidx,
&al, meth->parse_arg) <= 0) {
- SSLfatal(s, al, SSL_F_CUSTOM_EXT_PARSE, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, al, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -210,7 +209,7 @@ int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx,
meth->add_arg);
if (cb_retval < 0) {
- SSLfatal(s, al, SSL_F_CUSTOM_EXT_ADD, SSL_R_CALLBACK_FAILED);
+ SSLfatal(s, al, SSL_R_CALLBACK_FAILED);
return 0; /* error */
}
if (cb_retval == 0)
@@ -221,8 +220,7 @@ int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx,
|| !WPACKET_start_sub_packet_u16(pkt)
|| (outlen > 0 && !WPACKET_memcpy(pkt, out, outlen))
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
@@ -230,8 +228,7 @@ int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx,
* We can't send duplicates: code logic should prevent this.
*/
if (!ossl_assert((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
/*
@@ -492,11 +489,9 @@ int SSL_extension_supported(unsigned int ext_type)
switch (ext_type) {
/* Internally supported extensions. */
case TLSEXT_TYPE_application_layer_protocol_negotiation:
-#ifndef OPENSSL_NO_EC
case TLSEXT_TYPE_ec_point_formats:
case TLSEXT_TYPE_supported_groups:
case TLSEXT_TYPE_key_share:
-#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
case TLSEXT_TYPE_next_proto_neg:
#endif
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index 47541101db50..16765a5a5b6f 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -1,7 +1,7 @@
/*
* Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -47,26 +47,23 @@ int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
/* Parse the length byte */
if (!PACKET_get_1(pkt, &ilen)
|| !PACKET_get_bytes(pkt, &data, ilen)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
- SSL_R_RENEGOTIATION_ENCODING_ERR);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_RENEGOTIATION_ENCODING_ERR);
return 0;
}
/* Check that the extension matches */
- if (ilen != s->s3->previous_client_finished_len) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
- SSL_R_RENEGOTIATION_MISMATCH);
+ if (ilen != s->s3.previous_client_finished_len) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_RENEGOTIATION_MISMATCH);
return 0;
}
- if (memcmp(data, s->s3->previous_client_finished,
- s->s3->previous_client_finished_len)) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
- SSL_R_RENEGOTIATION_MISMATCH);
+ if (memcmp(data, s->s3.previous_client_finished,
+ s->s3.previous_client_finished_len)) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_RENEGOTIATION_MISMATCH);
return 0;
}
- s->s3->send_connection_binding = 1;
+ s->s3.send_connection_binding = 1;
return 1;
}
@@ -103,8 +100,7 @@ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
if (!PACKET_as_length_prefixed_2(pkt, &sni)
/* ServerNameList must be at least 1 byte long. */
|| PACKET_remaining(&sni) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -122,8 +118,7 @@ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
if (!PACKET_get_1(&sni, &servname_type)
|| servname_type != TLSEXT_NAMETYPE_host_name
|| !PACKET_as_length_prefixed_2(&sni, &hostname)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -133,16 +128,12 @@ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
*/
if (!s->hit || SSL_IS_TLS13(s)) {
if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) {
- SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME,
- SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME, SSL_R_BAD_EXTENSION);
return 0;
}
if (PACKET_contains_zero_byte(&hostname)) {
- SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME,
- SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -153,8 +144,7 @@ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
OPENSSL_free(s->ext.hostname);
s->ext.hostname = NULL;
if (!PACKET_strndup(&hostname, &s->ext.hostname)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -165,10 +155,6 @@ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
* the initial handshake and the resumption. In TLSv1.3 SNI is not
* associated with the session.
*/
- /*
- * TODO(openssl-team): if the SNI doesn't match, we MUST
- * fall back to a full handshake.
- */
s->servername_done = (s->session->ext.hostname != NULL)
&& PACKET_equal(&hostname, s->session->ext.hostname,
strlen(s->session->ext.hostname));
@@ -183,15 +169,13 @@ int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
unsigned int value;
if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
/* Received |value| should be a valid max-fragment-length code. */
if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
@@ -203,7 +187,6 @@ int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
*/
if (s->hit && s->session->ext.max_fragment_len_mode != value) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
@@ -224,19 +207,12 @@ int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
if (!PACKET_as_length_prefixed_1(pkt, &srp_I)
|| PACKET_contains_zero_byte(&srp_I)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_SRP,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
- /*
- * TODO(openssl-team): currently, we re-authenticate the user
- * upon resumption. Instead, we MUST ignore the login.
- */
if (!PACKET_strndup(&srp_I, &s->srp_ctx.login)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SRP,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -244,7 +220,6 @@ int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
}
#endif
-#ifndef OPENSSL_NO_EC
int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
@@ -252,8 +227,7 @@ int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
if (!PACKET_as_length_prefixed_1(pkt, &ec_point_format_list)
|| PACKET_remaining(&ec_point_format_list) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -261,15 +235,13 @@ int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
if (!PACKET_memdup(&ec_point_format_list,
&s->ext.peer_ecpointformats,
&s->ext.peer_ecpointformats_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
return 1;
}
-#endif /* OPENSSL_NO_EC */
int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
@@ -278,29 +250,28 @@ int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
!s->ext.session_ticket_cb(s, PACKET_data(pkt),
PACKET_remaining(pkt),
s->ext.session_ticket_cb_arg)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_CTOS_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
-int tls_parse_ctos_sig_algs_cert(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
+int tls_parse_ctos_sig_algs_cert(SSL *s, PACKET *pkt,
+ ossl_unused unsigned int context,
+ ossl_unused X509 *x,
+ ossl_unused size_t chainidx)
{
PACKET supported_sig_algs;
if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs)
|| PACKET_remaining(&supported_sig_algs) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 1)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -314,14 +285,12 @@ int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs)
|| PACKET_remaining(&supported_sig_algs) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 0)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -343,8 +312,7 @@ int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
return 1;
if (!PACKET_get_1(pkt, (unsigned int *)&s->ext.status_type)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -357,8 +325,7 @@ int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
}
if (!PACKET_get_length_prefixed_2 (pkt, &responder_id_list)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -370,8 +337,7 @@ int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
if (PACKET_remaining(&responder_id_list) > 0) {
s->ext.ocsp.ids = sk_OCSP_RESPID_new_null();
if (s->ext.ocsp.ids == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
} else {
@@ -385,33 +351,28 @@ int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
if (!PACKET_get_length_prefixed_2(&responder_id_list, &responder_id)
|| PACKET_remaining(&responder_id) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
id_data = PACKET_data(&responder_id);
- /* TODO(size_t): Convert d2i_* to size_t */
id = d2i_OCSP_RESPID(NULL, &id_data,
(int)PACKET_remaining(&responder_id));
if (id == NULL) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (id_data != PACKET_end(&responder_id)) {
OCSP_RESPID_free(id);
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (!sk_OCSP_RESPID_push(s->ext.ocsp.ids, id)) {
OCSP_RESPID_free(id);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -419,8 +380,7 @@ int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
/* Read in request_extensions */
if (!PACKET_as_length_prefixed_2(pkt, &exts)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -432,8 +392,7 @@ int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
s->ext.ocsp.exts =
d2i_X509_EXTENSIONS(NULL, &ext_data, (int)PACKET_remaining(&exts));
if (s->ext.ocsp.exts == NULL || ext_data != PACKET_end(&exts)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
}
@@ -451,7 +410,7 @@ int tls_parse_ctos_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
* renegotiation.
*/
if (SSL_IS_FIRST_HANDSHAKE(s))
- s->s3->npn_seen = 1;
+ s->s3.npn_seen = 1;
return 1;
}
@@ -471,8 +430,7 @@ int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
if (!PACKET_as_length_prefixed_2(pkt, &protocol_list)
|| PACKET_remaining(&protocol_list) < 2) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -481,19 +439,17 @@ int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
/* Protocol names can't be empty. */
if (!PACKET_get_length_prefixed_1(&protocol_list, &protocol)
|| PACKET_remaining(&protocol) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
} while (PACKET_remaining(&protocol_list) != 0);
- OPENSSL_free(s->s3->alpn_proposed);
- s->s3->alpn_proposed = NULL;
- s->s3->alpn_proposed_len = 0;
+ OPENSSL_free(s->s3.alpn_proposed);
+ s->s3.alpn_proposed = NULL;
+ s->s3.alpn_proposed_len = 0;
if (!PACKET_memdup(&save_protocol_list,
- &s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
- ERR_R_INTERNAL_ERROR);
+ &s->s3.alpn_proposed, &s->s3.alpn_proposed_len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -516,7 +472,7 @@ int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
/* Pull off the length of the cipher suite list and check it is even */
if (!PACKET_get_net_2(pkt, &ct) || (ct & 1) != 0
|| !PACKET_get_sub_packet(pkt, &subpkt, ct)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
return 0;
}
@@ -528,7 +484,7 @@ int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
while (PACKET_remaining(&subpkt)) {
if (!PACKET_get_net_2(&subpkt, &id)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
return 0;
}
@@ -553,15 +509,14 @@ int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
/* Now extract the MKI value as a sanity check, but discard it for now */
if (!PACKET_get_1(pkt, &mki_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
return 0;
}
if (!PACKET_forward(pkt, mki_len)
|| PACKET_remaining(pkt)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
- SSL_R_BAD_SRTP_MKI_VALUE);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_SRTP_MKI_VALUE);
return 0;
}
@@ -591,8 +546,7 @@ int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context,
if (!PACKET_as_length_prefixed_1(pkt, &psk_kex_modes)
|| PACKET_remaining(&psk_kex_modes) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -626,15 +580,13 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
return 1;
/* Sanity check */
- if (s->s3->peer_tmp != NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
+ if (s->s3.peer_tmp != NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
@@ -648,19 +600,18 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
* because we verify that the length is non-zero when we process that
* extension.
*/
- SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
+ SSLfatal(s, SSL_AD_MISSING_EXTENSION,
SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION);
return 0;
}
- if (s->s3->group_id != 0 && PACKET_remaining(&key_share_list) == 0) {
+ if (s->s3.group_id != 0 && PACKET_remaining(&key_share_list) == 0) {
/*
* If we set a group_id already, then we must have sent an HRR
* requesting a new key_share. If we haven't got one then that is an
* error
*/
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
- SSL_R_BAD_KEY_SHARE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE);
return 0;
}
@@ -668,8 +619,7 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
if (!PACKET_get_net_2(&key_share_list, &group_id)
|| !PACKET_get_length_prefixed_2(&key_share_list, &encoded_pt)
|| PACKET_remaining(&encoded_pt) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
@@ -684,40 +634,46 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
* If we sent an HRR then the key_share sent back MUST be for the group
* we requested, and must be the only key_share sent.
*/
- if (s->s3->group_id != 0
- && (group_id != s->s3->group_id
+ if (s->s3.group_id != 0
+ && (group_id != s->s3.group_id
|| PACKET_remaining(&key_share_list) != 0)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE);
return 0;
}
/* Check if this share is in supported_groups sent from client */
if (!check_in_list(s, group_id, clntgroups, clnt_num_groups, 0)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE);
return 0;
}
/* Check if this share is for a group we can use */
- if (!check_in_list(s, group_id, srvrgroups, srvr_num_groups, 1)) {
+ if (!check_in_list(s, group_id, srvrgroups, srvr_num_groups, 1)
+ || !tls_group_allowed(s, group_id, SSL_SECOP_CURVE_SUPPORTED)
+ /*
+ * We tolerate but ignore a group id that we don't think is
+ * suitable for TLSv1.3
+ */
+ || !tls_valid_group(s, group_id, TLS1_3_VERSION, TLS1_3_VERSION,
+ 0, NULL)) {
/* Share not suitable */
continue;
}
- if ((s->s3->peer_tmp = ssl_generate_param_group(group_id)) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
+ if ((s->s3.peer_tmp = ssl_generate_param_group(s, group_id)) == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
return 0;
}
- s->s3->group_id = group_id;
+ s->s3.group_id = group_id;
+ /* Cache the selected group ID in the SSL_SESSION */
+ s->session->kex_group = group_id;
- if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
- PACKET_data(&encoded_pt),
- PACKET_remaining(&encoded_pt))) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_ECPOINT);
+ if (tls13_set_encoded_pub_key(s->s3.peer_tmp,
+ PACKET_data(&encoded_pt),
+ PACKET_remaining(&encoded_pt)) <= 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_ECPOINT);
return 0;
}
@@ -745,12 +701,11 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
/* Ignore any cookie if we're not set up to verify it */
if (s->ctx->verify_stateless_cookie_cb == NULL
- || (s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
+ || (s->s3.flags & TLS1_FLAGS_STATELESS) == 0)
return 1;
if (!PACKET_as_length_prefixed_2(pkt, &cookie)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
@@ -759,35 +714,33 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
rawlen = PACKET_remaining(&raw);
if (rawlen < SHA256_DIGEST_LENGTH
|| !PACKET_forward(&raw, rawlen - SHA256_DIGEST_LENGTH)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
mdin = PACKET_data(&raw);
/* Verify the HMAC of the cookie */
hctx = EVP_MD_CTX_create();
- pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
- s->session_ctx->ext.cookie_hmac_key,
- sizeof(s->session_ctx->ext
- .cookie_hmac_key));
+ pkey = EVP_PKEY_new_raw_private_key_ex(s->ctx->libctx, "HMAC",
+ s->ctx->propq,
+ s->session_ctx->ext.cookie_hmac_key,
+ sizeof(s->session_ctx->ext.cookie_hmac_key));
if (hctx == NULL || pkey == NULL) {
EVP_MD_CTX_free(hctx);
EVP_PKEY_free(pkey);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
hmaclen = SHA256_DIGEST_LENGTH;
- if (EVP_DigestSignInit(hctx, NULL, EVP_sha256(), NULL, pkey) <= 0
+ if (EVP_DigestSignInit_ex(hctx, NULL, "SHA2-256", s->ctx->libctx,
+ s->ctx->propq, pkey, NULL) <= 0
|| EVP_DigestSign(hctx, hmac, &hmaclen, data,
rawlen - SHA256_DIGEST_LENGTH) <= 0
|| hmaclen != SHA256_DIGEST_LENGTH) {
EVP_MD_CTX_free(hctx);
EVP_PKEY_free(pkey);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -795,14 +748,12 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
EVP_PKEY_free(pkey);
if (CRYPTO_memcmp(hmac, mdin, SHA256_DIGEST_LENGTH) != 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_COOKIE_MISMATCH);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_COOKIE_MISMATCH);
return 0;
}
if (!PACKET_get_net_2(&cookie, &format)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
/* Check the cookie format is something we recognise. Ignore it if not */
@@ -816,37 +767,33 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
/* Check the version number is sane */
if (!PACKET_get_net_2(&cookie, &version)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
if (version != TLS1_3_VERSION) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
return 0;
}
if (!PACKET_get_net_2(&cookie, &group_id)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
ciphdata = PACKET_data(&cookie);
if (!PACKET_forward(&cookie, 2)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
- if (group_id != s->s3->group_id
- || s->s3->tmp.new_cipher
+ if (group_id != s->s3.group_id
+ || s->s3.tmp.new_cipher
!= ssl_get_cipher_by_char(s, ciphdata, 0)) {
/*
* We chose a different cipher or group id this time around to what is
* in the cookie. Something must have changed.
*/
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_BAD_CIPHER);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_CIPHER);
return 0;
}
@@ -855,8 +802,7 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|| !PACKET_get_length_prefixed_2(&cookie, &chhash)
|| !PACKET_get_length_prefixed_1(&cookie, &appcookie)
|| PACKET_remaining(&cookie) != SHA256_DIGEST_LENGTH) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
@@ -870,8 +816,7 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
/* Verify the app cookie */
if (s->ctx->verify_stateless_cookie_cb(s, PACKET_data(&appcookie),
PACKET_remaining(&appcookie)) == 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_COOKIE_MISMATCH);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_COOKIE_MISMATCH);
return 0;
}
@@ -881,8 +826,7 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
* Note: This won't work with custom HRR extensions
*/
if (!WPACKET_init_static_len(&hrrpkt, hrr, sizeof(hrr), 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!WPACKET_put_bytes_u8(&hrrpkt, SSL3_MT_SERVER_HELLO)
@@ -891,13 +835,12 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|| !WPACKET_memcpy(&hrrpkt, hrrrandom, SSL3_RANDOM_SIZE)
|| !WPACKET_sub_memcpy_u8(&hrrpkt, s->tmp_session_id,
s->tmp_session_id_len)
- || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, &hrrpkt,
+ || !s->method->put_cipher_by_char(s->s3.tmp.new_cipher, &hrrpkt,
&ciphlen)
|| !WPACKET_put_bytes_u8(&hrrpkt, 0)
|| !WPACKET_start_sub_packet_u16(&hrrpkt)) {
WPACKET_cleanup(&hrrpkt);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_supported_versions)
@@ -905,18 +848,16 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|| !WPACKET_put_bytes_u16(&hrrpkt, s->version)
|| !WPACKET_close(&hrrpkt)) {
WPACKET_cleanup(&hrrpkt);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (key_share) {
if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_key_share)
|| !WPACKET_start_sub_packet_u16(&hrrpkt)
- || !WPACKET_put_bytes_u16(&hrrpkt, s->s3->group_id)
+ || !WPACKET_put_bytes_u16(&hrrpkt, s->s3.group_id)
|| !WPACKET_close(&hrrpkt)) {
WPACKET_cleanup(&hrrpkt);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
@@ -929,8 +870,7 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|| !WPACKET_get_total_written(&hrrpkt, &hrrlen)
|| !WPACKET_finish(&hrrpkt)) {
WPACKET_cleanup(&hrrpkt);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -951,7 +891,6 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
return 1;
}
-#ifndef OPENSSL_NO_EC
int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
@@ -961,8 +900,7 @@ int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
if (!PACKET_as_length_prefixed_2(pkt, &supported_groups_list)
|| PACKET_remaining(&supported_groups_list) == 0
|| (PACKET_remaining(&supported_groups_list) % 2) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -973,28 +911,27 @@ int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
if (!tls1_save_u16(&supported_groups_list,
&s->ext.peer_supportedgroups,
&s->ext.peer_supportedgroups_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
return 1;
}
-#endif
int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
/* The extension must always be empty */
if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_EMS, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
- s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
+ if (s->options & SSL_OP_NO_EXTENDED_MASTER_SECRET)
+ return 1;
+
+ s->s3.flags |= TLS1_FLAGS_RECEIVED_EXTMS;
return 1;
}
@@ -1004,14 +941,12 @@ int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_EARLY_DATA, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (s->hello_retry_request != SSL_HRR_NONE) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_CTOS_EARLY_DATA, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -1064,8 +999,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
return 1;
if (!PACKET_get_length_prefixed_2(pkt, &identities)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -1077,8 +1011,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
if (!PACKET_get_length_prefixed_2(&identities, &identity)
|| !PACKET_get_net_4(&identities, &ticket_agel)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -1086,8 +1019,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
if (s->psk_find_session_cb != NULL
&& !s->psk_find_session_cb(s, PACKET_data(&identity), idlen,
&sess)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
@@ -1100,16 +1032,14 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
unsigned int pskdatalen;
if (!PACKET_strndup(&identity, &pskid)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
pskdatalen = s->psk_server_callback(s, pskid, pskdata,
sizeof(pskdata));
OPENSSL_free(pskid);
if (pskdatalen > PSK_MAX_PSK_LEN) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
} else if (pskdatalen > 0) {
const SSL_CIPHER *cipher;
@@ -1122,8 +1052,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id);
if (cipher == NULL) {
OPENSSL_cleanse(pskdata, pskdatalen);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -1135,8 +1064,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|| !SSL_SESSION_set_protocol_version(sess,
TLS1_3_VERSION)) {
OPENSSL_cleanse(pskdata, pskdatalen);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
OPENSSL_cleanse(pskdata, pskdatalen);
@@ -1149,9 +1077,8 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
SSL_SESSION *sesstmp = ssl_session_dup(sess, 0);
if (sesstmp == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR);
- goto err;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
SSL_SESSION_free(sess);
sess = sesstmp;
@@ -1185,15 +1112,13 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
&sess);
if (ret == SSL_TICKET_EMPTY) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
return 0;
}
if (ret == SSL_TICKET_FATAL_ERR_MALLOC
|| ret == SSL_TICKET_FATAL_ERR_OTHER) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (ret == SSL_TICKET_NONE || ret == SSL_TICKET_NO_DECRYPT)
@@ -1234,8 +1159,14 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
}
}
- md = ssl_md(sess->cipher->algorithm2);
- if (md != ssl_md(s->s3->tmp.new_cipher->algorithm2)) {
+ md = ssl_md(s->ctx, sess->cipher->algorithm2);
+ if (md == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ if (!EVP_MD_is_a(md,
+ EVP_MD_get0_name(ssl_md(s->ctx,
+ s->s3.tmp.new_cipher->algorithm2)))) {
/* The ciphersuite is not compatible with this session. */
SSL_SESSION_free(sess);
sess = NULL;
@@ -1250,25 +1181,22 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
return 1;
binderoffset = PACKET_data(pkt) - (const unsigned char *)s->init_buf->data;
- hashsize = EVP_MD_size(md);
+ hashsize = EVP_MD_get_size(md);
if (!PACKET_get_length_prefixed_2(pkt, &binders)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
goto err;
}
for (i = 0; i <= id; i++) {
if (!PACKET_get_length_prefixed_1(&binders, &binder)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
goto err;
}
}
if (PACKET_remaining(&binder) != hashsize) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
goto err;
}
if (tls_psk_do_binder(s, md, (const unsigned char *)s->init_buf->data,
@@ -1288,11 +1216,13 @@ err:
return 0;
}
-int tls_parse_ctos_post_handshake_auth(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
+int tls_parse_ctos_post_handshake_auth(SSL *s, PACKET *pkt,
+ ossl_unused unsigned int context,
+ ossl_unused X509 *x,
+ ossl_unused size_t chainidx)
{
if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH,
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR);
return 0;
}
@@ -1309,21 +1239,20 @@ EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
- if (!s->s3->send_connection_binding)
+ if (!s->s3.send_connection_binding)
return EXT_RETURN_NOT_SENT;
/* Still add this even if SSL_OP_NO_RENEGOTIATION is set */
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u8(pkt)
- || !WPACKET_memcpy(pkt, s->s3->previous_client_finished,
- s->s3->previous_client_finished_len)
- || !WPACKET_memcpy(pkt, s->s3->previous_server_finished,
- s->s3->previous_server_finished_len)
+ || !WPACKET_memcpy(pkt, s->s3.previous_client_finished,
+ s->s3.previous_client_finished_len)
+ || !WPACKET_memcpy(pkt, s->s3.previous_server_finished,
+ s->s3.previous_server_finished_len)
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1346,8 +1275,7 @@ EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1370,21 +1298,19 @@ EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u8(pkt, s->session->ext.max_fragment_len_mode)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
-#ifndef OPENSSL_NO_EC
EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
- unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
- unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+ unsigned long alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
+ unsigned long alg_a = s->s3.tmp.new_cipher->algorithm_auth;
int using_ecc = ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))
&& (s->ext.peer_ecpointformats != NULL);
const unsigned char *plist;
@@ -1398,46 +1324,45 @@ EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_sub_memcpy_u8(pkt, plist, plistlen)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
-#endif
-#ifndef OPENSSL_NO_EC
EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
const uint16_t *groups;
size_t numgroups, i, first = 1;
+ int version;
- /* s->s3->group_id is non zero if we accepted a key_share */
- if (s->s3->group_id == 0)
+ /* s->s3.group_id is non zero if we accepted a key_share */
+ if (s->s3.group_id == 0)
return EXT_RETURN_NOT_SENT;
/* Get our list of supported groups */
tls1_get_supported_groups(s, &groups, &numgroups);
if (numgroups == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/* Copy group ID if supported */
+ version = SSL_version(s);
for (i = 0; i < numgroups; i++) {
uint16_t group = groups[i];
- if (tls_curve_allowed(s, group, SSL_SECOP_CURVE_SUPPORTED)) {
+ if (tls_valid_group(s, group, version, version, 0, NULL)
+ && tls_group_allowed(s, group, SSL_SECOP_CURVE_SUPPORTED)) {
if (first) {
/*
* Check if the client is already using our preferred group. If
* so we don't need to add this extension
*/
- if (s->s3->group_id == group)
+ if (s->s3.group_id == group)
return EXT_RETURN_NOT_SENT;
/* Add extension header */
@@ -1445,33 +1370,26 @@ EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt,
/* Sub-packet for supported_groups extension */
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
first = 0;
}
if (!WPACKET_put_bytes_u16(pkt, group)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
}
}
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
-#endif
EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
@@ -1484,8 +1402,7 @@ EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt,
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1509,8 +1426,7 @@ EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt,
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
|| !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1524,8 +1440,7 @@ EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt,
return EXT_RETURN_FAIL;
}
if (!WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1541,9 +1456,9 @@ EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt,
const unsigned char *npa;
unsigned int npalen;
int ret;
- int npn_seen = s->s3->npn_seen;
+ int npn_seen = s->s3.npn_seen;
- s->s3->npn_seen = 0;
+ s->s3.npn_seen = 0;
if (!npn_seen || s->ctx->ext.npn_advertised_cb == NULL)
return EXT_RETURN_NOT_SENT;
@@ -1552,12 +1467,10 @@ EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt,
if (ret == SSL_TLSEXT_ERR_OK) {
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
|| !WPACKET_sub_memcpy_u16(pkt, npa, npalen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
- s->s3->npn_seen = 1;
+ s->s3.npn_seen = 1;
}
return EXT_RETURN_SENT;
@@ -1567,19 +1480,18 @@ EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt,
EXT_RETURN tls_construct_stoc_alpn(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
- if (s->s3->alpn_selected == NULL)
+ if (s->s3.alpn_selected == NULL)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt,
TLSEXT_TYPE_application_layer_protocol_negotiation)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_sub_memcpy_u8(pkt, s->s3->alpn_selected,
- s->s3->alpn_selected_len)
+ || !WPACKET_sub_memcpy_u8(pkt, s->s3.alpn_selected,
+ s->s3.alpn_selected_len)
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_ALPN, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1600,8 +1512,7 @@ EXT_RETURN tls_construct_stoc_use_srtp(SSL *s, WPACKET *pkt,
|| !WPACKET_put_bytes_u16(pkt, s->srtp_profile->id)
|| !WPACKET_put_bytes_u8(pkt, 0)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1619,18 +1530,19 @@ EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
* Don't use encrypt_then_mac if AEAD or RC4 might want to disable
* for other cases too.
*/
- if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD
- || s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4
- || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT
- || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) {
+ if (s->s3.tmp.new_cipher->algorithm_mac == SSL_AEAD
+ || s->s3.tmp.new_cipher->algorithm_enc == SSL_RC4
+ || s->s3.tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT
+ || s->s3.tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12
+ || s->s3.tmp.new_cipher->algorithm_enc == SSL_MAGMA
+ || s->s3.tmp.new_cipher->algorithm_enc == SSL_KUZNYECHIK) {
s->ext.use_etm = 0;
return EXT_RETURN_NOT_SENT;
}
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_ETM,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1640,13 +1552,12 @@ EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
- if ((s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) == 0)
+ if ((s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS) == 0)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EMS,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1658,9 +1569,7 @@ EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt,
size_t chainidx)
{
if (!ossl_assert(SSL_IS_TLS13(s))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1668,9 +1577,7 @@ EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt,
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u16(pkt, s->version)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1684,7 +1591,8 @@ EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
#ifndef OPENSSL_NO_TLS1_3
unsigned char *encodedPoint;
size_t encoded_pt_len = 0;
- EVP_PKEY *ckey = s->s3->peer_tmp, *skey = NULL;
+ EVP_PKEY *ckey = s->s3.peer_tmp, *skey = NULL;
+ const TLS_GROUP_INFO *ginf = NULL;
if (s->hello_retry_request == SSL_HRR_PENDING) {
if (ckey != NULL) {
@@ -1693,11 +1601,9 @@ EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
}
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
|| !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)
+ || !WPACKET_put_bytes_u16(pkt, s->s3.group_id)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1707,8 +1613,7 @@ EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
if (ckey == NULL) {
/* No key_share received from client - must be resuming */
if (!s->hit || !tls13_generate_handshake_secret(s, NULL, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_NOT_SENT;
@@ -1723,44 +1628,88 @@ EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
|| !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+ || !WPACKET_put_bytes_u16(pkt, s->s3.group_id)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
- skey = ssl_generate_pkey(ckey);
- if (skey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
- ERR_R_MALLOC_FAILURE);
+ if ((ginf = tls1_group_id_lookup(s->ctx, s->s3.group_id)) == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
- /* Generate encoding of server key */
- encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(skey, &encodedPoint);
- if (encoded_pt_len == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
- ERR_R_EC_LIB);
- EVP_PKEY_free(skey);
- return EXT_RETURN_FAIL;
- }
+ if (!ginf->is_kem) {
+ /* Regular KEX */
+ skey = ssl_generate_pkey(s, ckey);
+ if (skey == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ return EXT_RETURN_FAIL;
+ }
- if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
- EVP_PKEY_free(skey);
+ /* Generate encoding of server key */
+ encoded_pt_len = EVP_PKEY_get1_encoded_public_key(skey, &encodedPoint);
+ if (encoded_pt_len == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EC_LIB);
+ EVP_PKEY_free(skey);
+ return EXT_RETURN_FAIL;
+ }
+
+ if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ EVP_PKEY_free(skey);
+ OPENSSL_free(encodedPoint);
+ return EXT_RETURN_FAIL;
+ }
OPENSSL_free(encodedPoint);
- return EXT_RETURN_FAIL;
- }
- OPENSSL_free(encodedPoint);
- /* This causes the crypto state to be updated based on the derived keys */
- s->s3->tmp.pkey = skey;
- if (ssl_derive(s, skey, ckey, 1) == 0) {
- /* SSLfatal() already called */
- return EXT_RETURN_FAIL;
+ /*
+ * This causes the crypto state to be updated based on the derived keys
+ */
+ s->s3.tmp.pkey = skey;
+ if (ssl_derive(s, skey, ckey, 1) == 0) {
+ /* SSLfatal() already called */
+ return EXT_RETURN_FAIL;
+ }
+ } else {
+ /* KEM mode */
+ unsigned char *ct = NULL;
+ size_t ctlen = 0;
+
+ /*
+ * This does not update the crypto state.
+ *
+ * The generated pms is stored in `s->s3.tmp.pms` to be later used via
+ * ssl_gensecret().
+ */
+ if (ssl_encapsulate(s, ckey, &ct, &ctlen, 0) == 0) {
+ /* SSLfatal() already called */
+ return EXT_RETURN_FAIL;
+ }
+
+ if (ctlen == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ OPENSSL_free(ct);
+ return EXT_RETURN_FAIL;
+ }
+
+ if (!WPACKET_sub_memcpy_u16(pkt, ct, ctlen)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ OPENSSL_free(ct);
+ return EXT_RETURN_FAIL;
+ }
+ OPENSSL_free(ct);
+
+ /*
+ * This causes the crypto state to be updated based on the generated pms
+ */
+ if (ssl_gensecret(s, s->s3.tmp.pms, s->s3.tmp.pmslen) == 0) {
+ /* SSLfatal() already called */
+ return EXT_RETURN_FAIL;
+ }
}
+ s->s3.did_kex = 1;
return EXT_RETURN_SENT;
#else
return EXT_RETURN_FAIL;
@@ -1778,12 +1727,11 @@ EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
EVP_PKEY *pkey;
int ret = EXT_RETURN_FAIL;
- if ((s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
+ if ((s->s3.flags & TLS1_FLAGS_STATELESS) == 0)
return EXT_RETURN_NOT_SENT;
if (s->ctx->gen_stateless_cookie_cb == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- SSL_R_NO_COOKIE_CALLBACK_SET);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_NO_COOKIE_CALLBACK_SET);
return EXT_RETURN_FAIL;
}
@@ -1794,16 +1742,15 @@ EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
|| !WPACKET_reserve_bytes(pkt, MAX_COOKIE_SIZE, &cookie)
|| !WPACKET_put_bytes_u16(pkt, COOKIE_STATE_FORMAT_VERSION)
|| !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION)
- || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)
- || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt,
+ || !WPACKET_put_bytes_u16(pkt, s->s3.group_id)
+ || !s->method->put_cipher_by_char(s->s3.tmp.new_cipher, pkt,
&ciphlen)
/* Is there a key_share extension present in this HRR? */
- || !WPACKET_put_bytes_u8(pkt, s->s3->peer_tmp == NULL)
+ || !WPACKET_put_bytes_u8(pkt, s->s3.peer_tmp == NULL)
|| !WPACKET_put_bytes_u64(pkt, time(NULL))
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &hashval1)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1823,15 +1770,13 @@ EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
|| !WPACKET_close(pkt)
|| !WPACKET_start_sub_packet_u8(pkt)
|| !WPACKET_reserve_bytes(pkt, SSL_COOKIE_LENGTH, &appcookie1)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/* Generate the application cookie */
if (s->ctx->gen_stateless_cookie_cb(s, appcookie1, &appcookielen) == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
return EXT_RETURN_FAIL;
}
@@ -1840,42 +1785,38 @@ EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
|| !WPACKET_close(pkt)
|| !WPACKET_get_total_written(pkt, &totcookielen)
|| !WPACKET_reserve_bytes(pkt, SHA256_DIGEST_LENGTH, &hmac)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
hmaclen = SHA256_DIGEST_LENGTH;
totcookielen -= startlen;
if (!ossl_assert(totcookielen <= MAX_COOKIE_SIZE - SHA256_DIGEST_LENGTH)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/* HMAC the cookie */
hctx = EVP_MD_CTX_create();
- pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
- s->session_ctx->ext.cookie_hmac_key,
- sizeof(s->session_ctx->ext
- .cookie_hmac_key));
+ pkey = EVP_PKEY_new_raw_private_key_ex(s->ctx->libctx, "HMAC",
+ s->ctx->propq,
+ s->session_ctx->ext.cookie_hmac_key,
+ sizeof(s->session_ctx->ext.cookie_hmac_key));
if (hctx == NULL || pkey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (EVP_DigestSignInit(hctx, NULL, EVP_sha256(), NULL, pkey) <= 0
+ if (EVP_DigestSignInit_ex(hctx, NULL, "SHA2-256", s->ctx->libctx,
+ s->ctx->propq, pkey, NULL) <= 0
|| EVP_DigestSign(hctx, hmac, &hmaclen, cookie,
totcookielen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (!ossl_assert(totcookielen + hmaclen <= MAX_COOKIE_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -1884,8 +1825,7 @@ EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
|| !ossl_assert(cookie == hmac - totcookielen)
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -1913,14 +1853,13 @@ EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt,
0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17
};
- if (((s->s3->tmp.new_cipher->id & 0xFFFF) != 0x80
- && (s->s3->tmp.new_cipher->id & 0xFFFF) != 0x81)
+ if (((s->s3.tmp.new_cipher->id & 0xFFFF) != 0x80
+ && (s->s3.tmp.new_cipher->id & 0xFFFF) != 0x81)
|| (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG) == 0)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_memcpy(pkt, cryptopro_ext, sizeof(cryptopro_ext))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1939,8 +1878,7 @@ EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u32(pkt, s->max_early_data)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1953,8 +1891,7 @@ EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
@@ -1971,8 +1908,7 @@ EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u16(pkt, s->ext.tick_identity)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_PSK, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c
index 20f5bd584e6c..553546d93a41 100644
--- a/ssl/statem/statem.c
+++ b/ssl/statem/statem.c
@@ -1,12 +1,17 @@
/*
- * Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#if defined(__TANDEM) && defined(_SPT_MODEL_)
+# include <spthread.h>
+# include <spt_extensions.h> /* timeval */
+#endif
+
#include "internal/cryptlib.h"
#include <openssl/rand.h>
#include "../ssl_local.h"
@@ -111,14 +116,8 @@ void ossl_statem_set_renegotiate(SSL *s)
s->statem.request_state = TLS_ST_SW_HELLO_REQ;
}
-/*
- * Put the state machine into an error state and send an alert if appropriate.
- * This is a permanent error for the current connection.
- */
-void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
- int line)
+void ossl_statem_send_fatal(SSL *s, int al)
{
- ERR_put_error(ERR_LIB_SSL, func, reason, file, line);
/* We shouldn't call SSLfatal() twice. Once is enough */
if (s->statem.in_init && s->statem.state == MSG_FLOW_ERROR)
return;
@@ -130,16 +129,32 @@ void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
}
/*
+ * Error reporting building block that's used instead of ERR_set_error().
+ * In addition to what ERR_set_error() does, this puts the state machine
+ * into an error state and sends an alert if appropriate.
+ * This is a permanent error for the current connection.
+ */
+void ossl_statem_fatal(SSL *s, int al, int reason, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ ERR_vset_error(ERR_LIB_SSL, reason, fmt, args);
+ va_end(args);
+
+ ossl_statem_send_fatal(s, al);
+}
+
+/*
* This macro should only be called if we are already expecting to be in
* a fatal error state. We verify that we are, and set it if not (this would
* indicate a bug).
*/
-#define check_fatal(s, f) \
+#define check_fatal(s) \
do { \
if (!ossl_assert((s)->statem.in_init \
&& (s)->statem.state == MSG_FLOW_ERROR)) \
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, (f), \
- SSL_R_MISSING_FATAL); \
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_MISSING_FATAL); \
} while (0)
/*
@@ -319,7 +334,7 @@ static int state_machine(SSL *s, int server)
* If we are stateless then we already called SSL_clear() - don't do
* it again and clear the STATELESS flag itself.
*/
- if ((s->s3->flags & TLS1_FLAGS_STATELESS) == 0 && !SSL_clear(s))
+ if ((s->s3.flags & TLS1_FLAGS_STATELESS) == 0 && !SSL_clear(s))
return -1;
}
#ifndef OPENSSL_NO_SCTP
@@ -356,33 +371,28 @@ static int state_machine(SSL *s, int server)
if (SSL_IS_DTLS(s)) {
if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00) &&
(server || (s->version & 0xff00) != (DTLS1_BAD_VER & 0xff00))) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_NO_ALERT, ERR_R_INTERNAL_ERROR);
goto end;
}
} else {
if ((s->version >> 8) != SSL3_VERSION_MAJOR) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_NO_ALERT, ERR_R_INTERNAL_ERROR);
goto end;
}
}
if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_NO_ALERT, ERR_R_INTERNAL_ERROR);
goto end;
}
if (s->init_buf == NULL) {
if ((buf = BUF_MEM_new()) == NULL) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_NO_ALERT, ERR_R_INTERNAL_ERROR);
goto end;
}
if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_NO_ALERT, ERR_R_INTERNAL_ERROR);
goto end;
}
s->init_buf = buf;
@@ -390,8 +400,7 @@ static int state_machine(SSL *s, int server)
}
if (!ssl3_setup_buffers(s)) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_NO_ALERT, ERR_R_INTERNAL_ERROR);
goto end;
}
s->init_num = 0;
@@ -399,7 +408,7 @@ static int state_machine(SSL *s, int server)
/*
* Should have been reset by tls_process_finished, too.
*/
- s->s3->change_cipher_spec = 0;
+ s->s3.change_cipher_spec = 0;
/*
* Ok, we now need to push on a buffering BIO ...but not with
@@ -409,8 +418,7 @@ static int state_machine(SSL *s, int server)
if (!SSL_IS_DTLS(s) || !BIO_dgram_is_sctp(SSL_get_wbio(s)))
#endif
if (!ssl_init_wbio_buffer(s)) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_NO_ALERT, ERR_R_INTERNAL_ERROR);
goto end;
}
@@ -452,8 +460,8 @@ static int state_machine(SSL *s, int server)
}
} else {
/* Error */
- check_fatal(s, SSL_F_STATE_MACHINE);
- SSLerr(SSL_F_STATE_MACHINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ check_fatal(s);
+ ERR_raise(ERR_LIB_SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
goto end;
}
}
@@ -574,7 +582,7 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
/*
* In DTLS we get the whole message in one go - header and body
*/
- ret = dtls_get_message(s, &mt, &len);
+ ret = dtls_get_message(s, &mt);
} else {
ret = tls_get_message_header(s, &mt);
}
@@ -598,19 +606,18 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
if (!transition(s, mt))
return SUB_STATE_ERROR;
- if (s->s3->tmp.message_size > max_message_size(s)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_READ_STATE_MACHINE,
+ if (s->s3.tmp.message_size > max_message_size(s)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_EXCESSIVE_MESSAGE_SIZE);
return SUB_STATE_ERROR;
}
/* dtls_get_message already did this */
if (!SSL_IS_DTLS(s)
- && s->s3->tmp.message_size > 0
- && !grow_init_buf(s, s->s3->tmp.message_size
+ && s->s3.tmp.message_size > 0
+ && !grow_init_buf(s, s->s3.tmp.message_size
+ SSL3_HM_HEADER_LENGTH)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
- ERR_R_BUF_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_BUF_LIB);
return SUB_STATE_ERROR;
}
@@ -618,19 +625,23 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
/* Fall through */
case READ_STATE_BODY:
- if (!SSL_IS_DTLS(s)) {
- /* We already got this above for DTLS */
+ if (SSL_IS_DTLS(s)) {
+ /*
+ * Actually we already have the body, but we give DTLS the
+ * opportunity to do any further processing.
+ */
+ ret = dtls_get_message_body(s, &len);
+ } else {
ret = tls_get_message_body(s, &len);
- if (ret == 0) {
- /* Could be non-blocking IO */
- return SUB_STATE_ERROR;
- }
+ }
+ if (ret == 0) {
+ /* Could be non-blocking IO */
+ return SUB_STATE_ERROR;
}
s->first_packet = 0;
if (!PACKET_buf_init(&pkt, s->init_msg, len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return SUB_STATE_ERROR;
}
ret = process_message(s, &pkt);
@@ -640,7 +651,7 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
switch (ret) {
case MSG_PROCESS_ERROR:
- check_fatal(s, SSL_F_READ_STATE_MACHINE);
+ check_fatal(s);
return SUB_STATE_ERROR;
case MSG_PROCESS_FINISHED_READING:
@@ -664,7 +675,7 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
st->read_state_work = post_process_message(s, st->read_state_work);
switch (st->read_state_work) {
case WORK_ERROR:
- check_fatal(s, SSL_F_READ_STATE_MACHINE);
+ check_fatal(s);
/* Fall through */
case WORK_MORE_A:
case WORK_MORE_B:
@@ -685,8 +696,7 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
default:
/* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return SUB_STATE_ERROR;
}
}
@@ -801,7 +811,7 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
break;
case WRITE_TRAN_ERROR:
- check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
+ check_fatal(s);
return SUB_STATE_ERROR;
}
break;
@@ -809,7 +819,7 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
case WRITE_STATE_PRE_WORK:
switch (st->write_state_work = pre_work(s, st->write_state_work)) {
case WORK_ERROR:
- check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
+ check_fatal(s);
/* Fall through */
case WORK_MORE_A:
case WORK_MORE_B:
@@ -836,20 +846,32 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
if (!WPACKET_init(&pkt, s->init_buf)
|| !ssl_set_handshake_header(s, &pkt, mt)) {
WPACKET_cleanup(&pkt);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return SUB_STATE_ERROR;
}
- if (confunc != NULL && !confunc(s, &pkt)) {
- WPACKET_cleanup(&pkt);
- check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
- return SUB_STATE_ERROR;
+ if (confunc != NULL) {
+ int tmpret;
+
+ tmpret = confunc(s, &pkt);
+ if (tmpret <= 0) {
+ WPACKET_cleanup(&pkt);
+ check_fatal(s);
+ return SUB_STATE_ERROR;
+ } else if (tmpret == 2) {
+ /*
+ * The construction function decided not to construct the
+ * message after all and continue. Skip sending.
+ */
+ WPACKET_cleanup(&pkt);
+ st->write_state = WRITE_STATE_POST_WORK;
+ st->write_state_work = WORK_MORE_A;
+ break;
+ } /* else success */
}
if (!ssl_close_construct_packet(s, &pkt, mt)
|| !WPACKET_finish(&pkt)) {
WPACKET_cleanup(&pkt);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return SUB_STATE_ERROR;
}
@@ -870,7 +892,7 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
case WRITE_STATE_POST_WORK:
switch (st->write_state_work = post_work(s, st->write_state_work)) {
case WORK_ERROR:
- check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
+ check_fatal(s);
/* Fall through */
case WORK_MORE_A:
case WORK_MORE_B:
@@ -887,8 +909,7 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
break;
default:
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return SUB_STATE_ERROR;
}
}
@@ -923,7 +944,7 @@ int ossl_statem_app_data_allowed(SSL *s)
if (st->state == MSG_FLOW_UNINITED)
return 0;
- if (!s->s3->in_read_app_data || (s->s3->total_renegotiations == 0))
+ if (!s->s3.in_read_app_data || (s->s3.total_renegotiations == 0))
return 0;
if (s->server) {
@@ -952,7 +973,7 @@ int ossl_statem_app_data_allowed(SSL *s)
*/
int ossl_statem_export_allowed(SSL *s)
{
- return s->s3->previous_server_finished_len != 0
+ return s->s3.previous_server_finished_len != 0
&& s->statem.hand_state != TLS_ST_SW_FINISHED;
}
diff --git a/ssl/statem/statem.h b/ssl/statem/statem.h
index 144d930fc7c5..5db31b63585d 100644
--- a/ssl/statem/statem.h
+++ b/ssl/statem/statem.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -132,15 +132,15 @@ __owur int ossl_statem_accept(SSL *s);
__owur int ossl_statem_connect(SSL *s);
void ossl_statem_clear(SSL *s);
void ossl_statem_set_renegotiate(SSL *s);
-void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
- int line);
+void ossl_statem_send_fatal(SSL *s, int al);
+void ossl_statem_fatal(SSL *s, int al, int reason, const char *fmt, ...);
# define SSL_AD_NO_ALERT -1
-# ifndef OPENSSL_NO_ERR
-# define SSLfatal(s, al, f, r) ossl_statem_fatal((s), (al), (f), (r), \
- OPENSSL_FILE, OPENSSL_LINE)
-# else
-# define SSLfatal(s, al, f, r) ossl_statem_fatal((s), (al), (f), (r), NULL, 0)
-# endif
+# define SSLfatal_alert(s, al) ossl_statem_send_fatal((s), (al))
+# define SSLfatal(s, al, r) SSLfatal_data((s), (al), (r), NULL)
+# define SSLfatal_data \
+ (ERR_new(), \
+ ERR_set_debug(OPENSSL_FILE, OPENSSL_LINE, OPENSSL_FUNC), \
+ ossl_statem_fatal)
int ossl_statem_in_error(const SSL *s);
void ossl_statem_set_in_init(SSL *s, int init);
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index d19c44e8d984..3cd1ee2d3dfe 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -3,7 +3,7 @@
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -20,9 +20,13 @@
#include <openssl/evp.h>
#include <openssl/md5.h>
#include <openssl/dh.h>
+#include <openssl/rsa.h>
#include <openssl/bn.h>
#include <openssl/engine.h>
-#include <internal/cryptlib.h>
+#include <openssl/trace.h>
+#include <openssl/core_names.h>
+#include <openssl/param_build.h>
+#include "internal/cryptlib.h"
static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s, PACKET *pkt);
static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt);
@@ -43,8 +47,8 @@ static ossl_inline int cert_req_allowed(SSL *s)
{
/* TLS does not like anon-DH with client cert */
if ((s->version > SSL3_VERSION
- && (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL))
- || (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aSRP | SSL_aPSK)))
+ && (s->s3.tmp.new_cipher->algorithm_auth & SSL_aNULL))
+ || (s->s3.tmp.new_cipher->algorithm_auth & (SSL_aSRP | SSL_aPSK)))
return 0;
return 1;
@@ -59,7 +63,7 @@ static ossl_inline int cert_req_allowed(SSL *s)
*/
static int key_exchange_expected(SSL *s)
{
- long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ long alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
/*
* Can't skip server key exchange if this is an ephemeral
@@ -163,8 +167,9 @@ static int ossl_statem_client13_read_transition(SSL *s, int mt)
return 1;
}
if (mt == SSL3_MT_CERTIFICATE_REQUEST) {
-#if DTLS_MAX_VERSION != DTLS1_2_VERSION
-# error TODO(DTLS1.3): Restore digest for PHA before adding message.
+#if DTLS_MAX_VERSION_INTERNAL != DTLS1_2_VERSION
+ /* Restore digest for PHA before adding message.*/
+# error Internal DTLS version error
#endif
if (!SSL_IS_DTLS(s) && s->post_handshake_auth == SSL_PHA_EXT_SENT) {
s->post_handshake_auth = SSL_PHA_REQUESTED;
@@ -271,7 +276,7 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
s->hit = 1;
st->hand_state = TLS_ST_CR_CHANGE;
return 1;
- } else if (!(s->s3->tmp.new_cipher->algorithm_auth
+ } else if (!(s->s3.tmp.new_cipher->algorithm_auth
& (SSL_aNULL | SSL_aSRP | SSL_aPSK))) {
if (mt == SSL3_MT_CERTIFICATE) {
st->hand_state = TLS_ST_CR_CERT;
@@ -281,7 +286,7 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
ske_expected = key_exchange_expected(s);
/* SKE is optional for some PSK ciphersuites */
if (ske_expected
- || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)
+ || ((s->s3.tmp.new_cipher->algorithm_mkey & SSL_PSK)
&& mt == SSL3_MT_SERVER_KEY_EXCHANGE)) {
if (mt == SSL3_MT_SERVER_KEY_EXCHANGE) {
st->hand_state = TLS_ST_CR_KEY_EXCH;
@@ -313,7 +318,7 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
case TLS_ST_CR_CERT_STATUS:
ske_expected = key_exchange_expected(s);
/* SKE is optional for some PSK ciphersuites */
- if (ske_expected || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)
+ if (ske_expected || ((s->s3.tmp.new_cipher->algorithm_mkey & SSL_PSK)
&& mt == SSL3_MT_SERVER_KEY_EXCHANGE)) {
if (mt == SSL3_MT_SERVER_KEY_EXCHANGE) {
st->hand_state = TLS_ST_CR_KEY_EXCH;
@@ -390,9 +395,7 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
BIO_set_retry_read(rbio);
return 0;
}
- SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE,
- SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION,
- SSL_R_UNEXPECTED_MESSAGE);
+ SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
return 0;
}
@@ -413,9 +416,7 @@ static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s)
switch (st->hand_state) {
default:
/* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WRITE_TRAN_ERROR;
case TLS_ST_CR_CERT_REQ:
@@ -429,9 +430,7 @@ static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s)
*/
if (!ossl_assert((s->shutdown & SSL_SENT_SHUTDOWN) != 0)) {
/* Shouldn't happen - same as default case */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WRITE_TRAN_ERROR;
}
st->hand_state = TLS_ST_OK;
@@ -445,7 +444,7 @@ static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s)
&& s->hello_retry_request == SSL_HRR_NONE)
st->hand_state = TLS_ST_CW_CHANGE;
else
- st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
+ st->hand_state = (s->s3.tmp.cert_req != 0) ? TLS_ST_CW_CERT
: TLS_ST_CW_FINISHED;
return WRITE_TRAN_CONTINUE;
@@ -458,13 +457,13 @@ static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s)
case TLS_ST_CW_END_OF_EARLY_DATA:
case TLS_ST_CW_CHANGE:
- st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
+ st->hand_state = (s->s3.tmp.cert_req != 0) ? TLS_ST_CW_CERT
: TLS_ST_CW_FINISHED;
return WRITE_TRAN_CONTINUE;
case TLS_ST_CW_CERT:
/* If a non-empty Certificate we also send CertificateVerify */
- st->hand_state = (s->s3->tmp.cert_req == 1) ? TLS_ST_CW_CERT_VRFY
+ st->hand_state = (s->s3.tmp.cert_req == 1) ? TLS_ST_CW_CERT_VRFY
: TLS_ST_CW_FINISHED;
return WRITE_TRAN_CONTINUE;
@@ -509,9 +508,7 @@ WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
switch (st->hand_state) {
default:
/* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WRITE_TRAN_ERROR;
case TLS_ST_OK:
@@ -567,7 +564,7 @@ WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
return WRITE_TRAN_CONTINUE;
case TLS_ST_CR_SRVR_DONE:
- if (s->s3->tmp.cert_req)
+ if (s->s3.tmp.cert_req)
st->hand_state = TLS_ST_CW_CERT;
else
st->hand_state = TLS_ST_CW_KEY_EXCH;
@@ -588,12 +585,12 @@ WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
* need to skip the certificate verify message when client's
* ECDH public key is sent inside the client certificate.
*/
- if (s->s3->tmp.cert_req == 1) {
+ if (s->s3.tmp.cert_req == 1) {
st->hand_state = TLS_ST_CW_CERT_VRFY;
} else {
st->hand_state = TLS_ST_CW_CHANGE;
}
- if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) {
+ if (s->s3.flags & TLS1_FLAGS_SKIP_CERT_VERIFY) {
st->hand_state = TLS_ST_CW_CHANGE;
}
return WRITE_TRAN_CONTINUE;
@@ -611,7 +608,7 @@ WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
#if defined(OPENSSL_NO_NEXTPROTONEG)
st->hand_state = TLS_ST_CW_FINISHED;
#else
- if (!SSL_IS_DTLS(s) && s->s3->npn_seen)
+ if (!SSL_IS_DTLS(s) && s->s3.npn_seen)
st->hand_state = TLS_ST_CW_NEXT_PROTO;
else
st->hand_state = TLS_ST_CW_FINISHED;
@@ -796,14 +793,14 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
return WORK_ERROR;
break;
}
- s->session->cipher = s->s3->tmp.new_cipher;
+ s->session->cipher = s->s3.tmp.new_cipher;
#ifdef OPENSSL_NO_COMP
s->session->compress_meth = 0;
#else
- if (s->s3->tmp.new_compression == NULL)
+ if (s->s3.tmp.new_compression == NULL)
s->session->compress_meth = 0;
else
- s->session->compress_meth = s->s3->tmp.new_compression->id;
+ s->session->compress_meth = s->s3.tmp.new_compression->id;
#endif
if (!s->method->ssl3_enc->setup_key_block(s)) {
/* SSLfatal() already called */
@@ -890,9 +887,7 @@ int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt,
switch (st->hand_state) {
default:
/* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE,
- SSL_R_BAD_HANDSHAKE_STATE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_HANDSHAKE_STATE);
return 0;
case TLS_ST_CW_CHANGE:
@@ -1016,7 +1011,7 @@ size_t ossl_statem_client_max_message_size(SSL *s)
}
/*
- * Process a message that the client has been received from the server.
+ * Process a message that the client has received from the server.
*/
MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt)
{
@@ -1025,9 +1020,7 @@ MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt)
switch (st->hand_state) {
default:
/* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
case TLS_ST_CR_SRVR_HELLO:
@@ -1085,11 +1078,12 @@ WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst)
switch (st->hand_state) {
default:
/* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
+ case TLS_ST_CR_CERT:
+ return tls_post_process_server_certificate(s, wst);
+
case TLS_ST_CR_CERT_VRFY:
case TLS_ST_CR_CERT_REQ:
return tls_prepare_client_certificate(s, wst);
@@ -1110,8 +1104,7 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
/* Work out what SSL/TLS/DTLS version to use */
protverr = ssl_set_client_hello_version(s);
if (protverr != 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- protverr);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, protverr);
return 0;
}
@@ -1126,7 +1119,7 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
}
/* else use the pre-loaded session */
- p = s->s3->client_random;
+ p = s->s3.client_random;
/*
* for DTLS if client_random is initialized, reuse it, we are
@@ -1135,7 +1128,7 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
if (SSL_IS_DTLS(s)) {
size_t idx;
i = 1;
- for (idx = 0; idx < sizeof(s->s3->client_random); idx++) {
+ for (idx = 0; idx < sizeof(s->s3.client_random); idx++) {
if (p[idx]) {
i = 0;
break;
@@ -1145,10 +1138,9 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
i = (s->hello_retry_request == SSL_HRR_NONE);
}
- if (i && ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random),
+ if (i && ssl_fill_hello_random(s, 0, p, sizeof(s->s3.client_random),
DOWNGRADE_NONE) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -1186,9 +1178,8 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
* supported_versions extension for the real supported versions.
*/
if (!WPACKET_put_bytes_u16(pkt, s->client_version)
- || !WPACKET_memcpy(pkt, s->s3->client_random, SSL3_RANDOM_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ || !WPACKET_memcpy(pkt, s->s3.client_random, SSL3_RANDOM_SIZE)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -1201,10 +1192,9 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
s->tmp_session_id_len = sess_id_len;
session_id = s->tmp_session_id;
if (s->hello_retry_request == SSL_HRR_NONE
- && RAND_bytes(s->tmp_session_id, sess_id_len) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ && RAND_bytes_ex(s->ctx->libctx, s->tmp_session_id,
+ sess_id_len, 0) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
} else {
@@ -1222,8 +1212,7 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
|| (sess_id_len != 0 && !WPACKET_memcpy(pkt, session_id,
sess_id_len))
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -1232,16 +1221,14 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
if (s->d1->cookie_len > sizeof(s->d1->cookie)
|| !WPACKET_sub_memcpy_u8(pkt, s->d1->cookie,
s->d1->cookie_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
/* Ciphers supported */
if (!WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -1250,28 +1237,24 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
return 0;
}
if (!WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
/* COMPRESSION */
if (!WPACKET_start_sub_packet_u8(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
#ifndef OPENSSL_NO_COMP
if (ssl_allow_compression(s)
&& s->ctx->comp_methods
- && (SSL_IS_DTLS(s) || s->s3->tmp.max_ver < TLS1_3_VERSION)) {
+ && (SSL_IS_DTLS(s) || s->s3.tmp.max_ver < TLS1_3_VERSION)) {
int compnum = sk_SSL_COMP_num(s->ctx->comp_methods);
for (i = 0; i < compnum; i++) {
comp = sk_SSL_COMP_value(s->ctx->comp_methods, i);
if (!WPACKET_put_bytes_u8(pkt, comp->id)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
@@ -1279,8 +1262,7 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
#endif
/* Add the NULL method */
if (!WPACKET_put_bytes_u8(pkt, 0) || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -1300,21 +1282,18 @@ MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt)
if (!PACKET_forward(pkt, 2)
|| !PACKET_get_length_prefixed_1(pkt, &cookiepkt)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
cookie_len = PACKET_remaining(&cookiepkt);
if (cookie_len > sizeof(s->d1->cookie)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
- SSL_R_LENGTH_TOO_LONG);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_LENGTH_TOO_LONG);
return MSG_PROCESS_ERROR;
}
if (!PACKET_copy_bytes(&cookiepkt, s->d1->cookie, cookie_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
s->d1->cookie_len = cookie_len;
@@ -1331,8 +1310,7 @@ static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars)
c = ssl_get_cipher_by_char(s, cipherchars, 0);
if (c == NULL) {
/* unknown cipher */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
- SSL_R_UNKNOWN_CIPHER_RETURNED);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_UNKNOWN_CIPHER_RETURNED);
return 0;
}
/*
@@ -1340,8 +1318,7 @@ static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars)
* or it's not allowed for the selected protocol. So we return an error.
*/
if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK, 1)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
- SSL_R_WRONG_CIPHER_RETURNED);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_CIPHER_RETURNED);
return 0;
}
@@ -1349,16 +1326,14 @@ static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars)
i = sk_SSL_CIPHER_find(sk, c);
if (i < 0) {
/* we did not say we would use this cipher */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
- SSL_R_WRONG_CIPHER_RETURNED);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_CIPHER_RETURNED);
return 0;
}
- if (SSL_IS_TLS13(s) && s->s3->tmp.new_cipher != NULL
- && s->s3->tmp.new_cipher->id != c->id) {
+ if (SSL_IS_TLS13(s) && s->s3.tmp.new_cipher != NULL
+ && s->s3.tmp.new_cipher->id != c->id) {
/* ServerHello selected a different ciphersuite to that in the HRR */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
- SSL_R_WRONG_CIPHER_RETURNED);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_CIPHER_RETURNED);
return 0;
}
@@ -1371,14 +1346,15 @@ static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars)
s->session->cipher_id = s->session->cipher->id;
if (s->hit && (s->session->cipher_id != c->id)) {
if (SSL_IS_TLS13(s)) {
+ const EVP_MD *md = ssl_md(s->ctx, c->algorithm2);
+
/*
* In TLSv1.3 it is valid for the server to select a different
* ciphersuite as long as the hash is the same.
*/
- if (ssl_md(c->algorithm2)
- != ssl_md(s->session->cipher->algorithm2)) {
+ if (md == NULL
+ || md != ssl_md(s->ctx, s->session->cipher->algorithm2)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_SET_CLIENT_CIPHERSUITE,
SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED);
return 0;
}
@@ -1387,12 +1363,12 @@ static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars)
* Prior to TLSv1.3 resuming a session always meant using the same
* ciphersuite.
*/
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
return 0;
}
}
- s->s3->tmp.new_cipher = c;
+ s->s3.tmp.new_cipher = c;
return 1;
}
@@ -1412,8 +1388,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
#endif
if (!PACKET_get_net_2(pkt, &sversion)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
@@ -1423,48 +1398,41 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
&& PACKET_remaining(pkt) >= SSL3_RANDOM_SIZE
&& memcmp(hrrrandom, PACKET_data(pkt), SSL3_RANDOM_SIZE) == 0) {
if (s->hello_retry_request != SSL_HRR_NONE) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_UNEXPECTED_MESSAGE);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
goto err;
}
s->hello_retry_request = SSL_HRR_PENDING;
hrr = 1;
if (!PACKET_forward(pkt, SSL3_RANDOM_SIZE)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
} else {
- if (!PACKET_copy_bytes(pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_LENGTH_MISMATCH);
+ if (!PACKET_copy_bytes(pkt, s->s3.server_random, SSL3_RANDOM_SIZE)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
}
/* Get the session-id. */
if (!PACKET_get_length_prefixed_1(pkt, &session_id)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
session_id_len = PACKET_remaining(&session_id);
if (session_id_len > sizeof(s->session->session_id)
|| session_id_len > SSL3_SESSION_ID_SIZE) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_SSL3_SESSION_ID_TOO_LONG);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_SSL3_SESSION_ID_TOO_LONG);
goto err;
}
if (!PACKET_get_bytes(pkt, &cipherchars, TLS_CIPHER_LEN)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
if (!PACKET_get_1(pkt, &compression)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
@@ -1473,8 +1441,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
PACKET_null_init(&extpkt);
} else if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
|| PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_BAD_LENGTH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_LENGTH);
goto err;
}
@@ -1496,7 +1463,6 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
if (SSL_IS_TLS13(s) || hrr) {
if (compression != 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_INVALID_COMPRESSION_ALGORITHM);
goto err;
}
@@ -1504,8 +1470,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
if (session_id_len != s->tmp_session_id_len
|| memcmp(PACKET_data(&session_id), s->tmp_session_id,
session_id_len) != 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_INVALID_SESSION_ID);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_INVALID_SESSION_ID);
goto err;
}
}
@@ -1526,8 +1491,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
context = SSL_IS_TLS13(s) ? SSL_EXT_TLS1_3_SERVER_HELLO
: SSL_EXT_TLS1_2_SERVER_HELLO;
if (!tls_validate_all_contexts(s, context, extensions)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_BAD_EXTENSION);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_EXTENSION);
goto err;
}
@@ -1540,7 +1504,6 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
*/
if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_NOT_ON_RECORD_BOUNDARY);
goto err;
}
@@ -1583,8 +1546,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
s->session->cipher = pref_cipher ?
pref_cipher : ssl_get_cipher_by_char(s, cipherchars, 0);
} else {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
}
@@ -1601,7 +1563,6 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
|| memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) {
/* actually a client application bug */
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
goto err;
}
@@ -1614,7 +1575,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
* overwritten if the server refuses resumption.
*/
if (s->session->session_id_length > 0) {
- tsan_counter(&s->session_ctx->stats.sess_miss);
+ ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_miss);
if (!ssl_get_new_session(s, 0)) {
/* SSLfatal() already called */
goto err;
@@ -1639,7 +1600,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
/* Session version and negotiated protocol version should match */
if (s->version != s->session->ssl_version) {
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
SSL_R_SSL_SESSION_VERSION_MISMATCH);
goto err;
}
@@ -1647,8 +1608,8 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
* Now that we know the version, update the check to see if it's an allowed
* version.
*/
- s->s3->tmp.min_ver = s->version;
- s->s3->tmp.max_ver = s->version;
+ s->s3.tmp.min_ver = s->version;
+ s->s3.tmp.max_ver = s->version;
if (!set_client_ciphersuite(s, cipherchars)) {
/* SSLfatal() already called */
@@ -1657,7 +1618,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
#ifdef OPENSSL_NO_COMP
if (compression != 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
goto err;
}
@@ -1666,32 +1627,30 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
* using compression.
*/
if (s->session->compress_meth != 0) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_INCONSISTENT_COMPRESSION);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_INCONSISTENT_COMPRESSION);
goto err;
}
#else
if (s->hit && compression != s->session->compress_meth) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
goto err;
}
if (compression == 0)
comp = NULL;
else if (!ssl_allow_compression(s)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_COMPRESSION_DISABLED);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_COMPRESSION_DISABLED);
goto err;
} else {
comp = ssl3_comp_find(s->ctx->comp_methods, compression);
}
if (compression != 0 && comp == NULL) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
goto err;
} else {
- s->s3->tmp.new_compression = comp;
+ s->s3.tmp.new_compression = comp;
}
#endif
@@ -1722,8 +1681,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
sizeof(sctpauthkey),
labelbuffer,
labellen, NULL, 0, 0) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -1775,18 +1733,12 @@ static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s,
OPENSSL_free(extensions);
extensions = NULL;
- if (s->ext.tls13_cookie_len == 0
-#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
- && s->s3->tmp.pkey != NULL
-#endif
- ) {
+ if (s->ext.tls13_cookie_len == 0 && s->s3.tmp.pkey != NULL) {
/*
* We didn't receive a cookie or a new key_share so the next
* ClientHello will not change
*/
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST,
- SSL_R_NO_CHANGE_FOLLOWING_HRR);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_NO_CHANGE_FOLLOWING_HRR);
goto err;
}
@@ -1817,22 +1769,17 @@ static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s,
return MSG_PROCESS_ERROR;
}
+/* prepare server cert verification by setting s->session->peer_chain from pkt */
MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
{
- int i;
- MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
unsigned long cert_list_len, cert_len;
X509 *x = NULL;
const unsigned char *certstart, *certbytes;
- STACK_OF(X509) *sk = NULL;
- EVP_PKEY *pkey = NULL;
- size_t chainidx, certidx;
+ size_t chainidx;
unsigned int context = 0;
- const SSL_CERT_LOOKUP *clu;
- if ((sk = sk_X509_new_null()) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- ERR_R_MALLOC_FAILURE);
+ if ((s->session->peer_chain = sk_X509_new_null()) == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -1841,30 +1788,31 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
|| !PACKET_get_net_3(pkt, &cert_list_len)
|| PACKET_remaining(pkt) != cert_list_len
|| PACKET_remaining(pkt) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
for (chainidx = 0; PACKET_remaining(pkt); chainidx++) {
if (!PACKET_get_net_3(pkt, &cert_len)
|| !PACKET_get_bytes(pkt, &certbytes, cert_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- SSL_R_CERT_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_CERT_LENGTH_MISMATCH);
goto err;
}
certstart = certbytes;
- x = d2i_X509(NULL, (const unsigned char **)&certbytes, cert_len);
+ x = X509_new_ex(s->ctx->libctx, s->ctx->propq);
if (x == NULL) {
- SSLfatal(s, SSL_AD_BAD_CERTIFICATE,
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_ASN1_LIB);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
+ if (d2i_X509(&x, (const unsigned char **)&certbytes,
+ cert_len) == NULL) {
+ SSLfatal(s, SSL_AD_BAD_CERTIFICATE, ERR_R_ASN1_LIB);
+ goto err;
+ }
+
if (certbytes != (certstart + cert_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- SSL_R_CERT_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_CERT_LENGTH_MISMATCH);
goto err;
}
@@ -1873,9 +1821,7 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
PACKET extensions;
if (!PACKET_get_length_prefixed_2(pkt, &extensions)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- SSL_R_BAD_LENGTH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_LENGTH);
goto err;
}
if (!tls_collect_extensions(s, &extensions,
@@ -1891,16 +1837,40 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
OPENSSL_free(rawexts);
}
- if (!sk_X509_push(sk, x)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- ERR_R_MALLOC_FAILURE);
+ if (!sk_X509_push(s->session->peer_chain, x)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
x = NULL;
}
+ return MSG_PROCESS_CONTINUE_PROCESSING;
+
+ err:
+ X509_free(x);
+ sk_X509_pop_free(s->session->peer_chain, X509_free);
+ s->session->peer_chain = NULL;
+ return MSG_PROCESS_ERROR;
+}
+
+/*
+ * Verify the s->session->peer_chain and check server cert type.
+ * On success set s->session->peer and s->session->verify_result.
+ * Else the peer certificate verification callback may request retry.
+ */
+WORK_STATE tls_post_process_server_certificate(SSL *s, WORK_STATE wst)
+{
+ X509 *x;
+ EVP_PKEY *pkey = NULL;
+ const SSL_CERT_LOOKUP *clu;
+ size_t certidx;
+ int i;
- i = ssl_verify_cert_chain(s, sk);
+ if (s->rwstate == SSL_RETRY_VERIFY)
+ s->rwstate = SSL_NOTHING;
+ i = ssl_verify_cert_chain(s, s->session->peer_chain);
+ if (i > 0 && s->rwstate == SSL_RETRY_VERIFY) {
+ return WORK_MORE_A;
+ }
/*
* The documented interface is that SSL_VERIFY_PEER should be set in order
* for client side verification of the server certificate to take place.
@@ -1917,40 +1887,28 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
*/
if (s->verify_mode != SSL_VERIFY_NONE && i <= 0) {
SSLfatal(s, ssl_x509err2alert(s->verify_result),
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
SSL_R_CERTIFICATE_VERIFY_FAILED);
- goto err;
+ return WORK_ERROR;
}
ERR_clear_error(); /* but we keep s->verify_result */
- if (i > 1) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, i);
- goto err;
- }
- s->session->peer_chain = sk;
/*
* Inconsistency alert: cert_chain does include the peer's certificate,
* which we don't include in statem_srvr.c
*/
- x = sk_X509_value(sk, 0);
- sk = NULL;
+ x = sk_X509_value(s->session->peer_chain, 0);
pkey = X509_get0_pubkey(x);
if (pkey == NULL || EVP_PKEY_missing_parameters(pkey)) {
- x = NULL;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
- goto err;
+ return WORK_ERROR;
}
if ((clu = ssl_cert_lookup_by_pkey(pkey, &certidx)) == NULL) {
- x = NULL;
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- SSL_R_UNKNOWN_CERTIFICATE_TYPE);
- goto err;
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ return WORK_ERROR;
}
/*
* Check certificate type is consistent with ciphersuite. For TLS 1.3
@@ -1958,12 +1916,9 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
* type.
*/
if (!SSL_IS_TLS13(s)) {
- if ((clu->amask & s->s3->tmp.new_cipher->algorithm_auth) == 0) {
- x = NULL;
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- SSL_R_WRONG_CERTIFICATE_TYPE);
- goto err;
+ if ((clu->amask & s->s3.tmp.new_cipher->algorithm_auth) == 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_CERTIFICATE_TYPE);
+ return WORK_ERROR;
}
}
@@ -1971,7 +1926,6 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
X509_up_ref(x);
s->session->peer = x;
s->session->verify_result = s->verify_result;
- x = NULL;
/* Save the current hash state for when we receive the CertificateVerify */
if (SSL_IS_TLS13(s)
@@ -1979,15 +1933,9 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
sizeof(s->cert_verify_hash),
&s->cert_verify_hash_len)) {
/* SSLfatal() already called */;
- goto err;
+ return WORK_ERROR;
}
-
- ret = MSG_PROCESS_CONTINUE_READING;
-
- err:
- X509_free(x);
- sk_X509_pop_free(sk, X509_free);
- return ret;
+ return WORK_FINISHED_CONTINUE;
}
static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt)
@@ -1998,8 +1946,7 @@ static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt)
/* PSK ciphersuites are preceded by an identity hint */
if (!PACKET_get_length_prefixed_2(pkt, &psk_identity_hint)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
@@ -2010,9 +1957,7 @@ static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt)
* identity.
*/
if (PACKET_remaining(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
- SSL_R_DATA_LENGTH_TOO_LONG);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_DATA_LENGTH_TOO_LONG);
return 0;
}
@@ -2021,15 +1966,13 @@ static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt)
s->session->psk_identity_hint = NULL;
} else if (!PACKET_strndup(&psk_identity_hint,
&s->session->psk_identity_hint)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
@@ -2043,12 +1986,10 @@ static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
|| !PACKET_get_length_prefixed_2(pkt, &generator)
|| !PACKET_get_length_prefixed_1(pkt, &salt)
|| !PACKET_get_length_prefixed_2(pkt, &server_pub)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
- /* TODO(size_t): Convert BN_bin2bn() calls */
if ((s->srp_ctx.N =
BN_bin2bn(PACKET_data(&prime),
(int)PACKET_remaining(&prime), NULL)) == NULL
@@ -2061,8 +2002,7 @@ static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
|| (s->srp_ctx.B =
BN_bin2bn(PACKET_data(&server_pub),
(int)PACKET_remaining(&server_pub), NULL)) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
- ERR_R_BN_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_BN_LIB);
return 0;
}
@@ -2072,128 +2012,114 @@ static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
}
/* We must check if there is a certificate */
- if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
+ if (s->s3.tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
*pkey = X509_get0_pubkey(s->session->peer);
return 1;
#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
{
-#ifndef OPENSSL_NO_DH
PACKET prime, generator, pub_key;
EVP_PKEY *peer_tmp = NULL;
-
- DH *dh = NULL;
BIGNUM *p = NULL, *g = NULL, *bnpub_key = NULL;
-
- int check_bits = 0;
+ EVP_PKEY_CTX *pctx = NULL;
+ OSSL_PARAM *params = NULL;
+ OSSL_PARAM_BLD *tmpl = NULL;
+ int ret = 0;
if (!PACKET_get_length_prefixed_2(pkt, &prime)
|| !PACKET_get_length_prefixed_2(pkt, &generator)
|| !PACKET_get_length_prefixed_2(pkt, &pub_key)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
- peer_tmp = EVP_PKEY_new();
- dh = DH_new();
-
- if (peer_tmp == NULL || dh == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /* TODO(size_t): Convert these calls */
p = BN_bin2bn(PACKET_data(&prime), (int)PACKET_remaining(&prime), NULL);
g = BN_bin2bn(PACKET_data(&generator), (int)PACKET_remaining(&generator),
NULL);
bnpub_key = BN_bin2bn(PACKET_data(&pub_key),
(int)PACKET_remaining(&pub_key), NULL);
if (p == NULL || g == NULL || bnpub_key == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
- ERR_R_BN_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_BN_LIB);
goto err;
}
- /* test non-zero pubkey */
- if (BN_is_zero(bnpub_key)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_DHE,
- SSL_R_BAD_DH_VALUE);
+ tmpl = OSSL_PARAM_BLD_new();
+ if (tmpl == NULL
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, p)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, g)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
+ bnpub_key)
+ || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- if (!DH_set0_pqg(dh, p, NULL, g)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
- ERR_R_BN_LIB);
+ pctx = EVP_PKEY_CTX_new_from_name(s->ctx->libctx, "DH", s->ctx->propq);
+ if (pctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- p = g = NULL;
-
- if (DH_check_params(dh, &check_bits) == 0 || check_bits != 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_DHE,
- SSL_R_BAD_DH_VALUE);
+ if (EVP_PKEY_fromdata_init(pctx) <= 0
+ || EVP_PKEY_fromdata(pctx, &peer_tmp, EVP_PKEY_KEYPAIR, params) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_DH_VALUE);
goto err;
}
- if (!DH_set0_key(dh, bnpub_key, NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
- ERR_R_BN_LIB);
- goto err;
- }
- bnpub_key = NULL;
-
- if (EVP_PKEY_assign_DH(peer_tmp, dh) == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
- ERR_R_EVP_LIB);
+ EVP_PKEY_CTX_free(pctx);
+ pctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, peer_tmp, s->ctx->propq);
+ if (pctx == NULL
+ /*
+ * EVP_PKEY_param_check() will verify that the DH params are using
+ * a safe prime. In this context, because we're using ephemeral DH,
+ * we're ok with it not being a safe prime.
+ * EVP_PKEY_param_check_quick() skips the safe prime check.
+ */
+ || EVP_PKEY_param_check_quick(pctx) != 1
+ || EVP_PKEY_public_check(pctx) != 1) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_DH_VALUE);
goto err;
}
- dh = NULL;
- if (!ssl_security(s, SSL_SECOP_TMP_DH, EVP_PKEY_security_bits(peer_tmp),
+ if (!ssl_security(s, SSL_SECOP_TMP_DH,
+ EVP_PKEY_get_security_bits(peer_tmp),
0, peer_tmp)) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_SKE_DHE,
- SSL_R_DH_KEY_TOO_SMALL);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_DH_KEY_TOO_SMALL);
goto err;
}
- s->s3->peer_tmp = peer_tmp;
+ s->s3.peer_tmp = peer_tmp;
+ peer_tmp = NULL;
/*
* FIXME: This makes assumptions about which ciphersuites come with
* public keys. We should have a less ad-hoc way of doing this
*/
- if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
+ if (s->s3.tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
*pkey = X509_get0_pubkey(s->session->peer);
/* else anonymous DH, so no certificate or pkey. */
- return 1;
+ ret = 1;
err:
+ OSSL_PARAM_BLD_free(tmpl);
+ OSSL_PARAM_free(params);
+ EVP_PKEY_free(peer_tmp);
+ EVP_PKEY_CTX_free(pctx);
BN_free(p);
BN_free(g);
BN_free(bnpub_key);
- DH_free(dh);
- EVP_PKEY_free(peer_tmp);
- return 0;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
+ return ret;
}
static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
{
-#ifndef OPENSSL_NO_EC
PACKET encoded_pt;
unsigned int curve_type, curve_id;
@@ -2203,8 +2129,7 @@ static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
* ECParameters in this case is just three bytes.
*/
if (!PACKET_get_1(pkt, &curve_type) || !PACKET_get_net_2(pkt, &curve_id)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
- SSL_R_LENGTH_TOO_SHORT);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
return 0;
}
/*
@@ -2213,28 +2138,25 @@ static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
*/
if (curve_type != NAMED_CURVE_TYPE
|| !tls1_check_group_id(s, curve_id, 1)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_ECDHE,
- SSL_R_WRONG_CURVE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_CURVE);
return 0;
}
- if ((s->s3->peer_tmp = ssl_generate_param_group(curve_id)) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
+ if ((s->s3.peer_tmp = ssl_generate_param_group(s, curve_id)) == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
return 0;
}
if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
- if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
- PACKET_data(&encoded_pt),
- PACKET_remaining(&encoded_pt))) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_ECDHE,
- SSL_R_BAD_ECPOINT);
+ if (EVP_PKEY_set1_encoded_public_key(s->s3.peer_tmp,
+ PACKET_data(&encoded_pt),
+ PACKET_remaining(&encoded_pt)) <= 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_ECPOINT);
return 0;
}
@@ -2243,18 +2165,15 @@ static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
* ECParameters in the server key exchange message. We do support RSA
* and ECDSA.
*/
- if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aECDSA)
+ if (s->s3.tmp.new_cipher->algorithm_auth & SSL_aECDSA)
*pkey = X509_get0_pubkey(s->session->peer);
- else if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aRSA)
+ else if (s->s3.tmp.new_cipher->algorithm_auth & SSL_aRSA)
*pkey = X509_get0_pubkey(s->session->peer);
/* else anonymous ECDH, so no certificate or pkey. */
+ /* Cache the agreed upon group in the SSL_SESSION */
+ s->session->kex_group = curve_id;
return 1;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
}
MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
@@ -2265,14 +2184,12 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
EVP_PKEY_CTX *pctx = NULL;
PACKET save_param_start, signature;
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
save_param_start = *pkt;
-#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
- EVP_PKEY_free(s->s3->peer_tmp);
- s->s3->peer_tmp = NULL;
-#endif
+ EVP_PKEY_free(s->s3.peer_tmp);
+ s->s3.peer_tmp = NULL;
if (alg_k & SSL_PSK) {
if (!tls_process_ske_psk_preamble(s, pkt)) {
@@ -2299,15 +2216,13 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
goto err;
}
} else if (alg_k) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- SSL_R_UNEXPECTED_MESSAGE);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
goto err;
}
/* if it was signed, check the signature */
if (pkey != NULL) {
PACKET params;
- int maxsig;
const EVP_MD *md = NULL;
unsigned char *tbs;
size_t tbslen;
@@ -2320,8 +2235,7 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
if (!PACKET_get_sub_packet(&save_param_start, &params,
PACKET_remaining(&save_param_start) -
PACKET_remaining(pkt))) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -2329,8 +2243,7 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
unsigned int sigalg;
if (!PACKET_get_net_2(pkt, &sigalg)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- SSL_R_LENGTH_TOO_SHORT);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
goto err;
}
if (tls12_check_peer_sigalg(s, sigalg, pkey) <=0) {
@@ -2338,63 +2251,44 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
goto err;
}
} else if (!tls1_set_peer_legacy_sigalg(s, pkey)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_R_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED);
goto err;
}
- if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ if (!tls1_lookup_md(s->ctx, s->s3.tmp.peer_sigalg, &md)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_R_NO_SUITABLE_DIGEST_ALGORITHM);
goto err;
}
-#ifdef SSL_DEBUG
if (SSL_USE_SIGALGS(s))
- fprintf(stderr, "USING TLSv1.2 HASH %s\n",
- md == NULL ? "n/a" : EVP_MD_name(md));
-#endif
+ OSSL_TRACE1(TLS, "USING TLSv1.2 HASH %s\n",
+ md == NULL ? "n/a" : EVP_MD_get0_name(md));
if (!PACKET_get_length_prefixed_2(pkt, &signature)
|| PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
- maxsig = EVP_PKEY_size(pkey);
- if (maxsig < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /*
- * Check signature length
- */
- if (PACKET_remaining(&signature) > (size_t)maxsig) {
- /* wrong packet length */
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- SSL_R_WRONG_SIGNATURE_LENGTH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
md_ctx = EVP_MD_CTX_new();
if (md_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (EVP_DigestVerifyInit(md_ctx, &pctx, md, NULL, pkey) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- ERR_R_EVP_LIB);
+ if (EVP_DigestVerifyInit_ex(md_ctx, &pctx,
+ md == NULL ? NULL : EVP_MD_get0_name(md),
+ s->ctx->libctx, s->ctx->propq, pkey,
+ NULL) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
if (SSL_USE_PSS(s)) {
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
|| EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
RSA_PSS_SALTLEN_DIGEST) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
}
@@ -2409,28 +2303,25 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
PACKET_remaining(&signature), tbs, tbslen);
OPENSSL_free(tbs);
if (rv <= 0) {
- SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- SSL_R_BAD_SIGNATURE);
+ SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_R_BAD_SIGNATURE);
goto err;
}
EVP_MD_CTX_free(md_ctx);
md_ctx = NULL;
} else {
/* aNULL, aSRP or PSK do not need public keys */
- if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
+ if (!(s->s3.tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
&& !(alg_k & SSL_PSK)) {
/* Might be wrong key type, check it */
if (ssl3_check_cert_and_algorithm(s)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- SSL_R_BAD_DATA);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_DATA);
}
/* else this shouldn't happen, SSLfatal() already called */
goto err;
}
/* still data left over */
if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- SSL_R_EXTRA_DATA_IN_MESSAGE);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_EXTRA_DATA_IN_MESSAGE);
goto err;
}
}
@@ -2447,7 +2338,7 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
/* Clear certificate validity flags */
for (i = 0; i < SSL_PKEY_NUM; i++)
- s->s3->tmp.valid_flags[i] = 0;
+ s->s3.tmp.valid_flags[i] = 0;
if (SSL_IS_TLS13(s)) {
PACKET reqctx, extensions;
@@ -2463,25 +2354,21 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
}
/* Free and zero certificate types: it is not present in TLS 1.3 */
- OPENSSL_free(s->s3->tmp.ctype);
- s->s3->tmp.ctype = NULL;
- s->s3->tmp.ctype_len = 0;
+ OPENSSL_free(s->s3.tmp.ctype);
+ s->s3.tmp.ctype = NULL;
+ s->s3.tmp.ctype_len = 0;
OPENSSL_free(s->pha_context);
s->pha_context = NULL;
s->pha_context_len = 0;
if (!PACKET_get_length_prefixed_1(pkt, &reqctx) ||
!PACKET_memdup(&reqctx, &s->pha_context, &s->pha_context_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
if (!PACKET_get_length_prefixed_2(pkt, &extensions)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- SSL_R_BAD_LENGTH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_LENGTH);
return MSG_PROCESS_ERROR;
}
if (!tls_collect_extensions(s, &extensions,
@@ -2495,9 +2382,7 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
}
OPENSSL_free(rawexts);
if (!tls1_process_sigalgs(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- SSL_R_BAD_LENGTH);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_LENGTH);
return MSG_PROCESS_ERROR;
}
} else {
@@ -2505,16 +2390,12 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
/* get the certificate types */
if (!PACKET_get_length_prefixed_1(pkt, &ctypes)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
- if (!PACKET_memdup(&ctypes, &s->s3->tmp.ctype, &s->s3->tmp.ctype_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- ERR_R_INTERNAL_ERROR);
+ if (!PACKET_memdup(&ctypes, &s->s3.tmp.ctype, &s->s3.tmp.ctype_len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
}
@@ -2522,9 +2403,7 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
PACKET sigalgs;
if (!PACKET_get_length_prefixed_2(pkt, &sigalgs)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
@@ -2534,14 +2413,11 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
*/
if (!tls1_save_sigalgs(s, &sigalgs, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
SSL_R_SIGNATURE_ALGORITHMS_ERROR);
return MSG_PROCESS_ERROR;
}
if (!tls1_process_sigalgs(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return MSG_PROCESS_ERROR;
}
}
@@ -2554,21 +2430,19 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
}
if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
/* we should setup a certificate to return.... */
- s->s3->tmp.cert_req = 1;
+ s->s3.tmp.cert_req = 1;
/*
* In TLSv1.3 we don't prepare the client certificate yet. We wait until
* after the CertificateVerify message has been received. This is because
* in TLSv1.3 the CertificateRequest arrives before the Certificate message
* but in TLSv1.2 it is the other way around. We want to make sure that
- * SSL_get_peer_certificate() returns something sensible in
+ * SSL_get1_peer_certificate() returns something sensible in
* client_cert_cb.
*/
if (SSL_IS_TLS13(s) && s->post_handshake_auth != SSL_PHA_REQUESTED)
@@ -2584,6 +2458,7 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
unsigned int sess_len;
RAW_EXTENSION *exts = NULL;
PACKET nonce;
+ EVP_MD *sha256 = NULL;
PACKET_null_init(&nonce);
@@ -2594,8 +2469,7 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
|| !PACKET_get_net_2(pkt, &ticklen)
|| (SSL_IS_TLS13(s) ? (ticklen == 0 || PACKET_remaining(pkt) < ticklen)
: PACKET_remaining(pkt) != ticklen)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
@@ -2623,9 +2497,7 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
* one
*/
if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -2643,11 +2515,8 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
s->session = new_sess;
}
- /*
- * Technically the cast to long here is not guaranteed by the C standard -
- * but we use it elsewhere, so this should be ok.
- */
- s->session->time = (long)time(NULL);
+ s->session->time = time(NULL);
+ ssl_session_calculate_timeout(s->session);
OPENSSL_free(s->session->ext.tick);
s->session->ext.tick = NULL;
@@ -2655,13 +2524,11 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
s->session->ext.tick = OPENSSL_malloc(ticklen);
if (s->session->ext.tick == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!PACKET_copy_bytes(pkt, s->session->ext.tick, ticklen)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
@@ -2674,9 +2541,7 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
|| PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
@@ -2699,35 +2564,40 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
* other way is to set zero length session ID when the ticket is
* presented and rely on the handshake to determine session resumption.
* We choose the former approach because this fits in with assumptions
- * elsewhere in OpenSSL. The session ID is set to the SHA256 (or SHA1 is
- * SHA256 is disabled) hash of the ticket.
+ * elsewhere in OpenSSL. The session ID is set to the SHA256 hash of the
+ * ticket.
*/
+ sha256 = EVP_MD_fetch(s->ctx->libctx, "SHA2-256", s->ctx->propq);
+ if (sha256 == NULL) {
+ /* Error is already recorded */
+ SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
+ goto err;
+ }
/*
- * TODO(size_t): we use sess_len here because EVP_Digest expects an int
+ * We use sess_len here because EVP_Digest expects an int
* but s->session->session_id_length is a size_t
*/
if (!EVP_Digest(s->session->ext.tick, ticklen,
s->session->session_id, &sess_len,
- EVP_sha256(), NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
- ERR_R_EVP_LIB);
+ sha256, NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
+ EVP_MD_free(sha256);
+ sha256 = NULL;
s->session->session_id_length = sess_len;
s->session->not_resumable = 0;
/* This is a standalone message in TLSv1.3, so there is no more to read */
if (SSL_IS_TLS13(s)) {
const EVP_MD *md = ssl_handshake_md(s);
- int hashleni = EVP_MD_size(md);
+ int hashleni = EVP_MD_get_size(md);
size_t hashlen;
static const unsigned char nonce_label[] = "resumption";
/* Ensure cast to size_t is safe */
if (!ossl_assert(hashleni >= 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
hashlen = (size_t)hashleni;
@@ -2751,6 +2621,7 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
return MSG_PROCESS_CONTINUE_READING;
err:
+ EVP_MD_free(sha256);
OPENSSL_free(exts);
return MSG_PROCESS_ERROR;
}
@@ -2766,27 +2637,23 @@ int tls_process_cert_status_body(SSL *s, PACKET *pkt)
if (!PACKET_get_1(pkt, &type)
|| type != TLSEXT_STATUSTYPE_ocsp) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
- SSL_R_UNSUPPORTED_STATUS_TYPE);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_UNSUPPORTED_STATUS_TYPE);
return 0;
}
if (!PACKET_get_net_3_len(pkt, &resplen)
|| PACKET_remaining(pkt) != resplen) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
s->ext.ocsp.resp = OPENSSL_malloc(resplen);
if (s->ext.ocsp.resp == NULL) {
s->ext.ocsp.resp_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
s->ext.ocsp.resp_len = resplen;
if (!PACKET_copy_bytes(pkt, s->ext.ocsp.resp, resplen)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
@@ -2832,13 +2699,11 @@ int tls_process_initial_server_flight(SSL *s)
if (ret == 0) {
SSLfatal(s, SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE,
- SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT,
SSL_R_INVALID_STATUS_RESPONSE);
return 0;
}
if (ret < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT,
SSL_R_OCSP_CALLBACK_FAILURE);
return 0;
}
@@ -2860,15 +2725,13 @@ MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt)
{
if (PACKET_remaining(pkt) > 0) {
/* should contain no data */
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_DONE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
#ifndef OPENSSL_NO_SRP
- if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
- if (SRP_Calc_A_param(s) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_DONE,
- SSL_R_SRP_A_CALC);
+ if (s->s3.tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
+ if (ssl_srp_calc_a_param_intern(s) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_SRP_A_CALC);
return MSG_PROCESS_ERROR;
}
}
@@ -2899,8 +2762,7 @@ static int tls_construct_cke_psk_preamble(SSL *s, WPACKET *pkt)
size_t psklen = 0;
if (s->psk_client_callback == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
- SSL_R_PSK_NO_CLIENT_CB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_PSK_NO_CLIENT_CB);
goto err;
}
@@ -2911,43 +2773,37 @@ static int tls_construct_cke_psk_preamble(SSL *s, WPACKET *pkt)
psk, sizeof(psk));
if (psklen > PSK_MAX_PSK_LEN) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, ERR_R_INTERNAL_ERROR);
psklen = PSK_MAX_PSK_LEN; /* Avoid overrunning the array on cleanse */
goto err;
} else if (psklen == 0) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
- SSL_R_PSK_IDENTITY_NOT_FOUND);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_PSK_IDENTITY_NOT_FOUND);
goto err;
}
identitylen = strlen(identity);
if (identitylen > PSK_MAX_IDENTITY_LEN) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
tmppsk = OPENSSL_memdup(psk, psklen);
tmpidentity = OPENSSL_strdup(identity);
if (tmppsk == NULL || tmpidentity == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
- OPENSSL_free(s->s3->tmp.psk);
- s->s3->tmp.psk = tmppsk;
- s->s3->tmp.psklen = psklen;
+ OPENSSL_free(s->s3.tmp.psk);
+ s->s3.tmp.psk = tmppsk;
+ s->s3.tmp.psklen = psklen;
tmppsk = NULL;
OPENSSL_free(s->session->psk_identity);
s->session->psk_identity = tmpidentity;
tmpidentity = NULL;
if (!WPACKET_sub_memcpy_u16(pkt, identity, identitylen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -2961,15 +2817,13 @@ static int tls_construct_cke_psk_preamble(SSL *s, WPACKET *pkt)
return ret;
#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt)
{
-#ifndef OPENSSL_NO_RSA
unsigned char *encdata = NULL;
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *pctx = NULL;
@@ -2981,52 +2835,45 @@ static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt)
/*
* We should always have a server certificate with SSL_kRSA.
*/
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
pkey = X509_get0_pubkey(s->session->peer);
- if (EVP_PKEY_get0_RSA(pkey) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- ERR_R_INTERNAL_ERROR);
+ if (!EVP_PKEY_is_a(pkey, "RSA")) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
pmslen = SSL_MAX_MASTER_KEY_LENGTH;
pms = OPENSSL_malloc(pmslen);
if (pms == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
pms[0] = s->client_version >> 8;
pms[1] = s->client_version & 0xff;
- /* TODO(size_t): Convert this function */
- if (RAND_bytes(pms + 2, (int)(pmslen - 2)) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- ERR_R_MALLOC_FAILURE);
+ if (RAND_bytes_ex(s->ctx->libctx, pms + 2, pmslen - 2, 0) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
/* Fix buf for TLS and beyond */
if (s->version > SSL3_VERSION && !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- pctx = EVP_PKEY_CTX_new(pkey, NULL);
+
+ pctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, pkey, s->ctx->propq);
if (pctx == NULL || EVP_PKEY_encrypt_init(pctx) <= 0
|| EVP_PKEY_encrypt(pctx, NULL, &enclen, pms, pmslen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- ERR_R_EVP_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
if (!WPACKET_allocate_bytes(pkt, enclen, &encdata)
|| EVP_PKEY_encrypt(pctx, encdata, &enclen, pms, pmslen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- SSL_R_BAD_RSA_ENCRYPT);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_RSA_ENCRYPT);
goto err;
}
EVP_PKEY_CTX_free(pctx);
@@ -3034,8 +2881,7 @@ static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt)
/* Fix buf for TLS and beyond */
if (s->version > SSL3_VERSION && !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -3045,8 +2891,8 @@ static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt)
goto err;
}
- s->s3->tmp.pms = pms;
- s->s3->tmp.pmslen = pmslen;
+ s->s3.tmp.pms = pms;
+ s->s3.tmp.pmslen = pmslen;
return 1;
err:
@@ -3054,40 +2900,26 @@ static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt)
EVP_PKEY_CTX_free(pctx);
return 0;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
}
static int tls_construct_cke_dhe(SSL *s, WPACKET *pkt)
{
-#ifndef OPENSSL_NO_DH
- DH *dh_clnt = NULL;
- const BIGNUM *pub_key;
EVP_PKEY *ckey = NULL, *skey = NULL;
unsigned char *keybytes = NULL;
+ int prime_len;
+ unsigned char *encoded_pub = NULL;
+ size_t encoded_pub_len, pad_len;
+ int ret = 0;
- skey = s->s3->peer_tmp;
+ skey = s->s3.peer_tmp;
if (skey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- ckey = ssl_generate_pkey(skey);
+ ckey = ssl_generate_pkey(s, skey);
if (ckey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- dh_clnt = EVP_PKEY_get0_DH(ckey);
-
- if (dh_clnt == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -3097,47 +2929,58 @@ static int tls_construct_cke_dhe(SSL *s, WPACKET *pkt)
}
/* send off the data */
- DH_get0_key(dh_clnt, &pub_key, NULL);
- if (!WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(pub_key),
- &keybytes)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
- ERR_R_INTERNAL_ERROR);
- goto err;
+
+ /* Generate encoding of server key */
+ encoded_pub_len = EVP_PKEY_get1_encoded_public_key(ckey, &encoded_pub);
+ if (encoded_pub_len == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ EVP_PKEY_free(ckey);
+ return EXT_RETURN_FAIL;
}
- BN_bn2bin(pub_key, keybytes);
- EVP_PKEY_free(ckey);
+ /*
+ * For interoperability with some versions of the Microsoft TLS
+ * stack, we need to zero pad the DHE pub key to the same length
+ * as the prime.
+ */
+ prime_len = EVP_PKEY_get_size(ckey);
+ pad_len = prime_len - encoded_pub_len;
+ if (pad_len > 0) {
+ if (!WPACKET_sub_allocate_bytes_u16(pkt, pad_len, &keybytes)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ memset(keybytes, 0, pad_len);
+ }
- return 1;
+ if (!WPACKET_sub_memcpy_u16(pkt, encoded_pub, encoded_pub_len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ ret = 1;
err:
+ OPENSSL_free(encoded_pub);
EVP_PKEY_free(ckey);
- return 0;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
+ return ret;
}
static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt)
{
-#ifndef OPENSSL_NO_EC
unsigned char *encodedPoint = NULL;
size_t encoded_pt_len = 0;
EVP_PKEY *ckey = NULL, *skey = NULL;
int ret = 0;
- skey = s->s3->peer_tmp;
+ skey = s->s3.peer_tmp;
if (skey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
- ckey = ssl_generate_pkey(skey);
+ ckey = ssl_generate_pkey(s, skey);
if (ckey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -3147,17 +2990,15 @@ static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt)
}
/* Generate encoding of client key */
- encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(ckey, &encodedPoint);
+ encoded_pt_len = EVP_PKEY_get1_encoded_public_key(ckey, &encodedPoint);
if (encoded_pt_len == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
- ERR_R_EC_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EC_LIB);
goto err;
}
if (!WPACKET_sub_memcpy_u8(pkt, encodedPoint, encoded_pt_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -3166,11 +3007,6 @@ static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt)
OPENSSL_free(encodedPoint);
EVP_PKEY_free(ckey);
return ret;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
}
static int tls_construct_cke_gost(SSL *s, WPACKET *pkt)
@@ -3187,23 +3023,24 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt)
unsigned char *pms = NULL;
size_t pmslen = 0;
- if ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aGOST12) != 0)
+ if ((s->s3.tmp.new_cipher->algorithm_auth & SSL_aGOST12) != 0)
dgst_nid = NID_id_GostR3411_2012_256;
/*
* Get server certificate PKEY and create ctx from it
*/
peer_cert = s->session->peer;
- if (!peer_cert) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
+ if (peer_cert == NULL) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
return 0;
}
- pkey_ctx = EVP_PKEY_CTX_new(X509_get0_pubkey(peer_cert), NULL);
+ pkey_ctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx,
+ X509_get0_pubkey(peer_cert),
+ s->ctx->propq);
if (pkey_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
/*
@@ -3216,18 +3053,15 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt)
pmslen = 32;
pms = OPENSSL_malloc(pmslen);
if (pms == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0
/* Generate session key
- * TODO(size_t): Convert this function
*/
- || RAND_bytes(pms, (int)pmslen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- ERR_R_INTERNAL_ERROR);
+ || RAND_bytes_ex(s->ctx->libctx, pms, pmslen, 0) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
};
/*
@@ -3237,21 +3071,19 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt)
ukm_hash = EVP_MD_CTX_new();
if (ukm_hash == NULL
|| EVP_DigestInit(ukm_hash, EVP_get_digestbynid(dgst_nid)) <= 0
- || EVP_DigestUpdate(ukm_hash, s->s3->client_random,
+ || EVP_DigestUpdate(ukm_hash, s->s3.client_random,
SSL3_RANDOM_SIZE) <= 0
- || EVP_DigestUpdate(ukm_hash, s->s3->server_random,
+ || EVP_DigestUpdate(ukm_hash, s->s3.server_random,
SSL3_RANDOM_SIZE) <= 0
|| EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
EVP_MD_CTX_free(ukm_hash);
ukm_hash = NULL;
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
- EVP_PKEY_CTRL_SET_IV, 8, shared_ukm) < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- SSL_R_LIBRARY_BUG);
+ EVP_PKEY_CTRL_SET_IV, 8, shared_ukm) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_LIBRARY_BUG);
goto err;
}
/* Make GOST keytransport blob message */
@@ -3260,22 +3092,20 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt)
*/
msglen = 255;
if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- SSL_R_LIBRARY_BUG);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_LIBRARY_BUG);
goto err;
}
if (!WPACKET_put_bytes_u8(pkt, V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)
|| (msglen >= 0x80 && !WPACKET_put_bytes_u8(pkt, 0x81))
|| !WPACKET_sub_memcpy_u8(pkt, tmp, msglen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
EVP_PKEY_CTX_free(pkey_ctx);
- s->s3->tmp.pms = pms;
- s->s3->tmp.pmslen = pmslen;
+ s->s3.tmp.pms = pms;
+ s->s3.tmp.pmslen = pmslen;
return 1;
err:
@@ -3284,8 +3114,140 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt)
EVP_MD_CTX_free(ukm_hash);
return 0;
#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+#ifndef OPENSSL_NO_GOST
+int ossl_gost18_cke_cipher_nid(const SSL *s)
+{
+ if ((s->s3.tmp.new_cipher->algorithm_enc & SSL_MAGMA) != 0)
+ return NID_magma_ctr;
+ else if ((s->s3.tmp.new_cipher->algorithm_enc & SSL_KUZNYECHIK) != 0)
+ return NID_kuznyechik_ctr;
+
+ return NID_undef;
+}
+
+int ossl_gost_ukm(const SSL *s, unsigned char *dgst_buf)
+{
+ EVP_MD_CTX * hash = NULL;
+ unsigned int md_len;
+ const EVP_MD *md = ssl_evp_md_fetch(s->ctx->libctx, NID_id_GostR3411_2012_256, s->ctx->propq);
+
+ if (md == NULL)
+ return 0;
+
+ if ((hash = EVP_MD_CTX_new()) == NULL
+ || EVP_DigestInit(hash, md) <= 0
+ || EVP_DigestUpdate(hash, s->s3.client_random, SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestUpdate(hash, s->s3.server_random, SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestFinal_ex(hash, dgst_buf, &md_len) <= 0) {
+ EVP_MD_CTX_free(hash);
+ ssl_evp_md_free(md);
+ return 0;
+ }
+
+ EVP_MD_CTX_free(hash);
+ ssl_evp_md_free(md);
+ return 1;
+}
+#endif
+
+static int tls_construct_cke_gost18(SSL *s, WPACKET *pkt)
+{
+#ifndef OPENSSL_NO_GOST
+ /* GOST 2018 key exchange message creation */
+ unsigned char rnd_dgst[32];
+ unsigned char *encdata = NULL;
+ EVP_PKEY_CTX *pkey_ctx = NULL;
+ X509 *peer_cert;
+ unsigned char *pms = NULL;
+ size_t pmslen = 0;
+ size_t msglen;
+ int cipher_nid = ossl_gost18_cke_cipher_nid(s);
+
+ if (cipher_nid == NID_undef) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (ossl_gost_ukm(s, rnd_dgst) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Pre-master secret - random bytes */
+ pmslen = 32;
+ pms = OPENSSL_malloc(pmslen);
+ if (pms == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (RAND_bytes_ex(s->ctx->libctx, pms, pmslen, 0) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Get server certificate PKEY and create ctx from it */
+ peer_cert = s->session->peer;
+ if (peer_cert == NULL) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
+ goto err;
+ }
+
+ pkey_ctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx,
+ X509_get0_pubkey(peer_cert),
+ s->ctx->propq);
+ if (pkey_ctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0 ) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ };
+
+ /* Reuse EVP_PKEY_CTRL_SET_IV, make choice in engine code */
+ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
+ EVP_PKEY_CTRL_SET_IV, 32, rnd_dgst) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_LIBRARY_BUG);
+ goto err;
+ }
+
+ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
+ EVP_PKEY_CTRL_CIPHER, cipher_nid, NULL) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_LIBRARY_BUG);
+ goto err;
+ }
+
+ if (EVP_PKEY_encrypt(pkey_ctx, NULL, &msglen, pms, pmslen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ if (!WPACKET_allocate_bytes(pkt, msglen, &encdata)
+ || EVP_PKEY_encrypt(pkey_ctx, encdata, &msglen, pms, pmslen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ EVP_PKEY_CTX_free(pkey_ctx);
+ pkey_ctx = NULL;
+ s->s3.tmp.pms = pms;
+ s->s3.tmp.pmslen = pmslen;
+
+ return 1;
+ err:
+ EVP_PKEY_CTX_free(pkey_ctx);
+ OPENSSL_clear_free(pms, pmslen);
+ return 0;
+#else
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
@@ -3298,8 +3260,7 @@ static int tls_construct_cke_srp(SSL *s, WPACKET *pkt)
if (s->srp_ctx.A == NULL
|| !WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(s->srp_ctx.A),
&abytes)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
BN_bn2bin(s->srp_ctx.A, abytes);
@@ -3307,15 +3268,13 @@ static int tls_construct_cke_srp(SSL *s, WPACKET *pkt)
OPENSSL_free(s->session->srp_username);
s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
if (s->session->srp_username == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
@@ -3324,7 +3283,7 @@ int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt)
{
unsigned long alg_k;
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
/*
* All of the construct functions below call SSLfatal() if necessary so
@@ -3346,24 +3305,26 @@ int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt)
} else if (alg_k & SSL_kGOST) {
if (!tls_construct_cke_gost(s, pkt))
goto err;
+ } else if (alg_k & SSL_kGOST18) {
+ if (!tls_construct_cke_gost18(s, pkt))
+ goto err;
} else if (alg_k & SSL_kSRP) {
if (!tls_construct_cke_srp(s, pkt))
goto err;
} else if (!(alg_k & SSL_kPSK)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
return 1;
err:
- OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
- s->s3->tmp.pms = NULL;
- s->s3->tmp.pmslen = 0;
+ OPENSSL_clear_free(s->s3.tmp.pms, s->s3.tmp.pmslen);
+ s->s3.tmp.pms = NULL;
+ s->s3.tmp.pmslen = 0;
#ifndef OPENSSL_NO_PSK
- OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
- s->s3->tmp.psk = NULL;
- s->s3->tmp.psklen = 0;
+ OPENSSL_clear_free(s->s3.tmp.psk, s->s3.tmp.psklen);
+ s->s3.tmp.psk = NULL;
+ s->s3.tmp.psklen = 0;
#endif
return 0;
}
@@ -3373,12 +3334,12 @@ int tls_client_key_exchange_post_work(SSL *s)
unsigned char *pms = NULL;
size_t pmslen = 0;
- pms = s->s3->tmp.pms;
- pmslen = s->s3->tmp.pmslen;
+ pms = s->s3.tmp.pms;
+ pmslen = s->s3.tmp.pmslen;
#ifndef OPENSSL_NO_SRP
/* Check for SRP */
- if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
+ if (s->s3.tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
if (!srp_generate_client_master_secret(s)) {
/* SSLfatal() already called */
goto err;
@@ -3387,9 +3348,8 @@ int tls_client_key_exchange_post_work(SSL *s)
}
#endif
- if (pms == NULL && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_MALLOC_FAILURE);
+ if (pms == NULL && !(s->s3.tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!ssl_generate_master_secret(s, pms, pmslen, 1)) {
@@ -3423,9 +3383,7 @@ int tls_client_key_exchange_post_work(SSL *s)
if (SSL_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
labellen, NULL, 0, 0) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -3437,8 +3395,8 @@ int tls_client_key_exchange_post_work(SSL *s)
return 1;
err:
OPENSSL_clear_free(pms, pmslen);
- s->s3->tmp.pms = NULL;
- s->s3->tmp.pmslen = 0;
+ s->s3.tmp.pms = NULL;
+ s->s3.tmp.pmslen = 0;
return 0;
}
@@ -3450,7 +3408,7 @@ int tls_client_key_exchange_post_work(SSL *s)
static int ssl3_check_client_certificate(SSL *s)
{
/* If no suitable signature algorithm can't use certificate */
- if (!tls_choose_sigalg(s, 0) || s->s3->tmp.sigalg == NULL)
+ if (!tls_choose_sigalg(s, 0) || s->s3.tmp.sigalg == NULL)
return 0;
/*
* If strict mode check suitability of chain before using it. This also
@@ -3477,9 +3435,7 @@ WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst)
return WORK_MORE_A;
}
if (i == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE,
- SSL_R_CALLBACK_FAILED);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CALLBACK_FAILED);
return WORK_ERROR;
}
s->rwstate = SSL_NOTHING;
@@ -3512,8 +3468,7 @@ WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst)
i = 0;
} else if (i == 1) {
i = 0;
- SSLerr(SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE,
- SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
}
X509_free(x509);
@@ -3522,11 +3477,11 @@ WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst)
i = 0;
if (i == 0) {
if (s->version == SSL3_VERSION) {
- s->s3->tmp.cert_req = 0;
+ s->s3.tmp.cert_req = 0;
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_CERTIFICATE);
return WORK_FINISHED_CONTINUE;
} else {
- s->s3->tmp.cert_req = 2;
+ s->s3.tmp.cert_req = 2;
if (!ssl3_digest_cached_records(s, 0)) {
/* SSLfatal() already called */
return WORK_ERROR;
@@ -3540,8 +3495,7 @@ WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst)
}
/* Shouldn't ever get here */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
@@ -3551,18 +3505,16 @@ int tls_construct_client_certificate(SSL *s, WPACKET *pkt)
if (s->pha_context == NULL) {
/* no context available, add 0-length context */
if (!WPACKET_put_bytes_u8(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
} else if (!WPACKET_sub_memcpy_u8(pkt, s->pha_context, s->pha_context_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
if (!ssl3_output_cert_chain(s, pkt,
- (s->s3->tmp.cert_req == 2) ? NULL
+ (s->s3.tmp.cert_req == 2) ? NULL
: s->cert->key)) {
/* SSLfatal() already called */
return 0;
@@ -3576,8 +3528,7 @@ int tls_construct_client_certificate(SSL *s, WPACKET *pkt)
* This is a fatal error, which leaves enc_write_ctx in an inconsistent
* state and thus ssl3_send_alert may crash.
*/
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE,
- SSL_R_CANNOT_CHANGE_CIPHER);
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_R_CANNOT_CHANGE_CIPHER);
return 0;
}
@@ -3590,8 +3541,8 @@ int ssl3_check_cert_and_algorithm(SSL *s)
size_t idx;
long alg_k, alg_a;
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
- alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+ alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
+ alg_a = s->s3.tmp.new_cipher->algorithm_auth;
/* we don't have a certificate */
if (!(alg_a & SSL_aCERT))
@@ -3602,36 +3553,27 @@ int ssl3_check_cert_and_algorithm(SSL *s)
/* Check certificate is recognised and suitable for cipher */
if (clu == NULL || (alg_a & clu->amask) == 0) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
- SSL_R_MISSING_SIGNING_CERT);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_MISSING_SIGNING_CERT);
return 0;
}
-#ifndef OPENSSL_NO_EC
if (clu->amask & SSL_aECDSA) {
if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s))
return 1;
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_BAD_ECC_CERT);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_BAD_ECC_CERT);
return 0;
}
-#endif
-#ifndef OPENSSL_NO_RSA
+
if (alg_k & (SSL_kRSA | SSL_kRSAPSK) && idx != SSL_PKEY_RSA) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
SSL_R_MISSING_RSA_ENCRYPTING_CERT);
return 0;
}
-#endif
-#ifndef OPENSSL_NO_DH
- if ((alg_k & SSL_kDHE) && (s->s3->peer_tmp == NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
- ERR_R_INTERNAL_ERROR);
+
+ if ((alg_k & SSL_kDHE) && (s->s3.peer_tmp == NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
-#endif
return 1;
}
@@ -3647,8 +3589,7 @@ int tls_construct_next_proto(SSL *s, WPACKET *pkt)
if (!WPACKET_sub_memcpy_u8(pkt, s->ext.npn, len)
|| !WPACKET_sub_allocate_bytes_u8(pkt, padding_len, &padding)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_NEXT_PROTO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -3662,8 +3603,7 @@ MSG_PROCESS_RETURN tls_process_hello_req(SSL *s, PACKET *pkt)
{
if (PACKET_remaining(pkt) > 0) {
/* should contain no data */
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_HELLO_REQ,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
@@ -3694,8 +3634,7 @@ static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt)
if (!PACKET_as_length_prefixed_2(pkt, &extensions)
|| PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
@@ -3721,9 +3660,7 @@ int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
int i = 0;
#ifndef OPENSSL_NO_ENGINE
if (s->ctx->client_cert_engine) {
- i = ENGINE_load_ssl_client_cert(s->ctx->client_cert_engine, s,
- SSL_get_client_CA_list(s),
- px509, ppkey, NULL, NULL, NULL);
+ i = tls_engine_load_ssl_client_cert(s, px509, ppkey);
if (i != 0)
return i;
}
@@ -3741,14 +3678,12 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, WPACKET *pkt)
/* Set disabled masks for this session */
if (!ssl_set_client_disabled(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
- SSL_R_NO_PROTOCOLS_AVAILABLE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_NO_PROTOCOLS_AVAILABLE);
return 0;
}
if (sk == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -3782,20 +3717,19 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, WPACKET *pkt)
continue;
if (!s->method->put_cipher_by_char(c, pkt, &len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
/* Sanity check that the maximum version we offer has ciphers enabled */
if (!maxverok) {
if (SSL_IS_DTLS(s)) {
- if (DTLS_VERSION_GE(c->max_dtls, s->s3->tmp.max_ver)
- && DTLS_VERSION_LE(c->min_dtls, s->s3->tmp.max_ver))
+ if (DTLS_VERSION_GE(c->max_dtls, s->s3.tmp.max_ver)
+ && DTLS_VERSION_LE(c->min_dtls, s->s3.tmp.max_ver))
maxverok = 1;
} else {
- if (c->max_tls >= s->s3->tmp.max_ver
- && c->min_tls <= s->s3->tmp.max_ver)
+ if (c->max_tls >= s->s3.tmp.max_ver
+ && c->min_tls <= s->s3.tmp.max_ver)
maxverok = 1;
}
}
@@ -3804,13 +3738,13 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, WPACKET *pkt)
}
if (totlen == 0 || !maxverok) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
- SSL_R_NO_CIPHERS_AVAILABLE);
-
- if (!maxverok)
- ERR_add_error_data(1, "No ciphers enabled for max supported "
- "SSL/TLS version");
+ const char *maxvertext =
+ !maxverok
+ ? "No ciphers enabled for max supported SSL/TLS version"
+ : NULL;
+ SSLfatal_data(s, SSL_AD_INTERNAL_ERROR, SSL_R_NO_CIPHERS_AVAILABLE,
+ maxvertext);
return 0;
}
@@ -3820,8 +3754,7 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, WPACKET *pkt)
0, NULL, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
if (!s->method->put_cipher_by_char(&scsv, pkt, &len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
@@ -3830,8 +3763,7 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, WPACKET *pkt)
0, NULL, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
if (!s->method->put_cipher_by_char(&scsv, pkt, &len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
@@ -3844,9 +3776,7 @@ int tls_construct_end_of_early_data(SSL *s, WPACKET *pkt)
{
if (s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY
&& s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
diff --git a/ssl/statem/statem_dtls.c b/ssl/statem/statem_dtls.c
index 8fe6cea72359..788d0eff656b 100644
--- a/ssl/statem/statem_dtls.c
+++ b/ssl/statem/statem_dtls.c
@@ -1,7 +1,7 @@
/*
* Copyright 2005-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -60,13 +60,13 @@ static hm_fragment *dtls1_hm_fragment_new(size_t frag_len, int reassembly)
unsigned char *bitmask = NULL;
if ((frag = OPENSSL_malloc(sizeof(*frag))) == NULL) {
- SSLerr(SSL_F_DTLS1_HM_FRAGMENT_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (frag_len) {
if ((buf = OPENSSL_malloc(frag_len)) == NULL) {
- SSLerr(SSL_F_DTLS1_HM_FRAGMENT_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
OPENSSL_free(frag);
return NULL;
}
@@ -79,7 +79,7 @@ static hm_fragment *dtls1_hm_fragment_new(size_t frag_len, int reassembly)
if (reassembly) {
bitmask = OPENSSL_zalloc(RSMBLY_BITMASK_SIZE(frag_len));
if (bitmask == NULL) {
- SSLerr(SSL_F_DTLS1_HM_FRAGMENT_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
OPENSSL_free(buf);
OPENSSL_free(frag);
return NULL;
@@ -132,17 +132,17 @@ int dtls1_do_write(SSL *s, int type)
if (s->write_hash) {
if (s->enc_write_ctx
- && (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) &
+ && (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx)) &
EVP_CIPH_FLAG_AEAD_CIPHER) != 0)
mac_size = 0;
else
- mac_size = EVP_MD_CTX_size(s->write_hash);
+ mac_size = EVP_MD_CTX_get_size(s->write_hash);
} else
mac_size = 0;
if (s->enc_write_ctx &&
- (EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_CBC_MODE))
- blocksize = 2 * EVP_CIPHER_CTX_block_size(s->enc_write_ctx);
+ (EVP_CIPHER_CTX_get_mode(s->enc_write_ctx) == EVP_CIPH_CBC_MODE))
+ blocksize = 2 * EVP_CIPHER_CTX_get_block_size(s->enc_write_ctx);
else
blocksize = 0;
@@ -328,7 +328,7 @@ int dtls1_do_write(SSL *s, int type)
return 0;
}
-int dtls_get_message(SSL *s, int *mt, size_t *len)
+int dtls_get_message(SSL *s, int *mt)
{
struct hm_header_st *msg_hdr;
unsigned char *p;
@@ -349,10 +349,9 @@ int dtls_get_message(SSL *s, int *mt, size_t *len)
return 0;
}
- *mt = s->s3->tmp.message_type;
+ *mt = s->s3.tmp.message_type;
p = (unsigned char *)s->init_buf->data;
- *len = s->init_num;
if (*mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
if (s->msg_callback) {
@@ -373,32 +372,54 @@ int dtls_get_message(SSL *s, int *mt, size_t *len)
s2n(msg_hdr->seq, p);
l2n3(0, p);
l2n3(msg_len, p);
- if (s->version != DTLS1_BAD_VER) {
- p -= DTLS1_HM_HEADER_LENGTH;
- msg_len += DTLS1_HM_HEADER_LENGTH;
- }
+ memset(msg_hdr, 0, sizeof(*msg_hdr));
+
+ s->d1->handshake_read_seq++;
+
+ s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+
+ return 1;
+}
+
+/*
+ * Actually we already have the message body - but this is an opportunity for
+ * DTLS to do any further processing it wants at the same point that TLS would
+ * be asked for the message body.
+ */
+int dtls_get_message_body(SSL *s, size_t *len)
+{
+ unsigned char *msg = (unsigned char *)s->init_buf->data;
+ size_t msg_len = s->init_num + DTLS1_HM_HEADER_LENGTH;
+
+ if (s->s3.tmp.message_type == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ /* Nothing to be done */
+ goto end;
+ }
/*
* If receiving Finished, record MAC of prior handshake messages for
* Finished verification.
*/
- if (*mt == SSL3_MT_FINISHED && !ssl3_take_mac(s)) {
+ if (*(s->init_buf->data) == SSL3_MT_FINISHED && !ssl3_take_mac(s)) {
/* SSLfatal() already called */
return 0;
}
- if (!ssl3_finish_mac(s, p, msg_len))
+ if (s->version == DTLS1_BAD_VER) {
+ msg += DTLS1_HM_HEADER_LENGTH;
+ msg_len -= DTLS1_HM_HEADER_LENGTH;
+ }
+
+ if (!ssl3_finish_mac(s, msg, msg_len))
return 0;
+
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
- p, msg_len, s, s->msg_callback_arg);
-
- memset(msg_hdr, 0, sizeof(*msg_hdr));
-
- s->d1->handshake_read_seq++;
-
- s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+ s->init_buf->data, s->init_num + DTLS1_HM_HEADER_LENGTH,
+ s, s->msg_callback_arg);
+ end:
+ *len = s->init_num;
return 1;
}
@@ -426,8 +447,7 @@ static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr)
/* sanity checking */
if ((frag_off + frag_len) > msg_len
|| msg_len > dtls1_max_handshake_message_len(s)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_PREPROCESS_FRAGMENT,
- SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_EXCESSIVE_MESSAGE_SIZE);
return 0;
}
@@ -437,14 +457,13 @@ static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr)
* dtls_max_handshake_message_len(s) above
*/
if (!BUF_MEM_grow_clean(s->init_buf, msg_len + DTLS1_HM_HEADER_LENGTH)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PREPROCESS_FRAGMENT,
- ERR_R_BUF_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_BUF_LIB);
return 0;
}
- s->s3->tmp.message_size = msg_len;
+ s->s3.tmp.message_size = msg_len;
s->d1->r_msg_hdr.msg_len = msg_len;
- s->s3->tmp.message_type = msg_hdr->type;
+ s->s3.tmp.message_type = msg_hdr->type;
s->d1->r_msg_hdr.type = msg_hdr->type;
s->d1->r_msg_hdr.seq = msg_hdr->seq;
} else if (msg_len != s->d1->r_msg_hdr.msg_len) {
@@ -452,8 +471,7 @@ static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr)
* They must be playing with us! BTW, failure to enforce upper limit
* would open possibility for buffer overrun.
*/
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_PREPROCESS_FRAGMENT,
- SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_EXCESSIVE_MESSAGE_SIZE);
return 0;
}
@@ -473,23 +491,64 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, size_t *len)
* (2) update s->init_num
*/
pitem *item;
+ piterator iter;
hm_fragment *frag;
int ret;
+ int chretran = 0;
+ iter = pqueue_iterator(s->d1->buffered_messages);
do {
- item = pqueue_peek(s->d1->buffered_messages);
+ item = pqueue_next(&iter);
if (item == NULL)
return 0;
frag = (hm_fragment *)item->data;
if (frag->msg_header.seq < s->d1->handshake_read_seq) {
- /* This is a stale message that has been buffered so clear it */
- pqueue_pop(s->d1->buffered_messages);
- dtls1_hm_fragment_free(frag);
- pitem_free(item);
- item = NULL;
- frag = NULL;
+ pitem *next;
+ hm_fragment *nextfrag;
+
+ if (!s->server
+ || frag->msg_header.seq != 0
+ || s->d1->handshake_read_seq != 1
+ || s->statem.hand_state != DTLS_ST_SW_HELLO_VERIFY_REQUEST) {
+ /*
+ * This is a stale message that has been buffered so clear it.
+ * It is safe to pop this message from the queue even though
+ * we have an active iterator
+ */
+ pqueue_pop(s->d1->buffered_messages);
+ dtls1_hm_fragment_free(frag);
+ pitem_free(item);
+ item = NULL;
+ frag = NULL;
+ } else {
+ /*
+ * We have fragments for a ClientHello without a cookie,
+ * even though we have sent a HelloVerifyRequest. It is possible
+ * that the HelloVerifyRequest got lost and this is a
+ * retransmission of the original ClientHello
+ */
+ next = pqueue_next(&iter);
+ if (next != NULL) {
+ nextfrag = (hm_fragment *)next->data;
+ if (nextfrag->msg_header.seq == s->d1->handshake_read_seq) {
+ /*
+ * We have fragments for both a ClientHello without
+ * cookie and one with. Ditch the one without.
+ */
+ pqueue_pop(s->d1->buffered_messages);
+ dtls1_hm_fragment_free(frag);
+ pitem_free(item);
+ item = next;
+ frag = nextfrag;
+ } else {
+ chretran = 1;
+ }
+ } else {
+ chretran = 1;
+ }
+ }
}
} while (item == NULL);
@@ -497,7 +556,7 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, size_t *len)
if (frag->reassembly != NULL)
return 0;
- if (s->d1->handshake_read_seq == frag->msg_header.seq) {
+ if (s->d1->handshake_read_seq == frag->msg_header.seq || chretran) {
size_t frag_len = frag->msg_header.frag_len;
pqueue_pop(s->d1->buffered_messages);
@@ -515,6 +574,16 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, size_t *len)
pitem_free(item);
if (ret) {
+ if (chretran) {
+ /*
+ * We got a new ClientHello with a message sequence of 0.
+ * Reset the read/write sequences back to the beginning.
+ * We process it like this is the first time we've seen a
+ * ClientHello from the client.
+ */
+ s->d1->handshake_read_seq = 0;
+ s->d1->next_handshake_write_seq = 0;
+ }
*len = frag_len;
return 1;
}
@@ -741,6 +810,7 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
int i, ret, recvd_type;
struct hm_header_st msg_hdr;
size_t readbytes;
+ int chretran = 0;
*errtype = 0;
@@ -768,7 +838,6 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
if (wire[0] != SSL3_MT_CCS) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
SSL_R_BAD_CHANGE_CIPHER_SPEC);
goto f_err;
}
@@ -776,16 +845,15 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
memcpy(s->init_buf->data, wire, readbytes);
s->init_num = readbytes - 1;
s->init_msg = s->init_buf->data + 1;
- s->s3->tmp.message_type = SSL3_MT_CHANGE_CIPHER_SPEC;
- s->s3->tmp.message_size = readbytes - 1;
+ s->s3.tmp.message_type = SSL3_MT_CHANGE_CIPHER_SPEC;
+ s->s3.tmp.message_size = readbytes - 1;
*len = readbytes - 1;
return 1;
}
/* Handshake fails if message header is incomplete */
if (readbytes != DTLS1_HM_HEADER_LENGTH) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
goto f_err;
}
@@ -801,8 +869,7 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
* Fragments must not span records.
*/
if (frag_len > RECORD_LAYER_get_rrec_length(&s->rlayer)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_LENGTH);
goto f_err;
}
@@ -813,8 +880,20 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
* although we're still expecting seq 0 (ClientHello)
*/
if (msg_hdr.seq != s->d1->handshake_read_seq) {
- *errtype = dtls1_process_out_of_seq_message(s, &msg_hdr);
- return 0;
+ if (!s->server
+ || msg_hdr.seq != 0
+ || s->d1->handshake_read_seq != 1
+ || wire[0] != SSL3_MT_CLIENT_HELLO
+ || s->statem.hand_state != DTLS_ST_SW_HELLO_VERIFY_REQUEST) {
+ *errtype = dtls1_process_out_of_seq_message(s, &msg_hdr);
+ return 0;
+ }
+ /*
+ * We received a ClientHello and sent back a HelloVerifyRequest. We
+ * now seem to have received a retransmitted initial ClientHello. That
+ * is allowed (possibly our HelloVerifyRequest got lost).
+ */
+ chretran = 1;
}
if (frag_len && frag_len < mlen) {
@@ -841,9 +920,7 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
goto redo;
} else { /* Incorrectly formatted Hello request */
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
- SSL_R_UNEXPECTED_MESSAGE);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
goto f_err;
}
}
@@ -878,11 +955,21 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
* to fail
*/
if (readbytes != frag_len) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_LENGTH);
goto f_err;
}
+ if (chretran) {
+ /*
+ * We got a new ClientHello with a message sequence of 0.
+ * Reset the read/write sequences back to the beginning.
+ * We process it like this is the first time we've seen a ClientHello
+ * from the client.
+ */
+ s->d1->handshake_read_seq = 0;
+ s->d1->next_handshake_write_seq = 0;
+ }
+
/*
* Note that s->init_num is *not* used as current offset in
* s->init_buf->data, but as a counter summing up fragments' lengths: as
@@ -902,7 +989,7 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
* for these 2 messages, we need to
* ssl->enc_read_ctx re-init
* ssl->rlayer.read_sequence zero
- * ssl->s3->read_mac_secret re-init
+ * ssl->s3.read_mac_secret re-init
* ssl->session->read_sym_enc assign
* ssl->session->read_compression assign
* ssl->session->read_hash assign
@@ -913,9 +1000,7 @@ int dtls_construct_change_cipher_spec(SSL *s, WPACKET *pkt)
s->d1->next_handshake_write_seq++;
if (!WPACKET_put_bytes_u16(pkt, s->d1->handshake_write_seq)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
@@ -936,8 +1021,7 @@ WORK_STATE dtls_wait_for_dry(SSL *s)
/* read app data until dry event */
ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
if (ret < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS_WAIT_FOR_DRY,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
@@ -950,12 +1034,11 @@ WORK_STATE dtls_wait_for_dry(SSL *s)
*/
if (dtls_get_reassembled_message(s, &errtype, &len)) {
/* The call succeeded! This should never happen */
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS_WAIT_FOR_DRY,
- SSL_R_UNEXPECTED_MESSAGE);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
return WORK_ERROR;
}
- s->s3->in_read_app_data = 2;
+ s->s3.in_read_app_data = 2;
s->rwstate = SSL_READING;
BIO_clear_retry_flags(SSL_get_rbio(s));
BIO_set_retry_read(SSL_get_rbio(s));
@@ -968,8 +1051,7 @@ WORK_STATE dtls_wait_for_dry(SSL *s)
int dtls1_read_failed(SSL *s, int code)
{
if (code > 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_DTLS1_READ_FAILED, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -1051,12 +1133,16 @@ int dtls1_buffer_message(SSL *s, int is_ccs)
if (!ossl_assert(s->d1->w_msg_hdr.msg_len +
((s->version ==
DTLS1_BAD_VER) ? 3 : DTLS1_CCS_HEADER_LENGTH)
- == (unsigned int)s->init_num))
+ == (unsigned int)s->init_num)) {
+ dtls1_hm_fragment_free(frag);
return 0;
+ }
} else {
if (!ossl_assert(s->d1->w_msg_hdr.msg_len +
- DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num))
+ DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num)) {
+ dtls1_hm_fragment_free(frag);
return 0;
+ }
}
frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
@@ -1111,8 +1197,7 @@ int dtls1_retransmit_message(SSL *s, unsigned short seq, int *found)
item = pqueue_find(s->d1->sent_messages, seq64be);
if (item == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_RETRANSMIT_MESSAGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
*found = 0;
return 0;
}
diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c
index 695caab3d628..bcce73bcdc3e 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -1,8 +1,8 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -17,7 +17,9 @@
#include <openssl/buffer.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
+#include <openssl/rsa.h>
#include <openssl/x509.h>
+#include <openssl/trace.h>
/*
* Map error codes to TLS/SSL alart types.
@@ -88,6 +90,8 @@ int tls_close_construct_packet(SSL *s, WPACKET *pkt, int htype)
int tls_setup_handshake(SSL *s)
{
+ int ver_min, ver_max, ok;
+
if (!ssl3_init_finished_mac(s)) {
/* SSLfatal() already called */
return 0;
@@ -96,20 +100,59 @@ int tls_setup_handshake(SSL *s)
/* Reset any extension flags */
memset(s->ext.extflags, 0, sizeof(s->ext.extflags));
+ if (ssl_get_min_max_version(s, &ver_min, &ver_max, NULL) != 0) {
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_R_NO_PROTOCOLS_AVAILABLE);
+ return 0;
+ }
+
+ /* Sanity check that we have MD5-SHA1 if we need it */
+ if (s->ctx->ssl_digest_methods[SSL_MD_MD5_SHA1_IDX] == NULL) {
+ int md5sha1_needed = 0;
+
+ /* We don't have MD5-SHA1 - do we need it? */
+ if (SSL_IS_DTLS(s)) {
+ if (DTLS_VERSION_LE(ver_max, DTLS1_VERSION))
+ md5sha1_needed = 1;
+ } else {
+ if (ver_max <= TLS1_1_VERSION)
+ md5sha1_needed = 1;
+ }
+ if (md5sha1_needed) {
+ SSLfatal_data(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_R_NO_SUITABLE_DIGEST_ALGORITHM,
+ "The max supported SSL/TLS version needs the"
+ " MD5-SHA1 digest but it is not available"
+ " in the loaded providers. Use (D)TLSv1.2 or"
+ " above, or load different providers");
+ return 0;
+ }
+
+ ok = 1;
+ /* Don't allow TLSv1.1 or below to be negotiated */
+ if (SSL_IS_DTLS(s)) {
+ if (DTLS_VERSION_LT(ver_min, DTLS1_2_VERSION))
+ ok = SSL_set_min_proto_version(s, DTLS1_2_VERSION);
+ } else {
+ if (ver_min < TLS1_2_VERSION)
+ ok = SSL_set_min_proto_version(s, TLS1_2_VERSION);
+ }
+ if (!ok) {
+ /* Shouldn't happen */
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+
+ ok = 0;
if (s->server) {
STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(s);
- int i, ver_min, ver_max, ok = 0;
+ int i;
/*
* Sanity check that the maximum version we accept has ciphers
* enabled. For clients we do this check during construction of the
* ClientHello.
*/
- if (ssl_get_min_max_version(s, &ver_min, &ver_max, NULL) != 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_SETUP_HANDSHAKE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
const SSL_CIPHER *c = sk_SSL_CIPHER_value(ciphers, i);
@@ -124,32 +167,33 @@ int tls_setup_handshake(SSL *s)
break;
}
if (!ok) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_SETUP_HANDSHAKE,
- SSL_R_NO_CIPHERS_AVAILABLE);
- ERR_add_error_data(1, "No ciphers enabled for max supported "
- "SSL/TLS version");
+ SSLfatal_data(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_R_NO_CIPHERS_AVAILABLE,
+ "No ciphers enabled for max supported "
+ "SSL/TLS version");
return 0;
}
if (SSL_IS_FIRST_HANDSHAKE(s)) {
/* N.B. s->session_ctx == s->ctx here */
- tsan_counter(&s->session_ctx->stats.sess_accept);
+ ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_accept);
} else {
/* N.B. s->ctx may not equal s->session_ctx */
- tsan_counter(&s->ctx->stats.sess_accept_renegotiate);
+ ssl_tsan_counter(s->ctx, &s->ctx->stats.sess_accept_renegotiate);
- s->s3->tmp.cert_request = 0;
+ s->s3.tmp.cert_request = 0;
}
} else {
if (SSL_IS_FIRST_HANDSHAKE(s))
- tsan_counter(&s->session_ctx->stats.sess_connect);
+ ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_connect);
else
- tsan_counter(&s->session_ctx->stats.sess_connect_renegotiate);
+ ssl_tsan_counter(s->session_ctx,
+ &s->session_ctx->stats.sess_connect_renegotiate);
/* mark client_random uninitialized */
- memset(s->s3->client_random, 0, sizeof(s->s3->client_random));
+ memset(s->s3.client_random, 0, sizeof(s->s3.client_random));
s->hit = 0;
- s->s3->tmp.cert_req = 0;
+ s->s3.tmp.cert_req = 0;
if (SSL_IS_DTLS(s))
s->statem.use_timer = 1;
@@ -215,10 +259,9 @@ static int get_cert_verify_tbs_data(SSL *s, unsigned char *tls13tbs,
size_t retlen;
long retlen_l;
- retlen = retlen_l = BIO_get_mem_data(s->s3->handshake_buffer, hdata);
+ retlen = retlen_l = BIO_get_mem_data(s->s3.handshake_buffer, hdata);
if (retlen_l <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_GET_CERT_VERIFY_TBS_DATA,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
*hdatalen = retlen;
@@ -237,25 +280,22 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
void *hdata;
unsigned char *sig = NULL;
unsigned char tls13tbs[TLS13_TBS_PREAMBLE_SIZE + EVP_MAX_MD_SIZE];
- const SIGALG_LOOKUP *lu = s->s3->tmp.sigalg;
+ const SIGALG_LOOKUP *lu = s->s3.tmp.sigalg;
- if (lu == NULL || s->s3->tmp.cert == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_INTERNAL_ERROR);
+ if (lu == NULL || s->s3.tmp.cert == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- pkey = s->s3->tmp.cert->privatekey;
+ pkey = s->s3.tmp.cert->privatekey;
- if (pkey == NULL || !tls1_lookup_md(lu, &md)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_INTERNAL_ERROR);
+ if (pkey == NULL || !tls1_lookup_md(s->ctx, lu, &md)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
mctx = EVP_MD_CTX_new();
if (mctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -266,21 +306,15 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
}
if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- siglen = EVP_PKEY_size(pkey);
- sig = OPENSSL_malloc(siglen);
- if (sig == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- if (EVP_DigestSignInit(mctx, &pctx, md, NULL, pkey) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_EVP_LIB);
+ if (EVP_DigestSignInit_ex(mctx, &pctx,
+ md == NULL ? NULL : EVP_MD_get0_name(md),
+ s->ctx->libctx, s->ctx->propq, pkey,
+ NULL) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
@@ -288,26 +322,45 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
|| EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
RSA_PSS_SALTLEN_DIGEST) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_EVP_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
}
if (s->version == SSL3_VERSION) {
+ /*
+ * Here we use EVP_DigestSignUpdate followed by EVP_DigestSignFinal
+ * in order to add the EVP_CTRL_SSL3_MASTER_SECRET call between them.
+ */
if (EVP_DigestSignUpdate(mctx, hdata, hdatalen) <= 0
- || !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
- (int)s->session->master_key_length,
- s->session->master_key)
- || EVP_DigestSignFinal(mctx, sig, &siglen) <= 0) {
+ || EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
+ (int)s->session->master_key_length,
+ s->session->master_key) <= 0
+ || EVP_DigestSignFinal(mctx, NULL, &siglen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_EVP_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ goto err;
+ }
+ sig = OPENSSL_malloc(siglen);
+ if (sig == NULL
+ || EVP_DigestSignFinal(mctx, sig, &siglen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ goto err;
+ }
+ } else {
+ /*
+ * Here we *must* use EVP_DigestSign() because Ed25519/Ed448 does not
+ * support streaming via EVP_DigestSignUpdate/EVP_DigestSignFinal
+ */
+ if (EVP_DigestSign(mctx, NULL, &siglen, hdata, hdatalen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ goto err;
+ }
+ sig = OPENSSL_malloc(siglen);
+ if (sig == NULL
+ || EVP_DigestSign(mctx, sig, &siglen, hdata, hdatalen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
- } else if (EVP_DigestSign(mctx, sig, &siglen, hdata, hdatalen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_EVP_LIB);
- goto err;
}
#ifndef OPENSSL_NO_GOST
@@ -322,8 +375,7 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
#endif
if (!WPACKET_sub_memcpy_u16(pkt, sig, siglen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -361,21 +413,19 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
EVP_PKEY_CTX *pctx = NULL;
if (mctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
peer = s->session->peer;
pkey = X509_get0_pubkey(peer);
if (pkey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (ssl_cert_lookup_by_pkey(pkey, NULL) == NULL) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_CERT_VERIFY,
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
goto err;
}
@@ -384,8 +434,7 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
unsigned int sigalg;
if (!PACKET_get_net_2(pkt, &sigalg)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- SSL_R_BAD_PACKET);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_PACKET);
goto err;
}
if (tls12_check_peer_sigalg(s, sigalg, pkey) <= 0) {
@@ -393,22 +442,19 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
goto err;
}
} else if (!tls1_set_peer_legacy_sigalg(s, pkey)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_R_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED);
goto err;
}
- if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- ERR_R_INTERNAL_ERROR);
+ if (!tls1_lookup_md(s->ctx, s->s3.tmp.peer_sigalg, &md)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
-#ifdef SSL_DEBUG
if (SSL_USE_SIGALGS(s))
- fprintf(stderr, "USING TLSv1.2 HASH %s\n",
- md == NULL ? "n/a" : EVP_MD_name(md));
-#endif
+ OSSL_TRACE1(TLS, "USING TLSv1.2 HASH %s\n",
+ md == NULL ? "n/a" : EVP_MD_get0_name(md));
/* Check for broken implementations of GOST ciphersuites */
/*
@@ -418,29 +464,20 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
#ifndef OPENSSL_NO_GOST
if (!SSL_USE_SIGALGS(s)
&& ((PACKET_remaining(pkt) == 64
- && (EVP_PKEY_id(pkey) == NID_id_GostR3410_2001
- || EVP_PKEY_id(pkey) == NID_id_GostR3410_2012_256))
+ && (EVP_PKEY_get_id(pkey) == NID_id_GostR3410_2001
+ || EVP_PKEY_get_id(pkey) == NID_id_GostR3410_2012_256))
|| (PACKET_remaining(pkt) == 128
- && EVP_PKEY_id(pkey) == NID_id_GostR3410_2012_512))) {
+ && EVP_PKEY_get_id(pkey) == NID_id_GostR3410_2012_512))) {
len = PACKET_remaining(pkt);
} else
#endif
if (!PACKET_get_net_2(pkt, &len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
- j = EVP_PKEY_size(pkey);
- if (((int)len > j) || ((int)PACKET_remaining(pkt) > j)
- || (PACKET_remaining(pkt) == 0)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- SSL_R_WRONG_SIGNATURE_SIZE);
- goto err;
- }
if (!PACKET_get_bytes(pkt, &data, len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
@@ -449,24 +486,24 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
goto err;
}
-#ifdef SSL_DEBUG
- fprintf(stderr, "Using client verify alg %s\n",
- md == NULL ? "n/a" : EVP_MD_name(md));
-#endif
- if (EVP_DigestVerifyInit(mctx, &pctx, md, NULL, pkey) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- ERR_R_EVP_LIB);
+ OSSL_TRACE1(TLS, "Using client verify alg %s\n",
+ md == NULL ? "n/a" : EVP_MD_get0_name(md));
+
+ if (EVP_DigestVerifyInit_ex(mctx, &pctx,
+ md == NULL ? NULL : EVP_MD_get0_name(md),
+ s->ctx->libctx, s->ctx->propq, pkey,
+ NULL) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
#ifndef OPENSSL_NO_GOST
{
- int pktype = EVP_PKEY_id(pkey);
+ int pktype = EVP_PKEY_get_id(pkey);
if (pktype == NID_id_GostR3410_2001
|| pktype == NID_id_GostR3410_2012_256
|| pktype == NID_id_GostR3410_2012_512) {
if ((gost_data = OPENSSL_malloc(len)) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
BUF_reverse(gost_data, data, len);
@@ -479,30 +516,26 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
|| EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
RSA_PSS_SALTLEN_DIGEST) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- ERR_R_EVP_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
}
if (s->version == SSL3_VERSION) {
if (EVP_DigestVerifyUpdate(mctx, hdata, hdatalen) <= 0
- || !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
- (int)s->session->master_key_length,
- s->session->master_key)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- ERR_R_EVP_LIB);
+ || EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
+ (int)s->session->master_key_length,
+ s->session->master_key) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
if (EVP_DigestVerifyFinal(mctx, data, len) <= 0) {
- SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- SSL_R_BAD_SIGNATURE);
+ SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_R_BAD_SIGNATURE);
goto err;
}
} else {
j = EVP_DigestVerify(mctx, data, len, hdata, hdatalen);
if (j <= 0) {
- SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- SSL_R_BAD_SIGNATURE);
+ SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_R_BAD_SIGNATURE);
goto err;
}
}
@@ -512,16 +545,16 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
* certificate after the CertVerify instead of when we get the
* CertificateRequest. This is because in TLSv1.3 the CertificateRequest
* comes *before* the Certificate message. In TLSv1.2 it comes after. We
- * want to make sure that SSL_get_peer_certificate() will return the actual
+ * want to make sure that SSL_get1_peer_certificate() will return the actual
* server certificate from the client_cert_cb callback.
*/
- if (!s->server && SSL_IS_TLS13(s) && s->s3->tmp.cert_req == 1)
+ if (!s->server && SSL_IS_TLS13(s) && s->s3.tmp.cert_req == 1)
ret = MSG_PROCESS_CONTINUE_PROCESSING;
else
ret = MSG_PROCESS_CONTINUE_READING;
err:
- BIO_free(s->s3->handshake_buffer);
- s->s3->handshake_buffer = NULL;
+ BIO_free(s->s3.handshake_buffer);
+ s->s3.handshake_buffer = NULL;
EVP_MD_CTX_free(mctx);
#ifndef OPENSSL_NO_GOST
OPENSSL_free(gost_data);
@@ -545,7 +578,7 @@ int tls_construct_finished(SSL *s, WPACKET *pkt)
*/
if (SSL_IS_TLS13(s)
&& !s->server
- && s->s3->tmp.cert_req == 0
+ && s->s3.tmp.cert_req == 0
&& (!s->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {;
/* SSLfatal() already called */
@@ -562,17 +595,16 @@ int tls_construct_finished(SSL *s, WPACKET *pkt)
finish_md_len = s->method->ssl3_enc->final_finish_mac(s,
sender, slen,
- s->s3->tmp.finish_md);
+ s->s3.tmp.finish_md);
if (finish_md_len == 0) {
/* SSLfatal() already called */
return 0;
}
- s->s3->tmp.finish_md_len = finish_md_len;
+ s->s3.tmp.finish_md_len = finish_md_len;
- if (!WPACKET_memcpy(pkt, s->s3->tmp.finish_md, finish_md_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_FINISHED,
- ERR_R_INTERNAL_ERROR);
+ if (!WPACKET_memcpy(pkt, s->s3.tmp.finish_md, finish_md_len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -591,18 +623,17 @@ int tls_construct_finished(SSL *s, WPACKET *pkt)
* Copy the finished so we can use it for renegotiation checks
*/
if (!ossl_assert(finish_md_len <= EVP_MAX_MD_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_FINISHED,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!s->server) {
- memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md,
+ memcpy(s->s3.previous_client_finished, s->s3.tmp.finish_md,
finish_md_len);
- s->s3->previous_client_finished_len = finish_md_len;
+ s->s3.previous_client_finished_len = finish_md_len;
} else {
- memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md,
+ memcpy(s->s3.previous_server_finished, s->s3.tmp.finish_md,
finish_md_len);
- s->s3->previous_server_finished_len = finish_md_len;
+ s->s3.previous_server_finished_len = finish_md_len;
}
return 1;
@@ -611,8 +642,7 @@ int tls_construct_finished(SSL *s, WPACKET *pkt)
int tls_construct_key_update(SSL *s, WPACKET *pkt)
{
if (!WPACKET_put_bytes_u8(pkt, s->key_update)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_KEY_UPDATE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -629,15 +659,13 @@ MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt)
* be on a record boundary.
*/
if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_KEY_UPDATE,
- SSL_R_NOT_ON_RECORD_BOUNDARY);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_NOT_ON_RECORD_BOUNDARY);
return MSG_PROCESS_ERROR;
}
if (!PACKET_get_1(pkt, &updatetype)
|| PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_UPDATE,
- SSL_R_BAD_KEY_UPDATE);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_KEY_UPDATE);
return MSG_PROCESS_ERROR;
}
@@ -647,8 +675,7 @@ MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt)
*/
if (updatetype != SSL_KEY_UPDATE_NOT_REQUESTED
&& updatetype != SSL_KEY_UPDATE_REQUESTED) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_KEY_UPDATE,
- SSL_R_BAD_KEY_UPDATE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_UPDATE);
return MSG_PROCESS_ERROR;
}
@@ -685,11 +712,11 @@ int ssl3_take_mac(SSL *s)
slen = s->method->ssl3_enc->client_finished_label_len;
}
- s->s3->tmp.peer_finish_md_len =
+ s->s3.tmp.peer_finish_md_len =
s->method->ssl3_enc->final_finish_mac(s, sender, slen,
- s->s3->tmp.peer_finish_md);
+ s->s3.tmp.peer_finish_md);
- if (s->s3->tmp.peer_finish_md_len == 0) {
+ if (s->s3.tmp.peer_finish_md_len == 0) {
/* SSLfatal() already called */
return 0;
}
@@ -712,31 +739,25 @@ MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt)
&& remain != DTLS1_CCS_HEADER_LENGTH + 1)
|| (s->version != DTLS1_BAD_VER
&& remain != DTLS1_CCS_HEADER_LENGTH - 1)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
- SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_CHANGE_CIPHER_SPEC);
return MSG_PROCESS_ERROR;
}
} else {
if (remain != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
- SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_CHANGE_CIPHER_SPEC);
return MSG_PROCESS_ERROR;
}
}
/* Check we have a cipher to change to */
- if (s->s3->tmp.new_cipher == NULL) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY);
+ if (s->s3.tmp.new_cipher == NULL) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_CCS_RECEIVED_EARLY);
return MSG_PROCESS_ERROR;
}
- s->s3->change_cipher_spec = 1;
+ s->s3.change_cipher_spec = 1;
if (!ssl3_do_change_cipher_spec(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
}
@@ -785,31 +806,27 @@ MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)
* message must be on a record boundary.
*/
if (SSL_IS_TLS13(s) && RECORD_LAYER_processed_read_pending(&s->rlayer)) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_FINISHED,
- SSL_R_NOT_ON_RECORD_BOUNDARY);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_NOT_ON_RECORD_BOUNDARY);
return MSG_PROCESS_ERROR;
}
/* If this occurs, we have missed a message */
- if (!SSL_IS_TLS13(s) && !s->s3->change_cipher_spec) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_FINISHED,
- SSL_R_GOT_A_FIN_BEFORE_A_CCS);
+ if (!SSL_IS_TLS13(s) && !s->s3.change_cipher_spec) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_GOT_A_FIN_BEFORE_A_CCS);
return MSG_PROCESS_ERROR;
}
- s->s3->change_cipher_spec = 0;
+ s->s3.change_cipher_spec = 0;
- md_len = s->s3->tmp.peer_finish_md_len;
+ md_len = s->s3.tmp.peer_finish_md_len;
if (md_len != PACKET_remaining(pkt)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_FINISHED,
- SSL_R_BAD_DIGEST_LENGTH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_DIGEST_LENGTH);
return MSG_PROCESS_ERROR;
}
- if (CRYPTO_memcmp(PACKET_data(pkt), s->s3->tmp.peer_finish_md,
+ if (CRYPTO_memcmp(PACKET_data(pkt), s->s3.tmp.peer_finish_md,
md_len) != 0) {
- SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_FINISHED,
- SSL_R_DIGEST_CHECK_FAILED);
+ SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_R_DIGEST_CHECK_FAILED);
return MSG_PROCESS_ERROR;
}
@@ -817,18 +834,17 @@ MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)
* Copy the finished so we can use it for renegotiation checks
*/
if (!ossl_assert(md_len <= EVP_MAX_MD_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_FINISHED,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
}
if (s->server) {
- memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md,
+ memcpy(s->s3.previous_client_finished, s->s3.tmp.peer_finish_md,
md_len);
- s->s3->previous_client_finished_len = md_len;
+ s->s3.previous_client_finished_len = md_len;
} else {
- memcpy(s->s3->previous_server_finished, s->s3->tmp.peer_finish_md,
+ memcpy(s->s3.previous_server_finished, s->s3.tmp.peer_finish_md,
md_len);
- s->s3->previous_server_finished_len = md_len;
+ s->s3.previous_server_finished_len = md_len;
}
/*
@@ -870,8 +886,7 @@ MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)
int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt)
{
if (!WPACKET_put_bytes_u8(pkt, SSL3_MT_CCS)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -886,14 +901,12 @@ static int ssl_add_cert_to_wpacket(SSL *s, WPACKET *pkt, X509 *x, int chain)
len = i2d_X509(x, NULL);
if (len < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_TO_WPACKET,
- ERR_R_BUF_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_BUF_LIB);
return 0;
}
if (!WPACKET_sub_allocate_bytes_u24(pkt, len, &outbytes)
|| i2d_X509(x, &outbytes) != len) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_TO_WPACKET,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -937,17 +950,16 @@ static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
chain_store = s->ctx->cert_store;
if (chain_store != NULL) {
- X509_STORE_CTX *xs_ctx = X509_STORE_CTX_new();
+ X509_STORE_CTX *xs_ctx = X509_STORE_CTX_new_ex(s->ctx->libctx,
+ s->ctx->propq);
if (xs_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!X509_STORE_CTX_init(xs_ctx, chain_store, x, NULL)) {
X509_STORE_CTX_free(xs_ctx);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN,
- ERR_R_X509_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_X509_LIB);
return 0;
}
/*
@@ -964,12 +976,12 @@ static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
if (i != 1) {
#if 0
/* Dummy error calls so mkerr generates them */
- SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_EE_KEY_TOO_SMALL);
- SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_KEY_TOO_SMALL);
- SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_MD_TOO_WEAK);
+ ERR_raise(ERR_LIB_SSL, SSL_R_EE_KEY_TOO_SMALL);
+ ERR_raise(ERR_LIB_SSL, SSL_R_CA_KEY_TOO_SMALL);
+ ERR_raise(ERR_LIB_SSL, SSL_R_CA_MD_TOO_WEAK);
#endif
X509_STORE_CTX_free(xs_ctx);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, i);
return 0;
}
chain_count = sk_X509_num(chain);
@@ -986,7 +998,7 @@ static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
} else {
i = ssl_security_cert_chain(s, extra_certs, x, 0);
if (i != 1) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, i);
return 0;
}
if (!ssl_add_cert_to_wpacket(s, pkt, x, 0)) {
@@ -1007,8 +1019,7 @@ static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
{
if (!WPACKET_start_sub_packet_u24(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_OUTPUT_CERT_CHAIN,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -1016,8 +1027,7 @@ unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
return 0;
if (!WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_OUTPUT_CERT_CHAIN,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -1029,7 +1039,8 @@ unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
* in NBIO events. If |clearbufs| is set then init_buf and the wbio buffer is
* freed up as well.
*/
-WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop)
+WORK_STATE tls_finish_handshake(SSL *s, ossl_unused WORK_STATE wst,
+ int clearbufs, int stop)
{
void (*cb) (const SSL *ssl, int type, int val) = NULL;
int cleanuphand = s->statem.cleanuphand;
@@ -1055,8 +1066,7 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop)
}
if (!ssl_free_wbio_buffer(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_FINISH_HANDSHAKE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
s->init_num = 0;
@@ -1088,7 +1098,7 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop)
ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
/* N.B. s->ctx may not equal s->session_ctx */
- tsan_counter(&s->ctx->stats.sess_accept_good);
+ ssl_tsan_counter(s->ctx, &s->ctx->stats.sess_accept_good);
s->handshake_func = ossl_statem_accept;
} else {
if (SSL_IS_TLS13(s)) {
@@ -1107,10 +1117,12 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop)
ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
}
if (s->hit)
- tsan_counter(&s->session_ctx->stats.sess_hit);
+ ssl_tsan_counter(s->session_ctx,
+ &s->session_ctx->stats.sess_hit);
s->handshake_func = ossl_statem_connect;
- tsan_counter(&s->session_ctx->stats.sess_connect_good);
+ ssl_tsan_counter(s->session_ctx,
+ &s->session_ctx->stats.sess_connect_good);
}
if (SSL_IS_DTLS(s)) {
@@ -1172,12 +1184,11 @@ int tls_get_message_header(SSL *s, int *mt)
*/
if (s->init_num != 0 || readbytes != 1 || p[0] != SSL3_MT_CCS) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_TLS_GET_MESSAGE_HEADER,
SSL_R_BAD_CHANGE_CIPHER_SPEC);
return 0;
}
if (s->statem.hand_state == TLS_ST_BEFORE
- && (s->s3->flags & TLS1_FLAGS_STATELESS) != 0) {
+ && (s->s3.flags & TLS1_FLAGS_STATELESS) != 0) {
/*
* We are stateless and we received a CCS. Probably this is
* from a client between the first and second ClientHellos.
@@ -1187,14 +1198,13 @@ int tls_get_message_header(SSL *s, int *mt)
*/
return 0;
}
- s->s3->tmp.message_type = *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
+ s->s3.tmp.message_type = *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
s->init_num = readbytes - 1;
s->init_msg = s->init_buf->data;
- s->s3->tmp.message_size = readbytes;
+ s->s3.tmp.message_size = readbytes;
return 1;
} else if (recvd_type != SSL3_RT_HANDSHAKE) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_TLS_GET_MESSAGE_HEADER,
SSL_R_CCS_RECEIVED_EARLY);
return 0;
}
@@ -1224,7 +1234,7 @@ int tls_get_message_header(SSL *s, int *mt)
/* s->init_num == SSL3_HM_HEADER_LENGTH */
*mt = *p;
- s->s3->tmp.message_type = *(p++);
+ s->s3.tmp.message_type = *(p++);
if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
/*
@@ -1236,7 +1246,7 @@ int tls_get_message_header(SSL *s, int *mt)
*/
l = RECORD_LAYER_get_rrec_length(&s->rlayer)
+ SSL3_HM_HEADER_LENGTH;
- s->s3->tmp.message_size = l;
+ s->s3.tmp.message_size = l;
s->init_msg = s->init_buf->data;
s->init_num = SSL3_HM_HEADER_LENGTH;
@@ -1244,11 +1254,11 @@ int tls_get_message_header(SSL *s, int *mt)
n2l3(p, l);
/* BUF_MEM_grow takes an 'int' parameter */
if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_GET_MESSAGE_HEADER,
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_EXCESSIVE_MESSAGE_SIZE);
return 0;
}
- s->s3->tmp.message_size = l;
+ s->s3.tmp.message_size = l;
s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH;
s->init_num = 0;
@@ -1263,14 +1273,14 @@ int tls_get_message_body(SSL *s, size_t *len)
unsigned char *p;
int i;
- if (s->s3->tmp.message_type == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ if (s->s3.tmp.message_type == SSL3_MT_CHANGE_CIPHER_SPEC) {
/* We've already read everything in */
*len = (unsigned long)s->init_num;
return 1;
}
p = s->init_msg;
- n = s->s3->tmp.message_size - s->init_num;
+ n = s->s3.tmp.message_size - s->init_num;
while (n > 0) {
i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
&p[s->init_num], n, 0, &readbytes);
@@ -1313,9 +1323,9 @@ int tls_get_message_body(SSL *s, size_t *len)
*/
#define SERVER_HELLO_RANDOM_OFFSET (SSL3_HM_HEADER_LENGTH + 2)
/* KeyUpdate and NewSessionTicket do not need to be added */
- if (!SSL_IS_TLS13(s) || (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET
- && s->s3->tmp.message_type != SSL3_MT_KEY_UPDATE)) {
- if (s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO
+ if (!SSL_IS_TLS13(s) || (s->s3.tmp.message_type != SSL3_MT_NEWSESSION_TICKET
+ && s->s3.tmp.message_type != SSL3_MT_KEY_UPDATE)) {
+ if (s->s3.tmp.message_type != SSL3_MT_SERVER_HELLO
|| s->init_num < SERVER_HELLO_RANDOM_OFFSET + SSL3_RANDOM_SIZE
|| memcmp(hrrrandom,
s->init_buf->data + SERVER_HELLO_RANDOM_OFFSET,
@@ -1418,7 +1428,7 @@ typedef struct {
const SSL_METHOD *(*smeth) (void);
} version_info;
-#if TLS_MAX_VERSION != TLS1_3_VERSION
+#if TLS_MAX_VERSION_INTERNAL != TLS1_3_VERSION
# error Code needs update for TLS_method() support beyond TLS1_3_VERSION.
#endif
@@ -1452,7 +1462,7 @@ static const version_info tls_version_table[] = {
{0, NULL, NULL},
};
-#if DTLS_MAX_VERSION != DTLS1_2_VERSION
+#if DTLS_MAX_VERSION_INTERNAL != DTLS1_2_VERSION
# error Code needs update for DTLS_method() support beyond DTLS1_2_VERSION.
#endif
@@ -1505,15 +1515,12 @@ static int ssl_method_error(const SSL *s, const SSL_METHOD *method)
/*
* Only called by servers. Returns 1 if the server has a TLSv1.3 capable
* certificate type, or has PSK or a certificate callback configured, or has
- * a servername callback configured. Otherwise returns 0.
+ * a servername callback configure. Otherwise returns 0.
*/
static int is_tls13_capable(const SSL *s)
{
int i;
-#ifndef OPENSSL_NO_EC
int curve;
- EC_KEY *eckey;
-#endif
if (!ossl_assert(s->ctx != NULL) || !ossl_assert(s->session_ctx != NULL))
return 0;
@@ -1547,7 +1554,6 @@ static int is_tls13_capable(const SSL *s)
}
if (!ssl_has_cert(s, i))
continue;
-#ifndef OPENSSL_NO_EC
if (i != SSL_PKEY_ECC)
return 1;
/*
@@ -1555,15 +1561,9 @@ static int is_tls13_capable(const SSL *s)
* more restrictive so check that our sig algs are consistent with this
* EC cert. See section 4.2.3 of RFC8446.
*/
- eckey = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey);
- if (eckey == NULL)
- continue;
- curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey));
+ curve = ssl_get_EC_curve_nid(s->cert->pkeys[SSL_PKEY_ECC].privatekey);
if (tls_check_sigalg_curve(s, curve))
return 1;
-#else
- return 1;
-#endif
}
return 0;
@@ -1676,9 +1676,9 @@ int ssl_set_version_bound(int method_version, int version, int *bound)
return 1;
}
- valid_tls = version >= SSL3_VERSION && version <= TLS_MAX_VERSION;
+ valid_tls = version >= SSL3_VERSION && version <= TLS_MAX_VERSION_INTERNAL;
valid_dtls =
- DTLS_VERSION_LE(version, DTLS_MAX_VERSION) &&
+ DTLS_VERSION_LE(version, DTLS_MAX_VERSION_INTERNAL) &&
DTLS_VERSION_GE(version, DTLS1_BAD_VER);
if (!valid_tls && !valid_dtls)
@@ -1751,7 +1751,7 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd)
* With version-flexible methods we have an initial state with:
*
* s->method->version == (D)TLS_ANY_VERSION,
- * s->version == (D)TLS_MAX_VERSION.
+ * s->version == (D)TLS_MAX_VERSION_INTERNAL.
*
* So we detect version-flexible methods via the method version, not the
* handle version.
@@ -1914,8 +1914,7 @@ int ssl_choose_client_version(SSL *s, int version, RAW_EXTENSION *extensions)
if (s->hello_retry_request != SSL_HRR_NONE
&& s->version != TLS1_3_VERSION) {
s->version = origv;
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION,
- SSL_R_WRONG_SSL_VERSION);
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_R_WRONG_SSL_VERSION);
return 0;
}
@@ -1923,9 +1922,7 @@ int ssl_choose_client_version(SSL *s, int version, RAW_EXTENSION *extensions)
default:
if (s->version != s->method->version) {
s->version = origv;
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_SSL_CHOOSE_CLIENT_VERSION,
- SSL_R_WRONG_SSL_VERSION);
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_R_WRONG_SSL_VERSION);
return 0;
}
/*
@@ -1947,21 +1944,18 @@ int ssl_choose_client_version(SSL *s, int version, RAW_EXTENSION *extensions)
ret = ssl_get_min_max_version(s, &ver_min, &ver_max, &real_max);
if (ret != 0) {
s->version = origv;
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_SSL_CHOOSE_CLIENT_VERSION, ret);
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION, ret);
return 0;
}
if (SSL_IS_DTLS(s) ? DTLS_VERSION_LT(s->version, ver_min)
: s->version < ver_min) {
s->version = origv;
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_SSL_CHOOSE_CLIENT_VERSION, SSL_R_UNSUPPORTED_PROTOCOL);
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_R_UNSUPPORTED_PROTOCOL);
return 0;
} else if (SSL_IS_DTLS(s) ? DTLS_VERSION_GT(s->version, ver_max)
: s->version > ver_max) {
s->version = origv;
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_SSL_CHOOSE_CLIENT_VERSION, SSL_R_UNSUPPORTED_PROTOCOL);
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_R_UNSUPPORTED_PROTOCOL);
return 0;
}
@@ -1971,12 +1965,11 @@ int ssl_choose_client_version(SSL *s, int version, RAW_EXTENSION *extensions)
/* Check for downgrades */
if (s->version == TLS1_2_VERSION && real_max > s->version) {
if (memcmp(tls12downgrade,
- s->s3->server_random + SSL3_RANDOM_SIZE
+ s->s3.server_random + SSL3_RANDOM_SIZE
- sizeof(tls12downgrade),
sizeof(tls12downgrade)) == 0) {
s->version = origv;
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_SSL_CHOOSE_CLIENT_VERSION,
SSL_R_INAPPROPRIATE_FALLBACK);
return 0;
}
@@ -1984,12 +1977,11 @@ int ssl_choose_client_version(SSL *s, int version, RAW_EXTENSION *extensions)
&& s->version < TLS1_2_VERSION
&& real_max > s->version) {
if (memcmp(tls11downgrade,
- s->s3->server_random + SSL3_RANDOM_SIZE
+ s->s3.server_random + SSL3_RANDOM_SIZE
- sizeof(tls11downgrade),
sizeof(tls11downgrade)) == 0) {
s->version = origv;
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_SSL_CHOOSE_CLIENT_VERSION,
SSL_R_INAPPROPRIATE_FALLBACK);
return 0;
}
@@ -2004,8 +1996,7 @@ int ssl_choose_client_version(SSL *s, int version, RAW_EXTENSION *extensions)
}
s->version = origv;
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION,
- SSL_R_UNSUPPORTED_PROTOCOL);
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_R_UNSUPPORTED_PROTOCOL);
return 0;
}
@@ -2170,7 +2161,6 @@ int ssl_set_client_hello_version(SSL *s)
* used. Returns 1 if the group is in the list (and allowed if |checkallow| is
* 1) or 0 otherwise.
*/
-#ifndef OPENSSL_NO_EC
int check_in_list(SSL *s, uint16_t group_id, const uint16_t *groups,
size_t num_groups, int checkallow)
{
@@ -2184,14 +2174,13 @@ int check_in_list(SSL *s, uint16_t group_id, const uint16_t *groups,
if (group_id == group
&& (!checkallow
- || tls_curve_allowed(s, group, SSL_SECOP_CURVE_CHECK))) {
+ || tls_group_allowed(s, group, SSL_SECOP_CURVE_CHECK))) {
return 1;
}
}
return 0;
}
-#endif
/* Replace ClientHello1 in the transcript hash with a synthetic message */
int create_synthetic_message_hash(SSL *s, const unsigned char *hashval,
@@ -2238,7 +2227,7 @@ int create_synthetic_message_hash(SSL *s, const unsigned char *hashval,
if (hrr != NULL
&& (!ssl3_finish_mac(s, hrr, hrrlen)
|| !ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
- s->s3->tmp.message_size
+ s->s3.tmp.message_size
+ SSL3_HM_HEADER_LENGTH))) {
/* SSLfatal() already called */
return 0;
@@ -2259,14 +2248,12 @@ int parse_ca_names(SSL *s, PACKET *pkt)
PACKET cadns;
if (ca_sk == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_PARSE_CA_NAMES,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
/* get the CA RDNs */
if (!PACKET_get_length_prefixed_2(pkt, &cadns)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,SSL_F_PARSE_CA_NAMES,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
@@ -2276,33 +2263,29 @@ int parse_ca_names(SSL *s, PACKET *pkt)
if (!PACKET_get_net_2(&cadns, &name_len)
|| !PACKET_get_bytes(&cadns, &namebytes, name_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
namestart = namebytes;
if ((xn = d2i_X509_NAME(NULL, &namebytes, name_len)) == NULL) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
- ERR_R_ASN1_LIB);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_ASN1_LIB);
goto err;
}
if (namebytes != (namestart + name_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
- SSL_R_CA_DN_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_CA_DN_LENGTH_MISMATCH);
goto err;
}
if (!sk_X509_NAME_push(ca_sk, xn)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_PARSE_CA_NAMES,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
xn = NULL;
}
- sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free);
- s->s3->tmp.peer_ca_names = ca_sk;
+ sk_X509_NAME_pop_free(s->s3.tmp.peer_ca_names, X509_NAME_free);
+ s->s3.tmp.peer_ca_names = ca_sk;
return 1;
@@ -2332,12 +2315,11 @@ int construct_ca_names(SSL *s, const STACK_OF(X509_NAME) *ca_sk, WPACKET *pkt)
{
/* Start sub-packet for client CA list */
if (!WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
- if (ca_sk != NULL) {
+ if ((ca_sk != NULL) && !(s->options & SSL_OP_DISABLE_TLSEXT_CA_NAMES)) {
int i;
for (i = 0; i < sk_X509_NAME_num(ca_sk); i++) {
@@ -2350,16 +2332,14 @@ int construct_ca_names(SSL *s, const STACK_OF(X509_NAME) *ca_sk, WPACKET *pkt)
|| !WPACKET_sub_allocate_bytes_u16(pkt, namelen,
&namebytes)
|| i2d_X509_NAME(name, &namebytes) != namelen) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
}
if (!WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -2374,12 +2354,11 @@ size_t construct_key_exchange_tbs(SSL *s, unsigned char **ptbs,
unsigned char *tbs = OPENSSL_malloc(tbslen);
if (tbs == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
- memcpy(tbs, s->s3->client_random, SSL3_RANDOM_SIZE);
- memcpy(tbs + SSL3_RANDOM_SIZE, s->s3->server_random, SSL3_RANDOM_SIZE);
+ memcpy(tbs, s->s3.client_random, SSL3_RANDOM_SIZE);
+ memcpy(tbs + SSL3_RANDOM_SIZE, s->s3.server_random, SSL3_RANDOM_SIZE);
memcpy(tbs + SSL3_RANDOM_SIZE * 2, param, paramlen);
@@ -2400,16 +2379,12 @@ int tls13_save_handshake_digest_for_pha(SSL *s)
s->pha_dgst = EVP_MD_CTX_new();
if (s->pha_dgst == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!EVP_MD_CTX_copy_ex(s->pha_dgst,
- s->s3->handshake_dgst)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA,
- ERR_R_INTERNAL_ERROR);
+ s->s3.handshake_dgst)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
EVP_MD_CTX_free(s->pha_dgst);
s->pha_dgst = NULL;
return 0;
@@ -2425,16 +2400,12 @@ int tls13_save_handshake_digest_for_pha(SSL *s)
int tls13_restore_handshake_digest_for_pha(SSL *s)
{
if (s->pha_dgst == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
- if (!EVP_MD_CTX_copy_ex(s->s3->handshake_dgst,
+ if (!EVP_MD_CTX_copy_ex(s->s3.handshake_dgst,
s->pha_dgst)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
diff --git a/ssl/statem/statem_local.h b/ssl/statem/statem_local.h
index eae88053dcd7..ad4d93b1e279 100644
--- a/ssl/statem/statem_local.h
+++ b/ssl/statem/statem_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -19,7 +19,6 @@
/* The spec allows for a longer length than this, but we limit it */
#define HELLO_VERIFY_REQUEST_MAX_LENGTH 258
#define END_OF_EARLY_DATA_MAX_LENGTH 0
-#define SERVER_HELLO_MAX_LENGTH 20000
#define HELLO_RETRY_REQUEST_MAX_LENGTH 20000
#define ENCRYPTED_EXTENSIONS_MAX_LENGTH 20000
#define SESSION_TICKET_MAX_LENGTH_TLS13 131338
@@ -28,12 +27,21 @@
#define SERVER_HELLO_DONE_MAX_LENGTH 0
#define KEY_UPDATE_MAX_LENGTH 1
#define CCS_MAX_LENGTH 1
+
+/* Max ServerHello size permitted by RFC 8446 */
+#define SERVER_HELLO_MAX_LENGTH 65607
+
/* Max should actually be 36 but we are generous */
#define FINISHED_MAX_LENGTH 64
/* Dummy message type */
#define SSL3_MT_DUMMY -1
+/* Invalid extension ID for non-supported extensions */
+#define TLSEXT_TYPE_invalid 0x10000
+#define TLSEXT_TYPE_out_of_range 0x10001
+unsigned int ossl_get_extension_type(size_t idx);
+
extern const unsigned char hrrrandom[];
/* Message processing return codes */
@@ -94,7 +102,8 @@ WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst);
/* Functions for getting new message data */
__owur int tls_get_message_header(SSL *s, int *mt);
__owur int tls_get_message_body(SSL *s, size_t *len);
-__owur int dtls_get_message(SSL *s, int *mt, size_t *len);
+__owur int dtls_get_message(SSL *s, int *mt);
+__owur int dtls_get_message_body(SSL *s, size_t *len);
/* Message construction and processing functions */
__owur int tls_process_initial_server_flight(SSL *s);
@@ -128,6 +137,7 @@ __owur int tls_construct_cert_status_body(SSL *s, WPACKET *pkt);
__owur int tls_construct_cert_status(SSL *s, WPACKET *pkt);
__owur MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt);
__owur MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt);
+__owur WORK_STATE tls_post_process_server_certificate(SSL *s, WORK_STATE wst);
__owur int ssl3_check_cert_and_algorithm(SSL *s);
#ifndef OPENSSL_NO_NEXTPROTONEG
__owur int tls_construct_next_proto(SSL *s, WPACKET *pkt);
@@ -155,6 +165,11 @@ __owur MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt);
__owur int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt);
MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt);
+#ifndef OPENSSL_NO_GOST
+/* These functions are used in GOST18 CKE, both for client and server */
+int ossl_gost18_cke_cipher_nid(const SSL *s);
+int ossl_gost_ukm(const SSL *s, unsigned char *dgst_buf);
+#endif
/* Extension processing */
@@ -198,12 +213,10 @@ int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
#endif
int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
-#ifndef OPENSSL_NO_EC
int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidxl);
-#endif
int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
int tls_parse_ctos_sig_algs_cert(SSL *s, PACKET *pkt, unsigned int context,
@@ -251,11 +264,9 @@ EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
-#ifndef OPENSSL_NO_EC
EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
-#endif
EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
@@ -312,14 +323,13 @@ EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt, unsigned int
EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
#endif
-#ifndef OPENSSL_NO_EC
EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
EXT_RETURN tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
-#endif
+
EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
@@ -379,10 +389,8 @@ int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
-#ifndef OPENSSL_NO_EC
int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
-#endif
int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
#ifndef OPENSSL_NO_OCSP
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index 43f77a58992f..a9e67f9d32a7 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -3,7 +3,7 @@
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -18,11 +18,13 @@
#include <openssl/rand.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
-#include <openssl/hmac.h>
#include <openssl/x509.h>
#include <openssl/dh.h>
+#include <openssl/rsa.h>
#include <openssl/bn.h>
#include <openssl/md5.h>
+#include <openssl/trace.h>
+#include <openssl/core_names.h>
#include <openssl/asn1t.h>
#define TICKET_NONCE_SIZE 8
@@ -83,7 +85,7 @@ static int ossl_statem_server13_read_transition(SSL *s, int mt)
case TLS_ST_SR_END_OF_EARLY_DATA:
case TLS_ST_SW_FINISHED:
- if (s->s3->tmp.cert_request) {
+ if (s->s3.tmp.cert_request) {
if (mt == SSL3_MT_CERTIFICATE) {
st->hand_state = TLS_ST_SR_CERT;
return 1;
@@ -186,7 +188,7 @@ int ossl_statem_server_read_transition(SSL *s, int mt)
* list if we requested a certificate)
*/
if (mt == SSL3_MT_CLIENT_KEY_EXCHANGE) {
- if (s->s3->tmp.cert_request) {
+ if (s->s3.tmp.cert_request) {
if (s->version == SSL3_VERSION) {
if ((s->verify_mode & SSL_VERIFY_PEER)
&& (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
@@ -196,7 +198,6 @@ int ossl_statem_server_read_transition(SSL *s, int mt)
* cert.
*/
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
return 0;
}
@@ -207,7 +208,7 @@ int ossl_statem_server_read_transition(SSL *s, int mt)
st->hand_state = TLS_ST_SR_KEY_EXCH;
return 1;
}
- } else if (s->s3->tmp.cert_request) {
+ } else if (s->s3.tmp.cert_request) {
if (mt == SSL3_MT_CERTIFICATE) {
st->hand_state = TLS_ST_SR_CERT;
return 1;
@@ -259,7 +260,7 @@ int ossl_statem_server_read_transition(SSL *s, int mt)
case TLS_ST_SR_CHANGE:
#ifndef OPENSSL_NO_NEXTPROTONEG
- if (s->s3->npn_seen) {
+ if (s->s3.npn_seen) {
if (mt == SSL3_MT_NEXT_PROTO) {
st->hand_state = TLS_ST_SR_NEXT_PROTO;
return 1;
@@ -308,9 +309,7 @@ int ossl_statem_server_read_transition(SSL *s, int mt)
BIO_set_retry_read(rbio);
return 0;
}
- SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE,
- SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
- SSL_R_UNEXPECTED_MESSAGE);
+ SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
return 0;
}
@@ -323,7 +322,7 @@ int ossl_statem_server_read_transition(SSL *s, int mt)
*/
static int send_server_key_exchange(SSL *s)
{
- unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ unsigned long alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
/*
* only send a ServerKeyExchange if DH or fortezza but we have a
@@ -385,7 +384,7 @@ int send_certificate_request(SSL *s)
* section "Certificate request" in SSL 3 drafts and in
* RFC 2246):
*/
- && (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
+ && (!(s->s3.tmp.new_cipher->algorithm_auth & SSL_aNULL)
/*
* ... except when the application insists on
* verification (against the specs, but statem_clnt.c accepts
@@ -393,12 +392,12 @@ int send_certificate_request(SSL *s)
*/
|| (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
/* don't request certificate for SRP auth */
- && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aSRP)
+ && !(s->s3.tmp.new_cipher->algorithm_auth & SSL_aSRP)
/*
* With normal PSK Certificates and Certificate Requests
* are omitted
*/
- && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK)) {
+ && !(s->s3.tmp.new_cipher->algorithm_auth & SSL_aPSK)) {
return 1;
}
@@ -422,9 +421,7 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
switch (st->hand_state) {
default:
/* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WRITE_TRAN_ERROR;
case TLS_ST_OK:
@@ -436,6 +433,10 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
st->hand_state = TLS_ST_SW_CERT_REQ;
return WRITE_TRAN_CONTINUE;
}
+ if (s->ext.extra_tickets_expected > 0) {
+ st->hand_state = TLS_ST_SW_SESSION_TICKET;
+ return WRITE_TRAN_CONTINUE;
+ }
/* Try to read from the client instead */
return WRITE_TRAN_FINISHED;
@@ -526,7 +527,9 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
* Following an initial handshake we send the number of tickets we have
* been configured for.
*/
- if (s->hit || s->num_tickets <= s->sent_tickets) {
+ if (!SSL_IS_FIRST_HANDSHAKE(s) && s->ext.extra_tickets_expected > 0) {
+ return WRITE_TRAN_CONTINUE;
+ } else if (s->hit || s->num_tickets <= s->sent_tickets) {
/* We've written enough tickets out. */
st->hand_state = TLS_ST_OK;
}
@@ -553,9 +556,7 @@ WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
switch (st->hand_state) {
default:
/* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WRITE_TRAN_ERROR;
case TLS_ST_OK:
@@ -605,7 +606,7 @@ WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
} else {
/* Check if it is anon DH or anon ECDH, */
/* normal PSK or SRP */
- if (!(s->s3->tmp.new_cipher->algorithm_auth &
+ if (!(s->s3.tmp.new_cipher->algorithm_auth &
(SSL_aNULL | SSL_aSRP | SSL_aPSK))) {
st->hand_state = TLS_ST_SW_CERT;
} else if (send_server_key_exchange(s)) {
@@ -722,7 +723,8 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
return WORK_FINISHED_CONTINUE;
case TLS_ST_SW_SESSION_TICKET:
- if (SSL_IS_TLS13(s) && s->sent_tickets == 0) {
+ if (SSL_IS_TLS13(s) && s->sent_tickets == 0
+ && s->ext.extra_tickets_expected == 0) {
/*
* Actually this is the end of the handshake, but we're going
* straight into writing the session ticket out. So we finish off
@@ -731,7 +733,8 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
* Calls SSLfatal as required.
*/
return tls_finish_handshake(s, wst, 0, 0);
- } if (SSL_IS_DTLS(s)) {
+ }
+ if (SSL_IS_DTLS(s)) {
/*
* We're into the last flight. We don't retransmit the last flight
* unless we need to, so we don't use the timer
@@ -745,11 +748,9 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
break;
/* Writes to s->session are only safe for initial handshakes */
if (s->session->cipher == NULL) {
- s->session->cipher = s->s3->tmp.new_cipher;
- } else if (s->session->cipher != s->s3->tmp.new_cipher) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_SERVER_PRE_WORK,
- ERR_R_INTERNAL_ERROR);
+ s->session->cipher = s->s3.tmp.new_cipher;
+ } else if (s->session->cipher != s->s3.tmp.new_cipher) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
if (!s->method->ssl3_enc->setup_key_block(s)) {
@@ -769,7 +770,7 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
case TLS_ST_EARLY_DATA:
if (s->early_data_state != SSL_EARLY_DATA_ACCEPTING
- && (s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
+ && (s->s3.flags & TLS1_FLAGS_STATELESS) == 0)
return WORK_FINISHED_CONTINUE;
/* Fall through */
@@ -869,9 +870,7 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
sizeof(sctpauthkey), labelbuffer,
labellen, NULL, 0,
0) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_SERVER_POST_WORK,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
@@ -1023,9 +1022,7 @@ int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt,
switch (st->hand_state) {
default:
/* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE,
- SSL_R_BAD_HANDSHAKE_STATE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_HANDSHAKE_STATE);
return 0;
case TLS_ST_SW_CHANGE:
@@ -1186,9 +1183,7 @@ MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt)
switch (st->hand_state) {
default:
/* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
case TLS_ST_SR_CLNT_HELLO:
@@ -1234,9 +1229,7 @@ WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst)
switch (st->hand_state) {
default:
/* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
case TLS_ST_SR_CLNT_HELLO:
@@ -1254,7 +1247,7 @@ static int ssl_check_srp_ext_ClientHello(SSL *s)
int ret;
int al = SSL_AD_UNRECOGNIZED_NAME;
- if ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) &&
+ if ((s->s3.tmp.new_cipher->algorithm_mkey & SSL_kSRP) &&
(s->srp_ctx.TLS_ext_srp_username_callback != NULL)) {
if (s->srp_ctx.login == NULL) {
/*
@@ -1262,15 +1255,14 @@ static int ssl_check_srp_ext_ClientHello(SSL *s)
* login name
*/
SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY,
- SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO,
SSL_R_PSK_IDENTITY_NOT_FOUND);
return -1;
} else {
- ret = SSL_srp_server_param_with_username(s, &al);
+ ret = ssl_srp_server_param_with_username_intern(s, &al);
if (ret < 0)
return 0;
if (ret == SSL3_AL_FATAL) {
- SSLfatal(s, al, SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO,
+ SSLfatal(s, al,
al == SSL_AD_UNKNOWN_PSK_IDENTITY
? SSL_R_PSK_IDENTITY_NOT_FOUND
: SSL_R_CLIENTHELLO_TLSEXT);
@@ -1299,24 +1291,21 @@ int dtls_construct_hello_verify_request(SSL *s, WPACKET *pkt)
if (s->ctx->app_gen_cookie_cb == NULL ||
s->ctx->app_gen_cookie_cb(s, s->d1->cookie,
&cookie_leni) == 0 ||
- cookie_leni > 255) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST,
- SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
+ cookie_leni > DTLS1_COOKIE_LENGTH) {
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
return 0;
}
s->d1->cookie_len = cookie_leni;
if (!dtls_raw_hello_verify_request(pkt, s->d1->cookie,
s->d1->cookie_len)) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_NO_ALERT, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
-#ifndef OPENSSL_NO_EC
/*-
* ssl_check_for_safari attempts to fingerprint Safari using OS X
* SecureTransport using the TLS extension block in |hello|.
@@ -1375,10 +1364,13 @@ static void ssl_check_for_safari(SSL *s, const CLIENTHELLO_MSG *hello)
ext_len = TLS1_get_client_version(s) >= TLS1_2_VERSION ?
sizeof(kSafariExtensionsBlock) : kSafariCommonExtensionsLength;
- s->s3->is_probably_safari = PACKET_equal(&tmppkt, kSafariExtensionsBlock,
+ s->s3.is_probably_safari = PACKET_equal(&tmppkt, kSafariExtensionsBlock,
ext_len);
}
-#endif /* !OPENSSL_NO_EC */
+
+#define RENEG_OPTIONS_OK(options) \
+ ((options & SSL_OP_NO_RENEGOTIATION) == 0 \
+ && (options & SSL_OP_ALLOW_CLIENT_RENEGOTIATION) != 0)
MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
{
@@ -1390,12 +1382,11 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
/* Check if this is actually an unexpected renegotiation ClientHello */
if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) {
if (!ossl_assert(!SSL_IS_TLS13(s))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- if ((s->options & SSL_OP_NO_RENEGOTIATION) != 0
- || (!s->s3->send_connection_binding
+ if (!RENEG_OPTIONS_OK(s->options)
+ || (!s->s3.send_connection_binding
&& (s->options
& SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) == 0)) {
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
@@ -1407,8 +1398,7 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
clienthello = OPENSSL_zalloc(sizeof(*clienthello));
if (clienthello == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -1423,8 +1413,7 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
if (!SSL_IS_FIRST_HANDSHAKE(s)
|| s->hello_retry_request != SSL_HRR_NONE) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNEXPECTED_MESSAGE);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
goto err;
}
@@ -1450,15 +1439,13 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
* layer in order to have determined that this is a SSLv2 record
* in the first place
*/
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (!PACKET_get_net_2(pkt, &clienthello->legacy_version)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- SSL_R_LENGTH_TOO_SHORT);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
goto err;
}
@@ -1475,14 +1462,12 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
if (!PACKET_get_net_2(pkt, &ciphersuite_len)
|| !PACKET_get_net_2(pkt, &session_id_len)
|| !PACKET_get_net_2(pkt, &challenge_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- SSL_R_RECORD_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_RECORD_LENGTH_MISMATCH);
goto err;
}
if (session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_LENGTH_MISMATCH);
goto err;
}
@@ -1492,8 +1477,7 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
|| !PACKET_get_sub_packet(pkt, &challenge, challenge_len)
/* No extensions. */
|| PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- SSL_R_RECORD_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_RECORD_LENGTH_MISMATCH);
goto err;
}
clienthello->session_id_len = session_id_len;
@@ -1511,8 +1495,7 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
challenge_len, challenge_len)
/* Advertise only null compression. */
|| !PACKET_buf_init(&compression, &null_compression, 1)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -1524,22 +1507,19 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
|| !PACKET_copy_all(&session_id, clienthello->session_id,
SSL_MAX_SSL_SESSION_ID_LENGTH,
&clienthello->session_id_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
if (SSL_IS_DTLS(s)) {
if (!PACKET_get_length_prefixed_1(pkt, &cookie)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
if (!PACKET_copy_all(&cookie, clienthello->dtls_cookie,
DTLS1_COOKIE_LENGTH,
&clienthello->dtls_cookie_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
/*
@@ -1556,14 +1536,12 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
}
if (!PACKET_get_length_prefixed_2(pkt, &clienthello->ciphersuites)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
if (!PACKET_get_length_prefixed_1(pkt, &compression)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
@@ -1573,8 +1551,7 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
} else {
if (!PACKET_get_length_prefixed_2(pkt, &clienthello->extensions)
|| PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
}
@@ -1583,8 +1560,7 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
if (!PACKET_copy_all(&compression, clienthello->compressions,
MAX_COMPRESSIONS_SIZE,
&clienthello->compressions_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -1636,15 +1612,13 @@ static int tls_early_post_process_client_hello(SSL *s)
return -1;
case SSL_CLIENT_HELLO_ERROR:
default:
- SSLfatal(s, al,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_CALLBACK_FAILED);
+ SSLfatal(s, al, SSL_R_CALLBACK_FAILED);
goto err;
}
}
/* Set up the client_random */
- memcpy(s->s3->client_random, clienthello->random, SSL3_RANDOM_SIZE);
+ memcpy(s->s3.client_random, clienthello->random, SSL3_RANDOM_SIZE);
/* Choose the version */
@@ -1656,9 +1630,7 @@ static int tls_early_post_process_client_hello(SSL *s)
* This is real SSLv2 or something completely unknown. We don't
* support it.
*/
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_UNKNOWN_PROTOCOL);
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_R_UNKNOWN_PROTOCOL);
goto err;
}
/* SSLv3/TLS */
@@ -1682,16 +1654,13 @@ static int tls_early_post_process_client_hello(SSL *s)
/* like ssl3_get_record, send alert using remote version number */
s->version = s->client_version = clienthello->legacy_version;
}
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr);
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION, protverr);
goto err;
}
/* TLSv1.3 specifies that a ClientHello must end on a record boundary */
if (SSL_IS_TLS13(s) && RECORD_LAYER_processed_read_pending(&s->rlayer)) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_NOT_ON_RECORD_BOUNDARY);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_NOT_ON_RECORD_BOUNDARY);
goto err;
}
@@ -1702,7 +1671,6 @@ static int tls_early_post_process_client_hello(SSL *s)
if (s->ctx->app_verify_cookie_cb(s, clienthello->dtls_cookie,
clienthello->dtls_cookie_len) == 0) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_COOKIE_MISMATCH);
goto err;
/* else cookie verification succeeded */
@@ -1711,9 +1679,7 @@ static int tls_early_post_process_client_hello(SSL *s)
} else if (s->d1->cookie_len != clienthello->dtls_cookie_len
|| memcmp(clienthello->dtls_cookie, s->d1->cookie,
s->d1->cookie_len) != 0) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_COOKIE_MISMATCH);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_COOKIE_MISMATCH);
goto err;
}
s->d1->cookie_verified = 1;
@@ -1722,8 +1688,7 @@ static int tls_early_post_process_client_hello(SSL *s)
protverr = ssl_choose_server_version(s, clienthello, &dgrd);
if (protverr != 0) {
s->version = s->client_version;
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr);
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION, protverr);
goto err;
}
}
@@ -1739,7 +1704,7 @@ static int tls_early_post_process_client_hello(SSL *s)
goto err;
}
- s->s3->send_connection_binding = 0;
+ s->s3.send_connection_binding = 0;
/* Check what signalling cipher-suite values were received. */
if (scsvs != NULL) {
for(i = 0; i < sk_SSL_CIPHER_num(scsvs); i++) {
@@ -1748,11 +1713,10 @@ static int tls_early_post_process_client_hello(SSL *s)
if (s->renegotiate) {
/* SCSV is fatal if renegotiating */
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
goto err;
}
- s->s3->send_connection_binding = 1;
+ s->s3.send_connection_binding = 1;
} else if (SSL_CIPHER_get_id(c) == SSL3_CK_FALLBACK_SCSV &&
!ssl_check_version_downgrade(s)) {
/*
@@ -1763,7 +1727,6 @@ static int tls_early_post_process_client_hello(SSL *s)
* an insecure downgrade.
*/
SSLfatal(s, SSL_AD_INAPPROPRIATE_FALLBACK,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_INAPPROPRIATE_FALLBACK);
goto err;
}
@@ -1776,24 +1739,20 @@ static int tls_early_post_process_client_hello(SSL *s)
ssl3_choose_cipher(s, ciphers, SSL_get_ciphers(s));
if (cipher == NULL) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_NO_SHARED_CIPHER);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_NO_SHARED_CIPHER);
goto err;
}
if (s->hello_retry_request == SSL_HRR_PENDING
- && (s->s3->tmp.new_cipher == NULL
- || s->s3->tmp.new_cipher->id != cipher->id)) {
+ && (s->s3.tmp.new_cipher == NULL
+ || s->s3.tmp.new_cipher->id != cipher->id)) {
/*
* A previous HRR picked a different ciphersuite to the one we
* just selected. Something must have changed.
*/
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_BAD_CIPHER);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_CIPHER);
goto err;
}
- s->s3->tmp.new_cipher = cipher;
+ s->s3.tmp.new_cipher = cipher;
}
/* We need to do this before getting the session */
@@ -1806,7 +1765,7 @@ static int tls_early_post_process_client_hello(SSL *s)
/*
* We don't allow resumption in a backwards compatible ClientHello.
- * TODO(openssl-team): in TLS1.1+, session_id MUST be empty.
+ * In TLS1.1+, session_id MUST be empty.
*
* Versions before 0.9.7 always allow clients to resume sessions in
* renegotiation. 0.9.7 and later allow this by default, but optionally
@@ -1858,15 +1817,15 @@ static int tls_early_post_process_client_hello(SSL *s)
j = 0;
id = s->session->cipher->id;
-#ifdef CIPHER_DEBUG
- fprintf(stderr, "client sent %d ciphers\n", sk_SSL_CIPHER_num(ciphers));
-#endif
+ OSSL_TRACE_BEGIN(TLS_CIPHER) {
+ BIO_printf(trc_out, "client sent %d ciphers\n",
+ sk_SSL_CIPHER_num(ciphers));
+ }
for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
c = sk_SSL_CIPHER_value(ciphers, i);
-#ifdef CIPHER_DEBUG
- fprintf(stderr, "client [%2d of %2d]:%s\n",
- i, sk_SSL_CIPHER_num(ciphers), SSL_CIPHER_get_name(c));
-#endif
+ if (trc_out != NULL)
+ BIO_printf(trc_out, "client [%2d of %2d]:%s\n", i,
+ sk_SSL_CIPHER_num(ciphers), SSL_CIPHER_get_name(c));
if (c->id == id) {
j = 1;
break;
@@ -1878,10 +1837,11 @@ static int tls_early_post_process_client_hello(SSL *s)
* to reuse it
*/
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_REQUIRED_CIPHER_MISSING);
+ OSSL_TRACE_CANCEL(TLS_CIPHER);
goto err;
}
+ OSSL_TRACE_END(TLS_CIPHER);
}
for (loop = 0; loop < clienthello->compressions_len; loop++) {
@@ -1891,16 +1851,12 @@ static int tls_early_post_process_client_hello(SSL *s)
if (loop >= clienthello->compressions_len) {
/* no compress */
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_NO_COMPRESSION_SPECIFIED);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_NO_COMPRESSION_SPECIFIED);
goto err;
}
-#ifndef OPENSSL_NO_EC
if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
ssl_check_for_safari(s, clienthello);
-#endif /* !OPENSSL_NO_EC */
/* TLS extensions */
if (!tls_parse_all_extensions(s, SSL_EXT_CLIENT_HELLO,
@@ -1917,11 +1873,9 @@ static int tls_early_post_process_client_hello(SSL *s)
*/
{
unsigned char *pos;
- pos = s->s3->server_random;
+ pos = s->s3.server_random;
if (ssl_fill_hello_random(s, 1, pos, SSL3_RANDOM_SIZE, dgrd) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
}
@@ -1956,9 +1910,7 @@ static int tls_early_post_process_client_hello(SSL *s)
pref_cipher = ssl3_choose_cipher(s, s->peer_ciphers,
SSL_get_ciphers(s));
if (pref_cipher == NULL) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_NO_SHARED_CIPHER);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_NO_SHARED_CIPHER);
goto err;
}
@@ -1975,7 +1927,7 @@ static int tls_early_post_process_client_hello(SSL *s)
* options, we will now look for them. We have complen-1 compression
* algorithms from the client, starting at q.
*/
- s->s3->tmp.new_compression = NULL;
+ s->s3.tmp.new_compression = NULL;
if (SSL_IS_TLS13(s)) {
/*
* We already checked above that the NULL compression method appears in
@@ -1984,7 +1936,6 @@ static int tls_early_post_process_client_hello(SSL *s)
*/
if (clienthello->compressions_len != 1) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_INVALID_COMPRESSION_ALGORITHM);
goto err;
}
@@ -1998,7 +1949,6 @@ static int tls_early_post_process_client_hello(SSL *s)
/* Can't disable compression */
if (!ssl_allow_compression(s)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_INCONSISTENT_COMPRESSION);
goto err;
}
@@ -2006,13 +1956,12 @@ static int tls_early_post_process_client_hello(SSL *s)
for (m = 0; m < sk_SSL_COMP_num(s->ctx->comp_methods); m++) {
comp = sk_SSL_COMP_value(s->ctx->comp_methods, m);
if (comp_id == comp->id) {
- s->s3->tmp.new_compression = comp;
+ s->s3.tmp.new_compression = comp;
break;
}
}
- if (s->s3->tmp.new_compression == NULL) {
+ if (s->s3.tmp.new_compression == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_INVALID_COMPRESSION_ALGORITHM);
goto err;
}
@@ -2023,7 +1972,6 @@ static int tls_early_post_process_client_hello(SSL *s)
}
if (k >= clienthello->compressions_len) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING);
goto err;
}
@@ -2048,7 +1996,7 @@ static int tls_early_post_process_client_hello(SSL *s)
break;
}
if (done)
- s->s3->tmp.new_compression = comp;
+ s->s3.tmp.new_compression = comp;
else
comp = NULL;
}
@@ -2058,9 +2006,7 @@ static int tls_early_post_process_client_hello(SSL *s)
* using compression.
*/
if (s->session->compress_meth != 0) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_INCONSISTENT_COMPRESSION);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_INCONSISTENT_COMPRESSION);
goto err;
}
#endif
@@ -2073,9 +2019,7 @@ static int tls_early_post_process_client_hello(SSL *s)
sk_SSL_CIPHER_free(s->peer_ciphers);
s->peer_ciphers = ciphers;
if (ciphers == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
ciphers = NULL;
@@ -2128,12 +2072,12 @@ static int tls_handle_status_request(SSL *s)
int ret;
/* If no certificate can't return certificate status */
- if (s->s3->tmp.cert != NULL) {
+ if (s->s3.tmp.cert != NULL) {
/*
* Set current certificate to one we will use so SSL_get_certificate
* et al can pick it up.
*/
- s->cert->key = s->s3->tmp.cert;
+ s->cert->key = s->s3.tmp.cert;
ret = s->ctx->ext.status_cb(s, s->ctx->ext.status_arg);
switch (ret) {
/* We don't want to send a status request response */
@@ -2148,9 +2092,7 @@ static int tls_handle_status_request(SSL *s)
/* something bad happened */
case SSL_TLSEXT_ERR_ALERT_FATAL:
default:
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_HANDLE_STATUS_REQUEST,
- SSL_R_CLIENTHELLO_TLSEXT);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CLIENTHELLO_TLSEXT);
return 0;
}
}
@@ -2168,25 +2110,24 @@ int tls_handle_alpn(SSL *s)
const unsigned char *selected = NULL;
unsigned char selected_len = 0;
- if (s->ctx->ext.alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) {
+ if (s->ctx->ext.alpn_select_cb != NULL && s->s3.alpn_proposed != NULL) {
int r = s->ctx->ext.alpn_select_cb(s, &selected, &selected_len,
- s->s3->alpn_proposed,
- (unsigned int)s->s3->alpn_proposed_len,
+ s->s3.alpn_proposed,
+ (unsigned int)s->s3.alpn_proposed_len,
s->ctx->ext.alpn_select_cb_arg);
if (r == SSL_TLSEXT_ERR_OK) {
- OPENSSL_free(s->s3->alpn_selected);
- s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len);
- if (s->s3->alpn_selected == NULL) {
- s->s3->alpn_selected_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_HANDLE_ALPN,
- ERR_R_INTERNAL_ERROR);
+ OPENSSL_free(s->s3.alpn_selected);
+ s->s3.alpn_selected = OPENSSL_memdup(selected, selected_len);
+ if (s->s3.alpn_selected == NULL) {
+ s->s3.alpn_selected_len = 0;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
- s->s3->alpn_selected_len = selected_len;
+ s->s3.alpn_selected_len = selected_len;
#ifndef OPENSSL_NO_NEXTPROTONEG
/* ALPN takes precedence over NPN. */
- s->s3->npn_seen = 0;
+ s->s3.npn_seen = 0;
#endif
/* Check ALPN is consistent with session */
@@ -2205,7 +2146,6 @@ int tls_handle_alpn(SSL *s)
*/
if (!ossl_assert(s->session->ext.alpn_selected == NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_HANDLE_ALPN,
ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -2213,7 +2153,6 @@ int tls_handle_alpn(SSL *s)
selected_len);
if (s->session->ext.alpn_selected == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_HANDLE_ALPN,
ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -2223,7 +2162,7 @@ int tls_handle_alpn(SSL *s)
return 1;
} else if (r != SSL_TLSEXT_ERR_NOACK) {
- SSLfatal(s, SSL_AD_NO_APPLICATION_PROTOCOL, SSL_F_TLS_HANDLE_ALPN,
+ SSLfatal(s, SSL_AD_NO_APPLICATION_PROTOCOL,
SSL_R_NO_APPLICATION_PROTOCOL);
return 0;
}
@@ -2262,9 +2201,7 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
if (!s->hit && s->cert->cert_cb != NULL) {
int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg);
if (rv == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
- SSL_R_CERT_CB_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CERT_CB_ERROR);
goto err;
}
if (rv < 0) {
@@ -2281,11 +2218,10 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
if (cipher == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
SSL_R_NO_SHARED_CIPHER);
goto err;
}
- s->s3->tmp.new_cipher = cipher;
+ s->s3.tmp.new_cipher = cipher;
}
if (!s->hit) {
if (!tls_choose_sigalg(s, 1)) {
@@ -2296,7 +2232,7 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
if (s->not_resumable_session_cb != NULL)
s->session->not_resumable =
s->not_resumable_session_cb(s,
- ((s->s3->tmp.new_cipher->algorithm_mkey
+ ((s->s3.tmp.new_cipher->algorithm_mkey
& (SSL_kDHE | SSL_kECDHE)) != 0));
if (s->session->not_resumable)
/* do not send a session ticket */
@@ -2304,7 +2240,7 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
}
} else {
/* Session-id reuse */
- s->s3->tmp.new_cipher = s->session->cipher;
+ s->s3.tmp.new_cipher = s->session->cipher;
}
/*-
@@ -2316,7 +2252,7 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
* ssl version is set - sslv3
* s->session - The ssl session has been setup.
* s->hit - session reuse flag
- * s->s3->tmp.new_cipher- the new cipher to use.
+ * s->s3.tmp.new_cipher - the new cipher to use.
*/
/*
@@ -2378,10 +2314,9 @@ int tls_construct_server_hello(SSL *s, WPACKET *pkt)
*/
|| !WPACKET_memcpy(pkt,
s->hello_retry_request == SSL_HRR_PENDING
- ? hrrrandom : s->s3->server_random,
+ ? hrrrandom : s->s3.server_random,
SSL3_RANDOM_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -2417,8 +2352,7 @@ int tls_construct_server_hello(SSL *s, WPACKET *pkt)
}
if (sl > sizeof(s->session->session_id)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -2426,17 +2360,16 @@ int tls_construct_server_hello(SSL *s, WPACKET *pkt)
#ifdef OPENSSL_NO_COMP
compm = 0;
#else
- if (usetls13 || s->s3->tmp.new_compression == NULL)
+ if (usetls13 || s->s3.tmp.new_compression == NULL)
compm = 0;
else
- compm = s->s3->tmp.new_compression->id;
+ compm = s->s3.tmp.new_compression->id;
#endif
if (!WPACKET_sub_memcpy_u8(pkt, session_id, sl)
- || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt, &len)
+ || !s->method->put_cipher_by_char(s->s3.tmp.new_cipher, pkt, &len)
|| !WPACKET_put_bytes_u8(pkt, compm)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -2476,7 +2409,7 @@ int tls_construct_server_hello(SSL *s, WPACKET *pkt)
int tls_construct_server_done(SSL *s, WPACKET *pkt)
{
- if (!s->s3->tmp.cert_request) {
+ if (!s->s3.tmp.cert_request) {
if (!ssl3_digest_cached_records(s, 0)) {
/* SSLfatal() already called */
return 0;
@@ -2487,35 +2420,30 @@ int tls_construct_server_done(SSL *s, WPACKET *pkt)
int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
{
-#ifndef OPENSSL_NO_DH
EVP_PKEY *pkdh = NULL;
-#endif
-#ifndef OPENSSL_NO_EC
unsigned char *encodedPoint = NULL;
size_t encodedlen = 0;
int curve_id = 0;
-#endif
- const SIGALG_LOOKUP *lu = s->s3->tmp.sigalg;
+ const SIGALG_LOOKUP *lu = s->s3.tmp.sigalg;
int i;
unsigned long type;
- const BIGNUM *r[4];
+ BIGNUM *r[4];
EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
EVP_PKEY_CTX *pctx = NULL;
size_t paramlen, paramoffset;
+ int freer = 0, ret = 0;
if (!WPACKET_get_total_written(pkt, &paramoffset)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (md_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
- type = s->s3->tmp.new_cipher->algorithm_mkey;
+ type = s->s3.tmp.new_cipher->algorithm_mkey;
r[0] = r[1] = r[2] = r[3] = NULL;
#ifndef OPENSSL_NO_PSK
@@ -2523,87 +2451,68 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
if (type & (SSL_kPSK | SSL_kRSAPSK)) {
} else
#endif /* !OPENSSL_NO_PSK */
-#ifndef OPENSSL_NO_DH
if (type & (SSL_kDHE | SSL_kDHEPSK)) {
CERT *cert = s->cert;
-
EVP_PKEY *pkdhp = NULL;
- DH *dh;
if (s->cert->dh_tmp_auto) {
- DH *dhp = ssl_get_auto_dh(s);
- pkdh = EVP_PKEY_new();
- if (pkdh == NULL || dhp == NULL) {
- DH_free(dhp);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ pkdh = ssl_get_auto_dh(s);
+ if (pkdh == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- EVP_PKEY_assign_DH(pkdh, dhp);
pkdhp = pkdh;
} else {
pkdhp = cert->dh_tmp;
}
+#if !defined(OPENSSL_NO_DEPRECATED_3_0)
if ((pkdhp == NULL) && (s->cert->dh_tmp_cb != NULL)) {
- DH *dhp = s->cert->dh_tmp_cb(s, 0, 1024);
- pkdh = ssl_dh_to_pkey(dhp);
+ pkdh = ssl_dh_to_pkey(s->cert->dh_tmp_cb(s, 0, 1024));
if (pkdh == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
pkdhp = pkdh;
}
+#endif
if (pkdhp == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- SSL_R_MISSING_TMP_DH_KEY);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_MISSING_TMP_DH_KEY);
goto err;
}
if (!ssl_security(s, SSL_SECOP_TMP_DH,
- EVP_PKEY_security_bits(pkdhp), 0, pkdhp)) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- SSL_R_DH_KEY_TOO_SMALL);
+ EVP_PKEY_get_security_bits(pkdhp), 0, pkdhp)) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_DH_KEY_TOO_SMALL);
goto err;
}
- if (s->s3->tmp.pkey != NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- s->s3->tmp.pkey = ssl_generate_pkey(pkdhp);
- if (s->s3->tmp.pkey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, 0, ERR_R_INTERNAL_ERROR);
+ if (s->s3.tmp.pkey != NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- dh = EVP_PKEY_get0_DH(s->s3->tmp.pkey);
- if (dh == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ s->s3.tmp.pkey = ssl_generate_pkey(s, pkdhp);
+ if (s->s3.tmp.pkey == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
EVP_PKEY_free(pkdh);
pkdh = NULL;
- DH_get0_pqg(dh, &r[0], NULL, &r[1]);
- DH_get0_key(dh, &r[2], NULL);
- } else
-#endif
-#ifndef OPENSSL_NO_EC
- if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
+ /* These BIGNUMs need to be freed when we're finished */
+ freer = 1;
+ if (!EVP_PKEY_get_bn_param(s->s3.tmp.pkey, OSSL_PKEY_PARAM_FFC_P,
+ &r[0])
+ || !EVP_PKEY_get_bn_param(s->s3.tmp.pkey, OSSL_PKEY_PARAM_FFC_G,
+ &r[1])
+ || !EVP_PKEY_get_bn_param(s->s3.tmp.pkey,
+ OSSL_PKEY_PARAM_PUB_KEY, &r[2])) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ } else if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
- if (s->s3->tmp.pkey != NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ if (s->s3.tmp.pkey != NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -2611,23 +2520,23 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
curve_id = tls1_shared_group(s, -2);
if (curve_id == 0) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
goto err;
}
- s->s3->tmp.pkey = ssl_generate_pkey_group(s, curve_id);
+ /* Cache the group used in the SSL_SESSION */
+ s->session->kex_group = curve_id;
/* Generate a new key for this curve */
- if (s->s3->tmp.pkey == NULL) {
+ s->s3.tmp.pkey = ssl_generate_pkey_group(s, curve_id);
+ if (s->s3.tmp.pkey == NULL) {
/* SSLfatal() already called */
goto err;
}
/* Encode the public key. */
- encodedlen = EVP_PKEY_get1_tls_encodedpoint(s->s3->tmp.pkey,
- &encodedPoint);
+ encodedlen = EVP_PKEY_get1_encoded_public_key(s->s3.tmp.pkey,
+ &encodedPoint);
if (encodedlen == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EC_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EC_LIB);
goto err;
}
@@ -2640,15 +2549,12 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
r[2] = NULL;
r[3] = NULL;
} else
-#endif /* !OPENSSL_NO_EC */
#ifndef OPENSSL_NO_SRP
if (type & SSL_kSRP) {
if ((s->srp_ctx.N == NULL) ||
(s->srp_ctx.g == NULL) ||
(s->srp_ctx.s == NULL) || (s->srp_ctx.B == NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- SSL_R_MISSING_SRP_PARAM);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_MISSING_SRP_PARAM);
goto err;
}
r[0] = s->srp_ctx.N;
@@ -2658,18 +2564,15 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
} else
#endif
{
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
goto err;
}
- if (((s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) != 0)
- || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)) != 0) {
+ if (((s->s3.tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) != 0)
+ || ((s->s3.tmp.new_cipher->algorithm_mkey & SSL_PSK)) != 0) {
lu = NULL;
} else if (lu == NULL) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -2685,9 +2588,7 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
if (len > PSK_MAX_IDENTITY_LEN
|| !WPACKET_sub_memcpy_u16(pkt, s->cert->psk_identity_hint,
len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
}
@@ -2705,13 +2606,10 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
res = WPACKET_start_sub_packet_u16(pkt);
if (!res) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
-#ifndef OPENSSL_NO_DH
/*-
* for interoperability with some versions of the Microsoft TLS
* stack, we need to zero pad the DHE pub key to the same length
@@ -2722,27 +2620,22 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
if (len > 0) {
if (!WPACKET_allocate_bytes(pkt, len, &binval)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
memset(binval, 0, len);
}
}
-#endif
+
if (!WPACKET_allocate_bytes(pkt, BN_num_bytes(r[i]), &binval)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
BN_bn2bin(r[i], binval);
}
-#ifndef OPENSSL_NO_EC
if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
/*
* We only support named (not generic) curves. In this situation, the
@@ -2754,65 +2647,47 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
|| !WPACKET_put_bytes_u8(pkt, 0)
|| !WPACKET_put_bytes_u8(pkt, curve_id)
|| !WPACKET_sub_memcpy_u8(pkt, encodedPoint, encodedlen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
OPENSSL_free(encodedPoint);
encodedPoint = NULL;
}
-#endif
/* not anonymous */
if (lu != NULL) {
- EVP_PKEY *pkey = s->s3->tmp.cert->privatekey;
+ EVP_PKEY *pkey = s->s3.tmp.cert->privatekey;
const EVP_MD *md;
unsigned char *sigbytes1, *sigbytes2, *tbs;
- size_t siglen, tbslen;
- int rv;
+ size_t siglen = 0, tbslen;
- if (pkey == NULL || !tls1_lookup_md(lu, &md)) {
+ if (pkey == NULL || !tls1_lookup_md(s->ctx, lu, &md)) {
/* Should never happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
/* Get length of the parameters we have written above */
if (!WPACKET_get_length(pkt, &paramlen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
/* send signature algorithm */
if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- /*
- * Create the signature. We don't know the actual length of the sig
- * until after we've created it, so we reserve enough bytes for it
- * up front, and then properly allocate them in the WPACKET
- * afterwards.
- */
- siglen = EVP_PKEY_size(pkey);
- if (!WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1)
- || EVP_DigestSignInit(md_ctx, &pctx, md, NULL, pkey) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+
+ if (EVP_DigestSignInit_ex(md_ctx, &pctx,
+ md == NULL ? NULL : EVP_MD_get0_name(md),
+ s->ctx->libctx, s->ctx->propq, pkey,
+ NULL) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (lu->sig == EVP_PKEY_RSA_PSS) {
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
|| EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, RSA_PSS_SALTLEN_DIGEST) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_EVP_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
}
@@ -2823,28 +2698,31 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
/* SSLfatal() already called */
goto err;
}
- rv = EVP_DigestSign(md_ctx, sigbytes1, &siglen, tbs, tbslen);
- OPENSSL_free(tbs);
- if (rv <= 0 || !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2)
- || sigbytes1 != sigbytes2) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+
+ if (EVP_DigestSign(md_ctx, NULL, &siglen, tbs, tbslen) <=0
+ || !WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1)
+ || EVP_DigestSign(md_ctx, sigbytes1, &siglen, tbs, tbslen) <= 0
+ || !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2)
+ || sigbytes1 != sigbytes2) {
+ OPENSSL_free(tbs);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
+ OPENSSL_free(tbs);
}
- EVP_MD_CTX_free(md_ctx);
- return 1;
+ ret = 1;
err:
-#ifndef OPENSSL_NO_DH
EVP_PKEY_free(pkdh);
-#endif
-#ifndef OPENSSL_NO_EC
OPENSSL_free(encodedPoint);
-#endif
EVP_MD_CTX_free(md_ctx);
- return 0;
+ if (freer) {
+ BN_free(r[0]);
+ BN_free(r[1]);
+ BN_free(r[2]);
+ BN_free(r[3]);
+ }
+ return ret;
}
int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
@@ -2856,17 +2734,14 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
s->pha_context_len = 32;
if ((s->pha_context = OPENSSL_malloc(s->pha_context_len)) == NULL) {
s->pha_context_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
- if (RAND_bytes(s->pha_context, s->pha_context_len) <= 0
+ if (RAND_bytes_ex(s->ctx->libctx, s->pha_context,
+ s->pha_context_len, 0) <= 0
|| !WPACKET_sub_memcpy_u8(pkt, s->pha_context,
s->pha_context_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
/* reset the handshake hash back to just after the ClientFinished */
@@ -2876,9 +2751,7 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
}
} else {
if (!WPACKET_put_bytes_u8(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
@@ -2895,8 +2768,7 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
/* get the list of acceptable cert types */
if (!WPACKET_start_sub_packet_u8(pkt)
|| !ssl3_get_req_cert_type(s, pkt) || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -2908,9 +2780,7 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
|| !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)
|| !tls12_copy_sigalgs(s, pkt, psigs, nl)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
@@ -2922,7 +2792,7 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
done:
s->certreqs_sent++;
- s->s3->tmp.cert_request = 1;
+ s->s3.tmp.cert_request = 1;
return 1;
}
@@ -2934,24 +2804,20 @@ static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt)
PACKET psk_identity;
if (!PACKET_get_length_prefixed_2(pkt, &psk_identity)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
if (PACKET_remaining(&psk_identity) > PSK_MAX_IDENTITY_LEN) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
- SSL_R_DATA_LENGTH_TOO_LONG);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_DATA_LENGTH_TOO_LONG);
return 0;
}
if (s->psk_server_callback == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
- SSL_R_PSK_NO_SERVER_CB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_PSK_NO_SERVER_CB);
return 0;
}
if (!PACKET_strndup(&psk_identity, &s->session->psk_identity)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -2959,57 +2825,49 @@ static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt)
psk, sizeof(psk));
if (psklen > PSK_MAX_PSK_LEN) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
} else if (psklen == 0) {
/*
* PSK related to the given identity not found
*/
- SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY,
- SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
- SSL_R_PSK_IDENTITY_NOT_FOUND);
+ SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY, SSL_R_PSK_IDENTITY_NOT_FOUND);
return 0;
}
- OPENSSL_free(s->s3->tmp.psk);
- s->s3->tmp.psk = OPENSSL_memdup(psk, psklen);
+ OPENSSL_free(s->s3.tmp.psk);
+ s->s3.tmp.psk = OPENSSL_memdup(psk, psklen);
OPENSSL_cleanse(psk, psklen);
- if (s->s3->tmp.psk == NULL) {
- s->s3->tmp.psklen = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_MALLOC_FAILURE);
+ if (s->s3.tmp.psk == NULL) {
+ s->s3.tmp.psklen = 0;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
- s->s3->tmp.psklen = psklen;
+ s->s3.tmp.psklen = psklen;
return 1;
#else
/* Should never happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_process_cke_rsa(SSL *s, PACKET *pkt)
{
-#ifndef OPENSSL_NO_RSA
- unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
- int decrypt_len;
- unsigned char decrypt_good, version_good;
- size_t j, padding_len;
+ size_t outlen;
PACKET enc_premaster;
- RSA *rsa = NULL;
+ EVP_PKEY *rsa = NULL;
unsigned char *rsa_decrypt = NULL;
int ret = 0;
+ EVP_PKEY_CTX *ctx = NULL;
+ OSSL_PARAM params[3], *p = params;
- rsa = EVP_PKEY_get0_RSA(s->cert->pkeys[SSL_PKEY_RSA].privatekey);
+ rsa = s->cert->pkeys[SSL_PKEY_RSA].privatekey;
if (rsa == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
- SSL_R_MISSING_RSA_CERTIFICATE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_MISSING_RSA_CERTIFICATE);
return 0;
}
@@ -3019,136 +2877,70 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt)
} else {
if (!PACKET_get_length_prefixed_2(pkt, &enc_premaster)
|| PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
}
- /*
- * We want to be sure that the plaintext buffer size makes it safe to
- * iterate over the entire size of a premaster secret
- * (SSL_MAX_MASTER_KEY_LENGTH). Reject overly short RSA keys because
- * their ciphertext cannot accommodate a premaster secret anyway.
- */
- if (RSA_size(rsa) < SSL_MAX_MASTER_KEY_LENGTH) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
- RSA_R_KEY_SIZE_TOO_SMALL);
- return 0;
- }
-
- rsa_decrypt = OPENSSL_malloc(RSA_size(rsa));
+ outlen = SSL_MAX_MASTER_KEY_LENGTH;
+ rsa_decrypt = OPENSSL_malloc(outlen);
if (rsa_decrypt == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
- /*
- * We must not leak whether a decryption failure occurs because of
- * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246,
- * section 7.4.7.1). The code follows that advice of the TLS RFC and
- * generates a random premaster secret for the case that the decrypt
- * fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
- */
-
- if (RAND_priv_bytes(rand_premaster_secret,
- sizeof(rand_premaster_secret)) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
- ERR_R_INTERNAL_ERROR);
+ ctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, rsa, s->ctx->propq);
+ if (ctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
/*
- * Decrypt with no padding. PKCS#1 padding will be removed as part of
- * the timing-sensitive code below.
+ * We must not leak whether a decryption failure occurs because of
+ * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246,
+ * section 7.4.7.1). We use the special padding type
+ * RSA_PKCS1_WITH_TLS_PADDING to do that. It will automaticaly decrypt the
+ * RSA, check the padding and check that the client version is as expected
+ * in the premaster secret. If any of that fails then the function appears
+ * to return successfully but with a random result. The call below could
+ * still fail if the input is publicly invalid.
+ * See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
*/
- /* TODO(size_t): Convert this function */
- decrypt_len = (int)RSA_private_decrypt((int)PACKET_remaining(&enc_premaster),
- PACKET_data(&enc_premaster),
- rsa_decrypt, rsa, RSA_NO_PADDING);
- if (decrypt_len < 0) {
- SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
- ERR_R_INTERNAL_ERROR);
+ if (EVP_PKEY_decrypt_init(ctx) <= 0
+ || EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_WITH_TLS_PADDING) <= 0) {
+ SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
- /* Check the padding. See RFC 3447, section 7.2.2. */
+ *p++ = OSSL_PARAM_construct_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION,
+ (unsigned int *)&s->client_version);
+ if ((s->options & SSL_OP_TLS_ROLLBACK_BUG) != 0)
+ *p++ = OSSL_PARAM_construct_uint(
+ OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION,
+ (unsigned int *)&s->version);
+ *p++ = OSSL_PARAM_construct_end();
- /*
- * The smallest padded premaster is 11 bytes of overhead. Small keys
- * are publicly invalid, so this may return immediately. This ensures
- * PS is at least 8 bytes.
- */
- if (decrypt_len < 11 + SSL_MAX_MASTER_KEY_LENGTH) {
- SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
- SSL_R_DECRYPTION_FAILED);
+ if (!EVP_PKEY_CTX_set_params(ctx, params)
+ || EVP_PKEY_decrypt(ctx, rsa_decrypt, &outlen,
+ PACKET_data(&enc_premaster),
+ PACKET_remaining(&enc_premaster)) <= 0) {
+ SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
- padding_len = decrypt_len - SSL_MAX_MASTER_KEY_LENGTH;
- decrypt_good = constant_time_eq_int_8(rsa_decrypt[0], 0) &
- constant_time_eq_int_8(rsa_decrypt[1], 2);
- for (j = 2; j < padding_len - 1; j++) {
- decrypt_good &= ~constant_time_is_zero_8(rsa_decrypt[j]);
- }
- decrypt_good &= constant_time_is_zero_8(rsa_decrypt[padding_len - 1]);
-
/*
- * If the version in the decrypted pre-master secret is correct then
- * version_good will be 0xff, otherwise it'll be zero. The
- * Klima-Pokorny-Rosa extension of Bleichenbacher's attack
- * (http://eprint.iacr.org/2003/052/) exploits the version number
- * check as a "bad version oracle". Thus version checks are done in
- * constant time and are treated like any other decryption error.
+ * This test should never fail (otherwise we should have failed above) but
+ * we double check anyway.
*/
- version_good =
- constant_time_eq_8(rsa_decrypt[padding_len],
- (unsigned)(s->client_version >> 8));
- version_good &=
- constant_time_eq_8(rsa_decrypt[padding_len + 1],
- (unsigned)(s->client_version & 0xff));
-
- /*
- * The premaster secret must contain the same version number as the
- * ClientHello to detect version rollback attacks (strangely, the
- * protocol does not offer such protection for DH ciphersuites).
- * However, buggy clients exist that send the negotiated protocol
- * version instead if the server does not support the requested
- * protocol version. If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such
- * clients.
- */
- if (s->options & SSL_OP_TLS_ROLLBACK_BUG) {
- unsigned char workaround_good;
- workaround_good = constant_time_eq_8(rsa_decrypt[padding_len],
- (unsigned)(s->version >> 8));
- workaround_good &=
- constant_time_eq_8(rsa_decrypt[padding_len + 1],
- (unsigned)(s->version & 0xff));
- version_good |= workaround_good;
- }
-
- /*
- * Both decryption and version must be good for decrypt_good to
- * remain non-zero (0xff).
- */
- decrypt_good &= version_good;
-
- /*
- * Now copy rand_premaster_secret over from p using
- * decrypt_good_mask. If decryption failed, then p does not
- * contain valid plaintext, however, a check above guarantees
- * it is still sufficiently large to read from.
- */
- for (j = 0; j < sizeof(rand_premaster_secret); j++) {
- rsa_decrypt[padding_len + j] =
- constant_time_select_8(decrypt_good,
- rsa_decrypt[padding_len + j],
- rand_premaster_secret[j]);
+ if (outlen != SSL_MAX_MASTER_KEY_LENGTH) {
+ OPENSSL_cleanse(rsa_decrypt, SSL_MAX_MASTER_KEY_LENGTH);
+ SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_R_DECRYPTION_FAILED);
+ goto err;
}
- if (!ssl_generate_master_secret(s, rsa_decrypt + padding_len,
- sizeof(rand_premaster_secret), 0)) {
+ /* Also cleanses rsa_decrypt (on success or failure) */
+ if (!ssl_generate_master_secret(s, rsa_decrypt,
+ SSL_MAX_MASTER_KEY_LENGTH, 0)) {
/* SSLfatal() already called */
goto err;
}
@@ -3156,62 +2948,45 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt)
ret = 1;
err:
OPENSSL_free(rsa_decrypt);
+ EVP_PKEY_CTX_free(ctx);
return ret;
-#else
- /* Should never happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
}
static int tls_process_cke_dhe(SSL *s, PACKET *pkt)
{
-#ifndef OPENSSL_NO_DH
EVP_PKEY *skey = NULL;
- DH *cdh;
unsigned int i;
- BIGNUM *pub_key;
const unsigned char *data;
EVP_PKEY *ckey = NULL;
int ret = 0;
if (!PACKET_get_net_2(pkt, &i) || PACKET_remaining(pkt) != i) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
- SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
goto err;
}
- skey = s->s3->tmp.pkey;
+ skey = s->s3.tmp.pkey;
if (skey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
- SSL_R_MISSING_TMP_DH_KEY);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_MISSING_TMP_DH_KEY);
goto err;
}
if (PACKET_remaining(pkt) == 0L) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
- SSL_R_MISSING_TMP_DH_KEY);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_MISSING_TMP_DH_KEY);
goto err;
}
if (!PACKET_get_bytes(pkt, &data, i)) {
/* We already checked we have enough data */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
ckey = EVP_PKEY_new();
if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
- SSL_R_BN_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_COPY_PARAMETERS_FAILED);
goto err;
}
- cdh = EVP_PKEY_get0_DH(ckey);
- pub_key = BN_bin2bn(data, i, NULL);
- if (pub_key == NULL || cdh == NULL || !DH_set0_key(cdh, pub_key, NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
- ERR_R_INTERNAL_ERROR);
- BN_free(pub_key);
+ if (!EVP_PKEY_set1_encoded_public_key(ckey, data, i)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -3221,30 +2996,22 @@ static int tls_process_cke_dhe(SSL *s, PACKET *pkt)
}
ret = 1;
- EVP_PKEY_free(s->s3->tmp.pkey);
- s->s3->tmp.pkey = NULL;
+ EVP_PKEY_free(s->s3.tmp.pkey);
+ s->s3.tmp.pkey = NULL;
err:
EVP_PKEY_free(ckey);
return ret;
-#else
- /* Should never happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
}
static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt)
{
-#ifndef OPENSSL_NO_EC
- EVP_PKEY *skey = s->s3->tmp.pkey;
+ EVP_PKEY *skey = s->s3.tmp.pkey;
EVP_PKEY *ckey = NULL;
int ret = 0;
if (PACKET_remaining(pkt) == 0L) {
/* We don't support ECDH client auth */
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_CKE_ECDHE,
- SSL_R_MISSING_TMP_ECDH_KEY);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_MISSING_TMP_ECDH_KEY);
goto err;
} else {
unsigned int i;
@@ -3258,25 +3025,22 @@ static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt)
/* Get encoded point length */
if (!PACKET_get_1(pkt, &i) || !PACKET_get_bytes(pkt, &data, i)
|| PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
if (skey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
- SSL_R_MISSING_TMP_ECDH_KEY);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_MISSING_TMP_ECDH_KEY);
goto err;
}
ckey = EVP_PKEY_new();
if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
- ERR_R_EVP_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_COPY_PARAMETERS_FAILED);
goto err;
}
- if (EVP_PKEY_set1_tls_encodedpoint(ckey, data, i) == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
- ERR_R_EC_LIB);
+
+ if (EVP_PKEY_set1_encoded_public_key(ckey, data, i) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EC_LIB);
goto err;
}
}
@@ -3287,18 +3051,12 @@ static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt)
}
ret = 1;
- EVP_PKEY_free(s->s3->tmp.pkey);
- s->s3->tmp.pkey = NULL;
+ EVP_PKEY_free(s->s3.tmp.pkey);
+ s->s3.tmp.pkey = NULL;
err:
EVP_PKEY_free(ckey);
return ret;
-#else
- /* Should never happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
}
static int tls_process_cke_srp(SSL *s, PACKET *pkt)
@@ -3309,25 +3067,21 @@ static int tls_process_cke_srp(SSL *s, PACKET *pkt)
if (!PACKET_get_net_2(pkt, &i)
|| !PACKET_get_bytes(pkt, &data, i)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
- SSL_R_BAD_SRP_A_LENGTH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_SRP_A_LENGTH);
return 0;
}
if ((s->srp_ctx.A = BN_bin2bn(data, i, NULL)) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
- ERR_R_BN_LIB);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_BN_LIB);
return 0;
}
if (BN_ucmp(s->srp_ctx.A, s->srp_ctx.N) >= 0 || BN_is_zero(s->srp_ctx.A)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_CKE_SRP,
- SSL_R_BAD_SRP_PARAMETERS);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_SRP_PARAMETERS);
return 0;
}
OPENSSL_free(s->session->srp_username);
s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
if (s->session->srp_username == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -3339,8 +3093,7 @@ static int tls_process_cke_srp(SSL *s, PACKET *pkt)
return 1;
#else
/* Should never happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
@@ -3359,7 +3112,7 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt)
int ret = 0;
/* Get our certificate private key */
- alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+ alg_a = s->s3.tmp.new_cipher->algorithm_auth;
if (alg_a & SSL_aGOST12) {
/*
* New GOST ciphersuites have SSL_aGOST01 bit too
@@ -3375,15 +3128,13 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt)
pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
}
- pkey_ctx = EVP_PKEY_CTX_new(pk, NULL);
+ pkey_ctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, pk, s->ctx->propq);
if (pkey_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
/*
@@ -3405,20 +3156,17 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt)
if (pKX == NULL
|| pKX->kxBlob == NULL
|| ASN1_TYPE_get(pKX->kxBlob) != V_ASN1_SEQUENCE) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
- SSL_R_DECRYPTION_FAILED);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
if (!PACKET_forward(pkt, ptr - PACKET_data(pkt))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
- SSL_R_DECRYPTION_FAILED);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
- SSL_R_DECRYPTION_FAILED);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
@@ -3427,8 +3175,7 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt)
if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start,
inlen) <= 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
- SSL_R_DECRYPTION_FAILED);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
/* Generate master secret */
@@ -3449,8 +3196,85 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt)
return ret;
#else
/* Should never happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_process_cke_gost18(SSL *s, PACKET *pkt)
+{
+#ifndef OPENSSL_NO_GOST
+ unsigned char rnd_dgst[32];
+ EVP_PKEY_CTX *pkey_ctx = NULL;
+ EVP_PKEY *pk = NULL;
+ unsigned char premaster_secret[32];
+ const unsigned char *start = NULL;
+ size_t outlen = 32, inlen = 0;
+ int ret = 0;
+ int cipher_nid = ossl_gost18_cke_cipher_nid(s);
+
+ if (cipher_nid == NID_undef) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (ossl_gost_ukm(s, rnd_dgst) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Get our certificate private key */
+ pk = s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey != NULL ?
+ s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey :
+ s->cert->pkeys[SSL_PKEY_GOST12_256].privatekey;
+ if (pk == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_HANDSHAKE_STATE);
+ goto err;
+ }
+
+ pkey_ctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, pk, s->ctx->propq);
+ if (pkey_ctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Reuse EVP_PKEY_CTRL_SET_IV, make choice in engine code depending on size */
+ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_DECRYPT,
+ EVP_PKEY_CTRL_SET_IV, 32, rnd_dgst) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_LIBRARY_BUG);
+ goto err;
+ }
+
+ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_DECRYPT,
+ EVP_PKEY_CTRL_CIPHER, cipher_nid, NULL) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_LIBRARY_BUG);
+ goto err;
+ }
+ inlen = PACKET_remaining(pkt);
+ start = PACKET_data(pkt);
+
+ if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start, inlen) <= 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_DECRYPTION_FAILED);
+ goto err;
+ }
+ /* Generate master secret */
+ if (!ssl_generate_master_secret(s, premaster_secret,
+ sizeof(premaster_secret), 0)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ ret = 1;
+
+ err:
+ EVP_PKEY_CTX_free(pkey_ctx);
+ return ret;
+#else
+ /* Should never happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
@@ -3459,7 +3283,7 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
{
unsigned long alg_k;
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
/* For PSK parse and retrieve identity, obtain PSK key */
if ((alg_k & SSL_PSK) && !tls_process_cke_psk_preamble(s, pkt)) {
@@ -3470,9 +3294,7 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
if (alg_k & SSL_kPSK) {
/* Identity extracted earlier: should be nothing left */
if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
/* PSK handled by ssl_generate_master_secret */
@@ -3505,19 +3327,22 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
/* SSLfatal() already called */
goto err;
}
+ } else if (alg_k & SSL_kGOST18) {
+ if (!tls_process_cke_gost18(s, pkt)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
} else {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
- SSL_R_UNKNOWN_CIPHER_TYPE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_UNKNOWN_CIPHER_TYPE);
goto err;
}
return MSG_PROCESS_CONTINUE_PROCESSING;
err:
#ifndef OPENSSL_NO_PSK
- OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
- s->s3->tmp.psk = NULL;
- s->s3->tmp.psklen = 0;
+ OPENSSL_clear_free(s->s3.tmp.psk, s->s3.tmp.psklen);
+ s->s3.tmp.psk = NULL;
+ s->s3.tmp.psklen = 0;
#endif
return MSG_PROCESS_ERROR;
}
@@ -3546,9 +3371,7 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
sizeof(sctpauthkey), labelbuffer,
labellen, NULL, 0,
0) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
@@ -3569,10 +3392,8 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
}
return WORK_FINISHED_CONTINUE;
} else {
- if (!s->s3->handshake_buffer) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ if (!s->s3.handshake_buffer) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
/*
@@ -3608,8 +3429,7 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
s->statem.enc_read_state = ENC_READ_STATE_VALID;
if ((sk = sk_X509_new_null()) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -3617,38 +3437,36 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
|| (s->pha_context == NULL && PACKET_remaining(&context) != 0)
|| (s->pha_context != NULL &&
!PACKET_equal(&context, s->pha_context, s->pha_context_len)))) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- SSL_R_INVALID_CONTEXT);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_INVALID_CONTEXT);
goto err;
}
if (!PACKET_get_length_prefixed_3(pkt, &spkt)
|| PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
for (chainidx = 0; PACKET_remaining(&spkt) > 0; chainidx++) {
if (!PACKET_get_net_3(&spkt, &l)
|| !PACKET_get_bytes(&spkt, &certbytes, l)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- SSL_R_CERT_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_CERT_LENGTH_MISMATCH);
goto err;
}
certstart = certbytes;
- x = d2i_X509(NULL, (const unsigned char **)&certbytes, l);
+ x = X509_new_ex(s->ctx->libctx, s->ctx->propq);
if (x == NULL) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_ASN1_LIB);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (d2i_X509(&x, (const unsigned char **)&certbytes, l) == NULL) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_ASN1_LIB);
goto err;
}
+
if (certbytes != (certstart + l)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- SSL_R_CERT_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_CERT_LENGTH_MISMATCH);
goto err;
}
@@ -3657,9 +3475,7 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
PACKET extensions;
if (!PACKET_get_length_prefixed_2(&spkt, &extensions)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- SSL_R_BAD_LENGTH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_LENGTH);
goto err;
}
if (!tls_collect_extensions(s, &extensions,
@@ -3675,9 +3491,7 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
}
if (!sk_X509_push(sk, x)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
x = NULL;
@@ -3687,7 +3501,6 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
/* TLS does not mind 0 certs returned */
if (s->version == SSL3_VERSION) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
SSL_R_NO_CERTIFICATES_RETURNED);
goto err;
}
@@ -3695,12 +3508,11 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
else if ((s->verify_mode & SSL_VERIFY_PEER) &&
(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
SSLfatal(s, SSL_AD_CERTIFICATE_REQUIRED,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
goto err;
}
/* No client certificate so digest cached records */
- if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, 0)) {
+ if (s->s3.handshake_buffer && !ssl3_digest_cached_records(s, 0)) {
/* SSLfatal() already called */
goto err;
}
@@ -3709,19 +3521,12 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
i = ssl_verify_cert_chain(s, sk);
if (i <= 0) {
SSLfatal(s, ssl_x509err2alert(s->verify_result),
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
SSL_R_CERTIFICATE_VERIFY_FAILED);
goto err;
}
- if (i > 1) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, i);
- goto err;
- }
pkey = X509_get0_pubkey(sk_X509_value(sk, 0));
if (pkey == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
SSL_R_UNKNOWN_CERTIFICATE_TYPE);
goto err;
}
@@ -3737,9 +3542,7 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -3792,11 +3595,10 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
int tls_construct_server_certificate(SSL *s, WPACKET *pkt)
{
- CERT_PKEY *cpk = s->s3->tmp.cert;
+ CERT_PKEY *cpk = s->s3.tmp.cert;
if (cpk == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -3805,8 +3607,7 @@ int tls_construct_server_certificate(SSL *s, WPACKET *pkt)
* for the server Certificate message
*/
if (SSL_IS_TLS13(s) && !WPACKET_put_bytes_u8(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!ssl3_output_cert_chain(s, pkt, cpk)) {
@@ -3838,45 +3639,46 @@ static int create_ticket_prequel(SSL *s, WPACKET *pkt, uint32_t age_add,
timeout = 0;
if (!WPACKET_put_bytes_u32(pkt, timeout)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (SSL_IS_TLS13(s)) {
if (!WPACKET_put_bytes_u32(pkt, age_add)
|| !WPACKET_sub_memcpy_u8(pkt, tick_nonce, TICKET_NONCE_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
/* Start the sub-packet for the actual ticket data */
if (!WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
+/*
+ * Returns 1 on success, 0 to abort construction of the ticket (non-fatal), or
+ * -1 on fatal error
+ */
static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
unsigned char *tick_nonce)
{
unsigned char *senc = NULL;
EVP_CIPHER_CTX *ctx = NULL;
- HMAC_CTX *hctx = NULL;
+ SSL_HMAC *hctx = NULL;
unsigned char *p, *encdata1, *encdata2, *macdata1, *macdata2;
const unsigned char *const_p;
int len, slen_full, slen, lenfinal;
SSL_SESSION *sess;
- unsigned int hlen;
+ size_t hlen;
SSL_CTX *tctx = s->session_ctx;
unsigned char iv[EVP_MAX_IV_LENGTH];
unsigned char key_name[TLSEXT_KEYNAME_LENGTH];
- int iv_len, ok = 0;
+ int iv_len, ok = -1;
size_t macoffset, macendoffset;
/* get session encoding length */
@@ -3886,29 +3688,25 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
* long
*/
if (slen_full == 0 || slen_full > 0xFF00) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
senc = OPENSSL_malloc(slen_full);
if (senc == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
ctx = EVP_CIPHER_CTX_new();
- hctx = HMAC_CTX_new();
+ hctx = ssl_hmac_new(tctx);
if (ctx == NULL || hctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
p = senc;
if (!i2d_SSL_SESSION(s->session, &p)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -3918,23 +3716,20 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
const_p = senc;
sess = d2i_SSL_SESSION(NULL, &const_p, slen_full);
if (sess == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
slen = i2d_SSL_SESSION(sess, NULL);
if (slen == 0 || slen > slen_full) {
/* shouldn't ever happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
SSL_SESSION_free(sess);
goto err;
}
p = senc;
if (!i2d_SSL_SESSION(sess, &p)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
SSL_SESSION_free(sess);
goto err;
}
@@ -3944,46 +3739,78 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
* Initialize HMAC and cipher contexts. If callback present it does
* all the work otherwise use generated values from parent ctx.
*/
- if (tctx->ext.ticket_key_cb) {
- /* if 0 is returned, write an empty ticket */
- int ret = tctx->ext.ticket_key_cb(s, key_name, iv, ctx,
- hctx, 1);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (tctx->ext.ticket_key_evp_cb != NULL || tctx->ext.ticket_key_cb != NULL)
+#else
+ if (tctx->ext.ticket_key_evp_cb != NULL)
+#endif
+ {
+ int ret = 0;
+
+ if (tctx->ext.ticket_key_evp_cb != NULL)
+ ret = tctx->ext.ticket_key_evp_cb(s, key_name, iv, ctx,
+ ssl_hmac_get0_EVP_MAC_CTX(hctx),
+ 1);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ else if (tctx->ext.ticket_key_cb != NULL)
+ /* if 0 is returned, write an empty ticket */
+ ret = tctx->ext.ticket_key_cb(s, key_name, iv, ctx,
+ ssl_hmac_get0_HMAC_CTX(hctx), 1);
+#endif
if (ret == 0) {
-
+ /*
+ * In TLSv1.2 we construct a 0 length ticket. In TLSv1.3 a 0
+ * length ticket is not allowed so we abort construction of the
+ * ticket
+ */
+ if (SSL_IS_TLS13(s)) {
+ ok = 0;
+ goto err;
+ }
/* Put timeout and length */
if (!WPACKET_put_bytes_u32(pkt, 0)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
OPENSSL_free(senc);
EVP_CIPHER_CTX_free(ctx);
- HMAC_CTX_free(hctx);
+ ssl_hmac_free(hctx);
return 1;
}
if (ret < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- SSL_R_CALLBACK_FAILED);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CALLBACK_FAILED);
+ goto err;
+ }
+ iv_len = EVP_CIPHER_CTX_get_iv_length(ctx);
+ if (iv_len < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- iv_len = EVP_CIPHER_CTX_iv_length(ctx);
} else {
- const EVP_CIPHER *cipher = EVP_aes_256_cbc();
+ EVP_CIPHER *cipher = EVP_CIPHER_fetch(s->ctx->libctx, "AES-256-CBC",
+ s->ctx->propq);
- iv_len = EVP_CIPHER_iv_length(cipher);
- if (RAND_bytes(iv, iv_len) <= 0
+ if (cipher == NULL) {
+ /* Error is already recorded */
+ SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
+ goto err;
+ }
+
+ iv_len = EVP_CIPHER_get_iv_length(cipher);
+ if (iv_len < 0
+ || RAND_bytes_ex(s->ctx->libctx, iv, iv_len, 0) <= 0
|| !EVP_EncryptInit_ex(ctx, cipher, NULL,
tctx->ext.secure->tick_aes_key, iv)
- || !HMAC_Init_ex(hctx, tctx->ext.secure->tick_hmac_key,
- sizeof(tctx->ext.secure->tick_hmac_key),
- EVP_sha256(), NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_INTERNAL_ERROR);
+ || !ssl_hmac_init(hctx, tctx->ext.secure->tick_hmac_key,
+ sizeof(tctx->ext.secure->tick_hmac_key),
+ "SHA256")) {
+ EVP_CIPHER_free(cipher);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
+ EVP_CIPHER_free(cipher);
memcpy(key_name, tctx->ext.tick_key_name,
sizeof(tctx->ext.tick_key_name));
}
@@ -4009,23 +3836,21 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
|| encdata1 + len != encdata2
|| len + lenfinal > slen + EVP_MAX_BLOCK_LENGTH
|| !WPACKET_get_total_written(pkt, &macendoffset)
- || !HMAC_Update(hctx,
- (unsigned char *)s->init_buf->data + macoffset,
- macendoffset - macoffset)
+ || !ssl_hmac_update(hctx,
+ (unsigned char *)s->init_buf->data + macoffset,
+ macendoffset - macoffset)
|| !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &macdata1)
- || !HMAC_Final(hctx, macdata1, &hlen)
+ || !ssl_hmac_final(hctx, macdata1, &hlen, EVP_MAX_MD_SIZE)
|| hlen > EVP_MAX_MD_SIZE
|| !WPACKET_allocate_bytes(pkt, hlen, &macdata2)
|| macdata1 != macdata2) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
/* Close the sub-packet created by create_ticket_prequel() */
if (!WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -4033,7 +3858,7 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
err:
OPENSSL_free(senc);
EVP_CIPHER_CTX_free(ctx);
- HMAC_CTX_free(hctx);
+ ssl_hmac_free(hctx);
return ok;
}
@@ -4048,14 +3873,27 @@ static int construct_stateful_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
if (!WPACKET_memcpy(pkt, s->session->session_id,
s->session->session_id_length)
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATEFUL_TICKET,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
+static void tls_update_ticket_counts(SSL *s)
+{
+ /*
+ * Increment both |sent_tickets| and |next_ticket_nonce|. |sent_tickets|
+ * gets reset to 0 if we send more tickets following a post-handshake
+ * auth, but |next_ticket_nonce| does not. If we're sending extra
+ * tickets, decrement the count of pending extra tickets.
+ */
+ s->sent_tickets++;
+ s->next_ticket_nonce++;
+ if (s->ext.extra_tickets_expected > 0)
+ s->ext.extra_tickets_expected--;
+}
+
int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
{
SSL_CTX *tctx = s->session_ctx;
@@ -4064,6 +3902,7 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
unsigned char age_add_c[sizeof(uint32_t)];
uint32_t age_add;
} age_add_u;
+ int ret = 0;
age_add_u.age_add = 0;
@@ -4072,13 +3911,11 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
uint64_t nonce;
static const unsigned char nonce_label[] = "resumption";
const EVP_MD *md = ssl_handshake_md(s);
- int hashleni = EVP_MD_size(md);
+ int hashleni = EVP_MD_get_size(md);
/* Ensure cast to size_t is safe */
if (!ossl_assert(hashleni >= 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
hashlen = (size_t)hashleni;
@@ -4104,10 +3941,9 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
/* SSLfatal() already called */
goto err;
}
- if (RAND_bytes(age_add_u.age_add_c, sizeof(age_add_u)) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
- ERR_R_INTERNAL_ERROR);
+ if (RAND_bytes_ex(s->ctx->libctx, age_add_u.age_add_c,
+ sizeof(age_add_u), 0) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
s->session->ext.tick_age_add = age_add_u.age_add;
@@ -4130,28 +3966,25 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
}
s->session->master_key_length = hashlen;
- s->session->time = (long)time(NULL);
- if (s->s3->alpn_selected != NULL) {
+ s->session->time = time(NULL);
+ ssl_session_calculate_timeout(s->session);
+ if (s->s3.alpn_selected != NULL) {
OPENSSL_free(s->session->ext.alpn_selected);
s->session->ext.alpn_selected =
- OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len);
+ OPENSSL_memdup(s->s3.alpn_selected, s->s3.alpn_selected_len);
if (s->session->ext.alpn_selected == NULL) {
s->session->ext.alpn_selected_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
- s->session->ext.alpn_selected_len = s->s3->alpn_selected_len;
+ s->session->ext.alpn_selected_len = s->s3.alpn_selected_len;
}
s->session->ext.max_early_data = s->max_early_data;
}
if (tctx->generate_ticket_cb != NULL &&
tctx->generate_ticket_cb(s, tctx->ticket_cb_data) == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
/*
@@ -4167,10 +4000,20 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
/* SSLfatal() already called */
goto err;
}
- } else if (!construct_stateless_ticket(s, pkt, age_add_u.age_add,
- tick_nonce)) {
- /* SSLfatal() already called */
- goto err;
+ } else {
+ int tmpret;
+
+ tmpret = construct_stateless_ticket(s, pkt, age_add_u.age_add,
+ tick_nonce);
+ if (tmpret != 1) {
+ if (tmpret == 0) {
+ ret = 2; /* Non-fatal. Abort construction but continue */
+ /* We count this as a success so update the counts anwyay */
+ tls_update_ticket_counts(s);
+ }
+ /* else SSLfatal() already called */
+ goto err;
+ }
}
if (SSL_IS_TLS13(s)) {
@@ -4180,19 +4023,13 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
/* SSLfatal() already called */
goto err;
}
- /*
- * Increment both |sent_tickets| and |next_ticket_nonce|. |sent_tickets|
- * gets reset to 0 if we send more tickets following a post-handshake
- * auth, but |next_ticket_nonce| does not.
- */
- s->sent_tickets++;
- s->next_ticket_nonce++;
+ tls_update_ticket_counts(s);
ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
}
- return 1;
+ ret = 1;
err:
- return 0;
+ return ret;
}
/*
@@ -4204,8 +4041,7 @@ int tls_construct_cert_status_body(SSL *s, WPACKET *pkt)
if (!WPACKET_put_bytes_u8(pkt, s->ext.status_type)
|| !WPACKET_sub_memcpy_u24(pkt, s->ext.ocsp.resp,
s->ext.ocsp.resp_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -4242,15 +4078,13 @@ MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt)
if (!PACKET_get_length_prefixed_1(pkt, &next_proto)
|| !PACKET_get_length_prefixed_1(pkt, &padding)
|| PACKET_remaining(pkt) > 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEXT_PROTO,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
if (!PACKET_memdup(&next_proto, &s->ext.npn, &next_proto_len)) {
s->ext.npn_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEXT_PROTO,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
}
@@ -4274,15 +4108,13 @@ static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt)
MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt)
{
if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
- SSL_R_LENGTH_MISMATCH);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
if (s->early_data_state != SSL_EARLY_DATA_READING
&& s->early_data_state != SSL_EARLY_DATA_READ_RETRY) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
}
@@ -4291,9 +4123,7 @@ MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt)
* a record boundary.
*/
if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
- SSL_R_NOT_ON_RECORD_BOUNDARY);
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_NOT_ON_RECORD_BOUNDARY);
return MSG_PROCESS_ERROR;
}
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index f8e53d4efc79..91238e6457b8 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -2,7 +2,7 @@
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -10,10 +10,16 @@
#include <stdio.h>
#include "ssl_local.h"
+#include "record/record_local.h"
+#include "internal/ktls.h"
+#include "internal/cryptlib.h"
#include <openssl/comp.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include <openssl/rand.h>
+#include <openssl/obj_mac.h>
+#include <openssl/core_names.h>
+#include <openssl/trace.h>
/* seed1 through seed5 are concatenated */
static int tls1_PRF(SSL *s,
@@ -26,41 +32,55 @@ static int tls1_PRF(SSL *s,
unsigned char *out, size_t olen, int fatal)
{
const EVP_MD *md = ssl_prf_md(s);
- EVP_PKEY_CTX *pctx = NULL;
- int ret = 0;
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx = NULL;
+ OSSL_PARAM params[8], *p = params;
+ const char *mdname;
if (md == NULL) {
/* Should never happen */
if (fatal)
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_PRF,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
else
- SSLerr(SSL_F_TLS1_PRF, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
- pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL);
- if (pctx == NULL || EVP_PKEY_derive_init(pctx) <= 0
- || EVP_PKEY_CTX_set_tls1_prf_md(pctx, md) <= 0
- || EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, sec, (int)slen) <= 0
- || EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed1, (int)seed1_len) <= 0
- || EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed2, (int)seed2_len) <= 0
- || EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed3, (int)seed3_len) <= 0
- || EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed4, (int)seed4_len) <= 0
- || EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed5, (int)seed5_len) <= 0
- || EVP_PKEY_derive(pctx, out, &olen) <= 0) {
- if (fatal)
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_PRF,
- ERR_R_INTERNAL_ERROR);
- else
- SSLerr(SSL_F_TLS1_PRF, ERR_R_INTERNAL_ERROR);
+ kdf = EVP_KDF_fetch(s->ctx->libctx, OSSL_KDF_NAME_TLS1_PRF, s->ctx->propq);
+ if (kdf == NULL)
goto err;
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+ if (kctx == NULL)
+ goto err;
+ mdname = EVP_MD_get0_name(md);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ (char *)mdname, 0);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SECRET,
+ (unsigned char *)sec,
+ (size_t)slen);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED,
+ (void *)seed1, (size_t)seed1_len);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED,
+ (void *)seed2, (size_t)seed2_len);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED,
+ (void *)seed3, (size_t)seed3_len);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED,
+ (void *)seed4, (size_t)seed4_len);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED,
+ (void *)seed5, (size_t)seed5_len);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, out, olen, params)) {
+ EVP_KDF_CTX_free(kctx);
+ return 1;
}
- ret = 1;
-
err:
- EVP_PKEY_CTX_free(pctx);
- return ret;
+ if (fatal)
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ else
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
+ EVP_KDF_CTX_free(kctx);
+ return 0;
}
static int tls1_generate_key_block(SSL *s, unsigned char *km, size_t num)
@@ -70,14 +90,99 @@ static int tls1_generate_key_block(SSL *s, unsigned char *km, size_t num)
/* Calls SSLfatal() as required */
ret = tls1_PRF(s,
TLS_MD_KEY_EXPANSION_CONST,
- TLS_MD_KEY_EXPANSION_CONST_SIZE, s->s3->server_random,
- SSL3_RANDOM_SIZE, s->s3->client_random, SSL3_RANDOM_SIZE,
+ TLS_MD_KEY_EXPANSION_CONST_SIZE, s->s3.server_random,
+ SSL3_RANDOM_SIZE, s->s3.client_random, SSL3_RANDOM_SIZE,
NULL, 0, NULL, 0, s->session->master_key,
s->session->master_key_length, km, num, 1);
return ret;
}
+#ifndef OPENSSL_NO_KTLS
+ /*
+ * Count the number of records that were not processed yet from record boundary.
+ *
+ * This function assumes that there are only fully formed records read in the
+ * record layer. If read_ahead is enabled, then this might be false and this
+ * function will fail.
+ */
+# ifndef OPENSSL_NO_KTLS_RX
+static int count_unprocessed_records(SSL *s)
+{
+ SSL3_BUFFER *rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
+ PACKET pkt, subpkt;
+ int count = 0;
+
+ if (!PACKET_buf_init(&pkt, rbuf->buf + rbuf->offset, rbuf->left))
+ return -1;
+
+ while (PACKET_remaining(&pkt) > 0) {
+ /* Skip record type and version */
+ if (!PACKET_forward(&pkt, 3))
+ return -1;
+
+ /* Read until next record */
+ if (!PACKET_get_length_prefixed_2(&pkt, &subpkt))
+ return -1;
+
+ count += 1;
+ }
+
+ return count;
+}
+# endif
+#endif
+
+
+int tls_provider_set_tls_params(SSL *s, EVP_CIPHER_CTX *ctx,
+ const EVP_CIPHER *ciph,
+ const EVP_MD *md)
+{
+ /*
+ * Provided cipher, the TLS padding/MAC removal is performed provider
+ * side so we need to tell the ctx about our TLS version and mac size
+ */
+ OSSL_PARAM params[3], *pprm = params;
+ size_t macsize = 0;
+ int imacsize = -1;
+
+ if ((EVP_CIPHER_get_flags(ciph) & EVP_CIPH_FLAG_AEAD_CIPHER) == 0
+ /*
+ * We look at s->ext.use_etm instead of SSL_READ_ETM() or
+ * SSL_WRITE_ETM() because this test applies to both reading
+ * and writing.
+ */
+ && !s->ext.use_etm)
+ imacsize = EVP_MD_get_size(md);
+ if (imacsize >= 0)
+ macsize = (size_t)imacsize;
+
+ *pprm++ = OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_TLS_VERSION,
+ &s->version);
+ *pprm++ = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_TLS_MAC_SIZE,
+ &macsize);
+ *pprm = OSSL_PARAM_construct_end();
+
+ if (!EVP_CIPHER_CTX_set_params(ctx, params)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static int tls_iv_length_within_key_block(const EVP_CIPHER *c)
+{
+ /* If GCM/CCM mode only part of IV comes from PRF */
+ if (EVP_CIPHER_get_mode(c) == EVP_CIPH_GCM_MODE)
+ return EVP_GCM_TLS_FIXED_IV_LEN;
+ else if (EVP_CIPHER_get_mode(c) == EVP_CIPH_CCM_MODE)
+ return EVP_CCM_TLS_FIXED_IV_LEN;
+ else
+ return EVP_CIPHER_get_iv_length(c);
+}
+
int tls1_change_cipher_state(SSL *s, int which)
{
unsigned char *p, *mac_secret;
@@ -94,30 +199,44 @@ int tls1_change_cipher_state(SSL *s, int which)
EVP_PKEY *mac_key;
size_t n, i, j, k, cl;
int reuse_dd = 0;
+#ifndef OPENSSL_NO_KTLS
+ ktls_crypto_info_t crypto_info;
+ unsigned char *rec_seq;
+ void *rl_sequence;
+# ifndef OPENSSL_NO_KTLS_RX
+ int count_unprocessed;
+ int bit;
+# endif
+ BIO *bio;
+#endif
- c = s->s3->tmp.new_sym_enc;
- m = s->s3->tmp.new_hash;
- mac_type = s->s3->tmp.new_mac_pkey_type;
+ c = s->s3.tmp.new_sym_enc;
+ m = s->s3.tmp.new_hash;
+ mac_type = s->s3.tmp.new_mac_pkey_type;
#ifndef OPENSSL_NO_COMP
- comp = s->s3->tmp.new_compression;
+ comp = s->s3.tmp.new_compression;
#endif
if (which & SSL3_CC_READ) {
if (s->ext.use_etm)
- s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_READ;
+ s->s3.flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_READ;
else
- s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC_READ;
+ s->s3.flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC_READ;
- if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
+ if (s->s3.tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM;
else
s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM;
+ if (s->s3.tmp.new_cipher->algorithm2 & TLS1_TLSTREE)
+ s->mac_flags |= SSL_MAC_FLAG_READ_MAC_TLSTREE;
+ else
+ s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_TLSTREE;
+
if (s->enc_read_ctx != NULL) {
reuse_dd = 1;
} else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
} else {
/*
@@ -127,8 +246,10 @@ int tls1_change_cipher_state(SSL *s, int which)
}
dd = s->enc_read_ctx;
mac_ctx = ssl_replace_hash(&s->read_hash, NULL);
- if (mac_ctx == NULL)
+ if (mac_ctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
+ }
#ifndef OPENSSL_NO_COMP
COMP_CTX_free(s->expand);
s->expand = NULL;
@@ -136,7 +257,6 @@ int tls1_change_cipher_state(SSL *s, int which)
s->expand = COMP_CTX_new(comp->method);
if (s->expand == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS1_CHANGE_CIPHER_STATE,
SSL_R_COMPRESSION_LIBRARY_ERROR);
goto err;
}
@@ -147,42 +267,42 @@ int tls1_change_cipher_state(SSL *s, int which)
*/
if (!SSL_IS_DTLS(s))
RECORD_LAYER_reset_read_sequence(&s->rlayer);
- mac_secret = &(s->s3->read_mac_secret[0]);
- mac_secret_size = &(s->s3->read_mac_secret_size);
+ mac_secret = &(s->s3.read_mac_secret[0]);
+ mac_secret_size = &(s->s3.read_mac_secret_size);
} else {
s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
if (s->ext.use_etm)
- s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE;
+ s->s3.flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE;
else
- s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE;
+ s->s3.flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE;
- if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
+ if (s->s3.tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM;
else
s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM;
+
+ if (s->s3.tmp.new_cipher->algorithm2 & TLS1_TLSTREE)
+ s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_TLSTREE;
+ else
+ s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_TLSTREE;
if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s)) {
reuse_dd = 1;
} else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
dd = s->enc_write_ctx;
if (SSL_IS_DTLS(s)) {
mac_ctx = EVP_MD_CTX_new();
if (mac_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS1_CHANGE_CIPHER_STATE,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
s->write_hash = mac_ctx;
} else {
mac_ctx = ssl_replace_hash(&s->write_hash, NULL);
if (mac_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS1_CHANGE_CIPHER_STATE,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -193,8 +313,7 @@ int tls1_change_cipher_state(SSL *s, int which)
s->compress = COMP_CTX_new(comp->method);
if (s->compress == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS1_CHANGE_CIPHER_STATE,
- SSL_R_COMPRESSION_LIBRARY_ERROR);
+ SSL_R_COMPRESSION_LIBRARY_ERROR);
goto err;
}
}
@@ -204,27 +323,19 @@ int tls1_change_cipher_state(SSL *s, int which)
*/
if (!SSL_IS_DTLS(s))
RECORD_LAYER_reset_write_sequence(&s->rlayer);
- mac_secret = &(s->s3->write_mac_secret[0]);
- mac_secret_size = &(s->s3->write_mac_secret_size);
+ mac_secret = &(s->s3.write_mac_secret[0]);
+ mac_secret_size = &(s->s3.write_mac_secret_size);
}
if (reuse_dd)
EVP_CIPHER_CTX_reset(dd);
- p = s->s3->tmp.key_block;
- i = *mac_secret_size = s->s3->tmp.new_mac_secret_size;
+ p = s->s3.tmp.key_block;
+ i = *mac_secret_size = s->s3.tmp.new_mac_secret_size;
- /* TODO(size_t): convert me */
- cl = EVP_CIPHER_key_length(c);
+ cl = EVP_CIPHER_get_key_length(c);
j = cl;
- /* Was j=(exp)?5:EVP_CIPHER_key_length(c); */
- /* If GCM/CCM mode only part of IV comes from PRF */
- if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE)
- k = EVP_GCM_TLS_FIXED_IV_LEN;
- else if (EVP_CIPHER_mode(c) == EVP_CIPH_CCM_MODE)
- k = EVP_CCM_TLS_FIXED_IV_LEN;
- else
- k = EVP_CIPHER_iv_length(c);
+ k = tls_iv_length_within_key_block(c);
if ((which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
(which == SSL3_CHANGE_CIPHER_SERVER_READ)) {
ms = &(p[0]);
@@ -243,92 +354,166 @@ int tls1_change_cipher_state(SSL *s, int which)
n += k;
}
- if (n > s->s3->tmp.key_block_length) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
- ERR_R_INTERNAL_ERROR);
+ if (n > s->s3.tmp.key_block_length) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
memcpy(mac_secret, ms, i);
- if (!(EVP_CIPHER_flags(c) & EVP_CIPH_FLAG_AEAD_CIPHER)) {
- /* TODO(size_t): Convert this function */
- mac_key = EVP_PKEY_new_mac_key(mac_type, NULL, mac_secret,
- (int)*mac_secret_size);
+ if (!(EVP_CIPHER_get_flags(c) & EVP_CIPH_FLAG_AEAD_CIPHER)) {
+ if (mac_type == EVP_PKEY_HMAC) {
+ mac_key = EVP_PKEY_new_raw_private_key_ex(s->ctx->libctx, "HMAC",
+ s->ctx->propq, mac_secret,
+ *mac_secret_size);
+ } else {
+ /*
+ * If its not HMAC then the only other types of MAC we support are
+ * the GOST MACs, so we need to use the old style way of creating
+ * a MAC key.
+ */
+ mac_key = EVP_PKEY_new_mac_key(mac_type, NULL, mac_secret,
+ (int)*mac_secret_size);
+ }
if (mac_key == NULL
- || EVP_DigestSignInit(mac_ctx, NULL, m, NULL, mac_key) <= 0) {
+ || EVP_DigestSignInit_ex(mac_ctx, NULL, EVP_MD_get0_name(m),
+ s->ctx->libctx, s->ctx->propq, mac_key,
+ NULL) <= 0) {
EVP_PKEY_free(mac_key);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
EVP_PKEY_free(mac_key);
}
-#ifdef SSL_DEBUG
- printf("which = %04X\nmac key=", which);
- {
- size_t z;
- for (z = 0; z < i; z++)
- printf("%02X%c", ms[z], ((z + 1) % 16) ? ' ' : '\n');
- }
-#endif
- if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) {
+ OSSL_TRACE_BEGIN(TLS) {
+ BIO_printf(trc_out, "which = %04X, mac key:\n", which);
+ BIO_dump_indent(trc_out, ms, i, 4);
+ } OSSL_TRACE_END(TLS);
+
+ if (EVP_CIPHER_get_mode(c) == EVP_CIPH_GCM_MODE) {
if (!EVP_CipherInit_ex(dd, c, NULL, key, NULL, (which & SSL3_CC_WRITE))
- || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GCM_SET_IV_FIXED, (int)k,
- iv)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
- ERR_R_INTERNAL_ERROR);
+ || EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GCM_SET_IV_FIXED, (int)k,
+ iv) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- } else if (EVP_CIPHER_mode(c) == EVP_CIPH_CCM_MODE) {
+ } else if (EVP_CIPHER_get_mode(c) == EVP_CIPH_CCM_MODE) {
int taglen;
- if (s->s3->tmp.
+ if (s->s3.tmp.
new_cipher->algorithm_enc & (SSL_AES128CCM8 | SSL_AES256CCM8))
taglen = EVP_CCM8_TLS_TAG_LEN;
else
taglen = EVP_CCM_TLS_TAG_LEN;
if (!EVP_CipherInit_ex(dd, c, NULL, NULL, NULL, (which & SSL3_CC_WRITE))
- || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)
- || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_TAG, taglen, NULL)
- || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_CCM_SET_IV_FIXED, (int)k, iv)
+ || (EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL) <= 0)
+ || (EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_TAG, taglen, NULL) <= 0)
+ || (EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_CCM_SET_IV_FIXED, (int)k, iv) <= 0)
|| !EVP_CipherInit_ex(dd, NULL, NULL, key, NULL, -1)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
} else {
if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
}
/* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */
- if ((EVP_CIPHER_flags(c) & EVP_CIPH_FLAG_AEAD_CIPHER) && *mac_secret_size
- && !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_MAC_KEY,
- (int)*mac_secret_size, mac_secret)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
- ERR_R_INTERNAL_ERROR);
+ if ((EVP_CIPHER_get_flags(c) & EVP_CIPH_FLAG_AEAD_CIPHER)
+ && *mac_secret_size
+ && EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_MAC_KEY,
+ (int)*mac_secret_size, mac_secret) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
+ if (EVP_CIPHER_get0_provider(c) != NULL
+ && !tls_provider_set_tls_params(s, dd, c, m)) {
+ /* SSLfatal already called */
+ goto err;
+ }
+
+#ifndef OPENSSL_NO_KTLS
+ if (s->compress || (s->options & SSL_OP_ENABLE_KTLS) == 0)
+ goto skip_ktls;
-#ifdef SSL_DEBUG
- printf("which = %04X\nkey=", which);
- {
- int z;
- for (z = 0; z < EVP_CIPHER_key_length(c); z++)
- printf("%02X%c", key[z], ((z + 1) % 16) ? ' ' : '\n');
+ /* ktls supports only the maximum fragment size */
+ if (ssl_get_max_send_fragment(s) != SSL3_RT_MAX_PLAIN_LENGTH)
+ goto skip_ktls;
+
+ /* check that cipher is supported */
+ if (!ktls_check_supported_cipher(s, c, dd))
+ goto skip_ktls;
+
+ if (which & SSL3_CC_WRITE)
+ bio = s->wbio;
+ else
+ bio = s->rbio;
+
+ if (!ossl_assert(bio != NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* All future data will get encrypted by ktls. Flush the BIO or skip ktls */
+ if (which & SSL3_CC_WRITE) {
+ if (BIO_flush(bio) <= 0)
+ goto skip_ktls;
}
- printf("\niv=");
- {
- size_t z;
- for (z = 0; z < k; z++)
- printf("%02X%c", iv[z], ((z + 1) % 16) ? ' ' : '\n');
+
+ /* ktls doesn't support renegotiation */
+ if ((BIO_get_ktls_send(s->wbio) && (which & SSL3_CC_WRITE)) ||
+ (BIO_get_ktls_recv(s->rbio) && (which & SSL3_CC_READ))) {
+ SSLfatal(s, SSL_AD_NO_RENEGOTIATION, ERR_R_INTERNAL_ERROR);
+ goto err;
}
- printf("\n");
-#endif
+
+ if (which & SSL3_CC_WRITE)
+ rl_sequence = RECORD_LAYER_get_write_sequence(&s->rlayer);
+ else
+ rl_sequence = RECORD_LAYER_get_read_sequence(&s->rlayer);
+
+ if (!ktls_configure_crypto(s, c, dd, rl_sequence, &crypto_info, &rec_seq,
+ iv, key, ms, *mac_secret_size))
+ goto skip_ktls;
+
+ if (which & SSL3_CC_READ) {
+# ifndef OPENSSL_NO_KTLS_RX
+ count_unprocessed = count_unprocessed_records(s);
+ if (count_unprocessed < 0)
+ goto skip_ktls;
+
+ /* increment the crypto_info record sequence */
+ while (count_unprocessed) {
+ for (bit = 7; bit >= 0; bit--) { /* increment */
+ ++rec_seq[bit];
+ if (rec_seq[bit] != 0)
+ break;
+ }
+ count_unprocessed--;
+ }
+# else
+ goto skip_ktls;
+# endif
+ }
+
+ /* ktls works with user provided buffers directly */
+ if (BIO_set_ktls(bio, &crypto_info, which & SSL3_CC_WRITE)) {
+ if (which & SSL3_CC_WRITE)
+ ssl3_release_write_buffer(s);
+ SSL_set_options(s, SSL_OP_NO_RENEGOTIATION);
+ }
+
+ skip_ktls:
+#endif /* OPENSSL_NO_KTLS */
+ s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
+
+ OSSL_TRACE_BEGIN(TLS) {
+ BIO_printf(trc_out, "which = %04X, key:\n", which);
+ BIO_dump_indent(trc_out, key, EVP_CIPHER_get_key_length(c), 4);
+ BIO_printf(trc_out, "iv:\n");
+ BIO_dump_indent(trc_out, iv, k, 4);
+ } OSSL_TRACE_END(TLS);
return 1;
err:
@@ -345,69 +530,57 @@ int tls1_setup_key_block(SSL *s)
size_t num, mac_secret_size = 0;
int ret = 0;
- if (s->s3->tmp.key_block_length != 0)
+ if (s->s3.tmp.key_block_length != 0)
return 1;
- if (!ssl_cipher_get_evp(s->session, &c, &hash, &mac_type, &mac_secret_size,
- &comp, s->ext.use_etm)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_SETUP_KEY_BLOCK,
- SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
+ if (!ssl_cipher_get_evp(s->ctx, s->session, &c, &hash, &mac_type,
+ &mac_secret_size, &comp, s->ext.use_etm)) {
+ /* Error is already recorded */
+ SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
return 0;
}
- s->s3->tmp.new_sym_enc = c;
- s->s3->tmp.new_hash = hash;
- s->s3->tmp.new_mac_pkey_type = mac_type;
- s->s3->tmp.new_mac_secret_size = mac_secret_size;
- num = EVP_CIPHER_key_length(c) + mac_secret_size + EVP_CIPHER_iv_length(c);
+ ssl_evp_cipher_free(s->s3.tmp.new_sym_enc);
+ s->s3.tmp.new_sym_enc = c;
+ ssl_evp_md_free(s->s3.tmp.new_hash);
+ s->s3.tmp.new_hash = hash;
+ s->s3.tmp.new_mac_pkey_type = mac_type;
+ s->s3.tmp.new_mac_secret_size = mac_secret_size;
+ num = mac_secret_size + EVP_CIPHER_get_key_length(c)
+ + tls_iv_length_within_key_block(c);
num *= 2;
ssl3_cleanup_key_block(s);
if ((p = OPENSSL_malloc(num)) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_SETUP_KEY_BLOCK,
- ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
- s->s3->tmp.key_block_length = num;
- s->s3->tmp.key_block = p;
+ s->s3.tmp.key_block_length = num;
+ s->s3.tmp.key_block = p;
+
+ OSSL_TRACE_BEGIN(TLS) {
+ BIO_printf(trc_out, "key block length: %zu\n", num);
+ BIO_printf(trc_out, "client random\n");
+ BIO_dump_indent(trc_out, s->s3.client_random, SSL3_RANDOM_SIZE, 4);
+ BIO_printf(trc_out, "server random\n");
+ BIO_dump_indent(trc_out, s->s3.server_random, SSL3_RANDOM_SIZE, 4);
+ BIO_printf(trc_out, "master key\n");
+ BIO_dump_indent(trc_out,
+ s->session->master_key,
+ s->session->master_key_length, 4);
+ } OSSL_TRACE_END(TLS);
-#ifdef SSL_DEBUG
- printf("client random\n");
- {
- int z;
- for (z = 0; z < SSL3_RANDOM_SIZE; z++)
- printf("%02X%c", s->s3->client_random[z],
- ((z + 1) % 16) ? ' ' : '\n');
- }
- printf("server random\n");
- {
- int z;
- for (z = 0; z < SSL3_RANDOM_SIZE; z++)
- printf("%02X%c", s->s3->server_random[z],
- ((z + 1) % 16) ? ' ' : '\n');
- }
- printf("master key\n");
- {
- size_t z;
- for (z = 0; z < s->session->master_key_length; z++)
- printf("%02X%c", s->session->master_key[z],
- ((z + 1) % 16) ? ' ' : '\n');
- }
-#endif
if (!tls1_generate_key_block(s, p, num)) {
/* SSLfatal() already called */
goto err;
}
-#ifdef SSL_DEBUG
- printf("\nkey block\n");
- {
- size_t z;
- for (z = 0; z < num; z++)
- printf("%02X%c", p[z], ((z + 1) % 16) ? ' ' : '\n');
- }
-#endif
+
+ OSSL_TRACE_BEGIN(TLS) {
+ BIO_printf(trc_out, "key block\n");
+ BIO_dump_indent(trc_out, p, num, 4);
+ } OSSL_TRACE_END(TLS);
if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)
&& s->method->version <= TLS1_VERSION) {
@@ -415,16 +588,14 @@ int tls1_setup_key_block(SSL *s)
* enable vulnerability countermeasure for CBC ciphers with known-IV
* problem (http://www.openssl.org/~bodo/tls-cbc.txt)
*/
- s->s3->need_empty_fragments = 1;
+ s->s3.need_empty_fragments = 1;
if (s->session->cipher != NULL) {
if (s->session->cipher->algorithm_enc == SSL_eNULL)
- s->s3->need_empty_fragments = 0;
+ s->s3.need_empty_fragments = 0;
-#ifndef OPENSSL_NO_RC4
if (s->session->cipher->algorithm_enc == SSL_RC4)
- s->s3->need_empty_fragments = 0;
-#endif
+ s->s3.need_empty_fragments = 0;
}
}
@@ -438,6 +609,10 @@ size_t tls1_final_finish_mac(SSL *s, const char *str, size_t slen,
{
size_t hashlen;
unsigned char hash[EVP_MAX_MD_SIZE];
+ size_t finished_size = TLS1_FINISH_MAC_LENGTH;
+
+ if (s->s3.tmp.new_cipher->algorithm_mkey & SSL_kGOST18)
+ finished_size = 32;
if (!ssl3_digest_cached_records(s, 0)) {
/* SSLfatal() already called */
@@ -451,12 +626,12 @@ size_t tls1_final_finish_mac(SSL *s, const char *str, size_t slen,
if (!tls1_PRF(s, str, slen, hash, hashlen, NULL, 0, NULL, 0, NULL, 0,
s->session->master_key, s->session->master_key_length,
- out, TLS1_FINISH_MAC_LENGTH, 1)) {
+ out, finished_size, 1)) {
/* SSLfatal() already called */
return 0;
}
OPENSSL_cleanse(hash, hashlen);
- return TLS1_FINISH_MAC_LENGTH;
+ return finished_size;
}
int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
@@ -475,10 +650,10 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
/* SSLfatal() already called */
return 0;
}
-#ifdef SSL_DEBUG
- fprintf(stderr, "Handshake hashes:\n");
- BIO_dump_fp(stderr, (char *)hash, hashlen);
-#endif
+ OSSL_TRACE_BEGIN(TLS) {
+ BIO_printf(trc_out, "Handshake hashes:\n");
+ BIO_dump(trc_out, (char *)hash, hashlen);
+ } OSSL_TRACE_END(TLS);
if (!tls1_PRF(s,
TLS_MD_EXTENDED_MASTER_SECRET_CONST,
TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE,
@@ -495,26 +670,28 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
if (!tls1_PRF(s,
TLS_MD_MASTER_SECRET_CONST,
TLS_MD_MASTER_SECRET_CONST_SIZE,
- s->s3->client_random, SSL3_RANDOM_SIZE,
+ s->s3.client_random, SSL3_RANDOM_SIZE,
NULL, 0,
- s->s3->server_random, SSL3_RANDOM_SIZE,
+ s->s3.server_random, SSL3_RANDOM_SIZE,
NULL, 0, p, len, out,
SSL3_MASTER_SECRET_SIZE, 1)) {
/* SSLfatal() already called */
return 0;
}
}
-#ifdef SSL_DEBUG
- fprintf(stderr, "Premaster Secret:\n");
- BIO_dump_fp(stderr, (char *)p, len);
- fprintf(stderr, "Client Random:\n");
- BIO_dump_fp(stderr, (char *)s->s3->client_random, SSL3_RANDOM_SIZE);
- fprintf(stderr, "Server Random:\n");
- BIO_dump_fp(stderr, (char *)s->s3->server_random, SSL3_RANDOM_SIZE);
- fprintf(stderr, "Master Secret:\n");
- BIO_dump_fp(stderr, (char *)s->session->master_key,
- SSL3_MASTER_SECRET_SIZE);
-#endif
+
+ OSSL_TRACE_BEGIN(TLS) {
+ BIO_printf(trc_out, "Premaster Secret:\n");
+ BIO_dump_indent(trc_out, p, len, 4);
+ BIO_printf(trc_out, "Client Random:\n");
+ BIO_dump_indent(trc_out, s->s3.client_random, SSL3_RANDOM_SIZE, 4);
+ BIO_printf(trc_out, "Server Random:\n");
+ BIO_dump_indent(trc_out, s->s3.server_random, SSL3_RANDOM_SIZE, 4);
+ BIO_printf(trc_out, "Master Secret:\n");
+ BIO_dump_indent(trc_out,
+ s->session->master_key,
+ SSL3_MASTER_SECRET_SIZE, 4);
+ } OSSL_TRACE_END(TLS);
*secret_size = SSL3_MASTER_SECRET_SIZE;
return 1;
@@ -545,9 +722,9 @@ int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
currentvalpos = 0;
memcpy(val + currentvalpos, (unsigned char *)label, llen);
currentvalpos += llen;
- memcpy(val + currentvalpos, s->s3->client_random, SSL3_RANDOM_SIZE);
+ memcpy(val + currentvalpos, s->s3.client_random, SSL3_RANDOM_SIZE);
currentvalpos += SSL3_RANDOM_SIZE;
- memcpy(val + currentvalpos, s->s3->server_random, SSL3_RANDOM_SIZE);
+ memcpy(val + currentvalpos, s->s3.server_random, SSL3_RANDOM_SIZE);
currentvalpos += SSL3_RANDOM_SIZE;
if (use_context) {
@@ -592,11 +769,11 @@ int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
goto ret;
err1:
- SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
+ ERR_raise(ERR_LIB_SSL, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
rv = 0;
goto ret;
err2:
- SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
rv = 0;
ret:
OPENSSL_clear_free(val, vallen);
@@ -672,7 +849,7 @@ int tls1_alert_code(int code)
return TLS1_AD_NO_APPLICATION_PROTOCOL;
case SSL_AD_CERTIFICATE_REQUIRED:
return SSL_AD_HANDSHAKE_FAILURE;
- case SSL_AD_MISSING_EXTENSION:
+ case TLS13_AD_MISSING_EXTENSION:
return SSL_AD_HANDSHAKE_FAILURE;
default:
return -1;
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 5f657f888e0d..51c2283db915 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -12,12 +12,17 @@
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
+#include <openssl/core_names.h>
#include <openssl/ocsp.h>
#include <openssl/conf.h>
#include <openssl/x509v3.h>
#include <openssl/dh.h>
#include <openssl/bn.h>
+#include <openssl/provider.h>
+#include <openssl/param_build.h>
#include "internal/nelem.h"
+#include "internal/sizes.h"
+#include "internal/tlsgroups.h"
#include "ssl_local.h"
#include <openssl/ct.h>
@@ -124,51 +129,60 @@ int tls1_clear(SSL *s)
return 0;
if (s->method->version == TLS_ANY_VERSION)
- s->version = TLS_MAX_VERSION;
+ s->version = TLS_MAX_VERSION_INTERNAL;
else
s->version = s->method->version;
return 1;
}
-#ifndef OPENSSL_NO_EC
-
-/*
- * Table of curve information.
- * Do not delete entries or reorder this array! It is used as a lookup
- * table: the index of each entry is one less than the TLS curve id.
- */
-static const TLS_GROUP_INFO nid_list[] = {
- {NID_sect163k1, 80, TLS_CURVE_CHAR2}, /* sect163k1 (1) */
- {NID_sect163r1, 80, TLS_CURVE_CHAR2}, /* sect163r1 (2) */
- {NID_sect163r2, 80, TLS_CURVE_CHAR2}, /* sect163r2 (3) */
- {NID_sect193r1, 80, TLS_CURVE_CHAR2}, /* sect193r1 (4) */
- {NID_sect193r2, 80, TLS_CURVE_CHAR2}, /* sect193r2 (5) */
- {NID_sect233k1, 112, TLS_CURVE_CHAR2}, /* sect233k1 (6) */
- {NID_sect233r1, 112, TLS_CURVE_CHAR2}, /* sect233r1 (7) */
- {NID_sect239k1, 112, TLS_CURVE_CHAR2}, /* sect239k1 (8) */
- {NID_sect283k1, 128, TLS_CURVE_CHAR2}, /* sect283k1 (9) */
- {NID_sect283r1, 128, TLS_CURVE_CHAR2}, /* sect283r1 (10) */
- {NID_sect409k1, 192, TLS_CURVE_CHAR2}, /* sect409k1 (11) */
- {NID_sect409r1, 192, TLS_CURVE_CHAR2}, /* sect409r1 (12) */
- {NID_sect571k1, 256, TLS_CURVE_CHAR2}, /* sect571k1 (13) */
- {NID_sect571r1, 256, TLS_CURVE_CHAR2}, /* sect571r1 (14) */
- {NID_secp160k1, 80, TLS_CURVE_PRIME}, /* secp160k1 (15) */
- {NID_secp160r1, 80, TLS_CURVE_PRIME}, /* secp160r1 (16) */
- {NID_secp160r2, 80, TLS_CURVE_PRIME}, /* secp160r2 (17) */
- {NID_secp192k1, 80, TLS_CURVE_PRIME}, /* secp192k1 (18) */
- {NID_X9_62_prime192v1, 80, TLS_CURVE_PRIME}, /* secp192r1 (19) */
- {NID_secp224k1, 112, TLS_CURVE_PRIME}, /* secp224k1 (20) */
- {NID_secp224r1, 112, TLS_CURVE_PRIME}, /* secp224r1 (21) */
- {NID_secp256k1, 128, TLS_CURVE_PRIME}, /* secp256k1 (22) */
- {NID_X9_62_prime256v1, 128, TLS_CURVE_PRIME}, /* secp256r1 (23) */
- {NID_secp384r1, 192, TLS_CURVE_PRIME}, /* secp384r1 (24) */
- {NID_secp521r1, 256, TLS_CURVE_PRIME}, /* secp521r1 (25) */
- {NID_brainpoolP256r1, 128, TLS_CURVE_PRIME}, /* brainpoolP256r1 (26) */
- {NID_brainpoolP384r1, 192, TLS_CURVE_PRIME}, /* brainpoolP384r1 (27) */
- {NID_brainpoolP512r1, 256, TLS_CURVE_PRIME}, /* brainpool512r1 (28) */
- {EVP_PKEY_X25519, 128, TLS_CURVE_CUSTOM}, /* X25519 (29) */
- {EVP_PKEY_X448, 224, TLS_CURVE_CUSTOM}, /* X448 (30) */
+/* Legacy NID to group_id mapping. Only works for groups we know about */
+static struct {
+ int nid;
+ uint16_t group_id;
+} nid_to_group[] = {
+ {NID_sect163k1, OSSL_TLS_GROUP_ID_sect163k1},
+ {NID_sect163r1, OSSL_TLS_GROUP_ID_sect163r1},
+ {NID_sect163r2, OSSL_TLS_GROUP_ID_sect163r2},
+ {NID_sect193r1, OSSL_TLS_GROUP_ID_sect193r1},
+ {NID_sect193r2, OSSL_TLS_GROUP_ID_sect193r2},
+ {NID_sect233k1, OSSL_TLS_GROUP_ID_sect233k1},
+ {NID_sect233r1, OSSL_TLS_GROUP_ID_sect233r1},
+ {NID_sect239k1, OSSL_TLS_GROUP_ID_sect239k1},
+ {NID_sect283k1, OSSL_TLS_GROUP_ID_sect283k1},
+ {NID_sect283r1, OSSL_TLS_GROUP_ID_sect283r1},
+ {NID_sect409k1, OSSL_TLS_GROUP_ID_sect409k1},
+ {NID_sect409r1, OSSL_TLS_GROUP_ID_sect409r1},
+ {NID_sect571k1, OSSL_TLS_GROUP_ID_sect571k1},
+ {NID_sect571r1, OSSL_TLS_GROUP_ID_sect571r1},
+ {NID_secp160k1, OSSL_TLS_GROUP_ID_secp160k1},
+ {NID_secp160r1, OSSL_TLS_GROUP_ID_secp160r1},
+ {NID_secp160r2, OSSL_TLS_GROUP_ID_secp160r2},
+ {NID_secp192k1, OSSL_TLS_GROUP_ID_secp192k1},
+ {NID_X9_62_prime192v1, OSSL_TLS_GROUP_ID_secp192r1},
+ {NID_secp224k1, OSSL_TLS_GROUP_ID_secp224k1},
+ {NID_secp224r1, OSSL_TLS_GROUP_ID_secp224r1},
+ {NID_secp256k1, OSSL_TLS_GROUP_ID_secp256k1},
+ {NID_X9_62_prime256v1, OSSL_TLS_GROUP_ID_secp256r1},
+ {NID_secp384r1, OSSL_TLS_GROUP_ID_secp384r1},
+ {NID_secp521r1, OSSL_TLS_GROUP_ID_secp521r1},
+ {NID_brainpoolP256r1, OSSL_TLS_GROUP_ID_brainpoolP256r1},
+ {NID_brainpoolP384r1, OSSL_TLS_GROUP_ID_brainpoolP384r1},
+ {NID_brainpoolP512r1, OSSL_TLS_GROUP_ID_brainpoolP512r1},
+ {EVP_PKEY_X25519, OSSL_TLS_GROUP_ID_x25519},
+ {EVP_PKEY_X448, OSSL_TLS_GROUP_ID_x448},
+ {NID_id_tc26_gost_3410_2012_256_paramSetA, 0x0022},
+ {NID_id_tc26_gost_3410_2012_256_paramSetB, 0x0023},
+ {NID_id_tc26_gost_3410_2012_256_paramSetC, 0x0024},
+ {NID_id_tc26_gost_3410_2012_256_paramSetD, 0x0025},
+ {NID_id_tc26_gost_3410_2012_512_paramSetA, 0x0026},
+ {NID_id_tc26_gost_3410_2012_512_paramSetB, 0x0027},
+ {NID_id_tc26_gost_3410_2012_512_paramSetC, 0x0028},
+ {NID_ffdhe2048, OSSL_TLS_GROUP_ID_ffdhe2048},
+ {NID_ffdhe3072, OSSL_TLS_GROUP_ID_ffdhe3072},
+ {NID_ffdhe4096, OSSL_TLS_GROUP_ID_ffdhe4096},
+ {NID_ffdhe6144, OSSL_TLS_GROUP_ID_ffdhe6144},
+ {NID_ffdhe8192, OSSL_TLS_GROUP_ID_ffdhe8192}
};
static const unsigned char ecformats_default[] = {
@@ -178,12 +192,24 @@ static const unsigned char ecformats_default[] = {
};
/* The default curves */
-static const uint16_t eccurves_default[] = {
+static const uint16_t supported_groups_default[] = {
29, /* X25519 (29) */
23, /* secp256r1 (23) */
30, /* X448 (30) */
25, /* secp521r1 (25) */
24, /* secp384r1 (24) */
+ 34, /* GC256A (34) */
+ 35, /* GC256B (35) */
+ 36, /* GC256C (36) */
+ 37, /* GC256D (37) */
+ 38, /* GC512A (38) */
+ 39, /* GC512B (39) */
+ 40, /* GC512C (40) */
+ 0x100, /* ffdhe2048 (0x100) */
+ 0x101, /* ffdhe3072 (0x101) */
+ 0x102, /* ffdhe4096 (0x102) */
+ 0x103, /* ffdhe6144 (0x103) */
+ 0x104, /* ffdhe8192 (0x104) */
};
static const uint16_t suiteb_curves[] = {
@@ -191,21 +217,271 @@ static const uint16_t suiteb_curves[] = {
TLSEXT_curve_P_384
};
-const TLS_GROUP_INFO *tls1_group_id_lookup(uint16_t group_id)
+struct provider_group_data_st {
+ SSL_CTX *ctx;
+ OSSL_PROVIDER *provider;
+};
+
+#define TLS_GROUP_LIST_MALLOC_BLOCK_SIZE 10
+static OSSL_CALLBACK add_provider_groups;
+static int add_provider_groups(const OSSL_PARAM params[], void *data)
+{
+ struct provider_group_data_st *pgd = data;
+ SSL_CTX *ctx = pgd->ctx;
+ OSSL_PROVIDER *provider = pgd->provider;
+ const OSSL_PARAM *p;
+ TLS_GROUP_INFO *ginf = NULL;
+ EVP_KEYMGMT *keymgmt;
+ unsigned int gid;
+ unsigned int is_kem = 0;
+ int ret = 0;
+
+ if (ctx->group_list_max_len == ctx->group_list_len) {
+ TLS_GROUP_INFO *tmp = NULL;
+
+ if (ctx->group_list_max_len == 0)
+ tmp = OPENSSL_malloc(sizeof(TLS_GROUP_INFO)
+ * TLS_GROUP_LIST_MALLOC_BLOCK_SIZE);
+ else
+ tmp = OPENSSL_realloc(ctx->group_list,
+ (ctx->group_list_max_len
+ + TLS_GROUP_LIST_MALLOC_BLOCK_SIZE)
+ * sizeof(TLS_GROUP_INFO));
+ if (tmp == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ ctx->group_list = tmp;
+ memset(tmp + ctx->group_list_max_len,
+ 0,
+ sizeof(TLS_GROUP_INFO) * TLS_GROUP_LIST_MALLOC_BLOCK_SIZE);
+ ctx->group_list_max_len += TLS_GROUP_LIST_MALLOC_BLOCK_SIZE;
+ }
+
+ ginf = &ctx->group_list[ctx->group_list_len];
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_NAME);
+ if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
+ goto err;
+ }
+ ginf->tlsname = OPENSSL_strdup(p->data);
+ if (ginf->tlsname == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL);
+ if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
+ goto err;
+ }
+ ginf->realname = OPENSSL_strdup(p->data);
+ if (ginf->realname == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_ID);
+ if (p == NULL || !OSSL_PARAM_get_uint(p, &gid) || gid > UINT16_MAX) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
+ goto err;
+ }
+ ginf->group_id = (uint16_t)gid;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_ALG);
+ if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
+ goto err;
+ }
+ ginf->algorithm = OPENSSL_strdup(p->data);
+ if (ginf->algorithm == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS);
+ if (p == NULL || !OSSL_PARAM_get_uint(p, &ginf->secbits)) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
+ goto err;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_IS_KEM);
+ if (p != NULL && (!OSSL_PARAM_get_uint(p, &is_kem) || is_kem > 1)) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
+ goto err;
+ }
+ ginf->is_kem = 1 & is_kem;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_MIN_TLS);
+ if (p == NULL || !OSSL_PARAM_get_int(p, &ginf->mintls)) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
+ goto err;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_MAX_TLS);
+ if (p == NULL || !OSSL_PARAM_get_int(p, &ginf->maxtls)) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
+ goto err;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS);
+ if (p == NULL || !OSSL_PARAM_get_int(p, &ginf->mindtls)) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
+ goto err;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS);
+ if (p == NULL || !OSSL_PARAM_get_int(p, &ginf->maxdtls)) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
+ goto err;
+ }
+ /*
+ * Now check that the algorithm is actually usable for our property query
+ * string. Regardless of the result we still return success because we have
+ * successfully processed this group, even though we may decide not to use
+ * it.
+ */
+ ret = 1;
+ ERR_set_mark();
+ keymgmt = EVP_KEYMGMT_fetch(ctx->libctx, ginf->algorithm, ctx->propq);
+ if (keymgmt != NULL) {
+ /*
+ * We have successfully fetched the algorithm - however if the provider
+ * doesn't match this one then we ignore it.
+ *
+ * Note: We're cheating a little here. Technically if the same algorithm
+ * is available from more than one provider then it is undefined which
+ * implementation you will get back. Theoretically this could be
+ * different every time...we assume here that you'll always get the
+ * same one back if you repeat the exact same fetch. Is this a reasonable
+ * assumption to make (in which case perhaps we should document this
+ * behaviour)?
+ */
+ if (EVP_KEYMGMT_get0_provider(keymgmt) == provider) {
+ /* We have a match - so we will use this group */
+ ctx->group_list_len++;
+ ginf = NULL;
+ }
+ EVP_KEYMGMT_free(keymgmt);
+ }
+ ERR_pop_to_mark();
+ err:
+ if (ginf != NULL) {
+ OPENSSL_free(ginf->tlsname);
+ OPENSSL_free(ginf->realname);
+ OPENSSL_free(ginf->algorithm);
+ ginf->algorithm = ginf->tlsname = ginf->realname = NULL;
+ }
+ return ret;
+}
+
+static int discover_provider_groups(OSSL_PROVIDER *provider, void *vctx)
{
- /* ECC curves from RFC 4492 and RFC 7027 */
- if (group_id < 1 || group_id > OSSL_NELEM(nid_list))
- return NULL;
- return &nid_list[group_id - 1];
+ struct provider_group_data_st pgd;
+
+ pgd.ctx = vctx;
+ pgd.provider = provider;
+ return OSSL_PROVIDER_get_capabilities(provider, "TLS-GROUP",
+ add_provider_groups, &pgd);
}
-static uint16_t tls1_nid2group_id(int nid)
+int ssl_load_groups(SSL_CTX *ctx)
+{
+ size_t i, j, num_deflt_grps = 0;
+ uint16_t tmp_supp_groups[OSSL_NELEM(supported_groups_default)];
+
+ if (!OSSL_PROVIDER_do_all(ctx->libctx, discover_provider_groups, ctx))
+ return 0;
+
+ for (i = 0; i < OSSL_NELEM(supported_groups_default); i++) {
+ for (j = 0; j < ctx->group_list_len; j++) {
+ if (ctx->group_list[j].group_id == supported_groups_default[i]) {
+ tmp_supp_groups[num_deflt_grps++] = ctx->group_list[j].group_id;
+ break;
+ }
+ }
+ }
+
+ if (num_deflt_grps == 0)
+ return 1;
+
+ ctx->ext.supported_groups_default
+ = OPENSSL_malloc(sizeof(uint16_t) * num_deflt_grps);
+
+ if (ctx->ext.supported_groups_default == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ memcpy(ctx->ext.supported_groups_default,
+ tmp_supp_groups,
+ num_deflt_grps * sizeof(tmp_supp_groups[0]));
+ ctx->ext.supported_groups_default_len = num_deflt_grps;
+
+ return 1;
+}
+
+static uint16_t tls1_group_name2id(SSL_CTX *ctx, const char *name)
+{
+ size_t i;
+
+ for (i = 0; i < ctx->group_list_len; i++) {
+ if (strcmp(ctx->group_list[i].tlsname, name) == 0
+ || strcmp(ctx->group_list[i].realname, name) == 0)
+ return ctx->group_list[i].group_id;
+ }
+
+ return 0;
+}
+
+const TLS_GROUP_INFO *tls1_group_id_lookup(SSL_CTX *ctx, uint16_t group_id)
{
size_t i;
- for (i = 0; i < OSSL_NELEM(nid_list); i++) {
- if (nid_list[i].nid == nid)
- return (uint16_t)(i + 1);
+
+ for (i = 0; i < ctx->group_list_len; i++) {
+ if (ctx->group_list[i].group_id == group_id)
+ return &ctx->group_list[i];
+ }
+
+ return NULL;
+}
+
+int tls1_group_id2nid(uint16_t group_id, int include_unknown)
+{
+ size_t i;
+
+ if (group_id == 0)
+ return NID_undef;
+
+ /*
+ * Return well known Group NIDs - for backwards compatibility. This won't
+ * work for groups we don't know about.
+ */
+ for (i = 0; i < OSSL_NELEM(nid_to_group); i++)
+ {
+ if (nid_to_group[i].group_id == group_id)
+ return nid_to_group[i].nid;
+ }
+ if (!include_unknown)
+ return NID_undef;
+ return TLSEXT_nid_unknown | (int)group_id;
+}
+
+uint16_t tls1_nid2group_id(int nid)
+{
+ size_t i;
+
+ /*
+ * Return well known Group ids - for backwards compatibility. This won't
+ * work for groups we don't know about.
+ */
+ for (i = 0; i < OSSL_NELEM(nid_to_group); i++)
+ {
+ if (nid_to_group[i].nid == nid)
+ return nid_to_group[i].group_id;
}
+
return 0;
}
@@ -216,7 +492,6 @@ static uint16_t tls1_nid2group_id(int nid)
void tls1_get_supported_groups(SSL *s, const uint16_t **pgroups,
size_t *pgroupslen)
{
-
/* For Suite B mode only include P-256, P-384 */
switch (tls1_suiteb(s)) {
case SSL_CERT_FLAG_SUITEB_128_LOS:
@@ -236,8 +511,8 @@ void tls1_get_supported_groups(SSL *s, const uint16_t **pgroups,
default:
if (s->ext.supportedgroups == NULL) {
- *pgroups = eccurves_default;
- *pgroupslen = OSSL_NELEM(eccurves_default);
+ *pgroups = s->ctx->ext.supported_groups_default;
+ *pgroupslen = s->ctx->ext.supported_groups_default_len;
} else {
*pgroups = s->ext.supportedgroups;
*pgroupslen = s->ext.supportedgroups_len;
@@ -246,21 +521,61 @@ void tls1_get_supported_groups(SSL *s, const uint16_t **pgroups,
}
}
-/* See if curve is allowed by security callback */
-int tls_curve_allowed(SSL *s, uint16_t curve, int op)
+int tls_valid_group(SSL *s, uint16_t group_id, int minversion, int maxversion,
+ int isec, int *okfortls13)
{
- const TLS_GROUP_INFO *cinfo = tls1_group_id_lookup(curve);
- unsigned char ctmp[2];
+ const TLS_GROUP_INFO *ginfo = tls1_group_id_lookup(s->ctx, group_id);
+ int ret;
- if (cinfo == NULL)
+ if (okfortls13 != NULL)
+ *okfortls13 = 0;
+
+ if (ginfo == NULL)
return 0;
-# ifdef OPENSSL_NO_EC2M
- if (cinfo->flags & TLS_CURVE_CHAR2)
+
+ if (SSL_IS_DTLS(s)) {
+ if (ginfo->mindtls < 0 || ginfo->maxdtls < 0)
+ return 0;
+ if (ginfo->maxdtls == 0)
+ ret = 1;
+ else
+ ret = DTLS_VERSION_LE(minversion, ginfo->maxdtls);
+ if (ginfo->mindtls > 0)
+ ret &= DTLS_VERSION_GE(maxversion, ginfo->mindtls);
+ } else {
+ if (ginfo->mintls < 0 || ginfo->maxtls < 0)
+ return 0;
+ if (ginfo->maxtls == 0)
+ ret = 1;
+ else
+ ret = (minversion <= ginfo->maxtls);
+ if (ginfo->mintls > 0)
+ ret &= (maxversion >= ginfo->mintls);
+ if (ret && okfortls13 != NULL && maxversion == TLS1_3_VERSION)
+ *okfortls13 = (ginfo->maxtls == 0)
+ || (ginfo->maxtls >= TLS1_3_VERSION);
+ }
+ ret &= !isec
+ || strcmp(ginfo->algorithm, "EC") == 0
+ || strcmp(ginfo->algorithm, "X25519") == 0
+ || strcmp(ginfo->algorithm, "X448") == 0;
+
+ return ret;
+}
+
+/* See if group is allowed by security callback */
+int tls_group_allowed(SSL *s, uint16_t group, int op)
+{
+ const TLS_GROUP_INFO *ginfo = tls1_group_id_lookup(s->ctx, group);
+ unsigned char gtmp[2];
+
+ if (ginfo == NULL)
return 0;
-# endif
- ctmp[0] = curve >> 8;
- ctmp[1] = curve & 0xff;
- return ssl_security(s, op, cinfo->secbits, cinfo->nid, (void *)ctmp);
+
+ gtmp[0] = group >> 8;
+ gtmp[1] = group & 0xff;
+ return ssl_security(s, op, ginfo->secbits,
+ tls1_group_id2nid(ginfo->group_id, 0), (void *)gtmp);
}
/* Return 1 if "id" is in "list" */
@@ -295,7 +610,7 @@ uint16_t tls1_shared_group(SSL *s, int nmatch)
* For Suite B ciphersuite determines curve: we already know
* these are acceptable due to previous checks.
*/
- unsigned long cid = s->s3->tmp.new_cipher->id;
+ unsigned long cid = s->s3.tmp.new_cipher->id;
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
return TLSEXT_curve_P_256;
@@ -323,7 +638,7 @@ uint16_t tls1_shared_group(SSL *s, int nmatch)
uint16_t id = pref[i];
if (!tls1_in_list(id, supp, num_supp)
- || !tls_curve_allowed(s, id, SSL_SECOP_CURVE_SHARED))
+ || !tls_group_allowed(s, id, SSL_SECOP_CURVE_SHARED))
continue;
if (nmatch == k)
return id;
@@ -341,141 +656,121 @@ int tls1_set_groups(uint16_t **pext, size_t *pextlen,
uint16_t *glist;
size_t i;
/*
- * Bitmap of groups included to detect duplicates: only works while group
- * ids < 32
+ * Bitmap of groups included to detect duplicates: two variables are added
+ * to detect duplicates as some values are more than 32.
*/
- unsigned long dup_list = 0;
+ unsigned long *dup_list = NULL;
+ unsigned long dup_list_egrp = 0;
+ unsigned long dup_list_dhgrp = 0;
if (ngroups == 0) {
- SSLerr(SSL_F_TLS1_SET_GROUPS, SSL_R_BAD_LENGTH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_BAD_LENGTH);
return 0;
}
if ((glist = OPENSSL_malloc(ngroups * sizeof(*glist))) == NULL) {
- SSLerr(SSL_F_TLS1_SET_GROUPS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
for (i = 0; i < ngroups; i++) {
unsigned long idmask;
uint16_t id;
- /* TODO(TLS1.3): Convert for DH groups */
id = tls1_nid2group_id(groups[i]);
- idmask = 1L << id;
- if (!id || (dup_list & idmask)) {
- OPENSSL_free(glist);
- return 0;
- }
- dup_list |= idmask;
+ if ((id & 0x00FF) >= (sizeof(unsigned long) * 8))
+ goto err;
+ idmask = 1L << (id & 0x00FF);
+ dup_list = (id < 0x100) ? &dup_list_egrp : &dup_list_dhgrp;
+ if (!id || ((*dup_list) & idmask))
+ goto err;
+ *dup_list |= idmask;
glist[i] = id;
}
OPENSSL_free(*pext);
*pext = glist;
*pextlen = ngroups;
return 1;
+err:
+ OPENSSL_free(glist);
+ return 0;
}
-# define MAX_CURVELIST OSSL_NELEM(nid_list)
-
+# define GROUPLIST_INCREMENT 40
+# define GROUP_NAME_BUFFER_LENGTH 64
typedef struct {
- size_t nidcnt;
- int nid_arr[MAX_CURVELIST];
-} nid_cb_st;
+ SSL_CTX *ctx;
+ size_t gidcnt;
+ size_t gidmax;
+ uint16_t *gid_arr;
+} gid_cb_st;
-static int nid_cb(const char *elem, int len, void *arg)
+static int gid_cb(const char *elem, int len, void *arg)
{
- nid_cb_st *narg = arg;
+ gid_cb_st *garg = arg;
size_t i;
- int nid;
- char etmp[20];
+ uint16_t gid = 0;
+ char etmp[GROUP_NAME_BUFFER_LENGTH];
+
if (elem == NULL)
return 0;
- if (narg->nidcnt == MAX_CURVELIST)
- return 0;
+ if (garg->gidcnt == garg->gidmax) {
+ uint16_t *tmp =
+ OPENSSL_realloc(garg->gid_arr, garg->gidmax + GROUPLIST_INCREMENT);
+ if (tmp == NULL)
+ return 0;
+ garg->gidmax += GROUPLIST_INCREMENT;
+ garg->gid_arr = tmp;
+ }
if (len > (int)(sizeof(etmp) - 1))
return 0;
memcpy(etmp, elem, len);
etmp[len] = 0;
- nid = EC_curve_nist2nid(etmp);
- if (nid == NID_undef)
- nid = OBJ_sn2nid(etmp);
- if (nid == NID_undef)
- nid = OBJ_ln2nid(etmp);
- if (nid == NID_undef)
+
+ gid = tls1_group_name2id(garg->ctx, etmp);
+ if (gid == 0) {
+ ERR_raise_data(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT,
+ "group '%s' cannot be set", etmp);
return 0;
- for (i = 0; i < narg->nidcnt; i++)
- if (narg->nid_arr[i] == nid)
+ }
+ for (i = 0; i < garg->gidcnt; i++)
+ if (garg->gid_arr[i] == gid)
return 0;
- narg->nid_arr[narg->nidcnt++] = nid;
+ garg->gid_arr[garg->gidcnt++] = gid;
return 1;
}
-/* Set groups based on a colon separate list */
-int tls1_set_groups_list(uint16_t **pext, size_t *pextlen, const char *str)
-{
- nid_cb_st ncb;
- ncb.nidcnt = 0;
- if (!CONF_parse_list(str, ':', 1, nid_cb, &ncb))
- return 0;
- if (pext == NULL)
- return 1;
- return tls1_set_groups(pext, pextlen, ncb.nid_arr, ncb.nidcnt);
-}
-/* Return group id of a key */
-static uint16_t tls1_get_group_id(EVP_PKEY *pkey)
+/* Set groups based on a colon separated list */
+int tls1_set_groups_list(SSL_CTX *ctx, uint16_t **pext, size_t *pextlen,
+ const char *str)
{
- EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
- const EC_GROUP *grp;
+ gid_cb_st gcb;
+ uint16_t *tmparr;
+ int ret = 0;
- if (ec == NULL)
+ gcb.gidcnt = 0;
+ gcb.gidmax = GROUPLIST_INCREMENT;
+ gcb.gid_arr = OPENSSL_malloc(gcb.gidmax * sizeof(*gcb.gid_arr));
+ if (gcb.gid_arr == NULL)
return 0;
- grp = EC_KEY_get0_group(ec);
- return tls1_nid2group_id(EC_GROUP_get_curve_name(grp));
-}
-
-/* Check a key is compatible with compression extension */
-static int tls1_check_pkey_comp(SSL *s, EVP_PKEY *pkey)
-{
- const EC_KEY *ec;
- const EC_GROUP *grp;
- unsigned char comp_id;
- size_t i;
-
- /* If not an EC key nothing to check */
- if (EVP_PKEY_id(pkey) != EVP_PKEY_EC)
- return 1;
- ec = EVP_PKEY_get0_EC_KEY(pkey);
- grp = EC_KEY_get0_group(ec);
-
- /* Get required compression id */
- if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_UNCOMPRESSED) {
- comp_id = TLSEXT_ECPOINTFORMAT_uncompressed;
- } else if (SSL_IS_TLS13(s)) {
- /*
- * ec_point_formats extension is not used in TLSv1.3 so we ignore
- * this check.
- */
- return 1;
- } else {
- int field_type = EC_METHOD_get_field_type(EC_GROUP_method_of(grp));
-
- if (field_type == NID_X9_62_prime_field)
- comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
- else if (field_type == NID_X9_62_characteristic_two_field)
- comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
- else
- return 0;
+ gcb.ctx = ctx;
+ if (!CONF_parse_list(str, ':', 1, gid_cb, &gcb))
+ goto end;
+ if (pext == NULL) {
+ ret = 1;
+ goto end;
}
+
/*
- * If point formats extension present check it, otherwise everything is
- * supported (see RFC4492).
+ * gid_cb ensurse there are no duplicates so we can just go ahead and set
+ * the result
*/
- if (s->ext.peer_ecpointformats == NULL)
- return 1;
-
- for (i = 0; i < s->ext.peer_ecpointformats_len; i++) {
- if (s->ext.peer_ecpointformats[i] == comp_id)
- return 1;
- }
- return 0;
+ tmparr = OPENSSL_memdup(gcb.gid_arr, gcb.gidcnt * sizeof(*tmparr));
+ if (tmparr == NULL)
+ goto end;
+ *pext = tmparr;
+ *pextlen = gcb.gidcnt;
+ ret = 1;
+ end:
+ OPENSSL_free(gcb.gid_arr);
+ return ret;
}
/* Check a group id matches preferences */
@@ -488,8 +783,8 @@ int tls1_check_group_id(SSL *s, uint16_t group_id, int check_own_groups)
return 0;
/* Check for Suite B compliance */
- if (tls1_suiteb(s) && s->s3->tmp.new_cipher != NULL) {
- unsigned long cid = s->s3->tmp.new_cipher->id;
+ if (tls1_suiteb(s) && s->s3.tmp.new_cipher != NULL) {
+ unsigned long cid = s->s3.tmp.new_cipher->id;
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) {
if (group_id != TLSEXT_curve_P_256)
@@ -510,7 +805,7 @@ int tls1_check_group_id(SSL *s, uint16_t group_id, int check_own_groups)
return 0;
}
- if (!tls_curve_allowed(s, group_id, SSL_SECOP_CURVE_CHECK))
+ if (!tls_group_allowed(s, group_id, SSL_SECOP_CURVE_CHECK))
return 0;
/* For clients, nothing more to check */
@@ -550,6 +845,64 @@ void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
}
}
+/* Check a key is compatible with compression extension */
+static int tls1_check_pkey_comp(SSL *s, EVP_PKEY *pkey)
+{
+ unsigned char comp_id;
+ size_t i;
+ int point_conv;
+
+ /* If not an EC key nothing to check */
+ if (!EVP_PKEY_is_a(pkey, "EC"))
+ return 1;
+
+
+ /* Get required compression id */
+ point_conv = EVP_PKEY_get_ec_point_conv_form(pkey);
+ if (point_conv == 0)
+ return 0;
+ if (point_conv == POINT_CONVERSION_UNCOMPRESSED) {
+ comp_id = TLSEXT_ECPOINTFORMAT_uncompressed;
+ } else if (SSL_IS_TLS13(s)) {
+ /*
+ * ec_point_formats extension is not used in TLSv1.3 so we ignore
+ * this check.
+ */
+ return 1;
+ } else {
+ int field_type = EVP_PKEY_get_field_type(pkey);
+
+ if (field_type == NID_X9_62_prime_field)
+ comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
+ else if (field_type == NID_X9_62_characteristic_two_field)
+ comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
+ else
+ return 0;
+ }
+ /*
+ * If point formats extension present check it, otherwise everything is
+ * supported (see RFC4492).
+ */
+ if (s->ext.peer_ecpointformats == NULL)
+ return 1;
+
+ for (i = 0; i < s->ext.peer_ecpointformats_len; i++) {
+ if (s->ext.peer_ecpointformats[i] == comp_id)
+ return 1;
+ }
+ return 0;
+}
+
+/* Return group id of a key */
+static uint16_t tls1_get_group_id(EVP_PKEY *pkey)
+{
+ int curve_nid = ssl_get_EC_curve_nid(pkey);
+
+ if (curve_nid == NID_undef)
+ return 0;
+ return tls1_nid2group_id(curve_nid);
+}
+
/*
* Check cert parameters compatible with extensions: currently just checks EC
* certificates have compatible curves and compression.
@@ -562,7 +915,7 @@ static int tls1_check_cert_param(SSL *s, X509 *x, int check_ee_md)
if (pkey == NULL)
return 0;
/* If not EC nothing to do */
- if (EVP_PKEY_id(pkey) != EVP_PKEY_EC)
+ if (!EVP_PKEY_is_a(pkey, "EC"))
return 1;
/* Check compression */
if (!tls1_check_pkey_comp(s, pkey))
@@ -625,24 +978,13 @@ int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
return 0;
}
-#else
-
-static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md)
-{
- return 1;
-}
-
-#endif /* OPENSSL_NO_EC */
-
/* Default sigalg schemes */
static const uint16_t tls12_sigalgs[] = {
-#ifndef OPENSSL_NO_EC
TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
TLSEXT_SIGALG_ecdsa_secp384r1_sha384,
TLSEXT_SIGALG_ecdsa_secp521r1_sha512,
TLSEXT_SIGALG_ed25519,
TLSEXT_SIGALG_ed448,
-#endif
TLSEXT_SIGALG_rsa_pss_pss_sha256,
TLSEXT_SIGALG_rsa_pss_pss_sha384,
@@ -655,121 +997,125 @@ static const uint16_t tls12_sigalgs[] = {
TLSEXT_SIGALG_rsa_pkcs1_sha384,
TLSEXT_SIGALG_rsa_pkcs1_sha512,
-#ifndef OPENSSL_NO_EC
TLSEXT_SIGALG_ecdsa_sha224,
TLSEXT_SIGALG_ecdsa_sha1,
-#endif
+
TLSEXT_SIGALG_rsa_pkcs1_sha224,
TLSEXT_SIGALG_rsa_pkcs1_sha1,
-#ifndef OPENSSL_NO_DSA
+
TLSEXT_SIGALG_dsa_sha224,
TLSEXT_SIGALG_dsa_sha1,
TLSEXT_SIGALG_dsa_sha256,
TLSEXT_SIGALG_dsa_sha384,
TLSEXT_SIGALG_dsa_sha512,
-#endif
+
#ifndef OPENSSL_NO_GOST
+ TLSEXT_SIGALG_gostr34102012_256_intrinsic,
+ TLSEXT_SIGALG_gostr34102012_512_intrinsic,
TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256,
TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512,
TLSEXT_SIGALG_gostr34102001_gostr3411,
#endif
};
-#ifndef OPENSSL_NO_EC
+
static const uint16_t suiteb_sigalgs[] = {
TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
TLSEXT_SIGALG_ecdsa_secp384r1_sha384
};
-#endif
static const SIGALG_LOOKUP sigalg_lookup_tbl[] = {
-#ifndef OPENSSL_NO_EC
{"ecdsa_secp256r1_sha256", TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
- NID_ecdsa_with_SHA256, NID_X9_62_prime256v1},
+ NID_ecdsa_with_SHA256, NID_X9_62_prime256v1, 1},
{"ecdsa_secp384r1_sha384", TLSEXT_SIGALG_ecdsa_secp384r1_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
- NID_ecdsa_with_SHA384, NID_secp384r1},
+ NID_ecdsa_with_SHA384, NID_secp384r1, 1},
{"ecdsa_secp521r1_sha512", TLSEXT_SIGALG_ecdsa_secp521r1_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
- NID_ecdsa_with_SHA512, NID_secp521r1},
+ NID_ecdsa_with_SHA512, NID_secp521r1, 1},
{"ed25519", TLSEXT_SIGALG_ed25519,
NID_undef, -1, EVP_PKEY_ED25519, SSL_PKEY_ED25519,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{"ed448", TLSEXT_SIGALG_ed448,
NID_undef, -1, EVP_PKEY_ED448, SSL_PKEY_ED448,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_ecdsa_sha224,
NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
- NID_ecdsa_with_SHA224, NID_undef},
+ NID_ecdsa_with_SHA224, NID_undef, 1},
{NULL, TLSEXT_SIGALG_ecdsa_sha1,
NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
- NID_ecdsa_with_SHA1, NID_undef},
-#endif
+ NID_ecdsa_with_SHA1, NID_undef, 1},
{"rsa_pss_rsae_sha256", TLSEXT_SIGALG_rsa_pss_rsae_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{"rsa_pss_rsae_sha384", TLSEXT_SIGALG_rsa_pss_rsae_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{"rsa_pss_rsae_sha512", TLSEXT_SIGALG_rsa_pss_rsae_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{"rsa_pss_pss_sha256", TLSEXT_SIGALG_rsa_pss_pss_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{"rsa_pss_pss_sha384", TLSEXT_SIGALG_rsa_pss_pss_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{"rsa_pss_pss_sha512", TLSEXT_SIGALG_rsa_pss_pss_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{"rsa_pkcs1_sha256", TLSEXT_SIGALG_rsa_pkcs1_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
- NID_sha256WithRSAEncryption, NID_undef},
+ NID_sha256WithRSAEncryption, NID_undef, 1},
{"rsa_pkcs1_sha384", TLSEXT_SIGALG_rsa_pkcs1_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
- NID_sha384WithRSAEncryption, NID_undef},
+ NID_sha384WithRSAEncryption, NID_undef, 1},
{"rsa_pkcs1_sha512", TLSEXT_SIGALG_rsa_pkcs1_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
- NID_sha512WithRSAEncryption, NID_undef},
+ NID_sha512WithRSAEncryption, NID_undef, 1},
{"rsa_pkcs1_sha224", TLSEXT_SIGALG_rsa_pkcs1_sha224,
NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
- NID_sha224WithRSAEncryption, NID_undef},
+ NID_sha224WithRSAEncryption, NID_undef, 1},
{"rsa_pkcs1_sha1", TLSEXT_SIGALG_rsa_pkcs1_sha1,
NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
- NID_sha1WithRSAEncryption, NID_undef},
-#ifndef OPENSSL_NO_DSA
+ NID_sha1WithRSAEncryption, NID_undef, 1},
{NULL, TLSEXT_SIGALG_dsa_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
- NID_dsa_with_SHA256, NID_undef},
+ NID_dsa_with_SHA256, NID_undef, 1},
{NULL, TLSEXT_SIGALG_dsa_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_dsa_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_dsa_sha224,
NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_dsa_sha1,
NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
- NID_dsaWithSHA1, NID_undef},
-#endif
+ NID_dsaWithSHA1, NID_undef, 1},
#ifndef OPENSSL_NO_GOST
+ {NULL, TLSEXT_SIGALG_gostr34102012_256_intrinsic,
+ NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX,
+ NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256,
+ NID_undef, NID_undef, 1},
+ {NULL, TLSEXT_SIGALG_gostr34102012_512_intrinsic,
+ NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX,
+ NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512,
+ NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256,
NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX,
NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512,
NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX,
NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_gostr34102001_gostr3411,
NID_id_GostR3411_94, SSL_MD_GOST94_IDX,
NID_id_GostR3410_2001, SSL_PKEY_GOST01,
- NID_undef, NID_undef}
+ NID_undef, NID_undef, 1}
#endif
};
/* Legacy sigalgs for TLS < 1.2 RSA TLS signatures */
@@ -777,7 +1123,7 @@ static const SIGALG_LOOKUP legacy_rsa_sigalg = {
"rsa_pkcs1_md5_sha1", 0,
NID_md5_sha1, SSL_MD_MD5_SHA1_IDX,
EVP_PKEY_RSA, SSL_PKEY_RSA,
- NID_undef, NID_undef
+ NID_undef, NID_undef, 1
};
/*
@@ -790,27 +1136,86 @@ static const uint16_t tls_default_sigalg[] = {
TLSEXT_SIGALG_dsa_sha1, /* SSL_PKEY_DSA_SIGN */
TLSEXT_SIGALG_ecdsa_sha1, /* SSL_PKEY_ECC */
TLSEXT_SIGALG_gostr34102001_gostr3411, /* SSL_PKEY_GOST01 */
- TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, /* SSL_PKEY_GOST12_256 */
- TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512, /* SSL_PKEY_GOST12_512 */
+ TLSEXT_SIGALG_gostr34102012_256_intrinsic, /* SSL_PKEY_GOST12_256 */
+ TLSEXT_SIGALG_gostr34102012_512_intrinsic, /* SSL_PKEY_GOST12_512 */
0, /* SSL_PKEY_ED25519 */
0, /* SSL_PKEY_ED448 */
};
+int ssl_setup_sig_algs(SSL_CTX *ctx)
+{
+ size_t i;
+ const SIGALG_LOOKUP *lu;
+ SIGALG_LOOKUP *cache
+ = OPENSSL_malloc(sizeof(*lu) * OSSL_NELEM(sigalg_lookup_tbl));
+ EVP_PKEY *tmpkey = EVP_PKEY_new();
+ int ret = 0;
+
+ if (cache == NULL || tmpkey == NULL)
+ goto err;
+
+ ERR_set_mark();
+ for (i = 0, lu = sigalg_lookup_tbl;
+ i < OSSL_NELEM(sigalg_lookup_tbl); lu++, i++) {
+ EVP_PKEY_CTX *pctx;
+
+ cache[i] = *lu;
+
+ /*
+ * Check hash is available.
+ * This test is not perfect. A provider could have support
+ * for a signature scheme, but not a particular hash. However the hash
+ * could be available from some other loaded provider. In that case it
+ * could be that the signature is available, and the hash is available
+ * independently - but not as a combination. We ignore this for now.
+ */
+ if (lu->hash != NID_undef
+ && ctx->ssl_digest_methods[lu->hash_idx] == NULL) {
+ cache[i].enabled = 0;
+ continue;
+ }
+
+ if (!EVP_PKEY_set_type(tmpkey, lu->sig)) {
+ cache[i].enabled = 0;
+ continue;
+ }
+ pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, tmpkey, ctx->propq);
+ /* If unable to create pctx we assume the sig algorithm is unavailable */
+ if (pctx == NULL)
+ cache[i].enabled = 0;
+ EVP_PKEY_CTX_free(pctx);
+ }
+ ERR_pop_to_mark();
+ ctx->sigalg_lookup_cache = cache;
+ cache = NULL;
+
+ ret = 1;
+ err:
+ OPENSSL_free(cache);
+ EVP_PKEY_free(tmpkey);
+ return ret;
+}
+
/* Lookup TLS signature algorithm */
-static const SIGALG_LOOKUP *tls1_lookup_sigalg(uint16_t sigalg)
+static const SIGALG_LOOKUP *tls1_lookup_sigalg(const SSL *s, uint16_t sigalg)
{
size_t i;
- const SIGALG_LOOKUP *s;
+ const SIGALG_LOOKUP *lu;
- for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
- i++, s++) {
- if (s->sigalg == sigalg)
- return s;
+ for (i = 0, lu = s->ctx->sigalg_lookup_cache;
+ /* cache should have the same number of elements as sigalg_lookup_tbl */
+ i < OSSL_NELEM(sigalg_lookup_tbl);
+ lu++, i++) {
+ if (lu->sigalg == sigalg) {
+ if (!lu->enabled)
+ return NULL;
+ return lu;
+ }
}
return NULL;
}
/* Lookup hash: return 0 if invalid or not enabled */
-int tls1_lookup_md(const SIGALG_LOOKUP *lu, const EVP_MD **pmd)
+int tls1_lookup_md(SSL_CTX *ctx, const SIGALG_LOOKUP *lu, const EVP_MD **pmd)
{
const EVP_MD *md;
if (lu == NULL)
@@ -819,7 +1224,7 @@ int tls1_lookup_md(const SIGALG_LOOKUP *lu, const EVP_MD **pmd)
if (lu->hash == NID_undef) {
md = NULL;
} else {
- md = ssl_md(lu->hash_idx);
+ md = ssl_md(ctx, lu->hash_idx);
if (md == NULL)
return 0;
}
@@ -835,16 +1240,17 @@ int tls1_lookup_md(const SIGALG_LOOKUP *lu, const EVP_MD **pmd)
* SHA512 has a hash length of 64 bytes, which is incompatible
* with a 128 byte (1024 bit) key.
*/
-#define RSA_PSS_MINIMUM_KEY_SIZE(md) (2 * EVP_MD_size(md) + 2)
-static int rsa_pss_check_min_key_size(const RSA *rsa, const SIGALG_LOOKUP *lu)
+#define RSA_PSS_MINIMUM_KEY_SIZE(md) (2 * EVP_MD_get_size(md) + 2)
+static int rsa_pss_check_min_key_size(SSL_CTX *ctx, const EVP_PKEY *pkey,
+ const SIGALG_LOOKUP *lu)
{
const EVP_MD *md;
- if (rsa == NULL)
+ if (pkey == NULL)
return 0;
- if (!tls1_lookup_md(lu, &md) || md == NULL)
+ if (!tls1_lookup_md(ctx, lu, &md) || md == NULL)
return 0;
- if (RSA_size(rsa) < RSA_PSS_MINIMUM_KEY_SIZE(md))
+ if (EVP_PKEY_get_size(pkey) < RSA_PSS_MINIMUM_KEY_SIZE(md))
return 0;
return 1;
}
@@ -866,7 +1272,9 @@ static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL *s, int idx)
for (i = 0; i < SSL_PKEY_NUM; i++) {
const SSL_CERT_LOOKUP *clu = ssl_cert_lookup_by_idx(i);
- if (clu->amask & s->s3->tmp.new_cipher->algorithm_auth) {
+ if (clu == NULL)
+ continue;
+ if (clu->amask & s->s3.tmp.new_cipher->algorithm_auth) {
idx = i;
break;
}
@@ -875,7 +1283,7 @@ static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL *s, int idx)
/*
* Some GOST ciphersuites allow more than one signature algorithms
* */
- if (idx == SSL_PKEY_GOST01 && s->s3->tmp.new_cipher->algorithm_auth != SSL_aGOST01) {
+ if (idx == SSL_PKEY_GOST01 && s->s3.tmp.new_cipher->algorithm_auth != SSL_aGOST01) {
int real_idx;
for (real_idx = SSL_PKEY_GOST12_512; real_idx >= SSL_PKEY_GOST01;
@@ -886,6 +1294,21 @@ static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL *s, int idx)
}
}
}
+ /*
+ * As both SSL_PKEY_GOST12_512 and SSL_PKEY_GOST12_256 indices can be used
+ * with new (aGOST12-only) ciphersuites, we should find out which one is available really.
+ */
+ else if (idx == SSL_PKEY_GOST12_256) {
+ int real_idx;
+
+ for (real_idx = SSL_PKEY_GOST12_512; real_idx >= SSL_PKEY_GOST12_256;
+ real_idx--) {
+ if (s->cert->pkeys[real_idx].privatekey != NULL) {
+ idx = real_idx;
+ break;
+ }
+ }
+ }
} else {
idx = s->cert->key - s->cert->pkeys;
}
@@ -893,9 +1316,11 @@ static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL *s, int idx)
if (idx < 0 || idx >= (int)OSSL_NELEM(tls_default_sigalg))
return NULL;
if (SSL_USE_SIGALGS(s) || idx != SSL_PKEY_RSA) {
- const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(tls_default_sigalg[idx]);
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, tls_default_sigalg[idx]);
- if (!tls1_lookup_md(lu, NULL))
+ if (lu == NULL)
+ return NULL;
+ if (!tls1_lookup_md(s->ctx, lu, NULL))
return NULL;
if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu))
return NULL;
@@ -916,7 +1341,7 @@ int tls1_set_peer_legacy_sigalg(SSL *s, const EVP_PKEY *pkey)
lu = tls1_get_legacy_sigalg(s, idx);
if (lu == NULL)
return 0;
- s->s3->tmp.peer_sigalg = lu;
+ s->s3.tmp.peer_sigalg = lu;
return 1;
}
@@ -926,7 +1351,6 @@ size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs)
* If Suite B mode use Suite B sigalgs only, ignore any other
* preferences.
*/
-#ifndef OPENSSL_NO_EC
switch (tls1_suiteb(s)) {
case SSL_CERT_FLAG_SUITEB_128_LOS:
*psigs = suiteb_sigalgs;
@@ -940,7 +1364,6 @@ size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs)
*psigs = suiteb_sigalgs + 1;
return 1;
}
-#endif
/*
* We use client_sigalgs (if not NULL) if we're a server
* and sending a certificate request or if we're a client and
@@ -958,7 +1381,6 @@ size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs)
}
}
-#ifndef OPENSSL_NO_EC
/*
* Called by servers only. Checks that we have a sig alg that supports the
* specified EC curve.
@@ -977,7 +1399,7 @@ int tls_check_sigalg_curve(const SSL *s, int curve)
}
for (i = 0; i < siglen; i++) {
- const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(sigs[i]);
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, sigs[i]);
if (lu == NULL)
continue;
@@ -989,23 +1411,40 @@ int tls_check_sigalg_curve(const SSL *s, int curve)
return 0;
}
-#endif
/*
* Return the number of security bits for the signature algorithm, or 0 on
* error.
*/
-static int sigalg_security_bits(const SIGALG_LOOKUP *lu)
+static int sigalg_security_bits(SSL_CTX *ctx, const SIGALG_LOOKUP *lu)
{
const EVP_MD *md = NULL;
int secbits = 0;
- if (!tls1_lookup_md(lu, &md))
+ if (!tls1_lookup_md(ctx, lu, &md))
return 0;
if (md != NULL)
{
+ int md_type = EVP_MD_get_type(md);
+
/* Security bits: half digest bits */
- secbits = EVP_MD_size(md) * 4;
+ secbits = EVP_MD_get_size(md) * 4;
+ /*
+ * SHA1 and MD5 are known to be broken. Reduce security bits so that
+ * they're no longer accepted at security level 1. The real values don't
+ * really matter as long as they're lower than 80, which is our
+ * security level 1.
+ * https://eprint.iacr.org/2020/014 puts a chosen-prefix attack for
+ * SHA1 at 2^63.4 and MD5+SHA1 at 2^67.2
+ * https://documents.epfl.ch/users/l/le/lenstra/public/papers/lat.pdf
+ * puts a chosen-prefix attack for MD5 at 2^39.
+ */
+ if (md_type == NID_sha1)
+ secbits = 64;
+ else if (md_type == NID_md5_sha1)
+ secbits = 67;
+ else if (md_type == NID_md5)
+ secbits = 39;
} else {
/* Values from https://tools.ietf.org/html/rfc8032#section-8.5 */
if (lu->sigalg == TLSEXT_SIGALG_ed25519)
@@ -1027,25 +1466,25 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
const EVP_MD *md = NULL;
char sigalgstr[2];
size_t sent_sigslen, i, cidx;
- int pkeyid = EVP_PKEY_id(pkey);
+ int pkeyid = -1;
const SIGALG_LOOKUP *lu;
int secbits = 0;
+ pkeyid = EVP_PKEY_get_id(pkey);
/* Should never happen */
if (pkeyid == -1)
return -1;
if (SSL_IS_TLS13(s)) {
/* Disallow DSA for TLS 1.3 */
if (pkeyid == EVP_PKEY_DSA) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG,
- SSL_R_WRONG_SIGNATURE_TYPE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
/* Only allow PSS for TLS 1.3 */
if (pkeyid == EVP_PKEY_RSA)
pkeyid = EVP_PKEY_RSA_PSS;
}
- lu = tls1_lookup_sigalg(sig);
+ lu = tls1_lookup_sigalg(s, sig);
/*
* Check sigalgs is known. Disallow SHA1/SHA224 with TLS 1.3. Check key type
* is consistent with signature: RSA keys can be used for RSA-PSS
@@ -1054,45 +1493,38 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
|| (SSL_IS_TLS13(s) && (lu->hash == NID_sha1 || lu->hash == NID_sha224))
|| (pkeyid != lu->sig
&& (lu->sig != EVP_PKEY_RSA_PSS || pkeyid != EVP_PKEY_RSA))) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG,
- SSL_R_WRONG_SIGNATURE_TYPE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
/* Check the sigalg is consistent with the key OID */
- if (!ssl_cert_lookup_by_nid(EVP_PKEY_id(pkey), &cidx)
+ if (!ssl_cert_lookup_by_nid(EVP_PKEY_get_id(pkey), &cidx)
|| lu->sig_idx != (int)cidx) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG,
- SSL_R_WRONG_SIGNATURE_TYPE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
-#ifndef OPENSSL_NO_EC
if (pkeyid == EVP_PKEY_EC) {
/* Check point compression is permitted */
if (!tls1_check_pkey_comp(s, pkey)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS12_CHECK_PEER_SIGALG,
SSL_R_ILLEGAL_POINT_COMPRESSION);
return 0;
}
/* For TLS 1.3 or Suite B check curve matches signature algorithm */
if (SSL_IS_TLS13(s) || tls1_suiteb(s)) {
- EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
- int curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
+ int curve = ssl_get_EC_curve_nid(pkey);
if (lu->curve != NID_undef && curve != lu->curve) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_CURVE);
return 0;
}
}
if (!SSL_IS_TLS13(s)) {
/* Check curve matches extensions */
if (!tls1_check_group_id(s, tls1_get_group_id(pkey), 1)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_CURVE);
return 0;
}
if (tls1_suiteb(s)) {
@@ -1100,18 +1532,15 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
if (sig != TLSEXT_SIGALG_ecdsa_secp256r1_sha256
&& sig != TLSEXT_SIGALG_ecdsa_secp384r1_sha384) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS12_CHECK_PEER_SIGALG,
SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
}
}
} else if (tls1_suiteb(s)) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
- SSL_R_WRONG_SIGNATURE_TYPE);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
-#endif
/* Check signature matches a type we sent */
sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
@@ -1122,13 +1551,11 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
/* Allow fallback to SHA1 if not strict mode */
if (i == sent_sigslen && (lu->hash != NID_sha1
|| s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
- SSL_R_WRONG_SIGNATURE_TYPE);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
- if (!tls1_lookup_md(lu, &md)) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
- SSL_R_UNKNOWN_DIGEST);
+ if (!tls1_lookup_md(s->ctx, lu, &md)) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_UNKNOWN_DIGEST);
return 0;
}
/*
@@ -1137,33 +1564,32 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
*/
sigalgstr[0] = (sig >> 8) & 0xff;
sigalgstr[1] = sig & 0xff;
- secbits = sigalg_security_bits(lu);
+ secbits = sigalg_security_bits(s->ctx, lu);
if (secbits == 0 ||
!ssl_security(s, SSL_SECOP_SIGALG_CHECK, secbits,
- md != NULL ? EVP_MD_type(md) : NID_undef,
+ md != NULL ? EVP_MD_get_type(md) : NID_undef,
(void *)sigalgstr)) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
- SSL_R_WRONG_SIGNATURE_TYPE);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
/* Store the sigalg the peer uses */
- s->s3->tmp.peer_sigalg = lu;
+ s->s3.tmp.peer_sigalg = lu;
return 1;
}
int SSL_get_peer_signature_type_nid(const SSL *s, int *pnid)
{
- if (s->s3->tmp.peer_sigalg == NULL)
+ if (s->s3.tmp.peer_sigalg == NULL)
return 0;
- *pnid = s->s3->tmp.peer_sigalg->sig;
+ *pnid = s->s3.tmp.peer_sigalg->sig;
return 1;
}
int SSL_get_signature_type_nid(const SSL *s, int *pnid)
{
- if (s->s3->tmp.sigalg == NULL)
+ if (s->s3.tmp.sigalg == NULL)
return 0;
- *pnid = s->s3->tmp.sigalg->sig;
+ *pnid = s->s3.tmp.sigalg->sig;
return 1;
}
@@ -1179,23 +1605,23 @@ int SSL_get_signature_type_nid(const SSL *s, int *pnid)
*/
int ssl_set_client_disabled(SSL *s)
{
- s->s3->tmp.mask_a = 0;
- s->s3->tmp.mask_k = 0;
- ssl_set_sig_mask(&s->s3->tmp.mask_a, s, SSL_SECOP_SIGALG_MASK);
- if (ssl_get_min_max_version(s, &s->s3->tmp.min_ver,
- &s->s3->tmp.max_ver, NULL) != 0)
+ s->s3.tmp.mask_a = 0;
+ s->s3.tmp.mask_k = 0;
+ ssl_set_sig_mask(&s->s3.tmp.mask_a, s, SSL_SECOP_SIGALG_MASK);
+ if (ssl_get_min_max_version(s, &s->s3.tmp.min_ver,
+ &s->s3.tmp.max_ver, NULL) != 0)
return 0;
#ifndef OPENSSL_NO_PSK
/* with PSK there must be client callback set */
if (!s->psk_client_callback) {
- s->s3->tmp.mask_a |= SSL_aPSK;
- s->s3->tmp.mask_k |= SSL_PSK;
+ s->s3.tmp.mask_a |= SSL_aPSK;
+ s->s3.tmp.mask_k |= SSL_PSK;
}
#endif /* OPENSSL_NO_PSK */
#ifndef OPENSSL_NO_SRP
if (!(s->srp_ctx.srp_Mask & SSL_kSRP)) {
- s->s3->tmp.mask_a |= SSL_aSRP;
- s->s3->tmp.mask_k |= SSL_kSRP;
+ s->s3.tmp.mask_a |= SSL_aSRP;
+ s->s3.tmp.mask_k |= SSL_kSRP;
}
#endif
return 1;
@@ -1212,10 +1638,10 @@ int ssl_set_client_disabled(SSL *s)
*/
int ssl_cipher_disabled(const SSL *s, const SSL_CIPHER *c, int op, int ecdhe)
{
- if (c->algorithm_mkey & s->s3->tmp.mask_k
- || c->algorithm_auth & s->s3->tmp.mask_a)
+ if (c->algorithm_mkey & s->s3.tmp.mask_k
+ || c->algorithm_auth & s->s3.tmp.mask_a)
return 1;
- if (s->s3->tmp.max_ver == 0)
+ if (s->s3.tmp.max_ver == 0)
return 1;
if (!SSL_IS_DTLS(s)) {
int min_tls = c->min_tls;
@@ -1228,11 +1654,11 @@ int ssl_cipher_disabled(const SSL *s, const SSL_CIPHER *c, int op, int ecdhe)
&& (c->algorithm_mkey & (SSL_kECDHE | SSL_kECDHEPSK)) != 0)
min_tls = SSL3_VERSION;
- if ((min_tls > s->s3->tmp.max_ver) || (c->max_tls < s->s3->tmp.min_ver))
+ if ((min_tls > s->s3.tmp.max_ver) || (c->max_tls < s->s3.tmp.min_ver))
return 1;
}
- if (SSL_IS_DTLS(s) && (DTLS_VERSION_GT(c->min_dtls, s->s3->tmp.max_ver)
- || DTLS_VERSION_LT(c->max_dtls, s->s3->tmp.min_ver)))
+ if (SSL_IS_DTLS(s) && (DTLS_VERSION_GT(c->min_dtls, s->s3.tmp.max_ver)
+ || DTLS_VERSION_LT(c->max_dtls, s->s3.tmp.min_ver)))
return 1;
return !ssl_security(s, op, c->strength_bits, 0, (void *)c);
@@ -1255,13 +1681,13 @@ int tls1_set_server_sigalgs(SSL *s)
s->shared_sigalgslen = 0;
/* Clear certificate validity flags */
for (i = 0; i < SSL_PKEY_NUM; i++)
- s->s3->tmp.valid_flags[i] = 0;
+ s->s3.tmp.valid_flags[i] = 0;
/*
* If peer sent no signature algorithms check to see if we support
* the default algorithm for each certificate type
*/
- if (s->s3->tmp.peer_cert_sigalgs == NULL
- && s->s3->tmp.peer_sigalgs == NULL) {
+ if (s->s3.tmp.peer_cert_sigalgs == NULL
+ && s->s3.tmp.peer_sigalgs == NULL) {
const uint16_t *sent_sigs;
size_t sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
@@ -1274,7 +1700,7 @@ int tls1_set_server_sigalgs(SSL *s)
/* Check default matches a type we sent */
for (j = 0; j < sent_sigslen; j++) {
if (lu->sigalg == sent_sigs[j]) {
- s->s3->tmp.valid_flags[i] = CERT_PKEY_SIGN;
+ s->s3.tmp.valid_flags[i] = CERT_PKEY_SIGN;
break;
}
}
@@ -1283,15 +1709,14 @@ int tls1_set_server_sigalgs(SSL *s)
}
if (!tls1_process_sigalgs(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS1_SET_SERVER_SIGALGS, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (s->shared_sigalgs != NULL)
return 1;
/* Fatal error if no shared signature algorithms */
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS1_SET_SERVER_SIGALGS,
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS);
return 0;
}
@@ -1360,11 +1785,11 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick,
SSL_SESSION *sess = NULL;
unsigned char *sdec;
const unsigned char *p;
- int slen, renew_ticket = 0, declen;
+ int slen, ivlen, renew_ticket = 0, declen;
SSL_TICKET_STATUS ret = SSL_TICKET_FATAL_ERR_OTHER;
size_t mlen;
unsigned char tick_hmac[EVP_MAX_MD_SIZE];
- HMAC_CTX *hctx = NULL;
+ SSL_HMAC *hctx = NULL;
EVP_CIPHER_CTX *ctx = NULL;
SSL_CTX *tctx = s->session_ctx;
@@ -1394,7 +1819,7 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick,
}
/* Initialize session ticket encryption and HMAC contexts */
- hctx = HMAC_CTX_new();
+ hctx = ssl_hmac_new(tctx);
if (hctx == NULL) {
ret = SSL_TICKET_FATAL_ERR_MALLOC;
goto end;
@@ -1404,11 +1829,28 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick,
ret = SSL_TICKET_FATAL_ERR_MALLOC;
goto end;
}
- if (tctx->ext.ticket_key_cb) {
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (tctx->ext.ticket_key_evp_cb != NULL || tctx->ext.ticket_key_cb != NULL)
+#else
+ if (tctx->ext.ticket_key_evp_cb != NULL)
+#endif
+ {
unsigned char *nctick = (unsigned char *)etick;
- int rv = tctx->ext.ticket_key_cb(s, nctick,
+ int rv = 0;
+
+ if (tctx->ext.ticket_key_evp_cb != NULL)
+ rv = tctx->ext.ticket_key_evp_cb(s, nctick,
+ nctick + TLSEXT_KEYNAME_LENGTH,
+ ctx,
+ ssl_hmac_get0_EVP_MAC_CTX(hctx),
+ 0);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ else if (tctx->ext.ticket_key_cb != NULL)
+ /* if 0 is returned, write an empty ticket */
+ rv = tctx->ext.ticket_key_cb(s, nctick,
nctick + TLSEXT_KEYNAME_LENGTH,
- ctx, hctx, 0);
+ ctx, ssl_hmac_get0_HMAC_CTX(hctx), 0);
+#endif
if (rv < 0) {
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
@@ -1420,21 +1862,29 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick,
if (rv == 2)
renew_ticket = 1;
} else {
+ EVP_CIPHER *aes256cbc = NULL;
+
/* Check key name matches */
if (memcmp(etick, tctx->ext.tick_key_name,
TLSEXT_KEYNAME_LENGTH) != 0) {
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
- if (HMAC_Init_ex(hctx, tctx->ext.secure->tick_hmac_key,
- sizeof(tctx->ext.secure->tick_hmac_key),
- EVP_sha256(), NULL) <= 0
- || EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL,
+
+ aes256cbc = EVP_CIPHER_fetch(s->ctx->libctx, "AES-256-CBC",
+ s->ctx->propq);
+ if (aes256cbc == NULL
+ || ssl_hmac_init(hctx, tctx->ext.secure->tick_hmac_key,
+ sizeof(tctx->ext.secure->tick_hmac_key),
+ "SHA256") <= 0
+ || EVP_DecryptInit_ex(ctx, aes256cbc, NULL,
tctx->ext.secure->tick_aes_key,
etick + TLSEXT_KEYNAME_LENGTH) <= 0) {
+ EVP_CIPHER_free(aes256cbc);
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
+ EVP_CIPHER_free(aes256cbc);
if (SSL_IS_TLS13(s))
renew_ticket = 1;
}
@@ -1442,22 +1892,27 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick,
* Attempt to process session ticket, first conduct sanity and integrity
* checks on ticket.
*/
- mlen = HMAC_size(hctx);
+ mlen = ssl_hmac_size(hctx);
if (mlen == 0) {
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
+ ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
+ if (ivlen < 0) {
+ ret = SSL_TICKET_FATAL_ERR_OTHER;
+ goto end;
+ }
+
/* Sanity check ticket length: must exceed keyname + IV + HMAC */
- if (eticklen <=
- TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx) + mlen) {
+ if (eticklen <= TLSEXT_KEYNAME_LENGTH + ivlen + mlen) {
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
eticklen -= mlen;
/* Check HMAC of encrypted ticket */
- if (HMAC_Update(hctx, etick, eticklen) <= 0
- || HMAC_Final(hctx, tick_hmac, NULL) <= 0) {
+ if (ssl_hmac_update(hctx, etick, eticklen) <= 0
+ || ssl_hmac_final(hctx, tick_hmac, NULL, sizeof(tick_hmac)) <= 0) {
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
@@ -1468,8 +1923,8 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick,
}
/* Attempt to decrypt session data */
/* Move p after IV to start of encrypted ticket, update length */
- p = etick + TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx);
- eticklen -= TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx);
+ p = etick + TLSEXT_KEYNAME_LENGTH + ivlen;
+ eticklen -= TLSEXT_KEYNAME_LENGTH + ivlen;
sdec = OPENSSL_malloc(eticklen);
if (sdec == NULL || EVP_DecryptUpdate(ctx, sdec, &slen, p,
(int)eticklen) <= 0) {
@@ -1520,7 +1975,7 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick,
end:
EVP_CIPHER_CTX_free(ctx);
- HMAC_CTX_free(hctx);
+ ssl_hmac_free(hctx);
/*
* If set, the decrypt_ticket_cb() is called unless a fatal error was
@@ -1595,21 +2050,23 @@ static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu)
unsigned char sigalgstr[2];
int secbits;
- /* See if sigalgs is recognised and if hash is enabled */
- if (!tls1_lookup_md(lu, NULL))
+ if (lu == NULL || !lu->enabled)
return 0;
/* DSA is not allowed in TLS 1.3 */
if (SSL_IS_TLS13(s) && lu->sig == EVP_PKEY_DSA)
return 0;
- /* TODO(OpenSSL1.2) fully axe DSA/etc. in ClientHello per TLS 1.3 spec */
- if (!s->server && !SSL_IS_DTLS(s) && s->s3->tmp.min_ver >= TLS1_3_VERSION
+ /*
+ * At some point we should fully axe DSA/etc. in ClientHello as per TLS 1.3
+ * spec
+ */
+ if (!s->server && !SSL_IS_DTLS(s) && s->s3.tmp.min_ver >= TLS1_3_VERSION
&& (lu->sig == EVP_PKEY_DSA || lu->hash_idx == SSL_MD_SHA1_IDX
|| lu->hash_idx == SSL_MD_MD5_IDX
|| lu->hash_idx == SSL_MD_SHA224_IDX))
return 0;
/* See if public key algorithm allowed */
- if (ssl_cert_is_disabled(lu->sig_idx))
+ if (ssl_cert_is_disabled(s->ctx, lu->sig_idx))
return 0;
if (lu->sig == NID_id_GostR3410_2012_256
@@ -1620,7 +2077,7 @@ static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu)
return 0;
if (!s->server
&& s->method->version == TLS_ANY_VERSION
- && s->s3->tmp.max_ver >= TLS1_3_VERSION) {
+ && s->s3.tmp.max_ver >= TLS1_3_VERSION) {
int i, num;
STACK_OF(SSL_CIPHER) *sk;
@@ -1630,7 +2087,7 @@ static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu)
* ciphersuites enabled.
*/
- if (s->s3->tmp.min_ver >= TLS1_3_VERSION)
+ if (s->s3.tmp.min_ver >= TLS1_3_VERSION)
return 0;
sk = SSL_get_ciphers(s);
@@ -1643,7 +2100,7 @@ static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu)
if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0))
continue;
- if ((c->algorithm_mkey & SSL_kGOST) != 0)
+ if ((c->algorithm_mkey & (SSL_kGOST | SSL_kGOST18)) != 0)
break;
}
if (i == num)
@@ -1652,7 +2109,7 @@ static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu)
}
/* Finally see if security callback allows it */
- secbits = sigalg_security_bits(lu);
+ secbits = sigalg_security_bits(s->ctx, lu);
sigalgstr[0] = (lu->sigalg >> 8) & 0xff;
sigalgstr[1] = lu->sigalg & 0xff;
return ssl_security(s, op, secbits, lu->hash, (void *)sigalgstr);
@@ -1675,15 +2132,15 @@ void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op)
*/
sigalgslen = tls12_get_psigalgs(s, 1, &sigalgs);
for (i = 0; i < sigalgslen; i++, sigalgs++) {
- const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*sigalgs);
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *sigalgs);
const SSL_CERT_LOOKUP *clu;
if (lu == NULL)
continue;
clu = ssl_cert_lookup_by_idx(lu->sig_idx);
- if (clu == NULL)
- continue;
+ if (clu == NULL)
+ continue;
/* If algorithm is disabled see if we can enable it */
if ((clu->amask & disabled_mask) != 0
@@ -1700,9 +2157,10 @@ int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
int rv = 0;
for (i = 0; i < psiglen; i++, psig++) {
- const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*psig);
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *psig);
- if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu))
+ if (lu == NULL
+ || !tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu))
continue;
if (!WPACKET_put_bytes_u16(pkt, *psig))
return 0;
@@ -1717,7 +2175,7 @@ int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
rv = 1;
}
if (rv == 0)
- SSLerr(SSL_F_TLS12_COPY_SIGALGS, SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return rv;
}
@@ -1729,10 +2187,11 @@ static size_t tls12_shared_sigalgs(SSL *s, const SIGALG_LOOKUP **shsig,
const uint16_t *ptmp, *atmp;
size_t i, j, nmatch = 0;
for (i = 0, ptmp = pref; i < preflen; i++, ptmp++) {
- const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*ptmp);
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *ptmp);
/* Skip disabled hashes or signature algorithms */
- if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, lu))
+ if (lu == NULL
+ || !tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, lu))
continue;
for (j = 0, atmp = allow; j < allowlen; j++, atmp++) {
if (*ptmp == *atmp) {
@@ -1771,18 +2230,18 @@ static int tls1_set_shared_sigalgs(SSL *s)
if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || is_suiteb) {
pref = conf;
preflen = conflen;
- allow = s->s3->tmp.peer_sigalgs;
- allowlen = s->s3->tmp.peer_sigalgslen;
+ allow = s->s3.tmp.peer_sigalgs;
+ allowlen = s->s3.tmp.peer_sigalgslen;
} else {
allow = conf;
allowlen = conflen;
- pref = s->s3->tmp.peer_sigalgs;
- preflen = s->s3->tmp.peer_sigalgslen;
+ pref = s->s3.tmp.peer_sigalgs;
+ preflen = s->s3.tmp.peer_sigalgslen;
}
nmatch = tls12_shared_sigalgs(s, NULL, pref, preflen, allow, allowlen);
if (nmatch) {
if ((salgs = OPENSSL_malloc(nmatch * sizeof(*salgs))) == NULL) {
- SSLerr(SSL_F_TLS1_SET_SHARED_SIGALGS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
nmatch = tls12_shared_sigalgs(s, salgs, pref, preflen, allow, allowlen);
@@ -1809,7 +2268,7 @@ int tls1_save_u16(PACKET *pkt, uint16_t **pdest, size_t *pdestlen)
size >>= 1;
if ((buf = OPENSSL_malloc(size * sizeof(*buf))) == NULL) {
- SSLerr(SSL_F_TLS1_SAVE_U16, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
for (i = 0; i < size && PACKET_get_net_2(pkt, &stmp); i++)
@@ -1837,11 +2296,11 @@ int tls1_save_sigalgs(SSL *s, PACKET *pkt, int cert)
return 0;
if (cert)
- return tls1_save_u16(pkt, &s->s3->tmp.peer_cert_sigalgs,
- &s->s3->tmp.peer_cert_sigalgslen);
+ return tls1_save_u16(pkt, &s->s3.tmp.peer_cert_sigalgs,
+ &s->s3.tmp.peer_cert_sigalgslen);
else
- return tls1_save_u16(pkt, &s->s3->tmp.peer_sigalgs,
- &s->s3->tmp.peer_sigalgslen);
+ return tls1_save_u16(pkt, &s->s3.tmp.peer_sigalgs,
+ &s->s3.tmp.peer_sigalgslen);
}
@@ -1850,7 +2309,7 @@ int tls1_save_sigalgs(SSL *s, PACKET *pkt, int cert)
int tls1_process_sigalgs(SSL *s)
{
size_t i;
- uint32_t *pvalid = s->s3->tmp.valid_flags;
+ uint32_t *pvalid = s->s3.tmp.valid_flags;
if (!tls1_set_shared_sigalgs(s))
return 0;
@@ -1866,7 +2325,7 @@ int tls1_process_sigalgs(SSL *s)
if (SSL_IS_TLS13(s) && sigptr->sig == EVP_PKEY_RSA)
continue;
/* If not disabled indicate we can explicitly sign */
- if (pvalid[idx] == 0 && !ssl_cert_is_disabled(idx))
+ if (pvalid[idx] == 0 && !ssl_cert_is_disabled(s->ctx, idx))
pvalid[idx] = CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN;
}
return 1;
@@ -1876,8 +2335,8 @@ int SSL_get_sigalgs(SSL *s, int idx,
int *psign, int *phash, int *psignhash,
unsigned char *rsig, unsigned char *rhash)
{
- uint16_t *psig = s->s3->tmp.peer_sigalgs;
- size_t numsigalgs = s->s3->tmp.peer_sigalgslen;
+ uint16_t *psig = s->s3.tmp.peer_sigalgs;
+ size_t numsigalgs = s->s3.tmp.peer_sigalgslen;
if (psig == NULL || numsigalgs > INT_MAX)
return 0;
if (idx >= 0) {
@@ -1890,7 +2349,7 @@ int SSL_get_sigalgs(SSL *s, int idx,
*rhash = (unsigned char)((*psig >> 8) & 0xff);
if (rsig != NULL)
*rsig = (unsigned char)(*psig & 0xff);
- lu = tls1_lookup_sigalg(*psig);
+ lu = tls1_lookup_sigalg(s, *psig);
if (psign != NULL)
*psign = lu != NULL ? lu->sig : NID_undef;
if (phash != NULL)
@@ -2039,7 +2498,7 @@ int tls1_set_raw_sigalgs(CERT *c, const uint16_t *psigs, size_t salglen,
uint16_t *sigalgs;
if ((sigalgs = OPENSSL_malloc(salglen * sizeof(*sigalgs))) == NULL) {
- SSLerr(SSL_F_TLS1_SET_RAW_SIGALGS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(sigalgs, psigs, salglen * sizeof(*sigalgs));
@@ -2065,7 +2524,7 @@ int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen, int client)
if (salglen & 1)
return 0;
if ((sigalgs = OPENSSL_malloc((salglen / 2) * sizeof(*sigalgs))) == NULL) {
- SSLerr(SSL_F_TLS1_SET_SIGALGS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
for (i = 0, sptr = sigalgs; i < salglen; i += 2) {
@@ -2115,20 +2574,20 @@ static int tls1_check_sig_alg(SSL *s, X509 *x, int default_nid)
if (default_nid)
return sig_nid == default_nid ? 1 : 0;
- if (SSL_IS_TLS13(s) && s->s3->tmp.peer_cert_sigalgs != NULL) {
+ if (SSL_IS_TLS13(s) && s->s3.tmp.peer_cert_sigalgs != NULL) {
/*
* If we're in TLSv1.3 then we only get here if we're checking the
* chain. If the peer has specified peer_cert_sigalgs then we use them
* otherwise we default to normal sigalgs.
*/
- sigalgslen = s->s3->tmp.peer_cert_sigalgslen;
+ sigalgslen = s->s3.tmp.peer_cert_sigalgslen;
use_pc_sigalgs = 1;
} else {
sigalgslen = s->shared_sigalgslen;
}
for (i = 0; i < sigalgslen; i++) {
sigalg = use_pc_sigalgs
- ? tls1_lookup_sigalg(s->s3->tmp.peer_cert_sigalgs[i])
+ ? tls1_lookup_sigalg(s, s->s3.tmp.peer_cert_sigalgs[i])
: s->shared_sigalgs[i];
if (sigalg != NULL && sig_nid == sigalg->sigandhash)
return 1;
@@ -2139,7 +2598,7 @@ static int tls1_check_sig_alg(SSL *s, X509 *x, int default_nid)
/* Check to see if a certificate issuer name matches list of CA names */
static int ssl_check_ca_name(STACK_OF(X509_NAME) *names, X509 *x)
{
- X509_NAME *nm;
+ const X509_NAME *nm;
int i;
nm = X509_get_issuer_name(x);
for (i = 0; i < sk_X509_NAME_num(names); i++) {
@@ -2183,7 +2642,7 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
idx = (int)(cpk - c->pkeys);
} else
cpk = c->pkeys + idx;
- pvalid = s->s3->tmp.valid_flags + idx;
+ pvalid = s->s3.tmp.valid_flags + idx;
x = cpk->x509;
pk = cpk->privatekey;
chain = cpk->chain;
@@ -2200,7 +2659,7 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
if (ssl_cert_lookup_by_pkey(pk, &certidx) == NULL)
return 0;
idx = certidx;
- pvalid = s->s3->tmp.valid_flags + idx;
+ pvalid = s->s3.tmp.valid_flags + idx;
if (c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)
check_flags = CERT_PKEY_STRICT_FLAGS;
@@ -2227,8 +2686,8 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
if (TLS1_get_version(s) >= TLS1_2_VERSION && strict_mode) {
int default_nid;
int rsign = 0;
- if (s->s3->tmp.peer_cert_sigalgs != NULL
- || s->s3->tmp.peer_sigalgs != NULL) {
+ if (s->s3.tmp.peer_cert_sigalgs != NULL
+ || s->s3.tmp.peer_sigalgs != NULL) {
default_nid = 0;
/* If no sigalgs extension use defaults from RFC5246 */
} else {
@@ -2276,7 +2735,7 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
size_t j;
const uint16_t *p = c->conf_sigalgs;
for (j = 0; j < c->conf_sigalgslen; j++, p++) {
- const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*p);
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *p);
if (lu != NULL && lu->hash == NID_sha1 && lu->sig == rsign)
break;
@@ -2340,22 +2799,19 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
if (!s->server && strict_mode) {
STACK_OF(X509_NAME) *ca_dn;
int check_type = 0;
- switch (EVP_PKEY_id(pk)) {
- case EVP_PKEY_RSA:
+
+ if (EVP_PKEY_is_a(pk, "RSA"))
check_type = TLS_CT_RSA_SIGN;
- break;
- case EVP_PKEY_DSA:
+ else if (EVP_PKEY_is_a(pk, "DSA"))
check_type = TLS_CT_DSS_SIGN;
- break;
- case EVP_PKEY_EC:
+ else if (EVP_PKEY_is_a(pk, "EC"))
check_type = TLS_CT_ECDSA_SIGN;
- break;
- }
+
if (check_type) {
- const uint8_t *ctypes = s->s3->tmp.ctype;
+ const uint8_t *ctypes = s->s3.tmp.ctype;
size_t j;
- for (j = 0; j < s->s3->tmp.ctype_len; j++, ctypes++) {
+ for (j = 0; j < s->s3.tmp.ctype_len; j++, ctypes++) {
if (*ctypes == check_type) {
rv |= CERT_PKEY_CERT_TYPE;
break;
@@ -2367,7 +2823,7 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
rv |= CERT_PKEY_CERT_TYPE;
}
- ca_dn = s->s3->tmp.peer_ca_names;
+ ca_dn = s->s3.tmp.peer_ca_names;
if (ca_dn == NULL
|| sk_X509_NAME_num(ca_dn) == 0
@@ -2434,36 +2890,28 @@ int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain)
return tls1_check_chain(s, x, pk, chain, -1);
}
-#ifndef OPENSSL_NO_DH
-DH *ssl_get_auto_dh(SSL *s)
+EVP_PKEY *ssl_get_auto_dh(SSL *s)
{
- DH *dhp = NULL;
- BIGNUM *p = NULL, *g = NULL;
+ EVP_PKEY *dhp = NULL;
+ BIGNUM *p;
int dh_secbits = 80, sec_level_bits;
+ EVP_PKEY_CTX *pctx = NULL;
+ OSSL_PARAM_BLD *tmpl = NULL;
+ OSSL_PARAM *params = NULL;
if (s->cert->dh_tmp_auto != 2) {
- if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aPSK)) {
- if (s->s3->tmp.new_cipher->strength_bits == 256)
+ if (s->s3.tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aPSK)) {
+ if (s->s3.tmp.new_cipher->strength_bits == 256)
dh_secbits = 128;
else
dh_secbits = 80;
} else {
- if (s->s3->tmp.cert == NULL)
+ if (s->s3.tmp.cert == NULL)
return NULL;
- dh_secbits = EVP_PKEY_security_bits(s->s3->tmp.cert->privatekey);
+ dh_secbits = EVP_PKEY_get_security_bits(s->s3.tmp.cert->privatekey);
}
}
- dhp = DH_new();
- if (dhp == NULL)
- return NULL;
- g = BN_new();
- if (g == NULL || !BN_set_word(g, 2)) {
- DH_free(dhp);
- BN_free(g);
- return NULL;
- }
-
/* Do not pick a prime that is too weak for the current security level */
sec_level_bits = ssl_get_security_level_bits(s, NULL, NULL);
if (dh_secbits < sec_level_bits)
@@ -2479,15 +2927,32 @@ DH *ssl_get_auto_dh(SSL *s)
p = BN_get_rfc3526_prime_2048(NULL);
else
p = BN_get_rfc2409_prime_1024(NULL);
- if (p == NULL || !DH_set0_pqg(dhp, p, NULL, g)) {
- DH_free(dhp);
- BN_free(p);
- BN_free(g);
- return NULL;
- }
+ if (p == NULL)
+ goto err;
+
+ pctx = EVP_PKEY_CTX_new_from_name(s->ctx->libctx, "DH", s->ctx->propq);
+ if (pctx == NULL
+ || EVP_PKEY_fromdata_init(pctx) != 1)
+ goto err;
+
+ tmpl = OSSL_PARAM_BLD_new();
+ if (tmpl == NULL
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, p)
+ || !OSSL_PARAM_BLD_push_uint(tmpl, OSSL_PKEY_PARAM_FFC_G, 2))
+ goto err;
+
+ params = OSSL_PARAM_BLD_to_param(tmpl);
+ if (params == NULL
+ || EVP_PKEY_fromdata(pctx, &dhp, EVP_PKEY_KEY_PARAMETERS, params) != 1)
+ goto err;
+
+err:
+ OSSL_PARAM_free(params);
+ OSSL_PARAM_BLD_free(tmpl);
+ EVP_PKEY_CTX_free(pctx);
+ BN_free(p);
return dhp;
}
-#endif
static int ssl_security_cert_key(SSL *s, SSL_CTX *ctx, X509 *x, int op)
{
@@ -2500,7 +2965,7 @@ static int ssl_security_cert_key(SSL *s, SSL_CTX *ctx, X509 *x, int op)
* reject keys which omit parameters but this only affects DSA and
* omission of parameters is never (?) done in practice.
*/
- secbits = EVP_PKEY_security_bits(pkey);
+ secbits = EVP_PKEY_get_security_bits(pkey);
}
if (s)
return ssl_security(s, op, secbits, 0, x);
@@ -2584,12 +3049,12 @@ static int tls12_get_cert_sigalg_idx(const SSL *s, const SIGALG_LOOKUP *lu)
/* If not recognised or not supported by cipher mask it is not suitable */
if (clu == NULL
- || (clu->amask & s->s3->tmp.new_cipher->algorithm_auth) == 0
+ || (clu->amask & s->s3.tmp.new_cipher->algorithm_auth) == 0
|| (clu->nid == EVP_PKEY_RSA_PSS
- && (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kRSA) != 0))
+ && (s->s3.tmp.new_cipher->algorithm_mkey & SSL_kRSA) != 0))
return -1;
- return s->s3->tmp.valid_flags[sig_idx] & CERT_PKEY_VALID ? sig_idx : -1;
+ return s->s3.tmp.valid_flags[sig_idx] & CERT_PKEY_VALID ? sig_idx : -1;
}
/*
@@ -2602,27 +3067,36 @@ static int check_cert_usable(SSL *s, const SIGALG_LOOKUP *sig, X509 *x,
EVP_PKEY *pkey)
{
const SIGALG_LOOKUP *lu;
- int mdnid, pknid, default_mdnid;
+ int mdnid, pknid, supported;
size_t i;
+ const char *mdname = NULL;
- /* If the EVP_PKEY reports a mandatory digest, allow nothing else. */
- ERR_set_mark();
- if (EVP_PKEY_get_default_digest_nid(pkey, &default_mdnid) == 2 &&
- sig->hash != default_mdnid)
- return 0;
-
- /* If it didn't report a mandatory NID, for whatever reasons,
- * just clear the error and allow all hashes to be used. */
- ERR_pop_to_mark();
+ /*
+ * If the given EVP_PKEY cannot support signing with this digest,
+ * the answer is simply 'no'.
+ */
+ if (sig->hash != NID_undef)
+ mdname = OBJ_nid2sn(sig->hash);
+ supported = EVP_PKEY_digestsign_supports_digest(pkey, s->ctx->libctx,
+ mdname,
+ s->ctx->propq);
+ if (supported <= 0)
+ return 0;
- if (s->s3->tmp.peer_cert_sigalgs != NULL) {
- for (i = 0; i < s->s3->tmp.peer_cert_sigalgslen; i++) {
- lu = tls1_lookup_sigalg(s->s3->tmp.peer_cert_sigalgs[i]);
- if (lu == NULL
- || !X509_get_signature_info(x, &mdnid, &pknid, NULL, NULL))
+ /*
+ * The TLS 1.3 signature_algorithms_cert extension places restrictions
+ * on the sigalg with which the certificate was signed (by its issuer).
+ */
+ if (s->s3.tmp.peer_cert_sigalgs != NULL) {
+ if (!X509_get_signature_info(x, &mdnid, &pknid, NULL, NULL))
+ return 0;
+ for (i = 0; i < s->s3.tmp.peer_cert_sigalgslen; i++) {
+ lu = tls1_lookup_sigalg(s, s->s3.tmp.peer_cert_sigalgs[i]);
+ if (lu == NULL)
continue;
+
/*
- * TODO this does not differentiate between the
+ * This does not differentiate between the
* rsa_pss_pss_* and rsa_pss_rsae_* schemes since we do not
* have a chain here that lets us look at the key OID in the
* signing certificate.
@@ -2632,6 +3106,11 @@ static int check_cert_usable(SSL *s, const SIGALG_LOOKUP *sig, X509 *x,
}
return 0;
}
+
+ /*
+ * Without signat_algorithms_cert, any certificate for which we have
+ * a viable public key is permitted.
+ */
return 1;
}
@@ -2682,9 +3161,7 @@ static const SIGALG_LOOKUP *find_sig_alg(SSL *s, X509 *x, EVP_PKEY *pkey)
{
const SIGALG_LOOKUP *lu = NULL;
size_t i;
-#ifndef OPENSSL_NO_EC
int curve = -1;
-#endif
EVP_PKEY *tmppkey;
/* Look for a shared sigalgs matching possible certificates */
@@ -2698,7 +3175,7 @@ static const SIGALG_LOOKUP *find_sig_alg(SSL *s, X509 *x, EVP_PKEY *pkey)
|| lu->sig == EVP_PKEY_RSA)
continue;
/* Check that we have a cert, and signature_algorithms_cert */
- if (!tls1_lookup_md(lu, NULL))
+ if (!tls1_lookup_md(s->ctx, lu, NULL))
continue;
if ((pkey == NULL && !has_usable_cert(s, lu, -1))
|| (pkey != NULL && !is_cert_usable(s, lu, x, pkey)))
@@ -2708,19 +3185,13 @@ static const SIGALG_LOOKUP *find_sig_alg(SSL *s, X509 *x, EVP_PKEY *pkey)
: s->cert->pkeys[lu->sig_idx].privatekey;
if (lu->sig == EVP_PKEY_EC) {
-#ifndef OPENSSL_NO_EC
- if (curve == -1) {
- EC_KEY *ec = EVP_PKEY_get0_EC_KEY(tmppkey);
- curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
- }
+ if (curve == -1)
+ curve = ssl_get_EC_curve_nid(tmppkey);
if (lu->curve != NID_undef && curve != lu->curve)
continue;
-#else
- continue;
-#endif
} else if (lu->sig == EVP_PKEY_RSA_PSS) {
/* validate that key is large enough for the signature algorithm */
- if (!rsa_pss_check_min_key_size(EVP_PKEY_get0(tmppkey), lu))
+ if (!rsa_pss_check_min_key_size(s->ctx, tmppkey, lu))
continue;
}
break;
@@ -2748,39 +3219,34 @@ int tls_choose_sigalg(SSL *s, int fatalerrs)
const SIGALG_LOOKUP *lu = NULL;
int sig_idx = -1;
- s->s3->tmp.cert = NULL;
- s->s3->tmp.sigalg = NULL;
+ s->s3.tmp.cert = NULL;
+ s->s3.tmp.sigalg = NULL;
if (SSL_IS_TLS13(s)) {
lu = find_sig_alg(s, NULL, NULL);
if (lu == NULL) {
if (!fatalerrs)
return 1;
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CHOOSE_SIGALG,
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return 0;
}
} else {
/* If ciphersuite doesn't require a cert nothing to do */
- if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aCERT))
+ if (!(s->s3.tmp.new_cipher->algorithm_auth & SSL_aCERT))
return 1;
if (!s->server && !ssl_has_cert(s, s->cert->key - s->cert->pkeys))
return 1;
if (SSL_USE_SIGALGS(s)) {
size_t i;
- if (s->s3->tmp.peer_sigalgs != NULL) {
-#ifndef OPENSSL_NO_EC
- int curve;
+ if (s->s3.tmp.peer_sigalgs != NULL) {
+ int curve = -1;
/* For Suite B need to match signature algorithm to curve */
- if (tls1_suiteb(s)) {
- EC_KEY *ec = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey);
- curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
- } else {
- curve = -1;
- }
-#endif
+ if (tls1_suiteb(s))
+ curve = ssl_get_EC_curve_nid(s->cert->pkeys[SSL_PKEY_ECC]
+ .privatekey);
/*
* Find highest preference signature algorithm matching
@@ -2806,12 +3272,10 @@ int tls_choose_sigalg(SSL *s, int fatalerrs)
/* validate that key is large enough for the signature algorithm */
EVP_PKEY *pkey = s->cert->pkeys[sig_idx].privatekey;
- if (!rsa_pss_check_min_key_size(EVP_PKEY_get0(pkey), lu))
+ if (!rsa_pss_check_min_key_size(s->ctx, pkey, lu))
continue;
}
-#ifndef OPENSSL_NO_EC
if (curve == -1 || lu->curve == curve)
-#endif
break;
}
#ifndef OPENSSL_NO_GOST
@@ -2820,12 +3284,11 @@ int tls_choose_sigalg(SSL *s, int fatalerrs)
* in supported_algorithms extension, so when we have GOST-based ciphersuite,
* we have to assume GOST support.
*/
- if (i == s->shared_sigalgslen && s->s3->tmp.new_cipher->algorithm_auth & (SSL_aGOST01 | SSL_aGOST12)) {
+ if (i == s->shared_sigalgslen && s->s3.tmp.new_cipher->algorithm_auth & (SSL_aGOST01 | SSL_aGOST12)) {
if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
if (!fatalerrs)
return 1;
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_CHOOSE_SIGALG,
SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return 0;
} else {
@@ -2838,7 +3301,6 @@ int tls_choose_sigalg(SSL *s, int fatalerrs)
if (!fatalerrs)
return 1;
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_CHOOSE_SIGALG,
SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return 0;
}
@@ -2852,8 +3314,8 @@ int tls_choose_sigalg(SSL *s, int fatalerrs)
if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
if (!fatalerrs)
return 1;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CHOOSE_SIGALG,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return 0;
}
@@ -2867,8 +3329,7 @@ int tls_choose_sigalg(SSL *s, int fatalerrs)
if (i == sent_sigslen) {
if (!fatalerrs)
return 1;
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_CHOOSE_SIGALG,
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
@@ -2877,17 +3338,17 @@ int tls_choose_sigalg(SSL *s, int fatalerrs)
if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
if (!fatalerrs)
return 1;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CHOOSE_SIGALG,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return 0;
}
}
}
if (sig_idx == -1)
sig_idx = lu->sig_idx;
- s->s3->tmp.cert = &s->cert->pkeys[sig_idx];
- s->cert->key = s->s3->tmp.cert;
- s->s3->tmp.sigalg = lu;
+ s->s3.tmp.cert = &s->cert->pkeys[sig_idx];
+ s->cert->key = s->s3.tmp.cert;
+ s->s3.tmp.sigalg = lu;
return 1;
}
@@ -2895,8 +3356,7 @@ int SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode)
{
if (mode != TLSEXT_max_fragment_length_DISABLED
&& !IS_MAX_FRAGMENT_LENGTH_EXT_VALID(mode)) {
- SSLerr(SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH,
- SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
@@ -2908,8 +3368,7 @@ int SSL_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode)
{
if (mode != TLSEXT_max_fragment_length_DISABLED
&& !IS_MAX_FRAGMENT_LENGTH_EXT_VALID(mode)) {
- SSLerr(SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH,
- SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
+ ERR_raise(ERR_LIB_SSL, SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
@@ -2921,3 +3380,129 @@ uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *session)
{
return session->ext.max_fragment_len_mode;
}
+
+/*
+ * Helper functions for HMAC access with legacy support included.
+ */
+SSL_HMAC *ssl_hmac_new(const SSL_CTX *ctx)
+{
+ SSL_HMAC *ret = OPENSSL_zalloc(sizeof(*ret));
+ EVP_MAC *mac = NULL;
+
+ if (ret == NULL)
+ return NULL;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (ctx->ext.ticket_key_evp_cb == NULL
+ && ctx->ext.ticket_key_cb != NULL) {
+ if (!ssl_hmac_old_new(ret))
+ goto err;
+ return ret;
+ }
+#endif
+ mac = EVP_MAC_fetch(ctx->libctx, "HMAC", ctx->propq);
+ if (mac == NULL || (ret->ctx = EVP_MAC_CTX_new(mac)) == NULL)
+ goto err;
+ EVP_MAC_free(mac);
+ return ret;
+ err:
+ EVP_MAC_CTX_free(ret->ctx);
+ EVP_MAC_free(mac);
+ OPENSSL_free(ret);
+ return NULL;
+}
+
+void ssl_hmac_free(SSL_HMAC *ctx)
+{
+ if (ctx != NULL) {
+ EVP_MAC_CTX_free(ctx->ctx);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ ssl_hmac_old_free(ctx);
+#endif
+ OPENSSL_free(ctx);
+ }
+}
+
+EVP_MAC_CTX *ssl_hmac_get0_EVP_MAC_CTX(SSL_HMAC *ctx)
+{
+ return ctx->ctx;
+}
+
+int ssl_hmac_init(SSL_HMAC *ctx, void *key, size_t len, char *md)
+{
+ OSSL_PARAM params[2], *p = params;
+
+ if (ctx->ctx != NULL) {
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, md, 0);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_MAC_init(ctx->ctx, key, len, params))
+ return 1;
+ }
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (ctx->old_ctx != NULL)
+ return ssl_hmac_old_init(ctx, key, len, md);
+#endif
+ return 0;
+}
+
+int ssl_hmac_update(SSL_HMAC *ctx, const unsigned char *data, size_t len)
+{
+ if (ctx->ctx != NULL)
+ return EVP_MAC_update(ctx->ctx, data, len);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (ctx->old_ctx != NULL)
+ return ssl_hmac_old_update(ctx, data, len);
+#endif
+ return 0;
+}
+
+int ssl_hmac_final(SSL_HMAC *ctx, unsigned char *md, size_t *len,
+ size_t max_size)
+{
+ if (ctx->ctx != NULL)
+ return EVP_MAC_final(ctx->ctx, md, len, max_size);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (ctx->old_ctx != NULL)
+ return ssl_hmac_old_final(ctx, md, len);
+#endif
+ return 0;
+}
+
+size_t ssl_hmac_size(const SSL_HMAC *ctx)
+{
+ if (ctx->ctx != NULL)
+ return EVP_MAC_CTX_get_mac_size(ctx->ctx);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (ctx->old_ctx != NULL)
+ return ssl_hmac_old_size(ctx);
+#endif
+ return 0;
+}
+
+int ssl_get_EC_curve_nid(const EVP_PKEY *pkey)
+{
+ char gname[OSSL_MAX_NAME_SIZE];
+
+ if (EVP_PKEY_get_group_name(pkey, gname, sizeof(gname), NULL) > 0)
+ return OBJ_txt2nid(gname);
+
+ return NID_undef;
+}
+
+__owur int tls13_set_encoded_pub_key(EVP_PKEY *pkey,
+ const unsigned char *enckey,
+ size_t enckeylen)
+{
+ if (EVP_PKEY_is_a(pkey, "DH")) {
+ int bits = EVP_PKEY_get_bits(pkey);
+
+ if (bits <= 0 || enckeylen != (size_t)bits / 8)
+ /* the encoded key must be padded to the length of the p */
+ return 0;
+ } else if (EVP_PKEY_is_a(pkey, "EC")) {
+ if (enckeylen < 3 /* point format and at least 1 byte for x and y */
+ || enckey[0] != 0x04)
+ return 0;
+ }
+
+ return EVP_PKEY_set1_encoded_public_key(pkey, enckey, enckeylen);
+}
diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c
index e2c397b75657..405b1e6864a7 100644
--- a/ssl/t1_trce.c
+++ b/ssl/t1_trce.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -427,6 +427,7 @@ static const ssl_trace_tbl ssl_ciphers_tbl[] = {
{0xC0AD, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM"},
{0xC0AE, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8"},
{0xC0AF, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8"},
+ {0xC102, "IANA-GOST2012-GOST8912-GOST8912"},
{0xCCA8, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"},
{0xCCA9, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"},
{0xCCAA, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256"},
@@ -441,8 +442,11 @@ static const ssl_trace_tbl ssl_ciphers_tbl[] = {
{0x1305, "TLS_AES_128_CCM_8_SHA256"},
{0xFEFE, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"},
{0xFEFF, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"},
- {0xFF85, "GOST2012-GOST8912-GOST8912"},
+ {0xFF85, "LEGACY-GOST2012-GOST8912-GOST8912"},
{0xFF87, "GOST2012-NULL-GOST12"},
+ {0xC100, "GOST2012-KUZNYECHIK-KUZNYECHIKOMAC"},
+ {0xC101, "GOST2012-MAGMA-MAGMAOMAC"},
+ {0xC102, "GOST2012-GOST8912-IANA"},
};
/* Compression methods */
@@ -468,7 +472,6 @@ static const ssl_trace_tbl ssl_exts_tbl[] = {
{TLSEXT_TYPE_srp, "srp"},
{TLSEXT_TYPE_signature_algorithms, "signature_algorithms"},
{TLSEXT_TYPE_use_srtp, "use_srtp"},
- {TLSEXT_TYPE_heartbeat, "tls_heartbeat"},
{TLSEXT_TYPE_application_layer_protocol_negotiation,
"application_layer_protocol_negotiation"},
{TLSEXT_TYPE_signed_certificate_timestamp, "signed_certificate_timestamps"},
@@ -522,6 +525,13 @@ static const ssl_trace_tbl ssl_groups_tbl[] = {
{28, "brainpoolP512r1"},
{29, "ecdh_x25519"},
{30, "ecdh_x448"},
+ {34, "GC256A"},
+ {35, "GC256B"},
+ {36, "GC256C"},
+ {37, "GC256D"},
+ {38, "GC512A"},
+ {39, "GC512B"},
+ {40, "GC512C"},
{256, "ffdhe2048"},
{257, "ffdhe3072"},
{258, "ffdhe4096"},
@@ -569,6 +579,8 @@ static const ssl_trace_tbl ssl_sigalg_tbl[] = {
{TLSEXT_SIGALG_dsa_sha512, "dsa_sha512"},
{TLSEXT_SIGALG_dsa_sha224, "dsa_sha224"},
{TLSEXT_SIGALG_dsa_sha1, "dsa_sha1"},
+ {TLSEXT_SIGALG_gostr34102012_256_intrinsic, "gost2012_256"},
+ {TLSEXT_SIGALG_gostr34102012_512_intrinsic, "gost2012_512"},
{TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, "gost2012_256"},
{TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512, "gost2012_512"},
{TLSEXT_SIGALG_gostr34102001_gostr3411, "gost2001_gost94"},
@@ -584,7 +596,9 @@ static const ssl_trace_tbl ssl_ctype_tbl[] = {
{20, "fortezza_dms"},
{64, "ecdsa_sign"},
{65, "rsa_fixed_ecdh"},
- {66, "ecdsa_fixed_ecdh"}
+ {66, "ecdsa_fixed_ecdh"},
+ {67, "gost_sign256"},
+ {68, "gost_sign512"},
};
static const ssl_trace_tbl ssl_psk_kex_modes_tbl[] = {
@@ -786,9 +800,6 @@ static int ssl_print_extension(BIO *bio, int indent, int server,
}
break;
- case TLSEXT_TYPE_heartbeat:
- return 0;
-
case TLSEXT_TYPE_session_ticket:
if (extlen != 0)
ssl_print_hex(bio, indent + 4, "ticket", ext, extlen);
@@ -1039,7 +1050,7 @@ static int ssl_print_server_hello(BIO *bio, int indent,
static int ssl_get_keyex(const char **pname, const SSL *ssl)
{
- unsigned long alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
+ unsigned long alg_k = ssl->s3.tmp.new_cipher->algorithm_mkey;
if (alg_k & SSL_kRSA) {
*pname = "rsa";
@@ -1077,6 +1088,10 @@ static int ssl_get_keyex(const char **pname, const SSL *ssl)
*pname = "GOST";
return SSL_kGOST;
}
+ if (alg_k & SSL_kGOST18) {
+ *pname = "GOST18";
+ return SSL_kGOST18;
+ }
*pname = "UNKNOWN";
return 0;
}
@@ -1119,7 +1134,15 @@ static int ssl_print_client_keyex(BIO *bio, int indent, const SSL *ssl,
if (!ssl_print_hexbuf(bio, indent + 2, "ecdh_Yc", 1, &msg, &msglen))
return 0;
break;
-
+ case SSL_kGOST:
+ ssl_print_hex(bio, indent + 2, "GostKeyTransportBlob", msg, msglen);
+ msglen = 0;
+ break;
+ case SSL_kGOST18:
+ ssl_print_hex(bio, indent + 2,
+ "GOST-wrapped PreMasterSecret", msg, msglen);
+ msglen = 0;
+ break;
}
return !msglen;
@@ -1158,7 +1181,6 @@ static int ssl_print_server_keyex(BIO *bio, int indent, const SSL *ssl,
return 0;
break;
-# ifndef OPENSSL_NO_EC
case SSL_kECDHE:
case SSL_kECDHEPSK:
if (msglen < 1)
@@ -1184,7 +1206,6 @@ static int ssl_print_server_keyex(BIO *bio, int indent, const SSL *ssl,
return 0;
}
break;
-# endif
case SSL_kPSK:
case SSL_kRSAPSK:
diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c
index ff85df4483f7..ddcff5eb8911 100644
--- a/ssl/tls13_enc.c
+++ b/ssl/tls13_enc.c
@@ -1,7 +1,7 @@
/*
* Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,14 +9,20 @@
#include <stdlib.h>
#include "ssl_local.h"
+#include "internal/ktls.h"
+#include "record/record_local.h"
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/kdf.h>
+#include <openssl/core_names.h>
#define TLS13_MAX_LABEL_LEN 249
-/* Always filled with zeros */
-static const unsigned char default_zeros[EVP_MAX_MD_SIZE];
+#ifdef CHARSET_EBCDIC
+static const unsigned char label_prefix[] = { 0x74, 0x6C, 0x73, 0x31, 0x33, 0x20, 0x00 };
+#else
+static const unsigned char label_prefix[] = "tls13 ";
+#endif
/*
* Given a |secret|; a |label| of length |labellen|; and |data| of length
@@ -26,84 +32,72 @@ static const unsigned char default_zeros[EVP_MAX_MD_SIZE];
* |fatal| is set. Returns 1 on success 0 on failure.
*/
int tls13_hkdf_expand(SSL *s, const EVP_MD *md, const unsigned char *secret,
- const unsigned char *label, size_t labellen,
- const unsigned char *data, size_t datalen,
- unsigned char *out, size_t outlen, int fatal)
+ const unsigned char *label, size_t labellen,
+ const unsigned char *data, size_t datalen,
+ unsigned char *out, size_t outlen, int fatal)
{
-#ifdef CHARSET_EBCDIC
- static const unsigned char label_prefix[] = { 0x74, 0x6C, 0x73, 0x31, 0x33, 0x20, 0x00 };
-#else
- static const unsigned char label_prefix[] = "tls13 ";
-#endif
- EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
+ EVP_KDF *kdf = EVP_KDF_fetch(s->ctx->libctx, OSSL_KDF_NAME_TLS1_3_KDF,
+ s->ctx->propq);
+ EVP_KDF_CTX *kctx;
+ OSSL_PARAM params[7], *p = params;
+ int mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY;
+ const char *mdname = EVP_MD_get0_name(md);
int ret;
- size_t hkdflabellen;
size_t hashlen;
- /*
- * 2 bytes for length of derived secret + 1 byte for length of combined
- * prefix and label + bytes for the label itself + 1 byte length of hash
- * + bytes for the hash itself
- */
- unsigned char hkdflabel[sizeof(uint16_t) + sizeof(uint8_t)
- + (sizeof(label_prefix) - 1) + TLS13_MAX_LABEL_LEN
- + 1 + EVP_MAX_MD_SIZE];
- WPACKET pkt;
- if (pctx == NULL)
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+ if (kctx == NULL)
return 0;
if (labellen > TLS13_MAX_LABEL_LEN) {
if (fatal) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_HKDF_EXPAND,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
} else {
/*
* Probably we have been called from SSL_export_keying_material(),
* or SSL_export_keying_material_early().
*/
- SSLerr(SSL_F_TLS13_HKDF_EXPAND, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
+ ERR_raise(ERR_LIB_SSL, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
}
- EVP_PKEY_CTX_free(pctx);
+ EVP_KDF_CTX_free(kctx);
return 0;
}
- hashlen = EVP_MD_size(md);
-
- if (!WPACKET_init_static_len(&pkt, hkdflabel, sizeof(hkdflabel), 0)
- || !WPACKET_put_bytes_u16(&pkt, outlen)
- || !WPACKET_start_sub_packet_u8(&pkt)
- || !WPACKET_memcpy(&pkt, label_prefix, sizeof(label_prefix) - 1)
- || !WPACKET_memcpy(&pkt, label, labellen)
- || !WPACKET_close(&pkt)
- || !WPACKET_sub_memcpy_u8(&pkt, data, (data == NULL) ? 0 : datalen)
- || !WPACKET_get_total_written(&pkt, &hkdflabellen)
- || !WPACKET_finish(&pkt)) {
- EVP_PKEY_CTX_free(pctx);
- WPACKET_cleanup(&pkt);
+ if ((ret = EVP_MD_get_size(md)) <= 0) {
+ EVP_KDF_CTX_free(kctx);
if (fatal)
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_HKDF_EXPAND,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
else
- SSLerr(SSL_F_TLS13_HKDF_EXPAND, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
-
- ret = EVP_PKEY_derive_init(pctx) <= 0
- || EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY)
- <= 0
- || EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0
- || EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, hashlen) <= 0
- || EVP_PKEY_CTX_add1_hkdf_info(pctx, hkdflabel, hkdflabellen) <= 0
- || EVP_PKEY_derive(pctx, out, &outlen) <= 0;
-
- EVP_PKEY_CTX_free(pctx);
+ hashlen = (size_t)ret;
+
+ *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ (char *)mdname, 0);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ (unsigned char *)secret, hashlen);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PREFIX,
+ (unsigned char *)label_prefix,
+ sizeof(label_prefix) - 1);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_LABEL,
+ (unsigned char *)label, labellen);
+ if (data != NULL)
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_DATA,
+ (unsigned char *)data,
+ datalen);
+ *p++ = OSSL_PARAM_construct_end();
+
+ ret = EVP_KDF_derive(kctx, out, outlen, params) <= 0;
+ EVP_KDF_CTX_free(kctx);
if (ret != 0) {
if (fatal)
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_HKDF_EXPAND,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
else
- SSLerr(SSL_F_TLS13_HKDF_EXPAND, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
}
return ret == 0;
@@ -168,87 +162,61 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
size_t insecretlen,
unsigned char *outsecret)
{
- size_t mdlen, prevsecretlen;
+ size_t mdlen;
int mdleni;
int ret;
- EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx;
+ OSSL_PARAM params[7], *p = params;
+ int mode = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY;
+ const char *mdname = EVP_MD_get0_name(md);
#ifdef CHARSET_EBCDIC
static const char derived_secret_label[] = { 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x64, 0x00 };
#else
static const char derived_secret_label[] = "derived";
#endif
- unsigned char preextractsec[EVP_MAX_MD_SIZE];
- if (pctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET,
- ERR_R_INTERNAL_ERROR);
+ kdf = EVP_KDF_fetch(s->ctx->libctx, OSSL_KDF_NAME_TLS1_3_KDF, s->ctx->propq);
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+ if (kctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
- mdleni = EVP_MD_size(md);
+ mdleni = EVP_MD_get_size(md);
/* Ensure cast to size_t is safe */
if (!ossl_assert(mdleni >= 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET,
- ERR_R_INTERNAL_ERROR);
- EVP_PKEY_CTX_free(pctx);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ EVP_KDF_CTX_free(kctx);
return 0;
}
mdlen = (size_t)mdleni;
- if (insecret == NULL) {
- insecret = default_zeros;
- insecretlen = mdlen;
- }
- if (prevsecret == NULL) {
- prevsecret = default_zeros;
- prevsecretlen = 0;
- } else {
- EVP_MD_CTX *mctx = EVP_MD_CTX_new();
- unsigned char hash[EVP_MAX_MD_SIZE];
-
- /* The pre-extract derive step uses a hash of no messages */
- if (mctx == NULL
- || EVP_DigestInit_ex(mctx, md, NULL) <= 0
- || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET,
- ERR_R_INTERNAL_ERROR);
- EVP_MD_CTX_free(mctx);
- EVP_PKEY_CTX_free(pctx);
- return 0;
- }
- EVP_MD_CTX_free(mctx);
-
- /* Generate the pre-extract secret */
- if (!tls13_hkdf_expand(s, md, prevsecret,
- (unsigned char *)derived_secret_label,
- sizeof(derived_secret_label) - 1, hash, mdlen,
- preextractsec, mdlen, 1)) {
- /* SSLfatal() already called */
- EVP_PKEY_CTX_free(pctx);
- return 0;
- }
-
- prevsecret = preextractsec;
- prevsecretlen = mdlen;
- }
-
- ret = EVP_PKEY_derive_init(pctx) <= 0
- || EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY)
- <= 0
- || EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0
- || EVP_PKEY_CTX_set1_hkdf_key(pctx, insecret, insecretlen) <= 0
- || EVP_PKEY_CTX_set1_hkdf_salt(pctx, prevsecret, prevsecretlen)
- <= 0
- || EVP_PKEY_derive(pctx, outsecret, &mdlen)
- <= 0;
+ *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ (char *)mdname, 0);
+ if (insecret != NULL)
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ (unsigned char *)insecret,
+ insecretlen);
+ if (prevsecret != NULL)
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ (unsigned char *)prevsecret, mdlen);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PREFIX,
+ (unsigned char *)label_prefix,
+ sizeof(label_prefix) - 1);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_LABEL,
+ (unsigned char *)derived_secret_label,
+ sizeof(derived_secret_label) - 1);
+ *p++ = OSSL_PARAM_construct_end();
+
+ ret = EVP_KDF_derive(kctx, outsecret, mdlen, params) <= 0;
if (ret != 0)
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- EVP_PKEY_CTX_free(pctx);
- if (prevsecret == preextractsec)
- OPENSSL_cleanse(preextractsec, mdlen);
+ EVP_KDF_CTX_free(kctx);
return ret == 0;
}
@@ -277,7 +245,7 @@ int tls13_generate_master_secret(SSL *s, unsigned char *out,
{
const EVP_MD *md = ssl_handshake_md(s);
- *secret_size = EVP_MD_size(md);
+ *secret_size = EVP_MD_get_size(md);
/* Calls SSLfatal() if required */
return tls13_generate_secret(s, md, prev, NULL, 0, out);
}
@@ -290,10 +258,22 @@ size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen,
unsigned char *out)
{
const EVP_MD *md = ssl_handshake_md(s);
+ const char *mdname = EVP_MD_get0_name(md);
unsigned char hash[EVP_MAX_MD_SIZE];
- size_t hashlen, ret = 0;
- EVP_PKEY *key = NULL;
- EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+ unsigned char finsecret[EVP_MAX_MD_SIZE];
+ unsigned char *key = NULL;
+ size_t len = 0, hashlen;
+ OSSL_PARAM params[2], *p = params;
+
+ if (md == NULL)
+ return 0;
+
+ /* Safe to cast away const here since we're not "getting" any data */
+ if (s->ctx->propq != NULL)
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_PROPERTIES,
+ (char *)s->ctx->propq,
+ 0);
+ *p = OSSL_PARAM_construct_end();
if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) {
/* SSLfatal() already called */
@@ -301,39 +281,28 @@ size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen,
}
if (str == s->method->ssl3_enc->server_finished_label) {
- key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
- s->server_finished_secret, hashlen);
+ key = s->server_finished_secret;
} else if (SSL_IS_FIRST_HANDSHAKE(s)) {
- key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
- s->client_finished_secret, hashlen);
+ key = s->client_finished_secret;
} else {
- unsigned char finsecret[EVP_MAX_MD_SIZE];
-
- if (!tls13_derive_finishedkey(s, ssl_handshake_md(s),
+ if (!tls13_derive_finishedkey(s, md,
s->client_app_traffic_secret,
finsecret, hashlen))
goto err;
-
- key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finsecret,
- hashlen);
- OPENSSL_cleanse(finsecret, sizeof(finsecret));
+ key = finsecret;
}
- if (key == NULL
- || ctx == NULL
- || EVP_DigestSignInit(ctx, NULL, md, NULL, key) <= 0
- || EVP_DigestSignUpdate(ctx, hash, hashlen) <= 0
- || EVP_DigestSignFinal(ctx, out, &hashlen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_FINAL_FINISH_MAC,
- ERR_R_INTERNAL_ERROR);
+ if (!EVP_Q_mac(s->ctx->libctx, "HMAC", s->ctx->propq, mdname,
+ params, key, hashlen, hash, hashlen,
+ /* outsize as per sizeof(peer_finish_md) */
+ out, EVP_MAX_MD_SIZE * 2, &len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- ret = hashlen;
err:
- EVP_PKEY_free(key);
- EVP_MD_CTX_free(ctx);
- return ret;
+ OPENSSL_cleanse(finsecret, sizeof(finsecret));
+ return len;
}
/*
@@ -345,15 +314,18 @@ int tls13_setup_key_block(SSL *s)
const EVP_CIPHER *c;
const EVP_MD *hash;
- s->session->cipher = s->s3->tmp.new_cipher;
- if (!ssl_cipher_get_evp(s->session, &c, &hash, NULL, NULL, NULL, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_SETUP_KEY_BLOCK,
- SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
+ s->session->cipher = s->s3.tmp.new_cipher;
+ if (!ssl_cipher_get_evp(s->ctx, s->session, &c, &hash, NULL, NULL, NULL,
+ 0)) {
+ /* Error is already recorded */
+ SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
return 0;
}
- s->s3->tmp.new_sym_enc = c;
- s->s3->tmp.new_hash = hash;
+ ssl_evp_cipher_free(s->s3.tmp.new_sym_enc);
+ s->s3.tmp.new_sym_enc = c;
+ ssl_evp_md_free(s->s3.tmp.new_hash);
+ s->s3.tmp.new_hash = hash;
return 1;
}
@@ -364,35 +336,33 @@ static int derive_secret_key_and_iv(SSL *s, int sending, const EVP_MD *md,
const unsigned char *hash,
const unsigned char *label,
size_t labellen, unsigned char *secret,
- unsigned char *iv, EVP_CIPHER_CTX *ciph_ctx)
+ unsigned char *key, unsigned char *iv,
+ EVP_CIPHER_CTX *ciph_ctx)
{
- unsigned char key[EVP_MAX_KEY_LENGTH];
size_t ivlen, keylen, taglen;
- int hashleni = EVP_MD_size(md);
+ int hashleni = EVP_MD_get_size(md);
size_t hashlen;
/* Ensure cast to size_t is safe */
if (!ossl_assert(hashleni >= 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DERIVE_SECRET_KEY_AND_IV,
- ERR_R_EVP_LIB);
- goto err;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ return 0;
}
hashlen = (size_t)hashleni;
if (!tls13_hkdf_expand(s, md, insecret, label, labellen, hash, hashlen,
secret, hashlen, 1)) {
/* SSLfatal() already called */
- goto err;
+ return 0;
}
- /* TODO(size_t): convert me */
- keylen = EVP_CIPHER_key_length(ciph);
- if (EVP_CIPHER_mode(ciph) == EVP_CIPH_CCM_MODE) {
+ keylen = EVP_CIPHER_get_key_length(ciph);
+ if (EVP_CIPHER_get_mode(ciph) == EVP_CIPH_CCM_MODE) {
uint32_t algenc;
ivlen = EVP_CCM_TLS_IV_LEN;
- if (s->s3->tmp.new_cipher != NULL) {
- algenc = s->s3->tmp.new_cipher->algorithm_enc;
+ if (s->s3.tmp.new_cipher != NULL) {
+ algenc = s->s3.tmp.new_cipher->algorithm_enc;
} else if (s->session->cipher != NULL) {
/* We've not selected a cipher yet - we must be doing early data */
algenc = s->session->cipher->algorithm_enc;
@@ -400,39 +370,34 @@ static int derive_secret_key_and_iv(SSL *s, int sending, const EVP_MD *md,
/* We must be doing early data with out-of-band PSK */
algenc = s->psksession->cipher->algorithm_enc;
} else {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DERIVE_SECRET_KEY_AND_IV,
- ERR_R_EVP_LIB);
- goto err;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ return 0;
}
if (algenc & (SSL_AES128CCM8 | SSL_AES256CCM8))
taglen = EVP_CCM8_TLS_TAG_LEN;
else
taglen = EVP_CCM_TLS_TAG_LEN;
} else {
- ivlen = EVP_CIPHER_iv_length(ciph);
+ ivlen = EVP_CIPHER_get_iv_length(ciph);
taglen = 0;
}
if (!tls13_derive_key(s, md, secret, key, keylen)
|| !tls13_derive_iv(s, md, secret, iv, ivlen)) {
/* SSLfatal() already called */
- goto err;
+ return 0;
}
if (EVP_CipherInit_ex(ciph_ctx, ciph, NULL, NULL, NULL, sending) <= 0
- || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL)
- || (taglen != 0 && !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG,
- taglen, NULL))
+ || EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL) <= 0
+ || (taglen != 0 && EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG,
+ taglen, NULL) <= 0)
|| EVP_CipherInit_ex(ciph_ctx, NULL, NULL, key, NULL, -1) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DERIVE_SECRET_KEY_AND_IV,
- ERR_R_EVP_LIB);
- goto err;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ return 0;
}
return 1;
- err:
- OPENSSL_cleanse(key, sizeof(key));
- return 0;
}
int tls13_change_cipher_state(SSL *s, int which)
@@ -457,6 +422,7 @@ int tls13_change_cipher_state(SSL *s, int which)
static const unsigned char early_exporter_master_secret[] = "e exp master";
#endif
unsigned char *iv;
+ unsigned char key[EVP_MAX_KEY_LENGTH];
unsigned char secret[EVP_MAX_MD_SIZE];
unsigned char hashval[EVP_MAX_MD_SIZE];
unsigned char *hash = hashval;
@@ -470,6 +436,10 @@ int tls13_change_cipher_state(SSL *s, int which)
int ret = 0;
const EVP_MD *md = NULL;
const EVP_CIPHER *cipher = NULL;
+#if !defined(OPENSSL_NO_KTLS) && defined(OPENSSL_KTLS_TLS13)
+ ktls_crypto_info_t crypto_info;
+ BIO *bio;
+#endif
if (which & SSL3_CC_READ) {
if (s->enc_read_ctx != NULL) {
@@ -477,8 +447,7 @@ int tls13_change_cipher_state(SSL *s, int which)
} else {
s->enc_read_ctx = EVP_CIPHER_CTX_new();
if (s->enc_read_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -493,8 +462,7 @@ int tls13_change_cipher_state(SSL *s, int which)
} else {
s->enc_write_ctx = EVP_CIPHER_CTX_new();
if (s->enc_write_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -518,11 +486,9 @@ int tls13_change_cipher_state(SSL *s, int which)
labellen = sizeof(client_early_traffic) - 1;
log_label = CLIENT_EARLY_LABEL;
- handlen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+ handlen = BIO_get_mem_data(s->s3.handshake_buffer, &hdata);
if (handlen <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS13_CHANGE_CIPHER_STATE,
- SSL_R_BAD_HANDSHAKE_LENGTH);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_HANDSHAKE_LENGTH);
goto err;
}
@@ -537,16 +503,13 @@ int tls13_change_cipher_state(SSL *s, int which)
if (!ossl_assert(s->psksession != NULL
&& s->max_early_data ==
s->psksession->ext.max_early_data)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS13_CHANGE_CIPHER_STATE,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
sslcipher = SSL_SESSION_get0_cipher(s->psksession);
}
if (sslcipher == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS13_CHANGE_CIPHER_STATE, SSL_R_BAD_PSK);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_PSK);
goto err;
}
@@ -557,17 +520,26 @@ int tls13_change_cipher_state(SSL *s, int which)
*/
mdctx = EVP_MD_CTX_new();
if (mdctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /*
+ * This ups the ref count on cipher so we better make sure we free
+ * it again
+ */
+ if (!ssl_cipher_get_evp_cipher(s->ctx, sslcipher, &cipher)) {
+ /* Error is already recorded */
+ SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
+ EVP_MD_CTX_free(mdctx);
goto err;
}
- cipher = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(sslcipher));
- md = ssl_md(sslcipher->algorithm2);
+
+ md = ssl_md(s->ctx, sslcipher->algorithm2);
if (md == NULL || !EVP_DigestInit_ex(mdctx, md, NULL)
|| !EVP_DigestUpdate(mdctx, hdata, handlen)
|| !EVP_DigestFinal_ex(mdctx, hashval, &hashlenui)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
EVP_MD_CTX_free(mdctx);
goto err;
}
@@ -580,8 +552,7 @@ int tls13_change_cipher_state(SSL *s, int which)
hashval, hashlen,
s->early_exporter_master_secret, hashlen,
1)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -593,7 +564,7 @@ int tls13_change_cipher_state(SSL *s, int which)
} else if (which & SSL3_CC_HANDSHAKE) {
insecret = s->handshake_secret;
finsecret = s->client_finished_secret;
- finsecretlen = EVP_MD_size(ssl_handshake_md(s));
+ finsecretlen = EVP_MD_get_size(ssl_handshake_md(s));
label = client_handshake_traffic;
labellen = sizeof(client_handshake_traffic) - 1;
log_label = CLIENT_HANDSHAKE_LABEL;
@@ -625,7 +596,7 @@ int tls13_change_cipher_state(SSL *s, int which)
if (which & SSL3_CC_HANDSHAKE) {
insecret = s->handshake_secret;
finsecret = s->server_finished_secret;
- finsecretlen = EVP_MD_size(ssl_handshake_md(s));
+ finsecretlen = EVP_MD_get_size(ssl_handshake_md(s));
label = server_handshake_traffic;
labellen = sizeof(server_handshake_traffic) - 1;
log_label = SERVER_HANDSHAKE_LABEL;
@@ -639,7 +610,7 @@ int tls13_change_cipher_state(SSL *s, int which)
if (!(which & SSL3_CC_EARLY)) {
md = ssl_handshake_md(s);
- cipher = s->s3->tmp.new_sym_enc;
+ cipher = s->s3.tmp.new_sym_enc;
if (!ssl3_digest_cached_records(s, 1)
|| !ssl_handshake_hash(s, hashval, sizeof(hashval), &hashlen)) {
/* SSLfatal() already called */;
@@ -672,9 +643,13 @@ int tls13_change_cipher_state(SSL *s, int which)
}
}
+ /* check whether cipher is known */
+ if(!ossl_assert(cipher != NULL))
+ goto err;
+
if (!derive_secret_key_and_iv(s, which & SSL3_CC_WRITE, md, cipher,
- insecret, hash, label, labellen, secret, iv,
- ciph_ctx)) {
+ insecret, hash, label, labellen, secret, key,
+ iv, ciph_ctx)) {
/* SSLfatal() already called */
goto err;
}
@@ -715,8 +690,55 @@ int tls13_change_cipher_state(SSL *s, int which)
s->statem.enc_write_state = ENC_WRITE_STATE_WRITE_PLAIN_ALERTS;
else
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
+#ifndef OPENSSL_NO_KTLS
+# if defined(OPENSSL_KTLS_TLS13)
+ if (!(which & SSL3_CC_WRITE)
+ || !(which & SSL3_CC_APPLICATION)
+ || (s->options & SSL_OP_ENABLE_KTLS) == 0)
+ goto skip_ktls;
+
+ /* ktls supports only the maximum fragment size */
+ if (ssl_get_max_send_fragment(s) != SSL3_RT_MAX_PLAIN_LENGTH)
+ goto skip_ktls;
+
+ /* ktls does not support record padding */
+ if (s->record_padding_cb != NULL)
+ goto skip_ktls;
+
+ /* check that cipher is supported */
+ if (!ktls_check_supported_cipher(s, cipher, ciph_ctx))
+ goto skip_ktls;
+
+ bio = s->wbio;
+
+ if (!ossl_assert(bio != NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* All future data will get encrypted by ktls. Flush the BIO or skip ktls */
+ if (BIO_flush(bio) <= 0)
+ goto skip_ktls;
+
+ /* configure kernel crypto structure */
+ if (!ktls_configure_crypto(s, cipher, ciph_ctx,
+ RECORD_LAYER_get_write_sequence(&s->rlayer),
+ &crypto_info, NULL, iv, key, NULL, 0))
+ goto skip_ktls;
+
+ /* ktls works with user provided buffers directly */
+ if (BIO_set_ktls(bio, &crypto_info, which & SSL3_CC_WRITE))
+ ssl3_release_write_buffer(s);
+skip_ktls:
+# endif
+#endif
ret = 1;
err:
+ if ((which & SSL3_CC_EARLY) != 0) {
+ /* We up-refed this so now we need to down ref */
+ ssl_evp_cipher_free(cipher);
+ }
+ OPENSSL_cleanse(key, sizeof(key));
OPENSSL_cleanse(secret, sizeof(secret));
return ret;
}
@@ -729,11 +751,19 @@ int tls13_update_key(SSL *s, int sending)
static const unsigned char application_traffic[] = "traffic upd";
#endif
const EVP_MD *md = ssl_handshake_md(s);
- size_t hashlen = EVP_MD_size(md);
+ size_t hashlen;
+ unsigned char key[EVP_MAX_KEY_LENGTH];
unsigned char *insecret, *iv;
unsigned char secret[EVP_MAX_MD_SIZE];
+ char *log_label;
EVP_CIPHER_CTX *ciph_ctx;
- int ret = 0;
+ int ret = 0, l;
+
+ if ((l = EVP_MD_get_size(md)) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ hashlen = (size_t)l;
if (s->server == sending)
insecret = s->server_app_traffic_secret;
@@ -751,20 +781,28 @@ int tls13_update_key(SSL *s, int sending)
RECORD_LAYER_reset_read_sequence(&s->rlayer);
}
- if (!derive_secret_key_and_iv(s, sending, ssl_handshake_md(s),
- s->s3->tmp.new_sym_enc, insecret, NULL,
+ if (!derive_secret_key_and_iv(s, sending, md,
+ s->s3.tmp.new_sym_enc, insecret, NULL,
application_traffic,
- sizeof(application_traffic) - 1, secret, iv,
- ciph_ctx)) {
+ sizeof(application_traffic) - 1, secret, key,
+ iv, ciph_ctx)) {
/* SSLfatal() already called */
goto err;
}
memcpy(insecret, secret, hashlen);
+ /* Call Key log on successful traffic secret update */
+ log_label = s->server == sending ? SERVER_APPLICATION_N_LABEL : CLIENT_APPLICATION_N_LABEL;
+ if (!ssl_log_secret(s, log_label, secret, hashlen)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
ret = 1;
err:
+ OPENSSL_cleanse(key, sizeof(key));
OPENSSL_cleanse(secret, sizeof(secret));
return ret;
}
@@ -795,7 +833,7 @@ int tls13_export_keying_material(SSL *s, unsigned char *out, size_t olen,
unsigned int hashsize, datalen;
int ret = 0;
- if (ctx == NULL || !ossl_statem_export_allowed(s))
+ if (ctx == NULL || md == NULL || !ossl_statem_export_allowed(s))
goto err;
if (!use_context)
@@ -847,7 +885,7 @@ int tls13_export_keying_material_early(SSL *s, unsigned char *out, size_t olen,
else
sslcipher = SSL_SESSION_get0_cipher(s->session);
- md = ssl_md(sslcipher->algorithm2);
+ md = ssl_md(s->ctx, sslcipher->algorithm2);
/*
* Calculate the hash value and store it in |data|. The reason why
@@ -864,7 +902,8 @@ int tls13_export_keying_material_early(SSL *s, unsigned char *out, size_t olen,
*
* Here Transcript-Hash is the cipher suite hash algorithm.
*/
- if (EVP_DigestInit_ex(ctx, md, NULL) <= 0
+ if (md == NULL
+ || EVP_DigestInit_ex(ctx, md, NULL) <= 0
|| EVP_DigestUpdate(ctx, context, contextlen) <= 0
|| EVP_DigestFinal_ex(ctx, hash, &hashsize) <= 0
|| EVP_DigestInit_ex(ctx, md, NULL) <= 0
diff --git a/ssl/tls_depr.c b/ssl/tls_depr.c
new file mode 100644
index 000000000000..1761ba1d8ef1
--- /dev/null
+++ b/ssl/tls_depr.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* We need to use some engine and HMAC deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include <openssl/engine.h>
+#include "ssl_local.h"
+
+/*
+ * Engine APIs are only used to support applications that still use ENGINEs.
+ * Once ENGINE is removed completely, all of this code can also be removed.
+ */
+
+#ifndef OPENSSL_NO_ENGINE
+void tls_engine_finish(ENGINE *e)
+{
+ ENGINE_finish(e);
+}
+#endif
+
+const EVP_CIPHER *tls_get_cipher_from_engine(int nid)
+{
+ const EVP_CIPHER *ret = NULL;
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE *eng;
+
+ /*
+ * If there is an Engine available for this cipher we use the "implicit"
+ * form to ensure we use that engine later.
+ */
+ eng = ENGINE_get_cipher_engine(nid);
+ if (eng != NULL) {
+ ret = ENGINE_get_cipher(eng, nid);
+ ENGINE_finish(eng);
+ }
+#endif
+ return ret;
+}
+
+const EVP_MD *tls_get_digest_from_engine(int nid)
+{
+ const EVP_MD *ret = NULL;
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE *eng;
+
+ /*
+ * If there is an Engine available for this digest we use the "implicit"
+ * form to ensure we use that engine later.
+ */
+ eng = ENGINE_get_digest_engine(nid);
+ if (eng != NULL) {
+ ret = ENGINE_get_digest(eng, nid);
+ ENGINE_finish(eng);
+ }
+#endif
+ return ret;
+}
+
+#ifndef OPENSSL_NO_ENGINE
+int tls_engine_load_ssl_client_cert(SSL *s, X509 **px509, EVP_PKEY **ppkey)
+{
+ return ENGINE_load_ssl_client_cert(s->ctx->client_cert_engine, s,
+ SSL_get_client_CA_list(s),
+ px509, ppkey, NULL, NULL, NULL);
+}
+#endif
+
+#ifndef OPENSSL_NO_ENGINE
+int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e)
+{
+ if (!ENGINE_init(e)) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_ENGINE_LIB);
+ return 0;
+ }
+ if (!ENGINE_get_ssl_client_cert_function(e)) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_CLIENT_CERT_METHOD);
+ ENGINE_finish(e);
+ return 0;
+ }
+ ctx->client_cert_engine = e;
+ return 1;
+}
+#endif
+
+/*
+ * The HMAC APIs below are only used to support the deprecated public API
+ * macro SSL_CTX_set_tlsext_ticket_key_cb(). The application supplied callback
+ * takes an HMAC_CTX in its argument list. The preferred alternative is
+ * SSL_CTX_set_tlsext_ticket_key_evp_cb(). Once
+ * SSL_CTX_set_tlsext_ticket_key_cb() is removed, then all of this code can also
+ * be removed.
+ */
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+int ssl_hmac_old_new(SSL_HMAC *ret)
+{
+ ret->old_ctx = HMAC_CTX_new();
+ if (ret->old_ctx == NULL)
+ return 0;
+
+ return 1;
+}
+
+void ssl_hmac_old_free(SSL_HMAC *ctx)
+{
+ HMAC_CTX_free(ctx->old_ctx);
+}
+
+int ssl_hmac_old_init(SSL_HMAC *ctx, void *key, size_t len, char *md)
+{
+ return HMAC_Init_ex(ctx->old_ctx, key, len, EVP_get_digestbyname(md), NULL);
+}
+
+int ssl_hmac_old_update(SSL_HMAC *ctx, const unsigned char *data, size_t len)
+{
+ return HMAC_Update(ctx->old_ctx, data, len);
+}
+
+int ssl_hmac_old_final(SSL_HMAC *ctx, unsigned char *md, size_t *len)
+{
+ unsigned int l;
+
+ if (HMAC_Final(ctx->old_ctx, md, &l) > 0) {
+ if (len != NULL)
+ *len = l;
+ return 1;
+ }
+
+ return 0;
+}
+
+size_t ssl_hmac_old_size(const SSL_HMAC *ctx)
+{
+ return HMAC_size(ctx->old_ctx);
+}
+
+HMAC_CTX *ssl_hmac_get0_HMAC_CTX(SSL_HMAC *ctx)
+{
+ return ctx->old_ctx;
+}
+
+/* Some deprecated public APIs pass DH objects */
+EVP_PKEY *ssl_dh_to_pkey(DH *dh)
+{
+# ifndef OPENSSL_NO_DH
+ EVP_PKEY *ret;
+
+ if (dh == NULL)
+ return NULL;
+ ret = EVP_PKEY_new();
+ if (EVP_PKEY_set1_DH(ret, dh) <= 0) {
+ EVP_PKEY_free(ret);
+ return NULL;
+ }
+ return ret;
+# else
+ return NULL;
+# endif
+}
+
+/* Some deprecated public APIs pass EC_KEY objects */
+int ssl_set_tmp_ecdh_groups(uint16_t **pext, size_t *pextlen,
+ void *key)
+{
+# ifndef OPENSSL_NO_EC
+ const EC_GROUP *group = EC_KEY_get0_group((const EC_KEY *)key);
+ int nid;
+
+ if (group == NULL) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_MISSING_PARAMETERS);
+ return 0;
+ }
+ nid = EC_GROUP_get_curve_name(group);
+ if (nid == NID_undef)
+ return 0;
+ return tls1_set_groups(pext, pextlen, &nid, 1);
+# else
+ return 0;
+# endif
+}
+
+/*
+ * Set the callback for generating temporary DH keys.
+ * ctx: the SSL context.
+ * dh: the callback
+ */
+# if !defined(OPENSSL_NO_DH)
+void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
+ DH *(*dh) (SSL *ssl, int is_export,
+ int keylength))
+{
+ SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TMP_DH_CB, (void (*)(void))dh);
+}
+
+void SSL_set_tmp_dh_callback(SSL *ssl, DH *(*dh) (SSL *ssl, int is_export,
+ int keylength))
+{
+ SSL_callback_ctrl(ssl, SSL_CTRL_SET_TMP_DH_CB, (void (*)(void))dh);
+}
+# endif
+#endif /* OPENSSL_NO_DEPRECATED */
diff --git a/ssl/tls_srp.c b/ssl/tls_srp.c
index ede7427ff89d..872d1b66f8af 100644
--- a/ssl/tls_srp.c
+++ b/ssl/tls_srp.c
@@ -1,8 +1,8 @@
/*
- * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2004, EdelKey Project. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -11,6 +11,12 @@
* for the EdelKey project.
*/
+/*
+ * We need to use the SRP deprecated APIs in order to implement the SSL SRP
+ * APIs - which are themselves deprecated.
+ */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <openssl/crypto.h>
#include <openssl/rand.h>
#include <openssl/err.h>
@@ -19,7 +25,11 @@
#ifndef OPENSSL_NO_SRP
# include <openssl/srp.h>
-int SSL_CTX_SRP_CTX_free(struct ssl_ctx_st *ctx)
+/*
+ * The public API SSL_CTX_SRP_CTX_free() is deprecated so we use
+ * ssl_ctx_srp_ctx_free_intern() internally.
+ */
+int ssl_ctx_srp_ctx_free_intern(SSL_CTX *ctx)
{
if (ctx == NULL)
return 0;
@@ -38,7 +48,16 @@ int SSL_CTX_SRP_CTX_free(struct ssl_ctx_st *ctx)
return 1;
}
-int SSL_SRP_CTX_free(struct ssl_st *s)
+int SSL_CTX_SRP_CTX_free(SSL_CTX *ctx)
+{
+ return ssl_ctx_srp_ctx_free_intern(ctx);
+}
+
+/*
+ * The public API SSL_SRP_CTX_free() is deprecated so we use
+ * ssl_srp_ctx_free_intern() internally.
+ */
+int ssl_srp_ctx_free_intern(SSL *s)
{
if (s == NULL)
return 0;
@@ -57,7 +76,16 @@ int SSL_SRP_CTX_free(struct ssl_st *s)
return 1;
}
-int SSL_SRP_CTX_init(struct ssl_st *s)
+int SSL_SRP_CTX_free(SSL *s)
+{
+ return ssl_srp_ctx_free_intern(s);
+}
+
+/*
+ * The public API SSL_SRP_CTX_init() is deprecated so we use
+ * ssl_srp_ctx_init_intern() internally.
+ */
+int ssl_srp_ctx_init_intern(SSL *s)
{
SSL_CTX *ctx;
@@ -95,17 +123,17 @@ int SSL_SRP_CTX_init(struct ssl_st *s)
((s->srp_ctx.v = BN_dup(ctx->srp_ctx.v)) == NULL)) ||
((ctx->srp_ctx.b != NULL) &&
((s->srp_ctx.b = BN_dup(ctx->srp_ctx.b)) == NULL))) {
- SSLerr(SSL_F_SSL_SRP_CTX_INIT, ERR_R_BN_LIB);
+ ERR_raise(ERR_LIB_SSL, ERR_R_BN_LIB);
goto err;
}
if ((ctx->srp_ctx.login != NULL) &&
((s->srp_ctx.login = OPENSSL_strdup(ctx->srp_ctx.login)) == NULL)) {
- SSLerr(SSL_F_SSL_SRP_CTX_INIT, ERR_R_INTERNAL_ERROR);
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
goto err;
}
if ((ctx->srp_ctx.info != NULL) &&
- ((s->srp_ctx.info = BUF_strdup(ctx->srp_ctx.info)) == NULL)) {
- SSLerr(SSL_F_SSL_SRP_CTX_INIT, ERR_R_INTERNAL_ERROR);
+ ((s->srp_ctx.info = OPENSSL_strdup(ctx->srp_ctx.info)) == NULL)) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
goto err;
}
s->srp_ctx.srp_Mask = ctx->srp_ctx.srp_Mask;
@@ -126,7 +154,16 @@ int SSL_SRP_CTX_init(struct ssl_st *s)
return 0;
}
-int SSL_CTX_SRP_CTX_init(struct ssl_ctx_st *ctx)
+int SSL_SRP_CTX_init(SSL *s)
+{
+ return ssl_srp_ctx_init_intern(s);
+}
+
+/*
+ * The public API SSL_CTX_SRP_CTX_init() is deprecated so we use
+ * ssl_ctx_srp_ctx_init_intern() internally.
+ */
+int ssl_ctx_srp_ctx_init_intern(SSL_CTX *ctx)
{
if (ctx == NULL)
return 0;
@@ -137,8 +174,17 @@ int SSL_CTX_SRP_CTX_init(struct ssl_ctx_st *ctx)
return 1;
}
+int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx)
+{
+ return ssl_ctx_srp_ctx_init_intern(ctx);
+}
+
/* server side */
-int SSL_srp_server_param_with_username(SSL *s, int *ad)
+/*
+ * The public API SSL_srp_server_param_with_username() is deprecated so we use
+ * ssl_srp_server_param_with_username_intern() internally.
+ */
+int ssl_srp_server_param_with_username_intern(SSL *s, int *ad)
{
unsigned char b[SSL_MAX_MASTER_KEY_LENGTH];
int al;
@@ -157,7 +203,7 @@ int SSL_srp_server_param_with_username(SSL *s, int *ad)
(s->srp_ctx.s == NULL) || (s->srp_ctx.v == NULL))
return SSL3_AL_FATAL;
- if (RAND_priv_bytes(b, sizeof(b)) <= 0)
+ if (RAND_priv_bytes_ex(s->ctx->libctx, b, sizeof(b), 0) <= 0)
return SSL3_AL_FATAL;
s->srp_ctx.b = BN_bin2bn(b, sizeof(b), NULL);
OPENSSL_cleanse(b, sizeof(b));
@@ -165,11 +211,16 @@ int SSL_srp_server_param_with_username(SSL *s, int *ad)
/* Calculate: B = (kv + g^b) % N */
return ((s->srp_ctx.B =
- SRP_Calc_B(s->srp_ctx.b, s->srp_ctx.N, s->srp_ctx.g,
- s->srp_ctx.v)) !=
+ SRP_Calc_B_ex(s->srp_ctx.b, s->srp_ctx.N, s->srp_ctx.g,
+ s->srp_ctx.v, s->ctx->libctx, s->ctx->propq)) !=
NULL) ? SSL_ERROR_NONE : SSL3_AL_FATAL;
}
+int SSL_srp_server_param_with_username(SSL *s, int *ad)
+{
+ return ssl_srp_server_param_with_username_intern(s, ad);
+}
+
/*
* If the server just has the raw password, make up a verifier entry on the
* fly
@@ -186,8 +237,9 @@ int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass,
s->srp_ctx.v = NULL;
BN_clear_free(s->srp_ctx.s);
s->srp_ctx.s = NULL;
- if (!SRP_create_verifier_BN
- (user, pass, &s->srp_ctx.s, &s->srp_ctx.v, GN->N, GN->g))
+ if (!SRP_create_verifier_BN_ex(user, pass, &s->srp_ctx.s, &s->srp_ctx.v,
+ s->srp_ctx.N, s->srp_ctx.g, s->ctx->libctx,
+ s->ctx->propq))
return -1;
return 1;
@@ -235,7 +287,7 @@ int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
if (info != NULL) {
if (s->srp_ctx.info)
OPENSSL_free(s->srp_ctx.info);
- if ((s->srp_ctx.info = BUF_strdup(info)) == NULL)
+ if ((s->srp_ctx.info = OPENSSL_strdup(info)) == NULL)
return -1;
}
@@ -249,12 +301,13 @@ int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
int srp_generate_server_master_secret(SSL *s)
{
BIGNUM *K = NULL, *u = NULL;
- int ret = -1, tmp_len = 0;
+ int ret = 0, tmp_len = 0;
unsigned char *tmp = NULL;
if (!SRP_Verify_A_mod_N(s->srp_ctx.A, s->srp_ctx.N))
goto err;
- if ((u = SRP_Calc_u(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N)) == NULL)
+ if ((u = SRP_Calc_u_ex(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N,
+ s->ctx->libctx, s->ctx->propq)) == NULL)
goto err;
if ((K = SRP_Calc_server_key(s->srp_ctx.A, s->srp_ctx.v, u, s->srp_ctx.b,
s->srp_ctx.N)) == NULL)
@@ -262,8 +315,7 @@ int srp_generate_server_master_secret(SSL *s)
tmp_len = BN_num_bytes(K);
if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_SRP_GENERATE_SERVER_MASTER_SECRET, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
BN_bn2bin(K, tmp);
@@ -279,7 +331,7 @@ int srp_generate_server_master_secret(SSL *s)
int srp_generate_client_master_secret(SSL *s)
{
BIGNUM *x = NULL, *u = NULL, *K = NULL;
- int ret = -1, tmp_len = 0;
+ int ret = 0, tmp_len = 0;
char *passwd = NULL;
unsigned char *tmp = NULL;
@@ -287,34 +339,33 @@ int srp_generate_client_master_secret(SSL *s)
* Checks if b % n == 0
*/
if (SRP_Verify_B_mod_N(s->srp_ctx.B, s->srp_ctx.N) == 0
- || (u = SRP_Calc_u(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N))
+ || (u = SRP_Calc_u_ex(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N,
+ s->ctx->libctx, s->ctx->propq))
== NULL
|| s->srp_ctx.SRP_give_srp_client_pwd_callback == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if ((passwd = s->srp_ctx.SRP_give_srp_client_pwd_callback(s,
s->srp_ctx.SRP_cb_arg))
== NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET,
- SSL_R_CALLBACK_FAILED);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CALLBACK_FAILED);
goto err;
}
- if ((x = SRP_Calc_x(s->srp_ctx.s, s->srp_ctx.login, passwd)) == NULL
- || (K = SRP_Calc_client_key(s->srp_ctx.N, s->srp_ctx.B,
- s->srp_ctx.g, x,
- s->srp_ctx.a, u)) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET, ERR_R_INTERNAL_ERROR);
+ if ((x = SRP_Calc_x_ex(s->srp_ctx.s, s->srp_ctx.login, passwd,
+ s->ctx->libctx, s->ctx->propq)) == NULL
+ || (K = SRP_Calc_client_key_ex(s->srp_ctx.N, s->srp_ctx.B,
+ s->srp_ctx.g, x,
+ s->srp_ctx.a, u,
+ s->ctx->libctx,
+ s->ctx->propq)) == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
tmp_len = BN_num_bytes(K);
if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
BN_bn2bin(K, tmp);
@@ -338,26 +389,22 @@ int srp_verify_server_param(SSL *s)
*/
if (BN_ucmp(srp->g, srp->N) >= 0 || BN_ucmp(srp->B, srp->N) >= 0
|| BN_is_zero(srp->B)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SRP_VERIFY_SERVER_PARAM,
- SSL_R_BAD_DATA);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_DATA);
return 0;
}
if (BN_num_bits(srp->N) < srp->strength) {
- SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_F_SRP_VERIFY_SERVER_PARAM,
- SSL_R_INSUFFICIENT_SECURITY);
+ SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_R_INSUFFICIENT_SECURITY);
return 0;
}
if (srp->SRP_verify_param_callback) {
if (srp->SRP_verify_param_callback(s, srp->SRP_cb_arg) <= 0) {
- SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY,
- SSL_F_SRP_VERIFY_SERVER_PARAM,
- SSL_R_CALLBACK_FAILED);
+ SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_R_CALLBACK_FAILED);
return 0;
}
} else if (!SRP_check_known_gN_param(srp->g, srp->N)) {
- SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_F_SRP_VERIFY_SERVER_PARAM,
+ SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY,
SSL_R_INSUFFICIENT_SECURITY);
return 0;
}
@@ -365,11 +412,15 @@ int srp_verify_server_param(SSL *s)
return 1;
}
-int SRP_Calc_A_param(SSL *s)
+/*
+ * The public API SRP_Calc_A_param() is deprecated so we use
+ * ssl_srp_calc_a_param_intern() internally.
+ */
+int ssl_srp_calc_a_param_intern(SSL *s)
{
unsigned char rnd[SSL_MAX_MASTER_KEY_LENGTH];
- if (RAND_priv_bytes(rnd, sizeof(rnd)) <= 0)
+ if (RAND_priv_bytes_ex(s->ctx->libctx, rnd, sizeof(rnd), 0) <= 0)
return 0;
s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a);
OPENSSL_cleanse(rnd, sizeof(rnd));
@@ -380,6 +431,11 @@ int SRP_Calc_A_param(SSL *s)
return 1;
}
+int SRP_Calc_A_param(SSL *s)
+{
+ return ssl_srp_calc_a_param_intern(s);
+}
+
BIGNUM *SSL_get_srp_g(SSL *s)
{
if (s->srp_ctx.g != NULL)